summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore78
-rwxr-xr-xBUILD/compile-pentium-debug4
-rwxr-xr-xBUILD/compile-pentium-max4
-rw-r--r--BitKeeper/etc/config1
-rw-r--r--BitKeeper/etc/logging_ok15
-rwxr-xr-xBitKeeper/triggers/post-commit14
-rw-r--r--Docs/gis.txt874
-rw-r--r--Docs/internals.texi7
-rwxr-xr-xDocs/prepare.texi1736
-rw-r--r--Makefile.am7
-rw-r--r--VC++Files/bdb/bdb.dsp179
-rw-r--r--VC++Files/bdb/build_win32/Berkeley_DB.dsw1
-rw-r--r--VC++Files/bdb/build_win32/db_archive.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_buildall.dsp16
-rw-r--r--VC++Files/bdb/build_win32/db_checkpoint.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_deadlock.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_dll.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_dump.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_java.dsp58
-rw-r--r--VC++Files/bdb/build_win32/db_load.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_printlog.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_recover.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_stat.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_static.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_static1.dsp16
-rw-r--r--VC++Files/bdb/build_win32/db_tcl.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_test.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_upgrade.dsp14
-rw-r--r--VC++Files/bdb/build_win32/db_verify.dsp14
-rw-r--r--VC++Files/bdb/build_win32/ex_access.dsp14
-rw-r--r--VC++Files/bdb/build_win32/ex_btrec.dsp14
-rw-r--r--VC++Files/bdb/build_win32/ex_env.dsp14
-rw-r--r--VC++Files/bdb/build_win32/ex_lock.dsp14
-rw-r--r--VC++Files/bdb/build_win32/ex_mpool.dsp14
-rw-r--r--VC++Files/bdb/build_win32/ex_tpcb.dsp14
-rw-r--r--VC++Files/bdb/build_win32/excxx_access.dsp14
-rw-r--r--VC++Files/bdb/build_win32/excxx_btrec.dsp14
-rw-r--r--VC++Files/bdb/build_win32/excxx_env.dsp14
-rw-r--r--VC++Files/bdb/build_win32/excxx_lock.dsp14
-rw-r--r--VC++Files/bdb/build_win32/excxx_mpool.dsp14
-rw-r--r--VC++Files/bdb/build_win32/excxx_tpcb.dsp14
-rw-r--r--VC++Files/client/mysql.dsp16
-rw-r--r--VC++Files/client/mysqladmin.dsp14
-rw-r--r--VC++Files/client/mysqlcheck.dsp12
-rw-r--r--VC++Files/client/mysqlclient.dsp32
-rw-r--r--VC++Files/client/mysqlclient.dsw1
-rw-r--r--VC++Files/client/mysqldump.dsp16
-rw-r--r--VC++Files/client/mysqlimport.dsp14
-rw-r--r--VC++Files/client/mysqlshow.dsp14
-rw-r--r--VC++Files/comp_err/comp_err.dsp12
-rw-r--r--VC++Files/contrib/asm386/zlibvc.dsp76
-rw-r--r--VC++Files/contrib/asm386/zlibvc.dsw1
-rw-r--r--VC++Files/contrib/minizip/zlibvc.dsp76
-rw-r--r--VC++Files/contrib/minizip/zlibvc.dsw1
-rw-r--r--VC++Files/dbug/dbug.dsp14
-rw-r--r--VC++Files/dbug/dbug.dsw1
-rwxr-xr-xVC++Files/fix-project-files7
-rw-r--r--VC++Files/heap/heap.dsp16
-rw-r--r--VC++Files/innobase/innobase.dsp12
-rw-r--r--VC++Files/isam/isam.dsp14
-rw-r--r--VC++Files/isam/isam.dsw1
-rw-r--r--VC++Files/isamchk/isamchk.dsp14
-rw-r--r--VC++Files/libmysql/libmysql.def1
-rw-r--r--VC++Files/libmysql/libmysql.dsp17
-rw-r--r--VC++Files/libmysql/libmysql.dsw1
-rw-r--r--VC++Files/libmysqld/examples/test_libmysqld.dsp12
-rw-r--r--VC++Files/libmysqld/libmysqld.dsp53
-rw-r--r--VC++Files/libmysqltest/myTest.dsp14
-rw-r--r--VC++Files/libmysqltest/mytest.dsw1
-rw-r--r--VC++Files/merge/merge.dsp14
-rw-r--r--VC++Files/merge/merge.dsw1
-rw-r--r--VC++Files/my_print_defaults/my_print_defaults.dsp14
-rw-r--r--VC++Files/myisam/myisam.dsp38
-rw-r--r--VC++Files/myisamchk/myisamchk.dsp14
-rw-r--r--VC++Files/myisamlog/myisamlog.dsp14
-rw-r--r--VC++Files/myisammrg/myisammrg.dsp14
-rw-r--r--VC++Files/myisampack/myisampack.dsp14
-rw-r--r--VC++Files/mysql.dsp16
-rw-r--r--VC++Files/mysql.dsw1
-rw-r--r--VC++Files/mysqlbinlog/mysqlbinlog.dsp14
-rw-r--r--VC++Files/mysqlcheck/mysqlcheck.dsp14
-rw-r--r--VC++Files/mysqldemb/mysqldemb.dsp38
-rw-r--r--VC++Files/mysqlmanager/MySqlManager.dsp14
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.dsw1
-rw-r--r--VC++Files/mysqlserver/mysqlserver.dsp14
-rw-r--r--VC++Files/mysqlshutdown/myshutdown.dsp14
-rw-r--r--VC++Files/mysqlshutdown/mysqlshutdown.dsp14
-rw-r--r--VC++Files/mysqlwatch/mysqlwatch.dsp12
-rw-r--r--VC++Files/mysys/mysys.dsp24
-rw-r--r--VC++Files/mysys/mysys.dsw1
-rw-r--r--VC++Files/pack_isam/pack_isam.dsp14
-rw-r--r--VC++Files/perror/perror.dsp14
-rw-r--r--VC++Files/regex/regex.dsp14
-rw-r--r--VC++Files/regex/regex.dsw1
-rw-r--r--VC++Files/replace/replace.dsp14
-rw-r--r--VC++Files/sql/mysqld.dsp76
-rw-r--r--VC++Files/sql/mysqld.dsw1
-rw-r--r--VC++Files/sql/mysqldmax.dsp112
-rw-r--r--VC++Files/sql/old/mysqld.dsw1
-rw-r--r--VC++Files/strings/MASM6x/strings.dsp18
-rw-r--r--VC++Files/strings/MASM6x/strings.dsw1
-rw-r--r--VC++Files/strings/backup/strings.dsp18
-rw-r--r--VC++Files/strings/backup/strings.dsw1
-rw-r--r--VC++Files/strings/noMASM/strings.dsp14
-rw-r--r--VC++Files/strings/noMASM/strings.dsw1
-rw-r--r--VC++Files/strings/strings.dsp34
-rw-r--r--VC++Files/strings/strings.dsw1
-rw-r--r--VC++Files/test1/test1.dsp16
-rw-r--r--VC++Files/thr_insert_test/thr_insert_test.dsp14
-rw-r--r--VC++Files/thr_test/thr_test.dsp16
-rw-r--r--VC++Files/vio/vio.dsp14
-rw-r--r--VC++Files/zlib/zlib.dsp14
-rw-r--r--acconfig.h59
-rw-r--r--acinclude.m480
-rw-r--r--bdb/LICENSE4
-rw-r--r--bdb/Makefile.in13
-rw-r--r--bdb/btree/bt_compare.c14
-rw-r--r--bdb/btree/bt_conv.c30
-rw-r--r--bdb/btree/bt_curadj.c55
-rw-r--r--bdb/btree/bt_cursor.c1193
-rw-r--r--bdb/btree/bt_delete.c186
-rw-r--r--bdb/btree/bt_method.c33
-rw-r--r--bdb/btree/bt_open.c425
-rw-r--r--bdb/btree/bt_put.c165
-rw-r--r--bdb/btree/bt_rec.c494
-rw-r--r--bdb/btree/bt_reclaim.c45
-rw-r--r--bdb/btree/bt_recno.c430
-rw-r--r--bdb/btree/bt_rsearch.c85
-rw-r--r--bdb/btree/bt_search.c92
-rw-r--r--bdb/btree/bt_split.c323
-rw-r--r--bdb/btree/bt_stat.c203
-rw-r--r--bdb/btree/bt_upgrade.c24
-rw-r--r--bdb/btree/bt_verify.c526
-rw-r--r--bdb/btree/btree.src158
-rw-r--r--bdb/build_vxworks/BerkeleyDB.wpj6066
-rw-r--r--bdb/build_vxworks/BerkeleyDB.wsp17
-rw-r--r--bdb/build_vxworks/db_config.h264
-rw-r--r--bdb/build_vxworks/dbdemo/README39
-rw-r--r--bdb/build_vxworks/ex_access/ex_access.wpj244
-rw-r--r--bdb/build_vxworks/ex_btrec/ex_btrec.wpj250
-rw-r--r--bdb/build_vxworks/ex_dbclient/ex_dbclient.wpj266
-rw-r--r--bdb/build_vxworks/ex_env/ex_env.wpj248
-rw-r--r--bdb/build_vxworks/ex_mpool/ex_mpool.wpj248
-rw-r--r--bdb/build_vxworks/ex_tpcb/ex_tpcb.wpj261
-rw-r--r--bdb/build_win32/Berkeley_DB.dsw1
-rw-r--r--bdb/build_win32/app_dsp.src27
-rw-r--r--bdb/build_win32/build_all.dsp96
-rw-r--r--bdb/build_win32/db_buildall.dsp128
-rw-r--r--bdb/build_win32/db_config.h275
-rw-r--r--bdb/build_win32/db_java_xa.dsp85
-rw-r--r--bdb/build_win32/db_java_xaj.mak21
-rw-r--r--bdb/build_win32/db_lib.dsp92
-rw-r--r--bdb/build_win32/db_test.dsp99
-rw-r--r--bdb/build_win32/db_test.src97
-rw-r--r--bdb/build_win32/dbkill.cpp14
-rw-r--r--bdb/build_win32/dynamic_dsp.src83
-rw-r--r--bdb/build_win32/java_dsp.src60
-rw-r--r--bdb/build_win32/libdb.def151
-rw-r--r--bdb/build_win32/libdb_tcl.def10
-rw-r--r--bdb/build_win32/libdbrc.src2
-rw-r--r--bdb/build_win32/static_dsp.src84
-rw-r--r--bdb/build_win32/tcl_dsp.src19
-rw-r--r--bdb/clib/getcwd.c20
-rw-r--r--bdb/clib/getopt.c19
-rw-r--r--bdb/clib/memcmp.c4
-rw-r--r--bdb/clib/memmove.c4
-rw-r--r--bdb/clib/raise.c8
-rw-r--r--bdb/clib/snprintf.c35
-rw-r--r--bdb/clib/strcasecmp.c34
-rw-r--r--bdb/clib/strdup.c67
-rw-r--r--bdb/clib/strerror.c4
-rw-r--r--bdb/clib/vsnprintf.c6
-rw-r--r--bdb/common/db_byteorder.c50
-rw-r--r--bdb/common/db_err.c359
-rw-r--r--bdb/common/db_getlong.c73
-rw-r--r--bdb/common/db_idspace.c93
-rw-r--r--bdb/common/db_log2.c5
-rw-r--r--bdb/common/util_arg.c126
-rw-r--r--bdb/common/util_cache.c92
-rw-r--r--bdb/common/util_log.c9
-rw-r--r--bdb/common/util_sig.c7
-rw-r--r--bdb/cxx/cxx_app.cpp671
-rw-r--r--bdb/cxx/cxx_db.cpp605
-rw-r--r--bdb/cxx/cxx_dbc.cpp115
-rw-r--r--bdb/cxx/cxx_dbt.cpp61
-rw-r--r--bdb/cxx/cxx_env.cpp802
-rw-r--r--bdb/cxx/cxx_except.cpp254
-rw-r--r--bdb/cxx/cxx_lock.cpp86
-rw-r--r--bdb/cxx/cxx_log.cpp125
-rw-r--r--bdb/cxx/cxx_logc.cpp65
-rw-r--r--bdb/cxx/cxx_mpool.cpp208
-rw-r--r--bdb/cxx/cxx_table.cpp808
-rw-r--r--bdb/cxx/cxx_txn.cpp143
-rw-r--r--bdb/cxx/namemap.txt21
-rw-r--r--bdb/db/Design.fileop452
-rw-r--r--bdb/db/crdel.src85
-rw-r--r--bdb/db/crdel_rec.c577
-rw-r--r--bdb/db/db.c2087
-rw-r--r--bdb/db/db.src133
-rw-r--r--bdb/db/db_am.c926
-rw-r--r--bdb/db/db_cam.c1538
-rw-r--r--bdb/db/db_conv.c290
-rw-r--r--bdb/db/db_dispatch.c1305
-rw-r--r--bdb/db/db_dup.c118
-rw-r--r--bdb/db/db_iface.c504
-rw-r--r--bdb/db/db_join.c250
-rw-r--r--bdb/db/db_meta.c287
-rw-r--r--bdb/db/db_method.c288
-rw-r--r--bdb/db/db_open.c703
-rw-r--r--bdb/db/db_overflow.c213
-rw-r--r--bdb/db/db_pr.c444
-rw-r--r--bdb/db/db_rec.c456
-rw-r--r--bdb/db/db_reclaim.c228
-rw-r--r--bdb/db/db_remove.c318
-rw-r--r--bdb/db/db_rename.c297
-rw-r--r--bdb/db/db_ret.c36
-rw-r--r--bdb/db/db_truncate.c95
-rw-r--r--bdb/db/db_upg.c27
-rw-r--r--bdb/db/db_upg_opd.c79
-rw-r--r--bdb/db/db_vrfy.c704
-rw-r--r--bdb/db/db_vrfyutil.c118
-rw-r--r--bdb/db185/db185.c97
-rw-r--r--bdb/db185/db185_int.h129
-rw-r--r--bdb/db185/db185_int.in129
-rw-r--r--bdb/db_archive/db_archive.c74
-rw-r--r--bdb/db_checkpoint/db_checkpoint.c106
-rw-r--r--bdb/db_deadlock/db_deadlock.c118
-rw-r--r--bdb/db_dump/db_dump.c254
-rw-r--r--bdb/db_dump185/db_dump185.c28
-rw-r--r--bdb/db_load/db_load.c594
-rw-r--r--bdb/db_printlog/README11
-rw-r--r--bdb/db_printlog/db_printlog.c280
-rw-r--r--bdb/db_printlog/dbname.awk8
-rw-r--r--bdb/db_printlog/logstat.awk36
-rw-r--r--bdb/db_printlog/status.awk28
-rw-r--r--bdb/db_recover/db_recover.c115
-rw-r--r--bdb/db_stat/db_stat.c696
-rw-r--r--bdb/db_upgrade/db_upgrade.c79
-rw-r--r--bdb/db_verify/db_verify.c180
-rw-r--r--bdb/dbinc/btree.h320
-rw-r--r--bdb/dbinc/crypto.h78
-rw-r--r--bdb/dbinc/cxx_common.h45
-rw-r--r--bdb/dbinc/cxx_except.h141
-rw-r--r--bdb/dbinc/cxx_int.h81
-rw-r--r--bdb/dbinc/db.in1883
-rw-r--r--bdb/dbinc/db_185.in169
-rw-r--r--bdb/dbinc/db_am.h127
-rw-r--r--bdb/dbinc/db_cxx.in795
-rw-r--r--bdb/dbinc/db_dispatch.h105
-rw-r--r--bdb/dbinc/db_int.in473
-rw-r--r--bdb/dbinc/db_join.h31
-rw-r--r--bdb/dbinc/db_page.h651
-rw-r--r--bdb/dbinc/db_server_int.h148
-rw-r--r--bdb/dbinc/db_shash.h81
-rw-r--r--bdb/dbinc/db_swap.h116
-rw-r--r--bdb/dbinc/db_upgrade.h242
-rw-r--r--bdb/dbinc/db_verify.h205
-rw-r--r--bdb/dbinc/debug.h198
-rw-r--r--bdb/dbinc/fop.h16
-rw-r--r--bdb/dbinc/globals.h83
-rw-r--r--bdb/dbinc/hash.h147
-rw-r--r--bdb/dbinc/hmac.h32
-rw-r--r--bdb/dbinc/lock.h212
-rw-r--r--bdb/dbinc/log.h273
-rw-r--r--bdb/dbinc/mp.h293
-rw-r--r--bdb/dbinc/mutex.h879
-rw-r--r--bdb/dbinc/os.h54
-rw-r--r--bdb/dbinc/qam.h156
-rw-r--r--bdb/dbinc/queue.h (renamed from bdb/include/queue.h)0
-rw-r--r--bdb/dbinc/region.h304
-rw-r--r--bdb/dbinc/rep.h184
-rw-r--r--bdb/dbinc/shqueue.h337
-rw-r--r--bdb/dbinc/tcl_db.h261
-rw-r--r--bdb/dbinc/txn.h143
-rw-r--r--bdb/dbinc/xa.h179
-rw-r--r--bdb/dbm/dbm.c50
-rw-r--r--bdb/dbreg/dbreg.c450
-rw-r--r--bdb/dbreg/dbreg.src49
-rw-r--r--bdb/dbreg/dbreg_rec.c362
-rw-r--r--bdb/dbreg/dbreg_util.c797
-rw-r--r--bdb/dist/Makefile.in1677
-rw-r--r--bdb/dist/RELEASE30
-rw-r--r--bdb/dist/acconfig.h109
-rw-r--r--bdb/dist/aclocal/config.ac51
-rw-r--r--bdb/dist/aclocal/cxx.ac17
-rw-r--r--bdb/dist/aclocal/gcc.ac36
-rw-r--r--bdb/dist/aclocal/libtool.ac3633
-rw-r--r--bdb/dist/aclocal/mutex.ac611
-rw-r--r--bdb/dist/aclocal/mutex.m4409
-rw-r--r--bdb/dist/aclocal/options.ac197
-rw-r--r--bdb/dist/aclocal/options.m4121
-rw-r--r--bdb/dist/aclocal/programs.ac80
-rw-r--r--bdb/dist/aclocal/programs.m448
-rw-r--r--bdb/dist/aclocal/sosuffix.ac69
-rw-r--r--bdb/dist/aclocal/tcl.ac136
-rw-r--r--bdb/dist/aclocal/tcl.m4126
-rw-r--r--bdb/dist/aclocal/types.ac146
-rw-r--r--bdb/dist/aclocal/types.m4139
-rw-r--r--bdb/dist/aclocal_java/ac_check_class.ac107
-rw-r--r--bdb/dist/aclocal_java/ac_check_classpath.ac23
-rw-r--r--bdb/dist/aclocal_java/ac_check_junit.ac54
-rw-r--r--bdb/dist/aclocal_java/ac_check_rqrd_class.ac26
-rw-r--r--bdb/dist/aclocal_java/ac_java_options.ac32
-rw-r--r--bdb/dist/aclocal_java/ac_jni_include_dirs.ac112
-rw-r--r--bdb/dist/aclocal_java/ac_prog_jar.ac36
-rw-r--r--bdb/dist/aclocal_java/ac_prog_java.ac77
-rw-r--r--bdb/dist/aclocal_java/ac_prog_java_works.ac97
-rw-r--r--bdb/dist/aclocal_java/ac_prog_javac.ac43
-rw-r--r--bdb/dist/aclocal_java/ac_prog_javac_works.ac35
-rw-r--r--bdb/dist/aclocal_java/ac_prog_javadoc.ac37
-rw-r--r--bdb/dist/aclocal_java/ac_prog_javah.ac26
-rw-r--r--bdb/dist/aclocal_java/ac_try_compile_java.ac39
-rw-r--r--bdb/dist/aclocal_java/ac_try_run_javac.ac40
-rw-r--r--bdb/dist/build/script94
-rw-r--r--bdb/dist/buildrel109
-rwxr-xr-xbdb/dist/config.guess1354
-rwxr-xr-xbdb/dist/config.sub1460
-rw-r--r--bdb/dist/configure.ac611
-rw-r--r--bdb/dist/configure.in584
-rw-r--r--bdb/dist/db.ecd.in64
-rw-r--r--bdb/dist/db.spec.in52
-rw-r--r--bdb/dist/gen_inc.awk73
-rw-r--r--bdb/dist/gen_rec.awk651
-rw-r--r--bdb/dist/gen_rpc.awk1172
-rwxr-xr-xbdb/dist/install-sh251
-rw-r--r--bdb/dist/ltconfig3136
-rw-r--r--bdb/dist/ltmain.sh2554
-rw-r--r--bdb/dist/pubdef.in350
-rw-r--r--bdb/dist/rec_ctemp62
-rw-r--r--bdb/dist/s_all21
-rwxr-xr-xbdb/dist/s_config36
-rw-r--r--bdb/dist/s_crypto59
-rw-r--r--bdb/dist/s_dir42
-rwxr-xr-xbdb/dist/s_include181
-rwxr-xr-xbdb/dist/s_java280
-rwxr-xr-xbdb/dist/s_javah55
-rwxr-xr-xbdb/dist/s_perm62
-rwxr-xr-xbdb/dist/s_readme27
-rwxr-xr-xbdb/dist/s_recover75
-rw-r--r--bdb/dist/s_rpc136
-rwxr-xr-xbdb/dist/s_symlink52
-rwxr-xr-xbdb/dist/s_tags27
-rwxr-xr-xbdb/dist/s_tcl53
-rwxr-xr-xbdb/dist/s_test92
-rw-r--r--bdb/dist/s_vxworks306
-rwxr-xr-xbdb/dist/s_win3287
-rw-r--r--bdb/dist/s_win32_dsp25
-rw-r--r--bdb/dist/srcfiles.in581
-rw-r--r--bdb/dist/template/.IGNORE_ME3
-rw-r--r--bdb/dist/template/rec_ctemp62
-rw-r--r--bdb/dist/vx_2.0/BerkeleyDB.wpj251
-rw-r--r--bdb/dist/vx_2.0/wpj.in160
-rw-r--r--bdb/dist/vx_3.1/Makefile.custom51
-rw-r--r--bdb/dist/vx_3.1/cdf.112
-rw-r--r--bdb/dist/vx_3.1/cdf.29
-rw-r--r--bdb/dist/vx_3.1/cdf.32
-rw-r--r--bdb/dist/vx_3.1/component.cdf30
-rw-r--r--bdb/dist/vx_3.1/component.wpj475
-rw-r--r--bdb/dist/vx_3.1/wpj.122
-rw-r--r--bdb/dist/vx_3.1/wpj.2130
-rw-r--r--bdb/dist/vx_3.1/wpj.3128
-rw-r--r--bdb/dist/vx_3.1/wpj.4135
-rw-r--r--bdb/dist/vx_3.1/wpj.522
-rwxr-xr-xbdb/dist/vx_buildcd119
-rw-r--r--bdb/dist/vx_config.in381
-rw-r--r--bdb/dist/vx_setup/CONFIG.in10
-rw-r--r--bdb/dist/vx_setup/LICENSE.TXT3
-rw-r--r--bdb/dist/vx_setup/MESSAGES.TCL651
-rw-r--r--bdb/dist/vx_setup/README.in7
-rw-r--r--bdb/dist/vx_setup/SETUP.BMPbin0 -> 187962 bytes
-rw-r--r--bdb/dist/vx_setup/vx_allfile.in5
-rw-r--r--bdb/dist/vx_setup/vx_demofile.in3
-rw-r--r--bdb/dist/vx_setup/vx_setup.in13
-rw-r--r--bdb/dist/win_config.in439
-rw-r--r--bdb/dist/win_exports.in134
-rw-r--r--bdb/env/db_salloc.c34
-rw-r--r--bdb/env/db_shash.c9
-rw-r--r--bdb/env/env_file.c166
-rw-r--r--bdb/env/env_method.c354
-rw-r--r--bdb/env/env_method.c.b643
-rw-r--r--bdb/env/env_open.c781
-rw-r--r--bdb/env/env_recover.c747
-rw-r--r--bdb/env/env_region.c247
-rw-r--r--bdb/examples_c/README8
-rw-r--r--bdb/examples_c/bench_001.c382
-rw-r--r--bdb/examples_c/ex_access.c95
-rw-r--r--bdb/examples_c/ex_apprec/auto_rebuild9
-rw-r--r--bdb/examples_c/ex_apprec/ex_apprec.c267
-rw-r--r--bdb/examples_c/ex_apprec/ex_apprec.h24
-rw-r--r--bdb/examples_c/ex_apprec/ex_apprec.src41
-rw-r--r--bdb/examples_c/ex_apprec/ex_apprec_rec.c115
-rw-r--r--bdb/examples_c/ex_btrec.c72
-rw-r--r--bdb/examples_c/ex_dbclient.c82
-rw-r--r--bdb/examples_c/ex_env.c77
-rw-r--r--bdb/examples_c/ex_lock.c60
-rw-r--r--bdb/examples_c/ex_mpool.c151
-rw-r--r--bdb/examples_c/ex_repquote/ex_repquote.h69
-rw-r--r--bdb/examples_c/ex_repquote/ex_rq_client.c250
-rw-r--r--bdb/examples_c/ex_repquote/ex_rq_main.c303
-rw-r--r--bdb/examples_c/ex_repquote/ex_rq_master.c165
-rw-r--r--bdb/examples_c/ex_repquote/ex_rq_net.c692
-rw-r--r--bdb/examples_c/ex_repquote/ex_rq_util.c412
-rw-r--r--bdb/examples_c/ex_thread.c143
-rw-r--r--bdb/examples_c/ex_tpcb.c317
-rw-r--r--bdb/examples_c/ex_tpcb.h4
-rw-r--r--bdb/examples_cxx/AccessExample.cpp41
-rw-r--r--bdb/examples_cxx/BtRecExample.cpp59
-rw-r--r--bdb/examples_cxx/EnvExample.cpp39
-rw-r--r--bdb/examples_cxx/LockExample.cpp48
-rw-r--r--bdb/examples_cxx/MpoolExample.cpp114
-rw-r--r--bdb/examples_cxx/TpcbExample.cpp213
-rw-r--r--bdb/fileops/fileops.src111
-rw-r--r--bdb/fileops/fop_basic.c275
-rw-r--r--bdb/fileops/fop_rec.c308
-rw-r--r--bdb/fileops/fop_util.c928
-rw-r--r--bdb/hash/hash.c1386
-rw-r--r--bdb/hash/hash.src219
-rw-r--r--bdb/hash/hash_conv.c32
-rw-r--r--bdb/hash/hash_dup.c396
-rw-r--r--bdb/hash/hash_func.c11
-rw-r--r--bdb/hash/hash_meta.c56
-rw-r--r--bdb/hash/hash_method.c12
-rw-r--r--bdb/hash/hash_open.c558
-rw-r--r--bdb/hash/hash_page.c799
-rw-r--r--bdb/hash/hash_rec.c500
-rw-r--r--bdb/hash/hash_reclaim.c59
-rw-r--r--bdb/hash/hash_stat.c137
-rw-r--r--bdb/hash/hash_upgrade.c23
-rw-r--r--bdb/hash/hash_verify.c238
-rw-r--r--bdb/hmac/hmac.c207
-rw-r--r--bdb/hmac/sha1.c294
-rw-r--r--bdb/hsearch/hsearch.c24
-rw-r--r--bdb/include/btree.h317
-rw-r--r--bdb/include/cxx_int.h96
-rw-r--r--bdb/include/db.src1383
-rw-r--r--bdb/include/db_185.h175
-rw-r--r--bdb/include/db_am.h131
-rw-r--r--bdb/include/db_cxx.h652
-rw-r--r--bdb/include/db_dispatch.h95
-rw-r--r--bdb/include/db_int.src397
-rw-r--r--bdb/include/db_join.h30
-rw-r--r--bdb/include/db_page.h576
-rw-r--r--bdb/include/db_server_int.h85
-rw-r--r--bdb/include/db_shash.h77
-rw-r--r--bdb/include/db_swap.h115
-rw-r--r--bdb/include/db_upgrade.h174
-rw-r--r--bdb/include/db_verify.h191
-rw-r--r--bdb/include/debug.h104
-rw-r--r--bdb/include/hash.h140
-rw-r--r--bdb/include/lock.h190
-rw-r--r--bdb/include/log.h209
-rw-r--r--bdb/include/mp.h244
-rw-r--r--bdb/include/mutex.h766
-rw-r--r--bdb/include/os.h46
-rw-r--r--bdb/include/os_jump.h34
-rw-r--r--bdb/include/qam.h150
-rw-r--r--bdb/include/region.h292
-rw-r--r--bdb/include/shqueue.h337
-rw-r--r--bdb/include/tcl_db.h219
-rw-r--r--bdb/include/txn.h150
-rw-r--r--bdb/include/xa.h179
-rw-r--r--bdb/java/src/com/sleepycat/db/Db.java710
-rw-r--r--bdb/java/src/com/sleepycat/db/Db.java.in761
-rw-r--r--bdb/java/src/com/sleepycat/db/DbAppDispatch.java22
-rw-r--r--bdb/java/src/com/sleepycat/db/DbAppendRecno.java8
-rw-r--r--bdb/java/src/com/sleepycat/db/DbBtreeCompare.java8
-rw-r--r--bdb/java/src/com/sleepycat/db/DbBtreePrefix.java8
-rw-r--r--bdb/java/src/com/sleepycat/db/DbBtreeStat.java40
-rw-r--r--bdb/java/src/com/sleepycat/db/DbClient.java21
-rw-r--r--bdb/java/src/com/sleepycat/db/DbDeadlockException.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbDupCompare.java8
-rw-r--r--bdb/java/src/com/sleepycat/db/DbEnv.java138
-rw-r--r--bdb/java/src/com/sleepycat/db/DbEnvFeedback.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbErrcall.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbException.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbFeedback.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbHash.java8
-rw-r--r--bdb/java/src/com/sleepycat/db/DbHashStat.java37
-rw-r--r--bdb/java/src/com/sleepycat/db/DbKeyRange.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLock.java11
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLockNotGrantedException.java57
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLockRequest.java67
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLockStat.java30
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLogStat.java35
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLogc.java39
-rw-r--r--bdb/java/src/com/sleepycat/db/DbLsn.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMemoryException.java27
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMpoolFStat.java28
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMpoolStat.java10
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMultipleDataIterator.java46
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMultipleIterator.java51
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMultipleKeyDataIterator.java56
-rw-r--r--bdb/java/src/com/sleepycat/db/DbMultipleRecnoDataIterator.java51
-rw-r--r--bdb/java/src/com/sleepycat/db/DbOutputStreamErrcall.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbPreplist.java22
-rw-r--r--bdb/java/src/com/sleepycat/db/DbQueueStat.java32
-rw-r--r--bdb/java/src/com/sleepycat/db/DbRecoveryInit.java23
-rw-r--r--bdb/java/src/com/sleepycat/db/DbRepTransport.java19
-rw-r--r--bdb/java/src/com/sleepycat/db/DbRunRecoveryException.java6
-rw-r--r--bdb/java/src/com/sleepycat/db/DbSecondaryKeyCreate.java22
-rw-r--r--bdb/java/src/com/sleepycat/db/DbTxn.java42
-rw-r--r--bdb/java/src/com/sleepycat/db/DbTxnRecover.java22
-rw-r--r--bdb/java/src/com/sleepycat/db/DbTxnStat.java40
-rw-r--r--bdb/java/src/com/sleepycat/db/DbUtil.java98
-rw-r--r--bdb/java/src/com/sleepycat/db/Dbc.java10
-rw-r--r--bdb/java/src/com/sleepycat/db/Dbt.java210
-rw-r--r--bdb/java/src/com/sleepycat/db/xa/DbXAResource.java190
-rw-r--r--bdb/java/src/com/sleepycat/db/xa/DbXid.java49
-rw-r--r--bdb/java/src/com/sleepycat/examples/AccessExample.java19
-rw-r--r--bdb/java/src/com/sleepycat/examples/BtRecExample.java44
-rw-r--r--bdb/java/src/com/sleepycat/examples/BulkAccessExample.java198
-rw-r--r--bdb/java/src/com/sleepycat/examples/EnvExample.java4
-rw-r--r--bdb/java/src/com/sleepycat/examples/LockExample.java6
-rw-r--r--bdb/java/src/com/sleepycat/examples/TpcbExample.java48
-rw-r--r--bdb/libdb_java/checkapi.prl4
-rw-r--r--bdb/libdb_java/com_sleepycat_db_Db.h267
-rw-r--r--bdb/libdb_java/com_sleepycat_db_DbEnv.h238
-rw-r--r--bdb/libdb_java/com_sleepycat_db_DbLock.h10
-rw-r--r--bdb/libdb_java/com_sleepycat_db_DbLogc.h37
-rw-r--r--bdb/libdb_java/com_sleepycat_db_DbLsn.h2
-rw-r--r--bdb/libdb_java/com_sleepycat_db_DbTxn.h22
-rw-r--r--bdb/libdb_java/com_sleepycat_db_DbUtil.h22
-rw-r--r--bdb/libdb_java/com_sleepycat_db_Dbc.h10
-rw-r--r--bdb/libdb_java/com_sleepycat_db_Dbt.h134
-rw-r--r--bdb/libdb_java/com_sleepycat_db_xa_DbXAResource.h95
-rw-r--r--bdb/libdb_java/java_Db.c734
-rw-r--r--bdb/libdb_java/java_DbEnv.c1302
-rw-r--r--bdb/libdb_java/java_DbLock.c33
-rw-r--r--bdb/libdb_java/java_DbLogc.c110
-rw-r--r--bdb/libdb_java/java_DbLsn.c12
-rw-r--r--bdb/libdb_java/java_DbTxn.c71
-rw-r--r--bdb/libdb_java/java_DbUtil.c27
-rw-r--r--bdb/libdb_java/java_DbXAResource.c288
-rw-r--r--bdb/libdb_java/java_Dbc.c158
-rw-r--r--bdb/libdb_java/java_Dbt.c141
-rw-r--r--bdb/libdb_java/java_info.c816
-rw-r--r--bdb/libdb_java/java_info.h103
-rw-r--r--bdb/libdb_java/java_locked.c375
-rw-r--r--bdb/libdb_java/java_locked.h116
-rw-r--r--bdb/libdb_java/java_util.c584
-rw-r--r--bdb/libdb_java/java_util.h304
-rw-r--r--bdb/lock/Design10
-rw-r--r--bdb/lock/lock.c1085
-rw-r--r--bdb/lock/lock_conflict.c34
-rw-r--r--bdb/lock/lock_deadlock.c611
-rw-r--r--bdb/lock/lock_method.c177
-rw-r--r--bdb/lock/lock_region.c234
-rw-r--r--bdb/lock/lock_stat.c370
-rw-r--r--bdb/lock/lock_util.c12
-rw-r--r--bdb/log/log.c881
-rw-r--r--bdb/log/log.src46
-rw-r--r--bdb/log/log_archive.c263
-rw-r--r--bdb/log/log_compare.c6
-rw-r--r--bdb/log/log_findckp.c135
-rw-r--r--bdb/log/log_get.c1185
-rw-r--r--bdb/log/log_method.c113
-rw-r--r--bdb/log/log_put.c1040
-rw-r--r--bdb/log/log_rec.c647
-rw-r--r--bdb/log/log_register.c433
-rw-r--r--bdb/mp/Design52
-rw-r--r--bdb/mp/mp_alloc.c430
-rw-r--r--bdb/mp/mp_bh.c568
-rw-r--r--bdb/mp/mp_fget.c763
-rw-r--r--bdb/mp/mp_fopen.c1198
-rw-r--r--bdb/mp/mp_fput.c196
-rw-r--r--bdb/mp/mp_fset.c63
-rw-r--r--bdb/mp/mp_method.c109
-rw-r--r--bdb/mp/mp_region.c211
-rw-r--r--bdb/mp/mp_register.c33
-rw-r--r--bdb/mp/mp_stat.c325
-rw-r--r--bdb/mp/mp_sync.c909
-rw-r--r--bdb/mp/mp_trickle.c136
-rw-r--r--bdb/mutex/mut_fcntl.c48
-rw-r--r--bdb/mutex/mut_pthread.c145
-rw-r--r--bdb/mutex/mut_tas.c71
-rw-r--r--bdb/mutex/mut_win32.c257
-rw-r--r--bdb/mutex/mutex.c248
-rw-r--r--bdb/mutex/tm.c627
-rw-r--r--bdb/mutex/uts4_cc.s6
-rw-r--r--bdb/os/os_abs.c4
-rw-r--r--bdb/os/os_alloc.c308
-rw-r--r--bdb/os/os_clock.c92
-rw-r--r--bdb/os/os_config.c31
-rw-r--r--bdb/os/os_dir.c26
-rw-r--r--bdb/os/os_errno.c36
-rw-r--r--bdb/os/os_fid.c22
-rw-r--r--bdb/os/os_finit.c111
-rw-r--r--bdb/os/os_fsync.c15
-rw-r--r--bdb/os/os_handle.c60
-rw-r--r--bdb/os/os_id.c47
-rw-r--r--bdb/os/os_map.c45
-rw-r--r--bdb/os/os_method.c140
-rw-r--r--bdb/os/os_oflags.c20
-rw-r--r--bdb/os/os_open.c47
-rw-r--r--bdb/os/os_region.c17
-rw-r--r--bdb/os/os_rename.c27
-rw-r--r--bdb/os/os_root.c4
-rw-r--r--bdb/os/os_rpath.c4
-rw-r--r--bdb/os/os_rw.c23
-rw-r--r--bdb/os/os_seek.c15
-rw-r--r--bdb/os/os_sleep.c15
-rw-r--r--bdb/os/os_spin.c38
-rw-r--r--bdb/os/os_stat.c41
-rw-r--r--bdb/os/os_tmpdir.c10
-rw-r--r--bdb/os/os_unlink.c83
-rw-r--r--bdb/os_vxworks/os_abs.c45
-rw-r--r--bdb/os_vxworks/os_finit.c57
-rw-r--r--bdb/os_vxworks/os_map.c440
-rw-r--r--bdb/os_vxworks/os_vx_abs.c45
-rw-r--r--bdb/os_vxworks/os_vx_config.c31
-rw-r--r--bdb/os_vxworks/os_vx_map.c441
-rw-r--r--bdb/os_win32/os_abs.c4
-rw-r--r--bdb/os_win32/os_clock.c37
-rw-r--r--bdb/os_win32/os_config.c29
-rw-r--r--bdb/os_win32/os_dir.c30
-rw-r--r--bdb/os_win32/os_errno.c17
-rw-r--r--bdb/os_win32/os_fid.c20
-rw-r--r--bdb/os_win32/os_finit.c60
-rw-r--r--bdb/os_win32/os_fsync.c59
-rw-r--r--bdb/os_win32/os_handle.c126
-rw-r--r--bdb/os_win32/os_map.c118
-rw-r--r--bdb/os_win32/os_open.c98
-rw-r--r--bdb/os_win32/os_rename.c73
-rw-r--r--bdb/os_win32/os_rw.c182
-rw-r--r--bdb/os_win32/os_seek.c71
-rw-r--r--bdb/os_win32/os_sleep.c9
-rw-r--r--bdb/os_win32/os_spin.c20
-rw-r--r--bdb/os_win32/os_stat.c100
-rw-r--r--bdb/os_win32/os_type.c7
-rw-r--r--bdb/patches/log-corruption.patch62
-rw-r--r--bdb/perl.BerkeleyDB/BerkeleyDB.pm1227
-rw-r--r--bdb/perl.BerkeleyDB/BerkeleyDB.pod1751
-rw-r--r--bdb/perl.BerkeleyDB/BerkeleyDB.pod.P1518
-rw-r--r--bdb/perl.BerkeleyDB/BerkeleyDB.xs3927
-rw-r--r--bdb/perl.BerkeleyDB/Changes112
-rw-r--r--bdb/perl.BerkeleyDB/MANIFEST49
-rw-r--r--bdb/perl.BerkeleyDB/Makefile.PL112
-rw-r--r--bdb/perl.BerkeleyDB/README464
-rw-r--r--bdb/perl.BerkeleyDB/config.in51
-rwxr-xr-xbdb/perl.BerkeleyDB/dbinfo109
-rw-r--r--bdb/perl.BerkeleyDB/mkconsts211
-rw-r--r--bdb/perl.BerkeleyDB/t/btree.t976
-rw-r--r--bdb/perl.BerkeleyDB/t/db-3.0.t128
-rw-r--r--bdb/perl.BerkeleyDB/t/db-3.1.t172
-rw-r--r--bdb/perl.BerkeleyDB/t/db-3.2.t90
-rw-r--r--bdb/perl.BerkeleyDB/t/destroy.t141
-rw-r--r--bdb/perl.BerkeleyDB/t/env.t279
-rw-r--r--bdb/perl.BerkeleyDB/t/examples.t482
-rw-r--r--bdb/perl.BerkeleyDB/t/examples.t.T496
-rw-r--r--bdb/perl.BerkeleyDB/t/examples3.t213
-rw-r--r--bdb/perl.BerkeleyDB/t/examples3.t.T217
-rw-r--r--bdb/perl.BerkeleyDB/t/filter.t244
-rw-r--r--bdb/perl.BerkeleyDB/t/hash.t777
-rw-r--r--bdb/perl.BerkeleyDB/t/join.t270
-rw-r--r--bdb/perl.BerkeleyDB/t/mldbm.t166
-rw-r--r--bdb/perl.BerkeleyDB/t/queue.t837
-rw-r--r--bdb/perl.BerkeleyDB/t/recno.t967
-rw-r--r--bdb/perl.BerkeleyDB/t/strict.t220
-rw-r--r--bdb/perl.BerkeleyDB/t/subdb.t296
-rw-r--r--bdb/perl.BerkeleyDB/t/txn.t354
-rw-r--r--bdb/perl.BerkeleyDB/t/unknown.t212
-rw-r--r--bdb/perl.BerkeleyDB/typemap275
-rw-r--r--bdb/perl.DB_File/Changes343
-rw-r--r--bdb/perl.DB_File/DB_File.pm2072
-rw-r--r--bdb/perl.DB_File/DB_File.xs2072
-rw-r--r--bdb/perl.DB_File/MANIFEST27
-rw-r--r--bdb/perl.DB_File/Makefile.PL187
-rw-r--r--bdb/perl.DB_File/README396
-rw-r--r--bdb/perl.DB_File/config.in99
-rw-r--r--bdb/perl.DB_File/dbinfo109
-rw-r--r--bdb/perl.DB_File/t/db-btree.t1306
-rw-r--r--bdb/perl.DB_File/t/db-hash.t753
-rw-r--r--bdb/perl.DB_File/t/db-recno.t899
-rw-r--r--bdb/perl.DB_File/typemap44
-rw-r--r--bdb/perl.DB_File/version.c81
-rw-r--r--bdb/perl/BerkeleyDB/BerkeleyDB.pm1506
-rw-r--r--bdb/perl/BerkeleyDB/BerkeleyDB.pod1792
-rw-r--r--bdb/perl/BerkeleyDB/BerkeleyDB.pod.P1559
-rw-r--r--bdb/perl/BerkeleyDB/BerkeleyDB.xs3643
-rw-r--r--bdb/perl/BerkeleyDB/BerkeleyDB/Btree.pm (renamed from bdb/perl.BerkeleyDB/BerkeleyDB/Btree.pm)0
-rw-r--r--bdb/perl/BerkeleyDB/BerkeleyDB/Hash.pm (renamed from bdb/perl.BerkeleyDB/BerkeleyDB/Hash.pm)0
-rw-r--r--bdb/perl/BerkeleyDB/Changes167
-rw-r--r--bdb/perl/BerkeleyDB/MANIFEST56
-rw-r--r--bdb/perl/BerkeleyDB/Makefile.PL123
-rw-r--r--bdb/perl/BerkeleyDB/README484
-rw-r--r--bdb/perl/BerkeleyDB/Todo (renamed from bdb/perl.BerkeleyDB/Todo)0
-rw-r--r--bdb/perl/BerkeleyDB/config.in43
-rw-r--r--bdb/perl/BerkeleyDB/constants.h4046
-rw-r--r--bdb/perl/BerkeleyDB/constants.xs87
-rwxr-xr-xbdb/perl/BerkeleyDB/dbinfo112
-rw-r--r--bdb/perl/BerkeleyDB/hints/dec_osf.pl1
-rw-r--r--bdb/perl/BerkeleyDB/hints/irix_6_5.pl (renamed from bdb/perl.BerkeleyDB/hints/irix_6_5.pl)0
-rw-r--r--bdb/perl/BerkeleyDB/hints/solaris.pl (renamed from bdb/perl.BerkeleyDB/hints/solaris.pl)0
-rw-r--r--bdb/perl/BerkeleyDB/mkconsts770
-rwxr-xr-xbdb/perl/BerkeleyDB/mkpod (renamed from bdb/perl.BerkeleyDB/mkpod)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.004 (renamed from bdb/perl.BerkeleyDB/patches/5.004)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.004_01 (renamed from bdb/perl.BerkeleyDB/patches/5.004_01)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.004_02 (renamed from bdb/perl.BerkeleyDB/patches/5.004_02)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.004_03 (renamed from bdb/perl.BerkeleyDB/patches/5.004_03)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.004_04 (renamed from bdb/perl.BerkeleyDB/patches/5.004_04)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.004_05 (renamed from bdb/perl.BerkeleyDB/patches/5.004_05)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.005 (renamed from bdb/perl.BerkeleyDB/patches/5.005)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.005_01 (renamed from bdb/perl.BerkeleyDB/patches/5.005_01)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.005_02 (renamed from bdb/perl.BerkeleyDB/patches/5.005_02)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.005_03 (renamed from bdb/perl.BerkeleyDB/patches/5.005_03)0
-rw-r--r--bdb/perl/BerkeleyDB/patches/5.6.0 (renamed from bdb/perl.BerkeleyDB/patches/5.6.0)0
-rw-r--r--bdb/perl/BerkeleyDB/ppport.h329
-rw-r--r--bdb/perl/BerkeleyDB/scan229
-rw-r--r--bdb/perl/BerkeleyDB/t/btree.t931
-rw-r--r--bdb/perl/BerkeleyDB/t/destroy.t105
-rw-r--r--bdb/perl/BerkeleyDB/t/env.t217
-rw-r--r--bdb/perl/BerkeleyDB/t/examples.t401
-rw-r--r--bdb/perl/BerkeleyDB/t/examples.t.T415
-rw-r--r--bdb/perl/BerkeleyDB/t/examples3.t132
-rw-r--r--bdb/perl/BerkeleyDB/t/examples3.t.T136
-rw-r--r--bdb/perl/BerkeleyDB/t/filter.t217
-rw-r--r--bdb/perl/BerkeleyDB/t/hash.t728
-rw-r--r--bdb/perl/BerkeleyDB/t/join.t225
-rw-r--r--bdb/perl/BerkeleyDB/t/mldbm.t161
-rw-r--r--bdb/perl/BerkeleyDB/t/queue.t763
-rw-r--r--bdb/perl/BerkeleyDB/t/recno.t913
-rw-r--r--bdb/perl/BerkeleyDB/t/strict.t174
-rw-r--r--bdb/perl/BerkeleyDB/t/subdb.t243
-rw-r--r--bdb/perl/BerkeleyDB/t/txn.t320
-rw-r--r--bdb/perl/BerkeleyDB/t/unknown.t176
-rw-r--r--bdb/perl/BerkeleyDB/t/util.pm220
-rw-r--r--bdb/perl/BerkeleyDB/typemap275
-rw-r--r--bdb/perl/DB_File/Changes434
-rw-r--r--bdb/perl/DB_File/DB_File.pm2291
-rw-r--r--bdb/perl/DB_File/DB_File.xs1951
-rw-r--r--bdb/perl/DB_File/DB_File_BS (renamed from bdb/perl.DB_File/DB_File_BS)0
-rw-r--r--bdb/perl/DB_File/MANIFEST30
-rw-r--r--bdb/perl/DB_File/Makefile.PL330
-rw-r--r--bdb/perl/DB_File/README458
-rw-r--r--bdb/perl/DB_File/config.in97
-rw-r--r--bdb/perl/DB_File/dbinfo112
-rw-r--r--bdb/perl/DB_File/fallback.h455
-rw-r--r--bdb/perl/DB_File/fallback.xs88
-rw-r--r--bdb/perl/DB_File/hints/dynixptx.pl (renamed from bdb/perl.DB_File/hints/dynixptx.pl)0
-rw-r--r--bdb/perl/DB_File/hints/sco.pl (renamed from bdb/perl.DB_File/hints/sco.pl)0
-rw-r--r--bdb/perl/DB_File/patches/5.004 (renamed from bdb/perl.DB_File/patches/5.004)0
-rw-r--r--bdb/perl/DB_File/patches/5.004_01 (renamed from bdb/perl.DB_File/patches/5.004_01)0
-rw-r--r--bdb/perl/DB_File/patches/5.004_02 (renamed from bdb/perl.DB_File/patches/5.004_02)0
-rw-r--r--bdb/perl/DB_File/patches/5.004_03 (renamed from bdb/perl.DB_File/patches/5.004_03)0
-rw-r--r--bdb/perl/DB_File/patches/5.004_04 (renamed from bdb/perl.DB_File/patches/5.004_04)0
-rw-r--r--bdb/perl/DB_File/patches/5.004_05 (renamed from bdb/perl.DB_File/patches/5.004_05)0
-rw-r--r--bdb/perl/DB_File/patches/5.005 (renamed from bdb/perl.DB_File/patches/5.005)0
-rw-r--r--bdb/perl/DB_File/patches/5.005_01 (renamed from bdb/perl.DB_File/patches/5.005_01)0
-rw-r--r--bdb/perl/DB_File/patches/5.005_02 (renamed from bdb/perl.DB_File/patches/5.005_02)0
-rw-r--r--bdb/perl/DB_File/patches/5.005_03 (renamed from bdb/perl.DB_File/patches/5.005_03)0
-rw-r--r--bdb/perl/DB_File/patches/5.6.0 (renamed from bdb/perl.DB_File/patches/5.6.0)0
-rw-r--r--bdb/perl/DB_File/ppport.h329
-rw-r--r--bdb/perl/DB_File/t/db-btree.t1489
-rw-r--r--bdb/perl/DB_File/t/db-hash.t981
-rw-r--r--bdb/perl/DB_File/t/db-recno.t1428
-rw-r--r--bdb/perl/DB_File/typemap46
-rw-r--r--bdb/perl/DB_File/version.c82
-rw-r--r--bdb/qam/qam.c1070
-rw-r--r--bdb/qam/qam.src71
-rw-r--r--bdb/qam/qam_conv.c15
-rw-r--r--bdb/qam/qam_files.c293
-rw-r--r--bdb/qam/qam_method.c381
-rw-r--r--bdb/qam/qam_open.c309
-rw-r--r--bdb/qam/qam_rec.c424
-rw-r--r--bdb/qam/qam_stat.c90
-rw-r--r--bdb/qam/qam_upgrade.c9
-rw-r--r--bdb/qam/qam_verify.c50
-rw-r--r--bdb/rep/rep_method.c1144
-rw-r--r--bdb/rep/rep_record.c1513
-rw-r--r--bdb/rep/rep_region.c187
-rw-r--r--bdb/rep/rep_util.c867
-rw-r--r--bdb/rpc_client/client.c321
-rw-r--r--bdb/rpc_client/gen_client_ret.c516
-rw-r--r--bdb/rpc_server/c/db_server_proc.c.in2500
-rw-r--r--bdb/rpc_server/c/db_server_util.c815
-rw-r--r--bdb/rpc_server/clsrv.html436
-rw-r--r--bdb/rpc_server/cxx/db_server_cxxproc.cpp2200
-rw-r--r--bdb/rpc_server/cxx/db_server_cxxutil.cpp746
-rw-r--r--bdb/rpc_server/db_server.sed5
-rw-r--r--bdb/rpc_server/db_server_proc.c1546
-rw-r--r--bdb/rpc_server/db_server_svc.sed5
-rw-r--r--bdb/rpc_server/db_server_util.c612
-rw-r--r--bdb/rpc_server/java/DbDispatcher.java590
-rw-r--r--bdb/rpc_server/java/DbServer.java301
-rw-r--r--bdb/rpc_server/java/FreeList.java102
-rw-r--r--bdb/rpc_server/java/LocalIterator.java23
-rw-r--r--bdb/rpc_server/java/README24
-rw-r--r--bdb/rpc_server/java/RpcDb.java694
-rw-r--r--bdb/rpc_server/java/RpcDbEnv.java269
-rw-r--r--bdb/rpc_server/java/RpcDbTxn.java123
-rw-r--r--bdb/rpc_server/java/RpcDbc.java238
-rw-r--r--bdb/rpc_server/java/Timer.java22
-rw-r--r--bdb/rpc_server/java/gen/DbServerStub.java495
-rw-r--r--bdb/rpc_server/java/gen/__db_associate_msg.java41
-rw-r--r--bdb/rpc_server/java/gen/__db_associate_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_bt_maxkey_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_bt_maxkey_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_bt_minkey_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_bt_minkey_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_close_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_close_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_create_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_create_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_cursor_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__db_cursor_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_del_msg.java53
-rw-r--r--bdb/rpc_server/java/gen/__db_del_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_encrypt_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__db_encrypt_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_extentsize_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_extentsize_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_flags_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_flags_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_get_msg.java68
-rw-r--r--bdb/rpc_server/java/gen/__db_get_reply.java38
-rw-r--r--bdb/rpc_server/java/gen/__db_h_ffactor_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_h_ffactor_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_h_nelem_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_h_nelem_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_join_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__db_join_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_key_range_msg.java53
-rw-r--r--bdb/rpc_server/java/gen/__db_key_range_reply.java41
-rw-r--r--bdb/rpc_server/java/gen/__db_lorder_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_lorder_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_open_msg.java50
-rw-r--r--bdb/rpc_server/java/gen/__db_open_reply.java44
-rw-r--r--bdb/rpc_server/java/gen/__db_pagesize_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_pagesize_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_pget_msg.java83
-rw-r--r--bdb/rpc_server/java/gen/__db_pget_reply.java41
-rw-r--r--bdb/rpc_server/java/gen/__db_put_msg.java68
-rw-r--r--bdb/rpc_server/java/gen/__db_put_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_re_delim_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_re_delim_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_re_len_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_re_len_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_re_pad_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_re_pad_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_remove_msg.java41
-rw-r--r--bdb/rpc_server/java/gen/__db_remove_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_rename_msg.java44
-rw-r--r--bdb/rpc_server/java/gen/__db_rename_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_stat_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_stat_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_sync_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__db_sync_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__db_truncate_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__db_truncate_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__dbc_close_msg.java32
-rw-r--r--bdb/rpc_server/java/gen/__dbc_close_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__dbc_count_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__dbc_count_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__dbc_del_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__dbc_del_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__dbc_dup_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__dbc_dup_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__dbc_get_msg.java65
-rw-r--r--bdb/rpc_server/java/gen/__dbc_get_reply.java38
-rw-r--r--bdb/rpc_server/java/gen/__dbc_pget_msg.java80
-rw-r--r--bdb/rpc_server/java/gen/__dbc_pget_reply.java41
-rw-r--r--bdb/rpc_server/java/gen/__dbc_put_msg.java65
-rw-r--r--bdb/rpc_server/java/gen/__dbc_put_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__env_cachesize_msg.java41
-rw-r--r--bdb/rpc_server/java/gen/__env_cachesize_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_close_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__env_close_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_create_msg.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_create_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__env_dbremove_msg.java44
-rw-r--r--bdb/rpc_server/java/gen/__env_dbremove_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_dbrename_msg.java47
-rw-r--r--bdb/rpc_server/java/gen/__env_dbrename_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_encrypt_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__env_encrypt_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_flags_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__env_flags_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__env_open_msg.java41
-rw-r--r--bdb/rpc_server/java/gen/__env_open_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__env_remove_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__env_remove_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__txn_abort_msg.java32
-rw-r--r--bdb/rpc_server/java/gen/__txn_abort_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__txn_begin_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__txn_begin_reply.java35
-rw-r--r--bdb/rpc_server/java/gen/__txn_commit_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__txn_commit_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__txn_discard_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__txn_discard_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__txn_prepare_msg.java35
-rw-r--r--bdb/rpc_server/java/gen/__txn_prepare_reply.java32
-rw-r--r--bdb/rpc_server/java/gen/__txn_recover_msg.java38
-rw-r--r--bdb/rpc_server/java/gen/__txn_recover_reply.java41
-rw-r--r--bdb/rpc_server/java/gen/db_server.java67
-rw-r--r--bdb/rpc_server/java/jrpcgen.jarbin0 -> 57125 bytes
-rw-r--r--bdb/rpc_server/java/oncrpc.jarbin0 -> 84122 bytes
-rw-r--r--bdb/rpc_server/java/s_jrpcgen3
-rw-r--r--bdb/rpc_server/rpc.src477
-rw-r--r--bdb/tcl/docs/db.html403
-rw-r--r--bdb/tcl/docs/env.html607
-rw-r--r--bdb/tcl/docs/historic.html3
-rw-r--r--bdb/tcl/docs/index.html6
-rw-r--r--bdb/tcl/docs/library.html3
-rw-r--r--bdb/tcl/docs/lock.html308
-rw-r--r--bdb/tcl/docs/log.html24
-rw-r--r--bdb/tcl/docs/mpool.html3
-rw-r--r--bdb/tcl/docs/rep.html51
-rw-r--r--bdb/tcl/docs/test.html3
-rw-r--r--bdb/tcl/docs/txn.html93
-rw-r--r--bdb/tcl/tcl_compat.c467
-rw-r--r--bdb/tcl/tcl_db.c1180
-rw-r--r--bdb/tcl/tcl_db_pkg.c1739
-rw-r--r--bdb/tcl/tcl_dbcursor.c388
-rw-r--r--bdb/tcl/tcl_env.c882
-rw-r--r--bdb/tcl/tcl_internal.c367
-rw-r--r--bdb/tcl/tcl_lock.c258
-rw-r--r--bdb/tcl/tcl_log.c441
-rw-r--r--bdb/tcl/tcl_mp.c194
-rw-r--r--bdb/tcl/tcl_rep.c405
-rw-r--r--bdb/tcl/tcl_txn.c338
-rw-r--r--bdb/tcl/tcl_util.c381
-rw-r--r--bdb/test/TESTS448
-rw-r--r--bdb/test/archive.tcl62
-rw-r--r--bdb/test/bigfile001.tcl85
-rw-r--r--bdb/test/bigfile002.tcl45
-rw-r--r--bdb/test/byteorder.tcl19
-rw-r--r--bdb/test/conscript.tcl20
-rw-r--r--bdb/test/dbm.tcl16
-rw-r--r--bdb/test/dbscript.tcl30
-rw-r--r--bdb/test/ddoyscript.tcl172
-rw-r--r--bdb/test/ddscript.tcl7
-rw-r--r--bdb/test/dead001.tcl66
-rw-r--r--bdb/test/dead002.tcl49
-rw-r--r--bdb/test/dead003.tcl34
-rw-r--r--bdb/test/dead004.tcl108
-rw-r--r--bdb/test/dead005.tcl87
-rw-r--r--bdb/test/dead006.tcl16
-rw-r--r--bdb/test/dead007.tcl34
-rw-r--r--bdb/test/env001.tcl37
-rw-r--r--bdb/test/env002.tcl32
-rw-r--r--bdb/test/env003.tcl100
-rw-r--r--bdb/test/env004.tcl16
-rw-r--r--bdb/test/env005.tcl26
-rw-r--r--bdb/test/env006.tcl12
-rw-r--r--bdb/test/env007.tcl151
-rw-r--r--bdb/test/env008.tcl10
-rw-r--r--bdb/test/env009.tcl57
-rw-r--r--bdb/test/env010.tcl49
-rw-r--r--bdb/test/env011.tcl39
-rw-r--r--bdb/test/hsearch.tcl4
-rw-r--r--bdb/test/join.tcl28
-rw-r--r--bdb/test/lock001.tcl100
-rw-r--r--bdb/test/lock002.tcl36
-rw-r--r--bdb/test/lock003.tcl87
-rw-r--r--bdb/test/lock004.tcl29
-rw-r--r--bdb/test/lock005.tcl177
-rw-r--r--bdb/test/lockscript.tcl51
-rw-r--r--bdb/test/log.tcl337
-rw-r--r--bdb/test/log001.tcl120
-rw-r--r--bdb/test/log002.tcl85
-rw-r--r--bdb/test/log003.tcl118
-rw-r--r--bdb/test/log004.tcl46
-rw-r--r--bdb/test/log005.tcl89
-rw-r--r--bdb/test/logtrack.tcl23
-rw-r--r--bdb/test/mdbscript.tcl33
-rw-r--r--bdb/test/memp001.tcl199
-rw-r--r--bdb/test/memp002.tcl62
-rw-r--r--bdb/test/memp003.tcl153
-rw-r--r--bdb/test/mpool.tcl420
-rw-r--r--bdb/test/mpoolscript.tcl11
-rw-r--r--bdb/test/mutex.tcl225
-rw-r--r--bdb/test/mutex001.tcl51
-rw-r--r--bdb/test/mutex002.tcl94
-rw-r--r--bdb/test/mutex003.tcl52
-rw-r--r--bdb/test/mutexscript.tcl10
-rw-r--r--bdb/test/ndbm.tcl17
-rw-r--r--bdb/test/parallel.tcl295
-rw-r--r--bdb/test/recd001.tcl104
-rw-r--r--bdb/test/recd002.tcl17
-rw-r--r--bdb/test/recd003.tcl24
-rw-r--r--bdb/test/recd004.tcl17
-rw-r--r--bdb/test/recd005.tcl29
-rw-r--r--bdb/test/recd006.tcl14
-rw-r--r--bdb/test/recd007.tcl375
-rw-r--r--bdb/test/recd008.tcl10
-rw-r--r--bdb/test/recd009.tcl13
-rw-r--r--bdb/test/recd010.tcl72
-rw-r--r--bdb/test/recd011.tcl23
-rw-r--r--bdb/test/recd012.tcl135
-rw-r--r--bdb/test/recd013.tcl99
-rw-r--r--bdb/test/recd014.tcl114
-rw-r--r--bdb/test/recd015.tcl160
-rw-r--r--bdb/test/recd016.tcl183
-rw-r--r--bdb/test/recd017.tcl151
-rw-r--r--bdb/test/recd018.tcl110
-rw-r--r--bdb/test/recd019.tcl121
-rw-r--r--bdb/test/recd020.tcl180
-rw-r--r--bdb/test/recd15scr.tcl74
-rw-r--r--bdb/test/recdscript.tcl37
-rw-r--r--bdb/test/rep001.tcl249
-rw-r--r--bdb/test/rep002.tcl278
-rw-r--r--bdb/test/rep003.tcl221
-rw-r--r--bdb/test/rep004.tcl198
-rw-r--r--bdb/test/rep005.tcl225
-rw-r--r--bdb/test/reputils.tcl659
-rw-r--r--bdb/test/rpc001.tcl47
-rw-r--r--bdb/test/rpc002.tcl51
-rw-r--r--bdb/test/rpc003.tcl166
-rw-r--r--bdb/test/rpc004.tcl76
-rw-r--r--bdb/test/rpc005.tcl137
-rw-r--r--bdb/test/rsrc001.tcl22
-rw-r--r--bdb/test/rsrc002.tcl11
-rw-r--r--bdb/test/rsrc003.tcl33
-rw-r--r--bdb/test/rsrc004.tcl52
-rw-r--r--bdb/test/scr001/chk.code37
-rw-r--r--bdb/test/scr002/chk.def64
-rw-r--r--bdb/test/scr003/chk.define77
-rw-r--r--bdb/test/scr004/chk.javafiles31
-rw-r--r--bdb/test/scr005/chk.nl112
-rw-r--r--bdb/test/scr006/chk.offt36
-rw-r--r--bdb/test/scr007/chk.proto45
-rw-r--r--bdb/test/scr008/chk.pubdef179
-rw-r--r--bdb/test/scr009/chk.srcfiles39
-rw-r--r--bdb/test/scr010/chk.str31
-rw-r--r--bdb/test/scr010/spell.ok825
-rw-r--r--bdb/test/scr011/chk.tags41
-rw-r--r--bdb/test/scr012/chk.vx_code68
-rw-r--r--bdb/test/scr013/chk.stats114
-rw-r--r--bdb/test/scr014/chk.err34
-rw-r--r--bdb/test/scr015/README36
-rw-r--r--bdb/test/scr015/TestConstruct01.cpp330
-rw-r--r--bdb/test/scr015/TestConstruct01.testerr4
-rw-r--r--bdb/test/scr015/TestConstruct01.testout27
-rw-r--r--bdb/test/scr015/TestExceptInclude.cpp27
-rw-r--r--bdb/test/scr015/TestGetSetMethods.cpp91
-rw-r--r--bdb/test/scr015/TestKeyRange.cpp171
-rw-r--r--bdb/test/scr015/TestKeyRange.testin8
-rw-r--r--bdb/test/scr015/TestKeyRange.testout19
-rw-r--r--bdb/test/scr015/TestLogc.cpp101
-rw-r--r--bdb/test/scr015/TestLogc.testout1
-rw-r--r--bdb/test/scr015/TestSimpleAccess.cpp67
-rw-r--r--bdb/test/scr015/TestSimpleAccess.testout3
-rw-r--r--bdb/test/scr015/TestTruncate.cpp84
-rw-r--r--bdb/test/scr015/TestTruncate.testout6
-rw-r--r--bdb/test/scr015/chk.cxxtests71
-rw-r--r--bdb/test/scr015/ignore4
-rw-r--r--bdb/test/scr015/testall32
-rw-r--r--bdb/test/scr015/testone122
-rw-r--r--bdb/test/scr016/CallbackTest.java83
-rw-r--r--bdb/test/scr016/CallbackTest.testout60
-rw-r--r--bdb/test/scr016/README37
-rw-r--r--bdb/test/scr016/TestAppendRecno.java258
-rw-r--r--bdb/test/scr016/TestAppendRecno.testout82
-rw-r--r--bdb/test/scr016/TestAssociate.java333
-rw-r--r--bdb/test/scr016/TestAssociate.testout30
-rw-r--r--bdb/test/scr016/TestClosedDb.java62
-rw-r--r--bdb/test/scr016/TestClosedDb.testout2
-rw-r--r--bdb/test/scr016/TestConstruct01.java474
-rw-r--r--bdb/test/scr016/TestConstruct01.testerr (renamed from mysql-test/t/README)0
-rw-r--r--bdb/test/scr016/TestConstruct01.testout3
-rw-r--r--bdb/test/scr016/TestConstruct02.java326
-rw-r--r--bdb/test/scr016/TestConstruct02.testout3
-rw-r--r--bdb/test/scr016/TestDbtFlags.java241
-rw-r--r--bdb/test/scr016/TestDbtFlags.testerr54
-rw-r--r--bdb/test/scr016/TestDbtFlags.testout78
-rw-r--r--bdb/test/scr016/TestGetSetMethods.java99
-rw-r--r--bdb/test/scr016/TestKeyRange.java203
-rw-r--r--bdb/test/scr016/TestKeyRange.testout27
-rw-r--r--bdb/test/scr016/TestLockVec.java249
-rw-r--r--bdb/test/scr016/TestLockVec.testout8
-rw-r--r--bdb/test/scr016/TestLogc.java100
-rw-r--r--bdb/test/scr016/TestLogc.testout1
-rw-r--r--bdb/test/scr016/TestOpenEmpty.java189
-rw-r--r--bdb/test/scr016/TestOpenEmpty.testerr2
-rw-r--r--bdb/test/scr016/TestReplication.java289
-rw-r--r--bdb/test/scr016/TestRpcServer.java193
-rw-r--r--bdb/test/scr016/TestSameDbt.java56
-rw-r--r--bdb/test/scr016/TestSameDbt.testout2
-rw-r--r--bdb/test/scr016/TestSimpleAccess.java37
-rw-r--r--bdb/test/scr016/TestSimpleAccess.testout3
-rw-r--r--bdb/test/scr016/TestStat.java57
-rw-r--r--bdb/test/scr016/TestStat.testout11
-rw-r--r--bdb/test/scr016/TestTruncate.java87
-rw-r--r--bdb/test/scr016/TestTruncate.testout6
-rw-r--r--bdb/test/scr016/TestUtil.java57
-rw-r--r--bdb/test/scr016/TestXAServlet.java313
-rw-r--r--bdb/test/scr016/chk.javatests79
-rw-r--r--bdb/test/scr016/ignore22
-rw-r--r--bdb/test/scr016/testall32
-rw-r--r--bdb/test/scr016/testone122
-rw-r--r--bdb/test/scr017/O.BH196
-rw-r--r--bdb/test/scr017/O.R196
-rw-r--r--bdb/test/scr017/chk.db18526
-rw-r--r--bdb/test/scr017/t.c188
-rw-r--r--bdb/test/scr018/chk.comma30
-rw-r--r--bdb/test/scr018/t.c46
-rw-r--r--bdb/test/scr019/chk.include40
-rw-r--r--bdb/test/scr020/chk.inc43
-rw-r--r--bdb/test/scr021/chk.flags97
-rw-r--r--bdb/test/scr022/chk.rr22
-rw-r--r--bdb/test/sdb001.tcl51
-rw-r--r--bdb/test/sdb002.tcl78
-rw-r--r--bdb/test/sdb003.tcl66
-rw-r--r--bdb/test/sdb004.tcl88
-rw-r--r--bdb/test/sdb005.tcl59
-rw-r--r--bdb/test/sdb006.tcl129
-rw-r--r--bdb/test/sdb007.tcl197
-rw-r--r--bdb/test/sdb008.tcl234
-rw-r--r--bdb/test/sdb009.tcl59
-rw-r--r--bdb/test/sdb010.tcl142
-rw-r--r--bdb/test/sdb011.tcl143
-rw-r--r--bdb/test/sdb012.tcl428
-rw-r--r--bdb/test/sdbscript.tcl4
-rw-r--r--bdb/test/sdbtest001.tcl43
-rw-r--r--bdb/test/sdbtest002.tcl41
-rw-r--r--bdb/test/sdbutils.tcl50
-rw-r--r--bdb/test/sec001.tcl205
-rw-r--r--bdb/test/sec002.tcl143
-rw-r--r--bdb/test/shelltest.tcl88
-rw-r--r--bdb/test/si001.tcl116
-rw-r--r--bdb/test/si002.tcl167
-rw-r--r--bdb/test/si003.tcl142
-rw-r--r--bdb/test/si004.tcl194
-rw-r--r--bdb/test/si005.tcl179
-rw-r--r--bdb/test/si006.tcl129
-rw-r--r--bdb/test/sindex.tcl259
-rw-r--r--bdb/test/sysscript.tcl9
-rw-r--r--bdb/test/test.tcl1418
-rw-r--r--bdb/test/test001.tcl148
-rw-r--r--bdb/test/test002.tcl61
-rw-r--r--bdb/test/test003.tcl63
-rw-r--r--bdb/test/test004.tcl71
-rw-r--r--bdb/test/test005.tcl17
-rw-r--r--bdb/test/test006.tcl64
-rw-r--r--bdb/test/test007.tcl16
-rw-r--r--bdb/test/test008.tcl80
-rw-r--r--bdb/test/test009.tcl21
-rw-r--r--bdb/test/test010.tcl78
-rw-r--r--bdb/test/test011.tcl159
-rw-r--r--bdb/test/test012.tcl48
-rw-r--r--bdb/test/test013.tcl76
-rw-r--r--bdb/test/test014.tcl77
-rw-r--r--bdb/test/test015.tcl61
-rw-r--r--bdb/test/test016.tcl71
-rw-r--r--bdb/test/test017.tcl123
-rw-r--r--bdb/test/test018.tcl11
-rw-r--r--bdb/test/test019.tcl62
-rw-r--r--bdb/test/test020.tcl43
-rw-r--r--bdb/test/test021.tcl54
-rw-r--r--bdb/test/test022.tcl13
-rw-r--r--bdb/test/test023.tcl35
-rw-r--r--bdb/test/test024.tcl80
-rw-r--r--bdb/test/test025.tcl63
-rw-r--r--bdb/test/test026.tcl67
-rw-r--r--bdb/test/test027.tcl14
-rw-r--r--bdb/test/test028.tcl34
-rw-r--r--bdb/test/test029.tcl85
-rw-r--r--bdb/test/test030.tcl58
-rw-r--r--bdb/test/test031.tcl72
-rw-r--r--bdb/test/test032.tcl82
-rw-r--r--bdb/test/test033.tcl167
-rw-r--r--bdb/test/test034.tcl9
-rw-r--r--bdb/test/test035.tcl10
-rw-r--r--bdb/test/test036.tcl62
-rw-r--r--bdb/test/test037.tcl27
-rw-r--r--bdb/test/test038.tcl105
-rw-r--r--bdb/test/test039.tcl100
-rw-r--r--bdb/test/test040.tcl9
-rw-r--r--bdb/test/test041.tcl9
-rw-r--r--bdb/test/test042.tcl134
-rw-r--r--bdb/test/test043.tcl42
-rw-r--r--bdb/test/test044.tcl55
-rw-r--r--bdb/test/test045.tcl32
-rw-r--r--bdb/test/test046.tcl194
-rw-r--r--bdb/test/test047.tcl114
-rw-r--r--bdb/test/test048.tcl71
-rw-r--r--bdb/test/test049.tcl46
-rw-r--r--bdb/test/test050.tcl60
-rw-r--r--bdb/test/test051.tcl88
-rw-r--r--bdb/test/test052.tcl48
-rw-r--r--bdb/test/test053.tcl59
-rw-r--r--bdb/test/test054.tcl182
-rw-r--r--bdb/test/test055.tcl55
-rw-r--r--bdb/test/test056.tcl40
-rw-r--r--bdb/test/test057.tcl53
-rw-r--r--bdb/test/test058.tcl14
-rw-r--r--bdb/test/test059.tcl46
-rw-r--r--bdb/test/test060.tcl17
-rw-r--r--bdb/test/test061.tcl39
-rw-r--r--bdb/test/test062.tcl66
-rw-r--r--bdb/test/test063.tcl61
-rw-r--r--bdb/test/test064.tcl21
-rw-r--r--bdb/test/test065.tcl155
-rw-r--r--bdb/test/test066.tcl38
-rw-r--r--bdb/test/test067.tcl91
-rw-r--r--bdb/test/test068.tcl65
-rw-r--r--bdb/test/test069.tcl12
-rw-r--r--bdb/test/test070.tcl44
-rw-r--r--bdb/test/test071.tcl9
-rw-r--r--bdb/test/test072.tcl137
-rw-r--r--bdb/test/test073.tcl77
-rw-r--r--bdb/test/test074.tcl76
-rw-r--r--bdb/test/test075.tcl360
-rw-r--r--bdb/test/test076.tcl49
-rw-r--r--bdb/test/test077.tcl37
-rw-r--r--bdb/test/test078.tcl64
-rw-r--r--bdb/test/test079.tcl14
-rw-r--r--bdb/test/test080.tcl123
-rw-r--r--bdb/test/test081.tcl11
-rw-r--r--bdb/test/test082.tcl13
-rw-r--r--bdb/test/test083.tcl54
-rw-r--r--bdb/test/test084.tcl17
-rw-r--r--bdb/test/test085.tcl122
-rw-r--r--bdb/test/test086.tcl20
-rw-r--r--bdb/test/test087.tcl82
-rw-r--r--bdb/test/test088.tcl74
-rw-r--r--bdb/test/test089.tcl180
-rw-r--r--bdb/test/test090.tcl16
-rw-r--r--bdb/test/test091.tcl9
-rw-r--r--bdb/test/test092.tcl241
-rw-r--r--bdb/test/test093.tcl393
-rw-r--r--bdb/test/test094.tcl251
-rw-r--r--bdb/test/test095.tcl296
-rw-r--r--bdb/test/test096.tcl202
-rw-r--r--bdb/test/test097.tcl188
-rw-r--r--bdb/test/test098.tcl91
-rw-r--r--bdb/test/test099.tcl177
-rw-r--r--bdb/test/test100.tcl17
-rw-r--r--bdb/test/test101.tcl17
-rw-r--r--bdb/test/testparams.tcl113
-rw-r--r--bdb/test/testutils.tcl1139
-rw-r--r--bdb/test/txn.tcl181
-rw-r--r--bdb/test/txn001.tcl116
-rw-r--r--bdb/test/txn002.tcl91
-rw-r--r--bdb/test/txn003.tcl238
-rw-r--r--bdb/test/txn004.tcl62
-rw-r--r--bdb/test/txn005.tcl75
-rw-r--r--bdb/test/txn006.tcl47
-rw-r--r--bdb/test/txn007.tcl57
-rw-r--r--bdb/test/txn008.tcl32
-rw-r--r--bdb/test/txn009.tcl32
-rw-r--r--bdb/test/txnscript.tcl67
-rw-r--r--bdb/test/update.tcl5
-rw-r--r--bdb/test/upgrade.tcl43
-rw-r--r--bdb/test/upgrade/README85
-rw-r--r--bdb/test/upgrade/generate-2.X/pack-2.6.6.pl114
-rw-r--r--bdb/test/upgrade/generate-2.X/test-2.6.patch379
-rw-r--r--bdb/test/wrap.tcl27
-rw-r--r--bdb/txn/txn.c1175
-rw-r--r--bdb/txn/txn.src69
-rw-r--r--bdb/txn/txn_method.c105
-rw-r--r--bdb/txn/txn_rec.c265
-rw-r--r--bdb/txn/txn_recover.c306
-rw-r--r--bdb/txn/txn_region.c371
-rw-r--r--bdb/txn/txn_stat.c102
-rw-r--r--bdb/txn/txn_util.c234
-rw-r--r--bdb/xa/xa.c184
-rw-r--r--bdb/xa/xa_db.c28
-rw-r--r--bdb/xa/xa_map.c30
-rw-r--r--client/Makefile.am5
-rw-r--r--client/client_priv.h4
-rw-r--r--client/completion_hash.cc6
-rw-r--r--client/completion_hash.h4
-rw-r--r--client/connect_test.c1
-rw-r--r--client/insert_test.c2
-rw-r--r--client/mysql.cc517
-rw-r--r--client/mysqladmin.c80
-rw-r--r--client/mysqlbinlog.cc176
-rw-r--r--client/mysqlcheck.c31
-rw-r--r--client/mysqldump.c226
-rw-r--r--client/mysqlimport.c32
-rw-r--r--client/mysqlshow.c32
-rw-r--r--client/mysqltest.c184
-rw-r--r--client/select_test.c1
-rw-r--r--client/sql_string.cc452
-rw-r--r--client/sql_string.h122
-rw-r--r--cmd-line-utils/Makefile.am6
-rw-r--r--cmd-line-utils/libedit/Makefile.am88
-rw-r--r--cmd-line-utils/libedit/TEST/test.c269
-rw-r--r--cmd-line-utils/libedit/chared.c690
-rw-r--r--cmd-line-utils/libedit/chared.h159
-rw-r--r--cmd-line-utils/libedit/common.c954
-rw-r--r--cmd-line-utils/libedit/compat.h43
-rw-r--r--cmd-line-utils/libedit/compat_conf.h2
-rw-r--r--cmd-line-utils/libedit/editline.3619
-rw-r--r--cmd-line-utils/libedit/editrc.5491
-rw-r--r--cmd-line-utils/libedit/el.c468
-rw-r--r--cmd-line-utils/libedit/el.h142
-rw-r--r--cmd-line-utils/libedit/emacs.c482
-rw-r--r--cmd-line-utils/libedit/fgetln.c109
-rw-r--r--cmd-line-utils/libedit/fgetln.h3
-rw-r--r--cmd-line-utils/libedit/hist.c192
-rw-r--r--cmd-line-utils/libedit/hist.h80
-rw-r--r--cmd-line-utils/libedit/histedit.h190
-rw-r--r--cmd-line-utils/libedit/history.c864
-rw-r--r--cmd-line-utils/libedit/key.c681
-rw-r--r--cmd-line-utils/libedit/key.h79
-rw-r--r--cmd-line-utils/libedit/makelist254
-rw-r--r--cmd-line-utils/libedit/map.c1412
-rw-r--r--cmd-line-utils/libedit/map.h79
-rw-r--r--cmd-line-utils/libedit/parse.c253
-rw-r--r--cmd-line-utils/libedit/parse.h52
-rw-r--r--cmd-line-utils/libedit/prompt.c168
-rw-r--r--cmd-line-utils/libedit/prompt.h62
-rw-r--r--cmd-line-utils/libedit/read.c514
-rw-r--r--cmd-line-utils/libedit/readline.c1661
-rw-r--r--cmd-line-utils/libedit/readline/readline.h127
-rw-r--r--cmd-line-utils/libedit/refresh.c1100
-rw-r--r--cmd-line-utils/libedit/refresh.h63
-rw-r--r--cmd-line-utils/libedit/search.c646
-rw-r--r--cmd-line-utils/libedit/search.h70
-rw-r--r--cmd-line-utils/libedit/sig.c192
-rw-r--r--cmd-line-utils/libedit/sig.h72
-rw-r--r--cmd-line-utils/libedit/strlcpy.c28
-rw-r--r--cmd-line-utils/libedit/strlcpy.h2
-rw-r--r--cmd-line-utils/libedit/sys.h94
-rw-r--r--cmd-line-utils/libedit/term.c1564
-rw-r--r--cmd-line-utils/libedit/term.h124
-rw-r--r--cmd-line-utils/libedit/tokenizer.c391
-rw-r--r--cmd-line-utils/libedit/tokenizer.h54
-rw-r--r--cmd-line-utils/libedit/tty.c1177
-rw-r--r--cmd-line-utils/libedit/tty.h484
-rw-r--r--cmd-line-utils/libedit/vi.c935
-rw-r--r--cmd-line-utils/readline/.cvsignore (renamed from readline/.cvsignore)0
-rw-r--r--cmd-line-utils/readline/COPYING339
-rw-r--r--cmd-line-utils/readline/INSTALL273
-rw-r--r--cmd-line-utils/readline/Makefile.am35
-rw-r--r--cmd-line-utils/readline/README172
-rw-r--r--cmd-line-utils/readline/ansi_stdlib.h54
-rw-r--r--cmd-line-utils/readline/bind.c2151
-rw-r--r--cmd-line-utils/readline/callback.c156
-rw-r--r--cmd-line-utils/readline/chardefs.h159
-rw-r--r--cmd-line-utils/readline/complete.c2004
-rw-r--r--cmd-line-utils/readline/configure.in206
-rw-r--r--cmd-line-utils/readline/display.c2198
-rw-r--r--cmd-line-utils/readline/emacs_keymap.c873
-rw-r--r--cmd-line-utils/readline/funmap.c253
-rw-r--r--cmd-line-utils/readline/histexpand.c1491
-rw-r--r--cmd-line-utils/readline/histfile.c479
-rw-r--r--cmd-line-utils/readline/histlib.h82
-rw-r--r--cmd-line-utils/readline/history.c381
-rw-r--r--cmd-line-utils/readline/history.h246
-rw-r--r--cmd-line-utils/readline/histsearch.c195
-rw-r--r--cmd-line-utils/readline/input.c540
-rw-r--r--cmd-line-utils/readline/isearch.c560
-rw-r--r--cmd-line-utils/readline/keymaps.c150
-rw-r--r--cmd-line-utils/readline/keymaps.h103
-rw-r--r--cmd-line-utils/readline/kill.c652
-rw-r--r--cmd-line-utils/readline/macro.c262
-rw-r--r--cmd-line-utils/readline/mbutil.c337
-rw-r--r--cmd-line-utils/readline/misc.c496
-rw-r--r--cmd-line-utils/readline/nls.c225
-rw-r--r--cmd-line-utils/readline/parens.c179
-rw-r--r--cmd-line-utils/readline/posixdir.h57
-rw-r--r--cmd-line-utils/readline/posixjmp.h40
-rw-r--r--cmd-line-utils/readline/posixstat.h142
-rw-r--r--cmd-line-utils/readline/readline.c973
-rw-r--r--cmd-line-utils/readline/readline.h799
-rw-r--r--cmd-line-utils/readline/rlconf.h60
-rw-r--r--cmd-line-utils/readline/rldefs.h160
-rw-r--r--cmd-line-utils/readline/rlmbutil.h108
-rw-r--r--cmd-line-utils/readline/rlprivate.h284
-rw-r--r--cmd-line-utils/readline/rlshell.h34
-rw-r--r--cmd-line-utils/readline/rlstdc.h45
-rw-r--r--cmd-line-utils/readline/rltty.c911
-rw-r--r--cmd-line-utils/readline/rltty.h82
-rw-r--r--cmd-line-utils/readline/rltypedefs.h88
-rw-r--r--cmd-line-utils/readline/rlwinsize.h57
-rw-r--r--cmd-line-utils/readline/search.c465
-rw-r--r--cmd-line-utils/readline/shell.c196
-rw-r--r--cmd-line-utils/readline/signals.c398
-rw-r--r--cmd-line-utils/readline/tcap.h60
-rw-r--r--cmd-line-utils/readline/terminal.c663
-rw-r--r--cmd-line-utils/readline/text.c1540
-rw-r--r--cmd-line-utils/readline/tilde.c458
-rw-r--r--cmd-line-utils/readline/tilde.h78
-rw-r--r--cmd-line-utils/readline/undo.c264
-rw-r--r--cmd-line-utils/readline/util.c338
-rw-r--r--cmd-line-utils/readline/vi_keymap.c877
-rw-r--r--cmd-line-utils/readline/vi_mode.c1485
-rw-r--r--cmd-line-utils/readline/xmalloc.c88
-rw-r--r--cmd-line-utils/readline/xmalloc.h46
-rw-r--r--configure.in466
-rw-r--r--dbug/Makefile.am2
-rw-r--r--extra/Makefile.am2
-rw-r--r--extra/mysql_install.c2
-rw-r--r--extra/replace.c2
-rw-r--r--extra/resolve_stack_dump.c13
-rw-r--r--extra/resolveip.c2
-rw-r--r--fs/Makefile.am7
-rw-r--r--heap/Makefile.am2
-rw-r--r--heap/_check.c66
-rw-r--r--heap/_rectest.c4
-rw-r--r--heap/heapdef.h76
-rw-r--r--heap/hp_block.c8
-rw-r--r--heap/hp_clear.c26
-rw-r--r--heap/hp_close.c8
-rw-r--r--heap/hp_create.c196
-rw-r--r--heap/hp_delete.c58
-rw-r--r--heap/hp_hash.c295
-rw-r--r--heap/hp_info.c2
-rw-r--r--heap/hp_open.c149
-rw-r--r--heap/hp_panic.c4
-rw-r--r--heap/hp_rename.c2
-rw-r--r--heap/hp_rfirst.c42
-rw-r--r--heap/hp_rkey.c55
-rw-r--r--heap/hp_rlast.c37
-rw-r--r--heap/hp_rnext.c53
-rw-r--r--heap/hp_rprev.c45
-rw-r--r--heap/hp_rrnd.c2
-rw-r--r--heap/hp_rsame.c4
-rw-r--r--heap/hp_scan.c2
-rw-r--r--heap/hp_test1.c20
-rw-r--r--heap/hp_test2.c48
-rw-r--r--heap/hp_update.c50
-rw-r--r--heap/hp_write.c91
-rw-r--r--include/Makefile.am16
-rw-r--r--include/config-win.h19
-rw-r--r--include/errmsg.h24
-rw-r--r--include/ft_global.h2
-rw-r--r--include/hash.h12
-rw-r--r--include/heap.h60
-rw-r--r--include/m_ctype.h372
-rw-r--r--include/m_string.h9
-rw-r--r--include/my_base.h27
-rw-r--r--include/my_global.h5
-rw-r--r--include/my_handler.h66
-rw-r--r--include/my_list.h4
-rw-r--r--include/my_pthread.h5
-rw-r--r--include/my_sys.h55
-rw-r--r--include/my_tree.h29
-rw-r--r--include/my_xml.h61
-rw-r--r--include/myisam.h61
-rw-r--r--include/myisammrg.h1
-rw-r--r--include/myisampack.h2
-rw-r--r--include/mysql.h255
-rw-r--r--include/mysql_com.h167
-rw-r--r--include/mysqld_error.h17
-rw-r--r--include/thr_lock.h4
-rw-r--r--include/typelib.h33
-rw-r--r--include/violite.h35
-rw-r--r--innobase/btr/btr0cur.c7
-rw-r--r--innobase/btr/btr0pcur.c43
-rw-r--r--innobase/buf/buf0buf.c345
-rw-r--r--innobase/buf/buf0flu.c46
-rw-r--r--innobase/buf/buf0lru.c62
-rw-r--r--innobase/buf/buf0rea.c2
-rw-r--r--innobase/dict/dict0dict.c3
-rw-r--r--innobase/dict/dict0load.c4
-rw-r--r--innobase/include/btr0pcur.h3
-rw-r--r--innobase/include/buf0buf.h128
-rw-r--r--innobase/include/buf0buf.ic119
-rw-r--r--innobase/include/buf0lru.h4
-rw-r--r--innobase/include/log0recv.h7
-rw-r--r--innobase/include/mem0pool.h2
-rw-r--r--innobase/include/os0proc.h70
-rw-r--r--innobase/include/row0mysql.h8
-rw-r--r--innobase/include/row0sel.h3
-rw-r--r--innobase/include/srv0srv.h3
-rw-r--r--innobase/include/ut0mem.h10
-rw-r--r--innobase/lock/lock0lock.c3
-rw-r--r--innobase/log/log0log.c4
-rw-r--r--innobase/log/log0recv.c24
-rw-r--r--innobase/os/os0file.c2
-rw-r--r--innobase/os/os0proc.c462
-rw-r--r--innobase/row/row0mysql.c13
-rw-r--r--innobase/row/row0sel.c37
-rw-r--r--innobase/srv/srv0srv.c44
-rw-r--r--innobase/srv/srv0start.c41
-rw-r--r--innobase/trx/trx0sys.c6
-rw-r--r--innobase/trx/trx0trx.c2
-rw-r--r--innobase/ut/ut0mem.c37
-rw-r--r--innobase/ut/ut0ut.c2
-rw-r--r--isam/Makefile.am2
-rw-r--r--isam/_key.c18
-rw-r--r--isam/_search.c26
-rw-r--r--isam/isamlog.c6
-rw-r--r--isam/pack_isam.c25
-rw-r--r--isam/static.c2
-rw-r--r--libmysql/Makefile.am7
-rw-r--r--libmysql/Makefile.shared29
-rw-r--r--libmysql/errmsg.c66
-rw-r--r--libmysql/libmysql.c2849
-rw-r--r--libmysql/libmysql.def27
-rw-r--r--libmysql/manager.c2
-rwxr-xr-x[-rw-r--r--]libmysql/password.c191
-rw-r--r--libmysql_r/Makefile.am3
-rw-r--r--libmysqld/Makefile.am20
-rw-r--r--libmysqld/embedded_priv.h8
-rw-r--r--libmysqld/examples/Makefile.am2
-rw-r--r--libmysqld/examples/builder-sample/emb_sample.tdsbin2293760 -> 0 bytes
-rw-r--r--libmysqld/examples/builder-sample/libmysqld.libbin7168 -> 0 bytes
-rw-r--r--libmysqld/lib_sql.cc644
-rw-r--r--libmysqld/lib_vio.c30
-rw-r--r--libmysqld/libmysqld.c1067
-rw-r--r--merge/Makefile.am2
-rw-r--r--myisam/.cvsignore2
-rw-r--r--myisam/Makefile.am13
-rw-r--r--myisam/ft_boolean_search.c230
-rw-r--r--myisam/ft_dump.c30
-rw-r--r--myisam/ft_eval.h2
-rw-r--r--myisam/ft_nlq_search.c89
-rw-r--r--myisam/ft_parser.c54
-rw-r--r--myisam/ft_static.c22
-rw-r--r--myisam/ft_stopwords.c14
-rw-r--r--myisam/ft_test1.c2
-rw-r--r--myisam/ft_update.c16
-rw-r--r--myisam/ftdefs.h15
-rw-r--r--myisam/fulltext.h13
-rw-r--r--myisam/mi_check.c236
-rw-r--r--myisam/mi_create.c84
-rw-r--r--myisam/mi_dbug.c2
-rw-r--r--myisam/mi_delete.c106
-rw-r--r--myisam/mi_key.c17
-rw-r--r--myisam/mi_open.c103
-rw-r--r--myisam/mi_range.c36
-rw-r--r--myisam/mi_rkey.c53
-rw-r--r--myisam/mi_rnext.c62
-rw-r--r--myisam/mi_rnext_same.c42
-rw-r--r--myisam/mi_rrnd.c5
-rw-r--r--myisam/mi_search.c434
-rw-r--r--myisam/mi_static.c5
-rw-r--r--myisam/mi_test1.c11
-rw-r--r--myisam/mi_test2.c10
-rw-r--r--myisam/mi_test3.c4
-rw-r--r--myisam/mi_unique.c16
-rw-r--r--myisam/mi_update.c9
-rw-r--r--myisam/mi_write.c100
-rw-r--r--myisam/myisamchk.c31
-rw-r--r--myisam/myisamdef.h94
-rw-r--r--myisam/myisamlog.c7
-rw-r--r--myisam/myisampack.c9
-rw-r--r--myisam/rt_index.c914
-rw-r--r--myisam/rt_index.h44
-rw-r--r--myisam/rt_key.c151
-rw-r--r--myisam/rt_key.h31
-rw-r--r--myisam/rt_mbr.c759
-rw-r--r--myisam/rt_mbr.h33
-rw-r--r--myisam/rt_split.c343
-rw-r--r--myisam/rt_test.c421
-rw-r--r--myisam/sort.c218
-rw-r--r--myisam/sp_defs.h45
-rw-r--r--myisam/sp_key.c261
-rw-r--r--myisam/sp_test.c576
-rw-r--r--myisammrg/Makefile.am5
-rw-r--r--myisammrg/myrg_queue.c2
-rw-r--r--myisammrg/myrg_rkey.c4
-rw-r--r--myisammrg/myrg_rnext_same.c40
-rw-r--r--mysql-test/Makefile.am2
-rw-r--r--mysql-test/README7
-rwxr-xr-xmysql-test/create-test-result5
-rw-r--r--mysql-test/include/master-slave.inc8
-rw-r--r--mysql-test/install_test_db.sh45
-rw-r--r--mysql-test/mysql-test-run.sh40
-rw-r--r--mysql-test/r/alter_table.result14
-rw-r--r--mysql-test/r/analyse.result7
-rw-r--r--mysql-test/r/backup.result2
-rw-r--r--mysql-test/r/bdb.result25
-rw-r--r--mysql-test/r/bdb_cache.result1
-rw-r--r--mysql-test/r/bigint.result2
-rw-r--r--mysql-test/r/bool.result11
-rw-r--r--mysql-test/r/case.result4
-rw-r--r--mysql-test/r/cast.result4
-rw-r--r--mysql-test/r/compare.result4
-rw-r--r--mysql-test/r/connect.result43
-rw-r--r--mysql-test/r/create.result147
-rw-r--r--mysql-test/r/ctype_many.result1399
-rw-r--r--mysql-test/r/delayed.result6
-rw-r--r--mysql-test/r/delete.result8
-rw-r--r--mysql-test/r/derived.result148
-rw-r--r--mysql-test/r/distinct.result67
-rw-r--r--mysql-test/r/drop.result5
-rw-r--r--mysql-test/r/explain.result36
-rw-r--r--mysql-test/r/flush.result5
-rw-r--r--mysql-test/r/fulltext.result5
-rw-r--r--mysql-test/r/fulltext2.result871
-rw-r--r--mysql-test/r/fulltext_multi.result1
-rw-r--r--mysql-test/r/fulltext_order_by.result1
-rw-r--r--mysql-test/r/func_crypt.result18
-rw-r--r--mysql-test/r/func_date_add.result20
-rw-r--r--mysql-test/r/func_equal.result2
-rw-r--r--mysql-test/r/func_group.result48
-rw-r--r--mysql-test/r/func_in.result87
-rw-r--r--mysql-test/r/func_set.result17
-rw-r--r--mysql-test/r/func_str.result23
-rw-r--r--mysql-test/r/func_system.result3
-rw-r--r--mysql-test/r/func_test.result3
-rw-r--r--mysql-test/r/func_time.result64
-rw-r--r--mysql-test/r/gcc296.result16
-rw-r--r--mysql-test/r/group_by.result53
-rw-r--r--mysql-test/r/handler.result2
-rw-r--r--mysql-test/r/having.result4
-rw-r--r--mysql-test/r/heap.result32
-rw-r--r--mysql-test/r/heap_auto_increment.result41
-rw-r--r--mysql-test/r/heap_btree.result235
-rw-r--r--mysql-test/r/heap_hash.result205
-rw-r--r--mysql-test/r/help.result123
-rw-r--r--mysql-test/r/innodb-deadlock.result78
-rw-r--r--mysql-test/r/innodb.result87
-rw-r--r--mysql-test/r/innodb_cache.result2
-rw-r--r--mysql-test/r/innodb_handler.result2
-rw-r--r--mysql-test/r/insert.result10
-rw-r--r--mysql-test/r/insert_select.result17
-rw-r--r--mysql-test/r/insert_update.result51
-rw-r--r--mysql-test/r/isam.result18
-rw-r--r--mysql-test/r/join.result10
-rw-r--r--mysql-test/r/join_outer.result47
-rw-r--r--mysql-test/r/key.result1
-rw-r--r--mysql-test/r/key_diff.result6
-rw-r--r--mysql-test/r/key_primary.result8
-rw-r--r--mysql-test/r/keywords.result2
-rw-r--r--mysql-test/r/merge.result62
-rw-r--r--mysql-test/r/multi_update.result22
-rw-r--r--mysql-test/r/myisam.result87
-rw-r--r--mysql-test/r/null.result2
-rw-r--r--mysql-test/r/null_key.result107
-rw-r--r--mysql-test/r/odbc.result6
-rw-r--r--mysql-test/r/olap.result18
-rw-r--r--mysql-test/r/order_by.result137
-rw-r--r--mysql-test/r/query_cache.result2
-rw-r--r--mysql-test/r/range.result6
-rw-r--r--mysql-test/r/rename.result2
-rw-r--r--mysql-test/r/replace.result6
-rw-r--r--mysql-test/r/rollback.result19
-rw-r--r--mysql-test/r/row.result161
-rw-r--r--mysql-test/r/rpl000001.result15
-rw-r--r--mysql-test/r/rpl000002.result10
-rw-r--r--mysql-test/r/rpl000003.result17
-rw-r--r--mysql-test/r/rpl000004.result9
-rw-r--r--mysql-test/r/rpl000005.result5
-rw-r--r--mysql-test/r/rpl000006.result6
-rw-r--r--mysql-test/r/rpl000008.result32
-rw-r--r--mysql-test/r/rpl000009.result114
-rw-r--r--mysql-test/r/rpl000010.result6
-rw-r--r--mysql-test/r/rpl000011.result9
-rw-r--r--mysql-test/r/rpl000012.result14
-rw-r--r--mysql-test/r/rpl000013.result7
-rw-r--r--mysql-test/r/rpl000015.result10
-rw-r--r--mysql-test/r/rpl000017.result2
-rw-r--r--mysql-test/r/rpl000018.result8
-rw-r--r--mysql-test/r/rpl_alter.result26
-rw-r--r--mysql-test/r/rpl_empty_master_crash.result5
-rw-r--r--mysql-test/r/rpl_failsafe.result8
-rw-r--r--mysql-test/r/rpl_flush_log_loop.result12
-rw-r--r--mysql-test/r/rpl_get_lock.result4
-rw-r--r--mysql-test/r/rpl_insert_id.result5
-rw-r--r--mysql-test/r/rpl_loaddata.result4
-rw-r--r--mysql-test/r/rpl_log.result112
-rw-r--r--mysql-test/r/rpl_log_pos.result32
-rw-r--r--mysql-test/r/rpl_master_pos_wait.result4
-rw-r--r--mysql-test/r/rpl_mystery22.result10
-rw-r--r--mysql-test/r/rpl_redirect.result5
-rw-r--r--mysql-test/r/rpl_replicate_do.result6
-rw-r--r--mysql-test/r/rpl_rotate_logs.result42
-rw-r--r--mysql-test/r/rpl_skip_error.result5
-rw-r--r--mysql-test/r/rpl_sporadic_master.result8
-rw-r--r--mysql-test/r/rpl_temporary.result73
-rw-r--r--mysql-test/r/rpl_user_variables.result78
-rw-r--r--mysql-test/r/sel000001.result7
-rw-r--r--mysql-test/r/sel000002.result9
-rw-r--r--mysql-test/r/sel000003.result8
-rw-r--r--mysql-test/r/sel000031.result12
-rw-r--r--mysql-test/r/sel000032.result12
-rw-r--r--mysql-test/r/select.result153
-rw-r--r--mysql-test/r/select_found.result20
-rw-r--r--mysql-test/r/show_check.result75
-rw-r--r--mysql-test/r/sql_mode.result87
-rw-r--r--mysql-test/r/subselect.result1014
-rw-r--r--mysql-test/r/symlink.result8
-rw-r--r--mysql-test/r/temp_table.result2
-rw-r--r--mysql-test/r/type_blob.result52
-rw-r--r--mysql-test/r/type_date.result2
-rw-r--r--mysql-test/r/type_datetime.result8
-rw-r--r--mysql-test/r/type_enum.result4
-rw-r--r--mysql-test/r/type_float.result34
-rw-r--r--mysql-test/r/type_ranges.result172
-rw-r--r--mysql-test/r/type_set.result4
-rw-r--r--mysql-test/r/type_timestamp.result50
-rw-r--r--mysql-test/r/union.result47
-rw-r--r--mysql-test/r/update.result7
-rw-r--r--mysql-test/r/user_var.result18
-rw-r--r--mysql-test/r/varbinary.result6
-rw-r--r--mysql-test/r/variables.result3
-rw-r--r--mysql-test/r/warnings.result22
-rw-r--r--mysql-test/std_data/master-bin.000001 (renamed from mysql-test/std_data/master-bin.001)bin98 -> 98 bytes
-rw-r--r--mysql-test/t/alias.test3
-rw-r--r--mysql-test/t/alter_table.test4
-rw-r--r--mysql-test/t/analyse.test5
-rw-r--r--mysql-test/t/auto_increment.test4
-rw-r--r--mysql-test/t/backup.test4
-rw-r--r--mysql-test/t/bdb-alter-table-1.test3
-rw-r--r--mysql-test/t/bdb-crash.test2
-rw-r--r--mysql-test/t/bdb-deadlock.test13
-rw-r--r--mysql-test/t/bdb.test11
-rw-r--r--mysql-test/t/bdb_cache.test5
-rw-r--r--mysql-test/t/bench_count_distinct.test6
-rw-r--r--mysql-test/t/bigint.test8
-rw-r--r--mysql-test/t/binary.test4
-rw-r--r--mysql-test/t/bool.test14
-rw-r--r--mysql-test/t/bulk_replace.test5
-rw-r--r--mysql-test/t/case.test2
-rw-r--r--mysql-test/t/check.test5
-rw-r--r--mysql-test/t/compare.test3
-rw-r--r--mysql-test/t/connect.test64
-rw-r--r--mysql-test/t/constraints.test2
-rw-r--r--mysql-test/t/count_distinct.test3
-rw-r--r--mysql-test/t/count_distinct2.test2
-rw-r--r--mysql-test/t/create.test73
-rw-r--r--mysql-test/t/ctype_latin1_de.test2
-rw-r--r--mysql-test/t/ctype_many.test197
-rw-r--r--mysql-test/t/delayed.test2
-rw-r--r--mysql-test/t/delete.test11
-rw-r--r--mysql-test/t/derived.test64
-rw-r--r--mysql-test/t/dirty_close.test4
-rw-r--r--mysql-test/t/distinct.test8
-rw-r--r--mysql-test/t/drop.test5
-rw-r--r--mysql-test/t/empty_table.test3
-rw-r--r--mysql-test/t/err000001.test32
-rw-r--r--mysql-test/t/explain.test2
-rw-r--r--mysql-test/t/flush.test9
-rw-r--r--mysql-test/t/foreign_key.test3
-rw-r--r--mysql-test/t/fulltext.test4
-rw-r--r--mysql-test/t/fulltext2.test96
-rw-r--r--mysql-test/t/fulltext_cache.test3
-rw-r--r--mysql-test/t/fulltext_distinct.test3
-rw-r--r--mysql-test/t/fulltext_left_join.test3
-rw-r--r--mysql-test/t/fulltext_multi.test4
-rw-r--r--mysql-test/t/fulltext_order_by.test4
-rw-r--r--mysql-test/t/fulltext_update.test2
-rw-r--r--mysql-test/t/func_concat.test3
-rw-r--r--mysql-test/t/func_crypt.test8
-rw-r--r--mysql-test/t/func_date_add.test3
-rw-r--r--mysql-test/t/func_encrypt.test3
-rw-r--r--mysql-test/t/func_equal.test6
-rw-r--r--mysql-test/t/func_group.test13
-rw-r--r--mysql-test/t/func_if.test2
-rw-r--r--mysql-test/t/func_in.test38
-rw-r--r--mysql-test/t/func_isnull.test3
-rw-r--r--mysql-test/t/func_like.test3
-rw-r--r--mysql-test/t/func_regexp.test3
-rw-r--r--mysql-test/t/func_set.test18
-rw-r--r--mysql-test/t/func_str.test11
-rw-r--r--mysql-test/t/func_system.test1
-rw-r--r--mysql-test/t/func_test.test1
-rw-r--r--mysql-test/t/func_time.test33
-rw-r--r--mysql-test/t/func_timestamp.test3
-rw-r--r--mysql-test/t/gcc296.test19
-rw-r--r--mysql-test/t/grant_cache.test5
-rw-r--r--mysql-test/t/group_by.test15
-rw-r--r--mysql-test/t/handler.test5
-rw-r--r--mysql-test/t/having.test4
-rw-r--r--mysql-test/t/heap.test5
-rw-r--r--mysql-test/t/heap_auto_increment.test33
-rw-r--r--mysql-test/t/heap_btree.test158
-rw-r--r--mysql-test/t/heap_hash.test143
-rw-r--r--mysql-test/t/help.test50
-rw-r--r--mysql-test/t/innodb-deadlock.test77
-rw-r--r--mysql-test/t/innodb.test4
-rw-r--r--mysql-test/t/innodb_cache.test6
-rw-r--r--mysql-test/t/innodb_handler.test5
-rw-r--r--mysql-test/t/ins000001.test3
-rw-r--r--mysql-test/t/insert.test15
-rw-r--r--mysql-test/t/insert_select.test21
-rw-r--r--mysql-test/t/insert_update.test24
-rw-r--r--mysql-test/t/isam.test14
-rw-r--r--mysql-test/t/join.test3
-rw-r--r--mysql-test/t/join_crash.test3
-rw-r--r--mysql-test/t/join_outer.test3
-rw-r--r--mysql-test/t/key.test4
-rw-r--r--mysql-test/t/key_diff.test3
-rw-r--r--mysql-test/t/key_primary.test3
-rw-r--r--mysql-test/t/keywords.test3
-rw-r--r--mysql-test/t/kill.test3
-rw-r--r--mysql-test/t/limit.test3
-rw-r--r--mysql-test/t/lock.test2
-rw-r--r--mysql-test/t/lock_multi.test5
-rw-r--r--mysql-test/t/lowercase_table.test3
-rw-r--r--mysql-test/t/merge.test20
-rw-r--r--mysql-test/t/multi_update.test18
-rw-r--r--mysql-test/t/myisam.test19
-rw-r--r--mysql-test/t/null.test6
-rw-r--r--mysql-test/t/null_key.test6
-rw-r--r--mysql-test/t/odbc.test6
-rw-r--r--mysql-test/t/olap.test22
-rw-r--r--mysql-test/t/order_by.test24
-rw-r--r--mysql-test/t/order_fill_sortbuf.test3
-rw-r--r--mysql-test/t/outfile.test5
-rw-r--r--mysql-test/t/query_cache.test4
-rw-r--r--mysql-test/t/raid.test3
-rw-r--r--mysql-test/t/range.test3
-rw-r--r--mysql-test/t/rename.test5
-rw-r--r--mysql-test/t/repair.test3
-rw-r--r--mysql-test/t/replace.test7
-rw-r--r--mysql-test/t/rollback.test11
-rw-r--r--mysql-test/t/row.test81
-rw-r--r--mysql-test/t/rpl000001.test12
-rw-r--r--mysql-test/t/rpl000002.test19
-rw-r--r--mysql-test/t/rpl000003.test14
-rw-r--r--mysql-test/t/rpl000004.test6
-rw-r--r--mysql-test/t/rpl000005.test2
-rw-r--r--mysql-test/t/rpl000006.test2
-rw-r--r--mysql-test/t/rpl000008-slave.opt2
-rw-r--r--mysql-test/t/rpl000008.test41
-rw-r--r--mysql-test/t/rpl000009-slave.opt2
-rw-r--r--mysql-test/t/rpl000009.test81
-rw-r--r--mysql-test/t/rpl000010.test10
-rw-r--r--mysql-test/t/rpl000011.test18
-rw-r--r--mysql-test/t/rpl000012.test8
-rw-r--r--mysql-test/t/rpl000013.test6
-rw-r--r--mysql-test/t/rpl000015.test12
-rw-r--r--mysql-test/t/rpl000016-slave.opt1
-rwxr-xr-xmysql-test/t/rpl000017-slave.sh4
-rw-r--r--mysql-test/t/rpl000017.test12
-rw-r--r--mysql-test/t/rpl000018.test14
-rw-r--r--mysql-test/t/rpl_alter.test25
-rw-r--r--mysql-test/t/rpl_empty_master_crash.test3
-rw-r--r--mysql-test/t/rpl_failsafe.test8
-rw-r--r--mysql-test/t/rpl_flush_log_loop.test6
-rw-r--r--mysql-test/t/rpl_insert_id.test6
-rw-r--r--mysql-test/t/rpl_log.test30
-rw-r--r--mysql-test/t/rpl_log_pos.test25
-rw-r--r--mysql-test/t/rpl_mystery22.test14
-rw-r--r--mysql-test/t/rpl_redirect.test1
-rw-r--r--mysql-test/t/rpl_replicate_do.test5
-rw-r--r--mysql-test/t/rpl_rotate_logs.test51
-rw-r--r--mysql-test/t/rpl_skip_error.test1
-rw-r--r--mysql-test/t/rpl_sporadic_master.test16
-rw-r--r--mysql-test/t/rpl_temporary.test82
-rw-r--r--mysql-test/t/rpl_user_variables.test39
-rw-r--r--mysql-test/t/sel000001.test18
-rw-r--r--mysql-test/t/sel000002.test17
-rw-r--r--mysql-test/t/sel000003.test18
-rw-r--r--mysql-test/t/sel000031.test20
-rw-r--r--mysql-test/t/sel000032.test20
-rw-r--r--mysql-test/t/sel000033.test2
-rw-r--r--mysql-test/t/sel000100.test2
-rw-r--r--mysql-test/t/select.test18
-rw-r--r--mysql-test/t/select_found.test12
-rw-r--r--mysql-test/t/select_safe.test3
-rw-r--r--mysql-test/t/show_check.test8
-rw-r--r--mysql-test/t/sql_mode.test30
-rw-r--r--mysql-test/t/status.test3
-rw-r--r--mysql-test/t/subselect.test597
-rw-r--r--mysql-test/t/symlink.test6
-rw-r--r--mysql-test/t/tablelock.test3
-rw-r--r--mysql-test/t/temp_table.test6
-rw-r--r--mysql-test/t/truncate.test3
-rw-r--r--mysql-test/t/type_blob.test35
-rw-r--r--mysql-test/t/type_date.test5
-rw-r--r--mysql-test/t/type_datetime.test5
-rw-r--r--mysql-test/t/type_decimal.test3
-rw-r--r--mysql-test/t/type_enum.test3
-rw-r--r--mysql-test/t/type_float.test11
-rw-r--r--mysql-test/t/type_ranges.test4
-rw-r--r--mysql-test/t/type_set.test3
-rw-r--r--mysql-test/t/type_time.test4
-rw-r--r--mysql-test/t/type_timestamp.test5
-rw-r--r--mysql-test/t/type_uint.test3
-rw-r--r--mysql-test/t/type_year.test3
-rw-r--r--mysql-test/t/union.test13
-rw-r--r--mysql-test/t/update.test10
-rw-r--r--mysql-test/t/user_var.test8
-rw-r--r--mysql-test/t/varbinary.test6
-rw-r--r--mysql-test/t/variables.test6
-rw-r--r--mysql-test/t/warnings.test15
-rw-r--r--mysys/Makefile.am20
-rw-r--r--mysys/charset.c759
-rw-r--r--mysys/charset2html.c129
-rw-r--r--mysys/default.c10
-rw-r--r--mysys/hash.c55
-rw-r--r--mysys/list.c2
-rw-r--r--mysys/mf_casecnv.c297
-rw-r--r--mysys/mf_dirname.c6
-rw-r--r--mysys/mf_format.c6
-rw-r--r--mysys/mf_iocache2.c2
-rw-r--r--mysys/mf_keycache.c2229
-rw-r--r--mysys/mf_soundex.c21
-rw-r--r--mysys/mf_tempdir.c83
-rw-r--r--mysys/mf_wfile.c7
-rw-r--r--mysys/mulalloc.c14
-rw-r--r--mysys/my_error.c4
-rw-r--r--mysys/my_getwd.c3
-rw-r--r--mysys/my_handler.c411
-rw-r--r--mysys/my_init.c5
-rw-r--r--mysys/my_once.c20
-rw-r--r--mysys/my_symlink.c3
-rw-r--r--mysys/my_vsnprintf.c118
-rw-r--r--mysys/queues.c72
-rw-r--r--mysys/test_charset.c41
-rw-r--r--mysys/test_xml.c105
-rw-r--r--mysys/thr_lock.c8
-rw-r--r--mysys/tree.c228
-rw-r--r--mysys/typelib.c4
-rw-r--r--pstack/Makefile.am2
-rw-r--r--readline/COPYING339
-rw-r--r--readline/INSTALL176
-rw-r--r--readline/Makefile.am32
-rw-r--r--readline/README163
-rw-r--r--readline/ansi_stdlib.h41
-rw-r--r--readline/bind.c1991
-rw-r--r--readline/callback.c150
-rw-r--r--readline/chardefs.h142
-rw-r--r--readline/complete.c1748
-rwxr-xr-xreadline/configure2849
-rw-r--r--readline/configure.in143
-rw-r--r--readline/display.c1573
-rw-r--r--readline/emacs_keymap.c885
-rw-r--r--readline/funmap.c252
-rw-r--r--readline/histexpand.c1360
-rw-r--r--readline/histfile.c376
-rw-r--r--readline/histlib.h82
-rw-r--r--readline/history.c388
-rw-r--r--readline/history.h248
-rw-r--r--readline/histsearch.c200
-rw-r--r--readline/input.c557
-rw-r--r--readline/isearch.c449
-rw-r--r--readline/keymaps.c150
-rw-r--r--readline/keymaps.h100
-rw-r--r--readline/kill.c637
-rw-r--r--readline/macro.c274
-rw-r--r--readline/nls.c228
-rw-r--r--readline/parens.c156
-rw-r--r--readline/posixdir.h49
-rw-r--r--readline/posixjmp.h22
-rw-r--r--readline/posixstat.h142
-rw-r--r--readline/readline.c2155
-rw-r--r--readline/readline.h621
-rw-r--r--readline/rlconf.h61
-rw-r--r--readline/rldefs.h135
-rw-r--r--readline/rlstdc.h83
-rw-r--r--readline/rltty.c737
-rw-r--r--readline/rltty.h63
-rw-r--r--readline/rlwinsize.h58
-rw-r--r--readline/search.c373
-rw-r--r--readline/shell.c138
-rw-r--r--readline/signals.c394
-rw-r--r--readline/tcap.h60
-rw-r--r--readline/terminal.c558
-rw-r--r--readline/tilde.c438
-rw-r--r--readline/tilde.h65
-rw-r--r--readline/undo.c259
-rw-r--r--readline/util.c365
-rw-r--r--readline/vi_keymap.c877
-rw-r--r--readline/vi_mode.c1389
-rw-r--r--readline/xmalloc.c87
-rw-r--r--regex/Makefile.am2
-rw-r--r--regex/debug.c22
-rw-r--r--regex/debug.ih4
-rw-r--r--regex/engine.c97
-rw-r--r--regex/engine.ih10
-rw-r--r--regex/main.c4
-rw-r--r--regex/regcomp.c44
-rw-r--r--regex/regcomp.ih2
-rw-r--r--regex/regex.h7
-rw-r--r--regex/regex2.h2
-rw-r--r--regex/regexec.c4
-rw-r--r--regex/reginit.c24
-rw-r--r--scripts/Makefile.am23
-rw-r--r--scripts/fill_help_tables.sh239
-rw-r--r--scripts/mysql_fix_privilege_tables.sh9
-rw-r--r--scripts/mysql_install_db.sh9
-rw-r--r--sql-bench/test-insert.sh51
-rw-r--r--sql/Makefile.am24
-rw-r--r--sql/convert.cc7
-rw-r--r--sql/des_key_file.cc7
-rw-r--r--sql/field.cc1740
-rw-r--r--sql/field.h373
-rw-r--r--sql/field_conv.cc21
-rw-r--r--sql/filesort.cc146
-rw-r--r--sql/gen_lex_hash.cc774
-rw-r--r--sql/gstream.cc139
-rw-r--r--sql/gstream.h69
-rw-r--r--sql/ha_berkeley.cc97
-rw-r--r--sql/ha_berkeley.h2
-rw-r--r--sql/ha_heap.cc230
-rw-r--r--sql/ha_heap.h6
-rw-r--r--sql/ha_innodb.cc137
-rw-r--r--sql/ha_innodb.h3
-rw-r--r--sql/ha_myisam.cc62
-rw-r--r--sql/ha_myisam.h2
-rw-r--r--sql/ha_myisammrg.cc10
-rw-r--r--sql/ha_myisammrg.h9
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/handler.h20
-rw-r--r--sql/hash_filo.h4
-rw-r--r--sql/hostname.cc4
-rw-r--r--sql/init.cc11
-rw-r--r--sql/item.cc999
-rw-r--r--sql/item.h532
-rw-r--r--sql/item_buff.cc4
-rw-r--r--sql/item_cmpfunc.cc857
-rw-r--r--sql/item_cmpfunc.h525
-rw-r--r--sql/item_create.cc195
-rw-r--r--sql/item_create.h41
-rw-r--r--sql/item_func.cc545
-rw-r--r--sql/item_func.h286
-rw-r--r--sql/item_row.cc131
-rw-r--r--sql/item_row.h79
-rw-r--r--sql/item_strfunc.cc871
-rw-r--r--sql/item_strfunc.h359
-rw-r--r--sql/item_subselect.cc860
-rw-r--r--sql/item_subselect.h267
-rw-r--r--sql/item_sum.cc282
-rw-r--r--sql/item_sum.h203
-rw-r--r--sql/item_timefunc.cc267
-rw-r--r--sql/item_timefunc.h274
-rw-r--r--sql/item_uniq.h15
-rw-r--r--sql/key.cc6
-rw-r--r--sql/lex.h84
-rw-r--r--sql/lock.cc12
-rw-r--r--sql/log.cc94
-rw-r--r--sql/log_event.cc2973
-rw-r--r--sql/log_event.h227
-rw-r--r--sql/mf_iocache.cc5
-rw-r--r--sql/mini_client.cc137
-rw-r--r--sql/mysql_priv.h271
-rw-r--r--sql/mysqld.cc1118
-rw-r--r--sql/net_pkg.cc402
-rw-r--r--sql/net_serv.cc113
-rw-r--r--sql/nt_servc.cc32
-rw-r--r--sql/opt_range.cc262
-rw-r--r--sql/opt_range.h9
-rw-r--r--sql/opt_sum.cc3
-rw-r--r--sql/password.c569
-rw-r--r--sql/procedure.cc3
-rw-r--r--sql/procedure.h44
-rw-r--r--sql/protocol.cc1085
-rw-r--r--sql/protocol.h144
-rw-r--r--sql/repl_failsafe.cc93
-rw-r--r--sql/repl_failsafe.h2
-rw-r--r--sql/set_var.cc194
-rw-r--r--sql/set_var.h55
-rw-r--r--sql/share/Makefile.am5
-rw-r--r--sql/share/charsets/Index38
-rw-r--r--sql/share/charsets/Index.xml460
-rw-r--r--sql/share/charsets/MacCE.xml209
-rw-r--r--sql/share/charsets/MacRoman.xml201
-rw-r--r--sql/share/charsets/armscii8.xml119
-rw-r--r--sql/share/charsets/ascii.xml119
-rw-r--r--sql/share/charsets/cp1250.xml121
-rw-r--r--sql/share/charsets/cp1251.conf74
-rw-r--r--sql/share/charsets/cp1251.xml216
-rw-r--r--sql/share/charsets/cp1256.xml123
-rw-r--r--sql/share/charsets/cp1257.conf74
-rw-r--r--sql/share/charsets/cp1257.xml229
-rw-r--r--sql/share/charsets/cp866.xml122
-rw-r--r--sql/share/charsets/croat.conf74
-rw-r--r--sql/share/charsets/danish.conf74
-rw-r--r--sql/share/charsets/dec8.conf74
-rw-r--r--sql/share/charsets/dec8.xml121
-rw-r--r--sql/share/charsets/dos.conf74
-rw-r--r--sql/share/charsets/estonia.conf74
-rw-r--r--sql/share/charsets/german1.conf74
-rw-r--r--sql/share/charsets/greek.conf74
-rw-r--r--sql/share/charsets/greek.xml120
-rw-r--r--sql/share/charsets/hebrew.conf74
-rw-r--r--sql/share/charsets/hebrew.xml120
-rw-r--r--sql/share/charsets/hp8.conf74
-rw-r--r--sql/share/charsets/hp8.xml120
-rw-r--r--sql/share/charsets/hungarian.conf74
-rw-r--r--sql/share/charsets/keybcs2.xml120
-rw-r--r--sql/share/charsets/koi8_ru.conf74
-rw-r--r--sql/share/charsets/koi8_ukr.conf74
-rw-r--r--sql/share/charsets/koi8r.xml119
-rw-r--r--sql/share/charsets/koi8u.xml120
-rw-r--r--sql/share/charsets/latin1.conf74
-rw-r--r--sql/share/charsets/latin1.xml233
-rw-r--r--sql/share/charsets/latin2.conf74
-rw-r--r--sql/share/charsets/latin2.xml167
-rw-r--r--sql/share/charsets/latin5.conf78
-rw-r--r--sql/share/charsets/latin5.xml125
-rw-r--r--sql/share/charsets/latin7.xml168
-rw-r--r--sql/share/charsets/pclatin1.xml119
-rw-r--r--sql/share/charsets/pclatin2.xml119
-rw-r--r--sql/share/charsets/swe7.conf74
-rw-r--r--sql/share/charsets/swe7.xml121
-rw-r--r--sql/share/charsets/usa7.conf74
-rw-r--r--sql/share/charsets/win1250.conf74
-rw-r--r--sql/share/charsets/win1251.conf82
-rw-r--r--sql/share/charsets/win1251ukr.conf77
-rw-r--r--sql/share/czech/errmsg.txt23
-rw-r--r--sql/share/danish/errmsg.txt19
-rw-r--r--sql/share/dutch/errmsg.txt19
-rw-r--r--sql/share/english/errmsg.txt21
-rw-r--r--sql/share/estonian/errmsg.txt19
-rw-r--r--sql/share/french/errmsg.txt19
-rw-r--r--sql/share/german/errmsg.txt194
-rw-r--r--sql/share/greek/errmsg.txt21
-rw-r--r--sql/share/hungarian/errmsg.txt21
-rw-r--r--sql/share/italian/errmsg.txt19
-rw-r--r--sql/share/japanese/errmsg.txt21
-rw-r--r--sql/share/korean/errmsg.txt21
-rw-r--r--sql/share/norwegian-ny/errmsg.txt21
-rw-r--r--sql/share/norwegian/errmsg.txt21
-rw-r--r--sql/share/polish/errmsg.txt21
-rw-r--r--sql/share/portuguese/errmsg.txt19
-rw-r--r--sql/share/romanian/errmsg.txt21
-rw-r--r--sql/share/russian/errmsg.txt19
-rw-r--r--sql/share/serbian/errmsg.txt249
-rw-r--r--sql/share/slovak/errmsg.txt21
-rw-r--r--sql/share/spanish/errmsg.txt19
-rw-r--r--sql/share/swedish/errmsg.txt39
-rw-r--r--sql/share/ukrainian/errmsg.txt19
-rw-r--r--sql/slave.cc328
-rw-r--r--sql/slave.h98
-rw-r--r--sql/spatial.cc1443
-rw-r--r--sql/spatial.h497
-rw-r--r--sql/sql_acl.cc811
-rw-r--r--sql/sql_acl.h52
-rw-r--r--sql/sql_analyse.cc82
-rw-r--r--sql/sql_analyse.h55
-rw-r--r--sql/sql_base.cc500
-rw-r--r--sql/sql_cache.cc78
-rw-r--r--sql/sql_class.cc295
-rw-r--r--sql/sql_class.h331
-rw-r--r--sql/sql_db.cc405
-rw-r--r--sql/sql_delete.cc92
-rw-r--r--sql/sql_derived.cc217
-rw-r--r--sql/sql_do.cc4
-rw-r--r--sql/sql_error.cc193
-rw-r--r--sql/sql_handler.cc60
-rw-r--r--sql/sql_help.cc519
-rw-r--r--sql/sql_insert.cc163
-rw-r--r--sql/sql_lex.cc683
-rw-r--r--sql/sql_lex.h377
-rw-r--r--sql/sql_list.h33
-rw-r--r--sql/sql_load.cc16
-rw-r--r--sql/sql_olap.cc18
-rw-r--r--sql/sql_parse.cc1582
-rw-r--r--sql/sql_prepare.cc951
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc110
-rw-r--r--sql/sql_repl.h4
-rw-r--r--sql/sql_select.cc2156
-rw-r--r--sql/sql_select.h116
-rw-r--r--sql/sql_show.cc1111
-rw-r--r--sql/sql_sort.h2
-rw-r--r--sql/sql_string.cc526
-rw-r--r--sql/sql_string.h143
-rw-r--r--sql/sql_table.cc560
-rw-r--r--sql/sql_test.cc130
-rw-r--r--sql/sql_udf.cc105
-rw-r--r--sql/sql_udf.h7
-rw-r--r--sql/sql_union.cc457
-rw-r--r--sql/sql_update.cc97
-rw-r--r--sql/sql_yacc.yy1954
-rw-r--r--sql/stacktrace.c6
-rw-r--r--sql/structs.h8
-rw-r--r--sql/table.cc124
-rw-r--r--sql/table.h25
-rw-r--r--sql/thr_malloc.cc2
-rw-r--r--sql/time.cc141
-rw-r--r--sql/udf_example.cc55
-rw-r--r--sql/unireg.cc84
-rw-r--r--sql/unireg.h4
-rw-r--r--strings/Makefile.am27
-rw-r--r--strings/conf_to_src.c342
-rw-r--r--strings/ctype-big5.c5935
-rw-r--r--strings/ctype-bin.c343
-rw-r--r--strings/ctype-czech.c190
-rw-r--r--strings/ctype-euc_kr.c8508
-rw-r--r--strings/ctype-extra.c3972
-rw-r--r--strings/ctype-gb2312.c5576
-rw-r--r--strings/ctype-gbk.c7260
-rw-r--r--strings/ctype-latin1.c225
-rw-r--r--strings/ctype-latin1_de.c219
-rw-r--r--strings/ctype-mb.c306
-rw-r--r--strings/ctype-simple.c1052
-rw-r--r--strings/ctype-sjis.c4268
-rw-r--r--strings/ctype-tis620.c84
-rw-r--r--strings/ctype-ujis.c8297
-rw-r--r--strings/ctype-utf8.c3135
-rw-r--r--strings/ctype-win1250ch.c693
-rw-r--r--strings/ctype.c234
-rw-r--r--strings/longlong2str-x86.s95
-rw-r--r--strings/my_vsnprintf.c166
-rw-r--r--strings/str2int.c2
-rw-r--r--strings/strto.c12
-rw-r--r--strings/xml.c374
-rw-r--r--tests/Makefile.am11
-rw-r--r--tests/client_test.c5953
-rw-r--r--tests/fork_big2.pl705
-rw-r--r--tests/grant.res38
-rw-r--r--tools/Makefile.am3
-rw-r--r--tools/mysqlmanager.c24
-rw-r--r--vio/Makefile.am2
-rw-r--r--vio/vio.c78
-rw-r--r--vio/viosocket.c184
2188 files changed, 323408 insertions, 131283 deletions
diff --git a/.bzrignore b/.bzrignore
index 302ac6f658c..99e6c82316f 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -51,6 +51,8 @@ Docs/manual.ky
Docs/manual.log
Docs/manual.pdf
Docs/manual.pg
+Docs/manual.texi.orig
+Docs/manual.texi.rej
Docs/manual.toc
Docs/manual.tp
Docs/manual.txt
@@ -88,17 +90,21 @@ bdb/build_vxworks/db_int.h
bdb/build_win32/db.h
bdb/build_win32/db_archive.dsp
bdb/build_win32/db_checkpoint.dsp
+bdb/build_win32/db_config.h
+bdb/build_win32/db_cxx.h
bdb/build_win32/db_deadlock.dsp
bdb/build_win32/db_dll.dsp
bdb/build_win32/db_dump.dsp
bdb/build_win32/db_int.h
bdb/build_win32/db_java.dsp
bdb/build_win32/db_load.dsp
+bdb/build_win32/db_perf.dsp
bdb/build_win32/db_printlog.dsp
bdb/build_win32/db_recover.dsp
bdb/build_win32/db_stat.dsp
bdb/build_win32/db_static.dsp
bdb/build_win32/db_tcl.dsp
+bdb/build_win32/db_test.dsp
bdb/build_win32/db_upgrade.dsp
bdb/build_win32/db_verify.dsp
bdb/build_win32/ex_access.dsp
@@ -114,9 +120,12 @@ bdb/build_win32/excxx_lock.dsp
bdb/build_win32/excxx_mpool.dsp
bdb/build_win32/excxx_tpcb.dsp
bdb/build_win32/include.tcl
+bdb/build_win32/libdb.def
bdb/build_win32/libdb.rc
bdb/db/crdel_auto.c
bdb/db/db_auto.c
+bdb/dbinc_auto/*.*
+bdb/dbreg/dbreg_auto.c
bdb/dist/autom4te-2.53.cache/output.0
bdb/dist/autom4te-2.53.cache/requests
bdb/dist/autom4te-2.53.cache/traces.0
@@ -132,11 +141,17 @@ bdb/dist/template/gen_client_ret
bdb/dist/template/rec_btree
bdb/dist/template/rec_crdel
bdb/dist/template/rec_db
+bdb/dist/template/rec_dbreg
+bdb/dist/template/rec_fileops
bdb/dist/template/rec_hash
bdb/dist/template/rec_log
bdb/dist/template/rec_qam
bdb/dist/template/rec_txn
+bdb/examples_c/ex_apprec/ex_apprec_auto.c
+bdb/examples_c/ex_apprec/ex_apprec_auto.h
+bdb/examples_c/ex_apprec/ex_apprec_template
bdb/examples_java
+bdb/fileops/fileops_auto.c
bdb/hash/hash_auto.c
bdb/include/btree_auto.h
bdb/include/btree_ext.h
@@ -165,21 +180,44 @@ bdb/include/tcl_ext.h
bdb/include/txn_auto.h
bdb/include/txn_ext.h
bdb/include/xa_ext.h
+bdb/java/src/com/sleepycat/db/Db.java
+bdb/java/src/com/sleepycat/db/DbBtreeStat.java
bdb/java/src/com/sleepycat/db/DbConstants.java
+bdb/java/src/com/sleepycat/db/DbHashStat.java
+bdb/java/src/com/sleepycat/db/DbLockStat.java
+bdb/java/src/com/sleepycat/db/DbLogStat.java
+bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
+bdb/java/src/com/sleepycat/db/DbQueueStat.java
+bdb/java/src/com/sleepycat/db/DbRepStat.java
+bdb/java/src/com/sleepycat/db/DbTxnStat.java
+bdb/libdb_java/java_stat_auto.c
+bdb/libdb_java/java_stat_auto.h
bdb/log/log_auto.c
bdb/qam/qam_auto.c
bdb/rpc_client/db_server_clnt.c
bdb/rpc_client/gen_client.c
+bdb/rpc_server/c/db_server_proc.c
+bdb/rpc_server/c/db_server_proc.sed
+bdb/rpc_server/c/db_server_svc.c
+bdb/rpc_server/c/db_server_xdr.c
+bdb/rpc_server/c/gen_db_server.c
bdb/rpc_server/db_server.x
bdb/rpc_server/db_server_proc.sed
bdb/rpc_server/db_server_svc.c
bdb/rpc_server/db_server_xdr.c
bdb/rpc_server/gen_db_server.c
+bdb/test/TESTS
bdb/test/include.tcl
bdb/test/logtrack.list
bdb/txn/txn_auto.c
binary/*
bkpull.log
+bkpull.log.2
+bkpull.log.3
+bkpull.log.4
+bkpull.log.5
+bkpull.log.6
+bkpush.log
build.log
client/insert_test
client/log_event.cc
@@ -200,30 +238,40 @@ client/mysys_priv.h
client/select_test
client/thimble
client/thread_test
+cmd-line-utils/libedit/common.h
+comon.h
config.cache
config.h
config.h.in
config.log
config.status
configure
+configure.lineno
core
core.2430
db-*.*.*
dbug/user.t
depcomp
+emacs.h
extra/comp_err
extra/my_print_defaults
extra/mysql_install
+extra/mysql_waitpid
extra/perror
extra/replace
extra/resolve_stack_dump
extra/resolveip
+fcns.c
+fcns.h
gmon.out
heap/hp_test1
heap/hp_test2
+help.c
+help.h
include/my_config.h
include/my_global.h
include/mysql_version.h
+include/readline/readline.h
include/widec.h
innobase/autom4te-2.53.cache/output.0
innobase/autom4te-2.53.cache/requests
@@ -232,6 +280,7 @@ innobase/autom4te.cache/*
innobase/autom4te.cache/output.0
innobase/autom4te.cache/requests
innobase/autom4te.cache/traces.0
+innobase/configure.lineno
innobase/conftest.s1
innobase/conftest.subs
innobase/ib_config.h
@@ -273,6 +322,7 @@ libmysqld/field.cc
libmysqld/field_conv.cc
libmysqld/filesort.cc
libmysqld/get_password.c
+libmysqld/gstream.cc
libmysqld/ha_berkeley.cc
libmysqld/ha_heap.cc
libmysqld/ha_innobase.cc
@@ -290,6 +340,7 @@ libmysqld/item_buff.cc
libmysqld/item_cmpfunc.cc
libmysqld/item_create.cc
libmysqld/item_func.cc
+libmysqld/item_row.cc
libmysqld/item_strfunc.cc
libmysqld/item_sum.cc
libmysqld/item_timefunc.cc
@@ -308,11 +359,13 @@ libmysqld/opt_range.cc
libmysqld/opt_sum.cc
libmysqld/password.c
libmysqld/procedure.cc
+libmysqld/protocol.cc
libmysqld/records.cc
libmysqld/repl_failsafe.cc
libmysqld/set_var.cc
libmysqld/simple-test
libmysqld/slave.cc
+libmysqld/spatial.cc
libmysqld/sql_acl.cc
libmysqld/sql_analyse.cc
libmysqld/sql_base.cc
@@ -324,6 +377,7 @@ libmysqld/sql_db.cc
libmysqld/sql_delete.cc
libmysqld/sql_do.cc
libmysqld/sql_handler.cc
+libmysqld/sql_help.cc
libmysqld/sql_insert.cc
libmysqld/sql_lex.cc
libmysqld/sql_list.cc
@@ -382,6 +436,10 @@ myisam/myisam.log
myisam/myisamchk
myisam/myisamlog
myisam/myisampack
+myisam/rt_test
+myisam/rt_test.MYD
+myisam/rt_test.MYI
+myisam/sp_test
myisam/test1.MYD
myisam/test1.MYI
myisam/test2.MYD
@@ -408,6 +466,7 @@ mysql.proj
mysqld.S
mysqld.sym
mysys/#mf_iocache.c#
+mysys/charset2html
mysys/getopt.c
mysys/getopt1.c
mysys/ste5KbMa
@@ -425,6 +484,8 @@ repl-tests/test-repl/foo-dump-slave.master.
repl-tests/test-repl/sum-wlen-slave.master.
repl-tests/test-repl/sum-wlen-slave.master.re
repl-tests/test-repl/sum-wlen-slave.master.reje
+scripts/fill_func_tables
+scripts/fill_func_tables.sql
scripts/make_binary_distribution
scripts/msql2mysql
scripts/mysql_config
@@ -484,6 +545,7 @@ sql/mysqld-purecov
sql/mysqld-purify
sql/mysqld-quantify
sql/new.cc
+sql/safe_to_cache_query.txt
sql/share/*.sys
sql/share/charsets/gmon.out
sql/share/gmon.out
@@ -493,12 +555,21 @@ sql/share/norwegian/errmsg.sys
sql/sql_select.cc.orig
sql/sql_yacc.cc
sql/sql_yacc.h
+sql/sql_yacc.output
+sql/sql_yacc.yy.orig
+sql_error.cc
+sql_prepare.cc
stamp-h
stamp-h.in
stamp-h1
+stamp-h2
+stamp-h3
+stamp-h4
strings/conf_to_src
strings/ctype_autoconf.c
strings/ctype_extra_sources.c
+support-files/MacOSX/Description.plist
+support-files/MacOSX/Info.plist
support-files/binary-configure
support-files/my-huge.cnf
support-files/my-large.cnf
@@ -513,15 +584,16 @@ support-files/mysql-log-rotate
support-files/mysql.server
support-files/mysql.spec
tags
+test_xml
+tests/client_test
tmp/*
tools/my_vsnprintf.c
tools/mysqlmanager
tools/mysqlmngd
tools/mysys_priv.h
+vi.h
vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-extra/mysql_waitpid
-support-files/MacOSX/Description.plist
-support-files/MacOSX/Info.plist
+scripts/fill_help_tables.sql
diff --git a/BUILD/compile-pentium-debug b/BUILD/compile-pentium-debug
index d8a6b60809b..4a9d0e74599 100755
--- a/BUILD/compile-pentium-debug
+++ b/BUILD/compile-pentium-debug
@@ -6,8 +6,8 @@ path=`dirname $0`
extra_flags="$pentium_cflags $debug_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
-extra_configs="$pentium_configs $debug_configs $static_link"
+extra_configs="$pentium_configs $debug_configs "
-extra_configs="$extra_configs "
+extra_configs="$extra_configs"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-max b/BUILD/compile-pentium-max
index d41274d4f5e..a1a256f949f 100755
--- a/BUILD/compile-pentium-max
+++ b/BUILD/compile-pentium-max
@@ -3,9 +3,9 @@
path=`dirname $0`
. "$path/SETUP.sh"
-extra_flags="$pentium_cflags $fast_cflags"
+extra_flags="$pentium_cflags $fast_cflags -g"
extra_configs="$pentium_configs"
-strip=yes
+#strip=yes
extra_configs="$extra_configs --with-innodb --with-berkeley-db \
--with-embedded-server --enable-thread-safe-client \
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index 9df006ac7d5..ea30f368b52 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -69,4 +69,5 @@ pager:
hours:
[serg:]checkout:get
[arjen:]checkout:get
+[nick:]checkout:get
checkout:edit
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index df830cbe6cb..71388fba9c3 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -4,6 +4,7 @@ Administrator@co3064164-a.rochd1.qld.optushome.com.au
Administrator@fred.
Miguel@light.local
Sinisa@sinisa.nasamreza.org
+WAX@sergbook.mysql.com
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
akishkin@work.mysql.com
arjen@co3064164-a.bitbike.com
@@ -11,17 +12,24 @@ arjen@fred.bitbike.com
arjen@george.bitbike.com
bar@bar.mysql.r18.ru
bar@bar.udmsearch.izhnet.ru
+bar@gw.udmsearch.izhnet.ru
bell@sanja.is.com.ua
bk@admin.bk
davida@isil.mysql.com
gluh@gluh.(none)
+gluh@gluh.mysql.r18.ru
gweir@work.mysql.com
heikki@donna.mysql.fi
heikki@hundin.mysql.fi
heikki@rescue.
heikki@work.mysql.com
+hf@bison.(none)
+hf@bisonxp.(none)
+hf@deer.mysql.r18.ru
hf@genie.(none)
+igor@hundin.mysql.fi
jani@dsl-jkl1657.dial.inet.fi
+jani@dsl-kpogw4gb5.dial.inet.fi
jani@hynda.(none)
jani@hynda.mysql.fi
jani@janikt.pp.saunalahti.fi
@@ -62,10 +70,12 @@ paul@teton.kitebird.com
pem@mysql.com
peter@linux.local
peter@mysql.com
+ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
ram@ram.(none)
ranger@regul.home.lan
root@x3.internalnet
+salle@banica.(none)
salle@geopard.(none)
salle@geopard.online.bg
sasha@mysql.sashanet.com
@@ -87,11 +97,16 @@ tonu@hundin.mysql.fi
tonu@volk.internalnet
tonu@x153.internalnet
tonu@x3.internalnet
+venu@hundin.mysql.fi
+venu@myvenu.com
venu@work.mysql.com
+vva@eagle.mysql.r18.ru
vva@genie.(none)
walrus@kishkin.ru
walrus@mysql.com
+wax@mysql.com
worm@altair.is.lan
zak@balfor.local
zak@linux.local
+zak@mysql.com
zgreant@mysql.com
diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit
index 636e4262693..a2a0ecb2701 100755
--- a/BitKeeper/triggers/post-commit
+++ b/BitKeeper/triggers/post-commit
@@ -27,10 +27,10 @@ CHANGESET=`bk -R prs -r+ -h -d':I:' ChangeSet`
echo "Commit successful, notifying developers at $TO"
(
cat <<EOF
-List-ID: <bk.mysql-4.0>
+List-ID: <bk.mysql-4.1>
From: $FROM
To: $TO
-Subject: bk commit - 4.0 tree ($CHANGESET)
+Subject: bk commit - 4.1 tree ($CHANGESET)
EOF
bk changes -v -r+
@@ -43,13 +43,13 @@ EOF
echo "Notifying internals list at $INTERNALS"
(
cat <<EOF
-List-ID: <bk.mysql-4.0>
+List-ID: <bk.mysql-4.1>
From: $FROM
To: $INTERNALS
-Subject: bk commit into 4.0 tree ($CHANGESET)
+Subject: bk commit into 4.1 tree ($CHANGESET)
Below is the list of changes that have just been committed into a local
-4.0 repository of $USER. When $USER does a push these changes will
+4.1 repository of $USER. When $USER does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
@@ -70,10 +70,10 @@ EOF
echo "Notifying docs list at $DOCS"
(
cat <<EOF
-List-ID: <bk.mysql-4.0>
+List-ID: <bk.mysql-4.1>
From: $FROM
To: $DOCS
-Subject: bk commit - 4.0 tree (Manual) ($CHANGESET)
+Subject: bk commit - 4.1 tree (Manual) ($CHANGESET)
EOF
bk changes -v -r+
diff --git a/Docs/gis.txt b/Docs/gis.txt
new file mode 100644
index 00000000000..3556949d516
--- /dev/null
+++ b/Docs/gis.txt
@@ -0,0 +1,874 @@
+
+ OpenGIS <http://www.opengis.org> support in MySQL
+
+------------------------------------------------------------------------
+Note: Blue colored lines among the text is features not implemented yet.
+They are:
+
+ * Spatial Reference Systems and their IDs (SRIDs) related things:
+ o Functions like Length() and Area() assume planar coordinate
+ system.
+ o All objects are currently considered to be in the same
+ planar coordinate system.
+ * Function Length() on LineString and MultiLineString currently
+ should be called as GLength().
+* No binary constructors like GeomFromWKB().
+
+We also have to add "PostGIS compatibility" sections.
+
+
+ 1 Introduction
+
+MySQL implements a subset of *SQL2 with Geometry Types* environment
+proposed by OpenGIS consortium's *Simple Features Specification For
+SQL*. In this environment a geometry-valued column is implemented as a
+column whose SQL type is drawn from the set of Geometry Types. SQL
+server supports both textual and binary access to geometry.
+
+
+ 2 OpenGIS Geometry Model in MySQL
+
+MySQL supports the Open GIS Geometry Model based hierarcy of spatial
+objects classes, which consists of:
+
+ * Geometry
+ o *Point*
+ o Curve
+ + *LineString*
+ o Surface
+ + *Polygon*
+ o *GeometryCollection*
+ + *MultiPoint*
+ + MultiCurve
+ # *MultiLineString*
+ + MultiSurface
+ # *MultiPolygon*
+
+The base *Geometry* class has subclasses for Point, Curve, Surface and
+GeometryCollection.
+
+Geometry, Curve, Surface, MultiCurve and MultiSurface are defined to be
+non-instantiable classes, it is not possible to create an object of
+these classes.
+
+Point, LineString, Polygon, GeometryCollection, MultiPoint,
+MultiLineString, MultiPolygon are instantiable classes (bolded on the
+hierarcy tree). MySQL provides a number of functions to construct
+instances of these classes.
+
+TODO: Each spatial object is associated with a Spatial Reference System,
+which describes the coordinate space in which the geometric object is
+defined.
+
+
+ 2.1 Geometry
+
+Geometry is the root class of the hierarchy. Geometry is an abstract
+(non-instantiable) class. The instantiable subclasses of Geometry
+defined in this specification are restricted to 0, 1 and two-dimensional
+geometric objects that exist in two-dimensional coordinate space. All
+instantiable geometry classes are defined so that valid instances of a
+geometry class are topologically closed (i.e. all defined geometries
+include their boundary).
+
+
+ 2.2 Point
+
+A *Point* is a 0-dimensional geometry and represents a single location
+in coordinate space. A Point in the case of 2D has a x-coordinate value
+and a y-coordinate value. In the case of more dimensions, a Point has a
+coordinate value for each dimension. The boundary of a Point is the
+empty set.
+
+
+ 2.3 Curve
+
+A *Curve* is a one-dimensional geometric object usually stored as a
+sequence of points, with the subclass of Curve specifying the form of
+the interpolation between points. MySQL implementation defines only one
+subclass of Curve, LineString, which uses linear interpolation between
+points.
+
+A Curve is simple if it does not pass through the same point twice. A
+Curve is closed if its start point is equal to its end point. The
+boundary of a closed Curve is empty. A Curve that is simple and closed
+is a Ring. The boundary of a non-closed Curve consists of its two end
+points. A Curve is defined as topologically closed.
+
+
+ 2.4 LineString, Line, LinearRing
+
+A LineString is a Curve with linear interpolation between points. Each
+consecutive pair of points defines a line segment. A Line is a
+LineString with exactly 2 points. A LinearRing is a LineString that is
+both closed and simple.
+
+
+ 2.5 Surface
+
+A *Surface* is a two-dimensional geometric object. The OpenGIS Abstract
+Specification defines a simple Surface as consisting of a single 'patch'
+that is associated with one 'exterior boundary' and 0 or more 'interior'
+boundaries. Simple surfaces in three-dimensional space are isomorphic to
+planar surfaces. Polyhedral surfaces are formed by 'stitching' together
+simple surfaces along their boundaries, polyhedral surfaces in
+three-dimensional space may not be planar as a whole.
+
+The boundary of a simple Surface is the set of closed curves
+corresponding to its exterior and interior boundaries.
+
+The only instantiable subclass of Surface defined in this specification,
+Polygon, is a simple Surface that is planar.
+
+
+ 2.6 Polygon
+
+A Polygon is a planar Surface, defined by 1 exterior boundary and 0 or
+more interior boundaries. Each interior boundary defines a hole in the
+Polygon. The assertions for polygons (the rules that define valid
+polygons) are:
+
+ * Polygons are topologically closed.
+ * The boundary of a Polygon consists of a set of LinearRings (i.e.
+ LineStrings which are both simple and closed) that make up its
+ exterior and interior boundaries.
+ * No two rings in the boundary cross, the rings in the boundary of a
+ Polygon may intersect at a Point but only as a tangent.
+ * A Polygon may not have cut lines, spikes or punctures.
+ * The Interior of every Polygon is a connected point set.
+ * The Exterior of a Polygon with 1 or more holes is not connected.
+Each hole defines a connected component of the Exterior.
+
+In the above assertions, Interior, Closure and Exterior have the
+standard topological definitions. The combination of 1 and 3 make a
+Polygon a Regular Closed point set. Polygons are simple geometries.
+
+
+ 2.6 GeometryCollection
+
+A *GeometryCollection* is a geometry that is a collection of 1 or more
+geometries of any class. All the elements in a GeometryCollection must
+be in the same Spatial Reference (i.e. in the same coordinate system).
+GeometryCollection places no other constraints on its elements. However
+subclasses of GeometryCollection described below may restrict membership
+based on dimension and may also place other constraints on the degree of
+spatial overlap between elements.
+
+
+ 2.7 MultiPoint
+
+A *MultiPoint* is a 0 dimensional geometric collection. The elements of
+a MultiPoint are restricted to Points. The points are not connected or
+ordered. A MultiPoint is simple if no two Points in the MultiPoint are
+equal (have identical coordinate values). The boundary of a MultiPoint
+is the empty set.
+
+
+ 2.8 MultiCurve
+
+A MultiCurve is a one-dimensional geometry collection whose elements are
+Curves. MultiCurve is a non-instantiable class, it defines a set of
+methods for its subclasses and is included for reasons of extensibility.
+
+A MultiCurve is simple if and only if all of its elements are simple,
+the only intersections between any two elements occur at points that are
+on the boundaries of both elements.
+
+The boundary of a MultiCurve is obtained by applying the "mod 2 union
+rule": A point is in the boundary of a MultiCurve if it is in the
+boundaries of an odd number of elements of the MultiCurve.
+
+A MultiCurve is closed if all of its elements are closed. The boundary
+of a closed MultiCurve is always empty. A MultiCurve is defined as
+topologically closed.
+
+
+ 2.9 MultiLineString
+
+A *MultiLineString* is a MultiCurve whose elements are LineStrings.
+
+
+ 2.10 MultiSurface
+
+A MultiSurface is a two-dimensional geometric collection whose elements
+are surfaces. The interiors of any two surfaces in a MultiSurface may
+not intersect. The boundaries of any two elements in a MultiSurface may
+intersect at most at a finite number of points.
+
+MultiSurface is a non-instantiable class in this specification, it
+defines a set of methods for its subclasses and is included for reasons
+of extensibility. The instantiable subclass of MultiSurface is
+MultiPolygon, corresponding to a collection of Polygons.
+
+
+ 2.11 MultiPolygon
+
+A MultiPolygon is a MultiSurface whose elements are Polygons.
+
+The assertions for MultiPolygons are :
+
+ * The interiors of 2 Polygons that are elements of a MultiPolygon
+ may not intersect.
+ * The Boundaries of any 2 Polygons that are elements of a
+ MultiPolygon may not cross and may touch at only a finite number
+ of points. (Note that crossing is prevented by assertion 1 above).
+ * A MultiPolygon is defined as topologically closed.
+ * A MultiPolygon may not have cut lines, spikes or punctures, a
+ MultiPolygon is a Regular, Closed point set.
+ * The interior of a MultiPolygon with more than 1 Polygon is not
+ connected, the number of connected components of the interior of a
+MultiPolygon is equal to the number of Polygons in the MultiPolygon.
+
+The boundary of a MultiPolygon is a set of closed curves (LineStrings)
+corresponding to the boundaries of its element Polygons. Each Curve in
+the boundary of the MultiPolygon is in the boundary of exactly 1 element
+Polygon, and every Curve in the boundary of an element Polygon is in the
+boundary of the MultiPolygon.
+
+
+ 3 Exchange of spatial data
+
+MySQL provides binary and textual mechanismes to exchange spatial data.
+Exchange is provided via so called Well Known Binary (WKB) and Well
+Known Textual (WKT) representations of spatial data proposed by OpenGIS
+specifications.
+
+
+ 3.1 Well-known Text representation (WKT)
+
+The Well-known Text (WKT) representation of Geometry is designed to
+exchange geometry data in textual format.
+
+WKT is defined below in Bechus-Naur forms:
+
+ * the notation {}* denotes 0 or more repetitions of the tokens
+ within the braces;
+* the braces do not appear in the output token list.
+
+The text representation of the implemented instantiable geometric types
+conforms to this grammar:
+
+<Geometry Tagged Text> :=
+ <Point Tagged Text>
+ | <LineString Tagged Text>
+ | <Polygon Tagged Text>
+ | <MultiPoint Tagged Text>
+ | <MultiLineString Tagged Text>
+ | <MultiPolygon Tagged Text>
+ | <GeometryCollection Tagged Text>
+
+<Point Tagged Text> :=
+
+ POINT <Point Text>
+
+<LineString Tagged Text> :=
+
+ LINESTRING <LineString Text>
+
+<Polygon Tagged Text> :=
+
+ POLYGON <Polygon Text>
+
+<MultiPoint Tagged Text> :=
+
+ MULTIPOINT <Multipoint Text>
+
+<MultiLineString Tagged Text> :=
+
+ MULTILINESTRING <MultiLineString Text>
+
+<MultiPolygon Tagged Text> :=
+
+ MULTIPOLYGON <MultiPolygon Text>
+
+<GeometryCollection Tagged Text> :=
+
+ GEOMETRYCOLLECTION <GeometryCollection Text>
+
+<Point Text> := EMPTY | ( <Point> )
+
+<Point> := <x> <y>
+
+<x> := double precision literal
+
+<y> := double precision literal
+
+<LineString Text> := EMPTY
+
+ | ( <Point > {, <Point > }* )
+
+<Polygon Text> := EMPTY
+
+ | ( <LineString Text > {, < LineString Text > }*)
+
+<Multipoint Text> := EMPTY
+
+ | ( <Point Text > {, <Point Text > }* )
+
+<MultiLineString Text> := EMPTY
+
+ | ( <LineString Text > {, < LineString Text > }* )
+
+<MultiPolygon Text> := EMPTY
+
+ | ( < Polygon Text > {, < Polygon Text > }* )
+
+<GeometryCollection Text> := EMPTY
+
+ | ( <Geometry Tagged Text> {, <Geometry Tagged Text> }* )
+
+
+ WKT examples
+
+Examples of textual representations of Geometry objects are shown below:
+
+ * |POINT(10 10)| - a Point
+ * |LINESTRING( 10 10, 20 20, 30 40)| - a LineString with three points
+ * |POLYGON((10 10, 10 20, 20 20,20 15, 10 10))| - a Polygon with one
+ exterior ring and 0 interior rings
+ * |MULTIPOINT(10 10, 20 20)| - a MultiPoint with two Points
+ * |MULTILINESTRING((10 10, 20 20), (15 15, 30 15))| - a
+ MultiLineString with two LineStrings
+ * |MULTIPOLYGON(((10 10, 10 20, 20 20, 20 15, 10 10)), ((60 60, 70
+ 70, 80 60, 60 60 ) ))| - a MultiPolygon with two Polygons
+ * |GEOMETRYCOLLECTION( POINT (10 10),POINT (30 30), LINESTRING (15
+ 15, 20 20))| - a GeometryCollection consisting of two Points and
+one LineString
+
+
+ 3.2 Well-known Binary representation (WKB)
+
+Well Known Binary Representations is proposed by OpenGIS specifications
+to exchange geometry data in binary format. This is WKB description:
+
+// Basic Type definitions
+// byte : 1 byte
+// uint32 : 32 bit unsigned integer (4 bytes)
+// double : double precision number (8 bytes)
+// Building Blocks : Point, LinearRing
+
+Point {
+ double [numDimentions];
+};
+
+LinearRing {
+ uint32 numPoints;
+ Point points[numPoints];
+}
+
+enum wkbGeometryType {
+ wkbPoint = 1,
+ wkbLineString = 2,
+ wkbPolygon = 3,
+ wkbMultiPoint = 4,
+ wkbMultiLineString = 5,
+ wkbMultiPolygon = 6,
+ wkbGeometryCollection = 7
+};
+
+enum wkbByteOrder {
+ wkbXDR = 0, // Big Endian
+ wkbNDR = 1 // Little Endian
+};
+
+WKBPoint {
+ byte byteOrder;
+ uint32 wkbType; // 1
+ Point point;
+}
+
+WKBLineString {
+ byte byteOrder;
+ uint32 wkbType; // 2
+ uint32 numPoints;
+ Point points[numPoints];
+}
+
+WKBPolygon {
+ byte byteOrder;
+ uint32 wkbType; // 3
+ uint32 numRings;
+ LinearRing rings[numRings];
+}
+
+WKBMultiPoint {
+ byte byteOrder;
+ uint32 wkbType; // 4
+ uint32 num_wkbPoints;
+ WKBPoint WKBPoints[num_wkbPoints];
+}
+
+WKBMultiLineString {
+ byte byteOrder;
+ uint32 wkbType; // 5
+ uint32 num_wkbLineStrings;
+ WKBLineString WKBLineStrings[num_wkbLineStrings];
+}
+
+wkbMultiPolygon {
+ byte byteOrder;
+ uint32 wkbType; // 6
+ uint32 num_wkbPolygons;
+ WKBPolygon wkbPolygons[num_wkbPolygons];
+}
+
+WKBGeometry {
+ union {
+ WKBPoint point;
+ WKBLineString linestring;
+ WKBPolygon polygon;
+ WKBGeometryCollection collection;
+ WKBMultiPoint mpoint;
+ WKBMultiLineString mlinestring;
+ WKBMultiPolygon mpolygon;
+ }
+
+};
+
+WKBGeometryCollection {
+ byte byte_order;
+ uint32 wkbType; // 7
+ uint32 num_wkbGeometries;
+ WKBGeometry wkbGeometries[num_wkbGeometries];
+}
+
+
+ 3.3 MySQL data types for spatial objects
+
+MySQL implementation of OpenGIS provides the *GEOMETRY* data type to be
+used in CREATE TABLE statements. For example, this statement creates a
+table *geom* with spatial field *g*:
+
+CREATE TABLE geom (
+ g Geometry;
+);
+
+A field of *GEOMETRY* type can store a spatial objects of any OpenGIS
+geometry class described above.
+
+
+ 3.4 Internal spatial data representation
+
+Internally (in *.MYD* files) spatial objects are stored in *WKB*,
+combined with object's *SRID* (a numeric ID of Spatial Reference System
+object associated with). During spatial analysis, for example,
+calculating the fact that one object crosses another one, only those
+with the same *SRID* are accepted.
+
+*SRID* may affect a way in which various spatial characteristics are
+calculated. For example, in different coordinate systems distance
+between two objects may differ even objects have the same coordinates,
+like distance on plane coordinate system and distance on geocentric
+(coordinates on Earth surface) systems are different things.
+
+There is a plan to provide a number of commonly used coordinate systems
+in MySQL OpenGIS implementation.
+
+
+ 3.5 INSERTing spatial objects
+
+Spatial data can be INSERTed using a spatial constructor. The term
+*spatial constructor* is used in this manual to refer to any function
+which can construct a value of GEOMETRY type, i.e. an internal MySQL
+representation of spatial data.
+
+
+ 3.5.1 Textual spatial constructors
+
+Textual spatial constructors take a gemometry description in WKT and
+built GEOMETRY value.
+
+ * |*GeomFromText(geometryTaggedText String [, SRID
+ Integer]):Geometry *| - constructs a Geometry value from its
+ well-known textual representation.
+
+ |*GeomFromText()*| function accepts a WKT of any Geometry class as
+ it's first argument.
+
+ For construction of Geometry values restricted to a particular
+ subclass, an implementation also provides a class-specific
+ construction function for each instantiable subtype as described
+ in the list below:
+
+ * |*PointFromText(pointTaggedText String [,SRID Integer]):Point *| -
+ constructs a Point
+
+ * |*LineFromText(lineStringTaggedText String [,SRID
+ Integer]):LineString *| - constructs a LineString
+
+ . |*LineStringFromText()*| - synonym for LineFromText().
+
+ * |*PolyFromText(polygonTaggedText String [,SRID Integer]):Polygon
+ *|- constructs a Polygon
+
+ |*PolygonFromText()*| - synonym for PolyFromText().
+
+ * |*MPointFromText(multiPointTaggedText String [,SRID
+ Integer]):MultiPoint *| - constructs a MultiPoint
+
+ |*MultiPointFromText()*| - synonym for MPointFromText().
+
+ * |*MLineFromText(multiLineStringTaggedText String [,SRID
+ Integer]):MultiLineString *| - constructs a MultiLineString
+
+ |*MultiLineStringFromText()*| - synonym for MLineFromText().
+
+ * |*MPolyFromText(multiPolygonTaggedText String [,SRID
+ Integer]):MultiPolygon *| - constructs a MultiPolygon
+
+ |*MultiPolygonFromText()*| - synonym for MPolyFromText().
+
+ * |*GeomCollFromText(geometryCollectionTaggedText String [,SRID
+ Integer]):GeomCollection *| - constructs a GeometryCollection
+
+Usage examples:
+
+INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'))
+INSERT INTO geom VALUES (GeomFromText('LINESTRING(0 0,1 1,2 2)'))
+INSERT INTO geom VALUES (GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'))
+INSERT INTO geom VALUES (GeomFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'))
+
+The second argument of spatial constructirs, described above, is
+currently ignored, It will be used to specify SRID in the future.
+Nowdays, it is added for reasons of compatibility with OpenGIS
+specifications and PostGIS implementation.
+
+As an optional feature, an implementation may also support building of
+Polygon or MultiPolygon values given an arbitrary collection of possibly
+intersecting rings or closed LineString values. Implementations that
+support this feature should include the following functions:
+
+ * |*BdPolyFromText(multiLineStringTaggedText String, SRID
+ Integer):Polygon *| - constructs a Polygon given an arbitrary
+ collection of closed linestrings as a MultiLineString text
+ representation.
+ * |*BdMPolyFromText(multiLineStringTaggedText String, SRID
+ Integer):MultiPolygon *| - constructs a MultiPolygon given an
+ arbitrary collection of closed linestrings as a MultiLineString
+text representation.
+
+
+ 3.5.2 Binary spatial constructors
+
+ * |*GeomFromWKB(WKBGeometry Binary, SRID Integer):Geometry *| -
+ constructs a Geometry value given its well-known binary
+ representation.
+
+ |*GeomFromWKB()*| function can accept in it's first argument a WKB
+ of Geometry of any class. For construction of Geometry values
+ restricted to a particular subclass, an implementation also
+ provides a class-specific construction function for each
+ instantiable subclass as described in the list below:
+
+ * |*PointFromWKB(WKBPoint Binary, SRID Integer):Point - *|constructs
+ a Point
+ * |* LineFromWKB(WKBLineString Binary, SRID Integer):LineString *| -
+ constructs a LineString
+ * |* PolyFromWKB(WKBPolygon Binary, SRID Integer):Polygon *| -
+ constructs a Polygon
+ * |* MPointFromWKB(WKBMultiPoint Binary, SRID Integer):MultiPoint *|
+ - constructs a MultiPoint
+ * |* MLineFromWKB(WKBMultiLineString Binary, SRID
+ Integer):MultiLineString *| - constructs a MultiLineString
+ * |* MPolyFromWKB(WKBMultiPolygon Binary, SRID Integer):
+ MultiPolygon *| - constructs a MultiPolygon
+ * |* GeomCollFromWKB(WKBGeometryCollection Binary, SRID Integer):
+GeomCollection *| - constructs a GeometryCollection
+
+As an optional feature, an implementation may also support the uilding'
+of Polygon or MultiPolygon values given an arbitrary collection of
+possibly intersecting rings or closed LineString values. Implementations
+that support this feature should include the following functions:
+
+ * |* BdPolyFromWKB (WKBMultiLineString Binary,SRID Integer): Polygon
+ *| - constructs a Polygon given an arbitrary collection of closed
+ linestrings as a MultiLineString binary representation.
+ * |*BdMPolyFromWKB(WKBMultiLineString Binary, SRID
+ Integer):MultiPolygon *| - constructs a MultiPolygon given an
+ arbitrary collection of closed linestrings as a MultiLineString
+binary representation.
+
+Inserting in *WKB* assumes that |GeomFromWKB()| function argument
+contains a buffer with a correctly formed spatial object in WKB. In ODBC
+applications it can be done using binding of argument. One also can
+insert object in *WKB* using |mysql_escape_string()| in |libmysqlclient|
+applications.
+
+For example:
+
+INSERT INTO geom VALUES (GeomFromWKB(buf,SRID));
+
+where |buf| is a binary buffer with a spatial object in *WKB*
+representation.
+
+
+ 3.5 SELECTing spatial objects
+
+Spatial objects are selected either in *WKT* or *WKB* representation by
+use of AsText() and AsBinary() functions correspondently.
+
+
+mysql> select AsText(g) as g from geom;
++-------------------------+
+| g |
++-------------------------+
+| POINT(1 1) |
+| LINESTRING(0 0,1 1,2 2) |
++-------------------------+
+2 rows in set (0.00 sec)
+
+mysql>
+
+The query:
+
+SELECT AsBinary(g) FROM geom
+
+returns a BLOB which contains *WKB* representation of object.
+
+
+ 4 Functions for spatial analysis
+
+
+ 4.1 Basic functions on Geometry
+
+ * |*AsText(g:Geometry):String*| - Exports this Geometry to a
+ specific well-known text representation of Geometry.
+ * |*AsBinary(g:Geometry):Binary*| - Exports this Geometry to a
+ specific well-known binary representation of Geometry.
+ * |*GeometryType(g:Geometry):String*| - Returns the name of the
+ instantiable subtype of Geometry of which this Geometry instance
+ is a member. The name of the instantiable subtype of Geometry is
+ returned as a string.
+ * |*Dimension(g:Geometry):Integer*| - The inherent dimension of this
+ Geometry object, which must be less than or equal to the
+ coordinate dimension. This specification is restricted to
+ geometries in two-dimensional coordinate space.
+ * |*IsEmpty(g:Geometry):Integer*| - Returns 1 (TRUE) if this
+ Geometry is the empty geometry . If true, then this Geometry
+ represents the empty point set, , for the coordinate space.
+ * |*IsSimple(g:Geometry):Integer *| - Returns 1 (TRUE) if this
+ Geometry has no anomalous geometric points, such as self
+ intersection or self tangency. The description of each
+ instantiable geometric class includes the specific conditions that
+ cause an instance of that class to be classified as not simple.
+ * |*SRID(g:Geometry):Integer*| - Returns the Spatial Reference
+ System ID for this Geometry.
+ * |*Distance(g1:Geometry,g2:Geometry):Double*| - the shortest
+distance between any two points in the two geometries.
+
+
+ 4.2 Functions for specific geometry type
+
+
+ GeometryCollection functions
+
+ * *NumGeometries(g:GeometryCollection ):Integer * -Returns the
+ number of geometries in this GeometryCollection.
+ * *GeometryN(g:GeometryCollection,N:integer):Geometry * -Returns the
+Nth geometry in this GeometryCollection.
+
+
+ Point functions
+
+ * *X(p:Point):Double* -The x-coordinate value for this Point.
+* *Y(p:Point):Double* -The y-coordinate value for this Point.
+
+
+ LineString functions
+
+ * *StartPoint(l:LineString):Point* The start point of this LineString.
+ * *EndPoint(l:LineString):Point* The end point of this LineString.
+ * *PointN(l:LineString,N:Integer):Point* Returns the specified point
+ N in this Linestring.
+ * *Length(l:LineString):Double* The length of this LineString in its
+ associated spatial reference.
+ * *IsRing(l:LineString):Integer* Returns 1 (TRUE) if this LineString
+ is closed (StartPoint ( ) = EndPoint ( )) and this LineString is
+ simple (does not pass through the same point more than once).
+ * *IsClosed(l:LineString):Integer* Returns 1 (TRUE) if this
+ LineString is closed (StartPoint ( ) = EndPoint ( )).
+ * *NumPoints(l:LineString):Integer* The number of points in this
+LineString.
+
+
+ MultiLineString functions
+
+ * *Length(m:MultiLineString):Double* The Length of this
+ MultiLineString which is equal to the sum of the lengths of the
+ elements.
+ * *IsClosed(m:MultiLineString):Integer* Returns 1 (TRUE) if this
+ MultiLineString is closed (StartPoint() = EndPoint() for each
+LineString in this MultiLineString)
+
+
+ Polygon functions
+
+ * *Area(p:Polygon):Double* The area of this Polygon, as measured in
+ the spatial reference system of this Polygon.
+ * *Centroid(p:Polygon):Point* The mathematical centroid for this
+ Polygon as a Point. The result is not guaranteed to be on this
+ Polygon.
+ * *PointOnSurface(p:Polygon):Point* A point guaranteed to be on this
+ Polygon.
+ * *NumInteriorRing(p:Polygon):Integer* Returns the number of
+ interior rings in this Polygon.
+ * *ExteriorRing(p:Polygon):LineString* Returns the exterior ring of
+ this Polygon as a LineString.
+ * *InteriorRingN(p:Polygon,N:Integer):LineString* Returns the Nth
+interior ring for this Polygon as a LineString.
+
+
+ MultiPolygon functions
+
+ * *Area(m:MultuSurface):Double* The area of this MultiPolygon, as
+ measured in the spatial reference system of this MultiPolygon.
+ * *Centroid(m:MultyPolygon):Point* The mathematical centroid for
+ this MultiPolygon as a Point. The result is not guaranteed to be
+ on this MultiPolygon.
+ * *PointOnSurface(m:MultuPolygon):Point* A Point guaranteed to be on
+this MultiPolygon.
+
+Notes: /functions for specific geometry type retrun NULL if passed
+object type is incorrect. For example Area() returns NULL if object type
+is neither Polygon nor MultiPolygon/
+
+
+ 4.3 Spatial operations (compound spatial constructors)
+
+ * |*Envelope(g:Geometry):Geometry*|The minimum bounding box for this
+ Geometry, returned as a Geometry. The polygon is defined by the
+ corner points of the bounding box
+ |POLYGON((MINX,MINY),(MAXX,MINY),(MAXX,MAXY),(MINX,MAXY),(MINX,MINY))|.
+
+ * |*Boundary(g:Geometry):Geometry*| - returns the closure of the
+ combinatorial boundary of this Geometry.
+ * |*Intersection(g1,g2:Geometry):Geometry*| - a geometry that
+ represents the point set intersection of g1 with g2.
+ * |*Union(g1,g2:Geometry):Geometry*| - a geometry that represents
+ the point set union of g1 with g2.
+ * |*Difference(g1,g2:Geometry):Geometry*| - a geometry that
+ represents the point set difference of g1 with g2.
+ * |*SymDifference(g1,g2:Geometry):Geometry*| - a geometry that
+ represents the point set symmetric difference of g1 with g2.
+ * |*Buffer(g:Geometry,distance:Double):Geometry*| - a geometry that
+ represents all points whose distance from g is less than or equal
+ to distance.
+ * |*ConvexHull(g:Geometry):Geometry*| - a geometry that represents
+the convex hull of g.
+
+
+ 4.4 Functions for testing Spatial Relations between geometric objects
+
+ * |*Equals(g1,g2)*| - Returns 1 if g1 is spatially equal to g2.
+ * |*Disjoint(g1,g2)*| - Returns 1 if g1 is spatially disjoint from g2.
+ * |*Intersects(g1,g2)*| - Returns 1 if g1 spatially intersects g2.
+ * |*Touches(g1,g2)*| - Returns 1 if g1 spatially touches g2.
+ * |*Crosses(g1,g2)*| - Returns 1 if g1 spatially crosses g2.
+ * |*Within(g1,g2)*| - Returns 1 if g1 is spatially within g2.
+ * |*Contains(g1,g2)*| - Returns 1 if g1 spatially contains g2.
+* |*Overlaps(g1,g2)*| - Returns 1 if g1 spatially overlaps g2.
+
+
+ 5 Optimizing spatial analysis
+
+
+ 5.1 MBR
+
+MBR is a minimal bounding rectangle (box) for spatial object. It can be
+represented as a set of min and max values of each dimension.
+
+For example:
+
+(Xmin,Xmax,Ymin,Ymax)
+
+
+ 5.2 Using SPATIAL indexes
+
+To optimize spatial object relationships analysis it is possible to
+create a spatial index on geometry field using R-tree algorythm. R-tree
+based spatial indexes store MBRs of spatial objects as a key values.
+
+CREATE SPATIAL INDEX gind ON geom (g);
+
+Or together with table definition:
+
+CREATE TABLE geom (
+ g GEOMETRY,
+ SPATIAL INDEX(g)
+);
+
+Optimizer attaches R-tree based SPATIAL index when a query with spatial
+objects relationship functions is executed in WHERE clause.
+
+For example:
+
+SELECT geom.name FROM geom
+ WHERE Within(geom.g,GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))',SRID));
+
+
+ 8 OpenGIS extensions implemented in MySQL
+
+MySQL provides it's own constructors to build geometry objects:
+
+ * |*Point(double,double,SRID)*| - constructs a geometry of Point
+ class using it's coordinates and SRID.
+ * |*MultiPoint(Point,Point,...,Point)*| - constructs a MultiPoint
+ using Points. When any argument is not a geometry of Point class
+ the return value is NULL.
+ * |*LineString(Point,Point,...,Point)*| - constructs a LineString
+ from a number of Points. When any argument is not a geometry of
+ Point class the return value is NULL. When the number of Points is
+ less than two the return value is NULL.
+ * |*MultiLineString(LineString,LineString,...,LineString)*| -
+ constructs a MultiLineString using using LineStrings. When any
+ argument is not a geometry of LineStringClass return value is NULL.
+ * |*Polygon(LineString,LineString,...,LineString)*| - constructs a
+ Polygon from a number of LineStrings. When any argument is not a
+ LinearRing (i.e. not closed and simple geometry of class
+ LineString) the return value is NULL.
+ * |*MultiPolygon(Polygon,Polygon,...,Polygon)*| - constructs a
+ MultiPolygon from a set of Polygons. When any argument is not a
+ Polygon, the rerurn value is NULL.
+ * |*GeometryCollection(Geometry,Geometry,..,Geometry)*| - constucts
+ a GeometryCollection. When any argument is not a valid geometry
+object of any instantiable class, the return value is NULL.
+
+The above functions (except Point()) return NULL if arguments are not in
+the same spatial reference system (i.e. have different SRIDs).
+
+
+ Examples:
+
+INSERT INTO geom SELECT Point(x,y,SRID) FROM coords;
+SELECT AsText(g) FROM geom WHERE
+ Contains(Polygon(LineString(Point(0,0),Point(0,1),Point(1,1),Point(1,0),Point(0,0)),SRID),geom.g);
+
+
+ 9 Things that differ in MySQL implemention and OpenGIS specifications
+
+
+ 9.1 Single GEOMETRY type
+
+Besides a GEOMETRY type, OpenGIS consortium specifications suggest the
+implementation of several spatial field types correspondent to every
+instansiable object subclass. For example a *Point* type is proposed to
+restrict data stored in a field of this type to only Point OpenGIS
+subclass. MySQL provides an implementation of single GEOMETRY type which
+doesn't restrict objects to certain OpenGIS subclass. Other proposed
+spatial field types are mapped into GEOMETRY type, so all these types
+can be used as a symonym for GEOMETRY: POINT, MULTIPOINT, LINESTRING,
+MULTILINESTRING, POLYGON, MULTIPOLYGON.
+
+
+ 9.2 No additional Metadata Views
+
+OpenGIS specifications propose several additional metadata views. For
+example, a system view named GEOMETRY_COLUMNS contains a description of
+geometry columns, one row for each geometry column in the database.
+
+
+ 9.3 No functions to add/drop spatial columns
+
+OpenGIS assumes that columns can be added/dropped using
+AddGeometryColumn() and DropGeometryColumn() functions correspondently.
+In MySQL implementation one should use ALTER TABLE instead.
diff --git a/Docs/internals.texi b/Docs/internals.texi
index a94158f84f8..eac0fd11a07 100644
--- a/Docs/internals.texi
+++ b/Docs/internals.texi
@@ -1719,9 +1719,16 @@ The field description result set contains the meta info for a result set.
@item string @tab Table name alias (or table name if no alias)
@item string @tab Real table name
@item string @tab Alias for column name (or column name if not used)
+
+@item 11 byte @tab Fixed length fields in one field part:
+@itemize
+@item 2 byte int @tab Character set number
@item 3 byte int @tab Length of column definition
@item 1 byte int @tab Enum value for field type
@item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals.
+@item 2 byte int @tab zero (reserved for future use)
+@end itemize
+
@item string int @tab Default value, only set when using mysql_list_fields().
@end multitable
diff --git a/Docs/prepare.texi b/Docs/prepare.texi
new file mode 100755
index 00000000000..0b515012980
--- /dev/null
+++ b/Docs/prepare.texi
@@ -0,0 +1,1736 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright 1997-2002 TcX AB, Detron HB and MySQL Finland AB
+@c
+@c This manual is NOT distributed under a GPL style license.
+@c Use of the manual is subject to the following terms:
+@c - Conversion to other formats is allowed, but the actual
+@c content may not be altered or edited in any way.
+@c - You may create a printed copy for your own personal use.
+@c - For all other uses, such as selling printed copies or
+@c using (parts of) the manual in another publication,
+@c prior written agreement from MySQL AB is required.
+@c
+@c Please e-mail docs@mysql.com for more information or if
+@c you are interested in doing a translation.
+@c
+@c *********************************************************
+@c Note that @node names are used on our web site.
+@c So do not change node names without checking
+@c Makefile.am and SitePages first.
+@c *********************************************************
+@c
+@c %**start of header
+
+@c there's a better way to do this... i just don't know it yet
+@c sed will remove the "@c ifnusphere " to make this valid
+@c ifnusphere @set nusphere 1
+
+@setfilename prepare.info
+
+@c We want the types in the same index
+@c @syncodeindex tp fn
+
+@c Get version information. This file is generated by the Makefile!!
+@include include.texi
+
+@ifclear tex-debug
+@c This removes the black squares in the right margin
+@finalout
+@end ifclear
+
+@c Set background for HTML
+@set _body_tags BGCOLOR=#FFFFFF TEXT=#000000 LINK=#101090 VLINK=#7030B0
+@c Set some style elements for the manual in HTML form. 'suggested'
+@c natural language colors: aqua, black, blue, fuchsia, gray, green,
+@c lime, maroon, navy, olive, purple, red, silver, teal, white, and
+@c yellow. From Steeve Buehler <ahr@YogElements.com>
+@set _extra_head <style> code {color:purple} tt {color:green} samp {color:navy} pre {color:maroon} </style>
+
+@settitle MySQL Prepared Statements
+
+@c We want single-sided heading format, with chapters on new pages. To
+@c get double-sided format change 'on' below to 'odd'
+@ifclear nusphere
+@setchapternewpage on
+@end ifclear
+
+@ifset nusphere
+@setchapternewpage odd
+@end ifset
+
+@c @paragraphindent 0
+
+@ifset nusphere
+@smallbook
+@end ifset
+
+@c @titlepage
+@c @sp 10
+@c @center @titlefont{MySQL Prepared Statements}
+@c @sp 10
+@c @right Copyright @copyright{} 1995-2003 MySQL AB
+@c blank page after title page makes page 1 be a page front.
+@c also makes the back of the title page blank.
+@c @page
+@c @end titlepage
+
+@c Short contents, blank page, long contents.
+@c until i can figure out the blank page, no short contents.
+@c @shortcontents
+@c @page
+@c @page
+@contents
+
+@c This should be added. The HTML conversion also needs a MySQL version
+@c number somewhere.
+
+@iftex
+@c change this to double if you want formatting for double-sided
+@c printing
+@headings single
+@end iftex
+
+@c @node Top, MySQL C API, (dir), (dir)
+
+@c @menu
+@c * MySQL C API::
+@c @end menu
+
+@c @node MySQL C API, , Top, Top
+@c @chapter MySQL C API
+
+@c @menu
+@c * Prepared statements::
+@c @end menu
+
+@node Top, MySQL prepared statements, (dir), (dir)
+
+@menu
+* MySQL prepared statements::
+@end menu
+
+@node MySQL prepared statements, , Top, Top
+@chapter MySQL Prepared Statements
+
+@menu
+* C Prepared statements::
+* C Prepared statement datatypes::
+* C Prepared statements function overview::
+* C Prepared statement functions::
+* multiple queries::
+* date handling::
+@end menu
+
+@node C Prepared statements, C Prepared statement datatypes, MySQL prepared statements, MySQL prepared statements
+@subsection C Prepared Statements
+
+@sp 1
+
+From MySQL 4.1 and above, you can also make use of the prepared
+statements using the statement handler 'MYSQL_STMT', which supports
+simultanious query executions along with input and output binding.
+
+@sp 1
+
+Prepared execution is an efficient way to execute a statement more than
+once. The statement is first parsed, or prepared. This is executed one
+or more times at a later time using the statement handle that is
+returned during the prepare.
+
+@sp 1
+
+Another advantage of prepared statements is that, it uses a binary protocol
+which makes the data tranfer between client and server in a more efficient
+way than the old MySQL protocol.
+
+@sp 1
+
+Prepared execution is faster than direct execution for statements
+executed more than once, primarly becuase the query is parsed only
+once; In the case of direct execution, the query is parsed every
+time. Prepared execution also can provide a reduction in the network
+traffic becuase during the execute call, it only sends the data for the
+parameters.
+
+
+
+@node C Prepared statement datatypes, C Prepared statements function overview, C Prepared statements, MySQL prepared statements
+@subsection C Prepared Statements DataTypes
+
+Prepared statements mainly uses the following two @code{MYSQL_STMT} and
+@code{MYSQL_BIND} structures:
+@sp 1
+
+@table @code
+@tindex MYSQL_STMT C type
+
+@item MYSQL_STMT
+
+This structure represents a statement handle to prepared statements.It
+is used for all statement related functions.
+
+@sp 1
+
+The statement is initialized when the query is prepared using
+@code{mysql_prepare()}.
+
+@sp 1
+
+One connection can have 'n' statement handles, and the limit depends up on
+the system resources.
+
+@sp 1
+
+@tindex MYSQL_BIND C type
+
+@item MYSQL_BIND
+
+This structure is used in order to bind parameter
+buffers(@code{mysql_bind_param()}) inorder to the parameters data to
+@code{mysql_execute()} call; as well as to bind row
+buffers(@code{mysql_bind_result()}) to fetch the result set data using
+@code{mysql_fetch()}.
+
+@sp 1
+
+@noindent
+The @code{MYSQL_BIND} structure contains the members listed here:
+
+
+@table @code
+
+@item enum enum_field_types buffer_type [input]
+The type of the buffer. The @code{type} value must be one of the following:
+
+
+@itemize @bullet
+@item @code{MYSQL_TYPE_TINY}
+@item @code{MYSQL_TYPE_SHORT}
+@item @code{MYSQL_TYPE_LONG}
+@item @code{MYSQL_TYPE_LONGLONG}
+@item @code{MYSQL_TYPE_FLOAT}
+@item @code{MYSQL_TYPE_DOUBLE}
+@item @code{MYSQL_TYPE_TIME}
+@item @code{MYSQL_TYPE_DATE}
+@item @code{MYSQL_TYPE_DATETIME}
+@item @code{MYSQL_TYPE_TIMESTAMP}
+@item @code{MYSQL_TYPE_STRING}
+@item @code{MYSQL_TYPE_VAR_STRING}
+@item @code{MYSQL_TYPE_TINY_BLOB}
+@item @code{MYSQL_TYPE_MEDIUM_BLOB}
+@item @code{MYSQL_TYPE_LONG_BLOB}
+@item @code{MYSQL_TYPE_BLOB}
+@end itemize
+@sp 1
+
+@item void *buffer [input/output]
+A pointer to a buffer for the parameters data in case if it is used to
+supply parameters data or pointer to a buffer in which to return the
+data when the structure is used for result set bind.
+
+@sp 1
+
+@item unsigned long buffer_length [input]
+Length of the @code{*buffer} in bytes. For character and binary C data,
+the buffer_length specifies the length of the @code{*buffer} to be used
+as a parameter data in case if it is used with @code{mysql_bind_param()}
+or to return that many bytes when fetching results when this is used
+with @code{mysql_bind_result()}.
+
+
+@item long *length [input/output]
+Pointer to the buffer for the parameter's length. When the structure is
+used as a input parameter data binding, then this argument points to a
+buffer that, when @code{mysql_execute()} is called, contains the length
+of the parameter value stored in *buffer. This is ignored except for
+character or binary C data.
+
+If the length is a null pointer, then the protocol assumes that all
+character and binary data are null terminated.
+
+When this structure is used in output binding, then @code{mysql_fetch()}
+return the the length of the data that is returned.
+
+@sp 1
+
+@item bool *is_null [input/output]
+Indicates if the parameter data is NULL or fetched data is NULL.
+@end table
+
+@sp 1
+
+@tindex MySQL C type
+
+@item MYSQL_TIME
+
+This structure is used to send and receive DATE, TIME and
+TIMESTAMP data directly to/from server.
+
+@sp 1
+
+@noindent
+The @code{MYSQL_TIME} structure contains the members listed here:
+
+@multitable @columnfractions .20 .20 .68
+
+@item @strong{Member} @tab @strong{Type} @tab @strong{Description}
+
+@item @code{year} @tab unsigned int @tab Year.
+@item @code{month} @tab unsigned int @tab Month of the year.
+@item @code{day} @tab unsigned int @tab Day of the month.
+@item @code{hour} @tab unsigned int @tab Hour of the day(TIME).
+@item @code{minute} @tab unsigned int @tab Minute of the hour.
+@item @code{second} @tab unsigned int @tab Second of the minute.
+@item @code{neg} @tab my_bool @tab A boolean flag to
+indicate if the time is negative.
+@item @code{second_part} @tab unsigned long @tab Fraction part of the
+second(not yet used)
+@end multitable
+@end table
+
+
+@node C Prepared statements function overview, C Prepared statement functions, C Prepared statement datatypes, MySQL prepared statements
+@subsection C Prepared Statements Function Overview
+
+@cindex C Prepared statements API, functions
+@cindex functions, C Prepared statements API
+
+The functions available in the prepared statements are listed here and
+are described in greater detail in the later section.
+@xref{C Prepared statement functions}.
+
+@multitable @columnfractions .32 .68
+@item @strong{Function} @tab @strong{Description}
+
+@item @strong{mysql_prepare()} @tab Prepares an SQL string for execution.
+
+@item @strong{mysql_param_count()} @tab Returns the number of parameters in a prepared SQL statement.
+
+@item @strong{mysql_prepare_result()} @tab Returns prepared statement meta information in the form of resultset.
+
+@item @strong{mysql_bind_param()} @tab Binds a buffer to parameter markers in a prepared SQL statement.
+
+@item @strong{mysql_execute()} @tab Executes the prepared statement.
+
+@item @strong{mysql_stmt_affected_rows()} @tab Returns the number of rows changes/deleted/inserted by the last UPDATE,DELETE,or INSERT query
+
+@item @strong{mysql_bind_result()} @tab Binds application data buffers
+to columns in the resultset.
+
+@item @strong{mysql_stmt_store_result()} @tab Retrieves the complete result set to the client
+
+@item @strong{mysql_fetch()} @tab Fetches the next rowset of data from the result set and returns data for all bound columns.
+
+@item @strong{mysql_stmt_close()} @tab Frees memory used by prepared statement.
+
+@item @strong{mysql_stmt_errno()} @tab Returns the error number for the last statement execution.
+
+@item @strong{mysql_stmt_error()} @tab Returns the error message for the last statement execution.
+
+@item @strong{mysql_send_long_data()} @tab Sends long data in chunks to server.
+
+@c TO BE MOVED TO MAIN C API FUCTIONS
+@item @strong{mysql_commit()} @tab Commits the transaction.
+
+@item @strong{mysql_rollback()} @tab Rollbacks the transaction.
+
+@item @strong{mysql_autocommit()} @tab Toggles the autocommit mode to on/off.
+
+@item @strong{mysql_more_results()} @tab Returns if there are any more results exists
+
+@item @strong{mysql_next_result()} @tab Returns/Initiates the next result in the multi-query executions
+
+@end multitable
+
+@sp 1
+
+Call @code{mysql_prepare()} to prepare and initialize the statement
+handle, then call @code{mysql_bind_param()} to supply the parameters
+data, and then call @code{mysql_execute()} to execute the query. You can
+repeat the @code{mysql_execute()} by changing parameter values from the
+respective buffer supplied through @code{mysql_bind_param()}.
+
+@sp 1
+
+
+In case if the query is a SELECT statement or any other query which
+results in a resultset, then mysql_prepare() will also return the result
+set meta data information in the form of @code{MYSQL_RES } result set
+through @code{mysql_prepare_result()}.
+
+@sp 1
+
+You can supply the result buffers using @code{mysql_bind_result()}, so
+that the @code{mysql_fetch()} will automatically returns data to this
+buffers. This is row by row fetching.
+
+@sp 1
+
+You can also send the text or binary data in chunks to server using
+@code{mysql_send_long_data()}, by specifying the option is_long_data=1
+or length=MYSQL_LONG_DATA or -2 in the MYSQL_BIND structure supplied
+with @code{mysql_bind_param()}.
+
+@sp 1
+
+Once the statement execution is over, it must be freed using
+@code{mysql_stmt_close} so that it frees all the alloced resources for
+the statement handle.
+
+
+@subsubheading Execution Steps:
+
+To prepare and execute a statement, the application:
+
+@itemize @bullet
+@item
+Calls @strong{mysql_prepare()} and passes it a string containing the SQL
+statement. On a successful prepare, mysql_prepare returns the valid statement
+handle back to the application
+@item
+If the query results in a resultset, then @strong{mysql_prepare_result}
+returns the result set meta info..
+@item
+Sets the values of any parameters using @strong{mysql_bind_param}. All
+parameters must be set; else it will return an error or produce
+un-expected results
+@item
+Calls @strong{mysql_execute} to execute the statement.
+@item
+Repeat steps 2 and 3 as necessary, by changing the parameter values and
+re-executing the statement.
+@item
+Bind the data buffers to return the row values, if it is a result set
+query; using @strong{mysql_bind_result()}.
+@item
+Fetch the data to buffers row by row by calling @strong{mysql_fetch()}
+repetedely until no more rows found.
+@item
+When @strong{mysql_prepare()} is called, in the MySQL client/server protocol:
+@itemize @minus
+@item
+Server parses the query and sends the ok status back to client by
+assinging a statement id. It also sends total number of parameters,
+columns count and its meta information if it is a result set oriented
+query. All syntax and symantecs of the query is checked during this call
+by the server.
+@item
+Client uses this statement id for the further executions, so that server
+identifies the statement back from the pool of statements. Now, client
+allocates a statement handle with this id and returns back to
+application.
+@end itemize
+@item
+When @strong{mysql_execute()} is called, in the MySQL client/server protocol:
+@itemize @minus
+@item
+Client uses the statement handle and sends the parameters data to
+server.
+@item
+Server identifies the statement using the id provided by the client, and
+replaces the parameter markers with the newly supplied data and executes
+the query. If it results in a result set, then sends the data back to
+client, else sends an OK status with total number of rows
+changes/deleted/inserted.
+@end itemize
+@item
+When @strong{mysql_fetch()} is called, in the MySQL client/server protocol:
+@itemize @minus
+@item
+Client reads the data from the packet row by row and places it to
+application data buffers by doing the necessary conversions. If the
+application buffer type is same as that of field type, then the
+conversions are stright forward.
+@end itemize
+@end itemize
+
+
+
+You can get the statement error code and message using
+@code{mysql_stmt_errno()} and @code{mysql_stmt_error()} respectively.
+
+
+@node C Prepared statement functions, multiple queries, C Prepared statements function overview, MySQL prepared statements
+@subsection C Prepared Statement Function Descriptions
+
+You need to use the following functions when you want to prepare and
+execute the queries.
+
+
+@menu
+* mysql_prepare:: @code{mysql_prepare()}
+* mysql_param_count:: @code{mysql_param_count()}
+* mysql_prepare_result:: @code{mysql_prepare_result()}
+* mysql_bind_param:: @code{mysql_bind_param()}
+* mysql_execute:: @code{mysql_execute()}
+* mysql_stmt_affected_rows:: @code{mysql_stmt_affected_rows()}
+* mysql_bind_result:: @code{mysql_bind_result()}
+* mysql_stmt_store_result:: @code{mysql_stmt_store_result()}
+* mysql_fetch:: @code{mysql_fetch()}
+* mysql_send_long_data:: @code{mysql_send_long_data()}
+* mysql_stmt_close:: @code{mysql_stmt_close()}
+* mysql_stmt_errno:: @code{mysql_stmt_errno()}
+* mysql_stmt_error:: @code{mysql_stmt_error()}
+* mysql_commit:: @code{mysql_commit()}
+* mysql_rollback:: @code{mysql_rollback()}
+* mysql_autocommit:: @code{mysql_autocommit()}
+* mysql_more_results:: @code{mysql_more_results()}
+* mysql_next_result:: @code{mysql_next_result()}
+@end menu
+
+@node mysql_prepare, mysql_param_count, C Prepared statement functions, C Prepared statement functions
+@subsubsection @code{mysql_prepare()}
+
+@findex @code{mysql_prepare()}
+
+@code{MYSQL_STMT * mysql_prepare(MYSQL *mysql, const char *query, unsigned
+long length)}
+
+@subsubheading Description
+
+Prepares the SQL query pointed to by the null-terminated string
+'query'. The query must consist of a single SQL statement. You should
+not add a terminating semicolon (`;`) or \g to the statement.
+
+@sp 1
+The application can include one or more parameter markers in the SQL
+statement. To include a parameter marker, the appication embeds a
+question mark (@code{?}) into the SQL string at the appropriate
+position.
+
+@sp 1
+The markers are legal only in certain places in SQL statements. For
+example, they are not allowed in the select list(the list of columns to
+be returned by a SELECT statement), nor are they allowed as both
+operands of a binary operator such as the equal sign (=), becuase it
+would be impossible to determine the parameter type. In general,
+parameters are legal only in Data Manipulation Languange(DML)
+statements, and not in Data Defination Language(DDL) statements.
+
+@sp 1
+The parameter markers are then bound to application variables using
+@code{mysql_bind_param()}.
+
+
+
+@subsubheading Return Values
+
+@code{MYSQL_STMT} if the prepare was successful. NULL if an error
+occured.
+
+@subsubheading Errors
+
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order
+@item CR_OUT_OF_MEMORY
+Out of memory
+@item CR_SERVER_GONE_ERROR
+The MySQL server has gone away
+@item CR_SERVER_LOST
+The connection to the server was lost during the query
+@item CR_UNKNOWN_ERROR
+An unkown error occured
+@end table
+
+If the prepare is not successful, i.e. when @code{mysql_prepare()} returned a
+NULL statement, errors can be obtained by calling @code{mysql_error()}.
+
+
+@subsubheading Example
+
+For the usage of @code{mysql_prepare()} refer to the Example from
+@ref{mysql_execute,mysql_execute()}.
+
+
+
+
+@node mysql_param_count, mysql_prepare_result, mysql_prepare, C Prepared statement functions
+@subsubsection @code{mysql_param_count()}
+
+@findex @code{mysql_param_count()}
+
+@code{unsigned int mysql_param_count(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+Returns the number of parameter markers present from the prepared query.
+
+@subsubheading Return Values
+
+An unsigned integer representing the number of parameters in a
+statement.
+
+@subsubheading Errors
+
+None
+
+@subsubheading Example
+
+For the usage of @code{mysql_param_count()} refer to the Example from
+@ref{mysql_execute,mysql_execute()}.
+
+
+
+@node mysql_prepare_result, mysql_bind_param, mysql_param_count, C Prepared statement functions
+@subsubsection @code{mysql_prepare_result()}
+
+
+@findex @code{mysql_prepare_result}.
+
+@code{MYSQL_RES *mysql_prepare_result(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+If the @code{mysql_prepare()} resulted in a result set query, then
+@code{mysql_prepare_result()} returns the result set meta data in the form of
+@code{MYSQL_RES} structure; which can further be used to process the
+meta information such as total number of fields and individual field
+information. This resulted result set can be passed as an argument to
+any of the field based APIs in order to process the result set meta data
+information such as:
+
+@itemize @minus
+@item
+mysql_num_fields()
+@item
+mysql_fetch_field()
+@item
+mysql_fetch_field_direct()
+@item
+mysql_fetch_fields()
+@item
+mysql_field_count()
+@item
+mysql_field_seek()
+@item
+mysql_field_tell() and
+@item
+mysql_free_result()
+@end itemize
+
+
+@subsubheading Return Values
+
+A @code{MYSQL_RES} result structure. NULL if no meta information exists from
+the prepared query.
+
+
+@subsubheading Errors
+
+@item CR_OUT_OF_MEMOR
+Out of memory
+@item CR_UNKNOWN_ERROR
+An unknown error occured
+
+None
+
+
+@subsubheading Example
+
+For the usage of @code{mysql_prepare_result()} refer to the Example from
+@ref{mysql_fetch,mysql_fetch()}
+
+
+
+@node mysql_bind_param, mysql_execute, mysql_prepare_result, C Prepared statement functions
+@subsubsection @code{mysql_bind_param()}
+
+@findex @code{mysql_bind_param()}
+
+@code{int mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)}
+
+@subsubheading Description
+
+@code{mysql_bind_param} is used to bind data for the parameter markers
+in the SQL statement from @code{mysql_prepare}. It uses the structure
+MYSQL_BIND to supply the data.
+
+The supported buffer types are:
+
+@itemize @bullet
+@item
+MYSQL_TYPE_TINY
+@item
+MYSQL_TYPE_SHORT
+@item
+MYSQL_TYPE_LONG
+@item
+MYSQL_TYPE_LONGLONG
+@item
+MYSQL_TYPE_FLOAT
+@item
+MYSQL_TYPE_DOUBLE
+@item
+MYSQL_TYPE_TIME
+@item
+MYSQL_TYPE_DATE
+@item
+MYSQL_TYPE_DATETIME
+@item
+MYSQL_TYPE_TIMESTAMP
+@item
+MYSQL_TYPE_STRING
+@item
+MYSQL_TYPE_VAR_STRING
+@item
+MYSQL_TYPE_TINY_BLOB
+@item
+MYSQL_TYPE_MEDIUM_BLOB
+@item
+MYSQL_TYPE_LONG_BLOB
+@end itemize
+
+@subsubheading Return Values
+
+Zero if the bind was successful. Non-zero if an error occured.
+
+@subsubheading Errors
+@table @code
+@item CR_NO_PREPARE_STMT
+No prepared statement exists
+@item CR_NO_PARAMETERS_EXISTS
+No parameters exists to bind
+@item CR_INVALID_BUFFER_USE
+Indicates if the bind is to supply the long data in chunks and if the
+buffer type is non string or binary
+@item CR_UNSUPPORTED_PARAM_TYPE
+The conversion is not supported, possibly the buffer_type is illegal or
+its not from the above list of supported types.
+@item CR_OUT_OF_MEMOR
+Out of memory
+@item CR_UNKNOWN_ERROR
+An unknown error occured
+@end table
+
+@subsubheading Example
+
+For the usage of @code{mysql_bind_param()} refer to the Example from
+@ref{mysql_execute,mysql_execute()}.
+
+
+
+@node mysql_execute, mysql_stmt_affected_rows, mysql_bind_param, C Prepared statement functions
+@subsubsection @code{mysql_execute()}
+
+@findex @code{mysql_execute()}
+
+@code{int mysql_execute(MYSQL_STMT *stmt}.
+
+@subsubheading Description
+
+@code{mysql_execute()} executes the prepared query associated with the
+statement handle. The parameter marker values will be sent to server
+during this call, so that server replaces markers with this newly
+supplied data.
+
+@sp 1
+
+If the statement is UPDATE,DELETE,or INSERT, the total number of
+changed/deletd/inserted values can be found by calling
+@code{mysql_stmt_affected_rows}. If this is a result set query, then one
+must call @code{mysql_fetch()} to fetch the data prior to calling any
+other calls which results in query processing. For more information on
+how to fetch the statement binary data, refer to @ref{mysql_fetch}.
+
+
+@subsubheading Return Values
+
+@code{mysql_execute()} returns the following return values:
+
+@multitable @columnfractions .30 .65
+@item @strong{Return Value} @tab @strong{Description}
+@item 0 @tab Successful
+@item 1 @tab Error occured. Error code and
+message can be obtained by calling @code{mysql_stmt_errno()} and @code{mysql_stmt_error()}.
+@end multitable
+
+
+@subsubheading Errors
+
+@table @code
+@item CR_NO_PREPARE_QUERY
+No query prepared prior to execution
+@item CR_ALL_PARAMS_NOT_BOUND
+Not all parameters data is supplied
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_OUT_OF_MEMORY
+Out of memory.
+@item CR_SERVER_GONE_ERROR
+The MySQL server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+
+@subsubheading Example
+
+The following example explains the uasage of @code{mysql_prepare},
+@code{mysql_param_count}, @code{mysql_bind_param}, @code{mysql_execute}
+and @code{mysql_stmt_affected_rows()}.
+
+@example
+
+MYSQL_BIND bind[3];
+MYSQL_STMT *stmt;
+ulonglong affected_rows;
+long length;
+unsigned int param_count;
+int int_data;
+short small_data;
+char str_data[50], query[255];
+my_bool is_null;
+
+ /* Set autocommit mode to true */
+ mysql_autocommit(mysql, 1);
+
+ if (mysql_query(mysql,"DROP TABLE IF EXISTS test_table"))
+ @{
+ fprintf(stderr, "\n drop table failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ @}
+ if (mysql_query(mysql,"CREATE TABLE test_table(col1 int, col2 varchar(50), \
+ col3 smallint,\
+ col4 timestamp(14))"))
+ @{
+ fprintf(stderr, "\n create table failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ @}
+
+ /* Prepare a insert query with 3 parameters */
+ strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)");
+ if(!(stmt = mysql_prepare(mysql, query, strlen(query))))
+ @{
+ fprintf(stderr, "\n prepare, insert failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ @}
+ fprintf(stdout, "\n prepare, insert successful");
+
+ /* Get the parameter count from the statement */
+ param_count= mysql_param_count(stmt);
+
+ fprintf(stdout, "\n total parameters in insert: %d", param_count);
+ if (param_count != 3) /* validate parameter count */
+ @{
+ fprintf(stderr, "\n invalid parameter count returned by MySQL");
+ exit(0);
+ @}
+
+ /* Bind the data for the parameters */
+
+ /* INTEGER PART */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (char *)&int_data;
+ bind[0].is_null= 0;
+ bind[0].length= 0;
+
+ /* STRING PART */
+ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[1].buffer= (char *)str_data;
+ bind[1].buffer_length= sizeof(str_data);
+ bind[1].is_null= 0;
+ bind[1].length= 0;
+
+ /* SMALLINT PART */
+ bind[2].buffer_type= MYSQL_TYPE_SHORT;
+ bind[2].buffer= (char *)&small_data;
+ bind[2].is_null= &is_null;
+ bind[2].length= 0;
+ is_null= 0;
+
+
+ /* Bind the buffers */
+ if (mysql_bind_param(stmt, bind))
+ @{
+ fprintf(stderr, "\n param bind failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Specify the data */
+ int_data= 10; /* integer */
+ strcpy(str_data,"MySQL"); /* string */
+
+ /* INSERT SMALLINT data as NULL */
+ is_null= 1;
+
+ /* Execute the insert statement - 1*/
+ if (mysql_execute(stmt))
+ @{
+ fprintf(stderr, "\n execute 1 failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ fprintf(stderr, "\n send a bug report to bugs@@lists.mysql.com, by asking why this is not working ?");
+ exit(0);
+ @}
+
+ /* Get the total rows affected */
+ affected_rows= mysql_stmt_affected_rows(stmt);
+
+ fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ if (affected_rows != 1) /* validate affected rows */
+ @{
+ fprintf(stderr, "\n invalid affected rows by MySQL");
+ exit(0);
+ @}
+
+ /* Re-execute the insert, by changing the values */
+ int_data= 1000;
+ strcpy(str_data,"The most popular open source database");
+ small_data= 1000; /* smallint */
+ is_null= 0; /* reset NULL */
+
+ /* Execute the insert statement - 2*/
+ if (mysql_execute(stmt))
+ @{
+ fprintf(stderr, "\n execute 2 failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Get the total rows affected */
+ affected_rows= mysql_stmt_affected_rows(stmt);
+
+ fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ if (affected_rows != 1) /* validate affected rows */
+ @{
+ fprintf(stderr, "\n invalid affected rows by MySQL");
+ exit(0);
+ @}
+
+ /* Close the statement */
+ if (mysql_stmt_close(stmt))
+ @{
+ fprintf(stderr, "\n failed while closing the statement");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* DROP THE TABLE */
+ if (mysql_query(mysql,"DROP TABLE test_table"))
+ @{
+ fprintf(stderr, "\n drop table failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ @}
+ fprintf(stdout, "Success, MySQL prepared statements are working!!!");
+@end example
+
+
+
+
+@node mysql_stmt_affected_rows, mysql_bind_result, mysql_execute, C Prepared statement functions
+@subsubsection @code{mysql_stmt_affected_rows()}
+
+@findex @code{mysql_stmt_affected_rows()}
+
+@code{ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+Returns total number of rows changed by the last execute statement. May
+be called immediatlely after mysql_execute() for UPDATE,DELETE,or INSERT
+statements.For SELECT statements, mysql_stmt_affected rows works like
+mysql_num_rows().
+
+@subsubheading Return Values
+
+An integer greater than zero indicates the number of rows affected or
+retrieved. Zero indicates that no records where updated for an UPDATE
+statement, no rows matched the WHERE clause in the query or that no
+query has yet been executed. -1 indicates that the query returned an
+error or that, for a SELECT query, mysql_stmt_affected_rows() was called
+prior to calling mysql_fetch().
+
+@subsubheading Errors
+
+None.
+
+@subsubheading Example
+
+For the usage of @code{mysql_stmt_affected_rows()} refer to the Example
+from @ref{mysql_execute,mysql_execute()}.
+
+
+
+
+
+@node mysql_bind_result, mysql_stmt_store_result, mysql_stmt_affected_rows, C Prepared statement functions
+@subsubsection @code{mysql_bind_result()}
+
+@findex @code{mysql_bind_result()}
+
+@code{my_bool mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)}
+
+@subsubheading Description
+
+@code{mysql_bind_result()} is used to associate, or bind, columns in the
+resultset to data buffers and length buffers. When @code{mysql_fetch()} is
+called to fetch data, the MySQL client protocol returns the data for the
+bound columns in the specified buffers.
+
+@sp 1
+
+Note that all columns must be bound prior to calling @code{mysql_fetch()}
+in case of fetching the data to buffers; else @code{mysql_fetch()} simply ignores
+the data fetch; also the buffers should be sufficient enough to hold the
+data as the ptotocol doesn't return the data in chunks.
+
+@sp 1
+
+A column can be bound or rebound at any time, even after data has been
+fetched from the result set. The new binding takes effect the next time
+@code{mysql_fetch()} is called. For example, suppose an application binds
+the columns in a result set and calls @code{mysql_fetch()}. The mysql
+protocol returns data in the bound buffers. Now suppose the application
+binds the columns to a different set of buffers, then the protocol does
+not place the data for the just fetched row in the newly bound
+buffers. Instead, it does when the next @code{mysql_fetch()} is called.
+
+@sp 1
+
+To bind a column, an application calls @code{mysql_bind_result()} and
+passes the type, address, and the address of the length buffer.
+
+The supported buffer types are:
+
+@itemize @bullet
+@item
+MYSQL_TYPE_TINY
+@item
+MYSQL_TYPE_SHORT
+@item
+MYSQL_TYPE_LONG
+@item
+MYSQL_TYPE_LONGLONG
+@item
+MYSQL_TYPE_FLOAT
+@item
+MYSQL_TYPE_DOUBLE
+@item
+MYSQL_TYPE_TIME
+@item
+MYSQL_TYPE_DATE
+@item
+MYSQL_TYPE_DATETIME
+@item
+MYSQL_TYPE_TIMESTAMP
+@item
+MYSQL_TYPE_STRING
+@item
+MYSQL_TYPE_VAR_STRING
+@item
+MYSQL_TYPE_BLOB
+@item
+MYSQL_TYPE_TINY_BLOB
+@item
+MYSQL_TYPE_MEDIUM_BLOB
+@item
+MYSQL_TYPE_LONG_BLOB
+@end itemize
+
+@subsubheading Return Values
+
+Zero if the bind was successful. Non-zero if an error occured.
+
+@subsubheading Errors
+
+@table @code
+@item CR_NO_PREPARE_STMT
+No prepared statement exists
+@item CR_UNSUPPORTED_PARAM_TYPE
+The conversion is not supported, possibly the buffer_type is illegal or
+its not from the list of supported types.
+@item CR_OUT_OF_MEMOR
+Out of memory
+@item CR_UNKNOWN_ERROR
+An unknown error occured
+@end table
+
+@subsubheading Example
+
+For the usage of @code{mysql_bind_result()} refer to the Example from
+@ref{mysql_fetch,mysql_fetch()}
+
+
+
+
+@node mysql_stmt_store_result, mysql_fetch, mysql_bind_result, C Prepared statement functions
+@subsubsection @code{mysql_stmt_store_result()}
+
+@findex code{mysql_stmt_store_result()}
+
+@code{int mysql_stmt_store_result(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+You must call @code{mysql_stmt_store_result()} for every query that
+successfully retrieves
+data(@code{SELECT},@code{SHOW},@code{DESCRIBE},@code{EXPLAIN}), and only
+if you want to buffer the complete result set by the client, so that the
+subsequent @code{mysql_fetch()} call returns buffered data.
+
+@sp 1
+
+You don't have to call @code{mysql_stmt_store_result()} for other
+queries, but it will not harm or cause any notable performance in all
+cases.You can detect if the query didn't have a result set by checking
+if @code{mysql_prepare_result()} returns 0. For more information refer
+to @ref{mysql_prepare_result}.
+
+@subsubheading Return Values
+
+@code{Zero} if the results are buffered successfully or @code{Non Zero} in case of an error.
+
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_OUT_OF_MEMORY
+Out of memory.
+@item CR_SERVER_GONE_ERROR
+The MySQL server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+
+
+@node mysql_fetch, mysql_send_long_data, mysql_stmt_store_result, C Prepared statement functions
+@subsubsection @code{mysql_fetch()}
+
+@findex code{mysql_fetch()}
+
+@code{int mysql_fetch(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+@code{mysql_fetch()} returns the next rowset in the result set. It can
+be called only while the result set exists i.e. after a call to
+@code{mysql_execute()} that creates a result set or after
+@code{mysql_stmt_store_result()}, which is called after
+@code{mysql_execute()} to buffer the entire resultset.
+
+@sp 1
+
+If row buffers are bound using @code{mysql_bind_result()}, it returns
+the data in those buffers for all the columns in the current row
+set and the lengths are returned to the length pointer.
+
+@sp 1
+Note that, all columns must be bound by the application.
+
+@sp 1
+If the data fetched is a NULL data, then the @code{is_null} value from
+@code{MYSQL_BIND} contains TRUE, 1, else the data and its length is
+returned to @code{*buffer} and @code{*length} variables based on the
+buffer type specified by the application. All numeric, float and double
+types have the fixed length(in bytes) as listed below:
+
+
+@multitable @columnfractions .10 .30
+@item @strong{Type} @tab @strong{Length}
+@item MYSQL_TYPE_TINY @tab 1
+@item MYSQL_TYPE_SHORT @tab 2
+@item MYSQL_TYPE_LONG @tab 4
+@item MYSQL_TYPE_FLOAT @tab 4
+@item MYSQL_TYPE_LONGLONG @tab 8
+@item MYSQL_TYPE_DOUBLE @tab 8
+@item MYSQL_TYPE_TIME @tab sizeof(MYSQL_TIME)
+@item MYSQL_TYPE_DATE @tab sizeof(MYSQL_TIME)
+@item MYSQL_TYPE_DATETIME @tab sizeof(MYSQL_TIME)
+@item MYSQL_TYPE_TIMESTAMP @tab sizeof(MYSQL_TIME)
+@item MYSQL_TYPE_STRING @tab data length
+@item MYSQL_TYPE_VAR_STRING @tab data_length
+@item MYSQL_TYPE_BLOB @tab data_length
+@item MYSQL_TYPE_TINY_BLOB @tab data_length
+@item MYSQL_TYPE_MEDIUM_BLOB @tab data_length
+@item MYSQL_TYPE_LONG_BLOB @tab data_length
+@end multitable
+
+@*
+where @code{*data_length} is nothing but the 'Actual length of the data'.
+
+@subsubheading Return Values
+
+@multitable @columnfractions .30 .65
+@item @strong{Return Value} @tab @strong{Description}
+@item 0 @tab Successful, the data has been
+fetched to application data buffers.
+@item 1 @tab Error occured. Error code and
+message can be obtained by calling @code{mysql_stmt_errno()} and @code{mysql_stmt_error()}.
+@item 100, MYSQL_NO_DATA @tab No more rows/data exists
+@end multitable
+
+
+@subsubheading Errors
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_OUT_OF_MEMORY
+Out of memory.
+@item CR_SERVER_GONE_ERROR
+The MySQL server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@item CR_UNSUPPORTED_PARAM_TYPE
+If the buffer type is MYSQL_TYPE_DATE,DATETIME,TIME,or TIMESTAMP; and if
+the field type is not DATE, TIME, DATETIME or TIMESTAMP.
+@item
+All other unsupported conversion errors are returned from
+@code{mysql_bind_result()}.
+@end table
+
+@subsubheading Example
+
+The following example explains the usage of @code{mysql_prepare_result},
+@code{mysql_bind_result()}, and @code{mysql_fetch()}
+
+@example
+
+MYSQL_STMT *stmt;
+MYSQL_BIND bind[2];
+MYSQL_RES *result;
+int int_data;
+long int_length, str_length;
+char str_data[50];
+my_bool is_null[2];
+
+ query= "SELECT col1, col2 FROM test_table WHERE col1= 10)");
+ if (!(stmt= mysql_prepare(&mysql, query, strlen(query)))
+ @{
+ fprintf(stderr, "\n prepare failed");
+ fprintf(stderr, "\n %s", mysql_error(&stmt));
+ exit(0);
+ @}
+
+ /* Get the fields meta information */
+ if (!(result= mysql_prepare_result(stmt)))
+ @{
+ fprintf(stderr, "\n prepare_result failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ fprintf(stdout, "Total fields: %ld", mysql_num_fields(result));
+
+ if (mysql_num_fields(result) != 2)
+ @{
+ fprintf(stderr, "\n prepare returned invalid field count");
+ exit(0);
+ @}
+
+ /* Execute the SELECT query */
+ if (mysql_execute(stmt))
+ @{
+ fprintf(stderr, "\n execute failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Bind the result data buffers */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (char *)&int_data;
+ bind[0].is_null= &is_null[0];
+ bind[0].length= &int_length;
+
+ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[1].buffer= (void *)str_data;
+ bind[1].is_null= &is_null[1];
+ bind[1].length= &str_length;
+
+ if (mysql_bind_result(stmt, bind))
+ @{
+ fprintf(stderr, "\n bind_result failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Now fetch data to buffers */
+ if (mysql_fetch(stmt))
+ @{
+ fprintf(stderr, "\n fetch failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ if (is_null[0])
+ fprintf(stdout, "\n Col1 data is NULL");
+ else
+ fprintf(stdout, "\n Col1: %d, length: %ld", int_data, int_length);
+
+ if (is_null[1])
+ fprintf(stdout, "\n Col2 data is NULL");
+ else
+ fprintf(stdout, "\n Col2: %s, length: %ld", str_data, str_length);
+
+
+ /* call mysql_fetch again */
+ if (mysql_fetch(stmt) |= MYSQL_NO_DATA)
+ @{
+ fprintf(stderr, "\n fetch return more than one row);
+ exit(0);
+ @}
+
+ /* Free the prepare result meta information */
+ mysql_free_result(result);
+
+ /* Free the statement handle */
+ if (mysql_stmt_free(stmt))
+ @{
+ fprintf(stderr, "\n failed to free the statement handle);
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+@end example
+
+
+
+@node mysql_send_long_data, mysql_stmt_close, mysql_fetch, C Prepared statement functions
+@subsubsection @code{mysql_send_long_data()}
+
+
+@findex @code{mysql_send_long_data()}.
+
+@code{int mysql_send_long_data(MYSQL_STMT *stmt, unsigned int
+parameter_number, const char *data, ulong length)}
+
+@subsubheading Description
+
+Allows an application to send the data in pieces or chunks to
+server. This function can be used to send character or binary data
+values in parts to a column(it must be a text or blob) with a character or
+binary data type.
+
+@sp 1
+The @code{data} is a pointer to buffer containing the actual data for
+the parameter represendted by @code{parameter_number}. The @code{length}
+indicates the amount of data to be sent in bytes.
+
+
+@subsubheading Return Values
+
+Zero if the data is sent successfully to server. Non-zero if an error
+occured.
+
+
+@subsubheading Errors
+
+@table @code
+@item CR_INVALID_PARAMETER_NO
+Invalid parameter number
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The MySQL server has gone away
+@item CR_OUT_OF_MEMOR
+Out of memory
+@item CR_UNKNOWN_ERROR
+An unknown error occured
+@end table
+
+@subsubheading Example
+The following example explains how to send the data in chunks to text
+column:
+@example
+
+MYSQL_BIND bind[1];
+long length;
+
+ query= "INSERT INTO test_long_data(text_column) VALUES(?)");
+ if (!mysql_prepare(&mysql, query, strlen(query))
+ @{
+ fprintf(stderr, "\n prepare failed");
+ fprintf(stderr, "\n %s", mysql_error(&stmt));
+ exit(0);
+ @}
+ memset(bind, 0, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].length= &length;
+ bind[0].is_null= 0;
+
+ /* Bind the buffers */
+ if (mysql_bind_param(stmt, bind))
+ @{
+ fprintf(stderr, "\n param bind failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Supply data in chunks to server */
+ if (!mysql_send_long_data(stmt,1,"MySQL",5))
+ @{
+ fprintf(stderr, "\n send_long_data failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Supply the next piece of data */
+ if (mysql_send_long_data(stmt,1," - The most popular open source database",40))
+ @{
+ fprintf(stderr, "\n send_long_data failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ /* Now, execute the query */
+ if (mysql_execute(stmt))
+ @{
+ fprintf(stderr, "\n mysql_execute failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ @}
+
+ This inserts the data, "MySQL - The most popular open source database"
+ to the field 'text_column'.
+@end example
+
+
+
+@node mysql_stmt_close, mysql_stmt_errno, mysql_send_long_data, C Prepared statement functions
+@subsubsection @code{mysql_stmt_close()}
+
+@findex @code{mysql_stmt_close()}
+
+@code{my_bool mysql_stmt_close(MYSQL_STMT *)}
+
+@subsubheading Description
+
+Closes the prepared statement. @code{mysql_stmt_close()} also
+deallocates the statement handle pointed to by @code{stmt}.
+
+If the current query results are pending or un-read; this cancels the
+query results; so that next call can be executed.
+
+@subsubheading Return Values
+
+Zero if the statement was freed successfully. Non-zero if an error occured.
+
+
+@subsubheading Errors
+
+@table @code
+@item CR_SERVER_GONE_ERROR
+The MySQL server has gone away
+@item CR_UNKNOWN_ERROR
+An unkown error occured
+@end table
+
+@subsubheading Example
+
+For the usage of @code{mysql_stmt_close()} refer to the Example from
+@ref{mysql_execute,mysql_execute()}.
+
+
+
+@node mysql_stmt_errno, mysql_stmt_error, mysql_stmt_close, C Prepared statement functions
+@subsubsection @code{mysql_stmt_errno()}
+
+
+@findex @code{mysql_stmt_errno()}
+
+@code{unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+For the statement specified by @code{stmt}, @code{mysql_stmt_errno()}
+returns the error code for the most recently invoked statement API
+function that can succeed or fail. A return value of zero means that no
+error occured. Client error message numbers are listed in the MySQL
+errmsg.h header file. Server error message numbers are listed in
+mysqld_error.h. In the MySQL source distribution you can find a complete
+list of error messages and error numbers in the file Docs/mysqld_error.txt
+
+@subsubheading Return Values
+
+An error code value. Zero if no error occured.
+
+@subsubheading Errors
+
+None
+
+
+@node mysql_stmt_error, mysql_commit, mysql_stmt_errno, C Prepared statement functions
+@subsubsection @code{mysql_stmt_error()}
+
+
+@findex @code{mysql_stmt_error()}.
+
+@code{char *mysql_stmt_error(MYSQL_STMT *stmt)}
+
+@subsubheading Description
+
+For the statement specified by @code{stmt}, @code{mysql_stmt_error()}
+returns the error message for the most recently invoked statement API
+that can succeed or fail. An empty string ("") is returned if no error
+occured. This means the following two sets are equivalent:
+
+@example
+
+if (mysql_stmt_errno(stmt))
+@{
+ // an error occured
+@}
+
+if (mysql_stmt_error(stmt))
+@{
+ // an error occured
+@}
+@end example
+
+The language of the client error messages many be changed by recompiling
+the MySQL client library. Currently you can choose error messages in
+several different languages.
+
+
+@subsubheading Return Values
+
+A character string that describes the error. An empry string if no error
+occured.
+
+@subsubheading Errors
+
+None
+
+
+
+@node mysql_commit, mysql_rollback, mysql_stmt_error, C Prepared statement functions
+@subsubsection @code{mysql_commit()}
+
+
+@findex @code{mysql_commit()}.
+
+@code{my_bool mysql_commit(MYSQL *mysql)}
+
+@subsubheading Description
+
+Commits the current transaction
+
+@subsubheading Return Values
+
+Zero if successful. Non-zero if an error occured.
+
+@subsubheading Errors
+
+None
+
+
+
+@node mysql_rollback, mysql_autocommit, mysql_commit, C Prepared statement functions
+@subsubsection @code{mysql_rollback()}
+
+
+@findex @code{mysql_rollback()}.
+
+@code{my_bool mysql_rollback(MYSQL *mysql)}
+
+@subsubheading Description
+
+Rollbacks the current transaction.
+
+
+@subsubheading Return Values
+
+Zero if successful. Non-zero if an error occured.
+
+@subsubheading Errors
+
+None.
+
+
+
+
+@node mysql_autocommit, mysql_more_results, mysql_rollback, C Prepared statement functions
+@subsubsection @code{mysql_autocommit()}
+
+
+@findex @code{mysql_autocommit()}.
+
+@code{my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)}
+
+@subsubheading Description
+
+Sets the autocommit mode to on or off. If the @code{mode} is '1', then it
+sets the autocommit mode to on, else to off in case of '0'.
+
+@subsubheading Return Values
+
+Zero if successful. Non-zero if an error occured
+
+@subsubheading Errors
+
+None.
+
+
+@node mysql_more_results, mysql_next_result, mysql_autocommit, C Prepared statement functions
+@subsubsection @code{mysql_more_results()}
+
+
+@findex @code{mysql_more_results()}.
+
+@code{my_bool mysql_more_results(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns true if more results exists from the currently executed query,
+and the application must call @code{mysql_next_result()} to fetch the
+results.
+
+
+@subsubheading Return Values
+
+@code{TRUE} if more results exists. @code{FALSE} if no more results exists.
+
+@subsubheading Errors
+
+None.
+
+
+@node mysql_next_result, , mysql_more_results, C Prepared statement functions
+@subsubsection @code{mysql_next_result()}
+
+
+@findex @code{mysql_next_result()}.
+
+@code{int mysql_next_result(MYSQL *mysql)}
+
+@subsubheading Description
+
+If more query results exists, then @code{mysql_next_result()} reads the
+next query results and returns the status back to application.
+
+@subsubheading Return Values
+
+Zero if successful. Non-zero if an error occured
+
+@subsubheading Errors
+
+None.
+
+
+
+@node multiple queries, date handling, C Prepared statement functions, MySQL prepared statements
+@subsection Handling multiple query executions
+
+
+From version 4.1 and above, MySQL supports the multi query execution
+using the single command. In order to do this, you must set the client flag
+@code{CLIENT_MULTI_QUERIES} option during the connection.
+
+@sp 1
+
+By default @code{mysql_query()} or @code{mysql_real_query()} returns
+only the first query status and the subsequent queries status can
+be processed using @code{mysql_more_results()} and
+@code{mysql_next_result()}.
+
+
+@example
+
+ /* Connect to server with option CLIENT_MULTI_QUERIES */
+ mysql_real_query(..., CLIENT_MULTI_QUERIES);
+
+ /* Now execute multiple queries */
+ mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\
+ CREATE TABLE test_table(id int);\
+ INSERT INTO test_table VALUES(10);\
+ UPDATE test_table SET id=20 WHERE id=10;\
+ SELECT * FROM test_table;\
+ DROP TABLE test_table";
+ while (mysql_more_results(mysql))
+ {
+ /* Process all results */
+ mysql_next_result(mysql);
+ ...
+ printf("total affected rows: %lld", mysql_affected_rows(mysql));
+ ...
+ if ((result= mysql_store_result(mysql))
+ {
+ /* Returned a result set, process it */
+ }
+ }
+
+@end example
+
+
+
+@node date handling, , multiple queries, MySQL prepared statements
+@subsection Handling DATE, TIME and TIMESTAMP
+
+Using the new binary protocol from MySQL 4.1 and above, one can send and
+receive the DATE, TIME and TIMESTAMP data using the @code{MYSQL_TIME}
+structure.
+
+@code{MYSQL_TIME} structure consites of the following members:
+
+@itemize @bullet
+@item year
+@item month
+@item day
+@item hour
+@item minute
+@item second
+@item second_part
+@end itemize
+
+
+In order to send the data, one must use the prepared statements through
+@code{mysql_prepare()} and @code{mysql_execute()}; and must bind the
+parameter using type as @code{MYSQL_TYPE_DATE} inorder to process date
+value, @code{MYSQL_TYPE_TIME} for time and @code{MYSQL_TYPE_DATETIME} or
+@code{MYSQL_TYPE_TIMESTAMP} for datetime/timestamp using
+@code{mysql_bind_param()} when sending and @code{mysql_bind_results()}
+while receiving the data.
+
+@sp 1
+Here is a simple example; which inserts the DATE, TIME and TIMESTAMP data.
+
+@example
+
+MYSQL_TIME ts;
+MYSQL_BIND bind[3];
+MYSQL_STMT *stmt;
+
+ strmov(query, "INSERT INTO test_table(date_field, time_field,
+ timestamp_field) VALUES(?,?,?");
+
+ stmt= mysql_prepare(mysql, query, strlen(query)));
+
+ /* setup input buffers for all 3 parameters */
+ bind[0].buffer_type= MYSQL_TYPE_DATE;
+ bind[0].buffer= (char *)&ts;
+ bind[0].is_null= 0;
+ bind[0].length= 0;
+ ..
+ bind[1]= bind[2]= bind[0];
+ ..
+
+ mysql_bind_param(stmt, bind);
+
+ /* supply the data to be sent is the ts structure */
+ ts.year= 2002;
+ ts.month= 02;
+ ts.day= 03;
+
+ ts.hour= 10;
+ ts.minute= 45;
+ ts.second= 20;
+
+ mysql_execute(stmt);
+ ..
+
+@end example
+
+
+@bye
diff --git a/Makefile.am b/Makefile.am
index e69b336a2c0..fc3cc23cf69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,7 +21,8 @@ AUTOMAKE_OPTIONS = foreign
# These are built from source in the Docs directory
EXTRA_DIST = INSTALL-SOURCE README \
COPYING COPYING.LIB
-SUBDIRS = . include @docs_dirs@ @readline_dir@ \
+SUBDIRS = . include @docs_dirs@ \
+ @readline_topdir@ @readline_dir@ \
@thread_dirs@ pstack @sql_client_dirs@ \
@sql_server_dirs@ scripts man tests \
BUILD netware os2 @libmysqld_dirs@ \
@@ -75,6 +76,10 @@ init-db: all
bin-dist: all
$(top_builddir)/scripts/make_binary_distribution
+# Remove BK's "SCCS" subdirectories from source distribution
+dist-hook:
+ rm -rf `find $(distdir) -type d -name SCCS`
+
tags:
support-files/build-tags
.PHONY: init-db bin-dist
diff --git a/VC++Files/bdb/bdb.dsp b/VC++Files/bdb/bdb.dsp
index e8b730f4254..2809e65b793 100644
--- a/VC++Files/bdb/bdb.dsp
+++ b/VC++Files/bdb/bdb.dsp
@@ -25,7 +25,7 @@ CFG=bdb - Win32 Max
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "bdb - Win32 Debug"
@@ -41,14 +41,13 @@ RSC=rc.exe
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../bdb/build_win32" /I "../bdb/include" /D "__WIN32__" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /Fr
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../bdb/build_win32" /I "../bdb" /I "../bdb/dbinc" /D "__WIN32__" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\bdb.lib"
@@ -66,13 +65,13 @@ LIB32=link.exe -lib
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../bdb/build_win32" /I "../bdb/include" /D "__WIN32__" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
# SUBTRACT BASE CPP /Fr
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../bdb/include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /Fo"mysys___Win32_Max/" /Fd"mysys___Win32_Max/" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../bdb" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /Fo"mysys___Win32_Max/" /Fd"mysys___Win32_Max/" /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo /out:"..\lib_debug\bdb.lib"
# ADD LIB32 /nologo /out:"..\lib_release\bdb.lib"
@@ -167,34 +166,6 @@ SOURCE=.\db\crdel_rec.c
# End Source File
# Begin Source File
-SOURCE=.\cxx\cxx_app.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\cxx\cxx_except.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\cxx\cxx_lock.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\cxx\cxx_log.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\cxx\cxx_mpool.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\cxx\cxx_table.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\cxx\cxx_txn.cpp
-# End Source File
-# Begin Source File
-
SOURCE=.\db\db.c
# End Source File
# Begin Source File
@@ -235,6 +206,10 @@ SOURCE=.\common\db_getlong.c
# End Source File
# Begin Source File
+SOURCE=.\common\db_idspace.c
+# End Source File
+# Begin Source File
+
SOURCE=.\db\db_iface.c
# End Source File
# Begin Source File
@@ -255,6 +230,10 @@ SOURCE=.\db\db_method.c
# End Source File
# Begin Source File
+SOURCE=.\db\db_open.c
+# End Source File
+# Begin Source File
+
SOURCE=.\db\db_overflow.c
# End Source File
# Begin Source File
@@ -271,6 +250,14 @@ SOURCE=.\db\db_reclaim.c
# End Source File
# Begin Source File
+SOURCE=.\db\db_remove.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\db\db_rename.c
+# End Source File
+# Begin Source File
+
SOURCE=.\db\db_ret.c
# End Source File
# Begin Source File
@@ -283,6 +270,10 @@ SOURCE=.\env\db_shash.c
# End Source File
# Begin Source File
+SOURCE=.\db\db_truncate.c
+# End Source File
+# Begin Source File
+
SOURCE=.\db\db_upg.c
# End Source File
# Begin Source File
@@ -303,6 +294,26 @@ SOURCE=.\dbm\dbm.c
# End Source File
# Begin Source File
+SOURCE=.\dbreg\dbreg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbreg\dbreg_auto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbreg\dbreg_rec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbreg\dbreg_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\env\env_file.c
+# End Source File
+# Begin Source File
+
SOURCE=.\env\env_method.c
# End Source File
# Begin Source File
@@ -319,6 +330,22 @@ SOURCE=.\env\env_region.c
# End Source File
# Begin Source File
+SOURCE=.\fileops\fileops_auto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fileops\fop_basic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fileops\fop_rec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fileops\fop_util.c
+# End Source File
+# Begin Source File
+
SOURCE=.\hash\hash.c
# End Source File
# Begin Source File
@@ -347,6 +374,10 @@ SOURCE=.\hash\hash_method.c
# End Source File
# Begin Source File
+SOURCE=.\hash\hash_open.c
+# End Source File
+# Begin Source File
+
SOURCE=.\hash\hash_page.c
# End Source File
# Begin Source File
@@ -371,15 +402,15 @@ SOURCE=.\hash\hash_verify.c
# End Source File
# Begin Source File
-SOURCE=.\hsearch\hsearch.c
+SOURCE=.\hmac\hmac.c
# End Source File
# Begin Source File
-SOURCE=.\lock\lock.c
+SOURCE=.\hsearch\hsearch.c
# End Source File
# Begin Source File
-SOURCE=.\lock\lock_conflict.c
+SOURCE=.\lock\lock.c
# End Source File
# Begin Source File
@@ -411,18 +442,10 @@ SOURCE=.\log\log_archive.c
# End Source File
# Begin Source File
-SOURCE=.\log\log_auto.c
-# End Source File
-# Begin Source File
-
SOURCE=.\log\log_compare.c
# End Source File
# Begin Source File
-SOURCE=.\log\log_findckp.c
-# End Source File
-# Begin Source File
-
SOURCE=.\log\log_get.c
# End Source File
# Begin Source File
@@ -435,14 +458,6 @@ SOURCE=.\log\log_put.c
# End Source File
# Begin Source File
-SOURCE=.\log\log_rec.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\log\log_register.c
-# End Source File
-# Begin Source File
-
SOURCE=.\mp\mp_alloc.c
# End Source File
# Begin Source File
@@ -495,6 +510,10 @@ SOURCE=.\mutex\mut_tas.c
# End Source File
# Begin Source File
+SOURCE=.\mutex\mut_win32.c
+# End Source File
+# Begin Source File
+
SOURCE=.\mutex\mutex.c
# End Source File
# Begin Source File
@@ -507,6 +526,14 @@ SOURCE=.\os\os_alloc.c
# End Source File
# Begin Source File
+SOURCE=.\os_win32\os_clock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os_win32\os_config.c
+# End Source File
+# Begin Source File
+
SOURCE=.\os_win32\os_dir.c
# End Source File
# Begin Source File
@@ -519,15 +546,15 @@ SOURCE=.\os_win32\os_fid.c
# End Source File
# Begin Source File
-SOURCE=.\os_win32\os_finit.c
+SOURCE=.\os_win32\os_fsync.c
# End Source File
# Begin Source File
-SOURCE=.\os\os_fsync.c
+SOURCE=.\os_win32\os_handle.c
# End Source File
# Begin Source File
-SOURCE=.\os\os_handle.c
+SOURCE=.\os\os_id.c
# End Source File
# Begin Source File
@@ -563,7 +590,7 @@ SOURCE=.\os\os_rpath.c
# End Source File
# Begin Source File
-SOURCE=.\os\os_rw.c
+SOURCE=.\os_win32\os_rw.c
# End Source File
# Begin Source File
@@ -579,7 +606,7 @@ SOURCE=.\os_win32\os_spin.c
# End Source File
# Begin Source File
-SOURCE=.\os\os_stat.c
+SOURCE=.\os_win32\os_stat.c
# End Source File
# Begin Source File
@@ -635,6 +662,26 @@ SOURCE=.\qam\qam_verify.c
# End Source File
# Begin Source File
+SOURCE=.\rep\rep_method.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rep\rep_record.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rep\rep_region.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rep\rep_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hmac\sha1.c
+# End Source File
+# Begin Source File
+
SOURCE=.\clib\strcasecmp.c
# End Source File
# Begin Source File
@@ -647,11 +694,27 @@ SOURCE=.\txn\txn_auto.c
# End Source File
# Begin Source File
+SOURCE=.\txn\txn_method.c
+# End Source File
+# Begin Source File
+
SOURCE=.\txn\txn_rec.c
# End Source File
# Begin Source File
+SOURCE=.\txn\txn_recover.c
+# End Source File
+# Begin Source File
+
SOURCE=.\txn\txn_region.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\txn\txn_stat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\txn\txn_util.c
# End Source File
# Begin Source File
diff --git a/VC++Files/bdb/build_win32/Berkeley_DB.dsw b/VC++Files/bdb/build_win32/Berkeley_DB.dsw
index 482ac7537f0..899e31ad58d 100644
--- a/VC++Files/bdb/build_win32/Berkeley_DB.dsw
+++ b/VC++Files/bdb/build_win32/Berkeley_DB.dsw
@@ -566,4 +566,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/bdb/build_win32/db_archive.dsp b/VC++Files/bdb/build_win32/db_archive.dsp
index 4b8509950ef..b115caba486 100644
--- a/VC++Files/bdb/build_win32/db_archive.dsp
+++ b/VC++Files/bdb/build_win32/db_archive.dsp
@@ -7,16 +7,16 @@
CFG=db_archive - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_archive.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_archive.mak" CFG="db_archive - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_archive - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_archive - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_archive - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_archive - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_buildall.dsp b/VC++Files/bdb/build_win32/db_buildall.dsp
index 58990dbb867..1f54083d00f 100644
--- a/VC++Files/bdb/build_win32/db_buildall.dsp
+++ b/VC++Files/bdb/build_win32/db_buildall.dsp
@@ -7,23 +7,23 @@
CFG=db_buildall - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_buildall.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_buildall.mak" CFG="db_buildall - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_buildall - Win32 Release" (based on "Win32 (x86) External Target")
!MESSAGE "db_buildall - Win32 Debug" (based on "Win32 (x86) External Target")
!MESSAGE "db_buildall - Win32 Release Static" (based on\
"Win32 (x86) External Target")
!MESSAGE "db_buildall - Win32 Debug Static" (based on\
"Win32 (x86) External Target")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -105,7 +105,7 @@ CFG=db_buildall - Win32 Debug
# PROP Bsc_Name "db_buildall.bsc"
# PROP Target_Dir ""
-!ENDIF
+!ENDIF
# Begin Target
@@ -122,7 +122,7 @@ CFG=db_buildall - Win32 Debug
!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug Static"
-!ENDIF
+!ENDIF
# End Target
# End Project
diff --git a/VC++Files/bdb/build_win32/db_checkpoint.dsp b/VC++Files/bdb/build_win32/db_checkpoint.dsp
index ac464a07ab8..71ee57e1693 100644
--- a/VC++Files/bdb/build_win32/db_checkpoint.dsp
+++ b/VC++Files/bdb/build_win32/db_checkpoint.dsp
@@ -7,16 +7,16 @@
CFG=db_checkpoint - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_checkpoint.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_checkpoint.mak" CFG="db_checkpoint - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_checkpoint - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_checkpoint - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_checkpoint - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_checkpoint - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_deadlock.dsp b/VC++Files/bdb/build_win32/db_deadlock.dsp
index 429896ded04..d9112bace47 100644
--- a/VC++Files/bdb/build_win32/db_deadlock.dsp
+++ b/VC++Files/bdb/build_win32/db_deadlock.dsp
@@ -7,16 +7,16 @@
CFG=db_deadlock - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_deadlock.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_deadlock.mak" CFG="db_deadlock - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_deadlock - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_deadlock - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_deadlock - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_deadlock - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_dll.dsp b/VC++Files/bdb/build_win32/db_dll.dsp
index d394e0313fd..3ec370c1d72 100644
--- a/VC++Files/bdb/build_win32/db_dll.dsp
+++ b/VC++Files/bdb/build_win32/db_dll.dsp
@@ -7,23 +7,23 @@
CFG=db_dll - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_dll.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_dll.mak" CFG="db_dll - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "db_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "db_dll - Win32 Release Static" (based on\
"Win32 (x86) Dynamic-Link Library")
!MESSAGE "db_dll - Win32 Debug Static" (based on\
"Win32 (x86) Dynamic-Link Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -141,7 +141,7 @@ LINK32=link.exe
# ADD BASE LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb32d.dll" /fixed:no
# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb32d.dll" /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_dump.dsp b/VC++Files/bdb/build_win32/db_dump.dsp
index f4808b5138d..dbc183166a4 100644
--- a/VC++Files/bdb/build_win32/db_dump.dsp
+++ b/VC++Files/bdb/build_win32/db_dump.dsp
@@ -7,16 +7,16 @@
CFG=db_dump - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_dump.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_dump.mak" CFG="db_dump - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_dump - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_dump - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_dump - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_dump - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_java.dsp b/VC++Files/bdb/build_win32/db_java.dsp
index 0a0d9dc0fcb..5866d355259 100644
--- a/VC++Files/bdb/build_win32/db_java.dsp
+++ b/VC++Files/bdb/build_win32/db_java.dsp
@@ -7,20 +7,20 @@
CFG=db_java - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_java.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_java.mak" CFG="db_java - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_java - Win32 Release" (based on\
"Win32 (x86) Dynamic-Link Library")
!MESSAGE "db_java - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -60,20 +60,20 @@ InputPath=.\Release\libdb_java32.dll
SOURCE=$(InputPath)
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- cd $(ProjDir)\..\java\src\com\sleepycat\db
- mkdir ..\..\..\..\classes
- echo compiling Berkeley DB classes
+ cd $(ProjDir)\..\java\src\com\sleepycat\db
+ mkdir ..\..\..\..\classes
+ echo compiling Berkeley DB classes
javac -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
- echo compiling examples
- cd ..\examples
+ *.java
+ echo compiling examples
+ cd ..\examples
javac -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
- echo creating jar file
+ *.java
+ echo creating jar file
cd ..\..\..\..\classes
- jar cf db.jar com\sleepycat\db\*.class
- echo Java build finished
-
+ jar cf db.jar com\sleepycat\db\*.class
+ echo Java build finished
+
# End Custom Build
!ELSEIF "$(CFG)" == "db_java - Win32 Debug"
@@ -108,23 +108,23 @@ InputPath=.\Debug\libdb_java32d.dll
SOURCE=$(InputPath)
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- cd $(ProjDir)\..\java\src\com\sleepycat\db
- mkdir ..\..\..\..\classes
- echo compiling Berkeley DB classes
+ cd $(ProjDir)\..\java\src\com\sleepycat\db
+ mkdir ..\..\..\..\classes
+ echo compiling Berkeley DB classes
javac -g -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
- echo compiling examples
+ *.java
+ echo compiling examples
javac -g -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
- cd ..\examples
- echo creating jar file
+ *.java
+ cd ..\examples
+ echo creating jar file
cd ..\..\..\..\classes
- jar cf db.jar com\sleepycat\db\*.class
- echo Java build finished
-
+ jar cf db.jar com\sleepycat\db\*.class
+ echo Java build finished
+
# End Custom Build
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_load.dsp b/VC++Files/bdb/build_win32/db_load.dsp
index adec8475a88..ddd516e67fd 100644
--- a/VC++Files/bdb/build_win32/db_load.dsp
+++ b/VC++Files/bdb/build_win32/db_load.dsp
@@ -7,16 +7,16 @@
CFG=db_load - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_load.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_load.mak" CFG="db_load - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_load - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_load - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_load - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_load - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_printlog.dsp b/VC++Files/bdb/build_win32/db_printlog.dsp
index 8b3fbd9fe31..4e19ff7344a 100644
--- a/VC++Files/bdb/build_win32/db_printlog.dsp
+++ b/VC++Files/bdb/build_win32/db_printlog.dsp
@@ -7,16 +7,16 @@
CFG=db_printlog - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_printlog.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_printlog.mak" CFG="db_printlog - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_printlog - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_printlog - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_printlog - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_printlog - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_recover.dsp b/VC++Files/bdb/build_win32/db_recover.dsp
index bf07631f9b9..6419c3faf64 100644
--- a/VC++Files/bdb/build_win32/db_recover.dsp
+++ b/VC++Files/bdb/build_win32/db_recover.dsp
@@ -7,16 +7,16 @@
CFG=db_recover - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_recover.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_recover.mak" CFG="db_recover - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_recover - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_recover - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_recover - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_recover - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_stat.dsp b/VC++Files/bdb/build_win32/db_stat.dsp
index 3e906897e68..8cf59197d42 100644
--- a/VC++Files/bdb/build_win32/db_stat.dsp
+++ b/VC++Files/bdb/build_win32/db_stat.dsp
@@ -7,16 +7,16 @@
CFG=db_stat - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_stat.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_stat.mak" CFG="db_stat - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_stat - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_stat - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_stat - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_stat - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_static.dsp b/VC++Files/bdb/build_win32/db_static.dsp
index 0c355241537..5a95bf7b1c6 100644
--- a/VC++Files/bdb/build_win32/db_static.dsp
+++ b/VC++Files/bdb/build_win32/db_static.dsp
@@ -7,23 +7,23 @@
CFG=db_static - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_static.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_static.mak" CFG="db_static - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_static - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "db_static - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "db_static - Win32 Release Static" (based on\
"Win32 (x86) Static Library")
!MESSAGE "db_static - Win32 Debug Static" (based on\
"Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -114,7 +114,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Debug/libdb32sd.lib"
# ADD LIB32 /nologo /out:"Debug_static/libdb32sd.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_static1.dsp b/VC++Files/bdb/build_win32/db_static1.dsp
index 771397a455b..15498e58ca5 100644
--- a/VC++Files/bdb/build_win32/db_static1.dsp
+++ b/VC++Files/bdb/build_win32/db_static1.dsp
@@ -7,19 +7,19 @@
CFG=db_static1 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_static1.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_static1.mak" CFG="db_static1 - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_static1 - Win32 Release" (based on "Win32 (x86) External Target")
!MESSAGE "db_static1 - Win32 Debug" (based on "Win32 (x86) External Target")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -64,7 +64,7 @@ CFG=db_static1 - Win32 Debug
# PROP Bsc_Name "db_static1.bsc"
# PROP Target_Dir ""
-!ENDIF
+!ENDIF
# Begin Target
@@ -75,7 +75,7 @@ CFG=db_static1 - Win32 Debug
!ELSEIF "$(CFG)" == "db_static1 - Win32 Debug"
-!ENDIF
+!ENDIF
# Begin Source File
diff --git a/VC++Files/bdb/build_win32/db_tcl.dsp b/VC++Files/bdb/build_win32/db_tcl.dsp
index 5a0712c3f82..ae2e1a38e9b 100644
--- a/VC++Files/bdb/build_win32/db_tcl.dsp
+++ b/VC++Files/bdb/build_win32/db_tcl.dsp
@@ -7,19 +7,19 @@
CFG=db_tcl - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_tcl.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_tcl.mak" CFG="db_tcl - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_tcl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "db_tcl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -81,7 +81,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 Debug/libdb32d.lib tcl83d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_tcl32d.dll" /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_test.dsp b/VC++Files/bdb/build_win32/db_test.dsp
index e1bb9056824..406a1369696 100644
--- a/VC++Files/bdb/build_win32/db_test.dsp
+++ b/VC++Files/bdb/build_win32/db_test.dsp
@@ -7,19 +7,19 @@
CFG=db_test - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_test.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_test.mak" CFG="db_test - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_test - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "db_test - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -85,7 +85,7 @@ PostBuild_Desc=Copy built executable files.
PostBuild_Cmds=copy Debug\*.exe .
# End Special Build Tool
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_upgrade.dsp b/VC++Files/bdb/build_win32/db_upgrade.dsp
index 4bb821f57e2..c2f3a748a61 100644
--- a/VC++Files/bdb/build_win32/db_upgrade.dsp
+++ b/VC++Files/bdb/build_win32/db_upgrade.dsp
@@ -7,16 +7,16 @@
CFG=db_upgrade - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_upgrade.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_upgrade.mak" CFG="db_upgrade - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_upgrade - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_upgrade - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_upgrade - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_upgrade - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/db_verify.dsp b/VC++Files/bdb/build_win32/db_verify.dsp
index a8112364a83..b76bd203b44 100644
--- a/VC++Files/bdb/build_win32/db_verify.dsp
+++ b/VC++Files/bdb/build_win32/db_verify.dsp
@@ -7,16 +7,16 @@
CFG=db_verify - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_verify.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "db_verify.mak" CFG="db_verify - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "db_verify - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "db_verify - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=db_verify - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "db_verify - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/ex_access.dsp b/VC++Files/bdb/build_win32/ex_access.dsp
index 8c802b1d774..5c1615c915a 100644
--- a/VC++Files/bdb/build_win32/ex_access.dsp
+++ b/VC++Files/bdb/build_win32/ex_access.dsp
@@ -7,16 +7,16 @@
CFG=ex_access - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_access.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_access.mak" CFG="ex_access - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "ex_access - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ex_access - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=ex_access - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "ex_access - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/ex_btrec.dsp b/VC++Files/bdb/build_win32/ex_btrec.dsp
index 08bc90752f5..e687324d813 100644
--- a/VC++Files/bdb/build_win32/ex_btrec.dsp
+++ b/VC++Files/bdb/build_win32/ex_btrec.dsp
@@ -7,16 +7,16 @@
CFG=ex_btrec - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_btrec.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_btrec.mak" CFG="ex_btrec - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "ex_btrec - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ex_btrec - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=ex_btrec - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "ex_btrec - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/ex_env.dsp b/VC++Files/bdb/build_win32/ex_env.dsp
index a46e66dac27..ade4c87d965 100644
--- a/VC++Files/bdb/build_win32/ex_env.dsp
+++ b/VC++Files/bdb/build_win32/ex_env.dsp
@@ -7,16 +7,16 @@
CFG=ex_env - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_env.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_env.mak" CFG="ex_env - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "ex_env - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ex_env - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=ex_env - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "ex_env - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/ex_lock.dsp b/VC++Files/bdb/build_win32/ex_lock.dsp
index 0fa57a960f8..ce5ecc22b56 100644
--- a/VC++Files/bdb/build_win32/ex_lock.dsp
+++ b/VC++Files/bdb/build_win32/ex_lock.dsp
@@ -7,16 +7,16 @@
CFG=ex_lock - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_lock.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_lock.mak" CFG="ex_lock - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "ex_lock - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ex_lock - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=ex_lock - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "ex_lock - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/ex_mpool.dsp b/VC++Files/bdb/build_win32/ex_mpool.dsp
index 3e2ee7205ce..f6ae1df52dc 100644
--- a/VC++Files/bdb/build_win32/ex_mpool.dsp
+++ b/VC++Files/bdb/build_win32/ex_mpool.dsp
@@ -7,16 +7,16 @@
CFG=ex_mpool - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_mpool.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_mpool.mak" CFG="ex_mpool - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "ex_mpool - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ex_mpool - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=ex_mpool - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "ex_mpool - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/ex_tpcb.dsp b/VC++Files/bdb/build_win32/ex_tpcb.dsp
index fbaa67de7ac..43f7a560915 100644
--- a/VC++Files/bdb/build_win32/ex_tpcb.dsp
+++ b/VC++Files/bdb/build_win32/ex_tpcb.dsp
@@ -7,16 +7,16 @@
CFG=ex_tpcb - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_tpcb.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "ex_tpcb.mak" CFG="ex_tpcb - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "ex_tpcb - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ex_tpcb - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=ex_tpcb - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "ex_tpcb - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/excxx_access.dsp b/VC++Files/bdb/build_win32/excxx_access.dsp
index d93894dc5b7..f817b791627 100644
--- a/VC++Files/bdb/build_win32/excxx_access.dsp
+++ b/VC++Files/bdb/build_win32/excxx_access.dsp
@@ -7,16 +7,16 @@
CFG=excxx_access - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_access.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_access.mak" CFG="excxx_access - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "excxx_access - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "excxx_access - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=excxx_access - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "excxx_access - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/excxx_btrec.dsp b/VC++Files/bdb/build_win32/excxx_btrec.dsp
index 403e438a6e1..a06904f2160 100644
--- a/VC++Files/bdb/build_win32/excxx_btrec.dsp
+++ b/VC++Files/bdb/build_win32/excxx_btrec.dsp
@@ -7,16 +7,16 @@
CFG=excxx_btrec - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_btrec.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_btrec.mak" CFG="excxx_btrec - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "excxx_btrec - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "excxx_btrec - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=excxx_btrec - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "excxx_btrec - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/excxx_env.dsp b/VC++Files/bdb/build_win32/excxx_env.dsp
index 792358ee3ac..5f1b1c0a2e4 100644
--- a/VC++Files/bdb/build_win32/excxx_env.dsp
+++ b/VC++Files/bdb/build_win32/excxx_env.dsp
@@ -7,16 +7,16 @@
CFG=excxx_env - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_env.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_env.mak" CFG="excxx_env - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "excxx_env - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "excxx_env - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=excxx_env - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "excxx_env - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/excxx_lock.dsp b/VC++Files/bdb/build_win32/excxx_lock.dsp
index d35605cb412..5fe931537a9 100644
--- a/VC++Files/bdb/build_win32/excxx_lock.dsp
+++ b/VC++Files/bdb/build_win32/excxx_lock.dsp
@@ -7,16 +7,16 @@
CFG=excxx_lock - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_lock.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_lock.mak" CFG="excxx_lock - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "excxx_lock - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "excxx_lock - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=excxx_lock - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "excxx_lock - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/excxx_mpool.dsp b/VC++Files/bdb/build_win32/excxx_mpool.dsp
index 2159e75bb9a..213202b1726 100644
--- a/VC++Files/bdb/build_win32/excxx_mpool.dsp
+++ b/VC++Files/bdb/build_win32/excxx_mpool.dsp
@@ -7,16 +7,16 @@
CFG=excxx_mpool - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_mpool.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_mpool.mak" CFG="excxx_mpool - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "excxx_mpool - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "excxx_mpool - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=excxx_mpool - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "excxx_mpool - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/bdb/build_win32/excxx_tpcb.dsp b/VC++Files/bdb/build_win32/excxx_tpcb.dsp
index 9033daa6cfe..ef89fc0de87 100644
--- a/VC++Files/bdb/build_win32/excxx_tpcb.dsp
+++ b/VC++Files/bdb/build_win32/excxx_tpcb.dsp
@@ -7,16 +7,16 @@
CFG=excxx_tpcb - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_tpcb.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "excxx_tpcb.mak" CFG="excxx_tpcb - Win32 Debug Static"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "excxx_tpcb - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "excxx_tpcb - Win32 Debug" (based on\
@@ -25,7 +25,7 @@ CFG=excxx_tpcb - Win32 Debug Static
"Win32 (x86) Console Application")
!MESSAGE "excxx_tpcb - Win32 Debug Static" (based on\
"Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -131,7 +131,7 @@ LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb32sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp
index 9560a4cfef1..1cd03ee2fcc 100644
--- a/VC++Files/client/mysql.dsp
+++ b/VC++Files/client/mysql.dsp
@@ -7,19 +7,19 @@
CFG=mysql - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysql.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysql.mak" CFG="mysql - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysql - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysql - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
@@ -99,7 +99,7 @@ SOURCE=.\mysql.cpp
!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
-!ENDIF
+!ENDIF
# End Source File
# End Target
diff --git a/VC++Files/client/mysqladmin.dsp b/VC++Files/client/mysqladmin.dsp
index 82794da57cb..11189ecb065 100644
--- a/VC++Files/client/mysqladmin.dsp
+++ b/VC++Files/client/mysqladmin.dsp
@@ -7,19 +7,19 @@
CFG=mysqladmin - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqladmin.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqladmin.mak" CFG="mysqladmin - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqladmin - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqladmin - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -78,7 +78,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/client/mysqlcheck.dsp b/VC++Files/client/mysqlcheck.dsp
index b334c0a8f1c..30e7a365f04 100644
--- a/VC++Files/client/mysqlcheck.dsp
+++ b/VC++Files/client/mysqlcheck.dsp
@@ -7,18 +7,18 @@
CFG=mysqlcheck - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlcheck.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlcheck.mak" CFG="mysqlcheck - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlcheck - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp
index d03623cedb9..54cbf841a7c 100644
--- a/VC++Files/client/mysqlclient.dsp
+++ b/VC++Files/client/mysqlclient.dsp
@@ -25,7 +25,7 @@ CFG=mysqlclient - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "mysqlclient - Win32 Release"
@@ -48,7 +48,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_release\mysqlclient.lib"
@@ -72,7 +72,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib"
@@ -116,6 +116,10 @@ SOURCE="..\strings\ctype-big5.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-bin.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-czech.c"
# End Source File
# Begin Source File
@@ -136,6 +140,10 @@ SOURCE="..\strings\ctype-latin1_de.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-simple.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-sjis.c"
# End Source File
# Begin Source File
@@ -200,10 +208,6 @@ SOURCE=..\mysys\mf_cache.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\mf_casecnv.c
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\mf_dirname.c
# End Source File
# Begin Source File
@@ -378,7 +382,7 @@ SOURCE=..\mysys\my_thr_init.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\my_vsnprintf.c
+SOURCE=..\strings\my_vsnprintf.c
# End Source File
# Begin Source File
@@ -418,6 +422,10 @@ SOURCE=.\select_test.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\sha1.c
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_string.cpp
# End Source File
# Begin Source File
@@ -482,6 +490,10 @@ SOURCE=..\strings\strxmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\strxnmov.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\thr_mutex.c
# End Source File
# Begin Source File
@@ -504,5 +516,9 @@ SOURCE=..\vio\viossl.c
SOURCE=..\vio\viosslfactories.c
# End Source File
+# Begin Source File
+
+SOURCE=..\strings\xml.c
+# End Source File
# End Target
# End Project
diff --git a/VC++Files/client/mysqlclient.dsw b/VC++Files/client/mysqlclient.dsw
index 9c08bbf0407..0f35d0c2253 100644
--- a/VC++Files/client/mysqlclient.dsw
+++ b/VC++Files/client/mysqlclient.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/client/mysqldump.dsp b/VC++Files/client/mysqldump.dsp
index dcf1c1435a6..4fae9a5769a 100644
--- a/VC++Files/client/mysqldump.dsp
+++ b/VC++Files/client/mysqldump.dsp
@@ -7,19 +7,19 @@
CFG=mysqldump - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqldump.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqldump.mak" CFG="mysqldump - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqldump - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqldump - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -78,7 +78,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/mysqldump.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
@@ -95,7 +95,7 @@ SOURCE=.\mysqldump.c
# ADD CPP /W3
# SUBTRACT CPP /YX
-!ENDIF
+!ENDIF
# End Source File
# End Target
diff --git a/VC++Files/client/mysqlimport.dsp b/VC++Files/client/mysqlimport.dsp
index f10c1f90f58..8eb08f1411f 100644
--- a/VC++Files/client/mysqlimport.dsp
+++ b/VC++Files/client/mysqlimport.dsp
@@ -7,19 +7,19 @@
CFG=mysqlimport - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlimport.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlimport.mak" CFG="mysqlimport - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlimport - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqlimport - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/client/mysqlshow.dsp b/VC++Files/client/mysqlshow.dsp
index dd0fc09c70f..78627246050 100644
--- a/VC++Files/client/mysqlshow.dsp
+++ b/VC++Files/client/mysqlshow.dsp
@@ -7,19 +7,19 @@
CFG=mysqlshow - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlshow.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlshow.mak" CFG="mysqlshow - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlshow - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqlshow - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -78,7 +78,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/comp_err/comp_err.dsp b/VC++Files/comp_err/comp_err.dsp
index 784266f4016..71582b84763 100644
--- a/VC++Files/comp_err/comp_err.dsp
+++ b/VC++Files/comp_err/comp_err.dsp
@@ -7,18 +7,18 @@
CFG=comp_err - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "comp_err.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "comp_err.mak" CFG="comp_err - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "comp_err - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
diff --git a/VC++Files/contrib/asm386/zlibvc.dsp b/VC++Files/contrib/asm386/zlibvc.dsp
index a70d4d4a6b0..63d8fee6511 100644
--- a/VC++Files/contrib/asm386/zlibvc.dsp
+++ b/VC++Files/contrib/asm386/zlibvc.dsp
@@ -8,16 +8,16 @@
CFG=zlibvc - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "zlibvc.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\
@@ -26,7 +26,7 @@ CFG=zlibvc - Win32 Release
"Win32 (x86) Dynamic-Link Library")
!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\
"Win32 (x86) Dynamic-Link Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -191,7 +191,7 @@ LINK32=link.exe
# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll"
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
@@ -216,13 +216,13 @@ SOURCE=.\adler32.c
DEP_CPP_ADLER=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -238,13 +238,13 @@ SOURCE=.\compress.c
DEP_CPP_COMPR=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -260,13 +260,13 @@ SOURCE=.\crc32.c
DEP_CPP_CRC32=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -284,13 +284,13 @@ DEP_CPP_DEFLA=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -307,7 +307,7 @@ SOURCE=.\gvmat32c.c
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -324,13 +324,13 @@ DEP_CPP_GZIO_=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -351,13 +351,13 @@ DEP_CPP_INFBL=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -379,13 +379,13 @@ DEP_CPP_INFCO=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -407,13 +407,13 @@ DEP_CPP_INFFA=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -431,13 +431,13 @@ DEP_CPP_INFLA=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -455,13 +455,13 @@ DEP_CPP_INFTR=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -482,13 +482,13 @@ DEP_CPP_INFUT=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -506,13 +506,13 @@ DEP_CPP_TREES=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -528,13 +528,13 @@ SOURCE=.\uncompr.c
DEP_CPP_UNCOM=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -551,7 +551,7 @@ SOURCE=.\unzip.c
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -568,7 +568,7 @@ SOURCE=.\zip.c
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -593,13 +593,13 @@ DEP_CPP_ZUTIL=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# End Group
diff --git a/VC++Files/contrib/asm386/zlibvc.dsw b/VC++Files/contrib/asm386/zlibvc.dsw
index 493cd870365..041a77a06a2 100644
--- a/VC++Files/contrib/asm386/zlibvc.dsw
+++ b/VC++Files/contrib/asm386/zlibvc.dsw
@@ -38,4 +38,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/contrib/minizip/zlibvc.dsp b/VC++Files/contrib/minizip/zlibvc.dsp
index a70d4d4a6b0..63d8fee6511 100644
--- a/VC++Files/contrib/minizip/zlibvc.dsp
+++ b/VC++Files/contrib/minizip/zlibvc.dsp
@@ -8,16 +8,16 @@
CFG=zlibvc - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "zlibvc.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\
@@ -26,7 +26,7 @@ CFG=zlibvc - Win32 Release
"Win32 (x86) Dynamic-Link Library")
!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\
"Win32 (x86) Dynamic-Link Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -191,7 +191,7 @@ LINK32=link.exe
# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll"
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
@@ -216,13 +216,13 @@ SOURCE=.\adler32.c
DEP_CPP_ADLER=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -238,13 +238,13 @@ SOURCE=.\compress.c
DEP_CPP_COMPR=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -260,13 +260,13 @@ SOURCE=.\crc32.c
DEP_CPP_CRC32=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -284,13 +284,13 @@ DEP_CPP_DEFLA=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -307,7 +307,7 @@ SOURCE=.\gvmat32c.c
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -324,13 +324,13 @@ DEP_CPP_GZIO_=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -351,13 +351,13 @@ DEP_CPP_INFBL=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -379,13 +379,13 @@ DEP_CPP_INFCO=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -407,13 +407,13 @@ DEP_CPP_INFFA=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -431,13 +431,13 @@ DEP_CPP_INFLA=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -455,13 +455,13 @@ DEP_CPP_INFTR=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -482,13 +482,13 @@ DEP_CPP_INFUT=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -506,13 +506,13 @@ DEP_CPP_TREES=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -528,13 +528,13 @@ SOURCE=.\uncompr.c
DEP_CPP_UNCOM=\
".\zconf.h"\
".\zlib.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -551,7 +551,7 @@ SOURCE=.\unzip.c
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -568,7 +568,7 @@ SOURCE=.\zip.c
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -593,13 +593,13 @@ DEP_CPP_ZUTIL=\
".\zconf.h"\
".\zlib.h"\
".\zutil.h"\
-
+
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-!ENDIF
+!ENDIF
# End Source File
# End Group
diff --git a/VC++Files/contrib/minizip/zlibvc.dsw b/VC++Files/contrib/minizip/zlibvc.dsw
index 493cd870365..041a77a06a2 100644
--- a/VC++Files/contrib/minizip/zlibvc.dsw
+++ b/VC++Files/contrib/minizip/zlibvc.dsw
@@ -38,4 +38,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/dbug/dbug.dsp b/VC++Files/dbug/dbug.dsp
index 11721da98d6..5db7b05175b 100644
--- a/VC++Files/dbug/dbug.dsp
+++ b/VC++Files/dbug/dbug.dsp
@@ -7,19 +7,19 @@
CFG=dbug - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "dbug.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "dbug.mak" CFG="dbug - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "dbug - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "dbug - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\dbug.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/dbug/dbug.dsw b/VC++Files/dbug/dbug.dsw
index a0cd4da7891..b1e978b2c8f 100644
--- a/VC++Files/dbug/dbug.dsw
+++ b/VC++Files/dbug/dbug.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/fix-project-files b/VC++Files/fix-project-files
new file mode 100755
index 00000000000..b63ceab318a
--- /dev/null
+++ b/VC++Files/fix-project-files
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+#
+# Change linefeed -> return+linefeed for all VC++ project files
+#
+
+find . \( -name "*.dsp" -o -name "*.dsw" \) -print | grep -v "SCCS" | xargs replace '\r\$' ' ' '\$' ' ' --
diff --git a/VC++Files/heap/heap.dsp b/VC++Files/heap/heap.dsp
index c21c3139519..1edeec80e9b 100644
--- a/VC++Files/heap/heap.dsp
+++ b/VC++Files/heap/heap.dsp
@@ -7,19 +7,19 @@
CFG=heap - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "heap.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "heap.mak" CFG="heap - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "heap - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "heap - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\heap.lib"
-!ENDIF
+!ENDIF
# Begin Target
@@ -128,7 +128,7 @@ SOURCE=.\hp_hash.c
# SUBTRACT CPP /YX
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
diff --git a/VC++Files/innobase/innobase.dsp b/VC++Files/innobase/innobase.dsp
index 0c2b656f043..1c17168628d 100644
--- a/VC++Files/innobase/innobase.dsp
+++ b/VC++Files/innobase/innobase.dsp
@@ -27,7 +27,7 @@ CFG=INNOBASE - WIN32 RELEASE
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "innobase - Win32 Debug"
@@ -43,14 +43,14 @@ RSC=rc.exe
# PROP Intermediate_Dir "debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /GX /Z7 /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /GX /Z7 /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo /out:"..\lib_release\innobase-nt.lib"
# ADD LIB32 /nologo /out:"..\lib_debug\innodb.lib"
@@ -74,7 +74,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo /out:"..\lib_release\innodb.lib"
# ADD LIB32 /nologo /out:"..\lib_release\innodb.lib"
@@ -98,7 +98,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo /out:"..\lib_release\innodb.lib"
# ADD LIB32 /nologo /out:"..\lib_release\innodb.lib"
@@ -122,7 +122,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo /out:"..\lib_release\innodb.lib"
# ADD LIB32 /nologo /out:"..\lib_release\innodb.lib"
diff --git a/VC++Files/isam/isam.dsp b/VC++Files/isam/isam.dsp
index 32832919654..12047145f6d 100644
--- a/VC++Files/isam/isam.dsp
+++ b/VC++Files/isam/isam.dsp
@@ -7,19 +7,19 @@
CFG=isam - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "isam.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "isam.mak" CFG="isam - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "isam - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "isam - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_Debug\isam.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/isam/isam.dsw b/VC++Files/isam/isam.dsw
index 6874c8cf4c3..c18224a6d73 100644
--- a/VC++Files/isam/isam.dsw
+++ b/VC++Files/isam/isam.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/isamchk/isamchk.dsp b/VC++Files/isamchk/isamchk.dsp
index 7b9c03f23f4..e1e0f8aac3a 100644
--- a/VC++Files/isamchk/isamchk.dsp
+++ b/VC++Files/isamchk/isamchk.dsp
@@ -7,19 +7,19 @@
CFG=isamchk - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "isamchk.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "isamchk.mak" CFG="isamchk - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "isamchk - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "isamchk - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -80,7 +80,7 @@ LINK32=link.exe
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/isamchk.exe" /pdbtype:sept
# SUBTRACT LINK32 /verbose /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/libmysql/libmysql.def b/VC++Files/libmysql/libmysql.def
index 3ddbe28bc83..e7959078390 100644
--- a/VC++Files/libmysql/libmysql.def
+++ b/VC++Files/libmysql/libmysql.def
@@ -59,7 +59,6 @@ EXPORTS
list_add
list_delete
max_allowed_packet
- my_casecmp
my_init
my_end
my_strdup
diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index ea5ef096561..46b7b422f9d 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -127,6 +127,10 @@ SOURCE="..\strings\ctype-big5.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-bin.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-czech.c"
# End Source File
# Begin Source File
@@ -147,6 +151,10 @@ SOURCE="..\strings\ctype-latin1_de.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-simple.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-sjis.c"
# End Source File
# Begin Source File
@@ -215,10 +223,6 @@ SOURCE=..\strings\longlong2str.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\mf_casecnv.c
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\mf_dirname.c
# End Source File
# Begin Source File
@@ -256,6 +260,7 @@ SOURCE=..\mysys\my_alloc.c
# Begin Source File
SOURCE=..\mysys\my_compress.c
+# ADD CPP /I "../zlib"
# End Source File
# Begin Source File
@@ -391,6 +396,10 @@ SOURCE=..\client\select_test.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\sha1.c
+# End Source File
+# Begin Source File
+
SOURCE=..\client\sql_string.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysql/libmysql.dsw b/VC++Files/libmysql/libmysql.dsw
index fe121fa65cc..331802dc16d 100644
--- a/VC++Files/libmysql/libmysql.dsw
+++ b/VC++Files/libmysql/libmysql.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/libmysqld/examples/test_libmysqld.dsp b/VC++Files/libmysqld/examples/test_libmysqld.dsp
index 35d9689266d..d5fd0a0982d 100644
--- a/VC++Files/libmysqld/examples/test_libmysqld.dsp
+++ b/VC++Files/libmysqld/examples/test_libmysqld.dsp
@@ -7,18 +7,18 @@
CFG=test_libmysqld - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "test_libmysqld.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "test_libmysqld.mak" CFG="test_libmysqld - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "test_libmysqld - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index bd20c75a24e..2a055ab34c0 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -7,19 +7,19 @@
CFG=libmysqld - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "libmysqld.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "libmysqld.mak" CFG="libmysqld - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "libmysqld - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "libmysqld - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -43,8 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /mktyplib203 /win32 # ADD BASE MTL /c
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
@@ -53,8 +52,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
-# SUBTRACT LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib # SUBTRACT LINK32 /nologo /dll /pdb:none /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
!ELSEIF "$(CFG)" == "libmysqld - Win32 Debug"
@@ -70,8 +68,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /mktyplib203 /win32 # ADD BASE MTL /c
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x416 /d "_DEBUG"
# ADD RSC /l 0x416 /d "_DEBUG"
@@ -80,10 +77,9 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\innodb.lib /nologo /dll /incremental:no /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\innodb.lib # SUBTRACT LINK32 /nologo /dll /pdb:none /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib"
-!ENDIF
+!ENDIF
# Begin Target
@@ -119,6 +115,10 @@ SOURCE=..\libmysql\get_password.c
# End Source File
# Begin Source File
+SOURCE=..\sql\gstream.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\ha_berkeley.cpp
# End Source File
# Begin Source File
@@ -176,6 +176,7 @@ SOURCE=..\sql\item_create.cpp
# Begin Source File
SOURCE=..\sql\item_func.cpp
+# ADD CPP /I "../zlib"
# End Source File
# Begin Source File
@@ -183,6 +184,10 @@ SOURCE=..\sql\item_strfunc.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\item_subselect.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\item_sum.cpp
# End Source File
# Begin Source File
@@ -271,7 +276,7 @@ SOURCE=..\sql\set_var.cpp
# End Source File
# Begin Source File
-SOURCE=..\sql\slave.cpp
+SOURCE=..\sql\spatial.cpp
# End Source File
# Begin Source File
@@ -307,10 +312,18 @@ SOURCE=..\sql\sql_delete.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_derived.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_do.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_error.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_handler.cpp
# End Source File
# Begin Source File
@@ -327,10 +340,6 @@ SOURCE=..\sql\sql_list.cpp
# End Source File
# Begin Source File
-SOURCE=..\sql\sql_load.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\sql\sql_manager.cpp
# End Source File
# Begin Source File
@@ -340,6 +349,10 @@ SOURCE=..\sql\sql_map.cpp
# Begin Source File
SOURCE=..\sql\sql_parse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sql_prepare.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysqltest/myTest.dsp b/VC++Files/libmysqltest/myTest.dsp
index fec250e7a40..744b2c04993 100644
--- a/VC++Files/libmysqltest/myTest.dsp
+++ b/VC++Files/libmysqltest/myTest.dsp
@@ -7,19 +7,19 @@
CFG=myTest - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myTest.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myTest.mak" CFG="myTest - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myTest - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "myTest - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -78,7 +78,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 libmysql.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"..\lib_debug"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/libmysqltest/mytest.dsw b/VC++Files/libmysqltest/mytest.dsw
index 621899eb4d0..1aa804386bc 100644
--- a/VC++Files/libmysqltest/mytest.dsw
+++ b/VC++Files/libmysqltest/mytest.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/merge/merge.dsp b/VC++Files/merge/merge.dsp
index 70c0ce87d6b..8a8173fd606 100644
--- a/VC++Files/merge/merge.dsp
+++ b/VC++Files/merge/merge.dsp
@@ -7,19 +7,19 @@
CFG=merge - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "merge.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "merge.mak" CFG="merge - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "merge - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "merge - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\merge.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/merge/merge.dsw b/VC++Files/merge/merge.dsw
index a2d5ccb2ff2..26d3bb5200c 100644
--- a/VC++Files/merge/merge.dsw
+++ b/VC++Files/merge/merge.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/my_print_defaults/my_print_defaults.dsp b/VC++Files/my_print_defaults/my_print_defaults.dsp
index c7727b49851..b485a20a844 100644
--- a/VC++Files/my_print_defaults/my_print_defaults.dsp
+++ b/VC++Files/my_print_defaults/my_print_defaults.dsp
@@ -7,19 +7,19 @@
CFG=my_print_defaults - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "my_print_defaults.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "my_print_defaults.mak" CFG="my_print_defaults - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "my_print_defaults - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "my_print_defaults - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -75,7 +75,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"LIBCMTD.lib" /pdbtype:sept
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/myisam/myisam.dsp b/VC++Files/myisam/myisam.dsp
index 8346cddbc54..40d157a1c75 100644
--- a/VC++Files/myisam/myisam.dsp
+++ b/VC++Files/myisam/myisam.dsp
@@ -7,19 +7,19 @@
CFG=myisam - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisam.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisam.mak" CFG="myisam - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myisam - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "myisam - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -74,7 +74,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_Debug\myisam.lib"
-!ENDIF
+!ENDIF
# Begin Target
@@ -265,8 +265,28 @@ SOURCE=.\mi_write.c
# End Source File
# Begin Source File
+SOURCE=.\rt_index.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rt_key.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rt_mbr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rt_split.c
+# End Source File
+# Begin Source File
+
SOURCE=.\sort.c
# End Source File
+# Begin Source File
+
+SOURCE=.\sp_key.c
+# End Source File
# End Group
# Begin Group "Header Files"
@@ -279,6 +299,10 @@ SOURCE=.\ft_eval.h
SOURCE=.\myisamdef.h
# End Source File
+# Begin Source File
+
+SOURCE=.\rt_index.h
+# End Source File
# End Group
# End Target
# End Project
diff --git a/VC++Files/myisamchk/myisamchk.dsp b/VC++Files/myisamchk/myisamchk.dsp
index 7f0459d21d0..0c8e7c00f1a 100644
--- a/VC++Files/myisamchk/myisamchk.dsp
+++ b/VC++Files/myisamchk/myisamchk.dsp
@@ -7,19 +7,19 @@
CFG=myisamchk - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisamchk.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisamchk.mak" CFG="myisamchk - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myisamchk - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "myisamchk - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -78,7 +78,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/myisamchk.exe" /pdbtype:sept
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/myisamlog/myisamlog.dsp b/VC++Files/myisamlog/myisamlog.dsp
index efc43914759..bbb6739cb16 100644
--- a/VC++Files/myisamlog/myisamlog.dsp
+++ b/VC++Files/myisamlog/myisamlog.dsp
@@ -7,19 +7,19 @@
CFG=myisamlog - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisamlog.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisamlog.mak" CFG="myisamlog - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myisamlog - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "myisamlog - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /pdb:"debug/myisamchk.pdb" /debug /machine:I386 /out:"../client_debug/myisamlog.exe" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/myisammrg/myisammrg.dsp b/VC++Files/myisammrg/myisammrg.dsp
index e8f86dac0e8..9363bd63e62 100644
--- a/VC++Files/myisammrg/myisammrg.dsp
+++ b/VC++Files/myisammrg/myisammrg.dsp
@@ -7,19 +7,19 @@
CFG=myisammrg - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisammrg.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisammrg.mak" CFG="myisammrg - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myisammrg - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "myisammrg - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -75,7 +75,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_Debug\myisammrg.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/myisampack/myisampack.dsp b/VC++Files/myisampack/myisampack.dsp
index f576a93faf2..cdfc44331ea 100644
--- a/VC++Files/myisampack/myisampack.dsp
+++ b/VC++Files/myisampack/myisampack.dsp
@@ -7,19 +7,19 @@
CFG=myisampack - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisampack.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myisampack.mak" CFG="myisampack - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myisampack - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "myisampack - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -77,7 +77,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysql.dsp b/VC++Files/mysql.dsp
index 41f2538a7e5..4f97866cc31 100644
--- a/VC++Files/mysql.dsp
+++ b/VC++Files/mysql.dsp
@@ -7,19 +7,19 @@
CFG=mysql - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysql.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysql.mak" CFG="mysql - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysql - Win32 Release" (based on "Win32 (x86) External Target")
!MESSAGE "mysql - Win32 Debug" (based on "Win32 (x86) External Target")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
@@ -63,7 +63,7 @@ CFG=mysql - Win32 Debug
# PROP Bsc_Name "mysql.bsc"
# PROP Target_Dir ""
-!ENDIF
+!ENDIF
# Begin Target
@@ -74,7 +74,7 @@ CFG=mysql - Win32 Debug
!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
-!ENDIF
+!ENDIF
# End Target
# End Project
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index b576730b500..f72cd0f0163 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -797,4 +797,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.dsp b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
index 94723b0a127..a4e85becd49 100644
--- a/VC++Files/mysqlbinlog/mysqlbinlog.dsp
+++ b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
@@ -7,19 +7,19 @@
CFG=mysqlbinlog - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlbinlog.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlbinlog.mak" CFG="mysqlbinlog - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlbinlog - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqlbinlog - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -77,7 +77,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlbinlog.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysqlcheck/mysqlcheck.dsp b/VC++Files/mysqlcheck/mysqlcheck.dsp
index 49c3fc2b702..9b821261672 100644
--- a/VC++Files/mysqlcheck/mysqlcheck.dsp
+++ b/VC++Files/mysqlcheck/mysqlcheck.dsp
@@ -7,19 +7,19 @@
CFG=mysqlcheck - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlcheck.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlcheck.mak" CFG="mysqlcheck - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlcheck - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqlcheck - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlcheck.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysqldemb/mysqldemb.dsp b/VC++Files/mysqldemb/mysqldemb.dsp
index 25dc1f6fee1..21d1eb7eac0 100644
--- a/VC++Files/mysqldemb/mysqldemb.dsp
+++ b/VC++Files/mysqldemb/mysqldemb.dsp
@@ -25,7 +25,7 @@ CFG=mysqldemb - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "mysqldemb - Win32 Release"
@@ -41,14 +41,14 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
@@ -65,14 +65,14 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I "../zlib" /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "_DEBUG"
# ADD RSC /l 0x416 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
@@ -168,10 +168,18 @@ SOURCE=..\sql\item_func.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\item_row.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\item_strfunc.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\item_subselect.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\item_sum.cpp
# End Source File
# Begin Source File
@@ -216,10 +224,6 @@ SOURCE=..\sql\mini_client.cpp
# End Source File
# Begin Source File
-SOURCE=..\sql\net_pkg.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\sql\net_serv.cpp
# End Source File
# Begin Source File
@@ -244,6 +248,10 @@ SOURCE=..\sql\procedure.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\protocol.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\records.cpp
# End Source File
# Begin Source File
@@ -288,10 +296,18 @@ SOURCE=..\sql\sql_delete.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_derived.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_do.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_error.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_handler.cpp
# End Source File
# Begin Source File
@@ -317,6 +333,10 @@ SOURCE=..\sql\sql_map.cpp
# Begin Source File
SOURCE=..\sql\sql_parse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sql_prepare.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/mysqlmanager/MySqlManager.dsp b/VC++Files/mysqlmanager/MySqlManager.dsp
index 60ee700b00c..6b86b8dd45f 100644
--- a/VC++Files/mysqlmanager/MySqlManager.dsp
+++ b/VC++Files/mysqlmanager/MySqlManager.dsp
@@ -7,19 +7,19 @@
CFG=MySqlManager - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "MySqlManager.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "MySqlManager.mak" CFG="MySqlManager - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "MySqlManager - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "MySqlManager - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -86,7 +86,7 @@ LINK32=link.exe
# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /out:"../client_debug/MySqlManager.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysqlmanager/mysqlmanager.dsw b/VC++Files/mysqlmanager/mysqlmanager.dsw
index 02ec9a86dc5..013873b113b 100644
--- a/VC++Files/mysqlmanager/mysqlmanager.dsw
+++ b/VC++Files/mysqlmanager/mysqlmanager.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/mysqlserver/mysqlserver.dsp b/VC++Files/mysqlserver/mysqlserver.dsp
index 84c547ef453..0ef59eb226e 100644
--- a/VC++Files/mysqlserver/mysqlserver.dsp
+++ b/VC++Files/mysqlserver/mysqlserver.dsp
@@ -7,19 +7,19 @@
CFG=mysqlserver - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlserver.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlserver.mak" CFG="mysqlserver - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlserver - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "mysqlserver - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -74,7 +74,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysqlshutdown/myshutdown.dsp b/VC++Files/mysqlshutdown/myshutdown.dsp
index 390921f599c..0119df3cd59 100644
--- a/VC++Files/mysqlshutdown/myshutdown.dsp
+++ b/VC++Files/mysqlshutdown/myshutdown.dsp
@@ -7,19 +7,19 @@
CFG=myshutdown - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myshutdown.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "myshutdown.mak" CFG="myshutdown - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "myshutdown - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "myshutdown - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysqlshutdown/mysqlshutdown.dsp b/VC++Files/mysqlshutdown/mysqlshutdown.dsp
index 1489a5547ed..fd78c6ddb21 100644
--- a/VC++Files/mysqlshutdown/mysqlshutdown.dsp
+++ b/VC++Files/mysqlshutdown/mysqlshutdown.dsp
@@ -7,19 +7,19 @@
CFG=mysqlshutdown - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlshutdown.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlshutdown.mak" CFG="mysqlshutdown - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlshutdown - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "mysqlshutdown - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -85,7 +85,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../client_release/mysqlshutdown.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../client_debug/mysqlshutdown.exe"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/mysqlwatch/mysqlwatch.dsp b/VC++Files/mysqlwatch/mysqlwatch.dsp
index 004f444e09b..5c209f55e51 100644
--- a/VC++Files/mysqlwatch/mysqlwatch.dsp
+++ b/VC++Files/mysqlwatch/mysqlwatch.dsp
@@ -7,18 +7,18 @@
CFG=mysqlwatch - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlwatch.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlwatch.mak" CFG="mysqlwatch - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlwatch - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
diff --git a/VC++Files/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp
index c4c21d9a6db..eb96c1ed986 100644
--- a/VC++Files/mysys/mysys.dsp
+++ b/VC++Files/mysys/mysys.dsp
@@ -26,7 +26,7 @@ CFG=mysys - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "mysys - Win32 Release"
@@ -49,7 +49,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_release\mysys.lib"
@@ -73,7 +73,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\mysys.lib"
@@ -98,7 +98,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo /out:"..\lib_release\mysys.lib"
# ADD LIB32 /nologo /out:"..\lib_release\mysys-max.lib"
@@ -162,10 +162,6 @@ SOURCE=.\mf_cache.c
# End Source File
# Begin Source File
-SOURCE=.\mf_casecnv.c
-# End Source File
-# Begin Source File
-
SOURCE=.\mf_dirname.c
# End Source File
# Begin Source File
@@ -234,6 +230,10 @@ SOURCE=.\mf_strip.c
# End Source File
# Begin Source File
+SOURCE=.\mf_tempdir.c
+# End Source File
+# Begin Source File
+
SOURCE=.\mf_tempfile.c
# End Source File
# Begin Source File
@@ -326,6 +326,10 @@ SOURCE=.\my_getwd.c
# End Source File
# Begin Source File
+SOURCE=.\my_handler.c
+# End Source File
+# Begin Source File
+
SOURCE=.\my_init.c
# End Source File
# Begin Source File
@@ -430,10 +434,6 @@ SOURCE=.\my_thr_init.c
# End Source File
# Begin Source File
-SOURCE=.\my_vsnprintf.c
-# End Source File
-# Begin Source File
-
SOURCE=.\my_wincond.c
# End Source File
# Begin Source File
diff --git a/VC++Files/mysys/mysys.dsw b/VC++Files/mysys/mysys.dsw
index d5064051fc9..445079aed69 100644
--- a/VC++Files/mysys/mysys.dsw
+++ b/VC++Files/mysys/mysys.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/pack_isam/pack_isam.dsp b/VC++Files/pack_isam/pack_isam.dsp
index 1b377c0b68e..25e4ef4a2e0 100644
--- a/VC++Files/pack_isam/pack_isam.dsp
+++ b/VC++Files/pack_isam/pack_isam.dsp
@@ -7,19 +7,19 @@
CFG=pack_isam - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "pack_isam.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "pack_isam.mak" CFG="pack_isam - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "pack_isam - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "pack_isam - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -77,7 +77,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/pack_isam.exe" /pdbtype:sept
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/perror/perror.dsp b/VC++Files/perror/perror.dsp
index 3e98e5e5ca9..6d5c96b2a84 100644
--- a/VC++Files/perror/perror.dsp
+++ b/VC++Files/perror/perror.dsp
@@ -7,19 +7,19 @@
CFG=perror - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "perror.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "perror.mak" CFG="perror - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "perror - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "perror - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -85,7 +85,7 @@ LINK32=link.exe
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /incremental:no /debug /machine:I386 /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/regex/regex.dsp b/VC++Files/regex/regex.dsp
index 5ee617c58b7..59b55ffe46f 100644
--- a/VC++Files/regex/regex.dsp
+++ b/VC++Files/regex/regex.dsp
@@ -7,19 +7,19 @@
CFG=regex - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "regex.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "regex.mak" CFG="regex - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "regex - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "regex - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\regex.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/regex/regex.dsw b/VC++Files/regex/regex.dsw
index 102e07af409..1abe4485cd4 100644
--- a/VC++Files/regex/regex.dsw
+++ b/VC++Files/regex/regex.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/replace/replace.dsp b/VC++Files/replace/replace.dsp
index 011b62d08ec..f0c4848156a 100644
--- a/VC++Files/replace/replace.dsp
+++ b/VC++Files/replace/replace.dsp
@@ -7,19 +7,19 @@
CFG=replace - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "replace.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "replace.mak" CFG="replace - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "replace - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "replace - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /machine:I386 /out:"../client_debug/replace.exe" /pdbtype:sept
# SUBTRACT LINK32 /debug
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index c550407da30..e068ba8f164 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -28,7 +28,7 @@ CFG=mysqld - Win32 Release
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -52,7 +52,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-opt.exe"
# SUBTRACT LINK32 /debug
@@ -78,7 +78,7 @@ LINK32=link.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld.exe" /pdbtype:sept
@@ -105,7 +105,7 @@ LINK32=link.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\dbug.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
# SUBTRACT LINK32 /pdb:none /debug
@@ -133,7 +133,7 @@ LINK32=link.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
# SUBTRACT BASE LINK32 /pdb:none /debug
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-max-nt.exe"
@@ -162,7 +162,7 @@ LINK32=link.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"../client_release/mysqld-opt.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-max.exe"
# SUBTRACT LINK32 /debug
@@ -282,6 +282,10 @@ SOURCE=.\filesort.cpp
# End Source File
# Begin Source File
+SOURCE=.\gstream.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\ha_berkeley.cpp
# End Source File
# Begin Source File
@@ -462,20 +466,30 @@ SOURCE=.\item_func.cpp
!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
-# ADD CPP /G5
+# ADD CPP /G5 /I "../zlib"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+# ADD CPP /I "../zlib"
+
!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+# ADD CPP /I "../zlib"
+
!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+# ADD CPP /I "../zlib"
+
!ENDIF
# End Source File
# Begin Source File
+SOURCE=.\item_row.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\item_strfunc.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -496,6 +510,10 @@ SOURCE=.\item_strfunc.cpp
# End Source File
# Begin Source File
+SOURCE=.\item_subselect.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\item_sum.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -642,27 +660,11 @@ SOURCE=.\mini_client.cpp
# End Source File
# Begin Source File
-SOURCE=.\mysqld.cpp
-
-!IF "$(CFG)" == "mysqld - Win32 Release"
-
-!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
-
-# ADD CPP /G5
-# SUBTRACT CPP /YX /Yc /Yu
-
-!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
-
-!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
-
-!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
-
-!ENDIF
-
+SOURCE=..\myisammrg\myrg_rnext_same.c
# End Source File
# Begin Source File
-SOURCE=.\net_pkg.cpp
+SOURCE=.\mysqld.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -779,6 +781,10 @@ SOURCE=.\procedure.cpp
# End Source File
# Begin Source File
+SOURCE=.\protocol.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\records.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -811,6 +817,10 @@ SOURCE=.\slave.cpp
# End Source File
# Begin Source File
+SOURCE=.\spatial.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_acl.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -927,14 +937,26 @@ SOURCE=.\sql_delete.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_derived.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_do.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_error.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_handler.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_help.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_insert.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -1059,6 +1081,10 @@ SOURCE=.\sql_parse.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_prepare.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_rename.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/sql/mysqld.dsw b/VC++Files/sql/mysqld.dsw
index ed820ed7a90..67948565f66 100644
--- a/VC++Files/sql/mysqld.dsw
+++ b/VC++Files/sql/mysqld.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/sql/mysqldmax.dsp b/VC++Files/sql/mysqldmax.dsp
index 4d24d033c51..24ea83159d9 100644
--- a/VC++Files/sql/mysqldmax.dsp
+++ b/VC++Files/sql/mysqldmax.dsp
@@ -7,20 +7,20 @@
CFG=mysqldmax - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqldmax.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqldmax.mak" CFG="mysqldmax - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqldmax - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqldmax - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "mysqldmax - Win32 nt" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -103,7 +103,7 @@ LINK32=link.exe
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innobase-nt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:"NT/mysqld-nt.pdb" /map:"NT/mysqld-nt.map" /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-nt.exe"
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
@@ -123,7 +123,7 @@ SOURCE=.\convert.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -139,7 +139,7 @@ SOURCE=.\derror.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -155,7 +155,7 @@ SOURCE=.\field.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -171,7 +171,7 @@ SOURCE=.\field_conv.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -187,7 +187,7 @@ SOURCE=.\filesort.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -231,7 +231,7 @@ SOURCE=.\handler.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -246,7 +246,7 @@ SOURCE=.\hash_filo.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -265,7 +265,7 @@ SOURCE=.\hostname.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -281,7 +281,7 @@ SOURCE=.\init.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -297,7 +297,7 @@ SOURCE=.\item.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -313,7 +313,7 @@ SOURCE=.\item_buff.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -329,7 +329,7 @@ SOURCE=.\item_cmpfunc.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -349,7 +349,7 @@ SOURCE=.\item_func.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -365,7 +365,7 @@ SOURCE=.\item_strfunc.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -381,7 +381,7 @@ SOURCE=.\item_sum.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -396,7 +396,7 @@ SOURCE=.\item_timefunc.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -412,7 +412,7 @@ SOURCE=.\item_uniq.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -428,7 +428,7 @@ SOURCE=.\key.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -444,7 +444,7 @@ SOURCE=.\lock.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -460,7 +460,7 @@ SOURCE=.\log.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -483,7 +483,7 @@ SOURCE=.\mf_iocache.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -507,7 +507,7 @@ SOURCE=.\mysqld.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -523,7 +523,7 @@ SOURCE=.\net_pkg.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -542,7 +542,7 @@ SOURCE=.\nt_servc.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -565,7 +565,7 @@ SOURCE=.\opt_range.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -588,7 +588,7 @@ SOURCE=.\password.c
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -604,7 +604,7 @@ SOURCE=.\procedure.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -620,7 +620,7 @@ SOURCE=.\records.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -640,7 +640,7 @@ SOURCE=.\sql_acl.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -660,7 +660,7 @@ SOURCE=.\sql_base.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -680,7 +680,7 @@ SOURCE=.\sql_class.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -704,7 +704,7 @@ SOURCE=.\sql_db.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -720,7 +720,7 @@ SOURCE=.\sql_delete.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -736,7 +736,7 @@ SOURCE=.\sql_insert.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -752,7 +752,7 @@ SOURCE=.\sql_lex.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -768,7 +768,7 @@ SOURCE=.\sql_list.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -784,7 +784,7 @@ SOURCE=.\sql_load.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -804,7 +804,7 @@ SOURCE=.\sql_map.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -820,7 +820,7 @@ SOURCE=.\sql_parse.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -844,7 +844,7 @@ SOURCE=.\sql_select.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -860,7 +860,7 @@ SOURCE=.\sql_show.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -876,7 +876,7 @@ SOURCE=.\sql_string.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -892,7 +892,7 @@ SOURCE=.\sql_table.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -908,7 +908,7 @@ SOURCE=.\sql_test.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -924,7 +924,7 @@ SOURCE=.\sql_update.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -940,7 +940,7 @@ SOURCE=.\sql_yacc.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -960,7 +960,7 @@ SOURCE=.\thr_malloc.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -976,7 +976,7 @@ SOURCE=.\time.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -992,7 +992,7 @@ SOURCE=.\unireg.cpp
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
diff --git a/VC++Files/sql/old/mysqld.dsw b/VC++Files/sql/old/mysqld.dsw
index ed820ed7a90..67948565f66 100644
--- a/VC++Files/sql/old/mysqld.dsw
+++ b/VC++Files/sql/old/mysqld.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/strings/MASM6x/strings.dsp b/VC++Files/strings/MASM6x/strings.dsp
index 0c1a3bdc0c2..1f54910bf58 100644
--- a/VC++Files/strings/MASM6x/strings.dsp
+++ b/VC++Files/strings/MASM6x/strings.dsp
@@ -7,19 +7,19 @@
CFG=strings - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "strings.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "strings.mak" CFG="strings - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "strings - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "strings - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
-!ENDIF
+!ENDIF
# Begin Target
@@ -186,7 +186,7 @@ InputName=Strings
# End Custom Build
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -233,7 +233,7 @@ InputName=Strxmov
# End Custom Build
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
diff --git a/VC++Files/strings/MASM6x/strings.dsw b/VC++Files/strings/MASM6x/strings.dsw
index e3777b8e7d5..63fc3706c19 100644
--- a/VC++Files/strings/MASM6x/strings.dsw
+++ b/VC++Files/strings/MASM6x/strings.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/strings/backup/strings.dsp b/VC++Files/strings/backup/strings.dsp
index 45b22c52e21..a6be39b40ab 100644
--- a/VC++Files/strings/backup/strings.dsp
+++ b/VC++Files/strings/backup/strings.dsp
@@ -7,19 +7,19 @@
CFG=strings - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "strings.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "strings.mak" CFG="strings - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "strings - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "strings - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
-!ENDIF
+!ENDIF
# Begin Target
@@ -186,7 +186,7 @@ InputName=Strings
# End Custom Build
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -233,7 +233,7 @@ InputName=Strxmov
# End Custom Build
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
diff --git a/VC++Files/strings/backup/strings.dsw b/VC++Files/strings/backup/strings.dsw
index e3777b8e7d5..63fc3706c19 100644
--- a/VC++Files/strings/backup/strings.dsw
+++ b/VC++Files/strings/backup/strings.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/strings/noMASM/strings.dsp b/VC++Files/strings/noMASM/strings.dsp
index a84fb1b7835..6e2dbb3c013 100644
--- a/VC++Files/strings/noMASM/strings.dsp
+++ b/VC++Files/strings/noMASM/strings.dsp
@@ -7,19 +7,19 @@
CFG=strings - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "strings.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "strings.mak" CFG="strings - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "strings - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "strings - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -76,7 +76,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/strings/noMASM/strings.dsw b/VC++Files/strings/noMASM/strings.dsw
index e3777b8e7d5..63fc3706c19 100644
--- a/VC++Files/strings/noMASM/strings.dsw
+++ b/VC++Files/strings/noMASM/strings.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/strings/strings.dsp b/VC++Files/strings/strings.dsp
index 52655947790..2f206b30ba6 100644
--- a/VC++Files/strings/strings.dsp
+++ b/VC++Files/strings/strings.dsp
@@ -25,7 +25,7 @@ CFG=strings - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
RSC=rc.exe
!IF "$(CFG)" == "strings - Win32 Release"
@@ -48,7 +48,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_release\strings.lib"
@@ -72,7 +72,7 @@ LIB32=link.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=link.exe -lib
+LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
@@ -108,6 +108,10 @@ SOURCE=".\ctype-big5.c"
# End Source File
# Begin Source File
+SOURCE=".\ctype-bin.c"
+# End Source File
+# Begin Source File
+
SOURCE=".\ctype-czech.c"
# End Source File
# Begin Source File
@@ -128,6 +132,14 @@ SOURCE=".\ctype-latin1_de.c"
# End Source File
# Begin Source File
+SOURCE=".\ctype-mb.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-simple.c"
+# End Source File
+# Begin Source File
+
SOURCE=".\ctype-sjis.c"
# End Source File
# Begin Source File
@@ -140,6 +152,14 @@ SOURCE=".\ctype-ujis.c"
# End Source File
# Begin Source File
+SOURCE=".\ctype-utf8.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-win1250ch.c"
+# End Source File
+# Begin Source File
+
SOURCE=.\ctype.c
# End Source File
# Begin Source File
@@ -156,6 +176,10 @@ SOURCE=.\longlong2str.c
# End Source File
# Begin Source File
+SOURCE=.\my_vsnprintf.c
+# End Source File
+# Begin Source File
+
SOURCE=.\r_strinstr.c
# End Source File
# Begin Source File
@@ -244,5 +268,9 @@ InputName=Strxmov
SOURCE=.\strxnmov.c
# End Source File
+# Begin Source File
+
+SOURCE=.\xml.c
+# End Source File
# End Target
# End Project
diff --git a/VC++Files/strings/strings.dsw b/VC++Files/strings/strings.dsw
index e3777b8e7d5..63fc3706c19 100644
--- a/VC++Files/strings/strings.dsw
+++ b/VC++Files/strings/strings.dsw
@@ -26,4 +26,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/VC++Files/test1/test1.dsp b/VC++Files/test1/test1.dsp
index 50a165e3e4d..fb70ceda692 100644
--- a/VC++Files/test1/test1.dsp
+++ b/VC++Files/test1/test1.dsp
@@ -7,19 +7,19 @@
CFG=test1 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "test1.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "test1.mak" CFG="test1 - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "test1 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "test1 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD LINK32 libmysql.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\lib_debug"
# SUBTRACT LINK32 /incremental:no
-!ENDIF
+!ENDIF
# Begin Target
@@ -95,7 +95,7 @@ SOURCE=.\mysql_thr.c
!ELSEIF "$(CFG)" == "test1 - Win32 Debug"
-!ENDIF
+!ENDIF
# End Source File
# End Target
diff --git a/VC++Files/thr_insert_test/thr_insert_test.dsp b/VC++Files/thr_insert_test/thr_insert_test.dsp
index 770125ab65b..11028b926d1 100644
--- a/VC++Files/thr_insert_test/thr_insert_test.dsp
+++ b/VC++Files/thr_insert_test/thr_insert_test.dsp
@@ -7,19 +7,19 @@
CFG=thr_insert_test - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "thr_insert_test.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "thr_insert_test.mak" CFG="thr_insert_test - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "thr_insert_test - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "thr_insert_test - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -83,7 +83,7 @@ LINK32=link.exe
# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:"debug/mysqldump.pdb" /debug /machine:I386 /out:"../client_debug/thr_insert_test.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
# SUBTRACT LINK32 /pdb:none
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/thr_test/thr_test.dsp b/VC++Files/thr_test/thr_test.dsp
index 7256f8da2fa..a7854a66049 100644
--- a/VC++Files/thr_test/thr_test.dsp
+++ b/VC++Files/thr_test/thr_test.dsp
@@ -7,19 +7,19 @@
CFG=thr_test - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "thr_test.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "thr_test.mak" CFG="thr_test - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "thr_test - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "thr_test - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -79,7 +79,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept
-!ENDIF
+!ENDIF
# Begin Target
@@ -97,7 +97,7 @@ SOURCE=.\thr_test.c
# ADD CPP /FAcs
-!ENDIF
+!ENDIF
# End Source File
# End Target
diff --git a/VC++Files/vio/vio.dsp b/VC++Files/vio/vio.dsp
index d4b77aad391..50c920a465d 100644
--- a/VC++Files/vio/vio.dsp
+++ b/VC++Files/vio/vio.dsp
@@ -7,19 +7,19 @@
CFG=vio - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "vio.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "vio.mak" CFG="vio - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "vio - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "vio - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -74,7 +74,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\vio.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/VC++Files/zlib/zlib.dsp b/VC++Files/zlib/zlib.dsp
index b46afad005c..fd9d6b2bd68 100644
--- a/VC++Files/zlib/zlib.dsp
+++ b/VC++Files/zlib/zlib.dsp
@@ -7,19 +7,19 @@
CFG=zlib - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "zlib.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "zlib - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "zlib - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -75,7 +75,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\zlib.lib"
-!ENDIF
+!ENDIF
# Begin Target
diff --git a/acconfig.h b/acconfig.h
index 4b4fde6bff6..5f47365709c 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -18,6 +18,9 @@
#undef CRAY_STACKSEG_END
+/* Define the default charset name */
+#undef DEFAULT_CHARSET_NAME
+
/* Version of .frm files */
#undef DOT_FRM_VERSION
@@ -63,6 +66,43 @@
/* READLINE: */
#undef HAVE_BSD_SIGNALS
+/* Define charsets you want */
+#undef HAVE_CHARSET_armscii8
+#undef HAVE_CHARSET_big5
+#undef HAVE_CHARSET_cp1251
+#undef HAVE_CHARSET_cp1257
+#undef HAVE_CHARSET_croat
+#undef HAVE_CHARSET_czech
+#undef HAVE_CHARSET_danish
+#undef HAVE_CHARSET_dec8
+#undef HAVE_CHARSET_dos
+#undef HAVE_CHARSET_estonia
+#undef HAVE_CHARSET_euc_kr
+#undef HAVE_CHARSET_gb2312
+#undef HAVE_CHARSET_gbk
+#undef HAVE_CHARSET_german1
+#undef HAVE_CHARSET_greek
+#undef HAVE_CHARSET_hebrew
+#undef HAVE_CHARSET_hp8
+#undef HAVE_CHARSET_hungarian
+#undef HAVE_CHARSET_koi8_ru
+#undef HAVE_CHARSET_koi8_ukr
+#undef HAVE_CHARSET_latin1
+#undef HAVE_CHARSET_latin1_de
+#undef HAVE_CHARSET_latin2
+#undef HAVE_CHARSET_latin5
+#undef HAVE_CHARSET_sjis
+#undef HAVE_CHARSET_swe7
+#undef HAVE_CHARSET_tis620
+#undef HAVE_CHARSET_ucs2
+#undef HAVE_CHARSET_ujis
+#undef HAVE_CHARSET_usa7
+#undef HAVE_CHARSET_utf8
+#undef HAVE_CHARSET_win1250
+#undef HAVE_CHARSET_win1250ch
+#undef HAVE_CHARSET_win1251ukr
+#undef HAVE_CHARSET_win1251
+
/* ZLIB and compress: */
#undef HAVE_COMPRESS
@@ -269,15 +309,28 @@
/* Use MySQL RAID */
#undef USE_RAID
-/* Use strcoll() functions when comparing and sorting. */
-#undef USE_STRCOLL
-
/* Program version */
#undef VERSION
/* READLINE: */
#undef VOID_SIGHANDLER
+/* used libedit interface (can we dereference result of rl_completion_entry_function?) */
+#undef USE_LIBEDIT_INTERFACE
+
+/* used new readline interface (does rl_completion_func_t and rl_compentry_func_t defined?) */
+#undef USE_NEW_READLINE_INTERFACE
+
+/* macro for libedit */
+#undef HAVE_VIS_H
+#undef HAVE_FGETLN
+#undef HAVE_ISSETUGID
+#undef HAVE_STRLCPY
+#undef HAVE_GETLINE
+#undef HAVE_FLOCKFILE
+#undef HAVE_SYS_TYPES_H
+#undef HAVE_SYS_CDEFS_H
+
/* Leave that blank line there!! Autoheader needs it.
If you're adding to this file, keep in mind:
diff --git a/acinclude.m4 b/acinclude.m4
index cf0233fa38f..970620d9be7 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1,5 +1,45 @@
# Local macros for automake & autoconf
+AC_DEFUN(MYSQL_CHECK_LIBEDIT_INTERFACE,[
+ AC_CACHE_CHECK([libedit variant of rl_completion_entry_function], mysql_cv_libedit_interface,
+ AC_TRY_COMPILE(
+ [
+ #include "stdio.h"
+ #include "readline/readline.h"
+ ],
+ [
+ char res= *(*rl_completion_entry_function)(0,0);
+ completion_matches(0,0);
+ ],
+ [
+ mysql_cv_libedit_interface=yes
+ AC_DEFINE_UNQUOTED(USE_LIBEDIT_INTERFACE)
+ ],
+ [mysql_cv_libedit_interface=no]
+ )
+ )
+])
+
+AC_DEFUN(MYSQL_CHECK_NEW_RL_INTERFACE,[
+ AC_CACHE_CHECK([defined rl_compentry_func_t and rl_completion_func_t], mysql_cv_new_rl_interface,
+ AC_TRY_COMPILE(
+ [
+ #include "stdio.h"
+ #include "readline/readline.h"
+ ],
+ [
+ rl_completion_func_t *func1= (rl_completion_func_t*)0;
+ rl_compentry_func_t *func2= (rl_compentry_func_t*)0;
+ ],
+ [
+ mysql_cv_new_rl_interface=yes
+ AC_DEFINE_UNQUOTED(USE_NEW_READLINE_INTERFACE)
+ ],
+ [mysql_cv_new_rl_interface=no]
+ )
+ )
+])
+
# A local version of AC_CHECK_SIZEOF that includes sys/types.h
dnl MYSQL_CHECK_SIZEOF(TYPE [, CROSS-SIZE])
AC_DEFUN(MYSQL_CHECK_SIZEOF,
@@ -1063,24 +1103,28 @@ AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [
test -z "$db_patch" && db_patch=0
# This is ugly, but about as good as it can get
- mysql_bdb=
- if test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 3
- then
- mysql_bdb=h
- elif test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 9
- then
- want_bdb_version="3.2.9a" # hopefully this will stay up-to-date
- mysql_bdb=a
- fi
-
- if test -n "$mysql_bdb" && \
- grep "DB_VERSION_STRING.*:.*$mysql_bdb: " [$1] > /dev/null
- then
- bdb_version_ok=yes
- else
- bdb_version_ok="invalid version $db_major.$db_minor.$db_patch"
- bdb_version_ok="$bdb_version_ok (must be version 3.2.3h or $want_bdb_version)"
- fi
+# mysql_bdb=
+# if test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 3
+# then
+# mysql_bdb=h
+# elif test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 9
+# then
+# want_bdb_version="3.2.9a" # hopefully this will stay up-to-date
+# mysql_bdb=a
+# fi
+
+dbl RAM:
+want_bdb_version="4.1.24"
+bdb_version_ok=yes
+
+# if test -n "$mysql_bdb" && \
+# grep "DB_VERSION_STRING.*:.*$mysql_bdb: " [$1] > /dev/null
+# then
+# bdb_version_ok=yes
+# else
+# bdb_version_ok="invalid version $db_major.$db_minor.$db_patch"
+# bdb_version_ok="$bdb_version_ok (must be version 3.2.3h or $want_bdb_version)"
+# fi
])
AC_DEFUN([MYSQL_TOP_BUILDDIR], [
diff --git a/bdb/LICENSE b/bdb/LICENSE
index 32cc483d68a..1cd727bfd98 100644
--- a/bdb/LICENSE
+++ b/bdb/LICENSE
@@ -1,5 +1,5 @@
/*-
- * $Id: LICENSE,v 11.7 2000/11/01 20:35:49 bostic Exp $
+ * $Id: LICENSE,v 11.9 2002/01/11 15:51:10 bostic Exp $
*/
The following is the license that applies to this copy of the Berkeley DB
@@ -10,7 +10,7 @@ Web at http://www.sleepycat.com.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/*
- * Copyright (c) 1990-2000
+ * Copyright (c) 1990-2002
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/bdb/Makefile.in b/bdb/Makefile.in
index 92c5b6ff54e..c83d40ac8b2 100644
--- a/bdb/Makefile.in
+++ b/bdb/Makefile.in
@@ -24,12 +24,13 @@ top_srcdir = @top_srcdir@
bdb_build = build_unix
files = LICENSE Makefile Makefile.in README
-subdirs = btree build_vxworks build_win32 clib common cxx db db185 \
- db_archive db_checkpoint db_deadlock db_dump db_dump185 db_load \
- db_printlog db_recover db_stat db_upgrade db_verify dbm dist \
- env examples_c examples_cxx hash hsearch include java libdb_java \
- lock log mp mutex os os_vxworks os_win32 perl.BerkeleyDB \
- perl.DB_File qam rpc_client rpc_server tcl test txn xa
+subdirs = btree build_vxworks build_win32 clib common cxx db dbinc \
+ dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \
+ db_dump185 db_load db_printlog db_recover db_stat db_upgrade \
+ db_verify dbm dbreg dist env examples_c examples_cxx fileops hash \
+ hsearch hmac include java libdb_java lock log mp mutex os os_vxworks \
+ os_win32 perl.BerkeleyDB perl.DB_File qam rep rpc_client rpc_server tcl \
+ test txn xa
@SET_MAKE@
diff --git a/bdb/btree/bt_compare.c b/bdb/btree/bt_compare.c
index 91481c31366..cbe2a1a7170 100644
--- a/bdb/btree/bt_compare.c
+++ b/bdb/btree/bt_compare.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_compare.c,v 11.12 2000/10/26 19:00:28 krinsky Exp $";
+static const char revid[] = "$Id: bt_compare.c,v 11.17 2002/03/27 04:30:42 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -51,8 +51,8 @@ static const char revid[] = "$Id: bt_compare.c,v 11.12 2000/10/26 19:00:28 krins
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
/*
* __bam_cmp --
@@ -92,7 +92,7 @@ __bam_cmp(dbp, dbt, h, indx, func, cmpp)
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW)
bo = (BOVERFLOW *)bk;
else {
@@ -125,7 +125,7 @@ __bam_cmp(dbp, dbt, h, indx, func, cmpp)
return (0);
}
- bi = GET_BINTERNAL(h, indx);
+ bi = GET_BINTERNAL(dbp, h, indx);
if (B_TYPE(bi->type) == B_OVERFLOW)
bo = (BOVERFLOW *)(bi->data);
else {
@@ -136,7 +136,7 @@ __bam_cmp(dbp, dbt, h, indx, func, cmpp)
}
break;
default:
- return (__db_pgfmt(dbp, PGNO(h)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
/*
diff --git a/bdb/btree/bt_conv.c b/bdb/btree/bt_conv.c
index fd30f375f7c..4264b62ffdd 100644
--- a/bdb/btree/bt_conv.c
+++ b/bdb/btree/bt_conv.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_conv.c,v 11.6 2000/03/31 00:30:26 ubell Exp $";
+static const char revid[] = "$Id: bt_conv.c,v 11.13 2002/08/06 06:11:12 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,20 +16,21 @@ static const char revid[] = "$Id: bt_conv.c,v 11.6 2000/03/31 00:30:26 ubell Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
/*
* __bam_pgin --
* Convert host-specific page layout from the host-independent format
* stored on disk.
*
- * PUBLIC: int __bam_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
+ * PUBLIC: int __bam_pgin __P((DB_ENV *, DB *, db_pgno_t, void *, DBT *));
*/
int
-__bam_pgin(dbenv, pg, pp, cookie)
+__bam_pgin(dbenv, dummydbp, pg, pp, cookie)
DB_ENV *dbenv;
+ DB *dummydbp;
db_pgno_t pg;
void *pp;
DBT *cookie;
@@ -38,12 +39,12 @@ __bam_pgin(dbenv, pg, pp, cookie)
PAGE *h;
pginfo = (DB_PGINFO *)cookie->data;
- if (!pginfo->needswap)
+ if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
h = pp;
return (TYPE(h) == P_BTREEMETA ? __bam_mswap(pp) :
- __db_byteswap(dbenv, pg, pp, pginfo->db_pagesize, 1));
+ __db_byteswap(dbenv, dummydbp, pg, pp, pginfo->db_pagesize, 1));
}
/*
@@ -51,11 +52,12 @@ __bam_pgin(dbenv, pg, pp, cookie)
* Convert host-specific page layout to the host-independent format
* stored on disk.
*
- * PUBLIC: int __bam_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
+ * PUBLIC: int __bam_pgout __P((DB_ENV *, DB *, db_pgno_t, void *, DBT *));
*/
int
-__bam_pgout(dbenv, pg, pp, cookie)
+__bam_pgout(dbenv, dummydbp, pg, pp, cookie)
DB_ENV *dbenv;
+ DB *dummydbp;
db_pgno_t pg;
void *pp;
DBT *cookie;
@@ -64,12 +66,12 @@ __bam_pgout(dbenv, pg, pp, cookie)
PAGE *h;
pginfo = (DB_PGINFO *)cookie->data;
- if (!pginfo->needswap)
+ if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
h = pp;
return (TYPE(h) == P_BTREEMETA ? __bam_mswap(pp) :
- __db_byteswap(dbenv, pg, pp, pginfo->db_pagesize, 0));
+ __db_byteswap(dbenv, dummydbp, pg, pp, pginfo->db_pagesize, 0));
}
/*
@@ -93,6 +95,8 @@ __bam_mswap(pg)
SWAP32(p); /* re_len */
SWAP32(p); /* re_pad */
SWAP32(p); /* root */
+ p += 92 * sizeof(u_int32_t); /* unused */
+ SWAP32(p); /* crypto_magic */
return (0);
}
diff --git a/bdb/btree/bt_curadj.c b/bdb/btree/bt_curadj.c
index 011acd2f4a1..50d3d422e49 100644
--- a/bdb/btree/bt_curadj.c
+++ b/bdb/btree/bt_curadj.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_curadj.c,v 11.20 2001/01/17 16:15:49 bostic Exp $";
+static const char revid[] = "$Id: bt_curadj.c,v 11.30 2002/07/03 19:03:48 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,9 +16,8 @@ static const char revid[] = "$Id: bt_curadj.c,v 11.20 2001/01/17 16:15:49 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
@@ -203,10 +202,9 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
- if (found != 0 && DB_LOGGING(my_dbc)) {
- if ((ret = __bam_curadj_log(dbenv,
- my_dbc->txn, &lsn, 0, dbp->log_fileid,
- DB_CA_DI, pgno, 0, 0, adjust, indx, 0)) != 0)
+ if (found != 0 && DBC_LOGGING(my_dbc)) {
+ if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
+ &lsn, 0, DB_CA_DI, pgno, 0, 0, adjust, indx, 0)) != 0)
return (ret);
}
@@ -234,8 +232,13 @@ __bam_opd_cursor(dbp, dbc, first, tpgno, ti)
* Allocate a new cursor and create the stack. If duplicates
* are sorted, we've just created an off-page duplicate Btree.
* If duplicates aren't sorted, we've just created a Recno tree.
+ *
+ * Note that in order to get here at all, there shouldn't be
+ * an old off-page dup cursor--to augment the checking db_c_newopd
+ * will do, assert this.
*/
- if ((ret = __db_c_newopd(dbc, tpgno, &dbc_nopd)) != 0)
+ DB_ASSERT(orig_cp->opd == NULL);
+ if ((ret = __db_c_newopd(dbc, tpgno, orig_cp->opd, &dbc_nopd)) != 0)
return (ret);
cp = (BTREE_CURSOR *)dbc_nopd->internal;
@@ -321,17 +324,16 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
return (ret);
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
- /* We released the MUTEX to get a cursor, start over. */
+ /* We released the mutex to get a cursor, start over. */
goto loop;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
- if (found != 0 && DB_LOGGING(my_dbc)) {
- if ((ret = __bam_curadj_log(dbenv,
- my_dbc->txn, &lsn, 0, dbp->log_fileid,
- DB_CA_DUP, fpgno, tpgno, 0, first, fi, ti)) != 0)
+ if (found != 0 && DBC_LOGGING(my_dbc)) {
+ if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
+ &lsn, 0, DB_CA_DUP, fpgno, tpgno, 0, first, fi, ti)) != 0)
return (ret);
}
return (0);
@@ -372,8 +374,16 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
orig_cp = (BTREE_CURSOR *)dbc->internal;
+ /*
+ * A note on the orig_cp->opd != NULL requirement here:
+ * it's possible that there's a cursor that refers to
+ * the same duplicate set, but which has no opd cursor,
+ * because it refers to a different item and we took
+ * care of it while processing a previous record.
+ */
if (orig_cp->pgno != fpgno ||
orig_cp->indx != first ||
+ orig_cp->opd == NULL ||
((BTREE_CURSOR *)orig_cp->opd->internal)->indx
!= ti)
continue;
@@ -383,7 +393,7 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
orig_cp->opd = NULL;
orig_cp->indx = fi;
/*
- * We released the MUTEX to free a cursor,
+ * We released the mutex to free a cursor,
* start over.
*/
goto loop;
@@ -440,10 +450,9 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
- if (found != 0 && DB_LOGGING(my_dbc)) {
- if ((ret = __bam_curadj_log(dbenv,
- my_dbc->txn, &lsn, 0, dbp->log_fileid,
- DB_CA_RSPLIT, fpgno, tpgno, 0, 0, 0, 0)) != 0)
+ if (found != 0 && DBC_LOGGING(my_dbc)) {
+ if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
+ &lsn, 0, DB_CA_RSPLIT, fpgno, tpgno, 0, 0, 0, 0)) != 0)
return (ret);
}
return (0);
@@ -512,9 +521,9 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
- if (found != 0 && DB_LOGGING(my_dbc)) {
- if ((ret = __bam_curadj_log(dbenv, my_dbc->txn,
- &lsn, 0, dbp->log_fileid, DB_CA_SPLIT, ppgno, rpgno,
+ if (found != 0 && DBC_LOGGING(my_dbc)) {
+ if ((ret = __bam_curadj_log(dbp,
+ my_dbc->txn, &lsn, 0, DB_CA_SPLIT, ppgno, rpgno,
cleft ? lpgno : PGNO_INVALID, 0, split_indx, 0)) != 0)
return (ret);
}
diff --git a/bdb/btree/bt_cursor.c b/bdb/btree/bt_cursor.c
index 84ab7c80744..14d90e8873d 100644
--- a/bdb/btree/bt_cursor.c
+++ b/bdb/btree/bt_cursor.c
@@ -1,31 +1,29 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_cursor.c,v 11.88 2001/01/11 18:19:49 bostic Exp $";
+static const char revid[] = "$Id: bt_cursor.c,v 11.147 2002/08/13 20:46:07 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "lock.h"
-#include "qam.h"
-#include "common_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
+static int __bam_bulk __P((DBC *, DBT *, u_int32_t));
static int __bam_c_close __P((DBC *, db_pgno_t, int *));
static int __bam_c_del __P((DBC *));
static int __bam_c_destroy __P((DBC *));
@@ -33,15 +31,16 @@ static int __bam_c_first __P((DBC *));
static int __bam_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __bam_c_getstack __P((DBC *));
static int __bam_c_last __P((DBC *));
-static int __bam_c_next __P((DBC *, int));
+static int __bam_c_next __P((DBC *, int, int));
static int __bam_c_physdel __P((DBC *));
static int __bam_c_prev __P((DBC *));
static int __bam_c_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
-static void __bam_c_reset __P((BTREE_CURSOR *));
-static int __bam_c_search __P((DBC *, const DBT *, u_int32_t, int *));
+static int __bam_c_search __P((DBC *,
+ db_pgno_t, const DBT *, u_int32_t, int *));
static int __bam_c_writelock __P((DBC *));
-static int __bam_getboth_finddatum __P((DBC *, DBT *));
+static int __bam_getboth_finddatum __P((DBC *, DBT *, u_int32_t));
static int __bam_getbothc __P((DBC *, DBT *));
+static int __bam_get_prev __P((DBC *));
static int __bam_isopd __P((DBC *, db_pgno_t *));
/*
@@ -53,48 +52,60 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
* don't -- we don't duplicate locks when we duplicate cursors if we are
* running in a transaction environment as there's no point if locks are
* never discarded. This means that the cursor may or may not hold a lock.
+ * In the case where we are decending the tree we always want to
+ * unlock the held interior page so we use ACQUIRE_COUPLE.
*/
#undef ACQUIRE
-#define ACQUIRE(dbc, mode, lpgno, lock, fpgno, pagep, ret) {\
+#define ACQUIRE(dbc, mode, lpgno, lock, fpgno, pagep, ret) { \
+ DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \
if ((pagep) != NULL) { \
- ret = memp_fput((dbc)->dbp->mpf, pagep, 0); \
+ ret = __mpf->put(__mpf, pagep, 0); \
+ pagep = NULL; \
+ } else \
+ ret = 0; \
+ if ((ret) == 0 && STD_LOCKING(dbc)) \
+ ret = __db_lget(dbc, LCK_COUPLE, lpgno, mode, 0, &(lock));\
+ if ((ret) == 0) \
+ ret = __mpf->get(__mpf, &(fpgno), 0, &(pagep)); \
+}
+
+#undef ACQUIRE_COUPLE
+#define ACQUIRE_COUPLE(dbc, mode, lpgno, lock, fpgno, pagep, ret) { \
+ DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \
+ if ((pagep) != NULL) { \
+ ret = __mpf->put(__mpf, pagep, 0); \
pagep = NULL; \
} else \
ret = 0; \
if ((ret) == 0 && STD_LOCKING(dbc)) \
ret = __db_lget(dbc, \
- (lock).off == LOCK_INVALID ? 0 : LCK_COUPLE, \
- lpgno, mode, 0, &lock); \
- else \
- (lock).off = LOCK_INVALID; \
+ LCK_COUPLE_ALWAYS, lpgno, mode, 0, &(lock)); \
if ((ret) == 0) \
- ret = memp_fget((dbc)->dbp->mpf, &(fpgno), 0, &(pagep));\
+ ret = __mpf->get(__mpf, &(fpgno), 0, &(pagep)); \
}
/* Acquire a new page/lock for a cursor. */
#undef ACQUIRE_CUR
-#define ACQUIRE_CUR(dbc, mode, ret) { \
+#define ACQUIRE_CUR(dbc, mode, p, ret) { \
BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \
- ACQUIRE(dbc, mode, \
- __cp->pgno, __cp->lock, __cp->pgno, __cp->page, ret); \
- if ((ret) == 0) \
+ ACQUIRE(dbc, mode, p, __cp->lock, p, __cp->page, ret); \
+ if ((ret) == 0) { \
+ __cp->pgno = p; \
__cp->lock_mode = (mode); \
+ } \
}
/*
- * Acquire a new page/lock for a cursor, and move the cursor on success.
- * The reason that this is a separate macro is because we don't want to
- * set the pgno/indx fields in the cursor until we actually have the lock,
- * otherwise the cursor adjust routines will adjust the cursor even though
- * we're not really on the page.
+ * Acquire a new page/lock for a cursor and release the previous.
+ * This is typically used when decending a tree and we do not
+ * want to hold the interior nodes locked.
*/
-#undef ACQUIRE_CUR_SET
-#define ACQUIRE_CUR_SET(dbc, mode, p, ret) { \
+#undef ACQUIRE_CUR_COUPLE
+#define ACQUIRE_CUR_COUPLE(dbc, mode, p, ret) { \
BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \
- ACQUIRE(dbc, mode, p, __cp->lock, p, __cp->page, ret); \
+ ACQUIRE_COUPLE(dbc, mode, p, __cp->lock, p, __cp->page, ret); \
if ((ret) == 0) { \
- __cp->pgno = p; \
- __cp->indx = 0; \
+ __cp->pgno = p; \
__cp->lock_mode = (mode); \
} \
}
@@ -112,7 +123,7 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
if (STD_LOCKING(dbc) && \
__cp->lock_mode != DB_LOCK_WRITE && \
((ret) = __db_lget(dbc, \
- __cp->lock.off == LOCK_INVALID ? 0 : LCK_COUPLE, \
+ LOCK_ISSET(__cp->lock) ? LCK_COUPLE : 0, \
__cp->pgno, DB_LOCK_WRITE, 0, &__cp->lock)) == 0) \
__cp->lock_mode = DB_LOCK_WRITE; \
}
@@ -120,19 +131,19 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
/* Discard the current page/lock. */
#undef DISCARD
#define DISCARD(dbc, ldiscard, lock, pagep, ret) { \
+ DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \
int __t_ret; \
if ((pagep) != NULL) { \
- ret = memp_fput((dbc)->dbp->mpf, pagep, 0); \
+ ret = __mpf->put(__mpf, pagep, 0); \
pagep = NULL; \
} else \
ret = 0; \
- if ((lock).off != LOCK_INVALID) { \
- __t_ret = ldiscard ? \
- __LPUT((dbc), lock): __TLPUT((dbc), lock); \
- if (__t_ret != 0 && (ret) == 0) \
- ret = __t_ret; \
- (lock).off = LOCK_INVALID; \
- } \
+ if (ldiscard) \
+ __t_ret = __LPUT((dbc), lock); \
+ else \
+ __t_ret = __TLPUT((dbc), lock); \
+ if (__t_ret != 0 && (ret) == 0) \
+ ret = __t_ret; \
}
/* Discard the current page/lock for a cursor. */
@@ -146,12 +157,12 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
/* If on-page item is a deleted record. */
#undef IS_DELETED
-#define IS_DELETED(page, indx) \
- B_DISSET(GET_BKEYDATA(page, \
+#define IS_DELETED(dbp, page, indx) \
+ B_DISSET(GET_BKEYDATA(dbp, page, \
(indx) + (TYPE(page) == P_LBTREE ? O_INDX : 0))->type)
#undef IS_CUR_DELETED
#define IS_CUR_DELETED(dbc) \
- IS_DELETED((dbc)->internal->page, (dbc)->internal->indx)
+ IS_DELETED((dbc)->dbp, (dbc)->internal->page, (dbc)->internal->indx)
/*
* Test to see if two cursors could point to duplicates of the same key.
@@ -163,8 +174,8 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
*/
#undef IS_DUPLICATE
#define IS_DUPLICATE(dbc, i1, i2) \
- (((PAGE *)(dbc)->internal->page)->inp[i1] == \
- ((PAGE *)(dbc)->internal->page)->inp[i2])
+ (P_INP((dbc)->dbp,((PAGE *)(dbc)->internal->page))[i1] == \
+ P_INP((dbc)->dbp,((PAGE *)(dbc)->internal->page))[i2])
#undef IS_CUR_DUPLICATE
#define IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx) \
(F_ISSET(dbc, DBC_OPD) || \
@@ -172,22 +183,6 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
IS_DUPLICATE(dbc, (dbc)->internal->indx, orig_indx)))
/*
- * __bam_c_reset --
- * Initialize internal cursor structure.
- */
-static void
-__bam_c_reset(cp)
- BTREE_CURSOR *cp;
-{
- cp->csp = cp->sp;
- cp->lock.off = LOCK_INVALID;
- cp->lock_mode = DB_LOCK_NG;
- cp->recno = RECNO_OOB;
- cp->order = INVALID_ORDER;
- cp->flags = 0;
-}
-
-/*
* __bam_c_init --
* Initialize the access private portion of a cursor
*
@@ -198,35 +193,26 @@ __bam_c_init(dbc, dbtype)
DBC *dbc;
DBTYPE dbtype;
{
- BTREE *t;
- BTREE_CURSOR *cp;
- DB *dbp;
+ DB_ENV *dbenv;
int ret;
- u_int32_t minkey;
- dbp = dbc->dbp;
+ dbenv = dbc->dbp->dbenv;
/* Allocate/initialize the internal structure. */
- if (dbc->internal == NULL) {
- if ((ret = __os_malloc(dbp->dbenv,
- sizeof(BTREE_CURSOR), NULL, &cp)) != 0)
- return (ret);
- dbc->internal = (DBC_INTERNAL *)cp;
-
- cp->sp = cp->csp = cp->stack;
- cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]);
- } else
- cp = (BTREE_CURSOR *)dbc->internal;
- __bam_c_reset(cp);
+ if (dbc->internal == NULL && (ret =
+ __os_malloc(dbenv, sizeof(BTREE_CURSOR), &dbc->internal)) != 0)
+ return (ret);
/* Initialize methods. */
dbc->c_close = __db_c_close;
dbc->c_count = __db_c_count;
dbc->c_del = __db_c_del;
dbc->c_dup = __db_c_dup;
- dbc->c_get = __db_c_get;
+ dbc->c_get = dbc->c_real_get = __db_c_get;
+ dbc->c_pget = __db_c_pget;
dbc->c_put = __db_c_put;
if (dbtype == DB_BTREE) {
+ dbc->c_am_bulk = __bam_bulk;
dbc->c_am_close = __bam_c_close;
dbc->c_am_del = __bam_c_del;
dbc->c_am_destroy = __bam_c_destroy;
@@ -234,6 +220,7 @@ __bam_c_init(dbc, dbtype)
dbc->c_am_put = __bam_c_put;
dbc->c_am_writelock = __bam_c_writelock;
} else {
+ dbc->c_am_bulk = __bam_bulk;
dbc->c_am_close = __bam_c_close;
dbc->c_am_del = __ram_c_del;
dbc->c_am_destroy = __bam_c_destroy;
@@ -242,18 +229,6 @@ __bam_c_init(dbc, dbtype)
dbc->c_am_writelock = __bam_c_writelock;
}
- /*
- * The btree leaf page data structures require that two key/data pairs
- * (or four items) fit on a page, but other than that there's no fixed
- * requirement. The btree off-page duplicates only require two items,
- * to be exact, but requiring four for them as well seems reasonable.
- *
- * Recno uses the btree bt_ovflsize value -- it's close enough.
- */
- t = dbp->bt_internal;
- minkey = F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey;
- cp->ovflsize = B_MINKEY_TO_OVFLSIZE(minkey, dbp->pgsize);
-
return (0);
}
@@ -267,12 +242,13 @@ int
__bam_c_refresh(dbc)
DBC *dbc;
{
+ BTREE *t;
BTREE_CURSOR *cp;
DB *dbp;
dbp = dbc->dbp;
+ t = dbp->bt_internal;
cp = (BTREE_CURSOR *)dbc->internal;
- __bam_c_reset(cp);
/*
* If our caller set the root page number, it's because the root was
@@ -280,11 +256,32 @@ __bam_c_refresh(dbc)
* pull it out of our internal information.
*/
if (cp->root == PGNO_INVALID)
- cp->root = ((BTREE *)dbp->bt_internal)->bt_root;
+ cp->root = t->bt_root;
+
+ LOCK_INIT(cp->lock);
+ cp->lock_mode = DB_LOCK_NG;
+
+ cp->sp = cp->csp = cp->stack;
+ cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]);
+
+ /*
+ * The btree leaf page data structures require that two key/data pairs
+ * (or four items) fit on a page, but other than that there's no fixed
+ * requirement. The btree off-page duplicates only require two items,
+ * to be exact, but requiring four for them as well seems reasonable.
+ *
+ * Recno uses the btree bt_ovflsize value -- it's close enough.
+ */
+ cp->ovflsize = B_MINKEY_TO_OVFLSIZE(
+ dbp, F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey, dbp->pgsize);
+
+ cp->recno = RECNO_OOB;
+ cp->order = INVALID_ORDER;
+ cp->flags = 0;
/* Initialize for record numbers. */
if (F_ISSET(dbc, DBC_OPD) ||
- dbc->dbtype == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM)) {
+ dbc->dbtype == DB_RECNO || F_ISSET(dbp, DB_AM_RECNUM)) {
F_SET(cp, C_RECNUM);
/*
@@ -293,7 +290,7 @@ __bam_c_refresh(dbc)
* mutable record numbers.
*/
if ((F_ISSET(dbc, DBC_OPD) && dbc->dbtype == DB_RECNO) ||
- F_ISSET(dbp, DB_BT_RECNUM | DB_RE_RENUMBER))
+ F_ISSET(dbp, DB_AM_RECNUM | DB_AM_RENUMBER))
F_SET(cp, C_RENUMBER);
}
@@ -313,11 +310,12 @@ __bam_c_close(dbc, root_pgno, rmroot)
BTREE_CURSOR *cp, *cp_opd, *cp_c;
DB *dbp;
DBC *dbc_opd, *dbc_c;
+ DB_MPOOLFILE *mpf;
PAGE *h;
- u_int32_t num;
int cdb_lock, ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
cp_opd = (dbc_opd = cp->opd) == NULL ?
NULL : (BTREE_CURSOR *)dbc_opd->internal;
@@ -408,10 +406,10 @@ __bam_c_close(dbc, root_pgno, rmroot)
* We will not have been provided a root page number. Acquire
* one from the primary database.
*/
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &h)) != 0)
goto err;
- root_pgno = GET_BOVERFLOW(h, cp->indx + O_INDX)->pgno;
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ root_pgno = GET_BOVERFLOW(dbp, h, cp->indx + O_INDX)->pgno;
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
goto err;
dbc_c = dbc_opd;
@@ -453,18 +451,14 @@ lock: cp_c = (BTREE_CURSOR *)dbc_c->internal;
* info in __db_c_get--the OPD is also a WRITEDUP.
*/
if (CDB_LOCKING(dbp->dbenv)) {
- DB_ASSERT(!F_ISSET(dbc, DBC_OPD) || F_ISSET(dbc, DBC_WRITEDUP));
- if (!F_ISSET(dbc, DBC_WRITER)) {
- if ((ret =
- lock_get(dbp->dbenv, dbc->locker, DB_LOCK_UPGRADE,
+ if (F_ISSET(dbc, DBC_WRITEDUP | DBC_WRITECURSOR)) {
+ if ((ret = dbp->dbenv->lock_get(
+ dbp->dbenv, dbc->locker, DB_LOCK_UPGRADE,
&dbc->lock_dbt, DB_LOCK_WRITE, &dbc->mylock)) != 0)
goto err;
cdb_lock = 1;
}
-
- cp_c->lock.off = LOCK_INVALID;
- if ((ret =
- memp_fget(dbp->mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
goto err;
goto delete;
@@ -480,9 +474,7 @@ lock: cp_c = (BTREE_CURSOR *)dbc_c->internal;
* is responsible for acquiring any necessary locks before calling us.
*/
if (F_ISSET(dbc, DBC_OPD)) {
- cp_c->lock.off = LOCK_INVALID;
- if ((ret =
- memp_fget(dbp->mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
goto err;
goto delete;
}
@@ -542,13 +534,13 @@ delete: /*
* in that case. So, if the off-page duplicate tree is empty at this
* point, we want to remove it.
*/
- if ((ret = memp_fget(dbp->mpf, &root_pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0)
goto err;
- if ((num = NUM_ENT(h)) == 0) {
+ if (NUM_ENT(h) == 0) {
if ((ret = __db_free(dbc, h)) != 0)
goto err;
} else {
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
goto err;
goto done;
}
@@ -566,8 +558,7 @@ delete: /*
* the primary page.
*/
if (dbc_opd != NULL) {
- cp->lock.off = LOCK_INVALID;
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
goto err;
if ((ret = __bam_c_physdel(dbc)) != 0)
goto err;
@@ -604,7 +595,7 @@ __bam_c_destroy(dbc)
DBC *dbc;
{
/* Discard the structures. */
- __os_free(dbc->internal, sizeof(BTREE_CURSOR));
+ __os_free(dbc->dbp->dbenv, dbc->internal);
return (0);
}
@@ -622,11 +613,13 @@ __bam_c_count(dbc, recnop)
{
BTREE_CURSOR *cp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
db_indx_t indx, top;
db_recno_t recno;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
@@ -637,7 +630,7 @@ __bam_c_count(dbc, recnop)
* new locks, we have to have a read lock to even get here.
*/
if (cp->opd == NULL) {
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
return (ret);
/*
@@ -654,14 +647,14 @@ __bam_c_count(dbc, recnop)
break;
*recnop = recno;
} else {
- if ((ret = memp_fget(dbp->mpf,
- &cp->opd->internal->root, 0, &cp->page)) != 0)
+ if ((ret =
+ mpf->get(mpf, &cp->opd->internal->root, 0, &cp->page)) != 0)
return (ret);
*recnop = RE_NREC(cp->page);
}
- ret = memp_fput(dbp->mpf, cp->page, 0);
+ ret = mpf->put(mpf, cp->page, 0);
cp->page = NULL;
return (ret);
@@ -677,9 +670,11 @@ __bam_c_del(dbc)
{
BTREE_CURSOR *cp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
int ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
@@ -706,25 +701,27 @@ __bam_c_del(dbc)
goto err;
cp->page = cp->csp->page;
} else {
- ACQUIRE_CUR(dbc, DB_LOCK_WRITE, ret);
+ ACQUIRE_CUR(dbc, DB_LOCK_WRITE, cp->pgno, ret);
if (ret != 0)
goto err;
}
/* Log the change. */
- if (DB_LOGGING(dbc) &&
- (ret = __bam_cdel_log(dbp->dbenv, dbc->txn, &LSN(cp->page), 0,
- dbp->log_fileid, PGNO(cp->page), &LSN(cp->page), cp->indx)) != 0)
- goto err;
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __bam_cdel_log(dbp, dbc->txn, &LSN(cp->page), 0,
+ PGNO(cp->page), &LSN(cp->page), cp->indx)) != 0)
+ goto err;
+ } else
+ LSN_NOT_LOGGED(LSN(cp->page));
/* Set the intent-to-delete flag on the page. */
if (TYPE(cp->page) == P_LBTREE)
- B_DSET(GET_BKEYDATA(cp->page, cp->indx + O_INDX)->type);
+ B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx + O_INDX)->type);
else
- B_DSET(GET_BKEYDATA(cp->page, cp->indx)->type);
+ B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type);
/* Mark the page dirty. */
- ret = memp_fset(dbp->mpf, cp->page, DB_MPOOL_DIRTY);
+ ret = mpf->set(mpf, cp->page, DB_MPOOL_DIRTY);
err: /*
* If we've been successful so far and the tree has record numbers,
@@ -736,7 +733,7 @@ err: /*
(void)__bam_stkrel(dbc, 0);
} else
if (cp->page != NULL &&
- (t_ret = memp_fput(dbp->mpf, cp->page, 0)) != 0 && ret == 0)
+ (t_ret = mpf->put(mpf, cp->page, 0)) != 0 && ret == 0)
ret = t_ret;
cp->page = NULL;
@@ -771,7 +768,7 @@ __bam_c_dup(orig_dbc, new_dbc)
* holding inside a transaction because all the locks are retained
* until the transaction commits or aborts.
*/
- if (orig->lock.off != LOCK_INVALID && orig_dbc->txn == NULL) {
+ if (LOCK_ISSET(orig->lock) && orig_dbc->txn == NULL) {
if ((ret = __db_lget(new_dbc,
0, new->pgno, new->lock_mode, 0, &new->lock)) != 0)
return (ret);
@@ -796,11 +793,13 @@ __bam_c_get(dbc, key, data, flags, pgnop)
{
BTREE_CURSOR *cp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
db_pgno_t orig_pgno;
db_indx_t orig_indx;
int exact, newopd, ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
orig_pgno = cp->pgno;
orig_indx = cp->indx;
@@ -820,7 +819,7 @@ __bam_c_get(dbc, key, data, flags, pgnop)
* write lock, but upgrading to a write lock has no better
* chance of succeeding now instead of later, so don't try.
*/
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
goto err;
break;
case DB_FIRST:
@@ -829,9 +828,10 @@ __bam_c_get(dbc, key, data, flags, pgnop)
goto err;
break;
case DB_GET_BOTH:
+ case DB_GET_BOTH_RANGE:
/*
* There are two ways to get here based on DBcursor->c_get
- * with the DB_GET_BOTH flag set:
+ * with the DB_GET_BOTH/DB_GET_BOTH_RANGE flags set:
*
* 1. Searching a sorted off-page duplicate tree: do a tree
* search.
@@ -839,20 +839,34 @@ __bam_c_get(dbc, key, data, flags, pgnop)
* 2. Searching btree: do a tree search. If it returns a
* reference to off-page duplicate tree, return immediately
* and let our caller deal with it. If the search doesn't
- * return a reference to off-page duplicate tree, start an
- * on-page search.
+ * return a reference to off-page duplicate tree, continue
+ * with an on-page search.
*/
if (F_ISSET(dbc, DBC_OPD)) {
if ((ret = __bam_c_search(
- dbc, data, DB_GET_BOTH, &exact)) != 0)
- goto err;
- if (!exact) {
- ret = DB_NOTFOUND;
+ dbc, PGNO_INVALID, data, flags, &exact)) != 0)
goto err;
+ if (flags == DB_GET_BOTH) {
+ if (!exact) {
+ ret = DB_NOTFOUND;
+ goto err;
+ }
+ break;
}
+
+ /*
+ * We didn't require an exact match, so the search may
+ * may have returned an entry past the end of the page,
+ * or we may be referencing a deleted record. If so,
+ * move to the next entry.
+ */
+ if ((cp->indx == NUM_ENT(cp->page) ||
+ IS_CUR_DELETED(dbc)) &&
+ (ret = __bam_c_next(dbc, 1, 0)) != 0)
+ goto err;
} else {
if ((ret = __bam_c_search(
- dbc, key, DB_GET_BOTH, &exact)) != 0)
+ dbc, PGNO_INVALID, key, flags, &exact)) != 0)
return (ret);
if (!exact) {
ret = DB_NOTFOUND;
@@ -863,7 +877,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
newopd = 1;
break;
}
- if ((ret = __bam_getboth_finddatum(dbc, data)) != 0)
+ if ((ret =
+ __bam_getboth_finddatum(dbc, data, flags)) != 0)
goto err;
}
break;
@@ -882,11 +897,11 @@ __bam_c_get(dbc, key, data, flags, pgnop)
if ((ret = __bam_c_first(dbc)) != 0)
goto err;
} else
- if ((ret = __bam_c_next(dbc, 1)) != 0)
+ if ((ret = __bam_c_next(dbc, 1, 0)) != 0)
goto err;
break;
case DB_NEXT_DUP:
- if ((ret = __bam_c_next(dbc, 1)) != 0)
+ if ((ret = __bam_c_next(dbc, 1, 0)) != 0)
goto err;
if (!IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx)) {
ret = DB_NOTFOUND;
@@ -900,7 +915,7 @@ __bam_c_get(dbc, key, data, flags, pgnop)
goto err;
} else
do {
- if ((ret = __bam_c_next(dbc, 1)) != 0)
+ if ((ret = __bam_c_next(dbc, 1, 0)) != 0)
goto err;
} while (IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx));
break;
@@ -927,12 +942,14 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_SET:
case DB_SET_RECNO:
newopd = 1;
- if ((ret = __bam_c_search(dbc, key, flags, &exact)) != 0)
+ if ((ret = __bam_c_search(dbc,
+ PGNO_INVALID, key, flags, &exact)) != 0)
goto err;
break;
case DB_SET_RANGE:
newopd = 1;
- if ((ret = __bam_c_search(dbc, key, flags, &exact)) != 0)
+ if ((ret = __bam_c_search(dbc,
+ PGNO_INVALID, key, flags, &exact)) != 0)
goto err;
/*
@@ -942,7 +959,7 @@ __bam_c_get(dbc, key, data, flags, pgnop)
* the next entry.
*/
if (cp->indx == NUM_ENT(cp->page) || IS_CUR_DELETED(dbc))
- if ((ret = __bam_c_next(dbc, 0)) != 0)
+ if ((ret = __bam_c_next(dbc, 0, 0)) != 0)
goto err;
break;
default:
@@ -957,8 +974,15 @@ __bam_c_get(dbc, key, data, flags, pgnop)
if (newopd && pgnop != NULL)
(void)__bam_isopd(dbc, pgnop);
- /* Don't return the key, it was passed to us */
- if (flags == DB_SET)
+ /*
+ * Don't return the key, it was passed to us (this is true even if the
+ * application defines a compare function returning equality for more
+ * than one key value, since in that case which actual value we store
+ * in the database is undefined -- and particularly true in the case of
+ * duplicates where we only store one key value).
+ */
+ if (flags == DB_GET_BOTH ||
+ flags == DB_GET_BOTH_RANGE || flags == DB_SET)
F_SET(key, DB_DBT_ISSET);
err: /*
@@ -966,13 +990,596 @@ err: /*
* moved, clear the delete flag, DBcursor->c_get never references
* a deleted key, if it moved at all.
*/
- if (F_ISSET(cp, C_DELETED)
- && (cp->pgno != orig_pgno || cp->indx != orig_indx))
+ if (F_ISSET(cp, C_DELETED) &&
+ (cp->pgno != orig_pgno || cp->indx != orig_indx))
F_CLR(cp, C_DELETED);
return (ret);
}
+static int
+__bam_get_prev(dbc)
+ DBC *dbc;
+{
+ BTREE_CURSOR *cp;
+ DBT key, data;
+ db_pgno_t pgno;
+ int ret;
+
+ if ((ret = __bam_c_prev(dbc)) != 0)
+ return (ret);
+
+ if (__bam_isopd(dbc, &pgno)) {
+ cp = (BTREE_CURSOR *)dbc->internal;
+ if ((ret = __db_c_newopd(dbc, pgno, cp->opd, &cp->opd)) != 0)
+ return (ret);
+ if ((ret = cp->opd->c_am_get(cp->opd,
+ &key, &data, DB_LAST, NULL)) != 0)
+ return (ret);
+ }
+
+ return (0);
+}
+
+/*
+ * __bam_bulk -- Return bulk data from a btree.
+ */
+static int
+__bam_bulk(dbc, data, flags)
+ DBC *dbc;
+ DBT *data;
+ u_int32_t flags;
+{
+ BKEYDATA *bk;
+ BOVERFLOW *bo;
+ BTREE_CURSOR *cp;
+ PAGE *pg;
+ db_indx_t *inp, indx, pg_keyoff;
+ int32_t *endp, key_off, *offp, *saveoffp;
+ u_int8_t *dbuf, *dp, *np;
+ u_int32_t key_size, size, space;
+ int adj, is_key, need_pg, next_key, no_dup;
+ int pagesize, rec_key, ret;
+
+ ret = 0;
+ key_off = 0;
+ size = 0;
+ pagesize = dbc->dbp->pgsize;
+ cp = (BTREE_CURSOR *)dbc->internal;
+
+ /*
+ * dp tracks the beginging of the page in the buffer.
+ * np is the next place to copy things into the buffer.
+ * dbuf always stays at the beging of the buffer.
+ */
+ dbuf = data->data;
+ np = dp = dbuf;
+
+ /* Keep track of space that is left. There is a termination entry */
+ space = data->ulen;
+ space -= sizeof(*offp);
+
+ /* Build the offset/size table from the end up. */
+ endp = (int32_t *)((u_int8_t *)dbuf + data->ulen);
+ endp--;
+ offp = endp;
+
+ key_size = 0;
+
+ /*
+ * Distinguish between BTREE and RECNO.
+ * There are no keys in RECNO. If MULTIPLE_KEY is specified
+ * then we return the record numbers.
+ * is_key indicates that multiple btree keys are returned.
+ * rec_key is set if we are returning record numbers.
+ * next_key is set if we are going after the next key rather than dup.
+ */
+ if (dbc->dbtype == DB_BTREE) {
+ is_key = LF_ISSET(DB_MULTIPLE_KEY) ? 1: 0;
+ rec_key = 0;
+ next_key = is_key && LF_ISSET(DB_OPFLAGS_MASK) != DB_NEXT_DUP;
+ adj = 2;
+ } else {
+ is_key = 0;
+ rec_key = LF_ISSET(DB_MULTIPLE_KEY) ? 1 : 0;
+ next_key = LF_ISSET(DB_OPFLAGS_MASK) != DB_NEXT_DUP;
+ adj = 1;
+ }
+ no_dup = LF_ISSET(DB_OPFLAGS_MASK) == DB_NEXT_NODUP;
+
+next_pg:
+ indx = cp->indx;
+ pg = cp->page;
+
+ inp = P_INP(dbc->dbp, pg);
+ /* The current page is not yet in the buffer. */
+ need_pg = 1;
+
+ /*
+ * Keep track of the offset of the current key on the page.
+ * If we are returning keys, set it to 0 first so we force
+ * the copy of the key to the buffer.
+ */
+ pg_keyoff = 0;
+ if (is_key == 0)
+ pg_keyoff = inp[indx];
+
+ do {
+ if (IS_DELETED(dbc->dbp, pg, indx)) {
+ if (dbc->dbtype != DB_RECNO)
+ continue;
+
+ cp->recno++;
+ /*
+ * If we are not returning recnos then we
+ * need to fill in every slot so the user
+ * can calculate the record numbers.
+ */
+ if (rec_key != 0)
+ continue;
+
+ space -= 2 * sizeof(*offp);
+ /* Check if space as underflowed. */
+ if (space > data->ulen)
+ goto back_up;
+
+ /* Just mark the empty recno slots. */
+ *offp-- = 0;
+ *offp-- = 0;
+ continue;
+ }
+
+ /*
+ * Check to see if we have a new key.
+ * If so, then see if we need to put the
+ * key on the page. If its already there
+ * then we just point to it.
+ */
+ if (is_key && pg_keyoff != inp[indx]) {
+ bk = GET_BKEYDATA(dbc->dbp, pg, indx);
+ if (B_TYPE(bk->type) == B_OVERFLOW) {
+ bo = (BOVERFLOW *)bk;
+ size = key_size = bo->tlen;
+ if (key_size > space)
+ goto get_key_space;
+ if ((ret = __bam_bulk_overflow(dbc,
+ bo->tlen, bo->pgno, np)) != 0)
+ return (ret);
+ space -= key_size;
+ key_off = (int32_t)(np - dbuf);
+ np += key_size;
+ } else {
+ if (need_pg) {
+ dp = np;
+ size = pagesize - HOFFSET(pg);
+ if (space < size) {
+get_key_space:
+ /* Nothing added, then error. */
+ if (offp == endp) {
+ data->size =
+ ALIGN(size +
+ pagesize,
+ sizeof(u_int32_t));
+ return (ENOMEM);
+ }
+ /*
+ * We need to back up to the
+ * last record put into the
+ * buffer so that it is
+ * CURRENT.
+ */
+ if (indx != 0)
+ indx -= P_INDX;
+ else {
+ if ((ret =
+ __bam_get_prev(
+ dbc)) != 0)
+ return (ret);
+ indx = cp->indx;
+ pg = cp->page;
+ }
+ break;
+ }
+ /*
+ * Move the data part of the page
+ * to the buffer.
+ */
+ memcpy(dp,
+ (u_int8_t *)pg + HOFFSET(pg), size);
+ need_pg = 0;
+ space -= size;
+ np += size;
+ }
+ key_size = bk->len;
+ key_off = (int32_t)(inp[indx] - HOFFSET(pg)
+ + dp - dbuf + SSZA(BKEYDATA, data));
+ pg_keyoff = inp[indx];
+ }
+ }
+
+ /*
+ * Reserve space for the pointers and sizes.
+ * Either key/data pair or just for a data item.
+ */
+ space -= (is_key ? 4 : 2) * sizeof(*offp);
+ if (rec_key)
+ space -= sizeof(*offp);
+
+ /* Check to see if space has underflowed. */
+ if (space > data->ulen)
+ goto back_up;
+
+ /*
+ * Determine if the next record is in the
+ * buffer already or if it needs to be copied in.
+ * If we have an off page dup, then copy as many
+ * as will fit into the buffer.
+ */
+ bk = GET_BKEYDATA(dbc->dbp, pg, indx + adj - 1);
+ if (B_TYPE(bk->type) == B_DUPLICATE) {
+ bo = (BOVERFLOW *)bk;
+ if (is_key) {
+ *offp-- = key_off;
+ *offp-- = key_size;
+ }
+ /*
+ * We pass the offset of the current key.
+ * On return we check to see if offp has
+ * moved to see if any data fit.
+ */
+ saveoffp = offp;
+ if ((ret = __bam_bulk_duplicates(dbc, bo->pgno,
+ dbuf, is_key ? offp + P_INDX : NULL,
+ &offp, &np, &space, no_dup)) != 0) {
+ if (ret == ENOMEM) {
+ size = space;
+ /* If nothing was added, then error. */
+ if (offp == saveoffp) {
+ offp += 2;
+ goto back_up;
+ }
+ goto get_space;
+ }
+ return (ret);
+ }
+ } else if (B_TYPE(bk->type) == B_OVERFLOW) {
+ bo = (BOVERFLOW *)bk;
+ size = bo->tlen;
+ if (size > space)
+ goto back_up;
+ if ((ret =
+ __bam_bulk_overflow(dbc,
+ bo->tlen, bo->pgno, np)) != 0)
+ return (ret);
+ space -= size;
+ if (is_key) {
+ *offp-- = key_off;
+ *offp-- = key_size;
+ } else if (rec_key)
+ *offp-- = cp->recno;
+ *offp-- = (int32_t)(np - dbuf);
+ np += size;
+ *offp-- = size;
+ } else {
+ if (need_pg) {
+ dp = np;
+ size = pagesize - HOFFSET(pg);
+ if (space < size) {
+back_up:
+ /*
+ * Back up the index so that the
+ * last record in the buffer is CURRENT
+ */
+ if (indx >= adj)
+ indx -= adj;
+ else {
+ if ((ret =
+ __bam_get_prev(dbc)) != 0 &&
+ ret != DB_NOTFOUND)
+ return (ret);
+ indx = cp->indx;
+ pg = cp->page;
+ }
+ if (dbc->dbtype == DB_RECNO)
+ cp->recno--;
+get_space:
+ /*
+ * See if we put anything in the
+ * buffer or if we are doing a DBP->get
+ * did we get all of the data.
+ */
+ if (offp >=
+ (is_key ? &endp[-1] : endp) ||
+ F_ISSET(dbc, DBC_TRANSIENT)) {
+ data->size = ALIGN(size +
+ data->ulen - space,
+ sizeof(u_int32_t));
+ return (ENOMEM);
+ }
+ break;
+ }
+ memcpy(dp, (u_int8_t *)pg + HOFFSET(pg), size);
+ need_pg = 0;
+ space -= size;
+ np += size;
+ }
+ /*
+ * Add the offsets and sizes to the end of the buffer.
+ * First add the key info then the data info.
+ */
+ if (is_key) {
+ *offp-- = key_off;
+ *offp-- = key_size;
+ } else if (rec_key)
+ *offp-- = cp->recno;
+ *offp-- = (int32_t)(inp[indx + adj - 1] - HOFFSET(pg)
+ + dp - dbuf + SSZA(BKEYDATA, data));
+ *offp-- = bk->len;
+ }
+ if (dbc->dbtype == DB_RECNO)
+ cp->recno++;
+ else if (no_dup) {
+ while (indx + adj < NUM_ENT(pg) &&
+ pg_keyoff == inp[indx + adj])
+ indx += adj;
+ }
+ /*
+ * Stop when we either run off the page or we
+ * move to the next key and we are not returning mulitple keys.
+ */
+ } while ((indx += adj) < NUM_ENT(pg) &&
+ (next_key || pg_keyoff == inp[indx]));
+
+ /* If we are off the page then try to the next page. */
+ if (ret == 0 && next_key && indx >= NUM_ENT(pg)) {
+ cp->indx = indx;
+ ret = __bam_c_next(dbc, 0, 1);
+ if (ret == 0)
+ goto next_pg;
+ if (ret != DB_NOTFOUND)
+ return (ret);
+ }
+
+ /*
+ * If we did a DBP->get we must error if we did not return
+ * all the data for the current key because there is
+ * no way to know if we did not get it all, nor any
+ * interface to fetch the balance.
+ */
+
+ if (ret == 0 &&
+ F_ISSET(dbc, DBC_TRANSIENT) && pg_keyoff == inp[indx]) {
+ data->size = (data->ulen - space) + size;
+ return (ENOMEM);
+ }
+ /*
+ * Must leave the index pointing at the last record fetched.
+ * If we are not fetching keys, we may have stepped to the
+ * next key.
+ */
+ if (next_key || pg_keyoff == inp[indx])
+ cp->indx = indx;
+ else
+ cp->indx = indx - P_INDX;
+
+ if (rec_key == 1)
+ *offp = (u_int32_t) RECNO_OOB;
+ else
+ *offp = (u_int32_t) -1;
+ return (0);
+}
+
+/*
+ * __bam_bulk_overflow --
+ * Dump overflow record into the buffer.
+ * The space requirements have already been checked.
+ * PUBLIC: int __bam_bulk_overflow
+ * PUBLIC: __P((DBC *, u_int32_t, db_pgno_t, u_int8_t *));
+ */
+int
+__bam_bulk_overflow(dbc, len, pgno, dp)
+ DBC *dbc;
+ u_int32_t len;
+ db_pgno_t pgno;
+ u_int8_t *dp;
+{
+ DBT dbt;
+
+ memset(&dbt, 0, sizeof(dbt));
+ F_SET(&dbt, DB_DBT_USERMEM);
+ dbt.ulen = len;
+ dbt.data = (void *)dp;
+ return (__db_goff(dbc->dbp, &dbt, len, pgno, NULL, NULL));
+}
+
+/*
+ * __bam_bulk_duplicates --
+ * Put as many off page duplicates as will fit into the buffer.
+ * This routine will adjust the cursor to reflect the position in
+ * the overflow tree.
+ * PUBLIC: int __bam_bulk_duplicates __P((DBC *,
+ * PUBLIC: db_pgno_t, u_int8_t *, int32_t *,
+ * PUBLIC: int32_t **, u_int8_t **, u_int32_t *, int));
+ */
+int
+__bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
+ DBC *dbc;
+ db_pgno_t pgno;
+ u_int8_t *dbuf;
+ int32_t *keyoff, **offpp;
+ u_int8_t **dpp;
+ u_int32_t *spacep;
+ int no_dup;
+{
+ DB *dbp;
+ BKEYDATA *bk;
+ BOVERFLOW *bo;
+ BTREE_CURSOR *cp;
+ DBC *opd;
+ DBT key, data;
+ PAGE *pg;
+ db_indx_t indx, *inp;
+ int32_t *offp;
+ u_int32_t size, space;
+ u_int8_t *dp, *np;
+ int first, need_pg, pagesize, ret, t_ret;
+
+ ret = 0;
+
+ dbp = dbc->dbp;
+ cp = (BTREE_CURSOR *)dbc->internal;
+ opd = cp->opd;
+
+ if (opd == NULL) {
+ if ((ret = __db_c_newopd(dbc, pgno, NULL, &opd)) != 0)
+ return (ret);
+ cp->opd = opd;
+ if ((ret = opd->c_am_get(opd,
+ &key, &data, DB_FIRST, NULL)) != 0)
+ return (ret);
+ }
+
+ pagesize = opd->dbp->pgsize;
+ cp = (BTREE_CURSOR *)opd->internal;
+ space = *spacep;
+ /* Get current offset slot. */
+ offp = *offpp;
+
+ /*
+ * np is the next place to put data.
+ * dp is the begining of the current page in the buffer.
+ */
+ np = dp = *dpp;
+ first = 1;
+ indx = cp->indx;
+
+ do {
+ /* Fetch the current record. No initial move. */
+ if ((ret = __bam_c_next(opd, 0, 0)) != 0)
+ break;
+ pg = cp->page;
+ indx = cp->indx;
+ inp = P_INP(dbp, pg);
+ /* We need to copy the page to the buffer. */
+ need_pg = 1;
+
+ do {
+ if (IS_DELETED(dbp, pg, indx))
+ goto contin;
+ bk = GET_BKEYDATA(dbp, pg, indx);
+ space -= 2 * sizeof(*offp);
+ /* Allocate space for key if needed. */
+ if (first == 0 && keyoff != NULL)
+ space -= 2 * sizeof(*offp);
+
+ /* Did space underflow? */
+ if (space > *spacep) {
+ ret = ENOMEM;
+ if (first == 1) {
+ space = *spacep + -(int32_t)space;
+ if (need_pg)
+ space += pagesize - HOFFSET(pg);
+ }
+ break;
+ }
+ if (B_TYPE(bk->type) == B_OVERFLOW) {
+ bo = (BOVERFLOW *)bk;
+ size = bo->tlen;
+ if (size > space) {
+ ret = ENOMEM;
+ if (first == 1) {
+ space = *spacep + size;
+ }
+ break;
+ }
+ if (first == 0 && keyoff != NULL) {
+ *offp-- = keyoff[0];
+ *offp-- = keyoff[-1];
+ }
+ if ((ret = __bam_bulk_overflow(dbc,
+ bo->tlen, bo->pgno, np)) != 0)
+ return (ret);
+ space -= size;
+ *offp-- = (int32_t)(np - dbuf);
+ np += size;
+ } else {
+ if (need_pg) {
+ dp = np;
+ size = pagesize - HOFFSET(pg);
+ if (space < size) {
+ ret = ENOMEM;
+ /* Return space required. */
+ if (first == 1) {
+ space = *spacep + size;
+ }
+ break;
+ }
+ memcpy(dp,
+ (u_int8_t *)pg + HOFFSET(pg), size);
+ need_pg = 0;
+ space -= size;
+ np += size;
+ }
+ if (first == 0 && keyoff != NULL) {
+ *offp-- = keyoff[0];
+ *offp-- = keyoff[-1];
+ }
+ size = bk->len;
+ *offp-- = (int32_t)(inp[indx] - HOFFSET(pg)
+ + dp - dbuf + SSZA(BKEYDATA, data));
+ }
+ *offp-- = size;
+ first = 0;
+ if (no_dup)
+ break;
+contin:
+ indx++;
+ if (opd->dbtype == DB_RECNO)
+ cp->recno++;
+ } while (indx < NUM_ENT(pg));
+ if (no_dup)
+ break;
+ cp->indx = indx;
+
+ } while (ret == 0);
+
+ /* Return the updated information. */
+ *spacep = space;
+ *offpp = offp;
+ *dpp = np;
+
+ /*
+ * If we ran out of space back up the pointer.
+ * If we did not return any dups or reached the end, close the opd.
+ */
+ if (ret == ENOMEM) {
+ if (opd->dbtype == DB_RECNO) {
+ if (--cp->recno == 0)
+ goto close_opd;
+ } else if (indx != 0)
+ cp->indx--;
+ else {
+ t_ret = __bam_c_prev(opd);
+ if (t_ret == DB_NOTFOUND)
+ goto close_opd;
+ if (t_ret != 0)
+ ret = t_ret;
+ }
+ } else if (keyoff == NULL && ret == DB_NOTFOUND) {
+ cp->indx--;
+ if (opd->dbtype == DB_RECNO)
+ --cp->recno;
+ } else if (indx == 0 || ret == DB_NOTFOUND) {
+close_opd:
+ opd->c_close(opd);
+ ((BTREE_CURSOR *)dbc->internal)->opd = NULL;
+ }
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+
+ return (ret);
+}
+
/*
* __bam_getbothc --
* Search for a matching data item on a join.
@@ -984,9 +1591,11 @@ __bam_getbothc(dbc, data)
{
BTREE_CURSOR *cp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
int cmp, exact, ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
@@ -995,7 +1604,7 @@ __bam_getbothc(dbc, data)
* write lock, but upgrading to a write lock has no better
* chance of succeeding now instead of later, so don't try.
*/
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
return (ret);
/*
@@ -1017,11 +1626,12 @@ __bam_getbothc(dbc, data)
return (DB_NOTFOUND);
/* Discard the current page, we're going to do a full search. */
- if ((ret = memp_fput(dbp->mpf, cp->page, 0)) != 0)
+ if ((ret = mpf->put(mpf, cp->page, 0)) != 0)
return (ret);
cp->page = NULL;
- return (__bam_c_search(dbc, data, DB_GET_BOTH, &exact));
+ return (__bam_c_search(dbc,
+ PGNO_INVALID, data, DB_GET_BOTH, &exact));
}
/*
@@ -1038,7 +1648,7 @@ __bam_getbothc(dbc, data)
return (DB_NOTFOUND);
cp->indx += P_INDX;
- return (__bam_getboth_finddatum(dbc, data));
+ return (__bam_getboth_finddatum(dbc, data, DB_GET_BOTH));
}
/*
@@ -1046,9 +1656,10 @@ __bam_getbothc(dbc, data)
* Find a matching on-page data item.
*/
static int
-__bam_getboth_finddatum(dbc, data)
+__bam_getboth_finddatum(dbc, data, flags)
DBC *dbc;
DBT *data;
+ u_int32_t flags;
{
BTREE_CURSOR *cp;
DB *dbp;
@@ -1060,17 +1671,14 @@ __bam_getboth_finddatum(dbc, data)
/*
* Called (sometimes indirectly) from DBC->get to search on-page data
- * item(s) for a matching value. If the original flag was DB_GET_BOTH,
- * the cursor argument is set to the first data item for the key. If
- * the original flag was DB_GET_BOTHC, the cursor argument is set to
- * the first data item that we can potentially return. In both cases,
- * there may or may not be additional duplicate data items to search.
+ * item(s) for a matching value. If the original flag was DB_GET_BOTH
+ * or DB_GET_BOTH_RANGE, the cursor is set to the first undeleted data
+ * item for the key. If the original flag was DB_GET_BOTHC, the cursor
+ * argument is set to the first data item we can potentially return.
+ * In both cases, there may or may not be additional duplicate data
+ * items to search.
*
* If the duplicates are not sorted, do a linear search.
- *
- * If the duplicates are sorted, do a binary search. The reason for
- * this is that large pages and small key/data pairs result in large
- * numbers of on-page duplicates before they get pushed off-page.
*/
if (dbp->dup_compare == NULL) {
for (;; cp->indx += P_INDX) {
@@ -1085,41 +1693,62 @@ __bam_getboth_finddatum(dbc, data)
!IS_DUPLICATE(dbc, cp->indx, cp->indx + P_INDX))
break;
}
- } else {
- /*
- * Find the top and bottom of the duplicate set. Binary search
- * requires at least two items, don't loop if there's only one.
- */
- for (base = top = cp->indx;
- top < NUM_ENT(cp->page); top += P_INDX)
- if (!IS_DUPLICATE(dbc, cp->indx, top))
- break;
- if (base == (top - P_INDX)) {
- if ((ret = __bam_cmp(dbp, data,
- cp->page, cp->indx + O_INDX,
- dbp->dup_compare, &cmp)) != 0)
- return (ret);
- return (cmp == 0 ? 0 : DB_NOTFOUND);
- }
+ return (DB_NOTFOUND);
+ }
- for (lim =
- (top - base) / (db_indx_t)P_INDX; lim != 0; lim >>= 1) {
- cp->indx = base + ((lim >> 1) * P_INDX);
- if ((ret = __bam_cmp(dbp, data, cp->page,
- cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)
- return (ret);
- if (cmp == 0) {
- if (!IS_CUR_DELETED(dbc))
- return (0);
- break;
- }
- if (cmp > 0) {
- base = cp->indx + P_INDX;
- --lim;
- }
+ /*
+ * If the duplicates are sorted, do a binary search. The reason for
+ * this is that large pages and small key/data pairs result in large
+ * numbers of on-page duplicates before they get pushed off-page.
+ *
+ * Find the top and bottom of the duplicate set. Binary search
+ * requires at least two items, don't loop if there's only one.
+ */
+ for (base = top = cp->indx; top < NUM_ENT(cp->page); top += P_INDX)
+ if (!IS_DUPLICATE(dbc, cp->indx, top))
+ break;
+ if (base == (top - P_INDX)) {
+ if ((ret = __bam_cmp(dbp, data,
+ cp->page, cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)
+ return (ret);
+ return (cmp == 0 ||
+ (cmp < 0 && flags == DB_GET_BOTH_RANGE) ? 0 : DB_NOTFOUND);
+ }
+
+ for (lim = (top - base) / (db_indx_t)P_INDX; lim != 0; lim >>= 1) {
+ cp->indx = base + ((lim >> 1) * P_INDX);
+ if ((ret = __bam_cmp(dbp, data, cp->page,
+ cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)
+ return (ret);
+ if (cmp == 0) {
+ /*
+ * XXX
+ * No duplicate duplicates in sorted duplicate sets,
+ * so there can be only one.
+ */
+ if (!IS_CUR_DELETED(dbc))
+ return (0);
+ break;
+ }
+ if (cmp > 0) {
+ base = cp->indx + P_INDX;
+ --lim;
}
}
- return (DB_NOTFOUND);
+
+ /* No match found; if we're looking for an exact match, we're done. */
+ if (flags == DB_GET_BOTH)
+ return (DB_NOTFOUND);
+
+ /*
+ * Base is the smallest index greater than the data item, may be zero
+ * or a last + O_INDX index, and may be deleted. Find an undeleted
+ * item.
+ */
+ cp->indx = base;
+ while (cp->indx < top && IS_CUR_DELETED(dbc))
+ cp->indx += P_INDX;
+ return (cp->indx < top ? 0 : DB_NOTFOUND);
}
/*
@@ -1136,19 +1765,22 @@ __bam_c_put(dbc, key, data, flags, pgnop)
BTREE_CURSOR *cp;
DB *dbp;
DBT dbt;
+ DB_MPOOLFILE *mpf;
+ db_pgno_t root_pgno;
u_int32_t iiop;
- int cmp, exact, needkey, ret, stack;
+ int cmp, exact, ret, stack;
void *arg;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
+ root_pgno = cp->root;
-split: needkey = ret = stack = 0;
+split: ret = stack = 0;
switch (flags) {
case DB_AFTER:
case DB_BEFORE:
case DB_CURRENT:
- needkey = 1;
iiop = flags;
/*
@@ -1182,7 +1814,7 @@ split: needkey = ret = stack = 0;
ACQUIRE_WRITE_LOCK(dbc, ret);
if (ret != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
goto err;
break;
case DB_KEYFIRST:
@@ -1192,15 +1824,22 @@ split: needkey = ret = stack = 0;
* Searching off-page, sorted duplicate tree: do a tree search
* for the correct item; __bam_c_search returns the smallest
* slot greater than the key, use it.
+ *
+ * See comment below regarding where we can start the search.
*/
if (F_ISSET(dbc, DBC_OPD)) {
- if ((ret =
- __bam_c_search(dbc, data, flags, &exact)) != 0)
+ if ((ret = __bam_c_search(dbc,
+ F_ISSET(cp, C_RECNUM) ? cp->root : root_pgno,
+ data, flags, &exact)) != 0)
goto err;
stack = 1;
/* Disallow "sorted" duplicate duplicates. */
if (exact) {
+ if (IS_DELETED(dbp, cp->page, cp->indx)) {
+ iiop = DB_CURRENT;
+ break;
+ }
ret = __db_duperr(dbp, flags);
goto err;
}
@@ -1208,8 +1847,17 @@ split: needkey = ret = stack = 0;
break;
}
- /* Searching a btree. */
- if ((ret = __bam_c_search(dbc, key,
+ /*
+ * Searching a btree.
+ *
+ * If we've done a split, we can start the search from the
+ * parent of the split page, which __bam_split returned
+ * for us in root_pgno, unless we're in a Btree with record
+ * numbering. In that case, we'll need the true root page
+ * in order to adjust the record count.
+ */
+ if ((ret = __bam_c_search(dbc,
+ F_ISSET(cp, C_RECNUM) ? cp->root : root_pgno, key,
flags == DB_KEYFIRST || dbp->dup_compare != NULL ?
DB_KEYFIRST : DB_KEYLAST, &exact)) != 0)
goto err;
@@ -1264,8 +1912,8 @@ split: needkey = ret = stack = 0;
*/
for (;; cp->indx += P_INDX) {
if ((ret = __bam_cmp(dbp, data, cp->page,
- cp->indx + O_INDX, dbp->dup_compare, &cmp)) !=0)
- return (ret);
+ cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)
+ goto err;
if (cmp < 0) {
iiop = DB_BEFORE;
break;
@@ -1273,7 +1921,7 @@ split: needkey = ret = stack = 0;
/* Disallow "sorted" duplicate duplicates. */
if (cmp == 0) {
- if (IS_DELETED(cp->page, cp->indx)) {
+ if (IS_DELETED(dbp, cp->page, cp->indx)) {
iiop = DB_CURRENT;
break;
}
@@ -1282,8 +1930,8 @@ split: needkey = ret = stack = 0;
}
if (cp->indx + P_INDX >= NUM_ENT(cp->page) ||
- ((PAGE *)cp->page)->inp[cp->indx] !=
- ((PAGE *)cp->page)->inp[cp->indx + P_INDX]) {
+ P_INP(dbp, ((PAGE *)cp->page))[cp->indx] !=
+ P_INP(dbp, ((PAGE *)cp->page))[cp->indx + P_INDX]) {
iiop = DB_AFTER;
break;
}
@@ -1306,7 +1954,7 @@ split: needkey = ret = stack = 0;
flags == DB_BEFORE || flags == DB_CURRENT) {
memset(&dbt, 0, sizeof(DBT));
if ((ret = __db_ret(dbp, cp->page, 0, &dbt,
- &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
+ &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
goto err;
arg = &dbt;
} else
@@ -1327,7 +1975,7 @@ split: needkey = ret = stack = 0;
goto err;
/* Split the tree. */
- if ((ret = __bam_split(dbc, arg)) != 0)
+ if ((ret = __bam_split(dbc, arg, &root_pgno)) != 0)
return (ret);
goto split;
@@ -1361,22 +2009,22 @@ done: /*
* __bam_c_rget --
* Return the record number for a cursor.
*
- * PUBLIC: int __bam_c_rget __P((DBC *, DBT *, u_int32_t));
+ * PUBLIC: int __bam_c_rget __P((DBC *, DBT *));
*/
int
-__bam_c_rget(dbc, data, flags)
+__bam_c_rget(dbc, data)
DBC *dbc;
DBT *data;
- u_int32_t flags;
{
BTREE_CURSOR *cp;
DB *dbp;
DBT dbt;
+ DB_MPOOLFILE *mpf;
db_recno_t recno;
int exact, ret;
- COMPQUIET(flags, 0);
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
@@ -1384,24 +2032,24 @@ __bam_c_rget(dbc, data, flags)
* Get a copy of the key.
* Release the page, making sure we don't release it twice.
*/
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
return (ret);
memset(&dbt, 0, sizeof(DBT));
if ((ret = __db_ret(dbp, cp->page,
- cp->indx, &dbt, &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
+ cp->indx, &dbt, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
goto err;
- ret = memp_fput(dbp->mpf, cp->page, 0);
+ ret = mpf->put(mpf, cp->page, 0);
cp->page = NULL;
if (ret != 0)
return (ret);
- if ((ret = __bam_search(dbc, &dbt,
+ if ((ret = __bam_search(dbc, PGNO_INVALID, &dbt,
F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND,
1, &recno, &exact)) != 0)
goto err;
- ret = __db_retcopy(dbp, data,
- &recno, sizeof(recno), &dbc->rdata.data, &dbc->rdata.ulen);
+ ret = __db_retcopy(dbp->dbenv, data,
+ &recno, sizeof(recno), &dbc->rdata->data, &dbc->rdata->ulen);
/* Release the stack. */
err: __bam_stkrel(dbc, 0);
@@ -1444,17 +2092,15 @@ __bam_c_first(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
- DB *dbp;
db_pgno_t pgno;
int ret;
- dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/* Walk down the left-hand side of the tree. */
for (pgno = cp->root;;) {
- ACQUIRE_CUR_SET(dbc, DB_LOCK_READ, pgno, ret);
+ ACQUIRE_CUR_COUPLE(dbc, DB_LOCK_READ, pgno, ret);
if (ret != 0)
return (ret);
@@ -1462,7 +2108,7 @@ __bam_c_first(dbc)
if (ISLEAF(cp->page))
break;
- pgno = GET_BINTERNAL(cp->page, 0)->pgno;
+ pgno = GET_BINTERNAL(dbc->dbp, cp->page, 0)->pgno;
}
/* If we want a write lock instead of a read lock, get it now. */
@@ -1472,9 +2118,11 @@ __bam_c_first(dbc)
return (ret);
}
+ cp->indx = 0;
+
/* If on an empty page or a deleted record, move to the next one. */
if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))
- if ((ret = __bam_c_next(dbc, 0)) != 0)
+ if ((ret = __bam_c_next(dbc, 0, 0)) != 0)
return (ret);
return (0);
@@ -1489,17 +2137,15 @@ __bam_c_last(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
- DB *dbp;
db_pgno_t pgno;
int ret;
- dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/* Walk down the right-hand side of the tree. */
for (pgno = cp->root;;) {
- ACQUIRE_CUR_SET(dbc, DB_LOCK_READ, pgno, ret);
+ ACQUIRE_CUR_COUPLE(dbc, DB_LOCK_READ, pgno, ret);
if (ret != 0)
return (ret);
@@ -1507,8 +2153,8 @@ __bam_c_last(dbc)
if (ISLEAF(cp->page))
break;
- pgno =
- GET_BINTERNAL(cp->page, NUM_ENT(cp->page) - O_INDX)->pgno;
+ pgno = GET_BINTERNAL(dbc->dbp, cp->page,
+ NUM_ENT(cp->page) - O_INDX)->pgno;
}
/* If we want a write lock instead of a read lock, get it now. */
@@ -1535,18 +2181,16 @@ __bam_c_last(dbc)
* Move to the next record.
*/
static int
-__bam_c_next(dbc, initial_move)
+__bam_c_next(dbc, initial_move, deleted_okay)
DBC *dbc;
- int initial_move;
+ int initial_move, deleted_okay;
{
BTREE_CURSOR *cp;
- DB *dbp;
db_indx_t adjust;
db_lockmode_t lock_mode;
db_pgno_t pgno;
int ret;
- dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
@@ -1566,7 +2210,7 @@ __bam_c_next(dbc, initial_move)
F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE : DB_LOCK_READ;
}
if (cp->page == NULL) {
- ACQUIRE_CUR(dbc, lock_mode, ret);
+ ACQUIRE_CUR(dbc, lock_mode, cp->pgno, ret);
if (ret != 0)
return (ret);
}
@@ -1587,12 +2231,13 @@ __bam_c_next(dbc, initial_move)
= NEXT_PGNO(cp->page)) == PGNO_INVALID)
return (DB_NOTFOUND);
- ACQUIRE_CUR_SET(dbc, lock_mode, pgno, ret);
+ ACQUIRE_CUR(dbc, lock_mode, pgno, ret);
if (ret != 0)
return (ret);
+ cp->indx = 0;
continue;
}
- if (IS_CUR_DELETED(dbc)) {
+ if (!deleted_okay && IS_CUR_DELETED(dbc)) {
cp->indx += adjust;
continue;
}
@@ -1610,13 +2255,11 @@ __bam_c_prev(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
- DB *dbp;
db_indx_t adjust;
db_lockmode_t lock_mode;
db_pgno_t pgno;
int ret;
- dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
@@ -1636,7 +2279,7 @@ __bam_c_prev(dbc)
F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE : DB_LOCK_READ;
}
if (cp->page == NULL) {
- ACQUIRE_CUR(dbc, lock_mode, ret);
+ ACQUIRE_CUR(dbc, lock_mode, cp->pgno, ret);
if (ret != 0)
return (ret);
}
@@ -1648,7 +2291,7 @@ __bam_c_prev(dbc)
PREV_PGNO(cp->page)) == PGNO_INVALID)
return (DB_NOTFOUND);
- ACQUIRE_CUR_SET(dbc, lock_mode, pgno, ret);
+ ACQUIRE_CUR(dbc, lock_mode, pgno, ret);
if (ret != 0)
return (ret);
@@ -1671,8 +2314,9 @@ __bam_c_prev(dbc)
* Move to a specified record.
*/
static int
-__bam_c_search(dbc, key, flags, exactp)
+__bam_c_search(dbc, root_pgno, key, flags, exactp)
DBC *dbc;
+ db_pgno_t root_pgno;
const DBT *key;
u_int32_t flags;
int *exactp;
@@ -1681,7 +2325,7 @@ __bam_c_search(dbc, key, flags, exactp)
BTREE_CURSOR *cp;
DB *dbp;
PAGE *h;
- db_indx_t indx;
+ db_indx_t indx, *inp;
db_pgno_t bt_lpgno;
db_recno_t recno;
u_int32_t sflags;
@@ -1712,6 +2356,9 @@ __bam_c_search(dbc, key, flags, exactp)
case DB_GET_BOTH:
sflags = (F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND) | S_EXACT;
goto search;
+ case DB_GET_BOTH_RANGE:
+ sflags = (F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND);
+ goto search;
case DB_SET_RANGE:
sflags =
(F_ISSET(dbc, DBC_RMW) ? S_WRITE : S_READ) | S_DUPFIRST;
@@ -1758,6 +2405,7 @@ fast_search: /*
if (ret != 0)
goto fast_miss;
+ inp = P_INP(dbp, h);
/*
* It's okay if the page type isn't right or it's empty, it
* just means that the world changed.
@@ -1796,7 +2444,7 @@ fast_search: /*
if (flags == DB_KEYLAST)
goto fast_hit;
for (;
- indx > 0 && h->inp[indx - P_INDX] == h->inp[indx];
+ indx > 0 && inp[indx - P_INDX] == inp[indx];
indx -= P_INDX)
;
goto fast_hit;
@@ -1823,7 +2471,7 @@ try_begin: if (h->prev_pgno == PGNO_INVALID) {
goto fast_hit;
for (;
indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
- h->inp[indx] == h->inp[indx + P_INDX];
+ inp[indx] == inp[indx + P_INDX];
indx += P_INDX)
;
goto fast_hit;
@@ -1852,8 +2500,8 @@ fast_miss: /*
if (ret != 0)
return (ret);
-search: if ((ret =
- __bam_search(dbc, key, sflags, 1, NULL, exactp)) != 0)
+search: if ((ret = __bam_search(dbc, root_pgno,
+ key, sflags, 1, NULL, exactp)) != 0)
return (ret);
break;
default:
@@ -1870,12 +2518,15 @@ search: if ((ret =
/*
* If we inserted a key into the first or last slot of the tree,
* remember where it was so we can do it more quickly next time.
+ * If there are duplicates and we are inserting into the last slot,
+ * the cursor will point _to_ the last item, not after it, which
+ * is why we subtract P_INDX below.
*/
if (TYPE(cp->page) == P_LBTREE &&
(flags == DB_KEYFIRST || flags == DB_KEYLAST))
t->bt_lpgno =
(NEXT_PGNO(cp->page) == PGNO_INVALID &&
- cp->indx >= NUM_ENT(cp->page)) ||
+ cp->indx >= NUM_ENT(cp->page) - P_INDX) ||
(PREV_PGNO(cp->page) == PGNO_INVALID &&
cp->indx == 0) ? cp->pgno : PGNO_INVALID;
return (0);
@@ -1893,11 +2544,13 @@ __bam_c_physdel(dbc)
DB *dbp;
DBT key;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int delete_page, empty_page, exact, level, ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
delete_page = empty_page = ret = 0;
@@ -1911,7 +2564,7 @@ __bam_c_physdel(dbc)
* space will never be reused unless the exact same key is specified.
*/
if (delete_page &&
- !F_ISSET(dbc, DBC_OPD) && F_ISSET(dbp, DB_BT_REVSPLIT))
+ !F_ISSET(dbc, DBC_OPD) && F_ISSET(dbp, DB_AM_REVSPLITOFF))
delete_page = 0;
/*
@@ -1926,11 +2579,17 @@ __bam_c_physdel(dbc)
* To delete a leaf page other than an empty root page, we need a
* copy of a key from the page. Use the 0th page index since it's
* the last key the page held.
+ *
+ * !!!
+ * Note that because __bam_c_physdel is always called from a cursor
+ * close, it should be safe to use the cursor's own "my_rkey" memory
+ * to temporarily hold this key. We shouldn't own any returned-data
+ * memory of interest--if we do, we're in trouble anyway.
*/
if (delete_page) {
memset(&key, 0, sizeof(DBT));
if ((ret = __db_ret(dbp, cp->page,
- 0, &key, &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
+ 0, &key, &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0)
return (ret);
}
@@ -1940,7 +2599,7 @@ __bam_c_physdel(dbc)
* !!!
* The following operations to delete a page may deadlock. The easy
* scenario is if we're deleting an item because we're closing cursors
- * because we've already deadlocked and want to call txn_abort(). If
+ * because we've already deadlocked and want to call txn->abort. If
* we fail due to deadlock, we'll leave a locked, possibly empty page
* in the tree, which won't be empty long because we'll undo the delete
* when we undo the transaction's modifications.
@@ -1977,8 +2636,8 @@ __bam_c_physdel(dbc)
*/
for (level = LEAFLEVEL;; ++level) {
/* Acquire a page and its parent, locked. */
- if ((ret = __bam_search(
- dbc, &key, S_WRPAIR, level, NULL, &exact)) != 0)
+ if ((ret = __bam_search(dbc, PGNO_INVALID,
+ &key, S_WRPAIR, level, NULL, &exact)) != 0)
return (ret);
/*
@@ -2031,19 +2690,19 @@ __bam_c_physdel(dbc)
*/
switch (TYPE(h)) {
case P_IBTREE:
- pgno = GET_BINTERNAL(h, 0)->pgno;
+ pgno = GET_BINTERNAL(dbp, h, 0)->pgno;
break;
case P_IRECNO:
- pgno = GET_RINTERNAL(h, 0)->pgno;
+ pgno = GET_RINTERNAL(dbp, h, 0)->pgno;
break;
default:
- return (__db_pgfmt(dbp, PGNO(h)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &lock)) != 0)
break;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
break;
BT_STK_PUSH(dbp->dbenv, cp, h, 0, lock, DB_LOCK_WRITE, ret);
if (ret != 0)
@@ -2076,10 +2735,12 @@ __bam_c_getstack(dbc)
BTREE_CURSOR *cp;
DB *dbp;
DBT dbt;
+ DB_MPOOLFILE *mpf;
PAGE *h;
int exact, ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
@@ -2087,21 +2748,22 @@ __bam_c_getstack(dbc)
* routine has to already hold a read lock on the page, so there
* is no additional lock to acquire.
*/
- if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &cp->pgno, 0, &h)) != 0)
return (ret);
/* Get a copy of a key from the page. */
memset(&dbt, 0, sizeof(DBT));
if ((ret = __db_ret(dbp,
- h, 0, &dbt, &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
+ h, 0, &dbt, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
goto err;
/* Get a write-locked stack for the page. */
exact = 0;
- ret = __bam_search(dbc, &dbt, S_KEYFIRST, 1, NULL, &exact);
+ ret = __bam_search(dbc, PGNO_INVALID,
+ &dbt, S_KEYFIRST, 1, NULL, &exact);
err: /* Discard the key and the page. */
- if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
+ if ((t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret);
@@ -2122,7 +2784,8 @@ __bam_isopd(dbc, pgnop)
if (TYPE(dbc->internal->page) != P_LBTREE)
return (0);
- bo = GET_BOVERFLOW(dbc->internal->page, dbc->internal->indx + O_INDX);
+ bo = GET_BOVERFLOW(dbc->dbp,
+ dbc->internal->page, dbc->internal->indx + O_INDX);
if (B_TYPE(bo->type) == B_DUPLICATE) {
*pgnop = bo->pgno;
return (1);
diff --git a/bdb/btree/bt_delete.c b/bdb/btree/bt_delete.c
index 9725887882a..8c76ead2922 100644
--- a/bdb/btree/bt_delete.c
+++ b/bdb/btree/bt_delete.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_delete.c,v 11.31 2001/01/17 18:48:46 bostic Exp $";
+static const char revid[] = "$Id: bt_delete.c,v 11.44 2002/07/03 19:03:49 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -53,88 +53,10 @@ static const char revid[] = "$Id: bt_delete.c,v 11.31 2001/01/17 18:48:46 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "lock.h"
-
-/*
- * __bam_delete --
- * Delete the items referenced by a key.
- *
- * PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
- */
-int
-__bam_delete(dbp, txn, key, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- u_int32_t flags;
-{
- DBC *dbc;
- DBT lkey;
- DBT data;
- u_int32_t f_init, f_next;
- int ret, t_ret;
-
- PANIC_CHECK(dbp->dbenv);
- DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");
- DB_CHECK_TXN(dbp, txn);
-
- /* Check for invalid flags. */
- if ((ret =
- __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
- return (ret);
-
- /* Allocate a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
-
- DEBUG_LWRITE(dbc, txn, "bam_delete", key, NULL, flags);
-
- /*
- * Walk a cursor through the key/data pairs, deleting as we go. Set
- * the DB_DBT_USERMEM flag, as this might be a threaded application
- * and the flags checking will catch us. We don't actually want the
- * keys or data, so request a partial of length 0.
- */
- memset(&lkey, 0, sizeof(lkey));
- F_SET(&lkey, DB_DBT_USERMEM | DB_DBT_PARTIAL);
- memset(&data, 0, sizeof(data));
- F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);
-
- /*
- * If locking (and we haven't already acquired CDB locks), set the
- * read-modify-write flag.
- */
- f_init = DB_SET;
- f_next = DB_NEXT_DUP;
- if (STD_LOCKING(dbc)) {
- f_init |= DB_RMW;
- f_next |= DB_RMW;
- }
-
- /* Walk through the set of key/data pairs, deleting as we go. */
- if ((ret = dbc->c_get(dbc, key, &data, f_init)) != 0)
- goto err;
- for (;;) {
- if ((ret = dbc->c_del(dbc, 0)) != 0)
- goto err;
- if ((ret = dbc->c_get(dbc, &lkey, &data, f_next)) != 0) {
- if (ret == DB_NOTFOUND) {
- ret = 0;
- break;
- }
- goto err;
- }
- }
-
-err: /* Discard the cursor. */
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
-
- return (ret);
-}
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
/*
* __bam_ditem --
@@ -151,14 +73,18 @@ __bam_ditem(dbc, h, indx)
BINTERNAL *bi;
BKEYDATA *bk;
DB *dbp;
+ DB_MPOOLFILE *mpf;
u_int32_t nbytes;
int ret;
+ db_indx_t *inp;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
+ inp = P_INP(dbp, h);
switch (TYPE(h)) {
case P_IBTREE:
- bi = GET_BINTERNAL(h, indx);
+ bi = GET_BINTERNAL(dbp, h, indx);
switch (B_TYPE(bi->type)) {
case B_DUPLICATE:
case B_KEYDATA:
@@ -171,7 +97,7 @@ __bam_ditem(dbc, h, indx)
return (ret);
break;
default:
- return (__db_pgfmt(dbp, PGNO(h)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
break;
case P_IRECNO:
@@ -195,7 +121,7 @@ __bam_ditem(dbc, h, indx)
* won't work!
*/
if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
- h->inp[indx] == h->inp[indx + P_INDX])
+ inp[indx] == inp[indx + P_INDX])
return (__bam_adjindx(dbc,
h, indx, indx + O_INDX, 0));
/*
@@ -203,14 +129,14 @@ __bam_ditem(dbc, h, indx)
* doesn't matter if we delete the key item before or
* after the data item for the purposes of this one.
*/
- if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
+ if (indx > 0 && inp[indx] == inp[indx - P_INDX])
return (__bam_adjindx(dbc,
h, indx, indx - P_INDX, 0));
}
/* FALLTHROUGH */
case P_LDUP:
case P_LRECNO:
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
nbytes = BOVERFLOW_SIZE;
@@ -218,24 +144,24 @@ __bam_ditem(dbc, h, indx)
case B_OVERFLOW:
nbytes = BOVERFLOW_SIZE;
if ((ret = __db_doff(
- dbc, (GET_BOVERFLOW(h, indx))->pgno)) != 0)
+ dbc, (GET_BOVERFLOW(dbp, h, indx))->pgno)) != 0)
return (ret);
break;
case B_KEYDATA:
nbytes = BKEYDATA_SIZE(bk->len);
break;
default:
- return (__db_pgfmt(dbp, PGNO(h)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
break;
default:
- return (__db_pgfmt(dbp, PGNO(h)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
/* Delete the item and mark the page dirty. */
if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0)
return (ret);
- if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
return (0);
@@ -255,33 +181,37 @@ __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
int is_insert;
{
DB *dbp;
- db_indx_t copy;
+ DB_MPOOLFILE *mpf;
+ db_indx_t copy, *inp;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
+ inp = P_INP(dbp, h);
/* Log the change. */
- if (DB_LOGGING(dbc) &&
- (ret = __bam_adj_log(dbp->dbenv, dbc->txn, &LSN(h),
- 0, dbp->log_fileid, PGNO(h), &LSN(h), indx, indx_copy,
- (u_int32_t)is_insert)) != 0)
- return (ret);
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __bam_adj_log(dbp, dbc->txn, &LSN(h), 0,
+ PGNO(h), &LSN(h), indx, indx_copy, (u_int32_t)is_insert)) != 0)
+ return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(h));
/* Shuffle the indices and mark the page dirty. */
if (is_insert) {
- copy = h->inp[indx_copy];
+ copy = inp[indx_copy];
if (indx != NUM_ENT(h))
- memmove(&h->inp[indx + O_INDX], &h->inp[indx],
+ memmove(&inp[indx + O_INDX], &inp[indx],
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
- h->inp[indx] = copy;
+ inp[indx] = copy;
++NUM_ENT(h);
} else {
--NUM_ENT(h);
if (indx != NUM_ENT(h))
- memmove(&h->inp[indx], &h->inp[indx + O_INDX],
+ memmove(&inp[indx], &inp[indx + O_INDX],
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
}
- if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
return (0);
@@ -303,6 +233,7 @@ __bam_dpages(dbc, stack_epg)
DB *dbp;
DBT a, b;
DB_LOCK c_lock, p_lock;
+ DB_MPOOLFILE *mpf;
EPG *epg;
PAGE *child, *parent;
db_indx_t nitems;
@@ -311,6 +242,7 @@ __bam_dpages(dbc, stack_epg)
int done, ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
@@ -328,8 +260,7 @@ __bam_dpages(dbc, stack_epg)
*/
ret = 0;
for (epg = cp->sp; epg < stack_epg; ++epg) {
- if ((t_ret =
- memp_fput(dbp->mpf, epg->page, 0)) != 0 && ret == 0)
+ if ((t_ret = mpf->put(mpf, epg->page, 0)) != 0 && ret == 0)
ret = t_ret;
(void)__TLPUT(dbc, epg->lock);
}
@@ -364,7 +295,7 @@ __bam_dpages(dbc, stack_epg)
pgno = PGNO(epg->page);
nitems = NUM_ENT(epg->page);
- if ((ret = memp_fput(dbp->mpf, epg->page, 0)) != 0)
+ if ((ret = mpf->put(mpf, epg->page, 0)) != 0)
goto err_inc;
(void)__TLPUT(dbc, epg->lock);
@@ -394,7 +325,7 @@ __bam_dpages(dbc, stack_epg)
err_inc: ++epg;
err: for (; epg <= cp->csp; ++epg) {
if (epg->page != NULL)
- (void)memp_fput(dbp->mpf, epg->page, 0);
+ (void)mpf->put(mpf, epg->page, 0);
(void)__TLPUT(dbc, epg->lock);
}
BT_STK_CLR(cp);
@@ -415,14 +346,15 @@ err: for (; epg <= cp->csp; ++epg) {
for (done = 0; !done;) {
/* Initialize. */
parent = child = NULL;
- p_lock.off = c_lock.off = LOCK_INVALID;
+ LOCK_INIT(p_lock);
+ LOCK_INIT(c_lock);
/* Lock the root. */
pgno = root_pgno;
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &p_lock)) != 0)
goto stop;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &parent)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &parent)) != 0)
goto stop;
if (NUM_ENT(parent) != 1)
@@ -434,7 +366,7 @@ err: for (; epg <= cp->csp; ++epg) {
* If this is overflow, then try to delete it.
* The child may or may not still point at it.
*/
- bi = GET_BINTERNAL(parent, 0);
+ bi = GET_BINTERNAL(dbp, parent, 0);
if (B_TYPE(bi->type) == B_OVERFLOW)
if ((ret = __db_doff(dbc,
((BOVERFLOW *)bi->data)->pgno)) != 0)
@@ -442,7 +374,7 @@ err: for (; epg <= cp->csp; ++epg) {
pgno = bi->pgno;
break;
case P_IRECNO:
- pgno = GET_RINTERNAL(parent, 0)->pgno;
+ pgno = GET_RINTERNAL(dbp, parent, 0)->pgno;
break;
default:
goto stop;
@@ -452,24 +384,24 @@ err: for (; epg <= cp->csp; ++epg) {
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &c_lock)) != 0)
goto stop;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &child)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &child)) != 0)
goto stop;
/* Log the change. */
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
memset(&a, 0, sizeof(a));
a.data = child;
a.size = dbp->pgsize;
memset(&b, 0, sizeof(b));
- b.data = P_ENTRY(parent, 0);
+ b.data = P_ENTRY(dbp, parent, 0);
b.size = TYPE(parent) == P_IRECNO ? RINTERNAL_SIZE :
BINTERNAL_SIZE(((BINTERNAL *)b.data)->len);
- if ((ret =
- __bam_rsplit_log(dbp->dbenv, dbc->txn, &child->lsn,
- 0, dbp->log_fileid, PGNO(child), &a, PGNO(parent),
- RE_NREC(parent), &b, &parent->lsn)) != 0)
+ if ((ret = __bam_rsplit_log(dbp, dbc->txn,
+ &child->lsn, 0, PGNO(child), &a, PGNO(parent),
+ RE_NREC(parent), &b, &parent->lsn)) != 0)
goto stop;
- }
+ } else
+ LSN_NOT_LOGGED(child->lsn);
/*
* Make the switch.
@@ -491,9 +423,9 @@ err: for (; epg <= cp->csp; ++epg) {
RE_NREC_SET(parent, rcnt);
/* Mark the pages dirty. */
- if ((ret = memp_fset(dbp->mpf, parent, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, parent, DB_MPOOL_DIRTY)) != 0)
goto stop;
- if ((ret = memp_fset(dbp->mpf, child, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, child, DB_MPOOL_DIRTY)) != 0)
goto stop;
/* Adjust the cursors. */
@@ -514,15 +446,13 @@ err: for (; epg <= cp->csp; ++epg) {
if (0) {
stop: done = 1;
}
- if (p_lock.off != LOCK_INVALID)
- (void)__TLPUT(dbc, p_lock);
+ (void)__TLPUT(dbc, p_lock);
if (parent != NULL &&
- (t_ret = memp_fput(dbp->mpf, parent, 0)) != 0 && ret == 0)
+ (t_ret = mpf->put(mpf, parent, 0)) != 0 && ret == 0)
ret = t_ret;
- if (c_lock.off != LOCK_INVALID)
- (void)__TLPUT(dbc, c_lock);
+ (void)__TLPUT(dbc, c_lock);
if (child != NULL &&
- (t_ret = memp_fput(dbp->mpf, child, 0)) != 0 && ret == 0)
+ (t_ret = mpf->put(mpf, child, 0)) != 0 && ret == 0)
ret = t_ret;
}
diff --git a/bdb/btree/bt_method.c b/bdb/btree/bt_method.c
index 5e3af27d033..aa27ed6bab9 100644
--- a/bdb/btree/bt_method.c
+++ b/bdb/btree/bt_method.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_method.c,v 11.20 2000/11/30 00:58:28 ubell Exp $";
+static const char revid[] = "$Id: bt_method.c,v 11.29 2002/04/21 13:17:04 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,9 +16,9 @@ static const char revid[] = "$Id: bt_method.c,v 11.20 2000/11/30 00:58:28 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "qam.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/qam.h"
static int __bam_set_bt_compare
__P((DB *, int (*)(DB *, const DBT *, const DBT *)));
@@ -82,7 +82,8 @@ __bam_db_close(dbp)
{
BTREE *t;
- t = dbp->bt_internal;
+ if ((t = dbp->bt_internal) == NULL)
+ return (0);
/* Recno */
/* Close any backing source file descriptor. */
if (t->re_fp != NULL)
@@ -90,9 +91,9 @@ __bam_db_close(dbp)
/* Free any backing source file name. */
if (t->re_source != NULL)
- __os_freestr(t->re_source);
+ __os_free(dbp->dbenv, t->re_source);
- __os_free(t, sizeof(BTREE));
+ __os_free(dbp->dbenv, t);
dbp->bt_internal = NULL;
return (0);
@@ -127,7 +128,7 @@ __bam_set_flags(dbp, flagsp)
if (LF_ISSET(DB_DUP | DB_DUPSORT)) {
/* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
- if (F_ISSET(dbp, DB_BT_RECNUM))
+ if (F_ISSET(dbp, DB_AM_RECNUM))
goto incompat;
if (LF_ISSET(DB_DUPSORT)) {
@@ -145,12 +146,12 @@ __bam_set_flags(dbp, flagsp)
if (F_ISSET(dbp, DB_AM_DUP))
goto incompat;
- F_SET(dbp, DB_BT_RECNUM);
+ F_SET(dbp, DB_AM_RECNUM);
LF_CLR(DB_RECNUM);
}
if (LF_ISSET(DB_REVSPLITOFF)) {
- F_SET(dbp, DB_BT_REVSPLIT);
+ F_SET(dbp, DB_AM_REVSPLITOFF);
LF_CLR(DB_REVSPLITOFF);
}
@@ -279,12 +280,12 @@ __ram_set_flags(dbp, flagsp)
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
if (LF_ISSET(DB_RENUMBER)) {
- F_SET(dbp, DB_RE_RENUMBER);
+ F_SET(dbp, DB_AM_RENUMBER);
LF_CLR(DB_RENUMBER);
}
if (LF_ISSET(DB_SNAPSHOT)) {
- F_SET(dbp, DB_RE_SNAPSHOT);
+ F_SET(dbp, DB_AM_SNAPSHOT);
LF_CLR(DB_SNAPSHOT);
}
@@ -310,7 +311,7 @@ __ram_set_re_delim(dbp, re_delim)
t = dbp->bt_internal;
t->re_delim = re_delim;
- F_SET(dbp, DB_RE_DELIMITER);
+ F_SET(dbp, DB_AM_DELIMITER);
return (0);
}
@@ -336,7 +337,7 @@ __ram_set_re_len(dbp, re_len)
q = dbp->q_internal;
q->re_len = re_len;
- F_SET(dbp, DB_RE_FIXEDLEN);
+ F_SET(dbp, DB_AM_FIXEDLEN);
return (0);
}
@@ -362,7 +363,7 @@ __ram_set_re_pad(dbp, re_pad)
q = dbp->q_internal;
q->re_pad = re_pad;
- F_SET(dbp, DB_RE_PAD);
+ F_SET(dbp, DB_AM_PAD);
return (0);
}
diff --git a/bdb/btree/bt_open.c b/bdb/btree/bt_open.c
index 405c1880f5e..0b72391c267 100644
--- a/bdb/btree/bt_open.c
+++ b/bdb/btree/bt_open.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_open.c,v 11.42 2000/11/30 00:58:28 ubell Exp $";
+static const char revid[] = "$Id: bt_open.c,v 11.76 2002/09/04 19:06:42 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -54,33 +54,38 @@ static const char revid[] = "$Id: bt_open.c,v 11.42 2000/11/30 00:58:28 ubell Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "btree.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "log.h"
-#include "mp.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/fop.h"
+
+static void __bam_init_meta __P((DB *, BTMETA *, db_pgno_t, DB_LSN *));
/*
* __bam_open --
* Open a btree.
*
- * PUBLIC: int __bam_open __P((DB *, const char *, db_pgno_t, u_int32_t));
+ * PUBLIC: int __bam_open __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, db_pgno_t, u_int32_t));
*/
int
-__bam_open(dbp, name, base_pgno, flags)
+__bam_open(dbp, txn, name, base_pgno, flags)
DB *dbp;
+ DB_TXN *txn;
const char *name;
db_pgno_t base_pgno;
u_int32_t flags;
{
BTREE *t;
+ COMPQUIET(name, NULL);
t = dbp->bt_internal;
/* Initialize the remaining fields/methods of the DB. */
- dbp->del = __bam_delete;
dbp->key_range = __bam_key_range;
dbp->stat = __bam_stat;
@@ -99,8 +104,8 @@ __bam_open(dbp, name, base_pgno, flags)
* Verify that the bt_minkey value specified won't cause the
* calculation of ovflsize to underflow [#2406] for this pagesize.
*/
- if (B_MINKEY_TO_OVFLSIZE(t->bt_minkey, dbp->pgsize) >
- B_MINKEY_TO_OVFLSIZE(DEFMINKEYPAGE, dbp->pgsize)) {
+ if (B_MINKEY_TO_OVFLSIZE(dbp, t->bt_minkey, dbp->pgsize) >
+ B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) {
__db_err(dbp->dbenv,
"bt_minkey value of %lu too high for page size of %lu",
(u_long)t->bt_minkey, (u_long)dbp->pgsize);
@@ -108,7 +113,7 @@ __bam_open(dbp, name, base_pgno, flags)
}
/* Start up the tree. */
- return (__bam_read_root(dbp, name, base_pgno, flags));
+ return (__bam_read_root(dbp, txn, base_pgno, flags));
}
/*
@@ -143,6 +148,7 @@ __bam_metachk(dbp, name, btm)
name, (u_long)vers);
return (DB_OLD_VERSION);
case 8:
+ case 9:
break;
default:
__db_err(dbenv,
@@ -187,13 +193,13 @@ __bam_metachk(dbp, name, btm)
if (F_ISSET(&btm->dbmeta, BTM_RECNUM)) {
if (dbp->type != DB_BTREE)
goto wrong_type;
- F_SET(dbp, DB_BT_RECNUM);
+ F_SET(dbp, DB_AM_RECNUM);
if ((ret = __db_fcchk(dbenv,
- "DB->open", dbp->flags, DB_AM_DUP, DB_BT_RECNUM)) != 0)
+ "DB->open", dbp->flags, DB_AM_DUP, DB_AM_RECNUM)) != 0)
return (ret);
} else
- if (F_ISSET(dbp, DB_BT_RECNUM)) {
+ if (F_ISSET(dbp, DB_AM_RECNUM)) {
__db_err(dbenv,
"%s: DB_RECNUM specified to open method but not set in database",
name);
@@ -203,9 +209,9 @@ __bam_metachk(dbp, name, btm)
if (F_ISSET(&btm->dbmeta, BTM_FIXEDLEN)) {
if (dbp->type != DB_RECNO)
goto wrong_type;
- F_SET(dbp, DB_RE_FIXEDLEN);
+ F_SET(dbp, DB_AM_FIXEDLEN);
} else
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
__db_err(dbenv,
"%s: DB_FIXEDLEN specified to open method but not set in database",
name);
@@ -215,9 +221,9 @@ __bam_metachk(dbp, name, btm)
if (F_ISSET(&btm->dbmeta, BTM_RENUMBER)) {
if (dbp->type != DB_RECNO)
goto wrong_type;
- F_SET(dbp, DB_RE_RENUMBER);
+ F_SET(dbp, DB_AM_RENUMBER);
} else
- if (F_ISSET(dbp, DB_RE_RENUMBER)) {
+ if (F_ISSET(dbp, DB_AM_RENUMBER)) {
__db_err(dbenv,
"%s: DB_RENUMBER specified to open method but not set in database",
name);
@@ -266,116 +272,129 @@ wrong_type:
/*
* __bam_read_root --
- * Check (and optionally create) a tree.
+ * Read the root page and check a tree.
*
- * PUBLIC: int __bam_read_root __P((DB *, const char *, db_pgno_t, u_int32_t));
+ * PUBLIC: int __bam_read_root __P((DB *, DB_TXN *, db_pgno_t, u_int32_t));
*/
int
-__bam_read_root(dbp, name, base_pgno, flags)
+__bam_read_root(dbp, txn, base_pgno, flags)
DB *dbp;
- const char *name;
+ DB_TXN *txn;
db_pgno_t base_pgno;
u_int32_t flags;
{
BTMETA *meta;
BTREE *t;
DBC *dbc;
- DB_LSN orig_lsn;
DB_LOCK metalock;
- PAGE *root;
- int locked, ret, t_ret;
+ DB_MPOOLFILE *mpf;
+ int ret, t_ret;
- ret = 0;
- t = dbp->bt_internal;
meta = NULL;
- root = NULL;
- locked = 0;
+ t = dbp->bt_internal;
+ LOCK_INIT(metalock);
+ mpf = dbp->mpf;
+ ret = 0;
- /*
- * Get a cursor. If DB_CREATE is specified, we may be creating
- * the root page, and to do that safely in CDB we need a write
- * cursor. In STD_LOCKING mode, we'll synchronize using the
- * meta page lock instead.
- */
- if ((ret = dbp->cursor(dbp, dbp->open_txn,
- &dbc, LF_ISSET(DB_CREATE) && CDB_LOCKING(dbp->dbenv) ?
- DB_WRITECURSOR : 0)) != 0)
+ /* Get a cursor. */
+ if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
return (ret);
- /* Get, and optionally create the metadata page. */
+ /* Get the metadata page. */
if ((ret =
__db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
goto err;
- if ((ret = memp_fget(
- dbp->mpf, &base_pgno, DB_MPOOL_CREATE, (PAGE **)&meta)) != 0)
+ if ((ret = mpf->get(mpf, &base_pgno, 0, (PAGE **)&meta)) != 0)
goto err;
/*
- * If the magic number is correct, we're not creating the tree.
- * Correct any fields that may not be right. Note, all of the
- * local flags were set by DB->open.
+ * If the magic number is set, the tree has been created. Correct
+ * any fields that may not be right. Note, all of the local flags
+ * were set by DB->open.
+ *
+ * Otherwise, we'd better be in recovery or abort, in which case the
+ * metadata page will be created/initialized elsewhere.
*/
-again: if (meta->dbmeta.magic != 0) {
- t->bt_maxkey = meta->maxkey;
- t->bt_minkey = meta->minkey;
- t->re_pad = meta->re_pad;
- t->re_len = meta->re_len;
-
- t->bt_meta = base_pgno;
- t->bt_root = meta->root;
-
- (void)memp_fput(dbp->mpf, meta, 0);
- meta = NULL;
- goto done;
- }
+ DB_ASSERT(meta->dbmeta.magic != 0 ||
+ IS_RECOVERING(dbp->dbenv) || F_ISSET(dbp, DB_AM_RECOVER));
- /* In recovery if it's not there it will be created elsewhere.*/
- if (IS_RECOVERING(dbp->dbenv))
- goto done;
-
- /* If we're doing CDB; we now have to get the write lock. */
- if (CDB_LOCKING(dbp->dbenv)) {
- /*
- * We'd better have DB_CREATE set if we're actually doing
- * the create.
- */
- DB_ASSERT(LF_ISSET(DB_CREATE));
- if ((ret = lock_get(dbp->dbenv, dbc->locker, DB_LOCK_UPGRADE,
- &dbc->lock_dbt, DB_LOCK_WRITE, &dbc->mylock)) != 0)
- goto err;
- }
+ t->bt_maxkey = meta->maxkey;
+ t->bt_minkey = meta->minkey;
+ t->re_pad = meta->re_pad;
+ t->re_len = meta->re_len;
+
+ t->bt_meta = base_pgno;
+ t->bt_root = meta->root;
/*
- * If we are doing locking, relase the read lock and get a write lock.
- * We want to avoid deadlock.
+ * !!!
+ * If creating a subdatabase, we've already done an insert when
+ * we put the subdatabase's entry into the master database, so
+ * our last-page-inserted value is wrongly initialized for the
+ * master database, not the subdatabase we're creating. I'm not
+ * sure where the *right* place to clear this value is, it's not
+ * intuitively obvious that it belongs here.
*/
- if (locked == 0 && STD_LOCKING(dbc)) {
- if ((ret = __LPUT(dbc, metalock)) != 0)
- goto err;
- if ((ret = __db_lget(dbc,
- 0, base_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
- goto err;
- locked = 1;
- goto again;
- }
+ t->bt_lpgno = PGNO_INVALID;
+
+ /* We must initialize last_pgno, it could be stale. */
+ if (!LF_ISSET(DB_RDONLY) && dbp->meta_pgno == PGNO_BASE_MD) {
+ mpf->last_pgno(mpf, &meta->dbmeta.last_pgno);
+ ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+ } else
+ ret = mpf->put(mpf, meta, 0);
+ meta = NULL;
+
+err: /* Put the metadata page back. */
+ if (meta != NULL && (t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+}
+
+/*
+ * __bam_init_meta --
+ *
+ * Initialize a btree meta-data page. The following fields may need
+ * to be updated later: last_pgno, root.
+ */
+static void
+__bam_init_meta(dbp, meta, pgno, lsnp)
+ DB *dbp;
+ BTMETA *meta;
+ db_pgno_t pgno;
+ DB_LSN *lsnp;
+{
+ BTREE *t;
- /* Initialize the tree structure metadata information. */
- orig_lsn = meta->dbmeta.lsn;
memset(meta, 0, sizeof(BTMETA));
- meta->dbmeta.lsn = orig_lsn;
- meta->dbmeta.pgno = base_pgno;
+ meta->dbmeta.lsn = *lsnp;
+ meta->dbmeta.pgno = pgno;
meta->dbmeta.magic = DB_BTREEMAGIC;
meta->dbmeta.version = DB_BTREEVERSION;
meta->dbmeta.pagesize = dbp->pgsize;
+ if (F_ISSET(dbp, DB_AM_CHKSUM))
+ FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
+ if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
+ meta->dbmeta.encrypt_alg =
+ ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
+ DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
+ meta->crypto_magic = meta->dbmeta.magic;
+ }
meta->dbmeta.type = P_BTREEMETA;
meta->dbmeta.free = PGNO_INVALID;
+ meta->dbmeta.last_pgno = pgno;
if (F_ISSET(dbp, DB_AM_DUP))
F_SET(&meta->dbmeta, BTM_DUP);
- if (F_ISSET(dbp, DB_RE_FIXEDLEN))
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN))
F_SET(&meta->dbmeta, BTM_FIXEDLEN);
- if (F_ISSET(dbp, DB_BT_RECNUM))
+ if (F_ISSET(dbp, DB_AM_RECNUM))
F_SET(&meta->dbmeta, BTM_RECNUM);
- if (F_ISSET(dbp, DB_RE_RENUMBER))
+ if (F_ISSET(dbp, DB_AM_RENUMBER))
F_SET(&meta->dbmeta, BTM_RENUMBER);
if (F_ISSET(dbp, DB_AM_SUBDB))
F_SET(&meta->dbmeta, BTM_SUBDB);
@@ -385,14 +404,165 @@ again: if (meta->dbmeta.magic != 0) {
F_SET(&meta->dbmeta, BTM_RECNO);
memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
+ t = dbp->bt_internal;
meta->maxkey = t->bt_maxkey;
meta->minkey = t->bt_minkey;
meta->re_len = t->re_len;
meta->re_pad = t->re_pad;
+}
- /* If necessary, log the meta-data and root page creates. */
- if ((ret = __db_log_page(dbp,
- name, &orig_lsn, base_pgno, (PAGE *)meta)) != 0)
+/*
+ * __bam_new_file --
+ * Create the necessary pages to begin a new database file.
+ *
+ * This code appears more complex than it is because of the two cases (named
+ * and unnamed). The way to read the code is that for each page being created,
+ * there are three parts: 1) a "get page" chunk (which either uses malloc'd
+ * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
+ * chunk which either does a fop write or an mpf->put.
+ *
+ * PUBLIC: int __bam_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
+ */
+int
+__bam_new_file(dbp, txn, fhp, name)
+ DB *dbp;
+ DB_TXN *txn;
+ DB_FH *fhp;
+ const char *name;
+{
+ BTMETA *meta;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_MPOOLFILE *mpf;
+ DB_PGINFO pginfo;
+ DBT pdbt;
+ PAGE *root;
+ db_pgno_t pgno;
+ int ret;
+ void *buf;
+
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ root = NULL;
+ meta = NULL;
+ memset(&pdbt, 0, sizeof(pdbt));
+
+ /* Build meta-data page. */
+
+ if (name == NULL) {
+ pgno = PGNO_BASE_MD;
+ ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &meta);
+ } else {
+ pginfo.db_pagesize = dbp->pgsize;
+ pginfo.flags =
+ F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+ pginfo.type = dbp->type;
+ pdbt.data = &pginfo;
+ pdbt.size = sizeof(pginfo);
+ ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
+ meta = (BTMETA *)buf;
+ }
+ if (ret != 0)
+ return (ret);
+
+ LSN_NOT_LOGGED(lsn);
+ __bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
+ meta->root = 1;
+ meta->dbmeta.last_pgno = 1;
+
+ if (name == NULL)
+ ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+ else {
+ if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
+ goto err;
+ ret = __fop_write(dbenv,
+ txn, name, DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
+ }
+ if (ret != 0)
+ goto err;
+ meta = NULL;
+
+ /* Now build root page. */
+ if (name == NULL) {
+ pgno = 1;
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0)
+ goto err;
+ } else {
+#ifdef DIAGNOSTIC
+ memset(buf, dbp->pgsize, 0);
+#endif
+ root = (PAGE *)buf;
+ }
+
+ P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
+ LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
+ LSN_NOT_LOGGED(root->lsn);
+
+ if (name == NULL)
+ ret = mpf->put(mpf, root, DB_MPOOL_DIRTY);
+ else {
+ if ((ret = __db_pgout(dbenv, root->pgno, root, &pdbt)) != 0)
+ goto err;
+ ret = __fop_write(dbenv, txn,
+ name, DB_APP_DATA, fhp, dbp->pgsize, buf, dbp->pgsize, 1);
+ }
+ if (ret != 0)
+ goto err;
+ root = NULL;
+
+err: if (name != NULL)
+ __os_free(dbenv, buf);
+ else {
+ if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ if (root != NULL)
+ (void)mpf->put(mpf, root, 0);
+ }
+ return (ret);
+}
+
+/*
+ * __bam_new_subdb --
+ * Create a metadata page and a root page for a new btree.
+ *
+ * PUBLIC: int __bam_new_subdb __P((DB *, DB *, DB_TXN *));
+ */
+int
+__bam_new_subdb(mdbp, dbp, txn)
+ DB *mdbp, *dbp;
+ DB_TXN *txn;
+{
+ BTMETA *meta;
+ DBC *dbc;
+ DB_ENV *dbenv;
+ DB_LOCK metalock;
+ DB_LSN lsn;
+ DB_MPOOLFILE *mpf;
+ PAGE *root;
+ int ret, t_ret;
+
+ dbenv = mdbp->dbenv;
+ mpf = mdbp->mpf;
+ dbc = NULL;
+ meta = NULL;
+ root = NULL;
+
+ if ((ret = mdbp->cursor(mdbp, txn,
+ &dbc, CDB_LOCKING(dbenv) ? DB_WRITECURSOR : 0)) != 0)
+ return (ret);
+
+ /* Get, and optionally create the metadata page. */
+ if ((ret = __db_lget(dbc,
+ 0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
+ goto err;
+ if ((ret = mpf->get(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
+ goto err;
+
+ /* Build meta-data page. */
+ lsn = meta->dbmeta.lsn;
+ __bam_init_meta(dbp, meta, dbp->meta_pgno, &lsn);
+ if ((ret = __db_log_page(mdbp,
+ txn, &meta->dbmeta.lsn, dbp->meta_pgno, (PAGE *)meta)) != 0)
goto err;
/* Create and initialize a root page. */
@@ -401,68 +571,35 @@ again: if (meta->dbmeta.magic != 0) {
goto err;
root->level = LEAFLEVEL;
- if (dbp->open_txn != NULL && (ret = __bam_root_log(dbp->dbenv,
- dbp->open_txn, &meta->dbmeta.lsn, 0, dbp->log_fileid,
+ if (DBENV_LOGGING(dbenv) &&
+ (ret = __bam_root_log(mdbp, txn, &meta->dbmeta.lsn, 0,
meta->dbmeta.pgno, root->pgno, &meta->dbmeta.lsn)) != 0)
goto err;
meta->root = root->pgno;
-
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, name);
- if ((ret = __db_log_page(dbp,
- name, &root->lsn, root->pgno, root)) != 0)
+ if ((ret =
+ __db_log_page(mdbp, txn, &root->lsn, root->pgno, root)) != 0)
goto err;
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOG, ret, name);
-
- t->bt_meta = base_pgno;
- t->bt_root = root->pgno;
/* Release the metadata and root pages. */
- if ((ret = memp_fput(dbp->mpf, meta, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
goto err;
meta = NULL;
- if ((ret = memp_fput(dbp->mpf, root, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, root, DB_MPOOL_DIRTY)) != 0)
goto err;
root = NULL;
-
- /*
- * Flush the metadata and root pages to disk.
- *
- * !!!
- * It's not useful to return not-yet-flushed here -- convert it to
- * an error.
- */
- if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE) {
- __db_err(dbp->dbenv, "Metapage flush failed");
- ret = EINVAL;
- }
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name);
-
-done: /*
- * !!!
- * We already did an insert and so the last-page-inserted has been
- * set. I'm not sure where the *right* place to clear this value
- * is, it's not intuitively obvious that it belongs here.
- */
- t->bt_lpgno = PGNO_INVALID;
-
err:
-DB_TEST_RECOVERY_LABEL
- /* Put any remaining pages back. */
if (meta != NULL)
- if ((t_ret = memp_fput(dbp->mpf, meta, 0)) != 0 &&
- ret == 0)
+ if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
ret = t_ret;
if (root != NULL)
- if ((t_ret = memp_fput(dbp->mpf, root, 0)) != 0 &&
- ret == 0)
+ if ((t_ret = mpf->put(mpf, root, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (LOCK_ISSET(metalock))
+ if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+ ret = t_ret;
+ if (dbc != NULL)
+ if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
-
- /* We can release the metapage lock when we are done. */
- if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
- ret = t_ret;
-
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
return (ret);
}
diff --git a/bdb/btree/bt_put.c b/bdb/btree/bt_put.c
index 19a04526d1b..39bd2024e76 100644
--- a/bdb/btree/bt_put.c
+++ b/bdb/btree/bt_put.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_put.c,v 11.46 2001/01/17 18:48:46 bostic Exp $";
+static const char revid[] = "$Id: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -53,12 +53,16 @@ static const char revid[] = "$Id: bt_put.c,v 11.46 2001/01/17 18:48:46 bostic Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+static int __bam_build
+ __P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t));
static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t));
static int __bam_ovput
__P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *));
+static u_int32_t
+ __bam_partsize __P((DB *, u_int32_t, DBT *, PAGE *, u_int32_t));
/*
* __bam_iitem --
@@ -77,6 +81,7 @@ __bam_iitem(dbc, key, data, op, flags)
BTREE_CURSOR *cp;
DB *dbp;
DBT bk_hdr, tdbt;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t indx;
u_int32_t data_size, have_bytes, need_bytes, needed;
@@ -85,6 +90,7 @@ __bam_iitem(dbc, key, data, op, flags)
COMPQUIET(bk, NULL);
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
t = dbp->bt_internal;
h = cp->page;
@@ -95,7 +101,7 @@ __bam_iitem(dbc, key, data, op, flags)
* Fixed-length records with partial puts: it's an error to specify
* anything other simple overwrite.
*/
- if (F_ISSET(dbp, DB_RE_FIXEDLEN) &&
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
F_ISSET(data, DB_DBT_PARTIAL) && data->dlen != data->size) {
data_size = data->size;
goto len_err;
@@ -110,16 +116,18 @@ __bam_iitem(dbc, key, data, op, flags)
* the fixed-length record size.
*/
data_size = F_ISSET(data, DB_DBT_PARTIAL) ?
- __bam_partsize(op, data, h, indx) : data->size;
+ __bam_partsize(dbp, op, data, h, indx) : data->size;
padrec = 0;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
if (data_size > t->re_len) {
len_err: __db_err(dbp->dbenv,
"Length improper for fixed length record %lu",
(u_long)data_size);
return (EINVAL);
}
- if (data_size < t->re_len) {
+
+ /* Records that are deleted anyway needn't be padded out. */
+ if (!LF_ISSET(BI_DELETED) && data_size < t->re_len) {
padrec = 1;
data_size = t->re_len;
}
@@ -146,8 +154,8 @@ len_err: __db_err(dbp->dbenv,
*/
if (op == DB_CURRENT && dbp->dup_compare != NULL) {
if ((ret = __bam_cmp(dbp, data, h,
- indx + (TYPE(h) == P_LBTREE ? O_INDX : 0),
- dbp->dup_compare, &cmp)) != 0)
+ indx + (TYPE(h) == P_LBTREE ? O_INDX : 0),
+ dbp->dup_compare, &cmp)) != 0)
return (ret);
if (cmp != 0) {
__db_err(dbp->dbenv,
@@ -190,7 +198,7 @@ len_err: __db_err(dbp->dbenv,
*/
bigkey = 0;
if (op == DB_CURRENT) {
- bk = GET_BKEYDATA(h,
+ bk = GET_BKEYDATA(dbp, h,
indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
if (B_TYPE(bk->type) == B_KEYDATA)
have_bytes = BKEYDATA_PSIZE(bk->len);
@@ -221,7 +229,7 @@ len_err: __db_err(dbp->dbenv,
* The t->bt_maxkey test here may be insufficient -- do we have to
* check in the btree split code, so we don't undo it there!?!?
*/
- if (P_FREESPACE(h) < needed ||
+ if (P_FREESPACE(dbp, h) < needed ||
(t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey))
return (DB_NEEDSPLIT);
@@ -328,6 +336,11 @@ len_err: __db_err(dbp->dbenv,
/* Add the data. */
if (bigdata) {
+ /*
+ * We do not have to handle deleted (BI_DELETED) records
+ * in this case; the actual records should never be created.
+ */
+ DB_ASSERT(!LF_ISSET(BI_DELETED));
if ((ret = __bam_ovput(dbc,
B_OVERFLOW, PGNO_INVALID, h, indx, data)) != 0)
return (ret);
@@ -347,7 +360,7 @@ len_err: __db_err(dbp->dbenv,
if (ret != 0)
return (ret);
}
- if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
/*
@@ -375,7 +388,7 @@ len_err: __db_err(dbp->dbenv,
* up at least 25% of the space on the page. If it does, move it onto
* its own page.
*/
- if (dupadjust && P_FREESPACE(h) <= dbp->pgsize / 2) {
+ if (dupadjust && P_FREESPACE(dbp, h) <= dbp->pgsize / 2) {
if ((ret = __bam_dup_convert(dbc, h, indx - O_INDX)) != 0)
return (ret);
}
@@ -390,11 +403,10 @@ len_err: __db_err(dbp->dbenv,
/*
* __bam_partsize --
* Figure out how much space a partial data item is in total.
- *
- * PUBLIC: u_int32_t __bam_partsize __P((u_int32_t, DBT *, PAGE *, u_int32_t));
*/
-u_int32_t
-__bam_partsize(op, data, h, indx)
+static u_int32_t
+__bam_partsize(dbp, op, data, h, indx)
+ DB *dbp;
u_int32_t op, indx;
DBT *data;
PAGE *h;
@@ -413,38 +425,18 @@ __bam_partsize(op, data, h, indx)
* Otherwise, it's the data provided plus any already existing data
* that we're not replacing.
*/
- bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
+ bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
nbytes =
B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len;
- /*
- * There are really two cases here:
- *
- * Case 1: We are replacing some bytes that do not exist (i.e., they
- * are past the end of the record). In this case the number of bytes
- * we are replacing is irrelevant and all we care about is how many
- * bytes we are going to add from offset. So, the new record length
- * is going to be the size of the new bytes (size) plus wherever those
- * new bytes begin (doff).
- *
- * Case 2: All the bytes we are replacing exist. Therefore, the new
- * size is the oldsize (nbytes) minus the bytes we are replacing (dlen)
- * plus the bytes we are adding (size).
- */
- if (nbytes < data->doff + data->dlen) /* Case 1 */
- return (data->doff + data->size);
-
- return (nbytes + data->size - data->dlen); /* Case 2 */
+ return (__db_partsize(nbytes, data));
}
/*
* __bam_build --
* Build the real record for a partial put, or short fixed-length record.
- *
- * PUBLIC: int __bam_build __P((DBC *, u_int32_t,
- * PUBLIC: DBT *, PAGE *, u_int32_t, u_int32_t));
*/
-int
+static int
__bam_build(dbc, op, dbt, h, indx, nbytes)
DBC *dbc;
u_int32_t op, indx, nbytes;
@@ -454,9 +446,8 @@ __bam_build(dbc, op, dbt, h, indx, nbytes)
BKEYDATA *bk, tbk;
BOVERFLOW *bo;
BTREE *t;
- BTREE_CURSOR *cp;
DB *dbp;
- DBT copy;
+ DBT copy, *rdata;
u_int32_t len, tlen;
u_int8_t *p;
int ret;
@@ -464,26 +455,26 @@ __bam_build(dbc, op, dbt, h, indx, nbytes)
COMPQUIET(bo, NULL);
dbp = dbc->dbp;
- cp = (BTREE_CURSOR *) dbc->internal;
t = dbp->bt_internal;
/* We use the record data return memory, it's only a short-term use. */
- if (dbc->rdata.ulen < nbytes) {
+ rdata = &dbc->my_rdata;
+ if (rdata->ulen < nbytes) {
if ((ret = __os_realloc(dbp->dbenv,
- nbytes, NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
+ nbytes, &rdata->data)) != 0) {
+ rdata->ulen = 0;
+ rdata->data = NULL;
return (ret);
}
- dbc->rdata.ulen = nbytes;
+ rdata->ulen = nbytes;
}
/*
* We use nul or pad bytes for any part of the record that isn't
* specified; get it over with.
*/
- memset(dbc->rdata.data,
- F_ISSET(dbp, DB_RE_FIXEDLEN) ? t->re_pad : 0, nbytes);
+ memset(rdata->data,
+ F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_pad : 0, nbytes);
/*
* In the next clauses, we need to do three things: a) set p to point
@@ -495,14 +486,15 @@ __bam_build(dbc, op, dbt, h, indx, nbytes)
* the chase.
*/
if (!F_ISSET(dbt, DB_DBT_PARTIAL) || op != DB_CURRENT) {
- p = (u_int8_t *)dbc->rdata.data + dbt->doff;
+ p = (u_int8_t *)rdata->data + dbt->doff;
tlen = dbt->doff;
goto user_copy;
}
/* Find the current record. */
if (indx < NUM_ENT(h)) {
- bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
+ bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ?
+ O_INDX : 0));
bo = (BOVERFLOW *)bk;
} else {
bk = &tbk;
@@ -516,12 +508,12 @@ __bam_build(dbc, op, dbt, h, indx, nbytes)
*/
memset(&copy, 0, sizeof(copy));
if ((ret = __db_goff(dbp, &copy, bo->tlen,
- bo->pgno, &dbc->rdata.data, &dbc->rdata.ulen)) != 0)
+ bo->pgno, &rdata->data, &rdata->ulen)) != 0)
return (ret);
/* Skip any leading data from the original record. */
tlen = dbt->doff;
- p = (u_int8_t *)dbc->rdata.data + dbt->doff;
+ p = (u_int8_t *)rdata->data + dbt->doff;
/*
* Copy in any trailing data from the original record.
@@ -542,10 +534,10 @@ __bam_build(dbc, op, dbt, h, indx, nbytes)
}
} else {
/* Copy in any leading data from the original record. */
- memcpy(dbc->rdata.data,
+ memcpy(rdata->data,
bk->data, dbt->doff > bk->len ? bk->len : dbt->doff);
tlen = dbt->doff;
- p = (u_int8_t *)dbc->rdata.data + dbt->doff;
+ p = (u_int8_t *)rdata->data + dbt->doff;
/* Copy in any trailing data from the original record. */
len = dbt->doff + dbt->dlen;
@@ -564,11 +556,11 @@ user_copy:
tlen += dbt->size;
/* Set the DBT to reference our new record. */
- dbc->rdata.size = F_ISSET(dbp, DB_RE_FIXEDLEN) ? t->re_len : tlen;
- dbc->rdata.dlen = 0;
- dbc->rdata.doff = 0;
- dbc->rdata.flags = 0;
- *dbt = dbc->rdata;
+ rdata->size = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : tlen;
+ rdata->dlen = 0;
+ rdata->doff = 0;
+ rdata->flags = 0;
+ *dbt = *rdata;
return (0);
}
@@ -591,6 +583,7 @@ __bam_ritem(dbc, h, indx, data)
db_indx_t cnt, lo, ln, min, off, prefix, suffix;
int32_t nbytes;
int ret;
+ db_indx_t *inp;
u_int8_t *p, *t;
dbp = dbc->dbp;
@@ -600,10 +593,10 @@ __bam_ritem(dbc, h, indx, data)
* to insert and whether it fits is handled in the caller. All we do
* here is manage the page shuffling.
*/
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
/* Log the change. */
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
/*
* We might as well check to see if the two data items share
* a common prefix and suffix -- it can save us a lot of log
@@ -627,17 +620,18 @@ __bam_ritem(dbc, h, indx, data)
orig.size = bk->len - (prefix + suffix);
repl.data = (u_int8_t *)data->data + prefix;
repl.size = data->size - (prefix + suffix);
- if ((ret = __bam_repl_log(dbp->dbenv, dbc->txn,
- &LSN(h), 0, dbp->log_fileid, PGNO(h), &LSN(h),
- (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type),
+ if ((ret = __bam_repl_log(dbp, dbc->txn, &LSN(h), 0, PGNO(h),
+ &LSN(h), (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type),
&orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0)
return (ret);
- }
+ } else
+ LSN_NOT_LOGGED(LSN(h));
/*
* Set references to the first in-use byte on the page and the
* first byte of the item being replaced.
*/
+ inp = P_INP(dbp, h);
p = (u_int8_t *)h + HOFFSET(h);
t = (u_int8_t *)bk;
@@ -648,19 +642,19 @@ __bam_ritem(dbc, h, indx, data)
* the regions overlap.
*/
lo = BKEYDATA_SIZE(bk->len);
- ln = BKEYDATA_SIZE(data->size);
+ ln = (db_indx_t)BKEYDATA_SIZE(data->size);
if (lo != ln) {
nbytes = lo - ln; /* Signed difference. */
if (p == t) /* First index is fast. */
- h->inp[indx] += nbytes;
+ inp[indx] += nbytes;
else { /* Else, shift the page. */
memmove(p + nbytes, p, t - p);
/* Adjust the indices' offsets. */
- off = h->inp[indx];
+ off = inp[indx];
for (cnt = 0; cnt < NUM_ENT(h); ++cnt)
- if (h->inp[cnt] <= off)
- h->inp[cnt] += nbytes;
+ if (inp[cnt] <= off)
+ inp[cnt] += nbytes;
}
/* Clean up the page and adjust the item's reference. */
@@ -688,30 +682,31 @@ __bam_dup_convert(dbc, h, indx)
PAGE *h;
u_int32_t indx;
{
- BTREE_CURSOR *cp;
BKEYDATA *bk;
DB *dbp;
DBT hdr;
+ DB_MPOOLFILE *mpf;
PAGE *dp;
- db_indx_t cnt, cpindx, dindx, first, sz;
+ db_indx_t cnt, cpindx, dindx, first, *inp, sz;
int ret;
dbp = dbc->dbp;
- cp = (BTREE_CURSOR *)dbc->internal;
+ mpf = dbp->mpf;
+ inp = P_INP(dbp, h);
/*
* Count the duplicate records and calculate how much room they're
* using on the page.
*/
- while (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
+ while (indx > 0 && inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
for (cnt = 0, sz = 0, first = indx;; ++cnt, indx += P_INDX) {
- if (indx >= NUM_ENT(h) || h->inp[first] != h->inp[indx])
+ if (indx >= NUM_ENT(h) || inp[first] != inp[indx])
break;
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
sz += B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
- bk = GET_BKEYDATA(h, indx + O_INDX);
+ bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
sz += B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
}
@@ -766,7 +761,7 @@ __bam_dup_convert(dbc, h, indx)
* deleted entries are discarded (if the deleted entry is
* overflow, then free up those pages).
*/
- bk = GET_BKEYDATA(h, dindx + 1);
+ bk = GET_BKEYDATA(dbp, h, dindx + 1);
hdr.data = bk;
hdr.size = B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_SIZE(bk->len) : BOVERFLOW_SIZE;
@@ -778,7 +773,7 @@ __bam_dup_convert(dbc, h, indx)
*/
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_doff(dbc,
- (GET_BOVERFLOW(h, dindx + 1))->pgno)) != 0)
+ (GET_BOVERFLOW(dbp, h, dindx + 1))->pgno)) != 0)
goto err;
} else {
if ((ret = __db_pitem(
@@ -802,7 +797,7 @@ __bam_dup_convert(dbc, h, indx)
/* Put in a new data item that points to the duplicates page. */
if ((ret = __bam_ovput(dbc,
- B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0)
+ B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0)
goto err;
/* Adjust cursors for all the above movments. */
@@ -810,9 +805,9 @@ __bam_dup_convert(dbc, h, indx)
PGNO(h), first + P_INDX, first + P_INDX - indx)) != 0)
goto err;
- return (memp_fput(dbp->mpf, dp, DB_MPOOL_DIRTY));
+ return (mpf->put(mpf, dp, DB_MPOOL_DIRTY));
-err: (void)__db_free(dbc, dp);
+err: (void)mpf->put(mpf, dp, 0);
return (ret);
}
diff --git a/bdb/btree/bt_rec.c b/bdb/btree/bt_rec.c
index 24dc9bc6a6e..b6443547aa5 100644
--- a/bdb/btree/bt_rec.c
+++ b/bdb/btree/bt_rec.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_rec.c,v 11.35 2001/01/10 16:24:47 ubell Exp $";
+static const char revid[] = "$Id: bt_rec.c,v 11.57 2002/08/06 16:53:53 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,287 +18,17 @@ static const char revid[] = "$Id: bt_rec.c,v 11.35 2001/01/10 16:24:47 ubell Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "hash.h"
-#include "btree.h"
-#include "log.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
#define IS_BTREE_PAGE(pagep) \
(TYPE(pagep) == P_IBTREE || \
TYPE(pagep) == P_LBTREE || TYPE(pagep) == P_LDUP)
/*
- * __bam_pg_alloc_recover --
- * Recovery function for pg_alloc.
- *
- * PUBLIC: int __bam_pg_alloc_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__bam_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __bam_pg_alloc_args *argp;
- DB *file_dbp;
- DBC *dbc;
- DBMETA *meta;
- DB_MPOOLFILE *mpf;
- PAGE *pagep;
- db_pgno_t pgno;
- int cmp_n, cmp_p, level, modified, ret;
-
- REC_PRINT(__bam_pg_alloc_print);
- REC_INTRO(__bam_pg_alloc_read, 0);
-
- /*
- * Fix up the allocated page. If we're redoing the operation, we have
- * to get the page (creating it if it doesn't exist), and update its
- * LSN. If we're undoing the operation, we have to reset the page's
- * LSN and put it on the free list.
- *
- * Fix up the metadata page. If we're redoing the operation, we have
- * to get the metadata page and update its LSN and its free pointer.
- * If we're undoing the operation and the page was ever created, we put
- * it on the freelist.
- */
- pgno = PGNO_BASE_MD;
- meta = NULL;
- if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) {
- /* The metadata page must always exist on redo. */
- if (DB_REDO(op)) {
- (void)__db_pgerr(file_dbp, pgno);
- goto out;
- } else
- goto done;
- }
- if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
- /*
- * We specify creation and check for it later, because this
- * operation was supposed to create the page, and even in
- * the undo case it's going to get linked onto the freelist
- * which we're also fixing up.
- */
- (void)__db_pgerr(file_dbp, argp->pgno);
- goto err;
- }
-
- /* Fix up the allocated page. */
- modified = 0;
- cmp_n = log_compare(lsnp, &LSN(pagep));
- cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
-
- /*
- * If an inital allocation is aborted and then reallocated
- * during an archival restore the log record will have
- * an LSN for the page but the page will be empty.
- */
- if (IS_ZERO_LSN(LSN(pagep)))
- cmp_p = 0;
- CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
- /*
- * If we we rolled back this allocation previously during an
- * archive restore, the page may have the LSN of the meta page
- * at the point of the roll back. This will be no more
- * than the LSN of the metadata page at the time of this allocation.
- */
- if (DB_REDO(op) &&
- (cmp_p == 0 ||
- (IS_ZERO_LSN(argp->page_lsn) &&
- log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
- /* Need to redo update described. */
- switch (argp->ptype) {
- case P_LBTREE:
- case P_LRECNO:
- case P_LDUP:
- level = LEAFLEVEL;
- break;
- default:
- level = 0;
- break;
- }
- P_INIT(pagep, file_dbp->pgsize,
- argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);
-
- pagep->lsn = *lsnp;
- modified = 1;
- } else if (cmp_n == 0 && DB_UNDO(op)) {
- /*
- * Undo the allocation, reinitialize the page and
- * link its next pointer to the free list.
- */
- P_INIT(pagep, file_dbp->pgsize,
- argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
-
- pagep->lsn = argp->page_lsn;
- modified = 1;
- }
-
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
- goto err;
- }
-
- /*
- * If the page was newly created, put it on the limbo list.
- */
- if (IS_ZERO_LSN(LSN(pagep)) &&
- IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
- /* Put the page in limbo.*/
- if ((ret = __db_add_limbo(dbenv,
- info, argp->fileid, argp->pgno, 1)) != 0)
- goto err;
- }
-
- /* Fix up the metadata page. */
- modified = 0;
- cmp_n = log_compare(lsnp, &LSN(meta));
- cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
- CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
- if (cmp_p == 0 && DB_REDO(op)) {
- /* Need to redo update described. */
- LSN(meta) = *lsnp;
- meta->free = argp->next;
- modified = 1;
- } else if (cmp_n == 0 && DB_UNDO(op)) {
- /* Need to undo update described. */
- LSN(meta) = argp->meta_lsn;
-
- /*
- * If the page has a zero LSN then its newly created
- * and will go into limbo rather than directly on the
- * free list.
- */
- if (!IS_ZERO_LSN(argp->page_lsn))
- meta->free = argp->pgno;
- modified = 1;
- }
- if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
- goto out;
- /*
- * This could be the metapage from a subdb which is read from disk
- * to recover its creation.
- */
- if (F_ISSET(file_dbp, DB_AM_SUBDB))
- switch (argp->type) {
- case P_BTREEMETA:
- case P_HASHMETA:
- case P_QAMMETA:
- file_dbp->sync(file_dbp, 0);
- break;
- }
-
-done: *lsnp = argp->prev_lsn;
- ret = 0;
-
- if (0) {
-err:
- if (meta != NULL)
- (void)memp_fput(mpf, meta, 0);
- }
-out: REC_CLOSE;
-}
-
-/*
- * __bam_pg_free_recover --
- * Recovery function for pg_free.
- *
- * PUBLIC: int __bam_pg_free_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__bam_pg_free_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __bam_pg_free_args *argp;
- DB *file_dbp;
- DBC *dbc;
- DBMETA *meta;
- DB_LSN copy_lsn;
- DB_MPOOLFILE *mpf;
- PAGE *pagep;
- db_pgno_t pgno;
- int cmp_n, cmp_p, modified, ret;
-
- COMPQUIET(info, NULL);
- REC_PRINT(__bam_pg_free_print);
- REC_INTRO(__bam_pg_free_read, 1);
-
- /*
- * Fix up the freed page. If we're redoing the operation we get the
- * page and explicitly discard its contents, then update its LSN. If
- * we're undoing the operation, we get the page and restore its header.
- * Create the page if necessary, we may be freeing an aborted
- * create.
- */
- if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
- goto out;
- modified = 0;
- __ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
- cmp_n = log_compare(lsnp, &LSN(pagep));
- cmp_p = log_compare(&LSN(pagep), &copy_lsn);
- CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
- if (DB_REDO(op) &&
- (cmp_p == 0 ||
- (IS_ZERO_LSN(copy_lsn) &&
- log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
- /* Need to redo update described. */
- P_INIT(pagep, file_dbp->pgsize,
- argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
- pagep->lsn = *lsnp;
-
- modified = 1;
- } else if (cmp_n == 0 && DB_UNDO(op)) {
- /* Need to undo update described. */
- memcpy(pagep, argp->header.data, argp->header.size);
-
- modified = 1;
- }
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
- goto out;
-
- /*
- * Fix up the metadata page. If we're redoing or undoing the operation
- * we get the page and update its LSN and free pointer.
- */
- pgno = PGNO_BASE_MD;
- if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) {
- /* The metadata page must always exist. */
- (void)__db_pgerr(file_dbp, pgno);
- goto out;
- }
-
- modified = 0;
- cmp_n = log_compare(lsnp, &LSN(meta));
- cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
- CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
- if (cmp_p == 0 && DB_REDO(op)) {
- /* Need to redo the deallocation. */
- meta->free = argp->pgno;
- LSN(meta) = *lsnp;
- modified = 1;
- } else if (cmp_n == 0 && DB_UNDO(op)) {
- /* Need to undo the deallocation. */
- meta->free = argp->next;
- LSN(meta) = argp->meta_lsn;
- modified = 1;
- }
- if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
- goto out;
-
-done: *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: REC_CLOSE;
-}
-
-/*
* __bam_split_recover --
* Recovery function for split.
*
@@ -320,7 +50,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp;
db_pgno_t pgno, root_pgno;
u_int32_t ptype;
- int cmp, l_update, p_update, r_update, rc, ret, rootsplit, t_ret;
+ int cmp, l_update, p_update, r_update, rc, ret, ret_l, rootsplit, t_ret;
COMPQUIET(info, NULL);
REC_PRINT(__bam_split_print);
@@ -345,16 +75,16 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
* so it's got to be aligned. Copying it into allocated memory is
* the only way to guarantee this.
*/
- if ((ret = __os_malloc(dbenv, argp->pg.size, NULL, &sp)) != 0)
+ if ((ret = __os_malloc(dbenv, argp->pg.size, &sp)) != 0)
goto out;
memcpy(sp, argp->pg.data, argp->pg.size);
pgno = PGNO(sp);
root_pgno = argp->root_pgno;
- rootsplit = pgno == root_pgno;
- if (memp_fget(mpf, &argp->left, 0, &lp) != 0)
+ rootsplit = root_pgno != PGNO_INVALID;
+ if ((ret_l = mpf->get(mpf, &argp->left, 0, &lp)) != 0)
lp = NULL;
- if (memp_fget(mpf, &argp->right, 0, &rp) != 0)
+ if (mpf->get(mpf, &argp->right, 0, &rp) != 0)
rp = NULL;
if (DB_REDO(op)) {
@@ -368,8 +98,8 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
* same reason.
*/
if (rootsplit) {
- if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) {
- (void)__db_pgerr(file_dbp, pgno);
+ if ((ret = mpf->get(mpf, &pgno, 0, &pp)) != 0) {
+ __db_pgerr(file_dbp, pgno, ret);
pp = NULL;
goto out;
}
@@ -377,7 +107,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
CHECK_LSN(op, cmp, &LSN(pp), &LSN(argp->pg.data));
p_update = cmp == 0;
} else if (lp == NULL) {
- (void)__db_pgerr(file_dbp, argp->left);
+ __db_pgerr(file_dbp, argp->left, ret_l);
goto out;
}
@@ -400,10 +130,8 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
goto check_next;
/* Allocate and initialize new left/right child pages. */
- if ((ret =
- __os_malloc(dbenv, file_dbp->pgsize, NULL, &_lp)) != 0
- || (ret =
- __os_malloc(dbenv, file_dbp->pgsize, NULL, &_rp)) != 0)
+ if ((ret = __os_malloc(dbenv, file_dbp->pgsize, &_lp)) != 0 ||
+ (ret = __os_malloc(dbenv, file_dbp->pgsize, &_rp)) != 0)
goto out;
if (rootsplit) {
P_INIT(_lp, file_dbp->pgsize, argp->left,
@@ -431,31 +159,31 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
goto out;
/* If the left child is wrong, update it. */
- if (lp == NULL && (ret =
- memp_fget(mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) {
- (void)__db_pgerr(file_dbp, argp->left);
+ if (lp == NULL && (ret = mpf->get(
+ mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) {
+ __db_pgerr(file_dbp, argp->left, ret);
lp = NULL;
goto out;
}
if (l_update) {
memcpy(lp, _lp, file_dbp->pgsize);
lp->lsn = *lsnp;
- if ((ret = memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, lp, DB_MPOOL_DIRTY)) != 0)
goto out;
lp = NULL;
}
/* If the right child is wrong, update it. */
- if (rp == NULL && (ret = memp_fget(mpf,
- &argp->right, DB_MPOOL_CREATE, &rp)) != 0) {
- (void)__db_pgerr(file_dbp, argp->right);
+ if (rp == NULL && (ret = mpf->get(
+ mpf, &argp->right, DB_MPOOL_CREATE, &rp)) != 0) {
+ __db_pgerr(file_dbp, argp->right, ret);
rp = NULL;
goto out;
}
if (r_update) {
memcpy(rp, _rp, file_dbp->pgsize);
rp->lsn = *lsnp;
- if ((ret = memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, rp, DB_MPOOL_DIRTY)) != 0)
goto out;
rp = NULL;
}
@@ -477,11 +205,11 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
P_INIT(pp, file_dbp->pgsize, root_pgno,
PGNO_INVALID, PGNO_INVALID, _lp->level + 1, ptype);
- RE_NREC_SET(pp,
- rc ? __bam_total(_lp) + __bam_total(_rp) : 0);
+ RE_NREC_SET(pp, rc ? __bam_total(file_dbp, _lp) +
+ __bam_total(file_dbp, _rp) : 0);
pp->lsn = *lsnp;
- if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
goto out;
pp = NULL;
}
@@ -494,8 +222,8 @@ check_next: /*
* page must exist because we're redoing the operation.
*/
if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
- if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
- (void)__db_pgerr(file_dbp, argp->npgno);
+ if ((ret = mpf->get(mpf, &argp->npgno, 0, &np)) != 0) {
+ __db_pgerr(file_dbp, argp->npgno, ret);
np = NULL;
goto out;
}
@@ -505,7 +233,7 @@ check_next: /*
PREV_PGNO(np) = argp->right;
np->lsn = *lsnp;
if ((ret =
- memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0)
+ mpf->put(mpf, np, DB_MPOOL_DIRTY)) != 0)
goto out;
np = NULL;
}
@@ -518,13 +246,13 @@ check_next: /*
* the adds onto the page that caused the split, and there's
* really no undo-ing to be done.
*/
- if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) {
+ if ((ret = mpf->get(mpf, &pgno, 0, &pp)) != 0) {
pp = NULL;
goto lrundo;
}
if (log_compare(lsnp, &LSN(pp)) == 0) {
memcpy(pp, argp->pg.data, argp->pg.size);
- if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
goto out;
pp = NULL;
}
@@ -542,7 +270,7 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
log_compare(lsnp, &LSN(lp)) == 0) {
lp->lsn = argp->llsn;
if ((ret =
- memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
+ mpf->put(mpf, lp, DB_MPOOL_DIRTY)) != 0)
goto out;
lp = NULL;
}
@@ -550,7 +278,7 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
log_compare(lsnp, &LSN(rp)) == 0) {
rp->lsn = argp->rlsn;
if ((ret =
- memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
+ mpf->put(mpf, rp, DB_MPOOL_DIRTY)) != 0)
goto out;
rp = NULL;
}
@@ -565,14 +293,14 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
* if there's nothing to undo.
*/
if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
- if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->npgno, 0, &np)) != 0) {
np = NULL;
goto done;
}
if (log_compare(lsnp, &LSN(np)) == 0) {
PREV_PGNO(np) = argp->left;
np->lsn = argp->nlsn;
- if (memp_fput(mpf, np, DB_MPOOL_DIRTY))
+ if (mpf->put(mpf, np, DB_MPOOL_DIRTY))
goto out;
np = NULL;
}
@@ -583,22 +311,22 @@ done: *lsnp = argp->prev_lsn;
ret = 0;
out: /* Free any pages that weren't dirtied. */
- if (pp != NULL && (t_ret = memp_fput(mpf, pp, 0)) != 0 && ret == 0)
+ if (pp != NULL && (t_ret = mpf->put(mpf, pp, 0)) != 0 && ret == 0)
ret = t_ret;
- if (lp != NULL && (t_ret = memp_fput(mpf, lp, 0)) != 0 && ret == 0)
+ if (lp != NULL && (t_ret = mpf->put(mpf, lp, 0)) != 0 && ret == 0)
ret = t_ret;
- if (np != NULL && (t_ret = memp_fput(mpf, np, 0)) != 0 && ret == 0)
+ if (np != NULL && (t_ret = mpf->put(mpf, np, 0)) != 0 && ret == 0)
ret = t_ret;
- if (rp != NULL && (t_ret = memp_fput(mpf, rp, 0)) != 0 && ret == 0)
+ if (rp != NULL && (t_ret = mpf->put(mpf, rp, 0)) != 0 && ret == 0)
ret = t_ret;
/* Free any allocated space. */
if (_lp != NULL)
- __os_free(_lp, file_dbp->pgsize);
+ __os_free(dbenv, _lp);
if (_rp != NULL)
- __os_free(_rp, file_dbp->pgsize);
+ __os_free(dbenv, _rp);
if (sp != NULL)
- __os_free(sp, argp->pg.size);
+ __os_free(dbenv, sp);
REC_CLOSE;
}
@@ -627,23 +355,24 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
db_pgno_t pgno, root_pgno;
int cmp_n, cmp_p, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_rsplit_print);
REC_INTRO(__bam_rsplit_read, 1);
/* Fix the root page. */
pgno = root_pgno = argp->root_pgno;
- if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
/* The root page must always exist if we are going forward. */
if (DB_REDO(op)) {
- __db_pgerr(file_dbp, pgno);
+ __db_pgerr(file_dbp, pgno, ret);
goto out;
}
/* This must be the root of an OPD tree. */
DB_ASSERT(root_pgno !=
((BTREE *)file_dbp->bt_internal)->bt_root);
ret = 0;
- goto done;
+ goto do_page;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -666,22 +395,23 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
pagep->lsn = argp->rootlsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+do_page:
/*
* Fix the page copied over the root page. It's possible that the
* page never made it to disk, so if we're undo-ing and the page
* doesn't exist, it's okay and there's nothing further to do.
*/
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
modified = 0;
- __ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
+ (void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &copy_lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
@@ -694,13 +424,16 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -725,15 +458,16 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
PAGE *pagep;
int cmp_n, cmp_p, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_adj_print);
REC_INTRO(__bam_adj_read, 1);
/* Get the page; if it never existed and we're undoing, we're done. */
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
@@ -745,7 +479,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
/* Need to redo update described. */
if ((ret = __bam_adjindx(dbc,
pagep, argp->indx, argp->indx_copy, argp->is_insert)) != 0)
- goto err;
+ goto out;
LSN(pagep) = *lsnp;
modified = 1;
@@ -753,21 +487,21 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
/* Need to undo update described. */
if ((ret = __bam_adjindx(dbc,
pagep, argp->indx, argp->indx_copy, !argp->is_insert)) != 0)
- goto err;
+ goto out;
LSN(pagep) = argp->lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
- if (0) {
-err: (void)memp_fput(mpf, pagep, 0);
- }
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -793,15 +527,16 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
PAGE *pagep;
int cmp_n, cmp_p, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_cadjust_print);
REC_INTRO(__bam_cadjust_read, 1);
/* Get the page; if it never existed and we're undoing, we're done. */
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
@@ -812,11 +547,13 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
if (IS_BTREE_PAGE(pagep)) {
- GET_BINTERNAL(pagep, argp->indx)->nrecs += argp->adjust;
+ GET_BINTERNAL(file_dbp, pagep, argp->indx)->nrecs +=
+ argp->adjust;
if (argp->opflags & CAD_UPDATEROOT)
RE_NREC_ADJ(pagep, argp->adjust);
} else {
- GET_RINTERNAL(pagep, argp->indx)->nrecs += argp->adjust;
+ GET_RINTERNAL(file_dbp, pagep, argp->indx)->nrecs +=
+ argp->adjust;
if (argp->opflags & CAD_UPDATEROOT)
RE_NREC_ADJ(pagep, argp->adjust);
}
@@ -826,24 +563,29 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
} else if (cmp_n == 0 && DB_UNDO(op)) {
/* Need to undo update described. */
if (IS_BTREE_PAGE(pagep)) {
- GET_BINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust;
+ GET_BINTERNAL(file_dbp, pagep, argp->indx)->nrecs -=
+ argp->adjust;
if (argp->opflags & CAD_UPDATEROOT)
RE_NREC_ADJ(pagep, -(argp->adjust));
} else {
- GET_RINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust;
+ GET_RINTERNAL(file_dbp, pagep, argp->indx)->nrecs -=
+ argp->adjust;
if (argp->opflags & CAD_UPDATEROOT)
RE_NREC_ADJ(pagep, -(argp->adjust));
}
LSN(pagep) = argp->lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -869,15 +611,16 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
u_int32_t indx;
int cmp_n, cmp_p, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_cdel_print);
REC_INTRO(__bam_cdel_read, 1);
/* Get the page; if it never existed and we're undoing, we're done. */
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
@@ -888,27 +631,30 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
- B_DSET(GET_BKEYDATA(pagep, indx)->type);
+ B_DSET(GET_BKEYDATA(file_dbp, pagep, indx)->type);
LSN(pagep) = *lsnp;
modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
/* Need to undo update described. */
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
- B_DCLR(GET_BKEYDATA(pagep, indx)->type);
+ B_DCLR(GET_BKEYDATA(file_dbp, pagep, indx)->type);
(void)__bam_ca_delete(file_dbp, argp->pgno, argp->indx, 0);
LSN(pagep) = argp->lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -936,18 +682,19 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
int cmp_n, cmp_p, modified, ret;
u_int8_t *p;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_repl_print);
REC_INTRO(__bam_repl_read, 1);
/* Get the page; if it never existed and we're undoing, we're done. */
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
- bk = GET_BKEYDATA(pagep, argp->indx);
+ bk = GET_BKEYDATA(file_dbp, pagep, argp->indx);
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -961,8 +708,8 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
*/
memset(&dbt, 0, sizeof(dbt));
dbt.size = argp->prefix + argp->suffix + argp->repl.size;
- if ((ret = __os_malloc(dbenv, dbt.size, NULL, &dbt.data)) != 0)
- goto err;
+ if ((ret = __os_malloc(dbenv, dbt.size, &dbt.data)) != 0)
+ goto out;
p = dbt.data;
memcpy(p, bk->data, argp->prefix);
p += argp->prefix;
@@ -971,9 +718,9 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
ret = __bam_ritem(dbc, pagep, argp->indx, &dbt);
- __os_free(dbt.data, dbt.size);
+ __os_free(dbenv, dbt.data);
if (ret != 0)
- goto err;
+ goto out;
LSN(pagep) = *lsnp;
modified = 1;
@@ -985,8 +732,8 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
*/
memset(&dbt, 0, sizeof(dbt));
dbt.size = argp->prefix + argp->suffix + argp->orig.size;
- if ((ret = __os_malloc(dbenv, dbt.size, NULL, &dbt.data)) != 0)
- goto err;
+ if ((ret = __os_malloc(dbenv, dbt.size, &dbt.data)) != 0)
+ goto out;
p = dbt.data;
memcpy(p, bk->data, argp->prefix);
p += argp->prefix;
@@ -995,27 +742,27 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
ret = __bam_ritem(dbc, pagep, argp->indx, &dbt);
- __os_free(dbt.data, dbt.size);
+ __os_free(dbenv, dbt.data);
if (ret != 0)
- goto err;
+ goto out;
/* Reset the deleted flag, if necessary. */
if (argp->isdeleted)
- B_DSET(GET_BKEYDATA(pagep, argp->indx)->type);
+ B_DSET(GET_BKEYDATA(file_dbp, pagep, argp->indx)->type);
LSN(pagep) = argp->lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
- if (0) {
-err: (void)memp_fput(mpf, pagep, 0);
- }
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -1040,14 +787,15 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf;
int cmp_n, cmp_p, modified, ret;
+ meta = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_root_print);
REC_INTRO(__bam_root_read, 0);
- if ((ret = memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
/* The metadata page must always exist on redo. */
if (DB_REDO(op)) {
- (void)__db_pgerr(file_dbp, argp->meta_pgno);
+ __db_pgerr(file_dbp, argp->meta_pgno, ret);
goto out;
} else
goto done;
@@ -1068,13 +816,16 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
meta->dbmeta.lsn = argp->meta_lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ meta = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ REC_CLOSE;
}
/*
@@ -1116,7 +867,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
break;
case DB_CA_DUP:
if ((ret = __bam_ca_undodup(file_dbp, argp->first_indx,
- argp->from_pgno, argp->from_indx, argp->to_indx)) != 0)
+ argp->from_pgno, argp->from_indx, argp->to_indx)) != 0)
goto out;
break;
@@ -1181,7 +932,8 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
* this function know anything about how offpage dups work.
*/
if ((ret =
- __db_icursor(file_dbp, NULL, DB_RECNO, argp->root, 0, &rdbc)) != 0)
+ __db_icursor(file_dbp,
+ NULL, DB_RECNO, argp->root, 0, DB_LOCK_INVALIDID, &rdbc)) != 0)
goto out;
cp = (BTREE_CURSOR *)rdbc->internal;
diff --git a/bdb/btree/bt_reclaim.c b/bdb/btree/bt_reclaim.c
index 538d837c2d2..ae4554ea7d6 100644
--- a/bdb/btree/bt_reclaim.c
+++ b/bdb/btree/bt_reclaim.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_reclaim.c,v 11.5 2000/03/22 04:21:01 ubell Exp $";
+static const char revid[] = "$Id: bt_reclaim.c,v 11.11 2002/03/29 20:46:26 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,10 +18,8 @@ static const char revid[] = "$Id: bt_reclaim.c,v 11.5 2000/03/22 04:21:01 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
/*
* __bam_reclaim --
@@ -51,3 +49,38 @@ __bam_reclaim(dbp, txn)
return (ret);
}
+
+/*
+ * __bam_truncate --
+ * Truncate a database.
+ *
+ * PUBLIC: int __bam_truncate __P((DB *, DB_TXN *, u_int32_t *));
+ */
+int
+__bam_truncate(dbp, txn, countp)
+ DB *dbp;
+ DB_TXN *txn;
+ u_int32_t *countp;
+{
+ DBC *dbc;
+ db_trunc_param trunc;
+ int ret, t_ret;
+
+ /* Acquire a cursor. */
+ if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+ return (ret);
+
+ trunc.count = 0;
+ trunc.dbc = dbc;
+ /* Walk the tree, freeing pages. */
+ ret = __bam_traverse(dbc,
+ DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc);
+
+ /* Discard the cursor. */
+ if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ *countp = trunc.count;
+
+ return (ret);
+}
diff --git a/bdb/btree/bt_recno.c b/bdb/btree/bt_recno.c
index 6ac0cac350d..fab684f3a5f 100644
--- a/bdb/btree/bt_recno.c
+++ b/bdb/btree/bt_recno.c
@@ -1,36 +1,31 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_recno.c,v 11.65 2001/01/18 14:33:22 bostic Exp $";
+static const char revid[] = "$Id: bt_recno.c,v 11.106 2002/08/16 04:56:30 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <limits.h>
+#include <stdio.h>
#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "db_ext.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "lock_ext.h"
-#include "qam.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
static int __ram_add __P((DBC *, db_recno_t *, DBT *, u_int32_t, u_int32_t));
-static int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
-static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __ram_source __P((DB *));
static int __ram_sread __P((DBC *, db_recno_t));
static int __ram_update __P((DBC *, db_recno_t, int));
@@ -90,17 +85,32 @@ static int __ram_update __P((DBC *, db_recno_t, int));
* Do we need to log the current cursor adjustment?
*/
#define CURADJ_LOG(dbc) \
- (DB_LOGGING((dbc)) && (dbc)->txn != NULL && (dbc)->txn->parent != NULL)
+ (DBC_LOGGING((dbc)) && (dbc)->txn != NULL && (dbc)->txn->parent != NULL)
+
+/*
+ * After a search, copy the found page into the cursor, discarding any
+ * currently held lock.
+ */
+#define STACK_TO_CURSOR(cp) { \
+ (cp)->page = (cp)->csp->page; \
+ (cp)->pgno = (cp)->csp->page->pgno; \
+ (cp)->indx = (cp)->csp->indx; \
+ (void)__TLPUT(dbc, (cp)->lock); \
+ (cp)->lock = (cp)->csp->lock; \
+ (cp)->lock_mode = (cp)->csp->lock_mode; \
+}
/*
* __ram_open --
* Recno open function.
*
- * PUBLIC: int __ram_open __P((DB *, const char *, db_pgno_t, u_int32_t));
+ * PUBLIC: int __ram_open __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, db_pgno_t, u_int32_t));
*/
int
-__ram_open(dbp, name, base_pgno, flags)
+__ram_open(dbp, txn, name, base_pgno, flags)
DB *dbp;
+ DB_TXN *txn;
const char *name;
db_pgno_t base_pgno;
u_int32_t flags;
@@ -109,15 +119,14 @@ __ram_open(dbp, name, base_pgno, flags)
DBC *dbc;
int ret, t_ret;
+ COMPQUIET(name, NULL);
t = dbp->bt_internal;
/* Initialize the remaining fields/methods of the DB. */
- dbp->del = __ram_delete;
- dbp->put = __ram_put;
dbp->stat = __bam_stat;
/* Start up the tree. */
- if ((ret = __bam_read_root(dbp, name, base_pgno, flags)) != 0)
+ if ((ret = __bam_read_root(dbp, txn, base_pgno, flags)) != 0)
return (ret);
/*
@@ -132,7 +141,7 @@ __ram_open(dbp, name, base_pgno, flags)
return (ret);
/* If we're snapshotting an underlying source file, do it now. */
- if (F_ISSET(dbp, DB_RE_SNAPSHOT)) {
+ if (F_ISSET(dbp, DB_AM_SNAPSHOT)) {
/* Allocate a cursor. */
if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
return (ret);
@@ -147,104 +156,38 @@ __ram_open(dbp, name, base_pgno, flags)
ret = t_ret;
}
- return (0);
-}
-
-/*
- * __ram_delete --
- * Recno db->del function.
- */
-static int
-__ram_delete(dbp, txn, key, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- u_int32_t flags;
-{
- BTREE_CURSOR *cp;
- DBC *dbc;
- db_recno_t recno;
- int ret, t_ret;
-
- PANIC_CHECK(dbp->dbenv);
-
- /* Check for invalid flags. */
- if ((ret = __db_delchk(dbp,
- key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
- return (ret);
-
- /* Acquire a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
-
- DEBUG_LWRITE(dbc, txn, "ram_delete", key, NULL, flags);
-
- /* Check the user's record number and fill in as necessary. */
- if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0)
- goto err;
-
- /* Do the delete. */
- cp = (BTREE_CURSOR *)dbc->internal;
- cp->recno = recno;
-
- ret = __ram_c_del(dbc);
-
- /* Release the cursor. */
-err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
-
return (ret);
}
/*
- * __ram_put --
- * Recno db->put function.
+ * __ram_append --
+ * Recno append function.
+ *
+ * PUBLIC: int __ram_append __P((DBC *, DBT *, DBT *));
*/
-static int
-__ram_put(dbp, txn, key, data, flags)
- DB *dbp;
- DB_TXN *txn;
+int
+__ram_append(dbc, key, data)
+ DBC *dbc;
DBT *key, *data;
- u_int32_t flags;
{
- DBC *dbc;
- db_recno_t recno;
- int ret, t_ret;
-
- PANIC_CHECK(dbp->dbenv);
-
- /* Check for invalid flags. */
- if ((ret = __db_putchk(dbp,
- key, data, flags, F_ISSET(dbp, DB_AM_RDONLY), 0)) != 0)
- return (ret);
-
- /* Allocate a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
+ BTREE_CURSOR *cp;
+ int ret;
- DEBUG_LWRITE(dbc, txn, "ram_put", key, data, flags);
+ cp = (BTREE_CURSOR *)dbc->internal;
/*
- * If we're appending to the tree, make sure we've read in all of
- * the backing source file. Otherwise, check the user's record
- * number and fill in as necessary. If we found the record or it
- * simply didn't exist, add the user's record.
+ * Make sure we've read in all of the backing source file. If
+ * we found the record or it simply didn't exist, add the
+ * user's record.
*/
- if (flags == DB_APPEND)
- ret = __ram_update(dbc, DB_MAX_RECORDS, 0);
- else
- ret = __ram_getno(dbc, key, &recno, 1);
+ ret = __ram_update(dbc, DB_MAX_RECORDS, 0);
if (ret == 0 || ret == DB_NOTFOUND)
- ret = __ram_add(dbc, &recno, data, flags, 0);
-
- /* Discard the cursor. */
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
+ ret = __ram_add(dbc, &cp->recno, data, DB_APPEND, 0);
- /* Return the record number if we're appending to the tree. */
- if (ret == 0 && flags == DB_APPEND)
- ret = __db_retcopy(dbp, key, &recno, sizeof(recno),
- &dbc->rkey.data, &dbc->rkey.ulen);
+ /* Return the record number. */
+ if (ret == 0)
+ ret = __db_retcopy(dbc->dbp->dbenv, key, &cp->recno,
+ sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen);
return (ret);
}
@@ -295,9 +238,9 @@ __ram_c_del(dbc)
goto err;
}
stack = 1;
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
+
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
/*
* If re-numbering records, the on-page deleted flag can only mean
@@ -310,7 +253,7 @@ __ram_c_del(dbc)
* delete records they never created, the latter is an error because
* if the record was "deleted", we could never have found it.
*/
- if (B_DISSET(GET_BKEYDATA(cp->page, cp->indx)->type)) {
+ if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type)) {
ret = DB_KEYEMPTY;
goto err;
}
@@ -321,9 +264,8 @@ __ram_c_del(dbc)
goto err;
__bam_adjust(dbc, -1);
if (__ram_ca(dbc, CA_DELETE) > 0 &&
- CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_DELETE,
- cp->root, cp->recno, cp->order)) != 0)
+ CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp, dbc->txn,
+ &lsn, 0, CA_DELETE, cp->root, cp->recno, cp->order)) != 0)
goto err;
/*
@@ -346,15 +288,15 @@ __ram_c_del(dbc)
* going to be emptied by removing the single reference
* to the emptied page (or one of its parents).
*/
- for (epg = cp->sp; epg <= cp->csp; ++epg)
- if (NUM_ENT(epg->page) <= 1)
+ for (epg = cp->csp; epg >= cp->sp; --epg)
+ if (NUM_ENT(epg->page) > 1)
break;
/*
* We want to delete a single item out of the last page
- * that we're not deleting, back up to that page.
+ * that we're not deleting.
*/
- ret = __bam_dpages(dbc, --epg);
+ ret = __bam_dpages(dbc, epg);
/*
* Regardless of the return from __bam_dpages, it will
@@ -412,6 +354,7 @@ __ram_c_get(dbc, key, data, flags, pgnop)
dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
+ LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
retry: switch (flags) {
case DB_CURRENT:
/*
@@ -504,6 +447,7 @@ retry: switch (flags) {
goto err;
/* NOTREACHED */
case DB_GET_BOTH:
+ case DB_GET_BOTH_RANGE:
/*
* If we're searching a set of off-page dups, we start
* a new linear search from the first record. Otherwise,
@@ -531,6 +475,8 @@ retry: switch (flags) {
* read from the backing source file. Do it now for DB_CURRENT (if
* the current record was deleted we may need more records from the
* backing file for a DB_CURRENT operation), DB_FIRST and DB_NEXT.
+ * (We don't have to test for flags == DB_FIRST, because the switch
+ * statement above re-set flags to DB_NEXT in that case.)
*/
if ((flags == DB_NEXT || flags == DB_CURRENT) && ((ret =
__ram_update(dbc, cp->recno, 0)) != 0) && ret != DB_NOTFOUND)
@@ -547,16 +493,8 @@ retry: switch (flags) {
goto err;
}
- /*
- * Copy the page into the cursor, discarding any lock we
- * are currently holding.
- */
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
- (void)__TLPUT(dbc, cp->lock);
- cp->lock = cp->csp->lock;
- cp->lock_mode = cp->csp->lock_mode;
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
/*
* If re-numbering records, the on-page deleted flag means this
@@ -567,21 +505,34 @@ retry: switch (flags) {
* walking through off-page duplicates, and fail if they were
* requested explicitly by the application.
*/
- if (B_DISSET(GET_BKEYDATA(cp->page, cp->indx)->type))
+ if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type))
switch (flags) {
case DB_NEXT:
case DB_PREV:
(void)__bam_stkrel(dbc, STK_CLRDBC);
goto retry;
case DB_GET_BOTH:
- (void)__bam_stkrel(dbc, STK_CLRDBC);
- continue;
+ case DB_GET_BOTH_RANGE:
+ /*
+ * If we're an OPD tree, we don't care about
+ * matching a record number on a DB_GET_BOTH
+ * -- everything belongs to the same tree. A
+ * normal recno should give up and return
+ * DB_NOTFOUND if the matching recno is deleted.
+ */
+ if (F_ISSET(dbc, DBC_OPD)) {
+ (void)__bam_stkrel(dbc, STK_CLRDBC);
+ continue;
+ }
+ ret = DB_NOTFOUND;
+ goto err;
default:
ret = DB_KEYEMPTY;
goto err;
}
- if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC) {
+ if (flags == DB_GET_BOTH ||
+ flags == DB_GET_BOTHC || flags == DB_GET_BOTH_RANGE) {
if ((ret = __bam_cmp(dbp, data,
cp->page, cp->indx, __bam_defcmp, &cmp)) != 0)
return (ret);
@@ -598,10 +549,11 @@ retry: switch (flags) {
/* Return the key if the user didn't give us one. */
if (!F_ISSET(dbc, DBC_OPD)) {
- if (flags != DB_SET && flags != DB_SET_RANGE)
- ret = __db_retcopy(dbp,
- key, &cp->recno, sizeof(cp->recno),
- &dbc->rkey.data, &dbc->rkey.ulen);
+ if (flags != DB_GET_BOTH && flags != DB_GET_BOTH_RANGE &&
+ flags != DB_SET && flags != DB_SET_RANGE)
+ ret = __db_retcopy(dbp->dbenv,
+ key, &cp->recno, sizeof(cp->recno),
+ &dbc->rkey->data, &dbc->rkey->ulen);
F_SET(key, DB_DBT_ISSET);
}
@@ -637,23 +589,43 @@ __ram_c_put(dbc, key, data, flags, pgnop)
cp = (BTREE_CURSOR *)dbc->internal;
/*
- * DB_KEYFIRST and DB_KEYLAST will only be set if we're dealing with
- * an off-page duplicate tree, they can't be specified at user level.
- * Translate them into something else.
+ * DB_KEYFIRST and DB_KEYLAST mean different things if they're
+ * used in an off-page duplicate tree. If we're an off-page
+ * duplicate tree, they really mean "put at the beginning of the
+ * tree" and "put at the end of the tree" respectively, so translate
+ * them to something else.
*/
- switch (flags) {
- case DB_KEYFIRST:
- cp->recno = 1;
- flags = DB_BEFORE;
- break;
- case DB_KEYLAST:
- if ((ret = __ram_add(dbc, &cp->recno, data, DB_APPEND, 0)) != 0)
- return (ret);
- if (CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_ICURRENT,
- cp->root, cp->recno, cp->order)))
- return (ret);
- return (0);
+ if (F_ISSET(dbc, DBC_OPD))
+ switch (flags) {
+ case DB_KEYFIRST:
+ cp->recno = 1;
+ flags = DB_BEFORE;
+ break;
+ case DB_KEYLAST:
+ if ((ret = __ram_add(dbc,
+ &cp->recno, data, DB_APPEND, 0)) != 0)
+ return (ret);
+ if (CURADJ_LOG(dbc) &&
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0,
+ CA_ICURRENT, cp->root, cp->recno, cp->order)))
+ return (ret);
+ return (0);
+ }
+
+ /*
+ * Handle normal DB_KEYFIRST/DB_KEYLAST; for a recno, which has
+ * no duplicates, these are identical and mean "put the given
+ * datum at the given recno".
+ *
+ * Note that the code here used to be in __ram_put; now, we
+ * go through the access-method-common __db_put function, which
+ * handles DB_NOOVERWRITE, so we and __ram_add don't have to.
+ */
+ if (flags == DB_KEYFIRST || flags == DB_KEYLAST) {
+ ret = __ram_getno(dbc, key, &cp->recno, 1);
+ if (ret == 0 || ret == DB_NOTFOUND)
+ ret = __ram_add(dbc, &cp->recno, data, 0, 0);
+ return (ret);
}
/*
@@ -677,9 +649,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
*/
DB_ASSERT(exact || CD_ISSET(cp));
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
ret = __bam_iitem(dbc, key, data, iiflags, 0);
t_ret = __bam_stkrel(dbc, STK_CLRDBC);
@@ -688,7 +659,7 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
ret = t_ret;
else if (ret == DB_NEEDSPLIT) {
arg = &cp->recno;
- if ((ret = __bam_split(dbc, arg)) != 0)
+ if ((ret = __bam_split(dbc, arg, NULL)) != 0)
goto err;
goto split;
}
@@ -709,8 +680,7 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
/* Only log if __ram_ca found any relevant cursors. */
if (nc > 0 && CURADJ_LOG(dbc) &&
- (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_IAFTER,
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, CA_IAFTER,
cp->root, cp->recno, cp->order)) != 0)
goto err;
break;
@@ -720,8 +690,7 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
/* Only log if __ram_ca found any relevant cursors. */
if (nc > 0 && CURADJ_LOG(dbc) &&
- (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_IBEFORE,
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, CA_IBEFORE,
cp->root, cp->recno, cp->order)) != 0)
goto err;
break;
@@ -734,8 +703,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
* Only log if __ram_ca found any relevant cursors.
*/
if (CD_ISSET(cp) && __ram_ca(dbc, CA_ICURRENT) > 0 &&
- CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(
- dbp->dbenv, dbc->txn, &lsn, 0, dbp->log_fileid,
+ CURADJ_LOG(dbc) &&
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0,
CA_ICURRENT, cp->root, cp->recno, cp->order)) != 0)
goto err;
break;
@@ -743,8 +712,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
/* Return the key if we've created a new record. */
if (!F_ISSET(dbc, DBC_OPD) && (flags == DB_AFTER || flags == DB_BEFORE))
- ret = __db_retcopy(dbp, key, &cp->recno,
- sizeof(cp->recno), &dbc->rkey.data, &dbc->rkey.ulen);
+ ret = __db_retcopy(dbp->dbenv, key, &cp->recno,
+ sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen);
/* The cursor was reset, no further delete adjustment is necessary. */
err: CD_CLR(cp);
@@ -940,13 +909,12 @@ __ram_update(dbc, recno, can_create)
int can_create;
{
BTREE *t;
- BTREE_CURSOR *cp;
DB *dbp;
+ DBT *rdata;
db_recno_t nrecs;
int ret;
dbp = dbc->dbp;
- cp = (BTREE_CURSOR *)dbc->internal;
t = dbp->bt_internal;
/*
@@ -976,27 +944,13 @@ __ram_update(dbc, recno, can_create)
if (!can_create || recno <= nrecs + 1)
return (0);
- dbc->rdata.dlen = 0;
- dbc->rdata.doff = 0;
- dbc->rdata.flags = 0;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
- if (dbc->rdata.ulen < t->re_len) {
- if ((ret = __os_realloc(dbp->dbenv,
- t->re_len, NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
- return (ret);
- }
- dbc->rdata.ulen = t->re_len;
- }
- dbc->rdata.size = t->re_len;
- memset(dbc->rdata.data, t->re_pad, t->re_len);
- } else
- dbc->rdata.size = 0;
+ rdata = &dbc->my_rdata;
+ rdata->flags = 0;
+ rdata->size = 0;
while (recno > ++nrecs)
if ((ret = __ram_add(dbc,
- &nrecs, &dbc->rdata, 0, BI_DELETED)) != 0)
+ &nrecs, rdata, 0, BI_DELETED)) != 0)
return (ret);
return (0);
}
@@ -1017,9 +971,9 @@ __ram_source(dbp)
/* Find the real name, and swap out the one we had before. */
if ((ret = __db_appname(dbp->dbenv,
- DB_APP_DATA, NULL, t->re_source, 0, NULL, &source)) != 0)
+ DB_APP_DATA, t->re_source, 0, NULL, &source)) != 0)
return (ret);
- __os_freestr(t->re_source);
+ __os_free(dbp->dbenv, t->re_source);
t->re_source = source;
/*
@@ -1060,6 +1014,7 @@ __ram_writeback(dbp)
t = dbp->bt_internal;
dbenv = dbp->dbenv;
fp = NULL;
+ pad = NULL;
/* If the file wasn't modified, we're done. */
if (!t->re_modified)
@@ -1119,40 +1074,45 @@ __ram_writeback(dbp)
/*
* We step through the records, writing each one out. Use the record
* number and the dbp->get() function, instead of a cursor, so we find
- * and write out "deleted" or non-existent records.
+ * and write out "deleted" or non-existent records. The DB handle may
+ * be threaded, so allocate memory as we go.
*/
memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
key.size = sizeof(db_recno_t);
key.data = &keyno;
+ memset(&data, 0, sizeof(data));
+ F_SET(&data, DB_DBT_REALLOC);
/*
* We'll need the delimiter if we're doing variable-length records,
* and the pad character if we're doing fixed-length records.
*/
delim = t->re_delim;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
- if ((ret = __os_malloc(dbenv, t->re_len, NULL, &pad)) != 0)
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
+ if ((ret = __os_malloc(dbenv, t->re_len, &pad)) != 0)
goto err;
memset(pad, t->re_pad, t->re_len);
- } else
- COMPQUIET(pad, NULL);
+ }
for (keyno = 1;; ++keyno) {
switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
case 0:
- if (fwrite(data.data, 1, data.size, fp) != data.size)
+ if (data.size != 0 && (u_int32_t)fwrite(
+ data.data, 1, data.size, fp) != data.size)
goto write_err;
break;
case DB_KEYEMPTY:
- if (F_ISSET(dbp, DB_RE_FIXEDLEN) &&
- fwrite(pad, 1, t->re_len, fp) != t->re_len)
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
+ (u_int32_t)fwrite(pad, 1, t->re_len, fp) !=
+ t->re_len)
goto write_err;
break;
case DB_NOTFOUND:
ret = 0;
goto done;
+ default:
+ goto err;
}
- if (!F_ISSET(dbp, DB_RE_FIXEDLEN) &&
+ if (!F_ISSET(dbp, DB_AM_FIXEDLEN) &&
fwrite(&delim, 1, 1, fp) != 1) {
write_err: ret = errno;
__db_err(dbp->dbenv,
@@ -1174,6 +1134,12 @@ done: /* Close the file descriptor. */
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
+ /* Discard memory allocated to hold the data items. */
+ if (data.data != NULL)
+ __os_ufree(dbenv, data.data);
+ if (pad != NULL)
+ __os_free(dbenv, pad);
+
if (ret == 0)
t->re_modified = 0;
@@ -1191,7 +1157,7 @@ __ram_sread(dbc, top)
{
BTREE *t;
DB *dbp;
- DBT data;
+ DBT data, *rdata;
db_recno_t recno;
size_t len;
int ch, ret, was_modified;
@@ -1203,45 +1169,56 @@ __ram_sread(dbc, top)
if ((ret = __bam_nrecs(dbc, &recno)) != 0)
return (ret);
- /* Use the record data return memory, it's only a short-term use. */
- len = F_ISSET(dbp, DB_RE_FIXEDLEN) ? t->re_len : 256;
- if (dbc->rdata.ulen < len) {
+ /*
+ * Use the record key return memory, it's only a short-term use.
+ * The record data return memory is used by __bam_iitem, which
+ * we'll indirectly call, so use the key so as not to collide.
+ */
+ len = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : 256;
+ rdata = &dbc->my_rkey;
+ if (rdata->ulen < len) {
if ((ret = __os_realloc(
- dbp->dbenv, len, NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
+ dbp->dbenv, len, &rdata->data)) != 0) {
+ rdata->ulen = 0;
+ rdata->data = NULL;
return (ret);
}
- dbc->rdata.ulen = len;
+ rdata->ulen = (u_int32_t)len;
}
memset(&data, 0, sizeof(data));
while (recno < top) {
- data.data = dbc->rdata.data;
+ data.data = rdata->data;
data.size = 0;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN))
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN))
for (len = t->re_len; len > 0; --len) {
- if ((ch = getc(t->re_fp)) == EOF)
- goto eof;
+ if ((ch = getc(t->re_fp)) == EOF) {
+ if (data.size == 0)
+ goto eof;
+ break;
+ }
((u_int8_t *)data.data)[data.size++] = ch;
}
else
for (;;) {
- if ((ch = getc(t->re_fp)) == EOF)
- goto eof;
+ if ((ch = getc(t->re_fp)) == EOF) {
+ if (data.size == 0)
+ goto eof;
+ break;
+ }
if (ch == t->re_delim)
break;
((u_int8_t *)data.data)[data.size++] = ch;
- if (data.size == dbc->rdata.ulen) {
+ if (data.size == rdata->ulen) {
if ((ret = __os_realloc(dbp->dbenv,
- dbc->rdata.ulen *= 2,
- NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
+ rdata->ulen *= 2,
+ &rdata->data)) != 0) {
+ rdata->ulen = 0;
+ rdata->data = NULL;
return (ret);
} else
- data.data = dbc->rdata.data;
+ data.data = rdata->data;
}
}
@@ -1281,7 +1258,6 @@ __ram_add(dbc, recnop, data, flags, bi_flags)
DBT *data;
u_int32_t flags, bi_flags;
{
- BKEYDATA *bk;
BTREE_CURSOR *cp;
int exact, ret, stack;
@@ -1292,9 +1268,9 @@ retry: /* Find the slot for insertion. */
S_INSERT | (flags == DB_APPEND ? S_APPEND : 0), 1, &exact)) != 0)
return (ret);
stack = 1;
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
+
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
/*
* The application may modify the data based on the selected record
@@ -1305,24 +1281,6 @@ retry: /* Find the slot for insertion. */
goto err;
/*
- * If re-numbering records, the on-page deleted flag means this record
- * was implicitly created. If not re-numbering records, the on-page
- * deleted flag means this record was implicitly created, or, it was
- * deleted at some time.
- *
- * If DB_NOOVERWRITE is set and the item already exists in the tree,
- * return an error unless the item was either marked for deletion or
- * only implicitly created.
- */
- if (exact) {
- bk = GET_BKEYDATA(cp->page, cp->indx);
- if (!B_DISSET(bk->type) && flags == DB_NOOVERWRITE) {
- ret = DB_KEYEXIST;
- goto err;
- }
- }
-
- /*
* Select the arguments for __bam_iitem() and do the insert. If the
* key is an exact match, or we're replacing the data item with a
* new data item, replace the current item. If the key isn't an exact
@@ -1353,7 +1311,7 @@ retry: /* Find the slot for insertion. */
(void)__bam_stkrel(dbc, STK_CLRDBC);
stack = 0;
- if ((ret = __bam_split(dbc, recnop)) != 0)
+ if ((ret = __bam_split(dbc, recnop, NULL)) != 0)
goto err;
goto retry;
diff --git a/bdb/btree/bt_rsearch.c b/bdb/btree/bt_rsearch.c
index 7102cd715aa..a75181b44e2 100644
--- a/bdb/btree/bt_rsearch.c
+++ b/bdb/btree/bt_rsearch.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -40,7 +40,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_rsearch.c,v 11.21 2000/03/28 21:50:04 ubell Exp $";
+static const char revid[] = "$Id: bt_rsearch.c,v 11.34 2002/07/03 19:03:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -48,10 +48,10 @@ static const char revid[] = "$Id: bt_rsearch.c,v 11.21 2000/03/28 21:50:04 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "db_shash.h"
-#include "lock.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
/*
* __bam_rsearch --
@@ -70,6 +70,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
PAGE *h;
RINTERNAL *ri;
db_indx_t adjust, deloffset, indx, top;
@@ -79,6 +80,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
int ret, stack;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
BT_STK_CLR(cp);
@@ -99,11 +101,11 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* Retrieve the root page.
*/
pg = cp->root;
- stack = LF_ISSET(S_STACK);
+ stack = LF_ISSET(S_STACK) ? 1 : 0;
lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
@@ -120,12 +122,12 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
if (!stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
(void)__LPUT(dbc, lock);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
@@ -164,7 +166,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* eliminate any concurrency. A possible fix
* would be to lock the last leaf page instead.
*/
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
(void)__TLPUT(dbc, lock);
return (DB_NOTFOUND);
}
@@ -202,8 +204,8 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
goto err;
}
}
- if (!B_DISSET(
- GET_BKEYDATA(h, indx + deloffset)->type) &&
+ if (!B_DISSET(GET_BKEYDATA(dbp, h,
+ indx + deloffset)->type) &&
++t_recno == recno)
break;
}
@@ -216,7 +218,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
return (0);
case P_IBTREE:
for (indx = 0, top = NUM_ENT(h);;) {
- bi = GET_BINTERNAL(h, indx);
+ bi = GET_BINTERNAL(dbp, h, indx);
if (++indx == top || total + bi->nrecs >= recno)
break;
total += bi->nrecs;
@@ -235,7 +237,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
return (0);
case P_IRECNO:
for (indx = 0, top = NUM_ENT(h);;) {
- ri = GET_RINTERNAL(h, indx);
+ ri = GET_RINTERNAL(dbp, h, indx);
if (++indx == top || total + ri->nrecs >= recno)
break;
total += ri->nrecs;
@@ -243,7 +245,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
pg = ri->pgno;
break;
default:
- return (__db_pgfmt(dbp, h->pgno));
+ return (__db_pgfmt(dbp->dbenv, h->pgno));
}
--indx;
@@ -276,12 +278,12 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
(h->level - 1) == LEAFLEVEL)
stack = 1;
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
lock_mode = stack &&
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc,
- LCK_COUPLE, pg, lock_mode, 0, &lock)) != 0) {
+ LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
* If we fail, discard the lock we held. This
* is OK because this only happens when we are
@@ -292,7 +294,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
}
}
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0)
goto err;
}
/* NOTREACHED */
@@ -315,12 +317,14 @@ __bam_adjust(dbc, adjust)
{
BTREE_CURSOR *cp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
EPG *epg;
PAGE *h;
db_pgno_t root_pgno;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
root_pgno = cp->root;
@@ -328,22 +332,27 @@ __bam_adjust(dbc, adjust)
for (epg = cp->sp; epg <= cp->csp; ++epg) {
h = epg->page;
if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO) {
- if (DB_LOGGING(dbc) &&
- (ret = __bam_cadjust_log(dbp->dbenv,
- dbc->txn, &LSN(h), 0, dbp->log_fileid,
- PGNO(h), &LSN(h), (u_int32_t)epg->indx, adjust,
- PGNO(h) == root_pgno ? CAD_UPDATEROOT : 0)) != 0)
- return (ret);
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __bam_cadjust_log(dbp, dbc->txn,
+ &LSN(h), 0, PGNO(h), &LSN(h),
+ (u_int32_t)epg->indx, adjust,
+ PGNO(h) == root_pgno ?
+ CAD_UPDATEROOT : 0)) != 0)
+ return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(h));
if (TYPE(h) == P_IBTREE)
- GET_BINTERNAL(h, epg->indx)->nrecs += adjust;
+ GET_BINTERNAL(dbp, h, epg->indx)->nrecs +=
+ adjust;
else
- GET_RINTERNAL(h, epg->indx)->nrecs += adjust;
+ GET_RINTERNAL(dbp, h, epg->indx)->nrecs +=
+ adjust;
if (PGNO(h) == root_pgno)
RE_NREC_ADJ(h, adjust);
- if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
}
}
@@ -363,21 +372,23 @@ __bam_nrecs(dbc, rep)
{
DB *dbp;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
pgno = dbc->internal->root;
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
*rep = RE_NREC(h);
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
(void)__TLPUT(dbc, lock);
return (0);
@@ -387,10 +398,11 @@ __bam_nrecs(dbc, rep)
* __bam_total --
* Return the number of records below a page.
*
- * PUBLIC: db_recno_t __bam_total __P((PAGE *));
+ * PUBLIC: db_recno_t __bam_total __P((DB *, PAGE *));
*/
db_recno_t
-__bam_total(h)
+__bam_total(dbp, h)
+ DB *dbp;
PAGE *h;
{
db_recno_t nrecs;
@@ -403,25 +415,26 @@ __bam_total(h)
case P_LBTREE:
/* Check for logically deleted records. */
for (indx = 0; indx < top; indx += P_INDX)
- if (!B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type))
+ if (!B_DISSET(
+ GET_BKEYDATA(dbp, h, indx + O_INDX)->type))
++nrecs;
break;
case P_LDUP:
/* Check for logically deleted records. */
for (indx = 0; indx < top; indx += O_INDX)
- if (!B_DISSET(GET_BKEYDATA(h, indx)->type))
+ if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type))
++nrecs;
break;
case P_IBTREE:
for (indx = 0; indx < top; indx += O_INDX)
- nrecs += GET_BINTERNAL(h, indx)->nrecs;
+ nrecs += GET_BINTERNAL(dbp, h, indx)->nrecs;
break;
case P_LRECNO:
nrecs = NUM_ENT(h);
break;
case P_IRECNO:
for (indx = 0; indx < top; indx += O_INDX)
- nrecs += GET_RINTERNAL(h, indx)->nrecs;
+ nrecs += GET_RINTERNAL(dbp, h, indx)->nrecs;
break;
}
diff --git a/bdb/btree/bt_search.c b/bdb/btree/bt_search.c
index d822198f243..92b2106311d 100644
--- a/bdb/btree/bt_search.c
+++ b/bdb/btree/bt_search.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_search.c,v 11.32 2001/01/17 20:19:46 bostic Exp $";
+static const char revid[] = "$Id: bt_search.c,v 11.43 2002/07/03 19:03:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -53,21 +53,22 @@ static const char revid[] = "$Id: bt_search.c,v 11.32 2001/01/17 20:19:46 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "lock.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
/*
* __bam_search --
* Search a btree for a key.
*
- * PUBLIC: int __bam_search __P((DBC *,
+ * PUBLIC: int __bam_search __P((DBC *, db_pgno_t,
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
*/
int
-__bam_search(dbc, key, flags, stop, recnop, exactp)
+__bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp)
DBC *dbc;
+ db_pgno_t root_pgno;
const DBT *key;
u_int32_t flags;
int stop, *exactp;
@@ -77,8 +78,9 @@ __bam_search(dbc, key, flags, stop, recnop, exactp)
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
PAGE *h;
- db_indx_t base, i, indx, lim;
+ db_indx_t base, i, indx, *inp, lim;
db_lockmode_t lock_mode;
db_pgno_t pg;
db_recno_t recno;
@@ -86,6 +88,7 @@ __bam_search(dbc, key, flags, stop, recnop, exactp)
int (*func) __P((DB *, const DBT *, const DBT *));
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
t = dbp->bt_internal;
recno = 0;
@@ -109,12 +112,12 @@ __bam_search(dbc, key, flags, stop, recnop, exactp)
* Retrieve the root page.
*/
try_again:
- pg = cp->root;
+ pg = root_pgno == PGNO_INVALID ? cp->root : root_pgno;
stack = LF_ISSET(S_STACK) && F_ISSET(cp, C_RECNUM);
lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
@@ -131,21 +134,21 @@ try_again:
if (!stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
(void)__LPUT(dbc, lock);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
- if (!((LF_ISSET(S_PARENT)
- && (u_int8_t)(stop + 1) >= h->level) ||
+ if (!((LF_ISSET(S_PARENT) &&
+ (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
/* Someone else split the root, start over. */
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
(void)__LPUT(dbc, lock);
goto try_again;
}
@@ -158,6 +161,7 @@ try_again:
t->bt_compare;
for (;;) {
+ inp = P_INP(dbp, h);
/*
* Do a binary search on the current page. If we're searching
* a Btree leaf page, we have to walk the indices in groups of
@@ -199,7 +203,7 @@ try_again:
if (LF_ISSET(S_STK_ONLY)) {
BT_STK_NUM(dbp->dbenv, cp, h, base, ret);
__LPUT(dbc, lock);
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (ret);
}
@@ -232,21 +236,21 @@ try_again:
*/
next: if (recnop != NULL)
for (i = 0; i < indx; ++i)
- recno += GET_BINTERNAL(h, i)->nrecs;
+ recno += GET_BINTERNAL(dbp, h, i)->nrecs;
- pg = GET_BINTERNAL(h, indx)->pgno;
+ pg = GET_BINTERNAL(dbp, h, indx)->pgno;
if (LF_ISSET(S_STK_ONLY)) {
if (stop == h->level) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
__LPUT(dbc, lock);
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (ret);
}
BT_STK_NUMPUSH(dbp->dbenv, cp, h, indx, ret);
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
if ((ret = __db_lget(dbc,
- LCK_COUPLE, pg, lock_mode, 0, &lock)) != 0) {
+ LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
* Discard our lock and return on failure. This
* is OK because it only happens when descending
@@ -284,12 +288,12 @@ next: if (recnop != NULL)
(h->level - 1) == LEAFLEVEL)
stack = 1;
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
lock_mode = stack &&
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc,
- LCK_COUPLE, pg, lock_mode, 0, &lock)) != 0) {
+ LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
* If we fail, discard the lock we held. This
* is OK because this only happens when we are
@@ -299,7 +303,7 @@ next: if (recnop != NULL)
goto err;
}
}
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0)
goto err;
}
/* NOTREACHED */
@@ -327,11 +331,11 @@ found: *exactp = 1;
if (TYPE(h) == P_LBTREE) {
if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
- h->inp[indx] == h->inp[indx + P_INDX])
+ inp[indx] == inp[indx + P_INDX])
indx += P_INDX;
else
while (indx > 0 &&
- h->inp[indx] == h->inp[indx - P_INDX])
+ inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
}
@@ -344,29 +348,29 @@ found: *exactp = 1;
if (LF_ISSET(S_DELNO)) {
deloffset = TYPE(h) == P_LBTREE ? O_INDX : 0;
if (LF_ISSET(S_DUPLAST))
- while (B_DISSET(GET_BKEYDATA(
+ while (B_DISSET(GET_BKEYDATA(dbp,
h, indx + deloffset)->type) && indx > 0 &&
- h->inp[indx] == h->inp[indx - adjust])
+ inp[indx] == inp[indx - adjust])
indx -= adjust;
else
- while (B_DISSET(GET_BKEYDATA(
+ while (B_DISSET(GET_BKEYDATA(dbp,
h, indx + deloffset)->type) &&
indx < (db_indx_t)(NUM_ENT(h) - adjust) &&
- h->inp[indx] == h->inp[indx + adjust])
+ inp[indx] == inp[indx + adjust])
indx += adjust;
/*
* If we weren't able to find a non-deleted duplicate, return
* DB_NOTFOUND.
*/
- if (B_DISSET(GET_BKEYDATA(h, indx + deloffset)->type))
+ if (B_DISSET(GET_BKEYDATA(dbp, h, indx + deloffset)->type))
goto notfound;
}
if (LF_ISSET(S_STK_ONLY)) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
__LPUT(dbc, lock);
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
} else {
BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
@@ -376,7 +380,7 @@ found: *exactp = 1;
notfound:
/* Keep the page locked for serializability. */
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
(void)__TLPUT(dbc, lock);
ret = DB_NOTFOUND;
@@ -398,10 +402,12 @@ __bam_stkrel(dbc, flags)
{
BTREE_CURSOR *cp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
EPG *epg;
int ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
@@ -414,10 +420,10 @@ __bam_stkrel(dbc, flags)
if (epg->page != NULL) {
if (LF_ISSET(STK_CLRDBC) && cp->page == epg->page) {
cp->page = NULL;
- cp->lock.off = LOCK_INVALID;
+ LOCK_INIT(cp->lock);
}
- if ((t_ret = memp_fput(
- dbp->mpf, epg->page, 0)) != 0 && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, epg->page, 0)) != 0 && ret == 0)
ret = t_ret;
/*
* XXX
@@ -428,12 +434,10 @@ __bam_stkrel(dbc, flags)
*/
epg->page = NULL;
}
- if (epg->lock.off != LOCK_INVALID) {
- if (LF_ISSET(STK_NOLOCK))
- (void)__LPUT(dbc, epg->lock);
- else
- (void)__TLPUT(dbc, epg->lock);
- }
+ if (LF_ISSET(STK_NOLOCK))
+ (void)__LPUT(dbc, epg->lock);
+ else
+ (void)__TLPUT(dbc, epg->lock);
}
/* Clear the stack, all pages have been released. */
@@ -463,7 +467,7 @@ __bam_stkgrow(dbenv, cp)
return (ret);
memcpy(p, cp->sp, entries * sizeof(EPG));
if (cp->sp != cp->stack)
- __os_free(cp->sp, entries * sizeof(EPG));
+ __os_free(dbenv, cp->sp);
cp->sp = p;
cp->csp = p + entries;
cp->esp = p + entries * 2;
diff --git a/bdb/btree/bt_split.c b/bdb/btree/bt_split.c
index f76337b1944..f3302a6905f 100644
--- a/bdb/btree/bt_split.c
+++ b/bdb/btree/bt_split.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -40,7 +40,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_split.c,v 11.31 2000/12/22 19:08:27 bostic Exp $";
+static const char revid[] = "$Id: bt_split.c,v 11.58 2002/07/03 19:03:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -51,10 +51,10 @@ static const char revid[] = "$Id: bt_split.c,v 11.31 2000/12/22 19:08:27 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/btree.h"
static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
static int __bam_page __P((DBC *, EPG *, EPG *));
@@ -67,21 +67,19 @@ static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *));
* __bam_split --
* Split a page.
*
- * PUBLIC: int __bam_split __P((DBC *, void *));
+ * PUBLIC: int __bam_split __P((DBC *, void *, db_pgno_t *));
*/
int
-__bam_split(dbc, arg)
+__bam_split(dbc, arg, root_pgnop)
DBC *dbc;
void *arg;
+ db_pgno_t *root_pgnop;
{
- BTREE *t;
BTREE_CURSOR *cp;
- DB *dbp;
enum { UP, DOWN } dir;
db_pgno_t root_pgno;
int exact, level, ret;
- dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
root_pgno = cp->root;
@@ -112,17 +110,20 @@ __bam_split(dbc, arg)
* split. This would be an easy change for this code, but I have no
* numbers that indicate it's worthwhile.
*/
- t = dbp->bt_internal;
for (dir = UP, level = LEAFLEVEL;; dir == UP ? ++level : --level) {
/*
* Acquire a page and its parent, locked.
*/
if ((ret = (dbc->dbtype == DB_BTREE ?
- __bam_search(dbc, arg, S_WRPAIR, level, NULL, &exact) :
+ __bam_search(dbc, PGNO_INVALID,
+ arg, S_WRPAIR, level, NULL, &exact) :
__bam_rsearch(dbc,
(db_recno_t *)arg, S_WRPAIR, level, &exact))) != 0)
return (ret);
+ if (root_pgnop != NULL)
+ *root_pgnop = cp->csp[0].page->pgno == root_pgno ?
+ root_pgno : cp->csp[-1].page->pgno;
/*
* Split the page if it still needs it (it's possible another
* thread of control has already split the page). If we are
@@ -130,7 +131,7 @@ __bam_split(dbc, arg)
* is no longer necessary.
*/
if (2 * B_MAXSIZEONPAGE(cp->ovflsize)
- <= (db_indx_t)P_FREESPACE(cp->csp[0].page)) {
+ <= (db_indx_t)P_FREESPACE(dbc->dbp, cp->csp[0].page)) {
__bam_stkrel(dbc, STK_NOLOCK);
return (0);
}
@@ -178,12 +179,14 @@ __bam_root(dbc, cp)
DB *dbp;
DBT log_dbt;
DB_LSN log_lsn;
+ DB_MPOOLFILE *mpf;
PAGE *lp, *rp;
db_indx_t split;
u_int32_t opflags;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
/* Yeah, right. */
if (cp->page->level >= MAXBTREELEVEL) {
@@ -210,21 +213,22 @@ __bam_root(dbc, cp)
goto err;
/* Log the change. */
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
memset(&log_dbt, 0, sizeof(log_dbt));
log_dbt.data = cp->page;
log_dbt.size = dbp->pgsize;
ZERO_LSN(log_lsn);
opflags = F_ISSET(
(BTREE_CURSOR *)dbc->internal, C_RECNUM) ? SPL_NRECS : 0;
- if ((ret = __bam_split_log(dbp->dbenv, dbc->txn,
- &LSN(cp->page), 0, dbp->log_fileid, PGNO(lp), &LSN(lp),
- PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp), 0, &log_lsn,
+ if ((ret = __bam_split_log(dbp,
+ dbc->txn, &LSN(cp->page), 0, PGNO(lp), &LSN(lp), PGNO(rp),
+ &LSN(rp), (u_int32_t)NUM_ENT(lp), 0, &log_lsn,
dbc->internal->root, &log_dbt, opflags)) != 0)
goto err;
- LSN(lp) = LSN(cp->page);
- LSN(rp) = LSN(cp->page);
- }
+ } else
+ LSN_NOT_LOGGED(LSN(cp->page));
+ LSN(lp) = LSN(cp->page);
+ LSN(rp) = LSN(cp->page);
/* Clean up the new root page. */
if ((ret = (dbc->dbtype == DB_RECNO ?
@@ -238,18 +242,18 @@ __bam_root(dbc, cp)
goto err;
/* Success -- write the real pages back to the store. */
- (void)memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, cp->page, DB_MPOOL_DIRTY);
(void)__TLPUT(dbc, cp->lock);
- (void)memp_fput(dbp->mpf, lp, DB_MPOOL_DIRTY);
- (void)memp_fput(dbp->mpf, rp, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, lp, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, rp, DB_MPOOL_DIRTY);
return (0);
err: if (lp != NULL)
- (void)__db_free(dbc, lp);
+ (void)mpf->put(mpf, lp, 0);
if (rp != NULL)
- (void)__db_free(dbc, rp);
- (void)memp_fput(dbp->mpf, cp->page, 0);
+ (void)mpf->put(mpf, rp, 0);
+ (void)mpf->put(mpf, cp->page, 0);
(void)__TLPUT(dbc, cp->lock);
return (ret);
}
@@ -267,7 +271,8 @@ __bam_page(dbc, pp, cp)
DBT log_dbt;
DB_LSN log_lsn;
DB *dbp;
- DB_LOCK tplock;
+ DB_LOCK rplock, tplock;
+ DB_MPOOLFILE *mpf;
DB_LSN save_lsn;
PAGE *lp, *rp, *alloc_rp, *tp;
db_indx_t split;
@@ -275,8 +280,10 @@ __bam_page(dbc, pp, cp)
int ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
alloc_rp = lp = rp = tp = NULL;
- tplock.off = LOCK_INVALID;
+ LOCK_INIT(rplock);
+ LOCK_INIT(tplock);
ret = -1;
/*
@@ -296,7 +303,7 @@ __bam_page(dbc, pp, cp)
* up the tree badly, because we've violated the rule of always locking
* down the tree, and never up.
*/
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &rp)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &rp)) != 0)
goto err;
P_INIT(rp, dbp->pgsize, 0,
ISINTERNAL(cp->page) ? PGNO_INVALID : PGNO(cp->page),
@@ -307,7 +314,7 @@ __bam_page(dbc, pp, cp)
* Create new left page for the split, and fill in everything
* except its LSN and next-page page number.
*/
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &lp)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &lp)) != 0)
goto err;
P_INIT(lp, dbp->pgsize, PGNO(cp->page),
ISINTERNAL(cp->page) ? PGNO_INVALID : PREV_PGNO(cp->page),
@@ -351,8 +358,7 @@ __bam_page(dbc, pp, cp)
if ((ret = __db_lget(dbc,
0, NEXT_PGNO(cp->page), DB_LOCK_WRITE, 0, &tplock)) != 0)
goto err;
- if ((ret =
- memp_fget(dbp->mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
+ if ((ret = mpf->get(mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
goto err;
}
@@ -364,6 +370,15 @@ __bam_page(dbc, pp, cp)
goto err;
/*
+ * Lock the new page. We need to do this because someone
+ * could get here through bt_lpgno if this page was recently
+ * dealocated. They can't look at it before we commit.
+ */
+ if ((ret = __db_lget(dbc,
+ 0, PGNO(alloc_rp), DB_LOCK_WRITE, 0, &rplock)) != 0)
+ goto err;
+
+ /*
* Fix up the page numbers we didn't have before. We have to do this
* before calling __bam_pinsert because it may copy a page number onto
* the parent page and it takes the page number from its page argument.
@@ -376,29 +391,30 @@ __bam_page(dbc, pp, cp)
bc = (BTREE_CURSOR *)dbc->internal;
/* Log the change. */
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
memset(&log_dbt, 0, sizeof(log_dbt));
log_dbt.data = cp->page;
log_dbt.size = dbp->pgsize;
if (tp == NULL)
ZERO_LSN(log_lsn);
opflags = F_ISSET(bc, C_RECNUM) ? SPL_NRECS : 0;
- if ((ret = __bam_split_log(dbp->dbenv, dbc->txn,
- &LSN(cp->page), 0, dbp->log_fileid, PGNO(cp->page),
- &LSN(cp->page), PGNO(alloc_rp), &LSN(alloc_rp),
- (u_int32_t)NUM_ENT(lp),
+ if ((ret = __bam_split_log(dbp, dbc->txn, &LSN(cp->page), 0,
+ PGNO(cp->page), &LSN(cp->page), PGNO(alloc_rp),
+ &LSN(alloc_rp), (u_int32_t)NUM_ENT(lp),
tp == NULL ? 0 : PGNO(tp),
tp == NULL ? &log_lsn : &LSN(tp),
- bc->root, &log_dbt, opflags)) != 0)
+ PGNO_INVALID, &log_dbt, opflags)) != 0)
goto err;
- /* Update the LSNs for all involved pages. */
- LSN(alloc_rp) = LSN(cp->page);
- LSN(lp) = LSN(cp->page);
- LSN(rp) = LSN(cp->page);
- if (tp != NULL)
- LSN(tp) = LSN(cp->page);
- }
+ } else
+ LSN_NOT_LOGGED(LSN(cp->page));
+
+ /* Update the LSNs for all involved pages. */
+ LSN(alloc_rp) = LSN(cp->page);
+ LSN(lp) = LSN(cp->page);
+ LSN(rp) = LSN(cp->page);
+ if (tp != NULL)
+ LSN(tp) = LSN(cp->page);
/*
* Copy the left and right pages into place. There are two paths
@@ -411,13 +427,13 @@ __bam_page(dbc, pp, cp)
* do the copy.
*/
save_lsn = alloc_rp->lsn;
- memcpy(alloc_rp, rp, LOFFSET(rp));
+ memcpy(alloc_rp, rp, LOFFSET(dbp, rp));
memcpy((u_int8_t *)alloc_rp + HOFFSET(rp),
(u_int8_t *)rp + HOFFSET(rp), dbp->pgsize - HOFFSET(rp));
alloc_rp->lsn = save_lsn;
save_lsn = cp->page->lsn;
- memcpy(cp->page, lp, LOFFSET(lp));
+ memcpy(cp->page, lp, LOFFSET(dbp, lp));
memcpy((u_int8_t *)cp->page + HOFFSET(lp),
(u_int8_t *)lp + HOFFSET(lp), dbp->pgsize - HOFFSET(lp));
cp->page->lsn = save_lsn;
@@ -431,8 +447,8 @@ __bam_page(dbc, pp, cp)
PGNO(cp->page), PGNO(cp->page), PGNO(rp), split, 0)) != 0)
goto err;
- __os_free(lp, dbp->pgsize);
- __os_free(rp, dbp->pgsize);
+ __os_free(dbp->dbenv, lp);
+ __os_free(dbp->dbenv, rp);
/*
* Success -- write the real pages back to the store. As we never
@@ -440,45 +456,43 @@ __bam_page(dbc, pp, cp)
* releasing locks on the pages that reference it. We're finished
* modifying the page so it's not really necessary, but it's neater.
*/
- if ((t_ret =
- memp_fput(dbp->mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ if ((t_ret = mpf->put(mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
- if ((t_ret =
- memp_fput(dbp->mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ (void)__TLPUT(dbc, rplock);
+ if ((t_ret = mpf->put(mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
(void)__TLPUT(dbc, pp->lock);
- if ((t_ret =
- memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ if ((t_ret = mpf->put(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
(void)__TLPUT(dbc, cp->lock);
if (tp != NULL) {
if ((t_ret =
- memp_fput(dbp->mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ mpf->put(mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
(void)__TLPUT(dbc, tplock);
}
return (ret);
err: if (lp != NULL)
- __os_free(lp, dbp->pgsize);
+ __os_free(dbp->dbenv, lp);
if (rp != NULL)
- __os_free(rp, dbp->pgsize);
+ __os_free(dbp->dbenv, rp);
if (alloc_rp != NULL)
- (void)__db_free(dbc, alloc_rp);
-
+ (void)mpf->put(mpf, alloc_rp, 0);
if (tp != NULL)
- (void)memp_fput(dbp->mpf, tp, 0);
- if (tplock.off != LOCK_INVALID)
- /* We never updated the next page, we can release it. */
- (void)__LPUT(dbc, tplock);
+ (void)mpf->put(mpf, tp, 0);
+
+ /* We never updated the new or next pages, we can release them. */
+ (void)__LPUT(dbc, rplock);
+ (void)__LPUT(dbc, tplock);
- (void)memp_fput(dbp->mpf, pp->page, 0);
+ (void)mpf->put(mpf, pp->page, 0);
if (ret == DB_NEEDSPLIT)
(void)__LPUT(dbc, pp->lock);
else
(void)__TLPUT(dbc, pp->lock);
- (void)memp_fput(dbp->mpf, cp->page, 0);
+ (void)mpf->put(mpf, cp->page, 0);
if (ret == DB_NEEDSPLIT)
(void)__LPUT(dbc, cp->lock);
else
@@ -529,7 +543,7 @@ __bam_broot(dbc, rootp, lp, rp)
B_TSET(bi.type, B_KEYDATA, 0);
bi.pgno = lp->pgno;
if (F_ISSET(cp, C_RECNUM)) {
- bi.nrecs = __bam_total(lp);
+ bi.nrecs = __bam_total(dbp, lp);
RE_NREC_SET(rootp, bi.nrecs);
}
hdr.data = &bi;
@@ -541,13 +555,13 @@ __bam_broot(dbc, rootp, lp, rp)
switch (TYPE(rp)) {
case P_IBTREE:
/* Copy the first key of the child page onto the root page. */
- child_bi = GET_BINTERNAL(rp, 0);
+ child_bi = GET_BINTERNAL(dbp, rp, 0);
bi.len = child_bi->len;
B_TSET(bi.type, child_bi->type, 0);
bi.pgno = rp->pgno;
if (F_ISSET(cp, C_RECNUM)) {
- bi.nrecs = __bam_total(rp);
+ bi.nrecs = __bam_total(dbp, rp);
RE_NREC_ADJ(rootp, bi.nrecs);
}
hdr.data = &bi;
@@ -567,14 +581,14 @@ __bam_broot(dbc, rootp, lp, rp)
case P_LDUP:
case P_LBTREE:
/* Copy the first key of the child page onto the root page. */
- child_bk = GET_BKEYDATA(rp, 0);
+ child_bk = GET_BKEYDATA(dbp, rp, 0);
switch (B_TYPE(child_bk->type)) {
case B_KEYDATA:
bi.len = child_bk->len;
B_TSET(bi.type, child_bk->type, 0);
bi.pgno = rp->pgno;
if (F_ISSET(cp, C_RECNUM)) {
- bi.nrecs = __bam_total(rp);
+ bi.nrecs = __bam_total(dbp, rp);
RE_NREC_ADJ(rootp, bi.nrecs);
}
hdr.data = &bi;
@@ -591,7 +605,7 @@ __bam_broot(dbc, rootp, lp, rp)
B_TSET(bi.type, child_bk->type, 0);
bi.pgno = rp->pgno;
if (F_ISSET(cp, C_RECNUM)) {
- bi.nrecs = __bam_total(rp);
+ bi.nrecs = __bam_total(dbp, rp);
RE_NREC_ADJ(rootp, bi.nrecs);
}
hdr.data = &bi;
@@ -609,11 +623,11 @@ __bam_broot(dbc, rootp, lp, rp)
return (ret);
break;
default:
- return (__db_pgfmt(dbp, rp->pgno));
+ return (__db_pgfmt(dbp->dbenv, rp->pgno));
}
break;
default:
- return (__db_pgfmt(dbp, rp->pgno));
+ return (__db_pgfmt(dbp->dbenv, rp->pgno));
}
return (0);
}
@@ -647,12 +661,12 @@ __ram_root(dbc, rootp, lp, rp)
/* Insert the left and right keys, set the header information. */
ri.pgno = lp->pgno;
- ri.nrecs = __bam_total(lp);
+ ri.nrecs = __bam_total(dbp, lp);
if ((ret = __db_pitem(dbc, rootp, 0, RINTERNAL_SIZE, &hdr, NULL)) != 0)
return (ret);
RE_NREC_SET(rootp, ri.nrecs);
ri.pgno = rp->pgno;
- ri.nrecs = __bam_total(rp);
+ ri.nrecs = __bam_total(dbp, rp);
if ((ret = __db_pitem(dbc, rootp, 1, RINTERNAL_SIZE, &hdr, NULL)) != 0)
return (ret);
RE_NREC_ADJ(rootp, ri.nrecs);
@@ -690,7 +704,8 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
ppage = parent->page;
/* If handling record numbers, count records split to the right page. */
- nrecs = F_ISSET(cp, C_RECNUM) && !space_check ? __bam_total(rchild) : 0;
+ nrecs = F_ISSET(cp, C_RECNUM) &&
+ !space_check ? __bam_total(dbp, rchild) : 0;
/*
* Now we insert the new page's first key into the parent page, which
@@ -721,10 +736,10 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
*/
switch (TYPE(rchild)) {
case P_IBTREE:
- child_bi = GET_BINTERNAL(rchild, 0);
+ child_bi = GET_BINTERNAL(dbp, rchild, 0);
nbytes = BINTERNAL_PSIZE(child_bi->len);
- if (P_FREESPACE(ppage) < nbytes)
+ if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
return (0);
@@ -753,7 +768,7 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
break;
case P_LDUP:
case P_LBTREE:
- child_bk = GET_BKEYDATA(rchild, 0);
+ child_bk = GET_BKEYDATA(dbp, rchild, 0);
switch (B_TYPE(child_bk->type)) {
case B_KEYDATA:
/*
@@ -783,7 +798,7 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
goto noprefix;
if (ppage->prev_pgno == PGNO_INVALID && off <= 1)
goto noprefix;
- tmp_bk = GET_BKEYDATA(lchild, NUM_ENT(lchild) -
+ tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) -
(TYPE(lchild) == P_LDUP ? O_INDX : P_INDX));
if (B_TYPE(tmp_bk->type) != B_KEYDATA)
goto noprefix;
@@ -793,13 +808,13 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
memset(&b, 0, sizeof(b));
b.size = child_bk->len;
b.data = child_bk->data;
- nksize = func(dbp, &a, &b);
+ nksize = (u_int32_t)func(dbp, &a, &b);
if ((n = BINTERNAL_PSIZE(nksize)) < nbytes)
nbytes = n;
else
noprefix: nksize = child_bk->len;
- if (P_FREESPACE(ppage) < nbytes)
+ if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
return (0);
@@ -823,7 +838,7 @@ noprefix: nksize = child_bk->len;
case B_OVERFLOW:
nbytes = BINTERNAL_PSIZE(BOVERFLOW_SIZE);
- if (P_FREESPACE(ppage) < nbytes)
+ if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
return (0);
@@ -850,14 +865,14 @@ noprefix: nksize = child_bk->len;
return (ret);
break;
default:
- return (__db_pgfmt(dbp, rchild->pgno));
+ return (__db_pgfmt(dbp->dbenv, rchild->pgno));
}
break;
case P_IRECNO:
case P_LRECNO:
nbytes = RINTERNAL_PSIZE;
- if (P_FREESPACE(ppage) < nbytes)
+ if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
return (0);
@@ -873,7 +888,7 @@ noprefix: nksize = child_bk->len;
return (ret);
break;
default:
- return (__db_pgfmt(dbp, rchild->pgno));
+ return (__db_pgfmt(dbp->dbenv, rchild->pgno));
}
/*
@@ -882,17 +897,19 @@ noprefix: nksize = child_bk->len;
*/
if (F_ISSET(cp, C_RECNUM)) {
/* Log the change. */
- if (DB_LOGGING(dbc) &&
- (ret = __bam_cadjust_log(dbp->dbenv, dbc->txn,
- &LSN(ppage), 0, dbp->log_fileid, PGNO(ppage),
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __bam_cadjust_log(dbp, dbc->txn,
+ &LSN(ppage), 0, PGNO(ppage),
&LSN(ppage), parent->indx, -(int32_t)nrecs, 0)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(ppage));
/* Update the left page count. */
if (dbc->dbtype == DB_RECNO)
- GET_RINTERNAL(ppage, parent->indx)->nrecs -= nrecs;
+ GET_RINTERNAL(dbp, ppage, parent->indx)->nrecs -= nrecs;
else
- GET_BINTERNAL(ppage, parent->indx)->nrecs -= nrecs;
+ GET_BINTERNAL(dbp, ppage, parent->indx)->nrecs -= nrecs;
}
return (0);
@@ -911,28 +928,52 @@ __bam_psplit(dbc, cp, lp, rp, splitret)
{
DB *dbp;
PAGE *pp;
- db_indx_t half, nbytes, off, splitp, top;
+ db_indx_t half, *inp, nbytes, off, splitp, top;
int adjust, cnt, iflag, isbigkey, ret;
dbp = dbc->dbp;
pp = cp->page;
+ inp = P_INP(dbp, pp);
adjust = TYPE(pp) == P_LBTREE ? P_INDX : O_INDX;
/*
* If we're splitting the first (last) page on a level because we're
* inserting (appending) a key to it, it's likely that the data is
* sorted. Moving a single item to the new page is less work and can
- * push the fill factor higher than normal. If we're wrong it's not
- * a big deal, we'll just do the split the right way next time.
+ * push the fill factor higher than normal. This is trivial when we
+ * are splitting a new page before the beginning of the tree, all of
+ * the interesting tests are against values of 0.
+ *
+ * Catching appends to the tree is harder. In a simple append, we're
+ * inserting an item that sorts past the end of the tree; the cursor
+ * will point past the last element on the page. But, in trees with
+ * duplicates, the cursor may point to the last entry on the page --
+ * in this case, the entry will also be the last element of a duplicate
+ * set (the last because the search call specified the S_DUPLAST flag).
+ * The only way to differentiate between an insert immediately before
+ * the last item in a tree or an append after a duplicate set which is
+ * also the last item in the tree is to call the comparison function.
+ * When splitting internal pages during an append, the search code
+ * guarantees the cursor always points to the largest page item less
+ * than the new internal entry. To summarize, we want to catch three
+ * possible index values:
+ *
+ * NUM_ENT(page) Btree/Recno leaf insert past end-of-tree
+ * NUM_ENT(page) - O_INDX Btree or Recno internal insert past EOT
+ * NUM_ENT(page) - P_INDX Btree leaf insert past EOT after a set
+ * of duplicates
+ *
+ * two of which, (NUM_ENT(page) - O_INDX or P_INDX) might be an insert
+ * near the end of the tree, and not after the end of the tree at all.
+ * Do a simple test which might be wrong because calling the comparison
+ * functions is expensive. Regardless, it's not a big deal if we're
+ * wrong, we'll do the split the right way next time.
*/
off = 0;
- if (NEXT_PGNO(pp) == PGNO_INVALID &&
- ((ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page) - 1) ||
- (!ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page))))
- off = NUM_ENT(cp->page) - adjust;
+ if (NEXT_PGNO(pp) == PGNO_INVALID && cp->indx >= NUM_ENT(pp) - adjust)
+ off = NUM_ENT(pp) - adjust;
else if (PREV_PGNO(pp) == PGNO_INVALID && cp->indx == 0)
off = adjust;
-
if (off != 0)
goto sort;
@@ -962,16 +1003,18 @@ __bam_psplit(dbc, cp, lp, rp, splitret)
for (nbytes = 0, off = 0; off < top && nbytes < half; ++off)
switch (TYPE(pp)) {
case P_IBTREE:
- if (B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA)
- nbytes +=
- BINTERNAL_SIZE(GET_BINTERNAL(pp, off)->len);
+ if (B_TYPE(
+ GET_BINTERNAL(dbp, pp, off)->type) == B_KEYDATA)
+ nbytes += BINTERNAL_SIZE(
+ GET_BINTERNAL(dbp, pp, off)->len);
else
nbytes += BINTERNAL_SIZE(BOVERFLOW_SIZE);
break;
case P_LBTREE:
- if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)
- nbytes +=
- BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
+ if (B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) ==
+ B_KEYDATA)
+ nbytes += BKEYDATA_SIZE(GET_BKEYDATA(dbp,
+ pp, off)->len);
else
nbytes += BOVERFLOW_SIZE;
@@ -979,9 +1022,10 @@ __bam_psplit(dbc, cp, lp, rp, splitret)
/* FALLTHROUGH */
case P_LDUP:
case P_LRECNO:
- if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)
- nbytes +=
- BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
+ if (B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) ==
+ B_KEYDATA)
+ nbytes += BKEYDATA_SIZE(GET_BKEYDATA(dbp,
+ pp, off)->len);
else
nbytes += BOVERFLOW_SIZE;
break;
@@ -989,7 +1033,7 @@ __bam_psplit(dbc, cp, lp, rp, splitret)
nbytes += RINTERNAL_SIZE;
break;
default:
- return (__db_pgfmt(dbp, pp->pgno));
+ return (__db_pgfmt(dbp->dbenv, pp->pgno));
}
sort: splitp = off;
@@ -1002,12 +1046,14 @@ sort: splitp = off;
switch (TYPE(pp)) {
case P_IBTREE:
iflag = 1;
- isbigkey = B_TYPE(GET_BINTERNAL(pp, off)->type) != B_KEYDATA;
+ isbigkey =
+ B_TYPE(GET_BINTERNAL(dbp, pp, off)->type) != B_KEYDATA;
break;
case P_LBTREE:
case P_LDUP:
iflag = 0;
- isbigkey = B_TYPE(GET_BKEYDATA(pp, off)->type) != B_KEYDATA;
+ isbigkey = B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) !=
+ B_KEYDATA;
break;
default:
iflag = isbigkey = 0;
@@ -1016,18 +1062,20 @@ sort: splitp = off;
for (cnt = 1; cnt <= 3; ++cnt) {
off = splitp + cnt * adjust;
if (off < (db_indx_t)NUM_ENT(pp) &&
- ((iflag &&
- B_TYPE(GET_BINTERNAL(pp,off)->type) == B_KEYDATA) ||
- B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)) {
+ ((iflag && B_TYPE(
+ GET_BINTERNAL(dbp, pp,off)->type) == B_KEYDATA) ||
+ B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) ==
+ B_KEYDATA)) {
splitp = off;
break;
}
if (splitp <= (db_indx_t)(cnt * adjust))
continue;
off = splitp - cnt * adjust;
- if (iflag ?
- B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA :
- B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA) {
+ if (iflag ? B_TYPE(
+ GET_BINTERNAL(dbp, pp, off)->type) == B_KEYDATA :
+ B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) ==
+ B_KEYDATA) {
splitp = off;
break;
}
@@ -1040,18 +1088,18 @@ sort: splitp = off;
* page set. So, this loop can't be unbounded.
*/
if (TYPE(pp) == P_LBTREE &&
- pp->inp[splitp] == pp->inp[splitp - adjust])
+ inp[splitp] == inp[splitp - adjust])
for (cnt = 1;; ++cnt) {
off = splitp + cnt * adjust;
if (off < NUM_ENT(pp) &&
- pp->inp[splitp] != pp->inp[off]) {
+ inp[splitp] != inp[off]) {
splitp = off;
break;
}
if (splitp <= (db_indx_t)(cnt * adjust))
continue;
off = splitp - cnt * adjust;
- if (pp->inp[splitp] != pp->inp[off]) {
+ if (inp[splitp] != inp[off]) {
splitp = off + adjust;
break;
}
@@ -1079,18 +1127,20 @@ __bam_copy(dbp, pp, cp, nxt, stop)
PAGE *pp, *cp;
u_int32_t nxt, stop;
{
- db_indx_t nbytes, off;
+ db_indx_t *cinp, nbytes, off, *pinp;
+ cinp = P_INP(dbp, cp);
+ pinp = P_INP(dbp, pp);
/*
- * Copy the rest of the data to the right page. Nxt is the next
- * offset placed on the target page.
+ * Nxt is the offset of the next record to be placed on the target page.
*/
for (off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) {
switch (TYPE(pp)) {
case P_IBTREE:
- if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA)
- nbytes =
- BINTERNAL_SIZE(GET_BINTERNAL(pp, nxt)->len);
+ if (B_TYPE(
+ GET_BINTERNAL(dbp, pp, nxt)->type) == B_KEYDATA)
+ nbytes = BINTERNAL_SIZE(
+ GET_BINTERNAL(dbp, pp, nxt)->len);
else
nbytes = BINTERNAL_SIZE(BOVERFLOW_SIZE);
break;
@@ -1100,16 +1150,17 @@ __bam_copy(dbp, pp, cp, nxt, stop)
* the offset.
*/
if (off != 0 && (nxt % P_INDX) == 0 &&
- pp->inp[nxt] == pp->inp[nxt - P_INDX]) {
- cp->inp[off] = cp->inp[off - P_INDX];
+ pinp[nxt] == pinp[nxt - P_INDX]) {
+ cinp[off] = cinp[off - P_INDX];
continue;
}
/* FALLTHROUGH */
case P_LDUP:
case P_LRECNO:
- if (B_TYPE(GET_BKEYDATA(pp, nxt)->type) == B_KEYDATA)
- nbytes =
- BKEYDATA_SIZE(GET_BKEYDATA(pp, nxt)->len);
+ if (B_TYPE(GET_BKEYDATA(dbp, pp, nxt)->type) ==
+ B_KEYDATA)
+ nbytes = BKEYDATA_SIZE(GET_BKEYDATA(dbp,
+ pp, nxt)->len);
else
nbytes = BOVERFLOW_SIZE;
break;
@@ -1117,10 +1168,10 @@ __bam_copy(dbp, pp, cp, nxt, stop)
nbytes = RINTERNAL_SIZE;
break;
default:
- return (__db_pgfmt(dbp, pp->pgno));
+ return (__db_pgfmt(dbp->dbenv, pp->pgno));
}
- cp->inp[off] = HOFFSET(cp) -= nbytes;
- memcpy(P_ENTRY(cp, off), P_ENTRY(pp, nxt), nbytes);
+ cinp[off] = HOFFSET(cp) -= nbytes;
+ memcpy(P_ENTRY(dbp, cp, off), P_ENTRY(dbp, pp, nxt), nbytes);
}
return (0);
}
diff --git a/bdb/btree/bt_stat.c b/bdb/btree/bt_stat.c
index 349bb40cf8b..4428de98294 100644
--- a/bdb/btree/bt_stat.c
+++ b/bdb/btree/bt_stat.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_stat.c,v 11.29 2000/11/28 21:42:27 bostic Exp $";
+static const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,22 +18,22 @@ static const char revid[] = "$Id: bt_stat.c,v 11.29 2000/11/28 21:42:27 bostic E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
/*
* __bam_stat --
* Gather/print the btree statistics
*
- * PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
+ * PUBLIC: int __bam_stat __P((DB *, void *, u_int32_t));
*/
int
-__bam_stat(dbp, spp, db_malloc, flags)
+__bam_stat(dbp, spp, flags)
DB *dbp;
void *spp;
- void *(*db_malloc) __P((size_t));
u_int32_t flags;
{
BTMETA *meta;
@@ -42,9 +42,10 @@ __bam_stat(dbp, spp, db_malloc, flags)
DBC *dbc;
DB_BTREE_STAT *sp;
DB_LOCK lock, metalock;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
- int ret, t_ret;
+ int ret, t_ret, write_meta;
PANIC_CHECK(dbp->dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
@@ -52,9 +53,12 @@ __bam_stat(dbp, spp, db_malloc, flags)
meta = NULL;
t = dbp->bt_internal;
sp = NULL;
- metalock.off = lock.off = LOCK_INVALID;
+ LOCK_INIT(metalock);
+ LOCK_INIT(lock);
+ mpf = dbp->mpf;
h = NULL;
ret = 0;
+ write_meta = 0;
/* Check for invalid flags. */
if ((ret = __db_statchk(dbp, flags)) != 0)
@@ -68,52 +72,31 @@ __bam_stat(dbp, spp, db_malloc, flags)
DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags);
/* Allocate and clear the structure. */
- if ((ret = __os_malloc(dbp->dbenv, sizeof(*sp), db_malloc, &sp)) != 0)
+ if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0)
goto err;
memset(sp, 0, sizeof(*sp));
- /* If the app just wants the record count, make it fast. */
- if (flags == DB_RECORDCOUNT) {
- if ((ret = __db_lget(dbc, 0,
- cp->root, DB_LOCK_READ, 0, &lock)) != 0)
- goto err;
- if ((ret = memp_fget(dbp->mpf,
- &cp->root, 0, (PAGE **)&h)) != 0)
- goto err;
-
- sp->bt_nkeys = RE_NREC(h);
-
- goto done;
- }
- if (flags == DB_CACHED_COUNTS) {
- if ((ret = __db_lget(dbc,
- 0, t->bt_meta, DB_LOCK_READ, 0, &lock)) != 0)
- goto err;
- if ((ret =
- memp_fget(dbp->mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0)
- goto err;
- sp->bt_nkeys = meta->dbmeta.key_count;
- sp->bt_ndata = meta->dbmeta.record_count;
-
- goto done;
- }
-
/* Get the metadata page for the entire database. */
pgno = PGNO_BASE_MD;
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
goto err;
+ if (flags == DB_RECORDCOUNT || flags == DB_CACHED_COUNTS)
+ flags = DB_FAST_STAT;
+ if (flags == DB_FAST_STAT)
+ goto meta_only;
+
/* Walk the metadata free list, counting pages. */
for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) {
++sp->bt_free;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
pgno = h->next_pgno;
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
goto err;
h = NULL;
}
@@ -122,14 +105,14 @@ __bam_stat(dbp, spp, db_malloc, flags)
pgno = cp->root;
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
/* Get the levels from the root page. */
sp->bt_levels = h->level;
/* Discard the root page. */
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
goto err;
h = NULL;
__LPUT(dbc, lock);
@@ -143,20 +126,36 @@ __bam_stat(dbp, spp, db_malloc, flags)
* Get the subdatabase metadata page if it's not the same as the
* one we already have.
*/
- if (t->bt_meta != PGNO_BASE_MD || !F_ISSET(dbp, DB_AM_RDONLY)) {
- if ((ret = memp_fput(dbp->mpf, meta, 0)) != 0)
+ write_meta = !F_ISSET(dbp, DB_AM_RDONLY);
+meta_only:
+ if (t->bt_meta != PGNO_BASE_MD || write_meta != 0) {
+ if ((ret = mpf->put(mpf, meta, 0)) != 0)
goto err;
meta = NULL;
__LPUT(dbc, metalock);
if ((ret = __db_lget(dbc,
- 0, t->bt_meta, F_ISSET(dbp, DB_AM_RDONLY) ?
+ 0, t->bt_meta, write_meta == 0 ?
DB_LOCK_READ : DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
- if ((ret =
- memp_fget(dbp->mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0)
+ if ((ret = mpf->get(mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0)
goto err;
}
+ if (flags == DB_FAST_STAT) {
+ if (dbp->type == DB_RECNO ||
+ (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))) {
+ if ((ret = __db_lget(dbc, 0,
+ cp->root, DB_LOCK_READ, 0, &lock)) != 0)
+ goto err;
+ if ((ret =
+ mpf->get(mpf, &cp->root, 0, (PAGE **)&h)) != 0)
+ goto err;
+
+ sp->bt_nkeys = RE_NREC(h);
+ } else
+ sp->bt_nkeys = meta->dbmeta.key_count;
+ sp->bt_ndata = meta->dbmeta.record_count;
+ }
/* Get metadata page statistics. */
sp->bt_metaflags = meta->dbmeta.flags;
@@ -167,39 +166,33 @@ __bam_stat(dbp, spp, db_malloc, flags)
sp->bt_pagesize = meta->dbmeta.pagesize;
sp->bt_magic = meta->dbmeta.magic;
sp->bt_version = meta->dbmeta.version;
- if (!F_ISSET(dbp, DB_AM_RDONLY)) {
+
+ if (write_meta != 0) {
meta->dbmeta.key_count = sp->bt_nkeys;
meta->dbmeta.record_count = sp->bt_ndata;
}
- /* Discard the metadata page. */
- if ((ret = memp_fput(dbp->mpf,
- meta, F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY)) != 0)
- goto err;
- meta = NULL;
- __LPUT(dbc, metalock);
-
-done: *(DB_BTREE_STAT **)spp = sp;
-
- if (0) {
-err: if (sp != NULL)
- __os_free(sp, sizeof(*sp));
- }
+ *(DB_BTREE_STAT **)spp = sp;
- if (h != NULL &&
- (t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
+err: /* Discard the second page. */
+ __LPUT(dbc, lock);
+ if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
- if (meta != NULL &&
- (t_ret = memp_fput(dbp->mpf, meta, 0)) != 0 && ret == 0)
+ /* Discard the metadata page. */
+ __LPUT(dbc, metalock);
+ if (meta != NULL && (t_ret = mpf->put(
+ mpf, meta, write_meta == 0 ? 0 : DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
- if (lock.off != LOCK_INVALID)
- __LPUT(dbc, lock);
-
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
+ if (ret != 0 && sp != NULL) {
+ __os_ufree(dbp->dbenv, sp);
+ *(DB_BTREE_STAT **)spp = NULL;
+ }
+
return (ret);
}
@@ -222,22 +215,27 @@ __bam_traverse(dbc, mode, root_pgno, callback, cookie)
BKEYDATA *bk;
DB *dbp;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
PAGE *h;
RINTERNAL *ri;
db_indx_t indx;
int already_put, ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
+ already_put = 0;
if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &root_pgno, 0, &h)) != 0)
- goto err;
+ if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0) {
+ __LPUT(dbc, lock);
+ return (ret);
+ }
switch (TYPE(h)) {
case P_IBTREE:
for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
- bi = GET_BINTERNAL(h, indx);
+ bi = GET_BINTERNAL(dbp, h, indx);
if (B_TYPE(bi->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
((BOVERFLOW *)bi->data)->pgno,
@@ -245,34 +243,34 @@ __bam_traverse(dbc, mode, root_pgno, callback, cookie)
goto err;
if ((ret = __bam_traverse(
dbc, mode, bi->pgno, callback, cookie)) != 0)
- break;
+ goto err;
}
break;
case P_IRECNO:
for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
- ri = GET_RINTERNAL(h, indx);
+ ri = GET_RINTERNAL(dbp, h, indx);
if ((ret = __bam_traverse(
dbc, mode, ri->pgno, callback, cookie)) != 0)
- break;
+ goto err;
}
break;
case P_LBTREE:
for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) {
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
- GET_BOVERFLOW(h, indx)->pgno,
+ GET_BOVERFLOW(dbp, h, indx)->pgno,
callback, cookie)) != 0)
goto err;
- bk = GET_BKEYDATA(h, indx + O_INDX);
+ bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
if (B_TYPE(bk->type) == B_DUPLICATE &&
(ret = __bam_traverse(dbc, mode,
- GET_BOVERFLOW(h, indx + O_INDX)->pgno,
+ GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
callback, cookie)) != 0)
goto err;
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
- GET_BOVERFLOW(h, indx + O_INDX)->pgno,
+ GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
callback, cookie)) != 0)
goto err;
}
@@ -280,22 +278,19 @@ __bam_traverse(dbc, mode, root_pgno, callback, cookie)
case P_LDUP:
case P_LRECNO:
for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
- GET_BOVERFLOW(h, indx)->pgno,
+ GET_BOVERFLOW(dbp, h, indx)->pgno,
callback, cookie)) != 0)
goto err;
}
break;
}
- already_put = 0;
- if ((ret = callback(dbp, h, cookie, &already_put)) != 0)
- goto err;
+ ret = callback(dbp, h, cookie, &already_put);
-err: if (!already_put &&
- (t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret != 0)
+err: if (!already_put && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret != 0)
ret = t_ret;
__LPUT(dbc, lock);
@@ -316,33 +311,34 @@ __bam_stat_callback(dbp, h, cookie, putp)
int *putp;
{
DB_BTREE_STAT *sp;
- db_indx_t indx, top;
+ db_indx_t indx, *inp, top;
u_int8_t type;
sp = cookie;
*putp = 0;
top = NUM_ENT(h);
+ inp = P_INP(dbp, h);
switch (TYPE(h)) {
case P_IBTREE:
case P_IRECNO:
++sp->bt_int_pg;
- sp->bt_int_pgfree += P_FREESPACE(h);
+ sp->bt_int_pgfree += P_FREESPACE(dbp, h);
break;
case P_LBTREE:
/* Correct for on-page duplicates and deleted items. */
for (indx = 0; indx < top; indx += P_INDX) {
if (indx + P_INDX >= top ||
- h->inp[indx] != h->inp[indx + P_INDX])
+ inp[indx] != inp[indx + P_INDX])
++sp->bt_nkeys;
- type = GET_BKEYDATA(h, indx + O_INDX)->type;
+ type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type;
if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
++sp->bt_ndata;
}
++sp->bt_leaf_pg;
- sp->bt_leaf_pgfree += P_FREESPACE(h);
+ sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
break;
case P_LRECNO:
/*
@@ -356,39 +352,39 @@ __bam_stat_callback(dbp, h, cookie, putp)
* Correct for deleted items in non-renumbering
* Recno databases.
*/
- if (F_ISSET(dbp, DB_RE_RENUMBER))
+ if (F_ISSET(dbp, DB_AM_RENUMBER))
sp->bt_ndata += top;
else
for (indx = 0; indx < top; indx += O_INDX) {
- type = GET_BKEYDATA(h, indx)->type;
+ type = GET_BKEYDATA(dbp, h, indx)->type;
if (!B_DISSET(type))
++sp->bt_ndata;
}
++sp->bt_leaf_pg;
- sp->bt_leaf_pgfree += P_FREESPACE(h);
+ sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
} else {
sp->bt_ndata += top;
++sp->bt_dup_pg;
- sp->bt_dup_pgfree += P_FREESPACE(h);
+ sp->bt_dup_pgfree += P_FREESPACE(dbp, h);
}
break;
case P_LDUP:
/* Correct for deleted items. */
for (indx = 0; indx < top; indx += O_INDX)
- if (!B_DISSET(GET_BKEYDATA(h, indx)->type))
+ if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type))
++sp->bt_ndata;
++sp->bt_dup_pg;
- sp->bt_dup_pgfree += P_FREESPACE(h);
+ sp->bt_dup_pgfree += P_FREESPACE(dbp, h);
break;
case P_OVERFLOW:
++sp->bt_over_pg;
- sp->bt_over_pgfree += P_OVFLSPACE(dbp->pgsize, h);
+ sp->bt_over_pgfree += P_OVFLSPACE(dbp, dbp->pgsize, h);
break;
default:
- return (__db_pgfmt(dbp, h->pgno));
+ return (__db_pgfmt(dbp->dbenv, h->pgno));
}
return (0);
}
@@ -421,13 +417,18 @@ __bam_key_range(dbp, txn, dbt, kp, flags)
if (flags != 0)
return (__db_ferr(dbp->dbenv, "DB->key_range", 0));
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
+ return (ret);
+
/* Acquire a cursor. */
if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
return (ret);
DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0);
- if ((ret = __bam_search(dbc, dbt, S_STK_ONLY, 1, NULL, &exact)) != 0)
+ if ((ret = __bam_search(dbc, PGNO_INVALID,
+ dbt, S_STK_ONLY, 1, NULL, &exact)) != 0)
goto err;
cp = (BTREE_CURSOR *)dbc->internal;
diff --git a/bdb/btree/bt_upgrade.c b/bdb/btree/bt_upgrade.c
index 4032dba3b36..9f92648d739 100644
--- a/bdb/btree/bt_upgrade.c
+++ b/bdb/btree/bt_upgrade.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_upgrade.c,v 11.19 2000/11/30 00:58:29 ubell Exp $";
+static const char revid[] = "$Id: bt_upgrade.c,v 11.25 2002/08/06 06:11:13 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,11 +18,9 @@ static const char revid[] = "$Id: bt_upgrade.c,v 11.19 2000/11/30 00:58:29 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "btree.h"
-#include "db_am.h"
-#include "db_upgrade.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_upgrade.h"
/*
* __bam_30_btreemeta --
@@ -107,7 +105,7 @@ __bam_31_btreemeta(dbp, real_name, flags, fhp, h, dirtyp)
newmeta->minkey = oldmeta->minkey;
newmeta->maxkey = oldmeta->maxkey;
memmove(newmeta->dbmeta.uid,
- oldmeta->dbmeta.uid, sizeof(oldmeta->dbmeta.uid));
+ oldmeta->dbmeta.uid, sizeof(oldmeta->dbmeta.uid));
newmeta->dbmeta.flags = oldmeta->dbmeta.flags;
newmeta->dbmeta.record_count = 0;
newmeta->dbmeta.key_count = 0;
@@ -126,7 +124,7 @@ __bam_31_btreemeta(dbp, real_name, flags, fhp, h, dirtyp)
/*
* __bam_31_lbtree --
- * Upgrade the database btree leaf pages.
+ * Upgrade the database btree leaf pages.
*
* PUBLIC: int __bam_31_lbtree
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
@@ -147,15 +145,15 @@ __bam_31_lbtree(dbp, real_name, flags, fhp, h, dirtyp)
ret = 0;
for (indx = O_INDX; indx < NUM_ENT(h); indx += P_INDX) {
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_DUPLICATE) {
- pgno = GET_BOVERFLOW(h, indx)->pgno;
+ pgno = GET_BOVERFLOW(dbp, h, indx)->pgno;
if ((ret = __db_31_offdup(dbp, real_name, fhp,
LF_ISSET(DB_DUPSORT) ? 1 : 0, &pgno)) != 0)
break;
- if (pgno != GET_BOVERFLOW(h, indx)->pgno) {
+ if (pgno != GET_BOVERFLOW(dbp, h, indx)->pgno) {
*dirtyp = 1;
- GET_BOVERFLOW(h, indx)->pgno = pgno;
+ GET_BOVERFLOW(dbp, h, indx)->pgno = pgno;
}
}
}
diff --git a/bdb/btree/bt_verify.c b/bdb/btree/bt_verify.c
index 9f8647e7e2a..0cf8a47e476 100644
--- a/bdb/btree/bt_verify.c
+++ b/bdb/btree/bt_verify.c
@@ -1,16 +1,16 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: bt_verify.c,v 1.44 2000/12/06 19:55:44 ubell Exp $
+ * $Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic Exp $
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_verify.c,v 1.44 2000/12/06 19:55:44 ubell Exp $";
+static const char revid[] = "$Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,9 +20,9 @@ static const char revid[] = "$Id: bt_verify.c,v 1.44 2000/12/06 19:55:44 ubell E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_verify.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_verify.h"
+#include "dbinc/btree.h"
static int __bam_safe_getdata __P((DB *, PAGE *, u_int32_t, int, DBT *, int *));
static int __bam_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
@@ -79,15 +79,15 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
/* avoid division by zero */
ovflsize = meta->minkey > 0 ?
- B_MINKEY_TO_OVFLSIZE(meta->minkey, dbp->pgsize) : 0;
+ B_MINKEY_TO_OVFLSIZE(dbp, meta->minkey, dbp->pgsize) : 0;
if (meta->minkey < 2 ||
- ovflsize > B_MINKEY_TO_OVFLSIZE(DEFMINKEYPAGE, dbp->pgsize)) {
+ ovflsize > B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) {
pip->bt_minkey = 0;
isbad = 1;
EPRINT((dbp->dbenv,
- "Nonsensical bt_minkey value %lu on metadata page %lu",
- (u_long)meta->minkey, (u_long)pgno));
+ "Page %lu: nonsensical bt_minkey value %lu on metadata page",
+ (u_long)pgno, (u_long)meta->minkey));
} else
pip->bt_minkey = meta->minkey;
@@ -103,13 +103,13 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
* of the file, then the root page had better be page 1.
*/
pip->root = 0;
- if (meta->root == PGNO_INVALID
- || meta->root == pgno || !IS_VALID_PGNO(meta->root) ||
+ if (meta->root == PGNO_INVALID ||
+ meta->root == pgno || !IS_VALID_PGNO(meta->root) ||
(pgno == PGNO_BASE_MD && meta->root != 1)) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Nonsensical root page %lu on metadata page %lu",
- (u_long)meta->root, (u_long)vdp->last_pgno));
+ "Page %lu: nonsensical root page %lu on metadata page",
+ (u_long)pgno, (u_long)meta->root));
} else
pip->root = meta->root;
@@ -125,7 +125,7 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
if (F_ISSET(&meta->dbmeta, BTM_DUP) && pgno == PGNO_BASE_MD) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Btree metadata page %lu has both duplicates and multiple databases",
+"Page %lu: Btree metadata page has both duplicates and multiple databases",
(u_long)pgno));
}
F_SET(pip, VRFY_HAS_SUBDBS);
@@ -139,7 +139,7 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
F_SET(pip, VRFY_HAS_RECNUMS);
if (F_ISSET(pip, VRFY_HAS_RECNUMS) && F_ISSET(pip, VRFY_HAS_DUPS)) {
EPRINT((dbp->dbenv,
- "Btree metadata page %lu illegally has both recnums and dups",
+ "Page %lu: Btree metadata page illegally has both recnums and dups",
(u_long)pgno));
isbad = 1;
}
@@ -150,13 +150,13 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
} else if (F_ISSET(pip, VRFY_IS_RRECNO)) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Metadata page %lu has renumber flag set but is not recno",
+ "Page %lu: metadata page has renumber flag set but is not recno",
(u_long)pgno));
}
if (F_ISSET(pip, VRFY_IS_RECNO) && F_ISSET(pip, VRFY_HAS_DUPS)) {
EPRINT((dbp->dbenv,
- "Recno metadata page %lu specifies duplicates",
+ "Page %lu: recno metadata page specifies duplicates",
(u_long)pgno));
isbad = 1;
}
@@ -170,8 +170,8 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
*/
isbad = 1;
EPRINT((dbp->dbenv,
- "re_len of %lu in non-fixed-length database",
- (u_long)pip->re_len));
+ "Page %lu: re_len of %lu in non-fixed-length database",
+ (u_long)pgno, (u_long)pip->re_len));
}
/*
@@ -179,7 +179,8 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
* not be and may still be correct.
*/
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -242,7 +243,7 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
if (F_ISSET(pip, VRFY_HAS_DUPS)) {
EPRINT((dbp->dbenv,
- "Recno database has dups on page %lu", (u_long)pgno));
+ "Page %lu: Recno database has dups", (u_long)pgno));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -255,7 +256,7 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
*/
re_len_guess = 0;
for (i = 0; i < NUM_ENT(h); i++) {
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
/* KEYEMPTY. Go on. */
if (B_DISSET(bk->type))
continue;
@@ -266,8 +267,8 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
else {
isbad = 1;
EPRINT((dbp->dbenv,
- "Nonsensical type for item %lu, page %lu",
- (u_long)i, (u_long)pgno));
+ "Page %lu: nonsensical type for item %lu",
+ (u_long)pgno, (u_long)i));
continue;
}
if (re_len_guess == 0)
@@ -288,9 +289,10 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
/* Save off record count. */
pip->rec_cnt = NUM_ENT(h);
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
- return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : 0);
+ return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
/*
@@ -362,7 +364,7 @@ __bam_vrfy(dbp, vdp, h, pgno, flags)
else
goto err;
EPRINT((dbp->dbenv,
- "item order check on page %lu unsafe: skipping",
+ "Page %lu: item order check unsafe: skipping",
(u_long)pgno));
} else if (!LF_ISSET(DB_NOORDERCHK) && (ret =
__bam_vrfy_itemorder(dbp, vdp, h, pgno, 0, 0, 0, flags)) != 0) {
@@ -377,9 +379,10 @@ __bam_vrfy(dbp, vdp, h, pgno, flags)
goto err;
}
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
- return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : 0);
+ return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
/*
@@ -403,6 +406,7 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
VRFY_PAGEINFO *pip;
int ret, t_ret, isbad;
u_int32_t himark, i, offset, nentries;
+ db_indx_t *inp;
u_int8_t *pagelayout, *p;
isbad = 0;
@@ -422,30 +426,31 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
himark = dbp->pgsize;
if ((ret =
- __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &pagelayout)) != 0)
+ __os_malloc(dbp->dbenv, dbp->pgsize, &pagelayout)) != 0)
goto err;
memset(pagelayout, 0, dbp->pgsize);
+ inp = P_INP(dbp, h);
for (i = 0; i < NUM_ENT(h); i++) {
- if ((u_int8_t *)h->inp + i >= (u_int8_t *)h + himark) {
+ if ((u_int8_t *)inp + i >= (u_int8_t *)h + himark) {
EPRINT((dbp->dbenv,
- "Page %lu entries listing %lu overlaps data",
+ "Page %lu: entries listing %lu overlaps data",
(u_long)pgno, (u_long)i));
ret = DB_VERIFY_BAD;
goto err;
}
- offset = h->inp[i];
+ offset = inp[i];
/*
* Check that the item offset is reasonable: it points
* somewhere after the inp array and before the end of the
* page.
*/
- if (offset <= (u_int32_t)((u_int8_t *)h->inp + i -
+ if (offset <= (u_int32_t)((u_int8_t *)inp + i -
(u_int8_t *)h) ||
offset > (u_int32_t)(dbp->pgsize - RINTERNAL_SIZE)) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Bad offset %lu at page %lu index %lu",
- (u_long)offset, (u_long)pgno, (u_long)i));
+ "Page %lu: bad offset %lu at index %lu",
+ (u_long)pgno, (u_long)offset, (u_long)i));
continue;
}
@@ -456,7 +461,7 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
nentries++;
/* Make sure this RINTERNAL is not multiply referenced. */
- ri = GET_RINTERNAL(h, i);
+ ri = GET_RINTERNAL(dbp, h, i);
if (pagelayout[offset] == 0) {
pagelayout[offset] = 1;
child.pgno = ri->pgno;
@@ -466,8 +471,8 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
goto err;
} else {
EPRINT((dbp->dbenv,
- "RINTERNAL structure at offset %lu, page %lu referenced twice",
- (u_long)offset, (u_long)pgno));
+ "Page %lu: RINTERNAL structure at offset %lu referenced twice",
+ (u_long)pgno, (u_long)offset));
isbad = 1;
}
}
@@ -477,23 +482,25 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
p += RINTERNAL_SIZE)
if (*p != 1) {
EPRINT((dbp->dbenv,
- "Gap between items at offset %lu, page %lu",
- (u_long)(p - pagelayout), (u_long)pgno));
+ "Page %lu: gap between items at offset %lu",
+ (u_long)pgno, (u_long)(p - pagelayout)));
isbad = 1;
}
if ((db_indx_t)himark != HOFFSET(h)) {
- EPRINT((dbp->dbenv, "Bad HOFFSET %lu, appears to be %lu",
- (u_long)(HOFFSET(h)), (u_long)himark));
+ EPRINT((dbp->dbenv,
+ "Page %lu: bad HOFFSET %lu, appears to be %lu",
+ (u_long)pgno, (u_long)(HOFFSET(h)), (u_long)himark));
isbad = 1;
}
*nentriesp = nentries;
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
if (pagelayout != NULL)
- __os_free(pagelayout, dbp->pgsize);
+ __os_free(dbp->dbenv, pagelayout);
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -558,22 +565,24 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
* it and the region immediately after it.
*/
himark = dbp->pgsize;
- if ((ret = __os_malloc(dbp->dbenv,
- dbp->pgsize, NULL, &pagelayout)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &pagelayout)) != 0)
goto err;
memset(pagelayout, 0, dbp->pgsize);
for (i = 0; i < NUM_ENT(h); i++) {
-
- ret = __db_vrfy_inpitem(dbp,
- h, pgno, i, 1, flags, &himark, &offset);
- if (ret == DB_VERIFY_BAD) {
+ switch (ret = __db_vrfy_inpitem(dbp,
+ h, pgno, i, 1, flags, &himark, &offset)) {
+ case 0:
+ break;
+ case DB_VERIFY_BAD:
isbad = 1;
continue;
- } else if (ret == DB_VERIFY_FATAL) {
+ case DB_VERIFY_FATAL:
isbad = 1;
goto err;
- } else if (ret != 0)
- DB_ASSERT(0);
+ default:
+ DB_ASSERT(ret != 0);
+ break;
+ }
/*
* We now have a plausible beginning for the item, and we know
@@ -582,7 +591,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
* Mark the beginning and end in pagelayout so we can make sure
* items have no overlaps or gaps.
*/
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
#define ITEM_BEGIN 1
#define ITEM_END 2
if (pagelayout[offset] == 0)
@@ -609,8 +618,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
} else {
isbad = 1;
EPRINT((dbp->dbenv,
- "Duplicated item %lu on page %lu",
- (u_long)i, (u_long)pgno));
+ "Page %lu: duplicated item %lu",
+ (u_long)pgno, (u_long)i));
}
}
@@ -662,8 +671,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
*/
if (isdupitem && pagelayout[endoff] != ITEM_END) {
EPRINT((dbp->dbenv,
- "Duplicated item %lu on page %lu",
- (u_long)i, (u_long)pgno));
+ "Page %lu: duplicated item %lu",
+ (u_long)pgno, (u_long)i));
isbad = 1;
} else if (pagelayout[endoff] == 0)
pagelayout[endoff] = ITEM_END;
@@ -676,8 +685,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
if (B_DISSET(bk->type) && TYPE(h) != P_LRECNO) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Item %lu on page %lu marked deleted",
- (u_long)i, (u_long)pgno));
+ "Page %lu: item %lu marked deleted",
+ (u_long)pgno, (u_long)i));
}
/*
@@ -696,13 +705,13 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
if (TYPE(h) == P_IBTREE) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Duplicate page referenced by internal btree page %lu at item %lu",
+ "Page %lu: duplicate page referenced by internal btree page at item %lu",
(u_long)pgno, (u_long)i));
break;
} else if (TYPE(h) == P_LRECNO) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Duplicate page referenced by recno page %lu at item %lu",
+ "Page %lu: duplicate page referenced by recno page at item %lu",
(u_long)pgno, (u_long)i));
break;
}
@@ -717,9 +726,9 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
if (bo->tlen > dbp->pgsize * vdp->last_pgno) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Impossible tlen %lu, item %lu, page %lu",
- (u_long)bo->tlen, (u_long)i,
- (u_long)pgno));
+ "Page %lu: impossible tlen %lu, item %lu",
+ (u_long)pgno,
+ (u_long)bo->tlen, (u_long)i));
/* Don't save as a child. */
break;
}
@@ -728,8 +737,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
bo->pgno == PGNO_INVALID) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Offpage item %lu, page %lu has bad pgno",
- (u_long)i, (u_long)pgno));
+ "Page %lu: offpage item %lu has bad pgno %lu",
+ (u_long)pgno, (u_long)i, (u_long)bo->pgno));
/* Don't save as a child. */
break;
}
@@ -744,8 +753,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
default:
isbad = 1;
EPRINT((dbp->dbenv,
- "Item %lu on page %lu of invalid type %lu",
- (u_long)i, (u_long)pgno));
+ "Page %lu: item %lu of invalid type %lu",
+ (u_long)pgno, (u_long)i));
break;
}
}
@@ -765,7 +774,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
isbad = 1;
EPRINT((dbp->dbenv,
- "Gap between items, page %lu offset %lu",
+ "Page %lu: gap between items at offset %lu",
(u_long)pgno, (u_long)i));
/* Find the end of the gap */
for ( ; pagelayout[i + 1] == 0 &&
@@ -777,8 +786,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
if (i != ALIGN(i, sizeof(u_int32_t))) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Offset %lu page %lu unaligned",
- (u_long)i, (u_long)pgno));
+ "Page %lu: offset %lu unaligned",
+ (u_long)pgno, (u_long)i));
}
initem = 1;
nentries++;
@@ -791,7 +800,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
*/
isbad = 1;
EPRINT((dbp->dbenv,
- "Overlapping items, page %lu offset %lu",
+ "Page %lu: overlapping items at offset %lu",
(u_long)pgno, (u_long)i));
break;
default:
@@ -816,24 +825,26 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
*/
isbad = 1;
EPRINT((dbp->dbenv,
- "Overlapping items, page %lu offset %lu",
+ "Page %lu: overlapping items at offset %lu",
(u_long)pgno, (u_long)i));
break;
}
- (void)__os_free(pagelayout, dbp->pgsize);
+ (void)__os_free(dbp->dbenv, pagelayout);
/* Verify HOFFSET. */
if ((db_indx_t)himark != HOFFSET(h)) {
- EPRINT((dbp->dbenv, "Bad HOFFSET %lu, appears to be %lu",
- (u_long)HOFFSET(h), (u_long)himark));
+ EPRINT((dbp->dbenv,
+ "Page %lu: bad HOFFSET %lu, appears to be %lu",
+ (u_long)pgno, (u_long)HOFFSET(h), (u_long)himark));
isbad = 1;
}
err: if (nentriesp != NULL)
*nentriesp = nentries;
- if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+ if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
@@ -865,14 +876,14 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
int ovflok, hasdups;
u_int32_t flags;
{
- DBT dbta, dbtb, dup1, dup2, *p1, *p2, *tmp;
+ DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp;
BTREE *bt;
BINTERNAL *bi;
BKEYDATA *bk;
BOVERFLOW *bo;
VRFY_PAGEINFO *pip;
db_indx_t i;
- int cmp, freedup1, freedup2, isbad, ret, t_ret;
+ int cmp, freedup_1, freedup_2, isbad, ret, t_ret;
int (*dupfunc) __P((DB *, const DBT *, const DBT *));
int (*func) __P((DB *, const DBT *, const DBT *));
void *buf1, *buf2, *tmpbuf;
@@ -949,7 +960,7 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
*/
switch (TYPE(h)) {
case P_IBTREE:
- bi = GET_BINTERNAL(h, i);
+ bi = GET_BINTERNAL(dbp, h, i);
if (B_TYPE(bi->type) == B_OVERFLOW) {
bo = (BOVERFLOW *)(bi->data);
goto overflow;
@@ -972,14 +983,14 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
if (i == 0 && bi->len != 0) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Lowest key on internal page %lu of nonzero length",
+ "Page %lu: lowest key on internal page of nonzero length",
(u_long)pgno));
}
#endif
break;
case P_LBTREE:
case P_LDUP:
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
if (B_TYPE(bk->type) == B_OVERFLOW) {
bo = (BOVERFLOW *)bk;
goto overflow;
@@ -1030,8 +1041,8 @@ overflow: if (!ovflok) {
p2, bo->tlen, bo->pgno, NULL, NULL)) != 0) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Error %lu in fetching overflow item %lu, page %lu",
- (u_long)ret, (u_long)i, (u_long)pgno));
+ "Page %lu: error %lu in fetching overflow item %lu",
+ (u_long)pgno, (u_long)ret, (u_long)i));
}
/* In case it got realloc'ed and thus changed. */
buf2 = p2->data;
@@ -1045,7 +1056,7 @@ overflow: if (!ovflok) {
if (cmp > 0) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Out-of-order key, page %lu item %lu",
+ "Page %lu: out-of-order key at entry %lu",
(u_long)pgno, (u_long)i));
/* proceed */
} else if (cmp == 0) {
@@ -1060,7 +1071,7 @@ overflow: if (!ovflok) {
else if (hasdups == 0) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Database with no duplicates has duplicated keys on page %lu",
+ "Page %lu: database with no duplicates has duplicated keys",
(u_long)pgno));
}
@@ -1092,11 +1103,11 @@ overflow: if (!ovflok) {
* dups are probably (?) rare.
*/
if (((ret = __bam_safe_getdata(dbp,
- h, i - 1, ovflok, &dup1,
- &freedup1)) != 0) ||
+ h, i - 1, ovflok, &dup_1,
+ &freedup_1)) != 0) ||
((ret = __bam_safe_getdata(dbp,
- h, i + 1, ovflok, &dup2,
- &freedup2)) != 0))
+ h, i + 1, ovflok, &dup_2,
+ &freedup_2)) != 0))
goto err;
/*
@@ -1105,8 +1116,8 @@ overflow: if (!ovflok) {
* it's not safe to chase them now.
* Mark an incomplete and return.
*/
- if (dup1.data == NULL ||
- dup2.data == NULL) {
+ if (dup_1.data == NULL ||
+ dup_2.data == NULL) {
DB_ASSERT(!ovflok);
F_SET(pip, VRFY_INCOMPLETE);
goto err;
@@ -1118,26 +1129,28 @@ overflow: if (!ovflok) {
* until we do the structure check
* and see whether DUPSORT is set.
*/
- if (dupfunc(dbp, &dup1, &dup2) > 0)
+ if (dupfunc(dbp, &dup_1, &dup_2) > 0)
F_SET(pip, VRFY_DUPS_UNSORTED);
- if (freedup1)
- __os_free(dup1.data, 0);
- if (freedup2)
- __os_free(dup2.data, 0);
+ if (freedup_1)
+ __os_ufree(dbp->dbenv,
+ dup_1.data);
+ if (freedup_2)
+ __os_ufree(dbp->dbenv,
+ dup_2.data);
}
}
}
}
-err: if (pip != NULL &&
- ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0) && ret == 0)
+err: if (pip != NULL && ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0) && ret == 0)
ret = t_ret;
if (buf1 != NULL)
- __os_free(buf1, 0);
+ __os_ufree(dbp->dbenv, buf1);
if (buf2 != NULL)
- __os_free(buf2, 0);
+ __os_ufree(dbp->dbenv, buf2);
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -1173,7 +1186,7 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
goto err;
if (p != 0) {
EPRINT((dbp->dbenv,
- "Btree metadata page number %lu observed twice",
+ "Page %lu: btree metadata page observed twice",
(u_long)meta_pgno));
ret = DB_VERIFY_BAD;
goto err;
@@ -1185,7 +1198,8 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
if (root == 0) {
EPRINT((dbp->dbenv,
- "Btree metadata page %lu has no root", (u_long)meta_pgno));
+ "Page %lu: btree metadata page has no root",
+ (u_long)meta_pgno));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -1222,7 +1236,7 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
*/
if (mip->re_len > 0 && relen > 0 && mip->re_len != relen) {
EPRINT((dbp->dbenv,
- "Recno database with meta page %lu has bad re_len %lu",
+ "Page %lu: recno database has bad re_len %lu",
(u_long)meta_pgno, (u_long)relen));
ret = DB_VERIFY_BAD;
goto err;
@@ -1231,24 +1245,24 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
break;
case P_LDUP:
EPRINT((dbp->dbenv,
- "Duplicate tree referenced from metadata page %lu",
+ "Page %lu: duplicate tree referenced from metadata page",
(u_long)meta_pgno));
ret = DB_VERIFY_BAD;
break;
default:
EPRINT((dbp->dbenv,
- "Btree root of incorrect type %lu on meta page %lu",
- (u_long)rip->type, (u_long)meta_pgno));
+ "Page %lu: btree root of incorrect type %lu on metadata page",
+ (u_long)meta_pgno, (u_long)rip->type));
ret = DB_VERIFY_BAD;
break;
}
-err: if (mip != NULL &&
- ((t_ret = __db_vrfy_putpageinfo(vdp, mip)) != 0) && ret == 0)
- t_ret = ret;
- if (rip != NULL &&
- ((t_ret = __db_vrfy_putpageinfo(vdp, rip)) != 0) && ret == 0)
- t_ret = ret;
+err: if (mip != NULL && ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, mip)) != 0) && ret == 0)
+ ret = t_ret;
+ if (rip != NULL && ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, rip)) != 0) && ret == 0)
+ ret = t_ret;
return (ret);
}
@@ -1273,20 +1287,26 @@ __bam_vrfy_subtree(dbp,
{
BINTERNAL *li, *ri, *lp, *rp;
DB *pgset;
+ DB_MPOOLFILE *mpf;
DBC *cc;
PAGE *h;
VRFY_CHILDINFO *child;
VRFY_PAGEINFO *pip;
- db_recno_t nrecs, child_nrecs;
db_indx_t i;
- int ret, t_ret, isbad, toplevel, p;
+ db_pgno_t next_pgno, prev_pgno;
+ db_recno_t child_nrecs, nrecs;
+ u_int32_t child_level, child_relen, level, relen, stflags;
+ u_int8_t leaf_type;
int (*func) __P((DB *, const DBT *, const DBT *));
- u_int32_t level, child_level, stflags, child_relen, relen;
+ int isbad, p, ret, t_ret, toplevel;
+ mpf = dbp->mpf;
ret = isbad = 0;
nrecs = 0;
h = NULL;
relen = 0;
+ leaf_type = P_INVALID;
+ next_pgno = prev_pgno = PGNO_INVALID;
rp = (BINTERNAL *)r;
lp = (BINTERNAL *)l;
@@ -1300,10 +1320,33 @@ __bam_vrfy_subtree(dbp,
cc = NULL;
level = pip->bt_level;
- toplevel = LF_ISSET(ST_TOPLEVEL);
+ toplevel = LF_ISSET(ST_TOPLEVEL) ? 1 : 0;
LF_CLR(ST_TOPLEVEL);
/*
+ * If this is the root, initialize the vdp's prev- and next-pgno
+ * accounting.
+ *
+ * For each leaf page we hit, we'll want to make sure that
+ * vdp->prev_pgno is the same as pip->prev_pgno and vdp->next_pgno is
+ * our page number. Then, we'll set vdp->next_pgno to pip->next_pgno
+ * and vdp->prev_pgno to our page number, and the next leaf page in
+ * line should be able to do the same verification.
+ */
+ if (toplevel) {
+ /*
+ * Cache the values stored in the vdp so that if we're an
+ * auxiliary tree such as an off-page duplicate set, our
+ * caller's leaf page chain doesn't get lost.
+ */
+ prev_pgno = vdp->prev_pgno;
+ next_pgno = vdp->next_pgno;
+ leaf_type = vdp->leaf_type;
+ vdp->next_pgno = vdp->prev_pgno = PGNO_INVALID;
+ vdp->leaf_type = P_INVALID;
+ }
+
+ /*
* We are recursively descending a btree, starting from the root
* and working our way out to the leaves.
*
@@ -1333,8 +1376,53 @@ __bam_vrfy_subtree(dbp,
case P_LDUP:
case P_LBTREE:
/*
- * Cases 1, 2 and 3 (overflow pages are common to all three);
- * traverse child list, looking for overflows.
+ * Cases 1, 2 and 3.
+ *
+ * We're some sort of leaf page; verify
+ * that our linked list of leaves is consistent.
+ */
+ if (vdp->leaf_type == P_INVALID) {
+ /*
+ * First leaf page. Set the type that all its
+ * successors should be, and verify that our prev_pgno
+ * is PGNO_INVALID.
+ */
+ vdp->leaf_type = pip->type;
+ if (pip->prev_pgno != PGNO_INVALID)
+ goto bad_prev;
+ } else {
+ /*
+ * Successor leaf page. Check our type, the previous
+ * page's next_pgno, and our prev_pgno.
+ */
+ if (pip->type != vdp->leaf_type) {
+ EPRINT((dbp->dbenv,
+ "Page %lu: unexpected page type %lu found in leaf chain (expected %lu)",
+ (u_long)pip->pgno, (u_long)pip->type,
+ (u_long)vdp->leaf_type));
+ isbad = 1;
+ }
+ if (pip->pgno != vdp->next_pgno) {
+ EPRINT((dbp->dbenv,
+ "Page %lu: incorrect next_pgno %lu found in leaf chain (should be %lu)",
+ (u_long)vdp->prev_pgno,
+ (u_long)vdp->next_pgno, (u_long)pip->pgno));
+ isbad = 1;
+ }
+ if (pip->prev_pgno != vdp->prev_pgno) {
+bad_prev: EPRINT((dbp->dbenv,
+ "Page %lu: incorrect prev_pgno %lu found in leaf chain (should be %lu)",
+ (u_long)pip->pgno, (u_long)pip->prev_pgno,
+ (u_long)vdp->prev_pgno));
+ isbad = 1;
+ }
+ }
+ vdp->prev_pgno = pip->pgno;
+ vdp->next_pgno = pip->next_pgno;
+
+ /*
+ * Overflow pages are common to all three leaf types;
+ * traverse the child list, looking for overflows.
*/
if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0)
goto err;
@@ -1360,7 +1448,7 @@ __bam_vrfy_subtree(dbp,
!(LF_ISSET(ST_DUPOK) && !LF_ISSET(ST_DUPSORT))) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Recno leaf page %lu in non-recno tree",
+ "Page %lu: recno leaf page non-recno tree",
(u_long)pgno));
goto done;
}
@@ -1372,7 +1460,7 @@ __bam_vrfy_subtree(dbp,
*/
isbad = 1;
EPRINT((dbp->dbenv,
- "Non-recno leaf page %lu in recno tree",
+ "Page %lu: non-recno leaf page in recno tree",
(u_long)pgno));
goto done;
}
@@ -1389,7 +1477,7 @@ __bam_vrfy_subtree(dbp,
if (!LF_ISSET(ST_DUPOK)) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Duplicates on page %lu in non-dup btree",
+ "Page %lu: duplicates in non-dup btree",
(u_long)pgno));
} else {
/*
@@ -1414,8 +1502,8 @@ __bam_vrfy_subtree(dbp,
}
if ((ret = __bam_vrfy_subtree(
dbp, vdp, child->pgno, NULL,
- NULL, stflags, NULL, NULL,
- NULL)) != 0) {
+ NULL, stflags | ST_TOPLEVEL,
+ NULL, NULL, NULL)) != 0) {
if (ret !=
DB_VERIFY_BAD)
goto err;
@@ -1436,14 +1524,13 @@ __bam_vrfy_subtree(dbp,
if (F_ISSET(pip, VRFY_DUPS_UNSORTED) &&
LF_ISSET(ST_DUPSORT)) {
EPRINT((dbp->dbenv,
- "Unsorted duplicate set at page %lu in sorted-dup database",
+ "Page %lu: unsorted duplicate set in sorted-dup database",
(u_long)pgno));
isbad = 1;
}
}
}
goto leaf;
- break;
case P_IBTREE:
case P_IRECNO:
/* We handle these below. */
@@ -1455,10 +1542,18 @@ __bam_vrfy_subtree(dbp,
* Note that the code at the "done" label assumes that the
* current page is a btree/recno one of some sort; this
* is not the case here, so we goto err.
+ *
+ * If the page is entirely zeroed, its pip->type will be a lie
+ * (we assumed it was a hash page, as they're allowed to be
+ * zeroed); handle this case specially.
*/
- EPRINT((dbp->dbenv,
- "Page %lu is of inappropriate type %lu",
- (u_long)pgno, (u_long)pip->type));
+ if (F_ISSET(pip, VRFY_IS_ALLZEROES))
+ ZEROPG_ERR_PRINT(dbp->dbenv,
+ pgno, "btree or recno page");
+ else
+ EPRINT((dbp->dbenv,
+ "Page %lu: btree or recno page is of inappropriate type %lu",
+ (u_long)pgno, (u_long)pip->type));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -1500,8 +1595,9 @@ __bam_vrfy_subtree(dbp,
relen != child_relen) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Recno page %lu returned bad re_len",
- (u_long)child->pgno));
+ "Page %lu: recno page returned bad re_len %lu",
+ (u_long)child->pgno,
+ (u_long)child_relen));
}
if (relenp)
*relenp = relen;
@@ -1510,10 +1606,8 @@ __bam_vrfy_subtree(dbp,
nrecs += child_nrecs;
if (level != child_level + 1) {
isbad = 1;
- EPRINT((dbp->dbenv, "%s%lu%s%lu%s%lu",
- "Recno level incorrect on page ",
- (u_long)child->pgno, ": got ",
- (u_long)child_level, ", expected ",
+ EPRINT((dbp->dbenv, "Page %lu: recno level incorrect: got %lu, expected %lu",
+ (u_long)child->pgno, (u_long)child_level,
(u_long)(level - 1)));
}
} else if (child->type == V_OVERFLOW &&
@@ -1543,12 +1637,12 @@ __bam_vrfy_subtree(dbp,
* itself, which must sort lower than all entries on its child;
* ri will be the key to its right, which must sort greater.
*/
- if (h == NULL && (ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
for (i = 0; i < pip->entries; i += O_INDX) {
- li = GET_BINTERNAL(h, i);
+ li = GET_BINTERNAL(dbp, h, i);
ri = (i + O_INDX < pip->entries) ?
- GET_BINTERNAL(h, i + O_INDX) : NULL;
+ GET_BINTERNAL(dbp, h, i + O_INDX) : NULL;
/*
* The leftmost key is forcibly sorted less than all entries,
@@ -1578,18 +1672,18 @@ __bam_vrfy_subtree(dbp,
if (li->nrecs != child_nrecs) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Item %lu page %lu has incorrect record count of %lu, should be %lu",
- (u_long)i, (u_long)pgno, (u_long)li->nrecs,
+ "Page %lu: item %lu has incorrect record count of %lu, should be %lu",
+ (u_long)pgno, (u_long)i, (u_long)li->nrecs,
(u_long)child_nrecs));
}
}
if (level != child_level + 1) {
isbad = 1;
- EPRINT((dbp->dbenv, "%s%lu%s%lu%s%lu",
- "Btree level incorrect on page ", (u_long)li->pgno,
- ": got ", (u_long)child_level, ", expected ",
- (u_long)(level - 1)));
+ EPRINT((dbp->dbenv,
+ "Page %lu: Btree level incorrect: got %lu, expected %lu",
+ (u_long)li->pgno,
+ (u_long)child_level, (u_long)(level - 1)));
}
}
@@ -1616,7 +1710,7 @@ done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
* isbad == 0, though, it's now safe to do so, as we've
* traversed any child overflow pages. Do it.
*/
- if (h == NULL && (ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
if ((ret = __bam_vrfy_itemorder(dbp,
vdp, h, pgno, 0, 1, 0, flags)) != 0)
@@ -1625,12 +1719,35 @@ done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
}
/*
+ * It's possible to get to this point with a page that has no
+ * items, but without having detected any sort of failure yet.
+ * Having zero items is legal if it's a leaf--it may be the
+ * root page in an empty tree, or the tree may have been
+ * modified with the DB_REVSPLITOFF flag set (there's no way
+ * to tell from what's on disk). For an internal page,
+ * though, having no items is a problem (all internal pages
+ * must have children).
+ */
+ if (isbad == 0 && ret == 0) {
+ if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+ goto err;
+
+ if (NUM_ENT(h) == 0 && ISINTERNAL(h)) {
+ EPRINT((dbp->dbenv,
+ "Page %lu: internal page is empty and should not be",
+ (u_long)pgno));
+ isbad = 1;
+ goto err;
+ }
+ }
+
+ /*
* Our parent has sent us BINTERNAL pointers to parent records
* so that we can verify our place with respect to them. If it's
* appropriate--we have a default sort function--verify this.
*/
if (isbad == 0 && ret == 0 && !LF_ISSET(DB_NOORDERCHK) && lp != NULL) {
- if (h == NULL && (ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
/*
@@ -1662,7 +1779,7 @@ done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
if (LF_ISSET(ST_RECNUM) && nrecs != pip->rec_cnt && toplevel) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Bad record count on page %lu: got %lu, expected %lu",
+ "Page %lu: bad record count: has %lu records, claims %lu",
(u_long)pgno, (u_long)nrecs, (u_long)pip->rec_cnt));
}
@@ -1676,13 +1793,32 @@ done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
goto err;
if (p != 0) {
isbad = 1;
- EPRINT((dbp->dbenv, "Page %lu linked twice", (u_long)pgno));
+ EPRINT((dbp->dbenv, "Page %lu: linked twice", (u_long)pgno));
} else if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
goto err;
-err: if (h != NULL && (t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
+ if (toplevel)
+ /*
+ * The last page's next_pgno in the leaf chain should have been
+ * PGNO_INVALID.
+ */
+ if (vdp->next_pgno != PGNO_INVALID) {
+ EPRINT((dbp->dbenv, "Page %lu: unterminated leaf chain",
+ (u_long)vdp->prev_pgno));
+ isbad = 1;
+ }
+
+err: if (toplevel) {
+ /* Restore our caller's settings. */
+ vdp->next_pgno = next_pgno;
+ vdp->prev_pgno = prev_pgno;
+ vdp->leaf_type = leaf_type;
+ }
+
+ if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
- if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+ if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
if (cc != NULL && ((t_ret = __db_vrfy_ccclose(cc)) != 0) && ret == 0)
ret = t_ret;
@@ -1720,6 +1856,14 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
F_SET(&dbt, DB_DBT_MALLOC);
ret = 0;
+ /*
+ * Empty pages are sorted correctly by definition. We check
+ * to see whether they ought to be empty elsewhere; leaf
+ * pages legally may be.
+ */
+ if (NUM_ENT(h) == 0)
+ return (0);
+
switch (TYPE(h)) {
case P_IBTREE:
case P_LDUP:
@@ -1760,7 +1904,8 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
} else {
DB_ASSERT(0);
EPRINT((dbp->dbenv,
- "Unknown type for internal record"));
+ "Page %lu: unknown type for internal record",
+ (u_long)PGNO(h)));
return (EINVAL);
}
@@ -1768,17 +1913,17 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
if ((ret = __bam_cmp(dbp, &dbt, h, 0, func, &cmp)) == 0) {
if (cmp > 0) {
EPRINT((dbp->dbenv,
- "First item on page %lu sorted greater than parent entry",
+ "Page %lu: first item on page sorted greater than parent entry",
(u_long)PGNO(h)));
ret = DB_VERIFY_BAD;
}
} else
EPRINT((dbp->dbenv,
- "First item on page %lu had comparison error",
+ "Page %lu: first item on page had comparison error",
(u_long)PGNO(h)));
if (dbt.data != lp->data)
- __os_free(dbt.data, 0);
+ __os_ufree(dbp->dbenv, dbt.data);
if (ret != 0)
return (ret);
}
@@ -1795,7 +1940,8 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
} else {
DB_ASSERT(0);
EPRINT((dbp->dbenv,
- "Unknown type for internal record"));
+ "Page %lu: unknown type for internal record",
+ (u_long)PGNO(h)));
return (EINVAL);
}
@@ -1803,17 +1949,17 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
if ((ret = __bam_cmp(dbp, &dbt, h, last, func, &cmp)) == 0) {
if (cmp < 0) {
EPRINT((dbp->dbenv,
- "Last item on page %lu sorted greater than parent entry",
+ "Page %lu: last item on page sorted greater than parent entry",
(u_long)PGNO(h)));
ret = DB_VERIFY_BAD;
}
} else
EPRINT((dbp->dbenv,
- "Last item on page %lu had comparison error",
+ "Page %lu: last item on page had comparison error",
(u_long)PGNO(h)));
if (dbt.data != rp->data)
- __os_free(dbt.data, 0);
+ __os_ufree(dbp->dbenv, dbt.data);
}
return (ret);
@@ -1843,7 +1989,7 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
DBT dbt, unkdbt;
BKEYDATA *bk;
BOVERFLOW *bo;
- db_indx_t i, beg, end;
+ db_indx_t i, beg, end, *inp;
u_int32_t himark;
u_int8_t *pgmap;
void *ovflbuf;
@@ -1854,24 +2000,25 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
ovflbuf = pgmap = NULL;
err_ret = ret = 0;
+ inp = P_INP(dbp, h);
memset(&dbt, 0, sizeof(DBT));
dbt.flags = DB_DBT_REALLOC;
memset(&unkdbt, 0, sizeof(DBT));
- unkdbt.size = strlen("UNKNOWN") + 1;
+ unkdbt.size = (u_int32_t)(strlen("UNKNOWN") + 1);
unkdbt.data = "UNKNOWN";
/*
* Allocate a buffer for overflow items. Start at one page;
* __db_safe_goff will realloc as needed.
*/
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &ovflbuf)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &ovflbuf)) != 0)
return (ret);
if (LF_ISSET(DB_AGGRESSIVE)) {
if ((ret =
- __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &pgmap)) != 0)
+ __os_malloc(dbp->dbenv, dbp->pgsize, &pgmap)) != 0)
goto err;
memset(pgmap, 0, dbp->pgsize);
}
@@ -1914,7 +2061,7 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
* We only want to print deleted items if
* DB_AGGRESSIVE is set.
*/
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
continue;
@@ -1927,10 +2074,10 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
if (key != NULL &&
(i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
if ((ret = __db_prdbt(key,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
- beg = h->inp[i];
+ beg = inp[i];
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
end = beg + BOVERFLOW_SIZE - 1;
@@ -1958,23 +2105,24 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
(i % P_INDX == 0)) {
/* Not much to do on failure. */
if ((ret = __db_prdbt(&unkdbt, 0, " ",
- handle, callback, 0, NULL)) != 0)
+ handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
}
if ((ret = __db_salvage_duptree(dbp,
vdp, bo->pgno, &dbt, handle, callback,
- flags | SA_SKIPFIRSTKEY)) != 0)
+ flags | SA_SKIPFIRSTKEY)) != 0)
err_ret = ret;
break;
case B_KEYDATA:
- end = ALIGN(beg + bk->len, sizeof(u_int32_t)) - 1;
+ end =
+ ALIGN(beg + bk->len, sizeof(u_int32_t)) - 1;
dbt.data = bk->data;
dbt.size = bk->len;
if ((ret = __db_prdbt(&dbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case B_OVERFLOW:
@@ -1985,11 +2133,11 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
err_ret = ret;
/* We care about err_ret more. */
(void)__db_prdbt(&unkdbt, 0, " ",
- handle, callback, 0, NULL);
+ handle, callback, 0, vdp);
break;
}
if ((ret = __db_prdbt(&dbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
default:
@@ -2020,12 +2168,12 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
* a datum; fix this imbalance by printing an "UNKNOWN".
*/
if (pgtype == P_LBTREE && (i % P_INDX == 1) && ((ret =
- __db_prdbt(&unkdbt, 0, " ", handle, callback, 0, NULL)) != 0))
+ __db_prdbt(&unkdbt, 0, " ", handle, callback, 0, vdp)) != 0))
err_ret = ret;
err: if (pgmap != NULL)
- __os_free(pgmap, 0);
- __os_free(ovflbuf, 0);
+ __os_free(dbp->dbenv, pgmap);
+ __os_free(dbp->dbenv, ovflbuf);
/* Mark this page as done. */
if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
@@ -2061,12 +2209,13 @@ __bam_salvage_walkdupint(dbp, vdp, h, key, handle, callback, flags)
for (i = 0; i < NUM_ENT(h); i++) {
switch (TYPE(h)) {
case P_IBTREE:
- bi = GET_BINTERNAL(h, i);
+ bi = GET_BINTERNAL(dbp, h, i);
if ((t_ret = __db_salvage_duptree(dbp,
vdp, bi->pgno, key, handle, callback, flags)) != 0)
ret = t_ret;
+ break;
case P_IRECNO:
- ri = GET_RINTERNAL(h, i);
+ ri = GET_RINTERNAL(dbp, h, i);
if ((t_ret = __db_salvage_duptree(dbp,
vdp, ri->pgno, key, handle, callback, flags)) != 0)
ret = t_ret;
@@ -2110,11 +2259,13 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
DB *pgset;
{
BINTERNAL *bi;
+ DB_MPOOLFILE *mpf;
PAGE *h;
RINTERNAL *ri;
db_pgno_t current, p;
int err_ret, ret;
+ mpf = dbp->mpf;
h = NULL;
ret = err_ret = 0;
DB_ASSERT(pgset != NULL);
@@ -2123,7 +2274,7 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
err_ret = DB_VERIFY_BAD;
goto err;
}
- if ((ret = memp_fget(dbp->mpf, &current, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &current, 0, &h)) != 0) {
err_ret = ret;
goto err;
}
@@ -2137,10 +2288,10 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
goto err;
}
if (TYPE(h) == P_IBTREE) {
- bi = GET_BINTERNAL(h, 0);
+ bi = GET_BINTERNAL(dbp, h, 0);
current = bi->pgno;
} else { /* P_IRECNO */
- ri = GET_RINTERNAL(h, 0);
+ ri = GET_RINTERNAL(dbp, h, 0);
current = ri->pgno;
}
break;
@@ -2152,7 +2303,7 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
goto err;
}
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
err_ret = ret;
h = NULL;
}
@@ -2163,8 +2314,7 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
*/
traverse:
while (IS_VALID_PGNO(current) && current != PGNO_INVALID) {
- if (h == NULL &&
- (ret = memp_fget(dbp->mpf, &current, 0, &h) != 0)) {
+ if (h == NULL && (ret = mpf->get(mpf, &current, 0, &h)) != 0) {
err_ret = ret;
break;
}
@@ -2184,13 +2334,13 @@ traverse:
goto err;
current = NEXT_PGNO(h);
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
err_ret = ret;
h = NULL;
}
err: if (h != NULL)
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (ret == 0 ? err_ret : ret);
}
@@ -2218,7 +2368,7 @@ __bam_safe_getdata(dbp, h, i, ovflok, dbt, freedbtp)
memset(dbt, 0, sizeof(DBT));
*freedbtp = 0;
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
if (B_TYPE(bk->type) == B_OVERFLOW) {
if (!ovflok)
return (0);
diff --git a/bdb/btree/btree.src b/bdb/btree/btree.src
index a1eba7d7fc7..73f4abac874 100644
--- a/bdb/btree/btree.src
+++ b/bdb/btree/btree.src
@@ -1,13 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: btree.src,v 10.26 2000/12/12 17:40:23 bostic Exp $
+ * $Id: btree.src,v 10.35 2002/04/17 19:02:56 krinsky Exp $
*/
-PREFIX bam
+PREFIX __bam
+DBPRIVATE
INCLUDE #include "db_config.h"
INCLUDE
@@ -15,69 +16,23 @@ INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "btree.h"
-INCLUDE #include "txn.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/btree.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
- * BTREE-pg_alloc: used to record allocating a new page.
- *
- * meta_lsn: the meta-data page's original lsn.
- * page_lsn: the allocated page's original lsn.
- * pgno: the page allocated.
- * next: the next page on the free list.
+ * NOTE: pg_alloc and pg_free have been moved to db.src, where they belong.
*/
-BEGIN pg_alloc 51
-ARG fileid int32_t ld
-POINTER meta_lsn DB_LSN * lu
-POINTER page_lsn DB_LSN * lu
-ARG pgno db_pgno_t lu
-ARG ptype u_int32_t lu
-ARG next db_pgno_t lu
-END
-
-DEPRECATED pg_alloc1 60
-ARG fileid int32_t ld
-POINTER meta_lsn DB_LSN * lu
-POINTER alloc_lsn DB_LSN * lu
-POINTER page_lsn DB_LSN * lu
-ARG pgno db_pgno_t lu
-ARG ptype u_int32_t lu
-ARG next db_pgno_t lu
-END
-
-/*
- * BTREE-pg_free: used to record freeing a page.
- *
- * pgno: the page being freed.
- * meta_lsn: the meta-data page's original lsn.
- * header: the header from the free'd page.
- * next: the previous next pointer on the metadata page.
- */
-BEGIN pg_free 52
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-POINTER meta_lsn DB_LSN * lu
-DBT header DBT s
-ARG next db_pgno_t lu
-END
-
-DEPRECATED pg_free1 61
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-POINTER meta_lsn DB_LSN * lu
-POINTER alloc_lsn DB_LSN * lu
-DBT header DBT s
-ARG next db_pgno_t lu
-END
/*
* BTREE-split: used to log a page split.
@@ -89,46 +44,21 @@ END
* indx: the number of entries that went to the left page.
* npgno: the next page number
* nlsn: the next page's original LSN (or 0 if no next page).
- * pg: the split page's contents before the split.
- */
-DEPRECATED split1 53
-ARG fileid int32_t ld
-ARG left db_pgno_t lu
-POINTER llsn DB_LSN * lu
-ARG right db_pgno_t lu
-POINTER rlsn DB_LSN * lu
-ARG indx u_int32_t lu
-ARG npgno db_pgno_t lu
-POINTER nlsn DB_LSN * lu
-DBT pg DBT s
-END
-
-/*
- * BTREE-split: used to log a page split.
- *
- * left: the page number for the low-order contents.
- * llsn: the left page's original LSN.
- * right: the page number for the high-order contents.
- * rlsn: the right page's original LSN.
- * indx: the number of entries that went to the left page.
- * npgno: the next page number
- * npgno: the next page number
- * nlsn: the next page's original LSN (or 0 if no next page).
* root_pgno: the root page number
* pg: the split page's contents before the split.
* opflags: SPL_NRECS: if splitting a tree that maintains a record count.
*/
BEGIN split 62
-ARG fileid int32_t ld
-ARG left db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK left db_pgno_t lu
POINTER llsn DB_LSN * lu
-ARG right db_pgno_t lu
+WRLOCK right db_pgno_t lu
POINTER rlsn DB_LSN * lu
ARG indx u_int32_t lu
ARG npgno db_pgno_t lu
POINTER nlsn DB_LSN * lu
-ARG root_pgno db_pgno_t lu
-DBT pg DBT s
+WRLOCKNZ root_pgno db_pgno_t lu
+PGDBT pg DBT s
ARG opflags u_int32_t lu
END
@@ -137,34 +67,16 @@ END
*
* pgno: the page number of the page copied over the root.
* pgdbt: the page being copied on the root page.
- * nrec: the tree's record count.
- * rootent: last entry on the root page.
- * rootlsn: the root page's original lsn.
- */
-DEPRECATED rsplit1 54
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-DBT pgdbt DBT s
-ARG nrec db_pgno_t lu
-DBT rootent DBT s
-POINTER rootlsn DB_LSN * lu
-END
-
-/*
- * BTREE-rsplit: used to log a reverse-split
- *
- * pgno: the page number of the page copied over the root.
- * pgdbt: the page being copied on the root page.
* root_pgno: the root page number.
* nrec: the tree's record count.
* rootent: last entry on the root page.
* rootlsn: the root page's original lsn.
*/
BEGIN rsplit 63
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-DBT pgdbt DBT s
-ARG root_pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
+PGDBT pgdbt DBT s
+WRLOCK root_pgno db_pgno_t lu
ARG nrec db_pgno_t lu
DBT rootent DBT s
POINTER rootlsn DB_LSN * lu
@@ -180,8 +92,8 @@ END
* is_insert: 0 if a delete, 1 if an insert.
*/
BEGIN adj 55
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG indx_copy u_int32_t lu
@@ -198,8 +110,8 @@ END
* opflags: CAD_UPDATEROOT: if root page count was adjusted.
*/
BEGIN cadjust 56
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG adjust int32_t ld
@@ -214,8 +126,8 @@ END
* indx: the index to be deleted.
*/
BEGIN cdel 57
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
END
@@ -230,8 +142,8 @@ END
* duplicate: the prefix of the replacement that matches the original.
*/
BEGIN repl 58
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG isdeleted u_int32_t lu
@@ -245,9 +157,9 @@ END
* BTREE-root: log the assignment of a root btree page.
*/
BEGIN root 59
-ARG fileid int32_t ld
-ARG meta_pgno db_pgno_t lu
-ARG root_pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK meta_pgno db_pgno_t lu
+WRLOCK root_pgno db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
END
@@ -260,7 +172,7 @@ END
*/
BEGIN curadj 64
/* Fileid of db affected. */
-ARG fileid int32_t ld
+DB fileid int32_t ld
/* Which adjustment. */
ARG mode db_ca_mode ld
/* Page entry is from. */
@@ -284,7 +196,7 @@ END
*/
BEGIN rcuradj 65
/* Fileid of db affected. */
-ARG fileid int32_t ld
+DB fileid int32_t ld
/* Which adjustment. */
ARG mode ca_recno_arg ld
/* Root page number. */
diff --git a/bdb/build_vxworks/BerkeleyDB.wpj b/bdb/build_vxworks/BerkeleyDB.wpj
deleted file mode 100644
index fa8aa61c14e..00000000000
--- a/bdb/build_vxworks/BerkeleyDB.wpj
+++ /dev/null
@@ -1,6066 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_BUILDRULE
-BerkeleyDB.out
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -O0 \
- -I$(PRJ_DIR) \
- -I/export/home/db/include \
- -DDIAGNOSTIC \
- -DDEBUG \
- -DHAVE_RPC
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCdebug_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_BUILDRULE
-BerkeleyDB.out
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_CFLAGS
--mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -O2 \
- -I$(PRJ_DIR) \
- -I/export/home/db/include \
- -DHAVE_RPC
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUM_RPCnodebug_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_BUILDRULE
-BerkeleyDB.out
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -O0 \
- -I$(PRJ_DIR) \
- -I/export/home/db/include \
- -DDIAGNOSTIC \
- -DDEBUG
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUM_debug_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_BUILDRULE
-BerkeleyDB.out
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_CFLAGS
--mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -O2 \
- -I$(PRJ_DIR) \
- -I/export/home/db/include
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUM_nodebug_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_BerkeleyDB.out
-
-<END>
-
-<BEGIN> BUILD_RULE_BerkeleyDB_sim.out
-
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/BerkeleyDB.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS \
- -O2 \
- -I$(PRJ_DIR) \
- -I/export/home/db/include
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUM_RPCdebug
-<END>
-
-<BEGIN> BUILD__LIST
-PENTIUM_nodebug \
- PENTIUM_RPCdebug \
- PENTIUM_RPCnodebug \
- PENTIUM_debug \
- SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_compare.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_compare.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_compare.c_objects
-bt_compare.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_compare.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_conv.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_conv.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_conv.c_objects
-bt_conv.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_conv.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_curadj.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_curadj.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_curadj.c_objects
-bt_curadj.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_curadj.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_cursor.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_cursor.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_cursor.c_objects
-bt_cursor.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_cursor.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_delete.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_delete.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_delete.c_objects
-bt_delete.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_delete.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_method.c_objects
-bt_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_open.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_open.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_open.c_objects
-bt_open.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_open.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_put.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_put.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_put.c_objects
-bt_put.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_put.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rec.c_objects
-bt_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_reclaim.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_reclaim.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_reclaim.c_objects
-bt_reclaim.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_reclaim.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_recno.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_recno.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_recno.c_objects
-bt_recno.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_recno.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rsearch.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rsearch.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rsearch.c_objects
-bt_rsearch.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_rsearch.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_search.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_search.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_search.c_objects
-bt_search.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_search.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_split.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_split.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_split.c_objects
-bt_split.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_split.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_stat.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_stat.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_stat.c_objects
-bt_stat.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_stat.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_upgrade.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_upgrade.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_upgrade.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_upgrade.c_objects
-bt_upgrade.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_upgrade.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_verify.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_verify.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_verify.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_verify.c_objects
-bt_verify.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/bt_verify.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/btree_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/btree_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/btree_auto.c_objects
-btree_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/btree/btree_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/getopt.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/getopt.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/getopt.c_objects
-getopt.o
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/getopt.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/snprintf.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/snprintf.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/snprintf.c_objects
-snprintf.o
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/snprintf.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/strcasecmp.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/strcasecmp.c_dependencies
-$(PRJ_DIR)/db_config.h
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/strcasecmp.c_objects
-strcasecmp.o
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/strcasecmp.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/vsnprintf.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/vsnprintf.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/vsnprintf.c_objects
-vsnprintf.o
-<END>
-
-<BEGIN> FILE_/export/home/db/clib/vsnprintf.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_byteorder.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_byteorder.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_byteorder.c_objects
-db_byteorder.o
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_byteorder.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_err.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_err.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/clib_ext.h \
- /export/home/db/include/db_auto.h
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_err.c_objects
-db_err.o
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_err.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_getlong.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_getlong.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/clib_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_getlong.c_objects
-db_getlong.o
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_getlong.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_log2.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_log2.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_log2.c_objects
-db_log2.o
-<END>
-
-<BEGIN> FILE_/export/home/db/common/db_log2.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_log.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_log.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_log.c_objects
-util_log.o
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_log.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_sig.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_sig.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_sig.c_objects
-util_sig.o
-<END>
-
-<BEGIN> FILE_/export/home/db/common/util_sig.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_auto.c_objects
-crdel_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_rec.c_objects
-crdel_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/crdel_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db.c_objects
-db.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_am.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_am.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_am.c_objects
-db_am.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_am.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_auto.c_objects
-db_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_cam.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_cam.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_cam.c_objects
-db_cam.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_cam.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_conv.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_conv.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_conv.c_objects
-db_conv.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_conv.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dispatch.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dispatch.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dispatch.c_objects
-db_dispatch.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dispatch.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dup.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dup.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dup.c_objects
-db_dup.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_dup.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_iface.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_iface.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_iface.c_objects
-db_iface.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_iface.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_join.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_join.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_join.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_join.c_objects
-db_join.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_join.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_meta.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_meta.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_meta.c_objects
-db_meta.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_meta.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_method.c_objects
-db_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_overflow.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_overflow.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_verify.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_overflow.c_objects
-db_overflow.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_overflow.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_pr.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_pr.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/db_verify.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_pr.c_objects
-db_pr.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_pr.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_rec.c_objects
-db_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_reclaim.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_reclaim.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_reclaim.c_objects
-db_reclaim.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_reclaim.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_ret.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_ret.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_ret.c_objects
-db_ret.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_ret.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg.c_objects
-db_upg.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg_opd.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg_opd.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg_opd.c_objects
-db_upg_opd.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_upg_opd.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfy.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfy.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/db_verify.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfy.c_objects
-db_vrfy.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfy.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfyutil.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfyutil.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_verify.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfyutil.c_objects
-db_vrfyutil.o
-<END>
-
-<BEGIN> FILE_/export/home/db/db/db_vrfyutil.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_salloc.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_salloc.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_salloc.c_objects
-db_salloc.o
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_salloc.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_shash.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_shash.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_shash.c_objects
-db_shash.o
-<END>
-
-<BEGIN> FILE_/export/home/db/env/db_shash.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_method.c_objects
-env_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_open.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_open.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/clib_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_open.c_objects
-env_open.o
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_open.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_recover.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_recover.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_recover.c_objects
-env_recover.o
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_recover.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_region.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_region.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_region.c_objects
-env_region.o
-<END>
-
-<BEGIN> FILE_/export/home/db/env/env_region.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash.c_objects
-hash.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_auto.c_objects
-hash_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_conv.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_conv.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_conv.c_objects
-hash_conv.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_conv.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_dup.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_dup.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_dup.c_objects
-hash_dup.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_dup.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_func.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_func.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_func.c_objects
-hash_func.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_func.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_meta.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_meta.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_meta.c_objects
-hash_meta.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_meta.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_method.c_objects
-hash_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_page.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_page.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_page.c_objects
-hash_page.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_page.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_rec.c_objects
-hash_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_reclaim.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_reclaim.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_reclaim.c_objects
-hash_reclaim.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_reclaim.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_stat.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_stat.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_stat.c_objects
-hash_stat.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_stat.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_upgrade.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_upgrade.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_upgrade.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_upgrade.c_objects
-hash_upgrade.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_upgrade.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_verify.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_verify.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_verify.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_verify.c_objects
-hash_verify.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hash/hash_verify.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/hsearch/hsearch.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/hsearch/hsearch.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/hsearch/hsearch.c_objects
-hsearch.o
-<END>
-
-<BEGIN> FILE_/export/home/db/hsearch/hsearch.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/include/tcl_db.h_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock.c_objects
-lock.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_conflict.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_conflict.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_conflict.c_objects
-lock_conflict.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_conflict.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_deadlock.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_deadlock.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_deadlock.c_objects
-lock_deadlock.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_deadlock.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_method.c_objects
-lock_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_region.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_region.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_region.c_objects
-lock_region.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_region.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_stat.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_stat.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_stat.c_objects
-lock_stat.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_stat.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_util.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_util.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_util.c_objects
-lock_util.o
-<END>
-
-<BEGIN> FILE_/export/home/db/lock/lock_util.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log.c_objects
-log.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_archive.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_archive.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/clib_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_archive.c_objects
-log_archive.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_archive.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_auto.c_objects
-log_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_compare.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_compare.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_compare.c_objects
-log_compare.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_compare.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_findckp.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_findckp.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_findckp.c_objects
-log_findckp.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_findckp.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_get.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_get.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_get.c_objects
-log_get.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_get.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_method.c_objects
-log_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_put.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_put.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/hash.h \
- /export/home/db/include/hash_auto.h \
- /export/home/db/include/hash_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/clib_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_put.c_objects
-log_put.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_put.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_rec.c_objects
-log_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_register.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_register.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_register.c_objects
-log_register.o
-<END>
-
-<BEGIN> FILE_/export/home/db/log/log_register.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_alloc.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_alloc.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_alloc.c_objects
-mp_alloc.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_alloc.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_bh.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_bh.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/db_page.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_bh.c_objects
-mp_bh.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_bh.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fget.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fget.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fget.c_objects
-mp_fget.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fget.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fopen.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fopen.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fopen.c_objects
-mp_fopen.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fopen.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fput.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fput.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fput.c_objects
-mp_fput.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fput.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fset.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fset.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fset.c_objects
-mp_fset.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_fset.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_method.c_objects
-mp_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_region.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_region.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_region.c_objects
-mp_region.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_region.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_register.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_register.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_register.c_objects
-mp_register.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_register.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_stat.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_stat.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_stat.c_objects
-mp_stat.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_stat.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_sync.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_sync.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_sync.c_objects
-mp_sync.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_sync.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_trickle.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_trickle.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_trickle.c_objects
-mp_trickle.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mp/mp_trickle.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mut_tas.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mut_tas.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mut_tas.c_objects
-mut_tas.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mut_tas.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mutex.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mutex.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mutex.c_objects
-mutex.o
-<END>
-
-<BEGIN> FILE_/export/home/db/mutex/mutex.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_alloc.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_alloc.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_alloc.c_objects
-os_alloc.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_alloc.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_dir.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_dir.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_dir.c_objects
-os_dir.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_dir.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_errno.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_errno.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_errno.c_objects
-os_errno.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_errno.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fid.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fid.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fid.c_objects
-os_fid.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fid.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fsync.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fsync.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fsync.c_objects
-os_fsync.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_fsync.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_handle.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_handle.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_handle.c_objects
-os_handle.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_handle.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_method.c_objects
-os_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_oflags.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_oflags.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_oflags.c_objects
-os_oflags.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_oflags.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_open.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_open.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_open.c_objects
-os_open.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_open.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_region.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_region.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_region.c_objects
-os_region.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_region.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rename.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rename.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rename.c_objects
-os_rename.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rename.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_root.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_root.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_root.c_objects
-os_root.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_root.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rpath.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rpath.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rpath.c_objects
-os_rpath.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rpath.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rw.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rw.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rw.c_objects
-os_rw.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_rw.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_seek.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_seek.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_seek.c_objects
-os_seek.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_seek.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_sleep.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_sleep.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_sleep.c_objects
-os_sleep.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_sleep.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_spin.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_spin.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_spin.c_objects
-os_spin.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_spin.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_stat.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_stat.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_stat.c_objects
-os_stat.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_stat.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_tmpdir.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_tmpdir.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_tmpdir.c_objects
-os_tmpdir.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_tmpdir.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_unlink.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_unlink.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/os_jump.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_unlink.c_objects
-os_unlink.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os/os_unlink.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_abs.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_abs.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_abs.c_objects
-os_abs.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_abs.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_finit.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_finit.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_finit.c_objects
-os_finit.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_finit.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_map.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_map.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_map.c_objects
-os_map.o
-<END>
-
-<BEGIN> FILE_/export/home/db/os_vxworks/os_map.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam.c_objects
-qam.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_auto.c_objects
-qam_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_conv.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_conv.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_conv.c_objects
-qam_conv.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_conv.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_files.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_files.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/btree.h \
- /export/home/db/include/btree_auto.h \
- /export/home/db/include/btree_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_files.c_objects
-qam_files.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_files.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_method.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_method.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_method.c_objects
-qam_method.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_method.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_open.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_open.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_open.c_objects
-qam_open.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_open.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_rec.c_objects
-qam_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_stat.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_stat.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_stat.c_objects
-qam_stat.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_stat.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_upgrade.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_upgrade.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_swap.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/db_upgrade.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_upgrade.c_objects
-qam_upgrade.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_upgrade.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_verify.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_verify.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_verify.h \
- /export/home/db/include/qam.h \
- /export/home/db/include/qam_auto.h \
- /export/home/db/include/qam_ext.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_verify.c_objects
-qam_verify.o
-<END>
-
-<BEGIN> FILE_/export/home/db/qam/qam_verify.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/client.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/client.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/client.c_objects
-client.o
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/client.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/db_server_clnt.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/db_server_clnt.c_dependencies
-$(PRJ_DIR)/db_config.h /export/home/db/include/db_server.h
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/db_server_clnt.c_objects
-db_server_clnt.o
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/db_server_clnt.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/mp.h \
- /export/home/db/include/mp_ext.h \
- /export/home/db/include/rpc_client_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/gen_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client.c_objects
-gen_client.o
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client_ret.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client_ret.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client_ret.c_objects
-gen_client_ret.o
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_client/gen_client_ret.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_server/db_server_xdr.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_server/db_server_xdr.c_dependencies
-$(PRJ_DIR)/db_config.h /export/home/db/include/db_server.h
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_server/db_server_xdr.c_objects
-db_server_xdr.o
-<END>
-
-<BEGIN> FILE_/export/home/db/rpc_server/db_server_xdr.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_shash.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/lock.h \
- /export/home/db/include/lock_ext.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn.c_objects
-txn.o
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_auto.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_auto.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_auto.c_objects
-txn_auto.o
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_auto.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_rec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_rec.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_rec.c_objects
-txn_rec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_rec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_region.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_region.c_dependencies
-$(PRJ_DIR)/db_config.h \
- /export/home/db/include/db_server.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h \
- /export/home/db/include/gen_client_ext.h \
- /export/home/db/include/rpc_client_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_region.c_objects
-txn_region.o
-<END>
-
-<BEGIN> FILE_/export/home/db/txn/txn_region.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/db_page.h \
- /export/home/db/include/log.h \
- /export/home/db/include/log_auto.h \
- /export/home/db/include/log_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/db_am.h \
- /export/home/db/include/db_dispatch.h \
- /export/home/db/include/db_auto.h \
- /export/home/db/include/crdel_auto.h \
- /export/home/db/include/db_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa.c_objects
-xa.o
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_db.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_db.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/xa_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_db.c_objects
-xa_db.o
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_db.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_map.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_map.c_dependencies
-$(PRJ_DIR)/db_config.h \
- $(PRJ_DIR)/db_int.h \
- $(PRJ_DIR)/db.h \
- /export/home/db/include/queue.h \
- /export/home/db/include/shqueue.h \
- /export/home/db/include/debug.h \
- /export/home/db/include/mutex.h \
- /export/home/db/include/region.h \
- /export/home/db/include/mutex_ext.h \
- /export/home/db/include/env_ext.h \
- /export/home/db/include/os.h \
- /export/home/db/include/os_ext.h \
- /export/home/db/include/common_ext.h \
- /export/home/db/include/txn.h \
- /export/home/db/include/xa.h \
- /export/home/db/include/txn_auto.h \
- /export/home/db/include/txn_ext.h \
- /export/home/db/include/xa_ext.h
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_map.c_objects
-xa_map.o
-<END>
-
-<BEGIN> FILE_/export/home/db/xa/xa_map.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/hsearch/hsearch.c \
- /export/home/db/mp/mp_trickle.c \
- /export/home/db/mp/mp_bh.c \
- /export/home/db/mp/mp_fget.c \
- /export/home/db/mp/mp_fopen.c \
- /export/home/db/mp/mp_fput.c \
- /export/home/db/mp/mp_fset.c \
- /export/home/db/mp/mp_method.c \
- /export/home/db/mp/mp_region.c \
- /export/home/db/mp/mp_register.c \
- /export/home/db/mp/mp_stat.c \
- /export/home/db/mp/mp_sync.c \
- /export/home/db/mp/mp_alloc.c \
- /export/home/db/db/crdel_rec.c \
- /export/home/db/db/db.c \
- /export/home/db/db/db_am.c \
- /export/home/db/db/db_auto.c \
- /export/home/db/db/db_cam.c \
- /export/home/db/db/db_conv.c \
- /export/home/db/db/db_dispatch.c \
- /export/home/db/db/db_dup.c \
- /export/home/db/db/db_iface.c \
- /export/home/db/db/db_join.c \
- /export/home/db/db/db_meta.c \
- /export/home/db/db/db_method.c \
- /export/home/db/db/db_overflow.c \
- /export/home/db/db/db_pr.c \
- /export/home/db/db/db_rec.c \
- /export/home/db/db/db_reclaim.c \
- /export/home/db/db/db_ret.c \
- /export/home/db/db/crdel_auto.c \
- /export/home/db/clib/getopt.c \
- /export/home/db/clib/snprintf.c \
- /export/home/db/clib/strcasecmp.c \
- /export/home/db/os/os_unlink.c \
- /export/home/db/os/os_alloc.c \
- /export/home/db/os/os_dir.c \
- /export/home/db/os/os_errno.c \
- /export/home/db/os/os_fid.c \
- /export/home/db/os/os_fsync.c \
- /export/home/db/os/os_handle.c \
- /export/home/db/os/os_method.c \
- /export/home/db/os/os_oflags.c \
- /export/home/db/os/os_open.c \
- /export/home/db/os/os_region.c \
- /export/home/db/os/os_rename.c \
- /export/home/db/os/os_root.c \
- /export/home/db/os/os_rpath.c \
- /export/home/db/os/os_rw.c \
- /export/home/db/os/os_seek.c \
- /export/home/db/os/os_spin.c \
- /export/home/db/os/os_stat.c \
- /export/home/db/os/os_tmpdir.c \
- /export/home/db/qam/qam_upgrade.c \
- /export/home/db/qam/qam_auto.c \
- /export/home/db/qam/qam_conv.c \
- /export/home/db/qam/qam_method.c \
- /export/home/db/qam/qam_open.c \
- /export/home/db/qam/qam_rec.c \
- /export/home/db/qam/qam_stat.c \
- /export/home/db/qam/qam.c \
- /export/home/db/hash/hash_upgrade.c \
- /export/home/db/hash/hash_auto.c \
- /export/home/db/hash/hash_conv.c \
- /export/home/db/hash/hash_dup.c \
- /export/home/db/hash/hash_func.c \
- /export/home/db/hash/hash_meta.c \
- /export/home/db/hash/hash_method.c \
- /export/home/db/hash/hash_page.c \
- /export/home/db/hash/hash_rec.c \
- /export/home/db/hash/hash_reclaim.c \
- /export/home/db/hash/hash_stat.c \
- /export/home/db/hash/hash.c \
- /export/home/db/xa/xa_map.c \
- /export/home/db/xa/xa_db.c \
- /export/home/db/xa/xa.c \
- /export/home/db/btree/btree_auto.c \
- /export/home/db/btree/bt_conv.c \
- /export/home/db/btree/bt_curadj.c \
- /export/home/db/btree/bt_cursor.c \
- /export/home/db/btree/bt_delete.c \
- /export/home/db/btree/bt_method.c \
- /export/home/db/btree/bt_open.c \
- /export/home/db/btree/bt_put.c \
- /export/home/db/btree/bt_rec.c \
- /export/home/db/btree/bt_reclaim.c \
- /export/home/db/btree/bt_recno.c \
- /export/home/db/btree/bt_rsearch.c \
- /export/home/db/btree/bt_search.c \
- /export/home/db/btree/bt_split.c \
- /export/home/db/btree/bt_stat.c \
- /export/home/db/btree/bt_upgrade.c \
- /export/home/db/btree/bt_compare.c \
- /export/home/db/common/db_log2.c \
- /export/home/db/common/db_err.c \
- /export/home/db/common/db_getlong.c \
- /export/home/db/common/db_byteorder.c \
- /export/home/db/env/env_region.c \
- /export/home/db/env/db_shash.c \
- /export/home/db/env/env_method.c \
- /export/home/db/env/env_open.c \
- /export/home/db/env/env_recover.c \
- /export/home/db/env/db_salloc.c \
- /export/home/db/lock/lock_util.c \
- /export/home/db/lock/lock_conflict.c \
- /export/home/db/lock/lock_deadlock.c \
- /export/home/db/lock/lock_region.c \
- /export/home/db/lock/lock.c \
- /export/home/db/txn/txn_region.c \
- /export/home/db/txn/txn_auto.c \
- /export/home/db/txn/txn_rec.c \
- /export/home/db/txn/txn.c \
- /export/home/db/log/log_register.c \
- /export/home/db/log/log_archive.c \
- /export/home/db/log/log_auto.c \
- /export/home/db/log/log_compare.c \
- /export/home/db/log/log_findckp.c \
- /export/home/db/log/log_get.c \
- /export/home/db/log/log_method.c \
- /export/home/db/log/log_put.c \
- /export/home/db/log/log_rec.c \
- /export/home/db/log/log.c \
- /export/home/db/mutex/mut_tas.c \
- /export/home/db/mutex/mutex.c \
- /export/home/db/clib/vsnprintf.c \
- /export/home/db/common/util_log.c \
- /export/home/db/common/util_sig.c \
- /export/home/db/os/os_sleep.c \
- /export/home/db/btree/bt_verify.c \
- /export/home/db/hash/hash_verify.c \
- /export/home/db/qam/qam_verify.c \
- /export/home/db/db/db_upg_opd.c \
- /export/home/db/rpc_client/gen_client_ret.c \
- /export/home/db/rpc_client/db_server_clnt.c \
- /export/home/db/rpc_client/gen_client.c \
- /export/home/db/rpc_client/client.c \
- /export/home/db/include/tcl_db.h \
- /export/home/db/rpc_server/db_server_xdr.c \
- /export/home/db/os_vxworks/os_map.c \
- /export/home/db/db/db_vrfy.c \
- /export/home/db/db/db_upg.c \
- /export/home/db/db/db_vrfyutil.c \
- /export/home/db/os_vxworks/os_finit.c \
- /export/home/db/os_vxworks/os_abs.c \
- /export/home/db/lock/lock_method.c \
- /export/home/db/lock/lock_stat.c \
- /export/home/db/qam/qam_files.c
-<END>
-
-<BEGIN> userComments
-BerkeleyDB
-<END>
-
diff --git a/bdb/build_vxworks/BerkeleyDB.wsp b/bdb/build_vxworks/BerkeleyDB.wsp
index cffcf00dec9..ce2e71b0eb3 100644
--- a/bdb/build_vxworks/BerkeleyDB.wsp
+++ b/bdb/build_vxworks/BerkeleyDB.wsp
@@ -10,12 +10,17 @@ Workspace
<BEGIN> projectList
$(PRJ_DIR)/BerkeleyDB.wpj \
- $(PRJ_DIR)/ex_access/ex_access.wpj \
- $(PRJ_DIR)/ex_btrec/ex_btrec.wpj \
- $(PRJ_DIR)/ex_env/ex_env.wpj \
- $(PRJ_DIR)/ex_mpool/ex_mpool.wpj \
- $(PRJ_DIR)/ex_tpcb/ex_tpcb.wpj \
- $(PRJ_DIR)/ex_dbclient/ex_dbclient.wpj
+ $(PRJ_DIR)/db_archive/db_archive.wpj \
+ $(PRJ_DIR)/db_checkpoint/db_checkpoint.wpj \
+ $(PRJ_DIR)/db_deadlock/db_deadlock.wpj \
+ $(PRJ_DIR)/db_dump/db_dump.wpj \
+ $(PRJ_DIR)/db_load/db_load.wpj \
+ $(PRJ_DIR)/db_printlog/db_printlog.wpj \
+ $(PRJ_DIR)/db_recover/db_recover.wpj \
+ $(PRJ_DIR)/db_stat/db_stat.wpj \
+ $(PRJ_DIR)/db_upgrade/db_upgrade.wpj \
+ $(PRJ_DIR)/db_verify/db_verify.wpj \
+ $(PRJ_DIR)/dbdemo/dbdemo.wpj
<END>
<BEGIN> userComments
diff --git a/bdb/build_vxworks/db_config.h b/bdb/build_vxworks/db_config.h
deleted file mode 100644
index cccfc4a7cf6..00000000000
--- a/bdb/build_vxworks/db_config.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * $Id: db_config.h,v 1.4 2000/12/12 18:39:26 bostic Exp $
- */
-
-/* Define if building VxWorks */
-#define HAVE_VXWORKS 1
-
-/* Define to empty if the keyword does not work. */
-/* #undef const */
-
-/* Define if your struct stat has st_blksize. */
-#define HAVE_ST_BLKSIZE 1
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef mode_t */
-
-/* Define to `long' if <sys/types.h> doesn't define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef pid_t */
-
-/* Define to `unsigned' if <sys/types.h> doesn't define. */
-/* #undef size_t */
-
-/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-/* #undef STAT_MACROS_BROKEN */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if you can safely include both <sys/time.h> and <time.h>. */
-/* #undef TIME_WITH_SYS_TIME */
-
-/* !!!
- * WORDS_BIGENDIAN is the ONLY option in this file that may be edited
- * for VxWorks.
- *
- * The user must set this according to VxWork's target arch. We use an
- * x86 (little-endian) target.
- */
-/* Define if your processor stores words with the most significant
- byte first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
-
-/* !!!
- * The CONFIG_TEST option may be added using the Tornado project build.
- * DO NOT modify it here.
- */
-/* Define if you are building a version for running the test suite. */
-/* #undef CONFIG_TEST */
-
-/* !!!
- * The DEBUG option may be added using the Tornado project build.
- * DO NOT modify it here.
- */
-/* Define if you want a debugging version. */
-/* #undef DEBUG */
-
-/* Define if you want a version that logs read operations. */
-/* #undef DEBUG_ROP */
-
-/* Define if you want a version that logs write operations. */
-/* #undef DEBUG_WOP */
-
-/* !!!
- * The DIAGNOSTIC option may be added using the Tornado project build.
- * DO NOT modify it here.
- */
-/* Define if you want a version with run-time diagnostic checking. */
-/* #undef DIAGNOSTIC */
-
-/* Define if you want to mask harmless unitialized memory read/writes. */
-/* #undef UMRW */
-
-/* Define if fcntl/F_SETFD denies child access to file descriptors. */
-/* #undef HAVE_FCNTL_F_SETFD */
-
-/* Define if building big-file environment (e.g., AIX, HP/UX, Solaris). */
-/* #undef HAVE_FILE_OFFSET_BITS */
-
-/* Mutex possibilities. */
-/* #undef HAVE_MUTEX_68K_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_AIX_CHECK_LOCK */
-/* #undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_HPPA_MSEM_INIT */
-/* #undef HAVE_MUTEX_IA64_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_MACOS */
-/* #undef HAVE_MUTEX_MSEM_INIT */
-/* #undef HAVE_MUTEX_PPC_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_PTHREADS */
-/* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
-/* #undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY */
-/* #undef HAVE_MUTEX_SEMA_INIT */
-/* #undef HAVE_MUTEX_SGI_INIT_LOCK */
-/* #undef HAVE_MUTEX_SOLARIS_LOCK_TRY */
-/* #undef HAVE_MUTEX_SOLARIS_LWP */
-/* #undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY */
-#define HAVE_MUTEX_THREADS 1
-/* #undef HAVE_MUTEX_UI_THREADS */
-/* #undef HAVE_MUTEX_UTS_CC_ASSEMBLY */
-/* #undef HAVE_MUTEX_VMS */
-#define HAVE_MUTEX_VXWORKS 1
-/* #undef HAVE_MUTEX_WIN16 */
-/* #undef HAVE_MUTEX_WIN32 */
-/* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
-
-/* Define if building on QNX. */
-/* #undef HAVE_QNX */
-
-/* !!!
- * The HAVE_RPC option may be added using the Tornado project build.
- * DO NOT modify it here.
- */
-/* Define if building RPC client/server. */
-/* #undef HAVE_RPC */
-
-/* Define if your sprintf returns a pointer, not a length. */
-/* #undef SPRINTF_RET_CHARPNT */
-
-/* Define if you have the getcwd function. */
-#define HAVE_GETCWD 1
-
-/* Define if you have the getopt function. */
-/* #undef HAVE_GETOPT */
-
-/* Define if you have the getuid function. */
-/* #undef HAVE_GETUID */
-
-/* Define if you have the memcmp function. */
-#define HAVE_MEMCMP 1
-
-/* Define if you have the memcpy function. */
-#define HAVE_MEMCPY 1
-
-/* Define if you have the memmove function. */
-#define HAVE_MEMMOVE 1
-
-/* Define if you have the mlock function. */
-#define HAVE_MLOCK 1
-
-/* Define if you have the mmap function. */
-/* #undef HAVE_MMAP */
-
-/* Define if you have the munlock function. */
-#define HAVE_MUNLOCK 1
-
-/* Define if you have the munmap function. */
-/* #undef HAVE_MUNMAP */
-
-/* Define if you have the pread function. */
-/* #undef HAVE_PREAD */
-
-/* Define if you have the pstat_getdynamic function. */
-/* #undef HAVE_PSTAT_GETDYNAMIC */
-
-/* Define if you have the pwrite function. */
-/* #undef HAVE_PWRITE */
-
-/* Define if you have the qsort function. */
-#define HAVE_QSORT 1
-
-/* Define if you have the raise function. */
-#define HAVE_RAISE 1
-
-/* Define if you have the sched_yield function. */
-#define HAVE_SCHED_YIELD 1
-
-/* Define if you have the select function. */
-#define HAVE_SELECT 1
-
-/* Define if you have the shmget function. */
-/* #undef HAVE_SHMGET */
-
-/* Define if you have the snprintf function. */
-/* #undef HAVE_SNPRINTF */
-
-/* Define if you have the strcasecmp function. */
-/* #undef HAVE_STRCASECMP */
-
-/* Define if you have the strerror function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have the strtoul function. */
-#define HAVE_STRTOUL 1
-
-/* Define if you have the sysconf function. */
-/* #undef HAVE_SYSCONF */
-
-/* Define if you have the vsnprintf function. */
-/* #undef HAVE_VSNPRINTF */
-
-/* Define if you have the yield function. */
-/* #undef HAVE_YIELD */
-
-/* Define if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H 1
-
-/* Define if you have the <ndir.h> header file. */
-/* #undef HAVE_NDIR_H */
-
-/* Define if you have the <sys/dir.h> header file. */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define if you have the <sys/ndir.h> header file. */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define if you have the <sys/select.h> header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define if you have the <sys/time.h> header file. */
-/* #undef HAVE_SYS_TIME_H */
-
-/* Define if you have the nsl library (-lnsl). */
-/* #undef HAVE_LIBNSL */
-
-/*
- * !!!
- * The following is not part of the automatic configuration setup, but
- * provides necessary VxWorks information.
- */
-#include "vxWorks.h"
-
-/*
- * VxWorks does not have getpid().
- */
-#define getpid() taskIdSelf()
-
-/*
- * Don't step on the namespace. Other libraries may have their own
- * implementations of these functions, we don't want to use their
- * implementations or force them to use ours based on the load order.
- */
-#ifndef HAVE_GETCWD
-#define getcwd __db_Cgetcwd
-#endif
-#ifndef HAVE_GETOPT
-#define getopt __db_Cgetopt
-#endif
-#ifndef HAVE_MEMCMP
-#define memcmp __db_Cmemcmp
-#endif
-#ifndef HAVE_MEMCPY
-#define memcpy __db_Cmemcpy
-#endif
-#ifndef HAVE_MEMMOVE
-#define memmove __db_Cmemmove
-#endif
-#ifndef HAVE_RAISE
-#define raise __db_Craise
-#endif
-#ifndef HAVE_SNPRINTF
-#define snprintf __db_Csnprintf
-#endif
-#ifndef HAVE_STRCASECMP
-#define strcasecmp __db_Cstrcasecmp
-#endif
-#ifndef HAVE_STRERROR
-#define strerror __db_Cstrerror
-#endif
-#ifndef HAVE_VSNPRINTF
-#define vsnprintf __db_Cvsnprintf
-#endif
diff --git a/bdb/build_vxworks/dbdemo/README b/bdb/build_vxworks/dbdemo/README
new file mode 100644
index 00000000000..1a2c7c7d073
--- /dev/null
+++ b/bdb/build_vxworks/dbdemo/README
@@ -0,0 +1,39 @@
+This README describes the steps needed to run a demo example of BerkeleyDB.
+
+1. Read the pages in the Reference Guide that describe building
+ BerkeleyDB on VxWorks:
+
+ $(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/intro.html
+ $(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/notes.html
+ $(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/faq.html
+
+2. Launch Tornado 2.0 and open up the BerkeleyDB project.
+
+3. Add the demo project to that workspace:
+
+ $(WIND_BASE)/target/src/BerkeleyDB/build_vxworks/demo/dbdemo.wpj
+
+4. Build BerkeleyDB as described in the Reference Guide.
+
+5. Build the dbdemo project.
+
+6. Download BerkeleyDB onto the target.
+
+7. Download the dbdemo project onto the target.
+
+8. Open a windsh to the target and run the demo:
+
+ -> dbdemo "<pathname>/<dbname>"
+
+ Where pathname is a pathname string pointing to a directory that the
+ demo can create a database in. That directory should already exist.
+ The dbname is the name for the database. For example:
+
+ -> dbdemo "/tmp/demo.db"
+
+9. The demo program will ask for input. You can type in any string.
+ The program will add an entry to the database with that string as
+ the key and the reverse of that string as the data item for that key.
+ It will continue asking for input until you hit ^D or enter "quit".
+ Upon doing so, the demo program will display all the keys you have
+ entered as input and their data items.
diff --git a/bdb/build_vxworks/ex_access/ex_access.wpj b/bdb/build_vxworks/ex_access/ex_access.wpj
deleted file mode 100644
index bbbad47a253..00000000000
--- a/bdb/build_vxworks/ex_access/ex_access.wpj
+++ /dev/null
@@ -1,244 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/ex_access.a
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -I/export/home/db/build_vxworks
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_ex_access.out
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_BUILDRULE
-ex_access.out
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/ex_access.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I/export/home/db/build_vxworks \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUMgnu
-<END>
-
-<BEGIN> BUILD__LIST
-SIMSPARCSOLARISgnu PENTIUMgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_access.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_access.c_dependencies
-/export/home/db/build_vxworks/db_config.h /export/home/db/build_vxworks/db.h
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_access.c_objects
-ex_access.o
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_access.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/examples_c/ex_access.c
-<END>
-
-<BEGIN> userComments
-ex_access
-<END>
-
diff --git a/bdb/build_vxworks/ex_btrec/ex_btrec.wpj b/bdb/build_vxworks/ex_btrec/ex_btrec.wpj
deleted file mode 100644
index 801ca6808e2..00000000000
--- a/bdb/build_vxworks/ex_btrec/ex_btrec.wpj
+++ /dev/null
@@ -1,250 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/ex_btrec.a
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -I/export/home/db/build_vxworks
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_ex_btrec.out
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_BUILDRULE
-ex_btrec.out
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/ex_btrec.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I/export/home/db/build_vxworks \
- -I/export/home/db/build_vxworks \
- -I/export/home/db/include \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUMgnu
-<END>
-
-<BEGIN> BUILD__LIST
-SIMSPARCSOLARISgnu PENTIUMgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_btrec.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_btrec.c_dependencies
-/export/home/db/build_vxworks/db_config.h /export/home/db/build_vxworks/db.h
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_btrec.c_objects
-ex_btrec.o
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_btrec.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/examples_c/ex_btrec.c
-<END>
-
-<BEGIN> userComments
-ex_btrec
-<END>
-
diff --git a/bdb/build_vxworks/ex_dbclient/ex_dbclient.wpj b/bdb/build_vxworks/ex_dbclient/ex_dbclient.wpj
deleted file mode 100644
index fdb721406ad..00000000000
--- a/bdb/build_vxworks/ex_dbclient/ex_dbclient.wpj
+++ /dev/null
@@ -1,266 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUMgnu_BUILDRULE
-ex_dbclient.out
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/ex_dbclient.a
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I/export/home/db/build_vxworks \
- -I/export/home/db/include \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_ex_dbclient.out
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_BUILDRULE
-ex_dbclient.out
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/ex_dbclient.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I/export/home/db/build_vxworks \
- -I/export/home/db/include \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUMgnu
-<END>
-
-<BEGIN> BUILD__LIST
-SIMSPARCSOLARISgnu PENTIUMgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_dbclient.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_dbclient.c_dependencies
-/export/home/db/build_vxworks/db_config.h /export/home/db/build_vxworks/db.h
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_dbclient.c_objects
-ex_dbclient.o
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_dbclient.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/examples_c/ex_dbclient.c
-<END>
-
-<BEGIN> userComments
-RPC Client example
-<END>
-
diff --git a/bdb/build_vxworks/ex_env/ex_env.wpj b/bdb/build_vxworks/ex_env/ex_env.wpj
deleted file mode 100644
index 7229ffa1309..00000000000
--- a/bdb/build_vxworks/ex_env/ex_env.wpj
+++ /dev/null
@@ -1,248 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/ex_env.a
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -I/export/home/db/build_vxworks
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_ex_env.out
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_BUILDRULE
-ex_env.out
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/ex_env.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I/export/home/db/build_vxworks \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUMgnu
-<END>
-
-<BEGIN> BUILD__LIST
-SIMSPARCSOLARISgnu PENTIUMgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_env.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_env.c_dependencies
-/export/home/db/build_vxworks/db_config.h /export/home/db/build_vxworks/db.h
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_env.c_objects
-ex_env.o
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_env.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/examples_c/ex_env.c
-<END>
-
-<BEGIN> userComments
-ex_env
-<END>
-
diff --git a/bdb/build_vxworks/ex_mpool/ex_mpool.wpj b/bdb/build_vxworks/ex_mpool/ex_mpool.wpj
deleted file mode 100644
index 6dd9ed4db27..00000000000
--- a/bdb/build_vxworks/ex_mpool/ex_mpool.wpj
+++ /dev/null
@@ -1,248 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/ex_mpool.a
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -I/export/home/db/build_vxworks
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_ex_mpool.out
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_BUILDRULE
-ex_mpool.out
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/ex_mpool.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I/export/home/db/build_vxworks \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUMgnu
-<END>
-
-<BEGIN> BUILD__LIST
-SIMSPARCSOLARISgnu PENTIUMgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_mpool.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_mpool.c_dependencies
-/export/home/db/build_vxworks/db_config.h /export/home/db/build_vxworks/db.h
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_mpool.c_objects
-ex_mpool.o
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_mpool.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/examples_c/ex_mpool.c
-<END>
-
-<BEGIN> userComments
-ex_mpool
-<END>
-
diff --git a/bdb/build_vxworks/ex_tpcb/ex_tpcb.wpj b/bdb/build_vxworks/ex_tpcb/ex_tpcb.wpj
deleted file mode 100644
index 91de499dcf5..00000000000
--- a/bdb/build_vxworks/ex_tpcb/ex_tpcb.wpj
+++ /dev/null
@@ -1,261 +0,0 @@
-Document file - DO NOT EDIT
-
-<BEGIN> BUILD_PENTIUMgnu_BUILDRULE
-ex_tpcb.out
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
-ar386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/ex_tpcb.a
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
-cc386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM \
- -I/export/home/db/build_vxworks \
- -DVERY_TINY
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
--g \
- -mpentium \
- -ansi \
- -nostdinc \
- -fvolatile \
- -nostdlib \
- -fno-builtin \
- -fno-defer-pop \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=PENTIUM
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
-cc386 -E -P -xc
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
-ld386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
--X -N
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
--X -r
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
-nm386 -g
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
-size386
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_PENTIUMgnu_TC
-::tc_PENTIUMgnu
-<END>
-
-<BEGIN> BUILD_RULE_archive
-
-<END>
-
-<BEGIN> BUILD_RULE_ex_tpcb.out
-
-<END>
-
-<BEGIN> BUILD_RULE_objects
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_BUILDRULE
-ex_tpcb.out
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AR
-arsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/SIMSPARCSOLARISgnu/ex_tpcb.a
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_AS
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CC
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS
--g \
- -ansi \
- -nostdinc \
- -DRW_MULTI_THREAD \
- -D_REENTRANT \
- -fvolatile \
- -fno-builtin \
- -I/export/home/db/build_vxworks \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CFLAGS_AS
--g \
- -ansi \
- -nostdinc \
- -fvolatile \
- -fno-builtin \
- -P \
- -x \
- assembler-with-cpp \
- -I. \
- -I$(WIND_BASE)/target/h \
- -DCPU=SIMSPARCSOLARIS
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_CPP
-ccsimso -E -P -xc
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD
-ccsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDDEPS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LDFLAGS
--N
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_LD_PARTIAL_FLAGS
--nostdlib -r
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_NM
-nmsimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_DEFINE_MACRO
--D
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_OPTION_INCLUDE_DIR
--I
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_POST_BUILD_RULE
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_PRJ_LIBS
-
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_MACRO_SIZE
-sizesimso
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_RO_DEPEND_PATH
-{$(WIND_BASE)/target/h/} \
- {$(WIND_BASE)/target/src/} \
- {$(WIND_BASE)/target/config/}
-<END>
-
-<BEGIN> BUILD_SIMSPARCSOLARISgnu_TC
-::tc_SIMSPARCSOLARISgnu
-<END>
-
-<BEGIN> BUILD__CURRENT
-PENTIUMgnu
-<END>
-
-<BEGIN> BUILD__LIST
-SIMSPARCSOLARISgnu PENTIUMgnu
-<END>
-
-<BEGIN> CORE_INFO_TYPE
-::prj_vxApp
-<END>
-
-<BEGIN> CORE_INFO_VERSION
-2.0
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_tpcb.c_dependDone
-TRUE
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_tpcb.c_dependencies
-/export/home/db/build_vxworks/db_config.h /export/home/db/build_vxworks/db.h
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_tpcb.c_objects
-ex_tpcb.o
-<END>
-
-<BEGIN> FILE_/export/home/db/examples_c/ex_tpcb.c_tool
-C/C++ compiler
-<END>
-
-<BEGIN> PROJECT_FILES
-/export/home/db/examples_c/ex_tpcb.c
-<END>
-
-<BEGIN> userComments
-ex_tpcb
-<END>
-
diff --git a/bdb/build_win32/Berkeley_DB.dsw b/bdb/build_win32/Berkeley_DB.dsw
index 482ac7537f0..899e31ad58d 100644
--- a/bdb/build_win32/Berkeley_DB.dsw
+++ b/bdb/build_win32/Berkeley_DB.dsw
@@ -566,4 +566,3 @@ Package=<3>
}}}
###############################################################################
-
diff --git a/bdb/build_win32/app_dsp.src b/bdb/build_win32/app_dsp.src
index 064ea7ef51a..ff98d39ec79 100644
--- a/bdb/build_win32/app_dsp.src
+++ b/bdb/build_win32/app_dsp.src
@@ -1,5 +1,5 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
@@ -17,17 +17,14 @@ CFG=@project_name@ - Win32 Debug Static
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "@project_name@ - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "@project_name@ - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "@project_name@ - Win32 Release Static" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "@project_name@ - Win32 Debug Static" (based on\
- "Win32 (x86) Console Application")
+!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Console Application")
+!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
+# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
@@ -47,7 +44,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -71,7 +68,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -95,8 +92,8 @@ LINK32=link.exe
# PROP Intermediate_Dir "Release_static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -120,8 +117,8 @@ LINK32=link.exe
# PROP Intermediate_Dir "Debug_static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/bdb/build_win32/build_all.dsp b/bdb/build_win32/build_all.dsp
new file mode 100644
index 00000000000..7ae1f9bb031
--- /dev/null
+++ b/bdb/build_win32/build_all.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="build_all" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Generic Project" 0x010a
+
+CFG=build_all - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "build_all.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "build_all.mak" CFG="build_all - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "build_all - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "build_all - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE "build_all - Win32 Release Static" (based on "Win32 (x86) External Target")
+!MESSAGE "build_all - Win32 Debug Static" (based on "Win32 (x86) External Target")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "build_all - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "echo DB Release version built."
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "build_all - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "echo DB Debug version built."
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "build_all - Win32 Release Static"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_static"
+# PROP BASE Intermediate_Dir "Release_static"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_static"
+# PROP Intermediate_Dir "Release_static"
+# PROP Cmd_Line "echo DB Release Static version built."
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "build_all - Win32 Debug Static"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug_static"
+# PROP BASE Intermediate_Dir "Debug_Static"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_static"
+# PROP Intermediate_Dir "Debug_Static"
+# PROP Cmd_Line "echo DB Debug Static version built."
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "build_all - Win32 Release"
+# Name "build_all - Win32 Debug"
+# Name "build_all - Win32 Release Static"
+# Name "build_all - Win32 Debug Static"
+# End Target
+# End Project
diff --git a/bdb/build_win32/db_buildall.dsp b/bdb/build_win32/db_buildall.dsp
deleted file mode 100644
index 58990dbb867..00000000000
--- a/bdb/build_win32/db_buildall.dsp
+++ /dev/null
@@ -1,128 +0,0 @@
-# Microsoft Developer Studio Project File - Name="db_buildall" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) External Target" 0x0106
-
-CFG=db_buildall - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "db_buildall.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "db_buildall.mak" CFG="db_buildall - Win32 Debug Static"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "db_buildall - Win32 Release" (based on "Win32 (x86) External Target")
-!MESSAGE "db_buildall - Win32 Debug" (based on "Win32 (x86) External Target")
-!MESSAGE "db_buildall - Win32 Release Static" (based on\
- "Win32 (x86) External Target")
-!MESSAGE "db_buildall - Win32 Debug Static" (based on\
- "Win32 (x86) External Target")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-
-!IF "$(CFG)" == "db_buildall - Win32 Release"
-
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Cmd_Line "NMAKE /f db_buildall.mak"
-# PROP BASE Rebuild_Opt "/a"
-# PROP BASE Target_File "db_buildall.exe"
-# PROP BASE Bsc_Name "db_buildall.bsc"
-# PROP BASE Target_Dir ""
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Cmd_Line "echo DB release version built."
-# PROP Rebuild_Opt ""
-# PROP Target_File "db_buildall.exe"
-# PROP Bsc_Name "db_buildall.bsc"
-# PROP Target_Dir ""
-
-!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug"
-
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Cmd_Line "NMAKE /f db_buildall.mak"
-# PROP BASE Rebuild_Opt "/a"
-# PROP BASE Target_File "db_buildall.exe"
-# PROP BASE Bsc_Name "db_buildall.bsc"
-# PROP BASE Target_Dir ""
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Cmd_Line "echo DB debug version built."
-# PROP Rebuild_Opt ""
-# PROP Target_File "db_buildall.exe"
-# PROP Bsc_Name "db_buildall.bsc"
-# PROP Target_Dir ""
-
-!ELSEIF "$(CFG)" == "db_buildall - Win32 Release Static"
-
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release_static"
-# PROP BASE Intermediate_Dir "Release_static"
-# PROP BASE Cmd_Line "echo DB release version built."
-# PROP BASE Rebuild_Opt ""
-# PROP BASE Target_File "db_buildall.exe"
-# PROP BASE Bsc_Name "db_buildall.bsc"
-# PROP BASE Target_Dir ""
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release_static"
-# PROP Intermediate_Dir "Release_static"
-# PROP Cmd_Line "echo DB release version built."
-# PROP Rebuild_Opt ""
-# PROP Target_File "db_buildall.exe"
-# PROP Bsc_Name "db_buildall.bsc"
-# PROP Target_Dir ""
-
-!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug Static"
-
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug_static"
-# PROP BASE Intermediate_Dir "Debug_static"
-# PROP BASE Cmd_Line "echo DB debug version built."
-# PROP BASE Rebuild_Opt ""
-# PROP BASE Target_File "db_buildall.exe"
-# PROP BASE Bsc_Name "db_buildall.bsc"
-# PROP BASE Target_Dir ""
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug_static"
-# PROP Intermediate_Dir "Debug_static"
-# PROP Cmd_Line "echo DB debug version built."
-# PROP Rebuild_Opt ""
-# PROP Target_File "db_buildall.exe"
-# PROP Bsc_Name "db_buildall.bsc"
-# PROP Target_Dir ""
-
-!ENDIF
-
-# Begin Target
-
-# Name "db_buildall - Win32 Release"
-# Name "db_buildall - Win32 Debug"
-# Name "db_buildall - Win32 Release Static"
-# Name "db_buildall - Win32 Debug Static"
-
-!IF "$(CFG)" == "db_buildall - Win32 Release"
-
-!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug"
-
-!ELSEIF "$(CFG)" == "db_buildall - Win32 Release Static"
-
-!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug Static"
-
-!ENDIF
-
-# End Target
-# End Project
diff --git a/bdb/build_win32/db_config.h b/bdb/build_win32/db_config.h
deleted file mode 100644
index 8b12d64c3c9..00000000000
--- a/bdb/build_win32/db_config.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * $Id: db_config.h,v 11.24 2000/12/12 18:39:26 bostic Exp $
- */
-
-/* Define to empty if the keyword does not work. */
-/* #undef const */
-
-/* Define if your struct stat has st_blksize. */
-/* #undef HAVE_ST_BLKSIZE */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef mode_t */
-
-/* Define to `long' if <sys/types.h> doesn't define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef pid_t */
-
-/* Define to `unsigned' if <sys/types.h> doesn't define. */
-/* #undef size_t */
-
-/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-/* #undef STAT_MACROS_BROKEN */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if you can safely include both <sys/time.h> and <time.h>. */
-/* #undef TIME_WITH_SYS_TIME */
-
-/* Define if your processor stores words with the most significant
- byte first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define if you are building a version for running the test suite. */
-/* #undef CONFIG_TEST */
-
-/* Define if you want a debugging version. */
-/* #undef DEBUG */
-#if defined(_DEBUG)
-#if !defined(DEBUG)
-#define DEBUG 1
-#endif
-#endif
-
-/* Define if you want a version that logs read operations. */
-/* #undef DEBUG_ROP */
-
-/* Define if you want a version that logs write operations. */
-/* #undef DEBUG_WOP */
-
-/* Define if you want a version with run-time diagnostic checking. */
-/* #undef DIAGNOSTIC */
-
-/* Define if you want to mask harmless unitialized memory read/writes. */
-/* #undef UMRW */
-
-/* Define if fcntl/F_SETFD denies child access to file descriptors. */
-/* #undef HAVE_FCNTL_F_SETFD */
-
-/* Define if building big-file environment (e.g., AIX, HP/UX, Solaris). */
-/* #undef HAVE_FILE_OFFSET_BITS */
-
-/* Mutex possibilities. */
-/* #undef HAVE_MUTEX_68K_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_AIX_CHECK_LOCK */
-/* #undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_HPPA_MSEM_INIT */
-/* #undef HAVE_MUTEX_IA64_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_MACOS */
-/* #undef HAVE_MUTEX_MSEM_INIT */
-/* #undef HAVE_MUTEX_PPC_GCC_ASSEMBLY */
-/* #undef HAVE_MUTEX_PTHREADS */
-/* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
-/* #undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY */
-/* #undef HAVE_MUTEX_SEMA_INIT */
-/* #undef HAVE_MUTEX_SGI_INIT_LOCK */
-/* #undef HAVE_MUTEX_SOLARIS_LOCK_TRY */
-/* #undef HAVE_MUTEX_SOLARIS_LWP */
-/* #undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY */
-#define HAVE_MUTEX_THREADS 1
-/* #undef HAVE_MUTEX_UI_THREADS */
-/* #undef HAVE_MUTEX_UTS_CC_ASSEMBLY */
-/* #undef HAVE_MUTEX_VMS */
-/* #undef HAVE_MUTEX_VXWORKS */
-/* #undef HAVE_MUTEX_WIN16 */
-#define HAVE_MUTEX_WIN32 1
-/* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
-
-/* Define if building on QNX. */
-/* #undef HAVE_QNX */
-
-/* Define if building RPC client/server. */
-/* #undef HAVE_RPC */
-
-/* Define if your sprintf returns a pointer, not a length. */
-/* #undef SPRINTF_RET_CHARPNT */
-
-/* Define if you have the getcwd function. */
-#define HAVE_GETCWD 1
-
-/* Define if you have the getopt function. */
-/* #undef HAVE_GETOPT */
-
-/* Define if you have the getuid function. */
-/* #undef HAVE_GETUID */
-
-/* Define if you have the memcmp function. */
-#define HAVE_MEMCMP 1
-
-/* Define if you have the memcpy function. */
-#define HAVE_MEMCPY 1
-
-/* Define if you have the memmove function. */
-#define HAVE_MEMMOVE 1
-
-/* Define if you have the mlock function. */
-/* #undef HAVE_MLOCK */
-
-/* Define if you have the mmap function. */
-/* #undef HAVE_MMAP */
-
-/* Define if you have the munlock function. */
-/* #undef HAVE_MUNLOCK */
-
-/* Define if you have the munmap function. */
-/* #undef HAVE_MUNMAP */
-
-/* Define if you have the pread function. */
-/* #undef HAVE_PREAD */
-
-/* Define if you have the pstat_getdynamic function. */
-/* #undef HAVE_PSTAT_GETDYNAMIC */
-
-/* Define if you have the pwrite function. */
-/* #undef HAVE_PWRITE */
-
-/* Define if you have the qsort function. */
-#define HAVE_QSORT 1
-
-/* Define if you have the raise function. */
-#define HAVE_RAISE 1
-
-/* Define if you have the sched_yield function. */
-/* #undef HAVE_SCHED_YIELD */
-
-/* Define if you have the select function. */
-/* #undef HAVE_SELECT */
-
-/* Define if you have the shmget function. */
-/* #undef HAVE_SHMGET */
-
-/* Define if you have the snprintf function. */
-#define HAVE_SNPRINTF 1
-
-/* Define if you have the strcasecmp function. */
-/* #undef HAVE_STRCASECMP */
-
-/* Define if you have the strerror function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have the strtoul function. */
-#define HAVE_STRTOUL 1
-
-/* Define if you have the sysconf function. */
-/* #undef HAVE_SYSCONF */
-
-/* Define if you have the vsnprintf function. */
-#define HAVE_VSNPRINTF 1
-
-/* Define if you have the yield function. */
-/* #undef HAVE_YIELD */
-
-/* Define if you have the <dirent.h> header file. */
-/* #undef HAVE_DIRENT_H */
-
-/* Define if you have the <ndir.h> header file. */
-/* #undef HAVE_NDIR_H */
-
-/* Define if you have the <sys/dir.h> header file. */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define if you have the <sys/ndir.h> header file. */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define if you have the <sys/select.h> header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define if you have the <sys/time.h> header file. */
-/* #undef HAVE_SYS_TIME_H */
-
-/* Define if you have the nsl library (-lnsl). */
-/* #undef HAVE_LIBNSL */
-
-/*
- * XXX
- * The following is not part of the automatic configuration setup,
- * but provides the information necessary to build DB on Windows.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <direct.h>
-#include <fcntl.h>
-#include <io.h>
-#include <limits.h>
-#include <memory.h>
-#include <process.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <errno.h>
-
-#if defined(__cplusplus)
-#include <iostream.h>
-#endif
-
-/*
- * To build Tcl interface libraries, the include path must be configured to
- * use the directory containing <tcl.h>, usually the include directory in
- * the Tcl distribution.
- */
-#ifdef DB_TCL_SUPPORT
-#include <tcl.h>
-#endif
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-/*
- * Win32 has fsync, getcwd, snprintf and vsnprintf, but under different names.
- */
-#define fsync(fd) _commit(fd)
-#define getcwd(buf, size) _getcwd(buf, size)
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-
-/*
- * Win32 does not define getopt and friends in any header file, so we must.
- */
-#if defined(__cplusplus)
-extern "C" {
-#endif
-extern int optind;
-extern char *optarg;
-extern int getopt(int, char * const *, const char *);
-#if defined(__cplusplus)
-}
-#endif
-
-#define NO_SYSTEM_INCLUDES
-
-/*
- * We use DB_WIN32 much as one would use _WIN32, to determine that we're
- * using an operating system environment that supports Win32 calls
- * and semantics. We don't use _WIN32 because cygwin/gcc also defines
- * that, even though it closely emulates the Unix environment.
- */
-#define DB_WIN32 1
-
-/*
- * This is a grievous hack -- once we've included windows.h, we have no choice
- * but to use ANSI-style varargs (because it pulls in stdarg.h for us). DB's
- * code decides which type of varargs to use based on the state of __STDC__.
- * Sensible. Unfortunately, Microsoft's compiler _doesn't_ define __STDC__
- * unless you invoke it with arguments turning OFF all vendor extensions. Even
- * more unfortunately, if we do that, it fails to parse windows.h!!!!! So, we
- * define __STDC__ here, after windows.h comes in. Note: the compiler knows
- * we've defined it, and starts enforcing strict ANSI compilance from this point
- * on.
- */
-#define __STDC__ 1
diff --git a/bdb/build_win32/db_java_xa.dsp b/bdb/build_win32/db_java_xa.dsp
new file mode 100644
index 00000000000..9c700ffeed4
--- /dev/null
+++ b/bdb/build_win32/db_java_xa.dsp
@@ -0,0 +1,85 @@
+# Microsoft Developer Studio Project File - Name="db_java_xa" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=db_java_xa - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "db_java_xa.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "db_java_xa.mak" CFG="db_java_xa - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "db_java_xa - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "db_java_xa - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "db_java_xa - Win32 Release"
+
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Cmd_Line "NMAKE /f db_java_xaj.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "db_java_xaj.exe"
+# PROP BASE Bsc_Name "db_java_xaj.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "NMAKE /f db_java_xaj.mak Release/dbxa.jar"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "Release/dbxa.jar"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "db_java_xa - Win32 Debug"
+
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Cmd_Line "NMAKE /f db_java_xaj.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "db_java_xaj.exe"
+# PROP BASE Bsc_Name "db_java_xaj.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "NMAKE /f db_java_xaj.mak Debug/dbxa.jar"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "Debug/dbxa.jar"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "db_java_xa - Win32 Release"
+# Name "db_java_xa - Win32 Debug"
+
+!IF "$(CFG)" == "db_java_xa - Win32 Release"
+
+!ELSEIF "$(CFG)" == "db_java_xa - Win32 Debug"
+
+!ENDIF
+
+# Begin Source File
+
+SOURCE=.\db_java_xaj.mak
+# End Source File
+# End Target
+# End Project
diff --git a/bdb/build_win32/db_java_xaj.mak b/bdb/build_win32/db_java_xaj.mak
new file mode 100644
index 00000000000..c2dbc920d17
--- /dev/null
+++ b/bdb/build_win32/db_java_xaj.mak
@@ -0,0 +1,21 @@
+JAVA_XADIR=../java/src/com/sleepycat/db/xa
+
+JAVA_XASRCS=\
+ $(JAVA_XADIR)/DbXAResource.java \
+ $(JAVA_XADIR)/DbXid.java
+
+Release/dbxa.jar : $(JAVA_XASRCS)
+ @echo compiling Berkeley DB XA classes
+ @javac -g -d ./Release/classes -classpath "$(CLASSPATH);./Release/classes" $(JAVA_XASRCS)
+ @echo creating jar file
+ @cd .\Release\classes
+ @jar cf ../dbxa.jar com\sleepycat\db\xa\*.class
+ @echo Java XA build finished
+
+Debug/dbxa.jar : $(JAVA_XASRCS)
+ @echo compiling Berkeley DB XA classes
+ @javac -g -d ./Debug/classes -classpath "$(CLASSPATH);./Debug/classes" $(JAVA_XASRCS)
+ @echo creating jar file
+ @cd .\Debug\classes
+ @jar cf ../dbxa.jar com\sleepycat\db\xa\*.class
+ @echo Java XA build finished
diff --git a/bdb/build_win32/db_lib.dsp b/bdb/build_win32/db_lib.dsp
new file mode 100644
index 00000000000..a7fb4157909
--- /dev/null
+++ b/bdb/build_win32/db_lib.dsp
@@ -0,0 +1,92 @@
+# Microsoft Developer Studio Project File - Name="db_lib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Generic Project" 0x010a
+
+CFG=db_lib - Win32 Debug Static
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "db_lib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "db_lib.mak" CFG="db_lib - Win32 Debug Static"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "db_lib - Win32 Release" (based on "Win32 (x86) Generic Project")
+!MESSAGE "db_lib - Win32 Debug" (based on "Win32 (x86) Generic Project")
+!MESSAGE "db_lib - Win32 Release Static" (based on "Win32 (x86) Generic Project")
+!MESSAGE "db_lib - Win32 Debug Static" (based on "Win32 (x86) Generic Project")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "db_lib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "db_lib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "db_lib - Win32 Release Static"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_static"
+# PROP BASE Intermediate_Dir "Release_static"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_static"
+# PROP Intermediate_Dir "Release_static"
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "db_lib - Win32 Debug Static"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug_static"
+# PROP BASE Intermediate_Dir "Debug_Static"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_static"
+# PROP Intermediate_Dir "Debug_Static"
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "db_lib - Win32 Release"
+# Name "db_lib - Win32 Debug"
+# Name "db_lib - Win32 Release Static"
+# Name "db_lib - Win32 Debug Static"
+# End Target
+# End Project
diff --git a/bdb/build_win32/db_test.dsp b/bdb/build_win32/db_test.dsp
deleted file mode 100644
index e1bb9056824..00000000000
--- a/bdb/build_win32/db_test.dsp
+++ /dev/null
@@ -1,99 +0,0 @@
-# Microsoft Developer Studio Project File - Name="db_test" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=db_test - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "db_test.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "db_test.mak" CFG="db_test - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "db_test - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "db_test - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "db_test - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 Release/libdb32.lib /nologo /subsystem:console /machine:I386
-# Begin Special Build Tool
-SOURCE=$(InputPath)
-PostBuild_Desc=Copy built executable files.
-PostBuild_Cmds=copy Release\*.exe .
-# End Special Build Tool
-
-!ELSEIF "$(CFG)" == "db_test - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "db_recov"
-# PROP BASE Intermediate_Dir "db_recov"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 Debug/libdb32d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"Debug/dbkill.exe" /fixed:no
-# Begin Special Build Tool
-SOURCE=$(InputPath)
-PostBuild_Desc=Copy built executable files.
-PostBuild_Cmds=copy Debug\*.exe .
-# End Special Build Tool
-
-!ENDIF
-
-# Begin Target
-
-# Name "db_test - Win32 Release"
-# Name "db_test - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\dbkill.cpp
-# End Source File
-# End Target
-# End Project
diff --git a/bdb/build_win32/db_test.src b/bdb/build_win32/db_test.src
new file mode 100644
index 00000000000..73479d3856a
--- /dev/null
+++ b/bdb/build_win32/db_test.src
@@ -0,0 +1,97 @@
+# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=@project_name@ - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "@project_name@.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "@project_name@ - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:I386
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy built executable files.
+PostBuild_Cmds=copy Release\*.exe .
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"Debug/dbkill.exe" /fixed:no
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy built executable files.
+PostBuild_Cmds=copy Debug\*.exe .
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "@project_name@ - Win32 Release"
+# Name "@project_name@ - Win32 Debug"
+@SOURCE_FILES@
+# End Target
+# End Project
diff --git a/bdb/build_win32/dbkill.cpp b/bdb/build_win32/dbkill.cpp
index 24709f37201..23dc87b0e85 100644
--- a/bdb/build_win32/dbkill.cpp
+++ b/bdb/build_win32/dbkill.cpp
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: dbkill.cpp,v 11.4 2000/05/02 17:08:31 dda Exp $
+ * $Id: dbkill.cpp,v 11.7 2002/01/11 15:51:27 bostic Exp $
*/
/*
* Kill -
@@ -74,7 +74,7 @@ usage_exit()
{
fprintf(stderr, "Usage: kill [ -sig ] pid\n");
fprintf(stderr, " for win32, sig must be or 0, 15 (TERM)\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
int
@@ -117,15 +117,15 @@ main(int argc, char **argv)
hProcess = OpenProcess(accessflag, FALSE, pid);
if (hProcess == NULL) {
fprintf(stderr, "dbkill: %s: no such process\n", argv[1]);
- exit(1);
+ exit(EXIT_FAILURE);
}
if (sig == 0)
- exit(0);
+ exit(EXIT_SUCCESS);
if (!TerminateProcess(hProcess, 99)) {
DWORD err = GetLastError();
fprintf(stderr,
"dbkill: cannot kill process: error %d (0x%lx)\n", err, err);
- exit(1);
+ exit(EXIT_FAILURE);
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/bdb/build_win32/dynamic_dsp.src b/bdb/build_win32/dynamic_dsp.src
index d9881eda331..a92906a51f4 100644
--- a/bdb/build_win32/dynamic_dsp.src
+++ b/bdb/build_win32/dynamic_dsp.src
@@ -1,5 +1,5 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
@@ -13,19 +13,16 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
+!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "@project_name@ - Win32 Release Static" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "@project_name@ - Win32 Debug Static" (based on\
- "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
+# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
@@ -46,9 +43,9 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I "../include" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /I "../dbinc" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -72,74 +69,18 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /YX"config.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# SUBTRACT CPP /Fr
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
-
-!ELSEIF "$(CFG)" == "@project_name@ - Win32 Release Static"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "DB_DLL__"
-# PROP BASE Intermediate_Dir "DB_DLL__"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I "../include" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I "../include" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
-# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
-
-!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
-
-# PROP BASE Use_MFC 2
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "DB_DLL_0"
-# PROP BASE Intermediate_Dir "DB_DLL_0"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 2
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
-# SUBTRACT BASE CPP /Fr
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /YX"config.h" /FD /c
-# SUBTRACT CPP /Fr
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
-# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
-# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
!ENDIF
@@ -147,8 +88,6 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
-# Name "@project_name@ - Win32 Release Static"
-# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
# End Target
# End Project
diff --git a/bdb/build_win32/java_dsp.src b/bdb/build_win32/java_dsp.src
index eff251a44f4..15941bcab67 100644
--- a/bdb/build_win32/java_dsp.src
+++ b/bdb/build_win32/java_dsp.src
@@ -1,5 +1,5 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
@@ -17,12 +17,12 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "@project_name@ - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
+# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
@@ -43,9 +43,9 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -53,25 +53,22 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 Release/libdb32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
+# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# Begin Custom Build - Compiling java files using javac
ProjDir=.
InputPath=.\Release\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll
-SOURCE=$(InputPath)
+SOURCE="$(InputPath)"
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- cd $(ProjDir)\..\java\src\com\sleepycat\db
- mkdir ..\..\..\..\classes
+ mkdir $(ProjDir)\Release\classes
echo compiling Berkeley DB classes
- javac -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
+ javac -g -d $(ProjDir)/Release/classes -classpath "$(CLASSPATH);$(ProjDir)/Release/classes" ..\java\src\com\sleepycat\db\*.java
echo compiling examples
- cd ..\examples
- javac -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
- echo creating jar file
- cd ..\..\..\..\classes
- jar cf db.jar com\sleepycat\db\*.class
+ javac -g -d $(ProjDir)/Release/classes -classpath "$(CLASSPATH);$(ProjDir)/Release/classes" ..\java\src\com\sleepycat\examples\*.java
+ echo creating jar files
+ cd $(ProjDir)\Release\classes
+ jar cf ../db.jar com\sleepycat\db\*.class
+ jar cf ../dbexamples.jar com\sleepycat\examples\*.class
echo Java build finished
# End Custom Build
@@ -90,10 +87,10 @@ SOURCE=$(InputPath)
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
# SUBTRACT CPP /Fr
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
BSC32=bscmake.exe
@@ -101,25 +98,22 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 Debug/libdb32d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
+# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# Begin Custom Build - Compiling java files using javac
ProjDir=.
InputPath=.\Debug\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll
-SOURCE=$(InputPath)
+SOURCE="$(InputPath)"
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- cd $(ProjDir)\..\java\src\com\sleepycat\db
- mkdir ..\..\..\..\classes
+ mkdir $(ProjDir)\Debug\classes
echo compiling Berkeley DB classes
- javac -g -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
+ javac -g -d $(ProjDir)/Debug/classes -classpath "$(CLASSPATH);$(ProjDir)/Debug/classes" ..\java\src\com\sleepycat\db\*.java
echo compiling examples
- javac -g -d ../../../../classes -classpath "$(CLASSPATH);../../../../classes"\
- *.java
- cd ..\examples
- echo creating jar file
- cd ..\..\..\..\classes
- jar cf db.jar com\sleepycat\db\*.class
+ javac -g -d $(ProjDir)/Debug/classes -classpath "$(CLASSPATH);$(ProjDir)/Debug/classes" ..\java\src\com\sleepycat\examples\*.java
+ echo creating jar files
+ cd $(ProjDir)\Debug\classes
+ jar cf ../db.jar com\sleepycat\db\*.class
+ jar cf ../dbexamples.jar com\sleepycat\examples\*.class
echo Java build finished
# End Custom Build
diff --git a/bdb/build_win32/libdb.def b/bdb/build_win32/libdb.def
deleted file mode 100644
index a3b4cb3b26b..00000000000
--- a/bdb/build_win32/libdb.def
+++ /dev/null
@@ -1,151 +0,0 @@
-; $Id: libdb.def,v 11.21 2001/01/04 15:07:33 dda Exp $
-
-DESCRIPTION 'Berkeley DB 3.2 Library'
-EXPORTS
- lock_get @1
- lock_id @2
- lock_put @3
- lock_vec @4
- log_compare @5
- log_file @6
- log_flush @7
- log_get @8
- log_put @9
- log_register @10
- log_unregister @11
- memp_fclose @12
- memp_fget @13
- memp_fopen @14
- memp_fput @15
- memp_fset @16
- memp_fsync @17
- memp_register @18
- memp_sync @19
- txn_abort @20
- txn_begin @21
- txn_checkpoint @22
- txn_commit @23
- txn_prepare @24
- db_version @25
- memp_stat @26
- log_archive @27
- lock_detect @28
- txn_id @29
- txn_stat @30
- memp_trickle @31
- log_stat @32
- lock_stat @33
- db_create @34
- db_env_create @35
- db_strerror @36
- db_xa_switch @37
- db_env_set_func_close @38
- db_env_set_func_dirfree @39
- db_env_set_func_dirlist @40
- db_env_set_func_exists @41
- db_env_set_func_free @42
- db_env_set_func_fsync @43
- db_env_set_func_ioinfo @44
- db_env_set_func_malloc @45
- db_env_set_func_map @46
- db_env_set_func_open @47
- db_env_set_func_read @48
- db_env_set_func_realloc @49
- db_env_set_func_rename @50
- db_env_set_func_sleep @51
- db_env_set_func_unlink @52
- db_env_set_func_unmap @53
- db_env_set_func_write @54
- db_env_set_func_yield @55
-; FREE @56
- db_env_set_pageyield @57
- db_env_set_panicstate @58
- db_env_set_region_init @59
- db_env_set_tas_spins @60
-; these are only for testing
- __db_loadme @201
- __ham_func2 @202
- __ham_func3 @203
- __ham_func4 @204
- __ham_func5 @205
- __db_hcreate @206
- __db_hsearch @207
- __db_hdestroy @208
- __db_dbm_init @209
- __db_dbm_delete @210
- __db_dbm_fetch @211
- __db_dbm_store @212
- __db_dbm_firstkey @213
- __db_dbm_nextkey @214
- __db_dbm_close @215
- __db_ndbm_open @216
- __db_ndbm_store @217
- __db_ndbm_rdonly @218
- __db_ndbm_pagfno @219
- __db_ndbm_nextkey @220
- __db_ndbm_firstkey @221
- __db_ndbm_fetch @222
- __db_ndbm_error @223
- __db_ndbm_dirfno @224
- __db_ndbm_delete @225
- __db_ndbm_close @226
- __db_ndbm_clearerr @227
- __lock_dump_region @228
- __memp_dump_region @229
- __os_closehandle @230
- __os_openhandle @231
- __os_strdup @232
- __db_r_attach @233
- __db_r_detach @234
- __db_tas_mutex_init @235
- __db_tas_mutex_lock @236
- __db_tas_mutex_unlock @237
- __os_read @238
- __os_write @239
- __os_open @240
- __os_ioinfo @241
- __os_free @242
- __os_malloc @243
- __os_freestr @244
- __os_calloc @245
- __ham_test @246
-; these are needed for linking tools
- __db_dump @401
- __db_rpath @402
- __db_dispatch @403
- __db_err @404
- __db_init_print @405
- __txn_init_print @406
- __log_init_print @407
- __ham_init_print @408
- __bam_init_print @409
- __db_jump @410
- __ham_pgin @411
- __ham_pgout @412
- __bam_pgin @413
- __bam_pgout @414
- __db_omode @415
- __db_prdbt @416
- __os_sleep @417
- __db_e_stat @420
- __db_getlong @421
- __os_get_errno @422
- __os_set_errno @423
- __ham_get_meta @424
- __ham_release_meta @425
- __qam_init_print @426
- __crdel_init_print @427
- __qam_pgin_out @428
- __db_pgin @429
- __db_pgout @430
- __db_getulong @431
- __db_util_sigresend @432
- __db_util_siginit @433
- __db_util_interrupted @434
- __db_util_logset @435
- __db_prheader @436
- __db_prfooter @437
- __db_verify_callback @438
- __db_verify_internal @439
- __os_yield @440
- __db_global_values @441
diff --git a/bdb/build_win32/libdb_tcl.def b/bdb/build_win32/libdb_tcl.def
index a18459beaba..b6323c66bc6 100644
--- a/bdb/build_win32/libdb_tcl.def
+++ b/bdb/build_win32/libdb_tcl.def
@@ -1,16 +1,11 @@
-; $Id: libdb_tcl.def,v 11.2 1999/11/21 23:10:00 bostic Exp $
+; $Id: libdb_tcl.def,v 11.5 2002/04/03 12:01:27 mjc Exp $
DESCRIPTION 'Berkeley DB TCL interface Library'
EXPORTS
Db_tcl_Init
- bdb_DbmCommand
- bdb_HCommand
- bdb_NdbmOpen
- bdb_RandCommand
db_Cmd
dbc_Cmd
env_Cmd
- ndbm_Cmd
tcl_EnvRemove
tcl_LockDetect
tcl_LockGet
@@ -22,9 +17,7 @@ EXPORTS
tcl_LogFlush
tcl_LogGet
tcl_LogPut
- tcl_LogRegister
tcl_LogStat
- tcl_LogUnregister
tcl_Mp
tcl_MpStat
tcl_MpSync
@@ -32,4 +25,3 @@ EXPORTS
tcl_Txn
tcl_TxnCheckpoint
tcl_TxnStat
- txn_Cmd
diff --git a/bdb/build_win32/libdbrc.src b/bdb/build_win32/libdbrc.src
index 82a93068c8b..3e5d8deec6f 100644
--- a/bdb/build_win32/libdbrc.src
+++ b/bdb/build_win32/libdbrc.src
@@ -20,7 +20,7 @@ BEGIN
VALUE "FileDescription", "Berkeley DB 3.0 DLL\0"
VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
VALUE "InternalName", "libdb.dll\0"
- VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997, 1998, 1999, 2000\0"
+ VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2002\0"
VALUE "OriginalFilename", "libdb.dll\0"
VALUE "ProductName", "Sleepycat Software libdb\0"
VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
diff --git a/bdb/build_win32/static_dsp.src b/bdb/build_win32/static_dsp.src
index 99d00f14291..0c66c851025 100644
--- a/bdb/build_win32/static_dsp.src
+++ b/bdb/build_win32/static_dsp.src
@@ -1,10 +1,10 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
-CFG=@project_name@ - Win32 Debug
+CFG=@project_name@ - Win32 Debug Static
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
@@ -17,75 +17,33 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE "@project_name@ - Win32 Release Static" (based on\
- "Win32 (x86) Static Library")
-!MESSAGE "@project_name@ - Win32 Debug Static" (based on\
- "Win32 (x86) Static Library")
+!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Static Library")
+!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
+# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
+RSC=rc.exe
-!IF "$(CFG)" == "@project_name@ - Win32 Release"
+!IF "$(CFG)" == "@project_name@ - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "DB_Stati"
-# PROP BASE Intermediate_Dir "DB_Stati"
+# PROP BASE Output_Dir "Release_static"
+# PROP BASE Intermediate_Dir "Release_static"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static"
# PROP Intermediate_Dir "Release_static"
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
-
-!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "DB_Stat0"
-# PROP BASE Intermediate_Dir "DB_Stat0"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug_static"
-# PROP Intermediate_Dir "Debug_static"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I "../include" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
-
-!ELSEIF "$(CFG)" == "@project_name@ - Win32 Release Static"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "DB_Stati"
-# PROP BASE Intermediate_Dir "DB_Stati"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release_static"
-# PROP Intermediate_Dir "Release_static"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD BASE RSC /l 0xc09
+# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
@@ -95,18 +53,20 @@ LIB32=link.exe -lib
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
-# PROP BASE Use_MFC 0
+# PROP BASE Use_MFC 1
# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "DB_Stat0"
-# PROP BASE Intermediate_Dir "DB_Stat0"
+# PROP BASE Output_Dir "Debug_static"
+# PROP BASE Intermediate_Dir "Debug_static"
# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
+# PROP Use_MFC 1
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static"
# PROP Intermediate_Dir "Debug_static"
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I "../include" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
-# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I "../include" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD BASE RSC /l 0xc09
+# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
@@ -118,8 +78,6 @@ LIB32=link.exe -lib
# Begin Target
-# Name "@project_name@ - Win32 Release"
-# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
diff --git a/bdb/build_win32/tcl_dsp.src b/bdb/build_win32/tcl_dsp.src
index 11a36606e37..4de41e6934e 100644
--- a/bdb/build_win32/tcl_dsp.src
+++ b/bdb/build_win32/tcl_dsp.src
@@ -1,5 +1,5 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
@@ -22,6 +22,7 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE
# Begin Project
+# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
@@ -42,9 +43,9 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I "../include" /D "DB_TCL_SUPPORT" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /I "../dbinc" /D "DB_TCL_SUPPORT" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -52,7 +53,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 Release/libdb32.lib tcl83.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
+# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib tcl83.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
@@ -68,10 +69,10 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "DB_TCL_SUPPORT" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "DB_TCL_SUPPORT" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
# SUBTRACT CPP /Fr
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
BSC32=bscmake.exe
@@ -79,7 +80,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 Debug/libdb32d.lib tcl83d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
+# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib tcl83d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
!ENDIF
diff --git a/bdb/clib/getcwd.c b/bdb/clib/getcwd.c
index 630facb4fdb..bae50dfe90c 100644
--- a/bdb/clib/getcwd.c
+++ b/bdb/clib/getcwd.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -36,7 +36,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: getcwd.c,v 11.7 2000/11/30 00:58:30 ubell Exp $";
+static const char revid[] = "$Id: getcwd.c,v 11.13 2002/02/28 21:27:18 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -120,7 +120,7 @@ getcwd(pt, size)
ept = pt + size;
} else {
if ((ret =
- __os_malloc(NULL, ptsize = 1024 - 4, NULL, &pt)) != 0) {
+ __os_malloc(NULL, ptsize = 1024 - 4, &pt)) != 0) {
__os_set_errno(ret);
return (NULL);
}
@@ -134,7 +134,7 @@ getcwd(pt, size)
* Should always be enough (it's 340 levels). If it's not, allocate
* as necessary. Special case the first stat, it's ".", not "..".
*/
- if ((ret = __os_malloc(NULL, upsize = 1024 - 4, NULL, &up)) != 0)
+ if ((ret = __os_malloc(NULL, upsize = 1024 - 4, &up)) != 0)
goto err;
eup = up + 1024;
bup = up;
@@ -167,7 +167,7 @@ getcwd(pt, size)
* been that way and stuff would probably break.
*/
bcopy(bpt, pt, ept - bpt);
- __os_free(up, upsize);
+ __os_free(NULL, up);
return (pt);
}
@@ -177,7 +177,7 @@ getcwd(pt, size)
* possible component name, plus a trailing NULL.
*/
if (bup + 3 + MAXNAMLEN + 1 >= eup) {
- if (__os_realloc(NULL, upsize *= 2, NULL, &up) != 0)
+ if (__os_realloc(NULL, upsize *= 2, &up) != 0)
goto err;
bup = up;
eup = up + upsize;
@@ -238,7 +238,7 @@ getcwd(pt, size)
}
off = bpt - pt;
len = ept - bpt;
- if (__os_realloc(NULL, ptsize *= 2, NULL, &pt) != 0)
+ if (__os_realloc(NULL, ptsize *= 2, &pt) != 0)
goto err;
bpt = pt + off;
ept = pt + ptsize;
@@ -261,12 +261,12 @@ notfound:
* didn't find the current directory in its parent directory, set
* errno to ENOENT.
*/
- if (__os_get_errno() == 0)
+ if (__os_get_errno_ret_zero() == 0)
__os_set_errno(save_errno == 0 ? ENOENT : save_errno);
/* FALLTHROUGH */
err:
if (ptsize)
- __os_free(pt, ptsize);
- __os_free(up, upsize);
+ __os_free(NULL, pt);
+ __os_free(NULL, up);
return (NULL);
}
diff --git a/bdb/clib/getopt.c b/bdb/clib/getopt.c
index 667fca1d78c..3f6659ea6e6 100644
--- a/bdb/clib/getopt.c
+++ b/bdb/clib/getopt.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -36,7 +36,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: getopt.c,v 11.4 2000/02/14 02:59:40 bostic Exp $";
+static const char revid[] = "$Id: getopt.c,v 11.7 2002/01/11 15:51:28 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -47,6 +47,8 @@ static const char revid[] = "$Id: getopt.c,v 11.4 2000/02/14 02:59:40 bostic Exp
#include "db_int.h"
+int __db_getopt_reset; /* global reset for VxWorks. */
+
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
@@ -78,6 +80,19 @@ getopt(nargc, nargv, ostr)
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
+ /*
+ * VxWorks needs to be able to repeatedly call getopt from multiple
+ * programs within its global name space.
+ */
+ if (__db_getopt_reset) {
+ __db_getopt_reset = 0;
+
+ opterr = optind = 1;
+ optopt = optreset = 0;
+ optarg = NULL;
+ progname = NULL;
+ place = EMSG;
+ }
if (!progname) {
if ((progname = __db_rpath(*nargv)) == NULL)
progname = *nargv;
diff --git a/bdb/clib/memcmp.c b/bdb/clib/memcmp.c
index 2aedc3fa6b8..979badaef30 100644
--- a/bdb/clib/memcmp.c
+++ b/bdb/clib/memcmp.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -36,7 +36,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: memcmp.c,v 11.5 2000/02/24 21:58:12 bostic Exp $";
+static const char revid[] = "$Id: memcmp.c,v 11.7 2002/01/11 15:51:28 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
diff --git a/bdb/clib/memmove.c b/bdb/clib/memmove.c
index da6bcfe8b13..632d50788da 100644
--- a/bdb/clib/memmove.c
+++ b/bdb/clib/memmove.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -36,7 +36,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: memmove.c,v 11.4 2000/02/14 02:59:40 bostic Exp $";
+static const char revid[] = "$Id: memmove.c,v 11.6 2002/01/11 15:51:28 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
diff --git a/bdb/clib/raise.c b/bdb/clib/raise.c
index acec86cd63a..fcf3bbcbd7f 100644
--- a/bdb/clib/raise.c
+++ b/bdb/clib/raise.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: raise.c,v 11.3 2000/02/14 02:59:41 bostic Exp $";
+static const char revid[] = "$Id: raise.c,v 11.6 2002/01/11 15:51:28 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -28,5 +28,9 @@ int
raise(s)
int s;
{
+ /*
+ * Do not use __os_id(), as it may not return the process ID -- any
+ * system with kill(3) probably has getpid(3).
+ */
return (kill(getpid(), s));
}
diff --git a/bdb/clib/snprintf.c b/bdb/clib/snprintf.c
index 6aa9e3ae66c..fa1a63425e8 100644
--- a/bdb/clib/snprintf.c
+++ b/bdb/clib/snprintf.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: snprintf.c,v 11.5 2000/12/22 19:38:37 bostic Exp $";
+static const char revid[] = "$Id: snprintf.c,v 11.10 2002/01/11 15:51:28 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -39,23 +39,36 @@ snprintf(str, n, fmt, va_alist)
va_dcl
#endif
{
+ static int ret_charpnt = -1;
va_list ap;
- int rval;
+ int len;
COMPQUIET(n, 0);
+
+ /*
+ * Some old versions of sprintf return a pointer to the first argument
+ * instead of a character count. Assume the return value of snprintf,
+ * vsprintf, etc. will be the same as sprintf, and check the easy one.
+ *
+ * We do this test at run-time because it's not a test we can do in a
+ * cross-compilation environment.
+ */
+ if (ret_charpnt == -1) {
+ char buf[10];
+
+ ret_charpnt =
+ sprintf(buf, "123") != 3 ||
+ sprintf(buf, "123456789") != 9 ||
+ sprintf(buf, "1234") != 4;
+ }
+
#ifdef __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
-#ifdef SPRINTF_RET_CHARPNT
- (void)vsprintf(str, fmt, ap);
+ len = vsprintf(str, fmt, ap);
va_end(ap);
- return (strlen(str));
-#else
- rval = vsprintf(str, fmt, ap);
- va_end(ap);
- return (rval);
-#endif
+ return (ret_charpnt ? (int)strlen(str) : len);
}
#endif
diff --git a/bdb/clib/strcasecmp.c b/bdb/clib/strcasecmp.c
index 6633197bc8c..d5ce6d76d5f 100644
--- a/bdb/clib/strcasecmp.c
+++ b/bdb/clib/strcasecmp.c
@@ -34,7 +34,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: strcasecmp.c,v 1.4 2000/03/24 22:31:31 bostic Exp $";
+static const char revid[] = "$Id: strcasecmp.c,v 1.7 2001/11/15 17:51:38 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -78,14 +78,16 @@ static const unsigned char charmap[] = {
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
};
/*
* strcasecmp --
* Do strcmp(3) in a case-insensitive manner.
*
+ * PUBLIC: #ifndef HAVE_STRCASECMP
* PUBLIC: int strcasecmp __P((const char *, const char *));
+ * PUBLIC: #endif
*/
int
strcasecmp(s1, s2)
@@ -100,3 +102,31 @@ strcasecmp(s1, s2)
return (0);
return (cm[*us1] - cm[*--us2]);
}
+
+/*
+ * strncasecmp --
+ * Do strncmp(3) in a case-insensitive manner.
+ *
+ * PUBLIC: #ifndef HAVE_STRCASECMP
+ * PUBLIC: int strncasecmp __P((const char *, const char *, size_t));
+ * PUBLIC: #endif
+ */
+int
+strncasecmp(s1, s2, n)
+ const char *s1, *s2;
+ register size_t n;
+{
+ if (n != 0) {
+ register const unsigned char *cm = charmap,
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ do {
+ if (cm[*us1] != cm[*us2++])
+ return (cm[*us1] - cm[*--us2]);
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/bdb/clib/strdup.c b/bdb/clib/strdup.c
new file mode 100644
index 00000000000..e68623f1407
--- /dev/null
+++ b/bdb/clib/strdup.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: strdup.c,v 1.5 2002/05/01 18:40:05 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/*
+ * strdup --
+ *
+ * PUBLIC: #ifndef HAVE_STRDUP
+ * PUBLIC: char *strdup __P((const char *));
+ * PUBLIC: #endif
+ */
+char *
+strdup(str)
+ const char *str;
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if (!(copy = malloc((u_int)len)))
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
+}
diff --git a/bdb/clib/strerror.c b/bdb/clib/strerror.c
index 0f7447b0419..06c28946b88 100644
--- a/bdb/clib/strerror.c
+++ b/bdb/clib/strerror.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -36,7 +36,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: strerror.c,v 11.4 2000/02/14 02:59:41 bostic Exp $";
+static const char revid[] = "$Id: strerror.c,v 11.6 2002/01/11 15:51:29 bostic Exp $";
#endif /* not lint */
/*
diff --git a/bdb/clib/vsnprintf.c b/bdb/clib/vsnprintf.c
index 3d27bc0d2f8..4ffea8cb0ad 100644
--- a/bdb/clib/vsnprintf.c
+++ b/bdb/clib/vsnprintf.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: vsnprintf.c,v 11.4 2000/05/18 19:24:59 bostic Exp $";
+static const char revid[] = "$Id: vsnprintf.c,v 11.7 2002/01/11 15:51:29 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -24,7 +24,7 @@ static const char revid[] = "$Id: vsnprintf.c,v 11.4 2000/05/18 19:24:59 bostic
* Bounded version of vsprintf.
*
* PUBLIC: #ifndef HAVE_VSNPRINTF
- * PUBLIC: int vsnprintf();
+ * PUBLIC: int vsnprintf __P((char *, size_t, const char *, va_list));
* PUBLIC: #endif
*/
#ifndef HAVE_VSNPRINTF
diff --git a/bdb/common/db_byteorder.c b/bdb/common/db_byteorder.c
index d089cfe4c99..d42d8e6a958 100644
--- a/bdb/common/db_byteorder.c
+++ b/bdb/common/db_byteorder.c
@@ -1,30 +1,42 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_byteorder.c,v 11.4 2000/11/30 00:58:31 ubell Exp $";
+static const char revid[] = "$Id: db_byteorder.c,v 11.8 2002/02/01 18:15:29 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-
-#ifdef HAVE_ENDIAN_H
-#include <endian.h>
-#if BYTE_ORDER == BIG_ENDIAN
-#define WORDS_BIGENDIAN 1
-#endif
-#endif
-
#endif
#include "db_int.h"
-#include "common_ext.h"
+
+/*
+ * __db_isbigendian --
+ * Return 1 if big-endian (Motorola and Sparc), not little-endian
+ * (Intel and Vax). We do this work at run-time, rather than at
+ * configuration time so cross-compilation and general embedded
+ * system support is simpler.
+ *
+ * PUBLIC: int __db_isbigendian __P((void));
+ */
+int
+__db_isbigendian()
+{
+ union { /* From Harbison & Steele. */
+ long l;
+ char c[sizeof(long)];
+ } u;
+
+ u.l = 1;
+ return (u.c[sizeof(long) - 1] == 1);
+}
/*
* __db_byteorder --
@@ -38,21 +50,21 @@ __db_byteorder(dbenv, lorder)
DB_ENV *dbenv;
int lorder;
{
+ int is_bigendian;
+
+ is_bigendian = __db_isbigendian();
+
switch (lorder) {
case 0:
break;
case 1234:
-#if defined(WORDS_BIGENDIAN)
- return (DB_SWAPBYTES);
-#else
+ if (is_bigendian)
+ return (DB_SWAPBYTES);
break;
-#endif
case 4321:
-#if defined(WORDS_BIGENDIAN)
+ if (!is_bigendian)
+ return (DB_SWAPBYTES);
break;
-#else
- return (DB_SWAPBYTES);
-#endif
default:
__db_err(dbenv,
"unsupported byte order, only big and little-endian supported");
diff --git a/bdb/common/db_err.c b/bdb/common/db_err.c
index d69bd023dfd..7c9ee3c4fde 100644
--- a/bdb/common/db_err.c
+++ b/bdb/common/db_err.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_err.c,v 11.38 2001/01/22 21:50:25 sue Exp $";
+static const char revid[] = "$Id: db_err.c,v 11.80 2002/07/30 01:21:53 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,21 +20,12 @@ static const char revid[] = "$Id: db_err.c,v 11.38 2001/01/22 21:50:25 sue Exp $
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "lock_ext.h"
-#include "log.h"
-#include "log_ext.h"
-#include "mp.h"
-#include "mp_ext.h"
-#include "txn.h"
-#include "txn_ext.h"
-#include "clib_ext.h"
-#include "common_ext.h"
-#include "db_auto.h"
-
-static void __db_errcall __P((const DB_ENV *, int, int, const char *, va_list));
-static void __db_errfile __P((const DB_ENV *, int, int, const char *, va_list));
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
/*
* __db_fchk --
@@ -89,12 +80,13 @@ __db_ferr(dbenv, name, iscombo)
* __db_pgerr --
* Error when unable to retrieve a specified page.
*
- * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t));
+ * PUBLIC: void __db_pgerr __P((DB *, db_pgno_t, int));
*/
-int
-__db_pgerr(dbp, pgno)
+void
+__db_pgerr(dbp, pgno, errval)
DB *dbp;
db_pgno_t pgno;
+ int errval;
{
/*
* Three things are certain:
@@ -103,23 +95,22 @@ __db_pgerr(dbp, pgno)
*/
__db_err(dbp->dbenv,
"unable to create/retrieve page %lu", (u_long)pgno);
- return (__db_panic(dbp->dbenv, EIO));
+ (void)__db_panic(dbp->dbenv, errval);
}
/*
* __db_pgfmt --
* Error when a page has the wrong format.
*
- * PUBLIC: int __db_pgfmt __P((DB *, db_pgno_t));
+ * PUBLIC: int __db_pgfmt __P((DB_ENV *, db_pgno_t));
*/
int
-__db_pgfmt(dbp, pgno)
- DB *dbp;
+__db_pgfmt(dbenv, pgno)
+ DB_ENV *dbenv;
db_pgno_t pgno;
{
- __db_err(dbp->dbenv,
- "page %lu: illegal page type or format", (u_long)pgno);
- return (__db_panic(dbp->dbenv, EINVAL));
+ __db_err(dbenv, "page %lu: illegal page type or format", (u_long)pgno);
+ return (__db_panic(dbenv, EINVAL));
}
/*
@@ -157,7 +148,7 @@ __db_assert(failedexpr, file, line)
(void)fprintf(stderr,
"__db_assert: \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
- fflush(stderr);
+ (void)fflush(stderr);
/* We want a stack trace of how this could possibly happen. */
abort();
@@ -176,7 +167,7 @@ int
__db_panic_msg(dbenv)
DB_ENV *dbenv;
{
- __db_err(dbenv, "region error detected; run recovery.");
+ __db_err(dbenv, "fatal region error detected; run recovery");
return (DB_RUNRECOVERY);
}
@@ -191,11 +182,10 @@ __db_panic(dbenv, errval)
DB_ENV *dbenv;
int errval;
{
-
if (dbenv != NULL) {
- ((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->panic = 1;
+ PANIC_SET(dbenv, 1);
- dbenv->db_panic = errval;
+ dbenv->panic_errval = errval;
__db_err(dbenv, "PANIC: %s", db_strerror(errval));
@@ -203,6 +193,17 @@ __db_panic(dbenv, errval)
dbenv->db_paniccall(dbenv, errval);
}
+#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST)
+ /*
+ * We want a stack trace of how this could possibly happen.
+ *
+ * Don't drop core if it's the test suite -- it's reasonable for the
+ * test suite to check to make sure that DB_RUNRECOVERY is returned
+ * under certain conditions.
+ */
+ abort();
+#endif
+
/*
* Chaos reigns within.
* Reflect, repent, and reboot.
@@ -214,6 +215,8 @@ __db_panic(dbenv, errval)
/*
* db_strerror --
* ANSI C strerror(3) for DB.
+ *
+ * EXTERN: char *db_strerror __P((int));
*/
char *
db_strerror(error)
@@ -232,8 +235,8 @@ db_strerror(error)
* altered.
*/
switch (error) {
- case DB_INCOMPLETE:
- return ("DB_INCOMPLETE: Cache flush was unable to complete");
+ case DB_DONOTINDEX:
+ return ("DB_DONOTINDEX: Secondary index callback returns null");
case DB_KEYEMPTY:
return ("DB_KEYEMPTY: Non-existent key/data pair");
case DB_KEYEXIST:
@@ -253,8 +256,26 @@ db_strerror(error)
return ("DB_NOTFOUND: No matching key/data pair found");
case DB_OLD_VERSION:
return ("DB_OLDVERSION: Database requires a version upgrade");
+ case DB_PAGE_NOTFOUND:
+ return ("DB_PAGE_NOTFOUND: Requested page not found");
+ case DB_REP_DUPMASTER:
+ return ("DB_REP_DUPMASTER: A second master site appeared");
+ case DB_REP_HOLDELECTION:
+ return ("DB_REP_HOLDELECTION: Need to hold an election");
+ case DB_REP_NEWMASTER:
+ return ("DB_REP_NEWMASTER: A new master has declared itself");
+ case DB_REP_NEWSITE:
+ return ("DB_REP_NEWSITE: A new site has entered the system");
+ case DB_REP_OUTDATED:
+ return
+ ("DB_REP_OUTDATED: Insufficient logs on master to recover");
+ case DB_REP_UNAVAIL:
+ return ("DB_REP_UNAVAIL: Unable to elect a master");
case DB_RUNRECOVERY:
return ("DB_RUNRECOVERY: Fatal error, run database recovery");
+ case DB_SECONDARY_BAD:
+ return
+ ("DB_SECONDARY_BAD: Secondary index item missing from primary");
case DB_VERIFY_BAD:
return ("DB_VERIFY_BAD: Database verification failed");
default: {
@@ -274,8 +295,8 @@ db_strerror(error)
/*
* __db_err --
- * Standard DB error routine. The same as db_errx, except that we
- * don't write to stderr if no output mechanism was specified.
+ * Standard DB error routine. The same as errx, except we don't write
+ * to stderr if no output mechanism was specified.
*
* PUBLIC: void __db_err __P((const DB_ENV *, const char *, ...));
*/
@@ -289,81 +310,17 @@ __db_err(dbenv, fmt, va_alist)
va_dcl
#endif
{
- va_list ap;
-
-/*
- XXX
- Log the message.
-
- It would be nice to automatically log the error into the log files
- if the application is configured for logging. The problem is that
- if we currently hold the log region mutex, we will self-deadlock.
- Leave all the structure in place, but turned off. I'd like to fix
- this in the future by detecting if we have the log region already
- locked (e.g., a flag in the environment handle), or perhaps even
- have a finer granularity so that the only calls to __db_err we
- can't log are those made while we have the current log buffer
- locked, or perhaps have a separate buffer into which we log error
- messages.
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- __db_real_log(dbenv, NULL, "db_err", 0, fmt, ap);
-
- va_end(ap);
-#endif
-*/
-
- /* Tell the application. */
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- __db_real_err(dbenv, 0, 0, 0, fmt, ap);
-
- va_end(ap);
-}
-
-/*
- * __db_real_err --
- * All the DB error routines end up here.
- *
- * PUBLIC: void __db_real_err
- * PUBLIC: __P((const DB_ENV *, int, int, int, const char *, va_list));
- */
-void
-__db_real_err(dbenv, error, error_set, stderr_default, fmt, ap)
- const DB_ENV *dbenv;
- int error, error_set, stderr_default;
- const char *fmt;
- va_list ap;
-{
- /* Call the user's callback function, if specified. */
- if (dbenv != NULL && dbenv->db_errcall != NULL)
- __db_errcall(dbenv, error, error_set, fmt, ap);
-
- /* Write to the user's file descriptor, if specified. */
- if (dbenv != NULL && dbenv->db_errfile != NULL)
- __db_errfile(dbenv, error, error_set, fmt, ap);
-
- /*
- * If we have a default and we didn't do either of the above, write
- * to the default.
- */
- if (stderr_default && (dbenv == NULL ||
- (dbenv->db_errcall == NULL && dbenv->db_errfile == NULL)))
- __db_errfile(dbenv, error, error_set, fmt, ap);
+ DB_REAL_ERR(dbenv, 0, 0, 0, fmt);
}
/*
* __db_errcall --
* Do the error message work for callback functions.
+ *
+ * PUBLIC: void __db_errcall
+ * PUBLIC: __P((const DB_ENV *, int, int, const char *, va_list));
*/
-static void
+void
__db_errcall(dbenv, error, error_set, fmt, ap)
const DB_ENV *dbenv;
int error, error_set;
@@ -371,27 +328,44 @@ __db_errcall(dbenv, error, error_set, fmt, ap)
va_list ap;
{
char *p;
- char __errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
+ char errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
- p = __errbuf;
- if (fmt != NULL) {
- p += vsnprintf(__errbuf, sizeof(__errbuf), fmt, ap);
- if (error_set) {
- *p++ = ':';
- *p++ = ' ';
- }
- }
+ p = errbuf;
+ if (fmt != NULL)
+ p += vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
if (error_set)
- (void)strcpy(p, db_strerror(error));
+ p += snprintf(p,
+ sizeof(errbuf) - (p - errbuf), ": %s", db_strerror(error));
+ /*
+ * !!!
+ * We're potentially manipulating strings handed us by the application,
+ * and on systems without a real snprintf() the sprintf() calls could
+ * have overflowed the buffer. We can't do anything about it now, but
+ * we don't want to return control to the application, we might have
+ * overwritten the stack with a Trojan horse. We're not trying to do
+ * anything recoverable here because systems without snprintf support
+ * are pretty rare anymore.
+ */
+ if ((size_t)(p - errbuf) > sizeof(errbuf)) {
+ (void)fprintf(stderr,
+ "Berkeley DB: error callback interface buffer overflow\n");
+ (void)fflush(stderr);
+
+ abort();
+ /* NOTREACHED */
+ }
- dbenv->db_errcall(dbenv->db_errpfx, __errbuf);
+ dbenv->db_errcall(dbenv->db_errpfx, errbuf);
}
/*
* __db_errfile --
* Do the error message work for FILE *s.
+ *
+ * PUBLIC: void __db_errfile
+ * PUBLIC: __P((const DB_ENV *, int, int, const char *, va_list));
*/
-static void
+void
__db_errfile(dbenv, error, error_set, fmt, ap)
const DB_ENV *dbenv;
int error, error_set;
@@ -436,48 +410,22 @@ __db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
va_dcl
#endif
{
- va_list ap;
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- __db_real_log(dbenv, txnid, opname, flags, fmt, ap);
-
- va_end(ap);
-}
-
-/*
- * __db_real_log --
- * Write information into the DB log.
- *
- * PUBLIC: void __db_real_log __P((const DB_ENV *,
- * PUBLIC: DB_TXN *, const char *, u_int32_t, const char *, va_list ap));
- */
-void
-#ifdef __STDC__
-__db_real_log(const DB_ENV *dbenv, DB_TXN *txnid,
- const char *opname, u_int32_t flags, const char *fmt, va_list ap)
-#else
-__db_real_log(dbenv, txnid, opname, flags, fmt, ap)
- const DB_ENV *dbenv;
- DB_TXN *txnid;
- const char *opname, *fmt;
- u_int32_t flags;
- va_list ap;
-#endif
-{
DBT opdbt, msgdbt;
DB_LSN lsn;
+ va_list ap;
char __logbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
if (!LOGGING_ON(dbenv))
return;
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
memset(&opdbt, 0, sizeof(opdbt));
opdbt.data = (void *)opname;
- opdbt.size = strlen(opname) + 1;
+ opdbt.size = (u_int32_t)(strlen(opname) + 1);
memset(&msgdbt, 0, sizeof(msgdbt));
msgdbt.data = __logbuf;
@@ -490,6 +438,8 @@ __db_real_log(dbenv, txnid, opname, flags, fmt, ap)
*/
__db_debug_log(
(DB_ENV *)dbenv, txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0);
+
+ va_end(ap);
}
/*
@@ -511,34 +461,119 @@ __db_unknown_flag(dbenv, routine, flag)
/*
* __db_unknown_type -- report internal error
*
- * PUBLIC: int __db_unknown_type __P((DB_ENV *, char *, u_int32_t));
+ * PUBLIC: int __db_unknown_type __P((DB_ENV *, char *, DBTYPE));
*/
int
__db_unknown_type(dbenv, routine, type)
DB_ENV *dbenv;
char *routine;
- u_int32_t type;
+ DBTYPE type;
{
__db_err(dbenv, "%s: Unknown db type: 0x%x", routine, type);
DB_ASSERT(0);
return (EINVAL);
}
-#ifdef DIAGNOSTIC
/*
- * __db_missing_txn_err --
- * Cannot combine operations with and without transactions.
+ * __db_check_txn --
+ * Check for common transaction errors.
*
- * PUBLIC: #ifdef DIAGNOSTIC
- * PUBLIC: int __db_missing_txn_err __P((DB_ENV *));
- * PUBLIC: #endif
+ * PUBLIC: int __db_check_txn __P((DB *, DB_TXN *, u_int32_t, int));
*/
int
-__db_missing_txn_err(dbenv)
- DB_ENV *dbenv;
+__db_check_txn(dbp, txn, assoc_lid, read_op)
+ DB *dbp;
+ DB_TXN *txn;
+ u_int32_t assoc_lid;
+ int read_op;
{
+ DB_ENV *dbenv;
+
+ dbenv = dbp->dbenv;
+
+ /*
+ * If we are in recovery or aborting a transaction, then we
+ * don't need to enforce the rules about dbp's not allowing
+ * transactional operations in non-transactional dbps and
+ * vica-versa. This happens all the time as the dbp during
+ * an abort may be transactional, but we undo operations
+ * outside a transaction since we're aborting.
+ */
+ if (IS_RECOVERING(dbenv) || F_ISSET(dbp, DB_AM_RECOVER))
+ return (0);
+
+ /*
+ * Check for common transaction errors:
+ * Failure to pass a transaction handle to a DB operation
+ * Failure to configure the DB handle in a proper environment
+ * Operation on a handle whose open commit hasn't completed.
+ *
+ * Read operations don't require a txn even if we've used one before
+ * with this handle, although if they do have a txn, we'd better be
+ * prepared for it.
+ */
+ if (txn == NULL) {
+ if (!read_op && F_ISSET(dbp, DB_AM_TXN)) {
+ __db_err(dbenv,
+ "DB handle previously used in transaction, missing transaction handle");
+ return (EINVAL);
+ }
+
+ if (dbp->cur_lid >= TXN_MINIMUM)
+ goto open_err;
+ } else {
+ if (dbp->cur_lid >= TXN_MINIMUM && dbp->cur_lid != txn->txnid)
+ goto open_err;
+
+ if (!TXN_ON(dbenv))
+ return (__db_not_txn_env(dbenv));
+
+ if (!F_ISSET(dbp, DB_AM_TXN)) {
+ __db_err(dbenv,
+ "Transaction specified for a DB handle opened outside a transaction");
+ return (EINVAL);
+ }
+ }
+
+ /*
+ * If dbp->associate_lid is not DB_LOCK_INVALIDID, that means we're in
+ * the middle of a DB->associate with DB_CREATE (i.e., a secondary index
+ * creation).
+ *
+ * In addition to the usual transaction rules, we need to lock out
+ * non-transactional updates that aren't part of the associate (and
+ * thus are using some other locker ID).
+ *
+ * Transactional updates should simply block; from the time we
+ * decide to build the secondary until commit, we'll hold a write
+ * lock on all of its pages, so it should be safe to attempt to update
+ * the secondary in another transaction (presumably by updating the
+ * primary).
+ */
+ if (!read_op && dbp->associate_lid != DB_LOCK_INVALIDID &&
+ txn != NULL && dbp->associate_lid != assoc_lid) {
+ __db_err(dbenv,
+ "Operation forbidden while secondary index is being created");
+ return (EINVAL);
+ }
+
+ return (0);
+open_err:
__db_err(dbenv,
- "DB handle previously used in transaction, missing transaction handle.");
+ "Transaction that opened the DB handle is still active");
+ return (EINVAL);
+}
+
+/*
+ * __db_not_txn_env --
+ * DB handle must be in an environment that supports transactions.
+ *
+ * PUBLIC: int __db_not_txn_env __P((DB_ENV *));
+ */
+int
+__db_not_txn_env(dbenv)
+ DB_ENV *dbenv;
+{
+ __db_err(dbenv, "DB environment not configured for transactions");
return (EINVAL);
}
-#endif
diff --git a/bdb/common/db_getlong.c b/bdb/common/db_getlong.c
index bead530cd94..6ba8ebfcdaa 100644
--- a/bdb/common/db_getlong.c
+++ b/bdb/common/db_getlong.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_getlong.c,v 11.11 2000/12/22 19:16:04 bostic Exp $";
+static const char revid[] = "$Id: db_getlong.c,v 11.18 2002/03/28 20:13:33 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,6 @@ static const char revid[] = "$Id: db_getlong.c,v 11.11 2000/12/22 19:16:04 bosti
#endif
#include "db_int.h"
-#include "clib_ext.h"
/*
* __db_getlong --
@@ -43,42 +42,40 @@ __db_getlong(dbp, progname, p, min, max, storep)
val = strtol(p, &end, 10);
if ((val == LONG_MIN || val == LONG_MAX) &&
__os_get_errno() == ERANGE) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
"%s: %s: %s\n", progname, p, strerror(ERANGE));
- exit(1);
- }
- dbp->err(dbp, ERANGE, "%s", p);
+ else
+ dbp->err(dbp, ERANGE, "%s", p);
return (1);
}
if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
"%s: %s: Invalid numeric argument\n", progname, p);
- exit(1);
- }
- dbp->errx(dbp, "%s: Invalid numeric argument", p);
+ else
+ dbp->errx(dbp, "%s: Invalid numeric argument", p);
return (1);
}
if (val < min) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
"%s: %s: Less than minimum value (%ld)\n",
progname, p, min);
- exit(1);
- }
- dbp->errx(dbp, "%s: Less than minimum value (%ld)", p, min);
+ else
+ dbp->errx(dbp,
+ "%s: Less than minimum value (%ld)", p, min);
return (1);
}
if (val > max) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
"%s: %s: Greater than maximum value (%ld)\n",
progname, p, max);
- exit(1);
- }
- dbp->errx(dbp, "%s: Greater than maximum value (%ld)", p, max);
- exit(1);
+ else
+ dbp->errx(dbp,
+ "%s: Greater than maximum value (%ld)", p, max);
+ return (1);
}
*storep = val;
return (0);
@@ -109,31 +106,29 @@ __db_getulong(dbp, progname, p, min, max, storep)
__os_set_errno(0);
val = strtoul(p, &end, 10);
if (val == ULONG_MAX && __os_get_errno() == ERANGE) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
"%s: %s: %s\n", progname, p, strerror(ERANGE));
- exit(1);
- }
- dbp->err(dbp, ERANGE, "%s", p);
+ else
+ dbp->err(dbp, ERANGE, "%s", p);
return (1);
}
if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
"%s: %s: Invalid numeric argument\n", progname, p);
- exit(1);
- }
- dbp->errx(dbp, "%s: Invalid numeric argument", p);
+ else
+ dbp->errx(dbp, "%s: Invalid numeric argument", p);
return (1);
}
if (val < min) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
- "%s: %s: Less than minimum value (%ld)\n",
+ "%s: %s: Less than minimum value (%lu)\n",
progname, p, min);
- exit(1);
- }
- dbp->errx(dbp, "%s: Less than minimum value (%ld)", p, min);
+ else
+ dbp->errx(dbp,
+ "%s: Less than minimum value (%lu)", p, min);
return (1);
}
@@ -144,14 +139,14 @@ __db_getulong(dbp, progname, p, min, max, storep)
* may not exist on all platforms.
*/
if (max != 0 && val > max) {
- if (dbp == NULL) {
+ if (dbp == NULL)
fprintf(stderr,
- "%s: %s: Greater than maximum value (%ld)\n",
+ "%s: %s: Greater than maximum value (%lu)\n",
progname, p, max);
- exit(1);
- }
- dbp->errx(dbp, "%s: Greater than maximum value (%ld)", p, max);
- exit(1);
+ else
+ dbp->errx(dbp,
+ "%s: Greater than maximum value (%lu)", p, max);
+ return (1);
}
*storep = val;
return (0);
diff --git a/bdb/common/db_idspace.c b/bdb/common/db_idspace.c
new file mode 100644
index 00000000000..588ffd9fca9
--- /dev/null
+++ b/bdb/common/db_idspace.c
@@ -0,0 +1,93 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_idspace.c,v 1.5 2002/02/01 18:15:29 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdlib.h>
+#endif
+
+#include "db_int.h"
+
+static int __db_idcmp __P((const void *, const void *));
+
+static int
+__db_idcmp(a, b)
+ const void *a;
+ const void *b;
+{
+ u_int32_t i, j;
+
+ i = *(u_int32_t *)a;
+ j = *(u_int32_t *)b;
+
+ if (i < j)
+ return (-1);
+ else if (i > j)
+ return (1);
+ else
+ return (0);
+}
+
+/*
+ * __db_idspace --
+ *
+ * On input, minp and maxp contain the minimum and maximum valid values for
+ * the name space and on return, they contain the minimum and maximum ids
+ * available (by finding the biggest gap).
+ *
+ * PUBLIC: void __db_idspace __P((u_int32_t *, int, u_int32_t *, u_int32_t *));
+ */
+void
+__db_idspace(inuse, n, minp, maxp)
+ u_int32_t *inuse;
+ int n;
+ u_int32_t *minp, *maxp;
+{
+ int i, low;
+ u_int32_t gap, t;
+
+ /* A single locker ID is a special case. */
+ if (n == 1) {
+ /*
+ * If the single item in use is the last one in the range,
+ * then we've got to perform wrap which means that we set
+ * the min to the minimum ID, which is what we came in with,
+ * so we don't do anything.
+ */
+ if (inuse[0] != *maxp)
+ *minp = inuse[0];
+ *maxp = inuse[0] - 1;
+ return;
+ }
+
+ gap = 0;
+ low = 0;
+ qsort(inuse, n, sizeof(u_int32_t), __db_idcmp);
+ for (i = 0; i < n - 1; i++)
+ if ((t = (inuse[i + 1] - inuse[i])) > gap) {
+ gap = t;
+ low = i;
+ }
+
+ /* Check for largest gap at the end of the space. */
+ if ((*maxp - inuse[n - 1]) + (inuse[0] - *minp) > gap) {
+ /* Do same check as we do in the n == 1 case. */
+ if (inuse[n - 1] != *maxp)
+ *minp = inuse[n - 1];
+ *maxp = inuse[0];
+ } else {
+ *minp = inuse[low];
+ *maxp = inuse[low + 1];
+ }
+}
diff --git a/bdb/common/db_log2.c b/bdb/common/db_log2.c
index 95bc69499c6..cdd87dda11d 100644
--- a/bdb/common/db_log2.c
+++ b/bdb/common/db_log2.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -39,7 +39,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_log2.c,v 11.4 2000/02/14 02:59:41 bostic Exp $";
+static const char revid[] = "$Id: db_log2.c,v 11.7 2002/02/01 18:15:30 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -47,7 +47,6 @@ static const char revid[] = "$Id: db_log2.c,v 11.4 2000/02/14 02:59:41 bostic Ex
#endif
#include "db_int.h"
-#include "common_ext.h"
/*
* PUBLIC: u_int32_t __db_log2 __P((u_int32_t));
diff --git a/bdb/common/util_arg.c b/bdb/common/util_arg.c
new file mode 100644
index 00000000000..e034e3bd194
--- /dev/null
+++ b/bdb/common/util_arg.c
@@ -0,0 +1,126 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: util_arg.c,v 1.4 2002/02/01 18:15:30 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+
+static char *__db_strsep __P((char **, const char *));
+
+/*
+ * __db_util_arg --
+ * Convert a string into an argc/argv pair.
+ *
+ * PUBLIC: int __db_util_arg __P((char *, char *, int *, char ***));
+ */
+int
+__db_util_arg(arg0, str, argcp, argvp)
+ char *arg0, *str, ***argvp;
+ int *argcp;
+{
+ int n, ret;
+ char **ap, **argv;
+
+#define MAXARGS 25
+ if ((ret =
+ __os_malloc(NULL, (MAXARGS + 1) * sizeof(char **), &argv)) != 0)
+ return (ret);
+
+ ap = argv;
+ *ap++ = arg0;
+ for (n = 1; (*ap = __db_strsep(&str, " \t")) != NULL;)
+ if (**ap != '\0') {
+ ++ap;
+ if (++n == MAXARGS)
+ break;
+ }
+ *ap = NULL;
+
+ *argcp = ap - argv;
+ *argvp = argv;
+
+ return (0);
+}
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+static char *
+__db_strsep(stringp, delim)
+ char **stringp;
+ const char *delim;
+{
+ const char *spanp;
+ int c, sc;
+ char *s, *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/bdb/common/util_cache.c b/bdb/common/util_cache.c
new file mode 100644
index 00000000000..5ca88665cc7
--- /dev/null
+++ b/bdb/common/util_cache.c
@@ -0,0 +1,92 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: util_cache.c,v 1.3 2002/04/04 18:50:10 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdlib.h>
+
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __db_util_cache --
+ * Compute if we have enough cache.
+ *
+ * PUBLIC: int __db_util_cache __P((DB_ENV *, DB *, u_int32_t *, int *));
+ */
+int
+__db_util_cache(dbenv, dbp, cachep, resizep)
+ DB_ENV *dbenv;
+ DB *dbp;
+ u_int32_t *cachep;
+ int *resizep;
+{
+ DBTYPE type;
+ DB_BTREE_STAT *bsp;
+ DB_HASH_STAT *hsp;
+ DB_QUEUE_STAT *qsp;
+ u_int32_t pgsize;
+ int ret;
+ void *sp;
+
+ /*
+ * The current cache size is in cachep. If it's insufficient, set the
+ * the memory referenced by resizep to 1 and set cachep to the minimum
+ * size needed.
+ */
+ if ((ret = dbp->get_type(dbp, &type)) != 0) {
+ dbenv->err(dbenv, ret, "DB->get_type");
+ return (ret);
+ }
+
+ if ((ret = dbp->stat(dbp, &sp, DB_FAST_STAT)) != 0) {
+ dbenv->err(dbenv, ret, "DB->stat");
+ return (ret);
+ }
+
+ switch (type) {
+ case DB_QUEUE:
+ qsp = (DB_QUEUE_STAT *)sp;
+ pgsize = qsp->qs_pagesize;
+ break;
+ case DB_HASH:
+ hsp = (DB_HASH_STAT *)sp;
+ pgsize = hsp->hash_pagesize;
+ break;
+ case DB_BTREE:
+ case DB_RECNO:
+ bsp = (DB_BTREE_STAT *)sp;
+ pgsize = bsp->bt_pagesize;
+ break;
+ default:
+ dbenv->err(dbenv, ret, "unknown database type: %d", type);
+ return (EINVAL);
+ }
+ free(sp);
+
+ /*
+ * Make sure our current cache is big enough. We want at least
+ * DB_MINPAGECACHE pages in the cache.
+ */
+ if ((*cachep / pgsize) < DB_MINPAGECACHE) {
+ *resizep = 1;
+ *cachep = pgsize * DB_MINPAGECACHE;
+ } else
+ *resizep = 0;
+
+ return (0);
+}
diff --git a/bdb/common/util_log.c b/bdb/common/util_log.c
index a4743cc2cee..ae215fca64a 100644
--- a/bdb/common/util_log.c
+++ b/bdb/common/util_log.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
+ * Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: util_log.c,v 1.7 2000/11/30 00:58:31 ubell Exp $";
+static const char revid[] = "$Id: util_log.c,v 1.11 2002/02/01 18:15:30 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -31,7 +31,6 @@ static const char revid[] = "$Id: util_log.c,v 1.7 2000/11/30 00:58:31 ubell Exp
#endif
#include "db_int.h"
-#include "common_ext.h"
/*
* __db_util_logset --
@@ -46,12 +45,14 @@ __db_util_logset(progname, fname)
{
FILE *fp;
time_t now;
+ u_int32_t id;
if ((fp = fopen(fname, "w")) == NULL)
goto err;
(void)time(&now);
- fprintf(fp, "%s: %lu %s", progname, (u_long)getpid(), ctime(&now));
+ __os_id(&id);
+ fprintf(fp, "%s: %lu %s", progname, (u_long)id, ctime(&now));
if (fclose(fp) == EOF)
goto err;
diff --git a/bdb/common/util_sig.c b/bdb/common/util_sig.c
index 6fe0166fe64..9714427ad33 100644
--- a/bdb/common/util_sig.c
+++ b/bdb/common/util_sig.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
+ * Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: util_sig.c,v 1.3 2000/04/28 19:32:00 bostic Exp $";
+static const char revid[] = "$Id: util_sig.c,v 1.7 2002/02/02 17:04:42 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,7 +18,6 @@ static const char revid[] = "$Id: util_sig.c,v 1.3 2000/04/28 19:32:00 bostic Ex
#endif
#include "db_int.h"
-#include "common_ext.h"
static int interrupt;
static void onint __P((int));
@@ -79,7 +78,7 @@ void
__db_util_sigresend()
{
/* Resend any caught signal. */
- if (__db_util_interrupted != 0) {
+ if (interrupt != 0) {
(void)signal(interrupt, SIG_DFL);
(void)raise(interrupt);
/* NOTREACHED */
diff --git a/bdb/cxx/cxx_app.cpp b/bdb/cxx/cxx_app.cpp
deleted file mode 100644
index 1fcf04b5c43..00000000000
--- a/bdb/cxx/cxx_app.cpp
+++ /dev/null
@@ -1,671 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: cxx_app.cpp,v 11.38 2000/12/21 20:30:18 dda Exp $";
-#endif /* not lint */
-
-#include <errno.h>
-#include <stdio.h> // needed for set_error_stream
-#include <string.h>
-
-#include "db_cxx.h"
-#include "cxx_int.h"
-
-#include "db_int.h"
-#include "common_ext.h"
-
-// The reason for a static variable is that some structures
-// (like Dbts) have no connection to any Db or DbEnv, so when
-// errors occur in their methods, we must have some reasonable
-// way to determine whether to throw or return errors.
-//
-// This variable is taken from flags whenever a DbEnv is constructed.
-// Normally there is only one DbEnv per program, and even if not,
-// there is typically a single policy of throwing or returning.
-//
-static int last_known_error_policy = ON_ERROR_UNKNOWN;
-
-////////////////////////////////////////////////////////////////////////
-// //
-// DbEnv //
-// //
-////////////////////////////////////////////////////////////////////////
-
-ostream *DbEnv::error_stream_ = 0;
-
-// _destroy_check is called when there is a user error in a
-// destructor, specifically when close has not been called for an
-// object (even if it was never opened). If the DbEnv is being
-// destroyed we cannot always use DbEnv::error_stream_, so we'll
-// use cerr in that case.
-//
-void DbEnv::_destroy_check(const char *str, int isDbEnv)
-{
- ostream *out;
-
- out = error_stream_;
- if (out == NULL || isDbEnv == 1)
- out = &cerr;
-
- (*out) << "DbEnv::_destroy_check: open " << str << " object destroyed\n";
-}
-
-// A truism for the DbEnv object is that there is a valid
-// DB_ENV handle from the constructor until close().
-// After the close, the DB_ENV handle is invalid and
-// no operations are permitted on the DbEnv (other than
-// destructor). Leaving the DbEnv handle open and not
-// doing a close is generally considered an error.
-//
-// We used to allow DbEnv objects to be closed and reopened.
-// This implied always keeping a valid DB_ENV object, and
-// coordinating the open objects between Db/DbEnv turned
-// out to be overly complicated. Now we do not allow this.
-
-DbEnv::DbEnv(u_int32_t flags)
-: imp_(0)
-, construct_error_(0)
-, construct_flags_(flags)
-, tx_recover_callback_(0)
-, paniccall_callback_(0)
-{
- int err;
-
- COMPQUIET(err, 0);
- if ((err = initialize(0)) != 0)
- DB_ERROR("DbEnv::DbEnv", err, error_policy());
-}
-
-DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
-: imp_(0)
-, construct_error_(0)
-, construct_flags_(flags)
-, tx_recover_callback_(0)
-, paniccall_callback_(0)
-{
- int err;
-
- COMPQUIET(err, 0);
- if ((err = initialize(env)) != 0)
- DB_ERROR("DbEnv::DbEnv", err, error_policy());
-}
-
-// Note: if the user has not closed, we call _destroy_check
-// to warn against this non-safe programming practice,
-// and call close anyway.
-//
-DbEnv::~DbEnv()
-{
- DB_ENV *env = unwrap(this);
-
- if (env != NULL) {
- _destroy_check("DbEnv", 1);
- (void)env->close(env, 0);
-
- // extra safety
- cleanup();
- }
-}
-
-// called by Db destructor when the DbEnv is owned by DB.
-void DbEnv::cleanup()
-{
- DB_ENV *env = unwrap(this);
-
- if (env != NULL) {
- env->cj_internal = 0;
- imp_ = 0;
- }
-}
-
-int DbEnv::close(u_int32_t flags)
-{
- DB_ENV *env = unwrap(this);
- int err, init_err;
-
- COMPQUIET(init_err, 0);
-
- // after a close (no matter if success or failure),
- // the underlying DB_ENV object must not be accessed,
- // so we clean up in advance.
- //
- cleanup();
-
- // It's safe to throw an error after the close,
- // since our error mechanism does not peer into
- // the DB* structures.
- //
- if ((err = env->close(env, flags)) != 0) {
- DB_ERROR("DbEnv::close", err, error_policy());
- }
- return (err);
-}
-
-void DbEnv::err(int error, const char *format, ...)
-{
- va_list args;
- DB_ENV *env = unwrap(this);
-
- va_start(args, format);
- __db_real_err(env, error, 1, 1, format, args);
- va_end(args);
-}
-
-void DbEnv::errx(const char *format, ...)
-{
- va_list args;
- DB_ENV *env = unwrap(this);
-
- va_start(args, format);
- __db_real_err(env, 0, 0, 1, format, args);
- va_end(args);
-}
-
-// used internally during constructor
-// to associate an existing DB_ENV with this DbEnv,
-// or create a new one. If there is an error,
-// construct_error_ is set; this is examined during open.
-//
-int DbEnv::initialize(DB_ENV *env)
-{
- int err;
-
- last_known_error_policy = error_policy();
-
- if (env == 0) {
- // Create a new DB_ENV environment.
- if ((err = ::db_env_create(&env,
- construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0) {
- construct_error_ = err;
- return (err);
- }
- }
- imp_ = wrap(env);
- env->cj_internal = this; // for DB_ENV* to DbEnv* conversion
- return (0);
-}
-
-// Return a tristate value corresponding to whether we should
-// throw exceptions on errors:
-// ON_ERROR_RETURN
-// ON_ERROR_THROW
-// ON_ERROR_UNKNOWN
-//
-int DbEnv::error_policy()
-{
- if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
- return (ON_ERROR_RETURN);
- }
- else {
- return (ON_ERROR_THROW);
- }
-}
-
-// If an error occurred during the constructor, report it now.
-// Otherwise, call the underlying DB->open method.
-//
-int DbEnv::open(const char *db_home, u_int32_t flags, int mode)
-{
- DB_ENV *env = unwrap(this);
- int err;
-
- if ((err = construct_error_) != 0)
- DB_ERROR("Db::open", err, error_policy());
- else if ((err = env->open(env, db_home, flags, mode)) != 0)
- DB_ERROR("DbEnv::open", err, error_policy());
-
- return (err);
-}
-
-int DbEnv::remove(const char *db_home, u_int32_t flags)
-{
- DB_ENV *env;
- int ret;
-
- env = unwrap(this);
-
- // after a remove (no matter if success or failure),
- // the underlying DB_ENV object must not be accessed,
- // so we clean up in advance.
- //
- cleanup();
-
- if ((ret = env->remove(env, db_home, flags)) != 0)
- DB_ERROR("DbEnv::remove", ret, error_policy());
-
- return (ret);
-}
-
-// Report an error associated with the DbEnv.
-// error_policy is one of:
-// ON_ERROR_THROW throw an error
-// ON_ERROR_RETURN do nothing here, the caller will return an error
-// ON_ERROR_UNKNOWN defer the policy to policy saved in DbEnv::DbEnv
-//
-void DbEnv::runtime_error(const char *caller, int error, int error_policy)
-{
- if (error_policy == ON_ERROR_UNKNOWN)
- error_policy = last_known_error_policy;
- if (error_policy == ON_ERROR_THROW) {
- // Creating and throwing the object in two separate
- // statements seems to be necessary for HP compilers.
- DbException except(caller, error);
- throw except;
- }
-}
-
-// static method
-char *DbEnv::strerror(int error)
-{
- return (db_strerror(error));
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-void _stream_error_function_c(const char *prefix, char *message)
-{
- DbEnv::_stream_error_function(prefix, message);
-}
-
-void DbEnv::_stream_error_function(const char *prefix, char *message)
-{
- // HP compilers need the extra casts, we don't know why.
- if (error_stream_) {
- if (prefix) {
- (*error_stream_) << prefix << (const char *)": ";
- }
- if (message) {
- (*error_stream_) << (const char *)message;
- }
- (*error_stream_) << (const char *)"\n";
- }
-}
-
-// Note: This actually behaves a bit like a static function,
-// since DB_ENV.db_errcall has no information about which
-// db_env triggered the call. A user that has multiple DB_ENVs
-// will simply not be able to have different streams for each one.
-//
-void DbEnv::set_error_stream(ostream *stream)
-{
- DB_ENV *dbenv = unwrap(this);
-
- error_stream_ = stream;
- dbenv->set_errcall(dbenv, (stream == 0) ? 0 :
- _stream_error_function_c);
-}
-
-// static method
-char *DbEnv::version(int *major, int *minor, int *patch)
-{
- return (db_version(major, minor, patch));
-}
-
-// This is a variant of the DB_WO_ACCESS macro to define a simple set_
-// method calling the underlying C method, but unlike a simple
-// set method, it may return an error or raise an exception.
-// Note this macro expects that input _argspec is an argument
-// list element (e.g. "char *arg") defined in terms of "arg".
-//
-#define DB_DBENV_ACCESS(_name, _argspec) \
- \
-int DbEnv::set_##_name(_argspec) \
-{ \
- int ret; \
- DB_ENV *dbenv = unwrap(this); \
- \
- if ((ret = (*(dbenv->set_##_name))(dbenv, arg)) != 0) {\
- DB_ERROR("DbEnv::set_" # _name, ret, error_policy()); \
- } \
- return (ret); \
-}
-
-#define DB_DBENV_ACCESS_NORET(_name, _argspec) \
- \
-void DbEnv::set_##_name(_argspec) \
-{ \
- DB_ENV *dbenv = unwrap(this); \
- \
- (*(dbenv->set_##_name))(dbenv, arg); \
- return; \
-}
-
-DB_DBENV_ACCESS_NORET(errfile, FILE *arg)
-DB_DBENV_ACCESS_NORET(errpfx, const char *arg)
-
-// We keep these alphabetical by field name,
-// for comparison with Java's list.
-//
-DB_DBENV_ACCESS(data_dir, const char *arg)
-DB_DBENV_ACCESS(lg_bsize, u_int32_t arg)
-DB_DBENV_ACCESS(lg_dir, const char *arg)
-DB_DBENV_ACCESS(lg_max, u_int32_t arg)
-DB_DBENV_ACCESS(lk_detect, u_int32_t arg)
-DB_DBENV_ACCESS(lk_max, u_int32_t arg)
-DB_DBENV_ACCESS(lk_max_lockers, u_int32_t arg)
-DB_DBENV_ACCESS(lk_max_locks, u_int32_t arg)
-DB_DBENV_ACCESS(lk_max_objects, u_int32_t arg)
-DB_DBENV_ACCESS(mp_mmapsize, size_t arg)
-DB_DBENV_ACCESS(mutexlocks, int arg)
-DB_DBENV_ACCESS(tmp_dir, const char *arg)
-DB_DBENV_ACCESS(tx_max, u_int32_t arg)
-
-// Here are the set methods that don't fit the above mold.
-//
-extern "C" {
- typedef void (*db_errcall_fcn_type)
- (const char *, char *);
-};
-
-void DbEnv::set_errcall(void (*arg)(const char *, char *))
-{
- DB_ENV *dbenv = unwrap(this);
-
- // XXX
- // We are casting from a function ptr declared with C++
- // linkage to one (same arg types) declared with C
- // linkage. It's hard to imagine a pair of C/C++
- // compilers from the same vendor for which this
- // won't work. Unfortunately, we can't use a
- // intercept function like the others since the
- // function does not have a (DbEnv*) as one of
- // the args. If this causes trouble, we can pull
- // the same trick we use in Java, namely stuffing
- // a (DbEnv*) pointer into the prefix. We're
- // avoiding this for the moment because it obfuscates.
- //
- (*(dbenv->set_errcall))(dbenv, (db_errcall_fcn_type)arg);
-}
-
-int DbEnv::set_cachesize(u_int32_t gbytes, u_int32_t bytes, int ncache)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret =
- (*(dbenv->set_cachesize))(dbenv, gbytes, bytes, ncache)) != 0)
- DB_ERROR("DbEnv::set_cachesize", ret, error_policy());
-
- return (ret);
-}
-
-int DbEnv::set_flags(u_int32_t flags, int onoff)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret = (dbenv->set_flags)(dbenv, flags, onoff)) != 0)
- DB_ERROR("DbEnv::set_flags", ret, error_policy());
-
- return (ret);
-}
-
-int DbEnv::set_lk_conflicts(u_int8_t *lk_conflicts, int lk_max)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret = (*(dbenv->set_lk_conflicts))
- (dbenv, lk_conflicts, lk_max)) != 0)
- DB_ERROR("DbEnv::set_lk_conflicts", ret, error_policy());
-
- return (ret);
-}
-
-// static method
-int DbEnv::set_pageyield(int arg)
-{
- int ret;
-
- if ((ret = db_env_set_pageyield(arg)) != 0)
- DB_ERROR("DbEnv::set_pageyield", ret, last_known_error_policy);
-
- return (ret);
-}
-
-// static method
-int DbEnv::set_panicstate(int arg)
-{
- int ret;
-
- if ((ret = db_env_set_panicstate(arg)) != 0)
- DB_ERROR("DbEnv::set_panicstate", ret, last_known_error_policy);
-
- return (ret);
-}
-
-// static method
-int DbEnv::set_region_init(int arg)
-{
- int ret;
-
- if ((ret = db_env_set_region_init(arg)) != 0)
- DB_ERROR("DbEnv::set_region_init", ret, last_known_error_policy);
-
- return (ret);
-}
-
-int DbEnv::set_server(char *host, long tsec, long ssec, u_int32_t flags)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret = dbenv->set_server(dbenv, host, tsec, ssec, flags)) != 0)
- DB_ERROR("DbEnv::set_server", ret, error_policy());
-
- return (ret);
-}
-
-int DbEnv::set_shm_key(long shm_key)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret = dbenv->set_shm_key(dbenv, shm_key)) != 0)
- DB_ERROR("DbEnv::set_shm_key", ret, error_policy());
-
- return (ret);
-}
-
-// static method
-int DbEnv::set_tas_spins(u_int32_t arg)
-{
- int ret;
-
- if ((ret = db_env_set_tas_spins(arg)) != 0)
- DB_ERROR("DbEnv::set_tas_spins", ret, last_known_error_policy);
-
- return (ret);
-}
-
-int DbEnv::set_verbose(u_int32_t which, int onoff)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret = (*(dbenv->set_verbose))(dbenv, which, onoff)) != 0)
- DB_ERROR("DbEnv::set_verbose", ret, error_policy());
-
- return (ret);
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-int _tx_recover_intercept_c(DB_ENV *env, DBT *dbt,
- DB_LSN *lsn, db_recops op)
-{
- return (DbEnv::_tx_recover_intercept(env, dbt, lsn, op));
-}
-
-int DbEnv::_tx_recover_intercept(DB_ENV *env, DBT *dbt,
- DB_LSN *lsn, db_recops op)
-{
- if (env == 0) {
- DB_ERROR("DbEnv::tx_recover_callback", EINVAL, ON_ERROR_UNKNOWN);
- return (EINVAL);
- }
- DbEnv *cxxenv = (DbEnv *)env->cj_internal;
- if (cxxenv == 0) {
- DB_ERROR("DbEnv::tx_recover_callback", EINVAL, ON_ERROR_UNKNOWN);
- return (EINVAL);
- }
- if (cxxenv->tx_recover_callback_ == 0) {
- DB_ERROR("DbEnv::tx_recover_callback", EINVAL, cxxenv->error_policy());
- return (EINVAL);
- }
- Dbt *cxxdbt = (Dbt *)dbt;
- DbLsn *cxxlsn = (DbLsn *)lsn;
- return ((*cxxenv->tx_recover_callback_)(cxxenv, cxxdbt, cxxlsn, op));
-}
-
-int DbEnv::set_tx_recover
- (int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops))
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- tx_recover_callback_ = arg;
- if ((ret =
- (*(dbenv->set_tx_recover))(dbenv, _tx_recover_intercept_c)) != 0)
- DB_ERROR("DbEnv::set_tx_recover", ret, error_policy());
-
- return (ret);
-}
-
-int DbEnv::set_tx_timestamp(time_t *timestamp)
-{
- int ret;
- DB_ENV *dbenv = unwrap(this);
-
- if ((ret = dbenv->set_tx_timestamp(dbenv, timestamp)) != 0)
- DB_ERROR("DbEnv::set_tx_timestamp", ret, error_policy());
-
- return (ret);
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-void _paniccall_intercept_c(DB_ENV *env, int errval)
-{
- DbEnv::_paniccall_intercept(env, errval);
-}
-
-void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
-{
- if (env == 0) {
- DB_ERROR("DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN);
- }
- DbEnv *cxxenv = (DbEnv *)env->cj_internal;
- if (cxxenv == 0) {
- DB_ERROR("DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN);
- }
- if (cxxenv->paniccall_callback_ == 0) {
- DB_ERROR("DbEnv::paniccall_callback", EINVAL, cxxenv->error_policy());
- }
- (*cxxenv->paniccall_callback_)(cxxenv, errval);
-}
-
-int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
-{
- DB_ENV *dbenv = unwrap(this);
-
- paniccall_callback_ = arg;
-
- return ((*(dbenv->set_paniccall))(dbenv, _paniccall_intercept_c));
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-int _recovery_init_intercept_c(DB_ENV *env)
-{
- return (DbEnv::_recovery_init_intercept(env));
-}
-
-int DbEnv::_recovery_init_intercept(DB_ENV *env)
-{
- if (env == 0) {
- DB_ERROR("DbEnv::recovery_init_callback", EINVAL,
- ON_ERROR_UNKNOWN);
- }
- DbEnv *cxxenv = (DbEnv *)env->cj_internal;
- if (cxxenv == 0) {
- DB_ERROR("DbEnv::recovery_init_callback", EINVAL,
- ON_ERROR_UNKNOWN);
- }
- if (cxxenv->recovery_init_callback_ == 0) {
- DB_ERROR("DbEnv::recovery_init_callback", EINVAL,
- cxxenv->error_policy());
- }
- return ((*cxxenv->recovery_init_callback_)(cxxenv));
-}
-
-int DbEnv::set_recovery_init(int (*arg)(DbEnv *))
-{
- DB_ENV *dbenv = unwrap(this);
-
- recovery_init_callback_ = arg;
-
- return ((*(dbenv->set_recovery_init))(dbenv, _recovery_init_intercept_c));
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-void _feedback_intercept_c(DB_ENV *env, int opcode, int pct)
-{
- DbEnv::_feedback_intercept(env, opcode, pct);
-}
-
-void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
-{
- if (env == 0) {
- DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
- return;
- }
- DbEnv *cxxenv = (DbEnv *)env->cj_internal;
- if (cxxenv == 0) {
- DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
- return;
- }
- if (cxxenv->feedback_callback_ == 0) {
- DB_ERROR("DbEnv::feedback_callback", EINVAL,
- cxxenv->error_policy());
- return;
- }
- (*cxxenv->feedback_callback_)(cxxenv, opcode, pct);
-}
-
-int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
-{
- DB_ENV *dbenv = unwrap(this);
-
- feedback_callback_ = arg;
-
- return ((*(dbenv->set_feedback))(dbenv, _feedback_intercept_c));
-}
diff --git a/bdb/cxx/cxx_db.cpp b/bdb/cxx/cxx_db.cpp
new file mode 100644
index 00000000000..7e50a9b3f27
--- /dev/null
+++ b/bdb/cxx/cxx_db.cpp
@@ -0,0 +1,605 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: cxx_db.cpp,v 11.71 2002/08/26 22:13:36 mjc Exp $";
+#endif /* not lint */
+
+#include <errno.h>
+#include <string.h>
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc_auto/db_auto.h"
+#include "dbinc_auto/crdel_auto.h"
+#include "dbinc/db_dispatch.h"
+#include "dbinc_auto/db_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+// Helper macros for simple methods that pass through to the
+// underlying C method. It may return an error or raise an exception.
+// Note this macro expects that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(db, arg)")
+//
+#define DB_METHOD(_name, _argspec, _arglist, _retok) \
+int Db::_name _argspec \
+{ \
+ int ret; \
+ DB *db = unwrap(this); \
+ \
+ ret = db->_name _arglist; \
+ if (!_retok(ret)) \
+ DB_ERROR("Db::" # _name, ret, error_policy()); \
+ return (ret); \
+}
+
+#define DB_METHOD_CHECKED(_name, _cleanup, _argspec, _arglist, _retok) \
+int Db::_name _argspec \
+{ \
+ int ret; \
+ DB *db = unwrap(this); \
+ \
+ if (!db) { \
+ DB_ERROR("Db::" # _name, EINVAL, error_policy()); \
+ return (EINVAL); \
+ } \
+ if (_cleanup) \
+ cleanup(); \
+ ret = db->_name _arglist; \
+ if (!_retok(ret)) \
+ DB_ERROR("Db::" # _name, ret, error_policy()); \
+ return (ret); \
+}
+
+#define DB_METHOD_QUIET(_name, _argspec, _arglist) \
+int Db::_name _argspec \
+{ \
+ DB *db = unwrap(this); \
+ \
+ return (db->_name _arglist); \
+}
+
+#define DB_METHOD_VOID(_name, _argspec, _arglist) \
+void Db::_name _argspec \
+{ \
+ DB *db = unwrap(this); \
+ \
+ db->_name _arglist; \
+}
+
+// A truism for the Db object is that there is a valid
+// DB handle from the constructor until close().
+// After the close, the DB handle is invalid and
+// no operations are permitted on the Db (other than
+// destructor). Leaving the Db handle open and not
+// doing a close is generally considered an error.
+//
+// We used to allow Db objects to be closed and reopened.
+// This implied always keeping a valid DB object, and
+// coordinating the open objects between Db/DbEnv turned
+// out to be overly complicated. Now we do not allow this.
+
+Db::Db(DbEnv *env, u_int32_t flags)
+: imp_(0)
+, env_(env)
+, construct_error_(0)
+, flags_(0)
+, construct_flags_(flags)
+, append_recno_callback_(0)
+, associate_callback_(0)
+, bt_compare_callback_(0)
+, bt_prefix_callback_(0)
+, dup_compare_callback_(0)
+, feedback_callback_(0)
+, h_hash_callback_(0)
+{
+ if (env_ == 0)
+ flags_ |= DB_CXX_PRIVATE_ENV;
+
+ if ((construct_error_ = initialize()) != 0)
+ DB_ERROR("Db::Db", construct_error_, error_policy());
+}
+
+// If the DB handle is still open, we close it. This is to make stack
+// allocation of Db objects easier so that they are cleaned up in the error
+// path. If the environment was closed prior to this, it may cause a trap, but
+// an error message is generated during the environment close. Applications
+// should call close explicitly in normal (non-exceptional) cases to check the
+// return value.
+//
+Db::~Db()
+{
+ DB *db;
+
+ db = unwrap(this);
+ if (db != NULL) {
+ cleanup();
+ (void)db->close(db, 0);
+ }
+}
+
+// private method to initialize during constructor.
+// initialize must create a backing DB object,
+// and if that creates a new DB_ENV, it must be tied to a new DbEnv.
+//
+int Db::initialize()
+{
+ DB *db;
+ DB_ENV *cenv = unwrap(env_);
+ int ret;
+ u_int32_t cxx_flags;
+
+ cxx_flags = construct_flags_ & DB_CXX_NO_EXCEPTIONS;
+
+ // Create a new underlying DB object.
+ // We rely on the fact that if a NULL DB_ENV* is given,
+ // one is allocated by DB.
+ //
+ if ((ret = db_create(&db, cenv,
+ construct_flags_ & ~cxx_flags)) != 0)
+ return (ret);
+
+ // Associate the DB with this object
+ imp_ = wrap(db);
+ db->api_internal = this;
+
+ // Create a new DbEnv from a DB_ENV* if it was created locally.
+ // It is deleted in Db::close().
+ //
+ if ((flags_ & DB_CXX_PRIVATE_ENV) != 0)
+ env_ = new DbEnv(db->dbenv, cxx_flags);
+
+ return (0);
+}
+
+// private method to cleanup after destructor or during close.
+// If the environment was created by this Db object, we optionally
+// delete it, or return it so the caller can delete it after
+// last use.
+//
+void Db::cleanup()
+{
+ DB *db = unwrap(this);
+
+ if (db != NULL) {
+ // extra safety
+ db->api_internal = 0;
+ imp_ = 0;
+
+ // we must dispose of the DbEnv object if
+ // we created it. This will be the case
+ // if a NULL DbEnv was passed into the constructor.
+ // The underlying DB_ENV object will be inaccessible
+ // after the close, so we must clean it up now.
+ //
+ if ((flags_ & DB_CXX_PRIVATE_ENV) != 0) {
+ env_->cleanup();
+ delete env_;
+ env_ = 0;
+ }
+ }
+}
+
+// Return a tristate value corresponding to whether we should
+// throw exceptions on errors:
+// ON_ERROR_RETURN
+// ON_ERROR_THROW
+// ON_ERROR_UNKNOWN
+//
+int Db::error_policy()
+{
+ if (env_ != NULL)
+ return (env_->error_policy());
+ else {
+ // If the env_ is null, that means that the user
+ // did not attach an environment, so the correct error
+ // policy can be deduced from constructor flags
+ // for this Db.
+ //
+ if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
+ return (ON_ERROR_RETURN);
+ }
+ else {
+ return (ON_ERROR_THROW);
+ }
+ }
+}
+
+int Db::close(u_int32_t flags)
+{
+ DB *db = unwrap(this);
+ int ret;
+
+ // after a DB->close (no matter if success or failure),
+ // the underlying DB object must not be accessed,
+ // so we clean up in advance.
+ //
+ cleanup();
+
+ // It's safe to throw an error after the close,
+ // since our error mechanism does not peer into
+ // the DB* structures.
+ //
+ if ((ret = db->close(db, flags)) != 0)
+ DB_ERROR("Db::close", ret, error_policy());
+
+ return (ret);
+}
+
+// The following cast implies that Dbc can be no larger than DBC
+DB_METHOD(cursor, (DbTxn *txnid, Dbc **cursorp, u_int32_t flags),
+ (db, unwrap(txnid), (DBC **)cursorp, flags),
+ DB_RETOK_STD)
+
+DB_METHOD(del, (DbTxn *txnid, Dbt *key, u_int32_t flags),
+ (db, unwrap(txnid), key, flags),
+ DB_RETOK_DBDEL)
+
+void Db::err(int error, const char *format, ...)
+{
+ DB *db = unwrap(this);
+
+ DB_REAL_ERR(db->dbenv, error, 1, 1, format);
+}
+
+void Db::errx(const char *format, ...)
+{
+ DB *db = unwrap(this);
+
+ DB_REAL_ERR(db->dbenv, 0, 0, 1, format);
+}
+
+DB_METHOD(fd, (int *fdp),
+ (db, fdp),
+ DB_RETOK_STD)
+
+int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
+{
+ DB *db = unwrap(this);
+ int ret;
+
+ ret = db->get(db, unwrap(txnid), key, value, flags);
+
+ if (!DB_RETOK_DBGET(ret)) {
+ if (ret == ENOMEM && DB_OVERFLOWED_DBT(value))
+ DB_ERROR_DBT("Db::get", value, error_policy());
+ else
+ DB_ERROR("Db::get", ret, error_policy());
+ }
+
+ return (ret);
+}
+
+int Db::get_byteswapped(int *isswapped)
+{
+ DB *db = (DB *)unwrapConst(this);
+ return (db->get_byteswapped(db, isswapped));
+}
+
+int Db::get_type(DBTYPE *dbtype)
+{
+ DB *db = (DB *)unwrapConst(this);
+ return (db->get_type(db, dbtype));
+}
+
+// Dbc is a "compatible" subclass of DBC - that is, no virtual functions
+// or even extra data members, so these casts, although technically
+// non-portable, "should" always be okay.
+DB_METHOD(join, (Dbc **curslist, Dbc **cursorp, u_int32_t flags),
+ (db, (DBC **)curslist, (DBC **)cursorp, flags),
+ DB_RETOK_STD)
+
+DB_METHOD(key_range,
+ (DbTxn *txnid, Dbt *key, DB_KEY_RANGE *results, u_int32_t flags),
+ (db, unwrap(txnid), key, results, flags),
+ DB_RETOK_STD)
+
+// If an error occurred during the constructor, report it now.
+// Otherwise, call the underlying DB->open method.
+//
+int Db::open(DbTxn *txnid, const char *file, const char *database,
+ DBTYPE type, u_int32_t flags, int mode)
+{
+ int ret;
+ DB *db = unwrap(this);
+
+ if (construct_error_ != 0)
+ ret = construct_error_;
+ else
+ ret = db->open(db, unwrap(txnid), file, database, type, flags,
+ mode);
+
+ if (!DB_RETOK_STD(ret))
+ DB_ERROR("Db::open", ret, error_policy());
+
+ return (ret);
+}
+
+int Db::pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *value, u_int32_t flags)
+{
+ DB *db = unwrap(this);
+ int ret;
+
+ ret = db->pget(db, unwrap(txnid), key, pkey, value, flags);
+
+ /* The logic here is identical to Db::get - reuse the macro. */
+ if (!DB_RETOK_DBGET(ret)) {
+ if (ret == ENOMEM && DB_OVERFLOWED_DBT(value))
+ DB_ERROR_DBT("Db::pget", value, error_policy());
+ else
+ DB_ERROR("Db::pget", ret, error_policy());
+ }
+
+ return (ret);
+}
+
+DB_METHOD(put,
+ (DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags),
+ (db, unwrap(txnid), key, value, flags),
+ DB_RETOK_DBPUT)
+
+DB_METHOD_CHECKED(rename, 1,
+ (const char *file, const char *database, const char *newname,
+ u_int32_t flags),
+ (db, file, database, newname, flags), DB_RETOK_STD)
+
+DB_METHOD_CHECKED(remove, 1,
+ (const char *file, const char *database, u_int32_t flags),
+ (db, file, database, flags), DB_RETOK_STD)
+
+DB_METHOD_CHECKED(truncate, 0,
+ (DbTxn *txnid, u_int32_t *countp, u_int32_t flags),
+ (db, unwrap(txnid), countp, flags), DB_RETOK_STD)
+
+DB_METHOD_CHECKED(stat, 0,
+ (void *sp, u_int32_t flags), (db, sp, flags), DB_RETOK_STD)
+
+DB_METHOD_CHECKED(sync, 0,
+ (u_int32_t flags), (db, flags), DB_RETOK_STD)
+
+DB_METHOD_CHECKED(upgrade, 0,
+ (const char *name, u_int32_t flags), (db, name, flags), DB_RETOK_STD)
+
+////////////////////////////////////////////////////////////////////////
+//
+// callbacks
+//
+// *_intercept_c are 'glue' functions that must be declared
+// as extern "C" so to be typesafe. Using a C++ method, even
+// a static class method with 'correct' arguments, will not pass
+// the test; some picky compilers do not allow mixing of function
+// pointers to 'C' functions with function pointers to C++ functions.
+//
+// One wart with this scheme is that the *_callback_ method pointer
+// must be declared public to be accessible by the C intercept.
+// It's possible to accomplish the goal without this, and with
+// another public transfer method, but it's just too much overhead.
+// These callbacks are supposed to be *fast*.
+//
+// The DBTs we receive in these callbacks from the C layer may be
+// manufactured there, but we want to treat them as a Dbts.
+// Technically speaking, these DBTs were not constructed as a Dbts,
+// but it should be safe to cast them as such given that Dbt is a
+// *very* thin extension of the DBT. That is, Dbt has no additional
+// data elements, does not use virtual functions, virtual inheritance,
+// multiple inheritance, RTI, or any other language feature that
+// causes the structure to grow or be displaced. Although this may
+// sound risky, a design goal of C++ is complete structure
+// compatibility with C, and has the philosophy 'if you don't use it,
+// you shouldn't incur the overhead'. If the C/C++ compilers you're
+// using on a given machine do not have matching struct layouts, then
+// a lot more things will be broken than just this.
+//
+// The alternative, creating a Dbt here in the callback, and populating
+// it from the DBT, is just too slow and cumbersome to be very useful.
+
+// These macros avoid a lot of boilerplate code for callbacks
+
+#define DB_CALLBACK_C_INTERCEPT(_name, _rettype, _cargspec, \
+ _return, _cxxargs) \
+extern "C" _rettype _db_##_name##_intercept_c _cargspec \
+{ \
+ Db *cxxthis; \
+ \
+ DB_ASSERT(cthis != NULL); \
+ cxxthis = (Db *)cthis->api_internal; \
+ DB_ASSERT(cxxthis != NULL); \
+ DB_ASSERT(cxxthis->_name##_callback_ != 0); \
+ \
+ _return (*cxxthis->_name##_callback_) _cxxargs; \
+}
+
+#define DB_SET_CALLBACK(_cxxname, _name, _cxxargspec, _cb) \
+int Db::_cxxname _cxxargspec \
+{ \
+ DB *cthis = unwrap(this); \
+ \
+ _name##_callback_ = _cb; \
+ return ((*(cthis->_cxxname))(cthis, \
+ (_cb) ? _db_##_name##_intercept_c : NULL)); \
+}
+
+/* associate callback - doesn't quite fit the pattern because of the flags */
+DB_CALLBACK_C_INTERCEPT(associate,
+ int, (DB *cthis, const DBT *key, const DBT *data, DBT *retval),
+ return, (cxxthis, Dbt::get_const_Dbt(key), Dbt::get_const_Dbt(data),
+ Dbt::get_Dbt(retval)))
+
+int Db::associate(DbTxn *txn, Db *secondary, int (*callback)(Db *, const Dbt *,
+ const Dbt *, Dbt *), u_int32_t flags)
+{
+ DB *cthis = unwrap(this);
+
+ /* Since the secondary Db is used as the first argument
+ * to the callback, we store the C++ callback on it
+ * rather than on 'this'.
+ */
+ secondary->associate_callback_ = callback;
+ return ((*(cthis->associate))(cthis, unwrap(txn), unwrap(secondary),
+ (callback) ? _db_associate_intercept_c : NULL, flags));
+}
+
+DB_CALLBACK_C_INTERCEPT(feedback,
+ void, (DB *cthis, int opcode, int pct),
+ /* no return */ (void), (cxxthis, opcode, pct))
+
+DB_SET_CALLBACK(set_feedback, feedback,
+ (void (*arg)(Db *cxxthis, int opcode, int pct)), arg)
+
+DB_CALLBACK_C_INTERCEPT(append_recno,
+ int, (DB *cthis, DBT *data, db_recno_t recno),
+ return, (cxxthis, Dbt::get_Dbt(data), recno))
+
+DB_SET_CALLBACK(set_append_recno, append_recno,
+ (int (*arg)(Db *cxxthis, Dbt *data, db_recno_t recno)), arg)
+
+DB_CALLBACK_C_INTERCEPT(bt_compare,
+ int, (DB *cthis, const DBT *data1, const DBT *data2),
+ return,
+ (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2)))
+
+DB_SET_CALLBACK(set_bt_compare, bt_compare,
+ (int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg)
+
+DB_CALLBACK_C_INTERCEPT(bt_prefix,
+ size_t, (DB *cthis, const DBT *data1, const DBT *data2),
+ return,
+ (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2)))
+
+DB_SET_CALLBACK(set_bt_prefix, bt_prefix,
+ (size_t (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg)
+
+DB_CALLBACK_C_INTERCEPT(dup_compare,
+ int, (DB *cthis, const DBT *data1, const DBT *data2),
+ return,
+ (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2)))
+
+DB_SET_CALLBACK(set_dup_compare, dup_compare,
+ (int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg)
+
+DB_CALLBACK_C_INTERCEPT(h_hash,
+ u_int32_t, (DB *cthis, const void *data, u_int32_t len),
+ return, (cxxthis, data, len))
+
+DB_SET_CALLBACK(set_h_hash, h_hash,
+ (u_int32_t (*arg)(Db *cxxthis, const void *data, u_int32_t len)), arg)
+
+// This is a 'glue' function declared as extern "C" so it will
+// be compatible with picky compilers that do not allow mixing
+// of function pointers to 'C' functions with function pointers
+// to C++ functions.
+//
+extern "C"
+int _verify_callback_c(void *handle, const void *str_arg)
+{
+ char *str;
+ __DB_OSTREAMCLASS *out;
+
+ str = (char *)str_arg;
+ out = (__DB_OSTREAMCLASS *)handle;
+
+ (*out) << str;
+ if (out->fail())
+ return (EIO);
+
+ return (0);
+}
+
+int Db::verify(const char *name, const char *subdb,
+ __DB_OSTREAMCLASS *ostr, u_int32_t flags)
+{
+ DB *db = unwrap(this);
+ int ret;
+
+ if (!db)
+ ret = EINVAL;
+ else
+ ret = __db_verify_internal(db, name, subdb, ostr,
+ _verify_callback_c, flags);
+
+ if (!DB_RETOK_STD(ret))
+ DB_ERROR("Db::verify", ret, error_policy());
+
+ return (ret);
+}
+
+DB_METHOD(set_bt_compare, (bt_compare_fcn_type func),
+ (db, func), DB_RETOK_STD)
+DB_METHOD(set_bt_maxkey, (u_int32_t bt_maxkey),
+ (db, bt_maxkey), DB_RETOK_STD)
+DB_METHOD(set_bt_minkey, (u_int32_t bt_minkey),
+ (db, bt_minkey), DB_RETOK_STD)
+DB_METHOD(set_bt_prefix, (bt_prefix_fcn_type func),
+ (db, func), DB_RETOK_STD)
+DB_METHOD(set_dup_compare, (dup_compare_fcn_type func),
+ (db, func), DB_RETOK_STD)
+DB_METHOD(set_encrypt, (const char *passwd, int flags),
+ (db, passwd, flags), DB_RETOK_STD)
+DB_METHOD_VOID(set_errfile, (FILE *errfile), (db, errfile))
+DB_METHOD_VOID(set_errpfx, (const char *errpfx), (db, errpfx))
+DB_METHOD(set_flags, (u_int32_t flags), (db, flags),
+ DB_RETOK_STD)
+DB_METHOD(set_h_ffactor, (u_int32_t h_ffactor),
+ (db, h_ffactor), DB_RETOK_STD)
+DB_METHOD(set_h_hash, (h_hash_fcn_type func),
+ (db, func), DB_RETOK_STD)
+DB_METHOD(set_h_nelem, (u_int32_t h_nelem),
+ (db, h_nelem), DB_RETOK_STD)
+DB_METHOD(set_lorder, (int db_lorder), (db, db_lorder),
+ DB_RETOK_STD)
+DB_METHOD(set_pagesize, (u_int32_t db_pagesize),
+ (db, db_pagesize), DB_RETOK_STD)
+DB_METHOD(set_re_delim, (int re_delim),
+ (db, re_delim), DB_RETOK_STD)
+DB_METHOD(set_re_len, (u_int32_t re_len),
+ (db, re_len), DB_RETOK_STD)
+DB_METHOD(set_re_pad, (int re_pad),
+ (db, re_pad), DB_RETOK_STD)
+DB_METHOD(set_re_source, (char *re_source),
+ (db, re_source), DB_RETOK_STD)
+DB_METHOD(set_q_extentsize, (u_int32_t extentsize),
+ (db, extentsize), DB_RETOK_STD)
+
+DB_METHOD_QUIET(set_alloc, (db_malloc_fcn_type malloc_fcn,
+ db_realloc_fcn_type realloc_fcn, db_free_fcn_type free_fcn),
+ (db, malloc_fcn, realloc_fcn, free_fcn))
+
+void Db::set_errcall(void (*arg)(const char *, char *))
+{
+ env_->set_errcall(arg);
+}
+
+void *Db::get_app_private() const
+{
+ return unwrapConst(this)->app_private;
+}
+
+void Db::set_app_private(void *value)
+{
+ unwrap(this)->app_private = value;
+}
+
+DB_METHOD(set_cachesize, (u_int32_t gbytes, u_int32_t bytes, int ncache),
+ (db, gbytes, bytes, ncache), DB_RETOK_STD)
+DB_METHOD(set_cache_priority, (DB_CACHE_PRIORITY priority),
+ (db, priority), DB_RETOK_STD)
+
+int Db::set_paniccall(void (*callback)(DbEnv *, int))
+{
+ return (env_->set_paniccall(callback));
+}
+
+void Db::set_error_stream(__DB_OSTREAMCLASS *error_stream)
+{
+ env_->set_error_stream(error_stream);
+}
diff --git a/bdb/cxx/cxx_dbc.cpp b/bdb/cxx/cxx_dbc.cpp
new file mode 100644
index 00000000000..4d5844f922f
--- /dev/null
+++ b/bdb/cxx/cxx_dbc.cpp
@@ -0,0 +1,115 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: cxx_dbc.cpp,v 11.55 2002/07/03 21:03:52 bostic Exp $";
+#endif /* not lint */
+
+#include <errno.h>
+#include <string.h>
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc_auto/db_auto.h"
+#include "dbinc_auto/crdel_auto.h"
+#include "dbinc/db_dispatch.h"
+#include "dbinc_auto/db_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+// Helper macro for simple methods that pass through to the
+// underlying C method. It may return an error or raise an exception.
+// Note this macro expects that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(db, arg)")
+//
+#define DBC_METHOD(_name, _argspec, _arglist, _retok) \
+int Dbc::_name _argspec \
+{ \
+ int ret; \
+ DBC *dbc = this; \
+ \
+ ret = dbc->c_##_name _arglist; \
+ if (!_retok(ret)) \
+ DB_ERROR("Dbc::" # _name, ret, ON_ERROR_UNKNOWN); \
+ return (ret); \
+}
+
+// It's private, and should never be called, but VC4.0 needs it resolved
+//
+Dbc::~Dbc()
+{
+}
+
+DBC_METHOD(close, (void), (dbc), DB_RETOK_STD)
+DBC_METHOD(count, (db_recno_t *countp, u_int32_t _flags),
+ (dbc, countp, _flags), DB_RETOK_STD)
+DBC_METHOD(del, (u_int32_t _flags),
+ (dbc, _flags), DB_RETOK_DBCDEL)
+
+int Dbc::dup(Dbc** cursorp, u_int32_t _flags)
+{
+ int ret;
+ DBC *dbc = this;
+ DBC *new_cursor = 0;
+
+ ret = dbc->c_dup(dbc, &new_cursor, _flags);
+
+ if (DB_RETOK_STD(ret))
+ // The following cast implies that Dbc can be no larger than DBC
+ *cursorp = (Dbc*)new_cursor;
+ else
+ DB_ERROR("Dbc::dup", ret, ON_ERROR_UNKNOWN);
+
+ return (ret);
+}
+
+int Dbc::get(Dbt* key, Dbt *data, u_int32_t _flags)
+{
+ int ret;
+ DBC *dbc = this;
+
+ ret = dbc->c_get(dbc, key, data, _flags);
+
+ if (!DB_RETOK_DBCGET(ret)) {
+ if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
+ DB_ERROR_DBT("Dbc::get", key, ON_ERROR_UNKNOWN);
+ else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
+ DB_ERROR_DBT("Dbc::get", data, ON_ERROR_UNKNOWN);
+ else
+ DB_ERROR("Dbc::get", ret, ON_ERROR_UNKNOWN);
+ }
+
+ return (ret);
+}
+
+int Dbc::pget(Dbt* key, Dbt *pkey, Dbt *data, u_int32_t _flags)
+{
+ int ret;
+ DBC *dbc = this;
+
+ ret = dbc->c_pget(dbc, key, pkey, data, _flags);
+
+ /* Logic is the same as for Dbc::get - reusing macro. */
+ if (!DB_RETOK_DBCGET(ret)) {
+ if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
+ DB_ERROR_DBT("Dbc::pget", key, ON_ERROR_UNKNOWN);
+ else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
+ DB_ERROR_DBT("Dbc::pget", data, ON_ERROR_UNKNOWN);
+ else
+ DB_ERROR("Dbc::pget", ret, ON_ERROR_UNKNOWN);
+ }
+
+ return (ret);
+}
+
+DBC_METHOD(put, (Dbt* key, Dbt *data, u_int32_t _flags),
+ (dbc, key, data, _flags), DB_RETOK_DBCPUT)
diff --git a/bdb/cxx/cxx_dbt.cpp b/bdb/cxx/cxx_dbt.cpp
new file mode 100644
index 00000000000..7a4224503ee
--- /dev/null
+++ b/bdb/cxx/cxx_dbt.cpp
@@ -0,0 +1,61 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: cxx_dbt.cpp,v 11.53 2002/03/27 04:31:14 bostic Exp $";
+#endif /* not lint */
+
+#include <errno.h>
+#include <string.h>
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc_auto/db_auto.h"
+#include "dbinc_auto/crdel_auto.h"
+#include "dbinc/db_dispatch.h"
+#include "dbinc_auto/db_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+Dbt::Dbt()
+{
+ DBT *dbt = this;
+ memset(dbt, 0, sizeof(DBT));
+}
+
+Dbt::Dbt(void *data_arg, u_int32_t size_arg)
+{
+ DBT *dbt = this;
+ memset(dbt, 0, sizeof(DBT));
+ set_data(data_arg);
+ set_size(size_arg);
+}
+
+Dbt::~Dbt()
+{
+}
+
+Dbt::Dbt(const Dbt &that)
+{
+ const DBT *from = &that;
+ DBT *to = this;
+ memcpy(to, from, sizeof(DBT));
+}
+
+Dbt &Dbt::operator = (const Dbt &that)
+{
+ if (this != &that) {
+ const DBT *from = &that;
+ DBT *to = this;
+ memcpy(to, from, sizeof(DBT));
+ }
+ return (*this);
+}
diff --git a/bdb/cxx/cxx_env.cpp b/bdb/cxx/cxx_env.cpp
new file mode 100644
index 00000000000..c78c6e9fa47
--- /dev/null
+++ b/bdb/cxx/cxx_env.cpp
@@ -0,0 +1,802 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: cxx_env.cpp,v 11.88 2002/08/26 22:13:36 mjc Exp $";
+#endif /* not lint */
+
+#include <errno.h>
+#include <stdio.h> // needed for set_error_stream
+#include <string.h>
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+#include "dbinc_auto/common_ext.h"
+
+#ifdef HAVE_CXX_STDHEADERS
+using std::cerr;
+#endif
+
+// Helper macros for simple methods that pass through to the
+// underlying C method. They may return an error or raise an exception.
+// These macros expect that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(dbenv, arg)")
+//
+#define DBENV_METHOD_ERR(_name, _argspec, _arglist, _on_err) \
+int DbEnv::_name _argspec \
+{ \
+ DB_ENV *dbenv = unwrap(this); \
+ int ret; \
+ \
+ if ((ret = dbenv->_name _arglist) != 0) { \
+ _on_err; \
+ } \
+ return (ret); \
+}
+
+#define DBENV_METHOD(_name, _argspec, _arglist) \
+ DBENV_METHOD_ERR(_name, _argspec, _arglist, \
+ DB_ERROR("DbEnv::" # _name, ret, error_policy()))
+
+#define DBENV_METHOD_QUIET(_name, _argspec, _arglist) \
+int DbEnv::_name _argspec \
+{ \
+ DB_ENV *dbenv = unwrap(this); \
+ \
+ return (dbenv->_name _arglist); \
+}
+
+#define DBENV_METHOD_VOID(_name, _argspec, _arglist) \
+void DbEnv::_name _argspec \
+{ \
+ DB_ENV *dbenv = unwrap(this); \
+ \
+ dbenv->_name _arglist; \
+}
+
+// This datatype is needed for picky compilers.
+//
+extern "C" {
+ typedef void (*db_errcall_fcn_type)
+ (const char *, char *);
+};
+
+// The reason for a static variable is that some structures
+// (like Dbts) have no connection to any Db or DbEnv, so when
+// errors occur in their methods, we must have some reasonable
+// way to determine whether to throw or return errors.
+//
+// This variable is taken from flags whenever a DbEnv is constructed.
+// Normally there is only one DbEnv per program, and even if not,
+// there is typically a single policy of throwing or returning.
+//
+static int last_known_error_policy = ON_ERROR_UNKNOWN;
+
+__DB_OSTREAMCLASS *DbEnv::error_stream_ = 0;
+
+// These 'glue' function are declared as extern "C" so they will
+// be compatible with picky compilers that do not allow mixing
+// of function pointers to 'C' functions with function pointers
+// to C++ functions.
+//
+extern "C"
+void _feedback_intercept_c(DB_ENV *env, int opcode, int pct)
+{
+ DbEnv::_feedback_intercept(env, opcode, pct);
+}
+
+extern "C"
+void _paniccall_intercept_c(DB_ENV *env, int errval)
+{
+ DbEnv::_paniccall_intercept(env, errval);
+}
+
+extern "C"
+void _stream_error_function_c(const char *prefix, char *message)
+{
+ DbEnv::_stream_error_function(prefix, message);
+}
+
+extern "C"
+int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt,
+ DB_LSN *lsn, db_recops op)
+{
+ return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op));
+}
+
+extern "C"
+int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl,
+ const DBT *data, int id, u_int32_t flags)
+{
+ return (DbEnv::_rep_send_intercept(env,
+ cntrl, data, id, flags));
+}
+
+void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
+{
+ if (env == 0) {
+ DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
+ return;
+ }
+ DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+ if (cxxenv == 0) {
+ DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
+ return;
+ }
+ if (cxxenv->feedback_callback_ == 0) {
+ DB_ERROR("DbEnv::feedback_callback", EINVAL,
+ cxxenv->error_policy());
+ return;
+ }
+ (*cxxenv->feedback_callback_)(cxxenv, opcode, pct);
+}
+
+void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
+{
+ if (env == 0) {
+ DB_ERROR("DbEnv::paniccall_callback", EINVAL,
+ ON_ERROR_UNKNOWN);
+ }
+ DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+ if (cxxenv == 0) {
+ DB_ERROR("DbEnv::paniccall_callback", EINVAL,
+ ON_ERROR_UNKNOWN);
+ }
+ if (cxxenv->paniccall_callback_ == 0) {
+ DB_ERROR("DbEnv::paniccall_callback", EINVAL,
+ cxxenv->error_policy());
+ }
+ (*cxxenv->paniccall_callback_)(cxxenv, errval);
+}
+
+int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
+ DB_LSN *lsn, db_recops op)
+{
+ if (env == 0) {
+ DB_ERROR("DbEnv::app_dispatch_callback",
+ EINVAL, ON_ERROR_UNKNOWN);
+ return (EINVAL);
+ }
+ DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+ if (cxxenv == 0) {
+ DB_ERROR("DbEnv::app_dispatch_callback",
+ EINVAL, ON_ERROR_UNKNOWN);
+ return (EINVAL);
+ }
+ if (cxxenv->app_dispatch_callback_ == 0) {
+ DB_ERROR("DbEnv::app_dispatch_callback",
+ EINVAL, cxxenv->error_policy());
+ return (EINVAL);
+ }
+ Dbt *cxxdbt = (Dbt *)dbt;
+ DbLsn *cxxlsn = (DbLsn *)lsn;
+ return ((*cxxenv->app_dispatch_callback_)(cxxenv, cxxdbt, cxxlsn, op));
+}
+
+int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
+ const DBT *data, int id, u_int32_t flags)
+{
+
+ if (env == 0) {
+ DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
+ return (EINVAL);
+ }
+ DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+ if (cxxenv == 0) {
+ DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
+ return (EINVAL);
+ }
+ const Dbt *cxxcntrl = (const Dbt *)cntrl;
+ Dbt *cxxdata = (Dbt *)data;
+ return ((*cxxenv->rep_send_callback_)(cxxenv,
+ cxxcntrl, cxxdata, id, flags));
+}
+
+// A truism for the DbEnv object is that there is a valid
+// DB_ENV handle from the constructor until close().
+// After the close, the DB_ENV handle is invalid and
+// no operations are permitted on the DbEnv (other than
+// destructor). Leaving the DbEnv handle open and not
+// doing a close is generally considered an error.
+//
+// We used to allow DbEnv objects to be closed and reopened.
+// This implied always keeping a valid DB_ENV object, and
+// coordinating the open objects between Db/DbEnv turned
+// out to be overly complicated. Now we do not allow this.
+
+DbEnv::DbEnv(u_int32_t flags)
+: imp_(0)
+, construct_error_(0)
+, construct_flags_(flags)
+, app_dispatch_callback_(0)
+, feedback_callback_(0)
+, paniccall_callback_(0)
+, pgin_callback_(0)
+, pgout_callback_(0)
+, rep_send_callback_(0)
+{
+ if ((construct_error_ = initialize(0)) != 0)
+ DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
+}
+
+DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
+: imp_(0)
+, construct_error_(0)
+, construct_flags_(flags)
+, app_dispatch_callback_(0)
+, feedback_callback_(0)
+, paniccall_callback_(0)
+, pgin_callback_(0)
+, pgout_callback_(0)
+, rep_send_callback_(0)
+{
+ if ((construct_error_ = initialize(env)) != 0)
+ DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
+}
+
+// If the DB_ENV handle is still open, we close it. This is to make stack
+// allocation of DbEnv objects easier so that they are cleaned up in the error
+// path. Note that the C layer catches cases where handles are open in the
+// environment at close time and reports an error. Applications should call
+// close explicitly in normal (non-exceptional) cases to check the return
+// value.
+//
+DbEnv::~DbEnv()
+{
+ DB_ENV *env = unwrap(this);
+
+ if (env != NULL) {
+ cleanup();
+ (void)env->close(env, 0);
+ }
+}
+
+// called by destructors before the DB_ENV is destroyed.
+void DbEnv::cleanup()
+{
+ DB_ENV *env = unwrap(this);
+
+ if (env != NULL) {
+ env->api1_internal = 0;
+ imp_ = 0;
+ }
+}
+
+int DbEnv::close(u_int32_t flags)
+{
+ int ret;
+ DB_ENV *env = unwrap(this);
+
+ // after a close (no matter if success or failure),
+ // the underlying DB_ENV object must not be accessed,
+ // so we clean up in advance.
+ //
+ cleanup();
+
+ // It's safe to throw an error after the close,
+ // since our error mechanism does not peer into
+ // the DB* structures.
+ //
+ if ((ret = env->close(env, flags)) != 0)
+ DB_ERROR("DbEnv::close", ret, error_policy());
+
+ return (ret);
+}
+
+DBENV_METHOD(dbremove,
+ (DbTxn *txn, const char *name, const char *subdb, u_int32_t flags),
+ (dbenv, unwrap(txn), name, subdb, flags))
+DBENV_METHOD(dbrename, (DbTxn *txn, const char *name, const char *subdb,
+ const char *newname, u_int32_t flags),
+ (dbenv, unwrap(txn), name, subdb, newname, flags))
+
+void DbEnv::err(int error, const char *format, ...)
+{
+ DB_ENV *env = unwrap(this);
+
+ DB_REAL_ERR(env, error, 1, 1, format);
+}
+
+// Return a tristate value corresponding to whether we should
+// throw exceptions on errors:
+// ON_ERROR_RETURN
+// ON_ERROR_THROW
+// ON_ERROR_UNKNOWN
+//
+int DbEnv::error_policy()
+{
+ if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
+ return (ON_ERROR_RETURN);
+ }
+ else {
+ return (ON_ERROR_THROW);
+ }
+}
+
+void DbEnv::errx(const char *format, ...)
+{
+ DB_ENV *env = unwrap(this);
+
+ DB_REAL_ERR(env, 0, 0, 1, format);
+}
+
+void *DbEnv::get_app_private() const
+{
+ return unwrapConst(this)->app_private;
+}
+
+// used internally during constructor
+// to associate an existing DB_ENV with this DbEnv,
+// or create a new one.
+//
+int DbEnv::initialize(DB_ENV *env)
+{
+ int ret;
+
+ last_known_error_policy = error_policy();
+
+ if (env == 0) {
+ // Create a new DB_ENV environment.
+ if ((ret = ::db_env_create(&env,
+ construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0)
+ return (ret);
+ }
+ imp_ = wrap(env);
+ env->api1_internal = this; // for DB_ENV* to DbEnv* conversion
+ return (0);
+}
+
+// lock methods
+DBENV_METHOD(lock_detect, (u_int32_t flags, u_int32_t atype, int *aborted),
+ (dbenv, flags, atype, aborted))
+DBENV_METHOD_ERR(lock_get,
+ (u_int32_t locker, u_int32_t flags, const Dbt *obj,
+ db_lockmode_t lock_mode, DbLock *lock),
+ (dbenv, locker, flags, obj, lock_mode, &lock->lock_),
+ DbEnv::runtime_error_lock_get("DbEnv::lock_get", ret,
+ DB_LOCK_GET, lock_mode, obj, *lock,
+ -1, error_policy()))
+DBENV_METHOD(lock_id, (u_int32_t *idp), (dbenv, idp))
+DBENV_METHOD(lock_id_free, (u_int32_t id), (dbenv, id))
+DBENV_METHOD(lock_put, (DbLock *lock), (dbenv, &lock->lock_))
+DBENV_METHOD(lock_stat, (DB_LOCK_STAT **statp, u_int32_t flags),
+ (dbenv, statp, flags))
+DBENV_METHOD_ERR(lock_vec,
+ (u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
+ int nlist, DB_LOCKREQ **elist_returned),
+ (dbenv, locker, flags, list, nlist, elist_returned),
+ DbEnv::runtime_error_lock_get("DbEnv::lock_vec", ret,
+ (*elist_returned)->op, (*elist_returned)->mode,
+ Dbt::get_Dbt((*elist_returned)->obj), DbLock((*elist_returned)->lock),
+ (*elist_returned) - list, error_policy()))
+// log methods
+DBENV_METHOD(log_archive, (char **list[], u_int32_t flags),
+ (dbenv, list, flags))
+
+int DbEnv::log_compare(const DbLsn *lsn0, const DbLsn *lsn1)
+{
+ return (::log_compare(lsn0, lsn1));
+}
+
+// The following cast implies that DbLogc can be no larger than DB_LOGC
+DBENV_METHOD(log_cursor, (DbLogc **cursorp, u_int32_t flags),
+ (dbenv, (DB_LOGC **)cursorp, flags))
+DBENV_METHOD(log_file, (DbLsn *lsn, char *namep, size_t len),
+ (dbenv, lsn, namep, len))
+DBENV_METHOD(log_flush, (const DbLsn *lsn), (dbenv, lsn))
+DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
+ (dbenv, lsn, data, flags))
+DBENV_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags),
+ (dbenv, spp, flags))
+
+int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
+{
+ DB_ENV *env = unwrap(this);
+ int ret;
+ DB_MPOOLFILE *mpf;
+
+ if (env == NULL)
+ ret = EINVAL;
+ else
+ ret = env->memp_fcreate(env, &mpf, flags);
+
+ if (DB_RETOK_STD(ret)) {
+ *dbmfp = new DbMpoolFile();
+ (*dbmfp)->imp_ = wrap(mpf);
+ } else
+ DB_ERROR("DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
+
+ return (ret);
+}
+
+DBENV_METHOD(memp_register,
+ (int ftype, pgin_fcn_type pgin_fcn, pgout_fcn_type pgout_fcn),
+ (dbenv, ftype, pgin_fcn, pgout_fcn))
+
+// memory pool methods
+DBENV_METHOD(memp_stat,
+ (DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags),
+ (dbenv, gsp, fsp, flags))
+
+DBENV_METHOD(memp_sync, (DbLsn *sn), (dbenv, sn))
+
+DBENV_METHOD(memp_trickle, (int pct, int *nwrotep), (dbenv, pct, nwrotep))
+
+// If an error occurred during the constructor, report it now.
+// Otherwise, call the underlying DB->open method.
+//
+int DbEnv::open(const char *db_home, u_int32_t flags, int mode)
+{
+ int ret;
+ DB_ENV *env = unwrap(this);
+
+ if (construct_error_ != 0)
+ ret = construct_error_;
+ else
+ ret = env->open(env, db_home, flags, mode);
+
+ if (!DB_RETOK_STD(ret))
+ DB_ERROR("DbEnv::open", ret, error_policy());
+
+ return (ret);
+}
+
+int DbEnv::remove(const char *db_home, u_int32_t flags)
+{
+ int ret;
+ DB_ENV *env = unwrap(this);
+
+ // after a remove (no matter if success or failure),
+ // the underlying DB_ENV object must not be accessed,
+ // so we clean up in advance.
+ //
+ cleanup();
+
+ if ((ret = env->remove(env, db_home, flags)) != 0)
+ DB_ERROR("DbEnv::remove", ret, error_policy());
+
+ return (ret);
+}
+
+// Report an error associated with the DbEnv.
+// error_policy is one of:
+// ON_ERROR_THROW throw an error
+// ON_ERROR_RETURN do nothing here, the caller will return an error
+// ON_ERROR_UNKNOWN defer the policy to policy saved in DbEnv::DbEnv
+//
+void DbEnv::runtime_error(const char *caller, int error, int error_policy)
+{
+ if (error_policy == ON_ERROR_UNKNOWN)
+ error_policy = last_known_error_policy;
+ if (error_policy == ON_ERROR_THROW) {
+ // Creating and throwing the object in two separate
+ // statements seems to be necessary for HP compilers.
+ switch (error) {
+ case DB_LOCK_DEADLOCK:
+ {
+ DbDeadlockException dl_except(caller);
+ throw dl_except;
+ }
+ break;
+ case DB_RUNRECOVERY:
+ {
+ DbRunRecoveryException rr_except(caller);
+ throw rr_except;
+ }
+ break;
+ default:
+ {
+ DbException except(caller, error);
+ throw except;
+ }
+ break;
+ }
+ }
+}
+
+// Like DbEnv::runtime_error, but issue a DbMemoryException
+// based on the fact that this Dbt is not large enough.
+void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
+{
+ if (error_policy == ON_ERROR_UNKNOWN)
+ error_policy = last_known_error_policy;
+ if (error_policy == ON_ERROR_THROW) {
+ // Creating and throwing the object in two separate
+ // statements seems to be necessary for HP compilers.
+ DbMemoryException except(caller, dbt);
+ throw except;
+ }
+}
+
+// Like DbEnv::runtime_error, but issue a DbLockNotGrantedException,
+// or a regular runtime error.
+// call regular runtime_error if it
+void DbEnv::runtime_error_lock_get(const char *caller, int error,
+ db_lockop_t op, db_lockmode_t mode, const Dbt *obj,
+ DbLock lock, int index, int error_policy)
+{
+ if (error != DB_LOCK_NOTGRANTED) {
+ runtime_error(caller, error, error_policy);
+ return;
+ }
+
+ if (error_policy == ON_ERROR_UNKNOWN)
+ error_policy = last_known_error_policy;
+ if (error_policy == ON_ERROR_THROW) {
+ // Creating and throwing the object in two separate
+ // statements seems to be necessary for HP compilers.
+ DbLockNotGrantedException except(caller, op, mode,
+ obj, lock, index);
+ throw except;
+ }
+}
+
+// static method
+char *DbEnv::strerror(int error)
+{
+ return (db_strerror(error));
+}
+
+void DbEnv::_stream_error_function(const char *prefix, char *message)
+{
+ // HP compilers need the extra casts, we don't know why.
+ if (error_stream_) {
+ if (prefix) {
+ (*error_stream_) << prefix << (const char *)": ";
+ }
+ if (message) {
+ (*error_stream_) << (const char *)message;
+ }
+ (*error_stream_) << (const char *)"\n";
+ }
+}
+
+// set methods
+
+DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
+DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
+
+// We keep these alphabetical by field name,
+// for comparison with Java's list.
+//
+DBENV_METHOD(set_data_dir, (const char *dir), (dbenv, dir))
+DBENV_METHOD(set_encrypt, (const char *passwd, int flags),
+ (dbenv, passwd, flags))
+DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize))
+DBENV_METHOD(set_lg_dir, (const char *dir), (dbenv, dir))
+DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max))
+DBENV_METHOD(set_lg_regionmax, (u_int32_t regionmax), (dbenv, regionmax))
+DBENV_METHOD(set_lk_detect, (u_int32_t detect), (dbenv, detect))
+DBENV_METHOD(set_lk_max, (u_int32_t max), (dbenv, max))
+DBENV_METHOD(set_lk_max_lockers, (u_int32_t max_lockers), (dbenv, max_lockers))
+DBENV_METHOD(set_lk_max_locks, (u_int32_t max_locks), (dbenv, max_locks))
+DBENV_METHOD(set_lk_max_objects, (u_int32_t max_objects), (dbenv, max_objects))
+DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize))
+DBENV_METHOD(set_tmp_dir, (const char *tmp_dir), (dbenv, tmp_dir))
+DBENV_METHOD(set_tx_max, (u_int32_t tx_max), (dbenv, tx_max))
+
+DBENV_METHOD_QUIET(set_alloc,
+ (db_malloc_fcn_type malloc_fcn, db_realloc_fcn_type realloc_fcn,
+ db_free_fcn_type free_fcn),
+ (dbenv, malloc_fcn, realloc_fcn, free_fcn))
+
+void DbEnv::set_app_private(void *value)
+{
+ unwrap(this)->app_private = value;
+}
+
+DBENV_METHOD(set_cachesize,
+ (u_int32_t gbytes, u_int32_t bytes, int ncache),
+ (dbenv, gbytes, bytes, ncache))
+
+void DbEnv::set_errcall(void (*arg)(const char *, char *))
+{
+ DB_ENV *dbenv = unwrap(this);
+
+ // XXX
+ // We are casting from a function ptr declared with C++
+ // linkage to one (same arg types) declared with C
+ // linkage. It's hard to imagine a pair of C/C++
+ // compilers from the same vendor for which this
+ // won't work. Unfortunately, we can't use a
+ // intercept function like the others since the
+ // function does not have a (DbEnv*) as one of
+ // the args. If this causes trouble, we can pull
+ // the same trick we use in Java, namely stuffing
+ // a (DbEnv*) pointer into the prefix. We're
+ // avoiding this for the moment because it obfuscates.
+ //
+ (*(dbenv->set_errcall))(dbenv, (db_errcall_fcn_type)arg);
+}
+
+// Note: This actually behaves a bit like a static function,
+// since DB_ENV.db_errcall has no information about which
+// db_env triggered the call. A user that has multiple DB_ENVs
+// will simply not be able to have different streams for each one.
+//
+void DbEnv::set_error_stream(__DB_OSTREAMCLASS *stream)
+{
+ DB_ENV *dbenv = unwrap(this);
+
+ error_stream_ = stream;
+ dbenv->set_errcall(dbenv, (stream == 0) ? 0 :
+ _stream_error_function_c);
+}
+
+int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
+{
+ DB_ENV *dbenv = unwrap(this);
+
+ feedback_callback_ = arg;
+
+ return ((*(dbenv->set_feedback))(dbenv, _feedback_intercept_c));
+}
+
+DBENV_METHOD(set_flags, (u_int32_t flags, int onoff), (dbenv, flags, onoff))
+DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
+ (dbenv, lk_conflicts, lk_max))
+
+int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
+{
+ DB_ENV *dbenv = unwrap(this);
+
+ paniccall_callback_ = arg;
+
+ return ((*(dbenv->set_paniccall))(dbenv, _paniccall_intercept_c));
+}
+
+DBENV_METHOD(set_rpc_server,
+ (void *cl, char *host, long tsec, long ssec, u_int32_t flags),
+ (dbenv, cl, host, tsec, ssec, flags))
+DBENV_METHOD(set_shm_key, (long shm_key), (dbenv, shm_key))
+// Note: this changes from last_known_error_policy to error_policy()
+DBENV_METHOD(set_tas_spins, (u_int32_t arg), (dbenv, arg))
+
+int DbEnv::set_app_dispatch
+ (int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops))
+{
+ DB_ENV *dbenv = unwrap(this);
+ int ret;
+
+ app_dispatch_callback_ = arg;
+ if ((ret = (*(dbenv->set_app_dispatch))(dbenv,
+ _app_dispatch_intercept_c)) != 0)
+ DB_ERROR("DbEnv::set_app_dispatch", ret, error_policy());
+
+ return (ret);
+}
+
+DBENV_METHOD(set_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
+DBENV_METHOD(set_verbose, (u_int32_t which, int onoff), (dbenv, which, onoff))
+
+int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
+{
+ DB_ENV *env = unwrap(this);
+ DB_TXN *txn;
+ int ret;
+
+ ret = env->txn_begin(env, unwrap(pid), &txn, flags);
+ if (DB_RETOK_STD(ret))
+ *tid = new DbTxn(txn);
+ else
+ DB_ERROR("DbEnv::txn_begin", ret, error_policy());
+
+ return (ret);
+}
+
+DBENV_METHOD(txn_checkpoint, (u_int32_t kbyte, u_int32_t min, u_int32_t flags),
+ (dbenv, kbyte, min, flags))
+
+int DbEnv::txn_recover(DbPreplist *preplist, long count,
+ long *retp, u_int32_t flags)
+{
+ DB_ENV *dbenv = unwrap(this);
+ DB_PREPLIST *c_preplist;
+ long i;
+ int ret;
+
+ /*
+ * We need to allocate some local storage for the
+ * returned preplist, and that requires us to do
+ * our own argument validation.
+ */
+ if (count <= 0)
+ ret = EINVAL;
+ else
+ ret = __os_malloc(dbenv, sizeof(DB_PREPLIST) * count,
+ &c_preplist);
+
+ if (ret != 0) {
+ DB_ERROR("DbEnv::txn_recover", ret, error_policy());
+ return (ret);
+ }
+
+ if ((ret =
+ dbenv->txn_recover(dbenv, c_preplist, count, retp, flags)) != 0) {
+ __os_free(dbenv, c_preplist);
+ DB_ERROR("DbEnv::txn_recover", ret, error_policy());
+ return (ret);
+ }
+
+ for (i = 0; i < *retp; i++) {
+ preplist[i].txn = new DbTxn();
+ preplist[i].txn->imp_ = wrap(c_preplist[i].txn);
+ memcpy(preplist[i].gid, c_preplist[i].gid,
+ sizeof(preplist[i].gid));
+ }
+
+ __os_free(dbenv, c_preplist);
+
+ return (0);
+}
+
+DBENV_METHOD(txn_stat, (DB_TXN_STAT **statp, u_int32_t flags),
+ (dbenv, statp, flags))
+
+int DbEnv::set_rep_transport(u_int32_t myid,
+ int (*f_send)(DbEnv *, const Dbt *, const Dbt *, int, u_int32_t))
+{
+ DB_ENV *dbenv = unwrap(this);
+ int ret;
+
+ rep_send_callback_ = f_send;
+ if ((ret = dbenv->set_rep_transport(dbenv,
+ myid, _rep_send_intercept_c)) != 0)
+ DB_ERROR("DbEnv::set_rep_transport", ret, error_policy());
+
+ return (ret);
+}
+
+DBENV_METHOD(rep_elect,
+ (int nsites, int pri, u_int32_t timeout, int *idp),
+ (dbenv, nsites, pri, timeout, idp))
+
+int DbEnv::rep_process_message(Dbt *control, Dbt *rec, int *idp)
+{
+ DB_ENV *dbenv = unwrap(this);
+ int ret;
+
+ ret = dbenv->rep_process_message(dbenv, control, rec, idp);
+ if (!DB_RETOK_REPPMSG(ret))
+ DB_ERROR("DbEnv::rep_process_message", ret, error_policy());
+
+ return (ret);
+}
+
+DBENV_METHOD(rep_start,
+ (Dbt *cookie, u_int32_t flags),
+ (dbenv, (DBT *)cookie, flags))
+
+DBENV_METHOD(rep_stat, (DB_REP_STAT **statp, u_int32_t flags),
+ (dbenv, statp, flags))
+
+DBENV_METHOD(set_rep_limit, (u_int32_t gbytes, u_int32_t bytes),
+ (dbenv, gbytes, bytes))
+
+DBENV_METHOD(set_timeout,
+ (db_timeout_t timeout, u_int32_t flags),
+ (dbenv, timeout, flags))
+
+// static method
+char *DbEnv::version(int *major, int *minor, int *patch)
+{
+ return (db_version(major, minor, patch));
+}
+
+// static method
+DbEnv *DbEnv::wrap_DB_ENV(DB_ENV *dbenv)
+{
+ DbEnv *wrapped_env = get_DbEnv(dbenv);
+ if (wrapped_env == NULL)
+ wrapped_env = new DbEnv(dbenv, 0);
+ return wrapped_env;
+}
diff --git a/bdb/cxx/cxx_except.cpp b/bdb/cxx/cxx_except.cpp
index a62e21a767d..40fdeae69d6 100644
--- a/bdb/cxx/cxx_except.cpp
+++ b/bdb/cxx/cxx_except.cpp
@@ -1,20 +1,21 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: cxx_except.cpp,v 11.7 2000/09/21 15:05:45 dda Exp $";
+static const char revid[] = "$Id: cxx_except.cpp,v 11.17 2002/08/23 01:07:27 mjc Exp $";
#endif /* not lint */
#include <string.h>
+#include <errno.h>
#include "db_cxx.h"
-#include "cxx_int.h"
+#include "dbinc/cxx_int.h"
// tmpString is used to create strings on the stack
//
@@ -25,30 +26,7 @@ public:
const char *str2 = 0,
const char *str3 = 0,
const char *str4 = 0,
- const char *str5 = 0)
- {
- int len = strlen(str1);
- if (str2)
- len += strlen(str2);
- if (str3)
- len += strlen(str3);
- if (str4)
- len += strlen(str4);
- if (str5)
- len += strlen(str5);
-
- s_ = new char[len+1];
-
- strcpy(s_, str1);
- if (str2)
- strcat(s_, str2);
- if (str3)
- strcat(s_, str3);
- if (str4)
- strcat(s_, str4);
- if (str5)
- strcat(s_, str5);
- }
+ const char *str5 = 0);
~tmpString() { delete [] s_; }
operator const char *() { return (s_); }
@@ -56,6 +34,35 @@ private:
char *s_;
};
+tmpString::tmpString(const char *str1,
+ const char *str2,
+ const char *str3,
+ const char *str4,
+ const char *str5)
+{
+ size_t len = strlen(str1);
+ if (str2)
+ len += strlen(str2);
+ if (str3)
+ len += strlen(str3);
+ if (str4)
+ len += strlen(str4);
+ if (str5)
+ len += strlen(str5);
+
+ s_ = new char[len+1];
+
+ strcpy(s_, str1);
+ if (str2)
+ strcat(s_, str2);
+ if (str3)
+ strcat(s_, str3);
+ if (str4)
+ strcat(s_, str4);
+ if (str5)
+ strcat(s_, str5);
+}
+
// Note: would not be needed if we can inherit from exception
// It does not appear to be possible to inherit from exception
// with the current Microsoft library (VC5.0).
@@ -100,7 +107,8 @@ DbException::DbException(const char *prefix, int err)
DbException::DbException(const char *prefix1, const char *prefix2, int err)
: err_(err)
{
- what_ = dupString(tmpString(prefix1, ": ", prefix2, ": ", db_strerror(err)));
+ what_ = dupString(tmpString(prefix1, ": ", prefix2, ": ",
+ db_strerror(err)));
}
DbException::DbException(const DbException &that)
@@ -130,3 +138,193 @@ const char *DbException::what() const
{
return (what_);
}
+
+////////////////////////////////////////////////////////////////////////
+// //
+// DbMemoryException //
+// //
+////////////////////////////////////////////////////////////////////////
+
+static const char *memory_err_desc = "Dbt not large enough for available data";
+DbMemoryException::~DbMemoryException()
+{
+}
+
+DbMemoryException::DbMemoryException(Dbt *dbt)
+: DbException(memory_err_desc, ENOMEM)
+, dbt_(dbt)
+{
+}
+
+DbMemoryException::DbMemoryException(const char *description)
+: DbException(description, ENOMEM)
+, dbt_(0)
+{
+}
+
+DbMemoryException::DbMemoryException(const char *prefix, Dbt *dbt)
+: DbException(prefix, memory_err_desc, ENOMEM)
+, dbt_(dbt)
+{
+}
+
+DbMemoryException::DbMemoryException(const char *prefix1, const char *prefix2,
+ Dbt *dbt)
+: DbException(prefix1, prefix2, ENOMEM)
+, dbt_(dbt)
+{
+}
+
+DbMemoryException::DbMemoryException(const DbMemoryException &that)
+: DbException(that)
+, dbt_(that.dbt_)
+{
+}
+
+DbMemoryException
+&DbMemoryException::operator =(const DbMemoryException &that)
+{
+ if (this != &that) {
+ DbException::operator=(that);
+ dbt_ = that.dbt_;
+ }
+ return (*this);
+}
+
+Dbt *DbMemoryException::get_dbt() const
+{
+ return (dbt_);
+}
+
+////////////////////////////////////////////////////////////////////////
+// //
+// DbDeadlockException //
+// //
+////////////////////////////////////////////////////////////////////////
+
+DbDeadlockException::~DbDeadlockException()
+{
+}
+
+DbDeadlockException::DbDeadlockException(const char *description)
+: DbException(description, DB_LOCK_DEADLOCK)
+{
+}
+
+DbDeadlockException::DbDeadlockException(const DbDeadlockException &that)
+: DbException(that)
+{
+}
+
+DbDeadlockException
+&DbDeadlockException::operator =(const DbDeadlockException &that)
+{
+ if (this != &that)
+ DbException::operator=(that);
+ return (*this);
+}
+
+////////////////////////////////////////////////////////////////////////
+// //
+// DbLockNotGrantedException //
+// //
+////////////////////////////////////////////////////////////////////////
+
+DbLockNotGrantedException::~DbLockNotGrantedException()
+{
+ delete lock_;
+}
+
+DbLockNotGrantedException::DbLockNotGrantedException(const char *prefix,
+ db_lockop_t op, db_lockmode_t mode, const Dbt *obj, const DbLock lock,
+ int index)
+: DbException(prefix, DbEnv::strerror(DB_LOCK_NOTGRANTED),
+ DB_LOCK_NOTGRANTED)
+, op_(op)
+, mode_(mode)
+, obj_(obj)
+, index_(index)
+{
+ lock_ = new DbLock(lock);
+}
+
+DbLockNotGrantedException::DbLockNotGrantedException
+ (const DbLockNotGrantedException &that)
+: DbException(that)
+{
+ op_ = that.op_;
+ mode_ = that.mode_;
+ obj_ = that.obj_;
+ lock_ = new DbLock(*that.lock_);
+ index_ = that.index_;
+}
+
+DbLockNotGrantedException
+&DbLockNotGrantedException::operator =(const DbLockNotGrantedException &that)
+{
+ if (this != &that) {
+ DbException::operator=(that);
+ op_ = that.op_;
+ mode_ = that.mode_;
+ obj_ = that.obj_;
+ lock_ = new DbLock(*that.lock_);
+ index_ = that.index_;
+ }
+ return (*this);
+}
+
+db_lockop_t DbLockNotGrantedException::get_op() const
+{
+ return op_;
+}
+
+db_lockmode_t DbLockNotGrantedException::get_mode() const
+{
+ return mode_;
+}
+
+const Dbt* DbLockNotGrantedException::get_obj() const
+{
+ return obj_;
+}
+
+DbLock* DbLockNotGrantedException::get_lock() const
+{
+ return lock_;
+}
+
+int DbLockNotGrantedException::get_index() const
+{
+ return index_;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// //
+// DbRunRecoveryException //
+// //
+////////////////////////////////////////////////////////////////////////
+
+DbRunRecoveryException::~DbRunRecoveryException()
+{
+}
+
+DbRunRecoveryException::DbRunRecoveryException(const char *description)
+: DbException(description, DB_RUNRECOVERY)
+{
+}
+
+DbRunRecoveryException::DbRunRecoveryException
+ (const DbRunRecoveryException &that)
+: DbException(that)
+{
+}
+
+DbRunRecoveryException
+&DbRunRecoveryException::operator =(const DbRunRecoveryException &that)
+{
+ if (this != &that)
+ DbException::operator=(that);
+ return (*this);
+}
diff --git a/bdb/cxx/cxx_lock.cpp b/bdb/cxx/cxx_lock.cpp
index e8ce2aa9d30..446eba49e27 100644
--- a/bdb/cxx/cxx_lock.cpp
+++ b/bdb/cxx/cxx_lock.cpp
@@ -1,86 +1,21 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: cxx_lock.cpp,v 11.9 2000/09/21 15:05:45 dda Exp $";
+static const char revid[] = "$Id: cxx_lock.cpp,v 11.17 2002/03/27 04:31:16 bostic Exp $";
#endif /* not lint */
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
-#include "cxx_int.h"
-
-int DbEnv::lock_detect(u_int32_t flags, u_int32_t atype, int *aborted)
-{
- DB_ENV *env = unwrap(this);
- int err;
-
- if ((err = ::lock_detect(env, flags, atype, aborted)) != 0) {
- DB_ERROR("DbEnv::lock_detect", err, error_policy());
- return (err);
- }
- return (err);
-}
-
-int DbEnv::lock_get(u_int32_t locker, u_int32_t flags, const Dbt *obj,
- db_lockmode_t lock_mode, DbLock *lock)
-{
- DB_ENV *env = unwrap(this);
- int err;
-
- if ((err = ::lock_get(env, locker, flags, obj,
- lock_mode, &lock->lock_)) != 0) {
- DB_ERROR("DbEnv::lock_get", err, error_policy());
- return (err);
- }
- return (err);
-}
-
-int DbEnv::lock_id(u_int32_t *idp)
-{
- DB_ENV *env = unwrap(this);
- int err;
-
- if ((err = ::lock_id(env, idp)) != 0) {
- DB_ERROR("DbEnv::lock_id", err, error_policy());
- }
- return (err);
-}
-
-int DbEnv::lock_stat(DB_LOCK_STAT **statp,
- db_malloc_fcn_type db_malloc_fcn)
-{
- DB_ENV *env = unwrap(this);
- int err;
-
- if ((err = ::lock_stat(env, statp, db_malloc_fcn)) != 0) {
- DB_ERROR("DbEnv::lock_stat", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::lock_vec(u_int32_t locker, u_int32_t flags,
- DB_LOCKREQ list[],
- int nlist, DB_LOCKREQ **elist_returned)
-{
- DB_ENV *env = unwrap(this);
- int err;
-
- if ((err = ::lock_vec(env, locker, flags, list,
- nlist, elist_returned)) != 0) {
- DB_ERROR("DbEnv::lock_vec", err, error_policy());
- return (err);
- }
- return (err);
-}
+#include "dbinc/cxx_int.h"
////////////////////////////////////////////////////////////////////////
// //
@@ -108,18 +43,3 @@ DbLock &DbLock::operator = (const DbLock &that)
lock_ = that.lock_;
return (*this);
}
-
-int DbLock::put(DbEnv *env)
-{
- DB_ENV *envp = unwrap(env);
-
- if (!env) {
- return (EINVAL); // handle never assigned
- }
-
- int err;
- if ((err = lock_put(envp, &lock_)) != 0) {
- DB_ERROR("DbLock::put", err, env->error_policy());
- }
- return (err);
-}
diff --git a/bdb/cxx/cxx_log.cpp b/bdb/cxx/cxx_log.cpp
deleted file mode 100644
index 336b9d337f0..00000000000
--- a/bdb/cxx/cxx_log.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: cxx_log.cpp,v 11.9 2000/09/21 15:05:45 dda Exp $";
-#endif /* not lint */
-
-#include <errno.h>
-
-#include "db_cxx.h"
-#include "cxx_int.h"
-
-////////////////////////////////////////////////////////////////////////
-// //
-// DbLog //
-// //
-////////////////////////////////////////////////////////////////////////
-
-int DbEnv::log_archive(char **list[], u_int32_t flags,
- db_malloc_fcn_type db_malloc_fcn)
-{
- int err;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_archive(env, list, flags, db_malloc_fcn)) != 0) {
- DB_ERROR("DbEnv::log_archive", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_compare(const DbLsn *lsn0, const DbLsn *lsn1)
-{
- return (::log_compare(lsn0, lsn1));
-}
-
-int DbEnv::log_file(DbLsn *lsn, char *namep, size_t len)
-{
- int err;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_file(env, lsn, namep, len)) != 0) {
- DB_ERROR("DbEnv::log_file", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_flush(const DbLsn *lsn)
-{
- int err;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_flush(env, lsn)) != 0) {
- DB_ERROR("DbEnv::log_flush", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_get(DbLsn *lsn, Dbt *data, u_int32_t flags)
-{
- int err;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_get(env, lsn, data, flags)) != 0) {
- DB_ERROR("DbEnv::log_get", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_put(DbLsn *lsn, const Dbt *data, u_int32_t flags)
-{
- int err = 0;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_put(env, lsn, data, flags)) != 0) {
- DB_ERROR("DbEnv::log_put", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_register(Db *dbp, const char *name)
-{
- int err = 0;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_register(env, unwrap(dbp), name)) != 0) {
- DB_ERROR("DbEnv::log_register", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_stat(DB_LOG_STAT **spp, db_malloc_fcn_type db_malloc_fcn)
-{
- int err = 0;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_stat(env, spp, db_malloc_fcn)) != 0) {
- DB_ERROR("DbEnv::log_stat", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int DbEnv::log_unregister(Db *dbp)
-{
- int err;
- DB_ENV *env = unwrap(this);
-
- if ((err = ::log_unregister(env, unwrap(dbp))) != 0) {
- DB_ERROR("DbEnv::log_unregister", err, error_policy());
- return (err);
- }
- return (0);
-}
diff --git a/bdb/cxx/cxx_logc.cpp b/bdb/cxx/cxx_logc.cpp
new file mode 100644
index 00000000000..d1fe83dd58b
--- /dev/null
+++ b/bdb/cxx/cxx_logc.cpp
@@ -0,0 +1,65 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: cxx_logc.cpp,v 11.8 2002/07/03 21:03:53 bostic Exp $";
+#endif /* not lint */
+
+#include <errno.h>
+#include <string.h>
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc_auto/db_auto.h"
+#include "dbinc_auto/crdel_auto.h"
+#include "dbinc/db_dispatch.h"
+#include "dbinc_auto/db_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+// It's private, and should never be called,
+// but some compilers need it resolved
+//
+DbLogc::~DbLogc()
+{
+}
+
+// The name _flags prevents a name clash with __db_log_cursor::flags
+int DbLogc::close(u_int32_t _flags)
+{
+ DB_LOGC *logc = this;
+ int ret;
+
+ ret = logc->close(logc, _flags);
+
+ if (!DB_RETOK_STD(ret))
+ DB_ERROR("DbLogc::close", ret, ON_ERROR_UNKNOWN);
+
+ return (ret);
+}
+
+// The name _flags prevents a name clash with __db_log_cursor::flags
+int DbLogc::get(DbLsn *lsn, Dbt *data, u_int32_t _flags)
+{
+ DB_LOGC *logc = this;
+ int ret;
+
+ ret = logc->get(logc, lsn, data, _flags);
+
+ if (!DB_RETOK_LGGET(ret)) {
+ if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
+ DB_ERROR_DBT("DbLogc::get", data, ON_ERROR_UNKNOWN);
+ else
+ DB_ERROR("DbLogc::get", ret, ON_ERROR_UNKNOWN);
+ }
+
+ return (ret);
+}
diff --git a/bdb/cxx/cxx_mpool.cpp b/bdb/cxx/cxx_mpool.cpp
index 22f4735e333..3eb78d03ff4 100644
--- a/bdb/cxx/cxx_mpool.cpp
+++ b/bdb/cxx/cxx_mpool.cpp
@@ -1,20 +1,51 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: cxx_mpool.cpp,v 11.11 2000/09/21 15:05:45 dda Exp $";
+static const char revid[] = "$Id: cxx_mpool.cpp,v 11.20 2002/07/03 21:03:53 bostic Exp $";
#endif /* not lint */
#include <errno.h>
#include "db_cxx.h"
-#include "cxx_int.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+
+// Helper macros for simple methods that pass through to the
+// underlying C method. It may return an error or raise an exception.
+// Note this macro expects that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(mpf, arg)")
+//
+#define DB_MPOOLFILE_METHOD(_name, _argspec, _arglist, _retok) \
+int DbMpoolFile::_name _argspec \
+{ \
+ int ret; \
+ DB_MPOOLFILE *mpf = unwrap(this); \
+ \
+ if (mpf == NULL) \
+ ret = EINVAL; \
+ else \
+ ret = mpf->_name _arglist; \
+ if (!_retok(ret)) \
+ DB_ERROR("DbMpoolFile::"#_name, ret, ON_ERROR_UNKNOWN); \
+ return (ret); \
+}
+
+#define DB_MPOOLFILE_METHOD_VOID(_name, _argspec, _arglist) \
+void DbMpoolFile::_name _argspec \
+{ \
+ DB_MPOOLFILE *mpf = unwrap(this); \
+ \
+ mpf->_name _arglist; \
+}
////////////////////////////////////////////////////////////////////////
// //
@@ -31,150 +62,49 @@ DbMpoolFile::~DbMpoolFile()
{
}
-int DbMpoolFile::open(DbEnv *envp, const char *file,
- u_int32_t flags, int mode, size_t pagesize,
- DB_MPOOL_FINFO *finfop, DbMpoolFile **result)
-{
- int err;
-
- DB_MPOOLFILE *mpf;
- DB_ENV *env = unwrap(envp);
-
- if ((err = ::memp_fopen(env, file, flags, mode, pagesize,
- finfop, &mpf)) != 0) {
- DB_ERROR("DbMpoolFile::open", err, envp->error_policy());
- return (err);
- }
- *result = new DbMpoolFile();
- (*result)->imp_ = wrap(mpf);
- return (0);
-}
-
-int DbMpoolFile::close()
+int DbMpoolFile::close(u_int32_t flags)
{
DB_MPOOLFILE *mpf = unwrap(this);
- int err = 0;
- if (!mpf) {
- err = EINVAL;
- }
- else if ((err = ::memp_fclose(mpf)) != 0) {
- DB_ERROR("DbMpoolFile::close", err, ON_ERROR_UNKNOWN);
- return (err);
- }
+ int ret;
+
+ if (mpf == NULL)
+ ret = EINVAL;
+ else
+ ret = mpf->close(mpf, flags);
+
imp_ = 0; // extra safety
// This may seem weird, but is legal as long as we don't access
// any data before returning.
- //
delete this;
- return (0);
-}
-
-int DbMpoolFile::get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep)
-{
- DB_MPOOLFILE *mpf = unwrap(this);
- int err = 0;
- if (!mpf) {
- err = EINVAL;
- }
- else if ((err = ::memp_fget(mpf, pgnoaddr, flags, pagep)) != 0) {
- DB_ERROR("DbMpoolFile::get", err, ON_ERROR_UNKNOWN);
- }
- return (err);
-}
-
-int DbMpoolFile::put(void *pgaddr, u_int32_t flags)
-{
- DB_MPOOLFILE *mpf = unwrap(this);
- int err = 0;
- if (!mpf) {
- err = EINVAL;
- }
- else if ((err = ::memp_fput(mpf, pgaddr, flags)) != 0) {
- DB_ERROR("DbMpoolFile::put", err, ON_ERROR_UNKNOWN);
- }
- return (err);
-}
-
-int DbMpoolFile::set(void *pgaddr, u_int32_t flags)
-{
- DB_MPOOLFILE *mpf = unwrap(this);
- int err = 0;
- if (!mpf) {
- err = EINVAL;
- }
- else if ((err = ::memp_fset(mpf, pgaddr, flags)) != 0) {
- DB_ERROR("DbMpoolFile::set", err, ON_ERROR_UNKNOWN);
- }
- return (err);
-}
-
-int DbMpoolFile::sync()
-{
- DB_MPOOLFILE *mpf = unwrap(this);
- int err = 0;
- if (!mpf) {
- err = EINVAL;
- }
- else if ((err = ::memp_fsync(mpf)) != 0 && err != DB_INCOMPLETE) {
- DB_ERROR("DbMpoolFile::sync", err, ON_ERROR_UNKNOWN);
- }
- return (err);
-}
-////////////////////////////////////////////////////////////////////////
-// //
-// DbMpool //
-// //
-////////////////////////////////////////////////////////////////////////
+ if (!DB_RETOK_STD(ret))
+ DB_ERROR("DbMpoolFile::close", ret, ON_ERROR_UNKNOWN);
-int DbEnv::memp_register(int ftype,
- pgin_fcn_type pgin_fcn,
- pgout_fcn_type pgout_fcn)
-{
- DB_ENV *env = unwrap(this);
- int err = 0;
-
- if ((err = ::memp_register(env, ftype, pgin_fcn, pgout_fcn)) != 0) {
- DB_ERROR("DbEnv::memp_register", err, error_policy());
- return (err);
- }
- return (err);
+ return (ret);
}
-int DbEnv::memp_stat(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp,
- db_malloc_fcn_type db_malloc_fcn)
-{
- DB_ENV *env = unwrap(this);
- int err = 0;
-
- if ((err = ::memp_stat(env, gsp, fsp, db_malloc_fcn)) != 0) {
- DB_ERROR("DbEnv::memp_stat", err, error_policy());
- return (err);
- }
- return (err);
-}
-
-int DbEnv::memp_sync(DbLsn *sn)
-{
- DB_ENV *env = unwrap(this);
- int err = 0;
-
- if ((err = ::memp_sync(env, sn)) != 0 && err != DB_INCOMPLETE) {
- DB_ERROR("DbEnv::memp_sync", err, error_policy());
- return (err);
- }
- return (err);
-}
-
-int DbEnv::memp_trickle(int pct, int *nwrotep)
-{
- DB_ENV *env = unwrap(this);
- int err = 0;
-
- if ((err = ::memp_trickle(env, pct, nwrotep)) != 0) {
- DB_ERROR("DbEnv::memp_trickle", err, error_policy());
- return (err);
- }
- return (err);
-}
+DB_MPOOLFILE_METHOD(get, (db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep),
+ (mpf, pgnoaddr, flags, pagep), DB_RETOK_MPGET)
+DB_MPOOLFILE_METHOD_VOID(last_pgno, (db_pgno_t *pgnoaddr), (mpf, pgnoaddr))
+DB_MPOOLFILE_METHOD(open,
+ (const char *file, u_int32_t flags, int mode, size_t pagesize),
+ (mpf, file, flags, mode, pagesize), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(put, (void *pgaddr, u_int32_t flags),
+ (mpf, pgaddr, flags), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD_VOID(refcnt, (db_pgno_t *pgnoaddr), (mpf, pgnoaddr))
+DB_MPOOLFILE_METHOD(set, (void *pgaddr, u_int32_t flags),
+ (mpf, pgaddr, flags), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_clear_len, (u_int32_t len),
+ (mpf, len), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_fileid, (u_int8_t *fileid),
+ (mpf, fileid), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_ftype, (int ftype),
+ (mpf, ftype), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_lsn_offset, (int32_t offset),
+ (mpf, offset), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_pgcookie, (DBT *dbt),
+ (mpf, dbt), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD_VOID(set_unlink, (int ul), (mpf, ul))
+DB_MPOOLFILE_METHOD(sync, (),
+ (mpf), DB_RETOK_STD)
diff --git a/bdb/cxx/cxx_table.cpp b/bdb/cxx/cxx_table.cpp
deleted file mode 100644
index b7b335d26e9..00000000000
--- a/bdb/cxx/cxx_table.cpp
+++ /dev/null
@@ -1,808 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: cxx_table.cpp,v 11.35 2001/01/11 18:19:49 bostic Exp $";
-#endif /* not lint */
-
-#include <errno.h>
-#include <string.h>
-
-#include "db_cxx.h"
-#include "cxx_int.h"
-
-#include "db_int.h"
-#include "db_page.h"
-#include "db_ext.h"
-#include "common_ext.h"
-
-////////////////////////////////////////////////////////////////////////
-// //
-// Db //
-// //
-////////////////////////////////////////////////////////////////////////
-
-// A truism for the DbEnv object is that there is a valid
-// DB_ENV handle from the constructor until close().
-// After the close, the DB handle is invalid and
-// no operations are permitted on the Db (other than
-// destructor). Leaving the Db handle open and not
-// doing a close is generally considered an error.
-//
-// We used to allow Db objects to be closed and reopened.
-// This implied always keeping a valid DB object, and
-// coordinating the open objects between Db/DbEnv turned
-// out to be overly complicated. Now we do not allow this.
-
-Db::Db(DbEnv *env, u_int32_t flags)
-: imp_(0)
-, env_(env)
-, construct_error_(0)
-, flags_(0)
-, construct_flags_(flags)
-{
- if (env_ == 0)
- flags_ |= DB_CXX_PRIVATE_ENV;
- initialize();
-}
-
-// Note: if the user has not closed, we call _destroy_check
-// to warn against this non-safe programming practice.
-// We can't close, because the environment may already
-// be closed/destroyed.
-//
-Db::~Db()
-{
- DB *db;
-
- db = unwrap(this);
- if (db != NULL) {
- DbEnv::_destroy_check("Db", 0);
- cleanup();
- }
-}
-
-// private method to initialize during constructor.
-// initialize must create a backing DB object,
-// and if that creates a new DB_ENV, it must be tied to a new DbEnv.
-// If there is an error, construct_error_ is set; this is examined
-// during open.
-//
-int Db::initialize()
-{
- u_int32_t cxx_flags;
- DB *db;
- int err;
- DB_ENV *cenv = unwrap(env_);
-
- cxx_flags = construct_flags_ & DB_CXX_NO_EXCEPTIONS;
-
- // Create a new underlying DB object.
- // We rely on the fact that if a NULL DB_ENV* is given,
- // one is allocated by DB.
- //
- if ((err = db_create(&db, cenv,
- construct_flags_ & ~cxx_flags)) != 0) {
- construct_error_ = err;
- return (err);
- }
-
- // Associate the DB with this object
- imp_ = wrap(db);
- db->cj_internal = this;
-
- // Create a new DbEnv from a DB_ENV* if it was created locally.
- // It is deleted in Db::close().
- //
- if ((flags_ & DB_CXX_PRIVATE_ENV) != 0)
- env_ = new DbEnv(db->dbenv, cxx_flags);
-
- return (0);
-}
-
-// private method to cleanup after destructor or during close.
-// If the environment was created by this Db object, we optionally
-// delete it, or return it so the caller can delete it after
-// last use.
-//
-void Db::cleanup()
-{
- DB *db = unwrap(this);
-
- if (db != NULL) {
- // extra safety
- db->cj_internal = 0;
- imp_ = 0;
-
- // we must dispose of the DbEnv object if
- // we created it. This will be the case
- // if a NULL DbEnv was passed into the constructor.
- // The underlying DB_ENV object will be inaccessible
- // after the close, so we must clean it up now.
- //
- if ((flags_ & DB_CXX_PRIVATE_ENV) != 0) {
- env_->cleanup();
- delete env_;
- env_ = 0;
- }
- }
- construct_error_ = 0;
-}
-
-// Return a tristate value corresponding to whether we should
-// throw exceptions on errors:
-// ON_ERROR_RETURN
-// ON_ERROR_THROW
-// ON_ERROR_UNKNOWN
-//
-int Db::error_policy()
-{
- if (env_ != NULL)
- return (env_->error_policy());
- else {
- // If the env_ is null, that means that the user
- // did not attach an environment, so the correct error
- // policy can be deduced from constructor flags
- // for this Db.
- //
- if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
- return (ON_ERROR_RETURN);
- }
- else {
- return (ON_ERROR_THROW);
- }
- }
-}
-
-int Db::close(u_int32_t flags)
-{
- DB *db = unwrap(this);
- int err;
-
- // after a DB->close (no matter if success or failure),
- // the underlying DB object must not be accessed,
- // so we clean up in advance.
- //
- cleanup();
-
- // It's safe to throw an error after the close,
- // since our error mechanism does not peer into
- // the DB* structures.
- //
- if ((err = db->close(db, flags)) != 0 && err != DB_INCOMPLETE)
- DB_ERROR("Db::close", err, error_policy());
-
- return (err);
-}
-
-int Db::cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags)
-{
- DB *db = unwrap(this);
- DBC *dbc = 0;
- int err;
-
- if ((err = db->cursor(db, unwrap(txnid), &dbc, flags)) != 0) {
- DB_ERROR("Db::cursor", err, error_policy());
- return (err);
- }
-
- // The following cast implies that Dbc can be no larger than DBC
- *cursorp = (Dbc*)dbc;
- return (0);
-}
-
-int Db::del(DbTxn *txnid, Dbt *key, u_int32_t flags)
-{
- DB *db = unwrap(this);
- int err;
-
- if ((err = db->del(db, unwrap(txnid), key, flags)) != 0) {
- // DB_NOTFOUND is a "normal" return, so should not be
- // thrown as an error
- //
- if (err != DB_NOTFOUND) {
- DB_ERROR("Db::del", err, error_policy());
- return (err);
- }
- }
- return (err);
-}
-
-void Db::err(int error, const char *format, ...)
-{
- va_list args;
- DB *db = unwrap(this);
-
- va_start(args, format);
- __db_real_err(db->dbenv, error, 1, 1, format, args);
- va_end(args);
-}
-
-void Db::errx(const char *format, ...)
-{
- va_list args;
- DB *db = unwrap(this);
-
- va_start(args, format);
- __db_real_err(db->dbenv, 0, 0, 1, format, args);
- va_end(args);
-}
-
-int Db::fd(int *fdp)
-{
- DB *db = unwrap(this);
- int err;
-
- if ((err = db->fd(db, fdp)) != 0) {
- DB_ERROR("Db::fd", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-void _db_feedback_intercept_c(DB *db, int opcode, int pct)
-{
- Db::_feedback_intercept(db, opcode, pct);
-}
-
-//static
-void Db::_feedback_intercept(DB *db, int opcode, int pct)
-{
- if (db == 0) {
- DB_ERROR("Db::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
- return;
- }
- Db *cxxdb = (Db *)db->cj_internal;
- if (cxxdb == 0) {
- DB_ERROR("Db::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
- return;
- }
- if (cxxdb->feedback_callback_ == 0) {
- DB_ERROR("Db::feedback_callback", EINVAL, cxxdb->error_policy());
- return;
- }
- (*cxxdb->feedback_callback_)(cxxdb, opcode, pct);
-}
-
-int Db::set_feedback(void (*arg)(Db *, int, int))
-{
- DB *db = unwrap(this);
-
- feedback_callback_ = arg;
-
- return ((*(db->set_feedback))(db, _db_feedback_intercept_c));
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-int _db_append_recno_intercept_c(DB *db, DBT *data, db_recno_t recno)
-{
- return (Db::_append_recno_intercept(db, data, recno));
-}
-
-//static
-int Db::_append_recno_intercept(DB *db, DBT *data, db_recno_t recno)
-{
- int err;
-
- if (db == 0) {
- DB_ERROR("Db::append_recno_callback", EINVAL, ON_ERROR_UNKNOWN);
- return (EINVAL);
- }
- Db *cxxdb = (Db *)db->cj_internal;
- if (cxxdb == 0) {
- DB_ERROR("Db::append_recno_callback", EINVAL, ON_ERROR_UNKNOWN);
- return (EINVAL);
- }
- if (cxxdb->append_recno_callback_ == 0) {
- DB_ERROR("Db::append_recno_callback", EINVAL, cxxdb->error_policy());
- return (EINVAL);
- }
-
- // making these copies is slow but portable.
- // Another alternative is to cast the DBT* manufactured
- // by the C layer to a Dbt*. It 'should be' safe since
- // Dbt is a thin shell over DBT, adding no extra data,
- // but is nonportable, and could lead to errors if anything
- // were added to the Dbt class.
- //
- Dbt cxxdbt;
- memcpy((DBT *)&cxxdbt, data, sizeof(DBT));
- err = (*cxxdb->append_recno_callback_)(cxxdb, &cxxdbt, recno);
- memcpy(data, (DBT *)&cxxdbt, sizeof(DBT));
- return (err);
-}
-
-int Db::set_append_recno(int (*arg)(Db *, Dbt *, db_recno_t))
-{
- DB *db = unwrap(this);
-
- append_recno_callback_ = arg;
-
- return ((*(db->set_append_recno))(db, _db_append_recno_intercept_c));
-}
-
-int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
-{
- DB *db = unwrap(this);
- int err;
-
- if ((err = db->get(db, unwrap(txnid), key, value, flags)) != 0) {
- // DB_NOTFOUND and DB_KEYEMPTY are "normal" returns,
- // so should not be thrown as an error
- //
- if (err != DB_NOTFOUND && err != DB_KEYEMPTY) {
- DB_ERROR("Db::get", err, error_policy());
- return (err);
- }
- }
- return (err);
-}
-
-int Db::get_byteswapped() const
-{
- DB *db = (DB *)unwrapConst(this);
- return (db->get_byteswapped(db));
-}
-
-DBTYPE Db::get_type() const
-{
- DB *db = (DB *)unwrapConst(this);
- return ((DBTYPE)db->get_type(db));
-}
-
-int Db::join(Dbc **curslist, Dbc **cursorp, u_int32_t flags)
-{
- // Dbc is a "compatible" subclass of DBC -
- // that is, no virtual functions or even extra data members,
- // so this cast, although technically non-portable,
- // "should" always be okay.
- //
- DBC **list = (DBC **)(curslist);
- DB *db = unwrap(this);
- DBC *dbc = 0;
- int err;
-
- if ((err = db->join(db, list, &dbc, flags)) != 0) {
- DB_ERROR("Db::join_cursor", err, error_policy());
- return (err);
- }
- *cursorp = (Dbc*)dbc;
- return (0);
-}
-
-int Db::key_range(DbTxn *txnid, Dbt *key,
- DB_KEY_RANGE *results, u_int32_t flags)
-{
- DB *db = unwrap(this);
- int err;
-
- if ((err = db->key_range(db, unwrap(txnid), key,
- results, flags)) != 0) {
- DB_ERROR("Db::key_range", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-// If an error occurred during the constructor, report it now.
-// Otherwise, call the underlying DB->open method.
-//
-int Db::open(const char *file, const char *database,
- DBTYPE type, u_int32_t flags, int mode)
-{
- int err;
- DB *db = unwrap(this);
-
- if ((err = construct_error_) != 0)
- DB_ERROR("Db::open", construct_error_, error_policy());
- else if ((err = db->open(db, file, database, type, flags, mode)) != 0)
- DB_ERROR("Db::open", err, error_policy());
-
- return (err);
-}
-
-int Db::put(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
-{
- int err;
- DB *db = unwrap(this);
-
- if ((err = db->put(db, unwrap(txnid), key, value, flags)) != 0) {
-
- // DB_KEYEXIST is a "normal" return, so should not be
- // thrown as an error
- //
- if (err != DB_KEYEXIST) {
- DB_ERROR("Db::put", err, error_policy());
- return (err);
- }
- }
- return (err);
-}
-
-int Db::rename(const char *file, const char *database,
- const char *newname, u_int32_t flags)
-{
- int err = 0;
- DB *db = unwrap(this);
-
- if (!db) {
- DB_ERROR("Db::rename", EINVAL, error_policy());
- return (EINVAL);
- }
-
- // after a DB->rename (no matter if success or failure),
- // the underlying DB object must not be accessed,
- // so we clean up in advance.
- //
- cleanup();
-
- if ((err = db->rename(db, file, database, newname, flags)) != 0) {
- DB_ERROR("Db::rename", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int Db::remove(const char *file, const char *database, u_int32_t flags)
-{
- int err = 0;
- DB *db = unwrap(this);
-
- if (!db) {
- DB_ERROR("Db::remove", EINVAL, error_policy());
- return (EINVAL);
- }
-
- // after a DB->remove (no matter if success or failure),
- // the underlying DB object must not be accessed,
- // so we clean up in advance.
- //
- cleanup();
-
- if ((err = db->remove(db, file, database, flags)) != 0)
- DB_ERROR("Db::remove", err, error_policy());
-
- return (err);
-}
-
-int Db::stat(void *sp, db_malloc_fcn_type db_malloc_fcn, u_int32_t flags)
-{
- int err;
- DB *db = unwrap(this);
-
- if (!db) {
- DB_ERROR("Db::stat", EINVAL, error_policy());
- return (EINVAL);
- }
- if ((err = db->stat(db, sp, db_malloc_fcn, flags)) != 0) {
- DB_ERROR("Db::stat", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-int Db::sync(u_int32_t flags)
-{
- int err;
- DB *db = unwrap(this);
-
- if (!db) {
- DB_ERROR("Db::sync", EINVAL, error_policy());
- return (EINVAL);
- }
- if ((err = db->sync(db, flags)) != 0 && err != DB_INCOMPLETE) {
- DB_ERROR("Db::sync", err, error_policy());
- return (err);
- }
- return (err);
-}
-
-int Db::upgrade(const char *name, u_int32_t flags)
-{
- int err;
- DB *db = unwrap(this);
-
- if (!db) {
- DB_ERROR("Db::upgrade", EINVAL, error_policy());
- return (EINVAL);
- }
- if ((err = db->upgrade(db, name, flags)) != 0) {
- DB_ERROR("Db::upgrade", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-static int _verify_callback_cxx(void *handle, const void *str_arg)
-{
- char *str;
- ostream *out;
-
- str = (char *)str_arg;
- out = (ostream *)handle;
-
- (*out) << str;
- if (out->fail())
- return (EIO);
-
- return (0);
-}
-
-// This is a 'glue' function declared as extern "C" so it will
-// be compatible with picky compilers that do not allow mixing
-// of function pointers to 'C' functions with function pointers
-// to C++ functions.
-//
-extern "C"
-int _verify_callback_c(void *handle, const void *str_arg)
-{
- return (_verify_callback_cxx(handle, str_arg));
-}
-
-int Db::verify(const char *name, const char *subdb,
- ostream *ostr, u_int32_t flags)
-{
- int err;
- DB *db = unwrap(this);
-
- if (!db) {
- DB_ERROR("Db::verify", EINVAL, error_policy());
- return (EINVAL);
- }
- if ((err = __db_verify_internal(db, name, subdb, ostr,
- _verify_callback_c, flags)) != 0) {
- DB_ERROR("Db::verify", err, error_policy());
- return (err);
- }
- return (0);
-}
-
-// This is a variant of the DB_WO_ACCESS macro to define a simple set_
-// method calling the underlying C method, but unlike a simple
-// set method, it may return an error or raise an exception.
-// Note this macro expects that input _argspec is an argument
-// list element (e.g. "char *arg") defined in terms of "arg".
-//
-#define DB_DB_ACCESS(_name, _argspec) \
-\
-int Db::set_##_name(_argspec) \
-{ \
- int ret; \
- DB *db = unwrap(this); \
- \
- if ((ret = (*(db->set_##_name))(db, arg)) != 0) { \
- DB_ERROR("Db::set_" # _name, ret, error_policy()); \
- } \
- return (ret); \
-}
-
-#define DB_DB_ACCESS_NORET(_name, _argspec) \
- \
-void Db::set_##_name(_argspec) \
-{ \
- DB *db = unwrap(this); \
- \
- (*(db->set_##_name))(db, arg); \
- return; \
-}
-
-DB_DB_ACCESS(bt_compare, bt_compare_fcn_type arg)
-DB_DB_ACCESS(bt_maxkey, u_int32_t arg)
-DB_DB_ACCESS(bt_minkey, u_int32_t arg)
-DB_DB_ACCESS(bt_prefix, bt_prefix_fcn_type arg)
-DB_DB_ACCESS(dup_compare, dup_compare_fcn_type arg)
-DB_DB_ACCESS_NORET(errfile, FILE *arg)
-DB_DB_ACCESS_NORET(errpfx, const char *arg)
-DB_DB_ACCESS(flags, u_int32_t arg)
-DB_DB_ACCESS(h_ffactor, u_int32_t arg)
-DB_DB_ACCESS(h_hash, h_hash_fcn_type arg)
-DB_DB_ACCESS(h_nelem, u_int32_t arg)
-DB_DB_ACCESS(lorder, int arg)
-DB_DB_ACCESS(malloc, db_malloc_fcn_type arg)
-DB_DB_ACCESS(pagesize, u_int32_t arg)
-DB_DB_ACCESS(realloc, db_realloc_fcn_type arg)
-DB_DB_ACCESS(re_delim, int arg)
-DB_DB_ACCESS(re_len, u_int32_t arg)
-DB_DB_ACCESS(re_pad, int arg)
-DB_DB_ACCESS(re_source, char *arg)
-DB_DB_ACCESS(q_extentsize, u_int32_t arg)
-
-// Here are the set methods that don't fit the above mold.
-//
-
-void Db::set_errcall(void (*arg)(const char *, char *))
-{
- env_->set_errcall(arg);
-}
-
-int Db::set_cachesize(u_int32_t gbytes, u_int32_t bytes, int ncache)
-{
- int ret;
- DB *db = unwrap(this);
-
- if ((ret = (*(db->set_cachesize))(db, gbytes, bytes, ncache)) != 0) {
- DB_ERROR("Db::set_cachesize", ret, error_policy());
- }
- return (ret);
-}
-
-int Db::set_paniccall(void (*callback)(DbEnv *, int))
-{
- return (env_->set_paniccall(callback));
-}
-
-void Db::set_error_stream(ostream *error_stream)
-{
- env_->set_error_stream(error_stream);
-}
-
-////////////////////////////////////////////////////////////////////////
-// //
-// Dbc //
-// //
-////////////////////////////////////////////////////////////////////////
-
-// It's private, and should never be called, but VC4.0 needs it resolved
-//
-Dbc::~Dbc()
-{
-}
-
-int Dbc::close()
-{
- DBC *cursor = this;
- int err;
-
- if ((err = cursor->c_close(cursor)) != 0) {
- DB_ERROR("Db::close", err, ON_ERROR_UNKNOWN);
- return (err);
- }
- return (0);
-}
-
-int Dbc::count(db_recno_t *countp, u_int32_t flags_arg)
-{
- DBC *cursor = this;
- int err;
-
- if ((err = cursor->c_count(cursor, countp, flags_arg)) != 0) {
- DB_ERROR("Db::count", err, ON_ERROR_UNKNOWN);
- return (err);
- }
- return (0);
-}
-
-int Dbc::del(u_int32_t flags_arg)
-{
- DBC *cursor = this;
- int err;
-
- if ((err = cursor->c_del(cursor, flags_arg)) != 0) {
-
- // DB_KEYEMPTY is a "normal" return, so should not be
- // thrown as an error
- //
- if (err != DB_KEYEMPTY) {
- DB_ERROR("Db::del", err, ON_ERROR_UNKNOWN);
- return (err);
- }
- }
- return (err);
-}
-
-int Dbc::dup(Dbc** cursorp, u_int32_t flags_arg)
-{
- DBC *cursor = this;
- DBC *new_cursor = 0;
- int err;
-
- if ((err = cursor->c_dup(cursor, &new_cursor, flags_arg)) != 0) {
- DB_ERROR("Db::dup", err, ON_ERROR_UNKNOWN);
- return (err);
- }
-
- // The following cast implies that Dbc can be no larger than DBC
- *cursorp = (Dbc*)new_cursor;
- return (0);
-}
-
-int Dbc::get(Dbt* key, Dbt *data, u_int32_t flags_arg)
-{
- DBC *cursor = this;
- int err;
-
- if ((err = cursor->c_get(cursor, key, data, flags_arg)) != 0) {
-
- // DB_NOTFOUND and DB_KEYEMPTY are "normal" returns,
- // so should not be thrown as an error
- //
- if (err != DB_NOTFOUND && err != DB_KEYEMPTY) {
- DB_ERROR("Db::get", err, ON_ERROR_UNKNOWN);
- return (err);
- }
- }
- return (err);
-}
-
-int Dbc::put(Dbt* key, Dbt *data, u_int32_t flags_arg)
-{
- DBC *cursor = this;
- int err;
-
- if ((err = cursor->c_put(cursor, key, data, flags_arg)) != 0) {
-
- // DB_KEYEXIST is a "normal" return, so should not be
- // thrown as an error
- //
- if (err != DB_KEYEXIST) {
- DB_ERROR("Db::put", err, ON_ERROR_UNKNOWN);
- return (err);
- }
- }
- return (err);
-}
-
-////////////////////////////////////////////////////////////////////////
-// //
-// Dbt //
-// //
-////////////////////////////////////////////////////////////////////////
-
-Dbt::Dbt()
-{
- DBT *dbt = this;
- memset(dbt, 0, sizeof(DBT));
-}
-
-Dbt::Dbt(void *data_arg, size_t size_arg)
-{
- DBT *dbt = this;
- memset(dbt, 0, sizeof(DBT));
- set_data(data_arg);
- set_size(size_arg);
-}
-
-Dbt::~Dbt()
-{
-}
-
-Dbt::Dbt(const Dbt &that)
-{
- const DBT *from = &that;
- DBT *to = this;
- memcpy(to, from, sizeof(DBT));
-}
-
-Dbt &Dbt::operator = (const Dbt &that)
-{
- if (this != &that) {
- const DBT *from = &that;
- DBT *to = this;
- memcpy(to, from, sizeof(DBT));
- }
- return (*this);
-}
-
-DB_RW_ACCESS(Dbt, void *, data, data)
-DB_RW_ACCESS(Dbt, u_int32_t, size, size)
-DB_RW_ACCESS(Dbt, u_int32_t, ulen, ulen)
-DB_RW_ACCESS(Dbt, u_int32_t, dlen, dlen)
-DB_RW_ACCESS(Dbt, u_int32_t, doff, doff)
-DB_RW_ACCESS(Dbt, u_int32_t, flags, flags)
diff --git a/bdb/cxx/cxx_txn.cpp b/bdb/cxx/cxx_txn.cpp
index 0abae982644..b04077c0f5b 100644
--- a/bdb/cxx/cxx_txn.cpp
+++ b/bdb/cxx/cxx_txn.cpp
@@ -1,136 +1,81 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: cxx_txn.cpp,v 11.13 2000/12/21 16:24:33 dda Exp $";
+static const char revid[] = "$Id: cxx_txn.cpp,v 11.27 2002/07/20 13:50:11 dda Exp $";
#endif /* not lint */
#include <errno.h>
#include "db_cxx.h"
-#include "cxx_int.h"
-
-////////////////////////////////////////////////////////////////////////
-// //
-// DbTxnMgr //
-// //
-////////////////////////////////////////////////////////////////////////
-
-int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
-{
- int err;
- DB_ENV *env = unwrap(this);
- DB_TXN *txn;
-
- if ((err = ::txn_begin(env, unwrap(pid), &txn, flags)) != 0) {
- DB_ERROR("DbEnv::txn_begin", err, error_policy());
- return (err);
- }
- DbTxn *result = new DbTxn();
- result->imp_ = wrap(txn);
- *tid = result;
- return (err);
-}
-
-int DbEnv::txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags)
-{
- int err;
- DB_ENV *env = unwrap(this);
- if ((err = ::txn_checkpoint(env, kbyte, min, flags)) != 0 &&
- err != DB_INCOMPLETE) {
- DB_ERROR("DbEnv::txn_checkpoint", err, error_policy());
- return (err);
- }
- return (err);
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+
+// Helper macro for simple methods that pass through to the
+// underlying C method. It may return an error or raise an exception.
+// Note this macro expects that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(db, arg)")
+//
+#define DBTXN_METHOD(_name, _delete, _argspec, _arglist) \
+int DbTxn::_name _argspec \
+{ \
+ int ret; \
+ DB_TXN *txn = unwrap(this); \
+ \
+ ret = txn->_name _arglist; \
+ /* Weird, but safe if we don't access this again. */ \
+ if (_delete) \
+ delete this; \
+ if (!DB_RETOK_STD(ret)) \
+ DB_ERROR("DbTxn::" # _name, ret, ON_ERROR_UNKNOWN); \
+ return (ret); \
}
-int DbEnv::txn_stat(DB_TXN_STAT **statp, db_malloc_fcn_type db_malloc_fcn)
-{
- int err;
- DB_ENV *env = unwrap(this);
- if ((err = ::txn_stat(env, statp, db_malloc_fcn)) != 0) {
- DB_ERROR("DbEnv::txn_stat", err, error_policy());
- return (err);
- }
- return (err);
-}
-
-////////////////////////////////////////////////////////////////////////
-// //
-// DbTxn //
-// //
-////////////////////////////////////////////////////////////////////////
-
+// private constructor, never called but needed by some C++ linkers
DbTxn::DbTxn()
: imp_(0)
{
}
-DbTxn::~DbTxn()
+DbTxn::DbTxn(DB_TXN *txn)
+: imp_(wrap(txn))
{
+ txn->api_internal = this;
}
-int DbTxn::abort()
+DbTxn::~DbTxn()
{
- int err;
- DB_TXN *txn;
-
- txn = unwrap(this);
- err = txn_abort(txn);
-
- // It may seem weird to delete this, but is legal as long
- // as we don't access any of its data before returning.
- //
- delete this;
-
- if (err != 0)
- DB_ERROR("DbTxn::abort", err, ON_ERROR_UNKNOWN);
-
- return (err);
}
-int DbTxn::commit(u_int32_t flags)
-{
- int err;
- DB_TXN *txn;
-
- txn = unwrap(this);
- err = txn_commit(txn, flags);
-
- // It may seem weird to delete this, but is legal as long
- // as we don't access any of its data before returning.
- //
- delete this;
-
- if (err != 0)
- DB_ERROR("DbTxn::commit", err, ON_ERROR_UNKNOWN);
-
- return (err);
-}
+DBTXN_METHOD(abort, 1, (), (txn))
+DBTXN_METHOD(commit, 1, (u_int32_t flags), (txn, flags))
+DBTXN_METHOD(discard, 1, (u_int32_t flags), (txn, flags))
u_int32_t DbTxn::id()
{
DB_TXN *txn;
txn = unwrap(this);
- return (txn_id(txn)); // no error
+ return (txn->id(txn)); // no error
}
-int DbTxn::prepare()
-{
- int err;
- DB_TXN *txn;
+DBTXN_METHOD(prepare, 0, (u_int8_t *gid), (txn, gid))
+DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
+ (txn, timeout, flags))
- txn = unwrap(this);
- if ((err = txn_prepare(txn)) != 0) {
- DB_ERROR("DbTxn::prepare", err, ON_ERROR_UNKNOWN);
- return (err);
- }
- return (0);
+// static method
+DbTxn *DbTxn::wrap_DB_TXN(DB_TXN *txn)
+{
+ DbTxn *wrapped_txn = get_DbTxn(txn);
+ if (wrapped_txn == NULL)
+ wrapped_txn = new DbTxn(txn);
+ return wrapped_txn;
}
diff --git a/bdb/cxx/namemap.txt b/bdb/cxx/namemap.txt
deleted file mode 100644
index 75207718577..00000000000
--- a/bdb/cxx/namemap.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-$Id: namemap.txt,v 10.4 2000/02/19 20:57:54 bostic Exp $
-
-The bulk of DB provides for wrapper classes and appropriately named methods
-that call into DB. For the most part, there is a straightforward mapping of
-names. For the purposes of referencing documentation, this chart shows the
-underlying C structure name for each C++ class. In some cases, using the
-given C prefix with a C++ method name gives the underlying C function name.
-For example, DbMpoolFile::close() is implemented by memp_fclose().
-
-C++ C C prefix
-
-Db DB
-DbEnv DB_ENV
-Dbc DBC
-DbException none
-DbInfo DB_INFO
-DbLock DB_LOCK lock_
-DbLsn DB_LSN
-DbMpoolFile DB_MPOOL_FILE memp_
-Dbt DBT
-DbTxn DB_TXN txn_
diff --git a/bdb/db/Design.fileop b/bdb/db/Design.fileop
deleted file mode 100644
index 187f1ffaf22..00000000000
--- a/bdb/db/Design.fileop
+++ /dev/null
@@ -1,452 +0,0 @@
-# $Id: Design.fileop,v 11.4 2000/02/19 20:57:54 bostic Exp $
-
-The design of file operation recovery.
-
-Keith has asked me to write up notes on our current status of database
-create and delete and recovery, why it's so hard, and how we've violated
-all the cornerstone assumptions on which our recovery framework is based.
-
-I am including two documents at the end of this one. The first is the
-initial design of the recoverability of file create and delete (there is
-no talk of subdatabases there, because we didn't think we'd have to do
-anything special there). I will annotate this document on where things
-changed.
-
-The second is the design of recd007 which is supposed to test our ability
-to recover these operations regardless of where one crashes. This test
-is fundamentally different from our other recovery tests in the following
-manner. Normally, the application controls transaction boundaries.
-Therefore, we can perform an operation and then decide whether to commit
-or abort it. In the normal recovery tests, we force the database into
-each of the four possible states from a recovery perspective:
-
- database is pre-op, undo (do nothing)
- database is pre-op, redo
- database is post-op, undo
- database is post-op, redo (do nothing)
-
-By copying databases at various points and initiating txn_commit and abort
-appropriately, we can make all these things happen. Notice that the one
-case we don't handle is where page A is in one state (e.g., pre-op) and
-page B is in another state (e.g., post-op). I will argue that these don't
-matter because each page is recovered independently. If anyone can poke
-holes in this, I'm interested.
-
-The problem with create/delete recovery testing is that the transaction
-is begun and ended all inside the library. Therefore, there is never any
-point (outside the library) where we can copy files and or initiate
-abort/commit. In order to still put the recovery code through its paces,
-Sue designed an infrastructure that lets you tell the library where to
-make copies of things and where to suddenly inject errors so that the
-transaction gets aborted. This level of detail allows us to push the
-create/delete recovery code through just about every recovery path
-possible (although I'm sure Mike will tell me I'm wrong when he starts to
-run code coverage tools).
-
-OK, so that's all preamble and a brief discussion of the documents I'm
-enclosing.
-
-Why was this so hard and painful and why is the code so Q@#$!% complicated?
-The following is a discussion/explanation, but to the best of my knowledge,
-the structure we have in place now works. The key question we need to be
-asking is, "Does this need to have to be so complex or should we redesign
-portions to simplify it?" At this point, there is no obvious way to simplify
-it in my book, but I may be having difficulty seeing this because my mind is
-too polluted at this point.
-
-Our overall strategy for recovery is that we do write-ahead logging,
-that is we log an operation and make sure it is on disk before any
-data corresponding to the data that log record describes is on disk.
-Typically we use log sequence numbers (LSNs) to mark the data so that
-during recovery, we can look at the data and determine if it is in a
-state before a particular log record or after a particular log record.
-
-In the good old days, opens were not transaction protected, so we could
-do regular old opens during recovery and if the file existed, we opened
-it and if it didn't (or appeared corrupt), we didn't and treated it like
-a missing file. As will be discussed below in detail, our states are much
-more complicated and recovery can't make such simplistic assumptions.
-
-Also, since we are now dealing with file system operations, we have less
-control about when they actually happen and what the state of the system
-can be. That is, we have to write create log records synchronously, because
-the create/open system call may force a newly created (0-length) file to
-disk. This file has to now be identified as being in the "being-created"
-state.
-
-A. We used to make a number of assumptions during recovery:
-
-1. We could call db_open at any time and one of three things would happen:
- a) the file would be opened cleanly
- b) the file would not exist
- c) we would encounter an error while opening the file
-
-Case a posed no difficulty.
-In Case b, we simply spit out a warning that a file was missing and then
- ignored all subsequent operations to that file.
-In Case c, we reported a fatal error.
-
-2. We can always generate a warning if a file is missing.
-
-3. We never encounter NULL file names in the log.
-
-B. We also made some assumptions in the main-line library:
-
-1. If you try to open a file and it exists but is 0-length, then
-someone else is trying to open it.
-
-2. You can write pages anywhere in a file and any non-existent pages
-are 0-filled. [This breaks on Windows.]
-
-3. If you have proper permissions then you can always evict pages from
-the buffer pool.
-
-4. During open, we can close the master database handle as soon as
-we're done with it since all the rest of the activity will take place
-on the subdatabase handle.
-
-In our brave new world, most of these assumptions are no longer valid.
-Let's address them one at a time.
-
-A.1 We could call db_open at any time and one of three things would happen:
- a) the file would be opened cleanly
- b) the file would not exist
- c) we would encounter an error while opening the file
-There are now additional states. Since we are trying to make file
-operations recoverable, you can now die in the middle of such an
-operation and we have to be able to pick up the pieces. What this
-now means is that:
-
- * a 0-length file can be an indication of a create in-progress
- * you can have a meta-data page but no root page (of a btree)
- * if a file doesn't exist, it could mean that it was just about
- to be created and needs to be rolled forward.
- * if you encounter an error in a file (e.g., the meta-data page
- is all 0's) you could still be in mid-open.
-
-I have now made this all work, but it required significant changes to the
-db_open code and error handling and this is the sort of change that makes
-everyone nervous.
-
-A.2. We can always generate a warning if a file is missing.
-
-Now that we have a delete file method in the API, we need to make sure
-that we do not generate warning messages for files that don't exist if
-we see that they were explicitly deleted.
-
-This means that we need to save state during recovery, determine which
-files were missing and were not being recreated and were not deleted and
-only complain about those.
-
-A.3. We never encounter NULL file names in the log.
-
-Now that we allow tranaction protection on memory-resident files, we write
-log messages for files with NULL file names. This means that our assumption
-of always being able to call "db_open" on any log_register OPEN message found
-in the log is no longer valid.
-
-B.1. If you try to open a file and it exists but is 0-length, then
-someone else is trying to open it.
-
-As discussed for A.1, this is no longer true. It may be instead that you
-are in the process of recovering a create.
-
-B.2. You can write pages anywhere in a file and any non-existent pages
-are 0-filled.
-
-It turns out that this is not true on Windows. This means that places
-we do group allocation (hash) must explicitly allocate each page, because
-we can't count on recognizing the uninitialized pages later.
-
-B.3. If you have proper permissions then you can always evict pages from
-the buffer pool.
-
-In the brave new world though, files can be deleted and they may
-have pages in the mpool. If you later try to evict these, you
-discover that the file doesn't exist. We'd get here when we had
-to dirty pages during a remove operation.
-
-B.4. You can close files any time you want.
-
-However, if the file takes part in the open/remove transaction,
-then we had better not close it until after the transaction
-commits/aborts, because we need to be able to get our hands on the
-dbp and the open happened in a different transaction.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-Design for recovering file create and delete in the presence of subdatabases.
-
-Assumptions:
- Remove the O_TRUNCATE flag.
- Single-thread all open/create/delete operations.
- (Well, almost all; we'll optimize opens without DB_CREATE set.)
- The reasoning for this is that with two simultaneous
- open/creaters, during recovery, we cannot identify which
- transaction successfully created files and therefore cannot
- recovery correctly.
- File system creates/deletes are synchronous
- Once the file is open, subdatabase creates look like regular
- get/put operations and a metadata page creation.
-
-There are 4 cases to deal with:
- 1. Open/create file
- 2. Open/create subdatabase
- 3. Delete
- 4. Recovery records
-
- __db_fileopen_recover
- __db_metapage_recover
- __db_delete_recover
- existing c_put and c_get routines for subdatabase creation
-
- Note that the open/create of the file and the open/create of the
- subdatabase need to be in the same transaction.
-
-1. Open/create (full file and subdb version)
-
-If create
- LOCK_FILEOP
- txn_begin
- log create message (open message below)
- do file system open/create
- if we did not create
- abort transaction (before going to open_only)
- if (!subdb)
- set dbp->open_txn = NULL
- else
- txn_begin a new transaction for the subdb open
-
- construct meta-data page
- log meta-data page (see metapage)
- write the meta-data page
- * It may be the case that btrees need to log both meta-data pages
- and root pages. If that is the case, I believe that we can use
- this same record and recovery routines for both
-
- txn_commit
- UNLOCK_FILEOP
-
-2. Delete
- LOCK_FILEOP
- txn_begin
- log delete message (delete message below)
- mv file __db.file.lsn
- txn_commit
- unlink __db.file.lsn
- UNLOCK_FILEOP
-
-3. Recovery Routines
-
-__db_fileopen_recover
- if (argp->name.size == 0
- done;
-
- if (redo) /* Commit */
- __os_open(argp->name, DB_OSO_CREATE, argp->mode, &fh)
- __os_closehandle(fh)
- if (undo) /* Abort */
- if (argp->name exists)
- unlink(argp->name);
-
-__db_metapage_recover
- if (redo)
- __os_open(argp->name, 0, 0, &fh)
- __os_lseek(meta data page)
- __os_write(meta data page)
- __os_closehandle(fh);
- if (undo)
- done = 0;
- if (argp->name exists)
- if (length of argp->name != 0)
- __os_open(argp->name, 0, 0, &fh)
- __os_lseek(meta data page)
- __os_read(meta data page)
- if (read succeeds && page lsn != current_lsn)
- done = 1
- __os_closehandle(fh);
- if (!done)
- unlink(argp->name)
-
-__db_delete_recover
- if (redo)
- Check if the backup file still exists and if so, delete it.
-
- if (undo)
- if (__db_appname(__db.file.lsn exists))
- mv __db_appname(__db.file.lsn) __db_appname(file)
-
-__db_metasub_recover
- /* This is like a normal recovery routine */
- Get the metadata page
- if (cmp_n && redo)
- copy the log page onto the page
- update the lsn
- make sure page gets put dirty
- else if (cmp_p && undo)
- update the lsn to the lsn in the log record
- make sure page gets put dirty
-
- if the page was modified, put it back dirty
-
-In db.src
-
-# name: filename (before call to __db_appname)
-# mode: file system mode
-BEGIN open
-DBT name DBT s
-ARG mode u_int32_t o
-END
-
-# opcode: indicate if it is a create/delete and if it is a subdatabase
-# pgsize: page size on which we're going to write the meta-data page
-# pgno: page number on which to write this meta-data page
-# page: the actual meta-data page
-# lsn: LSN of the meta-data page -- 0 for new databases, may be non-0
-# for subdatabases.
-
-BEGIN metapage
-ARG opcode u_int32_t x
-DBT name DBT s
-ARG pgno db_pgno_t d
-DBT page DBT s
-POINTER lsn DB_LSN * lu
-END
-
-# We do not need a subdatabase name here because removing a subdatabase
-# name is simply a regular bt_delete operation from the master database.
-# It will get logged normally.
-# name: filename
-BEGIN delete
-DBT name DBT s
-END
-
-# We also need to reclaim pages, but we can use the existing
-# bt_pg_alloc routines.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-Testing recoverability of create/delete.
-
-These tests are unlike other tests in that they are going to
-require hooks in the library. The reason is that the create
-and delete calls are internally wrapped in a transaction, so
-that if the call returns, the transaction has already either
-commited or aborted. Using only that interface limits what
-kind of testing we can do. To match our other recovery testing
-efforts, we need to add hooks to trigger aborts at particular
-times in the create/delete path.
-
-The general recovery testing strategy is that we wish to
-execute every path through every recovery routine. That
-means that we try to:
- catch each operation in its pre-operation state
- call the recovery function with redo
- call the recovery function with undo
- catch each operation in its post-operation state
- call the recovery function with redo
- call the recovery function with undo
-
-In addition, there are a few critical points in the create and
-delete path that we want to make sure we capture.
-
-1. Test Structure
-
-The test structure should be similar to the existing recovery
-tests. We will want to have a structure in place where we
-can execute different commands:
- create a file/database
- create a file that will contain subdatabases.
- create a subdatabase
- remove a subdatabase (that contains valid data)
- remove a subdatabase (that does not contain any data)
- remove a file that used to contain subdatabases
- remove a file that contains a database
-
-The tricky part is capturing the state of the world at the
-various points in the create/delete process.
-
-The critical points in the create process are:
-
- 1. After we've logged the create, but before we've done anything.
- in db/db.c
- after the open_retry
- after the __crdel_fileopen_log call (and before we've
- called __os_open).
-
- 2. Immediately after the __os_open
-
- 3. Immediately after each __db_log_page call
- in bt_open.c
- log meta-data page
- log root page
- in hash.c
- log meta-data page
-
- 4. With respect to the log records above, shortly after each
- log write is an memp_fput. We need to do a sync after
- each memp_fput and trigger a point after that sync.
-
-The critical points in the remove process are:
-
- 1. Right after the crdel_delete_log in db/db.c
-
- 2. Right after the __os_rename call (below the crdel_delete_log)
-
- 3. After the __db_remove_callback call.
-
-I believe that there are the places where we'll need some sort of hook.
-
-2. Adding hooks to the library.
-
-The hooks need two components. One component is to capture the state of
-the database at the hook point and the other is to trigger a txn_abort at
-the hook point. The second part is fairly trivial.
-
-The first part requires more thought. Let me explain what we do in a
-"normal" recovery test. In a normal recovery test, we save an intial
-copy of the database (this copy is called init). Then we execute one
-or more operations. Then, right before the commit/abort, we sync the
-file, and save another copy (the afterop copy). Finally, we call txn_commit
-or txn_abort, sync the file again, and save the database one last time (the
-final copy).
-
-Then we run recovery. The first time, this should be a no-op, because
-we've either committed the transaction and are checking to redo it or
-we aborted the transaction, undid it on the abort and are checking to
-undo it again.
-
-We then run recovery again on whatever database will force us through
-the path that requires work. In the commit case, this means we start
-with the init copy of the database and run recovery. This pushes us
-through all the redo paths. In the abort case, we start with the afterop
-copy which pushes us through all the undo cases.
-
-In some sense, we're asking the create/delete test to be more exhaustive
-by defining all the trigger points, but I think that's the correct thing
-to do, since the create/delete is not initiated by a user transaction.
-
-So, what do we have to do at the hook points?
- 1. sync the file to disk.
- 2. save the file itself
- 3. save any files named __db_backup_name(name, &backup_name, lsn)
- Since we may not know the right lsns, I think we should save
- every file of the form __db.name.0xNNNNNNNN.0xNNNNNNNN into
- some temporary files from which we can restore it to run
- recovery.
-
-3. Putting it all together
-
-So, the three pieces are writing the test structure, putting in the hooks
-and then writing the recovery portions so that we restore the right thing
-that the hooks saved in order to initiate recovery.
-
-Some of the technical issues that need to be solved are:
- How does the hook code become active (i.e., we don't
- want it in there normally, but it's got to be
- there when you configure for testing)?
- How do you (the test) tell the library that you want a
- particular hook to abort?
- How do you (the test) tell the library that you want the
- hook code doing its copies (do we really want
- *every* test doing these copies during testing?
- Maybe it's not a big deal, but maybe it is; we
- should at least think about it).
diff --git a/bdb/db/crdel.src b/bdb/db/crdel.src
index 17c061d6887..d89fa7a0382 100644
--- a/bdb/db/crdel.src
+++ b/bdb/db/crdel.src
@@ -1,13 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: crdel.src,v 11.12 2000/12/12 17:41:48 bostic Exp $
+ * $Id: crdel.src,v 11.24 2002/04/17 19:02:57 krinsky Exp $
*/
-PREFIX crdel
+PREFIX __crdel
+DBPRIVATE
INCLUDE #include "db_config.h"
INCLUDE
@@ -15,30 +16,20 @@ INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "txn.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
- * Fileopen -- log a potential file create operation
- *
- * name: filename
- * subname: sub database name
- * mode: file system mode
- */
-BEGIN fileopen 141
-DBT name DBT s
-ARG mode u_int32_t o
-END
-
-/*
* Metasub: log the creation of a subdatabase meta data page.
*
* fileid: identifies the file being acted upon.
@@ -47,57 +38,9 @@ END
* lsn: lsn of the page.
*/
BEGIN metasub 142
-ARG fileid int32_t ld
-ARG pgno db_pgno_t d
-DBT page DBT s
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
+PGDBT page DBT s
POINTER lsn DB_LSN * lu
END
-/*
- * Metapage: log the creation of a meta data page for a new file.
- *
- * fileid: identifies the file being acted upon.
- * name: file containing the page.
- * pgno: page number on which to write this meta-data page
- * page: the actual meta-data page
- */
-BEGIN metapage 143
-ARG fileid int32_t ld
-DBT name DBT s
-ARG pgno db_pgno_t d
-DBT page DBT s
-END
-
-/*
- * Delete: remove a file.
- * Note that we don't need a special log record for subdatabase
- * removes, because we use normal btree operations to remove them.
- *
- * name: name of the file being removed (relative to DBHOME).
- */
-DEPRECATED old_delete 144
-DBT name DBT s
-END
-
-/*
- * Rename: rename a file
- * We do not need this for subdatabases
- *
- * name: name of the file being removed (relative to DBHOME).
- */
-BEGIN rename 145
-ARG fileid int32_t ld
-DBT name DBT s
-DBT newname DBT s
-END
-/*
- * Delete: remove a file.
- * Note that we don't need a special log record for subdatabase
- * removes, because we use normal btree operations to remove them.
- *
- * name: name of the file being removed (relative to DBHOME).
- */
-BEGIN delete 146
-ARG fileid int32_t ld
-DBT name DBT s
-END
diff --git a/bdb/db/crdel_rec.c b/bdb/db/crdel_rec.c
index 495b92a0ad7..542a0c358dd 100644
--- a/bdb/db/crdel_rec.c
+++ b/bdb/db/crdel_rec.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: crdel_rec.c,v 11.43 2000/12/13 08:06:34 krinsky Exp $";
+static const char revid[] = "$Id: crdel_rec.c,v 11.64 2002/08/14 20:27:34 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,112 +18,9 @@ static const char revid[] = "$Id: crdel_rec.c,v 11.43 2000/12/13 08:06:34 krinsk
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "log.h"
-#include "hash.h"
-#include "mp.h"
-#include "db_dispatch.h"
-
-/*
- * __crdel_fileopen_recover --
- * Recovery function for fileopen.
- *
- * PUBLIC: int __crdel_fileopen_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__crdel_fileopen_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __crdel_fileopen_args *argp;
- DBMETA ondisk;
- DB_FH fh;
- size_t nr;
- int do_unlink, ret;
- u_int32_t b, mb, io;
- char *real_name;
-
- COMPQUIET(info, NULL);
-
- real_name = NULL;
- REC_PRINT(__crdel_fileopen_print);
-
- if ((ret = __crdel_fileopen_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
- /*
- * If this is an in-memory database, then the name is going to
- * be NULL, which looks like a 0-length name in recovery.
- */
- if (argp->name.size == 0)
- goto done;
-
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (DB_REDO(op)) {
- /*
- * The create commited, so we need to make sure that the file
- * exists. A simple open should suffice.
- */
- if ((ret = __os_open(dbenv, real_name,
- DB_OSO_CREATE, argp->mode, &fh)) != 0)
- goto out;
- if ((ret = __os_closehandle(&fh)) != 0)
- goto out;
- } else if (DB_UNDO(op)) {
- /*
- * If the file is 0-length then it was in the process of being
- * created, so we should unlink it. If it is non-0 length, then
- * either someone else created it and we need to leave it
- * untouched or we were in the process of creating it, allocated
- * the first page on a system that requires you to actually
- * write pages as you allocate them, but never got any data
- * on it.
- * If the file doesn't exist, we never got around to creating
- * it, so that's fine.
- */
- if (__os_exists(real_name, NULL) != 0)
- goto done;
-
- if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
- goto out;
- if ((ret = __os_ioinfo(dbenv,
- real_name, &fh, &mb, &b, &io)) != 0)
- goto out;
- do_unlink = 0;
- if (mb != 0 || b != 0) {
- /*
- * We need to read the first page
- * to see if its got valid data on it.
- */
- if ((ret = __os_read(dbenv, &fh,
- &ondisk, sizeof(ondisk), &nr)) != 0 ||
- nr != sizeof(ondisk))
- goto out;
- if (ondisk.magic == 0)
- do_unlink = 1;
- }
- if ((ret = __os_closehandle(&fh)) != 0)
- goto out;
- /* Check for 0-length and if it is, delete it. */
- if (do_unlink || (mb == 0 && b == 0))
- if ((ret = __os_unlink(dbenv, real_name)) != 0)
- goto out;
- }
-
-done: *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: if (argp != NULL)
- __os_free(argp, 0);
- if (real_name != NULL)
- __os_freestr(real_name);
- return (ret);
-}
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
/*
* __crdel_metasub_recover --
@@ -145,16 +42,16 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
- u_int8_t *file_uid, ptype;
- int cmp_p, modified, reopen, ret;
+ int cmp_p, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__crdel_metasub_print);
REC_INTRO(__crdel_metasub_read, 0);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
- if ((ret = memp_fget(mpf,
+ if ((ret = mpf->get(mpf,
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
} else {
@@ -165,7 +62,6 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
}
modified = 0;
- reopen = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
@@ -173,14 +69,6 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
memcpy(pagep, argp->page.data, argp->page.size);
LSN(pagep) = *lsnp;
modified = 1;
- /*
- * If this is a meta-data page, then we must reopen;
- * if it was a root page, then we do not.
- */
- ptype = ((DBMETA *)argp->page.data)->type;
- if (ptype == P_HASHMETA || ptype == P_BTREEMETA ||
- ptype == P_QAMMETA)
- reopen = 1;
} else if (DB_UNDO(op)) {
/*
* We want to undo this page creation. The page creation
@@ -196,451 +84,14 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
LSN(pagep) = argp->lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
-
- /*
- * If we are redoing a subdatabase create, we must close and reopen the
- * file to be sure that we have the proper meta information in the
- * in-memory structures
- */
- if (reopen) {
- /* Close cursor if it's open. */
- if (dbc != NULL) {
- dbc->c_close(dbc);
- dbc = NULL;
- }
-
- if ((ret = __os_malloc(dbenv,
- DB_FILE_ID_LEN, NULL, &file_uid)) != 0)
- goto out;
- memcpy(file_uid, &file_dbp->fileid[0], DB_FILE_ID_LEN);
- ret = __log_reopen_file(dbenv,
- NULL, argp->fileid, file_uid, argp->pgno);
- (void)__os_free(file_uid, DB_FILE_ID_LEN);
- if (ret != 0)
- goto out;
- }
-
-done: *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: REC_CLOSE;
-}
-
-/*
- * __crdel_metapage_recover --
- * Recovery function for metapage.
- *
- * PUBLIC: int __crdel_metapage_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__crdel_metapage_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __crdel_metapage_args *argp;
- DB *dbp;
- DBMETA *meta, ondisk;
- DB_FH fh;
- size_t nr;
- u_int32_t b, io, mb, pagesize;
- int is_done, ret;
- char *real_name;
-
- COMPQUIET(info, NULL);
-
- real_name = NULL;
- memset(&fh, 0, sizeof(fh));
- REC_PRINT(__crdel_metapage_print);
-
- if ((ret = __crdel_metapage_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
-
- /*
- * If this is an in-memory database, then the name is going to
- * be NULL, which looks like a 0-length name in recovery.
- */
- if (argp->name.size == 0)
- goto done;
-
- meta = (DBMETA *)argp->page.data;
- __ua_memcpy(&pagesize, &meta->pagesize, sizeof(pagesize));
-
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (DB_REDO(op)) {
- if ((ret = __db_fileid_to_db(dbenv,
- &dbp, argp->fileid, 0)) != 0) {
- if (ret == DB_DELETED)
- goto done;
- else
- goto out;
- }
-
- /*
- * We simply read the first page and if the LSN is 0, we
- * write the meta-data page.
- */
- if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
- goto out;
- if ((ret = __os_seek(dbenv, &fh,
- pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
- goto out;
- /*
- * If the read succeeds then the page exists, then we need
- * to vrify that the page has actually been written, because
- * on some systems (e.g., Windows) we preallocate pages because
- * files aren't allowed to have holes in them. If the page
- * looks good then we're done.
- */
- if ((ret = __os_read(dbenv, &fh, &ondisk,
- sizeof(ondisk), &nr)) == 0 && nr == sizeof(ondisk)) {
- if (ondisk.magic != 0)
- goto done;
- if ((ret = __os_seek(dbenv, &fh,
- pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
- goto out;
- }
-
- /*
- * Page didn't exist, update the LSN and write a new one.
- * (seek pointer shouldn't have moved)
- */
- __ua_memcpy(&meta->lsn, lsnp, sizeof(DB_LSN));
- if ((ret = __os_write(dbp->dbenv, &fh,
- argp->page.data, argp->page.size, &nr)) != 0)
- goto out;
- if (nr != (size_t)argp->page.size) {
- __db_err(dbenv, "Write failed during recovery");
- ret = EIO;
- goto out;
- }
-
- /*
- * We must close and reopen the file to be sure
- * that we have the proper meta information
- * in the in memory structures
- */
-
- if ((ret = __log_reopen_file(dbenv,
- argp->name.data, argp->fileid,
- meta->uid, argp->pgno)) != 0)
- goto out;
-
- /* Handle will be closed on exit. */
- } else if (DB_UNDO(op)) {
- is_done = 0;
-
- /* If file does not exist, there is nothing to undo. */
- if (__os_exists(real_name, NULL) != 0)
- goto done;
-
- /*
- * Before we can look at anything on disk, we have to check
- * if there is a valid dbp for this, and if there is, we'd
- * better flush it.
- */
- dbp = NULL;
- if ((ret =
- __db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) == 0)
- (void)dbp->sync(dbp, 0);
-
- /*
- * We need to make sure that we do not remove a file that
- * someone else created. If the file is 0-length, then we
- * can assume that we created it and remove it. If it is
- * not 0-length, then we need to check the LSN and make
- * sure that it's the file we created.
- */
- if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
- goto out;
- if ((ret = __os_ioinfo(dbenv,
- real_name, &fh, &mb, &b, &io)) != 0)
- goto out;
- if (mb != 0 || b != 0) {
- /* The file has something in it. */
- if ((ret = __os_seek(dbenv, &fh,
- pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
- goto out;
- if ((ret = __os_read(dbenv, &fh,
- &ondisk, sizeof(ondisk), &nr)) != 0)
- goto out;
- if (log_compare(&ondisk.lsn, lsnp) != 0)
- is_done = 1;
- }
-
- /*
- * Must close here, because unlink with the file open fails
- * on some systems.
- */
- if ((ret = __os_closehandle(&fh)) != 0)
- goto out;
-
- if (!is_done) {
- /*
- * On some systems, you cannot unlink an open file so
- * we close the fd in the dbp here and make sure we
- * don't try to close it again. First, check for a
- * saved_open_fhp, then close down the mpool.
- */
- if (dbp != NULL && dbp->saved_open_fhp != NULL &&
- F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
- (ret = __os_closehandle(dbp->saved_open_fhp)) != 0)
- goto out;
- if (dbp != NULL && dbp->mpf != NULL) {
- (void)__memp_fremove(dbp->mpf);
- if ((ret = memp_fclose(dbp->mpf)) != 0)
- goto out;
- F_SET(dbp, DB_AM_DISCARD);
- dbp->mpf = NULL;
- }
- if ((ret = __os_unlink(dbenv, real_name)) != 0)
- goto out;
- }
- }
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: if (argp != NULL)
- __os_free(argp, 0);
- if (real_name != NULL)
- __os_freestr(real_name);
- if (F_ISSET(&fh, DB_FH_VALID))
- (void)__os_closehandle(&fh);
- return (ret);
-}
-
-/*
- * __crdel_delete_recover --
- * Recovery function for delete.
- *
- * PUBLIC: int __crdel_delete_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__crdel_delete_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- DB *dbp;
- __crdel_delete_args *argp;
- int ret;
- char *backup, *real_back, *real_name;
-
- REC_PRINT(__crdel_delete_print);
-
- backup = real_back = real_name = NULL;
- if ((ret = __crdel_delete_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
-
- if (DB_REDO(op)) {
- /*
- * On a recovery, as we recreate what was going on, we
- * recreate the creation of the file. And so, even though
- * it committed, we need to delete it. Try to delete it,
- * but it is not an error if that delete fails.
- */
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (__os_exists(real_name, NULL) == 0) {
- /*
- * If a file is deleted and then recreated, it's
- * possible for the __os_exists call above to
- * return success and for us to get here, but for
- * the fileid we're looking for to be marked
- * deleted. In that case, we needn't redo the
- * unlink even though the file exists, and it's
- * not an error.
- */
- ret = __db_fileid_to_db(dbenv, &dbp, argp->fileid, 0);
- if (ret == 0) {
- /*
- * On Windows, the underlying file must be
- * closed to perform a remove.
- */
- (void)__memp_fremove(dbp->mpf);
- if ((ret = memp_fclose(dbp->mpf)) != 0)
- goto out;
- dbp->mpf = NULL;
- if ((ret = __os_unlink(dbenv, real_name)) != 0)
- goto out;
- } else if (ret != DB_DELETED)
- goto out;
- }
- /*
- * The transaction committed, so the only thing that might
- * be true is that the backup file is still around. Try
- * to delete it, but it's not an error if that delete fails.
- */
- if ((ret = __db_backup_name(dbenv, argp->name.data,
- &backup, lsnp)) != 0)
- goto out;
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
- goto out;
- if (__os_exists(real_back, NULL) == 0)
- if ((ret = __os_unlink(dbenv, real_back)) != 0)
- goto out;
- if ((ret = __db_txnlist_delete(dbenv, info,
- argp->name.data, TXNLIST_INVALID_ID, 1)) != 0)
- goto out;
- } else if (DB_UNDO(op)) {
- /*
- * Trying to undo. File may or may not have been deleted.
- * Try to move the backup to the original. If the backup
- * exists, then this is right. If it doesn't exist, then
- * nothing will happen and that's OK.
- */
- if ((ret = __db_backup_name(dbenv, argp->name.data,
- &backup, lsnp)) != 0)
- goto out;
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
- goto out;
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (__os_exists(real_back, NULL) == 0)
- if ((ret =
- __os_rename(dbenv, real_back, real_name)) != 0)
- goto out;
- }
-
- *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: if (argp != NULL)
- __os_free(argp, 0);
- if (backup != NULL)
- __os_freestr(backup);
- if (real_back != NULL)
- __os_freestr(real_back);
- if (real_name != NULL)
- __os_freestr(real_name);
- return (ret);
-}
-/*
- * __crdel_rename_recover --
- * Recovery function for rename.
- *
- * PUBLIC: int __crdel_rename_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__crdel_rename_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- DB *dbp;
- __crdel_rename_args *argp;
- char *new_name, *real_name;
- int ret, set;
-
- COMPQUIET(info, NULL);
-
- REC_PRINT(__crdel_rename_print);
-
- new_name = real_name = NULL;
-
- if ((ret = __crdel_rename_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
-
- if ((ret = __db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) != 0)
- goto out;
- if (DB_REDO(op)) {
- /*
- * We don't use the dbp parameter to __log_filelist_update
- * in the rename case, so passing NULL for it is OK.
- */
- if ((ret = __log_filelist_update(dbenv, NULL,
- argp->fileid, argp->newname.data, &set)) != 0)
- goto out;
- if (set != 0) {
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (__os_exists(real_name, NULL) == 0) {
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, argp->newname.data,
- 0, NULL, &new_name)) != 0)
- goto out;
- /*
- * On Windows, the underlying file
- * must be closed to perform a remove.
- * The db will be closed by a
- * log_register record. Rename
- * has exclusive access to the db.
- */
- (void)__memp_fremove(dbp->mpf);
- if ((ret = memp_fclose(dbp->mpf)) != 0)
- goto out;
- dbp->mpf = NULL;
- if ((ret = __os_rename(dbenv,
- real_name, new_name)) != 0)
- goto out;
- }
- }
- } else {
- /*
- * We don't use the dbp parameter to __log_filelist_update
- * in the rename case, so passing NULL for it is OK.
- */
- if ((ret = __log_filelist_update(dbenv, NULL,
- argp->fileid, argp->name.data, &set)) != 0)
- goto out;
- if (set != 0) {
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->newname.data, 0, NULL, &new_name)) != 0)
- goto out;
- if (__os_exists(new_name, NULL) == 0) {
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, argp->name.data,
- 0, NULL, &real_name)) != 0)
- goto out;
- /*
- * On Windows, the underlying file
- * must be closed to perform a remove.
- * The file may have already been closed
- * if we are aborting the transaction.
- */
- if (dbp->mpf != NULL) {
- (void)__memp_fremove(dbp->mpf);
- if ((ret = memp_fclose(dbp->mpf)) != 0)
- goto out;
- dbp->mpf = NULL;
- }
- if ((ret = __os_rename(dbenv,
- new_name, real_name)) != 0)
- goto out;
- }
- }
- }
-
- *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: if (argp != NULL)
- __os_free(argp, 0);
-
- if (new_name != NULL)
- __os_free(new_name, 0);
-
- if (real_name != NULL)
- __os_free(real_name, 0);
-
- return (ret);
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
diff --git a/bdb/db/db.c b/bdb/db/db.c
index 6e74b4b21bd..986167d5ade 100644
--- a/bdb/db/db.c
+++ b/bdb/db/db.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -40,7 +40,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db.c,v 11.117 2001/01/11 18:19:50 bostic Exp $";
+static const char revid[] = "$Id: db.c,v 11.246 2002/08/20 14:40:00 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -52,352 +52,41 @@ static const char revid[] = "$Id: db.c,v 11.117 2001/01/11 18:19:50 bostic Exp $
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "db_swap.h"
-#include "btree.h"
-#include "db_am.h"
-#include "hash.h"
-#include "lock.h"
-#include "log.h"
-#include "mp.h"
-#include "qam.h"
-#include "common_ext.h"
-
-/* Actions that __db_master_update can take. */
-typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN } mu_action;
-
-/* Flag values that __db_file_setup can return. */
-#define DB_FILE_SETUP_CREATE 0x01
-#define DB_FILE_SETUP_ZERO 0x02
-
-static int __db_file_setup __P((DB *,
- const char *, u_int32_t, int, db_pgno_t, int *));
-static int __db_master_update __P((DB *,
- const char *, u_int32_t,
- db_pgno_t *, mu_action, const char *, u_int32_t));
-static int __db_refresh __P((DB *));
-static int __db_remove_callback __P((DB *, void *));
-static int __db_set_pgsize __P((DB *, DB_FH *, char *));
-static int __db_subdb_remove __P((DB *, const char *, const char *));
-static int __db_subdb_rename __P(( DB *,
- const char *, const char *, const char *));
-#if CONFIG_TEST
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+#include "dbinc/txn.h"
+
+static int __db_disassociate __P((DB *));
+#if CONFIG_TEST
static void __db_makecopy __P((const char *, const char *));
-static int __db_testdocopy __P((DB *, const char *));
-static int __qam_testdocopy __P((DB *, const char *));
+static int __db_testdocopy __P((DB_ENV *, const char *));
+static int __qam_testdocopy __P((DB *, const char *));
#endif
/*
- * __db_open --
- * Main library interface to the DB access methods.
- *
- * PUBLIC: int __db_open __P((DB *,
- * PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int));
+ * DB.C --
+ * This file contains the utility functions for the DBP layer.
*/
-int
-__db_open(dbp, name, subdb, type, flags, mode)
- DB *dbp;
- const char *name, *subdb;
- DBTYPE type;
- u_int32_t flags;
- int mode;
-{
- DB_ENV *dbenv;
- DB_LOCK open_lock;
- DB *mdbp;
- db_pgno_t meta_pgno;
- u_int32_t ok_flags;
- int ret, t_ret;
-
- dbenv = dbp->dbenv;
- mdbp = NULL;
-
- /* Validate arguments. */
-#define OKFLAGS \
- (DB_CREATE | DB_EXCL | DB_FCNTL_LOCKING | \
- DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER | DB_THREAD | DB_TRUNCATE)
- if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
- return (ret);
- if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
- return (__db_ferr(dbenv, "DB->open", 1));
- if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
- return (__db_ferr(dbenv, "DB->open", 1));
-#ifdef HAVE_VXWORKS
- if (LF_ISSET(DB_TRUNCATE)) {
- __db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks");
- return (__db_eopnotsup(dbenv));
- }
-#endif
- switch (type) {
- case DB_UNKNOWN:
- if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) {
- __db_err(dbenv,
- "%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE",
- name);
- return (EINVAL);
- }
- ok_flags = 0;
- break;
- case DB_BTREE:
- ok_flags = DB_OK_BTREE;
- break;
- case DB_HASH:
- ok_flags = DB_OK_HASH;
- break;
- case DB_QUEUE:
- ok_flags = DB_OK_QUEUE;
- break;
- case DB_RECNO:
- ok_flags = DB_OK_RECNO;
- break;
- default:
- __db_err(dbenv, "unknown type: %lu", (u_long)type);
- return (EINVAL);
- }
- if (ok_flags)
- DB_ILLEGAL_METHOD(dbp, ok_flags);
-
- /* The environment may have been created, but never opened. */
- if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
- __db_err(dbenv, "environment not yet opened");
- return (EINVAL);
- }
-
- /*
- * Historically, you could pass in an environment that didn't have a
- * mpool, and DB would create a private one behind the scenes. This
- * no longer works.
- */
- if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
- __db_err(dbenv, "environment did not include a memory pool.");
- return (EINVAL);
- }
-
- /*
- * You can't specify threads during DB->open if subsystems in the
- * environment weren't configured with them.
- */
- if (LF_ISSET(DB_THREAD) &&
- !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
- __db_err(dbenv, "environment not created using DB_THREAD");
- return (EINVAL);
- }
-
- /*
- * If the environment was configured with threads, the DB handle
- * must also be free-threaded, so we force the DB_THREAD flag on.
- * (See SR #2033 for why this is a requirement--recovery needs
- * to be able to grab a dbp using __db_fileid_to_dbp, and it has
- * no way of knowing which dbp goes with which thread, so whichever
- * one it finds has to be usable in any of them.)
- */
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- LF_SET(DB_THREAD);
-
- /* DB_TRUNCATE is not transaction recoverable. */
- if (LF_ISSET(DB_TRUNCATE) && TXN_ON(dbenv)) {
- __db_err(dbenv,
- "DB_TRUNCATE illegal in a transaction protected environment");
- return (EINVAL);
- }
-
- /* Subdatabase checks. */
- if (subdb != NULL) {
- /* Subdatabases must be created in named files. */
- if (name == NULL) {
- __db_err(dbenv,
- "multiple databases cannot be created in temporary files");
- return (EINVAL);
- }
-
- /* QAM can't be done as a subdatabase. */
- if (type == DB_QUEUE) {
- __db_err(dbenv, "Queue databases must be one-per-file");
- return (EINVAL);
- }
- }
-
- /* Convert any DB->open flags. */
- if (LF_ISSET(DB_RDONLY))
- F_SET(dbp, DB_AM_RDONLY);
-
- /* Fill in the type. */
- dbp->type = type;
-
- /*
- * If we're potentially creating a database, wrap the open inside of
- * a transaction.
- */
- if (TXN_ON(dbenv) && LF_ISSET(DB_CREATE))
- if ((ret = __db_metabegin(dbp, &open_lock)) != 0)
- return (ret);
-
- /*
- * If we're opening a subdatabase, we have to open (and potentially
- * create) the main database, and then get (and potentially store)
- * our base page number in that database. Then, we can finally open
- * the subdatabase.
- */
- if (subdb == NULL)
- meta_pgno = PGNO_BASE_MD;
- else {
- /*
- * Open the master database, optionally creating or updating
- * it, and retrieve the metadata page number.
- */
- if ((ret =
- __db_master_open(dbp, name, flags, mode, &mdbp)) != 0)
- goto err;
-
- /* Copy the page size and file id from the master. */
- dbp->pgsize = mdbp->pgsize;
- F_SET(dbp, DB_AM_SUBDB);
- memcpy(dbp->fileid, mdbp->fileid, DB_FILE_ID_LEN);
-
- if ((ret = __db_master_update(mdbp,
- subdb, type, &meta_pgno, MU_OPEN, NULL, flags)) != 0)
- goto err;
-
- /*
- * Clear the exclusive open and truncation flags, they only
- * apply to the open of the master database.
- */
- LF_CLR(DB_EXCL | DB_TRUNCATE);
- }
-
- ret = __db_dbopen(dbp, name, flags, mode, meta_pgno);
-
- /*
- * You can open the database that describes the subdatabases in the
- * rest of the file read-only. The content of each key's data is
- * unspecified and applications should never be adding new records
- * or updating existing records. However, during recovery, we need
- * to open these databases R/W so we can redo/undo changes in them.
- * Likewise, we need to open master databases read/write during
- * rename and remove so we can be sure they're fully sync'ed, so
- * we provide an override flag for the purpose.
- */
- if (subdb == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
- !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
- __db_err(dbenv,
- "files containing multiple databases may only be opened read-only");
- ret = EINVAL;
- goto err;
- }
-
-err: /*
- * End any transaction, committing if we were successful, aborting
- * otherwise.
- */
- if (TXN_ON(dbenv) && LF_ISSET(DB_CREATE))
- if ((t_ret = __db_metaend(dbp,
- &open_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
- ret = t_ret;
-
- /* If we were successful, don't discard the file on close. */
- if (ret == 0)
- F_CLR(dbp, DB_AM_DISCARD);
-
- /* If we were unsuccessful, destroy the DB handle. */
- if (ret != 0) {
- /* In recovery we set log_fileid early. */
- if (IS_RECOVERING(dbenv))
- dbp->log_fileid = DB_LOGFILEID_INVALID;
- __db_refresh(dbp);
- }
-
- if (mdbp != NULL) {
- /* If we were successful, don't discard the file on close. */
- if (ret == 0)
- F_CLR(mdbp, DB_AM_DISCARD);
- if ((t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
- ret = t_ret;
- }
-
- return (ret);
-}
-
-/*
- * __db_dbopen --
- * Open a database.
- * PUBLIC: int __db_dbopen __P((DB *, const char *, u_int32_t, int, db_pgno_t));
- */
-int
-__db_dbopen(dbp, name, flags, mode, meta_pgno)
- DB *dbp;
- const char *name;
- u_int32_t flags;
- int mode;
- db_pgno_t meta_pgno;
-{
- DB_ENV *dbenv;
- int ret, retinfo;
-
- dbenv = dbp->dbenv;
-
- /* Set up the underlying file. */
- if ((ret = __db_file_setup(dbp,
- name, flags, mode, meta_pgno, &retinfo)) != 0)
- return (ret);
-
- /*
- * If we created the file, set the truncate flag for the mpool. This
- * isn't for anything we've done, it's protection against stupid user
- * tricks: if the user deleted a file behind Berkeley DB's back, we
- * may still have pages in the mpool that match the file's "unique" ID.
- */
- if (retinfo & DB_FILE_SETUP_CREATE)
- flags |= DB_TRUNCATE;
-
- /* Set up the underlying environment. */
- if ((ret = __db_dbenv_setup(dbp, name, flags)) != 0)
- return (ret);
-
- /*
- * Do access method specific initialization.
- *
- * !!!
- * Set the open flag. (The underlying access method open functions
- * may want to do things like acquire cursors, so the open flag has
- * to be set before calling them.)
- */
- F_SET(dbp, DB_OPEN_CALLED);
-
- if (retinfo & DB_FILE_SETUP_ZERO)
- return (0);
-
- switch (dbp->type) {
- case DB_BTREE:
- ret = __bam_open(dbp, name, meta_pgno, flags);
- break;
- case DB_HASH:
- ret = __ham_open(dbp, name, meta_pgno, flags);
- break;
- case DB_RECNO:
- ret = __ram_open(dbp, name, meta_pgno, flags);
- break;
- case DB_QUEUE:
- ret = __qam_open(dbp, name, meta_pgno, mode, flags);
- break;
- case DB_UNKNOWN:
- return (__db_unknown_type(dbp->dbenv,
- "__db_dbopen", dbp->type));
- break;
- }
- return (ret);
-}
/*
* __db_master_open --
* Open up a handle on a master database.
*
* PUBLIC: int __db_master_open __P((DB *,
- * PUBLIC: const char *, u_int32_t, int, DB **));
+ * PUBLIC: DB_TXN *, const char *, u_int32_t, int, DB **));
*/
int
-__db_master_open(subdbp, name, flags, mode, dbpp)
+__db_master_open(subdbp, txn, name, flags, mode, dbpp)
DB *subdbp;
+ DB_TXN *txn;
const char *name;
u_int32_t flags;
int mode;
@@ -417,30 +106,62 @@ __db_master_open(subdbp, name, flags, mode, dbpp)
* Flag that we're creating a database with subdatabases.
*/
dbp->type = DB_BTREE;
- dbp->open_txn = subdbp->open_txn;
dbp->pgsize = subdbp->pgsize;
F_SET(dbp, DB_AM_SUBDB);
+ F_SET(dbp, F_ISSET(subdbp,
+ DB_AM_RECOVER | DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM));
- if ((ret = __db_dbopen(dbp, name, flags, mode, PGNO_BASE_MD)) != 0) {
- if (!F_ISSET(dbp, DB_AM_DISCARD))
- dbp->close(dbp, 0);
- return (ret);
- }
+ /*
+ * If there was a subdb specified, then we only want to apply
+ * DB_EXCL to the subdb, not the actual file. We only got here
+ * because there was a subdb specified.
+ */
+ LF_CLR(DB_EXCL);
+ LF_SET(DB_RDWRMASTER);
+ if ((ret = __db_dbopen(dbp, txn, name, NULL, flags, mode, PGNO_BASE_MD))
+ != 0)
+ goto err;
- *dbpp = dbp;
- return (0);
+ /*
+ * Verify that pagesize is the same on both.
+ * The items in dbp were now initialized from the meta
+ * page. The items in dbp were set in __db_dbopen
+ * when we either read or created the master file.
+ * Other items such as checksum and encryption are
+ * checked when we read the meta-page. So we do not
+ * check those here. However, if the meta-page caused
+ * chksumming to be turned on and it wasn't already, set
+ * it here.
+ */
+ if (F_ISSET(dbp, DB_AM_CHKSUM))
+ F_SET(subdbp, DB_AM_CHKSUM);
+ if (subdbp->pgsize != 0 && dbp->pgsize != subdbp->pgsize) {
+ ret = EINVAL;
+ __db_err(dbp->dbenv,
+ "Different pagesize specified on existent file");
+ goto err;
+ }
+err:
+ if (ret != 0 && !F_ISSET(dbp, DB_AM_DISCARD))
+ __db_close_i(dbp, txn, 0);
+ else
+ *dbpp = dbp;
+ return (ret);
}
/*
* __db_master_update --
- * Add/Remove a subdatabase from a master database.
+ * Add/Open/Remove a subdatabase from a master database.
+ *
+ * PUBLIC: int __db_master_update __P((DB *, DB *, DB_TXN *, const char *,
+ * PUBLIC: DBTYPE, mu_action, const char *, u_int32_t));
*/
-static int
-__db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
- DB *mdbp;
+int
+__db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
+ DB *mdbp, *sdbp;
+ DB_TXN *txn;
const char *subdb;
- u_int32_t type;
- db_pgno_t *meta_pgnop; /* may be NULL on MU_RENAME */
+ DBTYPE type;
mu_action action;
const char *newname;
u_int32_t flags;
@@ -456,33 +177,37 @@ __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
dbc = ndbc = NULL;
p = NULL;
- /* Might we modify the master database? If so, we'll need to lock. */
- modify = (action != MU_OPEN || LF_ISSET(DB_CREATE)) ? 1 : 0;
-
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
+ /* Might we modify the master database? If so, we'll need to lock. */
+ modify = (action != MU_OPEN || LF_ISSET(DB_CREATE)) ? 1 : 0;
+
/*
* Open up a cursor. If this is CDB and we're creating the database,
* make it an update cursor.
*/
- if ((ret = mdbp->cursor(mdbp, mdbp->open_txn, &dbc,
+ if ((ret = mdbp->cursor(mdbp, txn, &dbc,
(CDB_LOCKING(dbenv) && modify) ? DB_WRITECURSOR : 0)) != 0)
goto err;
/*
- * Try to point the cursor at the record.
+ * Point the cursor at the record.
*
* If we're removing or potentially creating an entry, lock the page
* with DB_RMW.
*
+ * We do multiple cursor operations with the cursor in some cases and
+ * subsequently access the data DBT information. Set DB_DBT_MALLOC so
+ * we don't risk modification of the data between our uses of it.
+ *
* !!!
* We don't include the name's nul termination in the database.
*/
- key.data = (char *)subdb;
- key.size = strlen(subdb);
- /* In the rename case, we do multiple cursor ops, so MALLOC is safer. */
+ key.data = (void *)subdb;
+ key.size = (u_int32_t)strlen(subdb);
F_SET(&data, DB_DBT_MALLOC);
+
ret = dbc->c_get(dbc, &key, &data,
DB_SET | ((STD_LOCKING(dbc) && modify) ? DB_RMW : 0));
@@ -514,9 +239,10 @@ __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
* so it hasn't been converted to/from opposite
* endian architectures. Do it explicitly, now.
*/
- memcpy(meta_pgnop, data.data, sizeof(db_pgno_t));
- DB_NTOHL(meta_pgnop);
- if ((ret = memp_fget(mdbp->mpf, meta_pgnop, 0, &p)) != 0)
+ memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));
+ DB_NTOHL(&sdbp->meta_pgno);
+ if ((ret =
+ mdbp->mpf->get(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)
goto err;
/* Free and put the page. */
@@ -538,11 +264,11 @@ __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
* for the existence of newname; it shouldn't appear under
* us since we hold the metadata lock.
*/
- if ((ret = mdbp->cursor(mdbp, mdbp->open_txn, &ndbc, 0)) != 0)
+ if ((ret = mdbp->cursor(mdbp, txn, &ndbc, 0)) != 0)
goto err;
DB_ASSERT(newname != NULL);
- key.data = (void *) newname;
- key.size = strlen(newname);
+ key.data = (void *)newname;
+ key.size = (u_int32_t)strlen(newname);
/*
* We don't actually care what the meta page of the potentially-
@@ -583,8 +309,12 @@ __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
*/
switch (ret) {
case 0:
- memcpy(meta_pgnop, data.data, sizeof(db_pgno_t));
- DB_NTOHL(meta_pgnop);
+ if (LF_ISSET(DB_CREATE) && LF_ISSET(DB_EXCL)) {
+ ret = EEXIST;
+ goto err;
+ }
+ memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));
+ DB_NTOHL(&sdbp->meta_pgno);
goto done;
case DB_NOTFOUND:
if (LF_ISSET(DB_CREATE))
@@ -599,10 +329,22 @@ __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
goto err;
}
+ /*
+ * We need to check against the master lorder here because
+ * we only want to check this if we are creating. In the
+ * case where we don't create we just want to inherit.
+ */
+ if (F_ISSET(mdbp, DB_AM_SWAP) != F_ISSET(sdbp, DB_AM_SWAP)) {
+ ret = EINVAL;
+ __db_err(mdbp->dbenv,
+ "Different lorder specified on existent file");
+ goto err;
+ }
+ /* Create a subdatabase. */
if ((ret = __db_new(dbc,
type == DB_HASH ? P_HASHMETA : P_BTREEMETA, &p)) != 0)
goto err;
- *meta_pgnop = PGNO(p);
+ sdbp->meta_pgno = PGNO(p);
/*
* XXX
@@ -617,6 +359,7 @@ __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
ndata.size = sizeof(db_pgno_t);
if ((ret = dbc->c_put(dbc, &key, &ndata, DB_KEYLAST)) != 0)
goto err;
+ F_SET(sdbp, DB_AM_CREATED);
break;
}
@@ -628,7 +371,7 @@ done: /*
if (p != NULL) {
if (ret == 0) {
if ((t_ret =
- memp_fput(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)
+ mdbp->mpf->put(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)
ret = t_ret;
/*
* Since we cannot close this file until after
@@ -639,12 +382,12 @@ done: /*
if ((t_ret = mdbp->sync(mdbp, 0)) != 0 && ret == 0)
ret = t_ret;
} else
- (void)__db_free(dbc, p);
+ (void)mdbp->mpf->put(mdbp->mpf, p, 0);
}
/* Discard the cursor(s) and data. */
if (data.data != NULL)
- __os_free(data.data, data.size);
+ __os_ufree(dbenv, data.data);
if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
if (ndbc != NULL && (t_ret = ndbc->c_close(ndbc)) != 0 && ret == 0)
@@ -657,21 +400,25 @@ done: /*
* __db_dbenv_setup --
* Set up the underlying environment during a db_open.
*
- * PUBLIC: int __db_dbenv_setup __P((DB *, const char *, u_int32_t));
+ * PUBLIC: int __db_dbenv_setup __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, u_int32_t, u_int32_t));
*/
int
-__db_dbenv_setup(dbp, name, flags)
+__db_dbenv_setup(dbp, txn, name, id, flags)
DB *dbp;
+ DB_TXN *txn;
const char *name;
+ u_int32_t id;
u_int32_t flags;
{
DB *ldbp;
- DB_ENV *dbenv;
DBT pgcookie;
- DB_MPOOL_FINFO finfo;
+ DB_ENV *dbenv;
+ DB_MPOOL *dbmp;
+ DB_MPOOLFILE *mpf;
DB_PGINFO pginfo;
- int ret;
u_int32_t maxid;
+ int ftype, ret;
dbenv = dbp->dbenv;
@@ -690,8 +437,18 @@ __db_dbenv_setup(dbp, name, flags)
}
/* Register DB's pgin/pgout functions. */
- if ((ret =
- memp_register(dbenv, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0)
+ if ((ret = dbenv->memp_register(
+ dbenv, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0)
+ return (ret);
+
+ /* Create the DB_MPOOLFILE structure. */
+ if ((ret = dbenv->memp_fcreate(dbenv, &dbp->mpf, 0)) != 0)
+ return (ret);
+ mpf = dbp->mpf;
+
+ /* Set the database's cache priority if we've been given one. */
+ if (dbp->priority != 0 &&
+ (ret = mpf->set_priority(mpf, dbp->priority)) != 0)
return (ret);
/*
@@ -704,22 +461,26 @@ __db_dbenv_setup(dbp, name, flags)
* need to page the file in and out. This has to be right -- we can't
* mmap files that are being paged in and out.
*/
- memset(&finfo, 0, sizeof(finfo));
switch (dbp->type) {
case DB_BTREE:
case DB_RECNO:
- finfo.ftype =
- F_ISSET(dbp, DB_AM_SWAP) ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
- finfo.clear_len = DB_PAGE_DB_LEN;
+ ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
+ ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
+ (void)mpf->set_ftype(mpf, ftype);
+ (void)mpf->set_clear_len(mpf, (CRYPTO_ON(dbenv) ?
+ dbp->pgsize : DB_PAGE_DB_LEN));
break;
case DB_HASH:
- finfo.ftype = DB_FTYPE_SET;
- finfo.clear_len = DB_PAGE_DB_LEN;
+ (void)mpf->set_ftype(mpf, DB_FTYPE_SET);
+ (void)mpf->set_clear_len(mpf, (CRYPTO_ON(dbenv) ?
+ dbp->pgsize : DB_PAGE_DB_LEN));
break;
case DB_QUEUE:
- finfo.ftype =
- F_ISSET(dbp, DB_AM_SWAP) ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
- finfo.clear_len = DB_PAGE_QUEUE_LEN;
+ ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
+ ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
+ (void)mpf->set_ftype(mpf, ftype);
+ (void)mpf->set_clear_len(mpf, (CRYPTO_ON(dbenv) ?
+ dbp->pgsize : DB_PAGE_QUEUE_LEN));
break;
case DB_UNKNOWN:
/*
@@ -735,48 +496,63 @@ __db_dbenv_setup(dbp, name, flags)
* to salvage some data even with no metadata page.
*/
if (F_ISSET(dbp, DB_AM_VERIFYING)) {
- finfo.ftype = DB_FTYPE_NOTSET;
- finfo.clear_len = DB_PAGE_DB_LEN;
+ (void)mpf->set_ftype(mpf, DB_FTYPE_NOTSET);
+ (void)mpf->set_clear_len(mpf, DB_PAGE_DB_LEN);
break;
}
- return (__db_unknown_type(dbp->dbenv,
- "__db_dbenv_setup", dbp->type));
+ /* FALLTHROUGH */
+ default:
+ return (
+ __db_unknown_type(dbenv, "__db_dbenv_setup", dbp->type));
}
- finfo.pgcookie = &pgcookie;
- finfo.fileid = dbp->fileid;
- finfo.lsn_offset = 0;
+
+ (void)mpf->set_fileid(mpf, dbp->fileid);
+ (void)mpf->set_lsn_offset(mpf, 0);
pginfo.db_pagesize = dbp->pgsize;
- pginfo.needswap = F_ISSET(dbp, DB_AM_SWAP);
+ pginfo.flags =
+ F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+ pginfo.type = dbp->type;
pgcookie.data = &pginfo;
pgcookie.size = sizeof(DB_PGINFO);
+ (void)mpf->set_pgcookie(mpf, &pgcookie);
- if ((ret = memp_fopen(dbenv, name,
- LF_ISSET(DB_RDONLY | DB_NOMMAP | DB_ODDFILESIZE | DB_TRUNCATE),
- 0, dbp->pgsize, &finfo, &dbp->mpf)) != 0)
+ if ((ret = mpf->open(mpf, name,
+ LF_ISSET(DB_RDONLY | DB_NOMMAP | DB_ODDFILESIZE | DB_TRUNCATE) |
+ (F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0),
+ 0, dbp->pgsize)) != 0)
return (ret);
/*
- * We may need a per-thread mutex. Allocate it from the environment
+ * We may need a per-thread mutex. Allocate it from the mpool
* region, there's supposed to be extra space there for that purpose.
*/
if (LF_ISSET(DB_THREAD)) {
- if ((ret = __db_mutex_alloc(
- dbenv, dbenv->reginfo, (MUTEX **)&dbp->mutexp)) != 0)
+ dbmp = dbenv->mp_handle;
+ if ((ret = __db_mutex_setup(dbenv, dbmp->reginfo, &dbp->mutexp,
+ MUTEX_ALLOC | MUTEX_THREAD)) != 0)
return (ret);
- if ((ret = __db_mutex_init(
- dbenv, dbp->mutexp, 0, MUTEX_THREAD)) != 0) {
- __db_mutex_free(dbenv, dbenv->reginfo, dbp->mutexp);
- return (ret);
- }
}
- /* Get a log file id. */
- if (LOGGING_ON(dbenv) && !IS_RECOVERING(dbenv) &&
+ /*
+ * Set up a bookkeeping entry for this database in the log region,
+ * if such a region exists. Note that even if we're in recovery
+ * or a replication client, where we won't log registries, we'll
+ * still need an FNAME struct, so LOGGING_ON is the correct macro.
+ */
+ if (LOGGING_ON(dbenv) &&
+ (ret = __dbreg_setup(dbp, name, id)) != 0)
+ return (ret);
+
+ /*
+ * If we're actively logging and our caller isn't a recovery function
+ * that already did so, assign this dbp a log fileid.
+ */
+ if (DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER) &&
#if !defined(DEBUG_ROP)
!F_ISSET(dbp, DB_AM_RDONLY) &&
#endif
- (ret = log_register(dbenv, dbp, name)) != 0)
+ (ret = __dbreg_new_id(dbp, txn)) != 0)
return (ret);
/*
@@ -822,541 +598,69 @@ __db_dbenv_setup(dbp, name, flags)
}
/*
- * __db_file_setup --
- * Setup the file or in-memory data.
- * Read the database metadata and resolve it with our arguments.
+ * __db_close --
+ * DB destructor.
+ *
+ * PUBLIC: int __db_close __P((DB *, u_int32_t));
*/
-static int
-__db_file_setup(dbp, name, flags, mode, meta_pgno, retflags)
+int
+__db_close(dbp, flags)
DB *dbp;
- const char *name;
u_int32_t flags;
- int mode;
- db_pgno_t meta_pgno;
- int *retflags;
-{
- DB *mdb;
- DBT namedbt;
- DB_ENV *dbenv;
- DB_FH *fhp, fh;
- DB_LSN lsn;
- DB_TXN *txn;
- size_t nr;
- u_int32_t magic, oflags;
- int ret, retry_cnt, t_ret;
- char *real_name, mbuf[DBMETASIZE];
-
-#define IS_SUBDB_SETUP (meta_pgno != PGNO_BASE_MD)
-
- dbenv = dbp->dbenv;
- dbp->meta_pgno = meta_pgno;
- txn = NULL;
- *retflags = 0;
-
- /*
- * If we open a file handle and our caller is doing fcntl(2) locking,
- * we can't close it because that would discard the caller's lock.
- * Save it until we close the DB handle.
- */
- if (LF_ISSET(DB_FCNTL_LOCKING)) {
- if ((ret = __os_malloc(dbenv, sizeof(*fhp), NULL, &fhp)) != 0)
- return (ret);
- } else
- fhp = &fh;
- memset(fhp, 0, sizeof(*fhp));
-
- /*
- * If the file is in-memory, set up is simple. Otherwise, do the
- * hard work of opening and reading the file.
- *
- * If we have a file name, try and read the first page, figure out
- * what type of file it is, and initialize everything we can based
- * on that file's meta-data page.
- *
- * !!!
- * There's a reason we don't push this code down into the buffer cache.
- * The problem is that there's no information external to the file that
- * we can use as a unique ID. UNIX has dev/inode pairs, but they are
- * not necessarily unique after reboot, if the file was mounted via NFS.
- * Windows has similar problems, as the FAT filesystem doesn't maintain
- * dev/inode numbers across reboot. So, we must get something from the
- * file we can use to ensure that, even after a reboot, the file we're
- * joining in the cache is the right file for us to join. The solution
- * we use is to maintain a file ID that's stored in the database, and
- * that's why we have to open and read the file before calling into the
- * buffer cache.
- *
- * The secondary reason is that there's additional information that
- * we want to have before instantiating a file in the buffer cache:
- * the page size, file type (btree/hash), if swapping is required,
- * and flags (DB_RDONLY, DB_CREATE, DB_TRUNCATE). We could handle
- * needing this information by allowing it to be set for a file in
- * the buffer cache even after the file has been opened, and, of
- * course, supporting the ability to flush a file from the cache as
- * necessary, e.g., if we guessed wrongly about the page size. Given
- * that we have to read the file anyway to get the file ID, we might
- * as well get the rest, too.
- *
- * Get the real file name.
- */
- if (name == NULL) {
- F_SET(dbp, DB_AM_INMEM);
-
- if (dbp->type == DB_UNKNOWN) {
- __db_err(dbenv,
- "DBTYPE of unknown without existing file");
- return (EINVAL);
- }
- real_name = NULL;
-
- /* Set the page size if we don't have one yet. */
- if (dbp->pgsize == 0)
- dbp->pgsize = DB_DEF_IOSIZE;
-
- /*
- * If the file is a temporary file and we're doing locking,
- * then we have to create a unique file ID. We can't use our
- * normal dev/inode pair (or whatever this OS uses in place of
- * dev/inode pairs) because no backing file will be created
- * until the mpool cache is filled forcing the buffers to disk.
- * Grab a random locker ID to use as a file ID. The created
- * ID must never match a potential real file ID -- we know it
- * won't because real file IDs contain a time stamp after the
- * dev/inode pair, and we're simply storing a 4-byte value.
- *
- * !!!
- * Store the locker in the file id structure -- we can get it
- * from there as necessary, and it saves having two copies.
- */
- if (LOCKING_ON(dbenv) &&
- (ret = lock_id(dbenv, (u_int32_t *)dbp->fileid)) != 0)
- return (ret);
-
- return (0);
- }
-
- /* Get the real backing file name. */
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
- return (ret);
-
- /*
- * Open the backing file. We need to make sure that multiple processes
- * attempting to create the file at the same time are properly ordered
- * so that only one of them creates the "unique" file ID, so we open it
- * O_EXCL and O_CREAT so two simultaneous attempts to create the region
- * will return failure in one of the attempts. If we're the one that
- * fails, simply retry without the O_CREAT flag, which will require the
- * meta-data page exist.
- */
-
- /* Fill in the default file mode. */
- if (mode == 0)
- mode = __db_omode("rwrw--");
-
- oflags = 0;
- if (LF_ISSET(DB_RDONLY))
- oflags |= DB_OSO_RDONLY;
- if (LF_ISSET(DB_TRUNCATE))
- oflags |= DB_OSO_TRUNC;
-
- retry_cnt = 0;
-open_retry:
- *retflags = 0;
- ret = 0;
- if (!IS_SUBDB_SETUP && LF_ISSET(DB_CREATE)) {
- if (dbp->open_txn != NULL) {
- /*
- * Start a child transaction to wrap this individual
- * create.
- */
- if ((ret =
- txn_begin(dbenv, dbp->open_txn, &txn, 0)) != 0)
- goto err_msg;
-
- memset(&namedbt, 0, sizeof(namedbt));
- namedbt.data = (char *)name;
- namedbt.size = strlen(name) + 1;
- if ((ret = __crdel_fileopen_log(dbenv, txn,
- &lsn, DB_FLUSH, &namedbt, mode)) != 0)
- goto err_msg;
- }
- DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, name);
- if ((ret = __os_open(dbenv, real_name,
- oflags | DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp)) == 0) {
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, name);
-
- /* Commit the file create. */
- if (dbp->open_txn != NULL) {
- if ((ret = txn_commit(txn, DB_TXN_SYNC)) != 0)
- goto err_msg;
- txn = NULL;
- }
-
- /*
- * We created the file. This means that if we later
- * fail, we need to delete the file and if we're going
- * to do that, we need to trash any pages in the
- * memory pool. Since we only know here that we
- * created the file, we're going to set the flag here
- * and clear it later if we commit successfully.
- */
- F_SET(dbp, DB_AM_DISCARD);
- *retflags |= DB_FILE_SETUP_CREATE;
- } else {
- /*
- * Abort the file create. If the abort fails, report
- * the error returned by txn_abort(), rather than the
- * open error, for no particular reason.
- */
- if (dbp->open_txn != NULL) {
- if ((t_ret = txn_abort(txn)) != 0) {
- ret = t_ret;
- goto err_msg;
- }
- txn = NULL;
- }
-
- /*
- * If we were not doing an exclusive open, try again
- * without the create flag.
- */
- if (ret == EEXIST && !LF_ISSET(DB_EXCL)) {
- LF_CLR(DB_CREATE);
- DB_TEST_RECOVERY(dbp,
- DB_TEST_POSTOPEN, ret, name);
- goto open_retry;
- }
- }
- } else
- ret = __os_open(dbenv, real_name, oflags, mode, fhp);
-
- /*
- * Be quiet if we couldn't open the file because it didn't exist
- * or we did not have permission,
- * the customers don't like those messages appearing in the logs.
- * Otherwise, complain loudly.
- */
- if (ret != 0) {
- if (ret == EACCES || ret == ENOENT)
- goto err;
- goto err_msg;
- }
-
- /* Set the page size if we don't have one yet. */
- if (dbp->pgsize == 0) {
- if (IS_SUBDB_SETUP) {
- if ((ret = __db_master_open(dbp,
- name, flags, mode, &mdb)) != 0)
- goto err;
- dbp->pgsize = mdb->pgsize;
- (void)mdb->close(mdb, 0);
- } else if ((ret = __db_set_pgsize(dbp, fhp, real_name)) != 0)
- goto err;
- }
-
- /*
- * Seek to the metadata offset; if it's a master database open or a
- * database without subdatabases, we're seeking to 0, but that's OK.
- */
- if ((ret = __os_seek(dbenv, fhp,
- dbp->pgsize, meta_pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
- goto err_msg;
-
- /*
- * Read the metadata page. We read DBMETASIZE bytes, which is larger
- * than any access method's metadata page and smaller than any disk
- * sector.
- */
- if ((ret = __os_read(dbenv, fhp, mbuf, sizeof(mbuf), &nr)) != 0)
- goto err_msg;
-
- if (nr == sizeof(mbuf)) {
- /*
- * Figure out what access method we're dealing with, and then
- * call access method specific code to check error conditions
- * based on conflicts between the found file and application
- * arguments. A found file overrides some user information --
- * we don't consider it an error, for example, if the user set
- * an expected byte order and the found file doesn't match it.
- */
- F_CLR(dbp, DB_AM_SWAP);
- magic = ((DBMETA *)mbuf)->magic;
-
-swap_retry: switch (magic) {
- case DB_BTREEMAGIC:
- if ((ret =
- __bam_metachk(dbp, name, (BTMETA *)mbuf)) != 0)
- goto err;
- break;
- case DB_HASHMAGIC:
- if ((ret =
- __ham_metachk(dbp, name, (HMETA *)mbuf)) != 0)
- goto err;
- break;
- case DB_QAMMAGIC:
- if ((ret =
- __qam_metachk(dbp, name, (QMETA *)mbuf)) != 0)
- goto err;
- break;
- case 0:
- /*
- * There are two ways we can get a 0 magic number.
- * If we're creating a subdatabase, then the magic
- * number will be 0. We allocate a page as part of
- * finding out what the base page number will be for
- * the new subdatabase, but it's not initialized in
- * any way.
- *
- * The second case happens if we are in recovery
- * and we are going to recreate a database, it's
- * possible that it's page was created (on systems
- * where pages must be created explicitly to avoid
- * holes in files) but is still 0.
- */
- if (IS_SUBDB_SETUP) { /* Case 1 */
- if ((IS_RECOVERING(dbenv)
- && F_ISSET((DB_LOG *)
- dbenv->lg_handle, DBLOG_FORCE_OPEN))
- || ((DBMETA *)mbuf)->pgno != PGNO_INVALID)
- goto empty;
-
- ret = EINVAL;
- goto err;
- }
- /* Case 2 */
- if (IS_RECOVERING(dbenv)) {
- *retflags |= DB_FILE_SETUP_ZERO;
- goto empty;
- }
- goto bad_format;
- default:
- if (F_ISSET(dbp, DB_AM_SWAP))
- goto bad_format;
-
- M_32_SWAP(magic);
- F_SET(dbp, DB_AM_SWAP);
- goto swap_retry;
- }
- } else {
- /*
- * Only newly created files are permitted to fail magic
- * number tests.
- */
- if (nr != 0 || (!IS_RECOVERING(dbenv) && IS_SUBDB_SETUP))
- goto bad_format;
-
- /* Let the caller know that we had a 0-length file. */
- if (!LF_ISSET(DB_CREATE | DB_TRUNCATE))
- *retflags |= DB_FILE_SETUP_ZERO;
-
- /*
- * The only way we can reach here with the DB_CREATE flag set
- * is if we created the file. If that's not the case, then
- * either (a) someone else created the file but has not yet
- * written out the metadata page, or (b) we truncated the file
- * (DB_TRUNCATE) leaving it zero-length. In the case of (a),
- * we want to sleep and give the file creator time to write
- * the metadata page. In the case of (b), we want to continue.
- *
- * !!!
- * There's a race in the case of two processes opening the file
- * with the DB_TRUNCATE flag set at roughly the same time, and
- * they could theoretically hurt each other. Sure hope that's
- * unlikely.
- */
- if (!LF_ISSET(DB_CREATE | DB_TRUNCATE) &&
- !IS_RECOVERING(dbenv)) {
- if (retry_cnt++ < 3) {
- __os_sleep(dbenv, 1, 0);
- goto open_retry;
- }
-bad_format: if (!IS_RECOVERING(dbenv))
- __db_err(dbenv,
- "%s: unexpected file type or format", name);
- ret = EINVAL;
- goto err;
- }
-
- DB_ASSERT (dbp->type != DB_UNKNOWN);
-
-empty: /*
- * The file is empty, and that's OK. If it's not a subdatabase,
- * though, we do need to generate a unique file ID for it. The
- * unique file ID includes a timestamp so that we can't collide
- * with any other files, even when the file IDs (dev/inode pair)
- * are reused.
- */
- if (!IS_SUBDB_SETUP) {
- if (*retflags & DB_FILE_SETUP_ZERO)
- memset(dbp->fileid, 0, DB_FILE_ID_LEN);
- else if ((ret = __os_fileid(dbenv,
- real_name, 1, dbp->fileid)) != 0)
- goto err_msg;
- }
- }
-
- if (0) {
-err_msg: __db_err(dbenv, "%s: %s", name, db_strerror(ret));
- }
-
- /*
- * Abort any running transaction -- it can only exist if something
- * went wrong.
- */
-err:
-DB_TEST_RECOVERY_LABEL
-
- /*
- * If we opened a file handle and our caller is doing fcntl(2) locking,
- * then we can't close it because that would discard the caller's lock.
- * Otherwise, close the handle.
- */
- if (F_ISSET(fhp, DB_FH_VALID)) {
- if (ret == 0 && LF_ISSET(DB_FCNTL_LOCKING))
- dbp->saved_open_fhp = fhp;
- else
- if ((t_ret = __os_closehandle(fhp)) != 0 && ret == 0)
- ret = t_ret;
- }
-
- /*
- * This must be done after the file is closed, since
- * txn_abort() may remove the file, and an open file
- * cannot be removed on a Windows platforms.
- */
- if (txn != NULL)
- (void)txn_abort(txn);
-
- if (real_name != NULL)
- __os_freestr(real_name);
-
- return (ret);
-}
-
-/*
- * __db_set_pgsize --
- * Set the page size based on file information.
- */
-static int
-__db_set_pgsize(dbp, fhp, name)
- DB *dbp;
- DB_FH *fhp;
- char *name;
{
DB_ENV *dbenv;
- u_int32_t iopsize;
- int ret;
dbenv = dbp->dbenv;
- /*
- * Use the filesystem's optimum I/O size as the pagesize if a pagesize
- * not specified. Some filesystems have 64K as their optimum I/O size,
- * but as that results in fairly large default caches, we limit the
- * default pagesize to 16K.
- */
- if ((ret = __os_ioinfo(dbenv, name, fhp, NULL, NULL, &iopsize)) != 0) {
- __db_err(dbenv, "%s: %s", name, db_strerror(ret));
- return (ret);
- }
- if (iopsize < 512)
- iopsize = 512;
- if (iopsize > 16 * 1024)
- iopsize = 16 * 1024;
-
- /*
- * Sheer paranoia, but we don't want anything that's not a power-of-2
- * (we rely on that for alignment of various types on the pages), and
- * we want a multiple of the sector size as well.
- */
- OS_ROUNDOFF(iopsize, 512);
+ PANIC_CHECK(dbenv);
- dbp->pgsize = iopsize;
- F_SET(dbp, DB_AM_PGDEF);
+ /* Validate arguments, but as a DB handle destructor, we can't fail. */
+ if (flags != 0 && flags != DB_NOSYNC)
+ (void)__db_ferr(dbenv, "DB->close", 0);
- return (0);
+ return (__db_close_i(dbp, NULL, flags));
}
/*
- * __db_close --
- * DB destructor.
+ * __db_close_i --
+ * Internal DB destructor.
*
- * PUBLIC: int __db_close __P((DB *, u_int32_t));
+ * PUBLIC: int __db_close_i __P((DB *, DB_TXN *, u_int32_t));
*/
int
-__db_close(dbp, flags)
+__db_close_i(dbp, txn, flags)
DB *dbp;
+ DB_TXN *txn;
u_int32_t flags;
{
DB_ENV *dbenv;
- DBC *dbc;
int ret, t_ret;
- ret = 0;
-
dbenv = dbp->dbenv;
- PANIC_CHECK(dbenv);
-
- /* Validate arguments. */
- if ((ret = __db_closechk(dbp, flags)) != 0)
- goto err;
-
- /* If never opened, or not currently open, it's easy. */
- if (!F_ISSET(dbp, DB_OPEN_CALLED))
- goto never_opened;
-
- /* Sync the underlying access method. */
- if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
- (t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0)
- ret = t_ret;
-
- /*
- * Go through the active cursors and call the cursor recycle routine,
- * which resolves pending operations and moves the cursors onto the
- * free list. Then, walk the free list and call the cursor destroy
- * routine.
- */
- while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
- while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
- if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0)
- ret = t_ret;
+ ret = 0;
/*
- * Close any outstanding join cursors. Join cursors destroy
- * themselves on close and have no separate destroy routine.
+ * Validate arguments, but as a DB handle destructor, we can't fail.
+ *
+ * Check for consistent transaction usage -- ignore errors. Only
+ * internal callers specify transactions, so it's a serious problem
+ * if we get error messages.
*/
- while ((dbc = TAILQ_FIRST(&dbp->join_queue)) != NULL)
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
-
- /* Remove this DB handle from the DB_ENV's dblist. */
- MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
- LIST_REMOVE(dbp, dblistlinks);
- MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
-
- /* Sync the memory pool. */
- if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
- (t_ret = memp_fsync(dbp->mpf)) != 0 &&
- t_ret != DB_INCOMPLETE && ret == 0)
- ret = t_ret;
+ if (txn != NULL)
+ (void)__db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0);
- /* Close any handle we've been holding since the open. */
- if (dbp->saved_open_fhp != NULL &&
- F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
- (t_ret = __os_closehandle(dbp->saved_open_fhp)) != 0 && ret == 0)
+ /* Refresh the structure and close any local environment. */
+ if ((t_ret = __db_refresh(dbp, txn, flags)) != 0 && ret == 0)
ret = t_ret;
-never_opened:
/*
* Call the access specific close function.
*
* !!!
- * Because of where the function is called in the close process,
- * these routines can't do anything that would dirty pages or
- * otherwise affect closing down the database.
+ * Because of where these functions are called in the DB handle close
+ * process, these routines can't do anything that would dirty pages or
+ * otherwise affect closing down the database. Specifically, we can't
+ * abort and recover any of the information they control.
*/
if ((t_ret = __ham_db_close(dbp)) != 0 && ret == 0)
ret = t_ret;
@@ -1365,17 +669,14 @@ never_opened:
if ((t_ret = __qam_db_close(dbp)) != 0 && ret == 0)
ret = t_ret;
-err:
- /* Refresh the structure and close any local environment. */
- if ((t_ret = __db_refresh(dbp)) != 0 && ret == 0)
- ret = t_ret;
- if (F_ISSET(dbenv, DB_ENV_DBLOCAL) &&
- --dbenv->dblocal_ref == 0 &&
+ --dbenv->db_ref;
+ if (F_ISSET(dbenv, DB_ENV_DBLOCAL) && dbenv->db_ref == 0 &&
(t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
ret = t_ret;
+ /* Free the database handle. */
memset(dbp, CLEAR_BYTE, sizeof(*dbp));
- __os_free(dbp, sizeof(*dbp));
+ __os_free(dbenv, dbp);
return (ret);
}
@@ -1383,653 +684,257 @@ err:
/*
* __db_refresh --
* Refresh the DB structure, releasing any allocated resources.
+ * This does most of the work of closing files now because refresh
+ * is what is used during abort processing (since we can't destroy
+ * the actual handle) and during abort processing, we may have a
+ * fully opened handle.
+ *
+ * PUBLIC: int __db_refresh __P((DB *, DB_TXN *, u_int32_t));
*/
-static int
-__db_refresh(dbp)
+int
+__db_refresh(dbp, txn, flags)
DB *dbp;
+ DB_TXN *txn;
+ u_int32_t flags;
{
- DB_ENV *dbenv;
+ DB *sdbp;
DBC *dbc;
+ DB_ENV *dbenv;
+ DB_LOCKREQ lreq;
+ DB_MPOOL *dbmp;
int ret, t_ret;
ret = 0;
dbenv = dbp->dbenv;
+ /* If never opened, or not currently open, it's easy. */
+ if (!F_ISSET(dbp, DB_AM_OPEN_CALLED))
+ goto never_opened;
+
/*
- * Go through the active cursors and call the cursor recycle routine,
- * which resolves pending operations and moves the cursors onto the
- * free list. Then, walk the free list and call the cursor destroy
- * routine.
+ * If we have any secondary indices, disassociate them from us.
+ * We don't bother with the mutex here; it only protects some
+ * of the ops that will make us core-dump mid-close anyway, and
+ * if you're trying to do something with a secondary *while* you're
+ * closing the primary, you deserve what you get. The disassociation
+ * is mostly done just so we can close primaries and secondaries in
+ * any order--but within one thread of control.
*/
- while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
- while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
- if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0)
+ for (sdbp = LIST_FIRST(&dbp->s_secondaries);
+ sdbp != NULL; sdbp = LIST_NEXT(sdbp, s_links)) {
+ LIST_REMOVE(sdbp, s_links);
+ if ((t_ret = __db_disassociate(sdbp)) != 0 && ret == 0)
ret = t_ret;
-
- dbp->type = 0;
-
- /* Close the memory pool file handle. */
- if (dbp->mpf != NULL) {
- if (F_ISSET(dbp, DB_AM_DISCARD))
- (void)__memp_fremove(dbp->mpf);
- if ((t_ret = memp_fclose(dbp->mpf)) != 0 && ret == 0)
- ret = t_ret;
- dbp->mpf = NULL;
}
- /* Discard the thread mutex. */
- if (dbp->mutexp != NULL) {
- __db_mutex_free(dbenv, dbenv->reginfo, dbp->mutexp);
- dbp->mutexp = NULL;
- }
-
- /* Discard the log file id. */
- if (!IS_RECOVERING(dbenv)
- && dbp->log_fileid != DB_LOGFILEID_INVALID)
- (void)log_unregister(dbenv, dbp);
-
- F_CLR(dbp, DB_AM_DISCARD);
- F_CLR(dbp, DB_AM_INMEM);
- F_CLR(dbp, DB_AM_RDONLY);
- F_CLR(dbp, DB_AM_SWAP);
- F_CLR(dbp, DB_DBM_ERROR);
- F_CLR(dbp, DB_OPEN_CALLED);
-
- return (ret);
-}
-
-/*
- * __db_remove
- * Remove method for DB.
- *
- * PUBLIC: int __db_remove __P((DB *, const char *, const char *, u_int32_t));
- */
-int
-__db_remove(dbp, name, subdb, flags)
- DB *dbp;
- const char *name, *subdb;
- u_int32_t flags;
-{
- DBT namedbt;
- DB_ENV *dbenv;
- DB_LOCK remove_lock;
- DB_LSN newlsn;
- int ret, t_ret, (*callback_func) __P((DB *, void *));
- char *backup, *real_back, *real_name;
- void *cookie;
-
- dbenv = dbp->dbenv;
- ret = 0;
- backup = real_back = real_name = NULL;
-
- PANIC_CHECK(dbenv);
/*
- * Cannot use DB_ILLEGAL_AFTER_OPEN here because that returns
- * and we cannot return, but must deal with the error and destroy
- * the handle anyway.
+ * Sync the underlying access method. Do before closing the cursors
+ * because DB->sync allocates cursors in order to write Recno backing
+ * source text files.
*/
- if (F_ISSET(dbp, DB_OPEN_CALLED)) {
- ret = __db_mi_open(dbp->dbenv, "remove", 1);
- goto err_close;
- }
-
- /* Validate arguments. */
- if ((ret = __db_removechk(dbp, flags)) != 0)
- goto err_close;
+ if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
+ (t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0)
+ ret = t_ret;
/*
- * Subdatabases.
+ * Go through the active cursors and call the cursor recycle routine,
+ * which resolves pending operations and moves the cursors onto the
+ * free list. Then, walk the free list and call the cursor destroy
+ * routine. Note that any failure on a close is considered "really
+ * bad" and we just break out of the loop and force forward.
*/
- if (subdb != NULL) {
- /* Subdatabases must be created in named files. */
- if (name == NULL) {
- __db_err(dbenv,
- "multiple databases cannot be created in temporary files");
- goto err_close;
+ while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
+ if ((t_ret = dbc->c_close(dbc)) != 0) {
+ if (ret == 0)
+ ret = t_ret;
+ break;
}
- return (__db_subdb_remove(dbp, name, subdb));
- }
-
- if ((ret = dbp->open(dbp,
- name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0)
- goto err_close;
-
- if (LOGGING_ON(dbenv) && (ret = __log_file_lock(dbp)) != 0)
- goto err_close;
- if ((ret = dbp->sync(dbp, 0)) != 0)
- goto err_close;
-
- /* Start the transaction and log the delete. */
- if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
- goto err_close;
-
- if (LOGGING_ON(dbenv)) {
- memset(&namedbt, 0, sizeof(namedbt));
- namedbt.data = (char *)name;
- namedbt.size = strlen(name) + 1;
-
- if ((ret = __crdel_delete_log(dbenv,
- dbp->open_txn, &newlsn, DB_FLUSH,
- dbp->log_fileid, &namedbt)) != 0) {
- __db_err(dbenv,
- "%s: %s", name, db_strerror(ret));
- goto err;
+ while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
+ if ((t_ret = __db_c_destroy(dbc)) != 0) {
+ if (ret == 0)
+ ret = t_ret;
+ break;
}
- }
-
- /* Find the real name of the file. */
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
- goto err;
/*
- * XXX
- * We don't bother to open the file and call __memp_fremove on the mpf.
- * There is a potential race here. It is at least possible that, if
- * the unique filesystem ID (dev/inode pair on UNIX) is reallocated
- * within a second (the granularity of the fileID timestamp), a new
- * file open will get the same fileID as the file being "removed".
- * We may actually want to open the file and call __memp_fremove on
- * the mpf to get around this.
- */
-
- /* Create name for backup file. */
- if (TXN_ON(dbenv)) {
- if ((ret =
- __db_backup_name(dbenv, name, &backup, &newlsn)) != 0)
- goto err;
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
- goto err;
- }
-
- callback_func = __db_remove_callback;
- cookie = real_back;
- DB_TEST_RECOVERY(dbp, DB_TEST_PRERENAME, ret, name);
- if (dbp->db_am_remove != NULL &&
- (ret = dbp->db_am_remove(dbp,
- name, subdb, &newlsn, &callback_func, &cookie)) != 0)
- goto err;
- /*
- * On Windows, the underlying file must be closed to perform a remove.
- * Nothing later in __db_remove requires that it be open, and the
- * dbp->close closes it anyway, so we just close it early.
+ * Close any outstanding join cursors. Join cursors destroy
+ * themselves on close and have no separate destroy routine.
*/
- (void)__memp_fremove(dbp->mpf);
- if ((ret = memp_fclose(dbp->mpf)) != 0)
- goto err;
- dbp->mpf = NULL;
-
- if (TXN_ON(dbenv))
- ret = __os_rename(dbenv, real_name, real_back);
- else
- ret = __os_unlink(dbenv, real_name);
-
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTRENAME, ret, name);
+ while ((dbc = TAILQ_FIRST(&dbp->join_queue)) != NULL)
+ if ((t_ret = dbc->c_close(dbc)) != 0) {
+ if (ret == 0)
+ ret = t_ret;
+ break;
+ }
-err:
-DB_TEST_RECOVERY_LABEL
/*
- * End the transaction, committing the transaction if we were
- * successful, aborting otherwise.
+ * Sync the memory pool, even though we've already called DB->sync,
+ * because closing cursors can dirty pages by deleting items they
+ * referenced.
*/
- if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp, &remove_lock,
- ret == 0, callback_func, cookie)) != 0 && ret == 0)
+ if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
+ (t_ret = dbp->mpf->sync(dbp->mpf)) != 0 && ret == 0)
ret = t_ret;
- /* FALLTHROUGH */
-
-err_close:
- if (real_back != NULL)
- __os_freestr(real_back);
- if (real_name != NULL)
- __os_freestr(real_name);
- if (backup != NULL)
- __os_freestr(backup);
-
- /* We no longer have an mpool, so syncing would be disastrous. */
- if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+ /* Close any handle we've been holding since the open. */
+ if (dbp->saved_open_fhp != NULL &&
+ F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
+ (t_ret = __os_closehandle(dbenv, dbp->saved_open_fhp)) != 0 &&
+ ret == 0)
ret = t_ret;
- return (ret);
-}
-
-/*
- * __db_subdb_remove --
- * Remove a subdatabase.
- */
-static int
-__db_subdb_remove(dbp, name, subdb)
- DB *dbp;
- const char *name, *subdb;
-{
- DB *mdbp;
- DBC *dbc;
- DB_ENV *dbenv;
- DB_LOCK remove_lock;
- db_pgno_t meta_pgno;
- int ret, t_ret;
-
- mdbp = NULL;
- dbc = NULL;
- dbenv = dbp->dbenv;
-
- /* Start the transaction. */
- if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
- goto err_close;
-
+never_opened:
/*
- * Open the subdatabase. We can use the user's DB handle for this
- * purpose, I think.
+ * We are not releasing the handle lock here because we're about
+ * to release all locks held by dbp->lid below. There are two
+ * ways that we can get in here with a handle_lock, but not a
+ * dbp->lid. The first is when our lid has been hijacked by a
+ * subdb. The second is when we are a Queue database in the midst
+ * of a rename. If the queue file hasn't actually been opened, we
+ * hijack the main dbp's locker id to do the open so we can get the
+ * extent files. In both cases, we needn't free the handle lock
+ * because it will be freed when the hijacked locker-id is freed.
*/
- if ((ret = __db_open(dbp, name, subdb, DB_UNKNOWN, 0, 0)) != 0)
- goto err;
+ DB_ASSERT(!LOCK_ISSET(dbp->handle_lock) ||
+ dbp->lid != DB_LOCK_INVALIDID ||
+ dbp->type == DB_QUEUE ||
+ F_ISSET(dbp, DB_AM_SUBDB));
+
+ if (dbp->lid != DB_LOCK_INVALIDID) {
+ /* We may have pending trade operations on this dbp. */
+ if (txn != NULL)
+ __txn_remlock(dbenv, txn, &dbp->handle_lock, dbp->lid);
+
+ /* We may be holding the handle lock; release it. */
+ lreq.op = DB_LOCK_PUT_ALL;
+ if ((t_ret = __lock_vec(dbenv,
+ dbp->lid, 0, &lreq, 1, NULL)) != 0 && ret == 0)
+ ret = t_ret;
- /* Free up the pages in the subdatabase. */
- switch (dbp->type) {
- case DB_BTREE:
- case DB_RECNO:
- if ((ret = __bam_reclaim(dbp, dbp->open_txn)) != 0)
- goto err;
- break;
- case DB_HASH:
- if ((ret = __ham_reclaim(dbp, dbp->open_txn)) != 0)
- goto err;
- break;
- default:
- ret = __db_unknown_type(dbp->dbenv,
- "__db_subdb_remove", dbp->type);
- goto err;
+ if ((t_ret =
+ dbenv->lock_id_free(dbenv, dbp->lid)) != 0 && ret == 0)
+ ret = t_ret;
+ dbp->lid = DB_LOCK_INVALIDID;
+ LOCK_INIT(dbp->handle_lock);
}
- /*
- * Remove the entry from the main database and free the subdatabase
- * metadata page.
- */
- if ((ret = __db_master_open(dbp, name, 0, 0, &mdbp)) != 0)
- goto err;
-
- if ((ret = __db_master_update(mdbp,
- subdb, dbp->type, &meta_pgno, MU_REMOVE, NULL, 0)) != 0)
- goto err;
-
-err: /*
- * End the transaction, committing the transaction if we were
- * successful, aborting otherwise.
- */
- if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp,
- &remove_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
+ /* Discard the locker ID allocated as the fileid. */
+ if (F_ISSET(dbp, DB_AM_INMEM) &&
+ LOCKING_ON(dbenv) && (t_ret = dbenv->lock_id_free(
+ dbenv, *(u_int32_t *)dbp->fileid)) != 0 && ret == 0)
ret = t_ret;
-err_close:
- /*
- * Close the user's DB handle -- do this LAST to avoid smashing the
- * the transaction information.
- */
- if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
- ret = t_ret;
-
- if (mdbp != NULL && (t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
- ret = t_ret;
+ dbp->type = DB_UNKNOWN;
- return (ret);
-}
-
-/*
- * __db_rename
- * Rename method for DB.
- *
- * PUBLIC: int __db_rename __P((DB *,
- * PUBLIC: const char *, const char *, const char *, u_int32_t));
- */
-int
-__db_rename(dbp, filename, subdb, newname, flags)
- DB *dbp;
- const char *filename, *subdb, *newname;
- u_int32_t flags;
-{
- DBT namedbt, newnamedbt;
- DB_ENV *dbenv;
- DB_LOCK remove_lock;
- DB_LSN newlsn;
- char *real_name, *real_newname;
- int ret, t_ret;
-
- dbenv = dbp->dbenv;
- ret = 0;
- real_name = real_newname = NULL;
-
- PANIC_CHECK(dbenv);
- /*
- * Cannot use DB_ILLEGAL_AFTER_OPEN here because that returns
- * and we cannot return, but must deal with the error and destroy
- * the handle anyway.
- */
- if (F_ISSET(dbp, DB_OPEN_CALLED)) {
- ret = __db_mi_open(dbp->dbenv, "rename", 1);
- goto err_close;
+ /* Discard the thread mutex. */
+ if (dbp->mutexp != NULL) {
+ dbmp = dbenv->mp_handle;
+ __db_mutex_free(dbenv, dbmp->reginfo, dbp->mutexp);
+ dbp->mutexp = NULL;
}
- /* Validate arguments -- has same rules as remove. */
- if ((ret = __db_removechk(dbp, flags)) != 0)
- goto err_close;
+ /* Discard any memory used to store returned data. */
+ if (dbp->my_rskey.data != NULL)
+ __os_free(dbp->dbenv, dbp->my_rskey.data);
+ if (dbp->my_rkey.data != NULL)
+ __os_free(dbp->dbenv, dbp->my_rkey.data);
+ if (dbp->my_rdata.data != NULL)
+ __os_free(dbp->dbenv, dbp->my_rdata.data);
+
+ /* For safety's sake; we may refresh twice. */
+ memset(&dbp->my_rskey, 0, sizeof(DBT));
+ memset(&dbp->my_rkey, 0, sizeof(DBT));
+ memset(&dbp->my_rdata, 0, sizeof(DBT));
/*
- * Subdatabases.
+ * Remove this DB handle from the DB_ENV's dblist, if it's been added.
*/
- if (subdb != NULL) {
- if (filename == NULL) {
- __db_err(dbenv,
- "multiple databases cannot be created in temporary files");
- goto err_close;
- }
- return (__db_subdb_rename(dbp, filename, subdb, newname));
- }
-
- if ((ret = dbp->open(dbp,
- filename, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0)
- goto err_close;
-
- if (LOGGING_ON(dbenv) && (ret = __log_file_lock(dbp)) != 0)
- goto err_close;
-
- if ((ret = dbp->sync(dbp, 0)) != 0)
- goto err_close;
-
- /* Start the transaction and log the rename. */
- if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
- goto err_close;
-
- if (LOGGING_ON(dbenv)) {
- memset(&namedbt, 0, sizeof(namedbt));
- namedbt.data = (char *)filename;
- namedbt.size = strlen(filename) + 1;
-
- memset(&newnamedbt, 0, sizeof(namedbt));
- newnamedbt.data = (char *)newname;
- newnamedbt.size = strlen(newname) + 1;
-
- if ((ret = __crdel_rename_log(dbenv, dbp->open_txn,
- &newlsn, 0, dbp->log_fileid, &namedbt, &newnamedbt)) != 0) {
- __db_err(dbenv, "%s: %s", filename, db_strerror(ret));
- goto err;
- }
+ MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+ if (dbp->dblistlinks.le_prev != NULL)
+ LIST_REMOVE(dbp, dblistlinks);
+ MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+ dbp->dblistlinks.le_prev = NULL;
- if ((ret = __log_filelist_update(dbenv, dbp,
- dbp->log_fileid, newname, NULL)) != 0)
- goto err;
+ /* Close the memory pool file handle. */
+ if (dbp->mpf != NULL) {
+ if ((t_ret = dbp->mpf->close(dbp->mpf,
+ F_ISSET(dbp, DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0)) != 0 &&
+ ret == 0)
+ ret = t_ret;
+ dbp->mpf = NULL;
}
- /* Find the real name of the file. */
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, filename, 0, NULL, &real_name)) != 0)
- goto err;
-
- /* Find the real newname of the file. */
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, newname, 0, NULL, &real_newname)) != 0)
- goto err;
+ if (LOGGING_ON(dbp->dbenv)) {
+ /*
+ * Discard the log file id, if any. We want to log the close
+ * if and only if this is not a recovery dbp.
+ */
+ if (F_ISSET(dbp, DB_AM_RECOVER))
+ (void)__dbreg_revoke_id(dbp, 0);
+ else
+ (void)__dbreg_close_id(dbp, txn);
- /*
- * It is an error to rename a file over one that already exists,
- * as that wouldn't be transaction-safe.
- */
- if (__os_exists(real_newname, NULL) == 0) {
- ret = EEXIST;
- __db_err(dbenv, "rename: file %s exists", real_newname);
- goto err;
+ /* Discard the log FNAME. */
+ (void)__dbreg_teardown(dbp);
}
- DB_TEST_RECOVERY(dbp, DB_TEST_PRERENAME, ret, filename);
- if (dbp->db_am_rename != NULL &&
- (ret = dbp->db_am_rename(dbp, filename, subdb, newname)) != 0)
- goto err;
- /*
- * We have to flush the cache for a couple of reasons. First, the
- * underlying MPOOLFILE maintains a "name" that unrelated processes
- * can use to open the file in order to flush pages, and that name
- * is about to be wrong. Second, on Windows the unique file ID is
- * generated from the file's name, not other file information as is
- * the case on UNIX, and so a subsequent open of the old file name
- * could conceivably result in a matching "unique" file ID.
- */
- if ((ret = __memp_fremove(dbp->mpf)) != 0)
- goto err;
-
- /*
- * On Windows, the underlying file must be closed to perform a rename.
- * Nothing later in __db_rename requires that it be open, and the call
- * to dbp->close closes it anyway, so we just close it early.
- */
- if ((ret = memp_fclose(dbp->mpf)) != 0)
- goto err;
- dbp->mpf = NULL;
-
- ret = __os_rename(dbenv, real_name, real_newname);
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTRENAME, ret, newname);
-
-DB_TEST_RECOVERY_LABEL
-err: if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp,
- &remove_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
- ret = t_ret;
-
-err_close:
- /* We no longer have an mpool, so syncing would be disastrous. */
- dbp->close(dbp, DB_NOSYNC);
- if (real_name != NULL)
- __os_freestr(real_name);
- if (real_newname != NULL)
- __os_freestr(real_newname);
-
- return (ret);
-}
-
-/*
- * __db_subdb_rename --
- * Rename a subdatabase.
- */
-static int
-__db_subdb_rename(dbp, name, subdb, newname)
- DB *dbp;
- const char *name, *subdb, *newname;
-{
- DB *mdbp;
- DBC *dbc;
- DB_ENV *dbenv;
- DB_LOCK remove_lock;
- int ret, t_ret;
-
- mdbp = NULL;
- dbc = NULL;
- dbenv = dbp->dbenv;
-
- /* Start the transaction. */
- if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
- goto err_close;
-
- /*
- * Open the subdatabase. We can use the user's DB handle for this
- * purpose, I think.
- */
- if ((ret = __db_open(dbp, name, subdb, DB_UNKNOWN, 0, 0)) != 0)
- goto err;
-
- /*
- * Rename the entry in the main database.
- */
- if ((ret = __db_master_open(dbp, name, 0, 0, &mdbp)) != 0)
- goto err;
-
- if ((ret = __db_master_update(mdbp,
- subdb, dbp->type, NULL, MU_RENAME, newname, 0)) != 0)
- goto err;
-
-err: /*
- * End the transaction, committing the transaction if we were
- * successful, aborting otherwise.
- */
- if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp,
- &remove_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
- ret = t_ret;
-
-err_close:
- /*
- * Close the user's DB handle -- do this LAST to avoid smashing the
- * the transaction information.
- */
- if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
- ret = t_ret;
-
- if (mdbp != NULL && (t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
- ret = t_ret;
-
- return (ret);
-}
-
-/*
- * __db_metabegin --
- *
- * Begin a meta-data operation. This involves doing any required locking,
- * potentially beginning a transaction and then telling the caller if you
- * did or did not begin the transaction.
- *
- * The writing flag indicates if the caller is actually allowing creates
- * or doing deletes (i.e., if the caller is opening and not creating, then
- * we don't need to do any of this).
- * PUBLIC: int __db_metabegin __P((DB *, DB_LOCK *));
- */
-int
-__db_metabegin(dbp, lockp)
- DB *dbp;
- DB_LOCK *lockp;
-{
- DB_ENV *dbenv;
- DBT dbplock;
- u_int32_t locker, lockval;
- int ret;
-
- dbenv = dbp->dbenv;
-
- lockp->off = LOCK_INVALID;
+ /* Clear out fields that normally get set during open. */
+ memset(dbp->fileid, 0, sizeof(dbp->fileid));
+ dbp->adj_fileid = 0;
+ dbp->meta_pgno = 0;
+ dbp->cur_lid = DB_LOCK_INVALIDID;
+ dbp->associate_lid = DB_LOCK_INVALIDID;
+ dbp->cl_id = 0;
/*
- * There is no single place where we can know that we are or are not
- * going to be creating any files and/or subdatabases, so we will
- * always begin a tranasaction when we start creating one. If we later
- * discover that this was unnecessary, we will abort the transaction.
- * Recovery is written so that if we log a file create, but then
- * discover that we didn't have to do it, we recover correctly. The
- * file recovery design document has details.
- *
- * We need to single thread all create and delete operations, so if we
- * are running with locking, we must obtain a lock. We use lock_id to
- * generate a unique locker id and use a handcrafted DBT as the object
- * on which we are locking.
+ * If we are being refreshed with a txn specified, then we need
+ * to make sure that we clear out the lock handle field, because
+ * releasing all the locks for this transaction will release this
+ * lock and we don't want close to stumble upon this handle and
+ * try to close it.
*/
- if (LOCKING_ON(dbenv)) {
- if ((ret = lock_id(dbenv, &locker)) != 0)
- return (ret);
- lockval = 0;
- dbplock.data = &lockval;
- dbplock.size = sizeof(lockval);
- if ((ret = lock_get(dbenv,
- locker, 0, &dbplock, DB_LOCK_WRITE, lockp)) != 0)
- return (ret);
- }
-
- return (txn_begin(dbenv, NULL, &dbp->open_txn, 0));
-}
-
-/*
- * __db_metaend --
- * End a meta-data operation.
- * PUBLIC: int __db_metaend __P((DB *,
- * PUBLIC: DB_LOCK *, int, int (*)(DB *, void *), void *));
- */
-int
-__db_metaend(dbp, lockp, commit, callback, cookie)
- DB *dbp;
- DB_LOCK *lockp;
- int commit, (*callback) __P((DB *, void *));
- void *cookie;
-{
- DB_ENV *dbenv;
- int ret, t_ret;
-
- ret = 0;
- dbenv = dbp->dbenv;
-
- /* End the transaction. */
- if (commit) {
- if ((ret = txn_commit(dbp->open_txn, DB_TXN_SYNC)) == 0) {
- /*
- * Unlink any underlying file, we've committed the
- * transaction.
- */
- if (callback != NULL)
- ret = callback(dbp, cookie);
- }
- } else if ((t_ret = txn_abort(dbp->open_txn)) && ret == 0)
- ret = t_ret;
+ if (txn != NULL)
+ LOCK_INIT(dbp->handle_lock);
- /* Release our lock. */
- if (lockp->off != LOCK_INVALID &&
- (t_ret = lock_put(dbenv, lockp)) != 0 && ret == 0)
- ret = t_ret;
+ F_CLR(dbp, DB_AM_DBM_ERROR);
+ F_CLR(dbp, DB_AM_DISCARD);
+ F_CLR(dbp, DB_AM_INMEM);
+ F_CLR(dbp, DB_AM_RECOVER);
+ F_CLR(dbp, DB_AM_OPEN_CALLED);
+ F_CLR(dbp, DB_AM_RDONLY);
+ F_CLR(dbp, DB_AM_SWAP);
return (ret);
}
/*
* __db_log_page
- * Log a meta-data or root page during a create operation.
+ * Log a meta-data or root page during a subdatabase create operation.
*
- * PUBLIC: int __db_log_page __P((DB *,
- * PUBLIC: const char *, DB_LSN *, db_pgno_t, PAGE *));
+ * PUBLIC: int __db_log_page __P((DB *, DB_TXN *, DB_LSN *, db_pgno_t, PAGE *));
*/
int
-__db_log_page(dbp, name, lsn, pgno, page)
+__db_log_page(dbp, txn, lsn, pgno, page)
DB *dbp;
- const char *name;
+ DB_TXN *txn;
DB_LSN *lsn;
db_pgno_t pgno;
PAGE *page;
{
- DBT name_dbt, page_dbt;
+ DBT page_dbt;
DB_LSN new_lsn;
int ret;
- if (dbp->open_txn == NULL)
+ if (!LOGGING_ON(dbp->dbenv) || txn == NULL)
return (0);
memset(&page_dbt, 0, sizeof(page_dbt));
page_dbt.size = dbp->pgsize;
page_dbt.data = page;
- if (pgno == PGNO_BASE_MD) {
- /*
- * !!!
- * Make sure that we properly handle a null name. The old
- * Tcl sent us pathnames of the form ""; it may be the case
- * that the new Tcl doesn't do that, so we can get rid of
- * the second check here.
- */
- memset(&name_dbt, 0, sizeof(name_dbt));
- name_dbt.data = (char *)name;
- if (name == NULL || *name == '\0')
- name_dbt.size = 0;
- else
- name_dbt.size = strlen(name) + 1;
- ret = __crdel_metapage_log(dbp->dbenv,
- dbp->open_txn, &new_lsn, DB_FLUSH,
- dbp->log_fileid, &name_dbt, pgno, &page_dbt);
- } else
- ret = __crdel_metasub_log(dbp->dbenv, dbp->open_txn,
- &new_lsn, 0, dbp->log_fileid, pgno, &page_dbt, lsn);
+ ret = __crdel_metasub_log(dbp, txn, &new_lsn, 0, pgno, &page_dbt, lsn);
if (ret == 0)
page->lsn = new_lsn;
@@ -2041,50 +946,89 @@ __db_log_page(dbp, name, lsn, pgno, page)
* Create the backup file name for a given file.
*
* PUBLIC: int __db_backup_name __P((DB_ENV *,
- * PUBLIC: const char *, char **, DB_LSN *));
+ * PUBLIC: const char *, DB_TXN *, char **));
*/
#undef BACKUP_PREFIX
#define BACKUP_PREFIX "__db."
#undef MAX_LSN_TO_TEXT
-#define MAX_LSN_TO_TEXT 21
+#define MAX_LSN_TO_TEXT 17
+
int
-__db_backup_name(dbenv, name, backup, lsn)
+__db_backup_name(dbenv, name, txn, backup)
DB_ENV *dbenv;
const char *name;
+ DB_TXN *txn;
char **backup;
- DB_LSN *lsn;
{
+ DB_LSN lsn;
size_t len;
int plen, ret;
char *p, *retp;
- len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 1;
-
- if ((ret = __os_malloc(dbenv, len, NULL, &retp)) != 0)
- return (ret);
-
/*
- * Create the name. Backup file names are of the form:
+ * Create the name. Backup file names are in one of two forms:
*
- * __db.name.0x[lsn-file].0x[lsn-offset]
+ * In a transactional env: __db.LSN(8).LSN(8)
+ * and
+ * in a non-transactional env: __db.FILENAME.
*
- * which guarantees uniqueness.
+ * If the transaction doesn't have a current LSN, we write
+ * a dummy log record to force it, so that we ensure that
+ * all tmp names are unique.
*
- * However, name may contain an env-relative path in it.
- * In that case, put the __db. after the last portion of
- * the pathname.
+ * In addition, the name passed may contain an env-relative path.
+ * In that case, put the __db. in the right place (in the last
+ * component of the pathname).
*/
- if ((p = __db_rpath(name)) == NULL)
- snprintf(retp, len,
- "%s%s.0x%x0x%x", BACKUP_PREFIX, name,
- lsn->file, lsn->offset);
- else {
- plen = p - name + 1;
+ if (txn != NULL) {
+ if (IS_ZERO_LSN(txn->last_lsn)) {
+ /*
+ * Write dummy log record. The two choices for
+ * dummy log records are __db_noop_log and
+ * __db_debug_log; unfortunately __db_noop_log requires
+ * a valid dbp, and we aren't guaranteed to be able
+ * to pass one in here.
+ */
+ if ((ret = __db_debug_log(dbenv, txn, &lsn, 0,
+ NULL, 0, NULL, NULL, 0)) != 0)
+ return (ret);
+ } else
+ lsn = txn->last_lsn;
+ }
+
+ /*
+ * Part of the name may be a full path, so we need to make sure that
+ * we allocate enough space for it, even in the case where we don't
+ * use the entire filename for the backup name.
+ */
+ len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT;
+
+ if ((ret = __os_malloc(dbenv, len, &retp)) != 0)
+ return (ret);
+
+ /*
+ * There are four cases here:
+ * 1. simple path w/out transaction
+ * 2. simple path + transaction
+ * 3. multi-component path w/out transaction
+ * 4. multi-component path + transaction
+ */
+ if ((p = __db_rpath(name)) == NULL) {
+ if (txn == NULL) /* case 1 */
+ snprintf(retp, len, "%s%s.", BACKUP_PREFIX, name);
+ else /* case 2 */
+ snprintf(retp, len,
+ "%s%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset);
+ } else {
+ plen = (int)(p - name) + 1;
p++;
- snprintf(retp, len,
- "%.*s%s%s.0x%x0x%x", plen, name, BACKUP_PREFIX, p,
- lsn->file, lsn->offset);
+ if (txn == NULL) /* case 3 */
+ snprintf(retp, len,
+ "%.*s%s%s.", plen, name, BACKUP_PREFIX, p);
+ else /* case 4 */
+ snprintf(retp, len,
+ "%.*s%x.%x.", plen, name, lsn.file, lsn.offset);
}
*backup = retp;
@@ -2092,19 +1036,6 @@ __db_backup_name(dbenv, name, backup, lsn)
}
/*
- * __db_remove_callback --
- * Callback function -- on file remove commit, it unlinks the backing
- * file.
- */
-static int
-__db_remove_callback(dbp, cookie)
- DB *dbp;
- void *cookie;
-{
- return (__os_unlink(dbp->dbenv, cookie));
-}
-
-/*
* __dblist_get --
* Get the first element of dbenv->dblist with
* dbp->adj_fileid matching adjid.
@@ -2126,22 +1057,73 @@ __dblist_get(dbenv, adjid)
return (dbp);
}
-#if CONFIG_TEST
+/*
+ * __db_disassociate --
+ * Destroy the association between a given secondary and its primary.
+ */
+static int
+__db_disassociate(sdbp)
+ DB *sdbp;
+{
+ DBC *dbc;
+ int ret, t_ret;
+
+ ret = 0;
+
+ sdbp->s_callback = NULL;
+ sdbp->s_primary = NULL;
+ sdbp->get = sdbp->stored_get;
+ sdbp->close = sdbp->stored_close;
+
+ /*
+ * Complain, but proceed, if we have any active cursors. (We're in
+ * the middle of a close, so there's really no turning back.)
+ */
+ if (sdbp->s_refcnt != 1 ||
+ TAILQ_FIRST(&sdbp->active_queue) != NULL ||
+ TAILQ_FIRST(&sdbp->join_queue) != NULL) {
+ __db_err(sdbp->dbenv,
+ "Closing a primary DB while a secondary DB has active cursors is unsafe");
+ ret = EINVAL;
+ }
+ sdbp->s_refcnt = 0;
+
+ while ((dbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)
+ if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ F_CLR(sdbp, DB_AM_SECONDARY);
+ return (ret);
+}
+
+#if CONFIG_TEST
/*
* __db_testcopy
* Create a copy of all backup files and our "main" DB.
*
- * PUBLIC: int __db_testcopy __P((DB *, const char *));
+ * PUBLIC: #if CONFIG_TEST
+ * PUBLIC: int __db_testcopy __P((DB_ENV *, DB *, const char *));
+ * PUBLIC: #endif
*/
int
-__db_testcopy(dbp, name)
+__db_testcopy(dbenv, dbp, name)
+ DB_ENV *dbenv;
DB *dbp;
const char *name;
{
- if (dbp->type == DB_QUEUE)
+ DB_MPOOLFILE *mpf;
+
+ DB_ASSERT(dbp != NULL || name != NULL);
+
+ if (name == NULL) {
+ mpf = dbp->mpf;
+ name = R_ADDR(mpf->dbmp->reginfo, mpf->mfp->path_off);
+ }
+
+ if (dbp != NULL && dbp->type == DB_QUEUE)
return (__qam_testdocopy(dbp, name));
else
- return (__db_testdocopy(dbp, name));
+ return (__db_testdocopy(dbenv, name));
}
static int
@@ -2154,7 +1136,7 @@ __qam_testdocopy(dbp, name)
int ret;
filelist = NULL;
- if ((ret = __db_testdocopy(dbp, name)) != 0)
+ if ((ret = __db_testdocopy(dbp->dbenv, name)) != 0)
return (ret);
if (dbp->mpf != NULL &&
(ret = __qam_gen_filelist(dbp, &filelist)) != 0)
@@ -2164,12 +1146,13 @@ __qam_testdocopy(dbp, name)
return (0);
dir = ((QUEUE *)dbp->q_internal)->dir;
for (fp = filelist; fp->mpf != NULL; fp++) {
- snprintf(buf, sizeof(buf), QUEUE_EXTENT, dir, name, fp->id);
- if ((ret = __db_testdocopy(dbp, buf)) != 0)
+ snprintf(buf, sizeof(buf),
+ QUEUE_EXTENT, dir, PATH_SEPARATOR[0], name, fp->id);
+ if ((ret = __db_testdocopy(dbp->dbenv, buf)) != 0)
return (ret);
}
- __os_free(filelist, 0);
+ __os_free(dbp->dbenv, filelist);
return (0);
}
@@ -2179,8 +1162,8 @@ __qam_testdocopy(dbp, name)
*
*/
static int
-__db_testdocopy(dbp, name)
- DB *dbp;
+__db_testdocopy(dbenv, name)
+ DB_ENV *dbenv;
const char *name;
{
size_t len;
@@ -2188,8 +1171,8 @@ __db_testdocopy(dbp, name)
char **namesp, *backup, *copy, *dir, *p, *real_name;
real_name = NULL;
/* Get the real backing file name. */
- if ((ret = __db_appname(dbp->dbenv,
- DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
return (ret);
copy = backup = NULL;
@@ -2200,10 +1183,10 @@ __db_testdocopy(dbp, name)
*/
len = strlen(real_name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 9;
- if ((ret = __os_malloc(dbp->dbenv, len, NULL, &copy)) != 0)
+ if ((ret = __os_malloc(dbenv, len, &copy)) != 0)
goto out;
- if ((ret = __os_malloc(dbp->dbenv, len, NULL, &backup)) != 0)
+ if ((ret = __os_malloc(dbenv, len, &backup)) != 0)
goto out;
/*
@@ -2212,9 +1195,9 @@ __db_testdocopy(dbp, name)
snprintf(copy, len, "%s.afterop", real_name);
__db_makecopy(real_name, copy);
- if ((ret = __os_strdup(dbp->dbenv, real_name, &dir)) != 0)
+ if ((ret = __os_strdup(dbenv, real_name, &dir)) != 0)
goto out;
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
real_name = NULL;
/*
* Create the name. Backup file names are of the form:
@@ -2234,7 +1217,7 @@ __db_testdocopy(dbp, name)
p = __db_rpath(dir);
if (p != NULL)
*p = '\0';
- ret = __os_dirlist(dbp->dbenv, dir, &namesp, &dircnt);
+ ret = __os_dirlist(dbenv, dir, &namesp, &dircnt);
#if DIAGNOSTIC
/*
* XXX
@@ -2245,7 +1228,7 @@ __db_testdocopy(dbp, name)
*/
*p = '/';
#endif
- __os_freestr(dir);
+ __os_free(dbenv, dir);
if (ret != 0)
goto out;
for (i = 0; i < dircnt; i++) {
@@ -2258,8 +1241,8 @@ __db_testdocopy(dbp, name)
* know its LSN's.
*/
if (strncmp(namesp[i], backup, strlen(backup)) == 0) {
- if ((ret = __db_appname(dbp->dbenv, DB_APP_DATA,
- NULL, namesp[i], 0, NULL, &real_name)) != 0)
+ if ((ret = __db_appname(dbenv, DB_APP_DATA,
+ namesp[i], 0, NULL, &real_name)) != 0)
goto out;
/*
@@ -2268,25 +1251,25 @@ __db_testdocopy(dbp, name)
* If so, just move on.
*/
if (strstr(real_name, ".afterop") != NULL) {
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
real_name = NULL;
continue;
}
snprintf(copy, len, "%s.afterop", real_name);
__db_makecopy(real_name, copy);
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
real_name = NULL;
}
}
out:
if (backup != NULL)
- __os_freestr(backup);
+ __os_free(dbenv, backup);
if (copy != NULL)
- __os_freestr(copy);
+ __os_free(dbenv, copy);
if (namesp != NULL)
- __os_dirfree(namesp, dircnt);
+ __os_dirfree(dbenv, namesp, dircnt);
if (real_name != NULL)
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
return (ret);
}
@@ -2301,7 +1284,7 @@ __db_makecopy(src, dest)
memset(&rfh, 0, sizeof(rfh));
memset(&wfh, 0, sizeof(wfh));
- if (__os_malloc(NULL, 1024, NULL, &buf) != 0)
+ if (__os_malloc(NULL, 1024, &buf) != 0)
return;
if (__os_open(NULL,
@@ -2313,13 +1296,13 @@ __db_makecopy(src, dest)
for (;;)
if (__os_read(NULL, &rfh, buf, 1024, &rcnt) < 0 || rcnt == 0 ||
- __os_write(NULL, &wfh, buf, rcnt, &wcnt) < 0 || wcnt != rcnt)
+ __os_write(NULL, &wfh, buf, rcnt, &wcnt) < 0)
break;
-err: __os_free(buf, 1024);
+err: __os_free(NULL, buf);
if (F_ISSET(&rfh, DB_FH_VALID))
- __os_closehandle(&rfh);
+ __os_closehandle(NULL, &rfh);
if (F_ISSET(&wfh, DB_FH_VALID))
- __os_closehandle(&wfh);
+ __os_closehandle(NULL, &wfh);
}
#endif
diff --git a/bdb/db/db.src b/bdb/db/db.src
index b695e1360c5..414321fcbbd 100644
--- a/bdb/db/db.src
+++ b/bdb/db/db.src
@@ -1,13 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: db.src,v 11.8 2000/02/17 20:24:07 bostic Exp $
+ * $Id: db.src,v 11.18 2002/04/17 19:02:58 krinsky Exp $
*/
-PREFIX db
+PREFIX __db
+DBPRIVATE
INCLUDE #include "db_config.h"
INCLUDE
@@ -15,15 +16,17 @@ INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "txn.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
@@ -44,33 +47,16 @@ INCLUDE
*/
BEGIN addrem 41
ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
ARG indx u_int32_t lu
-ARG nbytes size_t lu
-DBT hdr DBT s
+ARG nbytes u_int32_t lu
+PGDBT hdr DBT s
DBT dbt DBT s
POINTER pagelsn DB_LSN * lu
END
/*
- * split -- Handles the split of a duplicate page.
- *
- * opcode: defines whether we are splitting from or splitting onto
- * fileid: file identifier of the file being modified.
- * pgno: page number being split.
- * pageimage: entire page contents.
- * pagelsn: former lsn of the page.
- */
-DEPRECATED split 42
-ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-DBT pageimage DBT s
-POINTER pagelsn DB_LSN * lu
-END
-
-/*
* big -- Handles addition and deletion of big key/data items.
*
* opcode: identifies get/put.
@@ -87,10 +73,10 @@ END
*/
BEGIN big 43
ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-ARG prev_pgno db_pgno_t lu
-ARG next_pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
+WRLOCKNZ prev_pgno db_pgno_t lu
+WRLOCKNZ next_pgno db_pgno_t lu
DBT dbt DBT s
POINTER pagelsn DB_LSN * lu
POINTER prevlsn DB_LSN * lu
@@ -106,8 +92,8 @@ END
* lsn: the page's original lsn.
*/
BEGIN ovref 44
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
ARG adjust int32_t ld
POINTER lsn DB_LSN * lu
END
@@ -125,33 +111,16 @@ END
*/
BEGIN relink 45
ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
-ARG prev db_pgno_t lu
+WRLOCKNZ prev db_pgno_t lu
POINTER lsn_prev DB_LSN * lu
-ARG next db_pgno_t lu
+WRLOCKNZ next db_pgno_t lu
POINTER lsn_next DB_LSN * lu
END
/*
- * Addpage -- Handles adding a new duplicate page onto the end of
- * an existing duplicate page.
- * fileid: identifies the file being changed.
- * pgno: page number to which a new page is being added.
- * lsn: lsn of pgno
- * nextpgno: new page number being added.
- * nextlsn: lsn of nextpgno;
- */
-DEPRECATED addpage 46
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-POINTER lsn DB_LSN * lu
-ARG nextpgno db_pgno_t lu
-POINTER nextlsn DB_LSN * lu
-END
-
-/*
* Debug -- log an operation upon entering an access method.
* op: Operation (cursor, c_close, c_get, c_put, c_del,
* get, put, delete).
@@ -172,7 +141,55 @@ END
* noop -- do nothing, but get an LSN.
*/
BEGIN noop 48
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER prevlsn DB_LSN * lu
END
+
+/*
+ * pg_alloc: used to record allocating a new page.
+ *
+ * meta_lsn: the meta-data page's original lsn.
+ * meta_pgno the meta-data page number.
+ * page_lsn: the allocated page's original lsn.
+ * pgno: the page allocated.
+ * ptype: the type of the page allocated.
+ * next: the next page on the free list.
+ */
+BEGIN pg_alloc 49
+DB fileid int32_t ld
+POINTER meta_lsn DB_LSN * lu
+WRLOCK meta_pgno db_pgno_t lu
+POINTER page_lsn DB_LSN * lu
+WRLOCK pgno db_pgno_t lu
+ARG ptype u_int32_t lu
+ARG next db_pgno_t lu
+END
+
+/*
+ * pg_free: used to record freeing a page.
+ *
+ * pgno: the page being freed.
+ * meta_lsn: the meta-data page's original lsn.
+ * meta_pgno: the meta-data page number.
+ * header: the header from the free'd page.
+ * next: the previous next pointer on the metadata page.
+ */
+BEGIN pg_free 50
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
+POINTER meta_lsn DB_LSN * lu
+WRLOCK meta_pgno db_pgno_t lu
+PGDBT header DBT s
+ARG next db_pgno_t lu
+END
+
+/*
+ * cksum --
+ * This log record is written when we're unable to checksum a page,
+ * before returning DB_RUNRECOVERY. This log record causes normal
+ * recovery to itself return DB_RUNRECOVERY, as only catastrophic
+ * recovery can fix things.
+ */
+BEGIN cksum 51
+END
diff --git a/bdb/db/db_am.c b/bdb/db/db_am.c
index 2d224566904..cf6ef18549b 100644
--- a/bdb/db/db_am.c
+++ b/bdb/db/db_am.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_am.c,v 11.42 2001/01/11 18:19:50 bostic Exp $";
+static const char revid[] = "$Id: db_am.c,v 11.96 2002/08/27 15:17:32 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,16 +18,22 @@ static const char revid[] = "$Id: db_am.c,v 11.42 2001/01/11 18:19:50 bostic Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
-#include "lock.h"
-#include "mp.h"
-#include "txn.h"
-#include "db_am.h"
-#include "db_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+
+static int __db_append_primary __P((DBC *, DBT *, DBT *));
+static int __db_secondary_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+static int __db_secondary_close __P((DB *, u_int32_t));
+
+#ifdef DEBUG
+static int __db_cprint_item __P((DBC *));
+#endif
/*
* __db_cursor --
@@ -53,12 +59,22 @@ __db_cursor(dbp, txn, dbcp, flags)
PANIC_CHECK(dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor");
- /* Check for invalid flags. */
- if ((ret = __db_cursorchk(dbp, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
+ /* Validate arguments. */
+ if ((ret = __db_cursorchk(dbp, flags)) != 0)
return (ret);
- if ((ret =
- __db_icursor(dbp, txn, dbp->type, PGNO_INVALID, 0, dbcp)) != 0)
+ /*
+ * Check for consistent transaction usage. For now, assume that
+ * this cursor might be used for read operations only (in which
+ * case it may not require a txn). We'll check more stringently
+ * in c_del and c_put. (Note that this all means that the
+ * read-op txn tests have to be a subset of the write-op ones.)
+ */
+ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
+ return (ret);
+
+ if ((ret = __db_icursor(dbp,
+ txn, dbp->type, PGNO_INVALID, 0, DB_LOCK_INVALIDID, dbcp)) != 0)
return (ret);
dbc = *dbcp;
@@ -70,7 +86,7 @@ __db_cursor(dbp, txn, dbcp, flags)
op = LF_ISSET(DB_OPFLAGS_MASK);
mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE :
((op == DB_WRITECURSOR) ? DB_LOCK_IWRITE : DB_LOCK_READ);
- if ((ret = lock_get(dbenv, dbc->locker, 0,
+ if ((ret = dbenv->lock_get(dbenv, dbc->locker, 0,
&dbc->lock_dbt, mode, &dbc->mylock)) != 0) {
(void)__db_c_close(dbc);
return (ret);
@@ -81,6 +97,9 @@ __db_cursor(dbp, txn, dbcp, flags)
F_SET(dbc, DBC_WRITER);
}
+ if (LF_ISSET(DB_DIRTY_READ) ||
+ (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
+ F_SET(dbc, DBC_DIRTY_READ);
return (0);
}
@@ -91,15 +110,16 @@ __db_cursor(dbp, txn, dbcp, flags)
* initialize as a cursor.
*
* PUBLIC: int __db_icursor
- * PUBLIC: __P((DB *, DB_TXN *, DBTYPE, db_pgno_t, int, DBC **));
+ * PUBLIC: __P((DB *, DB_TXN *, DBTYPE, db_pgno_t, int, u_int32_t, DBC **));
*/
int
-__db_icursor(dbp, txn, dbtype, root, is_opd, dbcp)
+__db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
DB *dbp;
DB_TXN *txn;
DBTYPE dbtype;
db_pgno_t root;
int is_opd;
+ u_int32_t lockerid;
DBC **dbcp;
{
DBC *dbc, *adbc;
@@ -120,7 +140,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, dbcp)
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbtype == dbc->dbtype) {
TAILQ_REMOVE(&dbp->free_queue, dbc, links);
- dbc->flags = 0;
+ F_CLR(dbc, ~DBC_OWN_LID);
break;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
@@ -144,11 +164,35 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, dbcp)
if (!DB_IS_THREADED(dbp) &&
(adbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
dbc->lid = adbc->lid;
- else
- if ((ret = lock_id(dbenv, &dbc->lid)) != 0)
+ else {
+ if ((ret =
+ dbenv->lock_id(dbenv, &dbc->lid)) != 0)
goto err;
+ F_SET(dbc, DBC_OWN_LID);
+ }
+
+ /*
+ * In CDB, secondary indices should share a lock file
+ * ID with the primary; otherwise we're susceptible to
+ * deadlocks. We also use __db_icursor rather
+ * than sdbp->cursor to create secondary update
+ * cursors in c_put and c_del; these won't
+ * acquire a new lock.
+ *
+ * !!!
+ * Since this is in the one-time cursor allocation
+ * code, we need to be sure to destroy, not just
+ * close, all cursors in the secondary when we
+ * associate.
+ */
+ if (CDB_LOCKING(dbp->dbenv) &&
+ F_ISSET(dbp, DB_AM_SECONDARY))
+ memcpy(dbc->lock.fileid,
+ dbp->s_primary->fileid, DB_FILE_ID_LEN);
+ else
+ memcpy(dbc->lock.fileid,
+ dbp->fileid, DB_FILE_ID_LEN);
- memcpy(dbc->lock.fileid, dbp->fileid, DB_FILE_ID_LEN);
if (CDB_LOCKING(dbenv)) {
if (F_ISSET(dbenv, DB_ENV_CDB_ALLDB)) {
/*
@@ -198,18 +242,55 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, dbcp)
/* Refresh the DBC structure. */
dbc->dbtype = dbtype;
+ RESET_RET_MEM(dbc);
- if ((dbc->txn = txn) == NULL)
- dbc->locker = dbc->lid;
- else {
+ if ((dbc->txn = txn) == NULL) {
+ /*
+ * There are certain cases in which we want to create a
+ * new cursor with a particular locker ID that is known
+ * to be the same as (and thus not conflict with) an
+ * open cursor.
+ *
+ * The most obvious case is cursor duplication; when we
+ * call DBC->c_dup or __db_c_idup, we want to use the original
+ * cursor's locker ID.
+ *
+ * Another case is when updating secondary indices. Standard
+ * CDB locking would mean that we might block ourself: we need
+ * to open an update cursor in the secondary while an update
+ * cursor in the primary is open, and when the secondary and
+ * primary are subdatabases or we're using env-wide locking,
+ * this is disastrous.
+ *
+ * In these cases, our caller will pass a nonzero locker ID
+ * into this function. Use this locker ID instead of dbc->lid
+ * as the locker ID for our new cursor.
+ */
+ if (lockerid != DB_LOCK_INVALIDID)
+ dbc->locker = lockerid;
+ else
+ dbc->locker = dbc->lid;
+ } else {
dbc->locker = txn->txnid;
txn->cursors++;
}
+ /*
+ * These fields change when we are used as a secondary index, so
+ * if the DB is a secondary, make sure they're set properly just
+ * in case we opened some cursors before we were associated.
+ *
+ * __db_c_get is used by all access methods, so this should be safe.
+ */
+ if (F_ISSET(dbp, DB_AM_SECONDARY))
+ dbc->c_get = __db_c_secondary_get;
+
if (is_opd)
F_SET(dbc, DBC_OPD);
if (F_ISSET(dbp, DB_AM_RECOVER))
F_SET(dbc, DBC_RECOVER);
+ if (F_ISSET(dbp, DB_AM_COMPENSATE))
+ F_SET(dbc, DBC_COMPENSATE);
/* Refresh the DBC internal structure. */
cp = dbc->internal;
@@ -243,14 +324,14 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, dbcp)
return (0);
err: if (allocated)
- __os_free(dbc, sizeof(*dbc));
+ __os_free(dbp->dbenv, dbc);
return (ret);
}
#ifdef DEBUG
/*
* __db_cprint --
- * Display the current cursor list.
+ * Display the cursor active and free queues.
*
* PUBLIC: int __db_cprint __P((DB *));
*/
@@ -258,60 +339,76 @@ int
__db_cprint(dbp)
DB *dbp;
{
+ DBC *dbc;
+ int ret, t_ret;
+
+ ret = 0;
+ MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
+ fprintf(stderr, "Active queue:\n");
+ for (dbc = TAILQ_FIRST(&dbp->active_queue);
+ dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
+ if ((t_ret = __db_cprint_item(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ fprintf(stderr, "Free queue:\n");
+ for (dbc = TAILQ_FIRST(&dbp->free_queue);
+ dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
+ if ((t_ret = __db_cprint_item(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+
+ return (ret);
+}
+
+static
+int __db_cprint_item(dbc)
+ DBC *dbc;
+{
static const FN fn[] = {
{ DBC_ACTIVE, "active" },
+ { DBC_COMPENSATE, "compensate" },
{ DBC_OPD, "off-page-dup" },
{ DBC_RECOVER, "recover" },
{ DBC_RMW, "read-modify-write" },
+ { DBC_TRANSIENT, "transient" },
{ DBC_WRITECURSOR, "write cursor" },
{ DBC_WRITEDUP, "internally dup'ed write cursor" },
{ DBC_WRITER, "short-term write cursor" },
{ 0, NULL }
};
- DBC *dbc;
+ DB *dbp;
DBC_INTERNAL *cp;
- char *s;
+ const char *s;
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
- for (dbc = TAILQ_FIRST(&dbp->active_queue);
- dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
- switch (dbc->dbtype) {
- case DB_BTREE:
- s = "btree";
- break;
- case DB_HASH:
- s = "hash";
- break;
- case DB_RECNO:
- s = "recno";
- break;
- case DB_QUEUE:
- s = "queue";
- break;
- default:
- DB_ASSERT(0);
- return (1);
- }
- cp = dbc->internal;
- fprintf(stderr, "%s/%#0lx: opd: %#0lx\n",
- s, P_TO_ULONG(dbc), P_TO_ULONG(cp->opd));
- fprintf(stderr, "\ttxn: %#0lx lid: %lu locker: %lu\n",
- P_TO_ULONG(dbc->txn),
- (u_long)dbc->lid, (u_long)dbc->locker);
- fprintf(stderr, "\troot: %lu page/index: %lu/%lu",
- (u_long)cp->root, (u_long)cp->pgno, (u_long)cp->indx);
- __db_prflags(dbc->flags, fn, stderr);
- fprintf(stderr, "\n");
-
- if (dbp->type == DB_BTREE)
- __bam_cprint(dbc);
+ dbp = dbc->dbp;
+ cp = dbc->internal;
+
+ s = __db_dbtype_to_string(dbc->dbtype);
+ if (strcmp(s, "UNKNOWN TYPE") == 0) {
+ DB_ASSERT(0);
+ return (1);
}
- for (dbc = TAILQ_FIRST(&dbp->free_queue);
- dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
- fprintf(stderr, "free: %#0lx ", P_TO_ULONG(dbc));
+ fprintf(stderr, "%s/%#0lx: opd: %#0lx\n",
+ s, P_TO_ULONG(dbc), P_TO_ULONG(cp->opd));
+
+ fprintf(stderr, "\ttxn: %#0lx lid: %lu locker: %lu\n",
+ P_TO_ULONG(dbc->txn), (u_long)dbc->lid, (u_long)dbc->locker);
+
+ fprintf(stderr, "\troot: %lu page/index: %lu/%lu",
+ (u_long)cp->root, (u_long)cp->pgno, (u_long)cp->indx);
+
+ __db_prflags(dbc->flags, fn, stderr);
fprintf(stderr, "\n");
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ switch (dbp->type) {
+ case DB_BTREE:
+ __bam_cprint(dbc);
+ break;
+ case DB_HASH:
+ __ham_cprint(dbc);
+ break;
+ default:
+ break;
+ }
return (0);
}
#endif /* DEBUG */
@@ -345,7 +442,7 @@ __db_fd(dbp, fdp)
return (0);
} else {
*fdp = -1;
- __db_err(dbp->dbenv, "DB does not have a valid file handle.");
+ __db_err(dbp->dbenv, "DB does not have a valid file handle");
return (ENOENT);
}
}
@@ -372,8 +469,16 @@ __db_get(dbp, txn, key, data, flags)
if ((ret = __db_getchk(dbp, key, data, flags)) != 0)
return (ret);
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
+ return (ret);
+
mode = 0;
- if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
+ if (LF_ISSET(DB_DIRTY_READ)) {
+ mode = DB_DIRTY_READ;
+ LF_CLR(DB_DIRTY_READ);
+ }
+ else if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
mode = DB_WRITELOCK;
if ((ret = dbp->cursor(dbp, txn, &dbc, mode)) != 0)
return (ret);
@@ -387,11 +492,17 @@ __db_get(dbp, txn, key, data, flags)
* going to close it right away. Thus, we can perform the get
* without duplicating the cursor, saving some cycles in this
* common case.
+ *
+ * SET_RET_MEM indicates that if key and/or data have no DBT
+ * flags set and DB manages the returned-data memory, that memory
+ * will belong to this handle, not to the underlying cursor.
*/
F_SET(dbc, DBC_TRANSIENT);
+ SET_RET_MEM(dbc, dbp);
- ret = dbc->c_get(dbc, key, data,
- flags == 0 || flags == DB_RMW ? flags | DB_SET : flags);
+ if (LF_ISSET(~(DB_RMW | DB_MULTIPLE)) == 0)
+ LF_SET(DB_SET);
+ ret = dbc->c_get(dbc, key, data, flags);
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
@@ -414,20 +525,39 @@ __db_put(dbp, txn, key, data, flags)
{
DBC *dbc;
DBT tdata;
- int ret, t_ret;
+ DB_ENV *dbenv;
+ int ret, t_ret, txn_local;
- PANIC_CHECK(dbp->dbenv);
+ dbc = NULL;
+ dbenv = dbp->dbenv;
+ txn_local = 0;
+
+ PANIC_CHECK(dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put");
+ /* Validate arguments. */
if ((ret = __db_putchk(dbp, key, data,
- flags, F_ISSET(dbp, DB_AM_RDONLY),
- F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) != 0)
+ flags, F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) != 0)
return (ret);
- DB_CHECK_TXN(dbp, txn);
+ /* Create local transaction as necessary. */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ LF_CLR(DB_AUTO_COMMIT);
+ }
+
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
+ goto err;
if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
+ goto err;
+
+ DEBUG_LWRITE(dbc, txn, "db_put", key, data, flags);
+
+ SET_RET_MEM(dbc, dbp);
/*
* See the comment in __db_get().
@@ -441,9 +571,58 @@ __db_put(dbp, txn, key, data, flags)
*/
F_SET(dbc, DBC_TRANSIENT);
- DEBUG_LWRITE(dbc, txn, "__db_put", key, data, flags);
+ switch (flags) {
+ case DB_APPEND:
+ /*
+ * If there is an append callback, the value stored in
+ * data->data may be replaced and then freed. To avoid
+ * passing a freed pointer back to the user, just operate
+ * on a copy of the data DBT.
+ */
+ tdata = *data;
- if (flags == DB_NOOVERWRITE) {
+ /*
+ * Append isn't a normal put operation; call the appropriate
+ * access method's append function.
+ */
+ switch (dbp->type) {
+ case DB_QUEUE:
+ if ((ret = __qam_append(dbc, key, &tdata)) != 0)
+ goto err;
+ break;
+ case DB_RECNO:
+ if ((ret = __ram_append(dbc, key, &tdata)) != 0)
+ goto err;
+ break;
+ default:
+ /* The interface should prevent this. */
+ DB_ASSERT(0);
+ ret = __db_ferr(dbenv, "__db_put", flags);
+ goto err;
+ }
+
+ /*
+ * Secondary indices: since we've returned zero from
+ * an append function, we've just put a record, and done
+ * so outside __db_c_put. We know we're not a secondary--
+ * the interface prevents puts on them--but we may be a
+ * primary. If so, update our secondary indices
+ * appropriately.
+ */
+ DB_ASSERT(!F_ISSET(dbp, DB_AM_SECONDARY));
+
+ if (LIST_FIRST(&dbp->s_secondaries) != NULL)
+ ret = __db_append_primary(dbc, key, &tdata);
+
+ /*
+ * The append callback, if one exists, may have allocated
+ * a new tdata.data buffer. If so, free it.
+ */
+ FREE_IF_NEEDED(dbp, &tdata);
+
+ /* No need for a cursor put; we're done. */
+ goto err;
+ case DB_NOOVERWRITE:
flags = 0;
/*
* Set DB_DBT_USERMEM, this might be a threaded application and
@@ -460,16 +639,161 @@ __db_put(dbp, txn, key, data, flags)
if ((ret = dbc->c_get(dbc, key, &tdata,
DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0))) == 0)
ret = DB_KEYEXIST;
- else if (ret == DB_NOTFOUND)
+ else if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
ret = 0;
+ break;
+ default:
+ /* Fall through to normal cursor put. */
+ break;
}
if (ret == 0)
ret = dbc->c_put(dbc,
- key, data, flags == 0 ? DB_KEYLAST : flags);
+ key, data, flags == 0 ? DB_KEYLAST : flags);
- if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+err: /* Close the cursor. */
+ if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ /* Commit for DB_AUTO_COMMIT. */
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+ }
+
+ return (ret);
+}
+
+/*
+ * __db_delete --
+ * Delete the items referenced by a key.
+ *
+ * PUBLIC: int __db_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
+ */
+int
+__db_delete(dbp, txn, key, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ DBT *key;
+ u_int32_t flags;
+{
+ DBC *dbc;
+ DBT data, lkey;
+ DB_ENV *dbenv;
+ u_int32_t f_init, f_next;
+ int ret, t_ret, txn_local;
+
+ dbc = NULL;
+ dbenv = dbp->dbenv;
+ txn_local = 0;
+
+ PANIC_CHECK(dbenv);
+ DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");
+
+ /* Check for invalid flags. */
+ if ((ret = __db_delchk(dbp, key, flags)) != 0)
+ return (ret);
+
+ /* Create local transaction as necessary. */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ LF_CLR(DB_AUTO_COMMIT);
+ }
+
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
+ goto err;
+
+ /* Allocate a cursor. */
+ if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
+ goto err;
+
+ DEBUG_LWRITE(dbc, txn, "db_delete", key, NULL, flags);
+
+ /*
+ * Walk a cursor through the key/data pairs, deleting as we go. Set
+ * the DB_DBT_USERMEM flag, as this might be a threaded application
+ * and the flags checking will catch us. We don't actually want the
+ * keys or data, so request a partial of length 0.
+ */
+ memset(&lkey, 0, sizeof(lkey));
+ F_SET(&lkey, DB_DBT_USERMEM | DB_DBT_PARTIAL);
+ memset(&data, 0, sizeof(data));
+ F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);
+
+ /*
+ * If locking (and we haven't already acquired CDB locks), set the
+ * read-modify-write flag.
+ */
+ f_init = DB_SET;
+ f_next = DB_NEXT_DUP;
+ if (STD_LOCKING(dbc)) {
+ f_init |= DB_RMW;
+ f_next |= DB_RMW;
+ }
+
+ /* Walk through the set of key/data pairs, deleting as we go. */
+ if ((ret = dbc->c_get(dbc, key, &data, f_init)) != 0)
+ goto err;
+
+ /*
+ * Hash permits an optimization in DB->del: since on-page
+ * duplicates are stored in a single HKEYDATA structure, it's
+ * possible to delete an entire set of them at once, and as
+ * the HKEYDATA has to be rebuilt and re-put each time it
+ * changes, this is much faster than deleting the duplicates
+ * one by one. Thus, if we're not pointing at an off-page
+ * duplicate set, and we're not using secondary indices (in
+ * which case we'd have to examine the items one by one anyway),
+ * let hash do this "quick delete".
+ *
+ * !!!
+ * Note that this is the only application-executed delete call in
+ * Berkeley DB that does not go through the __db_c_del function.
+ * If anything other than the delete itself (like a secondary index
+ * update) has to happen there in a particular situation, the
+ * conditions here should be modified not to call __ham_quick_delete.
+ * The ordinary AM-independent alternative will work just fine with
+ * a hash; it'll just be slower.
+ */
+ if (dbp->type == DB_HASH) {
+ if (LIST_FIRST(&dbp->s_secondaries) == NULL &&
+ !F_ISSET(dbp, DB_AM_SECONDARY) &&
+ dbc->internal->opd == NULL) {
+ ret = __ham_quick_delete(dbc);
+ goto err;
+ }
+ }
+
+ for (;;) {
+ if ((ret = dbc->c_del(dbc, 0)) != 0)
+ goto err;
+ if ((ret = dbc->c_get(dbc, &lkey, &data, f_next)) != 0) {
+ if (ret == DB_NOTFOUND) {
+ ret = 0;
+ break;
+ }
+ goto err;
+ }
+ }
+
+err: /* Discard the cursor. */
+ if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
+ /* Commit for DB_AUTO_COMMIT. */
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+ }
+
return (ret);
}
@@ -505,7 +829,443 @@ __db_sync(dbp, flags)
return (0);
/* Flush any dirty pages from the cache to the backing file. */
- if ((t_ret = memp_fsync(dbp->mpf)) != 0 && ret == 0)
+ if ((t_ret = dbp->mpf->sync(dbp->mpf)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+}
+
+/*
+ * __db_associate --
+ * Associate another database as a secondary index to this one.
+ *
+ * PUBLIC: int __db_associate __P((DB *, DB_TXN *, DB *,
+ * PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));
+ */
+int
+__db_associate(dbp, txn, sdbp, callback, flags)
+ DB *dbp, *sdbp;
+ DB_TXN *txn;
+ int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ DBC *pdbc, *sdbc;
+ DBT skey, key, data;
+ int build, ret, t_ret, txn_local;
+
+ dbenv = dbp->dbenv;
+
+ PANIC_CHECK(dbenv);
+
+ txn_local = 0;
+ pdbc = NULL;
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ memset(&skey, 0, sizeof(DBT));
+
+ if ((ret = __db_associatechk(dbp, sdbp, callback, flags)) != 0)
+ return (ret);
+
+ /*
+ * Create a local transaction as necessary, check for consistent
+ * transaction usage, and, if we have no transaction but do have
+ * locking on, acquire a locker id for the handle lock acquisition.
+ */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ } else if (txn != NULL && !TXN_ON(dbenv))
+ return (__db_not_txn_env(dbenv));
+
+ /*
+ * Check that if an open transaction is in progress, we're in it,
+ * for other common transaction errors, and for concurrent associates.
+ */
+ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
+ return (ret);
+
+ sdbp->s_callback = callback;
+ sdbp->s_primary = dbp;
+
+ sdbp->stored_get = sdbp->get;
+ sdbp->get = __db_secondary_get;
+
+ sdbp->stored_close = sdbp->close;
+ sdbp->close = __db_secondary_close;
+
+ /*
+ * Secondary cursors may have the primary's lock file ID, so we
+ * need to make sure that no older cursors are lying around
+ * when we make the transition.
+ */
+ if (TAILQ_FIRST(&sdbp->active_queue) != NULL ||
+ TAILQ_FIRST(&sdbp->join_queue) != NULL) {
+ __db_err(dbenv,
+ "Databases may not become secondary indices while cursors are open");
+ ret = EINVAL;
+ goto err;
+ }
+ while ((sdbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)
+ if ((ret = __db_c_destroy(sdbc)) != 0)
+ goto err;
+
+ F_SET(sdbp, DB_AM_SECONDARY);
+
+ /*
+ * Check to see if the secondary is empty--and thus if we should
+ * build it--before we link it in and risk making it show up in
+ * other threads.
+ */
+ build = 0;
+ if (LF_ISSET(DB_CREATE)) {
+ if ((ret = sdbp->cursor(sdbp, txn, &sdbc, 0)) != 0)
+ goto err;
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ /*
+ * We don't care about key or data; we're just doing
+ * an existence check.
+ */
+ F_SET(&key, DB_DBT_PARTIAL | DB_DBT_USERMEM);
+ F_SET(&data, DB_DBT_PARTIAL | DB_DBT_USERMEM);
+ if ((ret = sdbc->c_real_get(sdbc, &key, &data,
+ (STD_LOCKING(sdbc) ? DB_RMW : 0) |
+ DB_FIRST)) == DB_NOTFOUND) {
+ build = 1;
+ ret = 0;
+ }
+
+ /*
+ * Secondary cursors have special refcounting close
+ * methods. Be careful.
+ */
+ if ((t_ret = __db_c_close(sdbc)) != 0)
+ ret = t_ret;
+ if (ret != 0)
+ goto err;
+ }
+
+ /*
+ * Add the secondary to the list on the primary. Do it here
+ * so that we see any updates that occur while we're walking
+ * the primary.
+ */
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+
+ /* See __db_s_next for an explanation of secondary refcounting. */
+ DB_ASSERT(sdbp->s_refcnt == 0);
+ sdbp->s_refcnt = 1;
+ LIST_INSERT_HEAD(&dbp->s_secondaries, sdbp, s_links);
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+
+ if (build) {
+ /*
+ * We loop through the primary, putting each item we
+ * find into the new secondary.
+ *
+ * If we're using CDB, opening these two cursors puts us
+ * in a bit of a locking tangle: CDB locks are done on the
+ * primary, so that we stay deadlock-free, but that means
+ * that updating the secondary while we have a read cursor
+ * open on the primary will self-block. To get around this,
+ * we force the primary cursor to use the same locker ID
+ * as the secondary, so they won't conflict. This should
+ * be harmless even if we're not using CDB.
+ */
+ if ((ret = sdbp->cursor(sdbp, txn, &sdbc,
+ CDB_LOCKING(sdbp->dbenv) ? DB_WRITECURSOR : 0)) != 0)
+ goto err;
+ if ((ret = __db_icursor(dbp,
+ txn, dbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
+ goto err;
+
+ /* Lock out other threads, now that we have a locker ID. */
+ dbp->associate_lid = sdbc->locker;
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ while ((ret = pdbc->c_get(pdbc, &key, &data, DB_NEXT)) == 0) {
+ memset(&skey, 0, sizeof(DBT));
+ if ((ret = callback(sdbp, &key, &data, &skey)) != 0) {
+ if (ret == DB_DONOTINDEX)
+ continue;
+ else
+ goto err;
+ }
+ if ((ret = sdbc->c_put(sdbc,
+ &skey, &key, DB_UPDATE_SECONDARY)) != 0) {
+ FREE_IF_NEEDED(sdbp, &skey);
+ goto err;
+ }
+
+ FREE_IF_NEEDED(sdbp, &skey);
+ }
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+
+ if ((ret = sdbc->c_close(sdbc)) != 0)
+ goto err;
+ }
+
+err: if (pdbc != NULL && (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ dbp->associate_lid = DB_LOCK_INVALIDID;
+
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+ }
+
+ return (ret);
+}
+
+/*
+ * __db_pget --
+ * Return a primary key/data pair given a secondary key.
+ *
+ * PUBLIC: int __db_pget __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_pget(dbp, txn, skey, pkey, data, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ DBT *skey, *pkey, *data;
+ u_int32_t flags;
+{
+ DBC *dbc;
+ int ret, t_ret;
+
+ PANIC_CHECK(dbp->dbenv);
+ DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->pget");
+
+ if ((ret = __db_pgetchk(dbp, skey, pkey, data, flags)) != 0)
+ return (ret);
+
+ if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+ return (ret);
+ SET_RET_MEM(dbc, dbp);
+
+ /*
+ * The underlying cursor pget will fill in a default DBT for null
+ * pkeys, and use the cursor's returned-key memory internally to
+ * store any intermediate primary keys. However, we've just set
+ * the returned-key memory to the DB handle's key memory, which
+ * is unsafe to use if the DB handle is threaded. If the pkey
+ * argument is NULL, use the DBC-owned returned-key memory
+ * instead; it'll go away when we close the cursor before we
+ * return, but in this case that's just fine, as we're not
+ * returning the primary key.
+ */
+ if (pkey == NULL)
+ dbc->rkey = &dbc->my_rkey;
+
+ DEBUG_LREAD(dbc, txn, "__db_pget", skey, NULL, flags);
+
+ /*
+ * The cursor is just a perfectly ordinary secondary database
+ * cursor. Call its c_pget() method to do the dirty work.
+ */
+ if (flags == 0 || flags == DB_RMW)
+ flags |= DB_SET;
+ ret = dbc->c_pget(dbc, skey, pkey, data, flags);
+
+ if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+}
+
+/*
+ * __db_secondary_get --
+ * This wrapper function for DB->pget() is the DB->get() function
+ * on a database which has been made into a secondary index.
+ */
+static int
+__db_secondary_get(sdbp, txn, skey, data, flags)
+ DB *sdbp;
+ DB_TXN *txn;
+ DBT *skey, *data;
+ u_int32_t flags;
+{
+
+ DB_ASSERT(F_ISSET(sdbp, DB_AM_SECONDARY));
+ return (sdbp->pget(sdbp, txn, skey, NULL, data, flags));
+}
+
+/*
+ * __db_secondary_close --
+ * Wrapper function for DB->close() which we use on secondaries to
+ * manage refcounting and make sure we don't close them underneath
+ * a primary that is updating.
+ */
+static int
+__db_secondary_close(sdbp, flags)
+ DB *sdbp;
+ u_int32_t flags;
+{
+ DB *primary;
+ int doclose;
+
+ doclose = 0;
+ primary = sdbp->s_primary;
+
+ MUTEX_THREAD_LOCK(primary->dbenv, primary->mutexp);
+ /*
+ * Check the refcount--if it was at 1 when we were called, no
+ * thread is currently updating this secondary through the primary,
+ * so it's safe to close it for real.
+ *
+ * If it's not safe to do the close now, we do nothing; the
+ * database will actually be closed when the refcount is decremented,
+ * which can happen in either __db_s_next or __db_s_done.
+ */
+ DB_ASSERT(sdbp->s_refcnt != 0);
+ if (--sdbp->s_refcnt == 0) {
+ LIST_REMOVE(sdbp, s_links);
+ /* We don't want to call close while the mutex is held. */
+ doclose = 1;
+ }
+ MUTEX_THREAD_UNLOCK(primary->dbenv, primary->mutexp);
+
+ /*
+ * sdbp->close is this function; call the real one explicitly if
+ * need be.
+ */
+ return (doclose ? __db_close(sdbp, flags) : 0);
+}
+
+/*
+ * __db_append_primary --
+ * Perform the secondary index updates necessary to put(DB_APPEND)
+ * a record to a primary database.
+ */
+static int
+__db_append_primary(dbc, key, data)
+ DBC *dbc;
+ DBT *key, *data;
+{
+ DB *dbp, *sdbp;
+ DBC *sdbc, *pdbc;
+ DBT oldpkey, pkey, pdata, skey;
+ int cmp, ret, t_ret;
+
+ dbp = dbc->dbp;
+ sdbp = NULL;
+ ret = 0;
+
+ /*
+ * Worrying about partial appends seems a little like worrying
+ * about Linear A character encodings. But we support those
+ * too if your application understands them.
+ */
+ pdbc = NULL;
+ if (F_ISSET(data, DB_DBT_PARTIAL) || F_ISSET(key, DB_DBT_PARTIAL)) {
+ /*
+ * The dbc we were passed is all set to pass things
+ * back to the user; we can't safely do a call on it.
+ * Dup the cursor, grab the real data item (we don't
+ * care what the key is--we've been passed it directly),
+ * and use that instead of the data DBT we were passed.
+ *
+ * Note that we can get away with this simple get because
+ * an appended item is by definition new, and the
+ * correctly-constructed full data item from this partial
+ * put is on the page waiting for us.
+ */
+ if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITIONI)) != 0)
+ return (ret);
+ memset(&pkey, 0, sizeof(DBT));
+ memset(&pdata, 0, sizeof(DBT));
+
+ if ((ret = pdbc->c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)
+ goto err;
+
+ key = &pkey;
+ data = &pdata;
+ }
+
+ /*
+ * Loop through the secondary indices, putting a new item in
+ * each that points to the appended item.
+ *
+ * This is much like the loop in "step 3" in __db_c_put, so
+ * I'm not commenting heavily here; it was unclean to excerpt
+ * just that section into a common function, but the basic
+ * overview is the same here.
+ */
+ for (sdbp = __db_s_first(dbp);
+ sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
+ memset(&skey, 0, sizeof(DBT));
+ if ((ret = sdbp->s_callback(sdbp, key, data, &skey)) != 0) {
+ if (ret == DB_DONOTINDEX)
+ continue;
+ else
+ goto err;
+ }
+
+ if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,
+ PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) {
+ FREE_IF_NEEDED(sdbp, &skey);
+ goto err;
+ }
+ if (CDB_LOCKING(sdbp->dbenv)) {
+ DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
+ F_SET(sdbc, DBC_WRITER);
+ }
+
+ /*
+ * Since we know we have a new primary key, it can't be a
+ * duplicate duplicate in the secondary. It can be a
+ * duplicate in a secondary that doesn't support duplicates,
+ * however, so we need to be careful to avoid an overwrite
+ * (which would corrupt our index).
+ */
+ if (!F_ISSET(sdbp, DB_AM_DUP)) {
+ memset(&oldpkey, 0, sizeof(DBT));
+ F_SET(&oldpkey, DB_DBT_MALLOC);
+ ret = sdbc->c_real_get(sdbc, &skey, &oldpkey,
+ DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0));
+ if (ret == 0) {
+ cmp = __bam_defcmp(sdbp, &oldpkey, key);
+ /*
+ * XXX
+ * This needs to use the right free function
+ * as soon as this is possible.
+ */
+ __os_ufree(sdbp->dbenv,
+ oldpkey.data);
+ if (cmp != 0) {
+ __db_err(sdbp->dbenv, "%s%s",
+ "Append results in a non-unique secondary key in",
+ " an index not configured to support duplicates");
+ ret = EINVAL;
+ goto err1;
+ }
+ } else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
+ goto err1;
+ }
+
+ ret = sdbc->c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);
+
+err1: FREE_IF_NEEDED(sdbp, &skey);
+
+ if ((t_ret = sdbc->c_close(sdbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (ret != 0)
+ goto err;
+ }
+
+err: if (pdbc != NULL && (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
+ ret = t_ret;
+ if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
diff --git a/bdb/db/db_cam.c b/bdb/db/db_cam.c
index 708d4cbda4d..4de3467d4aa 100644
--- a/bdb/db/db_cam.c
+++ b/bdb/db/db_cam.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
+ * Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_cam.c,v 11.52 2001/01/18 15:11:16 bostic Exp $";
+static const char revid[] = "$Id: db_cam.c,v 11.114 2002/09/03 15:44:46 krinsky Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,17 +18,18 @@ static const char revid[] = "$Id: db_cam.c,v 11.52 2001/01/18 15:11:16 bostic Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
-#include "txn.h"
-#include "db_ext.h"
-
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
+
+static int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *));
static int __db_c_cleanup __P((DBC *, DBC *, int));
-static int __db_c_idup __P((DBC *, DBC **, u_int32_t));
+static int __db_c_del_secondary __P((DBC *));
+static int __db_c_pget_recno __P((DBC *, DBT *, DBT *, u_int32_t));
static int __db_wrlock_err __P((DB_ENV *));
#define CDB_LOCKING_INIT(dbp, dbc) \
@@ -43,9 +44,9 @@ static int __db_wrlock_err __P((DB_ENV *));
return (__db_wrlock_err(dbp->dbenv)); \
\
if (F_ISSET(dbc, DBC_WRITECURSOR) && \
- (ret = lock_get((dbp)->dbenv, (dbc)->locker, \
- DB_LOCK_UPGRADE, &(dbc)->lock_dbt, DB_LOCK_WRITE, \
- &(dbc)->mylock)) != 0) \
+ (ret = (dbp)->dbenv->lock_get((dbp)->dbenv, \
+ (dbc)->locker, DB_LOCK_UPGRADE, &(dbc)->lock_dbt, \
+ DB_LOCK_WRITE, &(dbc)->mylock)) != 0) \
return (ret); \
}
#define CDB_LOCKING_DONE(dbp, dbc) \
@@ -63,9 +64,8 @@ static int __db_wrlock_err __P((DB_ENV *));
F_ISSET((dbc_o), DBC_WRITECURSOR | DBC_WRITEDUP)) { \
memcpy(&(dbc_n)->mylock, &(dbc_o)->mylock, \
sizeof((dbc_o)->mylock)); \
- (dbc_n)->locker = (dbc_o)->locker; \
- /* This lock isn't ours to put--just discard it on close. */ \
- F_SET((dbc_n), DBC_WRITEDUP); \
+ /* This lock isn't ours to put--just discard it on close. */ \
+ F_SET((dbc_n), DBC_WRITEDUP); \
}
/*
@@ -81,12 +81,14 @@ __db_c_close(dbc)
DB *dbp;
DBC *opd;
DBC_INTERNAL *cp;
+ DB_ENV *dbenv;
int ret, t_ret;
dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
ret = 0;
- PANIC_CHECK(dbp->dbenv);
+ PANIC_CHECK(dbenv);
/*
* If the cursor is already closed we have a serious problem, and we
@@ -95,7 +97,7 @@ __db_c_close(dbc)
*/
if (!F_ISSET(dbc, DBC_ACTIVE)) {
if (dbp != NULL)
- __db_err(dbp->dbenv, "Closing closed cursor");
+ __db_err(dbenv, "Closing already-closed cursor");
DB_ASSERT(0);
return (EINVAL);
@@ -113,11 +115,9 @@ __db_c_close(dbc)
* !!!
* Cursors must be removed from the active queue before calling the
* access specific cursor close routine, btree depends on having that
- * order of operations. It must also happen before any action that
- * can fail and cause __db_c_close to return an error, or else calls
- * here from __db_close may loop indefinitely.
+ * order of operations.
*/
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
if (opd != NULL) {
F_CLR(opd, DBC_ACTIVE);
@@ -126,7 +126,7 @@ __db_c_close(dbc)
F_CLR(dbc, DBC_ACTIVE);
TAILQ_REMOVE(&dbp->active_queue, dbc, links);
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
/* Call the access specific cursor close routine. */
if ((t_ret =
@@ -137,17 +137,20 @@ __db_c_close(dbc)
* Release the lock after calling the access method specific close
* routine, a Btree cursor may have had pending deletes.
*/
- if (CDB_LOCKING(dbc->dbp->dbenv)) {
+ if (CDB_LOCKING(dbenv)) {
/*
* If DBC_WRITEDUP is set, the cursor is an internally
* duplicated write cursor and the lock isn't ours to put.
+ *
+ * Also, be sure not to free anything if mylock.off is
+ * INVALID; in some cases, such as idup'ed read cursors
+ * and secondary update cursors, a cursor in a CDB
+ * environment may not have a lock at all.
*/
- if (!F_ISSET(dbc, DBC_WRITEDUP) &&
- dbc->mylock.off != LOCK_INVALID) {
- if ((t_ret = lock_put(dbc->dbp->dbenv,
- &dbc->mylock)) != 0 && ret == 0)
+ if (!F_ISSET(dbc, DBC_WRITEDUP) && LOCK_ISSET(dbc->mylock)) {
+ if ((t_ret = dbenv->lock_put(
+ dbenv, &dbc->mylock)) != 0 && ret == 0)
ret = t_ret;
- dbc->mylock.off = LOCK_INVALID;
}
/* For safety's sake, since this is going on the free queue. */
@@ -159,7 +162,7 @@ __db_c_close(dbc)
dbc->txn->cursors--;
/* Move the cursor(s) to the free queue. */
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
if (opd != NULL) {
if (dbc->txn != NULL)
dbc->txn->cursors--;
@@ -167,7 +170,7 @@ __db_c_close(dbc)
opd = NULL;
}
TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
return (ret);
}
@@ -183,27 +186,37 @@ __db_c_destroy(dbc)
DBC *dbc;
{
DB *dbp;
- DBC_INTERNAL *cp;
- int ret;
+ DB_ENV *dbenv;
+ int ret, t_ret;
dbp = dbc->dbp;
- cp = dbc->internal;
+ dbenv = dbp->dbenv;
/* Remove the cursor from the free queue. */
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
TAILQ_REMOVE(&dbp->free_queue, dbc, links);
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
/* Free up allocated memory. */
- if (dbc->rkey.data != NULL)
- __os_free(dbc->rkey.data, dbc->rkey.ulen);
- if (dbc->rdata.data != NULL)
- __os_free(dbc->rdata.data, dbc->rdata.ulen);
+ if (dbc->my_rskey.data != NULL)
+ __os_free(dbenv, dbc->my_rskey.data);
+ if (dbc->my_rkey.data != NULL)
+ __os_free(dbenv, dbc->my_rkey.data);
+ if (dbc->my_rdata.data != NULL)
+ __os_free(dbenv, dbc->my_rdata.data);
/* Call the access specific cursor destroy routine. */
ret = dbc->c_am_destroy == NULL ? 0 : dbc->c_am_destroy(dbc);
- __os_free(dbc, sizeof(*dbc));
+ /*
+ * Release the lock id for this cursor.
+ */
+ if (LOCKING_ON(dbenv) &&
+ F_ISSET(dbc, DBC_OWN_LID) &&
+ (t_ret = dbenv->lock_id_free(dbenv, dbc->lid)) != 0 && ret == 0)
+ ret = t_ret;
+
+ __os_free(dbenv, dbc);
return (ret);
}
@@ -256,7 +269,7 @@ __db_c_count(dbc, recnop, flags)
break;
default:
return (__db_unknown_type(dbp->dbenv,
- "__db_c_count", dbp->type));
+ "__db_c_count", dbp->type));
}
return (0);
}
@@ -286,11 +299,13 @@ __db_c_del(dbc, flags)
dbp = dbc->dbp;
PANIC_CHECK(dbp->dbenv);
- DB_CHECK_TXN(dbp, dbc->txn);
/* Check for invalid flags. */
- if ((ret = __db_cdelchk(dbp, flags,
- F_ISSET(dbp, DB_AM_RDONLY), IS_INITIALIZED(dbc))) != 0)
+ if ((ret = __db_cdelchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)
+ return (ret);
+
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
return (ret);
DEBUG_LWRITE(dbc, dbc->txn, "db_c_del", NULL, NULL, flags);
@@ -298,6 +313,27 @@ __db_c_del(dbc, flags)
CDB_LOCKING_INIT(dbp, dbc);
/*
+ * If we're a secondary index, and DB_UPDATE_SECONDARY isn't set
+ * (which it only is if we're being called from a primary update),
+ * then we need to call through to the primary and delete the item.
+ *
+ * Note that this will delete the current item; we don't need to
+ * delete it ourselves as well, so we can just goto done.
+ */
+ if (flags != DB_UPDATE_SECONDARY && F_ISSET(dbp, DB_AM_SECONDARY)) {
+ ret = __db_c_del_secondary(dbc);
+ goto done;
+ }
+
+ /*
+ * If we are a primary and have secondary indices, go through
+ * and delete any secondary keys that point at the current record.
+ */
+ if (LIST_FIRST(&dbp->s_secondaries) != NULL &&
+ (ret = __db_c_del_primary(dbc)) != 0)
+ goto done;
+
+ /*
* Off-page duplicate trees are locked in the primary tree, that is,
* we acquire a write lock in the primary tree and no locks in the
* off-page dup tree. If the del operation is done in an off-page
@@ -310,7 +346,7 @@ __db_c_del(dbc, flags)
if ((ret = dbc->c_am_writelock(dbc)) == 0)
ret = opd->c_am_del(opd);
- CDB_LOCKING_DONE(dbp, dbc);
+done: CDB_LOCKING_DONE(dbp, dbc);
return (ret);
}
@@ -362,7 +398,7 @@ __db_c_dup(dbc_orig, dbcp, flags)
if (CDB_LOCKING(dbenv) && flags != DB_POSITIONI) {
DB_ASSERT(!F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR));
- if ((ret = lock_get(dbenv, dbc_n->locker, 0,
+ if ((ret = dbenv->lock_get(dbenv, dbc_n->locker, 0,
&dbc_n->lock_dbt, DB_LOCK_READ, &dbc_n->mylock)) != 0) {
(void)__db_c_close(dbc_n);
return (ret);
@@ -380,6 +416,8 @@ __db_c_dup(dbc_orig, dbcp, flags)
dbc_n->internal->opd = dbc_nopd;
}
+ /* Copy the dirty read flag to the new cursor. */
+ F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));
return (0);
err: if (dbc_n != NULL)
@@ -393,8 +431,10 @@ err: if (dbc_n != NULL)
/*
* __db_c_idup --
* Internal version of __db_c_dup.
+ *
+ * PUBLIC: int __db_c_idup __P((DBC *, DBC **, u_int32_t));
*/
-static int
+int
__db_c_idup(dbc_orig, dbcp, flags)
DBC *dbc_orig, **dbcp;
u_int32_t flags;
@@ -408,17 +448,16 @@ __db_c_idup(dbc_orig, dbcp, flags)
dbc_n = *dbcp;
if ((ret = __db_icursor(dbp, dbc_orig->txn, dbc_orig->dbtype,
- dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD), &dbc_n)) != 0)
+ dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD),
+ dbc_orig->locker, &dbc_n)) != 0)
return (ret);
- dbc_n->locker = dbc_orig->locker;
-
/* If the user wants the cursor positioned, do it here. */
if (flags == DB_POSITION || flags == DB_POSITIONI) {
int_n = dbc_n->internal;
int_orig = dbc_orig->internal;
- dbc_n->flags = dbc_orig->flags;
+ dbc_n->flags |= dbc_orig->flags & ~DBC_OWN_LID;
int_n->indx = int_orig->indx;
int_n->pgno = int_orig->pgno;
@@ -449,6 +488,9 @@ __db_c_idup(dbc_orig, dbcp, flags)
/* Now take care of duping the CDB information. */
CDB_LOCKING_COPY(dbp, dbc_orig, dbc_n);
+ /* Copy the dirty read flag to the new cursor. */
+ F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));
+
*dbcp = dbc_n;
return (0);
@@ -460,12 +502,13 @@ err: (void)dbc_n->c_close(dbc_n);
* __db_c_newopd --
* Create a new off-page duplicate cursor.
*
- * PUBLIC: int __db_c_newopd __P((DBC *, db_pgno_t, DBC **));
+ * PUBLIC: int __db_c_newopd __P((DBC *, db_pgno_t, DBC *, DBC **));
*/
int
-__db_c_newopd(dbc_parent, root, dbcp)
+__db_c_newopd(dbc_parent, root, oldopd, dbcp)
DBC *dbc_parent;
db_pgno_t root;
+ DBC *oldopd;
DBC **dbcp;
{
DB *dbp;
@@ -476,14 +519,44 @@ __db_c_newopd(dbc_parent, root, dbcp)
dbp = dbc_parent->dbp;
dbtype = (dbp->dup_compare == NULL) ? DB_RECNO : DB_BTREE;
+ /*
+ * On failure, we want to default to returning the old off-page dup
+ * cursor, if any; our caller can't be left with a dangling pointer
+ * to a freed cursor. On error the only allowable behavior is to
+ * close the cursor (and the old OPD cursor it in turn points to), so
+ * this should be safe.
+ */
+ *dbcp = oldopd;
+
if ((ret = __db_icursor(dbp,
- dbc_parent->txn, dbtype, root, 1, &opd)) != 0)
+ dbc_parent->txn, dbtype, root, 1, dbc_parent->locker, &opd)) != 0)
return (ret);
+ /* !!!
+ * If the parent is a DBC_WRITER, this won't copy anything. That's
+ * not actually a problem--we only need lock information in an
+ * off-page dup cursor in order to upgrade at cursor close time
+ * if we've done a delete, but WRITERs don't need to upgrade.
+ */
CDB_LOCKING_COPY(dbp, dbc_parent, opd);
*dbcp = opd;
+ /*
+ * Check to see if we already have an off-page dup cursor that we've
+ * passed in. If we do, close it. It'd be nice to use it again
+ * if it's a cursor belonging to the right tree, but if we're doing
+ * a cursor-relative operation this might not be safe, so for now
+ * we'll take the easy way out and always close and reopen.
+ *
+ * Note that under no circumstances do we want to close the old
+ * cursor without returning a valid new one; we don't want to
+ * leave the main cursor in our caller with a non-NULL pointer
+ * to a freed off-page dup cursor.
+ */
+ if (oldopd != NULL && (ret = oldopd->c_close(oldopd)) != 0)
+ return (ret);
+
return (0);
}
@@ -502,8 +575,9 @@ __db_c_get(dbc_arg, key, data, flags)
DB *dbp;
DBC *dbc, *dbc_n, *opd;
DBC_INTERNAL *cp, *cp_n;
+ DB_MPOOLFILE *mpf;
db_pgno_t pgno;
- u_int32_t tmp_flags, tmp_rmw;
+ u_int32_t multi, tmp_dirty, tmp_flags, tmp_rmw;
u_int8_t type;
int ret, t_ret;
@@ -517,6 +591,7 @@ __db_c_get(dbc_arg, key, data, flags)
* functions.
*/
dbp = dbc_arg->dbp;
+ mpf = dbp->mpf;
dbc_n = NULL;
opd = NULL;
@@ -531,6 +606,12 @@ __db_c_get(dbc_arg, key, data, flags)
tmp_rmw = LF_ISSET(DB_RMW);
LF_CLR(DB_RMW);
+ tmp_dirty = LF_ISSET(DB_DIRTY_READ);
+ LF_CLR(DB_DIRTY_READ);
+
+ multi = LF_ISSET(DB_MULTIPLE|DB_MULTIPLE_KEY);
+ LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
+
DEBUG_LREAD(dbc_arg, dbc_arg->txn, "db_c_get",
flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
@@ -538,8 +619,18 @@ __db_c_get(dbc_arg, key, data, flags)
* Return a cursor's record number. It has nothing to do with the
* cursor get code except that it was put into the interface.
*/
- if (flags == DB_GET_RECNO)
- return (__bam_c_rget(dbc_arg, data, flags | tmp_rmw));
+ if (flags == DB_GET_RECNO) {
+ if (tmp_rmw)
+ F_SET(dbc_arg, DBC_RMW);
+ if (tmp_dirty)
+ F_SET(dbc_arg, DBC_DIRTY_READ);
+ ret = __bam_c_rget(dbc_arg, data);
+ if (tmp_rmw)
+ F_CLR(dbc_arg, DBC_RMW);
+ if (tmp_dirty)
+ F_CLR(dbc_arg, DBC_DIRTY_READ);
+ return (ret);
+ }
if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
CDB_LOCKING_INIT(dbp, dbc_arg);
@@ -564,8 +655,8 @@ __db_c_get(dbc_arg, key, data, flags)
if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITIONI)) != 0)
return (ret);
- switch (ret = opd->c_am_get(
- opd, key, data, flags, NULL)) {
+ switch (ret =
+ opd->c_am_get(opd, key, data, flags, NULL)) {
case 0:
goto done;
case DB_NOTFOUND:
@@ -605,21 +696,49 @@ __db_c_get(dbc_arg, key, data, flags)
break;
}
+ if (tmp_dirty)
+ F_SET(dbc_arg, DBC_DIRTY_READ);
+
/*
* If this cursor is going to be closed immediately, we don't
* need to take precautions to clean it up on error.
*/
if (F_ISSET(dbc_arg, DBC_TRANSIENT))
dbc_n = dbc_arg;
- else if ((ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags)) != 0)
- goto err;
+ else {
+ ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags);
+ if (tmp_dirty)
+ F_CLR(dbc_arg, DBC_DIRTY_READ);
+
+ if (ret != 0)
+ goto err;
+ COPY_RET_MEM(dbc_arg, dbc_n);
+ }
if (tmp_rmw)
F_SET(dbc_n, DBC_RMW);
+
+ switch (multi) {
+ case DB_MULTIPLE:
+ F_SET(dbc_n, DBC_MULTIPLE);
+ break;
+ case DB_MULTIPLE_KEY:
+ F_SET(dbc_n, DBC_MULTIPLE_KEY);
+ break;
+ case DB_MULTIPLE | DB_MULTIPLE_KEY:
+ F_SET(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
+ break;
+ case 0:
+ break;
+ }
+
pgno = PGNO_INVALID;
ret = dbc_n->c_am_get(dbc_n, key, data, flags, &pgno);
if (tmp_rmw)
F_CLR(dbc_n, DBC_RMW);
+ if (tmp_dirty)
+ F_CLR(dbc_arg, DBC_DIRTY_READ);
+ F_CLR(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
if (ret != 0)
goto err;
@@ -630,7 +749,8 @@ __db_c_get(dbc_arg, key, data, flags)
* a new cursor and call the underlying function.
*/
if (pgno != PGNO_INVALID) {
- if ((ret = __db_c_newopd(dbc_arg, pgno, &cp_n->opd)) != 0)
+ if ((ret = __db_c_newopd(dbc_arg,
+ pgno, cp_n->opd, &cp_n->opd)) != 0)
goto err;
switch (flags) {
@@ -648,10 +768,9 @@ __db_c_get(dbc_arg, key, data, flags)
tmp_flags = DB_LAST;
break;
case DB_GET_BOTH:
- tmp_flags = DB_GET_BOTH;
- break;
case DB_GET_BOTHC:
- tmp_flags = DB_GET_BOTHC;
+ case DB_GET_BOTH_RANGE:
+ tmp_flags = flags;
break;
default:
ret =
@@ -680,19 +799,66 @@ done: /*
cp_n = dbc_n == NULL ? dbc_arg->internal : dbc_n->internal;
if (!F_ISSET(key, DB_DBT_ISSET)) {
if (cp_n->page == NULL && (ret =
- memp_fget(dbp->mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
+ mpf->get(mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
goto err;
if ((ret = __db_ret(dbp, cp_n->page, cp_n->indx,
- key, &dbc_arg->rkey.data, &dbc_arg->rkey.ulen)) != 0)
+ key, &dbc_arg->rkey->data, &dbc_arg->rkey->ulen)) != 0)
goto err;
}
- dbc = opd != NULL ? opd : cp_n->opd != NULL ? cp_n->opd : dbc_n;
- if (!F_ISSET(data, DB_DBT_ISSET)) {
+ if (multi != 0) {
+ /*
+ * Even if fetching from the OPD cursor we need a duplicate
+ * primary cursor if we are going after multiple keys.
+ */
+ if (dbc_n == NULL) {
+ /*
+ * Non-"_KEY" DB_MULTIPLE doesn't move the main cursor,
+ * so it's safe to just use dbc_arg, unless dbc_arg
+ * has an open OPD cursor whose state might need to
+ * be preserved.
+ */
+ if ((!(multi & DB_MULTIPLE_KEY) &&
+ dbc_arg->internal->opd == NULL) ||
+ F_ISSET(dbc_arg, DBC_TRANSIENT))
+ dbc_n = dbc_arg;
+ else {
+ if ((ret = __db_c_idup(dbc_arg,
+ &dbc_n, DB_POSITIONI)) != 0)
+ goto err;
+ if ((ret = dbc_n->c_am_get(dbc_n,
+ key, data, DB_CURRENT, &pgno)) != 0)
+ goto err;
+ }
+ cp_n = dbc_n->internal;
+ }
+
+ /*
+ * If opd is set then we dupped the opd that we came in with.
+ * When we return we may have a new opd if we went to another
+ * key.
+ */
+ if (opd != NULL) {
+ DB_ASSERT(cp_n->opd == NULL);
+ cp_n->opd = opd;
+ opd = NULL;
+ }
+
+ /*
+ * Bulk get doesn't use __db_retcopy, so data.size won't
+ * get set up unless there is an error. Assume success
+ * here. This is the only call to c_am_bulk, and it avoids
+ * setting it exactly the same everywhere. If we have an
+ * ENOMEM error, it'll get overwritten with the needed value.
+ */
+ data->size = data->ulen;
+ ret = dbc_n->c_am_bulk(dbc_n, data, flags | multi);
+ } else if (!F_ISSET(data, DB_DBT_ISSET)) {
+ dbc = opd != NULL ? opd : cp_n->opd != NULL ? cp_n->opd : dbc_n;
type = TYPE(dbc->internal->page);
ret = __db_ret(dbp, dbc->internal->page, dbc->internal->indx +
(type == P_LBTREE || type == P_HASH ? O_INDX : 0),
- data, &dbc_arg->rdata.data, &dbc_arg->rdata.ulen);
+ data, &dbc_arg->rdata->data, &dbc_arg->rdata->ulen);
}
err: /* Don't pass DB_DBT_ISSET back to application level, error or no. */
@@ -701,9 +867,8 @@ err: /* Don't pass DB_DBT_ISSET back to application level, error or no. */
/* Cleanup and cursor resolution. */
if (opd != NULL) {
- if ((t_ret =
- __db_c_cleanup(dbc_arg->internal->opd,
- opd, ret)) != 0 && ret == 0)
+ if ((t_ret = __db_c_cleanup(
+ dbc_arg->internal->opd, opd, ret)) != 0 && ret == 0)
ret = t_ret;
}
@@ -728,11 +893,12 @@ __db_c_put(dbc_arg, key, data, flags)
DBT *key, *data;
u_int32_t flags;
{
- DB *dbp;
- DBC *dbc_n, *opd;
+ DB *dbp, *sdbp;
+ DBC *dbc_n, *oldopd, *opd, *sdbc, *pdbc;
+ DBT olddata, oldpkey, oldskey, newdata, pkey, save_skey, skey, temp;
db_pgno_t pgno;
- u_int32_t tmp_flags;
- int ret, t_ret;
+ int cmp, have_oldrec, ispartial, nodel, re_pad, ret, rmw, t_ret;
+ u_int32_t re_len, size, tmp_flags;
/*
* Cursor Cleanup Note:
@@ -744,16 +910,30 @@ __db_c_put(dbc_arg, key, data, flags)
* functions.
*/
dbp = dbc_arg->dbp;
- dbc_n = NULL;
+ sdbp = NULL;
+ pdbc = dbc_n = NULL;
+ memset(&newdata, 0, sizeof(DBT));
PANIC_CHECK(dbp->dbenv);
- DB_CHECK_TXN(dbp, dbc_arg->txn);
/* Check for invalid flags. */
- if ((ret = __db_cputchk(dbp, key, data, flags,
- F_ISSET(dbp, DB_AM_RDONLY), IS_INITIALIZED(dbc_arg))) != 0)
+ if ((ret = __db_cputchk(dbp,
+ key, data, flags, IS_INITIALIZED(dbc_arg))) != 0)
+ return (ret);
+
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, dbc_arg->txn, dbc_arg->locker, 0)) != 0)
return (ret);
+ /*
+ * Putting to secondary indices is forbidden; when we need
+ * to internally update one, we'll call this with a private
+ * synonym for DB_KEYLAST, DB_UPDATE_SECONDARY, which does
+ * the right thing but won't return an error from cputchk().
+ */
+ if (flags == DB_UPDATE_SECONDARY)
+ flags = DB_KEYLAST;
+
DEBUG_LWRITE(dbc_arg, dbc_arg->txn, "db_c_put",
flags == DB_KEYFIRST || flags == DB_KEYLAST ||
flags == DB_NODUPDATA ? key : NULL, data, flags);
@@ -761,6 +941,439 @@ __db_c_put(dbc_arg, key, data, flags)
CDB_LOCKING_INIT(dbp, dbc_arg);
/*
+ * Check to see if we are a primary and have secondary indices.
+ * If we are not, we save ourselves a good bit of trouble and
+ * just skip to the "normal" put.
+ */
+ if (LIST_FIRST(&dbp->s_secondaries) == NULL)
+ goto skip_s_update;
+
+ /*
+ * We have at least one secondary which we may need to update.
+ *
+ * There is a rather vile locking issue here. Secondary gets
+ * will always involve acquiring a read lock in the secondary,
+ * then acquiring a read lock in the primary. Ideally, we
+ * would likewise perform puts by updating all the secondaries
+ * first, then doing the actual put in the primary, to avoid
+ * deadlock (since having multiple threads doing secondary
+ * gets and puts simultaneously is probably a common case).
+ *
+ * However, if this put is a put-overwrite--and we have no way to
+ * tell in advance whether it will be--we may need to delete
+ * an outdated secondary key. In order to find that old
+ * secondary key, we need to get the record we're overwriting,
+ * before we overwrite it.
+ *
+ * (XXX: It would be nice to avoid this extra get, and have the
+ * underlying put routines somehow pass us the old record
+ * since they need to traverse the tree anyway. I'm saving
+ * this optimization for later, as it's a lot of work, and it
+ * would be hard to fit into this locking paradigm anyway.)
+ *
+ * The simple thing to do would be to go get the old record before
+ * we do anything else. Unfortunately, though, doing so would
+ * violate our "secondary, then primary" lock acquisition
+ * ordering--even in the common case where no old primary record
+ * exists, we'll still acquire and keep a lock on the page where
+ * we're about to do the primary insert.
+ *
+ * To get around this, we do the following gyrations, which
+ * hopefully solve this problem in the common case:
+ *
+ * 1) If this is a c_put(DB_CURRENT), go ahead and get the
+ * old record. We already hold the lock on this page in
+ * the primary, so no harm done, and we'll need the primary
+ * key (which we weren't passed in this case) to do any
+ * secondary puts anyway.
+ *
+ * 2) If we're doing a partial put, we need to perform the
+ * get on the primary key right away, since we don't have
+ * the whole datum that the secondary key is based on.
+ * We may also need to pad out the record if the primary
+ * has a fixed record length.
+ *
+ * 3) Loop through the secondary indices, putting into each a
+ * new secondary key that corresponds to the new record.
+ *
+ * 4) If we haven't done so in (1) or (2), get the old primary
+ * key/data pair. If one does not exist--the common case--we're
+ * done with secondary indices, and can go straight on to the
+ * primary put.
+ *
+ * 5) If we do have an old primary key/data pair, however, we need
+ * to loop through all the secondaries a second time and delete
+ * the old secondary in each.
+ */
+ memset(&pkey, 0, sizeof(DBT));
+ memset(&olddata, 0, sizeof(DBT));
+ have_oldrec = nodel = 0;
+
+ /*
+ * Primary indices can't have duplicates, so only DB_CURRENT,
+ * DB_KEYFIRST, and DB_KEYLAST make any sense. Other flags
+ * should have been caught by the checking routine, but
+ * add a sprinkling of paranoia.
+ */
+ DB_ASSERT(flags == DB_CURRENT ||
+ flags == DB_KEYFIRST || flags == DB_KEYLAST);
+
+ /*
+ * We'll want to use DB_RMW in a few places, but it's only legal
+ * when locking is on.
+ */
+ rmw = STD_LOCKING(dbc_arg) ? DB_RMW : 0;
+
+ if (flags == DB_CURRENT) { /* Step 1. */
+ /*
+ * This is safe to do on the cursor we already have;
+ * error or no, it won't move.
+ *
+ * We use DB_RMW for all of these gets because we'll be
+ * writing soon enough in the "normal" put code. In
+ * transactional databases we'll hold those write locks
+ * even if we close the cursor we're reading with.
+ */
+ ret = dbc_arg->c_get(dbc_arg,
+ &pkey, &olddata, rmw | DB_CURRENT);
+ if (ret == DB_KEYEMPTY) {
+ nodel = 1; /*
+ * We know we don't need a delete
+ * in the secondary.
+ */
+ have_oldrec = 1; /* We've looked for the old record. */
+ } else if (ret != 0)
+ goto err;
+ else
+ have_oldrec = 1;
+
+ } else {
+ /* So we can just use &pkey everywhere instead of key. */
+ pkey.data = key->data;
+ pkey.size = key->size;
+ }
+
+ /*
+ * Check for partial puts (step 2).
+ */
+ if (F_ISSET(data, DB_DBT_PARTIAL)) {
+ if (!have_oldrec && !nodel) {
+ /*
+ * We're going to have to search the tree for the
+ * specified key. Dup a cursor (so we have the same
+ * locking info) and do a c_get.
+ */
+ if ((ret = __db_c_idup(dbc_arg, &pdbc, 0)) != 0)
+ goto err;
+
+ /* We should have gotten DB_CURRENT in step 1. */
+ DB_ASSERT(flags != DB_CURRENT);
+
+ ret = pdbc->c_get(pdbc,
+ &pkey, &olddata, rmw | DB_SET);
+ if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
+ nodel = 1;
+ ret = 0;
+ }
+ if ((t_ret = pdbc->c_close(pdbc)) != 0)
+ ret = t_ret;
+ if (ret != 0)
+ goto err;
+
+ have_oldrec = 1;
+ }
+
+ /*
+ * Now build the new datum from olddata and the partial
+ * data we were given.
+ */
+ if ((ret =
+ __db_buildpartial(dbp, &olddata, data, &newdata)) != 0)
+ goto err;
+ ispartial = 1;
+ } else
+ ispartial = 0;
+
+ /*
+ * Handle fixed-length records. If the primary database has
+ * fixed-length records, we need to pad out the datum before
+ * we pass it into the callback function; we always index the
+ * "real" record.
+ */
+ if ((dbp->type == DB_RECNO && F_ISSET(dbp, DB_AM_FIXEDLEN)) ||
+ (dbp->type == DB_QUEUE)) {
+ if (dbp->type == DB_QUEUE) {
+ re_len = ((QUEUE *)dbp->q_internal)->re_len;
+ re_pad = ((QUEUE *)dbp->q_internal)->re_pad;
+ } else {
+ re_len = ((BTREE *)dbp->bt_internal)->re_len;
+ re_pad = ((BTREE *)dbp->bt_internal)->re_pad;
+ }
+
+ size = ispartial ? newdata.size : data->size;
+ if (size > re_len) {
+ __db_err(dbp->dbenv,
+ "Length improper for fixed length record %lu",
+ (u_long)size);
+ ret = EINVAL;
+ goto err;
+ } else if (size < re_len) {
+ /*
+ * If we're not doing a partial put, copy
+ * data->data into newdata.data, then pad out
+ * newdata.data.
+ *
+ * If we're doing a partial put, the data
+ * we want are already in newdata.data; we
+ * just need to pad.
+ *
+ * Either way, realloc is safe.
+ */
+ if ((ret = __os_realloc(dbp->dbenv, re_len,
+ &newdata.data)) != 0)
+ goto err;
+ if (!ispartial)
+ memcpy(newdata.data, data->data, size);
+ memset((u_int8_t *)newdata.data + size, re_pad,
+ re_len - size);
+ newdata.size = re_len;
+ ispartial = 1;
+ }
+ }
+
+ /*
+ * Loop through the secondaries. (Step 3.)
+ *
+ * Note that __db_s_first and __db_s_next will take care of
+ * thread-locking and refcounting issues.
+ */
+ for (sdbp = __db_s_first(dbp);
+ sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
+ /*
+ * Call the callback for this secondary, to get the
+ * appropriate secondary key.
+ */
+ memset(&skey, 0, sizeof(DBT));
+ if ((ret = sdbp->s_callback(sdbp,
+ &pkey, ispartial ? &newdata : data, &skey)) != 0) {
+ if (ret == DB_DONOTINDEX)
+ /*
+ * The callback returned a null value--don't
+ * put this key in the secondary. Just
+ * move on to the next one--we'll handle
+ * any necessary deletes in step 5.
+ */
+ continue;
+ else
+ goto err;
+ }
+
+ /*
+ * Save the DBT we just got back from the callback function
+ * off; we want to pass its value into c_get functions
+ * that may stomp on a buffer the callback function
+ * allocated.
+ */
+ memset(&save_skey, 0, sizeof(DBT)); /* Paranoia. */
+ save_skey = skey;
+
+ /*
+ * Open a cursor in this secondary.
+ *
+ * Use the same locker ID as our primary cursor, so that
+ * we're guaranteed that the locks don't conflict (e.g. in CDB
+ * or if we're subdatabases that share and want to lock a
+ * metadata page).
+ */
+ if ((ret = __db_icursor(sdbp, dbc_arg->txn, sdbp->type,
+ PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
+ goto err;
+
+ /*
+ * If we're in CDB, updates will fail since the new cursor
+ * isn't a writer. However, we hold the WRITE lock in the
+ * primary and will for as long as our new cursor lasts,
+ * and the primary and secondary share a lock file ID,
+ * so it's safe to consider this a WRITER. The close
+ * routine won't try to put anything because we don't
+ * really have a lock.
+ */
+ if (CDB_LOCKING(sdbp->dbenv)) {
+ DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
+ F_SET(sdbc, DBC_WRITER);
+ }
+
+ /*
+ * There are three cases here--
+ * 1) The secondary supports sorted duplicates.
+ * If we attempt to put a secondary/primary pair
+ * that already exists, that's a duplicate duplicate,
+ * and c_put will return DB_KEYEXIST (see __db_duperr).
+ * This will leave us with exactly one copy of the
+ * secondary/primary pair, and this is just right--we'll
+ * avoid deleting it later, as the old and new secondaries
+ * will match (since the old secondary is the dup dup
+ * that's already there).
+ * 2) The secondary supports duplicates, but they're not
+ * sorted. We need to avoid putting a duplicate
+ * duplicate, because the matching old and new secondaries
+ * will prevent us from deleting anything and we'll
+ * wind up with two secondary records that point to the
+ * same primary key. Do a c_get(DB_GET_BOTH); if
+ * that returns 0, skip the put.
+ * 3) The secondary doesn't support duplicates at all.
+ * In this case, secondary keys must be unique; if
+ * another primary key already exists for this
+ * secondary key, we have to either overwrite it or
+ * not put this one, and in either case we've
+ * corrupted the secondary index. Do a c_get(DB_SET).
+ * If the secondary/primary pair already exists, do
+ * nothing; if the secondary exists with a different
+ * primary, return an error; and if the secondary
+ * does not exist, put it.
+ */
+ if (!F_ISSET(sdbp, DB_AM_DUP)) {
+ /* Case 3. */
+ memset(&oldpkey, 0, sizeof(DBT));
+ F_SET(&oldpkey, DB_DBT_MALLOC);
+ ret = sdbc->c_real_get(sdbc,
+ &skey, &oldpkey, rmw | DB_SET);
+ if (ret == 0) {
+ cmp = __bam_defcmp(sdbp, &oldpkey, &pkey);
+ __os_ufree(sdbp->dbenv, oldpkey.data);
+ if (cmp != 0) {
+ __db_err(sdbp->dbenv, "%s%s",
+ "Put results in a non-unique secondary key in an ",
+ "index not configured to support duplicates");
+ ret = EINVAL;
+ goto skipput;
+ }
+ } else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
+ goto skipput;
+ } else if (!F_ISSET(sdbp, DB_AM_DUPSORT))
+ /* Case 2. */
+ if ((ret = sdbc->c_real_get(sdbc,
+ &skey, &pkey, rmw | DB_GET_BOTH)) == 0)
+ goto skipput;
+
+ ret = sdbc->c_put(sdbc, &skey, &pkey, DB_UPDATE_SECONDARY);
+
+ /*
+ * We don't know yet whether this was a put-overwrite that
+ * in fact changed nothing. If it was, we may get DB_KEYEXIST.
+ * This is not an error.
+ */
+ if (ret == DB_KEYEXIST)
+ ret = 0;
+
+skipput: FREE_IF_NEEDED(sdbp, &save_skey)
+
+ if ((t_ret = sdbc->c_close(sdbc)) != 0)
+ ret = t_ret;
+
+ if (ret != 0)
+ goto err;
+ }
+ if (ret != 0)
+ goto err;
+
+ /* If still necessary, go get the old primary key/data. (Step 4.) */
+ if (!have_oldrec) {
+ /* See the comments in step 2. This is real familiar. */
+ if ((ret = __db_c_idup(dbc_arg, &pdbc, 0)) != 0)
+ goto err;
+ DB_ASSERT(flags != DB_CURRENT);
+ pkey.data = key->data;
+ pkey.size = key->size;
+ ret = pdbc->c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
+ if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
+ nodel = 1;
+ ret = 0;
+ }
+ if ((t_ret = pdbc->c_close(pdbc)) != 0)
+ ret = t_ret;
+ if (ret != 0)
+ goto err;
+ have_oldrec = 1;
+ }
+
+ /*
+ * If we don't follow this goto, we do in fact have an old record
+ * we may need to go delete. (Step 5).
+ */
+ if (nodel)
+ goto skip_s_update;
+
+ for (sdbp = __db_s_first(dbp);
+ sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
+ /*
+ * Call the callback for this secondary to get the
+ * old secondary key.
+ */
+ memset(&oldskey, 0, sizeof(DBT));
+ if ((ret = sdbp->s_callback(sdbp,
+ &pkey, &olddata, &oldskey)) != 0) {
+ if (ret == DB_DONOTINDEX)
+ /*
+ * The callback returned a null value--there's
+ * nothing to delete. Go on to the next
+ * secondary.
+ */
+ continue;
+ else
+ goto err;
+ }
+ if ((ret = sdbp->s_callback(sdbp,
+ &pkey, ispartial ? &newdata : data, &skey)) != 0 &&
+ ret != DB_DONOTINDEX)
+ goto err;
+
+ /*
+ * If there is no new secondary key, or if the old secondary
+ * key is different from the new secondary key, then
+ * we need to delete the old one.
+ *
+ * Note that bt_compare is (and must be) set no matter
+ * what access method we're in.
+ */
+ sdbc = NULL;
+ if (ret == DB_DONOTINDEX ||
+ ((BTREE *)sdbp->bt_internal)->bt_compare(sdbp,
+ &oldskey, &skey) != 0) {
+ if ((ret = __db_icursor(sdbp, dbc_arg->txn, sdbp->type,
+ PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
+ goto err;
+ if (CDB_LOCKING(sdbp->dbenv)) {
+ DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
+ F_SET(sdbc, DBC_WRITER);
+ }
+
+ /*
+ * Don't let c_get(DB_GET_BOTH) stomp on
+ * any secondary key value that the callback
+ * function may have allocated. Use a temp
+ * DBT instead.
+ */
+ memset(&temp, 0, sizeof(DBT));
+ temp.data = oldskey.data;
+ temp.size = oldskey.size;
+ if ((ret = sdbc->c_real_get(sdbc,
+ &temp, &pkey, rmw | DB_GET_BOTH)) == 0)
+ ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);
+ }
+
+ FREE_IF_NEEDED(sdbp, &skey);
+ FREE_IF_NEEDED(sdbp, &oldskey);
+ if (sdbc != NULL && (t_ret = sdbc->c_close(sdbc)) != 0)
+ ret = t_ret;
+ if (ret != 0)
+ goto err;
+ }
+
+ /* Secondary index updates are now done. On to the "real" stuff. */
+
+skip_s_update:
+ /*
* If we have an off-page duplicates cursor, and the operation applies
* to it, perform the operation. Duplicate the cursor and call the
* underlying function.
@@ -826,8 +1439,12 @@ __db_c_put(dbc_arg, key, data, flags)
* a new cursor and call the underlying function.
*/
if (pgno != PGNO_INVALID) {
- if ((ret = __db_c_newopd(dbc_arg, pgno, &opd)) != 0)
+ oldopd = dbc_n->internal->opd;
+ if ((ret = __db_c_newopd(dbc_arg, pgno, oldopd, &opd)) != 0) {
+ dbc_n->internal->opd = opd;
goto err;
+ }
+
dbc_n->internal->opd = opd;
if ((ret = opd->c_am_put(
@@ -840,8 +1457,15 @@ err: /* Cleanup and cursor resolution. */
if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
ret = t_ret;
+ /* If newdata was used, free its buffer. */
+ if (newdata.data != NULL)
+ __os_free(dbp->dbenv, newdata.data);
+
CDB_LOCKING_DONE(dbp, dbc_arg);
+ if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0)
+ return (t_ret);
+
return (ret);
}
@@ -855,7 +1479,20 @@ __db_duperr(dbp, flags)
DB *dbp;
u_int32_t flags;
{
- if (flags != DB_NODUPDATA)
+
+ /*
+ * If we run into this error while updating a secondary index,
+ * don't yell--there's no clean way to pass DB_NODUPDATA in along
+ * with DB_UPDATE_SECONDARY, but we may run into this problem
+ * in a normal, non-error course of events.
+ *
+ * !!!
+ * If and when we ever permit duplicate duplicates in sorted-dup
+ * databases, we need to either change the secondary index code
+ * to check for dup dups, or we need to maintain the implicit
+ * "DB_NODUPDATA" behavior for databases with DB_AM_SECONDARY set.
+ */
+ if (flags != DB_NODUPDATA && !F_ISSET(dbp, DB_AM_SECONDARY))
__db_err(dbp->dbenv,
"Duplicate data items are not supported with sorted data");
return (DB_KEYEXIST);
@@ -873,60 +1510,55 @@ __db_c_cleanup(dbc, dbc_n, failed)
DB *dbp;
DBC *opd;
DBC_INTERNAL *internal;
+ DB_MPOOLFILE *mpf;
int ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
internal = dbc->internal;
ret = 0;
/* Discard any pages we're holding. */
if (internal->page != NULL) {
- if ((t_ret =
- memp_fput(dbp->mpf, internal->page, 0)) != 0 && ret == 0)
+ if ((t_ret = mpf->put(mpf, internal->page, 0)) != 0 && ret == 0)
ret = t_ret;
internal->page = NULL;
}
opd = internal->opd;
if (opd != NULL && opd->internal->page != NULL) {
- if ((t_ret = memp_fput(dbp->mpf,
- opd->internal->page, 0)) != 0 && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)
ret = t_ret;
opd->internal->page = NULL;
}
/*
- * If dbc_n is NULL, there's no internal cursor swapping to be
- * done and no dbc_n to close--we probably did the entire
- * operation on an offpage duplicate cursor. Just return.
- */
- if (dbc_n == NULL)
- return (ret);
-
- /*
- * If dbc is marked DBC_TRANSIENT, we're inside a DB->{put/get}
+ * If dbc_n is NULL, there's no internal cursor swapping to be done
+ * and no dbc_n to close--we probably did the entire operation on an
+ * offpage duplicate cursor. Just return.
+ *
+ * If dbc and dbc_n are the same, we're either inside a DB->{put/get}
* operation, and as an optimization we performed the operation on
- * the main cursor rather than on a duplicated one. Assert
- * that dbc_n == dbc (i.e., that we really did skip the
- * duplication). Then just do nothing--even if there was
- * an error, we're about to close the cursor, and the fact that we
- * moved it isn't a user-visible violation of our "cursor
- * stays put on error" rule.
- */
- if (F_ISSET(dbc, DBC_TRANSIENT)) {
- DB_ASSERT(dbc == dbc_n);
+ * the main cursor rather than on a duplicated one, or we're in a
+ * bulk get that can't have moved the cursor (DB_MULTIPLE with the
+ * initial c_get operation on an off-page dup cursor). Just
+ * return--either we know we didn't move the cursor, or we're going
+ * to close it before we return to application code, so we're sure
+ * not to visibly violate the "cursor stays put on error" rule.
+ */
+ if (dbc_n == NULL || dbc == dbc_n)
return (ret);
- }
if (dbc_n->internal->page != NULL) {
- if ((t_ret = memp_fput(dbp->mpf,
- dbc_n->internal->page, 0)) != 0 && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, dbc_n->internal->page, 0)) != 0 && ret == 0)
ret = t_ret;
dbc_n->internal->page = NULL;
}
opd = dbc_n->internal->opd;
if (opd != NULL && opd->internal->page != NULL) {
- if ((t_ret = memp_fput(dbp->mpf,
- opd->internal->page, 0)) != 0 && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)
ret = t_ret;
opd->internal->page = NULL;
}
@@ -963,6 +1595,316 @@ __db_c_cleanup(dbc, dbc_n, failed)
}
/*
+ * __db_c_secondary_get --
+ * This wrapper function for DBC->c_pget() is the DBC->c_get() function
+ * for a secondary index cursor.
+ *
+ * PUBLIC: int __db_c_secondary_get __P((DBC *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_c_secondary_get(dbc, skey, data, flags)
+ DBC *dbc;
+ DBT *skey, *data;
+ u_int32_t flags;
+{
+
+ DB_ASSERT(F_ISSET(dbc->dbp, DB_AM_SECONDARY));
+ return (dbc->c_pget(dbc, skey, NULL, data, flags));
+}
+
+/*
+ * __db_c_pget --
+ * Get a primary key/data pair through a secondary index.
+ *
+ * PUBLIC: int __db_c_pget __P((DBC *, DBT *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_c_pget(dbc, skey, pkey, data, flags)
+ DBC *dbc;
+ DBT *skey, *pkey, *data;
+ u_int32_t flags;
+{
+ DB *pdbp, *sdbp;
+ DBC *pdbc;
+ DBT *save_rdata, nullpkey;
+ int pkeymalloc, ret, save_pkey_flags, t_ret;
+
+ sdbp = dbc->dbp;
+ pdbp = sdbp->s_primary;
+ pkeymalloc = t_ret = 0;
+
+ PANIC_CHECK(sdbp->dbenv);
+ if ((ret = __db_cpgetchk(sdbp,
+ skey, pkey, data, flags, IS_INITIALIZED(dbc))) != 0)
+ return (ret);
+
+ /*
+ * The challenging part of this function is getting the behavior
+ * right for all the various permutations of DBT flags. The
+ * next several blocks handle the various cases we need to
+ * deal with specially.
+ */
+
+ /*
+ * We may be called with a NULL pkey argument, if we've been
+ * wrapped by a 2-DBT get call. If so, we need to use our
+ * own DBT.
+ */
+ if (pkey == NULL) {
+ memset(&nullpkey, 0, sizeof(DBT));
+ pkey = &nullpkey;
+ }
+
+ /*
+ * DB_GET_RECNO is a special case, because we're interested not in
+ * the primary key/data pair, but rather in the primary's record
+ * number.
+ */
+ if ((flags & DB_OPFLAGS_MASK) == DB_GET_RECNO)
+ return (__db_c_pget_recno(dbc, pkey, data, flags));
+
+ /*
+ * If the DBTs we've been passed don't have any of the
+ * user-specified memory management flags set, we want to make sure
+ * we return values using the DBTs dbc->rskey, dbc->rkey, and
+ * dbc->rdata, respectively.
+ *
+ * There are two tricky aspects to this: first, we need to pass
+ * skey and pkey *in* to the initial c_get on the secondary key,
+ * since either or both may be looked at by it (depending on the
+ * get flag). Second, we must not use a normal DB->get call
+ * on the secondary, even though that's what we want to accomplish,
+ * because the DB handle may be free-threaded. Instead,
+ * we open a cursor, then take steps to ensure that we actually use
+ * the rkey/rdata from the *secondary* cursor.
+ *
+ * We accomplish all this by passing in the DBTs we started out
+ * with to the c_get, but having swapped the contents of rskey and
+ * rkey, respectively, into rkey and rdata; __db_ret will treat
+ * them like the normal key/data pair in a c_get call, and will
+ * realloc them as need be (this is "step 1"). Then, for "step 2",
+ * we swap back rskey/rkey/rdata to normal, and do a get on the primary
+ * with the secondary dbc appointed as the owner of the returned-data
+ * memory.
+ *
+ * Note that in step 2, we copy the flags field in case we need to
+ * pass down a DB_DBT_PARTIAL or other flag that is compatible with
+ * letting DB do the memory management.
+ */
+ /* Step 1. */
+ save_rdata = dbc->rdata;
+ dbc->rdata = dbc->rkey;
+ dbc->rkey = dbc->rskey;
+
+ /*
+ * It is correct, though slightly sick, to attempt a partial get
+ * of a primary key. However, if we do so here, we'll never find the
+ * primary record; clear the DB_DBT_PARTIAL field of pkey just
+ * for the duration of the next call.
+ */
+ save_pkey_flags = pkey->flags;
+ F_CLR(pkey, DB_DBT_PARTIAL);
+
+ /*
+ * Now we can go ahead with the meat of this call. First, get the
+ * primary key from the secondary index. (What exactly we get depends
+ * on the flags, but the underlying cursor get will take care of the
+ * dirty work.)
+ */
+ if ((ret = dbc->c_real_get(dbc, skey, pkey, flags)) != 0) {
+ /* Restore rskey/rkey/rdata and return. */
+ pkey->flags = save_pkey_flags;
+ dbc->rskey = dbc->rkey;
+ dbc->rkey = dbc->rdata;
+ dbc->rdata = save_rdata;
+ goto err;
+ }
+
+ /* Restore pkey's flags in case we stomped the PARTIAL flag. */
+ pkey->flags = save_pkey_flags;
+
+ /*
+ * Restore the cursor's rskey, rkey, and rdata DBTs. If DB
+ * is handling the memory management, we now have newly
+ * reallocated buffers and ulens in rkey and rdata which we want
+ * to put in rskey and rkey. save_rdata contains the old value
+ * of dbc->rdata.
+ */
+ dbc->rskey = dbc->rkey;
+ dbc->rkey = dbc->rdata;
+ dbc->rdata = save_rdata;
+
+ /*
+ * Now we're ready for "step 2". If either or both of pkey and
+ * data do not have memory management flags set--that is, if DB is
+ * managing their memory--we need to swap around the rkey/rdata
+ * structures so that we don't wind up trying to use memory managed
+ * by the primary database cursor, which we'll close before we return.
+ *
+ * !!!
+ * If you're carefully following the bouncing ball, you'll note
+ * that in the DB-managed case, the buffer hanging off of pkey is
+ * the same as dbc->rkey->data. This is just fine; we may well
+ * realloc and stomp on it when we return, if we're going a
+ * DB_GET_BOTH and need to return a different partial or key
+ * (depending on the comparison function), but this is safe.
+ *
+ * !!!
+ * We need to use __db_icursor here rather than simply calling
+ * pdbp->cursor, because otherwise, if we're in CDB, we'll
+ * allocate a new locker ID and leave ourselves open to deadlocks.
+ * (Even though we're only acquiring read locks, we'll still block
+ * if there are any waiters.)
+ */
+ if ((ret = __db_icursor(pdbp,
+ dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
+ goto err;
+
+ /*
+ * We're about to use pkey a second time. If DB_DBT_MALLOC
+ * is set on it, we'll leak the memory we allocated the first time.
+ * Thus, set DB_DBT_REALLOC instead so that we reuse that memory
+ * instead of leaking it.
+ *
+ * !!!
+ * This assumes that the user must always specify a compatible
+ * realloc function if a malloc function is specified. I think
+ * this is a reasonable requirement.
+ */
+ if (F_ISSET(pkey, DB_DBT_MALLOC)) {
+ F_CLR(pkey, DB_DBT_MALLOC);
+ F_SET(pkey, DB_DBT_REALLOC);
+ pkeymalloc = 1;
+ }
+
+ /*
+ * Do the actual get. Set DBC_TRANSIENT since we don't care
+ * about preserving the position on error, and it's faster.
+ * SET_RET_MEM so that the secondary DBC owns any returned-data
+ * memory.
+ */
+ F_SET(pdbc, DBC_TRANSIENT);
+ SET_RET_MEM(pdbc, dbc);
+ ret = pdbc->c_get(pdbc, pkey, data, DB_SET);
+
+ /*
+ * If the item wasn't found in the primary, this is a bug;
+ * our secondary has somehow gotten corrupted, and contains
+ * elements that don't correspond to anything in the primary.
+ * Complain.
+ */
+ if (ret == DB_NOTFOUND)
+ ret = __db_secondary_corrupt(pdbp);
+
+ /* Now close the primary cursor. */
+ t_ret = pdbc->c_close(pdbc);
+
+err: if (pkeymalloc) {
+ /*
+ * If pkey had a MALLOC flag, we need to restore it;
+ * otherwise, if the user frees the buffer but reuses
+ * the DBT without NULL'ing its data field or changing
+ * the flags, we may drop core.
+ */
+ F_CLR(pkey, DB_DBT_REALLOC);
+ F_SET(pkey, DB_DBT_MALLOC);
+ }
+ return (t_ret == 0 ? ret : t_ret);
+}
+
+/*
+ * __db_c_pget_recno --
+ * Perform a DB_GET_RECNO c_pget on a secondary index. Returns
+ * the secondary's record number in the pkey field and the primary's
+ * in the data field.
+ */
+static int
+__db_c_pget_recno(sdbc, pkey, data, flags)
+ DBC *sdbc;
+ DBT *pkey, *data;
+ u_int32_t flags;
+{
+ DB *pdbp, *sdbp;
+ DB_ENV *dbenv;
+ DBC *pdbc;
+ DBT discardme, primary_key;
+ db_recno_t oob;
+ u_int32_t rmw;
+ int ret, t_ret;
+
+ sdbp = sdbc->dbp;
+ pdbp = sdbp->s_primary;
+ dbenv = sdbp->dbenv;
+ pdbc = NULL;
+ ret = t_ret = 0;
+
+ rmw = LF_ISSET(DB_RMW);
+
+ memset(&discardme, 0, sizeof(DBT));
+ F_SET(&discardme, DB_DBT_USERMEM | DB_DBT_PARTIAL);
+
+ oob = RECNO_OOB;
+
+ /*
+ * If the primary is an rbtree, we want its record number, whether
+ * or not the secondary is one too. Fetch the recno into "data".
+ *
+ * If it's not an rbtree, return RECNO_OOB in "data".
+ */
+ if (F_ISSET(pdbp, DB_AM_RECNUM)) {
+ /*
+ * Get the primary key, so we can find the record number
+ * in the primary. (We're uninterested in the secondary key.)
+ */
+ memset(&primary_key, 0, sizeof(DBT));
+ F_SET(&primary_key, DB_DBT_MALLOC);
+ if ((ret = sdbc->c_real_get(sdbc,
+ &discardme, &primary_key, rmw | DB_CURRENT)) != 0)
+ return (ret);
+
+ /*
+ * Open a cursor on the primary, set it to the right record,
+ * and fetch its recno into "data".
+ *
+ * (See __db_c_pget for a comment on the use of __db_icursor.)
+ *
+ * SET_RET_MEM so that the secondary DBC owns any returned-data
+ * memory.
+ */
+ if ((ret = __db_icursor(pdbp, sdbc->txn,
+ pdbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
+ goto perr;
+ SET_RET_MEM(pdbc, sdbc);
+ if ((ret = pdbc->c_get(pdbc,
+ &primary_key, &discardme, rmw | DB_SET)) != 0)
+ goto perr;
+
+ ret = pdbc->c_get(pdbc, &discardme, data, rmw | DB_GET_RECNO);
+
+perr: __os_ufree(sdbp->dbenv, primary_key.data);
+ if (pdbc != NULL &&
+ (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
+ ret = t_ret;
+ if (ret != 0)
+ return (ret);
+ } else if ((ret = __db_retcopy(dbenv, data, &oob,
+ sizeof(oob), &sdbc->rkey->data, &sdbc->rkey->ulen)) != 0)
+ return (ret);
+
+ /*
+ * If the secondary is an rbtree, we want its record number, whether
+ * or not the primary is one too. Fetch the recno into "pkey".
+ *
+ * If it's not an rbtree, return RECNO_OOB in "pkey".
+ */
+ if (F_ISSET(sdbp, DB_AM_RECNUM))
+ return (sdbc->c_real_get(sdbc, &discardme, pkey, flags));
+ else
+ return (__db_retcopy(dbenv, pkey, &oob,
+ sizeof(oob), &sdbc->rdata->data, &sdbc->rdata->ulen));
+}
+
+/*
* __db_wrlock_err -- do not have a write lock.
*/
static int
@@ -972,3 +1914,373 @@ __db_wrlock_err(dbenv)
__db_err(dbenv, "Write attempted on read-only cursor");
return (EPERM);
}
+
+/*
+ * __db_c_del_secondary --
+ * Perform a delete operation on a secondary index: call through
+ * to the primary and delete the primary record that this record
+ * points to.
+ *
+ * Note that deleting the primary record will call c_del on all
+ * the secondaries, including this one; thus, it is not necessary
+ * to execute both this function and an actual delete.
+ *
+ */
+static int
+__db_c_del_secondary(dbc)
+ DBC *dbc;
+{
+ DB *pdbp;
+ DBC *pdbc;
+ DBT skey, pkey;
+ int ret, t_ret;
+
+ memset(&skey, 0, sizeof(DBT));
+ memset(&pkey, 0, sizeof(DBT));
+
+ /*
+ * Get the current item that we're pointing at.
+ * We don't actually care about the secondary key, just
+ * the primary.
+ */
+ F_SET(&skey, DB_DBT_PARTIAL | DB_DBT_USERMEM);
+ if ((ret = dbc->c_real_get(dbc,
+ &skey, &pkey, DB_CURRENT)) != 0)
+ return (ret);
+
+ /*
+ * Create a cursor on the primary with our locker ID,
+ * so that when it calls back, we don't conflict.
+ *
+ * We create a cursor explicitly because there's no
+ * way to specify the same locker ID if we're using
+ * locking but not transactions if we use the DB->del
+ * interface. This shouldn't be any less efficient
+ * anyway.
+ */
+ pdbp = dbc->dbp->s_primary;
+ if ((ret = __db_icursor(pdbp, dbc->txn,
+ pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
+ return (ret);
+
+ /*
+ * See comment in __db_c_put--if we're in CDB,
+ * we already hold the locks we need, and we need to flag
+ * the cursor as a WRITER so we don't run into errors
+ * when we try to delete.
+ */
+ if (CDB_LOCKING(pdbp->dbenv)) {
+ DB_ASSERT(pdbc->mylock.off == LOCK_INVALID);
+ F_SET(pdbc, DBC_WRITER);
+ }
+
+ /*
+ * Set the new cursor to the correct primary key. Then
+ * delete it. We don't really care about the datum;
+ * just reuse our skey DBT.
+ *
+ * If the primary get returns DB_NOTFOUND, something is amiss--
+ * every record in the secondary should correspond to some record
+ * in the primary.
+ */
+ if ((ret = pdbc->c_get(pdbc, &pkey, &skey,
+ (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_SET)) == 0)
+ ret = pdbc->c_del(pdbc, 0);
+ else if (ret == DB_NOTFOUND)
+ ret = __db_secondary_corrupt(pdbp);
+
+ if ((t_ret = pdbc->c_close(pdbc)) != 0 && ret != 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __db_c_del_primary --
+ * Perform a delete operation on a primary index. Loop through
+ * all the secondary indices which correspond to this primary
+ * database, and delete any secondary keys that point at the current
+ * record.
+ *
+ * PUBLIC: int __db_c_del_primary __P((DBC *));
+ */
+int
+__db_c_del_primary(dbc)
+ DBC *dbc;
+{
+ DB *dbp, *sdbp;
+ DBC *sdbc;
+ DBT data, pkey, skey, temp;
+ int ret, t_ret;
+
+ dbp = dbc->dbp;
+
+ /*
+ * If we're called at all, we have at least one secondary.
+ * (Unfortunately, we can't assert this without grabbing the mutex.)
+ * Get the current record so that we can construct appropriate
+ * secondary keys as needed.
+ */
+ memset(&pkey, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ if ((ret = dbc->c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)
+ return (ret);
+
+ for (sdbp = __db_s_first(dbp);
+ sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
+ /*
+ * Get the secondary key for this secondary and the current
+ * item.
+ */
+ memset(&skey, 0, sizeof(DBT));
+ if ((ret = sdbp->s_callback(sdbp, &pkey, &data, &skey)) != 0) {
+ /*
+ * If the current item isn't in this index, we
+ * have no work to do. Proceed.
+ */
+ if (ret == DB_DONOTINDEX)
+ continue;
+
+ /* We had a substantive error. Bail. */
+ FREE_IF_NEEDED(sdbp, &skey);
+ goto done;
+ }
+
+ /* Open a secondary cursor. */
+ if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,
+ PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0)
+ goto done;
+ /* See comment above and in __db_c_put. */
+ if (CDB_LOCKING(sdbp->dbenv)) {
+ DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
+ F_SET(sdbc, DBC_WRITER);
+ }
+
+ /*
+ * Set the secondary cursor to the appropriate item.
+ * Delete it.
+ *
+ * We want to use DB_RMW if locking is on; it's only
+ * legal then, though.
+ *
+ * !!!
+ * Don't stomp on any callback-allocated buffer in skey
+ * when we do a c_get(DB_GET_BOTH); use a temp DBT instead.
+ */
+ memset(&temp, 0, sizeof(DBT));
+ temp.data = skey.data;
+ temp.size = skey.size;
+ if ((ret = sdbc->c_real_get(sdbc, &temp, &pkey,
+ (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_GET_BOTH)) == 0)
+ ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);
+
+ FREE_IF_NEEDED(sdbp, &skey);
+
+ if ((t_ret = sdbc->c_close(sdbc)) != 0 || ret != 0) {
+ if (ret == 0)
+ ret = t_ret;
+ goto done;
+ }
+ }
+
+done: if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
+ return (t_ret);
+ return (ret);
+}
+
+/*
+ * __db_s_first --
+ * Get the first secondary, if any are present, from the primary.
+ *
+ * PUBLIC: DB *__db_s_first __P((DB *));
+ */
+DB *
+__db_s_first(pdbp)
+ DB *pdbp;
+{
+ DB *sdbp;
+
+ MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
+ sdbp = LIST_FIRST(&pdbp->s_secondaries);
+
+ /* See __db_s_next. */
+ if (sdbp != NULL)
+ sdbp->s_refcnt++;
+ MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
+
+ return (sdbp);
+}
+
+/*
+ * __db_s_next --
+ * Get the next secondary in the list.
+ *
+ * PUBLIC: int __db_s_next __P((DB **));
+ */
+int
+__db_s_next(sdbpp)
+ DB **sdbpp;
+{
+ DB *sdbp, *pdbp, *closeme;
+ int ret;
+
+ /*
+ * Secondary indices are kept in a linked list, s_secondaries,
+ * off each primary DB handle. If a primary is free-threaded,
+ * this list may only be traversed or modified while the primary's
+ * thread mutex is held.
+ *
+ * The tricky part is that we don't want to hold the thread mutex
+ * across the full set of secondary puts necessary for each primary
+ * put, or we'll wind up essentially single-threading all the puts
+ * to the handle; the secondary puts will each take about as
+ * long as the primary does, and may require I/O. So we instead
+ * hold the thread mutex only long enough to follow one link to the
+ * next secondary, and then we release it before performing the
+ * actual secondary put.
+ *
+ * The only danger here is that we might legitimately close a
+ * secondary index in one thread while another thread is performing
+ * a put and trying to update that same secondary index. To
+ * prevent this from happening, we refcount the secondary handles.
+ * If close is called on a secondary index handle while we're putting
+ * to it, it won't really be closed--the refcount will simply drop,
+ * and we'll be responsible for closing it here.
+ */
+ sdbp = *sdbpp;
+ pdbp = sdbp->s_primary;
+ closeme = NULL;
+
+ MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
+ DB_ASSERT(sdbp->s_refcnt != 0);
+ if (--sdbp->s_refcnt == 0) {
+ LIST_REMOVE(sdbp, s_links);
+ closeme = sdbp;
+ }
+ sdbp = LIST_NEXT(sdbp, s_links);
+ if (sdbp != NULL)
+ sdbp->s_refcnt++;
+ MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
+
+ *sdbpp = sdbp;
+
+ /*
+ * closeme->close() is a wrapper; call __db_close explicitly.
+ */
+ ret = closeme != NULL ? __db_close(closeme, 0) : 0;
+ return (ret);
+}
+
+/*
+ * __db_s_done --
+ * Properly decrement the refcount on a secondary database handle we're
+ * using, without calling __db_s_next.
+ *
+ * PUBLIC: int __db_s_done __P((DB *));
+ */
+int
+__db_s_done(sdbp)
+ DB *sdbp;
+{
+ DB *pdbp;
+ int doclose;
+
+ pdbp = sdbp->s_primary;
+ doclose = 0;
+
+ MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
+ DB_ASSERT(sdbp->s_refcnt != 0);
+ if (--sdbp->s_refcnt == 0) {
+ LIST_REMOVE(sdbp, s_links);
+ doclose = 1;
+ }
+ MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
+
+ return (doclose ? __db_close(sdbp, 0) : 0);
+}
+
+/*
+ * __db_buildpartial --
+ * Build the record that will result after a partial put is applied to
+ * an existing record.
+ *
+ * This should probably be merged with __bam_build, but that requires
+ * a little trickery if we plan to keep the overflow-record optimization
+ * in that function.
+ */
+static int
+__db_buildpartial(dbp, oldrec, partial, newrec)
+ DB *dbp;
+ DBT *oldrec, *partial, *newrec;
+{
+ int ret;
+ u_int8_t *buf;
+ u_int32_t len, nbytes;
+
+ DB_ASSERT(F_ISSET(partial, DB_DBT_PARTIAL));
+
+ memset(newrec, 0, sizeof(DBT));
+
+ nbytes = __db_partsize(oldrec->size, partial);
+ newrec->size = nbytes;
+
+ if ((ret = __os_malloc(dbp->dbenv, nbytes, &buf)) != 0)
+ return (ret);
+ newrec->data = buf;
+
+ /* Nul or pad out the buffer, for any part that isn't specified. */
+ memset(buf,
+ F_ISSET(dbp, DB_AM_FIXEDLEN) ? ((BTREE *)dbp->bt_internal)->re_pad :
+ 0, nbytes);
+
+ /* Copy in any leading data from the original record. */
+ memcpy(buf, oldrec->data,
+ partial->doff > oldrec->size ? oldrec->size : partial->doff);
+
+ /* Copy the data from partial. */
+ memcpy(buf + partial->doff, partial->data, partial->size);
+
+ /* Copy any trailing data from the original record. */
+ len = partial->doff + partial->dlen;
+ if (oldrec->size > len)
+ memcpy(buf + partial->doff + partial->size,
+ (u_int8_t *)oldrec->data + len, oldrec->size - len);
+
+ return (0);
+}
+
+/*
+ * __db_partsize --
+ * Given the number of bytes in an existing record and a DBT that
+ * is about to be partial-put, calculate the size of the record
+ * after the put.
+ *
+ * This code is called from __bam_partsize.
+ *
+ * PUBLIC: u_int32_t __db_partsize __P((u_int32_t, DBT *));
+ */
+u_int32_t
+__db_partsize(nbytes, data)
+ u_int32_t nbytes;
+ DBT *data;
+{
+
+ /*
+ * There are really two cases here:
+ *
+ * Case 1: We are replacing some bytes that do not exist (i.e., they
+ * are past the end of the record). In this case the number of bytes
+ * we are replacing is irrelevant and all we care about is how many
+ * bytes we are going to add from offset. So, the new record length
+ * is going to be the size of the new bytes (size) plus wherever those
+ * new bytes begin (doff).
+ *
+ * Case 2: All the bytes we are replacing exist. Therefore, the new
+ * size is the oldsize (nbytes) minus the bytes we are replacing (dlen)
+ * plus the bytes we are adding (size).
+ */
+ if (nbytes < data->doff + data->dlen) /* Case 1 */
+ return (data->doff + data->size);
+
+ return (nbytes + data->size - data->dlen); /* Case 2 */
+}
diff --git a/bdb/db/db_conv.c b/bdb/db/db_conv.c
index df60be06790..f731c82d85e 100644
--- a/bdb/db/db_conv.c
+++ b/bdb/db/db_conv.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -40,7 +40,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_conv.c,v 11.11 2000/11/30 00:58:31 ubell Exp $";
+static const char revid[] = "$Id: db_conv.c,v 11.38 2002/08/15 03:00:13 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -50,12 +50,14 @@ static const char revid[] = "$Id: db_conv.c,v 11.11 2000/11/30 00:58:31 ubell Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "db_am.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
/*
* __db_pgin --
@@ -70,15 +72,135 @@ __db_pgin(dbenv, pg, pp, cookie)
void *pp;
DBT *cookie;
{
+ DB dummydb, *dbp;
DB_PGINFO *pginfo;
+ DB_CIPHER *db_cipher;
+ DB_LSN not_used;
+ PAGE *pagep;
+ size_t pg_off, pg_len, sum_len;
+ int is_hmac, ret;
+ u_int8_t *chksum, *iv;
pginfo = (DB_PGINFO *)cookie->data;
+ pagep = (PAGE *)pp;
- switch (((PAGE *)pp)->type) {
- case P_HASH:
+ ret = is_hmac = 0;
+ chksum = iv = NULL;
+ memset(&dummydb, 0, sizeof(DB));
+ dbp = &dummydb;
+ dummydb.flags = pginfo->flags;
+ db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+ switch (pagep->type) {
case P_HASHMETA:
+ case P_BTREEMETA:
+ case P_QAMMETA:
+ /*
+ * If checksumming is set on the meta-page, we must set
+ * it in the dbp.
+ */
+ if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM))
+ F_SET(dbp, DB_AM_CHKSUM);
+ if (((DBMETA *)pp)->encrypt_alg != 0 ||
+ F_ISSET(dbp, DB_AM_ENCRYPT))
+ is_hmac = 1;
+ /*
+ * !!!
+ * For all meta pages it is required that the chksum
+ * be at the same location. Use BTMETA to get to it
+ * for any meta type.
+ */
+ chksum = ((BTMETA *)pp)->chksum;
+ sum_len = DBMETASIZE;
+ break;
+ case P_INVALID:
+ /*
+ * We assume that we've read a file hole if we have
+ * a zero LSN, zero page number and P_INVALID. Otherwise
+ * we have an invalid page that might contain real data.
+ */
+ if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) {
+ sum_len = 0;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ chksum = P_CHKSUM(dbp, pagep);
+ sum_len = pginfo->db_pagesize;
+ /*
+ * If we are reading in a non-meta page, then if we have
+ * a db_cipher then we are using hmac.
+ */
+ is_hmac = CRYPTO_ON(dbenv) ? 1 : 0;
+ break;
+ }
+
+ /*
+ * We expect a checksum error if there was a configuration problem.
+ * If there is no configuration problem and we don't get a match,
+ * it's fatal: panic the system.
+ */
+ if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0)
+ switch (ret = __db_check_chksum(
+ dbenv, db_cipher, chksum, pp, sum_len, is_hmac)) {
+ case 0:
+ break;
+ case -1:
+ if (DBENV_LOGGING(dbenv))
+ __db_cksum_log(
+ dbenv, NULL, &not_used, DB_FLUSH);
+ __db_err(dbenv,
+ "checksum error: catastrophic recovery required");
+ return (__db_panic(dbenv, DB_RUNRECOVERY));
+ default:
+ return (ret);
+ }
+
+ if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
+ DB_ASSERT(db_cipher != NULL);
+ DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
+
+ pg_off = P_OVERHEAD(dbp);
+ DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
+
+ switch (pagep->type) {
+ case P_HASHMETA:
+ case P_BTREEMETA:
+ case P_QAMMETA:
+ /*
+ * !!!
+ * For all meta pages it is required that the iv
+ * be at the same location. Use BTMETA to get to it
+ * for any meta type.
+ */
+ iv = ((BTMETA *)pp)->iv;
+ pg_len = DBMETASIZE;
+ break;
+ case P_INVALID:
+ if (IS_ZERO_LSN(LSN(pagep)) &&
+ pagep->pgno == PGNO_INVALID) {
+ pg_len = 0;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ iv = P_IV(dbp, pagep);
+ pg_len = pginfo->db_pagesize;
+ break;
+ }
+ if (pg_len != 0 && (ret = db_cipher->decrypt(dbenv,
+ db_cipher->data, iv, ((u_int8_t *)pagep) + pg_off,
+ pg_len - pg_off)) != 0)
+ return (ret);
+ }
+ switch (pagep->type) {
case P_INVALID:
- return (__ham_pgin(dbenv, pg, pp, cookie));
+ if (pginfo->type == DB_QUEUE)
+ return (__qam_pgin_out(dbenv, pg, pp, cookie));
+ else
+ return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
+ case P_HASH:
+ case P_HASHMETA:
+ return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
case P_BTREEMETA:
case P_IBTREE:
case P_IRECNO:
@@ -86,14 +208,14 @@ __db_pgin(dbenv, pg, pp, cookie)
case P_LDUP:
case P_LRECNO:
case P_OVERFLOW:
- return (__bam_pgin(dbenv, pg, pp, cookie));
+ return (__bam_pgin(dbenv, dbp, pg, pp, cookie));
case P_QAMMETA:
case P_QAMDATA:
return (__qam_pgin_out(dbenv, pg, pp, cookie));
default:
break;
}
- return (__db_unknown_type(dbenv, "__db_pgin", ((PAGE *)pp)->type));
+ return (__db_pgfmt(dbenv, pg));
}
/*
@@ -109,15 +231,33 @@ __db_pgout(dbenv, pg, pp, cookie)
void *pp;
DBT *cookie;
{
+ DB dummydb, *dbp;
+ DB_CIPHER *db_cipher;
DB_PGINFO *pginfo;
+ PAGE *pagep;
+ size_t pg_off, pg_len, sum_len;
+ int ret;
+ u_int8_t *chksum, *iv, *key;
pginfo = (DB_PGINFO *)cookie->data;
+ pagep = (PAGE *)pp;
- switch (((PAGE *)pp)->type) {
+ chksum = iv = key = NULL;
+ memset(&dummydb, 0, sizeof(DB));
+ dbp = &dummydb;
+ dummydb.flags = pginfo->flags;
+ ret = 0;
+ switch (pagep->type) {
+ case P_INVALID:
+ if (pginfo->type == DB_QUEUE)
+ ret = __qam_pgin_out(dbenv, pg, pp, cookie);
+ else
+ ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
+ break;
case P_HASH:
case P_HASHMETA:
- case P_INVALID:
- return (__ham_pgout(dbenv, pg, pp, cookie));
+ ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
+ break;
case P_BTREEMETA:
case P_IBTREE:
case P_IRECNO:
@@ -125,14 +265,73 @@ __db_pgout(dbenv, pg, pp, cookie)
case P_LDUP:
case P_LRECNO:
case P_OVERFLOW:
- return (__bam_pgout(dbenv, pg, pp, cookie));
+ ret = __bam_pgout(dbenv, dbp, pg, pp, cookie);
+ break;
case P_QAMMETA:
case P_QAMDATA:
- return (__qam_pgin_out(dbenv, pg, pp, cookie));
- default:
+ ret = __qam_pgin_out(dbenv, pg, pp, cookie);
break;
+ default:
+ return (__db_pgfmt(dbenv, pg));
+ }
+ if (ret)
+ return (ret);
+
+ db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+ if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
+
+ DB_ASSERT(db_cipher != NULL);
+ DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
+
+ pg_off = P_OVERHEAD(dbp);
+ DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
+
+ key = db_cipher->mac_key;
+
+ switch (pagep->type) {
+ case P_HASHMETA:
+ case P_BTREEMETA:
+ case P_QAMMETA:
+ /*
+ * !!!
+ * For all meta pages it is required that the iv
+ * be at the same location. Use BTMETA to get to it
+ * for any meta type.
+ */
+ iv = ((BTMETA *)pp)->iv;
+ pg_len = DBMETASIZE;
+ break;
+ default:
+ iv = P_IV(dbp, pagep);
+ pg_len = pginfo->db_pagesize;
+ break;
+ }
+ if ((ret = db_cipher->encrypt(dbenv, db_cipher->data,
+ iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0)
+ return (ret);
+ }
+ if (F_ISSET(dbp, DB_AM_CHKSUM)) {
+ switch (pagep->type) {
+ case P_HASHMETA:
+ case P_BTREEMETA:
+ case P_QAMMETA:
+ /*
+ * !!!
+ * For all meta pages it is required that the chksum
+ * be at the same location. Use BTMETA to get to it
+ * for any meta type.
+ */
+ chksum = ((BTMETA *)pp)->chksum;
+ sum_len = DBMETASIZE;
+ break;
+ default:
+ chksum = P_CHKSUM(dbp, pagep);
+ sum_len = pginfo->db_pagesize;
+ break;
+ }
+ __db_chksum(pp, sum_len, key, chksum);
}
- return (__db_unknown_type(dbenv, "__db_pgout", ((PAGE *)pp)->type));
+ return (0);
}
/*
@@ -169,11 +368,13 @@ __db_metaswap(pg)
* __db_byteswap --
* Byteswap a page.
*
- * PUBLIC: int __db_byteswap __P((DB_ENV *, db_pgno_t, PAGE *, size_t, int));
+ * PUBLIC: int __db_byteswap
+ * PUBLIC: __P((DB_ENV *, DB *, db_pgno_t, PAGE *, size_t, int));
*/
int
-__db_byteswap(dbenv, pg, h, pagesize, pgin)
+__db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
DB_ENV *dbenv;
+ DB *dbp;
db_pgno_t pg;
PAGE *h;
size_t pagesize;
@@ -183,11 +384,12 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
BKEYDATA *bk;
BOVERFLOW *bo;
RINTERNAL *ri;
- db_indx_t i, len, tmp;
+ db_indx_t i, *inp, len, tmp;
u_int8_t *p, *end;
COMPQUIET(pg, 0);
+ inp = P_INP(dbp, h);
if (pgin) {
M_32_SWAP(h->lsn.file);
M_32_SWAP(h->lsn.offset);
@@ -202,14 +404,14 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
case P_HASH:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
- switch (HPAGE_TYPE(h, i)) {
+ switch (HPAGE_TYPE(dbp, h, i)) {
case H_KEYDATA:
break;
case H_DUPLICATE:
- len = LEN_HKEYDATA(h, pagesize, i);
- p = HKEYDATA_DATA(P_ENTRY(h, i));
+ len = LEN_HKEYDATA(dbp, h, pagesize, i);
+ p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
for (end = p + len; p < end;) {
if (pgin) {
P_16_SWAP(p);
@@ -226,11 +428,11 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
}
break;
case H_OFFDUP:
- p = HOFFPAGE_PGNO(P_ENTRY(h, i));
+ p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
SWAP32(p); /* pgno */
break;
case H_OFFPAGE:
- p = HOFFPAGE_PGNO(P_ENTRY(h, i));
+ p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
SWAP32(p); /* pgno */
SWAP32(p); /* tlen */
break;
@@ -246,14 +448,14 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
*/
if (!pgin)
for (i = 0; i < NUM_ENT(h); i++)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
break;
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
/*
* In the case of on-page duplicates, key information
@@ -261,17 +463,17 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
*/
if (h->type == P_LBTREE && i > 1) {
if (pgin) {
- if (h->inp[i] == h->inp[i - 2])
+ if (inp[i] == inp[i - 2])
continue;
} else {
- M_16_SWAP(h->inp[i]);
- if (h->inp[i] == h->inp[i - 2])
+ M_16_SWAP(inp[i]);
+ if (inp[i] == inp[i - 2])
continue;
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
}
}
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
switch (B_TYPE(bk->type)) {
case B_KEYDATA:
M_16_SWAP(bk->len);
@@ -285,15 +487,15 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
}
if (!pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
}
break;
case P_IBTREE:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
- bi = GET_BINTERNAL(h, i);
+ bi = GET_BINTERNAL(dbp, h, i);
M_16_SWAP(bi->len);
M_32_SWAP(bi->pgno);
M_32_SWAP(bi->nrecs);
@@ -310,20 +512,20 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
}
if (!pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
}
break;
case P_IRECNO:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
- ri = GET_RINTERNAL(h, i);
+ ri = GET_RINTERNAL(dbp, h, i);
M_32_SWAP(ri->pgno);
M_32_SWAP(ri->nrecs);
if (!pgin)
- M_16_SWAP(h->inp[i]);
+ M_16_SWAP(inp[i]);
}
break;
case P_OVERFLOW:
@@ -331,7 +533,7 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin)
/* Nothing to do. */
break;
default:
- return (__db_unknown_type(dbenv, "__db_byteswap", h->type));
+ return (__db_pgfmt(dbenv, pg));
}
if (!pgin) {
diff --git a/bdb/db/db_dispatch.c b/bdb/db/db_dispatch.c
index c9beac401a7..2cf29ec2f33 100644
--- a/bdb/db/db_dispatch.c
+++ b/bdb/db/db_dispatch.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -39,7 +39,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_dispatch.c,v 11.41 2001/01/11 18:19:50 bostic Exp $";
+static const char revid[] = "$Id: db_dispatch.c,v 11.121 2002/09/07 17:36:31 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -51,16 +51,24 @@ static const char revid[] = "$Id: db_dispatch.c,v 11.41 2001/01/11 18:19:50 bost
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_dispatch.h"
-#include "db_am.h"
-#include "log_auto.h"
-#include "txn.h"
-#include "txn_auto.h"
-#include "log.h"
-
-static int __db_txnlist_find_internal __P((void *, db_txnlist_type,
- u_int32_t, u_int8_t [DB_FILE_ID_LEN], DB_TXNLIST **, int));
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
+#include "dbinc/fop.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+
+static int __db_limbo_fix __P((DB *,
+ DB_TXN *, DB_TXNLIST *, db_pgno_t *, DBMETA *));
+static int __db_limbo_bucket __P((DB_ENV *, DB_TXN *, DB_TXNLIST *));
+static int __db_limbo_move __P((DB_ENV *, DB_TXN *, DB_TXN *, DB_TXNLIST *));
+static int __db_lock_move __P((DB_ENV *,
+ u_int8_t *, db_pgno_t, db_lockmode_t, DB_TXN *, DB_TXN *));
+static int __db_default_getpgnos __P((DB_ENV *, DB_LSN *lsnp, void *));
+static int __db_txnlist_find_internal __P((DB_ENV *, void *, db_txnlist_type,
+ u_int32_t, u_int8_t [DB_FILE_ID_LEN], DB_TXNLIST **, int));
+static int __db_txnlist_pgnoadd __P((DB_ENV *, DB_TXNHEAD *,
+ int32_t, u_int8_t [DB_FILE_ID_LEN], char *, db_pgno_t));
/*
* __db_dispatch --
@@ -71,16 +79,21 @@ static int __db_txnlist_find_internal __P((void *, db_txnlist_type,
* scripts in the tools directory). An application using a different
* recovery paradigm will supply a different dispatch function to txn_open.
*
- * PUBLIC: int __db_dispatch __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ * PUBLIC: int __db_dispatch __P((DB_ENV *,
+ * PUBLIC: int (**)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)),
+ * PUBLIC: size_t, DBT *, DB_LSN *, db_recops, void *));
*/
int
-__db_dispatch(dbenv, db, lsnp, redo, info)
+__db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
DB_ENV *dbenv; /* The environment. */
+ int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t dtabsize; /* Size of the dtab. */
DBT *db; /* The log record upon which to dispatch. */
DB_LSN *lsnp; /* The lsn of the record being dispatched. */
db_recops redo; /* Redo this op (or undo it). */
void *info;
{
+ DB_LSN prev_lsn;
u_int32_t rectype, txnid;
int make_call, ret;
@@ -88,6 +101,9 @@ __db_dispatch(dbenv, db, lsnp, redo, info)
memcpy(&txnid, (u_int8_t *)db->data + sizeof(rectype), sizeof(txnid));
make_call = ret = 0;
+ /* If we don't have a dispatch table, it's hard to dispatch. */
+ DB_ASSERT(dtab != NULL);
+
/*
* If we find a record that is in the user's number space and they
* have specified a recovery routine, let them handle it. If they
@@ -96,17 +112,29 @@ __db_dispatch(dbenv, db, lsnp, redo, info)
*/
switch (redo) {
case DB_TXN_ABORT:
- /*
- * XXX
- * db_printlog depends on DB_TXN_ABORT not examining the TXN
- * list. If that ever changes, fix db_printlog too.
- */
+ case DB_TXN_APPLY:
+ case DB_TXN_PRINT:
make_call = 1;
break;
case DB_TXN_OPENFILES:
- if (rectype == DB_log_register)
- return (dbenv->dtab[rectype](dbenv,
- db, lsnp, redo, info));
+ /*
+ * We collect all the transactions that have
+ * "begin" records, those with no previous LSN,
+ * so that we do not abort partial transactions.
+ * These are known to be undone, otherwise the
+ * log would not have been freeable.
+ */
+ memcpy(&prev_lsn, (u_int8_t *)db->data +
+ sizeof(rectype) + sizeof(txnid), sizeof(prev_lsn));
+ if (txnid != 0 && prev_lsn.file == 0 && (ret =
+ __db_txnlist_add(dbenv, info, txnid, TXN_OK, NULL)) != 0)
+ return (ret);
+
+ /* FALLTHROUGH */
+ case DB_TXN_POPENFILES:
+ if (rectype == DB___dbreg_register ||
+ rectype == DB___txn_ckp || rectype == DB___txn_recycle)
+ return (dtab[rectype](dbenv, db, lsnp, redo, info));
break;
case DB_TXN_BACKWARD_ROLL:
/*
@@ -117,43 +145,146 @@ __db_dispatch(dbenv, db, lsnp, redo, info)
* we've never seen it, then we call the appropriate recovery
* routine.
*
- * We need to always undo DB_db_noop records, so that we
+ * We need to always undo DB___db_noop records, so that we
* properly handle any aborts before the file was closed.
*/
- if (rectype == DB_log_register ||
- rectype == DB_txn_ckp || rectype == DB_db_noop
- || rectype == DB_txn_child || (txnid != 0 &&
- (ret = __db_txnlist_find(info, txnid)) != 0)) {
+ switch(rectype) {
+ case DB___txn_regop:
+ case DB___txn_recycle:
+ case DB___txn_ckp:
+ case DB___db_noop:
+ case DB___fop_file_remove:
+ case DB___txn_child:
make_call = 1;
- if (ret == DB_NOTFOUND && rectype != DB_txn_regop &&
- rectype != DB_txn_xa_regop && (ret =
- __db_txnlist_add(dbenv, info, txnid, 1)) != 0)
- return (ret);
+ break;
+
+ case DB___dbreg_register:
+ if (txnid == 0) {
+ make_call = 1;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (txnid != 0 && (ret =
+ __db_txnlist_find(dbenv,
+ info, txnid)) != TXN_COMMIT && ret != TXN_IGNORE) {
+ /*
+ * If not found then, this is an incomplete
+ * abort.
+ */
+ if (ret == TXN_NOTFOUND)
+ return (__db_txnlist_add(dbenv,
+ info, txnid, TXN_IGNORE, lsnp));
+ make_call = 1;
+ if (ret == TXN_OK &&
+ (ret = __db_txnlist_update(dbenv,
+ info, txnid,
+ rectype == DB___txn_xa_regop ?
+ TXN_PREPARE : TXN_ABORT, NULL)) != 0)
+ return (ret);
+ }
}
break;
case DB_TXN_FORWARD_ROLL:
/*
* In the forward pass, if we haven't seen the transaction,
- * do nothing, else recovery it.
+ * do nothing, else recover it.
*
- * We need to always redo DB_db_noop records, so that we
+ * We need to always redo DB___db_noop records, so that we
* properly handle any commits after the file was closed.
*/
- if (rectype == DB_log_register ||
- rectype == DB_txn_ckp ||
- rectype == DB_db_noop ||
- __db_txnlist_find(info, txnid) == 0)
+ switch(rectype) {
+ case DB___txn_recycle:
+ case DB___txn_ckp:
+ case DB___db_noop:
make_call = 1;
+ break;
+
+ default:
+ if (txnid != 0 && (ret = __db_txnlist_find(dbenv,
+ info, txnid)) == TXN_COMMIT)
+ make_call = 1;
+ else if (ret != TXN_IGNORE &&
+ (rectype == DB___ham_metagroup ||
+ rectype == DB___ham_groupalloc ||
+ rectype == DB___db_pg_alloc)) {
+ /*
+ * Because we cannot undo file extensions
+ * all allocation records must be reprocessed
+ * during rollforward in case the file was
+ * just created. It may not have been
+ * present during the backward pass.
+ */
+ make_call = 1;
+ redo = DB_TXN_BACKWARD_ALLOC;
+ } else if (rectype == DB___dbreg_register) {
+ /*
+ * This may be a transaction dbreg_register.
+ * If it is, we only make the call on a COMMIT,
+ * which we checked above. If it's not, then we
+ * should always make the call, because we need
+ * the file open information.
+ */
+ if (txnid == 0)
+ make_call = 1;
+ }
+ }
break;
+ case DB_TXN_GETPGNOS:
+ /*
+ * If this is one of DB's own log records, we simply
+ * dispatch.
+ */
+ if (rectype < DB_user_BEGIN) {
+ make_call = 1;
+ break;
+ }
+
+ /*
+ * If we're still here, this is a custom record in an
+ * application that's doing app-specific logging. Such a
+ * record doesn't have a getpgno function for the user
+ * dispatch function to call--the getpgnos functions return
+ * which pages replication needs to lock using the TXN_RECS
+ * structure, which is private and not something we want to
+ * document.
+ *
+ * Thus, we leave any necessary locking for the app's
+ * recovery function to do during the upcoming
+ * DB_TXN_APPLY. Fill in default getpgnos info (we need
+ * a stub entry for every log record that will get
+ * DB_TXN_APPLY'd) and return success.
+ */
+ return (__db_default_getpgnos(dbenv, lsnp, info));
default:
return (__db_unknown_flag(dbenv, "__db_dispatch", redo));
}
+ /*
+ * The switch statement uses ret to receive the return value of
+ * __db_txnlist_find, which returns a large number of different
+ * statuses, none of which we will be returning. For safety,
+ * let's reset this here in case we ever do a "return(ret)"
+ * below in the future.
+ */
+ ret = 0;
if (make_call) {
- if (rectype >= DB_user_BEGIN && dbenv->tx_recover != NULL)
- return (dbenv->tx_recover(dbenv, db, lsnp, redo));
- else
- return (dbenv->dtab[rectype](dbenv, db, lsnp, redo, info));
+ if (rectype >= DB_user_BEGIN && dbenv->app_dispatch != NULL)
+ return (dbenv->app_dispatch(dbenv, db, lsnp, redo));
+ else {
+ /*
+ * The size of the dtab table argument is the same as
+ * the standard table, use the standard table's size
+ * as our sanity check.
+ */
+ if (rectype > dtabsize || dtab[rectype] == NULL) {
+ __db_err(dbenv,
+ "Illegal record type %lu in log",
+ (u_long)rectype);
+ return (EINVAL);
+ }
+ return (dtab[rectype](dbenv, db, lsnp, redo, info));
+ }
}
return (0);
@@ -163,75 +294,100 @@ __db_dispatch(dbenv, db, lsnp, redo, info)
* __db_add_recovery --
*
* PUBLIC: int __db_add_recovery __P((DB_ENV *,
- * PUBLIC: int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t));
+ * PUBLIC: int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), size_t *,
+ * PUBLIC: int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t));
*/
int
-__db_add_recovery(dbenv, func, ndx)
+__db_add_recovery(dbenv, dtab, dtabsize, func, ndx)
DB_ENV *dbenv;
+ int (***dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t *dtabsize;
int (*func) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
u_int32_t ndx;
{
- u_int32_t i, nsize;
+ size_t i, nsize;
int ret;
/* Check if we have to grow the table. */
- if (ndx >= dbenv->dtab_size) {
+ if (ndx >= *dtabsize) {
nsize = ndx + 40;
- if ((ret = __os_realloc(dbenv,
- nsize * sizeof(dbenv->dtab[0]), NULL, &dbenv->dtab)) != 0)
+ if ((ret =
+ __os_realloc(dbenv, nsize * sizeof((*dtab)[0]), dtab)) != 0)
return (ret);
- for (i = dbenv->dtab_size; i < nsize; ++i)
- dbenv->dtab[i] = NULL;
- dbenv->dtab_size = nsize;
+ for (i = *dtabsize; i < nsize; ++i)
+ (*dtab)[i] = NULL;
+ *dtabsize = nsize;
}
- dbenv->dtab[ndx] = func;
+ (*dtab)[ndx] = func;
return (0);
}
/*
- * __deprecated_recover --
- * Stub routine for deprecated recovery functions.
- *
- * PUBLIC: int __deprecated_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__deprecated_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- COMPQUIET(dbenv, NULL);
- COMPQUIET(dbtp, NULL);
- COMPQUIET(lsnp, NULL);
- COMPQUIET(op, 0);
- COMPQUIET(info, NULL);
- return (EINVAL);
-}
-
-/*
* __db_txnlist_init --
* Initialize transaction linked list.
*
- * PUBLIC: int __db_txnlist_init __P((DB_ENV *, void *));
+ * PUBLIC: int __db_txnlist_init __P((DB_ENV *,
+ * PUBLIC: u_int32_t, u_int32_t, DB_LSN *, void *));
*/
int
-__db_txnlist_init(dbenv, retp)
+__db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
DB_ENV *dbenv;
+ u_int32_t low_txn, hi_txn;
+ DB_LSN *trunc_lsn;
void *retp;
{
DB_TXNHEAD *headp;
- int ret;
+ u_int32_t tmp;
+ int ret, size;
- if ((ret = __os_malloc(dbenv, sizeof(DB_TXNHEAD), NULL, &headp)) != 0)
+ /*
+ * Size a hash table.
+ * If low is zero then we are being called during rollback
+ * and we need only one slot.
+ * Hi maybe lower than low if we have recycled txnid's.
+ * The numbers here are guesses about txn density, we can afford
+ * to look at a few entries in each slot.
+ */
+ if (low_txn == 0)
+ size = 1;
+ else {
+ if (hi_txn < low_txn) {
+ tmp = hi_txn;
+ hi_txn = low_txn;
+ low_txn = tmp;
+ }
+ tmp = hi_txn - low_txn;
+ /* See if we wrapped around. */
+ if (tmp > (TXN_MAXIMUM - TXN_MINIMUM) / 2)
+ tmp = (low_txn - TXN_MINIMUM) + (TXN_MAXIMUM - hi_txn);
+ size = tmp / 5;
+ if (size < 100)
+ size = 100;
+ }
+ if ((ret = __os_malloc(dbenv,
+ sizeof(DB_TXNHEAD) + size * sizeof(headp->head), &headp)) != 0)
return (ret);
- LIST_INIT(&headp->head);
- headp->maxid = 0;
- headp->generation = 1;
+ memset(headp, 0, sizeof(DB_TXNHEAD) + size * sizeof(headp->head));
+ headp->maxid = hi_txn;
+ headp->generation = 0;
+ headp->nslots = size;
+ headp->gen_alloc = 8;
+ if ((ret = __os_malloc(dbenv, headp->gen_alloc *
+ sizeof(headp->gen_array[0]), &headp->gen_array)) != 0) {
+ __os_free(dbenv, headp);
+ return (ret);
+ }
+ headp->gen_array[0].generation = 0;
+ headp->gen_array[0].txn_min = TXN_MINIMUM;
+ headp->gen_array[0].txn_max = TXN_MAXIMUM;
+ if (trunc_lsn != NULL)
+ headp->trunc_lsn = *trunc_lsn;
+ else
+ ZERO_LSN(headp->trunc_lsn);
+ ZERO_LSN(headp->maxlsn);
+ ZERO_LSN(headp->ckplsn);
*(void **)retp = headp;
return (0);
@@ -241,132 +397,86 @@ __db_txnlist_init(dbenv, retp)
* __db_txnlist_add --
* Add an element to our transaction linked list.
*
- * PUBLIC: int __db_txnlist_add __P((DB_ENV *, void *, u_int32_t, int32_t));
+ * PUBLIC: int __db_txnlist_add __P((DB_ENV *,
+ * PUBLIC: void *, u_int32_t, int32_t, DB_LSN *));
*/
int
-__db_txnlist_add(dbenv, listp, txnid, aborted)
+__db_txnlist_add(dbenv, listp, txnid, status, lsn)
DB_ENV *dbenv;
void *listp;
u_int32_t txnid;
- int32_t aborted;
+ int32_t status;
+ DB_LSN *lsn;
{
DB_TXNHEAD *hp;
DB_TXNLIST *elp;
int ret;
- if ((ret = __os_malloc(dbenv, sizeof(DB_TXNLIST), NULL, &elp)) != 0)
+ if ((ret = __os_malloc(dbenv, sizeof(DB_TXNLIST), &elp)) != 0)
return (ret);
hp = (DB_TXNHEAD *)listp;
- LIST_INSERT_HEAD(&hp->head, elp, links);
+ LIST_INSERT_HEAD(&hp->head[DB_TXNLIST_MASK(hp, txnid)], elp, links);
elp->type = TXNLIST_TXNID;
elp->u.t.txnid = txnid;
- elp->u.t.aborted = aborted;
+ elp->u.t.status = status;
+ elp->u.t.generation = hp->generation;
if (txnid > hp->maxid)
hp->maxid = txnid;
- elp->u.t.generation = hp->generation;
+ if (lsn != NULL && IS_ZERO_LSN(hp->maxlsn) && status == TXN_COMMIT)
+ hp->maxlsn = *lsn;
+
+ DB_ASSERT(lsn == NULL ||
+ status != TXN_COMMIT || log_compare(&hp->maxlsn, lsn) >= 0);
return (0);
}
+
/*
* __db_txnlist_remove --
* Remove an element from our transaction linked list.
*
- * PUBLIC: int __db_txnlist_remove __P((void *, u_int32_t));
+ * PUBLIC: int __db_txnlist_remove __P((DB_ENV *, void *, u_int32_t));
*/
int
-__db_txnlist_remove(listp, txnid)
+__db_txnlist_remove(dbenv, listp, txnid)
+ DB_ENV *dbenv;
void *listp;
u_int32_t txnid;
{
DB_TXNLIST *entry;
- return (__db_txnlist_find_internal(listp,
- TXNLIST_TXNID, txnid, NULL, &entry, 1));
-}
-
-/* __db_txnlist_close --
- *
- * Call this when we close a file. It allows us to reconcile whether
- * we have done any operations on this file with whether the file appears
- * to have been deleted. If you never do any operations on a file, then
- * we assume it's OK to appear deleted.
- *
- * PUBLIC: int __db_txnlist_close __P((void *, int32_t, u_int32_t));
- */
-
-int
-__db_txnlist_close(listp, lid, count)
- void *listp;
- int32_t lid;
- u_int32_t count;
-{
- DB_TXNHEAD *hp;
- DB_TXNLIST *p;
-
- hp = (DB_TXNHEAD *)listp;
- for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
- if (p->type == TXNLIST_DELETE)
- if (lid == p->u.d.fileid &&
- !F_ISSET(&p->u.d, TXNLIST_FLAG_CLOSED)) {
- p->u.d.count += count;
- return (0);
- }
- }
-
- return (0);
+ return (__db_txnlist_find_internal(dbenv,
+ listp, TXNLIST_TXNID, txnid,
+ NULL, &entry, 1) == TXN_NOTFOUND ? TXN_NOTFOUND : TXN_OK);
}
/*
- * __db_txnlist_delete --
- *
- * Record that a file was missing or deleted. If the deleted
- * flag is set, then we've encountered a delete of a file, else we've
- * just encountered a file that is missing. The lid is the log fileid
- * and is only meaningful if deleted is not equal to 0.
+ * __db_txnlist_ckp --
+ * Used to record the maximum checkpoint that will be retained
+ * after recovery. Typically this is simply the max checkpoint, but
+ * if we are doing client replication recovery or timestamp-based
+ * recovery, we are going to virtually truncate the log and we need
+ * to retain the last checkpoint before the truncation point.
*
- * PUBLIC: int __db_txnlist_delete __P((DB_ENV *,
- * PUBLIC: void *, char *, u_int32_t, int));
+ * PUBLIC: void __db_txnlist_ckp __P((DB_ENV *, void *, DB_LSN *));
*/
-int
-__db_txnlist_delete(dbenv, listp, name, lid, deleted)
+void
+__db_txnlist_ckp(dbenv, listp, ckp_lsn)
DB_ENV *dbenv;
void *listp;
- char *name;
- u_int32_t lid;
- int deleted;
+ DB_LSN *ckp_lsn;
{
DB_TXNHEAD *hp;
- DB_TXNLIST *p;
- int ret;
- hp = (DB_TXNHEAD *)listp;
- for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
- if (p->type == TXNLIST_DELETE)
- if (strcmp(name, p->u.d.fname) == 0) {
- if (deleted)
- F_SET(&p->u.d, TXNLIST_FLAG_DELETED);
- else
- F_CLR(&p->u.d, TXNLIST_FLAG_CLOSED);
- return (0);
- }
- }
-
- /* Need to add it. */
- if ((ret = __os_malloc(dbenv, sizeof(DB_TXNLIST), NULL, &p)) != 0)
- return (ret);
- LIST_INSERT_HEAD(&hp->head, p, links);
+ COMPQUIET(dbenv, NULL);
- p->type = TXNLIST_DELETE;
- p->u.d.flags = 0;
- if (deleted)
- F_SET(&p->u.d, TXNLIST_FLAG_DELETED);
- p->u.d.fileid = lid;
- p->u.d.count = 0;
- ret = __os_strdup(dbenv, name, &p->u.d.fname);
+ hp = (DB_TXNHEAD *)listp;
- return (ret);
+ if (IS_ZERO_LSN(hp->ckplsn) && !IS_ZERO_LSN(hp->maxlsn) &&
+ log_compare(&hp->maxlsn, ckp_lsn) >= 0)
+ hp->ckplsn = *ckp_lsn;
}
/*
@@ -383,99 +493,156 @@ __db_txnlist_end(dbenv, listp)
{
DB_TXNHEAD *hp;
DB_TXNLIST *p;
- DB_LOG *lp;
+ int i;
- hp = (DB_TXNHEAD *)listp;
- lp = (DB_LOG *)dbenv->lg_handle;
- while (hp != NULL && (p = LIST_FIRST(&hp->head)) != NULL) {
- LIST_REMOVE(p, links);
- switch (p->type) {
- case TXNLIST_DELETE:
- /*
- * If we have a file that is not deleted and has
- * some operations, we flag the warning. Since
- * the file could still be open, we need to check
- * the actual log table as well.
- */
- if ((!F_ISSET(&p->u.d, TXNLIST_FLAG_DELETED) &&
- p->u.d.count != 0) ||
- (!F_ISSET(&p->u.d, TXNLIST_FLAG_CLOSED) &&
- p->u.d.fileid != (int32_t) TXNLIST_INVALID_ID &&
- p->u.d.fileid < lp->dbentry_cnt &&
- lp->dbentry[p->u.d.fileid].count != 0))
- __db_err(dbenv, "warning: %s: %s",
- p->u.d.fname, db_strerror(ENOENT));
- __os_freestr(p->u.d.fname);
- break;
- case TXNLIST_LSN:
- __os_free(p->u.l.lsn_array,
- p->u.l.maxn * sizeof(DB_LSN));
- break;
- default:
- /* Possibly an incomplete DB_TXNLIST; just free it. */
- break;
+ if ((hp = (DB_TXNHEAD *)listp) == NULL)
+ return;
+
+ for (i = 0; i < hp->nslots; i++)
+ while (hp != NULL && (p = LIST_FIRST(&hp->head[i])) != NULL) {
+ LIST_REMOVE(p, links);
+ switch (p->type) {
+ case TXNLIST_LSN:
+ __os_free(dbenv, p->u.l.lsn_array);
+ break;
+ default:
+ /*
+ * Possibly an incomplete DB_TXNLIST; just
+ * free it.
+ */
+ break;
+ }
+ __os_free(dbenv, p);
}
- __os_free(p, sizeof(DB_TXNLIST));
- }
- __os_free(listp, sizeof(DB_TXNHEAD));
+
+ if (hp->gen_array != NULL)
+ __os_free(dbenv, hp->gen_array);
+ __os_free(dbenv, listp);
}
/*
* __db_txnlist_find --
* Checks to see if a txnid with the current generation is in the
- * txnid list. This returns DB_NOTFOUND if the item isn't in the
- * list otherwise it returns (like __db_txnlist_find_internal) a
- * 1 or 0 indicating if the transaction is aborted or not. A txnid
- * of 0 means the record was generated while not in a transaction.
+ * txnid list. This returns TXN_NOTFOUND if the item isn't in the
+ * list otherwise it returns (like __db_txnlist_find_internal)
+ * the status of the transaction. A txnid of 0 means the record
+ * was generated while not in a transaction.
*
- * PUBLIC: int __db_txnlist_find __P((void *, u_int32_t));
+ * PUBLIC: int __db_txnlist_find __P((DB_ENV *, void *, u_int32_t));
*/
int
-__db_txnlist_find(listp, txnid)
+__db_txnlist_find(dbenv, listp, txnid)
+ DB_ENV *dbenv;
void *listp;
u_int32_t txnid;
{
DB_TXNLIST *entry;
if (txnid == 0)
- return (DB_NOTFOUND);
- return (__db_txnlist_find_internal(listp,
- TXNLIST_TXNID, txnid, NULL, &entry, 0));
+ return (TXN_NOTFOUND);
+ return (__db_txnlist_find_internal(dbenv, listp,
+ TXNLIST_TXNID, txnid, NULL, &entry, 0));
+}
+
+/*
+ * __db_txnlist_update --
+ * Change the status of an existing transaction entry.
+ * Returns TXN_NOTFOUND if no such entry exists.
+ *
+ * PUBLIC: int __db_txnlist_update __P((DB_ENV *,
+ * PUBLIC: void *, u_int32_t, u_int32_t, DB_LSN *));
+ */
+int
+__db_txnlist_update(dbenv, listp, txnid, status, lsn)
+ DB_ENV *dbenv;
+ void *listp;
+ u_int32_t txnid;
+ u_int32_t status;
+ DB_LSN *lsn;
+{
+ DB_TXNHEAD *hp;
+ DB_TXNLIST *elp;
+ int ret;
+
+ if (txnid == 0)
+ return (TXN_NOTFOUND);
+ hp = (DB_TXNHEAD *)listp;
+ ret = __db_txnlist_find_internal(dbenv,
+ listp, TXNLIST_TXNID, txnid, NULL, &elp, 0);
+
+ if (ret == TXN_NOTFOUND)
+ return (ret);
+ elp->u.t.status = status;
+
+ if (lsn != NULL && IS_ZERO_LSN(hp->maxlsn) && status == TXN_COMMIT)
+ hp->maxlsn = *lsn;
+
+ return (ret);
}
/*
* __db_txnlist_find_internal --
- * Find an entry on the transaction list.
- * If the entry is not there or the list pointeris not initialized
- * we return DB_NOTFOUND. If the item is found, we return the aborted
- * status (1 for aborted, 0 for not aborted). Currently we always call
- * this with an initialized list pointer but checking for NULL keeps it general.
+ * Find an entry on the transaction list. If the entry is not there or
+ * the list pointer is not initialized we return TXN_NOTFOUND. If the
+ * item is found, we return the status. Currently we always call this
+ * with an initialized list pointer but checking for NULL keeps it general.
*/
static int
-__db_txnlist_find_internal(listp, type, txnid, uid, txnlistp, delete)
+__db_txnlist_find_internal(dbenv, listp, type, txnid, uid, txnlistp, delete)
+ DB_ENV *dbenv;
void *listp;
db_txnlist_type type;
- u_int32_t txnid;
+ u_int32_t txnid;
u_int8_t uid[DB_FILE_ID_LEN];
DB_TXNLIST **txnlistp;
int delete;
{
DB_TXNHEAD *hp;
DB_TXNLIST *p;
- int ret;
+ int32_t generation;
+ u_int32_t hash;
+ struct __db_headlink *head;
+ int i, ret;
if ((hp = (DB_TXNHEAD *)listp) == NULL)
- return (DB_NOTFOUND);
+ return (TXN_NOTFOUND);
+
+ switch (type) {
+ case TXNLIST_TXNID:
+ hash = txnid;
+ /* Find the most recent generation containing this ID */
+ for (i = 0; i <= hp->generation; i++)
+ /* The range may wrap around the end. */
+ if (hp->gen_array[i].txn_min <
+ hp->gen_array[i].txn_max ?
+ (txnid >= hp->gen_array[i].txn_min &&
+ txnid <= hp->gen_array[i].txn_max) :
+ (txnid >= hp->gen_array[i].txn_min ||
+ txnid <= hp->gen_array[i].txn_max))
+ break;
+ DB_ASSERT(i <= hp->generation);
+ generation = hp->gen_array[i].generation;
+ break;
+ case TXNLIST_PGNO:
+ memcpy(&hash, uid, sizeof(hash));
+ generation = 0;
+ break;
+ default:
+ DB_ASSERT(0);
+ return (EINVAL);
+ }
+
+ head = &hp->head[DB_TXNLIST_MASK(hp, hash)];
- for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
+ for (p = LIST_FIRST(head); p != NULL; p = LIST_NEXT(p, links)) {
if (p->type != type)
continue;
switch (type) {
case TXNLIST_TXNID:
if (p->u.t.txnid != txnid ||
- hp->generation != p->u.t.generation)
+ generation != p->u.t.generation)
continue;
- ret = p->u.t.aborted;
+ ret = p->u.t.status;
break;
case TXNLIST_PGNO:
@@ -490,42 +657,67 @@ __db_txnlist_find_internal(listp, type, txnid, uid, txnlistp, delete)
}
if (delete == 1) {
LIST_REMOVE(p, links);
- __os_free(p, sizeof(DB_TXNLIST));
- } else if (p != LIST_FIRST(&hp->head)) {
+ __os_free(dbenv, p);
+ } else if (p != LIST_FIRST(head)) {
/* Move it to head of list. */
LIST_REMOVE(p, links);
- LIST_INSERT_HEAD(&hp->head, p, links);
+ LIST_INSERT_HEAD(head, p, links);
}
*txnlistp = p;
return (ret);
}
- return (DB_NOTFOUND);
+ return (TXN_NOTFOUND);
}
/*
* __db_txnlist_gen --
* Change the current generation number.
*
- * PUBLIC: void __db_txnlist_gen __P((void *, int));
+ * PUBLIC: int __db_txnlist_gen __P((DB_ENV *,
+ * PUBLIC: void *, int, u_int32_t, u_int32_t));
*/
-void
-__db_txnlist_gen(listp, incr)
+int
+__db_txnlist_gen(dbenv, listp, incr, min, max)
+ DB_ENV *dbenv;
void *listp;
int incr;
+ u_int32_t min, max;
{
DB_TXNHEAD *hp;
+ int ret;
/*
- * During recovery generation numbers keep track of how many "restart"
- * checkpoints we've seen. Restart checkpoints occur whenever we take
- * a checkpoint and there are no outstanding transactions. When that
- * happens, we can reset transaction IDs back to 1. It always happens
- * at recovery and it prevents us from exhausting the transaction IDs
- * name space.
+ * During recovery generation numbers keep track of "restart"
+ * checkpoints and recycle records. Restart checkpoints occur
+ * whenever we take a checkpoint and there are no outstanding
+ * transactions. When that happens, we can reset transaction IDs
+ * back to TXNID_MINIMUM. Currently we only do the reset
+ * at then end of recovery. Recycle records occrur when txnids
+ * are exhausted during runtime. A free range of ids is identified
+ * and logged. This code maintains a stack of ranges. A txnid
+ * is given the generation number of the first range it falls into
+ * in the stack.
*/
hp = (DB_TXNHEAD *)listp;
hp->generation += incr;
+ if (incr < 0)
+ memmove(hp->gen_array, &hp->gen_array[1],
+ (hp->generation + 1) * sizeof(hp->gen_array[0]));
+ else {
+ if (hp->generation >= hp->gen_alloc) {
+ hp->gen_alloc *= 2;
+ if ((ret = __os_realloc(dbenv, hp->gen_alloc *
+ sizeof(hp->gen_array[0]), &hp->gen_array)) != 0)
+ return (ret);
+ }
+ memmove(&hp->gen_array[1], &hp->gen_array[0],
+ hp->generation * sizeof(hp->gen_array[0]));
+ hp->gen_array[0].generation = hp->generation;
+ hp->gen_array[0].txn_min = min;
+ hp->gen_array[0].txn_max = max;
+ }
+ return (0);
}
#define TXN_BUBBLE(AP, MAX) { \
@@ -542,10 +734,10 @@ __db_txnlist_gen(listp, incr)
/*
* __db_txnlist_lsnadd --
- * Add to or re-sort the transaction list lsn entry.
- * Note that since this is used during an abort, the __txn_undo
- * code calls into the "recovery" subsystem explicitly, and there
- * is only a single TXNLIST_LSN entry on the list.
+ * Add to or re-sort the transaction list lsn entry. Note that since this
+ * is used during an abort, the __txn_undo code calls into the "recovery"
+ * subsystem explicitly, and there is only a single TXNLIST_LSN entry on
+ * the list.
*
* PUBLIC: int __db_txnlist_lsnadd __P((DB_ENV *, void *, DB_LSN *, u_int32_t));
*/
@@ -562,19 +754,19 @@ __db_txnlist_lsnadd(dbenv, listp, lsnp, flags)
hp = (DB_TXNHEAD *)listp;
- for (elp = LIST_FIRST(&hp->head);
+ for (elp = LIST_FIRST(&hp->head[0]);
elp != NULL; elp = LIST_NEXT(elp, links))
if (elp->type == TXNLIST_LSN)
break;
if (elp == NULL)
- return (EINVAL);
+ return (DB_SURPRISE_KID);
if (LF_ISSET(TXNLIST_NEW)) {
if (elp->u.l.ntxns >= elp->u.l.maxn) {
if ((ret = __os_realloc(dbenv,
2 * elp->u.l.maxn * sizeof(DB_LSN),
- NULL, &elp->u.l.lsn_array)) != 0)
+ &elp->u.l.lsn_array)) != 0)
return (ret);
elp->u.l.maxn *= 2;
}
@@ -584,9 +776,9 @@ __db_txnlist_lsnadd(dbenv, listp, lsnp, flags)
elp->u.l.lsn_array[0] = *lsnp;
/*
- * If we just added a new entry and there may be NULL
- * entries, so we have to do a complete bubble sort,
- * not just trickle a changed entry around.
+ * If we just added a new entry and there may be NULL entries, so we
+ * have to do a complete bubble sort, not just trickle a changed entry
+ * around.
*/
for (i = 0; i < (!LF_ISSET(TXNLIST_NEW) ? 1 : elp->u.l.ntxns); i++)
TXN_BUBBLE(elp->u.l.lsn_array, elp->u.l.ntxns);
@@ -597,35 +789,6 @@ __db_txnlist_lsnadd(dbenv, listp, lsnp, flags)
}
/*
- * __db_txnlist_lsnhead --
- * Return a pointer to the beginning of the lsn_array.
- *
- * PUBLIC: int __db_txnlist_lsnhead __P((void *, DB_LSN **));
- */
-int
-__db_txnlist_lsnhead(listp, lsnpp)
- void *listp;
- DB_LSN **lsnpp;
-{
- DB_TXNHEAD *hp;
- DB_TXNLIST *elp;
-
- hp = (DB_TXNHEAD *)listp;
-
- for (elp = LIST_FIRST(&hp->head);
- elp != NULL; elp = LIST_NEXT(elp, links))
- if (elp->type == TXNLIST_LSN)
- break;
-
- if (elp == NULL)
- return (EINVAL);
-
- *lsnpp = &elp->u.l.lsn_array[0];
-
- return (0);
-}
-
-/*
* __db_txnlist_lsninit --
* Initialize a transaction list with an lsn array entry.
*
@@ -642,12 +805,12 @@ __db_txnlist_lsninit(dbenv, hp, lsnp)
elp = NULL;
- if ((ret = __os_malloc(dbenv, sizeof(DB_TXNLIST), NULL, &elp)) != 0)
+ if ((ret = __os_malloc(dbenv, sizeof(DB_TXNLIST), &elp)) != 0)
goto err;
- LIST_INSERT_HEAD(&hp->head, elp, links);
+ LIST_INSERT_HEAD(&hp->head[0], elp, links);
if ((ret = __os_malloc(dbenv,
- 12 * sizeof(DB_LSN), NULL, &elp->u.l.lsn_array)) != 0)
+ 12 * sizeof(DB_LSN), &elp->u.l.lsn_array)) != 0)
goto err;
elp->type = TXNLIST_LSN;
elp->u.l.maxn = 12;
@@ -662,8 +825,7 @@ err: __db_txnlist_end(dbenv, hp);
/*
* __db_add_limbo -- add pages to the limbo list.
- * Get the file information and call pgnoadd
- * for each page.
+ * Get the file information and call pgnoadd for each page.
*
* PUBLIC: int __db_add_limbo __P((DB_ENV *,
* PUBLIC: void *, int32_t, db_pgno_t, int32_t));
@@ -681,7 +843,7 @@ __db_add_limbo(dbenv, info, fileid, pgno, count)
int ret;
dblp = dbenv->lg_handle;
- if ((ret = __log_lid_to_fname(dblp, fileid, &fnp)) != 0)
+ if ((ret = __dbreg_id_to_fname(dblp, fileid, 0, &fnp)) != 0)
return (ret);
do {
@@ -698,201 +860,429 @@ __db_add_limbo(dbenv, info, fileid, pgno, count)
/*
* __db_do_the_limbo -- move pages from limbo to free.
*
- * If we are in recovery we add things to the free list without
- * logging becasue we want to incrementaly apply logs that
- * may be generated on another copy of this environment.
- * Otherwise we just call __db_free to put the pages on
- * the free list and log the activity.
+ * Limbo processing is what ensures that we correctly handle and
+ * recover from page allocations. During recovery, for each database,
+ * we process each in-question allocation, link them into the free list
+ * and then write out the new meta-data page that contains the pointer
+ * to the new beginning of the free list. On an abort, we use our
+ * standard __db_free mechanism in a compensating transaction which logs
+ * the specific modifications to the free list.
+ *
+ * If we run out of log space during an abort, then we can't write the
+ * compensating transaction, so we abandon the idea of a compenating
+ * transaction, and go back to processing how we do during recovery.
+ * The reason that this is not the norm is that it's expensive: it requires
+ * that we flush any database with an in-question allocation. Thus if
+ * a compensating transaction fails, we never try to restart it.
+ *
+ * Since files may be open and closed within transactions (in particular,
+ * the master database for subdatabases), we must be prepared to open
+ * files during this process. If there is a compensating transaction, we
+ * can open the files in that transaction. If this was an abort and there
+ * is no compensating transaction, then we've got to perform these opens
+ * in the context of the aborting transaction so that we do not deadlock.
+ * During recovery, there's no locking, so this isn't an issue.
*
- * PUBLIC: int __db_do_the_limbo __P((DB_ENV *, DB_TXNHEAD *));
+ * What you want to keep in mind when reading this is that there are two
+ * algorithms going on here: ctxn == NULL, then we're either in recovery
+ * or our compensating transaction has failed and we're doing the
+ * "create list and write meta-data page" algorithm. Otherwise, we're in
+ * an abort and doing the "use compensating transaction" algorithm.
+ *
+ * PUBLIC: int __db_do_the_limbo __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, DB_TXN *, DB_TXNHEAD *));
*/
int
-__db_do_the_limbo(dbenv, hp)
+__db_do_the_limbo(dbenv, ptxn, txn, hp)
DB_ENV *dbenv;
+ DB_TXN *ptxn, *txn;
DB_TXNHEAD *hp;
{
- DB *dbp;
- DBC *dbc;
- DBMETA *meta;
- DB_TXN *txn;
DB_TXNLIST *elp;
- PAGE *pagep;
- db_pgno_t last_pgno, pgno;
- int i, in_recover, put_page, ret, t_ret;
+ int h, ret;
- dbp = NULL;
- dbc = NULL;
- txn = NULL;
ret = 0;
+ /*
+ * The slots correspond to hash buckets. We've hashed the
+ * fileids into hash buckets and need to pick up all affected
+ * files. (There will only be a single slot for an abort.)
+ */
+ for (h = 0; h < hp->nslots; h++) {
+ if ((elp = LIST_FIRST(&hp->head[h])) == NULL)
+ continue;
+ if (ptxn != NULL) {
+ if ((ret =
+ __db_limbo_move(dbenv, ptxn, txn, elp)) != 0)
+ goto err;
+ } else if ((ret = __db_limbo_bucket(dbenv, txn, elp)) != 0)
+ goto err;
+ }
+
+err: if (ret != 0) {
+ __db_err(dbenv, "Fatal error in abort of an allocation");
+ ret = __db_panic(dbenv, ret);
+ }
- /* Are we in recovery? */
- in_recover = F_ISSET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ return (ret);
+}
- for (elp = LIST_FIRST(&hp->head);
- elp != NULL; elp = LIST_NEXT(elp, links)) {
+/* Limbo support routines. */
+
+/*
+ * __db_lock_move --
+ * Move a lock from child to parent.
+ */
+static int
+__db_lock_move(dbenv, fileid, pgno, mode, ptxn, txn)
+ DB_ENV *dbenv;
+ u_int8_t *fileid;
+ db_pgno_t pgno;
+ db_lockmode_t mode;
+ DB_TXN *ptxn, *txn;
+{
+ DBT lock_dbt;
+ DB_LOCK lock;
+ DB_LOCK_ILOCK lock_obj;
+ DB_LOCKREQ req;
+ int ret;
+
+ lock_obj.pgno = pgno;
+ memcpy(lock_obj.fileid, fileid, DB_FILE_ID_LEN);
+ lock_obj.type = DB_PAGE_LOCK;
+
+ memset(&lock_dbt, 0, sizeof(lock_dbt));
+ lock_dbt.data = &lock_obj;
+ lock_dbt.size = sizeof(lock_obj);
+
+ if ((ret = dbenv->lock_get(dbenv,
+ txn->txnid, 0, &lock_dbt, mode, &lock)) == 0) {
+ memset(&req, 0, sizeof(req));
+ req.lock = lock;
+ req.op = DB_LOCK_TRADE;
+
+ ret = dbenv->lock_vec(dbenv, ptxn->txnid, 0, &req, 1, NULL);
+ }
+ return (ret);
+}
+
+/*
+ * __db_limbo_move
+ * Move just the metapage lock to the parent.
+ */
+static int
+__db_limbo_move(dbenv, ptxn, txn, elp)
+ DB_ENV *dbenv;
+ DB_TXN *ptxn, *txn;
+ DB_TXNLIST *elp;
+{
+ int ret;
+
+ for (; elp != NULL; elp = LIST_NEXT(elp, links)) {
+ if (elp->type != TXNLIST_PGNO || elp->u.p.locked == 1)
+ continue;
+ if ((ret = __db_lock_move(dbenv, elp->u.p.uid,
+ PGNO_BASE_MD, DB_LOCK_WRITE, ptxn, txn)) != 0)
+ return (ret);
+ elp->u.p.locked = 1;
+ }
+
+ return (0);
+}
+/*
+ * __db_limbo_bucket
+ * Perform limbo processing for a single hash bucket in the txnlist.
+ * txn is the transaction aborting in the case of an abort and ctxn is the
+ * compensating transaction.
+ */
+
+#define T_RESTORED(txn) ((txn) != NULL && F_ISSET(txn, TXN_RESTORED))
+static int
+__db_limbo_bucket(dbenv, txn, elp)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB_TXNLIST *elp;
+{
+ DB *dbp;
+ DB_MPOOLFILE *mpf;
+ DBMETA *meta;
+ DB_TXN *ctxn, *t;
+ db_pgno_t last_pgno, pgno;
+ int dbp_created, in_retry, ret, t_ret;
+
+ ctxn = NULL;
+ in_retry = 0;
+ meta = NULL;
+ mpf = NULL;
+ ret = 0;
+ for (; elp != NULL; elp = LIST_NEXT(elp, links)) {
if (elp->type != TXNLIST_PGNO)
continue;
+retry: dbp_created = 0;
+
+ /*
+ * Pick the transaction in which to potentially
+ * log compensations.
+ */
+ if (!in_retry && !IS_RECOVERING(dbenv) && !T_RESTORED(txn)
+ && (ret = __txn_compensate_begin(dbenv, &ctxn)) != 0)
+ return (ret);
+
+ /*
+ * Either use the compensating transaction or
+ * the one passed in, which will be null if recovering.
+ */
+ t = ctxn == NULL ? txn : ctxn;
+
+ /* First try to get a dbp by fileid. */
+ ret = __dbreg_id_to_db(dbenv, t, &dbp, elp->u.p.fileid, 0);
+
+ /*
+ * File is being destroyed. No need to worry about
+ * dealing with recovery of allocations.
+ */
+ if (ret == DB_DELETED ||
+ (ret == 0 && F_ISSET(dbp, DB_AM_DISCARD)))
+ goto next;
- if (in_recover) {
+ if (ret != 0) {
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
goto err;
/*
- * It is ok if the file is nolonger there.
+ * This tells the system not to lock, which is always
+ * OK, whether this is an abort or recovery.
*/
+ F_SET(dbp, DB_AM_COMPENSATE);
+ dbp_created = 1;
+
+ /* It is ok if the file is nolonger there. */
dbp->type = DB_UNKNOWN;
- ret = __db_dbopen(dbp,
- elp->u.p.fname, 0, __db_omode("rw----"), 0);
+ ret = __db_dbopen(dbp, t, elp->u.p.fname, NULL,
+ DB_ODDFILESIZE, __db_omode("rw----"), PGNO_BASE_MD);
+ if (ret == ENOENT)
+ goto next;
+ }
+
+ /*
+ * Verify that we are opening the same file that we were
+ * referring to when we wrote this log record.
+ */
+ if (memcmp(elp->u.p.uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
+ goto next;
+
+ mpf = dbp->mpf;
+ last_pgno = PGNO_INVALID;
+
+ if (ctxn == NULL) {
+ pgno = PGNO_BASE_MD;
+ if ((ret =
+ mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+ goto err;
+ last_pgno = meta->free;
+ }
+
+ ret = __db_limbo_fix(dbp, ctxn, elp, &last_pgno, meta);
+ /*
+ * If we were doing compensating transactions, then we are
+ * going to hope this error was due to running out of space.
+ * We'll change modes (into the sync the file mode) and keep
+ * trying. If we weren't doing compensating transactions,
+ * then this is a real error and we're sunk.
+ */
+ if (ret != 0) {
+ if (ret == DB_RUNRECOVERY || ctxn == NULL)
+ goto err;
+ in_retry = 1;
+ goto retry;
+ }
+
+ if (ctxn != NULL) {
+ ret = ctxn->commit(ctxn, DB_TXN_NOSYNC);
+ ctxn = NULL;
+ if (ret != 0)
+ goto retry;
+ goto next;
+ }
+
+ /*
+ * This is where we handle the case where we're explicitly
+ * putting together a free list. We need to decide whether
+ * we have to write the meta-data page, and if we do, then
+ * we need to sync it as well.
+ */
+ if (last_pgno == meta->free) {
+ /* No change to page; just put the page back. */
+ if ((ret = mpf->put(mpf, meta, 0)) != 0)
+ goto err;
+ meta = NULL;
} else {
/*
- * If we are in transaction undo, then we know
- * the fileid is still correct.
+ * These changes are unlogged so we cannot have the
+ * metapage pointing at pages that are not on disk.
+ * Therefore, we flush the new free list, then update
+ * the metapage. We have to put the meta-data page
+ * first so that it isn't pinned when we try to sync.
*/
+ if (!IS_RECOVERING(dbenv) && !T_RESTORED(txn))
+ __db_err(dbenv, "Flushing free list to disk");
+ if ((ret = mpf->put(mpf, meta, 0)) != 0)
+ goto err;
+ meta = NULL;
+ dbp->sync(dbp, 0);
+ pgno = PGNO_BASE_MD;
if ((ret =
- __db_fileid_to_db(dbenv, &dbp,
- elp->u.p.fileid, 0)) != 0 && ret != DB_DELETED)
+ mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+ goto err;
+ meta->free = last_pgno;
+ if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
goto err;
- /* File is being destroyed. */
- if (F_ISSET(dbp, DB_AM_DISCARD))
- ret = DB_DELETED;
+ meta = NULL;
}
+
+next:
/*
- * Verify that we are opening the same file that we were
- * referring to when we wrote this log record.
+ * If we get here, either we have processed the list
+ * or the db file has been deleted or could no be opened.
*/
- if (ret == 0 &&
- memcmp(elp->u.p.uid, dbp->fileid, DB_FILE_ID_LEN) == 0) {
- last_pgno = PGNO_INVALID;
- if (in_recover) {
- pgno = PGNO_BASE_MD;
- if ((ret = memp_fget(dbp->mpf,
- &pgno, 0, (PAGE **)&meta)) != 0)
- goto err;
- last_pgno = meta->free;
- /*
- * Check to see if the head of the free
- * list is any of the pages we are about
- * to link in. We could have crashed
- * after linking them in and before writing
- * a checkpoint.
- * It may not be the last one since
- * any page may get reallocated before here.
- */
- if (last_pgno != PGNO_INVALID)
- for (i = 0; i < elp->u.p.nentries; i++)
- if (last_pgno
- == elp->u.p.pgno_array[i])
- goto done_it;
- }
+ if (ctxn != NULL &&
+ (t_ret = ctxn->abort(ctxn)) != 0 && ret == 0)
+ ret = t_ret;
- for (i = 0; i < elp->u.p.nentries; i++) {
- pgno = elp->u.p.pgno_array[i];
- if ((ret = memp_fget(dbp->mpf,
- &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
- goto err;
+ if (dbp_created &&
+ (t_ret = __db_close_i(dbp, txn, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ dbp = NULL;
+ __os_free(dbenv, elp->u.p.fname);
+ __os_free(dbenv, elp->u.p.pgno_array);
+ if (ret == ENOENT)
+ ret = 0;
+ else if (ret != 0)
+ goto err;
+ }
- put_page = 1;
- if (IS_ZERO_LSN(LSN(pagep))) {
- P_INIT(pagep, dbp->pgsize,
- pgno, PGNO_INVALID,
- last_pgno, 0, P_INVALID);
-
- if (in_recover) {
- LSN(pagep) = LSN(meta);
- last_pgno = pgno;
- } else {
- /*
- * Starting the transaction
- * is postponed until we know
- * we have something to do.
- */
- if (txn == NULL &&
- (ret = txn_begin(dbenv,
- NULL, &txn, 0)) != 0)
- goto err;
-
- if (dbc == NULL &&
- (ret = dbp->cursor(dbp,
- txn, &dbc, 0)) != 0)
- goto err;
- /* Turn off locking. */
- F_SET(dbc, DBC_COMPENSATE);
-
- /* __db_free puts the page. */
- if ((ret =
- __db_free(dbc, pagep)) != 0)
- goto err;
- put_page = 0;
- }
- }
+err: if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ return (ret);
+}
- if (put_page == 1 &&
- (ret = memp_fput(dbp->mpf,
- pagep, DB_MPOOL_DIRTY)) != 0)
- goto err;
- }
- if (in_recover) {
- if (last_pgno == meta->free) {
-done_it:
+/*
+ * __db_limbo_fix --
+ * Process a single limbo entry which describes all the page allocations
+ * for a single file.
+ */
+static int
+__db_limbo_fix(dbp, ctxn, elp, lastp, meta)
+ DB *dbp;
+ DB_TXN *ctxn;
+ DB_TXNLIST *elp;
+ db_pgno_t *lastp;
+ DBMETA *meta;
+{
+ DBC *dbc;
+ DB_MPOOLFILE *mpf;
+ PAGE *freep, *pagep;
+ db_pgno_t next, pgno;
+ int i, put_page, ret, t_ret;
+
+ /*
+ * Loop through the entries for this txnlist element and
+ * either link them into the free list or write a compensating
+ * record for each.
+ */
+ put_page = 0;
+ ret = 0;
+ mpf = dbp->mpf;
+ dbc = NULL;
+
+ for (i = 0; i < elp->u.p.nentries; i++) {
+ pgno = elp->u.p.pgno_array[i];
+
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto err;
+ put_page = 1;
+
+ if (IS_ZERO_LSN(LSN(pagep))) {
+ if (ctxn == NULL) {
+ /*
+ * If this is a fatal recovery which
+ * spans a previous crash this page may
+ * be on the free list already.
+ */
+ for (next = *lastp; next != 0; ) {
+ if (next == pgno)
+ break;
+ if ((ret = mpf->get(mpf,
+ &next, 0, &freep)) != 0)
+ goto err;
+ next = NEXT_PGNO(freep);
if ((ret =
- memp_fput(dbp->mpf, meta, 0)) != 0)
+ mpf->put(mpf, freep, 0)) != 0)
goto err;
- } else {
- /*
- * Flush the new free list then
- * update the metapage. This is
- * unlogged so we cannot have the
- * metapage pointing at pages that
- * are not on disk.
- */
- dbp->sync(dbp, 0);
- meta->free = last_pgno;
- if ((ret = memp_fput(dbp->mpf,
- meta, DB_MPOOL_DIRTY)) != 0)
+ }
+
+ if (next != pgno) {
+ P_INIT(pagep, dbp->pgsize, pgno,
+ PGNO_INVALID, *lastp, 0, P_INVALID);
+ LSN(pagep) = LSN(meta);
+ *lastp = pgno;
+ }
+ } else {
+ P_INIT(pagep, dbp->pgsize, pgno,
+ PGNO_INVALID, *lastp, 0, P_INVALID);
+ if (dbc == NULL && (ret =
+ dbp->cursor(dbp, ctxn, &dbc, 0)) != 0)
goto err;
+ /*
+ * If the dbp is compensating (because we
+ * opened it), the dbc will automatically be
+ * marked compensating, but in case we didn't
+ * do the open, we have to mark it explicitly.
+ */
+ F_SET(dbc, DBC_COMPENSATE);
+ ret = __db_free(dbc, pagep);
+ put_page = 0;
+ /*
+ * On any error, we hope that the error was
+ * caused due to running out of space, and we
+ * switch modes, doing the processing where we
+ * sync out files instead of doing compensating
+ * transactions. If this was a real error and
+ * not out of space, we assume that some other
+ * call will fail real soon.
+ */
+ if (ret != 0) {
+ /* Assume that this is out of space. */
+ (void)dbc->c_close(dbc);
+ dbc = NULL;
+ goto err;
}
}
- if (dbc != NULL && (ret = dbc->c_close(dbc)) != 0)
- goto err;
- dbc = NULL;
}
- if (in_recover && (t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
- ret = t_ret;
- dbp = NULL;
- __os_free(elp->u.p.fname, 0);
- __os_free(elp->u.p.pgno_array, 0);
- if (ret == ENOENT)
- ret = 0;
- else if (ret != 0)
+
+ if (put_page == 1) {
+ ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY);
+ put_page = 0;
+ }
+ if (ret != 0)
goto err;
}
- if (txn != NULL) {
- ret = txn_commit(txn, 0);
- txn = NULL;
- }
-err:
- if (dbc != NULL)
- (void)dbc->c_close(dbc);
- if (in_recover && dbp != NULL)
- (void)dbp->close(dbp, 0);
- if (txn != NULL)
- (void)txn_abort(txn);
+err: if (put_page &&
+ (t_ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ ret = t_ret;
+ if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
return (ret);
-
}
-#define DB_TXNLIST_MAX_PGNO 8 /* A nice even number. */
+#define DB_TXNLIST_MAX_PGNO 8 /* A nice even number. */
/*
* __db_txnlist_pgnoadd --
- * Find the txnlist entry for a file and add this pgno,
- * or add the list entry for the file and then add the pgno.
- *
- * PUBLIC: int __db_txnlist_pgnoadd __P((DB_ENV *, DB_TXNHEAD *,
- * PUBLIC: int32_t, u_int8_t [DB_FILE_ID_LEN], char *, db_pgno_t));
+ * Find the txnlist entry for a file and add this pgno, or add the list
+ * entry for the file and then add the pgno.
*/
-int
+static int
__db_txnlist_pgnoadd(dbenv, hp, fileid, uid, fname, pgno)
DB_ENV *dbenv;
DB_TXNHEAD *hp;
@@ -902,34 +1292,39 @@ __db_txnlist_pgnoadd(dbenv, hp, fileid, uid, fname, pgno)
db_pgno_t pgno;
{
DB_TXNLIST *elp;
+ u_int32_t hash;
int len, ret;
elp = NULL;
- if (__db_txnlist_find_internal(hp, TXNLIST_PGNO, 0, uid, &elp, 0) != 0) {
+ if (__db_txnlist_find_internal(dbenv, hp,
+ TXNLIST_PGNO, 0, uid, &elp, 0) != 0) {
if ((ret =
- __os_malloc(dbenv, sizeof(DB_TXNLIST), NULL, &elp)) != 0)
+ __os_malloc(dbenv, sizeof(DB_TXNLIST), &elp)) != 0)
goto err;
- LIST_INSERT_HEAD(&hp->head, elp, links);
+ memcpy(&hash, uid, sizeof(hash));
+ LIST_INSERT_HEAD(
+ &hp->head[DB_TXNLIST_MASK(hp, hash)], elp, links);
elp->u.p.fileid = fileid;
memcpy(elp->u.p.uid, uid, DB_FILE_ID_LEN);
- len = strlen(fname) + 1;
- if ((ret = __os_malloc(dbenv, len, NULL, &elp->u.p.fname)) != 0)
+ len = (int)strlen(fname) + 1;
+ if ((ret = __os_malloc(dbenv, len, &elp->u.p.fname)) != 0)
goto err;
memcpy(elp->u.p.fname, fname, len);
elp->u.p.maxentry = 0;
+ elp->u.p.locked = 0;
elp->type = TXNLIST_PGNO;
if ((ret = __os_malloc(dbenv,
- 8 * sizeof(db_pgno_t), NULL, &elp->u.p.pgno_array)) != 0)
+ 8 * sizeof(db_pgno_t), &elp->u.p.pgno_array)) != 0)
goto err;
elp->u.p.maxentry = DB_TXNLIST_MAX_PGNO;
elp->u.p.nentries = 0;
} else if (elp->u.p.nentries == elp->u.p.maxentry) {
elp->u.p.maxentry <<= 1;
if ((ret = __os_realloc(dbenv, elp->u.p.maxentry *
- sizeof(db_pgno_t), NULL, &elp->u.p.pgno_array)) != 0)
+ sizeof(db_pgno_t), &elp->u.p.pgno_array)) != 0)
goto err;
}
@@ -941,6 +1336,36 @@ err: __db_txnlist_end(dbenv, hp);
return (ret);
}
+/*
+ * __db_default_getpgnos --
+ * Fill in default getpgnos information for an application-specific
+ * log record.
+ */
+static int
+__db_default_getpgnos(dbenv, lsnp, summary)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+ void *summary;
+{
+ TXN_RECS *t;
+ int ret;
+
+ t = (TXN_RECS *)summary;
+
+ if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
+ return (ret);
+
+ t->array[t->npages].flags = LSN_PAGE_NOLOCK;
+ t->array[t->npages].lsn = *lsnp;
+ t->array[t->npages].fid = DB_LOGFILEID_INVALID;
+ memset(&t->array[t->npages].pgdesc, 0,
+ sizeof(t->array[t->npages].pgdesc));
+
+ t->npages++;
+
+ return (0);
+}
+
#ifdef DEBUG
/*
* __db_txnlist_print --
@@ -954,25 +1379,21 @@ __db_txnlist_print(listp)
{
DB_TXNHEAD *hp;
DB_TXNLIST *p;
+ int i;
+ char *stats[] = { "ok", "commit", "prepare", "abort", "notfound",
+ "ignore", "expected", "unexpected" };
hp = (DB_TXNHEAD *)listp;
printf("Maxid: %lu Generation: %lu\n",
(u_long)hp->maxid, (u_long)hp->generation);
- for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
+ for (i = 0; i < hp->nslots; i++)
+ for (p = LIST_FIRST(&hp->head[i]); p != NULL; p = LIST_NEXT(p, links)) {
switch (p->type) {
case TXNLIST_TXNID:
- printf("TXNID: %lu(%lu)\n",
- (u_long)p->u.t.txnid, (u_long)p->u.t.generation);
- break;
- case TXNLIST_DELETE:
- printf("FILE: %s id=%d ops=%d %s %s\n",
- p->u.d.fname, p->u.d.fileid, p->u.d.count,
- F_ISSET(&p->u.d, TXNLIST_FLAG_DELETED) ?
- "(deleted)" : "(missing)",
- F_ISSET(&p->u.d, TXNLIST_FLAG_CLOSED) ?
- "(closed)" : "(open)");
-
+ printf("TXNID: %lx(%lu): %s\n",
+ (u_long)p->u.t.txnid, (u_long)p->u.t.generation,
+ stats[p->u.t.status]);
break;
default:
printf("Unrecognized type: %d\n", p->type);
diff --git a/bdb/db/db_dup.c b/bdb/db/db_dup.c
index 6d8b2df9518..2d33d79153f 100644
--- a/bdb/db/db_dup.c
+++ b/bdb/db/db_dup.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_dup.c,v 11.18 2000/11/30 00:58:32 ubell Exp $";
+static const char revid[] = "$Id: db_dup.c,v 11.32 2002/08/08 03:57:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,12 +18,10 @@ static const char revid[] = "$Id: db_dup.c,v 11.18 2000/11/30 00:58:32 ubell Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "hash.h"
-#include "lock.h"
-#include "db_am.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/db_am.h"
/*
* __db_ditem --
@@ -39,19 +37,20 @@ __db_ditem(dbc, pagep, indx, nbytes)
{
DB *dbp;
DBT ldbt;
- db_indx_t cnt, offset;
+ db_indx_t cnt, *inp, offset;
int ret;
u_int8_t *from;
dbp = dbc->dbp;
- if (DB_LOGGING(dbc)) {
- ldbt.data = P_ENTRY(pagep, indx);
+ if (DBC_LOGGING(dbc)) {
+ ldbt.data = P_ENTRY(dbp, pagep, indx);
ldbt.size = nbytes;
- if ((ret = __db_addrem_log(dbp->dbenv, dbc->txn,
- &LSN(pagep), 0, DB_REM_DUP, dbp->log_fileid, PGNO(pagep),
+ if ((ret = __db_addrem_log(dbp, dbc->txn,
+ &LSN(pagep), 0, DB_REM_DUP, PGNO(pagep),
(u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0)
return (ret);
- }
+ } else
+ LSN_NOT_LOGGED(LSN(pagep));
/*
* If there's only a single item on the page, we don't have to
@@ -63,24 +62,26 @@ __db_ditem(dbc, pagep, indx, nbytes)
return (0);
}
+ inp = P_INP(dbp, pagep);
/*
* Pack the remaining key/data items at the end of the page. Use
* memmove(3), the regions may overlap.
*/
from = (u_int8_t *)pagep + HOFFSET(pagep);
- memmove(from + nbytes, from, pagep->inp[indx] - HOFFSET(pagep));
+ DB_ASSERT((int)inp[indx] - HOFFSET(pagep) >= 0);
+ memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep));
HOFFSET(pagep) += nbytes;
/* Adjust the indices' offsets. */
- offset = pagep->inp[indx];
+ offset = inp[indx];
for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt)
- if (pagep->inp[cnt] < offset)
- pagep->inp[cnt] += nbytes;
+ if (inp[cnt] < offset)
+ inp[cnt] += nbytes;
/* Shift the indices down. */
--NUM_ENT(pagep);
if (indx != NUM_ENT(pagep))
- memmove(&pagep->inp[indx], &pagep->inp[indx + 1],
+ memmove(&inp[indx], &inp[indx + 1],
sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
return (0);
@@ -104,11 +105,13 @@ __db_pitem(dbc, pagep, indx, nbytes, hdr, data)
DB *dbp;
BKEYDATA bk;
DBT thdr;
+ db_indx_t *inp;
int ret;
u_int8_t *p;
- if (nbytes > P_FREESPACE(pagep)) {
- DB_ASSERT(nbytes <= P_FREESPACE(pagep));
+ dbp = dbc->dbp;
+ if (nbytes > P_FREESPACE(dbp, pagep)) {
+ DB_ASSERT(nbytes <= P_FREESPACE(dbp, pagep));
return (EINVAL);
}
/*
@@ -128,12 +131,13 @@ __db_pitem(dbc, pagep, indx, nbytes, hdr, data)
* the passed in header sizes must be adjusted for the structure's
* placeholder for the trailing variable-length data field.
*/
- dbp = dbc->dbp;
- if (DB_LOGGING(dbc))
- if ((ret = __db_addrem_log(dbp->dbenv, dbc->txn,
- &LSN(pagep), 0, DB_ADD_DUP, dbp->log_fileid, PGNO(pagep),
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __db_addrem_log(dbp, dbc->txn,
+ &LSN(pagep), 0, DB_ADD_DUP, PGNO(pagep),
(u_int32_t)indx, nbytes, hdr, data, &LSN(pagep))) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(pagep));
if (hdr == NULL) {
B_TSET(bk.type, B_KEYDATA, 0);
@@ -143,16 +147,17 @@ __db_pitem(dbc, pagep, indx, nbytes, hdr, data)
thdr.size = SSZA(BKEYDATA, data);
hdr = &thdr;
}
+ inp = P_INP(dbp, pagep);
/* Adjust the index table, then put the item on the page. */
if (indx != NUM_ENT(pagep))
- memmove(&pagep->inp[indx + 1], &pagep->inp[indx],
+ memmove(&inp[indx + 1], &inp[indx],
sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
HOFFSET(pagep) -= nbytes;
- pagep->inp[indx] = HOFFSET(pagep);
+ inp[indx] = HOFFSET(pagep);
++NUM_ENT(pagep);
- p = P_ENTRY(pagep, indx);
+ p = P_ENTRY(dbp, pagep, indx);
memcpy(p, hdr->data, hdr->size);
if (data != NULL)
memcpy(p + hdr->size, data->data, data->size);
@@ -177,13 +182,16 @@ __db_relink(dbc, add_rem, pagep, new_next, needlock)
PAGE *np, *pp;
DB_LOCK npl, ppl;
DB_LSN *nlsnp, *plsnp, ret_lsn;
+ DB_MPOOLFILE *mpf;
int ret;
- ret = 0;
+ dbp = dbc->dbp;
np = pp = NULL;
- npl.off = ppl.off = LOCK_INVALID;
+ LOCK_INIT(npl);
+ LOCK_INIT(ppl);
nlsnp = plsnp = NULL;
- dbp = dbc->dbp;
+ mpf = dbp->mpf;
+ ret = 0;
/*
* Retrieve and lock the one/two pages. For a remove, we may need
@@ -194,9 +202,8 @@ __db_relink(dbc, add_rem, pagep, new_next, needlock)
if (needlock && (ret = __db_lget(dbc,
0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf,
- &pagep->next_pgno, 0, &np)) != 0) {
- (void)__db_pgerr(dbp, pagep->next_pgno);
+ if ((ret = mpf->get(mpf, &pagep->next_pgno, 0, &np)) != 0) {
+ __db_pgerr(dbp, pagep->next_pgno, ret);
goto err;
}
nlsnp = &np->lsn;
@@ -205,28 +212,27 @@ __db_relink(dbc, add_rem, pagep, new_next, needlock)
if (needlock && (ret = __db_lget(dbc,
0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf,
- &pagep->prev_pgno, 0, &pp)) != 0) {
- (void)__db_pgerr(dbp, pagep->next_pgno);
+ if ((ret = mpf->get(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
+ __db_pgerr(dbp, pagep->next_pgno, ret);
goto err;
}
plsnp = &pp->lsn;
}
/* Log the change. */
- if (DB_LOGGING(dbc)) {
- if ((ret = __db_relink_log(dbp->dbenv, dbc->txn,
- &ret_lsn, 0, add_rem, dbp->log_fileid,
- pagep->pgno, &pagep->lsn,
- pagep->prev_pgno, plsnp, pagep->next_pgno, nlsnp)) != 0)
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __db_relink_log(dbp, dbc->txn, &ret_lsn, 0, add_rem,
+ pagep->pgno, &pagep->lsn, pagep->prev_pgno, plsnp,
+ pagep->next_pgno, nlsnp)) != 0)
goto err;
- if (np != NULL)
- np->lsn = ret_lsn;
- if (pp != NULL)
- pp->lsn = ret_lsn;
- if (add_rem == DB_REM_PAGE)
- pagep->lsn = ret_lsn;
- }
+ } else
+ LSN_NOT_LOGGED(ret_lsn);
+ if (np != NULL)
+ np->lsn = ret_lsn;
+ if (pp != NULL)
+ pp->lsn = ret_lsn;
+ if (add_rem == DB_REM_PAGE)
+ pagep->lsn = ret_lsn;
/*
* Modify and release the two pages.
@@ -242,10 +248,10 @@ __db_relink(dbc, add_rem, pagep, new_next, needlock)
else
np->prev_pgno = pagep->prev_pgno;
if (new_next == NULL)
- ret = memp_fput(dbp->mpf, np, DB_MPOOL_DIRTY);
+ ret = mpf->put(mpf, np, DB_MPOOL_DIRTY);
else {
*new_next = np;
- ret = memp_fset(dbp->mpf, np, DB_MPOOL_DIRTY);
+ ret = mpf->set(mpf, np, DB_MPOOL_DIRTY);
}
if (ret != 0)
goto err;
@@ -256,7 +262,7 @@ __db_relink(dbc, add_rem, pagep, new_next, needlock)
if (pp != NULL) {
pp->next_pgno = pagep->next_pgno;
- if ((ret = memp_fput(dbp->mpf, pp, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
goto err;
if (needlock)
(void)__TLPUT(dbc, ppl);
@@ -264,12 +270,12 @@ __db_relink(dbc, add_rem, pagep, new_next, needlock)
return (0);
err: if (np != NULL)
- (void)memp_fput(dbp->mpf, np, 0);
- if (needlock && npl.off != LOCK_INVALID)
+ (void)mpf->put(mpf, np, 0);
+ if (needlock)
(void)__TLPUT(dbc, npl);
if (pp != NULL)
- (void)memp_fput(dbp->mpf, pp, 0);
- if (needlock && ppl.off != LOCK_INVALID)
+ (void)mpf->put(mpf, pp, 0);
+ if (needlock)
(void)__TLPUT(dbc, ppl);
return (ret);
}
diff --git a/bdb/db/db_iface.c b/bdb/db/db_iface.c
index 3548a2527bb..b518c3b14b2 100644
--- a/bdb/db/db_iface.c
+++ b/bdb/db/db_iface.c
@@ -1,55 +1,69 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_iface.c,v 11.34 2001/01/11 18:19:51 bostic Exp $";
+static const char revid[] = "$Id: db_iface.c,v 11.77 2002/08/08 03:57:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-
-#include <errno.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
static int __db_curinval __P((const DB_ENV *));
+static int __db_fnl __P((const DB_ENV *, const char *));
static int __db_rdonly __P((const DB_ENV *, const char *));
static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));
/*
+ * A database should be required to be readonly if it's been explicitly
+ * specified as such or if we're a client in a replicated environment and
+ * we don't have the special "client-writer" designation.
+ */
+#define IS_READONLY(dbp) \
+ (F_ISSET(dbp, DB_AM_RDONLY) || \
+ (F_ISSET((dbp)->dbenv, DB_ENV_REP_CLIENT) && \
+ !F_ISSET((dbp), DB_AM_CL_WRITER)))
+
+/*
* __db_cursorchk --
* Common cursor argument checking routine.
*
- * PUBLIC: int __db_cursorchk __P((const DB *, u_int32_t, int));
+ * PUBLIC: int __db_cursorchk __P((const DB *, u_int32_t));
*/
int
-__db_cursorchk(dbp, flags, isrdonly)
+__db_cursorchk(dbp, flags)
const DB *dbp;
u_int32_t flags;
- int isrdonly;
{
+ /* DB_DIRTY_READ is the only valid bit-flag and requires locking. */
+ if (LF_ISSET(DB_DIRTY_READ)) {
+ if (!LOCKING_ON(dbp->dbenv))
+ return (__db_fnl(dbp->dbenv, "DB->cursor"));
+ LF_CLR(DB_DIRTY_READ);
+ }
+
/* Check for invalid function flags. */
switch (flags) {
case 0:
break;
case DB_WRITECURSOR:
- if (isrdonly)
+ if (IS_READONLY(dbp))
return (__db_rdonly(dbp->dbenv, "DB->cursor"));
if (!CDB_LOCKING(dbp->dbenv))
return (__db_ferr(dbp->dbenv, "DB->cursor", 0));
break;
case DB_WRITELOCK:
- if (isrdonly)
+ if (IS_READONLY(dbp))
return (__db_rdonly(dbp->dbenv, "DB->cursor"));
break;
default:
@@ -90,22 +104,25 @@ __db_ccountchk(dbp, flags, isvalid)
* __db_cdelchk --
* Common cursor delete argument checking routine.
*
- * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int, int));
+ * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int));
*/
int
-__db_cdelchk(dbp, flags, isrdonly, isvalid)
+__db_cdelchk(dbp, flags, isvalid)
const DB *dbp;
u_int32_t flags;
- int isrdonly, isvalid;
+ int isvalid;
{
/* Check for changes to a read-only tree. */
- if (isrdonly)
+ if (IS_READONLY(dbp))
return (__db_rdonly(dbp->dbenv, "c_del"));
/* Check for invalid function flags. */
switch (flags) {
case 0:
break;
+ case DB_UPDATE_SECONDARY:
+ DB_ASSERT(F_ISSET(dbp, DB_AM_SECONDARY));
+ break;
default:
return (__db_ferr(dbp->dbenv, "DBcursor->c_del", 0));
}
@@ -130,7 +147,7 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
u_int32_t flags;
int isvalid;
{
- int ret;
+ int dirty, multi, ret;
/*
* Check for read-modify-write validity. DB_RMW doesn't make sense
@@ -140,44 +157,68 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
* If this changes, confirm that DB does not itself set the DB_RMW
* flag in a path where CDB may have been configured.
*/
- if (LF_ISSET(DB_RMW)) {
- if (!LOCKING_ON(dbp->dbenv)) {
- __db_err(dbp->dbenv,
- "the DB_RMW flag requires locking");
- return (EINVAL);
- }
- LF_CLR(DB_RMW);
+ dirty = 0;
+ if (LF_ISSET(DB_DIRTY_READ | DB_RMW)) {
+ if (!LOCKING_ON(dbp->dbenv))
+ return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
+ if (LF_ISSET(DB_DIRTY_READ))
+ dirty = 1;
+ LF_CLR(DB_DIRTY_READ | DB_RMW);
+ }
+
+ multi = 0;
+ if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
+ multi = 1;
+ if (LF_ISSET(DB_MULTIPLE) && LF_ISSET(DB_MULTIPLE_KEY))
+ goto multi_err;
+ LF_CLR(DB_MULTIPLE | DB_MULTIPLE_KEY);
}
/* Check for invalid function flags. */
switch (flags) {
case DB_CONSUME:
case DB_CONSUME_WAIT:
+ if (dirty) {
+ __db_err(dbp->dbenv,
+ "DB_DIRTY_READ is not supported with DB_CONSUME or DB_CONSUME_WAIT");
+ return (EINVAL);
+ }
if (dbp->type != DB_QUEUE)
goto err;
break;
case DB_CURRENT:
case DB_FIRST:
case DB_GET_BOTH:
- case DB_LAST:
+ case DB_GET_BOTH_RANGE:
case DB_NEXT:
case DB_NEXT_DUP:
case DB_NEXT_NODUP:
- case DB_PREV:
- case DB_PREV_NODUP:
case DB_SET:
case DB_SET_RANGE:
break;
+ case DB_LAST:
+ case DB_PREV:
+ case DB_PREV_NODUP:
+ if (multi)
+multi_err: return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 1));
+ break;
case DB_GET_BOTHC:
if (dbp->type == DB_QUEUE)
goto err;
break;
case DB_GET_RECNO:
- if (!F_ISSET(dbp, DB_BT_RECNUM))
+ /*
+ * The one situation in which this might be legal with a
+ * non-RECNUM dbp is if dbp is a secondary and its primary is
+ * DB_AM_RECNUM.
+ */
+ if (!F_ISSET(dbp, DB_AM_RECNUM) &&
+ (!F_ISSET(dbp, DB_AM_SECONDARY) ||
+ !F_ISSET(dbp->s_primary, DB_AM_RECNUM)))
goto err;
break;
case DB_SET_RECNO:
- if (!F_ISSET(dbp, DB_BT_RECNUM))
+ if (!F_ISSET(dbp, DB_AM_RECNUM))
goto err;
break;
default:
@@ -190,11 +231,24 @@ err: return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
return (ret);
+ if (multi && !F_ISSET(data, DB_DBT_USERMEM)) {
+ __db_err(dbp->dbenv,
+ "DB_MULTIPLE(_KEY) requires that DB_DBT_USERMEM be set");
+ return (EINVAL);
+ }
+ if (multi &&
+ (F_ISSET(key, DB_DBT_PARTIAL) || F_ISSET(data, DB_DBT_PARTIAL))) {
+ __db_err(dbp->dbenv,
+ "DB_DBT_PARTIAL forbidden with DB_MULTIPLE(_KEY)");
+ return (EINVAL);
+ }
+
/*
- * The cursor must be initialized for DB_CURRENT or DB_NEXT_DUP,
- * return EINVAL for an invalid cursor, otherwise 0.
+ * The cursor must be initialized for DB_CURRENT, DB_GET_RECNO and
+ * DB_NEXT_DUP. Return EINVAL for an invalid cursor, otherwise 0.
*/
- if (isvalid || (flags != DB_CURRENT && flags != DB_NEXT_DUP))
+ if (isvalid || (flags != DB_CURRENT &&
+ flags != DB_GET_RECNO && flags != DB_NEXT_DUP))
return (0);
return (__db_curinval(dbp->dbenv));
@@ -205,24 +259,35 @@ err: return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
* Common cursor put argument checking routine.
*
* PUBLIC: int __db_cputchk __P((const DB *,
- * PUBLIC: const DBT *, DBT *, u_int32_t, int, int));
+ * PUBLIC: const DBT *, DBT *, u_int32_t, int));
*/
int
-__db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
+__db_cputchk(dbp, key, data, flags, isvalid)
const DB *dbp;
const DBT *key;
DBT *data;
u_int32_t flags;
- int isrdonly, isvalid;
+ int isvalid;
{
int key_flags, ret;
key_flags = 0;
/* Check for changes to a read-only tree. */
- if (isrdonly)
+ if (IS_READONLY(dbp))
return (__db_rdonly(dbp->dbenv, "c_put"));
+ /* Check for puts on a secondary. */
+ if (F_ISSET(dbp, DB_AM_SECONDARY)) {
+ if (flags == DB_UPDATE_SECONDARY)
+ flags = DB_KEYLAST;
+ else {
+ __db_err(dbp->dbenv,
+ "DBcursor->c_put forbidden on secondary indices");
+ return (EINVAL);
+ }
+ }
+
/* Check for invalid function flags. */
switch (flags) {
case DB_AFTER:
@@ -238,7 +303,7 @@ __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
case DB_QUEUE: /* Not permitted. */
goto err;
case DB_RECNO: /* Only with mutable record numbers. */
- if (!F_ISSET(dbp, DB_RE_RENUMBER))
+ if (!F_ISSET(dbp, DB_AM_RENUMBER))
goto err;
key_flags = 1;
break;
@@ -259,8 +324,6 @@ __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
/* FALLTHROUGH */
case DB_KEYFIRST:
case DB_KEYLAST:
- if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO)
- goto err;
key_flags = 1;
break;
default:
@@ -285,48 +348,153 @@ err: return (__db_ferr(dbp->dbenv, "DBcursor->c_put", 0));
}
/*
- * __db_closechk --
- * DB->close flag check.
+ * __db_pgetchk --
+ * DB->pget flag check.
*
- * PUBLIC: int __db_closechk __P((const DB *, u_int32_t));
+ * PUBLIC: int __db_pgetchk __P((const DB *, const DBT *, DBT *, DBT *,
+ * PUBLIC: u_int32_t));
*/
int
-__db_closechk(dbp, flags)
+__db_pgetchk(dbp, skey, pkey, data, flags)
const DB *dbp;
+ const DBT *skey;
+ DBT *pkey, *data;
u_int32_t flags;
{
- /* Check for invalid function flags. */
+ int ret;
+ u_int32_t save_flags;
+
+ save_flags = flags;
+
+ if (!F_ISSET(dbp, DB_AM_SECONDARY)) {
+ __db_err(dbp->dbenv,
+ "DB->pget may only be used on secondary indices");
+ return (EINVAL);
+ }
+
+ if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
+ __db_err(dbp->dbenv,
+ "DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices");
+ return (EINVAL);
+ }
+
+ /* DB_CONSUME makes no sense on a secondary index. */
+ LF_CLR(DB_RMW);
switch (flags) {
- case 0:
- case DB_NOSYNC:
+ case DB_CONSUME:
+ case DB_CONSUME_WAIT:
+ return (__db_ferr(dbp->dbenv, "DB->pget", 0));
+ default:
+ /* __db_getchk will catch the rest. */
+ break;
+ }
+
+ /*
+ * We allow the pkey field to be NULL, so that we can make the
+ * two-DBT get calls into wrappers for the three-DBT ones.
+ */
+ if (pkey != NULL &&
+ (ret = __dbt_ferr(dbp, "primary key", pkey, 1)) != 0)
+ return (ret);
+
+ /* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */
+ if (pkey == NULL && flags == DB_GET_BOTH) {
+ __db_err(dbp->dbenv,
+ "DB_GET_BOTH on a secondary index requires a primary key");
+ return (EINVAL);
+ }
+
+ return (__db_getchk(dbp, skey, data, save_flags));
+}
+
+/*
+ * __db_cpgetchk --
+ * Secondary-index cursor get argument checking routine.
+ *
+ * PUBLIC: int __db_cpgetchk __P((const DB *,
+ * PUBLIC: DBT *, DBT *, DBT *, u_int32_t, int));
+ */
+int
+__db_cpgetchk(dbp, skey, pkey, data, flags, isvalid)
+ const DB *dbp;
+ DBT *skey, *pkey, *data;
+ u_int32_t flags;
+ int isvalid;
+{
+ int ret;
+ u_int32_t save_flags;
+
+ save_flags = flags;
+
+ if (!F_ISSET(dbp, DB_AM_SECONDARY)) {
+ __db_err(dbp->dbenv,
+ "DBcursor->c_pget may only be used on secondary indices");
+ return (EINVAL);
+ }
+
+ if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
+ __db_err(dbp->dbenv,
+ "DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices");
+ return (EINVAL);
+ }
+
+ LF_CLR(DB_RMW);
+ switch (flags) {
+ case DB_CONSUME:
+ case DB_CONSUME_WAIT:
+ /* DB_CONSUME makes no sense on a secondary index. */
+ return (__db_ferr(dbp->dbenv, "DBcursor->c_pget", 0));
+ case DB_GET_BOTH:
+ /* DB_GET_BOTH is "get both the primary and the secondary". */
+ if (pkey == NULL) {
+ __db_err(dbp->dbenv,
+ "DB_GET_BOTH requires both a secondary and a primary key");
+ return (EINVAL);
+ }
break;
default:
- return (__db_ferr(dbp->dbenv, "DB->close", 0));
+ /* __db_cgetchk will catch the rest. */
+ break;
}
- return (0);
+ /*
+ * We allow the pkey field to be NULL, so that we can make the
+ * two-DBT get calls into wrappers for the three-DBT ones.
+ */
+ if (pkey != NULL &&
+ (ret = __dbt_ferr(dbp, "primary key", pkey, 0)) != 0)
+ return (ret);
+
+ /* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */
+ if (pkey == NULL && flags == DB_GET_BOTH) {
+ __db_err(dbp->dbenv,
+ "DB_GET_BOTH on a secondary index requires a primary key");
+ return (EINVAL);
+ }
+
+ return (__db_cgetchk(dbp, skey, data, save_flags, isvalid));
}
/*
* __db_delchk --
* Common delete argument checking routine.
*
- * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
+ * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t));
*/
int
-__db_delchk(dbp, key, flags, isrdonly)
+__db_delchk(dbp, key, flags)
const DB *dbp;
DBT *key;
u_int32_t flags;
- int isrdonly;
{
COMPQUIET(key, NULL);
/* Check for changes to a read-only tree. */
- if (isrdonly)
+ if (IS_READONLY(dbp))
return (__db_rdonly(dbp->dbenv, "delete"));
/* Check for invalid function flags. */
+ LF_CLR(DB_AUTO_COMMIT);
switch (flags) {
case 0:
break;
@@ -350,7 +518,7 @@ __db_getchk(dbp, key, data, flags)
DBT *data;
u_int32_t flags;
{
- int ret;
+ int dirty, multi, ret;
/*
* Check for read-modify-write validity. DB_RMW doesn't make sense
@@ -360,13 +528,21 @@ __db_getchk(dbp, key, data, flags)
* If this changes, confirm that DB does not itself set the DB_RMW
* flag in a path where CDB may have been configured.
*/
- if (LF_ISSET(DB_RMW)) {
- if (!LOCKING_ON(dbp->dbenv)) {
- __db_err(dbp->dbenv,
- "the DB_RMW flag requires locking");
- return (EINVAL);
- }
- LF_CLR(DB_RMW);
+ dirty = 0;
+ if (LF_ISSET(DB_DIRTY_READ | DB_RMW)) {
+ if (!LOCKING_ON(dbp->dbenv))
+ return (__db_fnl(dbp->dbenv, "DB->get"));
+ if (LF_ISSET(DB_DIRTY_READ))
+ dirty = 1;
+ LF_CLR(DB_DIRTY_READ | DB_RMW);
+ }
+
+ multi = 0;
+ if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
+ if (LF_ISSET(DB_MULTIPLE_KEY))
+ goto multi_err;
+ multi = LF_ISSET(DB_MULTIPLE) ? 1 : 0;
+ LF_CLR(DB_MULTIPLE);
}
/* Check for invalid function flags. */
@@ -375,24 +551,48 @@ __db_getchk(dbp, key, data, flags)
case DB_GET_BOTH:
break;
case DB_SET_RECNO:
- if (!F_ISSET(dbp, DB_BT_RECNUM))
+ if (!F_ISSET(dbp, DB_AM_RECNUM))
goto err;
break;
case DB_CONSUME:
case DB_CONSUME_WAIT:
+ if (dirty) {
+ __db_err(dbp->dbenv,
+ "DB_DIRTY_READ is not supported with DB_CONSUME or DB_CONSUME_WAIT");
+ return (EINVAL);
+ }
+ if (multi)
+multi_err: return (__db_ferr(dbp->dbenv, "DB->get", 1));
if (dbp->type == DB_QUEUE)
break;
- /* Fall through */
+ /* FALLTHROUGH */
default:
err: return (__db_ferr(dbp->dbenv, "DB->get", 0));
}
- /* Check for invalid key/data flags. */
+ /*
+ * Check for invalid key/data flags.
+ *
+ * XXX: Dave Krinsky
+ * Remember to modify this when we fix the flag-returning problem.
+ */
if ((ret = __dbt_ferr(dbp, "key", key, flags == DB_SET_RECNO)) != 0)
return (ret);
if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0)
return (ret);
+ if (multi && !F_ISSET(data, DB_DBT_USERMEM)) {
+ __db_err(dbp->dbenv,
+ "DB_MULTIPLE requires that DB_DBT_USERMEM be set");
+ return (EINVAL);
+ }
+ if (multi &&
+ (F_ISSET(key, DB_DBT_PARTIAL) || F_ISSET(data, DB_DBT_PARTIAL))) {
+ __db_err(dbp->dbenv,
+ "DB_DBT_PARTIAL forbidden with DB_MULTIPLE(_KEY)");
+ return (EINVAL);
+ }
+
return (0);
}
@@ -449,13 +649,11 @@ __db_joingetchk(dbp, key, flags)
u_int32_t flags;
{
- if (LF_ISSET(DB_RMW)) {
- if (!LOCKING_ON(dbp->dbenv)) {
- __db_err(dbp->dbenv,
- "the DB_RMW flag requires locking");
- return (EINVAL);
- }
- LF_CLR(DB_RMW);
+ if (LF_ISSET(DB_DIRTY_READ | DB_RMW)) {
+ if (!LOCKING_ON(dbp->dbenv))
+ return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
+
+ LF_CLR(DB_DIRTY_READ | DB_RMW);
}
switch (flags) {
@@ -491,23 +689,32 @@ __db_joingetchk(dbp, key, flags)
* Common put argument checking routine.
*
* PUBLIC: int __db_putchk
- * PUBLIC: __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
+ * PUBLIC: __P((const DB *, DBT *, const DBT *, u_int32_t, int));
*/
int
-__db_putchk(dbp, key, data, flags, isrdonly, isdup)
+__db_putchk(dbp, key, data, flags, isdup)
const DB *dbp;
DBT *key;
const DBT *data;
u_int32_t flags;
- int isrdonly, isdup;
+ int isdup;
{
- int ret;
+ int ret, returnkey;
+
+ returnkey = 0;
/* Check for changes to a read-only tree. */
- if (isrdonly)
+ if (IS_READONLY(dbp))
return (__db_rdonly(dbp->dbenv, "put"));
+ /* Check for puts on a secondary. */
+ if (F_ISSET(dbp, DB_AM_SECONDARY)) {
+ __db_err(dbp->dbenv, "DB->put forbidden on secondary indices");
+ return (EINVAL);
+ }
+
/* Check for invalid function flags. */
+ LF_CLR(DB_AUTO_COMMIT);
switch (flags) {
case 0:
case DB_NOOVERWRITE:
@@ -515,6 +722,7 @@ __db_putchk(dbp, key, data, flags, isrdonly, isdup)
case DB_APPEND:
if (dbp->type != DB_RECNO && dbp->type != DB_QUEUE)
goto err;
+ returnkey = 1;
break;
case DB_NODUPDATA:
if (F_ISSET(dbp, DB_AM_DUPSORT))
@@ -525,7 +733,7 @@ err: return (__db_ferr(dbp->dbenv, "DB->put", 0));
}
/* Check for invalid key/data flags. */
- if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
+ if ((ret = __dbt_ferr(dbp, "key", key, returnkey)) != 0)
return (ret);
if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
return (ret);
@@ -541,28 +749,6 @@ err: return (__db_ferr(dbp->dbenv, "DB->put", 0));
}
/*
- * __db_removechk --
- * DB->remove flag check.
- *
- * PUBLIC: int __db_removechk __P((const DB *, u_int32_t));
- */
-int
-__db_removechk(dbp, flags)
- const DB *dbp;
- u_int32_t flags;
-{
- /* Check for invalid function flags. */
- switch (flags) {
- case 0:
- break;
- default:
- return (__db_ferr(dbp->dbenv, "DB->remove", 0));
- }
-
- return (0);
-}
-
-/*
* __db_statchk --
* Common stat argument checking routine.
*
@@ -576,12 +762,13 @@ __db_statchk(dbp, flags)
/* Check for invalid function flags. */
switch (flags) {
case 0:
- case DB_CACHED_COUNTS:
+ case DB_FAST_STAT:
+ case DB_CACHED_COUNTS: /* Deprecated and undocumented. */
break;
- case DB_RECORDCOUNT:
+ case DB_RECORDCOUNT: /* Deprecated and undocumented. */
if (dbp->type == DB_RECNO)
break;
- if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_BT_RECNUM))
+ if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))
break;
goto err;
default:
@@ -636,9 +823,9 @@ __dbt_ferr(dbp, name, dbt, check_thread)
* database and then specify that same DBT as a key to a primary
* database, without having to clear flags.
*/
- if ((ret = __db_fchk(dbenv, name, dbt->flags,
- DB_DBT_MALLOC | DB_DBT_DUPOK |
- DB_DBT_REALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL)) != 0)
+ if ((ret = __db_fchk(dbenv, name, dbt->flags, DB_DBT_APPMALLOC |
+ DB_DBT_MALLOC | DB_DBT_DUPOK | DB_DBT_REALLOC | DB_DBT_USERMEM |
+ DB_DBT_PARTIAL)) != 0)
return (ret);
switch (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)) {
case 0:
@@ -674,6 +861,20 @@ __db_rdonly(dbenv, name)
}
/*
+ * __db_fnl --
+ * Common flag-needs-locking message.
+ */
+static int
+__db_fnl(dbenv, name)
+ const DB_ENV *dbenv;
+ const char *name;
+{
+ __db_err(dbenv,
+ "%s: the DB_DIRTY_READ and DB_RMW flags require locking", name);
+ return (EINVAL);
+}
+
+/*
* __db_curinval
* Report that a cursor is in an invalid state.
*/
@@ -685,3 +886,98 @@ __db_curinval(dbenv)
"Cursor position must be set before performing this operation");
return (EINVAL);
}
+
+/*
+ * __db_secondary_corrupt --
+ * Report that a secondary index appears corrupt, as it has a record
+ * that does not correspond to a record in the primary.
+ *
+ * PUBLIC: int __db_secondary_corrupt __P((DB *));
+ */
+int
+__db_secondary_corrupt(dbp)
+ DB *dbp;
+{
+
+ __db_err(dbp->dbenv,
+ "Secondary index corrupt: item in secondary not found in primary");
+ return (DB_SECONDARY_BAD);
+}
+
+/*
+ * __db_associatechk --
+ * Argument checking routine for DB->associate().
+ *
+ * PUBLIC: int __db_associatechk __P((DB *, DB *,
+ * PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));
+ */
+int
+__db_associatechk(dbp, sdbp, callback, flags)
+ DB *dbp, *sdbp;
+ int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+
+ dbenv = dbp->dbenv;
+
+ if (F_ISSET(sdbp, DB_AM_SECONDARY)) {
+ __db_err(dbenv,
+ "Secondary index handles may not be re-associated");
+ return (EINVAL);
+ }
+ if (F_ISSET(dbp, DB_AM_SECONDARY)) {
+ __db_err(dbenv,
+ "Secondary indices may not be used as primary databases");
+ return (EINVAL);
+ }
+ if (F_ISSET(dbp, DB_AM_DUP)) {
+ __db_err(dbenv,
+ "Primary databases may not be configured with duplicates");
+ return (EINVAL);
+ }
+ if (F_ISSET(dbp, DB_AM_RENUMBER)) {
+ __db_err(dbenv,
+ "Renumbering recno databases may not be used as primary databases");
+ return (EINVAL);
+ }
+ if (callback == NULL &&
+ (!F_ISSET(dbp, DB_AM_RDONLY) || !F_ISSET(sdbp, DB_AM_RDONLY))) {
+ __db_err(dbenv,
+ "Callback function may be NULL only when database handles are read-only");
+ return (EINVAL);
+ }
+
+ return (__db_fchk(dbenv,
+ "DB->associate", flags, DB_CREATE | DB_AUTO_COMMIT));
+}
+
+/*
+ * __db_txn_auto --
+ * Handle DB_AUTO_COMMIT initialization.
+ *
+ * PUBLIC: int __db_txn_auto __P((DB *, DB_TXN **));
+ */
+int
+__db_txn_auto(dbp, txnidp)
+ DB *dbp;
+ DB_TXN **txnidp;
+{
+ DB_ENV *dbenv;
+
+ dbenv = dbp->dbenv;
+
+ if (*txnidp != NULL) {
+ __db_err(dbenv,
+ "DB_AUTO_COMMIT may not be specified along with a transaction handle");
+ return (EINVAL);
+ }
+
+ if (!TXN_ON(dbenv)) {
+ __db_err(dbenv,
+ "DB_AUTO_COMMIT may not be specified in non-transactional environment");
+ return (EINVAL);
+ }
+
+ return (dbenv->txn_begin(dbenv, NULL, txnidp, 0));
+}
diff --git a/bdb/db/db_join.c b/bdb/db/db_join.c
index 881dedde0fc..6281b1a8383 100644
--- a/bdb/db/db_join.c
+++ b/bdb/db/db_join.c
@@ -1,14 +1,14 @@
-/*-
+/*
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_join.c,v 11.31 2000/12/20 22:41:54 krinsky Exp $";
+static const char revid[] = "$Id: db_join.c,v 11.55 2002/08/08 03:57:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,16 +19,17 @@ static const char revid[] = "$Id: db_join.c,v 11.31 2000/12/20 22:41:54 krinsky
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_join.h"
-#include "db_am.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_join.h"
+#include "dbinc/btree.h"
static int __db_join_close __P((DBC *));
static int __db_join_cmp __P((const void *, const void *));
static int __db_join_del __P((DBC *, u_int32_t));
static int __db_join_get __P((DBC *, DBT *, DBT *, u_int32_t));
-static int __db_join_getnext __P((DBC *, DBT *, DBT *, u_int32_t));
+static int __db_join_getnext __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t));
+static int __db_join_primget __P((DB *,
+ DB_TXN *, u_int32_t, DBT *, DBT *, u_int32_t));
static int __db_join_put __P((DBC *, DBT *, DBT *, u_int32_t));
/*
@@ -84,7 +85,8 @@ __db_join(primary, curslist, dbcp, flags)
DBC *dbc;
JOIN_CURSOR *jc;
int ret;
- u_int32_t i, ncurs, nslots;
+ u_int32_t i;
+ size_t ncurs, nslots;
COMPQUIET(nslots, 0);
@@ -104,11 +106,13 @@ __db_join(primary, curslist, dbcp, flags)
1, sizeof(JOIN_CURSOR), &jc)) != 0)
goto err;
- if ((ret = __os_malloc(dbenv, 256, NULL, &jc->j_key.data)) != 0)
+ if ((ret = __os_malloc(dbenv, 256, &jc->j_key.data)) != 0)
goto err;
jc->j_key.ulen = 256;
F_SET(&jc->j_key, DB_DBT_USERMEM);
+ F_SET(&jc->j_rdata, DB_DBT_REALLOC);
+
for (jc->j_curslist = curslist;
*jc->j_curslist != NULL; jc->j_curslist++)
;
@@ -184,7 +188,7 @@ __db_join(primary, curslist, dbcp, flags)
jc->j_fdupcurs[i] = NULL;
jc->j_exhausted[i] = 0;
}
- jc->j_ncurs = ncurs;
+ jc->j_ncurs = (u_int32_t)ncurs;
/*
* If DB_JOIN_NOSORT is not set, optimize secondary cursors by
@@ -226,20 +230,20 @@ __db_join(primary, curslist, dbcp, flags)
err: if (jc != NULL) {
if (jc->j_curslist != NULL)
- __os_free(jc->j_curslist, nslots * sizeof(DBC *));
+ __os_free(dbenv, jc->j_curslist);
if (jc->j_workcurs != NULL) {
if (jc->j_workcurs[0] != NULL)
- __os_free(jc->j_workcurs[0], sizeof(DBC));
- __os_free(jc->j_workcurs, nslots * sizeof(DBC *));
+ __os_free(dbenv, jc->j_workcurs[0]);
+ __os_free(dbenv, jc->j_workcurs);
}
if (jc->j_fdupcurs != NULL)
- __os_free(jc->j_fdupcurs, nslots * sizeof(DBC *));
+ __os_free(dbenv, jc->j_fdupcurs);
if (jc->j_exhausted != NULL)
- __os_free(jc->j_exhausted, nslots * sizeof(u_int8_t));
- __os_free(jc, sizeof(JOIN_CURSOR));
+ __os_free(dbenv, jc->j_exhausted);
+ __os_free(dbenv, jc);
}
if (dbc != NULL)
- __os_free(dbc, sizeof(DBC));
+ __os_free(dbenv, dbc);
return (ret);
}
@@ -279,8 +283,8 @@ __db_join_get(dbc, key_arg, data_arg, flags)
DB *dbp;
DBC *cp;
JOIN_CURSOR *jc;
- int ret;
- u_int32_t i, j, operation;
+ int db_manage_data, ret;
+ u_int32_t i, j, operation, opmods;
dbp = dbc->dbp;
jc = (JOIN_CURSOR *)dbc->internal;
@@ -289,6 +293,12 @@ __db_join_get(dbc, key_arg, data_arg, flags)
operation = LF_ISSET(DB_OPFLAGS_MASK);
+ /* !!!
+ * If the set of flags here changes, check that __db_join_primget
+ * is updated to handle them properly.
+ */
+ opmods = LF_ISSET(DB_RMW | DB_DIRTY_READ);
+
if ((ret = __db_joingetchk(dbp, key_arg, flags)) != 0)
return (ret);
@@ -319,13 +329,14 @@ __db_join_get(dbc, key_arg, data_arg, flags)
goto samekey;
F_CLR(jc, JOIN_RETRY);
-retry: ret = jc->j_workcurs[0]->c_get(jc->j_workcurs[0],
- &jc->j_key, key_n, jc->j_exhausted[0] ? DB_NEXT_DUP : DB_CURRENT);
+retry: ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
+ &jc->j_key, key_n,
+ opmods | (jc->j_exhausted[0] ? DB_NEXT_DUP : DB_CURRENT));
if (ret == ENOMEM) {
jc->j_key.ulen <<= 1;
if ((ret = __os_realloc(dbp->dbenv,
- jc->j_key.ulen, NULL, &jc->j_key.data)) != 0)
+ jc->j_key.ulen, &jc->j_key.data)) != 0)
goto mem_err;
goto retry;
}
@@ -379,7 +390,7 @@ retry: ret = jc->j_workcurs[0]->c_get(jc->j_workcurs[0],
retry2: cp = jc->j_workcurs[i];
if ((ret = __db_join_getnext(cp, &jc->j_key, key_n,
- jc->j_exhausted[i])) == DB_NOTFOUND) {
+ jc->j_exhausted[i], opmods)) == DB_NOTFOUND) {
/*
* jc->j_workcurs[i] has no more of the datum we're
* interested in. Go back one cursor and get
@@ -475,7 +486,7 @@ retry2: cp = jc->j_workcurs[i];
if (ret == ENOMEM) {
jc->j_key.ulen <<= 1;
if ((ret = __os_realloc(dbp->dbenv, jc->j_key.ulen,
- NULL, &jc->j_key.data)) != 0) {
+ &jc->j_key.data)) != 0) {
mem_err: __db_err(dbp->dbenv,
"Allocation failed for join key, len = %lu",
(u_long)jc->j_key.ulen);
@@ -523,8 +534,8 @@ samekey: /*
* Get the key we tried and failed to return last time;
* it should be the current datum of all the secondary cursors.
*/
- if ((ret = jc->j_workcurs[0]->c_get(jc->j_workcurs[0],
- &jc->j_key, key_n, DB_CURRENT)) != 0)
+ if ((ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
+ &jc->j_key, key_n, DB_CURRENT | opmods)) != 0)
return (ret);
F_CLR(jc, JOIN_RETRY);
}
@@ -532,36 +543,28 @@ samekey: /*
/*
* ret == 0; we have a key to return.
*
- * If DB_DBT_USERMEM or DB_DBT_MALLOC is set, we need to
- * copy it back into the dbt we were given for the key;
- * call __db_retcopy.
- *
- * Otherwise, assert that we do not in fact need to copy anything
- * and simply proceed.
+ * If DB_DBT_USERMEM or DB_DBT_MALLOC is set, we need to copy the key
+ * back into the dbt we were given for the key; call __db_retcopy.
+ * Otherwise, assert that we do not need to copy anything and proceed.
*/
- if (F_ISSET(key_arg, DB_DBT_USERMEM) ||
- F_ISSET(key_arg, DB_DBT_MALLOC)) {
+ DB_ASSERT(F_ISSET(
+ key_arg, DB_DBT_USERMEM | DB_DBT_MALLOC) || key_n == key_arg);
+
+ if (F_ISSET(key_arg, DB_DBT_USERMEM | DB_DBT_MALLOC) &&
+ (ret = __db_retcopy(dbp->dbenv,
+ key_arg, key_n->data, key_n->size, NULL, NULL)) != 0) {
/*
- * We need to copy the key back into our original
- * datum. Do so.
+ * The retcopy failed, most commonly because we have a user
+ * buffer for the key which is too small. Set things up to
+ * retry next time, and return.
*/
- if ((ret = __db_retcopy(dbp,
- key_arg, key_n->data, key_n->size, NULL, NULL)) != 0) {
- /*
- * The retcopy failed, most commonly because we
- * have a user buffer for the key which is too small.
- * Set things up to retry next time, and return.
- */
- F_SET(jc, JOIN_RETRY);
- return (ret);
- }
- } else
- DB_ASSERT(key_n == key_arg);
+ F_SET(jc, JOIN_RETRY);
+ return (ret);
+ }
/*
- * If DB_JOIN_ITEM is
- * set, we return it; otherwise we do the lookup in the
- * primary and then return.
+ * If DB_JOIN_ITEM is set, we return it; otherwise we do the lookup
+ * in the primary and then return.
*
* Note that we use key_arg here; it is safe (and appropriate)
* to do so.
@@ -569,14 +572,45 @@ samekey: /*
if (operation == DB_JOIN_ITEM)
return (0);
- if ((ret = jc->j_primary->get(jc->j_primary,
- jc->j_curslist[0]->txn, key_arg, data_arg, 0)) != 0)
- /*
- * The get on the primary failed, most commonly because we're
- * using a user buffer that's not big enough. Flag our
- * failure so we can return the same key next time.
- */
- F_SET(jc, JOIN_RETRY);
+ /*
+ * If data_arg->flags == 0--that is, if DB is managing the
+ * data DBT's memory--it's not safe to just pass the DBT
+ * through to the primary get call, since we don't want that
+ * memory to belong to the primary DB handle (and if the primary
+ * is free-threaded, it can't anyway).
+ *
+ * Instead, use memory that is managed by the join cursor, in
+ * jc->j_rdata.
+ */
+ if (!F_ISSET(data_arg, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM))
+ db_manage_data = 1;
+ else
+ db_manage_data = 0;
+ if ((ret = __db_join_primget(jc->j_primary,
+ jc->j_curslist[0]->txn, jc->j_curslist[0]->locker, key_arg,
+ db_manage_data ? &jc->j_rdata : data_arg, opmods)) != 0) {
+ if (ret == DB_NOTFOUND)
+ /*
+ * If ret == DB_NOTFOUND, the primary and secondary
+ * are out of sync; every item in each secondary
+ * should correspond to something in the primary,
+ * or we shouldn't have done the join this way.
+ * Wail.
+ */
+ ret = __db_secondary_corrupt(jc->j_primary);
+ else
+ /*
+ * The get on the primary failed for some other
+ * reason, most commonly because we're using a user
+ * buffer that's not big enough. Flag our failure
+ * so we can return the same key next time.
+ */
+ F_SET(jc, JOIN_RETRY);
+ }
+ if (db_manage_data && ret == 0) {
+ data_arg->data = jc->j_rdata.data;
+ data_arg->size = jc->j_rdata.size;
+ }
return (ret);
}
@@ -586,12 +620,14 @@ __db_join_close(dbc)
DBC *dbc;
{
DB *dbp;
+ DB_ENV *dbenv;
JOIN_CURSOR *jc;
int ret, t_ret;
u_int32_t i;
jc = (JOIN_CURSOR *)dbc->internal;
dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
ret = t_ret = 0;
/*
@@ -599,11 +635,11 @@ __db_join_close(dbc)
* must happen before any action that can fail and return, or else
* __db_close may loop indefinitely.
*/
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
TAILQ_REMOVE(&dbp->join_queue, dbc, links);
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
- PANIC_CHECK(dbc->dbp->dbenv);
+ PANIC_CHECK(dbenv);
/*
* Close any open scratch cursors. In each case, there may
@@ -625,13 +661,15 @@ __db_join_close(dbc)
ret = t_ret;
}
- __os_free(jc->j_exhausted, 0);
- __os_free(jc->j_curslist, 0);
- __os_free(jc->j_workcurs, 0);
- __os_free(jc->j_fdupcurs, 0);
- __os_free(jc->j_key.data, jc->j_key.ulen);
- __os_free(jc, sizeof(JOIN_CURSOR));
- __os_free(dbc, sizeof(DBC));
+ __os_free(dbenv, jc->j_exhausted);
+ __os_free(dbenv, jc->j_curslist);
+ __os_free(dbenv, jc->j_workcurs);
+ __os_free(dbenv, jc->j_fdupcurs);
+ __os_free(dbenv, jc->j_key.data);
+ if (jc->j_rdata.data != NULL)
+ __os_ufree(dbenv, jc->j_rdata.data);
+ __os_free(dbenv, jc);
+ __os_free(dbenv, dbc);
return (ret);
}
@@ -652,10 +690,10 @@ __db_join_close(dbc)
* If no matching datum exists, returns DB_NOTFOUND, else 0.
*/
static int
-__db_join_getnext(dbc, key, data, exhausted)
+__db_join_getnext(dbc, key, data, exhausted, opmods)
DBC *dbc;
DBT *key, *data;
- u_int32_t exhausted;
+ u_int32_t exhausted, opmods;
{
int ret, cmp;
DB *dbp;
@@ -667,10 +705,14 @@ __db_join_getnext(dbc, key, data, exhausted)
switch (exhausted) {
case 0:
+ /*
+ * We don't want to step on data->data; use a new
+ * DBT and malloc so we don't step on dbc's rdata memory.
+ */
memset(&ldata, 0, sizeof(DBT));
- /* We don't want to step on data->data; malloc. */
F_SET(&ldata, DB_DBT_MALLOC);
- if ((ret = dbc->c_get(dbc, key, &ldata, DB_CURRENT)) != 0)
+ if ((ret = dbc->c_real_get(dbc,
+ key, &ldata, opmods | DB_CURRENT)) != 0)
break;
cmp = func(dbp, data, &ldata);
if (cmp == 0) {
@@ -679,10 +721,10 @@ __db_join_getnext(dbc, key, data, exhausted)
* it into data, then free the buffer we malloc'ed
* above.
*/
- if ((ret = __db_retcopy(dbp, data, ldata.data,
+ if ((ret = __db_retcopy(dbp->dbenv, data, ldata.data,
ldata.size, &data->data, &data->size)) != 0)
return (ret);
- __os_free(ldata.data, 0);
+ __os_ufree(dbp->dbenv, ldata.data);
return (0);
}
@@ -691,10 +733,10 @@ __db_join_getnext(dbc, key, data, exhausted)
* dups. We just forget about ldata and free
* its buffer--data contains the value we're searching for.
*/
- __os_free(ldata.data, 0);
+ __os_ufree(dbp->dbenv, ldata.data);
/* FALLTHROUGH */
case 1:
- ret = dbc->c_get(dbc, key, data, DB_GET_BOTHC);
+ ret = dbc->c_real_get(dbc, key, data, opmods | DB_GET_BOTHC);
break;
default:
ret = EINVAL;
@@ -708,7 +750,6 @@ __db_join_getnext(dbc, key, data, exhausted)
* __db_join_cmp --
* Comparison function for sorting DBCs in cardinality order.
*/
-
static int
__db_join_cmp(a, b)
const void *a, *b;
@@ -728,3 +769,54 @@ __db_join_cmp(a, b)
return (counta - countb);
}
+
+/*
+ * __db_join_primget --
+ * Perform a DB->get in the primary, being careful not to use a new
+ * locker ID if we're doing CDB locking.
+ */
+static int
+__db_join_primget(dbp, txn, lockerid, key, data, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ u_int32_t lockerid;
+ DBT *key, *data;
+ u_int32_t flags;
+{
+ DBC *dbc;
+ int dirty, ret, rmw, t_ret;
+
+ /*
+ * The only allowable flags here are the two flags copied into
+ * "opmods" in __db_join_get, DB_RMW and DB_DIRTY_READ. The former
+ * is an op on the c_get call, the latter on the cursor call.
+ * It's a DB bug if we allow any other flags down in here.
+ */
+ rmw = LF_ISSET(DB_RMW);
+ dirty = LF_ISSET(DB_DIRTY_READ);
+ LF_CLR(DB_RMW | DB_DIRTY_READ);
+ DB_ASSERT(flags == 0);
+
+ if ((ret = __db_icursor(dbp,
+ txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
+ return (ret);
+
+ if (dirty ||
+ (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
+ F_SET(dbc, DBC_DIRTY_READ);
+ F_SET(dbc, DBC_TRANSIENT);
+
+ /*
+ * This shouldn't be necessary, thanks to the fact that join cursors
+ * swap in their own DB_DBT_REALLOC'ed buffers, but just for form's
+ * sake, we mirror what __db_get does.
+ */
+ SET_RET_MEM(dbc, dbp);
+
+ ret = dbc->c_get(dbc, key, data, DB_SET | rmw);
+
+ if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
diff --git a/bdb/db/db_meta.c b/bdb/db/db_meta.c
index 5b57c369454..015ef5c8fc7 100644
--- a/bdb/db/db_meta.c
+++ b/bdb/db/db_meta.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_meta.c,v 11.26 2001/01/16 21:57:19 ubell Exp $";
+static const char revid[] = "$Id: db_meta.c,v 11.61 2002/08/08 03:57:48 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -53,12 +53,37 @@ static const char revid[] = "$Id: db_meta.c,v 11.26 2001/01/16 21:57:19 ubell Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "txn.h"
-#include "db_am.h"
-#include "btree.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/db_am.h"
+
+static void __db_init_meta __P((void *, u_int32_t, db_pgno_t, u_int32_t));
+
+/*
+ * __db_init_meta --
+ * Helper function for __db_new that initializes the important fields in
+ * a meta-data page (used instead of P_INIT). We need to make sure that we
+ * retain the page number and LSN of the existing page.
+ */
+static void
+__db_init_meta(p, pgsize, pgno, pgtype)
+ void *p;
+ u_int32_t pgsize;
+ db_pgno_t pgno;
+ u_int32_t pgtype;
+{
+ DB_LSN save_lsn;
+ DBMETA *meta;
+
+ meta = (DBMETA *)p;
+ save_lsn = meta->lsn;
+ memset(meta, 0, sizeof(DBMETA));
+ meta->lsn = save_lsn;
+ meta->pagesize = pgsize;
+ meta->pgno = pgno;
+ meta->type = (u_int8_t)pgtype;
+}
/*
* __db_new --
@@ -75,60 +100,110 @@ __db_new(dbc, type, pagepp)
DBMETA *meta;
DB *dbp;
DB_LOCK metalock;
+ DB_LSN lsn;
+ DB_MPOOLFILE *mpf;
PAGE *h;
- db_pgno_t pgno;
- int ret;
+ db_pgno_t pgno, newnext;
+ int meta_flags, extend, ret;
- dbp = dbc->dbp;
meta = NULL;
+ meta_flags = 0;
+ dbp = dbc->dbp;
+ mpf = dbp->mpf;
h = NULL;
+ newnext = PGNO_INVALID;
pgno = PGNO_BASE_MD;
if ((ret = __db_lget(dbc,
LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
goto err;
-
if (meta->free == PGNO_INVALID) {
- if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
- goto err;
- ZERO_LSN(h->lsn);
- h->pgno = pgno;
+ pgno = meta->last_pgno + 1;
+ ZERO_LSN(lsn);
+ extend = 1;
} else {
pgno = meta->free;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
- meta->free = h->next_pgno;
- (void)memp_fset(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
+
+ /*
+ * We want to take the first page off the free list and
+ * then set meta->free to the that page's next_pgno, but
+ * we need to log the change first.
+ */
+ newnext = h->next_pgno;
+ lsn = h->lsn;
+ extend = 0;
}
- DB_ASSERT(TYPE(h) == P_INVALID);
+ /*
+ * Log the allocation before fetching the new page. If we
+ * don't have room in the log then we don't want to tell
+ * mpool to extend the file.
+ */
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __db_pg_alloc_log(dbp, dbc->txn, &LSN(meta), 0,
+ &LSN(meta), PGNO_BASE_MD, &lsn, pgno,
+ (u_int32_t)type, newnext)) != 0)
+ goto err;
+ } else
+ LSN_NOT_LOGGED(LSN(meta));
- if (TYPE(h) != P_INVALID)
- return (__db_panic(dbp->dbenv, EINVAL));
+ meta_flags = DB_MPOOL_DIRTY;
+ meta->free = newnext;
- /* Log the change. */
- if (DB_LOGGING(dbc)) {
- if ((ret = __db_pg_alloc_log(dbp->dbenv,
- dbc->txn, &LSN(meta), 0, dbp->log_fileid,
- &LSN(meta), &h->lsn, h->pgno,
- (u_int32_t)type, meta->free)) != 0)
+ if (extend == 1) {
+ meta->last_pgno++;
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
goto err;
- LSN(h) = LSN(meta);
+ ZERO_LSN(h->lsn);
+ h->pgno = pgno;
+ DB_ASSERT(pgno == meta->last_pgno);
}
+ LSN(h) = LSN(meta);
+
+ DB_ASSERT(TYPE(h) == P_INVALID);
+
+ if (TYPE(h) != P_INVALID)
+ return (__db_panic(dbp->dbenv, EINVAL));
- (void)memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
(void)__TLPUT(dbc, metalock);
- P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, PGNO_INVALID, 0, type);
+ switch (type) {
+ case P_BTREEMETA:
+ case P_HASHMETA:
+ case P_QAMMETA:
+ __db_init_meta(h, dbp->pgsize, h->pgno, type);
+ break;
+ default:
+ P_INIT(h, dbp->pgsize,
+ h->pgno, PGNO_INVALID, PGNO_INVALID, 0, type);
+ break;
+ }
+
+ /*
+ * If dirty reads are enabled and we are in a transaction, we could
+ * abort this allocation after the page(s) pointing to this
+ * one have their locks downgraded. This would permit dirty readers
+ * to access this page which is ok, but they must be off the
+ * page when we abort. This will also prevent updates happening
+ * to this page until we commit.
+ */
+ if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && dbc->txn != NULL) {
+ if ((ret = __db_lget(dbc, 0,
+ h->pgno, DB_LOCK_WWRITE, 0, &metalock)) != 0)
+ goto err;
+ }
*pagepp = h;
return (0);
err: if (h != NULL)
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
if (meta != NULL)
- (void)memp_fput(dbp->mpf, meta, 0);
+ (void)mpf->put(mpf, meta, meta_flags);
(void)__TLPUT(dbc, metalock);
return (ret);
}
@@ -148,11 +223,13 @@ __db_free(dbc, h)
DB *dbp;
DBT ldbt;
DB_LOCK metalock;
+ DB_MPOOLFILE *mpf;
db_pgno_t pgno;
u_int32_t dirty_flag;
int ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
/*
* Retrieve the metadata page and insert the page at the head of
@@ -163,43 +240,44 @@ __db_free(dbc, h)
dirty_flag = 0;
pgno = PGNO_BASE_MD;
if ((ret = __db_lget(dbc,
- LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
+ LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) {
+ if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0) {
(void)__TLPUT(dbc, metalock);
goto err;
}
DB_ASSERT(h->pgno != meta->free);
/* Log the change. */
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
memset(&ldbt, 0, sizeof(ldbt));
ldbt.data = h;
- ldbt.size = P_OVERHEAD;
- if ((ret = __db_pg_free_log(dbp->dbenv,
- dbc->txn, &LSN(meta), 0, dbp->log_fileid, h->pgno,
- &LSN(meta), &ldbt, meta->free)) != 0) {
- (void)memp_fput(dbp->mpf, (PAGE *)meta, 0);
+ ldbt.size = P_OVERHEAD(dbp);
+ if ((ret = __db_pg_free_log(dbp,
+ dbc->txn, &LSN(meta), 0, h->pgno,
+ &LSN(meta), PGNO_BASE_MD, &ldbt, meta->free)) != 0) {
+ (void)mpf->put(mpf, (PAGE *)meta, 0);
(void)__TLPUT(dbc, metalock);
- return (ret);
+ goto err;
}
- LSN(h) = LSN(meta);
- }
+ } else
+ LSN_NOT_LOGGED(LSN(meta));
+ LSN(h) = LSN(meta);
P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
meta->free = h->pgno;
/* Discard the metadata page. */
- if ((t_ret = memp_fput(dbp->mpf,
- (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
ret = t_ret;
/* Discard the caller's page reference. */
dirty_flag = DB_MPOOL_DIRTY;
-err: if ((t_ret = memp_fput(dbp->mpf, h, dirty_flag)) != 0 && ret == 0)
+err: if ((t_ret = mpf->put(mpf, h, dirty_flag)) != 0 && ret == 0)
ret = t_ret;
/*
@@ -227,44 +305,63 @@ __db_lprint(dbc)
if (LOCKING_ON(dbp->dbenv)) {
req.op = DB_LOCK_DUMP;
- lock_vec(dbp->dbenv, dbc->locker, 0, &req, 1, NULL);
+ dbp->dbenv->lock_vec(dbp->dbenv, dbc->locker, 0, &req, 1, NULL);
}
return (0);
}
#endif
/*
+ * Implement the rules for transactional locking. We can release the previous
+ * lock if we are not in a transaction or COUPLE_ALWAYS is specifed (used in
+ * record locking). If we are doing dirty reads then we can release read locks
+ * and down grade write locks.
+ */
+#define DB_PUT_ACTION(dbc, action, lockp) \
+ (((action == LCK_COUPLE || action == LCK_COUPLE_ALWAYS) && \
+ LOCK_ISSET(*lockp)) ? \
+ (dbc->txn == NULL || action == LCK_COUPLE_ALWAYS || \
+ (F_ISSET(dbc, DBC_DIRTY_READ) && \
+ (lockp)->mode == DB_LOCK_DIRTY)) ? LCK_COUPLE : \
+ (F_ISSET((dbc)->dbp, DB_AM_DIRTY) && \
+ (lockp)->mode == DB_LOCK_WRITE) ? LCK_DOWNGRADE : 0 : 0)
+
+/*
* __db_lget --
* The standard lock get call.
*
* PUBLIC: int __db_lget __P((DBC *,
- * PUBLIC: int, db_pgno_t, db_lockmode_t, int, DB_LOCK *));
+ * PUBLIC: int, db_pgno_t, db_lockmode_t, u_int32_t, DB_LOCK *));
*/
int
-__db_lget(dbc, flags, pgno, mode, lkflags, lockp)
+__db_lget(dbc, action, pgno, mode, lkflags, lockp)
DBC *dbc;
- int flags, lkflags;
+ int action;
db_pgno_t pgno;
db_lockmode_t mode;
+ u_int32_t lkflags;
DB_LOCK *lockp;
{
DB *dbp;
DB_ENV *dbenv;
DB_LOCKREQ couple[2], *reqp;
- int ret;
+ DB_TXN *txn;
+ int has_timeout, ret;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
+ txn = dbc->txn;
/*
* We do not always check if we're configured for locking before
* calling __db_lget to acquire the lock.
*/
- if (CDB_LOCKING(dbenv)
- || !LOCKING_ON(dbenv) || F_ISSET(dbc, DBC_COMPENSATE)
- || (!LF_ISSET(LCK_ROLLBACK) && F_ISSET(dbc, DBC_RECOVER))
- || (!LF_ISSET(LCK_ALWAYS) && F_ISSET(dbc, DBC_OPD))) {
- lockp->off = LOCK_INVALID;
+ if (CDB_LOCKING(dbenv) ||
+ !LOCKING_ON(dbenv) || F_ISSET(dbc, DBC_COMPENSATE) ||
+ (F_ISSET(dbc, DBC_RECOVER) &&
+ (action != LCK_ROLLBACK || F_ISSET(dbenv, DB_ENV_REP_CLIENT))) ||
+ (action != LCK_ALWAYS && F_ISSET(dbc, DBC_OPD))) {
+ LOCK_INIT(*lockp);
return (0);
}
@@ -282,27 +379,73 @@ __db_lget(dbc, flags, pgno, mode, lkflags, lockp)
if (DB_NONBLOCK(dbc))
lkflags |= DB_LOCK_NOWAIT;
- /*
- * If the object not currently locked, acquire the lock and return,
- * otherwise, lock couple.
- */
- if (LF_ISSET(LCK_COUPLE)) {
- couple[0].op = DB_LOCK_GET;
+ if (F_ISSET(dbc, DBC_DIRTY_READ) && mode == DB_LOCK_READ)
+ mode = DB_LOCK_DIRTY;
+
+ has_timeout = txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT);
+
+ switch (DB_PUT_ACTION(dbc, action, lockp)) {
+ case LCK_COUPLE:
+lck_couple: couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
couple[0].obj = &dbc->lock_dbt;
couple[0].mode = mode;
- couple[1].op = DB_LOCK_PUT;
- couple[1].lock = *lockp;
+ if (action == LCK_COUPLE_ALWAYS)
+ action = LCK_COUPLE;
+ UMRW_SET(couple[0].timeout);
+ if (has_timeout)
+ couple[0].timeout = txn->lock_timeout;
+ if (action == LCK_COUPLE) {
+ couple[1].op = DB_LOCK_PUT;
+ couple[1].lock = *lockp;
+ }
- ret = lock_vec(dbenv,
- dbc->locker, lkflags, couple, 2, &reqp);
+ ret = dbenv->lock_vec(dbenv, dbc->locker,
+ lkflags, couple, action == LCK_COUPLE ? 2 : 1, &reqp);
if (ret == 0 || reqp == &couple[1])
*lockp = couple[0].lock;
- } else {
- ret = lock_get(dbenv,
+ break;
+ case LCK_DOWNGRADE:
+ if ((ret = dbenv->lock_downgrade(
+ dbenv, lockp, DB_LOCK_WWRITE, 0)) != 0)
+ return (ret);
+ /* FALL THROUGH */
+ default:
+ if (has_timeout)
+ goto lck_couple;
+ ret = dbenv->lock_get(dbenv,
dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * __db_lput --
+ * The standard lock put call.
+ *
+ * PUBLIC: int __db_lput __P((DBC *, DB_LOCK *));
+ */
+int
+__db_lput(dbc, lockp)
+ DBC *dbc;
+ DB_LOCK *lockp;
+{
+ DB_ENV *dbenv;
+ int ret;
- if (ret != 0)
- lockp->off = LOCK_INVALID;
+ dbenv = dbc->dbp->dbenv;
+
+ switch (DB_PUT_ACTION(dbc, LCK_COUPLE, lockp)) {
+ case LCK_COUPLE:
+ ret = dbenv->lock_put(dbenv, lockp);
+ break;
+ case LCK_DOWNGRADE:
+ ret = __lock_downgrade(dbenv, lockp, DB_LOCK_WWRITE, 0);
+ break;
+ default:
+ ret = 0;
+ break;
}
return (ret);
diff --git a/bdb/db/db_method.c b/bdb/db/db_method.c
index 01568a6e144..14712180df0 100644
--- a/bdb/db/db_method.c
+++ b/bdb/db/db_method.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_method.c,v 11.36 2000/12/21 09:17:04 krinsky Exp $";
+static const char revid[] = "$Id: db_method.c,v 11.78 2002/07/02 19:26:55 sue Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -21,50 +21,56 @@ static const char revid[] = "$Id: db_method.c,v 11.36 2000/12/21 09:17:04 krinsk
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
-#include "xa.h"
-#include "xa_ext.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/qam.h"
+#include "dbinc/xa.h"
+#include "dbinc_auto/xa_ext.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
#endif
-static int __db_get_byteswapped __P((DB *));
-static DBTYPE
- __db_get_type __P((DB *));
+static int __db_get_byteswapped __P((DB *, int *));
+static int __db_get_type __P((DB *, DBTYPE *dbtype));
static int __db_init __P((DB *, u_int32_t));
static int __db_key_range
__P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
+static int __db_set_alloc __P((DB *, void *(*)(size_t),
+ void *(*)(void *, size_t), void (*)(void *)));
static int __db_set_append_recno __P((DB *, int (*)(DB *, DBT *, db_recno_t)));
static int __db_set_cachesize __P((DB *, u_int32_t, u_int32_t, int));
+static int __db_set_cache_priority __P((DB *, DB_CACHE_PRIORITY));
static int __db_set_dup_compare
__P((DB *, int (*)(DB *, const DBT *, const DBT *)));
-static void __db_set_errcall __P((DB *, void (*)(const char *, char *)));
-static void __db_set_errfile __P((DB *, FILE *));
+static int __db_set_encrypt __P((DB *, const char *, u_int32_t));
static int __db_set_feedback __P((DB *, void (*)(DB *, int, int)));
static int __db_set_flags __P((DB *, u_int32_t));
-static int __db_set_lorder __P((DB *, int));
-static int __db_set_malloc __P((DB *, void *(*)(size_t)));
static int __db_set_pagesize __P((DB *, u_int32_t));
-static int __db_set_realloc __P((DB *, void *(*)(void *, size_t)));
-static void __db_set_errpfx __P((DB *, const char *));
static int __db_set_paniccall __P((DB *, void (*)(DB_ENV *, int)));
+static void __db_set_errcall __P((DB *, void (*)(const char *, char *)));
+static void __db_set_errfile __P((DB *, FILE *));
+static void __db_set_errpfx __P((DB *, const char *));
+static int __db_stat_fail __P((DB *, void *, u_int32_t));
static void __dbh_err __P((DB *, int, const char *, ...));
static void __dbh_errx __P((DB *, const char *, ...));
+#ifdef HAVE_RPC
+static int __dbcl_init __P((DB *, DB_ENV *, u_int32_t));
+#endif
+
/*
* db_create --
* DB constructor.
+ *
+ * EXTERN: int db_create __P((DB **, DB_ENV *, u_int32_t));
*/
int
db_create(dbpp, dbenv, flags)
@@ -102,27 +108,25 @@ db_create(dbpp, dbenv, flags)
if ((ret = __os_calloc(dbenv, 1, sizeof(*dbp), &dbp)) != 0)
return (ret);
#ifdef HAVE_RPC
- if (dbenv != NULL && dbenv->cl_handle != NULL)
+ if (dbenv != NULL && RPC_ON(dbenv))
ret = __dbcl_init(dbp, dbenv, flags);
else
#endif
ret = __db_init(dbp, flags);
if (ret != 0) {
- __os_free(dbp, sizeof(*dbp));
+ __os_free(dbenv, dbp);
return (ret);
}
/* If we don't have an environment yet, allocate a local one. */
if (dbenv == NULL) {
if ((ret = db_env_create(&dbenv, 0)) != 0) {
- __os_free(dbp, sizeof(*dbp));
+ __os_free(dbenv, dbp);
return (ret);
}
- dbenv->dblocal_ref = 0;
F_SET(dbenv, DB_ENV_DBLOCAL);
}
- if (F_ISSET(dbenv, DB_ENV_DBLOCAL))
- ++dbenv->dblocal_ref;
+ ++dbenv->db_ref;
dbp->dbenv = dbenv;
@@ -141,18 +145,21 @@ __db_init(dbp, flags)
{
int ret;
- dbp->log_fileid = DB_LOGFILEID_INVALID;
+ dbp->lid = DB_LOCK_INVALIDID;
+ LOCK_INIT(dbp->handle_lock);
TAILQ_INIT(&dbp->free_queue);
TAILQ_INIT(&dbp->active_queue);
TAILQ_INIT(&dbp->join_queue);
+ LIST_INIT(&dbp->s_secondaries);
FLD_SET(dbp->am_ok,
DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO);
+ dbp->associate = __db_associate;
dbp->close = __db_close;
dbp->cursor = __db_cursor;
- dbp->del = NULL; /* !!! Must be set by access method. */
+ dbp->del = __db_delete;
dbp->err = __dbh_err;
dbp->errx = __dbh_errx;
dbp->fd = __db_fd;
@@ -162,26 +169,30 @@ __db_init(dbp, flags)
dbp->join = __db_join;
dbp->key_range = __db_key_range;
dbp->open = __db_open;
+ dbp->pget = __db_pget;
dbp->put = __db_put;
dbp->remove = __db_remove;
dbp->rename = __db_rename;
+ dbp->truncate = __db_truncate;
+ dbp->set_alloc = __db_set_alloc;
dbp->set_append_recno = __db_set_append_recno;
dbp->set_cachesize = __db_set_cachesize;
+ dbp->set_cache_priority = __db_set_cache_priority;
dbp->set_dup_compare = __db_set_dup_compare;
+ dbp->set_encrypt = __db_set_encrypt;
dbp->set_errcall = __db_set_errcall;
dbp->set_errfile = __db_set_errfile;
dbp->set_errpfx = __db_set_errpfx;
dbp->set_feedback = __db_set_feedback;
dbp->set_flags = __db_set_flags;
dbp->set_lorder = __db_set_lorder;
- dbp->set_malloc = __db_set_malloc;
dbp->set_pagesize = __db_set_pagesize;
dbp->set_paniccall = __db_set_paniccall;
- dbp->set_realloc = __db_set_realloc;
- dbp->stat = NULL; /* !!! Must be set by access method. */
+ dbp->stat = __db_stat_fail;
dbp->sync = __db_sync;
dbp->upgrade = __db_upgrade;
dbp->verify = __db_verify;
+
/* Access method specific. */
if ((ret = __bam_db_create(dbp)) != 0)
return (ret);
@@ -244,16 +255,7 @@ __dbh_err(dbp, error, fmt, va_alist)
va_dcl
#endif
{
- va_list ap;
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- __db_real_err(dbp->dbenv, error, 1, 1, fmt, ap);
-
- va_end(ap);
+ DB_REAL_ERR(dbp->dbenv, error, 1, 1, fmt);
}
/*
@@ -270,16 +272,7 @@ __dbh_errx(dbp, fmt, va_alist)
va_dcl
#endif
{
- va_list ap;
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- __db_real_err(dbp->dbenv, 0, 0, 1, fmt, ap);
-
- va_end(ap);
+ DB_REAL_ERR(dbp->dbenv, 0, 0, 1, fmt);
}
/*
@@ -287,25 +280,29 @@ __dbh_errx(dbp, fmt, va_alist)
* Return if database requires byte swapping.
*/
static int
-__db_get_byteswapped(dbp)
+__db_get_byteswapped(dbp, isswapped)
DB *dbp;
+ int *isswapped;
{
DB_ILLEGAL_BEFORE_OPEN(dbp, "get_byteswapped");
- return (F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0);
+ *isswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0;
+ return (0);
}
/*
* __db_get_type --
* Return type of underlying database.
*/
-static DBTYPE
-__db_get_type(dbp)
+static int
+__db_get_type(dbp, dbtype)
DB *dbp;
+ DBTYPE *dbtype;
{
DB_ILLEGAL_BEFORE_OPEN(dbp, "get_type");
- return (dbp->type);
+ *dbtype = dbp->type;
+ return (0);
}
/*
@@ -366,6 +363,26 @@ __db_set_cachesize(dbp, cache_gbytes, cache_bytes, ncache)
}
/*
+ * __db_set_cache_priority --
+ * Set cache priority for pages from this file.
+ */
+static int
+__db_set_cache_priority(dbp, priority)
+ DB *dbp;
+ DB_CACHE_PRIORITY priority;
+{
+ /*
+ * If an underlying DB_MPOOLFILE exists, call it. Otherwise, save
+ * the information away until DB->open is called.
+ */
+ if (dbp->mpf == NULL) {
+ dbp->priority = priority;
+ return (0);
+ }
+ return (dbp->mpf->set_priority(dbp->mpf, priority));
+}
+
+/*
* __db_set_dup_compare --
* Set duplicate comparison routine.
*/
@@ -374,14 +391,50 @@ __db_set_dup_compare(dbp, func)
DB *dbp;
int (*func) __P((DB *, const DBT *, const DBT *));
{
+ int ret;
+
DB_ILLEGAL_AFTER_OPEN(dbp, "dup_compare");
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
+ if ((ret = dbp->set_flags(dbp, DB_DUPSORT)) != 0)
+ return (ret);
+
dbp->dup_compare = func;
return (0);
}
+/*
+ * __db_set_encrypt --
+ * Set database passwd.
+ */
+static int
+__db_set_encrypt(dbp, passwd, flags)
+ DB *dbp;
+ const char *passwd;
+ u_int32_t flags;
+{
+ DB_CIPHER *db_cipher;
+ int ret;
+
+ DB_ILLEGAL_IN_ENV(dbp, "set_encrypt");
+ DB_ILLEGAL_AFTER_OPEN(dbp, "set_encrypt");
+
+ if ((ret = dbp->dbenv->set_encrypt(dbp->dbenv, passwd, flags)) != 0)
+ return (ret);
+
+ /*
+ * In a real env, this gets initialized with the region. In a local
+ * env, we must do it here.
+ */
+ db_cipher = (DB_CIPHER *)dbp->dbenv->crypto_handle;
+ if (!F_ISSET(db_cipher, CIPHER_ANY) &&
+ (ret = db_cipher->init(dbp->dbenv, db_cipher)) != 0)
+ return (ret);
+
+ return (dbp->set_flags(dbp, DB_ENCRYPT));
+}
+
static void
__db_set_errcall(dbp, errcall)
DB *dbp;
@@ -430,6 +483,21 @@ __db_set_flags(dbp, flags)
*
* The queue access method takes no flags.
*/
+ if (LF_ISSET(DB_ENCRYPT)) {
+ if (!CRYPTO_ON(dbp->dbenv)) {
+ __db_err(dbp->dbenv,
+ "Database environment not configured for encryption");
+ return (EINVAL);
+ }
+ F_SET(dbp, DB_AM_ENCRYPT);
+ F_SET(dbp, DB_AM_CHKSUM);
+ LF_CLR(DB_ENCRYPT);
+ }
+ if (LF_ISSET(DB_CHKSUM_SHA1)) {
+ F_SET(dbp, DB_AM_CHKSUM);
+ LF_CLR(DB_CHKSUM_SHA1);
+ }
+
if ((ret = __bam_set_flags(dbp, &flags)) != 0)
return (ret);
if ((ret = __ram_set_flags(dbp, &flags)) != 0)
@@ -438,7 +506,13 @@ __db_set_flags(dbp, flags)
return (flags == 0 ? 0 : __db_ferr(dbp->dbenv, "DB->set_flags", 0));
}
-static int
+/*
+ * __db_set_lorder --
+ * Set whether lorder is swapped or not.
+ *
+ * PUBLIC: int __db_set_lorder __P((DB *, int));
+ */
+int
__db_set_lorder(dbp, db_lorder)
DB *dbp;
int db_lorder;
@@ -463,14 +537,17 @@ __db_set_lorder(dbp, db_lorder)
}
static int
-__db_set_malloc(dbp, func)
+__db_set_alloc(dbp, mal_func, real_func, free_func)
DB *dbp;
- void *(*func) __P((size_t));
+ void *(*mal_func) __P((size_t));
+ void *(*real_func) __P((void *, size_t));
+ void (*free_func) __P((void *));
{
- DB_ILLEGAL_AFTER_OPEN(dbp, "set_malloc");
+ DB_ILLEGAL_IN_ENV(dbp, "set_alloc");
+ DB_ILLEGAL_AFTER_OPEN(dbp, "set_alloc");
- dbp->db_malloc = func;
- return (0);
+ return (dbp->dbenv->set_alloc(dbp->dbenv,
+ mal_func, real_func, free_func));
}
static int
@@ -495,7 +572,7 @@ __db_set_pagesize(dbp, db_pagesize)
* We don't want anything that's not a power-of-2, as we rely on that
* for alignment of various types on the pages.
*/
- if ((u_int32_t)1 << __db_log2(db_pagesize) != db_pagesize) {
+ if (!POWER_OF_TWO(db_pagesize)) {
__db_err(dbp->dbenv, "page sizes must be a power-of-2");
return (EINVAL);
}
@@ -511,44 +588,44 @@ __db_set_pagesize(dbp, db_pagesize)
}
static int
-__db_set_realloc(dbp, func)
+__db_set_paniccall(dbp, paniccall)
DB *dbp;
- void *(*func) __P((void *, size_t));
+ void (*paniccall) __P((DB_ENV *, int));
{
- DB_ILLEGAL_AFTER_OPEN(dbp, "set_realloc");
-
- dbp->db_realloc = func;
- return (0);
+ return (dbp->dbenv->set_paniccall(dbp->dbenv, paniccall));
}
static int
-__db_set_paniccall(dbp, paniccall)
+__db_stat_fail(dbp, sp, flags)
DB *dbp;
- void (*paniccall) __P((DB_ENV *, int));
+ void *sp;
+ u_int32_t flags;
{
- return (dbp->dbenv->set_paniccall(dbp->dbenv, paniccall));
+ COMPQUIET(sp, NULL);
+ COMPQUIET(flags, 0);
+
+ /*
+ * DB->stat isn't initialized until the actual DB->open call,
+ * but we don't want to core dump.
+ */
+ PANIC_CHECK(dbp->dbenv);
+ DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
+
+ /* NOTREACHED */
+ return (EINVAL);
}
#ifdef HAVE_RPC
/*
* __dbcl_init --
* Initialize a DB structure on the server.
- *
- * PUBLIC: #ifdef HAVE_RPC
- * PUBLIC: int __dbcl_init __P((DB *, DB_ENV *, u_int32_t));
- * PUBLIC: #endif
*/
-int
+static int
__dbcl_init(dbp, dbenv, flags)
DB *dbp;
DB_ENV *dbenv;
u_int32_t flags;
{
- CLIENT *cl;
- __db_create_reply *replyp;
- __db_create_msg req;
- int ret;
-
TAILQ_INIT(&dbp->free_queue);
TAILQ_INIT(&dbp->active_queue);
/* !!!
@@ -556,6 +633,7 @@ __dbcl_init(dbp, dbenv, flags)
* not used in RPC clients. See the comment in __dbcl_db_join_ret().
*/
+ dbp->associate = __dbcl_db_associate;
dbp->close = __dbcl_db_close;
dbp->cursor = __dbcl_db_cursor;
dbp->del = __dbcl_db_del;
@@ -563,31 +641,34 @@ __dbcl_init(dbp, dbenv, flags)
dbp->errx = __dbh_errx;
dbp->fd = __dbcl_db_fd;
dbp->get = __dbcl_db_get;
- dbp->get_byteswapped = __dbcl_db_swapped;
+ dbp->get_byteswapped = __db_get_byteswapped;
dbp->get_type = __db_get_type;
dbp->join = __dbcl_db_join;
dbp->key_range = __dbcl_db_key_range;
- dbp->open = __dbcl_db_open;
+ dbp->open = __dbcl_db_open_wrap;
+ dbp->pget = __dbcl_db_pget;
dbp->put = __dbcl_db_put;
dbp->remove = __dbcl_db_remove;
dbp->rename = __dbcl_db_rename;
+ dbp->set_alloc = __dbcl_db_alloc;
dbp->set_append_recno = __dbcl_db_set_append_recno;
dbp->set_cachesize = __dbcl_db_cachesize;
- dbp->set_dup_compare = NULL;
+ dbp->set_cache_priority = __dbcl_db_cache_priority;
+ dbp->set_dup_compare = __dbcl_db_dup_compare;
+ dbp->set_encrypt = __dbcl_db_encrypt;
dbp->set_errcall = __db_set_errcall;
dbp->set_errfile = __db_set_errfile;
dbp->set_errpfx = __db_set_errpfx;
dbp->set_feedback = __dbcl_db_feedback;
dbp->set_flags = __dbcl_db_flags;
dbp->set_lorder = __dbcl_db_lorder;
- dbp->set_malloc = __dbcl_db_malloc;
dbp->set_pagesize = __dbcl_db_pagesize;
dbp->set_paniccall = __dbcl_db_panic;
- dbp->set_q_extentsize = __dbcl_db_extentsize;
- dbp->set_realloc = __dbcl_db_realloc;
dbp->stat = __dbcl_db_stat;
dbp->sync = __dbcl_db_sync;
+ dbp->truncate = __dbcl_db_truncate;
dbp->upgrade = __dbcl_db_upgrade;
+ dbp->verify = __dbcl_db_verify;
/*
* Set all the method specific functions to client funcs as well.
@@ -599,31 +680,12 @@ __dbcl_init(dbp, dbenv, flags)
dbp->set_h_ffactor = __dbcl_db_h_ffactor;
dbp->set_h_hash = __dbcl_db_h_hash;
dbp->set_h_nelem = __dbcl_db_h_nelem;
+ dbp->set_q_extentsize = __dbcl_db_extentsize;
dbp->set_re_delim = __dbcl_db_re_delim;
dbp->set_re_len = __dbcl_db_re_len;
dbp->set_re_pad = __dbcl_db_re_pad;
dbp->set_re_source = __dbcl_db_re_source;
-/*
- dbp->set_q_extentsize = __dbcl_db_q_extentsize;
-*/
-
- cl = (CLIENT *)dbenv->cl_handle;
- req.flags = flags;
- req.envpcl_id = dbenv->cl_id;
-
- /*
- * CALL THE SERVER
- */
- replyp = __db_db_create_1(&req, cl);
- if (replyp == NULL) {
- __db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
- return (DB_NOSERVER);
- }
- if ((ret = replyp->status) != 0)
- return (ret);
-
- dbp->cl_id = replyp->dbpcl_id;
- return (0);
+ return (__dbcl_db_create(dbp, dbenv, flags));
}
#endif
diff --git a/bdb/db/db_open.c b/bdb/db/db_open.c
new file mode 100644
index 00000000000..8352525361f
--- /dev/null
+++ b/bdb/db/db_open.c
@@ -0,0 +1,703 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_open.c,v 11.215 2002/08/15 15:27:52 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/fop.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
+#include "dbinc/txn.h"
+
+static int __db_openchk __P((DB *,
+ DB_TXN *, const char *, const char *, DBTYPE, u_int32_t));
+
+/*
+ * __db_open --
+ * Main library interface to the DB access methods.
+ *
+ * PUBLIC: int __db_open __P((DB *, DB_TXN *,
+ * PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int));
+ */
+int
+__db_open(dbp, txn, name, subdb, type, flags, mode)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb;
+ DBTYPE type;
+ u_int32_t flags;
+ int mode;
+{
+ DB_ENV *dbenv;
+ int remove_master, remove_me, ret, t_ret, txn_local;
+
+ dbenv = dbp->dbenv;
+ remove_me = remove_master = txn_local = 0;
+
+ PANIC_CHECK(dbenv);
+
+ if ((ret = __db_openchk(dbp, txn, name, subdb, type, flags)) != 0)
+ return (ret);
+
+ /*
+ * Create local transaction as necessary, check for consistent
+ * transaction usage.
+ */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ } else
+ if (txn != NULL && !TXN_ON(dbenv))
+ return (__db_not_txn_env(dbenv));
+
+ /*
+ * If the environment was configured with threads, the DB handle
+ * must also be free-threaded, so we force the DB_THREAD flag on.
+ * (See SR #2033 for why this is a requirement--recovery needs
+ * to be able to grab a dbp using __db_fileid_to_dbp, and it has
+ * no way of knowing which dbp goes with which thread, so whichever
+ * one it finds has to be usable in any of them.)
+ */
+ if (F_ISSET(dbenv, DB_ENV_THREAD))
+ LF_SET(DB_THREAD);
+
+ /* Convert any DB->open flags. */
+ if (LF_ISSET(DB_RDONLY))
+ F_SET(dbp, DB_AM_RDONLY);
+ if (LF_ISSET(DB_DIRTY_READ))
+ F_SET(dbp, DB_AM_DIRTY);
+
+ /* Fill in the type. */
+ dbp->type = type;
+
+ /*
+ * If we're opening a subdatabase, we have to open (and potentially
+ * create) the main database, and then get (and potentially store)
+ * our base page number in that database. Then, we can finally open
+ * the subdatabase.
+ */
+ if ((ret = __db_dbopen(
+ dbp, txn, name, subdb, flags, mode, PGNO_BASE_MD)) != 0)
+ goto err;
+
+ /*
+ * You can open the database that describes the subdatabases in the
+ * rest of the file read-only. The content of each key's data is
+ * unspecified and applications should never be adding new records
+ * or updating existing records. However, during recovery, we need
+ * to open these databases R/W so we can redo/undo changes in them.
+ * Likewise, we need to open master databases read/write during
+ * rename and remove so we can be sure they're fully sync'ed, so
+ * we provide an override flag for the purpose.
+ */
+ if (subdb == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
+ !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
+ __db_err(dbenv,
+ "files containing multiple databases may only be opened read-only");
+ ret = EINVAL;
+ goto err;
+ }
+
+err: /* If we were successful, don't discard the file on close. */
+ if (ret == 0)
+ /* If we were successful, don't discard the file on close. */
+ F_CLR(dbp, DB_AM_DISCARD | DB_AM_CREATED | DB_AM_CREATED_MSTR);
+ else {
+ /*
+ * If we are not transactional, we need to remove the
+ * databases/subdatabases. If we are transactional, then
+ * the abort of the child transaction should take care of
+ * cleaning them up.
+ */
+ remove_me = txn == NULL && F_ISSET(dbp, DB_AM_CREATED);
+ remove_master = txn == NULL && F_ISSET(dbp, DB_AM_CREATED_MSTR);
+
+ /*
+ * If we had an error, it may have happened before or after
+ * we actually logged the open. If it happened before, then
+ * abort won't know anything about it and won't close or
+ * refresh the dbp, so we need to do it explicitly.
+ */
+ (void)__db_refresh(dbp, txn, DB_NOSYNC);
+ }
+
+ /* Remove anyone we created. */
+ if (remove_master || (subdb == NULL && remove_me))
+ /* Remove file. */
+ (void)dbenv->dbremove(dbenv, txn, name, NULL, 0);
+ else if (remove_me)
+ /* Remove subdatabase. */
+ (void)dbenv->dbremove(dbenv, txn, name, subdb, 0);
+
+ /* Commit for DB_AUTO_COMMIT. */
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+ }
+
+ return (ret);
+}
+
+/*
+ * __db_dbopen --
+ * Open a database. This routine gets called in three different ways.
+ * 1. It can be called to open a file/database. In this case, subdb will
+ * be NULL and meta_pgno will be PGNO_BASE_MD.
+ * 2. It can be called to open a subdatabase during normal operation. In
+ * this case, name and subname will both be non-NULL and meta_pgno will
+ * be PGNO_BAS_MD (also PGNO_INVALID).
+ * 3. It can be called during recovery to open a subdatabase in which case
+ * name will be non-NULL, subname mqy be NULL and meta-pgno will be
+ * a valid pgno (i.e., not PGNO_BASE_MD).
+ *
+ * PUBLIC: int __db_dbopen __P((DB *, DB_TXN *,
+ * PUBLIC: const char *, const char *, u_int32_t, int, db_pgno_t));
+ */
+int
+__db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb;
+ u_int32_t flags;
+ int mode;
+ db_pgno_t meta_pgno;
+{
+ DB_ENV *dbenv;
+ int ret;
+ u_int32_t id;
+
+ dbenv = dbp->dbenv;
+ id = TXN_INVALID;
+ if (txn != NULL)
+ F_SET(dbp, DB_AM_TXN);
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, name);
+ /*
+ * If name is NULL, it's always a create, so make sure that we
+ * have a type specified. It would be nice if this checking
+ * were done in __db_open where most of the interface checking
+ * is done, but this interface (__db_dbopen) is used by the
+ * recovery and limbo system, so we need to safeguard this
+ * interface as well.
+ */
+ if (name == NULL) {
+ F_SET(dbp, DB_AM_INMEM);
+
+ if (dbp->type == DB_UNKNOWN) {
+ __db_err(dbenv,
+ "DBTYPE of unknown without existing file");
+ return (EINVAL);
+ }
+
+ if (dbp->pgsize == 0)
+ dbp->pgsize = DB_DEF_IOSIZE;
+
+ /*
+ * If the file is a temporary file and we're doing locking,
+ * then we have to create a unique file ID. We can't use our
+ * normal dev/inode pair (or whatever this OS uses in place of
+ * dev/inode pairs) because no backing file will be created
+ * until the mpool cache is filled forcing the buffers to disk.
+ * Grab a random locker ID to use as a file ID. The created
+ * ID must never match a potential real file ID -- we know it
+ * won't because real file IDs contain a time stamp after the
+ * dev/inode pair, and we're simply storing a 4-byte value.
+ *
+ * !!!
+ * Store the locker in the file id structure -- we can get it
+ * from there as necessary, and it saves having two copies.
+ */
+ if (LOCKING_ON(dbenv) && (ret = dbenv->lock_id(dbenv,
+ (u_int32_t *)dbp->fileid)) != 0)
+ return (ret);
+ } else if (subdb == NULL && meta_pgno == PGNO_BASE_MD) {
+ /* Open/create the underlying file. Acquire locks. */
+ if ((ret =
+ __fop_file_setup(dbp, txn, name, mode, flags, &id)) != 0)
+ return (ret);
+ } else {
+ if ((ret = __fop_subdb_setup(dbp,
+ txn, name, subdb, mode, flags)) != 0)
+ return (ret);
+ meta_pgno = dbp->meta_pgno;
+ }
+
+ /*
+ * If we created the file, set the truncate flag for the mpool. This
+ * isn't for anything we've done, it's protection against stupid user
+ * tricks: if the user deleted a file behind Berkeley DB's back, we
+ * may still have pages in the mpool that match the file's "unique" ID.
+ *
+ * Note that if we're opening a subdatabase, we don't want to set
+ * the TRUNCATE flag even if we just created the file--we already
+ * opened and updated the master using access method interfaces,
+ * so we don't want to get rid of any pages that are in the mpool.
+ * If we created the file when we opened the master, we already hit
+ * this check in a non-subdb context then.
+ */
+ if (subdb == NULL && F_ISSET(dbp, DB_AM_CREATED))
+ LF_SET(DB_TRUNCATE);
+
+ /* Set up the underlying environment. */
+ if ((ret = __db_dbenv_setup(dbp, txn, name, id, flags)) != 0)
+ return (ret);
+
+ /*
+ * Set the open flag. We use it to mean that the dbp has gone
+ * through mpf setup, including dbreg_register. Also, below,
+ * the underlying access method open functions may want to do
+ * things like acquire cursors, so the open flag has to be set
+ * before calling them.
+ */
+ F_SET(dbp, DB_AM_OPEN_CALLED);
+
+ /*
+ * For unnamed files, we need to actually create the file now
+ * that the mpool is open.
+ */
+ if (name == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
+ return (ret);
+
+ switch (dbp->type) {
+ case DB_BTREE:
+ ret = __bam_open(dbp, txn, name, meta_pgno, flags);
+ break;
+ case DB_HASH:
+ ret = __ham_open(dbp, txn, name, meta_pgno, flags);
+ break;
+ case DB_RECNO:
+ ret = __ram_open(dbp, txn, name, meta_pgno, flags);
+ break;
+ case DB_QUEUE:
+ ret = __qam_open(dbp, txn, name, meta_pgno, mode, flags);
+ break;
+ case DB_UNKNOWN:
+ return (__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
+ }
+ if (ret != 0)
+ goto err;
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, name);
+
+ /*
+ * Unnamed files don't need handle locks, so we only have to check
+ * for a handle lock downgrade or lockevent in the case of named
+ * files.
+ */
+ if (!F_ISSET(dbp, DB_AM_RECOVER) &&
+ name != NULL && LOCK_ISSET(dbp->handle_lock)) {
+ if (txn != NULL) {
+ ret = __txn_lockevent(dbenv,
+ txn, dbp, &dbp->handle_lock, dbp->lid);
+ } else if (LOCKING_ON(dbenv))
+ /* Trade write handle lock for read handle lock. */
+ ret = __lock_downgrade(dbenv,
+ &dbp->handle_lock, DB_LOCK_READ, 0);
+ }
+DB_TEST_RECOVERY_LABEL
+err:
+ return (ret);
+}
+
+/*
+ * __db_new_file --
+ * Create a new database file.
+ *
+ * PUBLIC: int __db_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
+ */
+int
+__db_new_file(dbp, txn, fhp, name)
+ DB *dbp;
+ DB_TXN *txn;
+ DB_FH *fhp;
+ const char *name;
+{
+ int ret;
+
+ switch (dbp->type) {
+ case DB_BTREE:
+ case DB_RECNO:
+ ret = __bam_new_file(dbp, txn, fhp, name);
+ break;
+ case DB_HASH:
+ ret = __ham_new_file(dbp, txn, fhp, name);
+ break;
+ case DB_QUEUE:
+ ret = __qam_new_file(dbp, txn, fhp, name);
+ break;
+ default:
+ __db_err(dbp->dbenv,
+ "%s: Invalid type %d specified", name, dbp->type);
+ ret = EINVAL;
+ break;
+ }
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, name);
+ /* Sync the file in preparation for moving it into place. */
+ if (ret == 0 && fhp != NULL)
+ ret = __os_fsync(dbp->dbenv, fhp);
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name);
+
+DB_TEST_RECOVERY_LABEL
+ return (ret);
+}
+
+/*
+ * __db_init_subdb --
+ * Initialize the dbp for a subdb.
+ *
+ * PUBLIC: int __db_init_subdb __P((DB *, DB *, const char *, DB_TXN *));
+ */
+int
+__db_init_subdb(mdbp, dbp, name, txn)
+ DB *mdbp, *dbp;
+ const char *name;
+ DB_TXN *txn;
+{
+ DBMETA *meta;
+ DB_MPOOLFILE *mpf;
+ int ret, t_ret;
+
+ ret = 0;
+ if (!F_ISSET(dbp, DB_AM_CREATED)) {
+ /* Subdb exists; read meta-data page and initialize. */
+ mpf = mdbp->mpf;
+ if ((ret = mpf->get(mpf, &dbp->meta_pgno, 0, &meta)) != 0)
+ goto err;
+ ret = __db_meta_setup(mdbp->dbenv, dbp, name, meta, 0, 0);
+ if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ /*
+ * If __db_meta_setup found that the meta-page hadn't
+ * been written out during recovery, we can just return.
+ */
+ if (ret == ENOENT)
+ ret = 0;
+ goto err;
+ }
+
+ /* Handle the create case here. */
+ switch (dbp->type) {
+ case DB_BTREE:
+ case DB_RECNO:
+ ret = __bam_new_subdb(mdbp, dbp, txn);
+ break;
+ case DB_HASH:
+ ret = __ham_new_subdb(mdbp, dbp, txn);
+ break;
+ case DB_QUEUE:
+ ret = EINVAL;
+ break;
+ default:
+ __db_err(dbp->dbenv,
+ "Invalid subdatabase type %d specified", dbp->type);
+ return (EINVAL);
+ }
+
+err: return (ret);
+}
+
+/*
+ * __db_chk_meta --
+ * Take a buffer containing a meta-data page and check it for a checksum
+ * (and verify the checksum if necessary) and possibly decrypt it.
+ *
+ * Return 0 on success, >0 (errno) on error, -1 on checksum mismatch.
+ *
+ * PUBLIC: int __db_chk_meta __P((DB_ENV *, DB *, DBMETA *, int));
+ */
+int
+__db_chk_meta(dbenv, dbp, meta, do_metachk)
+ DB_ENV *dbenv;
+ DB *dbp;
+ DBMETA *meta;
+ int do_metachk;
+{
+ int is_hmac, ret;
+ u_int8_t *chksum;
+
+ ret = 0;
+
+ if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) {
+ if (dbp != NULL)
+ F_SET(dbp, DB_AM_CHKSUM);
+
+ is_hmac = meta->encrypt_alg == 0 ? 0 : 1;
+ chksum = ((BTMETA *)meta)->chksum;
+ if (do_metachk && ((ret = __db_check_chksum(dbenv,
+ (DB_CIPHER *)dbenv->crypto_handle, chksum, meta,
+ DBMETASIZE, is_hmac)) != 0))
+ return (ret);
+ }
+
+#ifdef HAVE_CRYPTO
+ ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);
+#endif
+ return (ret);
+}
+
+/*
+ * __db_meta_setup --
+ *
+ * Take a buffer containing a meta-data page and figure out if it's
+ * valid, and if so, initialize the dbp from the meta-data page.
+ *
+ * PUBLIC: int __db_meta_setup __P((DB_ENV *,
+ * PUBLIC: DB *, const char *, DBMETA *, u_int32_t, int));
+ */
+int
+__db_meta_setup(dbenv, dbp, name, meta, oflags, do_metachk)
+ DB_ENV *dbenv;
+ DB *dbp;
+ const char *name;
+ DBMETA *meta;
+ u_int32_t oflags;
+ int do_metachk;
+{
+ u_int32_t flags, magic;
+ int ret;
+
+ ret = 0;
+
+ /*
+ * Figure out what access method we're dealing with, and then
+ * call access method specific code to check error conditions
+ * based on conflicts between the found file and application
+ * arguments. A found file overrides some user information --
+ * we don't consider it an error, for example, if the user set
+ * an expected byte order and the found file doesn't match it.
+ */
+ F_CLR(dbp, DB_AM_SWAP);
+ magic = meta->magic;
+
+swap_retry:
+ switch (magic) {
+ case DB_BTREEMAGIC:
+ case DB_HASHMAGIC:
+ case DB_QAMMAGIC:
+ case DB_RENAMEMAGIC:
+ break;
+ case 0:
+ /*
+ * The only time this should be 0 is if we're in the
+ * midst of opening a subdb during recovery and that
+ * subdatabase had its meta-data page allocated, but
+ * not yet initialized.
+ */
+ if (F_ISSET(dbp, DB_AM_SUBDB) && ((IS_RECOVERING(dbenv) &&
+ F_ISSET((DB_LOG *) dbenv->lg_handle, DBLOG_FORCE_OPEN)) ||
+ meta->pgno != PGNO_INVALID))
+ return (ENOENT);
+
+ goto bad_format;
+ default:
+ if (F_ISSET(dbp, DB_AM_SWAP))
+ goto bad_format;
+
+ M_32_SWAP(magic);
+ F_SET(dbp, DB_AM_SWAP);
+ goto swap_retry;
+ }
+
+ /*
+ * We can only check the meta page if we are sure we have a meta page.
+ * If it is random data, then this check can fail. So only now can we
+ * checksum and decrypt. Don't distinguish between configuration and
+ * checksum match errors here, because we haven't opened the database
+ * and even a checksum error isn't a reason to panic the environment.
+ */
+ if ((ret = __db_chk_meta(dbenv, dbp, meta, do_metachk)) != 0) {
+ if (ret == -1)
+ __db_err(dbenv,
+ "%s: metadata page checksum error", name);
+ goto bad_format;
+ }
+
+ switch (magic) {
+ case DB_BTREEMAGIC:
+ flags = meta->flags;
+ if (F_ISSET(dbp, DB_AM_SWAP))
+ M_32_SWAP(flags);
+ if (LF_ISSET(BTM_RECNO))
+ dbp->type = DB_RECNO;
+ else
+ dbp->type = DB_BTREE;
+ if ((oflags & DB_TRUNCATE) == 0 && (ret =
+ __bam_metachk(dbp, name, (BTMETA *)meta)) != 0)
+ return (ret);
+ break;
+ case DB_HASHMAGIC:
+ dbp->type = DB_HASH;
+ if ((oflags & DB_TRUNCATE) == 0 && (ret =
+ __ham_metachk(dbp, name, (HMETA *)meta)) != 0)
+ return (ret);
+ break;
+ case DB_QAMMAGIC:
+ dbp->type = DB_QUEUE;
+ if ((oflags & DB_TRUNCATE) == 0 && (ret =
+ __qam_metachk(dbp, name, (QMETA *)meta)) != 0)
+ return (ret);
+ break;
+ case DB_RENAMEMAGIC:
+ F_SET(dbp, DB_AM_IN_RENAME);
+ break;
+ }
+ return (0);
+
+bad_format:
+ __db_err(dbenv, "%s: unexpected file type or format", name);
+ return (ret == 0 ? EINVAL : ret);
+}
+
+/*
+ * __db_openchk --
+ * Interface error checking for open calls.
+ */
+static int
+__db_openchk(dbp, txn, name, subdb, type, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb;
+ DBTYPE type;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int ret;
+ u_int32_t ok_flags;
+
+ dbenv = dbp->dbenv;
+
+ /* Validate arguments. */
+#define OKFLAGS \
+ (DB_AUTO_COMMIT | DB_CREATE | DB_DIRTY_READ | DB_EXCL | \
+ DB_FCNTL_LOCKING | DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER | \
+ DB_THREAD | DB_TRUNCATE | DB_WRITEOPEN)
+ if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
+ return (ret);
+ if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
+ return (__db_ferr(dbenv, "DB->open", 1));
+ if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
+ return (__db_ferr(dbenv, "DB->open", 1));
+
+#ifdef HAVE_VXWORKS
+ if (LF_ISSET(DB_TRUNCATE)) {
+ __db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks");
+ return (__db_eopnotsup(dbenv));
+ }
+#endif
+ switch (type) {
+ case DB_UNKNOWN:
+ if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) {
+ __db_err(dbenv,
+ "%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE",
+ name);
+ return (EINVAL);
+ }
+ ok_flags = 0;
+ break;
+ case DB_BTREE:
+ ok_flags = DB_OK_BTREE;
+ break;
+ case DB_HASH:
+ ok_flags = DB_OK_HASH;
+ break;
+ case DB_QUEUE:
+ ok_flags = DB_OK_QUEUE;
+ break;
+ case DB_RECNO:
+ ok_flags = DB_OK_RECNO;
+ break;
+ default:
+ __db_err(dbenv, "unknown type: %lu", (u_long)type);
+ return (EINVAL);
+ }
+ if (ok_flags)
+ DB_ILLEGAL_METHOD(dbp, ok_flags);
+
+ /* The environment may have been created, but never opened. */
+ if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
+ __db_err(dbenv, "environment not yet opened");
+ return (EINVAL);
+ }
+
+ /*
+ * Historically, you could pass in an environment that didn't have a
+ * mpool, and DB would create a private one behind the scenes. This
+ * no longer works.
+ */
+ if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
+ __db_err(dbenv, "environment did not include a memory pool");
+ return (EINVAL);
+ }
+
+ /*
+ * You can't specify threads during DB->open if subsystems in the
+ * environment weren't configured with them.
+ */
+ if (LF_ISSET(DB_THREAD) &&
+ !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
+ __db_err(dbenv, "environment not created using DB_THREAD");
+ return (EINVAL);
+ }
+
+ /* DB_TRUNCATE is not transaction recoverable. */
+ if (LF_ISSET(DB_TRUNCATE) && txn != NULL) {
+ __db_err(dbenv,
+ "DB_TRUNCATE illegal with transaction specified");
+ return (EINVAL);
+ }
+
+ /* Subdatabase checks. */
+ if (subdb != NULL) {
+ /* Subdatabases must be created in named files. */
+ if (name == NULL) {
+ __db_err(dbenv,
+ "multiple databases cannot be created in temporary files");
+ return (EINVAL);
+ }
+
+ /* Truncate is a physical file operation */
+ if (LF_ISSET(DB_TRUNCATE)) {
+ __db_err(dbenv,
+ "DB_TRUNCATE illegal with multiple databases");
+ return (EINVAL);
+ }
+
+ /* QAM can't be done as a subdatabase. */
+ if (type == DB_QUEUE) {
+ __db_err(dbenv, "Queue databases must be one-per-file");
+ return (EINVAL);
+ }
+ }
+
+ return (0);
+}
diff --git a/bdb/db/db_overflow.c b/bdb/db/db_overflow.c
index 54f0a03aafe..27dcb41a2ff 100644
--- a/bdb/db/db_overflow.c
+++ b/bdb/db/db_overflow.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_overflow.c,v 11.21 2000/11/30 00:58:32 ubell Exp $";
+static const char revid[] = "$Id: db_overflow.c,v 11.46 2002/08/08 03:57:48 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -53,9 +53,9 @@ static const char revid[] = "$Id: db_overflow.c,v 11.21 2000/11/30 00:58:32 ubel
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "db_verify.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_verify.h"
/*
* Big key/data code.
@@ -83,6 +83,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
u_int32_t *bpsz;
{
DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t bytes;
u_int32_t curoff, needed, start;
@@ -90,6 +91,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
int ret;
dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
/*
* Check if the buffer is big enough; if it is not and we are
@@ -99,7 +101,12 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
*/
if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
start = dbt->doff;
- needed = dbt->dlen;
+ if (start > tlen)
+ needed = 0;
+ else if (dbt->dlen > tlen - start)
+ needed = tlen - start;
+ else
+ needed = dbt->dlen;
} else {
start = 0;
needed = tlen;
@@ -112,15 +119,13 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
return (ENOMEM);
}
} else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
- if ((ret = __os_malloc(dbenv,
- needed, dbp->db_malloc, &dbt->data)) != 0)
+ if ((ret = __os_umalloc(dbenv, needed, &dbt->data)) != 0)
return (ret);
} else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
- if ((ret = __os_realloc(dbenv,
- needed, dbp->db_realloc, &dbt->data)) != 0)
+ if ((ret = __os_urealloc(dbenv, needed, &dbt->data)) != 0)
return (ret);
} else if (*bpsz == 0 || *bpsz < needed) {
- if ((ret = __os_realloc(dbenv, needed, NULL, bpp)) != 0)
+ if ((ret = __os_realloc(dbenv, needed, bpp)) != 0)
return (ret);
*bpsz = needed;
dbt->data = *bpp;
@@ -133,13 +138,12 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
*/
dbt->size = needed;
for (curoff = 0, p = dbt->data; pgno != PGNO_INVALID && needed > 0;) {
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
- (void)__db_pgerr(dbp, pgno);
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
- }
+
/* Check if we need any bytes from this page. */
if (curoff + OV_LEN(h) >= start) {
- src = (u_int8_t *)h + P_OVERHEAD;
+ src = (u_int8_t *)h + P_OVERHEAD(dbp);
bytes = OV_LEN(h);
if (start > curoff) {
src += start - curoff;
@@ -153,7 +157,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
}
curoff += OV_LEN(h);
pgno = h->next_pgno;
- memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
}
return (0);
}
@@ -171,13 +175,14 @@ __db_poff(dbc, dbt, pgnop)
db_pgno_t *pgnop;
{
DB *dbp;
- PAGE *pagep, *lastp;
- DB_LSN new_lsn, null_lsn;
DBT tmp_dbt;
+ DB_LSN new_lsn, null_lsn;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep, *lastp;
db_indx_t pagespace;
u_int32_t sz;
u_int8_t *p;
- int ret;
+ int ret, t_ret;
/*
* Allocate pages and copy the key/data item into them. Calculate the
@@ -185,8 +190,10 @@ __db_poff(dbc, dbt, pgnop)
* item.
*/
dbp = dbc->dbp;
- pagespace = P_MAXSPACE(dbp->pgsize);
+ mpf = dbp->mpf;
+ pagespace = P_MAXSPACE(dbp, dbp->pgsize);
+ ret = 0;
lastp = NULL;
for (p = dbt->data,
sz = dbt->size; sz > 0; p += pagespace, sz -= pagespace) {
@@ -203,30 +210,36 @@ __db_poff(dbc, dbt, pgnop)
* have a partial record.
*/
if ((ret = __db_new(dbc, P_OVERFLOW, &pagep)) != 0)
- return (ret);
- if (DB_LOGGING(dbc)) {
+ break;
+ if (DBC_LOGGING(dbc)) {
tmp_dbt.data = p;
tmp_dbt.size = pagespace;
ZERO_LSN(null_lsn);
- if ((ret = __db_big_log(dbp->dbenv, dbc->txn,
- &new_lsn, 0, DB_ADD_BIG, dbp->log_fileid,
- PGNO(pagep), lastp ? PGNO(lastp) : PGNO_INVALID,
+ if ((ret = __db_big_log(dbp, dbc->txn,
+ &new_lsn, 0, DB_ADD_BIG, PGNO(pagep),
+ lastp ? PGNO(lastp) : PGNO_INVALID,
PGNO_INVALID, &tmp_dbt, &LSN(pagep),
lastp == NULL ? &null_lsn : &LSN(lastp),
- &null_lsn)) != 0)
- return (ret);
+ &null_lsn)) != 0) {
+ if (lastp != NULL)
+ (void)mpf->put(mpf,
+ lastp, DB_MPOOL_DIRTY);
+ lastp = pagep;
+ break;
+ }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- if (lastp)
- LSN(lastp) = new_lsn;
- LSN(pagep) = new_lsn;
- }
+ /* Move LSN onto page. */
+ if (lastp != NULL)
+ LSN(lastp) = new_lsn;
+ LSN(pagep) = new_lsn;
P_INIT(pagep, dbp->pgsize,
PGNO(pagep), PGNO_INVALID, PGNO_INVALID, 0, P_OVERFLOW);
OV_LEN(pagep) = pagespace;
OV_REF(pagep) = 1;
- memcpy((u_int8_t *)pagep + P_OVERHEAD, p, pagespace);
+ memcpy((u_int8_t *)pagep + P_OVERHEAD(dbp), p, pagespace);
/*
* If this is the first entry, update the user's info.
@@ -238,12 +251,14 @@ __db_poff(dbc, dbt, pgnop)
else {
lastp->next_pgno = PGNO(pagep);
pagep->prev_pgno = PGNO(lastp);
- (void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, lastp, DB_MPOOL_DIRTY);
}
lastp = pagep;
}
- (void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
- return (0);
+ if (lastp != NULL &&
+ (t_ret = mpf->put(mpf, lastp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
}
/*
@@ -259,23 +274,29 @@ __db_ovref(dbc, pgno, adjust)
int32_t adjust;
{
DB *dbp;
+ DB_MPOOLFILE *mpf;
PAGE *h;
int ret;
dbp = dbc->dbp;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
- (void)__db_pgerr(dbp, pgno);
+ mpf = dbp->mpf;
+
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
+ __db_pgerr(dbp, pgno, ret);
return (ret);
}
- if (DB_LOGGING(dbc))
- if ((ret = __db_ovref_log(dbp->dbenv, dbc->txn,
- &LSN(h), 0, dbp->log_fileid, h->pgno, adjust,
- &LSN(h))) != 0)
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __db_ovref_log(dbp,
+ dbc->txn, &LSN(h), 0, h->pgno, adjust, &LSN(h))) != 0) {
+ (void)mpf->put(mpf, h, 0);
return (ret);
+ }
+ } else
+ LSN_NOT_LOGGED(LSN(h));
OV_REF(h) += adjust;
- (void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, h, DB_MPOOL_DIRTY);
return (0);
}
@@ -293,13 +314,16 @@ __db_doff(dbc, pgno)
DB *dbp;
PAGE *pagep;
DB_LSN null_lsn;
+ DB_MPOOLFILE *mpf;
DBT tmp_dbt;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
+
do {
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) {
- (void)__db_pgerr(dbp, pgno);
+ if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
+ __db_pgerr(dbp, pgno, ret);
return (ret);
}
@@ -309,20 +333,24 @@ __db_doff(dbc, pgno)
* decrement the reference count and return.
*/
if (OV_REF(pagep) > 1) {
- (void)memp_fput(dbp->mpf, pagep, 0);
+ (void)mpf->put(mpf, pagep, 0);
return (__db_ovref(dbc, pgno, -1));
}
- if (DB_LOGGING(dbc)) {
- tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD;
+ if (DBC_LOGGING(dbc)) {
+ tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD(dbp);
tmp_dbt.size = OV_LEN(pagep);
ZERO_LSN(null_lsn);
- if ((ret = __db_big_log(dbp->dbenv, dbc->txn,
- &LSN(pagep), 0, DB_REM_BIG, dbp->log_fileid,
- PGNO(pagep), PREV_PGNO(pagep), NEXT_PGNO(pagep),
- &tmp_dbt, &LSN(pagep), &null_lsn, &null_lsn)) != 0)
+ if ((ret = __db_big_log(dbp, dbc->txn,
+ &LSN(pagep), 0, DB_REM_BIG,
+ PGNO(pagep), PREV_PGNO(pagep),
+ NEXT_PGNO(pagep), &tmp_dbt,
+ &LSN(pagep), &null_lsn, &null_lsn)) != 0) {
+ (void)mpf->put(mpf, pagep, 0);
return (ret);
- }
+ }
+ } else
+ LSN_NOT_LOGGED(LSN(pagep));
pgno = pagep->next_pgno;
if ((ret = __db_free(dbc, pagep)) != 0)
return (ret);
@@ -352,13 +380,16 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
u_int32_t tlen;
int (*cmpfunc) __P((DB *, const DBT *, const DBT *)), *cmpp;
{
- PAGE *pagep;
DBT local_dbt;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep;
void *buf;
u_int32_t bufsize, cmp_bytes, key_left;
u_int8_t *p1, *p2;
int ret;
+ mpf = dbp->mpf;
+
/*
* If there is a user-specified comparison function, build a
* contiguous copy of the key, and call it.
@@ -373,27 +404,27 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
return (ret);
/* Pass the key as the first argument */
*cmpp = cmpfunc(dbp, dbt, &local_dbt);
- __os_free(buf, bufsize);
+ __os_free(dbp->dbenv, buf);
return (0);
}
/* While there are both keys to compare. */
for (*cmpp = 0, p1 = dbt->data,
key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0)
return (ret);
cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
tlen -= cmp_bytes;
key_left -= cmp_bytes;
- for (p2 =
- (u_int8_t *)pagep + P_OVERHEAD; cmp_bytes-- > 0; ++p1, ++p2)
+ for (p2 = (u_int8_t *)pagep + P_OVERHEAD(dbp);
+ cmp_bytes-- > 0; ++p1, ++p2)
if (*p1 != *p2) {
*cmpp = (long)*p1 - (long)*p2;
break;
}
pgno = NEXT_PGNO(pagep);
- if ((ret = memp_fput(dbp->mpf, pagep, 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, 0)) != 0)
return (ret);
if (*cmpp != 0)
return (0);
@@ -440,7 +471,7 @@ __db_vrfy_overflow(dbp, vdp, h, pgno, flags)
pip->refcount = OV_REF(h);
if (pip->refcount < 1) {
EPRINT((dbp->dbenv,
- "Overflow page %lu has zero reference count",
+ "Page %lu: overflow page has zero reference count",
(u_long)pgno));
isbad = 1;
}
@@ -448,7 +479,7 @@ __db_vrfy_overflow(dbp, vdp, h, pgno, flags)
/* Just store for now. */
pip->olen = HOFFSET(h);
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+err: if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -495,7 +526,7 @@ __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
if (pip->type != P_OVERFLOW) {
EPRINT((dbp->dbenv,
- "Overflow page %lu of invalid type",
+ "Page %lu: overflow page of invalid type %lu",
(u_long)pgno, (u_long)pip->type));
ret = DB_VERIFY_BAD;
goto err; /* Unsafe to continue. */
@@ -504,7 +535,8 @@ __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
prev = pip->prev_pgno;
if (prev != PGNO_INVALID) {
EPRINT((dbp->dbenv,
- "First overflow page %lu has a prev_pgno", (u_long)pgno));
+ "Page %lu: first page in overflow chain has a prev_pgno %lu",
+ (u_long)pgno, (u_long)prev));
isbad = 1;
}
@@ -543,7 +575,7 @@ __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
*/
if ((u_int32_t)p > refcount) {
EPRINT((dbp->dbenv,
- "Page %lu encountered twice in overflow traversal",
+ "Page %lu: encountered twice in overflow traversal",
(u_long)pgno));
ret = DB_VERIFY_BAD;
goto err;
@@ -571,19 +603,20 @@ __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
if (!IS_VALID_PGNO(next)) {
DB_ASSERT(0);
EPRINT((dbp->dbenv,
- "Overflow page %lu has bad next_pgno",
- (u_long)pgno));
+ "Page %lu: bad next_pgno %lu on overflow page",
+ (u_long)pgno, (u_long)next));
ret = DB_VERIFY_BAD;
goto err;
}
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 ||
+ if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
(ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
return (ret);
if (pip->prev_pgno != pgno) {
EPRINT((dbp->dbenv,
- "Overflow page %lu has bogus prev_pgno value",
- (u_long)next));
+ "Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",
+ (u_long)next, (u_long)pip->prev_pgno,
+ (u_long)pgno));
isbad = 1;
/*
* It's safe to continue because we have separate
@@ -597,10 +630,11 @@ __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
if (tlen > 0) {
isbad = 1;
EPRINT((dbp->dbenv,
- "Overflow item incomplete on page %lu", (u_long)pgno));
+ "Page %lu: overflow item incomplete", (u_long)pgno));
}
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -622,13 +656,15 @@ __db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
void **buf;
u_int32_t flags;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
- int ret, err_ret;
+ int ret, t_ret;
u_int32_t bytesgot, bytes;
u_int8_t *src, *dest;
- ret = DB_VERIFY_BAD;
- err_ret = 0;
+ mpf = dbp->mpf;
+ h = NULL;
+ ret = t_ret = 0;
bytesgot = bytes = 0;
while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
@@ -639,7 +675,7 @@ __db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
break;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
break;
/*
@@ -651,14 +687,14 @@ __db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
break;
}
- src = (u_int8_t *)h + P_OVERHEAD;
+ src = (u_int8_t *)h + P_OVERHEAD(dbp);
bytes = OV_LEN(h);
- if (bytes + P_OVERHEAD > dbp->pgsize)
- bytes = dbp->pgsize - P_OVERHEAD;
+ if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)
+ bytes = dbp->pgsize - P_OVERHEAD(dbp);
if ((ret = __os_realloc(dbp->dbenv,
- bytesgot + bytes, 0, buf)) != 0)
+ bytesgot + bytes, buf)) != 0)
break;
dest = (u_int8_t *)*buf + bytesgot;
@@ -667,15 +703,24 @@ __db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
memcpy(dest, src, bytes);
pgno = NEXT_PGNO(h);
- /* Not much we can do here--we don't want to quit. */
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
- err_ret = ret;
+
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
+ break;
+ h = NULL;
}
- if (ret == 0) {
+ /*
+ * If we're being aggressive, salvage a partial datum if there
+ * was an error somewhere along the way.
+ */
+ if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {
dbt->size = bytesgot;
dbt->data = *buf;
}
- return ((err_ret != 0 && ret == 0) ? err_ret : ret);
+ /* If we broke out on error, don't leave pages pinned. */
+ if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
}
diff --git a/bdb/db/db_pr.c b/bdb/db/db_pr.c
index cb977cadfda..235e7187f7c 100644
--- a/bdb/db/db_pr.c
+++ b/bdb/db/db_pr.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_pr.c,v 11.46 2001/01/22 17:25:06 krinsky Exp $";
+static const char revid[] = "$Id: db_pr.c,v 11.84 2002/09/10 02:45:20 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -21,34 +21,24 @@ static const char revid[] = "$Id: db_pr.c,v 11.46 2001/01/22 17:25:06 krinsky Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
-#include "db_am.h"
-#include "db_verify.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+#include "dbinc/db_verify.h"
static int __db_bmeta __P((DB *, FILE *, BTMETA *, u_int32_t));
static int __db_hmeta __P((DB *, FILE *, HMETA *, u_int32_t));
static void __db_meta __P((DB *, DBMETA *, FILE *, FN const *, u_int32_t));
-static const char *__db_dbtype_to_string __P((DB *));
-static void __db_prdb __P((DB *, FILE *, u_int32_t));
-static FILE *__db_prinit __P((FILE *));
-static void __db_proff __P((void *));
-static int __db_prtree __P((DB *, u_int32_t));
-static void __db_psize __P((DB *));
+static const char *__db_pagetype_to_string __P((u_int32_t));
+static void __db_prdb __P((DB *, FILE *));
+static void __db_proff __P((void *, FILE *));
+static int __db_prtree __P((DB *, FILE *, u_int32_t));
static int __db_qmeta __P((DB *, FILE *, QMETA *, u_int32_t));
/*
- * 64K is the maximum page size, so by default we check for offsets larger
- * than that, and, where possible, we refine the test.
- */
-#define PSIZE_BOUNDARY (64 * 1024 + 1)
-static size_t set_psize = PSIZE_BOUNDARY;
-
-static FILE *set_fp; /* Output file descriptor. */
-
-/*
* __db_loadme --
* A nice place to put a breakpoint.
*
@@ -57,7 +47,9 @@ static FILE *set_fp; /* Output file descriptor. */
void
__db_loadme()
{
- getpid();
+ u_int32_t id;
+
+ __os_id(&id);
}
/*
@@ -71,21 +63,9 @@ __db_dump(dbp, op, name)
DB *dbp;
char *op, *name;
{
- FILE *fp, *save_fp;
+ FILE *fp;
u_int32_t flags;
-
- COMPQUIET(save_fp, NULL);
-
- if (set_psize == PSIZE_BOUNDARY)
- __db_psize(dbp);
-
- if (name != NULL) {
- if ((fp = fopen(name, "w")) == NULL)
- return (__os_get_errno());
- save_fp = set_fp;
- set_fp = fp;
- } else
- fp = __db_prinit(NULL);
+ int ret;
for (flags = 0; *op != '\0'; ++op)
switch (*op) {
@@ -101,60 +81,93 @@ __db_dump(dbp, op, name)
return (EINVAL);
}
- __db_prdb(dbp, fp, flags);
+ if (name == NULL)
+ fp = stdout;
+ else {
+ if ((fp = fopen(name, "w")) == NULL)
+ return (__os_get_errno());
+ }
+
+ __db_prdb(dbp, fp);
fprintf(fp, "%s\n", DB_LINE);
- (void)__db_prtree(dbp, flags);
+ ret = __db_prtree(dbp, fp, flags);
fflush(fp);
-
- if (name != NULL) {
+ if (name != NULL)
fclose(fp);
- set_fp = save_fp;
- }
- return (0);
+
+ return (ret);
}
/*
- * __db_prdb --
- * Print out the DB structure information.
+ * __db_inmemdbflags --
+ * Call a callback for printing or other handling of strings associated
+ * with whatever in-memory DB structure flags are set.
+ *
+ * PUBLIC: void __db_inmemdbflags __P((u_int32_t, void *,
+ * PUBLIC: void (*)(u_int32_t, const FN *, void *)));
*/
-static void
-__db_prdb(dbp, fp, flags)
- DB *dbp;
- FILE *fp;
+void
+__db_inmemdbflags(flags, cookie, callback)
u_int32_t flags;
+ void *cookie;
+ void (*callback) __P((u_int32_t, const FN *, void *));
{
static const FN fn[] = {
+ { DB_AM_CHKSUM, "checksumming" },
+ { DB_AM_CL_WRITER, "client replica writer" },
+ { DB_AM_COMPENSATE, "created by compensating transaction" },
+ { DB_AM_CREATED, "database created" },
+ { DB_AM_CREATED_MSTR, "encompassing file created" },
+ { DB_AM_DBM_ERROR, "dbm/ndbm error" },
+ { DB_AM_DELIMITER, "variable length" },
+ { DB_AM_DIRTY, "dirty reads" },
{ DB_AM_DISCARD, "discard cached pages" },
{ DB_AM_DUP, "duplicates" },
+ { DB_AM_DUPSORT, "sorted duplicates" },
+ { DB_AM_ENCRYPT, "encrypted" },
+ { DB_AM_FIXEDLEN, "fixed-length records" },
{ DB_AM_INMEM, "in-memory" },
+ { DB_AM_IN_RENAME, "file is being renamed" },
+ { DB_AM_OPEN_CALLED, "DB->open called" },
+ { DB_AM_PAD, "pad value" },
{ DB_AM_PGDEF, "default page size" },
{ DB_AM_RDONLY, "read-only" },
- { DB_AM_SUBDB, "multiple-databases" },
+ { DB_AM_RECNUM, "Btree record numbers" },
+ { DB_AM_RECOVER, "opened for recovery" },
+ { DB_AM_RENUMBER, "renumber" },
+ { DB_AM_REVSPLITOFF, "no reverse splits" },
+ { DB_AM_SECONDARY, "secondary" },
+ { DB_AM_SNAPSHOT, "load on open" },
+ { DB_AM_SUBDB, "subdatabases" },
{ DB_AM_SWAP, "needswap" },
- { DB_BT_RECNUM, "btree:recnum" },
- { DB_BT_REVSPLIT, "btree:no reverse split" },
- { DB_DBM_ERROR, "dbm/ndbm error" },
- { DB_OPEN_CALLED, "DB->open called" },
- { DB_RE_DELIMITER, "recno:delimiter" },
- { DB_RE_FIXEDLEN, "recno:fixed-length" },
- { DB_RE_PAD, "recno:pad" },
- { DB_RE_RENUMBER, "recno:renumber" },
- { DB_RE_SNAPSHOT, "recno:snapshot" },
+ { DB_AM_TXN, "transactional" },
+ { DB_AM_VERIFYING, "verifier" },
{ 0, NULL }
};
+
+ callback(flags, fn, cookie);
+}
+
+/*
+ * __db_prdb --
+ * Print out the DB structure information.
+ */
+static void
+__db_prdb(dbp, fp)
+ DB *dbp;
+ FILE *fp;
+{
BTREE *bt;
HASH *h;
QUEUE *q;
- COMPQUIET(flags, 0);
-
fprintf(fp,
"In-memory DB structure:\n%s: %#lx",
- __db_dbtype_to_string(dbp), (u_long)dbp->flags);
- __db_prflags(dbp->flags, fn, fp);
+ __db_dbtype_to_string(dbp->type), (u_long)dbp->flags);
+ __db_inmemdbflags(dbp->flags, fp, __db_prflags);
fprintf(fp, "\n");
switch (dbp->type) {
@@ -166,7 +179,7 @@ __db_prdb(dbp, fp, flags)
fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n",
(u_long)bt->bt_maxkey, (u_long)bt->bt_minkey);
fprintf(fp, "bt_compare: %#lx bt_prefix: %#lx\n",
- (u_long)bt->bt_compare, (u_long)bt->bt_prefix);
+ P_TO_ULONG(bt->bt_compare), P_TO_ULONG(bt->bt_prefix));
fprintf(fp, "bt_lpgno: %lu\n", (u_long)bt->bt_lpgno);
if (dbp->type == DB_RECNO) {
fprintf(fp,
@@ -183,7 +196,7 @@ __db_prdb(dbp, fp, flags)
fprintf(fp, "meta_pgno: %lu\n", (u_long)h->meta_pgno);
fprintf(fp, "h_ffactor: %lu\n", (u_long)h->h_ffactor);
fprintf(fp, "h_nelem: %lu\n", (u_long)h->h_nelem);
- fprintf(fp, "h_hash: %#lx\n", (u_long)h->h_hash);
+ fprintf(fp, "h_hash: %#lx\n", P_TO_ULONG(h->h_hash));
break;
case DB_QUEUE:
q = dbp->q_internal;
@@ -204,39 +217,34 @@ __db_prdb(dbp, fp, flags)
* Print out the entire tree.
*/
static int
-__db_prtree(dbp, flags)
+__db_prtree(dbp, fp, flags)
DB *dbp;
+ FILE *fp;
u_int32_t flags;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t i, last;
int ret;
- if (set_psize == PSIZE_BOUNDARY)
- __db_psize(dbp);
+ mpf = dbp->mpf;
- if (dbp->type == DB_QUEUE) {
- ret = __db_prqueue(dbp, flags);
- goto done;
- }
-
- /* Find out the page number of the last page in the database. */
- if ((ret = memp_fget(dbp->mpf, &last, DB_MPOOL_LAST, &h)) != 0)
- return (ret);
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
- return (ret);
+ if (dbp->type == DB_QUEUE)
+ return (__db_prqueue(dbp, fp, flags));
- /* Dump each page. */
+ /*
+ * Find out the page number of the last page in the database, then
+ * dump each page.
+ */
+ mpf->last_pgno(mpf, &last);
for (i = 0; i <= last; ++i) {
- if ((ret = memp_fget(dbp->mpf, &i, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &i, 0, &h)) != 0)
return (ret);
- (void)__db_prpage(dbp, h, flags);
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ (void)__db_prpage(dbp, h, fp, flags);
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
return (ret);
}
-done:
- (void)fflush(__db_prinit(NULL));
return (0);
}
@@ -252,13 +260,15 @@ __db_meta(dbp, dbmeta, fp, fn, flags)
FN const *fn;
u_int32_t flags;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
- int cnt;
db_pgno_t pgno;
u_int8_t *p;
- int ret;
+ int cnt, ret;
const char *sep;
+ mpf = dbp->mpf;
+
fprintf(fp, "\tmagic: %#lx\n", (u_long)dbmeta->magic);
fprintf(fp, "\tversion: %lu\n", (u_long)dbmeta->version);
fprintf(fp, "\tpagesize: %lu\n", (u_long)dbmeta->pagesize);
@@ -275,14 +285,14 @@ __db_meta(dbp, dbmeta, fp, fn, flags)
fprintf(fp, "\tfree list: %lu", (u_long)dbmeta->free);
for (pgno = dbmeta->free,
cnt = 0, sep = ", "; pgno != PGNO_INVALID;) {
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
fprintf(fp,
"Unable to retrieve free-list page: %lu: %s\n",
(u_long)pgno, db_strerror(ret));
break;
}
pgno = h->next_pgno;
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
fprintf(fp, "%s%lu", sep, (u_long)pgno);
if (++cnt % 10 == 0) {
fprintf(fp, "\n");
@@ -292,6 +302,7 @@ __db_meta(dbp, dbmeta, fp, fn, flags)
sep = ", ";
}
fprintf(fp, "\n");
+ fprintf(fp, "\tlast_pgno: %lu\n", (u_long)dbmeta->last_pgno);
}
if (fn != NULL) {
@@ -404,26 +415,28 @@ __db_qmeta(dbp, fp, h, flags)
* __db_prnpage
* -- Print out a specific page.
*
- * PUBLIC: int __db_prnpage __P((DB *, db_pgno_t));
+ * PUBLIC: int __db_prnpage __P((DB *, db_pgno_t, FILE *));
*/
int
-__db_prnpage(dbp, pgno)
+__db_prnpage(dbp, pgno, fp)
DB *dbp;
db_pgno_t pgno;
+ FILE *fp;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
- int ret;
+ int ret, t_ret;
- if (set_psize == PSIZE_BOUNDARY)
- __db_psize(dbp);
+ mpf = dbp->mpf;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
- ret = __db_prpage(dbp, h, DB_PR_PAGE);
- (void)fflush(__db_prinit(NULL));
+ ret = __db_prpage(dbp, h, fp, DB_PR_PAGE);
+
+ if ((t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+ ret = t_ret;
- (void)memp_fput(dbp->mpf, h, 0);
return (ret);
}
@@ -431,32 +444,29 @@ __db_prnpage(dbp, pgno)
* __db_prpage
* -- Print out a page.
*
- * PUBLIC: int __db_prpage __P((DB *, PAGE *, u_int32_t));
+ * PUBLIC: int __db_prpage __P((DB *, PAGE *, FILE *, u_int32_t));
*/
int
-__db_prpage(dbp, h, flags)
+__db_prpage(dbp, h, fp, flags)
DB *dbp;
PAGE *h;
+ FILE *fp;
u_int32_t flags;
{
BINTERNAL *bi;
BKEYDATA *bk;
- BTREE *t;
- FILE *fp;
HOFFPAGE a_hkd;
QAMDATA *qp, *qep;
RINTERNAL *ri;
- db_indx_t dlen, len, i;
+ db_indx_t dlen, len, i, *inp;
db_pgno_t pgno;
db_recno_t recno;
+ u_int32_t pagesize, qlen;
+ u_int8_t *ep, *hk, *p;
int deleted, ret;
const char *s;
- u_int32_t qlen;
- u_int8_t *ep, *hk, *p;
void *sp;
- fp = __db_prinit(NULL);
-
/*
* If we're doing recovery testing and this page is P_INVALID,
* assume it's a page that's on the free list, and don't display it.
@@ -471,6 +481,14 @@ __db_prpage(dbp, h, flags)
return (1);
}
+ /*
+ * !!!
+ * Find out the page size. We don't want to do it the "right" way,
+ * by reading the value from the meta-data page, that's going to be
+ * slow. Reach down into the mpool region.
+ */
+ pagesize = (u_int32_t)dbp->mpf->mfp->stat.st_pagesize;
+
/* Page number, page type. */
fprintf(fp, "page %lu: %s level: %lu",
(u_long)h->pgno, s, (u_long)h->level);
@@ -500,7 +518,7 @@ __db_prpage(dbp, h, flags)
qlen = ((QUEUE *)dbp->q_internal)->re_len;
recno = (h->pgno - 1) * QAM_RECNO_PER_PAGE(dbp) + 1;
i = 0;
- qep = (QAMDATA *)((u_int8_t *)h + set_psize - qlen);
+ qep = (QAMDATA *)((u_int8_t *)h + pagesize - qlen);
for (qp = QAM_GET_RECORD(dbp, h, i); qp < qep;
recno++, i++, qp = QAM_GET_RECORD(dbp, h, i)) {
if (!F_ISSET(qp, QAM_SET))
@@ -508,9 +526,9 @@ __db_prpage(dbp, h, flags)
fprintf(fp, "%s",
F_ISSET(qp, QAM_VALID) ? "\t" : " D");
- fprintf(fp, "[%03lu] %4lu ",
- (u_long)recno, (u_long)qp - (u_long)h);
- __db_pr(qp->data, qlen);
+ fprintf(fp, "[%03lu] %4lu ", (u_long)recno,
+ (u_long)((u_int8_t *)qp - (u_int8_t *)h));
+ __db_pr(qp->data, qlen, fp);
}
return (0);
}
@@ -520,8 +538,6 @@ __db_prpage(dbp, h, flags)
fprintf(fp, " (lsn.file: %lu lsn.offset: %lu)\n",
(u_long)LSN(h).file, (u_long)LSN(h).offset);
- t = dbp->bt_internal;
-
s = "\t";
if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
fprintf(fp, "%sprev: %4lu next: %4lu",
@@ -530,7 +546,7 @@ __db_prpage(dbp, h, flags)
}
if (TYPE(h) == P_OVERFLOW) {
fprintf(fp, "%sref cnt: %4lu ", s, (u_long)OV_REF(h));
- __db_pr((u_int8_t *)h + P_OVERHEAD, OV_LEN(h));
+ __db_pr((u_int8_t *)h + P_OVERHEAD(dbp), OV_LEN(h), fp);
return (0);
}
fprintf(fp, "%sentries: %4lu", s, (u_long)NUM_ENT(h));
@@ -540,12 +556,14 @@ __db_prpage(dbp, h, flags)
return (0);
ret = 0;
+ inp = P_INP(dbp, h);
for (i = 0; i < NUM_ENT(h); i++) {
- if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD ||
- (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) {
+ if ((db_alignp_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) <
+ (db_alignp_t)(P_OVERHEAD(dbp)) ||
+ (size_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) >= pagesize) {
fprintf(fp,
"ILLEGAL PAGE OFFSET: indx: %lu of %lu\n",
- (u_long)i, (u_long)h->inp[i]);
+ (u_long)i, (u_long)inp[i]);
ret = EINVAL;
continue;
}
@@ -554,17 +572,17 @@ __db_prpage(dbp, h, flags)
case P_HASH:
case P_IBTREE:
case P_IRECNO:
- sp = P_ENTRY(h, i);
+ sp = P_ENTRY(dbp, h, i);
break;
case P_LBTREE:
- sp = P_ENTRY(h, i);
+ sp = P_ENTRY(dbp, h, i);
deleted = i % 2 == 0 &&
- B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type);
+ B_DISSET(GET_BKEYDATA(dbp, h, i + O_INDX)->type);
break;
case P_LDUP:
case P_LRECNO:
- sp = P_ENTRY(h, i);
- deleted = B_DISSET(GET_BKEYDATA(h, i)->type);
+ sp = P_ENTRY(dbp, h, i);
+ deleted = B_DISSET(GET_BKEYDATA(dbp, h, i)->type);
break;
default:
fprintf(fp,
@@ -573,7 +591,7 @@ __db_prpage(dbp, h, flags)
continue;
}
fprintf(fp, "%s", deleted ? " D" : "\t");
- fprintf(fp, "[%03lu] %4lu ", (u_long)i, (u_long)h->inp[i]);
+ fprintf(fp, "[%03lu] %4lu ", (u_long)i, (u_long)inp[i]);
switch (TYPE(h)) {
case P_HASH:
hk = sp;
@@ -592,7 +610,7 @@ __db_prpage(dbp, h, flags)
* set.
*/
if (i != 0)
- len = LEN_HKEYDATA(h, 0, i);
+ len = LEN_HKEYDATA(dbp, h, 0, i);
else
len = 1;
@@ -602,13 +620,14 @@ __db_prpage(dbp, h, flags)
memcpy(&dlen, p, sizeof(db_indx_t));
p += sizeof(db_indx_t);
fprintf(fp, "\t\t");
- __db_pr(p, dlen);
+ __db_pr(p, dlen, fp);
p += sizeof(db_indx_t) + dlen;
}
break;
case H_KEYDATA:
__db_pr(HKEYDATA_DATA(hk),
- LEN_HKEYDATA(h, i == 0 ? set_psize : 0, i));
+ LEN_HKEYDATA(dbp, h, i == 0 ?
+ pagesize : 0, i), fp);
break;
case H_OFFPAGE:
memcpy(&a_hkd, hk, HOFFPAGE_SIZE);
@@ -625,11 +644,11 @@ __db_prpage(dbp, h, flags)
(u_long)bi->type);
switch (B_TYPE(bi->type)) {
case B_KEYDATA:
- __db_pr(bi->data, bi->len);
+ __db_pr(bi->data, bi->len, fp);
break;
case B_DUPLICATE:
case B_OVERFLOW:
- __db_proff(bi->data);
+ __db_proff(bi->data, fp);
break;
default:
fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n",
@@ -649,11 +668,11 @@ __db_prpage(dbp, h, flags)
bk = sp;
switch (B_TYPE(bk->type)) {
case B_KEYDATA:
- __db_pr(bk->data, bk->len);
+ __db_pr(bk->data, bk->len, fp);
break;
case B_DUPLICATE:
case B_OVERFLOW:
- __db_proff(bk);
+ __db_proff(bk, fp);
break;
default:
fprintf(fp,
@@ -673,19 +692,17 @@ __db_prpage(dbp, h, flags)
* __db_pr --
* Print out a data element.
*
- * PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t));
+ * PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t, FILE *));
*/
void
-__db_pr(p, len)
+__db_pr(p, len, fp)
u_int8_t *p;
u_int32_t len;
-{
FILE *fp;
+{
u_int lastch;
int i;
- fp = __db_prinit(NULL);
-
fprintf(fp, "len: %3lu", (u_long)len);
lastch = '.';
if (len != 0) {
@@ -744,6 +761,13 @@ __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
handle, callback, vdp, 0);
F_CLR(vdp, SALVAGE_PRINTHEADER);
F_SET(vdp, SALVAGE_PRINTFOOTER);
+
+ /*
+ * Even if the printable flag wasn't set by our immediate
+ * caller, it may be set on a salvage-wide basis.
+ */
+ if (F_ISSET(vdp, SALVAGE_PRINTABLE))
+ checkprint = 1;
}
/*
@@ -760,12 +784,12 @@ __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
* in a platform-independent way. So we use the numeral in
* straight ASCII.
*/
- __ua_memcpy(&recno, dbtp->data, sizeof(recno));
+ (void)__ua_memcpy(&recno, dbtp->data, sizeof(recno));
snprintf(buf, DBTBUFLEN, "%lu", (u_long)recno);
/* If we're printing data as hex, print keys as hex too. */
if (!checkprint) {
- for (len = strlen(buf), p = buf, hp = hbuf;
+ for (len = (u_int32_t)strlen(buf), p = buf, hp = hbuf;
len-- > 0; ++p) {
*hp++ = hex[(u_int8_t)(*p & 0xf0) >> 4];
*hp++ = hex[*p & 0x0f];
@@ -810,14 +834,12 @@ __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
* Print out an off-page element.
*/
static void
-__db_proff(vp)
+__db_proff(vp, fp)
void *vp;
-{
FILE *fp;
+{
BOVERFLOW *bo;
- fp = __db_prinit(NULL);
-
bo = vp;
switch (B_TYPE(bo->type)) {
case B_OVERFLOW:
@@ -834,18 +856,25 @@ __db_proff(vp)
* __db_prflags --
* Print out flags values.
*
- * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, FILE *));
+ * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, void *));
*/
void
-__db_prflags(flags, fn, fp)
+__db_prflags(flags, fn, vfp)
u_int32_t flags;
FN const *fn;
- FILE *fp;
+ void *vfp;
{
+ FILE *fp;
const FN *fnp;
int found;
const char *sep;
+ /*
+ * We pass the FILE * through a void * so that we can use
+ * this function as as a callback.
+ */
+ fp = (FILE *)vfp;
+
sep = " (";
for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
if (LF_ISSET(fnp->mask)) {
@@ -858,62 +887,21 @@ __db_prflags(flags, fn, fp)
}
/*
- * __db_prinit --
- * Initialize tree printing routines.
- */
-static FILE *
-__db_prinit(fp)
- FILE *fp;
-{
- if (set_fp == NULL)
- set_fp = fp == NULL ? stdout : fp;
- return (set_fp);
-}
-
-/*
- * __db_psize --
- * Get the page size.
- */
-static void
-__db_psize(dbp)
- DB *dbp;
-{
- DBMETA *mp;
- db_pgno_t pgno;
-
- set_psize = PSIZE_BOUNDARY - 1;
-
- pgno = PGNO_BASE_MD;
- if (memp_fget(dbp->mpf, &pgno, 0, &mp) != 0)
- return;
-
- switch (mp->magic) {
- case DB_BTREEMAGIC:
- case DB_HASHMAGIC:
- case DB_QAMMAGIC:
- set_psize = mp->pagesize;
- break;
- }
- (void)memp_fput(dbp->mpf, mp, 0);
-}
-
-/*
* __db_dbtype_to_string --
* Return the name of the database type.
+ * PUBLIC: const char * __db_dbtype_to_string __P((DBTYPE));
*/
-static const char *
-__db_dbtype_to_string(dbp)
- DB *dbp;
+const char *
+__db_dbtype_to_string(type)
+ DBTYPE type;
{
- switch (dbp->type) {
+ switch (type) {
case DB_BTREE:
return ("btree");
case DB_HASH:
return ("hash");
- break;
case DB_RECNO:
return ("recno");
- break;
case DB_QUEUE:
return ("queue");
default:
@@ -925,10 +913,8 @@ __db_dbtype_to_string(dbp)
/*
* __db_pagetype_to_string --
* Return the name of the specified page type.
- *
- * PUBLIC: const char *__db_pagetype_to_string __P((u_int32_t));
*/
-const char *
+static const char *
__db_pagetype_to_string(type)
u_int32_t type;
{
@@ -1000,6 +986,7 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
DB_ENV *dbenv;
DB_HASH_STAT *hsp;
DB_QUEUE_STAT *qsp;
+ DBT dbt;
VRFY_PAGEINFO *pip;
char *buf;
int buflen, ret, t_ret;
@@ -1021,10 +1008,16 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
* If we've been passed a verifier statistics object, use
* that; we're being called in a context where dbp->stat
* is unsafe.
+ *
+ * Also, the verifier may set the pflag on a per-salvage basis.
+ * If so, respect that.
*/
if (vdp != NULL) {
if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
return (ret);
+
+ if (F_ISSET(vdp, SALVAGE_PRINTABLE))
+ pflag = 1;
} else
pip = NULL;
@@ -1071,16 +1064,22 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
/*
* 64 bytes is long enough, as a minimum bound, for any of the
- * fields besides subname. Subname can be anything, and so
- * 64 + subname is big enough for all the things we need to print here.
+ * fields besides subname. Subname uses __db_prdbt and therefore
+ * does not need buffer space here.
*/
- buflen = 64 + ((subname != NULL) ? strlen(subname) : 0);
- if ((ret = __os_malloc(dbenv, buflen, NULL, &buf)) != 0)
+ buflen = 64;
+ if ((ret = __os_malloc(dbenv, buflen, &buf)) != 0)
goto err;
if (subname != NULL) {
- snprintf(buf, buflen, "database=%s\n", subname);
+ snprintf(buf, buflen, "database=");
if ((ret = callback(handle, buf)) != 0)
goto err;
+ memset(&dbt, 0, sizeof(dbt));
+ dbt.data = subname;
+ dbt.size = (u_int32_t)strlen(subname);
+ if ((ret = __db_prdbt(&dbt,
+ 1, NULL, handle, callback, 0, NULL)) != 0)
+ goto err;
}
switch (dbtype) {
case DB_BTREE:
@@ -1106,11 +1105,11 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
}
break;
}
- if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &btsp, 0)) != 0) {
dbp->err(dbp, ret, "DB->stat");
goto err;
}
- if (F_ISSET(dbp, DB_BT_RECNUM))
+ if (F_ISSET(dbp, DB_AM_RECNUM))
if ((ret = callback(handle, "recnum=1\n")) != 0)
goto err;
if (btsp->bt_maxkey != 0) {
@@ -1144,7 +1143,7 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
}
break;
}
- if ((ret = dbp->stat(dbp, &hsp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &hsp, 0)) != 0) {
dbp->err(dbp, ret, "DB->stat");
goto err;
}
@@ -1154,10 +1153,9 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
if ((ret = callback(handle, buf)) != 0)
goto err;
}
- if (hsp->hash_nelem != 0 || hsp->hash_nkeys != 0) {
- snprintf(buf, buflen, "h_nelem=%lu\n",
- hsp->hash_nelem > hsp->hash_nkeys ?
- (u_long)hsp->hash_nelem : (u_long)hsp->hash_nkeys);
+ if (hsp->hash_nkeys != 0) {
+ snprintf(buf, buflen,
+ "h_nelem=%lu\n", (u_long)hsp->hash_nkeys);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
@@ -1172,15 +1170,24 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
goto err;
break;
}
- if ((ret = dbp->stat(dbp, &qsp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &qsp, 0)) != 0) {
dbp->err(dbp, ret, "DB->stat");
goto err;
}
snprintf(buf, buflen, "re_len=%lu\n", (u_long)qsp->qs_re_len);
- if (qsp->qs_re_pad != 0 && qsp->qs_re_pad != ' ')
- snprintf(buf, buflen, "re_pad=%#x\n", qsp->qs_re_pad);
if ((ret = callback(handle, buf)) != 0)
goto err;
+ if (qsp->qs_re_pad != 0 && qsp->qs_re_pad != ' ') {
+ snprintf(buf, buflen, "re_pad=%#x\n", qsp->qs_re_pad);
+ if ((ret = callback(handle, buf)) != 0)
+ goto err;
+ }
+ if (qsp->qs_extentsize != 0) {
+ snprintf(buf, buflen,
+ "extentsize=%lu\n", (u_long)qsp->qs_extentsize);
+ if ((ret = callback(handle, buf)) != 0)
+ goto err;
+ }
break;
case DB_RECNO:
if ((ret = callback(handle, "type=recno\n")) != 0)
@@ -1198,14 +1205,14 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
}
break;
}
- if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &btsp, 0)) != 0) {
dbp->err(dbp, ret, "DB->stat");
goto err;
}
- if (F_ISSET(dbp, DB_RE_RENUMBER))
+ if (F_ISSET(dbp, DB_AM_RENUMBER))
if ((ret = callback(handle, "renumber=1\n")) != 0)
goto err;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
snprintf(buf, buflen,
"re_len=%lu\n", (u_long)btsp->bt_re_len);
if ((ret = callback(handle, buf)) != 0)
@@ -1233,6 +1240,9 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
goto err;
/* We should handle page size. XXX */
} else {
+ if (F_ISSET(dbp, DB_AM_CHKSUM))
+ if ((ret = callback(handle, "chksum=1\n")) != 0)
+ goto err;
if (F_ISSET(dbp, DB_AM_DUP))
if ((ret = callback(handle, "duplicates=1\n")) != 0)
goto err;
@@ -1253,16 +1263,16 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
ret = callback(handle, "HEADER=END\n");
err: if (pip != NULL &&
- (t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+ (t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
if (btsp != NULL)
- __os_free(btsp, 0);
+ __os_ufree(dbenv, btsp);
if (hsp != NULL)
- __os_free(hsp, 0);
+ __os_ufree(dbenv, hsp);
if (qsp != NULL)
- __os_free(qsp, 0);
+ __os_ufree(dbenv, qsp);
if (buf != NULL)
- __os_free(buf, buflen);
+ __os_free(dbenv, buf);
return (ret);
}
diff --git a/bdb/db/db_rec.c b/bdb/db/db_rec.c
index 998d074290d..303ab2fe1d4 100644
--- a/bdb/db/db_rec.c
+++ b/bdb/db/db_rec.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_rec.c,v 11.10 2000/08/03 15:32:19 ubell Exp $";
+static const char revid[] = "$Id: db_rec.c,v 11.35 2002/08/08 03:57:49 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,9 +18,9 @@ static const char revid[] = "$Id: db_rec.c,v 11.10 2000/08/03 15:32:19 ubell Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "log.h"
-#include "hash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/log.h"
+#include "dbinc/hash.h"
/*
* PUBLIC: int __db_addrem_recover
@@ -45,11 +45,12 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
u_int32_t change;
int cmp_n, cmp_p, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_addrem_print);
REC_INTRO(__db_addrem_read, 1);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -59,7 +60,7 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
*/
goto done;
} else
- if ((ret = memp_fget(mpf,
+ if ((ret = mpf->get(mpf,
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -95,13 +96,16 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
LSN(pagep) = argp->pagelsn;
}
- if ((ret = memp_fput(mpf, pagep, change)) != 0)
+ if ((ret = mpf->put(mpf, pagep, change)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -124,11 +128,12 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
u_int32_t change;
int cmp_n, cmp_p, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_big_print);
REC_INTRO(__db_big_read, 1);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -139,7 +144,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
ret = 0;
goto ppage;
} else
- if ((ret = memp_fget(mpf,
+ if ((ret = mpf->get(mpf,
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -161,7 +166,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
argp->next_pgno, 0, P_OVERFLOW);
OV_LEN(pagep) = argp->dbt.size;
OV_REF(pagep) = 1;
- memcpy((u_int8_t *)pagep + P_OVERHEAD, argp->dbt.data,
+ memcpy((u_int8_t *)pagep + P_OVERHEAD(file_dbp), argp->dbt.data,
argp->dbt.size);
PREV_PGNO(pagep) = argp->prev_pgno;
change = DB_MPOOL_DIRTY;
@@ -177,13 +182,21 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
if (change)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
- if ((ret = memp_fput(mpf, pagep, change)) != 0)
+ if ((ret = mpf->put(mpf, pagep, change)) != 0)
goto out;
+ pagep = NULL;
+
+ /*
+ * We only delete a whole chain of overflow.
+ * Each page is handled individually
+ */
+ if (argp->opcode == DB_REM_BIG)
+ goto done;
/* Now check the previous page. */
ppage: if (argp->prev_pgno != PGNO_INVALID) {
change = 0;
- if ((ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist.
@@ -195,7 +208,7 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
ret = 0;
goto npage;
} else
- if ((ret = memp_fget(mpf, &argp->prev_pgno,
+ if ((ret = mpf->get(mpf, &argp->prev_pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -204,28 +217,27 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
- if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
- (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
+ if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {
/* Redo add, undo delete. */
NEXT_PGNO(pagep) = argp->pgno;
change = DB_MPOOL_DIRTY;
- } else if ((cmp_n == 0 &&
- DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
- (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
+ } else if (cmp_n == 0 &&
+ DB_UNDO(op) && argp->opcode == DB_ADD_BIG) {
/* Redo delete, undo add. */
NEXT_PGNO(pagep) = argp->next_pgno;
change = DB_MPOOL_DIRTY;
}
if (change)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
- if ((ret = memp_fput(mpf, pagep, change)) != 0)
+ if ((ret = mpf->put(mpf, pagep, change)) != 0)
goto out;
}
+ pagep = NULL;
/* Now check the next page. Can only be set on a delete. */
npage: if (argp->next_pgno != PGNO_INVALID) {
change = 0;
- if ((ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist.
@@ -235,7 +247,7 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
*/
goto done;
} else
- if ((ret = memp_fget(mpf, &argp->next_pgno,
+ if ((ret = mpf->get(mpf, &argp->next_pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -252,21 +264,25 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
}
if (change)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
- if ((ret = memp_fput(mpf, pagep, change)) != 0)
+ if ((ret = mpf->put(mpf, pagep, change)) != 0)
goto out;
}
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
* __db_ovref_recover --
* Recovery function for __db_ovref().
*
- * PUBLIC: int __db_ovref_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ * PUBLIC: int __db_ovref_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__db_ovref_recover(dbenv, dbtp, lsnp, op, info)
@@ -283,14 +299,15 @@ __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
PAGE *pagep;
int cmp, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_ovref_print);
REC_INTRO(__db_ovref_read, 1);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
@@ -310,13 +327,16 @@ __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
pagep->lsn = argp->lsn;
modified = 1;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -341,6 +361,7 @@ __db_relink_recover(dbenv, dbtp, lsnp, op, info)
PAGE *pagep;
int cmp_n, cmp_p, modified, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_relink_print);
REC_INTRO(__db_relink_read, 1);
@@ -351,9 +372,9 @@ __db_relink_recover(dbenv, dbtp, lsnp, op, info)
* the current page is the result of a split and is being recovered
* elsewhere, so all we need do is recover the next page.
*/
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
- (void)__db_pgerr(file_dbp, argp->pgno);
+ __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
goto next2;
@@ -376,12 +397,13 @@ __db_relink_recover(dbenv, dbtp, lsnp, op, info)
pagep->lsn = argp->lsn;
modified = 1;
}
-next1: if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+next1: if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
-next2: if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
+next2: if ((ret = mpf->get(mpf, &argp->next, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
- (void)__db_pgerr(file_dbp, argp->next);
+ __db_pgerr(file_dbp, argp->next, ret);
goto out;
}
goto prev;
@@ -409,14 +431,15 @@ next2: if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
else
pagep->lsn = *lsnp;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
if (argp->opcode == DB_ADD_PAGE)
goto done;
-prev: if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
+prev: if ((ret = mpf->get(mpf, &argp->prev, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
- (void)__db_pgerr(file_dbp, argp->prev);
+ __db_pgerr(file_dbp, argp->prev, ret);
goto out;
}
goto done;
@@ -441,13 +464,16 @@ prev: if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
else
pagep->lsn = *lsnp;
}
- if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
}
/*
@@ -468,8 +494,8 @@ __db_debug_recover(dbenv, dbtp, lsnp, op, info)
__db_debug_args *argp;
int ret;
- COMPQUIET(op, 0);
COMPQUIET(dbenv, NULL);
+ COMPQUIET(op, DB_TXN_ABORT);
COMPQUIET(info, NULL);
REC_PRINT(__db_debug_print);
@@ -504,11 +530,12 @@ __db_noop_recover(dbenv, dbtp, lsnp, op, info)
u_int32_t change;
int cmp_n, cmp_p, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_noop_print);
REC_INTRO(__db_noop_read, 0);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
goto out;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -522,8 +549,349 @@ __db_noop_recover(dbenv, dbtp, lsnp, op, info)
LSN(pagep) = argp->prevlsn;
change = DB_MPOOL_DIRTY;
}
- ret = memp_fput(mpf, pagep, change);
+ ret = mpf->put(mpf, pagep, change);
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
-out: REC_CLOSE;
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ REC_CLOSE;
+}
+
+/*
+ * __db_pg_alloc_recover --
+ * Recovery function for pg_alloc.
+ *
+ * PUBLIC: int __db_pg_alloc_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __db_pg_alloc_args *argp;
+ DB *file_dbp;
+ DBC *dbc;
+ DBMETA *meta;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep;
+ db_pgno_t pgno;
+ int cmp_n, cmp_p, created, level, modified, ret;
+
+ meta = NULL;
+ pagep = NULL;
+ REC_PRINT(__db_pg_alloc_print);
+ REC_INTRO(__db_pg_alloc_read, 0);
+
+ /*
+ * Fix up the allocated page. If we're redoing the operation, we have
+ * to get the page (creating it if it doesn't exist), and update its
+ * LSN. If we're undoing the operation, we have to reset the page's
+ * LSN and put it on the free list.
+ *
+ * Fix up the metadata page. If we're redoing the operation, we have
+ * to get the metadata page and update its LSN and its free pointer.
+ * If we're undoing the operation and the page was ever created, we put
+ * it on the freelist.
+ */
+ pgno = PGNO_BASE_MD;
+ if ((ret = mpf->get(mpf, &pgno, 0, &meta)) != 0) {
+ /* The metadata page must always exist on redo. */
+ if (DB_REDO(op)) {
+ __db_pgerr(file_dbp, pgno, ret);
+ goto out;
+ } else
+ goto done;
+ }
+ created = modified = 0;
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ /*
+ * We have to be able to identify if a page was newly
+ * created so we can recover it properly. We cannot simply
+ * look for an empty header, because hash uses a pgin
+ * function that will set the header. Instead, we explicitly
+ * try for the page without CREATE and if that fails, then
+ * create it.
+ */
+ if ((ret =
+ mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+ __db_pgerr(file_dbp, argp->pgno, ret);
+ goto out;
+ }
+ created = modified = 1;
+ }
+
+ /* Fix up the allocated page. */
+ cmp_n = log_compare(lsnp, &LSN(pagep));
+ cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
+
+ /*
+ * If an inital allocation is aborted and then reallocated
+ * during an archival restore the log record will have
+ * an LSN for the page but the page will be empty.
+ */
+ if (IS_ZERO_LSN(LSN(pagep)))
+ cmp_p = 0;
+ CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
+ /*
+ * If we we rolled back this allocation previously during an
+ * archive restore, the page may have the LSN of the meta page
+ * at the point of the roll back. This will be no more
+ * than the LSN of the metadata page at the time of this allocation.
+ * Another special case we have to handle is if we ended up with a
+ * page of all 0's which can happen if we abort between allocating a
+ * page in mpool and initializing it. In that case, even if we're
+ * undoing, we need to re-initialize the page.
+ */
+ if (DB_REDO(op) &&
+ (cmp_p == 0 ||
+ (IS_ZERO_LSN(argp->page_lsn) &&
+ log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
+ /* Need to redo update described. */
+ switch (argp->ptype) {
+ case P_LBTREE:
+ case P_LRECNO:
+ case P_LDUP:
+ level = LEAFLEVEL;
+ break;
+ default:
+ level = 0;
+ break;
+ }
+ P_INIT(pagep, file_dbp->pgsize,
+ argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);
+
+ pagep->lsn = *lsnp;
+ modified = 1;
+ } else if (DB_UNDO(op) && (cmp_n == 0 || created)) {
+ /*
+ * This is where we handle the case of a 0'd page (pagep->pgno
+ * is equal to PGNO_INVALID).
+ * Undo the allocation, reinitialize the page and
+ * link its next pointer to the free list.
+ */
+ P_INIT(pagep, file_dbp->pgsize,
+ argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
+
+ pagep->lsn = argp->page_lsn;
+ modified = 1;
+ }
+
+ /*
+ * If the page was newly created, put it on the limbo list.
+ */
+ if (IS_ZERO_LSN(LSN(pagep)) &&
+ IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
+ /* Put the page in limbo.*/
+ if ((ret = __db_add_limbo(dbenv,
+ info, argp->fileid, argp->pgno, 1)) != 0)
+ goto out;
+ }
+
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+ pagep = NULL;
+
+ /* Fix up the metadata page. */
+ modified = 0;
+ cmp_n = log_compare(lsnp, &LSN(meta));
+ cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
+ CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
+ if (cmp_p == 0 && DB_REDO(op)) {
+ /* Need to redo update described. */
+ LSN(meta) = *lsnp;
+ meta->free = argp->next;
+ modified = 1;
+ } else if (cmp_n == 0 && DB_UNDO(op)) {
+ /* Need to undo update described. */
+ LSN(meta) = argp->meta_lsn;
+
+ /*
+ * If the page has a zero LSN then its newly created
+ * and will go into limbo rather than directly on the
+ * free list.
+ */
+ if (!IS_ZERO_LSN(argp->page_lsn))
+ meta->free = argp->pgno;
+ modified = 1;
+ }
+ if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+ meta = NULL;
+ /*
+ * This could be the metapage from a subdb which is read from disk
+ * to recover its creation.
+ */
+ if (F_ISSET(file_dbp, DB_AM_SUBDB))
+ switch (argp->type) {
+ case P_BTREEMETA:
+ case P_HASHMETA:
+ case P_QAMMETA:
+ file_dbp->sync(file_dbp, 0);
+ break;
+ }
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
+ ret = 0;
+ REC_CLOSE;
+}
+
+/*
+ * __db_pg_free_recover --
+ * Recovery function for pg_free.
+ *
+ * PUBLIC: int __db_pg_free_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __db_pg_free_args *argp;
+ DB *file_dbp;
+ DBC *dbc;
+ DBMETA *meta;
+ DB_LSN copy_lsn;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep;
+ db_pgno_t pgno;
+ int cmp_n, cmp_p, modified, ret;
+
+ COMPQUIET(info, NULL);
+ meta = NULL;
+ pagep = NULL;
+ REC_PRINT(__db_pg_free_print);
+ REC_INTRO(__db_pg_free_read, 1);
+
+ /*
+ * Fix up the freed page. If we're redoing the operation we get the
+ * page and explicitly discard its contents, then update its LSN. If
+ * we're undoing the operation, we get the page and restore its header.
+ * Create the page if necessary, we may be freeing an aborted
+ * create.
+ */
+ if ((ret = mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+ modified = 0;
+ (void)__ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
+ cmp_n = log_compare(lsnp, &LSN(pagep));
+ cmp_p = log_compare(&LSN(pagep), &copy_lsn);
+ CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
+ if (DB_REDO(op) &&
+ (cmp_p == 0 ||
+ (IS_ZERO_LSN(copy_lsn) &&
+ log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
+ /* Need to redo update described. */
+ P_INIT(pagep, file_dbp->pgsize,
+ argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
+ pagep->lsn = *lsnp;
+
+ modified = 1;
+ } else if (cmp_n == 0 && DB_UNDO(op)) {
+ /* Need to undo update described. */
+ memcpy(pagep, argp->header.data, argp->header.size);
+
+ modified = 1;
+ }
+ if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+ pagep = NULL;
+
+ /*
+ * Fix up the metadata page. If we're redoing or undoing the operation
+ * we get the page and update its LSN and free pointer.
+ */
+ pgno = PGNO_BASE_MD;
+ if ((ret = mpf->get(mpf, &pgno, 0, &meta)) != 0) {
+ /* The metadata page must always exist. */
+ __db_pgerr(file_dbp, pgno, ret);
+ goto out;
+ }
+
+ modified = 0;
+ cmp_n = log_compare(lsnp, &LSN(meta));
+ cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
+ CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
+ if (cmp_p == 0 && DB_REDO(op)) {
+ /* Need to redo the deallocation. */
+ meta->free = argp->pgno;
+ LSN(meta) = *lsnp;
+ modified = 1;
+ } else if (cmp_n == 0 && DB_UNDO(op)) {
+ /* Need to undo the deallocation. */
+ meta->free = argp->next;
+ LSN(meta) = argp->meta_lsn;
+ modified = 1;
+ }
+ if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+ meta = NULL;
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
+ if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ REC_CLOSE;
+}
+
+/*
+ * __db_cksum_recover --
+ * Recovery function for checksum failure log record.
+ *
+ * PUBLIC: int __db_cksum_recover __P((DB_ENV *,
+ * PUBLIC: DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_cksum_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __db_cksum_args *argp;
+
+ int ret;
+
+ COMPQUIET(info, NULL);
+ COMPQUIET(lsnp, NULL);
+ COMPQUIET(op, DB_TXN_ABORT);
+
+ REC_PRINT(__db_cksum_print);
+
+ if ((ret = __db_cksum_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+
+ /*
+ * We had a checksum failure -- the only option is to run catastrophic
+ * recovery.
+ */
+ if (F_ISSET(dbenv, DB_ENV_FATAL))
+ ret = 0;
+ else {
+ __db_err(dbenv,
+ "Checksum failure requires catastrophic recovery");
+ ret = __db_panic(dbenv, DB_RUNRECOVERY);
+ }
+
+ __os_free(dbenv, argp);
+ return (ret);
}
diff --git a/bdb/db/db_reclaim.c b/bdb/db/db_reclaim.c
index 739f348407d..9aa39bcfa9b 100644
--- a/bdb/db/db_reclaim.c
+++ b/bdb/db/db_reclaim.c
@@ -1,74 +1,26 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_reclaim.c,v 11.5 2000/04/07 14:26:58 bostic Exp $";
+static const char revid[] = "$Id: db_reclaim.c,v 11.28 2002/08/06 06:11:17 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-
-/*
- * Assume that we enter with a valid pgno. We traverse a set of
- * duplicate pages. The format of the callback routine is:
- * callback(dbp, page, cookie, did_put). did_put is an output
- * value that will be set to 1 by the callback routine if it
- * already put the page back. Otherwise, this routine must
- * put the page.
- *
- * PUBLIC: int __db_traverse_dup __P((DB *,
- * PUBLIC: db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
- */
-int
-__db_traverse_dup(dbp, pgno, callback, cookie)
- DB *dbp;
- db_pgno_t pgno;
- int (*callback) __P((DB *, PAGE *, void *, int *));
- void *cookie;
-{
- PAGE *p;
- int did_put, i, opgno, ret;
-
- do {
- did_put = 0;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &p)) != 0)
- return (ret);
- pgno = NEXT_PGNO(p);
-
- for (i = 0; i < NUM_ENT(p); i++) {
- if (B_TYPE(GET_BKEYDATA(p, i)->type) == B_OVERFLOW) {
- opgno = GET_BOVERFLOW(p, i)->pgno;
- if ((ret = __db_traverse_big(dbp,
- opgno, callback, cookie)) != 0)
- goto err;
- }
- }
-
- if ((ret = callback(dbp, p, cookie, &did_put)) != 0)
- goto err;
-
- if (!did_put)
- if ((ret = memp_fput(dbp->mpf, p, 0)) != 0)
- return (ret);
- } while (pgno != PGNO_INVALID);
-
- if (0) {
-err: if (did_put == 0)
- (void)memp_fput(dbp->mpf, p, 0);
- }
- return (ret);
-}
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
/*
* __db_traverse_big
@@ -88,17 +40,20 @@ __db_traverse_big(dbp, pgno, callback, cookie)
int (*callback) __P((DB *, PAGE *, void *, int *));
void *cookie;
{
+ DB_MPOOLFILE *mpf;
PAGE *p;
int did_put, ret;
+ mpf = dbp->mpf;
+
do {
did_put = 0;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &p)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &p)) != 0)
return (ret);
pgno = NEXT_PGNO(p);
if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
!did_put)
- ret = memp_fput(dbp->mpf, p, 0);
+ ret = mpf->put(mpf, p, 0);
} while (ret == 0 && pgno != PGNO_INVALID);
return (ret);
@@ -132,3 +87,162 @@ __db_reclaim_callback(dbp, p, cookie, putp)
return (0);
}
+
+/*
+ * __db_truncate_callback
+ * This is the callback routine used during a truncate.
+ * we are traversing a btree or hash table and trying to free all the
+ * pages.
+ *
+ * PUBLIC: int __db_truncate_callback __P((DB *, PAGE *, void *, int *));
+ */
+int
+__db_truncate_callback(dbp, p, cookie, putp)
+ DB *dbp;
+ PAGE *p;
+ void *cookie;
+ int *putp;
+{
+ DBMETA *meta;
+ DBT ldbt;
+ DB_LOCK metalock;
+ DB_MPOOLFILE *mpf;
+ db_indx_t indx, len, off, tlen, top;
+ db_pgno_t pgno;
+ db_trunc_param *param;
+ u_int8_t *hk, type;
+ int ret;
+
+ top = NUM_ENT(p);
+ mpf = dbp->mpf;
+ param = cookie;
+ *putp = 1;
+
+ switch (TYPE(p)) {
+ case P_LBTREE:
+ /* Skip for off-page duplicates and deleted items. */
+ for (indx = 0; indx < top; indx += P_INDX) {
+ type = GET_BKEYDATA(dbp, p, indx + O_INDX)->type;
+ if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
+ ++param->count;
+ }
+ /* FALLTHROUGH */
+ case P_IBTREE:
+ case P_IRECNO:
+ case P_INVALID:
+ if (dbp->type != DB_HASH &&
+ ((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
+ type = dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE;
+ goto reinit;
+ }
+ break;
+ case P_OVERFLOW:
+ if (DBC_LOGGING(param->dbc)) {
+ if ((ret = __db_ovref_log(dbp, param->dbc->txn,
+ &LSN(p), 0, p->pgno, -1, &LSN(p))) != 0)
+ return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(p));
+ if (--OV_REF(p) != 0)
+ *putp = 0;
+ break;
+ case P_LRECNO:
+ param->count += top;
+ if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
+ type = P_LRECNO;
+ goto reinit;
+ }
+ break;
+ case P_LDUP:
+ /* Correct for deleted items. */
+ for (indx = 0; indx < top; indx += O_INDX)
+ if (!B_DISSET(GET_BKEYDATA(dbp, p, indx)->type))
+ ++param->count;
+
+ break;
+ case P_HASH:
+ /* Correct for on-page duplicates and deleted items. */
+ for (indx = 0; indx < top; indx += P_INDX) {
+ switch (*H_PAIRDATA(dbp, p, indx)) {
+ case H_OFFDUP:
+ case H_OFFPAGE:
+ break;
+ case H_KEYDATA:
+ ++param->count;
+ break;
+ case H_DUPLICATE:
+ tlen = LEN_HDATA(dbp, p, 0, indx);
+ hk = H_PAIRDATA(dbp, p, indx);
+ for (off = 0; off < tlen;
+ off += len + 2 * sizeof (db_indx_t)) {
+ ++param->count;
+ memcpy(&len,
+ HKEYDATA_DATA(hk)
+ + off, sizeof(db_indx_t));
+ }
+ }
+ }
+ /* Don't free the head of the bucket. */
+ if (PREV_PGNO(p) == PGNO_INVALID) {
+ type = P_HASH;
+
+reinit: *putp = 0;
+ if (DBC_LOGGING(param->dbc)) {
+ pgno = PGNO_BASE_MD;
+ if ((ret = __db_lget(param->dbc, LCK_ALWAYS,
+ pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
+ return (ret);
+ if ((ret = mpf->get(mpf,
+ &pgno, 0, (PAGE **)&meta)) != 0) {
+ goto err;
+ }
+ memset(&ldbt, 0, sizeof(ldbt));
+ ldbt.data = p;
+ ldbt.size = P_OVERHEAD(dbp);
+ if ((ret = __db_pg_free_log(dbp,
+ param->dbc->txn, &LSN(meta), 0,
+ p->pgno, &LSN(meta),
+ PGNO_BASE_MD, &ldbt, meta->free)) != 0)
+ goto err;
+ LSN(p) = LSN(meta);
+
+ if ((ret =
+ __db_pg_alloc_log(dbp,
+ param->dbc->txn, &LSN(meta), 0,
+ &LSN(meta), PGNO_BASE_MD,
+ &p->lsn, p->pgno, type, meta->free)) != 0) {
+err: (void)mpf->put(mpf, (PAGE *)meta, 0);
+ (void)__TLPUT(param->dbc, metalock);
+ return (ret);
+ }
+ LSN(p) = LSN(meta);
+
+ if ((ret = mpf->put(mpf,
+ (PAGE *)meta, DB_MPOOL_DIRTY)) != 0) {
+ (void)__TLPUT(param->dbc, metalock);
+ return (ret);
+ }
+ if ((ret = __TLPUT(param->dbc, metalock)) != 0)
+ return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(p));
+
+ P_INIT(p, dbp->pgsize, PGNO(p), PGNO_INVALID,
+ PGNO_INVALID, type == P_HASH ? 0 : 1, type);
+ }
+ break;
+ default:
+ return (__db_pgfmt(dbp->dbenv, p->pgno));
+ }
+
+ if (*putp == 1) {
+ if ((ret = __db_free(param->dbc, p)) != 0)
+ return (ret);
+ } else {
+ if ((ret = mpf->put(mpf, p, DB_MPOOL_DIRTY)) != 0)
+ return (ret);
+ *putp = 1;
+ }
+
+ return (0);
+}
diff --git a/bdb/db/db_remove.c b/bdb/db/db_remove.c
new file mode 100644
index 00000000000..ef11c342555
--- /dev/null
+++ b/bdb/db/db_remove.c
@@ -0,0 +1,318 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_remove.c,v 11.203 2002/08/19 18:34:18 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/fop.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+
+static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
+static int __db_dbtxn_remove __P((DB *, DB_TXN *, const char *));
+
+/*
+ * __dbenv_dbremove
+ * Remove method for DB_ENV.
+ *
+ * PUBLIC: int __dbenv_dbremove __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t));
+ */
+int
+__dbenv_dbremove(dbenv, txn, name, subdb, flags)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ const char *name, *subdb;
+ u_int32_t flags;
+{
+ DB *dbp;
+ int ret, t_ret, txn_local;
+
+ txn_local = 0;
+
+ PANIC_CHECK(dbenv);
+ ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbremove");
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "DB->remove", flags, DB_AUTO_COMMIT)) != 0)
+ return (ret);
+
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return (ret);
+
+ /*
+ * Create local transaction as necessary, check for consistent
+ * transaction usage.
+ */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ } else
+ if (txn != NULL && !TXN_ON(dbenv))
+ return (__db_not_txn_env(dbenv));
+
+ ret = __db_remove_i(dbp, txn, name, subdb);
+
+ /* Commit for DB_AUTO_COMMIT. */
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+ /*
+ * We created the DBP here and when we committed/aborted,
+ * we release all the tranasctional locks, which includes
+ * the handle lock; mark the handle cleared explicitly.
+ */
+ LOCK_INIT(dbp->handle_lock);
+ dbp->lid = DB_LOCK_INVALIDID;
+ }
+
+ /*
+ * We never opened this dbp for real, so don't call the transactional
+ * version of DB->close, and use NOSYNC to avoid calling into mpool.
+ */
+ if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __db_remove
+ * Remove method for DB.
+ *
+ * PUBLIC: int __db_remove __P((DB *, const char *, const char *, u_int32_t));
+ */
+int
+__db_remove(dbp, name, subdb, flags)
+ DB *dbp;
+ const char *name, *subdb;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret;
+
+ dbenv = dbp->dbenv;
+
+ PANIC_CHECK(dbenv);
+
+ /*
+ * Validate arguments, continuing to destroy the handle on failure.
+ *
+ * Cannot use DB_ILLEGAL_AFTER_OPEN directly because it returns.
+ *
+ * !!!
+ * We have a serious problem if we're here with a handle used to open
+ * a database -- we'll destroy the handle, and the application won't
+ * ever be able to close the database.
+ */
+ if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
+ ret = __db_mi_open(dbenv, "DB->remove", 1);
+ goto err;
+ }
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "DB->remove", flags, 0)) != 0)
+ goto err;
+
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
+ goto err;
+
+ /* Remove the file. */
+ ret = __db_remove_i(dbp, NULL, name, subdb);
+
+ /*
+ * We never opened this dbp for real, use NOSYNC to avoid calling into
+ * mpool.
+ */
+err: if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __db_remove_i
+ * Internal remove method for DB.
+ *
+ * PUBLIC: int __db_remove_i __P((DB *, DB_TXN *, const char *, const char *));
+ */
+int
+__db_remove_i(dbp, txn, name, subdb)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb;
+{
+ DB_ENV *dbenv;
+ DB_LSN newlsn;
+ int ret;
+ char *real_name;
+
+ dbenv = dbp->dbenv;
+ real_name = NULL;
+
+ /* Handle subdatabase removes separately. */
+ if (subdb != NULL)
+ return (__db_subdb_remove(dbp, txn, name, subdb));
+
+ /* Handle transactional file removes separately. */
+ if (txn != NULL)
+ return (__db_dbtxn_remove(dbp, txn, name));
+
+ /*
+ * The remaining case is a non-transactional file remove.
+ *
+ * Find the real name of the file.
+ */
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
+ return (ret);
+
+ if ((ret = __fop_remove_setup(dbp, NULL, real_name, 0)) != 0)
+ goto err;
+
+ if (dbp->db_am_remove != NULL &&
+ (ret = dbp->db_am_remove(dbp, NULL, name, subdb, &newlsn)) != 0)
+ goto err;
+
+ ret = __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA);
+
+err:
+ if (real_name != NULL)
+ __os_free(dbenv, real_name);
+
+ return (ret);
+}
+
+/*
+ * __db_subdb_remove --
+ * Remove a subdatabase.
+ */
+static int
+__db_subdb_remove(dbp, txn, name, subdb)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb;
+{
+ DB *mdbp, *sdbp;
+ int ret, t_ret;
+
+ mdbp = sdbp = NULL;
+
+ /* Open the subdatabase. */
+ if ((ret = db_create(&sdbp, dbp->dbenv, 0)) != 0)
+ goto err;
+ if ((ret = __db_open(sdbp,
+ txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0)) != 0)
+ goto err;
+
+ DB_TEST_RECOVERY(sdbp, DB_TEST_PREDESTROY, ret, name);
+
+ /* Free up the pages in the subdatabase. */
+ switch (sdbp->type) {
+ case DB_BTREE:
+ case DB_RECNO:
+ if ((ret = __bam_reclaim(sdbp, txn)) != 0)
+ goto err;
+ break;
+ case DB_HASH:
+ if ((ret = __ham_reclaim(sdbp, txn)) != 0)
+ goto err;
+ break;
+ default:
+ ret = __db_unknown_type(
+ sdbp->dbenv, "__db_subdb_remove", sdbp->type);
+ goto err;
+ }
+
+ /*
+ * Remove the entry from the main database and free the subdatabase
+ * metadata page.
+ */
+ if ((ret = __db_master_open(sdbp, txn, name, 0, 0, &mdbp)) != 0)
+ goto err;
+
+ if ((ret = __db_master_update(
+ mdbp, sdbp, txn, subdb, sdbp->type, MU_REMOVE, NULL, 0)) != 0)
+ goto err;
+
+ DB_TEST_RECOVERY(sdbp, DB_TEST_POSTDESTROY, ret, name);
+
+DB_TEST_RECOVERY_LABEL
+err:
+ /* Close the main and subdatabases. */
+ if ((t_ret = __db_close_i(sdbp, txn, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (mdbp != NULL &&
+ (t_ret = __db_close_i(mdbp, txn, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+static int
+__db_dbtxn_remove(dbp, txn, name)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name;
+{
+ DB_ENV *dbenv;
+ DB_LSN newlsn;
+ int ret;
+ char *tmpname;
+
+ dbenv = dbp->dbenv;
+ tmpname = NULL;
+
+ /*
+ * This is a transactional rename, so we have to keep the name
+ * of the file locked until the transaction commits. As a result,
+ * we implement remove by renaming the file to some other name
+ * (which creates a dummy named file as a placeholder for the
+ * file being rename/dremoved) and then deleting that file as
+ * a delayed remove at commit.
+ */
+ if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
+ return (ret);
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
+
+ if ((ret = __db_rename_i(dbp, txn, name, NULL, tmpname)) != 0)
+ goto err;
+
+ /* The internal removes will also translate into delayed removes. */
+ if (dbp->db_am_remove != NULL &&
+ (ret = dbp->db_am_remove(dbp, txn, tmpname, NULL, &newlsn)) != 0)
+ goto err;
+
+ ret = __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA);
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name);
+
+err:
+DB_TEST_RECOVERY_LABEL
+ if (tmpname != NULL)
+ __os_free(dbenv, tmpname);
+
+ return (ret);
+}
diff --git a/bdb/db/db_rename.c b/bdb/db/db_rename.c
new file mode 100644
index 00000000000..87f88232cda
--- /dev/null
+++ b/bdb/db/db_rename.c
@@ -0,0 +1,297 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_rename.c,v 11.203 2002/08/07 16:16:47 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/fop.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+
+static int __db_subdb_rename __P(( DB *, DB_TXN *,
+ const char *, const char *, const char *));
+
+/*
+ * __dbenv_dbrename
+ * Rename method for DB_ENV.
+ *
+ * PUBLIC: int __dbenv_dbrename __P((DB_ENV *, DB_TXN *,
+ * PUBLIC: const char *, const char *, const char *, u_int32_t));
+ */
+int
+__dbenv_dbrename(dbenv, txn, name, subdb, newname, flags)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ const char *name, *subdb, *newname;
+ u_int32_t flags;
+{
+ DB *dbp;
+ int ret, t_ret, txn_local;
+
+ txn_local = 0;
+
+ PANIC_CHECK(dbenv);
+ ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbrename");
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "DB->rename", flags, DB_AUTO_COMMIT)) != 0)
+ return (ret);
+
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return (ret);
+
+ /*
+ * Create local transaction as necessary, check for consistent
+ * transaction usage.
+ */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ } else
+ if (txn != NULL && !TXN_ON(dbenv))
+ return (__db_not_txn_env(dbenv));
+
+ ret = __db_rename_i(dbp, txn, name, subdb, newname);
+
+ /* Commit for DB_AUTO_COMMIT. */
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+
+ /*
+ * We created the DBP here and when we committed/aborted,
+ * we release all the tranasctional locks, which includes
+ * the handle lock; mark the handle cleared explicitly.
+ */
+ LOCK_INIT(dbp->handle_lock);
+ dbp->lid = DB_LOCK_INVALIDID;
+ }
+
+ /*
+ * We never opened this dbp for real, so don't call the transactional
+ * version of DB->close, and use NOSYNC to avoid calling into mpool.
+ */
+ if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __db_rename
+ * Rename method for DB.
+ *
+ * PUBLIC: int __db_rename __P((DB *,
+ * PUBLIC: const char *, const char *, const char *, u_int32_t));
+ */
+int
+__db_rename(dbp, name, subdb, newname, flags)
+ DB *dbp;
+ const char *name, *subdb, *newname;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret;
+
+ dbenv = dbp->dbenv;
+
+ PANIC_CHECK(dbenv);
+
+ /*
+ * Validate arguments, continuing to destroy the handle on failure.
+ *
+ * Cannot use DB_ILLEGAL_AFTER_OPEN directly because it returns.
+ *
+ * !!!
+ * We have a serious problem if we're here with a handle used to open
+ * a database -- we'll destroy the handle, and the application won't
+ * ever be able to close the database.
+ */
+ if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
+ ret = __db_mi_open(dbenv, "DB->rename", 1);
+ goto err;
+ }
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "DB->rename", flags, 0)) != 0)
+ goto err;
+
+ /* Check for consistent transaction usage. */
+ if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
+ goto err;
+
+ /* Rename the file. */
+ ret = __db_rename_i(dbp, NULL, name, subdb, newname);
+
+ /*
+ * We never opened this dbp for real, use NOSYNC to avoid calling into
+ * mpool.
+ */
+err: if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __db_rename_i
+ * Internal rename method for DB.
+ *
+ * PUBLIC: int __db_rename_i __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, const char *, const char *));
+ */
+int
+__db_rename_i(dbp, txn, name, subdb, newname)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb, *newname;
+{
+ DB_ENV *dbenv;
+ int ret;
+ char *real_name;
+
+ dbenv = dbp->dbenv;
+ real_name = NULL;
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
+
+ if (subdb != NULL) {
+ ret = __db_subdb_rename(dbp, txn, name, subdb, newname);
+ goto err;
+ }
+
+ /* From here on down, this pertains to files. */
+
+ /* Find the real name of the file. */
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
+ goto err;
+
+ if ((ret = __fop_remove_setup(dbp, txn, real_name, 0)) != 0)
+ goto err;
+
+ if (dbp->db_am_rename != NULL &&
+ (ret = dbp->db_am_rename(dbp, txn, name, subdb, newname)) != 0)
+ goto err;
+
+ /*
+ * The transactional case and non-transactional case are
+ * quite different. In the non-transactional case, we simply
+ * do the rename. In the transactional case, since we need
+ * the ability to back out and maintain locking, we have to
+ * create a temporary object as a placeholder. This is all
+ * taken care of in the fop layer.
+ */
+ if (txn != NULL) {
+ if ((ret = __fop_dummy(dbp, txn, name, newname, 0)) != 0)
+ goto err;
+ } else {
+ if ((ret = __fop_dbrename(dbp, name, newname)) != 0)
+ goto err;
+ }
+
+ /*
+ * I am pretty sure that we haven't gotten a dbreg id, so calling
+ * dbreg_filelist_update is not necessary.
+ */
+ DB_ASSERT(dbp->log_filename == NULL ||
+ dbp->log_filename->id == DB_LOGFILEID_INVALID);
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, newname);
+
+DB_TEST_RECOVERY_LABEL
+err:
+ if (real_name != NULL)
+ __os_free(dbenv, real_name);
+
+ return (ret);
+}
+
+/*
+ * __db_subdb_rename --
+ * Rename a subdatabase.
+ */
+static int
+__db_subdb_rename(dbp, txn, name, subdb, newname)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name, *subdb, *newname;
+{
+ DB *mdbp;
+ DB_ENV *dbenv;
+ PAGE *meta;
+ int ret, t_ret;
+
+ mdbp = NULL;
+ meta = NULL;
+ dbenv = dbp->dbenv;
+
+ /*
+ * We have not opened this dbp so it isn't marked as a subdb,
+ * but it ought to be.
+ */
+ F_SET(dbp, DB_AM_SUBDB);
+
+ /*
+ * Rename the entry in the main database. We need to first
+ * get the meta-data page number (via MU_OPEN) so that we can
+ * read the meta-data page and obtain a handle lock. Once we've
+ * done that, we can proceed to do the rename in the master.
+ */
+ if ((ret = __db_master_open(dbp, txn, name, 0, 0, &mdbp)) != 0)
+ goto err;
+
+ if ((ret = __db_master_update(mdbp, dbp, txn, subdb, dbp->type,
+ MU_OPEN, NULL, 0)) != 0)
+ goto err;
+
+ if ((ret = mdbp->mpf->get(mdbp->mpf, &dbp->meta_pgno, 0, &meta)) != 0)
+ goto err;
+ memcpy(&dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
+ if ((ret = __fop_lock_handle(dbenv,
+ dbp, mdbp->lid, DB_LOCK_WRITE, NULL, 0)) != 0)
+ goto err;
+
+ ret = mdbp->mpf->put(mdbp->mpf, meta, 0);
+ meta = NULL;
+ if (ret != 0)
+ goto err;
+
+ if ((ret = __db_master_update(mdbp, dbp, txn,
+ subdb, dbp->type, MU_RENAME, newname, 0)) != 0)
+ goto err;
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name);
+
+DB_TEST_RECOVERY_LABEL
+err:
+ if (meta != NULL &&
+ (t_ret = mdbp->mpf->put(mdbp->mpf, meta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (mdbp != NULL &&
+ (t_ret = __db_close_i(mdbp, txn, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
diff --git a/bdb/db/db_ret.c b/bdb/db/db_ret.c
index 0782de3e450..b1af7b4ffeb 100644
--- a/bdb/db/db_ret.c
+++ b/bdb/db/db_ret.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_ret.c,v 11.12 2000/11/30 00:58:33 ubell Exp $";
+static const char revid[] = "$Id: db_ret.c,v 11.21 2002/03/28 19:21:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,9 +18,8 @@ static const char revid[] = "$Id: db_ret.c,v 11.12 2000/11/30 00:58:33 ubell Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "db_am.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
/*
* __db_ret --
@@ -47,19 +46,19 @@ __db_ret(dbp, h, indx, dbt, memp, memsize)
switch (TYPE(h)) {
case P_HASH:
- hk = P_ENTRY(h, indx);
+ hk = P_ENTRY(dbp, h, indx);
if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
memcpy(&ho, hk, sizeof(HOFFPAGE));
return (__db_goff(dbp, dbt,
ho.tlen, ho.pgno, memp, memsize));
}
- len = LEN_HKEYDATA(h, dbp->pgsize, indx);
+ len = LEN_HKEYDATA(dbp, h, dbp->pgsize, indx);
data = HKEYDATA_DATA(hk);
break;
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
- bk = GET_BKEYDATA(h, indx);
+ bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW) {
bo = (BOVERFLOW *)bk;
return (__db_goff(dbp, dbt,
@@ -69,33 +68,30 @@ __db_ret(dbp, h, indx, dbt, memp, memsize)
data = bk->data;
break;
default:
- return (__db_pgfmt(dbp, h->pgno));
+ return (__db_pgfmt(dbp->dbenv, h->pgno));
}
- return (__db_retcopy(dbp, dbt, data, len, memp, memsize));
+ return (__db_retcopy(dbp->dbenv, dbt, data, len, memp, memsize));
}
/*
* __db_retcopy --
* Copy the returned data into the user's DBT, handling special flags.
*
- * PUBLIC: int __db_retcopy __P((DB *, DBT *,
+ * PUBLIC: int __db_retcopy __P((DB_ENV *, DBT *,
* PUBLIC: void *, u_int32_t, void **, u_int32_t *));
*/
int
-__db_retcopy(dbp, dbt, data, len, memp, memsize)
- DB *dbp;
+__db_retcopy(dbenv, dbt, data, len, memp, memsize)
+ DB_ENV *dbenv;
DBT *dbt;
void *data;
u_int32_t len;
void **memp;
u_int32_t *memsize;
{
- DB_ENV *dbenv;
int ret;
- dbenv = dbp == NULL ? NULL : dbp->dbenv;
-
/* If returning a partial record, reset the length. */
if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
data = (u_int8_t *)data + dbt->doff;
@@ -131,12 +127,10 @@ __db_retcopy(dbp, dbt, data, len, memp, memsize)
* memory pointer is allowed to be NULL.
*/
if (F_ISSET(dbt, DB_DBT_MALLOC)) {
- if ((ret = __os_malloc(dbenv, len,
- dbp == NULL ? NULL : dbp->db_malloc, &dbt->data)) != 0)
+ if ((ret = __os_umalloc(dbenv, len, &dbt->data)) != 0)
return (ret);
} else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
- if ((ret = __os_realloc(dbenv, len,
- dbp == NULL ? NULL : dbp->db_realloc, &dbt->data)) != 0)
+ if ((ret = __os_urealloc(dbenv, len, &dbt->data)) != 0)
return (ret);
} else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
@@ -145,7 +139,7 @@ __db_retcopy(dbp, dbt, data, len, memp, memsize)
return (EINVAL);
} else {
if (len != 0 && (*memsize == 0 || *memsize < len)) {
- if ((ret = __os_realloc(dbenv, len, NULL, memp)) != 0) {
+ if ((ret = __os_realloc(dbenv, len, memp)) != 0) {
*memsize = 0;
return (ret);
}
diff --git a/bdb/db/db_truncate.c b/bdb/db/db_truncate.c
new file mode 100644
index 00000000000..49546ae51b9
--- /dev/null
+++ b/bdb/db/db_truncate.c
@@ -0,0 +1,95 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_truncate.c,v 11.185 2002/08/07 16:16:48 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/qam.h"
+
+/*
+ * __db_truncate
+ * truncate method for DB.
+ *
+ * PUBLIC: int __db_truncate __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
+ */
+int
+__db_truncate(dbp, txn, countp, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ u_int32_t *countp, flags;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret, txn_local;
+
+ dbenv = dbp->dbenv;
+ ret = txn_local = 0;
+
+ PANIC_CHECK(dbenv);
+
+ /* Check for invalid flags. */
+ if ((ret =
+ __db_fchk(dbenv, "DB->truncate", flags, DB_AUTO_COMMIT)) != 0)
+ return (ret);
+
+ /*
+ * Create local transaction as necessary, check for consistent
+ * transaction usage.
+ */
+ if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+ if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+ return (ret);
+ txn_local = 1;
+ } else
+ if (txn != NULL && !TXN_ON(dbenv))
+ return (__db_not_txn_env(dbenv));
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, NULL);
+ switch (dbp->type) {
+ case DB_BTREE:
+ case DB_RECNO:
+ if ((ret = __bam_truncate(dbp, txn, countp)) != 0)
+ goto err;
+ break;
+ case DB_HASH:
+ if ((ret = __ham_truncate(dbp, txn, countp)) != 0)
+ goto err;
+ break;
+ case DB_QUEUE:
+ if ((ret = __qam_truncate(dbp, txn, countp)) != 0)
+ goto err;
+ break;
+ default:
+ ret = __db_unknown_type(
+ dbenv, "__db_truncate", dbp->type);
+ goto err;
+ }
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, NULL);
+
+DB_TEST_RECOVERY_LABEL
+err:
+ /* Commit for DB_AUTO_COMMIT. */
+ if (txn_local) {
+ if (ret == 0)
+ ret = txn->commit(txn, 0);
+ else
+ if ((t_ret = txn->abort(txn)) != 0)
+ ret = __db_panic(dbenv, t_ret);
+ }
+
+ return (ret);
+}
diff --git a/bdb/db/db_upg.c b/bdb/db/db_upg.c
index d8573146ad6..c0eb72f3713 100644
--- a/bdb/db/db_upg.c
+++ b/bdb/db/db_upg.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_upg.c,v 11.20 2000/12/12 17:35:30 bostic Exp $";
+static const char revid[] = "$Id: db_upg.c,v 11.29 2002/03/27 18:59:04 krinsky Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,11 +18,11 @@ static const char revid[] = "$Id: db_upg.c,v 11.20 2000/12/12 17:35:30 bostic Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/qam.h"
static int (* const func_31_list[P_PAGETYPE_MAX])
__P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)) = {
@@ -68,7 +68,7 @@ __db_upgrade(dbp, fname, flags)
/* Get the real backing file name. */
if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0)
+ DB_APP_DATA, fname, 0, NULL, &real_name)) != 0)
return (ret);
/* Open the file. */
@@ -117,6 +117,7 @@ __db_upgrade(dbp, fname, flags)
goto err;
/* FALLTHROUGH */
case 8:
+ case 9:
break;
default:
__db_err(dbenv, "%s: unsupported btree version: %lu",
@@ -173,6 +174,7 @@ __db_upgrade(dbp, fname, flags)
goto err;
/* FALLTHROUGH */
case 7:
+ case 8:
break;
default:
__db_err(dbenv, "%s: unsupported hash version: %lu",
@@ -202,6 +204,7 @@ __db_upgrade(dbp, fname, flags)
goto err;
/* FALLTHROUGH */
case 3:
+ case 4:
break;
default:
__db_err(dbenv, "%s: unsupported queue version: %lu",
@@ -231,9 +234,9 @@ __db_upgrade(dbp, fname, flags)
ret = __os_fsync(dbenv, &fh);
-err: if ((t_ret = __os_closehandle(&fh)) != 0 && ret == 0)
+err: if ((t_ret = __os_closehandle(dbenv, &fh)) != 0 && ret == 0)
ret = t_ret;
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
/* We're done. */
if (dbp->db_feedback != NULL)
@@ -268,7 +271,7 @@ __db_page_pass(dbp, real_name, flags, fl, fhp)
return (ret);
/* Allocate memory for a single page. */
- if ((ret = __os_malloc(dbenv, dbp->pgsize, NULL, &page)) != 0)
+ if ((ret = __os_malloc(dbenv, dbp->pgsize, &page)) != 0)
return (ret);
/* Walk the file, calling the underlying conversion functions. */
@@ -294,7 +297,7 @@ __db_page_pass(dbp, real_name, flags, fl, fhp)
}
}
- __os_free(page, dbp->pgsize);
+ __os_free(dbp->dbenv, page);
return (ret);
}
diff --git a/bdb/db/db_upg_opd.c b/bdb/db/db_upg_opd.c
index a7be784afb8..f410b797bff 100644
--- a/bdb/db/db_upg_opd.c
+++ b/bdb/db/db_upg_opd.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_upg_opd.c,v 11.9 2000/11/30 00:58:33 ubell Exp $";
+static const char revid[] = "$Id: db_upg_opd.c,v 11.18 2002/08/06 06:11:18 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,11 +18,8 @@ static const char revid[] = "$Id: db_upg_opd.c,v 11.9 2000/11/30 00:58:33 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
static int __db_build_bi __P((DB *, DB_FH *, PAGE *, PAGE *, u_int32_t, int *));
static int __db_build_ri __P((DB *, DB_FH *, PAGE *, PAGE *, u_int32_t, int *));
@@ -71,7 +68,7 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
pgno_cur = pgno_next = NULL;
/* Allocate room to hold a page. */
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &page)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &page)) != 0)
goto err;
/*
@@ -85,7 +82,7 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
if (pgno_max == cur_cnt) {
pgno_max += 20;
if ((ret = __os_realloc(dbp->dbenv, pgno_max *
- sizeof(db_pgno_t), NULL, &pgno_cur)) != 0)
+ sizeof(db_pgno_t), &pgno_cur)) != 0)
goto err;
}
pgno_cur[cur_cnt++] = pgno;
@@ -112,7 +109,7 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
* list while we do so.
*/
if ((ret = __os_malloc(dbp->dbenv,
- cur_cnt * sizeof(db_pgno_t), NULL, &pgno_next)) != 0)
+ cur_cnt * sizeof(db_pgno_t), &pgno_next)) != 0)
goto err;
/* Figure out where we can start allocating new pages. */
@@ -121,7 +118,7 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
/* Allocate room for an internal page. */
if ((ret = __os_malloc(dbp->dbenv,
- dbp->pgsize, NULL, &ipage)) != 0)
+ dbp->pgsize, &ipage)) != 0)
goto err;
PGNO(ipage) = PGNO_INVALID;
}
@@ -187,13 +184,13 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
*pgnop = pgno_cur[0];
err: if (pgno_cur != NULL)
- __os_free(pgno_cur, 0);
+ __os_free(dbp->dbenv, pgno_cur);
if (pgno_next != NULL)
- __os_free(pgno_next, 0);
+ __os_free(dbp->dbenv, pgno_next);
if (ipage != NULL)
- __os_free(ipage, dbp->pgsize);
+ __os_free(dbp->dbenv, ipage);
if (page != NULL)
- __os_free(page, dbp->pgsize);
+ __os_free(dbp->dbenv, page);
return (ret);
}
@@ -214,22 +211,24 @@ __db_build_bi(dbp, fhp, ipage, page, indx, nomemp)
BKEYDATA *child_bk;
u_int8_t *p;
int ret;
+ db_indx_t *inp;
+ inp = P_INP(dbp, ipage);
switch (TYPE(page)) {
case P_IBTREE:
- child_bi = GET_BINTERNAL(page, 0);
- if (P_FREESPACE(ipage) < BINTERNAL_PSIZE(child_bi->len)) {
+ child_bi = GET_BINTERNAL(dbp, page, 0);
+ if (P_FREESPACE(dbp, ipage) < BINTERNAL_PSIZE(child_bi->len)) {
*nomemp = 1;
return (0);
}
- ipage->inp[indx] =
- HOFFSET(ipage) -= BINTERNAL_SIZE(child_bi->len);
- p = P_ENTRY(ipage, indx);
+ inp[indx] =
+ HOFFSET(ipage) -= BINTERNAL_SIZE(child_bi->len);
+ p = P_ENTRY(dbp, ipage, indx);
bi.len = child_bi->len;
B_TSET(bi.type, child_bi->type, 0);
bi.pgno = PGNO(page);
- bi.nrecs = __bam_total(page);
+ bi.nrecs = __bam_total(dbp, page);
memcpy(p, &bi, SSZA(BINTERNAL, data));
p += SSZA(BINTERNAL, data);
memcpy(p, child_bi->data, child_bi->len);
@@ -241,40 +240,40 @@ __db_build_bi(dbp, fhp, ipage, page, indx, nomemp)
return (ret);
break;
case P_LDUP:
- child_bk = GET_BKEYDATA(page, 0);
+ child_bk = GET_BKEYDATA(dbp, page, 0);
switch (B_TYPE(child_bk->type)) {
case B_KEYDATA:
- if (P_FREESPACE(ipage) <
+ if (P_FREESPACE(dbp, ipage) <
BINTERNAL_PSIZE(child_bk->len)) {
*nomemp = 1;
return (0);
}
- ipage->inp[indx] =
+ inp[indx] =
HOFFSET(ipage) -= BINTERNAL_SIZE(child_bk->len);
- p = P_ENTRY(ipage, indx);
+ p = P_ENTRY(dbp, ipage, indx);
bi.len = child_bk->len;
B_TSET(bi.type, child_bk->type, 0);
bi.pgno = PGNO(page);
- bi.nrecs = __bam_total(page);
+ bi.nrecs = __bam_total(dbp, page);
memcpy(p, &bi, SSZA(BINTERNAL, data));
p += SSZA(BINTERNAL, data);
memcpy(p, child_bk->data, child_bk->len);
break;
case B_OVERFLOW:
- if (P_FREESPACE(ipage) <
+ if (P_FREESPACE(dbp, ipage) <
BINTERNAL_PSIZE(BOVERFLOW_SIZE)) {
*nomemp = 1;
return (0);
}
- ipage->inp[indx] =
+ inp[indx] =
HOFFSET(ipage) -= BINTERNAL_SIZE(BOVERFLOW_SIZE);
- p = P_ENTRY(ipage, indx);
+ p = P_ENTRY(dbp, ipage, indx);
bi.len = BOVERFLOW_SIZE;
B_TSET(bi.type, child_bk->type, 0);
bi.pgno = PGNO(page);
- bi.nrecs = __bam_total(page);
+ bi.nrecs = __bam_total(dbp, page);
memcpy(p, &bi, SSZA(BINTERNAL, data));
p += SSZA(BINTERNAL, data);
memcpy(p, child_bk, BOVERFLOW_SIZE);
@@ -285,11 +284,11 @@ __db_build_bi(dbp, fhp, ipage, page, indx, nomemp)
return (ret);
break;
default:
- return (__db_pgfmt(dbp, PGNO(page)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(page)));
}
break;
default:
- return (__db_pgfmt(dbp, PGNO(page)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(page)));
}
return (0);
@@ -308,19 +307,19 @@ __db_build_ri(dbp, fhp, ipage, page, indx, nomemp)
int *nomemp;
{
RINTERNAL ri;
+ db_indx_t *inp;
- COMPQUIET(dbp, NULL);
COMPQUIET(fhp, NULL);
-
- if (P_FREESPACE(ipage) < RINTERNAL_PSIZE) {
+ inp = P_INP(dbp, ipage);
+ if (P_FREESPACE(dbp, ipage) < RINTERNAL_PSIZE) {
*nomemp = 1;
return (0);
}
ri.pgno = PGNO(page);
- ri.nrecs = __bam_total(page);
- ipage->inp[indx] = HOFFSET(ipage) -= RINTERNAL_SIZE;
- memcpy(P_ENTRY(ipage, indx), &ri, RINTERNAL_SIZE);
+ ri.nrecs = __bam_total(dbp, page);
+ inp[indx] = HOFFSET(ipage) -= RINTERNAL_SIZE;
+ memcpy(P_ENTRY(dbp, ipage, indx), &ri, RINTERNAL_SIZE);
return (0);
}
@@ -340,14 +339,14 @@ __db_up_ovref(dbp, fhp, pgno)
int ret;
/* Allocate room to hold a page. */
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &page)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &page)) != 0)
return (ret);
GET_PAGE(dbp, fhp, pgno, page);
++OV_REF(page);
PUT_PAGE(dbp, fhp, pgno, page);
-err: __os_free(page, dbp->pgsize);
+err: __os_free(dbp->dbenv, page);
return (ret);
}
diff --git a/bdb/db/db_vrfy.c b/bdb/db/db_vrfy.c
index 3509e05e91f..1bbecdbd87a 100644
--- a/bdb/db/db_vrfy.c
+++ b/bdb/db/db_vrfy.c
@@ -1,16 +1,16 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
+ * Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: db_vrfy.c,v 1.53 2001/01/11 18:19:51 bostic Exp $
+ * $Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic Exp $
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_vrfy.c,v 1.53 2001/01/11 18:19:51 bostic Exp $";
+static const char revid[] = "$Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,19 +20,25 @@ static const char revid[] = "$Id: db_vrfy.c,v 1.53 2001/01/11 18:19:51 bostic Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "db_verify.h"
-#include "db_ext.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/db_verify.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/qam.h"
+#include "dbinc/txn.h"
static int __db_guesspgsize __P((DB_ENV *, DB_FH *));
static int __db_is_valid_magicno __P((u_int32_t, DBTYPE *));
static int __db_is_valid_pagetype __P((u_int32_t));
static int __db_meta2pgset
__P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, DB *));
+static int __db_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t,
+ PAGE *, void *, int (*)(void *, const void *), u_int32_t));
+static int __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *,
+ PAGE *, void *, int (*)(void *, const void *), u_int32_t));
static int __db_salvage_subdbs
__P((DB *, VRFY_DBINFO *, void *,
int(*)(void *, const void *), u_int32_t, int *));
@@ -136,9 +142,7 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
DB *dbp;
DB_ENV *dbenv;
DB_FH fh, *fhp;
- PAGE *h;
VRFY_DBINFO *vdp;
- db_pgno_t last;
int has, ret, isbad;
char *real_name;
@@ -153,16 +157,22 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
PANIC_CHECK(dbenv);
DB_ILLEGAL_AFTER_OPEN(dbp_orig, "verify");
-#define OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_ORDERCHKONLY | DB_SALVAGE)
+#define OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_ORDERCHKONLY | \
+ DB_PRINTABLE | DB_SALVAGE)
if ((ret = __db_fchk(dbenv, "DB->verify", flags, OKFLAGS)) != 0)
return (ret);
/*
* DB_SALVAGE is mutually exclusive with the other flags except
- * DB_AGGRESSIVE.
+ * DB_AGGRESSIVE and DB_PRINTABLE.
*/
if (LF_ISSET(DB_SALVAGE) &&
- (flags & ~DB_AGGRESSIVE) != DB_SALVAGE)
+ (flags & ~DB_AGGRESSIVE & ~DB_PRINTABLE) != DB_SALVAGE)
+ return (__db_ferr(dbenv, "__db_verify", 1));
+
+ /* DB_AGGRESSIVE and DB_PRINTABLE are only meaningful when salvaging. */
+ if ((LF_ISSET(DB_AGGRESSIVE) || LF_ISSET(DB_PRINTABLE)) &&
+ !LF_ISSET(DB_SALVAGE))
return (__db_ferr(dbenv, "__db_verify", 1));
if (LF_ISSET(DB_ORDERCHKONLY) && flags != DB_ORDERCHKONLY)
@@ -232,9 +242,17 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
if ((ret = __db_vrfy_dbinfo_create(dbenv, 1024, &vdp)) != 0)
goto err;
+ /*
+ * Note whether the user has requested that we use printable
+ * chars where possible. We won't get here with this flag if
+ * we're not salvaging.
+ */
+ if (LF_ISSET(DB_PRINTABLE))
+ F_SET(vdp, SALVAGE_PRINTABLE);
+
/* Find the real name of the file. */
if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
+ DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
goto err;
/*
@@ -271,25 +289,15 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
* the [safe] part of __db_open that initializes the environment--
* and the mpool--manually.
*/
- if ((ret = __db_dbenv_setup(dbp,
- name, DB_ODDFILESIZE | DB_RDONLY)) != 0)
+ if ((ret = __db_dbenv_setup(dbp, NULL,
+ name, TXN_INVALID, DB_ODDFILESIZE | DB_RDONLY)) != 0)
return (ret);
/* Mark the dbp as opened, so that we correctly handle its close. */
- F_SET(dbp, DB_OPEN_CALLED);
-
- /*
- * Find out the page number of the last page in the database.
- *
- * XXX: This currently fails if the last page is of bad type,
- * because it calls __db_pgin and that pukes. This is bad.
- */
- if ((ret = memp_fget(dbp->mpf, &last, DB_MPOOL_LAST, &h)) != 0)
- goto err;
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
- goto err;
+ F_SET(dbp, DB_AM_OPEN_CALLED);
- vdp->last_pgno = last;
+ /* Find out the page number of the last page in the database. */
+ dbp->mpf->last_pgno(dbp->mpf, &vdp->last_pgno);
/*
* DB_ORDERCHKONLY is a special case; our file consists of
@@ -373,7 +381,10 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
}
if (0) {
-err: (void)__db_err(dbenv, "%s: %s", name, db_strerror(ret));
+ /* Don't try to strerror() DB_VERIFY_FATAL; it's private. */
+err: if (ret == DB_VERIFY_FATAL)
+ ret = DB_VERIFY_BAD;
+ (void)__db_err(dbenv, "%s: %s", name, db_strerror(ret));
}
if (LF_ISSET(DB_SALVAGE) &&
@@ -385,13 +396,13 @@ done: if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)
dbp->db_feedback(dbp, DB_VERIFY, 100);
if (F_ISSET(fhp, DB_FH_VALID))
- (void)__os_closehandle(fhp);
+ (void)__os_closehandle(dbenv, fhp);
if (dbp)
(void)dbp->close(dbp, 0);
if (vdp)
- (void)__db_vrfy_dbinfo_destroy(vdp);
+ (void)__db_vrfy_dbinfo_destroy(dbenv, vdp);
if (real_name)
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
if ((ret == 0 && isbad == 1) || ret == DB_VERIFY_FATAL)
ret = DB_VERIFY_BAD;
@@ -417,10 +428,11 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
db_pgno_t freelist;
- int t_ret, ret, nr, swapped;
+ size_t nr;
+ int isbad, ret, swapped;
u_int8_t mbuf[DBMETASIZE];
- swapped = ret = t_ret = 0;
+ isbad = ret = swapped = 0;
freelist = 0;
dbenv = dbp->dbenv;
meta = (DBMETA *)mbuf;
@@ -432,29 +444,43 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
* may be zero; this is okay, as we want page zero anyway and
* 0*0 == 0.
*/
- if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
- goto err;
-
- if ((ret = __os_read(dbenv, fhp, mbuf, DBMETASIZE, (size_t *)&nr)) != 0)
- goto err;
+ if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0 ||
+ (ret = __os_read(dbenv, fhp, mbuf, DBMETASIZE, &nr)) != 0) {
+ __db_err(dbenv,
+ "Metadata page %lu cannot be read: %s",
+ (u_long)PGNO_BASE_MD, db_strerror(ret));
+ return (ret);
+ }
if (nr != DBMETASIZE) {
- EPRINT((dbp->dbenv,
- "Incomplete metadata page %lu", (u_long)PGNO_BASE_MD));
- t_ret = DB_VERIFY_FATAL;
- goto err;
+ EPRINT((dbenv,
+ "Page %lu: Incomplete metadata page",
+ (u_long)PGNO_BASE_MD));
+ return (DB_VERIFY_FATAL);
+ }
+
+ if ((ret = __db_chk_meta(dbenv, dbp, meta, 1)) != 0) {
+ EPRINT((dbenv,
+ "Page %lu: metadata page corrupted, (u_long)PGNO_BASE_MD"));
+ isbad = 1;
+ if (ret != -1) {
+ EPRINT((dbenv,
+ "Page %lu: could not check metadata page",
+ (u_long)PGNO_BASE_MD));
+ return (DB_VERIFY_FATAL);
+ }
}
/*
* Check all of the fields that we can.
+ *
+ * 08-11: Current page number. Must == pgno.
+ * Note that endianness doesn't matter--it's zero.
*/
-
- /* 08-11: Current page number. Must == pgno. */
- /* Note that endianness doesn't matter--it's zero. */
if (meta->pgno != PGNO_BASE_MD) {
- EPRINT((dbp->dbenv, "Bad pgno: was %lu, should be %lu",
- (u_long)meta->pgno, (u_long)PGNO_BASE_MD));
- ret = DB_VERIFY_BAD;
+ isbad = 1;
+ EPRINT((dbenv, "Page %lu: pgno incorrectly set to %lu",
+ (u_long)PGNO_BASE_MD, (u_long)meta->pgno));
}
/* 12-15: Magic number. Must be one of valid set. */
@@ -466,9 +492,10 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
&dbp->type))
swapped = 1;
else {
- EPRINT((dbp->dbenv,
- "Bad magic number: %lu", (u_long)meta->magic));
- ret = DB_VERIFY_BAD;
+ isbad = 1;
+ EPRINT((dbenv,
+ "Page %lu: bad magic number %lu",
+ (u_long)PGNO_BASE_MD, (u_long)meta->magic));
}
}
@@ -478,12 +505,19 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
*/
if (swapped)
M_32_SWAP(meta->version);
- if ((dbp->type == DB_BTREE && meta->version != DB_BTREEVERSION) ||
- (dbp->type == DB_HASH && meta->version != DB_HASHVERSION) ||
- (dbp->type == DB_QUEUE && meta->version != DB_QAMVERSION)) {
- ret = DB_VERIFY_BAD;
- EPRINT((dbp->dbenv, "%s%s", "Old or incorrect DB ",
- "version; extraneous errors may result"));
+ if ((dbp->type == DB_BTREE &&
+ (meta->version > DB_BTREEVERSION ||
+ meta->version < DB_BTREEOLDVER)) ||
+ (dbp->type == DB_HASH &&
+ (meta->version > DB_HASHVERSION ||
+ meta->version < DB_HASHOLDVER)) ||
+ (dbp->type == DB_QUEUE &&
+ (meta->version > DB_QAMVERSION ||
+ meta->version < DB_QAMOLDVER))) {
+ isbad = 1;
+ EPRINT((dbenv,
+ "Page %lu: unsupported DB version %lu; extraneous errors may result",
+ (u_long)PGNO_BASE_MD, (u_long)meta->version));
}
/*
@@ -495,9 +529,9 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
if (IS_VALID_PAGESIZE(meta->pagesize))
dbp->pgsize = meta->pagesize;
else {
- EPRINT((dbp->dbenv,
- "Bad page size: %lu", (u_long)meta->pagesize));
- ret = DB_VERIFY_BAD;
+ isbad = 1;
+ EPRINT((dbenv, "Page %lu: bad page size %lu",
+ (u_long)PGNO_BASE_MD, (u_long)meta->pagesize));
/*
* Now try to settle on a pagesize to use.
@@ -516,8 +550,9 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
if ((dbp->type == DB_BTREE && meta->type != P_BTREEMETA) ||
(dbp->type == DB_HASH && meta->type != P_HASHMETA) ||
(dbp->type == DB_QUEUE && meta->type != P_QAMMETA)) {
- ret = DB_VERIFY_BAD;
- EPRINT((dbp->dbenv, "Bad page type: %lu", (u_long)meta->type));
+ isbad = 1;
+ EPRINT((dbenv, "Page %lu: bad page type %lu",
+ (u_long)PGNO_BASE_MD, (u_long)meta->type));
}
/*
@@ -547,21 +582,16 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
pip->free = freelist;
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
return (ret);
/* Set up the dbp's fileid. We don't use the regular open path. */
memcpy(dbp->fileid, meta->uid, DB_FILE_ID_LEN);
- if (0) {
-err: __db_err(dbenv, "%s", db_strerror(ret));
- }
-
if (swapped == 1)
F_SET(dbp, DB_AM_SWAP);
- if (t_ret != 0)
- ret = t_ret;
- return (ret);
+
+ return (isbad ? DB_VERIFY_BAD : 0);
}
/*
@@ -578,12 +608,14 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
u_int32_t flags;
{
DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t i;
int ret, t_ret, isbad;
- ret = isbad = t_ret = 0;
dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ ret = isbad = t_ret = 0;
if ((ret = __db_fchk(dbenv,
"__db_vrfy_walkpages", flags, OKFLAGS)) != 0)
@@ -598,11 +630,17 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
if (LF_ISSET(DB_SALVAGE) && (__db_salvage_isdone(vdp, i) != 0))
continue;
- /* If an individual page get fails, keep going. */
- if ((t_ret = memp_fget(dbp->mpf, &i, 0, &h)) != 0) {
+ /*
+ * If an individual page get fails, keep going if and only
+ * if we're salvaging.
+ */
+ if ((t_ret = mpf->get(mpf, &i, 0, &h)) != 0) {
if (ret == 0)
ret = t_ret;
- continue;
+ if (LF_ISSET(DB_SALVAGE))
+ continue;
+ else
+ return (ret);
}
if (LF_ISSET(DB_SALVAGE)) {
@@ -619,63 +657,75 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
}
} else {
/*
+ * If we are not salvaging, and we get any error
+ * other than DB_VERIFY_BAD, return immediately;
+ * it may not be safe to proceed. If we get
+ * DB_VERIFY_BAD, keep going; listing more errors
+ * may make it easier to diagnose problems and
+ * determine the magnitude of the corruption.
+ */
+
+ /*
* Verify info common to all page
* types.
*/
- if (i != PGNO_BASE_MD)
- if ((t_ret = __db_vrfy_common(dbp,
- vdp, h, i, flags)) == DB_VERIFY_BAD)
+ if (i != PGNO_BASE_MD) {
+ ret = __db_vrfy_common(dbp, vdp, h, i, flags);
+ if (ret == DB_VERIFY_BAD)
isbad = 1;
+ else if (ret != 0)
+ goto err;
+ }
switch (TYPE(h)) {
case P_INVALID:
- t_ret = __db_vrfy_invalid(dbp,
- vdp, h, i, flags);
+ ret = __db_vrfy_invalid(dbp, vdp, h, i, flags);
break;
case __P_DUPLICATE:
isbad = 1;
- EPRINT((dbp->dbenv,
- "Old-style duplicate page: %lu",
+ EPRINT((dbenv,
+ "Page %lu: old-style duplicate page",
(u_long)i));
break;
case P_HASH:
- t_ret = __ham_vrfy(dbp,
+ ret = __ham_vrfy(dbp,
vdp, h, i, flags);
break;
case P_IBTREE:
case P_IRECNO:
case P_LBTREE:
case P_LDUP:
- t_ret = __bam_vrfy(dbp,
+ ret = __bam_vrfy(dbp,
vdp, h, i, flags);
break;
case P_LRECNO:
- t_ret = __ram_vrfy_leaf(dbp,
+ ret = __ram_vrfy_leaf(dbp,
vdp, h, i, flags);
break;
case P_OVERFLOW:
- t_ret = __db_vrfy_overflow(dbp,
+ ret = __db_vrfy_overflow(dbp,
vdp, h, i, flags);
break;
case P_HASHMETA:
- t_ret = __ham_vrfy_meta(dbp,
+ ret = __ham_vrfy_meta(dbp,
vdp, (HMETA *)h, i, flags);
break;
case P_BTREEMETA:
- t_ret = __bam_vrfy_meta(dbp,
+ ret = __bam_vrfy_meta(dbp,
vdp, (BTMETA *)h, i, flags);
break;
case P_QAMMETA:
- t_ret = __qam_vrfy_meta(dbp,
+ ret = __qam_vrfy_meta(dbp,
vdp, (QMETA *)h, i, flags);
break;
case P_QAMDATA:
- t_ret = __qam_vrfy_data(dbp,
+ ret = __qam_vrfy_data(dbp,
vdp, (QPAGE *)h, i, flags);
break;
default:
- EPRINT((dbp->dbenv,
- "Unknown page type: %lu", (u_long)TYPE(h)));
+ EPRINT((dbenv,
+ "Page %lu: unknown page type %lu",
+ (u_long)i, (u_long)TYPE(h)));
isbad = 1;
break;
}
@@ -683,12 +733,10 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
/*
* Set up error return.
*/
- if (t_ret == DB_VERIFY_BAD)
+ if (ret == DB_VERIFY_BAD)
isbad = 1;
- else if (t_ret == DB_VERIFY_FATAL)
+ else if (ret != 0)
goto err;
- else
- ret = t_ret;
/*
* Provide feedback to the application about our
@@ -701,14 +749,21 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
(i + 1) * 50 / (vdp->last_pgno + 1));
}
- if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
- ret = t_ret;
+ /*
+ * Just as with the page get, bail if and only if we're
+ * not salvaging.
+ */
+ if ((t_ret = mpf->put(mpf, h, 0)) != 0) {
+ if (ret == 0)
+ ret = t_ret;
+ if (!LF_ISSET(DB_SALVAGE))
+ return (ret);
+ }
}
if (0) {
-err: if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+err: if ((t_ret = mpf->put(mpf, h, 0)) != 0)
return (ret == 0 ? t_ret : ret);
- return (DB_VERIFY_BAD);
}
return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
@@ -786,8 +841,8 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
*/
if ((ret = __db_vrfy_getpageinfo(vdp, 0, &pip)) != 0)
goto err;
- hassubs = F_ISSET(pip, VRFY_HAS_SUBDBS);
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ hassubs = F_ISSET(pip, VRFY_HAS_SUBDBS) ? 1 : 0;
+ if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
goto err;
if (isbad == 0 && hassubs)
@@ -855,23 +910,23 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
if ((ret = __db_vrfy_pgset_get(pgset, i, &p)) != 0)
goto err;
if (p == 0) {
- EPRINT((dbp->dbenv,
- "Unreferenced page %lu", (u_long)i));
+ EPRINT((dbenv,
+ "Page %lu: unreferenced page", (u_long)i));
isbad = 1;
}
if (F_ISSET(pip, VRFY_IS_ALLZEROES)) {
- EPRINT((dbp->dbenv,
- "Totally zeroed page %lu", (u_long)i));
+ EPRINT((dbenv,
+ "Page %lu: totally zeroed page", (u_long)i));
isbad = 1;
}
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
goto err;
pip = NULL;
}
err: if (pip != NULL)
- (void)__db_vrfy_putpageinfo(vdp, pip);
+ (void)__db_vrfy_putpageinfo(dbenv, vdp, pip);
return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
}
@@ -936,10 +991,13 @@ __db_vrfy_common(dbp, vdp, h, pgno, flags)
db_pgno_t pgno;
u_int32_t flags;
{
+ DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
int ret, t_ret;
u_int8_t *p;
+ dbenv = dbp->dbenv;
+
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
return (ret);
@@ -957,8 +1015,8 @@ __db_vrfy_common(dbp, vdp, h, pgno, flags)
if (pgno != 0 && PGNO(h) == 0) {
for (p = (u_int8_t *)h; p < (u_int8_t *)h + dbp->pgsize; p++)
if (*p != 0) {
- EPRINT((dbp->dbenv,
- "Page %lu should be zeroed and is not",
+ EPRINT((dbenv,
+ "Page %lu: partially zeroed page",
(u_long)pgno));
ret = DB_VERIFY_BAD;
goto err;
@@ -976,19 +1034,19 @@ __db_vrfy_common(dbp, vdp, h, pgno, flags)
}
if (PGNO(h) != pgno) {
- EPRINT((dbp->dbenv,
- "Bad page number: %lu should be %lu",
- (u_long)h->pgno, (u_long)pgno));
+ EPRINT((dbenv, "Page %lu: bad page number %lu",
+ (u_long)pgno, (u_long)h->pgno));
ret = DB_VERIFY_BAD;
}
if (!__db_is_valid_pagetype(h->type)) {
- EPRINT((dbp->dbenv, "Bad page type: %lu", (u_long)h->type));
+ EPRINT((dbenv, "Page %lu: bad page type %lu",
+ (u_long)pgno, (u_long)h->type));
ret = DB_VERIFY_BAD;
}
pip->type = h->type;
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return (ret);
@@ -1007,22 +1065,24 @@ __db_vrfy_invalid(dbp, vdp, h, pgno, flags)
db_pgno_t pgno;
u_int32_t flags;
{
+ DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
int ret, t_ret;
+ dbenv = dbp->dbenv;
+
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
return (ret);
pip->next_pgno = pip->prev_pgno = 0;
if (!IS_VALID_PGNO(NEXT_PGNO(h))) {
- EPRINT((dbp->dbenv,
- "Invalid next_pgno %lu on page %lu",
- (u_long)NEXT_PGNO(h), (u_long)pgno));
+ EPRINT((dbenv, "Page %lu: invalid next_pgno %lu",
+ (u_long)pgno, (u_long)NEXT_PGNO(h)));
ret = DB_VERIFY_BAD;
} else
pip->next_pgno = NEXT_PGNO(h);
- if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+ if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
@@ -1048,9 +1108,12 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
db_pgno_t pgno;
u_int32_t flags;
{
+ DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
int isbad, ret, t_ret;
+ dbenv = dbp->dbenv;
+
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
return (ret);
isbad = 0;
@@ -1066,12 +1129,12 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
if (!IS_VALID_PGNO(PREV_PGNO(h)) || PREV_PGNO(h) == pip->pgno) {
isbad = 1;
- EPRINT((dbp->dbenv, "Page %lu: Invalid prev_pgno %lu",
+ EPRINT((dbenv, "Page %lu: invalid prev_pgno %lu",
(u_long)pip->pgno, (u_long)PREV_PGNO(h)));
}
if (!IS_VALID_PGNO(NEXT_PGNO(h)) || NEXT_PGNO(h) == pip->pgno) {
isbad = 1;
- EPRINT((dbp->dbenv, "Page %lu: Invalid next_pgno %lu",
+ EPRINT((dbenv, "Page %lu: invalid next_pgno %lu",
(u_long)pip->pgno, (u_long)NEXT_PGNO(h)));
}
pip->prev_pgno = PREV_PGNO(h);
@@ -1089,8 +1152,7 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
if (TYPE(h) != P_OVERFLOW) {
if (BKEYDATA_PSIZE(0) * NUM_ENT(h) > dbp->pgsize) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Page %lu: Too many entries: %lu",
+ EPRINT((dbenv, "Page %lu: too many entries: %lu",
(u_long)pgno, (u_long)NUM_ENT(h)));
}
pip->entries = NUM_ENT(h);
@@ -1106,8 +1168,8 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
case P_IRECNO:
if (LEVEL(h) < LEAFLEVEL + 1 || LEVEL(h) > MAXBTREELEVEL) {
isbad = 1;
- EPRINT((dbp->dbenv, "Bad btree level %lu on page %lu",
- (u_long)LEVEL(h), (u_long)pgno));
+ EPRINT((dbenv, "Page %lu: bad btree level %lu",
+ (u_long)pgno, (u_long)LEVEL(h)));
}
pip->bt_level = LEVEL(h);
break;
@@ -1116,17 +1178,17 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
case P_LRECNO:
if (LEVEL(h) != LEAFLEVEL) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Btree leaf page %lu has incorrect level %lu",
+ EPRINT((dbenv,
+ "Page %lu: btree leaf page has incorrect level %lu",
(u_long)pgno, (u_long)LEVEL(h)));
}
break;
default:
if (LEVEL(h) != 0) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Nonzero level %lu in non-btree database page %lu",
- (u_long)LEVEL(h), (u_long)pgno));
+ EPRINT((dbenv,
+ "Page %lu: nonzero level %lu in non-btree database",
+ (u_long)pgno, (u_long)LEVEL(h)));
}
break;
}
@@ -1139,7 +1201,7 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
* by offset and length--cover the right part of the page
* without overlaps, gaps, or violations of the page boundary.
*/
- if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+ if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
@@ -1161,11 +1223,14 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, flags)
db_pgno_t pgno;
u_int32_t flags;
{
+ DB_ENV *dbenv;
DBTYPE dbtype, magtype;
VRFY_PAGEINFO *pip;
int isbad, ret, t_ret;
isbad = 0;
+ dbenv = dbp->dbenv;
+
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
return (ret);
@@ -1190,31 +1255,37 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, flags)
/* magic number valid */
if (!__db_is_valid_magicno(meta->magic, &magtype)) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Magic number invalid on page %lu", (u_long)pgno));
+ EPRINT((dbenv,
+ "Page %lu: invalid magic number", (u_long)pgno));
}
if (magtype != dbtype) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Magic number does not match type of page %lu",
+ EPRINT((dbenv,
+ "Page %lu: magic number does not match database type",
(u_long)pgno));
}
/* version */
- if ((dbtype == DB_BTREE && meta->version != DB_BTREEVERSION) ||
- (dbtype == DB_HASH && meta->version != DB_HASHVERSION) ||
- (dbtype == DB_QUEUE && meta->version != DB_QAMVERSION)) {
+ if ((dbtype == DB_BTREE &&
+ (meta->version > DB_BTREEVERSION ||
+ meta->version < DB_BTREEOLDVER)) ||
+ (dbtype == DB_HASH &&
+ (meta->version > DB_HASHVERSION ||
+ meta->version < DB_HASHOLDVER)) ||
+ (dbtype == DB_QUEUE &&
+ (meta->version > DB_QAMVERSION ||
+ meta->version < DB_QAMOLDVER))) {
isbad = 1;
- EPRINT((dbp->dbenv, "%s%s", "Old of incorrect DB ",
- "version; extraneous errors may result"));
+ EPRINT((dbenv,
+ "Page %lu: unsupported database version %lu; extraneous errors may result",
+ (u_long)pgno, (u_long)meta->version));
}
/* pagesize */
if (meta->pagesize != dbp->pgsize) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Invalid pagesize %lu on page %lu",
- (u_long)meta->pagesize, (u_long)pgno));
+ EPRINT((dbenv, "Page %lu: invalid pagesize %lu",
+ (u_long)pgno, (u_long)meta->pagesize));
}
/* free list */
@@ -1224,9 +1295,9 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, flags)
*/
if (pgno != PGNO_BASE_MD && meta->free != PGNO_INVALID) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Nonempty free list on subdatabase metadata page %lu",
- pgno));
+ EPRINT((dbenv,
+ "Page %lu: nonempty free list on subdatabase metadata page",
+ (u_long)pgno));
}
/* Can correctly be PGNO_INVALID--that's just the end of the list. */
@@ -1234,9 +1305,9 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, flags)
pip->free = meta->free;
else if (!IS_VALID_PGNO(meta->free)) {
isbad = 1;
- EPRINT((dbp->dbenv,
- "Nonsensical free list pgno %lu on page %lu",
- (u_long)meta->free, (u_long)pgno));
+ EPRINT((dbenv,
+ "Page %lu: nonsensical free list pgno %lu",
+ (u_long)pgno, (u_long)meta->free));
}
/*
@@ -1245,7 +1316,7 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, flags)
*/
F_CLR(pip, VRFY_INCOMPLETE);
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
@@ -1264,51 +1335,56 @@ __db_vrfy_freelist(dbp, vdp, meta, flags)
u_int32_t flags;
{
DB *pgset;
+ DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
- db_pgno_t pgno;
+ db_pgno_t cur_pgno, next_pgno;
int p, ret, t_ret;
pgset = vdp->pgset;
DB_ASSERT(pgset != NULL);
+ dbenv = dbp->dbenv;
if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0)
return (ret);
- for (pgno = pip->free; pgno != PGNO_INVALID; pgno = pip->next_pgno) {
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ for (next_pgno = pip->free;
+ next_pgno != PGNO_INVALID; next_pgno = pip->next_pgno) {
+ cur_pgno = pip->pgno;
+ if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
return (ret);
/* This shouldn't happen, but just in case. */
- if (!IS_VALID_PGNO(pgno)) {
- EPRINT((dbp->dbenv,
- "Invalid next_pgno on free list page %lu",
- (u_long)pgno));
+ if (!IS_VALID_PGNO(next_pgno)) {
+ EPRINT((dbenv,
+ "Page %lu: invalid next_pgno %lu on free list page",
+ (u_long)cur_pgno, (u_long)next_pgno));
return (DB_VERIFY_BAD);
}
/* Detect cycles. */
- if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
+ if ((ret = __db_vrfy_pgset_get(pgset, next_pgno, &p)) != 0)
return (ret);
if (p != 0) {
- EPRINT((dbp->dbenv,
- "Page %lu encountered a second time on free list",
- (u_long)pgno));
+ EPRINT((dbenv,
+ "Page %lu: page %lu encountered a second time on free list",
+ (u_long)cur_pgno, (u_long)next_pgno));
return (DB_VERIFY_BAD);
}
- if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
+ if ((ret = __db_vrfy_pgset_inc(pgset, next_pgno)) != 0)
return (ret);
- if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
+ if ((ret = __db_vrfy_getpageinfo(vdp, next_pgno, &pip)) != 0)
return (ret);
if (pip->type != P_INVALID) {
- EPRINT((dbp->dbenv,
- "Non-invalid page %lu on free list", (u_long)pgno));
+ EPRINT((dbenv,
+ "Page %lu: non-invalid page %lu on free list",
+ (u_long)cur_pgno, (u_long)next_pgno));
ret = DB_VERIFY_BAD; /* unsafe to continue */
break;
}
}
- if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
ret = t_ret;
return (ret);
}
@@ -1328,6 +1404,7 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
DB *mdbp;
DBC *dbc;
DBT key, data;
+ DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
db_pgno_t meta_pgno;
int ret, t_ret, isbad;
@@ -1335,19 +1412,22 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
isbad = 0;
dbc = NULL;
+ dbenv = dbp->dbenv;
- if ((ret = __db_master_open(dbp, dbname, DB_RDONLY, 0, &mdbp)) != 0)
+ if ((ret =
+ __db_master_open(dbp, NULL, dbname, DB_RDONLY, 0, &mdbp)) != 0)
return (ret);
- if ((ret =
- __db_icursor(mdbp, NULL, DB_BTREE, PGNO_INVALID, 0, &dbc)) != 0)
+ if ((ret = __db_icursor(mdbp,
+ NULL, DB_BTREE, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0)
goto err;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
if (data.size != sizeof(db_pgno_t)) {
- EPRINT((dbp->dbenv, "Database entry of invalid size"));
+ EPRINT((dbenv,
+ "Subdatabase entry not page-number size"));
isbad = 1;
goto err;
}
@@ -1358,8 +1438,8 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
*/
DB_NTOHL(&meta_pgno);
if (meta_pgno == PGNO_INVALID || meta_pgno > vdp->last_pgno) {
- EPRINT((dbp->dbenv,
- "Database entry references invalid page %lu",
+ EPRINT((dbenv,
+ "Subdatabase entry references invalid page %lu",
(u_long)meta_pgno));
isbad = 1;
goto err;
@@ -1367,7 +1447,7 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
goto err;
type = pip->type;
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
goto err;
switch (type) {
case P_BTREEMETA:
@@ -1390,8 +1470,8 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
break;
case P_QAMMETA:
default:
- EPRINT((dbp->dbenv,
- "Database entry references page %lu of invalid type %lu",
+ EPRINT((dbenv,
+ "Subdatabase entry references page %lu of invalid type %lu",
(u_long)meta_pgno, (u_long)type));
ret = DB_VERIFY_BAD;
goto err;
@@ -1416,9 +1496,9 @@ err: if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
* Provide feedback during top-down database structure traversal.
* (See comment at the beginning of __db_vrfy_structure.)
*
- * PUBLIC: int __db_vrfy_struct_feedback __P((DB *, VRFY_DBINFO *));
+ * PUBLIC: void __db_vrfy_struct_feedback __P((DB *, VRFY_DBINFO *));
*/
-int
+void
__db_vrfy_struct_feedback(dbp, vdp)
DB *dbp;
VRFY_DBINFO *vdp;
@@ -1426,7 +1506,7 @@ __db_vrfy_struct_feedback(dbp, vdp)
int progress;
if (dbp->db_feedback == NULL)
- return (0);
+ return;
if (vdp->pgs_remaining > 0)
vdp->pgs_remaining--;
@@ -1434,8 +1514,6 @@ __db_vrfy_struct_feedback(dbp, vdp)
/* Don't allow a feedback call of 100 until we're really done. */
progress = 100 - (vdp->pgs_remaining * 50 / (vdp->last_pgno + 1));
dbp->db_feedback(dbp, DB_VERIFY, progress == 100 ? 99 : progress);
-
- return (0);
}
/*
@@ -1453,6 +1531,8 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
DB *mdbp, *pgset;
DBC *pgsc;
DBT key, data;
+ DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
HASH *h_internal;
HMETA *hmeta;
PAGE *h, *currpg;
@@ -1460,36 +1540,45 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
u_int32_t bucket;
int t_ret, ret;
- currpg = h = NULL;
- pgsc = NULL;
pgset = NULL;
+ pgsc = NULL;
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ currpg = h = NULL;
LF_CLR(DB_NOORDERCHK);
/* Open the master database and get the meta_pgno for the subdb. */
if ((ret = db_create(&mdbp, NULL, 0)) != 0)
return (ret);
- if ((ret = __db_master_open(dbp, name, DB_RDONLY, 0, &mdbp)) != 0)
+ if ((ret = __db_master_open(dbp, NULL, name, DB_RDONLY, 0, &mdbp)) != 0)
goto err;
memset(&key, 0, sizeof(key));
key.data = (void *)subdb;
+ key.size = (u_int32_t)strlen(subdb);
memset(&data, 0, sizeof(data));
- if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) != 0)
+ if ((ret = mdbp->get(mdbp, NULL, &key, &data, 0)) != 0)
goto err;
if (data.size != sizeof(db_pgno_t)) {
- EPRINT((dbp->dbenv, "Database entry of invalid size"));
+ EPRINT((dbenv, "Subdatabase entry of invalid size"));
ret = DB_VERIFY_BAD;
goto err;
}
memcpy(&meta_pgno, data.data, data.size);
- if ((ret = memp_fget(dbp->mpf, &meta_pgno, 0, &h)) != 0)
+ /*
+ * Subdatabase meta pgnos are stored in network byte
+ * order for cross-endian compatibility. Swap if appropriate.
+ */
+ DB_NTOHL(&meta_pgno);
+
+ if ((ret = mpf->get(mpf, &meta_pgno, 0, &h)) != 0)
goto err;
- if ((ret = __db_vrfy_pgset(dbp->dbenv, dbp->pgsize, &pgset)) != 0)
+ if ((ret = __db_vrfy_pgset(dbenv, dbp->pgsize, &pgset)) != 0)
goto err;
switch (TYPE(h)) {
@@ -1506,18 +1595,24 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
goto err;
while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
- if ((ret = memp_fget(dbp->mpf, &p, 0, &currpg)) != 0)
+ if ((ret = mpf->get(mpf, &p, 0, &currpg)) != 0)
goto err;
if ((ret = __bam_vrfy_itemorder(dbp,
NULL, currpg, p, NUM_ENT(currpg), 1,
F_ISSET(&btmeta->dbmeta, BTM_DUP), flags)) != 0)
goto err;
- if ((ret = memp_fput(dbp->mpf, currpg, 0)) != 0)
+ if ((ret = mpf->put(mpf, currpg, 0)) != 0)
goto err;
currpg = NULL;
}
- if ((ret = pgsc->c_close(pgsc)) != 0)
- goto err;
+
+ /*
+ * The normal exit condition for the loop above is DB_NOTFOUND.
+ * If we see that, zero it and continue on to cleanup.
+ * Otherwise, it's a real error and will be returned.
+ */
+ if (ret == DB_NOTFOUND)
+ ret = 0;
break;
case P_HASHMETA:
hmeta = (HMETA *)h;
@@ -1525,16 +1620,21 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
/*
* Make sure h_charkey is right.
*/
- if (h_internal == NULL || h_internal->h_hash == NULL) {
- EPRINT((dbp->dbenv,
- "DB_ORDERCHKONLY requires that a hash function be set"));
+ if (h_internal == NULL) {
+ EPRINT((dbenv,
+ "Page %lu: DB->h_internal field is NULL",
+ (u_long)meta_pgno));
ret = DB_VERIFY_BAD;
goto err;
}
+ if (h_internal->h_hash == NULL)
+ h_internal->h_hash = hmeta->dbmeta.version < 5
+ ? __ham_func4 : __ham_func5;
if (hmeta->h_charkey !=
h_internal->h_hash(dbp, CHARKEY, sizeof(CHARKEY))) {
- EPRINT((dbp->dbenv,
- "Incorrect hash function for database"));
+ EPRINT((dbenv,
+ "Page %lu: incorrect hash function for database",
+ (u_long)meta_pgno));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -1546,34 +1646,35 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
for (bucket = 0; bucket <= hmeta->max_bucket; bucket++) {
pgno = BS_TO_PAGE(bucket, hmeta->spares);
while (pgno != PGNO_INVALID) {
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = mpf->get(mpf,
&pgno, 0, &currpg)) != 0)
goto err;
if ((ret = __ham_vrfy_hashing(dbp,
- NUM_ENT(currpg),hmeta, bucket, pgno,
+ NUM_ENT(currpg), hmeta, bucket, pgno,
flags, h_internal->h_hash)) != 0)
goto err;
pgno = NEXT_PGNO(currpg);
- if ((ret = memp_fput(dbp->mpf, currpg, 0)) != 0)
+ if ((ret = mpf->put(mpf, currpg, 0)) != 0)
goto err;
currpg = NULL;
}
}
break;
default:
- EPRINT((dbp->dbenv, "Database meta page %lu of bad type %lu",
+ EPRINT((dbenv, "Page %lu: database metapage of bad type %lu",
(u_long)meta_pgno, (u_long)TYPE(h)));
ret = DB_VERIFY_BAD;
break;
}
-err: if (pgsc != NULL)
- (void)pgsc->c_close(pgsc);
- if (pgset != NULL)
- (void)pgset->close(pgset, 0);
- if (h != NULL && (t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+err: if (pgsc != NULL && (t_ret = pgsc->c_close(pgsc)) != 0 && ret == 0)
+ ret = t_ret;
+ if (pgset != NULL &&
+ (t_ret = pgset->close(pgset, 0)) != 0 && ret == 0)
ret = t_ret;
- if (currpg != NULL && (t_ret = memp_fput(dbp->mpf, currpg, 0)) != 0)
+ if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0)
+ ret = t_ret;
+ if (currpg != NULL && (t_ret = mpf->put(mpf, currpg, 0)) != 0)
ret = t_ret;
if ((t_ret = mdbp->close(mdbp, 0)) != 0)
ret = t_ret;
@@ -1584,11 +1685,8 @@ err: if (pgsc != NULL)
* __db_salvage --
* Walk through a page, salvaging all likely or plausible (w/
* DB_AGGRESSIVE) key/data pairs.
- *
- * PUBLIC: int __db_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *,
- * PUBLIC: void *, int (*)(void *, const void *), u_int32_t));
*/
-int
+static int
__db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
DB *dbp;
VRFY_DBINFO *vdp;
@@ -1659,24 +1757,29 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
u_int32_t flags;
{
DBT unkdbt, key, *dbt;
+ DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
u_int32_t pgtype;
int ret, err_ret;
void *ovflbuf;
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+
memset(&unkdbt, 0, sizeof(DBT));
- unkdbt.size = strlen("UNKNOWN") + 1;
+ unkdbt.size = (u_int32_t)strlen("UNKNOWN") + 1;
unkdbt.data = "UNKNOWN";
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, 0, &ovflbuf)) != 0)
+ if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0)
return (ret);
err_ret = 0;
while ((ret = __db_salvage_getnext(vdp, &pgno, &pgtype)) == 0) {
dbt = NULL;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
err_ret = ret;
continue;
}
@@ -1699,17 +1802,11 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
* a database with no dups. What to do?
*/
if ((ret = __db_safe_goff(dbp,
- vdp, pgno, &key, &ovflbuf, flags)) != 0) {
- err_ret = ret;
- continue;
- }
- if ((ret = __db_prdbt(&key,
- 0, " ", handle, callback, 0, NULL)) != 0) {
- err_ret = ret;
- continue;
- }
- if ((ret = __db_prdbt(&unkdbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ vdp, pgno, &key, &ovflbuf, flags)) != 0 ||
+ (ret = __db_prdbt(&key,
+ 0, " ", handle, callback, 0, vdp)) != 0 ||
+ (ret = __db_prdbt(&unkdbt,
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case SALVAGE_HASH:
@@ -1727,11 +1824,11 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
DB_ASSERT(0);
break;
}
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
err_ret = ret;
}
- __os_free(ovflbuf, 0);
+ __os_free(dbenv, ovflbuf);
if (err_ret != 0 && ret == 0)
ret = err_ret;
@@ -1743,8 +1840,8 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
* Offset of the ith inp array entry, which we can compare to the offset
* the entry stores.
*/
-#define INP_OFFSET(h, i) \
- ((db_indx_t)((u_int8_t *)(h)->inp + (i) - (u_int8_t *)(h)))
+#define INP_OFFSET(dbp, h, i) \
+ ((db_indx_t)((u_int8_t *)((P_INP(dbp,(h))) + (i)) - (u_int8_t *)(h)))
/*
* __db_vrfy_inpitem --
@@ -1770,33 +1867,35 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp)
u_int32_t flags, *himarkp, *offsetp;
{
BKEYDATA *bk;
- db_indx_t offset, len;
+ DB_ENV *dbenv;
+ db_indx_t *inp, offset, len;
+
+ dbenv = dbp->dbenv;
DB_ASSERT(himarkp != NULL);
+ inp = P_INP(dbp, h);
/*
* Check that the inp array, which grows from the beginning of the
* page forward, has not collided with the data, which grow from the
* end of the page backward.
*/
- if (h->inp + i >= (db_indx_t *)((u_int8_t *)h + *himarkp)) {
+ if (inp + i >= (db_indx_t *)((u_int8_t *)h + *himarkp)) {
/* We've collided with the data. We need to bail. */
- EPRINT((dbp->dbenv,
- "Page %lu entries listing %lu overlaps data",
+ EPRINT((dbenv, "Page %lu: entries listing %lu overlaps data",
(u_long)pgno, (u_long)i));
return (DB_VERIFY_FATAL);
}
- offset = h->inp[i];
+ offset = inp[i];
/*
* Check that the item offset is reasonable: it points somewhere
* after the inp array and before the end of the page.
*/
- if (offset <= INP_OFFSET(h, i) || offset > dbp->pgsize) {
- EPRINT((dbp->dbenv,
- "Bad offset %lu at page %lu index %lu",
- (u_long)offset, (u_long)pgno, (u_long)i));
+ if (offset <= INP_OFFSET(dbp, h, i) || offset > dbp->pgsize) {
+ EPRINT((dbenv, "Page %lu: bad offset %lu at page index %lu",
+ (u_long)pgno, (u_long)offset, (u_long)i));
return (DB_VERIFY_BAD);
}
@@ -1808,7 +1907,7 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp)
/*
* Check that the item length remains on-page.
*/
- bk = GET_BKEYDATA(h, i);
+ bk = GET_BKEYDATA(dbp, h, i);
/*
* We need to verify the type of the item here;
@@ -1826,16 +1925,16 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp)
len = BOVERFLOW_SIZE;
break;
default:
- EPRINT((dbp->dbenv,
- "Item %lu on page %lu of unrecognizable type",
- i, pgno));
+ EPRINT((dbenv,
+ "Page %lu: item %lu of unrecognizable type",
+ (u_long)pgno, (u_long)i));
return (DB_VERIFY_BAD);
}
if ((size_t)(offset + len) > dbp->pgsize) {
- EPRINT((dbp->dbenv,
- "Item %lu on page %lu extends past page boundary",
- (u_long)i, (u_long)pgno));
+ EPRINT((dbenv,
+ "Page %lu: item %lu extends past page boundary",
+ (u_long)pgno, (u_long)i));
return (DB_VERIFY_BAD);
}
}
@@ -1861,9 +1960,11 @@ __db_vrfy_duptype(dbp, vdp, pgno, flags)
db_pgno_t pgno;
u_int32_t flags;
{
+ DB_ENV *dbenv;
VRFY_PAGEINFO *pip;
int ret, isbad;
+ dbenv = dbp->dbenv;
isbad = 0;
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
@@ -1873,8 +1974,8 @@ __db_vrfy_duptype(dbp, vdp, pgno, flags)
case P_IBTREE:
case P_LDUP:
if (!LF_ISSET(ST_DUPSORT)) {
- EPRINT((dbp->dbenv,
- "Sorted duplicate set at page %lu in unsorted-dup database",
+ EPRINT((dbenv,
+ "Page %lu: sorted duplicate set in unsorted-dup database",
(u_long)pgno));
isbad = 1;
}
@@ -1882,21 +1983,29 @@ __db_vrfy_duptype(dbp, vdp, pgno, flags)
case P_IRECNO:
case P_LRECNO:
if (LF_ISSET(ST_DUPSORT)) {
- EPRINT((dbp->dbenv,
- "Unsorted duplicate set at page %lu in sorted-dup database",
+ EPRINT((dbenv,
+ "Page %lu: unsorted duplicate set in sorted-dup database",
(u_long)pgno));
isbad = 1;
}
break;
default:
- EPRINT((dbp->dbenv,
- "Duplicate page %lu of inappropriate type %lu",
- (u_long)pgno, (u_long)pip->type));
+ /*
+ * If the page is entirely zeroed, its pip->type will be a lie
+ * (we assumed it was a hash page, as they're allowed to be
+ * zeroed); handle this case specially.
+ */
+ if (F_ISSET(pip, VRFY_IS_ALLZEROES))
+ ZEROPG_ERR_PRINT(dbenv, pgno, "duplicate page");
+ else
+ EPRINT((dbenv,
+ "Page %lu: duplicate page of inappropriate type %lu",
+ (u_long)pgno, (u_long)pip->type));
isbad = 1;
break;
}
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
return (ret);
return (isbad == 1 ? DB_VERIFY_BAD : 0);
}
@@ -1934,14 +2043,17 @@ __db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags)
int (*callback) __P((void *, const void *));
u_int32_t flags;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
int ret, t_ret;
+ mpf = dbp->mpf;
+
if (pgno == PGNO_INVALID || !IS_VALID_PGNO(pgno))
return (DB_VERIFY_BAD);
/* We have a plausible page. Try it. */
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
switch (TYPE(h)) {
@@ -1972,7 +2084,7 @@ __db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags)
/* NOTREACHED */
}
-err: if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
+err: if ((t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
@@ -1994,16 +2106,18 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
BTMETA *btmeta;
DB *pgset;
DBC *pgsc;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t p, meta_pgno;
int ret, err_ret;
- err_ret = 0;
- pgsc = NULL;
pgset = NULL;
+ pgsc = NULL;
+ mpf = dbp->mpf;
+ err_ret = 0;
meta_pgno = PGNO_BASE_MD;
- if ((ret = memp_fget(dbp->mpf, &meta_pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &meta_pgno, 0, &h)) != 0)
return (ret);
if (TYPE(h) == P_BTREEMETA)
@@ -2028,7 +2142,7 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
/* We think we've got subdbs. Mark it so. */
*hassubsp = 1;
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
return (ret);
/*
@@ -2048,7 +2162,7 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
goto err;
while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
- if ((ret = memp_fget(dbp->mpf, &p, 0, &h)) != 0) {
+ if ((ret = mpf->get(mpf, &p, 0, &h)) != 0) {
err_ret = ret;
continue;
}
@@ -2061,7 +2175,7 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
else if ((ret = __db_salvage_subdbpg(
dbp, vdp, h, handle, callback, flags)) != 0)
err_ret = ret;
-nextpg: if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+nextpg: if ((ret = mpf->put(mpf, h, 0)) != 0)
err_ret = ret;
}
@@ -2079,7 +2193,7 @@ err: if (pgsc != NULL)
(void)pgsc->c_close(pgsc);
if (pgset != NULL)
(void)pgset->close(pgset, 0);
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (ret);
}
@@ -2087,12 +2201,8 @@ err: if (pgsc != NULL)
* __db_salvage_subdbpg --
* Given a known-good leaf page in the master database, salvage all
* leaf pages corresponding to each subdb.
- *
- * PUBLIC: int __db_salvage_subdbpg
- * PUBLIC: __P((DB *, VRFY_DBINFO *, PAGE *, void *,
- * PUBLIC: int (*)(void *, const void *), u_int32_t));
*/
-int
+static int
__db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
DB *dbp;
VRFY_DBINFO *vdp;
@@ -2106,16 +2216,20 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
DB *pgset;
DBC *pgsc;
DBT key;
+ DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
PAGE *subpg;
db_indx_t i;
db_pgno_t meta_pgno, p;
int ret, err_ret, t_ret;
char *subdbname;
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
ret = err_ret = 0;
subdbname = NULL;
- if ((ret = __db_vrfy_pgset(dbp->dbenv, dbp->pgsize, &pgset)) != 0)
+ if ((ret = __db_vrfy_pgset(dbenv, dbp->pgsize, &pgset)) != 0)
return (ret);
/*
@@ -2123,8 +2237,8 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
* corresponding to that entry.
*/
for (i = 0; i < NUM_ENT(master); i += P_INDX) {
- bkkey = GET_BKEYDATA(master, i);
- bkdata = GET_BKEYDATA(master, i + O_INDX);
+ bkkey = GET_BKEYDATA(dbp, master, i);
+ bkdata = GET_BKEYDATA(dbp, master, i + O_INDX);
/* Get the subdatabase name. */
if (B_TYPE(bkkey->type) == B_OVERFLOW) {
@@ -2140,13 +2254,13 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
}
/* Nul-terminate it. */
- if ((ret = __os_realloc(dbp->dbenv,
- key.size + 1, NULL, &subdbname)) != 0)
+ if ((ret = __os_realloc(dbenv,
+ key.size + 1, &subdbname)) != 0)
goto err;
subdbname[key.size] = '\0';
} else if (B_TYPE(bkkey->type == B_KEYDATA)) {
- if ((ret = __os_realloc(dbp->dbenv,
- bkkey->len + 1, NULL, &subdbname)) != 0)
+ if ((ret = __os_realloc(dbenv,
+ bkkey->len + 1, &subdbname)) != 0)
goto err;
memcpy(subdbname, bkkey->data, bkkey->len);
subdbname[bkkey->len] = '\0';
@@ -2159,9 +2273,15 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
}
memcpy(&meta_pgno, bkdata->data, sizeof(db_pgno_t));
+ /*
+ * Subdatabase meta pgnos are stored in network byte
+ * order for cross-endian compatibility. Swap if appropriate.
+ */
+ DB_NTOHL(&meta_pgno);
+
/* If we can't get the subdb meta page, just skip the subdb. */
if (!IS_VALID_PGNO(meta_pgno) ||
- (ret = memp_fget(dbp->mpf, &meta_pgno, 0, &subpg)) != 0) {
+ (ret = mpf->get(mpf, &meta_pgno, 0, &subpg)) != 0) {
err_ret = ret;
continue;
}
@@ -2177,7 +2297,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
if ((ret =
__db_vrfy_common(dbp, vdp, subpg, meta_pgno, flags)) != 0) {
err_ret = ret;
- (void)memp_fput(dbp->mpf, subpg, 0);
+ (void)mpf->put(mpf, subpg, 0);
continue;
}
switch (TYPE(subpg)) {
@@ -2185,7 +2305,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
if ((ret = __bam_vrfy_meta(dbp,
vdp, (BTMETA *)subpg, meta_pgno, flags)) != 0) {
err_ret = ret;
- (void)memp_fput(dbp->mpf, subpg, 0);
+ (void)mpf->put(mpf, subpg, 0);
continue;
}
break;
@@ -2193,7 +2313,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
if ((ret = __ham_vrfy_meta(dbp,
vdp, (HMETA *)subpg, meta_pgno, flags)) != 0) {
err_ret = ret;
- (void)memp_fput(dbp->mpf, subpg, 0);
+ (void)mpf->put(mpf, subpg, 0);
continue;
}
break;
@@ -2204,7 +2324,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
/* NOTREACHED */
}
- if ((ret = memp_fput(dbp->mpf, subpg, 0)) != 0) {
+ if ((ret = mpf->put(mpf, subpg, 0)) != 0) {
err_ret = ret;
continue;
}
@@ -2223,14 +2343,14 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
goto err;
while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
- if ((ret = memp_fget(dbp->mpf, &p, 0, &subpg)) != 0) {
+ if ((ret = mpf->get(mpf, &p, 0, &subpg)) != 0) {
err_ret = ret;
continue;
}
if ((ret = __db_salvage(dbp, vdp, p, subpg,
handle, callback, flags)) != 0)
err_ret = ret;
- if ((ret = memp_fput(dbp->mpf, subpg, 0)) != 0)
+ if ((ret = mpf->put(mpf, subpg, 0)) != 0)
err_ret = ret;
}
@@ -2243,7 +2363,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
goto err;
}
err: if (subdbname)
- __os_free(subdbname, 0);
+ __os_free(dbenv, subdbname);
if ((t_ret = pgset->close(pgset, 0)) != 0)
ret = t_ret;
@@ -2268,10 +2388,13 @@ __db_meta2pgset(dbp, vdp, pgno, flags, pgset)
u_int32_t flags;
DB *pgset;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
int ret, t_ret;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ mpf = dbp->mpf;
+
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
switch (TYPE(h)) {
@@ -2286,7 +2409,7 @@ __db_meta2pgset(dbp, vdp, pgno, flags, pgset)
break;
}
- if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((t_ret = mpf->put(mpf, h, 0)) != 0)
return (t_ret);
return (ret);
}
@@ -2305,7 +2428,6 @@ __db_guesspgsize(dbenv, fhp)
size_t nr;
u_int32_t guess;
u_int8_t type;
- int ret;
for (guess = DB_MAX_PGSIZE; guess >= DB_MIN_PGSIZE; guess >>= 1) {
/*
@@ -2321,11 +2443,11 @@ __db_guesspgsize(dbenv, fhp)
* our previous guess; that last one was probably the page size.
*/
for (i = 1; i <= 3; i++) {
- if ((ret = __os_seek(dbenv, fhp, guess,
- i, SSZ(DBMETA, type), 0, DB_OS_SEEK_SET)) != 0)
+ if (__os_seek(dbenv, fhp, guess,
+ i, SSZ(DBMETA, type), 0, DB_OS_SEEK_SET) != 0)
break;
- if ((ret = __os_read(dbenv,
- fhp, &type, 1, &nr)) != 0 || nr == 0)
+ if (__os_read(dbenv,
+ fhp, &type, 1, &nr) != 0 || nr == 0)
break;
if (type == P_INVALID || type >= P_PAGETYPE_MAX)
return (guess << 1);
diff --git a/bdb/db/db_vrfyutil.c b/bdb/db/db_vrfyutil.c
index 89dccdcc760..44344ceed11 100644
--- a/bdb/db/db_vrfyutil.c
+++ b/bdb/db/db_vrfyutil.c
@@ -1,16 +1,16 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
+ * Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: db_vrfyutil.c,v 11.11 2000/11/28 21:36:04 bostic Exp $
+ * $Id: db_vrfyutil.c,v 11.29 2002/08/08 03:57:50 bostic Exp $
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_vrfyutil.c,v 11.11 2000/11/28 21:36:04 bostic Exp $";
+static const char revid[] = "$Id: db_vrfyutil.c,v 11.29 2002/08/08 03:57:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,10 +20,11 @@ static const char revid[] = "$Id: db_vrfyutil.c,v 11.11 2000/11/28 21:36:04 bost
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_verify.h"
-#include "db_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_verify.h"
+#include "dbinc/db_am.h"
+static int __db_vrfy_pageinfo_create __P((DB_ENV *, VRFY_PAGEINFO **));
static int __db_vrfy_pgset_iinc __P((DB *, db_pgno_t, int));
/*
@@ -34,7 +35,7 @@ static int __db_vrfy_pgset_iinc __P((DB *, db_pgno_t, int));
* PUBLIC: __P((DB_ENV *, u_int32_t, VRFY_DBINFO **));
*/
int
-__db_vrfy_dbinfo_create (dbenv, pgsize, vdpp)
+__db_vrfy_dbinfo_create(dbenv, pgsize, vdpp)
DB_ENV *dbenv;
u_int32_t pgsize;
VRFY_DBINFO **vdpp;
@@ -53,14 +54,14 @@ __db_vrfy_dbinfo_create (dbenv, pgsize, vdpp)
if ((ret = db_create(&cdbp, dbenv, 0)) != 0)
goto err;
- if ((ret = cdbp->set_flags(cdbp, DB_DUP | DB_DUPSORT)) != 0)
+ if ((ret = cdbp->set_flags(cdbp, DB_DUP)) != 0)
goto err;
if ((ret = cdbp->set_pagesize(cdbp, pgsize)) != 0)
goto err;
if ((ret =
- cdbp->open(cdbp, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
+ cdbp->open(cdbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
goto err;
if ((ret = db_create(&pgdbp, dbenv, 0)) != 0)
@@ -69,8 +70,8 @@ __db_vrfy_dbinfo_create (dbenv, pgsize, vdpp)
if ((ret = pgdbp->set_pagesize(pgdbp, pgsize)) != 0)
goto err;
- if ((ret =
- pgdbp->open(pgdbp, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
+ if ((ret = pgdbp->open(pgdbp,
+ NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
goto err;
if ((ret = __db_vrfy_pgset(dbenv, pgsize, &pgset)) != 0)
@@ -90,7 +91,7 @@ err: if (cdbp != NULL)
if (pgdbp != NULL)
(void)pgdbp->close(pgdbp, 0);
if (vdp != NULL)
- __os_free(vdp, sizeof(VRFY_DBINFO));
+ __os_free(dbenv, vdp);
return (ret);
}
@@ -99,10 +100,11 @@ err: if (cdbp != NULL)
* Destructor for VRFY_DBINFO. Destroys VRFY_PAGEINFOs and deallocates
* structure.
*
- * PUBLIC: int __db_vrfy_dbinfo_destroy __P((VRFY_DBINFO *));
+ * PUBLIC: int __db_vrfy_dbinfo_destroy __P((DB_ENV *, VRFY_DBINFO *));
*/
int
-__db_vrfy_dbinfo_destroy(vdp)
+__db_vrfy_dbinfo_destroy(dbenv, vdp)
+ DB_ENV *dbenv;
VRFY_DBINFO *vdp;
{
VRFY_CHILDINFO *c, *d;
@@ -112,7 +114,7 @@ __db_vrfy_dbinfo_destroy(vdp)
for (c = LIST_FIRST(&vdp->subdbs); c != NULL; c = d) {
d = LIST_NEXT(c, links);
- __os_free(c, 0);
+ __os_free(NULL, c);
}
if ((t_ret = vdp->pgdbp->close(vdp->pgdbp, 0)) != 0)
@@ -126,7 +128,7 @@ __db_vrfy_dbinfo_destroy(vdp)
DB_ASSERT(LIST_FIRST(&vdp->activepips) == NULL);
- __os_free(vdp, sizeof(VRFY_DBINFO));
+ __os_free(dbenv, vdp);
return (ret);
}
@@ -192,7 +194,7 @@ __db_vrfy_getpageinfo(vdp, pgno, pipp)
return (ret);
/* Case 3 */
- if ((ret = __db_vrfy_pageinfo_create(&pip)) != 0)
+ if ((ret = __db_vrfy_pageinfo_create(pgdbp->dbenv, &pip)) != 0)
return (ret);
LIST_INSERT_HEAD(&vdp->activepips, pip, links);
@@ -208,10 +210,12 @@ found: pip->pi_refcount++;
* __db_vrfy_putpageinfo --
* Put back a VRFY_PAGEINFO that we're done with.
*
- * PUBLIC: int __db_vrfy_putpageinfo __P((VRFY_DBINFO *, VRFY_PAGEINFO *));
+ * PUBLIC: int __db_vrfy_putpageinfo __P((DB_ENV *,
+ * PUBLIC: VRFY_DBINFO *, VRFY_PAGEINFO *));
*/
int
-__db_vrfy_putpageinfo(vdp, pip)
+__db_vrfy_putpageinfo(dbenv, vdp, pip)
+ DB_ENV *dbenv;
VRFY_DBINFO *vdp;
VRFY_PAGEINFO *pip;
{
@@ -255,7 +259,7 @@ __db_vrfy_putpageinfo(vdp, pip)
#endif
DB_ASSERT(pip->pi_refcount == 0);
- __os_free(pip, 0);
+ __os_ufree(dbenv, pip);
return (0);
}
@@ -280,7 +284,8 @@ __db_vrfy_pgset(dbenv, pgsize, dbpp)
return (ret);
if ((ret = dbp->set_pagesize(dbp, pgsize)) != 0)
goto err;
- if ((ret = dbp->open(dbp, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) == 0)
+ if ((ret = dbp->open(dbp,
+ NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) == 0)
*dbpp = dbp;
else
err: (void)dbp->close(dbp, 0);
@@ -382,7 +387,7 @@ __db_vrfy_pgset_iinc(dbp, pgno, i)
F_SET(&data, DB_DBT_USERMEM);
if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0) {
- DB_ASSERT(data.size = sizeof(int));
+ DB_ASSERT(data.size == sizeof(int));
memcpy(&val, data.data, sizeof(int));
} else if (ret != DB_NOTFOUND)
return (ret);
@@ -463,8 +468,10 @@ __db_vrfy_childput(vdp, pgno, cip)
db_pgno_t pgno;
VRFY_CHILDINFO *cip;
{
- DBT key, data;
DB *cdbp;
+ DBC *cc;
+ DBT key, data;
+ VRFY_CHILDINFO *oldcip;
int ret;
cdbp = vdp->cdbp;
@@ -474,17 +481,44 @@ __db_vrfy_childput(vdp, pgno, cip)
key.data = &pgno;
key.size = sizeof(db_pgno_t);
+ /*
+ * We want to avoid adding multiple entries for a single child page;
+ * we only need to verify each child once, even if a child (such
+ * as an overflow key) is multiply referenced.
+ *
+ * However, we also need to make sure that when walking the list
+ * of children, we encounter them in the order they're referenced
+ * on a page. (This permits us, for example, to verify the
+ * prev_pgno/next_pgno chain of Btree leaf pages.)
+ *
+ * Check the child database to make sure that this page isn't
+ * already a child of the specified page number. If it's not,
+ * put it at the end of the duplicate set.
+ */
+ if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0)
+ return (ret);
+ for (ret = __db_vrfy_ccset(cc, pgno, &oldcip); ret == 0;
+ ret = __db_vrfy_ccnext(cc, &oldcip))
+ if (oldcip->pgno == cip->pgno) {
+ /*
+ * Found a matching child. Return without
+ * putting it again.
+ */
+ if ((ret = __db_vrfy_ccclose(cc)) != 0)
+ return (ret);
+ return (0);
+ }
+ if (ret != DB_NOTFOUND) {
+ (void)__db_vrfy_ccclose(cc);
+ return (ret);
+ }
+ if ((ret = __db_vrfy_ccclose(cc)) != 0)
+ return (ret);
+
data.data = cip;
data.size = sizeof(VRFY_CHILDINFO);
- /*
- * Don't add duplicate (data) entries for a given child, and accept
- * DB_KEYEXIST as a successful return; we only need to verify
- * each child once, even if a child (such as an overflow key) is
- * multiply referenced.
- */
- ret = cdbp->put(cdbp, NULL, &key, &data, DB_NODUPDATA);
- return (ret == DB_KEYEXIST ? 0 : ret);
+ return (cdbp->put(cdbp, NULL, &key, &data, 0));
}
/*
@@ -568,19 +602,26 @@ __db_vrfy_ccclose(dbc)
/*
* __db_vrfy_pageinfo_create --
* Constructor for VRFY_PAGEINFO; allocates and initializes.
- *
- * PUBLIC: int __db_vrfy_pageinfo_create __P((VRFY_PAGEINFO **));
*/
-int
-__db_vrfy_pageinfo_create(pgipp)
+static int
+__db_vrfy_pageinfo_create(dbenv, pgipp)
+ DB_ENV *dbenv;
VRFY_PAGEINFO **pgipp;
{
VRFY_PAGEINFO *pgip;
int ret;
- if ((ret = __os_calloc(NULL,
- 1, sizeof(VRFY_PAGEINFO), (void **)&pgip)) != 0)
+ /*
+ * pageinfo structs are sometimes allocated here and sometimes
+ * allocated by fetching them from a database with DB_DBT_MALLOC.
+ * There's no easy way for the destructor to tell which was
+ * used, and so we always allocate with __os_umalloc so we can free
+ * with __os_ufree.
+ */
+ if ((ret = __os_umalloc(dbenv,
+ sizeof(VRFY_PAGEINFO), (void **)&pgip)) != 0)
return (ret);
+ memset(pgip, 0, sizeof(VRFY_PAGEINFO));
DB_ASSERT(pgip->pi_refcount == 0);
@@ -607,7 +648,8 @@ __db_salvage_init(vdp)
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0)
goto err;
- if ((ret = dbp->open(dbp, NULL, NULL, DB_BTREE, DB_CREATE, 0)) != 0)
+ if ((ret = dbp->open(dbp,
+ NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0)) != 0)
goto err;
vdp->salvage_pages = dbp;
diff --git a/bdb/db185/db185.c b/bdb/db185/db185.c
index 84327542485..99d37bcf341 100644
--- a/bdb/db185/db185.c
+++ b/bdb/db185/db185.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db185.c,v 11.15 2001/01/23 21:27:03 bostic Exp $";
+ "$Id: db185.c,v 11.28 2002/05/09 01:55:14 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -38,6 +38,15 @@ static int db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
static int db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
static int db185_sync __P((const DB185 *, u_int));
+/*
+ * EXTERN: #ifdef _DB185_INT_H_
+ * EXTERN: DB185 *__db185_open
+ * EXTERN: __P((const char *, int, int, DBTYPE, const void *));
+ * EXTERN: #else
+ * EXTERN: DB *__db185_open
+ * EXTERN: __P((const char *, int, int, DBTYPE, const void *));
+ * EXTERN: #endif
+ */
DB185 *
__db185_open(file, oflags, mode, type, openinfo)
const char *file;
@@ -153,7 +162,7 @@ __db185_open(file, oflags, mode, type, openinfo)
if (oflags & O_CREAT && __os_exists(file, NULL) != 0)
if (__os_openhandle(NULL, file,
oflags, mode, &fh) == 0)
- (void)__os_closehandle(&fh);
+ (void)__os_closehandle(NULL, &fh);
(void)dbp->set_re_source(dbp, file);
if (O_RDONLY)
@@ -220,15 +229,12 @@ __db185_open(file, oflags, mode, type, openinfo)
* to the underlying DB structure, and vice-versa. This has to be
* done BEFORE the DB::open method call because the hash callback
* is exercised as part of hash database initialiation.
- *
- * XXX
- * Overload the cj_internal field for this purpose.
*/
db185p->dbp = dbp;
- dbp->cj_internal = db185p;
+ dbp->api_internal = db185p;
/* Open the database. */
- if ((ret = dbp->open(dbp,
+ if ((ret = dbp->open(dbp, NULL,
file, NULL, type, __db_oflags(oflags), mode)) != 0)
goto err;
@@ -238,10 +244,10 @@ __db185_open(file, oflags, mode, type, openinfo)
return (db185p);
-einval: ret = EINVAL;
-
-err: if (db185p != NULL)
- __os_free(db185p, sizeof(DB185));
+err: if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+einval: ret = EINVAL;
+ if (db185p != NULL)
+ __os_free(NULL, db185p);
if (dbp != NULL)
(void)dbp->close(dbp, 0);
@@ -260,11 +266,13 @@ db185_close(db185p)
ret = dbp->close(dbp, 0);
- __os_free(db185p, sizeof(DB185));
+ __os_free(NULL, db185p);
if (ret == 0)
return (0);
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+ ret = EINVAL;
__os_set_errno(ret);
return (-1);
}
@@ -299,11 +307,10 @@ db185_del(db185p, key185, flags)
return (1);
}
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+einval: ret = EINVAL;
__os_set_errno(ret);
return (-1);
-
-einval: __os_set_errno(EINVAL);
- return (-1);
}
static int
@@ -318,6 +325,8 @@ db185_fd(db185p)
if ((ret = dbp->fd(dbp, &fd)) == 0)
return (fd);
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+ ret = EINVAL;
__os_set_errno(ret);
return (-1);
}
@@ -354,11 +363,10 @@ db185_get(db185p, key185, data185, flags)
return (1);
}
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+einval: ret = EINVAL;
__os_set_errno(ret);
return (-1);
-
-einval: __os_set_errno(EINVAL);
- return (-1);
}
static int
@@ -371,7 +379,7 @@ db185_put(db185p, key185, data185, flags)
DB *dbp;
DBC *dbcp_put;
DBT key, data;
- int ret;
+ int ret, t_ret;
dbp = db185p->dbp;
@@ -394,23 +402,18 @@ db185_put(db185p, key185, data185, flags)
if (dbp->type != DB_RECNO)
goto einval;
- if ((ret = dbp->cursor(dbp, NULL, &dbcp_put, 0)) != 0) {
- __os_set_errno(ret);
- return (-1);
- }
+ if ((ret = dbp->cursor(dbp, NULL, &dbcp_put, 0)) != 0)
+ break;
if ((ret =
- dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) {
- (void)dbcp_put->c_close(dbcp_put);
- __os_set_errno(ret);
- return (-1);
+ dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) == 0) {
+ memset(&data, 0, sizeof(data));
+ data.data = data185->data;
+ data.size = data185->size;
+ ret = dbcp_put->c_put(dbcp_put, &key, &data,
+ flags == R_IAFTER ? DB_AFTER : DB_BEFORE);
}
- memset(&data, 0, sizeof(data));
- data.data = data185->data;
- data.size = data185->size;
- ret = dbcp_put->c_put(dbcp_put,
- &key, &data, flags == R_IAFTER ? DB_AFTER : DB_BEFORE);
- (void)dbcp_put->c_close(dbcp_put);
- __os_set_errno(ret);
+ if ((t_ret = dbcp_put->c_close(dbcp_put)) != 0 && ret == 0)
+ ret = t_ret;
break;
case R_NOOVERWRITE:
ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
@@ -436,10 +439,10 @@ db185_put(db185p, key185, data185, flags)
case DB_KEYEXIST:
return (1);
}
- __os_set_errno(ret);
- return (-1);
-einval: __os_set_errno(EINVAL);
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+einval: ret = EINVAL;
+ __os_set_errno(ret);
return (-1);
}
@@ -496,11 +499,10 @@ db185_seq(db185p, key185, data185, flags)
return (1);
}
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+einval: ret = EINVAL;
__os_set_errno(ret);
return (-1);
-
-einval: __os_set_errno(EINVAL);
- return (-1);
}
static int
@@ -534,11 +536,10 @@ db185_sync(db185p, flags)
if ((ret = dbp->sync(dbp, 0)) == 0)
return (0);
+ if (ret < 0) /* DB 1.85 can't handle DB 2.0's errors. */
+einval: ret = EINVAL;
__os_set_errno(ret);
return (-1);
-
-einval: __os_set_errno(EINVAL);
- return (-1);
}
static void
@@ -564,7 +565,7 @@ db185_compare(dbp, a, b)
DB *dbp;
const DBT *a, *b;
{
- return (((DB185 *)dbp->cj_internal)->compare(a, b));
+ return (((DB185 *)dbp->api_internal)->compare(a, b));
}
/*
@@ -576,7 +577,7 @@ db185_prefix(dbp, a, b)
DB *dbp;
const DBT *a, *b;
{
- return (((DB185 *)dbp->cj_internal)->prefix(a, b));
+ return (((DB185 *)dbp->api_internal)->prefix(a, b));
}
/*
@@ -589,5 +590,5 @@ db185_hash(dbp, key, len)
const void *key;
u_int32_t len;
{
- return (((DB185 *)dbp->cj_internal)->hash(key, (size_t)len));
+ return (((DB185 *)dbp->api_internal)->hash(key, (size_t)len));
}
diff --git a/bdb/db185/db185_int.h b/bdb/db185/db185_int.h
deleted file mode 100644
index 172019d3f00..00000000000
--- a/bdb/db185/db185_int.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: db185_int.h,v 11.7 2001/01/22 22:22:46 krinsky Exp $
- */
-
-#ifndef _DB185_H_
-#define _DB185_H_
-
-/* Routine flags. */
-#define R_CURSOR 1 /* del, put, seq */
-#define __R_UNUSED 2 /* UNUSED */
-#define R_FIRST 3 /* seq */
-#define R_IAFTER 4 /* put (RECNO) */
-#define R_IBEFORE 5 /* put (RECNO) */
-#define R_LAST 6 /* seq (BTREE, RECNO) */
-#define R_NEXT 7 /* seq */
-#define R_NOOVERWRITE 8 /* put */
-#define R_PREV 9 /* seq (BTREE, RECNO) */
-#define R_SETCURSOR 10 /* put (RECNO) */
-#define R_RECNOSYNC 11 /* sync (RECNO) */
-
-typedef struct {
- void *data; /* data */
- size_t size; /* data length */
-} DBT185;
-
-/* Access method description structure. */
-typedef struct __db185 {
- DBTYPE type; /* Underlying db type. */
- int (*close) __P((struct __db185 *));
- int (*del) __P((const struct __db185 *, const DBT185 *, u_int));
- int (*get)
- __P((const struct __db185 *, const DBT185 *, DBT185 *, u_int));
- int (*put)
- __P((const struct __db185 *, DBT185 *, const DBT185 *, u_int));
- int (*seq)
- __P((const struct __db185 *, DBT185 *, DBT185 *, u_int));
- int (*sync) __P((const struct __db185 *, u_int));
- DB *dbp; /* DB structure. Was void *internal. */
- int (*fd) __P((const struct __db185 *));
-
- /*
- * !!!
- * The following elements added to the end of the DB 1.85 DB
- * structure.
- */
- DBC *dbc; /* DB cursor. */
- /* Various callback functions. */
- int (*compare) __P((const DBT *, const DBT *));
- size_t (*prefix) __P((const DBT *, const DBT *));
- u_int32_t (*hash) __P((const void *, size_t));
-} DB185;
-
-/* Structure used to pass parameters to the btree routines. */
-typedef struct {
-#define R_DUP 0x01 /* duplicate keys */
- u_int32_t flags;
- u_int32_t cachesize; /* bytes to cache */
- u_int32_t maxkeypage; /* maximum keys per page */
- u_int32_t minkeypage; /* minimum keys per page */
- u_int32_t psize; /* page size */
- int (*compare) /* comparison function */
- __P((const DBT *, const DBT *));
- size_t (*prefix) /* prefix function */
- __P((const DBT *, const DBT *));
- int lorder; /* byte order */
-} BTREEINFO;
-
-/* Structure used to pass parameters to the hashing routines. */
-typedef struct {
- u_int32_t bsize; /* bucket size */
- u_int32_t ffactor; /* fill factor */
- u_int32_t nelem; /* number of elements */
- u_int32_t cachesize; /* bytes to cache */
- u_int32_t /* hash function */
- (*hash) __P((const void *, size_t));
- int lorder; /* byte order */
-} HASHINFO;
-
-/* Structure used to pass parameters to the record routines. */
-typedef struct {
-#define R_FIXEDLEN 0x01 /* fixed-length records */
-#define R_NOKEY 0x02 /* key not required */
-#define R_SNAPSHOT 0x04 /* snapshot the input */
- u_int32_t flags;
- u_int32_t cachesize; /* bytes to cache */
- u_int32_t psize; /* page size */
- int lorder; /* byte order */
- size_t reclen; /* record length (fixed-length records) */
- u_char bval; /* delimiting byte (variable-length records */
- char *bfname; /* btree file name */
-} RECNOINFO;
-#endif /* !_DB185_H_ */
diff --git a/bdb/db185/db185_int.in b/bdb/db185/db185_int.in
new file mode 100644
index 00000000000..a4a3ce19c17
--- /dev/null
+++ b/bdb/db185/db185_int.in
@@ -0,0 +1,129 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: db185_int.in,v 11.12 2002/01/11 15:51:51 bostic Exp $
+ */
+
+#ifndef _DB185_INT_H_
+#define _DB185_INT_H_
+
+/* Routine flags. */
+#define R_CURSOR 1 /* del, put, seq */
+#define __R_UNUSED 2 /* UNUSED */
+#define R_FIRST 3 /* seq */
+#define R_IAFTER 4 /* put (RECNO) */
+#define R_IBEFORE 5 /* put (RECNO) */
+#define R_LAST 6 /* seq (BTREE, RECNO) */
+#define R_NEXT 7 /* seq */
+#define R_NOOVERWRITE 8 /* put */
+#define R_PREV 9 /* seq (BTREE, RECNO) */
+#define R_SETCURSOR 10 /* put (RECNO) */
+#define R_RECNOSYNC 11 /* sync (RECNO) */
+
+typedef struct {
+ void *data; /* data */
+ size_t size; /* data length */
+} DBT185;
+
+/* Access method description structure. */
+typedef struct __db185 {
+ DBTYPE type; /* Underlying db type. */
+ int (*close) __P((struct __db185 *));
+ int (*del) __P((const struct __db185 *, const DBT185 *, u_int));
+ int (*get)
+ __P((const struct __db185 *, const DBT185 *, DBT185 *, u_int));
+ int (*put)
+ __P((const struct __db185 *, DBT185 *, const DBT185 *, u_int));
+ int (*seq)
+ __P((const struct __db185 *, DBT185 *, DBT185 *, u_int));
+ int (*sync) __P((const struct __db185 *, u_int));
+ DB *dbp; /* DB structure. Was void *internal. */
+ int (*fd) __P((const struct __db185 *));
+
+ /*
+ * !!!
+ * The following elements added to the end of the DB 1.85 DB
+ * structure.
+ */
+ DBC *dbc; /* DB cursor. */
+ /* Various callback functions. */
+ int (*compare) __P((const DBT *, const DBT *));
+ size_t (*prefix) __P((const DBT *, const DBT *));
+ u_int32_t (*hash) __P((const void *, size_t));
+} DB185;
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define R_DUP 0x01 /* duplicate keys */
+ u_int32_t flags;
+ u_int32_t cachesize; /* bytes to cache */
+ u_int32_t maxkeypage; /* maximum keys per page */
+ u_int32_t minkeypage; /* minimum keys per page */
+ u_int32_t psize; /* page size */
+ int (*compare) /* comparison function */
+ __P((const DBT *, const DBT *));
+ size_t (*prefix) /* prefix function */
+ __P((const DBT *, const DBT *));
+ int lorder; /* byte order */
+} BTREEINFO;
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+ u_int32_t bsize; /* bucket size */
+ u_int32_t ffactor; /* fill factor */
+ u_int32_t nelem; /* number of elements */
+ u_int32_t cachesize; /* bytes to cache */
+ u_int32_t /* hash function */
+ (*hash) __P((const void *, size_t));
+ int lorder; /* byte order */
+} HASHINFO;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define R_FIXEDLEN 0x01 /* fixed-length records */
+#define R_NOKEY 0x02 /* key not required */
+#define R_SNAPSHOT 0x04 /* snapshot the input */
+ u_int32_t flags;
+ u_int32_t cachesize; /* bytes to cache */
+ u_int32_t psize; /* page size */
+ int lorder; /* byte order */
+ size_t reclen; /* record length (fixed-length records) */
+ u_char bval; /* delimiting byte (variable-length records */
+ char *bfname; /* btree file name */
+} RECNOINFO;
+#endif /* !_DB185_INT_H_ */
diff --git a/bdb/db_archive/db_archive.c b/bdb/db_archive/db_archive.c
index 7c91e42f390..dc8718e4c03 100644
--- a/bdb/db_archive/db_archive.c
+++ b/bdb/db_archive/db_archive.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,29 +9,25 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_archive.c,v 11.18 2001/01/18 18:36:56 bostic Exp $";
+ "$Id: db_archive.c,v 11.36 2002/03/28 20:13:34 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
-#include "common_ext.h"
-int main __P((int, char *[]));
-void usage __P((void));
-void version_check __P((void));
-
-DB_ENV *dbenv;
-const char
- *progname = "db_archive"; /* Program name. */
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -40,16 +36,19 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ const char *progname = "db_archive";
+ DB_ENV *dbenv;
u_int32_t flags;
int ch, e_close, exitval, ret, verbose;
- char **file, *home, **list;
+ char **file, *home, **list, *passwd;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
flags = 0;
e_close = exitval = verbose = 0;
- home = NULL;
- while ((ch = getopt(argc, argv, "ah:lsVv")) != EOF)
+ home = passwd = NULL;
+ while ((ch = getopt(argc, argv, "ah:lP:sVv")) != EOF)
switch (ch) {
case 'a':
LF_SET(DB_ARCH_ABS);
@@ -60,24 +59,33 @@ main(argc, argv)
case 'l':
LF_SET(DB_ARCH_LOG);
break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ break;
case 's':
LF_SET(DB_ARCH_DATA);
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case 'v':
verbose = 1;
break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -99,6 +107,11 @@ main(argc, argv)
if (verbose)
(void)dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
+ if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ goto shutdown;
+ }
/*
* If attaching to a pre-existing environment fails, create a
* private one and try again.
@@ -112,8 +125,8 @@ main(argc, argv)
}
/* Get the list of names. */
- if ((ret = log_archive(dbenv, &list, flags, NULL)) != 0) {
- dbenv->err(dbenv, ret, "log_archive");
+ if ((ret = dbenv->log_archive(dbenv, &list, flags)) != 0) {
+ dbenv->err(dbenv, ret, "DB_ENV->log_archive");
goto shutdown;
}
@@ -121,7 +134,7 @@ main(argc, argv)
if (list != NULL) {
for (file = list; *file != NULL; ++file)
printf("%s\n", *file);
- __os_free(list, 0);
+ free(list);
}
if (0) {
@@ -136,18 +149,20 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage()
{
- (void)fprintf(stderr, "usage: db_archive [-alsVv] [-h home]\n");
- exit (1);
+ (void)fprintf(stderr,
+ "usage: db_archive [-alsVv] [-h home] [-P password]\n");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -159,6 +174,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_checkpoint/db_checkpoint.c b/bdb/db_checkpoint/db_checkpoint.c
index c7d16e02334..a59572c5f76 100644
--- a/bdb/db_checkpoint/db_checkpoint.c
+++ b/bdb/db_checkpoint/db_checkpoint.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_checkpoint.c,v 11.25 2001/01/18 18:36:57 bostic Exp $";
+ "$Id: db_checkpoint.c,v 11.46 2002/08/08 03:50:31 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -31,25 +31,17 @@ static const char revid[] =
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
-#include "common_ext.h"
-#include "clib_ext.h"
-
-char *check __P((DB_ENV *, long, long));
-int main __P((int, char *[]));
-void usage __P((void));
-void version_check __P((void));
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
-DB_ENV *dbenv;
-const char
- *progname = "db_checkpoint"; /* Program name. */
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -58,13 +50,16 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ DB_ENV *dbenv;
+ const char *progname = "db_checkpoint";
time_t now;
long argval;
u_int32_t flags, kbytes, minutes, seconds;
int ch, e_close, exitval, once, ret, verbose;
- char *home, *logfile;
+ char *home, *logfile, *passwd;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
/*
* !!!
@@ -76,8 +71,8 @@ main(argc, argv)
kbytes = minutes = 0;
e_close = exitval = once = verbose = 0;
flags = 0;
- home = logfile = NULL;
- while ((ch = getopt(argc, argv, "1h:k:L:p:Vv")) != EOF)
+ home = logfile = passwd = NULL;
+ while ((ch = getopt(argc, argv, "1h:k:L:P:p:Vv")) != EOF)
switch (ch) {
case '1':
once = 1;
@@ -87,40 +82,50 @@ main(argc, argv)
home = optarg;
break;
case 'k':
- (void)__db_getlong(NULL, progname,
- optarg, 1, (long)MAX_UINT32_T, &argval);
+ if (__db_getlong(NULL, progname,
+ optarg, 1, (long)MAX_UINT32_T, &argval))
+ return (EXIT_FAILURE);
kbytes = argval;
break;
case 'L':
logfile = optarg;
break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ break;
case 'p':
- (void)__db_getlong(NULL, progname,
- optarg, 1, (long)MAX_UINT32_T, &argval);
+ if (__db_getlong(NULL, progname,
+ optarg, 1, (long)MAX_UINT32_T, &argval))
+ return (EXIT_FAILURE);
minutes = argval;
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case 'v':
verbose = 1;
break;
case '?':
default:
- usage();
- goto shutdown;
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
- usage();
+ return (usage());
if (once == 0 && kbytes == 0 && minutes == 0) {
(void)fprintf(stderr,
"%s: at least one of -1, -k and -p must be specified\n",
progname);
- exit (1);
+ return (EXIT_FAILURE);
}
/* Handle possible interruptions. */
@@ -144,6 +149,11 @@ main(argc, argv)
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
+ if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ goto shutdown;
+ }
/* Initialize the environment. */
if ((ret = dbenv->open(dbenv,
home, DB_JOINENV | DB_USE_ENVIRON, 0)) != 0) {
@@ -152,10 +162,10 @@ main(argc, argv)
}
/* Register the standard pgin/pgout functions, in case we do I/O. */
- if ((ret =
- memp_register(dbenv, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0) {
+ if ((ret = dbenv->memp_register(
+ dbenv, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0) {
dbenv->err(dbenv, ret,
- "failed to register access method functions");
+ "DB_ENV->memp_register: failed to register access method functions");
goto shutdown;
}
@@ -171,15 +181,8 @@ main(argc, argv)
dbenv->errx(dbenv, "checkpoint: %s", ctime(&now));
}
- ret = txn_checkpoint(dbenv, kbytes, minutes, flags);
- while (ret == DB_INCOMPLETE) {
- if (verbose)
- dbenv->errx(dbenv,
- "checkpoint did not finish, retrying\n");
- (void)__os_sleep(dbenv, 2, 0);
- ret = txn_checkpoint(dbenv, 0, 0, flags);
- }
- if (ret != 0) {
+ if ((ret = dbenv->txn_checkpoint(dbenv,
+ kbytes, minutes, flags)) != 0) {
dbenv->err(dbenv, ret, "txn_checkpoint");
goto shutdown;
}
@@ -208,19 +211,21 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage()
{
- (void)fprintf(stderr,
- "usage: db_checkpoint [-1Vv] [-h home] [-k kbytes] [-L file] [-p min]\n");
- exit(1);
+ (void)fprintf(stderr, "%s\n\t%s\n",
+ "usage: db_checkpoint [-1Vv]",
+ "[-h home] [-k kbytes] [-L file] [-P password] [-p min]");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -232,6 +237,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_deadlock/db_deadlock.c b/bdb/db_deadlock/db_deadlock.c
index ac151db127a..523918b9ea4 100644
--- a/bdb/db_deadlock/db_deadlock.c
+++ b/bdb/db_deadlock/db_deadlock.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_deadlock.c,v 11.19 2001/01/18 18:36:57 bostic Exp $";
+ "$Id: db_deadlock.c,v 11.38 2002/08/08 03:50:32 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -31,19 +31,15 @@ static const char revid[] =
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
-#include "clib_ext.h"
-int main __P((int, char *[]));
-void usage __P((void));
-void version_check __P((void));
-
-DB_ENV *dbenv;
-const char
- *progname = "db_deadlock"; /* Program name. */
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -52,36 +48,49 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ const char *progname = "db_deadlock";
+ DB_ENV *dbenv;
u_int32_t atype;
time_t now;
- long usecs;
- u_int32_t flags;
+ long secs, usecs;
int ch, e_close, exitval, ret, verbose;
- char *home, *logfile;
+ char *home, *logfile, *str;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
atype = DB_LOCK_DEFAULT;
home = logfile = NULL;
- usecs = 0;
- flags = 0;
+ secs = usecs = 0;
e_close = exitval = verbose = 0;
while ((ch = getopt(argc, argv, "a:h:L:t:Vvw")) != EOF)
switch (ch) {
case 'a':
switch (optarg[0]) {
+ case 'e':
+ atype = DB_LOCK_EXPIRE;
+ break;
+ case 'm':
+ atype = DB_LOCK_MAXLOCKS;
+ break;
+ case 'n':
+ atype = DB_LOCK_MINLOCKS;
+ break;
case 'o':
atype = DB_LOCK_OLDEST;
break;
+ case 'w':
+ atype = DB_LOCK_MINWRITE;
+ break;
case 'y':
atype = DB_LOCK_YOUNGEST;
break;
default:
- usage();
+ return (usage());
/* NOTREACHED */
}
if (optarg[1] != '\0')
- usage();
+ return (usage());
break;
case 'h':
home = optarg;
@@ -90,42 +99,40 @@ main(argc, argv)
logfile = optarg;
break;
case 't':
- (void)__db_getlong(NULL,
- progname, optarg, 1, LONG_MAX, &usecs);
- usecs *= 1000000;
+ if ((str = strchr(optarg, '.')) != NULL) {
+ *str++ = '\0';
+ if (*str != '\0' && __db_getlong(
+ NULL, progname, str, 0, LONG_MAX, &usecs))
+ return (EXIT_FAILURE);
+ }
+ if (*optarg != '\0' && __db_getlong(
+ NULL, progname, optarg, 0, LONG_MAX, &secs))
+ return (EXIT_FAILURE);
+ if (secs == 0 && usecs == 0)
+ return (usage());
+
break;
+
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case 'v':
verbose = 1;
break;
- case 'w':
- LF_SET(DB_LOCK_CONFLICT);
+ case 'w': /* Undocumented. */
+ /* Detect every 100ms (100000 us) when polling. */
+ secs = 0;
+ usecs = 100000;
break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
- usage();
-
- if (usecs == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) {
- fprintf(stderr,
- "%s: at least one of -t and -w must be specified\n",
- progname);
- exit(1);
- }
-
- /*
- * We detect every 100ms (100000 us) when we're running in
- * DB_LOCK_CONFLICT mode.
- */
- if (usecs == 0)
- usecs = 100000;
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -166,13 +173,15 @@ main(argc, argv)
dbenv->errx(dbenv, "running at %.24s", ctime(&now));
}
- if ((ret = lock_detect(dbenv, flags, atype, NULL)) != 0) {
- dbenv->err(dbenv, ret, "lock_detect");
+ if ((ret = dbenv->lock_detect(dbenv, 0, atype, NULL)) != 0) {
+ dbenv->err(dbenv, ret, "DB_ENV->lock_detect");
goto shutdown;
}
- /* Make a pass every "usecs" usecs. */
- (void)__os_sleep(dbenv, 0, usecs);
+ /* Make a pass every "secs" secs and "usecs" usecs. */
+ if (secs == 0 && usecs == 0)
+ break;
+ (void)__os_sleep(dbenv, secs, usecs);
}
if (0) {
@@ -193,19 +202,21 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage()
{
- (void)fprintf(stderr,
- "usage: db_deadlock [-Vvw] [-a o | y] [-h home] [-L file] [-t sec]\n");
- exit(1);
+ (void)fprintf(stderr, "%s\n\t%s\n",
+ "usage: db_deadlock [-Vv]",
+ "[-a e | m | n | o | w | y] [-h home] [-L file] [-t sec.usec]");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -217,6 +228,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_dump/db_dump.c b/bdb/db_dump/db_dump.c
index ba24dd6cc09..143884a3fa8 100644
--- a/bdb/db_dump/db_dump.c
+++ b/bdb/db_dump/db_dump.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_dump.c,v 11.41 2001/01/18 18:36:57 bostic Exp $";
+ "$Id: db_dump.c,v 11.80 2002/08/08 03:50:34 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -24,25 +24,17 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "hash.h"
-#include "lock.h"
-
-void configure __P((char *));
-int db_init __P((char *));
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+
+int db_init __P((DB_ENV *, char *, int, u_int32_t, int *));
int dump __P((DB *, int, int));
-int dump_sub __P((DB *, char *, int, int));
+int dump_sub __P((DB_ENV *, DB *, char *, int, int));
int is_sub __P((DB *, int *));
int main __P((int, char *[]));
int show_subs __P((DB *));
-void usage __P((void));
-void version_check __P((void));
-
-DB_ENV *dbenv;
-const char
- *progname = "db_dump"; /* Program name. */
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -51,19 +43,25 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ const char *progname = "db_dump";
+ DB_ENV *dbenv;
DB *dbp;
+ u_int32_t cache;
int ch, d_close;
- int e_close, exitval;
- int lflag, nflag, pflag, ret, rflag, Rflag, subs, keyflag;
- char *dopt, *home, *subname;
+ int e_close, exitval, keyflag, lflag, nflag, pflag, private;
+ int ret, Rflag, rflag, resize, subs;
+ char *dopt, *home, *passwd, *subname;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
dbp = NULL;
d_close = e_close = exitval = lflag = nflag = pflag = rflag = Rflag = 0;
keyflag = 0;
- dopt = home = subname = NULL;
- while ((ch = getopt(argc, argv, "d:f:h:klNprRs:V")) != EOF)
+ cache = MEGABYTE;
+ private = 0;
+ dopt = home = passwd = subname = NULL;
+ while ((ch = getopt(argc, argv, "d:f:h:klNpP:rRs:V")) != EOF)
switch (ch) {
case 'd':
dopt = optarg;
@@ -72,7 +70,7 @@ main(argc, argv)
if (freopen(optarg, "w", stdout) == NULL) {
fprintf(stderr, "%s: %s: reopen: %s\n",
progname, optarg, strerror(errno));
- exit (1);
+ return (EXIT_FAILURE);
}
break;
case 'h':
@@ -86,11 +84,14 @@ main(argc, argv)
break;
case 'N':
nflag = 1;
- if ((ret = db_env_set_panicstate(0)) != 0) {
- fprintf(stderr,
- "%s: db_env_set_panicstate: %s\n",
- progname, db_strerror(ret));
- return (1);
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
case 'p':
@@ -108,42 +109,42 @@ main(argc, argv)
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 1)
- usage();
+ return (usage());
if (dopt != NULL && pflag) {
fprintf(stderr,
"%s: the -d and -p options may not both be specified\n",
progname);
- exit (1);
+ return (EXIT_FAILURE);
}
if (lflag && subname != NULL) {
fprintf(stderr,
"%s: the -l and -s options may not both be specified\n",
progname);
- exit (1);
+ return (EXIT_FAILURE);
}
if (keyflag && rflag) {
fprintf(stderr, "%s: %s",
"the -k and -r or -R options may not both be specified\n",
progname);
- exit(1);
+ return (EXIT_FAILURE);
}
if (subname != NULL && rflag) {
fprintf(stderr, "%s: %s",
"the -s and -r or R options may not both be specified\n",
progname);
- exit(1);
+ return (EXIT_FAILURE);
}
/* Handle possible interruptions. */
@@ -153,7 +154,7 @@ main(argc, argv)
* Create an environment object and initialize it for error
* reporting.
*/
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
+retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
goto err;
@@ -162,14 +163,24 @@ main(argc, argv)
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
-
- if (nflag && (ret = dbenv->set_mutexlocks(dbenv, 0)) != 0) {
- dbenv->err(dbenv, ret, "set_mutexlocks");
+ if (nflag) {
+ if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
+ goto err;
+ }
+ if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
+ goto err;
+ }
+ }
+ if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
goto err;
}
/* Initialize the environment. */
- if (db_init(home) != 0)
+ if (db_init(dbenv, home, rflag, cache, &private) != 0)
goto err;
/* Create the DB object and open the file. */
@@ -185,17 +196,31 @@ main(argc, argv)
*/
if (rflag) {
if ((ret = dbp->verify(dbp, argv[0], NULL, stdout,
- DB_SALVAGE | (Rflag ? DB_AGGRESSIVE : 0))) != 0)
+ DB_SALVAGE |
+ (Rflag ? DB_AGGRESSIVE : 0) |
+ (pflag ? DB_PRINTABLE : 0))) != 0)
goto err;
exitval = 0;
goto done;
}
- if ((ret = dbp->open(dbp,
+ if ((ret = dbp->open(dbp, NULL,
argv[0], subname, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
dbp->err(dbp, ret, "open: %s", argv[0]);
goto err;
}
+ if (private != 0) {
+ if ((ret = __db_util_cache(dbenv, dbp, &cache, &resize)) != 0)
+ goto err;
+ if (resize) {
+ (void)dbp->close(dbp, 0);
+ d_close = 0;
+
+ (void)dbenv->close(dbenv, 0);
+ e_close = 0;
+ goto retry;
+ }
+ }
if (dopt != NULL) {
if (__db_dump(dbp, dopt, NULL)) {
@@ -217,7 +242,7 @@ main(argc, argv)
if (subname == NULL && is_sub(dbp, &subs))
goto err;
if (subs) {
- if (dump_sub(dbp, argv[0], pflag, keyflag))
+ if (dump_sub(dbenv, dbp, argv[0], pflag, keyflag))
goto err;
} else
if (__db_prheader(dbp, NULL, pflag, keyflag, stdout,
@@ -231,7 +256,7 @@ err: exitval = 1;
}
done: if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
exitval = 1;
- dbp->err(dbp, ret, "close");
+ dbenv->err(dbenv, ret, "close");
}
if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
@@ -242,7 +267,7 @@ done: if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
/*
@@ -250,24 +275,36 @@ done: if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
* Initialize the environment.
*/
int
-db_init(home)
+db_init(dbenv, home, is_salvage, cache, is_privatep)
+ DB_ENV *dbenv;
char *home;
+ int is_salvage;
+ u_int32_t cache;
+ int *is_privatep;
{
int ret;
/*
- * Try and use the underlying environment when opening a database. We
- * wish to use the buffer pool so our information is as up-to-date as
- * possible, even if the mpool cache hasn't been flushed; we wish to
- * use the locking system, if present, so that we are safe to use with
- * transactions. (We don't need to use transactions explicitly, as
- * we're read-only.)
+ * Try and use the underlying environment when opening a database.
+ * We wish to use the buffer pool so our information is as up-to-date
+ * as possible, even if the mpool cache hasn't been flushed.
*
- * Note that in CDB, too, this will configure our environment
+ * If we are not doing a salvage, we wish to use the DB_JOINENV flag;
+ * if a locking system is present, this will let us use it and be
+ * safe to run concurrently with other threads of control. (We never
+ * need to use transactions explicitly, as we're read-only.) Note
+ * that in CDB, too, this will configure our environment
* appropriately, and our cursors will (correctly) do locking as CDB
* read cursors.
+ *
+ * If we are doing a salvage, the verification code will protest
+ * if we initialize transactions, logging, or locking; do an
+ * explicit DB_INIT_MPOOL to try to join any existing environment
+ * before we create our own.
*/
- if (dbenv->open(dbenv, home, DB_JOINENV | DB_USE_ENVIRON, 0) == 0)
+ *is_privatep = 0;
+ if (dbenv->open(dbenv, home,
+ DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : DB_JOINENV), 0) == 0)
return (0);
/*
@@ -280,7 +317,9 @@ db_init(home)
* an mpool region exists). Create one, but make it private so that
* no files are actually created.
*/
- if ((ret = dbenv->open(dbenv, home,
+ *is_privatep = 1;
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 &&
+ (ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0)
return (0);
@@ -305,18 +344,20 @@ is_sub(dbp, yesno)
switch (dbp->type) {
case DB_BTREE:
case DB_RECNO:
- if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &btsp, DB_FAST_STAT)) != 0) {
dbp->err(dbp, ret, "DB->stat");
return (ret);
}
*yesno = btsp->bt_metaflags & BTM_SUBDB ? 1 : 0;
+ free(btsp);
break;
case DB_HASH:
- if ((ret = dbp->stat(dbp, &hsp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &hsp, DB_FAST_STAT)) != 0) {
dbp->err(dbp, ret, "DB->stat");
return (ret);
}
*yesno = hsp->hash_metaflags & DB_HASH_SUBDB ? 1 : 0;
+ free(hsp);
break;
case DB_QUEUE:
break;
@@ -332,7 +373,8 @@ is_sub(dbp, yesno)
* Dump out the records for a DB containing subdatabases.
*/
int
-dump_sub(parent_dbp, parent_name, pflag, keyflag)
+dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
+ DB_ENV *dbenv;
DB *parent_dbp;
char *parent_name;
int pflag, keyflag;
@@ -369,7 +411,7 @@ dump_sub(parent_dbp, parent_name, pflag, keyflag)
free(subdb);
return (1);
}
- if ((ret = dbp->open(dbp,
+ if ((ret = dbp->open(dbp, NULL,
parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0)
dbp->err(dbp, ret,
"DB->open: %s:%s", parent_name, subdb);
@@ -449,7 +491,10 @@ dump(dbp, pflag, keyflag)
{
DBC *dbcp;
DBT key, data;
- int ret, is_recno;
+ DBT keyret, dataret;
+ db_recno_t recno;
+ int is_recno, failed, ret;
+ void *pointer;
/*
* Get a cursor and step through the database, printing out each
@@ -460,47 +505,95 @@ dump(dbp, pflag, keyflag)
return (1);
}
+ failed = 0;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
+ data.data = malloc(1024 * 1024);
+ if (data.data == NULL) {
+ dbp->err(dbp, ENOMEM, "bulk get buffer");
+ failed = 1;
+ goto err;
+ }
+ data.ulen = 1024 * 1024;
+ data.flags = DB_DBT_USERMEM;
is_recno = (dbp->type == DB_RECNO || dbp->type == DB_QUEUE);
keyflag = is_recno ? keyflag : 1;
- while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
- if ((keyflag && (ret = __db_prdbt(&key,
- pflag, " ", stdout, __db_verify_callback,
- is_recno, NULL)) != 0) || (ret =
- __db_prdbt(&data, pflag, " ", stdout,
- __db_verify_callback, 0, NULL)) != 0) {
- dbp->errx(dbp, NULL);
- return (1);
+ if (is_recno) {
+ keyret.data = &recno;
+ keyret.size = sizeof(recno);
+ }
+
+retry:
+ while ((ret =
+ dbcp->c_get(dbcp, &key, &data, DB_NEXT | DB_MULTIPLE_KEY)) == 0) {
+ DB_MULTIPLE_INIT(pointer, &data);
+ for (;;) {
+ if (is_recno)
+ DB_MULTIPLE_RECNO_NEXT(pointer, &data,
+ recno, dataret.data, dataret.size);
+ else
+ DB_MULTIPLE_KEY_NEXT(pointer,
+ &data, keyret.data,
+ keyret.size, dataret.data, dataret.size);
+
+ if (dataret.data == NULL)
+ break;
+
+ if ((keyflag && (ret = __db_prdbt(&keyret,
+ pflag, " ", stdout, __db_verify_callback,
+ is_recno, NULL)) != 0) || (ret =
+ __db_prdbt(&dataret, pflag, " ", stdout,
+ __db_verify_callback, 0, NULL)) != 0) {
+ dbp->errx(dbp, NULL);
+ failed = 1;
+ goto err;
+ }
}
+ }
+ if (ret == ENOMEM) {
+ data.data = realloc(data.data, data.size);
+ if (data.data == NULL) {
+ dbp->err(dbp, ENOMEM, "bulk get buffer");
+ failed = 1;
+ goto err;
+ }
+ data.ulen = data.size;
+ goto retry;
+ }
+
if (ret != DB_NOTFOUND) {
dbp->err(dbp, ret, "DBcursor->get");
- return (1);
+ failed = 1;
}
+err: if (data.data != NULL)
+ free(data.data);
+
if ((ret = dbcp->c_close(dbcp)) != 0) {
dbp->err(dbp, ret, "DBcursor->close");
- return (1);
+ failed = 1;
}
(void)__db_prfooter(stdout, __db_verify_callback);
- return (0);
+ return (failed);
}
/*
* usage --
* Display the usage message.
*/
-void
+int
usage()
{
- (void)fprintf(stderr, "usage: %s\n",
-"db_dump [-klNprRV] [-d ahr] [-f output] [-h home] [-s database] db_file");
- exit(1);
+ (void)fprintf(stderr, "%s\n\t%s\n",
+ "usage: db_dump [-klNprRV]",
+ "[-d ahr] [-f output] [-h home] [-P password] [-s database] db_file");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -512,6 +605,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_dump185/db_dump185.c b/bdb/db_dump185/db_dump185.c
index 4b57fffd2dc..97164f34a9a 100644
--- a/bdb/db_dump185/db_dump185.c
+++ b/bdb/db_dump185/db_dump185.c
@@ -1,15 +1,15 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#ifndef lint
static char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static char revid[] =
- "$Id: db_dump185.c,v 11.8 2001/01/10 17:26:21 bostic Exp $";
+ "$Id: db_dump185.c,v 11.17 2002/08/08 03:50:35 bostic Exp $";
#endif
#include <sys/types.h>
@@ -65,9 +65,11 @@ typedef struct hashhdr186 { /* Disk resident portion */
int32_t h_charkey; /* value of hash(CHARKEY) */
#define NCACHED 32 /* number of bit maps and spare points */
int32_t spares[NCACHED];/* spare pages for overflow */
- u_int16_t bitmaps[NCACHED]; /* address of overflow page bitmaps */
+ /* address of overflow page bitmaps */
+ u_int16_t bitmaps[NCACHED];
} HASHHDR186;
typedef struct htab186 { /* Memory resident data structure */
+ void *unused[2];
HASHHDR186 hdr; /* Header */
} HTAB186;
@@ -171,7 +173,7 @@ void db_hash __P((DB *, int));
void dbt_dump __P((DBT *));
void dbt_print __P((DBT *));
int main __P((int, char *[]));
-void usage __P((void));
+int usage __P((void));
int
main(argc, argv)
@@ -191,7 +193,7 @@ main(argc, argv)
if (freopen(optarg, "w", stdout) == NULL) {
fprintf(stderr, "db_dump185: %s: %s\n",
optarg, strerror(errno));
- exit (1);
+ return (EXIT_FAILURE);
}
break;
case 'p':
@@ -199,20 +201,20 @@ main(argc, argv)
break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 1)
- usage();
+ return (usage());
if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_BTREE, NULL)) == NULL) {
if ((dbp =
dbopen(argv[0], O_RDONLY, 0, DB_HASH, NULL)) == NULL) {
fprintf(stderr,
"db_dump185: %s: %s\n", argv[0], strerror(errno));
- exit (1);
+ return (EXIT_FAILURE);
}
db_hash(dbp, pflag);
} else
@@ -236,9 +238,9 @@ main(argc, argv)
if (rval == -1) {
fprintf(stderr, "db_dump185: seq: %s\n", strerror(errno));
- exit (1);
+ return (EXIT_FAILURE);
}
- return (0);
+ return (EXIT_SUCCESS);
}
/*
@@ -345,9 +347,9 @@ dbt_print(dbtp)
* usage --
* Display the usage message.
*/
-void
+int
usage()
{
(void)fprintf(stderr, "usage: db_dump185 [-p] [-f file] db_file\n");
- exit(1);
+ return (EXIT_FAILURE);
}
diff --git a/bdb/db_load/db_load.c b/bdb/db_load/db_load.c
index 33e2eb5e02b..d27fca04ec0 100644
--- a/bdb/db_load/db_load.c
+++ b/bdb/db_load/db_load.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_load.c,v 11.33 2001/01/22 17:25:07 krinsky Exp $";
+ "$Id: db_load.c,v 11.71 2002/08/08 03:50:36 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -25,33 +25,45 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "clib_ext.h"
-
-void badend __P((void));
-void badnum __P((void));
-int configure __P((DB *, char **, char **, int *));
-int db_init __P((char *));
-int dbt_rdump __P((DBT *));
-int dbt_rprint __P((DBT *));
-int dbt_rrecno __P((DBT *, int));
-int digitize __P((int, int *));
-int load __P((char *, DBTYPE, char **, int, u_int32_t));
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+
+typedef struct { /* XXX: Globals. */
+ const char *progname; /* Program name. */
+ char *hdrbuf; /* Input file header. */
+ u_long lineno; /* Input file line number. */
+ u_long origline; /* Original file line number. */
+ int endodata; /* Reached the end of a database. */
+ int endofile; /* Reached the end of the input. */
+ int version; /* Input version. */
+ char *home; /* Env home. */
+ char *passwd; /* Env passwd. */
+ int private; /* Private env. */
+ u_int32_t cache; /* Env cache size. */
+} LDG;
+
+void badend __P((DB_ENV *));
+void badnum __P((DB_ENV *));
+int configure __P((DB_ENV *, DB *, char **, char **, int *));
+int convprintable __P((DB_ENV *, char *, char **));
+int db_init __P((DB_ENV *, char *, u_int32_t, int *));
+int dbt_rdump __P((DB_ENV *, DBT *));
+int dbt_rprint __P((DB_ENV *, DBT *));
+int dbt_rrecno __P((DB_ENV *, DBT *, int));
+int digitize __P((DB_ENV *, int, int *));
+int env_create __P((DB_ENV **, LDG *));
+int load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));
int main __P((int, char *[]));
-int rheader __P((DB *, DBTYPE *, char **, int *, int *));
-void usage __P((void));
-void version_check __P((void));
+int rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *));
+int usage __P((void));
+int version_check __P((const char *));
-int endodata; /* Reached the end of a database. */
-int endofile; /* Reached the end of the input. */
-int existed; /* Tried to load existing key. */
-u_long lineno; /* Input file line number. */
-int version = 1; /* Input version. */
+#define G(f) ((LDG *)dbenv->app_private)->f
-DB_ENV *dbenv;
-const char
- *progname = "db_load"; /* Program name. */
+ /* Flags to the load function. */
+#define LDF_NOHEADER 0x01 /* No dump header. */
+#define LDF_NOOVERWRITE 0x02 /* Don't overwrite existing rows. */
+#define LDF_PASSWORD 0x04 /* Encrypt created databases. */
int
main(argc, argv)
@@ -61,24 +73,35 @@ main(argc, argv)
extern char *optarg;
extern int optind;
DBTYPE dbtype;
- u_int32_t db_nooverwrite;
- int ch, exitval, no_header, ret;
- char **clist, **clp, *home;
-
- version_check();
-
- home = NULL;
- db_nooverwrite = 0;
- exitval = no_header = 0;
+ DB_ENV *dbenv;
+ LDG ldg;
+ u_int32_t ldf;
+ int ch, existed, exitval, ret;
+ char **clist, **clp;
+
+ ldg.progname = "db_load";
+ ldg.lineno = 0;
+ ldg.endodata = ldg.endofile = 0;
+ ldg.version = 1;
+ ldg.cache = MEGABYTE;
+ ldg.hdrbuf = NULL;
+ ldg.home = NULL;
+ ldg.passwd = NULL;
+
+ if ((ret = version_check(ldg.progname)) != 0)
+ return (ret);
+
+ ldf = 0;
+ exitval = 0;
dbtype = DB_UNKNOWN;
/* Allocate enough room for configuration arguments. */
if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) {
- fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
- exit(1);
+ fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM));
+ return (EXIT_FAILURE);
}
- while ((ch = getopt(argc, argv, "c:f:h:nTt:V")) != EOF)
+ while ((ch = getopt(argc, argv, "c:f:h:nP:Tt:V")) != EOF)
switch (ch) {
case 'c':
*clp++ = optarg;
@@ -86,18 +109,28 @@ main(argc, argv)
case 'f':
if (freopen(optarg, "r", stdin) == NULL) {
fprintf(stderr, "%s: %s: reopen: %s\n",
- progname, optarg, strerror(errno));
- exit(1);
+ ldg.progname, optarg, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
case 'h':
- home = optarg;
+ ldg.home = optarg;
break;
case 'n':
- db_nooverwrite = DB_NOOVERWRITE;
+ ldf |= LDF_NOOVERWRITE;
+ break;
+ case 'P':
+ ldg.passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (ldg.passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ ldg.progname, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ ldf |= LDF_PASSWORD;
break;
case 'T':
- no_header = 1;
+ ldf |= LDF_NOHEADER;
break;
case 't':
if (strcmp(optarg, "btree") == 0) {
@@ -116,21 +149,19 @@ main(argc, argv)
dbtype = DB_QUEUE;
break;
}
- usage();
- /* NOTREACHED */
+ return (usage());
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case '?':
default:
- usage();
- /* NOTREACHED */
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 1)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -139,19 +170,12 @@ main(argc, argv)
* Create an environment object initialized for error reporting, and
* then open it.
*/
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
- fprintf(stderr,
- "%s: db_env_create: %s\n", progname, db_strerror(ret));
- goto shutdown;
- }
- dbenv->set_errfile(dbenv, stderr);
- dbenv->set_errpfx(dbenv, progname);
- if (db_init(home) != 0)
+ if (env_create(&dbenv, &ldg) != 0)
goto shutdown;
- while (!endofile)
- if (load(argv[0],
- dbtype, clist, no_header, db_nooverwrite) != 0)
+ while (!ldg.endofile)
+ if (load(dbenv, argv[0], dbtype, clist, ldf,
+ &ldg, &existed) != 0)
goto shutdown;
if (0) {
@@ -160,13 +184,20 @@ shutdown: exitval = 1;
if ((ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
fprintf(stderr,
- "%s: dbenv->close: %s\n", progname, db_strerror(ret));
+ "%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret));
}
/* Resend any caught signal. */
__db_util_sigresend();
+ free(clist);
- /* Return 0 on success, 1 if keys existed already, and 2 on failure. */
+ /*
+ * Return 0 on success, 1 if keys existed already, and 2 on failure.
+ *
+ * Technically, this is wrong, because exit of anything other than
+ * 0 is implementation-defined by the ANSI C standard. I don't see
+ * any good solutions that don't involve API changes.
+ */
return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);
}
@@ -175,32 +206,39 @@ shutdown: exitval = 1;
* Load a database.
*/
int
-load(name, argtype, clist, no_header, db_nooverwrite)
+load(dbenv, name, argtype, clist, flags, ldg, existedp)
+ DB_ENV *dbenv;
char *name, **clist;
DBTYPE argtype;
- int no_header;
- u_int32_t db_nooverwrite;
+ u_int flags;
+ LDG *ldg;
+ int *existedp;
{
DB *dbp;
DBT key, rkey, data, *readp, *writep;
DBTYPE dbtype;
DB_TXN *ctxn, *txn;
db_recno_t recno, datarecno;
- int checkprint, hexkeys, keys, ret, rval;
- int keyflag, ascii_recno;
+ u_int32_t put_flags;
+ int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;
char *subdb;
- endodata = 0;
+ *existedp = 0;
+
+ put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;
+ G(endodata) = 0;
+
subdb = NULL;
ctxn = txn = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&rkey, 0, sizeof(DBT));
+retry_db:
/* Create the DB object. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
- return (1);
+ goto err;
}
dbtype = DB_UNKNOWN;
@@ -208,13 +246,14 @@ load(name, argtype, clist, no_header, db_nooverwrite)
hexkeys = -1;
keyflag = -1;
/* Read the header -- if there's no header, we expect flat text. */
- if (no_header) {
+ if (LF_ISSET(LDF_NOHEADER)) {
checkprint = 1;
dbtype = argtype;
} else {
- if (rheader(dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
+ if (rheader(dbenv,
+ dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
goto err;
- if (endofile)
+ if (G(endofile))
goto done;
}
@@ -223,7 +262,7 @@ load(name, argtype, clist, no_header, db_nooverwrite)
* configuration changes to all databases that are loaded, e.g., all
* subdatabases.)
*/
- if (configure(dbp, clist, &subdb, &keyflag))
+ if (configure(dbenv, dbp, clist, &subdb, &keyflag))
goto err;
if (keys != 1) {
@@ -250,8 +289,8 @@ load(name, argtype, clist, no_header, db_nooverwrite)
if (argtype != DB_UNKNOWN) {
if (dbtype == DB_RECNO || dbtype == DB_QUEUE)
- if (keyflag != 1 && argtype != DB_RECNO
- && argtype != DB_QUEUE) {
+ if (keyflag != 1 && argtype != DB_RECNO &&
+ argtype != DB_QUEUE) {
dbenv->errx(dbenv,
"improper database type conversion specified");
goto err;
@@ -267,27 +306,48 @@ load(name, argtype, clist, no_header, db_nooverwrite)
if (keyflag == -1)
keyflag = 0;
- /*
+ /*
* Recno keys have only been printed in hexadecimal starting
- * with db_dump format version 3 (DB 3.2).
+ * with db_dump format version 3 (DB 3.2).
*
- * !!!
- * Note that version is set in rheader(), which must be called before
+ * !!!
+ * Note that version is set in rheader(), which must be called before
* this assignment.
*/
- hexkeys = (version >= 3 && keyflag == 1 && checkprint == 0);
+ hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0);
if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))
ascii_recno = 1;
else
ascii_recno = 0;
+ /* If configured with a password, encrypt databases we create. */
+ if (LF_ISSET(LDF_PASSWORD) &&
+ (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
+ dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
+ goto err;
+ }
+
/* Open the DB file. */
- if ((ret = dbp->open(dbp,
- name, subdb, dbtype, DB_CREATE, __db_omode("rwrwrw"))) != 0) {
+ if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,
+ DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),
+ __db_omode("rwrwrw"))) != 0) {
dbp->err(dbp, ret, "DB->open: %s", name);
goto err;
}
+ if (ldg->private != 0) {
+ if ((ret =
+ __db_util_cache(dbenv, dbp, &ldg->cache, &resize)) != 0)
+ goto err;
+ if (resize) {
+ dbp->close(dbp, 0);
+ dbp = NULL;
+ dbenv->close(dbenv, 0);
+ if ((ret = env_create(&dbenv, ldg)) != 0)
+ goto err;
+ goto retry_db;
+ }
+ }
/* Initialize the key/data pair. */
readp = &key;
@@ -314,39 +374,40 @@ key_data: if ((readp->data =
goto err;
}
- if (TXN_ON(dbenv) && (ret = txn_begin(dbenv, NULL, &txn, 0)) != 0)
+ if (TXN_ON(dbenv) &&
+ (ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
goto err;
/* Get each key/data pair and add them to the database. */
for (recno = 1; !__db_util_interrupted(); ++recno) {
if (!keyflag)
if (checkprint) {
- if (dbt_rprint(&data))
+ if (dbt_rprint(dbenv, &data))
goto err;
} else {
- if (dbt_rdump(&data))
+ if (dbt_rdump(dbenv, &data))
goto err;
}
else
if (checkprint) {
- if (dbt_rprint(readp))
+ if (dbt_rprint(dbenv, readp))
goto err;
- if (!endodata && dbt_rprint(&data))
+ if (!G(endodata) && dbt_rprint(dbenv, &data))
goto fmt;
} else {
if (ascii_recno) {
- if (dbt_rrecno(readp, hexkeys))
+ if (dbt_rrecno(dbenv, readp, hexkeys))
goto err;
} else
- if (dbt_rdump(readp))
+ if (dbt_rdump(dbenv, readp))
goto err;
- if (!endodata && dbt_rdump(&data)) {
+ if (!G(endodata) && dbt_rdump(dbenv, &data)) {
fmt: dbenv->errx(dbenv,
"odd number of key/data pairs");
goto err;
}
}
- if (endodata)
+ if (G(endodata))
break;
if (readp != writep) {
if (sscanf(readp->data, "%ud", &datarecno) != 1)
@@ -359,20 +420,19 @@ fmt: dbenv->errx(dbenv,
!keyflag ? recno : recno * 2 - 1);
}
retry: if (txn != NULL)
- if ((ret = txn_begin(dbenv, txn, &ctxn, 0)) != 0)
+ if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)
goto err;
- switch (ret =
- dbp->put(dbp, txn, writep, &data, db_nooverwrite)) {
+ switch (ret = dbp->put(dbp, ctxn, writep, &data, put_flags)) {
case 0:
if (ctxn != NULL) {
if ((ret =
- txn_commit(ctxn, DB_TXN_NOSYNC)) != 0)
+ ctxn->commit(ctxn, DB_TXN_NOSYNC)) != 0)
goto err;
ctxn = NULL;
}
break;
case DB_KEYEXIST:
- existed = 1;
+ *existedp = 1;
dbenv->errx(dbenv,
"%s: line %d: key already exists, not loaded:",
name,
@@ -384,7 +444,7 @@ retry: if (txn != NULL)
case DB_LOCK_DEADLOCK:
/* If we have a child txn, retry--else it's fatal. */
if (ctxn != NULL) {
- if ((ret = txn_abort(ctxn)) != 0)
+ if ((ret = ctxn->abort(ctxn)) != 0)
goto err;
ctxn = NULL;
goto retry;
@@ -393,20 +453,20 @@ retry: if (txn != NULL)
default:
dbenv->err(dbenv, ret, NULL);
if (ctxn != NULL) {
- (void)txn_abort(ctxn);
+ (void)ctxn->abort(ctxn);
ctxn = NULL;
}
goto err;
}
if (ctxn != NULL) {
- if ((ret = txn_abort(ctxn)) != 0)
+ if ((ret = ctxn->abort(ctxn)) != 0)
goto err;
ctxn = NULL;
}
}
done: rval = 0;
DB_ASSERT(ctxn == NULL);
- if (txn != NULL && (ret = txn_commit(txn, 0)) != 0) {
+ if (txn != NULL && (ret = txn->commit(txn, 0)) != 0) {
txn = NULL;
goto err;
}
@@ -415,15 +475,18 @@ done: rval = 0;
err: rval = 1;
DB_ASSERT(ctxn == NULL);
if (txn != NULL)
- (void)txn_abort(txn);
+ (void)txn->abort(txn);
}
/* Close the database. */
- if ((ret = dbp->close(dbp, 0)) != 0) {
- dbp->err(dbp, ret, "DB->close");
+ if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->close");
rval = 1;
}
+ if (G(hdrbuf) != NULL)
+ free(G(hdrbuf));
+ G(hdrbuf) = NULL;
/* Free allocated memory. */
if (subdb != NULL)
free(subdb);
@@ -441,12 +504,16 @@ err: rval = 1;
* Initialize the environment.
*/
int
-db_init(home)
+db_init(dbenv, home, cache, is_private)
+ DB_ENV *dbenv;
char *home;
+ u_int32_t cache;
+ int *is_private;
{
u_int32_t flags;
int ret;
+ *is_private = 0;
/* We may be loading into a live environment. Try and join. */
flags = DB_USE_ENVIRON |
DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
@@ -467,11 +534,16 @@ db_init(home)
*/
LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
LF_SET(DB_CREATE | DB_PRIVATE);
+ *is_private = 1;
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_cachesize");
+ return (1);
+ }
if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
return (0);
/* An environment is required. */
- dbenv->err(dbenv, ret, "DBENV->open");
+ dbenv->err(dbenv, ret, "DB_ENV->open");
return (1);
}
@@ -481,14 +553,14 @@ db_init(home)
case '1': \
if ((ret = dbp->set_flags(dbp, flag)) != 0) { \
dbp->err(dbp, ret, "%s: set_flags: %s", \
- progname, name); \
+ G(progname), name); \
return (1); \
} \
break; \
case '0': \
break; \
default: \
- badnum(); \
+ badnum(dbenv); \
return (1); \
} \
continue; \
@@ -514,7 +586,8 @@ db_init(home)
* Handle command-line configuration options.
*/
int
-configure(dbp, clp, subdbp, keysp)
+configure(dbenv, dbp, clp, subdbp, keysp)
+ DB_ENV *dbenv;
DB *dbp;
char **clp, **subdbp;
int *keysp;
@@ -534,6 +607,8 @@ configure(dbp, clp, subdbp, keysp)
if (strcmp(name, "database") == 0 ||
strcmp(name, "subdatabase") == 0) {
+ if (*subdbp != NULL)
+ free(*subdbp);
if ((*subdbp = strdup(value)) == NULL) {
dbp->err(dbp, ENOMEM, NULL);
return (1);
@@ -546,7 +621,7 @@ configure(dbp, clp, subdbp, keysp)
else if (strcmp(value, "0") == 0)
*keysp = 0;
else {
- badnum();
+ badnum(dbenv);
return (1);
}
continue;
@@ -558,6 +633,7 @@ configure(dbp, clp, subdbp, keysp)
NUMBER(name, value, "bt_minkey", set_bt_minkey);
NUMBER(name, value, "db_lorder", set_lorder);
NUMBER(name, value, "db_pagesize", set_pagesize);
+ FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
FLAG(name, value, "duplicates", DB_DUP);
FLAG(name, value, "dupsort", DB_DUPSORT);
NUMBER(name, value, "h_ffactor", set_h_ffactor);
@@ -568,13 +644,13 @@ configure(dbp, clp, subdbp, keysp)
FLAG(name, value, "renumber", DB_RENUMBER);
dbp->errx(dbp,
- "unknown command-line configuration keyword");
+ "unknown command-line configuration keyword \"%s\"", name);
return (1);
}
return (0);
nameerr:
- dbp->err(dbp, ret, "%s: %s=%s", progname, name, value);
+ dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
return (1);
}
@@ -583,35 +659,91 @@ nameerr:
* Read the header message.
*/
int
-rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
+rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
+ DB_ENV *dbenv;
DB *dbp;
DBTYPE *dbtypep;
char **subdbp;
int *checkprintp, *keysp;
{
long val;
- int first, ret;
- char *name, *value, *p, buf[128];
+ int ch, first, hdr, linelen, buflen, ret, start;
+ char *buf, *name, *p, *value;
*dbtypep = DB_UNKNOWN;
*checkprintp = 0;
+ name = p = NULL;
+
+ /*
+ * We start with a smallish buffer; most headers are small.
+ * We may need to realloc it for a large subdatabase name.
+ */
+ buflen = 4096;
+ if (G(hdrbuf) == NULL) {
+ hdr = 0;
+ if ((buf = (char *)malloc(buflen)) == NULL) {
+memerr: dbp->errx(dbp, "could not allocate buffer %d", buflen);
+ return (1);
+ }
+ G(hdrbuf) = buf;
+ G(origline) = G(lineno);
+ } else {
+ hdr = 1;
+ buf = G(hdrbuf);
+ G(lineno) = G(origline);
+ }
+ start = 0;
for (first = 1;; first = 0) {
- ++lineno;
+ ++G(lineno);
+
+ /* Read a line, which may be of arbitrary length, into buf. */
+ linelen = 0;
+ buf = &G(hdrbuf)[start];
+ if (hdr == 0) {
+ for (;;) {
+ if ((ch = getchar()) == EOF) {
+ if (!first || ferror(stdin))
+ goto badfmt;
+ G(endofile) = 1;
+ break;
+ }
- /* If we don't see the expected information, it's an error. */
- if (fgets(buf, sizeof(buf), stdin) == NULL) {
- if (!first || ferror(stdin))
- goto badfmt;
- endofile = 1;
- break;
+ if (ch == '\n')
+ break;
+
+ buf[linelen++] = ch;
+
+ /* If the buffer is too small, double it. */
+ if (linelen + start == buflen) {
+ G(hdrbuf) = (char *)realloc(G(hdrbuf),
+ buflen *= 2);
+ if (G(hdrbuf) == NULL)
+ goto memerr;
+ buf = &G(hdrbuf)[start];
+ }
+ }
+ if (G(endofile) == 1)
+ break;
+ buf[linelen++] = '\0';
+ } else
+ linelen = strlen(buf) + 1;
+ start += linelen;
+
+ if (name != NULL) {
+ *p = '=';
+ free(name);
+ name = NULL;
}
- if ((p = strchr(name = buf, '=')) == NULL)
+ /* If we don't see the expected information, it's an error. */
+ if ((name = strdup(buf)) == NULL)
+ goto memerr;
+ if ((p = strchr(name, '=')) == NULL)
goto badfmt;
*p++ = '\0';
- if ((p = strchr(value = p, '\n')) == NULL)
- goto badfmt;
- *p = '\0';
+
+ value = p--;
+
if (name[0] == '\0' || value[0] == '\0')
goto badfmt;
@@ -622,13 +754,13 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
* Version 1 didn't have a "VERSION" header line. We
* only support versions 1, 2, and 3 of the dump format.
*/
- version = atoi(value);
+ G(version) = atoi(value);
- if (version > 3) {
+ if (G(version) > 3) {
dbp->errx(dbp,
"line %lu: VERSION %d is unsupported",
- lineno, version);
- return (1);
+ G(lineno), G(version));
+ goto err;
}
continue;
}
@@ -660,14 +792,14 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
*dbtypep = DB_QUEUE;
continue;
}
- dbp->errx(dbp, "line %lu: unknown type", lineno);
- return (1);
+ dbp->errx(dbp, "line %lu: unknown type", G(lineno));
+ goto err;
}
if (strcmp(name, "database") == 0 ||
strcmp(name, "subdatabase") == 0) {
- if ((*subdbp = strdup(value)) == NULL) {
- dbp->err(dbp, ENOMEM, NULL);
- return (1);
+ if ((ret = convprintable(dbenv, value, subdbp)) != 0) {
+ dbp->err(dbp, ret, "error reading db name");
+ goto err;
}
continue;
}
@@ -677,8 +809,8 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
else if (strcmp(value, "0") == 0)
*keysp = 0;
else {
- badnum();
- return (1);
+ badnum(dbenv);
+ goto err;
}
continue;
}
@@ -689,6 +821,8 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
NUMBER(name, value, "bt_minkey", set_bt_minkey);
NUMBER(name, value, "db_lorder", set_lorder);
NUMBER(name, value, "db_pagesize", set_pagesize);
+ NUMBER(name, value, "extentsize", set_q_extentsize);
+ FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
FLAG(name, value, "duplicates", DB_DUP);
FLAG(name, value, "dupsort", DB_DUPSORT);
NUMBER(name, value, "h_ffactor", set_h_ffactor);
@@ -699,18 +833,81 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
FLAG(name, value, "renumber", DB_RENUMBER);
dbp->errx(dbp,
- "unknown input-file header configuration keyword");
- return (1);
+ "unknown input-file header configuration keyword \"%s\"",
+ name);
+ goto err;
}
- return (0);
-
+ ret = 0;
+ if (0) {
nameerr:
- dbp->err(dbp, ret, "%s: %s=%s", progname, name, value);
- return (1);
-
+ dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
+ ret = 1;
+ }
+ if (0)
+err: ret = 1;
+ if (0) {
badfmt:
- dbp->errx(dbp, "line %lu: unexpected format", lineno);
- return (1);
+ dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
+ ret = 1;
+ }
+ if (name != NULL) {
+ *p = '=';
+ free(name);
+ }
+ return (ret);
+}
+
+/*
+ * convprintable --
+ * Convert a printable-encoded string into a newly allocated string.
+ *
+ * In an ideal world, this would probably share code with dbt_rprint, but
+ * that's set up to read character-by-character (to avoid large memory
+ * allocations that aren't likely to be a problem here), and this has fewer
+ * special cases to deal with.
+ *
+ * Note that despite the printable encoding, the char * interface to this
+ * function (which is, not coincidentally, also used for database naming)
+ * means that outstr cannot contain any nuls.
+ */
+int
+convprintable(dbenv, instr, outstrp)
+ DB_ENV *dbenv;
+ char *instr, **outstrp;
+{
+ char c, *outstr;
+ int e1, e2;
+
+ /*
+ * Just malloc a string big enough for the whole input string;
+ * the output string will be smaller (or of equal length).
+ */
+ if ((outstr = (char *)malloc(strlen(instr))) == NULL)
+ return (ENOMEM);
+
+ *outstrp = outstr;
+
+ e1 = e2 = 0;
+ for ( ; *instr != '\0'; instr++)
+ if (*instr == '\\') {
+ if (*++instr == '\\') {
+ *outstr++ = '\\';
+ continue;
+ }
+ c = digitize(dbenv, *instr, &e1) << 4;
+ c |= digitize(dbenv, *++instr, &e2);
+ if (e1 || e2) {
+ badend(dbenv);
+ return (EINVAL);
+ }
+
+ *outstr++ = c;
+ } else
+ *outstr++ = *instr;
+
+ *outstr = '\0';
+
+ return (0);
}
/*
@@ -718,7 +915,8 @@ badfmt:
* Read a printable line into a DBT structure.
*/
int
-dbt_rprint(dbtp)
+dbt_rprint(dbenv, dbtp)
+ DB_ENV *dbenv;
DBT *dbtp;
{
u_int32_t len;
@@ -726,31 +924,31 @@ dbt_rprint(dbtp)
int c1, c2, e, escape, first;
char buf[32];
- ++lineno;
+ ++G(lineno);
first = 1;
e = escape = 0;
for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
if (c1 == EOF) {
if (len == 0) {
- endofile = endodata = 1;
+ G(endofile) = G(endodata) = 1;
return (0);
}
- badend();
+ badend(dbenv);
return (1);
}
if (first) {
first = 0;
- if (version > 1) {
+ if (G(version) > 1) {
if (c1 != ' ') {
buf[0] = c1;
if (fgets(buf + 1,
sizeof(buf) - 1, stdin) == NULL ||
strcmp(buf, "DATA=END\n") != 0) {
- badend();
+ badend(dbenv);
return (1);
}
- endodata = 1;
+ G(endodata) = 1;
return (0);
}
continue;
@@ -759,10 +957,11 @@ dbt_rprint(dbtp)
if (escape) {
if (c1 != '\\') {
if ((c2 = getchar()) == EOF) {
- badend();
+ badend(dbenv);
return (1);
}
- c1 = digitize(c1, &e) << 4 | digitize(c2, &e);
+ c1 = digitize(dbenv,
+ c1, &e) << 4 | digitize(dbenv, c2, &e);
if (e)
return (1);
}
@@ -794,7 +993,8 @@ dbt_rprint(dbtp)
* Read a byte dump line into a DBT structure.
*/
int
-dbt_rdump(dbtp)
+dbt_rdump(dbenv, dbtp)
+ DB_ENV *dbenv;
DBT *dbtp;
{
u_int32_t len;
@@ -802,38 +1002,38 @@ dbt_rdump(dbtp)
int c1, c2, e, first;
char buf[32];
- ++lineno;
+ ++G(lineno);
first = 1;
e = 0;
for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
if (c1 == EOF) {
if (len == 0) {
- endofile = endodata = 1;
+ G(endofile) = G(endodata) = 1;
return (0);
}
- badend();
+ badend(dbenv);
return (1);
}
if (first) {
first = 0;
- if (version > 1) {
+ if (G(version) > 1) {
if (c1 != ' ') {
buf[0] = c1;
if (fgets(buf + 1,
sizeof(buf) - 1, stdin) == NULL ||
strcmp(buf, "DATA=END\n") != 0) {
- badend();
+ badend(dbenv);
return (1);
}
- endodata = 1;
+ G(endodata) = 1;
return (0);
}
continue;
}
}
if ((c2 = getchar()) == EOF) {
- badend();
+ badend(dbenv);
return (1);
}
if (len >= dbtp->ulen - 10) {
@@ -846,7 +1046,7 @@ dbt_rdump(dbtp)
p = (u_int8_t *)dbtp->data + len;
}
++len;
- *p++ = digitize(c1, &e) << 4 | digitize(c2, &e);
+ *p++ = digitize(dbenv, c1, &e) << 4 | digitize(dbenv, c2, &e);
if (e)
return (1);
}
@@ -860,21 +1060,22 @@ dbt_rdump(dbtp)
* Read a record number dump line into a DBT structure.
*/
int
-dbt_rrecno(dbtp, ishex)
+dbt_rrecno(dbenv, dbtp, ishex)
+ DB_ENV *dbenv;
DBT *dbtp;
int ishex;
{
char buf[32], *p, *q;
- ++lineno;
+ ++G(lineno);
if (fgets(buf, sizeof(buf), stdin) == NULL) {
- endofile = endodata = 1;
+ G(endofile) = G(endodata) = 1;
return (0);
}
if (strcmp(buf, "DATA=END\n") == 0) {
- endodata = 1;
+ G(endodata) = 1;
return (0);
}
@@ -904,8 +1105,8 @@ dbt_rrecno(dbtp, ishex)
}
if (__db_getulong(NULL,
- progname, buf + 1, 0, 0, (u_long *)dbtp->data)) {
-bad: badend();
+ G(progname), buf + 1, 0, 0, (u_long *)dbtp->data)) {
+bad: badend(dbenv);
return (1);
}
@@ -918,7 +1119,8 @@ bad: badend();
* Convert a character to an integer.
*/
int
-digitize(c, errorp)
+digitize(dbenv, c, errorp)
+ DB_ENV *dbenv;
int c, *errorp;
{
switch (c) { /* Don't depend on ASCII ordering. */
@@ -951,7 +1153,8 @@ digitize(c, errorp)
* Display the bad number message.
*/
void
-badnum()
+badnum(dbenv)
+ DB_ENV *dbenv;
{
dbenv->errx(dbenv,
"boolean name=value pairs require a value of 0 or 1");
@@ -962,7 +1165,8 @@ badnum()
* Display the bad end to input message.
*/
void
-badend()
+badend(dbenv)
+ DB_ENV *dbenv;
{
dbenv->errx(dbenv, "unexpected end of input data or key/data pair");
}
@@ -971,17 +1175,18 @@ badend()
* usage --
* Display the usage message.
*/
-void
+int
usage()
{
(void)fprintf(stderr, "%s\n\t%s\n",
- "usage: db_load [-nTV]",
- "[-c name=value] [-f file] [-h home] [-t btree | hash | recno] db_file");
- exit(1);
+ "usage: db_load [-nTV] [-c name=value] [-f file]",
+ "[-h home] [-P password] [-t btree | hash | recno | queue] db_file");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -993,6 +1198,35 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
+}
+
+int
+env_create(dbenvp, ldg)
+ DB_ENV **dbenvp;
+ LDG *ldg;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ if ((ret = db_env_create(dbenvp, 0)) != 0) {
+ fprintf(stderr,
+ "%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));
+ return (ret);
+ }
+ dbenv = *dbenvp;
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, ldg->progname);
+ if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ ldg->passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ return (ret);
+ }
+ if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
+ return (ret);
+ dbenv->app_private = ldg;
+
+ return (0);
}
diff --git a/bdb/db_printlog/README b/bdb/db_printlog/README
index 7d8da505e49..d59f4c77f55 100644
--- a/bdb/db_printlog/README
+++ b/bdb/db_printlog/README
@@ -1,4 +1,4 @@
-# $Id: README,v 10.5 1999/11/21 23:08:01 bostic Exp $
+# $Id: README,v 10.6 2002/06/20 14:52:54 bostic Exp $
Berkeley DB log dump utility. This utility dumps out a DB log in human
readable form, a record at a time, to assist in recovery and transaction
@@ -10,14 +10,23 @@ commit.awk Output transaction ID of committed transactions.
count.awk Print out the number of log records for transactions
that we encountered.
+dbname.awk Take a comma-separated list of database names and spit
+ out all the log records that affect those databases.
+
fileid.awk Take a comma-separated list of file numbers and spit out
all the log records that affect those file numbers.
+logstat.awk Display log record count/size statistics.
+
pgno.awk Take a comma-separated list of page numbers and spit
out all the log records that affect those page numbers.
range.awk Print out a range of the log.
+rectype.awk Print out a range of the log -- command line should
+ set RECTYPE to the a comma separated list of the
+ rectypes (or partial strings of rectypes) sought.
+
status.awk Read through db_printlog output and list the transactions
encountered, and whether they commited or aborted.
diff --git a/bdb/db_printlog/db_printlog.c b/bdb/db_printlog/db_printlog.c
index 8b9fb74a6a9..af6d00d593a 100644
--- a/bdb/db_printlog/db_printlog.c
+++ b/bdb/db_printlog/db_printlog.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,14 +9,15 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_printlog.c,v 11.23 2001/01/18 18:36:58 bostic Exp $";
+ "$Id: db_printlog.c,v 11.52 2002/08/08 03:50:38 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -24,21 +25,20 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "db_am.h"
-#include "hash.h"
-#include "log.h"
-#include "qam.h"
-#include "txn.h"
-
-int main __P((int, char *[]));
-void usage __P((void));
-void version_check __P((void));
-
-DB_ENV *dbenv;
-const char
- *progname = "db_printlog"; /* Program name. */
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/fop.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((const char *));
+int print_app_record __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
+int open_rep_db __P((DB_ENV *, DB **, DBC **));
int
main(argc, argv)
@@ -47,42 +47,63 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
- DBT data;
+ const char *progname = "db_printlog";
+ DB *dbp;
+ DBC *dbc;
+ DB_ENV *dbenv;
+ DB_LOGC *logc;
+ int (**dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t dtabsize;
+ DBT data, keydbt;
DB_LSN key;
- int ch, e_close, exitval, nflag, ret;
- char *home;
+ int ch, e_close, exitval, nflag, rflag, ret, repflag;
+ char *home, *passwd;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
- e_close = exitval = 0;
- nflag = 0;
- home = NULL;
- while ((ch = getopt(argc, argv, "h:NV")) != EOF)
+ dbp = NULL;
+ dbc = NULL;
+ logc = NULL;
+ e_close = exitval = nflag = rflag = repflag = 0;
+ home = passwd = NULL;
+ dtabsize = 0;
+ dtab = NULL;
+ while ((ch = getopt(argc, argv, "h:NP:rRV")) != EOF)
switch (ch) {
case 'h':
home = optarg;
break;
case 'N':
nflag = 1;
- if ((ret = db_env_set_panicstate(0)) != 0) {
- fprintf(stderr,
- "%s: db_env_set_panicstate: %s\n",
- progname, db_strerror(ret));
- return (1);
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'R':
+ repflag = 1;
+ break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc > 0)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -101,8 +122,29 @@ main(argc, argv)
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
- if (nflag && (ret = dbenv->set_mutexlocks(dbenv, 0)) != 0) {
- dbenv->err(dbenv, ret, "set_mutexlocks");
+ if (nflag) {
+ if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
+ goto shutdown;
+ }
+ if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
+ goto shutdown;
+ }
+ }
+
+ if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ goto shutdown;
+ }
+
+ /*
+ * Set up an app-specific dispatch function so that we can gracefully
+ * handle app-specific log records.
+ */
+ if ((ret = dbenv->set_app_dispatch(dbenv, print_app_record)) != 0) {
+ dbenv->err(dbenv, ret, "app_dispatch");
goto shutdown;
}
@@ -110,8 +152,19 @@ main(argc, argv)
* An environment is required, but as all we're doing is reading log
* files, we create one if it doesn't already exist. If we create
* it, create it private so it automatically goes away when we're done.
+ * If we are reading the replication database, do not open the env
+ * with logging, because we don't want to log the opens.
*/
- if ((ret = dbenv->open(dbenv, home,
+ if (repflag) {
+ if ((ret = dbenv->open(dbenv, home,
+ DB_INIT_MPOOL | DB_USE_ENVIRON, 0)) != 0 &&
+ (ret = dbenv->open(dbenv, home,
+ DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0))
+ != 0) {
+ dbenv->err(dbenv, ret, "open");
+ goto shutdown;
+ }
+ } else if ((ret = dbenv->open(dbenv, home,
DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
(ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_LOG | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
@@ -120,33 +173,48 @@ main(argc, argv)
}
/* Initialize print callbacks. */
- if ((ret = __bam_init_print(dbenv)) != 0 ||
- (ret = __crdel_init_print(dbenv)) != 0 ||
- (ret = __db_init_print(dbenv)) != 0 ||
- (ret = __qam_init_print(dbenv)) != 0 ||
- (ret = __ham_init_print(dbenv)) != 0 ||
- (ret = __log_init_print(dbenv)) != 0 ||
- (ret = __txn_init_print(dbenv)) != 0) {
+ if ((ret = __bam_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __dbreg_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __crdel_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __db_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __fop_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __qam_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __ham_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+ (ret = __txn_init_print(dbenv, &dtab, &dtabsize)) != 0) {
dbenv->err(dbenv, ret, "callback: initialization");
goto shutdown;
}
+ /* Allocate a log cursor. */
+ if (repflag) {
+ if ((ret = open_rep_db(dbenv, &dbp, &dbc)) != 0)
+ goto shutdown;
+ } else if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB_ENV->log_cursor");
+ goto shutdown;
+ }
+
memset(&data, 0, sizeof(data));
+ memset(&keydbt, 0, sizeof(keydbt));
while (!__db_util_interrupted()) {
- if ((ret = log_get(dbenv, &key, &data, DB_NEXT)) != 0) {
+ if (repflag) {
+ ret = dbc->c_get(dbc,
+ &keydbt, &data, rflag ? DB_PREV : DB_NEXT);
+ if (ret == 0)
+ key = ((REP_CONTROL *)keydbt.data)->lsn;
+ } else
+ ret = logc->get(logc,
+ &key, &data, rflag ? DB_PREV : DB_NEXT);
+ if (ret != 0) {
if (ret == DB_NOTFOUND)
break;
- dbenv->err(dbenv, ret, "log_get");
+ dbenv->err(dbenv,
+ ret, repflag ? "DB_LOGC->get" : "DBC->get");
goto shutdown;
}
- /*
- * XXX
- * We use DB_TXN_ABORT as our op because that's the only op
- * that calls the underlying recovery function without any
- * consideration as to the contents of the transaction list.
- */
- ret = __db_dispatch(dbenv, &data, &key, DB_TXN_ABORT, NULL);
+ ret = __db_dispatch(dbenv,
+ dtab, dtabsize, &data, &key, DB_TXN_PRINT, NULL);
/*
* XXX
@@ -163,6 +231,22 @@ main(argc, argv)
if (0) {
shutdown: exitval = 1;
}
+ if (logc != NULL && (ret = logc->close(logc, 0)) != 0)
+ exitval = 1;
+
+ if (dbc != NULL && (ret = dbc->c_close(dbc)) != 0)
+ exitval = 1;
+
+ if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0)
+ exitval = 1;
+
+ /*
+ * The dtab is allocated by __db_add_recovery (called by *_init_print)
+ * using the library malloc function (__os_malloc). It thus needs to be
+ * freed using the corresponding free (__os_free).
+ */
+ if (dtab != NULL)
+ __os_free(dbenv, dtab);
if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
fprintf(stderr,
@@ -172,18 +256,20 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage()
{
- fprintf(stderr, "usage: db_printlog [-NV] [-h home]\n");
- exit (1);
+ fprintf(stderr, "%s\n",
+ "usage: db_printlog [-NrV] [-h home] [-P password]");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -195,6 +281,80 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
+ }
+ return (0);
+}
+
+/* Print an unknown, application-specific log record as best we can. */
+int
+print_app_record(dbenv, dbt, lsnp, op)
+ DB_ENV *dbenv;
+ DBT *dbt;
+ DB_LSN *lsnp;
+ db_recops op;
+{
+ int ch;
+ u_int32_t i, rectype;
+
+ DB_ASSERT(op == DB_TXN_PRINT);
+ COMPQUIET(dbenv, NULL);
+
+ /*
+ * Fetch the rectype, which always must be at the beginning of the
+ * record (if dispatching is to work at all).
+ */
+ memcpy(&rectype, dbt->data, sizeof(rectype));
+
+ /*
+ * Applications may wish to customize the output here based on the
+ * rectype. We just print the entire log record in the generic
+ * mixed-hex-and-printable format we use for binary data.
+ */
+ printf("[%lu][%lu]application specific record: rec: %lu\n",
+ (u_long)lsnp->file, (u_long)lsnp->offset, (u_long)rectype);
+ printf("\tdata: ");
+ for (i = 0; i < dbt->size; i++) {
+ ch = ((u_int8_t *)dbt->data)[i];
+ printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch);
}
+ printf("\n\n");
+
+ return (0);
+}
+
+int
+open_rep_db(dbenv, dbpp, dbcp)
+ DB_ENV *dbenv;
+ DB **dbpp;
+ DBC **dbcp;
+{
+ int ret;
+
+ DB *dbp;
+ *dbpp = NULL;
+ *dbcp = NULL;
+
+ if ((ret = db_create(dbpp, dbenv, 0)) != 0) {
+ dbenv->err(dbenv, ret, "db_create");
+ return (ret);
+ }
+
+ dbp = *dbpp;
+ if ((ret =
+ dbp->open(dbp, NULL, "__db.rep.db", NULL, DB_BTREE, 0, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->open");
+ goto err;
+ }
+
+ if ((ret = dbp->cursor(dbp, NULL, dbcp, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->cursor");
+ goto err;
+ }
+
+ return (0);
+
+err: if (*dbpp != NULL)
+ (void)(*dbpp)->close(*dbpp, 0);
+ return (ret);
}
diff --git a/bdb/db_printlog/dbname.awk b/bdb/db_printlog/dbname.awk
index d070335127c..47955994579 100644
--- a/bdb/db_printlog/dbname.awk
+++ b/bdb/db_printlog/dbname.awk
@@ -1,4 +1,4 @@
-# $Id: dbname.awk,v 1.2 2000/08/03 15:06:39 ubell Exp $
+# $Id: dbname.awk,v 1.5 2002/05/07 05:45:51 ubell Exp $
#
# Take a comma-separated list of database names and spit out all the
# log records that affect those databases.
@@ -16,7 +16,7 @@ NR == 1 {
myfile = -1;
}
-/^\[.*log_register/ {
+/^\[.*dbreg_register/ {
register = 1;
}
/opcode:/ {
@@ -58,8 +58,6 @@ NR == 1 {
}
}
-
-
/^\[/{
if (printme == 1) {
printf("%s\n", rec);
@@ -69,6 +67,8 @@ NR == 1 {
rec = $0
}
+
+TXN == 1 && /txn_regop/ {printme = 1}
/^ /{
rec = sprintf("%s\n%s", rec, $0);
}
diff --git a/bdb/db_printlog/logstat.awk b/bdb/db_printlog/logstat.awk
new file mode 100644
index 00000000000..1009343eba4
--- /dev/null
+++ b/bdb/db_printlog/logstat.awk
@@ -0,0 +1,36 @@
+# $Id: logstat.awk,v 1.1 2002/05/10 15:19:13 bostic Exp $
+#
+# Output accumulated log record count/size statistics.
+BEGIN {
+ l_file = 0;
+ l_offset = 0;
+}
+
+/^\[/{
+ gsub("[][: ]", " ", $1)
+ split($1, a)
+
+ if (a[1] == l_file) {
+ l[a[3]] += a[2] - l_offset
+ ++n[a[3]]
+ } else
+ ++s[a[3]]
+
+ l_file = a[1]
+ l_offset = a[2]
+}
+
+END {
+ # We can't figure out the size of the first record in each log file,
+ # use the average for other records we found as an estimate.
+ for (i in s)
+ if (s[i] != 0 && n[i] != 0) {
+ l[i] += s[i] * (l[i]/n[i])
+ n[i] += s[i]
+ delete s[i]
+ }
+ for (i in l)
+ printf "%s: %d (n: %d, avg: %.2f)\n", i, l[i], n[i], l[i]/n[i]
+ for (i in s)
+ printf "%s: unknown (n: %d, unknown)\n", i, s[i]
+}
diff --git a/bdb/db_printlog/status.awk b/bdb/db_printlog/status.awk
index 42e24b078b9..13df0b6194a 100644
--- a/bdb/db_printlog/status.awk
+++ b/bdb/db_printlog/status.awk
@@ -1,14 +1,17 @@
-# $Id: status.awk,v 10.2 1999/11/21 18:01:43 bostic Exp $
+# $Id: status.awk,v 10.3 2002/04/11 01:35:24 margo Exp $
#
# Read through db_printlog output and list all the transactions encountered
# and whether they commited or aborted.
#
# 1 = started
# 2 = commited
+# 3 = explicitly aborted
+# 4 = other
BEGIN {
cur_txn = 0
}
/^\[/{
+ in_regop = 0
if (status[$5] == 0) {
status[$5] = 1;
txns[cur_txn] = $5;
@@ -16,11 +19,28 @@ BEGIN {
}
}
/txn_regop/ {
- status[$5] = 2
+ txnid = $5
+ in_regop = 1
+}
+/opcode:/ {
+ if (in_regop == 1) {
+ if ($2 == 1)
+ status[txnid] = 2
+ else if ($2 == 3)
+ status[txnid] = 3
+ else
+ status[txnid] = 4
+ }
}
END {
for (i = 0; i < cur_txn; i++) {
- printf("%s\t%s\n",
- txns[i], status[txns[i]] == 1 ? "ABORT" : "COMMIT");
+ if (status[txns[i]] == 1)
+ printf("%s\tABORT\n", txns[i]);
+ if (status[txns[i]] == 2)
+ printf("%s\tCOMMIT\n", txns[i]);
+ if (status[txns[i]] == 3)
+ printf("%s\tABORT\n", txns[i]);
+ if (status[txns[i]] == 4)
+ printf("%s\tOTHER\n", txns[i]);
}
}
diff --git a/bdb/db_recover/db_recover.c b/bdb/db_recover/db_recover.c
index 59ab8bcef15..b6414267f93 100644
--- a/bdb/db_recover/db_recover.c
+++ b/bdb/db_recover/db_recover.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_recover.c,v 11.17 2001/01/18 18:36:58 bostic Exp $";
+ "$Id: db_recover.c,v 11.33 2002/03/28 20:13:42 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -34,17 +34,12 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "common_ext.h"
-#include "txn.h"
+#include "dbinc/txn.h"
-int main __P((int, char *[]));
-void read_timestamp __P((char *, time_t *));
-void usage __P((void));
-void version_check __P((void));
-
-DB_ENV *dbenv;
-const char
- *progname = "db_recover"; /* Program name. */
+int main __P((int, char *[]));
+int read_timestamp __P((const char *, char *, time_t *));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -53,43 +48,60 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ const char *progname = "db_recover";
+ DB_ENV *dbenv;
DB_TXNREGION *region;
time_t now, timestamp;
u_int32_t flags;
- int ch, exitval, fatal_recover, ret, verbose;
- char *home;
+ int ch, exitval, fatal_recover, ret, retain_env, verbose;
+ char *home, *passwd;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
- home = NULL;
+ home = passwd = NULL;
timestamp = 0;
- exitval = fatal_recover = verbose = 0;
- while ((ch = getopt(argc, argv, "ch:t:Vv")) != EOF)
+ exitval = fatal_recover = retain_env = verbose = 0;
+ while ((ch = getopt(argc, argv, "ceh:P:t:Vv")) != EOF)
switch (ch) {
case 'c':
fatal_recover = 1;
break;
+ case 'e':
+ retain_env = 1;
+ break;
case 'h':
home = optarg;
break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ break;
case 't':
- read_timestamp(optarg, &timestamp);
+ if ((ret =
+ read_timestamp(progname, optarg, &timestamp)) != 0)
+ return (ret);
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case 'v':
verbose = 1;
break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -101,7 +113,7 @@ main(argc, argv)
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
- exit (1);
+ return (EXIT_FAILURE);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
@@ -111,7 +123,13 @@ main(argc, argv)
}
if (timestamp &&
(ret = dbenv->set_tx_timestamp(dbenv, &timestamp)) != 0) {
- dbenv->err(dbenv, ret, "DBENV->set_timestamp");
+ dbenv->err(dbenv, ret, "DB_ENV->set_timestamp");
+ goto shutdown;
+ }
+
+ if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
goto shutdown;
}
@@ -119,18 +137,21 @@ main(argc, argv)
* Initialize the environment -- we don't actually do anything
* else, that all that's needed to run recovery.
*
- * Note that we specify a private environment, as we're about to
- * create a region, and we don't want to to leave it around. If
- * we leave the region around, the application that should create
- * it will simply join it instead, and will then be running with
- * incorrectly sized (and probably terribly small) caches.
+ * Note that unless the caller specified the -e option, we use a
+ * private environment, as we're about to create a region, and we
+ * don't want to to leave it around. If we leave the region around,
+ * the application that should create it will simply join it instead,
+ * and will then be running with incorrectly sized (and probably
+ * terribly small) caches. Applications that use -e should almost
+ * certainly use DB_CONFIG files in the directory.
*/
flags = 0;
LF_SET(DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
- DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE | DB_USE_ENVIRON);
+ DB_INIT_MPOOL | DB_INIT_TXN | DB_USE_ENVIRON);
LF_SET(fatal_recover ? DB_RECOVER_FATAL : DB_RECOVER);
+ LF_SET(retain_env ? 0 : DB_PRIVATE);
if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) {
- dbenv->err(dbenv, ret, "DBENV->open");
+ dbenv->err(dbenv, ret, "DB_ENV->open");
goto shutdown;
}
@@ -158,7 +179,7 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
@@ -194,8 +215,9 @@ shutdown: exitval = 1;
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-void
-read_timestamp(arg, timep)
+int
+read_timestamp(progname, arg, timep)
+ const char *progname;
char *arg;
time_t *timep;
{
@@ -208,7 +230,7 @@ read_timestamp(arg, timep)
if ((t = localtime(&now)) == NULL) {
fprintf(stderr,
"%s: localtime: %s\n", progname, strerror(errno));
- exit (1);
+ return (EXIT_FAILURE);
}
/* [[CC]YY]MMDDhhmm[.SS] */
if ((p = strchr(arg, '.')) == NULL)
@@ -226,7 +248,7 @@ read_timestamp(arg, timep)
t->tm_year = ATOI2(arg);
t->tm_year *= 100;
yearset = 1;
- /* FALLTHOUGH */
+ /* FALLTHROUGH */
case 10: /* YYMMDDhhmm */
if (yearset) {
yearset = ATOI2(arg);
@@ -258,20 +280,22 @@ read_timestamp(arg, timep)
terr: fprintf(stderr,
"%s: out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]",
progname);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
-void
+int
usage()
{
- (void)fprintf(stderr,
- "usage: db_recover [-cVv] [-h home] [-t [[CC]YY]MMDDhhmm[.SS]]\n");
- exit(1);
+ (void)fprintf(stderr, "%s\n",
+"usage: db_recover [-ceVv] [-h home] [-P password] [-t [[CC]YY]MMDDhhmm[.SS]]");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -283,6 +307,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_stat/db_stat.c b/bdb/db_stat/db_stat.c
index 9d80caa4889..a2b01b71e0a 100644
--- a/bdb/db_stat/db_stat.c
+++ b/bdb/db_stat/db_stat.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_stat.c,v 11.42 2001/01/18 18:36:59 bostic Exp $";
+ "$Id: db_stat.c,v 11.125 2002/08/08 15:26:15 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -35,41 +35,33 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "mp.h"
+#include "dbinc/db_page.h"
#define PCT(f, t, pgsize) \
((t) == 0 ? 0 : \
(((double)(((t) * (pgsize)) - (f)) / ((t) * (pgsize))) * 100))
-typedef enum { T_NOTSET, T_DB, T_ENV, T_LOCK, T_LOG, T_MPOOL, T_TXN } test_t;
+typedef enum { T_NOTSET,
+ T_DB, T_ENV, T_LOCK, T_LOG, T_MPOOL, T_REP, T_TXN } test_t;
int argcheck __P((char *, const char *));
-int btree_stats __P((DB_ENV *, DB *, DB_BTREE_STAT *));
-int db_init __P((char *, test_t));
+int btree_stats __P((DB_ENV *, DB *, DB_BTREE_STAT *, int));
+int db_init __P((DB_ENV *, char *, test_t, u_int32_t, int *));
void dl __P((const char *, u_long));
void dl_bytes __P((const char *, u_long, u_long, u_long));
-int env_stats __P((DB_ENV *));
-int hash_stats __P((DB_ENV *, DB *));
-int lock_ok __P((char *));
-int lock_stats __P((DB_ENV *));
-int log_stats __P((DB_ENV *));
+int env_stats __P((DB_ENV *, u_int32_t));
+int hash_stats __P((DB_ENV *, DB *, int));
+int lock_stats __P((DB_ENV *, char *, u_int32_t));
+int log_stats __P((DB_ENV *, u_int32_t));
int main __P((int, char *[]));
-int mpool_ok __P((char *));
-int mpool_stats __P((DB_ENV *));
+int mpool_stats __P((DB_ENV *, char *, u_int32_t));
void prflags __P((u_int32_t, const FN *));
-int queue_stats __P((DB_ENV *, DB *));
+int queue_stats __P((DB_ENV *, DB *, int));
+int rep_stats __P((DB_ENV *, u_int32_t));
int txn_compare __P((const void *, const void *));
-int txn_stats __P((DB_ENV *));
-void usage __P((void));
-void version_check __P((void));
-
-DB_ENV *dbenv;
-char *internal;
-const char
- *progname = "db_stat"; /* Program name. */
+int txn_stats __P((DB_ENV *, u_int32_t));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -78,72 +70,114 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ const char *progname = "db_stat";
+ DB_ENV *dbenv;
DB_BTREE_STAT *sp;
DB *alt_dbp, *dbp;
test_t ttype;
- int ch, checked, d_close, e_close, exitval, nflag, ret;
- char *db, *home, *subdb;
+ u_int32_t cache;
+ int ch, checked, d_close, e_close, exitval, fast, flags;
+ int nflag, private, resize, ret;
+ char *db, *home, *internal, *passwd, *subdb;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
dbp = NULL;
ttype = T_NOTSET;
- nflag = 0;
- d_close = e_close = exitval = 0;
- db = home = subdb = NULL;
- while ((ch = getopt(argc, argv, "C:cd:eh:lM:mNs:tV")) != EOF)
+ cache = MEGABYTE;
+ d_close = e_close = exitval = fast = flags = nflag = private = 0;
+ db = home = internal = passwd = subdb = NULL;
+
+ while ((ch = getopt(argc, argv, "C:cd:efh:lM:mNP:rs:tVZ")) != EOF)
switch (ch) {
case 'C':
+ if (ttype != T_NOTSET)
+ goto argcombo;
ttype = T_LOCK;
- if (!argcheck(internal = optarg, "Acflmo"))
- usage();
+ if (!argcheck(internal = optarg, "Aclmop"))
+ return (usage());
break;
case 'c':
+ if (ttype != T_NOTSET)
+ goto argcombo;
ttype = T_LOCK;
break;
case 'd':
- db = optarg;
+ if (ttype != T_DB && ttype != T_NOTSET)
+ goto argcombo;
ttype = T_DB;
+ db = optarg;
break;
case 'e':
+ if (ttype != T_NOTSET)
+ goto argcombo;
ttype = T_ENV;
break;
+ case 'f':
+ fast = DB_FAST_STAT;
+ break;
case 'h':
home = optarg;
break;
case 'l':
+ if (ttype != T_NOTSET)
+ goto argcombo;
ttype = T_LOG;
break;
case 'M':
+ if (ttype != T_NOTSET)
+ goto argcombo;
ttype = T_MPOOL;
- if (!argcheck(internal = optarg, "Ahlm"))
- usage();
+ if (!argcheck(internal = optarg, "Ahm"))
+ return (usage());
break;
case 'm':
+ if (ttype != T_NOTSET)
+ goto argcombo;
ttype = T_MPOOL;
break;
case 'N':
nflag = 1;
- if ((ret = db_env_set_panicstate(0)) != 0) {
- fprintf(stderr,
- "%s: db_env_set_panicstate: %s\n",
- progname, db_strerror(ret));
- return (1);
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
+ case 'r':
+ if (ttype != T_NOTSET)
+ goto argcombo;
+ ttype = T_REP;
+ break;
case 's':
- subdb = optarg;
+ if (ttype != T_DB && ttype != T_NOTSET)
+ goto argcombo;
ttype = T_DB;
+ subdb = optarg;
break;
case 't':
+ if (ttype != T_NOTSET) {
+argcombo: fprintf(stderr,
+ "%s: illegal option combination\n",
+ progname);
+ return (EXIT_FAILURE);
+ }
ttype = T_TXN;
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
+ case 'Z':
+ flags |= DB_STAT_CLEAR;
+ break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
@@ -151,12 +185,14 @@ main(argc, argv)
switch (ttype) {
case T_DB:
if (db == NULL)
- usage();
+ return (usage());
break;
case T_NOTSET:
- usage();
+ return (usage());
/* NOTREACHED */
default:
+ if (fast != 0)
+ return (usage());
break;
}
@@ -167,7 +203,7 @@ main(argc, argv)
* Create an environment object and initialize it for error
* reporting.
*/
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
+retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
goto shutdown;
@@ -177,29 +213,59 @@ main(argc, argv)
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
- if (nflag && (ret = dbenv->set_mutexlocks(dbenv, 0)) != 0) {
- dbenv->err(dbenv, ret, "set_mutexlocks");
+ if (nflag) {
+ if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
+ goto shutdown;
+ }
+ if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
+ goto shutdown;
+ }
+ }
+
+ if (passwd != NULL &&
+ (ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
goto shutdown;
}
/* Initialize the environment. */
- if (db_init(home, ttype) != 0)
+ if (db_init(dbenv, home, ttype, cache, &private) != 0)
goto shutdown;
switch (ttype) {
case T_DB:
/* Create the DB object and open the file. */
+ if (flags != 0)
+ return (usage());
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
goto shutdown;
}
+ d_close = 1;
- if ((ret =
- dbp->open(dbp, db, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
- dbp->err(dbp, ret, "open: %s", db);
+ if ((ret = dbp->open(dbp,
+ NULL, db, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
+ dbp->err(dbp, ret, "DB->open: %s", db);
goto shutdown;
}
+ /* Check if cache is too small for this DB's pagesize. */
+ if (private) {
+ if ((ret =
+ __db_util_cache(dbenv, dbp, &cache, &resize)) != 0)
+ goto shutdown;
+ if (resize) {
+ (void)dbp->close(dbp, 0);
+ d_close = 0;
+
+ (void)dbenv->close(dbenv, 0);
+ e_close = 0;
+ goto retry;
+ }
+ }
+
/*
* See if we can open this db read/write to update counts.
* If its a master-db then we cannot. So check to see,
@@ -207,9 +273,9 @@ main(argc, argv)
*/
checked = 0;
if (subdb == NULL && dbp->type == DB_BTREE) {
- if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) {
- dbp->err(dbp, ret, "dbp->stat");
- return (1);
+ if ((ret = dbp->stat(dbp, &sp, DB_FAST_STAT)) != 0) {
+ dbp->err(dbp, ret, "DB->stat");
+ goto shutdown;
}
checked = 1;
}
@@ -221,58 +287,68 @@ main(argc, argv)
dbenv->err(dbenv, ret, "db_create");
goto shutdown;
}
- if ((ret = dbp->open(alt_dbp,
- db, subdb, DB_UNKNOWN, 0, 0)) == 0) {
- (void)dbp->close(dbp, 0);
- dbp = alt_dbp;
+ if ((ret = dbp->open(alt_dbp, NULL,
+ db, subdb, DB_UNKNOWN, 0, 0)) != 0) {
+ dbenv->err(dbenv,
+ ret, "DB->open: %s:%s", db, subdb);
+ (void)alt_dbp->close(alt_dbp, 0);
+ goto shutdown;
}
+
+ (void)dbp->close(dbp, 0);
+ dbp = alt_dbp;
+
/* Need to run again to update counts */
checked = 0;
}
- d_close = 1;
switch (dbp->type) {
case DB_BTREE:
case DB_RECNO:
- if (btree_stats(dbenv, dbp, checked == 1 ? sp : NULL))
+ if (btree_stats(
+ dbenv, dbp, checked == 1 ? sp : NULL, fast))
goto shutdown;
break;
case DB_HASH:
- if (hash_stats(dbenv, dbp))
+ if (hash_stats(dbenv, dbp, fast))
goto shutdown;
break;
case DB_QUEUE:
- if (queue_stats(dbenv, dbp))
+ if (queue_stats(dbenv, dbp, fast))
goto shutdown;
break;
case DB_UNKNOWN:
- abort(); /* Impossible. */
- /* NOTREACHED */
+ dbenv->errx(dbenv, "Unknown database type.");
+ goto shutdown;
}
break;
case T_ENV:
- if (env_stats(dbenv))
- exitval = 1;
+ if (env_stats(dbenv, flags))
+ goto shutdown;
break;
case T_LOCK:
- if (lock_stats(dbenv))
- exitval = 1;
+ if (lock_stats(dbenv, internal, flags))
+ goto shutdown;
break;
case T_LOG:
- if (log_stats(dbenv))
- exitval = 1;
+ if (log_stats(dbenv, flags))
+ goto shutdown;
break;
case T_MPOOL:
- if (mpool_stats(dbenv))
- exitval = 1;
+ if (mpool_stats(dbenv, internal, flags))
+ goto shutdown;
+ break;
+ case T_REP:
+ if (rep_stats(dbenv, flags))
+ goto shutdown;
break;
case T_TXN:
- if (txn_stats(dbenv))
- exitval = 1;
+ if (txn_stats(dbenv, flags))
+ goto shutdown;
break;
case T_NOTSET:
- abort(); /* Impossible. */
- /* NOTREACHED */
+ dbenv->errx(dbenv, "Unknown statistics flag.");
+ goto shutdown;
}
if (0) {
@@ -280,7 +356,7 @@ shutdown: exitval = 1;
}
if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
exitval = 1;
- dbp->err(dbp, ret, "close");
+ dbenv->err(dbenv, ret, "close");
}
if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
@@ -291,7 +367,7 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
/*
@@ -299,8 +375,9 @@ shutdown: exitval = 1;
* Display environment statistics.
*/
int
-env_stats(dbenvp)
- DB_ENV *dbenvp;
+env_stats(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
{
REGENV renv;
REGION *rp, regs[1024];
@@ -308,15 +385,15 @@ env_stats(dbenvp)
const char *lable;
n = sizeof(regs) / sizeof(regs[0]);
- if ((ret = __db_e_stat(dbenvp, &renv, regs, &n)) != 0) {
- dbenvp->err(dbenvp, ret, "__db_e_stat");
+ if ((ret = __db_e_stat(dbenv, &renv, regs, &n, flags)) != 0) {
+ dbenv->err(dbenv, ret, "__db_e_stat");
return (1);
}
printf("%d.%d.%d\tEnvironment version.\n",
renv.majver, renv.minver, renv.patch);
printf("%lx\tMagic number.\n", (u_long)renv.magic);
- printf("%d\tPanic value.\n", renv.panic);
+ printf("%d\tPanic value.\n", renv.envpanic);
/* Adjust the reference count for us... */
printf("%d\tReferences.\n", renv.refcnt - 1);
@@ -370,10 +447,11 @@ env_stats(dbenvp)
* Display btree/recno statistics.
*/
int
-btree_stats(dbenvp, dbp, msp)
- DB_ENV *dbenvp;
+btree_stats(dbenv, dbp, msp, fast)
+ DB_ENV *dbenv;
DB *dbp;
DB_BTREE_STAT *msp;
+ int fast;
{
static const FN fn[] = {
{ BTM_DUP, "duplicates" },
@@ -387,12 +465,12 @@ btree_stats(dbenvp, dbp, msp)
DB_BTREE_STAT *sp;
int ret;
- COMPQUIET(dbenvp, NULL);
+ COMPQUIET(dbenv, NULL);
if (msp != NULL)
sp = msp;
- else if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) {
- dbp->err(dbp, ret, "dbp->stat");
+ else if ((ret = dbp->stat(dbp, &sp, fast)) != 0) {
+ dbp->err(dbp, ret, "DB->stat");
return (1);
}
@@ -447,6 +525,8 @@ btree_stats(dbenvp, dbp, msp)
dl("Number of pages on the free list.\n", (u_long)sp->bt_free);
+ free(sp);
+
return (0);
}
@@ -455,9 +535,10 @@ btree_stats(dbenvp, dbp, msp)
* Display hash statistics.
*/
int
-hash_stats(dbenvp, dbp)
- DB_ENV *dbenvp;
+hash_stats(dbenv, dbp, fast)
+ DB_ENV *dbenv;
DB *dbp;
+ int fast;
{
static const FN fn[] = {
{ DB_HASH_DUP, "duplicates" },
@@ -467,10 +548,10 @@ hash_stats(dbenvp, dbp)
DB_HASH_STAT *sp;
int ret;
- COMPQUIET(dbenvp, NULL);
+ COMPQUIET(dbenv, NULL);
- if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) {
- dbp->err(dbp, ret, "dbp->stat");
+ if ((ret = dbp->stat(dbp, &sp, fast)) != 0) {
+ dbp->err(dbp, ret, "DB->stat");
return (1);
}
@@ -478,6 +559,7 @@ hash_stats(dbenvp, dbp)
printf("%lu\tHash version number.\n", (u_long)sp->hash_version);
prflags(sp->hash_metaflags, fn);
dl("Underlying database page size.\n", (u_long)sp->hash_pagesize);
+ dl("Specified fill factor.\n", (u_long)sp->hash_ffactor);
dl("Number of keys in the database.\n", (u_long)sp->hash_nkeys);
dl("Number of data items in the database.\n", (u_long)sp->hash_ndata);
@@ -506,6 +588,8 @@ hash_stats(dbenvp, dbp)
dl("Number of pages on the free list.\n", (u_long)sp->hash_free);
+ free(sp);
+
return (0);
}
@@ -514,17 +598,18 @@ hash_stats(dbenvp, dbp)
* Display queue statistics.
*/
int
-queue_stats(dbenvp, dbp)
- DB_ENV *dbenvp;
+queue_stats(dbenv, dbp, fast)
+ DB_ENV *dbenv;
DB *dbp;
+ int fast;
{
DB_QUEUE_STAT *sp;
int ret;
- COMPQUIET(dbenvp, NULL);
+ COMPQUIET(dbenv, NULL);
- if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) {
- dbp->err(dbp, ret, "dbp->stat");
+ if ((ret = dbp->stat(dbp, &sp, fast)) != 0) {
+ dbp->err(dbp, ret, "DB->stat");
return (1);
}
@@ -536,6 +621,9 @@ queue_stats(dbenvp, dbp)
else
printf("0x%x\tFixed-length record pad.\n", (int)sp->qs_re_pad);
dl("Underlying database page size.\n", (u_long)sp->qs_pagesize);
+ if (sp->qs_extentsize != 0)
+ dl("Underlying database extent size.\n",
+ (u_long)sp->qs_extentsize);
dl("Number of records in the database.\n", (u_long)sp->qs_nkeys);
dl("Number of database pages.\n", (u_long)sp->qs_pages);
dl("Number of bytes free in database pages", (u_long)sp->qs_pgfree);
@@ -543,7 +631,9 @@ queue_stats(dbenvp, dbp)
PCT(sp->qs_pgfree, sp->qs_pages, sp->qs_pagesize));
printf("%lu\tFirst undeleted record.\n", (u_long)sp->qs_first_recno);
printf(
- "%lu\tLast allocated record number.\n", (u_long)sp->qs_cur_recno);
+ "%lu\tNext available record number.\n", (u_long)sp->qs_cur_recno);
+
+ free(sp);
return (0);
}
@@ -553,46 +643,68 @@ queue_stats(dbenvp, dbp)
* Display lock statistics.
*/
int
-lock_stats(dbenvp)
- DB_ENV *dbenvp;
+lock_stats(dbenv, internal, flags)
+ DB_ENV *dbenv;
+ char *internal;
+ u_int32_t flags;
{
DB_LOCK_STAT *sp;
int ret;
if (internal != NULL) {
- __lock_dump_region(dbenvp, internal, stdout);
+ if ((ret =
+ dbenv->lock_dump_region(dbenv, internal, stdout)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
+ return (1);
+ }
return (0);
}
- if ((ret = lock_stat(dbenvp, &sp, NULL)) != 0) {
- dbenvp->err(dbenvp, ret, NULL);
+ if ((ret = dbenv->lock_stat(dbenv, &sp, flags)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
return (1);
}
- dl("Last allocated locker ID.\n", (u_long)sp->st_lastid);
+ dl("Last allocated locker ID.\n", (u_long)sp->st_id);
+ dl("Current maximum unused locker ID.\n", (u_long)sp->st_cur_maxid);
dl("Number of lock modes.\n", (u_long)sp->st_nmodes);
dl("Maximum number of locks possible.\n", (u_long)sp->st_maxlocks);
dl("Maximum number of lockers possible.\n", (u_long)sp->st_maxlockers);
- dl("Maximum number of objects possible.\n", (u_long)sp->st_maxobjects);
- dl("Current locks.\n", (u_long)sp->st_nlocks);
- dl("Maximum number of locks so far.\n", (u_long)sp->st_maxnlocks);
- dl("Current number of lockers.\n", (u_long)sp->st_nlockers);
- dl("Maximum number lockers so far.\n", (u_long)sp->st_maxnlockers);
- dl("Current number lock objects.\n", (u_long)sp->st_nobjects);
- dl("Maximum number of lock objects so far.\n",
+ dl("Maximum number of lock objects possible.\n",
+ (u_long)sp->st_maxobjects);
+ dl("Number of current locks.\n", (u_long)sp->st_nlocks);
+ dl("Maximum number of locks at any one time.\n",
+ (u_long)sp->st_maxnlocks);
+ dl("Number of current lockers.\n", (u_long)sp->st_nlockers);
+ dl("Maximum number of lockers at any one time.\n",
+ (u_long)sp->st_maxnlockers);
+ dl("Number of current lock objects.\n", (u_long)sp->st_nobjects);
+ dl("Maximum number of lock objects at any one time.\n",
(u_long)sp->st_maxnobjects);
- dl("Number of lock requests.\n", (u_long)sp->st_nrequests);
- dl("Number of lock releases.\n", (u_long)sp->st_nreleases);
- dl("Number of lock requests that would have waited.\n",
+ dl("Total number of locks requested.\n", (u_long)sp->st_nrequests);
+ dl("Total number of locks released.\n", (u_long)sp->st_nreleases);
+ dl(
+ "Total number of lock requests failing because DB_LOCK_NOWAIT was set.\n",
(u_long)sp->st_nnowaits);
- dl("Number of lock conflicts.\n", (u_long)sp->st_nconflicts);
+ dl(
+ "Total number of locks not immediately available due to conflicts.\n",
+ (u_long)sp->st_nconflicts);
dl("Number of deadlocks.\n", (u_long)sp->st_ndeadlocks);
- dl_bytes("Lock region size",
+ dl("Lock timeout value.\n", (u_long)sp->st_locktimeout);
+ dl("Number of locks that have timed out.\n",
+ (u_long)sp->st_nlocktimeouts);
+ dl("Transaction timeout value.\n", (u_long)sp->st_txntimeout);
+ dl("Number of transactions that have timed out.\n",
+ (u_long)sp->st_ntxntimeouts);
+
+ dl_bytes("The size of the lock region.",
(u_long)0, (u_long)0, (u_long)sp->st_regsize);
- dl("The number of region locks granted without waiting.\n",
- (u_long)sp->st_region_nowait);
dl("The number of region locks granted after waiting.\n",
(u_long)sp->st_region_wait);
+ dl("The number of region locks granted without waiting.\n",
+ (u_long)sp->st_region_nowait);
+
+ free(sp);
return (0);
}
@@ -602,31 +714,32 @@ lock_stats(dbenvp)
* Display log statistics.
*/
int
-log_stats(dbenvp)
- DB_ENV *dbenvp;
+log_stats(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
{
DB_LOG_STAT *sp;
int ret;
- if ((ret = log_stat(dbenvp, &sp, NULL)) != 0) {
- dbenvp->err(dbenvp, ret, NULL);
+ if ((ret = dbenv->log_stat(dbenv, &sp, flags)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
return (1);
}
printf("%lx\tLog magic number.\n", (u_long)sp->st_magic);
printf("%lu\tLog version number.\n", (u_long)sp->st_version);
- dl_bytes("Log region size",
- (u_long)0, (u_long)0, (u_long)sp->st_regsize);
dl_bytes("Log record cache size",
(u_long)0, (u_long)0, (u_long)sp->st_lg_bsize);
printf("%#o\tLog file mode.\n", sp->st_mode);
- if (sp->st_lg_max % MEGABYTE == 0)
- printf("%luMb\tLog file size.\n",
- (u_long)sp->st_lg_max / MEGABYTE);
- else if (sp->st_lg_max % 1024 == 0)
- printf("%luKb\tLog file size.\n", (u_long)sp->st_lg_max / 1024);
+ if (sp->st_lg_size % MEGABYTE == 0)
+ printf("%luMb\tCurrent log file size.\n",
+ (u_long)sp->st_lg_size / MEGABYTE);
+ else if (sp->st_lg_size % 1024 == 0)
+ printf("%luKb\tCurrent log file size.\n",
+ (u_long)sp->st_lg_size / 1024);
else
- printf("%lu\tLog file size.\n", (u_long)sp->st_lg_max);
+ printf("%lu\tCurrent log file size.\n",
+ (u_long)sp->st_lg_size);
dl_bytes("Log bytes written",
(u_long)0, (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes);
dl_bytes("Log bytes written since last checkpoint",
@@ -637,10 +750,20 @@ log_stats(dbenvp)
dl("Total log file flushes.\n", (u_long)sp->st_scount);
printf("%lu\tCurrent log file number.\n", (u_long)sp->st_cur_file);
printf("%lu\tCurrent log file offset.\n", (u_long)sp->st_cur_offset);
- dl("The number of region locks granted without waiting.\n",
- (u_long)sp->st_region_nowait);
+ printf("%lu\tOn-disk log file number.\n", (u_long)sp->st_disk_file);
+ printf("%lu\tOn-disk log file offset.\n", (u_long)sp->st_disk_offset);
+
+ dl("Max commits in a log flush.\n", (u_long)sp->st_maxcommitperflush);
+ dl("Min commits in a log flush.\n", (u_long)sp->st_mincommitperflush);
+
+ dl_bytes("Log region size",
+ (u_long)0, (u_long)0, (u_long)sp->st_regsize);
dl("The number of region locks granted after waiting.\n",
(u_long)sp->st_region_wait);
+ dl("The number of region locks granted without waiting.\n",
+ (u_long)sp->st_region_nowait);
+
+ free(sp);
return (0);
}
@@ -650,34 +773,41 @@ log_stats(dbenvp)
* Display mpool statistics.
*/
int
-mpool_stats(dbenvp)
- DB_ENV *dbenvp;
+mpool_stats(dbenv, internal, flags)
+ DB_ENV *dbenv;
+ char *internal;
+ u_int32_t flags;
{
DB_MPOOL_FSTAT **fsp;
DB_MPOOL_STAT *gsp;
int ret;
if (internal != NULL) {
- __memp_dump_region(dbenvp, internal, stdout);
- return (1);
+ if ((ret =
+ dbenv->memp_dump_region(dbenv, internal, stdout)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
+ return (1);
+ }
+ return (0);
}
- if ((ret = memp_stat(dbenvp, &gsp, &fsp, NULL)) != 0) {
- dbenvp->err(dbenvp, ret, NULL);
+ if ((ret = dbenv->memp_stat(dbenv, &gsp, &fsp, flags)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
return (1);
}
dl_bytes("Total cache size",
(u_long)gsp->st_gbytes, (u_long)0, (u_long)gsp->st_bytes);
dl("Number of caches.\n", (u_long)gsp->st_ncache);
- dl("Pool individual cache size.\n", (u_long)gsp->st_regsize);
+ dl_bytes("Pool individual cache size",
+ (u_long)0, (u_long)0, (u_long)gsp->st_regsize);
+ dl("Requested pages mapped into the process' address space.\n",
+ (u_long)gsp->st_map);
dl("Requested pages found in the cache", (u_long)gsp->st_cache_hit);
if (gsp->st_cache_hit + gsp->st_cache_miss != 0)
printf(" (%.0f%%)", ((double)gsp->st_cache_hit /
(gsp->st_cache_hit + gsp->st_cache_miss)) * 100);
printf(".\n");
- dl("Requested pages mapped into the process' address space.\n",
- (u_long)gsp->st_map);
dl("Requested pages not found in the cache.\n",
(u_long)gsp->st_cache_miss);
dl("Pages created in the cache.\n", (u_long)gsp->st_page_create);
@@ -688,11 +818,13 @@ mpool_stats(dbenvp)
(u_long)gsp->st_ro_evict);
dl("Dirty pages forced from the cache.\n",
(u_long)gsp->st_rw_evict);
- dl("Dirty buffers written by trickle-sync thread.\n",
+ dl("Dirty pages written by trickle-sync thread.\n",
(u_long)gsp->st_page_trickle);
- dl("Current clean buffer count.\n",
+ dl("Current total page count.\n",
+ (u_long)gsp->st_pages);
+ dl("Current clean page count.\n",
(u_long)gsp->st_page_clean);
- dl("Current dirty buffer count.\n",
+ dl("Current dirty page count.\n",
(u_long)gsp->st_page_dirty);
dl("Number of hash buckets used for page location.\n",
(u_long)gsp->st_hash_buckets);
@@ -702,15 +834,33 @@ mpool_stats(dbenvp)
(u_long)gsp->st_hash_longest);
dl("Total number of hash buckets examined for page location.\n",
(u_long)gsp->st_hash_examined);
+ dl("The number of hash bucket locks granted without waiting.\n",
+ (u_long)gsp->st_hash_nowait);
+ dl("The number of hash bucket locks granted after waiting.\n",
+ (u_long)gsp->st_hash_wait);
+ dl("The maximum number of times any hash bucket lock was waited for.\n",
+ (u_long)gsp->st_hash_max_wait);
dl("The number of region locks granted without waiting.\n",
(u_long)gsp->st_region_nowait);
dl("The number of region locks granted after waiting.\n",
(u_long)gsp->st_region_wait);
+ dl("The number of page allocations.\n",
+ (u_long)gsp->st_alloc);
+ dl("The number of hash buckets examined during allocations\n",
+ (u_long)gsp->st_alloc_buckets);
+ dl("The max number of hash buckets examined for an allocation\n",
+ (u_long)gsp->st_alloc_max_buckets);
+ dl("The number of pages examined during allocations\n",
+ (u_long)gsp->st_alloc_pages);
+ dl("The max number of pages examined for an allocation\n",
+ (u_long)gsp->st_alloc_max_pages);
for (; fsp != NULL && *fsp != NULL; ++fsp) {
printf("%s\n", DB_LINE);
printf("Pool File: %s\n", (*fsp)->file_name);
dl("Page size.\n", (u_long)(*fsp)->st_pagesize);
+ dl("Requested pages mapped into the process' address space.\n",
+ (u_long)(*fsp)->st_map);
dl("Requested pages found in the cache",
(u_long)(*fsp)->st_cache_hit);
if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0)
@@ -718,8 +868,6 @@ mpool_stats(dbenvp)
((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) *
100);
printf(".\n");
- dl("Requested pages mapped into the process' address space.\n",
- (u_long)(*fsp)->st_map);
dl("Requested pages not found in the cache.\n",
(u_long)(*fsp)->st_cache_miss);
dl("Pages created in the cache.\n",
@@ -730,6 +878,123 @@ mpool_stats(dbenvp)
(u_long)(*fsp)->st_page_out);
}
+ free(gsp);
+
+ return (0);
+}
+
+/*
+ * rep_stats --
+ * Display replication statistics.
+ */
+int
+rep_stats(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ DB_REP_STAT *sp;
+ int is_client, ret;
+ const char *p;
+
+ if ((ret = dbenv->rep_stat(dbenv, &sp, flags)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
+ return (1);
+ }
+
+ is_client = 0;
+ switch (sp->st_status) {
+ case DB_REP_MASTER:
+ printf("Environment configured as a replication master.\n");
+ break;
+ case DB_REP_CLIENT:
+ printf("Environment configured as a replication client.\n");
+ is_client = 1;
+ break;
+ case DB_REP_LOGSONLY:
+ printf("Environment configured as a logs-only replica.\n");
+ is_client = 1;
+ break;
+ default:
+ printf("Environment not configured for replication.\n");
+ break;
+ }
+
+ printf("%lu/%lu\t%s\n",
+ (u_long)sp->st_next_lsn.file, (u_long)sp->st_next_lsn.offset,
+ is_client ? "Next LSN expected." : "Next LSN to be used.");
+ p = sp->st_waiting_lsn.file == 0 ?
+ "Not waiting for any missed log records." :
+ "LSN of first missed log record being waited for.";
+ printf("%lu/%lu\t%s\n",
+ (u_long)sp->st_waiting_lsn.file, (u_long)sp->st_waiting_lsn.offset,
+ p);
+
+ dl("Number of duplicate master conditions detected.\n",
+ (u_long)sp->st_dupmasters);
+ if (sp->st_env_id != DB_EID_INVALID)
+ dl("Current environment ID.\n", (u_long)sp->st_env_id);
+ else
+ printf("No current environment ID.\n");
+ dl("Current environment priority.\n", (u_long)sp->st_env_priority);
+ dl("Current generation number.\n", (u_long)sp->st_gen);
+ dl("Number of duplicate log records received.\n",
+ (u_long)sp->st_log_duplicated);
+ dl("Number of log records currently queued.\n",
+ (u_long)sp->st_log_queued);
+ dl("Maximum number of log records ever queued at once.\n",
+ (u_long)sp->st_log_queued_max);
+ dl("Total number of log records queued.\n",
+ (u_long)sp->st_log_queued_total);
+ dl("Number of log records received and appended to the log.\n",
+ (u_long)sp->st_log_records);
+ dl("Number of log records missed and requested.\n",
+ (u_long)sp->st_log_requested);
+ if (sp->st_master != DB_EID_INVALID)
+ dl("Current master ID.\n", (u_long)sp->st_master);
+ else
+ printf("No current master ID.\n");
+ dl("Number of times the master has changed.\n",
+ (u_long)sp->st_master_changes);
+ dl("Number of messages received with a bad generation number.\n",
+ (u_long)sp->st_msgs_badgen);
+ dl("Number of messages received and processed.\n",
+ (u_long)sp->st_msgs_processed);
+ dl("Number of messages ignored due to pending recovery.\n",
+ (u_long)sp->st_msgs_recover);
+ dl("Number of failed message sends.\n",
+ (u_long)sp->st_msgs_send_failures);
+ dl("Number of messages sent.\n", (u_long)sp->st_msgs_sent);
+ dl("Number of new site messages received.\n", (u_long)sp->st_newsites);
+ dl("Transmission limited.\n", (u_long)sp->st_nthrottles);
+ dl("Number of outdated conditions detected.\n",
+ (u_long)sp->st_outdated);
+ dl("Number of transactions applied.\n", (u_long)sp->st_txns_applied);
+
+ dl("Number of elections held.\n", (u_long)sp->st_elections);
+ dl("Number of elections won.\n", (u_long)sp->st_elections_won);
+
+ if (sp->st_election_status == 0)
+ printf("No election in progress.\n");
+ else {
+ dl("Current election phase.\n", (u_long)sp->st_election_status);
+ dl("Election winner.\n",
+ (u_long)sp->st_election_cur_winner);
+ dl("Election generation number.\n",
+ (u_long)sp->st_election_gen);
+ printf("%lu/%lu\tMaximum LSN of election winner.\n",
+ (u_long)sp->st_election_lsn.file,
+ (u_long)sp->st_election_lsn.offset);
+ dl("Number of sites expected to participate in elections.\n",
+ (u_long)sp->st_election_nsites);
+ dl("Election priority.\n", (u_long)sp->st_election_priority);
+ dl("Election tiebreaker value.\n",
+ (u_long)sp->st_election_tiebreaker);
+ dl("Votes received this election round.\n",
+ (u_long)sp->st_election_votes);
+ }
+
+ free(sp);
+
return (0);
}
@@ -738,16 +1003,17 @@ mpool_stats(dbenvp)
* Display transaction statistics.
*/
int
-txn_stats(dbenvp)
- DB_ENV *dbenvp;
+txn_stats(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
{
DB_TXN_STAT *sp;
u_int32_t i;
int ret;
const char *p;
- if ((ret = txn_stat(dbenvp, &sp, NULL)) != 0) {
- dbenvp->err(dbenvp, ret, NULL);
+ if ((ret = dbenv->txn_stat(dbenv, &sp, flags)) != 0) {
+ dbenv->err(dbenv, ret, NULL);
return (1);
}
@@ -755,12 +1021,6 @@ txn_stats(dbenvp)
"No checkpoint LSN." : "File/offset for last checkpoint LSN.";
printf("%lu/%lu\t%s\n",
(u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset, p);
- p = sp->st_pending_ckp.file == 0 ?
- "No pending checkpoint LSN." :
- "File/offset for last pending checkpoint LSN.";
- printf("%lu/%lu\t%s\n",
- (u_long)sp->st_pending_ckp.file,
- (u_long)sp->st_pending_ckp.offset, p);
if (sp->st_time_ckp == 0)
printf("0\tNo checkpoint timestamp.\n");
else
@@ -775,19 +1035,30 @@ txn_stats(dbenvp)
dl("Number of transactions begun.\n", (u_long)sp->st_nbegins);
dl("Number of transactions aborted.\n", (u_long)sp->st_naborts);
dl("Number of transactions committed.\n", (u_long)sp->st_ncommits);
+ dl("Number of transactions restored.\n", (u_long)sp->st_nrestores);
+
dl_bytes("Transaction region size",
(u_long)0, (u_long)0, (u_long)sp->st_regsize);
- dl("The number of region locks granted without waiting.\n",
- (u_long)sp->st_region_nowait);
dl("The number of region locks granted after waiting.\n",
(u_long)sp->st_region_wait);
+ dl("The number of region locks granted without waiting.\n",
+ (u_long)sp->st_region_nowait);
+
qsort(sp->st_txnarray,
sp->st_nactive, sizeof(sp->st_txnarray[0]), txn_compare);
- for (i = 0; i < sp->st_nactive; ++i)
- printf("\tid: %lx; initial LSN file/offest %lu/%lu\n",
+ for (i = 0; i < sp->st_nactive; ++i) {
+ printf("\tid: %lx; begin LSN: file/offset %lu/%lu",
(u_long)sp->st_txnarray[i].txnid,
(u_long)sp->st_txnarray[i].lsn.file,
(u_long)sp->st_txnarray[i].lsn.offset);
+ if (sp->st_txnarray[i].parentid == 0)
+ printf("\n");
+ else
+ printf(" parent: %lx\n",
+ (u_long)sp->st_txnarray[i].parentid);
+ }
+
+ free(sp);
return (0);
}
@@ -837,43 +1108,35 @@ dl_bytes(msg, gbytes, mbytes, bytes)
u_long gbytes, mbytes, bytes;
{
const char *sep;
- u_long sbytes;
- int showbytes;
- sbytes = bytes;
- while (bytes > MEGABYTE) {
+ /* Normalize the values. */
+ while (bytes >= MEGABYTE) {
++mbytes;
bytes -= MEGABYTE;
}
- while (mbytes > GIGABYTE / MEGABYTE) {
+ while (mbytes >= GIGABYTE / MEGABYTE) {
++gbytes;
- --mbytes;
+ mbytes -= GIGABYTE / MEGABYTE;
}
sep = "";
- showbytes = 0;
if (gbytes > 0) {
printf("%luGB", gbytes);
sep = " ";
- showbytes = 1;
}
if (mbytes > 0) {
printf("%s%luMB", sep, mbytes);
sep = " ";
- showbytes = 1;
}
- if (bytes > 1024) {
+ if (bytes >= 1024) {
printf("%s%luKB", sep, bytes / 1024);
bytes %= 1024;
sep = " ";
- showbytes = 1;
}
if (bytes > 0)
printf("%s%luB", sep, bytes);
- printf("\t%s", msg);
- if (showbytes)
- printf(" (%lu bytes)", sbytes);
- printf(".\n");
+
+ printf("\t%s.\n", msg);
}
/*
@@ -902,45 +1165,57 @@ prflags(flags, fnp)
* Initialize the environment.
*/
int
-db_init(home, ttype)
+db_init(dbenv, home, ttype, cache, is_private)
+ DB_ENV *dbenv;
char *home;
test_t ttype;
+ u_int32_t cache;
+ int *is_private;
{
+ u_int32_t oflags;
int ret;
/*
* If our environment open fails, and we're trying to look at a
* shared region, it's a hard failure.
+ *
+ * We will probably just drop core if the environment we join does
+ * not include a memory pool. This is probably acceptable; trying
+ * to use an existing environment that does not contain a memory
+ * pool to look at a database can be safely construed as operator
+ * error, I think.
*/
- if ((ret = dbenv->open(dbenv,
- home, DB_JOINENV | DB_USE_ENVIRON, 0)) == 0)
+ *is_private = 0;
+ if ((ret =
+ dbenv->open(dbenv, home, DB_JOINENV | DB_USE_ENVIRON, 0)) == 0)
return (0);
- if (ttype != T_DB) {
- dbenv->err(dbenv, ret, "DBENV->open%s%s",
+ if (ttype != T_DB && ttype != T_LOG) {
+ dbenv->err(dbenv, ret, "DB_ENV->open%s%s",
home == NULL ? "" : ": ", home == NULL ? "" : home);
return (1);
}
/*
- * We're trying to look at a database.
- *
- * An environment is required because we may be trying to look at
- * databases in directories other than the current one. We could
- * avoid using an environment iff the -h option wasn't specified,
- * but that seems like more work than it's worth.
- *
+ * We're looking at a database or set of log files and no environment
+ * exists. Create one, but make it private so no files are actually
+ * created. Declare a reasonably large cache so that we don't fail
+ * when reporting statistics on large databases.
*
- * No environment exists. Create one, but make it private so that
- * no files are actually created.
- *
- * Note that we will probably just drop core if the environment
- * we joined above does not include a memory pool. This is probably
- * acceptable; trying to use an existing shared environment that
- * does not contain a memory pool to look at a database can
- * be safely construed as operator error, I think.
+ * An environment is required to look at databases because we may be
+ * trying to look at databases in directories other than the current
+ * one.
*/
- if ((ret = dbenv->open(dbenv, home,
- DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0)
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_cachesize");
+ return (1);
+ }
+ *is_private = 1;
+ oflags = DB_CREATE | DB_PRIVATE | DB_USE_ENVIRON;
+ if (ttype == T_DB)
+ oflags |= DB_INIT_MPOOL;
+ if (ttype == T_LOG)
+ oflags |= DB_INIT_LOG;
+ if ((ret = dbenv->open(dbenv, home, oflags, 0)) == 0)
return (0);
/* An environment is required. */
@@ -963,16 +1238,18 @@ argcheck(arg, ok_args)
return (1);
}
-void
+int
usage()
{
- fprintf(stderr, "usage: db_stat %s\n",
- "[-celmNtV] [-C Acflmo] [-d file [-s file]] [-h home] [-M Ahlm]");
- exit (1);
+ fprintf(stderr, "%s\n\t%s\n",
+ "usage: db_stat [-celmNrtVZ] [-C Aclmop]",
+ "[-d file [-f] [-s database]] [-h home] [-M Ahlm] [-P password]");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -984,6 +1261,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_upgrade/db_upgrade.c b/bdb/db_upgrade/db_upgrade.c
index dc29b6c7e0c..f46b5eabc4e 100644
--- a/bdb/db_upgrade/db_upgrade.c
+++ b/bdb/db_upgrade/db_upgrade.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_upgrade.c,v 1.13 2001/01/18 18:36:59 bostic Exp $";
+ "$Id: db_upgrade.c,v 1.31 2002/03/28 20:13:47 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -25,12 +25,9 @@ static const char revid[] =
#include "db_int.h"
-int main __P((int, char *[]));
-void usage __P((void));
-void version_check __P((void));
-
-const char
- *progname = "db_upgrade"; /* Program name. */
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -39,30 +36,35 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
+ const char *progname = "db_upgrade";
DB *dbp;
DB_ENV *dbenv;
u_int32_t flags;
int ch, e_close, exitval, nflag, ret, t_ret;
- char *home;
+ char *home, *passwd;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
dbenv = NULL;
flags = nflag = 0;
e_close = exitval = 0;
- home = NULL;
- while ((ch = getopt(argc, argv, "h:NsV")) != EOF)
+ home = passwd = NULL;
+ while ((ch = getopt(argc, argv, "h:NP:sV")) != EOF)
switch (ch) {
case 'h':
home = optarg;
break;
case 'N':
nflag = 1;
- if ((ret = db_env_set_panicstate(0)) != 0) {
- fprintf(stderr,
- "%s: db_env_set_panicstate: %s\n",
- progname, db_strerror(ret));
- exit (1);
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
case 's':
@@ -70,16 +72,16 @@ main(argc, argv)
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc <= 0)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -98,8 +100,20 @@ main(argc, argv)
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
- if (nflag && (ret = dbenv->set_mutexlocks(dbenv, 0)) != 0) {
- dbenv->err(dbenv, ret, "set_mutexlocks");
+ if (nflag) {
+ if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
+ goto shutdown;
+ }
+ if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
+ goto shutdown;
+ }
+ }
+
+ if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
goto shutdown;
}
@@ -126,7 +140,7 @@ main(argc, argv)
if ((ret = dbp->upgrade(dbp, argv[0], flags)) != 0)
dbp->err(dbp, ret, "DB->upgrade: %s", argv[0]);
if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0) {
- dbp->err(dbp, ret, "DB->close: %s", argv[0]);
+ dbenv->err(dbenv, ret, "DB->close: %s", argv[0]);
ret = t_ret;
}
if (ret != 0)
@@ -145,18 +159,20 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage()
{
- fprintf(stderr, "usage: db_upgrade [-NsV] [-h home] db_file ...\n");
- exit (1);
+ fprintf(stderr, "%s\n",
+ "usage: db_upgrade [-NsV] [-h home] [-P password] db_file ...");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -168,6 +184,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/db_verify/db_verify.c b/bdb/db_verify/db_verify.c
index 3bbf14caac6..8d63a20e7bc 100644
--- a/bdb/db_verify/db_verify.c
+++ b/bdb/db_verify/db_verify.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_verify.c,v 1.15 2001/01/18 18:36:59 bostic Exp $";
+ "$Id: db_verify.c,v 1.38 2002/08/08 03:51:38 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -25,12 +25,9 @@ static const char revid[] =
#include "db_int.h"
-int main __P((int, char *[]));
-void usage __P((void));
-void version_check __P((void));
-
-const char
- *progname = "db_verify"; /* Program name. */
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((const char *));
int
main(argc, argv)
@@ -39,46 +36,56 @@ main(argc, argv)
{
extern char *optarg;
extern int optind;
- DB *dbp;
+ const char *progname = "db_verify";
+ DB *dbp, *dbp1;
DB_ENV *dbenv;
- int ch, e_close, exitval, nflag, quiet, ret, t_ret;
- char *home;
+ u_int32_t cache;
+ int ch, d_close, e_close, exitval, nflag, oflag, private;
+ int quiet, resize, ret, t_ret;
+ char *home, *passwd;
- version_check();
+ if ((ret = version_check(progname)) != 0)
+ return (ret);
dbenv = NULL;
- e_close = exitval = nflag = quiet = 0;
- home = NULL;
- while ((ch = getopt(argc, argv, "h:NqV")) != EOF)
+ cache = MEGABYTE;
+ d_close = e_close = exitval = nflag = oflag = quiet = 0;
+ home = passwd = NULL;
+ while ((ch = getopt(argc, argv, "h:NoP:qV")) != EOF)
switch (ch) {
case 'h':
home = optarg;
break;
case 'N':
nflag = 1;
- if ((ret = db_env_set_panicstate(0)) != 0) {
- fprintf(stderr,
- "%s: db_env_set_panicstate: %s\n",
- progname, db_strerror(ret));
- exit (1);
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
+ case 'o':
+ oflag = 1;
break;
case 'q':
quiet = 1;
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc <= 0)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -87,57 +94,108 @@ main(argc, argv)
* Create an environment object and initialize it for error
* reporting.
*/
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
- fprintf(stderr, "%s: db_env_create: %s\n",
- progname, db_strerror(ret));
+retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ fprintf(stderr,
+ "%s: db_env_create: %s\n", progname, db_strerror(ret));
goto shutdown;
}
e_close = 1;
- /*
- * XXX
- * We'd prefer to have error output configured while calling
- * db_env_create, but there's no way to turn it off once it's
- * turned on.
- */
if (!quiet) {
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
}
- if (nflag && (ret = dbenv->set_mutexlocks(dbenv, 0)) != 0) {
- dbenv->err(dbenv, ret, "set_mutexlocks");
- goto shutdown;
+ if (nflag) {
+ if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
+ goto shutdown;
+ }
+ if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
+ goto shutdown;
+ }
}
+ if (passwd != NULL &&
+ (ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ goto shutdown;
+ }
/*
- * Attach to an mpool if it exists, but if that fails, attach
- * to a private region.
+ * Attach to an mpool if it exists, but if that fails, attach to a
+ * private region. In the latter case, declare a reasonably large
+ * cache so that we don't fail when verifying large databases.
*/
- if ((ret = dbenv->open(dbenv,
- home, DB_INIT_MPOOL | DB_USE_ENVIRON, 0)) != 0 &&
- (ret = dbenv->open(dbenv, home,
+ private = 0;
+ if ((ret =
+ dbenv->open(dbenv, home, DB_INIT_MPOOL | DB_USE_ENVIRON, 0)) != 0) {
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_cachesize");
+ goto shutdown;
+ }
+ private = 1;
+ if ((ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
- dbenv->err(dbenv, ret, "open");
- goto shutdown;
+ dbenv->err(dbenv, ret, "open");
+ goto shutdown;
+ }
}
for (; !__db_util_interrupted() && argv[0] != NULL; ++argv) {
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
- fprintf(stderr,
- "%s: db_create: %s\n", progname, db_strerror(ret));
+ dbenv->err(dbenv, ret, "%s: db_create", progname);
goto shutdown;
}
- if (!quiet) {
- dbp->set_errfile(dbp, stderr);
- dbp->set_errpfx(dbp, progname);
+ d_close = 1;
+
+ /*
+ * We create a 2nd dbp to this database to get its pagesize
+ * because the dbp we're using for verify cannot be opened.
+ */
+ if (private) {
+ if ((ret = db_create(&dbp1, dbenv, 0)) != 0) {
+ dbenv->err(
+ dbenv, ret, "%s: db_create", progname);
+ goto shutdown;
+ }
+
+ if ((ret = dbp1->open(dbp1, NULL,
+ argv[0], NULL, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->open: %s", argv[0]);
+ (void)dbp1->close(dbp1, 0);
+ goto shutdown;
+ }
+ /*
+ * If we get here, we can check the cache/page.
+ * !!!
+ * If we have to retry with an env with a larger
+ * cache, we jump out of this loop. However, we
+ * will still be working on the same argv when we
+ * get back into the for-loop.
+ */
+ ret = __db_util_cache(dbenv, dbp1, &cache, &resize);
+ (void)dbp1->close(dbp1, 0);
+ if (ret != 0)
+ goto shutdown;
+
+ if (resize) {
+ (void)dbp->close(dbp, 0);
+ d_close = 0;
+
+ (void)dbenv->close(dbenv, 0);
+ e_close = 0;
+ goto retry;
+ }
}
- if ((ret = dbp->verify(dbp, argv[0], NULL, NULL, 0)) != 0)
+ if ((ret = dbp->verify(dbp,
+ argv[0], NULL, NULL, oflag ? DB_NOORDERCHK : 0)) != 0)
dbp->err(dbp, ret, "DB->verify: %s", argv[0]);
if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0) {
- dbp->err(dbp, ret, "DB->close: %s", argv[0]);
+ dbenv->err(dbenv, ret, "DB->close: %s", argv[0]);
ret = t_ret;
}
+ d_close = 0;
if (ret != 0)
goto shutdown;
}
@@ -145,6 +203,11 @@ main(argc, argv)
if (0) {
shutdown: exitval = 1;
}
+
+ if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
+ exitval = 1;
+ dbenv->err(dbenv, ret, "close");
+ }
if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
fprintf(stderr,
@@ -154,18 +217,20 @@ shutdown: exitval = 1;
/* Resend any caught signal. */
__db_util_sigresend();
- return (exitval);
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage()
{
- fprintf(stderr, "usage: db_verify [-NqV] [-h home] db_file ...\n");
- exit (1);
+ fprintf(stderr, "%s\n",
+ "usage: db_verify [-NoqV] [-h home] [-P password] db_file ...");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -177,6 +242,7 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
diff --git a/bdb/dbinc/btree.h b/bdb/dbinc/btree.h
new file mode 100644
index 00000000000..54da9c5b208
--- /dev/null
+++ b/bdb/dbinc/btree.h
@@ -0,0 +1,320 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: btree.h,v 11.45 2002/08/06 06:11:21 bostic Exp $
+ */
+#ifndef _DB_BTREE_H_
+#define _DB_BTREE_H_
+
+/* Forward structure declarations. */
+struct __btree; typedef struct __btree BTREE;
+struct __cursor; typedef struct __cursor BTREE_CURSOR;
+struct __epg; typedef struct __epg EPG;
+struct __recno; typedef struct __recno RECNO;
+
+#define DEFMINKEYPAGE (2)
+
+/*
+ * A recno order of 0 indicates that we don't have an order, not that we've
+ * an order less than 1.
+ */
+#define INVALID_ORDER 0
+
+#define ISINTERNAL(p) (TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO)
+#define ISLEAF(p) (TYPE(p) == P_LBTREE || \
+ TYPE(p) == P_LRECNO || TYPE(p) == P_LDUP)
+
+/* Flags for __bam_cadjust_log(). */
+#define CAD_UPDATEROOT 0x01 /* Root page count was updated. */
+
+/* Flags for __bam_split_log(). */
+#define SPL_NRECS 0x01 /* Split tree has record count. */
+
+/* Flags for __bam_iitem(). */
+#define BI_DELETED 0x01 /* Key/data pair only placeholder. */
+
+/* Flags for __bam_stkrel(). */
+#define STK_CLRDBC 0x01 /* Clear dbc->page reference. */
+#define STK_NOLOCK 0x02 /* Don't retain locks. */
+
+/* Flags for __ram_ca(). These get logged, so make the values explicit. */
+typedef enum {
+ CA_DELETE = 0, /* Delete the current record. */
+ CA_IAFTER = 1, /* Insert before the current record. */
+ CA_IBEFORE = 2, /* Insert after the current record. */
+ CA_ICURRENT = 3 /* Overwrite the current record. */
+} ca_recno_arg;
+
+/*
+ * Flags for __bam_search() and __bam_rsearch().
+ *
+ * Note, internal page searches must find the largest record less than key in
+ * the tree so that descents work. Leaf page searches must find the smallest
+ * record greater than key so that the returned index is the record's correct
+ * position for insertion.
+ *
+ * The flags parameter to the search routines describes three aspects of the
+ * search: the type of locking required (including if we're locking a pair of
+ * pages), the item to return in the presence of duplicates and whether or not
+ * to return deleted entries. To simplify both the mnemonic representation
+ * and the code that checks for various cases, we construct a set of bitmasks.
+ */
+#define S_READ 0x00001 /* Read locks. */
+#define S_WRITE 0x00002 /* Write locks. */
+
+#define S_APPEND 0x00040 /* Append to the tree. */
+#define S_DELNO 0x00080 /* Don't return deleted items. */
+#define S_DUPFIRST 0x00100 /* Return first duplicate. */
+#define S_DUPLAST 0x00200 /* Return last duplicate. */
+#define S_EXACT 0x00400 /* Exact items only. */
+#define S_PARENT 0x00800 /* Lock page pair. */
+#define S_STACK 0x01000 /* Need a complete stack. */
+#define S_PAST_EOF 0x02000 /* If doing insert search (or keyfirst
+ * or keylast operations), or a split
+ * on behalf of an insert, it's okay to
+ * return an entry one past end-of-page.
+ */
+#define S_STK_ONLY 0x04000 /* Just return info in the stack */
+
+#define S_DELETE (S_WRITE | S_DUPFIRST | S_DELNO | S_EXACT | S_STACK)
+#define S_FIND (S_READ | S_DUPFIRST | S_DELNO)
+#define S_FIND_WR (S_WRITE | S_DUPFIRST | S_DELNO)
+#define S_INSERT (S_WRITE | S_DUPLAST | S_PAST_EOF | S_STACK)
+#define S_KEYFIRST (S_WRITE | S_DUPFIRST | S_PAST_EOF | S_STACK)
+#define S_KEYLAST (S_WRITE | S_DUPLAST | S_PAST_EOF | S_STACK)
+#define S_WRPAIR (S_WRITE | S_DUPLAST | S_PAST_EOF | S_PARENT)
+
+/*
+ * Various routines pass around page references. A page reference is
+ * a pointer to the page, and the indx indicates an item on the page.
+ * Each page reference may include a lock.
+ */
+struct __epg {
+ PAGE *page; /* The page. */
+ db_indx_t indx; /* The index on the page. */
+ db_indx_t entries; /* The number of entries on page */
+ DB_LOCK lock; /* The page's lock. */
+ db_lockmode_t lock_mode; /* The lock mode. */
+};
+
+/*
+ * We maintain a stack of the pages that we're locking in the tree. Grow
+ * the stack as necessary.
+ *
+ * XXX
+ * Temporary fix for #3243 -- clear the page and lock from the stack entry.
+ * The correct fix is to never release a stack that doesn't hold items.
+ */
+#define BT_STK_CLR(c) do { \
+ (c)->csp = (c)->sp; \
+ (c)->csp->page = NULL; \
+ LOCK_INIT((c)->csp->lock); \
+} while (0)
+
+#define BT_STK_ENTER(dbenv, c, pagep, page_indx, l, mode, ret) do { \
+ if ((ret = \
+ (c)->csp == (c)->esp ? __bam_stkgrow(dbenv, c) : 0) == 0) { \
+ (c)->csp->page = pagep; \
+ (c)->csp->indx = page_indx; \
+ (c)->csp->entries = NUM_ENT(pagep); \
+ (c)->csp->lock = l; \
+ (c)->csp->lock_mode = mode; \
+ } \
+} while (0)
+
+#define BT_STK_PUSH(dbenv, c, pagep, page_indx, lock, mode, ret) do { \
+ BT_STK_ENTER(dbenv, c, pagep, page_indx, lock, mode, ret); \
+ ++(c)->csp; \
+} while (0)
+
+#define BT_STK_NUM(dbenv, c, pagep, page_indx, ret) do { \
+ if ((ret = \
+ (c)->csp == (c)->esp ? __bam_stkgrow(dbenv, c) : 0) == 0) { \
+ (c)->csp->page = NULL; \
+ (c)->csp->indx = page_indx; \
+ (c)->csp->entries = NUM_ENT(pagep); \
+ LOCK_INIT((c)->csp->lock); \
+ (c)->csp->lock_mode = DB_LOCK_NG; \
+ } \
+} while (0)
+
+#define BT_STK_NUMPUSH(dbenv, c, pagep, page_indx, ret) do { \
+ BT_STK_NUM(dbenv, cp, pagep, page_indx, ret); \
+ ++(c)->csp; \
+} while (0)
+
+#define BT_STK_POP(c) \
+ ((c)->csp == (c)->sp ? NULL : --(c)->csp)
+
+/* Btree/Recno cursor. */
+struct __cursor {
+ /* struct __dbc_internal */
+ __DBC_INTERNAL
+
+ /* btree private part */
+ EPG *sp; /* Stack pointer. */
+ EPG *csp; /* Current stack entry. */
+ EPG *esp; /* End stack pointer. */
+ EPG stack[5];
+
+ db_indx_t ovflsize; /* Maximum key/data on-page size. */
+
+ db_recno_t recno; /* Current record number. */
+ u_int32_t order; /* Relative order among deleted curs. */
+
+ /*
+ * Btree:
+ * We set a flag in the cursor structure if the underlying object has
+ * been deleted. It's not strictly necessary, we could get the same
+ * information by looking at the page itself, but this method doesn't
+ * require us to retrieve the page on cursor delete.
+ *
+ * Recno:
+ * When renumbering recno databases during deletes, cursors referencing
+ * "deleted" records end up positioned between two records, and so must
+ * be specially adjusted on the next operation.
+ */
+#define C_DELETED 0x0001 /* Record was deleted. */
+ /*
+ * There are three tree types that require maintaining record numbers.
+ * Recno AM trees, Btree AM trees for which the DB_RECNUM flag was set,
+ * and Btree off-page duplicate trees.
+ */
+#define C_RECNUM 0x0002 /* Tree requires record counts. */
+ /*
+ * Recno trees have immutable record numbers by default, but optionally
+ * support mutable record numbers. Off-page duplicate Recno trees have
+ * mutable record numbers. All Btrees with record numbers (including
+ * off-page duplicate trees) are mutable by design, no flag is needed.
+ */
+#define C_RENUMBER 0x0004 /* Tree records are mutable. */
+ u_int32_t flags;
+};
+
+/*
+ * Threshhold value, as a function of bt_minkey, of the number of
+ * bytes a key/data pair can use before being placed on an overflow
+ * page. Assume every item requires the maximum alignment for
+ * padding, out of sheer paranoia.
+ */
+#define B_MINKEY_TO_OVFLSIZE(dbp, minkey, pgsize) \
+ ((u_int16_t)(((pgsize) - P_OVERHEAD(dbp)) / ((minkey) * P_INDX) -\
+ (BKEYDATA_PSIZE(0) + ALIGN(1, sizeof(int32_t)))))
+
+/*
+ * The maximum space that a single item can ever take up on one page.
+ * Used by __bam_split to determine whether a split is still necessary.
+ */
+#define B_MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define B_MAXSIZEONPAGE(ovflsize) \
+ (B_MAX(BOVERFLOW_PSIZE, BKEYDATA_PSIZE(ovflsize)))
+
+/*
+ * The in-memory, per-tree btree/recno data structure.
+ */
+struct __btree { /* Btree access method. */
+ /*
+ * !!!
+ * These fields are write-once (when the structure is created) and
+ * so are ignored as far as multi-threading is concerned.
+ */
+ db_pgno_t bt_meta; /* Database meta-data page. */
+ db_pgno_t bt_root; /* Database root page. */
+
+ u_int32_t bt_maxkey; /* Maximum keys per page. */
+ u_int32_t bt_minkey; /* Minimum keys per page. */
+
+ /* Btree comparison function. */
+ int (*bt_compare) __P((DB *, const DBT *, const DBT *));
+ /* Btree prefix function. */
+ size_t (*bt_prefix) __P((DB *, const DBT *, const DBT *));
+
+ /* Recno access method. */
+ int re_pad; /* Fixed-length padding byte. */
+ int re_delim; /* Variable-length delimiting byte. */
+ u_int32_t re_len; /* Length for fixed-length records. */
+ char *re_source; /* Source file name. */
+
+ /*
+ * !!!
+ * The bt_lpgno field is NOT protected by any mutex, and for this
+ * reason must be advisory only, so, while it is read/written by
+ * multiple threads, DB is completely indifferent to the quality
+ * of its information.
+ */
+ db_pgno_t bt_lpgno; /* Last insert location. */
+
+ /*
+ * !!!
+ * The re_modified field is NOT protected by any mutex, and for this
+ * reason cannot be anything more complicated than a zero/non-zero
+ * value. The actual writing of the backing source file cannot be
+ * threaded, so clearing the flag isn't a problem.
+ */
+ int re_modified; /* If the tree was modified. */
+
+ /*
+ * !!!
+ * These fields are ignored as far as multi-threading is concerned.
+ * There are no transaction semantics associated with backing files,
+ * nor is there any thread protection.
+ */
+ FILE *re_fp; /* Source file handle. */
+ int re_eof; /* Backing source file EOF reached. */
+ db_recno_t re_last; /* Last record number read. */
+};
+
+/*
+ * Modes for the __bam_curadj recovery records (btree_curadj).
+ * These appear in log records, so we wire the values and
+ * do not leave it up to the compiler.
+ */
+typedef enum {
+ DB_CA_DI = 1,
+ DB_CA_DUP = 2,
+ DB_CA_RSPLIT = 3,
+ DB_CA_SPLIT = 4
+} db_ca_mode;
+
+#include "dbinc_auto/btree_auto.h"
+#include "dbinc_auto/btree_ext.h"
+#include "dbinc/db_am.h"
+#endif /* !_DB_BTREE_H_ */
diff --git a/bdb/dbinc/crypto.h b/bdb/dbinc/crypto.h
new file mode 100644
index 00000000000..92fad098a4a
--- /dev/null
+++ b/bdb/dbinc/crypto.h
@@ -0,0 +1,78 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: crypto.h,v 1.9 2002/08/06 06:37:07 bostic Exp $
+ */
+
+#ifndef _DB_CRYPTO_H_
+#define _DB_CRYPTO_H_
+
+/*
+ * !!!
+ * These are the internal representations of the algorithm flags.
+ * They are used in both the DB_CIPHER structure and the CIPHER
+ * structure so we can tell if users specified both passwd and alg
+ * correctly.
+ *
+ * CIPHER_ANY is used when an app joins an existing env but doesn't
+ * know the algorithm originally used. This is only valid in the
+ * DB_CIPHER structure until we open and can set the alg.
+ */
+/*
+ * We store the algorithm in an 8-bit field on the meta-page. So we
+ * use a numeric value, not bit fields.
+ * now we are limited to 8 algorithms before we cannot use bits and
+ * need numeric values. That should be plenty. It is okay for the
+ * CIPHER_ANY flag to go beyond that since that is never stored on disk.
+ */
+
+/*
+ * This structure is per-process, not in shared memory.
+ */
+struct __db_cipher {
+ int (*adj_size) __P((size_t));
+ int (*close) __P((DB_ENV *, void *));
+ int (*decrypt) __P((DB_ENV *, void *, void *, u_int8_t *, size_t));
+ int (*encrypt) __P((DB_ENV *, void *, void *, u_int8_t *, size_t));
+ int (*init) __P((DB_ENV *, DB_CIPHER *));
+
+ u_int8_t mac_key[DB_MAC_KEY]; /* MAC key. */
+ void *data; /* Algorithm-specific information */
+
+#define CIPHER_AES 1 /* AES algorithm */
+ u_int8_t alg; /* Algorithm used - See above */
+ u_int8_t spare[3]; /* Spares */
+
+#define CIPHER_ANY 0x00000001 /* Only for DB_CIPHER */
+ u_int32_t flags; /* Other flags */
+};
+
+#ifdef HAVE_CRYPTO
+
+#include "crypto/rijndael/rijndael-api-fst.h"
+
+/*
+ * Shared ciphering structure
+ * No DB_MUTEX needed because all information is read-only after creation.
+ */
+typedef struct __cipher {
+ roff_t passwd; /* Offset to shared passwd */
+ size_t passwd_len; /* Length of passwd */
+ u_int32_t flags; /* Algorithm used - see above */
+} CIPHER;
+
+#define DB_AES_KEYLEN 128 /* AES key length */
+#define DB_AES_CHUNK 16 /* AES byte unit size */
+
+typedef struct __aes_cipher {
+ keyInstance decrypt_ki; /* Decryption key instance */
+ keyInstance encrypt_ki; /* Encryption key instance */
+ u_int32_t flags; /* AES-specific flags */
+} AES_CIPHER;
+
+#include "dbinc_auto/crypto_ext.h"
+#endif /* HAVE_CRYPTO */
+#endif /* !_DB_CRYPTO_H_ */
diff --git a/bdb/dbinc/cxx_common.h b/bdb/dbinc/cxx_common.h
new file mode 100644
index 00000000000..e5cb3a9aef4
--- /dev/null
+++ b/bdb/dbinc/cxx_common.h
@@ -0,0 +1,45 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: cxx_common.h,v 11.2 2002/01/11 15:52:23 bostic Exp $
+ */
+
+#ifndef _CXX_COMMON_H_
+#define _CXX_COMMON_H_
+
+//
+// Common definitions used by all of Berkeley DB's C++ include files.
+//
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Mechanisms for declaring classes
+//
+
+//
+// Every class defined in this file has an _exported next to the class name.
+// This is needed for WinTel machines so that the class methods can
+// be exported or imported in a DLL as appropriate. Users of the DLL
+// use the define DB_USE_DLL. When the DLL is built, DB_CREATE_DLL
+// must be defined.
+//
+#if defined(_MSC_VER)
+
+# if defined(DB_CREATE_DLL)
+# define _exported __declspec(dllexport) // creator of dll
+# elif defined(DB_USE_DLL)
+# define _exported __declspec(dllimport) // user of dll
+# else
+# define _exported // static lib creator or user
+# endif
+
+#else /* _MSC_VER */
+
+# define _exported
+
+#endif /* _MSC_VER */
+#endif /* !_CXX_COMMON_H_ */
diff --git a/bdb/dbinc/cxx_except.h b/bdb/dbinc/cxx_except.h
new file mode 100644
index 00000000000..f9bf4f859f8
--- /dev/null
+++ b/bdb/dbinc/cxx_except.h
@@ -0,0 +1,141 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: cxx_except.h,v 11.5 2002/08/01 23:32:34 mjc Exp $
+ */
+
+#ifndef _CXX_EXCEPT_H_
+#define _CXX_EXCEPT_H_
+
+#include "cxx_common.h"
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Forward declarations
+//
+
+class DbDeadlockException; // forward
+class DbException; // forward
+class DbLockNotGrantedException; // forward
+class DbLock; // forward
+class DbMemoryException; // forward
+class DbRunRecoveryException; // forward
+class Dbt; // forward
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Exception classes
+//
+
+// Almost any error in the DB library throws a DbException.
+// Every exception should be considered an abnormality
+// (e.g. bug, misuse of DB, file system error).
+//
+// NOTE: We would like to inherit from class exception and
+// let it handle what(), but there are
+// MSVC++ problems when <exception> is included.
+//
+class _exported DbException
+{
+public:
+ virtual ~DbException();
+ DbException(int err);
+ DbException(const char *description);
+ DbException(const char *prefix, int err);
+ DbException(const char *prefix1, const char *prefix2, int err);
+ int get_errno() const;
+ virtual const char *what() const;
+
+ DbException(const DbException &);
+ DbException &operator = (const DbException &);
+
+private:
+ char *what_;
+ int err_; // errno
+};
+
+//
+// A specific sort of exception that occurs when
+// an operation is aborted to resolve a deadlock.
+//
+class _exported DbDeadlockException : public DbException
+{
+public:
+ virtual ~DbDeadlockException();
+ DbDeadlockException(const char *description);
+
+ DbDeadlockException(const DbDeadlockException &);
+ DbDeadlockException &operator = (const DbDeadlockException &);
+};
+
+//
+// A specific sort of exception that occurs when
+// a lock is not granted, e.g. by lock_get or lock_vec.
+// Note that the Dbt is only live as long as the Dbt used
+// in the offending call.
+//
+class _exported DbLockNotGrantedException : public DbException
+{
+public:
+ virtual ~DbLockNotGrantedException();
+ DbLockNotGrantedException(const char *prefix, db_lockop_t op,
+ db_lockmode_t mode, const Dbt *obj, const DbLock lock, int index);
+ DbLockNotGrantedException(const DbLockNotGrantedException &);
+ DbLockNotGrantedException &operator =
+ (const DbLockNotGrantedException &);
+
+ db_lockop_t get_op() const;
+ db_lockmode_t get_mode() const;
+ const Dbt* get_obj() const;
+ DbLock *get_lock() const;
+ int get_index() const;
+
+private:
+ db_lockop_t op_;
+ db_lockmode_t mode_;
+ const Dbt *obj_;
+ DbLock *lock_;
+ int index_;
+};
+
+//
+// A specific sort of exception that occurs when
+// user declared memory is insufficient in a Dbt.
+//
+class _exported DbMemoryException : public DbException
+{
+public:
+ virtual ~DbMemoryException();
+ DbMemoryException(Dbt *dbt);
+ DbMemoryException(const char *description);
+ DbMemoryException(const char *prefix, Dbt *dbt);
+ DbMemoryException(const char *prefix1, const char *prefix2, Dbt *dbt);
+ Dbt *get_dbt() const;
+
+ DbMemoryException(const DbMemoryException &);
+ DbMemoryException &operator = (const DbMemoryException &);
+
+private:
+ Dbt *dbt_;
+};
+
+//
+// A specific sort of exception that occurs when
+// recovery is required before continuing DB activity.
+//
+class _exported DbRunRecoveryException : public DbException
+{
+public:
+ virtual ~DbRunRecoveryException();
+ DbRunRecoveryException(const char *description);
+
+ DbRunRecoveryException(const DbRunRecoveryException &);
+ DbRunRecoveryException &operator = (const DbRunRecoveryException &);
+};
+
+#endif /* !_CXX_EXCEPT_H_ */
diff --git a/bdb/dbinc/cxx_int.h b/bdb/dbinc/cxx_int.h
new file mode 100644
index 00000000000..9af3979d9f1
--- /dev/null
+++ b/bdb/dbinc/cxx_int.h
@@ -0,0 +1,81 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: cxx_int.h,v 11.20 2002/01/11 15:52:23 bostic Exp $
+ */
+
+#ifndef _CXX_INT_H_
+#define _CXX_INT_H_
+
+// private data structures known to the implementation only
+
+//
+// Using FooImp classes will allow the implementation to change in the
+// future without any modification to user code or even to header files
+// that the user includes. FooImp * is just like void * except that it
+// provides a little extra protection, since you cannot randomly assign
+// any old pointer to a FooImp* as you can with void *. Currently, a
+// pointer to such an opaque class is always just a pointer to the
+// appropriate underlying implementation struct. These are converted
+// back and forth using the various overloaded wrap()/unwrap() methods.
+// This is essentially a use of the "Bridge" Design Pattern.
+//
+// WRAPPED_CLASS implements the appropriate wrap() and unwrap() methods
+// for a wrapper class that has an underlying pointer representation.
+//
+#define WRAPPED_CLASS(_WRAPPER_CLASS, _IMP_CLASS, _WRAPPED_TYPE) \
+ \
+ class _IMP_CLASS {}; \
+ \
+ inline _WRAPPED_TYPE unwrap(_WRAPPER_CLASS *val) \
+ { \
+ if (!val) return (0); \
+ return ((_WRAPPED_TYPE)((void *)(val->imp()))); \
+ } \
+ \
+ inline const _WRAPPED_TYPE unwrapConst(const _WRAPPER_CLASS *val) \
+ { \
+ if (!val) return (0); \
+ return ((const _WRAPPED_TYPE)((void *)(val->constimp()))); \
+ } \
+ \
+ inline _IMP_CLASS *wrap(_WRAPPED_TYPE val) \
+ { \
+ return ((_IMP_CLASS*)((void *)val)); \
+ }
+
+WRAPPED_CLASS(DbMpoolFile, DbMpoolFileImp, DB_MPOOLFILE*)
+WRAPPED_CLASS(Db, DbImp, DB*)
+WRAPPED_CLASS(DbEnv, DbEnvImp, DB_ENV*)
+WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN*)
+
+// A tristate integer value used by the DB_ERROR macro below.
+// We chose not to make this an enumerated type so it can
+// be kept private, even though methods that return the
+// tristate int can be declared in db_cxx.h .
+//
+#define ON_ERROR_THROW 1
+#define ON_ERROR_RETURN 0
+#define ON_ERROR_UNKNOWN (-1)
+
+// Macros that handle detected errors, in case we want to
+// change the default behavior. The 'policy' is one of
+// the tristate values given above. If UNKNOWN is specified,
+// the behavior is taken from the last initialized DbEnv.
+//
+#define DB_ERROR(caller, ecode, policy) \
+ DbEnv::runtime_error(caller, ecode, policy)
+
+#define DB_ERROR_DBT(caller, dbt, policy) \
+ DbEnv::runtime_error_dbt(caller, dbt, policy)
+
+#define DB_OVERFLOWED_DBT(dbt) \
+ (F_ISSET(dbt, DB_DBT_USERMEM) && dbt->size > dbt->ulen)
+
+/* values for Db::flags_ */
+#define DB_CXX_PRIVATE_ENV 0x00000001
+
+#endif /* !_CXX_INT_H_ */
diff --git a/bdb/dbinc/db.in b/bdb/dbinc/db.in
new file mode 100644
index 00000000000..208de3bd622
--- /dev/null
+++ b/bdb/dbinc/db.in
@@ -0,0 +1,1883 @@
+/*
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db.in,v 11.323 2002/09/03 17:27:16 bostic Exp $
+ *
+ * db.h include file layout:
+ * General.
+ * Database Environment.
+ * Locking subsystem.
+ * Logging subsystem.
+ * Shared buffer cache (mpool) subsystem.
+ * Transaction subsystem.
+ * Access methods.
+ * Access method cursors.
+ * Dbm/Ndbm, Hsearch historic interfaces.
+ */
+
+#ifndef _DB_H_
+#define _DB_H_
+
+#ifndef __NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdio.h>
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * XXX
+ * Handle function prototypes and the keyword "const". This steps on name
+ * space that DB doesn't control, but all of the other solutions are worse.
+ *
+ * XXX
+ * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
+ * defined by default, you specify a command line flag or #pragma to turn
+ * it on. Don't do that, however, because some of Microsoft's own header
+ * files won't compile.
+ */
+#undef __P
+#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
+#define __P(protos) protos /* ANSI C prototypes */
+#else
+#define const
+#define __P(protos) () /* K&R C preprocessor */
+#endif
+
+/*
+ * Berkeley DB version information.
+ */
+#define DB_VERSION_MAJOR @DB_VERSION_MAJOR@
+#define DB_VERSION_MINOR @DB_VERSION_MINOR@
+#define DB_VERSION_PATCH @DB_VERSION_PATCH@
+#define DB_VERSION_STRING @DB_VERSION_STRING@
+
+/*
+ * !!!
+ * Berkeley DB uses specifically sized types. If they're not provided by
+ * the system, typedef them here.
+ *
+ * We protect them against multiple inclusion using __BIT_TYPES_DEFINED__,
+ * as does BIND and Kerberos, since we don't know for sure what #include
+ * files the user is using.
+ *
+ * !!!
+ * We also provide the standard u_int, u_long etc., if they're not provided
+ * by the system.
+ */
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+@u_int8_decl@
+@int16_decl@
+@u_int16_decl@
+@int32_decl@
+@u_int32_decl@
+#endif
+
+@u_char_decl@
+@u_short_decl@
+@u_int_decl@
+@u_long_decl@
+@ssize_t_decl@
+
+/* Basic types that are exported or quasi-exported. */
+typedef u_int32_t db_pgno_t; /* Page number type. */
+typedef u_int16_t db_indx_t; /* Page offset type. */
+#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */
+
+typedef u_int32_t db_recno_t; /* Record number type. */
+#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */
+
+typedef u_int32_t db_timeout_t; /* Type of a timeout. */
+
+/*
+ * Region offsets are currently limited to 32-bits. I expect that's going
+ * to have to be fixed in the not-too-distant future, since we won't want to
+ * split 100Gb memory pools into that many different regions.
+ */
+typedef u_int32_t roff_t;
+
+/*
+ * Forward structure declarations, so we can declare pointers and
+ * applications can get type checking.
+ */
+struct __db; typedef struct __db DB;
+struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT;
+struct __db_cipher; typedef struct __db_cipher DB_CIPHER;
+struct __db_dbt; typedef struct __db_dbt DBT;
+struct __db_env; typedef struct __db_env DB_ENV;
+struct __db_h_stat; typedef struct __db_h_stat DB_HASH_STAT;
+struct __db_ilock; typedef struct __db_ilock DB_LOCK_ILOCK;
+struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
+struct __db_lock_u; typedef struct __db_lock_u DB_LOCK;
+struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
+struct __db_log_cursor; typedef struct __db_log_cursor DB_LOGC;
+struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
+struct __db_lsn; typedef struct __db_lsn DB_LSN;
+struct __db_mpool; typedef struct __db_mpool DB_MPOOL;
+struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
+struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
+struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
+struct __db_preplist; typedef struct __db_preplist DB_PREPLIST;
+struct __db_qam_stat; typedef struct __db_qam_stat DB_QUEUE_STAT;
+struct __db_rep; typedef struct __db_rep DB_REP;
+struct __db_rep_stat; typedef struct __db_rep_stat DB_REP_STAT;
+struct __db_txn; typedef struct __db_txn DB_TXN;
+struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE;
+struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT;
+struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR;
+struct __dbc; typedef struct __dbc DBC;
+struct __dbc_internal; typedef struct __dbc_internal DBC_INTERNAL;
+struct __fh_t; typedef struct __fh_t DB_FH;
+struct __fname; typedef struct __fname FNAME;
+struct __key_range; typedef struct __key_range DB_KEY_RANGE;
+struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
+struct __mutex_t; typedef struct __mutex_t DB_MUTEX;
+
+/* Key/data structure -- a Data-Base Thang. */
+struct __db_dbt {
+ /*
+ * data/size must be fields 1 and 2 for DB 1.85 compatibility.
+ */
+ void *data; /* Key/data */
+ u_int32_t size; /* key/data length */
+
+ u_int32_t ulen; /* RO: length of user buffer. */
+ u_int32_t dlen; /* RO: get/put record length. */
+ u_int32_t doff; /* RO: get/put record offset. */
+
+ void *app_private; /* Application-private handle. */
+
+#define DB_DBT_APPMALLOC 0x001 /* Callback allocated memory. */
+#define DB_DBT_ISSET 0x002 /* Lower level calls set value. */
+#define DB_DBT_MALLOC 0x004 /* Return in malloc'd memory. */
+#define DB_DBT_PARTIAL 0x008 /* Partial put/get. */
+#define DB_DBT_REALLOC 0x010 /* Return in realloc'd memory. */
+#define DB_DBT_USERMEM 0x020 /* Return in user's memory. */
+#define DB_DBT_DUPOK 0x040 /* Insert if duplicate. */
+ u_int32_t flags;
+};
+
+/*
+ * Common flags --
+ * Interfaces which use any of these common flags should never have
+ * interface specific flags in this range.
+ */
+#define DB_CREATE 0x000001 /* Create file as necessary. */
+#define DB_CXX_NO_EXCEPTIONS 0x000002 /* C++: return error values. */
+#define DB_FORCE 0x000004 /* Force (anything). */
+#define DB_NOMMAP 0x000008 /* Don't mmap underlying file. */
+#define DB_RDONLY 0x000010 /* Read-only (O_RDONLY). */
+#define DB_RECOVER 0x000020 /* Run normal recovery. */
+#define DB_THREAD 0x000040 /* Applications are threaded. */
+#define DB_TRUNCATE 0x000080 /* Discard existing DB (O_TRUNC). */
+#define DB_TXN_NOSYNC 0x000100 /* Do not sync log on commit. */
+#define DB_USE_ENVIRON 0x000200 /* Use the environment. */
+#define DB_USE_ENVIRON_ROOT 0x000400 /* Use the environment if root. */
+
+/*
+ * Common flags --
+ * Interfaces which use any of these common flags should never have
+ * interface specific flags in this range.
+ *
+ * DB_AUTO_COMMIT:
+ * DB_ENV->set_flags, DB->associate, DB->del, DB->put, DB->open,
+ * DB->remove, DB->rename, DB->truncate
+ * DB_DIRTY_READ:
+ * DB->cursor, DB->get, DB->join, DB->open, DBcursor->c_get,
+ * DB_ENV->txn_begin
+ *
+ * Shared flags up to 0x000400 */
+#define DB_AUTO_COMMIT 0x00800000 /* Implied transaction. */
+#define DB_DIRTY_READ 0x01000000 /* Dirty Read. */
+
+/*
+ * Flags private to db_env_create.
+ */
+#define DB_CLIENT 0x000001 /* Open for a client environment. */
+
+/*
+ * Flags private to db_create.
+ */
+#define DB_XA_CREATE 0x000001 /* Open in an XA environment. */
+
+/*
+ * Flags private to DB_ENV->open.
+ * Shared flags up to 0x000400 */
+#define DB_INIT_CDB 0x000800 /* Concurrent Access Methods. */
+#define DB_INIT_LOCK 0x001000 /* Initialize locking. */
+#define DB_INIT_LOG 0x002000 /* Initialize logging. */
+#define DB_INIT_MPOOL 0x004000 /* Initialize mpool. */
+#define DB_INIT_TXN 0x008000 /* Initialize transactions. */
+#define DB_JOINENV 0x010000 /* Initialize all subsystems present. */
+#define DB_LOCKDOWN 0x020000 /* Lock memory into physical core. */
+#define DB_PRIVATE 0x040000 /* DB_ENV is process local. */
+#define DB_RECOVER_FATAL 0x080000 /* Run catastrophic recovery. */
+#define DB_SYSTEM_MEM 0x100000 /* Use system-backed memory. */
+
+/*
+ * Flags private to DB->open.
+ * Shared flags up to 0x000400 */
+#define DB_EXCL 0x000800 /* Exclusive open (O_EXCL). */
+#define DB_FCNTL_LOCKING 0x001000 /* UNDOC: fcntl(2) locking. */
+#define DB_RDWRMASTER 0x002000 /* UNDOC: allow subdb master open R/W */
+#define DB_WRITEOPEN 0x004000 /* UNDOC: open with write lock. */
+
+/*
+ * Flags private to DB_ENV->txn_begin.
+ * Shared flags up to 0x000400 */
+#define DB_TXN_NOWAIT 0x000800 /* Do not wait for locks in this TXN. */
+#define DB_TXN_SYNC 0x001000 /* Always sync log on commit. */
+
+/*
+ * Flags private to DB_ENV->set_encrypt.
+ */
+#define DB_ENCRYPT_AES 0x000001 /* AES, assumes SHA1 checksum */
+
+/*
+ * Flags private to DB_ENV->set_flags.
+ * Shared flags up to 0x000400 */
+#define DB_CDB_ALLDB 0x000800 /* Set CDB locking per environment. */
+#define DB_DIRECT_DB 0x001000 /* Don't buffer databases in the OS. */
+#define DB_DIRECT_LOG 0x002000 /* Don't buffer log files in the OS. */
+#define DB_NOLOCKING 0x004000 /* Set locking/mutex behavior. */
+#define DB_NOPANIC 0x008000 /* Set panic state per DB_ENV. */
+#define DB_OVERWRITE 0x010000 /* Overwrite unlinked region files. */
+#define DB_PANIC_ENVIRONMENT 0x020000 /* Set panic state per environment. */
+#define DB_REGION_INIT 0x040000 /* Page-fault regions on open. */
+#define DB_TXN_WRITE_NOSYNC 0x080000 /* Write, don't sync, on txn commit. */
+#define DB_YIELDCPU 0x100000 /* Yield the CPU (a lot). */
+
+/*
+ * Flags private to DB->set_feedback's callback.
+ */
+#define DB_UPGRADE 0x000001 /* Upgrading. */
+#define DB_VERIFY 0x000002 /* Verifying. */
+
+/*
+ * Flags private to DB_MPOOLFILE->open.
+ * Shared flags up to 0x000400 */
+#define DB_DIRECT 0x000800 /* Don't buffer the file in the OS. */
+#define DB_EXTENT 0x001000 /* UNDOC: dealing with an extent. */
+#define DB_ODDFILESIZE 0x002000 /* Truncate file to N * pgsize. */
+
+/*
+ * Flags private to DB->set_flags.
+ */
+#define DB_CHKSUM_SHA1 0x000001 /* Use SHA1 checksumming */
+#define DB_DUP 0x000002 /* Btree, Hash: duplicate keys. */
+#define DB_DUPSORT 0x000004 /* Btree, Hash: duplicate keys. */
+#define DB_ENCRYPT 0x000008 /* Btree, Hash: duplicate keys. */
+#define DB_RECNUM 0x000010 /* Btree: record numbers. */
+#define DB_RENUMBER 0x000020 /* Recno: renumber on insert/delete. */
+#define DB_REVSPLITOFF 0x000040 /* Btree: turn off reverse splits. */
+#define DB_SNAPSHOT 0x000080 /* Recno: snapshot the input. */
+
+/*
+ * Flags private to the DB->stat methods.
+ */
+#define DB_STAT_CLEAR 0x000001 /* Clear stat after returning values. */
+
+/*
+ * Flags private to DB->join.
+ */
+#define DB_JOIN_NOSORT 0x000001 /* Don't try to optimize join. */
+
+/*
+ * Flags private to DB->verify.
+ */
+#define DB_AGGRESSIVE 0x000001 /* Salvage whatever could be data.*/
+#define DB_NOORDERCHK 0x000002 /* Skip sort order/hashing check. */
+#define DB_ORDERCHKONLY 0x000004 /* Only perform the order check. */
+#define DB_PR_PAGE 0x000008 /* Show page contents (-da). */
+#define DB_PR_RECOVERYTEST 0x000010 /* Recovery test (-dr). */
+#define DB_PRINTABLE 0x000020 /* Use printable format for salvage. */
+#define DB_SALVAGE 0x000040 /* Salvage what looks like data. */
+/*
+ * !!!
+ * These must not go over 0x8000, or they will collide with the flags
+ * used by __bam_vrfy_subtree.
+ */
+
+/*
+ * Flags private to DB->set_rep_transport's send callback.
+ */
+#define DB_REP_PERMANENT 0x0001 /* Important--app. may want to flush. */
+
+/*******************************************************
+ * Locking.
+ *******************************************************/
+#define DB_LOCKVERSION 1
+
+#define DB_FILE_ID_LEN 20 /* Unique file ID length. */
+
+/*
+ * Deadlock detector modes; used in the DB_ENV structure to configure the
+ * locking subsystem.
+ */
+#define DB_LOCK_NORUN 0
+#define DB_LOCK_DEFAULT 1 /* Default policy. */
+#define DB_LOCK_EXPIRE 2 /* Only expire locks, no detection. */
+#define DB_LOCK_MAXLOCKS 3 /* Abort txn with maximum # of locks. */
+#define DB_LOCK_MINLOCKS 4 /* Abort txn with minimum # of locks. */
+#define DB_LOCK_MINWRITE 5 /* Abort txn with minimum writelocks. */
+#define DB_LOCK_OLDEST 6 /* Abort oldest transaction. */
+#define DB_LOCK_RANDOM 7 /* Abort random transaction. */
+#define DB_LOCK_YOUNGEST 8 /* Abort youngest transaction. */
+
+/* Flag values for lock_vec(), lock_get(). */
+#define DB_LOCK_FREE_LOCKER 0x001 /* Internal: Free locker as well. */
+#define DB_LOCK_NOWAIT 0x002 /* Don't wait on unavailable lock. */
+#define DB_LOCK_RECORD 0x004 /* Internal: record lock. */
+#define DB_LOCK_REMOVE 0x008 /* Internal: flag object removed. */
+#define DB_LOCK_SET_TIMEOUT 0x010 /* Internal: set lock timeout. */
+#define DB_LOCK_SWITCH 0x020 /* Internal: switch existing lock. */
+#define DB_LOCK_UPGRADE 0x040 /* Internal: upgrade existing lock. */
+
+/*
+ * Simple R/W lock modes and for multi-granularity intention locking.
+ *
+ * !!!
+ * These values are NOT random, as they are used as an index into the lock
+ * conflicts arrays, i.e., DB_LOCK_IWRITE must be == 3, and DB_LOCK_IREAD
+ * must be == 4.
+ */
+typedef enum {
+ DB_LOCK_NG=0, /* Not granted. */
+ DB_LOCK_READ=1, /* Shared/read. */
+ DB_LOCK_WRITE=2, /* Exclusive/write. */
+ DB_LOCK_WAIT=3, /* Wait for event */
+ DB_LOCK_IWRITE=4, /* Intent exclusive/write. */
+ DB_LOCK_IREAD=5, /* Intent to share/read. */
+ DB_LOCK_IWR=6, /* Intent to read and write. */
+ DB_LOCK_DIRTY=7, /* Dirty Read. */
+ DB_LOCK_WWRITE=8 /* Was Written. */
+} db_lockmode_t;
+
+/*
+ * Request types.
+ */
+typedef enum {
+ DB_LOCK_DUMP=0, /* Display held locks. */
+ DB_LOCK_GET=1, /* Get the lock. */
+ DB_LOCK_GET_TIMEOUT=2, /* Get lock with a timeout. */
+ DB_LOCK_INHERIT=3, /* Pass locks to parent. */
+ DB_LOCK_PUT=4, /* Release the lock. */
+ DB_LOCK_PUT_ALL=5, /* Release locker's locks. */
+ DB_LOCK_PUT_OBJ=6, /* Release locker's locks on obj. */
+ DB_LOCK_PUT_READ=7, /* Release locker's read locks. */
+ DB_LOCK_TIMEOUT=8, /* Force a txn to timeout. */
+ DB_LOCK_TRADE=9, /* Trade locker ids on a lock. */
+ DB_LOCK_UPGRADE_WRITE=10 /* Upgrade writes for dirty reads. */
+} db_lockop_t;
+
+/*
+ * Status of a lock.
+ */
+typedef enum {
+ DB_LSTAT_ABORTED=1, /* Lock belongs to an aborted txn. */
+ DB_LSTAT_ERR=2, /* Lock is bad. */
+ DB_LSTAT_EXPIRED=3, /* Lock has expired. */
+ DB_LSTAT_FREE=4, /* Lock is unallocated. */
+ DB_LSTAT_HELD=5, /* Lock is currently held. */
+ DB_LSTAT_NOTEXIST=6, /* Object on which lock was waiting
+ * was removed */
+ DB_LSTAT_PENDING=7, /* Lock was waiting and has been
+ * promoted; waiting for the owner
+ * to run and upgrade it to held. */
+ DB_LSTAT_WAITING=8 /* Lock is on the wait queue. */
+}db_status_t;
+
+/* Lock statistics structure. */
+struct __db_lock_stat {
+ u_int32_t st_id; /* Last allocated locker ID. */
+ u_int32_t st_cur_maxid; /* Current maximum unused ID. */
+ u_int32_t st_maxlocks; /* Maximum number of locks in table. */
+ u_int32_t st_maxlockers; /* Maximum num of lockers in table. */
+ u_int32_t st_maxobjects; /* Maximum num of objects in table. */
+ u_int32_t st_nmodes; /* Number of lock modes. */
+ u_int32_t st_nlocks; /* Current number of locks. */
+ u_int32_t st_maxnlocks; /* Maximum number of locks so far. */
+ u_int32_t st_nlockers; /* Current number of lockers. */
+ u_int32_t st_maxnlockers; /* Maximum number of lockers so far. */
+ u_int32_t st_nobjects; /* Current number of objects. */
+ u_int32_t st_maxnobjects; /* Maximum number of objects so far. */
+ u_int32_t st_nconflicts; /* Number of lock conflicts. */
+ u_int32_t st_nrequests; /* Number of lock gets. */
+ u_int32_t st_nreleases; /* Number of lock puts. */
+ u_int32_t st_nnowaits; /* Number of requests that would have
+ waited, but NOWAIT was set. */
+ u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */
+ db_timeout_t st_locktimeout; /* Lock timeout. */
+ u_int32_t st_nlocktimeouts; /* Number of lock timeouts. */
+ db_timeout_t st_txntimeout; /* Transaction timeout. */
+ u_int32_t st_ntxntimeouts; /* Number of transaction timeouts. */
+ u_int32_t st_region_wait; /* Region lock granted after wait. */
+ u_int32_t st_region_nowait; /* Region lock granted without wait. */
+ u_int32_t st_regsize; /* Region size. */
+};
+
+/*
+ * DB_LOCK_ILOCK --
+ * Internal DB access method lock.
+ */
+struct __db_ilock {
+ db_pgno_t pgno; /* Page being locked. */
+ u_int8_t fileid[DB_FILE_ID_LEN];/* File id. */
+#define DB_HANDLE_LOCK 1
+#define DB_RECORD_LOCK 2
+#define DB_PAGE_LOCK 3
+#define DB_TXN_LOCK 4
+ u_int32_t type; /* Type of lock. */
+};
+
+/*
+ * DB_LOCK --
+ * The structure is allocated by the caller and filled in during a
+ * lock_get request (or a lock_vec/DB_LOCK_GET).
+ */
+struct __db_lock_u {
+ size_t off; /* Offset of the lock in the region */
+ u_int32_t ndx; /* Index of the object referenced by
+ * this lock; used for locking. */
+ u_int32_t gen; /* Generation number of this lock. */
+ db_lockmode_t mode; /* mode of this lock. */
+};
+
+/* Lock request structure. */
+struct __db_lockreq {
+ db_lockop_t op; /* Operation. */
+ db_lockmode_t mode; /* Requested mode. */
+ db_timeout_t timeout; /* Time to expire lock. */
+ DBT *obj; /* Object being locked. */
+ DB_LOCK lock; /* Lock returned. */
+};
+
+/*******************************************************
+ * Logging.
+ *******************************************************/
+#define DB_LOGVERSION 7 /* Current log version. */
+#define DB_LOGOLDVER 7 /* Oldest log version supported. */
+#define DB_LOGMAGIC 0x040988
+
+/* Flag values for log_archive(). */
+#define DB_ARCH_ABS 0x001 /* Absolute pathnames. */
+#define DB_ARCH_DATA 0x002 /* Data files. */
+#define DB_ARCH_LOG 0x004 /* Log files. */
+
+/*
+ * A DB_LSN has two parts, a fileid which identifies a specific file, and an
+ * offset within that file. The fileid is an unsigned 4-byte quantity that
+ * uniquely identifies a file within the log directory -- currently a simple
+ * counter inside the log. The offset is also an unsigned 4-byte value. The
+ * log manager guarantees the offset is never more than 4 bytes by switching
+ * to a new log file before the maximum length imposed by an unsigned 4-byte
+ * offset is reached.
+ */
+struct __db_lsn {
+ u_int32_t file; /* File ID. */
+ u_int32_t offset; /* File offset. */
+};
+
+/*
+ * DB_LOGC --
+ * Log cursor.
+ */
+struct __db_log_cursor {
+ DB_ENV *dbenv; /* Enclosing dbenv. */
+
+ DB_FH *c_fh; /* File handle. */
+ DB_LSN c_lsn; /* Cursor: LSN */
+ u_int32_t c_len; /* Cursor: record length */
+ u_int32_t c_prev; /* Cursor: previous record's offset */
+
+ DBT c_dbt; /* Return DBT. */
+
+#define DB_LOGC_BUF_SIZE (32 * 1024)
+ u_int8_t *bp; /* Allocated read buffer. */
+ u_int32_t bp_size; /* Read buffer length in bytes. */
+ u_int32_t bp_rlen; /* Read buffer valid data length. */
+ DB_LSN bp_lsn; /* Read buffer first byte LSN. */
+
+ u_int32_t bp_maxrec; /* Max record length in the log file. */
+
+ /* Methods. */
+ int (*close) __P((DB_LOGC *, u_int32_t));
+ int (*get) __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
+
+#define DB_LOG_DISK 0x01 /* Log record came from disk. */
+#define DB_LOG_LOCKED 0x02 /* Log region already locked */
+#define DB_LOG_SILENT_ERR 0x04 /* Turn-off error messages. */
+ u_int32_t flags;
+};
+
+/* Log statistics structure. */
+struct __db_log_stat {
+ u_int32_t st_magic; /* Log file magic number. */
+ u_int32_t st_version; /* Log file version number. */
+ int st_mode; /* Log file mode. */
+ u_int32_t st_lg_bsize; /* Log buffer size. */
+ u_int32_t st_lg_size; /* Log file size. */
+ u_int32_t st_w_bytes; /* Bytes to log. */
+ u_int32_t st_w_mbytes; /* Megabytes to log. */
+ u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */
+ u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */
+ u_int32_t st_wcount; /* Total writes to the log. */
+ u_int32_t st_wcount_fill; /* Overflow writes to the log. */
+ u_int32_t st_scount; /* Total syncs to the log. */
+ u_int32_t st_region_wait; /* Region lock granted after wait. */
+ u_int32_t st_region_nowait; /* Region lock granted without wait. */
+ u_int32_t st_cur_file; /* Current log file number. */
+ u_int32_t st_cur_offset; /* Current log file offset. */
+ u_int32_t st_disk_file; /* Known on disk log file number. */
+ u_int32_t st_disk_offset; /* Known on disk log file offset. */
+ u_int32_t st_regsize; /* Region size. */
+ u_int32_t st_maxcommitperflush; /* Max number of commits in a flush. */
+ u_int32_t st_mincommitperflush; /* Min number of commits in a flush. */
+};
+
+/*******************************************************
+ * Shared buffer cache (mpool).
+ *******************************************************/
+/* Flag values for DB_MPOOLFILE->get. */
+#define DB_MPOOL_CREATE 0x001 /* Create a page. */
+#define DB_MPOOL_LAST 0x002 /* Return the last page. */
+#define DB_MPOOL_NEW 0x004 /* Create a new page. */
+
+/* Flag values for DB_MPOOLFILE->put, DB_MPOOLFILE->set. */
+#define DB_MPOOL_CLEAN 0x001 /* Page is not modified. */
+#define DB_MPOOL_DIRTY 0x002 /* Page is modified. */
+#define DB_MPOOL_DISCARD 0x004 /* Don't cache the page. */
+
+/* Priority values for DB_MPOOLFILE->set_priority. */
+typedef enum {
+ DB_PRIORITY_VERY_LOW=1,
+ DB_PRIORITY_LOW=2,
+ DB_PRIORITY_DEFAULT=3,
+ DB_PRIORITY_HIGH=4,
+ DB_PRIORITY_VERY_HIGH=5
+} DB_CACHE_PRIORITY;
+
+/* Per-process DB_MPOOLFILE information. */
+struct __db_mpoolfile {
+ /* These fields need to be protected for multi-threaded support. */
+ DB_MUTEX *mutexp; /* Structure thread lock. */
+
+ DB_FH *fhp; /* Underlying file handle. */
+
+ u_int32_t ref; /* Reference count. */
+
+ /*
+ * !!!
+ * The pinref and q fields are protected by the region lock, not the
+ * DB_MPOOLFILE structure mutex. We don't use the structure mutex
+ * because then I/O (which holds the structure lock held because of
+ * the race between the seek and write of the file descriptor) would
+ * block any other put/get calls using this DB_MPOOLFILE structure.
+ */
+ u_int32_t pinref; /* Pinned block reference count. */
+
+ /*
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_ENTRY(__db_mpoolfile) q;
+ */
+ struct {
+ struct __db_mpoolfile *tqe_next;
+ struct __db_mpoolfile **tqe_prev;
+ } q; /* Linked list of DB_MPOOLFILE's. */
+
+ /*
+ * These fields are not thread-protected because they are initialized
+ * when the file is opened and never modified.
+ */
+ int ftype; /* File type. */
+ DBT *pgcookie; /* Byte-string passed to pgin/pgout. */
+ u_int8_t *fileid; /* Unique file ID. */
+ int32_t lsn_offset; /* LSN offset in page. */
+ u_int32_t clear_len; /* Cleared length on created pages. */
+
+ DB_MPOOL *dbmp; /* Overlying DB_MPOOL. */
+ MPOOLFILE *mfp; /* Underlying MPOOLFILE. */
+
+ void *addr; /* Address of mmap'd region. */
+ size_t len; /* Length of mmap'd region. */
+
+ /* Methods. */
+ int (*close) __P((DB_MPOOLFILE *, u_int32_t));
+ int (*get) __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
+ void (*get_fileid) __P((DB_MPOOLFILE *, u_int8_t *));
+ void (*last_pgno) __P((DB_MPOOLFILE *, db_pgno_t *));
+ int (*open)__P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t));
+ int (*put) __P((DB_MPOOLFILE *, void *, u_int32_t));
+ void (*refcnt) __P((DB_MPOOLFILE *, db_pgno_t *));
+ int (*set) __P((DB_MPOOLFILE *, void *, u_int32_t));
+ int (*set_clear_len) __P((DB_MPOOLFILE *, u_int32_t));
+ int (*set_fileid) __P((DB_MPOOLFILE *, u_int8_t *));
+ int (*set_ftype) __P((DB_MPOOLFILE *, int));
+ int (*set_lsn_offset) __P((DB_MPOOLFILE *, int32_t));
+ int (*set_pgcookie) __P((DB_MPOOLFILE *, DBT *));
+ int (*set_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY));
+ void (*set_unlink) __P((DB_MPOOLFILE *, int));
+ int (*sync) __P((DB_MPOOLFILE *));
+
+ /*
+ * MP_OPEN_CALLED and MP_READONLY do not need to be thread protected
+ * because they are initialized when the file is opened, and never
+ * modified.
+ *
+ * MP_FLUSH, MP_UPGRADE and MP_UPGRADE_FAIL are thread protected
+ * becase they are potentially read by multiple threads of control.
+ */
+#define MP_FLUSH 0x001 /* Was opened to flush a buffer. */
+#define MP_OPEN_CALLED 0x002 /* File opened. */
+#define MP_READONLY 0x004 /* File is readonly. */
+#define MP_UPGRADE 0x008 /* File descriptor is readwrite. */
+#define MP_UPGRADE_FAIL 0x010 /* Upgrade wasn't possible. */
+ u_int32_t flags;
+};
+
+/*
+ * Mpool statistics structure.
+ */
+struct __db_mpool_stat {
+ u_int32_t st_gbytes; /* Total cache size: GB. */
+ u_int32_t st_bytes; /* Total cache size: B. */
+ u_int32_t st_ncache; /* Number of caches. */
+ u_int32_t st_regsize; /* Cache size. */
+ u_int32_t st_map; /* Pages from mapped files. */
+ u_int32_t st_cache_hit; /* Pages found in the cache. */
+ u_int32_t st_cache_miss; /* Pages not found in the cache. */
+ u_int32_t st_page_create; /* Pages created in the cache. */
+ u_int32_t st_page_in; /* Pages read in. */
+ u_int32_t st_page_out; /* Pages written out. */
+ u_int32_t st_ro_evict; /* Clean pages forced from the cache. */
+ u_int32_t st_rw_evict; /* Dirty pages forced from the cache. */
+ u_int32_t st_page_trickle; /* Pages written by memp_trickle. */
+ u_int32_t st_pages; /* Total number of pages. */
+ u_int32_t st_page_clean; /* Clean pages. */
+ u_int32_t st_page_dirty; /* Dirty pages. */
+ u_int32_t st_hash_buckets; /* Number of hash buckets. */
+ u_int32_t st_hash_searches; /* Total hash chain searches. */
+ u_int32_t st_hash_longest; /* Longest hash chain searched. */
+ u_int32_t st_hash_examined; /* Total hash entries searched. */
+ u_int32_t st_hash_nowait; /* Hash lock granted with nowait. */
+ u_int32_t st_hash_wait; /* Hash lock granted after wait. */
+ u_int32_t st_hash_max_wait; /* Max hash lock granted after wait. */
+ u_int32_t st_region_nowait; /* Region lock granted with nowait. */
+ u_int32_t st_region_wait; /* Region lock granted after wait. */
+ u_int32_t st_alloc; /* Number of page allocations. */
+ u_int32_t st_alloc_buckets; /* Buckets checked during allocation. */
+ u_int32_t st_alloc_max_buckets; /* Max checked during allocation. */
+ u_int32_t st_alloc_pages; /* Pages checked during allocation. */
+ u_int32_t st_alloc_max_pages; /* Max checked during allocation. */
+};
+
+/* Mpool file statistics structure. */
+struct __db_mpool_fstat {
+ char *file_name; /* File name. */
+ size_t st_pagesize; /* Page size. */
+ u_int32_t st_map; /* Pages from mapped files. */
+ u_int32_t st_cache_hit; /* Pages found in the cache. */
+ u_int32_t st_cache_miss; /* Pages not found in the cache. */
+ u_int32_t st_page_create; /* Pages created in the cache. */
+ u_int32_t st_page_in; /* Pages read in. */
+ u_int32_t st_page_out; /* Pages written out. */
+};
+
+/*******************************************************
+ * Transactions and recovery.
+ *******************************************************/
+#define DB_TXNVERSION 1
+
+typedef enum {
+ DB_TXN_ABORT=0, /* Public. */
+ DB_TXN_APPLY=1, /* Public. */
+ DB_TXN_BACKWARD_ALLOC=2, /* Internal. */
+ DB_TXN_BACKWARD_ROLL=3, /* Public. */
+ DB_TXN_FORWARD_ROLL=4, /* Public. */
+ DB_TXN_GETPGNOS=5, /* Internal. */
+ DB_TXN_OPENFILES=6, /* Internal. */
+ DB_TXN_POPENFILES=7, /* Internal. */
+ DB_TXN_PRINT=8 /* Public. */
+} db_recops;
+
+/*
+ * BACKWARD_ALLOC is used during the forward pass to pick up any aborted
+ * allocations for files that were created during the forward pass.
+ * The main difference between _ALLOC and _ROLL is that the entry for
+ * the file not exist during the rollforward pass.
+ */
+#define DB_UNDO(op) ((op) == DB_TXN_ABORT || \
+ (op) == DB_TXN_BACKWARD_ROLL || (op) == DB_TXN_BACKWARD_ALLOC)
+#define DB_REDO(op) ((op) == DB_TXN_FORWARD_ROLL || (op) == DB_TXN_APPLY)
+
+struct __db_txn {
+ DB_TXNMGR *mgrp; /* Pointer to transaction manager. */
+ DB_TXN *parent; /* Pointer to transaction's parent. */
+ DB_LSN last_lsn; /* Lsn of last log write. */
+ u_int32_t txnid; /* Unique transaction id. */
+ roff_t off; /* Detail structure within region. */
+ db_timeout_t lock_timeout; /* Timeout for locks for this txn. */
+ db_timeout_t expire; /* Time this txn expires. */
+ void *txn_list; /* Undo information for parent. */
+
+ /*
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_ENTRY(__db_txn) links;
+ */
+ struct {
+ struct __db_txn *tqe_next;
+ struct __db_txn **tqe_prev;
+ } links; /* Links transactions off manager. */
+
+ /*
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_HEAD(__events, __txn_event) events;
+ */
+ struct {
+ struct __txn_event *tqh_first;
+ struct __txn_event **tqh_last;
+ } events;
+
+ /*
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_HEAD(__kids, __db_txn) kids;
+ */
+ struct __kids {
+ struct __db_txn *tqh_first;
+ struct __db_txn **tqh_last;
+ } kids;
+
+ /*
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_ENTRY(__db_txn) klinks;
+ */
+ struct {
+ struct __db_txn *tqe_next;
+ struct __db_txn **tqe_prev;
+ } klinks;
+
+ /* API-private structure: used by C++ */
+ void *api_internal;
+
+ u_int32_t cursors; /* Number of cursors open for txn */
+
+ /* Methods. */
+ int (*abort) __P((DB_TXN *));
+ int (*commit) __P((DB_TXN *, u_int32_t));
+ int (*discard) __P((DB_TXN *, u_int32_t));
+ u_int32_t (*id) __P((DB_TXN *));
+ int (*prepare) __P((DB_TXN *, u_int8_t *));
+ int (*set_timeout) __P((DB_TXN *, db_timeout_t, u_int32_t));
+
+#define TXN_CHILDCOMMIT 0x01 /* Transaction that has committed. */
+#define TXN_COMPENSATE 0x02 /* Compensating transaction. */
+#define TXN_DIRTY_READ 0x04 /* Transaction does dirty reads. */
+#define TXN_LOCKTIMEOUT 0x08 /* Transaction has a lock timeout. */
+#define TXN_MALLOC 0x10 /* Structure allocated by TXN system. */
+#define TXN_NOSYNC 0x20 /* Do not sync on prepare and commit. */
+#define TXN_NOWAIT 0x40 /* Do not wait on locks. */
+#define TXN_SYNC 0x80 /* Sync on prepare and commit. */
+ u_int32_t flags;
+};
+
+/* Transaction statistics structure. */
+struct __db_txn_active {
+ u_int32_t txnid; /* Transaction ID */
+ u_int32_t parentid; /* Transaction ID of parent */
+ DB_LSN lsn; /* LSN when transaction began */
+};
+
+struct __db_txn_stat {
+ DB_LSN st_last_ckp; /* lsn of the last checkpoint */
+ time_t st_time_ckp; /* time of last checkpoint */
+ u_int32_t st_last_txnid; /* last transaction id given out */
+ u_int32_t st_maxtxns; /* maximum txns possible */
+ u_int32_t st_naborts; /* number of aborted transactions */
+ u_int32_t st_nbegins; /* number of begun transactions */
+ u_int32_t st_ncommits; /* number of committed transactions */
+ u_int32_t st_nactive; /* number of active transactions */
+ u_int32_t st_nrestores; /* number of restored transactions
+ after recovery. */
+ u_int32_t st_maxnactive; /* maximum active transactions */
+ DB_TXN_ACTIVE *st_txnarray; /* array of active transactions */
+ u_int32_t st_region_wait; /* Region lock granted after wait. */
+ u_int32_t st_region_nowait; /* Region lock granted without wait. */
+ u_int32_t st_regsize; /* Region size. */
+};
+
+/*
+ * Structure used for two phase commit interface. Berkeley DB support for two
+ * phase commit is compatible with the X/open XA interface. The xa #define
+ * XIDDATASIZE defines the size of a global transaction ID. We have our own
+ * version here which must have the same value.
+ */
+#define DB_XIDDATASIZE 128
+struct __db_preplist {
+ DB_TXN *txn;
+ u_int8_t gid[DB_XIDDATASIZE];
+};
+
+/*******************************************************
+ * Replication.
+ *******************************************************/
+/* Special, out-of-band environment IDs. */
+#define DB_EID_BROADCAST -1
+#define DB_EID_INVALID -2
+
+/* rep_start flags values */
+#define DB_REP_CLIENT 0x001
+#define DB_REP_LOGSONLY 0x002
+#define DB_REP_MASTER 0x004
+
+/* Replication statistics. */
+struct __db_rep_stat {
+ /* !!!
+ * Many replication statistics fields cannot be protected by a mutex
+ * without an unacceptable performance penalty, since most message
+ * processing is done without the need to hold a region-wide lock.
+ * Fields whose comments end with a '+' may be updated without holding
+ * the replication or log mutexes (as appropriate), and thus may be
+ * off somewhat (or, on unreasonable architectures under unlucky
+ * circumstances, garbaged).
+ */
+ u_int32_t st_status; /* Current replication status. */
+ DB_LSN st_next_lsn; /* Next LSN to use or expect. */
+ DB_LSN st_waiting_lsn; /* LSN we're awaiting, if any. */
+
+ u_int32_t st_dupmasters; /* # of times a duplicate master
+ condition was detected.+ */
+ int st_env_id; /* Current environment ID. */
+ int st_env_priority; /* Current environment priority. */
+ u_int32_t st_gen; /* Current generation number. */
+ u_int32_t st_log_duplicated; /* Log records received multiply.+ */
+ u_int32_t st_log_queued; /* Log records currently queued.+ */
+ u_int32_t st_log_queued_max; /* Max. log records queued at once.+ */
+ u_int32_t st_log_queued_total; /* Total # of log recs. ever queued.+ */
+ u_int32_t st_log_records; /* Log records received and put.+ */
+ u_int32_t st_log_requested; /* Log recs. missed and requested.+ */
+ int st_master; /* Env. ID of the current master. */
+ u_int32_t st_master_changes; /* # of times we've switched masters. */
+ u_int32_t st_msgs_badgen; /* Messages with a bad generation #.+ */
+ u_int32_t st_msgs_processed; /* Messages received and processed.+ */
+ u_int32_t st_msgs_recover; /* Messages ignored because this site
+ was a client in recovery.+ */
+ u_int32_t st_msgs_send_failures;/* # of failed message sends.+ */
+ u_int32_t st_msgs_sent; /* # of successful message sends.+ */
+ u_int32_t st_newsites; /* # of NEWSITE msgs. received.+ */
+ int st_nsites; /* Current number of sites we will
+ assume during elections. */
+ u_int32_t st_nthrottles; /* # of times we were throttled. */
+ u_int32_t st_outdated; /* # of times we detected and returned
+ an OUTDATED condition.+ */
+ u_int32_t st_txns_applied; /* # of transactions applied.+ */
+
+ /* Elections generally. */
+ u_int32_t st_elections; /* # of elections held.+ */
+ u_int32_t st_elections_won; /* # of elections won by this site.+ */
+
+ /* Statistics about an in-progress election. */
+ int st_election_cur_winner; /* Current front-runner. */
+ u_int32_t st_election_gen; /* Election generation number. */
+ DB_LSN st_election_lsn; /* Max. LSN of current winner. */
+ int st_election_nsites; /* # of "registered voters". */
+ int st_election_priority; /* Current election priority. */
+ int st_election_status; /* Current election status. */
+ int st_election_tiebreaker; /* Election tiebreaker value. */
+ int st_election_votes; /* Votes received in this round. */
+};
+
+/*******************************************************
+ * Access methods.
+ *******************************************************/
+typedef enum {
+ DB_BTREE=1,
+ DB_HASH=2,
+ DB_RECNO=3,
+ DB_QUEUE=4,
+ DB_UNKNOWN=5 /* Figure it out on open. */
+} DBTYPE;
+
+#define DB_RENAMEMAGIC 0x030800 /* File has been renamed. */
+
+#define DB_BTREEVERSION 9 /* Current btree version. */
+#define DB_BTREEOLDVER 8 /* Oldest btree version supported. */
+#define DB_BTREEMAGIC 0x053162
+
+#define DB_HASHVERSION 8 /* Current hash version. */
+#define DB_HASHOLDVER 7 /* Oldest hash version supported. */
+#define DB_HASHMAGIC 0x061561
+
+#define DB_QAMVERSION 4 /* Current queue version. */
+#define DB_QAMOLDVER 3 /* Oldest queue version supported. */
+#define DB_QAMMAGIC 0x042253
+
+/*
+ * DB access method and cursor operation values. Each value is an operation
+ * code to which additional bit flags are added.
+ */
+#define DB_AFTER 1 /* c_put() */
+#define DB_APPEND 2 /* put() */
+#define DB_BEFORE 3 /* c_put() */
+#define DB_CACHED_COUNTS 4 /* stat() */
+#define DB_COMMIT 5 /* log_put() (internal) */
+#define DB_CONSUME 6 /* get() */
+#define DB_CONSUME_WAIT 7 /* get() */
+#define DB_CURRENT 8 /* c_get(), c_put(), DB_LOGC->get() */
+#define DB_FAST_STAT 9 /* stat() */
+#define DB_FIRST 10 /* c_get(), DB_LOGC->get() */
+#define DB_GET_BOTH 11 /* get(), c_get() */
+#define DB_GET_BOTHC 12 /* c_get() (internal) */
+#define DB_GET_BOTH_RANGE 13 /* get(), c_get() */
+#define DB_GET_RECNO 14 /* c_get() */
+#define DB_JOIN_ITEM 15 /* c_get(); do not do primary lookup */
+#define DB_KEYFIRST 16 /* c_put() */
+#define DB_KEYLAST 17 /* c_put() */
+#define DB_LAST 18 /* c_get(), DB_LOGC->get() */
+#define DB_NEXT 19 /* c_get(), DB_LOGC->get() */
+#define DB_NEXT_DUP 20 /* c_get() */
+#define DB_NEXT_NODUP 21 /* c_get() */
+#define DB_NODUPDATA 22 /* put(), c_put() */
+#define DB_NOOVERWRITE 23 /* put() */
+#define DB_NOSYNC 24 /* close() */
+#define DB_POSITION 25 /* c_dup() */
+#define DB_POSITIONI 26 /* c_dup() (internal) */
+#define DB_PREV 27 /* c_get(), DB_LOGC->get() */
+#define DB_PREV_NODUP 28 /* c_get(), DB_LOGC->get() */
+#define DB_RECORDCOUNT 29 /* stat() */
+#define DB_SET 30 /* c_get(), DB_LOGC->get() */
+#define DB_SET_LOCK_TIMEOUT 31 /* set_timout() */
+#define DB_SET_RANGE 32 /* c_get() */
+#define DB_SET_RECNO 33 /* get(), c_get() */
+#define DB_SET_TXN_NOW 34 /* set_timout() (internal) */
+#define DB_SET_TXN_TIMEOUT 35 /* set_timout() */
+#define DB_UPDATE_SECONDARY 36 /* c_get(), c_del() (internal) */
+#define DB_WRITECURSOR 37 /* cursor() */
+#define DB_WRITELOCK 38 /* cursor() (internal) */
+
+/* This has to change when the max opcode hits 255. */
+#define DB_OPFLAGS_MASK 0x000000ff /* Mask for operations flags. */
+/* DB_DIRTY_READ 0x01000000 Dirty Read. */
+#define DB_FLUSH 0x02000000 /* Flush data to disk. */
+#define DB_MULTIPLE 0x04000000 /* Return multiple data values. */
+#define DB_MULTIPLE_KEY 0x08000000 /* Return multiple data/key pairs. */
+#define DB_NOCOPY 0x10000000 /* Don't copy data */
+#define DB_PERMANENT 0x20000000 /* Flag record with REP_PERMANENT. */
+#define DB_RMW 0x40000000 /* Acquire write flag immediately. */
+#define DB_WRNOSYNC 0x80000000 /* Private: write, don't sync log_put */
+
+/*
+ * DB (user visible) error return codes.
+ *
+ * !!!
+ * For source compatibility with DB 2.X deadlock return (EAGAIN), use the
+ * following:
+ * #include <errno.h>
+ * #define DB_LOCK_DEADLOCK EAGAIN
+ *
+ * !!!
+ * We don't want our error returns to conflict with other packages where
+ * possible, so pick a base error value that's hopefully not common. We
+ * document that we own the error name space from -30,800 to -30,999.
+ */
+/* DB (public) error return codes. */
+#define DB_DONOTINDEX (-30999)/* "Null" return from 2ndary callbk. */
+#define DB_KEYEMPTY (-30998)/* Key/data deleted or never created. */
+#define DB_KEYEXIST (-30997)/* The key/data pair already exists. */
+#define DB_LOCK_DEADLOCK (-30996)/* Deadlock. */
+#define DB_LOCK_NOTGRANTED (-30995)/* Lock unavailable. */
+#define DB_NOSERVER (-30994)/* Server panic return. */
+#define DB_NOSERVER_HOME (-30993)/* Bad home sent to server. */
+#define DB_NOSERVER_ID (-30992)/* Bad ID sent to server. */
+#define DB_NOTFOUND (-30991)/* Key/data pair not found (EOF). */
+#define DB_OLD_VERSION (-30990)/* Out-of-date version. */
+#define DB_PAGE_NOTFOUND (-30989)/* Requested page not found. */
+#define DB_REP_DUPMASTER (-30988)/* There are two masters. */
+#define DB_REP_HOLDELECTION (-30987)/* Time to hold an election. */
+#define DB_REP_NEWMASTER (-30986)/* We have learned of a new master. */
+#define DB_REP_NEWSITE (-30985)/* New site entered system. */
+#define DB_REP_OUTDATED (-30984)/* Site is too far behind master. */
+#define DB_REP_UNAVAIL (-30983)/* Site cannot currently be reached. */
+#define DB_RUNRECOVERY (-30982)/* Panic return. */
+#define DB_SECONDARY_BAD (-30981)/* Secondary index corrupt. */
+#define DB_VERIFY_BAD (-30980)/* Verify failed; bad format. */
+
+/* DB (private) error return codes. */
+#define DB_ALREADY_ABORTED (-30899)
+#define DB_DELETED (-30898)/* Recovery file marked deleted. */
+#define DB_JAVA_CALLBACK (-30897)/* Exception during a java callback. */
+#define DB_LOCK_NOTEXIST (-30896)/* Object to lock is gone. */
+#define DB_NEEDSPLIT (-30895)/* Page needs to be split. */
+#define DB_SURPRISE_KID (-30894)/* Child commit where parent
+ didn't know it was a parent. */
+#define DB_SWAPBYTES (-30893)/* Database needs byte swapping. */
+#define DB_TIMEOUT (-30892)/* Timed out waiting for election. */
+#define DB_TXN_CKP (-30891)/* Encountered ckp record in log. */
+#define DB_VERIFY_FATAL (-30890)/* DB->verify cannot proceed. */
+
+/* Database handle. */
+struct __db {
+ /*******************************************************
+ * Public: owned by the application.
+ *******************************************************/
+ u_int32_t pgsize; /* Database logical page size. */
+
+ /* Callbacks. */
+ int (*db_append_recno) __P((DB *, DBT *, db_recno_t));
+ void (*db_feedback) __P((DB *, int, int));
+ int (*dup_compare) __P((DB *, const DBT *, const DBT *));
+
+ void *app_private; /* Application-private handle. */
+
+ /*******************************************************
+ * Private: owned by DB.
+ *******************************************************/
+ DB_ENV *dbenv; /* Backing environment. */
+
+ DBTYPE type; /* DB access method type. */
+
+ DB_MPOOLFILE *mpf; /* Backing buffer pool. */
+ DB_CACHE_PRIORITY priority; /* Priority in the buffer pool. */
+
+ DB_MUTEX *mutexp; /* Synchronization for free threading */
+
+ u_int8_t fileid[DB_FILE_ID_LEN];/* File's unique ID for locking. */
+
+ u_int32_t adj_fileid; /* File's unique ID for curs. adj. */
+
+#define DB_LOGFILEID_INVALID -1
+ FNAME *log_filename; /* File's naming info for logging. */
+
+ db_pgno_t meta_pgno; /* Meta page number */
+ u_int32_t lid; /* Locker id for handle locking. */
+ u_int32_t cur_lid; /* Current handle lock holder. */
+ u_int32_t associate_lid; /* Locker id for DB->associate call. */
+ DB_LOCK handle_lock; /* Lock held on this handle. */
+
+ long cl_id; /* RPC: remote client id. */
+
+ /*
+ * Returned data memory for DB->get() and friends.
+ */
+ DBT my_rskey; /* Secondary key. */
+ DBT my_rkey; /* [Primary] key. */
+ DBT my_rdata; /* Data. */
+
+ /*
+ * !!!
+ * Some applications use DB but implement their own locking outside of
+ * DB. If they're using fcntl(2) locking on the underlying database
+ * file, and we open and close a file descriptor for that file, we will
+ * discard their locks. The DB_FCNTL_LOCKING flag to DB->open is an
+ * undocumented interface to support this usage which leaves any file
+ * descriptors we open until DB->close. This will only work with the
+ * DB->open interface and simple caches, e.g., creating a transaction
+ * thread may open/close file descriptors this flag doesn't protect.
+ * Locking with fcntl(2) on a file that you don't own is a very, very
+ * unsafe thing to do. 'Nuff said.
+ */
+ DB_FH *saved_open_fhp; /* Saved file handle. */
+
+ /*
+ * Linked list of DBP's, linked from the DB_ENV, used to keep track
+ * of all open db handles for cursor adjustment.
+ *
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * LIST_ENTRY(__db) dblistlinks;
+ */
+ struct {
+ struct __db *le_next;
+ struct __db **le_prev;
+ } dblistlinks;
+
+ /*
+ * Cursor queues.
+ *
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_HEAD(__cq_fq, __dbc) free_queue;
+ * TAILQ_HEAD(__cq_aq, __dbc) active_queue;
+ * TAILQ_HEAD(__cq_jq, __dbc) join_queue;
+ */
+ struct __cq_fq {
+ struct __dbc *tqh_first;
+ struct __dbc **tqh_last;
+ } free_queue;
+ struct __cq_aq {
+ struct __dbc *tqh_first;
+ struct __dbc **tqh_last;
+ } active_queue;
+ struct __cq_jq {
+ struct __dbc *tqh_first;
+ struct __dbc **tqh_last;
+ } join_queue;
+
+ /*
+ * Secondary index support.
+ *
+ * Linked list of secondary indices -- set in the primary.
+ *
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * LIST_HEAD(s_secondaries, __db);
+ */
+ struct {
+ struct __db *lh_first;
+ } s_secondaries;
+
+ /*
+ * List entries for secondaries, and reference count of how
+ * many threads are updating this secondary (see __db_c_put).
+ *
+ * !!!
+ * Note that these are synchronized by the primary's mutex, but
+ * filled in in the secondaries.
+ *
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * LIST_ENTRY(__db) s_links;
+ */
+ struct {
+ struct __db *le_next;
+ struct __db **le_prev;
+ } s_links;
+ u_int32_t s_refcnt;
+
+ /* Secondary callback and free functions -- set in the secondary. */
+ int (*s_callback) __P((DB *, const DBT *, const DBT *, DBT *));
+
+ /* Reference to primary -- set in the secondary. */
+ DB *s_primary;
+
+ /* API-private structure: used by DB 1.85, C++, Java, Perl and Tcl */
+ void *api_internal;
+
+ /* Subsystem-private structure. */
+ void *bt_internal; /* Btree/Recno access method. */
+ void *h_internal; /* Hash access method. */
+ void *q_internal; /* Queue access method. */
+ void *xa_internal; /* XA. */
+
+ /* Methods. */
+ int (*associate) __P((DB *, DB_TXN *, DB *, int (*)(DB *, const DBT *,
+ const DBT *, DBT *), u_int32_t));
+ int (*close) __P((DB *, u_int32_t));
+ int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t));
+ int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
+ void (*err) __P((DB *, int, const char *, ...));
+ void (*errx) __P((DB *, const char *, ...));
+ int (*fd) __P((DB *, int *));
+ int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ int (*pget) __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
+ int (*get_byteswapped) __P((DB *, int *));
+ int (*get_type) __P((DB *, DBTYPE *));
+ int (*join) __P((DB *, DBC **, DBC **, u_int32_t));
+ int (*key_range) __P((DB *,
+ DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
+ int (*open) __P((DB *, DB_TXN *,
+ const char *, const char *, DBTYPE, u_int32_t, int));
+ int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ int (*remove) __P((DB *, const char *, const char *, u_int32_t));
+ int (*rename) __P((DB *,
+ const char *, const char *, const char *, u_int32_t));
+ int (*truncate) __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
+ int (*set_append_recno) __P((DB *, int (*)(DB *, DBT *, db_recno_t)));
+ int (*set_alloc) __P((DB *, void *(*)(size_t),
+ void *(*)(void *, size_t), void (*)(void *)));
+ int (*set_cachesize) __P((DB *, u_int32_t, u_int32_t, int));
+ int (*set_cache_priority) __P((DB *, DB_CACHE_PRIORITY));
+ int (*set_dup_compare) __P((DB *,
+ int (*)(DB *, const DBT *, const DBT *)));
+ int (*set_encrypt) __P((DB *, const char *, u_int32_t));
+ void (*set_errcall) __P((DB *, void (*)(const char *, char *)));
+ void (*set_errfile) __P((DB *, FILE *));
+ void (*set_errpfx) __P((DB *, const char *));
+ int (*set_feedback) __P((DB *, void (*)(DB *, int, int)));
+ int (*set_flags) __P((DB *, u_int32_t));
+ int (*set_lorder) __P((DB *, int));
+ int (*set_pagesize) __P((DB *, u_int32_t));
+ int (*set_paniccall) __P((DB *, void (*)(DB_ENV *, int)));
+ int (*stat) __P((DB *, void *, u_int32_t));
+ int (*sync) __P((DB *, u_int32_t));
+ int (*upgrade) __P((DB *, const char *, u_int32_t));
+ int (*verify) __P((DB *,
+ const char *, const char *, FILE *, u_int32_t));
+
+ int (*set_bt_compare) __P((DB *,
+ int (*)(DB *, const DBT *, const DBT *)));
+ int (*set_bt_maxkey) __P((DB *, u_int32_t));
+ int (*set_bt_minkey) __P((DB *, u_int32_t));
+ int (*set_bt_prefix) __P((DB *,
+ size_t (*)(DB *, const DBT *, const DBT *)));
+
+ int (*set_h_ffactor) __P((DB *, u_int32_t));
+ int (*set_h_hash) __P((DB *,
+ u_int32_t (*)(DB *, const void *, u_int32_t)));
+ int (*set_h_nelem) __P((DB *, u_int32_t));
+
+ int (*set_re_delim) __P((DB *, int));
+ int (*set_re_len) __P((DB *, u_int32_t));
+ int (*set_re_pad) __P((DB *, int));
+ int (*set_re_source) __P((DB *, const char *));
+ int (*set_q_extentsize) __P((DB *, u_int32_t));
+
+ int (*db_am_remove) __P((DB *,
+ DB_TXN *, const char *, const char *, DB_LSN *));
+ int (*db_am_rename) __P((DB *, DB_TXN *,
+ const char *, const char *, const char *));
+
+ /*
+ * Never called; these are a place to save function pointers
+ * so that we can undo an associate.
+ */
+ int (*stored_get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ int (*stored_close) __P((DB *, u_int32_t));
+
+#define DB_OK_BTREE 0x01
+#define DB_OK_HASH 0x02
+#define DB_OK_QUEUE 0x04
+#define DB_OK_RECNO 0x08
+ u_int32_t am_ok; /* Legal AM choices. */
+
+#define DB_AM_CHKSUM 0x00000001 /* Checksumming. */
+#define DB_AM_CL_WRITER 0x00000002 /* Allow writes in client replica. */
+#define DB_AM_COMPENSATE 0x00000004 /* Created by compensating txn. */
+#define DB_AM_CREATED 0x00000008 /* Database was created upon open. */
+#define DB_AM_CREATED_MSTR 0x00000010 /* Encompassing file was created. */
+#define DB_AM_DBM_ERROR 0x00000020 /* Error in DBM/NDBM database. */
+#define DB_AM_DELIMITER 0x00000040 /* Variable length delimiter set. */
+#define DB_AM_DIRTY 0x00000080 /* Support Dirty Reads. */
+#define DB_AM_DISCARD 0x00000100 /* Discard any cached pages. */
+#define DB_AM_DUP 0x00000200 /* DB_DUP. */
+#define DB_AM_DUPSORT 0x00000400 /* DB_DUPSORT. */
+#define DB_AM_ENCRYPT 0x00000800 /* Encryption. */
+#define DB_AM_FIXEDLEN 0x00001000 /* Fixed-length records. */
+#define DB_AM_INMEM 0x00002000 /* In-memory; no sync on close. */
+#define DB_AM_IN_RENAME 0x00004000 /* File is being renamed. */
+#define DB_AM_OPEN_CALLED 0x00008000 /* DB->open called. */
+#define DB_AM_PAD 0x00010000 /* Fixed-length record pad. */
+#define DB_AM_PGDEF 0x00020000 /* Page size was defaulted. */
+#define DB_AM_RDONLY 0x00040000 /* Database is readonly. */
+#define DB_AM_RECNUM 0x00080000 /* DB_RECNUM. */
+#define DB_AM_RECOVER 0x00100000 /* DB opened by recovery routine. */
+#define DB_AM_RENUMBER 0x00200000 /* DB_RENUMBER. */
+#define DB_AM_REVSPLITOFF 0x00400000 /* DB_REVSPLITOFF. */
+#define DB_AM_SECONDARY 0x00800000 /* Database is a secondary index. */
+#define DB_AM_SNAPSHOT 0x01000000 /* DB_SNAPSHOT. */
+#define DB_AM_SUBDB 0x02000000 /* Subdatabases supported. */
+#define DB_AM_SWAP 0x04000000 /* Pages need to be byte-swapped. */
+#define DB_AM_TXN 0x08000000 /* Opened in a transaction. */
+#define DB_AM_VERIFYING 0x10000000 /* DB handle is in the verifier. */
+ u_int32_t flags;
+};
+
+/*
+ * Macros for bulk get. Note that wherever we use a DBT *, we explicitly
+ * cast it; this allows the same macros to work with C++ Dbt *'s, as Dbt
+ * is a subclass of struct DBT in C++.
+ */
+#define DB_MULTIPLE_INIT(pointer, dbt) \
+ (pointer = (u_int8_t *)((DBT *)(dbt))->data + \
+ ((DBT *)(dbt))->ulen - sizeof(u_int32_t))
+#define DB_MULTIPLE_NEXT(pointer, dbt, retdata, retdlen) \
+ do { \
+ if (*((u_int32_t *)(pointer)) == (u_int32_t)-1) { \
+ retdata = NULL; \
+ pointer = NULL; \
+ break; \
+ } \
+ retdata = (u_int8_t *) \
+ ((DBT *)(dbt))->data + *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ retdlen = *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ if (retdlen == 0 && \
+ retdata == (u_int8_t *)((DBT *)(dbt))->data) \
+ retdata = NULL; \
+ } while (0)
+#define DB_MULTIPLE_KEY_NEXT(pointer, dbt, retkey, retklen, retdata, retdlen) \
+ do { \
+ if (*((u_int32_t *)(pointer)) == (u_int32_t)-1) { \
+ retdata = NULL; \
+ retkey = NULL; \
+ pointer = NULL; \
+ break; \
+ } \
+ retkey = (u_int8_t *) \
+ ((DBT *)(dbt))->data + *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ retklen = *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ retdata = (u_int8_t *) \
+ ((DBT *)(dbt))->data + *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ retdlen = *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ } while (0)
+
+#define DB_MULTIPLE_RECNO_NEXT(pointer, dbt, recno, retdata, retdlen) \
+ do { \
+ if (*((u_int32_t *)(pointer)) == (u_int32_t)0) { \
+ recno = 0; \
+ retdata = NULL; \
+ pointer = NULL; \
+ break; \
+ } \
+ recno = *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ retdata = (u_int8_t *) \
+ ((DBT *)(dbt))->data + *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ retdlen = *(u_int32_t *)(pointer); \
+ (pointer) = (u_int32_t *)(pointer) - 1; \
+ } while (0)
+
+/*******************************************************
+ * Access method cursors.
+ *******************************************************/
+struct __dbc {
+ DB *dbp; /* Related DB access method. */
+ DB_TXN *txn; /* Associated transaction. */
+
+ /*
+ * Active/free cursor queues.
+ *
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_ENTRY(__dbc) links;
+ */
+ struct {
+ DBC *tqe_next;
+ DBC **tqe_prev;
+ } links;
+
+ /*
+ * The DBT *'s below are used by the cursor routines to return
+ * data to the user when DBT flags indicate that DB should manage
+ * the returned memory. They point at a DBT containing the buffer
+ * and length that will be used, and "belonging" to the handle that
+ * should "own" this memory. This may be a "my_*" field of this
+ * cursor--the default--or it may be the corresponding field of
+ * another cursor, a DB handle, a join cursor, etc. In general, it
+ * will be whatever handle the user originally used for the current
+ * DB interface call.
+ */
+ DBT *rskey; /* Returned secondary key. */
+ DBT *rkey; /* Returned [primary] key. */
+ DBT *rdata; /* Returned data. */
+
+ DBT my_rskey; /* Space for returned secondary key. */
+ DBT my_rkey; /* Space for returned [primary] key. */
+ DBT my_rdata; /* Space for returned data. */
+
+ u_int32_t lid; /* Default process' locker id. */
+ u_int32_t locker; /* Locker for this operation. */
+ DBT lock_dbt; /* DBT referencing lock. */
+ DB_LOCK_ILOCK lock; /* Object to be locked. */
+ DB_LOCK mylock; /* Lock held on this cursor. */
+
+ long cl_id; /* Remote client id. */
+
+ DBTYPE dbtype; /* Cursor type. */
+
+ DBC_INTERNAL *internal; /* Access method private. */
+
+ int (*c_close) __P((DBC *)); /* Methods: public. */
+ int (*c_count) __P((DBC *, db_recno_t *, u_int32_t));
+ int (*c_del) __P((DBC *, u_int32_t));
+ int (*c_dup) __P((DBC *, DBC **, u_int32_t));
+ int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
+ int (*c_pget) __P((DBC *, DBT *, DBT *, DBT *, u_int32_t));
+ int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
+
+ /* Methods: private. */
+ int (*c_am_bulk) __P((DBC *, DBT *, u_int32_t));
+ int (*c_am_close) __P((DBC *, db_pgno_t, int *));
+ int (*c_am_del) __P((DBC *));
+ int (*c_am_destroy) __P((DBC *));
+ int (*c_am_get) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
+ int (*c_am_put) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
+ int (*c_am_writelock) __P((DBC *));
+
+ /* Private: for secondary indices. */
+ int (*c_real_get) __P((DBC *, DBT *, DBT *, u_int32_t));
+
+#define DBC_ACTIVE 0x0001 /* Cursor in use. */
+#define DBC_COMPENSATE 0x0002 /* Cursor compensating, don't lock. */
+#define DBC_DIRTY_READ 0x0004 /* Cursor supports dirty reads. */
+#define DBC_OPD 0x0008 /* Cursor references off-page dups. */
+#define DBC_RECOVER 0x0010 /* Recovery cursor; don't log/lock. */
+#define DBC_RMW 0x0020 /* Acquire write flag in read op. */
+#define DBC_TRANSIENT 0x0040 /* Cursor is transient. */
+#define DBC_WRITECURSOR 0x0080 /* Cursor may be used to write (CDB). */
+#define DBC_WRITEDUP 0x0100 /* idup'ed DBC_WRITECURSOR (CDB). */
+#define DBC_WRITER 0x0200 /* Cursor immediately writing (CDB). */
+#define DBC_MULTIPLE 0x0400 /* Return Multiple data. */
+#define DBC_MULTIPLE_KEY 0x0800 /* Return Multiple keys and data. */
+#define DBC_OWN_LID 0x1000 /* Free lock id on destroy. */
+ u_int32_t flags;
+};
+
+/* Key range statistics structure */
+struct __key_range {
+ double less;
+ double equal;
+ double greater;
+};
+
+/* Btree/Recno statistics structure. */
+struct __db_bt_stat {
+ u_int32_t bt_magic; /* Magic number. */
+ u_int32_t bt_version; /* Version number. */
+ u_int32_t bt_metaflags; /* Metadata flags. */
+ u_int32_t bt_nkeys; /* Number of unique keys. */
+ u_int32_t bt_ndata; /* Number of data items. */
+ u_int32_t bt_pagesize; /* Page size. */
+ u_int32_t bt_maxkey; /* Maxkey value. */
+ u_int32_t bt_minkey; /* Minkey value. */
+ u_int32_t bt_re_len; /* Fixed-length record length. */
+ u_int32_t bt_re_pad; /* Fixed-length record pad. */
+ u_int32_t bt_levels; /* Tree levels. */
+ u_int32_t bt_int_pg; /* Internal pages. */
+ u_int32_t bt_leaf_pg; /* Leaf pages. */
+ u_int32_t bt_dup_pg; /* Duplicate pages. */
+ u_int32_t bt_over_pg; /* Overflow pages. */
+ u_int32_t bt_free; /* Pages on the free list. */
+ u_int32_t bt_int_pgfree; /* Bytes free in internal pages. */
+ u_int32_t bt_leaf_pgfree; /* Bytes free in leaf pages. */
+ u_int32_t bt_dup_pgfree; /* Bytes free in duplicate pages. */
+ u_int32_t bt_over_pgfree; /* Bytes free in overflow pages. */
+};
+
+/* Hash statistics structure. */
+struct __db_h_stat {
+ u_int32_t hash_magic; /* Magic number. */
+ u_int32_t hash_version; /* Version number. */
+ u_int32_t hash_metaflags; /* Metadata flags. */
+ u_int32_t hash_nkeys; /* Number of unique keys. */
+ u_int32_t hash_ndata; /* Number of data items. */
+ u_int32_t hash_pagesize; /* Page size. */
+ u_int32_t hash_ffactor; /* Fill factor specified at create. */
+ u_int32_t hash_buckets; /* Number of hash buckets. */
+ u_int32_t hash_free; /* Pages on the free list. */
+ u_int32_t hash_bfree; /* Bytes free on bucket pages. */
+ u_int32_t hash_bigpages; /* Number of big key/data pages. */
+ u_int32_t hash_big_bfree; /* Bytes free on big item pages. */
+ u_int32_t hash_overflows; /* Number of overflow pages. */
+ u_int32_t hash_ovfl_free; /* Bytes free on ovfl pages. */
+ u_int32_t hash_dup; /* Number of dup pages. */
+ u_int32_t hash_dup_free; /* Bytes free on duplicate pages. */
+};
+
+/* Queue statistics structure. */
+struct __db_qam_stat {
+ u_int32_t qs_magic; /* Magic number. */
+ u_int32_t qs_version; /* Version number. */
+ u_int32_t qs_metaflags; /* Metadata flags. */
+ u_int32_t qs_nkeys; /* Number of unique keys. */
+ u_int32_t qs_ndata; /* Number of data items. */
+ u_int32_t qs_pagesize; /* Page size. */
+ u_int32_t qs_extentsize; /* Pages per extent. */
+ u_int32_t qs_pages; /* Data pages. */
+ u_int32_t qs_re_len; /* Fixed-length record length. */
+ u_int32_t qs_re_pad; /* Fixed-length record pad. */
+ u_int32_t qs_pgfree; /* Bytes free in data pages. */
+ u_int32_t qs_first_recno; /* First not deleted record. */
+ u_int32_t qs_cur_recno; /* Next available record number. */
+};
+
+/*******************************************************
+ * Environment.
+ *******************************************************/
+#define DB_REGION_MAGIC 0x120897 /* Environment magic number. */
+
+typedef enum {
+ DB_NOTICE_LOGFILE_CHANGED
+} db_notices;
+
+/* Database Environment handle. */
+struct __db_env {
+ /*******************************************************
+ * Public: owned by the application.
+ *******************************************************/
+ FILE *db_errfile; /* Error message file stream. */
+ const char *db_errpfx; /* Error message prefix. */
+ /* Callbacks. */
+ void (*db_errcall) __P((const char *, char *));
+ void (*db_feedback) __P((DB_ENV *, int, int));
+ void (*db_paniccall) __P((DB_ENV *, int));
+ void (*db_noticecall) __P((DB_ENV *, db_notices));
+
+ /* App-specified alloc functions. */
+ void *(*db_malloc) __P((size_t));
+ void *(*db_realloc) __P((void *, size_t));
+ void (*db_free) __P((void *));
+
+ /*
+ * Currently, the verbose list is a bit field with room for 32
+ * entries. There's no reason that it needs to be limited, if
+ * there are ever more than 32 entries, convert to a bit array.
+ */
+#define DB_VERB_CHKPOINT 0x0001 /* List checkpoints. */
+#define DB_VERB_DEADLOCK 0x0002 /* Deadlock detection information. */
+#define DB_VERB_RECOVERY 0x0004 /* Recovery information. */
+#define DB_VERB_REPLICATION 0x0008 /* Replication information. */
+#define DB_VERB_WAITSFOR 0x0010 /* Dump waits-for table. */
+ u_int32_t verbose; /* Verbose output. */
+
+ void *app_private; /* Application-private handle. */
+
+ int (*app_dispatch) /* User-specified recovery dispatch. */
+ __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
+
+ /* Locking. */
+ u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
+ u_int32_t lk_modes; /* Number of lock modes in table. */
+ u_int32_t lk_max; /* Maximum number of locks. */
+ u_int32_t lk_max_lockers;/* Maximum number of lockers. */
+ u_int32_t lk_max_objects;/* Maximum number of locked objects. */
+ u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
+ db_timeout_t lk_timeout; /* Lock timeout period. */
+
+ /* Logging. */
+ u_int32_t lg_bsize; /* Buffer size. */
+ u_int32_t lg_size; /* Log file size. */
+ u_int32_t lg_regionmax; /* Region size. */
+
+ /* Memory pool. */
+ u_int32_t mp_gbytes; /* Cachesize: GB. */
+ u_int32_t mp_bytes; /* Cachesize: Bytes. */
+ size_t mp_size; /* DEPRECATED: Cachesize: bytes. */
+ int mp_ncache; /* Number of cache regions. */
+ size_t mp_mmapsize; /* Maximum file size for mmap. */
+
+ int rep_eid; /* environment id. */
+
+ /* Transactions. */
+ u_int32_t tx_max; /* Maximum number of transactions. */
+ time_t tx_timestamp; /* Recover to specific timestamp. */
+ db_timeout_t tx_timeout; /* Timeout for transactions. */
+
+ /*******************************************************
+ * Private: owned by DB.
+ *******************************************************/
+ int panic_errval; /* Panic causing errno. */
+
+ /* User files, paths. */
+ char *db_home; /* Database home. */
+ char *db_log_dir; /* Database log file directory. */
+ char *db_tmp_dir; /* Database tmp file directory. */
+
+ char **db_data_dir; /* Database data file directories. */
+ int data_cnt; /* Database data file slots. */
+ int data_next; /* Next Database data file slot. */
+
+ int db_mode; /* Default open permissions. */
+
+ void *reginfo; /* REGINFO structure reference. */
+ DB_FH *lockfhp; /* fcntl(2) locking file handle. */
+
+ int (**recover_dtab) /* Dispatch table for recover funcs. */
+ __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t recover_dtab_size;
+ /* Slots in the dispatch table. */
+
+ void *cl_handle; /* RPC: remote client handle. */
+ long cl_id; /* RPC: remote client env id. */
+
+ int db_ref; /* DB reference count. */
+
+ long shm_key; /* shmget(2) key. */
+ u_int32_t tas_spins; /* test-and-set spins. */
+
+ /*
+ * List of open DB handles for this DB_ENV, used for cursor
+ * adjustment. Must be protected for multi-threaded support.
+ *
+ * !!!
+ * As this structure is allocated in per-process memory, the
+ * mutex may need to be stored elsewhere on architectures unable
+ * to support mutexes in heap memory, e.g. HP/UX 9.
+ *
+ * !!!
+ * Explicit representation of structure in queue.h.
+ * LIST_HEAD(dblist, __db);
+ */
+ DB_MUTEX *dblist_mutexp; /* Mutex. */
+ struct {
+ struct __db *lh_first;
+ } dblist;
+
+ /*
+ * XA support.
+ *
+ * !!!
+ * Explicit representations of structures from queue.h.
+ * TAILQ_ENTRY(__db_env) links;
+ */
+ struct {
+ struct __db_env *tqe_next;
+ struct __db_env **tqe_prev;
+ } links;
+ int xa_rmid; /* XA Resource Manager ID. */
+ DB_TXN *xa_txn; /* XA Current transaction. */
+
+ /* API-private structure. */
+ void *api1_internal; /* C++, Perl API private */
+ void *api2_internal; /* Java API private */
+
+ char *passwd; /* Cryptography support. */
+ size_t passwd_len;
+ void *crypto_handle; /* Primary handle. */
+ DB_MUTEX *mt_mutexp; /* Mersenne Twister mutex. */
+ int mti; /* Mersenne Twister index. */
+ u_long *mt; /* Mersenne Twister state vector. */
+
+ /* DB_ENV Methods. */
+ int (*close) __P((DB_ENV *, u_int32_t));
+ int (*dbremove) __P((DB_ENV *,
+ DB_TXN *, const char *, const char *, u_int32_t));
+ int (*dbrename) __P((DB_ENV *, DB_TXN *,
+ const char *, const char *, const char *, u_int32_t));
+ void (*err) __P((const DB_ENV *, int, const char *, ...));
+ void (*errx) __P((const DB_ENV *, const char *, ...));
+ int (*open) __P((DB_ENV *, const char *, u_int32_t, int));
+ int (*remove) __P((DB_ENV *, const char *, u_int32_t));
+ int (*set_data_dir) __P((DB_ENV *, const char *));
+ int (*set_alloc) __P((DB_ENV *, void *(*)(size_t),
+ void *(*)(void *, size_t), void (*)(void *)));
+ int (*set_app_dispatch) __P((DB_ENV *,
+ int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
+ int (*set_encrypt) __P((DB_ENV *, const char *, u_int32_t));
+ void (*set_errcall) __P((DB_ENV *, void (*)(const char *, char *)));
+ void (*set_errfile) __P((DB_ENV *, FILE *));
+ void (*set_errpfx) __P((DB_ENV *, const char *));
+ int (*set_feedback) __P((DB_ENV *, void (*)(DB_ENV *, int, int)));
+ int (*set_flags) __P((DB_ENV *, u_int32_t, int));
+ void (*set_noticecall) __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
+ int (*set_paniccall) __P((DB_ENV *, void (*)(DB_ENV *, int)));
+ int (*set_rpc_server) __P((DB_ENV *,
+ void *, const char *, long, long, u_int32_t));
+ int (*set_shm_key) __P((DB_ENV *, long));
+ int (*set_tas_spins) __P((DB_ENV *, u_int32_t));
+ int (*set_tmp_dir) __P((DB_ENV *, const char *));
+ int (*set_verbose) __P((DB_ENV *, u_int32_t, int));
+
+ void *lg_handle; /* Log handle and methods. */
+ int (*set_lg_bsize) __P((DB_ENV *, u_int32_t));
+ int (*set_lg_dir) __P((DB_ENV *, const char *));
+ int (*set_lg_max) __P((DB_ENV *, u_int32_t));
+ int (*set_lg_regionmax) __P((DB_ENV *, u_int32_t));
+ int (*log_archive) __P((DB_ENV *, char **[], u_int32_t));
+ int (*log_cursor) __P((DB_ENV *, DB_LOGC **, u_int32_t));
+ int (*log_file) __P((DB_ENV *, const DB_LSN *, char *, size_t));
+ int (*log_flush) __P((DB_ENV *, const DB_LSN *));
+ int (*log_put) __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
+ int (*log_stat) __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
+
+ void *lk_handle; /* Lock handle and methods. */
+ int (*set_lk_conflicts) __P((DB_ENV *, u_int8_t *, int));
+ int (*set_lk_detect) __P((DB_ENV *, u_int32_t));
+ int (*set_lk_max) __P((DB_ENV *, u_int32_t));
+ int (*set_lk_max_locks) __P((DB_ENV *, u_int32_t));
+ int (*set_lk_max_lockers) __P((DB_ENV *, u_int32_t));
+ int (*set_lk_max_objects) __P((DB_ENV *, u_int32_t));
+ int (*lock_detect) __P((DB_ENV *, u_int32_t, u_int32_t, int *));
+ int (*lock_dump_region) __P((DB_ENV *, char *, FILE *));
+ int (*lock_get) __P((DB_ENV *,
+ u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
+ int (*lock_put) __P((DB_ENV *, DB_LOCK *));
+ int (*lock_id) __P((DB_ENV *, u_int32_t *));
+ int (*lock_id_free) __P((DB_ENV *, u_int32_t));
+ int (*lock_id_set) __P((DB_ENV *, u_int32_t, u_int32_t));
+ int (*lock_stat) __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
+ int (*lock_vec) __P((DB_ENV *,
+ u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
+ int (*lock_downgrade) __P((DB_ENV *,
+ DB_LOCK *, db_lockmode_t, u_int32_t));
+
+ void *mp_handle; /* Mpool handle and methods. */
+ int (*set_mp_mmapsize) __P((DB_ENV *, size_t));
+ int (*set_cachesize) __P((DB_ENV *, u_int32_t, u_int32_t, int));
+ int (*memp_dump_region) __P((DB_ENV *, char *, FILE *));
+ int (*memp_fcreate) __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
+ int (*memp_nameop) __P((DB_ENV *,
+ u_int8_t *, const char *, const char *, const char *));
+ int (*memp_register) __P((DB_ENV *, int,
+ int (*)(DB_ENV *, db_pgno_t, void *, DBT *),
+ int (*)(DB_ENV *, db_pgno_t, void *, DBT *)));
+ int (*memp_stat) __P((DB_ENV *,
+ DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
+ int (*memp_sync) __P((DB_ENV *, DB_LSN *));
+ int (*memp_trickle) __P((DB_ENV *, int, int *));
+
+ void *rep_handle; /* Replication handle and methods. */
+ int (*rep_elect) __P((DB_ENV *, int, int, u_int32_t, int *));
+ int (*rep_flush) __P((DB_ENV *));
+ int (*rep_process_message) __P((DB_ENV *, DBT *, DBT *, int *));
+ int (*rep_start) __P((DB_ENV *, DBT *, u_int32_t));
+ int (*rep_stat) __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
+ int (*set_rep_election) __P((DB_ENV *,
+ u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+ int (*set_rep_limit) __P((DB_ENV *, u_int32_t, u_int32_t));
+ int (*set_rep_request) __P((DB_ENV *, u_int32_t, u_int32_t));
+ int (*set_rep_timeout) __P((DB_ENV *, u_int32_t, u_int32_t));
+ int (*set_rep_transport) __P((DB_ENV *, int,
+ int (*) (DB_ENV *, const DBT *, const DBT *, int, u_int32_t)));
+
+ void *tx_handle; /* Txn handle and methods. */
+ int (*set_tx_max) __P((DB_ENV *, u_int32_t));
+ int (*set_tx_timestamp) __P((DB_ENV *, time_t *));
+ int (*txn_begin) __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
+ int (*txn_checkpoint) __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t));
+ int (*txn_id_set) __P((DB_ENV *, u_int32_t, u_int32_t));
+ int (*txn_recover) __P((DB_ENV *,
+ DB_PREPLIST *, long, long *, u_int32_t));
+ int (*txn_stat) __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+ int (*set_timeout) __P((DB_ENV *, db_timeout_t, u_int32_t));
+
+#define DB_TEST_ELECTINIT 1 /* after __rep_elect_init */
+#define DB_TEST_ELECTSEND 2 /* after REP_ELECT msgnit */
+#define DB_TEST_ELECTVOTE1 3 /* after __rep_send_vote 1 */
+#define DB_TEST_ELECTVOTE2 4 /* after __rep_wait */
+#define DB_TEST_ELECTWAIT1 5 /* after REP_VOTE2 */
+#define DB_TEST_ELECTWAIT2 6 /* after __rep_wait 2 */
+#define DB_TEST_PREDESTROY 7 /* before destroy op */
+#define DB_TEST_PREOPEN 8 /* before __os_open */
+#define DB_TEST_POSTDESTROY 9 /* after destroy op */
+#define DB_TEST_POSTLOG 10 /* after logging all pages */
+#define DB_TEST_POSTLOGMETA 11 /* after logging meta in btree */
+#define DB_TEST_POSTOPEN 12 /* after __os_open */
+#define DB_TEST_POSTSYNC 13 /* after syncing the log */
+#define DB_TEST_SUBDB_LOCKS 14 /* subdb locking tests */
+ int test_abort; /* Abort value for testing. */
+ int test_copy; /* Copy value for testing. */
+
+#define DB_ENV_AUTO_COMMIT 0x0000001 /* DB_AUTO_COMMIT. */
+#define DB_ENV_CDB 0x0000002 /* DB_INIT_CDB. */
+#define DB_ENV_CDB_ALLDB 0x0000004 /* CDB environment wide locking. */
+#define DB_ENV_CREATE 0x0000008 /* DB_CREATE set. */
+#define DB_ENV_DBLOCAL 0x0000010 /* DB_ENV allocated for private DB. */
+#define DB_ENV_DIRECT_DB 0x0000020 /* DB_DIRECT_DB set. */
+#define DB_ENV_DIRECT_LOG 0x0000040 /* DB_DIRECT_LOG set. */
+#define DB_ENV_FATAL 0x0000080 /* Doing fatal recovery in env. */
+#define DB_ENV_LOCKDOWN 0x0000100 /* DB_LOCKDOWN set. */
+#define DB_ENV_NOLOCKING 0x0000200 /* DB_NOLOCKING set. */
+#define DB_ENV_NOMMAP 0x0000400 /* DB_NOMMAP set. */
+#define DB_ENV_NOPANIC 0x0000800 /* Okay if panic set. */
+#define DB_ENV_OPEN_CALLED 0x0001000 /* DB_ENV->open called. */
+#define DB_ENV_OVERWRITE 0x0002000 /* DB_OVERWRITE set. */
+#define DB_ENV_PRIVATE 0x0004000 /* DB_PRIVATE set. */
+#define DB_ENV_REGION_INIT 0x0008000 /* DB_REGION_INIT set. */
+#define DB_ENV_REP_CLIENT 0x0010000 /* Replication client. */
+#define DB_ENV_REP_LOGSONLY 0x0020000 /* Log files only replication site. */
+#define DB_ENV_REP_MASTER 0x0040000 /* Replication master. */
+#define DB_ENV_RPCCLIENT 0x0080000 /* DB_CLIENT set. */
+#define DB_ENV_RPCCLIENT_GIVEN 0x0100000 /* User-supplied RPC client struct */
+#define DB_ENV_SYSTEM_MEM 0x0200000 /* DB_SYSTEM_MEM set. */
+#define DB_ENV_THREAD 0x0400000 /* DB_THREAD set. */
+#define DB_ENV_TXN_NOSYNC 0x0800000 /* DB_TXN_NOSYNC set. */
+#define DB_ENV_TXN_WRITE_NOSYNC 0x1000000 /* DB_TXN_WRITE_NOSYNC set. */
+#define DB_ENV_YIELDCPU 0x2000000 /* DB_YIELDCPU set. */
+ u_int32_t flags;
+};
+
+#ifndef DB_DBM_HSEARCH
+#define DB_DBM_HSEARCH 0 /* No historic interfaces by default. */
+#endif
+#if DB_DBM_HSEARCH != 0
+/*******************************************************
+ * Dbm/Ndbm historic interfaces.
+ *******************************************************/
+typedef struct __db DBM;
+
+#define DBM_INSERT 0 /* Flags to dbm_store(). */
+#define DBM_REPLACE 1
+
+/*
+ * The DB support for ndbm(3) always appends this suffix to the
+ * file name to avoid overwriting the user's original database.
+ */
+#define DBM_SUFFIX ".db"
+
+#if defined(_XPG4_2)
+typedef struct {
+ char *dptr;
+ size_t dsize;
+} datum;
+#else
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+#endif
+
+/*
+ * Translate NDBM calls into DB calls so that DB doesn't step on the
+ * application's name space.
+ */
+#define dbm_clearerr(a) __db_ndbm_clearerr@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_close(a) __db_ndbm_close@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_delete(a, b) __db_ndbm_delete@DB_VERSION_UNIQUE_NAME@(a, b)
+#define dbm_dirfno(a) __db_ndbm_dirfno@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_error(a) __db_ndbm_error@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_fetch(a, b) __db_ndbm_fetch@DB_VERSION_UNIQUE_NAME@(a, b)
+#define dbm_firstkey(a) __db_ndbm_firstkey@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_nextkey(a) __db_ndbm_nextkey@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_open(a, b, c) __db_ndbm_open@DB_VERSION_UNIQUE_NAME@(a, b, c)
+#define dbm_pagfno(a) __db_ndbm_pagfno@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_rdonly(a) __db_ndbm_rdonly@DB_VERSION_UNIQUE_NAME@(a)
+#define dbm_store(a, b, c, d) \
+ __db_ndbm_store@DB_VERSION_UNIQUE_NAME@(a, b, c, d)
+
+/*
+ * Translate DBM calls into DB calls so that DB doesn't step on the
+ * application's name space.
+ *
+ * The global variables dbrdonly, dirf and pagf were not retained when 4BSD
+ * replaced the dbm interface with ndbm, and are not supported here.
+ */
+#define dbminit(a) __db_dbm_init@DB_VERSION_UNIQUE_NAME@(a)
+#define dbmclose __db_dbm_close@DB_VERSION_UNIQUE_NAME@
+#if !defined(__cplusplus)
+#define delete(a) __db_dbm_delete@DB_VERSION_UNIQUE_NAME@(a)
+#endif
+#define fetch(a) __db_dbm_fetch@DB_VERSION_UNIQUE_NAME@(a)
+#define firstkey __db_dbm_firstkey@DB_VERSION_UNIQUE_NAME@
+#define nextkey(a) __db_dbm_nextkey@DB_VERSION_UNIQUE_NAME@(a)
+#define store(a, b) __db_dbm_store@DB_VERSION_UNIQUE_NAME@(a, b)
+
+/*******************************************************
+ * Hsearch historic interface.
+ *******************************************************/
+typedef enum {
+ FIND, ENTER
+} ACTION;
+
+typedef struct entry {
+ char *key;
+ char *data;
+} ENTRY;
+
+#define hcreate(a) __db_hcreate@DB_VERSION_UNIQUE_NAME@(a)
+#define hdestroy __db_hdestroy@DB_VERSION_UNIQUE_NAME@
+#define hsearch(a, b) __db_hsearch@DB_VERSION_UNIQUE_NAME@(a, b)
+
+#endif /* DB_DBM_HSEARCH */
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* !_DB_H_ */
diff --git a/bdb/dbinc/db_185.in b/bdb/dbinc/db_185.in
new file mode 100644
index 00000000000..86e2290c304
--- /dev/null
+++ b/bdb/dbinc/db_185.in
@@ -0,0 +1,169 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: db_185.in,v 11.8 2002/01/11 15:52:24 bostic Exp $
+ */
+
+#ifndef _DB_185_H_
+#define _DB_185_H_
+
+#include <sys/types.h>
+
+#include <limits.h>
+
+/*
+ * XXX
+ * Handle function prototypes and the keyword "const". This steps on name
+ * space that DB doesn't control, but all of the other solutions are worse.
+ */
+#undef __P
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* ANSI C prototypes */
+#else
+#define const
+#define __P(protos) () /* K&R C preprocessor */
+#endif
+
+#define RET_ERROR -1 /* Return values. */
+#define RET_SUCCESS 0
+#define RET_SPECIAL 1
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+@u_int8_decl@
+@int16_decl@
+@u_int16_decl@
+@int32_decl@
+@u_int32_decl@
+#endif
+
+/*
+ * XXX
+ * SGI/IRIX already has a pgno_t.
+ */
+#ifdef sgi
+#define pgno_t db_pgno_t
+#endif
+
+#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
+typedef u_int32_t pgno_t;
+#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
+typedef u_int16_t indx_t;
+#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
+typedef u_int32_t recno_t;
+
+/* Key/data structure -- a Data-Base Thang. */
+typedef struct {
+ void *data; /* data */
+ size_t size; /* data length */
+} DBT;
+
+/* Routine flags. */
+#define R_CURSOR 1 /* del, put, seq */
+#define __R_UNUSED 2 /* UNUSED */
+#define R_FIRST 3 /* seq */
+#define R_IAFTER 4 /* put (RECNO) */
+#define R_IBEFORE 5 /* put (RECNO) */
+#define R_LAST 6 /* seq (BTREE, RECNO) */
+#define R_NEXT 7 /* seq */
+#define R_NOOVERWRITE 8 /* put */
+#define R_PREV 9 /* seq (BTREE, RECNO) */
+#define R_SETCURSOR 10 /* put (RECNO) */
+#define R_RECNOSYNC 11 /* sync (RECNO) */
+
+typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+
+/* Access method description structure. */
+typedef struct __db {
+ DBTYPE type; /* Underlying db type. */
+ int (*close) __P((struct __db *));
+ int (*del) __P((const struct __db *, const DBT *, u_int));
+ int (*get) __P((const struct __db *, const DBT *, DBT *, u_int));
+ int (*put) __P((const struct __db *, DBT *, const DBT *, u_int));
+ int (*seq) __P((const struct __db *, DBT *, DBT *, u_int));
+ int (*sync) __P((const struct __db *, u_int));
+ void *internal; /* Access method private. */
+ int (*fd) __P((const struct __db *));
+} DB;
+
+#define BTREEMAGIC 0x053162
+#define BTREEVERSION 3
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define R_DUP 0x01 /* duplicate keys */
+ u_int32_t flags;
+ u_int32_t cachesize; /* bytes to cache */
+ u_int32_t maxkeypage; /* maximum keys per page */
+ u_int32_t minkeypage; /* minimum keys per page */
+ u_int32_t psize; /* page size */
+ int (*compare) /* comparison function */
+ __P((const DBT *, const DBT *));
+ size_t (*prefix) /* prefix function */
+ __P((const DBT *, const DBT *));
+ int lorder; /* byte order */
+} BTREEINFO;
+
+#define HASHMAGIC 0x061561
+#define HASHVERSION 2
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+ u_int32_t bsize; /* bucket size */
+ u_int32_t ffactor; /* fill factor */
+ u_int32_t nelem; /* number of elements */
+ u_int32_t cachesize; /* bytes to cache */
+ u_int32_t /* hash function */
+ (*hash) __P((const void *, size_t));
+ int lorder; /* byte order */
+} HASHINFO;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define R_FIXEDLEN 0x01 /* fixed-length records */
+#define R_NOKEY 0x02 /* key not required */
+#define R_SNAPSHOT 0x04 /* snapshot the input */
+ u_int32_t flags;
+ u_int32_t cachesize; /* bytes to cache */
+ u_int32_t psize; /* page size */
+ int lorder; /* byte order */
+ size_t reclen; /* record length (fixed-length records) */
+ u_char bval; /* delimiting byte (variable-length records */
+ char *bfname; /* btree file name */
+} RECNOINFO;
+
+/* Re-define the user's dbopen calls. */
+#define dbopen __db185_open@DB_VERSION_UNIQUE_NAME@
+
+#endif /* !_DB_185_H_ */
diff --git a/bdb/dbinc/db_am.h b/bdb/dbinc/db_am.h
new file mode 100644
index 00000000000..c5aa424255d
--- /dev/null
+++ b/bdb/dbinc/db_am.h
@@ -0,0 +1,127 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_am.h,v 11.61 2002/08/08 03:20:46 bostic Exp $
+ */
+#ifndef _DB_AM_H_
+#define _DB_AM_H_
+
+/*
+ * IS_AUTO_COMMIT --
+ * Test for local auto-commit flag or global flag with no local DbTxn
+ * handle.
+ */
+#define IS_AUTO_COMMIT(dbenv, txn, flags) \
+ (LF_ISSET(DB_AUTO_COMMIT) || \
+ ((txn) == NULL && F_ISSET((dbenv), DB_ENV_AUTO_COMMIT)))
+
+/* DB recovery operation codes. */
+#define DB_ADD_DUP 1
+#define DB_REM_DUP 2
+#define DB_ADD_BIG 3
+#define DB_REM_BIG 4
+#define DB_ADD_PAGE 5
+#define DB_REM_PAGE 6
+
+/*
+ * Standard initialization and shutdown macros for all recovery functions.
+ */
+#define REC_INTRO(func, inc_count) { \
+ argp = NULL; \
+ dbc = NULL; \
+ file_dbp = NULL; \
+ mpf = NULL; \
+ if ((ret = func(dbenv, dbtp->data, &argp)) != 0) \
+ goto out; \
+ if ((ret = __dbreg_id_to_db(dbenv, argp->txnid, \
+ &file_dbp, argp->fileid, inc_count)) != 0) { \
+ if (ret == DB_DELETED) { \
+ ret = 0; \
+ goto done; \
+ } \
+ goto out; \
+ } \
+ if ((ret = file_dbp->cursor(file_dbp, NULL, &dbc, 0)) != 0) \
+ goto out; \
+ F_SET(dbc, DBC_RECOVER); \
+ mpf = file_dbp->mpf; \
+}
+
+#define REC_CLOSE { \
+ int __t_ret; \
+ if (argp != NULL) \
+ __os_free(dbenv, argp); \
+ if (dbc != NULL && \
+ (__t_ret = dbc->c_close(dbc)) != 0 && ret == 0) \
+ ret = __t_ret; \
+ return (ret); \
+}
+
+/*
+ * No-op versions of the same macros.
+ */
+#define REC_NOOP_INTRO(func) { \
+ argp = NULL; \
+ if ((ret = func(dbenv, dbtp->data, &argp)) != 0) \
+ return (ret); \
+}
+#define REC_NOOP_CLOSE \
+ if (argp != NULL) \
+ __os_free(dbenv, argp); \
+ return (ret); \
+
+/*
+ * Standard debugging macro for all recovery functions.
+ */
+#ifdef DEBUG_RECOVER
+#define REC_PRINT(func) \
+ (void)func(dbenv, dbtp, lsnp, op, info);
+#else
+#define REC_PRINT(func)
+#endif
+
+/*
+ * Actions to __db_lget
+ */
+#define LCK_ALWAYS 1 /* Lock even for off page dup cursors */
+#define LCK_COUPLE 2 /* Lock Couple */
+#define LCK_COUPLE_ALWAYS 3 /* Lock Couple even in txn. */
+#define LCK_DOWNGRADE 4 /* Downgrade the lock. (internal) */
+#define LCK_ROLLBACK 5 /* Lock even if in rollback */
+
+/*
+ * If doing transactions we have to hold the locks associated with a data item
+ * from a page for the entire transaction. However, we don't have to hold the
+ * locks associated with walking the tree. Distinguish between the two so that
+ * we don't tie up the internal pages of the tree longer than necessary.
+ */
+#define __LPUT(dbc, lock) \
+ (LOCK_ISSET(lock) ? \
+ (dbc)->dbp->dbenv->lock_put((dbc)->dbp->dbenv, &(lock)) : 0)
+
+/*
+ * __TLPUT -- transactional lock put
+ * If the lock is valid then
+ * If we are not in a transaction put the lock.
+ * Else if the cursor is doing dirty reads and this was a read then
+ * put the lock.
+ * Else if the db is supporting dirty reads and this is a write then
+ * downgrade it.
+ * Else do nothing.
+ */
+#define __TLPUT(dbc, lock) \
+ (LOCK_ISSET(lock) ? __db_lput(dbc, &(lock)) : 0)
+
+typedef struct {
+ DBC *dbc;
+ int count;
+} db_trunc_param;
+
+#include "dbinc/db_dispatch.h"
+#include "dbinc_auto/db_auto.h"
+#include "dbinc_auto/crdel_auto.h"
+#include "dbinc_auto/db_ext.h"
+#endif /* !_DB_AM_H_ */
diff --git a/bdb/dbinc/db_cxx.in b/bdb/dbinc/db_cxx.in
new file mode 100644
index 00000000000..6752b36ec42
--- /dev/null
+++ b/bdb/dbinc/db_cxx.in
@@ -0,0 +1,795 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_cxx.in,v 11.113 2002/08/23 13:02:27 mjc Exp $
+ */
+
+#ifndef _DB_CXX_H_
+#define _DB_CXX_H_
+//
+// C++ assumptions:
+//
+// To ensure portability to many platforms, both new and old, we make
+// few assumptions about the C++ compiler and library. For example,
+// we do not expect STL, templates or namespaces to be available. The
+// "newest" C++ feature used is exceptions, which are used liberally
+// to transmit error information. Even the use of exceptions can be
+// disabled at runtime, to do so, use the DB_CXX_NO_EXCEPTIONS flags
+// with the DbEnv or Db constructor.
+//
+// C++ naming conventions:
+//
+// - All top level class names start with Db.
+// - All class members start with lower case letter.
+// - All private data members are suffixed with underscore.
+// - Use underscores to divide names into multiple words.
+// - Simple data accessors are named with get_ or set_ prefix.
+// - All method names are taken from names of functions in the C
+// layer of db (usually by dropping a prefix like "db_").
+// These methods have the same argument types and order,
+// other than dropping the explicit arg that acts as "this".
+//
+// As a rule, each DbFoo object has exactly one underlying DB_FOO struct
+// (defined in db.h) associated with it. In some cases, we inherit directly
+// from the DB_FOO structure to make this relationship explicit. Often,
+// the underlying C layer allocates and deallocates these structures, so
+// there is no easy way to add any data to the DbFoo class. When you see
+// a comment about whether data is permitted to be added, this is what
+// is going on. Of course, if we need to add data to such C++ classes
+// in the future, we will arrange to have an indirect pointer to the
+// DB_FOO struct (as some of the classes already have).
+//
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Forward declarations
+//
+
+#include <stdarg.h>
+
+@cxx_have_stdheaders@
+#ifdef HAVE_CXX_STDHEADERS
+#include <iostream>
+#define __DB_OSTREAMCLASS std::ostream
+#else
+#include <iostream.h>
+#define __DB_OSTREAMCLASS ostream
+#endif
+
+#include "db.h"
+#include "cxx_common.h"
+#include "cxx_except.h"
+
+class Db; // forward
+class Dbc; // forward
+class DbEnv; // forward
+class DbInfo; // forward
+class DbLock; // forward
+class DbLogc; // forward
+class DbLsn; // forward
+class DbMpoolFile; // forward
+class DbPreplist; // forward
+class Dbt; // forward
+class DbTxn; // forward
+
+// These classes are not defined here and should be invisible
+// to the user, but some compilers require forward references.
+// There is one for each use of the DEFINE_DB_CLASS macro.
+
+class DbImp;
+class DbEnvImp;
+class DbMpoolFileImp;
+class DbTxnImp;
+
+// DEFINE_DB_CLASS defines an imp_ data member and imp() accessor.
+// The underlying type is a pointer to an opaque *Imp class, that
+// gets converted to the correct implementation class by the implementation.
+//
+// Since these defines use "private/public" labels, and leave the access
+// being "private", we always use these by convention before any data
+// members in the private section of a class. Keeping them in the
+// private section also emphasizes that they are off limits to user code.
+//
+#define DEFINE_DB_CLASS(name) \
+ public: class name##Imp* imp() { return (imp_); } \
+ public: const class name##Imp* constimp() const { return (imp_); } \
+ private: class name##Imp* imp_
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Turn off inappropriate compiler warnings
+//
+
+#ifdef _MSC_VER
+
+// These are level 4 warnings that are explicitly disabled.
+// With Visual C++, by default you do not see above level 3 unless
+// you use /W4. But we like to compile with the highest level
+// warnings to catch other errors.
+//
+// 4201: nameless struct/union
+// triggered by standard include file <winnt.h>
+//
+// 4514: unreferenced inline function has been removed
+// certain include files in MSVC define methods that are not called
+//
+#pragma warning(disable: 4201 4514)
+
+#endif
+
+// Some interfaces can be customized by allowing users to define
+// callback functions. For performance and logistical reasons, some
+// callback functions must be declared in extern "C" blocks. For others,
+// we allow you to declare the callbacks in C++ or C (or an extern "C"
+// block) as you wish. See the set methods for the callbacks for
+// the choices.
+//
+extern "C" {
+ typedef void * (*db_malloc_fcn_type)
+ (size_t);
+ typedef void * (*db_realloc_fcn_type)
+ (void *, size_t);
+ typedef void (*db_free_fcn_type)
+ (void *);
+ typedef int (*bt_compare_fcn_type) /*C++ version available*/
+ (DB *, const DBT *, const DBT *);
+ typedef size_t (*bt_prefix_fcn_type) /*C++ version available*/
+ (DB *, const DBT *, const DBT *);
+ typedef int (*dup_compare_fcn_type) /*C++ version available*/
+ (DB *, const DBT *, const DBT *);
+ typedef u_int32_t (*h_hash_fcn_type) /*C++ version available*/
+ (DB *, const void *, u_int32_t);
+ typedef int (*pgin_fcn_type)
+ (DB_ENV *dbenv, db_pgno_t pgno, void *pgaddr, DBT *pgcookie);
+ typedef int (*pgout_fcn_type)
+ (DB_ENV *dbenv, db_pgno_t pgno, void *pgaddr, DBT *pgcookie);
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Lock classes
+//
+
+class _exported DbLock
+{
+ friend class DbEnv;
+
+public:
+ DbLock();
+ DbLock(const DbLock &);
+ DbLock &operator = (const DbLock &);
+
+protected:
+ // We can add data to this class if needed
+ // since its contained class is not allocated by db.
+ // (see comment at top)
+
+ DbLock(DB_LOCK);
+ DB_LOCK lock_;
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Log classes
+//
+
+class _exported DbLsn : protected DB_LSN
+{
+ friend class DbEnv; // friendship needed to cast to base class
+ friend class DbLogc; // friendship needed to cast to base class
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Memory pool classes
+//
+
+class _exported DbMpoolFile
+{
+ friend class DbEnv;
+
+private:
+ // Put this first to allow inlining with some C++ compilers (g++-2.95)
+ DEFINE_DB_CLASS(DbMpoolFile);
+
+public:
+ int close(u_int32_t flags);
+ int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep);
+ void last_pgno(db_pgno_t *pgnoaddr);
+ int open(const char *file, u_int32_t flags, int mode, size_t pagesize);
+ int put(void *pgaddr, u_int32_t flags);
+ void refcnt(db_pgno_t *pgnoaddr);
+ int set(void *pgaddr, u_int32_t flags);
+ int set_clear_len(u_int32_t len);
+ int set_fileid(u_int8_t *fileid);
+ int set_ftype(int ftype);
+ int set_lsn_offset(int32_t offset);
+ int set_pgcookie(DBT *dbt);
+ void set_unlink(int);
+ int sync();
+
+ virtual DB_MPOOLFILE *get_DB_MPOOLFILE()
+ {
+ return (DB_MPOOLFILE *)imp();
+ }
+
+ virtual const DB_MPOOLFILE *get_const_DB_MPOOLFILE() const
+ {
+ return (const DB_MPOOLFILE *)constimp();
+ }
+
+private:
+ // We can add data to this class if needed
+ // since it is implemented via a pointer.
+ // (see comment at top)
+
+ // Note: use DbEnv::memp_fcreate() to get pointers to a DbMpoolFile,
+ // and call DbMpoolFile::close() rather than delete to release them.
+ //
+ DbMpoolFile();
+
+ // Shut g++ up.
+protected:
+ virtual ~DbMpoolFile();
+
+private:
+ // no copying
+ DbMpoolFile(const DbMpoolFile &);
+ void operator = (const DbMpoolFile &);
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// This is filled in and returned by the DbEnv::txn_recover() method.
+//
+
+class _exported DbPreplist
+{
+public:
+ DbTxn *txn;
+ u_int8_t gid[DB_XIDDATASIZE];
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Transaction classes
+//
+
+class _exported DbTxn
+{
+ friend class DbEnv;
+
+private:
+ // Put this first to allow inlining with some C++ compilers (g++-2.95)
+ DEFINE_DB_CLASS(DbTxn);
+
+public:
+ int abort();
+ int commit(u_int32_t flags);
+ int discard(u_int32_t flags);
+ u_int32_t id();
+ int prepare(u_int8_t *gid);
+ int set_timeout(db_timeout_t timeout, u_int32_t flags);
+
+ virtual DB_TXN *get_DB_TXN()
+ {
+ return (DB_TXN *)imp();
+ }
+
+ virtual const DB_TXN *get_const_DB_TXN() const
+ {
+ return (const DB_TXN *)constimp();
+ }
+
+ static DbTxn* get_DbTxn(DB_TXN *txn)
+ {
+ return (DbTxn *)txn->api_internal;
+ }
+
+ static const DbTxn* get_const_DbTxn(const DB_TXN *txn)
+ {
+ return (const DbTxn *)txn->api_internal;
+ }
+
+ // For internal use only.
+ static DbTxn* wrap_DB_TXN(DB_TXN *txn);
+
+private:
+ // We can add data to this class if needed
+ // since it is implemented via a pointer.
+ // (see comment at top)
+
+ // Note: use DbEnv::txn_begin() to get pointers to a DbTxn,
+ // and call DbTxn::abort() or DbTxn::commit rather than
+ // delete to release them.
+ //
+ DbTxn();
+ // For internal use only.
+ DbTxn(DB_TXN *txn);
+ virtual ~DbTxn();
+
+ // no copying
+ DbTxn(const DbTxn &);
+ void operator = (const DbTxn &);
+};
+
+//
+// Berkeley DB environment class. Provides functions for opening databases.
+// User of this library can use this class as a starting point for
+// developing a DB application - derive their application class from
+// this one, add application control logic.
+//
+// Note that if you use the default constructor, you must explicitly
+// call appinit() before any other db activity (e.g. opening files)
+//
+class _exported DbEnv
+{
+ friend class Db;
+ friend class DbLock;
+ friend class DbMpoolFile;
+
+private:
+ // Put this first to allow inlining with some C++ compilers (g++-2.95)
+ DEFINE_DB_CLASS(DbEnv);
+
+public:
+ // After using this constructor, you can set any needed
+ // parameters for the environment using the set_* methods.
+ // Then call open() to finish initializing the environment
+ // and attaching it to underlying files.
+ //
+ DbEnv(u_int32_t flags);
+
+ virtual ~DbEnv();
+
+ // These methods match those in the C interface.
+ //
+ virtual int close(u_int32_t);
+ virtual int dbremove(DbTxn *txn, const char *name, const char *subdb,
+ u_int32_t flags);
+ virtual int dbrename(DbTxn *txn, const char *name, const char *subdb,
+ const char *newname, u_int32_t flags);
+ virtual void err(int, const char *, ...);
+ virtual void errx(const char *, ...);
+ virtual void *get_app_private() const;
+ virtual int open(const char *, u_int32_t, int);
+ virtual int remove(const char *, u_int32_t);
+ virtual int set_alloc(db_malloc_fcn_type, db_realloc_fcn_type,
+ db_free_fcn_type);
+ virtual void set_app_private(void *);
+ virtual int set_cachesize(u_int32_t, u_int32_t, int);
+ virtual int set_data_dir(const char *);
+ virtual int set_encrypt(const char *, int);
+ virtual void set_errcall(void (*)(const char *, char *));
+ virtual void set_errfile(FILE *);
+ virtual void set_errpfx(const char *);
+ virtual int set_flags(u_int32_t, int);
+ virtual int set_feedback(void (*)(DbEnv *, int, int));
+ virtual int set_lg_bsize(u_int32_t);
+ virtual int set_lg_dir(const char *);
+ virtual int set_lg_max(u_int32_t);
+ virtual int set_lg_regionmax(u_int32_t);
+ virtual int set_lk_conflicts(u_int8_t *, int);
+ virtual int set_lk_detect(u_int32_t);
+ virtual int set_lk_max(u_int32_t);
+ virtual int set_lk_max_lockers(u_int32_t);
+ virtual int set_lk_max_locks(u_int32_t);
+ virtual int set_lk_max_objects(u_int32_t);
+ virtual int set_mp_mmapsize(size_t);
+ virtual int set_paniccall(void (*)(DbEnv *, int));
+ virtual int set_rpc_server(void *, char *, long, long, u_int32_t);
+ virtual int set_shm_key(long);
+ virtual int set_timeout(db_timeout_t timeout, u_int32_t flags);
+ virtual int set_tmp_dir(const char *);
+ virtual int set_tas_spins(u_int32_t);
+ virtual int set_tx_max(u_int32_t);
+ virtual int set_app_dispatch(int (*)(DbEnv *,
+ Dbt *, DbLsn *, db_recops));
+ virtual int set_tx_timestamp(time_t *);
+ virtual int set_verbose(u_int32_t which, int onoff);
+
+ // Version information. A static method so it can be obtained anytime.
+ //
+ static char *version(int *major, int *minor, int *patch);
+
+ // Convert DB errors to strings
+ static char *strerror(int);
+
+ // If an error is detected and the error call function
+ // or stream is set, a message is dispatched or printed.
+ // If a prefix is set, each message is prefixed.
+ //
+ // You can use set_errcall() or set_errfile() above to control
+ // error functionality. Alternatively, you can call
+ // set_error_stream() to force all errors to a C++ stream.
+ // It is unwise to mix these approaches.
+ //
+ virtual void set_error_stream(__DB_OSTREAMCLASS *);
+
+ // used internally
+ static void runtime_error(const char *caller, int err,
+ int error_policy);
+ static void runtime_error_dbt(const char *caller, Dbt *dbt,
+ int error_policy);
+ static void runtime_error_lock_get(const char *caller, int err,
+ db_lockop_t op, db_lockmode_t mode,
+ const Dbt *obj, DbLock lock, int index,
+ int error_policy);
+
+ // Lock functions
+ //
+ virtual int lock_detect(u_int32_t flags, u_int32_t atype, int *aborted);
+ virtual int lock_get(u_int32_t locker, u_int32_t flags, const Dbt *obj,
+ db_lockmode_t lock_mode, DbLock *lock);
+ virtual int lock_id(u_int32_t *idp);
+ virtual int lock_id_free(u_int32_t id);
+ virtual int lock_put(DbLock *lock);
+ virtual int lock_stat(DB_LOCK_STAT **statp, u_int32_t flags);
+ virtual int lock_vec(u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
+ int nlist, DB_LOCKREQ **elistp);
+
+ // Log functions
+ //
+ virtual int log_archive(char **list[], u_int32_t flags);
+ static int log_compare(const DbLsn *lsn0, const DbLsn *lsn1);
+ virtual int log_cursor(DbLogc **cursorp, u_int32_t flags);
+ virtual int log_file(DbLsn *lsn, char *namep, size_t len);
+ virtual int log_flush(const DbLsn *lsn);
+ virtual int log_put(DbLsn *lsn, const Dbt *data, u_int32_t flags);
+
+ virtual int log_stat(DB_LOG_STAT **spp, u_int32_t flags);
+
+ // Mpool functions
+ //
+ virtual int memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags);
+ virtual int memp_register(int ftype,
+ pgin_fcn_type pgin_fcn,
+ pgout_fcn_type pgout_fcn);
+ virtual int memp_stat(DB_MPOOL_STAT
+ **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags);
+ virtual int memp_sync(DbLsn *lsn);
+ virtual int memp_trickle(int pct, int *nwrotep);
+
+ // Transaction functions
+ //
+ virtual int txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags);
+ virtual int txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags);
+ virtual int txn_recover(DbPreplist *preplist, long count,
+ long *retp, u_int32_t flags);
+ virtual int txn_stat(DB_TXN_STAT **statp, u_int32_t flags);
+
+ // Replication functions
+ //
+ virtual int rep_elect(int, int, u_int32_t, int *);
+ virtual int rep_process_message(Dbt *, Dbt *, int *);
+ virtual int rep_start(Dbt *, u_int32_t);
+ virtual int rep_stat(DB_REP_STAT **statp, u_int32_t flags);
+ virtual int set_rep_limit(u_int32_t, u_int32_t);
+ virtual int set_rep_transport(u_int32_t,
+ int (*)(DbEnv *, const Dbt *, const Dbt *, int, u_int32_t));
+
+ // Conversion functions
+ //
+ virtual DB_ENV *get_DB_ENV()
+ {
+ return (DB_ENV *)imp();
+ }
+
+ virtual const DB_ENV *get_const_DB_ENV() const
+ {
+ return (const DB_ENV *)constimp();
+ }
+
+ static DbEnv* get_DbEnv(DB_ENV *dbenv)
+ {
+ return (DbEnv *)dbenv->api1_internal;
+ }
+
+ static const DbEnv* get_const_DbEnv(const DB_ENV *dbenv)
+ {
+ return (const DbEnv *)dbenv->api1_internal;
+ }
+
+ // For internal use only.
+ static DbEnv* wrap_DB_ENV(DB_ENV *dbenv);
+
+ // These are public only because they need to be called
+ // via C functions. They should never be called by users
+ // of this class.
+ //
+ static void _stream_error_function(const char *, char *);
+ static int _app_dispatch_intercept(DB_ENV *env, DBT *dbt, DB_LSN *lsn,
+ db_recops op);
+ static void _paniccall_intercept(DB_ENV *env, int errval);
+ static void _feedback_intercept(DB_ENV *env, int opcode, int pct);
+ static int _rep_send_intercept(DB_ENV *env,
+ const DBT *cntrl, const DBT *data,
+ int id, u_int32_t flags);
+
+private:
+ void cleanup();
+ int initialize(DB_ENV *env);
+ int error_policy();
+
+ // For internal use only.
+ DbEnv(DB_ENV *, u_int32_t flags);
+
+ // no copying
+ DbEnv(const DbEnv &);
+ void operator = (const DbEnv &);
+
+ // instance data
+ int construct_error_;
+ u_int32_t construct_flags_;
+ int (*app_dispatch_callback_)(DbEnv *, Dbt *, DbLsn *, db_recops);
+ void (*feedback_callback_)(DbEnv *, int, int);
+ void (*paniccall_callback_)(DbEnv *, int);
+ int (*pgin_callback_)(DbEnv *dbenv, db_pgno_t pgno,
+ void *pgaddr, Dbt *pgcookie);
+ int (*pgout_callback_)(DbEnv *dbenv, db_pgno_t pgno,
+ void *pgaddr, Dbt *pgcookie);
+ int (*rep_send_callback_)(DbEnv *,
+ const Dbt *, const Dbt *, int, u_int32_t);
+
+ // class data
+ static __DB_OSTREAMCLASS *error_stream_;
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Table access classes
+//
+
+//
+// Represents a database table = a set of keys with associated values.
+//
+class _exported Db
+{
+ friend class DbEnv;
+
+private:
+ // Put this first to allow inlining with some C++ compilers (g++-2.95)
+ DEFINE_DB_CLASS(Db);
+
+public:
+ Db(DbEnv*, u_int32_t); // create a Db object, then call open()
+ virtual ~Db(); // does *not* call close.
+
+ // These methods exactly match those in the C interface.
+ //
+ virtual int associate(DbTxn *txn, Db *secondary,
+ int (*callback)(Db *, const Dbt *, const Dbt *, Dbt *),
+ u_int32_t flags);
+ virtual int close(u_int32_t flags);
+ virtual int cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags);
+ virtual int del(DbTxn *txnid, Dbt *key, u_int32_t flags);
+ virtual void err(int, const char *, ...);
+ virtual void errx(const char *, ...);
+ virtual int fd(int *fdp);
+ virtual int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
+ virtual void *get_app_private() const;
+ virtual int get_byteswapped(int *);
+ virtual int get_type(DBTYPE *);
+ virtual int join(Dbc **curslist, Dbc **dbcp, u_int32_t flags);
+ virtual int key_range(DbTxn *, Dbt *, DB_KEY_RANGE *, u_int32_t);
+ virtual int open(DbTxn *txnid,
+ const char *, const char *subname, DBTYPE, u_int32_t, int);
+ virtual int pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *data,
+ u_int32_t flags);
+ virtual int put(DbTxn *, Dbt *, Dbt *, u_int32_t);
+ virtual int remove(const char *, const char *, u_int32_t);
+ virtual int rename(const char *, const char *, const char *, u_int32_t);
+ virtual int set_alloc(db_malloc_fcn_type, db_realloc_fcn_type,
+ db_free_fcn_type);
+ virtual void set_app_private(void *);
+ virtual int set_append_recno(int (*)(Db *, Dbt *, db_recno_t));
+ virtual int set_bt_compare(bt_compare_fcn_type); /*deprecated*/
+ virtual int set_bt_compare(int (*)(Db *, const Dbt *, const Dbt *));
+ virtual int set_bt_maxkey(u_int32_t);
+ virtual int set_bt_minkey(u_int32_t);
+ virtual int set_bt_prefix(bt_prefix_fcn_type); /*deprecated*/
+ virtual int set_bt_prefix(size_t (*)(Db *, const Dbt *, const Dbt *));
+ virtual int set_cachesize(u_int32_t, u_int32_t, int);
+ virtual int set_cache_priority(DB_CACHE_PRIORITY);
+ virtual int set_dup_compare(dup_compare_fcn_type); /*deprecated*/
+ virtual int set_dup_compare(int (*)(Db *, const Dbt *, const Dbt *));
+ virtual int set_encrypt(const char *, int);
+ virtual void set_errcall(void (*)(const char *, char *));
+ virtual void set_errfile(FILE *);
+ virtual void set_errpfx(const char *);
+ virtual int set_feedback(void (*)(Db *, int, int));
+ virtual int set_flags(u_int32_t);
+ virtual int set_h_ffactor(u_int32_t);
+ virtual int set_h_hash(h_hash_fcn_type); /*deprecated*/
+ virtual int set_h_hash(u_int32_t (*)(Db *, const void *, u_int32_t));
+ virtual int set_h_nelem(u_int32_t);
+ virtual int set_lorder(int);
+ virtual int set_pagesize(u_int32_t);
+ virtual int set_paniccall(void (*)(DbEnv *, int));
+ virtual int set_re_delim(int);
+ virtual int set_re_len(u_int32_t);
+ virtual int set_re_pad(int);
+ virtual int set_re_source(char *);
+ virtual int set_q_extentsize(u_int32_t);
+ virtual int stat(void *sp, u_int32_t flags);
+ virtual int sync(u_int32_t flags);
+ virtual int truncate(DbTxn *, u_int32_t *, u_int32_t);
+ virtual int upgrade(const char *name, u_int32_t flags);
+ virtual int verify(const char *, const char *, __DB_OSTREAMCLASS *, u_int32_t);
+
+ // These additional methods are not in the C interface, and
+ // are only available for C++.
+ //
+ virtual void set_error_stream(__DB_OSTREAMCLASS *);
+
+ virtual DB *get_DB()
+ {
+ return (DB *)imp();
+ }
+
+ virtual const DB *get_const_DB() const
+ {
+ return (const DB *)constimp();
+ }
+
+ static Db* get_Db(DB *db)
+ {
+ return (Db *)db->api_internal;
+ }
+
+ static const Db* get_const_Db(const DB *db)
+ {
+ return (const Db *)db->api_internal;
+ }
+
+private:
+ // no copying
+ Db(const Db &);
+ Db &operator = (const Db &);
+
+ void cleanup();
+ int initialize();
+ int error_policy();
+
+ // instance data
+ DbEnv *env_;
+ int construct_error_;
+ u_int32_t flags_;
+ u_int32_t construct_flags_;
+
+public:
+ // These are public only because they need to be called
+ // via C callback functions. They should never be used by
+ // external users of this class.
+ //
+ int (*append_recno_callback_)(Db *, Dbt *, db_recno_t);
+ int (*associate_callback_)(Db *, const Dbt *, const Dbt *, Dbt *);
+ int (*bt_compare_callback_)(Db *, const Dbt *, const Dbt *);
+ size_t (*bt_prefix_callback_)(Db *, const Dbt *, const Dbt *);
+ int (*dup_compare_callback_)(Db *, const Dbt *, const Dbt *);
+ void (*feedback_callback_)(Db *, int, int);
+ u_int32_t (*h_hash_callback_)(Db *, const void *, u_int32_t);
+};
+
+//
+// A chunk of data, maybe a key or value.
+//
+class _exported Dbt : private DBT
+{
+ friend class Dbc;
+ friend class Db;
+ friend class DbEnv;
+ friend class DbLogc;
+
+public:
+
+ // key/data
+ void *get_data() const { return data; }
+ void set_data(void *value) { data = value; }
+
+ // key/data length
+ u_int32_t get_size() const { return size; }
+ void set_size(u_int32_t value) { size = value; }
+
+ // RO: length of user buffer.
+ u_int32_t get_ulen() const { return ulen; }
+ void set_ulen(u_int32_t value) { ulen = value; }
+
+ // RO: get/put record length.
+ u_int32_t get_dlen() const { return dlen; }
+ void set_dlen(u_int32_t value) { dlen = value; }
+
+ // RO: get/put record offset.
+ u_int32_t get_doff() const { return doff; }
+ void set_doff(u_int32_t value) { doff = value; }
+
+ // flags
+ u_int32_t get_flags() const { return flags; }
+ void set_flags(u_int32_t value) { flags = value; }
+
+ // Conversion functions
+ DBT *get_DBT() { return (DBT *)this; }
+ const DBT *get_const_DBT() const { return (const DBT *)this; }
+
+ static Dbt* get_Dbt(DBT *dbt) { return (Dbt *)dbt; }
+ static const Dbt* get_const_Dbt(const DBT *dbt)
+ { return (const Dbt *)dbt; }
+
+ Dbt(void *data, u_int32_t size);
+ Dbt();
+ ~Dbt();
+ Dbt(const Dbt &);
+ Dbt &operator = (const Dbt &);
+
+private:
+ // Note: no extra data appears in this class (other than
+ // inherited from DBT) since we need DBT and Dbt objects
+ // to have interchangable pointers.
+ //
+ // When subclassing this class, remember that callback
+ // methods like bt_compare, bt_prefix, dup_compare may
+ // internally manufacture DBT objects (which later are
+ // cast to Dbt), so such callbacks might receive objects
+ // not of your subclassed type.
+};
+
+class _exported Dbc : protected DBC
+{
+ friend class Db;
+
+public:
+ int close();
+ int count(db_recno_t *countp, u_int32_t flags);
+ int del(u_int32_t flags);
+ int dup(Dbc** cursorp, u_int32_t flags);
+ int get(Dbt* key, Dbt *data, u_int32_t flags);
+ int pget(Dbt* key, Dbt* pkey, Dbt *data, u_int32_t flags);
+ int put(Dbt* key, Dbt *data, u_int32_t flags);
+
+private:
+ // No data is permitted in this class (see comment at top)
+
+ // Note: use Db::cursor() to get pointers to a Dbc,
+ // and call Dbc::close() rather than delete to release them.
+ //
+ Dbc();
+ ~Dbc();
+
+ // no copying
+ Dbc(const Dbc &);
+ Dbc &operator = (const Dbc &);
+};
+
+class _exported DbLogc : protected DB_LOGC
+{
+ friend class DbEnv;
+
+public:
+ int close(u_int32_t _flags);
+ int get(DbLsn *lsn, Dbt *data, u_int32_t _flags);
+
+private:
+ // No data is permitted in this class (see comment at top)
+
+ // Note: use Db::cursor() to get pointers to a Dbc,
+ // and call Dbc::close() rather than delete to release them.
+ //
+ DbLogc();
+ ~DbLogc();
+
+ // no copying
+ DbLogc(const Dbc &);
+ DbLogc &operator = (const Dbc &);
+};
+#endif /* !_DB_CXX_H_ */
diff --git a/bdb/dbinc/db_dispatch.h b/bdb/dbinc/db_dispatch.h
new file mode 100644
index 00000000000..283eb1e95de
--- /dev/null
+++ b/bdb/dbinc/db_dispatch.h
@@ -0,0 +1,105 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1995, 1996
+ * The President and Fellows of Harvard University. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: db_dispatch.h,v 11.30 2002/06/20 19:34:03 margo Exp $
+ */
+
+#ifndef _DB_DISPATCH_H_
+#define _DB_DISPATCH_H_
+
+/*
+ * Declarations and typedefs for the list of transaction IDs used during
+ * recovery. This is a generic list used to pass along whatever information
+ * we need during recovery.
+ */
+typedef enum {
+ TXNLIST_DELETE,
+ TXNLIST_LSN,
+ TXNLIST_PGNO,
+ TXNLIST_TXNID
+} db_txnlist_type;
+
+#define DB_TXNLIST_MASK(hp, n) (n % hp->nslots)
+struct __db_txnhead {
+ u_int32_t maxid; /* Maximum transaction id. */
+ DB_LSN maxlsn; /* Maximum commit lsn. */
+ DB_LSN ckplsn; /* LSN of last retained checkpoint. */
+ DB_LSN trunc_lsn; /* Lsn to which we are going to truncate;
+ * make sure we abort anyone after this. */
+ int32_t generation; /* Current generation number. */
+ int32_t gen_alloc; /* Number of generations allocated. */
+ struct {
+ int32_t generation;
+ u_int32_t txn_min;
+ u_int32_t txn_max;
+ } *gen_array; /* Array of txnids associted with a gen. */
+ int nslots;
+ LIST_HEAD(__db_headlink, __db_txnlist) head[1];
+};
+
+struct __db_txnlist {
+ db_txnlist_type type;
+ LIST_ENTRY(__db_txnlist) links;
+ union {
+ struct {
+ u_int32_t txnid;
+ int32_t generation;
+ int32_t status;
+ } t;
+ struct {
+ int32_t ntxns;
+ int32_t maxn;
+ DB_LSN *lsn_array;
+ } l;
+ struct {
+ int32_t nentries;
+ int32_t maxentry;
+ int32_t locked;
+ char *fname;
+ int32_t fileid;
+ db_pgno_t *pgno_array;
+ u_int8_t uid[DB_FILE_ID_LEN];
+ } p;
+ } u;
+};
+
+/*
+ * Flag value for __db_txnlist_lsnadd. Distinguish whether we are replacing
+ * an entry in the transaction list or adding a new one.
+ */
+#define TXNLIST_NEW 0x1
+
+#define DB_user_BEGIN 10000
+
+#endif /* !_DB_DISPATCH_H_ */
diff --git a/bdb/dbinc/db_int.in b/bdb/dbinc/db_int.in
new file mode 100644
index 00000000000..2f46293a65d
--- /dev/null
+++ b/bdb/dbinc/db_int.in
@@ -0,0 +1,473 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_int.in,v 11.106 2002/09/10 02:48:08 bostic Exp $
+ */
+
+#ifndef _DB_INTERNAL_H_
+#define _DB_INTERNAL_H_
+
+/*******************************************************
+ * System includes, db.h, a few general DB includes. The DB includes are
+ * here because it's OK if db_int.h includes queue structure declarations.
+ *******************************************************/
+#ifndef NO_SYSTEM_INCLUDES
+#if defined(__STDC__) || defined(__cplusplus)
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <errno.h>
+#endif
+
+#include "db.h"
+
+#include "dbinc/queue.h"
+#include "dbinc/shqueue.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*******************************************************
+ * General purpose constants and macros.
+ *******************************************************/
+#define UINT16_T_MAX 0xffff /* Maximum 16 bit unsigned. */
+#define UINT32_T_MAX 0xffffffff /* Maximum 32 bit unsigned. */
+
+#define MEGABYTE 1048576
+#define GIGABYTE 1073741824
+
+#define MS_PER_SEC 1000 /* Milliseconds in a second. */
+#define USEC_PER_MS 1000 /* Microseconds in a millisecond. */
+
+#define RECNO_OOB 0 /* Illegal record number. */
+
+/* Test for a power-of-two (tests true for zero, which doesn't matter here). */
+#define POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
+
+/* Test for valid page sizes. */
+#define DB_MIN_PGSIZE 0x000200 /* Minimum page size (512). */
+#define DB_MAX_PGSIZE 0x010000 /* Maximum page size (65536). */
+#define IS_VALID_PAGESIZE(x) \
+ (POWER_OF_TWO(x) && (x) >= DB_MIN_PGSIZE && ((x) <= DB_MAX_PGSIZE))
+
+/* Minimum number of pages cached, by default. */
+#define DB_MINPAGECACHE 16
+
+/*
+ * If we are unable to determine the underlying filesystem block size, use
+ * 8K on the grounds that most OS's use less than 8K for a VM page size.
+ */
+#define DB_DEF_IOSIZE (8 * 1024)
+
+/*
+ * Aligning items to particular sizes or in pages or memory.
+ *
+ * db_align_t --
+ * Largest integral type, used to align structures in memory. We don't store
+ * floating point types in structures, so integral types should be sufficient
+ * (and we don't have to worry about systems that store floats in other than
+ * power-of-2 numbers of bytes). Additionally this fixes compiler that rewrite
+ * structure assignments and ANSI C memcpy calls to be in-line instructions
+ * that happen to require alignment. Note: this alignment isn't sufficient for
+ * mutexes, which depend on things like cache line alignment. Mutex alignment
+ * is handled separately, in mutex.h.
+ *
+ * db_alignp_t --
+ * Integral type that's the same size as a pointer. There are places where
+ * DB modifies pointers by discarding the bottom bits to guarantee alignment.
+ * We can't use db_align_t, it may be larger than the pointer, and compilers
+ * get upset about that. So far we haven't run on any machine where there
+ * isn't an integral type the same size as a pointer -- here's hoping.
+ */
+@db_align_t_decl@
+@db_alignp_t_decl@
+
+/* Align an integer to a specific boundary. */
+#undef ALIGN
+#define ALIGN(v, bound) (((v) + (bound) - 1) & ~(((db_align_t)bound) - 1))
+
+/*
+ * Print an address as a u_long (a u_long is the largest type we can print
+ * portably). Most 64-bit systems have made longs 64-bits, so this should
+ * work.
+ */
+#define P_TO_ULONG(p) ((u_long)(db_alignp_t)(p))
+
+/*
+ * Convert a pointer to a small integral value.
+ *
+ * The (u_int16_t)(db_alignp_t) cast avoids warnings: the (db_alignp_t) cast
+ * converts the value to an integral type, and the (u_int16_t) cast converts
+ * it to a small integral type so we don't get complaints when we assign the
+ * final result to an integral type smaller than db_alignp_t.
+ */
+#define P_TO_UINT32(p) ((u_int32_t)(db_alignp_t)(p))
+#define P_TO_UINT16(p) ((u_int16_t)(db_alignp_t)(p))
+
+/*
+ * There are several on-page structures that are declared to have a number of
+ * fields followed by a variable length array of items. The structure size
+ * without including the variable length array or the address of the first of
+ * those elements can be found using SSZ.
+ *
+ * This macro can also be used to find the offset of a structure element in a
+ * structure. This is used in various places to copy structure elements from
+ * unaligned memory references, e.g., pointers into a packed page.
+ *
+ * There are two versions because compilers object if you take the address of
+ * an array.
+ */
+#undef SSZ
+#define SSZ(name, field) P_TO_UINT16(&(((name *)0)->field))
+
+#undef SSZA
+#define SSZA(name, field) P_TO_UINT16(&(((name *)0)->field[0]))
+
+/* Structure used to print flag values. */
+typedef struct __fn {
+ u_int32_t mask; /* Flag value. */
+ const char *name; /* Flag name. */
+} FN;
+
+/* Set, clear and test flags. */
+#define FLD_CLR(fld, f) (fld) &= ~(f)
+#define FLD_ISSET(fld, f) ((fld) & (f))
+#define FLD_SET(fld, f) (fld) |= (f)
+#define F_CLR(p, f) (p)->flags &= ~(f)
+#define F_ISSET(p, f) ((p)->flags & (f))
+#define F_SET(p, f) (p)->flags |= (f)
+#define LF_CLR(f) ((flags) &= ~(f))
+#define LF_ISSET(f) ((flags) & (f))
+#define LF_SET(f) ((flags) |= (f))
+
+/* Display separator string. */
+#undef DB_LINE
+#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
+
+/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
+#define COMPQUIET(n, v) (n) = (v)
+
+/*******************************************************
+ * API return values
+ *******************************************************/
+ /*
+ * Return values that are OK for each different call. Most calls have
+ * a standard 'return of 0 is only OK value', but some, like db->get
+ * have DB_NOTFOUND as a return value, but it really isn't an error.
+ */
+#define DB_RETOK_STD(ret) ((ret) == 0)
+#define DB_RETOK_DBCDEL(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \
+ (ret) == DB_NOTFOUND)
+#define DB_RETOK_DBCGET(ret) DB_RETOK_DBGET(ret)
+#define DB_RETOK_DBCPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST || \
+ (ret) == DB_NOTFOUND)
+#define DB_RETOK_DBDEL(ret) ((ret) == 0 || (ret) == DB_NOTFOUND)
+#define DB_RETOK_DBGET(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \
+ (ret) == DB_NOTFOUND)
+#define DB_RETOK_DBPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST)
+#define DB_RETOK_LGGET(ret) ((ret) == 0 || (ret) == DB_NOTFOUND)
+#define DB_RETOK_MPGET(ret) ((ret) == 0 || (ret) == DB_PAGE_NOTFOUND)
+#define DB_RETOK_REPPMSG(ret) ((ret) == 0 || (ret) == DB_REP_NEWMASTER || \
+ (ret) == DB_REP_NEWSITE)
+
+/*******************************************************
+ * Files.
+ *******************************************************/
+ /*
+ * We use 1024 as the maximum path length. It's too hard to figure out what
+ * the real path length is, as it was traditionally stored in <sys/param.h>,
+ * and that file isn't always available.
+ */
+#undef MAXPATHLEN
+#define MAXPATHLEN 1024
+
+#define PATH_DOT "." /* Current working directory. */
+#define PATH_SEPARATOR "/" /* Path separator character(s). */
+
+/*
+ * Flags understood by __os_open.
+ */
+#define DB_OSO_CREATE 0x0001 /* POSIX: O_CREAT */
+#define DB_OSO_DIRECT 0x0002 /* Don't buffer the file in the OS. */
+#define DB_OSO_EXCL 0x0004 /* POSIX: O_EXCL */
+#define DB_OSO_LOG 0x0008 /* Opening a log file. */
+#define DB_OSO_RDONLY 0x0010 /* POSIX: O_RDONLY */
+#define DB_OSO_REGION 0x0020 /* Opening a region file. */
+#define DB_OSO_SEQ 0x0040 /* Expected sequential access. */
+#define DB_OSO_TEMP 0x0080 /* Remove after last close. */
+#define DB_OSO_TRUNC 0x0100 /* POSIX: O_TRUNC */
+
+/*
+ * Seek options understood by __os_seek.
+ */
+typedef enum {
+ DB_OS_SEEK_CUR, /* POSIX: SEEK_CUR */
+ DB_OS_SEEK_END, /* POSIX: SEEK_END */
+ DB_OS_SEEK_SET /* POSIX: SEEK_SET */
+} DB_OS_SEEK;
+
+/*******************************************************
+ * Environment.
+ *******************************************************/
+/* Type passed to __db_appname(). */
+typedef enum {
+ DB_APP_NONE=0, /* No type (region). */
+ DB_APP_DATA, /* Data file. */
+ DB_APP_LOG, /* Log file. */
+ DB_APP_TMP /* Temporary file. */
+} APPNAME;
+
+/*
+ * CDB_LOCKING CDB product locking.
+ * CRYPTO_ON Security has been configured.
+ * LOCKING_ON Locking has been configured.
+ * LOGGING_ON Logging has been configured.
+ * MPOOL_ON Memory pool has been configured.
+ * RPC_ON RPC has been configured.
+ * TXN_ON Transactions have been configured.
+ */
+#define CDB_LOCKING(dbenv) F_ISSET(dbenv, DB_ENV_CDB)
+#define CRYPTO_ON(dbenv) ((dbenv)->crypto_handle != NULL)
+#define LOCKING_ON(dbenv) ((dbenv)->lk_handle != NULL)
+#define LOGGING_ON(dbenv) ((dbenv)->lg_handle != NULL)
+#define MPOOL_ON(dbenv) ((dbenv)->mp_handle != NULL)
+#define RPC_ON(dbenv) ((dbenv)->cl_handle != NULL)
+#define TXN_ON(dbenv) ((dbenv)->tx_handle != NULL)
+
+/*
+ * STD_LOCKING Standard locking, that is, locking was configured and CDB
+ * was not. We do not do locking in off-page duplicate trees,
+ * so we check for that in the cursor first.
+ */
+#define STD_LOCKING(dbc) \
+ (!F_ISSET(dbc, DBC_OPD) && \
+ !CDB_LOCKING((dbc)->dbp->dbenv) && LOCKING_ON((dbc)->dbp->dbenv))
+
+/*
+ * IS_RECOVERING: The system is running recovery.
+ */
+#define IS_RECOVERING(dbenv) \
+ (LOGGING_ON(dbenv) && \
+ F_ISSET((DB_LOG *)(dbenv)->lg_handle, DBLOG_RECOVER))
+
+/* Initialization methods are often illegal before/after open is called. */
+#define ENV_ILLEGAL_AFTER_OPEN(dbenv, name) \
+ if (F_ISSET((dbenv), DB_ENV_OPEN_CALLED)) \
+ return (__db_mi_open(dbenv, name, 1));
+#define ENV_ILLEGAL_BEFORE_OPEN(dbenv, name) \
+ if (!F_ISSET((dbenv), DB_ENV_OPEN_CALLED)) \
+ return (__db_mi_open(dbenv, name, 0));
+
+/* We're not actually user hostile, honest. */
+#define ENV_REQUIRES_CONFIG(dbenv, handle, i, flags) \
+ if (handle == NULL) \
+ return (__db_env_config(dbenv, i, flags));
+
+/*******************************************************
+ * Database Access Methods.
+ *******************************************************/
+/*
+ * DB_IS_THREADED --
+ * The database handle is free-threaded (was opened with DB_THREAD).
+ */
+#define DB_IS_THREADED(dbp) \
+ ((dbp)->mutexp != NULL)
+
+/* Initialization methods are often illegal before/after open is called. */
+#define DB_ILLEGAL_AFTER_OPEN(dbp, name) \
+ if (F_ISSET((dbp), DB_AM_OPEN_CALLED)) \
+ return (__db_mi_open((dbp)->dbenv, name, 1));
+#define DB_ILLEGAL_BEFORE_OPEN(dbp, name) \
+ if (!F_ISSET((dbp), DB_AM_OPEN_CALLED)) \
+ return (__db_mi_open((dbp)->dbenv, name, 0));
+/* Some initialization methods are illegal if environment isn't local. */
+#define DB_ILLEGAL_IN_ENV(dbp, name) \
+ if (!F_ISSET((dbp)->dbenv, DB_ENV_DBLOCAL)) \
+ return (__db_mi_env((dbp)->dbenv, name));
+#define DB_ILLEGAL_METHOD(dbp, flags) { \
+ int __ret; \
+ if ((__ret = __dbh_am_chk(dbp, flags)) != 0) \
+ return (__ret); \
+}
+
+/*
+ * Common DBC->internal fields. Each access method adds additional fields
+ * to this list, but the initial fields are common.
+ */
+#define __DBC_INTERNAL \
+ DBC *opd; /* Off-page duplicate cursor. */\
+ \
+ void *page; /* Referenced page. */ \
+ db_pgno_t root; /* Tree root. */ \
+ db_pgno_t pgno; /* Referenced page number. */ \
+ db_indx_t indx; /* Referenced key item index. */\
+ \
+ DB_LOCK lock; /* Cursor lock. */ \
+ db_lockmode_t lock_mode; /* Lock mode. */
+
+struct __dbc_internal {
+ __DBC_INTERNAL
+};
+
+/* Actions that __db_master_update can take. */
+typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN } mu_action;
+
+/*
+ * Access-method-common macro for determining whether a cursor
+ * has been initialized.
+ */
+#define IS_INITIALIZED(dbc) ((dbc)->internal->pgno != PGNO_INVALID)
+
+/* Free the callback-allocated buffer, if necessary, hanging off of a DBT. */
+#define FREE_IF_NEEDED(sdbp, dbt) \
+ if (F_ISSET((dbt), DB_DBT_APPMALLOC)) { \
+ __os_ufree((sdbp)->dbenv, (dbt)->data); \
+ F_CLR((dbt), DB_DBT_APPMALLOC); \
+ }
+
+/*
+ * Use memory belonging to object "owner" to return the results of
+ * any no-DBT-flag get ops on cursor "dbc".
+ */
+#define SET_RET_MEM(dbc, owner) \
+ do { \
+ (dbc)->rskey = &(owner)->my_rskey; \
+ (dbc)->rkey = &(owner)->my_rkey; \
+ (dbc)->rdata = &(owner)->my_rdata; \
+ } while (0)
+
+/* Use the return-data memory src is currently set to use in dest as well. */
+#define COPY_RET_MEM(src, dest) \
+ do { \
+ (dest)->rskey = (src)->rskey; \
+ (dest)->rkey = (src)->rkey; \
+ (dest)->rdata = (src)->rdata; \
+ } while (0)
+
+/* Reset the returned-memory pointers to their defaults. */
+#define RESET_RET_MEM(dbc) \
+ do { \
+ (dbc)->rskey = &(dbc)->my_rskey; \
+ (dbc)->rkey = &(dbc)->my_rkey; \
+ (dbc)->rdata = &(dbc)->my_rdata; \
+ } while (0)
+
+/*******************************************************
+ * Mpool.
+ *******************************************************/
+/*
+ * File types for DB access methods. Negative numbers are reserved to DB.
+ */
+#define DB_FTYPE_SET -1 /* Call pgin/pgout functions. */
+#define DB_FTYPE_NOTSET 0 /* Don't call... */
+
+/* Structure used as the DB pgin/pgout pgcookie. */
+typedef struct __dbpginfo {
+ size_t db_pagesize; /* Underlying page size. */
+ u_int32_t flags; /* Some DB_AM flags needed. */
+ DBTYPE type; /* DB type */
+} DB_PGINFO;
+
+/*******************************************************
+ * Log.
+ *******************************************************/
+/* Initialize an LSN to 'zero'. */
+#define ZERO_LSN(LSN) do { \
+ (LSN).file = 0; \
+ (LSN).offset = 0; \
+} while (0)
+#define IS_ZERO_LSN(LSN) ((LSN).file == 0)
+
+#define IS_INIT_LSN(LSN) ((LSN).file == 1 && (LSN).offset == 0)
+#define INIT_LSN(LSN) do { \
+ (LSN).file = 1; \
+ (LSN).offset = 0; \
+} while (0)
+
+#define MAX_LSN(LSN) do { \
+ (LSN).file = UINT32_T_MAX; \
+ (LSN).offset = UINT32_T_MAX; \
+} while (0)
+#define IS_MAX_LSN(LSN) \
+ ((LSN).file == UINT32_T_MAX && (LSN).offset == UINT32_T_MAX)
+
+/* If logging is turned off, smash the lsn. */
+#define LSN_NOT_LOGGED(LSN) do { \
+ (LSN).file = 0; \
+ (LSN).offset = 1; \
+} while (0)
+#define IS_NOT_LOGGED_LSN(LSN) \
+ ((LSN).file == 0 && (LSN).offset == 1)
+
+/*
+ * Test if the environment is currently logging changes. If we're in
+ * recovery or we're a replication client, we don't need to log changes
+ * because they're already in the log, even though we have a fully functional
+ * log system.
+ */
+#define DBENV_LOGGING(dbenv) \
+ (LOGGING_ON(dbenv) && !F_ISSET((dbenv), DB_ENV_REP_CLIENT) && \
+ (!IS_RECOVERING(dbenv)))
+
+/*
+ * Test if we need to log a change. Note that the DBC_RECOVER flag is set
+ * when we're in abort, as well as during recovery; thus DBC_LOGGING may be
+ * false for a particular dbc even when DBENV_LOGGING is true.
+ *
+ * We explicitly use LOGGING_ON/DB_ENV_REP_CLIENT here because we don't
+ * want to have to pull in the log headers, which IS_RECOVERING (and thus
+ * DBENV_LOGGING) rely on, and because DBC_RECOVER should be set anytime
+ * IS_RECOVERING would be true.
+ */
+#define DBC_LOGGING(dbc) \
+ (LOGGING_ON((dbc)->dbp->dbenv) && !F_ISSET((dbc), DBC_RECOVER) && \
+ !F_ISSET((dbc)->dbp->dbenv, DB_ENV_REP_CLIENT))
+
+/*******************************************************
+ * Txn.
+ *******************************************************/
+#define DB_NONBLOCK(C) ((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT))
+#define IS_SUBTRANSACTION(txn) \
+ ((txn) != NULL && (txn)->parent != NULL)
+
+/*******************************************************
+ * Crypto.
+ *******************************************************/
+#define DB_IV_BYTES 16 /* Bytes per IV */
+#define DB_MAC_KEY 20 /* Bytes per MAC checksum */
+
+/*******************************************************
+ * Forward structure declarations.
+ *******************************************************/
+struct __db_reginfo_t; typedef struct __db_reginfo_t REGINFO;
+struct __db_txnhead; typedef struct __db_txnhead DB_TXNHEAD;
+struct __db_txnlist; typedef struct __db_txnlist DB_TXNLIST;
+struct __vrfy_childinfo; typedef struct __vrfy_childinfo VRFY_CHILDINFO;
+struct __vrfy_dbinfo; typedef struct __vrfy_dbinfo VRFY_DBINFO;
+struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO;
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*******************************************************
+ * Remaining general DB includes.
+ *******************************************************/
+@db_int_def@
+
+#include "dbinc/globals.h"
+#include "dbinc/debug.h"
+#include "dbinc/mutex.h"
+#include "dbinc/region.h"
+#include "dbinc_auto/mutex_ext.h" /* XXX: Include after region.h. */
+#include "dbinc_auto/env_ext.h"
+#include "dbinc/os.h"
+#include "dbinc_auto/clib_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+#endif /* !_DB_INTERNAL_H_ */
diff --git a/bdb/dbinc/db_join.h b/bdb/dbinc/db_join.h
new file mode 100644
index 00000000000..487ce3eebbb
--- /dev/null
+++ b/bdb/dbinc/db_join.h
@@ -0,0 +1,31 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * @(#)db_join.h 11.1 (Sleepycat) 7/25/99
+ */
+
+#ifndef _DB_JOIN_H_
+#define _DB_JOIN_H_
+
+/*
+ * Joins use a join cursor that is similar to a regular DB cursor except
+ * that it only supports c_get and c_close functionality. Also, it does
+ * not support the full range of flags for get.
+ */
+typedef struct __join_cursor {
+ u_int8_t *j_exhausted; /* Array of flags; is cursor i exhausted? */
+ DBC **j_curslist; /* Array of cursors in the join: constant. */
+ DBC **j_fdupcurs; /* Cursors w/ first intances of current dup. */
+ DBC **j_workcurs; /* Scratch cursor copies to muck with. */
+ DB *j_primary; /* Primary dbp. */
+ DBT j_key; /* Used to do lookups. */
+ DBT j_rdata; /* Memory used for data return. */
+ u_int32_t j_ncurs; /* How many cursors do we have? */
+#define JOIN_RETRY 0x01 /* Error on primary get; re-return same key. */
+ u_int32_t flags;
+} JOIN_CURSOR;
+
+#endif /* !_DB_JOIN_H_ */
diff --git a/bdb/dbinc/db_page.h b/bdb/dbinc/db_page.h
new file mode 100644
index 00000000000..97497556fd9
--- /dev/null
+++ b/bdb/dbinc/db_page.h
@@ -0,0 +1,651 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_page.h,v 11.52 2002/09/13 21:24:04 bostic Exp $
+ */
+
+#ifndef _DB_PAGE_H_
+#define _DB_PAGE_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * DB page formats.
+ *
+ * !!!
+ * This implementation requires that values within the following structures
+ * NOT be padded -- note, ANSI C permits random padding within structures.
+ * If your compiler pads randomly you can just forget ever making DB run on
+ * your system. In addition, no data type can require larger alignment than
+ * its own size, e.g., a 4-byte data element may not require 8-byte alignment.
+ *
+ * Note that key/data lengths are often stored in db_indx_t's -- this is
+ * not accidental, nor does it limit the key/data size. If the key/data
+ * item fits on a page, it's guaranteed to be small enough to fit into a
+ * db_indx_t, and storing it in one saves space.
+ */
+
+#define PGNO_INVALID 0 /* Invalid page number in any database. */
+#define PGNO_BASE_MD 0 /* Base database: metadata page number. */
+
+/* Page types. */
+#define P_INVALID 0 /* Invalid page type. */
+#define __P_DUPLICATE 1 /* Duplicate. DEPRECATED in 3.1 */
+#define P_HASH 2 /* Hash. */
+#define P_IBTREE 3 /* Btree internal. */
+#define P_IRECNO 4 /* Recno internal. */
+#define P_LBTREE 5 /* Btree leaf. */
+#define P_LRECNO 6 /* Recno leaf. */
+#define P_OVERFLOW 7 /* Overflow. */
+#define P_HASHMETA 8 /* Hash metadata page. */
+#define P_BTREEMETA 9 /* Btree metadata page. */
+#define P_QAMMETA 10 /* Queue metadata page. */
+#define P_QAMDATA 11 /* Queue data page. */
+#define P_LDUP 12 /* Off-page duplicate leaf. */
+#define P_PAGETYPE_MAX 13
+
+/*
+ * When we create pages in mpool, we ask mpool to clear some number of bytes
+ * in the header. This number must be at least as big as the regular page
+ * headers and cover enough of the btree and hash meta-data pages to obliterate
+ * the page type.
+ */
+#define DB_PAGE_DB_LEN 32
+#define DB_PAGE_QUEUE_LEN 0
+
+/************************************************************************
+ GENERIC METADATA PAGE HEADER
+ *
+ * !!!
+ * The magic and version numbers have to be in the same place in all versions
+ * of the metadata page as the application may not have upgraded the database.
+ ************************************************************************/
+typedef struct _dbmeta33 {
+ DB_LSN lsn; /* 00-07: LSN. */
+ db_pgno_t pgno; /* 08-11: Current page number. */
+ u_int32_t magic; /* 12-15: Magic number. */
+ u_int32_t version; /* 16-19: Version. */
+ u_int32_t pagesize; /* 20-23: Pagesize. */
+ u_int8_t encrypt_alg; /* 24: Encryption algorithm. */
+ u_int8_t type; /* 25: Page type. */
+#define DBMETA_CHKSUM 0x01
+ u_int8_t metaflags; /* 26: Meta-only flags */
+ u_int8_t unused1; /* 27: Unused. */
+ u_int32_t free; /* 28-31: Free list page number. */
+ db_pgno_t last_pgno; /* 32-35: Page number of last page in db. */
+ u_int32_t unused3; /* 36-39: Unused. */
+ u_int32_t key_count; /* 40-43: Cached key count. */
+ u_int32_t record_count; /* 44-47: Cached record count. */
+ u_int32_t flags; /* 48-51: Flags: unique to each AM. */
+ /* 52-71: Unique file ID. */
+ u_int8_t uid[DB_FILE_ID_LEN];
+} DBMETA33, DBMETA;
+
+/************************************************************************
+ BTREE METADATA PAGE LAYOUT
+ ************************************************************************/
+typedef struct _btmeta33 {
+#define BTM_DUP 0x001 /* Duplicates. */
+#define BTM_RECNO 0x002 /* Recno tree. */
+#define BTM_RECNUM 0x004 /* Btree: maintain record count. */
+#define BTM_FIXEDLEN 0x008 /* Recno: fixed length records. */
+#define BTM_RENUMBER 0x010 /* Recno: renumber on insert/delete. */
+#define BTM_SUBDB 0x020 /* Subdatabases. */
+#define BTM_DUPSORT 0x040 /* Duplicates are sorted. */
+#define BTM_MASK 0x07f
+ DBMETA dbmeta; /* 00-71: Generic meta-data header. */
+
+ u_int32_t maxkey; /* 72-75: Btree: Maxkey. */
+ u_int32_t minkey; /* 76-79: Btree: Minkey. */
+ u_int32_t re_len; /* 80-83: Recno: fixed-length record length. */
+ u_int32_t re_pad; /* 84-87: Recno: fixed-length record pad. */
+ u_int32_t root; /* 88-91: Root page. */
+ u_int32_t unused[92]; /* 92-459: Unused space */
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
+
+ /*
+ * Minimum page size is 512.
+ */
+} BTMETA33, BTMETA;
+
+/************************************************************************
+ HASH METADATA PAGE LAYOUT
+ ************************************************************************/
+typedef struct _hashmeta33 {
+#define DB_HASH_DUP 0x01 /* Duplicates. */
+#define DB_HASH_SUBDB 0x02 /* Subdatabases. */
+#define DB_HASH_DUPSORT 0x04 /* Duplicates are sorted. */
+ DBMETA dbmeta; /* 00-71: Generic meta-data page header. */
+
+ u_int32_t max_bucket; /* 72-75: ID of Maximum bucket in use */
+ u_int32_t high_mask; /* 76-79: Modulo mask into table */
+ u_int32_t low_mask; /* 80-83: Modulo mask into table lower half */
+ u_int32_t ffactor; /* 84-87: Fill factor */
+ u_int32_t nelem; /* 88-91: Number of keys in hash table */
+ u_int32_t h_charkey; /* 92-95: Value of hash(CHARKEY) */
+#define NCACHED 32 /* number of spare points */
+ /* 96-223: Spare pages for overflow */
+ u_int32_t spares[NCACHED];
+ u_int32_t unused[59]; /* 224-459: Unused space */
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
+
+ /*
+ * Minimum page size is 512.
+ */
+} HMETA33, HMETA;
+
+/************************************************************************
+ QUEUE METADATA PAGE LAYOUT
+ ************************************************************************/
+/*
+ * QAM Meta data page structure
+ *
+ */
+typedef struct _qmeta33 {
+ DBMETA dbmeta; /* 00-71: Generic meta-data header. */
+
+ u_int32_t first_recno; /* 72-75: First not deleted record. */
+ u_int32_t cur_recno; /* 76-79: Next recno to be allocated. */
+ u_int32_t re_len; /* 80-83: Fixed-length record length. */
+ u_int32_t re_pad; /* 84-87: Fixed-length record pad. */
+ u_int32_t rec_page; /* 88-91: Records Per Page. */
+ u_int32_t page_ext; /* 92-95: Pages per extent */
+
+ u_int32_t unused[91]; /* 96-459: Unused space */
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
+ /*
+ * Minimum page size is 512.
+ */
+} QMETA33, QMETA;
+
+/*
+ * DBMETASIZE is a constant used by __db_file_setup and DB->verify
+ * as a buffer which is guaranteed to be larger than any possible
+ * metadata page size and smaller than any disk sector.
+ */
+#define DBMETASIZE 512
+
+/************************************************************************
+ BTREE/HASH MAIN PAGE LAYOUT
+ ************************************************************************/
+/*
+ * +-----------------------------------+
+ * | lsn | pgno | prev pgno |
+ * +-----------------------------------+
+ * | next pgno | entries | hf offset |
+ * +-----------------------------------+
+ * | level | type | chksum |
+ * +-----------------------------------+
+ * | iv | index | free --> |
+ * +-----------+-----------------------+
+ * | F R E E A R E A |
+ * +-----------------------------------+
+ * | <-- free | item |
+ * +-----------------------------------+
+ * | item | item | item |
+ * +-----------------------------------+
+ *
+ * sizeof(PAGE) == 26 bytes + possibly 20 bytes of checksum and possibly
+ * 16 bytes of IV (+ 2 bytes for alignment), and the following indices
+ * are guaranteed to be two-byte aligned. If we aren't doing crypto or
+ * checksumming the bytes are reclaimed for data storage.
+ *
+ * For hash and btree leaf pages, index items are paired, e.g., inp[0] is the
+ * key for inp[1]'s data. All other types of pages only contain single items.
+ */
+typedef struct __pg_chksum {
+ u_int8_t unused[2]; /* 26-27: For alignment */
+ u_int8_t chksum[4]; /* 28-31: Checksum */
+} PG_CHKSUM;
+
+typedef struct __pg_crypto {
+ u_int8_t unused[2]; /* 26-27: For alignment */
+ u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */
+ u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */
+ /* !!!
+ * Must be 16-byte aligned for crypto
+ */
+} PG_CRYPTO;
+
+typedef struct _db_page {
+ DB_LSN lsn; /* 00-07: Log sequence number. */
+ db_pgno_t pgno; /* 08-11: Current page number. */
+ db_pgno_t prev_pgno; /* 12-15: Previous page number. */
+ db_pgno_t next_pgno; /* 16-19: Next page number. */
+ db_indx_t entries; /* 20-21: Number of items on the page. */
+ db_indx_t hf_offset; /* 22-23: High free byte page offset. */
+
+ /*
+ * The btree levels are numbered from the leaf to the root, starting
+ * with 1, so the leaf is level 1, its parent is level 2, and so on.
+ * We maintain this level on all btree pages, but the only place that
+ * we actually need it is on the root page. It would not be difficult
+ * to hide the byte on the root page once it becomes an internal page,
+ * so we could get this byte back if we needed it for something else.
+ */
+#define LEAFLEVEL 1
+#define MAXBTREELEVEL 255
+ u_int8_t level; /* 24: Btree tree level. */
+ u_int8_t type; /* 25: Page type. */
+} PAGE;
+
+#define SIZEOF_PAGE 26
+/*
+ * !!!
+ * DB_AM_ENCRYPT always implies DB_AM_CHKSUM so that must come first.
+ */
+#define P_INP(dbp, pg) \
+ ((db_indx_t *)((u_int8_t *)(pg) + SIZEOF_PAGE + \
+ (F_ISSET((dbp), DB_AM_ENCRYPT) ? sizeof(PG_CRYPTO) : \
+ (F_ISSET((dbp), DB_AM_CHKSUM) ? sizeof(PG_CHKSUM) : 0))))
+
+#define P_IV(dbp, pg) \
+ (F_ISSET((dbp), DB_AM_ENCRYPT) ? ((u_int8_t *)(pg) + \
+ SIZEOF_PAGE + SSZA(PG_CRYPTO, iv)) \
+ : NULL)
+
+#define P_CHKSUM(dbp, pg) \
+ (F_ISSET((dbp), DB_AM_ENCRYPT) ? ((u_int8_t *)(pg) + \
+ SIZEOF_PAGE + SSZA(PG_CRYPTO, chksum)) : \
+ (F_ISSET((dbp), DB_AM_CHKSUM) ? ((u_int8_t *)(pg) + \
+ SIZEOF_PAGE + SSZA(PG_CHKSUM, chksum)) \
+ : NULL))
+
+/* PAGE element macros. */
+#define LSN(p) (((PAGE *)p)->lsn)
+#define PGNO(p) (((PAGE *)p)->pgno)
+#define PREV_PGNO(p) (((PAGE *)p)->prev_pgno)
+#define NEXT_PGNO(p) (((PAGE *)p)->next_pgno)
+#define NUM_ENT(p) (((PAGE *)p)->entries)
+#define HOFFSET(p) (((PAGE *)p)->hf_offset)
+#define LEVEL(p) (((PAGE *)p)->level)
+#define TYPE(p) (((PAGE *)p)->type)
+
+/************************************************************************
+ QUEUE MAIN PAGE LAYOUT
+ ************************************************************************/
+/*
+ * Sizes of page below. Used to reclaim space if not doing
+ * crypto or checksumming. If you change the QPAGE below you
+ * MUST adjust this too.
+ */
+#define QPAGE_NORMAL 28
+#define QPAGE_CHKSUM 48
+#define QPAGE_SEC 64
+
+typedef struct _qpage {
+ DB_LSN lsn; /* 00-07: Log sequence number. */
+ db_pgno_t pgno; /* 08-11: Current page number. */
+ u_int32_t unused0[3]; /* 12-23: Unused. */
+ u_int8_t unused1[1]; /* 24: Unused. */
+ u_int8_t type; /* 25: Page type. */
+ u_int8_t unused2[2]; /* 26-27: Unused. */
+ u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */
+ u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */
+} QPAGE;
+
+#define QPAGE_SZ(dbp) \
+ (F_ISSET((dbp), DB_AM_ENCRYPT) ? QPAGE_SEC : \
+ F_ISSET((dbp), DB_AM_CHKSUM) ? QPAGE_CHKSUM : QPAGE_NORMAL)
+/*
+ * !!!
+ * The next_pgno and prev_pgno fields are not maintained for btree and recno
+ * internal pages. Doing so only provides a minor performance improvement,
+ * it's hard to do when deleting internal pages, and it increases the chance
+ * of deadlock during deletes and splits because we have to re-link pages at
+ * more than the leaf level.
+ *
+ * !!!
+ * The btree/recno access method needs db_recno_t bytes of space on the root
+ * page to specify how many records are stored in the tree. (The alternative
+ * is to store the number of records in the meta-data page, which will create
+ * a second hot spot in trees being actively modified, or recalculate it from
+ * the BINTERNAL fields on each access.) Overload the PREV_PGNO field.
+ */
+#define RE_NREC(p) \
+ ((TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO) ? PREV_PGNO(p) : \
+ (db_pgno_t)(TYPE(p) == P_LBTREE ? NUM_ENT(p) / 2 : NUM_ENT(p)))
+#define RE_NREC_ADJ(p, adj) \
+ PREV_PGNO(p) += adj;
+#define RE_NREC_SET(p, num) \
+ PREV_PGNO(p) = num;
+
+/*
+ * Initialize a page.
+ *
+ * !!!
+ * Don't modify the page's LSN, code depends on it being unchanged after a
+ * P_INIT call.
+ */
+#define P_INIT(pg, pg_size, n, pg_prev, pg_next, btl, pg_type) do { \
+ PGNO(pg) = n; \
+ PREV_PGNO(pg) = pg_prev; \
+ NEXT_PGNO(pg) = pg_next; \
+ NUM_ENT(pg) = 0; \
+ HOFFSET(pg) = pg_size; \
+ LEVEL(pg) = btl; \
+ TYPE(pg) = pg_type; \
+} while (0)
+
+/* Page header length (offset to first index). */
+#define P_OVERHEAD(dbp) P_TO_UINT16(P_INP(dbp, 0))
+
+/* First free byte. */
+#define LOFFSET(dbp, pg) \
+ (P_OVERHEAD(dbp) + NUM_ENT(pg) * sizeof(db_indx_t))
+
+/* Free space on a regular page. */
+#define P_FREESPACE(dbp, pg) (HOFFSET(pg) - LOFFSET(dbp, pg))
+
+/* Get a pointer to the bytes at a specific index. */
+#define P_ENTRY(dbp, pg, indx) ((u_int8_t *)pg + P_INP(dbp, pg)[indx])
+
+/************************************************************************
+ OVERFLOW PAGE LAYOUT
+ ************************************************************************/
+
+/*
+ * Overflow items are referenced by HOFFPAGE and BOVERFLOW structures, which
+ * store a page number (the first page of the overflow item) and a length
+ * (the total length of the overflow item). The overflow item consists of
+ * some number of overflow pages, linked by the next_pgno field of the page.
+ * A next_pgno field of PGNO_INVALID flags the end of the overflow item.
+ *
+ * Overflow page overloads:
+ * The amount of overflow data stored on each page is stored in the
+ * hf_offset field.
+ *
+ * The implementation reference counts overflow items as it's possible
+ * for them to be promoted onto btree internal pages. The reference
+ * count is stored in the entries field.
+ */
+#define OV_LEN(p) (((PAGE *)p)->hf_offset)
+#define OV_REF(p) (((PAGE *)p)->entries)
+
+/* Maximum number of bytes that you can put on an overflow page. */
+#define P_MAXSPACE(dbp, psize) ((psize) - P_OVERHEAD(dbp))
+
+/* Free space on an overflow page. */
+#define P_OVFLSPACE(dbp, psize, pg) (P_MAXSPACE(dbp, psize) - HOFFSET(pg))
+
+/************************************************************************
+ HASH PAGE LAYOUT
+ ************************************************************************/
+
+/* Each index references a group of bytes on the page. */
+#define H_KEYDATA 1 /* Key/data item. */
+#define H_DUPLICATE 2 /* Duplicate key/data item. */
+#define H_OFFPAGE 3 /* Overflow key/data item. */
+#define H_OFFDUP 4 /* Overflow page of duplicates. */
+
+/*
+ * !!!
+ * Items on hash pages are (potentially) unaligned, so we can never cast the
+ * (page + offset) pointer to an HKEYDATA, HOFFPAGE or HOFFDUP structure, as
+ * we do with B+tree on-page structures. Because we frequently want the type
+ * field, it requires no alignment, and it's in the same location in all three
+ * structures, there's a pair of macros.
+ */
+#define HPAGE_PTYPE(p) (*(u_int8_t *)p)
+#define HPAGE_TYPE(dbp, pg, indx) (*P_ENTRY(dbp, pg, indx))
+
+/*
+ * The first and second types are H_KEYDATA and H_DUPLICATE, represented
+ * by the HKEYDATA structure:
+ *
+ * +-----------------------------------+
+ * | type | key/data ... |
+ * +-----------------------------------+
+ *
+ * For duplicates, the data field encodes duplicate elements in the data
+ * field:
+ *
+ * +---------------------------------------------------------------+
+ * | type | len1 | element1 | len1 | len2 | element2 | len2 |
+ * +---------------------------------------------------------------+
+ *
+ * Thus, by keeping track of the offset in the element, we can do both
+ * backward and forward traversal.
+ */
+typedef struct _hkeydata {
+ u_int8_t type; /* 00: Page type. */
+ u_int8_t data[1]; /* Variable length key/data item. */
+} HKEYDATA;
+#define HKEYDATA_DATA(p) (((u_int8_t *)p) + SSZA(HKEYDATA, data))
+
+/*
+ * The length of any HKEYDATA item. Note that indx is an element index,
+ * not a PAIR index.
+ */
+#define LEN_HITEM(dbp, pg, pgsize, indx) \
+ (((indx) == 0 ? pgsize : \
+ (P_INP(dbp, pg)[indx - 1])) - (P_INP(dbp, pg)[indx]))
+
+#define LEN_HKEYDATA(dbp, pg, psize, indx) \
+ (db_indx_t)(LEN_HITEM(dbp, pg, psize, indx) - HKEYDATA_SIZE(0))
+
+/*
+ * Page space required to add a new HKEYDATA item to the page, with and
+ * without the index value.
+ */
+#define HKEYDATA_SIZE(len) \
+ ((len) + SSZA(HKEYDATA, data))
+#define HKEYDATA_PSIZE(len) \
+ (HKEYDATA_SIZE(len) + sizeof(db_indx_t))
+
+/* Put a HKEYDATA item at the location referenced by a page entry. */
+#define PUT_HKEYDATA(pe, kd, len, type) { \
+ ((HKEYDATA *)pe)->type = type; \
+ memcpy((u_int8_t *)pe + sizeof(u_int8_t), kd, len); \
+}
+
+/*
+ * Macros the describe the page layout in terms of key-data pairs.
+ */
+#define H_NUMPAIRS(pg) (NUM_ENT(pg) / 2)
+#define H_KEYINDEX(indx) (indx)
+#define H_DATAINDEX(indx) ((indx) + 1)
+#define H_PAIRKEY(dbp, pg, indx) P_ENTRY(dbp, pg, H_KEYINDEX(indx))
+#define H_PAIRDATA(dbp, pg, indx) P_ENTRY(dbp, pg, H_DATAINDEX(indx))
+#define H_PAIRSIZE(dbp, pg, psize, indx) \
+ (LEN_HITEM(dbp, pg, psize, H_KEYINDEX(indx)) + \
+ LEN_HITEM(dbp, pg, psize, H_DATAINDEX(indx)))
+#define LEN_HDATA(dbp, p, psize, indx) \
+ LEN_HKEYDATA(dbp, p, psize, H_DATAINDEX(indx))
+#define LEN_HKEY(dbp, p, psize, indx) \
+ LEN_HKEYDATA(dbp, p, psize, H_KEYINDEX(indx))
+
+/*
+ * The third type is the H_OFFPAGE, represented by the HOFFPAGE structure:
+ */
+typedef struct _hoffpage {
+ u_int8_t type; /* 00: Page type and delete flag. */
+ u_int8_t unused[3]; /* 01-03: Padding, unused. */
+ db_pgno_t pgno; /* 04-07: Offpage page number. */
+ u_int32_t tlen; /* 08-11: Total length of item. */
+} HOFFPAGE;
+
+#define HOFFPAGE_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, pgno))
+#define HOFFPAGE_TLEN(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, tlen))
+
+/*
+ * Page space required to add a new HOFFPAGE item to the page, with and
+ * without the index value.
+ */
+#define HOFFPAGE_SIZE (sizeof(HOFFPAGE))
+#define HOFFPAGE_PSIZE (HOFFPAGE_SIZE + sizeof(db_indx_t))
+
+/*
+ * The fourth type is H_OFFDUP represented by the HOFFDUP structure:
+ */
+typedef struct _hoffdup {
+ u_int8_t type; /* 00: Page type and delete flag. */
+ u_int8_t unused[3]; /* 01-03: Padding, unused. */
+ db_pgno_t pgno; /* 04-07: Offpage page number. */
+} HOFFDUP;
+#define HOFFDUP_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFDUP, pgno))
+
+/*
+ * Page space required to add a new HOFFDUP item to the page, with and
+ * without the index value.
+ */
+#define HOFFDUP_SIZE (sizeof(HOFFDUP))
+
+/************************************************************************
+ BTREE PAGE LAYOUT
+ ************************************************************************/
+
+/* Each index references a group of bytes on the page. */
+#define B_KEYDATA 1 /* Key/data item. */
+#define B_DUPLICATE 2 /* Duplicate key/data item. */
+#define B_OVERFLOW 3 /* Overflow key/data item. */
+
+/*
+ * We have to store a deleted entry flag in the page. The reason is complex,
+ * but the simple version is that we can't delete on-page items referenced by
+ * a cursor -- the return order of subsequent insertions might be wrong. The
+ * delete flag is an overload of the top bit of the type byte.
+ */
+#define B_DELETE (0x80)
+#define B_DCLR(t) (t) &= ~B_DELETE
+#define B_DSET(t) (t) |= B_DELETE
+#define B_DISSET(t) ((t) & B_DELETE)
+
+#define B_TYPE(t) ((t) & ~B_DELETE)
+#define B_TSET(t, type, deleted) { \
+ (t) = (type); \
+ if (deleted) \
+ B_DSET(t); \
+}
+
+/*
+ * The first type is B_KEYDATA, represented by the BKEYDATA structure:
+ */
+typedef struct _bkeydata {
+ db_indx_t len; /* 00-01: Key/data item length. */
+ u_int8_t type; /* 02: Page type AND DELETE FLAG. */
+ u_int8_t data[1]; /* Variable length key/data item. */
+} BKEYDATA;
+
+/* Get a BKEYDATA item for a specific index. */
+#define GET_BKEYDATA(dbp, pg, indx) \
+ ((BKEYDATA *)P_ENTRY(dbp, pg, indx))
+
+/*
+ * Page space required to add a new BKEYDATA item to the page, with and
+ * without the index value.
+ */
+#define BKEYDATA_SIZE(len) \
+ ALIGN((len) + SSZA(BKEYDATA, data), sizeof(u_int32_t))
+#define BKEYDATA_PSIZE(len) \
+ (BKEYDATA_SIZE(len) + sizeof(db_indx_t))
+
+/*
+ * The second and third types are B_DUPLICATE and B_OVERFLOW, represented
+ * by the BOVERFLOW structure.
+ */
+typedef struct _boverflow {
+ db_indx_t unused1; /* 00-01: Padding, unused. */
+ u_int8_t type; /* 02: Page type AND DELETE FLAG. */
+ u_int8_t unused2; /* 03: Padding, unused. */
+ db_pgno_t pgno; /* 04-07: Next page number. */
+ u_int32_t tlen; /* 08-11: Total length of item. */
+} BOVERFLOW;
+
+/* Get a BOVERFLOW item for a specific index. */
+#define GET_BOVERFLOW(dbp, pg, indx) \
+ ((BOVERFLOW *)P_ENTRY(dbp, pg, indx))
+
+/*
+ * Page space required to add a new BOVERFLOW item to the page, with and
+ * without the index value. The (u_int16_t) cast avoids warnings: ALIGN
+ * casts to db_align_t, the cast converts it to a small integral type so
+ * we don't get complaints when we assign the final result to an integral
+ * type smaller than db_align_t.
+ */
+#define BOVERFLOW_SIZE \
+ ((u_int16_t)ALIGN(sizeof(BOVERFLOW), sizeof(u_int32_t)))
+#define BOVERFLOW_PSIZE \
+ (BOVERFLOW_SIZE + sizeof(db_indx_t))
+
+/*
+ * Btree leaf and hash page layouts group indices in sets of two, one for the
+ * key and one for the data. Everything else does it in sets of one to save
+ * space. Use the following macros so that it's real obvious what's going on.
+ */
+#define O_INDX 1
+#define P_INDX 2
+
+/************************************************************************
+ BTREE INTERNAL PAGE LAYOUT
+ ************************************************************************/
+
+/*
+ * Btree internal entry.
+ */
+typedef struct _binternal {
+ db_indx_t len; /* 00-01: Key/data item length. */
+ u_int8_t type; /* 02: Page type AND DELETE FLAG. */
+ u_int8_t unused; /* 03: Padding, unused. */
+ db_pgno_t pgno; /* 04-07: Page number of referenced page. */
+ db_recno_t nrecs; /* 08-11: Subtree record count. */
+ u_int8_t data[1]; /* Variable length key item. */
+} BINTERNAL;
+
+/* Get a BINTERNAL item for a specific index. */
+#define GET_BINTERNAL(dbp, pg, indx) \
+ ((BINTERNAL *)P_ENTRY(dbp, pg, indx))
+
+/*
+ * Page space required to add a new BINTERNAL item to the page, with and
+ * without the index value.
+ */
+#define BINTERNAL_SIZE(len) \
+ ALIGN((len) + SSZA(BINTERNAL, data), sizeof(u_int32_t))
+#define BINTERNAL_PSIZE(len) \
+ (BINTERNAL_SIZE(len) + sizeof(db_indx_t))
+
+/************************************************************************
+ RECNO INTERNAL PAGE LAYOUT
+ ************************************************************************/
+
+/*
+ * The recno internal entry.
+ */
+typedef struct _rinternal {
+ db_pgno_t pgno; /* 00-03: Page number of referenced page. */
+ db_recno_t nrecs; /* 04-07: Subtree record count. */
+} RINTERNAL;
+
+/* Get a RINTERNAL item for a specific index. */
+#define GET_RINTERNAL(dbp, pg, indx) \
+ ((RINTERNAL *)P_ENTRY(dbp, pg, indx))
+
+/*
+ * Page space required to add a new RINTERNAL item to the page, with and
+ * without the index value.
+ */
+#define RINTERNAL_SIZE \
+ ALIGN(sizeof(RINTERNAL), sizeof(u_int32_t))
+#define RINTERNAL_PSIZE \
+ (RINTERNAL_SIZE + sizeof(db_indx_t))
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* !_DB_PAGE_H_ */
diff --git a/bdb/dbinc/db_server_int.h b/bdb/dbinc/db_server_int.h
new file mode 100644
index 00000000000..efec539b2f8
--- /dev/null
+++ b/bdb/dbinc/db_server_int.h
@@ -0,0 +1,148 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_server_int.h,v 1.23 2002/02/12 15:01:24 sue Exp $
+ */
+
+#ifndef _DB_SERVER_INT_H_
+#define _DB_SERVER_INT_H_
+
+#define DB_SERVER_TIMEOUT 300 /* 5 minutes */
+#define DB_SERVER_MAXTIMEOUT 1200 /* 20 minutes */
+#define DB_SERVER_IDLETIMEOUT 86400 /* 1 day */
+
+/*
+ * Ignore/mask off the following env->open flags:
+ * Most are illegal for a client to specify as they would control
+ * server resource usage. We will just ignore them.
+ * DB_LOCKDOWN
+ * DB_PRIVATE
+ * DB_RECOVER
+ * DB_RECOVER_FATAL
+ * DB_SYSTEM_MEM
+ * DB_USE_ENVIRON, DB_USE_ENVIRON_ROOT - handled on client
+ */
+#define DB_SERVER_FLAGMASK ( \
+DB_LOCKDOWN | DB_PRIVATE | DB_RECOVER | DB_RECOVER_FATAL | \
+DB_SYSTEM_MEM | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
+
+#define CT_CURSOR 0x001 /* Cursor */
+#define CT_DB 0x002 /* Database */
+#define CT_ENV 0x004 /* Env */
+#define CT_TXN 0x008 /* Txn */
+
+#define CT_JOIN 0x10000000 /* Join cursor component */
+#define CT_JOINCUR 0x20000000 /* Join cursor */
+
+typedef struct home_entry home_entry;
+struct home_entry {
+ LIST_ENTRY(home_entry) entries;
+ char *home;
+ char *dir;
+ char *name;
+ char *passwd;
+};
+
+/*
+ * Data needed for sharing handles.
+ * To share an env handle, on the open call, they must have matching
+ * env flags, and matching set_flags.
+ *
+ * To share a db handle on the open call, the db, subdb and flags must
+ * all be the same.
+ */
+#define DB_SERVER_ENVFLAGS ( \
+DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | \
+DB_INIT_TXN | DB_JOINENV)
+
+#define DB_SERVER_DBFLAGS (DB_DIRTY_READ | DB_NOMMAP | DB_RDONLY)
+#define DB_SERVER_DBNOSHARE (DB_EXCL | DB_TRUNCATE)
+
+typedef struct ct_envdata ct_envdata;
+typedef struct ct_dbdata ct_dbdata;
+struct ct_envdata {
+ u_int32_t envflags;
+ u_int32_t onflags;
+ u_int32_t offflags;
+ home_entry *home;
+};
+
+struct ct_dbdata {
+ u_int32_t dbflags;
+ u_int32_t setflags;
+ char *db;
+ char *subdb;
+ DBTYPE type;
+};
+
+/*
+ * We maintain an activity timestamp for each handle. However, we
+ * set it to point, possibly to the ct_active field of its own handle
+ * or it may point to the ct_active field of a parent. In the case
+ * of nested transactions and any cursors within transactions it must
+ * point to the ct_active field of the ultimate parent of the transaction
+ * no matter how deeply it is nested.
+ */
+typedef struct ct_entry ct_entry;
+struct ct_entry {
+ LIST_ENTRY(ct_entry) entries; /* List of entries */
+ union {
+#ifdef __cplusplus
+ DbEnv *envp; /* H_ENV */
+ DbTxn *txnp; /* H_TXN */
+ Db *dbp; /* H_DB */
+ Dbc *dbc; /* H_CURSOR */
+#else
+ DB_ENV *envp; /* H_ENV */
+ DB_TXN *txnp; /* H_TXN */
+ DB *dbp; /* H_DB */
+ DBC *dbc; /* H_CURSOR */
+#endif
+ void *anyp;
+ } handle_u;
+ union { /* Private data per type */
+ ct_envdata envdp; /* Env info */
+ ct_dbdata dbdp; /* Db info */
+ } private_u;
+ long ct_id; /* Client ID */
+ long *ct_activep; /* Activity timestamp pointer*/
+ long *ct_origp; /* Original timestamp pointer*/
+ long ct_active; /* Activity timestamp */
+ long ct_timeout; /* Resource timeout */
+ long ct_idle; /* Idle timeout */
+ u_int32_t ct_refcount; /* Ref count for sharing */
+ u_int32_t ct_type; /* This entry's type */
+ struct ct_entry *ct_parent; /* Its parent */
+ struct ct_entry *ct_envparent; /* Its environment */
+};
+
+#define ct_envp handle_u.envp
+#define ct_txnp handle_u.txnp
+#define ct_dbp handle_u.dbp
+#define ct_dbc handle_u.dbc
+#define ct_anyp handle_u.anyp
+
+#define ct_envdp private_u.envdp
+#define ct_dbdp private_u.dbdp
+
+extern int __dbsrv_verbose;
+
+/*
+ * Get ctp and activate it.
+ * Assumes local variable 'replyp'.
+ * NOTE: May 'return' from macro.
+ */
+#define ACTIVATE_CTP(ctp, id, type) { \
+ (ctp) = get_tableent(id); \
+ if ((ctp) == NULL) { \
+ replyp->status = DB_NOSERVER_ID;\
+ return; \
+ } \
+ DB_ASSERT((ctp)->ct_type & (type)); \
+ __dbsrv_active(ctp); \
+}
+
+#endif /* !_DB_SERVER_INT_H_ */
diff --git a/bdb/dbinc/db_shash.h b/bdb/dbinc/db_shash.h
new file mode 100644
index 00000000000..2c54d6145c5
--- /dev/null
+++ b/bdb/dbinc/db_shash.h
@@ -0,0 +1,81 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_shash.h,v 11.11 2002/01/11 15:52:26 bostic Exp $
+ */
+
+#ifndef _DB_SHASH_H_
+#define _DB_SHASH_H_
+
+/* Hash Headers */
+typedef SH_TAILQ_HEAD(__hash_head) DB_HASHTAB;
+
+/*
+ * HASHLOOKUP --
+ *
+ * Look up something in a shared memory hash table. The "elt" argument
+ * should be a key, and cmp_func must know how to compare a key to whatever
+ * structure it is that appears in the hash table. The comparison function
+ *
+ * begin: address of the beginning of the hash table.
+ * ndx: index into table for this item.
+ * type: the structure type of the elements that are linked in each bucket.
+ * field: the name of the field by which the "type" structures are linked.
+ * elt: the item for which we are searching in the hash table.
+ * res: the variable into which we'll store the element if we find it.
+ * cmp: called as: cmp(lookup_elt, table_elt).
+ *
+ * If the element is not in the hash table, this macro exits with res set
+ * to NULL.
+ */
+#define HASHLOOKUP(begin, ndx, type, field, elt, res, cmp) do { \
+ DB_HASHTAB *__bucket; \
+ \
+ __bucket = &begin[ndx]; \
+ for (res = SH_TAILQ_FIRST(__bucket, type); \
+ res != NULL; res = SH_TAILQ_NEXT(res, field, type)) \
+ if (cmp(elt, res)) \
+ break; \
+} while (0)
+
+/*
+ * HASHINSERT --
+ *
+ * Insert a new entry into the hash table. This assumes that you already
+ * have the bucket locked and that lookup has failed; don't call it if you
+ * haven't already called HASHLOOKUP. If you do, you could get duplicate
+ * entries.
+ *
+ * begin: the beginning address of the hash table.
+ * ndx: the index for this element.
+ * type: the structure type of the elements that are linked in each bucket.
+ * field: the name of the field by which the "type" structures are linked.
+ * elt: the item to be inserted.
+ */
+#define HASHINSERT(begin, ndx, type, field, elt) do { \
+ DB_HASHTAB *__bucket; \
+ \
+ __bucket = &begin[ndx]; \
+ SH_TAILQ_INSERT_HEAD(__bucket, elt, field, type); \
+} while (0)
+
+/*
+ * HASHREMOVE_EL --
+ * Given the object "obj" in the table, remove it.
+ *
+ * begin: address of the beginning of the hash table.
+ * ndx: index into hash table of where this element belongs.
+ * type: the structure type of the elements that are linked in each bucket.
+ * field: the name of the field by which the "type" structures are linked.
+ * obj: the object in the table that we with to delete.
+ */
+#define HASHREMOVE_EL(begin, ndx, type, field, obj) { \
+ DB_HASHTAB *__bucket; \
+ \
+ __bucket = &begin[ndx]; \
+ SH_TAILQ_REMOVE(__bucket, obj, field, type); \
+}
+#endif /* !_DB_SHASH_H_ */
diff --git a/bdb/dbinc/db_swap.h b/bdb/dbinc/db_swap.h
new file mode 100644
index 00000000000..d5aad65385e
--- /dev/null
+++ b/bdb/dbinc/db_swap.h
@@ -0,0 +1,116 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: db_swap.h,v 11.8 2002/01/11 15:52:26 bostic Exp $
+ */
+
+#ifndef _DB_SWAP_H_
+#define _DB_SWAP_H_
+
+/*
+ * Little endian <==> big endian 32-bit swap macros.
+ * M_32_SWAP swap a memory location
+ * P_32_COPY copy potentially unaligned 4 byte quantities
+ * P_32_SWAP swap a referenced memory location
+ */
+#define M_32_SWAP(a) { \
+ u_int32_t _tmp; \
+ _tmp = a; \
+ ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[3]; \
+ ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[2]; \
+ ((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1]; \
+ ((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0]; \
+}
+#define P_32_COPY(a, b) { \
+ ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \
+ ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \
+ ((u_int8_t *)b)[2] = ((u_int8_t *)a)[2]; \
+ ((u_int8_t *)b)[3] = ((u_int8_t *)a)[3]; \
+}
+#define P_32_SWAP(a) { \
+ u_int32_t _tmp; \
+ P_32_COPY(a, &_tmp); \
+ ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[3]; \
+ ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[2]; \
+ ((u_int8_t *)a)[2] = ((u_int8_t *)&_tmp)[1]; \
+ ((u_int8_t *)a)[3] = ((u_int8_t *)&_tmp)[0]; \
+}
+
+/*
+ * Little endian <==> big endian 16-bit swap macros.
+ * M_16_SWAP swap a memory location
+ * P_16_COPY copy potentially unaligned 2 byte quantities
+ * P_16_SWAP swap a referenced memory location
+ */
+#define M_16_SWAP(a) { \
+ u_int16_t _tmp; \
+ _tmp = (u_int16_t)a; \
+ ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[1]; \
+ ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[0]; \
+}
+#define P_16_COPY(a, b) { \
+ ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \
+ ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \
+}
+#define P_16_SWAP(a) { \
+ u_int16_t _tmp; \
+ P_16_COPY(a, &_tmp); \
+ ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[1]; \
+ ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[0]; \
+}
+
+#define SWAP32(p) { \
+ P_32_SWAP(p); \
+ (p) += sizeof(u_int32_t); \
+}
+#define SWAP16(p) { \
+ P_16_SWAP(p); \
+ (p) += sizeof(u_int16_t); \
+}
+
+/*
+ * Berkeley DB has local versions of htonl() and ntohl() that operate on
+ * pointers to the right size memory locations; the portability magic for
+ * finding the real system functions isn't worth the effort.
+ */
+#define DB_HTONL(p) do { \
+ if (!__db_isbigendian()) \
+ P_32_SWAP(p); \
+} while (0)
+#define DB_NTOHL(p) do { \
+ if (!__db_isbigendian()) \
+ P_32_SWAP(p); \
+} while (0)
+
+#endif /* !_DB_SWAP_H_ */
diff --git a/bdb/dbinc/db_upgrade.h b/bdb/dbinc/db_upgrade.h
new file mode 100644
index 00000000000..3ccba810889
--- /dev/null
+++ b/bdb/dbinc/db_upgrade.h
@@ -0,0 +1,242 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_upgrade.h,v 1.10 2002/01/11 15:52:26 bostic Exp $
+ */
+
+#ifndef _DB_UPGRADE_H_
+#define _DB_UPGRADE_H_
+
+/*
+ * This file defines the metadata pages from the previous release.
+ * These structures are only used to upgrade old versions of databases.
+ */
+
+/* Structures from the 3.1 release */
+typedef struct _dbmeta31 {
+ DB_LSN lsn; /* 00-07: LSN. */
+ db_pgno_t pgno; /* 08-11: Current page number. */
+ u_int32_t magic; /* 12-15: Magic number. */
+ u_int32_t version; /* 16-19: Version. */
+ u_int32_t pagesize; /* 20-23: Pagesize. */
+ u_int8_t unused1[1]; /* 24: Unused. */
+ u_int8_t type; /* 25: Page type. */
+ u_int8_t unused2[2]; /* 26-27: Unused. */
+ u_int32_t free; /* 28-31: Free list page number. */
+ DB_LSN unused3; /* 36-39: Unused. */
+ u_int32_t key_count; /* 40-43: Cached key count. */
+ u_int32_t record_count; /* 44-47: Cached record count. */
+ u_int32_t flags; /* 48-51: Flags: unique to each AM. */
+ /* 52-71: Unique file ID. */
+ u_int8_t uid[DB_FILE_ID_LEN];
+} DBMETA31;
+
+typedef struct _btmeta31 {
+ DBMETA31 dbmeta; /* 00-71: Generic meta-data header. */
+
+ u_int32_t maxkey; /* 72-75: Btree: Maxkey. */
+ u_int32_t minkey; /* 76-79: Btree: Minkey. */
+ u_int32_t re_len; /* 80-83: Recno: fixed-length record length. */
+ u_int32_t re_pad; /* 84-87: Recno: fixed-length record pad. */
+ u_int32_t root; /* 88-92: Root page. */
+
+ /*
+ * Minimum page size is 128.
+ */
+} BTMETA31;
+
+/************************************************************************
+ HASH METADATA PAGE LAYOUT
+ ************************************************************************/
+typedef struct _hashmeta31 {
+ DBMETA31 dbmeta; /* 00-71: Generic meta-data page header. */
+
+ u_int32_t max_bucket; /* 72-75: ID of Maximum bucket in use */
+ u_int32_t high_mask; /* 76-79: Modulo mask into table */
+ u_int32_t low_mask; /* 80-83: Modulo mask into table lower half */
+ u_int32_t ffactor; /* 84-87: Fill factor */
+ u_int32_t nelem; /* 88-91: Number of keys in hash table */
+ u_int32_t h_charkey; /* 92-95: Value of hash(CHARKEY) */
+#define NCACHED 32 /* number of spare points */
+ /* 96-223: Spare pages for overflow */
+ u_int32_t spares[NCACHED];
+
+ /*
+ * Minimum page size is 256.
+ */
+} HMETA31;
+
+/*
+ * QAM Meta data page structure
+ *
+ */
+typedef struct _qmeta31 {
+ DBMETA31 dbmeta; /* 00-71: Generic meta-data header. */
+
+ u_int32_t start; /* 72-75: Start offset. */
+ u_int32_t first_recno; /* 76-79: First not deleted record. */
+ u_int32_t cur_recno; /* 80-83: Last recno allocated. */
+ u_int32_t re_len; /* 84-87: Fixed-length record length. */
+ u_int32_t re_pad; /* 88-91: Fixed-length record pad. */
+ u_int32_t rec_page; /* 92-95: Records Per Page. */
+
+ /*
+ * Minimum page size is 128.
+ */
+} QMETA31;
+/* Structures from the 3.2 release */
+typedef struct _qmeta32 {
+ DBMETA31 dbmeta; /* 00-71: Generic meta-data header. */
+
+ u_int32_t first_recno; /* 72-75: First not deleted record. */
+ u_int32_t cur_recno; /* 76-79: Last recno allocated. */
+ u_int32_t re_len; /* 80-83: Fixed-length record length. */
+ u_int32_t re_pad; /* 84-87: Fixed-length record pad. */
+ u_int32_t rec_page; /* 88-91: Records Per Page. */
+ u_int32_t page_ext; /* 92-95: Pages per extent */
+
+ /*
+ * Minimum page size is 128.
+ */
+} QMETA32;
+
+/* Structures from the 3.0 release */
+
+typedef struct _dbmeta30 {
+ DB_LSN lsn; /* 00-07: LSN. */
+ db_pgno_t pgno; /* 08-11: Current page number. */
+ u_int32_t magic; /* 12-15: Magic number. */
+ u_int32_t version; /* 16-19: Version. */
+ u_int32_t pagesize; /* 20-23: Pagesize. */
+ u_int8_t unused1[1]; /* 24: Unused. */
+ u_int8_t type; /* 25: Page type. */
+ u_int8_t unused2[2]; /* 26-27: Unused. */
+ u_int32_t free; /* 28-31: Free list page number. */
+ u_int32_t flags; /* 32-35: Flags: unique to each AM. */
+ /* 36-55: Unique file ID. */
+ u_int8_t uid[DB_FILE_ID_LEN];
+} DBMETA30;
+
+/************************************************************************
+ BTREE METADATA PAGE LAYOUT
+ ************************************************************************/
+typedef struct _btmeta30 {
+ DBMETA30 dbmeta; /* 00-55: Generic meta-data header. */
+
+ u_int32_t maxkey; /* 56-59: Btree: Maxkey. */
+ u_int32_t minkey; /* 60-63: Btree: Minkey. */
+ u_int32_t re_len; /* 64-67: Recno: fixed-length record length. */
+ u_int32_t re_pad; /* 68-71: Recno: fixed-length record pad. */
+ u_int32_t root; /* 72-75: Root page. */
+
+ /*
+ * Minimum page size is 128.
+ */
+} BTMETA30;
+
+/************************************************************************
+ HASH METADATA PAGE LAYOUT
+ ************************************************************************/
+typedef struct _hashmeta30 {
+ DBMETA30 dbmeta; /* 00-55: Generic meta-data page header. */
+
+ u_int32_t max_bucket; /* 56-59: ID of Maximum bucket in use */
+ u_int32_t high_mask; /* 60-63: Modulo mask into table */
+ u_int32_t low_mask; /* 64-67: Modulo mask into table lower half */
+ u_int32_t ffactor; /* 68-71: Fill factor */
+ u_int32_t nelem; /* 72-75: Number of keys in hash table */
+ u_int32_t h_charkey; /* 76-79: Value of hash(CHARKEY) */
+#define NCACHED30 32 /* number of spare points */
+ /* 80-207: Spare pages for overflow */
+ u_int32_t spares[NCACHED30];
+
+ /*
+ * Minimum page size is 256.
+ */
+} HMETA30;
+
+/************************************************************************
+ QUEUE METADATA PAGE LAYOUT
+ ************************************************************************/
+/*
+ * QAM Meta data page structure
+ *
+ */
+typedef struct _qmeta30 {
+ DBMETA30 dbmeta; /* 00-55: Generic meta-data header. */
+
+ u_int32_t start; /* 56-59: Start offset. */
+ u_int32_t first_recno; /* 60-63: First not deleted record. */
+ u_int32_t cur_recno; /* 64-67: Last recno allocated. */
+ u_int32_t re_len; /* 68-71: Fixed-length record length. */
+ u_int32_t re_pad; /* 72-75: Fixed-length record pad. */
+ u_int32_t rec_page; /* 76-79: Records Per Page. */
+
+ /*
+ * Minimum page size is 128.
+ */
+} QMETA30;
+
+/* Structures from Release 2.x */
+
+/************************************************************************
+ BTREE METADATA PAGE LAYOUT
+ ************************************************************************/
+
+/*
+ * Btree metadata page layout:
+ */
+typedef struct _btmeta2X {
+ DB_LSN lsn; /* 00-07: LSN. */
+ db_pgno_t pgno; /* 08-11: Current page number. */
+ u_int32_t magic; /* 12-15: Magic number. */
+ u_int32_t version; /* 16-19: Version. */
+ u_int32_t pagesize; /* 20-23: Pagesize. */
+ u_int32_t maxkey; /* 24-27: Btree: Maxkey. */
+ u_int32_t minkey; /* 28-31: Btree: Minkey. */
+ u_int32_t free; /* 32-35: Free list page number. */
+ u_int32_t flags; /* 36-39: Flags. */
+ u_int32_t re_len; /* 40-43: Recno: fixed-length record length. */
+ u_int32_t re_pad; /* 44-47: Recno: fixed-length record pad. */
+ /* 48-67: Unique file ID. */
+ u_int8_t uid[DB_FILE_ID_LEN];
+} BTMETA2X;
+
+/************************************************************************
+ HASH METADATA PAGE LAYOUT
+ ************************************************************************/
+
+/*
+ * Hash metadata page layout:
+ */
+/* Hash Table Information */
+typedef struct hashhdr { /* Disk resident portion */
+ DB_LSN lsn; /* 00-07: LSN of the header page */
+ db_pgno_t pgno; /* 08-11: Page number (btree compatibility). */
+ u_int32_t magic; /* 12-15: Magic NO for hash tables */
+ u_int32_t version; /* 16-19: Version ID */
+ u_int32_t pagesize; /* 20-23: Bucket/Page Size */
+ u_int32_t ovfl_point; /* 24-27: Overflow page allocation location */
+ u_int32_t last_freed; /* 28-31: Last freed overflow page pgno */
+ u_int32_t max_bucket; /* 32-35: ID of Maximum bucket in use */
+ u_int32_t high_mask; /* 36-39: Modulo mask into table */
+ u_int32_t low_mask; /* 40-43: Modulo mask into table lower half */
+ u_int32_t ffactor; /* 44-47: Fill factor */
+ u_int32_t nelem; /* 48-51: Number of keys in hash table */
+ u_int32_t h_charkey; /* 52-55: Value of hash(CHARKEY) */
+ u_int32_t flags; /* 56-59: Allow duplicates. */
+#define NCACHED2X 32 /* number of spare points */
+ /* 60-187: Spare pages for overflow */
+ u_int32_t spares[NCACHED2X];
+ /* 188-207: Unique file ID. */
+ u_int8_t uid[DB_FILE_ID_LEN];
+
+ /*
+ * Minimum page size is 256.
+ */
+} HASHHDR;
+
+#endif /* !_DB_UPGRADE_H_ */
diff --git a/bdb/dbinc/db_verify.h b/bdb/dbinc/db_verify.h
new file mode 100644
index 00000000000..949c9a2a6a1
--- /dev/null
+++ b/bdb/dbinc/db_verify.h
@@ -0,0 +1,205 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: db_verify.h,v 1.26 2002/08/06 06:37:08 bostic Exp $
+ */
+
+#ifndef _DB_VERIFY_H_
+#define _DB_VERIFY_H_
+
+/*
+ * Structures and macros for the storage and retrieval of all information
+ * needed for inter-page verification of a database.
+ */
+
+/*
+ * EPRINT is the macro for error printing. Takes as an arg the arg set
+ * for DB->err.
+ */
+#define EPRINT(x) \
+ do { \
+ if (!LF_ISSET(DB_SALVAGE)) \
+ __db_err x; \
+ } while (0)
+
+/* For fatal type errors--i.e., verifier bugs. */
+#define TYPE_ERR_PRINT(dbenv, func, pgno, ptype) \
+ EPRINT(((dbenv), "Page %lu: %s called on nonsensical page of type %lu", \
+ (u_long)(pgno), (func), (u_long)(ptype)));
+
+/* Complain about a totally zeroed page where we don't expect one. */
+#define ZEROPG_ERR_PRINT(dbenv, pgno, str) \
+ do { \
+ EPRINT(((dbenv), "Page %lu: %s is of inappropriate type %lu", \
+ (u_long)(pgno), str, (u_long)P_INVALID)); \
+ EPRINT(((dbenv), "Page %lu: totally zeroed page", \
+ (u_long)(pgno))); \
+ } while (0)
+
+/*
+ * Note that 0 is, in general, a valid pgno, despite equalling PGNO_INVALID;
+ * we have to test it separately where it's not appropriate.
+ */
+#define IS_VALID_PGNO(x) ((x) <= vdp->last_pgno)
+
+/*
+ * Flags understood by the btree structure checks (esp. __bam_vrfy_subtree).
+ * These share the same space as the global flags to __db_verify, and must not
+ * dip below 0x00010000.
+ */
+#define ST_DUPOK 0x00010000 /* Duplicates are acceptable. */
+#define ST_DUPSET 0x00020000 /* Subtree is in a duplicate tree. */
+#define ST_DUPSORT 0x00040000 /* Duplicates are sorted. */
+#define ST_IS_RECNO 0x00080000 /* Subtree is a recno. */
+#define ST_OVFL_LEAF 0x00100000 /* Overflow reffed from leaf page. */
+#define ST_RECNUM 0x00200000 /* Subtree has record numbering on. */
+#define ST_RELEN 0x00400000 /* Subtree has fixed-length records. */
+#define ST_TOPLEVEL 0x00800000 /* Subtree == entire tree */
+
+/*
+ * Flags understood by __bam_salvage and __db_salvage. These need not share
+ * the same space with the __bam_vrfy_subtree flags, but must share with
+ * __db_verify.
+ */
+#define SA_SKIPFIRSTKEY 0x00080000
+
+/*
+ * VRFY_DBINFO is the fundamental structure; it either represents the database
+ * of subdatabases, or the sole database if there are no subdatabases.
+ */
+struct __vrfy_dbinfo {
+ /* Info about this database in particular. */
+ DBTYPE type;
+
+ /* List of subdatabase meta pages, if any. */
+ LIST_HEAD(__subdbs, __vrfy_childinfo) subdbs;
+
+ /* File-global info--stores VRFY_PAGEINFOs for each page. */
+ DB *pgdbp;
+
+ /* Child database--stores VRFY_CHILDINFOs of each page. */
+ DB *cdbp;
+
+ /* Page info structures currently in use. */
+ LIST_HEAD(__activepips, __vrfy_pageinfo) activepips;
+
+ /*
+ * DB we use to keep track of which pages are linked somehow
+ * during verification. 0 is the default, "unseen"; 1 is seen.
+ */
+ DB *pgset;
+
+ /*
+ * This is a database we use during salvaging to keep track of which
+ * overflow and dup pages we need to come back to at the end and print
+ * with key "UNKNOWN". Pages which print with a good key get set
+ * to SALVAGE_IGNORE; others get set, as appropriate, to SALVAGE_LDUP,
+ * SALVAGE_LRECNODUP, SALVAGE_OVERFLOW for normal db overflow pages,
+ * and SALVAGE_BTREE, SALVAGE_LRECNO, and SALVAGE_HASH for subdb
+ * pages.
+ */
+#define SALVAGE_INVALID 0
+#define SALVAGE_IGNORE 1
+#define SALVAGE_LDUP 2
+#define SALVAGE_LRECNODUP 3
+#define SALVAGE_OVERFLOW 4
+#define SALVAGE_LBTREE 5
+#define SALVAGE_HASH 6
+#define SALVAGE_LRECNO 7
+ DB *salvage_pages;
+
+ db_pgno_t last_pgno;
+ db_pgno_t pgs_remaining; /* For dbp->db_feedback(). */
+
+ /*
+ * These are used during __bam_vrfy_subtree to keep track, while
+ * walking up and down the Btree structure, of the prev- and next-page
+ * chain of leaf pages and verify that it's intact. Also, make sure
+ * that this chain contains pages of only one type.
+ */
+ db_pgno_t prev_pgno;
+ db_pgno_t next_pgno;
+ u_int8_t leaf_type;
+
+ /* Queue needs these to verify data pages in the first pass. */
+ u_int32_t re_len;
+ u_int32_t rec_page;
+
+#define SALVAGE_PRINTABLE 0x01 /* Output printable chars literally. */
+#define SALVAGE_PRINTHEADER 0x02 /* Print the unknown-key header. */
+#define SALVAGE_PRINTFOOTER 0x04 /* Print the unknown-key footer. */
+ u_int32_t flags;
+}; /* VRFY_DBINFO */
+
+/*
+ * The amount of state information we need per-page is small enough that
+ * it's not worth the trouble to define separate structures for each
+ * possible type of page, and since we're doing verification with these we
+ * have to be open to the possibility that page N will be of a completely
+ * unexpected type anyway. So we define one structure here with all the
+ * info we need for inter-page verification.
+ */
+struct __vrfy_pageinfo {
+ u_int8_t type;
+ u_int8_t bt_level;
+ u_int8_t unused1;
+ u_int8_t unused2;
+ db_pgno_t pgno;
+ db_pgno_t prev_pgno;
+ db_pgno_t next_pgno;
+
+ /* meta pages */
+ db_pgno_t root;
+ db_pgno_t free; /* Free list head. */
+
+ db_indx_t entries; /* Actual number of entries. */
+ u_int16_t unused;
+ db_recno_t rec_cnt; /* Record count. */
+ u_int32_t re_len; /* Record length. */
+ u_int32_t bt_minkey;
+ u_int32_t bt_maxkey;
+ u_int32_t h_ffactor;
+ u_int32_t h_nelem;
+
+ /* overflow pages */
+ /*
+ * Note that refcount is the refcount for an overflow page; pi_refcount
+ * is this structure's own refcount!
+ */
+ u_int32_t refcount;
+ u_int32_t olen;
+
+#define VRFY_DUPS_UNSORTED 0x0001 /* Have to flag the negative! */
+#define VRFY_HAS_DUPS 0x0002
+#define VRFY_HAS_DUPSORT 0x0004 /* Has the flag set. */
+#define VRFY_HAS_SUBDBS 0x0008
+#define VRFY_HAS_RECNUMS 0x0010
+#define VRFY_INCOMPLETE 0x0020 /* Meta or item order checks incomp. */
+#define VRFY_IS_ALLZEROES 0x0040 /* Hash page we haven't touched? */
+#define VRFY_IS_FIXEDLEN 0x0080
+#define VRFY_IS_RECNO 0x0100
+#define VRFY_IS_RRECNO 0x0200
+#define VRFY_OVFL_LEAFSEEN 0x0400
+ u_int32_t flags;
+
+ LIST_ENTRY(__vrfy_pageinfo) links;
+ u_int32_t pi_refcount;
+}; /* VRFY_PAGEINFO */
+
+struct __vrfy_childinfo {
+ db_pgno_t pgno;
+
+#define V_DUPLICATE 1 /* off-page dup metadata */
+#define V_OVERFLOW 2 /* overflow page */
+#define V_RECNO 3 /* btree internal or leaf page */
+ u_int32_t type;
+ db_recno_t nrecs; /* record count on a btree subtree */
+ u_int32_t tlen; /* ovfl. item total size */
+
+ LIST_ENTRY(__vrfy_childinfo) links;
+}; /* VRFY_CHILDINFO */
+
+#endif /* !_DB_VERIFY_H_ */
diff --git a/bdb/dbinc/debug.h b/bdb/dbinc/debug.h
new file mode 100644
index 00000000000..21f80387ccc
--- /dev/null
+++ b/bdb/dbinc/debug.h
@@ -0,0 +1,198 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: debug.h,v 11.31 2002/08/06 06:37:08 bostic Exp $
+ */
+
+#ifndef _DB_DEBUG_H_
+#define _DB_DEBUG_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * When running with #DIAGNOSTIC defined, we smash memory and do memory
+ * guarding with a special byte value.
+ */
+#define CLEAR_BYTE 0xdb
+#define GUARD_BYTE 0xdc
+
+/*
+ * DB assertions.
+ */
+#if defined(DIAGNOSTIC) && defined(__STDC__)
+#define DB_ASSERT(e) ((e) ? (void)0 : __db_assert(#e, __FILE__, __LINE__))
+#else
+#define DB_ASSERT(e)
+#endif
+
+/*
+ * Purify and other run-time tools complain about uninitialized reads/writes
+ * of structure fields whose only purpose is padding, as well as when heap
+ * memory that was never initialized is written to disk.
+ */
+#ifdef UMRW
+#define UMRW_SET(v) (v) = 0
+#else
+#define UMRW_SET(v)
+#endif
+
+/*
+ * Error message handling. Use a macro instead of a function because va_list
+ * references to variadic arguments cannot be reset to the beginning of the
+ * variadic argument list (and then rescanned), by functions other than the
+ * original routine that took the variadic list of arguments.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define DB_REAL_ERR(env, error, error_set, stderr_default, fmt) { \
+ va_list ap; \
+ \
+ /* Call the user's callback function, if specified. */ \
+ va_start(ap, fmt); \
+ if ((env) != NULL && (env)->db_errcall != NULL) \
+ __db_errcall(env, error, error_set, fmt, ap); \
+ va_end(ap); \
+ \
+ /* Write to the user's file descriptor, if specified. */ \
+ va_start(ap, fmt); \
+ if ((env) != NULL && (env)->db_errfile != NULL) \
+ __db_errfile(env, error, error_set, fmt, ap); \
+ va_end(ap); \
+ \
+ /* \
+ * If we have a default and we didn't do either of the above, \
+ * write to the default. \
+ */ \
+ va_start(ap, fmt); \
+ if ((stderr_default) && ((env) == NULL || \
+ ((env)->db_errcall == NULL && (env)->db_errfile == NULL))) \
+ __db_errfile(env, error, error_set, fmt, ap); \
+ va_end(ap); \
+}
+#else
+#define DB_REAL_ERR(env, error, error_set, stderr_default, fmt) { \
+ va_list ap; \
+ \
+ /* Call the user's callback function, if specified. */ \
+ va_start(ap); \
+ if ((env) != NULL && (env)->db_errcall != NULL) \
+ __db_errcall(env, error, error_set, fmt, ap); \
+ va_end(ap); \
+ \
+ /* Write to the user's file descriptor, if specified. */ \
+ va_start(ap); \
+ if ((env) != NULL && (env)->db_errfile != NULL) \
+ __db_errfile(env, error, error_set, fmt, ap); \
+ va_end(ap); \
+ \
+ /* \
+ * If we have a default and we didn't do either of the above, \
+ * write to the default. \
+ */ \
+ va_start(ap); \
+ if ((stderr_default) && ((env) == NULL || \
+ ((env)->db_errcall == NULL && (env)->db_errfile == NULL))) \
+ __db_errfile(env, error, error_set, fmt, ap); \
+ va_end(ap); \
+}
+#endif
+
+/*
+ * Debugging macro to log operations.
+ * If DEBUG_WOP is defined, log operations that modify the database.
+ * If DEBUG_ROP is defined, log operations that read the database.
+ *
+ * D dbp
+ * T txn
+ * O operation (string)
+ * K key
+ * A data
+ * F flags
+ */
+#define LOG_OP(C, T, O, K, A, F) { \
+ DB_LSN __lsn; \
+ DBT __op; \
+ if (DBC_LOGGING((C))) { \
+ memset(&__op, 0, sizeof(__op)); \
+ __op.data = O; \
+ __op.size = strlen(O) + 1; \
+ (void)__db_debug_log((C)->dbp->dbenv, T, &__lsn, 0, \
+ &__op, (C)->dbp->log_filename->id, K, A, F); \
+ } \
+}
+#ifdef DEBUG_ROP
+#define DEBUG_LREAD(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F)
+#else
+#define DEBUG_LREAD(C, T, O, K, A, F)
+#endif
+#ifdef DEBUG_WOP
+#define DEBUG_LWRITE(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F)
+#else
+#define DEBUG_LWRITE(C, T, O, K, A, F)
+#endif
+
+/*
+ * Hook for testing recovery at various places in the create/delete paths.
+ * Hook for testing subdb locks.
+ */
+#if CONFIG_TEST
+#define DB_TEST_SUBLOCKS(env, flags) \
+do { \
+ if ((env)->test_abort == DB_TEST_SUBDB_LOCKS) \
+ (flags) |= DB_LOCK_NOWAIT; \
+} while (0)
+
+#define DB_ENV_TEST_RECOVERY(env, val, ret, name) \
+do { \
+ int __ret; \
+ PANIC_CHECK((env)); \
+ if ((env)->test_copy == (val)) { \
+ /* COPY the FILE */ \
+ if ((__ret = __db_testcopy((env), NULL, (name))) != 0) \
+ (ret) = __db_panic((env), __ret); \
+ } \
+ if ((env)->test_abort == (val)) { \
+ /* ABORT the TXN */ \
+ (env)->test_abort = 0; \
+ (ret) = EINVAL; \
+ goto db_tr_err; \
+ } \
+} while (0)
+
+#define DB_TEST_RECOVERY(dbp, val, ret, name) \
+do { \
+ int __ret; \
+ PANIC_CHECK((dbp)->dbenv); \
+ if ((dbp)->dbenv->test_copy == (val)) { \
+ /* Copy the file. */ \
+ if (F_ISSET((dbp), \
+ DB_AM_OPEN_CALLED) && (dbp)->mpf != NULL) \
+ (void)(dbp)->sync((dbp), 0); \
+ if ((__ret = \
+ __db_testcopy((dbp)->dbenv, (dbp), (name))) != 0) \
+ (ret) = __db_panic((dbp)->dbenv, __ret); \
+ } \
+ if ((dbp)->dbenv->test_abort == (val)) { \
+ /* Abort the transaction. */ \
+ (dbp)->dbenv->test_abort = 0; \
+ (ret) = EINVAL; \
+ goto db_tr_err; \
+ } \
+} while (0)
+
+#define DB_TEST_RECOVERY_LABEL db_tr_err:
+#else
+#define DB_TEST_SUBLOCKS(env, flags)
+#define DB_ENV_TEST_RECOVERY(env, val, ret, name)
+#define DB_TEST_RECOVERY(dbp, val, ret, name)
+#define DB_TEST_RECOVERY_LABEL
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* !_DB_DEBUG_H_ */
diff --git a/bdb/dbinc/fop.h b/bdb/dbinc/fop.h
new file mode 100644
index 00000000000..c438ef7ef40
--- /dev/null
+++ b/bdb/dbinc/fop.h
@@ -0,0 +1,16 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: fop.h,v 11.3 2002/03/27 04:34:54 bostic Exp $
+ */
+
+#ifndef _FOP_H_
+#define _FOP_H_
+
+#include "dbinc_auto/fileops_auto.h"
+#include "dbinc_auto/fileops_ext.h"
+
+#endif /* !_FOP_H_ */
diff --git a/bdb/dbinc/globals.h b/bdb/dbinc/globals.h
new file mode 100644
index 00000000000..3441ade2ea9
--- /dev/null
+++ b/bdb/dbinc/globals.h
@@ -0,0 +1,83 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: globals.h,v 11.1 2002/07/12 18:56:41 bostic Exp $
+ */
+
+/*******************************************************
+ * Global variables.
+ *
+ * Held in a single structure to minimize the name-space pollution.
+ *******************************************************/
+#ifdef HAVE_VXWORKS
+#include "semLib.h"
+#endif
+
+typedef struct __db_globals {
+ u_int32_t no_write_errors; /* write error testing disallowed */
+#ifdef HAVE_VXWORKS
+ u_int32_t db_global_init; /* VxWorks: inited */
+ SEM_ID db_global_lock; /* VxWorks: global semaphore */
+#endif
+ /* XA: list of opened environments. */
+ TAILQ_HEAD(__db_envq, __db_env) db_envq;
+
+ int (*j_close) __P((int)); /* Underlying OS interface jump table.*/
+ void (*j_dirfree) __P((char **, int));
+ int (*j_dirlist) __P((const char *, char ***, int *));
+ int (*j_exists) __P((const char *, int *));
+ void (*j_free) __P((void *));
+ int (*j_fsync) __P((int));
+ int (*j_ioinfo) __P((const char *,
+ int, u_int32_t *, u_int32_t *, u_int32_t *));
+ void *(*j_malloc) __P((size_t));
+ int (*j_map) __P((char *, size_t, int, int, void **));
+ int (*j_open) __P((const char *, int, ...));
+ ssize_t (*j_read) __P((int, void *, size_t));
+ void *(*j_realloc) __P((void *, size_t));
+ int (*j_rename) __P((const char *, const char *));
+ int (*j_seek) __P((int, size_t, db_pgno_t, u_int32_t, int, int));
+ int (*j_sleep) __P((u_long, u_long));
+ int (*j_unlink) __P((const char *));
+ int (*j_unmap) __P((void *, size_t));
+ ssize_t (*j_write) __P((int, const void *, size_t));
+ int (*j_yield) __P((void));
+} DB_GLOBALS;
+
+#ifdef DB_INITIALIZE_DB_GLOBALS
+DB_GLOBALS __db_global_values = {
+ 0, /* write error testing disallowed */
+#ifdef HAVE_VXWORKS
+ 0, /* VxWorks: initialized */
+ NULL, /* VxWorks: global semaphore */
+#endif
+ /* XA: list of opened environments. */
+ {NULL, &__db_global_values.db_envq.tqh_first},
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+#else
+extern DB_GLOBALS __db_global_values;
+#endif
+
+#define DB_GLOBAL(v) __db_global_values.v
diff --git a/bdb/dbinc/hash.h b/bdb/dbinc/hash.h
new file mode 100644
index 00000000000..98289735fc4
--- /dev/null
+++ b/bdb/dbinc/hash.h
@@ -0,0 +1,147 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * Margo Seltzer. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: hash.h,v 11.26 2002/03/27 04:34:54 bostic Exp $
+ */
+
+#ifndef _DB_HASH_H_
+#define _DB_HASH_H_
+
+/* Hash internal structure. */
+typedef struct hash_t {
+ db_pgno_t meta_pgno; /* Page number of the meta data page. */
+ u_int32_t h_ffactor; /* Fill factor. */
+ u_int32_t h_nelem; /* Number of elements. */
+ /* Hash function. */
+ u_int32_t (*h_hash) __P((DB *, const void *, u_int32_t));
+} HASH;
+
+/* Cursor structure definitions. */
+typedef struct cursor_t {
+ /* struct __dbc_internal */
+ __DBC_INTERNAL
+
+ /* Hash private part */
+
+ /* Per-thread information */
+ DB_LOCK hlock; /* Metadata page lock. */
+ HMETA *hdr; /* Pointer to meta-data page. */
+ PAGE *split_buf; /* Temporary buffer for splits. */
+
+ /* Hash cursor information */
+ db_pgno_t bucket; /* Bucket we are traversing. */
+ db_pgno_t lbucket; /* Bucket for which we are locked. */
+ db_indx_t dup_off; /* Offset within a duplicate set. */
+ db_indx_t dup_len; /* Length of current duplicate. */
+ db_indx_t dup_tlen; /* Total length of duplicate entry. */
+ u_int32_t seek_size; /* Number of bytes we need for add. */
+ db_pgno_t seek_found_page;/* Page on which we can insert. */
+ u_int32_t order; /* Relative order among deleted curs. */
+
+#define H_CONTINUE 0x0001 /* Join--search strictly fwd for data */
+#define H_DELETED 0x0002 /* Cursor item is deleted. */
+#define H_DIRTY 0x0004 /* Meta-data page needs to be written */
+#define H_DUPONLY 0x0008 /* Dups only; do not change key. */
+#define H_EXPAND 0x0010 /* Table expanded. */
+#define H_ISDUP 0x0020 /* Cursor is within duplicate set. */
+#define H_NEXT_NODUP 0x0040 /* Get next non-dup entry. */
+#define H_NOMORE 0x0080 /* No more entries in bucket. */
+#define H_OK 0x0100 /* Request succeeded. */
+ u_int32_t flags;
+} HASH_CURSOR;
+
+/* Test string. */
+#define CHARKEY "%$sniglet^&"
+
+/* Overflow management */
+/*
+ * The spares table indicates the page number at which each doubling begins.
+ * From this page number we subtract the number of buckets already allocated
+ * so that we can do a simple addition to calculate the page number here.
+ */
+#define BS_TO_PAGE(bucket, spares) \
+ ((bucket) + (spares)[__db_log2((bucket) + 1)])
+#define BUCKET_TO_PAGE(I, B) (BS_TO_PAGE((B), (I)->hdr->spares))
+
+/* Constraints about much data goes on a page. */
+
+#define MINFILL 4
+#define ISBIG(I, N) (((N) > ((I)->hdr->dbmeta.pagesize / MINFILL)) ? 1 : 0)
+
+/* Shorthands for accessing structure */
+#define NDX_INVALID 0xFFFF
+#define BUCKET_INVALID 0xFFFFFFFF
+
+/* On page duplicates are stored as a string of size-data-size triples. */
+#define DUP_SIZE(len) ((len) + 2 * sizeof(db_indx_t))
+
+/* Log messages types (these are subtypes within a record type) */
+#define PAIR_KEYMASK 0x1
+#define PAIR_DATAMASK 0x2
+#define PAIR_DUPMASK 0x4
+#define PAIR_MASK 0xf
+#define PAIR_ISKEYBIG(N) (N & PAIR_KEYMASK)
+#define PAIR_ISDATABIG(N) (N & PAIR_DATAMASK)
+#define PAIR_ISDATADUP(N) (N & PAIR_DUPMASK)
+#define OPCODE_OF(N) (N & ~PAIR_MASK)
+
+#define PUTPAIR 0x20
+#define DELPAIR 0x30
+#define PUTOVFL 0x40
+#define DELOVFL 0x50
+#define HASH_UNUSED1 0x60
+#define HASH_UNUSED2 0x70
+#define SPLITOLD 0x80
+#define SPLITNEW 0x90
+
+typedef enum {
+ DB_HAM_CHGPG = 1,
+ DB_HAM_DELFIRSTPG = 2,
+ DB_HAM_DELMIDPG = 3,
+ DB_HAM_DELLASTPG = 4,
+ DB_HAM_DUP = 5,
+ DB_HAM_SPLIT = 6
+} db_ham_mode;
+
+#include "dbinc_auto/hash_auto.h"
+#include "dbinc_auto/hash_ext.h"
+#include "dbinc/db_am.h"
+#endif /* !_DB_HASH_H_ */
diff --git a/bdb/dbinc/hmac.h b/bdb/dbinc/hmac.h
new file mode 100644
index 00000000000..16f61fb58ad
--- /dev/null
+++ b/bdb/dbinc/hmac.h
@@ -0,0 +1,32 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: hmac.h,v 1.3 2002/08/06 06:37:08 bostic Exp $
+ */
+
+#ifndef _DB_HMAC_H_
+#define _DB_HMAC_H_
+
+/*
+ * Algorithm specific information.
+ */
+/*
+ * SHA1 checksumming
+ */
+typedef struct {
+ u_int32_t state[5];
+ u_int32_t count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+/*
+ * AES assumes the SHA1 checksumming (also called MAC)
+ */
+#define DB_MAC_MAGIC "mac derivation key magic value"
+#define DB_ENC_MAGIC "encryption and decryption key value magic"
+
+#include "dbinc_auto/hmac_ext.h"
+#endif /* !_DB_HMAC_H_ */
diff --git a/bdb/dbinc/lock.h b/bdb/dbinc/lock.h
new file mode 100644
index 00000000000..7ddc9ce9988
--- /dev/null
+++ b/bdb/dbinc/lock.h
@@ -0,0 +1,212 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: lock.h,v 11.42 2002/05/18 01:34:13 bostic Exp $
+ */
+
+#ifndef _DB_LOCK_H_
+#define _DB_LOCK_H_
+
+#define DB_LOCK_DEFAULT_N 1000 /* Default # of locks in region. */
+
+/*
+ * The locker id space is divided between the transaction manager and the lock
+ * manager. Lock IDs start at 1 and go to DB_LOCK_MAXID. Txn IDs start at
+ * DB_LOCK_MAXID + 1 and go up to TXN_MAXIMUM.
+ */
+#define DB_LOCK_INVALIDID 0
+#define DB_LOCK_MAXID 0x7fffffff
+
+/*
+ * Out of band value for a lock. Locks contain an offset into a lock region,
+ * so we use an invalid region offset to indicate an invalid or unset lock.
+ */
+#define LOCK_INVALID INVALID_ROFF
+#define LOCK_ISSET(lock) ((lock).off != LOCK_INVALID)
+#define LOCK_INIT(lock) ((lock).off = LOCK_INVALID)
+
+/*
+ * Macro to identify a write lock for the purpose of counting locks
+ * for the NUMWRITES option to deadlock detection.
+ */
+#define IS_WRITELOCK(m) \
+ ((m) == DB_LOCK_WRITE || (m) == DB_LOCK_IWRITE || (m) == DB_LOCK_IWR)
+
+/*
+ * Lock timers.
+ */
+typedef struct {
+ u_int32_t tv_sec; /* Seconds. */
+ u_int32_t tv_usec; /* Microseconds. */
+} db_timeval_t;
+
+#define LOCK_TIME_ISVALID(time) ((time)->tv_sec != 0)
+#define LOCK_SET_TIME_INVALID(time) ((time)->tv_sec = 0)
+#define LOCK_TIME_EQUAL(t1, t2) \
+ ((t1)->tv_sec == (t2)->tv_sec && (t1)->tv_usec == (t2)->tv_usec)
+
+/*
+ * DB_LOCKREGION --
+ * The lock shared region.
+ */
+typedef struct __db_lockregion {
+ u_int32_t need_dd; /* flag for deadlock detector */
+ u_int32_t detect; /* run dd on every conflict */
+ /* free lock header */
+ SH_TAILQ_HEAD(__flock) free_locks;
+ /* free obj header */
+ SH_TAILQ_HEAD(__fobj) free_objs;
+ /* free locker header */
+ SH_TAILQ_HEAD(__flocker) free_lockers;
+ SH_TAILQ_HEAD(__dobj) dd_objs; /* objects with waiters */
+ SH_TAILQ_HEAD(__lkrs) lockers; /* list of lockers */
+
+ db_timeout_t lk_timeout; /* timeout for locks. */
+ db_timeout_t tx_timeout; /* timeout for txns. */
+
+ u_int32_t locker_t_size; /* size of locker hash table */
+ u_int32_t object_t_size; /* size of object hash table */
+
+ roff_t conf_off; /* offset of conflicts array */
+ roff_t obj_off; /* offset of object hash table */
+ roff_t osynch_off; /* offset of the object mutex table */
+ roff_t locker_off; /* offset of locker hash table */
+ roff_t lsynch_off; /* offset of the locker mutex table */
+
+ DB_LOCK_STAT stat; /* stats about locking. */
+
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ roff_t maint_off; /* offset of region maintenance info */
+#endif
+} DB_LOCKREGION;
+
+/*
+ * Since we will store DBTs in shared memory, we need the equivalent of a
+ * DBT that will work in shared memory.
+ */
+typedef struct __sh_dbt {
+ u_int32_t size; /* Byte length. */
+ ssize_t off; /* Region offset. */
+} SH_DBT;
+
+#define SH_DBT_PTR(p) ((void *)(((u_int8_t *)(p)) + (p)->off))
+
+/*
+ * Object structures; these live in the object hash table.
+ */
+typedef struct __db_lockobj {
+ SH_DBT lockobj; /* Identifies object locked. */
+ SH_TAILQ_ENTRY links; /* Links for free list or hash list. */
+ SH_TAILQ_ENTRY dd_links; /* Links for dd list. */
+ SH_TAILQ_HEAD(__wait) waiters; /* List of waiting locks. */
+ SH_TAILQ_HEAD(__hold) holders; /* List of held locks. */
+ /* Declare room in the object to hold
+ * typical DB lock structures so that
+ * we do not have to allocate them from
+ * shalloc at run-time. */
+ u_int8_t objdata[sizeof(struct __db_ilock)];
+} DB_LOCKOBJ;
+
+/*
+ * Locker structures; these live in the locker hash table.
+ */
+typedef struct __db_locker {
+ u_int32_t id; /* Locker id. */
+ u_int32_t dd_id; /* Deadlock detector id. */
+ u_int32_t nlocks; /* Number of locks held. */
+ u_int32_t nwrites; /* Number of write locks held. */
+ size_t master_locker; /* Locker of master transaction. */
+ size_t parent_locker; /* Parent of this child. */
+ SH_LIST_HEAD(_child) child_locker; /* List of descendant txns;
+ only used in a "master"
+ txn. */
+ SH_LIST_ENTRY child_link; /* Links transactions in the family;
+ elements of the child_locker
+ list. */
+ SH_TAILQ_ENTRY links; /* Links for free and hash list. */
+ SH_TAILQ_ENTRY ulinks; /* Links in-use list. */
+ SH_LIST_HEAD(_held) heldby; /* Locks held by this locker. */
+ db_timeval_t lk_expire; /* When current lock expires. */
+ db_timeval_t tx_expire; /* When this txn expires. */
+ db_timeout_t lk_timeout; /* How long do we let locks live. */
+
+#define DB_LOCKER_DELETED 0x0001
+#define DB_LOCKER_DIRTY 0x0002
+#define DB_LOCKER_INABORT 0x0004
+#define DB_LOCKER_TIMEOUT 0x0008
+ u_int32_t flags;
+} DB_LOCKER;
+
+/*
+ * DB_LOCKTAB --
+ * The primary library lock data structure (i.e., the one referenced
+ * by the environment, as opposed to the internal one laid out in the region.)
+ */
+typedef struct __db_locktab {
+ DB_ENV *dbenv; /* Environment. */
+ REGINFO reginfo; /* Region information. */
+ u_int8_t *conflicts; /* Pointer to conflict matrix. */
+ DB_HASHTAB *obj_tab; /* Beginning of object hash table. */
+ DB_HASHTAB *locker_tab; /* Beginning of locker hash table. */
+} DB_LOCKTAB;
+
+/* Test for conflicts. */
+#define CONFLICTS(T, R, HELD, WANTED) \
+ (T)->conflicts[(HELD) * (R)->stat.st_nmodes + (WANTED)]
+
+#define OBJ_LINKS_VALID(L) ((L)->links.stqe_prev != -1)
+
+struct __db_lock {
+ /*
+ * Wait on mutex to wait on lock. You reference your own mutex with
+ * ID 0 and others reference your mutex with ID 1.
+ */
+ DB_MUTEX mutex;
+
+ u_int32_t holder; /* Who holds this lock. */
+ u_int32_t gen; /* Generation count. */
+ SH_TAILQ_ENTRY links; /* Free or holder/waiter list. */
+ SH_LIST_ENTRY locker_links; /* List of locks held by a locker. */
+ u_int32_t refcount; /* Reference count the lock. */
+ db_lockmode_t mode; /* What sort of lock. */
+ ssize_t obj; /* Relative offset of object struct. */
+ db_status_t status; /* Status of this lock. */
+};
+
+/*
+ * Flag values for __lock_put_internal:
+ * DB_LOCK_DOALL: Unlock all references in this lock (instead of only 1).
+ * DB_LOCK_FREE: Free the lock (used in checklocker).
+ * DB_LOCK_IGNOREDEL: Remove from the locker hash table even if already
+ deleted (used in checklocker).
+ * DB_LOCK_NOPROMOTE: Don't bother running promotion when releasing locks
+ * (used by __lock_put_internal).
+ * DB_LOCK_UNLINK: Remove from the locker links (used in checklocker).
+ * Make sure that these do not conflict with the interface flags because
+ * we pass some of those around (i.e., DB_LOCK_REMOVE).
+ */
+#define DB_LOCK_DOALL 0x010000
+#define DB_LOCK_FREE 0x020000
+#define DB_LOCK_IGNOREDEL 0x040000
+#define DB_LOCK_NOPROMOTE 0x080000
+#define DB_LOCK_UNLINK 0x100000
+#define DB_LOCK_NOWAITERS 0x200000
+
+/*
+ * Macros to get/release different types of mutexes.
+ */
+#define OBJECT_LOCK(lt, reg, obj, ndx) \
+ ndx = __lock_ohash(obj) % (reg)->object_t_size
+#define SHOBJECT_LOCK(lt, reg, shobj, ndx) \
+ ndx = __lock_lhash(shobj) % (reg)->object_t_size
+#define LOCKER_LOCK(lt, reg, locker, ndx) \
+ ndx = __lock_locker_hash(locker) % (reg)->locker_t_size;
+
+#define LOCKREGION(dbenv, lt) R_LOCK((dbenv), &(lt)->reginfo)
+#define UNLOCKREGION(dbenv, lt) R_UNLOCK((dbenv), &(lt)->reginfo)
+
+#include "dbinc_auto/lock_ext.h"
+#endif /* !_DB_LOCK_H_ */
diff --git a/bdb/dbinc/log.h b/bdb/dbinc/log.h
new file mode 100644
index 00000000000..434994528ea
--- /dev/null
+++ b/bdb/dbinc/log.h
@@ -0,0 +1,273 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: log.h,v 11.60 2002/08/06 06:37:08 bostic Exp $
+ */
+
+#ifndef _LOG_H_
+#define _LOG_H_
+
+struct __db_log; typedef struct __db_log DB_LOG;
+struct __hdr; typedef struct __hdr HDR;
+struct __log; typedef struct __log LOG;
+struct __log_persist; typedef struct __log_persist LOGP;
+
+#define LFPREFIX "log." /* Log file name prefix. */
+#define LFNAME "log.%010d" /* Log file name template. */
+#define LFNAME_V1 "log.%05d" /* Log file name template, rev 1. */
+
+#define LG_MAX_DEFAULT (10 * MEGABYTE) /* 10 MB. */
+#define LG_BSIZE_DEFAULT (32 * 1024) /* 32 KB. */
+#define LG_BASE_REGION_SIZE (60 * 1024) /* 60 KB. */
+
+/*
+ * The per-process table that maps log file-id's to DB structures.
+ */
+typedef struct __db_entry {
+ DB *dbp; /* Open dbp for this file id. */
+ int deleted; /* File was not found during open. */
+} DB_ENTRY;
+
+/*
+ * DB_LOG
+ * Per-process log structure.
+ */
+struct __db_log {
+/*
+ * These fields need to be protected for multi-threaded support.
+ *
+ * !!!
+ * As this structure is allocated in per-process memory, the mutex may need
+ * to be stored elsewhere on architectures unable to support mutexes in heap
+ * memory, e.g., HP/UX 9.
+ */
+ DB_MUTEX *mutexp; /* Mutex for thread protection. */
+
+ DB_ENTRY *dbentry; /* Recovery file-id mapping. */
+#define DB_GROW_SIZE 64
+ int32_t dbentry_cnt; /* Entries. Grows by DB_GROW_SIZE. */
+
+/*
+ * These fields are always accessed while the region lock is held, so they do
+ * not have to be protected by the thread lock as well, OR, they are only used
+ * when threads are not being used, i.e. most cursor operations are disallowed
+ * on threaded logs.
+ */
+ u_int32_t lfname; /* Log file "name". */
+ DB_FH lfh; /* Log file handle. */
+
+ u_int8_t *bufp; /* Region buffer. */
+
+/* These fields are not protected. */
+ DB_ENV *dbenv; /* Reference to error information. */
+ REGINFO reginfo; /* Region information. */
+
+#define DBLOG_RECOVER 0x01 /* We are in recovery. */
+#define DBLOG_FORCE_OPEN 0x02 /* Force the DB open even if it appears
+ * to be deleted.
+ */
+ u_int32_t flags;
+};
+
+/*
+ * HDR --
+ * Log record header.
+ */
+struct __hdr {
+ u_int32_t prev; /* Previous offset. */
+ u_int32_t len; /* Current length. */
+ u_int8_t chksum[DB_MAC_KEY]; /* Current checksum. */
+ u_int8_t iv[DB_IV_BYTES]; /* IV */
+ u_int32_t orig_size; /* Original size of log record */
+ /* !!! - 'size' is not written to log, must be last in hdr */
+ size_t size; /* Size of header to use */
+};
+
+/*
+ * We use HDR internally, and then when we write out, we write out
+ * prev, len, and then a 4-byte checksum if normal operation or
+ * a crypto-checksum and IV and original size if running in crypto
+ * mode. We must store the original size in case we pad. Set the
+ * size when we set up the header. We compute a DB_MAC_KEY size
+ * checksum regardless, but we can safely just use the first 4 bytes.
+ */
+#define HDR_NORMAL_SZ 12
+#define HDR_CRYPTO_SZ 12 + DB_MAC_KEY + DB_IV_BYTES
+
+struct __log_persist {
+ u_int32_t magic; /* DB_LOGMAGIC */
+ u_int32_t version; /* DB_LOGVERSION */
+
+ u_int32_t log_size; /* Log file size. */
+ u_int32_t mode; /* Log file mode. */
+};
+
+/*
+ * LOG --
+ * Shared log region. One of these is allocated in shared memory,
+ * and describes the log.
+ */
+struct __log {
+ /*
+ * Due to alignment constraints on some architectures (e.g. HP-UX),
+ * DB_MUTEXes must be the first element of shalloced structures,
+ * and as a corollary there can be only one per structure. Thus,
+ * flush_mutex_off points to a mutex in a separately-allocated chunk.
+ */
+ DB_MUTEX fq_mutex; /* Mutex guarding file name list. */
+
+ LOGP persist; /* Persistent information. */
+
+ SH_TAILQ_HEAD(__fq1) fq; /* List of file names. */
+ int32_t fid_max; /* Max fid allocated. */
+ roff_t free_fid_stack; /* Stack of free file ids. */
+ int free_fids; /* Height of free fid stack. */
+ int free_fids_alloced; /* Number of free fid slots alloc'ed. */
+
+ /*
+ * The lsn LSN is the file offset that we're about to write and which
+ * we will return to the user.
+ */
+ DB_LSN lsn; /* LSN at current file offset. */
+
+ /*
+ * The f_lsn LSN is the LSN (returned to the user) that "owns" the
+ * first byte of the buffer. If the record associated with the LSN
+ * spans buffers, it may not reflect the physical file location of
+ * the first byte of the buffer.
+ */
+ DB_LSN f_lsn; /* LSN of first byte in the buffer. */
+ size_t b_off; /* Current offset in the buffer. */
+ u_int32_t w_off; /* Current write offset in the file. */
+ u_int32_t len; /* Length of the last record. */
+
+ /*
+ * The s_lsn LSN is the last LSN that we know is on disk, not just
+ * written, but synced. This field is protected by the flush mutex
+ * rather than by the region mutex.
+ */
+ int in_flush; /* Log flush in progress. */
+ roff_t flush_mutex_off; /* Mutex guarding flushing. */
+ DB_LSN s_lsn; /* LSN of the last sync. */
+
+ DB_LOG_STAT stat; /* Log statistics. */
+
+ /*
+ * The waiting_lsn is used by the replication system. It is the
+ * first LSN that we are holding without putting in the log, because
+ * we received one or more log records out of order. Associated with
+ * the waiting_lsn is the number of log records that we still have to
+ * receive before we decide that we should request it again.
+ */
+ DB_LSN waiting_lsn; /* First log record after a gap. */
+ DB_LSN verify_lsn; /* LSN we are waiting to verify. */
+ u_int32_t wait_recs; /* Records to wait before requesting. */
+ u_int32_t rcvd_recs; /* Records received while waiting. */
+
+ /*
+ * The ready_lsn is also used by the replication system. It is the
+ * next LSN we expect to receive. It's normally equal to "lsn",
+ * except at the beginning of a log file, at which point it's set
+ * to the LSN of the first record of the new file (after the
+ * header), rather than to 0.
+ */
+ DB_LSN ready_lsn;
+
+ /*
+ * During initialization, the log system walks forward through the
+ * last log file to find its end. If it runs into a checkpoint
+ * while it's doing so, it caches it here so that the transaction
+ * system doesn't need to walk through the file again on its
+ * initialization.
+ */
+ DB_LSN cached_ckp_lsn;
+
+ roff_t buffer_off; /* Log buffer offset in the region. */
+ u_int32_t buffer_size; /* Log buffer size. */
+
+ u_int32_t log_size; /* Log file's size. */
+ u_int32_t log_nsize; /* Next log file's size. */
+
+ u_int32_t ncommit; /* Number of txns waiting to commit. */
+
+ DB_LSN t_lsn; /* LSN of first commit */
+ SH_TAILQ_HEAD(__commit) commits;/* list of txns waiting to commit. */
+ SH_TAILQ_HEAD(__free) free_commits;/* free list of commit structs. */
+
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+#define LG_MAINT_SIZE (sizeof(roff_t) * DB_MAX_HANDLES)
+
+ roff_t maint_off; /* offset of region maintenance info */
+#endif
+};
+
+/*
+ * __db_commit structure --
+ * One of these is allocated for each transaction waiting
+ * to commit.
+ */
+struct __db_commit {
+ DB_MUTEX mutex; /* Mutex for txn to wait on. */
+ DB_LSN lsn; /* LSN of commit record. */
+ SH_TAILQ_ENTRY links; /* Either on free or waiting list. */
+
+#define DB_COMMIT_FLUSH 0x0001 /* Flush the log when you wake up. */
+ u_int32_t flags;
+};
+
+/*
+ * FNAME --
+ * File name and id.
+ */
+struct __fname {
+ SH_TAILQ_ENTRY q; /* File name queue. */
+
+ int32_t id; /* Logging file id. */
+ DBTYPE s_type; /* Saved DB type. */
+
+ roff_t name_off; /* Name offset. */
+ db_pgno_t meta_pgno; /* Page number of the meta page. */
+ u_int8_t ufid[DB_FILE_ID_LEN]; /* Unique file id. */
+
+ u_int32_t create_txnid; /*
+ * Txn ID of the DB create, stored so
+ * we can log it at register time.
+ */
+};
+
+/* File open/close register log record opcodes. */
+#define LOG_CHECKPOINT 1 /* Checkpoint: file name/id dump. */
+#define LOG_CLOSE 2 /* File close. */
+#define LOG_OPEN 3 /* File open. */
+#define LOG_RCLOSE 4 /* File close after recovery. */
+
+#define CHECK_LSN(redo, cmp, lsn, prev) \
+ DB_ASSERT(!DB_REDO(redo) || \
+ (cmp) >= 0 || IS_NOT_LOGGED_LSN(*lsn)); \
+ if (DB_REDO(redo) && (cmp) < 0 && !IS_NOT_LOGGED_LSN(*(lsn))) { \
+ __db_err(dbenv, \
+ "Log sequence error: page LSN %lu %lu; previous LSN %lu %lu", \
+ (u_long)(lsn)->file, (u_long)(lsn)->offset, \
+ (u_long)(prev)->file, (u_long)(prev)->offset); \
+ goto out; \
+ }
+
+/*
+ * Status codes indicating the validity of a log file examined by
+ * __log_valid().
+ */
+typedef enum {
+ DB_LV_INCOMPLETE,
+ DB_LV_NONEXISTENT,
+ DB_LV_NORMAL,
+ DB_LV_OLD_READABLE,
+ DB_LV_OLD_UNREADABLE
+} logfile_validity;
+
+#include "dbinc_auto/dbreg_auto.h"
+#include "dbinc_auto/dbreg_ext.h"
+#include "dbinc_auto/log_ext.h"
+#endif /* !_LOG_H_ */
diff --git a/bdb/dbinc/mp.h b/bdb/dbinc/mp.h
new file mode 100644
index 00000000000..5c805b92364
--- /dev/null
+++ b/bdb/dbinc/mp.h
@@ -0,0 +1,293 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: mp.h,v 11.44 2002/08/06 06:11:21 bostic Exp $
+ */
+
+#ifndef _DB_MP_H_
+#define _DB_MP_H_
+
+struct __bh; typedef struct __bh BH;
+struct __db_mpool_hash; typedef struct __db_mpool_hash DB_MPOOL_HASH;
+struct __db_mpreg; typedef struct __db_mpreg DB_MPREG;
+struct __mpool; typedef struct __mpool MPOOL;
+
+ /* We require at least 20KB of cache. */
+#define DB_CACHESIZE_MIN (20 * 1024)
+
+typedef enum {
+ DB_SYNC_ALLOC, /* Flush for allocation. */
+ DB_SYNC_CACHE, /* Checkpoint or flush entire cache. */
+ DB_SYNC_FILE, /* Flush file. */
+ DB_SYNC_TRICKLE /* Trickle sync. */
+} db_sync_op;
+
+/*
+ * DB_MPOOL --
+ * Per-process memory pool structure.
+ */
+struct __db_mpool {
+ /* These fields need to be protected for multi-threaded support. */
+ DB_MUTEX *mutexp; /* Structure thread lock. */
+
+ /* List of pgin/pgout routines. */
+ LIST_HEAD(__db_mpregh, __db_mpreg) dbregq;
+
+ /* List of DB_MPOOLFILE's. */
+ TAILQ_HEAD(__db_mpoolfileh, __db_mpoolfile) dbmfq;
+
+ /*
+ * The dbenv, nreg and reginfo fields are not thread protected,
+ * as they are initialized during mpool creation, and not modified
+ * again.
+ */
+ DB_ENV *dbenv; /* Enclosing environment. */
+
+ u_int32_t nreg; /* N underlying cache regions. */
+ REGINFO *reginfo; /* Underlying cache regions. */
+};
+
+/*
+ * DB_MPREG --
+ * DB_MPOOL registry of pgin/pgout functions.
+ */
+struct __db_mpreg {
+ LIST_ENTRY(__db_mpreg) q; /* Linked list. */
+
+ int32_t ftype; /* File type. */
+ /* Pgin, pgout routines. */
+ int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *));
+ int (*pgout) __P((DB_ENV *, db_pgno_t, void *, DBT *));
+};
+
+/*
+ * NCACHE --
+ * Select a cache based on the file and the page number. Assumes accesses
+ * are uniform across pages, which is probably OK. What we really want to
+ * avoid is anything that puts all pages from any single file in the same
+ * cache, as we expect that file access will be bursty, and to avoid
+ * putting all page number N pages in the same cache as we expect access
+ * to the metapages (page 0) and the root of a btree (page 1) to be much
+ * more frequent than a random data page.
+ */
+#define NCACHE(mp, mf_offset, pgno) \
+ (((pgno) ^ ((mf_offset) >> 3)) % ((MPOOL *)mp)->nreg)
+
+/*
+ * NBUCKET --
+ * We make the assumption that early pages of the file are more likely
+ * to be retrieved than the later pages, which means the top bits will
+ * be more interesting for hashing as they're less likely to collide.
+ * That said, as 512 8K pages represents a 4MB file, so only reasonably
+ * large files will have page numbers with any other than the bottom 9
+ * bits set. We XOR in the MPOOL offset of the MPOOLFILE that backs the
+ * page, since that should also be unique for the page. We don't want
+ * to do anything very fancy -- speed is more important to us than using
+ * good hashing.
+ */
+#define NBUCKET(mc, mf_offset, pgno) \
+ (((pgno) ^ ((mf_offset) << 9)) % (mc)->htab_buckets)
+
+/*
+ * MPOOL --
+ * Shared memory pool region.
+ */
+struct __mpool {
+ /*
+ * The memory pool can be broken up into individual pieces/files.
+ * Not what we would have liked, but on Solaris you can allocate
+ * only a little more than 2GB of memory in a contiguous chunk,
+ * and I expect to see more systems with similar issues.
+ *
+ * While this structure is duplicated in each piece of the cache,
+ * the first of these pieces/files describes the entire pool, the
+ * second only describe a piece of the cache.
+ */
+
+ /*
+ * The lsn field and list of underlying MPOOLFILEs are thread protected
+ * by the region lock.
+ */
+ DB_LSN lsn; /* Maximum checkpoint LSN. */
+
+ SH_TAILQ_HEAD(__mpfq) mpfq; /* List of MPOOLFILEs. */
+
+ /*
+ * The nreg, regids and maint_off fields are not thread protected,
+ * as they are initialized during mpool creation, and not modified
+ * again.
+ */
+ u_int32_t nreg; /* Number of underlying REGIONS. */
+ roff_t regids; /* Array of underlying REGION Ids. */
+
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ roff_t maint_off; /* Maintenance information offset */
+#endif
+
+ /*
+ * The following structure fields only describe the per-cache portion
+ * of the region.
+ *
+ * The htab and htab_buckets fields are not thread protected as they
+ * are initialized during mpool creation, and not modified again.
+ *
+ * The last_checked and lru_count fields are thread protected by
+ * the region lock.
+ */
+ int htab_buckets; /* Number of hash table entries. */
+ roff_t htab; /* Hash table offset. */
+ u_int32_t last_checked; /* Last bucket checked for free. */
+ u_int32_t lru_count; /* Counter for buffer LRU */
+
+ /*
+ * The stat fields are generally not thread protected, and cannot be
+ * trusted. Note that st_pages is an exception, and is always updated
+ * inside a region lock (although it is sometimes read outside of the
+ * region lock).
+ */
+ DB_MPOOL_STAT stat; /* Per-cache mpool statistics. */
+};
+
+struct __db_mpool_hash {
+ DB_MUTEX hash_mutex; /* Per-bucket mutex. */
+
+ DB_HASHTAB hash_bucket; /* Head of bucket. */
+
+ u_int32_t hash_page_dirty;/* Count of dirty pages. */
+ u_int32_t hash_priority; /* Minimum priority of bucket buffer. */
+};
+
+/*
+ * The base mpool priority is 1/4th of the name space, or just under 2^30.
+ * When the LRU counter wraps, we shift everybody down to a base-relative
+ * value.
+ */
+#define MPOOL_BASE_DECREMENT (UINT32_T_MAX - (UINT32_T_MAX / 4))
+
+/*
+ * Mpool priorities from low to high. Defined in terms of fractions of the
+ * buffers in the pool.
+ */
+#define MPOOL_PRI_VERY_LOW -1 /* Dead duck. Check and set to 0. */
+#define MPOOL_PRI_LOW -2 /* Low. */
+#define MPOOL_PRI_DEFAULT 0 /* No adjustment -- special case.*/
+#define MPOOL_PRI_HIGH 10 /* With the dirty buffers. */
+#define MPOOL_PRI_DIRTY 10 /* Dirty gets a 10% boost. */
+#define MPOOL_PRI_VERY_HIGH 1 /* Add number of buffers in pool. */
+
+/*
+ * MPOOLFILE_IGNORE --
+ * Discard an MPOOLFILE and any buffers it references: update the flags
+ * so we never try to write buffers associated with the file, nor can we
+ * find it when looking for files to join. In addition, clear the ftype
+ * field, there's no reason to post-process pages, they can be discarded
+ * by any thread.
+ *
+ * Expects the MPOOLFILE mutex to be held.
+ */
+#define MPOOLFILE_IGNORE(mfp) { \
+ (mfp)->ftype = 0; \
+ F_SET(mfp, MP_DEADFILE); \
+}
+
+/*
+ * MPOOLFILE --
+ * Shared DB_MPOOLFILE information.
+ */
+struct __mpoolfile {
+ DB_MUTEX mutex;
+
+ /* Protected by MPOOLFILE mutex. */
+ u_int32_t mpf_cnt; /* Ref count: DB_MPOOLFILEs. */
+ u_int32_t block_cnt; /* Ref count: blocks in cache. */
+
+ roff_t path_off; /* File name location. */
+
+ /* Protected by mpool cache 0 region lock. */
+ SH_TAILQ_ENTRY q; /* List of MPOOLFILEs */
+ db_pgno_t last_pgno; /* Last page in the file. */
+ db_pgno_t orig_last_pgno; /* Original last page in the file. */
+
+ /*
+ * None of the following fields are thread protected.
+ *
+ * There are potential races with the ftype field because it's read
+ * without holding a lock. However, it has to be set before adding
+ * any buffers to the cache that depend on it being set, so there
+ * would need to be incorrect operation ordering to have a problem.
+ *
+ * There are potential races with the priority field because it's read
+ * without holding a lock. However, a collision is unlikely and if it
+ * happens is of little consequence.
+ *
+ * We do not protect the statistics in "stat" because of the cost of
+ * the mutex in the get/put routines. There is a chance that a count
+ * will get lost.
+ *
+ * The remaining fields are initialized at open and never subsequently
+ * modified, except for the MP_DEADFILE, which is only set and never
+ * unset. (If there was more than one flag that was subsequently set,
+ * there might be a race, but with a single flag there can't be.)
+ */
+ int32_t ftype; /* File type. */
+
+ int32_t priority; /* Priority when unpinning buffer. */
+
+ DB_MPOOL_FSTAT stat; /* Per-file mpool statistics. */
+
+ int32_t lsn_off; /* Page's LSN offset. */
+ u_int32_t clear_len; /* Bytes to clear on page create. */
+
+ roff_t fileid_off; /* File ID string location. */
+
+ roff_t pgcookie_len; /* Pgin/pgout cookie length. */
+ roff_t pgcookie_off; /* Pgin/pgout cookie location. */
+
+#define MP_CAN_MMAP 0x01 /* If the file can be mmap'd. */
+#define MP_DEADFILE 0x02 /* Dirty pages can simply be trashed. */
+#define MP_DIRECT 0x04 /* No OS buffering. */
+#define MP_EXTENT 0x08 /* Extent file. */
+#define MP_TEMP 0x10 /* Backing file is a temporary. */
+#define MP_UNLINK 0x20 /* Unlink file on last close. */
+ u_int32_t flags;
+};
+
+/*
+ * BH --
+ * Buffer header.
+ */
+struct __bh {
+ DB_MUTEX mutex; /* Buffer thread/process lock. */
+
+ u_int16_t ref; /* Reference count. */
+ u_int16_t ref_sync; /* Sync wait-for reference count. */
+
+#define BH_CALLPGIN 0x001 /* Convert the page before use. */
+#define BH_DIRTY 0x002 /* Page was modified. */
+#define BH_DIRTY_CREATE 0x004 /* Page created, must be written. */
+#define BH_DISCARD 0x008 /* Page is useless. */
+#define BH_LOCKED 0x010 /* Page is locked (I/O in progress). */
+#define BH_TRASH 0x020 /* Page is garbage. */
+ u_int16_t flags;
+
+ u_int32_t priority; /* LRU priority. */
+ SH_TAILQ_ENTRY hq; /* MPOOL hash bucket queue. */
+
+ db_pgno_t pgno; /* Underlying MPOOLFILE page number. */
+ roff_t mf_offset; /* Associated MPOOLFILE offset. */
+
+ /*
+ * !!!
+ * This array must be at least size_t aligned -- the DB access methods
+ * put PAGE and other structures into it, and then access them directly.
+ * (We guarantee size_t alignment to applications in the documentation,
+ * too.)
+ */
+ u_int8_t buf[1]; /* Variable length data. */
+};
+
+#include "dbinc_auto/mp_ext.h"
+#endif /* !_DB_MP_H_ */
diff --git a/bdb/dbinc/mutex.h b/bdb/dbinc/mutex.h
new file mode 100644
index 00000000000..41bb1b4bb59
--- /dev/null
+++ b/bdb/dbinc/mutex.h
@@ -0,0 +1,879 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: mutex.h,v 11.71 2002/09/10 01:36:48 bostic Exp $
+ */
+
+#ifndef _DB_MUTEX_H_
+#define _DB_MUTEX_H_
+
+/*
+ * Some of the Berkeley DB ports require single-threading at various
+ * places in the code. In those cases, these #defines will be set.
+ */
+#define DB_BEGIN_SINGLE_THREAD
+#define DB_END_SINGLE_THREAD
+
+/*********************************************************************
+ * POSIX.1 pthreads interface.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_PTHREADS
+#include <pthread.h>
+
+#define MUTEX_FIELDS \
+ pthread_mutex_t mutex; /* Mutex. */ \
+ pthread_cond_t cond; /* Condition variable. */
+#endif
+
+/*********************************************************************
+ * Solaris lwp threads interface.
+ *
+ * !!!
+ * We use LWP mutexes on Solaris instead of UI or POSIX mutexes (both of
+ * which are available), for two reasons. First, the Solaris C library
+ * includes versions of the both UI and POSIX thread mutex interfaces, but
+ * they are broken in that they don't support inter-process locking, and
+ * there's no way to detect it, e.g., calls to configure the mutexes for
+ * inter-process locking succeed without error. So, we use LWP mutexes so
+ * that we don't fail in fairly undetectable ways because the application
+ * wasn't linked with the appropriate threads library. Second, there were
+ * bugs in SunOS 5.7 (Solaris 7) where if an application loaded the C library
+ * before loading the libthread/libpthread threads libraries (e.g., by using
+ * dlopen to load the DB library), the pwrite64 interface would be translated
+ * into a call to pwrite and DB would drop core.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_SOLARIS_LWP
+/*
+ * XXX
+ * Don't change <synch.h> to <sys/lwp.h> -- although lwp.h is listed in the
+ * Solaris manual page as the correct include to use, it causes the Solaris
+ * compiler on SunOS 2.6 to fail.
+ */
+#include <synch.h>
+
+#define MUTEX_FIELDS \
+ lwp_mutex_t mutex; /* Mutex. */ \
+ lwp_cond_t cond; /* Condition variable. */
+#endif
+
+/*********************************************************************
+ * Solaris/Unixware threads interface.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_UI_THREADS
+#include <thread.h>
+#include <synch.h>
+
+#define MUTEX_FIELDS \
+ mutex_t mutex; /* Mutex. */ \
+ cond_t cond; /* Condition variable. */
+#endif
+
+/*********************************************************************
+ * AIX C library functions.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_AIX_CHECK_LOCK
+#include <sys/atomic_op.h>
+typedef int tsl_t;
+#define MUTEX_ALIGN sizeof(int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) 0
+#define MUTEX_SET(x) (!_check_lock(x, 0, 1))
+#define MUTEX_UNSET(x) _clear_lock(x, 0)
+#endif
+#endif
+
+/*********************************************************************
+ * General C library functions (msemaphore).
+ *
+ * !!!
+ * Check for HPPA as a special case, because it requires unusual alignment,
+ * and doesn't support semaphores in malloc(3) or shmget(2) memory.
+ *
+ * !!!
+ * Do not remove the MSEM_IF_NOWAIT flag. The problem is that if a single
+ * process makes two msem_lock() calls in a row, the second one returns an
+ * error. We depend on the fact that we can lock against ourselves in the
+ * locking subsystem, where we set up a mutex so that we can block ourselves.
+ * Tested on OSF1 v4.0.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_HPPA_MSEM_INIT
+#define MUTEX_NO_MALLOC_LOCKS
+#define MUTEX_NO_SHMGET_LOCKS
+
+#define MUTEX_ALIGN 16
+#endif
+
+#if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
+#include <sys/mman.h>
+typedef msemaphore tsl_t;
+
+#ifndef MUTEX_ALIGN
+#define MUTEX_ALIGN sizeof(int)
+#endif
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) (msem_init(x, MSEM_UNLOCKED) <= (msemaphore *)0)
+#define MUTEX_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT))
+#define MUTEX_UNSET(x) msem_unlock(x, 0)
+#endif
+#endif
+
+/*********************************************************************
+ * Plan 9 library functions.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_PLAN9
+typedef Lock tsl_t;
+
+#define MUTEX_ALIGN sizeof(int)
+
+#define MUTEX_INIT(x) (memset(x, 0, sizeof(Lock)), 0)
+#define MUTEX_SET(x) canlock(x)
+#define MUTEX_UNSET(x) unlock(x)
+#endif
+
+/*********************************************************************
+ * Reliant UNIX C library functions.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_RELIANTUNIX_INITSPIN
+#include <ulocks.h>
+typedef spinlock_t tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) (initspin(x, 1), 0)
+#define MUTEX_SET(x) (cspinlock(x) == 0)
+#define MUTEX_UNSET(x) spinunlock(x)
+#endif
+#endif
+
+/*********************************************************************
+ * General C library functions (POSIX 1003.1 sema_XXX).
+ *
+ * !!!
+ * Never selected by autoconfig in this release (semaphore calls are known
+ * to not work in Solaris 5.5).
+ *********************************************************************/
+#ifdef HAVE_MUTEX_SEMA_INIT
+#include <synch.h>
+typedef sema_t tsl_t;
+#define MUTEX_ALIGN sizeof(int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_DESTROY(x) sema_destroy(x)
+#define MUTEX_INIT(x) (sema_init(x, 1, USYNC_PROCESS, NULL) != 0)
+#define MUTEX_SET(x) (sema_wait(x) == 0)
+#define MUTEX_UNSET(x) sema_post(x)
+#endif
+#endif
+
+/*********************************************************************
+ * SGI C library functions.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_SGI_INIT_LOCK
+#include <abi_mutex.h>
+typedef abilock_t tsl_t;
+#define MUTEX_ALIGN sizeof(int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) (init_lock(x) != 0)
+#define MUTEX_SET(x) (!acquire_lock(x))
+#define MUTEX_UNSET(x) release_lock(x)
+#endif
+#endif
+
+/*********************************************************************
+ * Solaris C library functions.
+ *
+ * !!!
+ * These are undocumented functions, but they're the only ones that work
+ * correctly as far as we know.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY
+#include <sys/machlock.h>
+typedef lock_t tsl_t;
+#define MUTEX_ALIGN sizeof(int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) 0
+#define MUTEX_SET(x) _lock_try(x)
+#define MUTEX_UNSET(x) _lock_clear(x)
+#endif
+#endif
+
+/*********************************************************************
+ * VMS.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_VMS
+#include <sys/mman.h>;
+#include <builtins.h>
+typedef unsigned char tsl_t;
+#define MUTEX_ALIGN sizeof(unsigned int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#ifdef __ALPHA
+#define MUTEX_SET(tsl) (!__TESTBITSSI(tsl, 0))
+#else /* __VAX */
+#define MUTEX_SET(tsl) (!(int)_BBSSI(0, tsl))
+#endif
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * VxWorks
+ * Use basic binary semaphores in VxWorks, as we currently do not need
+ * any special features. We do need the ability to single-thread the
+ * entire system, however, because VxWorks doesn't support the open(2)
+ * flag O_EXCL, the mechanism we normally use to single thread access
+ * when we're first looking for a DB environment.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_VXWORKS
+#include "taskLib.h"
+typedef SEM_ID tsl_t;
+#define MUTEX_ALIGN sizeof(unsigned int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_SET(tsl) (semTake((*tsl), WAIT_FOREVER) == OK)
+#define MUTEX_UNSET(tsl) (semGive((*tsl)))
+#define MUTEX_INIT(tsl) \
+ ((*(tsl) = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL)
+#define MUTEX_DESTROY(tsl) semDelete(*tsl)
+#endif
+
+/*
+ * Use the taskLock() mutex to eliminate a race where two tasks are
+ * trying to initialize the global lock at the same time.
+ */
+#undef DB_BEGIN_SINGLE_THREAD
+#define DB_BEGIN_SINGLE_THREAD \
+do { \
+ if (DB_GLOBAL(db_global_init)) \
+ (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \
+ else { \
+ taskLock(); \
+ if (DB_GLOBAL(db_global_init)) { \
+ taskUnlock(); \
+ (void)semTake(DB_GLOBAL(db_global_lock), \
+ WAIT_FOREVER); \
+ continue; \
+ } \
+ DB_GLOBAL(db_global_lock) = \
+ semBCreate(SEM_Q_FIFO, SEM_EMPTY); \
+ if (DB_GLOBAL(db_global_lock) != NULL) \
+ DB_GLOBAL(db_global_init) = 1; \
+ taskUnlock(); \
+ } \
+} while (DB_GLOBAL(db_global_init) == 0)
+#undef DB_END_SINGLE_THREAD
+#define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock))
+#endif
+
+/*********************************************************************
+ * Win16
+ *
+ * Win16 spinlocks are simple because we cannot possibly be preempted.
+ *
+ * !!!
+ * We should simplify this by always returning a no-need-to-lock lock
+ * when we initialize the mutex.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_WIN16
+typedef unsigned int tsl_t;
+#define MUTEX_ALIGN sizeof(unsigned int)
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) 0
+#define MUTEX_SET(tsl) (*(tsl) = 1)
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#endif
+#endif
+
+/*********************************************************************
+ * Win32
+ *********************************************************************/
+#ifdef HAVE_MUTEX_WIN32
+#define MUTEX_FIELDS \
+ LONG tas; \
+ LONG nwaiters; \
+ union { \
+ HANDLE event; /* Windows event HANDLE for wakeups */ \
+ u_int32_t id; /* ID used for shared mutexes */ \
+ } /* anonymous */;
+
+#if defined(LOAD_ACTUAL_MUTEX_CODE)
+#define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1))
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * 68K/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_68K_GCC_ASSEMBLY
+typedef unsigned char tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * For gcc/68K, 0 is clear, 1 is set.
+ */
+#define MUTEX_SET(tsl) ({ \
+ register tsl_t *__l = (tsl); \
+ int __r; \
+ asm volatile("tas %1; \n \
+ seq %0" \
+ : "=dm" (__r), "=m" (*__l) \
+ : "1" (*__l) \
+ ); \
+ __r & 1; \
+})
+
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * ALPHA/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
+typedef u_int32_t tsl_t;
+#define MUTEX_ALIGN 4
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * For gcc/alpha. Should return 0 if could not acquire the lock, 1 if
+ * lock was acquired properly.
+ */
+#ifdef __GNUC__
+static inline int
+MUTEX_SET(tsl_t *tsl) {
+ register tsl_t *__l = tsl;
+ register tsl_t __r;
+ asm volatile(
+ "1: ldl_l %0,%2\n"
+ " blbs %0,2f\n"
+ " or $31,1,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,3f\n"
+ " mb\n"
+ " br 3f\n"
+ "2: xor %0,%0\n"
+ "3:"
+ : "=&r"(__r), "=m"(*__l) : "1"(*__l) : "memory");
+ return __r;
+}
+
+/*
+ * Unset mutex. Judging by Alpha Architecture Handbook, the mb instruction
+ * might be necessary before unlocking
+ */
+static inline int
+MUTEX_UNSET(tsl_t *tsl) {
+ asm volatile(" mb\n");
+ return *tsl = 0;
+}
+#endif
+
+#ifdef __DECC
+#include <alpha/builtins.h>
+#define MUTEX_SET(tsl) (__LOCK_LONG_RETRY((tsl), 1) != 0)
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#endif
+
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * ARM/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_ARM_GCC_ASSEMBLY
+typedef unsigned char tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * For arm/gcc, 0 is clear, 1 is set.
+ */
+#define MUTEX_SET(tsl) ({ \
+ int __r; \
+ asm volatile("swpb %0, %1, [%2]" \
+ : "=r" (__r) \
+ : "0" (1), "r" (tsl) \
+ : "memory" \
+ ); \
+ __r & 1; \
+})
+
+#define MUTEX_UNSET(tsl) (*(volatile tsl_t *)(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * HPPA/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
+typedef u_int32_t tsl_t;
+#define MUTEX_ALIGN 16
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * The PA-RISC has a "load and clear" instead of a "test and set" instruction.
+ * The 32-bit word used by that instruction must be 16-byte aligned. We could
+ * use the "aligned" attribute in GCC but that doesn't work for stack variables.
+ */
+#define MUTEX_SET(tsl) ({ \
+ register tsl_t *__l = (tsl); \
+ int __r; \
+ asm volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l)); \
+ __r & 1; \
+})
+
+#define MUTEX_UNSET(tsl) (*(tsl) = -1)
+#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0)
+#endif
+#endif
+
+/*********************************************************************
+ * IA64/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY
+typedef unsigned char tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * For gcc/ia64, 0 is clear, 1 is set.
+ */
+#define MUTEX_SET(tsl) ({ \
+ register tsl_t *__l = (tsl); \
+ long __r; \
+ asm volatile("xchg1 %0=%1,%3" : "=r"(__r), "=m"(*__l) : "1"(*__l), "r"(1));\
+ __r ^ 1; \
+})
+
+/*
+ * Store through a "volatile" pointer so we get a store with "release"
+ * semantics.
+ */
+#define MUTEX_UNSET(tsl) (*(volatile unsigned char *)(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * PowerPC/gcc assembly.
+ *********************************************************************/
+#if defined(HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY) || \
+ (HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY)
+typedef u_int32_t tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * The PowerPC does a sort of pseudo-atomic locking. You set up a
+ * 'reservation' on a chunk of memory containing a mutex by loading the
+ * mutex value with LWARX. If the mutex has an 'unlocked' (arbitrary)
+ * value, you then try storing into it with STWCX. If no other process or
+ * thread broke your 'reservation' by modifying the memory containing the
+ * mutex, then the STCWX succeeds; otherwise it fails and you try to get
+ * a reservation again.
+ *
+ * While mutexes are explicitly 4 bytes, a 'reservation' applies to an
+ * entire cache line, normally 32 bytes, aligned naturally. If the mutex
+ * lives near data that gets changed a lot, there's a chance that you'll
+ * see more broken reservations than you might otherwise. The only
+ * situation in which this might be a problem is if one processor is
+ * beating on a variable in the same cache block as the mutex while another
+ * processor tries to acquire the mutex. That's bad news regardless
+ * because of the way it bashes caches, but if you can't guarantee that a
+ * mutex will reside in a relatively quiescent cache line, you might
+ * consider padding the mutex to force it to live in a cache line by
+ * itself. No, you aren't guaranteed that cache lines are 32 bytes. Some
+ * embedded processors use 16-byte cache lines, while some 64-bit
+ * processors use 128-bit cache lines. But assuming a 32-byte cache line
+ * won't get you into trouble for now.
+ *
+ * If mutex locking is a bottleneck, then you can speed it up by adding a
+ * regular LWZ load before the LWARX load, so that you can test for the
+ * common case of a locked mutex without wasting cycles making a reservation.
+ *
+ * 'set' mutexes have the value 1, like on Intel; the returned value from
+ * MUTEX_SET() is 1 if the mutex previously had its low bit clear, 0 otherwise.
+ *
+ * Mutexes on Mac OS X work the same way as the standard PowerPC version, but
+ * the assembler syntax is subtly different -- the standard PowerPC version
+ * assembles but doesn't work correctly. This version makes (unnecessary?)
+ * use of a stupid linker trick: __db_mutex_tas_dummy is never called, but the
+ * ___db_mutex_set label is used as a function name.
+ */
+#ifdef HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY
+extern int __db_mutex_set __P((volatile tsl_t *));
+void
+__db_mutex_tas_dummy()
+{
+ __asm__ __volatile__(" \n\
+ .globl ___db_mutex_set \n\
+___db_mutex_set: \n\
+ lwarx r5,0,r3 \n\
+ cmpwi r5,0 \n\
+ bne fail \n\
+ addi r5,r5,1 \n\
+ stwcx. r5,0,r3 \n\
+ beq success \n\
+fail: \n\
+ li r3,0 \n\
+ blr \n\
+success: \n\
+ li r3,1 \n\
+ blr");
+}
+#define MUTEX_SET(tsl) __db_mutex_set(tsl)
+#endif
+#ifdef HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY
+#define MUTEX_SET(tsl) ({ \
+ int __one = 1; \
+ int __r; \
+ tsl_t *__l = (tsl); \
+ asm volatile (" \
+0: \
+ lwarx %0,0,%1; \
+ cmpwi %0,0; \
+ bne 1f; \
+ stwcx. %2,0,%1; \
+ bne- 0b; \
+1:" \
+ : "=&r" (__r) \
+ : "r" (__l), "r" (__one)); \
+ !(__r & 1); \
+})
+#endif
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * S/390 32-bit assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_S390_GCC_ASSEMBLY
+typedef int tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * For gcc/S390, 0 is clear, 1 is set.
+ */
+static inline int
+MUTEX_SET(tsl_t *tsl) { \
+ register tsl_t *__l = (tsl); \
+ int __r; \
+ asm volatile( \
+ " la 1,%1\n" \
+ " lhi 0,1\n" \
+ " l %0,%1\n" \
+ "0: cs %0,0,0(1)\n" \
+ " jl 0b" \
+ : "=&d" (__r), "+m" (*__l) \
+ : : "0", "1", "cc"); \
+ return !__r; \
+}
+
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * SCO/cc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY
+typedef unsigned char tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * UnixWare has threads in libthread, but OpenServer doesn't (yet).
+ *
+ * For cc/x86, 0 is clear, 1 is set.
+ */
+
+#if defined(__USLC__)
+asm int
+_tsl_set(void *tsl)
+{
+%mem tsl
+ movl tsl, %ecx
+ movl $1, %eax
+ lock
+ xchgb (%ecx),%al
+ xorl $1,%eax
+}
+#endif
+
+#define MUTEX_SET(tsl) _tsl_set(tsl)
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * Sparc/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_SPARC_GCC_ASSEMBLY
+typedef unsigned char tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ *
+ * The ldstub instruction takes the location specified by its first argument
+ * (a register containing a memory address) and loads its contents into its
+ * second argument (a register) and atomically sets the contents the location
+ * specified by its first argument to a byte of 1s. (The value in the second
+ * argument is never read, but only overwritten.)
+ *
+ * The stbar is needed for v8, and is implemented as membar #sync on v9,
+ * so is functional there as well. For v7, stbar may generate an illegal
+ * instruction and we have no way to tell what we're running on. Some
+ * operating systems notice and skip this instruction in the fault handler.
+ *
+ * For gcc/sparc, 0 is clear, 1 is set.
+ */
+#define MUTEX_SET(tsl) ({ \
+ register tsl_t *__l = (tsl); \
+ register tsl_t __r; \
+ __asm__ volatile \
+ ("ldstub [%1],%0; stbar" \
+ : "=r"( __r) : "r" (__l)); \
+ !__r; \
+})
+
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * UTS/cc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_UTS_CC_ASSEMBLY
+typedef int tsl_t;
+
+#define MUTEX_ALIGN sizeof(int)
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#define MUTEX_INIT(x) 0
+#define MUTEX_SET(x) (!uts_lock(x, 1))
+#define MUTEX_UNSET(x) (*(x) = 0)
+#endif
+#endif
+
+/*********************************************************************
+ * x86/gcc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_X86_GCC_ASSEMBLY
+typedef unsigned char tsl_t;
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * For gcc/x86, 0 is clear, 1 is set.
+ */
+#define MUTEX_SET(tsl) ({ \
+ register tsl_t *__l = (tsl); \
+ int __r; \
+ asm volatile("movl $1,%%eax; lock; xchgb %1,%%al; xorl $1,%%eax"\
+ : "=&a" (__r), "=m" (*__l) \
+ : "1" (*__l) \
+ ); \
+ __r & 1; \
+})
+
+#define MUTEX_UNSET(tsl) (*(tsl) = 0)
+#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*
+ * Mutex alignment defaults to one byte.
+ *
+ * !!!
+ * Various systems require different alignments for mutexes (the worst we've
+ * seen so far is 16-bytes on some HP architectures). Malloc(3) is assumed
+ * to return reasonable alignment, all other mutex users must ensure proper
+ * alignment locally.
+ */
+#ifndef MUTEX_ALIGN
+#define MUTEX_ALIGN 1
+#endif
+
+/*
+ * Mutex destruction defaults to a no-op.
+ */
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+#ifndef MUTEX_DESTROY
+#define MUTEX_DESTROY(x)
+#endif
+#endif
+
+/*
+ * !!!
+ * These defines are separated into the u_int8_t flags stored in the
+ * mutex below, and the 32 bit flags passed to __db_mutex_setup.
+ * But they must co-exist and not overlap. Flags to __db_mutex_setup are:
+ *
+ * MUTEX_ALLOC - Use when the mutex to initialize needs to be allocated.
+ * The 'ptr' arg to __db_mutex_setup should be a DB_MUTEX ** whenever
+ * you use this flag. If this flag is not set, the 'ptr' arg is
+ * a DB_MUTEX *.
+ * MUTEX_NO_RECORD - Explicitly do not record the mutex in the region.
+ * Otherwise the mutex will be recorded by default. If you set
+ * this you need to understand why you don't need it recorded. The
+ * *only* ones not recorded are those that are part of region structures
+ * that only get destroyed when the regions are destroyed.
+ * MUTEX_NO_RLOCK - Explicitly do not lock the given region otherwise
+ * the region will be locked by default.
+ * MUTEX_SELF_BLOCK - Set if self blocking mutex.
+ * MUTEX_THREAD - Set if mutex is a thread-only mutex.
+ */
+#define MUTEX_IGNORE 0x001 /* Ignore, no lock required. */
+#define MUTEX_INITED 0x002 /* Mutex is successfully initialized */
+#define MUTEX_MPOOL 0x004 /* Allocated from mpool. */
+#define MUTEX_SELF_BLOCK 0x008 /* Must block self. */
+/* Flags only, may be larger than 0xff. */
+#define MUTEX_ALLOC 0x00000100 /* Allocate and init a mutex */
+#define MUTEX_NO_RECORD 0x00000200 /* Do not record lock */
+#define MUTEX_NO_RLOCK 0x00000400 /* Do not acquire region lock */
+#define MUTEX_THREAD 0x00000800 /* Thread-only mutex. */
+
+/* Mutex. */
+struct __mutex_t {
+#ifdef HAVE_MUTEX_THREADS
+#ifdef MUTEX_FIELDS
+ MUTEX_FIELDS
+#else
+ tsl_t tas; /* Test and set. */
+#endif
+ u_int32_t spins; /* Spins before block. */
+ u_int32_t locked; /* !0 if locked. */
+#else
+ u_int32_t off; /* Byte offset to lock. */
+ u_int32_t pid; /* Lock holder: 0 or process pid. */
+#endif
+ u_int32_t mutex_set_wait; /* Granted after wait. */
+ u_int32_t mutex_set_nowait; /* Granted without waiting. */
+ u_int32_t mutex_set_spin; /* Granted without spinning. */
+ u_int32_t mutex_set_spins; /* Total number of spins. */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ roff_t reg_off; /* Shared lock info offset. */
+#endif
+
+ u_int8_t flags; /* MUTEX_XXX */
+};
+
+/* Redirect calls to the correct functions. */
+#ifdef HAVE_MUTEX_THREADS
+#if defined(HAVE_MUTEX_PTHREADS) || \
+ defined(HAVE_MUTEX_SOLARIS_LWP) || \
+ defined(HAVE_MUTEX_UI_THREADS)
+#define __db_mutex_init_int(a, b, c, d) __db_pthread_mutex_init(a, b, d)
+#define __db_mutex_lock(a, b) __db_pthread_mutex_lock(a, b)
+#define __db_mutex_unlock(a, b) __db_pthread_mutex_unlock(a, b)
+#define __db_mutex_destroy(a) __db_pthread_mutex_destroy(a)
+#elif defined(HAVE_MUTEX_WIN32)
+#define __db_mutex_init_int(a, b, c, d) __db_win32_mutex_init(a, b, d)
+#define __db_mutex_lock(a, b) __db_win32_mutex_lock(a, b)
+#define __db_mutex_unlock(a, b) __db_win32_mutex_unlock(a, b)
+#define __db_mutex_destroy(a) __db_win32_mutex_destroy(a)
+#else
+#define __db_mutex_init_int(a, b, c, d) __db_tas_mutex_init(a, b, d)
+#define __db_mutex_lock(a, b) __db_tas_mutex_lock(a, b)
+#define __db_mutex_unlock(a, b) __db_tas_mutex_unlock(a, b)
+#define __db_mutex_destroy(a) __db_tas_mutex_destroy(a)
+#endif
+#else
+#define __db_mutex_init_int(a, b, c, d) __db_fcntl_mutex_init(a, b, c)
+#define __db_mutex_lock(a, b) __db_fcntl_mutex_lock(a, b)
+#define __db_mutex_unlock(a, b) __db_fcntl_mutex_unlock(a, b)
+#define __db_mutex_destroy(a) __db_fcntl_mutex_destroy(a)
+#endif
+
+/* Redirect system resource calls to correct functions */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+#define __db_maintinit(a, b, c) __db_shreg_maintinit(a, b, c)
+#define __db_shlocks_clear(a, b, c) __db_shreg_locks_clear(a, b, c)
+#define __db_shlocks_destroy(a, b) __db_shreg_locks_destroy(a, b)
+#define __db_mutex_init(a, b, c, d, e, f) \
+ __db_shreg_mutex_init(a, b, c, d, e, f)
+#else
+#define __db_maintinit(a, b, c)
+#define __db_shlocks_clear(a, b, c)
+#define __db_shlocks_destroy(a, b)
+#define __db_mutex_init(a, b, c, d, e, f) __db_mutex_init_int(a, b, c, d)
+#endif
+
+/*
+ * Lock/unlock a mutex. If the mutex was marked as uninteresting, the thread
+ * of control can proceed without it.
+ *
+ * If the lock is for threads-only, then it was optionally not allocated and
+ * file handles aren't necessary, as threaded applications aren't supported by
+ * fcntl(2) locking.
+ */
+#ifdef DIAGNOSTIC
+ /*
+ * XXX
+ * We want to switch threads as often as possible. Yield every time
+ * we get a mutex to ensure contention.
+ */
+#define MUTEX_LOCK(dbenv, mp) \
+ if (!F_ISSET((mp), MUTEX_IGNORE)) \
+ DB_ASSERT(__db_mutex_lock(dbenv, mp) == 0); \
+ if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) \
+ __os_yield(NULL, 1);
+#else
+#define MUTEX_LOCK(dbenv, mp) \
+ if (!F_ISSET((mp), MUTEX_IGNORE)) \
+ (void)__db_mutex_lock(dbenv, mp);
+#endif
+#define MUTEX_UNLOCK(dbenv, mp) \
+ if (!F_ISSET((mp), MUTEX_IGNORE)) \
+ (void)__db_mutex_unlock(dbenv, mp);
+#define MUTEX_THREAD_LOCK(dbenv, mp) \
+ if (mp != NULL) \
+ MUTEX_LOCK(dbenv, mp)
+#define MUTEX_THREAD_UNLOCK(dbenv, mp) \
+ if (mp != NULL) \
+ MUTEX_UNLOCK(dbenv, mp)
+
+/*
+ * We use a single file descriptor for fcntl(2) locking, and (generally) the
+ * object's offset in a shared region as the byte that we're locking. So,
+ * there's a (remote) possibility that two objects might have the same offsets
+ * such that the locks could conflict, resulting in deadlock. To avoid this
+ * possibility, we offset the region offset by a small integer value, using a
+ * different offset for each subsystem's locks. Since all region objects are
+ * suitably aligned, the offset guarantees that we don't collide with another
+ * region's objects.
+ */
+#define DB_FCNTL_OFF_GEN 0 /* Everything else. */
+#define DB_FCNTL_OFF_LOCK 1 /* Lock subsystem offset. */
+#define DB_FCNTL_OFF_MPOOL 2 /* Mpool subsystem offset. */
+
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+/*
+ * When the underlying mutexes require library (most likely heap) or system
+ * resources, we have to clean up when we discard mutexes (for the library
+ * resources) and both when discarding mutexes and after application failure
+ * (for the mutexes requiring system resources). This violates the rule that
+ * we never look at a shared region after application failure, but we've no
+ * other choice. In those cases, the #define HAVE_MUTEX_SYSTEM_RESOURCES is
+ * set.
+ *
+ * To support mutex release after application failure, allocate thread-handle
+ * mutexes in shared memory instead of in the heap. The number of slots we
+ * allocate for this purpose isn't configurable, but this tends to be an issue
+ * only on embedded systems where we don't expect large server applications.
+ */
+#define DB_MAX_HANDLES 100 /* Mutex slots for handles. */
+#endif
+#endif /* !_DB_MUTEX_H_ */
diff --git a/bdb/dbinc/os.h b/bdb/dbinc/os.h
new file mode 100644
index 00000000000..01ca0ac470d
--- /dev/null
+++ b/bdb/dbinc/os.h
@@ -0,0 +1,54 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: os.h,v 11.14 2002/03/27 04:34:55 bostic Exp $
+ */
+
+#ifndef _DB_OS_H_
+#define _DB_OS_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* DB filehandle. */
+struct __fh_t {
+#if defined(DB_WIN32)
+ HANDLE handle; /* Windows/32 file handle. */
+#endif
+ int fd; /* POSIX file descriptor. */
+ char *name; /* File name. */
+
+ u_int32_t log_size; /* XXX: Log file size. */
+ u_int32_t pagesize; /* XXX: Page size. */
+
+#define DB_FH_NOSYNC 0x01 /* Handle doesn't need to be sync'd. */
+#define DB_FH_UNLINK 0x02 /* Unlink on close */
+#define DB_FH_VALID 0x04 /* Handle is valid. */
+ u_int8_t flags;
+};
+
+/*
+ * We group certain seek/write calls into a single function so that we
+ * can use pread(2)/pwrite(2) where they're available.
+ */
+#define DB_IO_READ 1
+#define DB_IO_WRITE 2
+typedef struct __io_t {
+ DB_FH *fhp; /* I/O file handle. */
+ DB_MUTEX *mutexp; /* Mutex to lock. */
+ size_t pagesize; /* Page size. */
+ db_pgno_t pgno; /* Page number. */
+ u_int8_t *buf; /* Buffer. */
+ size_t bytes; /* Bytes read/written. */
+} DB_IO;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include "dbinc_auto/os_ext.h"
+#endif /* !_DB_OS_H_ */
diff --git a/bdb/dbinc/qam.h b/bdb/dbinc/qam.h
new file mode 100644
index 00000000000..0306ed07d2a
--- /dev/null
+++ b/bdb/dbinc/qam.h
@@ -0,0 +1,156 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: qam.h,v 11.38 2002/08/06 06:11:21 bostic Exp $
+ */
+
+#ifndef _DB_QAM_H_
+#define _DB_QAM_H_
+
+/*
+ * QAM data elements: a status field and the data.
+ */
+typedef struct _qamdata {
+ u_int8_t flags; /* 00: delete bit. */
+#define QAM_VALID 0x01
+#define QAM_SET 0x02
+ u_int8_t data[1]; /* Record. */
+} QAMDATA;
+
+struct __queue; typedef struct __queue QUEUE;
+struct __qcursor; typedef struct __qcursor QUEUE_CURSOR;
+
+struct __qcursor {
+ /* struct __dbc_internal */
+ __DBC_INTERNAL
+
+ /* Queue private part */
+
+ /* Per-thread information: queue private. */
+ db_recno_t recno; /* Current record number. */
+
+ u_int32_t flags;
+};
+
+typedef struct __mpfarray {
+ u_int32_t n_extent; /* Number of extents in table. */
+ u_int32_t low_extent; /* First extent open. */
+ u_int32_t hi_extent; /* Last extent open. */
+ struct __qmpf {
+ int pinref;
+ DB_MPOOLFILE *mpf;
+ } *mpfarray; /* Array of open extents. */
+} MPFARRAY;
+
+/*
+ * The in-memory, per-tree queue data structure.
+ */
+struct __queue {
+ db_pgno_t q_meta; /* Database meta-data page. */
+ db_pgno_t q_root; /* Database root page. */
+
+ int re_pad; /* Fixed-length padding byte. */
+ u_int32_t re_len; /* Length for fixed-length records. */
+ u_int32_t rec_page; /* records per page */
+ u_int32_t page_ext; /* Pages per extent */
+ MPFARRAY array1, array2; /* File arrays. */
+
+ /* Extent file configuration: */
+ DBT pgcookie; /* Initialized pgcookie. */
+ DB_PGINFO pginfo; /* Initialized pginfo struct. */
+
+ char *path; /* Space allocated to file pathname. */
+ char *name; /* The name of the file. */
+ char *dir; /* The dir of the file. */
+ int mode; /* Mode to open extents. */
+};
+
+/* Format for queue extent names. */
+#define QUEUE_EXTENT "%s%c__dbq.%s.%d"
+
+typedef struct __qam_filelist {
+ DB_MPOOLFILE *mpf;
+ u_int32_t id;
+} QUEUE_FILELIST;
+
+/*
+ * Caculate the page number of a recno
+ *
+ * Number of records per page =
+ * Divide the available space on the page by the record len + header.
+ *
+ * Page number for record =
+ * divide the physical record number by the records per page
+ * add the root page number
+ * For now the root page will always be 1, but we might want to change
+ * in the future (e.g. multiple fixed len queues per file).
+ *
+ * Index of record on page =
+ * physical record number, less the logical pno times records/page
+ */
+#define CALC_QAM_RECNO_PER_PAGE(dbp) \
+ (((dbp)->pgsize - QPAGE_SZ(dbp)) / \
+ ALIGN(((QUEUE *)(dbp)->q_internal)->re_len + \
+ sizeof(QAMDATA) - SSZA(QAMDATA, data), sizeof(u_int32_t)))
+
+#define QAM_RECNO_PER_PAGE(dbp) (((QUEUE*)(dbp)->q_internal)->rec_page)
+
+#define QAM_RECNO_PAGE(dbp, recno) \
+ (((QUEUE *)(dbp)->q_internal)->q_root \
+ + (((recno) - 1) / QAM_RECNO_PER_PAGE(dbp)))
+
+#define QAM_RECNO_INDEX(dbp, pgno, recno) \
+ (((recno) - 1) - (QAM_RECNO_PER_PAGE(dbp) \
+ * (pgno - ((QUEUE *)(dbp)->q_internal)->q_root)))
+
+#define QAM_GET_RECORD(dbp, page, index) \
+ ((QAMDATA *)((u_int8_t *)(page) + \
+ QPAGE_SZ(dbp) + (ALIGN(sizeof(QAMDATA) - SSZA(QAMDATA, data) + \
+ ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)) * index)))
+
+#define QAM_AFTER_CURRENT(meta, recno) \
+ ((recno) > (meta)->cur_recno && \
+ ((meta)->first_recno <= (meta)->cur_recno || (recno) < (meta)->first_recno))
+
+#define QAM_BEFORE_FIRST(meta, recno) \
+ ((recno) < (meta)->first_recno && \
+ ((meta->first_recno <= (meta)->cur_recno || (recno) > (meta)->cur_recno)))
+
+#define QAM_NOT_VALID(meta, recno) \
+ (recno == RECNO_OOB || \
+ QAM_BEFORE_FIRST(meta, recno) || QAM_AFTER_CURRENT(meta, recno))
+
+/*
+ * Log opcodes for the mvptr routine.
+ */
+#define QAM_SETFIRST 0x01
+#define QAM_SETCUR 0x02
+#define QAM_TRUNCATE 0x04
+
+/*
+ * Parameter to __qam_position.
+ */
+typedef enum {
+ QAM_READ,
+ QAM_WRITE,
+ QAM_CONSUME
+} qam_position_mode;
+
+typedef enum {
+ QAM_PROBE_GET,
+ QAM_PROBE_PUT,
+ QAM_PROBE_MPF
+} qam_probe_mode;
+
+#define __qam_fget(dbp, pgnoaddr, flags, addrp) \
+ __qam_fprobe(dbp, *pgnoaddr, addrp, QAM_PROBE_GET, flags)
+
+#define __qam_fput(dbp, pageno, addrp, flags) \
+ __qam_fprobe(dbp, pageno, addrp, QAM_PROBE_PUT, flags)
+
+#include "dbinc_auto/qam_auto.h"
+#include "dbinc_auto/qam_ext.h"
+#endif /* !_DB_QAM_H_ */
diff --git a/bdb/include/queue.h b/bdb/dbinc/queue.h
index 8d4a771add6..8d4a771add6 100644
--- a/bdb/include/queue.h
+++ b/bdb/dbinc/queue.h
diff --git a/bdb/dbinc/region.h b/bdb/dbinc/region.h
new file mode 100644
index 00000000000..9ee6c81062f
--- /dev/null
+++ b/bdb/dbinc/region.h
@@ -0,0 +1,304 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: region.h,v 11.33 2002/08/06 06:11:22 bostic Exp $
+ */
+
+#ifndef _DB_REGION_H_
+#define _DB_REGION_H_
+
+/*
+ * The DB environment consists of some number of "regions", which are described
+ * by the following four structures:
+ *
+ * REGENV -- shared information about the environment
+ * REGENV_REF -- file describing system memory version of REGENV
+ * REGION -- shared information about a single region
+ * REGINFO -- per-process information about a REGION
+ *
+ * There are three types of memory that hold regions:
+ * per-process heap (malloc)
+ * file mapped into memory (mmap, MapViewOfFile)
+ * system memory (shmget, CreateFileMapping)
+ *
+ * If the regions are private to a process, they're in malloc. If they're
+ * public, they're in file mapped memory, or, optionally, in system memory.
+ * Regions in the filesystem are named "__db.001", "__db.002" and so on. If
+ * we're not using a private environment allocated using malloc(3), the file
+ * "__db.001" will always exist, as we use it to synchronize on the regions,
+ * whether they exist in file mapped memory or system memory.
+ *
+ * The file "__db.001" contains a REGENV structure and a linked list of some
+ * number of REGION structures. Each of the REGION structures describes and
+ * locks one of the underlying shared regions used by DB.
+ *
+ * __db.001
+ * +---------+
+ * |REGENV |
+ * +---------+ +----------+
+ * |REGION |-> | __db.002 |
+ * | | +----------+
+ * +---------+ +----------+
+ * |REGION |-> | __db.003 |
+ * | | +----------+
+ * +---------+ +----------+
+ * |REGION |-> | __db.004 |
+ * | | +----------+
+ * +---------+
+ *
+ * The only tricky part about manipulating the regions is correctly creating
+ * or joining the REGENV file, i.e., __db.001. We have to be absolutely sure
+ * that only one process creates it, and that everyone else joins it without
+ * seeing inconsistent data. Once that region is created, we can use normal
+ * shared locking procedures to do mutal exclusion for all other regions.
+ *
+ * One of the REGION structures in the main environment region describes the
+ * environment region itself.
+ *
+ * To lock a region, locate the REGION structure that describes it and acquire
+ * the region's mutex. There is one exception to this rule -- the lock for the
+ * environment region itself is in the REGENV structure, and not in the REGION
+ * that describes the environment region. That's so that we can acquire a lock
+ * without walking linked lists that could potentially change underneath us.
+ * The REGION will not be moved or removed during the life of the region, and
+ * so long-lived references to it can be held by the process.
+ *
+ * All requests to create or join a region return a REGINFO structure, which
+ * is held by the caller and used to open and subsequently close the reference
+ * to the region. The REGINFO structure contains the per-process information
+ * that we need to access the region.
+ *
+ * The one remaining complication. If the regions (including the environment
+ * region) live in system memory, and the system memory isn't "named" somehow
+ * in the filesystem name space, we need some way of finding it. Do this by
+ * by writing the REGENV_REF structure into the "__db.001" file. When we find
+ * a __db.001 file that is too small to be a real, on-disk environment, we use
+ * the information it contains to redirect to the real "__db.001" file/memory.
+ * This currently only happens when the REGENV file is in shared system memory.
+ *
+ * Although DB does not currently grow regions when they run out of memory, it
+ * would be possible to do so. To grow a region, allocate a new region of the
+ * appropriate size, then copy the old region over it and insert the additional
+ * space into the already existing shalloc arena. Callers may have to fix up
+ * local references, but that should be easy to do. This failed in historic
+ * versions of DB because the region lock lived in the mapped memory, and when
+ * it was unmapped and remapped (or copied), threads could lose track of it.
+ * Once we moved that lock into a region that is never unmapped, growing should
+ * work. That all said, current versions of DB don't implement region grow
+ * because some systems don't support mutex copying, e.g., from OSF1 V4.0:
+ *
+ * The address of an msemaphore structure may be significant. If the
+ * msemaphore structure contains any value copied from an msemaphore
+ * structure at a different address, the result is undefined.
+ */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define DB_REGION_FMT "__db.%03d" /* Region file name format. */
+#define DB_REGION_NAME_NUM 5 /* First digit offset in file names. */
+#define DB_REGION_NAME_LENGTH 8 /* Length of file names. */
+
+#define DB_REGION_ENV "__db.001" /* Primary environment name. */
+
+#define INVALID_REGION_ID 0 /* Out-of-band region ID. */
+#define REGION_ID_ENV 1 /* Primary environment ID. */
+
+typedef enum {
+ INVALID_REGION_TYPE=0, /* Region type. */
+ REGION_TYPE_ENV,
+ REGION_TYPE_LOCK,
+ REGION_TYPE_LOG,
+ REGION_TYPE_MPOOL,
+ REGION_TYPE_MUTEX,
+ REGION_TYPE_TXN } reg_type;
+
+#define INVALID_REGION_SEGID -1 /* Segment IDs are either shmget(2) or
+ * Win16 segment identifiers. They are
+ * both stored in a "long", and we need
+ * an out-of-band value.
+ */
+/*
+ * Nothing can live at region offset 0, because, in all cases, that's where
+ * we store *something*. Lots of code needs an out-of-band value for region
+ * offsets, so we use 0.
+ */
+#define INVALID_ROFF 0
+
+/* Reference describing system memory version of REGENV. */
+typedef struct __db_reg_env_ref {
+ roff_t size; /* Region size. */
+ long segid; /* UNIX shmget ID, VxWorks ID. */
+} REGENV_REF;
+
+/* Per-environment region information. */
+typedef struct __db_reg_env {
+ /*
+ * !!!
+ * The mutex must be the first entry in the structure to guarantee
+ * correct alignment.
+ */
+ DB_MUTEX mutex; /* Environment mutex. */
+
+ /*
+ * !!!
+ * Note, the magic and panic fields are NOT protected by any mutex,
+ * and for this reason cannot be anything more complicated than a
+ * zero/non-zero value.
+ *
+ * !!!
+ * The valid region magic number must appear at the same byte offset
+ * in both the environment and each shared region, as Windows/95 uses
+ * it to determine if the memory has been zeroed since it was last used.
+ */
+ u_int32_t magic; /* Valid region magic number. */
+
+ int envpanic; /* Environment is dead. */
+
+ int majver; /* Major DB version number. */
+ int minver; /* Minor DB version number. */
+ int patch; /* Patch DB version number. */
+
+ u_int32_t init_flags; /* Flags the env was initialized with.*/
+ roff_t cipher_off; /* Offset of cipher area */
+
+ /* List of regions. */
+ SH_LIST_HEAD(__db_regionh) regionq;
+
+ u_int32_t refcnt; /* References to the environment. */
+
+ roff_t rep_off; /* Offset of the replication area. */
+
+ size_t pad; /* Guarantee that following memory is
+ * size_t aligned. This is necessary
+ * because we're going to store the
+ * allocation region information there.
+ */
+} REGENV;
+
+/* Per-region shared region information. */
+typedef struct __db_region {
+ /*
+ * !!!
+ * The mutex must be the first entry in the structure to guarantee
+ * correct alignment.
+ */
+ DB_MUTEX mutex; /* Region mutex. */
+
+ /*
+ * !!!
+ * The valid region magic number must appear at the same byte offset
+ * in both the environment and each shared region, as Windows/95 uses
+ * it to determine if the memory has been zeroed since it was last used.
+ */
+ u_int32_t magic;
+
+ SH_LIST_ENTRY q; /* Linked list of REGIONs. */
+
+ reg_type type; /* Region type. */
+ u_int32_t id; /* Region id. */
+
+ roff_t size; /* Region size in bytes. */
+
+ roff_t primary; /* Primary data structure offset. */
+
+ long segid; /* UNIX shmget(2), Win16 segment ID. */
+} REGION;
+
+/*
+ * Per-process/per-attachment information about a single region.
+ */
+struct __db_reginfo_t { /* __db_r_attach IN parameters. */
+ reg_type type; /* Region type. */
+ u_int32_t id; /* Region id. */
+ int mode; /* File creation mode. */
+
+ /* __db_r_attach OUT parameters. */
+ REGION *rp; /* Shared region. */
+
+ char *name; /* Region file name. */
+
+ void *addr; /* Region allocation address. */
+ void *primary; /* Primary data structure address. */
+
+ void *wnt_handle; /* Win/NT HANDLE. */
+
+#define REGION_CREATE 0x01 /* Caller created region. */
+#define REGION_CREATE_OK 0x02 /* Caller willing to create region. */
+#define REGION_JOIN_OK 0x04 /* Caller is looking for a match. */
+ u_int32_t flags;
+};
+
+/*
+ * Mutex maintenance information each subsystem region must keep track
+ * of to manage resources adequately.
+ */
+typedef struct __db_regmaint_stat_t {
+ u_int32_t st_hint_hit;
+ u_int32_t st_hint_miss;
+ u_int32_t st_records;
+ u_int32_t st_clears;
+ u_int32_t st_destroys;
+ u_int32_t st_max_locks;
+} REGMAINT_STAT;
+
+typedef struct __db_regmaint_t {
+ u_int32_t reglocks; /* Maximum # of mutexes we track. */
+ u_int32_t regmutex_hint; /* Hint for next slot */
+ REGMAINT_STAT stat; /* Stats */
+ roff_t regmutexes[1]; /* Region mutexes in use. */
+} REGMAINT;
+
+/*
+ * R_ADDR Return a per-process address for a shared region offset.
+ * R_OFFSET Return a shared region offset for a per-process address.
+ *
+ * !!!
+ * R_OFFSET should really be returning a ptrdiff_t, but that's not yet
+ * portable. We use u_int32_t, which restricts regions to 4Gb in size.
+ */
+#define R_ADDR(base, offset) \
+ ((void *)((u_int8_t *)((base)->addr) + offset))
+#define R_OFFSET(base, p) \
+ ((u_int32_t)((u_int8_t *)(p) - (u_int8_t *)(base)->addr))
+
+/*
+ * R_LOCK Lock/unlock a region.
+ * R_UNLOCK
+ */
+#define R_LOCK(dbenv, reginfo) \
+ MUTEX_LOCK(dbenv, &(reginfo)->rp->mutex)
+#define R_UNLOCK(dbenv, reginfo) \
+ MUTEX_UNLOCK(dbenv, &(reginfo)->rp->mutex)
+
+/* PANIC_CHECK: Check to see if the DB environment is dead. */
+#define PANIC_CHECK(dbenv) \
+ if (!F_ISSET((dbenv), DB_ENV_NOPANIC) && \
+ (dbenv)->reginfo != NULL && ((REGENV *) \
+ ((REGINFO *)(dbenv)->reginfo)->primary)->envpanic != 0) \
+ return (__db_panic_msg(dbenv));
+
+#define PANIC_SET(dbenv, onoff) \
+ ((REGENV *)((REGINFO *)(dbenv)->reginfo)->primary)->envpanic = (onoff);
+
+/*
+ * All regions are created on 8K boundaries out of sheer paranoia, so we
+ * don't make some underlying VM unhappy. Make sure we don't overflow or
+ * underflow.
+ */
+#define OS_VMPAGESIZE (8 * 1024)
+#define OS_VMROUNDOFF(i) { \
+ if ((i) < \
+ (UINT32_T_MAX - OS_VMPAGESIZE) + 1 || (i) < OS_VMPAGESIZE) \
+ (i) += OS_VMPAGESIZE - 1; \
+ (i) -= (i) % OS_VMPAGESIZE; \
+}
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* !_DB_REGION_H_ */
diff --git a/bdb/dbinc/rep.h b/bdb/dbinc/rep.h
new file mode 100644
index 00000000000..1e315494c87
--- /dev/null
+++ b/bdb/dbinc/rep.h
@@ -0,0 +1,184 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#ifndef _REP_H_
+#define _REP_H_
+
+#define REP_ALIVE 1 /* I am alive message. */
+#define REP_ALIVE_REQ 2 /* Request for alive messages. */
+#define REP_ALL_REQ 3 /* Request all log records greater than LSN. */
+#define REP_ELECT 4 /* Indicates that all listeners should */
+ /* begin master election */
+#define REP_FILE 6 /* Page of a database file. */
+#define REP_FILE_REQ 7 /* Request for a database file. */
+#define REP_LOG 8 /* Log record. */
+#define REP_LOG_MORE 9 /* There are more log records to request. */
+#define REP_LOG_REQ 10 /* Request for a log record. */
+#define REP_MASTER_REQ 11 /* Who is the master */
+#define REP_NEWCLIENT 12 /* Announces the presence of a new client. */
+#define REP_NEWFILE 13 /* Announce a log file change. */
+#define REP_NEWMASTER 14 /* Announces who the master is. */
+#define REP_NEWSITE 15 /* Announces that a site has heard from a new
+ * site; like NEWCLIENT, but indirect. A
+ * NEWCLIENT message comes directly from the new
+ * client while a NEWSITE comes indirectly from
+ * someone who heard about a NEWSITE.
+ */
+#define REP_PAGE 16 /* Database page. */
+#define REP_PAGE_REQ 17 /* Request for a database page. */
+#define REP_PLIST 18 /* Database page list. */
+#define REP_PLIST_REQ 19 /* Request for a page list. */
+#define REP_VERIFY 20 /* A log record for verification. */
+#define REP_VERIFY_FAIL 21 /* The client is outdated. */
+#define REP_VERIFY_REQ 22 /* Request for a log record to verify. */
+#define REP_VOTE1 23 /* Send out your information for an election. */
+#define REP_VOTE2 24 /* Send a "you are master" vote. */
+
+/* Used to consistently designate which messages ought to be received where. */
+#define MASTER_ONLY(dbenv) \
+ if (!F_ISSET(dbenv, DB_ENV_REP_MASTER)) return (EINVAL)
+
+#define CLIENT_ONLY(dbenv) \
+ if (!F_ISSET(dbenv, DB_ENV_REP_CLIENT)) return (EINVAL)
+
+#define ANYSITE(dbenv)
+
+/* Shared replication structure. */
+
+typedef struct __rep {
+ /*
+ * Due to alignment constraints on some architectures (e.g. HP-UX),
+ * DB_MUTEXes must be the first element of shalloced structures,
+ * and as a corollary there can be only one per structure. Thus,
+ * db_mutex_off points to a mutex in a separately-allocated chunk.
+ */
+ DB_MUTEX mutex; /* Region lock. */
+ roff_t db_mutex_off; /* Client database mutex. */
+ u_int32_t tally_off; /* Offset of the tally region. */
+ int eid; /* Environment id. */
+ int master_id; /* ID of the master site. */
+ u_int32_t gen; /* Replication generation number */
+ int asites; /* Space allocated for sites. */
+ int nsites; /* Number of sites in group. */
+ int priority; /* My priority in an election. */
+ u_int32_t gbytes; /* Limit on data sent in single... */
+ u_int32_t bytes; /* __rep_process_message call. */
+#define DB_REP_REQUEST_GAP 4
+#define DB_REP_MAX_GAP 128
+ u_int32_t request_gap; /* # of records to receive before we
+ * request a missing log record. */
+ u_int32_t max_gap; /* Maximum number of records before
+ * requesting a missing log record. */
+
+ /* Vote tallying information. */
+ int sites; /* Sites heard from. */
+ int winner; /* Current winner. */
+ int w_priority; /* Winner priority. */
+ u_int32_t w_gen; /* Winner generation. */
+ DB_LSN w_lsn; /* Winner LSN. */
+ int w_tiebreaker; /* Winner tiebreaking value. */
+ int votes; /* Number of votes for this site. */
+
+ /* Statistics. */
+ DB_REP_STAT stat;
+
+#define REP_F_EPHASE1 0x01 /* In phase 1 of election. */
+#define REP_F_EPHASE2 0x02 /* In phase 2 of election. */
+#define REP_F_LOGSONLY 0x04 /* Log-site only; cannot be upgraded. */
+#define REP_F_MASTER 0x08 /* Master replica. */
+#define REP_F_RECOVER 0x10
+#define REP_F_UPGRADE 0x20 /* Upgradeable replica. */
+#define REP_ISCLIENT (REP_F_UPGRADE | REP_F_LOGSONLY)
+ u_int32_t flags;
+} REP;
+
+#define IN_ELECTION(R) F_ISSET((R), REP_F_EPHASE1 | REP_F_EPHASE2)
+#define ELECTION_DONE(R) F_CLR((R), REP_F_EPHASE1 | REP_F_EPHASE2)
+
+/*
+ * Per-process replication structure.
+ */
+struct __db_rep {
+ DB_MUTEX *mutexp;
+
+ DB_MUTEX *db_mutexp; /* Mutex for bookkeeping database. */
+ DB *rep_db; /* Bookkeeping database. */
+
+ REP *region; /* In memory structure. */
+ int (*rep_send) /* Send function. */
+ __P((DB_ENV *,
+ const DBT *, const DBT *, int, u_int32_t));
+};
+
+/*
+ * Control structure for replication communication infrastructure.
+ *
+ * Note that the version information should be at the beginning of the
+ * structure, so that we can rearrange the rest of it while letting the
+ * version checks continue to work. DB_REPVERSION should be revved any time
+ * the rest of the structure changes.
+ */
+typedef struct __rep_control {
+#define DB_REPVERSION 1
+ u_int32_t rep_version; /* Replication version number. */
+ u_int32_t log_version; /* Log version number. */
+
+ DB_LSN lsn; /* Log sequence number. */
+ u_int32_t rectype; /* Message type. */
+ u_int32_t gen; /* Generation number. */
+ u_int32_t flags; /* log_put flag value. */
+} REP_CONTROL;
+
+/* Election vote information. */
+typedef struct __rep_vote {
+ int priority; /* My site's priority. */
+ int nsites; /* Number of sites I've been in
+ * communication with. */
+ int tiebreaker; /* Tie-breaking quasi-random int. */
+} REP_VOTE_INFO;
+
+/*
+ * This structure takes care of representing a transaction.
+ * It holds all the records, sorted by page number so that
+ * we can obtain locks and apply updates in a deadlock free
+ * order.
+ */
+typedef struct __lsn_page {
+ DB_LSN lsn;
+ u_int32_t fid;
+ DB_LOCK_ILOCK pgdesc;
+#define LSN_PAGE_NOLOCK 0x0001 /* No lock necessary for log rec. */
+ u_int32_t flags;
+} LSN_PAGE;
+
+typedef struct __txn_recs {
+ int npages;
+ int nalloc;
+ LSN_PAGE *array;
+ u_int32_t txnid;
+ u_int32_t lockid;
+} TXN_RECS;
+
+typedef struct __lsn_collection {
+ int nlsns;
+ int nalloc;
+ DB_LSN *array;
+} LSN_COLLECTION;
+
+/*
+ * This is used by the page-prep routines to do the lock_vec call to
+ * apply the updates for a single transaction or a collection of
+ * transactions.
+ */
+typedef struct _linfo {
+ int n;
+ DB_LOCKREQ *reqs;
+ DBT *objs;
+} linfo_t;
+
+#include "dbinc_auto/rep_ext.h"
+#endif /* !_REP_H_ */
diff --git a/bdb/dbinc/shqueue.h b/bdb/dbinc/shqueue.h
new file mode 100644
index 00000000000..47fdf12ac92
--- /dev/null
+++ b/bdb/dbinc/shqueue.h
@@ -0,0 +1,337 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: shqueue.h,v 11.9 2002/01/11 15:52:30 bostic Exp $
+ */
+
+#ifndef _SYS_SHQUEUE_H_
+#define _SYS_SHQUEUE_H_
+
+/*
+ * This file defines three types of data structures: lists, tail queues, and
+ * circular queues, similarly to the include file <sys/queue.h>.
+ *
+ * The difference is that this set of macros can be used for structures that
+ * reside in shared memory that may be mapped at different addresses in each
+ * process. In most cases, the macros for shared structures exactly mirror
+ * the normal macros, although the macro calls require an additional type
+ * parameter, only used by the HEAD and ENTRY macros of the standard macros.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Shared list definitions.
+ */
+#define SH_LIST_HEAD(name) \
+struct name { \
+ ssize_t slh_first; /* first element */ \
+}
+
+#define SH_LIST_ENTRY \
+struct { \
+ ssize_t sle_next; /* relative offset next element */ \
+ ssize_t sle_prev; /* relative offset of prev element */ \
+}
+
+/*
+ * Shared list functions. Since we use relative offsets for pointers,
+ * 0 is a valid offset. Therefore, we use -1 to indicate end of list.
+ * The macros ending in "P" return pointers without checking for end
+ * of list, the others check for end of list and evaluate to either a
+ * pointer or NULL.
+ */
+
+#define SH_LIST_FIRSTP(head, type) \
+ ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))
+
+#define SH_LIST_FIRST(head, type) \
+ ((head)->slh_first == -1 ? NULL : \
+ ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)))
+
+#define SH_LIST_NEXTP(elm, field, type) \
+ ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next))
+
+#define SH_LIST_NEXT(elm, field, type) \
+ ((elm)->field.sle_next == -1 ? NULL : \
+ ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)))
+
+#define SH_LIST_PREV(elm, field) \
+ ((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev))
+
+#define SH_PTR_TO_OFF(src, dest) \
+ ((ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src))))
+
+/*
+ * Take the element's next pointer and calculate what the corresponding
+ * Prev pointer should be -- basically it is the negation plus the offset
+ * of the next field in the structure.
+ */
+#define SH_LIST_NEXT_TO_PREV(elm, field) \
+ (-(elm)->field.sle_next + SH_PTR_TO_OFF(elm, &(elm)->field.sle_next))
+
+#define SH_LIST_INIT(head) (head)->slh_first = -1
+
+#define SH_LIST_INSERT_AFTER(listelm, elm, field, type) do { \
+ if ((listelm)->field.sle_next != -1) { \
+ (elm)->field.sle_next = SH_PTR_TO_OFF(elm, \
+ SH_LIST_NEXTP(listelm, field, type)); \
+ SH_LIST_NEXTP(listelm, field, type)->field.sle_prev = \
+ SH_LIST_NEXT_TO_PREV(elm, field); \
+ } else \
+ (elm)->field.sle_next = -1; \
+ (listelm)->field.sle_next = SH_PTR_TO_OFF(listelm, elm); \
+ (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(listelm, field); \
+} while (0)
+
+#define SH_LIST_INSERT_HEAD(head, elm, field, type) do { \
+ if ((head)->slh_first != -1) { \
+ (elm)->field.sle_next = \
+ (head)->slh_first - SH_PTR_TO_OFF(head, elm); \
+ SH_LIST_FIRSTP(head, type)->field.sle_prev = \
+ SH_LIST_NEXT_TO_PREV(elm, field); \
+ } else \
+ (elm)->field.sle_next = -1; \
+ (head)->slh_first = SH_PTR_TO_OFF(head, elm); \
+ (elm)->field.sle_prev = SH_PTR_TO_OFF(elm, &(head)->slh_first); \
+} while (0)
+
+#define SH_LIST_REMOVE(elm, field, type) do { \
+ if ((elm)->field.sle_next != -1) { \
+ SH_LIST_NEXTP(elm, field, type)->field.sle_prev = \
+ (elm)->field.sle_prev - (elm)->field.sle_next; \
+ *SH_LIST_PREV(elm, field) += (elm)->field.sle_next; \
+ } else \
+ *SH_LIST_PREV(elm, field) = -1; \
+} while (0)
+
+/*
+ * Shared tail queue definitions.
+ */
+#define SH_TAILQ_HEAD(name) \
+struct name { \
+ ssize_t stqh_first; /* relative offset of first element */ \
+ ssize_t stqh_last; /* relative offset of last's next */ \
+}
+
+#define SH_TAILQ_ENTRY \
+struct { \
+ ssize_t stqe_next; /* relative offset of next element */ \
+ ssize_t stqe_prev; /* relative offset of prev's next */ \
+}
+
+/*
+ * Shared tail queue functions.
+ */
+#define SH_TAILQ_FIRSTP(head, type) \
+ ((struct type *)((u_int8_t *)(head) + (head)->stqh_first))
+
+#define SH_TAILQ_FIRST(head, type) \
+ ((head)->stqh_first == -1 ? NULL : SH_TAILQ_FIRSTP(head, type))
+
+#define SH_TAILQ_NEXTP(elm, field, type) \
+ ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next))
+
+#define SH_TAILQ_NEXT(elm, field, type) \
+ ((elm)->field.stqe_next == -1 ? NULL : SH_TAILQ_NEXTP(elm, field, type))
+
+#define SH_TAILQ_PREVP(elm, field) \
+ ((ssize_t *)((u_int8_t *)(elm) + (elm)->field.stqe_prev))
+
+#define SH_TAILQ_LAST(head) \
+ ((ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last))
+
+#define SH_TAILQ_NEXT_TO_PREV(elm, field) \
+ (-(elm)->field.stqe_next + SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next))
+
+#define SH_TAILQ_INIT(head) { \
+ (head)->stqh_first = -1; \
+ (head)->stqh_last = SH_PTR_TO_OFF(head, &(head)->stqh_first); \
+}
+
+#define SH_TAILQ_INSERT_HEAD(head, elm, field, type) do { \
+ if ((head)->stqh_first != -1) { \
+ (elm)->field.stqe_next = \
+ (head)->stqh_first - SH_PTR_TO_OFF(head, elm); \
+ SH_TAILQ_FIRSTP(head, type)->field.stqe_prev = \
+ SH_TAILQ_NEXT_TO_PREV(elm, field); \
+ } else { \
+ (elm)->field.stqe_next = -1; \
+ (head)->stqh_last = \
+ SH_PTR_TO_OFF(head, &(elm)->field.stqe_next); \
+ } \
+ (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \
+ (elm)->field.stqe_prev = \
+ SH_PTR_TO_OFF(elm, &(head)->stqh_first); \
+} while (0)
+
+#define SH_TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = -1; \
+ (elm)->field.stqe_prev = \
+ -SH_PTR_TO_OFF(head, elm) + (head)->stqh_last; \
+ if ((head)->stqh_last == \
+ SH_PTR_TO_OFF((head), &(head)->stqh_first)) \
+ (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \
+ else \
+ *SH_TAILQ_LAST(head) = -(head)->stqh_last + \
+ SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) + \
+ SH_PTR_TO_OFF(head, elm); \
+ (head)->stqh_last = \
+ SH_PTR_TO_OFF(head, &((elm)->field.stqe_next)); \
+} while (0)
+
+#define SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do { \
+ if ((listelm)->field.stqe_next != -1) { \
+ (elm)->field.stqe_next = (listelm)->field.stqe_next - \
+ SH_PTR_TO_OFF(listelm, elm); \
+ SH_TAILQ_NEXTP(listelm, field, type)->field.stqe_prev = \
+ SH_TAILQ_NEXT_TO_PREV(elm, field); \
+ } else { \
+ (elm)->field.stqe_next = -1; \
+ (head)->stqh_last = \
+ SH_PTR_TO_OFF(head, &elm->field.stqe_next); \
+ } \
+ (listelm)->field.stqe_next = SH_PTR_TO_OFF(listelm, elm); \
+ (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(listelm, field); \
+} while (0)
+
+#define SH_TAILQ_REMOVE(head, elm, field, type) do { \
+ if ((elm)->field.stqe_next != -1) { \
+ SH_TAILQ_NEXTP(elm, field, type)->field.stqe_prev = \
+ (elm)->field.stqe_prev + \
+ SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm, \
+ field, type), elm); \
+ *SH_TAILQ_PREVP(elm, field) += elm->field.stqe_next; \
+ } else { \
+ (head)->stqh_last = (elm)->field.stqe_prev + \
+ SH_PTR_TO_OFF(head, elm); \
+ *SH_TAILQ_PREVP(elm, field) = -1; \
+ } \
+} while (0)
+
+/*
+ * Shared circular queue definitions.
+ */
+#define SH_CIRCLEQ_HEAD(name) \
+struct name { \
+ ssize_t scqh_first; /* first element */ \
+ ssize_t scqh_last; /* last element */ \
+}
+
+#define SH_CIRCLEQ_ENTRY \
+struct { \
+ ssize_t scqe_next; /* next element */ \
+ ssize_t scqe_prev; /* previous element */ \
+}
+
+/*
+ * Shared circular queue functions.
+ */
+#define SH_CIRCLEQ_FIRSTP(head, type) \
+ ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_first))
+
+#define SH_CIRCLEQ_FIRST(head, type) \
+ ((head)->scqh_first == -1 ? \
+ (void *)head : SH_CIRCLEQ_FIRSTP(head, type))
+
+#define SH_CIRCLEQ_LASTP(head, type) \
+ ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_last))
+
+#define SH_CIRCLEQ_LAST(head, type) \
+ ((head)->scqh_last == -1 ? (void *)head : SH_CIRCLEQ_LASTP(head, type))
+
+#define SH_CIRCLEQ_NEXTP(elm, field, type) \
+ ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_next))
+
+#define SH_CIRCLEQ_NEXT(head, elm, field, type) \
+ ((elm)->field.scqe_next == SH_PTR_TO_OFF(elm, head) ? \
+ (void *)head : SH_CIRCLEQ_NEXTP(elm, field, type))
+
+#define SH_CIRCLEQ_PREVP(elm, field, type) \
+ ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_prev))
+
+#define SH_CIRCLEQ_PREV(head, elm, field, type) \
+ ((elm)->field.scqe_prev == SH_PTR_TO_OFF(elm, head) ? \
+ (void *)head : SH_CIRCLEQ_PREVP(elm, field, type))
+
+#define SH_CIRCLEQ_INIT(head) { \
+ (head)->scqh_first = 0; \
+ (head)->scqh_last = 0; \
+}
+
+#define SH_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field, type) do { \
+ (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, listelm); \
+ (elm)->field.scqe_next = (listelm)->field.scqe_next + \
+ (elm)->field.scqe_prev; \
+ if (SH_CIRCLEQ_NEXTP(listelm, field, type) == (void *)head) \
+ (head)->scqh_last = SH_PTR_TO_OFF(head, elm); \
+ else \
+ SH_CIRCLEQ_NEXTP(listelm, \
+ field, type)->field.scqe_prev = \
+ SH_PTR_TO_OFF(SH_CIRCLEQ_NEXTP(listelm, \
+ field, type), elm); \
+ (listelm)->field.scqe_next = -(elm)->field.scqe_prev; \
+} while (0)
+
+#define SH_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field, type) do { \
+ (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, listelm); \
+ (elm)->field.scqe_prev = (elm)->field.scqe_next - \
+ SH_CIRCLEQ_PREVP(listelm, field, type)->field.scqe_next;\
+ if (SH_CIRCLEQ_PREVP(listelm, field, type) == (void *)(head)) \
+ (head)->scqh_first = SH_PTR_TO_OFF(head, elm); \
+ else \
+ SH_CIRCLEQ_PREVP(listelm, \
+ field, type)->field.scqe_next = \
+ SH_PTR_TO_OFF(SH_CIRCLEQ_PREVP(listelm, \
+ field, type), elm); \
+ (listelm)->field.scqe_prev = -(elm)->field.scqe_next; \
+} while (0)
+
+#define SH_CIRCLEQ_INSERT_HEAD(head, elm, field, type) do { \
+ (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, head); \
+ (elm)->field.scqe_next = (head)->scqh_first + \
+ (elm)->field.scqe_prev; \
+ if ((head)->scqh_last == 0) \
+ (head)->scqh_last = -(elm)->field.scqe_prev; \
+ else \
+ SH_CIRCLEQ_FIRSTP(head, type)->field.scqe_prev = \
+ SH_PTR_TO_OFF(SH_CIRCLEQ_FIRSTP(head, type), elm); \
+ (head)->scqh_first = -(elm)->field.scqe_prev; \
+} while (0)
+
+#define SH_CIRCLEQ_INSERT_TAIL(head, elm, field, type) do { \
+ (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, head); \
+ (elm)->field.scqe_prev = (head)->scqh_last + \
+ (elm)->field.scqe_next; \
+ if ((head)->scqh_first == 0) \
+ (head)->scqh_first = -(elm)->field.scqe_next; \
+ else \
+ SH_CIRCLEQ_LASTP(head, type)->field.scqe_next = \
+ SH_PTR_TO_OFF(SH_CIRCLEQ_LASTP(head, type), elm); \
+ (head)->scqh_last = -(elm)->field.scqe_next; \
+} while (0)
+
+#define SH_CIRCLEQ_REMOVE(head, elm, field, type) do { \
+ if (SH_CIRCLEQ_NEXTP(elm, field, type) == (void *)(head)) \
+ (head)->scqh_last += (elm)->field.scqe_prev; \
+ else \
+ SH_CIRCLEQ_NEXTP(elm, field, type)->field.scqe_prev += \
+ (elm)->field.scqe_prev; \
+ if (SH_CIRCLEQ_PREVP(elm, field, type) == (void *)(head)) \
+ (head)->scqh_first += (elm)->field.scqe_next; \
+ else \
+ SH_CIRCLEQ_PREVP(elm, field, type)->field.scqe_next += \
+ (elm)->field.scqe_next; \
+} while (0)
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* !_SYS_SHQUEUE_H_ */
diff --git a/bdb/dbinc/tcl_db.h b/bdb/dbinc/tcl_db.h
new file mode 100644
index 00000000000..8c04d545295
--- /dev/null
+++ b/bdb/dbinc/tcl_db.h
@@ -0,0 +1,261 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: tcl_db.h,v 11.30 2002/08/06 06:11:22 bostic Exp $
+ */
+
+#ifndef _DB_TCL_DB_H_
+#define _DB_TCL_DB_H_
+
+#define MSG_SIZE 100 /* Message size */
+
+enum INFOTYPE {
+ I_ENV, I_DB, I_DBC, I_TXN, I_MP, I_PG, I_LOCK, I_LOGC, I_NDBM, I_MUTEX };
+
+#define MAX_ID 8 /* Maximum number of sub-id's we need */
+#define DBTCL_PREP 64 /* Size of txn_recover preplist */
+
+#define DBTCL_DBM 1
+#define DBTCL_NDBM 2
+
+typedef struct _mutex_entry {
+ union {
+ struct {
+ DB_MUTEX real_m;
+ u_int32_t real_val;
+ } r;
+ /*
+ * This is here to make sure that each of the mutex structures
+ * are 16-byte aligned, which is required on HP architectures.
+ * The db_mutex_t structure might be >32 bytes itself, or the
+ * real_val might push it over the 32 byte boundary. The best
+ * we can do is use a 48 byte boundary.
+ */
+ char c[48];
+ } u;
+} _MUTEX_ENTRY;
+
+#define m u.r.real_m
+#define val u.r.real_val
+
+typedef struct _mutex_data {
+ DB_ENV *env;
+ REGINFO reginfo;
+ _MUTEX_ENTRY *marray;
+ size_t size;
+ u_int32_t n_mutex;
+} _MUTEX_DATA;
+
+/*
+ * Why use a home grown package over the Tcl_Hash functions?
+ *
+ * We could have implemented the stuff below without maintaining our
+ * own list manipulation, efficiently hashing it with the available
+ * Tcl functions (Tcl_CreateHashEntry, Tcl_GetHashValue, etc). I chose
+ * not to do so for these reasons:
+ *
+ * We still need the information below. Using the hashing only removes
+ * us from needing the next/prev pointers. We still need the structure
+ * itself because we need more than one value associated with a widget.
+ * We need to keep track of parent pointers for sub-widgets (like cursors)
+ * so we can correctly close. We need to keep track of individual widget's
+ * id counters for any sub-widgets they may have. We need to be able to
+ * associate the name/client data outside the scope of the widget.
+ *
+ * So, is it better to use the hashing rather than
+ * the linear list we have now? I decided against it for the simple reason
+ * that to access the structure would require two calls. The first is
+ * Tcl_FindHashEntry(table, key) and then, once we have the entry, we'd
+ * have to do Tcl_GetHashValue(entry) to get the pointer of the structure.
+ *
+ * I believe the number of simultaneous DB widgets in existence at one time
+ * is not going to be that large (more than several dozen) such that
+ * linearly searching the list is not going to impact performance in a
+ * noticable way. Should performance be impacted due to the size of the
+ * info list, then perhaps it is time to revisit this decision.
+ */
+typedef struct dbtcl_info {
+ LIST_ENTRY(dbtcl_info) entries;
+ Tcl_Interp *i_interp;
+ char *i_name;
+ enum INFOTYPE i_type;
+ union infop {
+ DB_ENV *envp;
+ void *anyp;
+ DB *dbp;
+ DBC *dbcp;
+ DB_TXN *txnp;
+ DB_MPOOLFILE *mp;
+ DB_LOCK *lock;
+ _MUTEX_DATA *mutex;
+ DB_LOGC *logc;
+ } un;
+ union data {
+ int anydata;
+ db_pgno_t pgno;
+ u_int32_t lockid;
+ } und;
+ union data2 {
+ int anydata;
+ size_t pagesz;
+ } und2;
+ DBT i_lockobj;
+ FILE *i_err;
+ char *i_errpfx;
+
+ /* Callbacks--Tcl_Objs containing proc names */
+ Tcl_Obj *i_btcompare;
+ Tcl_Obj *i_dupcompare;
+ Tcl_Obj *i_hashproc;
+ Tcl_Obj *i_rep_send;
+ Tcl_Obj *i_second_call;
+
+ /* Environment ID for the i_rep_send callback. */
+ Tcl_Obj *i_rep_eid;
+
+ struct dbtcl_info *i_parent;
+ int i_otherid[MAX_ID];
+} DBTCL_INFO;
+
+#define i_anyp un.anyp
+#define i_pagep un.anyp
+#define i_envp un.envp
+#define i_dbp un.dbp
+#define i_dbcp un.dbcp
+#define i_txnp un.txnp
+#define i_mp un.mp
+#define i_lock un.lock
+#define i_mutex un.mutex
+#define i_logc un.logc
+
+#define i_data und.anydata
+#define i_pgno und.pgno
+#define i_locker und.lockid
+#define i_data2 und2.anydata
+#define i_pgsz und2.pagesz
+
+#define i_envtxnid i_otherid[0]
+#define i_envmpid i_otherid[1]
+#define i_envlockid i_otherid[2]
+#define i_envmutexid i_otherid[3]
+#define i_envlogcid i_otherid[4]
+
+#define i_mppgid i_otherid[0]
+
+#define i_dbdbcid i_otherid[0]
+
+extern int __debug_on, __debug_print, __debug_stop, __debug_test;
+
+typedef struct dbtcl_global {
+ LIST_HEAD(infohead, dbtcl_info) g_infohead;
+} DBTCL_GLOBAL;
+#define __db_infohead __dbtcl_global.g_infohead
+
+extern DBTCL_GLOBAL __dbtcl_global;
+
+#define NAME_TO_ENV(name) (DB_ENV *)_NameToPtr((name))
+#define NAME_TO_DB(name) (DB *)_NameToPtr((name))
+#define NAME_TO_DBC(name) (DBC *)_NameToPtr((name))
+#define NAME_TO_TXN(name) (DB_TXN *)_NameToPtr((name))
+#define NAME_TO_MP(name) (DB_MPOOLFILE *)_NameToPtr((name))
+#define NAME_TO_LOCK(name) (DB_LOCK *)_NameToPtr((name))
+
+/*
+ * MAKE_STAT_LIST appends a {name value} pair to a result list
+ * that MUST be called 'res' that is a Tcl_Obj * in the local
+ * function. This macro also assumes a label "error" to go to
+ * in the even of a Tcl error. For stat functions this will
+ * typically go before the "free" function to free the stat structure
+ * returned by DB.
+ */
+#define MAKE_STAT_LIST(s,v) \
+do { \
+ result = _SetListElemInt(interp, res, (s), (v)); \
+ if (result != TCL_OK) \
+ goto error; \
+} while (0)
+
+/*
+ * MAKE_STAT_LSN appends a {name {LSNfile LSNoffset}} pair to a result list
+ * that MUST be called 'res' that is a Tcl_Obj * in the local
+ * function. This macro also assumes a label "error" to go to
+ * in the even of a Tcl error. For stat functions this will
+ * typically go before the "free" function to free the stat structure
+ * returned by DB.
+ */
+#define MAKE_STAT_LSN(s, lsn) \
+do { \
+ myobjc = 2; \
+ myobjv[0] = Tcl_NewLongObj((long)(lsn)->file); \
+ myobjv[1] = Tcl_NewLongObj((long)(lsn)->offset); \
+ lsnlist = Tcl_NewListObj(myobjc, myobjv); \
+ myobjc = 2; \
+ myobjv[0] = Tcl_NewStringObj((s), strlen(s)); \
+ myobjv[1] = lsnlist; \
+ thislist = Tcl_NewListObj(myobjc, myobjv); \
+ result = Tcl_ListObjAppendElement(interp, res, thislist); \
+ if (result != TCL_OK) \
+ goto error; \
+} while (0)
+
+/*
+ * MAKE_STAT_STRLIST appends a {name string} pair to a result list
+ * that MUST be called 'res' that is a Tcl_Obj * in the local
+ * function. This macro also assumes a label "error" to go to
+ * in the even of a Tcl error. For stat functions this will
+ * typically go before the "free" function to free the stat structure
+ * returned by DB.
+ */
+#define MAKE_STAT_STRLIST(s,s1) \
+do { \
+ result = _SetListElem(interp, res, (s), strlen(s), \
+ (s1), strlen(s1)); \
+ if (result != TCL_OK) \
+ goto error; \
+} while (0)
+
+/*
+ * FLAG_CHECK checks that the given flag is not set yet.
+ * If it is, it sets up an error message.
+ */
+#define FLAG_CHECK(flag) \
+do { \
+ if ((flag) != 0) { \
+ Tcl_SetResult(interp, \
+ " Only 1 policy can be specified.\n", \
+ TCL_STATIC); \
+ result = TCL_ERROR; \
+ break; \
+ } \
+} while (0)
+
+/*
+ * FLAG_CHECK2 checks that the given flag is not set yet or is
+ * only set to the given allowed value.
+ * If it is, it sets up an error message.
+ */
+#define FLAG_CHECK2(flag,val) \
+do { \
+ if (((flag) & ~(val)) != 0) { \
+ Tcl_SetResult(interp, \
+ " Only 1 policy can be specified.\n", \
+ TCL_STATIC); \
+ result = TCL_ERROR; \
+ break; \
+ } \
+} while (0)
+
+/*
+ * IS_HELP checks whether the arg we bombed on is -?, which is a help option.
+ * If it is, we return TCL_OK (but leave the result set to whatever
+ * Tcl_GetIndexFromObj says, which lists all the valid options. Otherwise
+ * return TCL_ERROR.
+ */
+#define IS_HELP(s) \
+ (strcmp(Tcl_GetStringFromObj(s,NULL), "-?") == 0) ? TCL_OK : TCL_ERROR
+
+#include "dbinc_auto/tcl_ext.h"
+#endif /* !_DB_TCL_DB_H_ */
diff --git a/bdb/dbinc/txn.h b/bdb/dbinc/txn.h
new file mode 100644
index 00000000000..31b00a6ba74
--- /dev/null
+++ b/bdb/dbinc/txn.h
@@ -0,0 +1,143 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: txn.h,v 11.43 2002/08/29 14:22:19 margo Exp $
+ */
+
+#ifndef _TXN_H_
+#define _TXN_H_
+
+#include "dbinc/xa.h"
+
+/* Operation parameters to the delayed commit processing code. */
+typedef enum {
+ TXN_REMOVE, /* Remove a file. */
+ TXN_TRADE, /* Trade lockers. */
+ TXN_TRADED /* Already traded; downgrade lock. */
+} TXN_EVENT_T;
+
+struct __db_txnregion; typedef struct __db_txnregion DB_TXNREGION;
+
+/*
+ * !!!
+ * TXN_MINIMUM = (DB_LOCK_MAXID + 1) but this makes compilers complain.
+ */
+#define TXN_MINIMUM 0x80000000
+#define TXN_MAXIMUM 0xffffffff /* Maximum number of txn ids. */
+#define TXN_INVALID 0 /* Invalid transaction ID. */
+
+#define DEF_MAX_TXNS 20 /* Default max transactions. */
+
+/*
+ * Internal data maintained in shared memory for each transaction.
+ */
+typedef struct __txn_detail {
+ u_int32_t txnid; /* current transaction id
+ used to link free list also */
+ DB_LSN last_lsn; /* last lsn written for this txn */
+ DB_LSN begin_lsn; /* lsn of begin record */
+ roff_t parent; /* Offset of transaction's parent. */
+
+#define TXN_RUNNING 1
+#define TXN_ABORTED 2
+#define TXN_PREPARED 3
+#define TXN_COMMITTED 4
+ u_int32_t status; /* status of the transaction */
+#define TXN_COLLECTED 0x1
+#define TXN_RESTORED 0x2
+ u_int32_t flags; /* collected during txn_recover */
+
+ SH_TAILQ_ENTRY links; /* free/active list */
+
+#define TXN_XA_ABORTED 1
+#define TXN_XA_DEADLOCKED 2
+#define TXN_XA_ENDED 3
+#define TXN_XA_PREPARED 4
+#define TXN_XA_STARTED 5
+#define TXN_XA_SUSPENDED 6
+ u_int32_t xa_status; /* XA status */
+
+ /*
+ * XID (xid_t) structure: because these fields are logged, the
+ * sizes have to be explicit.
+ */
+ u_int8_t xid[XIDDATASIZE]; /* XA global transaction id */
+ u_int32_t bqual; /* bqual_length from XID */
+ u_int32_t gtrid; /* gtrid_length from XID */
+ int32_t format; /* XA format */
+} TXN_DETAIL;
+
+/*
+ * DB_TXNMGR --
+ * The transaction manager encapsulates the transaction system.
+ */
+struct __db_txnmgr {
+/*
+ * These fields need to be protected for multi-threaded support.
+ *
+ * !!!
+ * As this structure is allocated in per-process memory, the mutex may need
+ * to be stored elsewhere on architectures unable to support mutexes in heap
+ * memory, e.g., HP/UX 9.
+ */
+ DB_MUTEX *mutexp; /* Lock list of active transactions
+ * (including the content of each
+ * TXN_DETAIL structure on the list).
+ */
+ /* List of active transactions. */
+ TAILQ_HEAD(_chain, __db_txn) txn_chain;
+ u_int32_t n_discards; /* Number of txns discarded. */
+
+/* These fields are never updated after creation, and so not protected. */
+ DB_ENV *dbenv; /* Environment. */
+ REGINFO reginfo; /* Region information. */
+};
+
+/*
+ * DB_TXNREGION --
+ * The primary transaction data structure in the shared memory region.
+ */
+struct __db_txnregion {
+ u_int32_t maxtxns; /* maximum number of active TXNs */
+ u_int32_t last_txnid; /* last transaction id given out */
+ u_int32_t cur_maxid; /* current max unused id. */
+ DB_LSN last_ckp; /* lsn of the last checkpoint */
+ time_t time_ckp; /* time of last checkpoint */
+ u_int32_t logtype; /* type of logging */
+ u_int32_t locktype; /* lock type */
+ DB_TXN_STAT stat; /* Statistics for txns. */
+
+#define TXN_IN_RECOVERY 0x01 /* environment is being recovered */
+ u_int32_t flags;
+ /* active TXN list */
+ SH_TAILQ_HEAD(__active) active_txn;
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+#define TXN_MAINT_SIZE (sizeof(roff_t) * DB_MAX_HANDLES)
+
+ roff_t maint_off; /* offset of region maintenance info */
+#endif
+};
+
+/*
+ * Log record types. Note that these are *not* alphabetical. This is
+ * intentional so that we don't change the meaning of values between
+ * software upgrades. EXPECTED, UNEXPECTED, IGNORE, NOTFOUND and OK
+ * are used in the
+ * txnlist functions.
+ */
+#define TXN_OK 0
+#define TXN_COMMIT 1
+#define TXN_PREPARE 2
+#define TXN_ABORT 3
+#define TXN_NOTFOUND 4
+#define TXN_IGNORE 5
+#define TXN_EXPECTED 6
+#define TXN_UNEXPECTED 7
+
+#include "dbinc_auto/txn_auto.h"
+#include "dbinc_auto/txn_ext.h"
+#include "dbinc_auto/xa_ext.h"
+#endif /* !_TXN_H_ */
diff --git a/bdb/dbinc/xa.h b/bdb/dbinc/xa.h
new file mode 100644
index 00000000000..64bdac8c914
--- /dev/null
+++ b/bdb/dbinc/xa.h
@@ -0,0 +1,179 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: xa.h,v 11.5 2002/01/11 15:52:30 bostic Exp $
+ */
+/*
+ * Start of xa.h header
+ *
+ * Define a symbol to prevent multiple inclusions of this header file
+ */
+#ifndef XA_H
+#define XA_H
+
+/*
+ * Transaction branch identification: XID and NULLXID:
+ */
+#define XIDDATASIZE 128 /* size in bytes */
+#define MAXGTRIDSIZE 64 /* maximum size in bytes of gtrid */
+#define MAXBQUALSIZE 64 /* maximum size in bytes of bqual */
+
+struct xid_t {
+ long formatID; /* format identifier */
+ long gtrid_length; /* value from 1 through 64 */
+ long bqual_length; /* value from 1 through 64 */
+ char data[XIDDATASIZE];
+};
+typedef struct xid_t XID;
+/*
+ * A value of -1 in formatID means that the XID is null.
+ */
+
+/*
+ * Declarations of routines by which RMs call TMs:
+ */
+extern int ax_reg __P((int, XID *, long));
+extern int ax_unreg __P((int, long));
+
+/*
+ * XA Switch Data Structure
+ */
+#define RMNAMESZ 32 /* length of resource manager name, */
+ /* including the null terminator */
+#define MAXINFOSIZE 256 /* maximum size in bytes of xa_info */
+ /* strings, including the null
+ terminator */
+struct xa_switch_t {
+ char name[RMNAMESZ]; /* name of resource manager */
+ long flags; /* resource manager specific options */
+ long version; /* must be 0 */
+ int (*xa_open_entry) /* xa_open function pointer */
+ __P((char *, int, long));
+ int (*xa_close_entry) /* xa_close function pointer */
+ __P((char *, int, long));
+ int (*xa_start_entry) /* xa_start function pointer */
+ __P((XID *, int, long));
+ int (*xa_end_entry) /* xa_end function pointer */
+ __P((XID *, int, long));
+ int (*xa_rollback_entry) /* xa_rollback function pointer */
+ __P((XID *, int, long));
+ int (*xa_prepare_entry) /* xa_prepare function pointer */
+ __P((XID *, int, long));
+ int (*xa_commit_entry) /* xa_commit function pointer */
+ __P((XID *, int, long));
+ int (*xa_recover_entry) /* xa_recover function pointer */
+ __P((XID *, long, int, long));
+ int (*xa_forget_entry) /* xa_forget function pointer */
+ __P((XID *, int, long));
+ int (*xa_complete_entry) /* xa_complete function pointer */
+ __P((int *, int *, int, long));
+};
+
+/*
+ * Flag definitions for the RM switch
+ */
+#define TMNOFLAGS 0x00000000L /* no resource manager features
+ selected */
+#define TMREGISTER 0x00000001L /* resource manager dynamically
+ registers */
+#define TMNOMIGRATE 0x00000002L /* resource manager does not support
+ association migration */
+#define TMUSEASYNC 0x00000004L /* resource manager supports
+ asynchronous operations */
+/*
+ * Flag definitions for xa_ and ax_ routines
+ */
+/* use TMNOFLAGGS, defined above, when not specifying other flags */
+#define TMASYNC 0x80000000L /* perform routine asynchronously */
+#define TMONEPHASE 0x40000000L /* caller is using one-phase commit
+ optimisation */
+#define TMFAIL 0x20000000L /* dissociates caller and marks
+ transaction branch rollback-only */
+#define TMNOWAIT 0x10000000L /* return if blocking condition
+ exists */
+#define TMRESUME 0x08000000L /* caller is resuming association with
+ suspended transaction branch */
+#define TMSUCCESS 0x04000000L /* dissociate caller from transaction
+ branch */
+#define TMSUSPEND 0x02000000L /* caller is suspending, not ending,
+ association */
+#define TMSTARTRSCAN 0x01000000L /* start a recovery scan */
+#define TMENDRSCAN 0x00800000L /* end a recovery scan */
+#define TMMULTIPLE 0x00400000L /* wait for any asynchronous
+ operation */
+#define TMJOIN 0x00200000L /* caller is joining existing
+ transaction branch */
+#define TMMIGRATE 0x00100000L /* caller intends to perform
+ migration */
+
+/*
+ * ax_() return codes (transaction manager reports to resource manager)
+ */
+#define TM_JOIN 2 /* caller is joining existing
+ transaction branch */
+#define TM_RESUME 1 /* caller is resuming association with
+ suspended transaction branch */
+#define TM_OK 0 /* normal execution */
+#define TMER_TMERR -1 /* an error occurred in the transaction
+ manager */
+#define TMER_INVAL -2 /* invalid arguments were given */
+#define TMER_PROTO -3 /* routine invoked in an improper
+ context */
+
+/*
+ * xa_() return codes (resource manager reports to transaction manager)
+ */
+#define XA_RBBASE 100 /* The inclusive lower bound of the
+ rollback codes */
+#define XA_RBROLLBACK XA_RBBASE /* The rollback was caused by an
+ unspecified reason */
+#define XA_RBCOMMFAIL XA_RBBASE+1 /* The rollback was caused by a
+ communication failure */
+#define XA_RBDEADLOCK XA_RBBASE+2 /* A deadlock was detected */
+#define XA_RBINTEGRITY XA_RBBASE+3 /* A condition that violates the
+ integrity of the resources was
+ detected */
+#define XA_RBOTHER XA_RBBASE+4 /* The resource manager rolled back the
+ transaction branch for a reason not
+ on this list */
+#define XA_RBPROTO XA_RBBASE+5 /* A protocol error occurred in the
+ resource manager */
+#define XA_RBTIMEOUT XA_RBBASE+6 /* A transaction branch took too long */
+#define XA_RBTRANSIENT XA_RBBASE+7 /* May retry the transaction branch */
+#define XA_RBEND XA_RBTRANSIENT /* The inclusive upper bound of the
+ rollback codes */
+#define XA_NOMIGRATE 9 /* resumption must occur where
+ suspension occurred */
+#define XA_HEURHAZ 8 /* the transaction branch may have
+ been heuristically completed */
+#define XA_HEURCOM 7 /* the transaction branch has been
+ heuristically committed */
+#define XA_HEURRB 6 /* the transaction branch has been
+ heuristically rolled back */
+#define XA_HEURMIX 5 /* the transaction branch has been
+ heuristically committed and rolled
+ back */
+#define XA_RETRY 4 /* routine returned with no effect and
+ may be re-issued */
+#define XA_RDONLY 3 /* the transaction branch was read-only
+ and has been committed */
+#define XA_OK 0 /* normal execution */
+#define XAER_ASYNC -2 /* asynchronous operation already
+ outstanding */
+#define XAER_RMERR -3 /* a resource manager error occurred in
+ the transaction branch */
+#define XAER_NOTA -4 /* the XID is not valid */
+#define XAER_INVAL -5 /* invalid arguments were given */
+#define XAER_PROTO -6 /* routine invoked in an improper
+ context */
+#define XAER_RMFAIL -7 /* resource manager unavailable */
+#define XAER_DUPID -8 /* the XID already exists */
+#define XAER_OUTSIDE -9 /* resource manager doing work outside
+ transaction */
+#endif /* ifndef XA_H */
+/*
+ * End of xa.h header
+ */
diff --git a/bdb/dbm/dbm.c b/bdb/dbm/dbm.c
index e5f423572c5..3aa6fff6982 100644
--- a/bdb/dbm/dbm.c
+++ b/bdb/dbm/dbm.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: dbm.c,v 11.7 2000/11/30 00:58:35 ubell Exp $";
+static const char revid[] = "$Id: dbm.c,v 11.14 2002/02/22 16:11:10 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -60,6 +60,36 @@ static const char revid[] = "$Id: dbm.c,v 11.7 2000/11/30 00:58:35 ubell Exp $";
*
* This package provides dbm and ndbm compatible interfaces to DB.
*
+ * EXTERN: #if DB_DBM_HSEARCH != 0
+ *
+ * EXTERN: int __db_ndbm_clearerr __P((DBM *));
+ * EXTERN: void __db_ndbm_close __P((DBM *));
+ * EXTERN: int __db_ndbm_delete __P((DBM *, datum));
+ * EXTERN: int __db_ndbm_dirfno __P((DBM *));
+ * EXTERN: int __db_ndbm_error __P((DBM *));
+ * EXTERN: datum __db_ndbm_fetch __P((DBM *, datum));
+ * EXTERN: datum __db_ndbm_firstkey __P((DBM *));
+ * EXTERN: datum __db_ndbm_nextkey __P((DBM *));
+ * EXTERN: DBM *__db_ndbm_open __P((const char *, int, int));
+ * EXTERN: int __db_ndbm_pagfno __P((DBM *));
+ * EXTERN: int __db_ndbm_rdonly __P((DBM *));
+ * EXTERN: int __db_ndbm_store __P((DBM *, datum, datum, int));
+ *
+ * EXTERN: int __db_dbm_close __P((void));
+ * EXTERN: int __db_dbm_dbrdonly __P((void));
+ * EXTERN: int __db_dbm_delete __P((datum));
+ * EXTERN: int __db_dbm_dirf __P((void));
+ * EXTERN: datum __db_dbm_fetch __P((datum));
+ * EXTERN: datum __db_dbm_firstkey __P((void));
+ * EXTERN: int __db_dbm_init __P((char *));
+ * EXTERN: datum __db_dbm_nextkey __P((datum));
+ * EXTERN: int __db_dbm_pagf __P((void));
+ * EXTERN: int __db_dbm_store __P((datum, datum));
+ *
+ * EXTERN: #endif
+ */
+
+/*
* The DBM routines, which call the NDBM routines.
*/
static DBM *__cur_db;
@@ -210,7 +240,7 @@ __db_ndbm_open(file, oflags, mode)
if ((ret = dbp->set_pagesize(dbp, 4096)) != 0 ||
(ret = dbp->set_h_ffactor(dbp, 40)) != 0 ||
(ret = dbp->set_h_nelem(dbp, 1)) != 0 ||
- (ret = dbp->open(dbp,
+ (ret = dbp->open(dbp, NULL,
path, NULL, DB_HASH, __db_oflags(oflags), mode)) != 0) {
__os_set_errno(ret);
return (NULL);
@@ -277,7 +307,7 @@ __db_ndbm_fetch(dbm, key)
__os_set_errno(ENOENT);
else {
__os_set_errno(ret);
- F_SET(dbc->dbp, DB_DBM_ERROR);
+ F_SET(dbc->dbp, DB_AM_DBM_ERROR);
}
}
return (data);
@@ -312,7 +342,7 @@ __db_ndbm_firstkey(dbm)
__os_set_errno(ENOENT);
else {
__os_set_errno(ret);
- F_SET(dbc->dbp, DB_DBM_ERROR);
+ F_SET(dbc->dbp, DB_AM_DBM_ERROR);
}
}
return (key);
@@ -347,7 +377,7 @@ __db_ndbm_nextkey(dbm)
__os_set_errno(ENOENT);
else {
__os_set_errno(ret);
- F_SET(dbc->dbp, DB_DBM_ERROR);
+ F_SET(dbc->dbp, DB_AM_DBM_ERROR);
}
}
return (key);
@@ -380,7 +410,7 @@ __db_ndbm_delete(dbm, key)
__os_set_errno(ENOENT);
else {
__os_set_errno(ret);
- F_SET(dbc->dbp, DB_DBM_ERROR);
+ F_SET(dbc->dbp, DB_AM_DBM_ERROR);
}
return (-1);
}
@@ -419,7 +449,7 @@ __db_ndbm_store(dbm, key, data, flags)
return (1);
__os_set_errno(ret);
- F_SET(dbc->dbp, DB_DBM_ERROR);
+ F_SET(dbc->dbp, DB_AM_DBM_ERROR);
return (-1);
}
@@ -431,7 +461,7 @@ __db_ndbm_error(dbm)
dbc = (DBC *)dbm;
- return (F_ISSET(dbc->dbp, DB_DBM_ERROR));
+ return (F_ISSET(dbc->dbp, DB_AM_DBM_ERROR));
}
int
@@ -442,7 +472,7 @@ __db_ndbm_clearerr(dbm)
dbc = (DBC *)dbm;
- F_CLR(dbc->dbp, DB_DBM_ERROR);
+ F_CLR(dbc->dbp, DB_AM_DBM_ERROR);
return (0);
}
diff --git a/bdb/dbreg/dbreg.c b/bdb/dbreg/dbreg.c
new file mode 100644
index 00000000000..289fe67ed50
--- /dev/null
+++ b/bdb/dbreg/dbreg.c
@@ -0,0 +1,450 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: dbreg.c,v 11.68 2002/08/28 19:05:27 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+/*
+ * The dbreg subsystem, as its name implies, registers database handles so
+ * that we can associate log messages with them without logging a filename
+ * or a full, unique DB ID. Instead, we assign each dbp an int32_t which is
+ * easy and cheap to log, and use this subsystem to map back and forth.
+ *
+ * Overview of how dbreg ids are managed:
+ *
+ * OPEN
+ * dbreg_setup (Creates FNAME struct.)
+ * dbreg_new_id (Assigns new ID to dbp and logs it. May be postponed
+ * until we attempt to log something else using that dbp, if the dbp
+ * was opened on a replication client.)
+ *
+ * CLOSE
+ * dbreg_close_id (Logs closure of dbp/revocation of ID.)
+ * dbreg_revoke_id (As name implies, revokes ID.)
+ * dbreg_teardown (Destroys FNAME.)
+ *
+ * RECOVERY
+ * dbreg_setup
+ * dbreg_assign_id (Assigns a particular ID we have in the log to a dbp.)
+ *
+ * sometimes: dbreg_revoke_id; dbreg_teardown
+ * other times: normal close path
+ *
+ * A note about locking:
+ *
+ * FNAME structures are referenced only by their corresponding dbp's
+ * until they have a valid id.
+ *
+ * Once they have a valid id, they must get linked into the log
+ * region list so they can get logged on checkpoints.
+ *
+ * An FNAME that may/does have a valid id must be accessed under
+ * protection of the fq_mutex, with the following exception:
+ *
+ * We don't want to have to grab the fq_mutex on every log
+ * record, and it should be safe not to do so when we're just
+ * looking at the id, because once allocated, the id should
+ * not change under a handle until the handle is closed.
+ *
+ * If a handle is closed during an attempt by another thread to
+ * log with it, well, the application doing the close deserves to
+ * go down in flames and a lot else is about to fail anyway.
+ *
+ * When in the course of logging we encounter an invalid id
+ * and go to allocate it lazily, we *do* need to check again
+ * after grabbing the mutex, because it's possible to race with
+ * another thread that has also decided that it needs to allocate
+ * a id lazily.
+ *
+ * See SR #5623 for further discussion of the new dbreg design.
+ */
+
+/*
+ * __dbreg_setup --
+ * Allocate and initialize an FNAME structure. The FNAME structures
+ * live in the log shared region and map one-to-one with open database handles.
+ * When the handle needs to be logged, the FNAME should have a valid fid
+ * allocated. If the handle currently isn't logged, it still has an FNAME
+ * entry. If we later discover that the handle needs to be logged, we can
+ * allocate a id for it later. (This happens when the handle is on a
+ * replication client that later becomes a master.)
+ *
+ * PUBLIC: int __dbreg_setup __P((DB *, const char *, u_int32_t));
+ */
+int
+__dbreg_setup(dbp, name, create_txnid)
+ DB *dbp;
+ const char *name;
+ u_int32_t create_txnid;
+{
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ FNAME *fnp;
+ int ret;
+ size_t len;
+ void *namep;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+
+ fnp = NULL;
+ namep = NULL;
+
+ /* Allocate an FNAME and, if necessary, a buffer for the name itself. */
+ R_LOCK(dbenv, &dblp->reginfo);
+ if ((ret =
+ __db_shalloc(dblp->reginfo.addr, sizeof(FNAME), 0, &fnp)) != 0) {
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (ret);
+ }
+ memset(fnp, 0, sizeof(FNAME));
+ if (name != NULL) {
+ len = strlen(name) + 1;
+ if ((ret = __db_shalloc(dblp->reginfo.addr,
+ len, 0, &namep)) != 0) {
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (ret);
+ }
+ fnp->name_off = R_OFFSET(&dblp->reginfo, namep);
+ memcpy(namep, name, len);
+ } else
+ fnp->name_off = INVALID_ROFF;
+
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ /*
+ * Fill in all the remaining info that we'll need later to register
+ * the file, if we use it for logging.
+ */
+ fnp->id = DB_LOGFILEID_INVALID;
+ fnp->s_type = dbp->type;
+ memcpy(fnp->ufid, dbp->fileid, DB_FILE_ID_LEN);
+ fnp->meta_pgno = dbp->meta_pgno;
+ fnp->create_txnid = create_txnid;
+
+ dbp->log_filename = fnp;
+
+ return (0);
+}
+
+/*
+ * __dbreg_teardown --
+ * Destroy a DB handle's FNAME struct.
+ *
+ * PUBLIC: int __dbreg_teardown __P((DB *));
+ */
+int
+__dbreg_teardown(dbp)
+ DB *dbp;
+{
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ FNAME *fnp;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+ fnp = dbp->log_filename;
+
+ /*
+ * We may not have an FNAME if we were never opened. This is not an
+ * error.
+ */
+ if (fnp == NULL)
+ return (0);
+
+ DB_ASSERT(fnp->id == DB_LOGFILEID_INVALID);
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ if (fnp->name_off != INVALID_ROFF)
+ __db_shalloc_free(dblp->reginfo.addr,
+ R_ADDR(&dblp->reginfo, fnp->name_off));
+ __db_shalloc_free(dblp->reginfo.addr, fnp);
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ dbp->log_filename = NULL;
+
+ return (0);
+}
+
+/*
+ * __dbreg_new_id --
+ * Assign an unused dbreg id to this database handle.
+ *
+ * PUBLIC: int __dbreg_new_id __P((DB *, DB_TXN *));
+ */
+int
+__dbreg_new_id(dbp, txn)
+ DB *dbp;
+ DB_TXN *txn;
+{
+ DBT fid_dbt, r_name;
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ DB_LSN unused;
+ FNAME *fnp;
+ LOG *lp;
+ int32_t id;
+ int ret;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ fnp = dbp->log_filename;
+
+ /* The fq_mutex protects the FNAME list and id management. */
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+
+ /*
+ * It's possible that after deciding we needed to call this function,
+ * someone else allocated an ID before we grabbed the lock. Check
+ * to make sure there was no race and we have something useful to do.
+ */
+ if (fnp->id != DB_LOGFILEID_INVALID) {
+ MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ return (0);
+ }
+
+ /* Get an unused ID from the free list. */
+ if ((ret = __dbreg_pop_id(dbenv, &id)) != 0)
+ goto err;
+
+ /* If no ID was found, allocate a new one. */
+ if (id == DB_LOGFILEID_INVALID)
+ id = lp->fid_max++;
+
+ fnp->id = id;
+
+ /* Hook the FNAME into the list of open files. */
+ SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
+
+ /*
+ * Log the registry. We should only request a new ID in situations
+ * where logging is reasonable.
+ */
+ DB_ASSERT(!F_ISSET(dbp, DB_AM_RECOVER));
+
+ memset(&fid_dbt, 0, sizeof(fid_dbt));
+ memset(&r_name, 0, sizeof(r_name));
+ if (fnp->name_off != INVALID_ROFF) {
+ r_name.data = R_ADDR(&dblp->reginfo, fnp->name_off);
+ r_name.size = (u_int32_t)strlen((char *)r_name.data) + 1;
+ }
+ fid_dbt.data = dbp->fileid;
+ fid_dbt.size = DB_FILE_ID_LEN;
+ if ((ret = __dbreg_register_log(dbenv, txn, &unused, 0, LOG_OPEN,
+ r_name.size == 0 ? NULL : &r_name, &fid_dbt, id, fnp->s_type,
+ fnp->meta_pgno, fnp->create_txnid)) != 0)
+ goto err;
+
+ DB_ASSERT(dbp->type == fnp->s_type);
+ DB_ASSERT(dbp->meta_pgno == fnp->meta_pgno);
+
+ if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0)
+ goto err;
+
+err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ return (ret);
+}
+
+/*
+ * __dbreg_assign_id --
+ * Assign a particular dbreg id to this database handle.
+ *
+ * PUBLIC: int __dbreg_assign_id __P((DB *, int32_t));
+ */
+int
+__dbreg_assign_id(dbp, id)
+ DB *dbp;
+ int32_t id;
+{
+ DB *close_dbp;
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ FNAME *close_fnp, *fnp;
+ LOG *lp;
+ int ret;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ fnp = dbp->log_filename;
+
+ close_dbp = NULL;
+ close_fnp = NULL;
+
+ /* The fq_mutex protects the FNAME list and id management. */
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+
+ /* We should only call this on DB handles that have no ID. */
+ DB_ASSERT(fnp->id == DB_LOGFILEID_INVALID);
+
+ /*
+ * Make sure there isn't already a file open with this ID. There can
+ * be in recovery, if we're recovering across a point where an ID got
+ * reused.
+ */
+ if (__dbreg_id_to_fname(dblp, id, 1, &close_fnp) == 0) {
+ /*
+ * We want to save off any dbp we have open with this id.
+ * We can't safely close it now, because we hold the fq_mutex,
+ * but we should be able to rely on it being open in this
+ * process, and we're running recovery, so no other thread
+ * should muck with it if we just put off closing it until
+ * we're ready to return.
+ *
+ * Once we have the dbp, revoke its id; we're about to
+ * reuse it.
+ */
+ ret = __dbreg_id_to_db_int(dbenv, NULL, &close_dbp, id, 0, 0);
+ if (ret == ENOENT) {
+ ret = 0;
+ goto cont;
+ } else if (ret != 0)
+ goto err;
+
+ if ((ret = __dbreg_revoke_id(close_dbp, 1)) != 0)
+ goto err;
+ }
+
+ /*
+ * Remove this ID from the free list, if it's there, and make sure
+ * we don't allocate it anew.
+ */
+cont: if ((ret = __dbreg_pluck_id(dbenv, id)) != 0)
+ goto err;
+ if (id >= lp->fid_max)
+ lp->fid_max = id + 1;
+
+ /* Now go ahead and assign the id to our dbp. */
+ fnp->id = id;
+ SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
+
+ if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0)
+ goto err;
+
+err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+
+ /* There's nothing useful that our caller can do if this close fails. */
+ if (close_dbp != NULL)
+ (void)close_dbp->close(close_dbp, DB_NOSYNC);
+
+ return (ret);
+}
+
+/*
+ * __dbreg_revoke_id --
+ * Take a log id away from a dbp, in preparation for closing it,
+ * but without logging the close.
+ *
+ * PUBLIC: int __dbreg_revoke_id __P((DB *, int));
+ */
+int
+__dbreg_revoke_id(dbp, have_lock)
+ DB *dbp;
+ int have_lock;
+{
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ FNAME *fnp;
+ LOG *lp;
+ int32_t id;
+ int ret;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ fnp = dbp->log_filename;
+
+ /* If we lack an ID, this is a null-op. */
+ if (fnp == NULL || fnp->id == DB_LOGFILEID_INVALID)
+ return (0);
+
+ if (!have_lock)
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+
+ id = fnp->id;
+ fnp->id = DB_LOGFILEID_INVALID;
+
+ /* Remove the FNAME from the list of open files. */
+ SH_TAILQ_REMOVE(&lp->fq, fnp, q, __fname);
+
+ /* Remove this id from the dbentry table. */
+ __dbreg_rem_dbentry(dblp, id);
+
+ /* Push this id onto the free list. */
+ ret = __dbreg_push_id(dbenv, id);
+
+ if (!have_lock)
+ MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ return (ret);
+}
+
+/*
+ * __dbreg_close_id --
+ * Take a dbreg id away from a dbp that we're closing, and log
+ * the unregistry.
+ *
+ * PUBLIC: int __dbreg_close_id __P((DB *, DB_TXN *));
+ */
+int
+__dbreg_close_id(dbp, txn)
+ DB *dbp;
+ DB_TXN *txn;
+{
+ DBT fid_dbt, r_name, *dbtp;
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ DB_LSN r_unused;
+ FNAME *fnp;
+ LOG *lp;
+ int ret;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ fnp = dbp->log_filename;
+
+ /* If we lack an ID, this is a null-op. */
+ if (fnp == NULL || fnp->id == DB_LOGFILEID_INVALID)
+ return (0);
+
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+
+ if (fnp->name_off == INVALID_ROFF)
+ dbtp = NULL;
+ else {
+ memset(&r_name, 0, sizeof(r_name));
+ r_name.data = R_ADDR(&dblp->reginfo, fnp->name_off);
+ r_name.size =
+ (u_int32_t)strlen((char *)r_name.data) + 1;
+ dbtp = &r_name;
+ }
+ memset(&fid_dbt, 0, sizeof(fid_dbt));
+ fid_dbt.data = fnp->ufid;
+ fid_dbt.size = DB_FILE_ID_LEN;
+ if ((ret = __dbreg_register_log(dbenv, txn,
+ &r_unused, 0, LOG_CLOSE, dbtp, &fid_dbt, fnp->id,
+ fnp->s_type, fnp->meta_pgno, TXN_INVALID)) != 0)
+ goto err;
+
+ ret = __dbreg_revoke_id(dbp, 1);
+
+err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ return (ret);
+}
diff --git a/bdb/dbreg/dbreg.src b/bdb/dbreg/dbreg.src
new file mode 100644
index 00000000000..18429471e82
--- /dev/null
+++ b/bdb/dbreg/dbreg.src
@@ -0,0 +1,49 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: dbreg.src,v 10.22 2002/03/27 04:31:44 bostic Exp $
+ */
+
+PREFIX __dbreg
+DBPRIVATE
+
+INCLUDE #include "db_config.h"
+INCLUDE
+INCLUDE #ifndef NO_SYSTEM_INCLUDES
+INCLUDE #include <sys/types.h>
+INCLUDE
+INCLUDE #include <ctype.h>
+INCLUDE #include <string.h>
+INCLUDE #endif
+INCLUDE
+INCLUDE #include "db_int.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
+INCLUDE
+
+/*
+ * Used for registering name/id translations at open or close.
+ * opcode: register or unregister
+ * name: file name
+ * fileid: unique file id
+ * ftype: file type
+ * ftype: database type
+ * id: transaction id of the subtransaction that created the fs object
+ */
+BEGIN register 2
+ARG opcode u_int32_t lu
+DBT name DBT s
+DBT uid DBT s
+ARG fileid int32_t ld
+ARG ftype DBTYPE lx
+ARG meta_pgno db_pgno_t lu
+ARG id u_int32_t lx
+END
diff --git a/bdb/dbreg/dbreg_rec.c b/bdb/dbreg/dbreg_rec.c
new file mode 100644
index 00000000000..ba3ba0e06d9
--- /dev/null
+++ b/bdb/dbreg/dbreg_rec.c
@@ -0,0 +1,362 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1995, 1996
+ * The President and Fellows of Harvard University. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: dbreg_rec.c,v 11.108 2002/08/14 20:04:25 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+static int __dbreg_open_file __P((DB_ENV *,
+ DB_TXN *, __dbreg_register_args *, void *));
+
+/*
+ * PUBLIC: int __dbreg_register_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ DB_ENTRY *dbe;
+ DB_LOG *dblp;
+ DB *dbp;
+ __dbreg_register_args *argp;
+ int do_close, do_open, do_rem, ret, t_ret;
+
+ dblp = dbenv->lg_handle;
+ dbp = NULL;
+
+#ifdef DEBUG_RECOVER
+ REC_PRINT(__dbreg_register_print);
+#endif
+ do_open = do_close = 0;
+ if ((ret = __dbreg_register_read(dbenv, dbtp->data, &argp)) != 0)
+ goto out;
+
+ switch (argp->opcode) {
+ case LOG_OPEN:
+ if ((DB_REDO(op) ||
+ op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES))
+ do_open = 1;
+ else
+ do_close = 1;
+ break;
+
+ case LOG_CLOSE:
+ if (DB_UNDO(op))
+ do_open = 1;
+ else
+ do_close = 1;
+ break;
+ case LOG_RCLOSE:
+ /*
+ * LOG_RCLOSE was generated by recover because a file
+ * was left open. The POPENFILES pass, which is run
+ * to open files to abort prepared transactions,
+ * may not include the open for this file so we
+ * open it here. Note that a normal CLOSE is
+ * not legal before the prepared transaction is
+ * committed or aborted.
+ */
+ if (DB_UNDO(op) || op == DB_TXN_POPENFILES)
+ do_open = 1;
+ else
+ do_close = 1;
+ break;
+
+ case LOG_CHECKPOINT:
+ if (DB_UNDO(op) ||
+ op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES)
+ do_open = 1;
+ break;
+ }
+
+ if (do_open) {
+ /*
+ * We must open the db even if the meta page is not
+ * yet written as we may be creating subdatabase.
+ */
+ if (op == DB_TXN_OPENFILES && argp->opcode != LOG_CHECKPOINT)
+ F_SET(dblp, DBLOG_FORCE_OPEN);
+
+ /*
+ * During an abort or an open pass to recover prepared txns,
+ * we need to make sure that we use the same locker id on the
+ * open. We pass the txnid along to ensure this.
+ */
+ ret = __dbreg_open_file(dbenv,
+ op == DB_TXN_ABORT || op == DB_TXN_POPENFILES ?
+ argp->txnid : NULL, argp, info);
+ if (ret == ENOENT || ret == EINVAL) {
+ /*
+ * If this is an OPEN while rolling forward, it's
+ * possible that the file was recreated since last
+ * time we got here. In that case, we've got deleted
+ * set and probably shouldn't, so we need to check
+ * for that case and possibly retry.
+ */
+ if (op == DB_TXN_FORWARD_ROLL &&
+ argp->txnid != 0 &&
+ dblp->dbentry[argp->fileid].deleted) {
+ dblp->dbentry[argp->fileid].deleted = 0;
+ ret =
+ __dbreg_open_file(dbenv, NULL, argp, info);
+ }
+ ret = 0;
+ }
+ F_CLR(dblp, DBLOG_FORCE_OPEN);
+ }
+
+ if (do_close) {
+ /*
+ * If we are undoing an open, or redoing a close,
+ * then we need to close the file.
+ *
+ * If the file is deleted, then we can just ignore this close.
+ * Otherwise, we should usually have a valid dbp we should
+ * close or whose reference count should be decremented.
+ * However, if we shut down without closing a file, we may, in
+ * fact, not have the file open, and that's OK.
+ */
+ do_rem = 0;
+ MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ if (argp->fileid < dblp->dbentry_cnt) {
+ /*
+ * Typically, closes should match an open which means
+ * that if this is a close, there should be a valid
+ * entry in the dbentry table when we get here,
+ * however there is an exception. If this is an
+ * OPENFILES pass, then we may have started from
+ * a log file other than the first, and the
+ * corresponding open appears in an earlier file.
+ * We can ignore that case, but all others are errors.
+ */
+ dbe = &dblp->dbentry[argp->fileid];
+ if (dbe->dbp == NULL && !dbe->deleted) {
+ /* No valid entry here. */
+ if ((argp->opcode != LOG_CLOSE &&
+ argp->opcode != LOG_RCLOSE) ||
+ (op != DB_TXN_OPENFILES &&
+ op !=DB_TXN_POPENFILES)) {
+ __db_err(dbenv,
+ "Improper file close at %lu/%lu",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset);
+ ret = EINVAL;
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ goto done;
+ }
+
+ /* We have either an open entry or a deleted entry. */
+ if ((dbp = dbe->dbp) != NULL) {
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ (void)__dbreg_revoke_id(dbp, 0);
+
+ /*
+ * If we're a replication client, it's
+ * possible to get here with a dbp that
+ * the user opened, but which we later
+ * assigned a fileid to. Be sure that
+ * we only close dbps that we opened in
+ * the recovery code; they should have
+ * DB_AM_RECOVER set.
+ *
+ * The only exception is if we're aborting
+ * in a normal environment; then we might
+ * get here with a non-AM_RECOVER database.
+ */
+ if (F_ISSET(dbp, DB_AM_RECOVER) ||
+ op == DB_TXN_ABORT)
+ do_rem = 1;
+ } else if (dbe->deleted) {
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ __dbreg_rem_dbentry(dblp, argp->fileid);
+ }
+ } else
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ if (do_rem) {
+ /*
+ * If we are undoing a create we'd better discard
+ * any buffers from the memory pool.
+ */
+ if (dbp != NULL && dbp->mpf != NULL && argp->id != 0) {
+ if ((ret = dbp->mpf->close(dbp->mpf,
+ DB_MPOOL_DISCARD)) != 0)
+ goto out;
+ dbp->mpf = NULL;
+ }
+
+ /*
+ * During recovery, all files are closed. On an abort,
+ * we only close the file if we opened it during the
+ * abort (DB_AM_RECOVER set), otherwise we simply do
+ * a __db_refresh. For the close case, if remove or
+ * rename has closed the file, don't request a sync,
+ * because the NULL mpf would be a problem.
+ */
+ if (dbp != NULL) {
+ if (op == DB_TXN_ABORT &&
+ !F_ISSET(dbp, DB_AM_RECOVER))
+ t_ret =
+ __db_refresh(dbp, NULL, DB_NOSYNC);
+ else
+ t_ret = dbp->close(dbp, DB_NOSYNC);
+ if (t_ret != 0 && ret == 0)
+ ret = t_ret;
+ }
+ }
+ }
+done: if (ret == 0)
+ *lsnp = argp->prev_lsn;
+out: if (argp != NULL)
+ __os_free(dbenv, argp);
+ return (ret);
+}
+
+/*
+ * __dbreg_open_file --
+ * Called during log_register recovery. Make sure that we have an
+ * entry in the dbentry table for this ndx. Returns 0 on success,
+ * non-zero on error.
+ */
+static int
+__dbreg_open_file(dbenv, txn, argp, info)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ __dbreg_register_args *argp;
+ void *info;
+{
+ DB_ENTRY *dbe;
+ DB_LOG *lp;
+ DB *dbp;
+ u_int32_t id;
+
+ lp = (DB_LOG *)dbenv->lg_handle;
+ /*
+ * We never re-open temporary files. Temp files are only
+ * useful during aborts in which case the dbp was entered
+ * when the file was registered. During recovery, we treat
+ * temp files as properly deleted files, allowing the open to
+ * fail and not reporting any errors when recovery fails to
+ * get a valid dbp from __dbreg_id_to_db.
+ */
+ if (argp->name.size == 0) {
+ (void)__dbreg_add_dbentry(dbenv, lp, NULL, argp->fileid);
+ return (ENOENT);
+ }
+
+ /*
+ * When we're opening, we have to check that the name we are opening
+ * is what we expect. If it's not, then we close the old file and
+ * open the new one.
+ */
+ MUTEX_THREAD_LOCK(dbenv, lp->mutexp);
+ if (argp->fileid < lp->dbentry_cnt)
+ dbe = &lp->dbentry[argp->fileid];
+ else
+ dbe = NULL;
+
+ if (dbe != NULL) {
+ if (dbe->deleted) {
+ MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+ return (ENOENT);
+ }
+ if ((dbp = dbe->dbp) != NULL) {
+ if (dbp->meta_pgno != argp->meta_pgno ||
+ memcmp(dbp->fileid,
+ argp->uid.data, DB_FILE_ID_LEN) != 0) {
+ MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+ (void)__dbreg_revoke_id(dbp, 0);
+ if (F_ISSET(dbp, DB_AM_RECOVER))
+ dbp->close(dbp, DB_NOSYNC);
+ goto reopen;
+ }
+
+ /*
+ * We should only get here if we already have the
+ * dbp from an openfiles pass, in which case, what's
+ * here had better be the same dbp.
+ */
+ DB_ASSERT(dbe->dbp == dbp);
+ MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+
+ /*
+ * This is a successful open. We need to record that
+ * in the txnlist so that we know how to handle the
+ * subtransaction that created the file system object.
+ */
+ if (argp->id != TXN_INVALID &&
+ __db_txnlist_update(dbenv, info,
+ argp->id, TXN_EXPECTED, NULL) == TXN_NOTFOUND)
+ (void)__db_txnlist_add(dbenv,
+ info, argp->id, TXN_EXPECTED, NULL);
+ return (0);
+ }
+ }
+
+ MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+
+ /*
+ * We are about to pass a recovery txn pointer into the main library.
+ * We need to make sure that any accessed fields are set appropriately.
+ */
+reopen: if (txn != NULL) {
+ id = txn->txnid;
+ memset(txn, 0, sizeof(DB_TXN));
+ txn->txnid = id;
+ txn->mgrp = dbenv->tx_handle;
+ }
+
+ return (__dbreg_do_open(dbenv, txn, lp, argp->uid.data, argp->name.data,
+ argp->ftype, argp->fileid, argp->meta_pgno, info, argp->id));
+}
diff --git a/bdb/dbreg/dbreg_util.c b/bdb/dbreg/dbreg_util.c
new file mode 100644
index 00000000000..0db5c640adb
--- /dev/null
+++ b/bdb/dbreg/dbreg_util.c
@@ -0,0 +1,797 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: dbreg_util.c,v 11.22 2002/09/10 02:43:10 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+static int __dbreg_check_master __P((DB_ENV *, u_int8_t *, char *));
+
+/*
+ * __dbreg_add_dbentry --
+ * Adds a DB entry to the dbreg DB entry table.
+ *
+ * PUBLIC: int __dbreg_add_dbentry __P((DB_ENV *, DB_LOG *, DB *, int32_t));
+ */
+int
+__dbreg_add_dbentry(dbenv, dblp, dbp, ndx)
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ DB *dbp;
+ int32_t ndx;
+{
+ int32_t i;
+ int ret;
+
+ ret = 0;
+
+ MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+
+ /*
+ * Check if we need to grow the table. Note, ndx is 0-based (the
+ * index into the DB entry table) an dbentry_cnt is 1-based, the
+ * number of available slots.
+ */
+ if (dblp->dbentry_cnt <= ndx) {
+ if ((ret = __os_realloc(dbenv,
+ (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
+ &dblp->dbentry)) != 0)
+ goto err;
+
+ /* Initialize the new entries. */
+ for (i = dblp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) {
+ dblp->dbentry[i].dbp = NULL;
+ dblp->dbentry[i].deleted = 0;
+ }
+ dblp->dbentry_cnt = i;
+ }
+
+ DB_ASSERT(dblp->dbentry[ndx].dbp == NULL);
+ dblp->dbentry[ndx].deleted = dbp == NULL;
+ dblp->dbentry[ndx].dbp = dbp;
+
+err: MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ return (ret);
+}
+
+/*
+ * __dbreg_rem_dbentry
+ * Remove an entry from the DB entry table.
+ *
+ * PUBLIC: void __dbreg_rem_dbentry __P((DB_LOG *, int32_t));
+ */
+void
+__dbreg_rem_dbentry(dblp, ndx)
+ DB_LOG *dblp;
+ int32_t ndx;
+{
+ MUTEX_THREAD_LOCK(dblp->dbenv, dblp->mutexp);
+ dblp->dbentry[ndx].dbp = NULL;
+ dblp->dbentry[ndx].deleted = 0;
+ MUTEX_THREAD_UNLOCK(dblp->dbenv, dblp->mutexp);
+}
+
+/*
+ * __dbreg_open_files --
+ * Put a LOG_CHECKPOINT log record for each open database.
+ *
+ * PUBLIC: int __dbreg_open_files __P((DB_ENV *));
+ */
+int
+__dbreg_open_files(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_LOG *dblp;
+ DB_LSN r_unused;
+ DBT *dbtp, fid_dbt, t;
+ FNAME *fnp;
+ LOG *lp;
+ int ret;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ ret = 0;
+
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+
+ for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
+ fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ if (fnp->name_off == INVALID_ROFF)
+ dbtp = NULL;
+ else {
+ memset(&t, 0, sizeof(t));
+ t.data = R_ADDR(&dblp->reginfo, fnp->name_off);
+ t.size = (u_int32_t)strlen(t.data) + 1;
+ dbtp = &t;
+ }
+ memset(&fid_dbt, 0, sizeof(fid_dbt));
+ fid_dbt.data = fnp->ufid;
+ fid_dbt.size = DB_FILE_ID_LEN;
+ /*
+ * Output LOG_CHECKPOINT records which will be
+ * processed during the OPENFILES pass of recovery.
+ * At the end of recovery we want to output the
+ * files that were open so that a future recovery
+ * run will have the correct files open during
+ * a backward pass. For this we output LOG_RCLOSE
+ * records so that the files will be closed on
+ * the forward pass.
+ */
+ if ((ret = __dbreg_register_log(dbenv,
+ NULL, &r_unused, 0,
+ F_ISSET(dblp, DBLOG_RECOVER) ? LOG_RCLOSE : LOG_CHECKPOINT,
+ dbtp, &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno,
+ TXN_INVALID)) != 0)
+ break;
+ }
+
+ MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+
+ return (ret);
+}
+
+/*
+ * __dbreg_close_files --
+ * Close files that were opened by the recovery daemon. We sync the
+ * file, unless its mpf pointer has been NULLed by a db_remove or
+ * db_rename. We may not have flushed the log_register record that
+ * closes the file.
+ *
+ * PUBLIC: int __dbreg_close_files __P((DB_ENV *));
+ */
+int
+__dbreg_close_files(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_LOG *dblp;
+ DB *dbp;
+ int ret, t_ret;
+ int32_t i;
+
+ /* If we haven't initialized logging, we have nothing to do. */
+ if (!LOGGING_ON(dbenv))
+ return (0);
+
+ dblp = dbenv->lg_handle;
+ ret = 0;
+ MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ for (i = 0; i < dblp->dbentry_cnt; i++) {
+ /* We only want to close dbps that recovery opened. */
+ if ((dbp = dblp->dbentry[i].dbp) != NULL &&
+ F_ISSET(dbp, DB_AM_RECOVER)) {
+ /*
+ * It's unsafe to call DB->close while holding the
+ * thread lock, because we'll call __dbreg_rem_dbentry
+ * and grab it again.
+ *
+ * Just drop it. Since dbreg ids go monotonically
+ * upward, concurrent opens should be safe, and the
+ * user should have no business closing files while
+ * we're in this loop anyway--we're in the process of
+ * making all outstanding dbps invalid.
+ */
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ if ((t_ret = dbp->close(dbp,
+ dbp->mpf == NULL ? DB_NOSYNC : 0)) != 0 && ret == 0)
+ ret = t_ret;
+ MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ }
+ dblp->dbentry[i].deleted = 0;
+ dblp->dbentry[i].dbp = NULL;
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ return (ret);
+}
+
+/*
+ * __dbreg_nofiles --
+ * Check that there are no open files in the process local table.
+ * Returns 0 if there are no files and EINVAL if there are any.
+ *
+ * PUBLIC: int __dbreg_nofiles __P((DB_ENV *));
+ */
+int
+__dbreg_nofiles(dbenv)
+ DB_ENV *dbenv;
+{
+ DB *dbp;
+ DB_LOG *dblp;
+ int ret;
+ int32_t i;
+
+ /* If we haven't initialized logging, we have nothing to do. */
+ if (!LOGGING_ON(dbenv))
+ return (0);
+
+ dblp = dbenv->lg_handle;
+ ret = 0;
+ MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ for (i = 0; i < dblp->dbentry_cnt; i++) {
+ if ((dbp = dblp->dbentry[i].dbp) != NULL &&
+ !F_ISSET(dbp, DB_AM_RECOVER)) {
+ ret = EINVAL;
+ break;
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ return (ret);
+}
+
+/*
+ * __dbreg_id_to_db --
+ * Return the DB corresponding to the specified dbreg id.
+ *
+ * PUBLIC: int __dbreg_id_to_db __P((DB_ENV *, DB_TXN *, DB **, int32_t, int));
+ */
+int
+__dbreg_id_to_db(dbenv, txn, dbpp, ndx, inc)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB **dbpp;
+ int32_t ndx;
+ int inc;
+{
+ return (__dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, 1));
+}
+
+/*
+ * __dbreg_id_to_db_int --
+ * Return the DB corresponding to the specified dbreg id. The internal
+ * version takes a final parameter that indicates whether we should attempt
+ * to open the file if no mapping is found. During recovery, the recovery
+ * routines all want to try to open the file (and this is called from
+ * __dbreg_id_to_db), however, if we have a multi-process environment where
+ * some processes may not have the files open (e.g., XA), then we also get
+ * called from __dbreg_assign_id and it's OK if there is no mapping.
+ *
+ * PUBLIC: int __dbreg_id_to_db_int __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, DB **, int32_t, int, int));
+ */
+int
+__dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB **dbpp;
+ int32_t ndx;
+ int inc, tryopen;
+{
+ DB_LOG *dblp;
+ FNAME *fname;
+ int ret;
+ char *name;
+
+ ret = 0;
+ dblp = dbenv->lg_handle;
+ COMPQUIET(inc, 0);
+
+ MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+
+ /*
+ * Under XA, a process different than the one issuing DB operations
+ * may abort a transaction. In this case, the "recovery" routines
+ * are run by a process that does not necessarily have the file open,
+ * so we we must open the file explicitly.
+ */
+ if (ndx >= dblp->dbentry_cnt ||
+ (!dblp->dbentry[ndx].deleted && dblp->dbentry[ndx].dbp == NULL)) {
+ if (!tryopen || F_ISSET(dblp, DBLOG_RECOVER)) {
+ ret = ENOENT;
+ goto err;
+ }
+
+ /*
+ * __dbreg_id_to_fname acquires the region's fq_mutex,
+ * which we can't safely acquire while we hold the thread lock.
+ * We no longer need it anyway--the dbentry table didn't
+ * have what we needed.
+ */
+ MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+
+ if (__dbreg_id_to_fname(dblp, ndx, 0, &fname) != 0)
+ /*
+ * With transactional opens, we may actually have
+ * closed this file in the transaction in which
+ * case this will fail too. Then it's up to the
+ * caller to reopen the file.
+ */
+ return (ENOENT);
+
+ /*
+ * Note that we're relying on fname not to change, even
+ * though we released the mutex that protects it (fq_mutex)
+ * inside __dbreg_id_to_fname. This should be a safe
+ * assumption, because the other process that has the file
+ * open shouldn't be closing it while we're trying to abort.
+ */
+ name = R_ADDR(&dblp->reginfo, fname->name_off);
+
+ /*
+ * At this point, we are not holding the thread lock, so exit
+ * directly instead of going through the exit code at the
+ * bottom. If the __dbreg_do_open succeeded, then we don't need
+ * to do any of the remaining error checking at the end of this
+ * routine.
+ * XXX I am sending a NULL txnlist and 0 txnid which may be
+ * completely broken ;(
+ */
+ if ((ret = __dbreg_do_open(dbenv, txn, dblp,
+ fname->ufid, name, fname->s_type,
+ ndx, fname->meta_pgno, NULL, 0)) != 0)
+ return (ret);
+
+ *dbpp = dblp->dbentry[ndx].dbp;
+ return (0);
+ }
+
+ /*
+ * Return DB_DELETED if the file has been deleted (it's not an error).
+ */
+ if (dblp->dbentry[ndx].deleted) {
+ ret = DB_DELETED;
+ goto err;
+ }
+
+ /* It's an error if we don't have a corresponding writeable DB. */
+ if ((*dbpp = dblp->dbentry[ndx].dbp) == NULL)
+ ret = ENOENT;
+
+err: MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ return (ret);
+}
+
+/*
+ * __dbreg_id_to_fname --
+ * Traverse the shared-memory region looking for the entry that
+ * matches the passed dbreg id. Returns 0 on success; -1 on error.
+ *
+ * PUBLIC: int __dbreg_id_to_fname __P((DB_LOG *, int32_t, int, FNAME **));
+ */
+int
+__dbreg_id_to_fname(dblp, lid, have_lock, fnamep)
+ DB_LOG *dblp;
+ int32_t lid;
+ int have_lock;
+ FNAME **fnamep;
+{
+ DB_ENV *dbenv;
+ FNAME *fnp;
+ LOG *lp;
+ int ret;
+
+ dbenv = dblp->dbenv;
+ lp = dblp->reginfo.primary;
+
+ ret = -1;
+
+ if (!have_lock)
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
+ fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ if (fnp->id == lid) {
+ *fnamep = fnp;
+ ret = 0;
+ break;
+ }
+ }
+ if (!have_lock)
+ MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+
+ return (ret);
+}
+/*
+ * __dbreg_fid_to_fname --
+ * Traverse the shared-memory region looking for the entry that
+ * matches the passed file unique id. Returns 0 on success; -1 on error.
+ *
+ * PUBLIC: int __dbreg_fid_to_fname __P((DB_LOG *, u_int8_t *, int, FNAME **));
+ */
+int
+__dbreg_fid_to_fname(dblp, fid, have_lock, fnamep)
+ DB_LOG *dblp;
+ u_int8_t *fid;
+ int have_lock;
+ FNAME **fnamep;
+{
+ DB_ENV *dbenv;
+ FNAME *fnp;
+ LOG *lp;
+ int ret;
+
+ dbenv = dblp->dbenv;
+ lp = dblp->reginfo.primary;
+
+ ret = -1;
+
+ if (!have_lock)
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
+ fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ if (memcmp(fnp->ufid, fid, DB_FILE_ID_LEN) == 0) {
+ *fnamep = fnp;
+ ret = 0;
+ break;
+ }
+ }
+ if (!have_lock)
+ MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+
+ return (ret);
+}
+
+/*
+ * __dbreg_get_name
+ *
+ * Interface to get name of registered files. This is mainly diagnostic
+ * and the name passed could be transient unless there is something
+ * ensuring that the file cannot be closed.
+ *
+ * PUBLIC: int __dbreg_get_name __P((DB_ENV *, u_int8_t *, char **));
+ */
+int
+__dbreg_get_name(dbenv, fid, namep)
+ DB_ENV *dbenv;
+ u_int8_t *fid;
+ char **namep;
+{
+ DB_LOG *dblp;
+ FNAME *fname;
+
+ dblp = dbenv->lg_handle;
+
+ if (dblp != NULL && __dbreg_fid_to_fname(dblp, fid, 0, &fname) == 0) {
+ *namep = R_ADDR(&dblp->reginfo, fname->name_off);
+ return (0);
+ }
+
+ return (-1);
+}
+
+/*
+ * __dbreg_do_open --
+ * Open files referenced in the log. This is the part of the open that
+ * is not protected by the thread mutex.
+ * PUBLIC: int __dbreg_do_open __P((DB_ENV *, DB_TXN *, DB_LOG *, u_int8_t *,
+ * PUBLIC: char *, DBTYPE, int32_t, db_pgno_t, void *, u_int32_t));
+ */
+int
+__dbreg_do_open(dbenv,
+ txn, lp, uid, name, ftype, ndx, meta_pgno, info, id)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB_LOG *lp;
+ u_int8_t *uid;
+ char *name;
+ DBTYPE ftype;
+ int32_t ndx;
+ db_pgno_t meta_pgno;
+ void *info;
+ u_int32_t id;
+{
+ DB *dbp;
+ int ret;
+ u_int32_t cstat;
+
+ if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0)
+ return (ret);
+
+ /*
+ * We can open files under a number of different scenarios.
+ * First, we can open a file during a normal txn_abort, if that file
+ * was opened and closed during the transaction (as is the master
+ * database of a sub-database).
+ * Second, we might be aborting a transaction in XA and not have
+ * it open in the process that is actually doing the abort.
+ * Third, we might be in recovery.
+ * In case 3, there is no locking, so there is no issue.
+ * In cases 1 and 2, we are guaranteed to already hold any locks
+ * that we need, since we're still in the same transaction, so by
+ * setting DB_AM_RECOVER, we guarantee that we don't log and that
+ * we don't try to acquire locks on behalf of a different locker id.
+ */
+ F_SET(dbp, DB_AM_RECOVER);
+ if (meta_pgno != PGNO_BASE_MD) {
+ memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
+ dbp->meta_pgno = meta_pgno;
+ }
+ dbp->type = ftype;
+ if ((ret = __db_dbopen(dbp, txn, name, NULL,
+ DB_ODDFILESIZE, __db_omode("rw----"), meta_pgno)) == 0) {
+
+ /*
+ * Verify that we are opening the same file that we were
+ * referring to when we wrote this log record.
+ */
+ if ((meta_pgno != PGNO_BASE_MD &&
+ __dbreg_check_master(dbenv, uid, name) != 0) ||
+ memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
+ cstat = TXN_IGNORE;
+ else
+ cstat = TXN_EXPECTED;
+
+ /* Assign the specific dbreg id to this dbp. */
+ if ((ret = __dbreg_assign_id(dbp, ndx)) != 0)
+ goto err;
+
+ /*
+ * If we successfully opened this file, then we need to
+ * convey that information to the txnlist so that we
+ * know how to handle the subtransaction that created
+ * the file system object.
+ */
+ if (id != TXN_INVALID) {
+ if ((ret = __db_txnlist_update(dbenv,
+ info, id, cstat, NULL)) == TXN_NOTFOUND)
+ ret = __db_txnlist_add(dbenv,
+ info, id, cstat, NULL);
+ else if (ret > 0)
+ ret = 0;
+ }
+err: if (cstat == TXN_IGNORE)
+ goto not_right;
+ return (ret);
+ } else {
+ /* Record that the open failed in the txnlist. */
+ if (id != TXN_INVALID && (ret = __db_txnlist_update(dbenv,
+ info, id, TXN_UNEXPECTED, NULL)) == TXN_NOTFOUND)
+ ret = __db_txnlist_add(dbenv,
+ info, id, TXN_UNEXPECTED, NULL);
+ }
+not_right:
+ (void)dbp->close(dbp, 0);
+ /* Add this file as deleted. */
+ (void)__dbreg_add_dbentry(dbenv, lp, NULL, ndx);
+ return (ENOENT);
+}
+
+static int
+__dbreg_check_master(dbenv, uid, name)
+ DB_ENV *dbenv;
+ u_int8_t *uid;
+ char *name;
+{
+ DB *dbp;
+ int ret;
+
+ ret = 0;
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return (ret);
+ dbp->type = DB_BTREE;
+ F_SET(dbp, DB_AM_RECOVER);
+ ret = __db_dbopen(dbp,
+ NULL, name, NULL, 0, __db_omode("rw----"), PGNO_BASE_MD);
+
+ if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
+ ret = EINVAL;
+
+ (void)dbp->close(dbp, 0);
+ return (ret);
+}
+
+/*
+ * __dbreg_lazy_id --
+ * When a replication client gets upgraded to being a replication master,
+ * it may have database handles open that have not been assigned an ID, but
+ * which have become legal to use for logging.
+ *
+ * This function lazily allocates a new ID for such a function, in a
+ * new transaction created for the purpose. We need to do this in a new
+ * transaction because we definitely wish to commit the dbreg_register, but
+ * at this point we have no way of knowing whether the log record that incited
+ * us to call this will be part of a committed transaction.
+ *
+ * PUBLIC: int __dbreg_lazy_id __P((DB *));
+ */
+int
+__dbreg_lazy_id(dbp)
+ DB *dbp;
+{
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ int ret;
+
+ dbenv = dbp->dbenv;
+
+ DB_ASSERT(F_ISSET(dbenv, DB_ENV_REP_MASTER));
+
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
+ return (ret);
+
+ if ((ret = __dbreg_new_id(dbp, txn)) != 0) {
+ (void)txn->abort(txn);
+ return (ret);
+ }
+
+ return (txn->commit(txn, DB_TXN_NOSYNC));
+}
+
+/*
+ * __dbreg_push_id and __dbreg_pop_id --
+ * Dbreg ids from closed files are kept on a stack in shared memory
+ * for recycling. (We want to reuse them as much as possible because each
+ * process keeps open files in an array by ID.) Push them to the stack and
+ * pop them from it, managing memory as appropriate.
+ *
+ * The stack is protected by the fq_mutex, and in both functions we assume
+ * that this is already locked.
+ *
+ * PUBLIC: int __dbreg_push_id __P((DB_ENV *, int32_t));
+ * PUBLIC: int __dbreg_pop_id __P((DB_ENV *, int32_t *));
+ */
+int
+__dbreg_push_id(dbenv, id)
+ DB_ENV *dbenv;
+ int32_t id;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+ int32_t *stack, *newstack;
+ int ret;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ if (lp->free_fid_stack != INVALID_ROFF)
+ stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
+ else
+ stack = NULL;
+
+ /* Check if we have room on the stack. */
+ if (lp->free_fids_alloced <= lp->free_fids + 1) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ if ((ret = __db_shalloc(dblp->reginfo.addr,
+ (lp->free_fids_alloced + 20) * sizeof(u_int32_t), 0,
+ &newstack)) != 0) {
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (ret);
+ }
+
+ memcpy(newstack, stack,
+ lp->free_fids_alloced * sizeof(u_int32_t));
+ lp->free_fid_stack = R_OFFSET(&dblp->reginfo, newstack);
+ lp->free_fids_alloced += 20;
+
+ if (stack != NULL)
+ __db_shalloc_free(dblp->reginfo.addr, stack);
+
+ stack = newstack;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ }
+
+ DB_ASSERT(stack != NULL);
+ stack[lp->free_fids++] = id;
+ return (0);
+}
+
+int
+__dbreg_pop_id(dbenv, id)
+ DB_ENV *dbenv;
+ int32_t *id;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+ int32_t *stack;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ /* Do we have anything to pop? */
+ if (lp->free_fid_stack != INVALID_ROFF && lp->free_fids > 0) {
+ stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
+ *id = stack[--lp->free_fids];
+ } else
+ *id = DB_LOGFILEID_INVALID;
+
+ return (0);
+}
+
+/*
+ * __dbreg_pluck_id --
+ * Remove a particular dbreg id from the stack of free ids. This is
+ * used when we open a file, as in recovery, with a specific ID that might
+ * be on the stack.
+ *
+ * Returns success whether or not the particular id was found, and like
+ * push and pop, assumes that the fq_mutex is locked.
+ *
+ * PUBLIC: int __dbreg_pluck_id __P((DB_ENV *, int32_t));
+ */
+int
+__dbreg_pluck_id(dbenv, id)
+ DB_ENV *dbenv;
+ int32_t id;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+ int32_t *stack;
+ int i;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ /* Do we have anything to look at? */
+ if (lp->free_fid_stack != INVALID_ROFF) {
+ stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
+ for (i = 0; i < lp->free_fids; i++)
+ if (id == stack[i]) {
+ /*
+ * Found it. Overwrite it with the top
+ * id (which may harmlessly be itself),
+ * and shorten the stack by one.
+ */
+ stack[i] = stack[lp->free_fids - 1];
+ lp->free_fids--;
+ return (0);
+ }
+ }
+
+ return (0);
+}
+
+#ifdef DEBUG
+/*
+ * __dbreg_print_dblist --
+ * Display the list of files.
+ *
+ * PUBLIC: void __dbreg_print_dblist __P((DB_ENV *));
+ */
+void
+__dbreg_print_dblist(dbenv)
+ DB_ENV *dbenv;
+{
+ DB *dbp;
+ DB_LOG *dblp;
+ FNAME *fnp;
+ LOG *lp;
+ int del, first;
+ char *name;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ MUTEX_LOCK(dbenv, &lp->fq_mutex);
+
+ for (first = 1, fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
+ fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ if (first) {
+ first = 0;
+ __db_err(dbenv,
+ "ID\t\t\tName\tType\tPgno\tTxnid\tDBP-info");
+ }
+ if (fnp->name_off == INVALID_ROFF)
+ name = "";
+ else
+ name = R_ADDR(&dblp->reginfo, fnp->name_off);
+
+ dbp = fnp->id >= dblp->dbentry_cnt ? NULL :
+ dblp->dbentry[fnp->id].dbp;
+ del = fnp->id >= dblp->dbentry_cnt ? 0 :
+ dblp->dbentry[fnp->id].deleted;
+ __db_err(dbenv, "%ld\t%s\t\t\t%s\t%lu\t%lx\t%s %d %lx %lx",
+ (long)fnp->id, name,
+ __db_dbtype_to_string(fnp->s_type),
+ (u_long)fnp->meta_pgno, (u_long)fnp->create_txnid,
+ dbp == NULL ? "No DBP" : "DBP", del, P_TO_ULONG(dbp),
+ dbp == NULL ? 0 : dbp->flags);
+ }
+
+ MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+}
+#endif
diff --git a/bdb/dist/Makefile.in b/bdb/dist/Makefile.in
index 4a47953e3e1..a7cc0e11f34 100644
--- a/bdb/dist/Makefile.in
+++ b/bdb/dist/Makefile.in
@@ -1,101 +1,139 @@
-# $Id: Makefile.in,v 11.66 2000/11/27 16:27:51 bostic Exp $
+# $Id: Makefile.in,v 11.175 2002/08/29 14:22:20 margo Exp $
srcdir= @srcdir@/..
builddir=.
##################################################
-# C, C++
+# Installation directories and permissions.
##################################################
-CPPFLAGS= -I$(builddir) -I$(srcdir)/include @CPPFLAGS@
-CFLAGS= -c $(CPPFLAGS) @CFLAGS@
-CXXFLAGS= -c $(CPPFLAGS) @CXXFLAGS@
+prefix= @prefix@
+exec_prefix=@exec_prefix@
+bindir= @bindir@
+includedir=@includedir@
+libdir= @libdir@
+docdir= $(prefix)/docs
-CC= @MAKEFILE_CC@
-CCLINK= @MAKEFILE_CCLINK@
-CXX= @MAKEFILE_CXX@
+dmode= 755
+emode= 555
+fmode= 444
-INSTALLER= @INSTALLER@
+transform=@program_transform_name@
-LDFLAGS= @LDFLAGS@
-LIBDB_ARGS= @LIBDB_ARGS@
-LIBJSO_LIBS= @LIBJSO_LIBS@
-LIBS= @LIBS@
-LIBSO_LIBS= @LIBSO_LIBS@
+##################################################
+# Paths for standard user-level commands.
+##################################################
+SHELL= @db_cv_path_sh@
+ar= @db_cv_path_ar@
+chmod= @db_cv_path_chmod@
+cp= @db_cv_path_cp@
+ln= @db_cv_path_ln@
+mkdir= @db_cv_path_mkdir@
+ranlib= @db_cv_path_ranlib@
+rm= @db_cv_path_rm@
+rpm= @db_cv_path_rpm@
+strip= @db_cv_path_strip@
+
+##################################################
+# General library information.
+##################################################
+DEF_LIB= @DEFAULT_LIB@
+DEF_LIB_CXX= @DEFAULT_LIB_CXX@
+INSTALLER= @INSTALLER@
LIBTOOL= @LIBTOOL@
-LIBTSO_LIBS= @LIBTSO_LIBS@
-LIBXSO_LIBS= @LIBXSO_LIBS@
POSTLINK= @POSTLINK@
-SOLINK= @SOLINK@
+SOLINK= @MAKEFILE_SOLINK@
SOFLAGS= @SOFLAGS@
SOMAJOR= @DB_VERSION_MAJOR@
SOVERSION= @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@
-libdb= libdb.a
+##################################################
+# C API.
+##################################################
+CPPFLAGS= -I$(builddir) -I$(srcdir) -I$(srcdir)/dbinc @CPPFLAGS@
+CFLAGS= -c $(CPPFLAGS) @CFLAGS@
+CC= @MAKEFILE_CC@
+CCLINK= @MAKEFILE_CCLINK@
+
+LDFLAGS= @LDFLAGS@
+LIBS= @LIBS@
+LIBSO_LIBS= @LIBSO_LIBS@
+libdb= libdb.a
libso_base= libdb
-libso_linkname= $(libso_base)-$(SOVERSION).la
libso= $(libso_base)-$(SOVERSION).@SOSUFFIX@
+libso_static= $(libso_base)-$(SOVERSION).a
libso_target= $(libso_base)-$(SOVERSION).la
libso_default= $(libso_base).@SOSUFFIX@
libso_major= $(libso_base)-$(SOMAJOR).@SOSUFFIX@
##################################################
-# C++
+# C++ API.
#
-# C++ support is optional, and it can be used with or without shared libraries.
-# You must configure it using:
-# --enable-cxx
+# C++ support is optional, and can be built with static or shared libraries.
##################################################
+CXXFLAGS= -c $(CPPFLAGS) @CXXFLAGS@
+CXX= @MAKEFILE_CXX@
+CXXLINK= @MAKEFILE_CXXLINK@
+XSOLINK= @MAKEFILE_XSOLINK@
+LIBXSO_LIBS= @LIBXSO_LIBS@
+
libcxx= libdb_cxx.a
libxso_base= libdb_cxx
libxso= $(libxso_base)-$(SOVERSION).@SOSUFFIX@
+libxso_static= $(libxso_base)-$(SOVERSION).a
libxso_target= $(libxso_base)-$(SOVERSION).la
libxso_default= $(libxso_base).@SOSUFFIX@
libxso_major= $(libxso_base)-$(SOMAJOR).@SOSUFFIX@
##################################################
-# JAVA
+# Java API.
#
# Java support is optional and requires shared librarires.
-# You must configure it using:
-# --enable-java --enable-dynamic
##################################################
CLASSPATH= $(JAVA_CLASSTOP)
-JAR= @JAR@
-JAVAC= env CLASSPATH=$(CLASSPATH) @JAVAC@
+LIBJSO_LIBS= @LIBJSO_LIBS@
+
+JAR= @JAR@
+JAVAC= env CLASSPATH="$(CLASSPATH)" @JAVAC@
JAVACFLAGS= @JAVACFLAGS@
-JAVA_BUILTFILE= .javabuilt
-JAVA_CLASSTOP= $(srcdir)/java/classes
+JAVA_CLASSTOP= ./classes
+JAVA_RPCCLASSES=./classes.rpc
JAVA_SRCDIR= $(srcdir)/java/src
-JAVA_DBREL= com/sleepycat/db
+JAVA_DBREL= com/sleepycat/db
+JAVA_EXREL= com/sleepycat/examples
+JAVA_RPCREL= com/sleepycat/db/rpcserver
JAVA_DBDIR= $(JAVA_SRCDIR)/$(JAVA_DBREL)
-JAVA_EXDIR= $(JAVA_SRCDIR)/com/sleepycat/examples
+JAVA_EXDIR= $(JAVA_SRCDIR)/$(JAVA_EXREL)
+JAVA_RPCDIR= $(srcdir)/rpc_server/java
libj_jarfile= db.jar
+libj_exjarfile= dbexamples.jar
+rpc_jarfile= dbsvc.jar
libjso_base= libdb_java
-libjso= $(libjso_base)-$(SOVERSION).@SOSUFFIX@
+libjso= $(libjso_base)-$(SOVERSION).@JMODSUFFIX@
+libjso_static= $(libjso_base)-$(SOVERSION).a
libjso_target= $(libjso_base)-$(SOVERSION).la
-libjso_default= $(libjso_base).@SOSUFFIX@
-libjso_major= $(libjso_base)-$(SOMAJOR).@SOSUFFIX@
-libjso_g= $(libjso_base)-$(SOVERSION)_g.@SOSUFFIX@
+libjso_default= $(libjso_base).@JMODSUFFIX@
+libjso_major= $(libjso_base)-$(SOMAJOR).@JMODSUFFIX@
+libjso_g= $(libjso_base)-$(SOVERSION)_g.@JMODSUFFIX@
##################################################
-# TCL
+# TCL API.
#
# Tcl support is optional and requires shared libraries.
-# You must configure it using:
-# --enable-tcl --with-tcl=DIR --enable-dynamic
##################################################
TCFLAGS= @TCFLAGS@
+LIBTSO_LIBS= @LIBTSO_LIBS@
libtso_base= libdb_tcl
-libtso= $(libtso_base)-$(SOVERSION).@SOSUFFIX@
+libtso= $(libtso_base)-$(SOVERSION).@MODSUFFIX@
+libtso_static= $(libtso_base)-$(SOVERSION).a
libtso_target= $(libtso_base)-$(SOVERSION).la
-libtso_default= $(libtso_base).@SOSUFFIX@
-libtso_major= $(libtso_base)-$(SOMAJOR).@SOSUFFIX@
+libtso_default= $(libtso_base).@MODSUFFIX@
+libtso_major= $(libtso_base)-$(SOMAJOR).@MODSUFFIX@
##################################################
-# DB_DUMP185 UTILITY
+# db_dump185 UTILITY
#
# The db_dump185 application should be compiled using the system's db.h file
# (which should be a DB 1.85/1.86 include file), and the system's 1.85/1.86
@@ -104,620 +142,1138 @@ libtso_major= $(libtso_base)-$(SOMAJOR).@SOSUFFIX@
# local libraries, for example. Do that by adding -I options to the DB185INC
# line, and -l options to the DB185LIB line.
##################################################
-DB185INC= -c @CFLAGS@ -I$(srcdir)/include @CPPFLAGS@
+DB185INC= -c @CFLAGS@ -I$(srcdir) @CPPFLAGS@
DB185LIB=
##################################################
-# INSTALLATION DIRECTORIES AND PERMISSIONS
-##################################################
-prefix= @prefix@
-exec_prefix=@exec_prefix@
-bindir= @bindir@
-includedir=@includedir@
-libdir= @libdir@
-docdir= $(prefix)/docs
-
-dmode= 755
-emode= 555
-fmode= 444
-
-transform=@program_transform_name@
-
-##################################################
-# PATHS FOR STANDARD USER-LEVEL COMMANDS
+# NOTHING BELOW THIS LINE SHOULD EVER NEED TO BE MODIFIED.
##################################################
-SHELL= @db_cv_path_sh@
-ar= @db_cv_path_ar@ cr
-chmod= @db_cv_path_chmod@
-cp= @db_cv_path_cp@
-ln= @db_cv_path_ln@
-mkdir= @db_cv_path_mkdir@
-ranlib= @db_cv_path_ranlib@
-rm= @db_cv_path_rm@
-strip= @db_cv_path_strip@
##################################################
-# NOTHING BELOW THIS LINE SHOULD EVER NEED TO BE MODIFIED.
+# Object and utility lists.
##################################################
-OBJS= @ADDITIONAL_OBJS@ @LIBOBJS@ @RPC_OBJS@ bt_compare@o@ bt_conv@o@ \
- bt_curadj@o@ bt_cursor@o@ bt_delete@o@ bt_method@o@ bt_open@o@ \
- bt_put@o@ bt_rec@o@ bt_reclaim@o@ bt_recno@o@ bt_rsearch@o@ \
- bt_search@o@ bt_split@o@ bt_stat@o@ bt_upgrade@o@ bt_verify@o@ \
- btree_auto@o@ crdel_auto@o@ crdel_rec@o@ db@o@ db_am@o@ db_auto@o@ \
- db_byteorder@o@ db_cam@o@ db_conv@o@ db_dispatch@o@ db_dup@o@ \
- db_err@o@ db_getlong@o@ db_iface@o@ db_join@o@ db_log2@o@ \
- db_meta@o@ db_method@o@ db_overflow@o@ db_pr@o@ db_rec@o@ \
- db_reclaim@o@ db_ret@o@ db_salloc@o@ db_shash@o@ db_upg@o@ \
- db_upg_opd@o@ db_vrfy@o@ db_vrfyutil@o@ dbm@o@ env_method@o@ \
- env_open@o@ env_recover@o@ env_region@o@ hash@o@ hash_auto@o@ \
- hash_conv@o@ hash_dup@o@ hash_func@o@ hash_meta@o@ hash_method@o@ \
- hash_page@o@ hash_rec@o@ hash_reclaim@o@ hash_stat@o@ hash_upgrade@o@ \
- hash_verify@o@ hsearch@o@ lock@o@ lock_conflict@o@ \
+C_OBJS= @ADDITIONAL_OBJS@ @LTLIBOBJS@ @RPC_CLIENT_OBJS@ \
+ bt_compare@o@ bt_conv@o@ bt_curadj@o@ bt_cursor@o@ bt_delete@o@ \
+ bt_method@o@ bt_open@o@ bt_put@o@ bt_rec@o@ bt_reclaim@o@ \
+ bt_recno@o@ bt_rsearch@o@ bt_search@o@ bt_split@o@ bt_stat@o@ \
+ bt_upgrade@o@ bt_verify@o@ btree_auto@o@ crdel_auto@o@ \
+ crdel_rec@o@ db@o@ db_am@o@ db_auto@o@ db_byteorder@o@ db_cam@o@ \
+ db_conv@o@ db_dispatch@o@ db_dup@o@ db_err@o@ db_getlong@o@ \
+ db_idspace@o@ db_iface@o@ db_join@o@ db_log2@o@ db_meta@o@ \
+ db_method@o@ db_open@o@ db_overflow@o@ db_pr@o@ db_rec@o@ \
+ db_reclaim@o@ db_rename@o@ db_remove@o@ db_ret@o@ db_salloc@o@ \
+ db_shash@o@ db_truncate@o@ db_upg@o@ db_upg_opd@o@ db_vrfy@o@ \
+ db_vrfyutil@o@ dbm@o@ dbreg@o@ dbreg_auto@o@ dbreg_rec@o@ \
+ dbreg_util@o@ env_file@o@ env_method@o@ env_open@o@ env_recover@o@ \
+ env_region@o@ fileops_auto@o@ fop_basic@o@ fop_rec@o@ \
+ fop_util@o@ hash@o@ hash_auto@o@ hash_conv@o@ hash_dup@o@ \
+ hash_func@o@ hash_meta@o@ hash_method@o@ hash_open@o@ \
+ hash_page@o@ hash_rec@o@ hash_reclaim@o@ hash_stat@o@ \
+ hash_upgrade@o@ hash_verify@o@ hmac@o@ hsearch@o@ lock@o@ \
lock_deadlock@o@ lock_method@o@ lock_region@o@ lock_stat@o@ \
- lock_util@o@ log@o@ log_archive@o@ log_auto@o@ log_compare@o@ \
- log_findckp@o@ log_get@o@ log_method@o@ log_put@o@ log_rec@o@ \
- log_register@o@ mp_alloc@o@ mp_bh@o@ mp_fget@o@ mp_fopen@o@ \
- mp_fput@o@ mp_fset@o@ mp_method@o@ mp_region@o@ mp_register@o@ \
- mp_stat@o@ mp_sync@o@ mp_trickle@o@ mutex@o@ os_abs@o@ \
- os_alloc@o@ os_dir@o@ os_errno@o@ os_fid@o@ os_finit@o@ \
- os_fsync@o@ os_handle@o@ os_map@o@ os_method@o@ os_oflags@o@ \
- os_open@o@ os_region@o@ os_rename@o@ os_root@o@ os_rpath@o@ \
- os_rw@o@ os_seek@o@ os_sleep@o@ os_spin@o@ os_stat@o@ \
- os_tmpdir@o@ os_unlink@o@ qam@o@ qam_auto@o@ qam_conv@o@ qam_files@o@ \
- qam_method@o@ qam_open@o@ qam_rec@o@ qam_stat@o@ qam_upgrade@o@ \
- qam_verify@o@ txn@o@ txn_auto@o@ txn_rec@o@ txn_region@o@ xa@o@ \
- xa_db@o@ xa_map@o@
-
-COBJS= cxx_app@o@ cxx_except@o@ cxx_lock@o@ cxx_log@o@ cxx_mpool@o@ \
- cxx_table@o@ cxx_txn@o@
-
-DBSOBJS=dbs@o@ dbs_am@o@ dbs_checkpoint@o@ dbs_debug@o@ dbs_handles@o@ \
- dbs_log@o@ dbs_qam@o@ dbs_spawn@o@ dbs_trickle@o@ dbs_util@o@ \
- dbs_yield@o@
-
-EOBJS= ex_access@o@ ex_btrec@o@ ex_dbclient@o@ ex_env@o@ ex_lock@o@ \
- ex_mpool@o@ ex_thread@o@ ex_tpcb@o@
-
-JOBJS= java_Db@o@ java_DbEnv@o@ java_DbLock@o@ java_DbLsn@o@ java_DbTxn@o@ \
- java_Dbc@o@ java_Dbt@o@ java_info@o@ java_locked@o@ java_util@o@
-
-RPC_OBJS=client@o@ db_server_clnt@o@ db_server_xdr@o@ gen_client@o@ \
- gen_client_ret@o@
-RPC_SRV=db_server_proc@o@ db_server_svc@o@ db_server_util@o@ gen_db_server@o@
-
-TOBJS= tcl_compat@o@ tcl_db@o@ tcl_db_pkg@o@ tcl_dbcursor@o@ tcl_env@o@ \
- tcl_internal@o@ tcl_lock@o@ tcl_log@o@ tcl_mp@o@ tcl_txn@o@
-
-UOBJS= db_archive@o@ db_checkpoint@o@ db_deadlock@o@ db_dump185@o@ \
- db_dump@o@ db_load@o@ db_printlog@o@ db_recover@o@ db_stat@o@ \
- db_upgrade@o@ db_verify@o@ util_log@o@ util_sig@o@
-
-PROGS= @ADDITIONAL_PROGS@ db_archive db_checkpoint db_deadlock \
- db_dump db_load db_printlog db_recover db_stat db_upgrade db_verify
+ lock_util@o@ log@o@ log_archive@o@ log_compare@o@ log_get@o@ \
+ log_method@o@ log_put@o@ mp_alloc@o@ mp_bh@o@ mp_fget@o@ \
+ mp_fopen@o@ mp_fput@o@ mp_fset@o@ mp_method@o@ mp_region@o@ \
+ mp_register@o@ mp_stat@o@ mp_sync@o@ mp_trickle@o@ mutex@o@ \
+ os_abs@o@ os_alloc@o@ os_clock@o@ os_config@o@ os_dir@o@ \
+ os_errno@o@ os_fid@o@ os_fsync@o@ os_handle@o@ os_id@o@ \
+ os_map@o@ os_method@o@ os_oflags@o@ os_open@o@ os_region@o@ \
+ os_rename@o@ os_root@o@ os_rpath@o@ os_rw@o@ os_seek@o@ \
+ os_sleep@o@ os_spin@o@ os_stat@o@ os_tmpdir@o@ os_unlink@o@ \
+ qam@o@ qam_auto@o@ qam_conv@o@ qam_files@o@ qam_method@o@ \
+ qam_open@o@ qam_rec@o@ qam_stat@o@ qam_upgrade@o@ qam_verify@o@ \
+ rep_method@o@ rep_record@o@ rep_region@o@ rep_util@o@ sha1@o@ \
+ txn@o@ txn_auto@o@ txn_method@o@ txn_rec@o@ txn_recover@o@ \
+ txn_region@o@ txn_stat@o@ txn_util@o@ xa@o@ xa_db@o@ xa_map@o@
+
+CXX_OBJS=\
+ cxx_db@o@ cxx_dbc@o@ cxx_dbt@o@ cxx_env@o@ cxx_except@o@ \
+ cxx_lock@o@ cxx_logc@o@ cxx_mpool@o@ cxx_txn@o@
+
+JAVA_OBJS=\
+ java_Db@o@ java_DbEnv@o@ java_DbLock@o@ java_DbLogc@o@ \
+ java_DbLsn@o@ java_DbTxn@o@ java_DbUtil@o@ java_Dbc@o@ \
+ java_Dbt@o@ \
+ java_info@o@ java_locked@o@ java_util@o@ java_stat_auto@o@
JAVA_DBSRCS=\
$(JAVA_DBDIR)/Db.java $(JAVA_DBDIR)/DbAppendRecno.java \
- $(JAVA_DBDIR)/DbBtreeCompare.java \
- $(JAVA_DBDIR)/DbBtreePrefix.java $(JAVA_DBDIR)/DbBtreeStat.java \
+ $(JAVA_DBDIR)/DbAppDispatch.java \
+ $(JAVA_DBDIR)/DbBtreeCompare.java $(JAVA_DBDIR)/DbBtreePrefix.java \
+ $(JAVA_DBDIR)/DbBtreeStat.java $(JAVA_DBDIR)/DbClient.java \
$(JAVA_DBDIR)/DbConstants.java $(JAVA_DBDIR)/DbDeadlockException.java \
$(JAVA_DBDIR)/DbDupCompare.java $(JAVA_DBDIR)/DbEnv.java \
$(JAVA_DBDIR)/DbEnvFeedback.java $(JAVA_DBDIR)/DbErrcall.java \
$(JAVA_DBDIR)/DbException.java $(JAVA_DBDIR)/DbFeedback.java \
$(JAVA_DBDIR)/DbHash.java $(JAVA_DBDIR)/DbHashStat.java \
$(JAVA_DBDIR)/DbKeyRange.java $(JAVA_DBDIR)/DbLock.java \
- $(JAVA_DBDIR)/DbLockStat.java $(JAVA_DBDIR)/DbLogStat.java \
+ $(JAVA_DBDIR)/DbLockNotGrantedException.java \
+ $(JAVA_DBDIR)/DbLockRequest.java $(JAVA_DBDIR)/DbLockStat.java \
+ $(JAVA_DBDIR)/DbLogc.java $(JAVA_DBDIR)/DbLogStat.java \
$(JAVA_DBDIR)/DbLsn.java $(JAVA_DBDIR)/DbMemoryException.java \
$(JAVA_DBDIR)/DbMpoolFStat.java $(JAVA_DBDIR)/DbMpoolStat.java \
+ $(JAVA_DBDIR)/DbMultipleDataIterator.java \
+ $(JAVA_DBDIR)/DbMultipleIterator.java \
+ $(JAVA_DBDIR)/DbMultipleKeyDataIterator.java \
+ $(JAVA_DBDIR)/DbMultipleRecnoDataIterator.java \
$(JAVA_DBDIR)/DbOutputStreamErrcall.java \
- $(JAVA_DBDIR)/DbQueueStat.java $(JAVA_DBDIR)/DbRecoveryInit.java \
- $(JAVA_DBDIR)/DbRunRecoveryException.java $(JAVA_DBDIR)/DbTxn.java \
- $(JAVA_DBDIR)/DbTxnRecover.java $(JAVA_DBDIR)/DbTxnStat.java \
- $(JAVA_DBDIR)/Dbc.java $(JAVA_DBDIR)/Dbt.java
+ $(JAVA_DBDIR)/DbPreplist.java $(JAVA_DBDIR)/DbQueueStat.java \
+ $(JAVA_DBDIR)/DbRepStat.java $(JAVA_DBDIR)/DbRepTransport.java \
+ $(JAVA_DBDIR)/DbRunRecoveryException.java \
+ $(JAVA_DBDIR)/DbSecondaryKeyCreate.java $(JAVA_DBDIR)/DbTxn.java \
+ $(JAVA_DBDIR)/DbTxnStat.java \
+ $(JAVA_DBDIR)/DbUtil.java $(JAVA_DBDIR)/Dbc.java $(JAVA_DBDIR)/Dbt.java
JAVA_EXSRCS=\
$(JAVA_EXDIR)/AccessExample.java \
$(JAVA_EXDIR)/BtRecExample.java \
+ $(JAVA_EXDIR)/BulkAccessExample.java \
$(JAVA_EXDIR)/EnvExample.java \
$(JAVA_EXDIR)/LockExample.java \
$(JAVA_EXDIR)/TpcbExample.java
+TCL_OBJS=\
+ tcl_compat@o@ tcl_db@o@ tcl_db_pkg@o@ tcl_dbcursor@o@ tcl_env@o@ \
+ tcl_internal@o@ tcl_lock@o@ tcl_log@o@ tcl_mp@o@ tcl_rep@o@ \
+ tcl_txn@o@ tcl_util@o@
+
+RPC_CLIENT_OBJS=\
+ client@o@ db_server_clnt@o@ db_server_xdr@o@ gen_client@o@ \
+ gen_client_ret@o@
+
+RPC_SRV_OBJS=\
+ db_server_proc@o@ db_server_svc@o@ db_server_util@o@ \
+ gen_db_server@o@
+
+RPC_CXXSRV_OBJS=\
+ db_server_cxxproc@o@ db_server_cxxutil@o@ db_server_svc@o@ \
+ gen_db_server@o@
+
+RPC_JAVASRV_SRCS=\
+ $(JAVA_RPCDIR)/DbDispatcher.java \
+ $(JAVA_RPCDIR)/DbServer.java \
+ $(JAVA_RPCDIR)/FreeList.java \
+ $(JAVA_RPCDIR)/LocalIterator.java \
+ $(JAVA_RPCDIR)/RpcDb.java \
+ $(JAVA_RPCDIR)/RpcDbEnv.java \
+ $(JAVA_RPCDIR)/RpcDbTxn.java \
+ $(JAVA_RPCDIR)/RpcDbc.java \
+ $(JAVA_RPCDIR)/Timer.java \
+ $(JAVA_RPCDIR)/gen/DbServerStub.java \
+ $(JAVA_RPCDIR)/gen/__db_associate_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_associate_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_bt_maxkey_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_bt_maxkey_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_bt_minkey_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_bt_minkey_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_close_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_close_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_create_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_create_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_cursor_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_cursor_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_del_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_del_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_encrypt_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_encrypt_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_extentsize_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_extentsize_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_flags_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_flags_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_get_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_get_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_h_ffactor_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_h_ffactor_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_h_nelem_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_h_nelem_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_join_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_join_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_key_range_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_key_range_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_lorder_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_lorder_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_open_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_open_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_pagesize_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_pagesize_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_pget_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_pget_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_put_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_put_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_re_delim_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_re_delim_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_re_len_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_re_len_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_re_pad_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_re_pad_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_remove_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_remove_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_rename_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_rename_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_stat_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_stat_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_sync_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_sync_reply.java \
+ $(JAVA_RPCDIR)/gen/__db_truncate_msg.java \
+ $(JAVA_RPCDIR)/gen/__db_truncate_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_close_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_close_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_count_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_count_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_del_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_del_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_dup_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_dup_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_get_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_get_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_pget_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_pget_reply.java \
+ $(JAVA_RPCDIR)/gen/__dbc_put_msg.java \
+ $(JAVA_RPCDIR)/gen/__dbc_put_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_cachesize_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_cachesize_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_close_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_close_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_create_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_create_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_dbremove_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_dbremove_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_dbrename_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_dbrename_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_encrypt_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_encrypt_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_flags_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_flags_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_open_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_open_reply.java \
+ $(JAVA_RPCDIR)/gen/__env_remove_msg.java \
+ $(JAVA_RPCDIR)/gen/__env_remove_reply.java \
+ $(JAVA_RPCDIR)/gen/__txn_abort_msg.java \
+ $(JAVA_RPCDIR)/gen/__txn_abort_reply.java \
+ $(JAVA_RPCDIR)/gen/__txn_begin_msg.java \
+ $(JAVA_RPCDIR)/gen/__txn_begin_reply.java \
+ $(JAVA_RPCDIR)/gen/__txn_commit_msg.java \
+ $(JAVA_RPCDIR)/gen/__txn_commit_reply.java \
+ $(JAVA_RPCDIR)/gen/__txn_discard_msg.java \
+ $(JAVA_RPCDIR)/gen/__txn_discard_reply.java \
+ $(JAVA_RPCDIR)/gen/__txn_prepare_msg.java \
+ $(JAVA_RPCDIR)/gen/__txn_prepare_reply.java \
+ $(JAVA_RPCDIR)/gen/__txn_recover_msg.java \
+ $(JAVA_RPCDIR)/gen/__txn_recover_reply.java \
+ $(JAVA_RPCDIR)/gen/db_server.java
+
+UTIL_PROGS=\
+ @ADDITIONAL_PROGS@ \
+ db_archive db_checkpoint db_deadlock \
+ db_dump db_load db_printlog db_recover db_stat db_upgrade db_verify
+
+##################################################
+# List of files installed into the library directory.
##################################################
-# Note: Berkeley DB Makefiles are configured to build either a static or
-# a dynamic library. You should not attempt to build both library types
-# in the same directory, as they have incompatible object file formats.
-# To build both static and dynamic libraries, create two separate build
-# directories, and configure and build them separately.
+LIB_INSTALL_FILE_LIST=\
+ $(libdb) \
+ $(libso) \
+ $(libso_default) \
+ $(libso_major) \
+ $(libso_static) \
+ $(libso_target) \
+ $(libcxx) \
+ $(libxso) \
+ $(libxso_default) \
+ $(libxso_major) \
+ $(libxso_static) \
+ $(libxso_target) \
+ $(libtso) \
+ $(libtso_default) \
+ $(libtso_major) \
+ $(libtso_static) \
+ $(libtso_target) \
+ $(libjso) \
+ $(libjso_default) \
+ $(libjso_g) \
+ $(libjso_major) \
+ $(libjso_static) \
+ $(libjso_target) \
+ $(libj_exjarfile) \
+ $(libj_jarfile)
+
+##################################################
+# We're building a standard library or a RPM file hierarchy, potentially
+# for Embedix. Note: "all" must be the first target in the Makefile.
##################################################
-all: @DEFAULT_LIB@ @ADDITIONAL_LIBS@ @ADDITIONAL_LANG@ $(PROGS)
+all: @BUILD_TARGET@ libdb.a
+
+install-strip install: all @INSTALL_TARGET@
-$(libdb): $(OBJS)
- $(ar) $@ $(OBJS)
+##################################################
+# Library and standard utilities build.
+##################################################
+library_build: @INSTALL_LIBS@ @ADDITIONAL_LANG@ $(UTIL_PROGS)
+
+$(libdb): $(C_OBJS)
+ $(ar) cr $@ $(C_OBJS)
test ! -f $(ranlib) || $(ranlib) $@
-$(libcxx): $(COBJS) $(OBJS)
- $(ar) $@ $(COBJS) $(OBJS)
+$(libcxx): $(CXX_OBJS) $(C_OBJS)
+ $(ar) cr $@ $(CXX_OBJS) $(C_OBJS)
test ! -f $(ranlib) || $(ranlib) $@
-$(libso_target): $(OBJS)
- $(SOLINK) $(SOFLAGS) -o $(libso_target) \
- $(OBJS) $(LDFLAGS) $(LIBSO_LIBS)
+$(libso_target): $(C_OBJS)
+ $(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
-$(libxso_target): $(COBJS) $(OBJS)
- $(SOLINK) $(SOFLAGS) -o $(libxso_target) \
- $(COBJS) $(OBJS) $(LDFLAGS) $(LIBXSO_LIBS)
+$(libjso_target): $(JAVA_OBJS) $(C_OBJS)
+ $(SOLINK) -jnimodule $(SOFLAGS) $(LDFLAGS) \
+ -o $@ $(JAVA_OBJS) $(C_OBJS) $(LIBJSO_LIBS)
-$(libjso_target): $(JOBJS) $(OBJS)
- $(SOLINK) $(SOFLAGS) -o $(libjso_target) \
- $(JOBJS) $(OBJS) $(LDFLAGS) $(LIBJSO_LIBS)
+$(libtso_target): $(TCL_OBJS) $(C_OBJS)
+ $(SOLINK) -module $(SOFLAGS) $(LDFLAGS) \
+ -o $@ $(TCL_OBJS) $(C_OBJS) $(LIBTSO_LIBS)
-$(libtso_target): $(TOBJS) $(OBJS)
- $(SOLINK) $(SOFLAGS) -o $(libtso_target) \
- $(TOBJS) $(OBJS) $(LDFLAGS) $(LIBTSO_LIBS)
+$(libxso_target): $(CXX_OBJS) $(C_OBJS)
+ $(XSOLINK) $(SOFLAGS) $(LDFLAGS) \
+ -o $@ $(CXX_OBJS) $(C_OBJS) $(LIBXSO_LIBS)
##################################################
# Creating individual dependencies and actions for building class
# files is possible, but it is very messy and error prone.
##################################################
-java: $(JAVA_CLASSTOP) $(JAVA_BUILTFILE)
+java: $(libj_jarfile) $(libj_exjarfile)
-$(JAVA_BUILTFILE): $(JAVA_DBSRCS) $(JAVA_EXSRCS)
- @test -f $(rm) || (echo 'rm not found.'; exit 1)
- @test -f $(cp) || (echo 'cp not found.'; exit 1)
+$(libj_jarfile): $(JAVA_DBSRCS)
+ @test -d $(JAVA_CLASSTOP) || \
+ ($(mkdir) -p $(JAVA_CLASSTOP) && $(chmod) $(dmode) $(JAVA_CLASSTOP))
$(JAVAC) -d $(JAVA_CLASSTOP) $(JAVACFLAGS) $(JAVA_DBSRCS)
- @cd $(JAVA_CLASSTOP) && $(JAR) cf $(libj_jarfile) $(JAVA_DBREL)
+ cd $(JAVA_CLASSTOP) && $(JAR) cf ../$(libj_jarfile) $(JAVA_DBREL)
+
+$(libj_exjarfile): $(libj_jarfile) $(JAVA_EXSRCS)
+ @test -d $(JAVA_CLASSTOP) || \
+ ($(mkdir) -p $(JAVA_CLASSTOP) && $(chmod) $(dmode) $(JAVA_CLASSTOP))
$(JAVAC) -d $(JAVA_CLASSTOP) $(JAVACFLAGS) $(JAVA_EXSRCS)
- @echo This file helps with building java using make > $(JAVA_BUILTFILE)
+ cd $(JAVA_CLASSTOP) && $(JAR) cf ../$(libj_exjarfile) $(JAVA_EXREL)
+
+$(rpc_jarfile): $(libj_jarfile) $(RPC_JAVASRV_SRCS)
+ @test -d $(JAVA_RPCCLASSES) || \
+ ($(mkdir) -p $(JAVA_RPCCLASSES) && \
+ $(chmod) $(dmode) $(JAVA_RPCCLASSES))
+ env CLASSPATH=$(CLASSPATH):$(JAVA_RPCDIR)/oncrpc.jar \
+ @JAVAC@ -d $(JAVA_RPCCLASSES) $(JAVACFLAGS) $(RPC_JAVASRV_SRCS)
+ cd $(JAVA_RPCCLASSES) && $(JAR) cf ../$(rpc_jarfile) $(JAVA_RPCREL)
-$(JAVA_CLASSTOP):
- @test -f $(mkdir) || (echo 'mkdir not found.'; exit 1)
- $(mkdir) $(JAVA_CLASSTOP)
##################################################
# Utilities
##################################################
-berkeley_db_svc: $(RPC_SRV) util_log@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) $(RPC_SRV) util_log@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
-
-db_archive: db_archive@o@ util_sig@o@ @DEFAULT_LIB@
+berkeley_db_svc: $(RPC_SRV_OBJS) util_log@o@ $(DEF_LIB)
$(CCLINK) -o $@ $(LDFLAGS) \
- db_archive@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
+ $(RPC_SRV_OBJS) util_log@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-db_checkpoint: db_checkpoint@o@ util_log@o@ util_sig@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) \
- db_checkpoint@o@ util_log@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
+berkeley_db_cxxsvc: $(RPC_CXXSRV_OBJS) util_log@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) \
+ $(RPC_CXXSRV_OBJS) util_log@o@ $(DEF_LIB_CXX) $(LIBS)
$(POSTLINK) $@
-db_deadlock: db_deadlock@o@ util_log@o@ util_sig@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) \
- db_deadlock@o@ util_log@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
-
-db_dump: db_dump@o@ util_sig@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) db_dump@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
+berkeley_db_javasvc: $(rpc_jarfile)
+ echo > $@ "#!/bin/sh"
+ echo >> $@ CLASSPATH="$(CLASSPATH):$(rpc_jarfile):$(JAVA_RPCDIR)/oncrpc.jar"
+ echo >> $@ LD_LIBRARY_PATH=.libs
+ echo >> $@ export CLASSPATH LD_LIBRARY_PATH
+ echo >> $@ exec java com.sleepycat.db.rpcserver.DbServer \$$@
+ chmod +x $@
-db_dump185: db_dump185@o@ @LIBOBJS@
- $(CCLINK) -o $@ $(LDFLAGS) db_dump185@o@ @LIBOBJS@ $(DB185LIB)
- $(POSTLINK) $@
-
-db_load: db_load@o@ util_sig@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) db_load@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
-
-db_printlog: db_printlog@o@ util_sig@o@ @DEFAULT_LIB@
+db_archive: db_archive@o@ util_sig@o@ $(DEF_LIB)
$(CCLINK) -o $@ $(LDFLAGS) \
- db_printlog@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
-
-db_recover: db_recover@o@ util_sig@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) \
- db_recover@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
-
-db_stat: db_stat@o@ util_sig@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) db_stat@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
+ db_archive@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-db_upgrade: db_upgrade@o@ util_sig@o@ @DEFAULT_LIB@
+db_checkpoint: db_checkpoint@o@ util_log@o@ util_sig@o@ $(DEF_LIB)
$(CCLINK) -o $@ $(LDFLAGS) \
- db_upgrade@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
+ db_checkpoint@o@ util_log@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-db_verify: db_verify@o@ util_sig@o@ @DEFAULT_LIB@
+db_deadlock: db_deadlock@o@ util_log@o@ util_sig@o@ $(DEF_LIB)
$(CCLINK) -o $@ $(LDFLAGS) \
- db_verify@o@ util_sig@o@ $(LIBDB_ARGS) $(LIBS)
+ db_deadlock@o@ util_log@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-##################################################
-# Example programs
-##################################################
-ex_access: ex_access@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_access@o@ $(LIBDB_ARGS) $(LIBS)
+db_dump: db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-ex_btrec: ex_btrec@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_btrec@o@ $(LIBDB_ARGS) $(LIBS)
+db_dump185: db_dump185@o@ @LTLIBOBJS@
+ $(CCLINK) -o $@ $(LDFLAGS) db_dump185@o@ @LTLIBOBJS@ $(DB185LIB)
$(POSTLINK) $@
-ex_dbclient: ex_dbclient@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_dbclient@o@ $(LIBDB_ARGS) $(LIBS)
+db_load: db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-ex_env: ex_env@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_env@o@ $(LIBDB_ARGS) $(LIBS)
- $(POSTLINK) $@
-
-ex_lock: ex_lock@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_lock@o@ $(LIBDB_ARGS) $(LIBS)
+db_printlog: db_printlog@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) \
+ db_printlog@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-ex_mpool: ex_mpool@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_mpool@o@ $(LIBDB_ARGS) $(LIBS)
+db_recover: db_recover@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) \
+ db_recover@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-ex_thread: ex_thread@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_thread@o@ $(LIBDB_ARGS) $(LIBS)
+db_stat: db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-ex_tpcb: ex_tpcb@o@ @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) ex_tpcb@o@ $(LIBDB_ARGS) $(LIBS)
+db_upgrade: db_upgrade@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) \
+ db_upgrade@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
-##################################################
-# Multi-threaded tester.
-##################################################
-dbs: $(DBSOBJS) @DEFAULT_LIB@
- $(CCLINK) -o $@ $(LDFLAGS) $(DBSOBJS) $(LIBDB_ARGS) @DBS_LIBS@ $(LIBS)
+db_verify: db_verify@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) \
+ db_verify@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
##################################################
-# Standard Makefile targets.
+# Library and standard utilities install.
##################################################
-RMLIST= berkeley_db_svc db_dump185 dbs ex_access ex_btrec ex_dbclient \
- ex_env ex_lock ex_mpool ex_thread ex_tpcb
-clean:
- $(rm) -f $(OBJS)
- $(rm) -f $(COBJS) $(DBSOBJS) $(EOBJS) $(CEOBJS) $(JOBJS)
- $(rm) -f $(TOBJS) $(UOBJS) $(RPC_OBJS) $(RPC_SRV)
- $(rm) -f $(PROGS) $(RMLIST)
- $(rm) -f *@o@ *.o *.lo core *.core
- $(rm) -rf ALL.OUT TESTDIR
- $(rm) -rf .libs $(libdb) $(libcxx)
- $(rm) -rf $(libso_target) $(libso) $(libso_default) $(libso_major)
- $(rm) -rf $(libxso_target) $(libxso) $(libxso_default) $(libxso_major)
- $(rm) -rf $(libtso_target) $(libtso) $(libtso_default) $(libtso_major)
- $(rm) -rf $(libjso_target) $(libjso) $(libjso_default) $(libjso_major)
+library_install: install_setup
+library_install: install_include install_lib install_utilities install_docs
-depend obj:
-
-realclean distclean: clean
- $(rm) -f Makefile config.cache config.log config.status db_config.h
- $(rm) -f confdefs.h db.h db_int.h db_185.h include.tcl libtool
-
-install: all install_setup \
- install_include install_lib install_utilities install_docs
-
-uninstall: uninstall_utilities uninstall_include uninstall_lib uninstall_docs
+uninstall: uninstall_include uninstall_lib uninstall_utilities uninstall_docs
install_setup:
- @test -f $(chmod) || (echo 'chmod not found.'; exit 1)
- @test -f $(cp) || (echo 'cp not found.'; exit 1)
- @test -f $(mkdir) || (echo 'mkdir not found.'; exit 1)
- @test -f $(rm) || (echo 'rm not found.'; exit 1)
+ @test -d $(prefix) || \
+ ($(mkdir) -p $(prefix) && $(chmod) $(dmode) $(prefix))
+INCDOT= db.h db_cxx.h @ADDITIONAL_INCS@
+INCINC= cxx_common.h cxx_except.h
install_include:
@echo "Installing DB include files: $(includedir) ..."
@test -d $(includedir) || \
($(mkdir) -p $(includedir) && $(chmod) $(dmode) $(includedir))
- @cd $(includedir) && $(rm) -f db.h db_185.h db_cxx.h
- @$(cp) -p db.h \
- $(srcdir)/include/db_cxx.h @ADDITIONAL_INCS@ $(includedir)
- @cd $(includedir) && $(chmod) $(fmode) db.h db_cxx.h @ADDITIONAL_INCS@
+ @cd $(includedir) && $(rm) -f $(INCDOT) $(INCINC)
+ @$(cp) -p $(INCDOT) $(includedir)
+ @cd $(srcdir)/dbinc/ && $(cp) -p $(INCINC) $(includedir)
+ @cd $(includedir) && $(chmod) $(fmode) $(INCDOT) $(INCINC)
uninstall_include:
- -cd $(includedir) && $(rm) -f db.h db_185.h db_cxx.h
+ @cd $(includedir) && $(rm) -f $(INCDOT) $(INCINC)
-install_lib: @DEFAULT_INSTALL@
-
-uninstall_lib:
- -cd $(libdir) && $(rm) -f $(libdb) $(libcxx) \
- $(libso_target) $(libso) $(libso_default) $(libso_major) \
- $(libxso_target) $(libxso) $(libxso_default) $(libxso_major) \
- $(libtso_target) $(libtso) $(libtso_default) $(libtso_major) \
- $(libjso_target) $(libjso) $(libjso_default) $(libjso_major) \
- $(libj_jarfile)
-
-install_static:
+install_lib:
@echo "Installing DB library: $(libdir) ..."
@test -d $(libdir) || \
($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
- @cd $(libdir) && $(rm) -f $(libdb)
- @$(cp) -p $(libdb) $(libdir)
- @cd $(libdir) && $(chmod) $(fmode) $(libdb)
+ @cd $(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
+ @$(INSTALLER) @INSTALL_LIBS@ $(libdir)
+ @(cd $(libdir) && \
+ test -f $(libso) && $(ln) -s $(libso) $(libso_default); \
+ test -f $(libso) && $(ln) -s $(libso) $(libso_major); \
+ test -f $(libso_static) && $(ln) -s $(libso_static) $(libdb); \
+ test -f $(libxso) && $(ln) -s $(libxso) $(libxso_default); \
+ test -f $(libxso) && $(ln) -s $(libxso) $(libxso_major); \
+ test -f $(libxso_static) && $(ln) -s $(libxso_static) $(libcxx); \
+ test -f $(libtso) && $(ln) -s $(libtso) $(libtso_default); \
+ test -f $(libtso) && $(ln) -s $(libtso) $(libtso_major); \
+ test -f $(libjso) && $(ln) -s $(libjso) $(libjso_default); \
+ test -f $(libjso) && $(ln) -s $(libjso) $(libjso_major); \
+ test -f $(libjso) && $(ln) -s $(libjso) $(libjso_g)) || true
+ @(test -f $(libj_jarfile) && \
+ $(cp) $(libj_jarfile) $(libdir) && \
+ $(chmod) $(fmode) $(libdir)/$(libj_jarfile)) || true
-install_static_cxx:
- @echo "Installing DB C++ static library: $(libdir) ..."
- @test -d $(libdir) || \
- ($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
- @cd $(libdir) && $(rm) -f $(libcxx)
- @$(cp) -p $(libcxx) $(libdir)
- @cd $(libdir) && $(chmod) $(fmode) $(libcxx)
-
-install_dynamic:
- @echo "Installing DB library: $(libdir) ..."
- @test -d $(libdir) || \
- ($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
- @cd $(libdir) && $(rm) -f \
- $(libso_target) $(libso) $(libso_default) $(libso_major)
- @$(INSTALLER) $(libso_target) $(libdir)
- @cd $(libdir) && $(ln) -s $(libso) $(libso_default)
- @cd $(libdir) && $(ln) -s $(libso) $(libso_major)
- @$(LIBTOOL) --mode=finish $(libdir)
-
-install_dynamic_cxx:
- @echo "Installing DB C++ library: $(libdir) ..."
- @test -d $(libdir) || \
- ($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
- @cd $(libdir) && $(rm) -f \
- $(libxso_target) $(libxso) $(libxso_default) $(libxso_major)
- @$(INSTALLER) $(libxso_target) $(libdir)
- @cd $(libdir) && $(ln) -s $(libxso) $(libxso_default)
- @cd $(libdir) && $(ln) -s $(libxso) $(libxso_major)
-
-install_tcl:
- @echo "Installing DB Tcl library: $(libdir) ..."
- @test -d $(libdir) || \
- ($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
- @cd $(libdir) && $(rm) -f \
- $(libtso_target) $(libtso) $(libtso_default) $(libtso_major)
- @$(INSTALLER) $(libtso_target) $(libdir)
- @cd $(libdir) && $(ln) -s $(libtso) $(libtso_default)
- @cd $(libdir) && $(ln) -s $(libtso) $(libtso_major)
-
-install_java:
- @echo "Installing DB Java library: $(libdir) ..."
- @test -d $(libdir) || \
- ($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
- @cd $(libdir) && $(rm) -f \
- $(libjso_target) $(libjso) $(libjso_default) $(libjso_major)
- @$(INSTALLER) $(libjso_target) $(libdir)
- @cd $(libdir) && $(ln) -s $(libjso) $(libjso_default)
- @cd $(libdir) && $(ln) -s $(libjso) $(libjso_major)
- @cd $(libdir) && $(ln) -s $(libjso) $(libjso_g)
- @$(cp) $(JAVA_CLASSTOP)/$(libj_jarfile) $(libdir)
+uninstall_lib:
+ @cd $(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
install_utilities:
- @echo "Installing DB utilities: $(bindir) ..."
+ echo "Installing DB utilities: $(bindir) ..."
@test -d $(bindir) || \
($(mkdir) -p $(bindir) && $(chmod) $(dmode) $(bindir))
- @cd $(bindir) && $(rm) -f $(PROGS)
- @$(INSTALLER) -fp $(PROGS) $(bindir)
- @cd $(bindir) && (test ! -f $(strip) || $(strip) $(PROGS))
- @cd $(bindir) && $(chmod) $(emode) $(PROGS)
+ @for i in $(UTIL_PROGS); do \
+ $(rm) -f $(bindir)/$$i $(bindir)/$$i.exe; \
+ test -f $$i.exe && i=$$i.exe || true; \
+ $(INSTALLER) $$i $(bindir)/$$i; \
+ test -f $(strip) && $(strip) $(bindir)/$$i || true; \
+ $(chmod) $(emode) $(bindir)/$$i; \
+ done
uninstall_utilities:
- -cd $(bindir) && $(rm) -f $(PROGS)
+ @(cd $(bindir); for i in $(UTIL_PROGS); do \
+ $(rm) -f $$i $$i.exe; \
+ done)
+DOCLIST=\
+ api_c api_cxx api_java api_tcl images index.html ref reftoc.html \
+ sleepycat utility
install_docs:
@echo "Installing documentation: $(docdir) ..."
@test -d $(docdir) || \
($(mkdir) -p $(docdir) && $(chmod) $(dmode) $(docdir))
- @cd $(docdir) && $(rm) -rf *
- @cd $(srcdir)/docs && $(cp) -pr * $(docdir)/
+ @cd $(docdir) && $(rm) -rf $(DOCLIST)
+ @cd $(srcdir)/docs && $(cp) -pr $(DOCLIST) $(docdir)/
uninstall_docs:
- -cd $(docdir) && $(rm) -rf *
+ @cd $(docdir) && $(rm) -rf $(DOCLIST)
##################################################
-# Object build rules.
+# RPM, Embedix build and install.
##################################################
-# Utilities
-db_archive@o@: $(srcdir)/db_archive/db_archive.c
+RPM_ARCHIVE=db-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@.tar.gz
+rpm_build:
+ @$(rm) -rf BUILD RPMS SOURCES SPECS SRPMS RPM_INSTALL
+ @$(mkdir) -p BUILD && $(chmod) $(dmode) BUILD
+ @$(mkdir) -p RPMS/i386 && $(chmod) $(dmode) RPMS RPMS/i386
+ @$(mkdir) -p SOURCES && $(chmod) $(dmode) SOURCES
+ @$(mkdir) -p SPECS && $(chmod) $(dmode) SPECS
+ @$(mkdir) -p SRPMS && $(chmod) $(dmode) SRPMS
+ $(cp) @db_cv_path_rpm_archive@/$(RPM_ARCHIVE) SOURCES/
+ $(cp) db.spec SPECS/db.spec
+ $(rpm) --rcfile @CONFIGURATION_PATH@/rpmrc -ba SPECS/db.spec
+
+rpm_install:
+
+RPM_SRPMS=db-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@-1.src.rpm
+embedix_install:
+ $(cp) db.ecd @db_cv_path_embedix_install@/config-data/ecds/db.ecd
+ $(chmod) $(fmode) @db_cv_path_embedix_install@/config-data/ecds/db.ecd
+ $(cp) SRPMS/$(RPM_SRPMS) \
+ @db_cv_path_embedix_install@/Packages/SRPMS/$(RPM_SRPMS)
+ $(chmod) $(fmode) \
+ @db_cv_path_embedix_install@/Packages/SRPMS/$(RPM_SRPMS)
+
+##################################################
+# Remaining standard Makefile targets.
+##################################################
+CLEAN_LIST=\
+ berkeley_db_svc berkeley_db_cxxsvc berkeley_db_javasvc \
+ db_dump185 db_perf dbs bench_001 \
+ ex_access ex_apprec ex_btrec ex_dbclient ex_env ex_lock ex_mpool \
+ ex_repquote ex_thread ex_tpcb excxx_access excxx_btrec excxx_env \
+ excxx_lock excxx_mpool excxx_tpcb rpmrc
+
+mostly-clean clean:
+ $(rm) -rf $(C_OBJS)
+ $(rm) -rf $(CXX_OBJS) $(JAVA_OBJS) $(TCL_OBJS)
+ $(rm) -rf $(RPC_CLIENT_OBJS) $(RPC_SRV_OBJS) $(RPC_CXXSRV_OBJS)
+ $(rm) -rf $(UTIL_PROGS) *.exe $(CLEAN_LIST)
+ $(rm) -rf $(JAVA_CLASSTOP) $(JAVA_RPCCLASSES) $(rpc_jarfile)
+ $(rm) -rf tags *@o@ *.o *.o.lock *.lo core *.core
+ $(rm) -rf ALL.OUT.* BUILD PARALLEL_TESTDIR.* RPMS RPM_INSTALL
+ $(rm) -rf RUN_LOG RUNQUEUE SOURCES SPECS SRPMS TESTDIR TESTDIR.A
+ $(rm) -rf logtrack_seen.db tm .libs $(LIB_INSTALL_FILE_LIST)
+
+REALCLEAN_LIST=\
+ Makefile confdefs.h config.cache config.log config.status db.h \
+ db.spec db185_int.h db_185.h db_config.h db_cxx.h db_int.h \
+ db_int_def.h include.tcl
+
+distclean maintainer-clean realclean: clean
+ $(rm) -rf $(REALCLEAN_LIST)
+ $(rm) -rf libtool
+
+check depend dvi info obj TAGS:
+ @echo "$@: make target not supported" && true
+
+dist:
+ @echo "$@: make target not supported" && false
+
+##################################################
+# Multi-threaded testers, benchmarks.
+##################################################
+dbs@o@: $(srcdir)/test_server/dbs.c
$(CC) $(CFLAGS) $?
-db_checkpoint@o@: $(srcdir)/db_checkpoint/db_checkpoint.c
+dbs_am@o@: $(srcdir)/test_server/dbs_am.c
$(CC) $(CFLAGS) $?
-db_deadlock@o@: $(srcdir)/db_deadlock/db_deadlock.c
+dbs_checkpoint@o@: $(srcdir)/test_server/dbs_checkpoint.c
$(CC) $(CFLAGS) $?
-db_dump@o@: $(srcdir)/db_dump/db_dump.c
+dbs_debug@o@: $(srcdir)/test_server/dbs_debug.c
$(CC) $(CFLAGS) $?
-db_dump185@o@: $(srcdir)/db_dump185/db_dump185.c
- $(CC) $(DB185INC) $?
-db_load@o@: $(srcdir)/db_load/db_load.c
+dbs_handles@o@: $(srcdir)/test_server/dbs_handles.c
$(CC) $(CFLAGS) $?
-db_printlog@o@: $(srcdir)/db_printlog/db_printlog.c
+dbs_log@o@: $(srcdir)/test_server/dbs_log.c
$(CC) $(CFLAGS) $?
-db_recover@o@: $(srcdir)/db_recover/db_recover.c
+dbs_qam@o@: $(srcdir)/test_server/dbs_qam.c
$(CC) $(CFLAGS) $?
-db_stat@o@: $(srcdir)/db_stat/db_stat.c
+dbs_spawn@o@: $(srcdir)/test_server/dbs_spawn.c
$(CC) $(CFLAGS) $?
-db_upgrade@o@: $(srcdir)/db_upgrade/db_upgrade.c
+dbs_trickle@o@: $(srcdir)/test_server/dbs_trickle.c
$(CC) $(CFLAGS) $?
-db_verify@o@: $(srcdir)/db_verify/db_verify.c
+dbs_util@o@: $(srcdir)/test_server/dbs_util.c
$(CC) $(CFLAGS) $?
-
-# Examples
-ex_access@o@: $(srcdir)/examples_c/ex_access.c
+dbs_yield@o@: $(srcdir)/test_server/dbs_yield.c
$(CC) $(CFLAGS) $?
-ex_btrec@o@: $(srcdir)/examples_c/ex_btrec.c
+DBS_OBJS=\
+ dbs@o@ dbs_am@o@ dbs_checkpoint@o@ dbs_debug@o@ dbs_handles@o@ \
+ dbs_log@o@ dbs_qam@o@ dbs_spawn@o@ dbs_trickle@o@ dbs_util@o@ \
+ dbs_yield@o@
+dbs: $(DBS_OBJS) $(DEF_LIB)
+ $(CCLINK) -o $@ \
+ $(LDFLAGS) $(DBS_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+ $(POSTLINK) $@
+
+db_perf@o@: $(srcdir)/test_perf/db_perf.c
$(CC) $(CFLAGS) $?
-ex_dbclient@o@: $(srcdir)/examples_c/ex_dbclient.c
+perf_cache_check@o@: $(srcdir)/test_perf/perf_cache_check.c
$(CC) $(CFLAGS) $?
-ex_env@o@: $(srcdir)/examples_c/ex_env.c
+perf_checkpoint@o@: $(srcdir)/test_perf/perf_checkpoint.c
$(CC) $(CFLAGS) $?
-ex_lock@o@: $(srcdir)/examples_c/ex_lock.c
+perf_config@o@: $(srcdir)/test_perf/perf_config.c
$(CC) $(CFLAGS) $?
-ex_mpool@o@: $(srcdir)/examples_c/ex_mpool.c
+perf_dbs@o@: $(srcdir)/test_perf/perf_dbs.c
$(CC) $(CFLAGS) $?
-ex_thread@o@: $(srcdir)/examples_c/ex_thread.c
+perf_debug@o@: $(srcdir)/test_perf/perf_debug.c
$(CC) $(CFLAGS) $?
-ex_tpcb@o@: $(srcdir)/examples_c/ex_tpcb.c
+perf_file@o@: $(srcdir)/test_perf/perf_file.c
$(CC) $(CFLAGS) $?
-
-# DB files
-crdel_auto@o@: $(srcdir)/db/crdel_auto.c
+perf_key@o@: $(srcdir)/test_perf/perf_key.c
$(CC) $(CFLAGS) $?
-crdel_rec@o@: $(srcdir)/db/crdel_rec.c
+perf_log@o@: $(srcdir)/test_perf/perf_log.c
$(CC) $(CFLAGS) $?
-db@o@: $(srcdir)/db/db.c
+perf_misc@o@: $(srcdir)/test_perf/perf_misc.c
$(CC) $(CFLAGS) $?
-db_am@o@: $(srcdir)/db/db_am.c
+perf_op@o@: $(srcdir)/test_perf/perf_op.c
$(CC) $(CFLAGS) $?
-db_auto@o@: $(srcdir)/db/db_auto.c
+perf_parse@o@: $(srcdir)/test_perf/perf_parse.c
$(CC) $(CFLAGS) $?
-db_cam@o@: $(srcdir)/db/db_cam.c
+perf_rand@o@: $(srcdir)/test_perf/perf_rand.c
$(CC) $(CFLAGS) $?
-db_conv@o@: $(srcdir)/db/db_conv.c
+perf_spawn@o@: $(srcdir)/test_perf/perf_spawn.c
$(CC) $(CFLAGS) $?
-db_dispatch@o@: $(srcdir)/db/db_dispatch.c
+perf_thread@o@: $(srcdir)/test_perf/perf_thread.c
$(CC) $(CFLAGS) $?
-db_dup@o@: $(srcdir)/db/db_dup.c
+perf_trickle@o@: $(srcdir)/test_perf/perf_trickle.c
$(CC) $(CFLAGS) $?
-db_iface@o@: $(srcdir)/db/db_iface.c
+perf_txn@o@: $(srcdir)/test_perf/perf_txn.c
$(CC) $(CFLAGS) $?
-db_join@o@: $(srcdir)/db/db_join.c
+perf_util@o@: $(srcdir)/test_perf/perf_util.c
$(CC) $(CFLAGS) $?
-db_meta@o@: $(srcdir)/db/db_meta.c
+perf_vx@o@: $(srcdir)/test_perf/perf_vx.c
$(CC) $(CFLAGS) $?
-db_method@o@: $(srcdir)/db/db_method.c
+DBPERF_OBJS=\
+ db_perf@o@ perf_cache_check@o@ perf_checkpoint@o@ perf_config@o@ \
+ perf_dbs@o@ perf_debug@o@ perf_file@o@ perf_key@o@ perf_log@o@ \
+ perf_misc@o@ perf_op@o@ perf_parse@o@ perf_rand@o@ \
+ perf_spawn@o@ perf_thread@o@ perf_trickle@o@ perf_txn@o@ \
+ perf_util@o@ perf_vx@o@
+db_perf: $(DBPERF_OBJS) $(DEF_LIB)
+ $(CCLINK) -o $@ \
+ $(LDFLAGS) $(DBPERF_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+ $(POSTLINK) $@
+
+tm@o@: $(srcdir)/mutex/tm.c
$(CC) $(CFLAGS) $?
-db_overflow@o@: $(srcdir)/db/db_overflow.c
+tm: tm@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) tm@o@ $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+ $(POSTLINK) $@
+
+##################################################
+# Example programs for C.
+##################################################
+bench_001@o@: $(srcdir)/examples_c/bench_001.c
$(CC) $(CFLAGS) $?
-db_pr@o@: $(srcdir)/db/db_pr.c
+bench_001: bench_001@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) bench_001@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+ex_access@o@: $(srcdir)/examples_c/ex_access.c
$(CC) $(CFLAGS) $?
-db_rec@o@: $(srcdir)/db/db_rec.c
+ex_access: ex_access@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_access@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+ex_apprec@o@: $(srcdir)/examples_c/ex_apprec/ex_apprec.c
$(CC) $(CFLAGS) $?
-db_reclaim@o@: $(srcdir)/db/db_reclaim.c
+ex_apprec_auto@o@: $(srcdir)/examples_c/ex_apprec/ex_apprec_auto.c
$(CC) $(CFLAGS) $?
-db_ret@o@: $(srcdir)/db/db_ret.c
+ex_apprec_rec@o@: $(srcdir)/examples_c/ex_apprec/ex_apprec_rec.c
$(CC) $(CFLAGS) $?
-db_upg@o@: $(srcdir)/db/db_upg.c
+EX_APPREC_OBJS=ex_apprec@o@ ex_apprec_auto@o@ ex_apprec_rec@o@
+ex_apprec: $(EX_APPREC_OBJS) $(DEF_LIB)
+ $(CCLINK) -o $@ \
+ $(LDFLAGS) $(EX_APPREC_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+
+ex_btrec@o@: $(srcdir)/examples_c/ex_btrec.c
$(CC) $(CFLAGS) $?
-db_upg_opd@o@: $(srcdir)/db/db_upg_opd.c
+ex_btrec: ex_btrec@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_btrec@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+ex_dbclient@o@: $(srcdir)/examples_c/ex_dbclient.c
$(CC) $(CFLAGS) $?
-db_vrfy@o@: $(srcdir)/db/db_vrfy.c
+ex_dbclient: ex_dbclient@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_dbclient@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+ex_env@o@: $(srcdir)/examples_c/ex_env.c
$(CC) $(CFLAGS) $?
-db_vrfyutil@o@: $(srcdir)/db/db_vrfyutil.c
+ex_env: ex_env@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_env@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+ex_lock@o@: $(srcdir)/examples_c/ex_lock.c
$(CC) $(CFLAGS) $?
+ex_lock: ex_lock@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_lock@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
-# Environment files
-db_salloc@o@: $(srcdir)/env/db_salloc.c
+ex_mpool@o@: $(srcdir)/examples_c/ex_mpool.c
$(CC) $(CFLAGS) $?
-db_shash@o@: $(srcdir)/env/db_shash.c
+ex_mpool: ex_mpool@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_mpool@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+ex_rq_client@o@: $(srcdir)/examples_c/ex_repquote/ex_rq_client.c
$(CC) $(CFLAGS) $?
-env_method@o@: $(srcdir)/env/env_method.c
+ex_rq_main@o@: $(srcdir)/examples_c/ex_repquote/ex_rq_main.c
$(CC) $(CFLAGS) $?
-env_open@o@: $(srcdir)/env/env_open.c
+ex_rq_master@o@: $(srcdir)/examples_c/ex_repquote/ex_rq_master.c
$(CC) $(CFLAGS) $?
-env_recover@o@: $(srcdir)/env/env_recover.c
+ex_rq_net@o@: $(srcdir)/examples_c/ex_repquote/ex_rq_net.c
$(CC) $(CFLAGS) $?
-env_region@o@: $(srcdir)/env/env_region.c
+ex_rq_util@o@: $(srcdir)/examples_c/ex_repquote/ex_rq_util.c
$(CC) $(CFLAGS) $?
+EX_RQ_OBJS=\
+ ex_rq_client@o@ ex_rq_main@o@ ex_rq_master@o@ ex_rq_net@o@ ex_rq_util@o@
+ex_repquote: $(EX_RQ_OBJS) $(DEF_LIB)
+ $(CCLINK) -o $@ \
+ $(LDFLAGS) $(EX_RQ_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+ $(POSTLINK) $@
-# Common files
-db_byteorder@o@: $(srcdir)/common/db_byteorder.c
- $(CC) $(CFLAGS) $?
-db_err@o@: $(srcdir)/common/db_err.c
- $(CC) $(CFLAGS) $?
-db_getlong@o@: $(srcdir)/common/db_getlong.c
- $(CC) $(CFLAGS) $?
-db_log2@o@: $(srcdir)/common/db_log2.c
- $(CC) $(CFLAGS) $?
-util_log@o@: $(srcdir)/common/util_log.c
+ex_thread@o@: $(srcdir)/examples_c/ex_thread.c
$(CC) $(CFLAGS) $?
-util_sig@o@: $(srcdir)/common/util_sig.c
+ex_thread: ex_thread@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ \
+ $(LDFLAGS) ex_thread@o@ $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+ $(POSTLINK) $@
+
+ex_tpcb@o@: $(srcdir)/examples_c/ex_tpcb.c
$(CC) $(CFLAGS) $?
+ex_tpcb: ex_tpcb@o@ $(DEF_LIB)
+ $(CCLINK) -o $@ $(LDFLAGS) ex_tpcb@o@ $(DEF_LIB) $(LIBS)
+ $(POSTLINK) $@
+
+##################################################
+# Example programs for C++.
+##################################################
+AccessExample@o@: $(srcdir)/examples_cxx/AccessExample.cpp
+ $(CXX) $(CXXFLAGS) $?
+excxx_access: AccessExample@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) AccessExample@o@ $(DEF_LIB_CXX) $(LIBS)
+ $(POSTLINK) $@
+
+BtRecExample@o@: $(srcdir)/examples_cxx/BtRecExample.cpp
+ $(CXX) $(CXXFLAGS) $?
+excxx_btrec: BtRecExample@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) BtRecExample@o@ $(DEF_LIB_CXX) $(LIBS)
+ $(POSTLINK) $@
+
+EnvExample@o@: $(srcdir)/examples_cxx/EnvExample.cpp
+ $(CXX) $(CXXFLAGS) $?
+excxx_env: EnvExample@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) EnvExample@o@ $(DEF_LIB_CXX) $(LIBS)
+ $(POSTLINK) $@
+
+LockExample@o@: $(srcdir)/examples_cxx/LockExample.cpp
+ $(CXX) $(CXXFLAGS) $?
+excxx_lock: LockExample@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) LockExample@o@ $(DEF_LIB_CXX) $(LIBS)
+ $(POSTLINK) $@
-# Btree files
+MpoolExample@o@: $(srcdir)/examples_cxx/MpoolExample.cpp
+ $(CXX) $(CXXFLAGS) $?
+excxx_mpool: MpoolExample@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) MpoolExample@o@ $(DEF_LIB_CXX) $(LIBS)
+ $(POSTLINK) $@
+
+TpcbExample@o@: $(srcdir)/examples_cxx/TpcbExample.cpp
+ $(CXX) $(CXXFLAGS) $?
+excxx_tpcb: TpcbExample@o@ $(DEF_LIB_CXX)
+ $(CXXLINK) -o $@ $(LDFLAGS) TpcbExample@o@ $(DEF_LIB_CXX) $(LIBS)
+ $(POSTLINK) $@
+
+##################################################
+# C API build rules.
+##################################################
+aes_method@o@: $(srcdir)/crypto/aes_method.c
+ $(CC) $(CFLAGS) $?
bt_compare@o@: $(srcdir)/btree/bt_compare.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_conv@o@: $(srcdir)/btree/bt_conv.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_curadj@o@: $(srcdir)/btree/bt_curadj.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_cursor@o@: $(srcdir)/btree/bt_cursor.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_delete@o@: $(srcdir)/btree/bt_delete.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_method@o@: $(srcdir)/btree/bt_method.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_open@o@: $(srcdir)/btree/bt_open.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_put@o@: $(srcdir)/btree/bt_put.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_rec@o@: $(srcdir)/btree/bt_rec.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_reclaim@o@: $(srcdir)/btree/bt_reclaim.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_recno@o@: $(srcdir)/btree/bt_recno.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_rsearch@o@: $(srcdir)/btree/bt_rsearch.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_search@o@: $(srcdir)/btree/bt_search.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_split@o@: $(srcdir)/btree/bt_split.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_stack@o@: $(srcdir)/btree/bt_stack.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_stat@o@: $(srcdir)/btree/bt_stat.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_upgrade@o@: $(srcdir)/btree/bt_upgrade.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
bt_verify@o@: $(srcdir)/btree/bt_verify.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
btree_auto@o@: $(srcdir)/btree/btree_auto.c
- $(CC) $(CFLAGS) $?
-
-# Queue files
+ $(CC) $(CFLAGS) $?
+crdel_auto@o@: $(srcdir)/db/crdel_auto.c
+ $(CC) $(CFLAGS) $?
+crdel_rec@o@: $(srcdir)/db/crdel_rec.c
+ $(CC) $(CFLAGS) $?
+crypto@o@: $(srcdir)/crypto/crypto.c
+ $(CC) $(CFLAGS) $?
+db185@o@: $(srcdir)/db185/db185.c
+ $(CC) $(CFLAGS) $?
+db@o@: $(srcdir)/db/db.c
+ $(CC) $(CFLAGS) $?
+db_am@o@: $(srcdir)/db/db_am.c
+ $(CC) $(CFLAGS) $?
+db_auto@o@: $(srcdir)/db/db_auto.c
+ $(CC) $(CFLAGS) $?
+db_byteorder@o@: $(srcdir)/common/db_byteorder.c
+ $(CC) $(CFLAGS) $?
+db_cam@o@: $(srcdir)/db/db_cam.c
+ $(CC) $(CFLAGS) $?
+db_conv@o@: $(srcdir)/db/db_conv.c
+ $(CC) $(CFLAGS) $?
+db_dispatch@o@: $(srcdir)/db/db_dispatch.c
+ $(CC) $(CFLAGS) $?
+db_dup@o@: $(srcdir)/db/db_dup.c
+ $(CC) $(CFLAGS) $?
+db_err@o@: $(srcdir)/common/db_err.c
+ $(CC) $(CFLAGS) $?
+db_getlong@o@: $(srcdir)/common/db_getlong.c
+ $(CC) $(CFLAGS) $?
+db_idspace@o@: $(srcdir)/common/db_idspace.c
+ $(CC) $(CFLAGS) $?
+db_iface@o@: $(srcdir)/db/db_iface.c
+ $(CC) $(CFLAGS) $?
+db_join@o@: $(srcdir)/db/db_join.c
+ $(CC) $(CFLAGS) $?
+db_log2@o@: $(srcdir)/common/db_log2.c
+ $(CC) $(CFLAGS) $?
+db_meta@o@: $(srcdir)/db/db_meta.c
+ $(CC) $(CFLAGS) $?
+db_method@o@: $(srcdir)/db/db_method.c
+ $(CC) $(CFLAGS) $?
+db_open@o@: $(srcdir)/db/db_open.c
+ $(CC) $(CFLAGS) $?
+db_overflow@o@: $(srcdir)/db/db_overflow.c
+ $(CC) $(CFLAGS) $?
+db_pr@o@: $(srcdir)/db/db_pr.c
+ $(CC) $(CFLAGS) $?
+db_rec@o@: $(srcdir)/db/db_rec.c
+ $(CC) $(CFLAGS) $?
+db_reclaim@o@: $(srcdir)/db/db_reclaim.c
+ $(CC) $(CFLAGS) $?
+db_rename@o@: $(srcdir)/db/db_rename.c
+ $(CC) $(CFLAGS) $?
+db_remove@o@: $(srcdir)/db/db_remove.c
+ $(CC) $(CFLAGS) $?
+db_ret@o@: $(srcdir)/db/db_ret.c
+ $(CC) $(CFLAGS) $?
+db_salloc@o@: $(srcdir)/env/db_salloc.c
+ $(CC) $(CFLAGS) $?
+db_shash@o@: $(srcdir)/env/db_shash.c
+ $(CC) $(CFLAGS) $?
+db_truncate@o@: $(srcdir)/db/db_truncate.c
+ $(CC) $(CFLAGS) $?
+db_upg@o@: $(srcdir)/db/db_upg.c
+ $(CC) $(CFLAGS) $?
+db_upg_opd@o@: $(srcdir)/db/db_upg_opd.c
+ $(CC) $(CFLAGS) $?
+db_vrfy@o@: $(srcdir)/db/db_vrfy.c
+ $(CC) $(CFLAGS) $?
+db_vrfyutil@o@: $(srcdir)/db/db_vrfyutil.c
+ $(CC) $(CFLAGS) $?
+dbm@o@: $(srcdir)/dbm/dbm.c
+ $(CC) $(CFLAGS) $?
+dbreg@o@: $(srcdir)/dbreg/dbreg.c
+ $(CC) $(CFLAGS) $?
+dbreg_auto@o@: $(srcdir)/dbreg/dbreg_auto.c
+ $(CC) $(CFLAGS) $?
+dbreg_rec@o@: $(srcdir)/dbreg/dbreg_rec.c
+ $(CC) $(CFLAGS) $?
+dbreg_util@o@: $(srcdir)/dbreg/dbreg_util.c
+ $(CC) $(CFLAGS) $?
+env_file@o@: $(srcdir)/env/env_file.c
+ $(CC) $(CFLAGS) $?
+env_method@o@: $(srcdir)/env/env_method.c
+ $(CC) $(CFLAGS) $?
+env_open@o@: $(srcdir)/env/env_open.c
+ $(CC) $(CFLAGS) $?
+env_recover@o@: $(srcdir)/env/env_recover.c
+ $(CC) $(CFLAGS) $?
+env_region@o@: $(srcdir)/env/env_region.c
+ $(CC) $(CFLAGS) $?
+fileops_auto@o@: $(srcdir)/fileops/fileops_auto.c
+ $(CC) $(CFLAGS) $?
+fop_basic@o@: $(srcdir)/fileops/fop_basic.c
+ $(CC) $(CFLAGS) $?
+fop_rec@o@: $(srcdir)/fileops/fop_rec.c
+ $(CC) $(CFLAGS) $?
+fop_util@o@: $(srcdir)/fileops/fop_util.c
+ $(CC) $(CFLAGS) $?
+hash@o@: $(srcdir)/hash/hash.c
+ $(CC) $(CFLAGS) $?
+hash_auto@o@: $(srcdir)/hash/hash_auto.c
+ $(CC) $(CFLAGS) $?
+hash_conv@o@: $(srcdir)/hash/hash_conv.c
+ $(CC) $(CFLAGS) $?
+hash_dup@o@: $(srcdir)/hash/hash_dup.c
+ $(CC) $(CFLAGS) $?
+hash_func@o@: $(srcdir)/hash/hash_func.c
+ $(CC) $(CFLAGS) $?
+hash_meta@o@: $(srcdir)/hash/hash_meta.c
+ $(CC) $(CFLAGS) $?
+hash_method@o@: $(srcdir)/hash/hash_method.c
+ $(CC) $(CFLAGS) $?
+hash_open@o@: $(srcdir)/hash/hash_open.c
+ $(CC) $(CFLAGS) $?
+hash_page@o@: $(srcdir)/hash/hash_page.c
+ $(CC) $(CFLAGS) $?
+hash_rec@o@: $(srcdir)/hash/hash_rec.c
+ $(CC) $(CFLAGS) $?
+hash_reclaim@o@: $(srcdir)/hash/hash_reclaim.c
+ $(CC) $(CFLAGS) $?
+hash_stat@o@: $(srcdir)/hash/hash_stat.c
+ $(CC) $(CFLAGS) $?
+hash_upgrade@o@: $(srcdir)/hash/hash_upgrade.c
+ $(CC) $(CFLAGS) $?
+hash_verify@o@: $(srcdir)/hash/hash_verify.c
+ $(CC) $(CFLAGS) $?
+hmac@o@: $(srcdir)/hmac/hmac.c
+ $(CC) $(CFLAGS) $?
+hsearch@o@: $(srcdir)/hsearch/hsearch.c
+ $(CC) $(CFLAGS) $?
+lock@o@: $(srcdir)/lock/lock.c
+ $(CC) $(CFLAGS) $?
+lock_deadlock@o@:$(srcdir)/lock/lock_deadlock.c
+ $(CC) $(CFLAGS) $?
+lock_method@o@:$(srcdir)/lock/lock_method.c
+ $(CC) $(CFLAGS) $?
+lock_region@o@:$(srcdir)/lock/lock_region.c
+ $(CC) $(CFLAGS) $?
+lock_stat@o@:$(srcdir)/lock/lock_stat.c
+ $(CC) $(CFLAGS) $?
+lock_util@o@:$(srcdir)/lock/lock_util.c
+ $(CC) $(CFLAGS) $?
+log@o@: $(srcdir)/log/log.c
+ $(CC) $(CFLAGS) $?
+log_archive@o@: $(srcdir)/log/log_archive.c
+ $(CC) $(CFLAGS) $?
+log_compare@o@: $(srcdir)/log/log_compare.c
+ $(CC) $(CFLAGS) $?
+log_get@o@: $(srcdir)/log/log_get.c
+ $(CC) $(CFLAGS) $?
+log_method@o@: $(srcdir)/log/log_method.c
+ $(CC) $(CFLAGS) $?
+log_put@o@: $(srcdir)/log/log_put.c
+ $(CC) $(CFLAGS) $?
+mp_alloc@o@: $(srcdir)/mp/mp_alloc.c
+ $(CC) $(CFLAGS) $?
+mp_bh@o@: $(srcdir)/mp/mp_bh.c
+ $(CC) $(CFLAGS) $?
+mp_fget@o@: $(srcdir)/mp/mp_fget.c
+ $(CC) $(CFLAGS) $?
+mp_fopen@o@: $(srcdir)/mp/mp_fopen.c
+ $(CC) $(CFLAGS) $?
+mp_fput@o@: $(srcdir)/mp/mp_fput.c
+ $(CC) $(CFLAGS) $?
+mp_fset@o@: $(srcdir)/mp/mp_fset.c
+ $(CC) $(CFLAGS) $?
+mp_method@o@: $(srcdir)/mp/mp_method.c
+ $(CC) $(CFLAGS) $?
+mp_region@o@: $(srcdir)/mp/mp_region.c
+ $(CC) $(CFLAGS) $?
+mp_register@o@: $(srcdir)/mp/mp_register.c
+ $(CC) $(CFLAGS) $?
+mp_stat@o@: $(srcdir)/mp/mp_stat.c
+ $(CC) $(CFLAGS) $?
+mp_sync@o@: $(srcdir)/mp/mp_sync.c
+ $(CC) $(CFLAGS) $?
+mp_trickle@o@: $(srcdir)/mp/mp_trickle.c
+ $(CC) $(CFLAGS) $?
+mt19937db@o@: $(srcdir)/crypto/mersenne/mt19937db.c
+ $(CC) $(CFLAGS) $?
+mut_fcntl@o@: $(srcdir)/mutex/mut_fcntl.c
+ $(CC) $(CFLAGS) $?
+mut_pthread@o@: $(srcdir)/mutex/mut_pthread.c
+ $(CC) $(CFLAGS) $?
+mut_tas@o@: $(srcdir)/mutex/mut_tas.c
+ $(CC) $(CFLAGS) $?
+mutex@o@: $(srcdir)/mutex/mutex.c
+ $(CC) $(CFLAGS) $?
+os_abs@o@: $(srcdir)/os/os_abs.c
+ $(CC) $(CFLAGS) $?
+os_alloc@o@: $(srcdir)/os/os_alloc.c
+ $(CC) $(CFLAGS) $?
+os_clock@o@: $(srcdir)/os/os_clock.c
+ $(CC) $(CFLAGS) $?
+os_config@o@: $(srcdir)/os/os_config.c
+ $(CC) $(CFLAGS) $?
+os_dir@o@: $(srcdir)/os/os_dir.c
+ $(CC) $(CFLAGS) $?
+os_errno@o@: $(srcdir)/os/os_errno.c
+ $(CC) $(CFLAGS) $?
+os_fid@o@: $(srcdir)/os/os_fid.c
+ $(CC) $(CFLAGS) $?
+os_fsync@o@: $(srcdir)/os/os_fsync.c
+ $(CC) $(CFLAGS) $?
+os_id@o@: $(srcdir)/os/os_id.c
+ $(CC) $(CFLAGS) $?
+os_handle@o@: $(srcdir)/os/os_handle.c
+ $(CC) $(CFLAGS) $?
+os_map@o@: $(srcdir)/os/os_map.c
+ $(CC) $(CFLAGS) $?
+os_method@o@: $(srcdir)/os/os_method.c
+ $(CC) $(CFLAGS) $?
+os_oflags@o@: $(srcdir)/os/os_oflags.c
+ $(CC) $(CFLAGS) $?
+os_open@o@: $(srcdir)/os/os_open.c
+ $(CC) $(CFLAGS) $?
+os_region@o@: $(srcdir)/os/os_region.c
+ $(CC) $(CFLAGS) $?
+os_rename@o@: $(srcdir)/os/os_rename.c
+ $(CC) $(CFLAGS) $?
+os_root@o@: $(srcdir)/os/os_root.c
+ $(CC) $(CFLAGS) $?
+os_rpath@o@: $(srcdir)/os/os_rpath.c
+ $(CC) $(CFLAGS) $?
+os_rw@o@: $(srcdir)/os/os_rw.c
+ $(CC) $(CFLAGS) $?
+os_seek@o@: $(srcdir)/os/os_seek.c
+ $(CC) $(CFLAGS) $?
+os_sleep@o@: $(srcdir)/os/os_sleep.c
+ $(CC) $(CFLAGS) $?
+os_spin@o@: $(srcdir)/os/os_spin.c
+ $(CC) $(CFLAGS) $?
+os_stat@o@: $(srcdir)/os/os_stat.c
+ $(CC) $(CFLAGS) $?
+os_tmpdir@o@: $(srcdir)/os/os_tmpdir.c
+ $(CC) $(CFLAGS) $?
+os_unlink@o@: $(srcdir)/os/os_unlink.c
+ $(CC) $(CFLAGS) $?
qam@o@: $(srcdir)/qam/qam.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_auto@o@: $(srcdir)/qam/qam_auto.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_conv@o@: $(srcdir)/qam/qam_conv.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_files@o@: $(srcdir)/qam/qam_files.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_method@o@: $(srcdir)/qam/qam_method.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_open@o@: $(srcdir)/qam/qam_open.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_rec@o@: $(srcdir)/qam/qam_rec.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_stat@o@: $(srcdir)/qam/qam_stat.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_upgrade@o@: $(srcdir)/qam/qam_upgrade.c
- $(CC) $(CFLAGS) $?
+ $(CC) $(CFLAGS) $?
qam_verify@o@: $(srcdir)/qam/qam_verify.c
+ $(CC) $(CFLAGS) $?
+rep_method@o@: $(srcdir)/rep/rep_method.c
+ $(CC) $(CFLAGS) $?
+rep_record@o@: $(srcdir)/rep/rep_record.c
+ $(CC) $(CFLAGS) $?
+rep_region@o@: $(srcdir)/rep/rep_region.c
+ $(CC) $(CFLAGS) $?
+rep_util@o@: $(srcdir)/rep/rep_util.c
+ $(CC) $(CFLAGS) $?
+rijndael-alg-fst@o@: $(srcdir)/crypto/rijndael/rijndael-alg-fst.c
+ $(CC) $(CFLAGS) $?
+rijndael-api-fst@o@: $(srcdir)/crypto/rijndael/rijndael-api-fst.c
$(CC) $(CFLAGS) $?
+sha1@o@: $(srcdir)/hmac/sha1.c
+ $(CC) $(CFLAGS) $?
+txn@o@: $(srcdir)/txn/txn.c
+ $(CC) $(CFLAGS) $?
+txn_auto@o@: $(srcdir)/txn/txn_auto.c
+ $(CC) $(CFLAGS) $?
+txn_method@o@: $(srcdir)/txn/txn_method.c
+ $(CC) $(CFLAGS) $?
+txn_rec@o@: $(srcdir)/txn/txn_rec.c
+ $(CC) $(CFLAGS) $?
+txn_recover@o@: $(srcdir)/txn/txn_recover.c
+ $(CC) $(CFLAGS) $?
+txn_region@o@: $(srcdir)/txn/txn_region.c
+ $(CC) $(CFLAGS) $?
+txn_stat@o@: $(srcdir)/txn/txn_stat.c
+ $(CC) $(CFLAGS) $?
+txn_util@o@: $(srcdir)/txn/txn_util.c
+ $(CC) $(CFLAGS) $?
+util_cache@o@: $(srcdir)/common/util_cache.c
+ $(CC) $(CFLAGS) $?
+util_log@o@: $(srcdir)/common/util_log.c
+ $(CC) $(CFLAGS) $?
+util_sig@o@: $(srcdir)/common/util_sig.c
+ $(CC) $(CFLAGS) $?
+uts4_cc@o@: $(srcdir)/mutex/uts4_cc.s
+ $(AS) $(ASFLAGS) -o $@ $?
+xa@o@: $(srcdir)/xa/xa.c
+ $(CC) $(CFLAGS) $?
+xa_db@o@: $(srcdir)/xa/xa_db.c
+ $(CC) $(CFLAGS) $?
+xa_map@o@: $(srcdir)/xa/xa_map.c
+ $(CC) $(CFLAGS) $?
-# C++ files
-cxx_app@o@: $(srcdir)/cxx/cxx_app.cpp
+##################################################
+# C++ API build rules.
+##################################################
+cxx_db@o@: $(srcdir)/cxx/cxx_db.cpp
+ $(CXX) $(CXXFLAGS) $?
+cxx_dbc@o@: $(srcdir)/cxx/cxx_dbc.cpp
+ $(CXX) $(CXXFLAGS) $?
+cxx_dbt@o@: $(srcdir)/cxx/cxx_dbt.cpp
+ $(CXX) $(CXXFLAGS) $?
+cxx_env@o@: $(srcdir)/cxx/cxx_env.cpp
$(CXX) $(CXXFLAGS) $?
cxx_except@o@: $(srcdir)/cxx/cxx_except.cpp
$(CXX) $(CXXFLAGS) $?
cxx_lock@o@: $(srcdir)/cxx/cxx_lock.cpp
$(CXX) $(CXXFLAGS) $?
-cxx_log@o@: $(srcdir)/cxx/cxx_log.cpp
+cxx_logc@o@: $(srcdir)/cxx/cxx_logc.cpp
$(CXX) $(CXXFLAGS) $?
cxx_mpool@o@: $(srcdir)/cxx/cxx_mpool.cpp
$(CXX) $(CXXFLAGS) $?
-cxx_table@o@: $(srcdir)/cxx/cxx_table.cpp
- $(CXX) $(CXXFLAGS) $?
cxx_txn@o@: $(srcdir)/cxx/cxx_txn.cpp
$(CXX) $(CXXFLAGS) $?
-# Java files
+##################################################
+# Java API build rules.
+##################################################
java_Db@o@::$(srcdir)/libdb_java/java_Db.c
$(CC) $(CFLAGS) $?
java_DbEnv@o@: $(srcdir)/libdb_java/java_DbEnv.c
$(CC) $(CFLAGS) $?
java_DbLock@o@: $(srcdir)/libdb_java/java_DbLock.c
$(CC) $(CFLAGS) $?
+java_DbLogc@o@: $(srcdir)/libdb_java/java_DbLogc.c
+ $(CC) $(CFLAGS) $?
java_DbLsn@o@: $(srcdir)/libdb_java/java_DbLsn.c
$(CC) $(CFLAGS) $?
java_DbTxn@o@: $(srcdir)/libdb_java/java_DbTxn.c
$(CC) $(CFLAGS) $?
+java_DbUtil@o@: $(srcdir)/libdb_java/java_DbUtil.c
+ $(CC) $(CFLAGS) $?
java_Dbc@o@: $(srcdir)/libdb_java/java_Dbc.c
$(CC) $(CFLAGS) $?
java_Dbt@o@: $(srcdir)/libdb_java/java_Dbt.c
@@ -728,8 +1284,12 @@ java_locked@o@: $(srcdir)/libdb_java/java_locked.c
$(CC) $(CFLAGS) $?
java_util@o@: $(srcdir)/libdb_java/java_util.c
$(CC) $(CFLAGS) $?
+java_stat_auto@o@: $(srcdir)/libdb_java/java_stat_auto.c
+ $(CC) $(CFLAGS) $?
-# Tcl files
+##################################################
+# Tcl API build rules.
+##################################################
tcl_compat@o@: $(srcdir)/tcl/tcl_compat.c
$(CC) $(CFLAGS) $(TCFLAGS) $?
tcl_db@o@: $(srcdir)/tcl/tcl_db.c
@@ -748,132 +1308,16 @@ tcl_log@o@: $(srcdir)/tcl/tcl_log.c
$(CC) $(CFLAGS) $(TCFLAGS) $?
tcl_mp@o@: $(srcdir)/tcl/tcl_mp.c
$(CC) $(CFLAGS) $(TCFLAGS) $?
+tcl_rep@o@: $(srcdir)/tcl/tcl_rep.c
+ $(CC) $(CFLAGS) $(TCFLAGS) $?
tcl_txn@o@: $(srcdir)/tcl/tcl_txn.c
$(CC) $(CFLAGS) $(TCFLAGS) $?
+tcl_util@o@: $(srcdir)/tcl/tcl_util.c
+ $(CC) $(CFLAGS) $(TCFLAGS) $?
-# Hash files
-hash_auto@o@: $(srcdir)/hash/hash_auto.c
- $(CC) $(CFLAGS) $?
-hash@o@: $(srcdir)/hash/hash.c
- $(CC) $(CFLAGS) $?
-hash_conv@o@: $(srcdir)/hash/hash_conv.c
- $(CC) $(CFLAGS) $?
-hash_dup@o@: $(srcdir)/hash/hash_dup.c
- $(CC) $(CFLAGS) $?
-hash_func@o@: $(srcdir)/hash/hash_func.c
- $(CC) $(CFLAGS) $?
-hash_meta@o@: $(srcdir)/hash/hash_meta.c
- $(CC) $(CFLAGS) $?
-hash_method@o@: $(srcdir)/hash/hash_method.c
- $(CC) $(CFLAGS) $?
-hash_page@o@: $(srcdir)/hash/hash_page.c
- $(CC) $(CFLAGS) $?
-hash_rec@o@: $(srcdir)/hash/hash_rec.c
- $(CC) $(CFLAGS) $?
-hash_reclaim@o@: $(srcdir)/hash/hash_reclaim.c
- $(CC) $(CFLAGS) $?
-hash_stat@o@: $(srcdir)/hash/hash_stat.c
- $(CC) $(CFLAGS) $?
-hash_upgrade@o@: $(srcdir)/hash/hash_upgrade.c
- $(CC) $(CFLAGS) $?
-hash_verify@o@: $(srcdir)/hash/hash_verify.c
- $(CC) $(CFLAGS) $?
-
-# Lock files
-lock@o@: $(srcdir)/lock/lock.c
- $(CC) $(CFLAGS) $?
-lock_conflict@o@:$(srcdir)/lock/lock_conflict.c
- $(CC) $(CFLAGS) $?
-lock_deadlock@o@:$(srcdir)/lock/lock_deadlock.c
- $(CC) $(CFLAGS) $?
-lock_method@o@:$(srcdir)/lock/lock_method.c
- $(CC) $(CFLAGS) $?
-lock_region@o@:$(srcdir)/lock/lock_region.c
- $(CC) $(CFLAGS) $?
-lock_stat@o@:$(srcdir)/lock/lock_stat.c
- $(CC) $(CFLAGS) $?
-lock_util@o@:$(srcdir)/lock/lock_util.c
- $(CC) $(CFLAGS) $?
-
-# Log files
-log@o@: $(srcdir)/log/log.c
- $(CC) $(CFLAGS) $?
-log_archive@o@: $(srcdir)/log/log_archive.c
- $(CC) $(CFLAGS) $?
-log_auto@o@: $(srcdir)/log/log_auto.c
- $(CC) $(CFLAGS) $?
-log_compare@o@: $(srcdir)/log/log_compare.c
- $(CC) $(CFLAGS) $?
-log_findckp@o@: $(srcdir)/log/log_findckp.c
- $(CC) $(CFLAGS) $?
-log_get@o@: $(srcdir)/log/log_get.c
- $(CC) $(CFLAGS) $?
-log_method@o@: $(srcdir)/log/log_method.c
- $(CC) $(CFLAGS) $?
-log_put@o@: $(srcdir)/log/log_put.c
- $(CC) $(CFLAGS) $?
-log_rec@o@: $(srcdir)/log/log_rec.c
- $(CC) $(CFLAGS) $?
-log_register@o@: $(srcdir)/log/log_register.c
- $(CC) $(CFLAGS) $?
-
-# Mpool files
-mp_alloc@o@: $(srcdir)/mp/mp_alloc.c
- $(CC) $(CFLAGS) $?
-mp_bh@o@: $(srcdir)/mp/mp_bh.c
- $(CC) $(CFLAGS) $?
-mp_fget@o@: $(srcdir)/mp/mp_fget.c
- $(CC) $(CFLAGS) $?
-mp_fopen@o@: $(srcdir)/mp/mp_fopen.c
- $(CC) $(CFLAGS) $?
-mp_fput@o@: $(srcdir)/mp/mp_fput.c
- $(CC) $(CFLAGS) $?
-mp_fset@o@: $(srcdir)/mp/mp_fset.c
- $(CC) $(CFLAGS) $?
-mp_method@o@: $(srcdir)/mp/mp_method.c
- $(CC) $(CFLAGS) $?
-mp_region@o@: $(srcdir)/mp/mp_region.c
- $(CC) $(CFLAGS) $?
-mp_register@o@: $(srcdir)/mp/mp_register.c
- $(CC) $(CFLAGS) $?
-mp_stat@o@: $(srcdir)/mp/mp_stat.c
- $(CC) $(CFLAGS) $?
-mp_sync@o@: $(srcdir)/mp/mp_sync.c
- $(CC) $(CFLAGS) $?
-mp_trickle@o@: $(srcdir)/mp/mp_trickle.c
- $(CC) $(CFLAGS) $?
-
-# Mutex files
-mutex@o@: $(srcdir)/mutex/mutex.c
- $(CC) $(CFLAGS) $?
-mut_fcntl@o@: $(srcdir)/mutex/mut_fcntl.c
- $(CC) $(CFLAGS) $?
-mut_pthread@o@: $(srcdir)/mutex/mut_pthread.c
- $(CC) $(CFLAGS) $?
-mut_tas@o@: $(srcdir)/mutex/mut_tas.c
- $(CC) $(CFLAGS) $?
-# UTS4 spinlock assembly.
-uts4_cc@o@: $(srcdir)/mutex/uts4_cc.s
- $(AS) $(ASFLAGS) -o $@ $?
-
-# Transaction files
-txn@o@: $(srcdir)/txn/txn.c
- $(CC) $(CFLAGS) $?
-txn_auto@o@: $(srcdir)/txn/txn_auto.c
- $(CC) $(CFLAGS) $?
-txn_rec@o@: $(srcdir)/txn/txn_rec.c
- $(CC) $(CFLAGS) $?
-txn_region@o@: $(srcdir)/txn/txn_region.c
- $(CC) $(CFLAGS) $?
-
-# XA files
-xa@o@: $(srcdir)/xa/xa.c
- $(CC) $(CFLAGS) $?
-xa_db@o@: $(srcdir)/xa/xa_db.c
- $(CC) $(CFLAGS) $?
-xa_map@o@: $(srcdir)/xa/xa_map.c
- $(CC) $(CFLAGS) $?
-
+##################################################
+# RPC build rules.
+##################################################
# RPC client files
client@o@: $(srcdir)/rpc_client/client.c
$(CC) $(CFLAGS) $?
@@ -885,98 +1329,50 @@ gen_client_ret@o@: $(srcdir)/rpc_client/gen_client_ret.c
$(CC) $(CFLAGS) $?
# RPC server files
-db_server_proc@o@: $(srcdir)/rpc_server/db_server_proc.c
- $(CC) $(CFLAGS) $?
-db_server_svc@o@: $(srcdir)/rpc_server/db_server_svc.c
- $(CC) $(CFLAGS) $?
-db_server_util@o@: $(srcdir)/rpc_server/db_server_util.c
+db_server_proc@o@: $(srcdir)/rpc_server/c/db_server_proc.c
$(CC) $(CFLAGS) $?
-db_server_xdr@o@: $(srcdir)/rpc_server/db_server_xdr.c
+db_server_svc@o@: $(srcdir)/rpc_server/c/db_server_svc.c
$(CC) $(CFLAGS) $?
-gen_db_server@o@: $(srcdir)/rpc_server/gen_db_server.c
+db_server_util@o@: $(srcdir)/rpc_server/c/db_server_util.c
$(CC) $(CFLAGS) $?
-
-# Historic compatibility files
-db185@o@: $(srcdir)/db185/db185.c
+db_server_xdr@o@: $(srcdir)/rpc_server/c/db_server_xdr.c
$(CC) $(CFLAGS) $?
-dbm@o@: $(srcdir)/dbm/dbm.c
- $(CC) $(CFLAGS) $?
-hsearch@o@: $(srcdir)/hsearch/hsearch.c
+gen_db_server@o@: $(srcdir)/rpc_server/c/gen_db_server.c
$(CC) $(CFLAGS) $?
+db_server_cxxproc@o@: $(srcdir)/rpc_server/cxx/db_server_cxxproc.cpp
+ $(CXX) $(CXXFLAGS) $?
+db_server_cxxutil@o@: $(srcdir)/rpc_server/cxx/db_server_cxxutil.cpp
+ $(CXX) $(CXXFLAGS) $?
-# OS specific files
-os_abs@o@: $(srcdir)/os/os_abs.c
- $(CC) $(CFLAGS) $?
-os_alloc@o@: $(srcdir)/os/os_alloc.c
- $(CC) $(CFLAGS) $?
-os_dir@o@: $(srcdir)/os/os_dir.c
- $(CC) $(CFLAGS) $?
-os_errno@o@: $(srcdir)/os/os_errno.c
- $(CC) $(CFLAGS) $?
-os_fid@o@: $(srcdir)/os/os_fid.c
- $(CC) $(CFLAGS) $?
-os_finit@o@: $(srcdir)/os/os_finit.c
- $(CC) $(CFLAGS) $?
-os_fsync@o@: $(srcdir)/os/os_fsync.c
- $(CC) $(CFLAGS) $?
-os_handle@o@: $(srcdir)/os/os_handle.c
- $(CC) $(CFLAGS) $?
-os_map@o@: $(srcdir)/os/os_map.c
- $(CC) $(CFLAGS) $?
-os_method@o@: $(srcdir)/os/os_method.c
- $(CC) $(CFLAGS) $?
-os_oflags@o@: $(srcdir)/os/os_oflags.c
- $(CC) $(CFLAGS) $?
-os_open@o@: $(srcdir)/os/os_open.c
- $(CC) $(CFLAGS) $?
-os_region@o@: $(srcdir)/os/os_region.c
- $(CC) $(CFLAGS) $?
-os_rename@o@: $(srcdir)/os/os_rename.c
+##################################################
+# Utility build rules.
+##################################################
+db_archive@o@: $(srcdir)/db_archive/db_archive.c
$(CC) $(CFLAGS) $?
-os_root@o@: $(srcdir)/os/os_root.c
+db_checkpoint@o@: $(srcdir)/db_checkpoint/db_checkpoint.c
$(CC) $(CFLAGS) $?
-os_rpath@o@: $(srcdir)/os/os_rpath.c
+db_deadlock@o@: $(srcdir)/db_deadlock/db_deadlock.c
$(CC) $(CFLAGS) $?
-os_rw@o@: $(srcdir)/os/os_rw.c
+db_dump@o@: $(srcdir)/db_dump/db_dump.c
$(CC) $(CFLAGS) $?
-os_seek@o@: $(srcdir)/os/os_seek.c
+db_dump185@o@: $(srcdir)/db_dump185/db_dump185.c
+ $(CC) $(DB185INC) $?
+db_load@o@: $(srcdir)/db_load/db_load.c
$(CC) $(CFLAGS) $?
-os_sleep@o@: $(srcdir)/os/os_sleep.c
+db_printlog@o@: $(srcdir)/db_printlog/db_printlog.c
$(CC) $(CFLAGS) $?
-os_spin@o@: $(srcdir)/os/os_spin.c
+db_recover@o@: $(srcdir)/db_recover/db_recover.c
$(CC) $(CFLAGS) $?
-os_stat@o@: $(srcdir)/os/os_stat.c
+db_stat@o@: $(srcdir)/db_stat/db_stat.c
$(CC) $(CFLAGS) $?
-os_tmpdir@o@: $(srcdir)/os/os_tmpdir.c
+db_upgrade@o@: $(srcdir)/db_upgrade/db_upgrade.c
$(CC) $(CFLAGS) $?
-os_unlink@o@: $(srcdir)/os/os_unlink.c
+db_verify@o@: $(srcdir)/db_verify/db_verify.c
$(CC) $(CFLAGS) $?
-# Dbs.
-dbs@o@: $(srcdir)/test_server/dbs.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_am@o@: $(srcdir)/test_server/dbs_am.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_checkpoint@o@: $(srcdir)/test_server/dbs_checkpoint.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_debug@o@: $(srcdir)/test_server/dbs_debug.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_handles@o@: $(srcdir)/test_server/dbs_handles.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_log@o@: $(srcdir)/test_server/dbs_log.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_qam@o@: $(srcdir)/test_server/dbs_qam.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_spawn@o@: $(srcdir)/test_server/dbs_spawn.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_trickle@o@: $(srcdir)/test_server/dbs_trickle.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_util@o@: $(srcdir)/test_server/dbs_util.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-dbs_yield@o@: $(srcdir)/test_server/dbs_yield.c
- $(CC) $(CFLAGS) -I$(srcdir)/test_server $?
-
-# Replacement files
+##################################################
+# C library replacement files.
+##################################################
getcwd@o@: $(srcdir)/clib/getcwd.c
$(CC) $(CFLAGS) $?
getopt@o@: $(srcdir)/clib/getopt.c
@@ -991,12 +1387,11 @@ raise@o@: $(srcdir)/clib/raise.c
$(CC) $(CFLAGS) $?
strcasecmp@o@: $(srcdir)/clib/strcasecmp.c
$(CC) $(CFLAGS) $?
+strdup@o@: $(srcdir)/clib/strdup.c
+ $(CC) $(CFLAGS) $?
snprintf@o@: $(srcdir)/clib/snprintf.c
$(CC) $(CFLAGS) $?
strerror@o@: $(srcdir)/clib/strerror.c
$(CC) $(CFLAGS) $?
vsnprintf@o@: $(srcdir)/clib/vsnprintf.c
$(CC) $(CFLAGS) $?
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/bdb/dist/RELEASE b/bdb/dist/RELEASE
index 7b7d7bde003..61151b8589c 100644
--- a/bdb/dist/RELEASE
+++ b/bdb/dist/RELEASE
@@ -1,8 +1,28 @@
-# $Id: RELEASE,v 11.72 2001/01/24 15:20:14 bostic Exp $
+# $Id: RELEASE,v 11.123 2002/09/13 22:16:02 bostic Exp $
+
+DB_VERSION_MAJOR=4
+DB_VERSION_MINOR=1
+DB_VERSION_PATCH=24
+DB_VERSION="$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH"
+
+DB_VERSION_UNIQUE_NAME=`printf "_%d%03d" $DB_VERSION_MAJOR $DB_VERSION_MINOR`
-DB_VERSION_MAJOR=3
-DB_VERSION_MINOR=2
-DB_VERSION_PATCH=9
DB_RELEASE_DATE=`date "+%B %e, %Y"`
+DB_VERSION_STRING="Sleepycat Software: Berkeley DB $DB_VERSION: ($DB_RELEASE_DATE)"
+
+# this file is included by all s_* scripts, so it's the way to apply
+# hacks :)
+
+# bitkeeper doesn't like somebody to mess with permissions!
+chmod()
+{
+ echo "chmod $1 $2" >/dev/null
+}
+
+# useful trick to find auto-generated files
+#cmp()
+#{
+# echo "==>> CMP $1 $2" >/dev/tty
+# /usr/bin/cmp "$1" "$2"
+#}
-DB_VERSION_STRING="Sleepycat Software: Berkeley DB $DB_VERSION_MAJOR.$DB_VERSION_MINOR.${DB_VERSION_PATCH}a: ($DB_RELEASE_DATE)"
diff --git a/bdb/dist/acconfig.h b/bdb/dist/acconfig.h
deleted file mode 100644
index 19f85a460d9..00000000000
--- a/bdb/dist/acconfig.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: acconfig.h,v 11.29 2000/09/20 16:30:33 bostic Exp $
- */
-
-/* Define if you are building a version for running the test suite. */
-#undef CONFIG_TEST
-
-/* Define if you want a debugging version. */
-#undef DEBUG
-
-/* Define if you want a version that logs read operations. */
-#undef DEBUG_ROP
-
-/* Define if you want a version that logs write operations. */
-#undef DEBUG_WOP
-
-/* Define if you want a version with run-time diagnostic checking. */
-#undef DIAGNOSTIC
-
-/* Define if you want to mask harmless unitialized memory read/writes. */
-#undef UMRW
-
-/* Define if fcntl/F_SETFD denies child access to file descriptors. */
-#undef HAVE_FCNTL_F_SETFD
-
-/* Define if building big-file environment (e.g., AIX, HP/UX, Solaris). */
-#undef HAVE_FILE_OFFSET_BITS
-
-/* Mutex possibilities. */
-#undef HAVE_MUTEX_68K_GCC_ASSEMBLY
-#undef HAVE_MUTEX_AIX_CHECK_LOCK
-#undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
-#undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
-#undef HAVE_MUTEX_HPPA_MSEM_INIT
-#undef HAVE_MUTEX_IA64_GCC_ASSEMBLY
-#undef HAVE_MUTEX_MACOS
-#undef HAVE_MUTEX_MSEM_INIT
-#undef HAVE_MUTEX_PPC_GCC_ASSEMBLY
-#undef HAVE_MUTEX_PTHREADS
-#undef HAVE_MUTEX_RELIANTUNIX_INITSPIN
-#undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY
-#undef HAVE_MUTEX_SEMA_INIT
-#undef HAVE_MUTEX_SGI_INIT_LOCK
-#undef HAVE_MUTEX_SOLARIS_LOCK_TRY
-#undef HAVE_MUTEX_SOLARIS_LWP
-#undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY
-#undef HAVE_MUTEX_THREADS
-#undef HAVE_MUTEX_UI_THREADS
-#undef HAVE_MUTEX_UTS_CC_ASSEMBLY
-#undef HAVE_MUTEX_VMS
-#undef HAVE_MUTEX_VXWORKS
-#undef HAVE_MUTEX_WIN16
-#undef HAVE_MUTEX_WIN32
-#undef HAVE_MUTEX_X86_GCC_ASSEMBLY
-#undef HAVE_MUTEX_X86_64_GCC_ASSEMBLY
-
-/* Define if building on QNX. */
-#undef HAVE_QNX
-
-/* Define if building RPC client/server. */
-#undef HAVE_RPC
-
-/* Define if your sprintf returns a pointer, not a length. */
-#undef SPRINTF_RET_CHARPNT
-
-@BOTTOM@
-
-/*
- * Big-file configuration.
- */
-#ifdef HAVE_FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 64
-#endif
-
-/*
- * Don't step on the namespace. Other libraries may have their own
- * implementations of these functions, we don't want to use their
- * implementations or force them to use ours based on the load order.
- */
-#ifndef HAVE_GETCWD
-#define getcwd __db_Cgetcwd
-#endif
-#ifndef HAVE_GETOPT
-#define getopt __db_Cgetopt
-#endif
-#ifndef HAVE_MEMCMP
-#define memcmp __db_Cmemcmp
-#endif
-#ifndef HAVE_MEMCPY
-#define memcpy __db_Cmemcpy
-#endif
-#ifndef HAVE_MEMMOVE
-#define memmove __db_Cmemmove
-#endif
-#ifndef HAVE_RAISE
-#define raise __db_Craise
-#endif
-#ifndef HAVE_SNPRINTF
-#define snprintf __db_Csnprintf
-#endif
-#ifndef HAVE_STRCASECMP
-#define strcasecmp __db_Cstrcasecmp
-#endif
-#ifndef HAVE_STRERROR
-#define strerror __db_Cstrerror
-#endif
-#ifndef HAVE_VSNPRINTF
-#define vsnprintf __db_Cvsnprintf
-#endif
diff --git a/bdb/dist/aclocal/config.ac b/bdb/dist/aclocal/config.ac
new file mode 100644
index 00000000000..cd288425946
--- /dev/null
+++ b/bdb/dist/aclocal/config.ac
@@ -0,0 +1,51 @@
+# Features we don't test for, but want the #defines to exist for
+# other ports.
+AH_TEMPLATE(HAVE_VXWORKS, [Define to 1 if building VxWorks.])
+
+AH_TEMPLATE(HAVE_FILESYSTEM_NOTZERO,
+ [Define to 1 if allocated filesystem blocks are not zeroed.])
+
+AH_TEMPLATE(HAVE_UNLINK_WITH_OPEN_FAILURE,
+ [Define to 1 if unlink of file with open file descriptors will fail.])
+
+AH_BOTTOM([/*
+ * Exit success/failure macros.
+ */
+#ifndef HAVE_EXIT_SUCCESS
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+#endif
+
+/*
+ * Don't step on the namespace. Other libraries may have their own
+ * implementations of these functions, we don't want to use their
+ * implementations or force them to use ours based on the load order.
+ */
+#ifndef HAVE_GETCWD
+#define getcwd __db_Cgetcwd
+#endif
+#ifndef HAVE_MEMCMP
+#define memcmp __db_Cmemcmp
+#endif
+#ifndef HAVE_MEMCPY
+#define memcpy __db_Cmemcpy
+#endif
+#ifndef HAVE_MEMMOVE
+#define memmove __db_Cmemmove
+#endif
+#ifndef HAVE_RAISE
+#define raise __db_Craise
+#endif
+#ifndef HAVE_SNPRINTF
+#define snprintf __db_Csnprintf
+#endif
+#ifndef HAVE_STRCASECMP
+#define strcasecmp __db_Cstrcasecmp
+#define strncasecmp __db_Cstrncasecmp
+#endif
+#ifndef HAVE_STRERROR
+#define strerror __db_Cstrerror
+#endif
+#ifndef HAVE_VSNPRINTF
+#define vsnprintf __db_Cvsnprintf
+#endif])
diff --git a/bdb/dist/aclocal/cxx.ac b/bdb/dist/aclocal/cxx.ac
new file mode 100644
index 00000000000..49103cc661a
--- /dev/null
+++ b/bdb/dist/aclocal/cxx.ac
@@ -0,0 +1,17 @@
+# C++ checks to determine what style of headers to use and
+# whether to use "using" clauses.
+
+AC_DEFUN(AC_CXX_HAVE_STDHEADERS, [
+AC_SUBST(cxx_have_stdheaders)
+AC_CACHE_CHECK([whether C++ supports the ISO C++ standard includes],
+db_cv_cxx_have_stdheaders,
+[AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <iostream>
+],[std::ostream *o; return 0;],
+ db_cv_cxx_have_stdheaders=yes, db_cv_cxx_have_stdheaders=no)
+ AC_LANG_RESTORE
+])
+if test "$db_cv_cxx_have_stdheaders" = yes; then
+ cxx_have_stdheaders="#define HAVE_CXX_STDHEADERS 1"
+fi])
diff --git a/bdb/dist/aclocal/gcc.ac b/bdb/dist/aclocal/gcc.ac
new file mode 100644
index 00000000000..0949d982f17
--- /dev/null
+++ b/bdb/dist/aclocal/gcc.ac
@@ -0,0 +1,36 @@
+# Version 2.96 of gcc (shipped with RedHat Linux 7.[01] and Mandrake) had
+# serious problems.
+AC_DEFUN(AC_GCC_CONFIG1, [
+AC_CACHE_CHECK([whether we are using gcc version 2.96],
+db_cv_gcc_2_96, [
+db_cv_gcc_2_96=no
+if test "$GCC" = "yes"; then
+ GCC_VERSION=`${MAKEFILE_CC} --version`
+ case ${GCC_VERSION} in
+ 2.96*)
+ db_cv_gcc_2_96=yes;;
+ esac
+fi])
+if test "$db_cv_gcc_2_96" = "yes"; then
+ CFLAGS=`echo "$CFLAGS" | sed 's/-O2/-O/'`
+ CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-O2/-O/'`
+ AC_MSG_WARN([INSTALLED GCC COMPILER HAS SERIOUS BUGS; PLEASE UPGRADE.])
+ AC_MSG_WARN([GCC OPTIMIZATION LEVEL SET TO -O.])
+fi])
+
+# Versions of g++ up to 2.8.0 required -fhandle-exceptions, but it is
+# renamed as -fexceptions and is the default in versions 2.8.0 and after.
+AC_DEFUN(AC_GCC_CONFIG2, [
+AC_CACHE_CHECK([whether g++ requires -fhandle-exceptions],
+db_cv_gxx_except, [
+db_cv_gxx_except=no;
+if test "$GXX" = "yes"; then
+ GXX_VERSION=`${MAKEFILE_CXX} --version`
+ case ${GXX_VERSION} in
+ 1.*|2.[[01234567]].*|*-1.*|*-2.[[01234567]].*)
+ db_cv_gxx_except=yes;;
+ esac
+fi])
+if test "$db_cv_gxx_except" = "yes"; then
+ CXXFLAGS="$CXXFLAGS -fhandle-exceptions"
+fi])
diff --git a/bdb/dist/aclocal/libtool.ac b/bdb/dist/aclocal/libtool.ac
new file mode 100644
index 00000000000..e99faf15e4e
--- /dev/null
+++ b/bdb/dist/aclocal/libtool.ac
@@ -0,0 +1,3633 @@
+# libtool.m4 - Configure libtool for the host system. -*-Shell-script-*-
+## Copyright 1996, 1997, 1998, 1999, 2000, 2001
+## Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## 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.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+# serial 46 AC_PROG_LIBTOOL
+
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])
+
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+_LT_AC_PROG_ECHO_BACKSLASH
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ AC_PATH_MAGIC
+ fi
+ ;;
+esac
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE(libtool-lock,
+ [ --disable-libtool-lock avoid locking (might break parallel builds)])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_SAVE
+ AC_LANG_C
+ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_RESTORE])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+
+ # recent cygwin and mingw systems supply a stub DllMain which the user
+ # can override, but on older systems we have to supply one
+ AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain,
+ [AC_TRY_LINK([],
+ [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*);
+ DllMain (0, 0, 0);],
+ [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])])
+
+ case $host/$CC in
+ *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*)
+ # old mingw systems require "-dll" to link a DLL, while more recent ones
+ # require "-mdll"
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -mdll"
+ AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch,
+ [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])])
+ CFLAGS="$SAVE_CFLAGS" ;;
+ *-*-cygwin* | *-*-pw32*)
+ # cygwin systems need to pass --dll to the linker, and not link
+ # crt.o which will require a WinMain@16 definition.
+ lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;;
+ esac
+ ;;
+ ])
+esac
+
+_LT_AC_LTCONFIG_HACK
+
+])
+
+# AC_LIBTOOL_HEADER_ASSERT
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT],
+[AC_CACHE_CHECK([whether $CC supports assert without backlinking],
+ [lt_cv_func_assert_works],
+ [case $host in
+ *-*-solaris*)
+ if test "$GCC" = yes && test "$with_gnu_ld" != yes; then
+ case `$CC --version 2>/dev/null` in
+ [[12]].*) lt_cv_func_assert_works=no ;;
+ *) lt_cv_func_assert_works=yes ;;
+ esac
+ fi
+ ;;
+ esac])
+
+if test "x$lt_cv_func_assert_works" = xyes; then
+ AC_CHECK_HEADERS(assert.h)
+fi
+])# AC_LIBTOOL_HEADER_ASSERT
+
+# _LT_AC_CHECK_DLFCN
+# --------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)
+])# _LT_AC_CHECK_DLFCN
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+irix*)
+ symcode='[[BCDEGRST]]'
+ ;;
+solaris* | sysv5*)
+ symcode='[[BDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $host_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+ symcode='[[ABCDGISTW]]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+ if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+ sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+ if AC_TRY_EVAL(ac_link) && test -s conftest; then
+ pipe_works=yes
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AC_FD_CC
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AC_FD_CC
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
+ fi
+ else
+ echo "$progname: failed program was:" >&AC_FD_CC
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ global_symbol_to_cdecl=
+ global_symbol_to_c_name_address=
+else
+ global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
+ global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
+fi
+if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
+then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+# ---------------------------------
+AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR],
+[# Find the correct PATH separator. Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+ UNAME=${UNAME-`uname 2>/dev/null`}
+ case X$UNAME in
+ *-DOS) lt_cv_sys_path_separator=';' ;;
+ *) lt_cv_sys_path_separator=':' ;;
+ esac
+ PATH_SEPARATOR=$lt_cv_sys_path_separator
+fi
+])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+ echo_test_string="`eval $cmd`" &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+AC_DIVERT_POP
+])# _LT_AC_PROG_ECHO_BACKSLASH
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}]
+EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_unknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+# AC_LIBTOOL_DLOPEN_SELF
+# -------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+AC_DEFUN([_LT_AC_LTCONFIG_HACK],
+[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+need_locks="$enable_libtool_lock"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+if test x"$host" != x"$build"; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case $host_os in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+ ;;
+ *)
+ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="[$]2"
+
+## FIXME: this should be a separate macro
+##
+AC_MSG_CHECKING([for objdir])
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+AC_MSG_RESULT($objdir)
+##
+## END FIXME
+
+
+## FIXME: this should be a separate macro
+##
+AC_ARG_WITH(pic,
+[ --with-pic try to use only PIC/non-PIC objects [default=use both]],
+pic_mode="$withval", pic_mode=default)
+test -z "$pic_mode" && pic_mode=default
+
+# We assume here that the value for lt_cv_prog_cc_pic will not be cached
+# in isolation, and that seeing it set (from the cache) indicates that
+# the associated values are set (in the cache) correctly too.
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+AC_CACHE_VAL(lt_cv_prog_cc_pic,
+[ lt_cv_prog_cc_pic=
+ lt_cv_prog_cc_shlib=
+ lt_cv_prog_cc_wl=
+ lt_cv_prog_cc_static=
+ lt_cv_prog_cc_no_builtin=
+ lt_cv_prog_cc_can_build_shared=$can_build_shared
+
+ if test "$GCC" = yes; then
+ lt_cv_prog_cc_wl='-Wl,'
+ lt_cv_prog_cc_static='-static'
+
+ case $host_os in
+ aix*)
+ # Below there is a dirty hack to force normal static linking with -ldl
+ # The problem is because libdl dynamically linked with both libc and
+ # libC (AIX C++ library), which obviously doesn't included in libraries
+ # list by gcc. This cause undefined symbols with -static flags.
+ # This hack allows C programs to be linked with "-static -ldl", but
+ # not sure about C++ programs.
+ lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_cv_prog_cc_pic='-fno-common'
+ ;;
+ cygwin* | mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_cv_prog_cc_pic='-DDLL_EXPORT'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_cv_prog_cc_pic=-Kconform_pic
+ fi
+ ;;
+ *)
+ lt_cv_prog_cc_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for PIC flags for the system compiler.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ lt_cv_prog_cc_wl='-Wl,'
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_cv_prog_cc_static='-Bstatic'
+ else
+ lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
+ lt_cv_prog_cc_wl='-Wl,'
+ lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
+ lt_cv_prog_cc_pic='+Z'
+ ;;
+
+ irix5* | irix6*)
+ lt_cv_prog_cc_wl='-Wl,'
+ lt_cv_prog_cc_static='-non_shared'
+ # PIC (with -KPIC) is the default.
+ ;;
+
+ cygwin* | mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_cv_prog_cc_pic='-DDLL_EXPORT'
+ ;;
+
+ newsos6)
+ lt_cv_prog_cc_pic='-KPIC'
+ lt_cv_prog_cc_static='-Bstatic'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ # All OSF/1 code is PIC.
+ lt_cv_prog_cc_wl='-Wl,'
+ lt_cv_prog_cc_static='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ lt_cv_prog_cc_pic='-Kpic'
+ lt_cv_prog_cc_static='-dn'
+ lt_cv_prog_cc_shlib='-belf'
+ ;;
+
+ solaris*)
+ lt_cv_prog_cc_pic='-KPIC'
+ lt_cv_prog_cc_static='-Bstatic'
+ lt_cv_prog_cc_wl='-Wl,'
+ ;;
+
+ sunos4*)
+ lt_cv_prog_cc_pic='-PIC'
+ lt_cv_prog_cc_static='-Bstatic'
+ lt_cv_prog_cc_wl='-Qoption ld '
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ lt_cv_prog_cc_pic='-KPIC'
+ lt_cv_prog_cc_static='-Bstatic'
+ if test "x$host_vendor" = xsni; then
+ lt_cv_prog_cc_wl='-LD'
+ else
+ lt_cv_prog_cc_wl='-Wl,'
+ fi
+ ;;
+
+ uts4*)
+ lt_cv_prog_cc_pic='-pic'
+ lt_cv_prog_cc_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_cv_prog_cc_pic='-Kconform_pic'
+ lt_cv_prog_cc_static='-Bstatic'
+ fi
+ ;;
+
+ *)
+ lt_cv_prog_cc_can_build_shared=no
+ ;;
+ esac
+ fi
+])
+if test -z "$lt_cv_prog_cc_pic"; then
+ AC_MSG_RESULT([none])
+else
+ AC_MSG_RESULT([$lt_cv_prog_cc_pic])
+
+ # Check to make sure the pic_flag actually works.
+ AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works])
+ AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+ AC_TRY_COMPILE([], [], [dnl
+ case $host_os in
+ hpux9* | hpux10* | hpux11*)
+ # On HP-UX, both CC and GCC only warn that PIC is supported... then
+ # they create non-PIC objects. So, if there were any warnings, we
+ # assume that PIC is not supported.
+ if test -s conftest.err; then
+ lt_cv_prog_cc_pic_works=no
+ else
+ lt_cv_prog_cc_pic_works=yes
+ fi
+ ;;
+ *)
+ lt_cv_prog_cc_pic_works=yes
+ ;;
+ esac
+ ], [dnl
+ lt_cv_prog_cc_pic_works=no
+ ])
+ CFLAGS="$save_CFLAGS"
+ ])
+
+ if test "X$lt_cv_prog_cc_pic_works" = Xno; then
+ lt_cv_prog_cc_pic=
+ lt_cv_prog_cc_can_build_shared=no
+ else
+ lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
+ fi
+
+ AC_MSG_RESULT([$lt_cv_prog_cc_pic_works])
+fi
+##
+## END FIXME
+
+# Check for any special shared library compilation flags.
+if test -n "$lt_cv_prog_cc_shlib"; then
+ AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries])
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$lt_cv_prog_cc_shlib[[ ]]" >/dev/null; then :
+ else
+ AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure])
+ lt_cv_prog_cc_can_build_shared=no
+ fi
+fi
+
+## FIXME: this should be a separate macro
+##
+AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works])
+AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl
+ lt_cv_prog_cc_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+ AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes])
+ LDFLAGS="$save_LDFLAGS"
+])
+
+# Belt *and* braces to stop my trousers falling down:
+test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
+AC_MSG_RESULT([$lt_cv_prog_cc_static_works])
+
+pic_flag="$lt_cv_prog_cc_pic"
+special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
+wl="$lt_cv_prog_cc_wl"
+link_static_flag="$lt_cv_prog_cc_static"
+no_builtin_flag="$lt_cv_prog_cc_no_builtin"
+can_build_shared="$lt_cv_prog_cc_can_build_shared"
+##
+## END FIXME
+
+
+## FIXME: this should be a separate macro
+##
+# Check to see if options -o and -c are simultaneously supported by compiler
+AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext])
+AC_CACHE_VAL([lt_cv_compiler_c_o], [
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+echo "int some_variable = 0;" > conftest.$ac_ext
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory. Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+compiler_c_o=no
+if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+ lt_cv_compiler_c_o=no
+ else
+ lt_cv_compiler_c_o=yes
+ fi
+else
+ # Append any errors to the config.log.
+ cat out/conftest.err 1>&AC_FD_CC
+ lt_cv_compiler_c_o=no
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+])
+compiler_c_o=$lt_cv_compiler_c_o
+AC_MSG_RESULT([$compiler_c_o])
+
+if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+ AC_MSG_CHECKING([if $compiler supports -c -o file.lo])
+ AC_CACHE_VAL([lt_cv_compiler_o_lo], [
+ lt_cv_compiler_o_lo=no
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+ save_objext="$ac_objext"
+ ac_objext=lo
+ AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ lt_cv_compiler_o_lo=no
+ else
+ lt_cv_compiler_o_lo=yes
+ fi
+ ])
+ ac_objext="$save_objext"
+ CFLAGS="$save_CFLAGS"
+ ])
+ compiler_o_lo=$lt_cv_compiler_o_lo
+ AC_MSG_RESULT([$compiler_o_lo])
+else
+ compiler_o_lo=no
+fi
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+if test "$GCC" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+ AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions])
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+ compiler_rtti_exceptions=no
+ AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ compiler_rtti_exceptions=no
+ else
+ compiler_rtti_exceptions=yes
+ fi
+ ])
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([$compiler_rtti_exceptions])
+
+ if test "$compiler_rtti_exceptions" = "yes"; then
+ no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+ else
+ no_builtin_flag=' -fno-builtin'
+ fi
+fi
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+# See if the linker supports building shared libraries.
+AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries])
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+old_archive_from_expsyms_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_into_libs=no
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+link_all_deplibs=unknown
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced. Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+extract_expsyms_cmds=
+
+case $host_os in
+cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+openbsd*)
+ with_gnu_ld=no
+ ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX, the GNU linker is very broken
+ # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+
+ extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
+ sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
+ test -f $output_objdir/impgen.exe || (cd $output_objdir && \
+ if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
+ else $CC -o impgen impgen.c ; fi)~
+ $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
+
+ old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
+
+ # cygwin and mingw dlls have different entry points and sets of symbols
+ # to exclude.
+ # FIXME: what about values for MSVC?
+ dll_entry=__cygwin_dll_entry@12
+ dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+ case $host_os in
+ mingw*)
+ # mingw values
+ dll_entry=_DllMainCRTStartup@12
+ dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+ ;;
+ esac
+
+ # mingw and cygwin differ, and it's simplest to just exclude the union
+ # of the two symbol sets.
+ dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+
+ # recent cygwin and mingw systems supply a stub DllMain which the user
+ # can override, but on older systems we have to supply one (in ltdll.c)
+ if test "x$lt_cv_need_dllmain" = "xyes"; then
+ ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
+ ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
+ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
+ else
+ ltdll_obj=
+ ltdll_cmds=
+ fi
+
+ # Extract the symbol export list from an `--export-all' def file,
+ # then regenerate the def file from the symbol export list, so that
+ # the compiled dll only exports the symbol export list.
+ # Be careful not to strip the DATA tag left be newer dlltools.
+ export_symbols_cmds="$ltdll_cmds"'
+ $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
+ sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
+
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is.
+ # If DATA tags from a recent dlltool are present, honour them!
+ archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname-def;
+ else
+ echo EXPORTS > $output_objdir/$soname-def;
+ _lt_hint=1;
+ cat $export_symbols | while read symbol; do
+ set dummy \$symbol;
+ case \[$]# in
+ 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
+ *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
+ esac;
+ _lt_hint=`expr 1 + \$_lt_hint`;
+ done;
+ fi~
+ '"$ltdll_cmds"'
+ $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
+ $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
+ $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # dlltool doesn't understand --whole-archive et. al.
+ whole_archive_flag_spec=
+ ;;
+ *)
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ ;;
+ esac
+ fi
+else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ hardcode_direct=yes
+ archive_cmds=''
+ hardcode_libdir_separator=':'
+
+ #### Local change for Sleepycat's Berkeley DB [#5779]:
+ # Added $aix_export variable to control use of exports file.
+ # For non-gcc, we don't use exports files, and rather trust
+ # the binder's -qmkshrobj option to export all the mangled
+ # symbols we need for C++ and java.
+
+ aix_export="\${wl}$exp_sym_flag:\$export_symbols"
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ esac
+
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ shared_flag='${wl}-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+
+ # Test for -qmkshrobj and use it if it's available.
+ # It's superior for determining exportable symbols,
+ # especially for C++ or JNI libraries, which have
+ # mangled names.
+ #
+ AC_LANG_CONFTEST(void f(){})
+ if AC_TRY_EVAL(CC -c conftest.c) && AC_TRY_EVAL(CC -o conftest conftest.$ac_objext -qmkshrobj -lC_r); then
+ lt_cv_aix_mkshrobj=yes
+ else
+ lt_cv_aix_mkshrobj=no
+ fi
+
+ if test "$lt_cv_aix_mkshrobj" = yes; then
+ aix_export="-qmkshrobj"
+ fi
+ fi
+
+ # It seems that -bexpall can do strange things, so it is better to
+ # generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag $aix_export $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag $aix_export"
+ else
+ hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='${wl}-berok'
+ # This is a bit strange, but is similar to how AIX traditionally builds
+ # it's shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag $aix_export"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ ;;
+
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[[012]])
+ allow_undefined_flag='-undefined suppress'
+ ;;
+ *) # Darwin 1.3 on
+ allow_undefined_flag='-flat_namespace -undefined suppress'
+ ;;
+ esac
+ # FIXME: Relying on posixy $() will cause problems for
+ # cross-compilation, but unfortunately the echo tests do not
+ # yet detect zsh echo's removal of \ escapes.
+
+ #### Local change for Sleepycat's Berkeley DB [#5664] [#6511]
+ case "$host_os" in
+ darwin[[12345]].*)
+ # removed double quotes in the following line:
+ archive_cmds='$nonopt $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring'
+ ;;
+ *) # Darwin6.0 on (Mac OS/X Jaguar)
+ archive_cmds='$nonopt $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -dynamiclib -install_name $rpath/$soname $verstring'
+ ;;
+ esac
+ #### End of changes for Sleepycat's Berkeley DB [#5664] [#6511]
+
+ # We need to add '_' to the symbols in $export_symbols first
+ #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ whole_archive_flag_spec='-all_load $convenience'
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ case $host_os in
+ hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
+ *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
+ esac
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_minus_L=yes # Not in the search PATH, but as the default
+ # location of the library.
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ irix5* | irix6*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case "$host_os" in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ #Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ ;;
+
+ solaris*)
+ # gcc --version < 3.0 without binutils cannot create self contained
+ # shared libraries reliably, requiring libgcc.a to resolve some of
+ # the object symbols generated in some cases. Libraries that use
+ # assert need libgcc.a to resolve __eprintf, for example. Linking
+ # a copy of libgcc.a into every shared library to guarantee resolving
+ # such symbols causes other problems: According to Tim Van Holder
+ # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
+ # (to the application) exception stack for one thing.
+ no_undefined_flag=' -z defs'
+ if test "$GCC" = yes; then
+ case `$CC --version 2>/dev/null` in
+ [[12]].*)
+ cat <<EOF 1>&2
+
+*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
+*** create self contained shared libraries on Solaris systems, without
+*** introducing a dependency on libgcc.a. Therefore, libtool is disabling
+*** -no-undefined support, which will at least allow you to build shared
+*** libraries. However, you may find that when you link such libraries
+*** into an application without using GCC, you have to manually add
+*** \`gcc --print-libgcc-file-name\` to the link command. We urge you to
+*** upgrade to a newer version of GCC. Another option is to rebuild your
+*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
+
+EOF
+ no_undefined_flag=
+ ;;
+ esac
+ fi
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ if test "x$host_vendor" = xsno; then
+ archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ else
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv5*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ hardcode_libdir_flag_spec=
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ sysv5uw7* | unixware7*)
+ no_undefined_flag='${wl}-z ${wl}text'
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+AC_MSG_RESULT([$ld_shlibs])
+test "$ld_shlibs" = no && can_build_shared=no
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+# Check hardcoding attributes.
+AC_MSG_CHECKING([how to hardcode library paths into programs])
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$hardcode_shlibpath_var" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+AC_MSG_RESULT([$hardcode_action])
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+##
+## END FIXME
+
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+## FIXME: this should be a separate macro
+##
+# PORTME Fill in your ld.so characteristics
+AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}.so$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+
+ #### Local change for Sleepycat's Berkeley DB [#5779]:
+ # If we don't set need_version, we'll get x.so.0.0.0,
+ # even if -avoid-version is set.
+ need_version=no
+
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can
+ # not hardcode correct soname into executable. Probably we can
+ # add versioning support to collect2, so additional links can
+ # be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}.so$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}.so'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi4*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ export_dynamic_flag_spec=-rdynamic
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ need_version=no
+ need_lib_prefix=no
+ case $GCC,$host_os in
+ yes,cygwin*)
+ library_names_spec='$libname.dll.a'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+ postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog .libs/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ ;;
+ yes,mingw*)
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
+ ;;
+ yes,pw32*)
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
+ ;;
+ *)
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ # FIXME: Relying on posixy $() will cause problems for
+ # cross-compilation, but unfortunately the echo tests do not
+ # yet detect zsh echo's removal of \ escapes.
+ #### Local change for Sleepycat's Berkeley DB [#6117]:
+ # added support for -jnimodule, encapsulated below in ${darwin_suffix}
+ darwin_suffix='$(test .$jnimodule = .yes && echo jnilib || (test .$module = .yes && echo so || echo dylib))'
+ library_names_spec='${libname}${release}${versuffix}.'"${darwin_suffix}"' ${libname}${release}${major}.'"${darwin_suffix}"' ${libname}.'"${darwin_suffix}"
+ soname_spec='${libname}${release}${major}.'"${darwin_suffix}"
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ *)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ dynamic_linker="$host_os dld.sl"
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+ soname_spec='${libname}${release}.sl$major'
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6*)
+ version_type=irix
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
+ case $host_os in
+ irix5*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case "$host_os" in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+os2*)
+ libname_spec='$name'
+ need_lib_prefix=no
+ library_names_spec='$libname.dll $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_version=no
+ soname_spec='${libname}${release}.so'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+# Report the final consequences.
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+##
+## END FIXME
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+AC_LIBTOOL_DLOPEN_SELF
+
+## FIXME: this should be a separate macro
+##
+if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ AC_CACHE_VAL([lt_cv_archive_cmds_need_lc],
+ [$rm conftest*
+ echo 'static int dummy;' > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile); then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_cv_prog_cc_wl
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+ lt_cv_archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi])
+ AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc])
+ ;;
+ esac
+fi
+need_lc=${lt_cv_archive_cmds_need_lc-yes}
+##
+## END FIXME
+
+## FIXME: this should be a separate macro
+##
+# The second clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ :
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ test -f Makefile && make "$ltmain"
+fi
+
+if test -f "$ltmain"; then
+ trap "$rm \"${ofile}T\"; exit 1" 1 2 15
+ $rm -f "${ofile}T"
+
+ echo creating $ofile
+
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS \
+ AR AR_FLAGS CC LD LN_S NM SHELL \
+ reload_flag reload_cmds wl \
+ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+ thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+ library_names_spec soname_spec \
+ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
+ postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
+ old_striplib striplib file_magic_cmd export_symbols_cmds \
+ deplibs_check_method allow_undefined_flag no_undefined_flag \
+ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+ global_symbol_to_c_name_address \
+ hardcode_libdir_flag_spec hardcode_libdir_separator \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+ case $var in
+ reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+ extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ cat <<__EOF__ > "${ofile}T"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996-2000 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$need_lc
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# The default C compiler.
+CC=$lt_CC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_pic_flag
+pic_mode=$pic_mode
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$lt_compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "${ofile}T"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ cat <<'EOF' >> "${ofile}T"
+ # This is a source program that is used to create dlls on Windows
+ # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+ # This is a source program that is used to create import libraries
+ # on Windows for dlls which lack them. Don't remove nor modify the
+ # starting and closing comments
+# /* impgen.c starts here */
+# /* Copyright (C) 1999-2000 Free Software Foundation, Inc.
+#
+# This file is part of GNU libtool.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU 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 <stdio.h> /* for printf() */
+# #include <unistd.h> /* for open(), lseek(), read() */
+# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
+# #include <string.h> /* for strdup() */
+#
+# /* O_BINARY isn't required (or even defined sometimes) under Unix */
+# #ifndef O_BINARY
+# #define O_BINARY 0
+# #endif
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[2];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 2);
+# return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[4];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 4);
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+# void *ptr;
+# {
+# unsigned char *b = ptr;
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+# int argc;
+# char *argv[];
+# {
+# int dll;
+# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+# unsigned long export_rva, export_size, nsections, secptr, expptr;
+# unsigned long name_rvas, nexp;
+# unsigned char *expdata, *erva;
+# char *filename, *dll_name;
+#
+# filename = argv[1];
+#
+# dll = open(filename, O_RDONLY|O_BINARY);
+# if (dll < 1)
+# return 1;
+#
+# dll_name = filename;
+#
+# for (i=0; filename[i]; i++)
+# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+# dll_name = filename + i +1;
+#
+# pe_header_offset = pe_get32 (dll, 0x3c);
+# opthdr_ofs = pe_header_offset + 4 + 20;
+# num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+# if (num_entries < 1) /* no exports */
+# return 1;
+#
+# export_rva = pe_get32 (dll, opthdr_ofs + 96);
+# export_size = pe_get32 (dll, opthdr_ofs + 100);
+# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+# secptr = (pe_header_offset + 4 + 20 +
+# pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+# expptr = 0;
+# for (i = 0; i < nsections; i++)
+# {
+# char sname[8];
+# unsigned long secptr1 = secptr + 40 * i;
+# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# lseek(dll, secptr1, SEEK_SET);
+# read(dll, sname, 8);
+# if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# {
+# expptr = fptr + (export_rva - vaddr);
+# if (export_rva + export_size > vaddr + vsize)
+# export_size = vsize - (export_rva - vaddr);
+# break;
+# }
+# }
+#
+# expdata = (unsigned char*)malloc(export_size);
+# lseek (dll, expptr, SEEK_SET);
+# read (dll, expdata, export_size);
+# erva = expdata - export_rva;
+#
+# nexp = pe_as32 (expdata+24);
+# name_rvas = pe_as32 (expdata+32);
+#
+# printf ("EXPORTS\n");
+# for (i = 0; i<nexp; i++)
+# {
+# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+# }
+#
+# return 0;
+# }
+# /* impgen.c ends here */
+
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
+
+ mv -f "${ofile}T" "$ofile" || \
+ (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
+ chmod +x "$ofile"
+fi
+##
+## END FIXME
+
+])# _LT_AC_LTCONFIG_HACK
+
+# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+
+# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case $enableval in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)])
+
+# AC_LIBTOOL_PICMODE - implement the --with-pic flag
+# Usage: AC_LIBTOOL_PICMODE[(MODE)]
+# Where MODE is either `yes' or `no'. If omitted, it defaults to
+# `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)])
+
+
+# AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+ /*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+ ;;
+ *)
+ ac_save_MAGIC_CMD="$MAGIC_CMD"
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ egrep "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ MAGIC_CMD="$ac_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+])
+
+
+# AC_PATH_MAGIC - find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl
+AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])
+
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | [[A-Za-z]]:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])
+
+# AC_PROG_LD_GNU -
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ lt_cv_prog_gnu_ld=yes
+else
+ lt_cv_prog_gnu_ld=no
+fi])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])
+
+# AC_PROG_LD_RELOAD_FLAG - find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag,
+[lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+])
+
+# AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependant libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi4*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin* | mingw* | pw32*)
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ case "$host_os" in
+ rhapsody* | darwin1.[[012]])
+ lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
+ ;;
+ *) # Darwin 1.3 on
+ lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+ ;;
+ esac
+ ;;
+
+freebsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20*|hpux11*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+
+irix5* | irix6*)
+ case $host_os in
+ irix5*)
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+ ;;
+ *)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1"
+ ;;
+ esac
+ lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ case $host_cpu in
+ alpha* | hppa* | i*86 | powerpc* | sparc* | ia64* )
+ lt_cv_deplibs_check_method=pass_all ;;
+ *)
+ # glibc up to 2.1.1 does not perform some relocations on ARM
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
+ esac
+ lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
+ else
+ lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ # this will be overridden with pass_all, but let us keep it just in case
+ lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sco3.2v5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+
+sysv5uw[[78]]* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ esac
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+])
+
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
+AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/${ac_tool_prefix}nm
+ if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ else
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+AC_MSG_RESULT([$NM])
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32*)
+ # These system don't have libm
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, main, LIBM="-lm")
+ ;;
+esac
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-convenience to the
+# configure arguments. Note that LIBLTDL and INCLTDL are not
+# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
+# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
+# with '${top_builddir}/' and INCLTDL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case $enable_ltdl_convenience in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-install to the configure
+# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
+# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
+# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
+# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
+# with '${top_srcdir}/' (note the single quotes!). If your package is
+# not flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, main,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ INCLTDL=
+ fi
+])
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
diff --git a/bdb/dist/aclocal/mutex.ac b/bdb/dist/aclocal/mutex.ac
new file mode 100644
index 00000000000..f3f5529c74f
--- /dev/null
+++ b/bdb/dist/aclocal/mutex.ac
@@ -0,0 +1,611 @@
+# $Id: mutex.ac,v 11.38 2002/07/25 20:07:52 sue Exp $
+
+# POSIX pthreads tests: inter-process safe and intra-process only.
+#
+# We need to run a test here, because the PTHREAD_PROCESS_SHARED flag compiles
+# fine on problematic systems, but won't actually work. This is a problem for
+# cross-compilation environments. I think inter-process mutexes are as likely
+# to fail in cross-compilation environments as real ones (especially since the
+# likely cross-compilation environment is Linux, where inter-process mutexes
+# don't currently work -- the latest estimate I've heard is Q1 2002, as part
+# of IBM's NGPT package). So:
+#
+# If checking for inter-process pthreads mutexes:
+# If it's local, run a test.
+# If it's a cross-compilation, fail.
+#
+# If the user specified pthreads mutexes and we're checking for intra-process
+# mutexes only:
+# If it's local, run a test.
+# If it's a cross-compilation, run a link-test.
+#
+# So, the thing you can't do here is configure for inter-process POSIX pthread
+# mutexes when cross-compiling. Since we're using the GNU/Cygnus toolchain for
+# cross-compilation, the target system is likely Linux or *BSD, so we're doing
+# the right thing.
+AC_DEFUN(AM_PTHREADS_SHARED, [
+AC_TRY_RUN([
+#include <pthread.h>
+main() {
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ pthread_condattr_t condattr;
+ pthread_mutexattr_t mutexattr;
+ exit (
+ pthread_condattr_init(&condattr) ||
+ pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) ||
+ pthread_mutexattr_init(&mutexattr) ||
+ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) ||
+ pthread_cond_init(&cond, &condattr) ||
+ pthread_mutex_init(&mutex, &mutexattr) ||
+ pthread_mutex_lock(&mutex) ||
+ pthread_mutex_unlock(&mutex) ||
+ pthread_mutex_destroy(&mutex) ||
+ pthread_cond_destroy(&cond) ||
+ pthread_condattr_destroy(&condattr) ||
+ pthread_mutexattr_destroy(&mutexattr));
+}], [db_cv_mutex="$1"],, [db_cv_mutex="no"])])
+AC_DEFUN(AM_PTHREADS_PRIVATE, [
+AC_TRY_RUN([
+#include <pthread.h>
+main() {
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ pthread_condattr_t condattr;
+ pthread_mutexattr_t mutexattr;
+ exit (
+ pthread_condattr_init(&condattr) ||
+ pthread_mutexattr_init(&mutexattr) ||
+ pthread_cond_init(&cond, &condattr) ||
+ pthread_mutex_init(&mutex, &mutexattr) ||
+ pthread_mutex_lock(&mutex) ||
+ pthread_mutex_unlock(&mutex) ||
+ pthread_mutex_destroy(&mutex) ||
+ pthread_cond_destroy(&cond) ||
+ pthread_condattr_destroy(&condattr) ||
+ pthread_mutexattr_destroy(&mutexattr));
+}], [db_cv_mutex="$1"],,
+AC_TRY_LINK([
+#include <pthread.h>],[
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ pthread_condattr_t condattr;
+ pthread_mutexattr_t mutexattr;
+ exit (
+ pthread_condattr_init(&condattr) ||
+ pthread_mutexattr_init(&mutexattr) ||
+ pthread_cond_init(&cond, &condattr) ||
+ pthread_mutex_init(&mutex, &mutexattr) ||
+ pthread_mutex_lock(&mutex) ||
+ pthread_mutex_unlock(&mutex) ||
+ pthread_mutex_destroy(&mutex) ||
+ pthread_cond_destroy(&cond) ||
+ pthread_condattr_destroy(&condattr) ||
+ pthread_mutexattr_destroy(&mutexattr));
+], [db_cv_mutex="$1"]))])
+
+# Figure out mutexes for this compiler/architecture.
+AC_DEFUN(AM_DEFINE_MUTEXES, [
+
+# Mutexes we don't test for, but want the #defines to exist for
+# other ports.
+AH_TEMPLATE(HAVE_MUTEX_VMS, [Define to 1 to use VMS mutexes.])
+AH_TEMPLATE(HAVE_MUTEX_VXWORKS, [Define to 1 to use VxWorks mutexes.])
+AH_TEMPLATE(HAVE_MUTEX_WIN32, [Define to 1 to use Windows mutexes.])
+
+AC_CACHE_CHECK([for mutexes], db_cv_mutex, [
+db_cv_mutex=no
+
+orig_libs=$LIBS
+
+# User-specified POSIX or UI mutexes.
+#
+# There are two different reasons to specify mutexes: First, the application
+# is already using one type of mutex and doesn't want to mix-and-match (for
+# example, on Solaris, which has POSIX, UI and LWP mutexes). Second, the
+# applications POSIX pthreads mutexes don't support inter-process locking,
+# but the application wants to use them anyway (for example, current Linux
+# and *BSD systems).
+#
+# If we're on Solaris, we insist that -lthread or -lpthread be used. The
+# problem is the Solaris C library has UI/POSIX interface stubs, but they're
+# broken, configuring them for inter-process mutexes doesn't return an error,
+# but it doesn't work either. Otherwise, we try first without the library
+# and then with it: there's some information that SCO/UnixWare/OpenUNIX needs
+# this. [#4950]
+#
+# Test for LWP threads before testing for UI/POSIX threads, we prefer them
+# on Solaris. There's a bug in SunOS 5.7 where applications get pwrite, not
+# pwrite64, if they load the C library before the appropriate threads library,
+# e.g., tclsh using dlopen to load the DB library. By using LWP threads we
+# avoid answering lots of user questions, not to mention the bugs.
+if test "$db_cv_posixmutexes" = yes; then
+ case "$host_os" in
+ solaris*)
+ db_cv_mutex="posix_library_only";;
+ *)
+ db_cv_mutex="posix_only";;
+ esac
+fi
+
+if test "$db_cv_uimutexes" = yes; then
+ case "$host_os" in
+ solaris*)
+ db_cv_mutex="ui_library_only";;
+ *)
+ db_cv_mutex="ui_only";;
+ esac
+fi
+
+# LWP threads: _lwp_XXX
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK([
+#include <synch.h>],[
+ static lwp_mutex_t mi = SHAREDMUTEX;
+ static lwp_cond_t ci = SHAREDCV;
+ lwp_mutex_t mutex = mi;
+ lwp_cond_t cond = ci;
+ exit (
+ _lwp_mutex_lock(&mutex) ||
+ _lwp_mutex_unlock(&mutex));
+], [db_cv_mutex="Solaris/lwp"])
+fi
+
+# UI threads: thr_XXX
+#
+# Try with and without the -lthread library.
+if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "ui_only"; then
+AC_TRY_LINK([
+#include <thread.h>
+#include <synch.h>],[
+ mutex_t mutex;
+ cond_t cond;
+ int type = USYNC_PROCESS;
+ exit (
+ mutex_init(&mutex, type, NULL) ||
+ cond_init(&cond, type, NULL) ||
+ mutex_lock(&mutex) ||
+ mutex_unlock(&mutex));
+], [db_cv_mutex="UI/threads"])
+fi
+if test "$db_cv_mutex" = no -o \
+ "$db_cv_mutex" = "ui_only" -o "$db_cv_mutex" = "ui_library_only"; then
+LIBS="$LIBS -lthread"
+AC_TRY_LINK([
+#include <thread.h>
+#include <synch.h>],[
+ mutex_t mutex;
+ cond_t cond;
+ int type = USYNC_PROCESS;
+ exit (
+ mutex_init(&mutex, type, NULL) ||
+ cond_init(&cond, type, NULL) ||
+ mutex_lock(&mutex) ||
+ mutex_unlock(&mutex));
+], [db_cv_mutex="UI/threads/library"])
+LIBS="$orig_libs"
+fi
+if test "$db_cv_mutex" = "ui_only" -o "$db_cv_mutex" = "ui_library_only"; then
+ AC_MSG_ERROR([unable to find UI mutex interfaces])
+fi
+
+# POSIX.1 pthreads: pthread_XXX
+#
+# Try with and without the -lpthread library. If the user specified we use
+# POSIX pthreads mutexes, and we fail to find the full interface, try and
+# configure for just intra-process support.
+if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "posix_only"; then
+ AM_PTHREADS_SHARED("POSIX/pthreads")
+fi
+if test "$db_cv_mutex" = no -o \
+ "$db_cv_mutex" = "posix_only" -o "$db_cv_mutex" = "posix_library_only"; then
+ LIBS="$LIBS -lpthread"
+ AM_PTHREADS_SHARED("POSIX/pthreads/library")
+ LIBS="$orig_libs"
+fi
+if test "$db_cv_mutex" = "posix_only"; then
+ AM_PTHREADS_PRIVATE("POSIX/pthreads/private")
+fi
+if test "$db_cv_mutex" = "posix_only" -o \
+ "$db_cv_mutex" = "posix_library_only"; then
+ LIBS="$LIBS -lpthread"
+ AM_PTHREADS_PRIVATE("POSIX/pthreads/library/private")
+ LIBS="$orig_libs"
+fi
+
+if test "$db_cv_mutex" = "posix_only" -o \
+ "$db_cv_mutex" = "posix_library_only"; then
+ AC_MSG_ERROR([unable to find POSIX 1003.1 mutex interfaces])
+fi
+
+# msemaphore: HPPA only
+# Try HPPA before general msem test, it needs special alignment.
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK([
+#include <sys/mman.h>],[
+#if defined(__hppa)
+ typedef msemaphore tsl_t;
+ msemaphore x;
+ msem_init(&x, 0);
+ msem_lock(&x, 0);
+ msem_unlock(&x, 0);
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="HP/msem_init"])
+fi
+
+# msemaphore: AIX, OSF/1
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/mman.h>],[
+ typedef msemaphore tsl_t;
+ msemaphore x;
+ msem_init(&x, 0);
+ msem_lock(&x, 0);
+ msem_unlock(&x, 0);
+ exit(0);
+], [db_cv_mutex="UNIX/msem_init"])
+fi
+
+# ReliantUNIX
+if test "$db_cv_mutex" = no; then
+LIBS="$LIBS -lmproc"
+AC_TRY_LINK([
+#include <ulocks.h>],[
+ typedef spinlock_t tsl_t;
+ spinlock_t x;
+ initspin(&x, 1);
+ cspinlock(&x);
+ spinunlock(&x);
+], [db_cv_mutex="ReliantUNIX/initspin"])
+LIBS="$orig_libs"
+fi
+
+# SCO: UnixWare has threads in libthread, but OpenServer doesn't.
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__USLC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="SCO/x86/cc-assembly"])
+fi
+
+# abilock_t: SGI
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK([
+#include <abi_mutex.h>],[
+ typedef abilock_t tsl_t;
+ abilock_t x;
+ init_lock(&x);
+ acquire_lock(&x);
+ release_lock(&x);
+], [db_cv_mutex="SGI/init_lock"])
+fi
+
+# sema_t: Solaris
+# The sema_XXX calls do not work on Solaris 5.5. I see no reason to ever
+# turn this test on, unless we find some other platform that uses the old
+# POSIX.1 interfaces. (I plan to move directly to pthreads on Solaris.)
+if test "$db_cv_mutex" = DOESNT_WORK; then
+AC_TRY_LINK([
+#include <synch.h>],[
+ typedef sema_t tsl_t;
+ sema_t x;
+ sema_init(&x, 1, USYNC_PROCESS, NULL);
+ sema_wait(&x);
+ sema_post(&x);
+], [db_cv_mutex="UNIX/sema_init"])
+fi
+
+# _lock_try/_lock_clear: Solaris
+# On Solaris systems without Pthread or UI mutex interfaces, DB uses the
+# undocumented _lock_try _lock_clear function calls instead of either the
+# sema_trywait(3T) or sema_wait(3T) function calls. This is because of
+# problems in those interfaces in some releases of the Solaris C library.
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK([
+#include <sys/machlock.h>],[
+ typedef lock_t tsl_t;
+ lock_t x;
+ _lock_try(&x);
+ _lock_clear(&x);
+], [db_cv_mutex="Solaris/_lock_try"])
+fi
+
+# _check_lock/_clear_lock: AIX
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK([
+#include <sys/atomic_op.h>],[
+ int x;
+ _check_lock(&x,0,1);
+ _clear_lock(&x,0);
+], [db_cv_mutex="AIX/_check_lock"])
+fi
+
+# Alpha/gcc: OSF/1
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__alpha) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="ALPHA/gcc-assembly"])
+fi
+
+# ARM/gcc: Linux
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__arm__) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="ARM/gcc-assembly"])
+fi
+
+# PaRisc/gcc: HP/UX
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if (defined(__hppa) || defined(__hppa__)) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="HPPA/gcc-assembly"])
+fi
+
+# PPC/gcc:
+# Test for Apple first, it requires slightly different assembly.
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__) && defined(__APPLE__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="PPC_APPLE/gcc-assembly"])
+fi
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="PPC_GENERIC/gcc-assembly"])
+fi
+
+# Sparc/gcc: SunOS, Solaris
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__sparc__) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="Sparc/gcc-assembly"])
+fi
+
+# 68K/gcc: SunOS
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if (defined(mc68020) || defined(sun3)) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="68K/gcc-assembly"])
+fi
+
+# x86/gcc: FreeBSD, NetBSD, BSD/OS, Linux
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if (defined(i386) || defined(__i386__)) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="x86/gcc-assembly"])
+fi
+
+# S390/gcc: Linux
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__s390__) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="S390/gcc-assembly"])
+fi
+
+# ia86/gcc: Linux
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__ia64) && defined(__GNUC__)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="ia64/gcc-assembly"])
+fi
+
+# uts/cc: UTS
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(_UTS)
+ exit(0);
+#else
+ FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="UTS/cc-assembly"])
+fi
+
+# default to UNIX fcntl system call mutexes.
+if test "$db_cv_mutex" = no; then
+ db_cv_mutex="UNIX/fcntl"
+fi
+])
+
+case "$db_cv_mutex" in
+68K/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_68K_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_68K_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and 68K assembly language mutexes.]);;
+AIX/_check_lock) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_AIX_CHECK_LOCK)
+ AH_TEMPLATE(HAVE_MUTEX_AIX_CHECK_LOCK,
+ [Define to 1 to use the AIX _check_lock mutexes.]);;
+ALPHA/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_ALPHA_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_ALPHA_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and Alpha assembly language mutexes.]);;
+ARM/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_ARM_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_ARM_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and ARM assembly language mutexes.]);;
+HP/msem_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_HPPA_MSEM_INIT)
+ AH_TEMPLATE(HAVE_MUTEX_HPPA_MSEM_INIT,
+ [Define to 1 to use the msem_XXX mutexes on HP-UX.]);;
+HPPA/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_HPPA_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_HPPA_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and PaRisc assembly language mutexes.]);;
+ia64/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_IA64_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_IA64_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and IA64 assembly language mutexes.]);;
+POSIX/pthreads) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_PTHREADS)
+ AH_TEMPLATE(HAVE_MUTEX_PTHREADS,
+ [Define to 1 to use POSIX 1003.1 pthread_XXX mutexes.]);;
+POSIX/pthreads/private) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_PTHREADS)
+ AH_TEMPLATE(HAVE_MUTEX_PTHREADS,
+ [Define to 1 to use POSIX 1003.1 pthread_XXX mutexes.])
+ AC_DEFINE(HAVE_MUTEX_THREAD_ONLY)
+ AH_TEMPLATE(HAVE_MUTEX_THREAD_ONLY,
+ [Define to 1 to configure mutexes intra-process only.]);;
+POSIX/pthreads/library) LIBS="$LIBS -lpthread"
+ ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_PTHREADS)
+ AH_TEMPLATE(HAVE_MUTEX_PTHREADS,
+ [Define to 1 to use POSIX 1003.1 pthread_XXX mutexes.]);;
+POSIX/pthreads/library/private)
+ LIBS="$LIBS -lpthread"
+ ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_PTHREADS)
+ AH_TEMPLATE(HAVE_MUTEX_PTHREADS,
+ [Define to 1 to use POSIX 1003.1 pthread_XXX mutexes.])
+ AC_DEFINE(HAVE_MUTEX_THREAD_ONLY)
+ AH_TEMPLATE(HAVE_MUTEX_THREAD_ONLY,
+ [Define to 1 to configure mutexes intra-process only.]);;
+PPC_GENERIC/gcc-assembly)
+ ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and generic PowerPC assembly language.]);;
+PPC_APPLE/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and Apple PowerPC assembly language.]);;
+ReliantUNIX/initspin) LIBS="$LIBS -lmproc"
+ ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_RELIANTUNIX_INITSPIN)
+ AH_TEMPLATE(HAVE_MUTEX_RELIANTUNIX_INITSPIN,
+ [Define to 1 to use Reliant UNIX initspin mutexes.]);;
+S390/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_S390_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_S390_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and S/390 assembly language mutexes.]);;
+SCO/x86/cc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_SCO_X86_CC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_SCO_X86_CC_ASSEMBLY,
+ [Define to 1 to use the SCO compiler and x86 assembly language mutexes.]);;
+SGI/init_lock) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_SGI_INIT_LOCK)
+ AH_TEMPLATE(HAVE_MUTEX_SGI_INIT_LOCK,
+ [Define to 1 to use the SGI XXX_lock mutexes.]);;
+Solaris/_lock_try) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_SOLARIS_LOCK_TRY)
+ AH_TEMPLATE(HAVE_MUTEX_SOLARIS_LOCK_TRY,
+ [Define to 1 to use the Solaris _lock_XXX mutexes.]);;
+Solaris/lwp) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_SOLARIS_LWP)
+ AH_TEMPLATE(HAVE_MUTEX_SOLARIS_LWP,
+ [Define to 1 to use the Solaris lwp threads mutexes.]);;
+Sparc/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_SPARC_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_SPARC_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and Sparc assembly language mutexes.]);;
+UI/threads) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_UI_THREADS)
+ AH_TEMPLATE(HAVE_MUTEX_UI_THREADS,
+ [Define to 1 to use the UNIX International mutexes.]);;
+UI/threads/library) LIBS="$LIBS -lthread"
+ ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_UI_THREADS)
+ AH_TEMPLATE(HAVE_MUTEX_UI_THREADS,
+ [Define to 1 to use the UNIX International mutexes.]);;
+UNIX/msem_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_MSEM_INIT)
+ AH_TEMPLATE(HAVE_MUTEX_MSEM_INIT,
+ [Define to 1 to use the msem_XXX mutexes on systems other than HP-UX.]);;
+UNIX/sema_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_SEMA_INIT)
+ AH_TEMPLATE(HAVE_MUTEX_SEMA_INIT,
+ [Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes.]);;
+UTS/cc-assembly) ADDITIONAL_OBJS="$ADDITIONAL_OBJS uts4.cc${o}"
+ AC_DEFINE(HAVE_MUTEX_UTS_CC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_UTS_CC_ASSEMBLY,
+ [Define to 1 to use the UTS compiler and assembly language mutexes.]);;
+x86/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_X86_GCC_ASSEMBLY)
+ AH_TEMPLATE(HAVE_MUTEX_X86_GCC_ASSEMBLY,
+ [Define to 1 to use the GCC compiler and x86 assembly language mutexes.]);;
+UNIX/fcntl) AC_MSG_WARN(
+ [NO FAST MUTEXES FOUND FOR THIS COMPILER/ARCHITECTURE.])
+ ADDITIONAL_OBJS="mut_fcntl${o} $ADDITIONAL_OBJS"
+ AC_DEFINE(HAVE_MUTEX_FCNTL)
+ AH_TEMPLATE(HAVE_MUTEX_FCNTL,
+ [Define to 1 to use the UNIX fcntl system call mutexes.]);;
+*) AC_MSG_ERROR([Unknown mutex interface: $db_cv_mutex]);;
+esac
+
+if test "$db_cv_mutex" != "UNIX/fcntl"; then
+ AC_DEFINE(HAVE_MUTEX_THREADS)
+ AH_TEMPLATE(HAVE_MUTEX_THREADS,
+ [Define to 1 if fast mutexes are available.])
+fi
+
+# There are 3 classes of mutexes:
+#
+# 1: Mutexes requiring no cleanup, for example, test-and-set mutexes.
+# 2: Mutexes that must be destroyed, but which don't hold permanent system
+# resources, for example, pthread mutexes on MVS aka OS/390 aka z/OS.
+# 3: Mutexes that must be destroyed, even after the process is gone, for
+# example, pthread mutexes on QNX and binary semaphores on VxWorks.
+#
+# DB cannot currently distinguish between #2 and #3 because DB does not know
+# if the application is running environment recovery as part of startup and
+# does not need to do cleanup, or if the environment is being removed and/or
+# recovered in a loop in the application, and so does need to clean up. If
+# we get it wrong, we're going to call the mutex destroy routine on a random
+# piece of memory, which usually works, but just might drop core. For now,
+# we group #2 and #3 into the HAVE_MUTEX_SYSTEM_RESOURCES define, until we
+# have a better solution or reason to solve this in a general way -- so far,
+# the places we've needed to handle this are few.
+AH_TEMPLATE(HAVE_MUTEX_SYSTEM_RESOURCES,
+ [Define to 1 if mutexes hold system resources.])
+
+case "$host_os$db_cv_mutex" in
+*qnx*POSIX/pthread*|openedition*POSIX/pthread*)
+ AC_DEFINE(HAVE_MUTEX_SYSTEM_RESOURCES);;
+esac])
diff --git a/bdb/dist/aclocal/mutex.m4 b/bdb/dist/aclocal/mutex.m4
deleted file mode 100644
index 2010670599f..00000000000
--- a/bdb/dist/aclocal/mutex.m4
+++ /dev/null
@@ -1,409 +0,0 @@
-dnl $Id: mutex.m4,v 11.20 2000/12/20 22:16:56 bostic Exp $
-
-dnl Figure out mutexes for this compiler/architecture.
-AC_DEFUN(AM_DEFINE_MUTEXES, [
-
-AC_CACHE_CHECK([for mutexes], db_cv_mutex, [dnl
-db_cv_mutex=no
-
-orig_libs=$LIBS
-
-dnl User-specified POSIX mutexes.
-dnl
-dnl Assume that -lpthread exists when the user specifies POSIX mutexes. (I
-dnl only expect this option to be used on Solaris, which has -lpthread.)
-if test "$db_cv_posixmutexes" = yes; then
- db_cv_mutex="posix_only"
-fi
-
-dnl User-specified UI mutexes.
-dnl
-dnl Assume that -lthread exists when the user specifies UI mutexes. (I only
-dnl expect this option to be used on Solaris, which has -lthread.)
-if test "$db_cv_uimutexes" = yes; then
- db_cv_mutex="ui_only"
-fi
-
-dnl LWP threads: _lwp_XXX
-dnl
-dnl Test for LWP threads before testing for UI/POSIX threads, we prefer them
-dnl on Solaris. There are two reasons: the Solaris C library has UI/POSIX
-dnl interface stubs, but they're broken, configuring them for inter-process
-dnl mutexes doesn't return an error, but it doesn't work either. Second,
-dnl there's a bug in SunOS 5.7 where applications get pwrite, not pwrite64,
-dnl if they load the C library before the appropriate threads library, e.g.,
-dnl tclsh using dlopen to load the DB library. Anyway, by using LWP threads
-dnl we avoid answering lots of user questions, not to mention the bugs.
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([
-#include <synch.h>
-main(){
- static lwp_mutex_t mi = SHAREDMUTEX;
- static lwp_cond_t ci = SHAREDCV;
- lwp_mutex_t mutex = mi;
- lwp_cond_t cond = ci;
- exit (
- _lwp_mutex_lock(&mutex) ||
- _lwp_mutex_unlock(&mutex));
-}], [db_cv_mutex="Solaris/lwp"])
-fi
-
-dnl UI threads: thr_XXX
-dnl
-dnl Try with and without the -lthread library.
-if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "ui_only"; then
-LIBS="-lthread $LIBS"
-AC_TRY_RUN([
-#include <thread.h>
-#include <synch.h>
-main(){
- mutex_t mutex;
- cond_t cond;
- int type = USYNC_PROCESS;
- exit (
- mutex_init(&mutex, type, NULL) ||
- cond_init(&cond, type, NULL) ||
- mutex_lock(&mutex) ||
- mutex_unlock(&mutex));
-}], [db_cv_mutex="UI/threads/library"])
-LIBS="$orig_libs"
-fi
-if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "ui_only"; then
-AC_TRY_RUN([
-#include <thread.h>
-#include <synch.h>
-main(){
- mutex_t mutex;
- cond_t cond;
- int type = USYNC_PROCESS;
- exit (
- mutex_init(&mutex, type, NULL) ||
- cond_init(&cond, type, NULL) ||
- mutex_lock(&mutex) ||
- mutex_unlock(&mutex));
-}], [db_cv_mutex="UI/threads"])
-fi
-if test "$db_cv_mutex" = "ui_only"; then
- AC_MSG_ERROR([unable to find UI mutex interfaces])
-fi
-
-
-dnl POSIX.1 pthreads: pthread_XXX
-dnl
-dnl Try with and without the -lpthread library.
-if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "posix_only"; then
-AC_TRY_RUN([
-#include <pthread.h>
-main(){
- pthread_cond_t cond;
- pthread_mutex_t mutex;
- pthread_condattr_t condattr;
- pthread_mutexattr_t mutexattr;
- exit (
- pthread_condattr_init(&condattr) ||
- pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) ||
- pthread_mutexattr_init(&mutexattr) ||
- pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) ||
- pthread_cond_init(&cond, &condattr) ||
- pthread_mutex_init(&mutex, &mutexattr) ||
- pthread_mutex_lock(&mutex) ||
- pthread_mutex_unlock(&mutex) ||
- pthread_mutex_destroy(&mutex) ||
- pthread_cond_destroy(&cond) ||
- pthread_condattr_destroy(&condattr) ||
- pthread_mutexattr_destroy(&mutexattr));
-}], [db_cv_mutex="POSIX/pthreads"])
-fi
-if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "posix_only"; then
-LIBS="-lpthread $LIBS"
-AC_TRY_RUN([
-#include <pthread.h>
-main(){
- pthread_cond_t cond;
- pthread_mutex_t mutex;
- pthread_condattr_t condattr;
- pthread_mutexattr_t mutexattr;
- exit (
- pthread_condattr_init(&condattr) ||
- pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) ||
- pthread_mutexattr_init(&mutexattr) ||
- pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) ||
- pthread_cond_init(&cond, &condattr) ||
- pthread_mutex_init(&mutex, &mutexattr) ||
- pthread_mutex_lock(&mutex) ||
- pthread_mutex_unlock(&mutex) ||
- pthread_mutex_destroy(&mutex) ||
- pthread_cond_destroy(&cond) ||
- pthread_condattr_destroy(&condattr) ||
- pthread_mutexattr_destroy(&mutexattr));
-}], [db_cv_mutex="POSIX/pthreads/library"])
-LIBS="$orig_libs"
-fi
-if test "$db_cv_mutex" = "posix_only"; then
- AC_MSG_ERROR([unable to find POSIX mutex interfaces])
-fi
-
-dnl msemaphore: HPPA only
-dnl Try HPPA before general msem test, it needs special alignment.
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([
-#include <sys/mman.h>
-main(){
-#if defined(__hppa)
- typedef msemaphore tsl_t;
- msemaphore x;
- msem_init(&x, 0);
- msem_lock(&x, 0);
- msem_unlock(&x, 0);
- exit(0);
-#else
- exit(1);
-#endif
-}], [db_cv_mutex="HP/msem_init"])
-fi
-
-dnl msemaphore: AIX, OSF/1
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([
-#include <sys/types.h>
-#include <sys/mman.h>;
-main(){
- typedef msemaphore tsl_t;
- msemaphore x;
- msem_init(&x, 0);
- msem_lock(&x, 0);
- msem_unlock(&x, 0);
- exit(0);
-}], [db_cv_mutex="UNIX/msem_init"])
-fi
-
-dnl ReliantUNIX
-if test "$db_cv_mutex" = no; then
-LIBS="$LIBS -lmproc"
-AC_TRY_LINK([#include <ulocks.h>],
-[typedef spinlock_t tsl_t;
-spinlock_t x; initspin(&x, 1); cspinlock(&x); spinunlock(&x);],
-[db_cv_mutex="ReliantUNIX/initspin"])
-LIBS="$orig_libs"
-fi
-
-dnl SCO: UnixWare has threads in libthread, but OpenServer doesn't.
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([
-main(){
-#if defined(__USLC__)
- exit(0);
-#endif
- exit(1);
-}], [db_cv_mutex="SCO/x86/cc-assembly"])
-fi
-
-dnl abilock_t: SGI
-if test "$db_cv_mutex" = no; then
-AC_TRY_LINK([#include <abi_mutex.h>],
-[typedef abilock_t tsl_t;
-abilock_t x; init_lock(&x); acquire_lock(&x); release_lock(&x);],
-[db_cv_mutex="SGI/init_lock"])
-fi
-
-dnl sema_t: Solaris
-dnl The sema_XXX calls do not work on Solaris 5.5. I see no reason to ever
-dnl turn this test on, unless we find some other platform that uses the old
-dnl POSIX.1 interfaces. (I plan to move directly to pthreads on Solaris.)
-if test "$db_cv_mutex" = DOESNT_WORK; then
-AC_TRY_LINK([#include <synch.h>],
-[typedef sema_t tsl_t;
- sema_t x;
- sema_init(&x, 1, USYNC_PROCESS, NULL); sema_wait(&x); sema_post(&x);],
-[db_cv_mutex="UNIX/sema_init"])
-fi
-
-dnl _lock_try/_lock_clear: Solaris
-dnl On Solaris systems without Pthread or UI mutex interfaces, DB uses the
-dnl undocumented _lock_try _lock_clear function calls instead of either the
-dnl sema_trywait(3T) or sema_wait(3T) function calls. This is because of
-dnl problems in those interfaces in some releases of the Solaris C library.
-if test "$db_cv_mutex" = no; then
-AC_TRY_LINK([#include <sys/machlock.h>],
-[typedef lock_t tsl_t;
- lock_t x;
- _lock_try(&x); _lock_clear(&x);],
-[db_cv_mutex="Solaris/_lock_try"])
-fi
-
-dnl _check_lock/_clear_lock: AIX
-if test "$db_cv_mutex" = no; then
-AC_TRY_LINK([#include <sys/atomic_op.h>],
-[int x; _check_lock(&x,0,1); _clear_lock(&x,0);],
-[db_cv_mutex="AIX/_check_lock"])
-fi
-
-dnl Alpha/gcc: OSF/1
-dnl The alpha/gcc code doesn't work as far as I know. There are
-dnl two versions, both have problems. See Support Request #1583.
-if test "$db_cv_mutex" = DOESNT_WORK; then
-AC_TRY_RUN([main(){
-#if defined(__alpha)
-#if defined(__GNUC__)
-exit(0);
-#endif
-#endif
-exit(1);}],
-[db_cv_mutex="ALPHA/gcc-assembly"])
-fi
-
-dnl PaRisc/gcc: HP/UX
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(__hppa)
-#if defined(__GNUC__)
-exit(0);
-#endif
-#endif
-exit(1);}],
-[db_cv_mutex="HPPA/gcc-assembly"])
-fi
-
-dnl PPC/gcc:
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(__powerpc__)
-#if defined(__GNUC__)
-exit(0);
-#endif
-#endif
-exit(1);}],
-[db_cv_mutex="PPC/gcc-assembly"])
-fi
-
-dnl Sparc/gcc: SunOS, Solaris
-dnl The sparc/gcc code doesn't always work, specifically, I've seen assembler
-dnl failures from the stbar instruction on SunOS 4.1.4/sun4c and gcc 2.7.2.2.
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(__sparc__)
-#if defined(__GNUC__)
- exit(0);
-#endif
-#endif
- exit(1);
-}], [db_cv_mutex="Sparc/gcc-assembly"])
-fi
-
-dnl 68K/gcc: SunOS
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if (defined(mc68020) || defined(sun3))
-#if defined(__GNUC__)
- exit(0);
-#endif
-#endif
- exit(1);
-}], [db_cv_mutex="68K/gcc-assembly"])
-fi
-
-dnl x86/gcc: FreeBSD, NetBSD, BSD/OS, Linux
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(i386) || defined(__i386__)
-#if defined(__GNUC__)
- exit(0);
-#endif
-#endif
- exit(1);
-}], [db_cv_mutex="x86/gcc-assembly"])
-fi
-
-dnl x86_64/gcc: FreeBSD, NetBSD, BSD/OS, Linux
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(x86_64) || defined(__x86_64__)
-#if defined(__GNUC__)
- exit(0);
-#endif
-#endif
- exit(1);
-}], [db_cv_mutex="x86_64/gcc-assembly"])
-fi
-
-dnl ia86/gcc: Linux
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(__ia64)
-#if defined(__GNUC__)
- exit(0);
-#endif
-#endif
- exit(1);
-}], [db_cv_mutex="ia64/gcc-assembly"])
-fi
-
-dnl: uts/cc: UTS
-if test "$db_cv_mutex" = no; then
-AC_TRY_RUN([main(){
-#if defined(_UTS)
- exit(0);
-#endif
- exit(1);
-}], [db_cv_mutex="UTS/cc-assembly"])
-fi
-])
-
-if test "$db_cv_mutex" = no; then
- AC_MSG_WARN(
- [THREAD MUTEXES NOT AVAILABLE FOR THIS COMPILER/ARCHITECTURE.])
- ADDITIONAL_OBJS="mut_fcntl${o} $ADDITIONAL_OBJS"
-else
- AC_DEFINE(HAVE_MUTEX_THREADS)
-fi
-
-case "$db_cv_mutex" in
-68K/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_68K_GCC_ASSEMBLY);;
-AIX/_check_lock) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_AIX_CHECK_LOCK);;
-ALPHA/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_ALPHA_GCC_ASSEMBLY);;
-HP/msem_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_HPPA_MSEM_INIT);;
-HPPA/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_HPPA_GCC_ASSEMBLY);;
-ia64/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_IA64_GCC_ASSEMBLY);;
-POSIX/pthreads) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_PTHREADS);;
-POSIX/pthreads/library) LIBS="-lpthread $LIBS"
- ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_PTHREADS);;
-PPC/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_PPC_GCC_ASSEMBLY);;
-ReliantUNIX/initspin) LIBS="$LIBS -lmproc"
- ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_RELIANTUNIX_INITSPIN);;
-SCO/x86/cc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_SCO_X86_CC_ASSEMBLY);;
-SGI/init_lock) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_SGI_INIT_LOCK);;
-Solaris/_lock_try) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_SOLARIS_LOCK_TRY);;
-Solaris/lwp) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_SOLARIS_LWP);;
-Sparc/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_SPARC_GCC_ASSEMBLY);;
-UI/threads) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_UI_THREADS);;
-UI/threads/library) LIBS="-lthread $LIBS"
- ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_UI_THREADS);;
-UNIX/msem_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_MSEM_INIT);;
-UNIX/sema_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_SEMA_INIT);;
-UTS/cc-assembly) ADDITIONAL_OBJS="$ADDITIONAL_OBJS uts4.cc${o}"
- AC_DEFINE(HAVE_MUTEX_UTS_CC_ASSEMBLY);;
-x86/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_X86_GCC_ASSEMBLY);;
-x86_64/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
- AC_DEFINE(HAVE_MUTEX_X86_64_GCC_ASSEMBLY);;
-esac
-])dnl
diff --git a/bdb/dist/aclocal/options.ac b/bdb/dist/aclocal/options.ac
new file mode 100644
index 00000000000..ba45c34dfe9
--- /dev/null
+++ b/bdb/dist/aclocal/options.ac
@@ -0,0 +1,197 @@
+# $Id: options.ac,v 11.19 2002/06/25 19:31:48 bostic Exp $
+
+# Process user-specified options.
+AC_DEFUN(AM_OPTIONS_SET, [
+
+# --enable-bigfile was the configuration option that Berkeley DB used before
+# autoconf 2.50 was released (which had --enable-largefile integrated in).
+AC_ARG_ENABLE(bigfile,
+ [AC_HELP_STRING([--disable-bigfile],
+ [Obsolete; use --disable-largefile instead.])],
+ [AC_MSG_ERROR(
+ [--enable-bigfile no longer supported, use --enable-largefile])])
+
+AC_MSG_CHECKING(if --enable-compat185 option specified)
+AC_ARG_ENABLE(compat185,
+ [AC_HELP_STRING([--enable-compat185],
+ [Build DB 1.85 compatibility API.])],
+ [db_cv_compat185="$enable_compat185"], [db_cv_compat185="no"])
+AC_MSG_RESULT($db_cv_compat185)
+
+AC_MSG_CHECKING(if --enable-cxx option specified)
+AC_ARG_ENABLE(cxx,
+ [AC_HELP_STRING([--enable-cxx],
+ [Build C++ API.])],
+ [db_cv_cxx="$enable_cxx"], [db_cv_cxx="no"])
+AC_MSG_RESULT($db_cv_cxx)
+
+AC_MSG_CHECKING(if --enable-debug option specified)
+AC_ARG_ENABLE(debug,
+ [AC_HELP_STRING([--enable-debug],
+ [Build a debugging version.])],
+ [db_cv_debug="$enable_debug"], [db_cv_debug="no"])
+AC_MSG_RESULT($db_cv_debug)
+
+AC_MSG_CHECKING(if --enable-debug_rop option specified)
+AC_ARG_ENABLE(debug_rop,
+ [AC_HELP_STRING([--enable-debug_rop],
+ [Build a version that logs read operations.])],
+ [db_cv_debug_rop="$enable_debug_rop"], [db_cv_debug_rop="no"])
+AC_MSG_RESULT($db_cv_debug_rop)
+
+AC_MSG_CHECKING(if --enable-debug_wop option specified)
+AC_ARG_ENABLE(debug_wop,
+ [AC_HELP_STRING([--enable-debug_wop],
+ [Build a version that logs write operations.])],
+ [db_cv_debug_wop="$enable_debug_wop"], [db_cv_debug_wop="no"])
+AC_MSG_RESULT($db_cv_debug_wop)
+
+AC_MSG_CHECKING(if --enable-diagnostic option specified)
+AC_ARG_ENABLE(diagnostic,
+ [AC_HELP_STRING([--enable-diagnostic],
+ [Build a version with run-time diagnostics.])],
+ [db_cv_diagnostic="$enable_diagnostic"], [db_cv_diagnostic="no"])
+AC_MSG_RESULT($db_cv_diagnostic)
+
+AC_MSG_CHECKING(if --enable-dump185 option specified)
+AC_ARG_ENABLE(dump185,
+ [AC_HELP_STRING([--enable-dump185],
+ [Build db_dump185(1) to dump 1.85 databases.])],
+ [db_cv_dump185="$enable_dump185"], [db_cv_dump185="no"])
+AC_MSG_RESULT($db_cv_dump185)
+
+AC_MSG_CHECKING(if --enable-java option specified)
+AC_ARG_ENABLE(java,
+ [AC_HELP_STRING([--enable-java],
+ [Build Java API.])],
+ [db_cv_java="$enable_java"], [db_cv_java="no"])
+AC_MSG_RESULT($db_cv_java)
+
+AC_MSG_CHECKING(if --enable-posixmutexes option specified)
+AC_ARG_ENABLE(posixmutexes,
+ [AC_HELP_STRING([--enable-posixmutexes],
+ [Force use of POSIX standard mutexes.])],
+ [db_cv_posixmutexes="$enable_posixmutexes"], [db_cv_posixmutexes="no"])
+AC_MSG_RESULT($db_cv_posixmutexes)
+
+AC_MSG_CHECKING(if --enable-rpc option specified)
+AC_ARG_ENABLE(rpc,
+ [AC_HELP_STRING([--enable-rpc],
+ [Build RPC client/server.])],
+ [db_cv_rpc="$enable_rpc"], [db_cv_rpc="no"])
+AC_MSG_RESULT($db_cv_rpc)
+
+AC_MSG_CHECKING(if --enable-tcl option specified)
+AC_ARG_ENABLE(tcl,
+ [AC_HELP_STRING([--enable-tcl],
+ [Build Tcl API.])],
+ [db_cv_tcl="$enable_tcl"], [db_cv_tcl="no"])
+AC_MSG_RESULT($db_cv_tcl)
+
+AC_MSG_CHECKING(if --enable-test option specified)
+AC_ARG_ENABLE(test,
+ [AC_HELP_STRING([--enable-test],
+ [Configure to run the test suite.])],
+ [db_cv_test="$enable_test"], [db_cv_test="no"])
+AC_MSG_RESULT($db_cv_test)
+
+AC_MSG_CHECKING(if --enable-uimutexes option specified)
+AC_ARG_ENABLE(uimutexes,
+ [AC_HELP_STRING([--enable-uimutexes],
+ [Force use of Unix International mutexes.])],
+ [db_cv_uimutexes="$enable_uimutexes"], [db_cv_uimutexes="no"])
+AC_MSG_RESULT($db_cv_uimutexes)
+
+AC_MSG_CHECKING(if --enable-umrw option specified)
+AC_ARG_ENABLE(umrw,
+ [AC_HELP_STRING([--enable-umrw],
+ [Mask harmless unitialized memory read/writes.])],
+ [db_cv_umrw="$enable_umrw"], [db_cv_umrw="no"])
+AC_MSG_RESULT($db_cv_umrw)
+
+AC_MSG_CHECKING([if --with-embedix=DIR option specified])
+AC_ARG_WITH(embedix,
+ [AC_HELP_STRING([--with-embedix=DIR],
+ [Embedix install directory location.])],
+ [with_embedix="$withval"], [with_embedix="no"])
+if test "$with_embedix" = "no"; then
+ db_cv_embedix="no"
+ AC_MSG_RESULT($with_embedix)
+else
+ db_cv_embedix="yes"
+ if test "$with_embedix" = "yes"; then
+ db_cv_path_embedix_install="/opt/Embedix"
+ else
+ db_cv_path_embedix_install="$with_embedix"
+ fi
+ AC_MSG_RESULT($db_cv_path_embedix_install)
+fi
+
+AC_MSG_CHECKING(if --with-mutex=MUTEX option specified)
+AC_ARG_WITH(mutex,
+ [AC_HELP_STRING([--with-mutex=MUTEX],
+ [Selection of non-standard mutexes.])],
+ [with_mutex="$withval"], [with_mutex="no"])
+if test "$with_mutex" = "yes"; then
+ AC_MSG_ERROR([--with-mutex requires a mutex name argument])
+fi
+if test "$with_mutex" != "no"; then
+ db_cv_mutex="$with_mutex"
+fi
+AC_MSG_RESULT($with_mutex)
+
+AC_MSG_CHECKING(if --with-rpm=DIR option specified)
+AC_ARG_WITH(rpm,
+ [AC_HELP_STRING([--with-rpm=DIR],
+ [Directory location of RPM archive.])],
+ [with_rpm="$withval"], [with_rpm="no"])
+if test "$with_rpm" = "no"; then
+ db_cv_rpm="no"
+else
+ if test "$with_rpm" = "yes"; then
+ AC_MSG_ERROR([--with-rpm requires a directory argument])
+ fi
+ db_cv_rpm="yes"
+ db_cv_path_rpm_archive="$with_rpm"
+fi
+AC_MSG_RESULT($with_rpm)
+
+AC_MSG_CHECKING([if --with-tcl=DIR option specified])
+AC_ARG_WITH(tcl,
+ [AC_HELP_STRING([--with-tcl=DIR],
+ [Directory location of tclConfig.sh.])],
+ [with_tclconfig="$withval"], [with_tclconfig="no"])
+AC_MSG_RESULT($with_tclconfig)
+if test "$with_tclconfig" != "no"; then
+ db_cv_tcl="yes"
+fi
+
+AC_MSG_CHECKING([if --with-uniquename=NAME option specified])
+AC_ARG_WITH(uniquename,
+ [AC_HELP_STRING([--with-uniquename=NAME],
+ [Build a uniquely named library.])],
+ [with_uniquename="$withval"], [with_uniquename="no"])
+if test "$with_uniquename" = "no"; then
+ db_cv_uniquename="no"
+ AC_MSG_RESULT($with_uniquename)
+else
+ db_cv_uniquename="yes"
+ if test "$with_uniquename" != "yes"; then
+ DB_VERSION_UNIQUE_NAME="$with_uniquename"
+ fi
+ AC_MSG_RESULT($DB_VERSION_UNIQUE_NAME)
+fi
+
+# Embedix requires RPM.
+if test "$db_cv_embedix" = "yes"; then
+ if test "$db_cv_rpm" = "no"; then
+ AC_MSG_ERROR([--with-embedix requires --with-rpm])
+ fi
+fi
+
+# Test requires Tcl
+if test "$db_cv_test" = "yes"; then
+ if test "$db_cv_tcl" = "no"; then
+ AC_MSG_ERROR([--enable-test requires --enable-tcl])
+ fi
+fi])
diff --git a/bdb/dist/aclocal/options.m4 b/bdb/dist/aclocal/options.m4
deleted file mode 100644
index c51a3952419..00000000000
--- a/bdb/dist/aclocal/options.m4
+++ /dev/null
@@ -1,121 +0,0 @@
-dnl $Id: options.m4,v 11.10 2000/07/07 15:50:39 bostic Exp $
-
-dnl Process user-specified options.
-AC_DEFUN(AM_OPTIONS_SET, [
-
-AC_MSG_CHECKING(if --disable-bigfile option specified)
-AC_ARG_ENABLE(bigfile,
- [ --disable-bigfile Disable AIX, HP/UX, Solaris big files.],
- [db_cv_bigfile="yes"], [db_cv_bigfile="no"])
-AC_MSG_RESULT($db_cv_bigfile)
-
-AC_MSG_CHECKING(if --enable-compat185 option specified)
-AC_ARG_ENABLE(compat185,
- [ --enable-compat185 Build DB 1.85 compatibility API.],
- [db_cv_compat185="$enable_compat185"], [db_cv_compat185="no"])
-AC_MSG_RESULT($db_cv_compat185)
-
-AC_MSG_CHECKING(if --enable-cxx option specified)
-AC_ARG_ENABLE(cxx,
- [ --enable-cxx Build C++ API.],
- [db_cv_cxx="$enable_cxx"], [db_cv_cxx="no"])
-AC_MSG_RESULT($db_cv_cxx)
-
-AC_MSG_CHECKING(if --enable-debug option specified)
-AC_ARG_ENABLE(debug,
- [ --enable-debug Build a debugging version.],
- [db_cv_debug="$enable_debug"], [db_cv_debug="no"])
-AC_MSG_RESULT($db_cv_debug)
-
-AC_MSG_CHECKING(if --enable-debug_rop option specified)
-AC_ARG_ENABLE(debug_rop,
- [ --enable-debug_rop Build a version that logs read operations.],
- [db_cv_debug_rop="$enable_debug_rop"], [db_cv_debug_rop="no"])
-AC_MSG_RESULT($db_cv_debug_rop)
-
-AC_MSG_CHECKING(if --enable-debug_wop option specified)
-AC_ARG_ENABLE(debug_wop,
- [ --enable-debug_wop Build a version that logs write operations.],
- [db_cv_debug_wop="$enable_debug_wop"], [db_cv_debug_wop="no"])
-AC_MSG_RESULT($db_cv_debug_wop)
-
-AC_MSG_CHECKING(if --enable-diagnostic option specified)
-AC_ARG_ENABLE(diagnostic,
- [ --enable-diagnostic Build a version with run-time diagnostics.],
- [db_cv_diagnostic="$enable_diagnostic"], [db_cv_diagnostic="no"])
-AC_MSG_RESULT($db_cv_diagnostic)
-
-AC_MSG_CHECKING(if --enable-dump185 option specified)
-AC_ARG_ENABLE(dump185,
- [ --enable-dump185 Build db_dump185(1) to dump 1.85 databases.],
- [db_cv_dump185="$enable_dump185"], [db_cv_dump185="no"])
-AC_MSG_RESULT($db_cv_dump185)
-
-AC_MSG_CHECKING(if --enable-dynamic option specified)
-AC_ARG_ENABLE(dynamic,
- [ --enable-dynamic Build with dynamic libraries.],
- [db_cv_dynamic="$enable_dynamic"], [db_cv_dynamic="no"])
-AC_MSG_RESULT($db_cv_dynamic)
-
-AC_MSG_CHECKING(if --enable-java option specified)
-AC_ARG_ENABLE(java,
- [ --enable-java Build Java API.],
- [db_cv_java="$enable_java"], [db_cv_java="no"])
-AC_MSG_RESULT($db_cv_java)
-
-AC_MSG_CHECKING(if --enable-posixmutexes option specified)
-AC_ARG_ENABLE(posixmutexes,
- [ --enable-posixmutexes Force use of POSIX standard mutexes.],
- [db_cv_posixmutexes="$enable_posixmutexes"], [db_cv_posixmutexes="no"])
-AC_MSG_RESULT($db_cv_posixmutexes)
-
-AC_MSG_CHECKING(if --enable-rpc option specified)
-AC_ARG_ENABLE(rpc,
- [ --enable-rpc Build RPC client/server.],
- [db_cv_rpc="$enable_rpc"], [db_cv_rpc="no"])
-AC_MSG_RESULT($db_cv_rpc)
-
-dnl --enable-shared is an alias for --enable-dynamic. We support it for
-dnl compatibility with other applications, e.g., Tcl.
-AC_MSG_CHECKING(if --enable-shared option specified)
-AC_ARG_ENABLE(shared,
- [ --enable-shared Build with dynamic libraries.],
- [db_cv_shared="$enable_shared"], [db_cv_shared="no"])
-AC_MSG_RESULT($db_cv_shared)
-if test "$db_cv_shared" != "no"; then
- db_cv_dynamic="yes"
-fi
-
-AC_MSG_CHECKING(if --enable-tcl option specified)
-AC_ARG_ENABLE(tcl,
- [ --enable-tcl Build Tcl API.],
- [db_cv_tcl="$enable_tcl"], [db_cv_tcl="no"])
-AC_MSG_RESULT($db_cv_tcl)
-
-AC_MSG_CHECKING(if --enable-test option specified)
-AC_ARG_ENABLE(test,
- [ --enable-test Configure to run the test suite.],
- [db_cv_test="$enable_test"], [db_cv_test="no"])
-AC_MSG_RESULT($db_cv_test)
-
-AC_MSG_CHECKING(if --enable-uimutexes option specified)
-AC_ARG_ENABLE(uimutexes,
- [ --enable-uimutexes Force use of Unix International mutexes.],
- [db_cv_uimutexes="$enable_uimutexes"], [db_cv_uimutexes="no"])
-AC_MSG_RESULT($db_cv_uimutexes)
-
-AC_MSG_CHECKING(if --enable-umrw option specified)
-AC_ARG_ENABLE(umrw,
- [ --enable-umrw Mask harmless unitialized memory read/writes.],
- [db_cv_umrw="$enable_umrw"], [db_cv_umrw="no"])
-AC_MSG_RESULT($db_cv_umrw)
-
-AC_MSG_CHECKING([if --with-tcl option specified])
-AC_ARG_WITH(tcl,
- [ --with-tcl=DIR Directory location of tclConfig.sh.],
- with_tclconfig=${withval}, with_tclconfig="no")
-AC_MSG_RESULT($with_tclconfig)
-if test "$with_tclconfig" != "no"; then
- db_cv_tcl="yes"
-fi
-])dnl
diff --git a/bdb/dist/aclocal/programs.ac b/bdb/dist/aclocal/programs.ac
new file mode 100644
index 00000000000..7bfa1fa2646
--- /dev/null
+++ b/bdb/dist/aclocal/programs.ac
@@ -0,0 +1,80 @@
+# $Id: programs.ac,v 11.20 2001/09/24 02:09:25 bostic Exp $
+
+# Check for programs used in building/installation.
+AC_DEFUN(AM_PROGRAMS_SET, [
+
+AC_CHECK_TOOL(db_cv_path_ar, ar, missing_ar)
+if test "$db_cv_path_ar" = missing_ar; then
+ AC_MSG_ERROR([No ar utility found.])
+fi
+
+AC_CHECK_TOOL(db_cv_path_chmod, chmod, missing_chmod)
+if test "$db_cv_path_chmod" = missing_chmod; then
+ AC_MSG_ERROR([No chmod utility found.])
+fi
+
+AC_CHECK_TOOL(db_cv_path_cp, cp, missing_cp)
+if test "$db_cv_path_cp" = missing_cp; then
+ AC_MSG_ERROR([No cp utility found.])
+fi
+
+if test "$db_cv_rpm" = "yes"; then
+ AC_CHECK_TOOL(path_ldconfig, ldconfig, missing_ldconfig)
+ AC_PATH_PROG(db_cv_path_ldconfig, $path_ldconfig, missing_ldconfig)
+ if test "$db_cv_path_ldconfig" != missing_ldconfig; then
+ RPM_POST_INSTALL="%post -p $db_cv_path_ldconfig"
+ RPM_POST_UNINSTALL="%postun -p $db_cv_path_ldconfig"
+ fi
+fi
+
+AC_CHECK_TOOL(db_cv_path_ln, ln, missing_ln)
+if test "$db_cv_path_ln" = missing_ln; then
+ AC_MSG_ERROR([No ln utility found.])
+fi
+
+AC_CHECK_TOOL(db_cv_path_mkdir, mkdir, missing_mkdir)
+if test "$db_cv_path_mkdir" = missing_mkdir; then
+ AC_MSG_ERROR([No mkdir utility found.])
+fi
+
+# We need a complete path for ranlib, because it doesn't exist on some
+# architectures because the ar utility packages the library itself.
+AC_CHECK_TOOL(path_ranlib, ranlib, missing_ranlib)
+AC_PATH_PROG(db_cv_path_ranlib, $path_ranlib, missing_ranlib)
+
+AC_CHECK_TOOL(db_cv_path_rm, rm, missing_rm)
+if test "$db_cv_path_rm" = missing_rm; then
+ AC_MSG_ERROR([No rm utility found.])
+fi
+
+if test "$db_cv_rpm" = "yes"; then
+ AC_CHECK_TOOL(db_cv_path_rpm, rpm, missing_rpm)
+ if test "$db_cv_path_rpm" = missing_rpm; then
+ AC_MSG_ERROR([No rpm utility found.])
+ fi
+fi
+
+# We need a complete path for sh, because some implementations of make
+# get upset if SHELL is set to just the command name.
+AC_CHECK_TOOL(path_sh, sh, missing_sh)
+AC_PATH_PROG(db_cv_path_sh, $path_sh, missing_sh)
+if test "$db_cv_path_sh" = missing_sh; then
+ AC_MSG_ERROR([No sh utility found.])
+fi
+
+# Don't strip the binaries if --enable-debug was specified.
+if test "$db_cv_debug" = yes; then
+ db_cv_path_strip=debug_build_no_strip
+else
+ AC_CHECK_TOOL(path_strip, strip, missing_strip)
+ AC_PATH_PROG(db_cv_path_strip, $path_strip, missing_strip)
+fi
+
+if test "$db_cv_test" = "yes"; then
+ AC_CHECK_TOOL(db_cv_path_kill, kill, missing_kill)
+ if test "$db_cv_path_kill" = missing_kill; then
+ AC_MSG_ERROR([No kill utility found.])
+ fi
+fi
+
+])
diff --git a/bdb/dist/aclocal/programs.m4 b/bdb/dist/aclocal/programs.m4
deleted file mode 100644
index 9ec04f4d8cd..00000000000
--- a/bdb/dist/aclocal/programs.m4
+++ /dev/null
@@ -1,48 +0,0 @@
-dnl $Id: programs.m4,v 11.11 2000/03/30 21:20:50 bostic Exp $
-
-dnl Check for programs used in building/installation.
-AC_DEFUN(AM_PROGRAMS_SET, [
-
-AC_PATH_PROG(db_cv_path_ar, ar, missing_ar)
-if test "$db_cv_path_ar" = missing_ar; then
- AC_MSG_ERROR([No ar utility found.])
-fi
-AC_PATH_PROG(db_cv_path_chmod, chmod, missing_chmod)
-if test "$db_cv_path_chmod" = missing_chmod; then
- AC_MSG_ERROR([No chmod utility found.])
-fi
-AC_PATH_PROG(db_cv_path_cp, cp, missing_cp)
-if test "$db_cv_path_cp" = missing_cp; then
- AC_MSG_ERROR([No cp utility found.])
-fi
-AC_PATH_PROG(db_cv_path_ln, ln, missing_ln)
-if test "$db_cv_path_ln" = missing_ln; then
- AC_MSG_ERROR([No ln utility found.])
-fi
-AC_PATH_PROG(db_cv_path_mkdir, mkdir, missing_mkdir)
-if test "$db_cv_path_mkdir" = missing_mkdir; then
- AC_MSG_ERROR([No mkdir utility found.])
-fi
-AC_PATH_PROG(db_cv_path_ranlib, ranlib, missing_ranlib)
-AC_PATH_PROG(db_cv_path_rm, rm, missing_rm)
-if test "$db_cv_path_rm" = missing_rm; then
- AC_MSG_ERROR([No rm utility found.])
-fi
-AC_PATH_PROG(db_cv_path_sh, sh, missing_sh)
-if test "$db_cv_path_sh" = missing_sh; then
- AC_MSG_ERROR([No sh utility found.])
-fi
-AC_PATH_PROG(db_cv_path_strip, strip, missing_strip)
-if test "$db_cv_path_strip" = missing_strip; then
- AC_MSG_ERROR([No strip utility found.])
-fi
-
-dnl Check for programs used in testing.
-if test "$db_cv_test" = "yes"; then
- AC_PATH_PROG(db_cv_path_kill, kill, missing_kill)
- if test "$db_cv_path_kill" = missing_kill; then
- AC_MSG_ERROR([No kill utility found.])
- fi
-fi
-
-])dnl
diff --git a/bdb/dist/aclocal/sosuffix.ac b/bdb/dist/aclocal/sosuffix.ac
new file mode 100644
index 00000000000..1197128293b
--- /dev/null
+++ b/bdb/dist/aclocal/sosuffix.ac
@@ -0,0 +1,69 @@
+# $Id: sosuffix.ac,v 1.1 2002/07/08 13:15:05 dda Exp $
+# Determine shared object suffixes.
+#
+# Our method is to use the libtool variable $library_names_spec,
+# set by using AC_PROG_LIBTOOL. This variable is a snippet of shell
+# defined in terms of $versuffix, $release, $libname, $module and $jnimodule.
+# We want to eval it and grab the suffix used for shared objects.
+# By setting $module and $jnimodule to yes/no, we obtain the suffixes
+# used to create dlloadable, or java loadable modules.
+# On many (*nix) systems, these all evaluate to .so, but there
+# are some notable exceptions.
+
+# This macro is used internally to discover the suffix for the current
+# settings of $module and $jnimodule. The result is stored in $_SOSUFFIX.
+AC_DEFUN(_SOSUFFIX_INTERNAL, [
+ versuffix=""
+ release=""
+ libname=libfoo
+ eval library_names=\"$library_names_spec\"
+ _SOSUFFIX=`echo "$library_names" | sed -e 's/.*\.\([[a-zA-Z0-9_]]*\).*/\1/'`
+ if test "$_SOSUFFIX" = '' ; then
+ _SOSUFFIX=so
+ if test "$enable_shared" = "yes" && test "$_SOSUFFIX_MESSAGE" = ""; then
+ _SOSUFFIX_MESSAGE=yes
+ AC_MSG_WARN([libtool may not know about this architecture.])
+ AC_MSG_WARN([assuming .$_SUFFIX suffix for dynamic libraries.])
+ fi
+ fi
+])
+
+# SOSUFFIX_CONFIG will set the variable SOSUFFIX to be the
+# shared library extension used for general linking, not dlopen.
+AC_DEFUN(SOSUFFIX_CONFIG, [
+ AC_MSG_CHECKING([SOSUFFIX from libtool])
+ module=no
+ jnimodule=no
+ _SOSUFFIX_INTERNAL
+ SOSUFFIX=$_SOSUFFIX
+ AC_MSG_RESULT($SOSUFFIX)
+ AC_SUBST(SOSUFFIX)
+])
+
+# MODSUFFIX_CONFIG will set the variable MODSUFFIX to be the
+# shared library extension used for dlopen'ed modules.
+# To discover this, we set $module, simulating libtool's -module option.
+AC_DEFUN(MODSUFFIX_CONFIG, [
+ AC_MSG_CHECKING([MODSUFFIX from libtool])
+ module=yes
+ jnimodule=no
+ _SOSUFFIX_INTERNAL
+ MODSUFFIX=$_SOSUFFIX
+ AC_MSG_RESULT($MODSUFFIX)
+ AC_SUBST(MODSUFFIX)
+])
+
+# JMODSUFFIX_CONFIG will set the variable JMODSUFFIX to be the
+# shared library extension used JNI modules opened by Java.
+# To discover this, we set $jnimodule, simulating libtool's -jnimodule option.
+# -jnimodule is currently a Sleepycat local extension to libtool.
+AC_DEFUN(JMODSUFFIX_CONFIG, [
+ AC_MSG_CHECKING([JMODSUFFIX from libtool])
+ module=yes
+ jnimodule=yes
+ _SOSUFFIX_INTERNAL
+ JMODSUFFIX=$_SOSUFFIX
+ AC_MSG_RESULT($JMODSUFFIX)
+ AC_SUBST(JMODSUFFIX)
+])
+
diff --git a/bdb/dist/aclocal/tcl.ac b/bdb/dist/aclocal/tcl.ac
new file mode 100644
index 00000000000..80ed19c5a97
--- /dev/null
+++ b/bdb/dist/aclocal/tcl.ac
@@ -0,0 +1,136 @@
+# $Id: tcl.ac,v 11.14 2002/09/07 17:25:58 dda Exp $
+
+# The SC_* macros in this file are from the unix/tcl.m4 files in the Tcl
+# 8.3.0 distribution, with some minor changes. For this reason, license
+# terms for the Berkeley DB distribution dist/aclocal/tcl.m4 file are as
+# follows (copied from the license.terms file in the Tcl 8.3 distribution):
+#
+# This software is copyrighted by the Regents of the University of
+# California, Sun Microsystems, Inc., Scriptics Corporation,
+# and other parties. The following terms apply to all files associated
+# with the software unless explicitly disclaimed in individual files.
+#
+# The authors hereby grant permission to use, copy, modify, distribute,
+# and license this software and its documentation for any purpose, provided
+# that existing copyright notices are retained in all copies and that this
+# notice is included verbatim in any distributions. No written agreement,
+# license, or royalty fee is required for any of the authorized uses.
+# Modifications to this software may be copyrighted by their authors
+# and need not follow the licensing terms described here, provided that
+# the new terms are clearly indicated on the first page of each file where
+# they apply.
+#
+# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+# MODIFICATIONS.
+#
+# GOVERNMENT USE: If you are acquiring this software on behalf of the
+# U.S. government, the Government shall have only "Restricted Rights"
+# in the software and related documentation as defined in the Federal
+# Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+# are acquiring the software on behalf of the Department of Defense, the
+# software shall be classified as "Commercial Computer Software" and the
+# Government shall have only "Restricted Rights" as defined in Clause
+# 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+# authors grant the U.S. Government and others acting in its behalf
+# permission to use and distribute the software in accordance with the
+# terms specified in this license.
+
+AC_DEFUN(SC_PATH_TCLCONFIG, [
+ AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+ # First check to see if --with-tclconfig was specified.
+ if test "${with_tclconfig}" != no; then
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+ fi
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+
+ ])
+
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCL_BIN_DIR="# no Tcl configs found"
+ AC_MSG_ERROR(can't find Tcl configuration definitions)
+ else
+ TCL_BIN_DIR=${ac_cv_c_tclconfig}
+ fi
+])
+
+AC_DEFUN(SC_LOAD_TCLCONFIG, [
+ AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
+
+ if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
+ AC_MSG_RESULT([loading])
+ . $TCL_BIN_DIR/tclConfig.sh
+ else
+ AC_MSG_RESULT([file not found])
+ fi
+
+ #
+ # The eval is required to do the TCL_DBGX substitution in the
+ # TCL_LIB_FILE variable
+ #
+ eval TCL_LIB_FILE="${TCL_LIB_FILE}"
+ eval TCL_LIB_FLAG="${TCL_LIB_FLAG}"
+ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+
+ #
+ # If the DB Tcl library isn't loaded with the Tcl spec and library
+ # flags on AIX, the resulting libdb_tcl-X.Y.so.0 will drop core at
+ # load time. [#4843] Furthermore, with Tcl 8.3, the link flags
+ # given by the Tcl spec are insufficient for our use. [#5779]
+ #
+ case "$host_os" in
+ aix4.[[2-9]].*)
+ LIBTSO_LIBS="$LIBTSO_LIBS $TCL_LIB_SPEC $TCL_LIB_FLAG"
+ LIBTSO_LIBS="$LIBTSO_LIBS -L$TCL_EXEC_PREFIX/lib -ltcl$TCL_VERSION";;
+ aix*)
+ LIBTSO_LIBS="$LIBTSO_LIBS $TCL_LIB_SPEC $TCL_LIB_FLAG";;
+ esac
+ AC_SUBST(TCL_BIN_DIR)
+ AC_SUBST(TCL_SRC_DIR)
+ AC_SUBST(TCL_LIB_FILE)
+
+ AC_SUBST(TCL_TCLSH)
+ TCL_TCLSH="${TCL_PREFIX}/bin/tclsh${TCL_VERSION}"
+])
+
+# Optional Tcl API.
+AC_DEFUN(AM_TCL_LOAD, [
+if test "$db_cv_tcl" = "yes"; then
+ if test "$enable_shared" = "no"; then
+ AC_MSG_ERROR([Tcl requires shared libraries])
+ fi
+
+ AC_SUBST(TCFLAGS)
+
+ SC_PATH_TCLCONFIG
+ SC_LOAD_TCLCONFIG
+
+ if test x"$TCL_PREFIX" != x && test -f "$TCL_PREFIX/include/tcl.h"; then
+ TCFLAGS="-I$TCL_PREFIX/include"
+ fi
+
+ INSTALL_LIBS="${INSTALL_LIBS} \$(libtso_target)"
+fi])
diff --git a/bdb/dist/aclocal/tcl.m4 b/bdb/dist/aclocal/tcl.m4
deleted file mode 100644
index 3d0aec2e8ff..00000000000
--- a/bdb/dist/aclocal/tcl.m4
+++ /dev/null
@@ -1,126 +0,0 @@
-dnl $Id: tcl.m4,v 11.5 2000/06/27 13:21:28 bostic Exp $
-
-dnl The SC_* macros in this file are from the unix/tcl.m4 files in the Tcl
-dnl 8.3.0 distribution, with some minor changes. For this reason, license
-dnl terms for the Berkeley DB distribution dist/aclocal/tcl.m4 file are as
-dnl follows (copied from the license.terms file in the Tcl 8.3 distribution):
-dnl
-dnl This software is copyrighted by the Regents of the University of
-dnl California, Sun Microsystems, Inc., Scriptics Corporation,
-dnl and other parties. The following terms apply to all files associated
-dnl with the software unless explicitly disclaimed in individual files.
-dnl
-dnl The authors hereby grant permission to use, copy, modify, distribute,
-dnl and license this software and its documentation for any purpose, provided
-dnl that existing copyright notices are retained in all copies and that this
-dnl notice is included verbatim in any distributions. No written agreement,
-dnl license, or royalty fee is required for any of the authorized uses.
-dnl Modifications to this software may be copyrighted by their authors
-dnl and need not follow the licensing terms described here, provided that
-dnl the new terms are clearly indicated on the first page of each file where
-dnl they apply.
-dnl
-dnl IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
-dnl FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-dnl ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
-dnl DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
-dnl POSSIBILITY OF SUCH DAMAGE.
-dnl
-dnl THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
-dnl INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
-dnl FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
-dnl IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
-dnl NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
-dnl MODIFICATIONS.
-dnl
-dnl GOVERNMENT USE: If you are acquiring this software on behalf of the
-dnl U.S. government, the Government shall have only "Restricted Rights"
-dnl in the software and related documentation as defined in the Federal
-dnl Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
-dnl are acquiring the software on behalf of the Department of Defense, the
-dnl software shall be classified as "Commercial Computer Software" and the
-dnl Government shall have only "Restricted Rights" as defined in Clause
-dnl 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
-dnl authors grant the U.S. Government and others acting in its behalf
-dnl permission to use and distribute the software in accordance with the
-dnl terms specified in this license.
-
-AC_DEFUN(SC_PATH_TCLCONFIG, [
- AC_CACHE_VAL(ac_cv_c_tclconfig,[
-
- # First check to see if --with-tclconfig was specified.
- if test "${with_tclconfig}" != no; then
- if test -f "${with_tclconfig}/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
- else
- AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
- fi
- fi
-
- # check in a few common install locations
- if test x"${ac_cv_c_tclconfig}" = x ; then
- for i in `ls -d /usr/local/lib 2>/dev/null` ; do
- if test -f "$i/tclConfig.sh" ; then
- ac_cv_c_tclconfig=`(cd $i; pwd)`
- break
- fi
- done
- fi
-
- ])
-
- if test x"${ac_cv_c_tclconfig}" = x ; then
- TCL_BIN_DIR="# no Tcl configs found"
- AC_MSG_ERROR(can't find Tcl configuration definitions)
- else
- TCL_BIN_DIR=${ac_cv_c_tclconfig}
- fi
-])
-
-AC_DEFUN(SC_LOAD_TCLCONFIG, [
- AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
-
- if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
- AC_MSG_RESULT([loading])
- . $TCL_BIN_DIR/tclConfig.sh
- else
- AC_MSG_RESULT([file not found])
- fi
-
- #
- # The eval is required to do the TCL_DBGX substitution in the
- # TCL_LIB_FILE variable
- #
- eval TCL_LIB_FILE="${TCL_LIB_FILE}"
- eval TCL_LIB_FLAG="${TCL_LIB_FLAG}"
- eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
-
- AC_SUBST(TCL_BIN_DIR)
- AC_SUBST(TCL_SRC_DIR)
- AC_SUBST(TCL_LIB_FILE)
-
- AC_SUBST(TCL_TCLSH)
- TCL_TCLSH="${TCL_PREFIX}/bin/tclsh${TCL_VERSION}"
-])
-
-dnl Optional Tcl API.
-AC_DEFUN(AM_TCL_LOAD, [
-if test "$db_cv_tcl" != no; then
- if test "$db_cv_dynamic" != "yes"; then
- AC_MSG_ERROR([--with-tcl requires --enable-dynamic])
- fi
-
- AC_SUBST(TCFLAGS)
-
- SC_PATH_TCLCONFIG
- SC_LOAD_TCLCONFIG
-
- if test x"$TCL_PREFIX" != x && test -f "$TCL_PREFIX/include/tcl.h"; then
- TCFLAGS="-I$TCL_PREFIX/include"
- fi
-
- LIBS="$LIBS $TCL_LIB_SPEC $TCL_LIBS"
-
- ADDITIONAL_LIBS="$ADDITIONAL_LIBS \$(libtso_target)"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_tcl"
-fi])
diff --git a/bdb/dist/aclocal/types.ac b/bdb/dist/aclocal/types.ac
new file mode 100644
index 00000000000..db8aaac6884
--- /dev/null
+++ b/bdb/dist/aclocal/types.ac
@@ -0,0 +1,146 @@
+# $Id: types.ac,v 11.10 2001/12/10 14:16:49 bostic Exp $
+
+# db.h includes <sys/types.h> and <stdio.h>, not the other default includes
+# autoconf usually includes. For that reason, we specify a set of includes
+# for all type checking tests. [#5060]
+AC_DEFUN(DB_INCLUDES, [[
+#include <sys/types.h>
+#include <stdio.h>]])
+
+# Check the sizes we know about, and see if any of them match what's needed.
+#
+# Prefer ints to anything else, because read, write and others historically
+# returned an int.
+AC_DEFUN(AM_SEARCH_USIZES, [
+ case "$3" in
+ "$ac_cv_sizeof_unsigned_int")
+ $1="typedef unsigned int $2;";;
+ "$ac_cv_sizeof_unsigned_char")
+ $1="typedef unsigned char $2;";;
+ "$ac_cv_sizeof_unsigned_short")
+ $1="typedef unsigned short $2;";;
+ "$ac_cv_sizeof_unsigned_long")
+ $1="typedef unsigned long $2;";;
+ *)
+ AC_MSG_ERROR([No unsigned $3-byte integral type]);;
+ esac])
+AC_DEFUN(AM_SEARCH_SSIZES, [
+ case "$3" in
+ "$ac_cv_sizeof_int")
+ $1="typedef int $2;";;
+ "$ac_cv_sizeof_char")
+ $1="typedef char $2;";;
+ "$ac_cv_sizeof_short")
+ $1="typedef short $2;";;
+ "$ac_cv_sizeof_long")
+ $1="typedef long $2;";;
+ *)
+ AC_MSG_ERROR([No signed $3-byte integral type]);;
+ esac])
+
+# Check for the standard system types.
+AC_DEFUN(AM_TYPES, [
+
+# We need to know the sizes of various objects on this system.
+# We don't use the SIZEOF_XXX values created by autoconf.
+AC_CHECK_SIZEOF(char,, DB_INCLUDES)
+AC_CHECK_SIZEOF(unsigned char,, DB_INCLUDES)
+AC_CHECK_SIZEOF(short,, DB_INCLUDES)
+AC_CHECK_SIZEOF(unsigned short,, DB_INCLUDES)
+AC_CHECK_SIZEOF(int,, DB_INCLUDES)
+AC_CHECK_SIZEOF(unsigned int,, DB_INCLUDES)
+AC_CHECK_SIZEOF(long,, DB_INCLUDES)
+AC_CHECK_SIZEOF(unsigned long,, DB_INCLUDES)
+AC_CHECK_SIZEOF(size_t,, DB_INCLUDES)
+AC_CHECK_SIZEOF(char *,, DB_INCLUDES)
+
+# We require off_t and size_t, and we don't try to substitute our own
+# if we can't find them.
+AC_CHECK_TYPE(off_t,,, DB_INCLUDES)
+if test "$ac_cv_type_off_t" = no; then
+ AC_MSG_ERROR([No off_t type.])
+fi
+
+AC_CHECK_TYPE(size_t,,, DB_INCLUDES)
+if test "$ac_cv_type_size_t" = no; then
+ AC_MSG_ERROR([No size_t type.])
+fi
+
+# We look for u_char, u_short, u_int, u_long -- if we can't find them,
+# we create our own.
+AC_SUBST(u_char_decl)
+AC_CHECK_TYPE(u_char,,, DB_INCLUDES)
+if test "$ac_cv_type_u_char" = no; then
+ u_char_decl="typedef unsigned char u_char;"
+fi
+
+AC_SUBST(u_short_decl)
+AC_CHECK_TYPE(u_short,,, DB_INCLUDES)
+if test "$ac_cv_type_u_short" = no; then
+ u_short_decl="typedef unsigned short u_short;"
+fi
+
+AC_SUBST(u_int_decl)
+AC_CHECK_TYPE(u_int,,, DB_INCLUDES)
+if test "$ac_cv_type_u_int" = no; then
+ u_int_decl="typedef unsigned int u_int;"
+fi
+
+AC_SUBST(u_long_decl)
+AC_CHECK_TYPE(u_long,,, DB_INCLUDES)
+if test "$ac_cv_type_u_long" = no; then
+ u_long_decl="typedef unsigned long u_long;"
+fi
+
+AC_SUBST(u_int8_decl)
+AC_CHECK_TYPE(u_int8_t,,, DB_INCLUDES)
+if test "$ac_cv_type_u_int8_t" = no; then
+ AM_SEARCH_USIZES(u_int8_decl, u_int8_t, 1)
+fi
+
+AC_SUBST(u_int16_decl)
+AC_CHECK_TYPE(u_int16_t,,, DB_INCLUDES)
+if test "$ac_cv_type_u_int16_t" = no; then
+ AM_SEARCH_USIZES(u_int16_decl, u_int16_t, 2)
+fi
+
+AC_SUBST(int16_decl)
+AC_CHECK_TYPE(int16_t,,, DB_INCLUDES)
+if test "$ac_cv_type_int16_t" = no; then
+ AM_SEARCH_SSIZES(int16_decl, int16_t, 2)
+fi
+
+AC_SUBST(u_int32_decl)
+AC_CHECK_TYPE(u_int32_t,,, DB_INCLUDES)
+if test "$ac_cv_type_u_int32_t" = no; then
+ AM_SEARCH_USIZES(u_int32_decl, u_int32_t, 4)
+fi
+
+AC_SUBST(int32_decl)
+AC_CHECK_TYPE(int32_t,,, DB_INCLUDES)
+if test "$ac_cv_type_int32_t" = no; then
+ AM_SEARCH_SSIZES(int32_decl, int32_t, 4)
+fi
+
+# Check for ssize_t -- if none exists, find a signed integral type that's
+# the same size as a size_t.
+AC_SUBST(ssize_t_decl)
+AC_CHECK_TYPE(ssize_t,,, DB_INCLUDES)
+if test "$ac_cv_type_ssize_t" = no; then
+ AM_SEARCH_SSIZES(ssize_t_decl, ssize_t, $ac_cv_sizeof_size_t)
+fi
+
+# Find the largest integral type.
+AC_SUBST(db_align_t_decl)
+AC_CHECK_TYPE(unsigned long long,,, DB_INCLUDES)
+if test "$ac_cv_type_unsigned_long_long" = no; then
+ db_align_t_decl="typedef unsigned long db_align_t;"
+else
+ db_align_t_decl="typedef unsigned long long db_align_t;"
+fi
+
+# Find an integral type which is the same size as a pointer.
+AC_SUBST(db_alignp_t_decl)
+AM_SEARCH_USIZES(db_alignp_t_decl, db_alignp_t, $ac_cv_sizeof_char_p)
+
+])
diff --git a/bdb/dist/aclocal/types.m4 b/bdb/dist/aclocal/types.m4
deleted file mode 100644
index a9a03ab6d87..00000000000
--- a/bdb/dist/aclocal/types.m4
+++ /dev/null
@@ -1,139 +0,0 @@
-dnl $Id: types.m4,v 11.4 1999/12/04 19:18:28 bostic Exp $
-
-dnl Check for the standard shorthand types.
-AC_DEFUN(AM_SHORTHAND_TYPES, [dnl
-
-AC_SUBST(ssize_t_decl)
-AC_CACHE_CHECK([for ssize_t], db_cv_ssize_t, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], ssize_t foo;,
- [db_cv_ssize_t=yes], [db_cv_ssize_t=no])])
-if test "$db_cv_ssize_t" = no; then
- ssize_t_decl="typedef int ssize_t;"
-fi
-
-AC_SUBST(u_char_decl)
-AC_CACHE_CHECK([for u_char], db_cv_uchar, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_char foo;,
- [db_cv_uchar=yes], [db_cv_uchar=no])])
-if test "$db_cv_uchar" = no; then
- u_char_decl="typedef unsigned char u_char;"
-fi
-
-AC_SUBST(u_short_decl)
-AC_CACHE_CHECK([for u_short], db_cv_ushort, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_short foo;,
- [db_cv_ushort=yes], [db_cv_ushort=no])])
-if test "$db_cv_ushort" = no; then
- u_short_decl="typedef unsigned short u_short;"
-fi
-
-AC_SUBST(u_int_decl)
-AC_CACHE_CHECK([for u_int], db_cv_uint, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_int foo;,
- [db_cv_uint=yes], [db_cv_uint=no])])
-if test "$db_cv_uint" = no; then
- u_int_decl="typedef unsigned int u_int;"
-fi
-
-AC_SUBST(u_long_decl)
-AC_CACHE_CHECK([for u_long], db_cv_ulong, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_long foo;,
- [db_cv_ulong=yes], [db_cv_ulong=no])])
-if test "$db_cv_ulong" = no; then
- u_long_decl="typedef unsigned long u_long;"
-fi
-
-dnl DB/Vi use specific integer sizes.
-AC_SUBST(u_int8_decl)
-AC_CACHE_CHECK([for u_int8_t], db_cv_uint8, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_int8_t foo;,
- [db_cv_uint8=yes],
- AC_TRY_RUN([main(){exit(sizeof(unsigned char) != 1);}],
- [db_cv_uint8="unsigned char"], [db_cv_uint8=no]))])
-if test "$db_cv_uint8" = no; then
- AC_MSG_ERROR(No unsigned 8-bit integral type.)
-fi
-if test "$db_cv_uint8" != yes; then
- u_int8_decl="typedef $db_cv_uint8 u_int8_t;"
-fi
-
-AC_SUBST(u_int16_decl)
-AC_CACHE_CHECK([for u_int16_t], db_cv_uint16, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_int16_t foo;,
- [db_cv_uint16=yes],
-AC_TRY_RUN([main(){exit(sizeof(unsigned short) != 2);}],
- [db_cv_uint16="unsigned short"],
-AC_TRY_RUN([main(){exit(sizeof(unsigned int) != 2);}],
- [db_cv_uint16="unsigned int"], [db_cv_uint16=no])))])
-if test "$db_cv_uint16" = no; then
- AC_MSG_ERROR([No unsigned 16-bit integral type.])
-fi
-if test "$db_cv_uint16" != yes; then
- u_int16_decl="typedef $db_cv_uint16 u_int16_t;"
-fi
-
-AC_SUBST(int16_decl)
-AC_CACHE_CHECK([for int16_t], db_cv_int16, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], int16_t foo;,
- [db_cv_int16=yes],
-AC_TRY_RUN([main(){exit(sizeof(short) != 2);}],
- [db_cv_int16="short"],
-AC_TRY_RUN([main(){exit(sizeof(int) != 2);}],
- [db_cv_int16="int"], [db_cv_int16=no])))])
-if test "$db_cv_int16" = no; then
- AC_MSG_ERROR([No signed 16-bit integral type.])
-fi
-if test "$db_cv_int16" != yes; then
- int16_decl="typedef $db_cv_int16 int16_t;"
-fi
-
-AC_SUBST(u_int32_decl)
-AC_CACHE_CHECK([for u_int32_t], db_cv_uint32, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], u_int32_t foo;,
- [db_cv_uint32=yes],
-AC_TRY_RUN([main(){exit(sizeof(unsigned int) != 4);}],
- [db_cv_uint32="unsigned int"],
-AC_TRY_RUN([main(){exit(sizeof(unsigned long) != 4);}],
- [db_cv_uint32="unsigned long"], [db_cv_uint32=no])))])
-if test "$db_cv_uint32" = no; then
- AC_MSG_ERROR([No unsigned 32-bit integral type.])
-fi
-if test "$db_cv_uint32" != yes; then
- u_int32_decl="typedef $db_cv_uint32 u_int32_t;"
-fi
-
-AC_SUBST(int32_decl)
-AC_CACHE_CHECK([for int32_t], db_cv_int32, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], int32_t foo;,
- [db_cv_int32=yes],
-AC_TRY_RUN([main(){exit(sizeof(int) != 4);}],
- [db_cv_int32="int"],
-AC_TRY_RUN([main(){exit(sizeof(long) != 4);}],
- [db_cv_int32="long"], [db_cv_int32=no])))])
-if test "$db_cv_int32" = no; then
- AC_MSG_ERROR([No signed 32-bit integral type.])
-fi
-if test "$db_cv_int32" != yes; then
- int32_decl="typedef $db_cv_int32 int32_t;"
-fi
-
-dnl Figure out largest integral type.
-AC_SUBST(db_align_t_decl)
-AC_CACHE_CHECK([for largest integral type], db_cv_align_t, [dnl
-AC_TRY_COMPILE([#include <sys/types.h>], long long foo;,
- [db_cv_align_t="unsigned long long"], [db_cv_align_t="unsigned long"])])
-db_align_t_decl="typedef $db_cv_align_t db_align_t;"
-
-dnl Figure out integral type the same size as a pointer.
-AC_SUBST(db_alignp_t_decl)
-AC_CACHE_CHECK([for integral type equal to pointer size], db_cv_alignp_t, [dnl
-db_cv_alignp_t=$db_cv_align_t
-AC_TRY_RUN([main(){exit(sizeof(unsigned int) != sizeof(char *));}],
- [db_cv_alignp_t="unsigned int"])
-AC_TRY_RUN([main(){exit(sizeof(unsigned long) != sizeof(char *));}],
- [db_cv_alignp_t="unsigned long"])
-AC_TRY_RUN([main(){exit(sizeof(unsigned long long) != sizeof(char *));}],
- [db_cv_alignp_t="unsigned long long"])])
-db_alignp_t_decl="typedef $db_cv_alignp_t db_alignp_t;"
-
-])dnl
diff --git a/bdb/dist/aclocal_java/ac_check_class.ac b/bdb/dist/aclocal_java/ac_check_class.ac
new file mode 100644
index 00000000000..915198af567
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_check_class.ac
@@ -0,0 +1,107 @@
+dnl @synopsis AC_CHECK_CLASS
+dnl
+dnl AC_CHECK_CLASS tests the existence of a given Java class, either in
+dnl a jar or in a '.class' file.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_check_class.ac,v 1.1 2001/08/23 16:58:42 dda Exp $
+dnl
+AC_DEFUN([AC_CHECK_CLASS],[
+AC_REQUIRE([AC_PROG_JAVA])
+ac_var_name=`echo $1 | sed 's/\./_/g'`
+dnl Normaly I'd use a AC_CACHE_CHECK here but since the variable name is
+dnl dynamic I need an extra level of extraction
+AC_MSG_CHECKING([for $1 class])
+AC_CACHE_VAL(ac_cv_class_$ac_var_name, [
+if test x$ac_cv_prog_uudecode_base64 = xyes; then
+dnl /**
+dnl * Test.java: used to test dynamicaly if a class exists.
+dnl */
+dnl public class Test
+dnl {
+dnl
+dnl public static void
+dnl main( String[] argv )
+dnl {
+dnl Class lib;
+dnl if (argv.length < 1)
+dnl {
+dnl System.err.println ("Missing argument");
+dnl System.exit (77);
+dnl }
+dnl try
+dnl {
+dnl lib = Class.forName (argv[0]);
+dnl }
+dnl catch (ClassNotFoundException e)
+dnl {
+dnl System.exit (1);
+dnl }
+dnl lib = null;
+dnl System.exit (0);
+dnl }
+dnl
+dnl }
+cat << \EOF > Test.uue
+begin-base64 644 Test.class
+yv66vgADAC0AKQcAAgEABFRlc3QHAAQBABBqYXZhL2xhbmcvT2JqZWN0AQAE
+bWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51
+bWJlclRhYmxlDAAKAAsBAANlcnIBABVMamF2YS9pby9QcmludFN0cmVhbTsJ
+AA0ACQcADgEAEGphdmEvbGFuZy9TeXN0ZW0IABABABBNaXNzaW5nIGFyZ3Vt
+ZW50DAASABMBAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWCgAV
+ABEHABYBABNqYXZhL2lvL1ByaW50U3RyZWFtDAAYABkBAARleGl0AQAEKEkp
+VgoADQAXDAAcAB0BAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylM
+amF2YS9sYW5nL0NsYXNzOwoAHwAbBwAgAQAPamF2YS9sYW5nL0NsYXNzBwAi
+AQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BAAY8aW5pdD4B
+AAMoKVYMACMAJAoAAwAlAQAKU291cmNlRmlsZQEACVRlc3QuamF2YQAhAAEA
+AwAAAAAAAgAJAAUABgABAAcAAABtAAMAAwAAACkqvgSiABCyAAwSD7YAFBBN
+uAAaKgMyuAAeTKcACE0EuAAaAUwDuAAasQABABMAGgAdACEAAQAIAAAAKgAK
+AAAACgAAAAsABgANAA4ADgATABAAEwASAB4AFgAiABgAJAAZACgAGgABACMA
+JAABAAcAAAAhAAEAAQAAAAUqtwAmsQAAAAEACAAAAAoAAgAAAAQABAAEAAEA
+JwAAAAIAKA==
+====
+EOF
+ if uudecode$EXEEXT Test.uue; then
+ :
+ else
+ echo "configure: __oline__: uudecode had trouble decoding base 64 file 'Test.uue'" >&AC_FD_CC
+ echo "configure: failed file was:" >&AC_FD_CC
+ cat Test.uue >&AC_FD_CC
+ ac_cv_prog_uudecode_base64=no
+ fi
+ rm -f Test.uue
+ if AC_TRY_COMMAND($JAVA $JAVAFLAGS Test $1) >/dev/null 2>&1; then
+ eval "ac_cv_class_$ac_var_name=yes"
+ else
+ eval "ac_cv_class_$ac_var_name=no"
+ fi
+ rm -f Test.class
+else
+ AC_TRY_COMPILE_JAVA([$1], , [eval "ac_cv_class_$ac_var_name=yes"],
+ [eval "ac_cv_class_$ac_var_name=no"])
+fi
+eval "ac_var_val=$`eval echo ac_cv_class_$ac_var_name`"
+eval "HAVE_$ac_var_name=$`echo ac_cv_class_$ac_var_val`"
+HAVE_LAST_CLASS=$ac_var_val
+if test x$ac_var_val = xyes; then
+ ifelse([$2], , :, [$2])
+else
+ ifelse([$3], , :, [$3])
+fi
+])
+dnl for some reason the above statment didn't fall though here?
+dnl do scripts have variable scoping?
+eval "ac_var_val=$`eval echo ac_cv_class_$ac_var_name`"
+AC_MSG_RESULT($ac_var_val)
+])
diff --git a/bdb/dist/aclocal_java/ac_check_classpath.ac b/bdb/dist/aclocal_java/ac_check_classpath.ac
new file mode 100644
index 00000000000..4a78d0f8785
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_check_classpath.ac
@@ -0,0 +1,23 @@
+dnl @synopsis AC_CHECK_CLASSPATH
+dnl
+dnl AC_CHECK_CLASSPATH just displays the CLASSPATH, for the edification
+dnl of the user.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_check_classpath.ac,v 1.1 2001/08/23 16:58:42 dda Exp $
+dnl
+AC_DEFUN([AC_CHECK_CLASSPATH],[
+if test "x$CLASSPATH" = x; then
+ echo "You have no CLASSPATH, I hope it is good"
+else
+ echo "You have CLASSPATH $CLASSPATH, hope it is correct"
+fi
+])
diff --git a/bdb/dist/aclocal_java/ac_check_junit.ac b/bdb/dist/aclocal_java/ac_check_junit.ac
new file mode 100644
index 00000000000..3b81d1dc3fc
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_check_junit.ac
@@ -0,0 +1,54 @@
+dnl @synopsis AC_CHECK_JUNIT
+dnl
+dnl AC_CHECK_JUNIT tests the availability of the Junit testing
+dnl framework, and set some variables for conditional compilation
+dnl of the test suite by automake.
+dnl
+dnl If available, JUNIT is set to a command launching the text
+dnl based user interface of Junit, @JAVA_JUNIT@ is set to $JAVA_JUNIT
+dnl and @TESTS_JUNIT@ is set to $TESTS_JUNIT, otherwise they are set
+dnl to empty values.
+dnl
+dnl You can use these variables in your Makefile.am file like this :
+dnl
+dnl # Some of the following classes are built only if junit is available
+dnl JAVA_JUNIT = Class1Test.java Class2Test.java AllJunitTests.java
+dnl
+dnl noinst_JAVA = Example1.java Example2.java @JAVA_JUNIT@
+dnl
+dnl EXTRA_JAVA = $(JAVA_JUNIT)
+dnl
+dnl TESTS_JUNIT = AllJunitTests
+dnl
+dnl TESTS = StandaloneTest1 StandaloneTest2 @TESTS_JUNIT@
+dnl
+dnl EXTRA_TESTS = $(TESTS_JUNIT)
+dnl
+dnl AllJunitTests :
+dnl echo "#! /bin/sh" > $@
+dnl echo "exec @JUNIT@ my.package.name.AllJunitTests" >> $@
+dnl chmod +x $@
+dnl
+dnl @author Luc Maisonobe
+dnl @version $Id: ac_check_junit.ac,v 1.1 2001/08/23 16:58:43 dda Exp $
+dnl
+AC_DEFUN([AC_CHECK_JUNIT],[
+AC_CACHE_VAL(ac_cv_prog_JUNIT,[
+AC_CHECK_CLASS(junit.textui.TestRunner)
+if test x"`eval 'echo $ac_cv_class_junit_textui_TestRunner'`" != xno ; then
+ ac_cv_prog_JUNIT='$(CLASSPATH_ENV) $(JAVA) $(JAVAFLAGS) junit.textui.TestRunner'
+fi])
+AC_MSG_CHECKING([for junit])
+if test x"`eval 'echo $ac_cv_prog_JUNIT'`" != x ; then
+ JUNIT="$ac_cv_prog_JUNIT"
+ JAVA_JUNIT='$(JAVA_JUNIT)'
+ TESTS_JUNIT='$(TESTS_JUNIT)'
+else
+ JUNIT=
+ JAVA_JUNIT=
+ TESTS_JUNIT=
+fi
+AC_MSG_RESULT($JAVA_JUNIT)
+AC_SUBST(JUNIT)
+AC_SUBST(JAVA_JUNIT)
+AC_SUBST(TESTS_JUNIT)])
diff --git a/bdb/dist/aclocal_java/ac_check_rqrd_class.ac b/bdb/dist/aclocal_java/ac_check_rqrd_class.ac
new file mode 100644
index 00000000000..ab62e33c887
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_check_rqrd_class.ac
@@ -0,0 +1,26 @@
+dnl @synopsis AC_CHECK_RQRD_CLASS
+dnl
+dnl AC_CHECK_RQRD_CLASS tests the existence of a given Java class, either in
+dnl a jar or in a '.class' file and fails if it doesn't exist.
+dnl Its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_check_rqrd_class.ac,v 1.1 2001/08/23 16:58:43 dda Exp $
+dnl
+
+AC_DEFUN([AC_CHECK_RQRD_CLASS],[
+CLASS=`echo $1|sed 's/\./_/g'`
+AC_CHECK_CLASS($1)
+if test "$HAVE_LAST_CLASS" = "no"; then
+ AC_MSG_ERROR([Required class $1 missing, exiting.])
+fi
+])
diff --git a/bdb/dist/aclocal_java/ac_java_options.ac b/bdb/dist/aclocal_java/ac_java_options.ac
new file mode 100644
index 00000000000..567afca7fa5
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_java_options.ac
@@ -0,0 +1,32 @@
+dnl @synopsis AC_JAVA_OPTIONS
+dnl
+dnl AC_JAVA_OPTIONS adds configure command line options used for Java m4
+dnl macros. This Macro is optional.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Devin Weaver <ktohg@tritarget.com>
+dnl @version $Id: ac_java_options.ac,v 1.1 2001/08/23 16:58:43 dda Exp $
+dnl
+AC_DEFUN([AC_JAVA_OPTIONS],[
+AC_ARG_WITH(java-prefix,
+ [ --with-java-prefix=PFX prefix where Java runtime is installed (optional)])
+AC_ARG_WITH(javac-flags,
+ [ --with-javac-flags=FLAGS flags to pass to the Java compiler (optional)])
+AC_ARG_WITH(java-flags,
+ [ --with-java-flags=FLAGS flags to pass to the Java VM (optional)])
+JAVAPREFIX=$with_java_prefix
+JAVACFLAGS=$with_javac_flags
+JAVAFLAGS=$with_java_flags
+AC_SUBST(JAVAPREFIX)dnl
+AC_SUBST(JAVACFLAGS)dnl
+AC_SUBST(JAVAFLAGS)dnl
+AC_SUBST(JAVA)dnl
+AC_SUBST(JAVAC)dnl
+])
diff --git a/bdb/dist/aclocal_java/ac_jni_include_dirs.ac b/bdb/dist/aclocal_java/ac_jni_include_dirs.ac
new file mode 100644
index 00000000000..65cfbbfd13e
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_jni_include_dirs.ac
@@ -0,0 +1,112 @@
+dnl @synopsis AC_JNI_INCLUDE_DIR
+dnl
+dnl AC_JNI_INCLUDE_DIR finds include directories needed
+dnl for compiling programs using the JNI interface.
+dnl
+dnl JNI include directories are usually in the java distribution
+dnl This is deduced from the value of JAVAC. When this macro
+dnl completes, a list of directories is left in the variable
+dnl JNI_INCLUDE_DIRS.
+dnl
+dnl Example usage follows:
+dnl
+dnl AC_JNI_INCLUDE_DIR
+dnl
+dnl for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
+dnl do
+dnl CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR"
+dnl done
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAVAC=yourcompiler before calling
+dnl AC_JNI_INCLUDE_DIR
+dnl
+dnl - at the configure level, setenv JAVAC
+dnl
+dnl Note: This macro can work with the autoconf M4 macros for Java programs.
+dnl This particular macro is not part of the original set of macros.
+dnl
+dnl @author Don Anderson <dda@sleepycat.com>
+dnl @version $Id: ac_jni_include_dirs.ac,v 1.8 2002/09/04 21:27:30 dda Exp $
+dnl
+AC_DEFUN(AC_JNI_INCLUDE_DIR,[
+
+JNI_INCLUDE_DIRS=""
+
+test "x$JAVAC" = x && AC_MSG_ERROR(['$JAVAC' undefined])
+AC_PATH_PROG(_ACJNI_JAVAC, $JAVAC, $JAVAC)
+test ! -x "$_ACJNI_JAVAC" && AC_MSG_ERROR([$JAVAC could not be found in path])
+AC_MSG_CHECKING(absolute path of $JAVAC)
+case "$_ACJNI_JAVAC" in
+/*) AC_MSG_RESULT($_ACJNI_JAVAC);;
+*) AC_MSG_ERROR([$_ACJNI_JAVAC is not an absolute path name]);;
+esac
+
+_ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC")
+_JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'`
+case "$host_os" in
+ darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'`
+ _JINC="$_JTOPDIR/Headers";;
+ *) _JINC="$_JTOPDIR/include";;
+esac
+
+# If we find jni.h in /usr/include, then it's not a java-only tree, so
+# don't add /usr/include or subdirectories to the list of includes.
+# An extra -I/usr/include can foul things up with newer gcc's.
+if test -f "$_JINC/jni.h"; then
+ if test "$_JINC" != "/usr/include"; then
+ JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JINC"
+ fi
+else
+ _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'`
+ if test -f "$_JTOPDIR/include/jni.h"; then
+ if test "$_JTOPDIR" != "/usr"; then
+ JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include"
+ fi
+ else
+ AC_MSG_ERROR([cannot find java include files])
+ fi
+fi
+
+# get the likely subdirectories for system specific java includes
+if test "$_JTOPDIR" != "/usr"; then
+ case "$host_os" in
+ aix*) _JNI_INC_SUBDIRS="aix";;
+ bsdi*) _JNI_INC_SUBDIRS="bsdos";;
+ linux*) _JNI_INC_SUBDIRS="linux genunix";;
+ osf*) _JNI_INC_SUBDIRS="alpha";;
+ solaris*) _JNI_INC_SUBDIRS="solaris";;
+ *) _JNI_INC_SUBDIRS="genunix";;
+ esac
+fi
+
+# add any subdirectories that are present
+for _JINCSUBDIR in $_JNI_INC_SUBDIRS
+do
+ if test -d "$_JTOPDIR/include/$_JINCSUBDIR"; then
+ JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$_JINCSUBDIR"
+ fi
+done
+])
+
+# _ACJNI_FOLLOW_SYMLINKS <path>
+# Follows symbolic links on <path>,
+# finally setting variable _ACJNI_FOLLOWED
+# --------------------
+AC_DEFUN(_ACJNI_FOLLOW_SYMLINKS,[
+# find the include directory relative to the javac executable
+_cur="$1"
+while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do
+ AC_MSG_CHECKING(symlink for $_cur)
+ _slink=`ls -ld "$_cur" | sed 's/.* -> //'`
+ case "$_slink" in
+ /*) _cur="$_slink";;
+ # 'X' avoids triggering unwanted echo options.
+ *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";;
+ esac
+ AC_MSG_RESULT($_cur)
+done
+_ACJNI_FOLLOWED="$_cur"
+])# _ACJNI
+
diff --git a/bdb/dist/aclocal_java/ac_prog_jar.ac b/bdb/dist/aclocal_java/ac_prog_jar.ac
new file mode 100644
index 00000000000..9dfa1be6dad
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_jar.ac
@@ -0,0 +1,36 @@
+dnl @synopsis AC_PROG_JAR
+dnl
+dnl AC_PROG_JAR tests for an existing jar program. It uses the environment
+dnl variable JAR then tests in sequence various common jar programs.
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAR=yourcompiler before calling
+dnl AC_PROG_JAR
+dnl
+dnl - at the configure level, setenv JAR
+dnl
+dnl You can use the JAR variable in your Makefile.in, with @JAR@.
+dnl
+dnl Note: This macro depends on the autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download that whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl
+dnl The general documentation of those macros, as well as the sample
+dnl configure.in, is included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Egon Willighagen <egonw@sci.kun.nl>
+dnl @version $Id: ac_prog_jar.ac,v 1.1 2001/08/23 16:58:43 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAR],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test "x$JAVAPREFIX" = x; then
+ test "x$JAR" = x && AC_CHECK_PROGS(JAR, jar$EXEEXT)
+else
+ test "x$JAR" = x && AC_CHECK_PROGS(JAR, jar, $JAVAPREFIX)
+fi
+test "x$JAR" = x && AC_MSG_ERROR([no acceptable jar program found in \$PATH])
+AC_PROVIDE([$0])dnl
+])
diff --git a/bdb/dist/aclocal_java/ac_prog_java.ac b/bdb/dist/aclocal_java/ac_prog_java.ac
new file mode 100644
index 00000000000..8cb24445132
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_java.ac
@@ -0,0 +1,77 @@
+dnl @synopsis AC_PROG_JAVA
+dnl
+dnl Here is a summary of the main macros:
+dnl
+dnl AC_PROG_JAVAC: finds a Java compiler.
+dnl
+dnl AC_PROG_JAVA: finds a Java virtual machine.
+dnl
+dnl AC_CHECK_CLASS: finds if we have the given class (beware of CLASSPATH!).
+dnl
+dnl AC_CHECK_RQRD_CLASS: finds if we have the given class and stops otherwise.
+dnl
+dnl AC_TRY_COMPILE_JAVA: attempt to compile user given source.
+dnl
+dnl AC_TRY_RUN_JAVA: attempt to compile and run user given source.
+dnl
+dnl AC_JAVA_OPTIONS: adds Java configure options.
+dnl
+dnl AC_PROG_JAVA tests an existing Java virtual machine. It uses the
+dnl environment variable JAVA then tests in sequence various common Java
+dnl virtual machines. For political reasons, it starts with the free ones.
+dnl You *must* call [AC_PROG_JAVAC] before.
+dnl
+dnl If you want to force a specific VM:
+dnl
+dnl - at the configure.in level, set JAVA=yourvm before calling AC_PROG_JAVA
+dnl (but after AC_INIT)
+dnl
+dnl - at the configure level, setenv JAVA
+dnl
+dnl You can use the JAVA variable in your Makefile.in, with @JAVA@.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl TODO: allow to exclude virtual machines (rationale: most Java programs
+dnl cannot run with some VM like kaffe).
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl
+dnl A Web page, with a link to the latest CVS snapshot is at
+dnl <http://www.internatif.org/bortzmeyer/autoconf-Java/>.
+dnl
+dnl This is a sample configure.in
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl AC_INIT(UnTag.java)
+dnl
+dnl dnl Checks for programs.
+dnl AC_CHECK_CLASSPATH
+dnl AC_PROG_JAVAC
+dnl AC_PROG_JAVA
+dnl
+dnl dnl Checks for classes
+dnl AC_CHECK_RQRD_CLASS(org.xml.sax.Parser)
+dnl AC_CHECK_RQRD_CLASS(com.jclark.xml.sax.Driver)
+dnl
+dnl AC_OUTPUT(Makefile)
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_java.ac,v 1.1 2001/08/23 16:58:43 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVA],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test x$JAVAPREFIX = x; then
+ test x$JAVA = x && AC_CHECK_PROGS(JAVA, kaffe$EXEEXT java$EXEEXT)
+else
+ test x$JAVA = x && AC_CHECK_PROGS(JAVA, kaffe$EXEEXT java$EXEEXT, $JAVAPREFIX)
+fi
+test x$JAVA = x && AC_MSG_ERROR([no acceptable Java virtual machine found in \$PATH])
+AC_PROG_JAVA_WORKS
+AC_PROVIDE([$0])dnl
+])
diff --git a/bdb/dist/aclocal_java/ac_prog_java_works.ac b/bdb/dist/aclocal_java/ac_prog_java_works.ac
new file mode 100644
index 00000000000..36acd2676fa
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_java_works.ac
@@ -0,0 +1,97 @@
+dnl @synopsis AC_PROG_JAVA_WORKS
+dnl
+dnl Internal use ONLY.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_java_works.ac,v 1.1 2001/08/23 16:58:44 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVA_WORKS], [
+AC_CHECK_PROG(uudecode, uudecode$EXEEXT, yes)
+if test x$uudecode = xyes; then
+AC_CACHE_CHECK([if uudecode can decode base 64 file], ac_cv_prog_uudecode_base64, [
+dnl /**
+dnl * Test.java: used to test if java compiler works.
+dnl */
+dnl public class Test
+dnl {
+dnl
+dnl public static void
+dnl main( String[] argv )
+dnl {
+dnl System.exit (0);
+dnl }
+dnl
+dnl }
+cat << \EOF > Test.uue
+begin-base64 644 Test.class
+yv66vgADAC0AFQcAAgEABFRlc3QHAAQBABBqYXZhL2xhbmcvT2JqZWN0AQAE
+bWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51
+bWJlclRhYmxlDAAKAAsBAARleGl0AQAEKEkpVgoADQAJBwAOAQAQamF2YS9s
+YW5nL1N5c3RlbQEABjxpbml0PgEAAygpVgwADwAQCgADABEBAApTb3VyY2VG
+aWxlAQAJVGVzdC5qYXZhACEAAQADAAAAAAACAAkABQAGAAEABwAAACEAAQAB
+AAAABQO4AAyxAAAAAQAIAAAACgACAAAACgAEAAsAAQAPABAAAQAHAAAAIQAB
+AAEAAAAFKrcAErEAAAABAAgAAAAKAAIAAAAEAAQABAABABMAAAACABQ=
+====
+EOF
+if uudecode$EXEEXT Test.uue; then
+ ac_cv_prog_uudecode_base64=yes
+else
+ echo "configure: __oline__: uudecode had trouble decoding base 64 file 'Test.uue'" >&AC_FD_CC
+ echo "configure: failed file was:" >&AC_FD_CC
+ cat Test.uue >&AC_FD_CC
+ ac_cv_prog_uudecode_base64=no
+fi
+rm -f Test.uue])
+fi
+if test x$ac_cv_prog_uudecode_base64 != xyes; then
+ rm -f Test.class
+ AC_MSG_WARN([I have to compile Test.class from scratch])
+ if test x$ac_cv_prog_javac_works = xno; then
+ AC_MSG_ERROR([Cannot compile java source. $JAVAC does not work properly])
+ fi
+ if test x$ac_cv_prog_javac_works = x; then
+ AC_PROG_JAVAC
+ fi
+fi
+AC_CACHE_CHECK(if $JAVA works, ac_cv_prog_java_works, [
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+TEST=Test
+changequote(, )dnl
+cat << \EOF > $JAVA_TEST
+/* [#]line __oline__ "configure" */
+public class Test {
+public static void main (String args[]) {
+ System.exit (0);
+} }
+EOF
+changequote([, ])dnl
+if test x$ac_cv_prog_uudecode_base64 != xyes; then
+ if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) && test -s $CLASS_TEST; then
+ :
+ else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat $JAVA_TEST >&AC_FD_CC
+ AC_MSG_ERROR(The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?))
+ fi
+fi
+if AC_TRY_COMMAND($JAVA $JAVAFLAGS $TEST) >/dev/null 2>&1; then
+ ac_cv_prog_java_works=yes
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat $JAVA_TEST >&AC_FD_CC
+ AC_MSG_ERROR(The Java VM $JAVA failed (see config.log, check the CLASSPATH?))
+fi
+rm -fr $JAVA_TEST $CLASS_TEST Test.uue
+])
+AC_PROVIDE([$0])dnl
+]
+)
diff --git a/bdb/dist/aclocal_java/ac_prog_javac.ac b/bdb/dist/aclocal_java/ac_prog_javac.ac
new file mode 100644
index 00000000000..5ded7d1b7e6
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_javac.ac
@@ -0,0 +1,43 @@
+dnl @synopsis AC_PROG_JAVAC
+dnl
+dnl AC_PROG_JAVAC tests an existing Java compiler. It uses the environment
+dnl variable JAVAC then tests in sequence various common Java compilers. For
+dnl political reasons, it starts with the free ones.
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAVAC=yourcompiler before calling
+dnl AC_PROG_JAVAC
+dnl
+dnl - at the configure level, setenv JAVAC
+dnl
+dnl You can use the JAVAC variable in your Makefile.in, with @JAVAC@.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl TODO: allow to exclude compilers (rationale: most Java programs cannot compile
+dnl with some compilers like guavac).
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_javac.ac,v 1.3 2001/08/23 17:08:22 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVAC],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test "x$JAVAPREFIX" = x; then
+ test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT)
+else
+ test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT, $JAVAPREFIX)
+fi
+test "x$JAVAC" = x && AC_MSG_ERROR([no acceptable Java compiler found in \$PATH])
+AC_PROG_JAVAC_WORKS
+AC_PROVIDE([$0])dnl
+])
diff --git a/bdb/dist/aclocal_java/ac_prog_javac_works.ac b/bdb/dist/aclocal_java/ac_prog_javac_works.ac
new file mode 100644
index 00000000000..139a99f989b
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_javac_works.ac
@@ -0,0 +1,35 @@
+dnl @synopsis AC_PROG_JAVAC_WORKS
+dnl
+dnl Internal use ONLY.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_javac_works.ac,v 1.1 2001/08/23 16:58:44 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVAC_WORKS],[
+AC_CACHE_CHECK([if $JAVAC works], ac_cv_prog_javac_works, [
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+cat << \EOF > $JAVA_TEST
+/* [#]line __oline__ "configure" */
+public class Test {
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) >/dev/null 2>&1; then
+ ac_cv_prog_javac_works=yes
+else
+ AC_MSG_ERROR([The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)])
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat $JAVA_TEST >&AC_FD_CC
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+])
+AC_PROVIDE([$0])dnl
+])
diff --git a/bdb/dist/aclocal_java/ac_prog_javadoc.ac b/bdb/dist/aclocal_java/ac_prog_javadoc.ac
new file mode 100644
index 00000000000..5154d3f1f3b
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_javadoc.ac
@@ -0,0 +1,37 @@
+dnl @synopsis AC_PROG_JAVADOC
+dnl
+dnl AC_PROG_JAVADOC tests for an existing javadoc generator. It uses the environment
+dnl variable JAVADOC then tests in sequence various common javadoc generator.
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAVADOC=yourgenerator before calling
+dnl AC_PROG_JAVADOC
+dnl
+dnl - at the configure level, setenv JAVADOC
+dnl
+dnl You can use the JAVADOC variable in your Makefile.in, with @JAVADOC@.
+dnl
+dnl Note: This macro depends on the autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download that whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl
+dnl The general documentation of those macros, as well as the sample
+dnl configure.in, is included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Egon Willighagen <egonw@sci.kun.nl>
+dnl @version $Id: ac_prog_javadoc.ac,v 1.1 2001/08/23 16:58:44 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVADOC],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test "x$JAVAPREFIX" = x; then
+ test "x$JAVADOC" = x && AC_CHECK_PROGS(JAVADOC, javadoc$EXEEXT)
+else
+ test "x$JAVADOC" = x && AC_CHECK_PROGS(JAVADOC, javadoc, $JAVAPREFIX)
+fi
+test "x$JAVADOC" = x && AC_MSG_ERROR([no acceptable javadoc generator found in \$PATH])
+AC_PROVIDE([$0])dnl
+])
+
diff --git a/bdb/dist/aclocal_java/ac_prog_javah.ac b/bdb/dist/aclocal_java/ac_prog_javah.ac
new file mode 100644
index 00000000000..1b16d9e24e5
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_prog_javah.ac
@@ -0,0 +1,26 @@
+dnl @synopsis AC_PROG_JAVAH
+dnl
+dnl AC_PROG_JAVAH tests the availability of the javah header generator
+dnl and looks for the jni.h header file. If available, JAVAH is set to
+dnl the full path of javah and CPPFLAGS is updated accordingly.
+dnl
+dnl @author Luc Maisonobe
+dnl @version $Id: ac_prog_javah.ac,v 1.1 2001/08/23 16:58:44 dda Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVAH],[
+AC_REQUIRE([AC_CANONICAL_SYSTEM])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+AC_PATH_PROG(JAVAH,javah)
+if test x"`eval 'echo $ac_cv_path_JAVAH'`" != x ; then
+ AC_TRY_CPP([#include <jni.h>],,[
+ ac_save_CPPFLAGS="$CPPFLAGS"
+changequote(, )dnl
+ ac_dir=`echo $ac_cv_path_JAVAH | sed 's,\(.*\)/[^/]*/[^/]*$,\1/include,'`
+ ac_machdep=`echo $build_os | sed 's,[-0-9].*,,'`
+changequote([, ])dnl
+ CPPFLAGS="$ac_save_CPPFLAGS -I$ac_dir -I$ac_dir/$ac_machdep"
+ AC_TRY_CPP([#include <jni.h>],
+ ac_save_CPPFLAGS="$CPPFLAGS",
+ AC_MSG_WARN([unable to include <jni.h>]))
+ CPPFLAGS="$ac_save_CPPFLAGS"])
+fi])
diff --git a/bdb/dist/aclocal_java/ac_try_compile_java.ac b/bdb/dist/aclocal_java/ac_try_compile_java.ac
new file mode 100644
index 00000000000..775569ba054
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_try_compile_java.ac
@@ -0,0 +1,39 @@
+dnl @synopsis AC_TRY_COMPILE_JAVA
+dnl
+dnl AC_TRY_COMPILE_JAVA attempt to compile user given source.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Devin Weaver <ktohg@tritarget.com>
+dnl @version $Id: ac_try_compile_java.ac,v 1.1 2001/08/23 16:58:44 dda Exp $
+dnl
+AC_DEFUN([AC_TRY_COMPILE_JAVA],[
+AC_REQUIRE([AC_PROG_JAVAC])dnl
+cat << \EOF > Test.java
+/* [#]line __oline__ "configure" */
+ifelse([$1], , , [import $1;])
+public class Test {
+[$2]
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS Test.java) && test -s Test.class
+then
+dnl Don't remove the temporary files here, so they can be examined.
+ ifelse([$3], , :, [$3])
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat Test.java >&AC_FD_CC
+ifelse([$4], , , [ rm -fr Test*
+ $4
+])dnl
+fi
+rm -fr Test*])
diff --git a/bdb/dist/aclocal_java/ac_try_run_javac.ac b/bdb/dist/aclocal_java/ac_try_run_javac.ac
new file mode 100644
index 00000000000..cf91306aff6
--- /dev/null
+++ b/bdb/dist/aclocal_java/ac_try_run_javac.ac
@@ -0,0 +1,40 @@
+dnl @synopsis AC_TRY_RUN_JAVA
+dnl
+dnl AC_TRY_RUN_JAVA attempt to compile and run user given source.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Devin Weaver <ktohg@tritarget.com>
+dnl @version $Id: ac_try_run_javac.ac,v 1.1 2001/08/23 16:58:45 dda Exp $
+dnl
+AC_DEFUN([AC_TRY_RUN_JAVA],[
+AC_REQUIRE([AC_PROG_JAVAC])dnl
+AC_REQUIRE([AC_PROG_JAVA])dnl
+cat << \EOF > Test.java
+/* [#]line __oline__ "configure" */
+ifelse([$1], , , [include $1;])
+public class Test {
+[$2]
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS Test.java) && test -s Test.class && ($JAVA $JAVAFLAGS Test; exit) 2>/dev/null
+then
+dnl Don't remove the temporary files here, so they can be examined.
+ ifelse([$3], , :, [$3])
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat Test.java >&AC_FD_CC
+ifelse([$4], , , [ rm -fr Test*
+ $4
+])dnl
+fi
+rm -fr Test*])
diff --git a/bdb/dist/build/script b/bdb/dist/build/script
deleted file mode 100644
index 8eef3099f08..00000000000
--- a/bdb/dist/build/script
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/sh -
-# $Id: script,v 1.21 2001/01/19 18:13:16 bostic Exp $
-#
-# Build the distribution archives.
-#
-# A set of commands intended to be cut and pasted into a csh window.
-
-# Development tree, release home.
-setenv D /a/db
-
-# Update the release number.
-cd $D/dist
-vi RELEASE
-setenv VERSION \
-`sh -c '. RELEASE; echo $DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH'`
-echo "Version: $VERSION"
-
-# Make sure the source tree is up-to-date, generate new support files, and
-# commit anything that's changed.
-cd $D && cvs -q update
-cd $D/dist && sh s_all
-cd $D && cvs -q commit
-
-# Build the documentation.
-cd $D/docs_src && make clean
-cd $D/docs_src && make
-cd $D/docs_src && make && make check
-
-# Copy a development tree into a release tree.
-setenv R /a/db-$VERSION
-rm -rf $R && mkdir -p $R
-cd $D && tar cf - \
-`cvs -q status | sed -n -e "/Repository/s;.*/CVSROOT/db/;;" -e "s/,v//p"` | \
-(cd $R && tar xpf -)
-
-# Fix symbolic links and permissions.
-cd $R/dist && sh s_perm
-cd $R/dist && sh s_symlink
-
-# Build the documents.
-cd $R/docs_src && make
-
-# Build a version.
-cd $R && rm -rf build_run && mkdir build_run
-cd $R/build_run && ~bostic/bin/dbconf && make >& mklog
-
-# Smoke test.
-./ex_access
-
-# Check the install
-make prefix=`pwd`/BDB install
-
-# Run distribution check scripts
-$R/dist/build/chk.def
-$R/dist/build/chk.define
-$R/dist/build/chk.offt
-$R/dist/build/chk.srcfiles
-$R/dist/build/chk.tags
-
-# Clean up the tree.
-cd $R && rm -rf build_run docs_src
-cd $R && rm -rf test_thread test_purify test_server test_vxworks test/TODO
-cd $R && rm -rf test/upgrade/databases && mkdir test/upgrade/databases
-
-# ACQUIRE ROOT PRIVILEGES
-cd $R && find . -type d | xargs chmod 775
-cd $R && find . -type f | xargs chmod 444
-cd $R/dist && sh s_perm
-chown -R 100.100 $R
-# DISCARD ROOT PRIVILEGES
-
-# Compare this release with the last one.
-set LR=3.1.X
-cd $R/.. && gzcat /a/releases/db-${LR}.tar.gz | tar xf -
-cd $R/../db-${LR} && find . | sort > /tmp/__OLD
-cd $R && find . | sort > /tmp/__NEW
-diff -c /tmp/__OLD /tmp/__NEW
-
-# Create the tar archive release.
-setenv T "$R/../db-$VERSION.tar.gz"
-cd $R/.. && tar cf - db-$VERSION | gzip --best > $T
-chmod 444 $T
-
-# Create the zip archive release.
-#
-# Remove symbolic links to tags files. They're large and we don't want to
-# store real symbolic links in the archive for portability reasons.
-# ACQUIRE ROOT PRIVILEGES
-cd $R && rm -f `find . -type l -name 'tags'`
-# DISCARD ROOT PRIVILEGES
-
-setenv T "$R/../db-$VERSION.zip"
-cd $R/.. && zip -r - db-$VERSION > $T
-chmod 444 $T
diff --git a/bdb/dist/buildrel b/bdb/dist/buildrel
new file mode 100644
index 00000000000..b796169c719
--- /dev/null
+++ b/bdb/dist/buildrel
@@ -0,0 +1,109 @@
+#!/bin/sh -
+# $Id: buildrel,v 1.39 2002/09/06 14:30:31 bostic Exp $
+#
+# Build the distribution archives.
+#
+# A set of commands intended to be cut and pasted into a csh window.
+
+# Development tree, release home.
+setenv D `pwd`
+
+# Update the release number.
+cd $D/dist
+vi RELEASE
+setenv VERSION \
+`sh -c '. RELEASE; echo $DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH'`
+echo "Version: $VERSION"
+
+# Make sure the source tree is up-to-date, generate new support files, and
+# commit anything that's changed.
+cd $D && cvs -q update
+cd $D/dist && sh s_all
+cd $D && cvs -q commit
+
+# Copy a development tree into a release tree.
+setenv R /var/tmp/db-$VERSION
+rm -rf $R && mkdir -p $R
+cd $D && tar cf - \
+`cvs -q status | sed -n -e "/Repository/s;.*/CVSROOT/db/;;" -e "s/,v//p"` | \
+(cd $R && tar xpf -)
+
+# Fix symbolic links and permissions.
+cd $R/dist && sh s_perm
+cd $R/dist && sh s_symlink
+
+# Build a version.
+cd $R && rm -rf build_run && mkdir build_run
+cd $R/build_run && ~bostic/bin/dbconf && make >& mklog
+
+# Smoke test.
+cd $R/build_run && ./ex_access
+
+# Build the documentation.
+cd $R/docs_src && sh build clean
+cd $R/docs_src && sh build |& sed '/.html$/d'
+
+# Check the install
+cd $R/build_run && make prefix=`pwd`/BDB install
+
+# Clean up the tree.
+cd $R && rm -rf build_run docs_src
+cd $R && rm -rf test/TODO test/upgrade test_perf test_purify
+cd $R && rm -rf test_server test_thread test_vxworks test_xa
+
+# ACQUIRE ROOT PRIVILEGES
+cd $R && find . -type d | xargs chmod 775
+cd $R && find . -type f | xargs chmod 444
+cd $R && chmod 664 build_win32/*.dsp
+cd $R/dist && sh s_perm
+chown -R 100.100 $R
+# DISCARD ROOT PRIVILEGES
+
+# Compare this release with the last one.
+set LR=3.1.X
+cd $R/.. && gzcat /a/releases/db-${LR}.tar.gz | tar xf -
+cd $R/../db-${LR} && find . | sort > /tmp/__OLD
+cd $R && find . | sort > /tmp/__NEW
+diff -c /tmp/__OLD /tmp/__NEW
+
+# Create the crypto tar archive release.
+setenv T "$R/../db-$VERSION.tar.gz"
+cd $R/.. && tar cf - db-$VERSION | gzip --best > $T
+chmod 444 $T
+
+# Create the non-crypto tree.
+setenv RNC "$R/../db-$VERSION.NC"
+rm -rf $RNC $R/../__TMP && mkdir $R/../__TMP
+cd $R/../__TMP && gzcat $T | tar xpf - && mv -i db-$VERSION $RNC
+cd $R && rm -rf $R/../__TMP
+cd $RNC/dist && sh s_crypto
+
+# ACQUIRE ROOT PRIVILEGES
+cd $RNC && find . -type d | xargs chmod 775
+cd $RNC && find . -type f | xargs chmod 444
+cd $RNC && chmod 664 build_win32/*.dsp
+cd $RNC/dist && sh s_perm
+chown -R 100.100 $RNC
+# DISCARD ROOT PRIVILEGES
+
+# Create the non-crypto tar archive release.
+setenv T "$R/../db-$VERSION.NC.tar.gz"
+cd $RNC/.. && tar cf - db-$VERSION.NC | gzip --best > $T
+chmod 444 $T
+
+# Remove symbolic links to tags files. They're large and we don't want
+# to store real symbolic links in the zip archive for portability reasons.
+# ACQUIRE ROOT PRIVILEGES
+cd $R && rm -f `find . -type l -name 'tags'`
+cd $RNC && rm -f `find . -type l -name 'tags'`
+# DISCARD ROOT PRIVILEGES
+
+# Create the crypto zip archive release.
+setenv T "$R/../db-$VERSION.zip"
+cd $R/.. && zip -r - db-$VERSION > $T
+chmod 444 $T
+
+# Create the non-crypto zip archive release.
+setenv T "$R/../db-$VERSION.NC.zip"
+cd $RNC/.. && zip -r - db-$VERSION.NC > $T
+chmod 444 $T
diff --git a/bdb/dist/config.guess b/bdb/dist/config.guess
new file mode 100755
index 00000000000..fd30ab0314c
--- /dev/null
+++ b/bdb/dist/config.guess
@@ -0,0 +1,1354 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-07-23'
+
+# 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# This shell variable is my proudest work .. or something. --bje
+
+set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ;
+(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old)
+ || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ;
+dummy=$tmpdir/dummy ;
+files="$dummy.c $dummy.o $dummy.rel $dummy" ;
+trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ rm -f $files ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;
+unset files'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ eval $set_cc_for_build
+ cat <<EOF >$dummy.s
+ .data
+\$Lformat:
+ .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+
+ .text
+ .globl main
+ .align 4
+ .ent main
+main:
+ .frame \$30,16,\$26,0
+ ldgp \$29,0(\$27)
+ .prologue 1
+ .long 0x47e03d80 # implver \$0
+ lda \$2,-1
+ .long 0x47e20c21 # amask \$2,\$1
+ lda \$16,\$Lformat
+ mov \$0,\$17
+ not \$1,\$18
+ jsr \$26,printf
+ ldgp \$29,0(\$26)
+ mov 0,\$16
+ jsr \$26,exit
+ .end main
+EOF
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ case `$dummy` in
+ 0-0)
+ UNAME_MACHINE="alpha"
+ ;;
+ 1-0)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 1-1)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 1-101)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 2-303)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ 2-307)
+ UNAME_MACHINE="alphaev67"
+ ;;
+ 2-1307)
+ UNAME_MACHINE="alphaev68"
+ ;;
+ 3-1307)
+ UNAME_MACHINE="alphaev7"
+ ;;
+ esac
+ fi
+ rm -f $dummy.s $dummy && rmdir $tmpdir
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`$dummy`
+ if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ fi ;;
+ esac
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3D:*:*:*)
+ echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ rm -f $dummy.c && rmdir $tmpdir
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:3*)
+ echo i386-pc-interix3
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ rm -f $dummy.c && rmdir $tmpdir
+ test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ rm -f $dummy.c && rmdir $tmpdir
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ echo `uname -p`-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+rm -f $dummy.c $dummy && rmdir $tmpdir
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/bdb/dist/config.sub b/bdb/dist/config.sub
new file mode 100755
index 00000000000..9ff085efaf7
--- /dev/null
+++ b/bdb/dist/config.sub
@@ -0,0 +1,1460 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-07-03'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU 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.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c54x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipstx39 | mipstx39el \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3d)
+ basic_machine=alpha-cray
+ os=-unicos
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ windows32)
+ basic_machine=i386-pc
+ os=-windows32-msvcrt
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto*)
+ os=-nto-qnx
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/bdb/dist/configure.ac b/bdb/dist/configure.ac
new file mode 100644
index 00000000000..a61b8595322
--- /dev/null
+++ b/bdb/dist/configure.ac
@@ -0,0 +1,611 @@
+# $Id: configure.ac,v 11.156 2002/09/04 13:51:17 bostic Exp $
+# Process this file with autoconf to produce a configure script.
+
+PACKAGE=db
+AC_INIT(Berkeley DB,
+ __EDIT_DB_VERSION__, support@sleepycat.com, db-__EDIT_DB_VERSION__)
+AC_CONFIG_SRCDIR([../db/db.c])
+AC_CONFIG_HEADER(db_config.h:config.hin)
+
+# Configure setup.
+AC_CANONICAL_HOST()
+AC_ARG_PROGRAM()
+
+# We cannot build in the top-level directory.
+AC_MSG_CHECKING(if building in the top-level directory)
+[ test -d db_archive ] && AC_MSG_ERROR([
+Berkeley DB cannot be built in the top-level distribution directory.])
+AC_MSG_RESULT(no)
+
+# Minimum autoconf version required.
+AC_PREREQ(2.53)
+
+# Substitution variables.
+AC_SUBST(ADDITIONAL_INCS)
+AC_SUBST(ADDITIONAL_LANG)
+AC_SUBST(ADDITIONAL_OBJS)
+AC_SUBST(ADDITIONAL_PROGS)
+AC_SUBST(BUILD_TARGET)
+AC_SUBST(CFLAGS)
+AC_SUBST(CONFIGURATION_ARGS)
+AC_SUBST(CONFIGURATION_PATH)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(CXX)
+AC_SUBST(CXXFLAGS)
+AC_SUBST(DEFAULT_LIB)
+AC_SUBST(DEFAULT_LIB_CXX)
+AC_SUBST(EMBEDIX_ECD_CXX)
+AC_SUBST(EMBEDIX_ECD_RPC)
+AC_SUBST(EMBEDIX_ROOT)
+AC_SUBST(INSTALLER)
+AC_SUBST(INSTALL_LIBS)
+AC_SUBST(INSTALL_TARGET)
+AC_SUBST(JAR)
+AC_SUBST(JAVACFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(LIBJSO_LIBS)
+AC_SUBST(LIBS)
+AC_SUBST(LIBSO_LIBS)
+AC_SUBST(LIBTOOL)
+AC_SUBST(LIBTSO_LIBS)
+AC_SUBST(LIBXSO_LIBS)
+AC_SUBST(LOAD_LIBS)
+AC_SUBST(MAKEFILE_CC)
+AC_SUBST(MAKEFILE_CCLINK)
+AC_SUBST(MAKEFILE_CXX)
+AC_SUBST(MAKEFILE_CXXLINK)
+AC_SUBST(MAKEFILE_SOLINK)
+AC_SUBST(MAKEFILE_XSOLINK)
+AC_SUBST(POSTLINK)
+AC_SUBST(RPC_CLIENT_OBJS)
+AC_SUBST(RPM_POST_INSTALL)
+AC_SUBST(RPM_POST_UNINSTALL)
+AC_SUBST(SOFLAGS)
+AC_SUBST(db_cv_path_embedix_install)
+AC_SUBST(db_cv_path_rpm_archive)
+AC_SUBST(db_int_def)
+AC_SUBST(o)
+
+# RPM needs the current absolute path.
+# RPM needs the list of original arguments, but we don't include the RPM
+# option itself.
+CONFIGURATION_PATH=${PWD-`pwd`}
+CONFIGURATION_ARGS=`echo "$*" |
+ sed -e 's/--with-embedix[[^ ]]*//' -e 's/--with-rpm[[^ ]]*//'`
+
+# Set the version.
+AM_VERSION_SET
+
+# Set the default installation location.
+AC_PREFIX_DEFAULT(/usr/local/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@)
+
+# Process all options before using them.
+AM_OPTIONS_SET
+
+# Set some #defines based on configuration options.
+if test "$db_cv_diagnostic" = yes; then
+ AC_DEFINE(DIAGNOSTIC)
+ AH_TEMPLATE(DIAGNOSTIC,
+ [Define to 1 if you want a version with run-time diagnostic checking.])
+fi
+if test "$db_cv_debug_rop" = yes; then
+ AC_DEFINE(DEBUG_ROP)
+ AH_TEMPLATE(DEBUG_ROP,
+ [Define to 1 if you want a version that logs read operations.])
+fi
+if test "$db_cv_debug_wop" = yes; then
+ AC_DEFINE(DEBUG_WOP)
+ AH_TEMPLATE(DEBUG_WOP,
+ [Define to 1 if you want a version that logs write operations.])
+fi
+if test "$db_cv_umrw" = yes; then
+ AC_DEFINE(UMRW)
+ AH_TEMPLATE(UMRW,
+ [Define to 1 to mask harmless unitialized memory read/writes.])
+
+fi
+if test "$db_cv_test" = yes; then
+ AC_DEFINE(CONFIG_TEST)
+ AH_TEMPLATE(CONFIG_TEST,
+ [Define to 1 if you want to build a version for running the test suite.])
+fi
+
+# Check for programs used in building and installation.
+AM_PROGRAMS_SET
+AC_PROG_INSTALL
+
+# RPM/Embedix support: change the standard make and install targets
+if test "$db_cv_rpm" = "yes"; then
+ BUILD_TARGET="rpm_build"
+ echo "topdir: $CONFIGURATION_PATH" > rpmrc
+ if test "$db_cv_embedix" = "yes"; then
+ EMBEDIX_ROOT="/usr"
+ INSTALL_TARGET="embedix_install"
+ else
+ INSTALL_TARGET="rpm_install"
+ fi
+else
+ BUILD_TARGET="library_build"
+ INSTALL_TARGET="library_install"
+fi
+
+# This is where we handle stuff that autoconf can't handle: compiler,
+# preprocessor and load flags, libraries that the standard tests don't
+# look for. The default optimization is -O. We would like to set the
+# default optimization for systems using gcc to -O2, but we can't. By
+# the time we know we're using gcc, it's too late to set optimization
+# flags.
+#
+# There are additional libraries we need for some compiler/architecture
+# combinations.
+#
+# Some architectures require DB to be compiled with special flags and/or
+# libraries for threaded applications
+#
+# The makefile CC may be different than the CC used in config testing,
+# because the makefile CC may be set to use $(LIBTOOL).
+#
+# XXX
+# Don't override anything if it's already set from the environment.
+optimize_def="-O"
+case "$host_os" in
+aix4.3.*|aix5*)
+ optimize_def="-O2"
+ CC=${CC-"xlc_r"}
+ CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
+ LDFLAGS="$LDFLAGS -Wl,-brtl";;
+bsdi3*) optimize_def="-O2"
+ CC=${CC-"shlicc2"}
+ LIBS="$LIBS -lipc";;
+bsdi*) optimize_def="-O2";;
+freebsd*)
+ optimize_def="-O2"
+ CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
+ LDFLAGS="$LDFLAGS -pthread";;
+hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
+irix*) optimize_def="-O2"
+ CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";;
+linux*) optimize_def="-O2"
+ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
+mpeix*) CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE"
+ LIBS="$LIBS -lsocket -lsvipc";;
+osf*) CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+ LDFLAGS="$LDFLAGS -pthread";;
+*qnx) AC_DEFINE(HAVE_QNX)
+ AH_TEMPLATE(HAVE_QNX, [Define to 1 if building on QNX.]);;
+solaris*)
+ CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
+esac
+
+# Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf
+# compiler configuration macros, because if we don't, they set CFLAGS
+# to no optimization and -g, which isn't what we want.
+CFLAGS=${CFLAGS-$optimize_def}
+CXXFLAGS=${CXXFLAGS-"$CFLAGS"}
+
+# If the user wants a debugging environment, add -g to the CFLAGS value.
+#
+# XXX
+# Some compilers can't mix optimizing and debug flags. The only way to
+# handle this is to specify CFLAGS in the environment before configuring.
+if test "$db_cv_debug" = yes; then
+ AC_DEFINE(DEBUG)
+ AH_TEMPLATE(DEBUG, [Define to 1 if you want a debugging version.])
+
+ CFLAGS="$CFLAGS -g"
+ CXXFLAGS="$CXXFLAGS -g"
+fi
+
+# The default compiler is cc (NOT gcc), the default CFLAGS is as specified
+# above, NOT what is set by AC_PROG_CC, as it won't set optimization flags
+# for any compiler other than gcc.
+AC_PROG_CC(cc gcc)
+
+# Because of shared library building, the ${CC} used for config tests
+# may be different than the ${CC} we want to put in the Makefile.
+# The latter is known as ${MAKEFILE_CC} in this script.
+MAKEFILE_CC="${CC}"
+MAKEFILE_CCLINK="${CC}"
+MAKEFILE_CXX="nocxx"
+MAKEFILE_CXXLINK="nocxx"
+
+# See if we need the C++ compiler at all. If so, we'd like to find one that
+# interoperates with the C compiler we chose. Since we prefered cc over gcc,
+# we'll also prefer the vendor's compiler over g++/gcc. If we're wrong, the
+# user can set CC and CXX in their environment before running configure.
+#
+# AC_PROG_CXX sets CXX, but it uses $CXX and $CCC (in that order) as its
+# first choices.
+if test "$db_cv_cxx" = "yes"; then
+ if test "$GCC" != "yes"; then
+ case "$host_os" in
+ aix*) AC_CHECK_TOOL(CCC, xlC_r)
+ LIBXSO_LIBS="-lC_r $LIBXSO_LIBS"
+ LIBS="-lC_r $LIBS";;
+ hpux*) AC_CHECK_TOOL(CCC, aCC);;
+ irix*) AC_CHECK_TOOL(CCC, CC);;
+ osf*) AC_CHECK_TOOL(CCC, cxx);;
+ solaris*) AC_CHECK_TOOL(CCC, CC);;
+ esac
+ fi
+ AC_PROG_CXX
+ AC_CXX_HAVE_STDHEADERS
+ MAKEFILE_CXX="${CXX}"
+ MAKEFILE_CXXLINK="${CXX}"
+fi
+
+# Do some gcc specific configuration.
+AC_GCC_CONFIG1
+AC_GCC_CONFIG2
+
+# We need the -Kthread/-pthread flag when compiling on SCO/Caldera's UnixWare
+# and OpenUNIX releases. We can't make the test until we know which compiler
+# we're using.
+case "$host_os" in
+sysv5UnixWare*|sysv5OpenUNIX8*)
+ if test "$GCC" == "yes"; then
+ CPPFLAGS="$CPPFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ else
+ CPPFLAGS="$CPPFLAGS -Kthread"
+ LDFLAGS="$LDFLAGS -Kthread"
+ fi;;
+esac
+
+# Export our compiler preferences for the libtool configuration.
+export CC CCC
+CCC=CXX
+
+# Libtool configuration.
+AC_PROG_LIBTOOL
+
+LIBTOOL="\$(SHELL) ./libtool"
+SOFLAGS="-rpath \$(libdir)"
+
+# Set SOSUFFIX and friends
+SOSUFFIX_CONFIG
+MODSUFFIX_CONFIG
+JMODSUFFIX_CONFIG
+
+INSTALLER="\$(LIBTOOL) --mode=install cp -p"
+
+MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}"
+MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version"
+MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}"
+MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}"
+MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
+MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}"
+
+# Configure for shared libraries, static libraries, or both. If both are
+# configured, build the utilities and example programs with shared versions.
+#
+# $o is set to ".o" or ".lo", and is the file suffix used in the Makefile
+# instead of .o
+if test "$enable_shared" = "no"; then
+ DEFAULT_LIB="\$(libdb)"
+ POSTLINK="@true"
+ o=".o"
+fi
+if test "$enable_shared" = "yes"; then
+ DEFAULT_LIB="\$(libso_target)"
+ POSTLINK="\$(LIBTOOL) --mode=execute true"
+ o=".lo"
+fi
+INSTALL_LIBS="$DEFAULT_LIB"
+
+# Optional C++ API.
+if test "$db_cv_cxx" = "yes"; then
+ if test "$enable_shared" = "no"; then
+ DEFAULT_LIB_CXX="\$(libcxx)"
+ fi
+ if test "$enable_shared" = "yes"; then
+ DEFAULT_LIB_CXX="\$(libxso_target)"
+ fi
+ INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX"
+
+ # Fill in C++ library for Embedix.
+ EMBEDIX_ECD_CXX='<OPTION db-extra>\
+ TYPE=bool\
+ DEFAULT_VALUE=1\
+ PROMPT=Include BerkeleyDB C++ library?\
+ <KEEPLIST>\
+ /usr/include/db_cxx.h\
+ /usr/lib/libdb_cxx-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so\
+ </KEEPLIST>\
+ <PROVIDES>\
+ libdb_cxx-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so\
+ </PROVIDES>\
+ <REQUIRES>\
+ ld-linux.so.2\
+ libc.so.6\
+ </REQUIRES>\
+ STATIC_SIZE=0\
+ STORAGE_SIZE=523612\
+ STARTUP_TIME=0\
+ </OPTION>'
+fi
+
+# Optional Java API.
+if test "$db_cv_java" = "yes"; then
+ # Java requires shared libraries.
+ if test "$enable_shared" = "no"; then
+ AC_MSG_ERROR([Java requires shared libraries])
+ fi
+
+ AC_PROG_JAVAC
+ AC_PROG_JAR
+ AC_JNI_INCLUDE_DIR
+
+ for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
+ do
+ CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR"
+ done
+
+ ADDITIONAL_LANG="$ADDITIONAL_LANG java"
+ INSTALL_LIBS="$INSTALL_LIBS \$(libjso_target)"
+else
+ JAVAC=nojavac
+fi
+
+# Optional RPC client/server.
+if test "$db_cv_rpc" = "yes"; then
+ AC_DEFINE(HAVE_RPC)
+ AH_TEMPLATE(HAVE_RPC, [Define to 1 if building RPC client/server.])
+
+ RPC_CLIENT_OBJS="\$(RPC_CLIENT_OBJS)"
+ ADDITIONAL_PROGS="berkeley_db_svc $ADDITIONAL_PROGS"
+
+ EMBEDIX_ECD_RPC="/usr/bin/berkeley_db_svc"
+
+ case "$host_os" in
+ hpux*)
+ AC_CHECK_FUNC(svc_run,,
+ AC_CHECK_LIB(nsl, svc_run,
+ LIBS="-lnsl $LIBS"; LIBTSO_LIBS="-lnsl $LIBTSO_LIBS"));;
+ solaris*)
+ AC_CHECK_FUNC(svc_run,, AC_CHECK_LIB(nsl, svc_run));;
+ esac
+fi
+
+AM_TCL_LOAD
+
+# Optional crypto support.
+if test -d "$srcdir/../crypto"; then
+ AC_DEFINE(HAVE_CRYPTO)
+ AH_TEMPLATE(HAVE_CRYPTO,
+ [Define to 1 if Berkeley DB release includes strong cryptography.])
+ ADDITIONAL_OBJS="aes_method${o} crypto${o} mt19937db${o} rijndael-alg-fst${o} rijndael-api-fst${o} $ADDITIONAL_OBJS"
+fi
+
+# Optional DB 1.85 compatibility API.
+if test "$db_cv_compat185" = "yes"; then
+ ADDITIONAL_INCS="db_185.h $ADDITIONAL_INCS"
+ ADDITIONAL_OBJS="db185${o} $ADDITIONAL_OBJS"
+fi
+
+# Optional utilities.
+if test "$db_cv_dump185" = "yes"; then
+ ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS"
+fi
+
+# Checks for compiler characteristics.
+AC_C_CONST
+
+# Checks for include files, structures, C types.
+AC_HEADER_STAT
+AC_HEADER_TIME
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(sys/select.h sys/time.h)
+AC_CHECK_MEMBERS([struct stat.st_blksize])
+AM_TYPES
+
+AC_CACHE_CHECK([for ANSI C exit success/failure values], db_cv_exit_defines, [
+AC_TRY_COMPILE([#include <stdlib.h>], return (EXIT_SUCCESS);,
+ [db_cv_exit_defines=yes], [db_cv_exit_defines=no])])
+if test "$db_cv_exit_defines" = yes; then
+ AC_DEFINE(HAVE_EXIT_SUCCESS)
+ AH_TEMPLATE(HAVE_EXIT_SUCCESS,
+ [Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines.])
+fi
+
+# Test for various functions/libraries that the test and example programs use:
+# sched_yield function
+# pthreads, socket and math libraries
+AC_CHECK_FUNC(sched_yield,,
+ AC_SEARCH_LIBS(sched_yield, rt, LOAD_LIBS="$LOAD_LIBS -lrt"))
+
+# XXX
+# We can't check for pthreads in the same way we did the test for sched_yield
+# because the Solaris C library includes pthread interfaces which are not
+# thread-safe. For that reason we always add -lpthread if we find a pthread
+# library. Also we can't depend on any specific call existing (pthread_create,
+# for example), as it may be #defined in an include file -- OSF/1 (Tru64) has
+# this problem.
+AC_HAVE_LIBRARY(pthread, LOAD_LIBS="$LOAD_LIBS -lpthread")
+
+# XXX
+# We could be more exact about whether these libraries are needed, but we don't
+# bother -- if they exist, we load them.
+AC_HAVE_LIBRARY(m, LOAD_LIBS="$LOAD_LIBS -lm")
+AC_HAVE_LIBRARY(socket, LOAD_LIBS="$LOAD_LIBS -lsocket")
+AC_HAVE_LIBRARY(nsl, LOAD_LIBS="$LOAD_LIBS -lnsl")
+
+# Check for mutexes.
+# We do this here because it changes $LIBS.
+AM_DEFINE_MUTEXES
+
+# Checks for system functions for which we have replacements.
+#
+# XXX
+# The only portable getcwd call is getcwd(char *, size_t), where the
+# buffer is non-NULL -- Solaris can't handle a NULL buffer, and they
+# deleted getwd().
+AC_REPLACE_FUNCS(getcwd getopt memcmp memcpy memmove raise)
+AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror vsnprintf)
+
+# Check for system functions we optionally use.
+AC_CHECK_FUNCS(_fstati64 clock_gettime directio gettimeofday getuid)
+AC_CHECK_FUNCS(pstat_getdynamic sched_yield select strtoul sysconf yield)
+
+# Checks for system functions for which we don't have replacements.
+# We require qsort(3).
+AC_CHECK_FUNCS(qsort, , AC_MSG_ERROR([No qsort library function.]))
+
+# Pread/pwrite.
+# HP-UX has pread/pwrite, but it doesn't work with largefile support.
+case "$host_os" in
+hpux*)
+ AC_MSG_WARN([pread/pwrite interfaces ignored on $host_os.]);;
+*) AC_CHECK_FUNCS(pread pwrite)
+esac
+
+# Check for fcntl(2) to deny child process access to file descriptors.
+AC_CACHE_CHECK([for fcntl/F_SETFD], db_cv_fcntl_f_setfd, [
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <fcntl.h>], [
+ fcntl(1, F_SETFD, 1);
+], [db_cv_fcntl_f_setfd=yes], [db_cv_fcntl_f_setfd=no])])
+if test "$db_cv_fcntl_f_setfd" = yes; then
+ AC_DEFINE(HAVE_FCNTL_F_SETFD)
+ AH_TEMPLATE(HAVE_FCNTL_F_SETFD,
+ [Define to 1 if fcntl/F_SETFD denies child access to file descriptors.])
+fi
+
+# A/UX has a broken getopt(3).
+case "$host_os" in
+aux*) ADDITIONAL_OBJS="getopt${o} $ADDITIONAL_OBJS";;
+esac
+
+# Linux has the O_DIRECT flag, but you can't actually use it.
+AC_CACHE_CHECK([for open/O_DIRECT], db_cv_open_o_direct, [
+echo "test for working open/O_DIRECT" > __o_direct_file
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <fcntl.h>
+main() {
+int c, fd = open("__o_direct_file", O_RDONLY | O_DIRECT, 0);
+exit ((fd == -1) || (read(fd, &c, 1) != 1));
+}], [db_cv_open_o_direct=yes], [db_cv_open_o_direct=no],
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <fcntl.h>], [
+ open("__o_direct_file", O_RDONLY | O_DIRECT, 0);
+], [db_cv_open_o_direct=yes], [db_cv_open_o_direct=no]))
+rm -f __o_direct_file])
+if test "$db_cv_open_o_direct" = yes; then
+ AC_DEFINE(HAVE_O_DIRECT)
+ AH_TEMPLATE(HAVE_O_DIRECT, [Define to 1 if you have the O_DIRECT flag.])
+fi
+
+# Check for largefile support.
+AC_SYS_LARGEFILE
+
+# Figure out how to create shared regions.
+#
+# First, we look for mmap.
+#
+# BSD/OS has mlock(2), but it doesn't work until the 4.1 release.
+#
+# Nextstep (version 3.3) apparently supports mmap(2) (the mmap symbol
+# is defined in the C library) but does not support munmap(2). Don't
+# try to use mmap if we can't find munmap.
+#
+# Ultrix has mmap(2), but it doesn't work.
+mmap_ok=no
+case "$host_os" in
+bsdi3*|bsdi4.0)
+ AC_MSG_WARN([mlock(2) interface ignored on BSD/OS 3.X and 4.0.])
+ mmap_ok=yes
+ AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);;
+ultrix*)
+ AC_MSG_WARN([mmap(2) interface ignored on Ultrix.]);;
+*)
+ mmap_ok=yes
+ AC_CHECK_FUNCS(mlock munlock)
+ AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);;
+esac
+
+# Second, we look for shmget.
+#
+# SunOS has the shmget(2) interfaces, but there appears to be a missing
+# #include <debug/debug.h> file, so we ignore them.
+shmget_ok=no
+case "$host_os" in
+sunos*)
+ AC_MSG_WARN([shmget(2) interface ignored on SunOS.]);;
+*)
+ shmget_ok=yes
+ AC_CHECK_FUNCS(shmget, , shmget_ok=no);;
+esac
+
+# We require either mmap/munmap(2) or shmget(2).
+if test "$mmap_ok" = no -a "$shmget_ok" = no; then
+ AC_MSG_WARN([Neither mmap/munmap(2) or shmget(2) library functions.])
+fi
+
+# If we're not doing version name substitution, DB_VERSION_UNIQUE_NAME
+# needs to be erased.
+if test "$db_cv_uniquename" = "no"; then
+ DB_VERSION_UNIQUE_NAME=""
+fi
+
+# This is necessary so that .o files in LIBOBJS are also built via
+# the ANSI2KNR-filtering rules.
+LIB@&t@OBJS=`echo "$LIB@&t@OBJS" |
+ sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'`
+LTLIBOBJS=`echo "$LIB@&t@OBJS" |
+ sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
+AC_SUBST(LTLIBOBJS)
+
+# Initial output file list.
+CREATE_LIST="Makefile
+ db_cxx.h:$srcdir/../dbinc/db_cxx.in
+ db_int.h:$srcdir/../dbinc/db_int.in
+ include.tcl:$srcdir/../test/include.tcl"
+
+# Create the db.h file from a source file, a list of global function
+# prototypes, and, if configured for unique names, a list of #defines
+# to do DB_VERSION_UNIQUE_NAME substitution.
+if test "$db_cv_uniquename" = "yes"; then
+ CREATE_LIST="$CREATE_LIST
+ db.h:$srcdir/../dbinc/db.in:$srcdir/../dbinc_auto/rpc_defs.in:$srcdir/../dbinc_auto/ext_def.in:$srcdir/../dbinc_auto/ext_prot.in"
+else
+ CREATE_LIST="$CREATE_LIST
+ db.h:$srcdir/../dbinc/db.in:$srcdir/../dbinc_auto/rpc_defs.in:$srcdir/../dbinc_auto/ext_prot.in"
+fi
+
+# If configured for unique names, create the db_int_uext.h file (which
+# does the DB_VERSION_UNIQUE_NAME substitution), which is included by
+# the db_int.h file.
+if test "$db_cv_uniquename" = "yes"; then
+ CREATE_LIST="$CREATE_LIST
+ db_int_def.h:$srcdir/../dbinc_auto/int_def.in"
+ db_int_def='#include "db_int_def.h"'
+fi
+
+# Create the db_185.h and db185_int.h files from source files, a list of
+# global function prototypes, and, if configured for unique names, a list
+# of #defines to do DB_VERSION_UNIQUE_NAME substitution.
+if test "$db_cv_compat185" = "yes"; then
+ if test "$db_cv_uniquename" = "yes"; then
+ CREATE_LIST="$CREATE_LIST
+ db_185.h:$srcdir/../dbinc/db_185.in:$srcdir/../dbinc_auto/ext_185_def.in:$srcdir/../dbinc_auto/ext_185_prot.in
+ db185_int.h:$srcdir/../db185/db185_int.in:$srcdir/../dbinc_auto/ext_185_def.in:$srcdir/../dbinc_auto/ext_185_prot.in"
+ else
+ CREATE_LIST="$CREATE_LIST
+ db_185.h:$srcdir/../dbinc/db_185.in:$srcdir/../dbinc_auto/ext_185_prot.in
+ db185_int.h:$srcdir/../db185/db185_int.in:$srcdir/../dbinc_auto/ext_185_prot.in"
+ fi
+fi
+
+if test "$db_cv_embedix" = "yes"; then
+ CREATE_LIST="$CREATE_LIST db.ecd:../dist/db.ecd.in"
+fi
+
+if test "$db_cv_rpm" = "yes"; then
+ CREATE_LIST="$CREATE_LIST db.spec:../dist/db.spec.in"
+fi
+
+AC_CONFIG_FILES($CREATE_LIST)
+AC_OUTPUT
diff --git a/bdb/dist/configure.in b/bdb/dist/configure.in
deleted file mode 100644
index 08d60a6c07a..00000000000
--- a/bdb/dist/configure.in
+++ /dev/null
@@ -1,584 +0,0 @@
-dnl $Id: configure.in,v 11.77 2001/01/18 19:05:25 bostic Exp $
-dnl Process this file with autoconf to produce a configure script.
-
-AC_INIT(../db/db.c)
-AC_CONFIG_HEADER(db_config.h:config.hin)
-
-dnl Configure setup.
-AC_PROG_INSTALL()
-AC_CANONICAL_HOST
-AC_ARG_PROGRAM()
-
-dnl We cannot build in the top-level directory.
-AC_MSG_CHECKING(if building in the top-level directory)
-[ test -d db_archive ] && AC_MSG_ERROR([
-Berkeley DB cannot be built in the top-level distribution directory.])
-AC_MSG_RESULT(no)
-
-dnl Substitution variables.
-AC_SUBST(ADDITIONAL_INCS)
-AC_SUBST(ADDITIONAL_LANG)
-AC_SUBST(ADDITIONAL_LIBS)
-AC_SUBST(ADDITIONAL_OBJS)
-AC_SUBST(ADDITIONAL_PROGS)
-AC_SUBST(CPPFLAGS)
-AC_SUBST(CXXFLAGS)
-AC_SUBST(DBS_LIBS)
-AC_SUBST(DEFAULT_INSTALL)
-AC_SUBST(DEFAULT_LIB)
-AC_SUBST(INSTALLER)
-AC_SUBST(INSTALL_LIBS)
-AC_SUBST(JAR)
-AC_SUBST(JAVAC)
-AC_SUBST(JAVACFLAGS)
-AC_SUBST(LDFLAGS)
-AC_SUBST(LIBDB_ARGS)
-AC_SUBST(LIBJSO_LIBS)
-AC_SUBST(LIBS)
-AC_SUBST(LIBSO_LIBS)
-AC_SUBST(LIBTOOL)
-AC_SUBST(LIBTSO_LIBS)
-AC_SUBST(LIBXSO_LIBS)
-AC_SUBST(MAKEFILE_CC)
-AC_SUBST(MAKEFILE_CCLINK)
-AC_SUBST(MAKEFILE_CXX)
-AC_SUBST(POSTLINK)
-AC_SUBST(RPC_OBJS)
-AC_SUBST(SOFLAGS)
-AC_SUBST(SOLINK)
-AC_SUBST(SOSUFFIX)
-
-dnl $o is set to ".o" or ".lo", and is the file suffix used in the
-dnl Makefile instead of .o
-AC_SUBST(o)
-o=.o
-INSTALLER="\$(cp)"
-DEFAULT_LIB="\$(libdb)"
-DEFAULT_INSTALL="install_static"
-
-dnl Set the version.
-AM_VERSION_SET
-
-dnl Set the default installation location.
-AC_PREFIX_DEFAULT(/usr/local/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@)
-
-dnl Process all options before using them. This is necessary because there
-dnl are dependencies among them.
-AM_OPTIONS_SET
-
-# This is to determine what compiler is being used and to set options.
-# i.e. SCO OpenServer 5.0.X and UnixWare 7.X.X
-# option, cache_name, variable
-AC_DEFUN(AC_SYS_COMPILER_FLAG,
-[
- AC_MSG_CHECKING($1)
- OLD_CFLAGS="[$]CFLAGS"
- AC_CACHE_VAL(db_cv_option_$2,
- [
- CFLAGS="[$]OLD_CFLAGS $1"
- AC_TRY_RUN([int main(){exit(0);}],db_cv_option_$2=yes,db_cv_option_$2=no,db_cv_option_$2=no)
- ])
-
- CFLAGS="[$]OLD_CFLAGS"
-
- if test x"[$]db_cv_option_$2" = "xyes" ; then
- $3="[$]$3 $1"
- AC_MSG_RESULT(yes)
- $5
- else
- AC_MSG_RESULT(no)
- $4
- fi
-])
-
-
-# os, option, cache_name, variable
-AC_DEFUN(AC_SYS_OS_COMPILER_FLAG,
-[
- if test "x$db_cv_sys_os" = "x$1" ; then
- AC_SYS_COMPILER_FLAG($2,$3,$4)
- fi
-])
-
-dnl This is where we handle stuff that autoconf can't handle: compiler,
-dnl preprocessor and load flags, libraries that the standard tests don't
-dnl look for. The default optimization is -O. We would like to set the
-dnl default optimization for systems using gcc to -O2, but we can't. By
-dnl the time we know we're using gcc, it's too late to set optimization
-dnl flags.
-dnl
-dnl There are additional libraries we need for some compiler/architecture
-dnl combinations.
-dnl
-dnl Some architectures require DB to be compiled with special flags and/or
-dnl libraries for threaded applications
-dnl
-dnl The makefile CC may be different than the CC used in config testing,
-dnl because the makefile CC may be set to use $(LIBTOOL).
-dnl
-dnl XXX
-dnl Don't override anything if it's already set from the environment.
-optimize_def="-O"
-case "$host_os" in
-aix4.*) optimize_def="-O2"
- CC=${CC-"xlc_r"}
- CPPFLAGS="-D_THREAD_SAFE $CPPFLAGS"
- LIBTSO_LIBS="\$(LIBS)";;
-bsdi3*) CC=${CC-"shlicc2"}
- optimize_def="-O2"
- LIBS="-lipc $LIBS";;
-bsdi*) optimize_def="-O2";;
-freebsd*) optimize_def="-O2"
- CPPFLAGS="-D_THREAD_SAFE $CPPFLAGS"
- LIBS="-pthread";;
-hpux*) CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
-irix*) optimize_def="-O2"
- CPPFLAGS="-D_SGI_MP_SOURCE $CPPFLAGS";;
-linux*) optimize_def="-O2"
- CFLAGS="-D_GNU_SOURCE"
- CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
-mpeix*) CPPFLAGS="-D_POSIX_SOURCE -D_SOCKET_SOURCE $CPPFLAGS"
- LIBS="-lsocket -lsvipc $LIBS";;
-osf*) CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
-*qnx) AC_DEFINE(HAVE_QNX);;
-sco3.2v4*) CC=${CC-"cc -belf"}
- LIBS="-lsocket -lnsl_s $LIBS";;
-sco*) CC=${CC-"cc -belf"}
- LIBS="-lsocket -lnsl $LIBS";;
-solaris*) CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
-esac
-
-dnl Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf
-dnl compiler configuration macros, because if we don't, they set CFLAGS
-dnl to no optimization and -g, which isn't what we want.
-CFLAGS=${CFLAGS-$optimize_def}
-CXXFLAGS=${CXXFLAGS-"$CFLAGS"}
-
-dnl If the user wants a debugging environment, add -g to the CFLAGS value.
-dnl
-dnl XXX
-dnl Some compilers can't mix optimizing and debug flags. The only way to
-dnl handle this is to specify CFLAGS in the environment before configuring.
-if test "$db_cv_debug" = yes; then
- AC_DEFINE(DEBUG)
- CFLAGS="$CFLAGS -g"
- CXXFLAGS="$CXXFLAGS -g"
-fi
-
-dnl The default compiler is cc (NOT gcc), the default CFLAGS is as specified
-dnl above, NOT what is set by AC_PROG_CC, as it won't set optimization flags.
-dnl We still call AC_PROG_CC so that we get the other side-effects.
-AC_CHECK_PROG(CC, cc, cc)
-AC_CHECK_PROG(CC, gcc, gcc)
-AC_PROG_CC
-
-dnl Because of dynamic library building, the ${CC} used for config tests
-dnl may be different than the ${CC} we want to put in the Makefile.
-dnl The latter is known as ${MAKEFILE_CC} in this script.
-MAKEFILE_CC=${CC}
-MAKEFILE_CCLINK="\$(CC)"
-MAKEFILE_CXX="nocxx"
-
-dnl Set some #defines based on configuration options.
-if test "$db_cv_diagnostic" = yes; then
- AC_DEFINE(DIAGNOSTIC)
-fi
-if test "$db_cv_debug_rop" = yes; then
- AC_DEFINE(DEBUG_ROP)
-fi
-if test "$db_cv_debug_wop" = yes; then
- AC_DEFINE(DEBUG_WOP)
-fi
-if test "$db_cv_umrw" = yes; then
- AC_DEFINE(UMRW)
-fi
-if test "$db_cv_test" = yes; then
- AC_DEFINE(CONFIG_TEST)
-fi
-
-dnl See if we need the C++ compiler at all. If so, we'd like to find one that
-dnl interoperates with the C compiler we chose. Since we prefered cc over gcc,
-dnl we'll also prefer the vendor's compiler over g++/gcc. If we're wrong, the
-dnl user can set CC and CXX in their environment before running configure.
-dnl
-dnl AC_PROG_CXX sets CXX, but it uses $CXX and $CCC (in that order) as its
-dnl first choices.
-if test "$db_cv_cxx" = "yes"; then
- if test "$GCC" != "yes"; then
- case "$host_os" in
- aix*) AC_CHECK_PROG(CCC, xlC_r, xlC_r);;
- hpux*) AC_CHECK_PROG(CCC, aCC, aCC);;
- osf*) AC_CHECK_PROG(CCC, cxx, cxx);;
- solaris*) AC_CHECK_PROG(CCC, CC, CC);;
- esac
- fi
- AC_PROG_CXX
- MAKEFILE_CXX=${CXX}
-fi
-
-dnl XXX
-dnl Versions of GCC up to 2.8.0 required -fhandle-exceptions, but it is
-dnl renamed as -fexceptions and is the default in versions 2.8.0 and after.
-dnl
-dnl $GXX may be set as a result of enabling C++ or Java.
-if test "$GXX" = "yes"; then
- CXXVERSION=`${MAKEFILE_CXX} --version`
- case ${CXXVERSION} in
- 1.*|2.[[01234567]].*|*-1.*|*-2.[[01234567]].* )
- CXXFLAGS="-fhandle-exceptions $CXXFLAGS";;
- * ) CXXFLAGS="-fexceptions $CXXFLAGS";;
- esac
-fi
-
-dnl Give the OS a last chance to override CFLAGS and LDFLAGS
-
-case "$host_os" in
-sco3.2v5*)
- if test "$GCC" != "yes"; then
- CFLAGS="$CFLAGS"
- LD='$(CC) $(CFLAGS)'
- LIBS="-lsocket -lnsl $LIBS"
- CPPFLAGS="-D_THREAD_SAFE -pthread $CPPFLAGS"
- case "$CFLAGS" in
- *-belf*)
- AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
- case "$LDFLAGS" in
- *-belf*) ;;
- *) echo "Adding -belf option to ldflags."
- LDFLAGS="$LDFLAGS -belf"
- ;;
- esac
- ])
- ;;
- *)
- AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
- case "$LDFLAGS" in
- *-belf*) ;;
- *)
- echo "Adding -belf option to ldflags."
- LDFLAGS="$LDFLAGS -belf"
- ;;
- esac
- ])
- ;;
- esac
- else
- CC="gcc"
- LIBS="-lsocket -lnsl $LIBS"
- CPPFLAGS="-D_THREAD_SAFE -pthread $CPPFLAGS"
- fi ;;
-sysv5uw7*) LIBS="-lsocket -lnsl $LIBS"
- if test "$GCC" != "yes"; then
- # We are using built-in inline function
- CC="cc -belf"
- CXX="CC -belf -DNO_CPLUSPLUS_ALLOCA"
- CFLAGS="$CFLAGS -Kalloca -Kthread"
- LIBS="-Kthread -lsocket -lnsl $LIBS"
- else
- CFLAGS="$CFLAGS -Kalloca -pthread"
- CXX="$CXX -DNO_CPLUSPLUS_ALLOCA"
- CPPFLAGS="-D_THREAD_SAFE -pthread $CPPFLAGS"
- LIBS="-pthread -lsocket -lnsl $LIBS"
- fi
- ;;
-esac
-
-dnl Export our compiler preferences for the libtool configuration.
-export CC CCC
-CCC=CXX
-
-dnl Dynamic library and libtool configuration; optional, but required for
-dnl Tcl or Java support.
-LIBDB_ARGS="libdb.a"
-LIBTOOL="nolibtool"
-POSTLINK="@true"
-SOSUFFIX="so"
-if test "$db_cv_dynamic" = "yes"; then
- SAVE_CC="${MAKEFILE_CC}"
- SAVE_CXX="${MAKEFILE_CXX}"
-
- # Configure libtool.
- AC_MSG_CHECKING(libtool configuration)
- AC_MSG_RESULT([])
- ${CONFIG_SHELL-/bin/sh} $srcdir/ltconfig \
- --no-verify $srcdir/ltmain.sh \
- --output=./libtool $host_os \
- --disable-static \
- || AC_MSG_ERROR([libtool configure failed])
-
- SOSUFFIX=`sed -e '/^library_names_spec=/!d' -e 's/.*\.\([[a-zA-Z0-9_]]*\).*/\1/' ./libtool`
- DEFAULT_LIB="\$(libso_target)"
- DEFAULT_INSTALL="install_dynamic"
- LIBDB_ARGS="\$(libso_linkname)"
- LIBTOOL="\$(SHELL) ./libtool"
-
- MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${SAVE_CC}"
- MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${SAVE_CXX}"
- MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${SAVE_CC}"
-
- INSTALLER="\$(LIBTOOL) --mode=install cp"
- POSTLINK="\$(LIBTOOL) --mode=execute true"
- SOLINK="\$(LIBTOOL) --mode=link ${SAVE_CC} -avoid-version"
- SOFLAGS="-rpath \$(libdir)"
- o=".lo"
-fi
-
-dnl Optional C++ API.
-if test "$db_cv_cxx" = "yes"; then
- if test "$db_cv_dynamic" = "yes"; then
- ADDITIONAL_LIBS="$ADDITIONAL_LIBS \$(libxso_target)"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_dynamic_cxx"
- else
- ADDITIONAL_LIBS="$ADDITIONAL_LIBS \$(libcxx)"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_static_cxx"
- fi
-fi
-
-dnl Optional Java API.
-if test "$db_cv_java" = "yes"; then
- if test "$db_cv_dynamic" != "yes"; then
- AC_MSG_ERROR([--enable-java requires --enable-dynamic])
- fi
-
- AC_CHECK_PROG(JAVAC, javac, javac, nojavac)
- if test "$JAVAC" = "nojavac"; then
- AC_MSG_ERROR([no javac compiler in PATH])
- fi
- AC_CHECK_PROG(JAR, jar, jar, nojar)
- if test "$JAR" = "nojar"; then
- AC_MSG_ERROR([no jar utility in PATH])
- fi
- AC_PATH_PROG(JAVACABS, javac, nojavac)
- ADDITIONAL_LIBS="$ADDITIONAL_LIBS \$(libjso_target)"
- ADDITIONAL_LANG="$ADDITIONAL_LANG java"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_java"
-
-dnl find the include directory relative to the javac executable
- while ls -ld "$JAVACABS" 2>/dev/null | grep " -> " >/dev/null; do
- AC_MSG_CHECKING(symlink for $JAVACABS)
- JAVACLINK=`ls -ld $JAVACABS | sed 's/.* -> //'`
- case "$JAVACLINK" in
- /*) JAVACABS="$JAVACLINK";;
-dnl 'X' avoids triggering unwanted echo options.
- *) JAVACABS=`echo "X$JAVACABS" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$JAVACLINK";;
- esac
- AC_MSG_RESULT($JAVACABS)
- done
- JTOPDIR=`echo "$JAVACABS" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'`
- if test -f "$JTOPDIR/include/jni.h"; then
- CPPFLAGS="$CPPFLAGSS -I$JTOPDIR/include"
- else
- JTOPDIR=`echo "$JTOPDIR" | sed -e 's:/[[^/]]*$::'`
- if test -f "$JTOPDIR/include/jni.h"; then
- CPPFLAGS="$CPPFLAGS -I$JTOPDIR/include"
- else
- AC_MSG_ERROR([cannot find java include files])
- fi
- fi
-
-dnl get the likely subdirectories for system specific java includes
- case "$host_os" in
- solaris*) JINCSUBDIRS="solaris";;
- linux*) JINCSUBDIRS="linux genunix";;
- *) JINCSUBDIRS="genunix";;
- esac
-
- for JINCSUBDIR in $JINCSUBDIRS
- do
- if test -d "$JTOPDIR/include/$JINCSUBDIR"; then
- CPPFLAGS="$CPPFLAGS -I$JTOPDIR/include/$JINCSUBDIR"
- fi
- done
-else
- JAVAC=nojavac
-fi
-
-dnl Optional RPC client/server.
-if test "$db_cv_rpc" = "yes"; then
- AC_DEFINE(HAVE_RPC)
-
- RPC_OBJS="\$(RPC_OBJS)"
- ADDITIONAL_PROGS="berkeley_db_svc $ADDITIONAL_PROGS"
-
- case "$host_os" in
- hpux*)
- AC_CHECK_FUNC(svc_run,,
- AC_CHECK_LIB(nsl, svc_run,
- LIBS="-lnsl $LIBS"; LIBTSO_LIBS="-lnsl $LIBTSO_LIBS"));;
- solaris*)
- AC_CHECK_FUNC(svc_run,, AC_CHECK_LIB(nsl, svc_run));;
- esac
-fi
-
-AM_TCL_LOAD
-
-dnl Optional DB 1.85 compatibility API.
-if test "$db_cv_compat185" = "yes"; then
- ADDITIONAL_INCS="db_185.h $ADDITIONAL_INCS"
- ADDITIONAL_OBJS="db185${o} $ADDITIONAL_OBJS"
-fi
-
-dnl Optional utilities.
-if test "$db_cv_dump185" = "yes"; then
- ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS"
-fi
-
-dnl Test Server.
-dnl Include -lpthread if the library exists.
-SCOLIBS=$LIBS
-AC_CHECK_LIB(pthread, pthread_create, DBS_LIBS=-lpthread)
-case "$host_os" in
-sysv5uw7*) LIBS=$SCOLIBS;;
-sco3.2v5*) LIBS=$SCOLIBS;;
-esac
-
-dnl Checks for typedefs, structures, and system/compiler characteristics.
-AC_C_BIGENDIAN
-AC_C_CONST
-AC_HEADER_STAT
-AC_HEADER_TIME
-AC_STRUCT_ST_BLKSIZE
-AC_TYPE_MODE_T
-AC_TYPE_OFF_T
-AC_TYPE_PID_T
-AC_TYPE_SIZE_T
-
-dnl Define any short-hand types we're missing.
-AM_SHORTHAND_TYPES
-
-dnl Checks for header files.
-AC_HEADER_DIRENT
-AC_CHECK_HEADERS(sys/select.h)
-AC_CHECK_HEADERS(sys/time.h)
-
-dnl Check for mutexes. We do this here because it changes $LIBS.
-AM_DEFINE_MUTEXES
-
-dnl Checks for system functions for which we have replacements.
-dnl
-dnl XXX
-dnl The only portable getcwd call is getcwd(char *, size_t), where the
-dnl buffer is non-NULL -- Solaris can't handle a NULL buffer, and they
-dnl deleted getwd().
-AC_REPLACE_FUNCS(getcwd getopt memcmp memcpy memmove)
-AC_REPLACE_FUNCS(raise snprintf strcasecmp strerror vsnprintf)
-
-dnl Check for system functions we optionally use.
-AC_CHECK_FUNCS(getuid pstat_getdynamic sysconf sched_yield strtoul yield)
-
-dnl Pread/pwrite.
-dnl
-dnl HP-UX has pread/pwrite, but it doesn't work with bigfile support.
-case "$host_os" in
-hpux*)
- AC_MSG_WARN([pread/pwrite interfaces ignored on $host_os.]);;
-*) AC_CHECK_FUNCS(pread pwrite)
-esac
-
-dnl Check for fcntl(2) to deny child process access to file descriptors.
-AC_CACHE_CHECK([for fcntl/F_SETFD], db_cv_fcntl_f_setfd, [dnl
-AC_TRY_RUN([
-#include <sys/types.h>
-#include <fcntl.h>
-main(){exit(fcntl(1, F_SETFD, 1) == -1);}],
- [db_cv_fcntl_f_setfd=yes], [db_cv_fcntl_f_setfd=no])])
-if test "$db_cv_fcntl_f_setfd" = yes; then
- AC_DEFINE(HAVE_FCNTL_F_SETFD)
-fi
-
-dnl A/UX has a broken getopt(3).
-case "$host_os" in
-aux*) ADDITIONAL_OBJS="getopt${o} $ADDITIONAL_OBJS";;
-esac
-
-dnl Checks for system functions for which we don't have replacements.
-
-dnl We require qsort(3) and select(2).
-AC_CHECK_FUNCS(qsort, , AC_MSG_ERROR([No qsort library function.]))
-AC_CHECK_FUNCS(select, , AC_MSG_ERROR([No select library function.]))
-
-dnl Some versions of sprintf return a pointer to the first argument instead
-dnl of a character count. We assume that the return value of snprintf and
-dnl vsprintf etc. will be the same as sprintf, and check the easy one.
-AC_CACHE_CHECK([for int type sprintf return value], db_cv_sprintf_count, [dnl
-AC_TRY_RUN([main(){char buf[20]; exit(sprintf(buf, "XXX") != 3);}],
- [db_cv_sprintf_count=yes], [db_cv_sprintf_count=no])])
-if test "$db_cv_sprintf_count" = no; then
- AC_DEFINE(SPRINTF_RET_CHARPNT)
-fi
-
-dnl Vendors are doing 64-bit lseek in different ways.
-dnl AIX, HP/UX, Solaris and Linux all use _FILE_OFFSET_BITS
-dnl to specify a "big-file" environment.
-dnl
-dnl You can't build C++ with big-file support on HP-UX, the include files
-dnl are wrong. On Solaris 8, <fcntl.h> included with big-file support
-dnl is not compatible with C++.
-if test "$db_cv_bigfile" = no; then
- case "$host_os" in
- solaris2.8|hpux*)
- if test "$db_cv_cxx" = "yes"; then
- AC_MSG_WARN([Large file and C++ API support are incompatible on HP-UX])
- AC_MSG_WARN([and Solaris 8; large file support has been turned off.])
- else
- AC_DEFINE(HAVE_FILE_OFFSET_BITS)
- fi;;
- aix*|solaris*|linux*)
- AC_DEFINE(HAVE_FILE_OFFSET_BITS);;
- esac
-fi
-
-dnl Figure out how to create shared regions.
-dnl
-dnl First, we look for mmap.
-dnl
-dnl BSD/OS has mlock(2), but it doesn't work until the 4.1 release.
-dnl
-dnl Nextstep (version 3.3) apparently supports mmap(2) (the mmap symbol
-dnl is defined in the C library) but does not support munmap(2). Don't
-dnl try to use mmap if we can't find munmap.
-dnl
-dnl Ultrix has mmap(2), but it doesn't work.
-mmap_ok=no
-case "$host_os" in
-bsdi3*|bsdi4.0)
- AC_MSG_WARN([mlock(2) interface ignored on BSD/OS 3.X and 4.0.])
- mmap_ok=yes
- AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);;
-ultrix*)
- AC_MSG_WARN([mmap(2) interface ignored on Ultrix.]);;
-*)
- mmap_ok=yes
- AC_CHECK_FUNCS(mlock munlock)
- AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);;
-esac
-
-dnl Second, we look for shmget.
-dnl
-dnl SunOS has the shmget(2) interfaces, but there appears to be a missing
-dnl #include <debug/debug.h> file, so we ignore them.
-shmget_ok=no
-case "$host_os" in
-sunos*)
- AC_MSG_WARN([shmget(2) interface ignored on SunOS.]);;
-*)
- shmget_ok=yes
- AC_CHECK_FUNCS(shmget, , shmget_ok=no);;
-esac
-
-dnl We require either mmap/munmap(2) or shmget(2).
-if test "$mmap_ok" = no -a "$shmget_ok" = no; then
- AC_MSG_WARN([Neither mmap/munmap(2) or shmget(2) library functions.])
-fi
-
-dnl Check for programs used in building and installation.
-AM_PROGRAMS_SET
-
-CREATE_LIST="Makefile
- include.tcl:../test/include.tcl
- db.h:../include/db.src
- db_int.h:../include/db_int.src"
-if test "$db_cv_compat185" = "yes"; then
- CREATE_LIST="${CREATE_LIST} db_185.h:../include/db_185.h"
-fi
-AC_OUTPUT(${CREATE_LIST})
diff --git a/bdb/dist/db.ecd.in b/bdb/dist/db.ecd.in
new file mode 100644
index 00000000000..92a6a090716
--- /dev/null
+++ b/bdb/dist/db.ecd.in
@@ -0,0 +1,64 @@
+# Embedix Componenet Description (ECD) file for BerkeleyDB.
+#
+# $Id: db.ecd.in,v 11.1 2001/04/04 14:06:13 bostic Exp $
+
+<GROUP System>
+<GROUP Library>
+<COMPONENT BerkeleyDB>
+ SRPM=db
+ <SPECPATCH></SPECPATCH>
+ <HELP>
+ Berkeley DB is Sleepycat Software's programmatic database toolkit.
+ </HELP>
+
+ TYPE=bool
+ DEFAULT_VALUE=1
+ PROMPT=Include BerkeleyDB library?
+ <KEEPLIST>
+ /usr/lib/libdb-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so
+ /usr/include/db.h
+ /usr/lib/libdb.so
+ </KEEPLIST>
+ <PROVIDES>
+ libdb-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so
+ </PROVIDES>
+ <REQUIRES>
+ ld-linux.so.2
+ libc.so.6
+ </REQUIRES>
+ STATIC_SIZE=0
+ STARTUP_TIME=0
+
+ @EMBEDIX_ECD_CXX@
+
+ <OPTION db-extra>
+ TYPE=bool
+ DEFAULT_VALUE=1
+ PROMPT=Include BerkeleyDB Utilities?
+ <KEEPLIST>
+ /usr/bin/db_archive
+ /usr/bin/db_checkpoint
+ /usr/bin/db_deadlock
+ /usr/bin/db_dump
+ /usr/bin/db_load
+ /usr/bin/db_printlog
+ /usr/bin/db_recover
+ /usr/bin/db_stat
+ /usr/bin/db_upgrade
+ /usr/bin/db_verify
+ @EMBEDIX_ECD_RPC@
+ </KEEPLIST>
+ <REQUIRES>
+ libdb-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so
+ ld-linux.so.2
+ libc.so.6
+ libdl.so.2
+ libm.so.6
+ </REQUIRES>
+ STATIC_SIZE=0
+ STARTUP_TIME=0
+ </OPTION>
+
+</COMPONENT>
+</GROUP>
+</GROUP>
diff --git a/bdb/dist/db.spec.in b/bdb/dist/db.spec.in
new file mode 100644
index 00000000000..ef253bcfcf4
--- /dev/null
+++ b/bdb/dist/db.spec.in
@@ -0,0 +1,52 @@
+# Berkeley DB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+
+Summary: Sleepycat Berkeley DB database library
+Name: db
+Version: @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+Release: 1
+Copyright: Freely redistributable, see LICENSE for details.
+Source: http://www.sleepycat.com/update/@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/db-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@.tar.gz
+URL: http://www.sleepycat.com
+Group: System Environment/Libraries
+BuildRoot: @CONFIGURATION_PATH@/RPM_INSTALL
+
+%description
+Berkeley DB is a programmatic toolkit that provides fast, reliable,
+mission-critical, and scalable built-in database support for software
+ranging from embedded applications running on hand-held appliances to
+enterprise-scale servers.
+
+The Berkeley DB access methods include B+tree, Extended Linear Hashing,
+Fixed and Variable-length records, and Persistent Queues. Berkeley DB
+provides full transactional support, database recovery, online backups,
+and separate access to locking, logging and shared memory caching
+subsystems.
+
+Berkeley DB supports C, C++, Java, Tcl, Perl, and Python APIs. The
+software is available for Linux, a wide variety of UNIX platforms,
+Windows 95/98, Windows/NT, Windows 2000, VxWorks and QNX.
+
+%prep
+%setup
+
+%build
+cd build_unix
+CFLAGS="$RPM_OPT_FLAGS" ../dist/configure @CONFIGURATION_ARGS@
+make library_build
+
+%install
+cd build_unix
+make prefix=@CONFIGURATION_PATH@/RPM_INSTALL@EMBEDIX_ROOT@ install
+
+@RPM_POST_INSTALL@
+
+@RPM_POST_UNINSTALL@
+
+%files
+%defattr(-,root,root)
+%dir @EMBEDIX_ROOT@/bin
+%dir @EMBEDIX_ROOT@/docs
+%dir @EMBEDIX_ROOT@/include
+%dir @EMBEDIX_ROOT@/lib
+
+%changelog
diff --git a/bdb/dist/gen_inc.awk b/bdb/dist/gen_inc.awk
new file mode 100644
index 00000000000..4d245623bee
--- /dev/null
+++ b/bdb/dist/gen_inc.awk
@@ -0,0 +1,73 @@
+# This awk script parses C input files looking for lines marked "PUBLIC:"
+# and "EXTERN:". (PUBLIC lines are DB internal function prototypes and
+# #defines, EXTERN are DB external function prototypes and #defines.)
+#
+# PUBLIC lines are put into two versions of per-directory include files:
+# one file that contains the prototypes, and one file that contains a
+# #define for the name to be processed during configuration when creating
+# unique names for every global symbol in the DB library.
+#
+# The EXTERN lines are put into two files: one of which contains prototypes
+# which are always appended to the db.h file, and one of which contains a
+# #define list for use when creating unique symbol names.
+#
+# Four arguments:
+# e_dfile list of EXTERN #defines
+# e_pfile include file that contains EXTERN prototypes
+# i_dfile list of internal (PUBLIC) #defines
+# i_pfile include file that contains internal (PUBLIC) prototypes
+/PUBLIC:/ {
+ sub("^.*PUBLIC:[ ][ ]*", "")
+ if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
+ print $0 >> i_pfile
+ print $0 >> i_dfile
+ next
+ }
+ pline = sprintf("%s %s", pline, $0)
+ if (pline ~ "));") {
+ sub("^[ ]*", "", pline)
+ print pline >> i_pfile
+ if (pline !~ db_version_unique_name) {
+ def = gensub("[ ][ ]*__P.*", "", 1, pline)
+ sub("^.*[ ][*]*", "", def)
+ printf("#define %s %s@DB_VERSION_UNIQUE_NAME@\n",
+ def, def) >> i_dfile
+ }
+ pline = ""
+ }
+}
+
+# When we switched to methods in 4.0, we guessed txn_{abort,begin,commit}
+# were the interfaces applications would likely use and not be willing to
+# change, due to the sheer volume of the calls. Provide wrappers -- we
+# could do txn_abort and txn_commit using macros, but not txn_begin, as
+# the name of the field is txn_begin, we didn't want to modify it.
+#
+# The issue with txn_begin hits us in another way. If configured with the
+# --with-uniquename option, we use #defines to re-define DB's interfaces
+# to unique names. We can't do that for these functions because txn_begin
+# is also a field name in the DB_ENV structure, and the #defines we use go
+# at the end of the db.h file -- we get control too late to #define a field
+# name. So, modify the script that generates the unique names #defines to
+# not generate them for these three functions, and don't include the three
+# functions in libraries built with that configuration option.
+/EXTERN:/ {
+ sub("^.*EXTERN:[ ][ ]*", "")
+ if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
+ print $0 >> e_pfile
+ print $0 >> e_dfile
+ next
+ }
+ eline = sprintf("%s %s", eline, $0)
+ if (eline ~ "));") {
+ sub("^[ ]*", "", eline)
+ print eline >> e_pfile
+ if (eline !~ db_version_unique_name && eline !~ "^int txn_") {
+ def = gensub("[ ][ ]*__P.*", "", 1, eline)
+ sub("^.*[ ][*]*", "", def)
+ printf("#define %s %s@DB_VERSION_UNIQUE_NAME@\n",
+ def, def) >> e_dfile
+ }
+ eline = ""
+ }
+}
diff --git a/bdb/dist/gen_rec.awk b/bdb/dist/gen_rec.awk
index 5953ee05120..75f2e86ca9e 100644
--- a/bdb/dist/gen_rec.awk
+++ b/bdb/dist/gen_rec.awk
@@ -2,10 +2,10 @@
#
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: gen_rec.awk,v 11.26 2001/01/08 21:06:46 bostic Exp $
+# $Id: gen_rec.awk,v 11.70 2002/08/08 15:44:47 bostic Exp $
#
# This awk script generates all the log, print, and read routines for the DB
@@ -21,33 +21,51 @@
# (logical types are defined in each subsystem manually)
# structures to contain the data unmarshalled from the log.
#
-# This awk script requires that five variables be set when it is called:
+# This awk script requires that four variables be set when it is called:
#
# source_file -- the C source file being created
-# subsystem -- the subsystem prefix, e.g., "db"
# header_file -- the C #include file being created
# template_file -- the template file being created
-# template_dir -- the directory to find the source template
#
# And stdin must be the input file that defines the recovery setup.
+#
+# Within each file prefix.src, we use a number of public keywords (documented
+# in the reference guide) as well as the following ones which are private to
+# DB:
+# DBPRIVATE Indicates that a file will be built as part of DB,
+# rather than compiled independently, and so can use
+# DB-private interfaces (such as DB_NOCOPY).
+# DB A DB handle. Logs the dbreg fileid for that handle,
+# and makes the *_log interface take a DB * instead of a
+# DB_ENV *.
+# PGDBT Just like DBT, only we know it stores a page or page
+# header, so we can byte-swap it (once we write the
+# byte-swapping code, which doesn't exist yet).
+# WRLOCK
+# WRLOCKNZ An ARG that stores a db_pgno_t, which the getpgnos
+# function should acquire a lock on. WRLOCK implies
+# that we should always get the lock; WRLOCKNZ implies
+# that we should do so if and only if the pgno is non-zero
+# (unfortunately, 0 is both PGNO_INVALID and the main
+# metadata page number).
BEGIN {
- if (source_file == "" || subsystem == "" ||
- header_file == "" || template_file == "" || template_dir == "") {
- print "Usage: gen_rec.awk requires five variables to be set:"
+ if (source_file == "" ||
+ header_file == "" || template_file == "") {
+ print "Usage: gen_rec.awk requires three variables to be set:"
print "\tsource_file\t-- the C source file being created"
- print "\tsubsystem\t-- the subsystem prefix, e.g., \"db\""
print "\theader_file\t-- the C #include file being created"
print "\ttemplate_file\t-- the template file being created"
- print "\ttemplate_dir\t-- the directory to find the source template"
exit
}
FS="[\t ][\t ]*"
CFILE=source_file
- NAME=subsystem
HFILE=header_file
TFILE=template_file
- TDIR=template_dir
+ dbprivate = 0
+}
+/^[ ]*DBPRIVATE/ {
+ dbprivate = 1
}
/^[ ]*PREFIX/ {
prefix = $2
@@ -71,9 +89,9 @@ BEGIN {
printf("#include <string.h>\n") >> TFILE
printf("#endif\n\n") >> TFILE
printf("#include \"db_int.h\"\n") >> TFILE
- printf("#include \"db_page.h\"\n") >> TFILE
- printf("#include \"%s.h\"\n", prefix) >> TFILE
- printf("#include \"log.h\"\n\n") >> TFILE
+ printf("#include \"dbinc/db_page.h\"\n") >> TFILE
+ printf("#include \"dbinc/%s.h\"\n", prefix) >> TFILE
+ printf("#include \"dbinc/log.h\"\n\n") >> TFILE
}
/^[ ]*INCLUDE/ {
if ($3 == "")
@@ -81,26 +99,30 @@ BEGIN {
else
printf("%s %s\n", $2, $3) >> CFILE
}
-/^[ ]*(BEGIN|DEPRECATED)/ {
+/^[ ]*(BEGIN|IGNORED)/ {
if (in_begin) {
print "Invalid format: missing END statement"
exit
}
in_begin = 1;
is_dbt = 0;
- is_deprecated = ($1 == "DEPRECATED");
+ has_dbp = 0;
+ is_uint = 0;
+ need_log_function = ($1 == "BEGIN");
nvars = 0;
+ # number of locks that the getpgnos functions will return
+ nlocks = 0;
+
thisfunc = $2;
funcname = sprintf("%s_%s", prefix, $2);
rectype = $3;
funcs[num_funcs] = funcname;
- funcs_dep[num_funcs] = is_deprecated;
++num_funcs;
}
-/^[ ]*(ARG|DBT|POINTER)/ {
+/^[ ]*(DB|ARG|DBT|PGDBT|POINTER|WRLOCK|WRLOCKNZ)/ {
vars[nvars] = $2;
types[nvars] = $3;
atypes[nvars] = $1;
@@ -109,11 +131,16 @@ BEGIN {
for (i = 4; i < NF; i++)
types[nvars] = sprintf("%s %s", types[nvars], $i);
- if ($1 == "ARG")
- sizes[nvars] = sprintf("sizeof(%s)", $2);
- else if ($1 == "POINTER")
+ if ($1 == "DB") {
+ has_dbp = 1;
+ }
+
+ if ($1 == "DB" || $1 == "ARG" || $1 == "WRLOCK" || $1 == "WRLOCKNZ") {
+ sizes[nvars] = sprintf("sizeof(u_int32_t)");
+ is_uint = 1;
+ } else if ($1 == "POINTER")
sizes[nvars] = sprintf("sizeof(*%s)", $2);
- else { # DBT
+ else { # DBT, PGDBT
sizes[nvars] = \
sprintf("sizeof(u_int32_t) + (%s == NULL ? 0 : %s->size)", \
$2, $2);
@@ -121,6 +148,17 @@ BEGIN {
}
nvars++;
}
+/^[ ]*(WRLOCK|WRLOCKNZ)/ {
+ nlocks++;
+
+ if ($1 == "WRLOCK") {
+ lock_if_zero[nlocks] = 1;
+ } else {
+ lock_if_zero[nlocks] = 0;
+ }
+
+ lock_pgnos[nlocks] = $2;
+}
/^[ ]*END/ {
if (!in_begin) {
print "Invalid format: missing BEGIN statement"
@@ -128,7 +166,7 @@ BEGIN {
}
# Declare the record type.
- printf("\n#define\tDB_%s\t%d\n", funcname, rectype) >> HFILE
+ printf("#define\tDB_%s\t%d\n", funcname, rectype) >> HFILE
# Structure declaration.
printf("typedef struct _%s_args {\n", funcname) >> HFILE
@@ -146,17 +184,26 @@ BEGIN {
}
printf("\t%s\t%s;\n", t, vars[i]) >> HFILE
}
- printf("} __%s_args;\n\n", funcname) >> HFILE
+ printf("} %s_args;\n\n", funcname) >> HFILE
- # Output the log, print and read functions.
- if (!is_deprecated)
+ # Output the log, print, read, and getpgnos functions.
+ if (need_log_function) {
log_function();
+
+ # The getpgnos function calls DB-private (__rep_*) functions,
+ # so we only generate it for our own logging functions,
+ # not application-specific ones.
+ if (dbprivate) {
+ getpgnos_function();
+ }
+ }
print_function();
read_function();
# Recovery template
- cmd = sprintf("sed -e s/PREF/%s/ -e s/FUNC/%s/ < %s/rec_ctemp >> %s",
- prefix, thisfunc, TDIR, TFILE)
+ cmd = sprintf(\
+ "sed -e s/PREF/%s/ -e s/FUNC/%s/ < template/rec_ctemp >> %s",
+ prefix, thisfunc, TFILE)
system(cmd);
# Done writing stuff, reset and continue.
@@ -164,63 +211,141 @@ BEGIN {
}
END {
+ # End the conditional for the HFILE
+ printf("#endif\n") >> HFILE;
+
# Print initialization routine; function prototype
- printf("int __%s_init_print __P((DB_ENV *));\n", prefix) >> HFILE;
+ p[1] = sprintf("int %s_init_print %s%s", prefix,
+ "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ",
+ "db_recops, void *), size_t *));");
+ p[2] = "";
+ proto_format(p);
+
+ # Create the routine to call __db_add_recovery(print_fn, id)
+ printf("int\n%s_init_print(dbenv, dtabp, dtabsizep)\n", \
+ prefix) >> CFILE;
+ printf("\tDB_ENV *dbenv;\n") >> CFILE;;
+ printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> CFILE;
+ printf(" db_recops, void *));\n") >> CFILE;
+ printf("\tsize_t *dtabsizep;\n{\n") >> CFILE;
+ # If application-specific, the user will need a prototype for
+ # __db_add_recovery, since they won't have DB's.
+ if (!dbprivate) {
+ printf("\tint __db_add_recovery __P((DB_ENV *,\n") >> CFILE;
+ printf(\
+"\t int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),\n") >> CFILE;
+ printf("\t size_t *,\n") >> CFILE;
+ printf(\
+"\t int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t));\n") \
+ >> CFILE;
+ }
- # Create the routine to call db_add_recovery(print_fn, id)
- printf("int\n__%s_init_print(dbenv)\n", prefix) >> CFILE;
- printf("\tDB_ENV *dbenv;\n{\n\tint ret;\n\n") >> CFILE;
+ printf("\tint ret;\n\n") >> CFILE;
for (i = 0; i < num_funcs; i++) {
- printf("\tif ((ret = __db_add_recovery(dbenv,\n") >> CFILE;
- printf("\t __%s_print, DB_%s)) != 0)\n", \
+ printf("\tif ((ret = __db_add_recovery(dbenv, ") >> CFILE;
+ printf("dtabp, dtabsizep,\n") >> CFILE;
+ printf("\t %s_print, DB_%s)) != 0)\n", \
funcs[i], funcs[i]) >> CFILE;
printf("\t\treturn (ret);\n") >> CFILE;
}
printf("\treturn (0);\n}\n\n") >> CFILE;
- # Recover initialization routine
- printf("int __%s_init_recover __P((DB_ENV *));\n", prefix) >> HFILE;
+ # We only want to generate *_init_{getpgnos,recover} functions
+ # if this is a DB-private, rather than application-specific,
+ # set of recovery functions. Application-specific recovery functions
+ # should be dispatched using the DB_ENV->set_app_dispatch callback
+ # rather than a DB dispatch table ("dtab").
+ if (!dbprivate)
+ exit
- # Create the routine to call db_add_recovery(func, id)
- printf("int\n__%s_init_recover(dbenv)\n", prefix) >> CFILE;
- printf("\tDB_ENV *dbenv;\n{\n\tint ret;\n\n") >> CFILE;
+ # Page number initialization routine; function prototype
+ p[1] = sprintf("int %s_init_getpgnos %s%s", prefix,
+ "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ",
+ "db_recops, void *), size_t *));");
+ p[2] = "";
+ proto_format(p);
+
+ # Create the routine to call db_add_recovery(pgno_fn, id)
+ printf("int\n%s_init_getpgnos(dbenv, dtabp, dtabsizep)\n", \
+ prefix) >> CFILE;
+ printf("\tDB_ENV *dbenv;\n") >> CFILE;
+ printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> CFILE;
+ printf(" db_recops, void *));\n") >> CFILE;
+ printf("\tsize_t *dtabsizep;\n{\n\tint ret;\n\n") >> CFILE;
for (i = 0; i < num_funcs; i++) {
- printf("\tif ((ret = __db_add_recovery(dbenv,\n") >> CFILE;
- if (funcs_dep[i] == 1)
- printf("\t __deprecated_recover, DB_%s)) != 0)\n", \
- funcs[i]) >> CFILE;
- else
- printf("\t __%s_recover, DB_%s)) != 0)\n", \
- funcs[i], funcs[i]) >> CFILE;
+ printf("\tif ((ret = __db_add_recovery(dbenv, ") >> CFILE;
+ printf("dtabp, dtabsizep,\n") >> CFILE;
+ printf("\t %s_getpgnos, DB_%s)) != 0)\n", \
+ funcs[i], funcs[i]) >> CFILE;
printf("\t\treturn (ret);\n") >> CFILE;
}
printf("\treturn (0);\n}\n\n") >> CFILE;
- # End the conditional for the HFILE
- printf("#endif\n") >> HFILE;
+ # Recover initialization routine
+ p[1] = sprintf("int %s_init_recover %s%s", prefix,
+ "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ",
+ "db_recops, void *), size_t *));");
+ p[2] = "";
+ proto_format(p);
+
+ # Create the routine to call db_add_recovery(func, id)
+ printf("int\n%s_init_recover(dbenv, dtabp, dtabsizep)\n", \
+ prefix) >> CFILE;
+ printf("\tDB_ENV *dbenv;\n") >> CFILE;
+ printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> CFILE;
+ printf(" db_recops, void *));\n") >> CFILE;
+ printf("\tsize_t *dtabsizep;\n{\n\tint ret;\n\n") >> CFILE;
+ for (i = 0; i < num_funcs; i++) {
+ printf("\tif ((ret = __db_add_recovery(dbenv, ") >> CFILE;
+ printf("dtabp, dtabsizep,\n") >> CFILE;
+ printf("\t %s_recover, DB_%s)) != 0)\n", \
+ funcs[i], funcs[i]) >> CFILE;
+ printf("\t\treturn (ret);\n") >> CFILE;
+ }
+ printf("\treturn (0);\n}\n") >> CFILE;
}
function log_function() {
# Write the log function; function prototype
- printf("int __%s_log __P((", funcname) >> HFILE;
- printf("DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t") >> HFILE;
+ pi = 1;
+ p[pi++] = sprintf("int %s_log", funcname);
+ p[pi++] = " ";
+ if (has_dbp == 1) {
+ p[pi++] = "__P((DB *, DB_TXN *, DB_LSN *, u_int32_t";
+ } else {
+ p[pi++] = "__P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t";
+ }
for (i = 0; i < nvars; i++) {
- printf(", ") >> HFILE;
- if (modes[i] == "DBT")
- printf("const ") >> HFILE;
- printf("%s", types[i]) >> HFILE;
- if (modes[i] == "DBT")
- printf(" *") >> HFILE;
+ if (modes[i] == "DB")
+ continue;
+ p[pi++] = ", ";
+ p[pi++] = sprintf("%s%s%s",
+ (modes[i] == "DBT" || modes[i] == "PGDBT") ? "const " : "",
+ types[i],
+ (modes[i] == "DBT" || modes[i] == "PGDBT") ? " *" : "");
}
- printf("));\n") >> HFILE;
+ p[pi++] = "";
+ p[pi++] = "));";
+ p[pi++] = "";
+ proto_format(p);
# Function declaration
- printf("int\n__%s_log(dbenv, txnid, ret_lsnp, flags", \
- funcname) >> CFILE;
+ if (has_dbp == 1) {
+ printf("int\n%s_log(dbp, txnid, ret_lsnp, flags", \
+ funcname) >> CFILE;
+ } else {
+ printf("int\n%s_log(dbenv, txnid, ret_lsnp, flags", \
+ funcname) >> CFILE;
+ }
for (i = 0; i < nvars; i++) {
+ if (modes[i] == "DB") {
+ # We pass in fileids on the dbp, so if this is one,
+ # skip it.
+ continue;
+ }
printf(",") >> CFILE;
if ((i % 6) == 0)
- printf("\n\t") >> CFILE;
+ printf("\n ") >> CFILE;
else
printf(" ") >> CFILE;
printf("%s", vars[i]) >> CFILE;
@@ -228,65 +353,95 @@ function log_function() {
printf(")\n") >> CFILE;
# Now print the parameters
- printf("\tDB_ENV *dbenv;\n") >> CFILE;
+ if (has_dbp == 1) {
+ printf("\tDB *dbp;\n") >> CFILE;
+ } else {
+ printf("\tDB_ENV *dbenv;\n") >> CFILE;
+ }
printf("\tDB_TXN *txnid;\n\tDB_LSN *ret_lsnp;\n") >> CFILE;
printf("\tu_int32_t flags;\n") >> CFILE;
for (i = 0; i < nvars; i++) {
- if (modes[i] == "DBT")
+ # We just skip for modes == DB.
+ if (modes[i] == "DBT" || modes[i] == "PGDBT")
printf("\tconst %s *%s;\n", types[i], vars[i]) >> CFILE;
- else
+ else if (modes[i] != "DB")
printf("\t%s %s;\n", types[i], vars[i]) >> CFILE;
}
# Function body and local decls
printf("{\n") >> CFILE;
printf("\tDBT logrec;\n") >> CFILE;
+ if (has_dbp == 1)
+ printf("\tDB_ENV *dbenv;\n") >> CFILE;
printf("\tDB_LSN *lsnp, null_lsn;\n") >> CFILE;
if (is_dbt == 1)
printf("\tu_int32_t zero;\n") >> CFILE;
- printf("\tu_int32_t rectype, txn_num;\n") >> CFILE;
+ if (is_uint == 1)
+ printf("\tu_int32_t uinttmp;\n") >> CFILE;
+ printf("\tu_int32_t npad, rectype, txn_num;\n") >> CFILE;
printf("\tint ret;\n") >> CFILE;
printf("\tu_int8_t *bp;\n\n") >> CFILE;
# Initialization
+ if (has_dbp == 1)
+ printf("\tdbenv = dbp->dbenv;\n") >> CFILE;
printf("\trectype = DB_%s;\n", funcname) >> CFILE;
- printf("\tif (txnid != NULL &&\n") >> CFILE;
- printf("\t TAILQ_FIRST(&txnid->kids) != NULL &&\n") >> CFILE;
- printf("\t (ret = __txn_activekids(dbenv, rectype, txnid)) != 0)\n")\
- >> CFILE;
- printf("\t\treturn (ret);\n") >> CFILE;
- printf("\ttxn_num = txnid == NULL ? 0 : txnid->txnid;\n") >> CFILE;
+ printf("\tnpad = 0;\n\n") >> CFILE;
+
printf("\tif (txnid == NULL) {\n") >> CFILE;
- printf("\t\tZERO_LSN(null_lsn);\n") >> CFILE;
+ printf("\t\ttxn_num = 0;\n") >> CFILE;
+ printf("\t\tnull_lsn.file = 0;\n") >> CFILE;
+ printf("\t\tnull_lsn.offset = 0;\n") >> CFILE;
printf("\t\tlsnp = &null_lsn;\n") >> CFILE;
- printf("\t} else\n\t\tlsnp = &txnid->last_lsn;\n") >> CFILE;
+ printf("\t} else {\n") >> CFILE;
+ if (funcname != "__db_debug" && dbprivate) {
+ printf(\
+ "\t\tif (TAILQ_FIRST(&txnid->kids) != NULL &&\n") >> CFILE;
+ printf("\t\t (ret = __txn_activekids(") >> CFILE;
+ printf("dbenv, rectype, txnid)) != 0)\n") >> CFILE;
+ printf("\t\t\treturn (ret);\n") >> CFILE;
+ }
+ printf("\t\ttxn_num = txnid->txnid;\n") >> CFILE;
+ printf("\t\tlsnp = &txnid->last_lsn;\n") >> CFILE;
+ printf("\t}\n\n") >> CFILE;
# Malloc
printf("\tlogrec.size = sizeof(rectype) + ") >> CFILE;
printf("sizeof(txn_num) + sizeof(DB_LSN)") >> CFILE;
for (i = 0; i < nvars; i++)
printf("\n\t + %s", sizes[i]) >> CFILE;
- printf(";\n\tif ((ret = ") >> CFILE;
- printf(\
- "__os_malloc(dbenv, logrec.size, NULL, &logrec.data)) != 0)\n")\
- >> CFILE;
- printf("\t\treturn (ret);\n\n") >> CFILE;
+ printf(";\n") >> CFILE
+ if (dbprivate) {
+ printf("\tif (CRYPTO_ON(dbenv)) {\n") >> CFILE;
+ printf("\t\tnpad =\n") >> CFILE
+ printf(\
+"\t\t ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size);\n")\
+ >> CFILE;
+ printf("\t\tlogrec.size += npad;\n\t}\n\n") >> CFILE
+ }
+ write_malloc("logrec.data", "logrec.size", CFILE)
+ printf("\tif (npad > 0)\n") >> CFILE;
+ printf("\t\tmemset((u_int8_t *)logrec.data + logrec.size ") >> CFILE;
+ printf("- npad, 0, npad);\n\n") >> CFILE;
# Copy args into buffer
- printf("\tbp = logrec.data;\n") >> CFILE;
+ printf("\tbp = logrec.data;\n\n") >> CFILE;
printf("\tmemcpy(bp, &rectype, sizeof(rectype));\n") >> CFILE;
- printf("\tbp += sizeof(rectype);\n") >> CFILE;
+ printf("\tbp += sizeof(rectype);\n\n") >> CFILE;
printf("\tmemcpy(bp, &txn_num, sizeof(txn_num));\n") >> CFILE;
- printf("\tbp += sizeof(txn_num);\n") >> CFILE;
+ printf("\tbp += sizeof(txn_num);\n\n") >> CFILE;
printf("\tmemcpy(bp, lsnp, sizeof(DB_LSN));\n") >> CFILE;
- printf("\tbp += sizeof(DB_LSN);\n") >> CFILE;
+ printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE;
for (i = 0; i < nvars; i ++) {
- if (modes[i] == "ARG") {
- printf("\tmemcpy(bp, &%s, %s);\n", \
- vars[i], sizes[i]) >> CFILE;
- printf("\tbp += %s;\n", sizes[i]) >> CFILE;
- } else if (modes[i] == "DBT") {
+ if (modes[i] == "ARG" || modes[i] == "WRLOCK" || \
+ modes[i] == "WRLOCKNZ") {
+ printf("\tuinttmp = (u_int32_t)%s;\n", \
+ vars[i]) >> CFILE;
+ printf("\tmemcpy(bp, &uinttmp, sizeof(uinttmp));\n") \
+ >> CFILE;
+ printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE;
+ } else if (modes[i] == "DBT" || modes[i] == "PGDBT") {
printf("\tif (%s == NULL) {\n", vars[i]) >> CFILE;
printf("\t\tzero = 0;\n") >> CFILE;
printf("\t\tmemcpy(bp, &zero, sizeof(u_int32_t));\n") \
@@ -299,49 +454,85 @@ function log_function() {
>> CFILE;
printf("\t\tmemcpy(bp, %s->data, %s->size);\n", \
vars[i], vars[i]) >> CFILE;
- printf("\t\tbp += %s->size;\n\t}\n", vars[i]) >> CFILE;
+ printf("\t\tbp += %s->size;\n\t}\n\n", \
+ vars[i]) >> CFILE;
+ } else if (modes[i] == "DB") {
+ # We need to log a DB handle. To do this, we
+ # actually just log its fileid; from that, we'll
+ # be able to acquire an open handle at recovery time.
+ printf("\tDB_ASSERT(dbp->log_filename != NULL);\n") \
+ >> CFILE;
+ printf("\tif (dbp->log_filename->id == ") >> CFILE;
+ printf("DB_LOGFILEID_INVALID &&\n\t ") >> CFILE
+ printf("(ret = __dbreg_lazy_id(dbp)) != 0)\n") \
+ >> CFILE;
+ printf("\t\treturn (ret);\n\n") >> CFILE;
+
+ printf("\tuinttmp = ") >> CFILE;
+ printf("(u_int32_t)dbp->log_filename->id;\n") >> CFILE;
+ printf("\tmemcpy(bp, &uinttmp, sizeof(uinttmp));\n") \
+ >> CFILE;
+ printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE;
} else { # POINTER
printf("\tif (%s != NULL)\n", vars[i]) >> CFILE;
printf("\t\tmemcpy(bp, %s, %s);\n", vars[i], \
sizes[i]) >> CFILE;
printf("\telse\n") >> CFILE;
printf("\t\tmemset(bp, 0, %s);\n", sizes[i]) >> CFILE;
- printf("\tbp += %s;\n", sizes[i]) >> CFILE;
+ printf("\tbp += %s;\n\n", sizes[i]) >> CFILE;
}
}
- # Error checking
- printf("\tDB_ASSERT((u_int32_t)") >> CFILE;
- printf("(bp - (u_int8_t *)logrec.data) == logrec.size);\n") >> CFILE;
+ # Error checking. User code won't have DB_ASSERT available, but
+ # this is a pretty unlikely assertion anyway, so we just leave it out
+ # rather than requiring assert.h.
+ if (dbprivate) {
+ printf("\tDB_ASSERT((u_int32_t)") >> CFILE;
+ printf("(bp - (u_int8_t *)logrec.data) <= logrec.size);\n") \
+ >> CFILE;
+ }
# Issue log call
- # The logging system cannot call the public log_put routine
- # due to mutual exclusion constraints. So, if we are
- # generating code for the log subsystem, use the internal
- # __log_put.
- if (prefix == "log")
- printf("\tret = __log_put\(dbenv, ret_lsnp, ") >> CFILE;
- else
- printf("\tret = log_put(dbenv, ret_lsnp, ") >> CFILE;
- printf("(DBT *)&logrec, flags);\n") >> CFILE;
+ # We didn't call the crypto alignment function when we created this
+ # log record (because we don't have the right header files to find
+ # the function), so we have to copy the log record to make sure the
+ # alignment is correct.
+ printf(\
+ "\tret = dbenv->log_put(dbenv,\n\t ret_lsnp, (DBT *)&logrec, ") \
+ >> CFILE;
+ if (dbprivate) {
+ printf("flags | DB_NOCOPY);\n") >> CFILE;
+ } else {
+ printf("flags);\n") >> CFILE;
+ }
# Update the transactions last_lsn
- printf("\tif (txnid != NULL)\n") >> CFILE;
+ printf("\tif (txnid != NULL && ret == 0)\n") >> CFILE;
printf("\t\ttxnid->last_lsn = *ret_lsnp;\n") >> CFILE;
+ # If out of disk space log writes may fail. If we are debugging
+ # that print out which records did not make it to disk.
+ printf("#ifdef LOG_DIAGNOSTIC\n") >> CFILE
+ printf("\tif (ret != 0)\n") >> CFILE;
+ printf("\t\t(void)%s_print(dbenv,\n", funcname) >> CFILE;
+ printf("\t\t (DBT *)&logrec, ret_lsnp, NULL, NULL);\n") >> CFILE
+ printf("#endif\n") >> CFILE
+
# Free and return
- printf("\t__os_free(logrec.data, logrec.size);\n") >> CFILE;
+ write_free("logrec.data", CFILE)
printf("\treturn (ret);\n}\n\n") >> CFILE;
}
function print_function() {
# Write the print function; function prototype
- printf("int __%s_print", funcname) >> HFILE;
- printf(" __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));\n") \
- >> HFILE;
+ p[1] = sprintf("int %s_print", funcname);
+ p[2] = " ";
+ p[3] = "__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));";
+ p[4] = "";
+ proto_format(p);
# Function declaration
- printf("int\n__%s_print(dbenv, ", funcname) >> CFILE;
+ printf("int\n%s_print(dbenv, ", funcname) >> CFILE;
printf("dbtp, lsnp, notused2, notused3)\n") >> CFILE;
printf("\tDB_ENV *dbenv;\n") >> CFILE;
printf("\tDBT *dbtp;\n") >> CFILE;
@@ -349,20 +540,26 @@ function print_function() {
printf("\tdb_recops notused2;\n\tvoid *notused3;\n{\n") >> CFILE;
# Locals
- printf("\t__%s_args *argp;\n", funcname) >> CFILE;
- printf("\tu_int32_t i;\n\tu_int ch;\n\tint ret;\n\n") >> CFILE;
+ printf("\t%s_args *argp;\n", funcname) >> CFILE;
+ for (i = 0; i < nvars; i ++)
+ if (modes[i] == "DBT" || modes[i] == "PGDBT") {
+ printf("\tu_int32_t i;\n") >> CFILE
+ printf("\tint ch;\n") >> CFILE
+ break;
+ }
+
+ printf("\tint ret;\n\n") >> CFILE;
# Get rid of complaints about unused parameters.
- printf("\ti = 0;\n\tch = 0;\n") >> CFILE;
printf("\tnotused2 = DB_TXN_ABORT;\n\tnotused3 = NULL;\n\n") >> CFILE;
# Call read routine to initialize structure
- printf("\tif ((ret = __%s_read(dbenv, dbtp->data, &argp)) != 0)\n", \
+ printf("\tif ((ret = %s_read(dbenv, dbtp->data, &argp)) != 0)\n", \
funcname) >> CFILE;
printf("\t\treturn (ret);\n") >> CFILE;
# Print values in every record
- printf("\tprintf(\"[%%lu][%%lu]%s: ", funcname) >> CFILE;
+ printf("\t(void)printf(\n\t \"[%%lu][%%lu]%s: ", funcname) >> CFILE;
printf("rec: %%lu txnid %%lx ") >> CFILE;
printf("prevlsn [%%lu][%%lu]\\n\",\n") >> CFILE;
printf("\t (u_long)lsnp->file,\n") >> CFILE;
@@ -374,19 +571,17 @@ function print_function() {
# Now print fields of argp
for (i = 0; i < nvars; i ++) {
- printf("\tprintf(\"\\t%s: ", vars[i]) >> CFILE;
+ printf("\t(void)printf(\"\\t%s: ", vars[i]) >> CFILE;
- if (modes[i] == "DBT") {
+ if (modes[i] == "DBT" || modes[i] == "PGDBT") {
printf("\");\n") >> CFILE;
printf("\tfor (i = 0; i < ") >> CFILE;
printf("argp->%s.size; i++) {\n", vars[i]) >> CFILE;
printf("\t\tch = ((u_int8_t *)argp->%s.data)[i];\n", \
vars[i]) >> CFILE;
- printf("\t\tif (isprint(ch) || ch == 0xa)\n") >> CFILE;
- printf("\t\t\tputchar(ch);\n") >> CFILE;
- printf("\t\telse\n") >> CFILE;
- printf("\t\t\tprintf(\"%%#x \", ch);\n") >> CFILE;
- printf("\t}\n\tprintf(\"\\n\");\n") >> CFILE;
+ printf("\t\tprintf(isprint(ch) || ch == 0x0a") >> CFILE;
+ printf(" ? \"%%c\" : \"%%#x \", ch);\n") >> CFILE;
+ printf("\t}\n\t(void)printf(\"\\n\");\n") >> CFILE;
} else if (types[i] == "DB_LSN *") {
printf("[%%%s][%%%s]\\n\",\n", \
formats[i], formats[i]) >> CFILE;
@@ -405,52 +600,63 @@ function print_function() {
printf("argp->%s);\n", vars[i]) >> CFILE;
}
}
- printf("\tprintf(\"\\n\");\n") >> CFILE;
- printf("\t__os_free(argp, 0);\n") >> CFILE;
+ printf("\t(void)printf(\"\\n\");\n") >> CFILE;
+ write_free("argp", CFILE);
printf("\treturn (0);\n") >> CFILE;
printf("}\n\n") >> CFILE;
}
function read_function() {
# Write the read function; function prototype
- printf("int __%s_read __P((DB_ENV *, void *, ", funcname) >> HFILE;
- printf("__%s_args **));\n", funcname) >> HFILE;
+ p[1] = sprintf("int %s_read __P((DB_ENV *, void *,", funcname);
+ p[2] = " ";
+ p[3] = sprintf("%s_args **));", funcname);
+ p[4] = "";
+ proto_format(p);
# Function declaration
- printf("int\n__%s_read(dbenv, recbuf, argpp)\n", funcname) >> CFILE;
+ printf("int\n%s_read(dbenv, recbuf, argpp)\n", funcname) >> CFILE;
# Now print the parameters
printf("\tDB_ENV *dbenv;\n") >> CFILE;
printf("\tvoid *recbuf;\n") >> CFILE;
- printf("\t__%s_args **argpp;\n", funcname) >> CFILE;
+ printf("\t%s_args **argpp;\n", funcname) >> CFILE;
# Function body and local decls
- printf("{\n\t__%s_args *argp;\n", funcname) >> CFILE;
+ printf("{\n\t%s_args *argp;\n", funcname) >> CFILE;
+ if (is_uint == 1)
+ printf("\tu_int32_t uinttmp;\n") >> CFILE;
printf("\tu_int8_t *bp;\n") >> CFILE;
- printf("\tint ret;\n") >> CFILE;
- printf("\n\tret = __os_malloc(dbenv, sizeof(") >> CFILE;
- printf("__%s_args) +\n\t sizeof(DB_TXN), NULL, &argp);\n", \
- funcname) >> CFILE;
- printf("\tif (ret != 0)\n\t\treturn (ret);\n") >> CFILE;
- # Set up the pointers to the txnid and the prev lsn
- printf("\targp->txnid = (DB_TXN *)&argp[1];\n") >> CFILE;
+ if (dbprivate) {
+ # We only use dbenv and ret in the private malloc case.
+ printf("\tint ret;\n\n") >> CFILE;
+ } else {
+ printf("\t/* Keep the compiler quiet. */\n") >> CFILE;
+ printf("\n\tdbenv = NULL;\n") >> CFILE;
+ }
+
+ malloc_size = sprintf("sizeof(%s_args) + sizeof(DB_TXN)", funcname)
+ write_malloc("argp", malloc_size, CFILE)
+
+ # Set up the pointers to the txnid.
+ printf("\targp->txnid = (DB_TXN *)&argp[1];\n\n") >> CFILE;
# First get the record type, prev_lsn, and txnid fields.
printf("\tbp = recbuf;\n") >> CFILE;
printf("\tmemcpy(&argp->type, bp, sizeof(argp->type));\n") >> CFILE;
- printf("\tbp += sizeof(argp->type);\n") >> CFILE;
+ printf("\tbp += sizeof(argp->type);\n\n") >> CFILE;
printf("\tmemcpy(&argp->txnid->txnid, bp, ") >> CFILE;
printf("sizeof(argp->txnid->txnid));\n") >> CFILE;
- printf("\tbp += sizeof(argp->txnid->txnid);\n") >> CFILE;
+ printf("\tbp += sizeof(argp->txnid->txnid);\n\n") >> CFILE;
printf("\tmemcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));\n") >> CFILE;
- printf("\tbp += sizeof(DB_LSN);\n") >> CFILE;
+ printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE;
# Now get rest of data.
for (i = 0; i < nvars; i ++) {
- if (modes[i] == "DBT") {
+ if (modes[i] == "DBT" || modes[i] == "PGDBT") {
printf("\tmemset(&argp->%s, 0, sizeof(argp->%s));\n", \
vars[i], vars[i]) >> CFILE;
printf("\tmemcpy(&argp->%s.size, ", vars[i]) >> CFILE;
@@ -458,18 +664,181 @@ function read_function() {
printf("\tbp += sizeof(u_int32_t);\n") >> CFILE;
printf("\targp->%s.data = bp;\n", vars[i]) >> CFILE;
printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE;
- } else if (modes[i] == "ARG") {
- printf("\tmemcpy(&argp->%s, bp, %s%s));\n", \
- vars[i], "sizeof(argp->", vars[i]) >> CFILE;
- printf("\tbp += sizeof(argp->%s);\n", vars[i]) >> CFILE;
+ } else if (modes[i] == "ARG" || modes[i] == "WRLOCK" || \
+ modes[i] == "WRLOCKNZ" || modes[i] == "DB") {
+ printf("\tmemcpy(&uinttmp, bp, sizeof(uinttmp));\n") \
+ >> CFILE;
+ printf("\targp->%s = (%s)uinttmp;\n", vars[i], \
+ types[i]) >> CFILE;
+ printf("\tbp += sizeof(uinttmp);\n") >> CFILE;
} else { # POINTER
printf("\tmemcpy(&argp->%s, bp, ", vars[i]) >> CFILE;
printf(" sizeof(argp->%s));\n", vars[i]) >> CFILE;
printf("\tbp += sizeof(argp->%s);\n", vars[i]) >> CFILE;
}
+ printf("\n") >> CFILE;
}
# Free and return
printf("\t*argpp = argp;\n") >> CFILE;
printf("\treturn (0);\n}\n\n") >> CFILE;
}
+
+function getpgnos_function() {
+ # Write the getpgnos function; function prototype
+ p[1] = sprintf("int %s_getpgnos", funcname);
+ p[2] = " ";
+ p[3] = "__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));";
+ p[4] = "";
+ proto_format(p);
+
+ # Function declaration
+ printf("int\n%s_getpgnos(dbenv, ", funcname) >> CFILE;
+ printf("rec, lsnp, notused1, summary)\n") >> CFILE;
+ printf("\tDB_ENV *dbenv;\n") >> CFILE;
+ printf("\tDBT *rec;\n") >> CFILE;
+ printf("\tDB_LSN *lsnp;\n") >> CFILE;
+ printf("\tdb_recops notused1;\n") >> CFILE;
+ printf("\tvoid *summary;\n{\n") >> CFILE;
+
+ # If there are no locks, return this fact.
+ if (nlocks == 0) {
+ printf("\tTXN_RECS *t;\n") >> CFILE;
+ printf("\tint ret;\n") >> CFILE;
+ printf("\tCOMPQUIET(rec, NULL);\n") >> CFILE;
+ printf("\tCOMPQUIET(notused1, DB_TXN_ABORT);\n") >> CFILE;
+
+ printf("\n\tt = (TXN_RECS *)summary;\n") >> CFILE;
+ printf("\n\tif ((ret = __rep_check_alloc(dbenv, ") >> CFILE;
+ printf("t, 1)) != 0)\n") >> CFILE;
+ printf("\t\treturn (ret);\n") >> CFILE;
+
+ printf("\n\tt->array[t->npages].flags = LSN_PAGE_NOLOCK;\n") \
+ >> CFILE;
+ printf("\tt->array[t->npages].lsn = *lsnp;\n") >> CFILE;
+ printf("\tt->array[t->npages].fid = DB_LOGFILEID_INVALID;\n") \
+ >> CFILE;
+ printf("\tmemset(&t->array[t->npages].pgdesc, 0,\n") >> CFILE;
+ printf("\t sizeof(t->array[t->npages].pgdesc));\n") >> CFILE;
+ printf("\n\tt->npages++;\n") >> CFILE;
+
+ printf("\n") >> CFILE;
+ printf("\treturn (0);\n") >> CFILE;
+ printf("}\n\n") >> CFILE;
+ return;
+ }
+
+ # Locals
+ printf("\tDB *dbp;\n") >> CFILE;
+ printf("\tTXN_RECS *t;\n") >> CFILE;
+ printf("\t%s_args *argp;\n", funcname) >> CFILE;
+ printf("\tu_int32_t ret;\n\n") >> CFILE;
+
+ # Shut up compiler.
+ printf("\tCOMPQUIET(notused1, DB_TXN_ABORT);\n\n") >> CFILE;
+
+ printf("\targp = NULL;\n") >> CFILE;
+ printf("\tt = (TXN_RECS *)summary;\n\n") >> CFILE;
+
+ printf("\tif ((ret = %s_read(dbenv, rec->data, &argp)) != 0)\n", \
+ funcname) >> CFILE;
+ printf("\t\treturn (ret);\n") >> CFILE;
+
+ # Get file ID.
+ printf("\n\tif ((ret = __dbreg_id_to_db(dbenv,\n\t ") >> CFILE;
+ printf("argp->txnid, &dbp, argp->fileid, 0)) != 0)\n") >> CFILE;
+ printf("\t\tgoto err;\n") >> CFILE;
+
+ printf("\n\tif ((ret = __rep_check_alloc(dbenv, t, %d)) != 0)\n", \
+ nlocks) >> CFILE;
+ printf("\t\tgoto err;\n\n") >> CFILE;
+
+ for (i = 1; i <= nlocks; i++) {
+ if (lock_if_zero[i]) {
+ indent = "\t";
+ } else {
+ indent = "\t\t";
+ printf("\tif (argp->%s != PGNO_INVALID) {\n", \
+ lock_pgnos[i]) >> CFILE;
+ }
+ printf("%st->array[t->npages].flags = 0;\n", indent) >> CFILE;
+ printf("%st->array[t->npages].fid = argp->fileid;\n", indent) \
+ >> CFILE;
+ printf("%st->array[t->npages].lsn = *lsnp;\n", indent) >> CFILE;
+ printf("%st->array[t->npages].pgdesc.pgno = argp->%s;\n", \
+ indent, lock_pgnos[i]) >> CFILE;
+ printf("%st->array[t->npages].pgdesc.type = DB_PAGE_LOCK;\n", \
+ indent) >> CFILE;
+ printf("%smemcpy(t->array[t->npages].pgdesc.fileid, ", indent) \
+ >> CFILE;
+ printf("dbp->fileid,\n%s DB_FILE_ID_LEN);\n", \
+ indent, indent) >> CFILE;
+ printf("%st->npages++;\n", indent) >> CFILE;
+ if (!lock_if_zero[i]) {
+ printf("\t}\n") >> CFILE;
+ }
+ }
+
+ printf("\nerr:\tif (argp != NULL)\n") >> CFILE;
+ write_free("argp", CFILE);
+
+ printf("\treturn (ret);\n") >> CFILE;
+
+ printf("}\n\n") >> CFILE;
+}
+
+# proto_format --
+# Pretty-print a function prototype.
+function proto_format(p)
+{
+ printf("/*\n") >> CFILE;
+
+ s = "";
+ for (i = 1; i in p; ++i)
+ s = s p[i];
+
+ t = " * PUBLIC: "
+ if (length(s) + length(t) < 80)
+ printf("%s%s", t, s) >> CFILE;
+ else {
+ split(s, p, "__P");
+ len = length(t) + length(p[1]);
+ printf("%s%s", t, p[1]) >> CFILE
+
+ n = split(p[2], comma, ",");
+ comma[1] = "__P" comma[1];
+ for (i = 1; i <= n; i++) {
+ if (len + length(comma[i]) > 70) {
+ printf("\n * PUBLIC: ") >> CFILE;
+ len = 0;
+ }
+ printf("%s%s", comma[i], i == n ? "" : ",") >> CFILE;
+ len += length(comma[i]) + 2;
+ }
+ }
+ printf("\n */\n") >> CFILE;
+ delete p;
+}
+
+function write_malloc(ptr, size, file)
+{
+ if (dbprivate) {
+ printf("\tif ((ret = ") >> file;
+ printf(\
+ "__os_malloc(dbenv,\n\t " size ", &" ptr ")) != 0)\n") \
+ >> file
+ printf("\t\treturn (ret);\n\n") >> file;
+ } else {
+ printf("\tif ((" ptr " = malloc(" size ")) == NULL)\n") >> file
+ printf("\t\treturn (ENOMEM);\n\n") >> file
+ }
+}
+
+function write_free(ptr, file)
+{
+ if (dbprivate) {
+ printf("\t__os_free(dbenv, " ptr ");\n") >> file
+ } else {
+ printf("\tfree(" ptr ");\n") >> file
+ }
+}
diff --git a/bdb/dist/gen_rpc.awk b/bdb/dist/gen_rpc.awk
index 6c3bffc1aa4..03975d7321b 100644
--- a/bdb/dist/gen_rpc.awk
+++ b/bdb/dist/gen_rpc.awk
@@ -1,5 +1,5 @@
#
-# $Id: gen_rpc.awk,v 11.25 2001/01/02 20:04:55 sue Exp $
+# $Id: gen_rpc.awk,v 11.50 2002/07/02 19:26:57 sue Exp $
# Awk script for generating client/server RPC code.
#
# This awk script generates most of the RPC routines for DB client/server
@@ -9,27 +9,30 @@
#
# This awk script requires that these variables be set when it is called:
#
+# major -- Major version number
+# minor -- Minor version number
+# xidsize -- size of GIDs
# client_file -- the C source file being created for client code
-# cproto_file -- the header file create for client prototypes
# ctmpl_file -- the C template file being created for client code
# sed_file -- the sed file created to alter server proc code
# server_file -- the C source file being created for server code
-# sproto_file -- the header file create for server prototypes
# stmpl_file -- the C template file being created for server code
# xdr_file -- the XDR message file created
#
# And stdin must be the input file that defines the RPC setup.
BEGIN {
- if (client_file == "" || cproto_file == "" || ctmpl_file == "" ||
+ if (major == "" || minor == "" || xidsize == "" ||
+ client_file == "" || ctmpl_file == "" ||
sed_file == "" || server_file == "" ||
- sproto_file == "" || stmpl_file == "" || xdr_file == "") {
+ stmpl_file == "" || xdr_file == "") {
print "Usage: gen_rpc.awk requires these variables be set:"
+ print "\tmajor\t-- Major version number"
+ print "\tminor\t-- Minor version number"
+ print "\txidsize\t-- GID size"
print "\tclient_file\t-- the client C source file being created"
- print "\tcproto_file\t-- the client prototype header created"
print "\tctmpl_file\t-- the client template file being created"
print "\tsed_file\t-- the sed command file being created"
print "\tserver_file\t-- the server C source file being created"
- print "\tsproto_file\t-- the server prototype header created"
print "\tstmpl_file\t-- the server template file being created"
print "\txdr_file\t-- the XDR message file being created"
error = 1; exit
@@ -40,10 +43,6 @@ BEGIN {
printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
> CFILE
- CHFILE=cproto_file
- printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
- > CHFILE
-
TFILE = ctmpl_file
printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
> TFILE
@@ -52,10 +51,6 @@ BEGIN {
printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
> SFILE
- SHFILE=sproto_file
- printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
- > SHFILE
-
# Server procedure template and a sed file to massage an existing
# template source file to change args.
# SEDFILE should be same name as PFILE but .c
@@ -74,28 +69,24 @@ BEGIN {
END {
printf("#endif /* HAVE_RPC */\n") >> CFILE
printf("#endif /* HAVE_RPC */\n") >> TFILE
- printf("program DB_SERVERPROG {\n") >> XFILE
- printf("\tversion DB_SERVERVERS {\n") >> XFILE
+ printf("program DB_RPC_SERVERPROG {\n") >> XFILE
+ printf("\tversion DB_RPC_SERVERVERS {\n") >> XFILE
for (i = 1; i < nendlist; ++i)
printf("\t\t%s;\n", endlist[i]) >> XFILE
- printf("\t} = 1;\n") >> XFILE
+ printf("\t} = %d%03d;\n", major, minor) >> XFILE
printf("} = 351457;\n") >> XFILE
}
/^[ ]*BEGIN/ {
name = $2;
- msgid = $3;
nofunc_code = 0;
funcvars = 0;
- gen_code = 1;
ret_code = 0;
- if ($4 == "NOCLNTCODE")
- gen_code = 0;
- if ($4 == "NOFUNC")
+ if ($3 == "NOFUNC")
nofunc_code = 1;
- if ($4 == "RETCODE")
+ if ($3 == "RETCODE")
ret_code = 1;
nvars = 0;
@@ -131,8 +122,10 @@ END {
if (c_type[nvars] == "DB *") {
ctp_type[nvars] = "CT_DB";
- db_handle = 1;
- db_idx = nvars;
+ if (db_handle != 1) {
+ db_handle = 1;
+ db_idx = nvars;
+ }
}
if (c_type[nvars] == "DBC *") {
@@ -182,6 +175,78 @@ END {
/^[ ]*END/ {
#
# =====================================================
+ # File headers, if necessary.
+ #
+ if (first == 0) {
+ printf("#include \"db_config.h\"\n") >> CFILE
+ printf("\n") >> CFILE
+ printf("#ifdef HAVE_RPC\n") >> CFILE
+ printf("#ifndef NO_SYSTEM_INCLUDES\n") >> CFILE
+ printf("#include <sys/types.h>\n\n") >> CFILE
+ printf("#include <rpc/rpc.h>\n") >> CFILE
+ printf("#include <rpc/xdr.h>\n") >> CFILE
+ printf("\n") >> CFILE
+ printf("#include <string.h>\n") >> CFILE
+ printf("#endif\n") >> CFILE
+ printf("\n") >> CFILE
+ printf("#include \"db_int.h\"\n") >> CFILE
+ printf("#include \"dbinc/txn.h\"\n") >> CFILE
+ printf("\n") >> CFILE
+ printf("#include \"dbinc_auto/db_server.h\"\n") >> CFILE
+ printf("#include \"dbinc_auto/rpc_client_ext.h\"\n") >> CFILE
+ printf("\n") >> CFILE
+
+ printf("#include \"db_config.h\"\n") >> TFILE
+ printf("\n") >> TFILE
+ printf("#ifdef HAVE_RPC\n") >> TFILE
+ printf("#ifndef NO_SYSTEM_INCLUDES\n") >> TFILE
+ printf("#include <sys/types.h>\n") >> TFILE
+ printf("#include <rpc/rpc.h>\n") >> TFILE
+ printf("\n") >> TFILE
+ printf("#include <string.h>\n") >> TFILE
+ printf("#endif\n") >> TFILE
+ printf("#include \"db_int.h\"\n") >> TFILE
+ printf("#include \"dbinc_auto/db_server.h\"\n") >> TFILE
+ printf("#include \"dbinc/txn.h\"\n") >> TFILE
+ printf("\n") >> TFILE
+
+ printf("#include \"db_config.h\"\n") >> SFILE
+ printf("\n") >> SFILE
+ printf("#ifndef NO_SYSTEM_INCLUDES\n") >> SFILE
+ printf("#include <sys/types.h>\n") >> SFILE
+ printf("\n") >> SFILE
+ printf("#include <rpc/rpc.h>\n") >> SFILE
+ printf("#include <rpc/xdr.h>\n") >> SFILE
+ printf("\n") >> SFILE
+ printf("#include <string.h>\n") >> SFILE
+ printf("#endif\n") >> SFILE
+ printf("\n") >> SFILE
+ printf("#include \"db_int.h\"\n") >> SFILE
+ printf("#include \"dbinc_auto/db_server.h\"\n") >> SFILE
+ printf("#include \"dbinc/db_server_int.h\"\n") >> SFILE
+ printf("#include \"dbinc_auto/rpc_server_ext.h\"\n") >> SFILE
+ printf("\n") >> SFILE
+
+ printf("#include \"db_config.h\"\n") >> PFILE
+ printf("\n") >> PFILE
+ printf("#ifndef NO_SYSTEM_INCLUDES\n") >> PFILE
+ printf("#include <sys/types.h>\n") >> PFILE
+ printf("\n") >> PFILE
+ printf("#include <rpc/rpc.h>\n") >> PFILE
+ printf("\n") >> PFILE
+ printf("#include <string.h>\n") >> PFILE
+ printf("#endif\n") >> PFILE
+ printf("\n") >> PFILE
+ printf("#include \"db_int.h\"\n") >> PFILE
+ printf("#include \"dbinc_auto/db_server.h\"\n") >> PFILE
+ printf("#include \"dbinc/db_server_int.h\"\n") >> PFILE
+ printf("#include \"dbinc_auto/rpc_server_ext.h\"\n") >> PFILE
+ printf("\n") >> PFILE
+
+ first = 1;
+ }
+ #
+ # =====================================================
# Generate Client Nofunc code first if necessary
# NOTE: This code must be first, because we don't want any
# other code other than this function, so before we write
@@ -190,50 +255,48 @@ END {
#
if (nofunc_code == 1) {
#
- # First time through, put out the general illegal function
+ # First time through, put out the general no server and
+ # illegal functions.
#
if (first_nofunc == 0) {
- printf("int __dbcl_rpc_illegal ") >> CHFILE
- printf("__P((DB_ENV *, char *));\n") >> CHFILE
- printf("int\n__dbcl_rpc_illegal(dbenv, name)\n") \
- >> CFILE
+ printf("static int __dbcl_noserver ") >> CFILE
+ printf("__P((DB_ENV *));\n\n") >> CFILE
+ printf("static int\n") >> CFILE
+ printf("__dbcl_noserver(dbenv)\n") >> CFILE
+ printf("\tDB_ENV *dbenv;\n") >> CFILE
+ printf("{\n\t__db_err(dbenv,") >> CFILE
+ printf(" \"No server environment\");\n") >> CFILE
+ printf("\treturn (DB_NOSERVER);\n") >> CFILE
+ printf("}\n\n") >> CFILE
+
+ printf("static int __dbcl_rpc_illegal ") >> CFILE
+ printf("__P((DB_ENV *, char *));\n\n") >> CFILE
+ printf("static int\n") >> CFILE
+ printf("__dbcl_rpc_illegal(dbenv, name)\n") >> CFILE
printf("\tDB_ENV *dbenv;\n\tchar *name;\n") >> CFILE
- printf("{\n\t__db_err(dbenv,\n") >> CFILE
- printf("\t \"%%s method meaningless in RPC") >> CFILE
+ printf("{\n\t__db_err(dbenv,") >> CFILE
+ printf(" \"%%s method meaningless in an RPC") >> CFILE
printf(" environment\", name);\n") >> CFILE
printf("\treturn (__db_eopnotsup(dbenv));\n") >> CFILE
printf("}\n\n") >> CFILE
+
first_nofunc = 1
}
#
- # If we are doing a list, spit out prototype decl.
- #
- for (i = 0; i < nvars; i++) {
- if (rpc_type[i] != "LIST")
- continue;
- printf("static int __dbcl_%s_%slist __P((", \
- name, args[i]) >> CFILE
- printf("__%s_%slist **, ", name, args[i]) >> CFILE
- if (list_type[i] == "STRING")
- printf("%s));\n", c_type[i]) >> CFILE
- if (list_type[i] == "INT")
- printf("u_int32_t));\n") >> CFILE
- if (list_type[i] == "ID")
- printf("%s));\n", c_type[i]) >> CFILE
- printf("static void __dbcl_%s_%sfree __P((", \
- name, args[i]) >> CFILE
- printf("__%s_%slist **));\n", name, args[i]) >> CFILE
- }
- #
# Spit out PUBLIC prototypes.
#
- printf("int __dbcl_%s __P((",name) >> CHFILE
- sep = "";
+ pi = 1;
+ p[pi++] = sprintf("int __dbcl_%s __P((", name);
+ p[pi++] = "";
for (i = 0; i < nvars; ++i) {
- printf("%s%s", sep, pr_type[i]) >> CHFILE
- sep = ", ";
+ p[pi++] = pr_type[i];
+ p[pi++] = ", ";
}
- printf("));\n") >> CHFILE
+ p[pi - 1] = "";
+ p[pi++] = "));";
+ p[pi] = "";
+ proto_format(p, 0, CFILE);
+
#
# Spit out function name/args.
#
@@ -286,7 +349,8 @@ END {
# to COMPQUIET that one.
for (i = 1; i < nvars; ++i) {
if (rpc_type[i] == "CONST" || rpc_type[i] == "DBT" ||
- rpc_type[i] == "LIST" || rpc_type[i] == "STRING") {
+ rpc_type[i] == "LIST" || rpc_type[i] == "STRING" ||
+ rpc_type[i] == "GID") {
printf("\tCOMPQUIET(%s, NULL);\n", args[i]) \
>> CFILE
}
@@ -313,60 +377,43 @@ END {
# XDR messages.
#
printf("\n") >> XFILE
- #
- # If there are any lists, generate the structure to contain them.
- #
+ printf("struct __%s_msg {\n", name) >> XFILE
for (i = 0; i < nvars; ++i) {
if (rpc_type[i] == "LIST") {
- printf("struct __%s_%slist {\n", name, args[i]) >> XFILE
- printf("\topaque ent<>;\n") >> XFILE
- printf("\t__%s_%slist *next;\n", name, args[i]) >> XFILE
- printf("};\n\n") >> XFILE
+ if (list_type[i] == "GID") {
+ printf("\topaque %s<>;\n", args[i]) >> XFILE
+ } else {
+ printf("\tunsigned int %s<>;\n", args[i]) >> XFILE
+ }
}
- }
- printf("struct __%s_msg {\n", name) >> XFILE
- for (i = 0; i < nvars; ++i) {
if (rpc_type[i] == "ID") {
printf("\tunsigned int %scl_id;\n", args[i]) >> XFILE
}
if (rpc_type[i] == "STRING") {
printf("\tstring %s<>;\n", args[i]) >> XFILE
}
+ if (rpc_type[i] == "GID") {
+ printf("\topaque %s[%d];\n", args[i], xidsize) >> XFILE
+ }
if (rpc_type[i] == "INT") {
printf("\tunsigned int %s;\n", args[i]) >> XFILE
}
if (rpc_type[i] == "DBT") {
printf("\tunsigned int %sdlen;\n", args[i]) >> XFILE
printf("\tunsigned int %sdoff;\n", args[i]) >> XFILE
+ printf("\tunsigned int %sulen;\n", args[i]) >> XFILE
printf("\tunsigned int %sflags;\n", args[i]) >> XFILE
printf("\topaque %sdata<>;\n", args[i]) >> XFILE
}
- if (rpc_type[i] == "LIST") {
- printf("\t__%s_%slist *%slist;\n", \
- name, args[i], args[i]) >> XFILE
- }
}
printf("};\n") >> XFILE
printf("\n") >> XFILE
#
- # If there are any lists, generate the structure to contain them.
- #
- for (i = 0; i < rvars; ++i) {
- if (ret_type[i] == "LIST") {
- printf("struct __%s_%sreplist {\n", \
- name, retargs[i]) >> XFILE
- printf("\topaque ent<>;\n") >> XFILE
- printf("\t__%s_%sreplist *next;\n", \
- name, retargs[i]) >> XFILE
- printf("};\n\n") >> XFILE
- }
- }
- #
# Generate the reply message
#
printf("struct __%s_reply {\n", name) >> XFILE
- printf("\tunsigned int status;\n") >> XFILE
+ printf("\tint status;\n") >> XFILE
for (i = 0; i < rvars; ++i) {
if (ret_type[i] == "ID") {
printf("\tunsigned int %scl_id;\n", retargs[i]) >> XFILE
@@ -384,8 +431,11 @@ END {
printf("\topaque %sdata<>;\n", retargs[i]) >> XFILE
}
if (ret_type[i] == "LIST") {
- printf("\t__%s_%sreplist *%slist;\n", \
- name, retargs[i], retargs[i]) >> XFILE
+ if (retlist_type[i] == "GID") {
+ printf("\topaque %s<>;\n", retargs[i]) >> XFILE
+ } else {
+ printf("\tunsigned int %s<>;\n", retargs[i]) >> XFILE
+ }
}
}
printf("};\n") >> XFILE
@@ -394,158 +444,30 @@ END {
sprintf("__%s_reply __DB_%s(__%s_msg) = %d", \
name, name, name, nendlist);
nendlist++;
-
- #
- # =====================================================
- # File headers, if necessary.
- #
- if (first == 0) {
- printf("#include \"db_config.h\"\n") >> CFILE
- printf("\n") >> CFILE
- printf("#ifdef HAVE_RPC\n") >> CFILE
- printf("#ifndef NO_SYSTEM_INCLUDES\n") >> CFILE
- printf("#include <sys/types.h>\n") >> CFILE
- printf("#include <rpc/rpc.h>\n") >> CFILE
- printf("#include <rpc/xdr.h>\n") >> CFILE
- printf("\n") >> CFILE
- printf("#include <errno.h>\n") >> CFILE
- printf("#include <string.h>\n") >> CFILE
- printf("#endif\n") >> CFILE
- printf("#include \"db_server.h\"\n") >> CFILE
- printf("\n") >> CFILE
- printf("#include \"db_int.h\"\n") >> CFILE
- printf("#include \"db_page.h\"\n") >> CFILE
- printf("#include \"db_ext.h\"\n") >> CFILE
- printf("#include \"mp.h\"\n") >> CFILE
- printf("#include \"rpc_client_ext.h\"\n") >> CFILE
- printf("#include \"txn.h\"\n") >> CFILE
- printf("\n") >> CFILE
- n = split(CHFILE, hpieces, "/");
- printf("#include \"%s\"\n", hpieces[n]) >> CFILE
- printf("\n") >> CFILE
-
- printf("#include \"db_config.h\"\n") >> TFILE
- printf("\n") >> TFILE
- printf("#ifdef HAVE_RPC\n") >> TFILE
- printf("#ifndef NO_SYSTEM_INCLUDES\n") >> TFILE
- printf("#include <sys/types.h>\n") >> TFILE
- printf("#include <rpc/rpc.h>\n") >> TFILE
- printf("\n") >> TFILE
- printf("#include <errno.h>\n") >> TFILE
- printf("#include <string.h>\n") >> TFILE
- printf("#endif\n") >> TFILE
- printf("#include \"db_server.h\"\n") >> TFILE
- printf("\n") >> TFILE
- printf("#include \"db_int.h\"\n") >> TFILE
- printf("#include \"db_page.h\"\n") >> TFILE
- printf("#include \"db_ext.h\"\n") >> TFILE
- printf("#include \"txn.h\"\n") >> TFILE
- printf("\n") >> TFILE
- n = split(CHFILE, hpieces, "/");
- printf("#include \"%s\"\n", hpieces[n]) >> TFILE
- printf("\n") >> TFILE
-
- printf("#include \"db_config.h\"\n") >> SFILE
- printf("\n") >> SFILE
- printf("#ifndef NO_SYSTEM_INCLUDES\n") >> SFILE
- printf("#include <sys/types.h>\n") >> SFILE
- printf("\n") >> SFILE
- printf("#include <rpc/rpc.h>\n") >> SFILE
- printf("#include <rpc/xdr.h>\n") >> SFILE
- printf("\n") >> SFILE
- printf("#include <errno.h>\n") >> SFILE
- printf("#include <string.h>\n") >> SFILE
- printf("#endif\n") >> SFILE
- printf("#include \"db_server.h\"\n") >> SFILE
- printf("\n") >> SFILE
- printf("#include \"db_int.h\"\n") >> SFILE
- printf("#include \"db_server_int.h\"\n") >> SFILE
- printf("#include \"rpc_server_ext.h\"\n") >> SFILE
- printf("\n") >> SFILE
- n = split(SHFILE, hpieces, "/");
- printf("#include \"%s\"\n", hpieces[n]) >> SFILE
- printf("\n") >> SFILE
-
- printf("#include \"db_config.h\"\n") >> PFILE
- printf("\n") >> PFILE
- printf("#ifndef NO_SYSTEM_INCLUDES\n") >> PFILE
- printf("#include <sys/types.h>\n") >> PFILE
- printf("\n") >> PFILE
- printf("#include <rpc/rpc.h>\n") >> PFILE
- printf("\n") >> PFILE
- printf("#include <errno.h>\n") >> PFILE
- printf("#include <string.h>\n") >> PFILE
- printf("#include \"db_server.h\"\n") >> PFILE
- printf("#endif\n") >> PFILE
- printf("\n") >> PFILE
- printf("#include \"db_int.h\"\n") >> PFILE
- printf("#include \"db_server_int.h\"\n") >> PFILE
- printf("#include \"rpc_server_ext.h\"\n") >> PFILE
- printf("\n") >> PFILE
- n = split(SHFILE, hpieces, "/");
- printf("#include \"%s\"\n", hpieces[n]) >> PFILE
- printf("\n") >> PFILE
-
- first = 1;
- }
-
#
# =====================================================
# Server functions.
#
- # If we are doing a list, send out local list prototypes.
- #
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] != "LIST")
- continue;
- if (list_type[i] != "STRING" && list_type[i] != "INT" &&
- list_type[i] != "ID")
- continue;
- printf("int __db_%s_%slist __P((", name, args[i]) >> SFILE
- printf("__%s_%slist *, ", name, args[i]) >> SFILE
- if (list_type[i] == "STRING") {
- printf("char ***));\n") >> SFILE
- }
- if (list_type[i] == "INT" || list_type[i] == "ID") {
- printf("u_int32_t **));\n") >> SFILE
- }
- printf("void __db_%s_%sfree __P((", name, args[i]) >> SFILE
- if (list_type[i] == "STRING")
- printf("char **));\n\n") >> SFILE
- if (list_type[i] == "INT" || list_type[i] == "ID")
- printf("u_int32_t *));\n\n") >> SFILE
-
- }
- #
# First spit out PUBLIC prototypes for server functions.
#
- printf("__%s_reply * __db_%s_%d __P((__%s_msg *));\n", \
- name, name, msgid, name) >> SHFILE
+ p[1] = sprintf("__%s_reply *__db_%s_%d%03d __P((__%s_msg *, struct svc_req *));",
+ name, name, major, minor, name);
+ p[2] = "";
+ proto_format(p, 0, SFILE);
printf("__%s_reply *\n", name) >> SFILE
- printf("__db_%s_%d(req)\n", name, msgid) >> SFILE
- printf("\t__%s_msg *req;\n", name) >> SFILE;
+ printf("__db_%s_%d%03d(msg, req)\n", name, major, minor) >> SFILE
+ printf("\t__%s_msg *msg;\n", name) >> SFILE;
+ printf("\tstruct svc_req *req;\n", name) >> SFILE;
printf("{\n") >> SFILE
- doing_list = 0;
- #
- # If we are doing a list, decompose it for server proc we'll call.
- #
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] != "LIST")
- continue;
- doing_list = 1;
- if (list_type[i] == "STRING")
- printf("\tchar **__db_%slist;\n", args[i]) >> SFILE
- if (list_type[i] == "ID" || list_type[i] == "INT")
- printf("\tu_int32_t *__db_%slist;\n", args[i]) >> SFILE
- }
- if (doing_list)
- printf("\tint ret;\n") >> SFILE
printf("\tstatic __%s_reply reply; /* must be static */\n", \
name) >> SFILE
if (xdr_free) {
printf("\tstatic int __%s_free = 0; /* must be static */\n\n", \
name) >> SFILE
+ }
+ printf("\tCOMPQUIET(req, NULL);\n", name) >> SFILE
+ if (xdr_free) {
printf("\tif (__%s_free)\n", name) >> SFILE
printf("\t\txdr_free((xdrproc_t)xdr___%s_reply, (void *)&reply);\n", \
name) >> SFILE
@@ -553,8 +475,8 @@ END {
printf("\n\t/* Reinitialize allocated fields */\n") >> SFILE
for (i = 0; i < rvars; ++i) {
if (ret_type[i] == "LIST") {
- printf("\treply.%slist = NULL;\n", \
- retargs[i]) >> SFILE
+ printf("\treply.%s.%s_val = NULL;\n", \
+ retargs[i], retargs[i]) >> SFILE
}
if (ret_type[i] == "DBT") {
printf("\treply.%sdata.%sdata_val = NULL;\n", \
@@ -564,44 +486,43 @@ END {
}
need_out = 0;
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] == "LIST") {
- printf("\n\tif ((ret = __db_%s_%slist(", \
- name, args[i]) >> SFILE
- printf("req->%slist, &__db_%slist)) != 0)\n", \
- args[i], args[i]) >> SFILE
- printf("\t\tgoto out;\n") >> SFILE
- need_out = 1;
- }
- }
-
#
# Compose server proc to call. Decompose message components as args.
#
- printf("\n\t__%s_%d_proc(", name, msgid) >> SFILE
+ printf("\n\t__%s_proc(", name) >> SFILE
sep = "";
for (i = 0; i < nvars; ++i) {
+ if (rpc_type[i] == "IGNORE") {
+ continue;
+ }
if (rpc_type[i] == "ID") {
- printf("%sreq->%scl_id", sep, args[i]) >> SFILE
+ printf("%smsg->%scl_id", sep, args[i]) >> SFILE
}
if (rpc_type[i] == "STRING") {
- printf("%s(*req->%s == '\\0') ? NULL : req->%s", \
+ printf("%s(*msg->%s == '\\0') ? NULL : msg->%s", \
sep, args[i], args[i]) >> SFILE
}
+ if (rpc_type[i] == "GID") {
+ printf("%smsg->%s", sep, args[i]) >> SFILE
+ }
if (rpc_type[i] == "INT") {
- printf("%sreq->%s", sep, args[i]) >> SFILE
+ printf("%smsg->%s", sep, args[i]) >> SFILE
}
if (rpc_type[i] == "LIST") {
- printf("%s__db_%slist", sep, args[i]) >> SFILE
+ printf("%smsg->%s.%s_val", \
+ sep, args[i], args[i]) >> SFILE
+ printf("%smsg->%s.%s_len", \
+ sep, args[i], args[i]) >> SFILE
}
if (rpc_type[i] == "DBT") {
- printf("%sreq->%sdlen", sep, args[i]) >> SFILE
+ printf("%smsg->%sdlen", sep, args[i]) >> SFILE
sep = ",\n\t ";
- printf("%sreq->%sdoff", sep, args[i]) >> SFILE
- printf("%sreq->%sflags", sep, args[i]) >> SFILE
- printf("%sreq->%sdata.%sdata_val", \
+ printf("%smsg->%sdoff", sep, args[i]) >> SFILE
+ printf("%smsg->%sulen", sep, args[i]) >> SFILE
+ printf("%smsg->%sflags", sep, args[i]) >> SFILE
+ printf("%smsg->%sdata.%sdata_val", \
sep, args[i], args[i]) >> SFILE
- printf("%sreq->%sdata.%sdata_len", \
+ printf("%smsg->%sdata.%sdata_len", \
sep, args[i], args[i]) >> SFILE
}
sep = ",\n\t ";
@@ -611,12 +532,6 @@ END {
printf("%s&__%s_free);\n", sep, name) >> SFILE
else
printf(");\n\n") >> SFILE
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] == "LIST") {
- printf("\t__db_%s_%sfree(__db_%slist);\n", \
- name, args[i], args[i]) >> SFILE
- }
- }
if (need_out) {
printf("\nout:\n") >> SFILE
}
@@ -624,191 +539,98 @@ END {
printf("}\n\n") >> SFILE
#
- # If we are doing a list, write list functions for this op.
- #
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] != "LIST")
- continue;
- if (list_type[i] != "STRING" && list_type[i] != "INT" &&
- list_type[i] != "ID")
- continue;
- printf("int\n") >> SFILE
- printf("__db_%s_%slist(locp, ppp)\n", name, args[i]) >> SFILE
- printf("\t__%s_%slist *locp;\n", name, args[i]) >> SFILE
- if (list_type[i] == "STRING") {
- printf("\tchar ***ppp;\n{\n") >> SFILE
- printf("\tchar **pp;\n") >> SFILE
- }
- if (list_type[i] == "INT" || list_type[i] == "ID") {
- printf("\tu_int32_t **ppp;\n{\n") >> SFILE
- printf("\tu_int32_t *pp;\n") >> SFILE
- }
- printf("\tint cnt, ret, size;\n") >> SFILE
- printf("\t__%s_%slist *nl;\n\n", name, args[i]) >> SFILE
- printf("\tfor (cnt = 0, nl = locp;") >> SFILE
- printf(" nl != NULL; cnt++, nl = nl->next)\n\t\t;\n\n") >> SFILE
- printf("\tif (cnt == 0) {\n") >> SFILE
- printf("\t\t*ppp = NULL;\n") >> SFILE
- printf("\t\treturn (0);\n\t}\n") >> SFILE
- printf("\tsize = sizeof(*pp) * (cnt + 1);\n") >> SFILE
- printf("\tif ((ret = __os_malloc(NULL, size, ") >> SFILE
- printf("NULL, ppp)) != 0)\n") >> SFILE
- printf("\t\treturn (ret);\n") >> SFILE
- printf("\tmemset(*ppp, 0, size);\n") >> SFILE
- printf("\tfor (pp = *ppp, nl = locp;") >> SFILE
- printf(" nl != NULL; nl = nl->next, pp++) {\n") >> SFILE
- if (list_type[i] == "STRING") {
- printf("\t\tif ((ret = __os_malloc(NULL ,") >> SFILE
- printf("nl->ent.ent_len + 1, NULL, pp)) != 0)\n") \
- >> SFILE
- printf("\t\t\tgoto out;\n") >> SFILE
- printf("\t\tif ((ret = __os_strdup(NULL, ") >> SFILE
- printf("(char *)nl->ent.ent_val, pp)) != 0)\n") >> SFILE
- printf("\t\t\tgoto out;\n") >> SFILE
- }
- if (list_type[i] == "INT" || list_type[i] == "ID")
- printf("\t\t*pp = *(u_int32_t *)nl->ent.ent_val;\n") \
- >> SFILE
- printf("\t}\n") >> SFILE
- printf("\treturn (0);\n") >> SFILE
- if (list_type[i] == "STRING") {
- printf("out:\n") >> SFILE
- printf("\t__db_%s_%sfree(*ppp);\n", \
- name, args[i]) >> SFILE
- printf("\treturn (ret);\n") >> SFILE
- }
- printf("}\n\n") >> SFILE
-
- printf("void\n") >> SFILE
- printf("__db_%s_%sfree(pp)\n", name, args[i]) >> SFILE
-
- if (list_type[i] == "STRING")
- printf("\tchar **pp;\n") >> SFILE
- if (list_type[i] == "INT" || list_type[i] == "ID")
- printf("\tu_int32_t *pp;\n") >> SFILE
-
- printf("{\n") >> SFILE
- printf("\tsize_t size;\n") >> SFILE
-
- if (list_type[i] == "STRING")
- printf("\tchar **p;\n\n") >> SFILE
- if (list_type[i] == "INT" || list_type[i] == "ID")
- printf("\tu_int32_t *p;\n\n") >> SFILE
-
- printf("\tif (pp == NULL)\n\t\treturn;\n") >> SFILE
- printf("\tsize = sizeof(*p);\n") >> SFILE
- printf("\tfor (p = pp; *p != 0; p++) {\n") >> SFILE
- printf("\t\tsize += sizeof(*p);\n") >> SFILE
-
- if (list_type[i] == "STRING")
- printf("\t\t__os_free(*p, strlen(*p)+1);\n") >> SFILE
- printf("\t}\n") >> SFILE
- printf("\t__os_free(pp, size);\n") >> SFILE
- printf("}\n\n") >> SFILE
- }
-
- #
# =====================================================
# Generate Procedure Template Server code
#
# Produce SED file commands if needed at the same time
#
- # Start with PUBLIC prototypes
+ # Spit out comment, prototype, function name and arg list.
#
- printf("void __%s_%d_proc __P((", name, msgid) >> SHFILE
- sep = "";
- argcount = 0;
+ printf("/^\\/\\* BEGIN __%s_proc/,/^\\/\\* END __%s_proc/c\\\n", \
+ name, name) >> SEDFILE
+
+ printf("/* BEGIN __%s_proc */\n", name) >> PFILE
+ printf("/* BEGIN __%s_proc */\\\n", name) >> SEDFILE
+
+ pi = 1;
+ p[pi++] = sprintf("void __%s_proc __P((", name);
+ p[pi++] = "";
for (i = 0; i < nvars; ++i) {
- argcount++;
- split_lines(1);
- if (argcount == 0) {
- sep = "";
- }
if (rpc_type[i] == "IGNORE")
continue;
if (rpc_type[i] == "ID") {
- printf("%slong", sep) >> SHFILE
+ p[pi++] = "long";
+ p[pi++] = ", ";
}
if (rpc_type[i] == "STRING") {
- printf("%schar *", sep) >> SHFILE
+ p[pi++] = "char *";
+ p[pi++] = ", ";
+ }
+ if (rpc_type[i] == "GID") {
+ p[pi++] = "u_int8_t *";
+ p[pi++] = ", ";
}
if (rpc_type[i] == "INT") {
- printf("%su_int32_t", sep) >> SHFILE
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
}
- if (rpc_type[i] == "LIST" && list_type[i] == "STRING") {
- printf("%schar **", sep) >> SHFILE
+ if (rpc_type[i] == "LIST" && list_type[i] == "GID") {
+ p[pi++] = "u_int8_t *";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
}
if (rpc_type[i] == "LIST" && list_type[i] == "INT") {
- printf("%su_int32_t *", sep) >> SHFILE
+ p[pi++] = "u_int32_t *";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
}
if (rpc_type[i] == "LIST" && list_type[i] == "ID") {
- printf("%su_int32_t *", sep) >> SHFILE
+ p[pi++] = "u_int32_t *";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
}
if (rpc_type[i] == "DBT") {
- printf("%su_int32_t", sep) >> SHFILE
- sep = ", ";
- argcount++;
- split_lines(1);
- if (argcount == 0) {
- sep = "";
- } else {
- sep = ", ";
- }
- printf("%su_int32_t", sep) >> SHFILE
- argcount++;
- split_lines(1);
- if (argcount == 0) {
- sep = "";
- } else {
- sep = ", ";
- }
- printf("%su_int32_t", sep) >> SHFILE
- argcount++;
- split_lines(1);
- if (argcount == 0) {
- sep = "";
- } else {
- sep = ", ";
- }
- printf("%svoid *", sep) >> SHFILE
- argcount++;
- split_lines(1);
- if (argcount == 0) {
- sep = "";
- } else {
- sep = ", ";
- }
- printf("%su_int32_t", sep) >> SHFILE
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
+ p[pi++] = "void *";
+ p[pi++] = ", ";
+ p[pi++] = "u_int32_t";
+ p[pi++] = ", ";
}
- sep = ", ";
}
- printf("%s__%s_reply *", sep, name) >> SHFILE
+ p[pi++] = sprintf("__%s_reply *", name);
if (xdr_free) {
- printf("%sint *));\n", sep) >> SHFILE
+ p[pi++] = ", ";
+ p[pi++] = "int *));";
} else {
- printf("));\n") >> SHFILE
+ p[pi++] = "";
+ p[pi++] = "));";
}
- #
- # Spit out function name and arg list
- #
- printf("/^\\/\\* BEGIN __%s_%d_proc/,/^\\/\\* END __%s_%d_proc/c\\\n", \
- name, msgid, name, msgid) >> SEDFILE
+ p[pi++] = "";
+ proto_format(p, 1, SEDFILE);
- printf("/* BEGIN __%s_%d_proc */\n", name, msgid) >> PFILE
- printf("/* BEGIN __%s_%d_proc */\\\n", name, msgid) >> SEDFILE
printf("void\n") >> PFILE
printf("void\\\n") >> SEDFILE
- printf("__%s_%d_proc(", name, msgid) >> PFILE
- printf("__%s_%d_proc(", name, msgid) >> SEDFILE
+ printf("__%s_proc(", name) >> PFILE
+ printf("__%s_proc(", name) >> SEDFILE
sep = "";
argcount = 0;
for (i = 0; i < nvars; ++i) {
argcount++;
- split_lines(0);
+ split_lines();
if (argcount == 0) {
sep = "";
}
- if (rpc_type[i] == "IGNORE")
+ if (rpc_type[i] == "IGNORE")
continue;
if (rpc_type[i] == "ID") {
printf("%s%scl_id", sep, args[i]) >> PFILE
@@ -818,20 +640,33 @@ END {
printf("%s%s", sep, args[i]) >> PFILE
printf("%s%s", sep, args[i]) >> SEDFILE
}
+ if (rpc_type[i] == "GID") {
+ printf("%s%s", sep, args[i]) >> PFILE
+ printf("%s%s", sep, args[i]) >> SEDFILE
+ }
if (rpc_type[i] == "INT") {
printf("%s%s", sep, args[i]) >> PFILE
printf("%s%s", sep, args[i]) >> SEDFILE
}
if (rpc_type[i] == "LIST") {
- printf("%s%slist", sep, args[i]) >> PFILE
- printf("%s%slist", sep, args[i]) >> SEDFILE
+ printf("%s%s", sep, args[i]) >> PFILE
+ printf("%s%s", sep, args[i]) >> SEDFILE
+ argcount++;
+ split_lines();
+ if (argcount == 0) {
+ sep = "";
+ } else {
+ sep = ", ";
+ }
+ printf("%s%slen", sep, args[i]) >> PFILE
+ printf("%s%slen", sep, args[i]) >> SEDFILE
}
if (rpc_type[i] == "DBT") {
printf("%s%sdlen", sep, args[i]) >> PFILE
printf("%s%sdlen", sep, args[i]) >> SEDFILE
sep = ", ";
argcount++;
- split_lines(0);
+ split_lines();
if (argcount == 0) {
sep = "";
} else {
@@ -840,7 +675,16 @@ END {
printf("%s%sdoff", sep, args[i]) >> PFILE
printf("%s%sdoff", sep, args[i]) >> SEDFILE
argcount++;
- split_lines(0);
+ split_lines();
+ if (argcount == 0) {
+ sep = "";
+ } else {
+ sep = ", ";
+ }
+ printf("%s%sulen", sep, args[i]) >> PFILE
+ printf("%s%sulen", sep, args[i]) >> SEDFILE
+ argcount++;
+ split_lines();
if (argcount == 0) {
sep = "";
} else {
@@ -849,7 +693,7 @@ END {
printf("%s%sflags", sep, args[i]) >> PFILE
printf("%s%sflags", sep, args[i]) >> SEDFILE
argcount++;
- split_lines(0);
+ split_lines();
if (argcount == 0) {
sep = "";
} else {
@@ -858,7 +702,7 @@ END {
printf("%s%sdata", sep, args[i]) >> PFILE
printf("%s%sdata", sep, args[i]) >> SEDFILE
argcount++;
- split_lines(0);
+ split_lines();
if (argcount == 0) {
sep = "";
} else {
@@ -890,22 +734,33 @@ END {
printf("\tchar *%s;\n", args[i]) >> PFILE
printf("\\\tchar *%s;\\\n", args[i]) >> SEDFILE
}
+ if (rpc_type[i] == "GID") {
+ printf("\tu_int8_t *%s;\n", args[i]) >> PFILE
+ printf("\\\tu_int8_t *%s;\\\n", args[i]) >> SEDFILE
+ }
if (rpc_type[i] == "INT") {
printf("\tu_int32_t %s;\n", args[i]) >> PFILE
printf("\\\tu_int32_t %s;\\\n", args[i]) >> SEDFILE
}
- if (rpc_type[i] == "LIST" && list_type[i] == "STRING") {
- printf("\tchar ** %slist;\n", args[i]) >> PFILE
- printf("\\\tchar ** %slist;\\\n", args[i]) >> SEDFILE
+ if (rpc_type[i] == "LIST" && list_type[i] == "GID") {
+ printf("\tu_int8_t * %s;\n", args[i]) >> PFILE
+ printf("\\\tu_int8_t * %s;\\\n", args[i]) >> SEDFILE
}
if (rpc_type[i] == "LIST" && list_type[i] == "INT") {
- printf("\tu_int32_t * %slist;\n", args[i]) >> PFILE
- printf("\\\tu_int32_t * %slist;\\\n", \
+ printf("\tu_int32_t * %s;\n", args[i]) >> PFILE
+ printf("\\\tu_int32_t * %s;\\\n", \
args[i]) >> SEDFILE
+ printf("\tu_int32_t %ssize;\n", args[i]) >> PFILE
+ printf("\\\tu_int32_t %ssize;\\\n", args[i]) >> SEDFILE
}
if (rpc_type[i] == "LIST" && list_type[i] == "ID") {
- printf("\tu_int32_t * %slist;\n", args[i]) >> PFILE
- printf("\\\tu_int32_t * %slist;\\\n", args[i]) \
+ printf("\tu_int32_t * %s;\n", args[i]) >> PFILE
+ printf("\\\tu_int32_t * %s;\\\n", args[i]) \
+ >> SEDFILE
+ }
+ if (rpc_type[i] == "LIST") {
+ printf("\tu_int32_t %slen;\n", args[i]) >> PFILE
+ printf("\\\tu_int32_t %slen;\\\n", args[i]) \
>> SEDFILE
}
if (rpc_type[i] == "DBT") {
@@ -913,6 +768,8 @@ END {
printf("\\\tu_int32_t %sdlen;\\\n", args[i]) >> SEDFILE
printf("\tu_int32_t %sdoff;\n", args[i]) >> PFILE
printf("\\\tu_int32_t %sdoff;\\\n", args[i]) >> SEDFILE
+ printf("\tu_int32_t %sulen;\n", args[i]) >> PFILE
+ printf("\\\tu_int32_t %sulen;\\\n", args[i]) >> SEDFILE
printf("\tu_int32_t %sflags;\n", args[i]) >> PFILE
printf("\\\tu_int32_t %sflags;\\\n", args[i]) >> SEDFILE
printf("\tvoid *%sdata;\n", args[i]) >> PFILE
@@ -928,8 +785,8 @@ END {
printf("\\\tint * freep;\\\n") >> SEDFILE
}
- printf("/* END __%s_%d_proc */\n", name, msgid) >> PFILE
- printf("/* END __%s_%d_proc */\n", name, msgid) >> SEDFILE
+ printf("/* END __%s_proc */\n", name) >> PFILE
+ printf("/* END __%s_proc */\n", name) >> SEDFILE
#
# Function body
@@ -957,43 +814,23 @@ END {
printf("}\n\n") >> PFILE
#
- # If we don't want client code generated, go on to next.
- #
- if (gen_code == 0)
- next;
-
- #
# =====================================================
# Generate Client code
#
- # If we are doing a list, spit out prototype decl.
- #
- for (i = 0; i < nvars; i++) {
- if (rpc_type[i] != "LIST")
- continue;
- printf("static int __dbcl_%s_%slist __P((", \
- name, args[i]) >> CFILE
- printf("__%s_%slist **, ", name, args[i]) >> CFILE
- if (list_type[i] == "STRING")
- printf("%s));\n", c_type[i]) >> CFILE
- if (list_type[i] == "INT")
- printf("u_int32_t));\n") >> CFILE
- if (list_type[i] == "ID")
- printf("%s));\n", c_type[i]) >> CFILE
- printf("static void __dbcl_%s_%sfree __P((", \
- name, args[i]) >> CFILE
- printf("__%s_%slist **));\n", name, args[i]) >> CFILE
- }
- #
# Spit out PUBLIC prototypes.
#
- printf("int __dbcl_%s __P((",name) >> CHFILE
- sep = "";
+ pi = 1;
+ p[pi++] = sprintf("int __dbcl_%s __P((", name);
+ p[pi++] = "";
for (i = 0; i < nvars; ++i) {
- printf("%s%s", sep, pr_type[i]) >> CHFILE
- sep = ", ";
+ p[pi++] = pr_type[i];
+ p[pi++] = ", ";
}
- printf("));\n") >> CHFILE
+ p[pi - 1] = "";
+ p[pi++] = "));";
+ p[pi] = "";
+ proto_format(p, 0, CFILE);
+
#
# Spit out function name/args.
#
@@ -1014,16 +851,28 @@ END {
printf("{\n") >> CFILE
printf("\tCLIENT *cl;\n") >> CFILE
- printf("\t__%s_msg req;\n", name) >> CFILE
- printf("\tstatic __%s_reply *replyp = NULL;\n", name) >> CFILE;
+ printf("\t__%s_msg msg;\n", name) >> CFILE
+ printf("\t__%s_reply *replyp = NULL;\n", name) >> CFILE;
printf("\tint ret;\n") >> CFILE
if (!env_handle)
printf("\tDB_ENV *dbenv;\n") >> CFILE
+ #
+ # If we are managing a list, we need a few more vars.
+ #
+ for (i = 0; i < nvars; ++i) {
+ if (rpc_type[i] == "LIST") {
+ printf("\t%s %sp;\n", c_type[i], args[i]) >> CFILE
+ printf("\tint %si;\n", args[i]) >> CFILE
+ if (list_type[i] == "GID")
+ printf("\tu_int8_t ** %sq;\n", args[i]) >> CFILE
+ else
+ printf("\tu_int32_t * %sq;\n", args[i]) >> CFILE
+ }
+ }
printf("\n") >> CFILE
printf("\tret = 0;\n") >> CFILE
if (!env_handle) {
- printf("\tdbenv = NULL;\n") >> CFILE
if (db_handle)
printf("\tdbenv = %s->dbenv;\n", args[db_idx]) >> CFILE
else if (dbc_handle)
@@ -1032,27 +881,19 @@ END {
else if (txn_handle)
printf("\tdbenv = %s->mgrp->dbenv;\n", \
args[txn_idx]) >> CFILE
- printf("\tif (dbenv == NULL || dbenv->cl_handle == NULL) {\n") \
- >> CFILE
- printf("\t\t__db_err(dbenv, \"No server environment.\");\n") \
+ else
+ printf("\tdbenv = NULL;\n") >> CFILE
+ printf("\tif (dbenv == NULL || !RPC_ON(dbenv))\n") \
>> CFILE
+ printf("\t\treturn (__dbcl_noserver(NULL));\n") >> CFILE
} else {
- printf("\tif (%s == NULL || %s->cl_handle == NULL) {\n", \
+ printf("\tif (%s == NULL || !RPC_ON(%s))\n", \
args[env_idx], args[env_idx]) >> CFILE
- printf("\t\t__db_err(%s, \"No server environment.\");\n", \
+ printf("\t\treturn (__dbcl_noserver(%s));\n", \
args[env_idx]) >> CFILE
}
- printf("\t\treturn (DB_NOSERVER);\n") >> CFILE
- printf("\t}\n") >> CFILE
printf("\n") >> CFILE
- #
- # Free old reply if there was one.
- #
- printf("\tif (replyp != NULL) {\n") >> CFILE
- printf("\t\txdr_free((xdrproc_t)xdr___%s_reply, (void *)replyp);\n", \
- name) >> CFILE
- printf("\t\treplyp = NULL;\n\t}\n") >> CFILE
if (!env_handle)
printf("\tcl = (CLIENT *)dbenv->cl_handle;\n") >> CFILE
else
@@ -1068,8 +909,12 @@ END {
if (func_arg[i] != 1)
continue;
printf("\tif (%s != NULL) {\n", args[i]) >> CFILE
- printf("\t\t__db_err(%s, ", args[env_idx]) >> CFILE
- printf("\"User functions not supported in RPC.\");\n") >> CFILE
+ if (!env_handle) {
+ printf("\t\t__db_err(dbenv, ") >> CFILE
+ } else {
+ printf("\t\t__db_err(%s, ", args[env_idx]) >> CFILE
+ }
+ printf("\"User functions not supported in RPC\");\n") >> CFILE
printf("\t\treturn (EINVAL);\n\t}\n") >> CFILE
}
@@ -1079,49 +924,102 @@ END {
for (i = 0; i < nvars; ++i) {
if (rpc_type[i] == "ID") {
printf("\tif (%s == NULL)\n", args[i]) >> CFILE
- printf("\t\treq.%scl_id = 0;\n\telse\n", \
+ printf("\t\tmsg.%scl_id = 0;\n\telse\n", \
args[i]) >> CFILE
if (c_type[i] == "DB_TXN *") {
- printf("\t\treq.%scl_id = %s->txnid;\n", \
+ printf("\t\tmsg.%scl_id = %s->txnid;\n", \
args[i], args[i]) >> CFILE
} else {
- printf("\t\treq.%scl_id = %s->cl_id;\n", \
+ printf("\t\tmsg.%scl_id = %s->cl_id;\n", \
args[i], args[i]) >> CFILE
}
}
+ if (rpc_type[i] == "GID") {
+ printf("\tmemcpy(msg.%s, %s, %d);\n", \
+ args[i], args[i], xidsize) >> CFILE
+ }
if (rpc_type[i] == "INT") {
- printf("\treq.%s = %s;\n", args[i], args[i]) >> CFILE
+ printf("\tmsg.%s = %s;\n", args[i], args[i]) >> CFILE
}
if (rpc_type[i] == "STRING") {
printf("\tif (%s == NULL)\n", args[i]) >> CFILE
- printf("\t\treq.%s = \"\";\n", args[i]) >> CFILE
+ printf("\t\tmsg.%s = \"\";\n", args[i]) >> CFILE
printf("\telse\n") >> CFILE
- printf("\t\treq.%s = (char *)%s;\n", \
+ printf("\t\tmsg.%s = (char *)%s;\n", \
args[i], args[i]) >> CFILE
}
if (rpc_type[i] == "DBT") {
- printf("\treq.%sdlen = %s->dlen;\n", \
+ printf("\tmsg.%sdlen = %s->dlen;\n", \
+ args[i], args[i]) >> CFILE
+ printf("\tmsg.%sdoff = %s->doff;\n", \
args[i], args[i]) >> CFILE
- printf("\treq.%sdoff = %s->doff;\n", \
+ printf("\tmsg.%sulen = %s->ulen;\n", \
args[i], args[i]) >> CFILE
- printf("\treq.%sflags = %s->flags;\n", \
+ printf("\tmsg.%sflags = %s->flags;\n", \
args[i], args[i]) >> CFILE
- printf("\treq.%sdata.%sdata_val = %s->data;\n", \
+ printf("\tmsg.%sdata.%sdata_val = %s->data;\n", \
args[i], args[i], args[i]) >> CFILE
- printf("\treq.%sdata.%sdata_len = %s->size;\n", \
+ printf("\tmsg.%sdata.%sdata_len = %s->size;\n", \
args[i], args[i], args[i]) >> CFILE
}
if (rpc_type[i] == "LIST") {
- printf("\tif ((ret = __dbcl_%s_%slist(", \
- name, args[i]) >> CFILE
- printf("&req.%slist, %s)) != 0)\n", \
+ printf("\tfor (%si = 0, %sp = %s; *%sp != 0; ", \
+ args[i], args[i], args[i], args[i]) >> CFILE
+ printf(" %si++, %sp++)\n\t\t;\n", args[i], args[i]) \
+ >> CFILE
+
+ #
+ # If we are an array of ints, *_len is how many
+ # elements. If we are a GID, *_len is total bytes.
+ #
+ printf("\tmsg.%s.%s_len = %si",args[i], args[i], \
+ args[i]) >> CFILE
+ if (list_type[i] == "GID")
+ printf(" * %d;\n", xidsize) >> CFILE
+ else
+ printf(";\n") >> CFILE
+ printf("\tif ((ret = __os_calloc(") >> CFILE
+ if (!env_handle)
+ printf("dbenv,\n") >> CFILE
+ else
+ printf("%s,\n", args[env_idx]) >> CFILE
+ printf("\t msg.%s.%s_len,", \
+ args[i], args[i]) >> CFILE
+ if (list_type[i] == "GID")
+ printf(" 1,") >> CFILE
+ else
+ printf(" sizeof(u_int32_t),") >> CFILE
+ printf(" &msg.%s.%s_val)) != 0)\n",\
+ args[i], args[i], args[i], args[i]) >> CFILE
+ printf("\t\treturn (ret);\n") >> CFILE
+ printf("\tfor (%sq = msg.%s.%s_val, %sp = %s; ", \
+ args[i], args[i], args[i], \
args[i], args[i]) >> CFILE
- printf("\t\tgoto out;\n") >> CFILE
+ printf("%si--; %sq++, %sp++)\n", \
+ args[i], args[i], args[i]) >> CFILE
+ printf("\t\t*%sq = ", args[i]) >> CFILE
+ if (list_type[i] == "GID")
+ printf("*%sp;\n", args[i]) >> CFILE
+ if (list_type[i] == "ID")
+ printf("(*%sp)->cl_id;\n", args[i]) >> CFILE
+ if (list_type[i] == "INT")
+ printf("*%sp;\n", args[i]) >> CFILE
}
}
printf("\n") >> CFILE
- printf("\treplyp = __db_%s_%d(&req, cl);\n", name, msgid) >> CFILE
+ printf("\treplyp = __db_%s_%d%03d(&msg, cl);\n", name, major, minor) \
+ >> CFILE
+ for (i = 0; i < nvars; ++i) {
+ if (rpc_type[i] == "LIST") {
+ printf("\t__os_free(") >> CFILE
+ if (!env_handle)
+ printf("dbenv, ") >> CFILE
+ else
+ printf("%s, ", args[env_idx]) >> CFILE
+ printf("msg.%s.%s_val);\n", args[i], args[i]) >> CFILE
+ }
+ }
printf("\tif (replyp == NULL) {\n") >> CFILE
if (!env_handle) {
printf("\t\t__db_err(dbenv, ") >> CFILE
@@ -1137,112 +1035,24 @@ END {
if (ret_code == 0) {
printf("\tret = replyp->status;\n") >> CFILE
} else {
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] == "LIST") {
- printf("\t__dbcl_%s_%sfree(&req.%slist);\n", \
- name, args[i], args[i]) >> CFILE
- }
- }
- printf("\treturn (__dbcl_%s_ret(", name) >> CFILE
+ printf("\tret = __dbcl_%s_ret(", name) >> CFILE
sep = "";
for (i = 0; i < nvars; ++i) {
printf("%s%s", sep, args[i]) >> CFILE
sep = ", ";
}
- printf("%sreplyp));\n", sep) >> CFILE
+ printf("%sreplyp);\n", sep) >> CFILE
}
printf("out:\n") >> CFILE
- for (i = 0; i < nvars; ++i) {
- if (rpc_type[i] == "LIST") {
- printf("\t__dbcl_%s_%sfree(&req.%slist);\n", \
- name, args[i], args[i]) >> CFILE
- }
- }
- printf("\treturn (ret);\n") >> CFILE
- printf("}\n\n") >> CFILE
-
#
- # If we are doing a list, write list functions for op.
+ # Free reply if there was one.
#
- for (i = 0; i < nvars; i++) {
- if (rpc_type[i] != "LIST")
- continue;
- printf("int\n__dbcl_%s_%slist(locp, pp)\n", \
- name, args[i]) >> CFILE
- printf("\t__%s_%slist **locp;\n", name, args[i]) >> CFILE
- if (list_type[i] == "STRING")
- printf("\t%s pp;\n{\n\t%s p;\n", \
- c_type[i], c_type[i]) >> CFILE
- if (list_type[i] == "INT")
- printf("\tu_int32_t *pp;\n{\n\tu_int32_t *p, *q;\n") \
- >> CFILE
- if (list_type[i] == "ID")
- printf("\t%s pp;\n{\n\t%s p;\n\tu_int32_t *q;\n", \
- c_type[i], c_type[i]) >> CFILE
-
- printf("\tint ret;\n") >> CFILE
- printf("\t__%s_%slist *nl, **nlp;\n\n", name, args[i]) >> CFILE
- printf("\t*locp = NULL;\n") >> CFILE
- printf("\tif (pp == NULL)\n\t\treturn (0);\n") >> CFILE
- printf("\tnlp = locp;\n") >> CFILE
- printf("\tfor (p = pp; *p != 0; p++) {\n") >> CFILE
- printf("\t\tif ((ret = __os_malloc(NULL, ") >> CFILE
- printf("sizeof(*nl), NULL, nlp)) != 0)\n") >> CFILE
- printf("\t\t\tgoto out;\n") >> CFILE
- printf("\t\tnl = *nlp;\n") >> CFILE
- printf("\t\tnl->next = NULL;\n") >> CFILE
- printf("\t\tnl->ent.ent_val = NULL;\n") >> CFILE
- printf("\t\tnl->ent.ent_len = 0;\n") >> CFILE
- if (list_type[i] == "STRING") {
- printf("\t\tif ((ret = __os_strdup(NULL, ") >> CFILE
- printf("*p, &nl->ent.ent_val)) != 0)\n") >> CFILE
- printf("\t\t\tgoto out;\n") >> CFILE
- printf("\t\tnl->ent.ent_len = strlen(*p)+1;\n") >> CFILE
- }
- if (list_type[i] == "INT") {
- printf("\t\tif ((ret = __os_malloc(NULL, ") >> CFILE
- printf("sizeof(%s), NULL, &nl->ent.ent_val)) != 0)\n", \
- c_type[i]) >> CFILE
- printf("\t\t\tgoto out;\n") >> CFILE
- printf("\t\tq = (u_int32_t *)nl->ent.ent_val;\n") \
- >> CFILE
- printf("\t\t*q = *p;\n") >> CFILE
- printf("\t\tnl->ent.ent_len = sizeof(%s);\n", \
- c_type[i]) >> CFILE
- }
- if (list_type[i] == "ID") {
- printf("\t\tif ((ret = __os_malloc(NULL, ") >> CFILE
- printf("sizeof(u_int32_t),") >> CFILE
- printf(" NULL, &nl->ent.ent_val)) != 0)\n") >> CFILE
- printf("\t\t\tgoto out;\n") >> CFILE
- printf("\t\tq = (u_int32_t *)nl->ent.ent_val;\n") \
- >> CFILE
- printf("\t\t*q = (*p)->cl_id;\n") >> CFILE
- printf("\t\tnl->ent.ent_len = sizeof(u_int32_t);\n") \
- >> CFILE
- }
- printf("\t\tnlp = &nl->next;\n") >> CFILE
- printf("\t}\n") >> CFILE
- printf("\treturn (0);\n") >> CFILE
- printf("out:\n") >> CFILE
- printf("\t__dbcl_%s_%sfree(locp);\n", name, args[i]) >> CFILE
- printf("\treturn (ret);\n") >> CFILE
-
- printf("}\n\n") >> CFILE
+ printf("\tif (replyp != NULL)\n") >> CFILE
+ printf("\t\txdr_free((xdrproc_t)xdr___%s_reply,",name) >> CFILE
+ printf(" (void *)replyp);\n") >> CFILE
+ printf("\treturn (ret);\n") >> CFILE
+ printf("}\n\n") >> CFILE
- printf("void\n__dbcl_%s_%sfree(locp)\n", name, args[i]) >> CFILE
- printf("\t__%s_%slist **locp;\n", name, args[i]) >> CFILE
- printf("{\n") >> CFILE
- printf("\t__%s_%slist *nl, *nl1;\n\n", name, args[i]) >> CFILE
- printf("\tif (locp == NULL)\n\t\treturn;\n") >> CFILE
- printf("\tfor (nl = *locp; nl != NULL; nl = nl1) {\n") >> CFILE
- printf("\t\tnl1 = nl->next;\n") >> CFILE
- printf("\t\tif (nl->ent.ent_val)\n") >> CFILE
- printf("\t\t\t__os_free(nl->ent.ent_val, nl->ent.ent_len);\n") \
- >> CFILE
- printf("\t\t__os_free(nl, sizeof(*nl));\n") >> CFILE
- printf("\t}\n}\n\n") >> CFILE
- }
#
# Generate Client Template code
#
@@ -1250,38 +1060,16 @@ END {
#
# If we are doing a list, write prototypes
#
- for (i = 0; i < rvars; ++i) {
- if (ret_type[i] != "LIST")
- continue;
- if (retlist_type[i] != "STRING" &&
- retlist_type[i] != "INT" && list_type[i] != "ID")
- continue;
- printf("int __db_%s_%sreplist __P((", \
- name, retargs[i]) >> TFILE
- printf("__%s_%sreplist, ", \
- name, retargs[i]) >> TFILE
- if (retlist_type[i] == "STRING") {
- printf("char ***));\n") >> TFILE
- }
- if (retlist_type[i] == "INT" ||
- retlist_type[i] == "ID") {
- printf("u_int32_t **));\n") >> TFILE
- }
- printf("void __db_%s_%sfree __P((", \
- name, retargs[i]) >> TFILE
- if (retlist_type[i] == "STRING")
- printf("char **));\n") >> TFILE
- if (retlist_type[i] == "INT" || retlist_type[i] == "ID")
- printf("u_int32_t *));\n\n") >> TFILE
- }
-
- printf("int __dbcl_%s_ret __P((", name) >> CHFILE
- sep = "";
+ pi = 1;
+ p[pi++] = sprintf("int __dbcl_%s_ret __P((", name);
+ p[pi++] = "";
for (i = 0; i < nvars; ++i) {
- printf("%s%s", sep, pr_type[i]) >> CHFILE
- sep = ", ";
+ p[pi++] = pr_type[i];
+ p[pi++] = ", ";
}
- printf("%s__%s_reply *));\n", sep, name) >> CHFILE
+ p[pi++] = sprintf("__%s_reply *));", name);
+ p[pi++] = "";
+ proto_format(p, 0, TFILE);
printf("int\n") >> TFILE
printf("__dbcl_%s_ret(", name) >> TFILE
@@ -1310,12 +1098,12 @@ END {
printf("\t%s %s;\n", \
retc_type[i], retargs[i]) >> TFILE
} else if (ret_type[i] == "LIST") {
- if (retlist_type[i] == "STRING")
- printf("\tchar **__db_%slist;\n", \
+ if (retlist_type[i] == "GID")
+ printf("\tu_int8_t *__db_%s;\n", \
retargs[i]) >> TFILE
if (retlist_type[i] == "ID" ||
retlist_type[i] == "INT")
- printf("\tu_int32_t *__db_%slist;\n", \
+ printf("\tu_int32_t *__db_%s;\n", \
retargs[i]) >> TFILE
} else {
printf("\t/* %s %s; */\n", \
@@ -1347,16 +1135,9 @@ END {
printf("\t%s = replyp->%s;\n", \
retargs[i], varname) >> TFILE
} else if (ret_type[i] == "LIST") {
- printf("\n\tif ((ret = __db_%s_%slist(", \
- name, retargs[i]) >> TFILE
- printf("replyp->%slist, &__db_%slist)) != 0)", \
- retargs[i], retargs[i]) >> TFILE
- printf("\n\t\treturn (ret);\n") >> TFILE
printf("\n\t/*\n") >> TFILE
printf("\t * XXX Handle list\n") >> TFILE
printf("\t */\n\n") >> TFILE
- printf("\t__db_%s_%sfree(__db_%slist);\n", \
- name, retargs[i], retargs[i]) >> TFILE
} else {
printf("\t/* Handle replyp->%s; */\n", \
varname) >> TFILE
@@ -1365,118 +1146,69 @@ END {
printf("\n\t/*\n\t * XXX Code goes here\n\t */\n\n") >> TFILE
printf("\treturn (replyp->status);\n") >> TFILE
printf("}\n\n") >> TFILE
- #
- # If we are doing a list, write list functions for this op.
- #
- for (i = 0; i < rvars; ++i) {
- if (ret_type[i] != "LIST")
- continue;
- if (retlist_type[i] != "STRING" &&
- retlist_type[i] != "INT" && list_type[i] != "ID")
- continue;
- printf("int\n") >> TFILE
- printf("__db_%s_%sreplist(locp, ppp)\n", \
- name, retargs[i]) >> TFILE
- printf("\t__%s_%sreplist *locp;\n", \
- name, retargs[i]) >> TFILE
- if (retlist_type[i] == "STRING") {
- printf("\tchar ***ppp;\n{\n") >> TFILE
- printf("\tchar **pp;\n") >> TFILE
- }
- if (retlist_type[i] == "INT" ||
- retlist_type[i] == "ID") {
- printf("\tu_int32_t **ppp;\n{\n") >> TFILE
- printf("\tu_int32_t *pp;\n") >> TFILE
- }
-
- printf("\tint cnt, ret, size;\n") >> TFILE
- printf("\t__%s_%sreplist *nl;\n\n", \
- name, retargs[i]) >> TFILE
- printf("\tfor (cnt = 0, nl = locp; ") >> TFILE
- printf("nl != NULL; cnt++, nl = nl->next)\n\t\t;\n\n") \
- >> TFILE
- printf("\tif (cnt == 0) {\n") >> TFILE
- printf("\t\t*ppp = NULL;\n") >> TFILE
- printf("\t\treturn (0);\n\t}\n") >> TFILE
- printf("\tsize = sizeof(*pp) * cnt;\n") >> TFILE
- printf("\tif ((ret = __os_malloc(NULL, ") >> TFILE
- printf("size, NULL, ppp)) != 0)\n") >> TFILE
- printf("\t\treturn (ret);\n") >> TFILE
- printf("\tmemset(*ppp, 0, size);\n") >> TFILE
- printf("\tfor (pp = *ppp, nl = locp; ") >> TFILE
- printf("nl != NULL; nl = nl->next, pp++) {\n") >> TFILE
- if (retlist_type[i] == "STRING") {
- printf("\t\tif ((ret = __os_malloc(NULL, ") \
- >> TFILE
- printf("nl->ent.ent_len + 1, NULL,") >> TFILE
- printf(" pp)) != 0)\n") >> TFILE
- printf("\t\t\tgoto out;\n") >> TFILE
- printf("\t\tif ((ret = __os_strdup(") >> TFILE
- printf("NULL, (char *)nl->ent.ent_val,") \
- >> TFILE
- printf(" pp)) != 0)\n") >> TFILE
- printf("\t\t\tgoto out;\n") >> TFILE
- }
- if (retlist_type[i] == "INT" ||
- retlist_type[i] == "ID") {
- printf("\t\t*pp = *(u_int32_t *)") >> TFILE
- printf("nl->ent.ent_val;\n") >> TFILE
- }
- printf("\t}\n") >> TFILE
- printf("\treturn (0);\n") >> TFILE
- printf("out:\n") >> TFILE
- printf("\t__db_%s_%sfree(*ppp);\n", \
- name, retargs[i]) >> TFILE
- printf("\treturn (ret);\n") >> TFILE
- printf("}\n\n") >> TFILE
-
- printf("void\n") >> TFILE
- printf("__db_%s_%sfree(pp)\n", \
- name, retargs[i]) >> TFILE
-
- if (retlist_type[i] == "STRING")
- printf("\tchar **pp;\n") >> TFILE
- if (retlist_type[i] == "INT" || retlist_type[i] == "ID")
- printf("\tu_int32_t *pp;\n") >> TFILE
-
- printf("{\n") >> TFILE
- printf("\tsize_t size;\n") >> TFILE
-
- if (retlist_type[i] == "STRING")
- printf("\tchar **p;\n\n") >> TFILE
- if (retlist_type[i] == "INT" || retlist_type[i] == "ID")
- printf("\tu_int32_t *p;\n\n") >> TFILE
-
- printf("\tif (pp == NULL)\n\t\treturn;\n") >> TFILE
- printf("\tsize = sizeof(*p);\n") >> TFILE
- printf("\tfor (p = pp; *p != 0; p++) {\n") >> TFILE
- printf("\t\tsize += sizeof(*p);\n") >> TFILE
-
- if (retlist_type[i] == "STRING")
- printf("\t\t__os_free(*p, strlen(*p)+1);\n") \
- >> TFILE
- printf("\t}\n") >> TFILE
- printf("\t__os_free(pp, size);\n") >> TFILE
- printf("}\n\n") >> TFILE
- }
}
}
#
# split_lines --
# Add line separators to pretty-print the output.
-function split_lines(is_public) {
+function split_lines() {
if (argcount > 3) {
# Reset the counter, remove any trailing whitespace from
# the separator.
argcount = 0;
sub("[ ]$", "", sep)
- if (is_public) {
- printf("%s\n\t", sep) >> SHFILE
- } else {
- printf("%s\n\t\t", sep) >> PFILE
- printf("%s\\\n\\\t\\\t", sep) >> SEDFILE
+ printf("%s\n\t\t", sep) >> PFILE
+ printf("%s\\\n\\\t\\\t", sep) >> SEDFILE
+ }
+}
+
+# proto_format --
+# Pretty-print a function prototype.
+function proto_format(p, sedfile, OUTPUT)
+{
+ if (sedfile)
+ printf("/*\\\n") >> OUTPUT;
+ else
+ printf("/*\n") >> OUTPUT;
+
+ s = "";
+ for (i = 1; i in p; ++i)
+ s = s p[i];
+
+ if (sedfile)
+ t = "\\ * PUBLIC: "
+ else
+ t = " * PUBLIC: "
+ if (length(s) + length(t) < 80)
+ if (sedfile)
+ printf("%s%s", t, s) >> OUTPUT;
+ else
+ printf("%s%s", t, s) >> OUTPUT;
+ else {
+ split(s, p, "__P");
+ len = length(t) + length(p[1]);
+ printf("%s%s", t, p[1]) >> OUTPUT
+
+ n = split(p[2], comma, ",");
+ comma[1] = "__P" comma[1];
+ for (i = 1; i <= n; i++) {
+ if (len + length(comma[i]) > 75) {
+ if (sedfile)
+ printf(\
+ "\\\n\\ * PUBLIC: ") >> OUTPUT;
+ else
+ printf("\n * PUBLIC: ") >> OUTPUT;
+ len = 0;
+ }
+ printf("%s%s", comma[i], i == n ? "" : ",") >> OUTPUT;
+ len += length(comma[i]);
}
}
+ if (sedfile)
+ printf("\\\n\\ */\\\n") >> OUTPUT;
+ else
+ printf("\n */\n") >> OUTPUT;
+ delete p;
}
diff --git a/bdb/dist/install-sh b/bdb/dist/install-sh
new file mode 100755
index 00000000000..b41a2459161
--- /dev/null
+++ b/bdb/dist/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=$mkdirprog
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+ '
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/bdb/dist/ltconfig b/bdb/dist/ltconfig
deleted file mode 100644
index f78afda0e1f..00000000000
--- a/bdb/dist/ltconfig
+++ /dev/null
@@ -1,3136 +0,0 @@
-#! /bin/sh
-
-# ltconfig - Create a system-specific libtool.
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# 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 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# 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.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A lot of this script is taken from autoconf-2.10.
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-echo=echo
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell.
- exec "$SHELL" "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit 0
-fi
-
-# Find the correct PATH separator. Usually this is `:', but
-# DJGPP uses `;' like DOS.
-if test "X${PATH_SEPARATOR+set}" != Xset; then
- UNAME=${UNAME-`uname 2>/dev/null`}
- case X$UNAME in
- *-DOS) PATH_SEPARATOR=';' ;;
- *) PATH_SEPARATOR=':' ;;
- esac
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-if test "X${echo_test_string+set}" != Xset; then
- # find a string as large as possible, as long as the shell can cope with it
- for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
- # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
- if (echo_test_string="`eval $cmd`") 2>/dev/null &&
- echo_test_string="`eval $cmd`" &&
- (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
- break
- fi
- done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
- test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
- # The Solaris, AIX, and Digital Unix default echo programs unquote
- # backslashes. This makes it impossible to quote backslashes using
- # echo "$something" | sed 's/\\/\\\\/g'
- #
- # So, first we look for a working echo in the user's PATH.
-
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for dir in $PATH /usr/ucb; do
- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- echo="$dir/echo"
- break
- fi
- done
- IFS="$save_ifs"
-
- if test "X$echo" = Xecho; then
- # We didn't find a better echo, so look for alternatives.
- if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
- test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- # This shell has a builtin print -r that does the trick.
- echo='print -r'
- elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
- test "X$CONFIG_SHELL" != X/bin/ksh; then
- # If we have ksh, try running ltconfig again with it.
- ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
- export ORIGINAL_CONFIG_SHELL
- CONFIG_SHELL=/bin/ksh
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
- else
- # Try using printf.
- echo='printf "%s\n"'
- if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- # Cool, printf works
- :
- elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
- export CONFIG_SHELL
- SHELL="$CONFIG_SHELL"
- export SHELL
- echo="$CONFIG_SHELL $0 --fallback-echo"
- elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- echo="$CONFIG_SHELL $0 --fallback-echo"
- else
- # maybe with a smaller string...
- prev=:
-
- for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
- if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
- break
- fi
- prev="$cmd"
- done
-
- if test "$prev" != 'sed 50q "$0"'; then
- echo_test_string=`eval $prev`
- export echo_test_string
- exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
- else
- # Oops. We lost completely, so just stick with echo.
- echo=echo
- fi
- fi
- fi
- fi
-fi
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e s/^X//'
-sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# The name of this program.
-progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
-
-# Constants:
-PROGRAM=ltconfig
-PACKAGE=libtool
-VERSION=1.3.5
-TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)"
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-rm="rm -f"
-
-help="Try \`$progname --help' for more information."
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-enable_shared=yes
-# All known linkers require a `.a' archive for static linking (except M$VC,
-# which needs '.lib').
-enable_static=yes
-enable_fast_install=yes
-enable_dlopen=unknown
-enable_win32_dll=no
-ltmain=
-silent=
-srcdir=
-ac_config_guess=
-ac_config_sub=
-host=
-nonopt=
-ofile="$default_ofile"
-verify_host=yes
-with_gcc=no
-with_gnu_ld=no
-need_locks=yes
-ac_ext=c
-objext=o
-libext=a
-exeext=
-cache_file=
-
-old_AR="$AR"
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-old_CPPFLAGS="$CPPFLAGS"
-old_LDFLAGS="$LDFLAGS"
-old_LD="$LD"
-old_LN_S="$LN_S"
-old_LIBS="$LIBS"
-old_NM="$NM"
-old_RANLIB="$RANLIB"
-old_DLLTOOL="$DLLTOOL"
-old_OBJDUMP="$OBJDUMP"
-old_AS="$AS"
-
-# Parse the command line options.
-args=
-prev=
-for option
-do
- case "$option" in
- -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- eval "$prev=\$option"
- prev=
- continue
- fi
-
- case "$option" in
- --help) cat <<EOM
-Usage: $progname [OPTION]... [HOST [LTMAIN]]
-
-Generate a system-specific libtool script.
-
- --debug enable verbose shell tracing
- --disable-shared do not build shared libraries
- --disable-static do not build static libraries
- --disable-fast-install do not optimize for fast installation
- --enable-dlopen enable dlopen support
- --enable-win32-dll enable building dlls on win32 hosts
- --help display this help and exit
- --no-verify do not verify that HOST is a valid host type
--o, --output=FILE specify the output file [default=$default_ofile]
- --quiet same as \`--silent'
- --silent do not print informational messages
- --srcdir=DIR find \`config.guess' in DIR
- --version output version information and exit
- --with-gcc assume that the GNU C compiler will be used
- --with-gnu-ld assume that the C compiler uses the GNU linker
- --disable-lock disable file locking
- --cache-file=FILE configure cache file
-
-LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
-that provides basic libtool functionality.
-
-HOST is the canonical host system name [default=guessed].
-EOM
- exit 0
- ;;
-
- --debug)
- echo "$progname: enabling shell trace mode"
- set -x
- ;;
-
- --disable-shared) enable_shared=no ;;
-
- --disable-static) enable_static=no ;;
-
- --disable-fast-install) enable_fast_install=no ;;
-
- --enable-dlopen) enable_dlopen=yes ;;
-
- --enable-win32-dll) enable_win32_dll=yes ;;
-
- --quiet | --silent) silent=yes ;;
-
- --srcdir) prev=srcdir ;;
- --srcdir=*) srcdir="$optarg" ;;
-
- --no-verify) verify_host=no ;;
-
- --output | -o) prev=ofile ;;
- --output=*) ofile="$optarg" ;;
-
- --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
-
- --with-gcc) with_gcc=yes ;;
- --with-gnu-ld) with_gnu_ld=yes ;;
-
- --disable-lock) need_locks=no ;;
-
- --cache-file=*) cache_file="$optarg" ;;
-
- -*)
- echo "$progname: unrecognized option \`$option'" 1>&2
- echo "$help" 1>&2
- exit 1
- ;;
-
- *)
- if test -z "$ltmain"; then
- ltmain="$option"
- elif test -z "$host"; then
-# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
-# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
-# echo "$progname: warning \`$option' is not a valid host type" 1>&2
-# fi
- host="$option"
- else
- echo "$progname: too many arguments" 1>&2
- echo "$help" 1>&2
- exit 1
- fi ;;
- esac
-done
-
-if test -z "$ltmain"; then
- echo "$progname: you must specify a LTMAIN file" 1>&2
- echo "$help" 1>&2
- exit 1
-fi
-
-if test ! -f "$ltmain"; then
- echo "$progname: \`$ltmain' does not exist" 1>&2
- echo "$help" 1>&2
- exit 1
-fi
-
-# Quote any args containing shell metacharacters.
-ltconfig_args=
-for arg
-do
- case "$arg" in
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ltconfig_args="$ltconfig_args '$arg'" ;;
- *) ltconfig_args="$ltconfig_args $arg" ;;
- esac
-done
-
-# A relevant subset of AC_INIT.
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 5 compiler messages saved in config.log
-# 6 checking for... messages and results
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>>./config.log
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi
-if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi
-
-if test -n "$cache_file" && test -r "$cache_file"; then
- echo "loading cache $cache_file within ltconfig"
- . $cache_file
-fi
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-if test -z "$srcdir"; then
- # Assume the source directory is the same one as the path to LTMAIN.
- srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
- test "$srcdir" = "$ltmain" && srcdir=.
-fi
-
-trap "$rm conftest*; exit 1" 1 2 15
-if test "$verify_host" = yes; then
- # Check for config.guess and config.sub.
- ac_aux_dir=
- for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/config.guess; then
- ac_aux_dir=$ac_dir
- break
- fi
- done
- if test -z "$ac_aux_dir"; then
- echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
- echo "$help" 1>&2
- exit 1
- fi
- ac_config_guess=$ac_aux_dir/config.guess
- ac_config_sub=$ac_aux_dir/config.sub
-
- # Make sure we can run config.sub.
- if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
- else
- echo "$progname: cannot run $ac_config_sub" 1>&2
- echo "$help" 1>&2
- exit 1
- fi
-
- echo $ac_n "checking host system type""... $ac_c" 1>&6
-
- host_alias=$host
- case "$host_alias" in
- "")
- if host_alias=`$SHELL $ac_config_guess`; then :
- else
- echo "$progname: cannot guess host type; you must specify one" 1>&2
- echo "$help" 1>&2
- exit 1
- fi ;;
- esac
- host=`$SHELL $ac_config_sub $host_alias`
- echo "$ac_t$host" 1>&6
-
- # Make sure the host verified.
- test -z "$host" && exit 1
-
-elif test -z "$host"; then
- echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
- echo "$help" 1>&2
- exit 1
-else
- host_alias=$host
-fi
-
-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
-case "$host_os" in
-linux-gnu*) ;;
-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
-esac
-
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-case "$host_os" in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR cru $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-# Set a sane default for `AR'.
-test -z "$AR" && AR=ar
-
-# Set a sane default for `OBJDUMP'.
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-# If RANLIB is not set, then run the test.
-if test "${RANLIB+set}" != "set"; then
- result=no
-
- echo $ac_n "checking for ranlib... $ac_c" 1>&6
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for dir in $PATH; do
- test -z "$dir" && dir=.
- if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
- RANLIB="ranlib"
- result="ranlib"
- break
- fi
- done
- IFS="$save_ifs"
-
- echo "$ac_t$result" 1>&6
-fi
-
-if test -n "$RANLIB"; then
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
- old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
-fi
-
-# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$AS" && AS=as
-
-# Check to see if we are using GCC.
-if test "$with_gcc" != yes || test -z "$CC"; then
- # If CC is not set, then try to find GCC or a usable CC.
- if test -z "$CC"; then
- echo $ac_n "checking for gcc... $ac_c" 1>&6
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for dir in $PATH; do
- test -z "$dir" && dir=.
- if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
- CC="gcc"
- break
- fi
- done
- IFS="$save_ifs"
-
- if test -n "$CC"; then
- echo "$ac_t$CC" 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
- fi
-
- # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
- if test -z "$CC"; then
- echo $ac_n "checking for cc... $ac_c" 1>&6
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- cc_rejected=no
- for dir in $PATH; do
- test -z "$dir" && dir=.
- if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
- if test "$dir/cc" = "/usr/ucb/cc"; then
- cc_rejected=yes
- continue
- fi
- CC="cc"
- break
- fi
- done
- IFS="$save_ifs"
- if test $cc_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same name, so the bogon will be chosen
- # first if we set CC to just the name; use the full file name.
- shift
- set dummy "$dir/cc" "$@"
- shift
- CC="$@"
- fi
- fi
-
- if test -n "$CC"; then
- echo "$ac_t$CC" 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
-
- if test -z "$CC"; then
- echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
- exit 1
- fi
- fi
-
- # Now see if the compiler is really GCC.
- with_gcc=no
- echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
- echo "$progname:581: checking whether we are using GNU C" >&5
-
- $rm conftest.c
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
- if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- with_gcc=yes
- fi
- $rm conftest.c
- echo "$ac_t$with_gcc" 1>&6
-fi
-
-# Allow CC to be a program name with arguments.
-set dummy $CC
-compiler="$2"
-
-echo $ac_n "checking for object suffix... $ac_c" 1>&6
-$rm conftest*
-echo 'int i = 1;' > conftest.c
-echo "$progname:603: checking for object suffix" >& 5
-if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
- # Append any warnings to the config.log.
- cat conftest.err 1>&5
-
- for ac_file in conftest.*; do
- case $ac_file in
- *.c) ;;
- *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
- esac
- done
-else
- cat conftest.err 1>&5
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
-fi
-$rm conftest*
-echo "$ac_t$objext" 1>&6
-
-echo $ac_n "checking for executable suffix... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_cv_exeext="no"
- $rm conftest*
- echo 'main () { return 0; }' > conftest.c
- echo "$progname:629: checking for executable suffix" >& 5
- if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
- # Append any warnings to the config.log.
- cat conftest.err 1>&5
-
- for ac_file in conftest.*; do
- case $ac_file in
- *.c | *.err | *.$objext ) ;;
- *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
- esac
- done
- else
- cat conftest.err 1>&5
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
- fi
- $rm conftest*
-fi
-if test "X$ac_cv_exeext" = Xno; then
- exeext=""
-else
- exeext="$ac_cv_exeext"
-fi
-echo "$ac_t$ac_cv_exeext" 1>&6
-
-echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
-pic_flag=
-special_shlib_compile_flags=
-wl=
-link_static_flag=
-no_builtin_flag=
-
-if test "$with_gcc" = yes; then
- wl='-Wl,'
- link_static_flag='-static'
-
- case "$host_os" in
- beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
- aix*)
- # Below there is a dirty hack to force normal static linking with -ldl
- # The problem is because libdl dynamically linked with both libc and
- # libC (AIX C++ library), which obviously doesn't included in libraries
- # list by gcc. This cause undefined symbols with -static flags.
- # This hack allows C programs to be linked with "-static -ldl", but
- # we not sure about C++ programs.
- link_static_flag="$link_static_flag ${wl}-lC"
- ;;
- cygwin* | mingw* | os2*)
- # We can build DLLs from non-PIC.
- ;;
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- pic_flag='-m68020 -resident32 -malways-restore-a4'
- ;;
- sysv4*MP*)
- if test -d /usr/nec; then
- pic_flag=-Kconform_pic
- fi
- ;;
- *)
- pic_flag='-fPIC'
- ;;
- esac
-else
- # PORTME Check for PIC flags for the system compiler.
- case "$host_os" in
- aix3* | aix4*)
- # All AIX code is PIC.
- link_static_flag='-bnso -bI:/lib/syscalls.exp'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- # Is there a better link_static_flag that works with the bundled CC?
- wl='-Wl,'
- link_static_flag="${wl}-a ${wl}archive"
- pic_flag='+Z'
- ;;
-
- irix5* | irix6*)
- wl='-Wl,'
- link_static_flag='-non_shared'
- # PIC (with -KPIC) is the default.
- ;;
-
- cygwin* | mingw* | os2*)
- # We can build DLLs from non-PIC.
- ;;
-
- osf3* | osf4* | osf5*)
- # All OSF/1 code is PIC.
- wl='-Wl,'
- link_static_flag='-non_shared'
- ;;
-
- sco3.2v5*)
- pic_flag='-Kpic'
- link_static_flag='-dn'
- special_shlib_compile_flags='-belf'
- ;;
-
- solaris*)
- pic_flag='-KPIC'
- link_static_flag='-Bstatic'
- wl='-Wl,'
- ;;
-
- sunos4*)
- pic_flag='-PIC'
- link_static_flag='-Bstatic'
- wl='-Qoption ld '
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- pic_flag='-KPIC'
- link_static_flag='-Bstatic'
- wl='-Wl,'
- ;;
-
- uts4*)
- pic_flag='-pic'
- link_static_flag='-Bstatic'
- ;;
- sysv4*MP*)
- if test -d /usr/nec ;then
- pic_flag='-Kconform_pic'
- link_static_flag='-Bstatic'
- fi
- ;;
- *)
- can_build_shared=no
- ;;
- esac
-fi
-
-if test -n "$pic_flag"; then
- echo "$ac_t$pic_flag" 1>&6
-
- # Check to make sure the pic_flag actually works.
- echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
- $rm conftest*
- echo "int some_variable = 0;" > conftest.c
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $pic_flag -DPIC"
- echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
- if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
- # Append any warnings to the config.log.
- cat conftest.err 1>&5
-
- case "$host_os" in
- hpux9* | hpux10* | hpux11*)
- # On HP-UX, both CC and GCC only warn that PIC is supported... then they
- # create non-PIC objects. So, if there were any warnings, we assume that
- # PIC is not supported.
- if test -s conftest.err; then
- echo "$ac_t"no 1>&6
- can_build_shared=no
- pic_flag=
- else
- echo "$ac_t"yes 1>&6
- pic_flag=" $pic_flag"
- fi
- ;;
- *)
- echo "$ac_t"yes 1>&6
- pic_flag=" $pic_flag"
- ;;
- esac
- else
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- can_build_shared=no
- pic_flag=
- echo "$ac_t"no 1>&6
- fi
- CFLAGS="$save_CFLAGS"
- $rm conftest*
-else
- echo "$ac_t"none 1>&6
-fi
-
-# Check to see if options -o and -c are simultaneously supported by compiler
-echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
-$rm -r conftest 2>/dev/null
-mkdir conftest
-cd conftest
-$rm conftest*
-echo "int some_variable = 0;" > conftest.c
-mkdir out
-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
-# that will create temporary files in the current directory regardless of
-# the output directory. Thus, making CWD read-only will cause this test
-# to fail, enabling locking or at least warning the user not to do parallel
-# builds.
-chmod -w .
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -o out/conftest2.o"
-echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
-if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
-
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s out/conftest.err; then
- echo "$ac_t"no 1>&6
- compiler_c_o=no
- else
- echo "$ac_t"yes 1>&6
- compiler_c_o=yes
- fi
-else
- # Append any errors to the config.log.
- cat out/conftest.err 1>&5
- compiler_c_o=no
- echo "$ac_t"no 1>&6
-fi
-CFLAGS="$save_CFLAGS"
-chmod u+w .
-$rm conftest* out/*
-rmdir out
-cd ..
-rmdir conftest
-$rm -r conftest 2>/dev/null
-
-if test x"$compiler_c_o" = x"yes"; then
- # Check to see if we can write to a .lo
- echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
- $rm conftest*
- echo "int some_variable = 0;" > conftest.c
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -c -o conftest.lo"
- echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
-if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
-
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- echo "$ac_t"no 1>&6
- compiler_o_lo=no
- else
- echo "$ac_t"yes 1>&6
- compiler_o_lo=yes
- fi
- else
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- compiler_o_lo=no
- echo "$ac_t"no 1>&6
- fi
- CFLAGS="$save_CFLAGS"
- $rm conftest*
-else
- compiler_o_lo=no
-fi
-
-# Check to see if we can do hard links to lock some files if needed
-hard_links="nottested"
-if test "$compiler_c_o" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- echo "$ac_t$hard_links" 1>&6
- $rm conftest*
- if test "$hard_links" = no; then
- echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-if test "$with_gcc" = yes; then
- # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
- echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
- $rm conftest*
- echo "int some_variable = 0;" > conftest.c
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
- echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
- if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
-
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- echo "$ac_t"no 1>&6
- compiler_rtti_exceptions=no
- else
- echo "$ac_t"yes 1>&6
- compiler_rtti_exceptions=yes
- fi
- else
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- compiler_rtti_exceptions=no
- echo "$ac_t"no 1>&6
- fi
- CFLAGS="$save_CFLAGS"
- $rm conftest*
-
- if test "$compiler_rtti_exceptions" = "yes"; then
- no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
- else
- no_builtin_flag=' -fno-builtin'
- fi
-
-fi
-
-# Check for any special shared library compilation flags.
-if test -n "$special_shlib_compile_flags"; then
- echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
- if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
- else
- echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
- can_build_shared=no
- fi
-fi
-
-echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
-$rm conftest*
-echo 'main(){return(0);}' > conftest.c
-save_LDFLAGS="$LDFLAGS"
-LDFLAGS="$LDFLAGS $link_static_flag"
-echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
-if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- echo "$ac_t$link_static_flag" 1>&6
-else
- echo "$ac_t"none 1>&6
- link_static_flag=
-fi
-LDFLAGS="$save_LDFLAGS"
-$rm conftest*
-
-if test -z "$LN_S"; then
- # Check to see if we can use ln -s, or we need hard links.
- echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
- $rm conftest.dat
- if ln -s X conftest.dat 2>/dev/null; then
- $rm conftest.dat
- LN_S="ln -s"
- else
- LN_S=ln
- fi
- if test "$LN_S" = "ln -s"; then
- echo "$ac_t"yes 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
-fi
-
-# Make sure LD is an absolute path.
-if test -z "$LD"; then
- ac_prog=ld
- if test "$with_gcc" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
- echo "$progname:991: checking for ld used by GCC" >&5
- ac_prog=`($CC -print-prog-name=ld) 2>&5`
- case "$ac_prog" in
- # Accept absolute paths.
- [\\/]* | [A-Za-z]:[\\/]*)
- re_direlt='/[^/][^/]*/\.\./'
- # Canonicalize the path of ld
- ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
- while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we are not using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
- elif test "$with_gnu_ld" = yes; then
- echo $ac_n "checking for GNU ld... $ac_c" 1>&6
- echo "$progname:1015: checking for GNU ld" >&5
- else
- echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
- echo "$progname:1018: checking for non-GNU ld" >&5
- fi
-
- if test -z "$LD"; then
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some GNU ld's only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
- test "$with_gnu_ld" != no && break
- else
- test "$with_gnu_ld" != yes && break
- fi
- fi
- done
- IFS="$ac_save_ifs"
- fi
-
- if test -n "$LD"; then
- echo "$ac_t$LD" 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
-
- if test -z "$LD"; then
- echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
- exit 1
- fi
-fi
-
-# Check to see if it really is or is not GNU ld.
-echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
-# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
- with_gnu_ld=yes
-else
- with_gnu_ld=no
-fi
-echo "$ac_t$with_gnu_ld" 1>&6
-
-# See if the linker supports building shared libraries.
-echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
-
-allow_undefined_flag=
-no_undefined_flag=
-need_lib_prefix=unknown
-need_version=unknown
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-archive_cmds=
-archive_expsym_cmds=
-old_archive_from_new_cmds=
-export_dynamic_flag_spec=
-whole_archive_flag_spec=
-thread_safe_flag_spec=
-hardcode_libdir_flag_spec=
-hardcode_libdir_separator=
-hardcode_direct=no
-hardcode_minus_L=no
-hardcode_shlibpath_var=unsupported
-runpath_var=
-always_export_symbols=no
-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
-# include_expsyms should be a list of space-separated symbols to be *always*
-# included in the symbol list
-include_expsyms=
-# exclude_expsyms can be an egrep regular expression of symbols to exclude
-# it will be wrapped by ` (' and `)$', so one must not match beginning or
-# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-# as well as any symbol that contains `d'.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-# platforms (ab)use it in PIC code, but their linkers get confused if
-# the symbol is explicitly referenced. Since portable code cannot
-# rely on this symbol name, it's probably fine to never include it in
-# preloaded symbol tables.
-
-case "$host_os" in
-cygwin* | mingw*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$with_gcc" != yes; then
- with_gnu_ld=no
- fi
- ;;
-
-esac
-
-ld_shlibs=yes
-if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # See if GNU ld supports shared libraries.
- case "$host_os" in
- aix3* | aix4*)
- # On AIX, the GNU linker is very broken
- ld_shlibs=no
- cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
- ;;
-
- amigaos*)
- archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
-
- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
- # that the semantics of dynamic libraries on AmigaOS, at least up
- # to version 4, is to share data among multiple programs linked
- # with the same dynamic library. Since this doesn't match the
- # behavior of shared libraries on other platforms, we can use
- # them.
- ld_shlibs=no
- ;;
-
- beos*)
- if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- cygwin* | mingw*)
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec='-L$libdir'
- allow_undefined_flag=unsupported
- always_export_symbols=yes
-
- # Extract the symbol export list from an `--export-all' def file,
- # then regenerate the def file from the symbol export list, so that
- # the compiled dll only exports the symbol export list.
- # Be careful not to strip the DATA tag left by newer dlltools.
- export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
- test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
- $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~
- sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols'
-
- # If DATA tags from a recent dlltool are present, honour them!
- archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
- _lt_hint=1;
- cat $export_symbols | while read symbol; do
- set dummy \$symbol;
- case \$# in
- 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;;
- *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;;
- esac;
- _lt_hint=`expr 1 + \$_lt_hint`;
- done~
- test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
- test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
- $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
- $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
- $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
- $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
- $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
-
- old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a'
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
- # can we support soname and/or expsyms with a.out? -oliva
- fi
- ;;
-
- solaris* | sysv5*)
- if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
- ld_shlibs=no
- cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
- elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- sunos4*)
- archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
- wlarc=
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- *)
- if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
- esac
-
- if test "$ld_shlibs" = yes; then
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec='${wl}--export-dynamic'
- case $host_os in
- cygwin* | mingw*)
- # dlltool doesn't understand --whole-archive et. al.
- whole_archive_flag_spec=
- ;;
- *)
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec=
- fi
- ;;
- esac
- fi
-else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case "$host_os" in
- aix3*)
- allow_undefined_flag=unsupported
- always_export_symbols=yes
- archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- hardcode_minus_L=yes
- if test "$with_gcc" = yes && test -z "$link_static_flag"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- hardcode_direct=unsupported
- fi
- ;;
-
- aix4*)
- hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
- hardcode_libdir_separator=':'
- if test "$with_gcc" = yes; then
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- hardcode_direct=yes
- else
- # We have old collect2
- hardcode_direct=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L=yes
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_libdir_separator=
- fi
- shared_flag='-shared'
- else
- shared_flag='${wl}-bM:SRE'
- hardcode_direct=yes
- fi
- allow_undefined_flag=' ${wl}-berok'
- archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
- archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
- #### local change for Sleepycat DB:
- # On AIX 4.3.2 (at least), -bexpall exports too much,
- # causing symbol conflicts. This was:
- # case "$host_os" in aix4.[01]|aix4.[01].*)
- case "$host_os" in aix4.*)
- # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
- always_export_symbols=yes ;;
- esac
- ;;
-
- amigaos*)
- archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- # see comment about different semantics on the GNU ld section
- ld_shlibs=no
- ;;
-
- cygwin* | mingw*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec=' '
- allow_undefined_flag=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # FIXME: Setting linknames here is a bad hack.
- archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- old_archive_from_new_cmds='true'
- # FIXME: Should let the user specify the lib program.
- old_archive_cmds='lib /OUT:$oldlib$oldobjs'
- fix_srcfile_path='`cygpath -w $srcfile`'
- ;;
-
- freebsd1*)
- ld_shlibs=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd*)
- archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- hpux9* | hpux10* | hpux11*)
- case "$host_os" in
- hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
- *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
- esac
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
- hardcode_direct=yes
- hardcode_minus_L=yes # Not in the search PATH, but as the default
- # location of the library.
- export_dynamic_flag_spec='${wl}-E'
- ;;
-
- irix5* | irix6*)
- if test "$with_gcc" = yes; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
- else
- archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out
- else
- archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF
- fi
- hardcode_libdir_flag_spec='${wl}-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- openbsd*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- os2*)
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- allow_undefined_flag=unsupported
- archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
- old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$with_gcc" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
-
- osf4* | osf5*) # As osf3* with the addition of the -msym flag
- if test "$with_gcc" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
- rhapsody*)
- archive_cmds='$CC -bundle -undefined suppress -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flags_spec='-L$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- sco3.2v5*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_shlibpath_var=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ;;
-
- solaris*)
- no_undefined_flag=' -z text'
- # $CC -shared without GNU ld will not create a library from C++
- # object files and a static libstdc++, better avoid it by now
- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_shlibpath_var=no
- case "$host_os" in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *) # Supported since Solaris 2.6 (maybe 2.5.1?)
- whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
- esac
- ;;
-
- sunos4*)
- archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- sysv4)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts'
- else
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- fi
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var=no
- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
- ;;
-
- sysv4.3*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_shlibpath_var=no
- export_dynamic_flag_spec='-Bexport'
- ;;
-
- sysv5*)
- no_undefined_flag=' -z text'
- # $CC -shared without GNU ld will not create a library from C++
- # object files and a static libstdc++, better avoid it by now
- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
- hardcode_libdir_flag_spec=
- hardcode_shlibpath_var=no
- runpath_var='LD_RUN_PATH'
- ;;
-
- uts4*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- dgux*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_shlibpath_var=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ld_shlibs=yes
- fi
- ;;
-
- sysv4.2uw2*)
- archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts'
- hardcode_direct=yes
- hardcode_minus_L=no
- hardcode_shlibpath_var=no
- hardcode_runpath_var=yes
- runpath_var=LD_RUN_PATH
- ;;
-
- unixware7*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var=no
- ;;
-
- *)
- ld_shlibs=no
- ;;
- esac
-fi
-echo "$ac_t$ld_shlibs" 1>&6
-test "$ld_shlibs" = no && can_build_shared=no
-
-if test -z "$NM"; then
- echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
- case "$NM" in
- [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
- *)
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
- NM="$ac_dir/nm -B"
- break
- elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
- NM="$ac_dir/nm -p"
- break
- else
- NM=${NM="$ac_dir/nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- fi
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$NM" && NM=nm
- ;;
- esac
- echo "$ac_t$NM" 1>&6
-fi
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Transform the above into a raw symbol and a C symbol.
-symxfrm='\1 \2\3 \3'
-
-# Transform an extracted symbol line into a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
-
-# Define system-specific variables.
-case "$host_os" in
-aix*)
- symcode='[BCDT]'
- ;;
-cygwin* | mingw*)
- symcode='[ABCDGISTW]'
- ;;
-hpux*) # Its linker distinguishes data from code symbols
- global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
- ;;
-irix*)
- symcode='[BCDEGRST]'
- ;;
-solaris*)
- symcode='[BDT]'
- ;;
-sysv4)
- symcode='[DFNSTU]'
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
- symcode='[ABCDGISTW]'
-fi
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Write the raw and C identifiers.
- global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
-
- # Check to see that the pipe works correctly.
- pipe_works=no
- $rm conftest*
- cat > conftest.c <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
- echo "$progname:1653: checking if global_symbol_pipe works" >&5
- if { (eval echo $progname:1654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if { echo "$progname:1657: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
-
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if egrep ' nm_test_var$' "$nlist" >/dev/null; then
- if egrep ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<EOF > conftest.c
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
- # Now generate the symbol file.
- eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
-
- cat <<EOF >> conftest.c
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{
-EOF
- sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
- cat <<\EOF >> conftest.c
- {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
- # Now try linking the two files.
- mv conftest.$objext conftstm.$objext
- save_LIBS="$LIBS"
- save_CFLAGS="$CFLAGS"
- LIBS="conftstm.$objext"
- CFLAGS="$CFLAGS$no_builtin_flag"
- if { (eval echo $progname:1709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- pipe_works=yes
- else
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
- fi
- LIBS="$save_LIBS"
- else
- echo "cannot find nm_test_func in $nlist" >&5
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&5
- fi
- else
- echo "cannot run $global_symbol_pipe" >&5
- fi
- else
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
- fi
- $rm conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- global_symbol_pipe=
- fi
-done
-if test "$pipe_works" = yes; then
- echo "${ac_t}ok" 1>&6
-else
- echo "${ac_t}failed" 1>&6
-fi
-
-if test -z "$global_symbol_pipe"; then
- global_symbol_to_cdecl=
-fi
-
-# Check hardcoding attributes.
-echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
- test -n "$runpath_var"; then
-
- # We can hardcode non-existant directories.
- if test "$hardcode_direct" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$hardcode_shlibpath_var" != no &&
- test "$hardcode_minus_L" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action=unsupported
-fi
-echo "$ac_t$hardcode_action" 1>&6
-
-
-reload_flag=
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
-# PORTME Some linkers may need a different reload flag.
-reload_flag='-r'
-echo "$ac_t$reload_flag" 1>&6
-test -n "$reload_flag" && reload_flag=" $reload_flag"
-
-# PORTME Fill in your ld.so characteristics
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-file_magic_cmd=
-file_magic_test_file=
-deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [regex]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given egrep regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
-case "$host_os" in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}.so$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}.so$major'
- ;;
-
-aix4*)
- version_type=linux
- # AIX has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- # We preserve .a as extension for shared libraries though AIX4.2
- # and later linker supports .so
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
- shlibpath_var=LIBPATH
- deplibs_check_method=pass_all
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}.so'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- deplibs_check_method=pass_all
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
-bsdi4*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/shlib/libc.so
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- export_dynamic_flag_spec=-rdynamic
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw*)
- version_type=windows
- need_version=no
- need_lib_prefix=no
- if test "$with_gcc" = yes; then
- library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
- else
- library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
- fi
- dynamic_linker='Win32 ld.exe'
- deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
- file_magic_cmd='${OBJDUMP} -f'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-freebsd*)
- objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
- version_type=freebsd-$objformat
- case "$version_type" in
- freebsd-elf*)
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /usr/lib/libc.so*`
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- deplibs_check_method=unknown
- library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case "$host_os" in
- freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- ;;
- *) # from 3.2 on
- shlibpath_overrides_runpath=no
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- dynamic_linker="$host_os dld.sl"
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
- soname_spec='${libname}${release}.sl$major'
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
-
- #### local change for Sleepycat DB: [#1990]
- # The following 3 lines added, otherwise dependent libraries are not allowed
- # on HP. We use dependent libraries in a very straightforward way, to
- # incorporate -lnsl into libtcl.sl, and for testing only.
- deplibs_check_method='file_magic PA-RISC[1-9][0-9.]* shared library'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /lib/libc.sl*`
- ;;
-
-irix5* | irix6*)
- version_type=irix
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}.so.$major'
- library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
- case "$host_os" in
- irix5*)
- libsuff= shlibsuff=
- # this will be overridden with pass_all, but let us keep it just in case
- deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
- ;;
- *)
- case "$LD" in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /lib${libsuff}/libc.so*`
- deplibs_check_method='pass_all'
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- deplibs_check_method=pass_all
-
- if test -f /lib/ld.so.1; then
- dynamic_linker='GNU ld.so'
- else
- # Only the GNU ld.so supports shared libraries on MkLinux.
- case "$host_cpu" in
- powerpc*) dynamic_linker=no ;;
- *) dynamic_linker='Linux ld.so' ;;
- esac
- fi
- ;;
-
-netbsd*)
- version_type=sunos
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
- soname_spec='${libname}${release}.so$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-openbsd*)
- version_type=sunos
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- need_version=no
- fi
- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-os2*)
- libname_spec='$name'
- need_lib_prefix=no
- library_names_spec='$libname.dll $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_version=no
- soname_spec='${libname}${release}.so'
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
- shlibpath_var=LD_LIBRARY_PATH
- # this will be overridden with pass_all, but let us keep it just in case
- deplibs_check_method='file_magic COFF format alpha shared library'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/shlib/libc.so
- deplibs_check_method='pass_all'
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-rhapsody*)
- version_type=sunos
- library_names_spec='${libname}.so'
- soname_spec='${libname}.so'
- shlibpath_var=DYLD_LIBRARY_PATH
- deplibs_check_method=pass_all
- ;;
-
-sco3.2v5*)
- version_type=osf
- soname_spec='${libname}${release}.so$major'
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- shlibpath_var=LD_LIBRARY_PATH
- #### local change for Sleepycat DB:
- # The following line added, otherwise dependent libraries are not allowed
- # on SCO. We use dependent libraries in a very straightforward way.
- deplibs_check_method='pass_all'
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/lib/libc.so
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- version_type=linux
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- case "$host_vendor" in
- sequent)
- file_magic_cmd='/bin/file'
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
- ;;
- ncr)
- deplibs_check_method='pass_all'
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- esac
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
- soname_spec='$libname.so.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-#### local change for Sleepycat DB:
-# Add in the QNX support from QNX.
-nto-qnx)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- deplibs_check_method='pass_all'
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-echo "$ac_t$dynamic_linker" 1>&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-# Report the final consequences.
-echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
-
-# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
-# configure.in, otherwise build static only libraries.
-case "$host_os" in
-cygwin* | mingw* | os2*)
- if test x$can_build_shared = xyes; then
- test x$enable_win32_dll = xno && can_build_shared=no
- echo "checking if package supports dlls... $can_build_shared" 1>&6
- fi
-;;
-esac
-
-if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
- case "$deplibs_check_method" in
- "file_magic "*)
- file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- egrep "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
- fi ;;
- esac
-fi
-
-echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case "$host_os" in
-aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
-aix4*)
- test "$enable_shared" = yes && enable_static=no
- ;;
-esac
-
-echo "$ac_t$enable_shared" 1>&6
-
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-
-echo "checking whether to build static libraries... $enable_static" 1>&6
-
-if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-echo $ac_n "checking for objdir... $ac_c" 1>&6
-rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-echo "$ac_t$objdir" 1>&6
-
-if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
-if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
- lt_cv_dlopen=no lt_cv_dlopen_libs=
-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "$progname:2248: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldl $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2256 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dlopen""... $ac_c" 1>&6
-echo "$progname:2288: checking for dlopen" >&5
-if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2293 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char dlopen(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_dlopen) || defined (__stub___dlopen)
-choke me
-#else
-dlopen();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_dlopen=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_dlopen=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="dlopen"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
-echo "$progname:2335: checking for dld_link in -ldld" >&5
-ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2343 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dld_link();
-
-int main() {
-dld_link()
-; return 0; }
-EOF
-if { (eval echo $progname:2356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load""... $ac_c" 1>&6
-echo "$progname:2375: checking for shl_load" >&5
-if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2380 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char shl_load(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_shl_load) || defined (__stub___shl_load)
-choke me
-#else
-shl_load();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_shl_load=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_shl_load=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="shl_load"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "$progname:2423: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2431 "ltconfig"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo $progname:2445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
- echo "$ac_t""no" 1>&6
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-fi
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- fi
-
- case "$lt_cv_dlopen" in
- dlopen)
-for ac_hdr in dlfcn.h; do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "$progname:2488: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2493 "ltconfig"
-#include <$ac_hdr>
-int fnord = 0;
-EOF
-ac_try="$ac_compile >/dev/null 2>conftest.out"
-{ (eval echo $progname:2498: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
- if test "x$ac_cv_header_dlfcn_h" = xyes; then
- CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
- fi
- eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2526: checking whether a program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self+set}" = set; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- lt_cv_dlopen_self=cross
- else
- cat > conftest.c <<EOF
-#line 2534 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LTDL_GLOBAL DL_GLOBAL
-# else
-# define LTDL_GLOBAL 0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LTDL_LAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LTDL_LAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LTDL_LAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LTDL_LAZY_OR_NOW DL_NOW
-# else
-# define LTDL_LAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
- if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
- if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
-
-EOF
-if { (eval echo $progname:2580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- lt_cv_dlopen_self=yes
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- lt_cv_dlopen_self=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self" 1>&6
-
- if test "$lt_cv_dlopen_self" = yes; then
- LDFLAGS="$LDFLAGS $link_static_flag"
- echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2599: checking whether a statically linked program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self_static+set}" = set; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- lt_cv_dlopen_self_static=cross
- else
- cat > conftest.c <<EOF
-#line 2607 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LTDL_GLOBAL DL_GLOBAL
-# else
-# define LTDL_GLOBAL 0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LTDL_LAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LTDL_LAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LTDL_LAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LTDL_LAZY_OR_NOW DL_NOW
-# else
-# define LTDL_LAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
- if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
- if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
-
-EOF
-if { (eval echo $progname:2653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- lt_cv_dlopen_self_static=yes
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- lt_cv_dlopen_self_static=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
-fi
- ;;
- esac
-
- case "$lt_cv_dlopen_self" in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case "$lt_cv_dlopen_self_static" in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-
-# Copy echo and quote the copy, instead of the original, because it is
-# used later.
-ltecho="$echo"
-if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
- ltecho="$CONFIG_SHELL \$0 --fallback-echo"
-fi
-LTSHELL="$SHELL"
-
-LTCONFIG_VERSION="$VERSION"
-
-# Only quote variables if we're using ltmain.sh.
-case "$ltmain" in
-*.sh)
- # Now quote all the things that may contain metacharacters.
- for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
- old_LD old_LDFLAGS old_LIBS \
- old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
- AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
- reload_flag reload_cmds wl \
- pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
- thread_safe_flag_spec whole_archive_flag_spec libname_spec \
- library_names_spec soname_spec \
- RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
- old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
- file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
- finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
- hardcode_libdir_flag_spec hardcode_libdir_separator \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
-
- case "$var" in
- reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case "$ltecho" in
- *'\$0 --fallback-echo"')
- ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
- trap "$rm \"$ofile\"; exit 1" 1 2 15
- echo "creating $ofile"
- $rm "$ofile"
- cat <<EOF > "$ofile"
-#! $SHELL
-
-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# 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.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-### BEGIN LIBTOOL CONFIG
-EOF
- cfgfile="$ofile"
- ;;
-
-*)
- # Double-quote the variables that need it (for aesthetics).
- for var in old_CC old_CFLAGS old_CPPFLAGS \
- old_LD old_LDFLAGS old_LIBS \
- old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
- eval "$var=\\\"\$var\\\""
- done
-
- # Just create a config file.
- cfgfile="$ofile.cfg"
- trap "$rm \"$cfgfile\"; exit 1" 1 2 15
- echo "creating $cfgfile"
- $rm "$cfgfile"
- cat <<EOF > "$cfgfile"
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-EOF
- ;;
-esac
-
-cat <<EOF >> "$cfgfile"
-# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
-# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
-# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
-# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
-# $0$ltconfig_args
-#
-# Compiler and other test output produced by $progname, useful for
-# debugging $progname, is in ./config.log if it exists.
-
-# The version of $progname that generated this script.
-LTCONFIG_VERSION=$LTCONFIG_VERSION
-
-# Shell to use when invoking shell scripts.
-SHELL=$LTSHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-
-# An echo program that does not interpret backslashes.
-echo=$ltecho
-
-# The archiver.
-AR=$AR
-
-# The default C compiler.
-CC=$CC
-
-# The linker used to build libraries.
-LD=$LD
-
-# Whether we need hard or soft links.
-LN_S=$LN_S
-
-# A BSD-compatible nm program.
-NM=$NM
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$reload_flag
-reload_cmds=$reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$wl
-
-# Object file suffix (normally "o").
-objext="$objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$pic_flag
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$compiler_c_o
-
-# Can we write directly to a .lo ?
-compiler_o_lo=$compiler_o_lo
-
-# Must we lock files when doing compilation ?
-need_locks=$need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$link_static_flag
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$no_builtin_flag
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$whole_archive_flag_spec
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$thread_safe_flag_spec
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$RANLIB
-old_archive_cmds=$old_archive_cmds
-old_postinstall_cmds=$old_postinstall_cmds
-old_postuninstall_cmds=$old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$old_archive_from_new_cmds
-
-# Commands used to build and install a shared archive.
-archive_cmds=$archive_cmds
-archive_expsym_cmds=$archive_expsym_cmds
-postinstall_cmds=$postinstall_cmds
-postuninstall_cmds=$postuninstall_cmds
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$allow_undefined_flag
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$no_undefined_flag
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$global_symbol_to_cdecl
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$hardcode_libdir_separator
-
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$include_expsyms
-
-EOF
-
-case "$ltmain" in
-*.sh)
- echo '### END LIBTOOL CONFIG' >> "$ofile"
- echo >> "$ofile"
- case "$host_os" in
- aix3*)
- cat <<\EOF >> "$ofile"
-
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-EOF
- ;;
- esac
-
- # Append the ltmain.sh script.
- sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
-
- chmod +x "$ofile"
- ;;
-
-*)
- # Compile the libtool program.
- echo "FIXME: would compile $ltmain"
- ;;
-esac
-
-test -n "$cache_file" || exit 0
-
-# AC_CACHE_SAVE
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
-#! /bin/bash
diff --git a/bdb/dist/ltmain.sh b/bdb/dist/ltmain.sh
index 4feadbfb759..f07d424527d 100644
--- a/bdb/dist/ltmain.sh
+++ b/bdb/dist/ltmain.sh
@@ -1,7 +1,8 @@
# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun ltconfig.
+# NOTE: Changing this file will not affect anything until you rerun configure.
#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
# This program is free software; you can redistribute it and/or modify
@@ -54,8 +55,8 @@ modename="$progname"
# Constants.
PROGRAM=ltmain.sh
PACKAGE=libtool
-VERSION=1.3.5
-TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)"
+VERSION=1.4.2
+TIMESTAMP=" (1.922.2.53 2001/09/11 03:18:52)"
default_mode=
help="Try \`$progname --help' for more information."
@@ -83,11 +84,8 @@ if test "${LANG+set}" = set; then
save_LANG="$LANG"; LANG=C; export LANG
fi
-if test "$LTCONFIG_VERSION" != "$VERSION"; then
- echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
- echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit 1
-fi
+# Make sure IFS has a sensible default
+: ${IFS=" "}
if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
echo "$modename: not configured to build any kind of library" 1>&2
@@ -113,16 +111,16 @@ do
arg="$1"
shift
- case "$arg" in
+ case $arg in
-*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
# If the previous option needs an argument, assign it.
if test -n "$prev"; then
- case "$prev" in
+ case $prev in
execute_dlfiles)
- eval "$prev=\"\$$prev \$arg\""
+ execute_dlfiles="$execute_dlfiles $arg"
;;
*)
eval "$prev=\$arg"
@@ -135,7 +133,7 @@ do
fi
# Have we seen a non-optional argument yet?
- case "$arg" in
+ case $arg in
--help)
show_help=yes
;;
@@ -146,7 +144,7 @@ do
;;
--config)
- sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
+ sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
exit 0
;;
@@ -207,16 +205,21 @@ if test -n "$prevopt"; then
exit 1
fi
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
if test -z "$show_help"; then
# Infer the operation mode.
if test -z "$mode"; then
- case "$nonopt" in
+ case $nonopt in
*cc | *++ | gcc* | *-gcc*)
mode=link
for arg
do
- case "$arg" in
+ case $arg in
-c)
mode=compile
break
@@ -261,12 +264,13 @@ if test -z "$show_help"; then
help="Try \`$modename --help --mode=$mode' for more information."
# These modes are in order of execution frequency so that they run quickly.
- case "$mode" in
+ case $mode in
# libtool compile mode
compile)
modename="$modename: compile"
# Get the compilation command and the source file.
base_compile=
+ prev=
lastarg=
srcfile="$nonopt"
suppress_output=
@@ -274,8 +278,34 @@ if test -z "$show_help"; then
user_target=no
for arg
do
+ case $prev in
+ "") ;;
+ xcompiler)
+ # Aesthetically quote the previous argument.
+ prev=
+ lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+
+ case $arg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ continue
+ ;;
+ esac
+
# Accept any command-line options.
- case "$arg" in
+ case $arg in
-o)
if test "$user_target" != "no"; then
$echo "$modename: you cannot specify \`-o' more than once" 1>&2
@@ -288,9 +318,53 @@ if test -z "$show_help"; then
build_old_libs=yes
continue
;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ continue
+ ;;
esac
- case "$user_target" in
+ case $user_target in
next)
# The next one is the -o target name
user_target=yes
@@ -316,10 +390,10 @@ if test -z "$show_help"; then
lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
# Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly in scan
- # sets, so we specify it separately.
- case "$lastarg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $lastarg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
lastarg="\"$lastarg\""
;;
esac
@@ -332,7 +406,7 @@ if test -z "$show_help"; then
fi
done
- case "$user_target" in
+ case $user_target in
set)
;;
no)
@@ -348,7 +422,7 @@ if test -z "$show_help"; then
# Recognize several different file suffixes.
# If the user specifies -o file.o, it is replaced with file.lo
xform='[cCFSfmso]'
- case "$libobj" in
+ case $libobj in
*.ada) xform=ada ;;
*.adb) xform=adb ;;
*.ads) xform=ads ;;
@@ -363,7 +437,7 @@ if test -z "$show_help"; then
libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
- case "$libobj" in
+ case $libobj in
*.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
*)
$echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
@@ -387,10 +461,21 @@ if test -z "$show_help"; then
$run $rm $removelist
trap "$run $rm $removelist; exit 1" 1 2 15
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test $pic_mode = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
# Calculate the filename of the output object if compiler does
# not support -o with -c
if test "$compiler_c_o" = no; then
- output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
lockfile="$output_obj.lock"
removelist="$removelist $output_obj $lockfile"
trap "$run $rm $removelist; exit 1" 1 2 15
@@ -402,7 +487,7 @@ if test -z "$show_help"; then
# Lock this critical section if it is needed
# We use this script file to make the link, it avoids creating a new file
if test "$need_locks" = yes; then
- until ln "$0" "$lockfile" 2>/dev/null; do
+ until $run ln "$0" "$lockfile" 2>/dev/null; do
$show "Waiting for $lockfile to be removed"
sleep 2
done
@@ -434,8 +519,13 @@ compiler."
# Without this assignment, base_compile gets emptied.
fbsd_hideous_sh_bug=$base_compile
- # All platforms use -DPIC, to notify preprocessed assembler code.
- command="$base_compile $srcfile $pic_flag -DPIC"
+ if test "$pic_mode" != no; then
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $srcfile $pic_flag -DPIC"
+ else
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ fi
if test "$build_old_libs" = yes; then
lo_libobj="$libobj"
dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
@@ -506,7 +596,8 @@ compiler."
fi
# If we have no pic_flag, then copy the object into place and finish.
- if test -z "$pic_flag" && test "$build_old_libs" = yes; then
+ if (test -z "$pic_flag" || test "$pic_mode" != default) &&
+ test "$build_old_libs" = yes; then
# Rename the .lo from within objdir to obj
if test -f $obj; then
$show $rm $obj
@@ -532,6 +623,10 @@ compiler."
# Now arrange that obj and lo_libobj become the same file
$show "(cd $xdir && $LN_S $baseobj $libobj)"
if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
exit 0
else
error=$?
@@ -546,7 +641,13 @@ compiler."
# Only build a position-dependent object if we build old libraries.
if test "$build_old_libs" = yes; then
- command="$base_compile $srcfile"
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ else
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $srcfile $pic_flag -DPIC"
+ fi
if test "$compiler_c_o" = yes; then
command="$command -o $obj"
output_obj="$obj"
@@ -612,17 +713,17 @@ compiler."
# Unlock the critical section if it was locked
if test "$need_locks" != no; then
- $rm "$lockfile"
+ $run $rm "$lockfile"
fi
exit 0
;;
# libtool link mode
- link)
+ link | relink)
modename="$modename: link"
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
# It is impossible to link a dll without this setting, and
# we shouldn't force the makefile maintainer to figure out
# which system we are compiling for in order to pass an extra
@@ -635,179 +736,12 @@ compiler."
# -no-undefined on the libtool link line when we can be certain
# that all symbols are satisfied, otherwise we get a static library.
allow_undefined=yes
-
- # This is a source program that is used to create dlls on Windows
- # Don't remove nor modify the starting and closing comments
-# /* ltdll.c starts here */
-# #define WIN32_LEAN_AND_MEAN
-# #include <windows.h>
-# #undef WIN32_LEAN_AND_MEAN
-# #include <stdio.h>
-#
-# #ifndef __CYGWIN__
-# # ifdef __CYGWIN32__
-# # define __CYGWIN__ __CYGWIN32__
-# # endif
-# #endif
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif
-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
-# #ifdef __cplusplus
-# }
-# #endif
-#
-# #ifdef __CYGWIN__
-# #include <cygwin/cygwin_dll.h>
-# DECLARE_CYGWIN_DLL( DllMain );
-# #endif
-# HINSTANCE __hDllInstance_base;
-#
-# BOOL APIENTRY
-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
-# {
-# __hDllInstance_base = hInst;
-# return TRUE;
-# }
-# /* ltdll.c ends here */
- # This is a source program that is used to create import libraries
- # on Windows for dlls which lack them. Don't remove nor modify the
- # starting and closing comments
-# /* impgen.c starts here */
-# /* Copyright (C) 1999 Free Software Foundation, Inc.
-#
-# This file is part of GNU libtool.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU 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 <stdio.h> /* for printf() */
-# #include <unistd.h> /* for open(), lseek(), read() */
-# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
-# #include <string.h> /* for strdup() */
-#
-# static unsigned int
-# pe_get16 (fd, offset)
-# int fd;
-# int offset;
-# {
-# unsigned char b[2];
-# lseek (fd, offset, SEEK_SET);
-# read (fd, b, 2);
-# return b[0] + (b[1]<<8);
-# }
-#
-# static unsigned int
-# pe_get32 (fd, offset)
-# int fd;
-# int offset;
-# {
-# unsigned char b[4];
-# lseek (fd, offset, SEEK_SET);
-# read (fd, b, 4);
-# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-# }
-#
-# static unsigned int
-# pe_as32 (ptr)
-# void *ptr;
-# {
-# unsigned char *b = ptr;
-# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-# }
-#
-# int
-# main (argc, argv)
-# int argc;
-# char *argv[];
-# {
-# int dll;
-# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
-# unsigned long export_rva, export_size, nsections, secptr, expptr;
-# unsigned long name_rvas, nexp;
-# unsigned char *expdata, *erva;
-# char *filename, *dll_name;
-#
-# filename = argv[1];
-#
-# dll = open(filename, O_RDONLY|O_BINARY);
-# if (!dll)
-# return 1;
-#
-# dll_name = filename;
-#
-# for (i=0; filename[i]; i++)
-# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
-# dll_name = filename + i +1;
-#
-# pe_header_offset = pe_get32 (dll, 0x3c);
-# opthdr_ofs = pe_header_offset + 4 + 20;
-# num_entries = pe_get32 (dll, opthdr_ofs + 92);
-#
-# if (num_entries < 1) /* no exports */
-# return 1;
-#
-# export_rva = pe_get32 (dll, opthdr_ofs + 96);
-# export_size = pe_get32 (dll, opthdr_ofs + 100);
-# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
-# secptr = (pe_header_offset + 4 + 20 +
-# pe_get16 (dll, pe_header_offset + 4 + 16));
-#
-# expptr = 0;
-# for (i = 0; i < nsections; i++)
-# {
-# char sname[8];
-# unsigned long secptr1 = secptr + 40 * i;
-# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
-# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
-# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
-# lseek(dll, secptr1, SEEK_SET);
-# read(dll, sname, 8);
-# if (vaddr <= export_rva && vaddr+vsize > export_rva)
-# {
-# expptr = fptr + (export_rva - vaddr);
-# if (export_rva + export_size > vaddr + vsize)
-# export_size = vsize - (export_rva - vaddr);
-# break;
-# }
-# }
-#
-# expdata = (unsigned char*)malloc(export_size);
-# lseek (dll, expptr, SEEK_SET);
-# read (dll, expdata, export_size);
-# erva = expdata - export_rva;
-#
-# nexp = pe_as32 (expdata+24);
-# name_rvas = pe_as32 (expdata+32);
-#
-# printf ("EXPORTS\n");
-# for (i = 0; i<nexp; i++)
-# {
-# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
-# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
-# }
-#
-# return 0;
-# }
-# /* impgen.c ends here */
;;
*)
allow_undefined=yes
;;
esac
+ libtool_args="$nonopt"
compile_command="$nonopt"
finalize_command="$nonopt"
@@ -818,18 +752,12 @@ compiler."
convenience=
old_convenience=
deplibs=
- linkopts=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
- if test -n "$shlibpath_var"; then
- # get the directories listed in $shlibpath_var
- eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
- else
- lib_search_path=
- fi
- # now prepend the system-specific ones
- eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
- eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-
avoid_version=no
dlfiles=
dlprefiles=
@@ -839,9 +767,9 @@ compiler."
export_symbols_regex=
generated=
libobjs=
- link_against_libtool_libs=
ltlibs=
module=no
+ no_install=no
objs=
prefer_static_libs=no
preload=no
@@ -858,7 +786,7 @@ compiler."
# We need to know -static, to get the right output filenames.
for arg
do
- case "$arg" in
+ case $arg in
-all-static | -static)
if test "X$arg" = "X-all-static"; then
if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
@@ -887,17 +815,24 @@ compiler."
while test $# -gt 0; do
arg="$1"
shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
# If the previous option needs an argument, assign it.
if test -n "$prev"; then
- case "$prev" in
+ case $prev in
output)
compile_command="$compile_command @OUTPUT@"
finalize_command="$finalize_command @OUTPUT@"
;;
esac
- case "$prev" in
+ case $prev in
dlfiles|dlprefiles)
if test "$preload" = no; then
# Add the symbol object into the linking commands.
@@ -905,7 +840,7 @@ compiler."
finalize_command="$finalize_command @SYMFILE@"
preload=yes
fi
- case "$arg" in
+ case $arg in
*.la | *.lo) ;; # We handle these cases below.
force)
if test "$dlself" = no; then
@@ -934,6 +869,7 @@ compiler."
dlprefiles="$dlprefiles $arg"
fi
prev=
+ continue
;;
esac
;;
@@ -958,7 +894,7 @@ compiler."
;;
rpath | xrpath)
# We need an absolute path.
- case "$arg" in
+ case $arg in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
$echo "$modename: only absolute run-paths are allowed" 1>&2
@@ -979,17 +915,32 @@ compiler."
prev=
continue
;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
*)
eval "$prev=\"\$arg\""
prev=
continue
;;
esac
- fi
+ fi # test -n $prev
prevarg="$arg"
- case "$arg" in
+ case $arg in
-all-static)
if test -n "$link_static_flag"; then
compile_command="$compile_command $link_static_flag"
@@ -1026,7 +977,7 @@ compiler."
-export-symbols | -export-symbols-regex)
if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: not more than one -exported-symbols argument allowed"
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
exit 1
fi
if test "X$arg" = "X-export-symbols"; then
@@ -1037,58 +988,76 @@ compiler."
continue
;;
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
-L*)
dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
# We need an absolute path.
- case "$dir" in
+ case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
absdir=`cd "$dir" && pwd`
if test -z "$absdir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
- $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
- absdir="$dir"
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit 1
fi
dir="$absdir"
;;
esac
- case " $deplibs " in
- *" $arg "*) ;;
- *) deplibs="$deplibs $arg";;
- esac
- case " $lib_search_path " in
- *" $dir "*) ;;
- *) lib_search_path="$lib_search_path $dir";;
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
esac
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2*)
- dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
- case ":$dllsearchpath:" in
- ::) dllsearchpath="$dllsearchdir";;
- *":$dllsearchdir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
esac
;;
esac
+ continue
;;
-l*)
- if test "$arg" = "-lc"; then
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
- # These systems don't actually have c library (as such)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
continue
;;
+ *-*-mingw* | *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
esac
- elif test "$arg" = "-lm"; then
- case "$host" in
- *-*-cygwin* | *-*-beos*)
- # These systems don't actually have math library (as such)
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd*)
+ # Do not include libc_r directly, use -pthread flag.
continue
;;
esac
fi
deplibs="$deplibs $arg"
+ continue
;;
-module)
@@ -1096,6 +1065,32 @@ compiler."
continue
;;
+ #### Local change for Sleepycat's Berkeley DB [#6117]:
+ -jnimodule)
+ module=yes
+ jnimodule=yes
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
-no-undefined)
allow_undefined=no
continue
@@ -1121,7 +1116,7 @@ compiler."
-R*)
dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
# We need an absolute path.
- case "$dir" in
+ case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
$echo "$modename: only absolute run-paths are allowed" 1>&2
@@ -1136,11 +1131,11 @@ compiler."
;;
-static)
- # If we have no pic_flag, then this is the same as -all-static.
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- compile_command="$compile_command $link_static_flag"
- finalize_command="$finalize_command $link_static_flag"
- fi
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
continue
;;
@@ -1154,28 +1149,71 @@ compiler."
continue
;;
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
# Some other compiler flag.
-* | +*)
# Unknown arguments in both finalize_command and compile_command need
# to be aesthetically quoted because they are evaled later.
arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
arg="\"$arg\""
;;
esac
;;
- *.o | *.obj | *.a | *.lib)
- # A standard object.
- objs="$objs $arg"
- ;;
-
- *.lo)
- # A library object.
+ *.lo | *.$objext)
+ # A library or standard object.
if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
+ # This file was specified with -dlopen.
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $arg"
prev=
continue
else
@@ -1188,357 +1226,890 @@ compiler."
# Preload the old-style object.
dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
prev=
+ else
+ case $arg in
+ *.lo) libobjs="$libobjs $arg" ;;
+ *) objs="$objs $arg" ;;
+ esac
fi
- libobjs="$libobjs $arg"
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
;;
*.la)
# A libtool-controlled library.
- dlname=
- libdir=
- library_names=
- old_library=
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d $output_objdir; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ specialdeplibs=
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ libs="$libs $deplib"
+ done
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test $linkmode = prog; then
+ # Determine which files to process
+ case $pass in
+ dlopen)
+ libs="$dlfiles"
+ save_deplibs="$deplibs" # Collect dlpreopened libraries
+ deplibs=
+ ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -l*)
+ if test $linkmode = oldlib && test $linkmode = obj; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2
+ continue
+ fi
+ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}.la"
+ if test -f "$lib"; then
+ found=yes
+ break
+ fi
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test $pass = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test $pass = scan; then
+ deplibs="$deplib $deplibs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test $pass = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test $pass = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ if test "$deplibs_check_method" != pass_all; then
+ echo
+ echo "*** Warning: This library needs some functionality provided by $deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ else
+ echo
+ echo "*** Warning: Linking the shared library $output against the"
+ echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test $pass != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test $found = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib'" 1>&2
+ exit 1
+ fi
# Check to see that this really is a libtool archive.
- if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
else
- $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
exit 1
fi
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
# If the library was installed with an old release of libtool,
# it will not redefine variable installed.
installed=yes
# Read the .la file
- # If there is no directory component, then add one.
- case "$arg" in
- */* | *\\*) . $arg ;;
- *) . ./$arg ;;
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
esac
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test $linkmode = oldlib && test $linkmode = obj; }; then
+ # Add dl[pre]opened files of deplib
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test $pass = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit 1
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test $linkmode != prog && test $linkmode != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit 1
+ fi
+ continue
+ fi # $pass = conv
+
# Get the name of the library we link against.
linklib=
for l in $old_library $library_names; do
linklib="$l"
done
-
if test -z "$linklib"; then
- $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
exit 1
fi
- # Find the relevant object directory and library name.
- name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
-
- if test "X$installed" = Xyes; then
- dir="$libdir"
- else
- dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$arg"; then
- dir="$objdir"
+ # This library was specified with -dlopen.
+ if test $pass = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit 1
+ fi
+ if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload.
+ dlprefiles="$dlprefiles $lib"
else
- dir="$dir/$objdir"
+ newdlfiles="$newdlfiles $lib"
fi
- fi
-
- if test -n "$dependency_libs"; then
- # Extract -R and -L from dependency_libs
- temp_deplibs=
- for deplib in $dependency_libs; do
- case "$deplib" in
- -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
- case " $rpath $xrpath " in
- *" $temp_xrpath "*) ;;
- *) xrpath="$xrpath $temp_xrpath";;
- esac;;
- -L*) case "$compile_command $temp_deplibs " in
- *" $deplib "*) ;;
- *) temp_deplibs="$temp_deplibs $deplib";;
- esac
- temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- case " $lib_search_path " in
- *" $temp_dir "*) ;;
- *) lib_search_path="$lib_search_path $temp_dir";;
- esac
- ;;
- *) temp_deplibs="$temp_deplibs $deplib";;
- esac
- done
- dependency_libs="$temp_deplibs"
- fi
-
- if test -z "$libdir"; then
- # It is a libtool convenience library, so add in its objects.
- convenience="$convenience $dir/$old_library"
- old_convenience="$old_convenience $dir/$old_library"
- deplibs="$deplibs$dependency_libs"
- compile_command="$compile_command $dir/$old_library$dependency_libs"
- finalize_command="$finalize_command $dir/$old_library$dependency_libs"
continue
- fi
+ fi # $pass = dlopen
- # This library was specified with -dlopen.
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
- # If there is no dlname, no dlopen support or we're linking statically,
- # we need to preload.
- prev=dlprefiles
- else
- # We should not create a dependency on this library, but we
- # may need any libraries it requires.
- compile_command="$compile_command$dependency_libs"
- finalize_command="$finalize_command$dependency_libs"
- prev=
- continue
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
fi
- fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- # The library was specified with -dlpreopen.
- if test "$prev" = dlprefiles; then
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test $pass = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit 1
+ fi
# Prefer using a static library (so that no silly _DYNAMIC symbols
# are required to link).
if test -n "$old_library"; then
- dlprefiles="$dlprefiles $dir/$old_library"
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
else
- dlprefiles="$dlprefiles $dir/$linklib"
+ newdlprefiles="$newdlprefiles $dir/$linklib"
fi
- prev=
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test $linkmode = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs"
+ fi
+ continue
fi
- if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
- link_against_libtool_libs="$link_against_libtool_libs $arg"
- if test -n "$shlibpath_var"; then
- # Make sure the rpath contains only unique directories.
- case "$temp_rpath " in
- *" $dir "*) ;;
- *) temp_rpath="$temp_rpath $dir" ;;
- esac
+ if test $linkmode = prog && test $pass != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
fi
- # We need an absolute path.
- case "$dir" in
- [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
- $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
- absdir="$dir"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test $linkalldeplibs = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
fi
- ;;
- esac
-
- # This is the magic to use -rpath.
- # Skip directories that are in the system default run-time
- # search path, unless they have been requested with -R.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
esac
- ;;
- esac
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
+ link_static=no # Whether the deplib will be linked statically
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ # Link against this shared library
+
+ if test "$linkmode,$pass" = "prog,link" ||
+ { test $linkmode = lib && test $hardcode_into_libs = yes; }; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
esac
- ;;
- esac
+ if test $linkmode = prog; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+ fi
+ fi # $linkmode,$pass = prog,link...
- lib_linked=yes
- case "$hardcode_action" in
- immediate | unsupported)
- if test "$hardcode_direct" = no; then
- compile_command="$compile_command $dir/$linklib"
- deplibs="$deplibs $dir/$linklib"
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2*)
- dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
- if test -n "$dllsearchpath"; then
- dllsearchpath="$dllsearchpath:$dllsearchdir"
- else
- dllsearchpath="$dllsearchdir"
- fi
- ;;
- esac
- elif test "$hardcode_minus_L" = no; then
- case "$host" in
- *-*-sunos*)
- compile_shlibpath="$compile_shlibpath$dir:"
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin*)
+ major=`expr $current - $age`
+ versuffix="-$major"
;;
esac
- case "$compile_command " in
- *" -L$dir "*) ;;
- *) compile_command="$compile_command -L$dir";;
- esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -L$dir -l$name"
- elif test "$hardcode_shlibpath_var" = no; then
- case ":$compile_shlibpath:" in
- *":$dir:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$dir:";;
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`echo $soroot | sed -e 's/^.*\///'`
+ newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ eval cmds=\"$extract_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ eval cmds=\"$old_archive_from_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n $old_archive_from_expsyms_cmds
+
+ if test $linkmode = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit 1
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -l$name"
+ fi
+ if test $linkmode = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
else
- lib_linked=no
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
fi
- ;;
+ fi
- relink)
+ if test $linkmode = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
if test "$hardcode_direct" = yes; then
- compile_command="$compile_command $absdir/$linklib"
- deplibs="$deplibs $absdir/$linklib"
+ add="$libdir/$linklib"
elif test "$hardcode_minus_L" = yes; then
- case "$compile_command " in
- *" -L$absdir "*) ;;
- *) compile_command="$compile_command -L$absdir";;
- esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -L$absdir -l$name"
+ add_dir="-L$libdir"
+ add="-l$name"
elif test "$hardcode_shlibpath_var" = yes; then
- case ":$compile_shlibpath:" in
- *":$absdir:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$absdir:";;
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -l$name"
+ add="-l$name"
else
- lib_linked=no
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ add="-l$name"
fi
- ;;
-
- *)
- lib_linked=no
- ;;
- esac
-
- if test "$lib_linked" != yes; then
- $echo "$modename: configuration error: unsupported hardcode properties"
- exit 1
- fi
- # Finalize command for both is simple: just hardcode it.
- if test "$hardcode_direct" = yes; then
- finalize_command="$finalize_command $libdir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- case "$finalize_command " in
- *" -L$libdir "*) ;;
- *) finalize_command="$finalize_command -L$libdir";;
- esac
- finalize_command="$finalize_command -l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- case ":$finalize_shlibpath:" in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
- esac
- finalize_command="$finalize_command -l$name"
- else
- # We cannot seem to hardcode it, guess we'll fake it.
- case "$finalize_command " in
- *" -L$dir "*) ;;
- *) finalize_command="$finalize_command -L$libdir";;
- esac
- finalize_command="$finalize_command -l$name"
+ if test $linkmode = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
fi
- else
- # Transform directly to old archives if we don't build new libraries.
- if test -n "$pic_flag" && test -z "$old_library"; then
- $echo "$modename: cannot find static library for \`$arg'" 1>&2
- exit 1
+ elif test $linkmode = prog; then
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
fi
+ # Try to link the static library
# Here we assume that one of hardcode_direct or hardcode_minus_L
# is not unsupported. This is valid on all known static and
# shared platforms.
if test "$hardcode_direct" != unsupported; then
test -n "$old_library" && linklib="$old_library"
- compile_command="$compile_command $dir/$linklib"
- finalize_command="$finalize_command $dir/$linklib"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
else
- case "$compile_command " in
- *" -L$dir "*) ;;
- *) compile_command="$compile_command -L$dir";;
- esac
- compile_command="$compile_command -l$name"
- case "$finalize_command " in
- *" -L$dir "*) ;;
- *) finalize_command="$finalize_command -L$dir";;
- esac
- finalize_command="$finalize_command -l$name"
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ echo
+ echo "*** Warning: This library needs some functionality provided by $lib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ echo "*** Therefore, libtool will create a static module, that should work "
+ echo "*** as long as the dlopening application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test $linkmode = lib; then
+ if test -n "$dependency_libs" &&
+ { test $hardcode_into_libs != yes || test $build_old_libs = yes ||
+ test $link_static = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
fi
- fi
-
- # Add in any libraries that this one depends upon.
- compile_command="$compile_command$dependency_libs"
- finalize_command="$finalize_command$dependency_libs"
- continue
- ;;
- # Some other compiler argument.
- *)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- ;;
- esac
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ tmp_libs="$tmp_libs $deplib"
+ done
- # Now actually substitute the argument into the commands.
- if test -n "$arg"; then
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
+ if test $link_all_deplibs != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="-L$absdir/$objdir"
+ else
+ eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="-L$absdir"
+ fi
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$deplibs $path" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ if test $pass = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
fi
- done
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
- eval arg=\"$export_dynamic_flag_spec\"
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
-
- oldlibs=
- # calculate the name of the file, without its directory
- outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
- libobjs_save="$libobjs"
-
- case "$output" in
- "")
- $echo "$modename: you must specify an output file" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
+ if test $pass != dlopen; then
+ test $pass != scan && dependency_libs="$newdependency_libs"
+ if test $pass != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
- *.a | *.lib)
- if test -n "$link_against_libtool_libs"; then
- $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
- exit 1
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
fi
-
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ if test "$pass" = "conv" &&
+ { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then
+ libs="$deplibs" # reset libs
+ deplibs=
fi
+ done # for pass
+ if test $linkmode = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+ case $linkmode in
+ oldlib)
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
fi
@@ -1566,11 +2137,12 @@ compiler."
# Now set the variables for building old libraries.
build_libtool_libs=no
oldlibs="$output"
+ objs="$objs$old_deplibs"
;;
- *.la)
+ lib)
# Make sure we only generate libraries of the form `libNAME.la'.
- case "$outputname" in
+ case $outputname in
lib*)
name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
eval libname=\"$libname_spec\"
@@ -1591,26 +2163,20 @@ compiler."
;;
esac
- output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$output_objdir" = "X$output"; then
- output_objdir="$objdir"
- else
- output_objdir="$output_objdir/$objdir"
- fi
-
if test -n "$objs"; then
- $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
- exit 1
- fi
-
- # How the heck are we supposed to write a wrapper for a shared library?
- if test -n "$link_against_libtool_libs"; then
- $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
- exit 1
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit 1
+ else
+ echo
+ echo "*** Warning: Linking the shared library $output against the non-libtool"
+ echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
fi
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
fi
set dummy $rpath
@@ -1628,7 +2194,6 @@ compiler."
build_libtool_libs=convenience
build_old_libs=yes
fi
- dependency_libs="$deplibs"
if test -n "$vinfo"; then
$echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
@@ -1640,7 +2205,7 @@ compiler."
else
# Parse the version information argument.
- IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ save_ifs="$IFS"; IFS=':'
set dummy $vinfo 0 0 0
IFS="$save_ifs"
@@ -1655,8 +2220,8 @@ compiler."
age="$4"
# Check that each of the things are valid numbers.
- case "$current" in
- 0 | [1-9] | [1-9][0-9]*) ;;
+ case $current in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
*)
$echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
@@ -1664,8 +2229,8 @@ compiler."
;;
esac
- case "$revision" in
- 0 | [1-9] | [1-9][0-9]*) ;;
+ case $revision in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
*)
$echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
@@ -1673,8 +2238,8 @@ compiler."
;;
esac
- case "$age" in
- 0 | [1-9] | [1-9][0-9]*) ;;
+ case $age in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
*)
$echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
@@ -1692,12 +2257,31 @@ compiler."
major=
versuffix=
verstring=
- case "$version_type" in
+ case $version_type in
none) ;;
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
irix)
major=`expr $current - $age + 1`
- versuffix="$major.$revision"
verstring="sgi$major.$revision"
# Add in all the interfaces that we are compatible with.
@@ -1707,6 +2291,10 @@ compiler."
loop=`expr $loop - 1`
verstring="sgi$major.$iface:$verstring"
done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
;;
linux)
@@ -1736,21 +2324,11 @@ compiler."
versuffix=".$current.$revision"
;;
- freebsd-aout)
- major=".$current"
- versuffix=".$current.$revision";
- ;;
-
- freebsd-elf)
- major=".$current"
- versuffix=".$current";
- ;;
-
windows)
- # Like Linux, but with '-' rather than '.', since we only
- # want one extension on Windows 95.
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
major=`expr $current - $age`
- versuffix="-$major-$age-$revision"
+ versuffix="-$major"
;;
*)
@@ -1764,6 +2342,16 @@ compiler."
if test -z "$vinfo" && test -n "$release"; then
major=
verstring="0.0"
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=""
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
if test "$need_version" = no; then
versuffix=
else
@@ -1777,7 +2365,7 @@ compiler."
versuffix=
verstring=""
fi
-
+
# Check to see if the archive will have undefined symbols.
if test "$allow_undefined" = yes; then
if test "$allow_undefined_flag" = unsupported; then
@@ -1789,38 +2377,12 @@ compiler."
# Don't allow undefined symbols.
allow_undefined_flag="$no_undefined_flag"
fi
-
- dependency_libs="$deplibs"
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
- # these systems don't actually have a c library (as such)!
- ;;
-
- #### local change for Sleepycat DB: [#2380]
- # The following case is added, since the linker's -pthread
- # option implicitly controls use of -lc or -lc_r.
- *freebsd*)
- # defer to whether the user wants -lc, or -lc_r
- ;;
-
- *)
- # Add libc to deplibs on all other systems.
- deplibs="$deplibs -lc"
- ;;
- esac
fi
- # Create the output directory, or remove our outputs if we need to.
- if test -d $output_objdir; then
+ if test "$mode" != relink; then
+ # Remove our outputs.
$show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
$run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
- else
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
- status=$?
- if test $status -ne 0 && test ! -d $output_objdir; then
- exit $status
- fi
fi
# Now set the variables for building old libraries.
@@ -1831,7 +2393,80 @@ compiler."
oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
fi
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+ lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'`
+ deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'`
+ dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'`
+ done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test $hardcode_into_libs != yes || test $build_old_libs = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ #### Local change for Sleepycat's Berkeley DB [#2380]:
+ # FreeBSD, like OpenBSD, uses libc/libc_r and should not
+ # link against libc/c_r explicitly; the -pthread linker flag
+ # implicitly controls use of -lc and -lc_r.
+ *-*-freebsd*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test $build_libtool_need_lc = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
# Transform deplibs into only deplibs that can be linked in shared.
name_save=$name
libname_save=$libname
@@ -1846,7 +2481,7 @@ compiler."
major=""
newdeplibs=
droppeddeps=no
- case "$deplibs_check_method" in
+ case $deplibs_check_method in
pass_all)
# Don't check for shared/static. Everything works.
# This might be a little naive. We might want to check
@@ -1871,7 +2506,7 @@ EOF
for i in $deplibs; do
name="`expr $i : '-l\(.*\)'`"
# If $name is empty we are operating on a -L argument.
- if test "$name" != "" ; then
+ if test -n "$name" && test "$name" != "0"; then
libname=`eval \\$echo \"$libname_spec\"`
deplib_matches=`eval \\$echo \"$library_names_spec\"`
set dummy $deplib_matches
@@ -1896,7 +2531,7 @@ EOF
for i in $deplibs; do
name="`expr $i : '-l\(.*\)'`"
# If $name is empty we are operating on a -L argument.
- if test "$name" != "" ; then
+ if test -n "$name" && test "$name" != "0"; then
$rm conftest
$CC -o conftest conftest.c $i
# Did it work?
@@ -1932,19 +2567,19 @@ EOF
;;
file_magic*)
set dummy $deplibs_check_method
- file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
for a_deplib in $deplibs; do
name="`expr $a_deplib : '-l\(.*\)'`"
# If $name is empty we are operating on a -L argument.
- if test "$name" != "" ; then
+ if test -n "$name" && test "$name" != "0"; then
libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path; do
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
for potent_lib in $potential_libs; do
# Follow soft links.
if ls -lLd "$potent_lib" 2>/dev/null \
| grep " -> " >/dev/null; then
- continue
+ continue
fi
# The statement above tries to avoid entering an
# endless loop below, in case of cyclic links.
@@ -1954,7 +2589,7 @@ EOF
potlib="$potent_lib"
while test -h "$potlib" 2>/dev/null; do
potliblink=`ls -ld $potlib | sed 's/.* -> //'`
- case "$potliblink" in
+ case $potliblink in
[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
*) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
esac
@@ -1982,6 +2617,40 @@ EOF
fi
done # Gone through all deplibs.
;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ if eval echo \"$potent_lib\" 2>/dev/null \
+ | sed 10q \
+ | egrep "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
none | unknown | *)
newdeplibs=""
if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
@@ -2004,6 +2673,13 @@ EOF
libname=$libname_save
name=$name_save
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
if test "$droppeddeps" = yes; then
if test "$module" = yes; then
echo
@@ -2029,6 +2705,21 @@ EOF
echo "*** The inter-library dependencies that have been dropped here will be"
echo "*** automatically added whenever a program is linked with this library"
echo "*** or is declared to -dlopen it."
+
+ if test $allow_undefined = no; then
+ echo
+ echo "*** Since this library must not contain undefined symbols,"
+ echo "*** because either the platform does not support them or"
+ echo "*** it was explicitly requested with -no-undefined,"
+ echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
fi
fi
# Done checking deplibs!
@@ -2039,9 +2730,64 @@ EOF
library_names=
old_library=
dlname=
-
+
# Test again, we may have decided not to build it any more
if test "$build_libtool_libs" = yes; then
+ if test $hardcode_into_libs = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
# Get the real and link names of the library.
eval library_names=\"$library_names_spec\"
set dummy $library_names
@@ -2053,6 +2799,7 @@ EOF
else
soname="$realname"
fi
+ test -z "$dlname" && dlname=$soname
lib="$output_objdir/$realname"
for link
@@ -2087,7 +2834,7 @@ EOF
export_symbols="$output_objdir/$libname.exp"
$run $rm $export_symbols
eval cmds=\"$export_symbols_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -2124,7 +2871,7 @@ EOF
for xlib in $convenience; do
# Extract the objects.
- case "$xlib" in
+ case $xlib in
[\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
*) xabs=`pwd`"/$xlib" ;;
esac
@@ -2149,7 +2896,12 @@ EOF
if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
eval flag=\"$thread_safe_flag_spec\"
- linkopts="$linkopts $flag"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
fi
# Do each of the archive commands.
@@ -2158,7 +2910,7 @@ EOF
else
eval cmds=\"$archive_cmds\"
fi
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -2166,6 +2918,12 @@ EOF
done
IFS="$save_ifs"
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+ exit 0
+ fi
+
# Create links to the real library.
for linkname in $linknames; do
if test "$realname" != "$linkname"; then
@@ -2182,12 +2940,7 @@ EOF
fi
;;
- *.lo | *.o | *.obj)
- if test -n "$link_against_libtool_libs"; then
- $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
- exit 1
- fi
-
+ obj)
if test -n "$deplibs"; then
$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
fi
@@ -2212,9 +2965,9 @@ EOF
$echo "$modename: warning: \`-release' is ignored for objects" 1>&2
fi
- case "$output" in
+ case $output in
*.lo)
- if test -n "$objs"; then
+ if test -n "$objs$old_deplibs"; then
$echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
exit 1
fi
@@ -2238,7 +2991,7 @@ EOF
gentop=
# reload_cmds runs $LD directly, so let us get rid of
# -Wl from whole_archive_flag_spec
- wl=
+ wl=
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec"; then
@@ -2257,7 +3010,7 @@ EOF
for xlib in $convenience; do
# Extract the objects.
- case "$xlib" in
+ case $xlib in
[\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
*) xabs=`pwd`"/$xlib" ;;
esac
@@ -2281,11 +3034,11 @@ EOF
fi
# Create the old-style object.
- reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
output="$obj"
eval cmds=\"$reload_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -2316,12 +3069,12 @@ EOF
exit 0
fi
- if test -n "$pic_flag"; then
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
# Only do commands if we really have different PIC objects.
reload_objs="$libobjs $reload_conv_objs"
output="$libobj"
eval cmds=\"$reload_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -2352,8 +3105,10 @@ EOF
exit 0
;;
- # Anything else should be a program.
- *)
+ prog)
+ case $host in
+ *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
if test -n "$vinfo"; then
$echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
fi
@@ -2363,20 +3118,27 @@ EOF
fi
if test "$preload" = yes; then
- if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
test "$dlopen_self_static" = unknown; then
$echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
- fi
+ fi
fi
-
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
if test -n "$rpath$xrpath"; then
# If the user specified any rpath flags, then add them.
for libdir in $rpath $xrpath; do
# This is the magic to use -rpath.
- case "$compile_rpath " in
- *" $libdir "*) ;;
- *) compile_rpath="$compile_rpath $libdir" ;;
- esac
case "$finalize_rpath " in
*" $libdir "*) ;;
*) finalize_rpath="$finalize_rpath $libdir" ;;
@@ -2394,7 +3156,7 @@ EOF
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
- case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
@@ -2412,6 +3174,14 @@ EOF
*) perm_rpath="$perm_rpath $libdir" ;;
esac
fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ ;;
+ esac
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
@@ -2430,7 +3200,7 @@ EOF
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
- case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
@@ -2457,23 +3227,6 @@ EOF
fi
finalize_rpath="$rpath"
- output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$output_objdir" = "X$output"; then
- output_objdir="$objdir"
- else
- output_objdir="$output_objdir/$objdir"
- fi
-
- # Create the binary in the object directory, then wrap it.
- if test ! -d $output_objdir; then
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
- status=$?
- if test $status -ne 0 && test ! -d $output_objdir; then
- exit $status
- fi
- fi
-
if test -n "$libobjs" && test "$build_old_libs" = yes; then
# Transform all the library objects into standard objects.
compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
@@ -2490,7 +3243,7 @@ EOF
fi
if test -n "$dlsyms"; then
- case "$dlsyms" in
+ case $dlsyms in
"") ;;
*.c)
# Discover the nlist of each of the dlfiles.
@@ -2522,7 +3275,7 @@ extern \"C\" {
test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
# Add our own program objects to the symbol list.
- progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
for arg in $progfiles; do
$show "extracting global C symbols from \`$arg'"
$run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
@@ -2532,7 +3285,7 @@ extern \"C\" {
$run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
$run eval '$mv "$nlist"T "$nlist"'
fi
-
+
if test -n "$export_symbols_regex"; then
$run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
$run eval '$mv "$nlist"T "$nlist"'
@@ -2584,27 +3337,25 @@ extern \"C\" {
#undef lt_preloaded_symbols
#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
+# define lt_ptr void *
#else
-# define lt_ptr_t char *
+# define lt_ptr char *
# define const
#endif
/* The mapping between symbol names and symbols. */
const struct {
const char *name;
- lt_ptr_t address;
+ lt_ptr address;
}
lt_preloaded_symbols[] =
{\
"
- sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
- -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
- < "$nlist" >> "$output_objdir/$dlsyms"
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
$echo >> "$output_objdir/$dlsyms" "\
- {0, (lt_ptr_t) 0}
+ {0, (lt_ptr) 0}
};
/* This works around a problem in FreeBSD linker */
@@ -2621,7 +3372,7 @@ static const void *lt_preloaded_setup() {
fi
pic_flag_for_symtable=
- case "$host" in
+ case $host in
# compiling the symbol table file with pic_flag works around
# a FreeBSD bug that causes programs to crash when -lm is
# linked before any other PIC object. But we must not use
@@ -2666,7 +3417,7 @@ static const void *lt_preloaded_setup() {
finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
fi
- if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ if test $need_relink = no || test "$build_libtool_libs" != yes; then
# Replace the output file specification.
compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
link_command="$compile_command$compile_rpath"
@@ -2675,7 +3426,7 @@ static const void *lt_preloaded_setup() {
$show "$link_command"
$run eval "$link_command"
status=$?
-
+
# Delete the generated files.
if test -n "$dlsyms"; then
$show "$rm $output_objdir/${outputname}S.${objext}"
@@ -2689,7 +3440,7 @@ static const void *lt_preloaded_setup() {
# We should set the shlibpath_var
rpath=
for dir in $temp_rpath; do
- case "$dir" in
+ case $dir in
[\\/]* | [A-Za-z]:[\\/]*)
# Absolute path.
rpath="$rpath$dir:"
@@ -2731,11 +3482,24 @@ static const void *lt_preloaded_setup() {
fi
fi
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit 0
+ fi
+
if test "$hardcode_action" = relink; then
# Fast installation is not supported
link_command="$compile_var$compile_command$compile_rpath"
relink_command="$finalize_var$finalize_command$finalize_rpath"
-
+
$echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
$echo "$modename: \`$output' will be relinked during installation" 1>&2
else
@@ -2755,7 +3519,7 @@ static const void *lt_preloaded_setup() {
# Replace the output file specification.
link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
+
# Delete the old output files.
$run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
@@ -2767,12 +3531,24 @@ static const void *lt_preloaded_setup() {
# Quote the relink command for shipping.
if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="cd `pwd`; $relink_command"
relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
fi
# Quote $echo for shipping.
if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
- case "$0" in
+ case $0 in
[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
*) qecho="$SHELL `pwd`/$0 --fallback-echo";;
esac
@@ -2788,6 +3564,11 @@ static const void *lt_preloaded_setup() {
case $output in
*.exe) output=`echo $output|sed 's,.exe$,,'` ;;
esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*) exeext=.exe ;;
+ *) exeext= ;;
+ esac
$rm $output
trap "$rm $output; exit 1" 1 2 15
@@ -2817,7 +3598,7 @@ relink_command=\"$relink_command\"
# This environment variable determines our operation mode.
if test \"\$libtool_install_magic\" = \"$magic\"; then
# install mode needs the following variable:
- link_against_libtool_libs='$link_against_libtool_libs'
+ notinst_deplibs='$notinst_deplibs'
else
# When we are sourced in execute mode, \$file and \$echo are already set.
if test \"\$libtool_execute_magic\" != \"$magic\"; then
@@ -2850,7 +3631,7 @@ else
# If there was a directory component, then change thisdir.
if test \"x\$destdir\" != \"x\$file\"; then
case \"\$destdir\" in
- [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
*) thisdir=\"\$thisdir/\$destdir\" ;;
esac
fi
@@ -2866,9 +3647,9 @@ else
if test "$fast_install" = yes; then
echo >> $output "\
- program=lt-'$outputname'
+ program=lt-'$outputname'$exeext
progdir=\"\$thisdir/$objdir\"
-
+
if test ! -f \"\$progdir/\$program\" || \\
{ file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
test \"X\$file\" != \"X\$progdir/\$program\"; }; then
@@ -2885,8 +3666,9 @@ else
# relink executable if necessary
if test -n \"\$relink_command\"; then
- if (cd \"\$thisdir\" && eval \$relink_command); then :
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
else
+ $echo \"\$relink_command_output\" >&2
$rm \"\$progdir/\$file\"
exit 1
fi
@@ -2935,9 +3717,9 @@ else
# Run the actual program with our arguments.
"
case $host in
- # win32 systems need to use the prog path for dll
- # lookup to work
- *-*-cygwin*)
+ # win32 systems need to use the prog path for dll
+ # lookup to work
+ *-*-cygwin* | *-*-pw32*)
$echo >> $output "\
exec \$progdir/\$program \${1+\"\$@\"}
"
@@ -2991,7 +3773,7 @@ fi\
oldobjs="$libobjs_save"
build_libtool_libs=no
else
- oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+ oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
fi
addlibs="$old_convenience"
fi
@@ -3007,11 +3789,11 @@ fi\
exit $status
fi
generated="$generated $gentop"
-
+
# Add in members from convenience archives.
for xlib in $addlibs; do
# Extract the objects.
- case "$xlib" in
+ case $xlib in
[\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
*) xabs=`pwd`"/$xlib" ;;
esac
@@ -3057,7 +3839,7 @@ fi\
eval cmds=\"$old_archive_cmds\"
fi
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -3072,19 +3854,26 @@ fi\
fi
# Now create the libtool archive.
- case "$output" in
+ case $output in
*.la)
old_library=
test "$build_old_libs" = yes && old_library="$libname.$libext"
$show "creating $output"
- if test -n "$xrpath"; then
- temp_xrpath=
- for libdir in $xrpath; do
- temp_xrpath="$temp_xrpath -R$libdir"
- done
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="cd `pwd`; $SHELL $0 --mode=relink $libtool_args"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
# Only create the output if not a dry run.
if test -z "$run"; then
@@ -3094,8 +3883,52 @@ fi\
break
fi
output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
fi
$rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
$echo > $output "\
# $outputname - a libtool library file
# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
@@ -3104,7 +3937,7 @@ fi\
# It is necessary for linking the library.
# The name that we can dlopen(3).
-dlname='$dlname'
+dlname='$tdlname'
# Names of this library.
library_names='$library_names'
@@ -3123,16 +3956,23 @@ revision=$revision
# Is this an already installed library?
installed=$installed
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
# Directory that this library needs to be installed in:
-libdir='$install_libdir'\
-"
+libdir='$install_libdir'"
+ if test "$installed" = no && test $need_relink = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
done
fi
# Do a symbolic link so that the libtool archive can be found in
# LD_LIBRARY_PATH before the program is installed.
$show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
- $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
;;
esac
exit 0
@@ -3144,10 +3984,12 @@ libdir='$install_libdir'\
# There may be an optional sh(1) argument at the beginning of
# install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
# Aesthetically quote it.
arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
+ case $arg in
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
arg="\"$arg\""
;;
@@ -3163,7 +4005,7 @@ libdir='$install_libdir'\
# The real first argument should be the name of the installation program.
# Aesthetically quote it.
arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
+ case $arg in
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
arg="\"$arg\""
;;
@@ -3186,7 +4028,7 @@ libdir='$install_libdir'\
continue
fi
- case "$arg" in
+ case $arg in
-d) isdir=yes ;;
-f) prev="-f" ;;
-g) prev="-g" ;;
@@ -3211,7 +4053,7 @@ libdir='$install_libdir'\
# Aesthetically quote the argument.
arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
+ case $arg in
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
arg="\"$arg\""
;;
@@ -3262,11 +4104,11 @@ libdir='$install_libdir'\
exit 1
fi
fi
- case "$destdir" in
+ case $destdir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
for file in $files; do
- case "$file" in
+ case $file in
*.lo) ;;
*)
$echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
@@ -3288,8 +4130,8 @@ libdir='$install_libdir'\
for file in $files; do
# Do each installation.
- case "$file" in
- *.a | *.lib)
+ case $file in
+ *.$libext)
# Do the static libraries later.
staticlibs="$staticlibs $file"
;;
@@ -3305,8 +4147,9 @@ libdir='$install_libdir'\
library_names=
old_library=
+ relink_command=
# If there is no directory component, then add one.
- case "$file" in
+ case $file in
*/* | *\\*) . $file ;;
*) . ./$file ;;
esac
@@ -3325,10 +4168,20 @@ libdir='$install_libdir'\
esac
fi
- dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
test "X$dir" = "X$file/" && dir=
dir="$dir$objdir"
+ if test -n "$relink_command"; then
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ continue
+ fi
+ fi
+
# See the names of the shared library.
set dummy $library_names
if test -n "$2"; then
@@ -3336,9 +4189,16 @@ libdir='$install_libdir'\
shift
shift
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
# Install the shared library and build the symlinks.
- $show "$install_prog $dir/$realname $destdir/$realname"
- $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
if test $# -gt 0; then
# Delete the old symlinks, and create new ones.
@@ -3354,7 +4214,7 @@ libdir='$install_libdir'\
# Do each command in the postinstall commands.
lib="$destdir/$realname"
eval cmds=\"$postinstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -3385,11 +4245,11 @@ libdir='$install_libdir'\
fi
# Deduce the name of the destination old-style object file.
- case "$destfile" in
+ case $destfile in
*.lo)
staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
;;
- *.o | *.obj)
+ *.$objext)
staticdest="$destfile"
destfile=
;;
@@ -3428,39 +4288,46 @@ libdir='$install_libdir'\
# Do a test to see if this is really a libtool program.
if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- link_against_libtool_libs=
+ notinst_deplibs=
relink_command=
# If there is no directory component, then add one.
- case "$file" in
+ case $file in
*/* | *\\*) . $file ;;
*) . ./$file ;;
esac
# Check the variables that should have been set.
- if test -z "$link_against_libtool_libs"; then
+ if test -z "$notinst_deplibs"; then
$echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
exit 1
fi
finalize=yes
- for lib in $link_against_libtool_libs; do
+ for lib in $notinst_deplibs; do
# Check to see that each library is installed.
libdir=
if test -f "$lib"; then
# If there is no directory component, then add one.
- case "$lib" in
+ case $lib in
*/* | *\\*) . $lib ;;
*) . ./$lib ;;
esac
fi
- libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
if test -n "$libdir" && test ! -f "$libfile"; then
$echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
finalize=no
fi
done
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
outputname=
if test "$fast_install" = no && test -n "$relink_command"; then
if test "$finalize" = yes && test -z "$run"; then
@@ -3472,6 +4339,7 @@ libdir='$install_libdir'\
$echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
continue
fi
+ file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
outputname="$tmpdir/$file"
# Replace the output file specification.
relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
@@ -3493,6 +4361,23 @@ libdir='$install_libdir'\
fi
fi
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyways
+ case $install_prog,$host in
+ /usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`echo $destfile | sed -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
$show "$install_prog$stripme $file $destfile"
$run eval "$install_prog\$stripme \$file \$destfile" || exit $?
test -n "$outputname" && ${rm}r "$tmpdir"
@@ -3509,9 +4394,14 @@ libdir='$install_libdir'\
$show "$install_prog $file $oldlib"
$run eval "$install_prog \$file \$oldlib" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
# Do each command in the postinstall commands.
eval cmds=\"$old_postinstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -3527,11 +4417,10 @@ libdir='$install_libdir'\
if test -n "$current_libdirs"; then
# Maybe just do a dry run.
test -n "$run" && current_libdirs=" -n$current_libdirs"
- exec $SHELL $0 --finish$current_libdirs
- exit 1
+ exec_cmd='$SHELL $0 --finish$current_libdirs'
+ else
+ exit 0
fi
-
- exit 0
;;
# libtool finish mode
@@ -3550,7 +4439,7 @@ libdir='$install_libdir'\
if test -n "$finish_cmds"; then
# Do each command in the finish commands.
eval cmds=\"$finish_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
$show "$cmd"
@@ -3569,7 +4458,7 @@ libdir='$install_libdir'\
fi
# Exit here if they wanted silent mode.
- test "$show" = : && exit 0
+ test "$show" = ":" && exit 0
echo "----------------------------------------------------------------------"
echo "Libraries have been installed in:"
@@ -3579,7 +4468,7 @@ libdir='$install_libdir'\
echo
echo "If you ever happen to want to link against installed libraries"
echo "in a given directory, LIBDIR, you must either use libtool, and"
- echo "specify the full pathname of the library, or use \`-LLIBDIR'"
+ echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
echo "flag during linking and do at least one of the following:"
if test -n "$shlibpath_var"; then
echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
@@ -3629,7 +4518,7 @@ libdir='$install_libdir'\
fi
dir=
- case "$file" in
+ case $file in
*.la)
# Check to see that this really is a libtool archive.
if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
@@ -3644,7 +4533,7 @@ libdir='$install_libdir'\
library_names=
# If there is no directory component, then add one.
- case "$file" in
+ case $file in
*/* | *\\*) . $file ;;
*) . ./$file ;;
esac
@@ -3699,13 +4588,13 @@ libdir='$install_libdir'\
args=
for file
do
- case "$file" in
+ case $file in
-*) ;;
*)
# Do a test to see if this is really a libtool program.
if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
# If there is no directory component, then add one.
- case "$file" in
+ case $file in
*/* | *\\*) . $file ;;
*) . ./$file ;;
esac
@@ -3722,8 +4611,8 @@ libdir='$install_libdir'\
if test -z "$run"; then
if test -n "$shlibpath_var"; then
- # Export the shlibpath_var.
- eval "export $shlibpath_var"
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
fi
# Restore saved enviroment variables
@@ -3734,31 +4623,35 @@ libdir='$install_libdir'\
LANG="$save_LANG"; export LANG
fi
- # Now actually exec the command.
- eval "exec \$cmd$args"
-
- $echo "$modename: cannot exec \$cmd$args"
- exit 1
+ # Now prepare to actually exec the command.
+ exec_cmd='"$cmd"$args'
else
# Display what would be done.
if test -n "$shlibpath_var"; then
- eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
- $echo "export $shlibpath_var"
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
fi
$echo "$cmd$args"
exit 0
fi
;;
- # libtool uninstall mode
- uninstall)
- modename="$modename: uninstall"
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
rm="$nonopt"
files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
for arg
do
- case "$arg" in
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
-*) rm="$rm $arg" ;;
*) files="$files $arg" ;;
esac
@@ -3770,14 +4663,42 @@ libdir='$install_libdir'\
exit 1
fi
+ rmdirs=
+
for file in $files; do
dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$objdir"
+ else
+ objdir="$dir/$objdir"
+ fi
name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test $mode = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test $mode = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
rmfiles="$file"
- case "$name" in
+ case $name in
*.la)
# Possibly a libtool archive, so verify it.
if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
@@ -3785,38 +4706,43 @@ libdir='$install_libdir'\
# Delete the libtool libraries and symlinks.
for n in $library_names; do
- rmfiles="$rmfiles $dir/$n"
+ rmfiles="$rmfiles $objdir/$n"
done
- test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
-
- $show "$rm $rmfiles"
- $run $rm $rmfiles
-
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
- eval cmds=\"$postuninstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+ test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+ if test $mode = uninstall; then
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test $? != 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd"
- done
- IFS="$save_ifs"
- fi
+ fi
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
- eval cmds=\"$old_postuninstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test $? != 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd"
- done
- IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
fi
-
- # FIXME: should reinstall the best remaining shared library.
fi
;;
@@ -3825,17 +4751,35 @@ libdir='$install_libdir'\
oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
rmfiles="$rmfiles $dir/$oldobj"
fi
- $show "$rm $rmfiles"
- $run $rm $rmfiles
;;
*)
- $show "$rm $rmfiles"
- $run $rm $rmfiles
+ # Do a test to see if this is a libtool program.
+ if test $mode = clean &&
+ (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$file
+
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ fi
;;
esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
done
- exit 0
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
;;
"")
@@ -3845,13 +4789,20 @@ libdir='$install_libdir'\
;;
esac
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$generic_help" 1>&2
- exit 1
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ fi
fi # test -z "$show_help"
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit 1
+fi
+
# We need to display help for each of the modes.
-case "$mode" in
+case $mode in
"") $echo \
"Usage: $modename [OPTION]... [MODE-ARG]...
@@ -3870,6 +4821,7 @@ Provide generalized library-building support services.
MODE must be one of the following:
+ clean remove files from the build directory
compile compile a source file into a libtool object
execute automatically set library path, then run a program
finish complete the installation of libtool libraries
@@ -3882,6 +4834,20 @@ a more detailed description of MODE."
exit 0
;;
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
compile)
$echo \
"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
@@ -3891,6 +4857,8 @@ Compile a source file into a libtool library object.
This mode accepts the following additional options:
-o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
-static always build a \`.o' file suitable for static linking
COMPILE-COMMAND is a command to be used in creating a \`standard' object file
@@ -3969,7 +4937,10 @@ The following components of LINK-COMMAND are treated specially:
try to export only the symbols matching REGEX
-LLIBDIR search LIBDIR for required installed libraries
-lNAME OUTPUT-FILE requires the installed library libNAME
+ -jnimodule build a library that can dlopened via Java JNI
-module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
-no-undefined declare that a library does not refer to external symbols
-o OUTPUT-FILE create OUTPUT-FILE from the specified objects
-release RELEASE specify package release information
@@ -4026,4 +4997,3 @@ exit 0
# mode:shell-script
# sh-indentation:2
# End:
-#! /bin/bash
diff --git a/bdb/dist/pubdef.in b/bdb/dist/pubdef.in
new file mode 100644
index 00000000000..f42363022cd
--- /dev/null
+++ b/bdb/dist/pubdef.in
@@ -0,0 +1,350 @@
+# Name
+# D == documentation
+# I == include file
+# C == Java case value (declared and initialized)
+# J == Java constant (declared only)
+DB_AFTER D I J
+DB_AGGRESSIVE D I J
+DB_ALREADY_ABORTED * I *
+DB_AM_CHKSUM * I *
+DB_AM_CL_WRITER * I *
+DB_AM_COMPENSATE * I *
+DB_AM_CREATED * I *
+DB_AM_CREATED_MSTR * I *
+DB_AM_DBM_ERROR * I *
+DB_AM_DELIMITER * I *
+DB_AM_DIRTY * I *
+DB_AM_DISCARD * I *
+DB_AM_DUP * I *
+DB_AM_DUPSORT * I *
+DB_AM_ENCRYPT * I *
+DB_AM_FIXEDLEN * I *
+DB_AM_INMEM * I *
+DB_AM_IN_RENAME * I *
+DB_AM_OPEN_CALLED * I *
+DB_AM_PAD * I *
+DB_AM_PGDEF * I *
+DB_AM_RDONLY * I *
+DB_AM_RECNUM * I *
+DB_AM_RECOVER * I *
+DB_AM_RENUMBER * I *
+DB_AM_REVSPLITOFF * I *
+DB_AM_SECONDARY * I *
+DB_AM_SNAPSHOT * I *
+DB_AM_SUBDB * I *
+DB_AM_SWAP * I *
+DB_AM_TXN * I *
+DB_AM_VERIFYING * I *
+DB_APPEND D I J
+DB_ARCH_ABS D I J
+DB_ARCH_DATA D I J
+DB_ARCH_LOG D I J
+DB_AUTO_COMMIT D I J
+DB_BEFORE D I J
+DB_BTREE D I C
+DB_BTREEMAGIC * I *
+DB_BTREEOLDVER * I *
+DB_BTREEVERSION * I *
+DB_CACHED_COUNTS * I J
+DB_CDB_ALLDB D I J
+DB_CHKSUM_SHA1 D I J
+DB_CLIENT D I J
+DB_COMMIT * I *
+DB_CONFIG D * *
+DB_CONSUME D I J
+DB_CONSUME_WAIT D I J
+DB_CREATE D I J
+DB_CURRENT D I J
+DB_CXX_NO_EXCEPTIONS D I J
+DB_DBM_HSEARCH * I *
+DB_DBT_APPMALLOC D I *
+DB_DBT_DUPOK * I *
+DB_DBT_ISSET * I *
+DB_DBT_MALLOC D I J
+DB_DBT_PARTIAL D I J
+DB_DBT_REALLOC D I J
+DB_DBT_USERMEM D I J
+DB_DELETED * I *
+DB_DIRECT D I J
+DB_DIRECT_DB D I J
+DB_DIRECT_LOG D I J
+DB_DIRTY_READ D I J
+DB_DONOTINDEX D I C
+DB_DUP D I J
+DB_DUPSORT D I J
+DB_EID_BROADCAST D I J
+DB_EID_INVALID D I J
+DB_ENCRYPT D I J
+DB_ENCRYPT_AES D I J
+DB_ENV_AUTO_COMMIT * I *
+DB_ENV_CDB * I *
+DB_ENV_CDB_ALLDB * I *
+DB_ENV_CREATE * I *
+DB_ENV_DBLOCAL * I *
+DB_ENV_DIRECT_DB * I *
+DB_ENV_DIRECT_LOG * I *
+DB_ENV_FATAL * I *
+DB_ENV_LOCKDOWN * I *
+DB_ENV_NOLOCKING * I *
+DB_ENV_NOMMAP * I *
+DB_ENV_NOPANIC * I *
+DB_ENV_OPEN_CALLED * I *
+DB_ENV_OVERWRITE * I *
+DB_ENV_PRIVATE * I *
+DB_ENV_REGION_INIT * I *
+DB_ENV_REP_CLIENT * I *
+DB_ENV_REP_LOGSONLY * I *
+DB_ENV_REP_MASTER * I *
+DB_ENV_RPCCLIENT * I *
+DB_ENV_RPCCLIENT_GIVEN * I *
+DB_ENV_SYSTEM_MEM * I *
+DB_ENV_THREAD * I *
+DB_ENV_TXN_NOSYNC * I *
+DB_ENV_TXN_WRITE_NOSYNC * I *
+DB_ENV_YIELDCPU * I *
+DB_EXCL D I J
+DB_EXTENT * I *
+DB_FAST_STAT D I J
+DB_FCNTL_LOCKING * I *
+DB_FILE_ID_LEN * I *
+DB_FIRST D I J
+DB_FLUSH D I J
+DB_FORCE D I J
+DB_GET_BOTH D I J
+DB_GET_BOTHC * I *
+DB_GET_BOTH_RANGE D I J
+DB_GET_RECNO D I J
+DB_HANDLE_LOCK * I *
+DB_HASH D I C
+DB_HASHMAGIC * I *
+DB_HASHOLDVER * I *
+DB_HASHVERSION * I *
+DB_HOME D * *
+DB_INIT_CDB D I J
+DB_INIT_LOCK D I J
+DB_INIT_LOG D I J
+DB_INIT_MPOOL D I J
+DB_INIT_TXN D I J
+DB_JAVA_CALLBACK * I *
+DB_JOINENV D I J
+DB_JOIN_ITEM D I J
+DB_JOIN_NOSORT D I J
+DB_KEYEMPTY D I C
+DB_KEYEXIST D I C
+DB_KEYFIRST D I J
+DB_KEYLAST D I J
+DB_LAST D I J
+DB_LOCKDOWN D I J
+DB_LOCKVERSION * I *
+DB_LOCK_DEADLOCK D I C
+DB_LOCK_DEFAULT D I J
+DB_LOCK_DIRTY * I *
+DB_LOCK_DUMP * I *
+DB_LOCK_EXPIRE D I J
+DB_LOCK_FREE_LOCKER * I *
+DB_LOCK_GET D I J
+DB_LOCK_GET_TIMEOUT D I J
+DB_LOCK_INHERIT * I *
+DB_LOCK_IREAD D I J
+DB_LOCK_IWR D I J
+DB_LOCK_IWRITE D I J
+DB_LOCK_MAXLOCKS D I J
+DB_LOCK_MINLOCKS D I J
+DB_LOCK_MINWRITE D I J
+DB_LOCK_NG * I *
+DB_LOCK_NORUN * I *
+DB_LOCK_NOTEXIST * I *
+DB_LOCK_NOTGRANTED D I C
+DB_LOCK_NOWAIT D I J
+DB_LOCK_OLDEST D I J
+DB_LOCK_PUT D I J
+DB_LOCK_PUT_ALL D I J
+DB_LOCK_PUT_OBJ D I J
+DB_LOCK_PUT_READ * I *
+DB_LOCK_RANDOM D I J
+DB_LOCK_READ D I J
+DB_LOCK_RECORD * I *
+DB_LOCK_REMOVE * I *
+DB_LOCK_SET_TIMEOUT * I *
+DB_LOCK_SWITCH * I *
+DB_LOCK_TIMEOUT D I J
+DB_LOCK_TRADE * I *
+DB_LOCK_UPGRADE * I *
+DB_LOCK_UPGRADE_WRITE * I *
+DB_LOCK_WAIT * I *
+DB_LOCK_WRITE D I J
+DB_LOCK_WWRITE * I *
+DB_LOCK_YOUNGEST D I J
+DB_LOGC_BUF_SIZE * I *
+DB_LOGFILEID_INVALID * I *
+DB_LOGMAGIC * I *
+DB_LOGOLDVER * I *
+DB_LOGVERSION * I *
+DB_LOG_DISK * I *
+DB_LOG_LOCKED * I *
+DB_LOG_SILENT_ERR * I *
+DB_LSTAT_ABORTED * I *
+DB_LSTAT_ERR * I *
+DB_LSTAT_EXPIRED * I *
+DB_LSTAT_FREE * I *
+DB_LSTAT_HELD * I *
+DB_LSTAT_NOTEXIST * I *
+DB_LSTAT_PENDING * I *
+DB_LSTAT_WAITING * I *
+DB_MAX_PAGES * I *
+DB_MAX_RECORDS * I *
+DB_MPOOL_CLEAN D I *
+DB_MPOOL_CREATE D I *
+DB_MPOOL_DIRTY D I *
+DB_MPOOL_DISCARD D I *
+DB_MPOOL_LAST D I *
+DB_MPOOL_NEW D I *
+DB_MULTIPLE D I J
+DB_MULTIPLE_INIT D I *
+DB_MULTIPLE_KEY D I J
+DB_MULTIPLE_KEY_NEXT D I *
+DB_MULTIPLE_NEXT D I *
+DB_MULTIPLE_RECNO_NEXT D I *
+DB_NEEDSPLIT * I *
+DB_NEXT D I J
+DB_NEXT_DUP D I J
+DB_NEXT_NODUP D I J
+DB_NOCOPY * I *
+DB_NODUPDATA D I J
+DB_NOLOCKING D I J
+DB_NOMMAP D I J
+DB_NOORDERCHK D I J
+DB_NOOVERWRITE D I J
+DB_NOPANIC D I J
+DB_NOSERVER D I C
+DB_NOSERVER_HOME D I C
+DB_NOSERVER_ID D I C
+DB_NOSYNC D I J
+DB_NOTFOUND D I C
+DB_ODDFILESIZE D I J
+DB_OK_BTREE * I *
+DB_OK_HASH * I *
+DB_OK_QUEUE * I *
+DB_OK_RECNO * I *
+DB_OLD_VERSION D I C
+DB_OPFLAGS_MASK * I *
+DB_ORDERCHKONLY D I J
+DB_OVERWRITE D I J
+DB_PAGE_LOCK * I *
+DB_PAGE_NOTFOUND D I C
+DB_PANIC_ENVIRONMENT D I J
+DB_PERMANENT * I *
+DB_POSITION D I J
+DB_POSITIONI * I *
+DB_PREV D I J
+DB_PREV_NODUP D I J
+DB_PRINTABLE D I J
+DB_PRIORITY_DEFAULT D I J
+DB_PRIORITY_HIGH D I J
+DB_PRIORITY_LOW D I J
+DB_PRIORITY_VERY_HIGH D I J
+DB_PRIORITY_VERY_LOW D I J
+DB_PRIVATE D I J
+DB_PR_PAGE * I *
+DB_PR_RECOVERYTEST * I *
+DB_QAMMAGIC * I *
+DB_QAMOLDVER * I *
+DB_QAMVERSION * I *
+DB_QUEUE D I C
+DB_RDONLY D I J
+DB_RDWRMASTER * I *
+DB_RECNO D I C
+DB_RECNUM D I J
+DB_RECORDCOUNT * I J
+DB_RECORD_LOCK * I *
+DB_RECOVER D I J
+DB_RECOVER_FATAL D I J
+DB_REDO * I *
+DB_REGION_INIT D I J
+DB_REGION_MAGIC * I *
+DB_RENAMEMAGIC * I *
+DB_RENUMBER D I J
+DB_REP_CLIENT D I J
+DB_REP_DUPMASTER D I C
+DB_REP_HOLDELECTION D I C
+DB_REP_LOGSONLY D I J
+DB_REP_MASTER D I J
+DB_REP_NEWMASTER D I C
+DB_REP_NEWSITE D I C
+DB_REP_OUTDATED D I C
+DB_REP_PERMANENT D I J
+DB_REP_UNAVAIL D I J
+DB_REVSPLITOFF D I J
+DB_RMW D I J
+DB_RUNRECOVERY D I C
+DB_SALVAGE D I J
+DB_SECONDARY_BAD D I C
+DB_SET D I J
+DB_SET_LOCK_TIMEOUT D I J
+DB_SET_RANGE D I J
+DB_SET_RECNO D I J
+DB_SET_TXN_NOW * I *
+DB_SET_TXN_TIMEOUT D I J
+DB_SNAPSHOT D I J
+DB_STAT_CLEAR D I J
+DB_SURPRISE_KID * I *
+DB_SWAPBYTES * I *
+DB_SYSTEM_MEM D I J
+DB_TEST_ELECTINIT * I *
+DB_TEST_ELECTSEND * I *
+DB_TEST_ELECTVOTE1 * I *
+DB_TEST_ELECTVOTE2 * I *
+DB_TEST_ELECTWAIT1 * I *
+DB_TEST_ELECTWAIT2 * I *
+DB_TEST_POSTDESTROY * I *
+DB_TEST_POSTLOG * I *
+DB_TEST_POSTLOGMETA * I *
+DB_TEST_POSTOPEN * I *
+DB_TEST_POSTSYNC * I *
+DB_TEST_PREDESTROY * I *
+DB_TEST_PREOPEN * I *
+DB_TEST_SUBDB_LOCKS * I *
+DB_THREAD D I J
+DB_TIMEOUT * I *
+DB_TRUNCATE D I J
+DB_TXNVERSION * I *
+DB_TXN_ABORT D I C
+DB_TXN_APPLY D I C
+DB_TXN_BACKWARD_ALLOC * I *
+DB_TXN_BACKWARD_ROLL D I C
+DB_TXN_CKP * I *
+DB_TXN_FORWARD_ROLL D I C
+DB_TXN_GETPGNOS * I *
+DB_TXN_LOCK * I *
+DB_TXN_NOSYNC D I J
+DB_TXN_NOWAIT D I J
+DB_TXN_OPENFILES * I *
+DB_TXN_POPENFILES * I *
+DB_TXN_PRINT D I C
+DB_TXN_SYNC D I J
+DB_TXN_WRITE_NOSYNC D I J
+DB_UNDO * I *
+DB_UNKNOWN D I C
+DB_UPDATE_SECONDARY * I *
+DB_UPGRADE D I J
+DB_USE_ENVIRON D I J
+DB_USE_ENVIRON_ROOT D I J
+DB_VERB_CHKPOINT D I J
+DB_VERB_DEADLOCK D I J
+DB_VERB_RECOVERY D I J
+DB_VERB_REPLICATION D I J
+DB_VERB_WAITSFOR D I J
+DB_VERIFY D I J
+DB_VERIFY_BAD D I C
+DB_VERIFY_FATAL * I *
+DB_VERSION_MAJOR * I J
+DB_VERSION_MINOR * I J
+DB_VERSION_PATCH * I J
+DB_VERSION_STRING * I *
+DB_WRITECURSOR D I J
+DB_WRITELOCK * I *
+DB_WRITEOPEN * I *
+DB_WRNOSYNC * I *
+DB_XA_CREATE D I J
+DB_XIDDATASIZE D I J
+DB_YIELDCPU D I J
diff --git a/bdb/dist/rec_ctemp b/bdb/dist/rec_ctemp
deleted file mode 100644
index 6be6d3166b8..00000000000
--- a/bdb/dist/rec_ctemp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * __PREF_FUNC_recover --
- * Recovery function for FUNC.
- *
- * PUBLIC: int __PREF_FUNC_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__PREF_FUNC_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __PREF_FUNC_args *argp;
- DB *file_dbp;
- DBC *dbc;
- DB_MPOOLFILE *mpf;
- PAGE *pagep;
- int cmp_n, cmp_p, modified, ret;
-
- REC_PRINT(__PREF_FUNC_print);
- REC_INTRO(__PREF_FUNC_read);
-
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
- if (DB_REDO(op)) {
- if ((ret = memp_fget(mpf,
- &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
- goto out;
- } else {
- *lsnp = argp->prev_lsn;
- ret = 0;
- goto out;
- }
-
- modified = 0;
- cmp_n = log_compare(lsnp, &LSN(pagep));
-
- /*
- * Use this when there is something like "pagelsn" in the argp
- * structure. Sometimes, you might need to compare meta-data
- * lsn's instead.
- *
- * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
- */
- if (cmp_p == 0 && DB_REDO(op)) {
- /* Need to redo update described. */
- modified = 1;
- } else if (cmp_n == 0 && !DB_REDO(op)) {
- /* Need to undo update described. */
- modified = 1;
- }
- if (ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
- goto out;
-
- *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: REC_CLOSE;
-}
-
diff --git a/bdb/dist/s_all b/bdb/dist/s_all
index dab6c75913b..ee0041032d8 100644
--- a/bdb/dist/s_all
+++ b/bdb/dist/s_all
@@ -1,16 +1,23 @@
#!/bin/sh -
-# $Id: s_all,v 1.7 2000/12/22 15:35:32 bostic Exp $
+# $Id: s_all,v 1.10 2001/08/04 14:01:44 bostic Exp $
-sh s_perm # permissions.
+sh s_dir
+
+#sh s_perm # permissions.
sh s_symlink # symbolic links.
-sh s_config # autoconf.
sh s_readme # db/README file.
+
+#
+# The following order is important, s_include must run last.
+#
+sh s_config # autoconf.
sh s_recover # logging/recovery files.
sh s_rpc # RPC files.
sh s_include # standard include files.
+
sh s_win32 # Win32 include files.
sh s_win32_dsp # Win32 build environment.
-sh s_vxworks # VxWorks include files.
-sh s_java # Java support.
-sh s_tcl # Tcl support.
-sh s_tags # Tags files.
+#sh s_vxworks # VxWorks include files.
+#sh s_java # Java support.
+sh s_test # Test suite support.
+#sh s_tags # Tags files.
diff --git a/bdb/dist/s_config b/bdb/dist/s_config
index 870109c38f9..3e033da81ab 100755
--- a/bdb/dist/s_config
+++ b/bdb/dist/s_config
@@ -1,15 +1,16 @@
#!/bin/sh -
-# $Id: s_config,v 1.3 2000/07/13 18:38:46 bostic Exp $
+# $Id: s_config,v 1.9 2002/05/20 19:18:13 bostic Exp $
#
# Build the autoconfiguration files.
-msgm4="dnl DO NOT EDIT: automatically built by dist/s_config."
+trap 'rm -f aclocal.m4 ; exit 0' 0 1 2 3 13 15
+
+msgac="# DO NOT EDIT: automatically built by dist/s_config."
. ./RELEASE
echo "Building aclocal.m4"
-rm -f aclocal.m4
-(echo "$msgm4" &&
+(echo "$msgac" &&
echo "AC_DEFUN(AM_VERSION_SET, [" &&
echo "AC_SUBST(DB_VERSION_MAJOR)" &&
echo "DB_VERSION_MAJOR=$DB_VERSION_MAJOR" &&
@@ -17,21 +18,28 @@ rm -f aclocal.m4
echo "DB_VERSION_MINOR=$DB_VERSION_MINOR" &&
echo "AC_SUBST(DB_VERSION_PATCH)" &&
echo "DB_VERSION_PATCH=$DB_VERSION_PATCH" &&
+ echo "AC_SUBST(DB_VERSION_UNIQUE_NAME)" &&
+ echo "DB_VERSION_UNIQUE_NAME=$DB_VERSION_UNIQUE_NAME" &&
echo "AC_SUBST(DB_VERSION_STRING)" &&
echo "DB_VERSION_STRING=\"\\\"$DB_VERSION_STRING\\\"\"" &&
- echo "])dnl" &&
- cat aclocal/*.m4) > aclocal.m4
-chmod 444 aclocal.m4
+ echo "])" &&
+ cat aclocal/*.ac aclocal_java/*.ac) > aclocal.m4
+echo "Running autoheader to build config.hin"
rm -f config.hin
-echo "Building config.hin (autoheader)"
-(autoheader configure.in > config.hin) 2>&1 | \
- sed '/warning: AC_TRY_RUN called without default/d'
+autoheader
chmod 444 config.hin
+echo "Running autoconf to build configure"
rm -f configure
-echo "Building configure (autoconf)"
-autoconf 2>&1 | sed '/warning: AC_TRY_RUN called without default/d'
+autoconf
+
+# Edit version information we couldn't pre-compute.
+(echo "1,\$s/__EDIT_DB_VERSION__/$DB_VERSION/g" &&
+ echo "w" &&
+ echo "q") | ed configure
+
+rm -rf autom4te.cache
+chmod 555 configure
-chmod 555 configure config.guess config.sub install-sh
-rm -f aclocal.m4
+chmod 555 config.guess config.sub install-sh
diff --git a/bdb/dist/s_crypto b/bdb/dist/s_crypto
new file mode 100644
index 00000000000..f7947cb3e10
--- /dev/null
+++ b/bdb/dist/s_crypto
@@ -0,0 +1,59 @@
+#!/bin/sh -
+# $Id: s_crypto,v 11.5 2002/09/13 13:14:14 bostic Exp $
+
+# Remove crypto from the DB source tree.
+
+. ./RELEASE
+
+d=..
+
+t=/tmp/__db_a
+trap 'rm -f $t ; exit 0' 0
+trap 'rm -f $t ; exit 1' 1 2 3 13 15
+
+if ! test -d $d/crypto; then
+ echo "s_crypto: no crypto sources found in the source tree."
+ exit 1
+fi
+
+# Remove the crypto.
+rm -rf $d/crypto
+
+# Update the docs.
+f=$d/docs/ref/env/encrypt.html
+chmod 664 $f
+(echo '/DOES/' &&
+ echo 's/DOES/DOES NOT/' &&
+ echo 'w' &&
+ echo 'q') | ed $f
+
+# Win/32.
+f=win_config.in
+chmod 664 $f
+(echo '/#define.HAVE_CRYPTO/' &&
+ echo 'c' &&
+ echo '/* #undef HAVE_CRYPTO */'
+ echo '.' &&
+ echo 'w' &&
+ echo 'q') | ed $f
+
+f=srcfiles.in
+chmod 664 $f
+(echo 'g/^crypto\//d' &&
+ echo 'w' &&
+ echo 'q') | ed $f
+
+ sh ./s_win32
+ sh ./s_win32_dsp
+
+# VxWorks
+f=vx_config.in
+chmod 664 $f
+(echo '/#define.HAVE_CRYPTO/' &&
+ echo 'c' &&
+ echo '/* #undef HAVE_CRYPTO */'
+ echo '.' &&
+ echo 'w' &&
+ echo 'q') | ed $f
+
+ sh ./s_vxworks
diff --git a/bdb/dist/s_dir b/bdb/dist/s_dir
new file mode 100644
index 00000000000..58513a8321d
--- /dev/null
+++ b/bdb/dist/s_dir
@@ -0,0 +1,42 @@
+#!/bin/sh -
+
+make_dir()
+{
+ if test ! -d $1; then
+ echo "mkdir $1"
+ mkdir $1
+ status=$?
+ if test $status -ne 0 && test ! -d $1; then
+ echo "error: $status"
+ fi
+ fi
+}
+
+echo "Creating directories..."
+
+make_dir ../test_server
+make_dir ../dbinc_auto
+make_dir ../build_vxworks/BerkeleyDB
+make_dir ../build_vxworks/db_archive
+make_dir ../build_vxworks/db_archive/db_archive
+make_dir ../build_vxworks/db_checkpoint
+make_dir ../build_vxworks/db_checkpoint/db_checkpoint
+make_dir ../build_vxworks/db_deadlock
+make_dir ../build_vxworks/db_deadlock/db_deadlock
+make_dir ../build_vxworks/db_dump
+make_dir ../build_vxworks/db_dump/db_dump
+make_dir ../build_vxworks/db_load
+make_dir ../build_vxworks/db_load/db_load
+make_dir ../build_vxworks/db_printlog
+make_dir ../build_vxworks/db_printlog/db_printlog
+make_dir ../build_vxworks/db_recover
+make_dir ../build_vxworks/db_recover/db_recover
+make_dir ../build_vxworks/db_stat
+make_dir ../build_vxworks/db_stat/db_stat
+make_dir ../build_vxworks/db_upgrade
+make_dir ../build_vxworks/db_upgrade/db_upgrade
+make_dir ../build_vxworks/db_verify
+make_dir ../build_vxworks/db_verify/db_verify
+make_dir ../build_vxworks/dbdemo/dbdemo
+make_dir ../dbinc_auto
+
diff --git a/bdb/dist/s_include b/bdb/dist/s_include
index fee6e50330f..44bfce30ee7 100755
--- a/bdb/dist/s_include
+++ b/bdb/dist/s_include
@@ -1,33 +1,160 @@
#!/bin/sh -
-# $Id: s_include,v 1.7 2000/07/13 18:38:46 bostic Exp $
+# $Id: s_include,v 1.19 2002/03/27 04:31:50 bostic Exp $
#
# Build the automatically generated function prototype files.
msgc="/* DO NOT EDIT: automatically built by dist/s_include. */"
-cxx_if="#if defined(__cplusplus)"
-cxx_head="extern \"C\" {"
-cxx_foot="}"
-cxx_endif="#endif"
-
-tmp=/tmp/__db_inc.$$
-trap 'rm -f $tmp ; exit 0' 0 1 2 3 13 15
-
-for i in db btree clib common env hash \
- lock log mp mutex os qam rpc_client rpc_server tcl txn xa; do
- f=../include/${i}_ext.h
- (echo "$msgc" &&
- echo "#ifndef _${i}_ext_h_" &&
- echo "#define _${i}_ext_h_" &&
- echo "$cxx_if" &&
- echo "$cxx_head" &&
- echo "$cxx_endif" &&
- sed -n "s/^ \* PUBLIC:[ ]\(.*\)/\1/p" ../$i/*.c;
- [ $i = os ] &&
- sed -n "s/^ \* PUBLIC:[ ]\(.*\)/\1/p" ../os_win32/*.c;
- echo "$cxx_if" &&
- echo "$cxx_foot" &&
- echo "$cxx_endif" &&
- echo "#endif /* _${i}_ext_h_ */") > $tmp
- cmp $tmp $f > /dev/null 2>&1 ||
- (echo "Building $f" && rm -f $f && cp $tmp $f && chmod 444 $f)
+
+. ./RELEASE
+
+head()
+{
+ defonly=0
+ while :
+ do case "$1" in
+ space)
+ echo ""; shift;;
+ defonly)
+ defonly=1; shift;;
+ *)
+ name="$1"; break;;
+ esac
+ done
+
+ echo "$msgc"
+ echo "#ifndef $name"
+ echo "#define $name"
+ echo ""
+ if [ $defonly -eq 0 ]; then
+ echo "#if defined(__cplusplus)"
+ echo "extern \"C\" {"
+ echo "#endif"
+ echo ""
+ fi
+}
+
+tail()
+{
+ defonly=0
+ while :
+ do case "$1" in
+ defonly)
+ defonly=1; shift;;
+ *)
+ name="$1"; break;;
+ esac
+ done
+
+ echo ""
+ if [ $defonly -eq 0 ]; then
+ echo "#if defined(__cplusplus)"
+ echo "}"
+ echo "#endif"
+ fi
+ echo "#endif /* !$name */"
+}
+
+# We are building several files:
+# 1 external #define file
+# 1 external prototype file
+# 1 internal #define file
+# N internal prototype files
+e_dfile=/tmp/__db_c.$$
+e_pfile=/tmp/__db_a.$$
+i_dfile=/tmp/__db_d.$$
+i_pfile=/tmp/__db_b.$$
+trap 'rm -f $e_dfile $e_pfile $i_dfile $i_pfile; exit 0' 0 1 2 3 13 15
+
+head defonly space _DB_EXT_DEF_IN_ > $e_dfile
+head space _DB_EXT_PROT_IN_ > $e_pfile
+head defonly _DB_INT_DEF_IN_ > $i_dfile
+
+# Process the standard directories, creating per-directory prototype
+# files and adding to the external prototype and #define files.
+for i in db btree clib common crypto dbreg env fileops hash hmac \
+ lock log mp mutex os qam rep rpc_client rpc_server tcl txn xa; do
+ head "_${i}_ext_h_" > $i_pfile
+
+ f="../$i/*.c"
+ [ $i = os ] && f="$f ../os_win32/*.c"
+ [ $i = rpc_server ] && f="../$i/c/*.c"
+ [ $i = crypto ] && f="../$i/*.c ../$i/*/*.c"
+ awk -f gen_inc.awk \
+ -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \
+ -v e_dfile=$e_dfile \
+ -v e_pfile=$e_pfile \
+ -v i_dfile=$i_dfile \
+ -v i_pfile=$i_pfile $f
+
+ tail "_${i}_ext_h_" >> $i_pfile
+
+ f=../dbinc_auto/${i}_ext.h
+ cmp $i_pfile $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $i_pfile $f && chmod 444 $f)
done
+
+# Process directories which only add to the external prototype and #define
+# files.
+for i in dbm hsearch; do
+ f="../$i/*.c"
+ awk -f gen_inc.awk \
+ -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \
+ -v e_dfile=$e_dfile \
+ -v e_pfile=$e_pfile \
+ -v i_dfile="" \
+ -v i_pfile="" $f
+done
+
+# RPC uses rpcgen to generate a header file; post-process it to add more
+# interfaces to the internal #define file.
+sed -e '/extern bool_t xdr___/{' \
+ -e 's/.* //' \
+ -e 's/();//' \
+ -e 's/.*/#define & &@DB_VERSION_UNIQUE_NAME@/' \
+ -e 'p' \
+ -e '}' \
+ -e d < ../dbinc_auto/db_server.h >> $i_dfile
+
+# There are a few globals in DB -- add them to the external/internal
+# #define files.
+(echo "#define __db_global_values __db_global_values@DB_VERSION_UNIQUE_NAME@";
+ echo "#define __db_jump __db_jump@DB_VERSION_UNIQUE_NAME@") >> $i_dfile
+(echo "#define db_xa_switch db_xa_switch@DB_VERSION_UNIQUE_NAME@") >> $e_dfile
+
+# Wrap up the external #defines/prototypes, and internal #defines.
+tail defonly _DB_EXT_DEF_IN_ >> $e_dfile
+f=../dbinc_auto/ext_def.in
+cmp $e_dfile $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $e_dfile $f && chmod 444 $f)
+
+tail _DB_EXT_PROT_IN_ >> $e_pfile
+f=../dbinc_auto/ext_prot.in
+cmp $e_pfile $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $e_pfile $f && chmod 444 $f)
+
+tail defonly _DB_INT_DEF_IN_ >> $i_dfile
+f=../dbinc_auto/int_def.in
+cmp $i_dfile $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $i_dfile $f && chmod 444 $f)
+
+# DB185 compatibility support.
+head space defonly _DB_EXT_185_DEF_IN_ > $e_dfile
+head space _DB_EXT_185_PROT_IN_ > $e_pfile
+
+f="../db185/*.c"
+awk -f gen_inc.awk \
+ -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \
+ -v e_dfile=$e_dfile \
+ -v e_pfile=$e_pfile \
+ -v i_dfile="" \
+ -v i_pfile="" $f
+
+tail defonly _DB_EXT_185_DEF_IN_ >> $e_dfile
+f=../dbinc_auto/ext_185_def.in
+cmp $e_dfile $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $e_dfile $f && chmod 444 $f)
+
+tail _DB_EXT_185_PROT_IN_ >> $e_pfile
+f=../dbinc_auto/ext_185_prot.in
+cmp $e_pfile $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $e_pfile $f && chmod 444 $f)
diff --git a/bdb/dist/s_java b/bdb/dist/s_java
index f324678abaa..f3c856d0532 100755
--- a/bdb/dist/s_java
+++ b/bdb/dist/s_java
@@ -1,31 +1,273 @@
#!/bin/sh -
-# $Id: s_java,v 1.3 2000/07/13 18:38:46 bostic Exp $
+# $Id: s_java,v 1.13 2002/09/09 20:47:30 bostic Exp $
#
# Build the Java files.
-msgcxx="// DO NOT EDIT: automatically built by dist/s_java."
+msgjava="/* DO NOT EDIT: automatically built by dist/s_java. */"
. RELEASE
-f=../java/src/com/sleepycat/db/DbConstants.java
-echo "Building $f"
-rm -f $f
-(echo "$msgcxx" && \
+t=/tmp/__java
+c=/tmp/__javajnic
+h=/tmp/__javajnih
+trap 'rm -f $t $c $h; exit 0' 0 1 2 3 13 15
+
+# Build DbConstants.java.
+(echo "$msgjava" &&
echo &&
echo 'package com.sleepycat.db;' &&
echo &&
- echo 'public class DbConstants' &&
+ echo 'class DbConstants' &&
echo '{' &&
- egrep '^#define.DB_' ../include/db.src | \
- sed -e '/"/d' \
- -e '/@DB_VERSION_/d' \
- -e '/DB_REDO/d' \
- -e '/DB_UNDO/d' \
- -e 's/[()]/ /g' \
+ for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
+ egrep -w "^#define[ ]$i|^[ ][ ]*$i" ../dbinc/db.in; \
+ done |
+ sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/" \
+ -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/" \
+ -e "s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/" \
+ -e 's/^#define[ ][ ]*//' \
+ -e 's/[()=,]/ /g' \
+ -e 's/\/\*/ /' | \
+ awk '{ print " static final int " $1 " = " $2 ";" }' &&
+ echo '}' &&
+ echo &&
+ echo '// end of DbConstants.java') > $t
+
+f=../java/src/com/sleepycat/db/DbConstants.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build Db.java.
+f=../java/src/com/sleepycat/db/Db.java.in
+sed '/BEGIN-JAVA-SPECIAL-CONSTANTS/q' < $f > $t
+(echo " $msgjava" &&
+ for i in `egrep '^DB_.*C$' pubdef.in | awk '{print $1}'`; do \
+ egrep -w "^#define[ ]$i|^[ ][ ]*$i" ../dbinc/db.in; \
+ done |
+ sed -e 's/^#define[ ][ ]*//' \
+ -e 's/[()=,]/ /g' |
+ awk '{ print " public static final int " $1 " = " $2 ";" }') >> $t
+(for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
+ egrep -w "^#define[ ]$i|^[ ][ ]*$i" ../dbinc/db.in; \
+ done |
+ sed -e 's/^#define[ ][ ]*//' \
+ -e 's/[()=,]/ /g' |
+ awk '{ print " public static final int " $1 ";" }') >> $t
+sed -n \
+ '/END-JAVA-SPECIAL-CONSTANTS/,/BEGIN-JAVA-CONSTANT-INITIALIZATION/p' \
+ < $f >> $t
+(echo " $msgjava" &&
+ for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
+ egrep -w "^#define[ ]$i|^[ ][ ]*$i" ../dbinc/db.in; \
+ done |
+ sed -e 's/^#define[ ][ ]*//' \
+ -e 's/[()=,]/ /g' \
-e 's/\/\*/ /' | \
- awk '{ print "\tpublic static final int " $2 " = " $3 ";" }' &&
- echo " public static final int DB_VERSION_MAJOR = $DB_VERSION_MAJOR;" &&
- echo " public static final int DB_VERSION_MINOR = $DB_VERSION_MINOR;" &&
- echo " public static final int DB_VERSION_PATCH = $DB_VERSION_PATCH;" &&
- echo '}') > $f
-chmod 444 $f
+ awk '{ print " " $1 " = DbConstants." $1 ";" }') >> $t
+sed -n '/END-JAVA-CONSTANT-INITIALIZATION/,$p' < $f >> $t
+
+f=../java/src/com/sleepycat/db/Db.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Script to convert DB C structure declarations into Java declarations.
+jclass()
+{
+ cat ../dbinc/db.in |
+ sed -n \
+ -e "/struct $1 {/,/^}/{" \
+ -e "/$1/d" \
+ -e '/;/!d' \
+ -e '/^}/d' \
+ -e '/char[ ]*\*/{' \
+ -e "s/^[ ]*[^\*]*\*[ ]*\([^;]*\).*/$2 public String \1;/p"\
+ -e 'd' \
+ -e '}' \
+ -e '/time_t/{' \
+ -e "s/^[ ]*[^ ]*[ ]*\([^;]*\).*/$2 public long \1;/p" \
+ -e 'd' \
+ -e '}' \
+ -e '/DB_LSN[ ]*/{' \
+ -e "s/^[ ]*[^ ]*[ ]*\([^;]*\).*/$2 public DbLsn \1;/p"\
+ -e 'd' \
+ -e '}' \
+ -e '/DB_TXN_ACTIVE[ ]*\*/{' \
+ -e "s/^[ ]*[^\*]*\*[ ]*\([^;]*\).*/$2 public Active \1[];/p"\
+ -e 'd' \
+ -e '}' \
+ -e "s/^[ ]*[^ ]*[ ]*\([^;]*\).*/$2 public int \1;/p" \
+ -e '}'
+}
+
+# Script to convert DB C structure declarations into Java declarations.
+jclass_jni()
+{
+ c=$3
+ h=$4
+ echo "extern int $2(JNIEnv *jnienv, jclass cl, jobject jobj, struct $1 *statp);" >> $h
+ echo "int $2(JNIEnv *jnienv, jclass cl," >> $c
+ echo " jobject jobj, struct $1 *statp) {" >> $c
+ cat ../dbinc/db.in |
+ sed -n \
+ -e "/struct $1 {/,/^}/{" \
+ -e "/$1/d" \
+ -e '/;/!d' \
+ -e '/^}/d' \
+ -e '/char[ ]*\*/{' \
+ -e "s/^[ ]*[^\*]*\*[ ]*\([^;]*\).*/ JAVADB_STAT_STRING(jnienv, cl, jobj, statp, \1);/p"\
+ -e 'd' \
+ -e '}' \
+ -e '/time_t/{' \
+ -e "s/^[ ]*[^ ]*[ ]*\([^;]*\).*/ JAVADB_STAT_LONG(jnienv, cl, jobj, statp, \1);/p" \
+ -e 'd' \
+ -e '}' \
+ -e '/DB_LSN[ ]*/{' \
+ -e "s/^[ ]*[^ ]*[ ]*\([^;]*\).*/ JAVADB_STAT_LSN(jnienv, cl, jobj, statp, \1);/p"\
+ -e 'd' \
+ -e '}' \
+ -e '/DB_TXN_ACTIVE[ ]*\*/{' \
+ -e "s/^[ ]*[^\*]*\*[ ]*\([^;]*\).*/ JAVADB_STAT_ACTIVE(jnienv, cl, jobj, statp, \1);/p"\
+ -e 'd' \
+ -e '}' \
+ -e "s/^[ ]*[^ ]*[ ]*\([^;]*\).*/ JAVADB_STAT_INT(jnienv, cl, jobj, statp, \1);/p" \
+ -e '}' >> $c
+ echo ' return (0);' >> $c
+ echo '}' >> $c
+}
+
+echo "$msgjava" >> $c
+echo "$msgjava" >> $h
+echo '#include "java_util.h"' >> $c
+
+# Build DbBtreeStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbBtreeStat"
+ echo '{'
+ jclass __db_bt_stat &&
+ echo '}' &&
+ echo '// end of DbBtreeStat.java') > $t
+jclass_jni __db_bt_stat __jv_fill_bt_stat $c $h
+f=../java/src/com/sleepycat/db/DbBtreeStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbHashStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbHashStat"
+ echo '{'
+ jclass __db_h_stat &&
+ echo '}' &&
+ echo '// end of DbHashStat.java') > $t
+jclass_jni __db_h_stat __jv_fill_h_stat $c $h
+f=../java/src/com/sleepycat/db/DbHashStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbLockStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbLockStat"
+ echo '{'
+ jclass __db_lock_stat &&
+ echo '}' &&
+ echo '// end of DbLockStat.java') > $t
+jclass_jni __db_lock_stat __jv_fill_lock_stat $c $h
+f=../java/src/com/sleepycat/db/DbLockStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbLogStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbLogStat"
+ echo '{'
+ jclass __db_log_stat &&
+ echo '}' &&
+ echo '// end of DbLogStat.java') > $t
+jclass_jni __db_log_stat __jv_fill_log_stat $c $h
+f=../java/src/com/sleepycat/db/DbLogStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbMpoolFStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbMpoolFStat"
+ echo '{'
+ jclass __db_mpool_fstat &&
+ echo '}' &&
+ echo '// end of DbMpoolFStat.java') > $t
+jclass_jni __db_mpool_stat __jv_fill_mpool_stat $c $h
+f=../java/src/com/sleepycat/db/DbMpoolFStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbQueueStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbQueueStat"
+ echo '{'
+ jclass __db_qam_stat &&
+ echo '}' &&
+ echo '// end of DbQueueStat.java') > $t
+jclass_jni __db_qam_stat __jv_fill_qam_stat $c $h
+f=../java/src/com/sleepycat/db/DbQueueStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbRepStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbRepStat"
+ echo '{'
+ jclass __db_rep_stat &&
+ echo '}' &&
+ echo '// end of DbRepStat.java') > $t
+jclass_jni __db_rep_stat __jv_fill_rep_stat $c $h
+f=../java/src/com/sleepycat/db/DbRepStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build DbTxnStat.java
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db;' &&
+ echo &&
+ echo "public class DbTxnStat"
+ echo '{'
+ echo " public static class Active {"
+ jclass __db_txn_active " " &&
+ echo ' };' &&
+ jclass __db_txn_stat &&
+ echo '}' &&
+ echo '// end of DbTxnStat.java') > $t
+jclass_jni __db_txn_stat __jv_fill_txn_stat $c $h
+f=../java/src/com/sleepycat/db/DbTxnStat.java
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+mv $c $t
+f=../libdb_java/java_stat_auto.c
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+mv $h $t
+f=../libdb_java/java_stat_auto.h
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
diff --git a/bdb/dist/s_javah b/bdb/dist/s_javah
new file mode 100755
index 00000000000..480856e4b5c
--- /dev/null
+++ b/bdb/dist/s_javah
@@ -0,0 +1,55 @@
+#!/bin/sh -
+# $Id: s_javah,v 1.1 2002/08/14 17:14:24 dda Exp $
+#
+# Use javah to build the libdb_java/com_*.h header files.
+#
+# To run this, you will need a javac and javah in your PATH.
+# If possible, install tools with a recent vintage, JDK 1.3 or higher is good.
+# Using Sun's JDK rather than some other installation ensures
+# that the header files will not be constantly changed.
+
+. RELEASE
+
+JAVAC=javac
+JAVAH=javah
+export CLASSPATH
+CLASSPATH=
+
+# CLASSES are only those classes for which we have native methods.
+D=com.sleepycat.db
+CLASSES="$D.Dbc $D.DbEnv $D.Db $D.DbLock $D.DbLogc $D.DbLsn $D.Dbt $D.DbTxn $D.xa.DbXAResource"
+
+d=/tmp/__javah
+c=$d/classes
+trap 'rm -rf $d; exit 0' 0 1 2 3 13 15
+
+rm -rf $d
+mkdir $d || exit 1
+mkdir $c || exit 1
+
+# Make skeleton versions of XA classes and interfaces
+# We only need to compile them, not run them.
+pkg="package javax.transaction.xa"
+echo "$pkg; public interface XAResource {}" > $d/XAResource.java
+echo "$pkg; public interface Xid {}" > $d/Xid.java
+echo "$pkg; public class XAException extends Exception {}" \
+ > $d/XAException.java
+
+
+# Create the .class files and use them with javah to create the .h files
+${JAVAC} -d $c $d/*.java \
+ ../java/src/com/sleepycat/db/*.java \
+ ../java/src/com/sleepycat/db/xa/*.java || exit 1
+${JAVAH} -classpath $c -d $d ${CLASSES} || exit 1
+
+for cl in ${CLASSES}; do
+ h=`echo $cl | sed -e 's/\./_/g'`.h
+ t=$d/$h
+ f=../libdb_java/$h
+ if [ ! -f $t ]; then
+ echo "ERROR: $t does not exist"
+ exit 1
+ fi
+ cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+done
diff --git a/bdb/dist/s_perm b/bdb/dist/s_perm
index 4b0997f2f55..c35278b8c83 100755
--- a/bdb/dist/s_perm
+++ b/bdb/dist/s_perm
@@ -1,37 +1,49 @@
#!/bin/sh -
-# $Id: s_perm,v 1.9 2001/01/24 15:55:38 bostic Exp $
+# $Id: s_perm,v 1.23 2002/09/09 15:03:06 bostic Exp $
+d=..
echo 'Updating Berkeley DB source tree permissions...'
+. ./RELEASE
+
run()
{
echo " $1 ($2)"
- if [ -f "../$1" ]; then
- chmod "$2" "../$1"
+ if [ -f "$d/$1" ]; then
+ chmod "$2" "$d/$1"
else
- echo "$1: no such file or directory"
+ echo "$d/$1: no such file or directory"
exit 1
fi
}
-run dist/build/chk.def 0555
-run dist/build/chk.define 0555
-run dist/build/chk.offt 0555
-run dist/build/chk.srcfiles 0555
-run dist/build/chk.tags 0555
-run dist/config.guess 0555
-run dist/config.sub 0555
-run dist/configure 0555
-run dist/install-sh 0555
-run dist/s_config 0555
-run dist/s_include 0555
-run dist/s_java 0555
-run dist/s_perm 0555
-run dist/s_readme 0555
-run dist/s_recover 0555
-run dist/s_symlink 0555
-run dist/s_tags 0555
-run dist/s_tcl 0555
-run dist/s_win32 0555
-run perl.BerkeleyDB/dbinfo 0555
-run perl.BerkeleyDB/mkpod 0555
+run build_win32/include.tcl 664
+run dist/config.guess 555
+run dist/config.sub 555
+run dist/configure 555
+run dist/install-sh 555
+run dist/s_all 555
+run dist/s_config 555
+run dist/s_include 555
+run dist/s_java 555
+run dist/s_javah 555
+run dist/s_perm 555
+run dist/s_readme 555
+run dist/s_recover 555
+run dist/s_rpc 555
+run dist/s_symlink 555
+run dist/s_tags 555
+run dist/s_test 555
+run dist/s_vxworks 555
+run dist/s_win32 555
+run dist/s_win32_dsp 555
+run dist/vx_buildcd 555
+
+run perl/BerkeleyDB/dbinfo 555
+run perl/BerkeleyDB/mkpod 555
+
+for i in `cd $d && find build_vxworks \
+ -name '*.wsp' -o -name '*.cdf' -o -name '*.wpj'`; do
+ echo " $i (775)"
+ chmod 775 $d/$i
+done
diff --git a/bdb/dist/s_readme b/bdb/dist/s_readme
index 9ff8a69bc88..229a152b8a9 100755
--- a/bdb/dist/s_readme
+++ b/bdb/dist/s_readme
@@ -1,18 +1,23 @@
#!/bin/sh -
-# $Id: s_readme,v 1.2 2000/01/27 21:42:18 bostic Exp $
+# $Id: s_readme,v 1.6 2002/02/14 02:50:26 bostic Exp $
#
# Build the README.
+d=..
+
+t=/tmp/__t
+trap 'rm -f $t; exit 0' 0 1 2 3 13 15
+
. RELEASE
+cat << END_OF_README>$t
+$DB_VERSION_STRING
+
+This is version $DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH of Berkeley DB from Sleepycat Software. To view
+the release and installation documentation, load the distribution file
+docs/index.html into your web browser.
+END_OF_README
+
f=../README
-echo "Building $f"
-rm -f $f
-(echo "$DB_VERSION_STRING" &&
- echo "" &&
- echo -n "This is version " &&
- echo -n "$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH" &&
- echo " of Berkeley DB from Sleepycat Software. To view" &&
- echo "the release and installation documentation, load the distribution file" &&
- echo "docs/index.html into your web browser.") > $f
-chmod 444 $f
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
diff --git a/bdb/dist/s_recover b/bdb/dist/s_recover
index b0593cfc052..869b5bfd363 100755
--- a/bdb/dist/s_recover
+++ b/bdb/dist/s_recover
@@ -1,23 +1,20 @@
#!/bin/sh -
-# $Id: s_recover,v 1.3 2000/03/30 05:24:36 krinsky Exp $
+# $Id: s_recover,v 1.14 2002/03/27 04:31:51 bostic Exp $
#
# Build the automatically generated logging/recovery files.
-DIR="db btree hash log qam txn"
+. ./RELEASE
-t=/tmp/__db_$$
-loglist=../test/logtrack.list
-rm -f $t
-rm -f $loglist
+tmp=/tmp/__db_a
+loglist=/tmp/__db_b
+source=/tmp/__db_c
+header=/tmp/__db_d
+template=/tmp/__db_e
-trap 'rm -f $t; exit 1' 1 2 3 13 15
+trap 'rm -f $tmp $loglist $source $header $template; exit 1' 1 2 3 13 15
+trap 'rm -f $tmp $loglist $source $header $template; exit 0' 0
-# Use the standard -k option if it works;
-# otherwise fall back on the traditional notation.
-if sort -k 1,1 /dev/null
-then sort_2_etc='-k 2'
-else sort_2_etc='+1'
-fi
+DIR="db dbreg btree hash qam txn"
# Check to make sure we haven't duplicated a log record entry, and build
# the list of log record types that the test suite uses.
@@ -27,38 +24,46 @@ for i in $DIR; do
# Grab the PREFIX; there should only be one per file, and
# so it's okay to just take the first.
grep '^PREFIX' $f | sed q
- egrep '^DEPRECATED[ ]|^BEGIN[ ]' $f | \
+ egrep '^BEGIN[ ]|^IGNORED[ ]|^DEPRECATED[ ]' $f |
awk '{print $1 "\t" $2 "\t" $3}'
done
done > $loglist
-grep -v '^PREFIX' $loglist | awk '{print $2 "\t" $3}' | \
- sort $sort_2_etc -n | \
- uniq -d -f 1 > $t
-[ -s $t ] && {
+grep -v '^PREFIX' $loglist |
+ awk '{print $2 "\t" $3}' | sort -n -k 2 | uniq -d -f 1 > $tmp
+[ -s $tmp ] && {
echo "DUPLICATE LOG VALUES:"
- cat $t
- rm -f $t
+ cat $tmp
+ rm -f $tmp
exit 1
}
-rm -f $t
+f=../test/logtrack.list
+cmp $loglist $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $loglist $f && chmod 444 $f)
-for i in db btree hash log qam txn; do
+# Build DB's recovery routines.
+for i in db dbreg btree fileops hash qam txn; do
for f in ../$i/*.src; do
subsystem=`basename $f .src`
- header_file=../include/${subsystem}_auto.h
- source_file=../$i/${subsystem}_auto.c
- template_file=template/rec_${subsystem}
- template_source=.
-
- echo "Building $source_file, $header_file, $template_file"
- rm -f $header_file $source_file $template_file
awk -f gen_rec.awk \
- -v subsystem=$subsystem \
- -v source_file=$source_file \
- -v header_file=$header_file \
- -v template_file=$template_file \
- -v template_dir=. < $f
- chmod 444 $header_file $source_file $template_file
+ -v source_file=$source \
+ -v header_file=$header \
+ -v template_file=$template < $f
+
+ f=../dbinc_auto/${subsystem}_auto.h
+ cmp $header $f > /dev/null 2>&1 ||
+ (echo "Building $f" &&
+ rm -f $f && cp $header $f && chmod 444 $f)
+ f=../$i/${subsystem}_auto.c
+ cmp $source $f > /dev/null 2>&1 ||
+ (echo "Building $f" &&
+ rm -f $f && cp $source $f && chmod 444 $f)
+ f=template/rec_${subsystem}
+ cmp $template $f > /dev/null 2>&1 ||
+ (echo "Building $f" &&
+ rm -f $f && cp $template $f && chmod 444 $f)
done
done
+
+# Build the example application's recovery routines.
+(cd ../examples_c/ex_apprec && sh auto_rebuild)
diff --git a/bdb/dist/s_rpc b/bdb/dist/s_rpc
index f7d9cf4eb1c..cdafa669d85 100644
--- a/bdb/dist/s_rpc
+++ b/bdb/dist/s_rpc
@@ -1,45 +1,56 @@
#!/bin/sh -
-# $Id: s_rpc,v 11.6 2000/04/26 19:15:51 sue Exp $
+# $Id: s_rpc,v 11.18 2002/08/15 15:22:09 bostic Exp $
#
# Build the automatically generated RPC files
echo "Building RPC client/server files"
+. ./RELEASE
+
+t=/tmp/__db_a
+trap 'rm -f $t ; exit 0' 0
+trap 'rm -f $t ; exit 1' 1 2 3 13 15
+
client_file=../rpc_client/gen_client.c
-cproto_file=../include/gen_client_ext.h
ctmpl_file=./template/gen_client_ret
-header_file=../include/db_server.h
+dbinc_file=../dbinc/db.in
+defs_file=../dbinc_auto/rpc_defs.in
+header_file=../dbinc_auto/db_server.h
+proc_file=../rpc_server/c/db_server_proc.c
rpcclnt_file=../rpc_client/db_server_clnt.c
-rpcsvc_file=../rpc_server/db_server_svc.c
-rpcxdr_file=../rpc_server/db_server_xdr.c
-sed_file=../rpc_server/db_server_proc.sed
-server_file=../rpc_server/gen_db_server.c
-sproto_file=../include/gen_server_ext.h
+rpcsvc_file=../rpc_server/c/db_server_svc.c
+rpcxdr_file=../rpc_server/c/db_server_xdr.c
+sed_file=../rpc_server/c/db_server_proc.sed
+server_file=../rpc_server/c/gen_db_server.c
stmpl_file=./template/db_server_proc
xdr_file=../rpc_server/db_server.x
-#
-# NOTE: We do NOT want to remove proc_file. It is what we apply
-# sed_file to, but we do not want to remove it.
-#
-proc_file=../rpc_server/db_server_proc.c
-svrsed_file=../rpc_server/db_server_svc.sed
-rpcsed_file=../rpc_server/db_server.sed
-
-rm -f $client_file $cproto_file $ctmpl_file $header_file $rpcsvc_file \
- $rpcclnt_file $rpcxdr_file $sed_file $server_file $sproto_file \
- $stmpl_file $xdr_file
+rm -f $client_file \
+ $ctmpl_file \
+ $header_file \
+ $rpcclnt_file \
+ $rpcsvc_file \
+ $proc_file \
+ $rpcxdr_file \
+ $sed_file \
+ $server_file \
+ $stmpl_file \
+ $xdr_file
#
# Generate client/server/XDR code
#
+xidsize=\
+`awk '/^#define/ { if ($2 == "DB_XIDDATASIZE") { print $3 }}' $dbinc_file`
+
awk -f gen_rpc.awk \
+ -v major=$DB_VERSION_MAJOR \
+ -v minor=$DB_VERSION_MINOR \
+ -v xidsize=$xidsize \
-v client_file=$client_file \
- -v cproto_file=$cproto_file \
-v ctmpl_file=$ctmpl_file \
-v sed_file=$sed_file \
-v server_file=$server_file \
- -v sproto_file=$sproto_file \
-v stmpl_file=$stmpl_file \
-v xdr_file=$xdr_file < ../rpc_server/rpc.src
chmod 444 $client_file $server_file
@@ -52,31 +63,72 @@ rpcgen -l $xdr_file > $rpcclnt_file
rpcgen -s tcp $xdr_file > $rpcsvc_file
rpcgen -c $xdr_file > $rpcxdr_file
-# Run server files through sed
-sed -f $svrsed_file $rpcsvc_file > ${rpcsvc_file}.new
-mv ${rpcsvc_file}.new $rpcsvc_file
-#
-# This is a hack to handle the $proc_file special case. Since it
-# is both a source file and a generated file, we have to dance a
-# bit to get it to work with 'bk get', not just with 'bk edit'.
-# This still isn't perfect (I don't know what perfect would be in
-# this case), but it seems to work for now.
#
-#sed -f $sed_file $proc_file > ${proc_file}.new
-#mv ${proc_file}.new $proc_file
+# Run various server files through sed.
#
-mv $proc_file ${proc_file}.old
-sed -f $sed_file ${proc_file}.old > $proc_file
-test -w ${proc_file}.old || chmod a-w $proc_file
-rm -f ${proc_file}.old
-
-# Run rpcgen files through sed to add HAVE_RPC ifdef
-sed -f $rpcsed_file $rpcsvc_file > ${rpcsvc_file}.new
+cat <<ENDOFSEDTEXT>$t
+s/^#include[ ]"db_server.h"/#include "db_config.h"\\
+\\
+\\#ifndef NO_SYSTEM_INCLUDES\\
+\\#include <rpc\\/rpc.h>\\
+\\#include <rpc\\/pmap_clnt.h>/
+/^#include <netinet.in.h>/a\\
+\\#endif\\
+\\
+\\#include "db_int.h"\\
+\\#include "dbinc_auto/db_server.h"\\
+\\#include "dbinc/db_server_int.h"\\
+\\#include "dbinc_auto/rpc_server_ext.h"
+/^ return;/i\\
+\\ __dbsrv_timeout(0);
+s/svc_sendreply(transp, xdr_void,/svc_sendreply(transp, (xdrproc_t)xdr_void,/
+s/svc_getargs(transp, xdr_argument, &argument)/svc_getargs(transp, (xdrproc_t)xdr_argument, (char *)\&argument)/
+s/svc_sendreply(transp, xdr_result, result)/svc_sendreply(transp, (xdrproc_t)xdr_result, result)/
+s/svc_freeargs(transp, xdr_argument, &argument)/svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)\&argument)/
+s/^main/void __dbsrv_main/
+ENDOFSEDTEXT
+sed -f $t $rpcsvc_file > ${rpcsvc_file}.new
mv ${rpcsvc_file}.new $rpcsvc_file
-sed -f $rpcsed_file $rpcxdr_file > ${rpcxdr_file}.new
+
+sed -f $sed_file ${proc_file}.in > ${proc_file}
+
+# Run rpcgen files through sed to add HAVE_RPC ifdef and appropriate
+# includes.
+cat <<ENDOFSEDTEXT>$t
+1i\\
+\\#include "db_config.h"\\
+\\
+\\#ifdef HAVE_RPC
+/^#include "db_server.h"/c\\
+\\#ifndef NO_SYSTEM_INCLUDES\\
+\\#include <rpc/rpc.h>\\
+\\
+\\#include <strings.h>\\
+\\#endif\\
+\\
+\\#include "db_int.h"\\
+\\#include "dbinc_auto/db_server.h"
+\$a\\
+\\#endif /* HAVE_RPC */
+ENDOFSEDTEXT
+
+sed -f $t $rpcxdr_file > ${rpcxdr_file}.new
mv ${rpcxdr_file}.new $rpcxdr_file
-sed -f $rpcsed_file $rpcclnt_file > ${rpcclnt_file}.new
+sed -f $t $rpcclnt_file > ${rpcclnt_file}.new
mv ${rpcclnt_file}.new $rpcclnt_file
-chmod 444 $header_file $rpcclnt_file $rpcsvc_file $rpcxdr_file
+# Copy the DB_RPC SERVER #defines into a separate file so
+# they can be part of db.h.
+msgc="/* DO NOT EDIT: automatically built by dist/s_rpc. */"
+(echo "" && echo "$msgc" &&
+ sed -n -e "/DB_RPC_SERVER/p" $header_file) > $defs_file
+
+# Fix up the header file:
+# Remove the DB_RPC_SERVER #defines.
+# Remove the <rpc/rpc.h> include, it needs to be included earlier
+# than that.
+sed -e "/DB_RPC_SERVER/d"\
+ -e "/^#include.*<rpc\/rpc.h>/d" $header_file > ${header_file}.new
+mv ${header_file}.new $header_file
+chmod 444 $header_file $rpcclnt_file $rpcsvc_file $rpcxdr_file
diff --git a/bdb/dist/s_symlink b/bdb/dist/s_symlink
index 70efa445521..ee80a220a83 100755
--- a/bdb/dist/s_symlink
+++ b/bdb/dist/s_symlink
@@ -1,7 +1,8 @@
#!/bin/sh -
-# $Id: s_symlink,v 1.9 2000/09/05 21:27:04 bostic Exp $
+# $Id: s_symlink,v 1.28 2002/08/18 21:15:45 bostic Exp $
echo 'Creating Berkeley DB source tree symbolic links...'
+. ./RELEASE
build()
{
@@ -13,6 +14,7 @@ build btree/tags ../dist/tags
build build_unix/tags ../dist/tags
build clib/tags ../dist/tags
build common/tags ../dist/tags
+build crypto/tags ../dist/tags
build cxx/tags ../dist/tags
build db/tags ../dist/tags
build db185/tags ../dist/tags
@@ -27,54 +29,18 @@ build db_recover/tags ../dist/tags
build db_stat/tags ../dist/tags
build db_upgrade/tags ../dist/tags
build db_verify/tags ../dist/tags
+build dbinc/tags ../dist/tags
+build dbinc_auto/tags ../dist/tags
build dbm/tags ../dist/tags
-build docs_src/api_cxx/Makefile ../api_c/Makefile
-build docs_src/api_cxx/m4.seealso ../api_c/m4.seealso
-build docs_src/api_cxx/spell.ok ../api_c/spell.ok
-build docs_src/api_java/Makefile ../api_c/Makefile
-build docs_src/api_java/java_index.so ../api_cxx/cxx_index.so
-build docs_src/api_java/m4.seealso ../api_c/m4.seealso
-build docs_src/api_java/spell.ok ../api_c/spell.ok
-build docs_src/api_tcl/spell.ok ../api_c/spell.ok
-build docs_src/ref/am/spell.ok ../spell.ok
-build docs_src/ref/am_conf/spell.ok ../spell.ok
-build docs_src/ref/arch/spell.ok ../spell.ok
-build docs_src/ref/build_unix/spell.ok ../spell.ok
-build docs_src/ref/build_vxworks/spell.ok ../spell.ok
-build docs_src/ref/build_win/spell.ok ../spell.ok
-build docs_src/ref/cam/spell.ok ../spell.ok
-build docs_src/ref/debug/spell.ok ../spell.ok
-build docs_src/ref/distrib/spell.ok ../spell.ok
-build docs_src/ref/dumpload/spell.ok ../spell.ok
-build docs_src/ref/env/spell.ok ../spell.ok
-build docs_src/ref/install/spell.ok ../spell.ok
-build docs_src/ref/intro/spell.ok ../spell.ok
-build docs_src/ref/java/spell.ok ../spell.ok
-build docs_src/ref/lock/spell.ok ../spell.ok
-build docs_src/ref/log/spell.ok ../spell.ok
-build docs_src/ref/mp/spell.ok ../spell.ok
-build docs_src/ref/perl/spell.ok ../spell.ok
-build docs_src/ref/program/spell.ok ../spell.ok
-build docs_src/ref/refs/spell.ok ../spell.ok
-build docs_src/ref/rpc/spell.ok ../spell.ok
-build docs_src/ref/sendmail/spell.ok ../spell.ok
-build docs_src/ref/simple_tut/spell.ok ../spell.ok
-build docs_src/ref/tcl/spell.ok ../spell.ok
-build docs_src/ref/test/spell.ok ../spell.ok
-build docs_src/ref/transapp/spell.ok ../spell.ok
-build docs_src/ref/txn/spell.ok ../spell.ok
-build docs_src/ref/upgrade.2.0/spell.ok ../spell.ok
-build docs_src/ref/upgrade.3.0/spell.ok ../spell.ok
-build docs_src/ref/upgrade.3.1/spell.ok ../spell.ok
-build docs_src/ref/upgrade.3.2/spell.ok ../spell.ok
-build docs_src/ref/xa/spell.ok ../spell.ok
+build dbreg/tags ../dist/tags
build env/tags ../dist/tags
build examples_c/tags ../dist/tags
build examples_cxx/tags ../dist/tags
build examples_java java/src/com/sleepycat/examples
+build fileops/tags ../dist/tags
build hash/tags ../dist/tags
+build hmac/tags ../dist/tags
build hsearch/tags ../dist/tags
-build include/tags ../dist/tags
build libdb_java/tags ../dist/tags
build lock/tags ../dist/tags
build log/tags ../dist/tags
@@ -84,8 +50,10 @@ build os/tags ../dist/tags
build os_vxworks/tags ../dist/tags
build os_win32/tags ../dist/tags
build qam/tags ../dist/tags
+build rep/tags ../dist/tags
build rpc_client/tags ../dist/tags
build rpc_server/tags ../dist/tags
build tcl/tags ../dist/tags
+build test_server/tags ../dist/tags
build txn/tags ../dist/tags
build xa/tags ../dist/tags
diff --git a/bdb/dist/s_tags b/bdb/dist/s_tags
index 834600b9fb1..18b6025aa86 100755
--- a/bdb/dist/s_tags
+++ b/bdb/dist/s_tags
@@ -1,31 +1,41 @@
#!/bin/sh -
-# $Id: s_tags,v 1.5 2000/09/05 21:27:04 bostic Exp $
+# $Id: s_tags,v 1.16 2002/03/28 20:13:07 krinsky Exp $
#
# Build tags files.
-files="../include/*.h \
- ../include/*.src \
+. ./RELEASE
+
+files="../dbinc/*.h \
+ ../dbinc/*.in \
../btree/*.[ch] \
../clib/*.[ch] \
../common/*.[ch] \
+# ../crypto/*.[ch] \
+ ../crypto/mersenne/*.[ch] \
+ ../crypto/rijndael/*.[ch] \
../db/*.[ch] \
../db185/*.[ch] \
../dbm/*.[ch] \
+ ../dbreg/*.[ch] \
../env/*.[ch] \
+ ../fileops/*.[ch] \
../hash/*.[ch] \
+ ../hmac/*.[ch] \
../hsearch/*.[ch] \
- ../libdb_java/*.[ch] \
../lock/*.[ch] \
../log/*.[ch] \
../mp/*.[ch] \
../mutex/*.[ch] \
../os/*.[ch] \
../qam/*.[ch] \
+ ../rep/*.[ch] \
../rpc_client/*.[ch] \
- ../rpc_server/*.[ch] \
+ ../rpc_server/c/*.[ch] \
../tcl/*.[ch] \
../txn/*.[ch] \
- ../xa/*.[ch]"
+ ../xa/*.[ch] \
+ ../cxx/*.cpp \
+ ../libdb_java/*.[ch]"
f=tags
echo "Building $f"
@@ -45,3 +55,8 @@ fi
ctags $flags $files 2>/dev/null
chmod 444 $f
+
+#f=../test_perf/tags
+#echo "Building $f"
+#(cd ../test_perf && ctags $flags *.[ch] 2>/dev/null)
+#chmod 444 $f
diff --git a/bdb/dist/s_tcl b/bdb/dist/s_tcl
deleted file mode 100755
index 7350e9a49e9..00000000000
--- a/bdb/dist/s_tcl
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh -
-# $Id: s_tcl,v 1.14 2000/11/09 19:24:07 sue Exp $
-#
-# Build the Tcl test files.
-
-msgshb="# DO NOT EDIT BELOW THIS LINE: automatically built by dist/s_tcl."
-
-. RELEASE
-
-f=../test/include.tcl
-echo "Building $f"
-rm -f $f
-(echo "set tclsh_path @TCL_TCLSH@" && \
- echo "set tcllib .libs/libdb_tcl-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@SOSUFFIX@" && \
- echo "set rpc_server localhost" && \
- echo "set rpc_path ." && \
- echo "set test_path @srcdir@/../test" && \
- echo "" && \
- echo "set KILL \"@db_cv_path_kill@\"" && \
- echo "" && \
- echo "$msgshb" && \
- echo "" && \
- echo "global dict" && \
- echo "global testdir" && \
- echo "global util_path" && \
- echo "set testdir ./TESTDIR" && \
- echo "set rpc_testdir \$rpc_path/TESTDIR" && \
- echo "" && \
- echo "global is_hp_test" && \
- echo "global is_qnx_test" && \
- echo "global is_windows_test") > $f
-chmod 444 $f
-
-f=../build_win32/include.tcl
-echo "Building $f"
-rm -f $f
-(echo "set tclsh_path SET_YOUR_TCLSH_PATH" && \
- echo "set test_path ../test" && \
- echo "set tcllib ./Debug/libdb_tcl${DB_VERSION_MAJOR}${DB_VERSION_MINOR}d.dll" && \
- echo "" && \
- echo "set KILL ./dbkill.exe" && \
- echo "" && \
- echo "$msgshb" && \
- echo "" && \
- echo "global dict" && \
- echo "global testdir" && \
- echo "global util_path" && \
- echo "set testdir ./TESTDIR" && \
- echo "" && \
- echo "global is_hp_test" && \
- echo "global is_qnx_test" && \
- echo "global is_windows_test") > $f
-chmod 444 $f
diff --git a/bdb/dist/s_test b/bdb/dist/s_test
new file mode 100755
index 00000000000..266f27a743f
--- /dev/null
+++ b/bdb/dist/s_test
@@ -0,0 +1,92 @@
+#!/bin/sh -
+# $Id: s_test,v 1.24 2002/08/09 02:24:58 bostic Exp $
+#
+# Build the Tcl test files.
+
+msg1="# Automatically built by dist/s_test; may require local editing."
+msg2="# Automatically built by dist/s_test; may require local editing."
+
+t=/tmp/__t
+trap 'rm -f $t; exit 0' 0 1 2 3 13 15
+
+. RELEASE
+
+(echo "$msg1" && \
+ echo "" && \
+ echo "set tclsh_path @TCL_TCLSH@" && \
+ echo "set tcllib .libs/libdb_tcl-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@MODSUFFIX@" && \
+ echo "" && \
+ echo "set rpc_server localhost" && \
+ echo "set rpc_path ." && \
+ echo "set rpc_testdir \$rpc_path/TESTDIR" && \
+ echo "" && \
+ echo "set src_root @srcdir@/.." && \
+ echo "set test_path @srcdir@/../test" && \
+ echo "" && \
+ echo "global testdir" && \
+ echo "set testdir ./TESTDIR" && \
+ echo "" && \
+ echo "global dict" && \
+ echo "global util_path" && \
+ echo "" && \
+ echo "global is_hp_test" && \
+ echo "global is_qnx_test" && \
+ echo "global is_windows_test" && \
+ echo "" && \
+ echo "set KILL \"@db_cv_path_kill@\"") > $t
+
+f=../test/include.tcl
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+(echo "$msg1" && \
+ echo "" && \
+ echo "set tclsh_path SET_YOUR_TCLSH_PATH" && \
+ echo "set tcllib ./Debug/libdb_tcl${DB_VERSION_MAJOR}${DB_VERSION_MINOR}d.dll" && \
+ echo "" && \
+ echo "set src_root .." && \
+ echo "set test_path ../test" && \
+ echo "" && \
+ echo "global testdir" && \
+ echo "set testdir ./TESTDIR" && \
+ echo "" && \
+ echo "global dict" && \
+ echo "global util_path" && \
+ echo "" && \
+ echo "global is_hp_test" && \
+ echo "global is_qnx_test" && \
+ echo "global is_windows_test" && \
+ echo "" && \
+ echo "set KILL ./dbkill.exe") > $t
+
+f=../build_win32/include.tcl
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build the test directory TESTS file.
+(echo $msg2;
+cat `egrep -l '^#[ ][ ]*TEST' ../test/*.tcl` |
+sed -e '/^#[ ][ ]*TEST/!{' \
+ -e 's/.*//' \
+ -e '}' |
+cat -s |
+sed -e '/TEST/{' \
+ -e 's/^#[ ][ ]*TEST[ ]*//' \
+ -e 's/^ //' \
+ -e 'H' \
+ -e 'd' \
+ -e '}' \
+ -e 's/.*//' \
+ -e x \
+ -e 's/\n/__LINEBREAK__/g' |
+sort |
+sed -e 's/__LINEBREAK__/\
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\
+/' \
+ -e 's/__LINEBREAK__/\
+ /g' |
+sed -e 's/^[ ][ ]*$//') > $t
+
+f=../test/TESTS
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
diff --git a/bdb/dist/s_vxworks b/bdb/dist/s_vxworks
index edf058df7ee..b7cf785f78b 100644
--- a/bdb/dist/s_vxworks
+++ b/bdb/dist/s_vxworks
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $Id: s_vxworks,v 1.3 2000/07/13 18:38:46 bostic Exp $
+# $Id: s_vxworks,v 1.37 2002/08/19 21:27:06 bostic Exp $
#
# Build the VxWorks files.
@@ -7,15 +7,26 @@ msgc="/* DO NOT EDIT: automatically built by dist/s_vxworks. */"
. RELEASE
-t=/tmp/__db_$$
-rm -f $t
+s=/tmp/__db_a
+t=/tmp/__db_b
+vxfilelist=/tmp/__db_c
-trap 'rm -f $t ; exit 1' 1 2 3 13 15
+trap 'rm -f $s $t $vxfilelist ; exit 0' 0
+trap 'rm -f $s $t $vxfilelist ; exit 1' 1 2 3 13 15
+# Build the VxWorks automatically generated files.
f=../build_vxworks/db.h
-echo "Building $f"
-rm -f $f
-cat <<ENDOFSEDTEXT > $t
+cat <<ENDOFSEDTEXT > $s
+/extern "C" {/{
+n
+n
+i\\
+\\
+/* Tornado 2 does not provide a standard C pre-processor #define. */\\
+#ifndef __vxworks\\
+#define __vxworks\\
+#endif
+}
s/@u_int8_decl@/typedef unsigned char u_int8_t;/
s/@u_int16_decl@/typedef unsigned short u_int16_t;/
s/@u_int32_decl@/typedef unsigned int u_int32_t;/
@@ -30,19 +41,284 @@ s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/
s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/
s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/
s/@DB_VERSION_STRING@/"$DB_VERSION_STRING"/
+s/@DB_VERSION_UNIQUE_NAME@//
ENDOFSEDTEXT
-(echo "$msgc" && sed -f $t ../include/db.src) > $f
-chmod 444 $f
+(echo "$msgc" &&
+ sed -f $s ../dbinc/db.in &&
+ cat ../dbinc_auto/rpc_defs.in &&
+ cat ../dbinc_auto/ext_prot.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
f=../build_vxworks/db_int.h
-echo "Building $f"
-rm -f $f
-cat <<ENDOFSEDTEXT > $t
+cat <<ENDOFSEDTEXT > $s
s/\(PATH_SEPARATOR[^"]*"\)\/"/\1\/\\\\\\\\\\"/
s/@db_align_t_decl@/typedef unsigned long db_align_t;/
s/@db_alignp_t_decl@/typedef unsigned long db_alignp_t;/
+s/@db_int_def@//
ENDOFSEDTEXT
-(echo "$msgc" && sed -f $t ../include/db_int.src) > $f
-chmod 444 $f
+(echo "$msgc" && sed -f $s ../dbinc/db_int.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-rm -f $t
+f=../build_vxworks/db_config.h
+(echo "$msgc" && sed "s/__EDIT_DB_VERSION__/$DB_VERSION/" vx_config.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build a sed script that will change a "standard" DB utility into
+# VxWorks-compatible code.
+transform()
+{
+ # Build a sed script that will add argument parsing support and
+ # rename all of the functions to be private to this file.
+cat <<ENDOFSEDTEXT
+/^main(argc, argv)$/{
+i\\
+$1(args)\\
+\\ char *args;\\
+{\\
+\\ int argc;\\
+\\ char **argv;\\
+\\
+\\ __db_util_arg("$1", args, &argc, &argv);\\
+\\ return ($1_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS);\\
+}\\
+\\
+#include <stdio.h>\\
+#define ERROR_RETURN ERROR\\
+\\
+int\\
+$1_main(argc, argv)
+d
+}
+/^ while ((ch = getopt/i\\
+\\ __db_getopt_reset = 1;
+/^[ ]*extern int optind;/s/;/, __db_getopt_reset;/
+ENDOFSEDTEXT
+
+ # Replace all function names with VxWorks safe names.
+ # Function names are:
+ # Tokens starting at the beginning of the line, immediately
+ # followed by an opening parenthesis.
+ # Replace:
+ # Matches preceded by a non-C-token character and immediately
+ # followed by an opening parenthesis.
+ # Matches preceded by a non-C-token character and immediately
+ # followed by " __P".
+ # Matches starting at the beginning of the line, immediately
+ # followed by an opening parenthesis.
+ for k in `sed -e 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)(.*$/\1/p' -e d $2`; do
+ echo "s/\([^a-zA-Z0-9_]\)\($k(\)/\1$1_\2/g"
+ echo "s/\([^a-zA-Z0-9_]\)\($k[ ]__P\)/\1$1_\2/g"
+ echo "s/^\($k(\)/$1_\1/g"
+ done
+
+ # There is a special case the rules above don't catch:
+ # a txn_compare function used as an argument to qsort(3).
+ # a print_app_record function used as argument to
+ # dbenv->set_app_dispatch).
+ echo "s/, txn_compare);/, db_stat_txn_compare);/"
+ echo "s/, print_app_record)) /, db_printlog_print_app_record)) /"
+
+ # We convert the ex_access sample into dbdemo for VxWorks.
+ echo 's/progname = "ex_access";/progname = "dbdemo";/'
+
+ # The example programs have to load db_int.h, not db.h -- else
+ # they won't have the right Berkeley DB prototypes for getopt
+ # and friends.
+ echo '/#include.*db.h/c\'
+ echo '#include <db_config.h>\'
+ echo '#include <db_int.h>'
+}
+
+PROGRAM_LIST="db_archive db_checkpoint db_deadlock db_dump db_load \
+ db_printlog db_recover db_stat db_upgrade db_verify ex_access"
+
+# Build VxWorks versions of the utilities.
+for i in $PROGRAM_LIST; do
+ if [ $i = "ex_access" ]; then
+ target=dbdemo
+ dir=../examples_c
+ else
+ target=$i
+ dir=../$i
+ fi
+
+ transform $target $dir/$i.c > $s
+ sed -f $s < $dir/$i.c > $t
+
+ f=../build_vxworks/$target/$target.c
+ cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+done
+
+# Build VxWorks Tornado 2.0 project files for the utilities.
+for i in $PROGRAM_LIST; do
+ if [ $i = "ex_access" ]; then
+ target=dbdemo
+ dir=../examples_c
+ else
+ target=$i
+ dir=../$i
+ fi
+
+ sed "s/__DB_APPLICATION_NAME__/$target/g" < vx_2.0/wpj.in > $t
+ f=../build_vxworks/$target/$target.wpj
+ cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+done
+
+# Build the list of files VxWorks knows about.
+sed -e '/^$/d' -e '/^[ #]/d' srcfiles.in |
+ egrep -w vx |
+ sed 's/[ ].*//' > $vxfilelist
+
+# Build VxWorks Tornado 2.0 project files for the library itself.
+(cat vx_2.0/BerkeleyDB.wpj
+for i in `cat $vxfilelist`; do
+ o="<BEGIN> FILE_\$(PRJ_DIR)/../$i"
+ echo "${o}_dependDone"
+ echo "TRUE"
+ echo "<END>"
+ echo
+ echo "${o}_dependencies"
+ echo "\$(PRJ_DIR)/db_config.h \\"
+ echo " \$(PRJ_DIR)/db_int.h \\"
+ echo " \$(PRJ_DIR)/db.h"
+ echo "<END>"
+ echo
+ echo "${o}_objects"
+ echo "`basename $i .c`.o"
+ echo "<END>"
+ echo
+ echo "${o}_tool"
+ echo "C/C++ compiler"
+ echo "<END>"
+ echo
+done
+echo "<BEGIN> PROJECT_FILES"
+sed -e '$!s/$/ \\/' \
+ -e 's/^/$(PRJ_DIR)\/..\//' \
+ -e '1!s/^/ /' < $vxfilelist
+echo "<END>"
+echo
+echo "<BEGIN> userComments"
+echo "BerkeleyDB"
+echo "<END>") > $t
+f=../build_vxworks/BerkeleyDB.wpj
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+# Build VxWorks Tornado 3.1 project files for the utilities.
+for i in $PROGRAM_LIST; do
+ if [ $i = "ex_access" ]; then
+ target=dbdemo
+ dir=../examples_c
+ else
+ target=$i
+ dir=../$i
+ fi
+
+ cp vx_3.1/Makefile.custom $t
+ f=../build_vxworks/$target/$target/Makefile.custom
+ cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+ for j in component.cdf component.wpj; do
+ #
+ # Some parts of the component files needs to have the
+ # name in all capitals. Sigh.
+ #
+ z=`echo $target | tr "a-z" "A-Z"`
+ sed -e "s/__DB_APPLICATION_NAME__/$target/g" \
+ -e "s/__DB_CAPAPPL_NAME__/$z/g" < vx_3.1/$j > $t
+ f=../build_vxworks/$target/$target/$j
+ cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+ done
+done
+
+# Build VxWorks Tornado 3.1 project files for the library itself.
+cp vx_3.1/Makefile.custom $t
+f=../build_vxworks/BerkeleyDB/Makefile.custom
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+(cat vx_3.1/cdf.1
+echo -n " MODULES"
+for i in `cat $vxfilelist`; do
+ echo " `basename $i .c`.o"
+done | sort | sed -e '$!s/$/ \\/'
+cat vx_3.1/cdf.2
+for i in `cat $vxfilelist`; do
+ b="`basename $i .c`.o"
+ echo "Module $b {"
+ echo
+ echo " NAME $b"
+ echo " SRC_PATH_NAME \$(PRJ_DIR)/../../$i"
+ echo "}"
+ echo
+done
+cat vx_3.1/cdf.3)> $t
+f=../build_vxworks/BerkeleyDB/component.cdf
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+(cat vx_3.1/wpj.1
+for i in `cat $vxfilelist`; do
+ o="<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_\$(PRJ_DIR)/../../$i"
+ echo "${o}_infoTags"
+ echo "toolMacro objects"
+ echo "<END>"
+ echo
+ echo "${o}_objects"
+ echo "`basename $i .c`.o"
+ echo "<END>"
+ echo
+ echo "${o}_toolMacro"
+ echo "CC"
+ echo "<END>"
+ echo
+done
+cat vx_3.1/wpj.2
+for i in `cat $vxfilelist`; do
+ o="<BEGIN> BUILD_PENTIUM2gnu.release_FILE_\$(PRJ_DIR)/../../$i"
+ echo "${o}_infoTags"
+ echo "toolMacro objects"
+ echo "<END>"
+ echo
+ echo "${o}_objects"
+ echo "`basename $i .c`.o"
+ echo "<END>"
+ echo
+ echo "${o}_toolMacro"
+ echo "CC"
+ echo "<END>"
+ echo
+done
+cat vx_3.1/wpj.3
+for i in `cat $vxfilelist`; do
+ o="<BEGIN> BUILD_PENTIUMgnu.debug_FILE_\$(PRJ_DIR)/../../$i"
+ echo "${o}_infoTags"
+ echo "toolMacro objects"
+ echo "<END>"
+ echo
+ echo "${o}_objects"
+ echo "`basename $i .c`.o"
+ echo "<END>"
+ echo
+ echo "${o}_toolMacro"
+ echo "CC"
+ echo "<END>"
+ echo
+done
+cat vx_3.1/wpj.4
+sort $vxfilelist |
+sed -e 's/^/$(PRJ_DIR)\/..\/..\//' \
+ -e '1!s/^/ /' \
+ -e '$!s/$/ \\/'
+cat vx_3.1/wpj.5) > $t
+f=../build_vxworks/BerkeleyDB/component.wpj
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
diff --git a/bdb/dist/s_win32 b/bdb/dist/s_win32
index f989a615e48..78814ababa1 100755
--- a/bdb/dist/s_win32
+++ b/bdb/dist/s_win32
@@ -1,21 +1,22 @@
#!/bin/sh -
-# $Id: s_win32,v 1.9 2000/09/20 15:29:54 bostic Exp $
+# $Id: s_win32,v 1.25 2002/05/20 19:18:14 bostic Exp $
#
# Build Windows/32 include files.
msgc="/* DO NOT EDIT: automatically built by dist/s_win32. */"
+msgw="; DO NOT EDIT: automatically built by dist/s_win32."
. RELEASE
-t=/tmp/__db_$$
-rm -f $t
+s=/tmp/__db_a$$
+t=/tmp/__db_b$$
+rm -f $s $t
-trap 'rm -f $t ; exit 1' 1 2 3 13 15
+trap 'rm -f $s $t ; exit 1' 1 2 3 13 15
+# Build the Win32 automatically generated files.
f=../build_win32/db.h
-echo "Building $f"
-rm -f $f
-cat <<ENDOFSEDTEXT > $t
+cat <<ENDOFSEDTEXT > $s
s/@u_int8_decl@/typedef unsigned char u_int8_t;/
s/@int16_decl@/typedef short int16_t;/
s/@u_int16_decl@/typedef unsigned short u_int16_t;/
@@ -23,7 +24,7 @@ s/@int32_decl@/typedef int int32_t;/
s/@u_int32_decl@/typedef unsigned int u_int32_t;/
/@u_char_decl@/{
i\\
- #if !defined(_WINSOCKAPI_)
+#if !defined(_WINSOCKAPI_)
s/@u_char_decl@/typedef unsigned char u_char;/
}
s/@u_short_decl@/typedef unsigned short u_short;/
@@ -31,37 +32,77 @@ s/@u_int_decl@/typedef unsigned int u_int;/
/@u_long_decl@/{
s/@u_long_decl@/typedef unsigned long u_long;/
a\\
- #endif
+#endif
+}
+/@ssize_t_decl@/{
+ i\\
+#if defined(_WIN64)\\
+typedef __int64 ssize_t;\\
+#else\\
+typedef int ssize_t;\\
+#endif
+ d
}
-s/@ssize_t_decl@/typedef int ssize_t;/
s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/
s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/
s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/
s/@DB_VERSION_STRING@/"$DB_VERSION_STRING"/
+s/@DB_VERSION_UNIQUE_NAME@//
+ENDOFSEDTEXT
+(echo "$msgc" &&
+ sed -f $s ../dbinc/db.in &&
+ cat ../dbinc_auto/rpc_defs.in &&
+ cat ../dbinc_auto/ext_prot.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+f=../build_win32/db_cxx.h
+cat <<ENDOFSEDTEXT > $s
+s/@cxx_have_stdheaders@/#define HAVE_CXX_STDHEADERS 1/
ENDOFSEDTEXT
-(echo "$msgc" && sed -f $t ../include/db.src) > $f
-chmod 444 $f
+(echo "$msgc" && sed -f $s ../dbinc/db_cxx.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
f=../build_win32/db_int.h
-echo "Building $f"
-rm -f $f
-cat <<ENDOFSEDTEXT > $t
+cat <<ENDOFSEDTEXT > $s
s/\(PATH_SEPARATOR[^"]*"\)\/"/\1\\\\\\\\\\/:\"/
s/@db_align_t_decl@/typedef unsigned long db_align_t;/
s/@db_alignp_t_decl@/typedef unsigned long db_alignp_t;/
+s/@db_int_def@//
ENDOFSEDTEXT
-(echo "$msgc" && sed -f $t ../include/db_int.src) > $f
-chmod 444 $f
+(echo "$msgc" && sed -f $s ../dbinc/db_int.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+f=../build_win32/db_config.h
+(echo "$msgc" && sed "s/__EDIT_DB_VERSION__/$DB_VERSION/" win_config.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
f=../build_win32/libdb.rc
-echo "Building $f"
-rm -f $f
-cat <<ENDOFSEDTEXT > $t
+cat <<ENDOFSEDTEXT > $s
s/%MAJOR%/$DB_VERSION_MAJOR/
s/%MINOR%/$DB_VERSION_MINOR/
s/%PATCH%/$DB_VERSION_PATCH/
ENDOFSEDTEXT
-sed -f $t ../build_win32/libdbrc.src > $f
-chmod 444 $f
+sed -f $s ../build_win32/libdbrc.src > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+f=../build_win32/libdb.def
+(echo $msgw &&
+ echo &&
+ echo \
+ "DESCRIPTION 'Berkeley DB $DB_VERSION_MAJOR.$DB_VERSION_MINOR Library'" &&
+ echo &&
+ echo EXPORTS;
+a=1
+for i in `sed -e '/^$/d' -e '/^#/d' win_exports.in`; do
+ echo " $i @$a"
+ a=`expr $a + 1`
+done) > $t
+cmp $t $f > /dev/null 2>&1 ||
+ (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-rm -f $t
+rm -f $s $t
diff --git a/bdb/dist/s_win32_dsp b/bdb/dist/s_win32_dsp
index 8abee7c1a61..3b0bef831ba 100644
--- a/bdb/dist/s_win32_dsp
+++ b/bdb/dist/s_win32_dsp
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $Id: s_win32_dsp,v 1.3 2000/12/02 04:36:47 dda Exp $
+# $Id: s_win32_dsp,v 1.8 2002/03/26 23:37:55 bostic Exp $
#
# Build Windows/32 .dsp files.
@@ -18,7 +18,6 @@ create_dsp()
dspoutput=$BUILDDIR/$projname.dsp
- echo "Building $dspoutput"
rm -f $dspoutput.insert
for srcpath in `egrep "$match" $sources | sed -e 's/[ ].*//'`
do
@@ -42,22 +41,26 @@ create_dsp()
-e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g" \
-e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/g" \
< $dsptemplate > $dspoutput.new
- rm -f $dspoutput $dspoutput.insert
- mv $dspoutput.new $dspoutput
+
+ # Set the file mode to 644 because the VC++ IDE needs a writeable file
+ # in our development environment.
+ cmp $dspoutput.new $dspoutput > /dev/null 2>&1 ||
+ (echo "Building $dspoutput" && rm -f $dspoutput &&
+ cp $dspoutput.new $dspoutput && chmod 664 $dspoutput)
+ rm -f $dspoutput.insert $dspoutput.new
}
TMPA=/tmp/swin32dsp$$a
-trap "rm -f $TMPA; exit 1" 1 2 3 15
+trap "rm -f $TMPA; exit 1" 1 2 3 15
-# create a copy of the srcfiles with comments and 'skip' lines removed.
+# create a copy of the srcfiles with comments and empty lines removed.
# add a space at the end of each list of modules so that each module
# can be unambiguously matched e.g. ' dynamic '
-#
sed -e "s/#.*$//" \
-e "/^[ ]*$/d" \
-e "s/[ ][ ]*/ /" \
-e "s/[ ]*$//" \
- -e "/ skip$/d" \
+ -e "/[ ]/!d" \
-e "s/$/ /" < $SRCFILES > $TMPA
# get a list of all modules mentioned
@@ -80,6 +83,10 @@ do
create_dsp db_tcl " $module " $TMPA \
$BUILDDIR/tcl_dsp.src $BUILDDIR/srcfile_dsp.src
;;
+ testutil )
+ create_dsp db_test " $module " $TMPA \
+ $BUILDDIR/db_test.src $BUILDDIR/srcfile_dsp.src
+ ;;
static )
create_dsp db_static " $module " $TMPA \
$BUILDDIR/static_dsp.src $BUILDDIR/srcfile_dsp.src
@@ -89,6 +96,8 @@ do
create_dsp $appname " $module " $TMPA \
$BUILDDIR/app_dsp.src $BUILDDIR/srcfile_dsp.src
;;
+ vx )
+ ;;
* )
echo "s_win32_dsp: module name $module in $SRCFILES is unknown type"
;;
diff --git a/bdb/dist/srcfiles.in b/bdb/dist/srcfiles.in
index bfc564e13bb..54aeea0c1bc 100644
--- a/bdb/dist/srcfiles.in
+++ b/bdb/dist/srcfiles.in
@@ -1,8 +1,8 @@
-# $Id: srcfiles.in,v 1.7 2000/11/30 18:42:21 dda Exp $
+# $Id: srcfiles.in,v 1.59 2002/08/29 14:22:21 margo Exp $
#
-# This is an input file for the s_win32_dsp script. It describes every
-# source files used by Windows, and lists those that aren't as well,
-# as a completeness sanity check.
+# This is an input file for the s_win32_dsp and s_vxworks scripts. It lists
+# the source files in the Berkeley DB tree and notes which are used to build
+# the Win/32 and VxWorks libraries.
#
# Please keep this list sorted alphabetically!
#
@@ -11,259 +11,322 @@
#
# The possible modules, including the name of the project (.dsp) file:
#
-# app=NAME this is linked into application NAME.exe (db_NAME.dsp)
-# dynamic file appears in the DLL (db_dll.dsp)
-# java file appears in the java DLL (db_java.dsp)
-# skip this file is not used by Windows
-# static file appears in the static library (db_static.dsp)
-# tcl file appears in the tcl DLL (db_tcl.dsp)
+# app=NAME Linked into application NAME.exe (db_NAME.dsp)
+# dynamic File is in the Windows DLL (db_dll.dsp)
+# java File is in the Windows Java DLL (db_java.dsp)
+# static File is in the Windows static library (db_static.dsp)
+# tcl File is in the Windows tcl DLL (db_tcl.dsp)
+# testutil File is used for Windows testing (db_test.dsp)
+# vx File is in the VxWorks library.
-btree/bt_compare.c dynamic static
-btree/bt_conv.c dynamic static
-btree/bt_curadj.c dynamic static
-btree/bt_cursor.c dynamic static
-btree/bt_delete.c dynamic static
-btree/bt_method.c dynamic static
-btree/bt_open.c dynamic static
-btree/bt_put.c dynamic static
-btree/bt_rec.c dynamic static
-btree/bt_reclaim.c dynamic static
-btree/bt_recno.c dynamic static
-btree/bt_rsearch.c dynamic static
-btree/bt_search.c dynamic static
-btree/bt_split.c dynamic static
-btree/bt_stat.c dynamic static
-btree/bt_upgrade.c dynamic static
-btree/bt_verify.c dynamic static
-btree/btree_auto.c dynamic static
-build_win32/dbkill.cpp skip
-build_win32/dllmain.c dynamic
-build_win32/libdb.def dynamic
-build_win32/libdb.rc dynamic
-build_win32/libdb_tcl.def tcl
-clib/getcwd.c skip
-clib/getopt.c skip # must be linked into each app
-clib/memcmp.c skip
-clib/memmove.c skip
-clib/raise.c skip
-clib/snprintf.c skip
-clib/strcasecmp.c dynamic static
-clib/strerror.c skip
-clib/vsnprintf.c skip
-common/db_byteorder.c dynamic static
-common/db_err.c dynamic static
-common/db_getlong.c dynamic static
-common/db_log2.c dynamic static
-common/util_log.c dynamic static
-common/util_sig.c dynamic static
-cxx/cxx_app.cpp dynamic static
-cxx/cxx_except.cpp dynamic static
-cxx/cxx_lock.cpp dynamic static
-cxx/cxx_log.cpp dynamic static
-cxx/cxx_mpool.cpp dynamic static
-cxx/cxx_table.cpp dynamic static
-cxx/cxx_txn.cpp dynamic static
-db/crdel_auto.c dynamic static
-db/crdel_rec.c dynamic static
-db/db.c dynamic static
-db/db_am.c dynamic static
-db/db_auto.c dynamic static
-db/db_cam.c dynamic static
-db/db_conv.c dynamic static
-db/db_dispatch.c dynamic static
-db/db_dup.c dynamic static
-db/db_iface.c dynamic static
-db/db_join.c dynamic static
-db/db_meta.c dynamic static
-db/db_method.c dynamic static
-db/db_overflow.c dynamic static
-db/db_pr.c dynamic static
-db/db_rec.c dynamic static
-db/db_reclaim.c dynamic static
-db/db_ret.c dynamic static
-db/db_upg.c dynamic static
-db/db_upg_opd.c dynamic static
-db/db_vrfy.c dynamic static
-db/db_vrfyutil.c dynamic static
-db185/db185.c skip
-db_archive/db_archive.c app=db_archive
-db_checkpoint/db_checkpoint.c app=db_checkpoint
-db_deadlock/db_deadlock.c app=db_deadlock
-db_dump/db_dump.c app=db_dump
-db_dump185/db_dump185.c skip
-db_load/db_load.c app=db_load
-db_printlog/db_printlog.c app=db_printlog
-db_recover/db_recover.c app=db_recover
-db_stat/db_stat.c app=db_stat
-db_upgrade/db_upgrade.c app=db_upgrade
-db_verify/db_verify.c app=db_verify
-dbm/dbm.c dynamic static
-env/db_salloc.c dynamic static
-env/db_shash.c dynamic static
-env/env_method.c dynamic static
-env/env_open.c dynamic static
-env/env_recover.c dynamic static
-env/env_region.c dynamic static
-examples_c/ex_access.c app=ex_access
-examples_c/ex_btrec.c app=ex_btrec
-examples_c/ex_dbclient.c skip
-examples_c/ex_env.c app=ex_env
-examples_c/ex_lock.c app=ex_lock
-examples_c/ex_mpool.c app=ex_mpool
-examples_c/ex_thread.c skip
-examples_c/ex_tpcb.c app=ex_tpcb
-examples_cxx/AccessExample.cpp app=excxx_access
-examples_cxx/BtRecExample.cpp app=excxx_btrec
-examples_cxx/EnvExample.cpp app=excxx_env
-examples_cxx/LockExample.cpp app=excxx_lock
-examples_cxx/MpoolExample.cpp app=excxx_mpool
-examples_cxx/TpcbExample.cpp app=excxx_tpcb
-hash/hash.c dynamic static
-hash/hash_auto.c dynamic static
-hash/hash_conv.c dynamic static
-hash/hash_dup.c dynamic static
-hash/hash_func.c dynamic static
-hash/hash_meta.c dynamic static
-hash/hash_method.c dynamic static
-hash/hash_page.c dynamic static
-hash/hash_rec.c dynamic static
-hash/hash_reclaim.c dynamic static
-hash/hash_stat.c dynamic static
-hash/hash_upgrade.c dynamic static
-hash/hash_verify.c dynamic static
-hsearch/hsearch.c dynamic static
-libdb_java/java_Db.c java
-libdb_java/java_DbEnv.c java
-libdb_java/java_DbLock.c java
-libdb_java/java_DbLsn.c java
-libdb_java/java_DbTxn.c java
-libdb_java/java_Dbc.c java
-libdb_java/java_Dbt.c java
-libdb_java/java_info.c java
-libdb_java/java_locked.c java
-libdb_java/java_util.c java
-lock/lock.c dynamic static
-lock/lock_conflict.c dynamic static
-lock/lock_deadlock.c dynamic static
-lock/lock_method.c dynamic static
-lock/lock_region.c dynamic static
-lock/lock_stat.c dynamic static
-lock/lock_util.c dynamic static
-log/log.c dynamic static
-log/log_archive.c dynamic static
-log/log_auto.c dynamic static
-log/log_compare.c dynamic static
-log/log_findckp.c dynamic static
-log/log_get.c dynamic static
-log/log_method.c dynamic static
-log/log_put.c dynamic static
-log/log_rec.c dynamic static
-log/log_register.c dynamic static
-mp/mp_alloc.c dynamic static
-mp/mp_bh.c dynamic static
-mp/mp_fget.c dynamic static
-mp/mp_fopen.c dynamic static
-mp/mp_fput.c dynamic static
-mp/mp_fset.c dynamic static
-mp/mp_method.c dynamic static
-mp/mp_region.c dynamic static
-mp/mp_register.c dynamic static
-mp/mp_stat.c dynamic static
-mp/mp_sync.c dynamic static
-mp/mp_trickle.c dynamic static
-mutex/mut_fcntl.c skip
-mutex/mut_pthread.c skip
-mutex/mut_tas.c dynamic static
-mutex/mutex.c dynamic static
-os/os_abs.c skip
-os/os_alloc.c dynamic static
-os/os_dir.c skip
-os/os_errno.c skip
-os/os_fid.c skip
-os/os_finit.c skip
-os/os_fsync.c dynamic static
-os/os_handle.c dynamic static
-os/os_map.c skip
-os/os_method.c dynamic static
-os/os_oflags.c dynamic static
-os/os_open.c skip
-os/os_region.c dynamic static
-os/os_rename.c skip
-os/os_root.c dynamic static
-os/os_rpath.c dynamic static
-os/os_rw.c dynamic static
-os/os_seek.c skip
-os/os_sleep.c skip
-os/os_spin.c skip
-os/os_stat.c dynamic static
-os/os_tmpdir.c dynamic static
-os/os_unlink.c dynamic static
-os_vxworks/os_abs.c skip
-os_vxworks/os_finit.c skip
-os_vxworks/os_map.c skip
-os_win32/os_abs.c dynamic static
-os_win32/os_dir.c dynamic static
-os_win32/os_errno.c dynamic static
-os_win32/os_fid.c dynamic static
-os_win32/os_finit.c dynamic static
-os_win32/os_map.c dynamic static
-os_win32/os_open.c dynamic static
-os_win32/os_rename.c dynamic static
-os_win32/os_seek.c dynamic static
-os_win32/os_sleep.c dynamic static
-os_win32/os_spin.c dynamic static
-os_win32/os_type.c dynamic static
-qam/qam.c dynamic static
-qam/qam_auto.c dynamic static
-qam/qam_conv.c dynamic static
-qam/qam_files.c dynamic static
-qam/qam_method.c dynamic static
-qam/qam_open.c dynamic static
-qam/qam_rec.c dynamic static
-qam/qam_stat.c dynamic static
-qam/qam_upgrade.c dynamic static
-qam/qam_verify.c dynamic static
-rpc_client/client.c skip
-rpc_client/db_server_clnt.c skip
-rpc_client/gen_client.c skip
-rpc_client/gen_client_ret.c skip
-rpc_server/db_server_proc.c skip
-rpc_server/db_server_svc.c skip
-rpc_server/db_server_util.c skip
-rpc_server/db_server_xdr.c skip
-rpc_server/gen_db_server.c skip
-tcl/tcl_compat.c tcl
-tcl/tcl_db.c tcl
-tcl/tcl_db_pkg.c tcl
-tcl/tcl_dbcursor.c tcl
-tcl/tcl_env.c tcl
-tcl/tcl_internal.c tcl
-tcl/tcl_lock.c tcl
-tcl/tcl_log.c tcl
-tcl/tcl_mp.c tcl
-tcl/tcl_txn.c tcl
-test_server/dbs.c skip
-test_server/dbs_am.c skip
-test_server/dbs_checkpoint.c skip
-test_server/dbs_debug.c skip
-test_server/dbs_handles.c skip
-test_server/dbs_log.c skip
-test_server/dbs_qam.c skip
-test_server/dbs_spawn.c skip
-test_server/dbs_trickle.c skip
-test_server/dbs_util.c skip
-test_server/dbs_yield.c skip
-test_thread/lock.c skip
-test_thread/log.c skip
-test_thread/mpool.c skip
-test_thread/mutex.c skip
-test_vxworks/vx_mutex.c skip
-test_vxworks/vxtpcb_files.c skip
-test_vxworks/vxtpcb_onefile.c skip
-txn/txn.c dynamic static
-txn/txn_auto.c dynamic static
-txn/txn_rec.c dynamic static
-txn/txn_region.c dynamic static
-xa/xa.c dynamic static
-xa/xa_db.c dynamic static
-xa/xa_map.c dynamic static
+btree/bt_compare.c dynamic static vx
+btree/bt_conv.c dynamic static vx
+btree/bt_curadj.c dynamic static vx
+btree/bt_cursor.c dynamic static vx
+btree/bt_delete.c dynamic static vx
+btree/bt_method.c dynamic static vx
+btree/bt_open.c dynamic static vx
+btree/bt_put.c dynamic static vx
+btree/bt_rec.c dynamic static vx
+btree/bt_reclaim.c dynamic static vx
+btree/bt_recno.c dynamic static vx
+btree/bt_rsearch.c dynamic static vx
+btree/bt_search.c dynamic static vx
+btree/bt_split.c dynamic static vx
+btree/bt_stat.c dynamic static vx
+btree/bt_upgrade.c dynamic static vx
+btree/bt_verify.c dynamic static vx
+btree/btree_auto.c dynamic static vx
+build_vxworks/db_archive/db_archive.c
+build_vxworks/db_checkpoint/db_checkpoint.c
+build_vxworks/db_deadlock/db_deadlock.c
+build_vxworks/db_dump/db_dump.c
+build_vxworks/db_load/db_load.c
+build_vxworks/db_printlog/db_printlog.c
+build_vxworks/db_recover/db_recover.c
+build_vxworks/db_stat/db_stat.c
+build_vxworks/db_upgrade/db_upgrade.c
+build_vxworks/db_verify/db_verify.c
+build_vxworks/dbdemo/dbdemo.c
+build_win32/dbkill.cpp testutil
+build_win32/dllmain.c dynamic
+build_win32/libdb.def dynamic
+build_win32/libdb.rc dynamic
+build_win32/libdb_tcl.def tcl
+clib/getcwd.c
+clib/getopt.c vx
+clib/memcmp.c
+clib/memmove.c
+clib/raise.c
+clib/snprintf.c vx
+clib/strcasecmp.c dynamic static vx
+clib/strdup.c vx
+clib/strerror.c
+clib/vsnprintf.c vx
+common/db_byteorder.c dynamic static vx
+common/db_err.c dynamic static vx
+common/db_getlong.c dynamic static vx
+common/db_idspace.c dynamic static vx
+common/db_log2.c dynamic static vx
+common/util_arg.c vx
+common/util_cache.c dynamic static vx
+common/util_log.c dynamic static vx
+common/util_sig.c dynamic static vx
+cxx/cxx_db.cpp dynamic static
+cxx/cxx_dbc.cpp dynamic static
+cxx/cxx_dbt.cpp dynamic static
+cxx/cxx_env.cpp dynamic static
+cxx/cxx_except.cpp dynamic static
+cxx/cxx_lock.cpp dynamic static
+cxx/cxx_logc.cpp dynamic static
+cxx/cxx_mpool.cpp dynamic static
+cxx/cxx_txn.cpp dynamic static
+db/crdel_auto.c dynamic static vx
+db/crdel_rec.c dynamic static vx
+db/db.c dynamic static vx
+db/db_am.c dynamic static vx
+db/db_auto.c dynamic static vx
+db/db_cam.c dynamic static vx
+db/db_conv.c dynamic static vx
+db/db_dispatch.c dynamic static vx
+db/db_dup.c dynamic static vx
+db/db_iface.c dynamic static vx
+db/db_join.c dynamic static vx
+db/db_meta.c dynamic static vx
+db/db_method.c dynamic static vx
+db/db_open.c dynamic static vx
+db/db_overflow.c dynamic static vx
+db/db_pr.c dynamic static vx
+db/db_rec.c dynamic static vx
+db/db_reclaim.c dynamic static vx
+db/db_remove.c dynamic static vx
+db/db_rename.c dynamic static vx
+db/db_ret.c dynamic static vx
+db/db_truncate.c dynamic static vx
+db/db_upg.c dynamic static vx
+db/db_upg_opd.c dynamic static vx
+db/db_vrfy.c dynamic static vx
+db/db_vrfyutil.c dynamic static vx
+db185/db185.c
+db_archive/db_archive.c app=db_archive
+db_checkpoint/db_checkpoint.c app=db_checkpoint
+db_deadlock/db_deadlock.c app=db_deadlock
+db_dump/db_dump.c app=db_dump
+db_dump185/db_dump185.c
+db_load/db_load.c app=db_load
+db_printlog/db_printlog.c app=db_printlog
+db_recover/db_recover.c app=db_recover
+db_stat/db_stat.c app=db_stat
+db_upgrade/db_upgrade.c app=db_upgrade
+db_verify/db_verify.c app=db_verify
+dbm/dbm.c dynamic static
+dbreg/dbreg.c dynamic static vx
+dbreg/dbreg_auto.c dynamic static vx
+dbreg/dbreg_rec.c dynamic static vx
+dbreg/dbreg_util.c dynamic static vx
+env/db_salloc.c dynamic static vx
+env/db_shash.c dynamic static vx
+env/env_file.c dynamic static vx
+env/env_method.c dynamic static vx
+env/env_open.c dynamic static vx
+env/env_recover.c dynamic static vx
+env/env_region.c dynamic static vx
+examples_c/bench_001.c
+examples_c/ex_access.c app=ex_access
+examples_c/ex_apprec/ex_apprec.c
+examples_c/ex_apprec/ex_apprec_auto.c
+examples_c/ex_apprec/ex_apprec_rec.c
+examples_c/ex_btrec.c app=ex_btrec
+examples_c/ex_dbclient.c
+examples_c/ex_env.c app=ex_env
+examples_c/ex_lock.c app=ex_lock
+examples_c/ex_mpool.c app=ex_mpool
+examples_c/ex_repquote/ex_rq_client.c
+examples_c/ex_repquote/ex_rq_main.c
+examples_c/ex_repquote/ex_rq_master.c
+examples_c/ex_repquote/ex_rq_net.c
+examples_c/ex_repquote/ex_rq_util.c
+examples_c/ex_thread.c
+examples_c/ex_tpcb.c app=ex_tpcb
+examples_cxx/AccessExample.cpp app=excxx_access
+examples_cxx/BtRecExample.cpp app=excxx_btrec
+examples_cxx/EnvExample.cpp app=excxx_env
+examples_cxx/LockExample.cpp app=excxx_lock
+examples_cxx/MpoolExample.cpp app=excxx_mpool
+examples_cxx/TpcbExample.cpp app=excxx_tpcb
+fileops/fileops_auto.c dynamic static vx
+fileops/fop_basic.c dynamic static vx
+fileops/fop_rec.c dynamic static vx
+fileops/fop_util.c dynamic static vx
+hash/hash.c dynamic static vx
+hash/hash_auto.c dynamic static vx
+hash/hash_conv.c dynamic static vx
+hash/hash_dup.c dynamic static vx
+hash/hash_func.c dynamic static vx
+hash/hash_meta.c dynamic static vx
+hash/hash_method.c dynamic static vx
+hash/hash_open.c dynamic static vx
+hash/hash_page.c dynamic static vx
+hash/hash_rec.c dynamic static vx
+hash/hash_reclaim.c dynamic static vx
+hash/hash_stat.c dynamic static vx
+hash/hash_upgrade.c dynamic static vx
+hash/hash_verify.c dynamic static vx
+hmac/hmac.c dynamic static vx
+hmac/sha1.c dynamic static vx
+hsearch/hsearch.c dynamic static vx
+libdb_java/java_Db.c java
+libdb_java/java_DbEnv.c java
+libdb_java/java_DbLock.c java
+libdb_java/java_DbLogc.c java
+libdb_java/java_DbLsn.c java
+libdb_java/java_DbTxn.c java
+libdb_java/java_DbUtil.c java
+libdb_java/java_Dbc.c java
+libdb_java/java_Dbt.c java
+libdb_java/java_info.c java
+libdb_java/java_locked.c java
+libdb_java/java_stat_auto.c java
+libdb_java/java_util.c java
+lock/lock.c dynamic static vx
+lock/lock_deadlock.c dynamic static vx
+lock/lock_method.c dynamic static vx
+lock/lock_region.c dynamic static vx
+lock/lock_stat.c dynamic static vx
+lock/lock_util.c dynamic static vx
+log/log.c dynamic static vx
+log/log_archive.c dynamic static vx
+log/log_compare.c dynamic static vx
+log/log_get.c dynamic static vx
+log/log_method.c dynamic static vx
+log/log_put.c dynamic static vx
+mp/mp_alloc.c dynamic static vx
+mp/mp_bh.c dynamic static vx
+mp/mp_fget.c dynamic static vx
+mp/mp_fopen.c dynamic static vx
+mp/mp_fput.c dynamic static vx
+mp/mp_fset.c dynamic static vx
+mp/mp_method.c dynamic static vx
+mp/mp_region.c dynamic static vx
+mp/mp_register.c dynamic static vx
+mp/mp_stat.c dynamic static vx
+mp/mp_sync.c dynamic static vx
+mp/mp_trickle.c dynamic static vx
+mutex/mut_fcntl.c
+mutex/mut_pthread.c
+mutex/mut_tas.c vx
+mutex/mut_win32.c dynamic static
+mutex/mutex.c dynamic static vx
+mutex/tm.c
+os/os_abs.c
+os/os_alloc.c dynamic static vx
+os/os_clock.c vx
+os/os_config.c
+os/os_dir.c vx
+os/os_errno.c vx
+os/os_fid.c vx
+os/os_fsync.c vx
+os/os_handle.c vx
+os/os_id.c dynamic static vx
+os/os_map.c
+os/os_method.c dynamic static vx
+os/os_oflags.c dynamic static vx
+os/os_open.c vx
+os/os_region.c dynamic static vx
+os/os_rename.c vx
+os/os_root.c dynamic static vx
+os/os_rpath.c dynamic static vx
+os/os_rw.c vx
+os/os_seek.c vx
+os/os_sleep.c vx
+os/os_spin.c vx
+os/os_stat.c vx
+os/os_tmpdir.c dynamic static vx
+os/os_unlink.c dynamic static vx
+os_vxworks/os_vx_abs.c vx
+os_vxworks/os_vx_config.c vx
+os_vxworks/os_vx_map.c vx
+os_win32/os_abs.c dynamic static
+os_win32/os_clock.c dynamic static
+os_win32/os_config.c dynamic static
+os_win32/os_dir.c dynamic static
+os_win32/os_errno.c dynamic static
+os_win32/os_fid.c dynamic static
+os_win32/os_fsync.c dynamic static
+os_win32/os_handle.c dynamic static
+os_win32/os_map.c dynamic static
+os_win32/os_open.c dynamic static
+os_win32/os_rename.c dynamic static
+os_win32/os_rw.c dynamic static
+os_win32/os_seek.c dynamic static
+os_win32/os_sleep.c dynamic static
+os_win32/os_spin.c dynamic static
+os_win32/os_stat.c dynamic static
+os_win32/os_type.c dynamic static
+qam/qam.c dynamic static vx
+qam/qam_auto.c dynamic static vx
+qam/qam_conv.c dynamic static vx
+qam/qam_files.c dynamic static vx
+qam/qam_method.c dynamic static vx
+qam/qam_open.c dynamic static vx
+qam/qam_rec.c dynamic static vx
+qam/qam_stat.c dynamic static vx
+qam/qam_upgrade.c dynamic static vx
+qam/qam_verify.c dynamic static vx
+rep/rep_method.c dynamic static vx
+rep/rep_record.c dynamic static vx
+rep/rep_region.c dynamic static vx
+rep/rep_util.c dynamic static vx
+rpc_client/client.c vx
+rpc_client/db_server_clnt.c vx
+rpc_client/gen_client.c vx
+rpc_client/gen_client_ret.c vx
+rpc_server/c/db_server_proc.c
+rpc_server/c/db_server_svc.c
+rpc_server/c/db_server_util.c
+rpc_server/c/db_server_xdr.c vx
+rpc_server/c/gen_db_server.c
+rpc_server/cxx/db_server_cxxproc.cpp
+rpc_server/cxx/db_server_cxxutil.cpp
+tcl/tcl_compat.c tcl
+tcl/tcl_db.c tcl
+tcl/tcl_db_pkg.c tcl
+tcl/tcl_dbcursor.c tcl
+tcl/tcl_env.c tcl
+tcl/tcl_internal.c tcl
+tcl/tcl_lock.c tcl
+tcl/tcl_log.c tcl
+tcl/tcl_mp.c tcl
+tcl/tcl_rep.c tcl
+tcl/tcl_txn.c tcl
+tcl/tcl_util.c tcl
+test_perf/db_perf.c app=db_perf
+test_perf/perf_cache_check.c app=db_perf
+test_perf/perf_checkpoint.c app=db_perf
+test_perf/perf_config.c app=db_perf
+test_perf/perf_dbs.c app=db_perf
+test_perf/perf_debug.c app=db_perf
+test_perf/perf_file.c app=db_perf
+test_perf/perf_key.c app=db_perf
+test_perf/perf_log.c app=db_perf
+test_perf/perf_misc.c app=db_perf
+test_perf/perf_op.c app=db_perf
+test_perf/perf_parse.c app=db_perf
+test_perf/perf_rand.c app=db_perf
+test_perf/perf_spawn.c app=db_perf
+test_perf/perf_thread.c app=db_perf
+test_perf/perf_trickle.c app=db_perf
+test_perf/perf_txn.c app=db_perf
+test_perf/perf_util.c app=db_perf
+test_perf/perf_vx.c
+txn/txn.c dynamic static vx
+txn/txn_auto.c dynamic static vx
+txn/txn_method.c dynamic static vx
+txn/txn_rec.c dynamic static vx
+txn/txn_recover.c dynamic static vx
+txn/txn_region.c dynamic static vx
+txn/txn_stat.c dynamic static vx
+txn/txn_util.c dynamic static vx
+xa/xa.c dynamic static vx
+xa/xa_db.c dynamic static vx
+xa/xa_map.c dynamic static vx
diff --git a/bdb/dist/template/.IGNORE_ME b/bdb/dist/template/.IGNORE_ME
deleted file mode 100644
index 558fd496f0c..00000000000
--- a/bdb/dist/template/.IGNORE_ME
+++ /dev/null
@@ -1,3 +0,0 @@
-Some combinations of the gzip and tar archive exploders found
-on Linux systems ignore directories that don't have any files
-(other than symbolic links) in them. So, here's a file.
diff --git a/bdb/dist/template/rec_ctemp b/bdb/dist/template/rec_ctemp
new file mode 100644
index 00000000000..2951189c5bd
--- /dev/null
+++ b/bdb/dist/template/rec_ctemp
@@ -0,0 +1,62 @@
+/*
+ * PREF_FUNC_recover --
+ * Recovery function for FUNC.
+ *
+ * PUBLIC: int PREF_FUNC_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+PREF_FUNC_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ PREF_FUNC_args *argp;
+ DB *file_dbp;
+ DBC *dbc;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep;
+ int cmp_n, cmp_p, modified, ret;
+
+ REC_PRINT(PREF_FUNC_print);
+ REC_INTRO(PREF_FUNC_read, 1);
+
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+ if (DB_REDO(op)) {
+ if ((ret = mpf->get(mpf,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+ } else {
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+ goto out;
+ }
+
+ modified = 0;
+ cmp_n = log_compare(lsnp, &LSN(pagep));
+
+ /*
+ * Use this when there is something like "pagelsn" in the argp
+ * structure. Sometimes, you might need to compare meta-data
+ * lsn's instead.
+ *
+ * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+ */
+ if (cmp_p == 0 && DB_REDO(op)) {
+ /* Need to redo update described. */
+ modified = 1;
+ } else if (cmp_n == 0 && !DB_REDO(op)) {
+ /* Need to undo update described. */
+ modified = 1;
+ }
+ if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+ goto out;
+
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: REC_CLOSE;
+}
+
diff --git a/bdb/dist/vx_2.0/BerkeleyDB.wpj b/bdb/dist/vx_2.0/BerkeleyDB.wpj
new file mode 100644
index 00000000000..78684d90067
--- /dev/null
+++ b/bdb/dist/vx_2.0/BerkeleyDB.wpj
@@ -0,0 +1,251 @@
+Document file - DO NOT EDIT
+
+<BEGIN> BUILD_PENTIUM_debug_BUILDRULE
+BerkeleyDB.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AR
+ar386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AS
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CC
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS
+-g \
+ -mpentium \
+ -ansi \
+ -nostdinc \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -fvolatile \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM \
+ -O0 \
+ -I$(PRJ_DIR) \
+ -I$(PRJ_DIR)/.. \
+ -DDIAGNOSTIC \
+ -DDEBUG
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS_AS
+-g \
+ -mpentium \
+ -ansi \
+ -nostdinc \
+ -fvolatile \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CPP
+cc386 -E -P -xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD
+ld386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_NM
+nm386 -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_SIZE
+size386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+ {$(WIND_BASE)/target/src/} \
+ {$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_TC
+::tc_PENTIUMgnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_BUILDRULE
+BerkeleyDB.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AR
+ar386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AS
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CC
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS
+-mpentium \
+ -ansi \
+ -nostdinc \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -fvolatile \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM \
+ -O2 \
+ -I$(PRJ_DIR) \
+ -I$(PRJ_DIR)/..
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS_AS
+-g \
+ -mpentium \
+ -ansi \
+ -nostdinc \
+ -fvolatile \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CPP
+cc386 -E -P -xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD
+ld386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LDDEPS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_NM
+nm386 -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_SIZE
+size386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+ {$(WIND_BASE)/target/src/} \
+ {$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_TC
+::tc_PENTIUMgnu
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB.out
+
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB_sim.out
+
+<END>
+
+<BEGIN> BUILD_RULE_archive
+
+<END>
+
+<BEGIN> BUILD_RULE_objects
+
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM_debug
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUM_release PENTIUM_debug
+<END>
+
+<BEGIN> CORE_INFO_TYPE
+::prj_vxApp
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+2.0
+<END>
+
diff --git a/bdb/dist/vx_2.0/wpj.in b/bdb/dist/vx_2.0/wpj.in
new file mode 100644
index 00000000000..2b942bb562c
--- /dev/null
+++ b/bdb/dist/vx_2.0/wpj.in
@@ -0,0 +1,160 @@
+Document file - DO NOT EDIT
+
+<BEGIN> BUILD_PENTIUMgnu_BUILDRULE
+__DB_APPLICATION_NAME__.out
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_AR
+ar386
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUMgnu/__DB_APPLICATION_NAME__.a
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_AS
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_CC
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS
+-g \
+ -mpentium \
+ -ansi \
+ -nostdinc \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -fvolatile \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -I$(PRJ_DIR)/.. \
+ -I$(PRJ_DIR)/../.. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_CFLAGS_AS
+-g \
+ -mpentium \
+ -ansi \
+ -nostdinc \
+ -fvolatile \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_CPP
+cc386 -E -P -xc
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_LD
+ld386
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_LDDEPS
+
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_NM
+nm386 -g
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_MACRO_SIZE
+size386
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+ {$(WIND_BASE)/target/src/} \
+ {$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu_TC
+::tc_PENTIUMgnu
+<END>
+
+<BEGIN> BUILD_RULE_archive
+
+<END>
+
+<BEGIN> BUILD_RULE___DB_APPLICATION_NAME__.out
+
+<END>
+
+<BEGIN> BUILD_RULE_objects
+
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUMgnu
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUMgnu
+<END>
+
+<BEGIN> CORE_INFO_TYPE
+::prj_vxApp
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+2.0
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_dependDone
+FALSE
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_dependencies
+
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_objects
+__DB_APPLICATION_NAME__.o
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_tool
+C/C++ compiler
+<END>
+
+<BEGIN> PROJECT_FILES
+$(PRJ_DIR)/__DB_APPLICATION_NAME__.c
+<END>
+
+<BEGIN> userComments
+__DB_APPLICATION_NAME__
+<END>
diff --git a/bdb/dist/vx_3.1/Makefile.custom b/bdb/dist/vx_3.1/Makefile.custom
new file mode 100644
index 00000000000..ca781f7b251
--- /dev/null
+++ b/bdb/dist/vx_3.1/Makefile.custom
@@ -0,0 +1,51 @@
+#
+# Custom Makefile shell
+#
+# This file may be edited freely, since it will not be regenerated
+# by the project manager.
+#
+# Use this makefile to define rules to make external binaries
+# and deposit them in the $(EXTERNAL_BINARIES_DIR) directory.
+#
+# If you have specified external modules during your component
+# creation, you will find make rules already in place below.
+# You will likely have to edit these to suit your individual
+# build setup.
+#
+# You may wish to use the CPU, BUILD_SPEC or TOOL make variables in
+# your Makefile to support builds for different architectures. Use
+# the FORCE_EXTERNAL_MAKE phony target to ensure that your external
+# make always runs.
+#
+# The example below assumes that your custom makefile is in the
+# mySourceTree directory, and that the binary file it produces
+# is placed into the $(BUILD_SPEC) sub-directory.
+#
+# EXTERNAL_SOURCE_BASE = /folk/me/mySourceTree
+# EXTERNAL_MODULE = myLibrary.o
+# EXTERNAL_MAKE = make
+#
+# $(EXTERNAL_BINARIES_DIR)/$(EXTERNAL_MODULE) : FORCE_EXTERNAL_MAKE
+# $(EXTERNAL_MAKE) -C $(EXTERNAL_SOURCE_BASE) \
+# -f $(EXTERNAL_SOURCE_BASE)/Makefile \
+# CPU=$(CPU) BUILD_SPEC=$(BUILD_SPEC) $(@F)
+# $(CP) $(subst /,$(DIRCHAR),$(EXTERNAL_SOURCE_BASE)/$(BUILD_SPEC)/$(@F) $@)
+#
+# If you are not adding your external modules from the component wizard,
+# you will have to include them in your component yourself:
+#
+# From the GUI, you can do this with the Component's 'Add external module'
+# dialog.
+#
+# If you are using the command line, add the module(s) by editing the
+# MODULES line in component.cdf file, e.g.
+#
+# Component INCLUDE_MYCOMPONENT {
+#
+# MODULES foo.o goo.o \
+# myLibrary.o
+#
+
+
+# rules to build custom libraries
+
diff --git a/bdb/dist/vx_3.1/cdf.1 b/bdb/dist/vx_3.1/cdf.1
new file mode 100644
index 00000000000..17db06f7e61
--- /dev/null
+++ b/bdb/dist/vx_3.1/cdf.1
@@ -0,0 +1,12 @@
+/* component.cdf - dynamically updated configuration */
+
+/*
+ * NOTE: you may edit this file to alter the configuration
+ * But all non-configuration information, including comments,
+ * will be lost upon rebuilding this project.
+ */
+
+/* Component information */
+
+Component INCLUDE_BERKELEYDB {
+ ENTRY_POINTS ALL_GLOBAL_SYMBOLS
diff --git a/bdb/dist/vx_3.1/cdf.2 b/bdb/dist/vx_3.1/cdf.2
new file mode 100644
index 00000000000..76f123af9fb
--- /dev/null
+++ b/bdb/dist/vx_3.1/cdf.2
@@ -0,0 +1,9 @@
+ NAME BerkeleyDB
+ PREF_DOMAIN ANY
+ _INIT_ORDER usrComponentsInit
+}
+
+/* EntryPoint information */
+
+/* Module information */
+
diff --git a/bdb/dist/vx_3.1/cdf.3 b/bdb/dist/vx_3.1/cdf.3
new file mode 100644
index 00000000000..a3146ced95a
--- /dev/null
+++ b/bdb/dist/vx_3.1/cdf.3
@@ -0,0 +1,2 @@
+/* Parameter information */
+
diff --git a/bdb/dist/vx_3.1/component.cdf b/bdb/dist/vx_3.1/component.cdf
new file mode 100644
index 00000000000..91edaa87853
--- /dev/null
+++ b/bdb/dist/vx_3.1/component.cdf
@@ -0,0 +1,30 @@
+/* component.cdf - dynamically updated configuration */
+
+/*
+ * NOTE: you may edit this file to alter the configuration
+ * But all non-configuration information, including comments,
+ * will be lost upon rebuilding this project.
+ */
+
+/* Component information */
+
+Component INCLUDE___DB_CAPAPPL_NAME__ {
+ ENTRY_POINTS ALL_GLOBAL_SYMBOLS
+ MODULES __DB_APPLICATION_NAME__.o
+ NAME __DB_APPLICATION_NAME__
+ PREF_DOMAIN ANY
+ _INIT_ORDER usrComponentsInit
+}
+
+/* EntryPoint information */
+
+/* Module information */
+
+Module __DB_APPLICATION_NAME__.o {
+
+ NAME __DB_APPLICATION_NAME__.o
+ SRC_PATH_NAME $PRJ_DIR/../__DB_APPLICATION_NAME__.c
+}
+
+/* Parameter information */
+
diff --git a/bdb/dist/vx_3.1/component.wpj b/bdb/dist/vx_3.1/component.wpj
new file mode 100644
index 00000000000..01c51c1b97f
--- /dev/null
+++ b/bdb/dist/vx_3.1/component.wpj
@@ -0,0 +1,475 @@
+Document file - DO NOT EDIT
+
+<BEGIN> CORE_INFO_TYPE
+::prj_component
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+AE1.1
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM2gnu.debug
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_CURRENT_TARGET
+default
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_DEFAULTFORCPU
+1
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_objects
+__DB_APPLICATION_NAME__.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_objects
+__DB_APPLICATION_NAME__.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/compConfig.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/compConfig.c_objects
+compConfig.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/compConfig.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CFLAGS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -MD \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -I$(PRJ_DIR)/../.. \
+ -I$(PRJ_DIR)/../../.. \
+ -DCPU=PENTIUM2
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CFLAGS_AS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM2
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CPPFILT
+c++filtpentium --strip-underscores
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LDFLAGS
+-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LDPARTIAL
+ccpentium \
+ -B$(WIND_BASE)/host/$(WIND_HOST_TYPE)/lib/gcc-lib/ \
+ -nostdlib \
+ -r \
+ -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_RO_DEPEND_PATH
+$(WIND_BASE)/target/h/
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_TC
+::tc_PENTIUM2gnu.debug
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_DEFAULTFORCPU
+0
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_objects
+__DB_APPLICATION_NAME__.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/compConfig.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/compConfig.c_objects
+compConfig.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/compConfig.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CFLAGS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -O2 \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -MD \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -I$(PRJ_DIR)/../.. \
+ -I$(PRJ_DIR)/../../.. \
+ -DCPU=PENTIUM2
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CFLAGS_AS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -O2 \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM2
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CPPFILT
+c++filtpentium --strip-underscores
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LDFLAGS
+-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LDPARTIAL
+ccpentium \
+ -B$(WIND_BASE)/host/$(WIND_HOST_TYPE)/lib/gcc-lib/ \
+ -nostdlib \
+ -r \
+ -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_RELEASE
+1
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_RELEASE
+1
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_RO_DEPEND_PATH
+$(WIND_BASE)/target/h/
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_TC
+::tc_PENTIUM2gnu.release
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_DEFAULTFORCPU
+1
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_objects
+__DB_APPLICATION_NAME__.o
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/compConfig.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/compConfig.c_objects
+compConfig.o
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/compConfig.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CFLAGS
+-mcpu=pentium \
+ -march=pentium \
+ -ansi \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -MD \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -I$(PRJ_DIR)/../.. \
+ -I$(PRJ_DIR)/../../.. \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CFLAGS_AS
+-mcpu=pentium \
+ -march=pentium \
+ -ansi \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CPPFILT
+c++filtpentium --strip-underscores
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LDFLAGS
+-X
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LDPARTIAL
+ccpentium \
+ -B$(WIND_BASE)/host/$(WIND_HOST_TYPE)/lib/gcc-lib/ \
+ -nostdlib \
+ -r \
+ -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_RO_DEPEND_PATH
+$(WIND_BASE)/target/h/
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_TC
+::tc_PENTIUMgnu.debug
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUM2gnu.debug PENTIUM2gnu.release PENTIUMgnu.debug
+<END>
+
+<BEGIN> PROJECT_FILES
+$(PRJ_DIR)/../__DB_APPLICATION_NAME__.c \
+ $(PRJ_DIR)/compConfig.c
+<END>
+
+<BEGIN> WCC__CDF_PATH
+$(PRJ_DIR)
+<END>
+
+<BEGIN> WCC__CURRENT
+PENTIUM2gnu.debug
+<END>
+
+<BEGIN> WCC__LIST
+PENTIUM2gnu.debug
+<END>
+
+<BEGIN> WCC__MXR_LIBS
+lib$(CPU)$(TOOL)vx.a
+<END>
+
+<BEGIN> WCC__OBJS_PATH
+$(WIND_BASE)/target/lib/obj$CPU$TOOLvx
+<END>
+
diff --git a/bdb/dist/vx_3.1/wpj.1 b/bdb/dist/vx_3.1/wpj.1
new file mode 100644
index 00000000000..414b4e8fa35
--- /dev/null
+++ b/bdb/dist/vx_3.1/wpj.1
@@ -0,0 +1,22 @@
+Document file - DO NOT EDIT
+
+<BEGIN> CORE_INFO_TYPE
+::prj_component
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+AE1.0
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM2gnu.debug
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_CURRENT_TARGET
+default
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_DEFAULTFORCPU
+0
+<END>
+
diff --git a/bdb/dist/vx_3.1/wpj.2 b/bdb/dist/vx_3.1/wpj.2
new file mode 100644
index 00000000000..0294f763ef7
--- /dev/null
+++ b/bdb/dist/vx_3.1/wpj.2
@@ -0,0 +1,130 @@
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/compConfig.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/compConfig.c_objects
+compConfig.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_$(PRJ_DIR)/compConfig.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CFLAGS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -MD \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM2 \
+ -I$(PRJ_DIR)/.. \
+ -I$(PRJ_DIR)/../.. \
+ -DDEBUG \
+ -DDIAGNOSTIC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CFLAGS_AS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM2
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_CPPFILT
+c++filtpentium --strip-underscores
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LDFLAGS
+-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LDPARTIAL
+ccpentium \
+ -B$(WIND_BASE)/host/$(WIND_HOST_TYPE)/lib/gcc-lib/ \
+ -nostdlib \
+ -r \
+ -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_RO_DEPEND_PATH
+$(WIND_BASE)/target/h/
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.debug_TC
+::tc_PENTIUM2gnu.debug
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_DEFAULTFORCPU
+0
+<END>
+
diff --git a/bdb/dist/vx_3.1/wpj.3 b/bdb/dist/vx_3.1/wpj.3
new file mode 100644
index 00000000000..f06e6253923
--- /dev/null
+++ b/bdb/dist/vx_3.1/wpj.3
@@ -0,0 +1,128 @@
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/compConfig.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/compConfig.c_objects
+compConfig.o
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_FILE_$(PRJ_DIR)/compConfig.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CFLAGS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -O2 \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -MD \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM2 \
+ -I$(PRJ_DIR)/.. \
+ -I$(PRJ_DIR)/../..
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CFLAGS_AS
+-mcpu=pentiumpro \
+ -march=pentiumpro \
+ -ansi \
+ -O2 \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM2
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_CPPFILT
+c++filtpentium --strip-underscores
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LDFLAGS
+-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LDPARTIAL
+ccpentium \
+ -B$(WIND_BASE)/host/$(WIND_HOST_TYPE)/lib/gcc-lib/ \
+ -nostdlib \
+ -r \
+ -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_RELEASE
+1
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_RELEASE
+1
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_RO_DEPEND_PATH
+$(WIND_BASE)/target/h/
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu.release_TC
+::tc_PENTIUM2gnu.release
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_DEFAULTFORCPU
+1
+<END>
+
diff --git a/bdb/dist/vx_3.1/wpj.4 b/bdb/dist/vx_3.1/wpj.4
new file mode 100644
index 00000000000..84de6ebf359
--- /dev/null
+++ b/bdb/dist/vx_3.1/wpj.4
@@ -0,0 +1,135 @@
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/compConfig.c_infoTags
+toolMacro objects
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/compConfig.c_objects
+compConfig.o
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_FILE_$(PRJ_DIR)/compConfig.c_toolMacro
+CC
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CFLAGS
+-mcpu=pentium \
+ -march=pentium \
+ -ansi \
+ -DRW_MULTI_THREAD \
+ -D_REENTRANT \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -MD \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM \
+ -I$(PRJ_DIR)/.. \
+ -I$(PRJ_DIR)/../.. \
+ -DDEBUG \
+ -DDIAGNOSTIC
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CFLAGS_AS
+-mcpu=pentium \
+ -march=pentium \
+ -ansi \
+ -g \
+ -nostdlib \
+ -fno-builtin \
+ -fno-defer-pop \
+ -P \
+ -x \
+ assembler-with-cpp \
+ -Wall \
+ -I. \
+ -I$(WIND_BASE)/target/h \
+ -DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_CPPFILT
+c++filtpentium --strip-underscores
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LDFLAGS
+-X
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LDPARTIAL
+ccpentium \
+ -B$(WIND_BASE)/host/$(WIND_HOST_TYPE)/lib/gcc-lib/ \
+ -nostdlib \
+ -r \
+ -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_RELEASE
+0
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_RO_DEPEND_PATH
+$(WIND_BASE)/target/h/
+<END>
+
+<BEGIN> BUILD_PENTIUMgnu.debug_TC
+::tc_PENTIUMgnu.debug
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUMgnu.debug PENTIUM2gnu.debug PENTIUM2gnu.release
+<END>
+
+<BEGIN> COMPONENT_COM_TYPE
+
+<END>
+
+<BEGIN> PROJECT_FILES
diff --git a/bdb/dist/vx_3.1/wpj.5 b/bdb/dist/vx_3.1/wpj.5
new file mode 100644
index 00000000000..f4056e7e22a
--- /dev/null
+++ b/bdb/dist/vx_3.1/wpj.5
@@ -0,0 +1,22 @@
+<END>
+
+<BEGIN> WCC__CDF_PATH
+$(PRJ_DIR)
+<END>
+
+<BEGIN> WCC__CURRENT
+PENTIUMgnu.debug
+<END>
+
+<BEGIN> WCC__LIST
+PENTIUMgnu.debug
+<END>
+
+<BEGIN> WCC__MXR_LIBS
+lib$(CPU)$(TOOL)vx.a
+<END>
+
+<BEGIN> WCC__OBJS_PATH
+$(WIND_BASE)/target/lib/obj$CPU$TOOLvx
+<END>
+
diff --git a/bdb/dist/vx_buildcd b/bdb/dist/vx_buildcd
new file mode 100755
index 00000000000..a94d78db974
--- /dev/null
+++ b/bdb/dist/vx_buildcd
@@ -0,0 +1,119 @@
+#!/bin/sh
+# $Id: vx_buildcd,v 1.6 2001/11/05 21:05:58 sue Exp $
+#
+# Build the Setup SDK CD image on the VxWorks host machine.
+
+. ./RELEASE
+
+B=`pwd`
+B=$B/..
+D=$B/dist/vx_setup
+C=$D/db.CD
+Q=/export/home/sue/SetupSDK
+S=$Q/resource/mfg/setup
+W=sun4-solaris2
+
+symdoc=$D/docs/BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH
+symdb=$D/windlink/sleepycat/BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH
+rm -rf $D/docs $D/windlink
+mkdir $D/docs $D/windlink $D/windlink/sleepycat
+ln -s $B/docs $symdoc
+ln -s $B $symdb
+
+s=/tmp/__db_a
+t=/tmp/__db_b
+
+#
+# Remove the old CD directory if it is there.
+if test -d $C; then
+ echo "$C cannot exist."
+ echo "As root, execute 'rm -rf $C'"
+ echo "and then rerun the script"
+ exit 1
+fi
+
+#
+# Check for absolute pathnames in the project files.
+# That is bad, but Tornado insists on putting them in
+# whenever you add new files.
+#
+rm -f $t
+f=`find $B/build_vxworks -name \*.wpj -print`
+for i in $f; do
+ grep -l -- "$B" $i >> $t
+done
+if test -s $t; then
+ echo "The following files contain absolute pathnames."
+ echo "They must be fixed before building the CD image:"
+ cat $t
+ exit 1
+fi
+
+#
+# NOTE: We reuse the same sed script over several files.
+#
+cat <<ENDOFSEDTEXT > $s
+s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g
+s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/g
+s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/g
+s#@DB_SETUP_DIR@#$D#g
+ENDOFSEDTEXT
+
+f=$D/setup.pool
+(sed -f $s $D/vx_setup.in) > $t
+ (echo "Building $f" && rm -f $f && cp $t $f)
+
+f=$D/README.TXT
+(sed -f $s $D/README.in) > $t
+ (echo "Building $f" && rm -f $f && cp $t $f)
+
+f=$D/CONFIG.TCL
+(sed -f $s $D/CONFIG.in) > $t
+ (echo "Building $f" && rm -f $f && cp $t $f)
+
+f=$D/filelist.demo
+(sed -f $s $D/vx_demofile.in) > $t
+ (echo "Building $f" && rm -f $f && cp $t $f)
+
+# Copy the Sleepycat specific files into the SetupSDK area.
+(cd $D && cp README.TXT $S)
+(cd $D && cp LICENSE.TXT $S)
+(cd $D && cp CONFIG.TCL $S/RESOURCE/TCL)
+(cd $D && cp SETUP.BMP $S/RESOURCE/BITMAPS)
+
+#
+# NOTE: The contents of LIB must be on one, long, single line.
+# Even preserving it with a \ doesn't work for htmlBook.
+#
+f=../docs/LIB
+(echo "Building $f" && rm -f $f)
+cat <<ENDOFLIBTEXT >> $f
+{BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH} {Sleepycat Software Berkeley DB} {<b>BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH</b>} {<b><a href="./index.html">BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH</a></b>} {Sleepycat BerkeleyDB} {} {} {}
+ENDOFLIBTEXT
+
+#
+# Start generating the file list.
+f=$D/filelist.all
+
+#
+# Just put everything into the image. But we only want to find regular
+# files; we cannot have all the directories listed too.
+#
+# NOTE: This find is overly aggressive in getting files, particularly
+# for the 'windlink/sleepycat' files. We actually end up with 3 sets of the
+# documentation, the "real" ones in 'docs/BerkeleyDB*', the set found
+# via 'windlink/sleepycat/Berk*/docs' and the one found via our symlink in
+# 'windlink/sleepycat/Berk*/dist/vx_setup/docs/Berk*'.
+#
+# However, we waste a little disk space so that the expression below
+# is trivial and we don't have to maintain it as new files/directories
+# are added to DB.
+#
+(cd $D && find docs/BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH/ -follow -name \* -type f -print) > $t
+(cd $D && find windlink/sleepycat/BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH/ -follow -name docs -prune -o -type f -print) >> $t
+(echo "Building $f" && rm -f $f && cp $t $f)
+#
+# Finally build the CD image!
+#
+env PATH=$Q/$W/bin:$PATH QMS_BASE=$Q WIND_HOST_TYPE=$W \
+pool mfg -d $C -v -nokey BerkeleyDB.$DB_VERSION_MAJOR.$DB_VERSION_MINOR < $D/setup.pool
diff --git a/bdb/dist/vx_config.in b/bdb/dist/vx_config.in
new file mode 100644
index 00000000000..43fc8eb71f3
--- /dev/null
+++ b/bdb/dist/vx_config.in
@@ -0,0 +1,381 @@
+/* !!!
+ * The CONFIG_TEST option may be added using the Tornado project build.
+ * DO NOT modify it here.
+ */
+/* Define to 1 if you want to build a version for running the test suite. */
+/* #undef CONFIG_TEST */
+
+/* !!!
+ * The DEBUG option may be added using the Tornado project build.
+ * DO NOT modify it here.
+ */
+/* Define to 1 if you want a debugging version. */
+/* #undef DEBUG */
+
+/* Define to 1 if you want a version that logs read operations. */
+/* #undef DEBUG_ROP */
+
+/* Define to 1 if you want a version that logs write operations. */
+/* #undef DEBUG_WOP */
+
+/* !!!
+ * The DIAGNOSTIC option may be added using the Tornado project build.
+ * DO NOT modify it here.
+ */
+/* Define to 1 if you want a version with run-time diagnostic checking. */
+/* #undef DIAGNOSTIC */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if Berkeley DB release includes strong cryptography. */
+/* #undef HAVE_CRYPTO */
+
+/* Define to 1 if you have the `directio' function. */
+/* #undef HAVE_DIRECTIO */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines. */
+#define HAVE_EXIT_SUCCESS 1
+
+/* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */
+/* #undef HAVE_FCNTL_F_SETFD */
+
+/* Define to 1 if allocated filesystem blocks are not zeroed. */
+#define HAVE_FILESYSTEM_NOTZERO 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getopt' function. */
+/* #undef HAVE_GETOPT */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have the `getuid' function. */
+/* #undef HAVE_GETUID */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mlock' function. */
+/* #undef HAVE_MLOCK */
+
+/* Define to 1 if you have the `mmap' function. */
+/* #undef HAVE_MMAP */
+
+/* Define to 1 if you have the `munlock' function. */
+/* #undef HAVE_MUNLOCK */
+
+/* Define to 1 if you have the `munmap' function. */
+/* #undef HAVE_MUNMAP */
+
+/* Define to 1 to use the GCC compiler and 68K assembly language mutexes. */
+/* #undef HAVE_MUTEX_68K_GCC_ASSEMBLY */
+
+/* Define to 1 to use the AIX _check_lock mutexes. */
+/* #undef HAVE_MUTEX_AIX_CHECK_LOCK */
+
+/* Define to 1 to use the GCC compiler and Alpha assembly language mutexes. */
+/* #undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY */
+
+/* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */
+/* #undef HAVE_MUTEX_ARM_GCC_ASSEMBLY */
+
+/* Define to 1 to use the UNIX fcntl system call mutexes. */
+/* #undef HAVE_MUTEX_FCNTL */
+
+/* Define to 1 to use the GCC compiler and PaRisc assembly language mutexes.
+ */
+/* #undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY */
+
+/* Define to 1 to use the msem_XXX mutexes on HP-UX. */
+/* #undef HAVE_MUTEX_HPPA_MSEM_INIT */
+
+/* Define to 1 to use the GCC compiler and IA64 assembly language mutexes. */
+/* #undef HAVE_MUTEX_IA64_GCC_ASSEMBLY */
+
+/* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */
+/* #undef HAVE_MUTEX_MSEM_INIT */
+
+/* Define to 1 to use the GCC compiler and Apple PowerPC assembly language. */
+/* #undef HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY */
+
+/* Define to 1 to use the GCC compiler and generic PowerPC assembly language.
+ */
+/* #undef HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY */
+
+/* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */
+/* #undef HAVE_MUTEX_PTHREADS */
+
+/* Define to 1 to use Reliant UNIX initspin mutexes. */
+/* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
+
+/* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */
+/* #undef HAVE_MUTEX_S390_GCC_ASSEMBLY */
+
+/* Define to 1 to use the SCO compiler and x86 assembly language mutexes. */
+/* #undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY */
+
+/* Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes. */
+/* #undef HAVE_MUTEX_SEMA_INIT */
+
+/* Define to 1 to use the SGI XXX_lock mutexes. */
+/* #undef HAVE_MUTEX_SGI_INIT_LOCK */
+
+/* Define to 1 to use the Solaris _lock_XXX mutexes. */
+/* #undef HAVE_MUTEX_SOLARIS_LOCK_TRY */
+
+/* Define to 1 to use the Solaris lwp threads mutexes. */
+/* #undef HAVE_MUTEX_SOLARIS_LWP */
+
+/* Define to 1 to use the GCC compiler and Sparc assembly language mutexes. */
+/* #undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY */
+
+/* Define to 1 if mutexes hold system resources. */
+#define HAVE_MUTEX_SYSTEM_RESOURCES 1
+
+/* Define to 1 if fast mutexes are available. */
+#define HAVE_MUTEX_THREADS 1
+
+/* Define to 1 to configure mutexes intra-process only. */
+/* #undef HAVE_MUTEX_THREAD_ONLY */
+
+/* Define to 1 to use the UNIX International mutexes. */
+/* #undef HAVE_MUTEX_UI_THREADS */
+
+/* Define to 1 to use the UTS compiler and assembly language mutexes. */
+/* #undef HAVE_MUTEX_UTS_CC_ASSEMBLY */
+
+/* Define to 1 to use VMS mutexes. */
+/* #undef HAVE_MUTEX_VMS */
+
+/* Define to 1 to use VxWorks mutexes. */
+#define HAVE_MUTEX_VXWORKS 1
+
+/* Define to 1 to use Windows mutexes. */
+/* #undef HAVE_MUTEX_WIN32 */
+
+/* Define to 1 to use the GCC compiler and x86 assembly language mutexes. */
+/* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the O_DIRECT flag. */
+/* #undef HAVE_O_DIRECT */
+
+/* Define to 1 if you have the `pread' function. */
+/* #undef HAVE_PREAD */
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `pwrite' function. */
+/* #undef HAVE_PWRITE */
+
+/* Define to 1 if building on QNX. */
+/* #undef HAVE_QNX */
+
+/* Define to 1 if you have the `qsort' function. */
+#define HAVE_QSORT 1
+
+/* Define to 1 if you have the `raise' function. */
+#define HAVE_RAISE 1
+
+/* Define to 1 if building RPC client/server. */
+/* #undef HAVE_RPC */
+
+/* Define to 1 if you have the `sched_yield' function. */
+#define HAVE_SCHED_YIELD 1
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the `shmget' function. */
+/* #undef HAVE_SHMGET */
+
+/* Define to 1 if you have the `snprintf' function. */
+/* #undef HAVE_SNPRINTF */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the `strdup' function. */
+/* #undef HAVE_STRDUP */
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+
+/* Define to 1 if you have the `sysconf' function. */
+/* #undef HAVE_SYSCONF */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+/* #undef HAVE_SYS_STAT_H */
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+/* #undef HAVE_SYS_TYPES_H */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if unlink of file with open file descriptors will fail. */
+#define HAVE_UNLINK_WITH_OPEN_FAILURE 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+/* #undef HAVE_VSNPRINTF */
+
+/* Define to 1 if building VxWorks. */
+#define HAVE_VXWORKS 1
+
+/* Define to 1 if you have the `yield' function. */
+/* #undef HAVE_YIELD */
+
+/* Define to 1 if you have the `_fstati64' function. */
+/* #undef HAVE__FSTATI64 */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "support@sleepycat.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Berkeley DB"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Berkeley DB __EDIT_DB_VERSION__"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "db-__EDIT_DB_VERSION__"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "__EDIT_DB_VERSION__"
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Define to 1 to mask harmless unitialized memory read/writes. */
+/* #undef UMRW */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/*
+ * Exit success/failure macros.
+ */
+#ifndef HAVE_EXIT_SUCCESS
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+#endif
+
+/*
+ * Don't step on the namespace. Other libraries may have their own
+ * implementations of these functions, we don't want to use their
+ * implementations or force them to use ours based on the load order.
+ */
+#ifndef HAVE_GETCWD
+#define getcwd __db_Cgetcwd
+#endif
+#ifndef HAVE_GETOPT
+#define getopt __db_Cgetopt
+#define optarg __db_Coptarg
+#define opterr __db_Copterr
+#define optind __db_Coptind
+#define optopt __db_Coptopt
+#endif
+#ifndef HAVE_MEMCMP
+#define memcmp __db_Cmemcmp
+#endif
+#ifndef HAVE_MEMCPY
+#define memcpy __db_Cmemcpy
+#endif
+#ifndef HAVE_MEMMOVE
+#define memmove __db_Cmemmove
+#endif
+#ifndef HAVE_RAISE
+#define raise __db_Craise
+#endif
+#ifndef HAVE_SNPRINTF
+#define snprintf __db_Csnprintf
+#endif
+#ifndef HAVE_STRCASECMP
+#define strcasecmp __db_Cstrcasecmp
+#define strncasecmp __db_Cstrncasecmp
+#endif
+#ifndef HAVE_STRERROR
+#define strerror __db_Cstrerror
+#endif
+#ifndef HAVE_VSNPRINTF
+#define vsnprintf __db_Cvsnprintf
+#endif
+
+/*
+ * !!!
+ * The following is not part of the automatic configuration setup, but
+ * provides the information necessary to build Berkeley DB on VxWorks.
+ */
+#include "vxWorks.h"
diff --git a/bdb/dist/vx_setup/CONFIG.in b/bdb/dist/vx_setup/CONFIG.in
new file mode 100644
index 00000000000..6ccceee7034
--- /dev/null
+++ b/bdb/dist/vx_setup/CONFIG.in
@@ -0,0 +1,10 @@
+#
+# Install configuration file.
+#
+# Note: This file may be modified during the pool manufacturing process to
+# add additional configuration statements. This file is sourced by
+# INSTW32.TCL.
+#
+
+cdromDescSet "Berkeley DB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@"
+
diff --git a/bdb/dist/vx_setup/LICENSE.TXT b/bdb/dist/vx_setup/LICENSE.TXT
new file mode 100644
index 00000000000..7814c679cd7
--- /dev/null
+++ b/bdb/dist/vx_setup/LICENSE.TXT
@@ -0,0 +1,3 @@
+Copyright (c) 1996-2002
+ Sleepycat Software. All rights reserved.
+See the file LICENSE for redistribution information.
diff --git a/bdb/dist/vx_setup/MESSAGES.TCL b/bdb/dist/vx_setup/MESSAGES.TCL
new file mode 100644
index 00000000000..718a67fbc50
--- /dev/null
+++ b/bdb/dist/vx_setup/MESSAGES.TCL
@@ -0,0 +1,651 @@
+# MESSAGES.TCL - All setup strings.
+
+# modification history
+# --------------------
+# 03q,20apr99,bjl added release notes message for backward compatibility
+# page.
+# 03p,12apr99,wmd Add word about simulator in message about the drivers
+# object product.
+# 03o,03mar99,tcy Adjust setup directory size based on platform (fix for
+# SPR 25228)
+# 03n,24feb99,tcy modified DLL update messages
+# 03m,22feb99,tcy modified to align messages
+# 03l,17feb99,tcy modified message in the finish page for program group
+# installation
+# 03k,11feb99,tcy added messages for backward compatibility page
+# 03j,25jan99,tcy added messages from INSTW32.TCL
+# 03i,25jan99,wmd Reword the message for 5010_DRIVERS_INFO.
+# 03h,09dec98,bjl added messages about manufacturers updating patches.
+# 03g,01dec98,wmd Fix typos.
+# 03f,23nov98,tcy warn user to disable virus protection on Welcome screen
+# 03e,19nov98,wmd fixed minor nits in wording.
+# 03d,19nov98,bjl added web site locations for patchinfo.
+# 03c,18nov98,bjl added formatted patch messages for patchinfo file.
+# 03b,12nov98,tcy added message for not saving installation key
+# 03a,10nov98,tcy added warning message for space in destination directory
+# removed message for checking temporary disk space
+# 02z,27oct98,bjl added recommended patch messages, modified required msg.
+# 02y,26oct98,tcy added message for checking temporary disk space
+# 02x,22oct98,wmd fix messages for clarity.
+# 02w,21oct98,wmd fix message for drv/obj.
+# 02v,20oct98,tcy added message for updating system and changed dcom message
+# 02u,20oct98,bjl added tornado registry name entry message.
+# 02t,19oct98,bjl added tornado registry description message.
+# 02s,16oct98,wmd add new message for driver product warning.
+# 02r,16oct98,wmd fixed README.TXT description.
+# 02q,12oct98,tcy removed extraneous "the" from messages
+# 02p,06oct98,tcy added CD description to Welcome page
+# 02o,29sep98,bjl added required patches message 5000_PATCHES_TEXT.
+# 02n,29sep98,wmd add text for readme page
+# 02m,29sep98,tcy refined DLL registration page text
+# 02l,29sep98,tcy changed message for DCOM
+# 02k,26sep98,tcy added messages for DLL and DCOM pages
+# 02j,24sep98,tcy removed "following" from 1080_WARN_4 message.
+# 02i,17sep98,tcy added comment on size of SETUP files to 1140_COMP_SELECT.
+# 02h,17sep98,wmd reword message 1080_WARN_4.
+# 02g,14sep98,tcy changed 1210_FINISH and 1550_USAGE messages
+# 02f,08sep98,tcy warn user library update may take several minutes
+# 02e,01sep98,wmd reword message for installing over tree.
+# added new messages for license agreement pages.
+# 02d,20aug98,wmd added message for license agreeement.
+# 02c,18aug98,tcy added message for zip-file dialog box
+# 02d,04aug98,wmd added newer/older duplicate file warnings.
+# 02c,24jul98,tcy added system check messages
+# 02b,16jul98,wmd add new messages for T-2.
+# 02a,22jul98,tcy moved license messages to LICW32.TCL;
+# removed portMapper messages
+# 01n,09feb98,pdn updated string 1080_WARN_4
+# 01m,08apr97,pdn added new string for remote icon installing
+# fixed spr#8334
+# 01l,08mar97,tcy fixed language in string id 3340
+# 01k,07mar97,tcy added string id 3340
+# 01j,10feb97,pdn added more license messages.
+# 01i,09feb97,pdn implemented variable argument list for strTableGet(),
+# clean up.
+# 01h,17jan97,jmo fixed language in strings
+# 01g,12dec96,tcy merged in TEXT-only strings
+# 01f,12dec96,pdn added 1080_WARN_4 string warning that CD-ROM
+# revision is older than expected.
+# 01e,27nov96,sj added string for warning against installing in
+# the root of windows drive.
+# 01d,18nov96,tcy added strings for text-based installation script
+# 01c,14nov96,pdn substituted function for some global variables
+# 01b,14nov96,sj added strings from Windows installation script
+# 01a,11nov96,pdn written
+
+proc strTableGet {strId args} {
+ global strTable
+ global setupVals
+ global current_file
+
+ if [regexp {^format.*$} $strTable($strId) junk] {
+ return [eval $strTable($strId)]
+ } {
+ return $strTable($strId)
+ }
+}
+
+set strTable(1000_WELCOME_CD) \
+ "format %s \"[cdNameGet description]\""
+
+set strTable(1000_WELCOME1) \
+ "format %s \"Welcome to the SETUP program. This program will\
+ install \[cdromDescGet\] on your computer.\""
+
+set strTable(1010_WELCOME2) \
+ "It is strongly recommended that you exit all programs and disable virus\
+ protection before running this SETUP program."
+
+set strTable(1020_WELCOME3) \
+ "At any time, you can quit the SETUP program by clicking the <Cancel>\
+ button. You also can go back to previous dialog boxes by clicking the\
+ <Back> button. To accept the current settings for a dialog box and go on\
+ with the installation process, click the <Next> button."
+
+set strTable(3020_WELCOME3) \
+ "format %s \"At any prompt, you can cancel installation \[cdromDescGet\]\
+ by typing \'exit\'. You can also go to the previous question\
+ by typing \'-\'. To accept current settings and go on with\
+ the installation process, press <Return>.\""
+
+set strTable(1030_WELCOME4) \
+ "WARNING: This program is protected by copyright law and international\
+ treaties."
+
+set strTable(1040_WELCOME5) \
+ "Unauthorized reproduction or distribution of this program, or any portion\
+ of it, may result in severe civil and criminal penalties, and will be\
+ prosecuted to the maximum extent possible under law."
+
+set strTable(1050_ROOT_WARN) \
+ "format %s \"Installing \[cdromDescGet\] as \[setupId effective user\] is not\
+ recommended. We suggest that you logoff and logon as a normal\
+ user before running this program.\
+ \n\nClick Next to continue with SETUP anyway.\""
+
+set strTable(3050_ROOT_WARN) \
+ "format %s \"Installing \[cdromDescGet\] as \[setupId effective user\]\
+ is not recommended. We suggest that you logoff and \
+ logon as a normal user before running this program.\
+ \n\nPress <Return> to continue with SETUP anyway.\""
+
+set strTable(1051_ROOT_WARN) \
+ "format %s \"Installing \[cdromDescGet\] without System Administrator\
+ privileges is not recommended. Under your present privileges,\
+ SETUP will not offer certain installation options, such as \
+ the installation of some services, etc. Also, the software\
+ will be installed as a personal copy and will not be visible\
+ to other users on this machine.\
+ \n\nTo install \[cdromDescGet\] with access to all its\
+ installation features and options, we suggest that you exit\
+ the installation now and rerun it later with System\
+ Administrator\'s privileges.\n\nClick <Next> to continue with\
+ SETUP anyway.\""
+
+set strTable(1060_REGISTRATION) \
+ "Below, type your name, the name of your company."
+
+set strTable(1070_WARN_1) \
+ "The installation key you entered is invalid. Please enter a valid\
+ installation key."
+
+set strTable(1071_WARN_1) \
+ "Please enter the requested information."
+
+set strTable(1080_WARN_2) \
+ "You entered a key that was not created for this CD-ROM. Please verify\
+ that you are using the appropriate key. If this problem persists, contact\
+ Wind River Systems Sales department for help."
+
+set strTable(1080_WARN_3) \
+ "The installation key you entered is meant for other vendor's CD-ROM.\
+ Please contact the vendor who issued the CD-ROM for a proper key."
+
+set strTable(1085_WARN_4) \
+ "This CD-ROM does not require an installation key. Click the \"Next\"\
+ button to continue the installation."
+
+set strTable(1090_WARN_3) \
+ "format %s \"Can\'t initiate SETUP: \[lindex \$args 0\]. Please correct\
+ the problem then run SETUP again.\""
+
+set strTable(1095_WARN_NO_TCPIP) \
+ "SETUP has detected that your system does not have TCP-IP installed.\
+ To correct the problem, please contact your administrator and then\
+ run SETUP again.\nAborting setup."
+
+set strTable(1097_WARN_NO_LONGFILENAME_SUP) \
+ "SETUP has detected that your system does not have long filename\
+ support. To correct the problem, please contact your administrator\
+ and then run SETUP again.\nAborting setup."
+
+set strTable(1105_FULL_INSTALL) \
+ "Installs the Tornado products, tools, compilers, and other optional\
+ components that you may have purchased."
+
+set strTable(1107_PROGRAM_GROUP) \
+"Installs only the Tornado program group and tools icons for access to\
+ Tornado tools installed on a remote server."
+
+set strTable(1100_DEST_DIR) \
+ "format %s \"Please type the name of the directory where you want SETUP to\
+ install \[cdromDescGet\].\
+ \n\nClick the <Browse> button to choose the directory\
+ interactively.\""
+
+set strTable(1100_REMOTE_DIR) \
+ "format %s \"Please type the name of the directory where Tornado has\
+ already been installed.\
+ \n\nClick the <Browse> button to choose the directory\
+ interactively.\""
+
+set strTable(3100_DEST_DIR) \
+ "format %s \"Please type the name of the directory where you want SETUP\
+ to install \[cdromDescGet\].\""
+
+set strTable(1110_DEST_DIR_WARN) \
+ "The installation directory you entered does not exist.\
+ \nDo you want to create it now?"
+
+set strTable(3110_DEST_DIR_WARN) \
+ "The installation directory you entered does not exist."
+
+set strTable(3115_DEST_DIR_QUESTION) \
+ "Do you want to create it now? \[y\]"
+
+set strTable(1111_DEST_DIR_WARN) \
+ "format %s \"Installing \[cdromDescGet\] in the root directory is not\
+ recommended.\nClick <Yes> to select another directory.\""
+
+set strTable(1120_DEST_DIR_WARN2) \
+ "format %s \"Creating \[destDirGet\] failed: file exists.\""
+
+set strTable(1121_DEST_DIR_WARN2) \
+ "format %s \"Installing in \[destDirGet\] is not recommended.\
+ \nDo you want to change the installation directory?\""
+
+set strTable(1122_DEST_DIR_WARN2) \
+ "format %s \"Unable to create \[destDirGet\].\""
+
+set strTable(1130_DEST_DIR_WARN3) \
+ "You do not have permission to write files into the installation directory\
+ you entered.\
+ \n\nPlease choose a writable directory."
+
+set strTable(1135_DEST_DIR_WARN4) \
+ "format %s \"The installation directory you entered contains white\
+ space(s). Please select another directory.\""
+
+set strTable(1137_DUP_PRODUCT_WARN) \
+ "format %s \"Reinstalling products may potentially destroy any\
+ modifications you may have made to previously installed files.\
+ Do you wish to continue with the installation or go back to the\
+ '\[strTableGet 1450_TITLE_OPTION\]' page to reconsider your choices?\""
+
+set strTable(3155_COMP_SELECT_QUESTION) \
+ "Do you want to go back and specify a directory on a bigger partition?\
+ \[y\]"
+
+set strTable(1140_COMP_SELECT) \
+ "format %s \"In the option list below, please check all items you wish\
+ to install. SETUP files will be copied to your selected directory and\
+ take up \[setupSizeGet\] MB of disk space.\n\""
+
+set strTable(3140_COMP_SELECT) \
+ "In the option list below, select the item(s) you want to install."
+
+set strTable(3145_COMP_SELECT_CHANGE) \
+ "Press <Return> to accept the setting. To change the setting, enter a\
+ list of item numbers separated by spaces."
+
+set strTable(3145_COMP_SELECT_CHANGE_INVALID) \
+ "The item number(s) you entered is not valid."
+
+set strTable(1150_COMP_SELECT_WARN) \
+ "There is not enough disk space to install the selected component(s).\
+ \n\nDo you want to go back and specify a directory on a bigger disk or\
+ partition?"
+
+set strTable(3150_COMP_SELECT_WARN) \
+ "There is not enough space to install the selected component(s)."
+
+set strTable(1151_COMP_SELECT_WARN) \
+ "At least one component must be selected to continue installation."
+
+set strTable(1160_PERMISSION) \
+ "SETUP is about to install the component(s) you have requested.\
+ \n\nThe selected button(s) below indicate the file permissions which\
+ will be set during the installation process.\
+ \n\nPlease adjust these to suit your site requirements."
+
+set strTable(3160_PERMISSION) \
+ "SETUP is about to install the component(s) you have requested."
+
+set strTable(3162_PERMISSION) \
+ "The list below indicates the file permissions which will be set during\
+ the installation process. Please adjust these to suit your site\
+ requirements."
+
+set strTable(3165_PERMISSION_QUESTION) \
+ "Press <Return> to accept the setting. To change the setting, enter a\
+ list of item numbers separated by spaces."
+
+set strTable(1161_FOLDER_SELECT) \
+ "SETUP will add program icons to the Program Folder listed below. You may\
+ type a new folder name, or select one from the existing Folders list."
+
+set strTable(1162_FOLDER_SELECT) \
+ "Please enter a valid folder name."
+
+set strTable(1170_FILE_COPY) \
+ "format %s \"SETUP is copying the selected component(s) to the directory\
+ \[destDirGet\].\""
+
+set strTable(1171_FILE_COPY) \
+ "format %s \"SETUP cannot read \[setupFileNameGet 0\] from the CD-ROM.\
+ Please ensure that the CD-ROM is properly mounted.\""
+
+set strTable(1180_LIB_UPDATE) \
+ "SETUP is updating the VxWorks libraries. We recommend that you let\
+ SETUP finish this step, or the libraries will be in an inconsistent\
+ state. Please be patient as the process may take several minutes. \
+ If you want to quit the SETUP program, click <Cancel> and run\
+ the SETUP program again at a later time."
+
+set strTable(3180_LIB_UPDATE) \
+ "SETUP is updating the VxWorks libraries."
+
+set strTable(1190_REGISTRY_HOST) \
+ "The Tornado Registry is a daemon that keeps track of all available\
+ targets by name. Only one registry is required on your network, \
+ and it can run on any networked host.\
+ \n\nPlease enter the name of the host where the Tornado Registry will\
+ be running."
+
+set strTable(1191_REGISTRY_DESC) \
+ "The Tornado Registry is a daemon that keeps track of all available\
+ targets by name. Only one registry is required on your network, \
+ and it can run on any networked host."
+
+set strTable(1192_REGISTRY_NAME) \
+ "Please enter the name of the host where the Tornado Registry will\
+ be running."
+
+set strTable(1200_FINISH_WARN) \
+ "format %s \"However, there were \[errorCountGet\] error(s) which occured\
+ during the process. Please review the log file\
+ \[destDirDispGet\]/setup.log for more information.\""
+
+set strTable(1210_FINISH) \
+ "format %s \"SETUP has completed installing the selected product(s).\""
+
+set strTable(1212_FINISH) \
+ "SETUP has completed installing the program folders and icons."
+
+set strTable(1213_FINISH) \
+ "Terminating SETUP program."
+
+set strTable(1360_QUIT_CALLBACK) \
+ "format %s \"SETUP is not complete. If you quit the SETUP program now,\
+ \[cdromDescGet\] will not be installed.\n\nYou may run\
+ the SETUP program at a later time to complete the\
+ installation.\
+ \n\nTo continue installing the program, click <Resume>. \
+ To quit the SETUP program, click <Exit SETUP>.\""
+
+set strTable(3360_QUIT_CALLBACK) \
+ "format %s \"SETUP is not complete. If you quit the SETUP program now,\
+ \[cdromDescGet\] will not be installed.\n\nYou may run the\
+ SETUP program at a later time to complete the installation.\
+ \n\nTo continue installing the program, Press <Return>. \
+ To quit the SETUP program, type \'exit\'.\""
+
+set strTable(1370_FILE_ACCESS_ERROR) \
+ "format %s \"SETUP cannot create/update file \[lindex \$args 0\]:\
+ \[lindex \$args 1\]\""
+
+set strTable(1380_DEFLATE_ERROR) \
+ "format %s \"SETUP isn\'t able to deflate \[setupFileNameGet 0\]\
+ \n\nPlease select one of the following options\
+ to continue with the SETUP process.\""
+
+set strTable(1390_MEMORY_LOW) \
+ "The system is running out of memory. To continue, close applications\
+ or increase the system swap space."
+
+set strTable(1400_DISK_FULL) \
+ "No disk space left. To continue, free up some disk space."
+
+set strTable(1550_USAGE) \
+ "Usage: SETUP /I\[con\]\]\t\n\
+ /I : Add standard Tornado icons \n\
+ from a remote installation"
+
+set strTable(1410_TITLE_WELCOME) "Welcome"
+set strTable(1420_TITLE_WARNING) "Warning"
+set strTable(1430_TITLE_REGISTRATION) "User Registration"
+set strTable(1440_TITLE_DESTDIR) "Select Directory"
+set strTable(1450_TITLE_OPTION) "Select Products"
+set strTable(1460_TITLE_PERMISSION) "Permission"
+set strTable(1470_TITLE_FILECOPY) "Copying Files"
+set strTable(1480_TITLE_LIBUPDATE) "Update Libraries"
+set strTable(1490_TITLE_REGISTRY_HOST) "Tornado Registry"
+set strTable(1495_TITLE_BACKWARD_COMPATIBILITY) "Backward Compatibility"
+set strTable(1500_TITLE_FINISH) "Finish"
+set strTable(1560_TITLE_FOLDER) "Select Folder"
+set strTable(1563_TITLE_DLL_REG) "Software Registration"
+set strTable(1567_TITLE_DCOM) "DCOM Installation"
+
+set strTable(1570_OPTION_SELECT) \
+ "Choose one of the options listed below, then click the\
+ <Next> button to continue the installation."
+
+set strTable(1576_OPTION_MANUAL) \
+ "Install Tornado Registry manually"
+
+set strTable(1577_OPTION_STARTUP) \
+ "Install Tornado Registry locally in the Startup Group"
+
+set strTable(1578_OPTION_SERVICE) \
+ "Install Tornado Registry locally as a Service"
+
+set strTable(1579_OPTION_REMOTE) \
+ "Configure to use a remote Tornado Registry"
+
+set strTable(1580_OPTION_DESC) \
+ "If you plan on running Tornado in a non-networked environment, we\
+ recommend that you install the registry in your Startup Group or as an\
+ NT Service. For more information, consult your Tornado User\'s Guide."
+
+set strTable(1581_OPTION_DESC) \
+ "If you plan on running Tornado in a non-networked environment, we\
+ recommend that you install the registry in your Startup Group. For more\
+ information, consult your Tornado User\'s Guide."
+
+set strTable(3000_RETURN_QUESTION) \
+ "Press <Return> to continue"
+
+set strTable(3055_EXIT_QUESTION) \
+ "Type \'exit\' to quit the program or press <Return> to continue"
+
+set strTable(3370_BACK_CALLBACK) \
+ "Cannot go back further."
+
+set strTable(1080_WARN_4) \
+ "The installation key you entered attempted to unlock one or more \
+ products that may have been removed from our product line. \
+ Please compare the unlocked product list on the\
+ \"[strTableGet 1450_TITLE_OPTION]\" screen with your purchased order\
+ list, and contact us if you discover any differences."
+
+set strTable(4000_BASE_INSTALL_WARN) \
+ "format %s \"Warning! Re-installing Tornado over an existing \
+ tree will overwrite any installed patches. \
+ If you proceed with the installation, please \
+ re-install patches if any.\""
+
+set strTable(4000_BASE_INSTALL_WARN_1) \
+ "Select <Install> to overwrite existing Tornado installation,\
+ or choose <Select Path> to enable you to back up to the \'Select\
+ Directory\' page to enter an alternate path."
+
+set strTable(4010_FILE_EXISTS_OLDER_WARN) \
+ "format %s \"The file \'\$current_file\' exists in your destination\
+ directory path \'\[destDirGet\]\' and is older. You can\
+ set the policy for handling duplicate files by\
+ selecting one of the following buttons. All files to be\
+ overwritten will be backed up.\""
+
+set strTable(4010_FILE_EXISTS_NEWER_WARN) \
+ "format %s \"The file \'\$current_file\' exists in your destination\
+ directory path \'\[destDirGet\]\' and is newer. You can\
+ set the policy for handling duplicate files by\
+ selecting one of the following buttons. All files to be\
+ overwritten will be backed up.\""
+
+set strTable(4010_FILE_EXISTS_WARN_1) \
+ "Overwrite the existing file."
+
+set strTable(4010_FILE_EXISTS_WARN_2) \
+ "Do not overwrite the existing file."
+
+set strTable(4010_FILE_EXISTS_WARN_3) \
+ "Overwrite ALL files, do not show this dialog again."
+
+set strTable(4020_ANALYZING_BANNER) \
+ "Analyzing installation files, please wait..."
+
+set strTable(4030_NO_ZIP_FILE) \
+ "format %s \"SETUP cannot find the ZIP files for installing\
+ \[cdromDescGet\] in the default directory.\n\n\
+ Please type the name of the WIND\
+ directory containing the ZIP files.\n\nClick the\
+ <Browse> button to choose the directory interactively.\""
+
+set strTable(4040_LIC_TEXT) \
+ "Attention: By clicking on the \"I accept\" button or by\
+ Installing the software you are consenting to be bound by\
+ the terms of this agreement (this \"Agreement\"). If you do\
+ not agree to all of the terms, click the \"I don't Accept\" button\
+ and do not install this software. A copy of this Agreement can be viewed\
+ in the Setup directory under the destination path that you have\
+ designated after the installation is completed."
+
+set strTable(4050_PROJECT_TEXT) \
+ "Please enter your project name, and the number of licensed\
+ users on the project in the spaces below."
+
+set strTable(4060_LICENSE_TEXT) \
+ "By clicking on the \"I accept\" button \
+ you are consenting to be bound by the terms of this agreement.\
+ If you do not agree to all of the terms, click the \"Cancel\"\
+ button and do not install this software."
+
+set strTable(4070_DLL_TEXT) \
+ "SETUP is registering software on your machine. This will take a few\
+ minutes."
+
+set strTable(4080_DCOM_TEXT) \
+ "Setup has detected that your COM/DCOM DLLs must\
+ be updated for the correct operation of Tornado 2.0.\
+ \n\n\
+ Setup will now ask you to run DCOM95 to update your\
+ DLLs.\
+ \n\n\
+ You will have to reboot your system after DLL files have been\
+ installed. Please rerun SETUP to continue with installation\
+ after your system has rebooted.\
+ \n\n\
+ Note: The DCOM95 installation programs update your\
+ system DLLs. You should save all open documents and close all\
+ programs before proceeding.\
+ \n\nWould you like to install \"DCOM95\" now?"
+
+set strTable(4082_DCOM95_AND_COMCTL_TEXT) \
+ "Setup has detected that your COM/DCOM and Common Control DLLs must\
+ be updated for the correct operation of Tornado 2.0.\
+ \n\n\
+ Setup will now ask you to run DCOM95 and 401comupd.exe to update your\
+ DLLs.\
+ \n\n\
+ You must reboot your system after DLL files have been\
+ installed. After rebooting, please rerun SETUP to continue with\
+ installation.\
+ \n\n\
+ Note: 401comupd.exe and DCOM95 installation programs update your\
+ system DLLs. You should save all open documents and close all\
+ programs before proceeding\
+ \n\nWould you like to install \"401comupd.exe\" and \"DCOM95\" now?"
+
+set strTable(4085_COMCTL_UPDATE_TEXT) \
+ "Setup has detected that your Common Control DLLs must\
+ be updated for the correct operation of Tornado 2.0.\
+ \n\n\
+ Setup will now ask you to run DCOM95 and 401comupd.exe to update your\
+ DLLs.\
+ \n\n\
+ You will have to reboot your system after DLL files have been\
+ installed. Please rerun SETUP to continue with installation\
+ after your system has rebooted.\
+ \n\n\
+ Note: The 401comupd.exe installation program updates your system DLLs. You\
+ should save all open documents and close all programs before installing\
+ 401comupd.exe.\
+ \n\nWould you like to install \"401comupd.exe\" now?"
+
+set strTable(4090_README_TEXT) \
+ "Please read the README file contents that are displayed below.\
+ It contains important information that will enable you to install\
+ and successfully run the BerkeleyDB product. For your convenience\
+ this file is copied to your installation directory path."
+
+set strTable(5000_PATCHES_REQUIRED_TEXT) \
+ "SETUP has detected that required operating system patches\
+ have not been installed on this machine. These patches are\
+ necessary for the correct operation of SETUP and Tornado. Please refer\
+ to the Tornado Release Notes for details.\n\n\
+ The following operating system patches must be installed before\
+ you can continue with installation:\n\n"
+
+set strTable(5001_PATCHES_RECOMMENDED_TEXT) \
+ "\n\nSETUP has also detected that recommended operating system patches\
+ have not been installed. It is recommended that these patches are\
+ installed before starting Tornado to ensure correct operation.\n\n\
+ The following operating system patches are recommended to be installed:\n\n"
+
+set strTable(5002_PATCHES_RECOMMENDED_TEXT) \
+ "SETUP has detected that some operating system patches have not been\
+ installed on this machine. It is recommended that these\
+ patches are installed before starting Tornado to ensure correct\
+ operation. Please refer to the Tornado Release Notes\
+ for details.\n\n\
+ The following operating system patches are recommended to be installed:\n\n"
+
+set strTable(5003_PATCHES_REQUIRED_FORMATTED_TEXT) \
+ "\n SETUP has detected that required operating system patches\n\
+ have not been installed on this machine. These patches are\n\
+ necessary for the correct operation of SETUP and Tornado. Please refer\n\
+ to the Tornado Release Notes for details.\n\n\
+ The following operating system patches must be installed before\n\
+ you can continue with installation:\n\n"
+
+set strTable(5004_PATCHES_RECOMMENDED_FORMATTED_TEXT) \
+ "\n\n SETUP has also detected that recommended operating system patches\n\
+ have not been installed. It is recommended that these patches are\n\
+ installed before starting Tornado to ensure correct operation.\n\n\
+ The following operating system patches are recommended to be installed:\n\n"
+
+set strTable(5005_PATCHES_RECOMMENDED_FORMATTED_TEXT) \
+ "\n SETUP has detected that some operating system patches have not been\n\
+ installed on this machine. It is recommended that these\n\
+ patches are installed before starting Tornado to ensure correct\n\
+ operation. Please refer to the Tornado Release Notes\n\
+ for details.\n\n\
+ The following operating system patches are recommended to be installed:\n\n"
+
+set strTable(5006_PATCHES_SUN_LOCATION) \
+ "\nPatches for Sun machines are available at http://sunsolve.sun.com.\n"
+
+set strTable(5007_PATCHES_HP_LOCATION) \
+ "\nPatches for HP machines are available at:\n\
+ http://us-support.external.hp.com (US, Canada, Asia-Pacific, and\
+ Latin-America)\n\
+ http://europe-support.external.hp.com (Europe)\n"
+
+set strTable(5008_PATCHES_UPDATE) \
+ "\nNote: System vendors very frequently update and replace patches.\
+ If a specific patch is no longer available, please use the\
+ replacement patch suggested by the system vendor.\n"
+
+set strTable(5009_PATCHES_UPDATE_FORMATTED) \
+ "\n Note: System vendors very frequently update and replace patches.\n\
+ If a specific patch is no longer available, please use the\n\
+ replacement patch suggested by the system vendor.\n"
+
+set strTable(5010_DRIVERS_INFO) \
+ "The installation of the Driver component is required because\n\
+ you have selected the basic Tornado product for installation.\n\n\
+ If you wish to uncheck this item you must uncheck either the\n\
+ basic Tornado and/or Tornado Simulator product(s) or go to the\n\
+ 'Details' button for Tornado and uncheck both the Simulator and\n\
+ the Tornado Object parts."
+
+set strTable(5020_DO_NOT_SAVE_KEY_FOR_FAE) \
+ "The installation key you are about to enter will NOT\
+ be saved in the system registry.\nIs this what you want?"
+
+set strTable(5030_BACKWARD_COMPATIBILITY) \
+ "While the portmapper is not needed for Tornado 2.0, it is\
+ included in this release for development environments in\
+ which both Tornado 2.0 and Tornado 1.0.1 are in use.\
+ \n\nWould you like to use your Tornado 1.0.x tools with Tornado 2.0?"
+
+set strTable(5040_BACKWARD_COMPATIBILITY) \
+ "Note:\
+ \n\nIf you have selected to install the Tornado Registry as\
+ a service, there is no way to retain backward compatibility\
+ with Tornado 1.0.x."
+
+set strTable(5050_BACKWARD_COMPATIBILITY) \
+ "For more information on backward compatibility,\
+ please consult the Tornado 2.0 Release Notes."
diff --git a/bdb/dist/vx_setup/README.in b/bdb/dist/vx_setup/README.in
new file mode 100644
index 00000000000..f96948c37ba
--- /dev/null
+++ b/bdb/dist/vx_setup/README.in
@@ -0,0 +1,7 @@
+README.TXT: Sleepycat Software Berkeley DB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@ Release v@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+
+Information on known problems, changes introduced with the
+current revision of the CD-ROM, and other product bulletins
+can be obtained from the Sleepycat Software web site:
+
+ http://www.sleepycat.com/
diff --git a/bdb/dist/vx_setup/SETUP.BMP b/bdb/dist/vx_setup/SETUP.BMP
new file mode 100644
index 00000000000..2918480b8c2
--- /dev/null
+++ b/bdb/dist/vx_setup/SETUP.BMP
Binary files differ
diff --git a/bdb/dist/vx_setup/vx_allfile.in b/bdb/dist/vx_setup/vx_allfile.in
new file mode 100644
index 00000000000..61a1b8ee805
--- /dev/null
+++ b/bdb/dist/vx_setup/vx_allfile.in
@@ -0,0 +1,5 @@
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB.wpj
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB.wsp
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/db.h
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/db_config.h
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/db_int.h
diff --git a/bdb/dist/vx_setup/vx_demofile.in b/bdb/dist/vx_setup/vx_demofile.in
new file mode 100644
index 00000000000..42a698ea367
--- /dev/null
+++ b/bdb/dist/vx_setup/vx_demofile.in
@@ -0,0 +1,3 @@
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/dbdemo.wpj
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/README
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/dbdemo.c
diff --git a/bdb/dist/vx_setup/vx_setup.in b/bdb/dist/vx_setup/vx_setup.in
new file mode 100644
index 00000000000..7bc3f510cfa
--- /dev/null
+++ b/bdb/dist/vx_setup/vx_setup.in
@@ -0,0 +1,13 @@
+Sleepycat Software BerkeleyDB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+db@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@ demo-db@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+@DB_SETUP_DIR@
+Sleepycat Software BerkeleyDB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+db@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+@DB_SETUP_DIR@/filelist.all
+BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@-Demo
+@DB_SETUP_DIR@
+BerkeleyDB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@ Demo program
+demo-db@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
+@DB_SETUP_DIR@/filelist.demo
+Sleepycat Software BerkeleyDB @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@
diff --git a/bdb/dist/win_config.in b/bdb/dist/win_config.in
new file mode 100644
index 00000000000..09acab28806
--- /dev/null
+++ b/bdb/dist/win_config.in
@@ -0,0 +1,439 @@
+/* Define to 1 if you want to build a version for running the test suite. */
+/* #undef CONFIG_TEST */
+
+/* Define to 1 if you want a debugging version. */
+/* #undef DEBUG */
+#if defined(_DEBUG)
+#if !defined(DEBUG)
+#define DEBUG 1
+#endif
+#endif
+
+/* Define to 1 if you want a version that logs read operations. */
+/* #undef DEBUG_ROP */
+
+/* Define to 1 if you want a version that logs write operations. */
+/* #undef DEBUG_WOP */
+
+/* Define to 1 if you want a version with run-time diagnostic checking. */
+/* #undef DIAGNOSTIC */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define to 1 if Berkeley DB release includes strong cryptography. */
+/* #undef HAVE_CRYPTO */
+
+/* Define to 1 if you have the `directio' function. */
+/* #undef HAVE_DIRECTIO */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_DIRENT_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines. */
+#define HAVE_EXIT_SUCCESS 1
+
+/* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */
+/* #undef HAVE_FCNTL_F_SETFD */
+
+/* Define to 1 if allocated filesystem blocks are not zeroed. */
+#define HAVE_FILESYSTEM_NOTZERO 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getopt' function. */
+/* #undef HAVE_GETOPT */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have the `getuid' function. */
+/* #undef HAVE_GETUID */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mlock' function. */
+/* #undef HAVE_MLOCK */
+
+/* Define to 1 if you have the `mmap' function. */
+/* #undef HAVE_MMAP */
+
+/* Define to 1 if you have the `munlock' function. */
+/* #undef HAVE_MUNLOCK */
+
+/* Define to 1 if you have the `munmap' function. */
+/* #undef HAVE_MUNMAP */
+
+/* Define to 1 to use the GCC compiler and 68K assembly language mutexes. */
+/* #undef HAVE_MUTEX_68K_GCC_ASSEMBLY */
+
+/* Define to 1 to use the AIX _check_lock mutexes. */
+/* #undef HAVE_MUTEX_AIX_CHECK_LOCK */
+
+/* Define to 1 to use the GCC compiler and Alpha assembly language mutexes. */
+/* #undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY */
+
+/* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */
+/* #undef HAVE_MUTEX_ARM_GCC_ASSEMBLY */
+
+/* Define to 1 to use the UNIX fcntl system call mutexes. */
+/* #undef HAVE_MUTEX_FCNTL */
+
+/* Define to 1 to use the GCC compiler and PaRisc assembly language mutexes.
+ */
+/* #undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY */
+
+/* Define to 1 to use the msem_XXX mutexes on HP-UX. */
+/* #undef HAVE_MUTEX_HPPA_MSEM_INIT */
+
+/* Define to 1 to use the GCC compiler and IA64 assembly language mutexes. */
+/* #undef HAVE_MUTEX_IA64_GCC_ASSEMBLY */
+
+/* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */
+/* #undef HAVE_MUTEX_MSEM_INIT */
+
+/* Define to 1 to use the GCC compiler and Apple PowerPC assembly language. */
+/* #undef HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY */
+
+/* Define to 1 to use the GCC compiler and generic PowerPC assembly language.
+ */
+/* #undef HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY */
+
+/* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */
+/* #undef HAVE_MUTEX_PTHREADS */
+
+/* Define to 1 to use Reliant UNIX initspin mutexes. */
+/* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
+
+/* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */
+/* #undef HAVE_MUTEX_S390_GCC_ASSEMBLY */
+
+/* Define to 1 to use the SCO compiler and x86 assembly language mutexes. */
+/* #undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY */
+
+/* Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes. */
+/* #undef HAVE_MUTEX_SEMA_INIT */
+
+/* Define to 1 to use the SGI XXX_lock mutexes. */
+/* #undef HAVE_MUTEX_SGI_INIT_LOCK */
+
+/* Define to 1 to use the Solaris _lock_XXX mutexes. */
+/* #undef HAVE_MUTEX_SOLARIS_LOCK_TRY */
+
+/* Define to 1 to use the Solaris lwp threads mutexes. */
+/* #undef HAVE_MUTEX_SOLARIS_LWP */
+
+/* Define to 1 to use the GCC compiler and Sparc assembly language mutexes. */
+/* #undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY */
+
+/* Define to 1 if mutexes hold system resources. */
+/* #undef HAVE_MUTEX_SYSTEM_RESOURCES */
+
+/* Define to 1 if fast mutexes are available. */
+#define HAVE_MUTEX_THREADS 1
+
+/* Define to 1 to configure mutexes intra-process only. */
+/* #undef HAVE_MUTEX_THREAD_ONLY */
+
+/* Define to 1 to use the UNIX International mutexes. */
+/* #undef HAVE_MUTEX_UI_THREADS */
+
+/* Define to 1 to use the UTS compiler and assembly language mutexes. */
+/* #undef HAVE_MUTEX_UTS_CC_ASSEMBLY */
+
+/* Define to 1 to use VMS mutexes. */
+/* #undef HAVE_MUTEX_VMS */
+
+/* Define to 1 to use VxWorks mutexes. */
+/* #undef HAVE_MUTEX_VXWORKS */
+
+/* Define to 1 to use Windows mutexes. */
+#define HAVE_MUTEX_WIN32 1
+
+/* Define to 1 to use the GCC compiler and x86 assembly language mutexes. */
+/* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the O_DIRECT flag. */
+/* #undef HAVE_O_DIRECT */
+
+/* Define to 1 if you have the `pread' function. */
+/* #undef HAVE_PREAD */
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `pwrite' function. */
+/* #undef HAVE_PWRITE */
+
+/* Define to 1 if building on QNX. */
+/* #undef HAVE_QNX */
+
+/* Define to 1 if you have the `qsort' function. */
+#define HAVE_QSORT 1
+
+/* Define to 1 if you have the `raise' function. */
+#define HAVE_RAISE 1
+
+/* Define to 1 if building RPC client/server. */
+/* #undef HAVE_RPC */
+
+/* Define to 1 if you have the `sched_yield' function. */
+/* #undef HAVE_SCHED_YIELD */
+
+/* Define to 1 if you have the `select' function. */
+/* #undef HAVE_SELECT */
+
+/* Define to 1 if you have the `shmget' function. */
+/* #undef HAVE_SHMGET */
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */
+
+/* Define to 1 if you have the `sysconf' function. */
+/* #undef HAVE_SYSCONF */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* Define to 1 if unlink of file with open file descriptors will fail. */
+/* #undef HAVE_UNLINK_WITH_OPEN_FAILURE */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if building VxWorks. */
+/* #undef HAVE_VXWORKS */
+
+/* Define to 1 if you have the `yield' function. */
+/* #undef HAVE_YIELD */
+
+/* Define to 1 if you have the `_fstati64' function. */
+#define HAVE__FSTATI64 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "support@sleepycat.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Berkeley DB"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Berkeley DB __EDIT_DB_VERSION__"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "db-__EDIT_DB_VERSION__"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "__EDIT_DB_VERSION__"
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Define to 1 to mask harmless unitialized memory read/writes. */
+/* #undef UMRW */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/*
+ * Exit success/failure macros.
+ */
+#ifndef HAVE_EXIT_SUCCESS
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+#endif
+
+/*
+ * Don't step on the namespace. Other libraries may have their own
+ * implementations of these functions, we don't want to use their
+ * implementations or force them to use ours based on the load order.
+ */
+#ifndef HAVE_GETCWD
+#define getcwd __db_Cgetcwd
+#endif
+#ifndef HAVE_MEMCMP
+#define memcmp __db_Cmemcmp
+#endif
+#ifndef HAVE_MEMCPY
+#define memcpy __db_Cmemcpy
+#endif
+#ifndef HAVE_MEMMOVE
+#define memmove __db_Cmemmove
+#endif
+#ifndef HAVE_RAISE
+#define raise __db_Craise
+#endif
+#ifndef HAVE_SNPRINTF
+#define snprintf __db_Csnprintf
+#endif
+#ifndef HAVE_STRCASECMP
+#define strcasecmp __db_Cstrcasecmp
+#define strncasecmp __db_Cstrncasecmp
+#endif
+#ifndef HAVE_STRERROR
+#define strerror __db_Cstrerror
+#endif
+#ifndef HAVE_VSNPRINTF
+#define vsnprintf __db_Cvsnprintf
+#endif
+
+/*
+ * XXX
+ * The following is not part of the automatic configuration setup, but
+ * provides the information necessary to build Berkeley DB on Windows.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <direct.h>
+#include <fcntl.h>
+#include <io.h>
+#include <limits.h>
+#include <memory.h>
+#include <process.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+/*
+ * To build Tcl interface libraries, the include path must be configured to
+ * use the directory containing <tcl.h>, usually the include directory in
+ * the Tcl distribution.
+ */
+#ifdef DB_TCL_SUPPORT
+#include <tcl.h>
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/*
+ * All of the necessary includes have been included, ignore the #includes
+ * in the Berkeley DB source files.
+ */
+#define NO_SYSTEM_INCLUDES
+
+/*
+ * Win32 has getcwd, snprintf and vsnprintf, but under different names.
+ */
+#define getcwd(buf, size) _getcwd(buf, size)
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+
+/*
+ * Win32 does not define getopt and friends in any header file, so we must.
+ */
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern int optind;
+extern char *optarg;
+extern int getopt(int, char * const *, const char *);
+#if defined(__cplusplus)
+}
+#endif
+
+/*
+ * We use DB_WIN32 much as one would use _WIN32, to determine that we're
+ * using an operating system environment that supports Win32 calls
+ * and semantics. We don't use _WIN32 because cygwin/gcc also defines
+ * that, even though it closely emulates the Unix environment.
+ */
+#define DB_WIN32 1
+
+/*
+ * This is a grievous hack -- once we've included windows.h, we have no choice
+ * but to use ANSI-style varargs (because it pulls in stdarg.h for us). DB's
+ * code decides which type of varargs to use based on the state of __STDC__.
+ * Sensible. Unfortunately, Microsoft's compiler _doesn't_ define __STDC__
+ * unless you invoke it with arguments turning OFF all vendor extensions. Even
+ * more unfortunately, if we do that, it fails to parse windows.h!!!!! So, we
+ * define __STDC__ here, after windows.h comes in. Note: the compiler knows
+ * we've defined it, and starts enforcing strict ANSI compilance from this point
+ * on.
+ */
+#define __STDC__ 1
diff --git a/bdb/dist/win_exports.in b/bdb/dist/win_exports.in
new file mode 100644
index 00000000000..52df529d028
--- /dev/null
+++ b/bdb/dist/win_exports.in
@@ -0,0 +1,134 @@
+# $Id: win_exports.in,v 1.25 2002/08/29 14:22:21 margo Exp $
+
+# Standard interfaces.
+ db_create
+ db_env_create
+ db_strerror
+ db_version
+ db_xa_switch
+ log_compare
+ txn_abort
+ txn_begin
+ txn_commit
+
+# Library configuration interfaces.
+ db_env_set_func_close
+ db_env_set_func_dirfree
+ db_env_set_func_dirlist
+ db_env_set_func_exists
+ db_env_set_func_free
+ db_env_set_func_fsync
+ db_env_set_func_ioinfo
+ db_env_set_func_malloc
+ db_env_set_func_map
+ db_env_set_func_open
+ db_env_set_func_read
+ db_env_set_func_realloc
+ db_env_set_func_rename
+ db_env_set_func_seek
+ db_env_set_func_sleep
+ db_env_set_func_unlink
+ db_env_set_func_unmap
+ db_env_set_func_write
+ db_env_set_func_yield
+
+# Needed for application-specific logging and recovery routines.
+ __db_add_recovery
+
+# These are needed to link the tcl library.
+ __db_dbm_close
+ __db_dbm_delete
+ __db_dbm_fetch
+ __db_dbm_firstkey
+ __db_dbm_init
+ __db_dbm_nextkey
+ __db_dbm_store
+ __db_hcreate
+ __db_hdestroy
+ __db_hsearch
+ __db_loadme
+ __db_ndbm_clearerr
+ __db_ndbm_close
+ __db_ndbm_delete
+ __db_ndbm_dirfno
+ __db_ndbm_error
+ __db_ndbm_fetch
+ __db_ndbm_firstkey
+ __db_ndbm_nextkey
+ __db_ndbm_open
+ __db_ndbm_pagfno
+ __db_ndbm_rdonly
+ __db_ndbm_store
+ __db_panic
+ __db_r_attach
+ __db_r_detach
+ __db_win32_mutex_init
+ __db_win32_mutex_lock
+ __db_win32_mutex_unlock
+ __ham_func2
+ __ham_func3
+ __ham_func4
+ __ham_func5
+ __ham_test
+ __lock_dump_region
+ __memp_dump_region
+ __os_calloc
+ __os_closehandle
+ __os_free
+ __os_ioinfo
+ __os_malloc
+ __os_open
+ __os_openhandle
+ __os_read
+ __os_realloc
+ __os_strdup
+ __os_umalloc
+ __os_write
+
+#These are needed for linking tools or java.
+ __bam_init_print
+ __bam_pgin
+ __bam_pgout
+ __crdel_init_print
+ __db_dispatch
+ __db_dump
+ __db_e_stat
+ __db_err
+ __db_getlong
+ __db_getulong
+ __db_global_values
+ __db_init_print
+ __db_inmemdbflags
+ __db_isbigendian
+ __db_omode
+ __db_overwrite
+ __db_pgin
+ __db_pgout
+ __db_prdbt
+ __db_prfooter
+ __db_prheader
+ __db_rpath
+ __db_util_cache
+ __db_util_interrupted
+ __db_util_logset
+ __db_util_siginit
+ __db_util_sigresend
+ __db_verify_callback
+ __db_verify_internal
+ __dbreg_init_print
+ __fop_init_print
+ __ham_get_meta
+ __ham_init_print
+ __ham_pgin
+ __ham_pgout
+ __ham_release_meta
+ __os_clock
+ __os_get_errno
+ __os_id
+ __os_set_errno
+ __os_sleep
+ __os_ufree
+ __os_yield
+ __qam_init_print
+ __qam_pgin_out
+ __txn_init_print
diff --git a/bdb/env/db_salloc.c b/bdb/env/db_salloc.c
index 4780107c593..1ef768d4114 100644
--- a/bdb/env/db_salloc.c
+++ b/bdb/env/db_salloc.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_salloc.c,v 11.10 2000/12/06 19:55:44 ubell Exp $";
+static const char revid[] = "$Id: db_salloc.c,v 11.16 2002/08/24 20:27:25 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -59,8 +59,8 @@ __db_shalloc_init(area, size)
}
/*
- * __db_shalloc --
- * Allocate some space from the shared region.
+ * __db_shalloc_size --
+ * Return the space needed for an allocation, including alignment.
*
* PUBLIC: int __db_shalloc_size __P((size_t, size_t));
*/
@@ -81,7 +81,7 @@ __db_shalloc_size(len, align)
if (align <= sizeof(db_align_t))
align = sizeof(db_align_t);
- return (ALIGN(len, align) + sizeof (struct __data));
+ return ((int)(ALIGN(len, align) + sizeof (struct __data)));
}
/*
@@ -284,28 +284,6 @@ __db_shalloc_free(regionp, ptr)
}
/*
- * __db_shalloc_count --
- * Return the amount of memory on the free list.
- *
- * PUBLIC: size_t __db_shalloc_count __P((void *));
- */
-size_t
-__db_shalloc_count(addr)
- void *addr;
-{
- struct __data *elp;
- size_t count;
-
- count = 0;
- for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
- elp != NULL;
- elp = SH_LIST_NEXT(elp, links, __data))
- count += elp->len;
-
- return (count);
-}
-
-/*
* __db_shsizeof --
* Return the size of a shalloc'd piece of memory.
*
@@ -355,6 +333,6 @@ __db_shalloc_dump(addr, fp)
for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
elp != NULL;
elp = SH_LIST_NEXT(elp, links, __data))
- fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len);
+ fprintf(fp, "%#lx: %lu\t", P_TO_ULONG(elp), (u_long)elp->len);
fprintf(fp, "\n");
}
diff --git a/bdb/env/db_shash.c b/bdb/env/db_shash.c
index 1c33b383098..743a126307d 100644
--- a/bdb/env/db_shash.c
+++ b/bdb/env/db_shash.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: db_shash.c,v 11.3 2000/02/14 02:59:49 bostic Exp $";
+static const char revid[] = "$Id: db_shash.c,v 11.6 2002/03/01 17:22:16 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -30,6 +30,7 @@ static const struct {
u_int32_t power;
u_int32_t prime;
} list[] = {
+ { 32, 37}, /* 2^5 */
{ 64, 67}, /* 2^6 */
{ 128, 131}, /* 2^7 */
{ 256, 257}, /* 2^8 */
@@ -89,8 +90,8 @@ __db_tablesize(n_buckets)
*
* Ref: Sedgewick, Algorithms in C, "Hash Functions"
*/
- if (n_buckets < 64)
- n_buckets = 64;
+ if (n_buckets < 32)
+ n_buckets = 32;
for (i = 0;; ++i) {
if (list[i].power == 0) {
diff --git a/bdb/env/env_file.c b/bdb/env/env_file.c
new file mode 100644
index 00000000000..f221fd8d701
--- /dev/null
+++ b/bdb/env/env_file.c
@@ -0,0 +1,166 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: env_file.c,v 1.5 2002/03/08 17:47:18 sue Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+static int __db_overwrite_pass __P((DB_ENV *,
+ const char *, DB_FH *, u_int32_t, u_int32_t, u_int32_t));
+
+/*
+ * __db_fileinit --
+ * Initialize a regular file, optionally zero-filling it as well.
+ *
+ * PUBLIC: int __db_fileinit __P((DB_ENV *, DB_FH *, size_t, int));
+ */
+int
+__db_fileinit(dbenv, fhp, size, zerofill)
+ DB_ENV *dbenv;
+ DB_FH *fhp;
+ size_t size;
+ int zerofill;
+{
+ db_pgno_t pages;
+ size_t i;
+ size_t nw;
+ u_int32_t relative;
+ int ret;
+ char buf[OS_VMPAGESIZE];
+
+ /* Write nuls to the new bytes. */
+ memset(buf, 0, sizeof(buf));
+
+ /*
+ * Extend the region by writing the last page. If the region is >4Gb,
+ * increment may be larger than the maximum possible seek "relative"
+ * argument, as it's an unsigned 32-bit value. Break the offset into
+ * pages of 1MB each so that we don't overflow (2^20 + 2^32 is bigger
+ * than any memory I expect to see for awhile).
+ */
+ if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_END)) != 0)
+ return (ret);
+ pages = (db_pgno_t)((size - OS_VMPAGESIZE) / MEGABYTE);
+ relative = (u_int32_t)((size - OS_VMPAGESIZE) % MEGABYTE);
+ if ((ret = __os_seek(dbenv,
+ fhp, MEGABYTE, pages, relative, 0, DB_OS_SEEK_CUR)) != 0)
+ return (ret);
+ if ((ret = __os_write(dbenv, fhp, buf, sizeof(buf), &nw)) != 0)
+ return (ret);
+
+ /*
+ * We may want to guarantee that there is enough disk space for the
+ * file, so we also write a byte to each page. We write the byte
+ * because reading it is insufficient on systems smart enough not to
+ * instantiate disk pages to satisfy a read (e.g., Solaris).
+ */
+ if (zerofill) {
+ pages = (db_pgno_t)(size / MEGABYTE);
+ relative = (u_int32_t)(size % MEGABYTE);
+ if ((ret = __os_seek(dbenv, fhp,
+ MEGABYTE, pages, relative, 1, DB_OS_SEEK_END)) != 0)
+ return (ret);
+
+ /* Write a byte to each page. */
+ for (i = 0; i < size; i += OS_VMPAGESIZE) {
+ if ((ret = __os_write(dbenv, fhp, buf, 1, &nw)) != 0)
+ return (ret);
+ if ((ret = __os_seek(dbenv, fhp,
+ 0, 0, OS_VMPAGESIZE - 1, 0, DB_OS_SEEK_CUR)) != 0)
+ return (ret);
+ }
+ }
+ return (0);
+}
+
+/*
+ * __db_overwrite --
+ * Overwrite a file.
+ *
+ * PUBLIC: int __db_overwrite __P((DB_ENV *, const char *));
+ */
+int
+__db_overwrite(dbenv, path)
+ DB_ENV *dbenv;
+ const char *path;
+{
+ DB_FH fh, *fhp;
+ u_int32_t mbytes, bytes;
+ int ret;
+
+ fhp = &fh;
+ if ((ret = __os_open(dbenv, path, DB_OSO_REGION, 0, fhp)) == 0 &&
+ (ret = __os_ioinfo(dbenv, path, fhp, &mbytes, &bytes, NULL)) == 0) {
+ /*
+ * !!!
+ * Overwrite a regular file with alternating 0xff, 0x00 and 0xff
+ * byte patterns. Implies a fixed-block filesystem, journaling
+ * or logging filesystems will require operating system support.
+ */
+ if ((ret = __db_overwrite_pass(
+ dbenv, path, fhp, mbytes, bytes, 0xff)) != 0)
+ goto err;
+ if ((ret = __db_overwrite_pass(
+ dbenv, path, fhp, mbytes, bytes, 0x00)) != 0)
+ goto err;
+ if ((ret = __db_overwrite_pass(
+ dbenv, path, fhp, mbytes, bytes, 0xff)) != 0)
+ goto err;
+ } else
+ __db_err(dbenv, "%s: %s", path, db_strerror(ret));
+
+err: if (F_ISSET(fhp, DB_FH_VALID))
+ __os_closehandle(dbenv, fhp);
+ return (ret);
+}
+
+/*
+ * __db_overwrite_pass --
+ * A single pass over the file, writing the specified byte pattern.
+ */
+static int
+__db_overwrite_pass(dbenv, path, fhp, mbytes, bytes, pattern)
+ DB_ENV *dbenv;
+ const char *path;
+ DB_FH *fhp;
+ u_int32_t mbytes, bytes, pattern;
+{
+ size_t len, nw;
+ int i, ret;
+ char buf[8 * 1024];
+
+ if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
+ goto err;
+
+ memset(buf, pattern, sizeof(buf));
+
+ for (; mbytes > 0; --mbytes)
+ for (i = MEGABYTE / sizeof(buf); i > 0; --i)
+ if ((ret =
+ __os_write(dbenv, fhp, buf, sizeof(buf), &nw)) != 0)
+ goto err;
+ for (; bytes > 0; bytes -= (u_int32_t)len) {
+ len = bytes < sizeof(buf) ? bytes : sizeof(buf);
+ if ((ret = __os_write(dbenv, fhp, buf, len, &nw)) != 0)
+ goto err;
+ }
+
+ if ((ret = __os_fsync(dbenv, fhp)) != 0)
+err: __db_err(dbenv, "%s: %s", path, db_strerror(ret));
+
+ return (ret);
+}
diff --git a/bdb/env/env_method.c b/bdb/env/env_method.c
index 8acb293acca..b51237ec44a 100644
--- a/bdb/env/env_method.c
+++ b/bdb/env/env_method.c
@@ -1,24 +1,24 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: env_method.c,v 11.31 2000/11/30 00:58:35 ubell Exp $";
+static const char revid[] = "$Id: env_method.c,v 11.87 2002/08/29 14:22:21 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#include <string.h>
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
+#include <string.h>
#endif
/*
@@ -29,41 +29,50 @@ static const char revid[] = "$Id: env_method.c,v 11.31 2000/11/30 00:58:35 ubell
#define DB_INITIALIZE_DB_GLOBALS 1
#include "db_int.h"
-#include "db_shash.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "lock.h"
-#include "log.h"
-#include "mp.h"
-#include "txn.h"
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
#endif
static void __dbenv_err __P((const DB_ENV *, int, const char *, ...));
static void __dbenv_errx __P((const DB_ENV *, const char *, ...));
+static int __dbenv_init __P((DB_ENV *));
+static int __dbenv_set_alloc __P((DB_ENV *, void *(*)(size_t),
+ void *(*)(void *, size_t), void (*)(void *)));
+static int __dbenv_set_app_dispatch __P((DB_ENV *,
+ int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
static int __dbenv_set_data_dir __P((DB_ENV *, const char *));
+static int __dbenv_set_encrypt __P((DB_ENV *, const char *, u_int32_t));
static void __dbenv_set_errcall __P((DB_ENV *, void (*)(const char *, char *)));
static void __dbenv_set_errfile __P((DB_ENV *, FILE *));
static void __dbenv_set_errpfx __P((DB_ENV *, const char *));
static int __dbenv_set_feedback __P((DB_ENV *, void (*)(DB_ENV *, int, int)));
static int __dbenv_set_flags __P((DB_ENV *, u_int32_t, int));
-static int __dbenv_set_mutexlocks __P((DB_ENV *, int));
-static void __dbenv_set_noticecall
- __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
+static void __dbenv_set_noticecall __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
static int __dbenv_set_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int)));
-static int __dbenv_set_recovery_init __P((DB_ENV *, int (*)(DB_ENV *)));
-static int __dbenv_set_server_noclnt
- __P((DB_ENV *, char *, long, long, u_int32_t));
+static int __dbenv_set_rpc_server_noclnt
+ __P((DB_ENV *, void *, const char *, long, long, u_int32_t));
static int __dbenv_set_shm_key __P((DB_ENV *, long));
+static int __dbenv_set_tas_spins __P((DB_ENV *, u_int32_t));
static int __dbenv_set_tmp_dir __P((DB_ENV *, const char *));
static int __dbenv_set_verbose __P((DB_ENV *, u_int32_t, int));
/*
* db_env_create --
* DB_ENV constructor.
+ *
+ * EXTERN: int db_env_create __P((DB_ENV **, u_int32_t));
*/
int
db_env_create(dbenvpp, flags)
@@ -75,6 +84,11 @@ db_env_create(dbenvpp, flags)
/*
* !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ *
+ * !!!
* We can't call the flags-checking routines, we don't have an
* environment yet.
*/
@@ -91,7 +105,7 @@ db_env_create(dbenvpp, flags)
ret = __dbenv_init(dbenv);
if (ret != 0) {
- __os_free(dbenv, sizeof(*dbenv));
+ __os_free(NULL, dbenv);
return (ret);
}
@@ -102,14 +116,17 @@ db_env_create(dbenvpp, flags)
/*
* __dbenv_init --
* Initialize a DB_ENV structure.
- *
- * PUBLIC: int __dbenv_init __P((DB_ENV *));
*/
-int
+static int
__dbenv_init(dbenv)
DB_ENV *dbenv;
{
/*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ *
* Set up methods that are the same in both normal and RPC
*/
dbenv->err = __dbenv_err;
@@ -121,44 +138,54 @@ __dbenv_init(dbenv)
#ifdef HAVE_RPC
if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
dbenv->close = __dbcl_env_close;
- dbenv->open = __dbcl_env_open;
+ dbenv->dbremove = __dbcl_env_dbremove;
+ dbenv->dbrename = __dbcl_env_dbrename;
+ dbenv->open = __dbcl_env_open_wrap;
dbenv->remove = __dbcl_env_remove;
+ dbenv->set_alloc = __dbcl_env_alloc;
+ dbenv->set_app_dispatch = __dbcl_set_app_dispatch;
dbenv->set_data_dir = __dbcl_set_data_dir;
+ dbenv->set_encrypt = __dbcl_env_encrypt;
dbenv->set_feedback = __dbcl_env_set_feedback;
dbenv->set_flags = __dbcl_env_flags;
- dbenv->set_mutexlocks = __dbcl_set_mutex_locks;
dbenv->set_noticecall = __dbcl_env_noticecall;
dbenv->set_paniccall = __dbcl_env_paniccall;
- dbenv->set_recovery_init = __dbcl_set_recovery_init;
- dbenv->set_server = __dbcl_envserver;
+ dbenv->set_rpc_server = __dbcl_envrpcserver;
dbenv->set_shm_key = __dbcl_set_shm_key;
+ dbenv->set_tas_spins = __dbcl_set_tas_spins;
+ dbenv->set_timeout = __dbcl_set_timeout;
dbenv->set_tmp_dir = __dbcl_set_tmp_dir;
dbenv->set_verbose = __dbcl_set_verbose;
} else {
#endif
dbenv->close = __dbenv_close;
+ dbenv->dbremove = __dbenv_dbremove;
+ dbenv->dbrename = __dbenv_dbrename;
dbenv->open = __dbenv_open;
dbenv->remove = __dbenv_remove;
+ dbenv->set_alloc = __dbenv_set_alloc;
+ dbenv->set_app_dispatch = __dbenv_set_app_dispatch;
dbenv->set_data_dir = __dbenv_set_data_dir;
+ dbenv->set_encrypt = __dbenv_set_encrypt;
dbenv->set_feedback = __dbenv_set_feedback;
dbenv->set_flags = __dbenv_set_flags;
- dbenv->set_mutexlocks = __dbenv_set_mutexlocks;
dbenv->set_noticecall = __dbenv_set_noticecall;
dbenv->set_paniccall = __dbenv_set_paniccall;
- dbenv->set_recovery_init = __dbenv_set_recovery_init;
- dbenv->set_server = __dbenv_set_server_noclnt;
+ dbenv->set_rpc_server = __dbenv_set_rpc_server_noclnt;
dbenv->set_shm_key = __dbenv_set_shm_key;
+ dbenv->set_tas_spins = __dbenv_set_tas_spins;
dbenv->set_tmp_dir = __dbenv_set_tmp_dir;
dbenv->set_verbose = __dbenv_set_verbose;
#ifdef HAVE_RPC
}
#endif
dbenv->shm_key = INVALID_REGION_SEGID;
- dbenv->db_mutexlocks = 1;
+ dbenv->db_ref = 0;
__log_dbenv_create(dbenv); /* Subsystem specific. */
__lock_dbenv_create(dbenv);
__memp_dbenv_create(dbenv);
+ __rep_dbenv_create(dbenv);
__txn_dbenv_create(dbenv);
return (0);
@@ -179,16 +206,7 @@ __dbenv_err(dbenv, error, fmt, va_alist)
va_dcl
#endif
{
- va_list ap;
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- __db_real_err(dbenv, error, 1, 1, fmt, ap);
-
- va_end(ap);
+ DB_REAL_ERR(dbenv, error, 1, 1, fmt);
}
/*
@@ -205,16 +223,109 @@ __dbenv_errx(dbenv, fmt, va_alist)
va_dcl
#endif
{
- va_list ap;
+ DB_REAL_ERR(dbenv, 0, 0, 1, fmt);
+}
-#ifdef __STDC__
- va_start(ap, fmt);
+static int
+__dbenv_set_alloc(dbenv, mal_func, real_func, free_func)
+ DB_ENV *dbenv;
+ void *(*mal_func) __P((size_t));
+ void *(*real_func) __P((void *, size_t));
+ void (*free_func) __P((void *));
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_alloc");
+
+ dbenv->db_malloc = mal_func;
+ dbenv->db_realloc = real_func;
+ dbenv->db_free = free_func;
+ return (0);
+}
+
+/*
+ * __dbenv_set_app_dispatch --
+ * Set the transaction abort recover function.
+ */
+static int
+__dbenv_set_app_dispatch(dbenv, app_dispatch)
+ DB_ENV *dbenv;
+ int (*app_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_app_dispatch");
+
+ dbenv->app_dispatch = app_dispatch;
+ return (0);
+}
+
+static int
+__dbenv_set_encrypt(dbenv, passwd, flags)
+ DB_ENV *dbenv;
+ const char *passwd;
+ u_int32_t flags;
+{
+#ifdef HAVE_CRYPTO
+ DB_CIPHER *db_cipher;
+ int ret;
+
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_encrypt");
+#define OK_CRYPTO_FLAGS (DB_ENCRYPT_AES)
+
+ if (flags != 0 && LF_ISSET(~OK_CRYPTO_FLAGS))
+ return (__db_ferr(dbenv, "DB_ENV->set_encrypt", 0));
+
+ if (passwd == NULL || strlen(passwd) == 0) {
+ __db_err(dbenv, "Empty password specified to set_encrypt");
+ return (EINVAL);
+ }
+ if (!CRYPTO_ON(dbenv)) {
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_CIPHER), &db_cipher))
+ != 0)
+ goto err;
+ dbenv->crypto_handle = db_cipher;
+ } else
+ db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+
+ if (dbenv->passwd != NULL)
+ __os_free(dbenv, dbenv->passwd);
+ if ((ret = __os_strdup(dbenv, passwd, &dbenv->passwd)) != 0) {
+ __os_free(dbenv, db_cipher);
+ goto err;
+ }
+ /*
+ * We're going to need this often enough to keep around
+ */
+ dbenv->passwd_len = strlen(dbenv->passwd) + 1;
+ /*
+ * The MAC key is for checksumming, and is separate from
+ * the algorithm. So initialize it here, even if they
+ * are using CIPHER_ANY.
+ */
+ __db_derive_mac((u_int8_t *)dbenv->passwd,
+ dbenv->passwd_len, db_cipher->mac_key);
+ switch (flags) {
+ case 0:
+ F_SET(db_cipher, CIPHER_ANY);
+ break;
+ case DB_ENCRYPT_AES:
+ if ((ret = __crypto_algsetup(dbenv, db_cipher, CIPHER_AES, 0))
+ != 0)
+ goto err1;
+ break;
+ }
+ return (0);
+
+err1:
+ __os_free(dbenv, dbenv->passwd);
+ __os_free(dbenv, db_cipher);
+ dbenv->crypto_handle = NULL;
+err:
+ return (ret);
#else
- va_start(ap);
-#endif
- __db_real_err(dbenv, 0, 0, 1, fmt, ap);
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(passwd, NULL);
+ COMPQUIET(flags, 0);
- va_end(ap);
+ return (__db_eopnotsup(dbenv));
+#endif
}
static int
@@ -223,11 +334,23 @@ __dbenv_set_flags(dbenv, flags, onoff)
u_int32_t flags;
int onoff;
{
-#define OK_FLAGS (DB_CDB_ALLDB | DB_NOMMAP | DB_TXN_NOSYNC)
+#define OK_FLAGS \
+ (DB_AUTO_COMMIT | DB_CDB_ALLDB | DB_DIRECT_DB | DB_DIRECT_LOG | \
+ DB_NOLOCKING | DB_NOMMAP | DB_NOPANIC | DB_OVERWRITE | \
+ DB_PANIC_ENVIRONMENT | DB_REGION_INIT | DB_TXN_NOSYNC | \
+ DB_TXN_WRITE_NOSYNC | DB_YIELDCPU)
if (LF_ISSET(~OK_FLAGS))
- return (__db_ferr(dbenv, "DBENV->set_flags", 0));
+ return (__db_ferr(dbenv, "DB_ENV->set_flags", 0));
+ if (onoff && LF_ISSET(DB_TXN_WRITE_NOSYNC) && LF_ISSET(DB_TXN_NOSYNC))
+ return (__db_ferr(dbenv, "DB_ENV->set_flags", 1));
+ if (LF_ISSET(DB_AUTO_COMMIT)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_AUTO_COMMIT);
+ else
+ F_CLR(dbenv, DB_ENV_AUTO_COMMIT);
+ }
if (LF_ISSET(DB_CDB_ALLDB)) {
ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_flags: DB_CDB_ALLDB");
if (onoff)
@@ -235,18 +358,72 @@ __dbenv_set_flags(dbenv, flags, onoff)
else
F_CLR(dbenv, DB_ENV_CDB_ALLDB);
}
+ if (LF_ISSET(DB_DIRECT_DB)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_DIRECT_DB);
+ else
+ F_CLR(dbenv, DB_ENV_DIRECT_DB);
+ }
+ if (LF_ISSET(DB_DIRECT_LOG)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_DIRECT_LOG);
+ else
+ F_CLR(dbenv, DB_ENV_DIRECT_LOG);
+ }
+ if (LF_ISSET(DB_NOLOCKING)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_NOLOCKING);
+ else
+ F_CLR(dbenv, DB_ENV_NOLOCKING);
+ }
if (LF_ISSET(DB_NOMMAP)) {
if (onoff)
F_SET(dbenv, DB_ENV_NOMMAP);
else
F_CLR(dbenv, DB_ENV_NOMMAP);
}
+ if (LF_ISSET(DB_NOPANIC)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_NOPANIC);
+ else
+ F_CLR(dbenv, DB_ENV_NOPANIC);
+ }
+ if (LF_ISSET(DB_OVERWRITE)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_OVERWRITE);
+ else
+ F_CLR(dbenv, DB_ENV_OVERWRITE);
+ }
+ if (LF_ISSET(DB_PANIC_ENVIRONMENT)) {
+ ENV_ILLEGAL_BEFORE_OPEN(dbenv,
+ "set_flags: DB_PANIC_ENVIRONMENT");
+ PANIC_SET(dbenv, onoff);
+ }
+ if (LF_ISSET(DB_REGION_INIT)) {
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_flags: DB_REGION_INIT");
+ if (onoff)
+ F_SET(dbenv, DB_ENV_REGION_INIT);
+ else
+ F_CLR(dbenv, DB_ENV_REGION_INIT);
+ }
if (LF_ISSET(DB_TXN_NOSYNC)) {
if (onoff)
F_SET(dbenv, DB_ENV_TXN_NOSYNC);
else
F_CLR(dbenv, DB_ENV_TXN_NOSYNC);
}
+ if (LF_ISSET(DB_TXN_WRITE_NOSYNC)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_TXN_WRITE_NOSYNC);
+ else
+ F_CLR(dbenv, DB_ENV_TXN_WRITE_NOSYNC);
+ }
+ if (LF_ISSET(DB_YIELDCPU)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_YIELDCPU);
+ else
+ F_CLR(dbenv, DB_ENV_YIELDCPU);
+ }
return (0);
}
@@ -267,7 +444,7 @@ __dbenv_set_data_dir(dbenv, dir)
dbenv->data_cnt *= 2;
if ((ret = __os_realloc(dbenv,
dbenv->data_cnt * sizeof(char **),
- NULL, &dbenv->db_data_dir)) != 0)
+ &dbenv->db_data_dir)) != 0)
return (ret);
}
return (__os_strdup(dbenv,
@@ -314,16 +491,7 @@ __dbenv_set_noticecall(dbenv, noticecall)
{
dbenv->db_noticecall = noticecall;
}
-
-static int
-__dbenv_set_mutexlocks(dbenv, onoff)
- DB_ENV *dbenv;
- int onoff;
-{
- dbenv->db_mutexlocks = onoff;
- return (0);
-}
-
+
static int
__dbenv_set_paniccall(dbenv, paniccall)
DB_ENV *dbenv;
@@ -334,25 +502,22 @@ __dbenv_set_paniccall(dbenv, paniccall)
}
static int
-__dbenv_set_recovery_init(dbenv, recovery_init)
+__dbenv_set_shm_key(dbenv, shm_key)
DB_ENV *dbenv;
- int (*recovery_init) __P((DB_ENV *));
+ long shm_key; /* !!!: really a key_t. */
{
- ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_recovery_init");
-
- dbenv->db_recovery_init = recovery_init;
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_shm_key");
+ dbenv->shm_key = shm_key;
return (0);
}
static int
-__dbenv_set_shm_key(dbenv, shm_key)
+__dbenv_set_tas_spins(dbenv, tas_spins)
DB_ENV *dbenv;
- long shm_key; /* !!!: really a key_t. */
+ u_int32_t tas_spins;
{
- ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_shm_key");
-
- dbenv->shm_key = shm_key;
+ dbenv->tas_spins = tas_spins;
return (0);
}
@@ -362,7 +527,7 @@ __dbenv_set_tmp_dir(dbenv, dir)
const char *dir;
{
if (dbenv->db_tmp_dir != NULL)
- __os_freestr(dbenv->db_tmp_dir);
+ __os_free(dbenv, dbenv->db_tmp_dir);
return (__os_strdup(dbenv, dir, &dbenv->db_tmp_dir));
}
@@ -376,6 +541,7 @@ __dbenv_set_verbose(dbenv, which, onoff)
case DB_VERB_CHKPOINT:
case DB_VERB_DEADLOCK:
case DB_VERB_RECOVERY:
+ case DB_VERB_REPLICATION:
case DB_VERB_WAITSFOR:
if (onoff)
FLD_SET(dbenv->verbose, which);
@@ -399,7 +565,7 @@ __db_mi_env(dbenv, name)
DB_ENV *dbenv;
const char *name;
{
- __db_err(dbenv, "%s: method meaningless in shared environment", name);
+ __db_err(dbenv, "%s: method not permitted in shared environment", name);
return (EINVAL);
}
@@ -415,59 +581,63 @@ __db_mi_open(dbenv, name, after)
const char *name;
int after;
{
- __db_err(dbenv,
- "%s: method meaningless %s open", name, after ? "after" : "before");
+ __db_err(dbenv, "%s: method not permitted %s open",
+ name, after ? "after" : "before");
return (EINVAL);
}
/*
* __db_env_config --
- * Method or function called without subsystem being configured.
+ * Method or function called without required configuration.
*
- * PUBLIC: int __db_env_config __P((DB_ENV *, int));
+ * PUBLIC: int __db_env_config __P((DB_ENV *, char *, u_int32_t));
*/
int
-__db_env_config(dbenv, subsystem)
+__db_env_config(dbenv, i, flags)
DB_ENV *dbenv;
- int subsystem;
+ char *i;
+ u_int32_t flags;
{
- const char *name;
+ char *sub;
- switch (subsystem) {
+ switch (flags) {
case DB_INIT_LOCK:
- name = "lock";
+ sub = "locking";
break;
case DB_INIT_LOG:
- name = "log";
+ sub = "logging";
break;
case DB_INIT_MPOOL:
- name = "mpool";
+ sub = "memory pool";
break;
case DB_INIT_TXN:
- name = "txn";
+ sub = "transaction";
break;
default:
- name = "unknown";
+ sub = "<unspecified>";
break;
}
__db_err(dbenv,
- "%s interface called with environment not configured for that subsystem",
- name);
+ "%s interface requires an environment configured for the %s subsystem",
+ i, sub);
return (EINVAL);
}
static int
-__dbenv_set_server_noclnt(dbenv, host, tsec, ssec, flags)
+__dbenv_set_rpc_server_noclnt(dbenv, cl, host, tsec, ssec, flags)
DB_ENV *dbenv;
- char *host;
+ void *cl;
+ const char *host;
long tsec, ssec;
u_int32_t flags;
{
COMPQUIET(host, NULL);
+ COMPQUIET(cl, NULL);
COMPQUIET(tsec, 0);
COMPQUIET(ssec, 0);
COMPQUIET(flags, 0);
- __db_err(dbenv, "set_server method meaningless in non-RPC enviroment");
+ __db_err(dbenv,
+ "set_rpc_server method not permitted in non-RPC environment");
return (__db_eopnotsup(dbenv));
}
diff --git a/bdb/env/env_method.c.b b/bdb/env/env_method.c.b
new file mode 100644
index 00000000000..b6802b8a77c
--- /dev/null
+++ b/bdb/env/env_method.c.b
@@ -0,0 +1,643 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: env_method.c,v 11.87 2002/08/29 14:22:21 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
+
+#include <string.h>
+#endif
+
+/*
+ * This is the file that initializes the global array. Do it this way because
+ * people keep changing one without changing the other. Having declaration and
+ * initialization in one file will hopefully fix that.
+ */
+#define DB_INITIALIZE_DB_GLOBALS 1
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+
+#ifdef HAVE_RPC
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
+#endif
+
+static void __dbenv_err __P((const DB_ENV *, int, const char *, ...));
+static void __dbenv_errx __P((const DB_ENV *, const char *, ...));
+static int __dbenv_init __P((DB_ENV *));
+static int __dbenv_set_alloc __P((DB_ENV *, void *(*)(size_t),
+ void *(*)(void *, size_t), void (*)(void *)));
+static int __dbenv_set_app_dispatch __P((DB_ENV *,
+ int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
+static int __dbenv_set_data_dir __P((DB_ENV *, const char *));
+static int __dbenv_set_encrypt __P((DB_ENV *, const char *, u_int32_t));
+static void __dbenv_set_errcall __P((DB_ENV *, void (*)(const char *, char *)));
+static void __dbenv_set_errfile __P((DB_ENV *, FILE *));
+static void __dbenv_set_errpfx __P((DB_ENV *, const char *));
+static int __dbenv_set_feedback __P((DB_ENV *, void (*)(DB_ENV *, int, int)));
+static int __dbenv_set_flags __P((DB_ENV *, u_int32_t, int));
+static void __dbenv_set_noticecall __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
+static int __dbenv_set_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int)));
+static int __dbenv_set_rpc_server_noclnt
+ __P((DB_ENV *, void *, const char *, long, long, u_int32_t));
+static int __dbenv_set_shm_key __P((DB_ENV *, long));
+static int __dbenv_set_tas_spins __P((DB_ENV *, u_int32_t));
+static int __dbenv_set_tmp_dir __P((DB_ENV *, const char *));
+static int __dbenv_set_verbose __P((DB_ENV *, u_int32_t, int));
+
+/*
+ * db_env_create --
+ * DB_ENV constructor.
+ *
+ * EXTERN: int db_env_create __P((DB_ENV **, u_int32_t));
+ */
+int
+db_env_create(dbenvpp, flags)
+ DB_ENV **dbenvpp;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ /*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ *
+ * !!!
+ * We can't call the flags-checking routines, we don't have an
+ * environment yet.
+ */
+ if (flags != 0 && flags != DB_CLIENT)
+ return (EINVAL);
+
+ if ((ret = __os_calloc(NULL, 1, sizeof(*dbenv), &dbenv)) != 0)
+ return (ret);
+
+#ifdef HAVE_RPC
+ if (LF_ISSET(DB_CLIENT))
+ F_SET(dbenv, DB_ENV_RPCCLIENT);
+#endif
+ ret = __dbenv_init(dbenv);
+
+ if (ret != 0) {
+ __os_free(NULL, dbenv);
+ return (ret);
+ }
+
+ *dbenvpp = dbenv;
+ return (0);
+}
+
+/*
+ * __dbenv_init --
+ * Initialize a DB_ENV structure.
+ */
+static int
+__dbenv_init(dbenv)
+ DB_ENV *dbenv;
+{
+ /*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ *
+ * Set up methods that are the same in both normal and RPC
+ */
+ dbenv->err = __dbenv_err;
+ dbenv->errx = __dbenv_errx;
+ dbenv->set_errcall = __dbenv_set_errcall;
+ dbenv->set_errfile = __dbenv_set_errfile;
+ dbenv->set_errpfx = __dbenv_set_errpfx;
+
+#ifdef HAVE_RPC
+ if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+ dbenv->close = __dbcl_env_close;
+ dbenv->dbremove = __dbcl_env_dbremove;
+ dbenv->dbrename = __dbcl_env_dbrename;
+ dbenv->open = __dbcl_env_open_wrap;
+ dbenv->remove = __dbcl_env_remove;
+ dbenv->set_alloc = __dbcl_env_alloc;
+ dbenv->set_app_dispatch = __dbcl_set_app_dispatch;
+ dbenv->set_data_dir = __dbcl_set_data_dir;
+ dbenv->set_encrypt = __dbcl_env_encrypt;
+ dbenv->set_feedback = __dbcl_env_set_feedback;
+ dbenv->set_flags = __dbcl_env_flags;
+ dbenv->set_noticecall = __dbcl_env_noticecall;
+ dbenv->set_paniccall = __dbcl_env_paniccall;
+ dbenv->set_rpc_server = __dbcl_envrpcserver;
+ dbenv->set_shm_key = __dbcl_set_shm_key;
+ dbenv->set_tas_spins = __dbcl_set_tas_spins;
+ dbenv->set_timeout = __dbcl_set_timeout;
+ dbenv->set_tmp_dir = __dbcl_set_tmp_dir;
+ dbenv->set_verbose = __dbcl_set_verbose;
+ } else {
+#endif
+ dbenv->close = __dbenv_close;
+ dbenv->dbremove = __dbenv_dbremove;
+ dbenv->dbrename = __dbenv_dbrename;
+ dbenv->open = __dbenv_open;
+ dbenv->remove = __dbenv_remove;
+ dbenv->set_alloc = __dbenv_set_alloc;
+ dbenv->set_app_dispatch = __dbenv_set_app_dispatch;
+ dbenv->set_data_dir = __dbenv_set_data_dir;
+ dbenv->set_encrypt = __dbenv_set_encrypt;
+ dbenv->set_feedback = __dbenv_set_feedback;
+ dbenv->set_flags = __dbenv_set_flags;
+ dbenv->set_noticecall = __dbcl_env_noticecall;
+ dbenv->set_paniccall = __dbenv_set_paniccall;
+ dbenv->set_rpc_server = __dbenv_set_rpc_server_noclnt;
+ dbenv->set_shm_key = __dbenv_set_shm_key;
+ dbenv->set_tas_spins = __dbenv_set_tas_spins;
+ dbenv->set_tmp_dir = __dbenv_set_tmp_dir;
+ dbenv->set_verbose = __dbenv_set_verbose;
+#ifdef HAVE_RPC
+ }
+#endif
+ dbenv->shm_key = INVALID_REGION_SEGID;
+ dbenv->db_ref = 0;
+
+ __log_dbenv_create(dbenv); /* Subsystem specific. */
+ __lock_dbenv_create(dbenv);
+ __memp_dbenv_create(dbenv);
+ __rep_dbenv_create(dbenv);
+ __txn_dbenv_create(dbenv);
+
+ return (0);
+}
+
+/*
+ * __dbenv_err --
+ * Error message, including the standard error string.
+ */
+static void
+#ifdef __STDC__
+__dbenv_err(const DB_ENV *dbenv, int error, const char *fmt, ...)
+#else
+__dbenv_err(dbenv, error, fmt, va_alist)
+ const DB_ENV *dbenv;
+ int error;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ DB_REAL_ERR(dbenv, error, 1, 1, fmt);
+}
+
+/*
+ * __dbenv_errx --
+ * Error message.
+ */
+static void
+#ifdef __STDC__
+__dbenv_errx(const DB_ENV *dbenv, const char *fmt, ...)
+#else
+__dbenv_errx(dbenv, fmt, va_alist)
+ const DB_ENV *dbenv;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ DB_REAL_ERR(dbenv, 0, 0, 1, fmt);
+}
+
+static int
+__dbenv_set_alloc(dbenv, mal_func, real_func, free_func)
+ DB_ENV *dbenv;
+ void *(*mal_func) __P((size_t));
+ void *(*real_func) __P((void *, size_t));
+ void (*free_func) __P((void *));
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_alloc");
+
+ dbenv->db_malloc = mal_func;
+ dbenv->db_realloc = real_func;
+ dbenv->db_free = free_func;
+ return (0);
+}
+
+/*
+ * __dbenv_set_app_dispatch --
+ * Set the transaction abort recover function.
+ */
+static int
+__dbenv_set_app_dispatch(dbenv, app_dispatch)
+ DB_ENV *dbenv;
+ int (*app_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_app_dispatch");
+
+ dbenv->app_dispatch = app_dispatch;
+ return (0);
+}
+
+static int
+__dbenv_set_encrypt(dbenv, passwd, flags)
+ DB_ENV *dbenv;
+ const char *passwd;
+ u_int32_t flags;
+{
+#ifdef HAVE_CRYPTO
+ DB_CIPHER *db_cipher;
+ int ret;
+
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_encrypt");
+#define OK_CRYPTO_FLAGS (DB_ENCRYPT_AES)
+
+ if (flags != 0 && LF_ISSET(~OK_CRYPTO_FLAGS))
+ return (__db_ferr(dbenv, "DB_ENV->set_encrypt", 0));
+
+ if (passwd == NULL || strlen(passwd) == 0) {
+ __db_err(dbenv, "Empty password specified to set_encrypt");
+ return (EINVAL);
+ }
+ if (!CRYPTO_ON(dbenv)) {
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_CIPHER), &db_cipher))
+ != 0)
+ goto err;
+ dbenv->crypto_handle = db_cipher;
+ } else
+ db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+
+ if (dbenv->passwd != NULL)
+ __os_free(dbenv, dbenv->passwd);
+ if ((ret = __os_strdup(dbenv, passwd, &dbenv->passwd)) != 0) {
+ __os_free(dbenv, db_cipher);
+ goto err;
+ }
+ /*
+ * We're going to need this often enough to keep around
+ */
+ dbenv->passwd_len = strlen(dbenv->passwd) + 1;
+ /*
+ * The MAC key is for checksumming, and is separate from
+ * the algorithm. So initialize it here, even if they
+ * are using CIPHER_ANY.
+ */
+ __db_derive_mac((u_int8_t *)dbenv->passwd,
+ dbenv->passwd_len, db_cipher->mac_key);
+ switch (flags) {
+ case 0:
+ F_SET(db_cipher, CIPHER_ANY);
+ break;
+ case DB_ENCRYPT_AES:
+ if ((ret = __crypto_algsetup(dbenv, db_cipher, CIPHER_AES, 0))
+ != 0)
+ goto err1;
+ break;
+ }
+ return (0);
+
+err1:
+ __os_free(dbenv, dbenv->passwd);
+ __os_free(dbenv, db_cipher);
+ dbenv->crypto_handle = NULL;
+err:
+ return (ret);
+#else
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(passwd, NULL);
+ COMPQUIET(flags, 0);
+
+ return (__db_eopnotsup(dbenv));
+#endif
+}
+
+static int
+__dbenv_set_flags(dbenv, flags, onoff)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+ int onoff;
+{
+#define OK_FLAGS \
+ (DB_AUTO_COMMIT | DB_CDB_ALLDB | DB_DIRECT_DB | DB_DIRECT_LOG | \
+ DB_NOLOCKING | DB_NOMMAP | DB_NOPANIC | DB_OVERWRITE | \
+ DB_PANIC_ENVIRONMENT | DB_REGION_INIT | DB_TXN_NOSYNC | \
+ DB_TXN_WRITE_NOSYNC | DB_YIELDCPU)
+
+ if (LF_ISSET(~OK_FLAGS))
+ return (__db_ferr(dbenv, "DB_ENV->set_flags", 0));
+ if (onoff && LF_ISSET(DB_TXN_WRITE_NOSYNC) && LF_ISSET(DB_TXN_NOSYNC))
+ return (__db_ferr(dbenv, "DB_ENV->set_flags", 1));
+
+ if (LF_ISSET(DB_AUTO_COMMIT)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_AUTO_COMMIT);
+ else
+ F_CLR(dbenv, DB_ENV_AUTO_COMMIT);
+ }
+ if (LF_ISSET(DB_CDB_ALLDB)) {
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_flags: DB_CDB_ALLDB");
+ if (onoff)
+ F_SET(dbenv, DB_ENV_CDB_ALLDB);
+ else
+ F_CLR(dbenv, DB_ENV_CDB_ALLDB);
+ }
+ if (LF_ISSET(DB_DIRECT_DB)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_DIRECT_DB);
+ else
+ F_CLR(dbenv, DB_ENV_DIRECT_DB);
+ }
+ if (LF_ISSET(DB_DIRECT_LOG)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_DIRECT_LOG);
+ else
+ F_CLR(dbenv, DB_ENV_DIRECT_LOG);
+ }
+ if (LF_ISSET(DB_NOLOCKING)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_NOLOCKING);
+ else
+ F_CLR(dbenv, DB_ENV_NOLOCKING);
+ }
+ if (LF_ISSET(DB_NOMMAP)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_NOMMAP);
+ else
+ F_CLR(dbenv, DB_ENV_NOMMAP);
+ }
+ if (LF_ISSET(DB_NOPANIC)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_NOPANIC);
+ else
+ F_CLR(dbenv, DB_ENV_NOPANIC);
+ }
+ if (LF_ISSET(DB_OVERWRITE)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_OVERWRITE);
+ else
+ F_CLR(dbenv, DB_ENV_OVERWRITE);
+ }
+ if (LF_ISSET(DB_PANIC_ENVIRONMENT)) {
+ ENV_ILLEGAL_BEFORE_OPEN(dbenv,
+ "set_flags: DB_PANIC_ENVIRONMENT");
+ PANIC_SET(dbenv, onoff);
+ }
+ if (LF_ISSET(DB_REGION_INIT)) {
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_flags: DB_REGION_INIT");
+ if (onoff)
+ F_SET(dbenv, DB_ENV_REGION_INIT);
+ else
+ F_CLR(dbenv, DB_ENV_REGION_INIT);
+ }
+ if (LF_ISSET(DB_TXN_NOSYNC)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_TXN_NOSYNC);
+ else
+ F_CLR(dbenv, DB_ENV_TXN_NOSYNC);
+ }
+ if (LF_ISSET(DB_TXN_WRITE_NOSYNC)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_TXN_WRITE_NOSYNC);
+ else
+ F_CLR(dbenv, DB_ENV_TXN_WRITE_NOSYNC);
+ }
+ if (LF_ISSET(DB_YIELDCPU)) {
+ if (onoff)
+ F_SET(dbenv, DB_ENV_YIELDCPU);
+ else
+ F_CLR(dbenv, DB_ENV_YIELDCPU);
+ }
+ return (0);
+}
+
+static int
+__dbenv_set_data_dir(dbenv, dir)
+ DB_ENV *dbenv;
+ const char *dir;
+{
+ int ret;
+
+#define DATA_INIT_CNT 20 /* Start with 20 data slots. */
+ if (dbenv->db_data_dir == NULL) {
+ if ((ret = __os_calloc(dbenv, DATA_INIT_CNT,
+ sizeof(char **), &dbenv->db_data_dir)) != 0)
+ return (ret);
+ dbenv->data_cnt = DATA_INIT_CNT;
+ } else if (dbenv->data_next == dbenv->data_cnt - 1) {
+ dbenv->data_cnt *= 2;
+ if ((ret = __os_realloc(dbenv,
+ dbenv->data_cnt * sizeof(char **),
+ &dbenv->db_data_dir)) != 0)
+ return (ret);
+ }
+ return (__os_strdup(dbenv,
+ dir, &dbenv->db_data_dir[dbenv->data_next++]));
+}
+
+static void
+__dbenv_set_errcall(dbenv, errcall)
+ DB_ENV *dbenv;
+ void (*errcall) __P((const char *, char *));
+{
+ dbenv->db_errcall = errcall;
+}
+
+static void
+__dbenv_set_errfile(dbenv, errfile)
+ DB_ENV *dbenv;
+ FILE *errfile;
+{
+ dbenv->db_errfile = errfile;
+}
+
+static void
+__dbenv_set_errpfx(dbenv, errpfx)
+ DB_ENV *dbenv;
+ const char *errpfx;
+{
+ dbenv->db_errpfx = errpfx;
+}
+
+static int
+__dbenv_set_feedback(dbenv, feedback)
+ DB_ENV *dbenv;
+ void (*feedback) __P((DB_ENV *, int, int));
+{
+ dbenv->db_feedback = feedback;
+ return (0);
+}
+
+static void
+__dbenv_set_noticecall(dbenv, noticecall)
+ DB_ENV *dbenv;
+ void (*noticecall) __P((DB_ENV *, db_notices));
+{
+ dbenv->db_noticecall = noticecall;
+}
+
+static int
+__dbenv_set_paniccall(dbenv, paniccall)
+ DB_ENV *dbenv;
+ void (*paniccall) __P((DB_ENV *, int));
+{
+ dbenv->db_paniccall = paniccall;
+ return (0);
+}
+
+static int
+__dbenv_set_shm_key(dbenv, shm_key)
+ DB_ENV *dbenv;
+ long shm_key; /* !!!: really a key_t. */
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_shm_key");
+
+ dbenv->shm_key = shm_key;
+ return (0);
+}
+
+static int
+__dbenv_set_tas_spins(dbenv, tas_spins)
+ DB_ENV *dbenv;
+ u_int32_t tas_spins;
+{
+ dbenv->tas_spins = tas_spins;
+ return (0);
+}
+
+static int
+__dbenv_set_tmp_dir(dbenv, dir)
+ DB_ENV *dbenv;
+ const char *dir;
+{
+ if (dbenv->db_tmp_dir != NULL)
+ __os_free(dbenv, dbenv->db_tmp_dir);
+ return (__os_strdup(dbenv, dir, &dbenv->db_tmp_dir));
+}
+
+static int
+__dbenv_set_verbose(dbenv, which, onoff)
+ DB_ENV *dbenv;
+ u_int32_t which;
+ int onoff;
+{
+ switch (which) {
+ case DB_VERB_CHKPOINT:
+ case DB_VERB_DEADLOCK:
+ case DB_VERB_RECOVERY:
+ case DB_VERB_REPLICATION:
+ case DB_VERB_WAITSFOR:
+ if (onoff)
+ FLD_SET(dbenv->verbose, which);
+ else
+ FLD_CLR(dbenv->verbose, which);
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+/*
+ * __db_mi_env --
+ * Method illegally called with public environment.
+ *
+ * PUBLIC: int __db_mi_env __P((DB_ENV *, const char *));
+ */
+int
+__db_mi_env(dbenv, name)
+ DB_ENV *dbenv;
+ const char *name;
+{
+ __db_err(dbenv, "%s: method not permitted in shared environment", name);
+ return (EINVAL);
+}
+
+/*
+ * __db_mi_open --
+ * Method illegally called after open.
+ *
+ * PUBLIC: int __db_mi_open __P((DB_ENV *, const char *, int));
+ */
+int
+__db_mi_open(dbenv, name, after)
+ DB_ENV *dbenv;
+ const char *name;
+ int after;
+{
+ __db_err(dbenv, "%s: method not permitted %s open",
+ name, after ? "after" : "before");
+ return (EINVAL);
+}
+
+/*
+ * __db_env_config --
+ * Method or function called without required configuration.
+ *
+ * PUBLIC: int __db_env_config __P((DB_ENV *, char *, u_int32_t));
+ */
+int
+__db_env_config(dbenv, i, flags)
+ DB_ENV *dbenv;
+ char *i;
+ u_int32_t flags;
+{
+ char *sub;
+
+ switch (flags) {
+ case DB_INIT_LOCK:
+ sub = "locking";
+ break;
+ case DB_INIT_LOG:
+ sub = "logging";
+ break;
+ case DB_INIT_MPOOL:
+ sub = "memory pool";
+ break;
+ case DB_INIT_TXN:
+ sub = "transaction";
+ break;
+ default:
+ sub = "<unspecified>";
+ break;
+ }
+ __db_err(dbenv,
+ "%s interface requires an environment configured for the %s subsystem",
+ i, sub);
+ return (EINVAL);
+}
+
+static int
+__dbenv_set_rpc_server_noclnt(dbenv, cl, host, tsec, ssec, flags)
+ DB_ENV *dbenv;
+ void *cl;
+ const char *host;
+ long tsec, ssec;
+ u_int32_t flags;
+{
+ COMPQUIET(host, NULL);
+ COMPQUIET(cl, NULL);
+ COMPQUIET(tsec, 0);
+ COMPQUIET(ssec, 0);
+ COMPQUIET(flags, 0);
+
+ __db_err(dbenv,
+ "set_rpc_server method not permitted in non-RPC environment");
+ return (__db_eopnotsup(dbenv));
+}
diff --git a/bdb/env/env_open.c b/bdb/env/env_open.c
index 2007b4266c0..ae8399f61cd 100644
--- a/bdb/env/env_open.c
+++ b/bdb/env/env_open.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: env_open.c,v 11.34 2000/12/21 19:20:00 bostic Exp $";
+static const char revid[] = "$Id: env_open.c,v 11.111 2002/09/03 01:20:51 mjc Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -21,26 +21,30 @@ static const char revid[] = "$Id: env_open.c,v 11.34 2000/12/21 19:20:00 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "hash.h"
-#include "qam.h"
-#include "lock.h"
-#include "log.h"
-#include "mp.h"
-#include "txn.h"
-#include "clib_ext.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+#include "dbinc/fop.h"
-static int __dbenv_config __P((DB_ENV *, const char *, u_int32_t));
-static int __dbenv_refresh __P((DB_ENV *));
-static int __db_home __P((DB_ENV *, const char *, u_int32_t));
static int __db_parse __P((DB_ENV *, char *));
static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, DB_FH *));
+static int __dbenv_config __P((DB_ENV *, const char *, u_int32_t));
+static int __dbenv_iremove __P((DB_ENV *, const char *, u_int32_t));
+static int __dbenv_refresh __P((DB_ENV *, u_int32_t));
/*
* db_version --
* Return version information.
+ *
+ * EXTERN: char *db_version __P((int *, int *, int *));
*/
char *
db_version(majverp, minverp, patchp)
@@ -68,9 +72,11 @@ __dbenv_open(dbenv, db_home, flags, mode)
u_int32_t flags;
int mode;
{
- DB_ENV *rm_dbenv;
+ DB_MPOOL *dbmp;
int ret;
- u_int32_t init_flags;
+ u_int32_t init_flags, orig_flags;
+
+ orig_flags = dbenv->flags;
#undef OKFLAGS
#define OKFLAGS \
@@ -86,7 +92,7 @@ __dbenv_open(dbenv, db_home, flags, mode)
/*
* Flags saved in the init_flags field of the environment, representing
- * flags to DBENV->set_flags and DBENV->open that need to be set.
+ * flags to DB_ENV->set_flags and DB_ENV->open that need to be set.
*/
#define DB_INITENV_CDB 0x0001 /* DB_INIT_CDB */
#define DB_INITENV_CDB_ALLDB 0x0002 /* DB_INIT_CDB_ALLDB */
@@ -95,20 +101,36 @@ __dbenv_open(dbenv, db_home, flags, mode)
#define DB_INITENV_MPOOL 0x0010 /* DB_INIT_MPOOL */
#define DB_INITENV_TXN 0x0020 /* DB_INIT_TXN */
- if ((ret = __db_fchk(dbenv, "DBENV->open", flags, OKFLAGS)) != 0)
+ if ((ret = __db_fchk(dbenv, "DB_ENV->open", flags, OKFLAGS)) != 0)
return (ret);
if (LF_ISSET(DB_INIT_CDB) &&
- (ret = __db_fchk(dbenv, "DBENV->open", flags, OKFLAGS_CDB)) != 0)
+ (ret = __db_fchk(dbenv, "DB_ENV->open", flags, OKFLAGS_CDB)) != 0)
return (ret);
if ((ret = __db_fcchk(dbenv,
- "DBENV->open", flags, DB_PRIVATE, DB_SYSTEM_MEM)) != 0)
+ "DB_ENV->open", flags, DB_PRIVATE, DB_SYSTEM_MEM)) != 0)
return (ret);
- if ((ret = __db_fcchk(dbenv, "DBENV->open", flags, DB_JOINENV,
+ if ((ret = __db_fcchk(dbenv,
+ "DB_ENV->open", flags, DB_RECOVER, DB_RECOVER_FATAL)) != 0)
+ return (ret);
+ if ((ret = __db_fcchk(dbenv, "DB_ENV->open", flags, DB_JOINENV,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
DB_INIT_TXN | DB_PRIVATE)) != 0)
return (ret);
/*
+ * Currently we support one kind of mutex that is intra-process only,
+ * POSIX 1003.1 pthreads, because a variety of systems don't support
+ * the full pthreads API, and our only alternative is test-and-set.
+ */
+#ifdef HAVE_MUTEX_THREAD_ONLY
+ if (!LF_ISSET(DB_PRIVATE)) {
+ __db_err(dbenv,
+ "Berkeley DB library configured to support only DB_PRIVATE environments");
+ return (EINVAL);
+ }
+#endif
+
+ /*
* If we're doing recovery, destroy the environment so that we create
* all the regions from scratch. I'd like to reuse already created
* regions, but that's hard. We would have to create the environment
@@ -126,24 +148,24 @@ __dbenv_open(dbenv, db_home, flags, mode)
* not, we just want to nail any files that are left-over for whatever
* reason, from whatever session.
*/
- if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) {
- if ((ret = db_env_create(&rm_dbenv, 0)) != 0)
- return (ret);
- if ((ret = dbenv->remove(rm_dbenv, db_home, DB_FORCE)) != 0)
+ if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))
+ if ((ret = __dbenv_iremove(dbenv, db_home, DB_FORCE)) != 0 ||
+ (ret = __dbenv_refresh(dbenv, orig_flags)) != 0)
return (ret);
- }
/* Initialize the DB_ENV structure. */
if ((ret = __dbenv_config(dbenv, db_home, flags)) != 0)
goto err;
- /* Convert the DBENV->open flags to internal flags. */
+ /* Convert the DB_ENV->open flags to internal flags. */
if (LF_ISSET(DB_CREATE))
F_SET(dbenv, DB_ENV_CREATE);
if (LF_ISSET(DB_LOCKDOWN))
F_SET(dbenv, DB_ENV_LOCKDOWN);
if (LF_ISSET(DB_PRIVATE))
F_SET(dbenv, DB_ENV_PRIVATE);
+ if (LF_ISSET(DB_RECOVER_FATAL))
+ F_SET(dbenv, DB_ENV_FATAL);
if (LF_ISSET(DB_SYSTEM_MEM))
F_SET(dbenv, DB_ENV_SYSTEM_MEM);
if (LF_ISSET(DB_THREAD))
@@ -194,20 +216,6 @@ __dbenv_open(dbenv, db_home, flags, mode)
F_SET(dbenv, DB_ENV_CDB);
}
- /* Initialize the DB list, and its mutex if appropriate. */
- LIST_INIT(&dbenv->dblist);
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if ((ret = __db_mutex_alloc(dbenv,
- dbenv->reginfo, (MUTEX **)&dbenv->dblist_mutexp)) != 0)
- return (ret);
- if ((ret = __db_mutex_init(dbenv,
- dbenv->dblist_mutexp, 0, MUTEX_THREAD)) != 0) {
- __db_mutex_free(dbenv, dbenv->reginfo,
- dbenv->dblist_mutexp);
- return (ret);
- }
- }
-
/*
* Initialize the subsystems. Transactions imply logging but do not
* imply locking. While almost all applications want both locking
@@ -215,9 +223,24 @@ __dbenv_open(dbenv, db_home, flags, mode)
* process to want transactions for atomicity guarantees, but not
* necessarily need concurrency.
*/
+
if (LF_ISSET(DB_INIT_MPOOL))
if ((ret = __memp_open(dbenv)) != 0)
goto err;
+
+#ifdef HAVE_CRYPTO
+ /*
+ * Initialize the ciphering area prior to any running of recovery so
+ * that we can initialize the keys, etc. before recovery.
+ *
+ * !!!
+ * This must be after the mpool init, but before the log initialization
+ * because log_open may attempt to run log_recover during its open.
+ */
+ if ((ret = __crypto_region_init(dbenv)) != 0)
+ goto err;
+#endif
+
if (LF_ISSET(DB_INIT_LOG | DB_INIT_TXN))
if ((ret = __log_open(dbenv)) != 0)
goto err;
@@ -232,38 +255,98 @@ __dbenv_open(dbenv, db_home, flags, mode)
* If the application is running with transactions, initialize
* the function tables.
*/
- if ((ret = __bam_init_recover(dbenv)) != 0)
+ if ((ret = __bam_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
- if ((ret = __crdel_init_recover(dbenv)) != 0)
+ if ((ret = __crdel_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
- if ((ret = __db_init_recover(dbenv)) != 0)
+ if ((ret = __db_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
- if ((ret = __ham_init_recover(dbenv)) != 0)
+ if ((ret = __dbreg_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
- if ((ret = __log_init_recover(dbenv)) != 0)
+ if ((ret = __fop_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
- if ((ret = __qam_init_recover(dbenv)) != 0)
+ if ((ret = __ham_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
- if ((ret = __txn_init_recover(dbenv)) != 0)
+ if ((ret = __qam_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
-
- /*
- * If the application specified their own recovery
- * initialization function, call it.
- */
- if (dbenv->db_recovery_init != NULL &&
- (ret = dbenv->db_recovery_init(dbenv)) != 0)
+ if ((ret = __txn_init_recover(dbenv, &dbenv->recover_dtab,
+ &dbenv->recover_dtab_size)) != 0)
goto err;
/* Perform recovery for any previous run. */
if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
- (ret = __db_apprec(dbenv,
+ (ret = __db_apprec(dbenv, NULL,
LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
goto err;
}
+
+ /* Initialize the replication area just in case. */
+ if ((ret = __rep_region_init(dbenv)) != 0)
+ goto err;
+
+ /*
+ * Initialize the DB list, and its mutex as necessary. If the env
+ * handle isn't free-threaded we don't need a mutex because there
+ * will never be more than a single DB handle on the list. If the
+ * mpool wasn't initialized, then we can't ever open a DB handle.
+ *
+ * We also need to initialize the MT mutex as necessary, so do them
+ * both. If we error, __dbenv_refresh() will clean up.
+ *
+ * !!!
+ * This must come after the __memp_open call above because if we are
+ * recording mutexes for system resources, we will do it in the mpool
+ * region for environments and db handles. So, the mpool region must
+ * already be initialized.
+ */
+ LIST_INIT(&dbenv->dblist);
+ if (F_ISSET(dbenv, DB_ENV_THREAD) && LF_ISSET(DB_INIT_MPOOL)) {
+ dbmp = dbenv->mp_handle;
+ if ((ret = __db_mutex_setup(
+ dbenv, dbmp->reginfo, &dbenv->dblist_mutexp,
+ MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+ goto err;
+ if ((ret = __db_mutex_setup(
+ dbenv, dbmp->reginfo, &dbenv->mt_mutexp,
+ MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+ goto err;
+ }
+
+ /*
+ * If we've created the regions, are running with transactions, and did
+ * not just run recovery, we need to log the fact that the transaction
+ * IDs got reset.
+ *
+ * If we ran recovery, there may be prepared-but-not-yet-committed
+ * transactions that need to be resolved. Recovery resets the minimum
+ * transaction ID and logs the reset if that's appropriate, so we
+ * don't need to do anything here in the recover case.
+ */
+ if (TXN_ON(dbenv) &&
+ F_ISSET((REGINFO *)dbenv->reginfo, REGION_CREATE) &&
+ !LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
+ (ret = __txn_reset(dbenv)) != 0)
+ goto err;
+
return (0);
-err: (void)__dbenv_refresh(dbenv);
+err: /* If we fail after creating the regions, remove them. */
+ if (dbenv->reginfo != NULL &&
+ F_ISSET((REGINFO *)dbenv->reginfo, REGION_CREATE)) {
+ ret = __db_panic(dbenv, ret);
+
+ (void)__dbenv_refresh(dbenv, orig_flags);
+ (void)__dbenv_iremove(dbenv, db_home, DB_FORCE);
+ }
+ (void)__dbenv_refresh(dbenv, orig_flags);
+
return (ret);
}
@@ -281,40 +364,42 @@ __dbenv_remove(dbenv, db_home, flags)
{
int ret, t_ret;
+ ret = __dbenv_iremove(dbenv, db_home, flags);
+
+ if ((t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __dbenv_iremove --
+ * Discard an environment, internal version.
+ */
+static int
+__dbenv_iremove(dbenv, db_home, flags)
+ DB_ENV *dbenv;
+ const char *db_home;
+ u_int32_t flags;
+{
+ int ret;
+
#undef OKFLAGS
#define OKFLAGS \
DB_FORCE | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
/* Validate arguments. */
- if ((ret = __db_fchk(dbenv, "DBENV->remove", flags, OKFLAGS)) != 0)
- goto err;
+ if ((ret = __db_fchk(dbenv, "DB_ENV->remove", flags, OKFLAGS)) != 0)
+ return (ret);
- /*
- * A hard-to-debug error is calling DBENV->remove after open. That's
- * not legal. You have to close the original, already opened handle
- * and then allocate a new DBENV handle to use for DBENV->remove.
- */
- if (F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
- __db_err(dbenv,
- "DBENV handle opened, not usable for remove method.");
- return (EINVAL);
- }
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->remove");
/* Initialize the DB_ENV structure. */
if ((ret = __dbenv_config(dbenv, db_home, flags)) != 0)
- goto err;
+ return (ret);
/* Remove the environment. */
- ret = __db_e_remove(dbenv, LF_ISSET(DB_FORCE) ? 1 : 0);
-
- /* Discard any resources we've acquired. */
-err: if ((t_ret = __dbenv_refresh(dbenv)) != 0 && ret == 0)
- ret = t_ret;
-
- memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV));
- __os_free(dbenv, sizeof(DB_ENV));
-
- return (ret);
+ return (__db_e_remove(dbenv, flags));
}
/*
@@ -329,53 +414,48 @@ __dbenv_config(dbenv, db_home, flags)
{
FILE *fp;
int ret;
- char *lp, buf[MAXPATHLEN * 2];
+ char *p, buf[256];
- /* Set the database home. */
+ /*
+ * Set the database home. Do this before calling __db_appname,
+ * it uses the home directory.
+ */
if ((ret = __db_home(dbenv, db_home, flags)) != 0)
return (ret);
- /*
- * Parse the config file.
- *
- * !!!
- * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
- * the latter isn't standard, and we're manipulating strings handed
- * us by the application.
- */
- if (dbenv->db_home != NULL) {
-#define CONFIG_NAME "/DB_CONFIG"
- if (strlen(dbenv->db_home) +
- strlen(CONFIG_NAME) + 1 > sizeof(buf)) {
- ret = ENAMETOOLONG;
- return (ret);
- }
- (void)strcpy(buf, dbenv->db_home);
- (void)strcat(buf, CONFIG_NAME);
- if ((fp = fopen(buf, "r")) != NULL) {
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- if ((lp = strchr(buf, '\n')) == NULL) {
- __db_err(dbenv,
- "%s: line too long", CONFIG_NAME);
- (void)fclose(fp);
- ret = EINVAL;
- return (ret);
- }
- *lp = '\0';
- if (buf[0] == '\0' ||
- buf[0] == '#' || isspace((int)buf[0]))
- continue;
-
- if ((ret = __db_parse(dbenv, buf)) != 0) {
- (void)fclose(fp);
- return (ret);
- }
+ /* Parse the config file. */
+ if ((ret =
+ __db_appname(dbenv, DB_APP_NONE, "DB_CONFIG", 0, NULL, &p)) != 0)
+ return (ret);
+
+ fp = fopen(p, "r");
+ __os_free(dbenv, p);
+
+ if (fp != NULL) {
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if ((p = strchr(buf, '\n')) != NULL)
+ *p = '\0';
+ else if (strlen(buf) + 1 == sizeof(buf)) {
+ __db_err(dbenv, "DB_CONFIG: line too long");
+ (void)fclose(fp);
+ return (EINVAL);
+ }
+ if (buf[0] == '\0' ||
+ buf[0] == '#' || isspace((int)buf[0]))
+ continue;
+
+ if ((ret = __db_parse(dbenv, buf)) != 0) {
+ (void)fclose(fp);
+ return (ret);
}
- (void)fclose(fp);
}
+ (void)fclose(fp);
}
- /* Set up the tmp directory path. */
+ /*
+ * If no temporary directory path was specified in the config file,
+ * choose one.
+ */
if (dbenv->db_tmp_dir == NULL && (ret = __os_tmpdir(dbenv, flags)) != 0)
return (ret);
@@ -383,17 +463,12 @@ __dbenv_config(dbenv, db_home, flags)
* The locking file descriptor is rarely on. Set the fd to -1, not
* because it's ever tested, but to make sure we catch mistakes.
*/
- if ((ret =
- __os_calloc(dbenv,
- 1, sizeof(*dbenv->lockfhp), &dbenv->lockfhp)) != 0)
+ if ((ret = __os_calloc(
+ dbenv, 1, sizeof(*dbenv->lockfhp), &dbenv->lockfhp)) != 0)
return (ret);
dbenv->lockfhp->fd = -1;
- /*
- * Flag that the DB_ENV structure has been initialized. Note, this
- * must be set before calling into the subsystems as it's used during
- * file naming.
- */
+ /* Flag that the DB_ENV structure has been initialized. */
F_SET(dbenv, DB_ENV_OPEN_CALLED);
return (0);
@@ -410,66 +485,149 @@ __dbenv_close(dbenv, flags)
DB_ENV *dbenv;
u_int32_t flags;
{
- int ret;
+ char **p;
+ int ret, t_ret;
COMPQUIET(flags, 0);
PANIC_CHECK(dbenv);
+ ret = 0;
+
+ /*
+ * Before checking the reference count, we have to see if we
+ * were in the middle of restoring transactions and need to
+ * close the open files.
+ */
+ if (TXN_ON(dbenv) && (t_ret = __txn_preclose(dbenv)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (dbenv->rep_handle != NULL &&
+ (t_ret = __rep_preclose(dbenv, 1)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (dbenv->db_ref != 0) {
+ __db_err(dbenv,
+ "Database handles open during environment close");
+ if (ret == 0)
+ ret = EINVAL;
+ }
- ret = __dbenv_refresh(dbenv);
+ /*
+ * Detach from the regions and undo the allocations done by
+ * DB_ENV->open.
+ */
+ if ((t_ret = __dbenv_refresh(dbenv, 0)) != 0 && ret == 0)
+ ret = t_ret;
- /* Discard the structure if we allocated it. */
- if (!F_ISSET(dbenv, DB_ENV_USER_ALLOC)) {
- memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV));
- __os_free(dbenv, sizeof(DB_ENV));
+ /* Do per-subsystem destruction. */
+ __lock_dbenv_close(dbenv); /* void */
+ if ((t_ret = __rep_dbenv_close(dbenv)) != 0 && ret == 0)
+ ret = t_ret;
+
+#ifdef HAVE_CRYPTO
+ if ((t_ret = __crypto_dbenv_close(dbenv)) != 0 && ret == 0)
+ ret = t_ret;
+#endif
+
+ /* Release any string-based configuration parameters we've copied. */
+ if (dbenv->db_log_dir != NULL)
+ __os_free(dbenv, dbenv->db_log_dir);
+ if (dbenv->db_tmp_dir != NULL)
+ __os_free(dbenv, dbenv->db_tmp_dir);
+ if (dbenv->db_data_dir != NULL) {
+ for (p = dbenv->db_data_dir; *p != NULL; ++p)
+ __os_free(dbenv, *p);
+ __os_free(dbenv, dbenv->db_data_dir);
}
+ /* Discard the structure. */
+ memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV));
+ __os_free(NULL, dbenv);
+
return (ret);
}
/*
* __dbenv_refresh --
- * Refresh the DB_ENV structure, releasing any allocated resources.
+ * Refresh the DB_ENV structure, releasing resources allocated by
+ * DB_ENV->open, and returning it to the state it was in just before
+ * open was called. (Note that this means that any state set by
+ * pre-open configuration functions must be preserved.)
*/
static int
-__dbenv_refresh(dbenv)
+__dbenv_refresh(dbenv, orig_flags)
DB_ENV *dbenv;
+ u_int32_t orig_flags;
{
+ DB_MPOOL *dbmp;
int ret, t_ret;
- char **p;
ret = 0;
/*
* Close subsystems, in the reverse order they were opened (txn
* must be first, it may want to discard locks and flush the log).
+ *
+ * !!!
+ * Note that these functions, like all of __dbenv_refresh, only undo
+ * the effects of __dbenv_open. Functions that undo work done by
+ * db_env_create or by a configurator function should go in
+ * __dbenv_close.
*/
- if (TXN_ON(dbenv)) {
- if ((t_ret = __txn_close(dbenv)) != 0 && ret == 0)
- ret = t_ret;
- }
+ if (TXN_ON(dbenv) &&
+ (t_ret = __txn_dbenv_refresh(dbenv)) != 0 && ret == 0)
+ ret = t_ret;
- if (LOCKING_ON(dbenv)) {
- if ((t_ret = __lock_close(dbenv)) != 0 && ret == 0)
- ret = t_ret;
- }
- __lock_dbenv_close(dbenv);
+ if (LOGGING_ON(dbenv) &&
+ (t_ret = __log_dbenv_refresh(dbenv)) != 0 && ret == 0)
+ ret = t_ret;
- if (LOGGING_ON(dbenv)) {
- if ((t_ret = __log_close(dbenv)) != 0 && ret == 0)
- ret = t_ret;
+ /*
+ * Locking should come after logging, because closing log results
+ * in files closing which may require locks being released.
+ */
+ if (LOCKING_ON(dbenv) &&
+ (t_ret = __lock_dbenv_refresh(dbenv)) != 0 && ret == 0)
+ ret = t_ret;
+
+ /*
+ * Discard DB list and its mutex.
+ * Discard the MT mutex.
+ *
+ * !!!
+ * This must be done before we close the mpool region because we
+ * may have allocated the DB handle mutex in the mpool region.
+ * It must be done *after* we close the log region, though, because
+ * we close databases and try to acquire the mutex when we close
+ * log file handles. Ick.
+ */
+ LIST_INIT(&dbenv->dblist);
+ if (dbenv->dblist_mutexp != NULL) {
+ dbmp = dbenv->mp_handle;
+ __db_mutex_free(dbenv, dbmp->reginfo, dbenv->dblist_mutexp);
+ }
+ if (dbenv->mt_mutexp != NULL) {
+ dbmp = dbenv->mp_handle;
+ __db_mutex_free(dbenv, dbmp->reginfo, dbenv->mt_mutexp);
+ }
+ if (dbenv->mt != NULL) {
+ __os_free(dbenv, dbenv->mt);
+ dbenv->mt = NULL;
}
if (MPOOL_ON(dbenv)) {
- if ((t_ret = __memp_close(dbenv)) != 0 && ret == 0)
+ /*
+ * If it's a private environment, flush the contents to disk.
+ * Recovery would have put everything back together, but it's
+ * faster and cleaner to flush instead.
+ */
+ if (F_ISSET(dbenv, DB_ENV_PRIVATE) &&
+ (t_ret = dbenv->memp_sync(dbenv, NULL)) != 0 && ret == 0)
+ ret = t_ret;
+ if ((t_ret = __memp_dbenv_refresh(dbenv)) != 0 && ret == 0)
ret = t_ret;
}
- /* Discard DB list and its mutex. */
- LIST_INIT(&dbenv->dblist);
- if (dbenv->dblist_mutexp != NULL)
- __db_mutex_free(dbenv, dbenv->reginfo, dbenv->dblist_mutexp);
-
/* Detach from the region. */
if (dbenv->reginfo != NULL) {
if ((t_ret = __db_e_detach(dbenv, 0)) != 0 && ret == 0)
@@ -481,51 +639,26 @@ __dbenv_refresh(dbenv)
*/
}
- /* Clean up the structure. */
- dbenv->db_panic = 0;
-
+ /* Undo changes and allocations done by __dbenv_open. */
if (dbenv->db_home != NULL) {
- __os_freestr(dbenv->db_home);
+ __os_free(dbenv, dbenv->db_home);
dbenv->db_home = NULL;
}
- if (dbenv->db_log_dir != NULL) {
- __os_freestr(dbenv->db_log_dir);
- dbenv->db_log_dir = NULL;
- }
- if (dbenv->db_tmp_dir != NULL) {
- __os_freestr(dbenv->db_tmp_dir);
- dbenv->db_tmp_dir = NULL;
- }
- if (dbenv->db_data_dir != NULL) {
- for (p = dbenv->db_data_dir; *p != NULL; ++p)
- __os_freestr(*p);
- __os_free(dbenv->db_data_dir,
- dbenv->data_cnt * sizeof(char **));
- dbenv->db_data_dir = NULL;
- }
- dbenv->data_cnt = dbenv->data_next = 0;
dbenv->db_mode = 0;
if (dbenv->lockfhp != NULL) {
- __os_free(dbenv->lockfhp, sizeof(*dbenv->lockfhp));
+ __os_free(dbenv, dbenv->lockfhp);
dbenv->lockfhp = NULL;
}
- if (dbenv->dtab != NULL) {
- __os_free(dbenv->dtab,
- dbenv->dtab_size * sizeof(dbenv->dtab[0]));
- dbenv->dtab = NULL;
- dbenv->dtab_size = 0;
+ if (dbenv->recover_dtab != NULL) {
+ __os_free(dbenv, dbenv->recover_dtab);
+ dbenv->recover_dtab = NULL;
+ dbenv->recover_dtab_size = 0;
}
- dbenv->mp_mmapsize = 0;
- dbenv->links.tqe_next = NULL;
- dbenv->links.tqe_prev = NULL;
- dbenv->xa_rmid = 0;
- dbenv->xa_txn = 0;
-
- F_CLR(dbenv, ~(DB_ENV_STANDALONE | DB_ENV_USER_ALLOC));
+ dbenv->flags = orig_flags;
return (ret);
}
@@ -550,34 +683,33 @@ __dbenv_refresh(dbenv)
/*
* __db_appname --
* Given an optional DB environment, directory and file name and type
- * of call, build a path based on the DBENV->open rules, and return
+ * of call, build a path based on the DB_ENV->open rules, and return
* it in allocated space.
*
* PUBLIC: int __db_appname __P((DB_ENV *, APPNAME,
- * PUBLIC: const char *, const char *, u_int32_t, DB_FH *, char **));
+ * PUBLIC: const char *, u_int32_t, DB_FH *, char **));
*/
int
-__db_appname(dbenv, appname, dir, file, tmp_oflags, fhp, namep)
+__db_appname(dbenv, appname, file, tmp_oflags, fhp, namep)
DB_ENV *dbenv;
APPNAME appname;
- const char *dir, *file;
+ const char *file;
u_int32_t tmp_oflags;
DB_FH *fhp;
char **namep;
{
- DB_ENV etmp;
size_t len, str_len;
- int data_entry, ret, slash, tmp_create, tmp_free;
- const char *a, *b, *c;
+ int data_entry, ret, slash, tmp_create;
+ const char *a, *b;
char *p, *str;
- a = b = c = NULL;
+ a = b = NULL;
data_entry = -1;
- tmp_create = tmp_free = 0;
+ tmp_create = 0;
/*
- * We don't return a name when creating temporary files, just a
- * file handle. Default to an error now.
+ * We don't return a name when creating temporary files, just a file
+ * handle. Default to an error now.
*/
if (fhp != NULL)
F_CLR(fhp, DB_FH_VALID);
@@ -586,118 +718,49 @@ __db_appname(dbenv, appname, dir, file, tmp_oflags, fhp, namep)
/*
* Absolute path names are never modified. If the file is an absolute
- * path, we're done. If the directory is, simply append the file and
- * return.
+ * path, we're done.
*/
if (file != NULL && __os_abspath(file))
return (__os_strdup(dbenv, file, namep));
- if (dir != NULL && __os_abspath(dir)) {
- a = dir;
- goto done;
- }
- /*
- * DB_ENV DIR APPNAME RESULT
- * -------------------------------------------
- * null null none <tmp>/file
- * null set none DIR/file
- * set null none DB_HOME/file
- * set set none DB_HOME/DIR/file
- *
- * DB_ENV FILE APPNAME RESULT
- * -------------------------------------------
- * null null DB_APP_DATA <tmp>/<create>
- * null set DB_APP_DATA ./file
- * set null DB_APP_DATA <tmp>/<create>
- * set set DB_APP_DATA DB_HOME/DB_DATA_DIR/file
- *
- * DB_ENV DIR APPNAME RESULT
- * -------------------------------------------
- * null null DB_APP_LOG <tmp>/file
- * null set DB_APP_LOG DIR/file
- * set null DB_APP_LOG DB_HOME/DB_LOG_DIR/file
- * set set DB_APP_LOG DB_HOME/DB_LOG_DIR/DIR/file
- *
- * DB_ENV APPNAME RESULT
- * -------------------------------------------
- * null DB_APP_TMP* <tmp>/<create>
- * set DB_APP_TMP* DB_HOME/DB_TMP_DIR/<create>
+ /* Everything else is relative to the environment home. */
+ if (dbenv != NULL)
+ a = dbenv->db_home;
+
+retry: /*
+ * DB_APP_NONE:
+ * DB_HOME/file
+ * DB_APP_DATA:
+ * DB_HOME/DB_DATA_DIR/file
+ * DB_APP_LOG:
+ * DB_HOME/DB_LOG_DIR/file
+ * DB_APP_TMP:
+ * DB_HOME/DB_TMP_DIR/<create>
*/
-retry: switch (appname) {
+ switch (appname) {
case DB_APP_NONE:
- if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
- if (dir == NULL)
- goto tmp;
- a = dir;
- } else {
- a = dbenv->db_home;
- b = dir;
- }
break;
case DB_APP_DATA:
- if (dir != NULL) {
- __db_err(dbenv,
- "DB_APP_DATA: illegal directory specification");
- return (EINVAL);
- }
-
- if (file == NULL) {
- tmp_create = 1;
- goto tmp;
- }
- if (dbenv != NULL && F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
- a = dbenv->db_home;
- if (dbenv->db_data_dir != NULL &&
- (b = dbenv->db_data_dir[++data_entry]) == NULL) {
- data_entry = -1;
- b = dbenv->db_data_dir[0];
- }
+ if (dbenv != NULL && dbenv->db_data_dir != NULL &&
+ (b = dbenv->db_data_dir[++data_entry]) == NULL) {
+ data_entry = -1;
+ b = dbenv->db_data_dir[0];
}
break;
case DB_APP_LOG:
- if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
- if (dir == NULL)
- goto tmp;
- a = dir;
- } else {
- a = dbenv->db_home;
+ if (dbenv != NULL)
b = dbenv->db_log_dir;
- c = dir;
- }
break;
case DB_APP_TMP:
- if (dir != NULL || file != NULL) {
- __db_err(dbenv,
- "DB_APP_TMP: illegal directory or file specification");
- return (EINVAL);
- }
-
- tmp_create = 1;
- if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED))
- goto tmp;
- else {
- a = dbenv->db_home;
+ if (dbenv != NULL)
b = dbenv->db_tmp_dir;
- }
+ tmp_create = 1;
break;
}
- /* Reference a file from the appropriate temporary directory. */
- if (0) {
-tmp: if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
- memset(&etmp, 0, sizeof(etmp));
- if ((ret = __os_tmpdir(&etmp, DB_USE_ENVIRON)) != 0)
- return (ret);
- tmp_free = 1;
- a = etmp.db_tmp_dir;
- } else
- a = dbenv->db_tmp_dir;
- }
-
-done: len =
+ len =
(a == NULL ? 0 : strlen(a) + 1) +
(b == NULL ? 0 : strlen(b) + 1) +
- (c == NULL ? 0 : strlen(c) + 1) +
(file == NULL ? 0 : strlen(file) + 1);
/*
@@ -707,11 +770,8 @@ done: len =
*/
#define DB_TRAIL "BDBXXXXXX"
str_len = len + sizeof(DB_TRAIL) + 10;
- if ((ret = __os_malloc(dbenv, str_len, NULL, &str)) != 0) {
- if (tmp_free)
- __os_freestr(etmp.db_tmp_dir);
+ if ((ret = __os_malloc(dbenv, str_len, &str)) != 0)
return (ret);
- }
slash = 0;
p = str;
@@ -720,31 +780,25 @@ done: len =
DB_ADDSTR(file);
*p = '\0';
- /* Discard any space allocated to find the temp directory. */
- if (tmp_free) {
- __os_freestr(etmp.db_tmp_dir);
- tmp_free = 0;
- }
-
/*
* If we're opening a data file, see if it exists. If it does,
* return it, otherwise, try and find another one to open.
*/
- if (data_entry != -1 && __os_exists(str, NULL) != 0) {
- __os_free(str, str_len);
- a = b = c = NULL;
+ if (__os_exists(str, NULL) != 0 && data_entry != -1) {
+ __os_free(dbenv, str);
+ b = NULL;
goto retry;
}
/* Create the file if so requested. */
if (tmp_create &&
(ret = __db_tmp_open(dbenv, tmp_oflags, str, fhp)) != 0) {
- __os_free(str, str_len);
+ __os_free(dbenv, str);
return (ret);
}
if (namep == NULL)
- __os_free(str, str_len);
+ __os_free(dbenv, str);
else
*namep = str;
return (0);
@@ -753,8 +807,10 @@ done: len =
/*
* __db_home --
* Find the database home.
+ *
+ * PUBLIC: int __db_home __P((DB_ENV *, const char *, u_int32_t));
*/
-static int
+int
__db_home(dbenv, db_home, flags)
DB_ENV *dbenv;
const char *db_home;
@@ -779,6 +835,13 @@ __db_home(dbenv, db_home, flags)
return (p == NULL ? 0 : __os_strdup(dbenv, p, &dbenv->db_home));
}
+#define __DB_OVFL(v, max) \
+ if (v > max) { \
+ __v = v; \
+ __max = max; \
+ goto toobig; \
+ }
+
/*
* __db_parse --
* Parse a single NAME VALUE pair.
@@ -788,7 +851,7 @@ __db_parse(dbenv, s)
DB_ENV *dbenv;
char *s;
{
- u_long v1, v2, v3;
+ u_long __max, __v, v1, v2, v3;
u_int32_t flags;
char *name, *p, *value, v4;
@@ -831,7 +894,11 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
if (!strcasecmp(name, "set_cachesize")) {
if (sscanf(value, "%lu %lu %lu %c", &v1, &v2, &v3, &v4) != 3)
goto badarg;
- return (dbenv->set_cachesize(dbenv, v1, v2, v3));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ __DB_OVFL(v2, UINT32_T_MAX);
+ __DB_OVFL(v3, 10000);
+ return (dbenv->set_cachesize(
+ dbenv, (u_int32_t)v1, (u_int32_t)v2, (int)v3));
}
if (!strcasecmp(name, "set_data_dir") ||
@@ -844,23 +911,49 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
if (!strcasecmp(value, "db_cdb_alldb"))
return (dbenv->set_flags(dbenv, DB_CDB_ALLDB, 1));
+ if (!strcasecmp(value, "db_direct_db"))
+ return (dbenv->set_flags(dbenv, DB_DIRECT_DB, 1));
+ if (!strcasecmp(value, "db_direct_log"))
+ return (dbenv->set_flags(dbenv, DB_DIRECT_LOG, 1));
+ if (!strcasecmp(value, "db_nolocking"))
+ return (dbenv->set_flags(dbenv, DB_NOLOCKING, 1));
if (!strcasecmp(value, "db_nommap"))
return (dbenv->set_flags(dbenv, DB_NOMMAP, 1));
+ if (!strcasecmp(value, "db_overwrite"))
+ return (dbenv->set_flags(dbenv, DB_OVERWRITE, 1));
+ if (!strcasecmp(value, "db_nopanic"))
+ return (dbenv->set_flags(dbenv, DB_NOPANIC, 1));
+ if (!strcasecmp(value, "db_region_init"))
+ return (dbenv->set_flags(dbenv, DB_REGION_INIT, 1));
if (!strcasecmp(value, "db_txn_nosync"))
return (dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1));
+ if (!strcasecmp(value, "db_txn_write_nosync"))
+ return (
+ dbenv->set_flags(dbenv, DB_TXN_WRITE_NOSYNC, 1));
+ if (!strcasecmp(value, "db_yieldcpu"))
+ return (dbenv->set_flags(dbenv, DB_YIELDCPU, 1));
goto badarg;
}
if (!strcasecmp(name, "set_lg_bsize")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_lg_bsize(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lg_bsize(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_lg_max")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_lg_max(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lg_max(dbenv, (u_int32_t)v1));
+ }
+
+ if (!strcasecmp(name, "set_lg_regionmax")) {
+ if (sscanf(value, "%lu %c", &v1, &v4) != 1)
+ goto badarg;
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lg_regionmax(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_lg_dir") ||
@@ -872,6 +965,14 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
goto badarg;
if (!strcasecmp(value, "db_lock_default"))
flags = DB_LOCK_DEFAULT;
+ else if (!strcasecmp(value, "db_lock_expire"))
+ flags = DB_LOCK_EXPIRE;
+ else if (!strcasecmp(value, "db_lock_maxlocks"))
+ flags = DB_LOCK_MAXLOCKS;
+ else if (!strcasecmp(value, "db_lock_minlocks"))
+ flags = DB_LOCK_MINLOCKS;
+ else if (!strcasecmp(value, "db_lock_minwrite"))
+ flags = DB_LOCK_MINWRITE;
else if (!strcasecmp(value, "db_lock_oldest"))
flags = DB_LOCK_OLDEST;
else if (!strcasecmp(value, "db_lock_random"))
@@ -886,37 +987,51 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
if (!strcasecmp(name, "set_lk_max")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_lk_max(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lk_max(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_lk_max_locks")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_lk_max_locks(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lk_max_locks(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_lk_max_lockers")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_lk_max_lockers(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lk_max_lockers(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_lk_max_objects")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_lk_max_objects(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_lk_max_objects(dbenv, (u_int32_t)v1));
+ }
+
+ if (!strcasecmp(name, "set_lock_timeout")) {
+ if (sscanf(value, "%lu %c", &v1, &v4) != 1)
+ goto badarg;
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_timeout(
+ dbenv, (u_int32_t)v1, DB_SET_LOCK_TIMEOUT));
}
if (!strcasecmp(name, "set_mp_mmapsize")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_mp_mmapsize(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_mp_mmapsize(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_region_init")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1 || v1 != 1)
goto badarg;
- return (db_env_set_region_init(v1));
+ return (dbenv->set_flags(
+ dbenv, DB_REGION_INIT, v1 == 0 ? 0 : 1));
}
if (!strcasecmp(name, "set_shm_key")) {
@@ -928,7 +1043,8 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
if (!strcasecmp(name, "set_tas_spins")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (db_env_set_tas_spins(v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_tas_spins(dbenv, (u_int32_t)v1));
}
if (!strcasecmp(name, "set_tmp_dir") ||
@@ -938,7 +1054,16 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
if (!strcasecmp(name, "set_tx_max")) {
if (sscanf(value, "%lu %c", &v1, &v4) != 1)
goto badarg;
- return (dbenv->set_tx_max(dbenv, v1));
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_tx_max(dbenv, (u_int32_t)v1));
+ }
+
+ if (!strcasecmp(name, "set_txn_timeout")) {
+ if (sscanf(value, "%lu %c", &v1, &v4) != 1)
+ goto badarg;
+ __DB_OVFL(v1, UINT32_T_MAX);
+ return (dbenv->set_timeout(
+ dbenv, (u_int32_t)v1, DB_SET_TXN_TIMEOUT));
}
if (!strcasecmp(name, "set_verbose")) {
@@ -963,6 +1088,10 @@ illegal: __db_err(dbenv, "mis-formatted name-value pair: %s", s);
badarg: __db_err(dbenv, "incorrect arguments for name-value pair: %s", s);
return (EINVAL);
+
+toobig: __db_err(dbenv,
+ "%s: %lu larger than maximum value %lu", s, __v, __max);
+ return (EINVAL);
}
/*
@@ -976,7 +1105,7 @@ __db_tmp_open(dbenv, tmp_oflags, path, fhp)
char *path;
DB_FH *fhp;
{
- u_long pid;
+ u_int32_t id;
int mode, isdir, ret;
const char *p;
char *trv;
@@ -1001,12 +1130,9 @@ __db_tmp_open(dbenv, tmp_oflags, path, fhp)
for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p)
;
- /*
- * Replace the X's with the process ID. Pid should be a pid_t,
- * but we use unsigned long for portability.
- */
- for (pid = getpid(); *--trv == 'X'; pid /= 10)
- switch (pid % 10) {
+ /* Replace the X's with the process ID. */
+ for (__os_id(&id); *--trv == 'X'; id /= 10)
+ switch (id % 10) {
case 0: *trv = '0'; break;
case 1: *trv = '1'; break;
case 2: *trv = '2'; break;
@@ -1026,7 +1152,8 @@ __db_tmp_open(dbenv, tmp_oflags, path, fhp)
/* Loop, trying to open a file. */
for (;;) {
if ((ret = __os_open(dbenv, path,
- tmp_oflags | DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp)) == 0)
+ tmp_oflags | DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_TEMP,
+ mode, fhp)) == 0)
return (0);
/*
diff --git a/bdb/env/env_recover.c b/bdb/env/env_recover.c
index bc5e4760584..fbe3b345b0d 100644
--- a/bdb/env/env_recover.c
+++ b/bdb/env/env_recover.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: env_recover.c,v 11.33 2001/01/04 22:38:42 ubell Exp $";
+ "$Id: env_recover.c,v 11.97 2002/08/22 17:43:22 margo Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -32,37 +32,65 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_dispatch.h"
-#include "db_am.h"
-#include "log.h"
-#include "txn.h"
-
-static float __lsn_diff __P((DB_LSN *, DB_LSN *, DB_LSN *, u_int32_t, int));
-static int __log_earliest __P((DB_ENV *, int32_t *, DB_LSN *));
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+#include "dbinc/db_am.h"
+
+static int __log_backup __P((DB_ENV *, DB_LOGC *, DB_LSN *, DB_LSN *));
+static int __log_earliest __P((DB_ENV *, DB_LOGC *, int32_t *, DB_LSN *));
+static double __lsn_diff __P((DB_LSN *, DB_LSN *, DB_LSN *, u_int32_t, int));
/*
* __db_apprec --
- * Perform recovery.
+ * Perform recovery. If max_lsn is non-NULL, then we are trying
+ * to synchronize this system up with another system that has a max
+ * LSN of max_lsn, so we need to roll back sufficiently far for that
+ * to work. See __log_backup for details.
*
- * PUBLIC: int __db_apprec __P((DB_ENV *, u_int32_t));
+ * PUBLIC: int __db_apprec __P((DB_ENV *, DB_LSN *, u_int32_t));
*/
int
-__db_apprec(dbenv, flags)
+__db_apprec(dbenv, max_lsn, flags)
DB_ENV *dbenv;
+ DB_LSN *max_lsn;
u_int32_t flags;
{
DBT data;
- DB_LSN ckp_lsn, first_lsn, last_lsn, lowlsn, lsn, open_lsn;
+ DB_LOGC *logc;
+ DB_LSN ckp_lsn, first_lsn, last_lsn, lowlsn, lsn, stop_lsn;
DB_TXNREGION *region;
__txn_ckp_args *ckp_args;
time_t now, tlow;
- float nfiles;
- int32_t low;
- int is_thread, progress, ret;
+ int32_t log_size, low;
+ double nfiles;
+ int have_rec, is_thread, progress, ret, t_ret;
+ int (**dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t dtabsize;
+ u_int32_t hi_txn, lockid, txnid;
+ char *p, *pass, t1[60], t2[60];
void *txninfo;
- COMPQUIET(nfiles, (float)0);
+ COMPQUIET(nfiles, (double)0);
+
+ logc = NULL;
+ ckp_args = NULL;
+ dtab = NULL;
+ hi_txn = TXN_MAXIMUM;
+ lockid = DB_LOCK_INVALIDID;
+ txninfo = NULL;
+ pass = "initial";
+
+ /*
+ * XXX
+ * Get the log size. No locking required because we're single-threaded
+ * during recovery.
+ */
+ log_size =
+ ((LOG *)(((DB_LOG *)dbenv->lg_handle)->reginfo.primary))->log_size;
/*
* Save the state of the thread flag -- we don't need it on at the
@@ -70,60 +98,83 @@ __db_apprec(dbenv, flags)
*/
is_thread = F_ISSET(dbenv, DB_ENV_THREAD) ? 1 : 0;
F_CLR(dbenv, DB_ENV_THREAD);
+
+ /* Set in-recovery flags. */
F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ region = ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary;
+ F_SET(region, TXN_IN_RECOVERY);
+
+ /* Allocate a cursor for the log. */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ goto err;
/*
- * If the user is specifying recover to a particular point in time,
- * verify that the logs present are sufficient to do this.
+ * If the user is specifying recovery to a particular point in time
+ * or to a particular LSN, find the point to start recovery from.
*/
ZERO_LSN(lowlsn);
- if (dbenv->tx_timestamp != 0) {
- if ((ret = __log_earliest(dbenv, &low, &lowlsn)) != 0)
- return (ret);
+ if (max_lsn != NULL) {
+ if ((ret = __log_backup(dbenv, logc, max_lsn, &lowlsn)) != 0)
+ goto err;
+ } else if (dbenv->tx_timestamp != 0) {
+ if ((ret = __log_earliest(dbenv, logc, &low, &lowlsn)) != 0)
+ goto err;
if ((int32_t)dbenv->tx_timestamp < low) {
- char t1[30], t2[30];
-
- strcpy(t1, ctime(&dbenv->tx_timestamp));
+ (void)snprintf(t1, sizeof(t1),
+ "%s", ctime(&dbenv->tx_timestamp));
+ if ((p = strchr(t1, '\n')) != NULL)
+ *p = '\0';
tlow = (time_t)low;
- strcpy(t2, ctime(&tlow));
+ (void)snprintf(t2, sizeof(t2), "%s", ctime(&tlow));
+ if ((p = strchr(t2, '\n')) != NULL)
+ *p = '\0';
__db_err(dbenv,
- "Invalid recovery timestamp %.*s; earliest time is %.*s",
- 24, t1, 24, t2);
- return (EINVAL);
+ "Invalid recovery timestamp %s; earliest time is %s",
+ t1, t2);
+ ret = EINVAL;
+ goto err;
}
}
- /* Initialize the transaction list. */
- if ((ret = __db_txnlist_init(dbenv, &txninfo)) != 0)
- return (ret);
-
/*
* Recovery is done in three passes:
* Pass #0:
- * We need to find the position from which we will open files
- * We need to open files beginning with the last to next
- * checkpoint because we might have crashed after writing the
- * last checkpoint record, but before having written out all
- * the open file information.
+ * We need to find the position from which we will open files.
+ * We need to open files beginning with the earlier of the
+ * most recent checkpoint LSN and a checkpoint LSN before the
+ * recovery timestamp, if specified. We need to be before the
+ * most recent checkpoint LSN because we are going to collect
+ * information about which transactions were begun before we
+ * start rolling forward. Those that were should never be undone
+ * because queue cannot use LSNs to determine what operations can
+ * safely be aborted and it cannot rollback operations in
+ * transactions for which there may be records not processed
+ * during recovery. We need to consider earlier points in time
+ * in case we are recovering to a particular timestamp.
*
* Pass #1:
- * Read forward through the log from the second to last checkpoint
- * opening and closing files so that at the end of the log we have
- * the "current" set of files open.
+ * Read forward through the log from the position found in pass 0
+ * opening and closing files, and recording transactions for which
+ * we've seen their first record (the transaction's prev_lsn is
+ * 0,0). At the end of this pass, we know all transactions for
+ * which we've seen begins and we have the "current" set of files
+ * open.
*
* Pass #2:
* Read backward through the log undoing any uncompleted TXNs.
- * There are three cases:
- * 1. If doing catastrophic recovery, we read to the beginning
- * of the log
+ * There are four cases:
+ * 1. If doing catastrophic recovery, we read to the
+ * beginning of the log
* 2. If we are doing normal reovery, then we have to roll
- * back to the most recent checkpoint that occurs
- * before the most recent checkpoint LSN, which is
- * returned by __log_findckp().
+ * back to the most recent checkpoint LSN.
* 3. If we are recovering to a point in time, then we have
* to roll back to the checkpoint whose ckp_lsn is earlier
* than the specified time. __log_earliest will figure
* this out for us.
+ * 4. If we are recovering back to a particular LSN, then
+ * we have to roll back to the checkpoint whose ckp_lsn
+ * is earlier than the max_lsn. __log_backup will figure
+ * that out for us.
* In case 2, "uncompleted TXNs" include all those who commited
* after the user's specified timestamp.
*
@@ -133,6 +184,14 @@ __db_apprec(dbenv, flags)
* specified rollback point). During this pass, checkpoint
* file information is ignored, and file openings and closings
* are redone.
+ *
+ * ckp_lsn -- lsn of the last checkpoint or the first in the log.
+ * first_lsn -- the lsn where the forward passes begin.
+ * last_lsn -- the last lsn in the log, used for feedback
+ * lowlsn -- the lsn we are rolling back to, if we are recovering
+ * to a point in time.
+ * lsn -- temporary use lsn.
+ * stop_lsn -- the point at which forward roll should stop
*/
/*
@@ -143,132 +202,209 @@ __db_apprec(dbenv, flags)
* same amount of time (a false assumption) and then use the %-age
* of the amount of log traversed to figure out how much of the
* pass we've accomplished.
+ *
+ * If we can't find any log records, we're kind of done.
*/
+#ifdef UMRW
+ ZERO_LSN(last_lsn);
+#endif
memset(&data, 0, sizeof(data));
- if (dbenv->db_feedback != NULL &&
- (ret = log_get(dbenv, &last_lsn, &data, DB_LAST)) != 0)
- goto out;
+ if ((ret = logc->get(logc, &last_lsn, &data, DB_LAST)) != 0) {
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+ else
+ __db_err(dbenv, "Last log record not found");
+ goto err;
+ }
+
+ do {
+ /* txnid is after rectype, which is a u_int32. */
+ memcpy(&txnid,
+ (u_int8_t *)data.data + sizeof(u_int32_t), sizeof(txnid));
+
+ if (txnid != 0)
+ break;
+ } while ((ret = logc->get(logc, &lsn, &data, DB_PREV)) == 0);
/*
- * Pass #0
- * Find the second to last checkpoint in the log. This is the point
- * from which we want to begin pass #1 (the open files pass).
+ * There are no transactions, so there is nothing to do unless
+ * we're recovering to an LSN. If we are, we need to proceed since
+ * we'll still need to do a vtruncate based on information we haven't
+ * yet collected.
*/
- ckp_args = NULL;
+ if (ret == DB_NOTFOUND) {
+ ret = 0;
+ if (max_lsn == NULL)
+ goto done;
+ }
+ if (ret != 0)
+ goto err;
- if (LF_ISSET(DB_RECOVER_FATAL)) {
- if ((ret = log_get(dbenv, &ckp_lsn, &data, DB_FIRST)) != 0) {
- if (ret == DB_NOTFOUND)
- ret = 0;
- else
- __db_err(dbenv, "First log record not found");
- goto out;
+ hi_txn = txnid;
+
+ /*
+ * Pass #0
+ * Find the LSN from which we begin OPENFILES.
+ *
+ * If this is a catastrophic recovery, or if no checkpoint exists
+ * in the log, the LSN is the first LSN in the log.
+ *
+ * Otherwise, it is the minimum of (1) the LSN in the last checkpoint
+ * and (2) the LSN in the checkpoint before any specified recovery
+ * timestamp or max_lsn.
+ */
+ /*
+ * Get the first LSN in the log; it's an initial default
+ * even if this is not a catastrophic recovery.
+ */
+ if ((ret = logc->get(logc, &ckp_lsn, &data, DB_FIRST)) != 0) {
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+ else
+ __db_err(dbenv, "First log record not found");
+ goto err;
+ }
+ first_lsn = ckp_lsn;
+ have_rec = 1;
+
+ if (!LF_ISSET(DB_RECOVER_FATAL)) {
+ if ((ret = __txn_getckp(dbenv, &ckp_lsn)) == 0 &&
+ (ret = logc->get(logc, &ckp_lsn, &data, DB_SET)) == 0) {
+ /* We have a recent checkpoint. This is LSN (1). */
+ if ((ret = __txn_ckp_read(dbenv,
+ data.data, &ckp_args)) != 0) {
+ __db_err(dbenv,
+ "Invalid checkpoint record at [%ld][%ld]",
+ (u_long)ckp_lsn.file,
+ (u_long)ckp_lsn.offset);
+ goto err;
+ }
+ first_lsn = ckp_args->ckp_lsn;
+ have_rec = 0;
}
- open_lsn = ckp_lsn;
- } else if ((ret =
- log_get(dbenv, &ckp_lsn, &data, DB_CHECKPOINT)) != 0) {
+
/*
- * If we don't find a checkpoint, start from the beginning.
- * If that fails, we're done. Note, we do not require that
- * there be log records if we're performing recovery.
+ * If LSN (2) exists, use it if it's before LSN (1).
+ * (If LSN (1) doesn't exist, first_lsn is the
+ * beginning of the log, so will "win" this check.)
+ *
+ * XXX
+ * In the recovery-to-a-timestamp case, lowlsn is chosen by
+ * __log_earliest, and is the checkpoint LSN of the
+ * *earliest* checkpoint in the unreclaimed log. I
+ * (krinsky) believe that we could optimize this by looking
+ * instead for the LSN of the *latest* checkpoint before
+ * the timestamp of interest, but I'm not sure that this
+ * is worth doing right now. (We have to look for lowlsn
+ * and low anyway, to make sure the requested timestamp is
+ * somewhere in the logs we have, and all that's required
+ * is that we pick *some* checkpoint after the beginning of
+ * the logs and before the timestamp.
*/
-first: if ((ret = log_get(dbenv, &ckp_lsn, &data, DB_FIRST)) != 0) {
- if (ret == DB_NOTFOUND)
- ret = 0;
- else
- __db_err(dbenv, "First log record not found");
- goto out;
+ if ((dbenv->tx_timestamp != 0 || max_lsn != NULL) &&
+ log_compare(&lowlsn, &first_lsn) < 0) {
+ DB_ASSERT(have_rec == 0);
+ first_lsn = lowlsn;
}
- open_lsn = ckp_lsn;
- } else if ((ret = __txn_ckp_read(dbenv, data.data, &ckp_args)) != 0) {
- __db_err(dbenv, "Invalid checkpoint record at [%ld][%ld]\n",
- (u_long)ckp_lsn.file, (u_long)ckp_lsn.offset);
- goto out;
- } else if (IS_ZERO_LSN(ckp_args->last_ckp) ||
- (ret = log_get(dbenv, &ckp_args->last_ckp, &data, DB_SET)) != 0)
- goto first;
- else
- open_lsn = ckp_args->last_ckp;
+ }
+
+ /* Get the record at first_lsn if we don't have it already. */
+ if (!have_rec &&
+ (ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0) {
+ __db_err(dbenv, "Checkpoint LSN record [%ld][%ld] not found",
+ (u_long)first_lsn.file, (u_long)first_lsn.offset);
+ goto err;
+ }
if (dbenv->db_feedback != NULL) {
- if (last_lsn.file == open_lsn.file)
- nfiles = (float)(last_lsn.offset - open_lsn.offset) /
- dbenv->lg_max;
+ if (last_lsn.file == first_lsn.file)
+ nfiles = (double)
+ (last_lsn.offset - first_lsn.offset) / log_size;
else
- nfiles = (float)(last_lsn.file - open_lsn.file) +
- (float)(dbenv->lg_max - open_lsn.offset +
- last_lsn.offset) / dbenv->lg_max;
+ nfiles = (double)(last_lsn.file - first_lsn.file) +
+ (double)(log_size - first_lsn.offset +
+ last_lsn.offset) / log_size;
/* We are going to divide by nfiles; make sure it isn't 0. */
if (nfiles == 0)
- nfiles = (float)0.001;
+ nfiles = (double)0.001;
}
+ /* Find a low txnid. */
+ ret = 0;
+ do {
+ /* txnid is after rectype, which is a u_int32. */
+ memcpy(&txnid,
+ (u_int8_t *)data.data + sizeof(u_int32_t), sizeof(txnid));
+
+ if (txnid != 0)
+ break;
+ } while ((ret = logc->get(logc, &lsn, &data, DB_NEXT)) == 0);
+
/*
- * Pass #1
- * Now, ckp_lsn is either the lsn of the last checkpoint
- * or the lsn of the first record in the log. Open_lsn is
- * the second to last checkpoint or the beinning of the log;
- * begin the open files pass from that lsn, and proceed to
- * the end of the log.
+ * There are no transactions and we're not recovering to an LSN (see
+ * above), so there is nothing to do.
*/
- lsn = open_lsn;
- for (;;) {
- if (dbenv->db_feedback != NULL) {
- progress = (int)(33 * (__lsn_diff(&open_lsn,
- &last_lsn, &lsn, dbenv->lg_max, 1) / nfiles));
- dbenv->db_feedback(dbenv, DB_RECOVER, progress);
- }
- ret = __db_dispatch(dbenv,
- &data, &lsn, DB_TXN_OPENFILES, txninfo);
- if (ret != 0 && ret != DB_TXN_CKP)
- goto msgerr;
- if ((ret = log_get(dbenv, &lsn, &data, DB_NEXT)) != 0) {
- if (ret == DB_NOTFOUND)
- break;
- goto out;
- }
+ if (ret == DB_NOTFOUND) {
+ ret = 0;
+ if (max_lsn == NULL)
+ goto done;
}
+ /* Reset to the first lsn. */
+ if (ret != 0 || (ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0)
+ goto err;
+
+ /* Initialize the transaction list. */
+ if ((ret =
+ __db_txnlist_init(dbenv, txnid, hi_txn, max_lsn, &txninfo)) != 0)
+ goto err;
+
+ /*
+ * Pass #1
+ * Run forward through the log starting at the first relevant lsn.
+ */
+ if ((ret = __env_openfiles(dbenv, logc,
+ txninfo, &data, &first_lsn, &last_lsn, nfiles, 1)) != 0)
+ goto err;
+
/*
* Pass #2.
*
- * Before we can begin pass #2, backward roll phase, we determine how
- * far back in the log to recover. If we are doing catastrophic
- * recovery, then we go as far back as we have files. If we are
- * doing normal recovery, we go as back to the most recent checkpoint
- * that occurs before the most recent checkpoint LSN. If we are
- * recovering to a point in time, then rollback to the checkpoint whose
- * ckp_lsn precedes the first log record (and then roll forward to
- * the appropriate timestamp in Pass #3).
+ * We used first_lsn to tell us how far back we need to recover,
+ * use it here.
*/
- if (LF_ISSET(DB_RECOVER_FATAL)) {
- ZERO_LSN(first_lsn);
- } else if (dbenv->tx_timestamp != 0)
- first_lsn = lowlsn;
- else
- if ((ret = __log_findckp(dbenv, &first_lsn)) == DB_NOTFOUND) {
- /*
- * We don't require that log files exist if recovery
- * was specified.
- */
- ret = 0;
- goto out;
- }
if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))
__db_err(dbenv, "Recovery starting from [%lu][%lu]",
(u_long)first_lsn.file, (u_long)first_lsn.offset);
- for (ret = log_get(dbenv, &lsn, &data, DB_LAST);
- ret == 0 && log_compare(&lsn, &first_lsn) > 0;
- ret = log_get(dbenv, &lsn, &data, DB_PREV)) {
+ /*
+ * If we are doing client recovery, then we need to allocate
+ * the page-info lock table.
+ */
+ if (max_lsn != NULL) {
+ if ((ret = __rep_lockpgno_init(dbenv, &dtab, &dtabsize)) != 0)
+ goto err;
+ if ((ret = dbenv->lock_id(dbenv, &lockid)) != 0)
+ goto err;
+ }
+
+ pass = "backward";
+ for (ret = logc->get(logc, &lsn, &data, DB_LAST);
+ ret == 0 && log_compare(&lsn, &first_lsn) >= 0;
+ ret = logc->get(logc, &lsn, &data, DB_PREV)) {
if (dbenv->db_feedback != NULL) {
- progress = 34 + (int)(33 * (__lsn_diff(&open_lsn,
- &last_lsn, &lsn, dbenv->lg_max, 0) / nfiles));
+ progress = 34 + (int)(33 * (__lsn_diff(&first_lsn,
+ &last_lsn, &lsn, log_size, 0) / nfiles));
dbenv->db_feedback(dbenv, DB_RECOVER, progress);
}
- ret = __db_dispatch(dbenv,
- &data, &lsn, DB_TXN_BACKWARD_ROLL, txninfo);
+ if (max_lsn != NULL && (ret = __rep_lockpages(dbenv,
+ dtab, dtabsize, &lsn, NULL, NULL, lockid)) != 0)
+ continue;
+
+ ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+ dbenv->recover_dtab_size, &data, &lsn,
+ DB_TXN_BACKWARD_ROLL, txninfo);
if (ret != 0) {
if (ret != DB_TXN_CKP)
goto msgerr;
@@ -277,63 +413,128 @@ first: if ((ret = log_get(dbenv, &ckp_lsn, &data, DB_FIRST)) != 0) {
}
}
if (ret != 0 && ret != DB_NOTFOUND)
- goto out;
+ goto err;
/*
- * Pass #3.
+ * Pass #3. If we are recovering to a timestamp or to an LSN,
+ * we need to make sure that we don't roll-forward beyond that
+ * point because there may be non-transactional operations (e.g.,
+ * closes that would fail). The last_lsn variable is used for
+ * feedback calculations, but use it to set an initial stopping
+ * point for the forward pass, and then reset appropriately to
+ * derive a real stop_lsn that tells how far the forward pass
+ * should go.
*/
- for (ret = log_get(dbenv, &lsn, &data, DB_NEXT);
- ret == 0; ret = log_get(dbenv, &lsn, &data, DB_NEXT)) {
+ pass = "forward";
+ stop_lsn = last_lsn;
+ if (max_lsn != NULL || dbenv->tx_timestamp != 0)
+ stop_lsn = ((DB_TXNHEAD *)txninfo)->maxlsn;
+
+ for (ret = logc->get(logc, &lsn, &data, DB_NEXT);
+ ret == 0; ret = logc->get(logc, &lsn, &data, DB_NEXT)) {
+ /*
+ * If we are recovering to a timestamp or an LSN,
+ * we need to make sure that we don't try to roll
+ * forward beyond the soon-to-be end of log.
+ */
+ if (log_compare(&lsn, &stop_lsn) > 0)
+ break;
+
if (dbenv->db_feedback != NULL) {
- progress = 67 + (int)(33 * (__lsn_diff(&open_lsn,
- &last_lsn, &lsn, dbenv->lg_max, 1) / nfiles));
+ progress = 67 + (int)(33 * (__lsn_diff(&first_lsn,
+ &last_lsn, &lsn, log_size, 1) / nfiles));
dbenv->db_feedback(dbenv, DB_RECOVER, progress);
}
- ret = __db_dispatch(dbenv,
- &data, &lsn, DB_TXN_FORWARD_ROLL, txninfo);
+ ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+ dbenv->recover_dtab_size, &data, &lsn,
+ DB_TXN_FORWARD_ROLL, txninfo);
if (ret != 0) {
if (ret != DB_TXN_CKP)
goto msgerr;
else
ret = 0;
}
+
}
- if (ret != DB_NOTFOUND)
- goto out;
+ if (ret != 0 && ret != DB_NOTFOUND)
+ goto err;
/*
- * Process any pages that were on the limbo list
- * and move them to the free list. Do this
- * before checkpointing the database.
+ * Process any pages that were on the limbo list and move them to
+ * the free list. Do this before checkpointing the database.
*/
- if ((ret = __db_do_the_limbo(dbenv, txninfo)) != 0)
- goto out;
+ if ((ret = __db_do_the_limbo(dbenv, NULL, NULL, txninfo)) != 0)
+ goto err;
- /*
- * Now set the last checkpoint lsn and the current time,
- * take a checkpoint, and reset the txnid.
- */
- (void)time(&now);
- region = ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary;
- region->last_txnid = ((DB_TXNHEAD *)txninfo)->maxid;
- region->last_ckp = ckp_lsn;
- region->time_ckp = (u_int32_t)now;
+ if (max_lsn == NULL)
+ region->last_txnid = ((DB_TXNHEAD *)txninfo)->maxid;
- /*
- * Take two checkpoints so that we don't re-recover any of the
- * work we've already done.
- */
- if ((ret = txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0)
- goto out;
+ /* Take a checkpoint here to force any dirty data pages to disk. */
+ if (dbenv->tx_timestamp != 0) {
+ region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;
+ __log_vtruncate(dbenv, &((DB_TXNHEAD *)txninfo)->maxlsn,
+ &((DB_TXNHEAD *)txninfo)->ckplsn);
+ }
- /* Now close all the db files that are open. */
- __log_close_files(dbenv);
+ if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0)
+ goto err;
- if ((ret = txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0)
- goto out;
- region->last_txnid = TXN_MINIMUM;
+ /* Close all the db files that are open. */
+ if ((ret = __dbreg_close_files(dbenv)) != 0)
+ goto err;
+
+ if (max_lsn != NULL) {
+ region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;
+
+ /* We are going to truncate, so we'd best close the cursor. */
+ if (logc != NULL && (ret = logc->close(logc, 0)) != 0)
+ goto err;
+ __log_vtruncate(dbenv,
+ max_lsn, &((DB_TXNHEAD *)txninfo)->ckplsn);
+
+ /*
+ * Now we need to open files that should be open in order for
+ * client processing to continue. However, since we've
+ * truncated the log, we need to recompute from where the
+ * openfiles pass should begin.
+ */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ goto err;
+ if ((ret = logc->get(logc, &first_lsn, &data, DB_FIRST)) != 0) {
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+ else
+ __db_err(dbenv, "First log record not found");
+ goto err;
+ }
+ if ((ret = __txn_getckp(dbenv, &first_lsn)) == 0 &&
+ (ret = logc->get(logc, &first_lsn, &data, DB_SET)) == 0) {
+ /* We have a recent checkpoint. This is LSN (1). */
+ if ((ret = __txn_ckp_read(dbenv,
+ data.data, &ckp_args)) != 0) {
+ __db_err(dbenv,
+ "Invalid checkpoint record at [%ld][%ld]",
+ (u_long)first_lsn.file,
+ (u_long)first_lsn.offset);
+ goto err;
+ }
+ first_lsn = ckp_args->ckp_lsn;
+ }
+ if ((ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0)
+ goto err;
+ if ((ret = __env_openfiles(dbenv, logc,
+ txninfo, &data, &first_lsn, NULL, nfiles, 1)) != 0)
+ goto err;
+ } else if (region->stat.st_nrestores == 0)
+ /*
+ * If there are no prepared transactions that need resolution,
+ * we need to reset the transaction ID space and log this fact.
+ */
+ if ((ret = __txn_reset(dbenv)) != 0)
+ goto err;
if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) {
+ (void)time(&now);
__db_err(dbenv, "Recovery complete at %.24s", ctime(&now));
__db_err(dbenv, "%s %lx %s [%lu][%lu]",
"Maximum transaction ID",
@@ -344,18 +545,41 @@ first: if ((ret = log_get(dbenv, &ckp_lsn, &data, DB_FIRST)) != 0) {
}
if (0) {
-msgerr: __db_err(dbenv, "Recovery function for LSN %lu %lu failed",
- (u_long)lsn.file, (u_long)lsn.offset);
+msgerr: __db_err(dbenv,
+ "Recovery function for LSN %lu %lu failed on %s pass",
+ (u_long)lsn.file, (u_long)lsn.offset, pass);
}
-out: if (is_thread)
- F_SET(dbenv, DB_ENV_THREAD);
- __db_txnlist_end(dbenv, txninfo);
+done:
+err: if (lockid != DB_LOCK_INVALIDID) {
+ if ((t_ret = __rep_unlockpages(dbenv, lockid)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if ((t_ret =
+ dbenv->lock_id_free(dbenv, lockid)) != 0 && ret == 0)
+ ret = t_ret;
+ }
+
+ if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (txninfo != NULL)
+ __db_txnlist_end(dbenv, txninfo);
+
+ if (dtab != NULL)
+ __os_free(dbenv, dtab);
+
if (ckp_args != NULL)
- __os_free(ckp_args, sizeof(*ckp_args));
- F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ __os_free(dbenv, ckp_args);
dbenv->tx_timestamp = 0;
+
+ /* Restore the state of the thread flag, clear in-recovery flags. */
+ if (is_thread)
+ F_SET(dbenv, DB_ENV_THREAD);
+ F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ F_CLR(region, TXN_IN_RECOVERY);
+
return (ret);
}
@@ -365,13 +589,13 @@ out: if (is_thread)
* we are moving backward, we are computing high - current. max is
* the number of bytes per logfile.
*/
-static float
+static double
__lsn_diff(low, high, current, max, is_forward)
DB_LSN *low, *high, *current;
u_int32_t max;
int is_forward;
{
- float nf;
+ double nf;
/*
* There are three cases in each direction. If you are in the
@@ -382,27 +606,78 @@ __lsn_diff(low, high, current, max, is_forward)
*/
if (is_forward) {
if (current->file == low->file)
- nf = (float)(current->offset - low->offset) / max;
+ nf = (double)(current->offset - low->offset) / max;
else if (current->offset < low->offset)
- nf = (float)(current->file - low->file - 1) +
- (float)(max - low->offset + current->offset) / max;
+ nf = (double)(current->file - low->file - 1) +
+ (double)(max - low->offset + current->offset) / max;
else
- nf = (float)(current->file - low->file) +
- (float)(current->offset - low->offset) / max;
+ nf = (double)(current->file - low->file) +
+ (double)(current->offset - low->offset) / max;
} else {
if (current->file == high->file)
- nf = (float)(high->offset - current->offset) / max;
+ nf = (double)(high->offset - current->offset) / max;
else if (current->offset > high->offset)
- nf = (float)(high->file - current->file - 1) +
- (float)(max - current->offset + high->offset) / max;
+ nf = (double)(high->file - current->file - 1) +
+ (double)
+ (max - current->offset + high->offset) / max;
else
- nf = (float)(high->file - current->file) +
- (float)(high->offset - current->offset) / max;
+ nf = (double)(high->file - current->file) +
+ (double)(high->offset - current->offset) / max;
}
return (nf);
}
/*
+ * __log_backup --
+ *
+ * This is used to find the earliest log record to process when a client
+ * is trying to sync up with a master whose max LSN is less than this
+ * client's max lsn; we want to roll back everything after that
+ *
+ * Find the latest checkpoint whose ckp_lsn is less than the max lsn.
+ */
+static int
+__log_backup(dbenv, logc, max_lsn, start_lsn)
+ DB_ENV *dbenv;
+ DB_LOGC *logc;
+ DB_LSN *max_lsn, *start_lsn;
+{
+ DB_LSN lsn;
+ DBT data;
+ __txn_ckp_args *ckp_args;
+ int ret;
+
+ memset(&data, 0, sizeof(data));
+ ckp_args = NULL;
+
+ /*
+ * Follow checkpoints through the log until we find one with
+ * a ckp_lsn less than max_lsn.
+ */
+ if ((ret = __txn_getckp(dbenv, &lsn)) != 0)
+ goto err;
+ while ((ret = logc->get(logc, &lsn, &data, DB_SET)) == 0) {
+ if ((ret = __txn_ckp_read(dbenv, data.data, &ckp_args)) != 0)
+ return (ret);
+ if (log_compare(&ckp_args->ckp_lsn, max_lsn) <= 0) {
+ *start_lsn = ckp_args->ckp_lsn;
+ break;
+ }
+
+ lsn = ckp_args->prev_lsn;
+ if (IS_ZERO_LSN(lsn))
+ break;
+ __os_free(dbenv, ckp_args);
+ }
+
+ if (ckp_args != NULL)
+ __os_free(dbenv, ckp_args);
+err: if (IS_ZERO_LSN(*start_lsn) && (ret == 0 || ret == DB_NOTFOUND))
+ ret = logc->get(logc, start_lsn, &data, DB_FIRST);
+ return (ret);
+}
+
+/*
* __log_earliest --
*
* Return the earliest recovery point for the log files present. The
@@ -410,8 +685,9 @@ __lsn_diff(low, high, current, max, is_forward)
* whose checkpoint LSN is greater than the first LSN we process.
*/
static int
-__log_earliest(dbenv, lowtime, lowlsn)
+__log_earliest(dbenv, logc, lowtime, lowlsn)
DB_ENV *dbenv;
+ DB_LOGC *logc;
int32_t *lowtime;
DB_LSN *lowlsn;
{
@@ -427,19 +703,17 @@ __log_earliest(dbenv, lowtime, lowlsn)
* record whose ckp_lsn is greater than first_lsn.
*/
- for (ret = log_get(dbenv, &first_lsn, &data, DB_FIRST);
- ret == 0; ret = log_get(dbenv, &lsn, &data, DB_NEXT)) {
- if (ret != 0)
- break;
+ for (ret = logc->get(logc, &first_lsn, &data, DB_FIRST);
+ ret == 0; ret = logc->get(logc, &lsn, &data, DB_NEXT)) {
memcpy(&rectype, data.data, sizeof(rectype));
- if (rectype != DB_txn_ckp)
+ if (rectype != DB___txn_ckp)
continue;
if ((ret = __txn_ckp_read(dbenv, data.data, &ckpargs)) == 0) {
cmp = log_compare(&ckpargs->ckp_lsn, &first_lsn);
*lowlsn = ckpargs->ckp_lsn;
*lowtime = ckpargs->timestamp;
- __os_free(ckpargs, 0);
+ __os_free(dbenv, ckpargs);
if (cmp >= 0)
break;
}
@@ -447,3 +721,70 @@ __log_earliest(dbenv, lowtime, lowlsn)
return (ret);
}
+
+/*
+ * __env_openfiles --
+ * Perform the pass of recovery that opens files. This is used
+ * both during regular recovery and an initial call to txn_recover (since
+ * we need files open in order to abort prepared, but not yet committed
+ * transactions).
+ *
+ * See the comments in db_apprec for a detailed description of the
+ * various recovery passes.
+ *
+ * If we are not doing feedback processing (i.e., we are doing txn_recover
+ * processing and in_recovery is zero), then last_lsn can be NULL.
+ *
+ * PUBLIC: int __env_openfiles __P((DB_ENV *, DB_LOGC *,
+ * PUBLIC: void *, DBT *, DB_LSN *, DB_LSN *, double, int));
+ */
+int
+__env_openfiles(dbenv, logc, txninfo,
+ data, open_lsn, last_lsn, nfiles, in_recovery)
+ DB_ENV *dbenv;
+ DB_LOGC *logc;
+ void *txninfo;
+ DBT *data;
+ DB_LSN *open_lsn, *last_lsn;
+ int in_recovery;
+ double nfiles;
+{
+ DB_LSN lsn;
+ u_int32_t log_size;
+ int progress, ret;
+
+ /*
+ * XXX
+ * Get the log size. No locking required because we're single-threaded
+ * during recovery.
+ */
+ log_size =
+ ((LOG *)(((DB_LOG *)dbenv->lg_handle)->reginfo.primary))->log_size;
+
+ lsn = *open_lsn;
+ for (;;) {
+ if (in_recovery && dbenv->db_feedback != NULL) {
+ DB_ASSERT(last_lsn != NULL);
+ progress = (int)(33 * (__lsn_diff(open_lsn,
+ last_lsn, &lsn, log_size, 1) / nfiles));
+ dbenv->db_feedback(dbenv, DB_RECOVER, progress);
+ }
+ ret = __db_dispatch(dbenv,
+ dbenv->recover_dtab, dbenv->recover_dtab_size, data, &lsn,
+ in_recovery ? DB_TXN_OPENFILES : DB_TXN_POPENFILES,
+ txninfo);
+ if (ret != 0 && ret != DB_TXN_CKP) {
+ __db_err(dbenv,
+ "Recovery function for LSN %lu %lu failed",
+ (u_long)lsn.file, (u_long)lsn.offset);
+ break;
+ }
+ if ((ret = logc->get(logc, &lsn, data, DB_NEXT)) != 0) {
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+ break;
+ }
+ }
+
+ return (ret);
+}
diff --git a/bdb/env/env_region.c b/bdb/env/env_region.c
index f3df4bac184..a919cf328b4 100644
--- a/bdb/env/env_region.c
+++ b/bdb/env/env_region.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: env_region.c,v 11.28 2000/12/12 17:36:10 bostic Exp $";
+static const char revid[] = "$Id: env_region.c,v 11.64 2002/07/17 15:09:19 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,20 +20,17 @@ static const char revid[] = "$Id: env_region.c,v 11.28 2000/12/12 17:36:10 bosti
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "lock_ext.h"
-#include "log.h"
-#include "log_ext.h"
-#include "mp.h"
-#include "mp_ext.h"
-#include "txn.h"
-#include "txn_ext.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
static int __db_des_destroy __P((DB_ENV *, REGION *));
static int __db_des_get __P((DB_ENV *, REGINFO *, REGINFO *, REGION **));
static int __db_e_remfile __P((DB_ENV *));
-static int __db_faultmem __P((void *, size_t, int));
+static int __db_faultmem __P((DB_ENV *, void *, size_t, int));
static void __db_region_destroy __P((DB_ENV *, REGINFO *));
/*
@@ -110,13 +107,17 @@ loop: renv = NULL;
* If this is a public environment, we use the filesystem to ensure
* the creation of the environment file is single-threaded.
*/
- if (F_ISSET(dbenv, DB_ENV_PRIVATE))
+ if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+ if ((ret = __os_strdup(dbenv,
+ "process-private", &infop->name)) != 0)
+ goto err;
goto creation;
+ }
/* Build the region name. */
(void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
if ((ret = __db_appname(dbenv,
- DB_APP_NONE, NULL, buf, 0, NULL, &infop->name)) != 0)
+ DB_APP_NONE, buf, 0, NULL, &infop->name)) != 0)
goto err;
/*
@@ -128,8 +129,8 @@ loop: renv = NULL;
* errno return value -- I sure hope they're right.
*/
if (F_ISSET(dbenv, DB_ENV_CREATE)) {
- if ((ret = __os_open(dbenv,
- infop->name, DB_OSO_REGION | DB_OSO_CREATE | DB_OSO_EXCL,
+ if ((ret = __os_open(dbenv, infop->name,
+ DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_REGION,
dbenv->db_mode, dbenv->lockfhp)) == 0)
goto creation;
if (ret != EEXIST) {
@@ -143,8 +144,8 @@ loop: renv = NULL;
* If we couldn't create the file, try and open it. (If that fails,
* we're done.)
*/
- if ((ret = __os_open(dbenv, infop->name,
- DB_OSO_REGION, dbenv->db_mode, dbenv->lockfhp)) != 0)
+ if ((ret = __os_open(dbenv, infop->name, DB_OSO_REGION | DB_OSO_DIRECT,
+ dbenv->db_mode, dbenv->lockfhp)) != 0)
goto err;
/*
@@ -230,12 +231,12 @@ loop: renv = NULL;
* the better.
*/
#ifdef HAVE_MUTEX_THREADS
- __os_closehandle(dbenv->lockfhp);
+ __os_closehandle(dbenv, dbenv->lockfhp);
#endif
/* Call the region join routine to acquire the region. */
memset(&tregion, 0, sizeof(tregion));
- tregion.size = size;
+ tregion.size = (roff_t)size;
tregion.segid = segid;
if ((ret = __os_r_attach(dbenv, infop, &tregion)) != 0)
goto err;
@@ -265,7 +266,7 @@ loop: renv = NULL;
* can't because Windows/NT filesystems won't open files mode 0.
*/
renv = infop->primary;
- if (renv->panic) {
+ if (renv->envpanic && !F_ISSET(dbenv, DB_ENV_NOPANIC)) {
ret = __db_panic_msg(dbenv);
goto err;
}
@@ -287,13 +288,13 @@ loop: renv = NULL;
}
/* Lock the environment. */
- MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &renv->mutex);
/*
* Finally! We own the environment now. Repeat the panic check, it's
* possible that it was set while we waited for the lock.
*/
- if (renv->panic) {
+ if (renv->envpanic && !F_ISSET(dbenv, DB_ENV_NOPANIC)) {
ret = __db_panic_msg(dbenv);
goto err_unlock;
}
@@ -338,7 +339,7 @@ err_unlock: MUTEX_UNLOCK(dbenv, &renv->mutex);
* Fault the pages into memory. Note, do this AFTER releasing the
* lock, because we're only reading the pages, not writing them.
*/
- (void)__db_faultmem(infop->primary, rp->size, 0);
+ (void)__db_faultmem(dbenv, infop->primary, rp->size, 0);
/* Everything looks good, we're done. */
dbenv->reginfo = infop;
@@ -352,9 +353,12 @@ creation:
* Allocate room for 50 REGION structures plus overhead (we're going
* to use this space for last-ditch allocation requests), although we
* should never need anything close to that.
+ *
+ * Encryption passwds are stored in the env region. Add that in too.
*/
memset(&tregion, 0, sizeof(tregion));
- tregion.size = 50 * sizeof(REGION) + 50 * sizeof(MUTEX) + 2048;
+ tregion.size = (roff_t)(50 * sizeof(REGION) +
+ dbenv->passwd_len + 2048);
tregion.segid = INVALID_REGION_SEGID;
if ((ret = __os_r_attach(dbenv, infop, &tregion)) != 0)
goto err;
@@ -363,7 +367,7 @@ creation:
* Fault the pages into memory. Note, do this BEFORE we initialize
* anything, because we're writing the pages, not just reading them.
*/
- (void)__db_faultmem(infop->addr, tregion.size, 1);
+ (void)__db_faultmem(dbenv, infop->addr, tregion.size, 1);
/*
* The first object in the region is the REGENV structure. This is
@@ -392,10 +396,12 @@ creation:
* number which validates the file/environment.
*/
renv = infop->primary;
- renv->panic = 0;
+ renv->envpanic = 0;
db_version(&renv->majver, &renv->minver, &renv->patch);
SH_LIST_INIT(&renv->regionq);
renv->refcnt = 1;
+ renv->cipher_off = INVALID_ROFF;
+ renv->rep_off = INVALID_ROFF;
/*
* Initialize init_flags to store the flags that any other environment
@@ -412,15 +418,15 @@ creation:
* filesystem as the database home. But you knew that, I'm sure -- it
* probably wasn't even worth mentioning.)
*/
- if ((ret =
- __db_mutex_init(dbenv, &renv->mutex, DB_FCNTL_OFF_GEN, 0)) != 0) {
+ if ((ret = __db_mutex_setup(dbenv, infop, &renv->mutex,
+ MUTEX_NO_RECORD | MUTEX_NO_RLOCK)) != 0) {
__db_err(dbenv, "%s: unable to initialize environment lock: %s",
infop->name, db_strerror(ret));
goto err;
}
if (!F_ISSET(&renv->mutex, MUTEX_IGNORE) &&
- (ret = __db_mutex_lock(dbenv, &renv->mutex, dbenv->lockfhp)) != 0) {
+ (ret = __db_mutex_lock(dbenv, &renv->mutex)) != 0) {
__db_err(dbenv, "%s: unable to acquire environment lock: %s",
infop->name, db_strerror(ret));
goto err;
@@ -459,8 +465,8 @@ find_err: __db_err(dbenv,
if (tregion.segid != INVALID_REGION_SEGID) {
ref.size = tregion.size;
ref.segid = tregion.segid;
- if ((ret = __os_write(dbenv, dbenv->lockfhp,
- &ref, sizeof(ref), &nrw)) != 0 || nrw != sizeof(ref)) {
+ if ((ret = __os_write(
+ dbenv, dbenv->lockfhp, &ref, sizeof(ref), &nrw)) != 0) {
__db_err(dbenv,
"%s: unable to write out public environment ID: %s",
infop->name, db_strerror(ret));
@@ -476,7 +482,7 @@ find_err: __db_err(dbenv,
*/
#if defined(HAVE_MUTEX_THREADS)
if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
- __os_closehandle(dbenv->lockfhp);
+ __os_closehandle(dbenv, dbenv->lockfhp);
#endif
/* Validate the file. */
@@ -492,7 +498,7 @@ find_err: __db_err(dbenv,
err:
retry: /* Close any open file handle. */
if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
- (void)__os_closehandle(dbenv->lockfhp);
+ (void)__os_closehandle(dbenv, dbenv->lockfhp);
/*
* If we joined or created the region, detach from it. If we created
@@ -513,8 +519,8 @@ retry: /* Close any open file handle. */
/* Free the allocated name and/or REGINFO structure. */
if (infop->name != NULL)
- __os_freestr(infop->name);
- __os_free(infop, sizeof(REGINFO));
+ __os_free(dbenv, infop->name);
+ __os_free(dbenv, infop);
/* If we had a temporary error, wait awhile and try again. */
if (ret == 0) {
@@ -547,8 +553,10 @@ __db_e_detach(dbenv, destroy)
infop = dbenv->reginfo;
renv = infop->primary;
+ if (F_ISSET(dbenv, DB_ENV_PRIVATE))
+ destroy = 1;
/* Lock the environment. */
- MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &renv->mutex);
/* Decrement the reference count. */
if (renv->refcnt == 0) {
@@ -563,33 +571,39 @@ __db_e_detach(dbenv, destroy)
/* Close the locking file handle. */
if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
- (void)__os_closehandle(dbenv->lockfhp);
+ (void)__os_closehandle(dbenv, dbenv->lockfhp);
/* Reset the addr value that we "corrected" above. */
infop->addr = infop->primary;
/*
* If we are destroying the environment, we need to
- * destroy any system resources backing the mutex.
- * Do that now before we free the memory in __os_r_detach.
+ * destroy any system resources backing the mutex, as well
+ * as any system resources that the replication system may have
+ * acquired and put in the main region.
+ *
+ * Do these now before we free the memory in __os_r_detach.
*/
- if (destroy)
+ if (destroy) {
+ __rep_region_destroy(dbenv);
__db_mutex_destroy(&renv->mutex);
+ __db_mutex_destroy(&infop->rp->mutex);
+ }
/*
* Release the region, and kill our reference.
*
- * We set the DBENV->reginfo field to NULL here and discard its memory.
- * DBENV->remove calls __dbenv_remove to do the region remove, and
+ * We set the DB_ENV->reginfo field to NULL here and discard its memory.
+ * DB_ENV->remove calls __dbenv_remove to do the region remove, and
* __dbenv_remove attached and then detaches from the region. We don't
- * want to return to DBENV->remove with a non-NULL DBENV->reginfo field
- * because it will attempt to detach again as part of its cleanup.
+ * want to return to DB_ENV->remove with a non-NULL DB_ENV->reginfo
+ * field because it will attempt to detach again as part of its cleanup.
*/
(void)__os_r_detach(dbenv, infop, destroy);
if (infop->name != NULL)
- __os_free(infop->name, 0);
- __os_free(dbenv->reginfo, sizeof(REGINFO));
+ __os_free(dbenv, infop->name);
+ __os_free(dbenv, dbenv->reginfo);
dbenv->reginfo = NULL;
return (0);
@@ -599,18 +613,20 @@ __db_e_detach(dbenv, destroy)
* __db_e_remove --
* Discard an environment if it's not in use.
*
- * PUBLIC: int __db_e_remove __P((DB_ENV *, int));
+ * PUBLIC: int __db_e_remove __P((DB_ENV *, u_int32_t));
*/
int
-__db_e_remove(dbenv, force)
+__db_e_remove(dbenv, flags)
DB_ENV *dbenv;
- int force;
+ u_int32_t flags;
{
REGENV *renv;
REGINFO *infop, reginfo;
REGION *rp;
- int ret;
+ u_int32_t db_env_reset;
+ int force, ret;
+ force = LF_ISSET(DB_FORCE) ? 1 : 0;
/*
* This routine has to walk a nasty line between not looking into
* the environment (which may be corrupted after an app or system
@@ -632,8 +648,10 @@ __db_e_remove(dbenv, force)
* If the force flag is set, we do not acquire any locks during this
* process.
*/
+ db_env_reset = F_ISSET(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC);
if (force)
- dbenv->db_mutexlocks = 0;
+ F_SET(dbenv, DB_ENV_NOLOCKING);
+ F_SET(dbenv, DB_ENV_NOPANIC);
/* Join the environment. */
if ((ret = __db_e_attach(dbenv, NULL)) != 0) {
@@ -645,17 +663,21 @@ __db_e_remove(dbenv, force)
ret = 0;
if (force)
goto remfiles;
- goto err;
+ goto done;
}
infop = dbenv->reginfo;
renv = infop->primary;
/* Lock the environment. */
- MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &renv->mutex);
- /* If it's in use, we're done. */
- if (renv->refcnt == 1 || force) {
+ /*
+ * If it's in use, we're done unless we're forcing the issue or the
+ * environment has panic'd. (Presumably, if the environment panic'd,
+ * the thread holding the reference count may not have cleaned up.)
+ */
+ if (renv->refcnt == 1 || renv->envpanic == 1 || force) {
/*
* Set the panic flag and overwrite the magic number.
*
@@ -663,7 +685,7 @@ __db_e_remove(dbenv, force)
* From this point on, there's no going back, we pretty
* much ignore errors, and just whack on whatever we can.
*/
- renv->panic = 1;
+ renv->envpanic = 1;
renv->magic = 0;
/*
@@ -713,7 +735,7 @@ restart: for (rp = SH_LIST_FIRST(&renv->regionq, __db_region);
/* Destroy the environment's region. */
(void)__db_e_detach(dbenv, 1);
- /* Discard the physical files. */
+ /* Discard any remaining physical files. */
remfiles: (void)__db_e_remfile(dbenv);
} else {
/* Unlock the environment. */
@@ -725,7 +747,9 @@ remfiles: (void)__db_e_remfile(dbenv);
ret = EBUSY;
}
-err:
+done: F_CLR(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC);
+ F_SET(dbenv, db_env_reset);
+
return (ret);
}
@@ -742,7 +766,7 @@ __db_e_remfile(dbenv)
"__db_log.share",
"__db_mpool.share",
"__db_txn.share",
- NULL,
+ NULL
};
int cnt, fcnt, lastrm, ret;
u_int8_t saved_byte;
@@ -751,8 +775,7 @@ __db_e_remfile(dbenv)
/* Get the full path of a file in the environment. */
(void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
- if ((ret =
- __db_appname(dbenv, DB_APP_NONE, NULL, buf, 0, NULL, &path)) != 0)
+ if ((ret = __db_appname(dbenv, DB_APP_NONE, buf, 0, NULL, &path)) != 0)
return (ret);
/* Get the parent directory for the environment. */
@@ -769,16 +792,15 @@ __db_e_remfile(dbenv)
}
/* Get the list of file names. */
- ret = __os_dirlist(dbenv, dir, &names, &fcnt);
+ if ((ret = __os_dirlist(dbenv, dir, &names, &fcnt)) != 0)
+ __db_err(dbenv, "%s: %s", dir, db_strerror(ret));
/* Restore the path, and free it. */
*p = saved_byte;
- __os_freestr(path);
+ __os_free(dbenv, path);
- if (ret != 0) {
- __db_err(dbenv, "%s: %s", dir, db_strerror(ret));
+ if (ret != 0)
return (ret);
- }
/*
* Search for valid region names, and remove them. We remove the
@@ -799,19 +821,23 @@ __db_e_remfile(dbenv)
continue;
if (__db_appname(dbenv,
- DB_APP_NONE, NULL, names[cnt], 0, NULL, &path) == 0) {
+ DB_APP_NONE, names[cnt], 0, NULL, &path) == 0) {
+ if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
+ (void)__db_overwrite(dbenv, path);
(void)__os_unlink(dbenv, path);
- __os_freestr(path);
+ __os_free(dbenv, path);
}
}
if (lastrm != -1)
if (__db_appname(dbenv,
- DB_APP_NONE, NULL, names[lastrm], 0, NULL, &path) == 0) {
+ DB_APP_NONE, names[lastrm], 0, NULL, &path) == 0) {
+ if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
+ (void)__db_overwrite(dbenv, path);
(void)__os_unlink(dbenv, path);
- __os_freestr(path);
+ __os_free(dbenv, path);
}
- __os_dirfree(names, fcnt);
+ __os_dirfree(dbenv, names, fcnt);
/*
* !!!
@@ -820,9 +846,9 @@ __db_e_remfile(dbenv)
*/
for (names = (char **)old_region_names; *names != NULL; ++names)
if (__db_appname(dbenv,
- DB_APP_NONE, NULL, *names, 0, NULL, &path) == 0) {
+ DB_APP_NONE, *names, 0, NULL, &path) == 0) {
(void)__os_unlink(dbenv, path);
- __os_freestr(path);
+ __os_free(dbenv, path);
}
return (0);
@@ -832,33 +858,47 @@ __db_e_remfile(dbenv)
* __db_e_stat
* Statistics for the environment.
*
- * PUBLIC: int __db_e_stat __P((DB_ENV *, REGENV *, REGION *, int *));
+ * PUBLIC: int __db_e_stat __P((DB_ENV *,
+ * PUBLIC: REGENV *, REGION *, int *, u_int32_t));
*/
int
-__db_e_stat(dbenv, arg_renv, arg_regions, arg_regions_cnt)
+__db_e_stat(dbenv, arg_renv, arg_regions, arg_regions_cnt, flags)
DB_ENV *dbenv;
REGENV *arg_renv;
REGION *arg_regions;
int *arg_regions_cnt;
+ u_int32_t flags;
{
REGENV *renv;
REGINFO *infop;
REGION *rp;
- int n;
+ int n, ret;
infop = dbenv->reginfo;
renv = infop->primary;
rp = infop->rp;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
/* Lock the environment. */
- MUTEX_LOCK(dbenv, &rp->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &rp->mutex);
*arg_renv = *renv;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ renv->mutex.mutex_set_nowait = 0;
+ renv->mutex.mutex_set_wait = 0;
+ }
for (n = 0, rp = SH_LIST_FIRST(&renv->regionq, __db_region);
n < *arg_regions_cnt && rp != NULL;
- ++n, rp = SH_LIST_NEXT(rp, q, __db_region))
+ ++n, rp = SH_LIST_NEXT(rp, q, __db_region)) {
arg_regions[n] = *rp;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ rp->mutex.mutex_set_nowait = 0;
+ rp->mutex.mutex_set_wait = 0;
+ }
+ }
/* Release the lock. */
rp = infop->rp;
@@ -887,12 +927,15 @@ __db_r_attach(dbenv, infop, size)
char buf[sizeof(DB_REGION_FMT) + 20];
renv = ((REGINFO *)dbenv->reginfo)->primary;
- F_CLR(infop, REGION_CREATE);
/* Lock the environment. */
- MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &renv->mutex);
- /* Find or create a REGION structure for this region. */
+ /*
+ * Find or create a REGION structure for this region. If we create
+ * it, the REGION_CREATE flag will be set in the infop structure.
+ */
+ F_CLR(infop, REGION_CREATE);
if ((ret = __db_des_get(dbenv, dbenv->reginfo, infop, &rp)) != 0) {
MUTEX_UNLOCK(dbenv, &renv->mutex);
return (ret);
@@ -903,12 +946,12 @@ __db_r_attach(dbenv, infop, size)
/* If we're creating the region, set the desired size. */
if (F_ISSET(infop, REGION_CREATE))
- rp->size = size;
+ rp->size = (roff_t)size;
/* Join/create the underlying region. */
(void)snprintf(buf, sizeof(buf), DB_REGION_FMT, infop->id);
if ((ret = __db_appname(dbenv,
- DB_APP_NONE, NULL, buf, 0, NULL, &infop->name)) != 0)
+ DB_APP_NONE, buf, 0, NULL, &infop->name)) != 0)
goto err;
if ((ret = __os_r_attach(dbenv, infop, rp)) != 0)
goto err;
@@ -918,8 +961,8 @@ __db_r_attach(dbenv, infop, size)
* anything because we're writing pages in created regions, not just
* reading them.
*/
- (void)__db_faultmem(infop->addr,
- rp->size, F_ISSET(infop, REGION_CREATE));
+ (void)__db_faultmem(dbenv,
+ infop->addr, rp->size, F_ISSET(infop, REGION_CREATE));
/*
* !!!
@@ -940,7 +983,7 @@ __db_r_attach(dbenv, infop, size)
* for it and release our lock on the environment.
*/
if (infop->type != REGION_TYPE_ENV) {
- MUTEX_LOCK(dbenv, &rp->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &rp->mutex);
MUTEX_UNLOCK(dbenv, &renv->mutex);
}
@@ -954,8 +997,10 @@ err: if (infop->addr != NULL)
infop->id = INVALID_REGION_ID;
/* Discard the REGION structure if we created it. */
- if (F_ISSET(infop, REGION_CREATE))
+ if (F_ISSET(infop, REGION_CREATE)) {
(void)__db_des_destroy(dbenv, rp);
+ F_CLR(infop, REGION_CREATE);
+ }
/* Release the environment lock. */
MUTEX_UNLOCK(dbenv, &renv->mutex);
@@ -981,12 +1026,14 @@ __db_r_detach(dbenv, infop, destroy)
renv = ((REGINFO *)dbenv->reginfo)->primary;
rp = infop->rp;
+ if (F_ISSET(dbenv, DB_ENV_PRIVATE))
+ destroy = 1;
/* Lock the environment. */
- MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &renv->mutex);
/* Acquire the lock for the REGION. */
- MUTEX_LOCK(dbenv, &rp->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &rp->mutex);
/*
* We need to call destroy on per-subsystem info before
@@ -1011,7 +1058,7 @@ __db_r_detach(dbenv, infop, destroy)
/* Destroy the structure. */
if (infop->name != NULL)
- __os_freestr(infop->name);
+ __os_free(dbenv, infop->name);
return (ret);
}
@@ -1089,9 +1136,8 @@ __db_des_get(dbenv, env_infop, infop, rpp)
/* Initialize the region. */
memset(rp, 0, sizeof(*rp));
- if ((ret = __db_mutex_init(dbenv, &rp->mutex,
- R_OFFSET(env_infop, &rp->mutex) + DB_FCNTL_OFF_GEN,
- 0)) != 0) {
+ if ((ret = __db_mutex_setup(dbenv, env_infop, &rp->mutex,
+ MUTEX_NO_RECORD | MUTEX_NO_RLOCK)) != 0) {
__db_shalloc_free(env_infop->addr, rp);
return (ret);
}
@@ -1141,7 +1187,8 @@ __db_des_destroy(dbenv, rp)
* Fault the region into memory.
*/
static int
-__db_faultmem(addr, size, created)
+__db_faultmem(dbenv, addr, size, created)
+ DB_ENV *dbenv;
void *addr;
size_t size;
int created;
@@ -1162,7 +1209,7 @@ __db_faultmem(addr, size, created)
* that it doesn't figure out that we're never really using it.
*/
ret = 0;
- if (DB_GLOBAL(db_region_init)) {
+ if (F_ISSET(dbenv, DB_ENV_REGION_INIT)) {
if (created)
for (p = addr, t = (u_int8_t *)addr + size;
p < t; p += OS_VMPAGESIZE)
@@ -1190,13 +1237,17 @@ __db_region_destroy(dbenv, infop)
case REGION_TYPE_LOCK:
__lock_region_destroy(dbenv, infop);
break;
+ case REGION_TYPE_LOG:
+ __log_region_destroy(dbenv, infop);
+ break;
case REGION_TYPE_MPOOL:
__mpool_region_destroy(dbenv, infop);
break;
+ case REGION_TYPE_TXN:
+ __txn_region_destroy(dbenv, infop);
+ break;
case REGION_TYPE_ENV:
- case REGION_TYPE_LOG:
case REGION_TYPE_MUTEX:
- case REGION_TYPE_TXN:
break;
default:
DB_ASSERT(0);
diff --git a/bdb/examples_c/README b/bdb/examples_c/README
index f59ae00a608..d5475ba01b2 100644
--- a/bdb/examples_c/README
+++ b/bdb/examples_c/README
@@ -1,7 +1,9 @@
-# $Id: README,v 11.3 2000/12/13 06:32:29 krinsky Exp $
+# $Id: README,v 11.5 2002/02/26 16:22:45 krinsky Exp $
ex_access.c Using just the DB access methods.
+ex_apprec Application-specific recovery.
+
ex_btrec.c Using the BTREE access method with record numbers.
ex_env.c Setting up the DB environment.
@@ -10,6 +12,10 @@ ex_lock.c Locking.
ex_mpool.c Shared memory buffer pools.
+ex_repquote Replication. This creates a toy stock quote server
+ with DB's single-master, multiple-client replication,
+ with communication over TCP.
+
ex_tpcb.c TPC/B.
Ex_tpcb sets up a framework in which to run a TPC/B test.
Database initialization (the -i flag) and running the
diff --git a/bdb/examples_c/bench_001.c b/bdb/examples_c/bench_001.c
new file mode 100644
index 00000000000..14fd3e549b6
--- /dev/null
+++ b/bdb/examples_c/bench_001.c
@@ -0,0 +1,382 @@
+/*-
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: bench_001.c,v 1.13 2002/08/15 02:45:39 bostic Exp $
+ */
+
+/*
+ * bench_001 - time bulk fetch interface.
+ * Without -R builds a btree acording to the arguments.
+ * With -R runs and times bulk fetches. If -d is specified
+ * during reads the DB_MULTIPLE interface is used
+ * otherwise the DB_MULTIPLE_KEY interface is used.
+ *
+ * ARGUMENTS:
+ * -c cachesize [1000 * pagesize]
+ * -d number of duplicates [none]
+ * -E don't use environment
+ * -I Just initialize the environment
+ * -i number of read iterations [1000000]
+ * -l length of data item [20]
+ * -n number of keys [1000000]
+ * -p pagesize [65536]
+ * -R perform read test.
+ * -T incorporate transactions.
+ *
+ * COMPILE:
+ * cc -I /usr/local/BerkeleyDB/include \
+ * -o bench_001 -O2 bench_001.c /usr/local/BerkeleyDB/lib/libdb.so
+ */
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#define DATABASE "bench_001.db"
+
+int main(int, char *[]);
+void usage(void);
+
+const char
+ *progname = "bench_001"; /* Program name. */
+/*
+ * db_init --
+ * Initialize the environment.
+ */
+DB_ENV *
+db_init(home, prefix, cachesize, txn)
+ char *home, *prefix;
+ int cachesize, txn;
+{
+ DB_ENV *dbenv;
+ int flags, ret;
+
+ if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ dbenv->err(dbenv, ret, "db_env_create");
+ return (NULL);
+ }
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, prefix);
+ (void)dbenv->set_cachesize(dbenv, 0,
+ cachesize == 0 ? 50 * 1024 * 1024 : (u_int32_t)cachesize, 0);
+
+ flags = DB_CREATE | DB_INIT_MPOOL;
+ if (txn)
+ flags |= DB_INIT_TXN | DB_INIT_LOCK;
+ if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
+ (void)dbenv->close(dbenv, 0);
+ return (NULL);
+ }
+ return (dbenv);
+}
+
+/*
+ * get -- loop getting batches of records.
+ *
+ */
+int
+get(dbp, txn, datalen, num, dups, iter, countp)
+ DB *dbp;
+ int txn, datalen, num, dups, iter, *countp;
+{
+ DBC *dbcp;
+ DBT key, data;
+ DB_TXN *txnp;
+ u_int32_t len, klen;
+ int count, flags, i, j, ret;
+ void *pointer, *dp, *kp;
+
+ memset(&key, 0, sizeof(key));
+ key.data = &j;
+ key.size = sizeof(j);
+ memset(&data, 0, sizeof(data));
+ data.flags = DB_DBT_USERMEM;
+ data.data = malloc(datalen*1024*1024);
+ data.ulen = data.size = datalen*1024*1024;
+ count = 0;
+ flags = DB_SET;
+ if (!dups)
+ flags |= DB_MULTIPLE_KEY;
+ else
+ flags |= DB_MULTIPLE;
+ for (i = 0; i < iter; i++) {
+ txnp = NULL;
+ if (txn)
+ dbp->dbenv->txn_begin(dbp->dbenv, NULL, &txnp, 0);
+ dbp->cursor(dbp, txnp, &dbcp, 0);
+
+ j = random() % num;
+ switch (ret = dbcp->c_get(dbcp, &key, &data, flags)) {
+ case 0:
+ break;
+ default:
+ dbp->err(dbcp->dbp, ret, "DBC->c_get");
+ return (ret);
+ }
+ DB_MULTIPLE_INIT(pointer, &data);
+ if (dups)
+ while (pointer != NULL) {
+ DB_MULTIPLE_NEXT(pointer, &data, dp, len);
+ if (dp != NULL)
+ count++;
+ }
+ else
+ while (pointer != NULL) {
+ DB_MULTIPLE_KEY_NEXT(pointer,
+ &data, kp, klen, dp, len);
+ if (kp != NULL)
+ count++;
+ }
+ dbcp->c_close(dbcp);
+ if (txn)
+ txnp->commit(txnp, 0);
+ }
+
+ *countp = count;
+ return (0);
+}
+
+/*
+ * fill - fill a db
+ * Since we open/created the db with transactions (potentially),
+ * we need to populate it with transactions. We'll bundle the puts
+ * 10 to a transaction.
+ */
+#define PUTS_PER_TXN 10
+int
+fill(dbenv, dbp, txn, datalen, num, dups)
+ DB_ENV *dbenv;
+ DB *dbp;
+ int txn, datalen, num, dups;
+{
+ DBT key, data;
+ DB_TXN *txnp;
+ struct data {
+ int id;
+ char str[1];
+ } *data_val;
+ int count, i, ret;
+ /*
+ * Insert records into the database, where the key is the user
+ * input and the data is the user input in reverse order.
+ */
+ txnp = NULL;
+ ret = 0;
+ count = 0;
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ key.data = &i;
+ key.size = sizeof(i);
+ data.data = data_val = (struct data *) malloc(datalen);
+ memcpy(data_val->str, "0123456789012345678901234567890123456789",
+ datalen - sizeof (data_val->id));
+ data.size = datalen;
+ data.flags = DB_DBT_USERMEM;
+
+ for (i = 0; i < num; i++) {
+ if (txn != 0 && i % PUTS_PER_TXN == 0) {
+ if (txnp != NULL) {
+ ret = txnp->commit(txnp, 0);
+ txnp = NULL;
+ if (ret != 0)
+ goto err;
+ }
+ if ((ret =
+ dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
+ goto err;
+ }
+ data_val->id = 0;
+ do {
+ switch (ret =
+ dbp->put(dbp, txnp, &key, &data, 0)) {
+ case 0:
+ count++;
+ break;
+ default:
+ dbp->err(dbp, ret, "DB->put");
+ goto err;
+ }
+ } while (++data_val->id < dups);
+ }
+ if (txnp != NULL)
+ ret = txnp->commit(txnp, 0);
+
+ printf("%d\n", count);
+ return (ret);
+
+err: if (txnp != NULL)
+ (void)txnp->abort(txnp);
+ return (ret);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ DB *dbp;
+ DB_ENV *dbenv;
+ DB_TXN *txnp;
+ struct timeval start_time, end_time;
+ double secs;
+ int cache, ch, count, datalen, dups, env, init, iter, num, pagesize;
+ int ret, rflag, txn;
+
+ txnp = NULL;
+ datalen = 20;
+ iter = num = 1000000;
+ env = 1;
+ dups = init = rflag = txn = 0;
+
+ pagesize = 65536;
+ cache = 1000 * pagesize;
+
+ while ((ch = getopt(argc, argv, "c:d:EIi:l:n:p:RT")) != EOF)
+ switch (ch) {
+ case 'c':
+ cache = atoi(optarg);
+ break;
+ case 'd':
+ dups = atoi(optarg);
+ break;
+ case 'E':
+ env = 0;
+ break;
+ case 'I':
+ init = 1;
+ break;
+ case 'i':
+ iter = atoi(optarg);
+ break;
+ case 'l':
+ datalen = atoi(optarg);
+ break;
+ case 'n':
+ num = atoi(optarg);
+ break;
+ case 'p':
+ pagesize = atoi(optarg);
+ break;
+ case 'R':
+ rflag = 1;
+ break;
+ case 'T':
+ txn = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Remove the previous database. */
+ if (!rflag) {
+ if (env)
+ system("rm -rf BENCH_001; mkdir BENCH_001");
+ else
+ (void)unlink(DATABASE);
+ }
+
+ dbenv = NULL;
+ if (env == 1 &&
+ (dbenv = db_init("BENCH_001", "bench_001", cache, txn)) == NULL)
+ return (-1);
+ if (init)
+ exit(0);
+ /* Create and initialize database object, open the database. */
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
+ fprintf(stderr,
+ "%s: db_create: %s\n", progname, db_strerror(ret));
+ exit(EXIT_FAILURE);
+ }
+ dbp->set_errfile(dbp, stderr);
+ dbp->set_errpfx(dbp, progname);
+ if ((ret = dbp->set_pagesize(dbp, pagesize)) != 0) {
+ dbp->err(dbp, ret, "set_pagesize");
+ goto err1;
+ }
+ if (dups && (ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
+ dbp->err(dbp, ret, "set_flags");
+ goto err1;
+ }
+
+ if (env == 0 && (ret = dbp->set_cachesize(dbp, 0, cache, 0)) != 0) {
+ dbp->err(dbp, ret, "set_cachesize");
+ goto err1;
+ }
+
+ if ((ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
+ dbp->err(dbp, ret, "set_flags");
+ goto err1;
+ }
+
+ if (txn != 0)
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
+ goto err1;
+
+ if ((ret = dbp->open(
+ dbp, txnp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
+ dbp->err(dbp, ret, "%s: open", DATABASE);
+ if (txnp != NULL)
+ (void)txnp->abort(txnp);
+ goto err1;
+ }
+
+ if (txnp != NULL)
+ ret = txnp->commit(txnp, 0);
+ txnp = NULL;
+ if (ret != 0)
+ goto err1;
+
+ if (rflag) {
+ /* If no environment, fill the cache. */
+ if (!env && (ret =
+ get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
+ goto err1;
+
+ /* Time the get loop. */
+ gettimeofday(&start_time, NULL);
+ if ((ret =
+ get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
+ goto err1;
+ gettimeofday(&end_time, NULL);
+ secs =
+ (((double)end_time.tv_sec * 1000000 + end_time.tv_usec) -
+ ((double)start_time.tv_sec * 1000000 + start_time.tv_usec))
+ / 1000000;
+ printf("%d records read using %d batches in %.2f seconds: ",
+ count, iter, secs);
+ printf("%.0f records/second\n", (double)count / secs);
+
+ } else if ((ret = fill(dbenv, dbp, txn, datalen, num, dups)) != 0)
+ goto err1;
+
+ /* Close everything down. */
+ if ((ret = dbp->close(dbp, rflag ? DB_NOSYNC : 0)) != 0) {
+ fprintf(stderr,
+ "%s: DB->close: %s\n", progname, db_strerror(ret));
+ return (1);
+ }
+ return (ret);
+
+err1: (void)dbp->close(dbp, 0);
+ return (1);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: %s %s\n\t%s\n",
+ progname, "[-EIRT] [-c cachesize] [-d dups]",
+ "[-i iterations] [-l datalen] [-n keys] [-p pagesize]");
+ exit(EXIT_FAILURE);
+}
diff --git a/bdb/examples_c/ex_access.c b/bdb/examples_c/ex_access.c
index 3448daf43a3..5cac09ecf05 100644
--- a/bdb/examples_c/ex_access.c
+++ b/bdb/examples_c/ex_access.c
@@ -1,87 +1,69 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_access.c,v 11.7 2000/05/22 15:17:03 sue Exp $
+ * $Id: ex_access.c,v 11.22 2002/09/03 12:54:26 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#ifdef _WIN32
+extern int getopt(int, char * const *, const char *);
+#else
#include <unistd.h>
#endif
#include <db.h>
-#ifdef HAVE_VXWORKS
-#include "stdio.h"
-#define DATABASE "/vxtmp/vxtmp/access.db"
-#define ERROR_RETURN ERROR
-#else
#define DATABASE "access.db"
-#define ERROR_RETURN 1
-int main __P((int, char *[]));
-void usage __P((char *));
-#endif
-
-int ex_access __P((void));
+int main __P((int, char *[]));
+int usage __P((void));
-#ifndef HAVE_VXWORKS
int
main(argc, argv)
int argc;
char *argv[];
{
- extern char *optarg;
extern int optind;
- int ch;
+ DB *dbp;
+ DBC *dbcp;
+ DBT key, data;
+ u_int32_t len;
+ int ch, ret, rflag;
+ char *database, *p, *t, buf[1024], rbuf[1024];
+ const char *progname = "ex_access"; /* Program name. */
- while ((ch = getopt(argc, argv, "")) != EOF)
+ rflag = 0;
+ while ((ch = getopt(argc, argv, "r")) != EOF)
switch (ch) {
+ case 'r':
+ rflag = 1;
+ break;
case '?':
default:
- usage(argv[0]);
+ return (usage());
}
argc -= optind;
argv += optind;
- return (ex_access());
-}
-
-void
-usage(progname)
- char *progname;
-{
- (void)fprintf(stderr, "usage: %s\n", progname);
- exit(1);
-}
-#endif
-
-int
-ex_access()
-{
- DB *dbp;
- DBC *dbcp;
- DBT key, data;
- u_int32_t len;
- int ret;
- char *p, *t, buf[1024], rbuf[1024];
- const char *progname = "ex_access"; /* Program name. */
+ /* Accept optional database name. */
+ database = *argv == NULL ? DATABASE : argv[0];
- /* Remove the previous database. */
- (void)unlink(DATABASE);
+ /* Optionally discard the database. */
+ if (rflag)
+ (void)remove(database);
/* Create and initialize database object, open the database. */
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
fprintf(stderr,
"%s: db_create: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (EXIT_FAILURE);
}
dbp->set_errfile(dbp, stderr);
dbp->set_errpfx(dbp, progname);
@@ -93,9 +75,9 @@ ex_access()
dbp->err(dbp, ret, "set_cachesize");
goto err1;
}
- if ((ret =
- dbp->open(dbp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
- dbp->err(dbp, ret, "%s: open", DATABASE);
+ if ((ret = dbp->open(dbp,
+ NULL, database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
+ dbp->err(dbp, ret, "%s: open", database);
goto err1;
}
@@ -110,6 +92,8 @@ ex_access()
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
+ if (strcmp(buf, "exit\n") == 0 || strcmp(buf, "quit\n") == 0)
+ break;
if ((len = strlen(buf)) <= 1)
continue;
for (t = rbuf, p = buf + (len - 2); p >= buf;)
@@ -161,11 +145,18 @@ ex_access()
if ((ret = dbp->close(dbp, 0)) != 0) {
fprintf(stderr,
"%s: DB->close: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (EXIT_FAILURE);
}
- return (0);
+ return (EXIT_SUCCESS);
err2: (void)dbcp->c_close(dbcp);
err1: (void)dbp->close(dbp, 0);
- return (ERROR_RETURN);
+ return (EXIT_FAILURE);
+}
+
+int
+usage()
+{
+ (void)fprintf(stderr, "usage: ex_access [-r] [database]\n");
+ return (EXIT_FAILURE);
}
diff --git a/bdb/examples_c/ex_apprec/auto_rebuild b/bdb/examples_c/ex_apprec/auto_rebuild
new file mode 100644
index 00000000000..34251984888
--- /dev/null
+++ b/bdb/examples_c/ex_apprec/auto_rebuild
@@ -0,0 +1,9 @@
+# Script to rebuild automatically generated files for ex_apprec.
+
+E=../examples_c/ex_apprec
+
+cd ../../dist
+awk -f gen_rec.awk \
+ -v source_file=$E/ex_apprec_auto.c \
+ -v header_file=$E/ex_apprec_auto.h \
+ -v template_file=$E/ex_apprec_template < $E/ex_apprec.src
diff --git a/bdb/examples_c/ex_apprec/ex_apprec.c b/bdb/examples_c/ex_apprec/ex_apprec.c
new file mode 100644
index 00000000000..c045e734250
--- /dev/null
+++ b/bdb/examples_c/ex_apprec/ex_apprec.c
@@ -0,0 +1,267 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_apprec.c,v 1.2 2002/08/06 05:39:01 bostic Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#include "ex_apprec.h"
+
+int apprec_dispatch __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
+int open_env __P((const char *, FILE *, const char *, DB_ENV **));
+int verify_absence __P((DB_ENV *, const char *));
+int verify_presence __P((DB_ENV *, const char *));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_TXN *txn;
+ DBT dirnamedbt;
+ int ret;
+ const char *home;
+ char ch, dirname[256];
+ const char *progname = "ex_apprec"; /* Program name. */
+
+ /* Default home. */
+ home = "TESTDIR";
+
+ while ((ch = getopt(argc, argv, "h:")) != EOF)
+ switch (ch) {
+ case 'h':
+ home = optarg;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-h home]", progname);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Set up environment.\n");
+ if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
+ return (EXIT_FAILURE);
+
+ printf("Create a directory in a transaction.\n");
+ /*
+ * This application's convention is to log the full directory name,
+ * including trailing nul.
+ */
+ memset(&dirnamedbt, 0, sizeof(dirnamedbt));
+ sprintf(dirname, "%s/MYDIRECTORY", home);
+ dirnamedbt.data = dirname;
+ dirnamedbt.size = strlen(dirname) + 1;
+
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
+ dbenv->err(dbenv, ret, "txn_begin");
+ return (EXIT_FAILURE);
+ }
+
+ /* Remember, always log actions before you execute them! */
+ memset(&lsn, 0, sizeof(lsn));
+ if ((ret =
+ ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
+ dbenv->err(dbenv, ret, "mkdir_log");
+ return (EXIT_FAILURE);
+ }
+ if (mkdir(dirname, 0755) != 0) {
+ dbenv->err(dbenv, errno, "mkdir");
+ return (EXIT_FAILURE);
+ }
+
+ printf("Verify the directory's presence: ");
+ verify_presence(dbenv, dirname);
+ printf("check.\n");
+
+ /* Now abort the transaction and verify that the directory goes away. */
+ printf("Abort the transaction.\n");
+ if ((ret = txn->abort(txn)) != 0) {
+ dbenv->err(dbenv, ret, "txn_abort");
+ return (EXIT_FAILURE);
+ }
+
+ printf("Verify the directory's absence: ");
+ verify_absence(dbenv, dirname);
+ printf("check.\n");
+
+ /* Now do the same thing over again, only with a commit this time. */
+ printf("Create a directory in a transaction.\n");
+ memset(&dirnamedbt, 0, sizeof(dirnamedbt));
+ sprintf(dirname, "%s/MYDIRECTORY", home);
+ dirnamedbt.data = dirname;
+ dirnamedbt.size = strlen(dirname) + 1;
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
+ dbenv->err(dbenv, ret, "txn_begin");
+ return (EXIT_FAILURE);
+ }
+
+ memset(&lsn, 0, sizeof(lsn));
+ if ((ret =
+ ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
+ dbenv->err(dbenv, ret, "mkdir_log");
+ return (EXIT_FAILURE);
+ }
+ if (mkdir(dirname, 0755) != 0) {
+ dbenv->err(dbenv, errno, "mkdir");
+ return (EXIT_FAILURE);
+ }
+
+ printf("Verify the directory's presence: ");
+ verify_presence(dbenv, dirname);
+ printf("check.\n");
+
+ /* Now abort the transaction and verify that the directory goes away. */
+ printf("Commit the transaction.\n");
+ if ((ret = txn->commit(txn, 0)) != 0) {
+ dbenv->err(dbenv, ret, "txn_commit");
+ return (EXIT_FAILURE);
+ }
+
+ printf("Verify the directory's presence: ");
+ verify_presence(dbenv, dirname);
+ printf("check.\n");
+
+ printf("Now remove the directory, then run recovery.\n");
+ if ((ret = dbenv->close(dbenv, 0)) != 0) {
+ fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ if (rmdir(dirname) != 0) {
+ fprintf(stderr,
+ "%s: rmdir failed with error %s", progname,
+ strerror(errno));
+ }
+ verify_absence(dbenv, dirname);
+
+ /* Opening with DB_RECOVER runs recovery. */
+ if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
+ return (EXIT_FAILURE);
+
+ printf("Verify the directory's presence: ");
+ verify_presence(dbenv, dirname);
+ printf("check.\n");
+
+ /* Close the handle. */
+ if ((ret = dbenv->close(dbenv, 0)) != 0) {
+ fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+
+ return (EXIT_SUCCESS);
+}
+
+int
+open_env(home, errfp, progname, dbenvp)
+ const char *home, *progname;
+ FILE *errfp;
+ DB_ENV **dbenvp;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ /*
+ * Create an environment object and initialize it for error
+ * reporting.
+ */
+ if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
+ return (ret);
+ }
+ dbenv->set_errfile(dbenv, errfp);
+ dbenv->set_errpfx(dbenv, progname);
+
+ /* Set up our custom recovery dispatch function. */
+ if ((ret = dbenv->set_app_dispatch(dbenv, apprec_dispatch)) != 0) {
+ dbenv->err(dbenv, ret, "set_app_dispatch");
+ return (ret);
+ }
+
+ /*
+ * Open the environment with full transactional support, running
+ * recovery.
+ */
+ if ((ret =
+ dbenv->open(dbenv, home, DB_CREATE | DB_RECOVER | DB_INIT_LOCK |
+ DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) {
+ dbenv->err(dbenv, ret, "environment open: %s", home);
+ dbenv->close(dbenv, 0);
+ return (ret);
+ }
+
+ *dbenvp = dbenv;
+ return (0);
+}
+
+/*
+ * Sample application dispatch function to handle user-specified log record
+ * types.
+ */
+int
+apprec_dispatch(dbenv, dbt, lsn, op)
+ DB_ENV *dbenv;
+ DBT *dbt;
+ DB_LSN *lsn;
+ db_recops op;
+{
+ u_int32_t rectype;
+
+ /* Pull the record type out of the log record. */
+ memcpy(&rectype, dbt->data, sizeof(rectype));
+
+ switch (rectype) {
+ case DB_ex_apprec_mkdir:
+ return (ex_apprec_mkdir_recover(dbenv, dbt, lsn, op, NULL));
+ default:
+ /*
+ * We've hit an unexpected, allegedly user-defined record
+ * type.
+ */
+ dbenv->errx(dbenv, "Unexpected log record type encountered");
+ return (EINVAL);
+ }
+}
+
+int
+verify_absence(dbenv, dirname)
+ DB_ENV *dbenv;
+ const char *dirname;
+{
+
+ if (access(dirname, F_OK) == 0) {
+ dbenv->errx(dbenv, "Error--directory present!");
+ exit(EXIT_FAILURE);
+ }
+
+ return (0);
+}
+
+int
+verify_presence(dbenv, dirname)
+ DB_ENV *dbenv;
+ const char *dirname;
+{
+
+ if (access(dirname, F_OK) != 0) {
+ dbenv->errx(dbenv, "Error--directory not present!");
+ exit(EXIT_FAILURE);
+ }
+
+ return (0);
+}
diff --git a/bdb/examples_c/ex_apprec/ex_apprec.h b/bdb/examples_c/ex_apprec/ex_apprec.h
new file mode 100644
index 00000000000..9bbb567d4a6
--- /dev/null
+++ b/bdb/examples_c/ex_apprec/ex_apprec.h
@@ -0,0 +1,24 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_apprec.h,v 1.2 2002/08/08 15:47:00 bostic Exp $
+ */
+
+#ifndef _EX_APPREC_H_
+#define _EX_APPREC_H_
+
+#include "ex_apprec_auto.h"
+
+int ex_apprec_mkdir_log
+ __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t, const DBT *));
+int ex_apprec_mkdir_print
+ __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+int ex_apprec_mkdir_read
+ __P((DB_ENV *, void *, ex_apprec_mkdir_args **));
+int ex_apprec_mkdir_recover
+ __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+
+#endif /* !_EX_APPREC_H_ */
diff --git a/bdb/examples_c/ex_apprec/ex_apprec.src b/bdb/examples_c/ex_apprec/ex_apprec.src
new file mode 100644
index 00000000000..b048c504927
--- /dev/null
+++ b/bdb/examples_c/ex_apprec/ex_apprec.src
@@ -0,0 +1,41 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_apprec.src,v 1.3 2002/08/08 15:47:00 bostic Exp $
+ */
+
+PREFIX ex_apprec
+
+/*
+ * This is the source file used to generate the application-specific recovery
+ * functions used by the ex_apprec example. It should be turned into usable
+ * source code (including a template for the recovery function itself) by
+ * invoking changing to the dist directory of the DB distribution and
+ * running the gen_rec.awk script there as follows:
+ *
+ * awk -f ./gen_rec.awk \
+ * -v source_file=../examples_c/ex_apprec/ex_apprec_auto.c \
+ * -v header_file=../examples_c/ex_apprec/ex_apprec_auto.h \
+ * -v template_file=../examples_c/ex_apprec/ex_apprec_template \
+ * < ../examples_c/ex_apprec/ex_apprec.src
+
+INCLUDE #include <ctype.h>
+INCLUDE #include <errno.h>
+INCLUDE #include <stdlib.h>
+INCLUDE #include <string.h>
+INCLUDE
+INCLUDE #include <db.h>
+INCLUDE
+INCLUDE #include "ex_apprec.h"
+
+/*
+ * mkdir: used to create a directory
+ *
+ * dirname: relative or absolute pathname of the directory to be created
+ */
+BEGIN mkdir 10000
+DBT dirname DBT s
+END
diff --git a/bdb/examples_c/ex_apprec/ex_apprec_rec.c b/bdb/examples_c/ex_apprec/ex_apprec_rec.c
new file mode 100644
index 00000000000..8b6056d73f1
--- /dev/null
+++ b/bdb/examples_c/ex_apprec/ex_apprec_rec.c
@@ -0,0 +1,115 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_apprec_rec.c,v 1.2 2002/08/06 05:39:02 bostic Exp $
+ */
+
+/*
+ * This file is based on the template file ex_apprec_template. Note that
+ * because ex_apprec_mkdir, like most application-specific recovery functions,
+ * does not make use of DB-private structures, it has actually been simplified
+ * significantly.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#include "ex_apprec.h"
+
+/*
+ * ex_apprec_mkdir_recover --
+ * Recovery function for mkdir.
+ *
+ * PUBLIC: int ex_apprec_mkdir_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+ex_apprec_mkdir_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ ex_apprec_mkdir_args *argp;
+ int ret;
+
+ argp = NULL;
+
+ /*
+ * Shut up the compiler--"info" is used for the recovery functions
+ * belonging to transaction meta-operations such as txn_create, and
+ * need not concern us here either.
+ */
+ info = NULL;
+
+ if ((ret = ex_apprec_mkdir_read(dbenv, dbtp->data, &argp)) != 0)
+ goto out;
+
+ switch (op) {
+ case DB_TXN_ABORT:
+ case DB_TXN_BACKWARD_ROLL:
+ /*
+ * If we're aborting, we need to remove the directory if it
+ * exists. We log the trailing zero in pathnames, so we can
+ * simply pass the data part of the DBT into rmdir as a string.
+ * (Note that we don't have any alignment guarantees, but for
+ * a char * this doesn't matter.)
+ *
+ * Ignore all errors other than ENOENT; DB may attempt to undo
+ * or redo operations without knowing whether they have already
+ * been done or undone, so we should never assume in a recovery
+ * function that the task definitely needs doing or undoing.
+ */
+ ret = rmdir(argp->dirname.data);
+ if (ret != 0 && errno != ENOENT)
+ dbenv->err(dbenv, ret, "Error in abort of mkdir");
+ else
+ ret = 0;
+ break;
+ case DB_TXN_FORWARD_ROLL:
+ /*
+ * The forward direction is just the opposite; here, we ignore
+ * EEXIST, because the directory may already exist.
+ */
+ ret = mkdir(argp->dirname.data, 0755);
+ if (ret != 0 && errno != EEXIST)
+ dbenv->err(dbenv,
+ ret, "Error in roll-forward of mkdir");
+ else
+ ret = 0;
+ break;
+ default:
+ /*
+ * We might want to handle DB_TXN_PRINT or DB_TXN_APPLY here,
+ * too, but we don't try to print the log records and aren't
+ * using replication, so there's no need to in this example.
+ */
+ dbenv->errx(dbenv, "Unexpected operation type\n");
+ return (EINVAL);
+ }
+
+ /*
+ * The recovery function is responsible for returning the LSN of the
+ * previous log record in this transaction, so that transaction aborts
+ * can follow the chain backwards.
+ *
+ * (If we'd wanted the LSN of this record earlier, we could have
+ * read it from lsnp, as well--but because we weren't working with
+ * pages or other objects that store their LSN and base recovery
+ * decisions on it, we didn't need to.)
+ */
+ *lsnp = argp->prev_lsn;
+
+out: if (argp != NULL)
+ free(argp);
+ return (ret);
+}
diff --git a/bdb/examples_c/ex_btrec.c b/bdb/examples_c/ex_btrec.c
index b74f16b83e4..8e4aa3901d1 100644
--- a/bdb/examples_c/ex_btrec.c
+++ b/bdb/examples_c/ex_btrec.c
@@ -1,70 +1,32 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_btrec.c,v 11.8 2000/05/22 15:17:03 sue Exp $
+ * $Id: ex_btrec.c,v 11.18 2002/01/23 15:33:18 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#endif
#include <db.h>
-#ifdef HAVE_VXWORKS
-#define DATABASE "/vxtmp/vxtmp/access.db"
-#define WORDLIST "/vxtmp/vxtmp/wordlist"
-#define ERROR_RETURN ERROR
-#else
#define DATABASE "access.db"
#define WORDLIST "../test/wordlist"
-#define ERROR_RETURN 1
-int main __P((int, char *[]));
-void usage __P((char *));
-#endif
+int main __P((void));
int ex_btrec __P((void));
-void show __P((char *, DBT *, DBT *));
+void show __P((const char *, DBT *, DBT *));
-#ifndef HAVE_VXWORKS
int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- extern char *optarg;
- extern int optind;
- int ch;
-
- while ((ch = getopt(argc, argv, "")) != EOF)
- switch (ch) {
- case '?':
- default:
- usage(argv[0]);
- }
- argc -= optind;
- argv += optind;
-
- return (ex_btrec());
-}
-
-void
-usage(progname)
- char *progname;
+main()
{
- (void)fprintf(stderr, "usage: %s\n", progname);
- exit(1);
+ return (ex_btrec() == 1 ? EXIT_FAILURE : EXIT_SUCCESS);
}
-#endif
int
ex_btrec()
@@ -84,32 +46,32 @@ ex_btrec()
if ((fp = fopen(WORDLIST, "r")) == NULL) {
fprintf(stderr, "%s: open %s: %s\n",
progname, WORDLIST, db_strerror(errno));
- return (ERROR_RETURN);
+ return (1);
}
/* Remove the previous database. */
- (void)unlink(DATABASE);
+ (void)remove(DATABASE);
/* Create and initialize database object, open the database. */
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
fprintf(stderr,
"%s: db_create: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
dbp->set_errfile(dbp, stderr);
dbp->set_errpfx(dbp, progname); /* 1K page sizes. */
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
- return (ERROR_RETURN);
+ return (1);
} /* Record numbers. */
if ((ret = dbp->set_flags(dbp, DB_RECNUM)) != 0) {
dbp->err(dbp, ret, "set_flags: DB_RECNUM");
- return (ERROR_RETURN);
+ return (1);
}
- if ((ret =
- dbp->open(dbp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
+ if ((ret = dbp->open(dbp,
+ NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "open: %s", DATABASE);
- return (ERROR_RETURN);
+ return (1);
}
/*
@@ -144,7 +106,7 @@ ex_btrec()
(void)fclose(fp);
/* Print out the number of records in the database. */
- if ((ret = dbp->stat(dbp, &statp, NULL, 0)) != 0) {
+ if ((ret = dbp->stat(dbp, &statp, 0)) != 0) {
dbp->err(dbp, ret, "DB->stat");
goto err1;
}
@@ -215,7 +177,7 @@ get_err: dbp->err(dbp, ret, "DBcursor->get");
if ((ret = dbp->close(dbp, 0)) != 0) {
fprintf(stderr,
"%s: DB->close: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
return (0);
@@ -232,8 +194,8 @@ err1: (void)dbp->close(dbp, 0);
*/
void
show(msg, key, data)
+ const char *msg;
DBT *key, *data;
- char *msg;
{
printf("%s%.*s : %.*s\n", msg,
(int)key->size, (char *)key->data,
diff --git a/bdb/examples_c/ex_dbclient.c b/bdb/examples_c/ex_dbclient.c
index 27461a8923f..5baa640811f 100644
--- a/bdb/examples_c/ex_dbclient.c
+++ b/bdb/examples_c/ex_dbclient.c
@@ -1,22 +1,18 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_dbclient.c,v 1.12 2000/10/26 14:13:05 bostic Exp $
+ * $Id: ex_dbclient.c,v 1.28 2002/08/06 06:11:24 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#endif
#include <db.h>
@@ -24,52 +20,40 @@
#define DATABASE "access.db"
-int db_clientrun __P((DB_ENV *, char *));
-int ex_dbclient_run __P((char *, FILE *, char *, char *));
-#ifdef HAVE_VXWORKS
-int ex_dbclient __P((char *));
-#define ERROR_RETURN ERROR
-#define VXSHM_KEY 10
-#else
+int db_clientrun __P((DB_ENV *, const char *));
+int ex_dbclient_run __P((const char *, FILE *, const char *, const char *));
int main __P((int, char *[]));
-#define ERROR_RETURN 1
-#endif
/*
* An example of a program creating/configuring a Berkeley DB environment.
*/
-#ifndef HAVE_VXWORKS
int
main(argc, argv)
int argc;
char *argv[];
{
- char *home;
- int ret;
+ const char *home;
if (argc != 2) {
- fprintf(stderr, "Usage: %s hostname\n",argv[0]);
- exit(1);
+ fprintf(stderr, "Usage: %s hostname\n", argv[0]);
+ return (EXIT_FAILURE);
}
+
/*
* All of the shared database files live in DATABASE_HOME, but
* data files will live in CONFIG_DATA_DIR.
*/
home = DATABASE_HOME;
-
- if ((ret = ex_dbclient_run(home, stderr, argv[1], argv[0])) != 0)
- return (ret);
-
- return (0);
+ return (ex_dbclient_run(home,
+ stderr, argv[1], argv[0]) == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-#endif
int
ex_dbclient(host)
- char *host;
+ const char *host;
{
- char *home;
- char *progname = "ex_dbclient"; /* Program name. */
+ const char *home;
+ const char *progname = "ex_dbclient"; /* Program name. */
int ret;
/*
@@ -86,7 +70,7 @@ ex_dbclient(host)
int
ex_dbclient_run(home, errfp, host, progname)
- char *home, *host, *progname;
+ const char *home, *host, *progname;
FILE *errfp;
{
DB_ENV *dbenv;
@@ -98,35 +82,29 @@ ex_dbclient_run(home, errfp, host, progname)
*/
if ((ret = db_env_create(&dbenv, DB_CLIENT)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
- }
-#ifdef HAVE_VXWORKS
- if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) {
- fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
-#endif
retry = 0;
retry:
while (retry < 5) {
/*
* Set the server host we are talking to.
*/
- if ((ret =
- dbenv->set_server(dbenv, host, 10000, 10000, 0)) != 0) {
- fprintf(stderr, "Try %d: DBENV->set_server: %s\n",
+ if ((ret = dbenv->set_rpc_server(dbenv, NULL, host, 10000,
+ 10000, 0)) != 0) {
+ fprintf(stderr, "Try %d: DB_ENV->set_rpc_server: %s\n",
retry, db_strerror(ret));
retry++;
- if ((ret = __os_sleep(dbenv, 15, 0)) != 0)
- return (ret);
+ sleep(15);
} else
break;
}
if (retry >= 5) {
- fprintf(stderr, "DBENV->set_server: %s\n", db_strerror(ret));
+ fprintf(stderr,
+ "DB_ENV->set_rpc_server: %s\n", db_strerror(ret));
dbenv->close(dbenv, 0);
- return (ERROR_RETURN);
+ return (1);
}
/*
* We want to specify the shared memory buffer pool cachesize,
@@ -135,7 +113,7 @@ retry:
if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
dbenv->close(dbenv, 0);
- return (ERROR_RETURN);
+ return (1);
}
/*
* We have multiple processes reading/writing these files, so
@@ -143,12 +121,12 @@ retry:
* not logging or transactions.
*/
if ((ret = dbenv->open(dbenv, home,
- DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) {
+ DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL, 0)) != 0) {
dbenv->err(dbenv, ret, "environment open: %s", home);
dbenv->close(dbenv, 0);
if (ret == DB_NOSERVER)
goto retry;
- return (ERROR_RETURN);
+ return (1);
}
ret = db_clientrun(dbenv, progname);
@@ -158,8 +136,8 @@ retry:
/* Close the handle. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
- fprintf(stderr, "DBENV->close: %s\n", db_strerror(ret));
- return (ERROR_RETURN);
+ fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
+ return (1);
}
return (0);
}
@@ -167,7 +145,7 @@ retry:
int
db_clientrun(dbenv, progname)
DB_ENV *dbenv;
- char *progname;
+ const char *progname;
{
DB *dbp;
DBT key, data;
@@ -187,8 +165,8 @@ db_clientrun(dbenv, progname)
dbp->err(dbp, ret, "set_pagesize");
goto err1;
}
- if ((ret =
- dbp->open(dbp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
+ if ((ret = dbp->open(dbp,
+ NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "%s: open", DATABASE);
goto err1;
}
diff --git a/bdb/examples_c/ex_env.c b/bdb/examples_c/ex_env.c
index 5490723a31c..32257effb7b 100644
--- a/bdb/examples_c/ex_env.c
+++ b/bdb/examples_c/ex_env.c
@@ -1,21 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_env.c,v 11.18 2000/10/27 20:32:00 dda Exp $
+ * $Id: ex_env.c,v 11.27 2002/08/15 14:34:11 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#endif
#include <db.h>
@@ -27,40 +23,23 @@
#define DATABASE_HOME "\\tmp\\database"
#define CONFIG_DATA_DIR "\\database\\files"
#else
-#ifdef HAVE_VXWORKS
-#define DATABASE_HOME "/ata0/vxtmp/database"
-#define CONFIG_DATA_DIR "/vxtmp/vxtmp/database/files"
-#else
#define DATABASE_HOME "/tmp/database"
#define CONFIG_DATA_DIR "/database/files"
#endif
#endif
-#endif
-int db_setup __P((char *, char *, FILE *, char *));
-int db_teardown __P((char *, char *, FILE *, char *));
-#ifdef HAVE_VXWORKS
-int ex_env __P((void));
-#define ERROR_RETURN ERROR
-#define VXSHM_KEY 11
-#else
+int db_setup __P((const char *, const char *, FILE *, const char *));
+int db_teardown __P((const char *, const char *, FILE *, const char *));
int main __P((void));
-#define ERROR_RETURN 1
-#endif
/*
* An example of a program creating/configuring a Berkeley DB environment.
*/
int
-#ifdef HAVE_VXWORKS
-ex_env()
-#else
main()
-#endif
{
- int ret;
- char *data_dir, *home;
- char *progname = "ex_env"; /* Program name. */
+ const char *data_dir, *home;
+ const char *progname = "ex_env"; /* Program name. */
/*
* All of the shared database files live in DATABASE_HOME, but
@@ -70,19 +49,19 @@ main()
data_dir = CONFIG_DATA_DIR;
printf("Setup env\n");
- if ((ret = db_setup(home, data_dir, stderr, progname)) != 0)
- return (ret);
+ if (db_setup(home, data_dir, stderr, progname) != 0)
+ return (EXIT_FAILURE);
printf("Teardown env\n");
- if ((ret = db_teardown(home, data_dir, stderr, progname)) != 0)
- return (ret);
+ if (db_teardown(home, data_dir, stderr, progname) != 0)
+ return (EXIT_FAILURE);
- return (0);
+ return (EXIT_SUCCESS);
}
int
db_setup(home, data_dir, errfp, progname)
- char *home, *data_dir, *progname;
+ const char *home, *data_dir, *progname;
FILE *errfp;
{
DB_ENV *dbenv;
@@ -94,19 +73,11 @@ db_setup(home, data_dir, errfp, progname)
*/
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
dbenv->set_errfile(dbenv, errfp);
dbenv->set_errpfx(dbenv, progname);
-#ifdef HAVE_VXWORKS
- /* VxWorks needs to specify a base segment ID. */
- if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) {
- fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
- }
-#endif
-
/*
* We want to specify the shared memory buffer pool cachesize,
* but everything else is the default.
@@ -114,7 +85,7 @@ db_setup(home, data_dir, errfp, progname)
if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
dbenv->close(dbenv, 0);
- return (ERROR_RETURN);
+ return (1);
}
/* Databases are in a subdirectory. */
@@ -126,22 +97,22 @@ db_setup(home, data_dir, errfp, progname)
0)) != 0) {
dbenv->err(dbenv, ret, "environment open: %s", home);
dbenv->close(dbenv, 0);
- return (ERROR_RETURN);
+ return (1);
}
/* Do something interesting... */
/* Close the handle. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
- fprintf(stderr, "DBENV->close: %s\n", db_strerror(ret));
- return (ERROR_RETURN);
+ fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
+ return (1);
}
return (0);
}
int
db_teardown(home, data_dir, errfp, progname)
- char *home, *data_dir, *progname;
+ const char *home, *data_dir, *progname;
FILE *errfp;
{
DB_ENV *dbenv;
@@ -150,21 +121,15 @@ db_teardown(home, data_dir, errfp, progname)
/* Remove the shared database regions. */
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
dbenv->set_errfile(dbenv, errfp);
dbenv->set_errpfx(dbenv, progname);
-#ifdef HAVE_VXWORKS
- if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) {
- fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
- }
-#endif
(void)dbenv->set_data_dir(dbenv, data_dir);
if ((ret = dbenv->remove(dbenv, home, 0)) != 0) {
- fprintf(stderr, "DBENV->remove: %s\n", db_strerror(ret));
- return (ERROR_RETURN);
+ fprintf(stderr, "DB_ENV->remove: %s\n", db_strerror(ret));
+ return (1);
}
return (0);
}
diff --git a/bdb/examples_c/ex_lock.c b/bdb/examples_c/ex_lock.c
index e858be6b330..21a3584ceea 100644
--- a/bdb/examples_c/ex_lock.c
+++ b/bdb/examples_c/ex_lock.c
@@ -1,27 +1,28 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_lock.c,v 11.6 2001/01/04 14:23:29 dda Exp $
+ * $Id: ex_lock.c,v 11.18 2002/04/10 21:48:20 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
+
+#ifdef _WIN32
+extern int getopt(int, char * const *, const char *);
+#else
#include <unistd.h>
#endif
#include <db.h>
-void db_init __P((char *, u_int32_t, int));
-int main __P((int, char *[]));
-void usage __P((void));
+int db_init __P((const char *, u_int32_t, int));
+int main __P((int, char *[]));
+int usage __P((void));
DB_ENV *dbenv;
const char
@@ -41,7 +42,8 @@ main(argc, argv)
long held;
u_int32_t len, locker, maxlocks;
int ch, do_unlink, did_get, i, lockid, lockcount, ret;
- char *home, opbuf[16], objbuf[1024], lockbuf[16];
+ const char *home;
+ char opbuf[16], objbuf[1024], lockbuf[16];
home = "TESTDIR";
maxlocks = 0;
@@ -53,7 +55,7 @@ main(argc, argv)
break;
case 'm':
if ((i = atoi(optarg)) <= 0)
- usage();
+ return (usage());
maxlocks = (u_int32_t)i; /* XXX: possible overflow. */
break;
case 'u':
@@ -61,16 +63,17 @@ main(argc, argv)
break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
- usage();
+ return (usage());
/* Initialize the database environment. */
- db_init(home, maxlocks, do_unlink);
+ if ((ret = db_init(home, maxlocks, do_unlink)) != 0)
+ return (ret);
locks = 0;
lockcount = 0;
@@ -78,10 +81,10 @@ main(argc, argv)
/*
* Accept lock requests.
*/
- if ((ret = lock_id(dbenv, &locker)) != 0) {
+ if ((ret = dbenv->lock_id(dbenv, &locker)) != 0) {
dbenv->err(dbenv, ret, "unable to get locker id");
(void)dbenv->close(dbenv, 0);
- exit (1);
+ return (EXIT_FAILURE);
}
lockid = -1;
@@ -117,7 +120,7 @@ main(argc, argv)
lock_dbt.data = objbuf;
lock_dbt.size = strlen(objbuf);
- ret = lock_get(dbenv, locker,
+ ret = dbenv->lock_get(dbenv, locker,
DB_LOCK_NOWAIT, &lock_dbt, lock_type, &lock);
if (ret == 0) {
did_get = 1;
@@ -145,7 +148,7 @@ main(argc, argv)
continue;
}
lock = locks[lockid];
- ret = lock_put(dbenv, &lock);
+ ret = dbenv->lock_put(dbenv, &lock);
did_get = 0;
}
switch (ret) {
@@ -165,7 +168,7 @@ main(argc, argv)
dbenv->err(dbenv, ret,
"lock_%s", did_get ? "get" : "put");
(void)dbenv->close(dbenv, 0);
- exit (1);
+ return (EXIT_FAILURE);
}
}
@@ -177,18 +180,18 @@ main(argc, argv)
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr,
"%s: dbenv->close: %s\n", progname, db_strerror(ret));
- return (1);
+ return (EXIT_FAILURE);
}
- return (0);
+ return (EXIT_SUCCESS);
}
/*
* db_init --
* Initialize the environment.
*/
-void
+int
db_init(home, maxlocks, do_unlink)
- char *home;
+ const char *home;
u_int32_t maxlocks;
int do_unlink;
{
@@ -197,19 +200,19 @@ db_init(home, maxlocks, do_unlink)
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr, "%s: db_env_create: %s\n",
progname, db_strerror(ret));
- exit (1);
+ return (EXIT_FAILURE);
}
if (do_unlink) {
if ((ret = dbenv->remove(dbenv, home, DB_FORCE)) != 0) {
fprintf(stderr, "%s: dbenv->remove: %s\n",
progname, db_strerror(ret));
- exit (1);
+ return (EXIT_FAILURE);
}
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr, "%s: db_env_create: %s\n",
progname, db_strerror(ret));
- exit (1);
+ return (EXIT_FAILURE);
}
}
@@ -222,14 +225,15 @@ db_init(home, maxlocks, do_unlink)
dbenv->open(dbenv, home, DB_CREATE | DB_INIT_LOCK, 0)) != 0) {
dbenv->err(dbenv, ret, NULL);
(void)dbenv->close(dbenv, 0);
- exit(1);
+ return (EXIT_FAILURE);
}
+ return (0);
}
-void
+int
usage()
{
(void)fprintf(stderr,
"usage: %s [-u] [-h home] [-m maxlocks]\n", progname);
- exit(1);
+ return (EXIT_FAILURE);
}
diff --git a/bdb/examples_c/ex_mpool.c b/bdb/examples_c/ex_mpool.c
index 376c6647895..280adc48910 100644
--- a/bdb/examples_c/ex_mpool.c
+++ b/bdb/examples_c/ex_mpool.c
@@ -1,53 +1,35 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_mpool.c,v 11.13 2000/10/27 20:32:00 dda Exp $
+ * $Id: ex_mpool.c,v 11.26 2002/08/15 14:34:56 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
+
+#ifdef _WIN32
+extern int getopt(int, char * const *, const char *);
+#else
#include <unistd.h>
#endif
#include <db.h>
-int init __P((char *, int, int, char *));
-int run __P((int, int, int, int, char *));
-int run_mpool __P((int, int, int, int, char *));
-#ifdef HAVE_VXWORKS
-int ex_mpool __P((void));
-#define MPOOL "/vxtmp/vxtmp/mpool" /* File. */
-#define ERROR_RETURN ERROR
-#define VXSHM_KEY 12
-#else
+int init __P((const char *, int, int, const char *));
+int run __P((int, int, int, int, const char *));
+int run_mpool __P((int, int, int, int, const char *));
int main __P((int, char *[]));
-void usage __P((char *));
+int usage __P((const char *));
#define MPOOL "mpool" /* File. */
-#define ERROR_RETURN 1
-#endif
-#ifndef HAVE_VXWORKS
int
main(argc, argv)
int argc;
@@ -67,59 +49,45 @@ main(argc, argv)
switch (ch) {
case 'c':
if ((cachesize = atoi(optarg)) < 20 * 1024)
- usage(progname);
+ return (usage(progname));
break;
case 'h':
if ((hits = atoi(optarg)) <= 0)
- usage(progname);
+ return (usage(progname));
break;
case 'n':
if ((npages = atoi(optarg)) <= 0)
- usage(progname);
+ return (usage(progname));
break;
case 'p':
if ((pagesize = atoi(optarg)) <= 0)
- usage(progname);
+ return (usage(progname));
break;
case '?':
default:
- usage(progname);
+ return (usage(progname));
}
argc -= optind;
argv += optind;
- return (run_mpool(pagesize, cachesize, hits, npages, progname));
+ return (run_mpool(pagesize, cachesize,
+ hits, npages, progname) == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-void
+int
usage(progname)
- char *progname;
+ const char *progname;
{
(void)fprintf(stderr,
"usage: %s [-c cachesize] [-h hits] [-n npages] [-p pagesize]\n",
progname);
- exit(1);
+ return (EXIT_FAILURE);
}
-#else
-int
-ex_mpool()
-{
- char *progname = "ex_mpool"; /* Program name. */
- int cachesize, ch, hits, npages, pagesize;
-
- cachesize = 20 * 1024;
- hits = 1000;
- npages = 50;
- pagesize = 1024;
-
- return (run_mpool(pagesize, cachesize, hits, npages, progname));
-}
-#endif
int
run_mpool(pagesize, cachesize, hits, npages, progname)
int pagesize, cachesize, hits, npages;
- char *progname;
+ const char *progname;
{
int ret;
@@ -140,41 +108,38 @@ run_mpool(pagesize, cachesize, hits, npages, progname)
*/
int
init(file, pagesize, npages, progname)
- char *file, *progname;
+ const char *file, *progname;
int pagesize, npages;
{
- int cnt, flags, fd;
+ FILE *fp;
+ int cnt;
char *p;
/*
* Create a file with the right number of pages, and store a page
* number on each page.
*/
- flags = O_CREAT | O_RDWR | O_TRUNC;
-#ifdef DB_WIN32
- flags |= O_BINARY;
-#endif
- if ((fd = open(file, flags, 0666)) < 0) {
+ if ((fp = fopen(file, "wb")) == NULL) {
fprintf(stderr,
"%s: %s: %s\n", progname, file, strerror(errno));
- return (ERROR_RETURN);
+ return (1);
}
if ((p = (char *)malloc(pagesize)) == NULL) {
fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
- return (ERROR_RETURN);
+ return (1);
}
/* The pages are numbered from 0. */
for (cnt = 0; cnt <= npages; ++cnt) {
*(int *)p = cnt;
- if (write(fd, p, pagesize) != pagesize) {
+ if (fwrite(p, pagesize, 1, fp) != 1) {
fprintf(stderr,
"%s: %s: %s\n", progname, file, strerror(errno));
- return (ERROR_RETURN);
+ return (1);
}
}
- (void)close(fd);
+ (void)fclose(fp);
free(p);
return (0);
}
@@ -186,14 +151,17 @@ init(file, pagesize, npages, progname)
int
run(hits, cachesize, pagesize, npages, progname)
int hits, cachesize, pagesize, npages;
- char *progname;
+ const char *progname;
{
DB_ENV *dbenv;
- DB_MPOOLFILE *dbmfp;
+ DB_MPOOLFILE *mfp;
db_pgno_t pageno;
int cnt, ret;
void *p;
+ dbenv = NULL;
+ mfp = NULL;
+
printf("%s: cachesize: %d; pagesize: %d; N pages: %d\n",
progname, cachesize, pagesize, npages);
@@ -204,35 +172,38 @@ run(hits, cachesize, pagesize, npages, progname)
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
#ifdef HAVE_VXWORKS
if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) {
dbenv->err(dbenv, ret, "set_shm_key");
- return (ERROR_RETURN);
+ return (1);
}
#endif
/* Set the cachesize. */
if ((ret = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
- goto err1;
+ goto err;
}
/* Open the environment. */
if ((ret = dbenv->open(
dbenv, NULL, DB_CREATE | DB_INIT_MPOOL, 0)) != 0) {
- dbenv->err(dbenv, ret, "open");
- goto err1;
+ dbenv->err(dbenv, ret, "DB_ENV->open");
+ goto err;
}
/* Open the file in the environment. */
- if ((ret =
- memp_fopen(dbenv, MPOOL, 0, 0, pagesize, NULL, &dbmfp)) != 0) {
- dbenv->err(dbenv, ret, "memp_fopen: %s", MPOOL);
- goto err1;
+ if ((ret = dbenv->memp_fcreate(dbenv, &mfp, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB_ENV->memp_fcreate: %s", MPOOL);
+ goto err;
+ }
+ if ((ret = mfp->open(mfp, MPOOL, 0, 0, pagesize)) != 0) {
+ dbenv->err(dbenv, ret, "DB_MPOOLFILE->open: %s", MPOOL);
+ goto err;
}
printf("retrieve %d random pages... ", hits);
@@ -240,41 +211,43 @@ run(hits, cachesize, pagesize, npages, progname)
srand((u_int)time(NULL));
for (cnt = 0; cnt < hits; ++cnt) {
pageno = (rand() % npages) + 1;
- if ((ret = memp_fget(dbmfp, &pageno, 0, &p)) != 0) {
+ if ((ret = mfp->get(mfp, &pageno, 0, &p)) != 0) {
dbenv->err(dbenv, ret,
"unable to retrieve page %lu", (u_long)pageno);
- goto err2;
+ goto err;
}
if (*(db_pgno_t *)p != pageno) {
dbenv->errx(dbenv,
"wrong page retrieved (%lu != %d)",
(u_long)pageno, *(int *)p);
- goto err2;
+ goto err;
}
- if ((ret = memp_fput(dbmfp, p, 0)) != 0) {
+ if ((ret = mfp->put(mfp, p, 0)) != 0) {
dbenv->err(dbenv, ret,
"unable to return page %lu", (u_long)pageno);
- goto err2;
+ goto err;
}
}
printf("successful.\n");
/* Close the file. */
- if ((ret = memp_fclose(dbmfp)) != 0) {
- dbenv->err(dbenv, ret, "memp_fclose");
- goto err1;
+ if ((ret = mfp->close(mfp, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB_MPOOLFILE->close");
+ goto err;
}
/* Close the pool. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
+ return (1);
}
return (0);
-err2: (void)memp_fclose(dbmfp);
-err1: (void)dbenv->close(dbenv, 0);
- return (ERROR_RETURN);
+err: if (mfp != NULL)
+ (void)mfp->close(mfp, 0);
+ if (dbenv != NULL)
+ (void)dbenv->close(dbenv, 0);
+ return (1);
}
diff --git a/bdb/examples_c/ex_repquote/ex_repquote.h b/bdb/examples_c/ex_repquote/ex_repquote.h
new file mode 100644
index 00000000000..74a0860e050
--- /dev/null
+++ b/bdb/examples_c/ex_repquote/ex_repquote.h
@@ -0,0 +1,69 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_repquote.h,v 1.27 2002/04/23 04:27:50 krinsky Exp $
+ */
+
+#ifndef _EX_REPQUOTE_H_
+#define _EX_REPQUOTE_H_
+
+#define SELF_EID 1
+
+typedef struct {
+ char *host; /* Host name. */
+ u_int32_t port; /* Port on which to connect to this site. */
+} repsite_t;
+
+/* Globals */
+extern int master_eid;
+extern char *myaddr;
+
+struct __member; typedef struct __member member_t;
+struct __machtab; typedef struct __machtab machtab_t;
+
+/* Arguments for the connect_all thread. */
+typedef struct {
+ DB_ENV *dbenv;
+ const char *progname;
+ const char *home;
+ machtab_t *machtab;
+ repsite_t *sites;
+ int nsites;
+} all_args;
+
+/* Arguments for the connect_loop thread. */
+typedef struct {
+ DB_ENV *dbenv;
+ const char * home;
+ const char * progname;
+ machtab_t *machtab;
+ int port;
+} connect_args;
+
+#define CACHESIZE (10 * 1024 * 1024)
+#define DATABASE "quote.db"
+#define SLEEPTIME 3
+
+void *connect_all __P((void *args));
+void *connect_thread __P((void *args));
+int doclient __P((DB_ENV *, const char *, machtab_t *));
+int domaster __P((DB_ENV *, const char *));
+int get_accepted_socket __P((const char *, int));
+int get_connected_socket __P((machtab_t *, const char *, const char *, int, int *, int *));
+int get_next_message __P((int, DBT *, DBT *));
+int listen_socket_init __P((const char *, int));
+int listen_socket_accept __P((machtab_t *, const char *, int, int *));
+int machtab_getinfo __P((machtab_t *, int, u_int32_t *, int *));
+int machtab_init __P((machtab_t **, int, int));
+void machtab_parm __P((machtab_t *, int *, int *, u_int32_t *));
+int machtab_rem __P((machtab_t *, int, int));
+int quote_send __P((DB_ENV *, const DBT *, const DBT *, int, u_int32_t));
+
+#ifndef COMPQUIET
+#define COMPQUIET(x,y) x = (y)
+#endif
+
+#endif /* !_EX_REPQUOTE_H_ */
diff --git a/bdb/examples_c/ex_repquote/ex_rq_client.c b/bdb/examples_c/ex_repquote/ex_rq_client.c
new file mode 100644
index 00000000000..d382fe84fc7
--- /dev/null
+++ b/bdb/examples_c/ex_repquote/ex_rq_client.c
@@ -0,0 +1,250 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_rq_client.c,v 1.29 2002/01/23 15:33:19 bostic Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#include "ex_repquote.h"
+
+static void *check_loop __P((void *));
+static void *display_loop __P((void *));
+static int print_stocks __P((DBC *));
+
+typedef struct {
+ const char *progname;
+ DB_ENV *dbenv;
+} disploop_args;
+
+typedef struct {
+ DB_ENV *dbenv;
+ machtab_t *machtab;
+} checkloop_args;
+
+int
+doclient(dbenv, progname, machtab)
+ DB_ENV *dbenv;
+ const char *progname;
+ machtab_t *machtab;
+{
+ checkloop_args cargs;
+ disploop_args dargs;
+ pthread_t check_thr, disp_thr;
+ void *cstatus, *dstatus;
+ int rval, s;
+
+ rval = EXIT_SUCCESS;
+ s = -1;
+
+ memset(&dargs, 0, sizeof(dargs));
+ dstatus = (void *)EXIT_FAILURE;
+
+ dargs.progname = progname;
+ dargs.dbenv = dbenv;
+ if (pthread_create(&disp_thr, NULL, display_loop, (void *)&dargs)) {
+ dbenv->err(dbenv, errno, "display_loop pthread_create failed");
+ goto err;
+ }
+
+ cargs.dbenv = dbenv;
+ cargs.machtab = machtab;
+ if (pthread_create(&check_thr, NULL, check_loop, (void *)&cargs)) {
+ dbenv->err(dbenv, errno, "check_thread pthread_create failed");
+ goto err;
+ }
+ if (pthread_join(disp_thr, &dstatus) ||
+ pthread_join(check_thr, &cstatus)) {
+ dbenv->err(dbenv, errno, "pthread_join failed");
+ goto err;
+ }
+
+ if (0) {
+err: rval = EXIT_FAILURE;
+ }
+ return (rval);
+}
+
+/*
+ * Our only job is to check that the master is valid and if it's not
+ * for an extended period, to trigger an election. We do two phases.
+ * If we do not have a master, first we send out a request for a master
+ * to identify itself (that would be a call to rep_start). If that fails,
+ * we trigger an election.
+ */
+static void *
+check_loop(args)
+ void *args;
+{
+ DB_ENV *dbenv;
+ DBT dbt;
+ checkloop_args *cargs;
+ int count, n, pri;
+ machtab_t *machtab;
+ u_int32_t timeout;
+
+ cargs = (checkloop_args *)args;
+ dbenv = cargs->dbenv;
+ machtab = cargs->machtab;
+
+#define IDLE_INTERVAL 1
+
+ count = 0;
+ while (master_eid == DB_EID_INVALID) {
+ /*
+ * Call either rep_start or rep_elect depending on if
+ * count is 0 or 1.
+ */
+
+ if (count == 0) {
+ memset(&dbt, 0, sizeof(dbt));
+ dbt.data = myaddr;
+ dbt.size = strlen(myaddr) + 1;
+ (void)dbenv->rep_start(dbenv, &dbt, DB_REP_CLIENT);
+ count = 1;
+ } else {
+ machtab_parm(machtab, &n, &pri, &timeout);
+ (void)dbenv->rep_elect(dbenv,
+ n, pri, timeout, &master_eid);
+ count = 0;
+ }
+ sleep(IDLE_INTERVAL);
+ }
+
+ return ((void *)EXIT_SUCCESS);
+}
+
+static void *
+display_loop(args)
+ void *args;
+{
+ DB *dbp;
+ DB_ENV *dbenv;
+ DBC *dbc;
+ const char *progname;
+ disploop_args *dargs;
+ int ret, rval;
+
+ dargs = (disploop_args *)args;
+ progname = dargs->progname;
+ dbenv = dargs->dbenv;
+
+ dbc = NULL;
+ dbp = NULL;
+
+ for (;;) {
+ /* If we become master, shut this loop off. */
+ if (master_eid == SELF_EID)
+ break;
+
+ if (dbp == NULL) {
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
+ dbenv->err(dbenv, ret, "db_create");
+ return ((void *)EXIT_FAILURE);
+ }
+
+ if ((ret = dbp->open(dbp, NULL,
+ DATABASE, NULL, DB_BTREE, DB_RDONLY, 0)) != 0) {
+ if (ret == ENOENT) {
+ printf(
+ "No stock database yet available.\n");
+ if ((ret = dbp->close(dbp, 0)) != 0) {
+ dbenv->err(dbenv,
+ ret, "DB->close");
+ goto err;
+ }
+ dbp = NULL;
+ sleep(SLEEPTIME);
+ continue;
+ }
+ dbenv->err(dbenv, ret, "DB->open");
+ goto err;
+ }
+ }
+
+ if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->cursor");
+ goto err;
+ }
+
+ if ((ret = print_stocks(dbc)) != 0) {
+ dbenv->err(dbenv, ret, "database traversal failed");
+ goto err;
+ }
+
+ if ((ret = dbc->c_close(dbc)) != 0) {
+ dbenv->err(dbenv, ret, "DB->close");
+ goto err;
+ }
+
+ dbc = NULL;
+
+ sleep(SLEEPTIME);
+ }
+
+ rval = EXIT_SUCCESS;
+
+ if (0) {
+err: rval = EXIT_FAILURE;
+ }
+
+ if (dbc != NULL && (ret = dbc->c_close(dbc)) != 0) {
+ dbenv->err(dbenv, ret, "DB->close");
+ rval = EXIT_FAILURE;
+ }
+
+ if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->close");
+ return ((void *)EXIT_FAILURE);
+ }
+
+ return ((void *)rval);
+}
+
+static int
+print_stocks(dbc)
+ DBC *dbc;
+{
+ DBT key, data;
+#define MAXKEYSIZE 10
+#define MAXDATASIZE 20
+ char keybuf[MAXKEYSIZE + 1], databuf[MAXDATASIZE + 1];
+ int ret;
+ u_int32_t keysize, datasize;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ printf("\tSymbol\tPrice\n");
+ printf("\t======\t=====\n");
+
+ for (ret = dbc->c_get(dbc, &key, &data, DB_FIRST);
+ ret == 0;
+ ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) {
+ keysize = key.size > MAXKEYSIZE ? MAXKEYSIZE : key.size;
+ memcpy(keybuf, key.data, keysize);
+ keybuf[keysize] = '\0';
+
+ datasize = data.size >= MAXDATASIZE ? MAXDATASIZE : data.size;
+ memcpy(databuf, data.data, datasize);
+ databuf[datasize] = '\0';
+
+ printf("\t%s\t%s\n", keybuf, databuf);
+ }
+ printf("\n");
+ return (ret == DB_NOTFOUND ? 0 : ret);
+}
diff --git a/bdb/examples_c/ex_repquote/ex_rq_main.c b/bdb/examples_c/ex_repquote/ex_rq_main.c
new file mode 100644
index 00000000000..03819728679
--- /dev/null
+++ b/bdb/examples_c/ex_repquote/ex_rq_main.c
@@ -0,0 +1,303 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_rq_main.c,v 1.23 2002/08/06 05:39:03 bostic Exp $
+ */
+
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#include "ex_repquote.h"
+
+/*
+ * Process globals (we could put these in the machtab I suppose.
+ */
+int master_eid;
+char *myaddr;
+
+static int env_init __P((const char *, const char *, DB_ENV **, machtab_t *,
+ u_int32_t));
+static void usage __P((const char *));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ DB_ENV *dbenv;
+ DBT local;
+ enum { MASTER, CLIENT, UNKNOWN } whoami;
+ all_args aa;
+ connect_args ca;
+ machtab_t *machtab;
+ pthread_t all_thr, conn_thr;
+ repsite_t site, *sitep, self, *selfp;
+ struct sigaction sigact;
+ int maxsites, nsites, ret, priority, totalsites;
+ char *c, ch;
+ const char *home, *progname;
+ void *astatus, *cstatus;
+
+ master_eid = DB_EID_INVALID;
+
+ dbenv = NULL;
+ whoami = UNKNOWN;
+ machtab = NULL;
+ selfp = sitep = NULL;
+ maxsites = nsites = ret = totalsites = 0;
+ priority = 100;
+ home = "TESTDIR";
+ progname = "ex_repquote";
+
+ while ((ch = getopt(argc, argv, "Ch:Mm:n:o:p:")) != EOF)
+ switch (ch) {
+ case 'M':
+ whoami = MASTER;
+ master_eid = SELF_EID;
+ break;
+ case 'C':
+ whoami = CLIENT;
+ break;
+ case 'h':
+ home = optarg;
+ break;
+ case 'm':
+ if ((myaddr = strdup(optarg)) == NULL) {
+ fprintf(stderr,
+ "System error %s\n", strerror(errno));
+ goto err;
+ }
+ self.host = optarg;
+ self.host = strtok(self.host, ":");
+ if ((c = strtok(NULL, ":")) == NULL) {
+ fprintf(stderr, "Bad host specification.\n");
+ goto err;
+ }
+ self.port = atoi(c);
+ selfp = &self;
+ break;
+ case 'n':
+ totalsites = atoi(optarg);
+ break;
+ case 'o':
+ site.host = optarg;
+ site.host = strtok(site.host, ":");
+ if ((c = strtok(NULL, ":")) == NULL) {
+ fprintf(stderr, "Bad host specification.\n");
+ goto err;
+ }
+ site.port = atoi(c);
+ if (sitep == NULL || nsites >= maxsites) {
+ maxsites = maxsites == 0 ? 10 : 2 * maxsites;
+ if ((sitep = realloc(sitep,
+ maxsites * sizeof(repsite_t))) == NULL) {
+ fprintf(stderr, "System error %s\n",
+ strerror(errno));
+ goto err;
+ }
+ }
+ sitep[nsites++] = site;
+ break;
+ case 'p':
+ priority = atoi(optarg);
+ break;
+ case '?':
+ default:
+ usage(progname);
+ }
+
+ /* Error check command line. */
+ if (whoami == UNKNOWN) {
+ fprintf(stderr, "Must specify -M or -C.\n");
+ goto err;
+ }
+
+ if (selfp == NULL)
+ usage(progname);
+
+ if (home == NULL)
+ usage(progname);
+
+ /*
+ * Turn off SIGPIPE so that we don't kill processes when they
+ * happen to lose a connection at the wrong time.
+ */
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = SIG_IGN;
+ if ((ret = sigaction(SIGPIPE, &sigact, NULL)) != 0) {
+ fprintf(stderr,
+ "Unable to turn off SIGPIPE: %s\n", strerror(ret));
+ goto err;
+ }
+
+ /*
+ * We are hardcoding priorities here that all clients have the
+ * same priority except for a designated master who gets a higher
+ * priority.
+ */
+ if ((ret =
+ machtab_init(&machtab, priority, totalsites)) != 0)
+ goto err;
+
+ /*
+ * We can know open our environment, although we're not ready to
+ * begin replicating. However, we want to have a dbenv around
+ * so that we can send it into any of our message handlers.
+ */
+ if ((ret = env_init(progname, home, &dbenv, machtab, DB_RECOVER)) != 0)
+ goto err;
+
+ /*
+ * Now sets up comm infrastructure. There are two phases. First,
+ * we open our port for listening for incoming connections. Then
+ * we attempt to connect to every host we know about.
+ */
+
+ ca.dbenv = dbenv;
+ ca.home = home;
+ ca.progname = progname;
+ ca.machtab = machtab;
+ ca.port = selfp->port;
+ if ((ret = pthread_create(&conn_thr, NULL, connect_thread, &ca)) != 0)
+ goto err;
+
+ aa.dbenv = dbenv;
+ aa.progname = progname;
+ aa.home = home;
+ aa.machtab = machtab;
+ aa.sites = sitep;
+ aa.nsites = nsites;
+ if ((ret = pthread_create(&all_thr, NULL, connect_all, &aa)) != 0)
+ goto err;
+
+ /*
+ * We have now got the entire communication infrastructure set up.
+ * It's time to declare ourselves to be a client or master.
+ */
+ if (whoami == MASTER) {
+ if ((ret = dbenv->rep_start(dbenv, NULL, DB_REP_MASTER)) != 0) {
+ dbenv->err(dbenv, ret, "dbenv->rep_start failed");
+ goto err;
+ }
+ if ((ret = domaster(dbenv, progname)) != 0) {
+ dbenv->err(dbenv, ret, "Master failed");
+ goto err;
+ }
+ } else {
+ memset(&local, 0, sizeof(local));
+ local.data = myaddr;
+ local.size = strlen(myaddr) + 1;
+ if ((ret =
+ dbenv->rep_start(dbenv, &local, DB_REP_CLIENT)) != 0) {
+ dbenv->err(dbenv, ret, "dbenv->rep_start failed");
+ goto err;
+ }
+ /* Sleep to give ourselves a minute to find a master. */
+ sleep(5);
+ if ((ret = doclient(dbenv, progname, machtab)) != 0) {
+ dbenv->err(dbenv, ret, "Client failed");
+ goto err;
+ }
+
+ }
+
+ /* Wait on the connection threads. */
+ if (pthread_join(all_thr, &astatus) || pthread_join(conn_thr, &cstatus))
+ ret = errno;
+ if (ret == 0 &&
+ ((int)astatus != EXIT_SUCCESS || (int)cstatus != EXIT_SUCCESS))
+ ret = -1;
+
+err: if (machtab != NULL)
+ free(machtab);
+ if (dbenv != NULL)
+ (void)dbenv->close(dbenv, 0);
+ return (ret);
+}
+
+/*
+ * In this application, we specify all communication via the command line.
+ * In a real application, we would expect that information about the other
+ * sites in the system would be maintained in some sort of configuration
+ * file. The critical part of this interface is that we assume at startup
+ * that we can find out 1) what host/port we wish to listen on for connections,
+ * 2) a (possibly empty) list of other sites we should attempt to connect to.
+ * 3) whether we are a master or client (if we don't know, we should come up
+ * as a client and see if there is a master out there) and 4) what our
+ * Berkeley DB home environment is.
+ *
+ * These pieces of information are expressed by the following flags.
+ * -m host:port (required; m stands for me)
+ * -o host:port (optional; o stands for other; any number of these may be
+ * specified)
+ * -[MC] M for master/C for client
+ * -h home directory
+ * -n nsites (optional; number of sites in replication group; defaults to 0
+ * in which case we try to dynamically compute the number of sites in
+ * the replication group.)
+ * -p priority (optional: defaults to 100)
+ */
+static void
+usage(progname)
+ const char *progname;
+{
+ fprintf(stderr, "usage: %s ", progname);
+ fprintf(stderr, "[-CM][-h home][-o host:port][-m host:port]%s",
+ "[-n nsites][-p priority]\n");
+ exit(EXIT_FAILURE);
+}
+
+/* Open and configure an environment. */
+int
+env_init(progname, home, dbenvp, machtab, flags)
+ const char *progname, *home;
+ DB_ENV **dbenvp;
+ machtab_t *machtab;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int ret;
+ char *prefix;
+
+ if ((prefix = malloc(strlen(progname) + 2)) == NULL) {
+ fprintf(stderr,
+ "%s: System error: %s\n", progname, strerror(errno));
+ return (errno);
+ }
+ sprintf(prefix, "%s:", progname);
+
+ if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ fprintf(stderr, "%s: env create failed: %s\n",
+ progname, db_strerror(ret));
+ return (ret);
+ }
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, prefix);
+ /* (void)dbenv->set_verbose(dbenv, DB_VERB_REPLICATION, 1); */
+ (void)dbenv->set_cachesize(dbenv, 0, CACHESIZE, 0);
+ /* (void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1); */
+
+ dbenv->app_private = machtab;
+ (void)dbenv->set_rep_transport(dbenv, SELF_EID, quote_send);
+
+ flags |= DB_CREATE | DB_THREAD |
+ DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
+
+ ret = dbenv->open(dbenv, home, flags, 0);
+
+ *dbenvp = dbenv;
+ return (ret);
+}
diff --git a/bdb/examples_c/ex_repquote/ex_rq_master.c b/bdb/examples_c/ex_repquote/ex_rq_master.c
new file mode 100644
index 00000000000..bb3f37f55b9
--- /dev/null
+++ b/bdb/examples_c/ex_repquote/ex_rq_master.c
@@ -0,0 +1,165 @@
+/*-
+ * #include <pthread.h>
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_rq_master.c,v 1.22 2002/08/06 05:39:03 bostic Exp $
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#include "ex_repquote.h"
+
+static void *master_loop __P((void *));
+
+#define BUFSIZE 1024
+
+int
+domaster(dbenv, progname)
+ DB_ENV *dbenv;
+ const char *progname;
+{
+ int ret, t_ret;
+ pthread_t interface_thr;
+ pthread_attr_t attr;
+
+ COMPQUIET(progname, NULL);
+
+ /* Spawn off a thread to handle the basic master interface. */
+ if ((ret = pthread_attr_init(&attr)) != 0 &&
+ (ret = pthread_attr_setdetachstate(&attr,
+ PTHREAD_CREATE_DETACHED)) != 0)
+ goto err;
+
+ if ((ret = pthread_create(&interface_thr,
+ &attr, master_loop, (void *)dbenv)) != 0)
+ goto err;
+
+err: if ((t_ret = pthread_attr_destroy(&attr)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+static void *
+master_loop(dbenvv)
+ void *dbenvv;
+{
+ DB *dbp;
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DBT key, data;
+ char buf[BUFSIZE], *rbuf;
+ int ret;
+
+ dbp = NULL;
+ txn = NULL;
+
+ dbenv = (DB_ENV *)dbenvv;
+ /*
+ * Check if the database exists and if it verifies cleanly.
+ * If it does, run with it; else recreate it and go. Note
+ * that we have to verify outside of the environment.
+ */
+#ifdef NOTDEF
+ if ((ret = db_create(&dbp, NULL, 0)) != 0)
+ return (ret);
+ if ((ret = dbp->verify(dbp, DATABASE, NULL, NULL, 0)) != 0) {
+ if ((ret = dbp->remove(dbp, DATABASE, NULL, 0)) != 0 &&
+ ret != DB_NOTFOUND && ret != ENOENT)
+ return (ret);
+#endif
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return ((void *)ret);
+
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
+ goto err;
+ if ((ret = dbp->open(dbp, txn, DATABASE,
+ NULL, DB_BTREE, DB_CREATE /* | DB_THREAD */, 0)) != 0)
+ goto err;
+ ret = txn->commit(txn, 0);
+ txn = NULL;
+ if (ret != 0) {
+ dbp = NULL;
+ goto err;
+ }
+
+#ifdef NOTDEF
+ } else {
+ /* Reopen in the environment. */
+ if ((ret = dbp->close(dbp, 0)) != 0)
+ return (ret);
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return (ret);
+ if ((ret = dbp->open(dbp,
+ DATABASE, NULL, DB_UNKNOWN, DB_THREAD, 0)) != 0)
+ goto err;
+ }
+#endif
+ /*
+ * XXX
+ * It would probably be kind of cool to do this in Tcl and
+ * have a nice GUI. It would also be cool to be independently
+ * wealthy.
+ */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ for (;;) {
+ printf("QUOTESERVER> ");
+ fflush(stdout);
+
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ break;
+ (void)strtok(&buf[0], " \t\n");
+ rbuf = strtok(NULL, " \t\n");
+ if (rbuf == NULL || rbuf[0] == '\0') {
+ if (strncmp(buf, "exit", 4) == 0 ||
+ strncmp(buf, "quit", 4) == 0)
+ break;
+ dbenv->errx(dbenv, "Format: TICKER VALUE");
+ continue;
+ }
+
+ key.data = buf;
+ key.size = strlen(buf);
+
+ data.data = rbuf;
+ data.size = strlen(rbuf);
+
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
+ goto err;
+ switch (ret =
+ dbp->put(dbp, txn, &key, &data, 0)) {
+ case 0:
+ break;
+ default:
+ dbp->err(dbp, ret, "DB->put");
+ if (ret != DB_KEYEXIST)
+ goto err;
+ break;
+ }
+ ret = txn->commit(txn, 0);
+ txn = NULL;
+ if (ret != 0)
+ goto err;
+ }
+
+err: if (txn != NULL)
+ (void)txn->abort(txn);
+
+ if (dbp != NULL)
+ (void)dbp->close(dbp, DB_NOSYNC);
+
+ return ((void *)ret);
+}
diff --git a/bdb/examples_c/ex_repquote/ex_rq_net.c b/bdb/examples_c/ex_repquote/ex_rq_net.c
new file mode 100644
index 00000000000..1a6d26488d6
--- /dev/null
+++ b/bdb/examples_c/ex_repquote/ex_rq_net.c
@@ -0,0 +1,692 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_rq_net.c,v 1.37 2002/08/06 05:39:04 bostic Exp $
+ */
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include <dbinc/queue.h> /* !!!: for the LIST_XXX macros. */
+
+#include "ex_repquote.h"
+
+int machtab_add __P((machtab_t *, int, u_int32_t, int, int *));
+ssize_t readn __P((int, void *, size_t));
+
+/*
+ * This file defines the communication infrastructure for the ex_repquote
+ * sample application.
+ *
+ * This application uses TCP/IP for its communication. In an N-site
+ * replication group, this means that there are N * N communication
+ * channels so that every site can communicate with every other site
+ * (this allows elections to be held when the master fails). We do
+ * not require that anyone know about all sites when the application
+ * starts up. In order to communicate, the application should know
+ * about someone, else it has no idea how to ever get in the game.
+ *
+ * Communication is handled via a number of different threads. These
+ * thread functions are implemented in rep_util.c In this file, we
+ * define the data structures that maintain the state that describes
+ * the comm infrastructure, the functions that manipulates this state
+ * and the routines used to actually send and receive data over the
+ * sockets.
+ */
+
+/*
+ * The communication infrastructure is represented by a machine table,
+ * machtab_t, which is essentially a mutex-protected linked list of members
+ * of the group. The machtab also contains the parameters that are needed
+ * to call for an election. We hardwire values for these parameters in the
+ * init function, but these could be set via some configuration setup in a
+ * real application. We reserve the machine-id 1 to refer to ourselves and
+ * make the machine-id 0 be invalid.
+ */
+
+#define MACHID_INVALID 0
+#define MACHID_SELF 1
+
+struct __machtab {
+ LIST_HEAD(__machlist, __member) machlist;
+ int nextid;
+ pthread_mutex_t mtmutex;
+ u_int32_t timeout_time;
+ int current;
+ int max;
+ int nsites;
+ int priority;
+};
+
+/* Data structure that describes each entry in the machtab. */
+struct __member {
+ u_int32_t hostaddr; /* Host IP address. */
+ int port; /* Port number. */
+ int eid; /* Application-specific machine id. */
+ int fd; /* File descriptor for the socket. */
+ LIST_ENTRY(__member) links;
+ /* For linked list of all members we know of. */
+};
+
+static int quote_send_broadcast __P((machtab_t *,
+ const DBT *, const DBT *, u_int32_t));
+static int quote_send_one __P((const DBT *, const DBT *, int, u_int32_t));
+
+/*
+ * machtab_init --
+ * Initialize the machine ID table.
+ * XXX Right now we treat the number of sites as the maximum
+ * number we've ever had on the list at one time. We probably
+ * want to make that smarter.
+ */
+int
+machtab_init(machtabp, pri, nsites)
+ machtab_t **machtabp;
+ int pri, nsites;
+{
+ int ret;
+ machtab_t *machtab;
+
+ if ((machtab = malloc(sizeof(machtab_t))) == NULL)
+ return (ENOMEM);
+
+ LIST_INIT(&machtab->machlist);
+
+ /* Reserve eid's 0 and 1. */
+ machtab->nextid = 2;
+ machtab->timeout_time = 2 * 1000000; /* 2 seconds. */
+ machtab->current = machtab->max = 0;
+ machtab->priority = pri;
+ machtab->nsites = nsites;
+
+ ret = pthread_mutex_init(&machtab->mtmutex, NULL);
+
+ *machtabp = machtab;
+
+ return (ret);
+}
+
+/*
+ * machtab_add --
+ * Add a file descriptor to the table of machines, returning
+ * a new machine ID.
+ */
+int
+machtab_add(machtab, fd, hostaddr, port, idp)
+ machtab_t *machtab;
+ int fd;
+ u_int32_t hostaddr;
+ int port, *idp;
+{
+ int ret;
+ member_t *m, *member;
+
+ if ((member = malloc(sizeof(member_t))) == NULL)
+ return (ENOMEM);
+
+ member->fd = fd;
+ member->hostaddr = hostaddr;
+ member->port = port;
+
+ if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
+ return (ret);
+
+ for (m = LIST_FIRST(&machtab->machlist);
+ m != NULL; m = LIST_NEXT(m, links))
+ if (m->hostaddr == hostaddr && m->port == port)
+ break;
+
+ if (m == NULL) {
+ member->eid = machtab->nextid++;
+ LIST_INSERT_HEAD(&machtab->machlist, member, links);
+ } else
+ member->eid = m->eid;
+
+ ret = pthread_mutex_unlock(&machtab->mtmutex);
+
+ if (idp != NULL)
+ *idp = member->eid;
+
+ if (m == NULL) {
+ if (++machtab->current > machtab->max)
+ machtab->max = machtab->current;
+ } else {
+ free(member);
+ ret = EEXIST;
+ }
+ return (ret);
+}
+
+/*
+ * machtab_getinfo --
+ * Return host and port information for a particular machine id.
+ */
+int
+machtab_getinfo(machtab, eid, hostp, portp)
+ machtab_t *machtab;
+ int eid;
+ u_int32_t *hostp;
+ int *portp;
+{
+ int ret;
+ member_t *member;
+
+ if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
+ return (ret);
+
+ for (member = LIST_FIRST(&machtab->machlist);
+ member != NULL;
+ member = LIST_NEXT(member, links))
+ if (member->eid == eid) {
+ *hostp = member->hostaddr;
+ *portp = member->port;
+ break;
+ }
+
+ if ((ret = pthread_mutex_unlock(&machtab->mtmutex)) != 0)
+ return (ret);
+
+ return (member != NULL ? 0 : EINVAL);
+}
+
+/*
+ * machtab_rem --
+ * Remove a mapping from the table of machines. Lock indicates
+ * whether we need to lock the machtab or not (0 indicates we do not
+ * need to lock; non-zero indicates that we do need to lock).
+ */
+int
+machtab_rem(machtab, eid, lock)
+ machtab_t *machtab;
+ int eid;
+ int lock;
+{
+ int found, ret;
+ member_t *member;
+
+ ret = 0;
+ if (lock && (ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
+ return (ret);
+
+ for (found = 0, member = LIST_FIRST(&machtab->machlist);
+ member != NULL;
+ member = LIST_NEXT(member, links))
+ if (member->eid == eid) {
+ found = 1;
+ LIST_REMOVE(member, links);
+ (void)close(member->fd);
+ free(member);
+ machtab->current--;
+ break;
+ }
+
+ if (LIST_FIRST(&machtab->machlist) == NULL)
+ machtab->nextid = 2;
+
+ if (lock)
+ ret = pthread_mutex_unlock(&machtab->mtmutex);
+
+ return (ret);
+}
+
+void
+machtab_parm(machtab, nump, prip, timeoutp)
+ machtab_t *machtab;
+ int *nump, *prip;
+ u_int32_t *timeoutp;
+{
+ if (machtab->nsites == 0)
+ *nump = machtab->max;
+ else
+ *nump = machtab->nsites;
+ *prip = machtab->priority;
+ *timeoutp = machtab->timeout_time;
+}
+
+/*
+ * listen_socket_init --
+ * Initialize a socket for listening on the specified port. Returns
+ * a file descriptor for the socket, ready for an accept() call
+ * in a thread that we're happy to let block.
+ */
+int
+listen_socket_init(progname, port)
+ const char *progname;
+ int port;
+{
+ int s;
+ struct protoent *proto;
+ struct sockaddr_in si;
+
+ if ((proto = getprotobyname("tcp")) == NULL)
+ return (-1);
+
+ if ((s = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
+ return (-1);
+
+ memset(&si, 0, sizeof(si));
+ si.sin_family = AF_INET;
+ si.sin_addr.s_addr = htonl(INADDR_ANY);
+ si.sin_port = htons(port);
+
+ if (bind(s, (struct sockaddr *)&si, sizeof(si)) != 0)
+ goto err;
+
+ if (listen(s, 5) != 0)
+ goto err;
+
+ return (s);
+
+err: fprintf(stderr, "%s: %s", progname, strerror(errno));
+ close (s);
+ return (-1);
+}
+
+/*
+ * listen_socket_accept --
+ * Accept a connection on a socket. This is essentially just a wrapper
+ * for accept(3).
+ */
+int
+listen_socket_accept(machtab, progname, s, eidp)
+ machtab_t *machtab;
+ const char *progname;
+ int s, *eidp;
+{
+ struct sockaddr_in si;
+ int si_len;
+ int host, ns, port, ret;
+
+ COMPQUIET(progname, NULL);
+
+wait: memset(&si, 0, sizeof(si));
+ si_len = sizeof(si);
+ ns = accept(s, (struct sockaddr *)&si, &si_len);
+ host = ntohl(si.sin_addr.s_addr);
+ port = ntohs(si.sin_port);
+ ret = machtab_add(machtab, ns, host, port, eidp);
+ if (ret == EEXIST) {
+ close(ns);
+ goto wait;
+ } else if (ret != 0)
+ goto err;
+
+ return (ns);
+
+err: close(ns);
+ return (-1);
+}
+
+/*
+ * get_accepted_socket --
+ * Listen on the specified port, and return a file descriptor
+ * when we have accepted a connection on it.
+ */
+int
+get_accepted_socket(progname, port)
+ const char *progname;
+ int port;
+{
+ struct protoent *proto;
+ struct sockaddr_in si;
+ int si_len;
+ int s, ns;
+
+ if ((proto = getprotobyname("tcp")) == NULL)
+ return (-1);
+
+ if ((s = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
+ return (-1);
+
+ memset(&si, 0, sizeof(si));
+ si.sin_family = AF_INET;
+ si.sin_addr.s_addr = htonl(INADDR_ANY);
+ si.sin_port = htons(port);
+
+ if (bind(s, (struct sockaddr *)&si, sizeof(si)) != 0)
+ goto err;
+
+ if (listen(s, 5) != 0)
+ goto err;
+
+ memset(&si, 0, sizeof(si));
+ si_len = sizeof(si);
+ ns = accept(s, (struct sockaddr *)&si, &si_len);
+
+ return (ns);
+
+err: fprintf(stderr, "%s: %s", progname, strerror(errno));
+ close (s);
+ return (-1);
+}
+
+/*
+ * get_connected_socket --
+ * Connect to the specified port of the specified remote machine,
+ * and return a file descriptor when we have accepted a connection on it.
+ * Add this connection to the machtab. If we already have a connection
+ * open to this machine, then don't create another one, return the eid
+ * of the connection (in *eidp) and set is_open to 1. Return 0.
+ */
+int
+get_connected_socket(machtab, progname, remotehost, port, is_open, eidp)
+ machtab_t *machtab;
+ const char *progname, *remotehost;
+ int port, *is_open, *eidp;
+{
+ int ret, s;
+ struct hostent *hp;
+ struct protoent *proto;
+ struct sockaddr_in si;
+ u_int32_t addr;
+
+ *is_open = 0;
+
+ if ((proto = getprotobyname("tcp")) == NULL)
+ return (-1);
+
+ if ((hp = gethostbyname(remotehost)) == NULL) {
+ fprintf(stderr, "%s: host not found: %s\n", progname,
+ strerror(errno));
+ return (-1);
+ }
+
+ if ((s = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
+ return (-1);
+ memset(&si, 0, sizeof(si));
+ memcpy((char *)&si.sin_addr, hp->h_addr, hp->h_length);
+ addr = ntohl(si.sin_addr.s_addr);
+ ret = machtab_add(machtab, s, addr, port, eidp);
+ if (ret == EEXIST) {
+ *is_open = 1;
+ close(s);
+ return (0);
+ } else if (ret != 0) {
+ close (s);
+ return (-1);
+ }
+
+ si.sin_family = AF_INET;
+ si.sin_port = htons(port);
+ if (connect(s, (struct sockaddr *)&si, sizeof(si)) < 0) {
+ fprintf(stderr, "%s: connection failed: %s",
+ progname, strerror(errno));
+ (void)machtab_rem(machtab, *eidp, 1);
+ return (-1);
+ }
+
+ return (s);
+}
+
+/*
+ * get_next_message --
+ * Read a single message from the specified file descriptor, and
+ * return it in the format used by rep functions (two DBTs and a type).
+ *
+ * This function is called in a loop by both clients and masters, and
+ * the resulting DBTs are manually dispatched to DB_ENV->rep_process_message().
+ */
+int
+get_next_message(fd, rec, control)
+ int fd;
+ DBT *rec, *control;
+{
+ size_t nr;
+ u_int32_t rsize, csize;
+ u_int8_t *recbuf, *controlbuf;
+
+ /*
+ * The protocol we use on the wire is dead simple:
+ *
+ * 4 bytes - rec->size
+ * (# read above) - rec->data
+ * 4 bytes - control->size
+ * (# read above) - control->data
+ */
+
+ /* Read rec->size. */
+ nr = readn(fd, &rsize, 4);
+ if (nr != 4)
+ return (1);
+
+ /* Read the record itself. */
+ if (rsize > 0) {
+ if (rec->size < rsize)
+ rec->data = realloc(rec->data, rsize);
+ recbuf = rec->data;
+ nr = readn(fd, recbuf, rsize);
+ } else {
+ if (rec->data != NULL)
+ free(rec->data);
+ rec->data = NULL;
+ }
+ rec->size = rsize;
+
+ /* Read control->size. */
+ nr = readn(fd, &csize, 4);
+ if (nr != 4)
+ return (1);
+
+ /* Read the control struct itself. */
+ if (csize > 0) {
+ controlbuf = control->data;
+ if (control->size < csize)
+ controlbuf = realloc(controlbuf, csize);
+ nr = readn(fd, controlbuf, csize);
+ if (nr != csize)
+ return (1);
+ } else {
+ if (control->data != NULL)
+ free(control->data);
+ controlbuf = NULL;
+ }
+ control->data = controlbuf;
+ control->size = csize;
+
+ return (0);
+}
+
+/*
+ * readn --
+ * Read a full n characters from a file descriptor, unless we get an error
+ * or EOF.
+ */
+ssize_t
+readn(fd, vptr, n)
+ int fd;
+ void *vptr;
+ size_t n;
+{
+ size_t nleft;
+ ssize_t nread;
+ char *ptr;
+
+ ptr = vptr;
+ nleft = n;
+ while (nleft > 0) {
+ if ( (nread = read(fd, ptr, nleft)) < 0) {
+ /*
+ * Call read() again on interrupted system call;
+ * on other errors, bail.
+ */
+ if (errno == EINTR)
+ nread = 0;
+ else
+ return (-1);
+ } else if (nread == 0)
+ break; /* EOF */
+
+ nleft -= nread;
+ ptr += nread;
+ }
+
+ return (n - nleft);
+}
+
+/*
+ * quote_send --
+ * The f_send function for DB_ENV->set_rep_transport.
+ */
+int
+quote_send(dbenv, control, rec, eid, flags)
+ DB_ENV *dbenv;
+ const DBT *control, *rec;
+ int eid;
+ u_int32_t flags;
+{
+ int fd, n, ret, t_ret;
+ machtab_t *machtab;
+ member_t *m;
+
+ machtab = (machtab_t *)dbenv->app_private;
+
+ if (eid == DB_EID_BROADCAST) {
+ /*
+ * Right now, we do not require successful transmission.
+ * I'd like to move this requiring at least one successful
+ * transmission on PERMANENT requests.
+ */
+ n = quote_send_broadcast(machtab, rec, control, flags);
+ if (n < 0 /*|| (n == 0 && LF_ISSET(DB_REP_PERMANENT))*/)
+ return (DB_REP_UNAVAIL);
+ return (0);
+ }
+
+ if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
+ return (ret);
+
+ fd = 0;
+ for (m = LIST_FIRST(&machtab->machlist); m != NULL;
+ m = LIST_NEXT(m, links)) {
+ if (m->eid == eid) {
+ fd = m->fd;
+ break;
+ }
+ }
+
+ if (fd == 0) {
+ dbenv->err(dbenv, DB_REP_UNAVAIL,
+ "quote_send: cannot find machine ID %d", eid);
+ return (DB_REP_UNAVAIL);
+ }
+
+ ret = quote_send_one(rec, control, fd, flags);
+
+ if ((t_ret = (pthread_mutex_unlock(&machtab->mtmutex))) != 0 &&
+ ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * quote_send_broadcast --
+ * Send a message to everybody.
+ * Returns the number of sites to which this message was successfully
+ * communicated. A -1 indicates a fatal error.
+ */
+static int
+quote_send_broadcast(machtab, rec, control, flags)
+ machtab_t *machtab;
+ const DBT *rec, *control;
+ u_int32_t flags;
+{
+ int ret, sent;
+ member_t *m, *next;
+
+ if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
+ return (0);
+
+ sent = 0;
+ for (m = LIST_FIRST(&machtab->machlist); m != NULL; m = next) {
+ next = LIST_NEXT(m, links);
+ if ((ret = quote_send_one(rec, control, m->fd, flags)) != 0) {
+ (void)machtab_rem(machtab, m->eid, 0);
+ } else
+ sent++;
+ }
+
+ if (pthread_mutex_unlock(&machtab->mtmutex) != 0)
+ return (-1);
+
+ return (sent);
+}
+
+/*
+ * quote_send_one --
+ * Send a message to a single machine, given that machine's file
+ * descriptor.
+ *
+ * !!!
+ * Note that the machtab mutex should be held through this call.
+ * It doubles as a synchronizer to make sure that two threads don't
+ * intersperse writes that are part of two single messages.
+ */
+static int
+quote_send_one(rec, control, fd, flags)
+ const DBT *rec, *control;
+ int fd;
+ u_int32_t flags;
+
+{
+ int retry;
+ ssize_t bytes_left, nw;
+ u_int8_t *wp;
+
+ COMPQUIET(flags, 0);
+
+ /*
+ * The protocol is simply: write rec->size, write rec->data,
+ * write control->size, write control->data.
+ */
+ nw = write(fd, &rec->size, 4);
+ if (nw != 4)
+ return (DB_REP_UNAVAIL);
+
+ if (rec->size > 0) {
+ nw = write(fd, rec->data, rec->size);
+ if (nw < 0)
+ return (DB_REP_UNAVAIL);
+ if (nw != (ssize_t)rec->size) {
+ /* Try a couple of times to finish the write. */
+ wp = (u_int8_t *)rec->data + nw;
+ bytes_left = rec->size - nw;
+ for (retry = 0; bytes_left > 0 && retry < 3; retry++) {
+ nw = write(fd, wp, bytes_left);
+ if (nw < 0)
+ return (DB_REP_UNAVAIL);
+ bytes_left -= nw;
+ wp += nw;
+ }
+ if (bytes_left > 0)
+ return (DB_REP_UNAVAIL);
+ }
+ }
+
+ nw = write(fd, &control->size, 4);
+ if (nw != 4)
+ return (DB_REP_UNAVAIL);
+ if (control->size > 0) {
+ nw = write(fd, control->data, control->size);
+ if (nw != (ssize_t)control->size)
+ return (DB_REP_UNAVAIL);
+ }
+ return (0);
+}
diff --git a/bdb/examples_c/ex_repquote/ex_rq_util.c b/bdb/examples_c/ex_repquote/ex_rq_util.c
new file mode 100644
index 00000000000..89fd7ae485a
--- /dev/null
+++ b/bdb/examples_c/ex_repquote/ex_rq_util.c
@@ -0,0 +1,412 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: ex_rq_util.c,v 1.20 2002/08/06 05:39:04 bostic Exp $
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#include "ex_repquote.h"
+
+static int connect_site __P((DB_ENV *, machtab_t *, const char *,
+ repsite_t *, int *, int *));
+void * elect_thread __P((void *));
+
+typedef struct {
+ DB_ENV *dbenv;
+ machtab_t *machtab;
+} elect_args;
+
+typedef struct {
+ DB_ENV *dbenv;
+ const char *progname;
+ const char *home;
+ int fd;
+ u_int32_t eid;
+ machtab_t *tab;
+} hm_loop_args;
+
+/*
+ * This is a generic message handling loop that is used both by the
+ * master to accept messages from a client as well as by clients
+ * to communicate with other clients.
+ */
+void *
+hm_loop(args)
+ void *args;
+{
+ DB_ENV *dbenv;
+ DBT rec, control;
+ const char *c, *home, *progname;
+ int fd, eid, n, newm;
+ int open, pri, r, ret, t_ret, tmpid;
+ elect_args *ea;
+ hm_loop_args *ha;
+ machtab_t *tab;
+ pthread_t elect_thr;
+ repsite_t self;
+ u_int32_t timeout;
+ void *status;
+
+ ea = NULL;
+
+ ha = (hm_loop_args *)args;
+ dbenv = ha->dbenv;
+ fd = ha->fd;
+ home = ha->home;
+ eid = ha->eid;
+ progname = ha->progname;
+ tab = ha->tab;
+ free(ha);
+
+ memset(&rec, 0, sizeof(DBT));
+ memset(&control, 0, sizeof(DBT));
+
+ for (ret = 0; ret == 0;) {
+ if ((ret = get_next_message(fd, &rec, &control)) != 0) {
+ /*
+ * Close this connection; if it's the master call
+ * for an election.
+ */
+ close(fd);
+ if ((ret = machtab_rem(tab, eid, 1)) != 0)
+ break;
+
+ /*
+ * If I'm the master, I just lost a client and this
+ * thread is done.
+ */
+ if (master_eid == SELF_EID)
+ break;
+
+ /*
+ * If I was talking with the master and the master
+ * went away, I need to call an election; else I'm
+ * done.
+ */
+ if (master_eid != eid)
+ break;
+
+ master_eid = DB_EID_INVALID;
+ machtab_parm(tab, &n, &pri, &timeout);
+ if ((ret = dbenv->rep_elect(dbenv,
+ n, pri, timeout, &newm)) != 0)
+ continue;
+
+ /*
+ * Regardless of the results, the site I was talking
+ * to is gone, so I have nothing to do but exit.
+ */
+ if (newm == SELF_EID && (ret =
+ dbenv->rep_start(dbenv, NULL, DB_REP_MASTER)) == 0)
+ ret = domaster(dbenv, progname);
+ break;
+ }
+
+ tmpid = eid;
+ switch(r = dbenv->rep_process_message(dbenv,
+ &control, &rec, &tmpid)) {
+ case DB_REP_NEWSITE:
+ /*
+ * Check if we got sent connect information and if we
+ * did, if this is me or if we already have a
+ * connection to this new site. If we don't,
+ * establish a new one.
+ */
+
+ /* No connect info. */
+ if (rec.size == 0)
+ break;
+
+ /* It's me, do nothing. */
+ if (strncmp(myaddr, rec.data, rec.size) == 0)
+ break;
+
+ self.host = (char *)rec.data;
+ self.host = strtok(self.host, ":");
+ if ((c = strtok(NULL, ":")) == NULL) {
+ dbenv->errx(dbenv, "Bad host specification");
+ goto out;
+ }
+ self.port = atoi(c);
+
+ /*
+ * We try to connect to the new site. If we can't,
+ * we treat it as an error since we know that the site
+ * should be up if we got a message from it (even
+ * indirectly).
+ */
+ if ((ret = connect_site(dbenv,
+ tab, progname, &self, &open, &eid)) != 0)
+ goto out;
+ break;
+ case DB_REP_HOLDELECTION:
+ if (master_eid == SELF_EID)
+ break;
+ /* Make sure that previous election has finished. */
+ if (ea != NULL) {
+ (void)pthread_join(elect_thr, &status);
+ ea = NULL;
+ }
+ if ((ea = calloc(sizeof(elect_args), 1)) == NULL) {
+ ret = errno;
+ goto out;
+ }
+ ea->dbenv = dbenv;
+ ea->machtab = tab;
+ ret = pthread_create(&elect_thr,
+ NULL, elect_thread, (void *)ea);
+ break;
+ case DB_REP_NEWMASTER:
+ /* Check if it's us. */
+ master_eid = tmpid;
+ if (tmpid == SELF_EID) {
+ if ((ret = dbenv->rep_start(dbenv,
+ NULL, DB_REP_MASTER)) != 0)
+ goto out;
+ ret = domaster(dbenv, progname);
+ }
+ break;
+ case 0:
+ break;
+ default:
+ dbenv->err(dbenv, r, "DB_ENV->rep_process_message");
+ break;
+ }
+ }
+
+out: if ((t_ret = machtab_rem(tab, eid, 1)) != 0 && ret == 0)
+ ret = t_ret;
+
+ /* Don't close the environment before any children exit. */
+ if (ea != NULL)
+ (void)pthread_join(elect_thr, &status);
+
+ return ((void *)ret);
+}
+
+/*
+ * This is a generic thread that spawns a thread to listen for connections
+ * on a socket and then spawns off child threads to handle each new
+ * connection.
+ */
+void *
+connect_thread(args)
+ void *args;
+{
+ DB_ENV *dbenv;
+ const char *home, *progname;
+ int fd, i, eid, ns, port, ret;
+ hm_loop_args *ha;
+ connect_args *cargs;
+ machtab_t *machtab;
+#define MAX_THREADS 25
+ pthread_t hm_thrs[MAX_THREADS];
+ pthread_attr_t attr;
+
+ ha = NULL;
+ cargs = (connect_args *)args;
+ dbenv = cargs->dbenv;
+ home = cargs->home;
+ progname = cargs->progname;
+ machtab = cargs->machtab;
+ port = cargs->port;
+
+ if ((ret = pthread_attr_init(&attr)) != 0)
+ return ((void *)EXIT_FAILURE);
+
+ if ((ret =
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) != 0)
+ goto err;
+
+ /*
+ * Loop forever, accepting connections from new machines,
+ * and forking off a thread to handle each.
+ */
+ if ((fd = listen_socket_init(progname, port)) < 0) {
+ ret = errno;
+ goto err;
+ }
+
+ for (i = 0; i < MAX_THREADS; i++) {
+ if ((ns = listen_socket_accept(machtab,
+ progname, fd, &eid)) < 0) {
+ ret = errno;
+ goto err;
+ }
+ if ((ha = calloc(sizeof(hm_loop_args), 1)) == NULL)
+ goto err;
+ ha->progname = progname;
+ ha->home = home;
+ ha->fd = ns;
+ ha->eid = eid;
+ ha->tab = machtab;
+ ha->dbenv = dbenv;
+ if ((ret = pthread_create(&hm_thrs[i++], &attr,
+ hm_loop, (void *)ha)) != 0)
+ goto err;
+ ha = NULL;
+ }
+
+ /* If we fell out, we ended up with too many threads. */
+ dbenv->errx(dbenv, "Too many threads");
+ ret = ENOMEM;
+
+err: pthread_attr_destroy(&attr);
+ return (ret == 0 ? (void *)EXIT_SUCCESS : (void *)EXIT_FAILURE);
+}
+
+/*
+ * Open a connection to everyone that we've been told about. If we
+ * cannot open some connections, keep trying.
+ */
+void *
+connect_all(args)
+ void *args;
+{
+ DB_ENV *dbenv;
+ all_args *aa;
+ const char *home, *progname;
+ hm_loop_args *ha;
+ int failed, i, eid, nsites, open, ret, *success;
+ machtab_t *machtab;
+ repsite_t *sites;
+
+ ha = NULL;
+ aa = (all_args *)args;
+ dbenv = aa->dbenv;
+ progname = aa->progname;
+ home = aa->home;
+ machtab = aa->machtab;
+ nsites = aa->nsites;
+ sites = aa->sites;
+
+ ret = 0;
+
+ /* Some implementations of calloc are sad about alloc'ing 0 things. */
+ if ((success = calloc(nsites > 0 ? nsites : 1, sizeof(int))) == NULL) {
+ dbenv->err(dbenv, errno, "connect_all");
+ ret = 1;
+ goto err;
+ }
+
+ for (failed = nsites; failed > 0;) {
+ for (i = 0; i < nsites; i++) {
+ if (success[i])
+ continue;
+
+ ret = connect_site(dbenv, machtab,
+ progname, &sites[i], &open, &eid);
+
+ /*
+ * If we couldn't make the connection, this isn't
+ * fatal to the loop, but we have nothing further
+ * to do on this machine at the moment.
+ */
+ if (ret == DB_REP_UNAVAIL)
+ continue;
+
+ if (ret != 0)
+ goto err;
+
+ failed--;
+ success[i] = 1;
+
+ /* If the connection is already open, we're done. */
+ if (ret == 0 && open == 1)
+ continue;
+
+ }
+ sleep(1);
+ }
+
+err: free(success);
+ return (ret ? (void *)EXIT_FAILURE : (void *)EXIT_SUCCESS);
+}
+
+int
+connect_site(dbenv, machtab, progname, site, is_open, eidp)
+ DB_ENV *dbenv;
+ machtab_t *machtab;
+ const char *progname;
+ repsite_t *site;
+ int *is_open;
+ int *eidp;
+{
+ int ret, s;
+ hm_loop_args *ha;
+ pthread_t hm_thr;
+
+ if ((s = get_connected_socket(machtab, progname,
+ site->host, site->port, is_open, eidp)) < 0)
+ return (DB_REP_UNAVAIL);
+
+ if (*is_open)
+ return (0);
+
+ if ((ha = calloc(sizeof(hm_loop_args), 1)) == NULL) {
+ ret = errno;
+ goto err;
+ }
+
+ ha->progname = progname;
+ ha->fd = s;
+ ha->eid = *eidp;
+ ha->tab = machtab;
+ ha->dbenv = dbenv;
+
+ if ((ret = pthread_create(&hm_thr, NULL,
+ hm_loop, (void *)ha)) != 0) {
+ dbenv->err(dbenv, ret, "connect site");
+ goto err1;
+ }
+
+ return (0);
+
+err1: free(ha);
+err:
+ return (ret);
+}
+
+/*
+ * We need to spawn off a new thread in which to hold an election in
+ * case we are the only thread listening on for messages.
+ */
+void *
+elect_thread(args)
+ void *args;
+{
+ DB_ENV *dbenv;
+ elect_args *eargs;
+ int n, ret, pri;
+ machtab_t *machtab;
+ u_int32_t timeout;
+
+ eargs = (elect_args *)args;
+ dbenv = eargs->dbenv;
+ machtab = eargs->machtab;
+ free(eargs);
+
+ machtab_parm(machtab, &n, &pri, &timeout);
+ while ((ret =
+ dbenv->rep_elect(dbenv, n, pri, timeout, &master_eid)) != 0)
+ sleep(2);
+
+ /* Check if it's us. */
+ if (master_eid == SELF_EID)
+ ret = dbenv->rep_start(dbenv, NULL, DB_REP_MASTER);
+
+ return ((void *)(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE));
+}
diff --git a/bdb/examples_c/ex_thread.c b/bdb/examples_c/ex_thread.c
index 93812ade764..104de37ad38 100644
--- a/bdb/examples_c/ex_thread.c
+++ b/bdb/examples_c/ex_thread.c
@@ -1,33 +1,26 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_thread.c,v 11.9 2000/05/31 15:10:04 bostic Exp $
+ * $Id: ex_thread.c,v 11.34 2002/08/15 14:37:13 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
#include <errno.h>
#include <pthread.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
+
+#ifdef _WIN32
+extern int getopt(int, char * const *, const char *);
+#else
#include <unistd.h>
#endif
@@ -39,18 +32,21 @@
*/
extern int sched_yield __P((void)); /* Pthread yield function. */
-DB_ENV *db_init __P((char *));
+int db_init __P((const char *));
void *deadlock __P((void *));
-void fatal __P((char *, int, int));
+void fatal __P((const char *, int, int));
+void onint __P((int));
int main __P((int, char *[]));
int reader __P((int));
void stats __P((void));
void *trickle __P((void *));
void *tstart __P((void *));
-void usage __P((void));
+int usage __P((void));
void word __P((void));
int writer __P((int));
+int quit; /* Interrupt handling flag. */
+
struct _statistics {
int aborted; /* Write. */
int aborts; /* Read/write. */
@@ -100,11 +96,13 @@ main(argc, argv)
{
extern char *optarg;
extern int errno, optind;
+ DB_TXN *txnp;
pthread_t *tids;
int ch, i, ret;
- char *home;
+ const char *home;
void *retp;
+ txnp = NULL;
nlist = 1000;
nreaders = nwriters = 4;
home = "TESTDIR";
@@ -130,7 +128,7 @@ main(argc, argv)
break;
case '?':
default:
- usage();
+ return (usage());
}
argc -= optind;
argv += optind;
@@ -138,29 +136,41 @@ main(argc, argv)
/* Initialize the random number generator. */
srand(getpid() | time(NULL));
+ /* Register the signal handler. */
+ (void)signal(SIGINT, onint);
+
/* Build the key list. */
word();
/* Remove the previous database. */
- (void)unlink(DATABASE);
+ (void)remove(DATABASE);
/* Initialize the database environment. */
- dbenv = db_init(home);
+ if ((ret = db_init(home)) != 0)
+ return (ret);
/* Initialize the database. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
(void)dbenv->close(dbenv, 0);
- return (1);
+ return (EXIT_FAILURE);
}
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
goto err;
}
- if ((ret = dbp->open(dbp,
+
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
+ fatal("txn_begin", ret, 1);
+ if ((ret = dbp->open(dbp, txnp,
DATABASE, NULL, DB_BTREE, DB_CREATE | DB_THREAD, 0664)) != 0) {
dbp->err(dbp, ret, "%s: open", DATABASE);
goto err;
+ } else {
+ ret = txnp->commit(txnp, 0);
+ txnp = NULL;
+ if (ret != 0)
+ goto err;
}
nthreads = nreaders + nwriters + 2;
@@ -177,8 +187,9 @@ main(argc, argv)
/* Create reader/writer threads. */
for (i = 0; i < nreaders + nwriters; ++i)
- if (pthread_create(&tids[i], NULL, tstart, (void *)i))
- fatal("pthread_create", errno, 1);
+ if ((ret =
+ pthread_create(&tids[i], NULL, tstart, (void *)i)) != 0)
+ fatal("pthread_create", ret > 0 ? ret : errno, 1);
/* Create buffer pool trickle thread. */
if (pthread_create(&tids[i], NULL, trickle, &i))
@@ -193,10 +204,15 @@ main(argc, argv)
for (i = 0; i < nthreads; ++i)
(void)pthread_join(tids[i], &retp);
-err: (void)dbp->close(dbp, 0);
+ printf("Exiting\n");
+ stats();
+
+err: if (txnp != NULL)
+ (void)txnp->abort(txnp);
+ (void)dbp->close(dbp, 0);
(void)dbenv->close(dbenv, 0);
- return (0);
+ return (EXIT_SUCCESS);
}
int
@@ -219,7 +235,7 @@ reader(id)
* Read-only threads do not require transaction protection, unless
* there's a need for repeatable reads.
*/
- for (;;) {
+ while (!quit) {
/* Pick a key at random, and look it up. */
n = rand() % nlist;
key.data = list[n];
@@ -273,7 +289,7 @@ writer(id)
data.ulen = sizeof(dbuf);
data.flags = DB_DBT_USERMEM;
- for (;;) {
+ while (!quit) {
/* Pick a random key. */
n = rand() % nlist;
key.data = list[n];
@@ -286,8 +302,8 @@ writer(id)
/* Abort and retry. */
if (0) {
-retry: if ((ret = txn_abort(tid)) != 0)
- fatal("txn_abort", ret, 1);
+retry: if ((ret = tid->abort(tid)) != 0)
+ fatal("DB_TXN->abort", ret, 1);
++perf[id].aborts;
++perf[id].aborted;
}
@@ -302,7 +318,7 @@ retry: if ((ret = txn_abort(tid)) != 0)
}
/* Begin the transaction. */
- if ((ret = txn_begin(dbenv, NULL, &tid, 0)) != 0)
+ if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0)
fatal("txn_begin", ret, 1);
/*
@@ -352,8 +368,8 @@ add: /* Add the key. 1 data item in 30 is an overflow item. */
}
commit: /* The transaction finished, commit it. */
- if ((ret = txn_commit(tid, 0)) != 0)
- fatal("txn_commit", ret, 1);
+ if ((ret = tid->commit(tid, 0)) != 0)
+ fatal("DB_TXN->commit", ret, 1);
/*
* Every time the thread completes 20 transactions, show
@@ -415,23 +431,22 @@ stats()
* db_init --
* Initialize the environment.
*/
-DB_ENV *
+int
db_init(home)
- char *home;
+ const char *home;
{
- DB_ENV *dbenv;
int ret;
- if (punish) {
- (void)db_env_set_pageyield(1);
- (void)db_env_set_func_yield(sched_yield);
- }
-
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
- exit (1);
+ return (EXIT_FAILURE);
+ }
+ if (punish) {
+ (void)dbenv->set_flags(dbenv, DB_YIELDCPU, 1);
+ (void)db_env_set_func_yield(sched_yield);
}
+
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
(void)dbenv->set_cachesize(dbenv, 0, 100 * 1024, 0);
@@ -442,9 +457,10 @@ db_init(home)
DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD, 0)) != 0) {
dbenv->err(dbenv, ret, NULL);
(void)dbenv->close(dbenv, 0);
- exit (1);
+ return (EXIT_FAILURE);
}
- return (dbenv);
+
+ return (0);
}
/*
@@ -478,7 +494,7 @@ tstart(arg)
/*
* deadlock --
- * Thread start function for lock_detect().
+ * Thread start function for DB_ENV->lock_detect.
*/
void *
deadlock(arg)
@@ -495,21 +511,19 @@ deadlock(arg)
t.tv_sec = 0;
t.tv_usec = 100000;
- for (;;) {
- (void)lock_detect(dbenv,
- DB_LOCK_CONFLICT, DB_LOCK_YOUNGEST, NULL);
+ while (!quit) {
+ (void)dbenv->lock_detect(dbenv, 0, DB_LOCK_YOUNGEST, NULL);
/* Check every 100ms. */
(void)select(0, NULL, NULL, NULL, &t);
}
- /* NOTREACHED */
return (NULL);
}
/*
* trickle --
- * Thread start function for memp_trickle().
+ * Thread start function for memp_trickle.
*/
void *
trickle(arg)
@@ -525,8 +539,8 @@ trickle(arg)
printf("trickle thread starting: tid: %lu\n", (u_long)tid);
fflush(stdout);
- for (;;) {
- (void)memp_trickle(dbenv, 10, &wrote);
+ while (!quit) {
+ (void)dbenv->memp_trickle(dbenv, 10, &wrote);
if (verbose) {
sprintf(buf, "trickle: wrote %d\n", wrote);
write(STDOUT_FILENO, buf, strlen(buf));
@@ -537,7 +551,6 @@ trickle(arg)
}
}
- /* NOTREACHED */
return (NULL);
}
@@ -573,7 +586,7 @@ word()
*/
void
fatal(msg, err, syserr)
- char *msg;
+ const char *msg;
int err, syserr;
{
fprintf(stderr, "%s: ", progname);
@@ -585,7 +598,7 @@ fatal(msg, err, syserr)
if (syserr)
fprintf(stderr, "%s", strerror(err));
fprintf(stderr, "\n");
- exit (1);
+ exit(EXIT_FAILURE);
/* NOTREACHED */
}
@@ -594,11 +607,23 @@ fatal(msg, err, syserr)
* usage --
* Usage message.
*/
-void
+int
usage()
{
(void)fprintf(stderr,
"usage: %s [-pv] [-h home] [-n words] [-r readers] [-w writers]\n",
progname);
- exit(1);
+ return (EXIT_FAILURE);
+}
+
+/*
+ * onint --
+ * Interrupt signal handler.
+ */
+void
+onint(signo)
+ int signo;
+{
+ signo = 0; /* Quiet compiler. */
+ quit = 1;
}
diff --git a/bdb/examples_c/ex_tpcb.c b/bdb/examples_c/ex_tpcb.c
index 2fd11510af7..017cfeb5bdd 100644
--- a/bdb/examples_c/ex_tpcb.c
+++ b/bdb/examples_c/ex_tpcb.c
@@ -1,64 +1,41 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_tpcb.c,v 11.21 2000/10/27 20:32:00 dda Exp $
+ * $Id: ex_tpcb.c,v 11.42 2002/08/06 05:39:00 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#endif
+#include <time.h>
-#ifdef DB_WIN32
-#include <sys/types.h>
-#include <sys/timeb.h>
+#ifdef _WIN32
+extern int getopt(int, char * const *, const char *);
+#else
+#include <unistd.h>
#endif
#include <db.h>
typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
-DB_ENV *db_init __P((char *, char *, int, int, int));
+DB_ENV *db_init __P((const char *, const char *, int, int, u_int32_t));
int hpopulate __P((DB *, int, int, int, int));
-int populate __P((DB *, u_int32_t, u_int32_t, int, char *));
+int populate __P((DB *, u_int32_t, u_int32_t, int, const char *));
u_int32_t random_id __P((FTYPE, int, int, int));
u_int32_t random_int __P((u_int32_t, u_int32_t));
int tp_populate __P((DB_ENV *, int, int, int, int, int));
int tp_run __P((DB_ENV *, int, int, int, int, int));
int tp_txn __P((DB_ENV *, DB *, DB *, DB *, DB *, int, int, int, int));
-#ifdef HAVE_VXWORKS
-#define ERROR_RETURN ERROR
-#define HOME "/vxtmp/vxtmp/TESTDIR"
-#define VXSHM_KEY 13
-int ex_tpcb_init __P(());
-int ex_tpcb __P(());
-#else
-#define ERROR_RETURN 1
-void invarg __P((char *, int, char *));
+int invarg __P((const char *, int, const char *));
int main __P((int, char *[]));
-void usage __P((char *));
-#endif
+int usage __P((const char *));
/*
* This program implements a basic TPC/B driver program. To create the
@@ -125,77 +102,6 @@ typedef struct _histrec {
u_int8_t pad[RECLEN - 4 * sizeof(u_int32_t)];
} histrec;
-#ifdef HAVE_VXWORKS
-int
-ex_tpcb_init()
-{
- DB_ENV *dbenv;
- int accounts, branches, ret, seed, t_ret, tellers, history, verbose;
- char *home;
- char *progname = "ex_tpcb_init"; /* Program name. */
-
- verbose = 1;
- if ((dbenv = db_init(HOME, progname, 0, 1, 0)) == NULL)
- return (ERROR_RETURN);
-
- accounts = ACCOUNTS;
- branches = BRANCHES;
- tellers = TELLERS;
- history = HISTORY;
-
- if ((ret = tp_populate(dbenv, accounts, branches, history, tellers,
- verbose)) != OK)
- fprintf(stderr, "%s: %s\n", progname, db_strerror(ret));
- if ((t_ret = dbenv->close(dbenv, 0)) != 0) {
- fprintf(stderr, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
- }
-
- return (ret == 0 ? t_ret : ret);
-}
-
-int
-ex_tpcb()
-{
- DB_ENV *dbenv;
- int accounts, branches, seed, tellers, history;
- int ch, mpool, ntxns, ret, t_ret, txn_no_sync, verbose;
- char *progname = "ex_tpcb"; /* Program name. */
-
- accounts = ACCOUNTS;
- branches = BRANCHES;
- tellers = TELLERS;
- history = HISTORY;
-
- txn_no_sync = 0;
- mpool = 0;
- ntxns = 20;
- verbose = 1;
- seed = (int)((u_int)getpid() | time(NULL));
-
- srand((u_int)seed);
-
- /* Initialize the database environment. */
- if ((dbenv = db_init(HOME, progname, mpool, 0,
- txn_no_sync ? DB_TXN_NOSYNC : 0)) == NULL)
- return (ERROR_RETURN);
-
- if (verbose)
- printf("%ld Accounts, %ld Branches, %ld Tellers, %ld History\n",
- (long)accounts, (long)branches,
- (long)tellers, (long)history);
-
- if ((ret = tp_run(dbenv, ntxns, accounts, branches, tellers, verbose))
- != OK)
- fprintf(stderr, "tp_run failed\n");
-
- if ((t_ret = dbenv->close(dbenv, 0)) != 0) {
- fprintf(stderr, "%s: %s\n", progname, db_strerror(ret));
- return (ERROR_RETURN);
- }
- return (ret == 0 ? t_ret : ret);
-}
-#else
int
main(argc, argv)
int argc;
@@ -206,29 +112,27 @@ main(argc, argv)
DB_ENV *dbenv;
int accounts, branches, seed, tellers, history;
int ch, iflag, mpool, ntxns, ret, txn_no_sync, verbose;
- char *home, *progname;
+ const char *home, *progname;
home = "TESTDIR";
progname = "ex_tpcb";
accounts = branches = history = tellers = 0;
- txn_no_sync = 0;
- mpool = ntxns = 0;
- verbose = 0;
- iflag = 0;
- seed = (int)((u_int)getpid() | time(NULL));
+ iflag = mpool = ntxns = txn_no_sync = verbose = 0;
+ seed = (int)time(NULL);
+
while ((ch = getopt(argc, argv, "a:b:c:fh:in:S:s:t:v")) != EOF)
switch (ch) {
case 'a': /* Number of account records */
if ((accounts = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 'b': /* Number of branch records */
if ((branches = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 'c': /* Cachesize in bytes */
if ((mpool = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 'f': /* Fast mode: no txn sync. */
txn_no_sync = 1;
@@ -241,26 +145,26 @@ main(argc, argv)
break;
case 'n': /* Number of transactions */
if ((ntxns = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 'S': /* Random number seed. */
if ((seed = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 's': /* Number of history records */
if ((history = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 't': /* Number of teller records */
if ((tellers = atoi(optarg)) <= 0)
- invarg(progname, ch, optarg);
+ return (invarg(progname, ch, optarg));
break;
case 'v': /* Verbose option. */
verbose = 1;
break;
case '?':
default:
- usage(progname);
+ return (usage(progname));
}
argc -= optind;
argv += optind;
@@ -270,7 +174,7 @@ main(argc, argv)
/* Initialize the database environment. */
if ((dbenv = db_init(home,
progname, mpool, iflag, txn_no_sync ? DB_TXN_NOSYNC : 0)) == NULL)
- return (1);
+ return (EXIT_FAILURE);
accounts = accounts == 0 ? ACCOUNTS : accounts;
branches = branches == 0 ? BRANCHES : branches;
@@ -284,49 +188,48 @@ main(argc, argv)
if (iflag) {
if (ntxns != 0)
- usage(progname);
+ return (usage(progname));
tp_populate(dbenv,
accounts, branches, history, tellers, verbose);
} else {
if (ntxns == 0)
- usage(progname);
+ return (usage(progname));
tp_run(dbenv, ntxns, accounts, branches, tellers, verbose);
}
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "%s: dbenv->close failed: %s\n",
progname, db_strerror(ret));
- return (1);
+ return (EXIT_FAILURE);
}
- return (0);
+ return (EXIT_SUCCESS);
}
-void
+int
invarg(progname, arg, str)
- char *progname;
+ const char *progname;
int arg;
- char *str;
+ const char *str;
{
(void)fprintf(stderr,
"%s: invalid argument for -%c: %s\n", progname, arg, str);
- exit (1);
+ return (EXIT_FAILURE);
}
-void
+int
usage(progname)
- char *progname;
+ const char *progname;
{
- char *a1, *a2;
+ const char *a1, *a2;
a1 = "[-fv] [-a accounts] [-b branches]\n";
a2 = "\t[-c cache_size] [-h home] [-S seed] [-s history] [-t tellers]";
(void)fprintf(stderr, "usage: %s -i %s %s\n", progname, a1, a2);
(void)fprintf(stderr,
" %s -n transactions %s %s\n", progname, a1, a2);
- exit(1);
+ return (EXIT_FAILURE);
}
-#endif
/*
* db_init --
@@ -334,8 +237,9 @@ usage(progname)
*/
DB_ENV *
db_init(home, prefix, cachesize, initializing, flags)
- char *home, *prefix;
- int cachesize, initializing, flags;
+ const char *home, *prefix;
+ int cachesize, initializing;
+ u_int32_t flags;
{
DB_ENV *dbenv;
u_int32_t local_flags;
@@ -347,19 +251,17 @@ db_init(home, prefix, cachesize, initializing, flags)
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, prefix);
-#ifdef HAVE_VXWORKS
- if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) {
- dbenv->err(dbenv, ret, "set_shm_key");
- return (NULL);
- }
-#endif
(void)dbenv->set_cachesize(dbenv, 0,
cachesize == 0 ? 4 * 1024 * 1024 : (u_int32_t)cachesize, 0);
+ if (flags & (DB_TXN_NOSYNC))
+ (void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1);
+ flags &= ~(DB_TXN_NOSYNC);
+
local_flags = flags | DB_CREATE | (initializing ? DB_INIT_MPOOL :
DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL);
if ((ret = dbenv->open(dbenv, home, local_flags, 0)) != 0) {
- dbenv->err(dbenv, ret, "DBENV->open: %s", home);
+ dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
(void)dbenv->close(dbenv, 0);
return (NULL);
}
@@ -376,7 +278,6 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
int accounts, branches, history, tellers, verbose;
{
DB *dbp;
- char dbname[100];
u_int32_t balance, idnum, oflags;
u_int32_t end_anum, end_bnum, end_tnum;
u_int32_t start_anum, start_bnum, start_tnum;
@@ -384,23 +285,18 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
idnum = BEGID;
balance = 500000;
-#ifdef HAVE_VXWORKS
- oflags = DB_CREATE;
-#else
oflags = DB_CREATE | DB_TRUNCATE;
-#endif
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
- return (ERROR_RETURN);
+ return (1);
}
(void)dbp->set_h_nelem(dbp, (u_int32_t)accounts);
- snprintf(dbname, sizeof(dbname), "account");
- if ((ret = dbp->open(dbp, dbname, NULL,
+ if ((ret = dbp->open(dbp, NULL, "account", NULL,
DB_HASH, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: account");
- return (ERROR_RETURN);
+ return (1);
}
start_anum = idnum;
@@ -409,7 +305,7 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
end_anum = idnum - 1;
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: account");
- return (ERROR_RETURN);
+ return (1);
}
if (verbose)
printf("Populated accounts: %ld - %ld\n",
@@ -422,16 +318,15 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
*/
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
- return (ERROR_RETURN);
+ return (1);
}
(void)dbp->set_h_ffactor(dbp, 1);
(void)dbp->set_h_nelem(dbp, (u_int32_t)branches);
(void)dbp->set_pagesize(dbp, 512);
- snprintf(dbname, sizeof(dbname), "branch");
- if ((ret = dbp->open(dbp, dbname, NULL,
+ if ((ret = dbp->open(dbp, NULL, "branch", NULL,
DB_HASH, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: branch");
- return (ERROR_RETURN);
+ return (1);
}
start_bnum = idnum;
populate(dbp, idnum, balance, branches, "branch");
@@ -439,7 +334,7 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
end_bnum = idnum - 1;
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: branch");
- return (ERROR_RETURN);
+ return (1);
}
if (verbose)
printf("Populated branches: %ld - %ld\n",
@@ -451,16 +346,15 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
*/
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
- return (ERROR_RETURN);
+ return (1);
}
(void)dbp->set_h_ffactor(dbp, 0);
(void)dbp->set_h_nelem(dbp, (u_int32_t)tellers);
(void)dbp->set_pagesize(dbp, 512);
- snprintf(dbname, sizeof(dbname), "teller");
- if ((ret = dbp->open(dbp, dbname, NULL,
+ if ((ret = dbp->open(dbp, NULL, "teller", NULL,
DB_HASH, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: teller");
- return (ERROR_RETURN);
+ return (1);
}
start_tnum = idnum;
@@ -469,7 +363,7 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
end_tnum = idnum - 1;
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: teller");
- return (ERROR_RETURN);
+ return (1);
}
if (verbose)
printf("Populated tellers: %ld - %ld\n",
@@ -477,20 +371,19 @@ tp_populate(env, accounts, branches, history, tellers, verbose)
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
- return (ERROR_RETURN);
+ return (1);
}
(void)dbp->set_re_len(dbp, HISTORY_LEN);
- snprintf(dbname, sizeof(dbname), "history");
- if ((ret = dbp->open(dbp, dbname, NULL,
+ if ((ret = dbp->open(dbp, NULL, "history", NULL,
DB_RECNO, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: history");
- return (ERROR_RETURN);
+ return (1);
}
hpopulate(dbp, history, accounts, branches, tellers);
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: history");
- return (ERROR_RETURN);
+ return (1);
}
return (0);
}
@@ -500,7 +393,7 @@ populate(dbp, start_id, balance, nrecs, msg)
DB *dbp;
u_int32_t start_id, balance;
int nrecs;
- char *msg;
+ const char *msg;
{
DBT kdbt, ddbt;
defrec drec;
@@ -521,7 +414,7 @@ populate(dbp, start_id, balance, nrecs, msg)
(dbp->put)(dbp, NULL, &kdbt, &ddbt, DB_NOOVERWRITE)) != 0) {
dbp->err(dbp,
ret, "Failure initializing %s file\n", msg);
- return (ERROR_RETURN);
+ return (1);
}
}
return (0);
@@ -552,7 +445,7 @@ hpopulate(dbp, history, accounts, branches, tellers)
hrec.tid = random_id(TELLER, accounts, branches, tellers);
if ((ret = dbp->put(dbp, NULL, &kdbt, &ddbt, DB_APPEND)) != 0) {
dbp->err(dbp, ret, "dbp->put");
- return (ERROR_RETURN);
+ return (1);
}
}
return (0);
@@ -606,67 +499,56 @@ tp_run(dbenv, n, accounts, branches, tellers, verbose)
int n, accounts, branches, tellers, verbose;
{
DB *adb, *bdb, *hdb, *tdb;
- char dbname[100];
double gtps, itps;
int failed, ifailed, ret, txns;
time_t starttime, curtime, lasttime;
-#ifndef DB_WIN32
- pid_t pid;
-
- pid = getpid();
-#else
- int pid;
- pid = 0;
-#endif
+ adb = bdb = hdb = tdb = NULL;
+ txns = failed = 0;
/*
* Open the database files.
*/
if ((ret = db_create(&adb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
- return (ERROR_RETURN);
+ goto err;
}
- snprintf(dbname, sizeof(dbname), "account");
- if ((ret = adb->open(adb, dbname, NULL, DB_UNKNOWN, 0, 0)) != 0) {
+ if ((ret = adb->open(adb, NULL, "account", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: account");
- return (ERROR_RETURN);
+ goto err;
}
-
if ((ret = db_create(&bdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
- return (ERROR_RETURN);
+ goto err;
}
- snprintf(dbname, sizeof(dbname), "branch");
- if ((ret = bdb->open(bdb, dbname, NULL, DB_UNKNOWN, 0, 0)) != 0) {
+ if ((ret = bdb->open(bdb, NULL, "branch", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: branch");
- return (ERROR_RETURN);
+ goto err;
}
-
- if ((ret = db_create(&tdb, dbenv, 0)) != 0) {
+ if ((ret = db_create(&hdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
- return (ERROR_RETURN);
+ goto err;
}
- snprintf(dbname, sizeof(dbname), "teller");
- if ((ret = tdb->open(tdb, dbname, NULL, DB_UNKNOWN, 0, 0)) != 0) {
- dbenv->err(dbenv, ret, "DB->open: teller");
- return (ERROR_RETURN);
+ if ((ret = hdb->open(hdb, NULL, "history", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->open: history");
+ goto err;
}
-
- if ((ret = db_create(&hdb, dbenv, 0)) != 0) {
+ if ((ret = db_create(&tdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
- return (ERROR_RETURN);
+ goto err;
}
- snprintf(dbname, sizeof(dbname), "history");
- if ((ret = hdb->open(hdb, dbname, NULL, DB_UNKNOWN, 0, 0)) != 0) {
- dbenv->err(dbenv, ret, "DB->open: history");
- return (ERROR_RETURN);
+ if ((ret = tdb->open(tdb, NULL, "teller", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->open: teller");
+ goto err;
}
- txns = failed = ifailed = 0;
starttime = time(NULL);
lasttime = starttime;
- while (n-- > 0) {
+ for (ifailed = 0; n-- > 0;) {
txns++;
ret = tp_txn(dbenv, adb, bdb, tdb, hdb,
accounts, branches, tellers, verbose);
@@ -678,8 +560,7 @@ tp_run(dbenv, n, accounts, branches, tellers, verbose)
curtime = time(NULL);
gtps = (double)(txns - failed) / (curtime - starttime);
itps = (double)(5000 - ifailed) / (curtime - lasttime);
- printf("[%d] %d txns %d failed ", (int)pid,
- txns, failed);
+ printf("%d txns %d failed ", txns, failed);
printf("%6.2f TPS (gross) %6.2f TPS (interval)\n",
gtps, itps);
lasttime = curtime;
@@ -687,13 +568,17 @@ tp_run(dbenv, n, accounts, branches, tellers, verbose)
}
}
- (void)adb->close(adb, 0);
- (void)bdb->close(bdb, 0);
- (void)tdb->close(tdb, 0);
- (void)hdb->close(hdb, 0);
+err: if (adb != NULL)
+ (void)adb->close(adb, 0);
+ if (bdb != NULL)
+ (void)bdb->close(bdb, 0);
+ if (tdb != NULL)
+ (void)tdb->close(tdb, 0);
+ if (hdb != NULL)
+ (void)hdb->close(hdb, 0);
printf("%ld transactions begun %ld failed\n", (long)txns, (long)failed);
- return (0);
+ return (ret == 0 ? 0 : 1);
}
/*
@@ -711,7 +596,7 @@ tp_txn(dbenv, adb, bdb, tdb, hdb, accounts, branches, tellers, verbose)
db_recno_t key;
defrec rec;
histrec hrec;
- int account, branch, teller;
+ int account, branch, teller, ret;
t = NULL;
acurs = bcurs = tcurs = NULL;
@@ -746,7 +631,7 @@ tp_txn(dbenv, adb, bdb, tdb, hdb, accounts, branches, tellers, verbose)
d_histdbt.flags = DB_DBT_PARTIAL;
/* START TIMING */
- if (txn_begin(dbenv, NULL, &t, 0) != 0)
+ if (dbenv->txn_begin(dbenv, NULL, &t, 0) != 0)
goto err;
if (adb->cursor(adb, t, &acurs, 0) != 0 ||
@@ -789,7 +674,9 @@ tp_txn(dbenv, adb, bdb, tdb, hdb, accounts, branches, tellers, verbose)
tcurs->c_close(tcurs) != 0)
goto err;
- if (txn_commit(t, 0) != 0)
+ ret = t->commit(t, 0);
+ t = NULL;
+ if (ret != 0)
goto err;
/* END TIMING */
@@ -802,7 +689,7 @@ err: if (acurs != NULL)
if (tcurs != NULL)
(void)tcurs->c_close(tcurs);
if (t != NULL)
- (void)txn_abort(t);
+ (void)t->abort(t);
if (verbose)
printf("Transaction A=%ld B=%ld T=%ld failed\n",
diff --git a/bdb/examples_c/ex_tpcb.h b/bdb/examples_c/ex_tpcb.h
index ef90bc53234..22b79c37e80 100644
--- a/bdb/examples_c/ex_tpcb.h
+++ b/bdb/examples_c/ex_tpcb.h
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: ex_tpcb.h,v 11.4 2000/05/17 19:21:02 bostic Exp $
+ * $Id: ex_tpcb.h,v 11.6 2002/01/11 15:52:06 bostic Exp $
*/
#ifndef _TPCB_H_
diff --git a/bdb/examples_cxx/AccessExample.cpp b/bdb/examples_cxx/AccessExample.cpp
index ae885aa8388..921463b3a54 100644
--- a/bdb/examples_cxx/AccessExample.cpp
+++ b/bdb/examples_cxx/AccessExample.cpp
@@ -1,29 +1,26 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: AccessExample.cpp,v 11.7 2000/12/06 18:58:23 bostic Exp $
+ * $Id: AccessExample.cpp,v 11.18 2002/01/23 15:33:20 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#include <iostream.h>
+#include <iostream>
+#include <iomanip>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
-#endif
-#include <iomanip.h>
#include <db_cxx.h>
+using std::cin;
+using std::cout;
+using std::cerr;
+
class AccessExample
{
public:
@@ -38,14 +35,8 @@ private:
void operator = (const AccessExample &);
};
-static void usage(); // forward
-
-int main(int argc, char *argv[])
+int main()
{
- if (argc > 1) {
- usage();
- }
-
// Use a try block just to report any errors.
// An alternate approach to using exceptions is to
// use error models (see DbEnv::set_error_model()) so
@@ -54,20 +45,14 @@ int main(int argc, char *argv[])
try {
AccessExample app;
app.run();
- return 0;
+ return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "AccessExample: " << dbe.what() << "\n";
- return 1;
+ return (EXIT_FAILURE);
}
}
-static void usage()
-{
- cerr << "usage: AccessExample\n";
- exit(1);
-}
-
const char AccessExample::FileName[] = "access.db";
AccessExample::AccessExample()
@@ -77,7 +62,7 @@ AccessExample::AccessExample()
void AccessExample::run()
{
// Remove the previous database.
- (void)unlink(FileName);
+ (void)remove(FileName);
// Create the database object.
// There is no environment for this simple example.
@@ -87,7 +72,7 @@ void AccessExample::run()
db.set_errpfx("AccessExample");
db.set_pagesize(1024); /* Page size: 1K. */
db.set_cachesize(0, 32 * 1024, 0);
- db.open(FileName, NULL, DB_BTREE, DB_CREATE, 0664);
+ db.open(NULL, FileName, NULL, DB_BTREE, DB_CREATE, 0664);
//
// Insert records into the database, where the key is the user
diff --git a/bdb/examples_cxx/BtRecExample.cpp b/bdb/examples_cxx/BtRecExample.cpp
index 98d9626b969..b56c3fe5837 100644
--- a/bdb/examples_cxx/BtRecExample.cpp
+++ b/bdb/examples_cxx/BtRecExample.cpp
@@ -1,35 +1,31 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: BtRecExample.cpp,v 11.6 2000/02/19 20:57:59 bostic Exp $
+ * $Id: BtRecExample.cpp,v 11.21 2002/01/23 15:33:20 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+
#include <errno.h>
-#include <iostream.h>
+#include <iostream>
+#include <iomanip>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#endif
-#include <iomanip.h>
#include <db_cxx.h>
+using std::cout;
+using std::cerr;
+
#define DATABASE "access.db"
#define WORDLIST "../test/wordlist"
-void usage();
-extern "C" int getopt(int, char * const *, const char *);
-
-char *progname = "BtRecExample"; // Program name.
+const char *progname = "BtRecExample"; // Program name.
class BtRecExample
{
@@ -38,7 +34,7 @@ public:
~BtRecExample();
void run();
void stats();
- void show(char *msg, Dbt *key, Dbt *data);
+ void show(const char *msg, Dbt *key, Dbt *data);
private:
Db *dbp;
@@ -51,7 +47,7 @@ BtRecExample::BtRecExample(FILE *fp)
int ret;
// Remove the previous database.
- (void)unlink(DATABASE);
+ (void)remove(DATABASE);
dbp = new Db(NULL, 0);
@@ -60,7 +56,7 @@ BtRecExample::BtRecExample(FILE *fp)
dbp->set_pagesize(1024); // 1K page sizes.
dbp->set_flags(DB_RECNUM); // Record numbers.
- dbp->open(DATABASE, NULL, DB_BTREE, DB_CREATE, 0664);
+ dbp->open(NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664);
//
// Insert records into the database, where the key is the word
@@ -107,7 +103,7 @@ void BtRecExample::stats()
{
DB_BTREE_STAT *statp;
- dbp->stat(&statp, NULL, 0);
+ dbp->stat(&statp, 0);
cout << progname << ": database contains "
<< (u_long)statp->bt_ndata << " records\n";
@@ -191,34 +187,22 @@ void BtRecExample::run()
// show --
// Display a key/data pair.
//
-void BtRecExample::show(char *msg, Dbt *key, Dbt *data)
+void BtRecExample::show(const char *msg, Dbt *key, Dbt *data)
{
cout << msg << (char *)key->get_data()
<< " : " << (char *)data->get_data() << "\n";
}
int
-main(int argc, char *argv[])
+main()
{
- extern char *optarg;
- extern int optind;
FILE *fp;
- int ch;
-
- while ((ch = getopt(argc, argv, "")) != EOF)
- switch (ch) {
- case '?':
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
// Open the word database.
if ((fp = fopen(WORDLIST, "r")) == NULL) {
fprintf(stderr, "%s: open %s: %s\n",
progname, WORDLIST, db_strerror(errno));
- exit (1);
+ return (EXIT_FAILURE);
}
try {
@@ -233,15 +217,8 @@ main(int argc, char *argv[])
}
catch (DbException &dbe) {
cerr << "Exception: " << dbe.what() << "\n";
- return dbe.get_errno();
+ return (EXIT_FAILURE);
}
- return (0);
-}
-
-void
-usage()
-{
- (void)fprintf(stderr, "usage: %s\n", progname);
- exit(1);
+ return (EXIT_SUCCESS);
}
diff --git a/bdb/examples_cxx/EnvExample.cpp b/bdb/examples_cxx/EnvExample.cpp
index bef1f3d1ace..4eeb9f115e2 100644
--- a/bdb/examples_cxx/EnvExample.cpp
+++ b/bdb/examples_cxx/EnvExample.cpp
@@ -1,28 +1,27 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: EnvExample.cpp,v 11.12 2000/10/27 20:32:00 dda Exp $
+ * $Id: EnvExample.cpp,v 11.24 2002/01/11 15:52:15 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
-#include <iostream.h>
+#include <iostream>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#endif
#include <db_cxx.h>
+using std::ostream;
+using std::cout;
+using std::cerr;
+
#ifdef macintosh
#define DATABASE_HOME ":database"
#define CONFIG_DATA_DIR ":database"
@@ -36,10 +35,10 @@
#endif
#endif
-void db_setup(char *, char *, ostream&);
-void db_teardown(char *, char *, ostream&);
+void db_setup(const char *, const char *, ostream&);
+void db_teardown(const char *, const char *, ostream&);
-char *progname = "EnvExample"; /* Program name. */
+const char *progname = "EnvExample"; /* Program name. */
//
// An example of a program creating/configuring a Berkeley DB environment.
@@ -54,7 +53,7 @@ main(int, char **)
// and check error returns from all methods.
//
try {
- char *data_dir, *home;
+ const char *data_dir, *home;
//
// All of the shared database files live in /home/database,
@@ -64,21 +63,21 @@ main(int, char **)
data_dir = CONFIG_DATA_DIR;
cout << "Setup env\n";
- db_setup(DATABASE_HOME, data_dir, cerr);
+ db_setup(home, data_dir, cerr);
cout << "Teardown env\n";
- db_teardown(DATABASE_HOME, data_dir, cerr);
- return 0;
+ db_teardown(home, data_dir, cerr);
+ return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
- cerr << "AccessExample: " << dbe.what() << "\n";
- return 1;
+ cerr << "EnvExample: " << dbe.what() << "\n";
+ return (EXIT_FAILURE);
}
}
// Note that any of the db calls can throw DbException
void
-db_setup(char *home, char *data_dir, ostream& err_stream)
+db_setup(const char *home, const char *data_dir, ostream& err_stream)
{
//
// Create an environment object and initialize it for error
@@ -98,7 +97,7 @@ db_setup(char *home, char *data_dir, ostream& err_stream)
(void)dbenv->set_data_dir(data_dir);
// Open the environment with full transactional support.
- dbenv->open(DATABASE_HOME,
+ dbenv->open(home,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0);
// Do something interesting...
@@ -108,7 +107,7 @@ db_setup(char *home, char *data_dir, ostream& err_stream)
}
void
-db_teardown(char *home, char *data_dir, ostream& err_stream)
+db_teardown(const char *home, const char *data_dir, ostream& err_stream)
{
// Remove the shared database regions.
DbEnv *dbenv = new DbEnv(0);
diff --git a/bdb/examples_cxx/LockExample.cpp b/bdb/examples_cxx/LockExample.cpp
index cfab2868098..167900b9476 100644
--- a/bdb/examples_cxx/LockExample.cpp
+++ b/bdb/examples_cxx/LockExample.cpp
@@ -1,27 +1,26 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: LockExample.cpp,v 11.8 2001/01/04 14:23:30 dda Exp $
+ * $Id: LockExample.cpp,v 11.22 2002/01/11 15:52:15 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
-#include <iostream.h>
+#include <iostream>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#endif
#include <db_cxx.h>
-char *progname = "LockExample"; // Program name.
+using std::cin;
+using std::cout;
+using std::cerr;
+
+const char *progname = "LockExample"; // Program name.
//
// An example of a program using DBLock and related classes.
@@ -30,18 +29,20 @@ class LockExample : public DbEnv
{
public:
void run();
+ int error_code() { return (ecode); }
LockExample(const char *home, u_int32_t maxlocks, int do_unlink);
private:
static const char FileName[];
+ int ecode;
// no need for copy and assignment
LockExample(const LockExample &);
void operator = (const LockExample &);
};
-static void usage(); // forward
+static int usage(); // forward
int
main(int argc, char *argv[])
@@ -57,44 +58,51 @@ main(int argc, char *argv[])
for (int argnum = 1; argnum < argc; ++argnum) {
if (strcmp(argv[argnum], "-h") == 0) {
if (++argnum >= argc)
- usage();
+ return (usage());
home = argv[argnum];
}
else if (strcmp(argv[argnum], "-m") == 0) {
if (++argnum >= argc)
- usage();
+ return (usage());
if ((i = atoi(argv[argnum])) <= 0)
- usage();
+ return (usage());
maxlocks = (u_int32_t)i; /* XXX: possible overflow. */
}
else if (strcmp(argv[argnum], "-u") == 0) {
do_unlink = 1;
}
else {
- usage();
+ return (usage());
}
}
try {
+ int ecode;
+
if (do_unlink) {
// Create an environment that immediately
// removes all files.
LockExample tmp(home, maxlocks, do_unlink);
+ if ((ecode = tmp.error_code()) != 0)
+ return (ecode);
}
LockExample app(home, maxlocks, do_unlink);
+ if ((ecode = app.error_code()) != 0)
+ return (ecode);
app.run();
app.close(0);
- return 0;
+ return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "LockExample: " << dbe.what() << "\n";
- return 1;
+ return (EXIT_FAILURE);
}
}
LockExample::LockExample(const char *home, u_int32_t maxlocks, int do_unlink)
: DbEnv(0)
+, ecode(0)
{
int ret;
@@ -102,7 +110,7 @@ LockExample::LockExample(const char *home, u_int32_t maxlocks, int do_unlink)
if ((ret = remove(home, DB_FORCE)) != 0) {
cerr << progname << ": DbEnv::remove: "
<< strerror(errno) << "\n";
- exit (1);
+ ecode = EXIT_FAILURE;
}
}
else {
@@ -198,7 +206,7 @@ void LockExample::run()
continue;
}
DbLock lock = locks[lockid];
- ret = lock.put(this);
+ ret = lock_put(&lock);
did_get = 0;
}
@@ -228,9 +236,9 @@ void LockExample::run()
delete locks;
}
-static void
+static int
usage()
{
cerr << "usage: LockExample [-u] [-h home] [-m maxlocks]\n";
- exit(1);
+ return (EXIT_FAILURE);
}
diff --git a/bdb/examples_cxx/MpoolExample.cpp b/bdb/examples_cxx/MpoolExample.cpp
index cf0f5f7e6a4..276cb94d66d 100644
--- a/bdb/examples_cxx/MpoolExample.cpp
+++ b/bdb/examples_cxx/MpoolExample.cpp
@@ -1,43 +1,44 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: MpoolExample.cpp,v 11.9 2000/10/27 20:32:01 dda Exp $
+ * $Id: MpoolExample.cpp,v 11.23 2002/01/11 15:52:15 bostic Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
-#include <iostream.h>
+#include <iostream>
+#include <fstream>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include <unistd.h>
-#endif
#include <db_cxx.h>
+using std::cout;
+using std::cerr;
+using std::ios;
+using std::ofstream;
+
#define MPOOL "mpool"
-void init(char *, int, int);
-void run(DB_ENV *, int, int, int);
+int init(const char *, int, int);
+int run(DB_ENV *, int, int, int);
-static void usage();
+static int usage();
-char *progname = "MpoolExample"; // Program name.
+const char *progname = "MpoolExample"; // Program name.
class MpoolExample : public DbEnv
{
public:
MpoolExample();
- void initdb(const char *home, int cachesize);
- void run(int hits, int pagesize, int npages);
+ int initdb(const char *home, int cachesize);
+ int run(int hits, int pagesize, int npages);
private:
static const char FileName[];
@@ -49,6 +50,7 @@ private:
int main(int argc, char *argv[])
{
+ int ret;
int cachesize = 20 * 1024;
int hits = 1000;
int npages = 50;
@@ -77,7 +79,8 @@ int main(int argc, char *argv[])
}
// Initialize the file.
- init(MPOOL, pagesize, npages);
+ if ((ret = init(MPOOL, pagesize, npages)) != 0)
+ return (ret);
try {
MpoolExample app;
@@ -87,14 +90,16 @@ int main(int argc, char *argv[])
<< "; pagesize: " << pagesize
<< "; N pages: " << npages << "\n";
- app.initdb(NULL, cachesize);
- app.run(hits, pagesize, npages);
+ if ((ret = app.initdb(NULL, cachesize)) != 0)
+ return (ret);
+ if ((ret = app.run(hits, pagesize, npages)) != 0)
+ return (ret);
cout << "MpoolExample: completed\n";
- return 0;
+ return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "MpoolExample: " << dbe.what() << "\n";
- return 1;
+ return (EXIT_FAILURE);
}
}
@@ -102,21 +107,16 @@ int main(int argc, char *argv[])
// init --
// Create a backing file.
//
-void
-init(char *file, int pagesize, int npages)
+int
+init(const char *file, int pagesize, int npages)
{
- //
// Create a file with the right number of pages, and store a page
// number on each page.
- //
- int fd;
- int flags = O_CREAT | O_RDWR | O_TRUNC;
-#ifdef DB_WIN32
- flags |= O_BINARY;
-#endif
- if ((fd = open(file, flags, 0666)) < 0) {
- cerr << "MpoolExample: " << file << ": " << strerror(errno) << "\n";
- exit(1);
+ ofstream of(file, ios::out | ios::binary);
+
+ if (of.fail()) {
+ cerr << "MpoolExample: " << file << ": open failed\n";
+ return (EXIT_FAILURE);
}
char *p = new char[pagesize];
memset(p, 0, pagesize);
@@ -124,21 +124,22 @@ init(char *file, int pagesize, int npages)
// The pages are numbered from 0.
for (int cnt = 0; cnt <= npages; ++cnt) {
*(db_pgno_t *)p = cnt;
- if (write(fd, p, pagesize) != pagesize) {
- cerr << "MpoolExample: " << file
- << ": " << strerror(errno) << "\n";
- exit(1);
+ of.write(p, pagesize);
+ if (of.fail()) {
+ cerr << "MpoolExample: " << file << ": write failed\n";
+ return (EXIT_FAILURE);
}
}
delete [] p;
+ return (EXIT_SUCCESS);
}
-static void
+static int
usage()
{
cerr << "usage: MpoolExample [-c cachesize] "
<< "[-h hits] [-n npages] [-p pagesize]\n";
- exit(1);
+ return (EXIT_FAILURE);
}
// Note: by using DB_CXX_NO_EXCEPTIONS, we get explicit error returns
@@ -150,61 +151,68 @@ MpoolExample::MpoolExample()
{
}
-void MpoolExample::initdb(const char *home, int cachesize)
+int MpoolExample::initdb(const char *home, int cachesize)
{
set_error_stream(&cerr);
set_errpfx("MpoolExample");
set_cachesize(0, cachesize, 0);
open(home, DB_CREATE | DB_INIT_MPOOL, 0);
+ return (EXIT_SUCCESS);
}
//
// run --
// Get a set of pages.
//
-void
+int
MpoolExample::run(int hits, int pagesize, int npages)
{
db_pgno_t pageno;
- int cnt;
+ int cnt, ret;
void *p;
- // Open the file in the pool.
- DbMpoolFile *dbmfp;
+ // Open the file in the environment.
+ DbMpoolFile *mfp;
- DbMpoolFile::open(this, MPOOL, 0, 0, pagesize, NULL, &dbmfp);
+ if ((ret = memp_fcreate(&mfp, 0)) != 0) {
+ cerr << "MpoolExample: memp_fcreate failed: "
+ << strerror(ret) << "\n";
+ return (EXIT_FAILURE);
+ }
+ mfp->open(MPOOL, 0, 0, pagesize);
cout << "retrieve " << hits << " random pages... ";
srand((unsigned int)time(NULL));
for (cnt = 0; cnt < hits; ++cnt) {
pageno = (rand() % npages) + 1;
- if ((errno = dbmfp->get(&pageno, 0, &p)) != 0) {
+ if ((ret = mfp->get(&pageno, 0, &p)) != 0) {
cerr << "MpoolExample: unable to retrieve page "
<< (unsigned long)pageno << ": "
- << strerror(errno) << "\n";
- exit(1);
+ << strerror(ret) << "\n";
+ return (EXIT_FAILURE);
}
if (*(db_pgno_t *)p != pageno) {
cerr << "MpoolExample: wrong page retrieved ("
<< (unsigned long)pageno << " != "
<< *(int *)p << ")\n";
- exit(1);
+ return (EXIT_FAILURE);
}
- if ((errno = dbmfp->put(p, 0)) != 0) {
+ if ((ret = mfp->put(p, 0)) != 0) {
cerr << "MpoolExample: unable to return page "
<< (unsigned long)pageno << ": "
- << strerror(errno) << "\n";
- exit(1);
+ << strerror(ret) << "\n";
+ return (EXIT_FAILURE);
}
}
cout << "successful.\n";
// Close the pool.
- if ((errno = close(0)) != 0) {
- cerr << "MpoolExample: " << strerror(errno) << "\n";
- exit(1);
+ if ((ret = close(0)) != 0) {
+ cerr << "MpoolExample: " << strerror(ret) << "\n";
+ return (EXIT_FAILURE);
}
+ return (EXIT_SUCCESS);
}
diff --git a/bdb/examples_cxx/TpcbExample.cpp b/bdb/examples_cxx/TpcbExample.cpp
index f4ca72df8e3..a57fa6aee8a 100644
--- a/bdb/examples_cxx/TpcbExample.cpp
+++ b/bdb/examples_cxx/TpcbExample.cpp
@@ -1,54 +1,35 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: TpcbExample.cpp,v 11.14 2000/10/27 20:32:01 dda Exp $
+ * $Id: TpcbExample.cpp,v 11.30 2002/02/13 06:08:34 mjc Exp $
*/
-#include "db_config.h"
-
-#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#endif
-
-#ifdef DB_WIN32
-#include <sys/types.h>
-#include <sys/timeb.h>
-#endif
+#include <time.h>
-#include <iostream.h>
-#include <iomanip.h>
+#include <iostream>
+#include <iomanip>
#include <db_cxx.h>
-typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
+using std::cout;
+using std::cerr;
-void errExit(int err, const char *); // show err as errno and exit
+typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
-void invarg(int, char *);
+static int invarg(int, char *);
u_int32_t random_id(FTYPE, u_int32_t, u_int32_t, u_int32_t);
u_int32_t random_int(u_int32_t, u_int32_t);
-static void usage(void);
+static int usage(void);
int verbose;
-char *progname = "TpcbExample"; // Program name.
+const char *progname = "TpcbExample"; // Program name.
class TpcbExample : public DbEnv
{
@@ -58,7 +39,7 @@ public:
int txn(Db *, Db *, Db *, Db *,
int, int, int);
void populateHistory(Db *, int, u_int32_t, u_int32_t, u_int32_t);
- void populateTable(Db *, u_int32_t, u_int32_t, int, char *);
+ void populateTable(Db *, u_int32_t, u_int32_t, int, const char *);
// Note: the constructor creates a DbEnv(), which is
// not fully initialized until the DbEnv::open() method
@@ -139,7 +120,8 @@ main(int argc, char *argv[])
unsigned long seed;
int accounts, branches, tellers, history;
int iflag, mpool, ntxns, txn_no_sync;
- char *home, *endarg;
+ const char *home;
+ char *endarg;
home = "TESTDIR";
accounts = branches = history = tellers = 0;
@@ -147,24 +129,24 @@ main(int argc, char *argv[])
mpool = ntxns = 0;
verbose = 0;
iflag = 0;
- seed = (unsigned long)getpid();
+ seed = (unsigned long)time(NULL);
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-a") == 0) {
// Number of account records
if ((accounts = atoi(argv[++i])) <= 0)
- invarg('a', argv[i]);
+ return (invarg('a', argv[i]));
}
else if (strcmp(argv[i], "-b") == 0) {
// Number of branch records
if ((branches = atoi(argv[++i])) <= 0)
- invarg('b', argv[i]);
+ return (invarg('b', argv[i]));
}
else if (strcmp(argv[i], "-c") == 0) {
// Cachesize in bytes
if ((mpool = atoi(argv[++i])) <= 0)
- invarg('c', argv[i]);
+ return (invarg('c', argv[i]));
}
else if (strcmp(argv[i], "-f") == 0) {
// Fast mode: no txn sync.
@@ -181,30 +163,30 @@ main(int argc, char *argv[])
else if (strcmp(argv[i], "-n") == 0) {
// Number of transactions
if ((ntxns = atoi(argv[++i])) <= 0)
- invarg('n', argv[i]);
+ return (invarg('n', argv[i]));
}
else if (strcmp(argv[i], "-S") == 0) {
// Random number seed.
seed = strtoul(argv[++i], &endarg, 0);
if (*endarg != '\0')
- invarg('S', argv[i]);
+ return (invarg('S', argv[i]));
}
else if (strcmp(argv[i], "-s") == 0) {
// Number of history records
if ((history = atoi(argv[++i])) <= 0)
- invarg('s', argv[i]);
+ return (invarg('s', argv[i]));
}
else if (strcmp(argv[i], "-t") == 0) {
// Number of teller records
if ((tellers = atoi(argv[++i])) <= 0)
- invarg('t', argv[i]);
+ return (invarg('t', argv[i]));
}
else if (strcmp(argv[i], "-v") == 0) {
// Verbose option.
verbose = 1;
}
else {
- usage();
+ return (usage());
}
}
@@ -216,9 +198,9 @@ main(int argc, char *argv[])
history = history == 0 ? HISTORY : history;
if (verbose)
- cout << (long)accounts << " Accounts "
- << (long)branches << " Branches "
- << (long)tellers << " Tellers "
+ cout << (long)accounts << " Accounts, "
+ << (long)branches << " Branches, "
+ << (long)tellers << " Tellers, "
<< (long)history << " History\n";
try {
@@ -226,43 +208,44 @@ main(int argc, char *argv[])
// Must be done in within a try block, unless you
// change the error model in the environment options.
//
- TpcbExample app(home, mpool, iflag, txn_no_sync ? DB_TXN_NOSYNC : 0);
+ TpcbExample app(home, mpool, iflag,
+ txn_no_sync ? DB_TXN_NOSYNC : 0);
if (iflag) {
if (ntxns != 0)
- usage();
+ return (usage());
app.populate(accounts, branches, history, tellers);
}
else {
if (ntxns == 0)
- usage();
+ return (usage());
app.run(ntxns, accounts, branches, tellers);
}
app.close(0);
- return 0;
+ return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "TpcbExample: " << dbe.what() << "\n";
- return 1;
+ return (EXIT_FAILURE);
}
}
-void
+static int
invarg(int arg, char *str)
{
cerr << "TpcbExample: invalid argument for -"
<< (char)arg << ": " << str << "\n";
- exit(1);
+ return (EXIT_FAILURE);
}
-static void
+static int
usage()
{
cerr << "usage: TpcbExample [-fiv] [-a accounts] [-b branches]\n"
<< " [-c cachesize] [-h home] [-n transactions ]\n"
<< " [-S seed] [-s history] [-t tellers]\n";
- exit(1);
+ return (EXIT_FAILURE);
}
TpcbExample::TpcbExample(const char *home, int cachesize,
@@ -274,7 +257,11 @@ TpcbExample::TpcbExample(const char *home, int cachesize,
set_error_stream(&cerr);
set_errpfx("TpcbExample");
(void)set_cachesize(0, cachesize == 0 ?
- 4 * 1024 * 1024 : (u_int32_t)cachesize, 0);
+ 4 * 1024 * 1024 : (u_int32_t)cachesize, 0);
+
+ if (flags & (DB_TXN_NOSYNC))
+ set_flags(DB_TXN_NOSYNC, 1);
+ flags &= ~(DB_TXN_NOSYNC);
local_flags = flags | DB_CREATE | DB_INIT_MPOOL;
if (!initializing)
@@ -302,9 +289,10 @@ TpcbExample::populate(int accounts, int branches, int history, int tellers)
dbp = new Db(this, 0);
dbp->set_h_nelem((unsigned int)accounts);
- if ((err = dbp->open("account", NULL, DB_HASH,
- DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
- errExit(err, "Open of account file failed");
+ if ((err = dbp->open(NULL, "account", NULL, DB_HASH,
+ DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
+ DbException except("Account file create failed", err);
+ throw except;
}
start_anum = idnum;
@@ -312,7 +300,8 @@ TpcbExample::populate(int accounts, int branches, int history, int tellers)
idnum += accounts;
end_anum = idnum - 1;
if ((err = dbp->close(0)) != 0) {
- errExit(err, "Account file close failed");
+ DbException except("Account file close failed", err);
+ throw except;
}
delete dbp;
if (verbose)
@@ -329,16 +318,18 @@ TpcbExample::populate(int accounts, int branches, int history, int tellers)
dbp->set_h_nelem((unsigned int)branches);
dbp->set_pagesize(512);
- if ((err = dbp->open("branch", NULL, DB_HASH,
- DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
- errExit(err, "Branch file create failed");
+ if ((err = dbp->open(NULL, "branch", NULL, DB_HASH,
+ DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
+ DbException except("Branch file create failed", err);
+ throw except;
}
start_bnum = idnum;
populateTable(dbp, idnum, balance, branches, "branch");
idnum += branches;
end_bnum = idnum - 1;
if ((err = dbp->close(0)) != 0) {
- errExit(err, "Close of branch file failed");
+ DbException except("Close of branch file failed", err);
+ throw except;
}
delete dbp;
@@ -355,9 +346,10 @@ TpcbExample::populate(int accounts, int branches, int history, int tellers)
dbp->set_h_nelem((unsigned int)tellers);
dbp->set_pagesize(512);
- if ((err = dbp->open("teller", NULL, DB_HASH,
- DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
- errExit(err, "Teller file create failed");
+ if ((err = dbp->open(NULL, "teller", NULL, DB_HASH,
+ DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
+ DbException except("Teller file create failed", err);
+ throw except;
}
start_tnum = idnum;
@@ -365,7 +357,8 @@ TpcbExample::populate(int accounts, int branches, int history, int tellers)
idnum += tellers;
end_tnum = idnum - 1;
if ((err = dbp->close(0)) != 0) {
- errExit(err, "Close of teller file failed");
+ DbException except("Close of teller file failed", err);
+ throw except;
}
delete dbp;
if (verbose)
@@ -374,22 +367,24 @@ TpcbExample::populate(int accounts, int branches, int history, int tellers)
dbp = new Db(this, 0);
dbp->set_re_len(HISTORY_LEN);
- if ((err = dbp->open("history", NULL, DB_RECNO,
- DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
- errExit(err, "Create of history file failed");
+ if ((err = dbp->open(NULL, "history", NULL, DB_RECNO,
+ DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
+ DbException except("Create of history file failed", err);
+ throw except;
}
populateHistory(dbp, history, accounts, branches, tellers);
if ((err = dbp->close(0)) != 0) {
- errExit(err, "Close of history file failed");
+ DbException except("Close of history file failed", err);
+ throw except;
}
delete dbp;
}
void
TpcbExample::populateTable(Db *dbp,
- u_int32_t start_id, u_int32_t balance,
- int nrecs, char *msg)
+ u_int32_t start_id, u_int32_t balance,
+ int nrecs, const char *msg)
{
Defrec drec;
memset(&drec.pad[0], 1, sizeof(drec.pad));
@@ -405,14 +400,15 @@ TpcbExample::populateTable(Db *dbp,
dbp->put(NULL, &kdbt, &ddbt, DB_NOOVERWRITE)) != 0) {
cerr << "Failure initializing " << msg << " file: "
<< strerror(err) << "\n";
- exit(1);
+ DbException except("failure initializing file", err);
+ throw except;
}
}
}
void
-TpcbExample::populateHistory(Db *dbp, int nrecs,
- u_int32_t accounts, u_int32_t branches, u_int32_t tellers)
+TpcbExample::populateHistory(Db *dbp, int nrecs, u_int32_t accounts,
+ u_int32_t branches, u_int32_t tellers)
{
Histrec hrec;
memset(&hrec.pad[0], 1, sizeof(hrec.pad));
@@ -430,7 +426,9 @@ TpcbExample::populateHistory(Db *dbp, int nrecs,
int err;
key = (db_recno_t)i;
if ((err = dbp->put(NULL, &kdbt, &ddbt, DB_APPEND)) != 0) {
- errExit(err, "Failure initializing history file");
+ DbException except("failure initializing history file",
+ err);
+ throw except;
}
}
}
@@ -478,15 +476,6 @@ TpcbExample::run(int n, int accounts, int branches, int tellers)
double gtps, itps;
int failed, ifailed, ret, txns;
time_t starttime, curtime, lasttime;
-#ifndef DB_WIN32
- pid_t pid;
-
- pid = getpid();
-#else
- int pid;
-
- pid = 0;
-#endif
//
// Open the database files.
@@ -494,20 +483,32 @@ TpcbExample::run(int n, int accounts, int branches, int tellers)
int err;
adb = new Db(this, 0);
- if ((err = adb->open("account", NULL, DB_UNKNOWN, 0, 0)) != 0)
- errExit(err, "Open of account file failed");
+ if ((err = adb->open(NULL, "account", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
+ DbException except("Open of account file failed", err);
+ throw except;
+ }
bdb = new Db(this, 0);
- if ((err = bdb->open("branch", NULL, DB_UNKNOWN, 0, 0)) != 0)
- errExit(err, "Open of branch file failed");
+ if ((err = bdb->open(NULL, "branch", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
+ DbException except("Open of branch file failed", err);
+ throw except;
+ }
tdb = new Db(this, 0);
- if ((err = tdb->open("teller", NULL, DB_UNKNOWN, 0, 0)) != 0)
- errExit(err, "Open of teller file failed");
+ if ((err = tdb->open(NULL, "teller", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
+ DbException except("Open of teller file failed", err);
+ throw except;
+ }
hdb = new Db(this, 0);
- if ((err = hdb->open("history", NULL, DB_UNKNOWN, 0, 0)) != 0)
- errExit(err, "Open of history file failed");
+ if ((err = hdb->open(NULL, "history", NULL, DB_UNKNOWN,
+ DB_AUTO_COMMIT, 0)) != 0) {
+ DbException except("Open of history file failed", err);
+ throw except;
+ }
txns = failed = ifailed = 0;
starttime = time(NULL);
@@ -527,10 +528,9 @@ TpcbExample::run(int n, int accounts, int branches, int tellers)
// We use printf because it provides much simpler
// formatting than iostreams.
//
- printf("[%d] %d txns %d failed ", (int)pid,
- txns, failed);
+ printf("%d txns %d failed ", txns, failed);
printf("%6.2f TPS (gross) %6.2f TPS (interval)\n",
- gtps, itps);
+ gtps, itps);
lasttime = curtime;
ifailed = 0;
}
@@ -550,7 +550,7 @@ TpcbExample::run(int n, int accounts, int branches, int tellers)
//
int
TpcbExample::txn(Db *adb, Db *bdb, Db *tdb, Db *hdb,
- int accounts, int branches, int tellers)
+ int accounts, int branches, int tellers)
{
Dbc *acurs = NULL;
Dbc *bcurs = NULL;
@@ -560,7 +560,7 @@ TpcbExample::txn(Db *adb, Db *bdb, Db *tdb, Db *hdb,
db_recno_t key;
Defrec rec;
Histrec hrec;
- int account, branch, teller;
+ int account, branch, teller, ret;
Dbt d_dbt;
Dbt d_histdbt;
@@ -628,11 +628,12 @@ TpcbExample::txn(Db *adb, Db *bdb, Db *tdb, Db *hdb,
if (hdb->put(t, &k_histdbt, &d_histdbt, DB_APPEND) != 0)
goto err;
- if (acurs->close() != 0 || bcurs->close() != 0 ||
- tcurs->close() != 0)
+ if (acurs->close() != 0 || bcurs->close() != 0 || tcurs->close() != 0)
goto err;
- if (t->commit(0) != 0)
+ ret = t->commit(0);
+ t = NULL;
+ if (ret != 0)
goto err;
// END TIMING
@@ -654,13 +655,3 @@ err:
<< " T=" << (long)teller << " failed\n";
return (-1);
}
-
-void errExit(int err, const char *s)
-{
- cerr << progname << ": ";
- if (s != NULL) {
- cerr << s << ": ";
- }
- cerr << strerror(err) << "\n";
- exit(1);
-}
diff --git a/bdb/fileops/fileops.src b/bdb/fileops/fileops.src
new file mode 100644
index 00000000000..1fd39dc3c45
--- /dev/null
+++ b/bdb/fileops/fileops.src
@@ -0,0 +1,111 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: fileops.src,v 1.8 2002/04/06 18:25:55 bostic Exp $
+ */
+
+PREFIX __fop
+DBPRIVATE
+
+INCLUDE #include "db_config.h"
+INCLUDE
+INCLUDE #ifndef NO_SYSTEM_INCLUDES
+INCLUDE #include <sys/types.h>
+INCLUDE
+INCLUDE #include <ctype.h>
+INCLUDE #include <string.h>
+INCLUDE #endif
+INCLUDE
+INCLUDE #include "db_int.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
+INCLUDE #include "dbinc/fop.h"
+INCLUDE
+
+/*
+ * create -- create a file system object.
+ *
+ * name: name in the file system
+ * appname: indicates if the name needs to go through __db_appname
+ * mode: file system mode
+ */
+BEGIN create 143
+DBT name DBT s
+ARG appname u_int32_t lu
+ARG mode u_int32_t o
+END
+
+/*
+ * remove -- remove a file system object.
+ *
+ * name: name in the file system
+ * appname: indicates if the name needs to go through __db_appname
+ */
+BEGIN remove 144
+DBT name DBT s
+DBT fid DBT s
+ARG appname u_int32_t lu
+END
+
+/*
+ * write: log the writing of data into an object.
+ *
+ * name: file containing the page.
+ * appname: indicates if the name needs to go through __db_appname
+ * offset: offset in the file.
+ * page: the actual meta-data page.
+ * flag: non-0 indicates that this is a tempfile, so we needn't undo
+ * these modifications (we'll toss the file).
+ */
+BEGIN write 145
+DBT name DBT s
+ARG appname u_int32_t lu
+ARG offset u_int32_t lu
+PGDBT page DBT s
+ARG flag u_int32_t lu
+END
+
+/*
+ * rename: move a file from one name to another.
+ * The appname value indicates if this is a path name that should be used
+ * directly (i.e., no interpretation) or if it is a pathname that should
+ * be interpreted via calls to __db_appname. The fileid is the 20-byte
+ * DB fileid of the file being renamed. We need to check it on recovery
+ * so that we don't inadvertently overwrite good files.
+ */
+BEGIN rename 146
+DBT oldname DBT s
+DBT newname DBT s
+DBT fileid DBT s
+ARG appname u_int32_t lu
+END
+
+/*
+ * File removal record. This is a DB-level log record that indicates
+ * we've just completed some form of file removal. The purpose of this
+ * log record is to logically identify the particular instance of the
+ * named file so that during recovery, in deciding if we should roll-forward
+ * a remove or a rename, we can make sure that we don't roll one forward and
+ * delete or overwrite the wrong file.
+ * real_fid: The 20-byte unique file identifier of the original file being
+ * removed.
+ * tmp_fid: The unique fid of the tmp file that is removed.
+ * name: The pre- __db_appname name of the file
+ * child: The transaction that removed or renamed the file.
+ */
+ */
+BEGIN file_remove 141
+DBT real_fid DBT s
+DBT tmp_fid DBT s
+DBT name DBT s
+ARG appname u_int32_t lu
+ARG child u_int32_t lx
+END
diff --git a/bdb/fileops/fop_basic.c b/bdb/fileops/fop_basic.c
new file mode 100644
index 00000000000..08160ab2e1a
--- /dev/null
+++ b/bdb/fileops/fop_basic.c
@@ -0,0 +1,275 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: fop_basic.c,v 1.23 2002/08/11 02:11:23 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/log.h"
+#include "dbinc/db_page.h"
+#include "dbinc/fop.h"
+#include "dbinc/txn.h"
+#include "dbinc/db_am.h"
+
+/*
+ * This file implements the basic file-level operations. This code
+ * ought to be fairly independent of DB, other than through its
+ * error-reporting mechanism.
+ */
+
+/*
+ * __fop_create --
+ * Create a (transactionally protected) file system object. This is used
+ * to create DB files now, potentially blobs, queue extents and anything
+ * else you wish to store in a file system object.
+ *
+ * PUBLIC: int __fop_create __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, DB_FH *, const char *, APPNAME, int));
+ */
+int
+__fop_create(dbenv, txn, fhp, name, appname, mode)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB_FH *fhp;
+ const char *name;
+ APPNAME appname;
+ int mode;
+{
+ DB_FH fh;
+ DB_LSN lsn;
+ DBT data;
+ char *real_name;
+ int do_close, ret;
+
+ ret = 0;
+ real_name = NULL;
+
+ if (fhp != NULL)
+ do_close = 0;
+ else {
+ fhp = &fh;
+ memset(fhp, 0, sizeof(fh));
+ do_close = 1;
+ }
+
+ if (mode == 0)
+ mode = __db_omode("rw----");
+
+ if ((ret =
+ __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
+ goto err;
+
+ if (DBENV_LOGGING(dbenv)) {
+ memset(&data, 0, sizeof(data));
+ data.data = (void *)name;
+ data.size = (u_int32_t)strlen(name) + 1;
+ if ((ret = __fop_create_log(dbenv,
+ txn, &lsn, DB_FLUSH, &data, (u_int32_t)appname, mode)) != 0)
+ goto err;
+ }
+
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_POSTLOG, ret, name);
+
+ ret =
+ __os_open(dbenv, real_name, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp);
+
+err:
+DB_TEST_RECOVERY_LABEL
+ if (do_close && F_ISSET(fhp, DB_FH_VALID))
+ __os_closehandle(dbenv, fhp);
+ if (real_name != NULL)
+ __os_free(dbenv, real_name);
+ return (ret);
+}
+
+/*
+ * __fop_remove --
+ * Remove a file system object.
+ *
+ * PUBLIC: int __fop_remove __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, u_int8_t *, const char *, APPNAME));
+ */
+int
+__fop_remove(dbenv, txn, fileid, name, appname)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ u_int8_t *fileid;
+ const char *name;
+ APPNAME appname;
+{
+ DB_LSN lsn;
+ DBT fdbt, ndbt;
+ char *real_name;
+ int ret;
+
+ real_name = NULL;
+
+ if ((ret =
+ __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
+ goto err;
+
+ if (txn == NULL) {
+ if (fileid != NULL && (ret = dbenv->memp_nameop(
+ dbenv, fileid, NULL, real_name, NULL)) != 0)
+ goto err;
+ } else {
+ if (DBENV_LOGGING(dbenv)) {
+ memset(&fdbt, 0, sizeof(ndbt));
+ fdbt.data = fileid;
+ fdbt.size = fileid == NULL ? 0 : DB_FILE_ID_LEN;
+ memset(&ndbt, 0, sizeof(ndbt));
+ ndbt.data = (void *)name;
+ ndbt.size = (u_int32_t)strlen(name) + 1;
+ if ((ret = __fop_remove_log(dbenv,
+ txn, &lsn, 0, &ndbt, &fdbt, appname)) != 0)
+ goto err;
+ }
+ ret = __txn_remevent(dbenv, txn, real_name, fileid);
+ }
+
+err: if (real_name != NULL)
+ __os_free(dbenv, real_name);
+ return (ret);
+}
+
+/*
+ * __fop_write
+ *
+ * Write "size" bytes from "buf" to file "name" beginning at offset "off."
+ * If the file is open, supply a handle in fhp. Istmp indicate if this is
+ * an operation that needs to be undone in the face of failure (i.e., if
+ * this is a write to a temporary file, we're simply going to remove the
+ * file, so don't worry about undoing the write).
+ *
+ * Currently, we *only* use this with istmp true. If we need more general
+ * handling, then we'll have to zero out regions on abort (and possibly
+ * log the before image of the data in the log record).
+ *
+ * PUBLIC: int __fop_write __P((DB_ENV *, DB_TXN *, const char *, APPNAME,
+ * PUBLIC: DB_FH *, u_int32_t, u_int8_t *, u_int32_t, u_int32_t));
+ */
+int
+__fop_write(dbenv, txn, name, appname, fhp, off, buf, size, istmp)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ const char *name;
+ APPNAME appname;
+ DB_FH *fhp;
+ u_int32_t off;
+ u_int8_t *buf;
+ u_int32_t size, istmp;
+{
+ DB_FH fh;
+ DB_LSN lsn;
+ DBT data, namedbt;
+ char *real_name;
+ int ret, t_ret, we_opened;
+ size_t nbytes;
+
+ ret = 0;
+ we_opened = 0;
+ real_name = NULL;
+
+ if ((ret =
+ __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
+ goto err;
+
+ if (DBENV_LOGGING(dbenv)) {
+ memset(&data, 0, sizeof(data));
+ data.data = buf;
+ data.size = size;
+ memset(&namedbt, 0, sizeof(namedbt));
+ namedbt.data = (void *)name;
+ namedbt.size = (u_int32_t)strlen(name) + 1;
+ if ((ret = __fop_write_log(dbenv,
+ txn, &lsn, 0, &namedbt, appname, off, &data, istmp)) != 0)
+ goto err;
+ }
+
+ if (fhp == NULL) {
+ /* File isn't open; we need to reopen it. */
+ if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
+ goto err;
+ fhp = &fh;
+ we_opened = 1;
+ } else
+ we_opened = 0;
+
+ /* Seek to offset. */
+ if ((ret = __os_seek(dbenv, fhp, 0, 0, off, 0, DB_OS_SEEK_SET)) != 0)
+ goto err;
+
+ /* Now do the write. */
+ if ((ret = __os_write(dbenv, fhp, buf, size, &nbytes)) != 0)
+ goto err;
+
+err: if (we_opened)
+ if ((t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (real_name != NULL)
+ __os_free(dbenv, real_name);
+ return (ret);
+}
+
+/*
+ * __fop_rename --
+ * Change a file's name.
+ *
+ * PUBLIC: int __fop_rename __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, const char *, const char *, u_int8_t *, APPNAME));
+ */
+int
+__fop_rename(dbenv, txn, oldname, newname, fid, appname)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ const char *oldname;
+ const char *newname;
+ u_int8_t *fid;
+ APPNAME appname;
+{
+ DB_LSN lsn;
+ DBT fiddbt, new, old;
+ int ret;
+ char *n, *o;
+
+ if ((ret = __db_appname(dbenv, appname, oldname, 0, NULL, &o)) != 0)
+ goto err;
+ if ((ret = __db_appname(dbenv, appname, newname, 0, NULL, &n)) != 0)
+ goto err;
+
+ if (DBENV_LOGGING(dbenv)) {
+ memset(&old, 0, sizeof(old));
+ memset(&new, 0, sizeof(new));
+ memset(&fiddbt, 0, sizeof(fiddbt));
+ old.data = (void *)oldname;
+ old.size = (u_int32_t)strlen(oldname) + 1;
+ new.data = (void *)newname;
+ new.size = (u_int32_t)strlen(newname) + 1;
+ fiddbt.data = fid;
+ fiddbt.size = DB_FILE_ID_LEN;
+ if ((ret = __fop_rename_log(dbenv, txn, &lsn,
+ DB_FLUSH, &old, &new, &fiddbt, (u_int32_t)appname)) != 0)
+ goto err;
+ }
+
+ ret = dbenv->memp_nameop(dbenv, fid, newname, o, n);
+
+err: if (o != oldname)
+ __os_free(dbenv, o);
+ if (n != newname)
+ __os_free(dbenv, n);
+ return (ret);
+}
diff --git a/bdb/fileops/fop_rec.c b/bdb/fileops/fop_rec.c
new file mode 100644
index 00000000000..67720e01d13
--- /dev/null
+++ b/bdb/fileops/fop_rec.c
@@ -0,0 +1,308 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/fop.h"
+#include "dbinc/db_am.h"
+#include "dbinc/txn.h"
+
+/*
+ * __fop_create_recover --
+ * Recovery function for create.
+ *
+ * PUBLIC: int __fop_create_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_create_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ DB_FH fh;
+ __fop_create_args *argp;
+ char *real_name;
+ int ret;
+
+ real_name = NULL;
+ COMPQUIET(info, NULL);
+ REC_PRINT(__fop_create_print);
+ REC_NOOP_INTRO(__fop_create_read);
+
+ if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
+ (const char *)argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+
+ if (DB_UNDO(op))
+ (void)__os_unlink(dbenv, real_name);
+ else if (DB_REDO(op))
+ if ((ret = __os_open(dbenv, real_name,
+ DB_OSO_CREATE | DB_OSO_EXCL, argp->mode, &fh)) == 0)
+ __os_closehandle(dbenv, &fh);
+
+ *lsnp = argp->prev_lsn;
+
+out: if (real_name != NULL)
+ __os_free(dbenv, real_name);
+
+ REC_NOOP_CLOSE;
+}
+
+/*
+ * __fop_remove_recover --
+ * Recovery function for remove.
+ *
+ * PUBLIC: int __fop_remove_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_remove_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __fop_remove_args *argp;
+ char *real_name;
+ int ret;
+
+ real_name = NULL;
+ COMPQUIET(info, NULL);
+ REC_PRINT(__fop_remove_print);
+ REC_NOOP_INTRO(__fop_remove_read);
+
+ if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
+ (const char *)argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+
+ if (DB_REDO(op) && (ret = dbenv->memp_nameop(dbenv,
+ (u_int8_t *)argp->fid.data, NULL, real_name, NULL)) != 0)
+ goto out;
+
+ *lsnp = argp->prev_lsn;
+out: if (real_name != NULL)
+ __os_free(dbenv, real_name);
+ REC_NOOP_CLOSE;
+}
+
+/*
+ * __fop_write_recover --
+ * Recovery function for writechunk.
+ *
+ * PUBLIC: int __fop_write_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_write_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __fop_write_args *argp;
+ int ret;
+
+ COMPQUIET(info, NULL);
+ REC_PRINT(__fop_write_print);
+ REC_NOOP_INTRO(__fop_write_read);
+
+ if (DB_UNDO(op))
+ DB_ASSERT(argp->flag != 0);
+ else if (DB_REDO(op))
+ ret = __fop_write(dbenv,
+ argp->txnid, argp->name.data, argp->appname, NULL,
+ argp->offset, argp->page.data, argp->page.size, argp->flag);
+
+ *lsnp = argp->prev_lsn;
+ REC_NOOP_CLOSE;
+}
+
+/*
+ * __fop_rename_recover --
+ * Recovery function for rename.
+ *
+ * PUBLIC: int __fop_rename_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_rename_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __fop_rename_args *argp;
+ DBMETA *meta;
+ char *real_new, *real_old, *src;
+ int ret;
+ u_int8_t *fileid, mbuf[DBMETASIZE];
+
+ real_new = NULL;
+ real_old = NULL;
+ ret = 0;
+ meta = (DBMETA *)&mbuf[0];
+
+ COMPQUIET(info, NULL);
+ REC_PRINT(__fop_rename_print);
+ REC_NOOP_INTRO(__fop_rename_read);
+ fileid = argp->fileid.data;
+
+ if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
+ (const char *)argp->newname.data, 0, NULL, &real_new)) != 0)
+ goto out;
+ if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
+ (const char *)argp->oldname.data, 0, NULL, &real_old)) != 0)
+ goto out;
+
+ /*
+ * Verify that we are manipulating the correct file. We should always
+ * be OK on an ABORT or an APPLY, but during recovery, we have to
+ * check.
+ */
+ if (op != DB_TXN_ABORT && op != DB_TXN_APPLY) {
+ src = DB_UNDO(op) ? real_new : real_old;
+ /*
+ * Interpret any error as meaning that the file either doesn't
+ * exist, doesn't have a meta-data page, or is in some other
+ * way, shape or form, incorrect, so that we should not restore
+ * it.
+ */
+ if (__fop_read_meta(
+ dbenv, src, mbuf, DBMETASIZE, NULL, 1, 0) != 0)
+ goto done;
+ if (__db_chk_meta(dbenv, NULL, meta, 1) != 0)
+ goto done;
+ if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0)
+ goto done;
+ }
+
+ if (DB_UNDO(op))
+ (void)dbenv->memp_nameop(dbenv, fileid,
+ (const char *)argp->oldname.data, real_new, real_old);
+ if (DB_REDO(op))
+ (void)dbenv->memp_nameop(dbenv, fileid,
+ (const char *)argp->newname.data, real_old, real_new);
+
+done: *lsnp = argp->prev_lsn;
+out: if (real_new != NULL)
+ __os_free(dbenv, real_new);
+ if (real_old != NULL)
+ __os_free(dbenv, real_old);
+
+ REC_NOOP_CLOSE;
+}
+
+/*
+ * __fop_file_remove_recover --
+ * Recovery function for file_remove. On the REDO pass, we need to
+ * make sure no one recreated the file while we weren't looking. On an
+ * undo pass must check if the file we are interested in is the one that
+ * exists and then set the status of the child transaction depending on
+ * what we find out.
+ *
+ * PUBLIC: int __fop_file_remove_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __fop_file_remove_args *argp;
+ DBMETA *meta;
+ char *real_name;
+ int is_real, is_tmp, ret;
+ u_int8_t mbuf[DBMETASIZE];
+ u_int32_t cstat;
+
+ real_name = NULL;
+ is_real = is_tmp = 0;
+ meta = (DBMETA *)&mbuf[0];
+ REC_PRINT(__fop_file_remove_print);
+ REC_NOOP_INTRO(__fop_file_remove_read);
+
+ /*
+ * This record is only interesting on the backward, forward, and
+ * apply phases.
+ */
+ if (op != DB_TXN_BACKWARD_ROLL &&
+ op != DB_TXN_FORWARD_ROLL && op != DB_TXN_APPLY)
+ goto done;
+
+ if ((ret = __db_appname(dbenv,
+ (APPNAME)argp->appname, argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+
+ /* Verify that we are manipulating the correct file. */
+ if ((ret = __fop_read_meta(dbenv,
+ real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
+ /* File does not exist. */
+ cstat = TXN_EXPECTED;
+ } else {
+ /*
+ * We can ignore errors here since we'll simply fail the
+ * checks below and assume this is the wrong file.
+ */
+ (void)__db_chk_meta(dbenv, NULL, meta, 1);
+ is_real =
+ memcmp(argp->real_fid.data, meta->uid, DB_FILE_ID_LEN) == 0;
+ is_tmp =
+ memcmp(argp->tmp_fid.data, meta->uid, DB_FILE_ID_LEN) == 0;
+
+ if (!is_real && !is_tmp)
+ /* File exists, but isn't what we were removing. */
+ cstat = TXN_IGNORE;
+ else
+ /* File exists and is the one that we were removing. */
+ cstat = TXN_COMMIT;
+ }
+
+ if (DB_UNDO(op)) {
+ /* On the backward pass, we leave a note for the child txn. */
+ if ((ret = __db_txnlist_update(dbenv,
+ info, argp->child, cstat, NULL)) == DB_NOTFOUND)
+ ret = __db_txnlist_add(dbenv,
+ info, argp->child, cstat, NULL);
+ } else if (DB_REDO(op)) {
+ /*
+ * On the forward pass, check if someone recreated the
+ * file while we weren't looking.
+ */
+ if (cstat == TXN_COMMIT)
+ (void)dbenv->memp_nameop(dbenv,
+ is_real ? argp->real_fid.data : argp->tmp_fid.data,
+ NULL, real_name, NULL);
+ }
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (real_name != NULL)
+ __os_free(dbenv, real_name);
+ REC_NOOP_CLOSE;
+}
diff --git a/bdb/fileops/fop_util.c b/bdb/fileops/fop_util.c
new file mode 100644
index 00000000000..ea6d86ab08d
--- /dev/null
+++ b/bdb/fileops/fop_util.c
@@ -0,0 +1,928 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: fop_util.c,v 1.52 2002/09/10 02:41:42 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/fop.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+static int __fop_set_pgsize __P((DB *, DB_FH *, const char *));
+
+/*
+ * Acquire the environment meta-data lock. The parameters are the
+ * environment (ENV), the locker id to use in acquiring the lock (ID)
+ * and a pointer to a DB_LOCK.
+ */
+#define GET_ENVLOCK(ENV, ID, L) do { \
+ DBT __dbt; \
+ u_int32_t __lockval; \
+ \
+ if (LOCKING_ON((ENV))) { \
+ __lockval = 0; \
+ __dbt.data = &__lockval; \
+ __dbt.size = sizeof(__lockval); \
+ if ((ret = (ENV)->lock_get((ENV), (ID), \
+ 0, &__dbt, DB_LOCK_WRITE, (L))) != 0) \
+ goto err; \
+ } \
+} while (0)
+
+#define REL_ENVLOCK(ENV, L) \
+ (!LOCK_ISSET(*(L)) ? 0 : (ENV)->lock_put((ENV), (L)))
+
+/*
+ * If our caller is doing fcntl(2) locking, then we can't close it
+ * because that would discard the caller's lock. Otherwise, close
+ * the handle.
+ */
+#define CLOSE_HANDLE(D, F) { \
+ if (F_ISSET((F), DB_FH_VALID)) { \
+ if (LF_ISSET(DB_FCNTL_LOCKING)) \
+ (D)->saved_open_fhp = (F); \
+ else if ((ret = __os_closehandle((D)->dbenv,(F))) != 0) \
+ goto err; \
+ } \
+}
+
+/*
+ * __fop_lock_handle --
+ *
+ * Get the handle lock for a database. If the envlock is specified,
+ * do this as a lock_vec call that releases the enviroment lock before
+ * acquiring the handle lock.
+ *
+ * PUBLIC: int __fop_lock_handle __P((DB_ENV *,
+ * PUBLIC: DB *, u_int32_t, db_lockmode_t, DB_LOCK *, u_int32_t));
+ *
+ */
+int
+__fop_lock_handle(dbenv, dbp, locker, mode, elock, flags)
+ DB_ENV *dbenv;
+ DB *dbp;
+ u_int32_t locker;
+ db_lockmode_t mode;
+ DB_LOCK *elock;
+ u_int32_t flags;
+{
+ DBT fileobj;
+ DB_LOCKREQ reqs[2], *ereq;
+ DB_LOCK_ILOCK lock_desc;
+ int ret;
+
+ if (!LOCKING_ON(dbenv) || F_ISSET(dbp, DB_AM_COMPENSATE))
+ return (0);
+
+ /*
+ * If we are in recovery, the only locking we should be
+ * doing is on the global environment.
+ */
+ if (IS_RECOVERING(dbenv)) {
+ if (elock != NULL)
+ REL_ENVLOCK(dbenv, elock);
+ return (0);
+ }
+
+ memcpy(&lock_desc.fileid, &dbp->fileid, DB_FILE_ID_LEN);
+ lock_desc.pgno = dbp->meta_pgno;
+ lock_desc.type = DB_HANDLE_LOCK;
+
+ memset(&fileobj, 0, sizeof(fileobj));
+ fileobj.data = &lock_desc;
+ fileobj.size = sizeof(lock_desc);
+ DB_TEST_SUBLOCKS(dbenv, flags);
+ if (elock == NULL)
+ ret = dbenv->lock_get(dbenv, locker,
+ flags, &fileobj, mode, &dbp->handle_lock);
+ else {
+ reqs[0].op = DB_LOCK_PUT;
+ reqs[0].lock = *elock;
+ reqs[1].op = DB_LOCK_GET;
+ reqs[1].mode = mode;
+ reqs[1].obj = &fileobj;
+ reqs[1].timeout = 0;
+ if ((ret = __lock_vec(dbenv,
+ locker, flags, reqs, 2, &ereq)) == 0) {
+ dbp->handle_lock = reqs[1].lock;
+ LOCK_INIT(*elock);
+ } else if (ereq != reqs)
+ LOCK_INIT(*elock);
+ }
+
+ dbp->cur_lid = locker;
+ return (ret);
+}
+
+/*
+ * __fop_file_setup --
+ *
+ * Perform all the needed checking and locking to open up or create a
+ * file.
+ *
+ * There's a reason we don't push this code down into the buffer cache.
+ * The problem is that there's no information external to the file that
+ * we can use as a unique ID. UNIX has dev/inode pairs, but they are
+ * not necessarily unique after reboot, if the file was mounted via NFS.
+ * Windows has similar problems, as the FAT filesystem doesn't maintain
+ * dev/inode numbers across reboot. So, we must get something from the
+ * file we can use to ensure that, even after a reboot, the file we're
+ * joining in the cache is the right file for us to join. The solution
+ * we use is to maintain a file ID that's stored in the database, and
+ * that's why we have to open and read the file before calling into the
+ * buffer cache or obtaining a lock (we use this unique fileid to lock
+ * as well as to identify like files in the cache).
+ *
+ * PUBLIC: int __fop_file_setup __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, int, u_int32_t, u_int32_t *));
+ */
+int
+__fop_file_setup(dbp, txn, name, mode, flags, retidp)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name;
+ int mode;
+ u_int32_t flags, *retidp;
+{
+ DB_ENV *dbenv;
+ DB_FH fh, *fhp;
+ DB_LOCK elock, tmp_lock;
+ DB_TXN *stxn;
+ db_lockmode_t lmode;
+ u_int32_t locker, oflags;
+ u_int8_t mbuf[DBMETASIZE];
+ int created_fhp, created_locker, ret, tmp_created, truncating;
+ char *real_name, *real_tmpname, *tmpname;
+
+ DB_ASSERT(name != NULL);
+
+ *retidp = TXN_INVALID;
+
+ dbenv = dbp->dbenv;
+ LOCK_INIT(elock);
+ LOCK_INIT(tmp_lock);
+ stxn = NULL;
+ created_fhp = created_locker = 0;
+ real_name = real_tmpname = tmpname = NULL;
+ tmp_created = truncating = 0;
+
+ /*
+ * If we open a file handle and our caller is doing fcntl(2) locking,
+ * we can't close it because that would discard the caller's lock.
+ * Save it until we close the DB handle.
+ */
+ if (LF_ISSET(DB_FCNTL_LOCKING)) {
+ if ((ret = __os_malloc(dbenv, sizeof(*fhp), &fhp)) != 0)
+ return (ret);
+ created_fhp = 1;
+ } else
+ fhp = &fh;
+ memset(fhp, 0, sizeof(*fhp));
+
+ /*
+ * Get a lockerid for this handle. There are paths through queue
+ * rename and remove where this dbp already has a locker, so make
+ * sure we don't clobber it and conflict.
+ */
+ if (LOCKING_ON(dbenv) &&
+ !F_ISSET(dbp, DB_AM_COMPENSATE) && dbp->lid == DB_LOCK_INVALIDID) {
+ if ((ret = __lock_id(dbenv, &dbp->lid)) != 0)
+ goto err;
+ created_locker = 1;
+ }
+
+ locker = txn == NULL ? dbp->lid : txn->txnid;
+
+ /* Get the real backing file name. */
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
+ goto err;
+
+ /* Fill in the default file mode. */
+ if (mode == 0)
+ mode = __db_omode("rwrw--");
+
+ oflags = 0;
+ if (LF_ISSET(DB_RDONLY))
+ oflags |= DB_OSO_RDONLY;
+
+retry: if (!F_ISSET(dbp, DB_AM_COMPENSATE))
+ GET_ENVLOCK(dbenv, locker, &elock);
+ if ((ret = __os_exists(real_name, NULL)) == 0) {
+ if (LF_ISSET(DB_EXCL)) {
+ ret = EEXIST;
+ goto err;
+ }
+reopen: if ((ret = __fop_read_meta(dbenv, real_name,
+ mbuf, sizeof(mbuf), fhp, 0, oflags)) != 0)
+ goto err;
+
+ if ((ret = __db_meta_setup(dbenv,
+ dbp, real_name, (DBMETA *)mbuf, flags, 1)) != 0)
+ goto err;
+
+ /* Now, get our handle lock. */
+ lmode = LF_ISSET(DB_TRUNCATE) ? DB_LOCK_WRITE : DB_LOCK_READ;
+ if ((ret = __fop_lock_handle(dbenv,
+ dbp, locker, lmode, NULL, DB_LOCK_NOWAIT)) == 0) {
+ if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
+ goto err;
+ } else {
+ /* Someone else has file locked; need to wait. */
+ if ((ret = __os_closehandle(dbenv, fhp)) != 0)
+ goto err;
+ ret = __fop_lock_handle(dbenv,
+ dbp, locker, lmode, &elock, 0);
+ if (ret == DB_LOCK_NOTEXIST)
+ goto retry;
+ if (ret != 0)
+ goto err;
+ /*
+ * XXX I need to convince myself that I don't need
+ * to re-read the metadata page here.
+ * XXX If you do need to re-read it you'd better
+ * decrypt it too...
+ */
+ if ((ret = __os_open(dbenv, real_name, 0, 0, fhp)) != 0)
+ goto err;
+ }
+
+ /*
+ * Check for a truncate which needs to leap over to the
+ * create case.
+ */
+ if (LF_ISSET(DB_TRUNCATE)) {
+ /*
+ * Sadly, we need to close and reopen the handle
+ * in order to do the actual truncate. We couldn't
+ * do the truncate on the initial open because we
+ * needed to read the old file-id in order to lock.
+ */
+ if ((ret = __os_closehandle(dbenv, fhp)) != 0)
+ goto err;
+ if ((ret = __os_open(dbenv,
+ real_name, DB_OSO_TRUNC, 0, fhp)) != 0)
+ goto err;
+ /*
+ * This is not-transactional, so we'll do the
+ * open/create in-place.
+ */
+ tmp_lock = dbp->handle_lock;
+ truncating = 1;
+ tmpname = (char *)name;
+ goto creat2;
+ }
+
+ /*
+ * Check for a file in the midst of a rename
+ */
+ if (F_ISSET(dbp, DB_AM_IN_RENAME)) {
+ if (LF_ISSET(DB_CREATE)) {
+ F_CLR(dbp, DB_AM_IN_RENAME);
+ goto create;
+ } else {
+ ret = ENOENT;
+ goto err;
+ }
+ }
+
+ CLOSE_HANDLE(dbp, fhp);
+ goto done;
+ }
+
+ /* File does not exist. */
+ if (!LF_ISSET(DB_CREATE))
+ goto err;
+ ret = 0;
+
+ /*
+ * Need to create file; we need to set up the file,
+ * the fileid and the locks. Then we need to call
+ * the appropriate routines to create meta-data pages.
+ */
+ if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
+ goto err;
+
+create: if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
+ goto err;
+ if (TXN_ON(dbenv) && txn != NULL &&
+ (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0)
+ goto err;
+ if ((ret = __fop_create(dbenv,
+ stxn, fhp, tmpname, DB_APP_DATA, mode)) != 0)
+ goto err;
+ tmp_created = 1;
+creat2: if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, tmpname, 0, NULL, &real_tmpname)) != 0)
+ goto err;
+
+ /* Set the pagesize if it isn't yet set. */
+ if (dbp->pgsize == 0 &&
+ (ret = __fop_set_pgsize(dbp, fhp, real_tmpname)) != 0)
+ goto errmsg;
+
+ /* Construct a file_id. */
+ if ((ret = __os_fileid(dbenv, real_tmpname, 1, dbp->fileid)) != 0)
+ goto errmsg;
+
+ if ((ret = __db_new_file(dbp, stxn, fhp, tmpname)) != 0)
+ goto err;
+ CLOSE_HANDLE(dbp, fhp);
+
+ /* Now move the file into place. */
+ if (!F_ISSET(dbp, DB_AM_COMPENSATE))
+ GET_ENVLOCK(dbenv, locker, &elock);
+ if (!truncating && __os_exists(real_name, NULL) == 0) {
+ /*
+ * Someone managed to create the file; remove our temp
+ * and try to open the file that now exists.
+ */
+ (void)__fop_remove(dbenv,
+ NULL, dbp->fileid, tmpname, DB_APP_DATA);
+ if (LOCKING_ON(dbenv))
+ dbenv->lock_put(dbenv, &dbp->handle_lock);
+ LOCK_INIT(dbp->handle_lock);
+
+ /* If we have a saved handle; close it. */
+ if (LF_ISSET(DB_FCNTL_LOCKING))
+ (void)__os_closehandle(dbenv, fhp);
+ if (stxn != NULL) {
+ ret = stxn->abort(stxn);
+ stxn = NULL;
+ }
+ if (ret != 0)
+ goto err;
+ goto reopen;
+ }
+
+ /* We've successfully created, move the file into place. */
+ if ((ret = __fop_lock_handle(dbenv,
+ dbp, locker, DB_LOCK_WRITE, &elock, 0)) != 0)
+ goto err;
+ if (!truncating && (ret = __fop_rename(dbenv,
+ stxn, tmpname, name, dbp->fileid, DB_APP_DATA)) != 0)
+ goto err;
+
+ /* If this was a truncate; release lock on the old file. */
+ if (LOCK_ISSET(tmp_lock) && (ret = __lock_put(dbenv, &tmp_lock)) != 0)
+ goto err;
+
+ if (stxn != NULL) {
+ *retidp = stxn->txnid;
+ ret = stxn->commit(stxn, 0);
+ stxn = NULL;
+ } else
+ *retidp = TXN_INVALID;
+
+ if (ret != 0)
+ goto err;
+
+ F_SET(dbp, DB_AM_CREATED);
+
+ if (0) {
+errmsg: __db_err(dbenv, "%s: %s", name, db_strerror(ret));
+
+err: if (stxn != NULL)
+ (void)stxn->abort(stxn);
+ if (tmp_created && txn == NULL)
+ (void)__fop_remove(dbenv,
+ NULL, NULL, tmpname, DB_APP_DATA);
+ if (F_ISSET(fhp, DB_FH_VALID))
+ (void)__os_closehandle(dbenv, fhp);
+ if (LOCK_ISSET(tmp_lock))
+ __lock_put(dbenv, &tmp_lock);
+ if (LOCK_ISSET(dbp->handle_lock) && txn == NULL)
+ __lock_put(dbenv, &dbp->handle_lock);
+ if (LOCK_ISSET(elock))
+ (void)REL_ENVLOCK(dbenv, &elock);
+ if (created_locker) {
+ (void)__lock_id_free(dbenv, dbp->lid);
+ dbp->lid = DB_LOCK_INVALIDID;
+ }
+ if (created_fhp)
+ __os_free(dbenv, fhp);
+ }
+
+done: if (!truncating && tmpname != NULL)
+ __os_free(dbenv, tmpname);
+ if (real_name != NULL)
+ __os_free(dbenv, real_name);
+ if (real_tmpname != NULL)
+ __os_free(dbenv, real_tmpname);
+
+ return (ret);
+}
+
+/*
+ * __fop_set_pgsize --
+ * Set the page size based on file information.
+ */
+static int
+__fop_set_pgsize(dbp, fhp, name)
+ DB *dbp;
+ DB_FH *fhp;
+ const char *name;
+{
+ DB_ENV *dbenv;
+ u_int32_t iopsize;
+ int ret;
+
+ dbenv = dbp->dbenv;
+
+ /*
+ * Use the filesystem's optimum I/O size as the pagesize if a pagesize
+ * not specified. Some filesystems have 64K as their optimum I/O size,
+ * but as that results in fairly large default caches, we limit the
+ * default pagesize to 16K.
+ */
+ if ((ret = __os_ioinfo(dbenv, name, fhp, NULL, NULL, &iopsize)) != 0) {
+ __db_err(dbenv, "%s: %s", name, db_strerror(ret));
+ return (ret);
+ }
+ if (iopsize < 512)
+ iopsize = 512;
+ if (iopsize > 16 * 1024)
+ iopsize = 16 * 1024;
+
+ /*
+ * Sheer paranoia, but we don't want anything that's not a power-of-2
+ * (we rely on that for alignment of various types on the pages), and
+ * we want a multiple of the sector size as well. If the value
+ * we got out of __os_ioinfo looks bad, use a default instead.
+ */
+ if (!IS_VALID_PAGESIZE(iopsize))
+ iopsize = DB_DEF_IOSIZE;
+
+ dbp->pgsize = iopsize;
+ F_SET(dbp, DB_AM_PGDEF);
+
+ return (0);
+}
+
+/*
+ * __fop_subdb_setup --
+ *
+ * Subdb setup is significantly simpler than file setup. In terms of
+ * locking, for the duration of the operation/transaction, the locks on
+ * the meta-data page will suffice to protect us from simultaneous operations
+ * on the sub-database. Before we complete the operation though, we'll get a
+ * handle lock on the subdatabase so that on one else can try to remove it
+ * while we've got it open. We use an object that looks like the meta-data
+ * page lock with a different type (DB_HANDLE_LOCK) for the long-term handle.
+ * locks.
+ *
+ * PUBLIC: int __fop_subdb_setup __P((DB *, DB_TXN *,
+ * PUBLIC: const char *, const char *, int, u_int32_t));
+ */
+int
+__fop_subdb_setup(dbp, txn, mname, name, mode, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *mname, *name;
+ int mode;
+ u_int32_t flags;
+{
+ DB *mdbp;
+ DB_ENV *dbenv;
+ int do_remove, ret;
+
+ mdbp = NULL;
+ dbenv = dbp->dbenv;
+
+ if ((ret = __db_master_open(dbp, txn, mname, flags, mode, &mdbp)) != 0)
+ return (ret);
+
+ /*
+ * We are going to close this instance of the master, so we can
+ * steal its handle instead of reopening a handle on the database.
+ */
+ if (LF_ISSET(DB_FCNTL_LOCKING)) {
+ dbp->saved_open_fhp = mdbp->saved_open_fhp;
+ mdbp->saved_open_fhp = NULL;
+ }
+
+ /* Now copy the pagesize. */
+ dbp->pgsize = mdbp->pgsize;
+ F_SET(dbp, DB_AM_SUBDB);
+
+ if (name != NULL && (ret = __db_master_update(mdbp, dbp, txn,
+ name, dbp->type, MU_OPEN, NULL, flags)) != 0)
+ goto err;
+
+ /*
+ * Hijack the master's locker ID as well, so that our locks don't
+ * conflict with the master's. Since we're closing the master,
+ * that lid would just have been freed anyway. Once we've gotten
+ * the locker id, we need to acquire the handle lock for this
+ * subdatabase.
+ */
+ dbp->lid = mdbp->lid;
+ mdbp->lid = DB_LOCK_INVALIDID;
+
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOG, ret, mname);
+
+ /*
+ * We copy our fileid from our master so that we all open
+ * the same file in mpool. We'll use the meta-pgno to lock
+ * so that we end up with different handle locks.
+ */
+
+ memcpy(dbp->fileid, mdbp->fileid, DB_FILE_ID_LEN);
+ if ((ret = __fop_lock_handle(dbenv, dbp,
+ txn == NULL ? dbp->lid : txn->txnid,
+ F_ISSET(dbp, DB_AM_CREATED) || LF_ISSET(DB_WRITEOPEN) ?
+ DB_LOCK_WRITE : DB_LOCK_READ, NULL, 0)) != 0)
+ goto err;
+
+ if ((ret = __db_init_subdb(mdbp, dbp, name, txn)) != 0)
+ goto err;
+
+ /*
+ * In the file create case, these happen in separate places so we have
+ * two different tests. They end up in the same place for subdbs, but
+ * for compatibility with file testing, we put them both here anyway.
+ */
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, mname);
+ DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, mname);
+
+ /*
+ * File exists and we have the appropriate locks; we should now
+ * process a normal open.
+ */
+ if (F_ISSET(mdbp, DB_AM_CREATED)) {
+ F_SET(dbp, DB_AM_CREATED_MSTR);
+ F_CLR(mdbp, DB_AM_DISCARD);
+ }
+
+ /*
+ * The master's handle lock is under the control of the
+ * subdb (it acquired the master's locker. We want to
+ * keep the master's handle lock so that no one can remove
+ * the file while the subdb is open. If we register the
+ * trade event and then invalidate the copy of the lock
+ * in the master's handle, that will accomplish this. However,
+ * before we register this event, we'd better remove any
+ * events that we've already registered for the master.
+ */
+
+ if (!F_ISSET(dbp, DB_AM_RECOVER) && txn != NULL) {
+ /* Unregister old master events. */
+ __txn_remlock(dbenv,
+ txn, &mdbp->handle_lock, DB_LOCK_INVALIDID);
+
+ /* Now register the new event. */
+ if ((ret = __txn_lockevent(dbenv,
+ txn, dbp, &mdbp->handle_lock, dbp->lid)) != 0)
+ goto err;
+ }
+ LOCK_INIT(mdbp->handle_lock);
+ return (__db_close_i(mdbp, txn, 0));
+
+err:
+DB_TEST_RECOVERY_LABEL
+ if (LOCK_ISSET(dbp->handle_lock) && txn == NULL)
+ __lock_put(dbenv, &dbp->handle_lock);
+
+ /* If we created the master file then we need to remove it. */
+ if (mdbp != NULL) {
+ do_remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0;
+ if (do_remove)
+ F_SET(mdbp, DB_AM_DISCARD);
+ (void)__db_close_i(mdbp, txn, 0);
+ if (do_remove) {
+ (void)db_create(&mdbp, dbp->dbenv, 0);
+ (void)__db_remove_i(mdbp, txn, mname, NULL);
+ }
+ }
+ return (ret);
+}
+
+/*
+ * __fop_remove_setup --
+ * Open handle appropriately and lock for removal of a database file.
+ *
+ * PUBLIC: int __fop_remove_setup __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, u_int32_t));
+ */
+int
+__fop_remove_setup(dbp, txn, name, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ DB_LOCK elock;
+ u_int8_t mbuf[DBMETASIZE];
+ int ret;
+
+ COMPQUIET(flags, 0);
+ dbenv = dbp->dbenv;
+ PANIC_CHECK(dbenv);
+ LOCK_INIT(elock);
+
+ /* Create locker if necessary. */
+ if (LOCKING_ON(dbenv)) {
+ if (txn != NULL)
+ dbp->lid = txn->txnid;
+ else if (dbp->lid == DB_LOCK_INVALIDID) {
+ if ((ret = __lock_id(dbenv, &dbp->lid)) != 0)
+ goto err;
+ }
+ }
+
+ /*
+ * Lock environment to protect file open. That will enable us to
+ * read the meta-data page and get the fileid so that we can lock
+ * the handle.
+ */
+ GET_ENVLOCK(dbenv, dbp->lid, &elock);
+ if ((ret = __fop_read_meta(dbenv,
+ name, mbuf, sizeof(mbuf), NULL, 0, 0)) != 0)
+ goto err;
+
+ if ((ret =
+ __db_meta_setup(dbenv, dbp, name, (DBMETA *)mbuf, flags, 1)) != 0)
+ goto err;
+
+ /* Now, release the environment and get the handle lock. */
+ if ((ret = __fop_lock_handle(dbenv,
+ dbp, dbp->lid, DB_LOCK_WRITE, &elock, 0)) != 0)
+ goto err;
+
+ return (0);
+
+err: (void)REL_ENVLOCK(dbenv, &elock);
+ return (ret);
+}
+
+/*
+ * __fop_read_meta --
+ * Read the meta-data page from a file and return it in buf. The
+ * open file handle is returned in fhp.
+ *
+ * PUBLIC: int __fop_read_meta __P((DB_ENV *,
+ * PUBLIC: const char *, u_int8_t *, size_t, DB_FH *, int, u_int32_t));
+ */
+int
+__fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
+ DB_ENV *dbenv;
+ const char *name;
+ u_int8_t *buf;
+ size_t size;
+ DB_FH *fhp;
+ int errok;
+ u_int32_t flags;
+{
+ DB_FH fh, *lfhp;
+ size_t nr;
+ int ret;
+
+ lfhp = fhp == NULL ? &fh : fhp;
+ memset(lfhp, 0, sizeof(*fhp));
+ if ((ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0)
+ goto err;
+ if ((ret = __os_read(dbenv, lfhp, buf, size, &nr)) != 0) {
+ if (!errok)
+ __db_err(dbenv, "%s: %s", name, db_strerror(ret));
+ goto err;
+ }
+
+ if (nr != size) {
+ if (!errok)
+ __db_err(dbenv,
+ "%s: unexpected file type or format", name);
+ ret = EINVAL;
+ goto err;
+ }
+
+err: /*
+ * On error, we always close the handle. If there is no error,
+ * then we only return the handle if the user didn't pass us
+ * a handle into which to return it. If fhp is valid, then
+ * lfhp is the same as fhp.
+ */
+ if (F_ISSET(lfhp, DB_FH_VALID) && (ret != 0 || fhp == NULL))
+ __os_closehandle(dbenv, lfhp);
+ return (ret);
+}
+
+/*
+ * __fop_dummy --
+ * This implements the creation and name swapping of dummy files that
+ * we use for remove and rename (remove is simply a rename with a delayed
+ * remove).
+ *
+ * PUBLIC: int __fop_dummy __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t));
+ */
+int
+__fop_dummy(dbp, txn, old, new, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *old, *new;
+ u_int32_t flags;
+{
+ DB *tmpdbp;
+ DB_ENV *dbenv;
+ DB_LOCK elock;
+ DB_LSN lsn;
+ DBT fiddbt, namedbt, tmpdbt;
+ DB_TXN *stxn;
+ char *back;
+ char *realback, *realnew, *realold;
+ int ret, t_ret;
+ u_int8_t mbuf[DBMETASIZE];
+ u_int32_t locker, stxnid;
+
+ dbenv = dbp->dbenv;
+ LOCK_INIT(elock);
+ realback = NULL;
+ realnew = NULL;
+ realold = NULL;
+ back = NULL;
+ stxn = NULL;
+ tmpdbp = NULL;
+
+ DB_ASSERT(txn != NULL);
+ locker = txn->txnid;
+
+ /* Begin sub transaction to encapsulate the rename. */
+ if (TXN_ON(dbenv) &&
+ (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0)
+ goto err;
+
+ /* We need to create a dummy file as a place holder. */
+ if ((ret = __db_backup_name(dbenv, new, stxn, &back)) != 0)
+ goto err;
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, back, flags, NULL, &realback)) != 0)
+ goto err;
+ if ((ret = __fop_create(dbenv, stxn, NULL, back, DB_APP_DATA, 0)) != 0)
+ goto err;
+
+ memset(mbuf, 0, sizeof(mbuf));
+ if ((ret =
+ __os_fileid(dbenv, realback, 1, ((DBMETA *)mbuf)->uid)) != 0)
+ goto err;
+ ((DBMETA *)mbuf)->magic = DB_RENAMEMAGIC;
+ if ((ret = __fop_write(dbenv,
+ stxn, back, DB_APP_DATA, NULL, 0, mbuf, DBMETASIZE, 1)) != 0)
+ goto err;
+
+ /* Create a dummy dbp handle. */
+ if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
+ goto err;
+ memcpy(&tmpdbp->fileid, ((DBMETA *)mbuf)->uid, DB_FILE_ID_LEN);
+
+ /* Now, lock the name space while we initialize this file. */
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, new, 0, NULL, &realnew)) != 0)
+ goto err;
+ GET_ENVLOCK(dbenv, locker, &elock);
+ if (__os_exists(realnew, NULL) == 0) {
+ ret = EEXIST;
+ goto err;
+ }
+
+ /*
+ * While we have the namespace locked, do the renames and then
+ * swap for the handle lock.
+ */
+ if ((ret = __fop_rename(dbenv,
+ stxn, old, new, dbp->fileid, DB_APP_DATA)) != 0)
+ goto err;
+ if ((ret = __fop_rename(dbenv,
+ stxn, back, old, tmpdbp->fileid, DB_APP_DATA)) != 0)
+ goto err;
+ if ((ret = __fop_lock_handle(dbenv,
+ tmpdbp, locker, DB_LOCK_WRITE, &elock, 0)) != 0)
+ goto err;
+
+ /*
+ * We just acquired a transactional lock on the tmp handle.
+ * We need to null out the tmp handle's lock so that it
+ * doesn't create problems for us in the close path.
+ */
+ LOCK_INIT(tmpdbp->handle_lock);
+
+ if (stxn != NULL) {
+ /* Commit the child. */
+ stxnid = stxn->txnid;
+ ret = stxn->commit(stxn, 0);
+ stxn = NULL;
+
+ /* Now log the child information in the parent. */
+ memset(&fiddbt, 0, sizeof(fiddbt));
+ memset(&tmpdbt, 0, sizeof(fiddbt));
+ memset(&namedbt, 0, sizeof(namedbt));
+ fiddbt.data = dbp->fileid;
+ fiddbt.size = DB_FILE_ID_LEN;
+ tmpdbt.data = tmpdbp->fileid;
+ tmpdbt.size = DB_FILE_ID_LEN;
+ namedbt.data = (void *)old;
+ namedbt.size = (u_int32_t)strlen(old) + 1;
+ if ((t_ret =
+ __fop_file_remove_log(dbenv, txn, &lsn, 0, &fiddbt,
+ &tmpdbt, &namedbt, DB_APP_DATA, stxnid)) != 0 && ret == 0)
+ ret = t_ret;
+ }
+
+ /* This is a delayed delete of the dummy file. */
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, old, flags, NULL, &realold)) != 0)
+ goto err;
+ if ((ret = __txn_remevent(dbenv, txn, realold, NULL)) != 0)
+ goto err;
+
+err: (void)REL_ENVLOCK(dbenv, &elock);
+ if (stxn != NULL)
+ (void)stxn->abort(stxn);
+ if (tmpdbp != NULL &&
+ (t_ret = __db_close_i(tmpdbp, NULL, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (realold != NULL)
+ __os_free(dbenv, realold);
+ if (realnew != NULL)
+ __os_free(dbenv, realnew);
+ if (realback != NULL)
+ __os_free(dbenv, realback);
+ if (back != NULL)
+ __os_free(dbenv, back);
+ return (ret);
+}
+
+/*
+ * __fop_dbrename --
+ * Do the appropriate file locking and file system operations
+ * to effect a dbrename in the absence of transactions (__fop_dummy
+ * and the subsequent calls in __db_rename do the work for the
+ * transactional case).
+ *
+ * PUBLIC: int __fop_dbrename __P((DB *, const char *, const char *));
+ */
+int
+__fop_dbrename(dbp, old, new)
+ DB *dbp;
+ const char *old, *new;
+{
+ DB_ENV *dbenv;
+ DB_LOCK elock;
+ char *real_new, *real_old;
+ int ret, tret;
+
+ dbenv = dbp->dbenv;
+ real_new = NULL;
+ real_old = NULL;
+ LOCK_INIT(elock);
+
+ /* Find the real newname of the file. */
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, new, 0, NULL, &real_new)) != 0)
+ goto err;
+
+ /*
+ * It is an error to rename a file over one that already exists,
+ * as that wouldn't be transaction-safe.
+ */
+ GET_ENVLOCK(dbenv, dbp->lid, &elock);
+ if (__os_exists(real_new, NULL) == 0) {
+ ret = EEXIST;
+ __db_err(dbenv, "rename: file %s exists", real_new);
+ goto err;
+ }
+
+ if ((ret = __db_appname(dbenv,
+ DB_APP_DATA, old, 0, NULL, &real_old)) != 0)
+ goto err;
+
+ ret = dbenv->memp_nameop(dbenv, dbp->fileid, new, real_old, real_new);
+
+err: if ((tret = REL_ENVLOCK(dbenv, &elock)) != 0 && ret == 0)
+ ret = tret;
+ if (real_old != NULL)
+ __os_free(dbenv, real_old);
+ if (real_new != NULL)
+ __os_free(dbenv, real_new);
+ return (ret);
+}
diff --git a/bdb/hash/hash.c b/bdb/hash/hash.c
index e96fd4898f0..2f972a3238d 100644
--- a/bdb/hash/hash.c
+++ b/bdb/hash/hash.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash.c,v 11.94 2001/01/03 16:42:26 ubell Exp $";
+static const char revid[] = "$Id: hash.c,v 11.166 2002/08/06 06:11:25 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -54,446 +54,70 @@ static const char revid[] = "$Id: hash.c,v 11.94 2001/01/03 16:42:26 ubell Exp $
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "db_ext.h"
-#include "db_shash.h"
-#include "db_swap.h"
-#include "hash.h"
-#include "btree.h"
-#include "log.h"
-#include "lock.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+static int __ham_bulk __P((DBC *, DBT *, u_int32_t));
static int __ham_c_close __P((DBC *, db_pgno_t, int *));
static int __ham_c_del __P((DBC *));
static int __ham_c_destroy __P((DBC *));
static int __ham_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __ham_c_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __ham_c_writelock __P((DBC *));
-static int __ham_del_dups __P((DBC *, DBT *));
-static int __ham_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
static int __ham_dup_return __P((DBC *, DBT *, u_int32_t));
static int __ham_expand_table __P((DBC *));
-static int __ham_init_htab __P((DBC *,
- const char *, db_pgno_t, u_int32_t, u_int32_t));
static int __ham_lookup __P((DBC *,
const DBT *, u_int32_t, db_lockmode_t, db_pgno_t *));
static int __ham_overwrite __P((DBC *, DBT *, u_int32_t));
/*
- * __ham_metachk --
+ * __ham_quick_delete --
+ * When performing a DB->del operation that does not involve secondary
+ * indices and is not removing an off-page duplicate tree, we can
+ * speed things up substantially by removing the entire duplicate
+ * set, if any is present, in one operation, rather than by conjuring
+ * up and deleting each of the items individually. (All are stored
+ * in one big HKEYDATA structure.) We don't bother to distinguish
+ * on-page duplicate sets from single, non-dup items; they're deleted
+ * in exactly the same way.
*
- * PUBLIC: int __ham_metachk __P((DB *, const char *, HMETA *));
- */
-int
-__ham_metachk(dbp, name, hashm)
- DB *dbp;
- const char *name;
- HMETA *hashm;
-{
- DB_ENV *dbenv;
- u_int32_t vers;
- int ret;
-
- dbenv = dbp->dbenv;
-
- /*
- * At this point, all we know is that the magic number is for a Hash.
- * Check the version, the database may be out of date.
- */
- vers = hashm->dbmeta.version;
- if (F_ISSET(dbp, DB_AM_SWAP))
- M_32_SWAP(vers);
- switch (vers) {
- case 4:
- case 5:
- case 6:
- __db_err(dbenv,
- "%s: hash version %lu requires a version upgrade",
- name, (u_long)vers);
- return (DB_OLD_VERSION);
- case 7:
- break;
- default:
- __db_err(dbenv,
- "%s: unsupported hash version: %lu", name, (u_long)vers);
- return (EINVAL);
- }
-
- /* Swap the page if we need to. */
- if (F_ISSET(dbp, DB_AM_SWAP) && (ret = __ham_mswap((PAGE *)hashm)) != 0)
- return (ret);
-
- /* Check the type. */
- if (dbp->type != DB_HASH && dbp->type != DB_UNKNOWN)
- return (EINVAL);
- dbp->type = DB_HASH;
- DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
-
- /*
- * Check application info against metadata info, and set info, flags,
- * and type based on metadata info.
- */
- if ((ret = __db_fchk(dbenv,
- "DB->open", hashm->dbmeta.flags,
- DB_HASH_DUP | DB_HASH_SUBDB | DB_HASH_DUPSORT)) != 0)
- return (ret);
-
- if (F_ISSET(&hashm->dbmeta, DB_HASH_DUP))
- F_SET(dbp, DB_AM_DUP);
- else
- if (F_ISSET(dbp, DB_AM_DUP)) {
- __db_err(dbenv,
- "%s: DB_DUP specified to open method but not set in database",
- name);
- return (EINVAL);
- }
-
- if (F_ISSET(&hashm->dbmeta, DB_HASH_SUBDB))
- F_SET(dbp, DB_AM_SUBDB);
- else
- if (F_ISSET(dbp, DB_AM_SUBDB)) {
- __db_err(dbenv,
- "%s: multiple databases specified but not supported in file",
- name);
- return (EINVAL);
- }
-
- if (F_ISSET(&hashm->dbmeta, DB_HASH_DUPSORT)) {
- if (dbp->dup_compare == NULL)
- dbp->dup_compare = __bam_defcmp;
- } else
- if (dbp->dup_compare != NULL) {
- __db_err(dbenv,
- "%s: duplicate sort function specified but not set in database",
- name);
- return (EINVAL);
- }
-
- /* Set the page size. */
- dbp->pgsize = hashm->dbmeta.pagesize;
-
- /* Copy the file's ID. */
- memcpy(dbp->fileid, hashm->dbmeta.uid, DB_FILE_ID_LEN);
-
- return (0);
-}
-
-/*
- * __ham_open --
+ * This function is called by __db_delete when the appropriate
+ * conditions are met, and it performs the delete in the optimized way.
*
- * PUBLIC: int __ham_open __P((DB *, const char *, db_pgno_t, u_int32_t));
+ * The cursor should be set to the first item in the duplicate
+ * set, or to the sole key/data pair when the key does not have a
+ * duplicate set, before the function is called.
+ *
+ * PUBLIC: int __ham_quick_delete __P((DBC *));
*/
int
-__ham_open(dbp, name, base_pgno, flags)
- DB *dbp;
- const char *name;
- db_pgno_t base_pgno;
- u_int32_t flags;
-{
- DB_ENV *dbenv;
- DBC *dbc;
- HASH_CURSOR *hcp;
- HASH *hashp;
- int need_sync, ret, t_ret;
-
- dbc = NULL;
- dbenv = dbp->dbenv;
- need_sync = 0;
-
- /* Initialize the remaining fields/methods of the DB. */
- dbp->del = __ham_delete;
- dbp->stat = __ham_stat;
-
- /*
- * Get a cursor. If DB_CREATE is specified, we may be creating
- * pages, and to do that safely in CDB we need a write cursor.
- * In STD_LOCKING mode, we'll synchronize using the meta page
- * lock instead.
- */
- if ((ret = dbp->cursor(dbp,
- dbp->open_txn, &dbc, LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?
- DB_WRITECURSOR : 0)) != 0)
- return (ret);
-
- hcp = (HASH_CURSOR *)dbc->internal;
- hashp = dbp->h_internal;
- hashp->meta_pgno = base_pgno;
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto err1;
-
- /*
- * If this is a new file, initialize it, and put it back dirty.
- *
- * Initialize the hdr structure.
- */
- if (hcp->hdr->dbmeta.magic == DB_HASHMAGIC) {
- /* File exists, verify the data in the header. */
- if (hashp->h_hash == NULL)
- hashp->h_hash = hcp->hdr->dbmeta.version < 5
- ? __ham_func4 : __ham_func5;
- if (!F_ISSET(dbp, DB_RDONLY) &&
- hashp->h_hash(dbp,
- CHARKEY, sizeof(CHARKEY)) != hcp->hdr->h_charkey) {
- __db_err(dbp->dbenv,
- "hash: incompatible hash function");
- ret = EINVAL;
- goto err2;
- }
- if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_DUP))
- F_SET(dbp, DB_AM_DUP);
- if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_DUPSORT))
- F_SET(dbp, DB_AM_DUPSORT);
- if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_SUBDB))
- F_SET(dbp, DB_AM_SUBDB);
- } else if (!IS_RECOVERING(dbenv)) {
- /*
- * File does not exist, we must initialize the header. If
- * locking is enabled that means getting a write lock first.
- * During recovery the meta page will be in the log.
- */
- dbc->lock.pgno = base_pgno;
-
- if (STD_LOCKING(dbc) &&
- ((ret = lock_put(dbenv, &hcp->hlock)) != 0 ||
- (ret = lock_get(dbenv, dbc->locker,
- DB_NONBLOCK(dbc) ? DB_LOCK_NOWAIT : 0,
- &dbc->lock_dbt, DB_LOCK_WRITE, &hcp->hlock)) != 0))
- goto err2;
- else if (CDB_LOCKING(dbp->dbenv)) {
- DB_ASSERT(LF_ISSET(DB_CREATE));
- if ((ret = lock_get(dbenv, dbc->locker,
- DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE,
- &dbc->mylock)) != 0)
- goto err2;
- }
- if ((ret = __ham_init_htab(dbc, name,
- base_pgno, hashp->h_nelem, hashp->h_ffactor)) != 0)
- goto err2;
-
- need_sync = 1;
- }
-
-err2: /* Release the meta data page */
- if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
- ret = t_ret;
-err1: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
-
- /* Sync the file so that we know that the meta data goes to disk. */
- if (ret == 0 && need_sync)
- ret = dbp->sync(dbp, 0);
-#if CONFIG_TEST
- if (ret == 0)
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name);
-
-DB_TEST_RECOVERY_LABEL
-#endif
- if (ret != 0)
- (void)__ham_db_close(dbp);
-
- return (ret);
-}
-
-/************************** LOCAL CREATION ROUTINES **********************/
-/*
- * Returns 0 on No Error
- */
-static int
-__ham_init_htab(dbc, name, pgno, nelem, ffactor)
+__ham_quick_delete(dbc)
DBC *dbc;
- const char *name;
- db_pgno_t pgno;
- u_int32_t nelem, ffactor;
{
- DB *dbp;
- DB_LOCK metalock;
- DB_LSN orig_lsn;
- DBMETA *mmeta;
- HASH_CURSOR *hcp;
- HASH *hashp;
- PAGE *h;
- db_pgno_t mpgno;
- int32_t l2, nbuckets;
- int dirty_mmeta, i, ret, t_ret;
-
- hcp = (HASH_CURSOR *)dbc->internal;
- dbp = dbc->dbp;
- hashp = dbp->h_internal;
- mmeta = NULL;
- h = NULL;
- ret = 0;
- dirty_mmeta = 0;
- metalock.off = LOCK_INVALID;
-
- if (hashp->h_hash == NULL)
- hashp->h_hash = DB_HASHVERSION < 5 ? __ham_func4 : __ham_func5;
-
- if (nelem != 0 && ffactor != 0) {
- nelem = (nelem - 1) / ffactor + 1;
- l2 = __db_log2(nelem > 2 ? nelem : 2);
- } else
- l2 = 1;
- nbuckets = 1 << l2;
-
- orig_lsn = hcp->hdr->dbmeta.lsn;
- memset(hcp->hdr, 0, sizeof(HMETA));
- ZERO_LSN(hcp->hdr->dbmeta.lsn);
- hcp->hdr->dbmeta.pgno = pgno;
- hcp->hdr->dbmeta.magic = DB_HASHMAGIC;
- hcp->hdr->dbmeta.version = DB_HASHVERSION;
- hcp->hdr->dbmeta.pagesize = dbp->pgsize;
- hcp->hdr->dbmeta.type = P_HASHMETA;
- hcp->hdr->dbmeta.free = PGNO_INVALID;
- hcp->hdr->max_bucket = hcp->hdr->high_mask = nbuckets - 1;
- hcp->hdr->low_mask = (nbuckets >> 1) - 1;
- hcp->hdr->ffactor = ffactor;
- hcp->hdr->h_charkey = hashp->h_hash(dbp, CHARKEY, sizeof(CHARKEY));
- memcpy(hcp->hdr->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
-
- if (F_ISSET(dbp, DB_AM_DUP))
- F_SET(&hcp->hdr->dbmeta, DB_HASH_DUP);
- if (F_ISSET(dbp, DB_AM_SUBDB))
- F_SET(&hcp->hdr->dbmeta, DB_HASH_SUBDB);
- if (dbp->dup_compare != NULL)
- F_SET(&hcp->hdr->dbmeta, DB_HASH_DUPSORT);
-
- if ((ret = memp_fset(dbp->mpf, hcp->hdr, DB_MPOOL_DIRTY)) != 0)
- goto err;
-
- /*
- * Create the first and second buckets pages so that we have the
- * page numbers for them and we can store that page number
- * in the meta-data header (spares[0]).
- */
- hcp->hdr->spares[0] = nbuckets;
- if ((ret = memp_fget(dbp->mpf,
- &hcp->hdr->spares[0], DB_MPOOL_NEW_GROUP, &h)) != 0)
- goto err;
-
- P_INIT(h, dbp->pgsize, hcp->hdr->spares[0], PGNO_INVALID,
- PGNO_INVALID, 0, P_HASH);
-
- /* Fill in the last fields of the meta data page. */
- hcp->hdr->spares[0] -= (nbuckets - 1);
- for (i = 1; i <= l2; i++)
- hcp->hdr->spares[i] = hcp->hdr->spares[0];
- for (; i < NCACHED; i++)
- hcp->hdr->spares[i] = PGNO_INVALID;
-
- /*
- * Before we are about to put any dirty pages, we need to log
- * the meta-data page create.
- */
- ret = __db_log_page(dbp, name, &orig_lsn, pgno, (PAGE *)hcp->hdr);
-
- if (dbp->open_txn != NULL) {
- mmeta = (DBMETA *) hcp->hdr;
- if (F_ISSET(dbp, DB_AM_SUBDB)) {
-
- /*
- * If this is a subdatabase, then we need to
- * get the LSN off the master meta data page
- * because that's where free pages are linked
- * and during recovery we need to access
- * that page and roll it backward/forward
- * correctly with respect to LSN.
- */
- mpgno = PGNO_BASE_MD;
- if ((ret = __db_lget(dbc,
- 0, mpgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
- goto err;
- if ((ret = memp_fget(dbp->mpf,
- &mpgno, 0, (PAGE **)&mmeta)) != 0)
- goto err;
- }
- if ((t_ret = __ham_groupalloc_log(dbp->dbenv,
- dbp->open_txn, &LSN(mmeta), 0, dbp->log_fileid,
- &LSN(mmeta), hcp->hdr->spares[0],
- hcp->hdr->max_bucket + 1, mmeta->free)) != 0 && ret == 0)
- ret = t_ret;
- if (ret == 0) {
- /* need to update real LSN for buffer manager */
- dirty_mmeta = 1;
- }
-
- }
-
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOG, ret, name);
-
-DB_TEST_RECOVERY_LABEL
-err: if (h != NULL &&
- (t_ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0 && ret == 0)
- ret = t_ret;
-
- if (F_ISSET(dbp, DB_AM_SUBDB) && mmeta != NULL)
- if ((t_ret = memp_fput(dbp->mpf, mmeta,
- dirty_mmeta ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
- ret = t_ret;
- if (metalock.off != LOCK_INVALID)
- (void)__TLPUT(dbc, metalock);
-
- return (ret);
-}
-
-static int
-__ham_delete(dbp, txn, key, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- u_int32_t flags;
-{
- DBC *dbc;
- HASH_CURSOR *hcp;
- db_pgno_t pgno;
int ret, t_ret;
- /*
- * This is the only access method routine called directly from
- * the dbp, so we have to do error checking.
- */
-
- PANIC_CHECK(dbp->dbenv);
- DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");
- DB_CHECK_TXN(dbp, txn);
-
- if ((ret =
- __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
- return (ret);
-
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
+ if ((ret = __ham_get_meta(dbc)) != 0)
return (ret);
- DEBUG_LWRITE(dbc, txn, "ham_delete", key, NULL, flags);
+ /* Assert that we're not using secondary indices. */
+ DB_ASSERT(!F_ISSET(dbc->dbp, DB_AM_SECONDARY));
+ /*
+ * We should assert that we're not a primary either, but that
+ * would require grabbing the dbp's mutex, so we don't bother.
+ */
- hcp = (HASH_CURSOR *)dbc->internal;
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto out;
+ /* Assert that we're set, but not to an off-page duplicate. */
+ DB_ASSERT(IS_INITIALIZED(dbc));
+ DB_ASSERT(((HASH_CURSOR *)dbc->internal)->opd == NULL);
- pgno = PGNO_INVALID;
- if ((ret = __ham_lookup(dbc, key, 0, DB_LOCK_WRITE, &pgno)) == 0) {
- if (F_ISSET(hcp, H_OK)) {
- if (pgno == PGNO_INVALID)
- ret = __ham_del_pair(dbc, 1);
- else {
- /* When we close the cursor in __ham_del_dups,
- * that will make the off-page dup tree go
- * go away as well as our current entry. When
- * it updates cursors, ours should get marked
- * as H_DELETED.
- */
- ret = __ham_del_dups(dbc, key);
- }
- } else
- ret = DB_NOTFOUND;
- }
+ ret = __ham_del_pair(dbc, 1);
if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
ret = t_ret;
-out: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
return (ret);
}
@@ -517,8 +141,8 @@ __ham_c_init(dbc)
1, sizeof(struct cursor_t), &new_curs)) != 0)
return (ret);
if ((ret = __os_malloc(dbenv,
- dbc->dbp->pgsize, NULL, &new_curs->split_buf)) != 0) {
- __os_free(new_curs, sizeof(*new_curs));
+ dbc->dbp->pgsize, &new_curs->split_buf)) != 0) {
+ __os_free(dbenv, new_curs);
return (ret);
}
@@ -527,8 +151,10 @@ __ham_c_init(dbc)
dbc->c_count = __db_c_count;
dbc->c_del = __db_c_del;
dbc->c_dup = __db_c_dup;
- dbc->c_get = __db_c_get;
+ dbc->c_get = dbc->c_real_get = __db_c_get;
+ dbc->c_pget = __db_c_pget;
dbc->c_put = __db_c_put;
+ dbc->c_am_bulk = __ham_bulk;
dbc->c_am_close = __ham_c_close;
dbc->c_am_del = __ham_c_del;
dbc->c_am_destroy = __ham_c_destroy;
@@ -551,12 +177,14 @@ __ham_c_close(dbc, root_pgno, rmroot)
db_pgno_t root_pgno;
int *rmroot;
{
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
HKEYDATA *dp;
int doroot, gotmeta, ret, t_ret;
u_int32_t dirty;
COMPQUIET(rmroot, 0);
+ mpf = dbc->dbp->mpf;
dirty = 0;
doroot = gotmeta = ret = 0;
hcp = (HASH_CURSOR *) dbc->internal;
@@ -568,9 +196,14 @@ __ham_c_close(dbc, root_pgno, rmroot)
gotmeta = 1;
if ((ret = __ham_get_cpage(dbc, DB_LOCK_READ)) != 0)
goto out;
- dp = (HKEYDATA *)H_PAIRDATA(hcp->page, hcp->indx);
- DB_ASSERT(HPAGE_PTYPE(dp) == H_OFFDUP);
- memcpy(&root_pgno, HOFFPAGE_PGNO(dp), sizeof(db_pgno_t));
+ dp = (HKEYDATA *)H_PAIRDATA(dbc->dbp, hcp->page, hcp->indx);
+
+ /* If its not a dup we aborted before we changed it. */
+ if (HPAGE_PTYPE(dp) == H_OFFDUP)
+ memcpy(&root_pgno,
+ HOFFPAGE_PGNO(dp), sizeof(db_pgno_t));
+ else
+ root_pgno = PGNO_INVALID;
if ((ret =
hcp->opd->c_am_close(hcp->opd, root_pgno, &doroot)) != 0)
@@ -583,7 +216,7 @@ __ham_c_close(dbc, root_pgno, rmroot)
}
out: if (hcp->page != NULL && (t_ret =
- memp_fput(dbc->dbp->mpf, hcp->page, dirty)) != 0 && ret == 0)
+ mpf->put(mpf, hcp->page, dirty)) != 0 && ret == 0)
ret = t_ret;
if (gotmeta != 0 && (t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
ret = t_ret;
@@ -605,8 +238,8 @@ __ham_c_destroy(dbc)
hcp = (HASH_CURSOR *)dbc->internal;
if (hcp->split_buf != NULL)
- __os_free(hcp->split_buf, dbc->dbp->pgsize);
- __os_free(hcp, sizeof(HASH_CURSOR));
+ __os_free(dbc->dbp->dbenv, hcp->split_buf);
+ __os_free(dbc->dbp->dbenv, hcp);
return (0);
}
@@ -623,6 +256,7 @@ __ham_c_count(dbc, recnop)
db_recno_t *recnop;
{
DB *dbp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
db_indx_t len;
db_recno_t recno;
@@ -630,22 +264,23 @@ __ham_c_count(dbc, recnop)
u_int8_t *p, *pend;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *) dbc->internal;
+ mpf = dbp->mpf;
+ hcp = (HASH_CURSOR *)dbc->internal;
recno = 0;
if ((ret = __ham_get_cpage(dbc, DB_LOCK_READ)) != 0)
return (ret);
- switch (HPAGE_PTYPE(H_PAIRDATA(hcp->page, hcp->indx))) {
+ switch (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))) {
case H_KEYDATA:
case H_OFFPAGE:
recno = 1;
break;
case H_DUPLICATE:
- p = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx));
+ p = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
pend = p +
- LEN_HDATA(hcp->page, dbp->pgsize, hcp->indx);
+ LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);
for (; p < pend; recno++) {
/* p may be odd, so copy rather than just dereffing */
memcpy(&len, p, sizeof(db_indx_t));
@@ -654,14 +289,13 @@ __ham_c_count(dbc, recnop)
break;
default:
- ret = __db_unknown_type(dbp->dbenv, "__ham_c_count",
- HPAGE_PTYPE(H_PAIRDATA(hcp->page, hcp->indx)));
+ ret = __db_pgfmt(dbp->dbenv, hcp->pgno);
goto err;
}
*recnop = recno;
-err: if ((t_ret = memp_fput(dbc->dbp->mpf, hcp->page, 0)) != 0 && ret == 0)
+err: if ((t_ret = mpf->put(mpf, hcp->page, 0)) != 0 && ret == 0)
ret = t_ret;
hcp->page = NULL;
return (ret);
@@ -673,10 +307,12 @@ __ham_c_del(dbc)
{
DB *dbp;
DBT repldbt;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
int ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
if (F_ISSET(hcp, H_DELETED))
@@ -689,12 +325,12 @@ __ham_c_del(dbc)
goto out;
/* Off-page duplicates. */
- if (HPAGE_TYPE(hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP)
+ if (HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP)
goto out;
if (F_ISSET(hcp, H_ISDUP)) { /* On-page duplicate. */
if (hcp->dup_off == 0 &&
- DUP_SIZE(hcp->dup_len) == LEN_HDATA(hcp->page,
+ DUP_SIZE(hcp->dup_len) == LEN_HDATA(dbp, hcp->page,
hcp->hdr->dbmeta.pagesize, hcp->indx))
ret = __ham_del_pair(dbc, 1);
else {
@@ -703,21 +339,25 @@ __ham_c_del(dbc)
repldbt.doff = hcp->dup_off;
repldbt.dlen = DUP_SIZE(hcp->dup_len);
repldbt.size = 0;
- repldbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->page,
+ repldbt.data = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page,
hcp->indx));
- ret = __ham_replpair(dbc, &repldbt, 0);
- hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);
- F_SET(hcp, H_DELETED);
- ret = __ham_c_update(dbc, DUP_SIZE(hcp->dup_len), 0, 1);
+ if ((ret = __ham_replpair(dbc, &repldbt, 0)) == 0) {
+ hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);
+ F_SET(hcp, H_DELETED);
+ ret = __ham_c_update(dbc,
+ DUP_SIZE(hcp->dup_len), 0, 1);
+ }
}
} else /* Not a duplicate */
ret = __ham_del_pair(dbc, 1);
-out: if (ret == 0 && hcp->page != NULL &&
- (t_ret = memp_fput(dbp->mpf, hcp->page, DB_MPOOL_DIRTY)) != 0)
- ret = t_ret;
- hcp->page = NULL;
+out: if (hcp->page != NULL) {
+ if ((t_ret = mpf->put(mpf,
+ hcp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) && ret == 0)
+ ret = t_ret;
+ hcp->page = NULL;
+ }
if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
@@ -760,7 +400,7 @@ __ham_c_dup(orig_dbc, new_dbc)
* holds a lock of the correct type, so if we need a write lock and
* request it, we know that we'll get it.
*/
- if (orig->lock.off == LOCK_INVALID || orig_dbc->txn != NULL)
+ if (!LOCK_ISSET(orig->lock) || orig_dbc->txn != NULL)
return (0);
return (__ham_lock_bucket(new_dbc, DB_LOCK_READ));
@@ -775,12 +415,14 @@ __ham_c_get(dbc, key, data, flags, pgnop)
db_pgno_t *pgnop;
{
DB *dbp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
db_lockmode_t lock_type;
int get_key, ret, t_ret;
hcp = (HASH_CURSOR *)dbc->internal;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
/* Clear OR'd in additional bits so we can check for flag equality. */
if (F_ISSET(dbc, DBC_RMW))
@@ -827,6 +469,7 @@ __ham_c_get(dbc, key, data, flags, pgnop)
case DB_SET:
case DB_SET_RANGE:
case DB_GET_BOTH:
+ case DB_GET_BOTH_RANGE:
ret = __ham_lookup(dbc, key, 0, lock_type, pgnop);
get_key = 0;
break;
@@ -856,11 +499,11 @@ __ham_c_get(dbc, key, data, flags, pgnop)
goto err;
else if (F_ISSET(hcp, H_OK)) {
if (*pgnop == PGNO_INVALID)
- ret = __ham_dup_return (dbc, data, flags);
+ ret = __ham_dup_return(dbc, data, flags);
break;
} else if (!F_ISSET(hcp, H_NOMORE)) {
__db_err(dbp->dbenv,
- "H_NOMORE returned to __ham_c_get");
+ "H_NOMORE returned to __ham_c_get");
ret = EINVAL;
break;
}
@@ -872,7 +515,7 @@ __ham_c_get(dbc, key, data, flags, pgnop)
case DB_LAST:
case DB_PREV:
case DB_PREV_NODUP:
- ret = memp_fput(dbp->mpf, hcp->page, 0);
+ ret = mpf->put(mpf, hcp->page, 0);
hcp->page = NULL;
if (hcp->bucket == 0) {
ret = DB_NOTFOUND;
@@ -890,7 +533,7 @@ __ham_c_get(dbc, key, data, flags, pgnop)
case DB_FIRST:
case DB_NEXT:
case DB_NEXT_NODUP:
- ret = memp_fput(dbp->mpf, hcp->page, 0);
+ ret = mpf->put(mpf, hcp->page, 0);
hcp->page = NULL;
hcp->indx = NDX_INVALID;
hcp->bucket++;
@@ -907,6 +550,7 @@ __ham_c_get(dbc, key, data, flags, pgnop)
break;
case DB_GET_BOTH:
case DB_GET_BOTHC:
+ case DB_GET_BOTH_RANGE:
case DB_NEXT_DUP:
case DB_SET:
case DB_SET_RANGE:
@@ -940,6 +584,382 @@ err: if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
return (ret);
}
+/*
+ * __ham_bulk -- Return bulk data from a hash table.
+ */
+static int
+__ham_bulk(dbc, data, flags)
+ DBC *dbc;
+ DBT *data;
+ u_int32_t flags;
+{
+ DB *dbp;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *cp;
+ PAGE *pg;
+ db_indx_t dup_len, dup_off, dup_tlen, indx, *inp;
+ db_lockmode_t lock_mode;
+ db_pgno_t pgno;
+ int32_t *endp, key_off, *offp, *saveoff;
+ u_int32_t key_size, size, space;
+ u_int8_t *dbuf, *dp, *hk, *np, *tmp;
+ int is_dup, is_key;
+ int need_pg, next_key, no_dup, pagesize, ret, t_ret;
+
+ ret = 0;
+ key_off = 0;
+ dup_len = dup_off = dup_tlen = 0;
+ size = 0;
+ dbp = dbc->dbp;
+ pagesize = dbp->pgsize;
+ mpf = dbp->mpf;
+ cp = (HASH_CURSOR *)dbc->internal;
+ is_key = LF_ISSET(DB_MULTIPLE_KEY) ? 1 : 0;
+ next_key = is_key && LF_ISSET(DB_OPFLAGS_MASK) != DB_NEXT_DUP;
+ no_dup = LF_ISSET(DB_OPFLAGS_MASK) == DB_NEXT_NODUP;
+ dbuf = data->data;
+ np = dp = dbuf;
+
+ /* Keep track of space that is left. There is an termination entry */
+ space = data->ulen;
+ space -= sizeof(*offp);
+
+ /* Build the offset/size table from the end up. */
+ endp = (int32_t *) ((u_int8_t *)dbuf + data->ulen);
+ endp--;
+ offp = endp;
+
+ key_size = 0;
+ lock_mode = F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE: DB_LOCK_READ;
+
+next_pg:
+ need_pg = 1;
+ indx = cp->indx;
+ pg = cp->page;
+ inp = P_INP(dbp, pg);
+
+ do {
+ if (is_key) {
+ hk = H_PAIRKEY(dbp, pg, indx);
+ if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
+ memcpy(&key_size,
+ HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
+ memcpy(&pgno,
+ HOFFPAGE_PGNO(hk), sizeof(db_pgno_t));
+ size = key_size;
+ if (key_size > space)
+ goto get_key_space;
+ if ((ret = __bam_bulk_overflow(
+ dbc, key_size, pgno, np)) != 0)
+ return (ret);
+ space -= key_size;
+ key_off = (int32_t)(np - dbuf);
+ np += key_size;
+ } else {
+ if (need_pg) {
+ dp = np;
+ size = pagesize - HOFFSET(pg);
+ if (space < size) {
+get_key_space:
+ if (offp == endp) {
+ data->size =
+ ALIGN(size +
+ pagesize,
+ sizeof(u_int32_t));
+ return (ENOMEM);
+ }
+ goto back_up;
+ }
+ memcpy(dp,
+ (u_int8_t *)pg + HOFFSET(pg), size);
+ need_pg = 0;
+ space -= size;
+ np += size;
+ }
+ key_size = LEN_HKEY(dbp, pg, pagesize, indx);
+ key_off = (int32_t)(inp[indx] - HOFFSET(pg)
+ + dp - dbuf + SSZA(HKEYDATA, data));
+ }
+ }
+
+ hk = H_PAIRDATA(dbp, pg, indx);
+ switch (HPAGE_PTYPE(hk)) {
+ case H_DUPLICATE:
+ case H_KEYDATA:
+ if (need_pg) {
+ dp = np;
+ size = pagesize - HOFFSET(pg);
+ if (space < size) {
+back_up:
+ if (indx != 0) {
+ indx -= 2;
+ /* XXX
+ * It's not clear that this is
+ * the right way to fix this,
+ * but here goes.
+ * If we are backing up onto a
+ * duplicate, then we need to
+ * position ourselves at the
+ * end of the duplicate set.
+ * We probably need to make
+ * this work for H_OFFDUP too.
+ * It might be worth making a
+ * dummy cursor and calling
+ * __ham_item_prev.
+ */
+ tmp = H_PAIRDATA(dbp, pg, indx);
+ if (HPAGE_PTYPE(tmp) ==
+ H_DUPLICATE) {
+ dup_off = dup_tlen =
+ LEN_HDATA(dbp, pg,
+ pagesize, indx + 1);
+ memcpy(&dup_len,
+ HKEYDATA_DATA(tmp),
+ sizeof(db_indx_t));
+ }
+ goto get_space;
+ }
+ /* indx == 0 */
+ if ((ret = __ham_item_prev(dbc,
+ lock_mode, &pgno)) != 0) {
+ if (ret != DB_NOTFOUND)
+ return (ret);
+ if ((ret = mpf->put(mpf,
+ cp->page, 0)) != 0)
+ return (ret);
+ cp->page = NULL;
+ if (cp->bucket == 0) {
+ cp->indx = indx =
+ NDX_INVALID;
+ goto get_space;
+ }
+ if ((ret =
+ __ham_get_meta(dbc)) != 0)
+ return (ret);
+
+ cp->bucket--;
+ cp->pgno = BUCKET_TO_PAGE(cp,
+ cp->bucket);
+ cp->indx = NDX_INVALID;
+ if ((ret = __ham_release_meta(
+ dbc)) != 0)
+ return (ret);
+ if ((ret = __ham_item_prev(dbc,
+ lock_mode, &pgno)) != 0)
+ return (ret);
+ }
+ indx = cp->indx;
+get_space:
+ /*
+ * See if we put any data in the buffer.
+ */
+ if (offp >= endp ||
+ F_ISSET(dbc, DBC_TRANSIENT)) {
+ data->size = ALIGN(size +
+ data->ulen - space,
+ sizeof(u_int32_t));
+ return (ENOMEM);
+ }
+ /*
+ * Don't continue; we're all out
+ * of space, even though we're
+ * returning success.
+ */
+ next_key = 0;
+ break;
+ }
+ memcpy(dp, (u_int8_t *)pg + HOFFSET(pg), size);
+ need_pg = 0;
+ space -= size;
+ np += size;
+ }
+
+ /*
+ * We're about to crack the offset(s) and length(s)
+ * out of an H_KEYDATA or H_DUPLICATE item.
+ * There are three cases:
+ * 1. We were moved into a duplicate set by
+ * the standard hash cursor code. Respect
+ * the dup_off and dup_tlen we were given.
+ * 2. We stumbled upon a duplicate set while
+ * walking the page on our own. We need to
+ * recognize it as a dup and set dup_off and
+ * dup_tlen.
+ * 3. The current item is not a dup.
+ */
+ if (F_ISSET(cp, H_ISDUP)) {
+ /* Case 1 */
+ is_dup = 1;
+ dup_len = cp->dup_len;
+ dup_off = cp->dup_off;
+ dup_tlen = cp->dup_tlen;
+ } else if (HPAGE_PTYPE(hk) == H_DUPLICATE) {
+ /* Case 2 */
+ is_dup = 1;
+ /*
+ * If we run out of memory and bail,
+ * make sure the fact we're in a dup set
+ * isn't ignored later.
+ */
+ F_SET(cp, H_ISDUP);
+ dup_off = 0;
+ memcpy(&dup_len,
+ HKEYDATA_DATA(hk), sizeof(db_indx_t));
+ dup_tlen = LEN_HDATA(dbp, pg, pagesize, indx);
+ } else
+ /* Case 3 */
+ is_dup = dup_len = dup_off = dup_tlen = 0;
+
+ do {
+ space -= (is_key ? 4 : 2) * sizeof(*offp);
+ size += (is_key ? 4 : 2) * sizeof(*offp);
+ /*
+ * Since space is an unsigned, if we happen
+ * to wrap, then this comparison will turn out
+ * to be true. XXX Wouldn't it be better to
+ * simply check above that space is greater than
+ * the value we're about to subtract???
+ */
+ if (space > data->ulen) {
+ if (!is_dup || dup_off == 0)
+ goto back_up;
+ dup_off -= (db_indx_t)DUP_SIZE(offp[1]);
+ goto get_space;
+ }
+ if (is_key) {
+ *offp-- = key_off;
+ *offp-- = key_size;
+ }
+ if (is_dup) {
+ *offp-- = (int32_t)(
+ inp[indx + 1] - HOFFSET(pg) +
+ dp - dbuf + SSZA(HKEYDATA, data) +
+ dup_off + sizeof(db_indx_t));
+ memcpy(&dup_len,
+ HKEYDATA_DATA(hk) + dup_off,
+ sizeof(db_indx_t));
+ dup_off += DUP_SIZE(dup_len);
+ *offp-- = dup_len;
+ } else {
+ *offp-- = (int32_t)(
+ inp[indx + 1] - HOFFSET(pg) +
+ dp - dbuf + SSZA(HKEYDATA, data));
+ *offp-- = LEN_HDATA(dbp, pg,
+ pagesize, indx);
+ }
+ } while (is_dup && dup_off < dup_tlen && no_dup == 0);
+ F_CLR(cp, H_ISDUP);
+ break;
+ case H_OFFDUP:
+ memcpy(&pgno, HOFFPAGE_PGNO(hk), sizeof(db_pgno_t));
+ space -= 2 * sizeof(*offp);
+ if (space > data->ulen)
+ goto back_up;
+
+ if (is_key) {
+ space -= 2 * sizeof(*offp);
+ if (space > data->ulen)
+ goto back_up;
+ *offp-- = key_off;
+ *offp-- = key_size;
+ }
+ saveoff = offp;
+ if ((ret = __bam_bulk_duplicates(dbc,
+ pgno, dbuf, is_key ? offp + 2 : NULL,
+ &offp, &np, &space, no_dup)) != 0) {
+ if (ret == ENOMEM) {
+ size = space;
+ if (is_key && saveoff == offp) {
+ offp += 2;
+ goto back_up;
+ }
+ goto get_space;
+ }
+ return (ret);
+ }
+ break;
+ case H_OFFPAGE:
+ space -= (is_key ? 4 : 2) * sizeof(*offp);
+ if (space > data->ulen)
+ goto back_up;
+
+ memcpy(&size, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
+ memcpy(&pgno, HOFFPAGE_PGNO(hk), sizeof(db_pgno_t));
+ if (size > space)
+ goto back_up;
+
+ if ((ret =
+ __bam_bulk_overflow(dbc, size, pgno, np)) != 0)
+ return (ret);
+
+ if (is_key) {
+ *offp-- = key_off;
+ *offp-- = key_size;
+ }
+
+ *offp-- = (int32_t)(np - dbuf);
+ *offp-- = size;
+
+ np += size;
+ space -= size;
+ break;
+ }
+ } while (next_key && (indx += 2) < NUM_ENT(pg));
+
+ cp->indx = indx;
+ cp->dup_len = dup_len;
+ cp->dup_off = dup_off;
+ cp->dup_tlen = dup_tlen;
+
+ /* If we are off the page then try to the next page. */
+ if (ret == 0 && next_key && indx >= NUM_ENT(pg)) {
+ if ((ret = __ham_item_next(dbc, lock_mode, &pgno)) == 0)
+ goto next_pg;
+ if (ret != DB_NOTFOUND)
+ return (ret);
+ if ((ret = mpf->put(dbc->dbp->mpf, cp->page, 0)) != 0)
+ return (ret);
+ cp->page = NULL;
+ if ((ret = __ham_get_meta(dbc)) != 0)
+ return (ret);
+
+ cp->bucket++;
+ if (cp->bucket > cp->hdr->max_bucket) {
+ /*
+ * Restore cursor to its previous state. We're past
+ * the last item in the last bucket, so the next
+ * DBC->c_get(DB_NEXT) will return DB_NOTFOUND.
+ */
+ cp->bucket--;
+ ret = DB_NOTFOUND;
+ } else {
+ /*
+ * Start on the next bucket.
+ *
+ * Note that if this new bucket happens to be empty,
+ * but there's another non-empty bucket after it,
+ * we'll return early. This is a rare case, and we
+ * don't guarantee any particular number of keys
+ * returned on each call, so just let the next call
+ * to bulk get move forward by yet another bucket.
+ */
+ cp->pgno = BUCKET_TO_PAGE(cp, cp->bucket);
+ cp->indx = NDX_INVALID;
+ F_CLR(cp, H_ISDUP);
+ ret = __ham_item_next(dbc, lock_mode, &pgno);
+ }
+
+ if ((t_ret = __ham_release_meta(dbc)) != 0)
+ return (t_ret);
+ if (ret == 0)
+ goto next_pg;
+ if (ret != DB_NOTFOUND)
+ return (ret);
+ }
+ *offp = (u_int32_t) -1;
+ return (0);
+}
+
static int
__ham_c_put(dbc, key, data, flags, pgnop)
DBC *dbc;
@@ -949,6 +969,7 @@ __ham_c_put(dbc, key, data, flags, pgnop)
db_pgno_t *pgnop;
{
DB *dbp;
+ DB_MPOOLFILE *mpf;
DBT tmp_val, *myval;
HASH_CURSOR *hcp;
u_int32_t nbytes;
@@ -962,6 +983,7 @@ __ham_c_put(dbc, key, data, flags, pgnop)
COMPQUIET(myval, NULL);
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
if (F_ISSET(hcp, H_DELETED) &&
@@ -984,8 +1006,7 @@ __ham_c_put(dbc, key, data, flags, pgnop)
ret = 0;
if (hcp->seek_found_page != PGNO_INVALID &&
hcp->seek_found_page != hcp->pgno) {
- if ((ret = memp_fput(dbp->mpf, hcp->page, 0))
- != 0)
+ if ((ret = mpf->put(mpf, hcp->page, 0)) != 0)
goto err2;
hcp->page = NULL;
hcp->pgno = hcp->seek_found_page;
@@ -1000,9 +1021,10 @@ __ham_c_put(dbc, key, data, flags, pgnop)
* and then write the new bytes represented by
* val.
*/
- if ((ret = __ham_init_dbt(dbp->dbenv,
- &tmp_val, data->size + data->doff,
- &dbc->rdata.data, &dbc->rdata.ulen)) == 0) {
+ if ((ret = __ham_init_dbt(dbp->dbenv, &tmp_val,
+ data->size + data->doff,
+ &dbc->my_rdata.data,
+ &dbc->my_rdata.ulen)) == 0) {
memset(tmp_val.data, 0, data->doff);
memcpy((u_int8_t *)tmp_val.data +
data->doff, data->data, data->size);
@@ -1038,8 +1060,8 @@ done: if (ret == 0 && F_ISSET(hcp, H_EXPAND)) {
F_CLR(hcp, H_EXPAND);
}
- if (ret == 0 &&
- (t_ret = memp_fset(dbp->mpf, hcp->page, DB_MPOOL_DIRTY)) != 0)
+ if (hcp->page != NULL &&
+ (t_ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
err2: if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
@@ -1058,17 +1080,30 @@ __ham_expand_table(dbc)
DBC *dbc;
{
DB *dbp;
- PAGE *h;
+ DB_LOCK metalock;
+ DB_LSN lsn;
+ DB_MPOOLFILE *mpf;
+ DBMETA *mmeta;
HASH_CURSOR *hcp;
- db_pgno_t pgno;
- u_int32_t old_bucket, new_bucket;
- int ret;
+ PAGE *h;
+ db_pgno_t pgno, mpgno;
+ u_int32_t newalloc, new_bucket, old_bucket;
+ int dirty_meta, got_meta, logn, new_double, ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
if ((ret = __ham_dirty_meta(dbc)) != 0)
return (ret);
+ LOCK_INIT(metalock);
+ mmeta = (DBMETA *) hcp->hdr;
+ mpgno = mmeta->pgno;
+ h = NULL;
+ dirty_meta = 0;
+ got_meta = 0;
+ newalloc = 0;
+
/*
* If the split point is about to increase, make sure that we
* have enough extra pages. The calculation here is weird.
@@ -1078,86 +1113,116 @@ __ham_expand_table(dbc)
* see what the log of one greater than that is; here we have to
* look at the log of max + 2. VERY NASTY STUFF.
*
- * It just got even nastier. With subdatabases, we have to request
- * a chunk of contiguous pages, so we do that here using an
- * undocumented feature of mpool (the MPOOL_NEW_GROUP flag) to
- * give us a number of contiguous pages. Ouch.
+ * We figure out what we need to do, then we log it, then request
+ * the pages from mpool. We don't want to fail after extending
+ * the file.
+ *
+ * If the page we are about to split into has already been allocated,
+ * then we simply need to get it to get its LSN. If it hasn't yet
+ * been allocated, then we know it's LSN (0,0).
*/
- if (hcp->hdr->max_bucket == hcp->hdr->high_mask) {
- /*
- * Ask mpool to give us a set of contiguous page numbers
- * large enough to contain the next doubling.
- *
- * Figure out how many new pages we need. This will return
- * us the last page. We calculate its page number, initialize
- * the page and then write it back to reserve all the pages
- * in between. It is possible that the allocation of new pages
- * has already been done, but the tranaction aborted. Since
- * we don't undo the allocation, check for a valid pgno before
- * doing the allocation.
- */
- pgno = hcp->hdr->max_bucket + 1;
- if (hcp->hdr->spares[__db_log2(pgno) + 1] == PGNO_INVALID)
- /* Allocate a group of pages. */
- ret = memp_fget(dbp->mpf,
- &pgno, DB_MPOOL_NEW_GROUP, &h);
- else {
- /* Just read in the last page of the batch */
- pgno = hcp->hdr->spares[__db_log2(pgno) + 1] +
- hcp->hdr->max_bucket + 1;
- /* Move to the last page of the group. */
- pgno += hcp->hdr->max_bucket;
- ret = memp_fget(dbp->mpf,
- &pgno, DB_MPOOL_CREATE, &h);
- }
- if (ret != 0)
- return (ret);
- P_INIT(h, dbp->pgsize, pgno,
- PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
- pgno -= hcp->hdr->max_bucket;
- } else {
- pgno = BUCKET_TO_PAGE(hcp, hcp->hdr->max_bucket + 1);
+ new_bucket = hcp->hdr->max_bucket + 1;
+ old_bucket = new_bucket & hcp->hdr->low_mask;
+
+ new_double = hcp->hdr->max_bucket == hcp->hdr->high_mask;
+ logn = __db_log2(new_bucket);
+
+ if (!new_double || hcp->hdr->spares[logn + 1] != PGNO_INVALID) {
+ /* Page exists; get it so we can get its LSN */
+ pgno = BUCKET_TO_PAGE(hcp, new_bucket);
if ((ret =
- memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
- return (ret);
+ mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
+ goto err;
+ lsn = h->lsn;
+ } else {
+ /* Get the master meta-data page to do allocation. */
+ if (F_ISSET(dbp, DB_AM_SUBDB)) {
+ mpgno = PGNO_BASE_MD;
+ if ((ret = __db_lget(dbc,
+ 0, mpgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
+ goto err;
+ if ((ret =
+ mpf->get(mpf, &mpgno, 0, (PAGE **)&mmeta)) != 0)
+ goto err;
+ got_meta = 1;
+ }
+ pgno = mmeta->last_pgno + 1;
+ ZERO_LSN(lsn);
+ newalloc = 1;
}
- /* Now we can log the meta-data split. */
- if (DB_LOGGING(dbc)) {
- if ((ret = __ham_metagroup_log(dbp->dbenv,
- dbc->txn, &h->lsn, 0, dbp->log_fileid,
- hcp->hdr->max_bucket, pgno, &hcp->hdr->dbmeta.lsn,
- &h->lsn)) != 0) {
- (void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
- return (ret);
- }
+ /* Log the meta-data split first. */
+ if (DBC_LOGGING(dbc)) {
+ /*
+ * We always log the page number of the first page of
+ * the allocation group. However, the LSN that we log
+ * is either the LSN on the first page (if we did not
+ * do the actual allocation here) or the LSN on the last
+ * page of the unit (if we did do the allocation here).
+ */
+ if ((ret = __ham_metagroup_log(dbp, dbc->txn,
+ &lsn, 0, hcp->hdr->max_bucket, mpgno, &mmeta->lsn,
+ hcp->hdr->dbmeta.pgno, &hcp->hdr->dbmeta.lsn,
+ pgno, &lsn, newalloc)) != 0)
+ goto err;
+ } else
+ LSN_NOT_LOGGED(lsn);
- hcp->hdr->dbmeta.lsn = h->lsn;
- }
+ hcp->hdr->dbmeta.lsn = lsn;
- /* If we allocated some new pages, write out the last page. */
- if ((ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
- return (ret);
+ if (new_double && hcp->hdr->spares[logn + 1] == PGNO_INVALID) {
+ /*
+ * We need to begin a new doubling and we have not allocated
+ * any pages yet. Read the last page in and initialize it to
+ * make the allocation contiguous. The pgno we calculated
+ * above is the first page allocated. The entry in spares is
+ * that page number minus any buckets already allocated (it
+ * simplifies bucket to page transaction). After we've set
+ * that, we calculate the last pgno.
+ */
+
+ hcp->hdr->spares[logn + 1] = pgno - new_bucket;
+ pgno += hcp->hdr->max_bucket;
+ mmeta->last_pgno = pgno;
+ mmeta->lsn = lsn;
+ dirty_meta = DB_MPOOL_DIRTY;
- new_bucket = ++hcp->hdr->max_bucket;
- old_bucket = (hcp->hdr->max_bucket & hcp->hdr->low_mask);
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
+ goto err;
+
+ P_INIT(h, dbp->pgsize,
+ pgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+ }
+
+ /* Write out whatever page we ended up modifying. */
+ h->lsn = lsn;
+ if ((ret = mpf->put(mpf, h, DB_MPOOL_DIRTY)) != 0)
+ goto err;
+ h = NULL;
/*
- * If we started a new doubling, fill in the spares array with
- * the starting page number negatively offset by the bucket number.
+ * Update the meta-data page of this hash database.
*/
- if (new_bucket > hcp->hdr->high_mask) {
- /* Starting a new doubling */
+ hcp->hdr->max_bucket = new_bucket;
+ if (new_double) {
hcp->hdr->low_mask = hcp->hdr->high_mask;
hcp->hdr->high_mask = new_bucket | hcp->hdr->low_mask;
- if (hcp->hdr->spares[__db_log2(new_bucket) + 1] == PGNO_INVALID)
- hcp->hdr->spares[__db_log2(new_bucket) + 1] =
- pgno - new_bucket;
}
/* Relocate records to the new bucket */
- return (__ham_split_page(dbc, old_bucket, new_bucket));
+ ret = __ham_split_page(dbc, old_bucket, new_bucket);
+
+err: if (got_meta)
+ (void)mpf->put(mpf, mmeta, dirty_meta);
+
+ if (LOCK_ISSET(metalock))
+ (void)__TLPUT(dbc, metalock);
+
+ if (h != NULL)
+ (void)mpf->put(mpf, h, 0);
+
+ return (ret);
}
/*
@@ -1191,7 +1256,7 @@ __ham_call_hash(dbc, k, len)
* everything held by the cursor.
*/
static int
-__ham_dup_return (dbc, val, flags)
+__ham_dup_return(dbc, val, flags)
DBC *dbc;
DBT *val;
u_int32_t flags;
@@ -1211,7 +1276,7 @@ __ham_dup_return (dbc, val, flags)
dbp = dbc->dbp;
hcp = (HASH_CURSOR *)dbc->internal;
ndx = H_DATAINDEX(hcp->indx);
- type = HPAGE_TYPE(hcp->page, ndx);
+ type = HPAGE_TYPE(dbp, hcp->page, ndx);
pp = hcp->page;
myval = val;
@@ -1228,8 +1293,8 @@ __ham_dup_return (dbc, val, flags)
DB_ASSERT(type != H_OFFDUP);
/* Case 1 */
- if (type != H_DUPLICATE &&
- flags != DB_GET_BOTH && flags != DB_GET_BOTHC)
+ if (type != H_DUPLICATE && flags != DB_GET_BOTH &&
+ flags != DB_GET_BOTHC && flags != DB_GET_BOTH_RANGE)
return (0);
/*
@@ -1239,11 +1304,11 @@ __ham_dup_return (dbc, val, flags)
*/
if (!F_ISSET(hcp, H_ISDUP) && type == H_DUPLICATE) {
F_SET(hcp, H_ISDUP);
- hcp->dup_tlen = LEN_HDATA(hcp->page,
+ hcp->dup_tlen = LEN_HDATA(dbp, hcp->page,
hcp->hdr->dbmeta.pagesize, hcp->indx);
- hk = H_PAIRDATA(hcp->page, hcp->indx);
- if (flags == DB_LAST
- || flags == DB_PREV || flags == DB_PREV_NODUP) {
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
+ if (flags == DB_LAST ||
+ flags == DB_PREV || flags == DB_PREV_NODUP) {
hcp->dup_off = 0;
do {
memcpy(&len,
@@ -1265,7 +1330,8 @@ __ham_dup_return (dbc, val, flags)
* may need to adjust the cursor before returning data.
* Case 4
*/
- if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC) {
+ if (flags == DB_GET_BOTH ||
+ flags == DB_GET_BOTHC || flags == DB_GET_BOTH_RANGE) {
if (F_ISSET(hcp, H_ISDUP)) {
/*
* If we're doing a join, search forward from the
@@ -1274,7 +1340,7 @@ __ham_dup_return (dbc, val, flags)
if (flags == DB_GET_BOTHC)
F_SET(hcp, H_CONTINUE);
- __ham_dsearch(dbc, val, &off, &cmp);
+ __ham_dsearch(dbc, val, &off, &cmp, flags);
/*
* This flag is set nowhere else and is safe to
@@ -1283,7 +1349,7 @@ __ham_dup_return (dbc, val, flags)
F_CLR(hcp, H_CONTINUE);
hcp->dup_off = off;
} else {
- hk = H_PAIRDATA(hcp->page, hcp->indx);
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
if (((HKEYDATA *)hk)->type == H_OFFPAGE) {
memcpy(&tlen,
HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
@@ -1298,7 +1364,7 @@ __ham_dup_return (dbc, val, flags)
* routines may only look at data and size.
*/
tmp_val.data = HKEYDATA_DATA(hk);
- tmp_val.size = LEN_HDATA(hcp->page,
+ tmp_val.size = LEN_HDATA(dbp, hcp->page,
dbp->pgsize, hcp->indx);
cmp = dbp->dup_compare == NULL ?
__bam_defcmp(dbp, &tmp_val, val) :
@@ -1311,6 +1377,18 @@ __ham_dup_return (dbc, val, flags)
}
/*
+ * If we're doing a bulk get, we don't want to actually return
+ * the data: __ham_bulk will take care of cracking out the
+ * duplicates appropriately.
+ *
+ * The rest of this function calculates partial offsets and
+ * handles the actual __db_ret, so just return if
+ * DB_MULTIPLE(_KEY) is set.
+ */
+ if (F_ISSET(dbc, DBC_MULTIPLE | DBC_MULTIPLE_KEY))
+ return (0);
+
+ /*
* Now, everything is initialized, grab a duplicate if
* necessary.
*/
@@ -1351,8 +1429,8 @@ __ham_dup_return (dbc, val, flags)
* Finally, if we had a duplicate, pp, ndx, and myval should be
* set appropriately.
*/
- if ((ret = __db_ret(dbp, pp, ndx, myval, &dbc->rdata.data,
- &dbc->rdata.ulen)) != 0)
+ if ((ret = __db_ret(dbp, pp, ndx, myval, &dbc->rdata->data,
+ &dbc->rdata->ulen)) != 0)
return (ret);
/*
@@ -1374,6 +1452,7 @@ __ham_overwrite(dbc, nval, flags)
u_int32_t flags;
{
DB *dbp;
+ DB_ENV *dbenv;
HASH_CURSOR *hcp;
DBT *myval, tmp_val, tmp_val2;
void *newrec;
@@ -1383,6 +1462,7 @@ __ham_overwrite(dbc, nval, flags)
int ret;
dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
hcp = (HASH_CURSOR *)dbc->internal;
if (F_ISSET(hcp, H_ISDUP)) {
/*
@@ -1399,7 +1479,7 @@ __ham_overwrite(dbc, nval, flags)
*/
memset(&tmp_val, 0, sizeof(tmp_val));
if ((ret =
- __ham_dup_return (dbc, &tmp_val, DB_CURRENT)) != 0)
+ __ham_dup_return(dbc, &tmp_val, DB_CURRENT)) != 0)
return (ret);
/* Figure out new size. */
@@ -1435,7 +1515,7 @@ __ham_overwrite(dbc, nval, flags)
}
if ((ret = __os_malloc(dbp->dbenv,
- DUP_SIZE(newsize), NULL, &newrec)) != 0)
+ DUP_SIZE(newsize), &newrec)) != 0)
return (ret);
memset(&tmp_val2, 0, sizeof(tmp_val2));
F_SET(&tmp_val2, DB_DBT_PARTIAL);
@@ -1483,8 +1563,7 @@ __ham_overwrite(dbc, nval, flags)
tmp_val2.size = newsize;
if (dbp->dup_compare(
dbp, &tmp_val, &tmp_val2) != 0) {
- (void)__os_free(newrec,
- DUP_SIZE(newsize));
+ (void)__os_free(dbenv, newrec);
return (__db_duperr(dbp, flags));
}
}
@@ -1495,7 +1574,7 @@ __ham_overwrite(dbc, nval, flags)
tmp_val2.dlen = DUP_SIZE(hcp->dup_len);
ret = __ham_replpair(dbc, &tmp_val2, 0);
- (void)__os_free(newrec, DUP_SIZE(newsize));
+ (void)__os_free(dbenv, newrec);
/* Update cursor */
if (ret != 0)
@@ -1520,7 +1599,7 @@ __ham_overwrite(dbc, nval, flags)
/* Make sure we maintain sort order. */
if (dbp->dup_compare != NULL) {
tmp_val2.data =
- HKEYDATA_DATA(H_PAIRDATA(hcp->page,
+ HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page,
hcp->indx)) + hcp->dup_off +
sizeof(db_indx_t);
tmp_val2.size = hcp->dup_len;
@@ -1529,8 +1608,8 @@ __ham_overwrite(dbc, nval, flags)
}
/* Overwriting a complete duplicate. */
if ((ret =
- __ham_make_dup(dbp->dbenv, nval,
- &tmp_val, &dbc->rdata.data, &dbc->rdata.ulen)) != 0)
+ __ham_make_dup(dbp->dbenv, nval, &tmp_val,
+ &dbc->my_rdata.data, &dbc->my_rdata.ulen)) != 0)
return (ret);
/* Now fix what we are replacing. */
tmp_val.doff = hcp->dup_off;
@@ -1541,7 +1620,7 @@ __ham_overwrite(dbc, nval, flags)
hcp->dup_tlen += (nval->size - hcp->dup_len);
else
hcp->dup_tlen -= (hcp->dup_len - nval->size);
- hcp->dup_len = DUP_SIZE(nval->size);
+ hcp->dup_len = (db_indx_t)DUP_SIZE(nval->size);
}
myval = &tmp_val;
} else if (!F_ISSET(nval, DB_DBT_PARTIAL)) {
@@ -1549,12 +1628,12 @@ __ham_overwrite(dbc, nval, flags)
memcpy(&tmp_val, nval, sizeof(*nval));
F_SET(&tmp_val, DB_DBT_PARTIAL);
tmp_val.doff = 0;
- hk = H_PAIRDATA(hcp->page, hcp->indx);
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
if (HPAGE_PTYPE(hk) == H_OFFPAGE)
memcpy(&tmp_val.dlen,
HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
else
- tmp_val.dlen = LEN_HDATA(hcp->page,
+ tmp_val.dlen = LEN_HDATA(dbp, hcp->page,
hcp->hdr->dbmeta.pagesize, hcp->indx);
myval = &tmp_val;
} else
@@ -1601,7 +1680,7 @@ __ham_lookup(dbc, key, sought, mode, pgnop)
hcp->bucket = __ham_call_hash(dbc, (u_int8_t *)key->data, key->size);
hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
- while (1) {
+ for (;;) {
*pgnop = PGNO_INVALID;
if ((ret = __ham_item_next(dbc, mode, pgnop)) != 0)
return (ret);
@@ -1609,7 +1688,7 @@ __ham_lookup(dbc, key, sought, mode, pgnop)
if (F_ISSET(hcp, H_NOMORE))
break;
- hk = H_PAIRKEY(hcp->page, hcp->indx);
+ hk = H_PAIRKEY(dbp, hcp->page, hcp->indx);
switch (HPAGE_PTYPE(hk)) {
case H_OFFPAGE:
memcpy(&tlen, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
@@ -1625,12 +1704,12 @@ __ham_lookup(dbc, key, sought, mode, pgnop)
break;
case H_KEYDATA:
if (key->size ==
- LEN_HKEY(hcp->page, dbp->pgsize, hcp->indx) &&
+ LEN_HKEY(dbp, hcp->page, dbp->pgsize, hcp->indx) &&
memcmp(key->data,
HKEYDATA_DATA(hk), key->size) == 0) {
/* Found the key, check for data type. */
found_key: F_SET(hcp, H_OK);
- dk = H_PAIRDATA(hcp->page, hcp->indx);
+ dk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
if (HPAGE_PTYPE(dk) == H_OFFDUP)
memcpy(pgnop, HOFFDUP_PGNO(dk),
sizeof(db_pgno_t));
@@ -1643,7 +1722,7 @@ found_key: F_SET(hcp, H_OK);
* These are errors because keys are never
* duplicated, only data items are.
*/
- return (__db_pgfmt(dbp, PGNO(hcp->page)));
+ return (__db_pgfmt(dbp->dbenv, PGNO(hcp->page)));
}
}
@@ -1677,7 +1756,7 @@ __ham_init_dbt(dbenv, dbt, size, bufp, sizep)
memset(dbt, 0, sizeof(*dbt));
if (*sizep < size) {
- if ((ret = __os_realloc(dbenv, size, NULL, bufp)) != 0) {
+ if ((ret = __os_realloc(dbenv, size, bufp)) != 0) {
*sizep = 0;
return (ret);
}
@@ -1732,8 +1811,8 @@ __ham_c_update(dbc, len, add, is_dup)
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
/*
- * Calcuate the order of this deleted record.
- * This will be one grater than any cursor that is pointing
+ * Calculate the order of this deleted record.
+ * This will be one greater than any cursor that is pointing
* at this record and already marked as deleted.
*/
order = 0;
@@ -1749,11 +1828,11 @@ __ham_c_update(dbc, len, add, is_dup)
continue;
lcp = (HASH_CURSOR *)cp->internal;
if (F_ISSET(lcp, H_DELETED) &&
- hcp->pgno == lcp->pgno &&
- hcp->indx == lcp->indx &&
- order <= lcp->order &&
- (!is_dup || hcp->dup_off == lcp->dup_off))
- order = lcp->order +1;
+ hcp->pgno == lcp->pgno &&
+ hcp->indx == lcp->indx &&
+ order <= lcp->order &&
+ (!is_dup || hcp->dup_off == lcp->dup_off))
+ order = lcp->order + 1;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
}
@@ -1788,8 +1867,8 @@ __ham_c_update(dbc, len, add, is_dup)
* We are "undeleting" so unmark all
* cursors with the same order.
*/
- if (lcp->indx == hcp->indx
- && F_ISSET(lcp, H_DELETED)) {
+ if (lcp->indx == hcp->indx &&
+ F_ISSET(lcp, H_DELETED)) {
if (lcp->order == hcp->order)
F_CLR(lcp, H_DELETED);
else if (lcp->order >
@@ -1815,12 +1894,13 @@ __ham_c_update(dbc, len, add, is_dup)
} else {
if (lcp->indx > hcp->indx) {
lcp->indx -= 2;
- if (lcp->indx == hcp->indx
- && F_ISSET(lcp, H_DELETED))
+ if (lcp->indx == hcp->indx &&
+ F_ISSET(lcp, H_DELETED))
lcp->order += order;
- } else if (lcp->indx == hcp->indx
- && !F_ISSET(lcp, H_DELETED)) {
+ } else if (lcp->indx == hcp->indx &&
+ !F_ISSET(lcp, H_DELETED)) {
F_SET(lcp, H_DELETED);
+ F_CLR(lcp, H_ISDUP);
lcp->order = order;
}
}
@@ -1833,10 +1913,10 @@ __ham_c_update(dbc, len, add, is_dup)
*/
if (add) {
lcp->dup_tlen += len;
- if (lcp->dup_off == hcp->dup_off
- && F_ISSET(hcp, H_DELETED)
- && F_ISSET(lcp, H_DELETED)) {
- /* Abort of a delete. */
+ if (lcp->dup_off == hcp->dup_off &&
+ F_ISSET(hcp, H_DELETED) &&
+ F_ISSET(lcp, H_DELETED)) {
+ /* Abort of a delete. */
if (lcp->order == hcp->order)
F_CLR(lcp, H_DELETED);
else if (lcp->order >
@@ -1851,8 +1931,9 @@ __ham_c_update(dbc, len, add, is_dup)
lcp->dup_tlen -= len;
if (lcp->dup_off > hcp->dup_off) {
lcp->dup_off -= len;
- if (lcp->dup_off == hcp->dup_off
- && F_ISSET(lcp, H_DELETED))
+ if (lcp->dup_off ==
+ hcp->dup_off &&
+ F_ISSET(lcp, H_DELETED))
lcp->order += order;
} else if (lcp->dup_off ==
hcp->dup_off &&
@@ -1867,10 +1948,9 @@ __ham_c_update(dbc, len, add, is_dup)
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
- if (found != 0 && DB_LOGGING(dbc)) {
- if ((ret = __ham_curadj_log(dbenv,
- my_txn, &lsn, 0, dbp->log_fileid, hcp->pgno,
- hcp->indx, len, hcp->dup_off, add, is_dup, order)) != 0)
+ if (found != 0 && DBC_LOGGING(dbc)) {
+ if ((ret = __ham_curadj_log(dbp, my_txn, &lsn, 0, hcp->pgno,
+ hcp->indx, len, hcp->dup_off, add, is_dup, order)) != 0)
return (ret);
}
@@ -1885,13 +1965,12 @@ __ham_c_update(dbc, len, add, is_dup)
* cursors on a split. The latter is so we can update cursors when we
* move items off page.
*
- * PUBLIC: int __ham_get_clist __P((DB *,
- * PUBLIC: db_pgno_t, u_int32_t, DBC ***));
+ * PUBLIC: int __ham_get_clist __P((DB *, db_pgno_t, u_int32_t, DBC ***));
*/
int
-__ham_get_clist(dbp, bucket, indx, listp)
+__ham_get_clist(dbp, pgno, indx, listp)
DB *dbp;
- db_pgno_t bucket;
+ db_pgno_t pgno;
u_int32_t indx;
DBC ***listp;
{
@@ -1915,18 +1994,20 @@ __ham_get_clist(dbp, bucket, indx, listp)
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
cp = TAILQ_NEXT(cp, links))
- if (cp->dbtype == DB_HASH &&
- ((indx == NDX_INVALID &&
- ((HASH_CURSOR *)(cp->internal))->bucket
- == bucket) || (indx != NDX_INVALID &&
- cp->internal->pgno == bucket &&
- cp->internal->indx == indx))) {
+ /*
+ * We match if cp->pgno matches the specified
+ * pgno, and if either the cp->indx matches
+ * or we weren't given an index.
+ */
+ if (cp->internal->pgno == pgno &&
+ (indx == NDX_INVALID ||
+ cp->internal->indx == indx)) {
if (nused >= nalloc) {
nalloc += 10;
if ((ret = __os_realloc(dbp->dbenv,
nalloc * sizeof(HASH_CURSOR *),
- NULL, listp)) != 0)
- return (ret);
+ listp)) != 0)
+ goto err;
}
(*listp)[nused++] = cp;
}
@@ -1939,74 +2020,25 @@ __ham_get_clist(dbp, bucket, indx, listp)
if (nused >= nalloc) {
nalloc++;
if ((ret = __os_realloc(dbp->dbenv,
- nalloc * sizeof(HASH_CURSOR *), NULL, listp)) != 0)
+ nalloc * sizeof(HASH_CURSOR *), listp)) != 0)
return (ret);
}
(*listp)[nused] = NULL;
}
return (0);
-}
-
-static int
-__ham_del_dups(orig_dbc, key)
- DBC *orig_dbc;
- DBT *key;
-{
- DBC *dbc;
- DBT data, lkey;
- int ret, t_ret;
-
- /* Allocate a cursor. */
- if ((ret = orig_dbc->c_dup(orig_dbc, &dbc, 0)) != 0)
- return (ret);
-
- /*
- * Walk a cursor through the key/data pairs, deleting as we go. Set
- * the DB_DBT_USERMEM flag, as this might be a threaded application
- * and the flags checking will catch us. We don't actually want the
- * keys or data, so request a partial of length 0.
- */
- memset(&lkey, 0, sizeof(lkey));
- F_SET(&lkey, DB_DBT_USERMEM | DB_DBT_PARTIAL);
- memset(&data, 0, sizeof(data));
- F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);
-
- /* Walk through the set of key/data pairs, deleting as we go. */
- if ((ret = dbc->c_get(dbc, key, &data, DB_SET)) != 0) {
- if (ret == DB_NOTFOUND)
- ret = 0;
- goto err;
- }
-
- for (;;) {
- if ((ret = dbc->c_del(dbc, 0)) != 0)
- goto err;
- if ((ret = dbc->c_get(dbc, &lkey, &data, DB_NEXT_DUP)) != 0) {
- if (ret == DB_NOTFOUND) {
- ret = 0;
- break;
- }
- goto err;
- }
- }
-
-err: /*
- * Discard the cursor. This will cause the underlying off-page dup
- * tree to go away as well as the actual entry on the page.
- */
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
-
+err:
+ MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
return (ret);
-
}
static int
__ham_c_writelock(dbc)
DBC *dbc;
{
- HASH_CURSOR *hcp;
+ DB_ENV *dbenv;
DB_LOCK tmp_lock;
+ HASH_CURSOR *hcp;
int ret;
/*
@@ -2017,79 +2049,13 @@ __ham_c_writelock(dbc)
return (0);
hcp = (HASH_CURSOR *)dbc->internal;
- if ((hcp->lock.off == LOCK_INVALID || hcp->lock_mode == DB_LOCK_READ)) {
+ if ((!LOCK_ISSET(hcp->lock) || hcp->lock_mode == DB_LOCK_READ)) {
tmp_lock = hcp->lock;
if ((ret = __ham_lock_bucket(dbc, DB_LOCK_WRITE)) != 0)
return (ret);
- if (tmp_lock.off != LOCK_INVALID &&
- (ret = lock_put(dbc->dbp->dbenv, &tmp_lock)) != 0)
- return (ret);
- }
- return (0);
-}
-
-/*
- * __ham_c_chgpg --
- *
- * Adjust the cursors after moving an item from one page to another.
- * If the old_index is NDX_INVALID, that means that we copied the
- * page wholesale and we're leaving indices intact and just changing
- * the page number.
- *
- * PUBLIC: int __ham_c_chgpg
- * PUBLIC: __P((DBC *, db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
- */
-int
-__ham_c_chgpg(dbc, old_pgno, old_index, new_pgno, new_index)
- DBC *dbc;
- db_pgno_t old_pgno, new_pgno;
- u_int32_t old_index, new_index;
-{
- DB *dbp, *ldbp;
- DB_ENV *dbenv;
- DB_LSN lsn;
- DB_TXN *my_txn;
- DBC *cp;
- HASH_CURSOR *hcp;
- int found, ret;
-
- dbp = dbc->dbp;
- dbenv = dbp->dbenv;
-
- my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL;
- found = 0;
-
- MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
- for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
- ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
- ldbp = LIST_NEXT(ldbp, dblistlinks)) {
- MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
- for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
- cp = TAILQ_NEXT(cp, links)) {
- if (cp == dbc || cp->dbtype != DB_HASH)
- continue;
-
- hcp = (HASH_CURSOR *)cp->internal;
- if (hcp->pgno == old_pgno) {
- if (old_index == NDX_INVALID) {
- hcp->pgno = new_pgno;
- } else if (hcp->indx == old_index) {
- hcp->pgno = new_pgno;
- hcp->indx = new_index;
- } else
- continue;
- if (my_txn != NULL && cp->txn != my_txn)
- found = 1;
- }
- }
- MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
- }
- MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
-
- if (found != 0 && DB_LOGGING(dbc)) {
- if ((ret = __ham_chgpg_log(dbenv,
- my_txn, &lsn, 0, dbp->log_fileid, DB_HAM_CHGPG,
- old_pgno, new_pgno, old_index, new_index)) != 0)
+ dbenv = dbc->dbp->dbenv;
+ if (LOCK_ISSET(tmp_lock) &&
+ (ret = dbenv->lock_put(dbenv, &tmp_lock)) != 0)
return (ret);
}
return (0);
diff --git a/bdb/hash/hash.src b/bdb/hash/hash.src
index e6ecd11c907..b4b633c56e6 100644
--- a/bdb/hash/hash.src
+++ b/bdb/hash/hash.src
@@ -1,8 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
+ *
+ * $Id: hash.src,v 10.38 2002/04/17 19:03:10 krinsky Exp $
*/
/*
* Copyright (c) 1995, 1996
@@ -38,44 +40,10 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $Id: hash.src,v 10.24 2000/12/12 17:41:48 bostic Exp $
- */
-
-/*
- * This is the source file used to create the logging functions for the
- * hash package. Each access method (or set of routines wishing to register
- * record types with the transaction system) should have a file like this.
- * Each type of log record and its parameters is defined. The basic
- * format of a record definition is:
- *
- * BEGIN <RECORD_TYPE>
- * ARG|STRING|POINTER <variable name> <variable type> <printf format>
- * ...
- * END
- * ARG the argument is a simple parameter of the type * specified.
- * DBT the argument is a DBT (db.h) containing a length and pointer.
- * PTR the argument is a pointer to the data type specified; the entire
- * type should be logged.
- *
- * There are a set of shell scripts of the form xxx.sh that generate c
- * code and or h files to process these. (This is probably better done
- * in a single PERL script, but for now, this works.)
- *
- * The DB recovery system requires the following three fields appear in
- * every record, and will assign them to the per-record-type structures
- * as well as making them the first parameters to the appropriate logging
- * call.
- * rectype: record-type, identifies the structure and log/read call
- * txnid: transaction id, a DBT in this implementation
- * prev: the last LSN for this transaction
*/
-/*
- * Use the argument of PREFIX as the prefix for all record types,
- * routines, id numbers, etc.
- */
-PREFIX ham
+PREFIX __ham
+DBPRIVATE
INCLUDE #include "db_config.h"
INCLUDE
@@ -83,16 +51,18 @@ INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "hash.h"
-INCLUDE #include "txn.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/hash.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
@@ -109,8 +79,8 @@ INCLUDE
*/
BEGIN insdel 21
ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
ARG ndx u_int32_t lu
POINTER pagelsn DB_LSN * lu
DBT key DBT s
@@ -129,46 +99,26 @@ END
*/
BEGIN newpage 22
ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG prev_pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCKNZ prev_pgno db_pgno_t lu
POINTER prevlsn DB_LSN * lu
-ARG new_pgno db_pgno_t lu
+WRLOCKNZ new_pgno db_pgno_t lu
POINTER pagelsn DB_LSN * lu
-ARG next_pgno db_pgno_t lu
+WRLOCKNZ next_pgno db_pgno_t lu
POINTER nextlsn DB_LSN * lu
END
/*
- * DEPRECATED in 3.0.
- * Superceded by metagroup which allocates a group of new pages.
- *
- * Splitting requires two types of log messages. The first logs the
- * meta-data of the split.
- *
- * For the meta-data split
- * bucket: max_bucket in table before split
- * ovflpoint: overflow point before split.
- * spares: spares[ovflpoint] before split.
- */
-DEPRECATED splitmeta 23
-ARG fileid int32_t ld
-ARG bucket u_int32_t lu
-ARG ovflpoint u_int32_t lu
-ARG spares u_int32_t lu
-POINTER metalsn DB_LSN * lu
-END
-
-/*
* Splitting requires two types of log messages. The second logs the
* data on the original page. To redo the split, we have to visit the
* new page (pages) and add the items back on the page if they are not
* yet there.
*/
BEGIN splitdata 24
-ARG fileid int32_t ld
+DB fileid int32_t ld
ARG opcode u_int32_t lu
-ARG pgno db_pgno_t lu
-DBT pageimage DBT s
+WRLOCK pgno db_pgno_t lu
+PGDBT pageimage DBT s
POINTER pagelsn DB_LSN * lu
END
@@ -185,8 +135,8 @@ END
* makedup - this was a replacement that made an item a duplicate.
*/
BEGIN replace 25
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
ARG ndx u_int32_t lu
POINTER pagelsn DB_LSN * lu
ARG off int32_t ld
@@ -196,52 +146,6 @@ ARG makedup u_int32_t lu
END
/*
- * DEPRECATED in 3.0.
- * Hash now uses the btree allocation and deletion page routines.
- *
- * HASH-newpgno: is used to record getting/deleting a new page number.
- * This doesn't require much data modification, just modifying the
- * meta-data.
- * pgno is the page being allocated/freed.
- * free_pgno is the next_pgno on the free list.
- * old_type was the type of a page being deallocated.
- * old_pgno was the next page number before the deallocation.
- */
-DEPRECATED newpgno 26
-ARG opcode u_int32_t lu
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-ARG free_pgno db_pgno_t lu
-ARG old_type u_int32_t lu
-ARG old_pgno db_pgno_t lu
-ARG new_type u_int32_t lu
-POINTER pagelsn DB_LSN * lu
-POINTER metalsn DB_LSN * lu
-END
-
-/*
- * DEPRECATED in 3.0.
- * Since we now pre-allocate the contiguous chunk of pages for a doubling,
- * there is no big benefit to pre-allocating a few extra pages. It used
- * to be that the file was only physically as large as the current bucket,
- * so if you were on a doubling of 16K, but were only on the first bucket
- * of that 16K, the file was much shorter than it would be at the end of
- * the doubling, so we didn't want to force overflow pages at the end of the
- * 16K pages. Since we now must allocate the 16K pages (because of sub
- * databases), it's not a big deal to tack extra pages on at the end.
- *
- * ovfl: initialize a set of overflow pages.
- */
-DEPRECATED ovfl 27
-ARG fileid int32_t ld
-ARG start_pgno db_pgno_t lu
-ARG npages u_int32_t lu
-ARG free_pgno db_pgno_t lu
-ARG ovflpoint u_int32_t lu
-POINTER metalsn DB_LSN * lu
-END
-
-/*
* Used when we empty the first page in a bucket and there are pages after
* it. The page after it gets copied into the bucket page (since bucket
* pages have to be in fixed locations).
@@ -252,33 +156,46 @@ END
* nnextlsn: the LSN of nnext_pgno.
*/
BEGIN copypage 28
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
+DB fileid int32_t ld
+WRLOCK pgno db_pgno_t lu
POINTER pagelsn DB_LSN * lu
-ARG next_pgno db_pgno_t lu
+WRLOCK next_pgno db_pgno_t lu
POINTER nextlsn DB_LSN * lu
-ARG nnext_pgno db_pgno_t lu
+WRLOCKNZ nnext_pgno db_pgno_t lu
POINTER nnextlsn DB_LSN * lu
-DBT page DBT s
+PGDBT page DBT s
END
/*
- * This replaces the old splitmeta operation. It behaves largely the same
- * way, but it has enough information so that we can record a group allocation
- * which we do now because of sub databases. The number of pages allocated is
- * always bucket + 1 pgno is the page number of the first newly allocated
- * bucket.
+ * This record logs the meta-data aspects of a split operation. It has enough
+ * information so that we can record both an individual page allocation as well
+ * as a group allocation which we do because in sub databases, the pages in
+ * a hash doubling, must be contiguous. If we do a group allocation, the
+ * number of pages allocated is bucket + 1, pgno is the page number of the
+ * first newly allocated bucket.
+ *
* bucket: Old maximum bucket number.
- * pgno: Page allocated to bucket + 1 (first newly allocated page)
+ * mmpgno: Master meta-data page number (0 if same as mpgno).
+ * mmetalsn: Lsn of the master meta-data page.
+ * mpgno: Meta-data page number.
* metalsn: Lsn of the meta-data page.
- * pagelsn: Lsn of the maximum page allocated.
+ * pgno: Page allocated to bucket + 1 (first newly allocated page)
+ * pagelsn: Lsn of either the first page allocated (if newalloc == 0) or
+ * the last page allocated (if newalloc == 1).
+ * newalloc: 1 indicates that this record did the actual allocation;
+ * 0 indicates that the pages were already allocated from a
+ * previous (failed) allocation.
*/
BEGIN metagroup 29
-ARG fileid int32_t ld
+DB fileid int32_t ld
ARG bucket u_int32_t lu
-ARG pgno db_pgno_t lu
+WRLOCK mmpgno db_pgno_t lu
+POINTER mmetalsn DB_LSN * lu
+WRLOCKNZ mpgno db_pgno_t lu
POINTER metalsn DB_LSN * lu
+WRLOCK pgno db_pgno_t lu
POINTER pagelsn DB_LSN * lu
+ARG newalloc u_int32_t lu
END
/*
@@ -293,28 +210,10 @@ END
* start_pgno: starting page number
* num: number of allocated pages
*/
-DEPRECATED groupalloc1 30
-ARG fileid int32_t ld
-ARG pgno db_pgno_t lu
-POINTER metalsn DB_LSN * lu
-POINTER mmetalsn DB_LSN * lu
-ARG start_pgno db_pgno_t lu
-ARG num u_int32_t lu
-END
-
-DEPRECATED groupalloc2 31
-ARG fileid int32_t ld
-POINTER meta_lsn DB_LSN * lu
-POINTER alloc_lsn DB_LSN * lu
-ARG start_pgno db_pgno_t lu
-ARG num u_int32_t lu
-ARG free db_pgno_t lu
-END
-
BEGIN groupalloc 32
-ARG fileid int32_t ld
+DB fileid int32_t ld
POINTER meta_lsn DB_LSN * lu
-ARG start_pgno db_pgno_t lu
+WRLOCK start_pgno db_pgno_t lu
ARG num u_int32_t lu
ARG free db_pgno_t lu
END
@@ -329,7 +228,7 @@ END
* dup_off - if a dup its offset
* add - 1 if add 0 if delete
* is_dup - 1 if dup 0 otherwise.
- * order - order assinged to this deleted record or dup.
+ * order - order assigned to this deleted record or dup.
*
* chgpg - rmoved a page, move the records to a new page
* mode - CHGPG page was deleted or records move to new page.
@@ -338,9 +237,15 @@ END
* old_pgno, new_pgno - old and new page numbers.
* old_index, new_index - old and new index numbers, NDX_INVALID if
* it effects all records on the page.
+ * For three opcodes new in 3.3 (DB_HAM_DELFIRSTPG, DELMIDPG,
+ * and DELLASTPG), we overload old_indx and new_indx to avoid
+ * needing a new log record type: old_indx stores the only
+ * indx of interest to these records, and new_indx stores the
+ * order that's assigned to the lowest deleted record we're
+ * moving.
*/
BEGIN curadj 33
-ARG fileid int32_t ld
+DB fileid int32_t ld
ARG pgno db_pgno_t lu
ARG indx u_int32_t lu
ARG len u_int32_t lu
@@ -351,7 +256,7 @@ ARG order u_int32_t lu
END
BEGIN chgpg 34
-ARG fileid int32_t ld
+DB fileid int32_t ld
ARG mode db_ham_mode ld
ARG old_pgno db_pgno_t lu
ARG new_pgno db_pgno_t lu
diff --git a/bdb/hash/hash_conv.c b/bdb/hash/hash_conv.c
index 30d17a6164d..a93e56a2ee4 100644
--- a/bdb/hash/hash_conv.c
+++ b/bdb/hash/hash_conv.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_conv.c,v 11.5 2000/03/31 00:30:32 ubell Exp $";
+static const char revid[] = "$Id: hash_conv.c,v 11.13 2002/08/06 05:34:35 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -15,20 +15,21 @@ static const char revid[] = "$Id: hash_conv.c,v 11.5 2000/03/31 00:30:32 ubell E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "hash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/hash.h"
/*
* __ham_pgin --
* Convert host-specific page layout from the host-independent format
* stored on disk.
*
- * PUBLIC: int __ham_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
+ * PUBLIC: int __ham_pgin __P((DB_ENV *, DB *, db_pgno_t, void *, DBT *));
*/
int
-__ham_pgin(dbenv, pg, pp, cookie)
+__ham_pgin(dbenv, dummydbp, pg, pp, cookie)
DB_ENV *dbenv;
+ DB *dummydbp;
db_pgno_t pg;
void *pp;
DBT *cookie;
@@ -45,16 +46,16 @@ __ham_pgin(dbenv, pg, pp, cookie)
* initialize the rest of the page and return.
*/
if (h->type != P_HASHMETA && h->pgno == PGNO_INVALID) {
- P_INIT(pp, pginfo->db_pagesize,
+ P_INIT(pp, (db_indx_t)pginfo->db_pagesize,
pg, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
return (0);
}
- if (!pginfo->needswap)
+ if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
return (h->type == P_HASHMETA ? __ham_mswap(pp) :
- __db_byteswap(dbenv, pg, pp, pginfo->db_pagesize, 1));
+ __db_byteswap(dbenv, dummydbp, pg, pp, pginfo->db_pagesize, 1));
}
/*
@@ -62,11 +63,12 @@ __ham_pgin(dbenv, pg, pp, cookie)
* Convert host-specific page layout to the host-independent format
* stored on disk.
*
- * PUBLIC: int __ham_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
+ * PUBLIC: int __ham_pgout __P((DB_ENV *, DB *, db_pgno_t, void *, DBT *));
*/
int
-__ham_pgout(dbenv, pg, pp, cookie)
+__ham_pgout(dbenv, dummydbp, pg, pp, cookie)
DB_ENV *dbenv;
+ DB *dummydbp;
db_pgno_t pg;
void *pp;
DBT *cookie;
@@ -75,12 +77,12 @@ __ham_pgout(dbenv, pg, pp, cookie)
PAGE *h;
pginfo = (DB_PGINFO *)cookie->data;
- if (!pginfo->needswap)
+ if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
h = pp;
return (h->type == P_HASHMETA ? __ham_mswap(pp) :
- __db_byteswap(dbenv, pg, pp, pginfo->db_pagesize, 0));
+ __db_byteswap(dbenv, dummydbp, pg, pp, pginfo->db_pagesize, 0));
}
/*
@@ -108,5 +110,7 @@ __ham_mswap(pg)
SWAP32(p); /* h_charkey */
for (i = 0; i < NCACHED; ++i)
SWAP32(p); /* spares */
+ p += 59 * sizeof(u_int32_t); /* unusued */
+ SWAP32(p); /* crypto_magic */
return (0);
}
diff --git a/bdb/hash/hash_dup.c b/bdb/hash/hash_dup.c
index f5fbf4f472f..ec70e519d54 100644
--- a/bdb/hash/hash_dup.c
+++ b/bdb/hash/hash_dup.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -38,20 +38,14 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_dup.c,v 11.49 2000/12/21 21:54:35 margo Exp $";
+static const char revid[] = "$Id: hash_dup.c,v 11.76 2002/08/06 05:34:40 bostic Exp $";
#endif /* not lint */
/*
* PACKAGE: hashing
*
* DESCRIPTION:
- * Manipulation of duplicates for the hash package.
- *
- * ROUTINES:
- *
- * External
- * __add_dup
- * Internal
+ * Manipulation of duplicates for the hash package.
*/
#ifndef NO_SYSTEM_INCLUDES
@@ -61,13 +55,15 @@ static const char revid[] = "$Id: hash_dup.c,v 11.49 2000/12/21 21:54:35 margo E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "hash.h"
-#include "btree.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+#include "dbinc/btree.h"
+static int __ham_c_chgpg __P((DBC *,
+ db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
static int __ham_check_move __P((DBC *, u_int32_t));
static int __ham_dcursor __P((DBC *, db_pgno_t, u_int32_t));
+static int __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));
/*
* Called from hash_access to add a duplicate key. nval is the new
@@ -92,13 +88,15 @@ __ham_add_dup(dbc, nval, flags, pgnop)
db_pgno_t *pgnop;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT pval, tmp_val;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
u_int32_t add_bytes, new_size;
int cmp, ret;
u_int8_t *hk;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
DB_ASSERT(flags != DB_CURRENT);
@@ -117,12 +115,12 @@ __ham_add_dup(dbc, nval, flags, pgnop)
* hcp->dndx is the first free ndx or the index of the
* current pointer into the duplicate set.
*/
- hk = H_PAIRDATA(hcp->page, hcp->indx);
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
/* Add the len bytes to the current singleton. */
if (HPAGE_PTYPE(hk) != H_DUPLICATE)
add_bytes += DUP_SIZE(0);
new_size =
- LEN_HKEYDATA(hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx)) +
+ LEN_HKEYDATA(dbp, hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx)) +
add_bytes;
/*
@@ -132,7 +130,7 @@ __ham_add_dup(dbc, nval, flags, pgnop)
*/
if (HPAGE_PTYPE(hk) != H_OFFDUP &&
(HPAGE_PTYPE(hk) == H_OFFPAGE || ISBIG(hcp, new_size) ||
- add_bytes > P_FREESPACE(hcp->page))) {
+ add_bytes > P_FREESPACE(dbp, hcp->page))) {
if ((ret = __ham_dup_convert(dbc)) != 0)
return (ret);
@@ -145,14 +143,14 @@ __ham_add_dup(dbc, nval, flags, pgnop)
if (HPAGE_PTYPE(hk) != H_DUPLICATE) {
pval.flags = 0;
pval.data = HKEYDATA_DATA(hk);
- pval.size = LEN_HDATA(hcp->page, dbp->pgsize,
+ pval.size = LEN_HDATA(dbp, hcp->page, dbp->pgsize,
hcp->indx);
if ((ret = __ham_make_dup(dbp->dbenv,
- &pval, &tmp_val, &dbc->rdata.data,
- &dbc->rdata.ulen)) != 0 || (ret =
+ &pval, &tmp_val, &dbc->my_rdata.data,
+ &dbc->my_rdata.ulen)) != 0 || (ret =
__ham_replpair(dbc, &tmp_val, 1)) != 0)
return (ret);
- hk = H_PAIRDATA(hcp->page, hcp->indx);
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
HPAGE_PTYPE(hk) = H_DUPLICATE;
/*
@@ -167,7 +165,7 @@ __ham_add_dup(dbc, nval, flags, pgnop)
/* Now make the new entry a duplicate. */
if ((ret = __ham_make_dup(dbp->dbenv, nval,
- &tmp_val, &dbc->rdata.data, &dbc->rdata.ulen)) != 0)
+ &tmp_val, &dbc->my_rdata.data, &dbc->my_rdata.ulen)) != 0)
return (ret);
tmp_val.dlen = 0;
@@ -176,13 +174,14 @@ __ham_add_dup(dbc, nval, flags, pgnop)
case DB_KEYLAST:
case DB_NODUPDATA:
if (dbp->dup_compare != NULL) {
- __ham_dsearch(dbc, nval, &tmp_val.doff, &cmp);
+ __ham_dsearch(dbc,
+ nval, &tmp_val.doff, &cmp, flags);
/* dup dups are not supported w/ sorted dups */
if (cmp == 0)
return (__db_duperr(dbp, flags));
} else {
- hcp->dup_tlen = LEN_HDATA(hcp->page,
+ hcp->dup_tlen = LEN_HDATA(dbp, hcp->page,
dbp->pgsize, hcp->indx);
hcp->dup_len = nval->size;
F_SET(hcp, H_ISDUP);
@@ -203,8 +202,7 @@ __ham_add_dup(dbc, nval, flags, pgnop)
/* Add the duplicate. */
ret = __ham_replpair(dbc, &tmp_val, 0);
if (ret == 0)
- ret = memp_fset(dbp->mpf, hcp->page, DB_MPOOL_DIRTY);
-
+ ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);
if (ret != 0)
return (ret);
@@ -213,12 +211,12 @@ __ham_add_dup(dbc, nval, flags, pgnop)
case DB_AFTER:
hcp->dup_off += DUP_SIZE(hcp->dup_len);
hcp->dup_len = nval->size;
- hcp->dup_tlen += DUP_SIZE(nval->size);
+ hcp->dup_tlen += (db_indx_t)DUP_SIZE(nval->size);
break;
case DB_KEYFIRST:
case DB_KEYLAST:
case DB_BEFORE:
- hcp->dup_tlen += DUP_SIZE(nval->size);
+ hcp->dup_tlen += (db_indx_t)DUP_SIZE(nval->size);
hcp->dup_len = nval->size;
break;
}
@@ -230,8 +228,8 @@ __ham_add_dup(dbc, nval, flags, pgnop)
* If we get here, then we're on duplicate pages; set pgnop and
* return so the common code can handle it.
*/
- memcpy(pgnop,
- HOFFDUP_PGNO(H_PAIRDATA(hcp->page, hcp->indx)), sizeof(db_pgno_t));
+ memcpy(pgnop, HOFFDUP_PGNO(H_PAIRDATA(dbp, hcp->page, hcp->indx)),
+ sizeof(db_pgno_t));
return (ret);
}
@@ -245,19 +243,21 @@ int
__ham_dup_convert(dbc)
DBC *dbc;
{
+ BOVERFLOW bo;
DB *dbp;
DBC **hcs;
+ DBT dbt;
DB_LSN lsn;
- PAGE *dp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
- BOVERFLOW bo;
- DBT dbt;
HOFFPAGE ho;
+ PAGE *dp;
db_indx_t i, len, off;
int c, ret, t_ret;
u_int8_t *p, *pend;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
/*
@@ -274,24 +274,24 @@ __ham_dup_convert(dbc)
*/
if ((ret = __ham_get_clist(dbp,
PGNO(hcp->page), (u_int32_t)hcp->indx, &hcs)) != 0)
- return (ret);
+ goto err;
/*
* Now put the duplicates onto the new page.
*/
dbt.flags = 0;
- switch (HPAGE_PTYPE(H_PAIRDATA(hcp->page, hcp->indx))) {
+ switch (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))) {
case H_KEYDATA:
/* Simple case, one key on page; move it to dup page. */
- dbt.size = LEN_HDATA(hcp->page, dbp->pgsize, hcp->indx);
- dbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx));
+ dbt.size = LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);
+ dbt.data = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
ret = __db_pitem(dbc,
dp, 0, BKEYDATA_SIZE(dbt.size), NULL, &dbt);
goto finish;
case H_OFFPAGE:
/* Simple case, one key on page; move it to dup page. */
- memcpy(&ho,
- P_ENTRY(hcp->page, H_DATAINDEX(hcp->indx)), HOFFPAGE_SIZE);
+ memcpy(&ho, P_ENTRY(dbp, hcp->page, H_DATAINDEX(hcp->indx)),
+ HOFFPAGE_SIZE);
UMRW_SET(bo.unused1);
B_TSET(bo.type, ho.type, 0);
UMRW_SET(bo.unused2);
@@ -301,17 +301,15 @@ __ham_dup_convert(dbc)
dbt.data = &bo;
ret = __db_pitem(dbc, dp, 0, dbt.size, &dbt, NULL);
-
finish: if (ret == 0) {
- memp_fset(dbp->mpf, dp, DB_MPOOL_DIRTY);
- /*
- * Update any other cursors
- */
- if (hcs != NULL && DB_LOGGING(dbc)
- && IS_SUBTRANSACTION(dbc->txn)) {
- if ((ret = __ham_chgpg_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid,
- DB_HAM_DUP, PGNO(hcp->page),
+ if ((ret = mpf->set(mpf, dp, DB_MPOOL_DIRTY)) != 0)
+ break;
+
+ /* Update any other cursors. */
+ if (hcs != NULL && DBC_LOGGING(dbc) &&
+ IS_SUBTRANSACTION(dbc->txn)) {
+ if ((ret = __ham_chgpg_log(dbp, dbc->txn,
+ &lsn, 0, DB_HAM_DUP, PGNO(hcp->page),
PGNO(dp), hcp->indx, 0)) != 0)
break;
}
@@ -319,14 +317,12 @@ finish: if (ret == 0) {
if ((ret = __ham_dcursor(hcs[c],
PGNO(dp), 0)) != 0)
break;
-
}
break;
-
case H_DUPLICATE:
- p = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx));
+ p = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
pend = p +
- LEN_HDATA(hcp->page, dbp->pgsize, hcp->indx);
+ LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);
/*
* We need to maintain the duplicate cursor position.
@@ -344,39 +340,48 @@ finish: if (ret == 0) {
if ((ret = __db_pitem(dbc, dp,
i, BKEYDATA_SIZE(dbt.size), NULL, &dbt)) != 0)
break;
- /*
- * Update any other cursors
- */
+
+ /* Update any other cursors */
+ if (hcs != NULL && DBC_LOGGING(dbc) &&
+ IS_SUBTRANSACTION(dbc->txn)) {
+ if ((ret = __ham_chgpg_log(dbp, dbc->txn,
+ &lsn, 0, DB_HAM_DUP, PGNO(hcp->page),
+ PGNO(dp), hcp->indx, i)) != 0)
+ break;
+ }
for (c = 0; hcs != NULL && hcs[c] != NULL; c++)
if (((HASH_CURSOR *)(hcs[c]->internal))->dup_off
== off && (ret = __ham_dcursor(hcs[c],
PGNO(dp), i)) != 0)
- goto out;
+ goto err;
off += len + 2 * sizeof(db_indx_t);
}
-out: break;
-
+ break;
default:
- ret = __db_pgfmt(dbp, (u_long)hcp->pgno);
+ ret = __db_pgfmt(dbp->dbenv, (u_long)hcp->pgno);
break;
}
- if (ret == 0) {
- /*
- * Now attach this to the source page in place of
- * the old duplicate item.
- */
- __ham_move_offpage(dbc, hcp->page,
+
+ /*
+ * Now attach this to the source page in place of the old duplicate
+ * item.
+ */
+ if (ret == 0)
+ ret = __ham_move_offpage(dbc, hcp->page,
(u_int32_t)H_DATAINDEX(hcp->indx), PGNO(dp));
- ret = memp_fset(dbp->mpf, hcp->page, DB_MPOOL_DIRTY);
- if ((t_ret = memp_fput(dbp->mpf, dp, DB_MPOOL_DIRTY)) != 0)
- ret = t_ret;
+err: if (ret == 0)
+ ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);
+
+ if ((t_ret =
+ mpf->put(mpf, dp, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (ret == 0)
hcp->dup_tlen = hcp->dup_off = hcp->dup_len = 0;
- } else
- (void)__db_free(dbc, dp);
if (hcs != NULL)
- __os_free(hcs, 0);
+ __os_free(dbp->dbenv, hcs);
return (ret);
}
@@ -444,9 +449,10 @@ __ham_check_move(dbc, add_len)
u_int32_t add_len;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT k, d;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
PAGE *next_pagep;
db_pgno_t next_pgno;
u_int32_t new_datalen, old_len, rectype;
@@ -454,9 +460,10 @@ __ham_check_move(dbc, add_len)
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
- hk = H_PAIRDATA(hcp->page, hcp->indx);
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
/*
* If the item is already off page duplicates or an offpage item,
@@ -465,7 +472,7 @@ __ham_check_move(dbc, add_len)
if (HPAGE_PTYPE(hk) == H_OFFDUP || HPAGE_PTYPE(hk) == H_OFFPAGE)
return (0);
- old_len = LEN_HITEM(hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx));
+ old_len = LEN_HITEM(dbp, hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx));
new_datalen = old_len - HKEYDATA_SIZE(0) + add_len;
if (HPAGE_PTYPE(hk) != H_DUPLICATE)
new_datalen += DUP_SIZE(0);
@@ -479,10 +486,10 @@ __ham_check_move(dbc, add_len)
* If neither of these is true, then we can return.
*/
if (ISBIG(hcp, new_datalen) && (old_len > HOFFDUP_SIZE ||
- HOFFDUP_SIZE - old_len <= P_FREESPACE(hcp->page)))
+ HOFFDUP_SIZE - old_len <= P_FREESPACE(dbp, hcp->page)))
return (0);
- if (!ISBIG(hcp, new_datalen) && add_len <= P_FREESPACE(hcp->page))
+ if (!ISBIG(hcp, new_datalen) && add_len <= P_FREESPACE(dbp, hcp->page))
return (0);
/*
@@ -494,20 +501,20 @@ __ham_check_move(dbc, add_len)
new_datalen = ISBIG(hcp, new_datalen) ?
HOFFDUP_SIZE : HKEYDATA_SIZE(new_datalen);
- new_datalen += LEN_HITEM(hcp->page, dbp->pgsize, H_KEYINDEX(hcp->indx));
+ new_datalen += LEN_HITEM(dbp, hcp->page, dbp->pgsize, H_KEYINDEX(hcp->indx));
next_pagep = NULL;
for (next_pgno = NEXT_PGNO(hcp->page); next_pgno != PGNO_INVALID;
next_pgno = NEXT_PGNO(next_pagep)) {
if (next_pagep != NULL &&
- (ret = memp_fput(dbp->mpf, next_pagep, 0)) != 0)
+ (ret = mpf->put(mpf, next_pagep, 0)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = mpf->get(mpf,
&next_pgno, DB_MPOOL_CREATE, &next_pagep)) != 0)
return (ret);
- if (P_FREESPACE(next_pagep) >= new_datalen)
+ if (P_FREESPACE(dbp, next_pagep) >= new_datalen)
break;
}
@@ -517,58 +524,58 @@ __ham_check_move(dbc, add_len)
return (ret);
/* Add new page at the end of the chain. */
- if (P_FREESPACE(next_pagep) < new_datalen && (ret =
+ if (P_FREESPACE(dbp, next_pagep) < new_datalen && (ret =
__ham_add_ovflpage(dbc, next_pagep, 1, &next_pagep)) != 0) {
- (void)memp_fput(dbp->mpf, next_pagep, 0);
+ (void)mpf->put(mpf, next_pagep, 0);
return (ret);
}
/* Copy the item to the new page. */
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
rectype = PUTPAIR;
k.flags = 0;
d.flags = 0;
if (HPAGE_PTYPE(
- H_PAIRKEY(hcp->page, hcp->indx)) == H_OFFPAGE) {
+ H_PAIRKEY(dbp, hcp->page, hcp->indx)) == H_OFFPAGE) {
rectype |= PAIR_KEYMASK;
- k.data = H_PAIRKEY(hcp->page, hcp->indx);
+ k.data = H_PAIRKEY(dbp, hcp->page, hcp->indx);
k.size = HOFFPAGE_SIZE;
} else {
k.data =
- HKEYDATA_DATA(H_PAIRKEY(hcp->page, hcp->indx));
- k.size = LEN_HKEY(hcp->page, dbp->pgsize, hcp->indx);
+ HKEYDATA_DATA(H_PAIRKEY(dbp, hcp->page, hcp->indx));
+ k.size =
+ LEN_HKEY(dbp, hcp->page, dbp->pgsize, hcp->indx);
}
if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
rectype |= PAIR_DATAMASK;
- d.data = H_PAIRDATA(hcp->page, hcp->indx);
+ d.data = H_PAIRDATA(dbp, hcp->page, hcp->indx);
d.size = HOFFPAGE_SIZE;
} else {
- if (HPAGE_PTYPE(H_PAIRDATA(hcp->page, hcp->indx))
+ if (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))
== H_DUPLICATE)
rectype |= PAIR_DUPMASK;
d.data =
- HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx));
- d.size = LEN_HDATA(hcp->page, dbp->pgsize, hcp->indx);
+ HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
+ d.size = LEN_HDATA(dbp, hcp->page,
+ dbp->pgsize, hcp->indx);
}
- if ((ret = __ham_insdel_log(dbp->dbenv,
- dbc->txn, &new_lsn, 0, rectype,
- dbp->log_fileid, PGNO(next_pagep),
+ if ((ret = __ham_insdel_log(dbp,
+ dbc->txn, &new_lsn, 0, rectype, PGNO(next_pagep),
(u_int32_t)NUM_ENT(next_pagep), &LSN(next_pagep),
&k, &d)) != 0) {
- (void)memp_fput(dbp->mpf, next_pagep, 0);
+ (void)mpf->put(mpf, next_pagep, 0);
return (ret);
}
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(next_pagep) = new_lsn; /* Structure assignment. */
- }
+ /* Move lsn onto page. */
+ LSN(next_pagep) = new_lsn; /* Structure assignment. */
- __ham_copy_item(dbp->pgsize,
- hcp->page, H_KEYINDEX(hcp->indx), next_pagep);
- __ham_copy_item(dbp->pgsize,
- hcp->page, H_DATAINDEX(hcp->indx), next_pagep);
+ __ham_copy_item(dbp, hcp->page, H_KEYINDEX(hcp->indx), next_pagep);
+ __ham_copy_item(dbp, hcp->page, H_DATAINDEX(hcp->indx), next_pagep);
/*
* We've just manually inserted a key and set of data onto
@@ -581,7 +588,7 @@ __ham_check_move(dbc, add_len)
* Note that __ham_del_pair should dirty the page we're moving
* the items from, so we need only dirty the new page ourselves.
*/
- if ((ret = memp_fset(dbp->mpf, next_pagep, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, next_pagep, DB_MPOOL_DIRTY)) != 0)
goto out;
/* Update all cursors that used to point to this item. */
@@ -596,12 +603,17 @@ __ham_check_move(dbc, add_len)
* __ham_del_pair decremented nelem. This is incorrect; we
* manually copied the element elsewhere, so the total number
* of elements hasn't changed. Increment it again.
+ *
+ * !!!
+ * Note that we still have the metadata page pinned, and
+ * __ham_del_pair dirtied it, so we don't need to set the dirty
+ * flag again.
*/
if (!STD_LOCKING(dbc))
hcp->hdr->nelem++;
out:
- (void)memp_fput(dbp->mpf, hcp->page, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, hcp->page, DB_MPOOL_DIRTY);
hcp->page = next_pagep;
hcp->pgno = PGNO(hcp->page);
hcp->indx = NUM_ENT(hcp->page) - 2;
@@ -620,9 +632,8 @@ out:
* This is really just a special case of __onpage_replace; we should
* probably combine them.
*
- * PUBLIC: void __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));
*/
-void
+static int
__ham_move_offpage(dbc, pagep, ndx, pgno)
DBC *dbc;
PAGE *pagep;
@@ -630,48 +641,51 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
db_pgno_t pgno;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT new_dbt;
DBT old_dbt;
HOFFDUP od;
- db_indx_t i;
+ db_indx_t i, *inp;
int32_t shrink;
u_int8_t *src;
+ int ret;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
od.type = H_OFFDUP;
UMRW_SET(od.unused[0]);
UMRW_SET(od.unused[1]);
UMRW_SET(od.unused[2]);
od.pgno = pgno;
+ ret = 0;
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
new_dbt.data = &od;
new_dbt.size = HOFFDUP_SIZE;
- old_dbt.data = P_ENTRY(pagep, ndx);
- old_dbt.size = LEN_HITEM(pagep, dbp->pgsize, ndx);
- (void)__ham_replace_log(dbp->dbenv,
- dbc->txn, &LSN(pagep), 0, dbp->log_fileid,
+ old_dbt.data = P_ENTRY(dbp, pagep, ndx);
+ old_dbt.size = LEN_HITEM(dbp, pagep, dbp->pgsize, ndx);
+ if ((ret = __ham_replace_log(dbp, dbc->txn, &LSN(pagep), 0,
PGNO(pagep), (u_int32_t)ndx, &LSN(pagep), -1,
- &old_dbt, &new_dbt, 0);
- }
+ &old_dbt, &new_dbt, 0)) != 0)
+ return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(pagep));
- shrink = LEN_HITEM(pagep, dbp->pgsize, ndx) - HOFFDUP_SIZE;
+ shrink = LEN_HITEM(dbp, pagep, dbp->pgsize, ndx) - HOFFDUP_SIZE;
+ inp = P_INP(dbp, pagep);
if (shrink != 0) {
/* Copy data. */
src = (u_int8_t *)(pagep) + HOFFSET(pagep);
- memmove(src + shrink, src, pagep->inp[ndx] - HOFFSET(pagep));
+ memmove(src + shrink, src, inp[ndx] - HOFFSET(pagep));
HOFFSET(pagep) += shrink;
/* Update index table. */
for (i = ndx; i < NUM_ENT(pagep); i++)
- pagep->inp[i] += shrink;
+ inp[i] += shrink;
}
/* Now copy the offdup entry onto the page. */
- memcpy(P_ENTRY(pagep, ndx), &od, HOFFDUP_SIZE);
+ memcpy(P_ENTRY(dbp, pagep, ndx), &od, HOFFDUP_SIZE);
+ return (ret);
}
/*
@@ -679,13 +693,14 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
* Locate a particular duplicate in a duplicate set. Make sure that
* we exit with the cursor set appropriately.
*
- * PUBLIC: void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *));
+ * PUBLIC: void __ham_dsearch
+ * PUBLIC: __P((DBC *, DBT *, u_int32_t *, int *, u_int32_t));
*/
void
-__ham_dsearch(dbc, dbt, offp, cmpp)
+__ham_dsearch(dbc, dbt, offp, cmpp, flags)
DBC *dbc;
DBT *dbt;
- u_int32_t *offp;
+ u_int32_t *offp, flags;
int *cmpp;
{
DB *dbp;
@@ -697,25 +712,36 @@ __ham_dsearch(dbc, dbt, offp, cmpp)
dbp = dbc->dbp;
hcp = (HASH_CURSOR *)dbc->internal;
- if (dbp->dup_compare == NULL)
- func = __bam_defcmp;
- else
- func = dbp->dup_compare;
+ func = dbp->dup_compare == NULL ? __bam_defcmp : dbp->dup_compare;
i = F_ISSET(hcp, H_CONTINUE) ? hcp->dup_off: 0;
- data = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx)) + i;
- hcp->dup_tlen = LEN_HDATA(hcp->page, dbp->pgsize, hcp->indx);
+ data = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx)) + i;
+ hcp->dup_tlen = LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);
while (i < hcp->dup_tlen) {
memcpy(&len, data, sizeof(db_indx_t));
data += sizeof(db_indx_t);
cur.data = data;
cur.size = (u_int32_t)len;
+
+ /*
+ * If we find an exact match, we're done. If in a sorted
+ * duplicate set and the item is larger than our test item,
+ * we're done. In the latter case, if permitting partial
+ * matches, it's not a failure.
+ */
*cmpp = func(dbp, dbt, &cur);
- if (*cmpp == 0 || (*cmpp < 0 && dbp->dup_compare != NULL))
+ if (*cmpp == 0)
+ break;
+ if (*cmpp < 0 && dbp->dup_compare != NULL) {
+ if (flags == DB_GET_BOTH_RANGE)
+ *cmpp = 0;
break;
+ }
+
i += len + 2 * sizeof(db_indx_t);
data += len + sizeof(db_indx_t);
}
+
*offp = i;
hcp->dup_off = i;
hcp->dup_len = len;
@@ -727,29 +753,22 @@ __ham_dsearch(dbc, dbt, offp, cmpp)
* __ham_cprint --
* Display the current cursor list.
*
- * PUBLIC: int __ham_cprint __P((DB *));
+ * PUBLIC: void __ham_cprint __P((DBC *));
*/
-int
-__ham_cprint(dbp)
- DB *dbp;
+void
+__ham_cprint(dbc)
+ DBC *dbc;
{
HASH_CURSOR *cp;
- DBC *dbc;
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
- for (dbc = TAILQ_FIRST(&dbp->active_queue);
- dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
- cp = (HASH_CURSOR *)dbc->internal;
- fprintf(stderr, "%#0lx->%#0lx: page: %lu index: %lu",
- P_TO_ULONG(dbc), P_TO_ULONG(cp), (u_long)cp->pgno,
- (u_long)cp->indx);
- if (F_ISSET(cp, H_DELETED))
- fprintf(stderr, " (deleted)");
- fprintf(stderr, "\n");
- }
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ cp = (HASH_CURSOR *)dbc->internal;
- return (0);
+ fprintf(stderr, "%#0lx->%#0lx: page: %lu index: %lu",
+ P_TO_ULONG(dbc), P_TO_ULONG(cp), (u_long)cp->pgno,
+ (u_long)cp->indx);
+ if (F_ISSET(cp, H_DELETED))
+ fprintf(stderr, " (deleted)");
+ fprintf(stderr, "\n");
}
#endif /* DEBUG */
@@ -765,17 +784,17 @@ __ham_dcursor(dbc, pgno, indx)
u_int32_t indx;
{
DB *dbp;
- DBC *dbc_nopd;
HASH_CURSOR *hcp;
BTREE_CURSOR *dcp;
int ret;
dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
- if ((ret = __db_c_newopd(dbc, pgno, &dbc_nopd)) != 0)
+ if ((ret = __db_c_newopd(dbc, pgno, hcp->opd, &hcp->opd)) != 0)
return (ret);
- dcp = (BTREE_CURSOR *)dbc_nopd->internal;
+ dcp = (BTREE_CURSOR *)hcp->opd->internal;
dcp->pgno = pgno;
dcp->indx = indx;
@@ -792,14 +811,81 @@ __ham_dcursor(dbc, pgno, indx)
* Transfer the deleted flag from the top-level cursor to the
* created one.
*/
- hcp = (HASH_CURSOR *)dbc->internal;
if (F_ISSET(hcp, H_DELETED)) {
F_SET(dcp, C_DELETED);
F_CLR(hcp, H_DELETED);
}
- /* Stack the cursors and reset the initial cursor's index. */
- hcp->opd = dbc_nopd;
+ return (0);
+}
+
+/*
+ * __ham_c_chgpg --
+ * Adjust the cursors after moving an item to a new page. We only
+ * move cursors that are pointing at this one item and are not
+ * deleted; since we only touch non-deleted cursors, and since
+ * (by definition) no item existed at the pgno/indx we're moving the
+ * item to, we're guaranteed that all the cursors we affect here or
+ * on abort really do refer to this one item.
+ */
+static int
+__ham_c_chgpg(dbc, old_pgno, old_index, new_pgno, new_index)
+ DBC *dbc;
+ db_pgno_t old_pgno, new_pgno;
+ u_int32_t old_index, new_index;
+{
+ DB *dbp, *ldbp;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_TXN *my_txn;
+ DBC *cp;
+ HASH_CURSOR *hcp;
+ int found, ret;
+
+ dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
+
+ my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL;
+ found = 0;
+
+ MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+ for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+ ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+ ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+ for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
+ cp = TAILQ_NEXT(cp, links)) {
+ if (cp == dbc || cp->dbtype != DB_HASH)
+ continue;
+
+ hcp = (HASH_CURSOR *)cp->internal;
+ /*
+ * If a cursor is deleted, it doesn't refer to this
+ * item--it just happens to have the same indx, but
+ * it points to a former neighbor. Don't move it.
+ */
+ if (F_ISSET(hcp, H_DELETED))
+ continue;
+
+ if (hcp->pgno == old_pgno) {
+ if (hcp->indx == old_index) {
+ hcp->pgno = new_pgno;
+ hcp->indx = new_index;
+ } else
+ continue;
+ if (my_txn != NULL && cp->txn != my_txn)
+ found = 1;
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+ if (found != 0 && DBC_LOGGING(dbc)) {
+ if ((ret = __ham_chgpg_log(dbp, my_txn, &lsn, 0, DB_HAM_CHGPG,
+ old_pgno, new_pgno, old_index, new_index)) != 0)
+ return (ret);
+ }
return (0);
}
diff --git a/bdb/hash/hash_func.c b/bdb/hash/hash_func.c
index 22b4f08ee70..c6cc2ad4460 100644
--- a/bdb/hash/hash_func.c
+++ b/bdb/hash/hash_func.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_func.c,v 11.7 2000/08/16 18:26:19 ubell Exp $";
+static const char revid[] = "$Id: hash_func.c,v 11.12 2002/03/28 19:49:42 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -51,8 +51,6 @@ static const char revid[] = "$Id: hash_func.c,v 11.7 2000/08/16 18:26:19 ubell E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "hash.h"
/*
* __ham_func2 --
@@ -230,6 +228,11 @@ __ham_func5(dbp, key, len)
return (h);
}
+/*
+ * __ham_test --
+ *
+ * PUBLIC: u_int32_t __ham_test __P((DB *, const void *, u_int32_t));
+ */
u_int32_t
__ham_test(dbp, key, len)
DB *dbp;
diff --git a/bdb/hash/hash_meta.c b/bdb/hash/hash_meta.c
index d96a6db3207..9f224454869 100644
--- a/bdb/hash/hash_meta.c
+++ b/bdb/hash/hash_meta.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_meta.c,v 11.10 2000/12/21 21:54:35 margo Exp $";
+static const char revid[] = "$Id: hash_meta.c,v 11.19 2002/06/03 14:22:15 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,11 +16,10 @@ static const char revid[] = "$Id: hash_meta.c,v 11.10 2000/12/21 21:54:35 margo
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "hash.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
/*
* Acquire the meta-data page.
@@ -31,30 +30,32 @@ int
__ham_get_meta(dbc)
DBC *dbc;
{
- HASH_CURSOR *hcp;
- HASH *hashp;
DB *dbp;
+ DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
+ HASH *hashp;
+ HASH_CURSOR *hcp;
int ret;
- hcp = (HASH_CURSOR *)dbc->internal;
dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
hashp = dbp->h_internal;
+ hcp = (HASH_CURSOR *)dbc->internal;
- if (dbp->dbenv != NULL &&
- STD_LOCKING(dbc) && !F_ISSET(dbc, DBC_RECOVER)) {
+ if (dbenv != NULL &&
+ STD_LOCKING(dbc) && !F_ISSET(dbc, DBC_RECOVER | DBC_COMPENSATE)) {
dbc->lock.pgno = hashp->meta_pgno;
- if ((ret = lock_get(dbp->dbenv, dbc->locker,
+ if ((ret = dbenv->lock_get(dbenv, dbc->locker,
DB_NONBLOCK(dbc) ? DB_LOCK_NOWAIT : 0,
&dbc->lock_dbt, DB_LOCK_READ, &hcp->hlock)) != 0)
return (ret);
}
- if ((ret = memp_fget(dbc->dbp->mpf,
+ if ((ret = mpf->get(mpf,
&hashp->meta_pgno, DB_MPOOL_CREATE, &(hcp->hdr))) != 0 &&
- hcp->hlock.off != LOCK_INVALID) {
- (void)lock_put(dbc->dbp->dbenv, &hcp->hlock);
- hcp->hlock.off = LOCK_INVALID;
- }
+ LOCK_ISSET(hcp->hlock))
+ (void)dbenv->lock_put(dbenv, &hcp->hlock);
return (ret);
}
@@ -68,18 +69,19 @@ int
__ham_release_meta(dbc)
DBC *dbc;
{
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
+ mpf = dbc->dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
if (hcp->hdr)
- (void)memp_fput(dbc->dbp->mpf, hcp->hdr,
+ (void)mpf->put(mpf, hcp->hdr,
F_ISSET(hcp, H_DIRTY) ? DB_MPOOL_DIRTY : 0);
hcp->hdr = NULL;
- if (!F_ISSET(dbc, DBC_RECOVER) &&
- dbc->txn == NULL && hcp->hlock.off != LOCK_INVALID)
- (void)lock_put(dbc->dbp->dbenv, &hcp->hlock);
- hcp->hlock.off = LOCK_INVALID;
+ if (!F_ISSET(dbc, DBC_RECOVER | DBC_COMPENSATE) &&
+ dbc->txn == NULL && LOCK_ISSET(hcp->hlock))
+ (void)dbc->dbp->dbenv->lock_put(dbc->dbp->dbenv, &hcp->hlock);
F_CLR(hcp, H_DIRTY);
return (0);
@@ -95,6 +97,7 @@ __ham_dirty_meta(dbc)
DBC *dbc;
{
DB *dbp;
+ DB_ENV *dbenv;
DB_LOCK _tmp;
HASH *hashp;
HASH_CURSOR *hcp;
@@ -105,12 +108,13 @@ __ham_dirty_meta(dbc)
hcp = (HASH_CURSOR *)dbc->internal;
ret = 0;
- if (STD_LOCKING(dbc) && !F_ISSET(dbc, DBC_RECOVER)) {
+ if (STD_LOCKING(dbc) && !F_ISSET(dbc, DBC_RECOVER | DBC_COMPENSATE)) {
+ dbenv = dbp->dbenv;
dbc->lock.pgno = hashp->meta_pgno;
- if ((ret = lock_get(dbp->dbenv, dbc->locker,
+ if ((ret = dbenv->lock_get(dbenv, dbc->locker,
DB_NONBLOCK(dbc) ? DB_LOCK_NOWAIT : 0,
&dbc->lock_dbt, DB_LOCK_WRITE, &_tmp)) == 0) {
- ret = lock_put(dbp->dbenv, &hcp->hlock);
+ ret = dbenv->lock_put(dbenv, &hcp->hlock);
hcp->hlock = _tmp;
}
}
diff --git a/bdb/hash/hash_method.c b/bdb/hash/hash_method.c
index f8239993dc5..9a6bf59536a 100644
--- a/bdb/hash/hash_method.c
+++ b/bdb/hash/hash_method.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_method.c,v 11.7 2000/07/04 18:28:23 bostic Exp $";
+static const char revid[] = "$Id: hash_method.c,v 11.12 2002/03/27 04:32:12 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,8 +16,8 @@ static const char revid[] = "$Id: hash_method.c,v 11.7 2000/07/04 18:28:23 bosti
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "hash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
static int __ham_set_h_ffactor __P((DB *, u_int32_t));
static int __ham_set_h_hash
@@ -38,7 +38,7 @@ __ham_db_create(dbp)
int ret;
if ((ret = __os_malloc(dbp->dbenv,
- sizeof(HASH), NULL, &dbp->h_internal)) != 0)
+ sizeof(HASH), &dbp->h_internal)) != 0)
return (ret);
hashp = dbp->h_internal;
@@ -63,7 +63,7 @@ __ham_db_close(dbp)
{
if (dbp->h_internal == NULL)
return (0);
- __os_free(dbp->h_internal, sizeof(HASH));
+ __os_free(dbp->dbenv, dbp->h_internal);
dbp->h_internal = NULL;
return (0);
}
diff --git a/bdb/hash/hash_open.c b/bdb/hash/hash_open.c
new file mode 100644
index 00000000000..041a1df1e7b
--- /dev/null
+++ b/bdb/hash/hash_open.c
@@ -0,0 +1,558 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * Margo Seltzer. All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: hash_open.c,v 11.175 2002/09/04 19:06:44 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/btree.h"
+#include "dbinc/fop.h"
+
+static db_pgno_t __ham_init_meta __P((DB *, HMETA *, db_pgno_t, DB_LSN *));
+
+/*
+ * __ham_open --
+ *
+ * PUBLIC: int __ham_open __P((DB *,
+ * PUBLIC: DB_TXN *, const char * name, db_pgno_t, u_int32_t));
+ */
+int
+__ham_open(dbp, txn, name, base_pgno, flags)
+ DB *dbp;
+ DB_TXN *txn;
+ const char *name;
+ db_pgno_t base_pgno;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ DBC *dbc;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
+ HASH *hashp;
+ int ret, t_ret;
+
+ COMPQUIET(name, NULL);
+ dbenv = dbp->dbenv;
+ dbc = NULL;
+ mpf = dbp->mpf;
+
+ /* Initialize the remaining fields/methods of the DB. */
+ dbp->stat = __ham_stat;
+
+ /*
+ * Get a cursor. If DB_CREATE is specified, we may be creating
+ * pages, and to do that safely in CDB we need a write cursor.
+ * In STD_LOCKING mode, we'll synchronize using the meta page
+ * lock instead.
+ */
+ if ((ret = dbp->cursor(dbp,
+ txn, &dbc, LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?
+ DB_WRITECURSOR : 0)) != 0)
+ return (ret);
+
+ hcp = (HASH_CURSOR *)dbc->internal;
+ hashp = dbp->h_internal;
+ hashp->meta_pgno = base_pgno;
+ if ((ret = __ham_get_meta(dbc)) != 0)
+ goto err1;
+
+ /* Initialize the hdr structure. */
+ if (hcp->hdr->dbmeta.magic == DB_HASHMAGIC) {
+ /* File exists, verify the data in the header. */
+ if (hashp->h_hash == NULL)
+ hashp->h_hash = hcp->hdr->dbmeta.version < 5
+ ? __ham_func4 : __ham_func5;
+ if (!F_ISSET(dbp, DB_AM_RDONLY) && !IS_RECOVERING(dbenv) &&
+ hashp->h_hash(dbp,
+ CHARKEY, sizeof(CHARKEY)) != hcp->hdr->h_charkey) {
+ __db_err(dbp->dbenv,
+ "hash: incompatible hash function");
+ ret = EINVAL;
+ goto err2;
+ }
+ if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_DUP))
+ F_SET(dbp, DB_AM_DUP);
+ if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_DUPSORT))
+ F_SET(dbp, DB_AM_DUPSORT);
+ if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_SUBDB))
+ F_SET(dbp, DB_AM_SUBDB);
+
+ /* We must initialize last_pgno, it could be stale. */
+ if (!F_ISSET(dbp, DB_AM_RDONLY) &&
+ dbp->meta_pgno == PGNO_BASE_MD) {
+ if ((ret = __ham_dirty_meta(dbc)) != 0)
+ goto err2;
+ mpf->last_pgno(mpf, &hcp->hdr->dbmeta.last_pgno);
+ }
+ } else if (!IS_RECOVERING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER))
+ DB_ASSERT(0);
+
+err2: /* Release the meta data page */
+ if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+err1: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __ham_metachk --
+ *
+ * PUBLIC: int __ham_metachk __P((DB *, const char *, HMETA *));
+ */
+int
+__ham_metachk(dbp, name, hashm)
+ DB *dbp;
+ const char *name;
+ HMETA *hashm;
+{
+ DB_ENV *dbenv;
+ u_int32_t vers;
+ int ret;
+
+ dbenv = dbp->dbenv;
+
+ /*
+ * At this point, all we know is that the magic number is for a Hash.
+ * Check the version, the database may be out of date.
+ */
+ vers = hashm->dbmeta.version;
+ if (F_ISSET(dbp, DB_AM_SWAP))
+ M_32_SWAP(vers);
+ switch (vers) {
+ case 4:
+ case 5:
+ case 6:
+ __db_err(dbenv,
+ "%s: hash version %lu requires a version upgrade",
+ name, (u_long)vers);
+ return (DB_OLD_VERSION);
+ case 7:
+ case 8:
+ break;
+ default:
+ __db_err(dbenv,
+ "%s: unsupported hash version: %lu", name, (u_long)vers);
+ return (EINVAL);
+ }
+
+ /* Swap the page if we need to. */
+ if (F_ISSET(dbp, DB_AM_SWAP) && (ret = __ham_mswap((PAGE *)hashm)) != 0)
+ return (ret);
+
+ /* Check the type. */
+ if (dbp->type != DB_HASH && dbp->type != DB_UNKNOWN)
+ return (EINVAL);
+ dbp->type = DB_HASH;
+ DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
+
+ /*
+ * Check application info against metadata info, and set info, flags,
+ * and type based on metadata info.
+ */
+ if ((ret = __db_fchk(dbenv,
+ "DB->open", hashm->dbmeta.flags,
+ DB_HASH_DUP | DB_HASH_SUBDB | DB_HASH_DUPSORT)) != 0)
+ return (ret);
+
+ if (F_ISSET(&hashm->dbmeta, DB_HASH_DUP))
+ F_SET(dbp, DB_AM_DUP);
+ else
+ if (F_ISSET(dbp, DB_AM_DUP)) {
+ __db_err(dbenv,
+ "%s: DB_DUP specified to open method but not set in database",
+ name);
+ return (EINVAL);
+ }
+
+ if (F_ISSET(&hashm->dbmeta, DB_HASH_SUBDB))
+ F_SET(dbp, DB_AM_SUBDB);
+ else
+ if (F_ISSET(dbp, DB_AM_SUBDB)) {
+ __db_err(dbenv,
+ "%s: multiple databases specified but not supported in file",
+ name);
+ return (EINVAL);
+ }
+
+ if (F_ISSET(&hashm->dbmeta, DB_HASH_DUPSORT)) {
+ if (dbp->dup_compare == NULL)
+ dbp->dup_compare = __bam_defcmp;
+ } else
+ if (dbp->dup_compare != NULL) {
+ __db_err(dbenv,
+ "%s: duplicate sort function specified but not set in database",
+ name);
+ return (EINVAL);
+ }
+
+ /* Set the page size. */
+ dbp->pgsize = hashm->dbmeta.pagesize;
+
+ /* Copy the file's ID. */
+ memcpy(dbp->fileid, hashm->dbmeta.uid, DB_FILE_ID_LEN);
+
+ return (0);
+}
+
+/*
+ * __ham_init_meta --
+ *
+ * Initialize a hash meta-data page. We assume that the meta-data page is
+ * contiguous with the initial buckets that we create. If that turns out
+ * to be false, we'll fix it up later. Return the initial number of buckets
+ * allocated.
+ */
+static db_pgno_t
+__ham_init_meta(dbp, meta, pgno, lsnp)
+ DB *dbp;
+ HMETA *meta;
+ db_pgno_t pgno;
+ DB_LSN *lsnp;
+{
+ HASH *hashp;
+ db_pgno_t nbuckets;
+ int i;
+ int32_t l2;
+
+ hashp = dbp->h_internal;
+ if (hashp->h_hash == NULL)
+ hashp->h_hash = DB_HASHVERSION < 5 ? __ham_func4 : __ham_func5;
+
+ if (hashp->h_nelem != 0 && hashp->h_ffactor != 0) {
+ hashp->h_nelem = (hashp->h_nelem - 1) / hashp->h_ffactor + 1;
+ l2 = __db_log2(hashp->h_nelem > 2 ? hashp->h_nelem : 2);
+ } else
+ l2 = 1;
+ nbuckets = (db_pgno_t)(1 << l2);
+
+ memset(meta, 0, sizeof(HMETA));
+ meta->dbmeta.lsn = *lsnp;
+ meta->dbmeta.pgno = pgno;
+ meta->dbmeta.magic = DB_HASHMAGIC;
+ meta->dbmeta.version = DB_HASHVERSION;
+ meta->dbmeta.pagesize = dbp->pgsize;
+ if (F_ISSET(dbp, DB_AM_CHKSUM))
+ FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
+ if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
+ meta->dbmeta.encrypt_alg =
+ ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
+ DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
+ meta->crypto_magic = meta->dbmeta.magic;
+ }
+ meta->dbmeta.type = P_HASHMETA;
+ meta->dbmeta.free = PGNO_INVALID;
+ meta->dbmeta.last_pgno = pgno;
+ meta->max_bucket = nbuckets - 1;
+ meta->high_mask = nbuckets - 1;
+ meta->low_mask = (nbuckets >> 1) - 1;
+ meta->ffactor = hashp->h_ffactor;
+ meta->h_charkey = hashp->h_hash(dbp, CHARKEY, sizeof(CHARKEY));
+ memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
+
+ if (F_ISSET(dbp, DB_AM_DUP))
+ F_SET(&meta->dbmeta, DB_HASH_DUP);
+ if (F_ISSET(dbp, DB_AM_SUBDB))
+ F_SET(&meta->dbmeta, DB_HASH_SUBDB);
+ if (dbp->dup_compare != NULL)
+ F_SET(&meta->dbmeta, DB_HASH_DUPSORT);
+
+ /*
+ * Create the first and second buckets pages so that we have the
+ * page numbers for them and we can store that page number in the
+ * meta-data header (spares[0]).
+ */
+ meta->spares[0] = pgno + 1;
+
+ /* Fill in the last fields of the meta data page. */
+ for (i = 1; i <= l2; i++)
+ meta->spares[i] = meta->spares[0];
+ for (; i < NCACHED; i++)
+ meta->spares[i] = PGNO_INVALID;
+
+ return (nbuckets);
+}
+
+/*
+ * __ham_new_file --
+ * Create the necessary pages to begin a new database file. If name
+ * is NULL, then this is an unnamed file, the mpf has been set in the dbp
+ * and we simply create the pages using mpool. In this case, we don't log
+ * because we never have to redo an unnamed create and the undo simply
+ * frees resources.
+ *
+ * This code appears more complex than it is because of the two cases (named
+ * and unnamed). The way to read the code is that for each page being created,
+ * there are three parts: 1) a "get page" chunk (which either uses malloc'd
+ * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
+ * chunk which either does a fop write or an mpf->put.
+ *
+ * PUBLIC: int __ham_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
+ */
+int
+__ham_new_file(dbp, txn, fhp, name)
+ DB *dbp;
+ DB_TXN *txn;
+ DB_FH *fhp;
+ const char *name;
+{
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_MPOOLFILE *mpf;
+ DB_PGINFO pginfo;
+ DBT pdbt;
+ HMETA *meta;
+ PAGE *page;
+ int ret;
+ db_pgno_t lpgno;
+ void *buf;
+
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ meta = NULL;
+ page = NULL;
+ memset(&pdbt, 0, sizeof(pdbt));
+
+ /* Build meta-data page. */
+ if (name == NULL) {
+ lpgno = PGNO_BASE_MD;
+ ret = mpf->get(mpf, &lpgno, DB_MPOOL_CREATE, &meta);
+ } else {
+ pginfo.db_pagesize = dbp->pgsize;
+ pginfo.type = dbp->type;
+ pginfo.flags =
+ F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+ pdbt.data = &pginfo;
+ pdbt.size = sizeof(pginfo);
+ ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
+ meta = (HMETA *)buf;
+ }
+ if (ret != 0)
+ return (ret);
+
+ LSN_NOT_LOGGED(lsn);
+ lpgno = __ham_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
+ meta->dbmeta.last_pgno = lpgno;
+
+ if (name == NULL)
+ ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+ else {
+ if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
+ goto err;
+ ret = __fop_write(dbenv, txn, name,
+ DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
+ }
+ if (ret != 0)
+ goto err;
+ meta = NULL;
+
+ /* Now allocate the final hash bucket. */
+ if (name == NULL) {
+ if ((ret = mpf->get(mpf, &lpgno, DB_MPOOL_CREATE, &page)) != 0)
+ goto err;
+ } else {
+#ifdef DIAGNOSTIC
+ memset(buf, dbp->pgsize, 0);
+#endif
+ page = (PAGE *)buf;
+ }
+
+ P_INIT(page, dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+ LSN_NOT_LOGGED(page->lsn);
+
+ if (name == NULL)
+ ret = mpf->put(mpf, page, DB_MPOOL_DIRTY);
+ else {
+ if ((ret = __db_pgout(dbenv, lpgno, buf, &pdbt)) != 0)
+ goto err;
+ ret = __fop_write(dbenv, txn, name,
+ DB_APP_DATA, fhp, lpgno * dbp->pgsize, buf, dbp->pgsize, 1);
+ }
+ if (ret != 0)
+ goto err;
+ page = NULL;
+
+err: if (name != NULL)
+ __os_free(dbenv, buf);
+ else {
+ if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ if (page != NULL)
+ (void)mpf->put(mpf, page, 0);
+ }
+ return (ret);
+}
+
+/*
+ * __ham_new_subdb --
+ * Create the necessary pages to begin a new subdatabase.
+ *
+ * PUBLIC: int __ham_new_subdb __P((DB *, DB *, DB_TXN *));
+ */
+int
+__ham_new_subdb(mdbp, dbp, txn)
+ DB *mdbp, *dbp;
+ DB_TXN *txn;
+{
+ DBC *dbc;
+ DB_ENV *dbenv;
+ DB_LOCK metalock, mmlock;
+ DB_LSN lsn;
+ DB_MPOOLFILE *mpf;
+ DBMETA *mmeta;
+ HMETA *meta;
+ PAGE *h;
+ int i, ret, t_ret;
+ db_pgno_t lpgno, mpgno;
+
+ dbenv = mdbp->dbenv;
+ mpf = mdbp->mpf;
+ dbc = NULL;
+ meta = NULL;
+ mmeta = NULL;
+ LOCK_INIT(metalock);
+ LOCK_INIT(mmlock);
+
+ if ((ret = mdbp->cursor(mdbp, txn,
+ &dbc, CDB_LOCKING(dbenv) ? DB_WRITECURSOR : 0)) != 0)
+ return (ret);
+
+ /* Get and lock the new meta data page. */
+ if ((ret = __db_lget(dbc,
+ 0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
+ goto err;
+ if ((ret = mpf->get(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
+ goto err;
+
+ /* Initialize the new meta-data page. */
+ lsn = meta->dbmeta.lsn;
+ lpgno = __ham_init_meta(dbp, meta, dbp->meta_pgno, &lsn);
+
+ /*
+ * We are about to allocate a set of contiguous buckets (lpgno
+ * worth). We need to get the master meta-data page to figure
+ * out where these pages are and to allocate them. So, lock and
+ * get the master meta data page.
+ */
+ mpgno = PGNO_BASE_MD;
+ if ((ret = __db_lget(dbc, 0, mpgno, DB_LOCK_WRITE, 0, &mmlock)) != 0)
+ goto err;
+ if ((ret = mpf->get(mpf, &mpgno, 0, &mmeta)) != 0)
+ goto err;
+
+ /*
+ * Now update the hash meta-data page to reflect where the first
+ * set of buckets are actually located.
+ */
+ meta->spares[0] = mmeta->last_pgno + 1;
+ for (i = 0; i < NCACHED && meta->spares[i] != PGNO_INVALID; i++)
+ meta->spares[i] = meta->spares[0];
+
+ /* The new meta data page is now complete; log it. */
+ if ((ret = __db_log_page(mdbp,
+ txn, &meta->dbmeta.lsn, dbp->meta_pgno, (PAGE *)meta)) != 0)
+ goto err;
+
+ /* Reflect the group allocation. */
+ if (DBENV_LOGGING(dbenv))
+ if ((ret = __ham_groupalloc_log(mdbp, txn,
+ &LSN(mmeta), 0, &LSN(mmeta),
+ meta->spares[0], meta->max_bucket + 1, mmeta->free)) != 0)
+ goto err;
+
+ /* Release the new meta-data page. */
+ if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
+ goto err;
+ meta = NULL;
+
+ mmeta->last_pgno +=lpgno;
+ lpgno = mmeta->last_pgno;
+
+ /* Now allocate the final hash bucket. */
+ if ((ret = mpf->get(mpf, &lpgno, DB_MPOOL_CREATE, &h)) != 0)
+ goto err;
+ P_INIT(h, dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+ LSN(h) = LSN(mmeta);
+ if ((ret = mpf->put(mpf, h, DB_MPOOL_DIRTY)) != 0)
+ goto err;
+
+ /* Now put the master-metadata page back. */
+ if ((ret = mpf->put(mpf, mmeta, DB_MPOOL_DIRTY)) != 0)
+ goto err;
+ mmeta = NULL;
+
+err:
+ if (mmeta != NULL)
+ if ((t_ret = mpf->put(mpf, mmeta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (LOCK_ISSET(mmlock))
+ if ((t_ret = __LPUT(dbc, mmlock)) != 0 && ret == 0)
+ ret = t_ret;
+ if (meta != NULL)
+ if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (LOCK_ISSET(metalock))
+ if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+ ret = t_ret;
+ if (dbc != NULL)
+ if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+}
diff --git a/bdb/hash/hash_page.c b/bdb/hash/hash_page.c
index 64f38853284..6788129773f 100644
--- a/bdb/hash/hash_page.c
+++ b/bdb/hash/hash_page.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,23 +43,14 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_page.c,v 11.46 2001/01/11 18:19:51 bostic Exp $";
+static const char revid[] = "$Id: hash_page.c,v 11.87 2002/08/15 02:46:20 bostic Exp $";
#endif /* not lint */
/*
* PACKAGE: hashing
*
* DESCRIPTION:
- * Page manipulation for hashing package.
- *
- * ROUTINES:
- *
- * External
- * __get_page
- * __add_ovflpage
- * __overflow_page
- * Internal
- * open_temp
+ * Page manipulation for hashing package.
*/
#ifndef NO_SYSTEM_INCLUDES
@@ -69,11 +60,13 @@ static const char revid[] = "$Id: hash_page.c,v 11.46 2001/01/11 18:19:51 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "hash.h"
-#include "lock.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+
+static int __ham_c_delpg
+ __P((DBC *, db_pgno_t, db_pgno_t, u_int32_t, db_ham_mode, u_int32_t *));
/*
* PUBLIC: int __ham_item __P((DBC *, db_lockmode_t, db_pgno_t *));
@@ -104,15 +97,15 @@ __ham_item(dbc, mode, pgnop)
recheck:
/* Check if we are looking for space in which to insert an item. */
- if (hcp->seek_size && hcp->seek_found_page == PGNO_INVALID
- && hcp->seek_size < P_FREESPACE(hcp->page))
+ if (hcp->seek_size && hcp->seek_found_page == PGNO_INVALID &&
+ hcp->seek_size < P_FREESPACE(dbp, hcp->page))
hcp->seek_found_page = hcp->pgno;
/* Check for off-page duplicates. */
if (hcp->indx < NUM_ENT(hcp->page) &&
- HPAGE_TYPE(hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP) {
+ HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP) {
memcpy(pgnop,
- HOFFDUP_PGNO(H_PAIRDATA(hcp->page, hcp->indx)),
+ HOFFDUP_PGNO(H_PAIRDATA(dbp, hcp->page, hcp->indx)),
sizeof(db_pgno_t));
F_SET(hcp, H_OK);
return (0);
@@ -126,7 +119,7 @@ recheck:
* pointer to be the beginning of the datum.
*/
memcpy(&hcp->dup_len,
- HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx)) +
+ HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx)) +
hcp->dup_off, sizeof(db_indx_t));
if (hcp->indx >= (db_indx_t)NUM_ENT(hcp->page)) {
@@ -153,15 +146,18 @@ int
__ham_item_reset(dbc)
DBC *dbc;
{
- HASH_CURSOR *hcp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
int ret;
- ret = 0;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
+
+ ret = 0;
if (hcp->page != NULL)
- ret = memp_fput(dbp->mpf, hcp->page, 0);
+ ret = mpf->put(mpf, hcp->page, 0);
__ham_item_init(dbc);
return (ret);
@@ -181,8 +177,7 @@ __ham_item_init(dbc)
* If this cursor still holds any locks, we must
* release them if we are not running with transactions.
*/
- if (hcp->lock.off != LOCK_INVALID && dbc->txn == NULL)
- (void)lock_put(dbc->dbp->dbenv, &hcp->lock);
+ (void)__TLPUT(dbc, hcp->lock);
/*
* The following fields must *not* be initialized here
@@ -191,7 +186,7 @@ __ham_item_init(dbc)
*/
hcp->bucket = BUCKET_INVALID;
hcp->lbucket = BUCKET_INVALID;
- hcp->lock.off = LOCK_INVALID;
+ LOCK_INIT(hcp->lock);
hcp->lock_mode = DB_LOCK_NG;
hcp->dup_off = 0;
hcp->dup_len = 0;
@@ -269,8 +264,9 @@ __ham_item_prev(dbc, mode, pgnop)
db_pgno_t next_pgno;
int ret;
- dbp = dbc->dbp;
hcp = (HASH_CURSOR *)dbc->internal;
+ dbp = dbc->dbp;
+
/*
* There are 5 cases for backing up in a hash file.
* Case 1: In the middle of a page, no duplicates, just dec the index.
@@ -291,9 +287,10 @@ __ham_item_prev(dbc, mode, pgnop)
* to handle backing up through keys.
*/
if (!F_ISSET(hcp, H_NEXT_NODUP) && F_ISSET(hcp, H_ISDUP)) {
- if (HPAGE_TYPE(hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP) {
+ if (HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) ==
+ H_OFFDUP) {
memcpy(pgnop,
- HOFFDUP_PGNO(H_PAIRDATA(hcp->page, hcp->indx)),
+ HOFFDUP_PGNO(H_PAIRDATA(dbp, hcp->page, hcp->indx)),
sizeof(db_pgno_t));
F_SET(hcp, H_OK);
return (0);
@@ -302,7 +299,7 @@ __ham_item_prev(dbc, mode, pgnop)
/* Duplicates are on-page. */
if (hcp->dup_off != 0) {
memcpy(&hcp->dup_len, HKEYDATA_DATA(
- H_PAIRDATA(hcp->page, hcp->indx))
+ H_PAIRDATA(dbp, hcp->page, hcp->indx))
+ hcp->dup_off - sizeof(db_indx_t),
sizeof(db_indx_t));
hcp->dup_off -=
@@ -396,7 +393,7 @@ __ham_item_next(dbc, mode, pgnop)
if (F_ISSET(hcp, H_DELETED)) {
if (hcp->indx != NDX_INVALID &&
F_ISSET(hcp, H_ISDUP) &&
- HPAGE_TYPE(hcp->page, H_DATAINDEX(hcp->indx))
+ HPAGE_TYPE(dbc->dbp, hcp->page, H_DATAINDEX(hcp->indx))
== H_DUPLICATE && hcp->dup_tlen == hcp->dup_off) {
if (F_ISSET(hcp, H_DUPONLY)) {
F_CLR(hcp, H_OK);
@@ -447,7 +444,7 @@ __ham_item_next(dbc, mode, pgnop)
}
/*
- * PUBLIC: void __ham_putitem __P((PAGE *p, const DBT *, int));
+ * PUBLIC: void __ham_putitem __P((DB *, PAGE *p, const DBT *, int));
*
* This is a little bit sleazy in that we're overloading the meaning
* of the H_OFFPAGE type here. When we recover deletes, we have the
@@ -456,24 +453,27 @@ __ham_item_next(dbc, mode, pgnop)
* an H_KEYDATA around it.
*/
void
-__ham_putitem(p, dbt, type)
+__ham_putitem(dbp, p, dbt, type)
+ DB *dbp;
PAGE *p;
const DBT *dbt;
int type;
{
u_int16_t n, off;
+ db_indx_t *inp;
n = NUM_ENT(p);
+ inp = P_INP(dbp, p);
/* Put the item element on the page. */
if (type == H_OFFPAGE) {
off = HOFFSET(p) - dbt->size;
- HOFFSET(p) = p->inp[n] = off;
- memcpy(P_ENTRY(p, n), dbt->data, dbt->size);
+ HOFFSET(p) = inp[n] = off;
+ memcpy(P_ENTRY(dbp, p, n), dbt->data, dbt->size);
} else {
off = HOFFSET(p) - HKEYDATA_SIZE(dbt->size);
- HOFFSET(p) = p->inp[n] = off;
- PUT_HKEYDATA(P_ENTRY(p, n), dbt->data, dbt->size, type);
+ HOFFSET(p) = inp[n] = off;
+ PUT_HKEYDATA(P_ENTRY(dbp, p, n), dbt->data, dbt->size, type);
}
/* Adjust page info. */
@@ -481,8 +481,8 @@ __ham_putitem(p, dbt, type)
}
/*
- * PUBLIC: void __ham_reputpair
- * PUBLIC: __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *));
+ * PUBLIC: void __ham_reputpair __P((DB *, PAGE *,
+ * PUBLIC: u_int32_t, const DBT *, const DBT *));
*
* This is a special case to restore a key/data pair to its original
* location during recovery. We are guaranteed that the pair fits
@@ -490,17 +490,21 @@ __ham_putitem(p, dbt, type)
* the last pair, the normal insert works).
*/
void
-__ham_reputpair(p, psize, ndx, key, data)
+__ham_reputpair(dbp, p, ndx, key, data)
+ DB *dbp;
PAGE *p;
- u_int32_t psize, ndx;
+ u_int32_t ndx;
const DBT *key, *data;
{
- db_indx_t i, movebytes, newbytes;
+ db_indx_t i, *inp, movebytes, newbytes;
+ size_t psize;
u_int8_t *from;
+ psize = dbp->pgsize;
+ inp = P_INP(dbp, p);
/* First shuffle the existing items up on the page. */
- movebytes =
- (ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 2)]) - HOFFSET(p);
+ movebytes = (db_indx_t)(
+ (ndx == 0 ? psize : inp[H_DATAINDEX(ndx - 2)]) - HOFFSET(p));
newbytes = key->size + data->size;
from = (u_int8_t *)p + HOFFSET(p);
memmove(from - newbytes, from, movebytes);
@@ -511,17 +515,17 @@ __ham_reputpair(p, psize, ndx, key, data)
* we are dealing with index 0 (db_indx_t's are unsigned).
*/
for (i = NUM_ENT(p) - 1; ; i-- ) {
- p->inp[i + 2] = p->inp[i] - newbytes;
+ inp[i + 2] = inp[i] - newbytes;
if (i == H_KEYINDEX(ndx))
break;
}
/* Put the key and data on the page. */
- p->inp[H_KEYINDEX(ndx)] =
- (ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 2)]) - key->size;
- p->inp[H_DATAINDEX(ndx)] = p->inp[H_KEYINDEX(ndx)] - data->size;
- memcpy(P_ENTRY(p, H_KEYINDEX(ndx)), key->data, key->size);
- memcpy(P_ENTRY(p, H_DATAINDEX(ndx)), data->data, data->size);
+ inp[H_KEYINDEX(ndx)] = (db_indx_t)(
+ (ndx == 0 ? psize : inp[H_DATAINDEX(ndx - 2)]) - key->size);
+ inp[H_DATAINDEX(ndx)] = inp[H_KEYINDEX(ndx)] - data->size;
+ memcpy(P_ENTRY(dbp, p, H_KEYINDEX(ndx)), key->data, key->size);
+ memcpy(P_ENTRY(dbp, p, H_DATAINDEX(ndx)), data->data, data->size);
/* Adjust page info. */
HOFFSET(p) -= newbytes;
@@ -537,25 +541,25 @@ __ham_del_pair(dbc, reclaim_page)
int reclaim_page;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT data_dbt, key_dbt;
- DB_ENV *dbenv;
DB_LSN new_lsn, *n_lsn, tmp_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
PAGE *n_pagep, *nn_pagep, *p, *p_pagep;
+ db_ham_mode op;
db_indx_t ndx;
db_pgno_t chg_pgno, pgno, tmp_pgno;
int ret, t_ret;
+ u_int32_t order;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
-
- dbenv = dbp->dbenv;
- ndx = hcp->indx;
-
n_pagep = p_pagep = nn_pagep = NULL;
+ ndx = hcp->indx;
- if (hcp->page == NULL && (ret = memp_fget(dbp->mpf,
- &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
+ if (hcp->page == NULL &&
+ (ret = mpf->get(mpf, &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
return (ret);
p = hcp->page;
@@ -567,17 +571,17 @@ __ham_del_pair(dbc, reclaim_page)
* entry referring to the big item.
*/
ret = 0;
- if (HPAGE_PTYPE(H_PAIRKEY(p, ndx)) == H_OFFPAGE) {
- memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(p, H_KEYINDEX(ndx))),
+ if (HPAGE_PTYPE(H_PAIRKEY(dbp, p, ndx)) == H_OFFPAGE) {
+ memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(dbp, p, H_KEYINDEX(ndx))),
sizeof(db_pgno_t));
ret = __db_doff(dbc, pgno);
}
if (ret == 0)
- switch (HPAGE_PTYPE(H_PAIRDATA(p, ndx))) {
+ switch (HPAGE_PTYPE(H_PAIRDATA(dbp, p, ndx))) {
case H_OFFPAGE:
memcpy(&pgno,
- HOFFPAGE_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
+ HOFFPAGE_PGNO(P_ENTRY(dbp, p, H_DATAINDEX(ndx))),
sizeof(db_pgno_t));
ret = __db_doff(dbc, pgno);
break;
@@ -596,21 +600,21 @@ __ham_del_pair(dbc, reclaim_page)
return (ret);
/* Now log the delete off this page. */
- if (DB_LOGGING(dbc)) {
- key_dbt.data = P_ENTRY(p, H_KEYINDEX(ndx));
- key_dbt.size = LEN_HITEM(p, dbp->pgsize, H_KEYINDEX(ndx));
- data_dbt.data = P_ENTRY(p, H_DATAINDEX(ndx));
- data_dbt.size = LEN_HITEM(p, dbp->pgsize, H_DATAINDEX(ndx));
-
- if ((ret = __ham_insdel_log(dbenv,
- dbc->txn, &new_lsn, 0, DELPAIR,
- dbp->log_fileid, PGNO(p), (u_int32_t)ndx,
+ if (DBC_LOGGING(dbc)) {
+ key_dbt.data = P_ENTRY(dbp, p, H_KEYINDEX(ndx));
+ key_dbt.size = LEN_HITEM(dbp, p, dbp->pgsize, H_KEYINDEX(ndx));
+ data_dbt.data = P_ENTRY(dbp, p, H_DATAINDEX(ndx));
+ data_dbt.size = LEN_HITEM(dbp, p, dbp->pgsize, H_DATAINDEX(ndx));
+
+ if ((ret = __ham_insdel_log(dbp,
+ dbc->txn, &new_lsn, 0, DELPAIR, PGNO(p), (u_int32_t)ndx,
&LSN(p), &key_dbt, &data_dbt)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(p) = new_lsn;
- }
+ /* Move lsn onto page. */
+ LSN(p) = new_lsn;
/* Do the delete. */
__ham_dpair(dbp, p, ndx);
@@ -636,8 +640,11 @@ __ham_del_pair(dbc, reclaim_page)
* XXX
* Perhaps we can retain incremental numbers and apply them later.
*/
- if (!STD_LOCKING(dbc))
+ if (!STD_LOCKING(dbc)) {
--hcp->hdr->nelem;
+ if ((ret = __ham_dirty_meta(dbc)) != 0)
+ return (ret);
+ }
/*
* If we need to reclaim the page, then check if the page is empty.
@@ -650,43 +657,43 @@ __ham_del_pair(dbc, reclaim_page)
if (!reclaim_page ||
NUM_ENT(p) != 0 ||
(PREV_PGNO(p) == PGNO_INVALID && NEXT_PGNO(p) == PGNO_INVALID))
- return (memp_fset(dbp->mpf, p, DB_MPOOL_DIRTY));
+ return (mpf->set(mpf, p, DB_MPOOL_DIRTY));
if (PREV_PGNO(p) == PGNO_INVALID) {
/*
* First page in chain is empty and we know that there
* are more pages in the chain.
*/
- if ((ret =
- memp_fget(dbp->mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
+ if ((ret = mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
return (ret);
- if (NEXT_PGNO(n_pagep) != PGNO_INVALID &&
- (ret = memp_fget(dbp->mpf, &NEXT_PGNO(n_pagep), 0,
- &nn_pagep)) != 0)
+ if (NEXT_PGNO(n_pagep) != PGNO_INVALID && (ret =
+ mpf->get(mpf, &NEXT_PGNO(n_pagep), 0, &nn_pagep)) != 0)
goto err;
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
key_dbt.data = n_pagep;
key_dbt.size = dbp->pgsize;
- if ((ret = __ham_copypage_log(dbenv,
- dbc->txn, &new_lsn, 0, dbp->log_fileid, PGNO(p),
+ if ((ret = __ham_copypage_log(dbp,
+ dbc->txn, &new_lsn, 0, PGNO(p),
&LSN(p), PGNO(n_pagep), &LSN(n_pagep),
NEXT_PGNO(n_pagep),
nn_pagep == NULL ? NULL : &LSN(nn_pagep),
&key_dbt)) != 0)
goto err;
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ /* Move lsn onto page. */
+ LSN(p) = new_lsn; /* Structure assignment. */
+ LSN(n_pagep) = new_lsn;
+ if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
+ LSN(nn_pagep) = new_lsn;
- /* Move lsn onto page. */
- LSN(p) = new_lsn; /* Structure assignment. */
- LSN(n_pagep) = new_lsn;
- if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
- LSN(nn_pagep) = new_lsn;
- }
if (nn_pagep != NULL) {
PREV_PGNO(nn_pagep) = PGNO(p);
- if ((ret = memp_fput(dbp->mpf,
- nn_pagep, DB_MPOOL_DIRTY)) != 0) {
+ if ((ret =
+ mpf->put(mpf, nn_pagep, DB_MPOOL_DIRTY)) != 0) {
nn_pagep = NULL;
goto err;
}
@@ -703,26 +710,30 @@ __ham_del_pair(dbc, reclaim_page)
* Update cursors to reflect the fact that records
* on the second page have moved to the first page.
*/
- if ((ret = __ham_c_chgpg(dbc,
- PGNO(n_pagep), NDX_INVALID, PGNO(p), NDX_INVALID)) != 0)
- return (ret);
+ if ((ret = __ham_c_delpg(dbc, PGNO(n_pagep),
+ PGNO(p), 0, DB_HAM_DELFIRSTPG, &order)) != 0)
+ goto err;
/*
* Update the cursor to reflect its new position.
*/
hcp->indx = 0;
hcp->pgno = PGNO(p);
- if ((ret = memp_fset(dbp->mpf, p, DB_MPOOL_DIRTY)) != 0 ||
- (ret = __db_free(dbc, n_pagep)) != 0)
- return (ret);
+ hcp->order += order;
+
+ if ((ret = mpf->set(mpf, p, DB_MPOOL_DIRTY)) != 0)
+ goto err;
+ if ((ret = __db_free(dbc, n_pagep)) != 0) {
+ n_pagep = NULL;
+ goto err;
+ }
} else {
- if ((ret =
- memp_fget(dbp->mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
+ if ((ret = mpf->get(mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
goto err;
if (NEXT_PGNO(p) != PGNO_INVALID) {
- if ((ret = memp_fget(dbp->mpf,
- &NEXT_PGNO(p), 0, &n_pagep)) != 0)
+ if ((ret =
+ mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
goto err;
n_lsn = &LSN(n_pagep);
} else {
@@ -734,32 +745,40 @@ __ham_del_pair(dbc, reclaim_page)
if (n_pagep != NULL)
PREV_PGNO(n_pagep) = PGNO(p_pagep);
- if (DB_LOGGING(dbc)) {
- if ((ret = __ham_newpage_log(dbenv,
- dbc->txn, &new_lsn, 0, DELOVFL,
- dbp->log_fileid, PREV_PGNO(p), &LSN(p_pagep),
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __ham_newpage_log(dbp, dbc->txn,
+ &new_lsn, 0, DELOVFL, PREV_PGNO(p), &LSN(p_pagep),
PGNO(p), &LSN(p), NEXT_PGNO(p), n_lsn)) != 0)
goto err;
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ /* Move lsn onto page. */
+ LSN(p_pagep) = new_lsn; /* Structure assignment. */
+ if (n_pagep)
+ LSN(n_pagep) = new_lsn;
+ LSN(p) = new_lsn;
- /* Move lsn onto page. */
- LSN(p_pagep) = new_lsn; /* Structure assignment. */
- if (n_pagep)
- LSN(n_pagep) = new_lsn;
- LSN(p) = new_lsn;
- }
if (NEXT_PGNO(p) == PGNO_INVALID) {
/*
* There is no next page; put the cursor on the
* previous page as if we'd deleted the last item
- * on that page; index greater than number of
- * valid entries and H_DELETED set.
+ * on that page, with index after the last valid
+ * entry.
+ *
+ * The deleted flag was set up above.
*/
hcp->pgno = PGNO(p_pagep);
hcp->indx = NUM_ENT(p_pagep);
- F_SET(hcp, H_DELETED);
+ op = DB_HAM_DELLASTPG;
} else {
+ /*
+ * There is a next page, so put the cursor at
+ * the beginning of it.
+ */
hcp->pgno = NEXT_PGNO(p);
hcp->indx = 0;
+ op = DB_HAM_DELMIDPG;
}
/*
@@ -770,26 +789,28 @@ __ham_del_pair(dbc, reclaim_page)
hcp->page = NULL;
chg_pgno = PGNO(p);
ret = __db_free(dbc, p);
- if ((t_ret = memp_fput(dbp->mpf, p_pagep, DB_MPOOL_DIRTY)) != 0
- && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, p_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
- if (n_pagep != NULL && (t_ret = memp_fput(dbp->mpf,
- n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ if (n_pagep != NULL && (t_ret =
+ mpf->put(mpf, n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
- ret = __ham_c_chgpg(dbc,
- chg_pgno, 0, hcp->pgno, hcp->indx);
+ if ((ret = __ham_c_delpg(dbc,
+ chg_pgno, hcp->pgno, hcp->indx, op, &order)) != 0)
+ return (ret);
+ hcp->order += order;
}
return (ret);
err: /* Clean up any pages. */
if (n_pagep != NULL)
- (void)memp_fput(dbp->mpf, n_pagep, 0);
+ (void)mpf->put(mpf, n_pagep, 0);
if (nn_pagep != NULL)
- (void)memp_fput(dbp->mpf, nn_pagep, 0);
+ (void)mpf->put(mpf, nn_pagep, 0);
if (p_pagep != NULL)
- (void)memp_fput(dbp->mpf, p_pagep, 0);
+ (void)mpf->put(mpf, p_pagep, 0);
return (ret);
}
@@ -807,12 +828,13 @@ __ham_replpair(dbc, dbt, make_dup)
u_int32_t make_dup;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT old_dbt, tdata, tmp;
+ DB_ENV *dbenv;
DB_LSN new_lsn;
+ HASH_CURSOR *hcp;
int32_t change; /* XXX: Possible overflow. */
- u_int32_t dup, len, memsize;
- int is_big, ret, type;
+ u_int32_t dup_flag, len, memsize;
+ int beyond_eor, is_big, ret, type;
u_int8_t *beg, *dest, *end, *hk, *src;
void *memp;
@@ -828,6 +850,7 @@ __ham_replpair(dbc, dbt, make_dup)
* add.
*/
dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
hcp = (HASH_CURSOR *)dbc->internal;
/*
@@ -841,19 +864,21 @@ __ham_replpair(dbc, dbt, make_dup)
*/
change = dbt->size - dbt->dlen;
- hk = H_PAIRDATA(hcp->page, hcp->indx);
+ hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
is_big = HPAGE_PTYPE(hk) == H_OFFPAGE;
if (is_big)
memcpy(&len, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
else
- len = LEN_HKEYDATA(hcp->page,
+ len = LEN_HKEYDATA(dbp, hcp->page,
dbp->pgsize, H_DATAINDEX(hcp->indx));
- if (dbt->doff + dbt->dlen > len)
+ beyond_eor = dbt->doff + dbt->dlen > len;
+ if (beyond_eor)
change += dbt->doff + dbt->dlen - len;
- if (change > (int32_t)P_FREESPACE(hcp->page) || is_big) {
+ if (change > (int32_t)P_FREESPACE(dbp, hcp->page) ||
+ beyond_eor || is_big) {
/*
* Case 3 -- two subcases.
* A. This is not really a partial operation, but an overwrite.
@@ -868,16 +893,16 @@ __ham_replpair(dbc, dbt, make_dup)
memset(&tmp, 0, sizeof(tmp));
if ((ret =
__db_ret(dbp, hcp->page, H_KEYINDEX(hcp->indx),
- &tmp, &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
+ &tmp, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
return (ret);
/* Preserve duplicate info. */
- dup = F_ISSET(hcp, H_ISDUP);
+ dup_flag = F_ISSET(hcp, H_ISDUP);
if (dbt->doff == 0 && dbt->dlen == len) {
ret = __ham_del_pair(dbc, 0);
if (ret == 0)
ret = __ham_add_el(dbc,
- &tmp, dbt, dup ? H_DUPLICATE : H_KEYDATA);
+ &tmp, dbt, dup_flag ? H_DUPLICATE : H_KEYDATA);
} else { /* Case B */
type = HPAGE_PTYPE(hk) != H_OFFPAGE ?
HPAGE_PTYPE(hk) : H_KEYDATA;
@@ -891,15 +916,14 @@ __ham_replpair(dbc, dbt, make_dup)
/* Now we can delete the item. */
if ((ret = __ham_del_pair(dbc, 0)) != 0) {
- __os_free(memp, memsize);
+ __os_free(dbenv, memp);
goto err;
}
/* Now shift old data around to make room for new. */
if (change > 0) {
- if ((ret = __os_realloc(dbp->dbenv,
- tdata.size + change,
- NULL, &tdata.data)) != 0)
+ if ((ret = __os_realloc(dbenv,
+ tdata.size + change, &tdata.data)) != 0)
return (ret);
memp = tdata.data;
memsize = tdata.size + change;
@@ -920,9 +944,9 @@ __ham_replpair(dbc, dbt, make_dup)
/* Now add the pair. */
ret = __ham_add_el(dbc, &tmp, &tdata, type);
- __os_free(memp, memsize);
+ __os_free(dbenv, memp);
}
- F_SET(hcp, dup);
+ F_SET(hcp, dup_flag);
err: return (ret);
}
@@ -930,7 +954,7 @@ err: return (ret);
* Set up pointer into existing data. Do it before the log
* message so we can use it inside of the log setup.
*/
- beg = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx));
+ beg = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
beg += dbt->doff;
/*
@@ -938,20 +962,22 @@ err: return (ret);
* all the parameters here. Then log the call before moving
* anything around.
*/
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
old_dbt.data = beg;
old_dbt.size = dbt->dlen;
- if ((ret = __ham_replace_log(dbp->dbenv,
- dbc->txn, &new_lsn, 0, dbp->log_fileid, PGNO(hcp->page),
+ if ((ret = __ham_replace_log(dbp,
+ dbc->txn, &new_lsn, 0, PGNO(hcp->page),
(u_int32_t)H_DATAINDEX(hcp->indx), &LSN(hcp->page),
(u_int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0)
return (ret);
- LSN(hcp->page) = new_lsn; /* Structure assignment. */
- }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ LSN(hcp->page) = new_lsn; /* Structure assignment. */
- __ham_onpage_replace(hcp->page, dbp->pgsize,
- (u_int32_t)H_DATAINDEX(hcp->indx), (int32_t)dbt->doff, change, dbt);
+ __ham_onpage_replace(dbp, hcp->page, (u_int32_t)H_DATAINDEX(hcp->indx),
+ (int32_t)dbt->doff, change, dbt);
return (0);
}
@@ -967,34 +993,41 @@ err: return (ret);
* off: Offset at which we are beginning the replacement.
* change: the number of bytes (+ or -) that the element is growing/shrinking.
* dbt: the new data that gets written at beg.
- * PUBLIC: void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t,
- * PUBLIC: int32_t, DBT *));
+ *
+ * PUBLIC: void __ham_onpage_replace __P((DB *, PAGE *, u_int32_t,
+ * PUBLIC: int32_t, int32_t, DBT *));
*/
void
-__ham_onpage_replace(pagep, pgsize, ndx, off, change, dbt)
+__ham_onpage_replace(dbp, pagep, ndx, off, change, dbt)
+ DB *dbp;
PAGE *pagep;
- size_t pgsize;
u_int32_t ndx;
int32_t off;
int32_t change;
DBT *dbt;
{
- db_indx_t i;
+ db_indx_t i, *inp;
int32_t len;
+ size_t pgsize;
u_int8_t *src, *dest;
int zero_me;
+ pgsize = dbp->pgsize;
+ inp = P_INP(dbp, pagep);
if (change != 0) {
zero_me = 0;
src = (u_int8_t *)(pagep) + HOFFSET(pagep);
if (off < 0)
- len = pagep->inp[ndx] - HOFFSET(pagep);
- else if ((u_int32_t)off >= LEN_HKEYDATA(pagep, pgsize, ndx)) {
- len = HKEYDATA_DATA(P_ENTRY(pagep, ndx)) +
- LEN_HKEYDATA(pagep, pgsize, ndx) - src;
+ len = inp[ndx] - HOFFSET(pagep);
+ else if ((u_int32_t)off >=
+ LEN_HKEYDATA(dbp, pagep, pgsize, ndx)) {
+ len = (int32_t)(HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx))
+ + LEN_HKEYDATA(dbp, pagep, pgsize, ndx) - src);
zero_me = 1;
} else
- len = (HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + off) - src;
+ len = (int32_t)(
+ (HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx)) + off) -
+ src);
dest = src - change;
memmove(dest, src, len);
if (zero_me)
@@ -1002,14 +1035,14 @@ __ham_onpage_replace(pagep, pgsize, ndx, off, change, dbt)
/* Now update the indices. */
for (i = ndx; i < NUM_ENT(pagep); i++)
- pagep->inp[i] -= change;
+ inp[i] -= change;
HOFFSET(pagep) -= change;
}
if (off >= 0)
- memcpy(HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + off,
+ memcpy(HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx)) + off,
dbt->data, dbt->size);
else
- memcpy(P_ENTRY(pagep, ndx), dbt->data, dbt->size);
+ memcpy(P_ENTRY(dbp, pagep, ndx), dbt->data, dbt->size);
}
/*
@@ -1022,10 +1055,12 @@ __ham_split_page(dbc, obucket, nbucket)
{
DB *dbp;
DBC **carray;
- HASH_CURSOR *hcp, *cp;
DBT key, page_dbt;
DB_ENV *dbenv;
+ DB_LOCK block;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp, *cp;
PAGE **pp, *old_pagep, *temp_pagep, *new_pagep;
db_indx_t n;
db_pgno_t bucket_pgno, npgno, next_pgno;
@@ -1034,22 +1069,24 @@ __ham_split_page(dbc, obucket, nbucket)
void *big_buf;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ hcp = (HASH_CURSOR *)dbc->internal;
temp_pagep = old_pagep = new_pagep = NULL;
-
- if ((ret = __ham_get_clist(dbp, obucket, NDX_INVALID, &carray)) != 0)
- return (ret);
+ carray = NULL;
+ LOCK_INIT(block);
bucket_pgno = BUCKET_TO_PAGE(hcp, obucket);
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = __db_lget(dbc,
+ 0, bucket_pgno, DB_LOCK_WRITE, 0, &block)) != 0)
+ goto err;
+ if ((ret = mpf->get(mpf,
&bucket_pgno, DB_MPOOL_CREATE, &old_pagep)) != 0)
goto err;
/* Properly initialize the new bucket page. */
npgno = BUCKET_TO_PAGE(hcp, nbucket);
- if ((ret = memp_fget(dbp->mpf,
- &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
+ if ((ret = mpf->get(mpf, &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
goto err;
P_INIT(new_pagep,
dbp->pgsize, npgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
@@ -1057,33 +1094,35 @@ __ham_split_page(dbc, obucket, nbucket)
temp_pagep = hcp->split_buf;
memcpy(temp_pagep, old_pagep, dbp->pgsize);
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
page_dbt.size = dbp->pgsize;
page_dbt.data = old_pagep;
- if ((ret = __ham_splitdata_log(dbenv,
- dbc->txn, &new_lsn, 0, dbp->log_fileid, SPLITOLD,
+ if ((ret = __ham_splitdata_log(dbp,
+ dbc->txn, &new_lsn, 0, SPLITOLD,
PGNO(old_pagep), &page_dbt, &LSN(old_pagep))) != 0)
goto err;
- }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ LSN(old_pagep) = new_lsn; /* Structure assignment. */
P_INIT(old_pagep, dbp->pgsize, PGNO(old_pagep), PGNO_INVALID,
PGNO_INVALID, 0, P_HASH);
- if (DB_LOGGING(dbc))
- LSN(old_pagep) = new_lsn; /* Structure assignment. */
-
big_len = 0;
big_buf = NULL;
key.flags = 0;
while (temp_pagep != NULL) {
+ if ((ret = __ham_get_clist(dbp,
+ PGNO(temp_pagep), NDX_INVALID, &carray)) != 0)
+ goto err;
+
for (n = 0; n < (db_indx_t)NUM_ENT(temp_pagep); n += 2) {
- if ((ret =
- __db_ret(dbp, temp_pagep, H_KEYINDEX(n),
- &key, &big_buf, &big_len)) != 0)
+ if ((ret = __db_ret(dbp, temp_pagep,
+ H_KEYINDEX(n), &key, &big_buf, &big_len)) != 0)
goto err;
- if (__ham_call_hash(dbc, key.data, key.size)
- == obucket)
+ if (__ham_call_hash(dbc, key.data, key.size) == obucket)
pp = &old_pagep;
else
pp = &new_pagep;
@@ -1092,25 +1131,24 @@ __ham_split_page(dbc, obucket, nbucket)
* Figure out how many bytes we need on the new
* page to store the key/data pair.
*/
-
- len = LEN_HITEM(temp_pagep, dbp->pgsize,
+ len = LEN_HITEM(dbp, temp_pagep, dbp->pgsize,
H_DATAINDEX(n)) +
- LEN_HITEM(temp_pagep, dbp->pgsize,
+ LEN_HITEM(dbp, temp_pagep, dbp->pgsize,
H_KEYINDEX(n)) +
2 * sizeof(db_indx_t);
- if (P_FREESPACE(*pp) < len) {
- if (DB_LOGGING(dbc)) {
+ if (P_FREESPACE(dbp, *pp) < len) {
+ if (DBC_LOGGING(dbc)) {
page_dbt.size = dbp->pgsize;
page_dbt.data = *pp;
- if ((ret = __ham_splitdata_log(
- dbenv, dbc->txn,
- &new_lsn, 0, dbp->log_fileid,
+ if ((ret = __ham_splitdata_log(dbp,
+ dbc->txn, &new_lsn, 0,
SPLITNEW, PGNO(*pp), &page_dbt,
&LSN(*pp))) != 0)
goto err;
- LSN(*pp) = new_lsn;
- }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+ LSN(*pp) = new_lsn;
if ((ret =
__ham_add_ovflpage(dbc, *pp, 1, pp)) != 0)
goto err;
@@ -1122,28 +1160,25 @@ __ham_split_page(dbc, obucket, nbucket)
for (i = 0; carray[i] != NULL; i++) {
cp =
(HASH_CURSOR *)carray[i]->internal;
- if (cp->pgno == PGNO(temp_pagep)
- && cp->indx == n) {
+ if (cp->pgno == PGNO(temp_pagep) &&
+ cp->indx == n) {
cp->pgno = PGNO(*pp);
cp->indx = NUM_ENT(*pp);
found = 1;
}
}
- if (found && DB_LOGGING(dbc)
- && IS_SUBTRANSACTION(dbc->txn)) {
+ if (found && DBC_LOGGING(dbc) &&
+ IS_SUBTRANSACTION(dbc->txn)) {
if ((ret =
- __ham_chgpg_log(dbp->dbenv,
+ __ham_chgpg_log(dbp,
dbc->txn, &new_lsn, 0,
- dbp->log_fileid,
DB_HAM_SPLIT, PGNO(temp_pagep),
PGNO(*pp), n, NUM_ENT(*pp))) != 0)
goto err;
}
}
- __ham_copy_item(dbp->pgsize,
- temp_pagep, H_KEYINDEX(n), *pp);
- __ham_copy_item(dbp->pgsize,
- temp_pagep, H_DATAINDEX(n), *pp);
+ __ham_copy_item(dbp, temp_pagep, H_KEYINDEX(n), *pp);
+ __ham_copy_item(dbp, temp_pagep, H_DATAINDEX(n), *pp);
}
next_pgno = NEXT_PGNO(temp_pagep);
@@ -1156,23 +1191,30 @@ __ham_split_page(dbc, obucket, nbucket)
if (next_pgno == PGNO_INVALID)
temp_pagep = NULL;
- else if ((ret = memp_fget(dbp->mpf,
- &next_pgno, DB_MPOOL_CREATE, &temp_pagep)) != 0)
+ else if ((ret = mpf->get(
+ mpf, &next_pgno, DB_MPOOL_CREATE, &temp_pagep)) != 0)
goto err;
- if (temp_pagep != NULL && DB_LOGGING(dbc)) {
- page_dbt.size = dbp->pgsize;
- page_dbt.data = temp_pagep;
- if ((ret = __ham_splitdata_log(dbenv,
- dbc->txn, &new_lsn, 0, dbp->log_fileid,
- SPLITOLD, PGNO(temp_pagep),
- &page_dbt, &LSN(temp_pagep))) != 0)
- goto err;
+ if (temp_pagep != NULL) {
+ if (DBC_LOGGING(dbc)) {
+ page_dbt.size = dbp->pgsize;
+ page_dbt.data = temp_pagep;
+ if ((ret = __ham_splitdata_log(dbp,
+ dbc->txn, &new_lsn, 0,
+ SPLITOLD, PGNO(temp_pagep),
+ &page_dbt, &LSN(temp_pagep))) != 0)
+ goto err;
+ } else
+ LSN_NOT_LOGGED(new_lsn);
LSN(temp_pagep) = new_lsn;
}
+
+ if (carray != NULL) /* We never knew its size. */
+ __os_free(dbenv, carray);
+ carray = NULL;
}
if (big_buf != NULL)
- __os_free(big_buf, big_len);
+ __os_free(dbenv, big_buf);
/*
* If the original bucket spanned multiple pages, then we've got
@@ -1188,37 +1230,43 @@ __ham_split_page(dbc, obucket, nbucket)
/*
* Write new buckets out.
*/
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
page_dbt.size = dbp->pgsize;
page_dbt.data = old_pagep;
- if ((ret = __ham_splitdata_log(dbenv, dbc->txn, &new_lsn, 0,
- dbp->log_fileid, SPLITNEW, PGNO(old_pagep), &page_dbt,
+ if ((ret = __ham_splitdata_log(dbp, dbc->txn,
+ &new_lsn, 0, SPLITNEW, PGNO(old_pagep), &page_dbt,
&LSN(old_pagep))) != 0)
goto err;
LSN(old_pagep) = new_lsn;
page_dbt.data = new_pagep;
- if ((ret = __ham_splitdata_log(dbenv, dbc->txn, &new_lsn, 0,
- dbp->log_fileid, SPLITNEW, PGNO(new_pagep), &page_dbt,
+ if ((ret = __ham_splitdata_log(dbp, dbc->txn, &new_lsn, 0,
+ SPLITNEW, PGNO(new_pagep), &page_dbt,
&LSN(new_pagep))) != 0)
goto err;
LSN(new_pagep) = new_lsn;
+ } else {
+ LSN_NOT_LOGGED(LSN(old_pagep));
+ LSN_NOT_LOGGED(LSN(new_pagep));
}
- ret = memp_fput(dbp->mpf, old_pagep, DB_MPOOL_DIRTY);
- if ((t_ret = memp_fput(dbp->mpf, new_pagep, DB_MPOOL_DIRTY)) != 0
- && ret == 0)
+
+ ret = mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
+ if ((t_ret =
+ mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if (0) {
err: if (old_pagep != NULL)
- (void)memp_fput(dbp->mpf, old_pagep, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
if (new_pagep != NULL)
- (void)memp_fput(dbp->mpf, new_pagep, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY);
if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno)
- (void)memp_fput(dbp->mpf, temp_pagep, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, temp_pagep, DB_MPOOL_DIRTY);
}
+ if (LOCK_ISSET(block))
+ __TLPUT(dbc, block);
if (carray != NULL) /* We never knew its size. */
- __os_free(carray, 0);
+ __os_free(dbenv, carray);
return (ret);
}
@@ -1237,11 +1285,12 @@ __ham_add_el(dbc, key, val, type)
const DBT *key, *val;
int type;
{
- DB *dbp;
- HASH_CURSOR *hcp;
const DBT *pkey, *pdata;
+ DB *dbp;
DBT key_dbt, data_dbt;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
HOFFPAGE doff, koff;
db_pgno_t next_pgno, pgno;
u_int32_t data_size, key_size, pairsize, rectype;
@@ -1249,13 +1298,14 @@ __ham_add_el(dbc, key, val, type)
int key_type, data_type;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
do_expand = 0;
- pgno = hcp->seek_found_page != PGNO_INVALID ? hcp->seek_found_page :
- hcp->pgno;
- if (hcp->page == NULL && (ret = memp_fget(dbp->mpf, &pgno,
- DB_MPOOL_CREATE, &hcp->page)) != 0)
+ pgno = hcp->seek_found_page != PGNO_INVALID ?
+ hcp->seek_found_page : hcp->pgno;
+ if (hcp->page == NULL &&
+ (ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
return (ret);
key_size = HKEYDATA_PSIZE(key->size);
@@ -1276,21 +1326,20 @@ __ham_add_el(dbc, key, val, type)
* anyway. Check if it's a bigpair that fits or a regular
* pair that fits.
*/
- if (P_FREESPACE(hcp->page) >= pairsize)
+ if (P_FREESPACE(dbp, hcp->page) >= pairsize)
break;
next_pgno = NEXT_PGNO(hcp->page);
- if ((ret =
- __ham_next_cpage(dbc, next_pgno, 0)) != 0)
+ if ((ret = __ham_next_cpage(dbc, next_pgno, 0)) != 0)
return (ret);
}
/*
* Check if we need to allocate a new page.
*/
- if (P_FREESPACE(hcp->page) < pairsize) {
+ if (P_FREESPACE(dbp, hcp->page) < pairsize) {
do_expand = 1;
if ((ret = __ham_add_ovflpage(dbc,
- (PAGE *)hcp->page, 1, (PAGE **)&hcp->page)) != 0)
+ (PAGE *)hcp->page, 1, (PAGE **)&hcp->page)) != 0)
return (ret);
hcp->pgno = PGNO(hcp->page);
}
@@ -1334,7 +1383,7 @@ __ham_add_el(dbc, key, val, type)
data_type = type;
}
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
rectype = PUTPAIR;
if (is_databig)
rectype |= PAIR_DATAMASK;
@@ -1343,18 +1392,18 @@ __ham_add_el(dbc, key, val, type)
if (type == H_DUPLICATE)
rectype |= PAIR_DUPMASK;
- if ((ret = __ham_insdel_log(dbp->dbenv, dbc->txn, &new_lsn, 0,
- rectype, dbp->log_fileid, PGNO(hcp->page),
- (u_int32_t)NUM_ENT(hcp->page), &LSN(hcp->page), pkey,
- pdata)) != 0)
+ if ((ret = __ham_insdel_log(dbp, dbc->txn, &new_lsn, 0,
+ rectype, PGNO(hcp->page), (u_int32_t)NUM_ENT(hcp->page),
+ &LSN(hcp->page), pkey, pdata)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(hcp->page) = new_lsn; /* Structure assignment. */
- }
+ /* Move lsn onto page. */
+ LSN(hcp->page) = new_lsn; /* Structure assignment. */
- __ham_putitem(hcp->page, pkey, key_type);
- __ham_putitem(hcp->page, pdata, data_type);
+ __ham_putitem(dbp, hcp->page, pkey, key_type);
+ __ham_putitem(dbp, hcp->page, pdata, data_type);
/*
* For splits, we are going to update item_info's page number
@@ -1369,8 +1418,11 @@ __ham_add_el(dbc, key, val, type)
* XXX
* Maybe keep incremental numbers here.
*/
- if (!STD_LOCKING(dbc))
+ if (!STD_LOCKING(dbc)) {
hcp->hdr->nelem++;
+ if ((ret = __ham_dirty_meta(dbc)) != 0)
+ return (ret);
+ }
if (do_expand || (hcp->hdr->ffactor != 0 &&
(u_int32_t)H_NUMPAIRS(hcp->page) > hcp->hdr->ffactor))
@@ -1384,28 +1436,32 @@ __ham_add_el(dbc, key, val, type)
* H_DUPLICATE, H_OFFDUP). Since we log splits at a high level, we
* do not need to do any logging here.
*
- * PUBLIC: void __ham_copy_item __P((size_t, PAGE *, u_int32_t, PAGE *));
+ * PUBLIC: void __ham_copy_item __P((DB *, PAGE *, u_int32_t, PAGE *));
*/
void
-__ham_copy_item(pgsize, src_page, src_ndx, dest_page)
- size_t pgsize;
+__ham_copy_item(dbp, src_page, src_ndx, dest_page)
+ DB *dbp;
PAGE *src_page;
u_int32_t src_ndx;
PAGE *dest_page;
{
u_int32_t len;
+ size_t pgsize;
void *src, *dest;
+ db_indx_t *inp;
+ pgsize = dbp->pgsize;
+ inp = P_INP(dbp, dest_page);
/*
* Copy the key and data entries onto this new page.
*/
- src = P_ENTRY(src_page, src_ndx);
+ src = P_ENTRY(dbp, src_page, src_ndx);
/* Set up space on dest. */
- len = LEN_HITEM(src_page, pgsize, src_ndx);
+ len = (u_int32_t)LEN_HITEM(dbp, src_page, pgsize, src_ndx);
HOFFSET(dest_page) -= len;
- dest_page->inp[NUM_ENT(dest_page)] = HOFFSET(dest_page);
- dest = P_ENTRY(dest_page, NUM_ENT(dest_page));
+ inp[NUM_ENT(dest_page)] = HOFFSET(dest_page);
+ dest = P_ENTRY(dbp, dest_page, NUM_ENT(dest_page));
NUM_ENT(dest_page)++;
memcpy(dest, src, len);
@@ -1414,8 +1470,8 @@ __ham_copy_item(pgsize, src_page, src_ndx, dest_page)
/*
*
* Returns:
- * pointer on success
- * NULL on error
+ * pointer on success
+ * NULL on error
*
* PUBLIC: int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **));
*/
@@ -1427,31 +1483,33 @@ __ham_add_ovflpage(dbc, pagep, release, pp)
PAGE **pp;
{
DB *dbp;
- HASH_CURSOR *hcp;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
PAGE *new_pagep;
int ret;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
+ mpf = dbp->mpf;
if ((ret = __db_new(dbc, P_HASH, &new_pagep)) != 0)
return (ret);
- if (DB_LOGGING(dbc)) {
- if ((ret = __ham_newpage_log(dbp->dbenv, dbc->txn, &new_lsn, 0,
- PUTOVFL, dbp->log_fileid, PGNO(pagep), &LSN(pagep),
+ if (DBC_LOGGING(dbc)) {
+ if ((ret = __ham_newpage_log(dbp, dbc->txn, &new_lsn, 0,
+ PUTOVFL, PGNO(pagep), &LSN(pagep),
PGNO(new_pagep), &LSN(new_pagep), PGNO_INVALID, NULL)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(pagep) = LSN(new_pagep) = new_lsn;
- }
+ /* Move lsn onto page. */
+ LSN(pagep) = LSN(new_pagep) = new_lsn;
NEXT_PGNO(pagep) = PGNO(new_pagep);
+
PREV_PGNO(new_pagep) = PGNO(pagep);
if (release)
- ret = memp_fput(dbp->mpf, pagep, DB_MPOOL_DIRTY);
+ ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY);
*pp = new_pagep;
return (ret);
@@ -1467,10 +1525,12 @@ __ham_get_cpage(dbc, mode)
{
DB *dbp;
DB_LOCK tmp_lock;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
ret = 0;
@@ -1485,25 +1545,22 @@ __ham_get_cpage(dbc, mode)
* 4. If there is a lock, but it's for a different bucket, then we need
* to release the existing lock and get a new lock.
*/
- tmp_lock.off = LOCK_INVALID;
+ LOCK_INIT(tmp_lock);
if (STD_LOCKING(dbc)) {
- if (hcp->lock.off != LOCK_INVALID &&
- hcp->lbucket != hcp->bucket) { /* Case 4 */
- if (dbc->txn == NULL &&
- (ret = lock_put(dbp->dbenv, &hcp->lock)) != 0)
- return (ret);
- hcp->lock.off = LOCK_INVALID;
- }
- if ((hcp->lock.off != LOCK_INVALID &&
+ if (hcp->lbucket != hcp->bucket && /* Case 4 */
+ (ret = __TLPUT(dbc, hcp->lock)) != 0)
+ return (ret);
+
+ if ((LOCK_ISSET(hcp->lock) &&
(hcp->lock_mode == DB_LOCK_READ &&
mode == DB_LOCK_WRITE))) {
/* Case 3. */
tmp_lock = hcp->lock;
- hcp->lock.off = LOCK_INVALID;
+ LOCK_INIT(hcp->lock);
}
/* Acquire the lock. */
- if (hcp->lock.off == LOCK_INVALID)
+ if (!LOCK_ISSET(hcp->lock))
/* Cases 1, 3, and 4. */
if ((ret = __ham_lock_bucket(dbc, mode)) != 0)
return (ret);
@@ -1511,17 +1568,18 @@ __ham_get_cpage(dbc, mode)
if (ret == 0) {
hcp->lock_mode = mode;
hcp->lbucket = hcp->bucket;
- if (tmp_lock.off != LOCK_INVALID)
+ if (LOCK_ISSET(tmp_lock))
/* Case 3: release the original lock. */
- ret = lock_put(dbp->dbenv, &tmp_lock);
- } else if (tmp_lock.off != LOCK_INVALID)
+ ret =
+ dbp->dbenv->lock_put(dbp->dbenv, &tmp_lock);
+ } else if (LOCK_ISSET(tmp_lock))
hcp->lock = tmp_lock;
}
if (ret == 0 && hcp->page == NULL) {
if (hcp->pgno == PGNO_INVALID)
hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = mpf->get(mpf,
&hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
return (ret);
}
@@ -1543,18 +1601,21 @@ __ham_next_cpage(dbc, pgno, dirty)
int dirty;
{
DB *dbp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
PAGE *p;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
- if (hcp->page != NULL && (ret = memp_fput(dbp->mpf,
- hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
+ if (hcp->page != NULL &&
+ (ret = mpf->put(mpf, hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
return (ret);
+ hcp->page = NULL;
- if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
return (ret);
hcp->page = p;
@@ -1576,7 +1637,7 @@ __ham_lock_bucket(dbc, mode)
db_lockmode_t mode;
{
HASH_CURSOR *hcp;
- u_int32_t flags;
+ db_pgno_t pgno;
int gotmeta, ret;
hcp = (HASH_CURSOR *)dbc->internal;
@@ -1584,17 +1645,12 @@ __ham_lock_bucket(dbc, mode)
if (gotmeta)
if ((ret = __ham_get_meta(dbc)) != 0)
return (ret);
- dbc->lock.pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
+ pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
if (gotmeta)
if ((ret = __ham_release_meta(dbc)) != 0)
return (ret);
- flags = 0;
- if (DB_NONBLOCK(dbc))
- LF_SET(DB_LOCK_NOWAIT);
-
- ret = lock_get(dbc->dbp->dbenv,
- dbc->locker, flags, &dbc->lock_dbt, mode, &hcp->lock);
+ ret = __db_lget(dbc, 0, pgno, mode, 0, &hcp->lock);
hcp->lock_mode = mode;
return (ret);
@@ -1606,6 +1662,9 @@ __ham_lock_bucket(dbc, mode)
* represents. The caller is responsible for freeing up duplicates
* or offpage entries that might be referenced by this pair.
*
+ * Recovery assumes that this may be called without the metadata
+ * page pinned.
+ *
* PUBLIC: void __ham_dpair __P((DB *, PAGE *, u_int32_t));
*/
void
@@ -1614,15 +1673,16 @@ __ham_dpair(dbp, p, indx)
PAGE *p;
u_int32_t indx;
{
- db_indx_t delta, n;
+ db_indx_t delta, n, *inp;
u_int8_t *dest, *src;
+ inp = P_INP(dbp, p);
/*
* Compute "delta", the amount we have to shift all of the
* offsets. To find the delta, we just need to calculate
* the size of the pair of elements we are removing.
*/
- delta = H_PAIRSIZE(p, dbp->pgsize, indx);
+ delta = H_PAIRSIZE(dbp, p, dbp->pgsize, indx);
/*
* The hard case: we want to remove something other than
@@ -1641,7 +1701,7 @@ __ham_dpair(dbp, p, indx)
* be an overlapping copy, so we have to use memmove.
*/
dest = src + delta;
- memmove(dest, src, p->inp[H_DATAINDEX(indx)] - HOFFSET(p));
+ memmove(dest, src, inp[H_DATAINDEX(indx)] - HOFFSET(p));
}
/* Adjust page metadata. */
@@ -1650,6 +1710,153 @@ __ham_dpair(dbp, p, indx)
/* Adjust the offsets. */
for (n = (db_indx_t)indx; n < (db_indx_t)(NUM_ENT(p)); n++)
- p->inp[n] = p->inp[n + 2] + delta;
+ inp[n] = inp[n + 2] + delta;
+
+}
+
+/*
+ * __ham_c_delpg --
+ *
+ * Adjust the cursors after we've emptied a page in a bucket, taking
+ * care that when we move cursors pointing to deleted items, their
+ * orders don't collide with the orders of cursors on the page we move
+ * them to (since after this function is called, cursors with the same
+ * index on the two pages will be otherwise indistinguishable--they'll
+ * all have pgno new_pgno). There are three cases:
+ *
+ * 1) The emptied page is the first page in the bucket. In this
+ * case, we've copied all the items from the second page into the
+ * first page, so the first page is new_pgno and the second page is
+ * old_pgno. new_pgno is empty, but can have deleted cursors
+ * pointing at indx 0, so we need to be careful of the orders
+ * there. This is DB_HAM_DELFIRSTPG.
+ *
+ * 2) The page is somewhere in the middle of a bucket. Our caller
+ * can just delete such a page, so it's old_pgno. old_pgno is
+ * empty, but may have deleted cursors pointing at indx 0, so we
+ * need to be careful of indx 0 when we move those cursors to
+ * new_pgno. This is DB_HAM_DELMIDPG.
+ *
+ * 3) The page is the last in a bucket. Again the empty page is
+ * old_pgno, and again it should only have cursors that are deleted
+ * and at indx == 0. This time, though, there's no next page to
+ * move them to, so we set them to indx == num_ent on the previous
+ * page--and indx == num_ent is the index whose cursors we need to
+ * be careful of. This is DB_HAM_DELLASTPG.
+ */
+static int
+__ham_c_delpg(dbc, old_pgno, new_pgno, num_ent, op, orderp)
+ DBC *dbc;
+ db_pgno_t old_pgno, new_pgno;
+ u_int32_t num_ent;
+ db_ham_mode op;
+ u_int32_t *orderp;
+{
+ DB *dbp, *ldbp;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_TXN *my_txn;
+ DBC *cp;
+ HASH_CURSOR *hcp;
+ int found, ret;
+ db_indx_t indx;
+ u_int32_t order;
+
+ /* Which is the worrisome index? */
+ indx = (op == DB_HAM_DELLASTPG) ? num_ent : 0;
+ dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
+
+ my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL;
+ found = 0;
+
+ MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+ /*
+ * Find the highest order of any cursor our movement
+ * may collide with.
+ */
+ order = 1;
+ for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+ ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+ ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+ for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
+ cp = TAILQ_NEXT(cp, links)) {
+ if (cp == dbc || cp->dbtype != DB_HASH)
+ continue;
+ hcp = (HASH_CURSOR *)cp->internal;
+ if (hcp->pgno == new_pgno) {
+ if (hcp->indx == indx &&
+ F_ISSET(hcp, H_DELETED) &&
+ hcp->order >= order)
+ order = hcp->order + 1;
+ DB_ASSERT(op != DB_HAM_DELFIRSTPG ||
+ hcp->indx == NDX_INVALID ||
+ (hcp->indx == 0 &&
+ F_ISSET(hcp, H_DELETED)));
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+ }
+
+ for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+ ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+ ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+ for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
+ cp = TAILQ_NEXT(cp, links)) {
+ if (cp == dbc || cp->dbtype != DB_HASH)
+ continue;
+
+ hcp = (HASH_CURSOR *)cp->internal;
+
+ if (hcp->pgno == old_pgno) {
+ switch (op) {
+ case DB_HAM_DELFIRSTPG:
+ /*
+ * We're moving all items,
+ * regardless of index.
+ */
+ hcp->pgno = new_pgno;
+
+ /*
+ * But we have to be careful of
+ * the order values.
+ */
+ if (hcp->indx == indx)
+ hcp->order += order;
+ break;
+ case DB_HAM_DELMIDPG:
+ hcp->pgno = new_pgno;
+ DB_ASSERT(hcp->indx == 0 &&
+ F_ISSET(hcp, H_DELETED));
+ hcp->order += order;
+ break;
+ case DB_HAM_DELLASTPG:
+ hcp->pgno = new_pgno;
+ DB_ASSERT(hcp->indx == 0 &&
+ F_ISSET(hcp, H_DELETED));
+ hcp->indx = indx;
+ hcp->order += order;
+ break;
+ default:
+ DB_ASSERT(0);
+ return (__db_panic(dbenv, EINVAL));
+ }
+ if (my_txn != NULL && cp->txn != my_txn)
+ found = 1;
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+ if (found != 0 && DBC_LOGGING(dbc)) {
+ if ((ret = __ham_chgpg_log(dbp, my_txn, &lsn, 0, op,
+ old_pgno, new_pgno, indx, order)) != 0)
+ return (ret);
+ }
+ *orderp = order;
+ return (0);
}
diff --git a/bdb/hash/hash_rec.c b/bdb/hash/hash_rec.c
index ded58c281e9..24d3473c508 100644
--- a/bdb/hash/hash_rec.c
+++ b/bdb/hash/hash_rec.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_rec.c,v 11.34 2001/01/11 18:19:52 bostic Exp $";
+static const char revid[] = "$Id: hash_rec.c,v 11.69 2002/09/03 14:12:49 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -53,15 +53,12 @@ static const char revid[] = "$Id: hash_rec.c,v 11.34 2001/01/11 18:19:52 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "hash.h"
-#include "lock.h"
-#include "log.h"
-#include "mp.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
-static int __ham_alloc_pages __P((DB *, __ham_groupalloc_args *));
+static int __ham_alloc_pages __P((DB *, __ham_groupalloc_args *, DB_LSN *));
/*
* __ham_insdel_recover --
@@ -82,16 +79,16 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
- u_int32_t opcode;
- int cmp_n, cmp_p, flags, getmeta, ret, type;
+ u_int32_t flags, opcode;
+ int cmp_n, cmp_p, ret, type;
+ pagep = NULL;
COMPQUIET(info, NULL);
- getmeta = 0;
REC_PRINT(__ham_insdel_print);
REC_INTRO(__ham_insdel_read, 1);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -100,15 +97,11 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
* don't bother creating a page.
*/
goto done;
- } else if ((ret = memp_fget(mpf, &argp->pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto out;
- getmeta = 1;
-
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
@@ -135,7 +128,7 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
*/
if (opcode != DELPAIR ||
argp->ndx == (u_int32_t)NUM_ENT(pagep)) {
- __ham_putitem(pagep, &argp->key,
+ __ham_putitem(file_dbp, pagep, &argp->key,
DB_UNDO(op) || PAIR_ISKEYBIG(argp->opcode) ?
H_OFFPAGE : H_KEYDATA);
@@ -145,31 +138,32 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
type = H_OFFPAGE;
else
type = H_KEYDATA;
- __ham_putitem(pagep, &argp->data, type);
+ __ham_putitem(file_dbp, pagep, &argp->data, type);
} else
- (void)__ham_reputpair(pagep, file_dbp->pgsize,
+ (void)__ham_reputpair(file_dbp, pagep,
argp->ndx, &argp->key, &argp->data);
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
flags = DB_MPOOL_DIRTY;
- } else if ((opcode == DELPAIR && cmp_p == 0 && DB_REDO(op))
- || (opcode == PUTPAIR && cmp_n == 0 && DB_UNDO(op))) {
+ } else if ((opcode == DELPAIR && cmp_p == 0 && DB_REDO(op)) ||
+ (opcode == PUTPAIR && cmp_n == 0 && DB_UNDO(op))) {
/* Need to undo a put or redo a delete. */
__ham_dpair(file_dbp, pagep, argp->ndx);
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
flags = DB_MPOOL_DIRTY;
}
- if ((ret = memp_fput(file_dbp->mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
/* Return the previous LSN. */
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: if (getmeta)
- (void)__ham_release_meta(dbc);
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
REC_CLOSE;
}
@@ -194,15 +188,16 @@ __ham_newpage_recover(dbenv, dbtp, lsnp, op, info)
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
- int cmp_n, cmp_p, flags, getmeta, ret;
+ u_int32_t flags;
+ int cmp_n, cmp_p, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
- getmeta = 0;
REC_PRINT(__ham_newpage_print);
REC_INTRO(__ham_newpage_read, 1);
- if ((ret = memp_fget(mpf, &argp->new_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->new_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -212,15 +207,11 @@ __ham_newpage_recover(dbenv, dbtp, lsnp, op, info)
*/
ret = 0;
goto ppage;
- } else if ((ret = memp_fget(mpf, &argp->new_pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->new_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto out;
- getmeta = 1;
-
/*
* There are potentially three pages we need to check: the one
* that we created/deleted, the one before it and the one after
@@ -250,12 +241,13 @@ __ham_newpage_recover(dbenv, dbtp, lsnp, op, info)
if (flags)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
- if ((ret = memp_fput(file_dbp->mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
/* Now do the prev page. */
ppage: if (argp->prev_pgno != PGNO_INVALID) {
- if ((ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist.
@@ -265,9 +257,8 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
*/
ret = 0;
goto npage;
- } else if ((ret =
- memp_fget(mpf, &argp->prev_pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->prev_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -281,7 +272,8 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
/* Redo a create new page or undo a delete new page. */
pagep->next_pgno = argp->new_pgno;
flags = DB_MPOOL_DIRTY;
- } else if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DELOVFL) ||
+ } else if ((cmp_p == 0 &&
+ DB_REDO(op) && argp->opcode == DELOVFL) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == PUTOVFL)) {
/* Redo a delete or undo a create new page. */
pagep->next_pgno = argp->next_pgno;
@@ -291,13 +283,14 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
if (flags)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
- if ((ret = memp_fput(file_dbp->mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
}
/* Now time to do the next page */
npage: if (argp->next_pgno != PGNO_INVALID) {
- if ((ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist.
@@ -306,9 +299,8 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
* this case, don't bother creating a page.
*/
goto done;
- } else if ((ret =
- memp_fget(mpf, &argp->next_pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->next_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -322,7 +314,8 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
/* Redo a create new page or undo a delete new page. */
pagep->prev_pgno = argp->new_pgno;
flags = DB_MPOOL_DIRTY;
- } else if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DELOVFL) ||
+ } else if ((cmp_p == 0 &&
+ DB_REDO(op) && argp->opcode == DELOVFL) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == PUTOVFL)) {
/* Redo a delete or undo a create new page. */
pagep->prev_pgno = argp->prev_pgno;
@@ -332,14 +325,15 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
if (flags)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
- if ((ret = memp_fput(file_dbp->mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
}
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: if (getmeta)
- (void)__ham_release_meta(dbc);
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
REC_CLOSE;
}
@@ -366,17 +360,18 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf;
DBT dbt;
PAGE *pagep;
+ u_int32_t flags;
int32_t grow;
- int cmp_n, cmp_p, flags, getmeta, ret;
+ int cmp_n, cmp_p, ret;
u_int8_t *hk;
+ pagep = NULL;
COMPQUIET(info, NULL);
- getmeta = 0;
REC_PRINT(__ham_replace_print);
REC_INTRO(__ham_replace_read, 1);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -385,15 +380,11 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
* don't bother creating a page.
*/
goto done;
- } else if ((ret = memp_fget(mpf, &argp->pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto out;
- getmeta = 1;
-
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
@@ -419,10 +410,10 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
}
if (flags) {
- __ham_onpage_replace(pagep,
- file_dbp->pgsize, argp->ndx, argp->off, grow, &dbt);
+ __ham_onpage_replace(file_dbp, pagep,
+ argp->ndx, argp->off, grow, &dbt);
if (argp->makedup) {
- hk = P_ENTRY(pagep, argp->ndx);
+ hk = P_ENTRY(file_dbp, pagep, argp->ndx);
if (DB_REDO(op))
HPAGE_PTYPE(hk) = H_DUPLICATE;
else
@@ -430,14 +421,15 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
}
}
- if ((ret = memp_fput(file_dbp->mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: if (getmeta)
- (void)__ham_release_meta(dbc);
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
REC_CLOSE;
}
@@ -460,15 +452,16 @@ __ham_splitdata_recover(dbenv, dbtp, lsnp, op, info)
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
- int cmp_n, cmp_p, flags, getmeta, ret;
+ u_int32_t flags;
+ int cmp_n, cmp_p, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
- getmeta = 0;
REC_PRINT(__ham_splitdata_print);
REC_INTRO(__ham_splitdata_read, 1);
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -477,15 +470,11 @@ __ham_splitdata_recover(dbenv, dbtp, lsnp, op, info)
* don't bother creating a page.
*/
goto done;
- } else if ((ret = memp_fget(mpf, &argp->pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto out;
- getmeta = 1;
-
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
@@ -519,14 +508,15 @@ __ham_splitdata_recover(dbenv, dbtp, lsnp, op, info)
LSN(pagep) = argp->pagelsn;
flags = DB_MPOOL_DIRTY;
}
- if ((ret = memp_fput(file_dbp->mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: if (getmeta)
- (void)__ham_release_meta(dbc);
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
REC_CLOSE;
}
@@ -550,21 +540,19 @@ __ham_copypage_recover(dbenv, dbtp, lsnp, op, info)
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
- int cmp_n, cmp_p, flags, getmeta, ret;
+ u_int32_t flags;
+ int cmp_n, cmp_p, ret;
+ pagep = NULL;
COMPQUIET(info, NULL);
- getmeta = 0;
REC_PRINT(__ham_copypage_print);
REC_INTRO(__ham_copypage_read, 1);
- if ((ret = __ham_get_meta(dbc)) != 0)
- goto out;
- getmeta = 1;
flags = 0;
/* This is the bucket page. */
- if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -574,8 +562,8 @@ __ham_copypage_recover(dbenv, dbtp, lsnp, op, info)
*/
ret = 0;
goto donext;
- } else if ((ret = memp_fget(mpf, &argp->pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -597,11 +585,12 @@ __ham_copypage_recover(dbenv, dbtp, lsnp, op, info)
LSN(pagep) = argp->pagelsn;
flags = DB_MPOOL_DIRTY;
}
- if ((ret = memp_fput(mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
donext: /* Now fix up the "next" page. */
- if ((ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -611,8 +600,8 @@ donext: /* Now fix up the "next" page. */
*/
ret = 0;
goto do_nn;
- } else if ((ret = memp_fget(mpf, &argp->next_pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->next_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -629,14 +618,15 @@ donext: /* Now fix up the "next" page. */
memcpy(pagep, argp->page.data, argp->page.size);
flags = DB_MPOOL_DIRTY;
}
- if ((ret = memp_fput(mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
/* Now fix up the next's next page. */
do_nn: if (argp->nnext_pgno == PGNO_INVALID)
goto done;
- if ((ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep)) != 0) {
+ if ((ret = mpf->get(mpf, &argp->nnext_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
/*
* We are undoing and the page doesn't exist. That
@@ -645,8 +635,8 @@ do_nn: if (argp->nnext_pgno == PGNO_INVALID)
* don't bother creating a page.
*/
goto done;
- } else if ((ret = memp_fget(mpf, &argp->nnext_pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
+ } else if ((ret = mpf->get(mpf,
+ &argp->nnext_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
@@ -666,14 +656,15 @@ do_nn: if (argp->nnext_pgno == PGNO_INVALID)
LSN(pagep) = argp->nnextlsn;
flags = DB_MPOOL_DIRTY;
}
- if ((ret = memp_fput(mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
+ pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: if (getmeta)
- (void)__ham_release_meta(dbc);
+out: if (pagep != NULL)
+ (void)mpf->put(mpf, pagep, 0);
REC_CLOSE;
}
@@ -695,13 +686,17 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
__ham_metagroup_args *argp;
HASH_CURSOR *hcp;
DB *file_dbp;
+ DBMETA *mmeta;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
- db_pgno_t last_pgno;
- int cmp_n, cmp_p, flags, groupgrow, ret;
+ db_pgno_t pgno;
+ u_int32_t flags, mmeta_flags;
+ int cmp_n, cmp_p, did_recover, groupgrow, ret;
COMPQUIET(info, NULL);
+ mmeta_flags = 0;
+ mmeta = NULL;
REC_PRINT(__ham_metagroup_print);
REC_INTRO(__ham_metagroup_read, 1);
@@ -709,22 +704,24 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
* This logs the virtual create of pages pgno to pgno + bucket
* Since the mpool page-allocation is not really able to be
* transaction protected, we can never undo it. Even in an abort,
- * we have to allocate these pages to the hash table.
+ * we have to allocate these pages to the hash table if they
+ * were actually created. In particular, during disaster
+ * recovery the metapage may be before this point if we
+ * are rolling backward. If the file has not been extended
+ * then the metapage could not have been updated.
* The log record contains:
* bucket: new bucket being allocated.
* pgno: page number of the new bucket.
* if bucket is a power of 2, then we allocated a whole batch of
* pages; if it's not, then we simply allocated one new page.
*/
- groupgrow =
- (u_int32_t)(1 << __db_log2(argp->bucket + 1)) == argp->bucket + 1;
+ groupgrow = (u_int32_t)(1 << __db_log2(argp->bucket + 1)) ==
+ argp->bucket + 1;
+ pgno = argp->pgno;
+ if (argp->newalloc)
+ pgno += argp->bucket;
- last_pgno = argp->pgno;
- if (groupgrow)
- /* Read the last page. */
- last_pgno += argp->bucket;
-
- if ((ret = memp_fget(mpf, &last_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -743,7 +740,7 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
pagep->lsn = argp->pagelsn;
flags = DB_MPOOL_DIRTY;
}
- if ((ret = memp_fput(mpf, pagep, flags)) != 0)
+ if ((ret = mpf->put(mpf, pagep, flags)) != 0)
goto out;
/* Now we have to update the meta-data page. */
@@ -753,39 +750,90 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
cmp_n = log_compare(lsnp, &hcp->hdr->dbmeta.lsn);
cmp_p = log_compare(&hcp->hdr->dbmeta.lsn, &argp->metalsn);
CHECK_LSN(op, cmp_p, &hcp->hdr->dbmeta.lsn, &argp->metalsn);
- if ((cmp_p == 0 && DB_REDO(op)) || (cmp_n == 0 && DB_UNDO(op))) {
- if (DB_REDO(op)) {
- /* Redo the actual updating of bucket counts. */
- ++hcp->hdr->max_bucket;
- if (groupgrow) {
- hcp->hdr->low_mask = hcp->hdr->high_mask;
- hcp->hdr->high_mask =
- (argp->bucket + 1) | hcp->hdr->low_mask;
- }
- hcp->hdr->dbmeta.lsn = *lsnp;
- } else {
- /* Undo the actual updating of bucket counts. */
- --hcp->hdr->max_bucket;
- if (groupgrow) {
- hcp->hdr->high_mask = hcp->hdr->low_mask;
- hcp->hdr->low_mask = hcp->hdr->high_mask >> 1;
- }
- hcp->hdr->dbmeta.lsn = argp->metalsn;
+ did_recover = 0;
+ if (cmp_p == 0 && DB_REDO(op)) {
+ /* Redo the actual updating of bucket counts. */
+ ++hcp->hdr->max_bucket;
+ if (groupgrow) {
+ hcp->hdr->low_mask = hcp->hdr->high_mask;
+ hcp->hdr->high_mask =
+ (argp->bucket + 1) | hcp->hdr->low_mask;
}
- if (groupgrow &&
- hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] ==
- PGNO_INVALID)
- hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] =
- argp->pgno - argp->bucket - 1;
- F_SET(hcp, H_DIRTY);
+ hcp->hdr->dbmeta.lsn = *lsnp;
+ did_recover = 1;
+ } else if (cmp_n == 0 && DB_UNDO(op)) {
+ /* Undo the actual updating of bucket counts. */
+ --hcp->hdr->max_bucket;
+ if (groupgrow) {
+ hcp->hdr->high_mask = hcp->hdr->low_mask;
+ hcp->hdr->low_mask = hcp->hdr->high_mask >> 1;
+ }
+ hcp->hdr->dbmeta.lsn = argp->metalsn;
+ did_recover = 1;
+ }
+
+ /*
+ * Now we need to fix up the spares array. Each entry in the
+ * spares array indicates the beginning page number for the
+ * indicated doubling. We need to fill this in whenever the
+ * spares array is invalid, since we never reclaim pages from
+ * the spares array and we have to allocate the pages to the
+ * spares array in both the redo and undo cases.
+ */
+ if (argp->newalloc &&
+ hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] == PGNO_INVALID) {
+ hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] =
+ argp->pgno - argp->bucket - 1;
+ did_recover = 1;
+ }
+
+ /*
+ * Finally, we need to potentially fix up the last_pgno field
+ * in the master meta-data page (which may or may not be the
+ * same as the hash header page).
+ */
+ if (argp->mmpgno != argp->mpgno) {
+ if ((ret =
+ mpf->get(mpf, &argp->mmpgno, 0, (PAGE **)&mmeta)) != 0)
+ goto out;
+ mmeta_flags = 0;
+ cmp_n = log_compare(lsnp, &mmeta->lsn);
+ cmp_p = log_compare(&mmeta->lsn, &argp->mmetalsn);
+ if (cmp_p == 0 && DB_REDO(op)) {
+ mmeta->lsn = *lsnp;
+ mmeta_flags = DB_MPOOL_DIRTY;
+ } else if (cmp_n == 0 && DB_UNDO(op)) {
+ mmeta->lsn = argp->mmetalsn;
+ mmeta_flags = DB_MPOOL_DIRTY;
+ }
+ } else
+ mmeta = (DBMETA *)hcp->hdr;
+
+ if (argp->newalloc) {
+ if (mmeta->last_pgno < pgno)
+ mmeta->last_pgno = pgno;
+ mmeta_flags = DB_MPOOL_DIRTY;
}
- if ((ret = __ham_release_meta(dbc)) != 0)
+
+ if (argp->mmpgno != argp->mpgno &&
+ (ret = mpf->put(mpf, mmeta, mmeta_flags)) != 0)
goto out;
+ mmeta = NULL;
+
+ if (did_recover)
+ F_SET(hcp, H_DIRTY);
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
+out: if (mmeta != NULL)
+ (void)mpf->put(mpf, mmeta, 0);
+ if (dbc != NULL)
+ (void)__ham_release_meta(dbc);
+ if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
+ ret = 0;
+
+ REC_CLOSE;
}
/*
@@ -808,17 +856,20 @@ __ham_groupalloc_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf;
DB *file_dbp;
DBC *dbc;
+ PAGE *pagep;
db_pgno_t pgno;
- int cmp_n, cmp_p, flags, ret;
+ int cmp_n, cmp_p, modified, ret;
+ mmeta = NULL;
+ modified = 0;
REC_PRINT(__ham_groupalloc_print);
REC_INTRO(__ham_groupalloc_read, 0);
pgno = PGNO_BASE_MD;
- if ((ret = memp_fget(mpf, &pgno, 0, &mmeta)) != 0) {
+ if ((ret = mpf->get(mpf, &pgno, 0, &mmeta)) != 0) {
if (DB_REDO(op)) {
/* Page should have existed. */
- (void)__db_pgerr(file_dbp, pgno);
+ __db_pgerr(file_dbp, pgno, ret);
goto out;
} else {
ret = 0;
@@ -839,37 +890,48 @@ __ham_groupalloc_recover(dbenv, dbtp, lsnp, op, info)
* that the pages were never allocated, so we'd better check for
* that and handle it here.
*/
-
- flags = 0;
if (DB_REDO(op)) {
- if ((ret = __ham_alloc_pages(file_dbp, argp)) != 0)
- goto out1;
+ if ((ret = __ham_alloc_pages(file_dbp, argp, lsnp)) != 0)
+ goto out;
if (cmp_p == 0) {
LSN(mmeta) = *lsnp;
- flags = DB_MPOOL_DIRTY;
+ modified = 1;
}
- }
+ } else if (DB_UNDO(op)) {
+ /*
+ * Reset the last page back to its preallocation state.
+ */
+ pgno = argp->start_pgno + argp->num - 1;
+ if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) == 0) {
- /*
- * Always put the pages into the limbo list and free them later.
- */
- else if (DB_UNDO(op)) {
+ if (log_compare(&pagep->lsn, lsnp) == 0)
+ ZERO_LSN(pagep->lsn);
+
+ if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
+ goto out;
+ } else if (ret != DB_PAGE_NOTFOUND)
+ goto out;
+ /*
+ * Always put the pages into the limbo list and free them later.
+ */
if ((ret = __db_add_limbo(dbenv,
info, argp->fileid, argp->start_pgno, argp->num)) != 0)
goto out;
if (cmp_n == 0) {
LSN(mmeta) = argp->meta_lsn;
- flags = DB_MPOOL_DIRTY;
+ modified = 1;
}
}
-out1: if ((ret = memp_fput(mpf, mmeta, flags)) != 0)
- goto out;
-
done: if (ret == 0)
*lsnp = argp->prev_lsn;
-out: REC_CLOSE;
+out: if (mmeta != NULL)
+ (void)mpf->put(mpf, mmeta, modified ? DB_MPOOL_DIRTY : 0);
+
+ if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
+ ret = 0;
+ REC_CLOSE;
}
/*
@@ -883,9 +945,10 @@ out: REC_CLOSE;
* Hash normally has holes in its files and handles them appropriately.
*/
static int
-__ham_alloc_pages(dbp, argp)
+__ham_alloc_pages(dbp, argp, lsnp)
DB *dbp;
__ham_groupalloc_args *argp;
+ DB_LSN *lsnp;
{
DB_MPOOLFILE *mpf;
PAGE *pagep;
@@ -898,38 +961,26 @@ __ham_alloc_pages(dbp, argp)
pgno = argp->start_pgno + argp->num - 1;
/* If the page exists, and it has been initialized, then we're done. */
- if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) == 0) {
- if ((pagep->type == P_INVALID) && IS_ZERO_LSN(pagep->lsn))
+ if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) == 0) {
+ if (NUM_ENT(pagep) == 0 && IS_ZERO_LSN(pagep->lsn))
goto reinit_page;
- if ((ret = memp_fput(mpf, pagep, 0)) != 0)
+ if ((ret = mpf->put(mpf, pagep, 0)) != 0)
return (ret);
return (0);
}
- /*
- * Had to create the page. On some systems (read "Windows"),
- * you can find random garbage on pages to which you haven't
- * yet written. So, we have an os layer that will do the
- * right thing for group allocations. We call that directly
- * to make sure all the pages are allocated and then continue
- * merrily on our way with normal recovery.
- */
- if ((ret = __os_fpinit(dbp->dbenv, &mpf->fh,
- argp->start_pgno, argp->num, dbp->pgsize)) != 0)
- return (ret);
-
- if ((ret = memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
- (void)__db_pgerr(dbp, pgno);
+ /* Had to create the page. */
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+ __db_pgerr(dbp, pgno, ret);
return (ret);
}
reinit_page:
/* Initialize the newly allocated page. */
- P_INIT(pagep,
- dbp->pgsize, pgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
- ZERO_LSN(pagep->lsn);
+ P_INIT(pagep, dbp->pgsize, pgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+ pagep->lsn = *lsnp;
- if ((ret = memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
return (ret);
return (0);
@@ -942,7 +993,6 @@ reinit_page:
* PUBLIC: int __ham_curadj_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
-
int
__ham_curadj_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
@@ -958,14 +1008,13 @@ __ham_curadj_recover(dbenv, dbtp, lsnp, op, info)
int ret;
HASH_CURSOR *hcp;
- REC_PRINT(__ham_groupalloc_print);
+ COMPQUIET(info, NULL);
+ REC_PRINT(__ham_curadj_print);
+ REC_INTRO(__ham_curadj_read, 0);
- ret = 0;
if (op != DB_TXN_ABORT)
goto done;
- REC_INTRO(__ham_curadj_read, 0);
- COMPQUIET(info, NULL);
/*
* Undo the adjustment by reinitializing the the cursor
* to look like the one that was used to do the adustment,
@@ -991,7 +1040,6 @@ out: REC_CLOSE;
* PUBLIC: int __ham_chgpg_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
-
int
__ham_chgpg_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
@@ -1008,15 +1056,18 @@ __ham_chgpg_recover(dbenv, dbtp, lsnp, op, info)
int ret;
DBC *cp;
HASH_CURSOR *lcp;
+ u_int32_t order, indx;
+ COMPQUIET(info, NULL);
REC_PRINT(__ham_chgpg_print);
+ REC_INTRO(__ham_chgpg_read, 0);
- ret = 0;
if (op != DB_TXN_ABORT)
- goto out;
- REC_INTRO(__ham_chgpg_read, 0);
+ goto done;
- COMPQUIET(info, NULL);
+ /* Overloaded fields for DB_HAM_DEL*PG */
+ indx = argp->old_indx;
+ order = argp->new_indx;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
for (ldbp = __dblist_get(dbenv, file_dbp->adj_fileid);
@@ -1029,50 +1080,77 @@ __ham_chgpg_recover(dbenv, dbtp, lsnp, op, info)
lcp = (HASH_CURSOR *)cp->internal;
switch (argp->mode) {
- case DB_HAM_CHGPG:
+ case DB_HAM_DELFIRSTPG:
if (lcp->pgno != argp->new_pgno)
break;
-
- if (argp->old_indx == NDX_INVALID)
+ if (lcp->indx != indx ||
+ !F_ISSET(lcp, H_DELETED) ||
+ lcp->order >= order) {
lcp->pgno = argp->old_pgno;
- else if (lcp->indx == argp->new_indx) {
- lcp->indx = argp->old_indx;
+ if (lcp->indx == indx)
+ lcp->order -= order;
+ }
+ break;
+ case DB_HAM_DELMIDPG:
+ case DB_HAM_DELLASTPG:
+ if (lcp->pgno == argp->new_pgno &&
+ lcp->indx == indx &&
+ F_ISSET(lcp, H_DELETED) &&
+ lcp->order >= order) {
lcp->pgno = argp->old_pgno;
+ lcp->order -= order;
+ lcp->indx = 0;
}
break;
-
+ case DB_HAM_CHGPG:
+ /*
+ * If we're doing a CHGPG, we're undoing
+ * the move of a non-deleted item to a
+ * new page. Any cursors with the deleted
+ * flag set do not belong to this item;
+ * don't touch them.
+ */
+ if (F_ISSET(lcp, H_DELETED))
+ break;
+ /* FALLTHROUGH */
case DB_HAM_SPLIT:
- if (lcp->pgno == argp->new_pgno
- && lcp->indx == argp->new_indx) {
+ if (lcp->pgno == argp->new_pgno &&
+ lcp->indx == argp->new_indx) {
lcp->indx = argp->old_indx;
lcp->pgno = argp->old_pgno;
}
break;
-
case DB_HAM_DUP:
- if (lcp->opd != NULL) {
- opdcp =
- (BTREE_CURSOR *)lcp->opd->internal;
- if (opdcp->pgno == argp->new_pgno &&
- opdcp->indx == argp->new_indx) {
- if (F_ISSET(opdcp, C_DELETED))
- F_SET(lcp, H_DELETED);
- if ((ret =
- lcp->opd->c_close(
- lcp->opd)) != 0)
- goto out;
- lcp->opd = NULL;
- }
- }
+ if (lcp->opd == NULL)
+ break;
+ opdcp = (BTREE_CURSOR *)lcp->opd->internal;
+ if (opdcp->pgno != argp->new_pgno ||
+ opdcp->indx != argp->new_indx)
+ break;
+
+ if (F_ISSET(opdcp, C_DELETED))
+ F_SET(lcp, H_DELETED);
+ /*
+ * We can't close a cursor while we have the
+ * dbp mutex locked, since c_close reacquires
+ * it. It should be safe to drop the mutex
+ * here, though, since newly opened cursors
+ * are put only at the end of the tailq and
+ * the cursor we're adjusting can't be closed
+ * under us.
+ */
+ MUTEX_THREAD_UNLOCK(dbenv, file_dbp->mutexp);
+ if ((ret = lcp->opd->c_close(lcp->opd)) != 0)
+ goto out;
+ MUTEX_THREAD_LOCK(dbenv, file_dbp->mutexp);
+ lcp->opd = NULL;
break;
}
}
-
MUTEX_THREAD_UNLOCK(dbenv, file_dbp->mutexp);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
done: *lsnp = argp->prev_lsn;
- ret = 0;
out: REC_CLOSE;
}
diff --git a/bdb/hash/hash_reclaim.c b/bdb/hash/hash_reclaim.c
index 8857c5406a4..ac90ffff08a 100644
--- a/bdb/hash/hash_reclaim.c
+++ b/bdb/hash/hash_reclaim.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_reclaim.c,v 11.4 2000/11/30 00:58:37 ubell Exp $";
+static const char revid[] = "$Id: hash_reclaim.c,v 11.12 2002/03/28 19:49:43 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,10 +18,8 @@ static const char revid[] = "$Id: hash_reclaim.c,v 11.4 2000/11/30 00:58:37 ubel
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "hash.h"
-#include "lock.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
/*
* __ham_reclaim --
@@ -52,8 +50,8 @@ __ham_reclaim(dbp, txn)
if ((ret = __ham_get_meta(dbc)) != 0)
goto err;
- if ((ret = __ham_traverse(dbp,
- dbc, DB_LOCK_WRITE, __db_reclaim_callback, dbc)) != 0)
+ if ((ret = __ham_traverse(dbc,
+ DB_LOCK_WRITE, __db_reclaim_callback, dbc, 1)) != 0)
goto err;
if ((ret = dbc->c_close(dbc)) != 0)
goto err;
@@ -66,3 +64,48 @@ err: if (hcp->hdr != NULL)
(void)dbc->c_close(dbc);
return (ret);
}
+
+/*
+ * __ham_truncate --
+ * Reclaim the pages from a subdatabase and return them to the
+ * parent free list.
+ *
+ * PUBLIC: int __ham_truncate __P((DB *, DB_TXN *txn, u_int32_t *));
+ */
+int
+__ham_truncate(dbp, txn, countp)
+ DB *dbp;
+ DB_TXN *txn;
+ u_int32_t *countp;
+{
+ DBC *dbc;
+ HASH_CURSOR *hcp;
+ db_trunc_param trunc;
+ int ret;
+
+ /* Open up a cursor that we'll use for traversing. */
+ if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+ return (ret);
+ hcp = (HASH_CURSOR *)dbc->internal;
+
+ if ((ret = __ham_get_meta(dbc)) != 0)
+ goto err;
+
+ trunc.count = 0;
+ trunc.dbc = dbc;
+
+ if ((ret = __ham_traverse(dbc,
+ DB_LOCK_WRITE, __db_truncate_callback, &trunc, 1)) != 0)
+ goto err;
+ if ((ret = __ham_release_meta(dbc)) != 0)
+ goto err;
+ if ((ret = dbc->c_close(dbc)) != 0)
+ goto err;
+ *countp = trunc.count;
+ return (0);
+
+err: if (hcp->hdr != NULL)
+ (void)__ham_release_meta(dbc);
+ (void)dbc->c_close(dbc);
+ return (ret);
+}
diff --git a/bdb/hash/hash_stat.c b/bdb/hash/hash_stat.c
index ed64bbc68bd..f9ee1d099cb 100644
--- a/bdb/hash/hash_stat.c
+++ b/bdb/hash/hash_stat.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_stat.c,v 11.24 2000/12/21 21:54:35 margo Exp $";
+static const char revid[] = "$Id: hash_stat.c,v 11.48 2002/08/06 06:11:28 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,11 +18,9 @@ static const char revid[] = "$Id: hash_stat.c,v 11.24 2000/12/21 21:54:35 margo
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "btree.h"
-#include "hash.h"
-#include "lock.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
static int __ham_stat_callback __P((DB *, PAGE *, void *, int *));
@@ -30,24 +28,29 @@ static int __ham_stat_callback __P((DB *, PAGE *, void *, int *));
* __ham_stat --
* Gather/print the hash statistics
*
- * PUBLIC: int __ham_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
+ * PUBLIC: int __ham_stat __P((DB *, void *, u_int32_t));
*/
int
-__ham_stat(dbp, spp, db_malloc, flags)
+__ham_stat(dbp, spp, flags)
DB *dbp;
- void *spp, *(*db_malloc) __P((size_t));
+ void *spp;
u_int32_t flags;
{
+ DBC *dbc;
+ DB_ENV *dbenv;
DB_HASH_STAT *sp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
- DBC *dbc;
PAGE *h;
db_pgno_t pgno;
int ret;
- PANIC_CHECK(dbp->dbenv);
+ dbenv = dbp->dbenv;
+
+ PANIC_CHECK(dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
+ mpf = dbp->mpf;
sp = NULL;
/* Check for invalid flags. */
@@ -62,39 +65,39 @@ __ham_stat(dbp, spp, db_malloc, flags)
goto err;
/* Allocate and clear the structure. */
- if ((ret = __os_malloc(dbp->dbenv, sizeof(*sp), db_malloc, &sp)) != 0)
+ if ((ret = __os_umalloc(dbenv, sizeof(*sp), &sp)) != 0)
goto err;
memset(sp, 0, sizeof(*sp));
- if (flags == DB_CACHED_COUNTS) {
- sp->hash_nkeys = hcp->hdr->dbmeta.key_count;
- sp->hash_ndata = hcp->hdr->dbmeta.record_count;
- goto done;
- }
-
/* Copy the fields that we have. */
+ sp->hash_nkeys = hcp->hdr->dbmeta.key_count;
+ sp->hash_ndata = hcp->hdr->dbmeta.record_count;
sp->hash_pagesize = dbp->pgsize;
sp->hash_buckets = hcp->hdr->max_bucket + 1;
sp->hash_magic = hcp->hdr->dbmeta.magic;
sp->hash_version = hcp->hdr->dbmeta.version;
sp->hash_metaflags = hcp->hdr->dbmeta.flags;
- sp->hash_nelem = hcp->hdr->nelem;
sp->hash_ffactor = hcp->hdr->ffactor;
+ if (flags == DB_FAST_STAT || flags == DB_CACHED_COUNTS)
+ goto done;
+
/* Walk the free list, counting pages. */
for (sp->hash_free = 0, pgno = hcp->hdr->dbmeta.free;
pgno != PGNO_INVALID;) {
++sp->hash_free;
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
goto err;
pgno = h->next_pgno;
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
}
/* Now traverse the rest of the table. */
- if ((ret = __ham_traverse(dbp,
- dbc, DB_LOCK_READ, __ham_stat_callback, sp)) != 0)
+ sp->hash_nkeys = 0;
+ sp->hash_ndata = 0;
+ if ((ret = __ham_traverse(dbc,
+ DB_LOCK_READ, __ham_stat_callback, sp, 0)) != 0)
goto err;
if (!F_ISSET(dbp, DB_AM_RDONLY)) {
@@ -114,7 +117,7 @@ done:
return (0);
err: if (sp != NULL)
- __os_free(sp, sizeof(*sp));
+ __os_ufree(dbenv, sp);
if (hcp->hdr != NULL)
(void)__ham_release_meta(dbc);
(void)dbc->c_close(dbc);
@@ -127,26 +130,30 @@ err: if (sp != NULL)
* Traverse an entire hash table. We use the callback so that we
* can use this both for stat collection and for deallocation.
*
- * PUBLIC: int __ham_traverse __P((DB *, DBC *, db_lockmode_t,
- * PUBLIC: int (*)(DB *, PAGE *, void *, int *), void *));
+ * PUBLIC: int __ham_traverse __P((DBC *, db_lockmode_t,
+ * PUBLIC: int (*)(DB *, PAGE *, void *, int *), void *, int));
*/
int
-__ham_traverse(dbp, dbc, mode, callback, cookie)
- DB *dbp;
+__ham_traverse(dbc, mode, callback, cookie, look_past_max)
DBC *dbc;
db_lockmode_t mode;
int (*callback) __P((DB *, PAGE *, void *, int *));
void *cookie;
+ int look_past_max;
{
+ DB *dbp;
+ DBC *opd;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
HKEYDATA *hk;
- DBC *opd;
db_pgno_t pgno, opgno;
- u_int32_t bucket;
int did_put, i, ret, t_ret;
+ u_int32_t bucket, spares_entry;
- hcp = (HASH_CURSOR *)dbc->internal;
+ dbp = dbc->dbp;
opd = NULL;
+ mpf = dbp->mpf;
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = 0;
/*
@@ -156,12 +163,47 @@ __ham_traverse(dbp, dbc, mode, callback, cookie)
* locking easy, makes this a pain in the butt. We have to traverse
* duplicate, overflow and big pages from the bucket so that we
* don't access anything that isn't properly locked.
+ *
*/
- for (bucket = 0; bucket <= hcp->hdr->max_bucket; bucket++) {
+ for (bucket = 0;; bucket++) {
+ /*
+ * We put the loop exit condition check here, because
+ * it made for a really vile extended ?: that made SCO's
+ * compiler drop core.
+ *
+ * If look_past_max is not set, we can stop at max_bucket;
+ * if it is set, we need to include pages that are part of
+ * the current doubling but beyond the highest bucket we've
+ * split into, as well as pages from a "future" doubling
+ * that may have been created within an aborted
+ * transaction. To do this, keep looping (and incrementing
+ * bucket) until the corresponding spares array entries
+ * cease to be defined.
+ */
+ if (look_past_max) {
+ spares_entry = __db_log2(bucket + 1);
+ if (spares_entry >= NCACHED ||
+ hcp->hdr->spares[spares_entry] == 0)
+ break;
+ } else {
+ if (bucket > hcp->hdr->max_bucket)
+ break;
+ }
+
hcp->bucket = bucket;
hcp->pgno = pgno = BUCKET_TO_PAGE(hcp, bucket);
for (ret = __ham_get_cpage(dbc, mode); ret == 0;
ret = __ham_next_cpage(dbc, pgno, 0)) {
+
+ /*
+ * If we are cleaning up pages past the max_bucket,
+ * then they may be on the free list and have their
+ * next pointers set, but the should be ignored. In
+ * fact, we really ought to just skip anybody who is
+ * not a valid page.
+ */
+ if (TYPE(hcp->page) == P_INVALID)
+ break;
pgno = NEXT_PGNO(hcp->page);
/*
@@ -171,17 +213,17 @@ __ham_traverse(dbp, dbc, mode, callback, cookie)
* case we have to count those pages).
*/
for (i = 0; i < NUM_ENT(hcp->page); i++) {
- hk = (HKEYDATA *)P_ENTRY(hcp->page, i);
+ hk = (HKEYDATA *)P_ENTRY(dbp, hcp->page, i);
switch (HPAGE_PTYPE(hk)) {
case H_OFFDUP:
memcpy(&opgno, HOFFDUP_PGNO(hk),
sizeof(db_pgno_t));
if ((ret = __db_c_newopd(dbc,
- opgno, &opd)) != 0)
+ opgno, NULL, &opd)) != 0)
return (ret);
if ((ret = __bam_traverse(opd,
DB_LOCK_READ, opgno,
- __ham_stat_callback, cookie))
+ callback, cookie))
!= 0)
goto err;
if ((ret = opd->c_close(opd)) != 0)
@@ -221,10 +263,10 @@ __ham_traverse(dbp, dbc, mode, callback, cookie)
goto err;
if (STD_LOCKING(dbc))
- (void)lock_put(dbp->dbenv, &hcp->lock);
+ (void)dbp->dbenv->lock_put(dbp->dbenv, &hcp->lock);
if (hcp->page != NULL) {
- if ((ret = memp_fput(dbc->dbp->mpf, hcp->page, 0)) != 0)
+ if ((ret = mpf->put(mpf, hcp->page, 0)) != 0)
return (ret);
hcp->page = NULL;
}
@@ -247,6 +289,7 @@ __ham_stat_callback(dbp, pagep, cookie, putp)
DB_BTREE_STAT bstat;
db_indx_t indx, len, off, tlen, top;
u_int8_t *hk;
+ int ret;
*putp = 0;
sp = cookie;
@@ -266,15 +309,15 @@ __ham_stat_callback(dbp, pagep, cookie, putp)
* is a bucket.
*/
if (PREV_PGNO(pagep) == PGNO_INVALID)
- sp->hash_bfree += P_FREESPACE(pagep);
+ sp->hash_bfree += P_FREESPACE(dbp, pagep);
else {
sp->hash_overflows++;
- sp->hash_ovfl_free += P_FREESPACE(pagep);
+ sp->hash_ovfl_free += P_FREESPACE(dbp, pagep);
}
top = NUM_ENT(pagep);
/* Correct for on-page duplicates and deleted items. */
for (indx = 0; indx < top; indx += P_INDX) {
- switch (*H_PAIRDATA(pagep, indx)) {
+ switch (*H_PAIRDATA(dbp, pagep, indx)) {
case H_OFFDUP:
case H_OFFPAGE:
break;
@@ -282,8 +325,8 @@ __ham_stat_callback(dbp, pagep, cookie, putp)
sp->hash_ndata++;
break;
case H_DUPLICATE:
- tlen = LEN_HDATA(pagep, 0, indx);
- hk = H_PAIRDATA(pagep, indx);
+ tlen = LEN_HDATA(dbp, pagep, 0, indx);
+ hk = H_PAIRDATA(dbp, pagep, indx);
for (off = 0; off < tlen;
off += len + 2 * sizeof (db_indx_t)) {
sp->hash_ndata++;
@@ -310,7 +353,8 @@ __ham_stat_callback(dbp, pagep, cookie, putp)
bstat.bt_int_pgfree = 0;
bstat.bt_leaf_pgfree = 0;
bstat.bt_ndata = 0;
- __bam_stat_callback(dbp, pagep, &bstat, putp);
+ if ((ret = __bam_stat_callback(dbp, pagep, &bstat, putp)) != 0)
+ return (ret);
sp->hash_dup++;
sp->hash_dup_free += bstat.bt_leaf_pgfree +
bstat.bt_dup_pgfree + bstat.bt_int_pgfree;
@@ -318,11 +362,10 @@ __ham_stat_callback(dbp, pagep, cookie, putp)
break;
case P_OVERFLOW:
sp->hash_bigpages++;
- sp->hash_big_bfree += P_OVFLSPACE(dbp->pgsize, pagep);
+ sp->hash_big_bfree += P_OVFLSPACE(dbp, dbp->pgsize, pagep);
break;
default:
- return (__db_unknown_type(dbp->dbenv,
- "__ham_stat_callback", pagep->type));
+ return (__db_pgfmt(dbp->dbenv, pagep->pgno));
}
return (0);
diff --git a/bdb/hash/hash_upgrade.c b/bdb/hash/hash_upgrade.c
index c34381276b4..2dd21d7b644 100644
--- a/bdb/hash/hash_upgrade.c
+++ b/bdb/hash/hash_upgrade.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_upgrade.c,v 11.25 2000/12/14 19:18:32 bostic Exp $";
+static const char revid[] = "$Id: hash_upgrade.c,v 11.32 2002/08/06 05:34:58 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,14 +18,13 @@ static const char revid[] = "$Id: hash_upgrade.c,v 11.25 2000/12/14 19:18:32 bos
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "hash.h"
-#include "db_upgrade.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+#include "dbinc/db_upgrade.h"
/*
* __ham_30_hashmeta --
- * Upgrade the database from version 4/5 to version 6.
+ * Upgrade the database from version 4/5 to version 6.
*
* PUBLIC: int __ham_30_hashmeta __P((DB *, char *, u_int8_t *));
*/
@@ -163,10 +162,6 @@ __ham_30_sizefix(dbp, fhp, realname, metabuf)
return (ret);
if ((ret = __os_write(dbenv, fhp, buf, pagesize, &nw)) != 0)
return (ret);
- if (nw != pagesize) {
- __db_err(dbenv, "Short write during upgrade");
- return (EIO);
- }
}
return (0);
@@ -174,7 +169,7 @@ __ham_30_sizefix(dbp, fhp, realname, metabuf)
/*
* __ham_31_hashmeta --
- * Upgrade the database from version 6 to version 7.
+ * Upgrade the database from version 6 to version 7.
*
* PUBLIC: int __ham_31_hashmeta
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
@@ -229,7 +224,7 @@ __ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp)
/*
* __ham_31_hash --
- * Upgrade the database hash leaf pages.
+ * Upgrade the database hash leaf pages.
*
* PUBLIC: int __ham_31_hash
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
@@ -252,7 +247,7 @@ __ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp)
ret = 0;
for (indx = 0; indx < NUM_ENT(h); indx += 2) {
- hk = (HKEYDATA *)H_PAIRDATA(h, indx);
+ hk = (HKEYDATA *)H_PAIRDATA(dbp, h, indx);
if (HPAGE_PTYPE(hk) == H_OFFDUP) {
memcpy(&pgno, HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
tpgno = pgno;
diff --git a/bdb/hash/hash_verify.c b/bdb/hash/hash_verify.c
index 31dd7cc2299..e6f5a2b0d65 100644
--- a/bdb/hash/hash_verify.c
+++ b/bdb/hash/hash_verify.c
@@ -1,16 +1,16 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: hash_verify.c,v 1.31 2000/11/30 00:58:37 ubell Exp $
+ * $Id: hash_verify.c,v 1.53 2002/08/06 05:35:02 bostic Exp $
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_verify.c,v 1.31 2000/11/30 00:58:37 ubell Exp $";
+static const char revid[] = "$Id: hash_verify.c,v 1.53 2002/08/06 05:35:02 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,10 +20,10 @@ static const char revid[] = "$Id: hash_verify.c,v 1.31 2000/11/30 00:58:37 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_verify.h"
-#include "btree.h"
-#include "hash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_verify.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
static int __ham_dups_unsorted __P((DB *, u_int8_t *, u_int32_t));
static int __ham_vrfy_bucket __P((DB *, VRFY_DBINFO *, HMETA *, u_int32_t,
@@ -83,8 +83,8 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
if (!LF_ISSET(DB_NOORDERCHK))
if (m->h_charkey != hfunc(dbp, CHARKEY, sizeof(CHARKEY))) {
EPRINT((dbp->dbenv,
-"Database has different custom hash function; reverify with DB_NOORDERCHK set"
- ));
+"Page %lu: database has different custom hash function; reverify with DB_NOORDERCHK set",
+ (u_long)pgno));
/*
* Return immediately; this is probably a sign
* of user error rather than database corruption, so
@@ -97,8 +97,8 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
/* max_bucket must be less than the last pgno. */
if (m->max_bucket > vdp->last_pgno) {
EPRINT((dbp->dbenv,
- "Impossible max_bucket %lu on meta page %lu",
- m->max_bucket, pgno));
+ "Page %lu: Impossible max_bucket %lu on meta page",
+ (u_long)pgno, (u_long)m->max_bucket));
/*
* Most other fields depend somehow on max_bucket, so
* we just return--there will be lots of extraneous
@@ -118,15 +118,15 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
pwr = (m->max_bucket == 0) ? 1 : 1 << __db_log2(m->max_bucket + 1);
if (m->high_mask != pwr - 1) {
EPRINT((dbp->dbenv,
- "Incorrect high_mask %lu on page %lu, should be %lu",
- m->high_mask, pgno, pwr - 1));
+ "Page %lu: incorrect high_mask %lu, should be %lu",
+ (u_long)pgno, (u_long)m->high_mask, (u_long)pwr - 1));
isbad = 1;
}
pwr >>= 1;
if (m->low_mask != pwr - 1) {
EPRINT((dbp->dbenv,
- "Incorrect low_mask %lu on page %lu, should be %lu",
- m->low_mask, pgno, pwr - 1));
+ "Page %lu: incorrect low_mask %lu, should be %lu",
+ (u_long)pgno, (u_long)m->low_mask, (u_long)pwr - 1));
isbad = 1;
}
@@ -140,8 +140,8 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
*/
if (m->nelem > 0x80000000) {
EPRINT((dbp->dbenv,
- "Suspiciously high nelem of %lu on page %lu",
- m->nelem, pgno));
+ "Page %lu: suspiciously high nelem of %lu",
+ (u_long)pgno, (u_long)m->nelem));
isbad = 1;
pip->h_nelem = 0;
} else
@@ -164,13 +164,14 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
mbucket = (1 << i) - 1;
if (BS_TO_PAGE(mbucket, m->spares) > vdp->last_pgno) {
EPRINT((dbp->dbenv,
- "Spares array entry %lu, page %lu is invalid",
- i, pgno));
+ "Page %lu: spares array entry %d is invalid",
+ (u_long)pgno, i));
isbad = 1;
}
}
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -192,6 +193,7 @@ __ham_vrfy(dbp, vdp, h, pgno, flags)
{
VRFY_PAGEINFO *pip;
u_int32_t ent, himark, inpend;
+ db_indx_t *inp;
int isbad, ret, t_ret;
isbad = 0;
@@ -226,31 +228,33 @@ __ham_vrfy(dbp, vdp, h, pgno, flags)
* In any case, we return immediately if things are bad, as it would
* be unsafe to proceed.
*/
+ inp = P_INP(dbp, h);
for (ent = 0, himark = dbp->pgsize,
- inpend = (u_int8_t *)h->inp - (u_int8_t *)h;
+ inpend = (u_int32_t)((u_int8_t *)inp - (u_int8_t *)h);
ent < NUM_ENT(h); ent++)
- if (h->inp[ent] >= himark) {
+ if (inp[ent] >= himark) {
EPRINT((dbp->dbenv,
- "Item %lu on page %lu out of order or nonsensical",
- ent, pgno));
+ "Page %lu: item %lu is out of order or nonsensical",
+ (u_long)pgno, (u_long)ent));
isbad = 1;
goto err;
} else if (inpend >= himark) {
EPRINT((dbp->dbenv,
- "inp array collided with data on page %lu",
- pgno));
+ "Page %lu: entries array collided with data",
+ (u_long)pgno));
isbad = 1;
goto err;
} else {
- himark = h->inp[ent];
+ himark = inp[ent];
inpend += sizeof(db_indx_t);
if ((ret = __ham_vrfy_item(
dbp, vdp, pgno, h, ent, flags)) != 0)
goto err;
}
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return (ret == 0 && isbad == 1 ? DB_VERIFY_BAD : ret);
}
@@ -279,7 +283,7 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
return (ret);
- switch (HPAGE_TYPE(h, i)) {
+ switch (HPAGE_TYPE(dbp, h, i)) {
case H_KEYDATA:
/* Nothing to do here--everything but the type field is data */
break;
@@ -287,8 +291,8 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
/* Are we a datum or a key? Better be the former. */
if (i % 2 == 0) {
EPRINT((dbp->dbenv,
- "Hash key stored as duplicate at page %lu item %lu",
- pip->pgno, i));
+ "Page %lu: hash key stored as duplicate item %lu",
+ (u_long)pip->pgno, (u_long)i));
}
/*
* Dups are encoded as a series within a single HKEYDATA,
@@ -300,16 +304,16 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
* Note that at this point, we've verified item i-1, so
* it's safe to use LEN_HKEYDATA (which looks at inp[i-1]).
*/
- len = LEN_HKEYDATA(h, dbp->pgsize, i);
- databuf = HKEYDATA_DATA(P_ENTRY(h, i));
+ len = LEN_HKEYDATA(dbp, h, dbp->pgsize, i);
+ databuf = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
for (offset = 0; offset < len; offset += DUP_SIZE(dlen)) {
memcpy(&dlen, databuf + offset, sizeof(db_indx_t));
/* Make sure the length is plausible. */
if (offset + DUP_SIZE(dlen) > len) {
EPRINT((dbp->dbenv,
- "Duplicate item %lu, page %lu has bad length",
- i, pip->pgno));
+ "Page %lu: duplicate item %lu has bad length",
+ (u_long)pip->pgno, (u_long)i));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -323,8 +327,8 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
sizeof(db_indx_t));
if (elen != dlen) {
EPRINT((dbp->dbenv,
- "Duplicate item %lu, page %lu has two different lengths",
- i, pip->pgno));
+ "Page %lu: duplicate item %lu has two different lengths",
+ (u_long)pip->pgno, (u_long)i));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -336,12 +340,12 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
break;
case H_OFFPAGE:
/* Offpage item. Make sure pgno is sane, save off. */
- memcpy(&hop, P_ENTRY(h, i), HOFFPAGE_SIZE);
+ memcpy(&hop, P_ENTRY(dbp, h, i), HOFFPAGE_SIZE);
if (!IS_VALID_PGNO(hop.pgno) || hop.pgno == pip->pgno ||
hop.pgno == PGNO_INVALID) {
EPRINT((dbp->dbenv,
- "Offpage item %lu, page %lu has bad page number",
- i, pip->pgno));
+ "Page %lu: offpage item %lu has bad pgno %lu",
+ (u_long)pip->pgno, (u_long)i, (u_long)hop.pgno));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -354,12 +358,12 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
break;
case H_OFFDUP:
/* Offpage duplicate item. Same drill. */
- memcpy(&hod, P_ENTRY(h, i), HOFFDUP_SIZE);
+ memcpy(&hod, P_ENTRY(dbp, h, i), HOFFDUP_SIZE);
if (!IS_VALID_PGNO(hod.pgno) || hod.pgno == pip->pgno ||
hod.pgno == PGNO_INVALID) {
EPRINT((dbp->dbenv,
- "Offpage item %lu, page %lu has bad page number",
- i, pip->pgno));
+ "Page %lu: offpage item %lu has bad page number",
+ (u_long)pip->pgno, (u_long)i));
ret = DB_VERIFY_BAD;
goto err;
}
@@ -372,12 +376,14 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
break;
default:
EPRINT((dbp->dbenv,
- "Item %i, page %lu has bad type", i, pip->pgno));
+ "Page %lu: item %i has bad type",
+ (u_long)pip->pgno, (u_long)i));
ret = DB_VERIFY_BAD;
break;
}
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
@@ -397,29 +403,32 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
u_int32_t flags;
{
DB *pgset;
+ DB_MPOOLFILE *mpf;
HMETA *m;
PAGE *h;
VRFY_PAGEINFO *pip;
int isbad, p, ret, t_ret;
db_pgno_t pgno;
- u_int32_t bucket;
+ u_int32_t bucket, spares_entry;
- ret = isbad = 0;
- h = NULL;
+ mpf = dbp->mpf;
pgset = vdp->pgset;
+ h = NULL;
+ ret = isbad = 0;
if ((ret = __db_vrfy_pgset_get(pgset, meta_pgno, &p)) != 0)
return (ret);
if (p != 0) {
EPRINT((dbp->dbenv,
- "Hash meta page %lu referenced twice", meta_pgno));
+ "Page %lu: Hash meta page referenced twice",
+ (u_long)meta_pgno));
return (DB_VERIFY_BAD);
}
if ((ret = __db_vrfy_pgset_inc(pgset, meta_pgno)) != 0)
return (ret);
/* Get the meta page; we'll need it frequently. */
- if ((ret = memp_fget(dbp->mpf, &meta_pgno, 0, &m)) != 0)
+ if ((ret = mpf->get(mpf, &meta_pgno, 0, &m)) != 0)
return (ret);
/* Loop through bucket by bucket. */
@@ -445,8 +454,8 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
* Note that this should be safe, since we've already verified
* that the spares array is sane.
*/
- for (bucket = m->max_bucket + 1;
- m->spares[__db_log2(bucket + 1)] != 0; bucket++) {
+ for (bucket = m->max_bucket + 1; spares_entry = __db_log2(bucket + 1),
+ spares_entry < NCACHED && m->spares[spares_entry] != 0; bucket++) {
pgno = BS_TO_PAGE(bucket, m->spares);
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
goto err;
@@ -454,43 +463,51 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
/* It's okay if these pages are totally zeroed; unmark it. */
F_CLR(pip, VRFY_IS_ALLZEROES);
+ /* It's also OK if this page is simply invalid. */
+ if (pip->type == P_INVALID) {
+ if ((ret = __db_vrfy_putpageinfo(dbp->dbenv,
+ vdp, pip)) != 0)
+ goto err;
+ continue;
+ }
+
if (pip->type != P_HASH) {
EPRINT((dbp->dbenv,
- "Hash bucket %lu maps to non-hash page %lu",
- bucket, pgno));
+ "Page %lu: hash bucket %lu maps to non-hash page",
+ (u_long)pgno, (u_long)bucket));
isbad = 1;
} else if (pip->entries != 0) {
EPRINT((dbp->dbenv,
- "Non-empty page %lu in unused hash bucket %lu",
- pgno, bucket));
+ "Page %lu: non-empty page in unused hash bucket %lu",
+ (u_long)pgno, (u_long)bucket));
isbad = 1;
} else {
if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
goto err;
if (p != 0) {
EPRINT((dbp->dbenv,
- "Hash page %lu above max_bucket referenced",
- pgno));
+ "Page %lu: above max_bucket referenced",
+ (u_long)pgno));
isbad = 1;
} else {
if ((ret =
__db_vrfy_pgset_inc(pgset, pgno)) != 0)
goto err;
- if ((ret =
- __db_vrfy_putpageinfo(vdp, pip)) != 0)
+ if ((ret = __db_vrfy_putpageinfo(dbp->dbenv,
+ vdp, pip)) != 0)
goto err;
continue;
}
}
/* If we got here, it's an error. */
- (void)__db_vrfy_putpageinfo(vdp, pip);
+ (void)__db_vrfy_putpageinfo(dbp->dbenv, vdp, pip);
goto err;
}
-err: if ((t_ret = memp_fput(dbp->mpf, m, 0)) != 0)
+err: if ((t_ret = mpf->put(mpf, m, 0)) != 0)
return (t_ret);
- if (h != NULL && (t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0)
return (t_ret);
return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD: ret);
}
@@ -535,8 +552,9 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
/* Make sure we got a plausible page number. */
if (pgno > vdp->last_pgno || pip->type != P_HASH) {
- EPRINT((dbp->dbenv, "Bucket %lu has impossible first page %lu",
- bucket, pgno));
+ EPRINT((dbp->dbenv,
+ "Page %lu: impossible first page in bucket %lu",
+ (u_long)pgno, (u_long)bucket));
/* Unsafe to continue. */
isbad = 1;
goto err;
@@ -544,7 +562,8 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
if (pip->prev_pgno != PGNO_INVALID) {
EPRINT((dbp->dbenv,
- "First hash page %lu in bucket %lu has a prev_pgno", pgno));
+ "Page %lu: first page in hash bucket %lu has a prev_pgno",
+ (u_long)pgno, (u_long)bucket));
isbad = 1;
}
@@ -564,7 +583,8 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
goto err;
if (p != 0) {
EPRINT((dbp->dbenv,
- "Hash page %lu referenced twice", pgno));
+ "Page %lu: hash page referenced twice",
+ (u_long)pgno));
isbad = 1;
/* Unsafe to continue. */
goto err;
@@ -584,11 +604,11 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
F_CLR(pip, VRFY_IS_ALLZEROES);
/* If we have dups, our meta page had better know about it. */
- if (F_ISSET(pip, VRFY_HAS_DUPS)
- && !F_ISSET(mip, VRFY_HAS_DUPS)) {
+ if (F_ISSET(pip, VRFY_HAS_DUPS) &&
+ !F_ISSET(mip, VRFY_HAS_DUPS)) {
EPRINT((dbp->dbenv,
- "Duplicates present in non-duplicate database, page %lu",
- pgno));
+ "Page %lu: duplicates present in non-duplicate database",
+ (u_long)pgno));
isbad = 1;
}
@@ -599,8 +619,8 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
if (F_ISSET(mip, VRFY_HAS_DUPSORT) &&
F_ISSET(pip, VRFY_DUPS_UNSORTED)) {
EPRINT((dbp->dbenv,
- "Unsorted dups in sorted-dup database, page %lu",
- pgno));
+ "Page %lu: unsorted dups in sorted-dup database",
+ (u_long)pgno));
isbad = 1;
}
@@ -625,8 +645,8 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
}
if ((ret = __bam_vrfy_subtree(dbp, vdp,
child->pgno, NULL, NULL,
- flags | ST_RECNUM | ST_DUPSET, NULL,
- NULL, NULL)) != 0) {
+ flags | ST_RECNUM | ST_DUPSET | ST_TOPLEVEL,
+ NULL, NULL, NULL)) != 0) {
if (ret == DB_VERIFY_BAD)
isbad = 1;
else
@@ -648,7 +668,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
}
next_pgno = pip->next_pgno;
- ret = __db_vrfy_putpageinfo(vdp, pip);
+ ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip);
pip = NULL;
if (ret != 0)
@@ -661,7 +681,8 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
if (!IS_VALID_PGNO(next_pgno)) {
DB_ASSERT(0);
EPRINT((dbp->dbenv,
- "Hash page %lu has bad next_pgno", pgno));
+ "Page %lu: hash page has bad next_pgno",
+ (u_long)pgno));
isbad = 1;
goto err;
}
@@ -670,8 +691,9 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
goto err;
if (pip->prev_pgno != pgno) {
- EPRINT((dbp->dbenv, "Hash page %lu has bad prev_pgno",
- next_pgno));
+ EPRINT((dbp->dbenv,
+ "Page %lu: hash page has bad prev_pgno",
+ (u_long)next_pgno));
isbad = 1;
}
pgno = next_pgno;
@@ -679,11 +701,11 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
err: if (cc != NULL && ((t_ret = __db_vrfy_ccclose(cc)) != 0) && ret == 0)
ret = t_ret;
- if (mip != NULL && ((t_ret = __db_vrfy_putpageinfo(vdp, mip)) != 0) &&
- ret == 0)
+ if (mip != NULL && ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, mip)) != 0) && ret == 0)
ret = t_ret;
- if (pip != NULL && ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0) &&
- ret == 0)
+ if (pip != NULL && ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0) && ret == 0)
ret = t_ret;
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
}
@@ -707,16 +729,19 @@ __ham_vrfy_hashing(dbp, nentries, m, thisbucket, pgno, flags, hfunc)
u_int32_t (*hfunc) __P((DB *, const void *, u_int32_t));
{
DBT dbt;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t i;
int ret, t_ret, isbad;
u_int32_t hval, bucket;
+ mpf = dbp->mpf;
ret = isbad = 0;
+
memset(&dbt, 0, sizeof(DBT));
F_SET(&dbt, DB_DBT_REALLOC);
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
for (i = 0; i < nentries; i += 2) {
@@ -738,15 +763,15 @@ __ham_vrfy_hashing(dbp, nentries, m, thisbucket, pgno, flags, hfunc)
if (bucket != thisbucket) {
EPRINT((dbp->dbenv,
- "Item %lu on page %lu hashes incorrectly",
- i, pgno));
+ "Page %lu: item %lu hashes incorrectly",
+ (u_long)pgno, (u_long)i));
isbad = 1;
}
}
err: if (dbt.data != NULL)
- __os_free(dbt.data, 0);
- if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ __os_ufree(dbp->dbenv, dbt.data);
+ if ((t_ret = mpf->put(mpf, h, 0)) != 0)
return (t_ret);
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
@@ -782,7 +807,7 @@ __ham_salvage(dbp, vdp, pgno, h, handle, callback, flags)
dbt.flags = DB_DBT_REALLOC;
memset(&unkdbt, 0, sizeof(DBT));
- unkdbt.size = strlen("UNKNOWN") + 1;
+ unkdbt.size = (u_int32_t)strlen("UNKNOWN") + 1;
unkdbt.data = "UNKNOWN";
err_ret = 0;
@@ -791,7 +816,7 @@ __ham_salvage(dbp, vdp, pgno, h, handle, callback, flags)
* Allocate a buffer for overflow items. Start at one page;
* __db_safe_goff will realloc as needed.
*/
- if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &buf)) != 0)
+ if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &buf)) != 0)
return (ret);
himark = dbp->pgsize;
@@ -808,8 +833,8 @@ __ham_salvage(dbp, vdp, pgno, h, handle, callback, flags)
break;
if (ret == 0) {
- hk = P_ENTRY(h, i);
- len = LEN_HKEYDATA(h, dbp->pgsize, i);
+ hk = P_ENTRY(dbp, h, i);
+ len = LEN_HKEYDATA(dbp, h, dbp->pgsize, i);
if ((u_int32_t)(hk + len - (u_int8_t *)h) >
dbp->pgsize) {
/*
@@ -834,7 +859,7 @@ keydata: memcpy(buf, HKEYDATA_DATA(hk), len);
dbt.size = len;
dbt.data = buf;
if ((ret = __db_prdbt(&dbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case H_OFFPAGE:
@@ -848,11 +873,11 @@ keydata: memcpy(buf, HKEYDATA_DATA(hk), len);
dpgno, &dbt, &buf, flags)) != 0) {
err_ret = ret;
(void)__db_prdbt(&unkdbt, 0, " ",
- handle, callback, 0, NULL);
+ handle, callback, 0, vdp);
break;
}
if ((ret = __db_prdbt(&dbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case H_OFFDUP:
@@ -865,7 +890,7 @@ keydata: memcpy(buf, HKEYDATA_DATA(hk), len);
/* UNKNOWN iff pgno is bad or we're a key. */
if (!IS_VALID_PGNO(dpgno) || (i % 2 == 0)) {
if ((ret = __db_prdbt(&unkdbt, 0, " ",
- handle, callback, 0, NULL)) != 0)
+ handle, callback, 0, vdp)) != 0)
err_ret = ret;
} else if ((ret = __db_salvage_duptree(dbp,
vdp, dpgno, &dbt, handle, callback,
@@ -908,7 +933,7 @@ keydata: memcpy(buf, HKEYDATA_DATA(hk), len);
dbt.size = dlen;
dbt.data = buf;
if ((ret = __db_prdbt(&dbt, 0, " ",
- handle, callback, 0, NULL)) != 0)
+ handle, callback, 0, vdp)) != 0)
err_ret = ret;
tlen += sizeof(db_indx_t);
}
@@ -917,7 +942,7 @@ keydata: memcpy(buf, HKEYDATA_DATA(hk), len);
}
}
- __os_free(buf, 0);
+ __os_free(dbp->dbenv, buf);
if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
return (t_ret);
return ((ret == 0 && err_ret != 0) ? err_ret : ret);
@@ -938,6 +963,7 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
u_int32_t flags;
DB *pgset;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
u_int32_t bucket, totpgs;
@@ -951,6 +977,7 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
DB_ASSERT(pgset != NULL);
+ mpf = dbp->mpf;
totpgs = 0;
/*
@@ -967,7 +994,7 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
* Safely walk the list of pages in this bucket.
*/
for (;;) {
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
if (TYPE(h) == P_HASH) {
@@ -976,24 +1003,26 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
* pgset.
*/
if (++totpgs > vdp->last_pgno) {
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (DB_VERIFY_BAD);
}
if ((ret =
- __db_vrfy_pgset_inc(pgset, pgno)) != 0)
+ __db_vrfy_pgset_inc(pgset, pgno)) != 0) {
+ (void)mpf->put(mpf, h, 0);
return (ret);
+ }
pgno = NEXT_PGNO(h);
} else
pgno = PGNO_INVALID;
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
return (ret);
/* If the new pgno is wonky, go onto the next bucket. */
if (!IS_VALID_PGNO(pgno) ||
pgno == PGNO_INVALID)
- goto nextbucket;
+ break;
/*
* If we've touched this page before, we have a cycle;
@@ -1002,9 +1031,8 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
if ((ret = __db_vrfy_pgset_get(pgset, pgno, &val)) != 0)
return (ret);
if (val != 0)
- goto nextbucket;
+ break;
}
-nextbucket: ;
}
return (0);
}
diff --git a/bdb/hmac/hmac.c b/bdb/hmac/hmac.c
new file mode 100644
index 00000000000..d39a154ec63
--- /dev/null
+++ b/bdb/hmac/hmac.c
@@ -0,0 +1,207 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * Some parts of this code originally written by Adam Stubblefield,
+ * astubble@rice.edu.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: hmac.c,v 1.25 2002/09/10 02:40:40 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h" /* for hash.h only */
+#include "dbinc/hash.h"
+#include "dbinc/hmac.h"
+
+#define HMAC_OUTPUT_SIZE 20
+#define HMAC_BLOCK_SIZE 64
+
+static void __db_hmac __P((u_int8_t *, u_int8_t *, size_t, u_int8_t *));
+
+/*
+ * !!!
+ * All of these functions use a ctx structure on the stack. The __db_SHA1Init
+ * call does not initialize the 64-byte buffer portion of it. The
+ * underlying SHA1 functions will properly pad the buffer if the data length
+ * is less than 64-bytes, so there isn't a chance of reading uninitialized
+ * memory. Although it would be cleaner to do a memset(ctx.buffer, 0, 64)
+ * we do not want to incur that penalty if we don't have to for performance.
+ */
+
+/*
+ * __db_hmac --
+ * Do a hashed MAC.
+ */
+static void
+__db_hmac(k, data, data_len, mac)
+ u_int8_t *k, *data, *mac;
+ size_t data_len;
+{
+ SHA1_CTX ctx;
+ u_int8_t key[HMAC_BLOCK_SIZE];
+ u_int8_t ipad[HMAC_BLOCK_SIZE];
+ u_int8_t opad[HMAC_BLOCK_SIZE];
+ u_int8_t tmp[HMAC_OUTPUT_SIZE];
+ int i;
+
+ memset(key, 0x00, HMAC_BLOCK_SIZE);
+ memset(ipad, 0x36, HMAC_BLOCK_SIZE);
+ memset(opad, 0x5C, HMAC_BLOCK_SIZE);
+
+ memcpy(key, k, HMAC_OUTPUT_SIZE);
+
+ for (i = 0; i < HMAC_BLOCK_SIZE; i++) {
+ ipad[i] ^= key[i];
+ opad[i] ^= key[i];
+ }
+
+ __db_SHA1Init(&ctx);
+ __db_SHA1Update(&ctx, ipad, HMAC_BLOCK_SIZE);
+ __db_SHA1Update(&ctx, data, data_len);
+ __db_SHA1Final(tmp, &ctx);
+ __db_SHA1Init(&ctx);
+ __db_SHA1Update(&ctx, opad, HMAC_BLOCK_SIZE);
+ __db_SHA1Update(&ctx, tmp, HMAC_OUTPUT_SIZE);
+ __db_SHA1Final(mac, &ctx);
+ return;
+}
+
+/*
+ * __db_chksum --
+ * Create a MAC/SHA1 checksum.
+ *
+ * PUBLIC: void __db_chksum __P((u_int8_t *, size_t, u_int8_t *, u_int8_t *));
+ */
+void
+__db_chksum(data, data_len, mac_key, store)
+ u_int8_t *data;
+ size_t data_len;
+ u_int8_t *mac_key;
+ u_int8_t *store;
+{
+ int sumlen;
+ u_int32_t hash4;
+ u_int8_t tmp[DB_MAC_KEY];
+
+ /*
+ * Since the checksum might be on a page of data we are checksumming
+ * we might be overwriting after checksumming, we zero-out the
+ * checksum value so that we can have a known value there when
+ * we verify the checksum.
+ */
+ if (mac_key == NULL)
+ sumlen = sizeof(u_int32_t);
+ else
+ sumlen = DB_MAC_KEY;
+ memset(store, 0, sumlen);
+ if (mac_key == NULL) {
+ /* Just a hash, no MAC */
+ hash4 = __ham_func4(NULL, data, (u_int32_t)data_len);
+ memcpy(store, &hash4, sumlen);
+ } else {
+ memset(tmp, 0, DB_MAC_KEY);
+ __db_hmac(mac_key, data, data_len, tmp);
+ memcpy(store, tmp, sumlen);
+ }
+ return;
+}
+/*
+ * __db_derive_mac --
+ * Create a MAC/SHA1 key.
+ *
+ * PUBLIC: void __db_derive_mac __P((u_int8_t *, size_t, u_int8_t *));
+ */
+void
+__db_derive_mac(passwd, plen, mac_key)
+ u_int8_t *passwd;
+ size_t plen;
+ u_int8_t *mac_key;
+{
+ SHA1_CTX ctx;
+
+ /* Compute the MAC key. mac_key must be 20 bytes. */
+ __db_SHA1Init(&ctx);
+ __db_SHA1Update(&ctx, passwd, plen);
+ __db_SHA1Update(&ctx, (u_int8_t *)DB_MAC_MAGIC, strlen(DB_MAC_MAGIC));
+ __db_SHA1Update(&ctx, passwd, plen);
+ __db_SHA1Final(mac_key, &ctx);
+
+ return;
+}
+
+/*
+ * __db_check_chksum --
+ * Verify a checksum.
+ *
+ * Return 0 on success, >0 (errno) on error, -1 on checksum mismatch.
+ *
+ * PUBLIC: int __db_check_chksum __P((DB_ENV *,
+ * PUBLIC: DB_CIPHER *, u_int8_t *, void *, size_t, int));
+ */
+int
+__db_check_chksum(dbenv, db_cipher, chksum, data, data_len, is_hmac)
+ DB_ENV *dbenv;
+ DB_CIPHER *db_cipher;
+ u_int8_t *chksum;
+ void *data;
+ size_t data_len;
+ int is_hmac;
+{
+ int ret;
+ size_t sum_len;
+ u_int32_t hash4;
+ u_int8_t *mac_key, old[DB_MAC_KEY], new[DB_MAC_KEY];
+
+ /*
+ * If we are just doing checksumming and not encryption, then checksum
+ * is 4 bytes. Otherwise, it is DB_MAC_KEY size. Check for illegal
+ * combinations of crypto/non-crypto checksums.
+ */
+ if (is_hmac == 0) {
+ if (db_cipher != NULL) {
+ __db_err(dbenv,
+ "Unencrypted checksum with a supplied encryption key");
+ return (EINVAL);
+ }
+ sum_len = sizeof(u_int32_t);
+ mac_key = NULL;
+ } else {
+ if (db_cipher == NULL) {
+ __db_err(dbenv,
+ "Encrypted checksum: no encryption key specified");
+ return (EINVAL);
+ }
+ sum_len = DB_MAC_KEY;
+ mac_key = db_cipher->mac_key;
+ }
+
+ /*
+ * !!!
+ * Since the checksum might be on the page, we need to have known data
+ * there so that we can generate the same original checksum. We zero
+ * it out, just like we do in __db_chksum above.
+ */
+ memcpy(old, chksum, sum_len);
+ memset(chksum, 0, sum_len);
+ if (mac_key == NULL) {
+ /* Just a hash, no MAC */
+ hash4 = __ham_func4(NULL, data, (u_int32_t)data_len);
+ ret = memcmp((u_int32_t *)old, &hash4, sum_len) ? -1 : 0;
+ } else {
+ __db_hmac(mac_key, data, data_len, new);
+ ret = memcmp(old, new, sum_len) ? -1 : 0;
+ }
+
+ return (ret);
+}
diff --git a/bdb/hmac/sha1.c b/bdb/hmac/sha1.c
new file mode 100644
index 00000000000..2f2c806a21f
--- /dev/null
+++ b/bdb/hmac/sha1.c
@@ -0,0 +1,294 @@
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: sha1.c,v 1.13 2002/04/09 13:40:36 sue Exp $";
+#endif /* not lint */
+/*
+SHA-1 in C
+By Steve Reid <sreid@sea-to-sky.net>
+100% Public Domain
+
+-----------------
+Modified 7/98
+By James H. Brown <jbrown@burgoyne.com>
+Still 100% Public Domain
+
+Corrected a problem which generated improper hash values on 16 bit machines
+Routine SHA1Update changed from
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+len)
+to
+ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+long len)
+
+The 'len' parameter was declared an int which works fine on 32 bit machines.
+However, on 16 bit machines an int is too small for the shifts being done
+against
+it. This caused the hash function to generate incorrect values if len was
+greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+Since the file IO in main() reads 16K at a time, any file 8K or larger would
+be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+"a"s).
+
+I also changed the declaration of variables i & j in SHA1Update to
+unsigned long from unsigned int for the same reason.
+
+These changes should make no difference to any 32 bit implementations since
+an
+int and a long are the same size in those environments.
+
+--
+I also corrected a few compiler warnings generated by Borland C.
+1. Added #include <process.h> for exit() prototype
+2. Removed unused variable 'j' in SHA1Final
+3. Changed exit(0) to return(0) at end of main.
+
+ALL changes I made can be located by searching for comments containing 'JHB'
+-----------------
+Modified 8/98
+By Steve Reid <sreid@sea-to-sky.net>
+Still 100% public domain
+
+1- Removed #include <process.h> and used return() instead of exit()
+2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
+
+-----------------
+Modified 4/01
+By Saul Kravitz <Saul.Kravitz@celera.com>
+Still 100% PD
+Modified to run on Compaq Alpha hardware.
+
+
+*/
+
+/*
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#define SHA1HANDSOFF
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/hmac.h"
+
+/* #include <process.h> */ /* prototype for exit() - JHB */
+/* Using return() instead of exit() - SWR */
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#define blk0(i) is_bigendian ? block->l[i] : \
+ (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+#ifdef VERBOSE /* SAK */
+static void __db_SHAPrintContext __P((SHA1_CTX *, char *));
+static void
+__db_SHAPrintContext(context, msg)
+ SHA1_CTX *context;
+ char *msg;
+{
+ printf("%s (%d,%d) %x %x %x %x %x\n",
+ msg,
+ context->count[0], context->count[1],
+ context->state[0],
+ context->state[1],
+ context->state[2],
+ context->state[3],
+ context->state[4]);
+}
+#endif
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+/*
+ * __db_SHA1Transform --
+ *
+ * PUBLIC: void __db_SHA1Transform __P((u_int32_t *, unsigned char *));
+ */
+void
+__db_SHA1Transform(state, buffer)
+ u_int32_t *state;
+ unsigned char *buffer;
+{
+u_int32_t a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ u_int32_t l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+static int is_bigendian = -1;
+#ifdef SHA1HANDSOFF
+ unsigned char workspace[64];
+
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ if (is_bigendian == -1)
+ is_bigendian = __db_isbigendian();
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+/*
+ * __db_SHA1Init --
+ * Initialize new context
+ *
+ * PUBLIC: void __db_SHA1Init __P((SHA1_CTX *));
+ */
+void
+__db_SHA1Init(context)
+ SHA1_CTX *context;
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+/*
+ * __db_SHA1Update --
+ * Run your data through this.
+ *
+ * PUBLIC: void __db_SHA1Update __P((SHA1_CTX *, unsigned char *,
+ * PUBLIC: size_t));
+ */
+void
+__db_SHA1Update(context, data, len)
+ SHA1_CTX *context;
+ unsigned char *data;
+ size_t len;
+{
+u_int32_t i, j; /* JHB */
+
+#ifdef VERBOSE
+ __db_SHAPrintContext(context, "before");
+#endif
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += (u_int32_t)len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (u_int32_t)(len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ __db_SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ __db_SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+#ifdef VERBOSE
+ __db_SHAPrintContext(context, "after ");
+#endif
+}
+
+
+/* Add padding and return the message digest. */
+
+/*
+ * __db_SHA1Final --
+ * Add padding and return the message digest.
+ *
+ * PUBLIC: void __db_SHA1Final __P((unsigned char *, SHA1_CTX *));
+ */
+void
+__db_SHA1Final(digest, context)
+ unsigned char *digest;
+ SHA1_CTX *context;
+{
+u_int32_t i; /* JHB */
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ __db_SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ __db_SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ __db_SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
+*/
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = 0; /* JHB */
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(finalcount, 0, 8); /* SWR */
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ __db_SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+/*************************************************************/
+
diff --git a/bdb/hsearch/hsearch.c b/bdb/hsearch/hsearch.c
index c2869c4c47c..9760aeeb9e8 100644
--- a/bdb/hsearch/hsearch.c
+++ b/bdb/hsearch/hsearch.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hsearch.c,v 11.5 2000/11/30 00:58:37 ubell Exp $";
+static const char revid[] = "$Id: hsearch.c,v 11.12 2002/02/22 01:55:57 mjc Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -58,6 +58,18 @@ static const char revid[] = "$Id: hsearch.c,v 11.5 2000/11/30 00:58:37 ubell Exp
static DB *dbp;
static ENTRY retval;
+/*
+ * Translate HSEARCH calls into DB calls so that DB doesn't step on the
+ * application's name space.
+ *
+ * EXTERN: #if DB_DBM_HSEARCH != 0
+ *
+ * EXTERN: int __db_hcreate __P((size_t));
+ * EXTERN: ENTRY *__db_hsearch __P((ENTRY, ACTION));
+ * EXTERN: void __db_hdestroy __P((void));
+ *
+ * EXTERN: #endif
+ */
int
__db_hcreate(nel)
size_t nel;
@@ -71,9 +83,9 @@ __db_hcreate(nel)
if ((ret = dbp->set_pagesize(dbp, 512)) != 0 ||
(ret = dbp->set_h_ffactor(dbp, 16)) != 0 ||
- (ret = dbp->set_h_nelem(dbp, nel)) != 0 ||
+ (ret = dbp->set_h_nelem(dbp, (u_int32_t)nel)) != 0 ||
(ret = dbp->open(dbp,
- NULL, NULL, DB_HASH, DB_CREATE, __db_omode("rw----"))) != 0)
+ NULL, NULL, NULL, DB_HASH, DB_CREATE, __db_omode("rw----"))) != 0)
__os_set_errno(ret);
/*
@@ -98,12 +110,12 @@ __db_hsearch(item, action)
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
key.data = item.key;
- key.size = strlen(item.key) + 1;
+ key.size = (u_int32_t)strlen(item.key) + 1;
switch (action) {
case ENTER:
val.data = item.data;
- val.size = strlen(item.data) + 1;
+ val.size = (u_int32_t)strlen(item.data) + 1;
/*
* Try and add the key to the database. If we fail because
diff --git a/bdb/include/btree.h b/bdb/include/btree.h
deleted file mode 100644
index 395f645f03f..00000000000
--- a/bdb/include/btree.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994, 1995
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: btree.h,v 11.37 2001/01/17 17:09:52 bostic Exp $
- */
-
-/* Forward structure declarations. */
-struct __btree; typedef struct __btree BTREE;
-struct __cursor; typedef struct __cursor BTREE_CURSOR;
-struct __epg; typedef struct __epg EPG;
-struct __recno; typedef struct __recno RECNO;
-
-#define DEFMINKEYPAGE (2)
-
-/*
- * A recno order of 0 indicates that we don't have an order, not that we've
- * an order less than 1.
- */
-#define INVALID_ORDER 0
-
-#define ISINTERNAL(p) (TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO)
-#define ISLEAF(p) (TYPE(p) == P_LBTREE || \
- TYPE(p) == P_LRECNO || TYPE(p) == P_LDUP)
-
-/* Flags for __bam_cadjust_log(). */
-#define CAD_UPDATEROOT 0x01 /* Root page count was updated. */
-
-/* Flags for __bam_split_log(). */
-#define SPL_NRECS 0x01 /* Split tree has record count. */
-
-/* Flags for __bam_iitem(). */
-#define BI_DELETED 0x01 /* Key/data pair only placeholder. */
-
-/* Flags for __bam_stkrel(). */
-#define STK_CLRDBC 0x01 /* Clear dbc->page reference. */
-#define STK_NOLOCK 0x02 /* Don't retain locks. */
-
-/* Flags for __ram_ca(). These get logged, so make the values explicit. */
-typedef enum {
- CA_DELETE = 0, /* Delete the current record. */
- CA_IAFTER = 1, /* Insert before the current record. */
- CA_IBEFORE = 2, /* Insert after the current record. */
- CA_ICURRENT = 3 /* Overwrite the current record. */
-} ca_recno_arg;
-
-/*
- * Flags for __bam_search() and __bam_rsearch().
- *
- * Note, internal page searches must find the largest record less than key in
- * the tree so that descents work. Leaf page searches must find the smallest
- * record greater than key so that the returned index is the record's correct
- * position for insertion.
- *
- * The flags parameter to the search routines describes three aspects of the
- * search: the type of locking required (including if we're locking a pair of
- * pages), the item to return in the presence of duplicates and whether or not
- * to return deleted entries. To simplify both the mnemonic representation
- * and the code that checks for various cases, we construct a set of bitmasks.
- */
-#define S_READ 0x00001 /* Read locks. */
-#define S_WRITE 0x00002 /* Write locks. */
-
-#define S_APPEND 0x00040 /* Append to the tree. */
-#define S_DELNO 0x00080 /* Don't return deleted items. */
-#define S_DUPFIRST 0x00100 /* Return first duplicate. */
-#define S_DUPLAST 0x00200 /* Return last duplicate. */
-#define S_EXACT 0x00400 /* Exact items only. */
-#define S_PARENT 0x00800 /* Lock page pair. */
-#define S_STACK 0x01000 /* Need a complete stack. */
-#define S_PAST_EOF 0x02000 /* If doing insert search (or keyfirst
- * or keylast operations), or a split
- * on behalf of an insert, it's okay to
- * return an entry one past end-of-page.
- */
-#define S_STK_ONLY 0x04000 /* Just return info in the stack */
-
-#define S_DELETE (S_WRITE | S_DUPFIRST | S_DELNO | S_EXACT | S_STACK)
-#define S_FIND (S_READ | S_DUPFIRST | S_DELNO)
-#define S_FIND_WR (S_WRITE | S_DUPFIRST | S_DELNO)
-#define S_INSERT (S_WRITE | S_DUPLAST | S_PAST_EOF | S_STACK)
-#define S_KEYFIRST (S_WRITE | S_DUPFIRST | S_PAST_EOF | S_STACK)
-#define S_KEYLAST (S_WRITE | S_DUPLAST | S_PAST_EOF | S_STACK)
-#define S_WRPAIR (S_WRITE | S_DUPLAST | S_PAST_EOF | S_PARENT)
-
-/*
- * Various routines pass around page references. A page reference is
- * a pointer to the page, and the indx indicates an item on the page.
- * Each page reference may include a lock.
- */
-struct __epg {
- PAGE *page; /* The page. */
- db_indx_t indx; /* The index on the page. */
- db_indx_t entries; /* The number of entries on page */
- DB_LOCK lock; /* The page's lock. */
- db_lockmode_t lock_mode; /* The lock mode. */
-};
-
-/*
- * We maintain a stack of the pages that we're locking in the tree. Grow
- * the stack as necessary.
- *
- * XXX
- * Temporary fix for #3243 -- clear the page and lock from the stack entry.
- * The correct fix is to never release a stack that doesn't hold items.
- */
-#define BT_STK_CLR(c) do { \
- (c)->csp = (c)->sp; \
- (c)->csp->page = NULL; \
- (c)->csp->lock.off = LOCK_INVALID; \
-} while (0)
-
-#define BT_STK_ENTER(dbenv, c, pagep, page_indx, l, mode, ret) do { \
- if ((ret = \
- (c)->csp == (c)->esp ? __bam_stkgrow(dbenv, c) : 0) == 0) { \
- (c)->csp->page = pagep; \
- (c)->csp->indx = page_indx; \
- (c)->csp->entries = NUM_ENT(pagep); \
- (c)->csp->lock = l; \
- (c)->csp->lock_mode = mode; \
- } \
-} while (0)
-
-#define BT_STK_PUSH(dbenv, c, pagep, page_indx, lock, mode, ret) do { \
- BT_STK_ENTER(dbenv, c, pagep, page_indx, lock, mode, ret); \
- ++(c)->csp; \
-} while (0)
-
-#define BT_STK_NUM(dbenv, c, pagep, page_indx, ret) do { \
- if ((ret = \
- (c)->csp == (c)->esp ? __bam_stkgrow(dbenv, c) : 0) == 0) { \
- (c)->csp->page = NULL; \
- (c)->csp->indx = page_indx; \
- (c)->csp->entries = NUM_ENT(pagep); \
- (c)->csp->lock.off = LOCK_INVALID; \
- (c)->csp->lock_mode = DB_LOCK_NG; \
- } \
-} while (0)
-
-#define BT_STK_NUMPUSH(dbenv, c, pagep, page_indx,ret) do { \
- BT_STK_NUM(dbenv, cp, pagep, page_indx, ret); \
- ++(c)->csp; \
-} while (0)
-
-#define BT_STK_POP(c) \
- ((c)->csp == (c)->sp ? NULL : --(c)->csp)
-
-/* Btree/Recno cursor. */
-struct __cursor {
- /* struct __dbc_internal */
- __DBC_INTERNAL
-
- /* btree private part */
- EPG *sp; /* Stack pointer. */
- EPG *csp; /* Current stack entry. */
- EPG *esp; /* End stack pointer. */
- EPG stack[5];
-
- db_indx_t ovflsize; /* Maximum key/data on-page size. */
-
- db_recno_t recno; /* Current record number. */
- u_int32_t order; /* Relative order among deleted curs. */
-
- /*
- * Btree:
- * We set a flag in the cursor structure if the underlying object has
- * been deleted. It's not strictly necessary, we could get the same
- * information by looking at the page itself, but this method doesn't
- * require us to retrieve the page on cursor delete.
- *
- * Recno:
- * When renumbering recno databases during deletes, cursors referencing
- * "deleted" records end up positioned between two records, and so must
- * be specially adjusted on the next operation.
- */
-#define C_DELETED 0x0001 /* Record was deleted. */
- /*
- * There are three tree types that require maintaining record numbers.
- * Recno AM trees, Btree AM trees for which the DB_RECNUM flag was set,
- * and Btree off-page duplicate trees.
- */
-#define C_RECNUM 0x0002 /* Tree requires record counts. */
- /*
- * Recno trees have immutable record numbers by default, but optionally
- * support mutable record numbers. Off-page duplicate Recno trees have
- * mutable record numbers. All Btrees with record numbers (including
- * off-page duplicate trees) are mutable by design, no flag is needed.
- */
-#define C_RENUMBER 0x0004 /* Tree records are mutable. */
- u_int32_t flags;
-};
-
-/*
- * Threshhold value, as a function of bt_minkey, of the number of
- * bytes a key/data pair can use before being placed on an overflow
- * page. Assume every item requires the maximum alignment for
- * padding, out of sheer paranoia.
- */
-#define B_MINKEY_TO_OVFLSIZE(minkey, pgsize) \
- ((u_int16_t)(((pgsize) - P_OVERHEAD) / ((minkey) * P_INDX) - \
- (BKEYDATA_PSIZE(0) + ALIGN(1, sizeof(int32_t)))))
-
-/*
- * The maximum space that a single item can ever take up on one page.
- * Used by __bam_split to determine whether a split is still necessary.
- */
-#define B_MAX(a,b) (((a) > (b)) ? (a) : (b))
-#define B_MAXSIZEONPAGE(ovflsize) \
- (B_MAX(BOVERFLOW_PSIZE, BKEYDATA_PSIZE(ovflsize)))
-
-/*
- * The in-memory, per-tree btree/recno data structure.
- */
-struct __btree { /* Btree access method. */
- /*
- * !!!
- * These fields are write-once (when the structure is created) and
- * so are ignored as far as multi-threading is concerned.
- */
- db_pgno_t bt_meta; /* Database meta-data page. */
- db_pgno_t bt_root; /* Database root page. */
-
- u_int32_t bt_maxkey; /* Maximum keys per page. */
- u_int32_t bt_minkey; /* Minimum keys per page. */
-
- /* Btree comparison function. */
- int (*bt_compare) __P((DB *, const DBT *, const DBT *));
- /* Btree prefix function. */
- size_t (*bt_prefix) __P((DB *, const DBT *, const DBT *));
-
- /* Recno access method. */
- int re_pad; /* Fixed-length padding byte. */
- int re_delim; /* Variable-length delimiting byte. */
- u_int32_t re_len; /* Length for fixed-length records. */
- char *re_source; /* Source file name. */
-
- /*
- * !!!
- * The bt_lpgno field is NOT protected by any mutex, and for this
- * reason must be advisory only, so, while it is read/written by
- * multiple threads, DB is completely indifferent to the quality
- * of its information.
- */
- db_pgno_t bt_lpgno; /* Last insert location. */
-
- /*
- * !!!
- * The re_modified field is NOT protected by any mutex, and for this
- * reason cannot be anything more complicated than a zero/non-zero
- * value. The actual writing of the backing source file cannot be
- * threaded, so clearing the flag isn't a problem.
- */
- int re_modified; /* If the tree was modified. */
-
- /*
- * !!!
- * These fields are ignored as far as multi-threading is concerned.
- * There are no transaction semantics associated with backing files,
- * nor is there any thread protection.
- */
- FILE *re_fp; /* Source file handle. */
- int re_eof; /* Backing source file EOF reached. */
- db_recno_t re_last; /* Last record number read. */
-};
-
-/*
- * Modes for the __bam_curadj recovery records (btree_curadj).
- * These appear in log records, so we wire the values and
- * do not leave it up to the compiler.
- */
-typedef enum {
- DB_CA_DI = 1,
- DB_CA_DUP = 2,
- DB_CA_RSPLIT = 3,
- DB_CA_SPLIT = 4
-} db_ca_mode;
-
-#include "btree_auto.h"
-#include "btree_ext.h"
-#include "db_am.h"
diff --git a/bdb/include/cxx_int.h b/bdb/include/cxx_int.h
deleted file mode 100644
index 4a9a40ceba1..00000000000
--- a/bdb/include/cxx_int.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: cxx_int.h,v 11.13 2000/11/21 22:56:36 dda Exp $
- */
-
-#ifndef _CXX_INT_H_
-#define _CXX_INT_H_
-
-// private data structures known to the implementation only
-
-//
-// Using FooImp classes will allow the implementation to change in the
-// future without any modification to user code or even to header files
-// that the user includes. FooImp * is just like void * except that it
-// provides a little extra protection, since you cannot randomly assign
-// any old pointer to a FooImp* as you can with void *. Currently, a
-// pointer to such an opaque class is always just a pointer to the
-// appropriate underlying implementation struct. These are converted
-// back and forth using the various overloaded wrap()/unwrap() methods.
-// This is essentially a use of the "Bridge" Design Pattern.
-//
-// WRAPPED_CLASS implements the appropriate wrap() and unwrap() methods
-// for a wrapper class that has an underlying pointer representation.
-//
-#define WRAPPED_CLASS(_WRAPPER_CLASS, _IMP_CLASS, _WRAPPED_TYPE) \
- \
- class _IMP_CLASS {}; \
- \
- inline _WRAPPED_TYPE unwrap(_WRAPPER_CLASS *val) \
- { \
- if (!val) return (0); \
- return ((_WRAPPED_TYPE)((void *)(val->imp()))); \
- } \
- \
- inline const _WRAPPED_TYPE unwrapConst(const _WRAPPER_CLASS *val) \
- { \
- if (!val) return (0); \
- return ((const _WRAPPED_TYPE)((void *)(val->constimp()))); \
- } \
- \
- inline _IMP_CLASS *wrap(_WRAPPED_TYPE val) \
- { \
- return ((_IMP_CLASS*)((void *)val)); \
- }
-
-WRAPPED_CLASS(DbMpoolFile, DbMpoolFileImp, DB_MPOOLFILE*)
-WRAPPED_CLASS(Db, DbImp, DB*)
-WRAPPED_CLASS(DbEnv, DbEnvImp, DB_ENV*)
-WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN*)
-
-// A tristate integer value used by the DB_ERROR macro below.
-// We chose not to make this an enumerated type so it can
-// be kept private, even though methods that return the
-// tristate int can be declared in db_cxx.h .
-//
-#define ON_ERROR_THROW 1
-#define ON_ERROR_RETURN 0
-#define ON_ERROR_UNKNOWN (-1)
-
-// Macros that handle detected errors, in case we want to
-// change the default behavior. The 'policy' is one of
-// the tristate values given above. If UNKNOWN is specified,
-// the behavior is taken from the last initialized DbEnv.
-//
-#define DB_ERROR(caller, ecode, policy) \
- DbEnv::runtime_error(caller, ecode, policy)
-
-// These defines are for tedious field set/get access methods.
-//
-
-#define DB_RO_ACCESS(_class, _type, _cxx_name, _field) \
- \
-_type _class::get_##_cxx_name() const \
-{ \
- return (_field); \
-}
-
-#define DB_WO_ACCESS(_class, _type, _cxx_name, _field) \
- \
-void _class::set_##_cxx_name(_type value) \
-{ \
- _field = value; \
-} \
-
-#define DB_RW_ACCESS(_class, _type, _cxx_name, _field) \
- DB_RO_ACCESS(_class, _type, _cxx_name, _field) \
- DB_WO_ACCESS(_class, _type, _cxx_name, _field)
-
-/* values for Db::flags_ */
-#define DB_CXX_PRIVATE_ENV 0x00000001
-
-#endif /* !_CXX_INT_H_ */
diff --git a/bdb/include/db.src b/bdb/include/db.src
deleted file mode 100644
index 5226d4e98c6..00000000000
--- a/bdb/include/db.src
+++ /dev/null
@@ -1,1383 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db.src,v 11.121 2001/01/10 15:43:08 sue Exp $
- */
-
-#ifndef _DB_H_
-#define _DB_H_
-
-#ifndef __NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <stdio.h>
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
- * XXX
- * Handle function prototypes and the keyword "const". This steps on name
- * space that DB doesn't control, but all of the other solutions are worse.
- *
- * XXX
- * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
- * defined by default, you specify a command line flag or #pragma to turn
- * it on. Don't do that, however, because some of Microsoft's own header
- * files won't compile.
- */
-#undef __P
-#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
-#define __P(protos) protos /* ANSI C prototypes */
-#else
-#define const
-#define __P(protos) () /* K&R C preprocessor */
-#endif
-
-/*
- * !!!
- * DB needs basic information about specifically sized types. If they're
- * not provided by the system, typedef them here.
- *
- * We protect them against multiple inclusion using __BIT_TYPES_DEFINED__,
- * as does BIND and Kerberos, since we don't know for sure what #include
- * files the user is using.
- *
- * !!!
- * We also provide the standard u_int, u_long etc., if they're not provided
- * by the system.
- */
-#ifndef __BIT_TYPES_DEFINED__
-#define __BIT_TYPES_DEFINED__
-@u_int8_decl@
-@int16_decl@
-@u_int16_decl@
-@int32_decl@
-@u_int32_decl@
-#endif
-
-@u_char_decl@
-@u_short_decl@
-@u_int_decl@
-@u_long_decl@
-@ssize_t_decl@
-
-#define DB_VERSION_MAJOR @DB_VERSION_MAJOR@
-#define DB_VERSION_MINOR @DB_VERSION_MINOR@
-#define DB_VERSION_PATCH @DB_VERSION_PATCH@
-#define DB_VERSION_STRING @DB_VERSION_STRING@
-
-typedef u_int32_t db_pgno_t; /* Page number type. */
-typedef u_int16_t db_indx_t; /* Page offset type. */
-#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */
-
-typedef u_int32_t db_recno_t; /* Record number type. */
-#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */
-
-/* Forward structure declarations, so applications get type checking. */
-struct __db; typedef struct __db DB;
-#ifdef DB_DBM_HSEARCH
- typedef struct __db DBM;
-#endif
-struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT;
-struct __db_dbt; typedef struct __db_dbt DBT;
-struct __db_env; typedef struct __db_env DB_ENV;
-struct __db_h_stat; typedef struct __db_h_stat DB_HASH_STAT;
-struct __db_ilock; typedef struct __db_ilock DB_LOCK_ILOCK;
-struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
-struct __db_lock_u; typedef struct __db_lock_u DB_LOCK;
-struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
-struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
-struct __db_lsn; typedef struct __db_lsn DB_LSN;
-struct __db_mpool_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
-struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
-struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
-struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
-struct __db_qam_stat; typedef struct __db_qam_stat DB_QUEUE_STAT;
-struct __db_txn; typedef struct __db_txn DB_TXN;
-struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE;
-struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT;
-struct __dbc; typedef struct __dbc DBC;
-struct __dbc_internal; typedef struct __dbc_internal DBC_INTERNAL;
-struct __fh_t; typedef struct __fh_t DB_FH;
-struct __key_range; typedef struct __key_range DB_KEY_RANGE;
-
-/* Key/data structure -- a Data-Base Thang. */
-struct __db_dbt {
- /*
- * data/size must be fields 1 and 2 for DB 1.85 compatibility.
- */
- void *data; /* Key/data */
- u_int32_t size; /* key/data length */
-
- u_int32_t ulen; /* RO: length of user buffer. */
- u_int32_t dlen; /* RO: get/put record length. */
- u_int32_t doff; /* RO: get/put record offset. */
-
- void *app_private; /* Application-private handle. */
-#define DB_DBT_ISSET 0x001 /* Lower level calls set value. */
-#define DB_DBT_MALLOC 0x002 /* Return in malloc'd memory. */
-#define DB_DBT_PARTIAL 0x004 /* Partial put/get. */
-#define DB_DBT_REALLOC 0x008 /* Return in realloc'd memory. */
-#define DB_DBT_USERMEM 0x010 /* Return in user's memory. */
-#define DB_DBT_DUPOK 0x020 /* Insert if duplicate. */
- u_int32_t flags;
-};
-
-/*
- * Common flags --
- * Interfaces which use any of these common flags should never have
- * interface specific flags in this range.
- */
-#define DB_CREATE 0x000001 /* Create file as necessary. */
-#define DB_CXX_NO_EXCEPTIONS 0x000002 /* C++: return error values. */
-#define DB_FORCE 0x000004 /* Force (anything). */
-#define DB_NOMMAP 0x000008 /* Don't mmap underlying file. */
-#define DB_RDONLY 0x000010 /* Read-only (O_RDONLY). */
-#define DB_RECOVER 0x000020 /* Run normal recovery. */
-#define DB_THREAD 0x000040 /* Applications are threaded. */
-#define DB_TXN_NOSYNC 0x000080 /* Do not sync log on commit. */
-#define DB_USE_ENVIRON 0x000100 /* Use the environment. */
-#define DB_USE_ENVIRON_ROOT 0x000200 /* Use the environment if root. */
-
-/*
- * Flags private to db_env_create.
- */
-#define DB_CLIENT 0x000400 /* Open for a client environment. */
-
-/*
- * Flags private to db_create.
- */
-#define DB_XA_CREATE 0x000400 /* Open in an XA environment. */
-
-/*
- * Flags private to DBENV->open.
- */
-#define DB_INIT_CDB 0x000400 /* Concurrent Access Methods. */
-#define DB_INIT_LOCK 0x000800 /* Initialize locking. */
-#define DB_INIT_LOG 0x001000 /* Initialize logging. */
-#define DB_INIT_MPOOL 0x002000 /* Initialize mpool. */
-#define DB_INIT_TXN 0x004000 /* Initialize transactions. */
-#define DB_JOINENV 0x008000 /* Initialize all subsystems present. */
-#define DB_LOCKDOWN 0x010000 /* Lock memory into physical core. */
-#define DB_PRIVATE 0x020000 /* DB_ENV is process local. */
-#define DB_RECOVER_FATAL 0x040000 /* Run catastrophic recovery. */
-#define DB_SYSTEM_MEM 0x080000 /* Use system-backed memory. */
-
-/*
- * Flags private to DB->open.
- */
-#define DB_EXCL 0x000400 /* Exclusive open (O_EXCL). */
-#define DB_FCNTL_LOCKING 0x000800 /* UNDOC: fcntl(2) locking. */
-#define DB_ODDFILESIZE 0x001000 /* UNDOC: truncate to N * pgsize. */
-#define DB_RDWRMASTER 0x002000 /* UNDOC: allow subdb master open R/W */
-#define DB_TRUNCATE 0x004000 /* Discard existing DB (O_TRUNC). */
-#define DB_EXTENT 0x008000 /* UNDOC: dealing with an extent. */
-
-/*
- * Flags private to DBENV->txn_begin.
- */
-#define DB_TXN_NOWAIT 0x000400 /* Do not wait for locks in this TXN. */
-#define DB_TXN_SYNC 0x000800 /* Always sync log on commit. */
-
-/*
- * Flags private to DBENV->set_flags.
- */
-#define DB_CDB_ALLDB 0x000400 /* In CDB, lock across environment. */
-
-/*
- * Flags private to DB->set_feedback's callback.
- */
-#define DB_UPGRADE 0x000400 /* Upgrading. */
-#define DB_VERIFY 0x000800 /* Verifying. */
-
-/*
- * Flags private to DB->set_flags.
- *
- * DB->set_flags does not share common flags and so values start at 0x01.
- */
-#define DB_DUP 0x0001 /* Btree, Hash: duplicate keys. */
-#define DB_DUPSORT 0x0002 /* Btree, Hash: duplicate keys. */
-#define DB_RECNUM 0x0004 /* Btree: record numbers. */
-#define DB_RENUMBER 0x0008 /* Recno: renumber on insert/delete. */
-#define DB_REVSPLITOFF 0x0010 /* Btree: turn off reverse splits. */
-#define DB_SNAPSHOT 0x0020 /* Recno: snapshot the input. */
-
-/*
- * Flags private to DB->join.
- *
- * DB->join does not share common flags and so values start at 0x01.
- */
-#define DB_JOIN_NOSORT 0x0001 /* Don't try to optimize join. */
-
-/*
- * Flags private to DB->verify.
- *
- * DB->verify does not share common flags and so values start at 0x01.
- */
-#define DB_AGGRESSIVE 0x0001 /* Salvage anything which might be data.*/
-#define DB_NOORDERCHK 0x0002 /* Skip order check; subdb w/ user func */
-#define DB_ORDERCHKONLY 0x0004 /* Only perform an order check on subdb */
-#define DB_PR_PAGE 0x0008 /* Show page contents (-da). */
-#define DB_PR_HEADERS 0x0010 /* Show only page headers (-dh). */
-#define DB_PR_RECOVERYTEST 0x0020 /* Recovery test (-dr). */
-#define DB_SALVAGE 0x0040 /* Salvage what looks like data. */
-/*
- * !!!
- * These must not go over 0x8000, or they will collide with the flags
- * used by __bam_vrfy_subtree.
- */
-#define DB_VRFY_FLAGMASK 0xffff /* For masking above flags. */
-
-/*
- * Deadlock detector modes; used in the DBENV structure to configure the
- * locking subsystem.
- */
-#define DB_LOCK_NORUN 0
-#define DB_LOCK_DEFAULT 1 /* Default policy. */
-#define DB_LOCK_OLDEST 2 /* Abort oldest transaction. */
-#define DB_LOCK_RANDOM 3 /* Abort random transaction. */
-#define DB_LOCK_YOUNGEST 4 /* Abort youngest transaction. */
-
-/*******************************************************
- * Environment.
- *******************************************************/
-#define DB_REGION_MAGIC 0x120897 /* Environment magic number. */
-
-typedef enum {
- DB_NOTICE_LOGFILE_CHANGED
- /* DB_NOTICE_DISK_LOW */
-} db_notices;
-
-typedef enum {
- DB_TXN_ABORT,
- DB_TXN_BACKWARD_ROLL,
- DB_TXN_FORWARD_ROLL,
- DB_TXN_OPENFILES
-} db_recops;
-
-#define DB_UNDO(op) ((op) == DB_TXN_ABORT || (op) == DB_TXN_BACKWARD_ROLL)
-#define DB_REDO(op) ((op) == DB_TXN_FORWARD_ROLL)
-
-struct __db_env {
- /*******************************************************
- * Public: owned by the application.
- *******************************************************/
- FILE *db_errfile; /* Error message file stream. */
- const char *db_errpfx; /* Error message prefix. */
- /* Callbacks. */
- void (*db_errcall) __P((const char *, char *));
- void (*db_feedback) __P((DB_ENV *, int, int));
- void (*db_noticecall) __P((DB_ENV *, db_notices));
- void (*db_paniccall) __P((DB_ENV *, int));
- int (*db_recovery_init) __P((DB_ENV *));
-
- /*
- * Currently, the verbose list is a bit field with room for 32
- * entries. There's no reason that it needs to be limited, if
- * there are ever more than 32 entries, convert to a bit array.
- */
-#define DB_VERB_CHKPOINT 0x0001 /* List checkpoints. */
-#define DB_VERB_DEADLOCK 0x0002 /* Deadlock detection information. */
-#define DB_VERB_RECOVERY 0x0004 /* Recovery information. */
-#define DB_VERB_WAITSFOR 0x0008 /* Dump waits-for table. */
- u_int32_t verbose; /* Verbose output. */
-
- void *app_private; /* Application-private handle. */
-
- /* Locking. */
- u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
- u_int32_t lk_modes; /* Number of lock modes in table. */
- u_int32_t lk_max; /* Maximum number of locks. */
- u_int32_t lk_max_lockers;/* Maximum number of lockers. */
- u_int32_t lk_max_objects;/* Maximum number of locked objects. */
- u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
-
- /* Logging. */
- u_int32_t lg_bsize; /* Buffer size. */
- u_int32_t lg_max; /* Maximum file size. */
-
- /* Memory pool. */
- u_int32_t mp_gbytes; /* Cachesize: GB. */
- u_int32_t mp_bytes; /* Cachesize: Bytes. */
- size_t mp_size; /* DEPRECATED: Cachesize: bytes. */
- int mp_ncache; /* Number of cache regions. */
- size_t mp_mmapsize; /* Maximum file size for mmap. */
-
- /* Transactions. */
- u_int32_t tx_max; /* Maximum number of transactions. */
- time_t tx_timestamp; /* Recover to specific timestamp. */
- int (*tx_recover) /* Dispatch function for recovery. */
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
-
- /*******************************************************
- * Private: owned by DB.
- *******************************************************/
- int db_panic; /* Panic causing errno. */
-
- /* User files, paths. */
- char *db_home; /* Database home. */
- char *db_log_dir; /* Database log file directory. */
- char *db_tmp_dir; /* Database tmp file directory. */
-
- char **db_data_dir; /* Database data file directories. */
- int data_cnt; /* Database data file slots. */
- int data_next; /* Next Database data file slot. */
-
- int db_mode; /* Default open permissions. */
-
- void *reginfo; /* REGINFO structure reference. */
- DB_FH *lockfhp; /* fcntl(2) locking file handle. */
- long shm_key; /* shmget(2) key. */
-
- void *lg_handle; /* Log handle. */
-
- void *lk_handle; /* Lock handle. */
-
- void *mp_handle; /* Mpool handle. */
-
- void *tx_handle; /* Txn handle. */
-
- int (**dtab) /* Dispatch table */
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- size_t dtab_size; /* Slots in the dispatch table. */
-
- void *cl_handle; /* RPC: remote client handle. */
- long cl_id; /* RPC: Remote client env id. */
-
- int dblocal_ref; /* DB_ENV_DBLOCAL: reference count. */
- u_int32_t db_mutexlocks; /* db_set_mutexlocks */
-
- /*
- * List of open DB handles for this DB_ENV, used for cursor
- * adjustment. Must be protected for multi-threaded support.
- *
- * !!!
- * As this structure is allocated in per-process memory, the
- * mutex may need to be stored elsewhere on architectures unable
- * to support mutexes in heap memory, e.g. HP/UX 9.
- */
- void *dblist_mutexp; /* Mutex. */
- /*
- * !!!
- * Explicit representation of structure in queue.h.
- * LIST_HEAD(dblist, __db);
- */
- struct {
- struct __db *lh_first;
- } dblist;
-
- /*
- * XA support.
- *
- * !!!
- * Explicit representations of structures in queue.h.
- *
- * TAILQ_ENTRY(__db_env);
- */
- struct {
- struct __db_env *tqe_next;
- struct __db_env **tqe_prev;
- } links;
- int xa_rmid; /* XA Resource Manager ID. */
- DB_TXN *xa_txn; /* XA Current transaction. */
-
- void *cj_internal; /* C++/Java private. */
-
- /* Methods. */
- int (*close) __P((DB_ENV *, u_int32_t));
- void (*err) __P((const DB_ENV *, int, const char *, ...));
- void (*errx) __P((const DB_ENV *, const char *, ...));
- int (*open) __P((DB_ENV *, const char *, u_int32_t, int));
- int (*remove) __P((DB_ENV *, const char *, u_int32_t));
- int (*set_data_dir) __P((DB_ENV *, const char *));
- void (*set_errcall) __P((DB_ENV *, void (*)(const char *, char *)));
- void (*set_errfile) __P((DB_ENV *, FILE *));
- void (*set_errpfx) __P((DB_ENV *, const char *));
- int (*set_feedback) __P((DB_ENV *, void (*)(DB_ENV *, int, int)));
- int (*set_flags) __P((DB_ENV *, u_int32_t, int));
- int (*set_mutexlocks) __P((DB_ENV *, int));
- void (*set_noticecall) __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
- int (*set_paniccall) __P((DB_ENV *, void (*)(DB_ENV *, int)));
- int (*set_recovery_init) __P((DB_ENV *, int (*)(DB_ENV *)));
- int (*set_server) __P((DB_ENV *, char *, long, long, u_int32_t));
- int (*set_shm_key) __P((DB_ENV *, long));
- int (*set_tmp_dir) __P((DB_ENV *, const char *));
- int (*set_verbose) __P((DB_ENV *, u_int32_t, int));
-
- int (*set_lg_bsize) __P((DB_ENV *, u_int32_t));
- int (*set_lg_dir) __P((DB_ENV *, const char *));
- int (*set_lg_max) __P((DB_ENV *, u_int32_t));
-
- int (*set_lk_conflicts) __P((DB_ENV *, u_int8_t *, int));
- int (*set_lk_detect) __P((DB_ENV *, u_int32_t));
- int (*set_lk_max) __P((DB_ENV *, u_int32_t));
- int (*set_lk_max_locks) __P((DB_ENV *, u_int32_t));
- int (*set_lk_max_lockers) __P((DB_ENV *, u_int32_t));
- int (*set_lk_max_objects) __P((DB_ENV *, u_int32_t));
-
- int (*set_mp_mmapsize) __P((DB_ENV *, size_t));
- int (*set_cachesize) __P((DB_ENV *, u_int32_t, u_int32_t, int));
-
- int (*set_tx_max) __P((DB_ENV *, u_int32_t));
- int (*set_tx_recover) __P((DB_ENV *,
- int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
- int (*set_tx_timestamp) __P((DB_ENV *, time_t *));
-
-#ifdef CONFIG_TEST
-#define DB_TEST_PREOPEN 1 /* before __os_open */
-#define DB_TEST_POSTOPEN 2 /* after __os_open */
-#define DB_TEST_POSTLOGMETA 3 /* after logging meta in btree */
-#define DB_TEST_POSTLOG 4 /* after logging all pages */
-#define DB_TEST_POSTSYNC 5 /* after syncing the log */
-#define DB_TEST_PRERENAME 6 /* before __os_rename */
-#define DB_TEST_POSTRENAME 7 /* after __os_rename */
- int test_abort; /* Abort value for testing. */
- int test_copy; /* Copy value for testing. */
-#endif
-
-#define DB_ENV_CDB 0x00001 /* DB_INIT_CDB. */
-#define DB_ENV_CDB_ALLDB 0x00002 /* CDB environment wide locking. */
-#define DB_ENV_CREATE 0x00004 /* DB_CREATE set. */
-#define DB_ENV_DBLOCAL 0x00008 /* DB_ENV allocated for private DB. */
-#define DB_ENV_LOCKDOWN 0x00010 /* DB_LOCKDOWN set. */
-#define DB_ENV_NOMMAP 0x00020 /* DB_NOMMAP set. */
-#define DB_ENV_OPEN_CALLED 0x00040 /* DBENV->open called (paths valid). */
-#define DB_ENV_PRIVATE 0x00080 /* DB_PRIVATE set. */
-#define DB_ENV_RPCCLIENT 0x00100 /* DB_CLIENT set. */
-#define DB_ENV_STANDALONE 0x00200 /* Test: freestanding environment. */
-#define DB_ENV_SYSTEM_MEM 0x00400 /* DB_SYSTEM_MEM set. */
-#define DB_ENV_THREAD 0x00800 /* DB_THREAD set. */
-#define DB_ENV_TXN_NOSYNC 0x01000 /* DB_TXN_NOSYNC set. */
-#define DB_ENV_USER_ALLOC 0x02000 /* User allocated the structure. */
- u_int32_t flags; /* Flags. */
-};
-
-/*******************************************************
- * Access methods.
- *******************************************************/
-/*
- * !!!
- * Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
- */
-typedef enum {
- DB_BTREE=1,
- DB_HASH,
- DB_RECNO,
- DB_QUEUE,
- DB_UNKNOWN /* Figure it out on open. */
-} DBTYPE;
-
-#define DB_BTREEVERSION 8 /* Current btree version. */
-#define DB_BTREEOLDVER 6 /* Oldest btree version supported. */
-#define DB_BTREEMAGIC 0x053162
-
-#define DB_HASHVERSION 7 /* Current hash version. */
-#define DB_HASHOLDVER 4 /* Oldest hash version supported. */
-#define DB_HASHMAGIC 0x061561
-
-#define DB_QAMVERSION 3 /* Current queue version. */
-#define DB_QAMOLDVER 1 /* Oldest queue version supported. */
-#define DB_QAMMAGIC 0x042253
-
-#define DB_LOGVERSION 3 /* Current log version. */
-#define DB_LOGOLDVER 3 /* Oldest log version supported. */
-#define DB_LOGMAGIC 0x040988
-
-/*
- * DB access method and cursor operation values. Each value is an operation
- * code to which additional bit flags are added.
- */
-#define DB_AFTER 1 /* c_put() */
-#define DB_APPEND 2 /* put() */
-#define DB_BEFORE 3 /* c_put() */
-#define DB_CACHED_COUNTS 4 /* stat() */
-#define DB_CHECKPOINT 5 /* log_put(), log_get() */
-#define DB_CONSUME 6 /* get() */
-#define DB_CONSUME_WAIT 7 /* get() */
-#define DB_CURLSN 8 /* log_put() */
-#define DB_CURRENT 9 /* c_get(), c_put(), log_get() */
-#define DB_FIRST 10 /* c_get(), log_get() */
-#define DB_FLUSH 11 /* log_put() */
-#define DB_GET_BOTH 12 /* get(), c_get() */
-#define DB_GET_BOTHC 13 /* c_get() (internal) */
-#define DB_GET_RECNO 14 /* c_get() */
-#define DB_JOIN_ITEM 15 /* c_get(); do not do primary lookup */
-#define DB_KEYFIRST 16 /* c_put() */
-#define DB_KEYLAST 17 /* c_put() */
-#define DB_LAST 18 /* c_get(), log_get() */
-#define DB_NEXT 19 /* c_get(), log_get() */
-#define DB_NEXT_DUP 20 /* c_get() */
-#define DB_NEXT_NODUP 21 /* c_get() */
-#define DB_NODUPDATA 22 /* put(), c_put() */
-#define DB_NOOVERWRITE 23 /* put() */
-#define DB_NOSYNC 24 /* close() */
-#define DB_POSITION 25 /* c_dup() */
-#define DB_POSITIONI 26 /* c_dup() (internal) */
-#define DB_PREV 27 /* c_get(), log_get() */
-#define DB_PREV_NODUP 28 /* c_get(), log_get() */
-#define DB_RECORDCOUNT 29 /* stat() */
-#define DB_SET 30 /* c_get(), log_get() */
-#define DB_SET_RANGE 31 /* c_get() */
-#define DB_SET_RECNO 32 /* get(), c_get() */
-#define DB_WRITECURSOR 33 /* cursor() */
-#define DB_WRITELOCK 34 /* cursor() (internal) */
-
-/* This has to change when the max opcode hits 255. */
-#define DB_OPFLAGS_MASK 0x000000ff /* Mask for operations flags. */
-#define DB_RMW 0x80000000 /* Acquire write flag immediately. */
-
-/*
- * DB (user visible) error return codes.
- *
- * !!!
- * Changes to any of the user visible error return codes must be reflected
- * in java/src/com/sleepycat/db/Db.java.
- *
- * !!!
- * For source compatibility with DB 2.X deadlock return (EAGAIN), use the
- * following:
- * #include <errno.h>
- * #define DB_LOCK_DEADLOCK EAGAIN
- *
- * !!!
- * We don't want our error returns to conflict with other packages where
- * possible, so pick a base error value that's hopefully not common. We
- * document that we own the error name space from -30,800 to -30,999.
- */
-/* Public error return codes. */
-#define DB_INCOMPLETE (-30999)/* Sync didn't finish. */
-#define DB_KEYEMPTY (-30998)/* Key/data deleted or never created. */
-#define DB_KEYEXIST (-30997)/* The key/data pair already exists. */
-#define DB_LOCK_DEADLOCK (-30996)/* Deadlock. */
-#define DB_LOCK_NOTGRANTED (-30995)/* Lock unavailable. */
-#define DB_NOSERVER (-30994)/* Server panic return. */
-#define DB_NOSERVER_HOME (-30993)/* Bad home sent to server. */
-#define DB_NOSERVER_ID (-30992)/* Bad ID sent to server. */
-#define DB_NOTFOUND (-30991)/* Key/data pair not found (EOF). */
-#define DB_OLD_VERSION (-30990)/* Out-of-date version. */
-#define DB_RUNRECOVERY (-30989)/* Panic return. */
-#define DB_VERIFY_BAD (-30988)/* Verify failed; bad format. */
-
-/* DB (private) error return codes. */
-#define DB_ALREADY_ABORTED (-30899)
-#define DB_DELETED (-30898)/* Recovery file marked deleted. */
-#define DB_JAVA_CALLBACK (-30897)/* Exception during a java callback. */
-#define DB_NEEDSPLIT (-30896)/* Page needs to be split. */
-#define DB_SWAPBYTES (-30895)/* Database needs byte swapping. */
-#define DB_TXN_CKP (-30894)/* Encountered ckp record in log. */
-#define DB_VERIFY_FATAL (-30893)/* Fatal: DB->verify cannot proceed. */
-
-#define DB_FILE_ID_LEN 20 /* DB file ID length. */
-
-/* DB access method description structure. */
-struct __db {
- /*******************************************************
- * Public: owned by the application.
- *******************************************************/
- u_int32_t pgsize; /* Database logical page size. */
-
- /* Callbacks. */
- int (*db_append_recno) __P((DB *, DBT *, db_recno_t));
- void (*db_feedback) __P((DB *, int, int));
- void *(*db_malloc) __P((size_t));
- void *(*db_realloc) __P((void *, size_t));
- int (*dup_compare) __P((DB *, const DBT *, const DBT *));
-
- void *app_private; /* Application-private handle. */
-
- /*******************************************************
- * Private: owned by DB.
- *******************************************************/
- DB_ENV *dbenv; /* Backing environment. */
-
- DBTYPE type; /* DB access method type. */
-
- DB_MPOOLFILE *mpf; /* Backing buffer pool. */
-
- void *mutexp; /* Synchronization for free threading */
-
- u_int8_t fileid[DB_FILE_ID_LEN];/* File's unique ID for locking. */
-
- u_int32_t adj_fileid; /* File's unique ID for curs. adj. */
-
-#define DB_LOGFILEID_INVALID -1
- int32_t log_fileid; /* File's unique ID for logging. */
- db_pgno_t meta_pgno; /* Meta page number */
- DB_TXN *open_txn; /* Transaction to protect creates. */
-
- long cl_id; /* RPC: remote client id. */
-
- /*
- * !!!
- * Some applications use DB but implement their own locking outside of
- * DB. If they're using fcntl(2) locking on the underlying database
- * file, and we open and close a file descriptor for that file, we will
- * discard their locks. The DB_FCNTL_LOCKING flag to DB->open is an
- * undocumented interface to support this usage which leaves any file
- * descriptors we open until DB->close. This will only work with the
- * DB->open interface and simple caches, e.g., creating a transaction
- * thread may open/close file descriptors this flag doesn't protect.
- * Locking with fcntl(2) on a file that you don't own is a very, very
- * unsafe thing to do. 'Nuff said.
- */
- DB_FH *saved_open_fhp; /* Saved file handle. */
-
- /*
- * Linked list of DBP's, used in the log's dbentry table
- * to keep track of all open db handles for a given log id.
- * !!!
- * Explicit representations of structures in queue.h.
- *
- * TAILQ_ENTRY(__db) links;
- */
- struct {
- struct __db *tqe_next;
- struct __db **tqe_prev;
- } links;
-
- /*
- * Linked list of DBP's, linked from the DB_ENV, used to
- * keep track of all open db handles for cursor adjustment.
- *
- * XXX
- * Eventually, this should be merged with "links" above.
- *
- * !!!
- * Explicit representations of structures in queue.h.
- *
- * LIST_ENTRY(__db) dblistlinks;
- */
- struct {
- struct __db *le_next;
- struct __db **le_prev;
- } dblistlinks;
-
- /*
- * Cursor queues.
- *
- * !!!
- * Explicit representations of structures in queue.h.
- *
- * TAILQ_HEAD(free_queue, __dbc);
- * TAILQ_HEAD(active_queue, __dbc);
- * TAILQ_HEAD(join_queue, __dbc);
- */
- struct {
- struct __dbc *tqh_first;
- struct __dbc **tqh_last;
- } free_queue;
- struct {
- struct __dbc *tqh_first;
- struct __dbc **tqh_last;
- } active_queue;
- struct {
- struct __dbc *tqh_first;
- struct __dbc **tqh_last;
- } join_queue;
-
- void *bt_internal; /* Btree/Recno access method private. */
- void *cj_internal; /* C++/Java private. */
- void *h_internal; /* Hash access method private. */
- void *q_internal; /* Queue access method private. */
- void *xa_internal; /* XA private. */
-
- /* Methods. */
- int (*close) __P((DB *, u_int32_t));
- int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t));
- int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
- void (*err) __P((DB *, int, const char *, ...));
- void (*errx) __P((DB *, const char *, ...));
- int (*fd) __P((DB *, int *));
- int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
- int (*get_byteswapped) __P((DB *));
- DBTYPE
- (*get_type) __P((DB *));
- int (*join) __P((DB *, DBC **, DBC **, u_int32_t));
- int (*key_range) __P((DB *,
- DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
- int (*open) __P((DB *,
- const char *, const char *, DBTYPE, u_int32_t, int));
- int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
- int (*remove) __P((DB *, const char *, const char *, u_int32_t));
- int (*rename) __P((DB *,
- const char *, const char *, const char *, u_int32_t));
- int (*set_append_recno) __P((DB *, int (*)(DB *, DBT *, db_recno_t)));
- int (*set_cachesize) __P((DB *, u_int32_t, u_int32_t, int));
- int (*set_dup_compare) __P((DB *,
- int (*)(DB *, const DBT *, const DBT *)));
- void (*set_errcall) __P((DB *, void (*)(const char *, char *)));
- void (*set_errfile) __P((DB *, FILE *));
- void (*set_errpfx) __P((DB *, const char *));
- int (*set_feedback) __P((DB *, void (*)(DB *, int, int)));
- int (*set_flags) __P((DB *, u_int32_t));
- int (*set_lorder) __P((DB *, int));
- int (*set_malloc) __P((DB *, void *(*)(size_t)));
- int (*set_pagesize) __P((DB *, u_int32_t));
- int (*set_paniccall) __P((DB *, void (*)(DB_ENV *, int)));
- int (*set_realloc) __P((DB *, void *(*)(void *, size_t)));
- int (*stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
- int (*sync) __P((DB *, u_int32_t));
- int (*upgrade) __P((DB *, const char *, u_int32_t));
- int (*verify) __P((DB *,
- const char *, const char *, FILE *, u_int32_t));
-
- int (*set_bt_compare) __P((DB *,
- int (*)(DB *, const DBT *, const DBT *)));
- int (*set_bt_maxkey) __P((DB *, u_int32_t));
- int (*set_bt_minkey) __P((DB *, u_int32_t));
- int (*set_bt_prefix) __P((DB *,
- size_t (*)(DB *, const DBT *, const DBT *)));
-
- int (*set_h_ffactor) __P((DB *, u_int32_t));
- int (*set_h_hash) __P((DB *,
- u_int32_t (*)(DB *, const void *, u_int32_t)));
- int (*set_h_nelem) __P((DB *, u_int32_t));
-
- int (*set_re_delim) __P((DB *, int));
- int (*set_re_len) __P((DB *, u_int32_t));
- int (*set_re_pad) __P((DB *, int));
- int (*set_re_source) __P((DB *, const char *));
- int (*set_q_extentsize) __P((DB *, u_int32_t));
-
- int (*db_am_remove) __P((DB *, const char *,
- const char *, DB_LSN *, int (**)(DB *, void*), void **));
- int (*db_am_rename) __P((DB *,
- const char *, const char *, const char *));
-
-#define DB_OK_BTREE 0x01
-#define DB_OK_HASH 0x02
-#define DB_OK_QUEUE 0x04
-#define DB_OK_RECNO 0x08
- u_int32_t am_ok; /* Legal AM choices. */
-
-#define DB_AM_DISCARD 0x00001 /* Discard any cached pages. */
-#define DB_AM_DUP 0x00002 /* DB_DUP. */
-#define DB_AM_DUPSORT 0x00004 /* DB_DUPSORT. */
-#define DB_AM_INMEM 0x00008 /* In-memory; no sync on close. */
-#define DB_AM_PGDEF 0x00010 /* Page size was defaulted. */
-#define DB_AM_RDONLY 0x00020 /* Database is readonly. */
-#define DB_AM_RECOVER 0x00040 /* DBP opened by recovery routine. */
-#define DB_AM_SUBDB 0x00080 /* Subdatabases supported. */
-#define DB_AM_SWAP 0x00100 /* Pages need to be byte-swapped. */
-#define DB_AM_TXN 0x00200 /* DBP was in a transaction. */
-#define DB_AM_VERIFYING 0x00400 /* DB handle is in the verifier. */
-#define DB_BT_RECNUM 0x00800 /* DB_RECNUM. */
-#define DB_BT_REVSPLIT 0x01000 /* DB_REVSPLITOFF. */
-#define DB_DBM_ERROR 0x02000 /* Error in DBM/NDBM database. */
-#define DB_OPEN_CALLED 0x04000 /* DB->open called. */
-#define DB_RE_DELIMITER 0x08000 /* Variablen length delimiter set. */
-#define DB_RE_FIXEDLEN 0x10000 /* Fixed-length records. */
-#define DB_RE_PAD 0x20000 /* Fixed-length record pad. */
-#define DB_RE_RENUMBER 0x40000 /* DB_RENUMBER. */
-#define DB_RE_SNAPSHOT 0x80000 /* DB_SNAPSHOT. */
- u_int32_t flags;
-};
-
-/*
- * DB_LOCK_ILOCK --
- * Internal DB access method lock.
- */
-struct __db_ilock {
- db_pgno_t pgno; /* Page being locked. */
- u_int8_t fileid[DB_FILE_ID_LEN];/* File id. */
-#define DB_RECORD_LOCK 1
-#define DB_PAGE_LOCK 2
- u_int8_t type; /* Record or Page lock */
-};
-
-/*
- * DB_LOCK --
- * The structure is allocated by the caller and filled in during a
- * lock_get request (or a lock_vec/DB_LOCK_GET).
- */
-struct __db_lock_u {
- size_t off; /* Offset of the lock in the region */
- u_int32_t ndx; /* Index of the object referenced by
- * this lock; used for locking. */
- u_int32_t gen; /* Generation number of this lock. */
-};
-
-/* Cursor description structure. */
-struct __dbc {
- DB *dbp; /* Related DB access method. */
- DB_TXN *txn; /* Associated transaction. */
-
- /*
- * !!!
- * Explicit representations of structures in queue.h.
- *
- * TAILQ_ENTRY(__dbc) links; Active/free cursor queues.
- */
- struct {
- DBC *tqe_next;
- DBC **tqe_prev;
- } links;
-
- DBT rkey; /* Returned key. */
- DBT rdata; /* Returned data. */
-
- u_int32_t lid; /* Default process' locker id. */
- u_int32_t locker; /* Locker for this operation. */
- DBT lock_dbt; /* DBT referencing lock. */
- DB_LOCK_ILOCK lock; /* Object to be locked. */
- DB_LOCK mylock; /* Lock held on this cursor. */
-
- long cl_id; /* Remote client id. */
-
- DBTYPE dbtype; /* Cursor type. */
-
- DBC_INTERNAL *internal; /* Access method private. */
-
- int (*c_close) __P((DBC *)); /* Methods: public. */
- int (*c_count) __P((DBC *, db_recno_t *, u_int32_t));
- int (*c_del) __P((DBC *, u_int32_t));
- int (*c_dup) __P((DBC *, DBC **, u_int32_t));
- int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
- int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
-
- /* Methods: private. */
- int (*c_am_close) __P((DBC *, db_pgno_t, int *));
- int (*c_am_del) __P((DBC *));
- int (*c_am_destroy) __P((DBC *));
- int (*c_am_get) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
- int (*c_am_put) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
- int (*c_am_writelock) __P((DBC *));
-
-#define DBC_ACTIVE 0x001 /* Cursor is being used. */
-#define DBC_OPD 0x002 /* Cursor references off-page dups. */
-#define DBC_RECOVER 0x004 /* Cursor created by recovery routine
- * (do not log or lock).
- */
-#define DBC_RMW 0x008 /* Acquire write flag in read op. */
-#define DBC_WRITECURSOR 0x010 /* Cursor may be used to write (CDB). */
-#define DBC_WRITEDUP 0x020 /* idup'ed DBC_WRITECURSOR (CDB). */
-#define DBC_WRITER 0x040 /* Cursor immediately writing (CDB). */
-#define DBC_TRANSIENT 0x080 /* Cursor is transient. */
-#define DBC_COMPENSATE 0x100 /* Cursor is doing compensation
- * do not lock.
- */
- u_int32_t flags;
-};
-
-/* Key range statistics structure */
-struct __key_range {
- double less;
- double equal;
- double greater;
-};
-
-/* Btree/Recno statistics structure. */
-struct __db_bt_stat {
- u_int32_t bt_magic; /* Magic number. */
- u_int32_t bt_version; /* Version number. */
- u_int32_t bt_metaflags; /* Metadata flags. */
- u_int32_t bt_nkeys; /* Number of unique keys. */
- u_int32_t bt_ndata; /* Number of data items. */
- u_int32_t bt_pagesize; /* Page size. */
- u_int32_t bt_maxkey; /* Maxkey value. */
- u_int32_t bt_minkey; /* Minkey value. */
- u_int32_t bt_re_len; /* Fixed-length record length. */
- u_int32_t bt_re_pad; /* Fixed-length record pad. */
- u_int32_t bt_levels; /* Tree levels. */
- u_int32_t bt_int_pg; /* Internal pages. */
- u_int32_t bt_leaf_pg; /* Leaf pages. */
- u_int32_t bt_dup_pg; /* Duplicate pages. */
- u_int32_t bt_over_pg; /* Overflow pages. */
- u_int32_t bt_free; /* Pages on the free list. */
- u_int32_t bt_int_pgfree; /* Bytes free in internal pages. */
- u_int32_t bt_leaf_pgfree; /* Bytes free in leaf pages. */
- u_int32_t bt_dup_pgfree; /* Bytes free in duplicate pages. */
- u_int32_t bt_over_pgfree; /* Bytes free in overflow pages. */
-};
-
-/* Queue statistics structure. */
-struct __db_qam_stat {
- u_int32_t qs_magic; /* Magic number. */
- u_int32_t qs_version; /* Version number. */
- u_int32_t qs_metaflags; /* Metadata flags. */
- u_int32_t qs_nkeys; /* Number of unique keys. */
- u_int32_t qs_ndata; /* Number of data items. */
- u_int32_t qs_pagesize; /* Page size. */
- u_int32_t qs_pages; /* Data pages. */
- u_int32_t qs_re_len; /* Fixed-length record length. */
- u_int32_t qs_re_pad; /* Fixed-length record pad. */
- u_int32_t qs_pgfree; /* Bytes free in data pages. */
- u_int32_t qs_first_recno; /* First not deleted record. */
- u_int32_t qs_cur_recno; /* Last allocated record number. */
-};
-
-/* Hash statistics structure. */
-struct __db_h_stat {
- u_int32_t hash_magic; /* Magic number. */
- u_int32_t hash_version; /* Version number. */
- u_int32_t hash_metaflags; /* Metadata flags. */
- u_int32_t hash_nkeys; /* Number of unique keys. */
- u_int32_t hash_ndata; /* Number of data items. */
- u_int32_t hash_pagesize; /* Page size. */
- u_int32_t hash_nelem; /* Original nelem specified. */
- u_int32_t hash_ffactor; /* Fill factor specified at create. */
- u_int32_t hash_buckets; /* Number of hash buckets. */
- u_int32_t hash_free; /* Pages on the free list. */
- u_int32_t hash_bfree; /* Bytes free on bucket pages. */
- u_int32_t hash_bigpages; /* Number of big key/data pages. */
- u_int32_t hash_big_bfree; /* Bytes free on big item pages. */
- u_int32_t hash_overflows; /* Number of overflow pages. */
- u_int32_t hash_ovfl_free; /* Bytes free on ovfl pages. */
- u_int32_t hash_dup; /* Number of dup pages. */
- u_int32_t hash_dup_free; /* Bytes free on duplicate pages. */
-};
-
-int db_create __P((DB **, DB_ENV *, u_int32_t));
-int db_env_create __P((DB_ENV **, u_int32_t));
-int db_env_set_func_close __P((int (*)(int)));
-int db_env_set_func_dirfree __P((void (*)(char **, int)));
-int db_env_set_func_dirlist __P((int (*)(const char *, char ***, int *)));
-int db_env_set_func_exists __P((int (*)(const char *, int *)));
-int db_env_set_func_free __P((void (*)(void *)));
-int db_env_set_func_fsync __P((int (*)(int)));
-int db_env_set_func_ioinfo __P((int (*)(const char *,
- int, u_int32_t *, u_int32_t *, u_int32_t *)));
-int db_env_set_func_malloc __P((void *(*)(size_t)));
-int db_env_set_func_map __P((int (*)(char *, size_t, int, int, void **)));
-int db_env_set_func_open __P((int (*)(const char *, int, ...)));
-int db_env_set_func_read __P((ssize_t (*)(int, void *, size_t)));
-int db_env_set_func_realloc __P((void *(*)(void *, size_t)));
-int db_env_set_func_rename __P((int (*)(const char *, const char *)));
-int db_env_set_func_seek
- __P((int (*)(int, size_t, db_pgno_t, u_int32_t, int, int)));
-int db_env_set_func_sleep __P((int (*)(u_long, u_long)));
-int db_env_set_func_unlink __P((int (*)(const char *)));
-int db_env_set_func_unmap __P((int (*)(void *, size_t)));
-int db_env_set_func_write __P((ssize_t (*)(int, const void *, size_t)));
-int db_env_set_func_yield __P((int (*)(void)));
-int db_env_set_pageyield __P((int));
-int db_env_set_panicstate __P((int));
-int db_env_set_region_init __P((int));
-int db_env_set_tas_spins __P((u_int32_t));
-char *db_strerror __P((int));
-char *db_version __P((int *, int *, int *));
-
-/*******************************************************
- * Locking
- *******************************************************/
-#define DB_LOCKVERSION 1
-
-/* Flag values for lock_vec(), lock_get(). */
-#define DB_LOCK_NOWAIT 0x01 /* Don't wait on unavailable lock. */
-#define DB_LOCK_RECORD 0x02 /* Internal: record lock. */
-#define DB_LOCK_UPGRADE 0x04 /* Internal: upgrade existing lock. */
-#define DB_LOCK_SWITCH 0x08 /* Internal: switch existing lock. */
-
-/* Flag values for lock_detect(). */
-#define DB_LOCK_CONFLICT 0x01 /* Run on any conflict. */
-
-/*
- * Request types.
- *
- * !!!
- * Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
- */
-typedef enum {
- DB_LOCK_DUMP=0, /* Display held locks. */
- DB_LOCK_GET, /* Get the lock. */
- DB_LOCK_INHERIT, /* Pass locks to parent. */
- DB_LOCK_PUT, /* Release the lock. */
- DB_LOCK_PUT_ALL, /* Release locker's locks. */
- DB_LOCK_PUT_OBJ /* Release locker's locks on obj. */
-} db_lockop_t;
-
-/*
- * Simple R/W lock modes and for multi-granularity intention locking.
- *
- * !!!
- * These values are NOT random, as they are used as an index into the lock
- * conflicts arrays, i.e., DB_LOCK_IWRITE must be == 3, and DB_LOCK_IREAD
- * must be == 4.
- *
- * !!!
- * Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
- */
-typedef enum {
- DB_LOCK_NG=0, /* Not granted. */
- DB_LOCK_READ, /* Shared/read. */
- DB_LOCK_WRITE, /* Exclusive/write. */
- DB_LOCK_WAIT, /* Wait for event */
- DB_LOCK_IWRITE, /* Intent exclusive/write. */
- DB_LOCK_IREAD, /* Intent to share/read. */
- DB_LOCK_IWR /* Intent to read and write. */
-} db_lockmode_t;
-
-/*
- * Status of a lock.
- */
-typedef enum {
- DB_LSTAT_ABORTED, /* Lock belongs to an aborted txn. */
- DB_LSTAT_ERR, /* Lock is bad. */
- DB_LSTAT_FREE, /* Lock is unallocated. */
- DB_LSTAT_HELD, /* Lock is currently held. */
- DB_LSTAT_NOGRANT, /* Lock was not granted. */
- DB_LSTAT_PENDING, /* Lock was waiting and has been
- * promoted; waiting for the owner
- * to run and upgrade it to held. */
- DB_LSTAT_WAITING /* Lock is on the wait queue. */
-} db_status_t;
-
-/* Lock request structure. */
-struct __db_lockreq {
- db_lockop_t op; /* Operation. */
- db_lockmode_t mode; /* Requested mode. */
- u_int32_t locker; /* Locker identity. */
- DBT *obj; /* Object being locked. */
- DB_LOCK lock; /* Lock returned. */
-};
-
-/*
- * Commonly used conflict matrices.
- *
- */
-
-/* Multi-granularity locking. */
-#define DB_LOCK_RIW_N 7
-extern const u_int8_t db_riw_conflicts[];
-
-struct __db_lock_stat {
- u_int32_t st_lastid; /* Last allocated locker ID. */
- u_int32_t st_maxlocks; /* Maximum number of locks in table. */
- u_int32_t st_maxlockers; /* Maximum number of lockers in table. */
- u_int32_t st_maxobjects; /* Maximum number of objects in table. */
- u_int32_t st_nmodes; /* Number of lock modes. */
- u_int32_t st_nlocks; /* Current number of locks. */
- u_int32_t st_maxnlocks; /* Maximum number of locks so far. */
- u_int32_t st_nlockers; /* Current number of lockers. */
- u_int32_t st_maxnlockers; /* Maximum number of lockers so far. */
- u_int32_t st_nobjects; /* Current number of objects. */
- u_int32_t st_maxnobjects; /* Maximum number of objects so far. */
- u_int32_t st_nconflicts; /* Number of lock conflicts. */
- u_int32_t st_nrequests; /* Number of lock gets. */
- u_int32_t st_nreleases; /* Number of lock puts. */
- u_int32_t st_nnowaits; /* Number of requests that would have
- waited, but NOWAIT was set. */
- u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */
- u_int32_t st_region_wait; /* Region lock granted after wait. */
- u_int32_t st_region_nowait; /* Region lock granted without wait. */
- u_int32_t st_regsize; /* Region size. */
-};
-
-int lock_detect __P((DB_ENV *, u_int32_t, u_int32_t, int *));
-int lock_get __P((DB_ENV *,
- u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
-int lock_id __P((DB_ENV *, u_int32_t *));
-int lock_put __P((DB_ENV *, DB_LOCK *));
-int lock_stat __P((DB_ENV *, DB_LOCK_STAT **, void *(*)(size_t)));
-int lock_vec __P((DB_ENV *,
- u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
-
-/*******************************************************
- * Logging.
- *******************************************************/
-/* Flag values for log_archive(). */
-#define DB_ARCH_ABS 0x001 /* Absolute pathnames. */
-#define DB_ARCH_DATA 0x002 /* Data files. */
-#define DB_ARCH_LOG 0x004 /* Log files. */
-
-/*
- * A DB_LSN has two parts, a fileid which identifies a specific file, and an
- * offset within that file. The fileid is an unsigned 4-byte quantity that
- * uniquely identifies a file within the log directory -- currently a simple
- * counter inside the log. The offset is also an unsigned 4-byte value. The
- * log manager guarantees the offset is never more than 4 bytes by switching
- * to a new log file before the maximum length imposed by an unsigned 4-byte
- * offset is reached.
- */
-struct __db_lsn {
- u_int32_t file; /* File ID. */
- u_int32_t offset; /* File offset. */
-};
-
-/* Log statistics structure. */
-struct __db_log_stat {
- u_int32_t st_magic; /* Log file magic number. */
- u_int32_t st_version; /* Log file version number. */
- int st_mode; /* Log file mode. */
- u_int32_t st_lg_bsize; /* Log buffer size. */
- u_int32_t st_lg_max; /* Maximum log file size. */
- u_int32_t st_w_bytes; /* Bytes to log. */
- u_int32_t st_w_mbytes; /* Megabytes to log. */
- u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */
- u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */
- u_int32_t st_wcount; /* Total writes to the log. */
- u_int32_t st_wcount_fill; /* Overflow writes to the log. */
- u_int32_t st_scount; /* Total syncs to the log. */
- u_int32_t st_region_wait; /* Region lock granted after wait. */
- u_int32_t st_region_nowait; /* Region lock granted without wait. */
- u_int32_t st_cur_file; /* Current log file number. */
- u_int32_t st_cur_offset; /* Current log file offset. */
- u_int32_t st_regsize; /* Region size. */
-};
-
-int log_archive __P((DB_ENV *, char **[], u_int32_t, void *(*)(size_t)));
-int log_compare __P((const DB_LSN *, const DB_LSN *));
-int log_file __P((DB_ENV *, const DB_LSN *, char *, size_t));
-int log_flush __P((DB_ENV *, const DB_LSN *));
-int log_get __P((DB_ENV *, DB_LSN *, DBT *, u_int32_t));
-int log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
-int log_register __P((DB_ENV *, DB *, const char *));
-int log_stat __P((DB_ENV *, DB_LOG_STAT **, void *(*)(size_t)));
-int log_unregister __P((DB_ENV *, DB *));
-
-/*******************************************************
- * Mpool
- *******************************************************/
-/* Flag values for memp_fget(). */
-#define DB_MPOOL_CREATE 0x001 /* Create a page. */
-#define DB_MPOOL_LAST 0x002 /* Return the last page. */
-#define DB_MPOOL_NEW 0x004 /* Create a new page. */
-#define DB_MPOOL_NEW_GROUP 0x008 /* Create a group of pages. */
-#define DB_MPOOL_EXTENT 0x010 /* Get for an extent. */
-
-/* Flag values for memp_fput(), memp_fset(). */
-#define DB_MPOOL_CLEAN 0x001 /* Page is not modified. */
-#define DB_MPOOL_DIRTY 0x002 /* Page is modified. */
-#define DB_MPOOL_DISCARD 0x004 /* Don't cache the page. */
-
-/* Mpool statistics structure. */
-struct __db_mpool_stat {
- u_int32_t st_cache_hit; /* Pages found in the cache. */
- u_int32_t st_cache_miss; /* Pages not found in the cache. */
- u_int32_t st_map; /* Pages from mapped files. */
- u_int32_t st_page_create; /* Pages created in the cache. */
- u_int32_t st_page_in; /* Pages read in. */
- u_int32_t st_page_out; /* Pages written out. */
- u_int32_t st_ro_evict; /* Clean pages forced from the cache. */
- u_int32_t st_rw_evict; /* Dirty pages forced from the cache. */
- u_int32_t st_hash_buckets; /* Number of hash buckets. */
- u_int32_t st_hash_searches; /* Total hash chain searches. */
- u_int32_t st_hash_longest; /* Longest hash chain searched. */
- u_int32_t st_hash_examined; /* Total hash entries searched. */
- u_int32_t st_page_clean; /* Clean pages. */
- u_int32_t st_page_dirty; /* Dirty pages. */
- u_int32_t st_page_trickle; /* Pages written by memp_trickle. */
- u_int32_t st_region_wait; /* Region lock granted after wait. */
- u_int32_t st_region_nowait; /* Region lock granted without wait. */
- u_int32_t st_gbytes; /* Total cache size: GB. */
- u_int32_t st_bytes; /* Total cache size: B. */
- u_int32_t st_ncache; /* Number of caches. */
- u_int32_t st_regsize; /* Cache size. */
-};
-
-/* Mpool file open information structure. */
-struct __db_mpool_finfo {
- int ftype; /* File type. */
- DBT *pgcookie; /* Byte-string passed to pgin/pgout. */
- u_int8_t *fileid; /* Unique file ID. */
- int32_t lsn_offset; /* LSN offset in page. */
- u_int32_t clear_len; /* Cleared length on created pages. */
-};
-
-/* Mpool file statistics structure. */
-struct __db_mpool_fstat {
- char *file_name; /* File name. */
- size_t st_pagesize; /* Page size. */
- u_int32_t st_cache_hit; /* Pages found in the cache. */
- u_int32_t st_cache_miss; /* Pages not found in the cache. */
- u_int32_t st_map; /* Pages from mapped files. */
- u_int32_t st_page_create; /* Pages created in the cache. */
- u_int32_t st_page_in; /* Pages read in. */
- u_int32_t st_page_out; /* Pages written out. */
-};
-
-int memp_fclose __P((DB_MPOOLFILE *));
-int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
-int memp_fopen __P((DB_ENV *, const char *,
- u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
-int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
-int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
-int memp_fsync __P((DB_MPOOLFILE *));
-int memp_register __P((DB_ENV *, int,
- int (*)(DB_ENV *, db_pgno_t, void *, DBT *),
- int (*)(DB_ENV *, db_pgno_t, void *, DBT *)));
-int memp_stat __P((DB_ENV *,
- DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
-int memp_sync __P((DB_ENV *, DB_LSN *));
-int memp_trickle __P((DB_ENV *, int, int *));
-
-/*******************************************************
- * Transactions.
- *******************************************************/
-#define DB_TXNVERSION 1
-
-/* Operations values to the tx_recover() function. */
-#define DB_TXN_BACKWARD_ROLL 1 /* Read the log backwards. */
-#define DB_TXN_FORWARD_ROLL 2 /* Read the log forwards. */
-#define DB_TXN_OPENFILES 3 /* Read for open files. */
-#define DB_TXN_REDO 4 /* Redo the operation. */
-#define DB_TXN_UNDO 5 /* Undo the operation. */
-
-/* Internal transaction status values. */
-
-/* Transaction statistics structure. */
-struct __db_txn_active {
- u_int32_t txnid; /* Transaction ID */
- u_int32_t parentid; /* Transaction ID of parent */
- DB_LSN lsn; /* Lsn of the begin record */
-};
-
-struct __db_txn_stat {
- DB_LSN st_last_ckp; /* lsn of the last checkpoint */
- DB_LSN st_pending_ckp; /* last checkpoint did not finish */
- time_t st_time_ckp; /* time of last checkpoint */
- u_int32_t st_last_txnid; /* last transaction id given out */
- u_int32_t st_maxtxns; /* maximum txns possible */
- u_int32_t st_naborts; /* number of aborted transactions */
- u_int32_t st_nbegins; /* number of begun transactions */
- u_int32_t st_ncommits; /* number of committed transactions */
- u_int32_t st_nactive; /* number of active transactions */
- u_int32_t st_maxnactive; /* maximum active transactions */
- DB_TXN_ACTIVE
- *st_txnarray; /* array of active transactions */
- u_int32_t st_region_wait; /* Region lock granted after wait. */
- u_int32_t st_region_nowait; /* Region lock granted without wait. */
- u_int32_t st_regsize; /* Region size. */
-};
-
-int txn_abort __P((DB_TXN *));
-int txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
-int txn_checkpoint __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t));
-int txn_commit __P((DB_TXN *, u_int32_t));
-u_int32_t txn_id __P((DB_TXN *));
-int txn_prepare __P((DB_TXN *));
-int txn_stat __P((DB_ENV *, DB_TXN_STAT **, void *(*)(size_t)));
-
-#ifndef DB_DBM_HSEARCH
-#define DB_DBM_HSEARCH 0 /* No historic interfaces by default. */
-#endif
-#if DB_DBM_HSEARCH != 0
-/*******************************************************
- * Dbm/Ndbm historic interfaces.
- *******************************************************/
-#define DBM_INSERT 0 /* Flags to dbm_store(). */
-#define DBM_REPLACE 1
-
-/*
- * The DB support for ndbm(3) always appends this suffix to the
- * file name to avoid overwriting the user's original database.
- */
-#define DBM_SUFFIX ".db"
-
-#if defined(_XPG4_2)
-typedef struct {
- char *dptr;
- size_t dsize;
-} datum;
-#else
-typedef struct {
- char *dptr;
- int dsize;
-} datum;
-#endif
-
-/*
- * Translate DBM calls into DB calls so that DB doesn't step on the
- * application's name space.
- *
- * The global variables dbrdonly, dirf and pagf were not retained when 4BSD
- * replaced the dbm interface with ndbm, and are not supported here.
- */
-#define dbminit(a) __db_dbm_init(a)
-#define dbmclose __db_dbm_close
-#if !defined(__cplusplus)
-#define delete(a) __db_dbm_delete(a)
-#endif
-#define fetch(a) __db_dbm_fetch(a)
-#define firstkey __db_dbm_firstkey
-#define nextkey(a) __db_dbm_nextkey(a)
-#define store(a, b) __db_dbm_store(a, b)
-
-/* Prototype the DB calls. */
-int __db_dbm_close __P((void));
-int __db_dbm_dbrdonly __P((void));
-int __db_dbm_delete __P((datum));
-int __db_dbm_dirf __P((void));
-datum __db_dbm_fetch __P((datum));
-datum __db_dbm_firstkey __P((void));
-int __db_dbm_init __P((char *));
-datum __db_dbm_nextkey __P((datum));
-int __db_dbm_pagf __P((void));
-int __db_dbm_store __P((datum, datum));
-
-/*
- * Translate NDBM calls into DB calls so that DB doesn't step on the
- * application's name space.
- */
-#define dbm_clearerr(a) __db_ndbm_clearerr(a)
-#define dbm_close(a) __db_ndbm_close(a)
-#define dbm_delete(a, b) __db_ndbm_delete(a, b)
-#define dbm_dirfno(a) __db_ndbm_dirfno(a)
-#define dbm_error(a) __db_ndbm_error(a)
-#define dbm_fetch(a, b) __db_ndbm_fetch(a, b)
-#define dbm_firstkey(a) __db_ndbm_firstkey(a)
-#define dbm_nextkey(a) __db_ndbm_nextkey(a)
-#define dbm_open(a, b, c) __db_ndbm_open(a, b, c)
-#define dbm_pagfno(a) __db_ndbm_pagfno(a)
-#define dbm_rdonly(a) __db_ndbm_rdonly(a)
-#define dbm_store(a, b, c, d) __db_ndbm_store(a, b, c, d)
-
-/* Prototype the DB calls. */
-int __db_ndbm_clearerr __P((DBM *));
-void __db_ndbm_close __P((DBM *));
-int __db_ndbm_delete __P((DBM *, datum));
-int __db_ndbm_dirfno __P((DBM *));
-int __db_ndbm_error __P((DBM *));
-datum __db_ndbm_fetch __P((DBM *, datum));
-datum __db_ndbm_firstkey __P((DBM *));
-datum __db_ndbm_nextkey __P((DBM *));
-DBM *__db_ndbm_open __P((const char *, int, int));
-int __db_ndbm_pagfno __P((DBM *));
-int __db_ndbm_rdonly __P((DBM *));
-int __db_ndbm_store __P((DBM *, datum, datum, int));
-
-/*******************************************************
- * Hsearch historic interface.
- *******************************************************/
-typedef enum {
- FIND, ENTER
-} ACTION;
-
-typedef struct entry {
- char *key;
- char *data;
-} ENTRY;
-
-/*
- * Translate HSEARCH calls into DB calls so that DB doesn't step on the
- * application's name space.
- */
-#define hcreate(a) __db_hcreate(a)
-#define hdestroy __db_hdestroy
-#define hsearch(a, b) __db_hsearch(a, b)
-
-/* Prototype the DB calls. */
-int __db_hcreate __P((size_t));
-void __db_hdestroy __P((void));
-ENTRY *__db_hsearch __P((ENTRY, ACTION));
-#endif /* DB_DBM_HSEARCH */
-
-/*
- * XXX
- * MacOS: Reset Metrowerks C enum sizes.
- */
-#ifdef __MWERKS__
-#pragma enumsalwaysint reset
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* !_DB_H_ */
diff --git a/bdb/include/db_185.h b/bdb/include/db_185.h
deleted file mode 100644
index e50ebb0adb8..00000000000
--- a/bdb/include/db_185.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: db_185.h,v 11.4 2000/02/14 02:59:54 bostic Exp $
- */
-
-#ifndef _DB_185_H_
-#define _DB_185_H_
-
-#include <sys/types.h>
-
-#include <limits.h>
-
-/*
- * XXX
- * Handle function prototypes and the keyword "const". This steps on name
- * space that DB doesn't control, but all of the other solutions are worse.
- */
-#undef __P
-#if defined(__STDC__) || defined(__cplusplus)
-#define __P(protos) protos /* ANSI C prototypes */
-#else
-#define const
-#define __P(protos) () /* K&R C preprocessor */
-#endif
-
-#define RET_ERROR -1 /* Return values. */
-#define RET_SUCCESS 0
-#define RET_SPECIAL 1
-
-#ifndef __BIT_TYPES_DEFINED__
-#define __BIT_TYPES_DEFINED__
-@u_int8_decl@
-@int16_decl@
-@u_int16_decl@
-@int32_decl@
-@u_int32_decl@
-#endif
-
-/*
- * XXX
- * SGI/IRIX already has a pgno_t.
- */
-#ifdef sgi
-#define pgno_t db_pgno_t
-#endif
-
-#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
-typedef u_int32_t pgno_t;
-#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
-typedef u_int16_t indx_t;
-#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
-typedef u_int32_t recno_t;
-
-/* Key/data structure -- a Data-Base Thang. */
-typedef struct {
- void *data; /* data */
- size_t size; /* data length */
-} DBT;
-
-/* Routine flags. */
-#define R_CURSOR 1 /* del, put, seq */
-#define __R_UNUSED 2 /* UNUSED */
-#define R_FIRST 3 /* seq */
-#define R_IAFTER 4 /* put (RECNO) */
-#define R_IBEFORE 5 /* put (RECNO) */
-#define R_LAST 6 /* seq (BTREE, RECNO) */
-#define R_NEXT 7 /* seq */
-#define R_NOOVERWRITE 8 /* put */
-#define R_PREV 9 /* seq (BTREE, RECNO) */
-#define R_SETCURSOR 10 /* put (RECNO) */
-#define R_RECNOSYNC 11 /* sync (RECNO) */
-
-typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
-
-/* Access method description structure. */
-typedef struct __db {
- DBTYPE type; /* Underlying db type. */
- int (*close) __P((struct __db *));
- int (*del) __P((const struct __db *, const DBT *, u_int));
- int (*get) __P((const struct __db *, const DBT *, DBT *, u_int));
- int (*put) __P((const struct __db *, DBT *, const DBT *, u_int));
- int (*seq) __P((const struct __db *, DBT *, DBT *, u_int));
- int (*sync) __P((const struct __db *, u_int));
- void *internal; /* Access method private. */
- int (*fd) __P((const struct __db *));
-} DB;
-
-#define BTREEMAGIC 0x053162
-#define BTREEVERSION 3
-
-/* Structure used to pass parameters to the btree routines. */
-typedef struct {
-#define R_DUP 0x01 /* duplicate keys */
- u_int32_t flags;
- u_int32_t cachesize; /* bytes to cache */
- u_int32_t maxkeypage; /* maximum keys per page */
- u_int32_t minkeypage; /* minimum keys per page */
- u_int32_t psize; /* page size */
- int (*compare) /* comparison function */
- __P((const DBT *, const DBT *));
- size_t (*prefix) /* prefix function */
- __P((const DBT *, const DBT *));
- int lorder; /* byte order */
-} BTREEINFO;
-
-#define HASHMAGIC 0x061561
-#define HASHVERSION 2
-
-/* Structure used to pass parameters to the hashing routines. */
-typedef struct {
- u_int32_t bsize; /* bucket size */
- u_int32_t ffactor; /* fill factor */
- u_int32_t nelem; /* number of elements */
- u_int32_t cachesize; /* bytes to cache */
- u_int32_t /* hash function */
- (*hash) __P((const void *, size_t));
- int lorder; /* byte order */
-} HASHINFO;
-
-/* Structure used to pass parameters to the record routines. */
-typedef struct {
-#define R_FIXEDLEN 0x01 /* fixed-length records */
-#define R_NOKEY 0x02 /* key not required */
-#define R_SNAPSHOT 0x04 /* snapshot the input */
- u_int32_t flags;
- u_int32_t cachesize; /* bytes to cache */
- u_int32_t psize; /* page size */
- int lorder; /* byte order */
- size_t reclen; /* record length (fixed-length records) */
- u_char bval; /* delimiting byte (variable-length records */
- char *bfname; /* btree file name */
-} RECNOINFO;
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-#define dbopen __db185_open
-DB *__db185_open __P((const char *, int, int, DBTYPE, const void *));
-
-#if defined(__cplusplus)
-}
-#endif
-#endif /* !_DB_185_H_ */
diff --git a/bdb/include/db_am.h b/bdb/include/db_am.h
deleted file mode 100644
index 3a41eb3bbfd..00000000000
--- a/bdb/include/db_am.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_am.h,v 11.21 2000/12/12 17:43:56 bostic Exp $
- */
-#ifndef _DB_AM_H_
-#define _DB_AM_H_
-
-#define DB_MINPAGECACHE 10 /* Min pages access methods cache. */
-
-/* DB recovery operation codes. The low bits used to have flags or'd in. */
-#define DB_ADD_DUP 0x10
-#define DB_REM_DUP 0x20
-#define DB_ADD_BIG 0x30
-#define DB_REM_BIG 0x40
-#define DB_UNUSED_1 0x50
-#define DB_UNUSED_2 0x60
-#define DB_ADD_PAGE 0x70
-#define DB_REM_PAGE 0x80
-
-/*
- * This is a grotesque naming hack. We have modified the btree page
- * allocation and freeing functions to be generic and have therefore
- * moved them into the access-method independent portion of the code.
- * However, since we didn't want to create new log records and routines
- * for them, we left their logging and recovery functions over in btree.
- * To make the code look prettier, we macro them, but this is sure to
- * confuse the heck out of everyone.
- */
-#define __db_pg_alloc_log __bam_pg_alloc_log
-#define __db_pg_free_log __bam_pg_free_log
-
-/*
- * Standard initialization and shutdown macros for all recovery functions.
- *
- * Requires the following local variables:
- *
- * DB *file_dbp;
- * DB_MPOOLFILE *mpf;
- * int ret;
- */
-#define REC_INTRO(func, inc_count) { \
- file_dbp = NULL; \
- dbc = NULL; \
- if ((ret = func(dbenv, dbtp->data, &argp)) != 0) \
- goto out; \
- if ((ret = __db_fileid_to_db(dbenv, \
- &file_dbp, argp->fileid, inc_count)) != 0) { \
- if (ret == DB_DELETED) { \
- ret = 0; \
- goto done; \
- } \
- goto out; \
- } \
- if (file_dbp == NULL) \
- goto out; \
- if ((ret = file_dbp->cursor(file_dbp, NULL, &dbc, 0)) != 0) \
- goto out; \
- F_SET(dbc, DBC_RECOVER); \
- mpf = file_dbp->mpf; \
-}
-
-#define REC_CLOSE { \
- int __t_ret; \
- if (argp != NULL) \
- __os_free(argp, sizeof(*argp)); \
- if (dbc != NULL && (__t_ret = dbc->c_close(dbc)) != 0 && ret == 0) \
- return (__t_ret); \
- return (ret); \
-}
-
-/*
- * No-op versions of the same macros.
- */
-#define REC_NOOP_INTRO(func) { \
- if ((ret = func(dbenv, dbtp->data, &argp)) != 0) \
- return (ret); \
-}
-#define REC_NOOP_CLOSE \
- if (argp != NULL) \
- __os_free(argp, sizeof(*argp)); \
- return (ret); \
-
-/*
- * Standard debugging macro for all recovery functions.
- */
-#ifdef DEBUG_RECOVER
-#define REC_PRINT(func) \
- (void)func(dbenv, dbtp, lsnp, op, info);
-#else
-#define REC_PRINT(func)
-#endif
-
-/*
- * Flags to __db_lget
- */
-#define LCK_COUPLE 0x01 /* Lock Couple */
-#define LCK_ALWAYS 0x02 /* Lock even for off page dup cursors */
-#define LCK_ROLLBACK 0x04 /* Lock even if in rollback */
-
-/*
- * If doing transactions we have to hold the locks associated with a data item
- * from a page for the entire transaction. However, we don't have to hold the
- * locks associated with walking the tree. Distinguish between the two so that
- * we don't tie up the internal pages of the tree longer than necessary.
- */
-#define __LPUT(dbc, lock) \
- (lock.off != LOCK_INVALID ? \
- lock_put((dbc)->dbp->dbenv, &(lock)) : 0)
-#define __TLPUT(dbc, lock) \
- (lock.off != LOCK_INVALID && \
- (dbc)->txn == NULL ? lock_put((dbc)->dbp->dbenv, &(lock)) : 0)
-
-#ifdef DIAGNOSTIC
-#define DB_CHECK_TXN(dbp, txn) \
- if (txn != NULL) \
- F_SET(dbp, DB_AM_TXN); \
- else if (F_ISSET(dbp, DB_AM_TXN)) \
- return (__db_missing_txn_err((dbp)->dbenv));
-#else
-#define DB_CHECK_TXN(dbp, txn)
-#endif
-
-#include "db_dispatch.h"
-#include "db_auto.h"
-#include "crdel_auto.h"
-#include "db_ext.h"
-#endif
diff --git a/bdb/include/db_cxx.h b/bdb/include/db_cxx.h
deleted file mode 100644
index b5599ee699c..00000000000
--- a/bdb/include/db_cxx.h
+++ /dev/null
@@ -1,652 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_cxx.h,v 11.44 2000/12/21 20:30:18 dda Exp $
- */
-
-#ifndef _DB_CXX_H_
-#define _DB_CXX_H_
-//
-// C++ assumptions:
-//
-// To ensure portability to many platforms, both new and old, we make
-// few assumptions about the C++ compiler and library. For example,
-// we do not expect STL, templates or namespaces to be available. The
-// "newest" C++ feature used is exceptions, which are used liberally
-// to transmit error information. Even the use of exceptions can be
-// disabled at runtime, to do so, use the DB_CXX_NO_EXCEPTIONS flags
-// with the DbEnv or Db constructor.
-//
-// C++ naming conventions:
-//
-// - All top level class names start with Db.
-// - All class members start with lower case letter.
-// - All private data members are suffixed with underscore.
-// - Use underscores to divide names into multiple words.
-// - Simple data accessors are named with get_ or set_ prefix.
-// - All method names are taken from names of functions in the C
-// layer of db (usually by dropping a prefix like "db_").
-// These methods have the same argument types and order,
-// other than dropping the explicit arg that acts as "this".
-//
-// As a rule, each DbFoo object has exactly one underlying DB_FOO struct
-// (defined in db.h) associated with it. In some cases, we inherit directly
-// from the DB_FOO structure to make this relationship explicit. Often,
-// the underlying C layer allocates and deallocates these structures, so
-// there is no easy way to add any data to the DbFoo class. When you see
-// a comment about whether data is permitted to be added, this is what
-// is going on. Of course, if we need to add data to such C++ classes
-// in the future, we will arrange to have an indirect pointer to the
-// DB_FOO struct (as some of the classes already have).
-//
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Forward declarations
-//
-
-#include <iostream.h>
-#include <stdarg.h>
-#include "db.h"
-
-class Db; // forward
-class Dbc; // forward
-class DbEnv; // forward
-class DbException; // forward
-class DbInfo; // forward
-class DbLock; // forward
-class DbLsn; // forward
-class DbMpoolFile; // forward
-class Dbt; // forward
-class DbTxn; // forward
-
-// These classes are not defined here and should be invisible
-// to the user, but some compilers require forward references.
-// There is one for each use of the DEFINE_DB_CLASS macro.
-
-class DbImp;
-class DbEnvImp;
-class DbMpoolFileImp;
-class DbTxnImp;
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Mechanisms for declaring classes
-//
-
-//
-// Every class defined in this file has an _exported next to the class name.
-// This is needed for WinTel machines so that the class methods can
-// be exported or imported in a DLL as appropriate. Users of the DLL
-// use the define DB_USE_DLL. When the DLL is built, DB_CREATE_DLL
-// must be defined.
-//
-#if defined(_MSC_VER)
-
-# if defined(DB_CREATE_DLL)
-# define _exported __declspec(dllexport) // creator of dll
-# elif defined(DB_USE_DLL)
-# define _exported __declspec(dllimport) // user of dll
-# else
-# define _exported // static lib creator or user
-# endif
-
-#else
-
-# define _exported
-
-#endif
-
-// DEFINE_DB_CLASS defines an imp_ data member and imp() accessor.
-// The underlying type is a pointer to an opaque *Imp class, that
-// gets converted to the correct implementation class by the implementation.
-//
-// Since these defines use "private/public" labels, and leave the access
-// being "private", we always use these by convention before any data
-// members in the private section of a class. Keeping them in the
-// private section also emphasizes that they are off limits to user code.
-//
-#define DEFINE_DB_CLASS(name) \
- public: class name##Imp* imp() { return (imp_); } \
- public: const class name##Imp* constimp() const { return (imp_); } \
- private: class name##Imp* imp_
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Turn off inappropriate compiler warnings
-//
-
-#ifdef _MSC_VER
-
-// These are level 4 warnings that are explicitly disabled.
-// With Visual C++, by default you do not see above level 3 unless
-// you use /W4. But we like to compile with the highest level
-// warnings to catch other errors.
-//
-// 4201: nameless struct/union
-// triggered by standard include file <winnt.h>
-//
-// 4514: unreferenced inline function has been removed
-// certain include files in MSVC define methods that are not called
-//
-#pragma warning(disable: 4201 4514)
-
-#endif
-
-// Some interfaces can be customized by allowing users
-// to define callback functions. For performance and
-// logistical reasons, some callbacks require you do
-// declare the functions in C, or in an extern "C" block.
-//
-extern "C" {
- typedef void * (*db_malloc_fcn_type)
- (size_t);
- typedef void * (*db_realloc_fcn_type)
- (void *, size_t);
- typedef int (*bt_compare_fcn_type)
- (DB *, const DBT *, const DBT *);
- typedef size_t (*bt_prefix_fcn_type)
- (DB *, const DBT *, const DBT *);
- typedef int (*dup_compare_fcn_type)
- (DB *, const DBT *, const DBT *);
- typedef u_int32_t (*h_hash_fcn_type)
- (DB *, const void *, u_int32_t);
- typedef int (*pgin_fcn_type)(DB_ENV *dbenv,
- db_pgno_t pgno, void *pgaddr, DBT *pgcookie);
- typedef int (*pgout_fcn_type)(DB_ENV *dbenv,
- db_pgno_t pgno, void *pgaddr, DBT *pgcookie);
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Exception classes
-//
-
-// Almost any error in the DB library throws a DbException.
-// Every exception should be considered an abnormality
-// (e.g. bug, misuse of DB, file system error).
-//
-// NOTE: We would like to inherit from class exception and
-// let it handle what(), but there are
-// MSVC++ problems when <exception> is included.
-//
-class _exported DbException
-{
-public:
- virtual ~DbException();
- DbException(int err);
- DbException(const char *description);
- DbException(const char *prefix, int err);
- DbException(const char *prefix1, const char *prefix2, int err);
- int get_errno() const;
- virtual const char *what() const;
-
- DbException(const DbException &);
- DbException &operator = (const DbException &);
-
-private:
- char *what_;
- int err_; // errno
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Lock classes
-//
-
-class _exported DbLock
-{
- friend class DbEnv;
-
-public:
- DbLock();
-
- int put(DbEnv *env);
-
- DbLock(const DbLock &);
- DbLock &operator = (const DbLock &);
-
-protected:
- // We can add data to this class if needed
- // since its contained class is not allocated by db.
- // (see comment at top)
-
- DbLock(DB_LOCK);
- DB_LOCK lock_;
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Log classes
-//
-
-class _exported DbLsn : protected DB_LSN
-{
- friend class DbEnv; // friendship needed to cast to base class
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Memory pool classes
-//
-
-class _exported DbMpoolFile
-{
- friend class DbEnv;
-
-public:
- int close();
- int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep);
- int put(void *pgaddr, u_int32_t flags);
- int set(void *pgaddr, u_int32_t flags);
- int sync();
-
- static int open(DbEnv *envp, const char *file,
- u_int32_t flags, int mode, size_t pagesize,
- DB_MPOOL_FINFO *finfop, DbMpoolFile **mpf);
-
-private:
- // We can add data to this class if needed
- // since it is implemented via a pointer.
- // (see comment at top)
-
- // Note: use DbMpoolFile::open()
- // to get pointers to a DbMpoolFile,
- // and call DbMpoolFile::close() rather than delete to release them.
- //
- DbMpoolFile();
-
- // Shut g++ up.
-protected:
- ~DbMpoolFile();
-
-private:
- // no copying
- DbMpoolFile(const DbMpoolFile &);
- void operator = (const DbMpoolFile &);
-
- DEFINE_DB_CLASS(DbMpoolFile);
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Transaction classes
-//
-
-class _exported DbTxn
-{
- friend class DbEnv;
-
-public:
- int abort();
- int commit(u_int32_t flags);
- u_int32_t id();
- int prepare();
-
-private:
- // We can add data to this class if needed
- // since it is implemented via a pointer.
- // (see comment at top)
-
- // Note: use DbEnv::txn_begin() to get pointers to a DbTxn,
- // and call DbTxn::abort() or DbTxn::commit rather than
- // delete to release them.
- //
- DbTxn();
- ~DbTxn();
-
- // no copying
- DbTxn(const DbTxn &);
- void operator = (const DbTxn &);
-
- DEFINE_DB_CLASS(DbTxn);
-};
-
-//
-// Berkeley DB environment class. Provides functions for opening databases.
-// User of this library can use this class as a starting point for
-// developing a DB application - derive their application class from
-// this one, add application control logic.
-//
-// Note that if you use the default constructor, you must explicitly
-// call appinit() before any other db activity (e.g. opening files)
-//
-class _exported DbEnv
-{
- friend class Db;
- friend class DbLock;
- friend class DbMpoolFile;
-
-public:
-
- ~DbEnv();
-
- // After using this constructor, you can set any needed
- // parameters for the environment using the set_* methods.
- // Then call open() to finish initializing the environment
- // and attaching it to underlying files.
- //
- DbEnv(u_int32_t flags);
-
- // These methods match those in the C interface.
- //
- int close(u_int32_t);
- void err(int, const char *, ...);
- void errx(const char *, ...);
- int open(const char *, u_int32_t, int);
- int remove(const char *, u_int32_t);
- int set_cachesize(u_int32_t, u_int32_t, int);
- int set_data_dir(const char *);
- void set_errcall(void (*)(const char *, char *));
- void set_errfile(FILE *);
- void set_errpfx(const char *);
- int set_flags(u_int32_t, int);
- int set_feedback(void (*)(DbEnv *, int, int));
- int set_recovery_init(int (*)(DbEnv *));
- int set_lg_bsize(u_int32_t);
- int set_lg_dir(const char *);
- int set_lg_max(u_int32_t);
- int set_lk_conflicts(u_int8_t *, int);
- int set_lk_detect(u_int32_t);
- int set_lk_max(u_int32_t);
- int set_lk_max_lockers(u_int32_t);
- int set_lk_max_locks(u_int32_t);
- int set_lk_max_objects(u_int32_t);
- int set_mp_mmapsize(size_t);
- int set_mutexlocks(int);
- static int set_pageyield(int);
- int set_paniccall(void (*)(DbEnv *, int));
- static int set_panicstate(int);
- static int set_region_init(int);
- int set_server(char *, long, long, u_int32_t);
- int set_shm_key(long);
- int set_tmp_dir(const char *);
- static int set_tas_spins(u_int32_t);
- int set_tx_max(u_int32_t);
- int set_tx_recover(int (*)(DbEnv *, Dbt *, DbLsn *, db_recops));
- int set_tx_timestamp(time_t *);
- int set_verbose(u_int32_t which, int onoff);
-
- // Version information. A static method so it can be obtained anytime.
- //
- static char *version(int *major, int *minor, int *patch);
-
- // Convert DB errors to strings
- static char *strerror(int);
-
- // If an error is detected and the error call function
- // or stream is set, a message is dispatched or printed.
- // If a prefix is set, each message is prefixed.
- //
- // You can use set_errcall() or set_errfile() above to control
- // error functionality. Alternatively, you can call
- // set_error_stream() to force all errors to a C++ stream.
- // It is unwise to mix these approaches.
- //
- void set_error_stream(ostream *);
-
- // used internally
- static void runtime_error(const char *caller, int err,
- int error_policy);
-
- // Lock functions
- //
- int lock_detect(u_int32_t flags, u_int32_t atype, int *aborted);
- int lock_get(u_int32_t locker, u_int32_t flags, const Dbt *obj,
- db_lockmode_t lock_mode, DbLock *lock);
- int lock_id(u_int32_t *idp);
- int lock_stat(DB_LOCK_STAT **statp, db_malloc_fcn_type db_malloc_fcn);
- int lock_vec(u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
- int nlist, DB_LOCKREQ **elistp);
-
- // Log functions
- //
- int log_archive(char **list[], u_int32_t flags, db_malloc_fcn_type db_malloc_fcn);
- static int log_compare(const DbLsn *lsn0, const DbLsn *lsn1);
- int log_file(DbLsn *lsn, char *namep, size_t len);
- int log_flush(const DbLsn *lsn);
- int log_get(DbLsn *lsn, Dbt *data, u_int32_t flags);
- int log_put(DbLsn *lsn, const Dbt *data, u_int32_t flags);
-
- int log_register(Db *dbp, const char *name);
- int log_stat(DB_LOG_STAT **spp, db_malloc_fcn_type db_malloc_fcn);
- int log_unregister(Db *dbp);
-
- // Mpool functions
- //
- int memp_register(int ftype,
- pgin_fcn_type pgin_fcn,
- pgout_fcn_type pgout_fcn);
-
- int memp_stat(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp,
- db_malloc_fcn_type db_malloc_fcn);
- int memp_sync(DbLsn *lsn);
- int memp_trickle(int pct, int *nwrotep);
-
- // Transaction functions
- //
- int txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags);
- int txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags);
- int txn_stat(DB_TXN_STAT **statp, db_malloc_fcn_type db_malloc_fcn);
-
- // These are public only because they need to be called
- // via C functions. They should never be called by users
- // of this class.
- //
- static void _stream_error_function(const char *, char *);
- static int _tx_recover_intercept(DB_ENV *env, DBT *dbt, DB_LSN *lsn,
- db_recops op);
- static void _paniccall_intercept(DB_ENV *env, int errval);
- static int _recovery_init_intercept(DB_ENV *env);
- static void _feedback_intercept(DB_ENV *env, int opcode, int pct);
- static void _destroy_check(const char *str, int isDbEnv);
-
-private:
- void cleanup();
- int initialize(DB_ENV *env);
- int error_policy();
-
- // Used internally
- DbEnv(DB_ENV *, u_int32_t flags);
-
- // no copying
- DbEnv(const DbEnv &);
- void operator = (const DbEnv &);
-
- DEFINE_DB_CLASS(DbEnv);
-
- // instance data
- int construct_error_;
- u_int32_t construct_flags_;
- Db *headdb_;
- Db *taildb_;
- int (*tx_recover_callback_)(DbEnv *, Dbt *, DbLsn *, db_recops);
- int (*recovery_init_callback_)(DbEnv *);
- void (*paniccall_callback_)(DbEnv *, int);
- void (*feedback_callback_)(DbEnv *, int, int);
-
- // class data
- static ostream *error_stream_;
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Table access classes
-//
-
-//
-// Represents a database table = a set of keys with associated values.
-//
-class _exported Db
-{
- friend class DbEnv;
-
-public:
- Db(DbEnv*, u_int32_t); // create a Db object, then call open()
- ~Db(); // does *not* call close.
-
- // These methods exactly match those in the C interface.
- //
- int close(u_int32_t flags);
- int cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags);
- int del(DbTxn *txnid, Dbt *key, u_int32_t flags);
- void err(int, const char *, ...);
- void errx(const char *, ...);
- int fd(int *fdp);
- int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
- int get_byteswapped() const;
- DBTYPE get_type() const;
- int join(Dbc **curslist, Dbc **dbcp, u_int32_t flags);
- int key_range(DbTxn *, Dbt *, DB_KEY_RANGE *, u_int32_t);
- int open(const char *, const char *subname, DBTYPE, u_int32_t, int);
- int put(DbTxn *, Dbt *, Dbt *, u_int32_t);
- int remove(const char *, const char *, u_int32_t);
- int rename(const char *, const char *, const char *, u_int32_t);
- int set_bt_compare(bt_compare_fcn_type);
- int set_bt_maxkey(u_int32_t);
- int set_bt_minkey(u_int32_t);
- int set_bt_prefix(bt_prefix_fcn_type);
- int set_cachesize(u_int32_t, u_int32_t, int);
- int set_dup_compare(dup_compare_fcn_type);
- void set_errcall(void (*)(const char *, char *));
- void set_errfile(FILE *);
- void set_errpfx(const char *);
- int set_append_recno(int (*)(Db *, Dbt *, db_recno_t));
- int set_feedback(void (*)(Db *, int, int));
- int set_flags(u_int32_t);
- int set_h_ffactor(u_int32_t);
- int set_h_hash(h_hash_fcn_type);
- int set_h_nelem(u_int32_t);
- int set_lorder(int);
- int set_malloc(db_malloc_fcn_type);
- int set_pagesize(u_int32_t);
- int set_paniccall(void (*)(DbEnv *, int));
- int set_realloc(db_realloc_fcn_type);
- int set_re_delim(int);
- int set_re_len(u_int32_t);
- int set_re_pad(int);
- int set_re_source(char *);
- int set_q_extentsize(u_int32_t);
- int stat(void *sp, db_malloc_fcn_type db_malloc_fcn, u_int32_t flags);
- int sync(u_int32_t flags);
- int upgrade(const char *name, u_int32_t flags);
- int verify(const char *, const char *, ostream *, u_int32_t);
-
- // This additional method is available for C++
- //
- void set_error_stream(ostream *);
-
- // These are public only because it needs to be called
- // via C functions. It should never be called by users
- // of this class.
- //
- static void _feedback_intercept(DB *db, int opcode, int pct);
- static int _append_recno_intercept(DB *db, DBT *data, db_recno_t recno);
-private:
-
- // no copying
- Db(const Db &);
- Db &operator = (const Db &);
-
- DEFINE_DB_CLASS(Db);
-
- void cleanup();
- int initialize();
- int error_policy();
-
- // instance data
- DbEnv *env_;
- Db *next_;
- Db *prev_;
- int construct_error_;
- u_int32_t flags_;
- u_int32_t construct_flags_;
- void (*feedback_callback_)(Db *, int, int);
- int (*append_recno_callback_)(Db *, Dbt *, db_recno_t);
-};
-
-//
-// A chunk of data, maybe a key or value.
-//
-class _exported Dbt : private DBT
-{
- friend class Dbc;
- friend class Db;
- friend class DbEnv;
-
-public:
-
- // key/data
- void *get_data() const;
- void set_data(void *);
-
- // key/data length
- u_int32_t get_size() const;
- void set_size(u_int32_t);
-
- // RO: length of user buffer.
- u_int32_t get_ulen() const;
- void set_ulen(u_int32_t);
-
- // RO: get/put record length.
- u_int32_t get_dlen() const;
- void set_dlen(u_int32_t);
-
- // RO: get/put record offset.
- u_int32_t get_doff() const;
- void set_doff(u_int32_t);
-
- // flags
- u_int32_t get_flags() const;
- void set_flags(u_int32_t);
-
- Dbt(void *data, size_t size);
- Dbt();
- ~Dbt();
- Dbt(const Dbt &);
- Dbt &operator = (const Dbt &);
-
-private:
- // We can add data to this class if needed
- // since parent class is not allocated by db.
- // (see comment at top)
-};
-
-class _exported Dbc : protected DBC
-{
- friend class Db;
-
-public:
- int close();
- int count(db_recno_t *countp, u_int32_t flags);
- int del(u_int32_t flags);
- int dup(Dbc** cursorp, u_int32_t flags);
- int get(Dbt* key, Dbt *data, u_int32_t flags);
- int put(Dbt* key, Dbt *data, u_int32_t flags);
-
-private:
- // No data is permitted in this class (see comment at top)
-
- // Note: use Db::cursor() to get pointers to a Dbc,
- // and call Dbc::close() rather than delete to release them.
- //
- Dbc();
- ~Dbc();
-
- // no copying
- Dbc(const Dbc &);
- Dbc &operator = (const Dbc &);
-};
-#endif /* !_DB_CXX_H_ */
diff --git a/bdb/include/db_dispatch.h b/bdb/include/db_dispatch.h
deleted file mode 100644
index 003acee6f65..00000000000
--- a/bdb/include/db_dispatch.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1995, 1996
- * The President and Fellows of Harvard University. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: db_dispatch.h,v 11.17 2000/12/14 07:39:13 ubell Exp $
- */
-
-#ifndef _DB_DISPATCH_H_
-#define _DB_DISPATCH_H_
-
-/*
- * Declarations and typedefs for the list of transaction IDs used during
- * recovery. This is a generic list used to pass along whatever information
- * we need during recovery.
- */
-struct __db_txnhead {
- LIST_HEAD(__db_headlink, __db_txnlist) head;
- u_int32_t maxid;
- int32_t generation;
-};
-
-#define TXNLIST_INVALID_ID 0xffffffff
-struct __db_txnlist {
- db_txnlist_type type;
- LIST_ENTRY(__db_txnlist) links;
- union {
- struct {
- u_int32_t txnid;
- int32_t generation;
- int32_t aborted;
- } t;
- struct {
-#define TXNLIST_FLAG_DELETED 0x1
-#define TXNLIST_FLAG_CLOSED 0x2
- u_int32_t flags;
- int32_t fileid;
- u_int32_t count;
- char *fname;
- } d;
- struct {
- int32_t ntxns;
- int32_t maxn;
- DB_LSN *lsn_array;
- } l;
- struct {
- int32_t nentries;
- int32_t maxentry;
- char *fname;
- int32_t fileid;
- db_pgno_t *pgno_array;
- u_int8_t uid[DB_FILE_ID_LEN];
- } p;
- } u;
-};
-
-/*
- * Flag value for __db_txnlist_lsnadd. Distinguish whether we are replacing
- * an entry in the transaction list or adding a new one.
- */
-
-#define TXNLIST_NEW 0x1
-
-#define DB_user_BEGIN 10000
-
-#endif
diff --git a/bdb/include/db_int.src b/bdb/include/db_int.src
deleted file mode 100644
index 347169ab5cd..00000000000
--- a/bdb/include/db_int.src
+++ /dev/null
@@ -1,397 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_int.src,v 11.42 2001/01/11 17:49:17 krinsky Exp $
- */
-
-#ifndef _DB_INTERNAL_H_
-#define _DB_INTERNAL_H_
-
-/*******************************************************
- * General includes.
- *******************************************************/
-#include "db.h"
-
-#ifndef NO_SYSTEM_INCLUDES
-#if defined(__STDC__) || defined(__cplusplus)
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-#include <errno.h>
-#endif
-
-#include "queue.h"
-#include "shqueue.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*******************************************************
- * General purpose constants and macros.
- *******************************************************/
-#define UINT16_T_MAX 0xffff /* Maximum 16 bit unsigned. */
-#define UINT32_T_MAX 0xffffffff /* Maximum 32 bit unsigned. */
-
-#define MEGABYTE 1048576
-#define GIGABYTE 1073741824
-
-#define MS_PER_SEC 1000 /* Milliseconds in a second. */
-#define USEC_PER_MS 1000 /* Microseconds in a millisecond. */
-
-#define DB_MIN_PGSIZE 0x000200 /* Minimum page size (512). */
-#define DB_MAX_PGSIZE 0x010000 /* Maximum page size (65536). */
-
-#define RECNO_OOB 0 /* Illegal record number. */
-
-/*
- * If we are unable to determine the underlying filesystem block size, use
- * 8K on the grounds that most OS's use less than 8K for a VM page size.
- */
-#define DB_DEF_IOSIZE (8 * 1024)
-
-/*
- * Aligning items to particular sizes or in pages or memory.
- *
- * db_align_t --
- * Largest integral type, used to align structures in memory. We don't store
- * floating point types in structures, so integral types should be sufficient
- * (and we don't have to worry about systems that store floats in other than
- * power-of-2 numbers of bytes). Additionally this fixes compiler that rewrite
- * structure assignments and ANSI C memcpy calls to be in-line instructions
- * that happen to require alignment. Note: this alignment isn't sufficient for
- * mutexes, which depend on things like cache line alignment. Mutex alignment
- * is handled separately, in mutex.h.
- *
- * db_alignp_t --
- * Integral type that's the same size as a pointer. There are places where
- * DB modifies pointers by discarding the bottom bits to guarantee alignment.
- * We can't use db_align_t, it may be larger than the pointer, and compilers
- * get upset about that. So far we haven't run on any machine where there
- * isn't an integral type the same size as a pointer -- here's hoping.
- */
-@db_align_t_decl@
-@db_alignp_t_decl@
-
-/* Align an integer to a specific boundary. */
-#undef ALIGN
-#define ALIGN(value, bound) \
- (((value) + (bound) - 1) & ~(((u_int)bound) - 1))
-
-/* Align a pointer to a specific boundary. */
-#undef ALIGNP
-#define ALIGNP(value, bound) ALIGN((db_alignp_t)value, bound)
-
-/*
- * There are several on-page structures that are declared to have a number of
- * fields followed by a variable length array of items. The structure size
- * without including the variable length array or the address of the first of
- * those elements can be found using SSZ.
- *
- * This macro can also be used to find the offset of a structure element in a
- * structure. This is used in various places to copy structure elements from
- * unaligned memory references, e.g., pointers into a packed page.
- *
- * There are two versions because compilers object if you take the address of
- * an array.
- */
-#undef SSZ
-#define SSZ(name, field) ((int)&(((name *)0)->field))
-
-#undef SSZA
-#define SSZA(name, field) ((int)&(((name *)0)->field[0]))
-
-/*
- * Print an address as a u_long (a u_long is the largest type we can print
- * portably). Most 64-bit systems have made longs 64-bits, so this should
- * work.
- */
-#define P_TO_ULONG(p) ((u_long)(db_alignp_t)(p))
-
-/* Structure used to print flag values. */
-typedef struct __fn {
- u_int32_t mask; /* Flag value. */
- const char *name; /* Flag name. */
-} FN;
-
-/* Set, clear and test flags. */
-#define FLD_CLR(fld, f) (fld) &= ~(f)
-#define FLD_ISSET(fld, f) ((fld) & (f))
-#define FLD_SET(fld, f) (fld) |= (f)
-#define F_CLR(p, f) (p)->flags &= ~(f)
-#define F_ISSET(p, f) ((p)->flags & (f))
-#define F_SET(p, f) (p)->flags |= (f)
-#define LF_CLR(f) (flags &= ~(f))
-#define LF_ISSET(f) (flags & (f))
-#define LF_SET(f) (flags |= (f))
-
-/* Display separator string. */
-#undef DB_LINE
-#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
-
-/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
-#define COMPQUIET(n, v) (n) = (v)
-
-/*******************************************************
- * Files.
- *******************************************************/
- /*
- * We use 1024 as the maximum path length. It's too hard to figure out what
- * the real path length is, as it was traditionally stored in <sys/param.h>,
- * and that file isn't always available.
- */
-#undef MAXPATHLEN
-#define MAXPATHLEN 1024
-
-#define PATH_DOT "." /* Current working directory. */
-#define PATH_SEPARATOR "/" /* Path separator character. */
-
-/*
- * Flags understood by __os_open.
- */
-#define DB_OSO_CREATE 0x001 /* POSIX: O_CREAT */
-#define DB_OSO_EXCL 0x002 /* POSIX: O_EXCL */
-#define DB_OSO_LOG 0x004 /* Opening a log file. */
-#define DB_OSO_RDONLY 0x008 /* POSIX: O_RDONLY */
-#define DB_OSO_REGION 0x010 /* Opening a region file. */
-#define DB_OSO_SEQ 0x020 /* Expected sequential access. */
-#define DB_OSO_TEMP 0x040 /* Remove after last close. */
-#define DB_OSO_TRUNC 0x080 /* POSIX: O_TRUNC */
-
-/*
- * Seek options understood by __os_seek.
- */
-typedef enum {
- DB_OS_SEEK_CUR, /* POSIX: SEEK_CUR */
- DB_OS_SEEK_END, /* POSIX: SEEK_END */
- DB_OS_SEEK_SET /* POSIX: SEEK_SET */
-} DB_OS_SEEK;
-
-/*******************************************************
- * Environment.
- *******************************************************/
-/* Type passed to __db_appname(). */
-typedef enum {
- DB_APP_NONE=0, /* No type (region). */
- DB_APP_DATA, /* Data file. */
- DB_APP_LOG, /* Log file. */
- DB_APP_TMP /* Temporary file. */
-} APPNAME;
-
-/*
- * CDB_LOCKING CDB product locking.
- * LOCKING_ON Locking has been configured.
- * LOGGING_ON Logging has been configured.
- * MPOOL_ON Memory pool has been configured.
- * TXN_ON Transactions have been configured.
- */
-#define CDB_LOCKING(dbenv) F_ISSET(dbenv, DB_ENV_CDB)
-#define LOCKING_ON(dbenv) ((dbenv)->lk_handle != NULL)
-#define LOGGING_ON(dbenv) ((dbenv)->lg_handle != NULL)
-#define MPOOL_ON(dbenv) ((dbenv)->mp_handle != NULL)
-#define TXN_ON(dbenv) ((dbenv)->tx_handle != NULL)
-
-/*
- * STD_LOCKING Standard locking, that is, locking was configured and CDB
- * was not. We do not do locking in off-page duplicate trees,
- * so we check for that in the cursor first.
- */
-#define STD_LOCKING(dbc) \
- (!F_ISSET(dbc, DBC_OPD) && \
- !CDB_LOCKING((dbc)->dbp->dbenv) && LOCKING_ON((dbc)->dbp->dbenv))
-
-/*
- * IS_RECOVERING The system is running recovery.
- */
-#define IS_RECOVERING(dbenv) \
- (LOGGING_ON(dbenv) && \
- F_ISSET((DB_LOG *)(dbenv)->lg_handle, DBLOG_RECOVER))
-
-/* Most initialization methods cannot be called after open is called. */
-#define ENV_ILLEGAL_AFTER_OPEN(dbenv, name) \
- if (F_ISSET((dbenv), DB_ENV_OPEN_CALLED)) \
- return (__db_mi_open(dbenv, name, 1));
-
-/* We're not actually user hostile, honest. */
-#define ENV_REQUIRES_CONFIG(dbenv, handle, subsystem) \
- if (handle == NULL) \
- return (__db_env_config(dbenv, subsystem));
-
-/*******************************************************
- * Database Access Methods.
- *******************************************************/
-/*
- * DB_IS_THREADED --
- * The database handle is free-threaded (was opened with DB_THREAD).
- */
-#define DB_IS_THREADED(dbp) \
- ((dbp)->mutexp != NULL)
-
-/* Initialization methods are often illegal before/after open is called. */
-#define DB_ILLEGAL_AFTER_OPEN(dbp, name) \
- if (F_ISSET((dbp), DB_OPEN_CALLED)) \
- return (__db_mi_open(dbp->dbenv, name, 1));
-#define DB_ILLEGAL_BEFORE_OPEN(dbp, name) \
- if (!F_ISSET((dbp), DB_OPEN_CALLED)) \
- return (__db_mi_open(dbp->dbenv, name, 0));
-/* Some initialization methods are illegal if environment isn't local. */
-#define DB_ILLEGAL_IN_ENV(dbp, name) \
- if (!F_ISSET(dbp->dbenv, DB_ENV_DBLOCAL)) \
- return (__db_mi_env(dbp->dbenv, name));
-#define DB_ILLEGAL_METHOD(dbp, flags) { \
- int __ret; \
- if ((__ret = __dbh_am_chk(dbp, flags)) != 0) \
- return (__ret); \
-}
-
-/*
- * Common DBC->internal fields. Each access method adds additional fields
- * to this list, but the initial fields are common.
- */
-#define __DBC_INTERNAL \
- DBC *opd; /* Off-page duplicate cursor. */\
- \
- void *page; /* Referenced page. */ \
- db_pgno_t root; /* Tree root. */ \
- db_pgno_t pgno; /* Referenced page number. */ \
- db_indx_t indx; /* Referenced key item index. */\
- \
- DB_LOCK lock; /* Cursor lock. */ \
- db_lockmode_t lock_mode; /* Lock mode. */
-
-struct __dbc_internal {
- __DBC_INTERNAL
-};
-
-/*
- * Access-method-common macro for determining whether a cursor
- * has been initialized.
- */
-#define IS_INITIALIZED(dbc) ((dbc)->internal->pgno != PGNO_INVALID)
-
-/*******************************************************
- * Mpool.
- *******************************************************/
-/*
- * File types for DB access methods. Negative numbers are reserved to DB.
- */
-#define DB_FTYPE_SET -1 /* Call pgin/pgout functions. */
-#define DB_FTYPE_NOTSET 0 /* Don't call... */
-
-/* Structure used as the DB pgin/pgout pgcookie. */
-typedef struct __dbpginfo {
- size_t db_pagesize; /* Underlying page size. */
- int needswap; /* If swapping required. */
-} DB_PGINFO;
-
-/*******************************************************
- * Log.
- *******************************************************/
-/* Initialize an LSN to 'zero'. */
-#define ZERO_LSN(LSN) do { \
- (LSN).file = 0; \
- (LSN).offset = 0; \
-} while (0)
-
-/* Return 1 if LSN is a 'zero' lsn, otherwise return 0. */
-#define IS_ZERO_LSN(LSN) ((LSN).file == 0)
-
-/* Test if we need to log a change. */
-#define DB_LOGGING(dbc) \
- (LOGGING_ON((dbc)->dbp->dbenv) && !F_ISSET(dbc, DBC_RECOVER))
-
-/* Internal flag for use with internal __log_unregister. */
-#define DB_LOGONLY 0x01
-/*******************************************************
- * Txn.
- *******************************************************/
-#define DB_NONBLOCK(C) ((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT))
-#define IS_SUBTRANSACTION(txn) \
- ((txn) != NULL && (txn)->parent != NULL)
-
-/*******************************************************
- * Global variables.
- *******************************************************/
-#ifdef HAVE_VXWORKS
-#include "semLib.h"
-#endif
-
-/*
- * DB global variables. Done in a single structure to minimize the name-space
- * pollution.
- */
-typedef struct __db_globals {
- u_int32_t db_pageyield; /* db_set_pageyield */
- u_int32_t db_panic; /* db_set_panic */
- u_int32_t db_region_init; /* db_set_region_init */
- u_int32_t db_tas_spins; /* db_set_tas_spins */
-#ifdef HAVE_VXWORKS
- u_int32_t db_global_init; /* VxWorks: inited */
- SEM_ID db_global_lock; /* VxWorks: global semaphore */
-#endif
- /* XA: list of opened environments. */
- TAILQ_HEAD(__db_envq, __db_env) db_envq;
-} DB_GLOBALS;
-
-#ifdef DB_INITIALIZE_DB_GLOBALS
-DB_GLOBALS __db_global_values = {
- 0, /* db_set_pageyield */
- 1, /* db_set_panic */
- 0, /* db_set_region_init */
- 0, /* db_set_tas_spins */
-#ifdef HAVE_VXWORKS
- 0, /* db_global_init */
- NULL, /* db_global_lock */
-#endif
- /* XA environment queue */
- {NULL, &__db_global_values.db_envq.tqh_first}
-};
-#else
-extern DB_GLOBALS __db_global_values;
-#endif
-#define DB_GLOBAL(v) __db_global_values.v
-
-/* Forward structure declarations. */
-struct __db_reginfo_t; typedef struct __db_reginfo_t REGINFO;
-struct __mutex_t; typedef struct __mutex_t MUTEX;
-struct __vrfy_childinfo; typedef struct __vrfy_childinfo VRFY_CHILDINFO;
-struct __vrfy_dbinfo; typedef struct __vrfy_dbinfo VRFY_DBINFO;
-struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO;
-struct __db_txnlist; typedef struct __db_txnlist DB_TXNLIST;
-struct __db_txnhead; typedef struct __db_txnhead DB_TXNHEAD;
-typedef enum {
- TXNLIST_DELETE,
- TXNLIST_LSN,
- TXNLIST_TXNID,
- TXNLIST_PGNO
-} db_txnlist_type;
-
-/*
- * Currently, region offsets are limited to 32-bits. I expect that's going
- * to have to be fixed in the not-too-distant future, since we won't want to
- * split 100Gb memory pools into that many different regions. It's typedef'd
- * so it won't be too painful to upgrade.
- */
-typedef u_int32_t roff_t;
-
-#if defined(__cplusplus)
-}
-#endif
-
-/*******************************************************
- * More general includes.
- *******************************************************/
-#include "debug.h"
-#include "mutex.h"
-#include "region.h"
-#include "mutex_ext.h"
-#include "env_ext.h"
-#include "os.h"
-#include "os_ext.h"
-#include "common_ext.h"
-
-#endif /* !_DB_INTERNAL_H_ */
diff --git a/bdb/include/db_join.h b/bdb/include/db_join.h
deleted file mode 100644
index d92887bb589..00000000000
--- a/bdb/include/db_join.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * @(#)db_join.h 11.1 (Sleepycat) 7/25/99
- */
-
-#ifndef _DB_JOIN_H_
-#define _DB_JOIN_H_
-
-/*
- * Joins use a join cursor that is similar to a regular DB cursor except
- * that it only supports c_get and c_close functionality. Also, it does
- * not support the full range of flags for get.
- */
-typedef struct __join_cursor {
- u_int8_t *j_exhausted; /* Array of flags; is cursor i exhausted? */
- DBC **j_curslist; /* Array of cursors in the join: constant. */
- DBC **j_fdupcurs; /* Cursors w/ first intances of current dup. */
- DBC **j_workcurs; /* Scratch cursor copies to muck with. */
- DB *j_primary; /* Primary dbp. */
- DBT j_key; /* Used to do lookups. */
- u_int32_t j_ncurs; /* How many cursors do we have? */
-#define JOIN_RETRY 0x01 /* Error on primary get; re-return same key. */
- u_int32_t flags;
-} JOIN_CURSOR;
-
-#endif
diff --git a/bdb/include/db_page.h b/bdb/include/db_page.h
deleted file mode 100644
index 8066424143b..00000000000
--- a/bdb/include/db_page.h
+++ /dev/null
@@ -1,576 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_page.h,v 11.28 2000/12/06 19:55:45 ubell Exp $
- */
-
-#ifndef _DB_PAGE_H_
-#define _DB_PAGE_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
- * DB page formats.
- *
- * !!!
- * This implementation requires that values within the following structures
- * NOT be padded -- note, ANSI C permits random padding within structures.
- * If your compiler pads randomly you can just forget ever making DB run on
- * your system. In addition, no data type can require larger alignment than
- * its own size, e.g., a 4-byte data element may not require 8-byte alignment.
- *
- * Note that key/data lengths are often stored in db_indx_t's -- this is
- * not accidental, nor does it limit the key/data size. If the key/data
- * item fits on a page, it's guaranteed to be small enough to fit into a
- * db_indx_t, and storing it in one saves space.
- */
-
-#define PGNO_INVALID 0 /* Invalid page number in any database. */
-#define PGNO_BASE_MD 0 /* Base database: metadata page number. */
-
-/* Page types. */
-#define P_INVALID 0 /* Invalid page type. */
-#define __P_DUPLICATE 1 /* Duplicate. DEPRECATED in 3.1 */
-#define P_HASH 2 /* Hash. */
-#define P_IBTREE 3 /* Btree internal. */
-#define P_IRECNO 4 /* Recno internal. */
-#define P_LBTREE 5 /* Btree leaf. */
-#define P_LRECNO 6 /* Recno leaf. */
-#define P_OVERFLOW 7 /* Overflow. */
-#define P_HASHMETA 8 /* Hash metadata page. */
-#define P_BTREEMETA 9 /* Btree metadata page. */
-#define P_QAMMETA 10 /* Queue metadata page. */
-#define P_QAMDATA 11 /* Queue data page. */
-#define P_LDUP 12 /* Off-page duplicate leaf. */
-#define P_PAGETYPE_MAX 13
-
-/*
- * When we create pages in mpool, we ask mpool to clear some number of bytes
- * in the header. This number must be at least as big as the regular page
- * headers and cover enough of the btree and hash meta-data pages to obliterate
- * the page type.
- */
-#define DB_PAGE_DB_LEN 32
-#define DB_PAGE_QUEUE_LEN 0
-
-/************************************************************************
- GENERIC METADATA PAGE HEADER
- *
- * !!!
- * The magic and version numbers have to be in the same place in all versions
- * of the metadata page as the application may not have upgraded the database.
- ************************************************************************/
-typedef struct _dbmeta31 {
- DB_LSN lsn; /* 00-07: LSN. */
- db_pgno_t pgno; /* 08-11: Current page number. */
- u_int32_t magic; /* 12-15: Magic number. */
- u_int32_t version; /* 16-19: Version. */
- u_int32_t pagesize; /* 20-23: Pagesize. */
- u_int8_t unused1[1]; /* 24: Unused. */
- u_int8_t type; /* 25: Page type. */
- u_int8_t unused2[2]; /* 26-27: Unused. */
- u_int32_t free; /* 28-31: Free list page number. */
- DB_LSN unused3; /* 32-39: former Lsn for allocation */
- u_int32_t key_count; /* 40-43: Cached key count. */
- u_int32_t record_count; /* 44-47: Cached record count. */
- u_int32_t flags; /* 48-51: Flags: unique to each AM. */
- /* 52-71: Unique file ID. */
- u_int8_t uid[DB_FILE_ID_LEN];
-} DBMETA31, DBMETA;
-
-/************************************************************************
- BTREE METADATA PAGE LAYOUT
- ************************************************************************/
-typedef struct _btmeta31 {
-#define BTM_DUP 0x001 /* Duplicates. */
-#define BTM_RECNO 0x002 /* Recno tree. */
-#define BTM_RECNUM 0x004 /* Btree: maintain record count. */
-#define BTM_FIXEDLEN 0x008 /* Recno: fixed length records. */
-#define BTM_RENUMBER 0x010 /* Recno: renumber on insert/delete. */
-#define BTM_SUBDB 0x020 /* Subdatabases. */
-#define BTM_DUPSORT 0x040 /* Duplicates are sorted. */
-#define BTM_MASK 0x07f
- DBMETA dbmeta; /* 00-71: Generic meta-data header. */
-
- u_int32_t maxkey; /* 72-75: Btree: Maxkey. */
- u_int32_t minkey; /* 76-79: Btree: Minkey. */
- u_int32_t re_len; /* 80-83: Recno: fixed-length record length. */
- u_int32_t re_pad; /* 84-87: Recno: fixed-length record pad. */
- u_int32_t root; /* 88-92: Root page. */
-
- /*
- * Minimum page size is 128.
- */
-} BTMETA31, BTMETA;
-
-/************************************************************************
- HASH METADATA PAGE LAYOUT
- ************************************************************************/
-typedef struct _hashmeta31 {
-#define DB_HASH_DUP 0x01 /* Duplicates. */
-#define DB_HASH_SUBDB 0x02 /* Subdatabases. */
-#define DB_HASH_DUPSORT 0x04 /* Duplicates are sorted. */
- DBMETA dbmeta; /* 00-71: Generic meta-data page header. */
-
- u_int32_t max_bucket; /* 72-75: ID of Maximum bucket in use */
- u_int32_t high_mask; /* 76-79: Modulo mask into table */
- u_int32_t low_mask; /* 80-83: Modulo mask into table lower half */
- u_int32_t ffactor; /* 84-87: Fill factor */
- u_int32_t nelem; /* 88-91: Number of keys in hash table */
- u_int32_t h_charkey; /* 92-95: Value of hash(CHARKEY) */
-#define NCACHED 32 /* number of spare points */
- /* 96-223: Spare pages for overflow */
- u_int32_t spares[NCACHED];
-
- /*
- * Minimum page size is 256.
- */
-} HMETA31, HMETA;
-
-/************************************************************************
- QUEUE METADATA PAGE LAYOUT
- ************************************************************************/
-/*
- * QAM Meta data page structure
- *
- */
-typedef struct _qmeta32 {
- DBMETA dbmeta; /* 00-71: Generic meta-data header. */
-
- u_int32_t first_recno; /* 72-75: First not deleted record. */
- u_int32_t cur_recno; /* 76-79: Last recno allocated. */
- u_int32_t re_len; /* 80-83: Fixed-length record length. */
- u_int32_t re_pad; /* 84-87: Fixed-length record pad. */
- u_int32_t rec_page; /* 88-91: Records Per Page. */
- u_int32_t page_ext; /* 92-95: Pages per extent */
-
- /*
- * Minimum page size is 128.
- */
-} QMETA32, QMETA;
-
-/*
- * DBMETASIZE is a constant used by __db_file_setup and DB->verify
- * as a buffer which is guaranteed to be larger than any possible
- * metadata page size and smaller than any disk sector.
- */
-#define DBMETASIZE 256
-
-/************************************************************************
- BTREE/HASH MAIN PAGE LAYOUT
- ************************************************************************/
-/*
- * +-----------------------------------+
- * | lsn | pgno | prev pgno |
- * +-----------------------------------+
- * | next pgno | entries | hf offset |
- * +-----------------------------------+
- * | level | type | index |
- * +-----------------------------------+
- * | index | free --> |
- * +-----------+-----------------------+
- * | F R E E A R E A |
- * +-----------------------------------+
- * | <-- free | item |
- * +-----------------------------------+
- * | item | item | item |
- * +-----------------------------------+
- *
- * sizeof(PAGE) == 26 bytes, and the following indices are guaranteed to be
- * two-byte aligned.
- *
- * For hash and btree leaf pages, index items are paired, e.g., inp[0] is the
- * key for inp[1]'s data. All other types of pages only contain single items.
- */
-typedef struct _db_page {
- DB_LSN lsn; /* 00-07: Log sequence number. */
- db_pgno_t pgno; /* 08-11: Current page number. */
- db_pgno_t prev_pgno; /* 12-15: Previous page number. */
- db_pgno_t next_pgno; /* 16-19: Next page number. */
- db_indx_t entries; /* 20-21: Number of items on the page. */
- db_indx_t hf_offset; /* 22-23: High free byte page offset. */
-
- /*
- * The btree levels are numbered from the leaf to the root, starting
- * with 1, so the leaf is level 1, its parent is level 2, and so on.
- * We maintain this level on all btree pages, but the only place that
- * we actually need it is on the root page. It would not be difficult
- * to hide the byte on the root page once it becomes an internal page,
- * so we could get this byte back if we needed it for something else.
- */
-#define LEAFLEVEL 1
-#define MAXBTREELEVEL 255
- u_int8_t level; /* 24: Btree tree level. */
- u_int8_t type; /* 25: Page type. */
- db_indx_t inp[1]; /* Variable length index of items. */
-} PAGE;
-
-/* PAGE element macros. */
-#define LSN(p) (((PAGE *)p)->lsn)
-#define PGNO(p) (((PAGE *)p)->pgno)
-#define PREV_PGNO(p) (((PAGE *)p)->prev_pgno)
-#define NEXT_PGNO(p) (((PAGE *)p)->next_pgno)
-#define NUM_ENT(p) (((PAGE *)p)->entries)
-#define HOFFSET(p) (((PAGE *)p)->hf_offset)
-#define LEVEL(p) (((PAGE *)p)->level)
-#define TYPE(p) (((PAGE *)p)->type)
-
-/************************************************************************
- QUEUE MAIN PAGE LAYOUT
- ************************************************************************/
-typedef struct _qpage {
- DB_LSN lsn; /* 00-07: Log sequence number. */
- db_pgno_t pgno; /* 08-11: Current page number. */
- u_int32_t unused0[3]; /* 12-23: Unused. */
- u_int8_t unused1[1]; /* 24: Unused. */
- u_int8_t type; /* 25: Page type. */
- u_int8_t unused2[2]; /* 26-27: Unused. */
-} QPAGE;
-
-/*
- * !!!
- * The next_pgno and prev_pgno fields are not maintained for btree and recno
- * internal pages. Doing so only provides a minor performance improvement,
- * it's hard to do when deleting internal pages, and it increases the chance
- * of deadlock during deletes and splits because we have to re-link pages at
- * more than the leaf level.
- *
- * !!!
- * The btree/recno access method needs db_recno_t bytes of space on the root
- * page to specify how many records are stored in the tree. (The alternative
- * is to store the number of records in the meta-data page, which will create
- * a second hot spot in trees being actively modified, or recalculate it from
- * the BINTERNAL fields on each access.) Overload the PREV_PGNO field.
- */
-#define RE_NREC(p) \
- ((TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO) ? \
- PREV_PGNO(p) : (TYPE(p) == P_LBTREE ? NUM_ENT(p) / 2 : NUM_ENT(p)))
-#define RE_NREC_ADJ(p, adj) \
- PREV_PGNO(p) += adj;
-#define RE_NREC_SET(p, num) \
- PREV_PGNO(p) = num;
-
-/*
- * Initialize a page.
- *
- * !!!
- * Don't modify the page's LSN, code depends on it being unchanged after a
- * P_INIT call.
- */
-#define P_INIT(pg, pg_size, n, pg_prev, pg_next, btl, pg_type) do { \
- PGNO(pg) = n; \
- PREV_PGNO(pg) = pg_prev; \
- NEXT_PGNO(pg) = pg_next; \
- NUM_ENT(pg) = 0; \
- HOFFSET(pg) = pg_size; \
- LEVEL(pg) = btl; \
- TYPE(pg) = pg_type; \
-} while (0)
-
-/* Page header length (offset to first index). */
-#define P_OVERHEAD (SSZA(PAGE, inp))
-
-/* First free byte. */
-#define LOFFSET(pg) (P_OVERHEAD + NUM_ENT(pg) * sizeof(db_indx_t))
-
-/* Free space on a regular page. */
-#define P_FREESPACE(pg) (HOFFSET(pg) - LOFFSET(pg))
-
-/* Get a pointer to the bytes at a specific index. */
-#define P_ENTRY(pg, indx) ((u_int8_t *)pg + ((PAGE *)pg)->inp[indx])
-
-/************************************************************************
- OVERFLOW PAGE LAYOUT
- ************************************************************************/
-
-/*
- * Overflow items are referenced by HOFFPAGE and BOVERFLOW structures, which
- * store a page number (the first page of the overflow item) and a length
- * (the total length of the overflow item). The overflow item consists of
- * some number of overflow pages, linked by the next_pgno field of the page.
- * A next_pgno field of PGNO_INVALID flags the end of the overflow item.
- *
- * Overflow page overloads:
- * The amount of overflow data stored on each page is stored in the
- * hf_offset field.
- *
- * The implementation reference counts overflow items as it's possible
- * for them to be promoted onto btree internal pages. The reference
- * count is stored in the entries field.
- */
-#define OV_LEN(p) (((PAGE *)p)->hf_offset)
-#define OV_REF(p) (((PAGE *)p)->entries)
-
-/* Maximum number of bytes that you can put on an overflow page. */
-#define P_MAXSPACE(psize) ((psize) - P_OVERHEAD)
-
-/* Free space on an overflow page. */
-#define P_OVFLSPACE(psize, pg) (P_MAXSPACE(psize) - HOFFSET(pg))
-
-/************************************************************************
- HASH PAGE LAYOUT
- ************************************************************************/
-
-/* Each index references a group of bytes on the page. */
-#define H_KEYDATA 1 /* Key/data item. */
-#define H_DUPLICATE 2 /* Duplicate key/data item. */
-#define H_OFFPAGE 3 /* Overflow key/data item. */
-#define H_OFFDUP 4 /* Overflow page of duplicates. */
-
-/*
- * !!!
- * Items on hash pages are (potentially) unaligned, so we can never cast the
- * (page + offset) pointer to an HKEYDATA, HOFFPAGE or HOFFDUP structure, as
- * we do with B+tree on-page structures. Because we frequently want the type
- * field, it requires no alignment, and it's in the same location in all three
- * structures, there's a pair of macros.
- */
-#define HPAGE_PTYPE(p) (*(u_int8_t *)p)
-#define HPAGE_TYPE(pg, indx) (*P_ENTRY(pg, indx))
-
-/*
- * The first and second types are H_KEYDATA and H_DUPLICATE, represented
- * by the HKEYDATA structure:
- *
- * +-----------------------------------+
- * | type | key/data ... |
- * +-----------------------------------+
- *
- * For duplicates, the data field encodes duplicate elements in the data
- * field:
- *
- * +---------------------------------------------------------------+
- * | type | len1 | element1 | len1 | len2 | element2 | len2 |
- * +---------------------------------------------------------------+
- *
- * Thus, by keeping track of the offset in the element, we can do both
- * backward and forward traversal.
- */
-typedef struct _hkeydata {
- u_int8_t type; /* 00: Page type. */
- u_int8_t data[1]; /* Variable length key/data item. */
-} HKEYDATA;
-#define HKEYDATA_DATA(p) (((u_int8_t *)p) + SSZA(HKEYDATA, data))
-
-/*
- * The length of any HKEYDATA item. Note that indx is an element index,
- * not a PAIR index.
- */
-#define LEN_HITEM(pg, pgsize, indx) \
- (((indx) == 0 ? pgsize : \
- ((PAGE *)(pg))->inp[indx - 1]) - ((PAGE *)(pg))->inp[indx])
-
-#define LEN_HKEYDATA(pg, psize, indx) \
- (LEN_HITEM(pg, psize, indx) - HKEYDATA_SIZE(0))
-
-/*
- * Page space required to add a new HKEYDATA item to the page, with and
- * without the index value.
- */
-#define HKEYDATA_SIZE(len) \
- ((len) + SSZA(HKEYDATA, data))
-#define HKEYDATA_PSIZE(len) \
- (HKEYDATA_SIZE(len) + sizeof(db_indx_t))
-
-/* Put a HKEYDATA item at the location referenced by a page entry. */
-#define PUT_HKEYDATA(pe, kd, len, type) { \
- ((HKEYDATA *)pe)->type = type; \
- memcpy((u_int8_t *)pe + sizeof(u_int8_t), kd, len); \
-}
-
-/*
- * Macros the describe the page layout in terms of key-data pairs.
- */
-#define H_NUMPAIRS(pg) (NUM_ENT(pg) / 2)
-#define H_KEYINDEX(indx) (indx)
-#define H_DATAINDEX(indx) ((indx) + 1)
-#define H_PAIRKEY(pg, indx) P_ENTRY(pg, H_KEYINDEX(indx))
-#define H_PAIRDATA(pg, indx) P_ENTRY(pg, H_DATAINDEX(indx))
-#define H_PAIRSIZE(pg, psize, indx) \
- (LEN_HITEM(pg, psize, H_KEYINDEX(indx)) + \
- LEN_HITEM(pg, psize, H_DATAINDEX(indx)))
-#define LEN_HDATA(p, psize, indx) LEN_HKEYDATA(p, psize, H_DATAINDEX(indx))
-#define LEN_HKEY(p, psize, indx) LEN_HKEYDATA(p, psize, H_KEYINDEX(indx))
-
-/*
- * The third type is the H_OFFPAGE, represented by the HOFFPAGE structure:
- */
-typedef struct _hoffpage {
- u_int8_t type; /* 00: Page type and delete flag. */
- u_int8_t unused[3]; /* 01-03: Padding, unused. */
- db_pgno_t pgno; /* 04-07: Offpage page number. */
- u_int32_t tlen; /* 08-11: Total length of item. */
-} HOFFPAGE;
-
-#define HOFFPAGE_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, pgno))
-#define HOFFPAGE_TLEN(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, tlen))
-
-/*
- * Page space required to add a new HOFFPAGE item to the page, with and
- * without the index value.
- */
-#define HOFFPAGE_SIZE (sizeof(HOFFPAGE))
-#define HOFFPAGE_PSIZE (HOFFPAGE_SIZE + sizeof(db_indx_t))
-
-/*
- * The fourth type is H_OFFDUP represented by the HOFFDUP structure:
- */
-typedef struct _hoffdup {
- u_int8_t type; /* 00: Page type and delete flag. */
- u_int8_t unused[3]; /* 01-03: Padding, unused. */
- db_pgno_t pgno; /* 04-07: Offpage page number. */
-} HOFFDUP;
-#define HOFFDUP_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFDUP, pgno))
-
-/*
- * Page space required to add a new HOFFDUP item to the page, with and
- * without the index value.
- */
-#define HOFFDUP_SIZE (sizeof(HOFFDUP))
-
-/************************************************************************
- BTREE PAGE LAYOUT
- ************************************************************************/
-
-/* Each index references a group of bytes on the page. */
-#define B_KEYDATA 1 /* Key/data item. */
-#define B_DUPLICATE 2 /* Duplicate key/data item. */
-#define B_OVERFLOW 3 /* Overflow key/data item. */
-
-/*
- * We have to store a deleted entry flag in the page. The reason is complex,
- * but the simple version is that we can't delete on-page items referenced by
- * a cursor -- the return order of subsequent insertions might be wrong. The
- * delete flag is an overload of the top bit of the type byte.
- */
-#define B_DELETE (0x80)
-#define B_DCLR(t) (t) &= ~B_DELETE
-#define B_DSET(t) (t) |= B_DELETE
-#define B_DISSET(t) ((t) & B_DELETE)
-
-#define B_TYPE(t) ((t) & ~B_DELETE)
-#define B_TSET(t, type, deleted) { \
- (t) = (type); \
- if (deleted) \
- B_DSET(t); \
-}
-
-/*
- * The first type is B_KEYDATA, represented by the BKEYDATA structure:
- */
-typedef struct _bkeydata {
- db_indx_t len; /* 00-01: Key/data item length. */
- u_int8_t type; /* 02: Page type AND DELETE FLAG. */
- u_int8_t data[1]; /* Variable length key/data item. */
-} BKEYDATA;
-
-/* Get a BKEYDATA item for a specific index. */
-#define GET_BKEYDATA(pg, indx) \
- ((BKEYDATA *)P_ENTRY(pg, indx))
-
-/*
- * Page space required to add a new BKEYDATA item to the page, with and
- * without the index value.
- */
-#define BKEYDATA_SIZE(len) \
- ALIGN((len) + SSZA(BKEYDATA, data), sizeof(u_int32_t))
-#define BKEYDATA_PSIZE(len) \
- (BKEYDATA_SIZE(len) + sizeof(db_indx_t))
-
-/*
- * The second and third types are B_DUPLICATE and B_OVERFLOW, represented
- * by the BOVERFLOW structure.
- */
-typedef struct _boverflow {
- db_indx_t unused1; /* 00-01: Padding, unused. */
- u_int8_t type; /* 02: Page type AND DELETE FLAG. */
- u_int8_t unused2; /* 03: Padding, unused. */
- db_pgno_t pgno; /* 04-07: Next page number. */
- u_int32_t tlen; /* 08-11: Total length of item. */
-} BOVERFLOW;
-
-/* Get a BOVERFLOW item for a specific index. */
-#define GET_BOVERFLOW(pg, indx) \
- ((BOVERFLOW *)P_ENTRY(pg, indx))
-
-/*
- * Page space required to add a new BOVERFLOW item to the page, with and
- * without the index value.
- */
-#define BOVERFLOW_SIZE \
- ALIGN(sizeof(BOVERFLOW), sizeof(u_int32_t))
-#define BOVERFLOW_PSIZE \
- (BOVERFLOW_SIZE + sizeof(db_indx_t))
-
-/*
- * Btree leaf and hash page layouts group indices in sets of two, one for the
- * key and one for the data. Everything else does it in sets of one to save
- * space. Use the following macros so that it's real obvious what's going on.
- */
-#define O_INDX 1
-#define P_INDX 2
-
-/************************************************************************
- BTREE INTERNAL PAGE LAYOUT
- ************************************************************************/
-
-/*
- * Btree internal entry.
- */
-typedef struct _binternal {
- db_indx_t len; /* 00-01: Key/data item length. */
- u_int8_t type; /* 02: Page type AND DELETE FLAG. */
- u_int8_t unused; /* 03: Padding, unused. */
- db_pgno_t pgno; /* 04-07: Page number of referenced page. */
- db_recno_t nrecs; /* 08-11: Subtree record count. */
- u_int8_t data[1]; /* Variable length key item. */
-} BINTERNAL;
-
-/* Get a BINTERNAL item for a specific index. */
-#define GET_BINTERNAL(pg, indx) \
- ((BINTERNAL *)P_ENTRY(pg, indx))
-
-/*
- * Page space required to add a new BINTERNAL item to the page, with and
- * without the index value.
- */
-#define BINTERNAL_SIZE(len) \
- ALIGN((len) + SSZA(BINTERNAL, data), sizeof(u_int32_t))
-#define BINTERNAL_PSIZE(len) \
- (BINTERNAL_SIZE(len) + sizeof(db_indx_t))
-
-/************************************************************************
- RECNO INTERNAL PAGE LAYOUT
- ************************************************************************/
-
-/*
- * The recno internal entry.
- */
-typedef struct _rinternal {
- db_pgno_t pgno; /* 00-03: Page number of referenced page. */
- db_recno_t nrecs; /* 04-07: Subtree record count. */
-} RINTERNAL;
-
-/* Get a RINTERNAL item for a specific index. */
-#define GET_RINTERNAL(pg, indx) \
- ((RINTERNAL *)P_ENTRY(pg, indx))
-
-/*
- * Page space required to add a new RINTERNAL item to the page, with and
- * without the index value.
- */
-#define RINTERNAL_SIZE \
- ALIGN(sizeof(RINTERNAL), sizeof(u_int32_t))
-#define RINTERNAL_PSIZE \
- (RINTERNAL_SIZE + sizeof(db_indx_t))
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* _DB_PAGE_H_ */
diff --git a/bdb/include/db_server_int.h b/bdb/include/db_server_int.h
deleted file mode 100644
index 69e88ea5aec..00000000000
--- a/bdb/include/db_server_int.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_server_int.h,v 1.13 2001/01/11 18:19:52 bostic Exp $
- */
-
-#ifndef _DB_SERVER_INT_H_
-#define _DB_SERVER_INT_H_
-
-#define DB_SERVER_TIMEOUT 300 /* 5 minutes */
-#define DB_SERVER_MAXTIMEOUT 1200 /* 20 minutes */
-#define DB_SERVER_IDLETIMEOUT 86400 /* 1 day */
-
-#define CT_CURSOR 0x001 /* Cursor */
-#define CT_DB 0x002 /* Database */
-#define CT_ENV 0x004 /* Env */
-#define CT_TXN 0x008 /* Txn */
-
-#define CT_JOIN 0x10000000 /* Join cursor component */
-#define CT_JOINCUR 0x20000000 /* Join cursor */
-
-typedef struct home_entry home_entry;
-struct home_entry {
- LIST_ENTRY(home_entry) entries;
- char *home;
- char *dir;
- char *name;
-};
-
-/*
- * We maintain an activity timestamp for each handle. However, we
- * set it to point, possibly to the ct_active field of its own handle
- * or it may point to the ct_active field of a parent. In the case
- * of nested transactions and any cursors within transactions it must
- * point to the ct_active field of the ultimate parent of the transaction
- * no matter how deeply it is nested.
- */
-typedef struct ct_entry ct_entry;
-struct ct_entry {
- LIST_ENTRY(ct_entry) entries; /* List of entries */
- union {
- DB_ENV *envp; /* H_ENV */
- DB_TXN *txnp; /* H_TXN */
- DB *dbp; /* H_DB */
- DBC *dbc; /* H_CURSOR */
- void *anyp;
- } handle_u;
- long ct_id; /* Client ID */
- long *ct_activep; /* Activity timestamp pointer*/
- long *ct_origp; /* Original timestamp pointer*/
- long ct_active; /* Activity timestamp */
- long ct_timeout; /* Resource timeout */
- long ct_idle; /* Idle timeout */
- u_int32_t ct_type; /* This entry's type */
- struct ct_entry *ct_parent; /* Its parent */
- struct ct_entry *ct_envparent; /* Its environment */
-};
-
-#define ct_envp handle_u.envp
-#define ct_txnp handle_u.txnp
-#define ct_dbp handle_u.dbp
-#define ct_dbc handle_u.dbc
-#define ct_anyp handle_u.anyp
-
-extern int __dbsrv_verbose;
-
-/*
- * Get ctp and activate it.
- * Assumes local variable 'replyp'.
- * NOTE: May 'return' from macro.
- */
-#define ACTIVATE_CTP(ctp, id, type) { \
- (ctp) = get_tableent(id); \
- if ((ctp) == NULL) { \
- replyp->status = DB_NOSERVER_ID;\
- return; \
- } \
- DB_ASSERT((ctp)->ct_type & (type)); \
- __dbsrv_active(ctp); \
-}
-
-#endif /* _DB_SERVER_INT_H_ */
diff --git a/bdb/include/db_shash.h b/bdb/include/db_shash.h
deleted file mode 100644
index 0b9aac98f53..00000000000
--- a/bdb/include/db_shash.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_shash.h,v 11.7 2000/12/12 17:43:56 bostic Exp $
- */
-
-/* Hash Headers */
-typedef SH_TAILQ_HEAD(__hash_head) DB_HASHTAB;
-
-/*
- * HASHLOOKUP --
- *
- * Look up something in a shared memory hash table. The "elt" argument
- * should be a key, and cmp_func must know how to compare a key to whatever
- * structure it is that appears in the hash table. The comparison function
- *
- * begin: address of the beginning of the hash table.
- * ndx: index into table for this item.
- * type: the structure type of the elements that are linked in each bucket.
- * field: the name of the field by which the "type" structures are linked.
- * elt: the item for which we are searching in the hash table.
- * res: the variable into which we'll store the element if we find it.
- * cmp: called as: cmp(lookup_elt, table_elt).
- *
- * If the element is not in the hash table, this macro exits with res set
- * to NULL.
- */
-#define HASHLOOKUP(begin, ndx, type, field, elt, res, cmp) do { \
- DB_HASHTAB *__bucket; \
- \
- __bucket = &begin[ndx]; \
- for (res = SH_TAILQ_FIRST(__bucket, type); \
- res != NULL; res = SH_TAILQ_NEXT(res, field, type)) \
- if (cmp(elt, res)) \
- break; \
-} while (0)
-
-/*
- * HASHINSERT --
- *
- * Insert a new entry into the hash table. This assumes that you already
- * have the bucket locked and that lookup has failed; don't call it if you
- * haven't already called HASHLOOKUP. If you do, you could get duplicate
- * entries.
- *
- * begin: the beginning address of the hash table.
- * ndx: the index for this element.
- * type: the structure type of the elements that are linked in each bucket.
- * field: the name of the field by which the "type" structures are linked.
- * elt: the item to be inserted.
- */
-#define HASHINSERT(begin, ndx, type, field, elt) do { \
- DB_HASHTAB *__bucket; \
- \
- __bucket = &begin[ndx]; \
- SH_TAILQ_INSERT_HEAD(__bucket, elt, field, type); \
-} while (0)
-
-/*
- * HASHREMOVE_EL --
- * Given the object "obj" in the table, remove it.
- *
- * begin: address of the beginning of the hash table.
- * ndx: index into hash table of where this element belongs.
- * type: the structure type of the elements that are linked in each bucket.
- * field: the name of the field by which the "type" structures are linked.
- * obj: the object in the table that we with to delete.
- */
-#define HASHREMOVE_EL(begin, ndx, type, field, obj) { \
- DB_HASHTAB *__bucket; \
- \
- __bucket = &begin[ndx]; \
- SH_TAILQ_REMOVE(__bucket, obj, field, type); \
-}
diff --git a/bdb/include/db_swap.h b/bdb/include/db_swap.h
deleted file mode 100644
index bc96afb7a10..00000000000
--- a/bdb/include/db_swap.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: db_swap.h,v 11.5 2000/03/28 16:14:36 bostic Exp $
- */
-
-#ifndef _DB_SWAP_H_
-#define _DB_SWAP_H_
-
-/*
- * Little endian <==> big endian 32-bit swap macros.
- * M_32_SWAP swap a memory location
- * P_32_COPY copy potentially unaligned 4 byte quantities
- * P_32_SWAP swap a referenced memory location
- */
-#define M_32_SWAP(a) { \
- u_int32_t _tmp; \
- _tmp = a; \
- ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[3]; \
- ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[2]; \
- ((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1]; \
- ((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0]; \
-}
-#define P_32_COPY(a, b) { \
- ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \
- ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \
- ((u_int8_t *)b)[2] = ((u_int8_t *)a)[2]; \
- ((u_int8_t *)b)[3] = ((u_int8_t *)a)[3]; \
-}
-#define P_32_SWAP(a) { \
- u_int32_t _tmp; \
- P_32_COPY(a, &_tmp); \
- ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[3]; \
- ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[2]; \
- ((u_int8_t *)a)[2] = ((u_int8_t *)&_tmp)[1]; \
- ((u_int8_t *)a)[3] = ((u_int8_t *)&_tmp)[0]; \
-}
-
-/*
- * Little endian <==> big endian 16-bit swap macros.
- * M_16_SWAP swap a memory location
- * P_16_COPY copy potentially unaligned 2 byte quantities
- * P_16_SWAP swap a referenced memory location
- */
-#define M_16_SWAP(a) { \
- u_int16_t _tmp; \
- _tmp = (u_int16_t)a; \
- ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[1]; \
- ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[0]; \
-}
-#define P_16_COPY(a, b) { \
- ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \
- ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \
-}
-#define P_16_SWAP(a) { \
- u_int16_t _tmp; \
- P_16_COPY(a, &_tmp); \
- ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[1]; \
- ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[0]; \
-}
-
-#define SWAP32(p) { \
- P_32_SWAP(p); \
- (p) += sizeof(u_int32_t); \
-}
-#define SWAP16(p) { \
- P_16_SWAP(p); \
- (p) += sizeof(u_int16_t); \
-}
-
-/*
- * DB has local versions of htonl() and ntohl() that only operate on pointers
- * to the right size memory locations, the portability magic for finding the
- * real ones isn't worth the effort.
- */
-#if defined(WORDS_BIGENDIAN)
-#define DB_HTONL(p)
-#define DB_NTOHL(p)
-#else
-#define DB_HTONL(p) P_32_SWAP(p)
-#define DB_NTOHL(p) P_32_SWAP(p)
-#endif
-
-#endif /* !_DB_SWAP_H_ */
diff --git a/bdb/include/db_upgrade.h b/bdb/include/db_upgrade.h
deleted file mode 100644
index d8d99645231..00000000000
--- a/bdb/include/db_upgrade.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_upgrade.h,v 1.5 2000/11/16 23:40:56 ubell Exp $
- */
-
-#ifndef _DB_UPGRADE_H_
-#define _DB_UPGRADE_H_
-
-/*
- * This file defines the metadata pages from the previous release.
- * These structures are only used to upgrade old versions of databases.
- */
-
-/* Structures from the 3.1 release */
-/*
- * QAM Meta data page structure
- *
- */
-typedef struct _qmeta31 {
- DBMETA dbmeta; /* 00-71: Generic meta-data header. */
-
- u_int32_t start; /* 72-75: Start offset. */
- u_int32_t first_recno; /* 76-79: First not deleted record. */
- u_int32_t cur_recno; /* 80-83: Last recno allocated. */
- u_int32_t re_len; /* 84-87: Fixed-length record length. */
- u_int32_t re_pad; /* 88-91: Fixed-length record pad. */
- u_int32_t rec_page; /* 92-95: Records Per Page. */
-
- /*
- * Minimum page size is 128.
- */
-} QMETA31;
-
-/* Structures from the 3.0 release */
-
-typedef struct _dbmeta30 {
- DB_LSN lsn; /* 00-07: LSN. */
- db_pgno_t pgno; /* 08-11: Current page number. */
- u_int32_t magic; /* 12-15: Magic number. */
- u_int32_t version; /* 16-19: Version. */
- u_int32_t pagesize; /* 20-23: Pagesize. */
- u_int8_t unused1[1]; /* 24: Unused. */
- u_int8_t type; /* 25: Page type. */
- u_int8_t unused2[2]; /* 26-27: Unused. */
- u_int32_t free; /* 28-31: Free list page number. */
- u_int32_t flags; /* 32-35: Flags: unique to each AM. */
- /* 36-55: Unique file ID. */
- u_int8_t uid[DB_FILE_ID_LEN];
-} DBMETA30;
-
-/************************************************************************
- BTREE METADATA PAGE LAYOUT
- ************************************************************************/
-typedef struct _btmeta30 {
- DBMETA30 dbmeta; /* 00-55: Generic meta-data header. */
-
- u_int32_t maxkey; /* 56-59: Btree: Maxkey. */
- u_int32_t minkey; /* 60-63: Btree: Minkey. */
- u_int32_t re_len; /* 64-67: Recno: fixed-length record length. */
- u_int32_t re_pad; /* 68-71: Recno: fixed-length record pad. */
- u_int32_t root; /* 72-75: Root page. */
-
- /*
- * Minimum page size is 128.
- */
-} BTMETA30;
-
-/************************************************************************
- HASH METADATA PAGE LAYOUT
- ************************************************************************/
-typedef struct _hashmeta30 {
- DBMETA30 dbmeta; /* 00-55: Generic meta-data page header. */
-
- u_int32_t max_bucket; /* 56-59: ID of Maximum bucket in use */
- u_int32_t high_mask; /* 60-63: Modulo mask into table */
- u_int32_t low_mask; /* 64-67: Modulo mask into table lower half */
- u_int32_t ffactor; /* 68-71: Fill factor */
- u_int32_t nelem; /* 72-75: Number of keys in hash table */
- u_int32_t h_charkey; /* 76-79: Value of hash(CHARKEY) */
-#define NCACHED30 32 /* number of spare points */
- /* 80-207: Spare pages for overflow */
- u_int32_t spares[NCACHED30];
-
- /*
- * Minimum page size is 256.
- */
-} HMETA30;
-
-/************************************************************************
- QUEUE METADATA PAGE LAYOUT
- ************************************************************************/
-/*
- * QAM Meta data page structure
- *
- */
-typedef struct _qmeta30 {
- DBMETA30 dbmeta; /* 00-55: Generic meta-data header. */
-
- u_int32_t start; /* 56-59: Start offset. */
- u_int32_t first_recno; /* 60-63: First not deleted record. */
- u_int32_t cur_recno; /* 64-67: Last recno allocated. */
- u_int32_t re_len; /* 68-71: Fixed-length record length. */
- u_int32_t re_pad; /* 72-75: Fixed-length record pad. */
- u_int32_t rec_page; /* 76-79: Records Per Page. */
-
- /*
- * Minimum page size is 128.
- */
-} QMETA30;
-
-/* Structures from Release 2.x */
-
-/************************************************************************
- BTREE METADATA PAGE LAYOUT
- ************************************************************************/
-
-/*
- * Btree metadata page layout:
- */
-typedef struct _btmeta2X {
- DB_LSN lsn; /* 00-07: LSN. */
- db_pgno_t pgno; /* 08-11: Current page number. */
- u_int32_t magic; /* 12-15: Magic number. */
- u_int32_t version; /* 16-19: Version. */
- u_int32_t pagesize; /* 20-23: Pagesize. */
- u_int32_t maxkey; /* 24-27: Btree: Maxkey. */
- u_int32_t minkey; /* 28-31: Btree: Minkey. */
- u_int32_t free; /* 32-35: Free list page number. */
- u_int32_t flags; /* 36-39: Flags. */
- u_int32_t re_len; /* 40-43: Recno: fixed-length record length. */
- u_int32_t re_pad; /* 44-47: Recno: fixed-length record pad. */
- /* 48-67: Unique file ID. */
- u_int8_t uid[DB_FILE_ID_LEN];
-} BTMETA2X;
-
-/************************************************************************
- HASH METADATA PAGE LAYOUT
- ************************************************************************/
-
-/*
- * Hash metadata page layout:
- */
-/* Hash Table Information */
-typedef struct hashhdr { /* Disk resident portion */
- DB_LSN lsn; /* 00-07: LSN of the header page */
- db_pgno_t pgno; /* 08-11: Page number (btree compatibility). */
- u_int32_t magic; /* 12-15: Magic NO for hash tables */
- u_int32_t version; /* 16-19: Version ID */
- u_int32_t pagesize; /* 20-23: Bucket/Page Size */
- u_int32_t ovfl_point; /* 24-27: Overflow page allocation location */
- u_int32_t last_freed; /* 28-31: Last freed overflow page pgno */
- u_int32_t max_bucket; /* 32-35: ID of Maximum bucket in use */
- u_int32_t high_mask; /* 36-39: Modulo mask into table */
- u_int32_t low_mask; /* 40-43: Modulo mask into table lower half */
- u_int32_t ffactor; /* 44-47: Fill factor */
- u_int32_t nelem; /* 48-51: Number of keys in hash table */
- u_int32_t h_charkey; /* 52-55: Value of hash(CHARKEY) */
- u_int32_t flags; /* 56-59: Allow duplicates. */
-#define NCACHED2X 32 /* number of spare points */
- /* 60-187: Spare pages for overflow */
- u_int32_t spares[NCACHED2X];
- /* 188-207: Unique file ID. */
- u_int8_t uid[DB_FILE_ID_LEN];
-
- /*
- * Minimum page size is 256.
- */
-} HASHHDR;
-
-#endif
diff --git a/bdb/include/db_verify.h b/bdb/include/db_verify.h
deleted file mode 100644
index 2507f1f1082..00000000000
--- a/bdb/include/db_verify.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: db_verify.h,v 1.18 2000/12/31 17:51:52 bostic Exp $
- */
-
-#ifndef _DB_VERIFY_H_
-#define _DB_VERIFY_H_
-
-/*
- * Structures and macros for the storage and retrieval of all information
- * needed for inter-page verification of a database.
- */
-
-/*
- * EPRINT is the macro for error printing. Takes as an arg the arg set
- * for DB->err.
- */
-#define EPRINT(x) \
- do { \
- if (!LF_ISSET(DB_SALVAGE)) \
- __db_err x; \
- } while (0)
-
-/* For fatal type errors--i.e., verifier bugs. */
-#define TYPE_ERR_PRINT(dbenv, func, pgno, ptype) \
- EPRINT(((dbenv), "%s called on nonsensical page %lu of type %lu", \
- (func), (u_long)(pgno), (u_long)(ptype)));
-
-/* Is x a power of two? (Tests true for zero, which doesn't matter here.) */
-#define POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
-
-#define IS_VALID_PAGESIZE(x) \
- (POWER_OF_TWO(x) && (x) >= DB_MIN_PGSIZE && ((x) <= DB_MAX_PGSIZE))
-
-/*
- * Note that 0 is, in general, a valid pgno, despite equalling PGNO_INVALID;
- * we have to test it separately where it's not appropriate.
- */
-#define IS_VALID_PGNO(x) ((x) <= vdp->last_pgno)
-
-/*
- * Flags understood by the btree structure checks (esp. __bam_vrfy_subtree).
- * These share the same space as the global flags to __db_verify, and must not
- * dip below 0x00010000.
- */
-#define ST_DUPOK 0x00010000 /* Duplicates are acceptable. */
-#define ST_DUPSET 0x00020000 /* Subtree is in a duplicate tree. */
-#define ST_DUPSORT 0x00040000 /* Duplicates are sorted. */
-#define ST_IS_RECNO 0x00080000 /* Subtree is a recno. */
-#define ST_OVFL_LEAF 0x00100000 /* Overflow reffed from leaf page. */
-#define ST_RECNUM 0x00200000 /* Subtree has record numbering on. */
-#define ST_RELEN 0x00400000 /* Subtree has fixed-length records. */
-#define ST_TOPLEVEL 0x00800000 /* Subtree == entire tree */
-
-/*
- * Flags understood by __bam_salvage and __db_salvage. These need not share
- * the same space with the __bam_vrfy_subtree flags, but must share with
- * __db_verify.
- */
-#define SA_SKIPFIRSTKEY 0x00080000
-
-/*
- * VRFY_DBINFO is the fundamental structure; it either represents the database
- * of subdatabases, or the sole database if there are no subdatabases.
- */
-struct __vrfy_dbinfo {
- /* Info about this database in particular. */
- DBTYPE type;
-
- /* List of subdatabase meta pages, if any. */
- LIST_HEAD(__subdbs, __vrfy_childinfo) subdbs;
-
- /* File-global info--stores VRFY_PAGEINFOs for each page. */
- DB *pgdbp;
-
- /* Child database--stores VRFY_CHILDINFOs of each page. */
- DB *cdbp;
-
- /* Page info structures currently in use. */
- LIST_HEAD(__activepips, __vrfy_pageinfo) activepips;
-
- /*
- * DB we use to keep track of which pages are linked somehow
- * during verification. 0 is the default, "unseen"; 1 is seen.
- */
- DB *pgset;
-
- /*
- * This is a database we use during salvaging to keep track of which
- * overflow and dup pages we need to come back to at the end and print
- * with key "UNKNOWN". Pages which print with a good key get set
- * to SALVAGE_IGNORE; others get set, as appropriate, to SALVAGE_LDUP,
- * SALVAGE_LRECNODUP, SALVAGE_OVERFLOW for normal db overflow pages,
- * and SALVAGE_BTREE, SALVAGE_LRECNO, and SALVAGE_HASH for subdb
- * pages.
- */
-#define SALVAGE_INVALID 0
-#define SALVAGE_IGNORE 1
-#define SALVAGE_LDUP 2
-#define SALVAGE_LRECNODUP 3
-#define SALVAGE_OVERFLOW 4
-#define SALVAGE_LBTREE 5
-#define SALVAGE_HASH 6
-#define SALVAGE_LRECNO 7
- DB *salvage_pages;
-
- db_pgno_t last_pgno;
- db_pgno_t pgs_remaining; /* For dbp->db_feedback(). */
-
- /* Queue needs these to verify data pages in the first pass. */
- u_int32_t re_len;
- u_int32_t rec_page;
-
-#define SALVAGE_PRINTHEADER 0x01
-#define SALVAGE_PRINTFOOTER 0x02
- u_int32_t flags;
-}; /* VRFY_DBINFO */
-
-/*
- * The amount of state information we need per-page is small enough that
- * it's not worth the trouble to define separate structures for each
- * possible type of page, and since we're doing verification with these we
- * have to be open to the possibility that page N will be of a completely
- * unexpected type anyway. So we define one structure here with all the
- * info we need for inter-page verification.
- */
-struct __vrfy_pageinfo {
- u_int8_t type;
- u_int8_t bt_level;
- u_int8_t unused1;
- u_int8_t unused2;
- db_pgno_t pgno;
- db_pgno_t prev_pgno;
- db_pgno_t next_pgno;
-
- /* meta pages */
- db_pgno_t root;
- db_pgno_t free; /* Free list head. */
-
- db_indx_t entries; /* Actual number of entries. */
- u_int16_t unused;
- db_recno_t rec_cnt; /* Record count. */
- u_int32_t re_len; /* Record length. */
- u_int32_t bt_minkey;
- u_int32_t bt_maxkey;
- u_int32_t h_ffactor;
- u_int32_t h_nelem;
-
- /* overflow pages */
- /*
- * Note that refcount is the refcount for an overflow page; pi_refcount
- * is this structure's own refcount!
- */
- u_int32_t refcount;
- u_int32_t olen;
-
-#define VRFY_DUPS_UNSORTED 0x0001 /* Have to flag the negative! */
-#define VRFY_HAS_DUPS 0x0002
-#define VRFY_HAS_DUPSORT 0x0004 /* Has the flag set. */
-#define VRFY_HAS_SUBDBS 0x0008
-#define VRFY_HAS_RECNUMS 0x0010
-#define VRFY_INCOMPLETE 0x0020 /* Meta or item order checks incomp. */
-#define VRFY_IS_ALLZEROES 0x0040 /* Hash page we haven't touched? */
-#define VRFY_IS_FIXEDLEN 0x0080
-#define VRFY_IS_RECNO 0x0100
-#define VRFY_IS_RRECNO 0x0200
-#define VRFY_OVFL_LEAFSEEN 0x0400
- u_int32_t flags;
-
- LIST_ENTRY(__vrfy_pageinfo) links;
- u_int32_t pi_refcount;
-}; /* VRFY_PAGEINFO */
-
-struct __vrfy_childinfo {
- db_pgno_t pgno;
-
-#define V_DUPLICATE 1 /* off-page dup metadata */
-#define V_OVERFLOW 2 /* overflow page */
-#define V_RECNO 3 /* btree internal or leaf page */
- u_int32_t type;
- db_recno_t nrecs; /* record count on a btree subtree */
- u_int32_t tlen; /* ovfl. item total size */
-
- LIST_ENTRY(__vrfy_childinfo) links;
-}; /* VRFY_CHILDINFO */
-
-#endif /* _DB_VERIFY_H_ */
diff --git a/bdb/include/debug.h b/bdb/include/debug.h
deleted file mode 100644
index 9a3ffc1acb6..00000000000
--- a/bdb/include/debug.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: debug.h,v 11.17 2000/07/07 15:50:36 bostic Exp $
- */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
- * When running with #DIAGNOSTIC defined, we smash memory and do memory
- * guarding with a special byte value.
- */
-#define CLEAR_BYTE 0xdb
-#define GUARD_BYTE 0xdc
-
-/*
- * DB assertions.
- */
-#if defined(DIAGNOSTIC) && defined(__STDC__)
-#define DB_ASSERT(e) ((e) ? (void)0 : __db_assert(#e, __FILE__, __LINE__))
-#else
-#define DB_ASSERT(e) ((void)0)
-#endif
-
-/*
- * Purify and other run-time tools complain about uninitialized reads/writes
- * of structure fields whose only purpose is padding, as well as when heap
- * memory that was never initialized is written to disk.
- */
-#ifdef UMRW
-#define UMRW_SET(v) (v) = 0
-#else
-#define UMRW_SET(v)
-#endif
-
-/*
- * Debugging macro to log operations.
- * If DEBUG_WOP is defined, log operations that modify the database.
- * If DEBUG_ROP is defined, log operations that read the database.
- *
- * D dbp
- * T txn
- * O operation (string)
- * K key
- * A data
- * F flags
- */
-#define LOG_OP(C, T, O, K, A, F) { \
- DB_LSN __lsn; \
- DBT __op; \
- if (DB_LOGGING((C))) { \
- memset(&__op, 0, sizeof(__op)); \
- __op.data = O; \
- __op.size = strlen(O) + 1; \
- (void)__db_debug_log((C)->dbp->dbenv, \
- T, &__lsn, 0, &__op, (C)->dbp->log_fileid, K, A, F);\
- } \
-}
-#ifdef DEBUG_ROP
-#define DEBUG_LREAD(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F)
-#else
-#define DEBUG_LREAD(C, T, O, K, A, F)
-#endif
-#ifdef DEBUG_WOP
-#define DEBUG_LWRITE(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F)
-#else
-#define DEBUG_LWRITE(C, T, O, K, A, F)
-#endif
-
-/*
- * Hook for testing recovery at various places in the create/delete paths.
- */
-#if CONFIG_TEST
-#define DB_TEST_RECOVERY(dbp, val, ret, name) \
-do { \
- int __ret; \
- PANIC_CHECK((dbp)->dbenv); \
- if ((dbp)->dbenv->test_copy == (val)) { \
- /* COPY the FILE */ \
- if (F_ISSET((dbp), DB_OPEN_CALLED) && (dbp)->mpf != NULL) \
- (void)(dbp)->sync((dbp), 0); \
- if ((__ret = __db_testcopy((dbp), (name))) != 0) \
- (ret) = __db_panic((dbp)->dbenv, __ret); \
- } \
- if ((dbp)->dbenv->test_abort == (val)) { \
- /* ABORT the TXN */ \
- (ret) = EINVAL; \
- goto db_tr_err; \
- } \
-} while (0)
-#define DB_TEST_RECOVERY_LABEL db_tr_err:
-#else
-#define DB_TEST_RECOVERY(dbp, val, ret, name)
-#define DB_TEST_RECOVERY_LABEL
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/bdb/include/hash.h b/bdb/include/hash.h
deleted file mode 100644
index 14a88c80b9c..00000000000
--- a/bdb/include/hash.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994
- * Margo Seltzer. All rights reserved.
- */
-/*
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: hash.h,v 11.19 2000/12/21 23:05:16 krinsky Exp $
- */
-
-/* Hash internal structure. */
-typedef struct hash_t {
- db_pgno_t meta_pgno; /* Page number of the meta data page. */
- u_int32_t h_ffactor; /* Fill factor. */
- u_int32_t h_nelem; /* Number of elements. */
- /* Hash function. */
- u_int32_t (*h_hash) __P((DB *, const void *, u_int32_t));
-} HASH;
-
-/* Cursor structure definitions. */
-typedef struct cursor_t {
- /* struct __dbc_internal */
- __DBC_INTERNAL
-
- /* Hash private part */
-
- /* Per-thread information */
- DB_LOCK hlock; /* Metadata page lock. */
- HMETA *hdr; /* Pointer to meta-data page. */
- PAGE *split_buf; /* Temporary buffer for splits. */
-
- /* Hash cursor information */
- db_pgno_t bucket; /* Bucket we are traversing. */
- db_pgno_t lbucket; /* Bucket for which we are locked. */
- db_indx_t dup_off; /* Offset within a duplicate set. */
- db_indx_t dup_len; /* Length of current duplicate. */
- db_indx_t dup_tlen; /* Total length of duplicate entry. */
- u_int32_t seek_size; /* Number of bytes we need for add. */
- db_pgno_t seek_found_page;/* Page on which we can insert. */
- u_int32_t order; /* Relative order among deleted curs. */
-
-#define H_CONTINUE 0x0001 /* Join--search strictly fwd for data */
-#define H_DELETED 0x0002 /* Cursor item is deleted. */
-#define H_DIRTY 0x0004 /* Meta-data page needs to be written */
-#define H_DUPONLY 0x0008 /* Dups only; do not change key. */
-#define H_EXPAND 0x0010 /* Table expanded. */
-#define H_ISDUP 0x0020 /* Cursor is within duplicate set. */
-#define H_NEXT_NODUP 0x0040 /* Get next non-dup entry. */
-#define H_NOMORE 0x0080 /* No more entries in bucket. */
-#define H_OK 0x0100 /* Request succeeded. */
- u_int32_t flags;
-} HASH_CURSOR;
-
-/* Test string. */
-#define CHARKEY "%$sniglet^&"
-
-/* Overflow management */
-/*
- * The spares table indicates the page number at which each doubling begins.
- * From this page number we subtract the number of buckets already allocated
- * so that we can do a simple addition to calculate the page number here.
- */
-#define BS_TO_PAGE(bucket, spares) \
- ((bucket) + (spares)[__db_log2((bucket) + 1)])
-#define BUCKET_TO_PAGE(I, B) (BS_TO_PAGE((B), (I)->hdr->spares))
-
-/* Constraints about much data goes on a page. */
-
-#define MINFILL 4
-#define ISBIG(I, N) (((N) > ((I)->hdr->dbmeta.pagesize / MINFILL)) ? 1 : 0)
-
-/* Shorthands for accessing structure */
-#define NDX_INVALID 0xFFFF
-#define BUCKET_INVALID 0xFFFFFFFF
-
-/* On page duplicates are stored as a string of size-data-size triples. */
-#define DUP_SIZE(len) ((len) + 2 * sizeof(db_indx_t))
-
-/* Log messages types (these are subtypes within a record type) */
-#define PAIR_KEYMASK 0x1
-#define PAIR_DATAMASK 0x2
-#define PAIR_DUPMASK 0x4
-#define PAIR_MASK 0xf
-#define PAIR_ISKEYBIG(N) (N & PAIR_KEYMASK)
-#define PAIR_ISDATABIG(N) (N & PAIR_DATAMASK)
-#define PAIR_ISDATADUP(N) (N & PAIR_DUPMASK)
-#define OPCODE_OF(N) (N & ~PAIR_MASK)
-
-#define PUTPAIR 0x20
-#define DELPAIR 0x30
-#define PUTOVFL 0x40
-#define DELOVFL 0x50
-#define HASH_UNUSED1 0x60
-#define HASH_UNUSED2 0x70
-#define SPLITOLD 0x80
-#define SPLITNEW 0x90
-
-typedef enum {
- DB_HAM_CHGPG = 1,
- DB_HAM_SPLIT = 2,
- DB_HAM_DUP = 3
-} db_ham_mode;
-
-#include "hash_auto.h"
-#include "hash_ext.h"
-#include "db_am.h"
diff --git a/bdb/include/lock.h b/bdb/include/lock.h
deleted file mode 100644
index e4a01ddf9c7..00000000000
--- a/bdb/include/lock.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: lock.h,v 11.20 2000/12/12 17:43:56 bostic Exp $
- */
-
-#define DB_LOCK_DEFAULT_N 1000 /* Default # of locks in region. */
-
-/*
- * Out of band value for a lock. Locks contain an offset into a lock region,
- * so we use an invalid region offset to indicate an invalid or unset lock.
- */
-#define LOCK_INVALID INVALID_ROFF
-
-/*
- * The locker id space is divided between the transaction manager and the lock
- * manager. Lock IDs start at 0 and go to DB_LOCK_MAXID. Txn IDs start at
- * DB_LOCK_MAXID + 1 and go up to TXN_INVALID.
- */
-#define DB_LOCK_MAXID 0x7fffffff
-
-/*
- * DB_LOCKREGION --
- * The lock shared region.
- */
-typedef struct __db_lockregion {
- u_int32_t id; /* unique id generator */
- u_int32_t need_dd; /* flag for deadlock detector */
- u_int32_t detect; /* run dd on every conflict */
- /* free lock header */
- SH_TAILQ_HEAD(__flock) free_locks;
- /* free obj header */
- SH_TAILQ_HEAD(__fobj) free_objs;
- /* free locker header */
- SH_TAILQ_HEAD(__flocker) free_lockers;
- SH_TAILQ_HEAD(__dobj) dd_objs; /* objects with waiters */
- u_int32_t maxlocks; /* maximum number of locks in table */
- u_int32_t maxlockers; /* maximum number of lockers in table */
- u_int32_t maxobjects; /* maximum number of objects in table */
- u_int32_t locker_t_size; /* size of locker hash table */
- u_int32_t object_t_size; /* size of object hash table */
- u_int32_t nmodes; /* number of lock modes */
- u_int32_t nlocks; /* current number of locks */
- u_int32_t maxnlocks; /* maximum number of locks so far*/
- u_int32_t nlockers; /* current number of lockers */
- u_int32_t maxnlockers; /* maximum number of lockers so far */
- u_int32_t nobjects; /* current number of objects */
- u_int32_t maxnobjects; /* maximum number of objects so far */
- roff_t conf_off; /* offset of conflicts array */
- roff_t obj_off; /* offset of object hash table */
- roff_t osynch_off; /* offset of the object mutex table */
- roff_t locker_off; /* offset of locker hash table */
- roff_t lsynch_off; /* offset of the locker mutex table */
- u_int32_t nconflicts; /* number of lock conflicts */
- u_int32_t nrequests; /* number of lock gets */
- u_int32_t nreleases; /* number of lock puts */
- u_int32_t nnowaits; /* number of lock requests that would
- have waited without nowait */
- u_int32_t ndeadlocks; /* number of deadlocks */
-#ifdef MUTEX_SYSTEM_RESOURCES
- roff_t maint_off; /* offset of region maintenance info */
-#endif
-} DB_LOCKREGION;
-
-/*
- * Since we will store DBTs in shared memory, we need the equivalent of a
- * DBT that will work in shared memory.
- */
-typedef struct __sh_dbt {
- u_int32_t size; /* Byte length. */
- ssize_t off; /* Region offset. */
-} SH_DBT;
-
-#define SH_DBT_PTR(p) ((void *)(((u_int8_t *)(p)) + (p)->off))
-
-/*
- * Object structures; these live in the object hash table.
- */
-typedef struct __db_lockobj {
- SH_DBT lockobj; /* Identifies object locked. */
- SH_TAILQ_ENTRY links; /* Links for free list or hash list. */
- SH_TAILQ_ENTRY dd_links; /* Links for dd list. */
- SH_TAILQ_HEAD(__wait) waiters; /* List of waiting locks. */
- SH_TAILQ_HEAD(__hold) holders; /* List of held locks. */
- /* Declare room in the object to hold
- * typical DB lock structures so that
- * we do not have to allocate them from
- * shalloc at run-time. */
- u_int8_t objdata[sizeof(struct __db_ilock)];
-} DB_LOCKOBJ;
-
-/*
- * Locker structures; these live in the locker hash table.
- */
-typedef struct __db_locker {
- u_int32_t id; /* Locker id. */
- u_int32_t dd_id; /* Deadlock detector id. */
- size_t master_locker; /* Locker of master transaction. */
- size_t parent_locker; /* Parent of this child. */
- SH_LIST_HEAD(_child) child_locker; /* List of descendant txns;
- only used in a "master"
- txn. */
- SH_LIST_ENTRY child_link; /* Links transactions in the family;
- elements of the child_locker
- list. */
- SH_TAILQ_ENTRY links; /* Links for free list. */
- SH_LIST_HEAD(_held) heldby; /* Locks held by this locker. */
-
-#define DB_LOCKER_DELETED 0x0001
- u_int32_t flags;
-} DB_LOCKER;
-
-/*
- * Lockers can be freed if they are not part of a transaction family.
- * Members of a family either point at the master transaction or are
- * the master transaction and have children lockers.
- */
-#define LOCKER_FREEABLE(lp) \
- ((lp)->master_locker == TXN_INVALID_ID && \
- SH_LIST_FIRST(&(lp)->child_locker, __db_locker) == NULL)
-
-/*
- * DB_LOCKTAB --
- * The primary library lock data structure (i.e., the one referenced
- * by the environment, as opposed to the internal one laid out in the region.)
- */
-typedef struct __db_locktab {
- DB_ENV *dbenv; /* Environment. */
- REGINFO reginfo; /* Region information. */
- u_int8_t *conflicts; /* Pointer to conflict matrix. */
- DB_HASHTAB *obj_tab; /* Beginning of object hash table. */
- DB_HASHTAB *locker_tab; /* Beginning of locker hash table. */
-} DB_LOCKTAB;
-
-/* Test for conflicts. */
-#define CONFLICTS(T, R, HELD, WANTED) \
- (T)->conflicts[(HELD) * (R)->nmodes + (WANTED)]
-
-#define OBJ_LINKS_VALID(L) ((L)->links.stqe_prev != -1)
-
-struct __db_lock {
- /*
- * Wait on mutex to wait on lock. You reference your own mutex with
- * ID 0 and others reference your mutex with ID 1.
- */
- MUTEX mutex;
-
- u_int32_t holder; /* Who holds this lock. */
- u_int32_t gen; /* Generation count. */
- SH_TAILQ_ENTRY links; /* Free or holder/waiter list. */
- SH_LIST_ENTRY locker_links; /* List of locks held by a locker. */
- u_int32_t refcount; /* Reference count the lock. */
- db_lockmode_t mode; /* What sort of lock. */
- ssize_t obj; /* Relative offset of object struct. */
- db_status_t status; /* Status of this lock. */
-};
-
-/*
- * Flag values for __lock_put_internal:
- * DB_LOCK_DOALL: Unlock all references in this lock (instead of only 1).
- * DB_LOCK_FREE: Free the lock (used in checklocker).
- * DB_LOCK_IGNOREDEL: Remove from the locker hash table even if already
- deleted (used in checklocker).
- * DB_LOCK_NOPROMOTE: Don't bother running promotion when releasing locks
- * (used by __lock_put_internal).
- * DB_LOCK_UNLINK: Remove from the locker links (used in checklocker).
- */
-#define DB_LOCK_DOALL 0x001
-#define DB_LOCK_FREE 0x002
-#define DB_LOCK_IGNOREDEL 0x004
-#define DB_LOCK_NOPROMOTE 0x008
-#define DB_LOCK_UNLINK 0x010
-#define DB_LOCK_NOWAITERS 0x020
-
-/*
- * Macros to get/release different types of mutexes.
- */
-#define OBJECT_LOCK(lt, reg, obj, ndx) \
- ndx = __lock_ohash(obj) % (reg)->object_t_size
-#define SHOBJECT_LOCK(lt, reg, shobj, ndx) \
- ndx = __lock_lhash(shobj) % (reg)->object_t_size
-#define LOCKER_LOCK(lt, reg, locker, ndx) \
- ndx = __lock_locker_hash(locker) % (reg)->locker_t_size;
-
-#define LOCKREGION(dbenv, lt) R_LOCK((dbenv), &(lt)->reginfo)
-#define UNLOCKREGION(dbenv, lt) R_UNLOCK((dbenv), &(lt)->reginfo)
-#include "lock_ext.h"
diff --git a/bdb/include/log.h b/bdb/include/log.h
deleted file mode 100644
index 81ecb4174a6..00000000000
--- a/bdb/include/log.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: log.h,v 11.19 2001/01/11 18:19:52 bostic Exp $
- */
-
-#ifndef _LOG_H_
-#define _LOG_H_
-
-struct __db_log; typedef struct __db_log DB_LOG;
-struct __fname; typedef struct __fname FNAME;
-struct __hdr; typedef struct __hdr HDR;
-struct __log; typedef struct __log LOG;
-struct __log_persist; typedef struct __log_persist LOGP;
-
-#define LFPREFIX "log." /* Log file name prefix. */
-#define LFNAME "log.%010d" /* Log file name template. */
-#define LFNAME_V1 "log.%05d" /* Log file name template, rev 1. */
-
-#define LG_MAX_DEFAULT (10 * MEGABYTE) /* 10 MB. */
-#define LG_BSIZE_DEFAULT (32 * 1024) /* 32 KB. */
-#define LG_BASE_REGION_SIZE (480 * 1024) /* 480 KB. */
-
-/*
- * The per-process table that maps log file-id's to DB structures.
- */
-typedef struct __db_entry {
- TAILQ_HEAD(dblist, __db) dblist; /* Associated DB structures. */
- u_int32_t refcount; /* Reference counted. */
- u_int32_t count; /* Number of ops on a deleted db. */
- int deleted; /* File was not found during open. */
-} DB_ENTRY;
-
-/*
- * DB_LOG
- * Per-process log structure.
- */
-struct __db_log {
-/*
- * These fields need to be protected for multi-threaded support.
- *
- * !!!
- * As this structure is allocated in per-process memory, the mutex may need
- * to be stored elsewhere on architectures unable to support mutexes in heap
- * memory, e.g., HP/UX 9.
- */
- MUTEX *mutexp; /* Mutex for thread protection. */
-
- DB_ENTRY *dbentry; /* Recovery file-id mapping. */
-#define DB_GROW_SIZE 64
- int32_t dbentry_cnt; /* Entries. Grows by DB_GROW_SIZE. */
-
-/*
- * These fields are always accessed while the region lock is held, so they do
- * not have to be protected by the thread lock as well, OR, they are only used
- * when threads are not being used, i.e. most cursor operations are disallowed
- * on threaded logs.
- */
- u_int32_t lfname; /* Log file "name". */
- DB_FH lfh; /* Log file handle. */
-
- DB_LSN c_lsn; /* Cursor: current LSN. */
- DBT c_dbt; /* Cursor: return DBT structure. */
- DB_FH c_fh; /* Cursor: file handle. */
- FILE *c_fp; /* Cursor: file pointer. */
- u_int32_t c_off; /* Cursor: previous record offset. */
- u_int32_t c_len; /* Cursor: current record length. */
- u_int32_t r_file; /* Cursor: current read file */
- u_int32_t r_off; /* Cursor: offset of read buffer. */
- u_int32_t r_size; /* Cursor: size of data in read buf. */
-
- u_int8_t *bufp; /* Region buffer. */
- u_int8_t *readbufp; /* Read buffer. */
-
-/* These fields are not protected. */
- DB_ENV *dbenv; /* Reference to error information. */
- REGINFO reginfo; /* Region information. */
-
-/*
- * These fields are used by XA; since XA forbids threaded execution, these
- * do not have to be protected.
- */
- void *xa_info; /* Committed transaction list that
- * has to be carried between calls
- * to xa_recover. */
- DB_LSN xa_lsn; /* Position of an XA recovery scan. */
- DB_LSN xa_first; /* LSN to which we need to roll back
- for this XA recovery scan. */
-
-#define DBLOG_RECOVER 0x01 /* We are in recovery. */
-#define DBLOG_FORCE_OPEN 0x02 /* Force the db open even
- * if it appears to be deleted.
- */
- u_int32_t flags;
-};
-
-/*
- * HDR --
- * Log record header.
- */
-struct __hdr {
- u_int32_t prev; /* Previous offset. */
- u_int32_t cksum; /* Current checksum. */
- u_int32_t len; /* Current length. */
-};
-
-struct __log_persist {
- u_int32_t magic; /* DB_LOGMAGIC */
- u_int32_t version; /* DB_LOGVERSION */
-
- u_int32_t lg_max; /* Maximum file size. */
- int mode; /* Log file mode. */
-};
-
-/*
- * LOG --
- * Shared log region. One of these is allocated in shared memory,
- * and describes the log.
- */
-struct __log {
- LOGP persist; /* Persistent information. */
-
- SH_TAILQ_HEAD(__fq) fq; /* List of file names. */
-
- /*
- * The lsn LSN is the file offset that we're about to write and which
- * we will return to the user.
- */
- DB_LSN lsn; /* LSN at current file offset. */
-
- /*
- * The s_lsn LSN is the last LSN that we know is on disk, not just
- * written, but synced.
- */
- DB_LSN s_lsn; /* LSN of the last sync. */
-
- u_int32_t len; /* Length of the last record. */
-
- u_int32_t w_off; /* Current write offset in the file. */
-
- DB_LSN chkpt_lsn; /* LSN of the last checkpoint. */
- time_t chkpt; /* Time of the last checkpoint. */
-
- DB_LOG_STAT stat; /* Log statistics. */
-
- /*
- * The f_lsn LSN is the LSN (returned to the user) that "owns" the
- * first byte of the buffer. If the record associated with the LSN
- * spans buffers, it may not reflect the physical file location of
- * the first byte of the buffer.
- */
- DB_LSN f_lsn; /* LSN of first byte in the buffer. */
- size_t b_off; /* Current offset in the buffer. */
-
- roff_t buffer_off; /* Log buffer offset. */
- u_int32_t buffer_size; /* Log buffer size. */
-};
-
-/*
- * FNAME --
- * File name and id.
- */
-struct __fname {
- SH_TAILQ_ENTRY q; /* File name queue. */
-
- u_int16_t ref; /* Reference count. */
- u_int16_t locked; /* Table is locked. */
-
- int32_t id; /* Logging file id. */
- DBTYPE s_type; /* Saved DB type. */
-
- roff_t name_off; /* Name offset. */
- db_pgno_t meta_pgno; /* Page number of the meta page. */
- u_int8_t ufid[DB_FILE_ID_LEN]; /* Unique file id. */
-};
-
-/* File open/close register log record opcodes. */
-#define LOG_CHECKPOINT 1 /* Checkpoint: file name/id dump. */
-#define LOG_CLOSE 2 /* File close. */
-#define LOG_OPEN 3 /* File open. */
-
-#define CHECK_LSN(redo, cmp, lsn, prev) \
- DB_ASSERT(!DB_REDO(redo) || (cmp) >= 0); \
- if (DB_REDO(redo) && (cmp) < 0) { \
- __db_err(dbenv, \
- "Log sequence error: page LSN %lu:%lu; previous LSN %lu %lu", \
- (u_long)(lsn)->file, (u_long)(lsn)->offset, \
- (u_long)(prev)->file, (u_long)(prev)->offset); \
- goto out; \
- }
-
-/*
- * Status codes indicating the validity of a log file examined by
- * __log_valid().
- */
-typedef enum {
- DB_LV_INCOMPLETE,
- DB_LV_NONEXISTENT,
- DB_LV_NORMAL,
- DB_LV_OLD_READABLE,
- DB_LV_OLD_UNREADABLE
-} logfile_validity;
-
-#include "log_auto.h"
-#include "log_ext.h"
-#endif /* _LOG_H_ */
diff --git a/bdb/include/mp.h b/bdb/include/mp.h
deleted file mode 100644
index 233cb1c2b10..00000000000
--- a/bdb/include/mp.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: mp.h,v 11.16 2001/01/10 04:50:53 ubell Exp $
- */
-
-struct __bh; typedef struct __bh BH;
-struct __db_mpool; typedef struct __db_mpool DB_MPOOL;
-struct __db_mpreg; typedef struct __db_mpreg DB_MPREG;
-struct __mpool; typedef struct __mpool MPOOL;
-struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
-
-/* We require at least 40K of cache. */
-#define DB_CACHESIZE_MIN (20 * 1024)
-
-/*
- * DB_MPOOL --
- * Per-process memory pool structure.
- */
-struct __db_mpool {
- /* These fields need to be protected for multi-threaded support. */
- MUTEX *mutexp; /* Structure thread lock. */
-
- /* List of pgin/pgout routines. */
- LIST_HEAD(__db_mpregh, __db_mpreg) dbregq;
-
- /* List of DB_MPOOLFILE's. */
- TAILQ_HEAD(__db_mpoolfileh, __db_mpoolfile) dbmfq;
-
- /* These fields are not thread-protected. */
- DB_ENV *dbenv; /* Reference to error information. */
-
- u_int32_t nreg; /* N underlying cache regions. */
- REGINFO *reginfo; /* Underlying cache regions. */
-};
-
-/*
- * DB_MPREG --
- * DB_MPOOL registry of pgin/pgout functions.
- */
-struct __db_mpreg {
- LIST_ENTRY(__db_mpreg) q; /* Linked list. */
-
- int ftype; /* File type. */
- /* Pgin, pgout routines. */
- int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *));
- int (*pgout) __P((DB_ENV *, db_pgno_t, void *, DBT *));
-};
-
-/*
- * DB_MPOOLFILE --
- * Per-process DB_MPOOLFILE information.
- */
-struct __db_mpoolfile {
- /* These fields need to be protected for multi-threaded support. */
- MUTEX *mutexp; /* Structure thread lock. */
-
- DB_FH fh; /* Underlying file handle. */
-
- u_int32_t ref; /* Reference count. */
-
- /*
- * !!!
- * This field is a special case -- it's protected by the region lock
- * NOT the thread lock. The reason for this is that we always have
- * the region lock immediately before or after we modify the field,
- * and we don't want to use the structure lock to protect it because
- * then I/O (which is done with the structure lock held because of
- * the race between the seek and write of the file descriptor) will
- * block any other put/get calls using this DB_MPOOLFILE structure.
- */
- u_int32_t pinref; /* Pinned block reference count. */
-
- /*
- * !!!
- * This field is a special case -- it's protected by the region lock
- * since it's manipulated only when new files are added to the list.
- */
- TAILQ_ENTRY(__db_mpoolfile) q; /* Linked list of DB_MPOOLFILE's. */
-
- /* These fields are not thread-protected. */
- DB_MPOOL *dbmp; /* Overlying DB_MPOOL. */
- MPOOLFILE *mfp; /* Underlying MPOOLFILE. */
-
- void *addr; /* Address of mmap'd region. */
- size_t len; /* Length of mmap'd region. */
-
- /* These fields need to be protected for multi-threaded support. */
-#define MP_READONLY 0x01 /* File is readonly. */
-#define MP_UPGRADE 0x02 /* File descriptor is readwrite. */
-#define MP_UPGRADE_FAIL 0x04 /* Upgrade wasn't possible. */
- u_int32_t flags;
-};
-
-/*
- * NCACHE --
- * Select a cache based on the page number. This assumes accesses are
- * uniform across pages, which is probably OK -- what we really want to
- * avoid is anything that puts all the pages for any single file in the
- * same cache, as we expect that file access will be bursty.
- */
-#define NCACHE(mp, pgno) \
- ((pgno) % ((MPOOL *)mp)->nreg)
-
-/*
- * NBUCKET --
- * We make the assumption that early pages of the file are more likely
- * to be retrieved than the later pages, which means the top bits will
- * be more interesting for hashing as they're less likely to collide.
- * That said, as 512 8K pages represents a 4MB file, so only reasonably
- * large files will have page numbers with any other than the bottom 9
- * bits set. We XOR in the MPOOL offset of the MPOOLFILE that backs the
- * page, since that should also be unique for the page. We don't want
- * to do anything very fancy -- speed is more important to us than using
- * good hashing.
- */
-#define NBUCKET(mc, mf_offset, pgno) \
- (((pgno) ^ ((mf_offset) << 9)) % (mc)->htab_buckets)
-
-/*
- * MPOOL --
- * Shared memory pool region.
- */
-struct __mpool {
- /*
- * The memory pool can be broken up into individual pieces/files.
- * Not what we would have liked, but on Solaris you can allocate
- * only a little more than 2GB of memory in a contiguous chunk,
- * and I expect to see more systems with similar issues.
- *
- * The first of these pieces/files describes the entire pool, all
- * subsequent ones only describe a part of the cache.
- *
- * We single-thread memp_sync and memp_fsync calls.
- *
- * This mutex is intended *only* to single-thread access to the call,
- * it is not used to protect the lsn and lsn_cnt fields, the region
- * lock is used to protect them.
- */
- MUTEX sync_mutex; /* Checkpoint lock. */
- DB_LSN lsn; /* Maximum checkpoint LSN. */
- u_int32_t lsn_cnt; /* Checkpoint buffers left to write. */
-
- SH_TAILQ_HEAD(__mpfq) mpfq; /* List of MPOOLFILEs. */
-
- u_int32_t nreg; /* Number of underlying REGIONS. */
- roff_t regids; /* Array of underlying REGION Ids. */
-
-#define MP_LSN_RETRY 0x01 /* Retry all BH_WRITE buffers. */
- u_int32_t flags;
-
- /*
- * The following structure fields only describe the cache portion of
- * the region.
- */
- SH_TAILQ_HEAD(__bhq) bhq; /* LRU list of buffer headers. */
-
- int htab_buckets; /* Number of hash table entries. */
- roff_t htab; /* Hash table offset. */
-
- DB_MPOOL_STAT stat; /* Per-cache mpool statistics. */
-#ifdef MUTEX_SYSTEM_RESOURCES
- roff_t maint_off; /* Maintenance information offset */
-#endif
-};
-
-/*
- * MPOOLFILE --
- * Shared DB_MPOOLFILE information.
- */
-struct __mpoolfile {
- SH_TAILQ_ENTRY q; /* List of MPOOLFILEs */
-
- db_pgno_t mpf_cnt; /* Ref count: DB_MPOOLFILEs. */
- db_pgno_t block_cnt; /* Ref count: blocks in cache. */
- db_pgno_t lsn_cnt; /* Checkpoint buffers left to write. */
-
- int ftype; /* File type. */
- int32_t lsn_off; /* Page's LSN offset. */
- u_int32_t clear_len; /* Bytes to clear on page create. */
-
- roff_t path_off; /* File name location. */
- roff_t fileid_off; /* File identification location. */
-
- roff_t pgcookie_len; /* Pgin/pgout cookie length. */
- roff_t pgcookie_off; /* Pgin/pgout cookie location. */
-
- db_pgno_t last_pgno; /* Last page in the file. */
- db_pgno_t orig_last_pgno; /* Original last page in the file. */
-
- DB_MPOOL_FSTAT stat; /* Per-file mpool statistics. */
-
-#define MP_CAN_MMAP 0x01 /* If the file can be mmap'd. */
-#define MP_DEADFILE 0x02 /* Dirty pages can simply be trashed. */
-#define MP_TEMP 0x04 /* Backing file is a temporary. */
-#define MP_UNLINK 0x08 /* Unlink file on last close. */
- u_int32_t flags;
-};
-
-/*
- * BH_TO_CACHE --
- * Return the cache where we can find the specified buffer header.
- */
-#define BH_TO_CACHE(dbmp, bhp) \
- (dbmp)->reginfo[NCACHE((dbmp)->reginfo[0].primary, (bhp)->pgno)].primary
-
-/*
- * BH --
- * Buffer header.
- */
-struct __bh {
- MUTEX mutex; /* Buffer thread/process lock. */
-
- u_int16_t ref; /* Reference count. */
-
-#define BH_CALLPGIN 0x001 /* Page needs to be reworked... */
-#define BH_DIRTY 0x002 /* Page was modified. */
-#define BH_DISCARD 0x004 /* Page is useless. */
-#define BH_LOCKED 0x008 /* Page is locked (I/O in progress). */
-#define BH_SYNC 0x010 /* memp sync: write the page */
-#define BH_SYNC_LOGFLSH 0x020 /* memp sync: also flush the log */
-#define BH_TRASH 0x040 /* Page is garbage. */
- u_int16_t flags;
-
- SH_TAILQ_ENTRY q; /* LRU queue. */
- SH_TAILQ_ENTRY hq; /* MPOOL hash bucket queue. */
-
- db_pgno_t pgno; /* Underlying MPOOLFILE page number. */
- roff_t mf_offset; /* Associated MPOOLFILE offset. */
-
- /*
- * !!!
- * This array must be at least size_t aligned -- the DB access methods
- * put PAGE and other structures into it, and then access them directly.
- * (We guarantee size_t alignment to applications in the documentation,
- * too.)
- */
- u_int8_t buf[1]; /* Variable length data. */
-};
-
-#include "mp_ext.h"
diff --git a/bdb/include/mutex.h b/bdb/include/mutex.h
deleted file mode 100644
index 9f341695cbf..00000000000
--- a/bdb/include/mutex.h
+++ /dev/null
@@ -1,766 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: mutex.h,v 11.41 2000/12/22 19:28:15 bostic Exp $
- */
-
-/*
- * Some of the Berkeley DB ports require single-threading at various
- * places in the code. In those cases, these #defines will be set.
- */
-#define DB_BEGIN_SINGLE_THREAD
-#define DB_END_SINGLE_THREAD
-
-/*
- * When the underlying system mutexes require system resources, we have
- * to clean up after application failure. This violates the rule that
- * we never look at a shared region after a failure, but there's no other
- * choice. In those cases, this #define is set.
- */
-#ifdef HAVE_QNX
-#define MUTEX_SYSTEM_RESOURCES
-#endif
-
-/*********************************************************************
- * POSIX.1 pthreads interface.
- *********************************************************************/
-#ifdef HAVE_MUTEX_PTHREADS
-#include <pthread.h>
-
-#define MUTEX_FIELDS \
- pthread_mutex_t mutex; /* Mutex. */ \
- pthread_cond_t cond; /* Condition variable. */
-#endif
-
-/*********************************************************************
- * Solaris lwp threads interface.
- *
- * !!!
- * We use LWP mutexes on Solaris instead of UI or POSIX mutexes (both of
- * which are available), for two reasons. First, the Solaris C library
- * includes versions of the both UI and POSIX thread mutex interfaces, but
- * they are broken in that they don't support inter-process locking, and
- * there's no way to detect it, e.g., calls to configure the mutexes for
- * inter-process locking succeed without error. So, we use LWP mutexes so
- * that we don't fail in fairly undetectable ways because the application
- * wasn't linked with the appropriate threads library. Second, there were
- * bugs in SunOS 5.7 (Solaris 7) where if an application loaded the C library
- * before loading the libthread/libpthread threads libraries (e.g., by using
- * dlopen to load the DB library), the pwrite64 interface would be translated
- * into a call to pwrite and DB would drop core.
- *********************************************************************/
-#ifdef HAVE_MUTEX_SOLARIS_LWP
-/*
- * XXX
- * Don't change <synch.h> to <sys/lwp.h> -- although lwp.h is listed in the
- * Solaris manual page as the correct include to use, it causes the Solaris
- * compiler on SunOS 2.6 to fail.
- */
-#include <synch.h>
-
-#define MUTEX_FIELDS \
- lwp_mutex_t mutex; /* Mutex. */ \
- lwp_cond_t cond; /* Condition variable. */
-#endif
-
-/*********************************************************************
- * Solaris/Unixware threads interface.
- *********************************************************************/
-#ifdef HAVE_MUTEX_UI_THREADS
-#include <thread.h>
-#include <synch.h>
-
-#define MUTEX_FIELDS \
- mutex_t mutex; /* Mutex. */ \
- cond_t cond; /* Condition variable. */
-#endif
-
-/*********************************************************************
- * AIX C library functions.
- *********************************************************************/
-#ifdef HAVE_MUTEX_AIX_CHECK_LOCK
-#include <sys/atomic_op.h>
-typedef int tsl_t;
-#define MUTEX_ALIGN sizeof(int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) 0
-#define MUTEX_SET(x) (!_check_lock(x, 0, 1))
-#define MUTEX_UNSET(x) _clear_lock(x, 0)
-#endif
-#endif
-
-/*********************************************************************
- * General C library functions (msemaphore).
- *
- * !!!
- * Check for HPPA as a special case, because it requires unusual alignment,
- * and doesn't support semaphores in malloc(3) or shmget(2) memory.
- *
- * !!!
- * Do not remove the MSEM_IF_NOWAIT flag. The problem is that if a single
- * process makes two msem_lock() calls in a row, the second one returns an
- * error. We depend on the fact that we can lock against ourselves in the
- * locking subsystem, where we set up a mutex so that we can block ourselves.
- * Tested on OSF1 v4.0.
- *********************************************************************/
-#ifdef HAVE_MUTEX_HPPA_MSEM_INIT
-#define MUTEX_NO_MALLOC_LOCKS
-#define MUTEX_NO_SHMGET_LOCKS
-
-#define MUTEX_ALIGN 16
-#endif
-
-#if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
-#include <sys/mman.h>
-typedef msemaphore tsl_t;
-
-#ifndef MUTEX_ALIGN
-#define MUTEX_ALIGN sizeof(int)
-#endif
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) (msem_init(x, MSEM_UNLOCKED) <= (msemaphore *)0)
-#define MUTEX_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT))
-#define MUTEX_UNSET(x) msem_unlock(x, 0)
-#endif
-#endif
-
-/*********************************************************************
- * Plan 9 library functions.
- *********************************************************************/
-#ifdef HAVE_MUTEX_PLAN9
-typedef Lock tsl_t;
-
-#define MUTEX_ALIGN sizeof(int)
-
-#define MUTEX_INIT(x) (memset(x, 0, sizeof(Lock)), 0)
-#define MUTEX_SET(x) canlock(x)
-#define MUTEX_UNSET(x) unlock(x)
-#endif
-
-/*********************************************************************
- * Reliant UNIX C library functions.
- *********************************************************************/
-#ifdef HAVE_MUTEX_RELIANTUNIX_INITSPIN
-#include <ulocks.h>
-typedef spinlock_t tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) (initspin(x, 1), 0)
-#define MUTEX_SET(x) (cspinlock(x) == 0)
-#define MUTEX_UNSET(x) spinunlock(x)
-#endif
-#endif
-
-/*********************************************************************
- * General C library functions (POSIX 1003.1 sema_XXX).
- *
- * !!!
- * Never selected by autoconfig in this release (semaphore calls are known
- * to not work in Solaris 5.5).
- *********************************************************************/
-#ifdef HAVE_MUTEX_SEMA_INIT
-#include <synch.h>
-typedef sema_t tsl_t;
-#define MUTEX_ALIGN sizeof(int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_DESTROY(x) sema_destroy(x)
-#define MUTEX_INIT(x) (sema_init(x, 1, USYNC_PROCESS, NULL) != 0)
-#define MUTEX_SET(x) (sema_wait(x) == 0)
-#define MUTEX_UNSET(x) sema_post(x)
-#endif
-#endif
-
-/*********************************************************************
- * SGI C library functions.
- *********************************************************************/
-#ifdef HAVE_MUTEX_SGI_INIT_LOCK
-#include <abi_mutex.h>
-typedef abilock_t tsl_t;
-#define MUTEX_ALIGN sizeof(int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) (init_lock(x) != 0)
-#define MUTEX_SET(x) (!acquire_lock(x))
-#define MUTEX_UNSET(x) release_lock(x)
-#endif
-#endif
-
-/*********************************************************************
- * Solaris C library functions.
- *
- * !!!
- * These are undocumented functions, but they're the only ones that work
- * correctly as far as we know.
- *********************************************************************/
-#ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY
-#include <sys/machlock.h>
-typedef lock_t tsl_t;
-#define MUTEX_ALIGN sizeof(int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) 0
-#define MUTEX_SET(x) _lock_try(x)
-#define MUTEX_UNSET(x) _lock_clear(x)
-#endif
-#endif
-
-/*********************************************************************
- * VMS.
- *********************************************************************/
-#ifdef HAVE_MUTEX_VMS
-#include <sys/mman.h>;
-#include <builtins.h>
-typedef unsigned char tsl_t;
-#define MUTEX_ALIGN sizeof(unsigned int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#ifdef __ALPHA
-#define MUTEX_SET(tsl) (!__TESTBITSSI(tsl, 0))
-#else /* __VAX */
-#define MUTEX_SET(tsl) (!(int)_BBSSI(0, tsl))
-#endif
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * VxWorks
- * Use basic binary semaphores in VxWorks, as we currently do not need
- * any special features. We do need the ability to single-thread the
- * entire system, however, because VxWorks doesn't support the open(2)
- * flag O_EXCL, the mechanism we normally use to single thread access
- * when we're first looking for a DB environment.
- *********************************************************************/
-#ifdef HAVE_MUTEX_VXWORKS
-#define MUTEX_SYSTEM_RESOURCES
-
-#include "semLib.h"
-typedef SEM_ID tsl_t;
-#define MUTEX_ALIGN sizeof(unsigned int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_SET(tsl) (semTake((*tsl), WAIT_FOREVER) == OK)
-#define MUTEX_UNSET(tsl) (semGive((*tsl)) == OK)
-#define MUTEX_INIT(tsl) \
- ((*(tsl) = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL)
-#define MUTEX_DESTROY(tsl) semDelete(*tsl)
-#endif
-
-/*
- * Use the taskLock() mutex to eliminate a race where two tasks are
- * trying to initialize the global lock at the same time.
- */
-#undef DB_BEGIN_SINGLE_THREAD
-#define DB_BEGIN_SINGLE_THREAD \
-do { \
- if (DB_GLOBAL(db_global_init)) \
- (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \
- else { \
- taskLock(); \
- if (DB_GLOBAL(db_global_init)) { \
- taskUnlock(); \
- (void)semTake(DB_GLOBAL(db_global_lock), \
- WAIT_FOREVER); \
- continue; \
- } \
- DB_GLOBAL(db_global_lock) = \
- semBCreate(SEM_Q_FIFO, SEM_EMPTY); \
- if (DB_GLOBAL(db_global_lock) != NULL) \
- DB_GLOBAL(db_global_init) = 1; \
- taskUnlock(); \
- } \
-} while (DB_GLOBAL(db_global_init) == 0)
-#undef DB_END_SINGLE_THREAD
-#define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock))
-#endif
-
-/*********************************************************************
- * Win16
- *
- * Win16 spinlocks are simple because we cannot possibly be preempted.
- *
- * !!!
- * We should simplify this by always returning a no-need-to-lock lock
- * when we initialize the mutex.
- *********************************************************************/
-#ifdef HAVE_MUTEX_WIN16
-typedef unsigned int tsl_t;
-#define MUTEX_ALIGN sizeof(unsigned int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) 0
-#define MUTEX_SET(tsl) (*(tsl) = 1)
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#endif
-#endif
-
-/*********************************************************************
- * Win32
- *********************************************************************/
-#ifdef HAVE_MUTEX_WIN32
-typedef unsigned int tsl_t;
-#define MUTEX_ALIGN sizeof(unsigned int)
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) 0
-#define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1))
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#endif
-#endif
-
-/*********************************************************************
- * 68K/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_68K_GCC_ASSEMBLY
-typedef unsigned char tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/68K, 0 is clear, 1 is set.
- */
-#define MUTEX_SET(tsl) ({ \
- register tsl_t *__l = (tsl); \
- unsigned char __r; \
- asm volatile("tas %1; \n \
- seq %0" \
- : "=dm" (__r), "=m" (*__l) \
- : "1" (*__l) \
- ); \
- __r & 1; \
-})
-
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * ALPHA/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
-typedef u_int32_t tsl_t;
-#define MUTEX_ALIGN 4
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/alpha. Should return 0 if could not acquire the lock, 1 if
- * lock was acquired properly.
- */
-#ifdef __GNUC__
-static inline int
-MUTEX_SET(tsl_t *tsl) {
- register tsl_t *__l = tsl;
- register tsl_t __r;
- asm volatile(
- "1: ldl_l %0,%2\n"
- " blbs %0,2f\n"
- " or $31,1,%0\n"
- " stl_c %0,%1\n"
- " beq %0,3f\n"
- " mb\n"
- " br 3f\n"
- "2: xor %0,%0\n"
- "3:"
- : "=&r"(__r), "=m"(*__l) : "1"(*__l) : "memory");
- return __r;
-}
-
-/*
- * Unset mutex. Judging by Alpha Architecture Handbook, the mb instruction
- * might be necessary before unlocking
- */
-static inline int
-MUTEX_UNSET(tsl_t *tsl) {
- asm volatile(" mb\n");
- return *tsl = 0;
-}
-#endif
-
-#ifdef __DECC
-#include <alpha/builtins.h>
-#define MUTEX_SET(tsl) (__LOCK_LONG_RETRY((tsl), 1) != 0)
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#endif
-
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * HPPA/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
-typedef u_int32_t tsl_t;
-#define MUTEX_ALIGN 16
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * The PA-RISC has a "load and clear" instead of a "test and set" instruction.
- * The 32-bit word used by that instruction must be 16-byte aligned. We could
- * use the "aligned" attribute in GCC but that doesn't work for stack variables.
- */
-#define MUTEX_SET(tsl) ({ \
- register tsl_t *__l = (tsl); \
- int __r; \
- asm volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l)); \
- __r & 1; \
-})
-
-#define MUTEX_UNSET(tsl) (*(tsl) = -1)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * IA64/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY
-typedef unsigned char tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/ia64, 0 is clear, 1 is set.
- */
-#define MUTEX_SET(tsl) ({ \
- register tsl_t *__l = (tsl); \
- long __r; \
- asm volatile("xchg1 %0=%1,%3" : "=r"(__r), "=m"(*__l) : "1"(*__l), "r"(1));\
- __r ^ 1; \
-})
-
-/*
- * Store through a "volatile" pointer so we get a store with "release"
- * semantics.
- */
-#define MUTEX_UNSET(tsl) (*(volatile unsigned char *)(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * PowerPC/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_PPC_GCC_ASSEMBLY
-typedef u_int32_t tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * The PowerPC does a sort of pseudo-atomic locking. You set up a
- * 'reservation' on a chunk of memory containing a mutex by loading the
- * mutex value with LWARX. If the mutex has an 'unlocked' (arbitrary)
- * value, you then try storing into it with STWCX. If no other process or
- * thread broke your 'reservation' by modifying the memory containing the
- * mutex, then the STCWX succeeds; otherwise it fails and you try to get
- * a reservation again.
- *
- * While mutexes are explicitly 4 bytes, a 'reservation' applies to an
- * entire cache line, normally 32 bytes, aligned naturally. If the mutex
- * lives near data that gets changed a lot, there's a chance that you'll
- * see more broken reservations than you might otherwise. The only
- * situation in which this might be a problem is if one processor is
- * beating on a variable in the same cache block as the mutex while another
- * processor tries to acquire the mutex. That's bad news regardless
- * because of the way it bashes caches, but if you can't guarantee that a
- * mutex will reside in a relatively quiescent cache line, you might
- * consider padding the mutex to force it to live in a cache line by
- * itself. No, you aren't guaranteed that cache lines are 32 bytes. Some
- * embedded processors use 16-byte cache lines, while some 64-bit
- * processors use 128-bit cache lines. But assuming a 32-byte cache line
- * won't get you into trouble for now.
- *
- * If mutex locking is a bottleneck, then you can speed it up by adding a
- * regular LWZ load before the LWARX load, so that you can test for the
- * common case of a locked mutex without wasting cycles making a reservation.
- *
- * 'set' mutexes have the value 1, like on Intel; the returned value from
- * MUTEX_SET() is 1 if the mutex previously had its low bit set, 0 otherwise.
- */
-#define MUTEX_SET(tsl) ({ \
- int __one = 1; \
- int __r; \
- tsl_t *__l = (tsl); \
- asm volatile (" \
-0: \
- lwarx %0,0,%1; \
- cmpwi %0,0; \
- bne 1f; \
- stwcx. %2,0,%1; \
- bne- 0b; \
-1:" \
- : "=&r" (__r) \
- : "r" (__l), "r" (__one)); \
- __r & 1; \
-})
-
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * SCO/cc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY
-typedef unsigned char tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * UnixWare has threads in libthread, but OpenServer doesn't (yet).
- *
- * For cc/x86, 0 is clear, 1 is set.
- */
-
-#if defined(__USLC__)
-asm int
-_tsl_set(void *tsl)
-{
-%mem tsl
- movl tsl, %ecx
- movl $1, %eax
- lock
- xchgb (%ecx),%al
- xorl $1,%eax
-}
-#endif
-
-#define MUTEX_SET(tsl) _tsl_set(tsl)
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * Sparc/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_SPARC_GCC_ASSEMBLY
-typedef unsigned char tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- *
- * The ldstub instruction takes the location specified by its first argument
- * (a register containing a memory address) and loads its contents into its
- * second argument (a register) and atomically sets the contents the location
- * specified by its first argument to a byte of 1s. (The value in the second
- * argument is never read, but only overwritten.)
- *
- * The stbar is needed for v8, and is implemented as membar #sync on v9,
- + so is functional there as well. For v7, stbar may generate an illegal
- + instruction and we have no way to tell what we're running on. Some
- + operating systems notice and skip this instruction in the fault handler.
- *
- * For gcc/sparc, 0 is clear, 1 is set.
- */
-#define MUTEX_SET(tsl) ({ \
- register tsl_t *__l = (tsl); \
- register tsl_t __r; \
- __asm__ volatile \
- ("ldstub [%1],%0; stbar" \
- : "=r"( __r) : "r" (__l)); \
- !__r; \
-})
-
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*********************************************************************
- * UTS/cc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_UTS_CC_ASSEMBLY
-typedef int tsl_t;
-
-#define MUTEX_ALIGN sizeof(int)
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#define MUTEX_INIT(x) 0
-#define MUTEX_SET(x) (!uts_lock(x, 1))
-#define MUTEX_UNSET(x) (*(x) = 0)
-#endif
-#endif
-
-/*********************************************************************
- * x86/gcc assembly.
- *********************************************************************/
-#ifdef HAVE_MUTEX_X86_GCC_ASSEMBLY
-typedef unsigned char tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/x86, 0 is clear, 1 is set.
- */
-#define MUTEX_SET(tsl) ({ \
- register tsl_t *__l = (tsl); \
- int __r; \
- asm volatile("movl $1,%%eax; lock; xchgb %1,%%al; xorl $1,%%eax"\
- : "=&a" (__r), "=m" (*__l) \
- : "1" (*__l) \
- ); \
- __r & 1; \
-})
-
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-#ifdef HAVE_MUTEX_X86_64_GCC_ASSEMBLY
-typedef unsigned char tsl_t;
-
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/x86, 0 is clear, 1 is set.
- */
-#define MUTEX_SET(tsl) ({ \
- register tsl_t *__l = (tsl); \
- int __r; \
- asm volatile("mov $1,%%rax; lock; xchgb %1,%%al; xor $1,%%rax"\
- : "=&a" (__r), "=m" (*__l) \
- : "1" (*__l) \
- ); \
- __r & 1; \
-})
-
-#define MUTEX_UNSET(tsl) (*(tsl) = 0)
-#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
-#endif
-#endif
-
-/*
- * Mutex alignment defaults to one byte.
- *
- * !!!
- * Various systems require different alignments for mutexes (the worst we've
- * seen so far is 16-bytes on some HP architectures). Malloc(3) is assumed
- * to return reasonable alignment, all other mutex users must ensure proper
- * alignment locally.
- */
-#ifndef MUTEX_ALIGN
-#define MUTEX_ALIGN 1
-#endif
-
-/*
- * Mutex destruction defaults to a no-op.
- */
-#ifdef LOAD_ACTUAL_MUTEX_CODE
-#ifndef MUTEX_DESTROY
-#define MUTEX_DESTROY(x)
-#endif
-#endif
-
-#define MUTEX_IGNORE 0x001 /* Ignore, no lock required. */
-#define MUTEX_INITED 0x002 /* Mutex is successfully initialized */
-#define MUTEX_SELF_BLOCK 0x004 /* Must block self. */
-#define MUTEX_THREAD 0x008 /* Thread-only mutex. */
-
-/* Mutex. */
-struct __mutex_t {
-#ifdef HAVE_MUTEX_THREADS
-#ifdef MUTEX_FIELDS
- MUTEX_FIELDS
-#else
- tsl_t tas; /* Test and set. */
-#endif
- u_int32_t spins; /* Spins before block. */
- u_int32_t locked; /* !0 if locked. */
-#else
- u_int32_t off; /* Byte offset to lock. */
- u_int32_t pid; /* Lock holder: 0 or process pid. */
-#endif
- u_int32_t mutex_set_wait; /* Granted after wait. */
- u_int32_t mutex_set_nowait; /* Granted without waiting. */
-#ifdef MUTEX_SYSTEM_RESOURCES
- roff_t reg_off; /* Shared lock info offset. */
-#endif
-
- u_int8_t flags; /* MUTEX_XXX */
-};
-
-/* Redirect calls to the correct functions. */
-#ifdef HAVE_MUTEX_THREADS
-#if defined(HAVE_MUTEX_PTHREADS) || defined(HAVE_MUTEX_SOLARIS_LWP) || defined(HAVE_MUTEX_UI_THREADS)
-#define __db_mutex_init(a, b, c, d) __db_pthread_mutex_init(a, b, d)
-#define __db_mutex_lock(a, b, c) __db_pthread_mutex_lock(a, b)
-#define __db_mutex_unlock(a, b) __db_pthread_mutex_unlock(a, b)
-#define __db_mutex_destroy(a) __db_pthread_mutex_destroy(a)
-#else
-#define __db_mutex_init(a, b, c, d) __db_tas_mutex_init(a, b, d)
-#define __db_mutex_lock(a, b, c) __db_tas_mutex_lock(a, b)
-#define __db_mutex_unlock(a, b) __db_tas_mutex_unlock(a, b)
-#define __db_mutex_destroy(a) __db_tas_mutex_destroy(a)
-#endif
-#else
-#define __db_mutex_init(a, b, c, d) __db_fcntl_mutex_init(a, b, c)
-#define __db_mutex_lock(a, b, c) __db_fcntl_mutex_lock(a, b, c)
-#define __db_mutex_unlock(a, b) __db_fcntl_mutex_unlock(a, b)
-#define __db_mutex_destroy(a) __db_fcntl_mutex_destroy(a)
-#endif
-
-/* Redirect system resource calls to correct functions */
-#ifdef MUTEX_SYSTEM_RESOURCES
-#define __db_maintinit(a, b, c) __db_shreg_maintinit(a, b, c)
-#define __db_shlocks_clear(a, b, c) __db_shreg_locks_clear(a, b, c)
-#define __db_shlocks_destroy(a, b) __db_shreg_locks_destroy(a, b)
-#define __db_shmutex_init(a, b, c, d, e, f) \
- __db_shreg_mutex_init(a, b, c, d, e, f)
-#else
-#define __db_maintinit(a, b, c)
-#define __db_shlocks_clear(a, b, c)
-#define __db_shlocks_destroy(a, b)
-#define __db_shmutex_init(a, b, c, d, e, f) __db_mutex_init(a, b, c, d)
-#endif
-
-/*
- * Lock/unlock a mutex. If the mutex was marked as uninteresting, the thread
- * of control can proceed without it.
- *
- * If the lock is for threads-only, then it was optionally not allocated and
- * file handles aren't necessary, as threaded applications aren't supported by
- * fcntl(2) locking.
- */
-#ifdef DIAGNOSTIC
- /*
- * XXX
- * We want to switch threads as often as possible. Yield every time
- * we get a mutex to ensure contention.
- */
-#define MUTEX_LOCK(dbenv, mp, fh) \
- if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE)) \
- (void)__db_mutex_lock(dbenv, mp, fh); \
- if (DB_GLOBAL(db_pageyield)) \
- __os_yield(NULL, 1);
-#else
-#define MUTEX_LOCK(dbenv, mp, fh) \
- if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE)) \
- (void)__db_mutex_lock(dbenv, mp, fh);
-#endif
-#define MUTEX_UNLOCK(dbenv, mp) \
- if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE)) \
- (void)__db_mutex_unlock(dbenv, mp);
-#define MUTEX_THREAD_LOCK(dbenv, mp) \
- if (mp != NULL) \
- MUTEX_LOCK(dbenv, mp, NULL)
-#define MUTEX_THREAD_UNLOCK(dbenv, mp) \
- if (mp != NULL) \
- MUTEX_UNLOCK(dbenv, mp)
-
-/*
- * We use a single file descriptor for fcntl(2) locking, and (generally) the
- * object's offset in a shared region as the byte that we're locking. So,
- * there's a (remote) possibility that two objects might have the same offsets
- * such that the locks could conflict, resulting in deadlock. To avoid this
- * possibility, we offset the region offset by a small integer value, using a
- * different offset for each subsystem's locks. Since all region objects are
- * suitably aligned, the offset guarantees that we don't collide with another
- * region's objects.
- */
-#define DB_FCNTL_OFF_GEN 0 /* Everything else. */
-#define DB_FCNTL_OFF_LOCK 1 /* Lock subsystem offset. */
-#define DB_FCNTL_OFF_MPOOL 2 /* Mpool subsystem offset. */
diff --git a/bdb/include/os.h b/bdb/include/os.h
deleted file mode 100644
index b5d469e88fa..00000000000
--- a/bdb/include/os.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: os.h,v 11.5 2000/10/27 20:32:01 dda Exp $
- */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-/*
- * Filehandle.
- */
-struct __fh_t {
-#if defined(DB_WIN32)
- HANDLE handle; /* Windows/32 file handle. */
-#endif
- int fd; /* POSIX file descriptor. */
-
- u_int32_t log_size; /* XXX: Log file size. */
-
-#define DB_FH_NOSYNC 0x01 /* Handle doesn't need to be sync'd. */
-#define DB_FH_VALID 0x02 /* Handle is valid. */
- u_int8_t flags;
-};
-
-/*
- * We group certain seek/write calls into a single function so that we
- * can use pread(2)/pwrite(2) where they're available.
- */
-#define DB_IO_READ 1
-#define DB_IO_WRITE 2
-typedef struct __io_t {
- DB_FH *fhp; /* I/O file handle. */
- MUTEX *mutexp; /* Mutex to lock. */
- size_t pagesize; /* Page size. */
- db_pgno_t pgno; /* Page number. */
- u_int8_t *buf; /* Buffer. */
- size_t bytes; /* Bytes read/written. */
-} DB_IO;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/bdb/include/os_jump.h b/bdb/include/os_jump.h
deleted file mode 100644
index 681ba82d5eb..00000000000
--- a/bdb/include/os_jump.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: os_jump.h,v 11.3 2000/02/14 02:59:55 bostic Exp $
- */
-
-/* Calls which can be replaced by the application. */
-struct __db_jumptab {
- int (*j_close) __P((int));
- void (*j_dirfree) __P((char **, int));
- int (*j_dirlist) __P((const char *, char ***, int *));
- int (*j_exists) __P((const char *, int *));
- void (*j_free) __P((void *));
- int (*j_fsync) __P((int));
- int (*j_ioinfo) __P((const char *,
- int, u_int32_t *, u_int32_t *, u_int32_t *));
- void *(*j_malloc) __P((size_t));
- int (*j_map) __P((char *, size_t, int, int, void **));
- int (*j_open) __P((const char *, int, ...));
- ssize_t (*j_read) __P((int, void *, size_t));
- void *(*j_realloc) __P((void *, size_t));
- int (*j_rename) __P((const char *, const char *));
- int (*j_seek) __P((int, size_t, db_pgno_t, u_int32_t, int, int));
- int (*j_sleep) __P((u_long, u_long));
- int (*j_unlink) __P((const char *));
- int (*j_unmap) __P((void *, size_t));
- ssize_t (*j_write) __P((int, const void *, size_t));
- int (*j_yield) __P((void));
-};
-
-extern struct __db_jumptab __db_jump;
diff --git a/bdb/include/qam.h b/bdb/include/qam.h
deleted file mode 100644
index 88cd68776a8..00000000000
--- a/bdb/include/qam.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: qam.h,v 11.26 2001/01/11 18:19:52 bostic Exp $
- */
-
-/*
- * QAM data elements: a status field and the data.
- */
-typedef struct _qamdata {
- u_int8_t flags; /* 00: delete bit. */
-#define QAM_VALID 0x01
-#define QAM_SET 0x02
- u_int8_t data[1]; /* Record. */
-} QAMDATA;
-
-struct __queue; typedef struct __queue QUEUE;
-struct __qcursor; typedef struct __qcursor QUEUE_CURSOR;
-
-struct __qcursor {
- /* struct __dbc_internal */
- __DBC_INTERNAL
-
- /* Queue private part */
-
- /* Per-thread information: queue private. */
- db_recno_t recno; /* Current record number. */
-
- u_int32_t flags;
-};
-
-/*
- * The in-memory, per-tree queue data structure.
- */
-
-typedef struct __mpfarray {
- u_int32_t n_extent; /* Number of extents in table. */
- u_int32_t low_extent; /* First extent open. */
- u_int32_t hi_extent; /* Last extent open. */
- struct __qmpf {
- int pinref;
- DB_MPOOLFILE *mpf;
- } *mpfarray; /* Array of open extents. */
-} MPFARRAY;
-
-struct __queue {
- db_pgno_t q_meta; /* Database meta-data page. */
- db_pgno_t q_root; /* Database root page. */
-
- int re_pad; /* Fixed-length padding byte. */
- u_int32_t re_len; /* Length for fixed-length records. */
- u_int32_t rec_page; /* records per page */
- u_int32_t page_ext; /* Pages per extent */
- MPFARRAY array1, array2; /* File arrays. */
- DB_MPOOL_FINFO finfo; /* Initialized info struct. */
- DB_PGINFO pginfo; /* Initialized pginfo struct. */
- DBT pgcookie; /* Initialized pgcookie. */
- char *path; /* Space allocated to file pathname. */
- char *name; /* The name of the file. */
- char *dir; /* The dir of the file. */
- int mode; /* Mode to open extents. */
-};
-
-/* Format for queue extent names. */
-#define QUEUE_EXTENT "%s/__dbq.%s.%d"
-
-typedef struct __qam_filelist {
- DB_MPOOLFILE *mpf;
- u_int32_t id;
-} QUEUE_FILELIST;
-
-/*
- * Caculate the page number of a recno
- *
- * Number of records per page =
- * Divide the available space on the page by the record len + header.
- *
- * Page number for record =
- * divide the physical record number by the records per page
- * add the root page number
- * For now the root page will always be 1, but we might want to change
- * in the future (e.g. multiple fixed len queues per file).
- *
- * Index of record on page =
- * physical record number, less the logical pno times records/page
- */
-#define CALC_QAM_RECNO_PER_PAGE(dbp) \
- (((dbp)->pgsize - sizeof(QPAGE)) / \
- ALIGN(((QUEUE *)(dbp)->q_internal)->re_len + \
- sizeof(QAMDATA) - SSZA(QAMDATA, data), sizeof(u_int32_t)))
-
-#define QAM_RECNO_PER_PAGE(dbp) (((QUEUE*)(dbp)->q_internal)->rec_page)
-
-#define QAM_RECNO_PAGE(dbp, recno) \
- (((QUEUE *)(dbp)->q_internal)->q_root \
- + (((recno) - 1) / QAM_RECNO_PER_PAGE(dbp)))
-
-#define QAM_RECNO_INDEX(dbp, pgno, recno) \
- (((recno) - 1) - (QAM_RECNO_PER_PAGE(dbp) \
- * (pgno - ((QUEUE *)(dbp)->q_internal)->q_root)))
-
-#define QAM_GET_RECORD(dbp, page, index) \
- ((QAMDATA *)((u_int8_t *)(page) + \
- sizeof(QPAGE) + (ALIGN(sizeof(QAMDATA) - SSZA(QAMDATA, data) + \
- ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)) * index)))
-
-#define QAM_AFTER_CURRENT(meta, recno) \
- ((recno) > (meta)->cur_recno && \
- ((meta)->first_recno <= (meta)->cur_recno || (recno) < (meta)->first_recno))
-
-#define QAM_BEFORE_FIRST(meta, recno) \
- ((recno) < (meta)->first_recno && \
- ((meta->first_recno <= (meta)->cur_recno || (recno) > (meta)->cur_recno)))
-
-#define QAM_NOT_VALID(meta, recno) \
- (recno == RECNO_OOB || \
- QAM_BEFORE_FIRST(meta, recno) || QAM_AFTER_CURRENT(meta, recno))
-
-/*
- * Log opcodes for the mvptr routine.
- */
-#define QAM_SETFIRST 0x01
-#define QAM_SETCUR 0x02
-
-/*
- * Parameter to __qam_position.
- */
-typedef enum {
- QAM_READ,
- QAM_WRITE,
- QAM_CONSUME
-} qam_position_mode;
-
-typedef enum {
- QAM_PROBE_GET,
- QAM_PROBE_PUT,
- QAM_PROBE_MPF
-} qam_probe_mode;
-
-#define __qam_fget(dbp, pgnoaddr, flags, addrp) \
- __qam_fprobe(dbp, *pgnoaddr, addrp, QAM_PROBE_GET, flags)
-
-#define __qam_fput(dbp, pageno, addrp, flags) \
- __qam_fprobe(dbp, pageno, addrp, QAM_PROBE_PUT, flags)
-
-#include "qam_auto.h"
-#include "qam_ext.h"
diff --git a/bdb/include/region.h b/bdb/include/region.h
deleted file mode 100644
index c5882d09aad..00000000000
--- a/bdb/include/region.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: region.h,v 11.13 2000/11/15 19:25:37 sue Exp $
- */
-
-/*
- * The DB environment consists of some number of "regions", which are described
- * by the following four structures:
- *
- * REGENV -- shared information about the environment
- * REGENV_REF -- file describing system memory version of REGENV
- * REGION -- shared information about a single region
- * REGINFO -- per-process information about a REGION
- *
- * There are three types of memory that hold regions:
- * per-process heap (malloc)
- * file mapped into memory (mmap, MapViewOfFile)
- * system memory (shmget, CreateFileMapping)
- *
- * If the regions are private to a process, they're in malloc. If they're
- * public, they're in file mapped memory, or, optionally, in system memory.
- * Regions in the filesystem are named "__db.001", "__db.002" and so on. If
- * we're not using a private environment allocated using malloc(3), the file
- * "__db.001" will always exist, as we use it to synchronize on the regions,
- * whether they exist in file mapped memory or system memory.
- *
- * The file "__db.001" contains a REGENV structure and a linked list of some
- * number of REGION structures. Each of the REGION structures describes and
- * locks one of the underlying shared regions used by DB.
- *
- * __db.001
- * +---------+
- * |REGENV |
- * +---------+ +----------+
- * |REGION |-> | __db.002 |
- * | | +----------+
- * +---------+ +----------+
- * |REGION |-> | __db.003 |
- * | | +----------+
- * +---------+ +----------+
- * |REGION |-> | __db.004 |
- * | | +----------+
- * +---------+
- *
- * The only tricky part about manipulating the regions is correctly creating
- * or joining the REGENV file, i.e., __db.001. We have to be absolutely sure
- * that only one process creates it, and that everyone else joins it without
- * seeing inconsistent data. Once that region is created, we can use normal
- * shared locking procedures to do mutal exclusion for all other regions.
- *
- * One of the REGION structures in the main environment region describes the
- * environment region itself.
- *
- * To lock a region, locate the REGION structure that describes it and acquire
- * the region's mutex. There is one exception to this rule -- the lock for the
- * environment region itself is in the REGENV structure, and not in the REGION
- * that describes the environment region. That's so that we can acquire a lock
- * without walking linked lists that could potentially change underneath us.
- * The REGION will not be moved or removed during the life of the region, and
- * so long-lived references to it can be held by the process.
- *
- * All requests to create or join a region return a REGINFO structure, which
- * is held by the caller and used to open and subsequently close the reference
- * to the region. The REGINFO structure contains the per-process information
- * that we need to access the region.
- *
- * The one remaining complication. If the regions (including the environment
- * region) live in system memory, and the system memory isn't "named" somehow
- * in the filesystem name space, we need some way of finding it. Do this by
- * by writing the REGENV_REF structure into the "__db.001" file. When we find
- * a __db.001 file that is too small to be a real, on-disk environment, we use
- * the information it contains to redirect to the real "__db.001" file/memory.
- * This currently only happens when the REGENV file is in shared system memory.
- *
- * Although DB does not currently grow regions when they run out of memory, it
- * would be possible to do so. To grow a region, allocate a new region of the
- * appropriate size, then copy the old region over it and insert the additional
- * space into the already existing shalloc arena. Callers may have to fix up
- * local references, but that should be easy to do. This failed in historic
- * versions of DB because the region lock lived in the mapped memory, and when
- * it was unmapped and remapped (or copied), threads could lose track of it.
- * Once we moved that lock into a region that is never unmapped, growing should
- * work. That all said, current versions of DB don't implement region grow
- * because some systems don't support mutex copying, e.g., from OSF1 V4.0:
- *
- * The address of an msemaphore structure may be significant. If the
- * msemaphore structure contains any value copied from an msemaphore
- * structure at a different address, the result is undefined.
- */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define DB_REGION_FMT "__db.%03d" /* Region file name format. */
-#define DB_REGION_NAME_NUM 5 /* First digit offset in file names. */
-#define DB_REGION_NAME_LENGTH 8 /* Length of file names. */
-
-#define DB_REGION_ENV "__db.001" /* Primary environment name. */
-
-#define INVALID_REGION_ID 0 /* Out-of-band region ID. */
-#define REGION_ID_ENV 1 /* Primary environment ID. */
-
-typedef enum {
- INVALID_REGION_TYPE=0, /* Region type. */
- REGION_TYPE_ENV,
- REGION_TYPE_LOCK,
- REGION_TYPE_LOG,
- REGION_TYPE_MPOOL,
- REGION_TYPE_MUTEX,
- REGION_TYPE_TXN } reg_type;
-
-#define INVALID_REGION_SEGID -1 /* Segment IDs are either shmget(2) or
- * Win16 segment identifiers. They are
- * both stored in a "long", and we need
- * an out-of-band value.
- */
-/*
- * Nothing can live at region offset 0, because, in all cases, that's where
- * we store *something*. Lots of code needs an out-of-band value for region
- * offsets, so we use 0.
- */
-#define INVALID_ROFF 0
-
-/* Reference describing system memory version of REGENV. */
-typedef struct __db_reg_env_ref {
- roff_t size; /* Region size. */
- long segid; /* UNIX shmget(2) ID. */
-} REGENV_REF;
-
-/* Per-environment region information. */
-typedef struct __db_reg_env {
- /*
- * !!!
- * The mutex must be the first entry in the structure to guarantee
- * correct alignment.
- */
- MUTEX mutex; /* Environment mutex. */
-
- /*
- * !!!
- * Note, the magic and panic fields are NOT protected by any mutex,
- * and for this reason cannot be anything more complicated than a
- * zero/non-zero value.
- *
- * !!!
- * The valid region magic number must appear at the same byte offset
- * in both the environment and each shared region, as Windows/95 uses
- * it to determine if the memory has been zeroed since it was last used.
- */
- u_int32_t magic; /* Valid region magic number. */
-
- int panic; /* Environment is dead. */
-
- int majver; /* Major DB version number. */
- int minver; /* Minor DB version number. */
- int patch; /* Patch DB version number. */
-
- u_int32_t init_flags; /* Flags the env was initialized with.*/
-
- /* List of regions. */
- SH_LIST_HEAD(__db_regionh) regionq;
-
- u_int32_t refcnt; /* References to the environment. */
-
- size_t pad; /* Guarantee that following memory is
- * size_t aligned. This is necessary
- * because we're going to store the
- * allocation region information there.
- */
-} REGENV;
-
-/* Per-region shared region information. */
-typedef struct __db_region {
- /*
- * !!!
- * The mutex must be the first entry in the structure to guarantee
- * correct alignment.
- */
- MUTEX mutex; /* Region mutex. */
-
- /*
- * !!!
- * The valid region magic number must appear at the same byte offset
- * in both the environment and each shared region, as Windows/95 uses
- * it to determine if the memory has been zeroed since it was last used.
- */
- u_int32_t magic;
-
- SH_LIST_ENTRY q; /* Linked list of REGIONs. */
-
- reg_type type; /* Region type. */
- u_int32_t id; /* Region id. */
-
- roff_t size; /* Region size in bytes. */
-
- roff_t primary; /* Primary data structure offset. */
-
- long segid; /* UNIX shmget(2), Win16 segment ID. */
-} REGION;
-
-/*
- * Per-process/per-attachment information about a single region.
- */
-struct __db_reginfo_t { /* __db_r_attach IN parameters. */
- reg_type type; /* Region type. */
- u_int32_t id; /* Region id. */
- int mode; /* File creation mode. */
-
- /* __db_r_attach OUT parameters. */
- REGION *rp; /* Shared region. */
-
- char *name; /* Region file name. */
-
- void *addr; /* Region allocation address. */
- void *primary; /* Primary data structure address. */
-
- void *wnt_handle; /* Win/NT HANDLE. */
-
-#define REGION_CREATE 0x01 /* Caller created region. */
-#define REGION_CREATE_OK 0x02 /* Caller willing to create region. */
-#define REGION_JOIN_OK 0x04 /* Caller is looking for a match. */
- u_int32_t flags;
-};
-
-/*
- * Mutex maintenance information each subsystem region must keep track
- * of to manage resources adequately.
- */
-typedef struct __db_regmaint_stat_t {
- u_int32_t st_hint_hit;
- u_int32_t st_hint_miss;
- u_int32_t st_records;
- u_int32_t st_clears;
- u_int32_t st_destroys;
- u_int32_t st_max_locks;
-} REGMAINT_STAT;
-
-typedef struct __db_regmaint_t {
- u_int32_t reglocks; /* Maximum # of mutexes we track. */
- u_int32_t regmutex_hint; /* Hint for next slot */
- REGMAINT_STAT stat; /* Stats */
- roff_t regmutexes[1]; /* Region mutexes in use. */
-} REGMAINT;
-
-/*
- * R_ADDR Return a per-process address for a shared region offset.
- * R_OFFSET Return a shared region offset for a per-process address.
- *
- * !!!
- * R_OFFSET should really be returning a ptrdiff_t, but that's not yet
- * portable. We use u_int32_t, which restricts regions to 4Gb in size.
- */
-#define R_ADDR(base, offset) \
- ((void *)((u_int8_t *)((base)->addr) + offset))
-#define R_OFFSET(base, p) \
- ((u_int32_t)((u_int8_t *)(p) - (u_int8_t *)(base)->addr))
-
-/*
- * R_LOCK Lock/unlock a region.
- * R_UNLOCK
- */
-#define R_LOCK(dbenv, reginfo) \
- MUTEX_LOCK(dbenv, &(reginfo)->rp->mutex, (dbenv)->lockfhp)
-#define R_UNLOCK(dbenv, reginfo) \
- MUTEX_UNLOCK(dbenv, &(reginfo)->rp->mutex)
-
-/* PANIC_CHECK: Check to see if the DB environment is dead. */
-#define PANIC_CHECK(dbenv) \
- if (DB_GLOBAL(db_panic) && \
- (dbenv)->reginfo != NULL && ((REGENV *) \
- ((REGINFO *)(dbenv)->reginfo)->primary)->panic != 0) \
- return (DB_RUNRECOVERY);
-
-/*
- * All regions are created on 8K boundaries out of sheer paranoia, so that
- * we don't make some underlying VM unhappy.
- */
-#define OS_ROUNDOFF(i, s) { \
- (i) += (s) - 1; \
- (i) -= (i) % (s); \
-}
-#define OS_VMPAGESIZE (8 * 1024)
-#define OS_VMROUNDOFF(i) OS_ROUNDOFF(i, OS_VMPAGESIZE)
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/bdb/include/shqueue.h b/bdb/include/shqueue.h
deleted file mode 100644
index 115c5d39e88..00000000000
--- a/bdb/include/shqueue.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: shqueue.h,v 11.6 2000/11/14 20:20:28 bostic Exp $
- */
-#ifndef _SYS_SHQUEUE_H_
-#define _SYS_SHQUEUE_H_
-
-/*
- * This file defines three types of data structures: lists, tail queues, and
- * circular queues, similarly to the include file <sys/queue.h>.
- *
- * The difference is that this set of macros can be used for structures that
- * reside in shared memory that may be mapped at different addresses in each
- * process. In most cases, the macros for shared structures exactly mirror
- * the normal macros, although the macro calls require an additional type
- * parameter, only used by the HEAD and ENTRY macros of the standard macros.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*
- * Shared list definitions.
- */
-#define SH_LIST_HEAD(name) \
-struct name { \
- ssize_t slh_first; /* first element */ \
-}
-
-#define SH_LIST_ENTRY \
-struct { \
- ssize_t sle_next; /* relative offset next element */ \
- ssize_t sle_prev; /* relative offset of prev element */ \
-}
-
-/*
- * Shared list functions. Since we use relative offsets for pointers,
- * 0 is a valid offset. Therefore, we use -1 to indicate end of list.
- * The macros ending in "P" return pointers without checking for end
- * of list, the others check for end of list and evaluate to either a
- * pointer or NULL.
- */
-
-#define SH_LIST_FIRSTP(head, type) \
- ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))
-
-#define SH_LIST_FIRST(head, type) \
- ((head)->slh_first == -1 ? NULL : \
- ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)))
-
-#define SH_LIST_NEXTP(elm, field, type) \
- ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next))
-
-#define SH_LIST_NEXT(elm, field, type) \
- ((elm)->field.sle_next == -1 ? NULL : \
- ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)))
-
-#define SH_LIST_PREV(elm, field) \
- ((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev))
-
-#define SH_PTR_TO_OFF(src, dest) \
- ((ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src))))
-
-/*
- * Take the element's next pointer and calculate what the corresponding
- * Prev pointer should be -- basically it is the negation plus the offset
- * of the next field in the structure.
- */
-#define SH_LIST_NEXT_TO_PREV(elm, field) \
- (-(elm)->field.sle_next + SH_PTR_TO_OFF(elm, &(elm)->field.sle_next))
-
-#define SH_LIST_INIT(head) (head)->slh_first = -1
-
-#define SH_LIST_INSERT_AFTER(listelm, elm, field, type) do { \
- if ((listelm)->field.sle_next != -1) { \
- (elm)->field.sle_next = SH_PTR_TO_OFF(elm, \
- SH_LIST_NEXTP(listelm, field, type)); \
- SH_LIST_NEXTP(listelm, field, type)->field.sle_prev = \
- SH_LIST_NEXT_TO_PREV(elm, field); \
- } else \
- (elm)->field.sle_next = -1; \
- (listelm)->field.sle_next = SH_PTR_TO_OFF(listelm, elm); \
- (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(listelm, field); \
-} while (0)
-
-#define SH_LIST_INSERT_HEAD(head, elm, field, type) do { \
- if ((head)->slh_first != -1) { \
- (elm)->field.sle_next = \
- (head)->slh_first - SH_PTR_TO_OFF(head, elm); \
- SH_LIST_FIRSTP(head, type)->field.sle_prev = \
- SH_LIST_NEXT_TO_PREV(elm, field); \
- } else \
- (elm)->field.sle_next = -1; \
- (head)->slh_first = SH_PTR_TO_OFF(head, elm); \
- (elm)->field.sle_prev = SH_PTR_TO_OFF(elm, &(head)->slh_first); \
-} while (0)
-
-#define SH_LIST_REMOVE(elm, field, type) do { \
- if ((elm)->field.sle_next != -1) { \
- SH_LIST_NEXTP(elm, field, type)->field.sle_prev = \
- (elm)->field.sle_prev - (elm)->field.sle_next; \
- *SH_LIST_PREV(elm, field) += (elm)->field.sle_next; \
- } else \
- *SH_LIST_PREV(elm, field) = -1; \
-} while (0)
-
-/*
- * Shared tail queue definitions.
- */
-#define SH_TAILQ_HEAD(name) \
-struct name { \
- ssize_t stqh_first; /* relative offset of first element */ \
- ssize_t stqh_last; /* relative offset of last's next */ \
-}
-
-#define SH_TAILQ_ENTRY \
-struct { \
- ssize_t stqe_next; /* relative offset of next element */ \
- ssize_t stqe_prev; /* relative offset of prev's next */ \
-}
-
-/*
- * Shared tail queue functions.
- */
-#define SH_TAILQ_FIRSTP(head, type) \
- ((struct type *)((u_int8_t *)(head) + (head)->stqh_first))
-
-#define SH_TAILQ_FIRST(head, type) \
- ((head)->stqh_first == -1 ? NULL : SH_TAILQ_FIRSTP(head, type))
-
-#define SH_TAILQ_NEXTP(elm, field, type) \
- ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next))
-
-#define SH_TAILQ_NEXT(elm, field, type) \
- ((elm)->field.stqe_next == -1 ? NULL : SH_TAILQ_NEXTP(elm, field, type))
-
-#define SH_TAILQ_PREVP(elm, field) \
- ((ssize_t *)((u_int8_t *)(elm) + (elm)->field.stqe_prev))
-
-#define SH_TAILQ_LAST(head) \
- ((ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last))
-
-#define SH_TAILQ_NEXT_TO_PREV(elm, field) \
- (-(elm)->field.stqe_next + SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next))
-
-#define SH_TAILQ_INIT(head) { \
- (head)->stqh_first = -1; \
- (head)->stqh_last = SH_PTR_TO_OFF(head, &(head)->stqh_first); \
-}
-
-#define SH_TAILQ_INSERT_HEAD(head, elm, field, type) do { \
- if ((head)->stqh_first != -1) { \
- (elm)->field.stqe_next = \
- (head)->stqh_first - SH_PTR_TO_OFF(head, elm); \
- SH_TAILQ_FIRSTP(head, type)->field.stqe_prev = \
- SH_TAILQ_NEXT_TO_PREV(elm, field); \
- } else { \
- (elm)->field.stqe_next = -1; \
- (head)->stqh_last = \
- SH_PTR_TO_OFF(head, &(elm)->field.stqe_next); \
- } \
- (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \
- (elm)->field.stqe_prev = \
- SH_PTR_TO_OFF(elm, &(head)->stqh_first); \
-} while (0)
-
-#define SH_TAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.stqe_next = -1; \
- (elm)->field.stqe_prev = \
- -SH_PTR_TO_OFF(head, elm) + (head)->stqh_last; \
- if ((head)->stqh_last == \
- SH_PTR_TO_OFF((head), &(head)->stqh_first)) \
- (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \
- else \
- *SH_TAILQ_LAST(head) = -(head)->stqh_last + \
- SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) + \
- SH_PTR_TO_OFF(head, elm); \
- (head)->stqh_last = \
- SH_PTR_TO_OFF(head, &((elm)->field.stqe_next)); \
-} while (0)
-
-#define SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do { \
- if ((listelm)->field.stqe_next != -1) { \
- (elm)->field.stqe_next = (listelm)->field.stqe_next - \
- SH_PTR_TO_OFF(listelm, elm); \
- SH_TAILQ_NEXTP(listelm, field, type)->field.stqe_prev = \
- SH_TAILQ_NEXT_TO_PREV(elm, field); \
- } else { \
- (elm)->field.stqe_next = -1; \
- (head)->stqh_last = \
- SH_PTR_TO_OFF(head, &elm->field.stqe_next); \
- } \
- (listelm)->field.stqe_next = SH_PTR_TO_OFF(listelm, elm); \
- (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(listelm, field); \
-} while (0)
-
-#define SH_TAILQ_REMOVE(head, elm, field, type) do { \
- if ((elm)->field.stqe_next != -1) { \
- SH_TAILQ_NEXTP(elm, field, type)->field.stqe_prev = \
- (elm)->field.stqe_prev + \
- SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm, \
- field, type), elm); \
- *SH_TAILQ_PREVP(elm, field) += elm->field.stqe_next; \
- } else { \
- (head)->stqh_last = (elm)->field.stqe_prev + \
- SH_PTR_TO_OFF(head, elm); \
- *SH_TAILQ_PREVP(elm, field) = -1; \
- } \
-} while (0)
-
-/*
- * Shared circular queue definitions.
- */
-#define SH_CIRCLEQ_HEAD(name) \
-struct name { \
- ssize_t scqh_first; /* first element */ \
- ssize_t scqh_last; /* last element */ \
-}
-
-#define SH_CIRCLEQ_ENTRY \
-struct { \
- ssize_t scqe_next; /* next element */ \
- ssize_t scqe_prev; /* previous element */ \
-}
-
-/*
- * Shared circular queue functions.
- */
-#define SH_CIRCLEQ_FIRSTP(head, type) \
- ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_first))
-
-#define SH_CIRCLEQ_FIRST(head, type) \
- ((head)->scqh_first == -1 ? \
- (void *)head : SH_CIRCLEQ_FIRSTP(head, type))
-
-#define SH_CIRCLEQ_LASTP(head, type) \
- ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_last))
-
-#define SH_CIRCLEQ_LAST(head, type) \
- ((head)->scqh_last == -1 ? (void *)head : SH_CIRCLEQ_LASTP(head, type))
-
-#define SH_CIRCLEQ_NEXTP(elm, field, type) \
- ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_next))
-
-#define SH_CIRCLEQ_NEXT(head, elm, field, type) \
- ((elm)->field.scqe_next == SH_PTR_TO_OFF(elm, head) ? \
- (void *)head : SH_CIRCLEQ_NEXTP(elm, field, type))
-
-#define SH_CIRCLEQ_PREVP(elm, field, type) \
- ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_prev))
-
-#define SH_CIRCLEQ_PREV(head, elm, field, type) \
- ((elm)->field.scqe_prev == SH_PTR_TO_OFF(elm, head) ? \
- (void *)head : SH_CIRCLEQ_PREVP(elm, field, type))
-
-#define SH_CIRCLEQ_INIT(head) { \
- (head)->scqh_first = 0; \
- (head)->scqh_last = 0; \
-}
-
-#define SH_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field, type) do { \
- (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, listelm); \
- (elm)->field.scqe_next = (listelm)->field.scqe_next + \
- (elm)->field.scqe_prev; \
- if (SH_CIRCLEQ_NEXTP(listelm, field, type) == (void *)head) \
- (head)->scqh_last = SH_PTR_TO_OFF(head, elm); \
- else \
- SH_CIRCLEQ_NEXTP(listelm, \
- field, type)->field.scqe_prev = \
- SH_PTR_TO_OFF(SH_CIRCLEQ_NEXTP(listelm, \
- field, type), elm); \
- (listelm)->field.scqe_next = -(elm)->field.scqe_prev; \
-} while (0)
-
-#define SH_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field, type) do { \
- (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, listelm); \
- (elm)->field.scqe_prev = (elm)->field.scqe_next - \
- SH_CIRCLEQ_PREVP(listelm, field, type)->field.scqe_next;\
- if (SH_CIRCLEQ_PREVP(listelm, field, type) == (void *)(head)) \
- (head)->scqh_first = SH_PTR_TO_OFF(head, elm); \
- else \
- SH_CIRCLEQ_PREVP(listelm, \
- field, type)->field.scqe_next = \
- SH_PTR_TO_OFF(SH_CIRCLEQ_PREVP(listelm, \
- field, type), elm); \
- (listelm)->field.scqe_prev = -(elm)->field.scqe_next; \
-} while (0)
-
-#define SH_CIRCLEQ_INSERT_HEAD(head, elm, field, type) do { \
- (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, head); \
- (elm)->field.scqe_next = (head)->scqh_first + \
- (elm)->field.scqe_prev; \
- if ((head)->scqh_last == 0) \
- (head)->scqh_last = -(elm)->field.scqe_prev; \
- else \
- SH_CIRCLEQ_FIRSTP(head, type)->field.scqe_prev = \
- SH_PTR_TO_OFF(SH_CIRCLEQ_FIRSTP(head, type), elm); \
- (head)->scqh_first = -(elm)->field.scqe_prev; \
-} while (0)
-
-#define SH_CIRCLEQ_INSERT_TAIL(head, elm, field, type) do { \
- (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, head); \
- (elm)->field.scqe_prev = (head)->scqh_last + \
- (elm)->field.scqe_next; \
- if ((head)->scqh_first == 0) \
- (head)->scqh_first = -(elm)->field.scqe_next; \
- else \
- SH_CIRCLEQ_LASTP(head, type)->field.scqe_next = \
- SH_PTR_TO_OFF(SH_CIRCLEQ_LASTP(head, type), elm); \
- (head)->scqh_last = -(elm)->field.scqe_next; \
-} while (0)
-
-#define SH_CIRCLEQ_REMOVE(head, elm, field, type) do { \
- if (SH_CIRCLEQ_NEXTP(elm, field, type) == (void *)(head)) \
- (head)->scqh_last += (elm)->field.scqe_prev; \
- else \
- SH_CIRCLEQ_NEXTP(elm, field, type)->field.scqe_prev += \
- (elm)->field.scqe_prev; \
- if (SH_CIRCLEQ_PREVP(elm, field, type) == (void *)(head)) \
- (head)->scqh_first += (elm)->field.scqe_next; \
- else \
- SH_CIRCLEQ_PREVP(elm, field, type)->field.scqe_next += \
- (elm)->field.scqe_next; \
-} while (0)
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* !_SYS_SHQUEUE_H_ */
diff --git a/bdb/include/tcl_db.h b/bdb/include/tcl_db.h
deleted file mode 100644
index 254006c2f6d..00000000000
--- a/bdb/include/tcl_db.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: tcl_db.h,v 11.9 2000/12/12 17:43:56 bostic Exp $
- */
-
-#define MSG_SIZE 100 /* Message size */
-
-enum INFOTYPE {
- I_ENV, I_DB, I_DBC, I_TXN, I_MP, I_PG, I_LOCK, I_NDBM, I_MUTEX };
-
-#define MAX_ID 8 /* Maximum number of sub-id's we need */
-
-#define DBTCL_DBM 1
-#define DBTCL_NDBM 2
-
-typedef struct _mutex_entry {
- union {
- struct {
- MUTEX real_m;
- u_int32_t real_val;
- } r;
- /*
- * This is here to make sure that each of the mutex structures
- * are 16-byte aligned, which is required on HP architectures.
- * The db_mutex_t structure might be >32 bytes itself, or the
- * real_val might push it over the 32 byte boundary. The best
- * we can do is use a 48 byte boundary.
- */
- char c[48];
- } u;
-} _MUTEX_ENTRY;
-
-#define m u.r.real_m
-#define val u.r.real_val
-
-typedef struct _mutex_data {
- DB_ENV *env;
- REGINFO reginfo;
- _MUTEX_ENTRY *marray;
- size_t size;
- u_int32_t n_mutex;
-} _MUTEX_DATA;
-
-/*
- * Why use a home grown package over the Tcl_Hash functions?
- *
- * We could have implemented the stuff below without maintaining our
- * own list manipulation, efficiently hashing it with the available
- * Tcl functions (Tcl_CreateHashEntry, Tcl_GetHashValue, etc). I chose
- * not to do so for these reasons:
- *
- * We still need the information below. Using the hashing only removes
- * us from needing the next/prev pointers. We still need the structure
- * itself because we need more than one value associated with a widget.
- * We need to keep track of parent pointers for sub-widgets (like cursors)
- * so we can correctly close. We need to keep track of individual widget's
- * id counters for any sub-widgets they may have. We need to be able to
- * associate the name/client data outside the scope of the widget.
- *
- * So, is it better to use the hashing rather than
- * the linear list we have now? I decided against it for the simple reason
- * that to access the structure would require two calls. The first is
- * Tcl_FindHashEntry(table, key) and then, once we have the entry, we'd
- * have to do Tcl_GetHashValue(entry) to get the pointer of the structure.
- *
- * I believe the number of simultaneous DB widgets in existence at one time
- * is not going to be that large (more than several dozen) such that
- * linearly searching the list is not going to impact performance in a
- * noticable way. Should performance be impacted due to the size of the
- * info list, then perhaps it is time to revisit this decision.
- */
-typedef struct dbtcl_info {
- LIST_ENTRY(dbtcl_info) entries;
- Tcl_Interp *i_interp;
- char *i_name;
- enum INFOTYPE i_type;
- union infop {
- DB_ENV *envp;
- void *anyp;
- DB *dbp;
- DBC *dbcp;
- DB_TXN *txnp;
- DB_MPOOLFILE *mp;
- DB_LOCK *lock;
- _MUTEX_DATA *mutex;
-#if 0
- DBM *ndbmp; /* Compatibility */
-#endif
- } un;
- union data {
- int anydata;
- db_pgno_t pgno;
- u_int32_t lockid;
- } und;
- union data2 {
- int anydata;
- size_t pagesz;
- } und2;
- DBT i_lockobj;
- FILE *i_err;
- char *i_errpfx;
- struct dbtcl_info *i_parent;
- int i_otherid[MAX_ID];
-} DBTCL_INFO;
-
-extern int __debug_on, __debug_print, __debug_stop, __debug_test;
-LIST_HEAD(infohead, dbtcl_info) __db_infohead;
-
-#define i_anyp un.anyp
-#define i_pagep un.anyp
-#define i_envp un.envp
-#define i_dbp un.dbp
-#define i_dbcp un.dbcp
-#define i_txnp un.txnp
-#define i_mp un.mp
-#define i_lock un.lock
-#define i_mutex un.mutex
-#if 0
-#define i_ndbm un.ndbmp
-#endif
-
-#define i_data und.anydata
-#define i_pgno und.pgno
-#define i_locker und.lockid
-#define i_data2 und2.anydata
-#define i_pgsz und2.pagesz
-
-#define i_envtxnid i_otherid[0]
-#define i_envmpid i_otherid[1]
-#define i_envlockid i_otherid[2]
-#define i_envmutexid i_otherid[3]
-
-#define i_mppgid i_otherid[0]
-
-#define i_dbdbcid i_otherid[0]
-
-#define NAME_TO_ENV(name) (DB_ENV *)_NameToPtr((name))
-#define NAME_TO_DB(name) (DB *)_NameToPtr((name))
-#define NAME_TO_DBC(name) (DBC *)_NameToPtr((name))
-#define NAME_TO_TXN(name) (DB_TXN *)_NameToPtr((name))
-#define NAME_TO_MP(name) (DB_MPOOLFILE *)_NameToPtr((name))
-#define NAME_TO_LOCK(name) (DB_LOCK *)_NameToPtr((name))
-
-/*
- * MAKE_STAT_LIST appends a {name value} pair to a result list
- * that MUST be called 'res' that is a Tcl_Obj * in the local
- * function. This macro also assumes a label "error" to go to
- * in the even of a Tcl error. For stat functions this will
- * typically go before the "free" function to free the stat structure
- * returned by DB.
- */
-#define MAKE_STAT_LIST(s,v) \
-do { \
- result = _SetListElemInt(interp, res, (s), (v)); \
- if (result != TCL_OK) \
- goto error; \
-} while (0)
-
-/*
- * MAKE_STAT_STRLIST appends a {name string} pair to a result list
- * that MUST be called 'res' that is a Tcl_Obj * in the local
- * function. This macro also assumes a label "error" to go to
- * in the even of a Tcl error. For stat functions this will
- * typically go before the "free" function to free the stat structure
- * returned by DB.
- */
-#define MAKE_STAT_STRLIST(s,s1) \
-do { \
- result = _SetListElem(interp, res, (s), strlen(s), \
- (s1), strlen(s1)); \
- if (result != TCL_OK) \
- goto error; \
-} while (0)
-
-/*
- * FLAG_CHECK checks that the given flag is not set yet.
- * If it is, it sets up an error message.
- */
-#define FLAG_CHECK(flag) \
-do { \
- if ((flag) != 0) { \
- Tcl_SetResult(interp, \
- " Only 1 policy can be specified.\n", \
- TCL_STATIC); \
- result = TCL_ERROR; \
- break; \
- } \
-} while (0)
-
-/*
- * FLAG_CHECK2 checks that the given flag is not set yet or is
- * only set to the given allowed value.
- * If it is, it sets up an error message.
- */
-#define FLAG_CHECK2(flag,val) \
-do { \
- if ((flag) != 0 && (flag) != (val)) { \
- Tcl_SetResult(interp, \
- " Only 1 policy can be specified.\n", \
- TCL_STATIC); \
- result = TCL_ERROR; \
- break; \
- } \
-} while (0)
-
-/*
- * IS_HELP checks whether the arg we bombed on is -?, which is a help option.
- * If it is, we return TCL_OK (but leave the result set to whatever
- * Tcl_GetIndexFromObj says, which lists all the valid options. Otherwise
- * return TCL_ERROR.
- */
-#define IS_HELP(s) \
- (strcmp(Tcl_GetStringFromObj(s,NULL), "-?") == 0) ? TCL_OK : TCL_ERROR
-
-#include "tcl_ext.h"
diff --git a/bdb/include/txn.h b/bdb/include/txn.h
deleted file mode 100644
index 009a1ca1589..00000000000
--- a/bdb/include/txn.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: txn.h,v 11.12 2001/01/02 17:23:39 margo Exp $
- */
-
-#ifndef _TXN_H_
-#define _TXN_H_
-
-#include "xa.h"
-
-struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR;
-struct __db_txnregion; typedef struct __db_txnregion DB_TXNREGION;
-
-/*
- * !!!
- * TXN_MINIMUM = (DB_LOCK_MAXID + 1) but this makes compilers complain.
- */
-#define TXN_MINIMUM 0x80000000
-#define TXN_INVALID 0xffffffff /* Maximum number of txn ids. */
-#define TXN_INVALID_ID 0 /* Invalid transaction ID. */
-
-#define DEF_MAX_TXNS 20 /* Default max transactions. */
-
-/* The structure allocated for every transaction. */
-struct __db_txn {
- DB_TXNMGR *mgrp; /* Pointer to transaction manager. */
- DB_TXN *parent; /* Pointer to transaction's parent. */
- DB_LSN last_lsn; /* Lsn of last log write. */
- u_int32_t txnid; /* Unique transaction id. */
- roff_t off; /* Detail structure within region. */
- TAILQ_ENTRY(__db_txn) links; /* Links transactions off manager. */
- TAILQ_HEAD(__kids, __db_txn) kids; /* Child transactions. */
- TAILQ_ENTRY(__db_txn) klinks; /* Links child transactions. */
- u_int32_t cursors; /* Number of cursors open for txn */
-
-#define TXN_CHILDCOMMIT 0x01 /* Transaction that has committed. */
-#define TXN_MALLOC 0x02 /* Structure allocated by TXN system. */
-#define TXN_NOSYNC 0x04 /* Do not sync on prepare and commit. */
-#define TXN_NOWAIT 0x08 /* Do not wait on locks. */
-#define TXN_SYNC 0x10 /* Sync on prepare and commit. */
- u_int32_t flags;
-};
-
-/*
- * Internal data maintained in shared memory for each transaction.
- */
-typedef char DB_XID[XIDDATASIZE];
-
-typedef struct __txn_detail {
- u_int32_t txnid; /* current transaction id
- used to link free list also */
- DB_LSN last_lsn; /* last lsn written for this txn */
- DB_LSN begin_lsn; /* lsn of begin record */
- roff_t parent; /* Offset of transaction's parent. */
-
-#define TXN_RUNNING 1
-#define TXN_ABORTED 2
-#define TXN_PREPARED 3
-#define TXN_COMMITTED 4
- u_int32_t status; /* status of the transaction */
-
- SH_TAILQ_ENTRY links; /* free/active list */
-
-#define TXN_XA_ABORTED 1
-#define TXN_XA_DEADLOCKED 2
-#define TXN_XA_ENDED 3
-#define TXN_XA_PREPARED 4
-#define TXN_XA_STARTED 5
-#define TXN_XA_SUSPENDED 6
- u_int32_t xa_status; /* XA status */
-
- /*
- * XID (xid_t) structure: because these fields are logged, the
- * sizes have to be explicit.
- */
- DB_XID xid; /* XA global transaction id */
- u_int32_t bqual; /* bqual_length from XID */
- u_int32_t gtrid; /* gtrid_length from XID */
- int32_t format; /* XA format */
-} TXN_DETAIL;
-
-/*
- * DB_TXNMGR --
- * The transaction manager encapsulates the transaction system.
- */
-struct __db_txnmgr {
-/*
- * These fields need to be protected for multi-threaded support.
- *
- * !!!
- * As this structure is allocated in per-process memory, the mutex may need
- * to be stored elsewhere on architectures unable to support mutexes in heap
- * memory, e.g., HP/UX 9.
- */
- MUTEX *mutexp; /* Lock list of active transactions
- * (including the content of each
- * TXN_DETAIL structure on the list).
- */
- /* List of active transactions. */
- TAILQ_HEAD(_chain, __db_txn) txn_chain;
-
-/* These fields are never updated after creation, and so not protected. */
- DB_ENV *dbenv; /* Environment. */
- REGINFO reginfo; /* Region information. */
-};
-
-/*
- * DB_TXNREGION --
- * The primary transaction data structure in the shared memory region.
- */
-struct __db_txnregion {
- u_int32_t maxtxns; /* maximum number of active TXNs */
- u_int32_t last_txnid; /* last transaction id given out */
- DB_LSN pending_ckp; /* last checkpoint did not finish */
- DB_LSN last_ckp; /* lsn of the last checkpoint */
- time_t time_ckp; /* time of last checkpoint */
- u_int32_t logtype; /* type of logging */
- u_int32_t locktype; /* lock type */
- u_int32_t naborts; /* number of aborted TXNs */
- u_int32_t ncommits; /* number of committed TXNs */
- u_int32_t nbegins; /* number of begun TXNs */
- u_int32_t nactive; /* number of active TXNs */
- u_int32_t maxnactive; /* maximum number of active TXNs */
- /* active TXN list */
- SH_TAILQ_HEAD(__active) active_txn;
-};
-
-/*
- * Make the region large enough to hold N transaction detail structures
- * plus some space to hold thread handles and the beginning of the shalloc
- * region.
- */
-#define TXN_REGION_SIZE(N) \
- (sizeof(DB_TXNREGION) + N * sizeof(TXN_DETAIL) + 1000)
-
-/*
- * Log record types.
- */
-#define TXN_COMMIT 1
-#define TXN_PREPARE 2
-
-#include "txn_auto.h"
-#include "txn_ext.h"
-
-#include "xa_ext.h"
-#endif /* !_TXN_H_ */
diff --git a/bdb/include/xa.h b/bdb/include/xa.h
deleted file mode 100644
index ce46179263a..00000000000
--- a/bdb/include/xa.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: xa.h,v 11.3 2000/02/14 02:59:55 bostic Exp $
- */
-/*
- * Start of xa.h header
- *
- * Define a symbol to prevent multiple inclusions of this header file
- */
-#ifndef XA_H
-#define XA_H
-
-/*
- * Transaction branch identification: XID and NULLXID:
- */
-#define XIDDATASIZE 128 /* size in bytes */
-#define MAXGTRIDSIZE 64 /* maximum size in bytes of gtrid */
-#define MAXBQUALSIZE 64 /* maximum size in bytes of bqual */
-
-struct xid_t {
- long formatID; /* format identifier */
- long gtrid_length; /* value from 1 through 64 */
- long bqual_length; /* value from 1 through 64 */
- char data[XIDDATASIZE];
-};
-typedef struct xid_t XID;
-/*
- * A value of -1 in formatID means that the XID is null.
- */
-
-/*
- * Declarations of routines by which RMs call TMs:
- */
-extern int ax_reg __P((int, XID *, long));
-extern int ax_unreg __P((int, long));
-
-/*
- * XA Switch Data Structure
- */
-#define RMNAMESZ 32 /* length of resource manager name, */
- /* including the null terminator */
-#define MAXINFOSIZE 256 /* maximum size in bytes of xa_info */
- /* strings, including the null
- terminator */
-struct xa_switch_t {
- char name[RMNAMESZ]; /* name of resource manager */
- long flags; /* resource manager specific options */
- long version; /* must be 0 */
- int (*xa_open_entry) /* xa_open function pointer */
- __P((char *, int, long));
- int (*xa_close_entry) /* xa_close function pointer */
- __P((char *, int, long));
- int (*xa_start_entry) /* xa_start function pointer */
- __P((XID *, int, long));
- int (*xa_end_entry) /* xa_end function pointer */
- __P((XID *, int, long));
- int (*xa_rollback_entry) /* xa_rollback function pointer */
- __P((XID *, int, long));
- int (*xa_prepare_entry) /* xa_prepare function pointer */
- __P((XID *, int, long));
- int (*xa_commit_entry) /* xa_commit function pointer */
- __P((XID *, int, long));
- int (*xa_recover_entry) /* xa_recover function pointer */
- __P((XID *, long, int, long));
- int (*xa_forget_entry) /* xa_forget function pointer */
- __P((XID *, int, long));
- int (*xa_complete_entry) /* xa_complete function pointer */
- __P((int *, int *, int, long));
-};
-
-/*
- * Flag definitions for the RM switch
- */
-#define TMNOFLAGS 0x00000000L /* no resource manager features
- selected */
-#define TMREGISTER 0x00000001L /* resource manager dynamically
- registers */
-#define TMNOMIGRATE 0x00000002L /* resource manager does not support
- association migration */
-#define TMUSEASYNC 0x00000004L /* resource manager supports
- asynchronous operations */
-/*
- * Flag definitions for xa_ and ax_ routines
- */
-/* use TMNOFLAGGS, defined above, when not specifying other flags */
-#define TMASYNC 0x80000000L /* perform routine asynchronously */
-#define TMONEPHASE 0x40000000L /* caller is using one-phase commit
- optimisation */
-#define TMFAIL 0x20000000L /* dissociates caller and marks
- transaction branch rollback-only */
-#define TMNOWAIT 0x10000000L /* return if blocking condition
- exists */
-#define TMRESUME 0x08000000L /* caller is resuming association with
- suspended transaction branch */
-#define TMSUCCESS 0x04000000L /* dissociate caller from transaction
- branch */
-#define TMSUSPEND 0x02000000L /* caller is suspending, not ending,
- association */
-#define TMSTARTRSCAN 0x01000000L /* start a recovery scan */
-#define TMENDRSCAN 0x00800000L /* end a recovery scan */
-#define TMMULTIPLE 0x00400000L /* wait for any asynchronous
- operation */
-#define TMJOIN 0x00200000L /* caller is joining existing
- transaction branch */
-#define TMMIGRATE 0x00100000L /* caller intends to perform
- migration */
-
-/*
- * ax_() return codes (transaction manager reports to resource manager)
- */
-#define TM_JOIN 2 /* caller is joining existing
- transaction branch */
-#define TM_RESUME 1 /* caller is resuming association with
- suspended transaction branch */
-#define TM_OK 0 /* normal execution */
-#define TMER_TMERR -1 /* an error occurred in the transaction
- manager */
-#define TMER_INVAL -2 /* invalid arguments were given */
-#define TMER_PROTO -3 /* routine invoked in an improper
- context */
-
-/*
- * xa_() return codes (resource manager reports to transaction manager)
- */
-#define XA_RBBASE 100 /* The inclusive lower bound of the
- rollback codes */
-#define XA_RBROLLBACK XA_RBBASE /* The rollback was caused by an
- unspecified reason */
-#define XA_RBCOMMFAIL XA_RBBASE+1 /* The rollback was caused by a
- communication failure */
-#define XA_RBDEADLOCK XA_RBBASE+2 /* A deadlock was detected */
-#define XA_RBINTEGRITY XA_RBBASE+3 /* A condition that violates the
- integrity of the resources was
- detected */
-#define XA_RBOTHER XA_RBBASE+4 /* The resource manager rolled back the
- transaction branch for a reason not
- on this list */
-#define XA_RBPROTO XA_RBBASE+5 /* A protocol error occurred in the
- resource manager */
-#define XA_RBTIMEOUT XA_RBBASE+6 /* A transaction branch took too long */
-#define XA_RBTRANSIENT XA_RBBASE+7 /* May retry the transaction branch */
-#define XA_RBEND XA_RBTRANSIENT /* The inclusive upper bound of the
- rollback codes */
-#define XA_NOMIGRATE 9 /* resumption must occur where
- suspension occurred */
-#define XA_HEURHAZ 8 /* the transaction branch may have
- been heuristically completed */
-#define XA_HEURCOM 7 /* the transaction branch has been
- heuristically committed */
-#define XA_HEURRB 6 /* the transaction branch has been
- heuristically rolled back */
-#define XA_HEURMIX 5 /* the transaction branch has been
- heuristically committed and rolled
- back */
-#define XA_RETRY 4 /* routine returned with no effect and
- may be re-issued */
-#define XA_RDONLY 3 /* the transaction branch was read-only
- and has been committed */
-#define XA_OK 0 /* normal execution */
-#define XAER_ASYNC -2 /* asynchronous operation already
- outstanding */
-#define XAER_RMERR -3 /* a resource manager error occurred in
- the transaction branch */
-#define XAER_NOTA -4 /* the XID is not valid */
-#define XAER_INVAL -5 /* invalid arguments were given */
-#define XAER_PROTO -6 /* routine invoked in an improper
- context */
-#define XAER_RMFAIL -7 /* resource manager unavailable */
-#define XAER_DUPID -8 /* the XID already exists */
-#define XAER_OUTSIDE -9 /* resource manager doing work outside
- transaction */
-#endif /* ifndef XA_H */
-/*
- * End of xa.h header
- */
diff --git a/bdb/java/src/com/sleepycat/db/Db.java b/bdb/java/src/com/sleepycat/db/Db.java
deleted file mode 100644
index de11e28414a..00000000000
--- a/bdb/java/src/com/sleepycat/db/Db.java
+++ /dev/null
@@ -1,710 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: Db.java,v 11.38 2000/12/31 19:26:22 bostic Exp $
- */
-
-package com.sleepycat.db;
-
-import java.io.OutputStream;
-import java.io.FileNotFoundException;
-
-/**
- *
- * @author Donald D. Anderson
- */
-public class Db
-{
- // All constant and flag values used with Db* classes are defined here.
-
- // Collectively, these constants are known by the name
- // "DBTYPE" in the documentation.
- //
- public static final int DB_BTREE = 1; // B+tree
- public static final int DB_HASH = 2; // Extended Linear Hashing.
- public static final int DB_RECNO = 3; // Fixed and variable-length records.
- public static final int DB_QUEUE = 4; // Queue
- public static final int DB_UNKNOWN = 5; // Figure it out on open.
-
- // Flags understood by DbEnv()
- //
- // Note: DB_CXX_NO_EXCEPTIONS will have no effect in Java.
- //
- public static final int DB_CXX_NO_EXCEPTIONS; // C++: return error values
- public static final int DB_CLIENT; // Open for a client environment.
-
- // Flags understood by Db()
- //
- public static final int DB_XA_CREATE; // Open in an XA environment.
-
- // Flags understood by Db.open(), DbEnv.open().
- //
- public static final int DB_CREATE; // O_CREAT: create file as necessary.
- public static final int DB_NOMMAP; // Don't mmap underlying file.
- public static final int DB_THREAD; // Free-thread DB package handles.
-
- // Flags understood by only DbEnv.open().
- //
- public static final int DB_LOCKDOWN; // Lock memory into physical core.
- public static final int DB_PRIVATE; // DB_ENV is process local.
-
- //
- // Flags understood by DbEnv.txn_begin().
- //
- public static final int DB_TXN_NOWAIT; // Do not wait for locks in this TXN.
- public static final int DB_TXN_SYNC; // Always sync log on commit.
-
- // Flags understood by DbEnv.set_flags().
- //
- public static final int DB_CDB_ALLDB; // In CDB, lock across environment.
-
- //
- // Flags understood by Db.open().
- //
- public static final int DB_EXCL; // Exclusive open (O_EXCL).
- public static final int DB_RDONLY; // Read-only (O_RDONLY).
- public static final int DB_TRUNCATE; // Discard existing DB.
- public static final int DB_UPGRADE; // Upgrade if necessary.
-
- //
- // DB (user visible) error return codes.
- //
- public static final int DB_INCOMPLETE = -30999; // Sync didn't finish.
- public static final int DB_KEYEMPTY = -30998; // The key/data pair was deleted or
- // was never created by the user.
- public static final int DB_KEYEXIST = -30997; // The key/data pair already exists.
- public static final int DB_LOCK_DEADLOCK = -30996; // Locker killed to resolve deadlock.
- public static final int DB_LOCK_NOTGRANTED = -30995; // Lock unavailable, no-wait set.
- public static final int DB_NOSERVER = -30994; // Server panic return.
- public static final int DB_NOSERVER_HOME = -30993; // Bad home sent to server.
- public static final int DB_NOSERVER_ID = -30992; // Bad ID sent to server.
- public static final int DB_NOTFOUND = -30991; // Key/data pair not found (EOF).
- public static final int DB_OLD_VERSION = -30990; // Out-of-date version.
- public static final int DB_RUNRECOVERY = -30989; // Panic return.
- public static final int DB_VERIFY_BAD = -30988; // Verify failed; bad format.
-
- //
- // Flags used by DbEnv.open and DbEnv.remove.
- //
- public static final int DB_FORCE; // Force (anything).
- public static final int DB_INIT_CDB; // Concurrent Access Methods.
- public static final int DB_INIT_LOCK; // Initialize locking.
- public static final int DB_INIT_LOG; // Initialize logging.
- public static final int DB_INIT_MPOOL; // Initialize mpool.
- public static final int DB_INIT_TXN; // Initialize transactions.
- public static final int DB_JOINENV; // Initialize all subsystems present.
- public static final int DB_RECOVER; // Run normal recovery.
- public static final int DB_RECOVER_FATAL; // Run catastrophic recovery.
- public static final int DB_SYSTEM_MEM; // Use system-backed memory.
- public static final int DB_TXN_NOSYNC; // Do not sync log on commit.
- public static final int DB_USE_ENVIRON; // Use the environment.
- public static final int DB_USE_ENVIRON_ROOT; // Use the environment if root.
-
- //
- // Operations values to the tx_recover() function.
- //
- public static final int DB_TXN_BACKWARD_ROLL = 1;
- public static final int DB_TXN_FORWARD_ROLL = 2;
- public static final int DB_TXN_OPENFILES = 3;
- public static final int DB_TXN_REDO = 4;
- public static final int DB_TXN_UNDO = 5;
-
- //
- // Verbose flags; used for DbEnv.set_verbose
- //
- public static final int DB_VERB_CHKPOINT; // List checkpoints.
- public static final int DB_VERB_DEADLOCK; // Deadlock detection information.
- public static final int DB_VERB_RECOVERY; // Recovery information.
- public static final int DB_VERB_WAITSFOR; // Dump waits-for table.
-
- //
- // Deadlock detector modes; used in the DBENV structure to configure the
- // locking subsystem.
- //
- public static final int DB_LOCK_NORUN;
- public static final int DB_LOCK_DEFAULT;
- public static final int DB_LOCK_OLDEST;
- public static final int DB_LOCK_RANDOM;
- public static final int DB_LOCK_YOUNGEST;
-
- //
- // Flags understood by only Db.set_flags.
- //
- public static final int DB_DUP; // Btree, Hash: duplicate keys.
- public static final int DB_DUPSORT; // Btree, Hash: duplicate keys.
- public static final int DB_RECNUM; // Btree: record numbers.
- public static final int DB_RENUMBER; // Recno: renumber on insert/delete.
- public static final int DB_REVSPLITOFF;// Btree: turn off reverse splits.
- public static final int DB_SNAPSHOT; // Recno: snapshot the input.
-
- //
- // Flags understood by only Db.join
- //
- public static final int DB_JOIN_NOSORT;// Don't try to optimize join.
-
- //
- // Flags understood by only Db.verify
- //
- public static final int DB_NOORDERCHK; // Skip order check; subdb w/ user func
- public static final int DB_ORDERCHKONLY;// Only perform an order check on subdb
- public static final int DB_SALVAGE; // Salvage what looks like data.
- public static final int DB_AGGRESSIVE; // Salvage anything which might be data.
-
- // Collectively, these constants are known by the name
- // "db_lockmode_t" in the documentation.
- //
- public static final int DB_LOCK_NG = 0; // Not granted.
- public static final int DB_LOCK_READ = 1; // Shared/read.
- public static final int DB_LOCK_WRITE = 2; // Exclusive/write.
- public static final int DB_LOCK_IWRITE = 3; // Intent exclusive/write.
- public static final int DB_LOCK_IREAD = 4; // Intent to share/read.
- public static final int DB_LOCK_IWR = 5; // Intent to read and write.
-
- // Collectively, these constants are known by the name
- // "db_lockop_t" in the documentation.
- //
- public static final int DB_LOCK_DUMP = 0; // Display held locks.
- public static final int DB_LOCK_GET = 1; // Get the lock.
- /* Not visible to API: DB_LOCK_INHERIT = 2 // Pass locks to parent. */
- public static final int DB_LOCK_PUT = 3; // Release the lock.
- public static final int DB_LOCK_PUT_ALL = 4;// Release locker's locks.
- public static final int DB_LOCK_PUT_OBJ = 5;// Release locker's locks on obj.
-
- // Flag values for DbLock.vec()
- public static final int DB_LOCK_NOWAIT; // Don't wait on unavailable lock.
-
- // Flag values for DbLock.detect()
- public static final int DB_LOCK_CONFLICT; // Run on any conflict.
-
- //
- // Flag values for DbLog.archive()
- //
- public static final int DB_ARCH_ABS; // Absolute pathnames.
- public static final int DB_ARCH_DATA; // Data files.
- public static final int DB_ARCH_LOG; // Log files.
-
- //
- // DB access method and cursor operation values.
- // Each value is an operation code to which
- // additional bit flags are added.
- //
- public static final int DB_AFTER; // Dbc.put()
- public static final int DB_APPEND; // Db.put()
- public static final int DB_BEFORE; // Dbc.put()
- public static final int DB_CACHED_COUNTS; // Db.stat()
- public static final int DB_CHECKPOINT; // DbLog.put(), DbLog.get()
- public static final int DB_CONSUME; // Db.get()
- public static final int DB_CONSUME_WAIT; // Db.get()
- public static final int DB_CURLSN; // DbLog.put()
- public static final int DB_CURRENT; // Dbc.get(), Dbc.put(), DbLog.get()
- public static final int DB_FIRST; // Dbc.get(), DbLog.get()
- public static final int DB_FLUSH; // DbLog.put()
- public static final int DB_GET_BOTH; // Db.get(), Dbc.get()
- public static final int DB_GET_RECNO; // Dbc.get()
- public static final int DB_JOIN_ITEM; // Dbc.get()
- public static final int DB_KEYFIRST; // Dbc.put()
- public static final int DB_KEYLAST; // Dbc.put()
- public static final int DB_LAST; // Dbc.get(), DbLog.get()
- public static final int DB_NEXT; // Dbc.get(), DbLog.get()
- public static final int DB_NEXT_DUP; // Dbc.get()
- public static final int DB_NEXT_NODUP; // Dbc.get()
- public static final int DB_NODUPDATA; // Don't permit duplicated data
- public static final int DB_NOOVERWRITE;// Db.put()
- public static final int DB_NOSYNC; // Db.close()
- public static final int DB_POSITION; // Dbc.dup()
- public static final int DB_PREV; // Dbc.get(), DbLog.get()
- public static final int DB_PREV_NODUP; // Dbc.get()
- public static final int DB_RECORDCOUNT;// Db.stat()
- public static final int DB_SET; // Dbc.get(), DbLog.get()
- public static final int DB_SET_RANGE; // Dbc.get()
- public static final int DB_SET_RECNO; // Dbc.get()
- public static final int DB_WRITECURSOR;// Db.cursor()
-
- // Other flags that can be added to an operation codes above.
- //
- public static final int DB_RMW; // Acquire write flag immediately.
-
- // Collectively, these values are used for Dbt flags
- //
- // Return in allocated memory.
- public static final int DB_DBT_MALLOC;
-
- // Partial put/get.
- public static final int DB_DBT_PARTIAL;
-
- // Return in realloc'd memory.
- public static final int DB_DBT_REALLOC;
-
- // Return in user's memory.
- public static final int DB_DBT_USERMEM;
-
- // Note: the env can be null
- //
- public Db(DbEnv env, int flags)
- throws DbException
- {
- constructor_env_ = env;
- _init(env, flags);
- if (env == null) {
- dbenv_ = new DbEnv(this);
- }
- else {
- dbenv_ = env;
- }
- dbenv_._add_db(this);
- }
-
- //
- // Our parent DbEnv is notifying us that the environment is closing.
- //
- /*package*/ void _notify_dbenv_close()
- {
- dbenv_ = null;
- _notify_internal();
- }
-
- private native void _init(DbEnv env, int flags)
- throws DbException;
-
- private native void _notify_internal();
-
- // methods
- //
-
- public synchronized int close(int flags)
- throws DbException
- {
- int err;
-
- dbenv_._remove_db(this);
- err = _close(flags);
- if (constructor_env_ == null) {
- dbenv_._notify_db_close();
- }
- return err;
- }
-
- public native int _close(int flags)
- throws DbException;
-
- public native Dbc cursor(DbTxn txnid, int flags)
- throws DbException;
-
- public native int del(DbTxn txnid, Dbt key, int flags)
- throws DbException;
-
- public native void err(int errcode, String message);
-
- public native void errx(String message);
-
- public native int fd()
- throws DbException;
-
- // overrides Object.finalize
- protected void finalize()
- throws Throwable
- {
- _finalize(dbenv_.errcall_, dbenv_.errpfx_);
- }
-
- protected native void _finalize(DbErrcall errcall, String errpfx)
- throws Throwable;
-
- // returns: 0, DB_NOTFOUND, or throws error
- public native int get(DbTxn txnid, Dbt key, Dbt data, int flags)
- throws DbException;
-
- public native boolean get_byteswapped();
-
- public native /*DBTYPE*/ int get_type();
-
- public native Dbc join(Dbc curslist[], int flags)
- throws DbException;
-
- public native void key_range(DbTxn txn, Dbt key,
- DbKeyRange range, int flags)
- throws DbException;
-
- public synchronized void open(String file, String database,
- /*DBTYPE*/ int type,
- int flags, int mode)
- throws DbException, FileNotFoundException
- {
- _open(file, database, type, flags, mode);
- }
-
- // (Internal)
- public native void _open(String file, String database,
- /*DBTYPE*/ int type,
- int flags, int mode)
- throws DbException, FileNotFoundException;
-
-
- // returns: 0, DB_KEYEXIST, or throws error
- public native int put(DbTxn txnid, Dbt key, Dbt data, int flags)
- throws DbException;
-
- public synchronized native void rename(String file, String database,
- String newname, int flags)
- throws DbException, FileNotFoundException;
-
- public synchronized native void remove(String file, String database,
- int flags)
- throws DbException, FileNotFoundException;
-
- // Comparison function.
- public void set_append_recno(DbAppendRecno append_recno)
- throws DbException
- {
- append_recno_ = append_recno;
- append_recno_changed(append_recno);
- }
-
- // (Internal)
- private native void append_recno_changed(DbAppendRecno append_recno)
- throws DbException;
-
- // Comparison function.
- public void set_bt_compare(DbBtreeCompare bt_compare)
- throws DbException
- {
- bt_compare_ = bt_compare;
- bt_compare_changed(bt_compare);
- }
-
- // (Internal)
- private native void bt_compare_changed(DbBtreeCompare bt_compare)
- throws DbException;
-
- // Maximum keys per page.
- public native void set_bt_maxkey(int maxkey)
- throws DbException;
-
- // Minimum keys per page.
- public native void set_bt_minkey(int minkey)
- throws DbException;
-
- // Prefix function.
- public void set_bt_prefix(DbBtreePrefix bt_prefix)
- throws DbException
- {
- bt_prefix_ = bt_prefix;
- bt_prefix_changed(bt_prefix);
- }
-
- // (Internal)
- private native void bt_prefix_changed(DbBtreePrefix bt_prefix)
- throws DbException;
-
- // Set cache size
- public native void set_cachesize(int gbytes, int bytes, int ncaches)
- throws DbException;
-
- // Duplication resolution
- public void set_dup_compare(DbDupCompare dup_compare)
- throws DbException
- {
- dup_compare_ = dup_compare;
- dup_compare_changed(dup_compare);
- }
-
- // (Internal)
- private native void dup_compare_changed(DbDupCompare dup_compare)
- throws DbException;
-
- // Error message callback.
- public void set_errcall(DbErrcall errcall)
- {
- if (dbenv_ != null)
- dbenv_.set_errcall(errcall);
- }
-
- // Error stream.
- public void set_error_stream(OutputStream s)
- {
- DbOutputStreamErrcall errcall = new DbOutputStreamErrcall(s);
- set_errcall(errcall);
- }
-
- // Error message prefix.
- public void set_errpfx(String errpfx)
- {
- if (dbenv_ != null)
- dbenv_.set_errpfx(errpfx);
- }
-
-
- // Feedback
- public void set_feedback(DbFeedback feedback)
- throws DbException
- {
- feedback_ = feedback;
- feedback_changed(feedback);
- }
-
- // (Internal)
- private native void feedback_changed(DbFeedback feedback)
- throws DbException;
-
- // Flags.
- public native void set_flags(/*u_int32_t*/ int flags);
-
- // Fill factor.
- public native void set_h_ffactor(/*unsigned*/ int h_ffactor);
-
- // Hash function.
- public void set_h_hash(DbHash h_hash)
- throws DbException
- {
- h_hash_ = h_hash;
- hash_changed(h_hash);
- }
-
- // (Internal)
- private native void hash_changed(DbHash hash)
- throws DbException;
-
- // Number of elements.
- public native void set_h_nelem(/*unsigned*/ int h_nelem);
-
- // Byte order.
- public native void set_lorder(int lorder);
-
- // Underlying page size.
- public native void set_pagesize(/*size_t*/ long pagesize);
-
- // Variable-length delimiting byte.
- public native void set_re_delim(int re_delim);
-
- // Length for fixed-length records.
- public native void set_re_len(/*u_int32_t*/ int re_len);
-
- // Fixed-length padding byte.
- public native void set_re_pad(int re_pad);
-
- // Source file name.
- public native void set_re_source(String re_source);
-
- // Extent size of Queue
- public native void set_q_extentsize(/*u_int32_t*/ int extent_size);
-
- // returns a DbBtreeStat or DbHashStat
- public native Object stat(int flags)
- throws DbException;
-
- public native int sync(int flags)
- throws DbException;
-
- public native void upgrade(String name, int flags)
- throws DbException;
-
- public native void verify(String name, String subdb,
- OutputStream outstr, int flags)
- throws DbException;
-
- ////////////////////////////////////////////////////////////////
- //
- // private data
- //
- private long private_dbobj_ = 0;
- private long private_info_ = 0;
- private DbEnv dbenv_ = null;
- private DbEnv constructor_env_ = null;
- private DbFeedback feedback_ = null;
- private DbAppendRecno append_recno_ = null;
- private DbBtreeCompare bt_compare_ = null;
- private DbBtreePrefix bt_prefix_ = null;
- private DbDupCompare dup_compare_ = null;
- private DbHash h_hash_ = null;
-
- ////////////////////////////////////////////////////////////////
- //
- // static methods and data that implement
- // loading the native library and doing any
- // extra sanity checks on startup.
- //
- private static boolean already_loaded_ = false;
-
- public static void load_db()
- {
- if (already_loaded_)
- return;
-
- // An alternate library name can be specified via a property.
- //
- String overrideLibname = System.getProperty("sleepycat.db.libname");
- if (overrideLibname != null) {
- System.loadLibrary(overrideLibname);
- }
- else {
- String os = System.getProperty("os.name");
- if (os != null && os.startsWith("Windows")) {
- // library name is "libdb_java30.dll" (for example) on Win/*
- System.loadLibrary("libdb_java" +
- DbConstants.DB_VERSION_MAJOR +
- DbConstants.DB_VERSION_MINOR);
- }
- else {
- // library name is "libdb_java-3.0.so" (for example) on UNIX
- // Note: "db_java" isn't good enough;
- // some Unixes require us to use the explicit SONAME.
- System.loadLibrary("db_java-" +
- DbConstants.DB_VERSION_MAJOR + "." +
- DbConstants.DB_VERSION_MINOR);
- }
- }
-
- already_loaded_ = true;
- }
-
- static private native void one_time_init();
-
- static private void check_constant(int c1, int c2)
- {
- if (c1 != c2) {
- System.err.println("Db: constant mismatch");
- System.exit(1);
- }
- }
-
- static {
- Db.load_db();
-
- // Note: constant values are stored in DbConstants, which
- // is automatically generated. Initializing constants in
- // static code insulates users from the possibility of
- // changing constants.
- //
- DB_CXX_NO_EXCEPTIONS = DbConstants.DB_CXX_NO_EXCEPTIONS;
- DB_CLIENT = DbConstants.DB_CLIENT;
- DB_XA_CREATE = DbConstants.DB_XA_CREATE;
-
- DB_CREATE = DbConstants.DB_CREATE;
- DB_NOMMAP = DbConstants.DB_NOMMAP;
- DB_THREAD = DbConstants.DB_THREAD;
-
- DB_LOCKDOWN = DbConstants.DB_LOCKDOWN;
- DB_PRIVATE = DbConstants.DB_PRIVATE;
- DB_TXN_NOWAIT = DbConstants.DB_TXN_NOWAIT;
- DB_TXN_SYNC = DbConstants.DB_TXN_SYNC;
- DB_CDB_ALLDB = DbConstants.DB_CDB_ALLDB;
-
- DB_EXCL = DbConstants.DB_EXCL;
- DB_RDONLY = DbConstants.DB_RDONLY;
- DB_TRUNCATE = DbConstants.DB_TRUNCATE;
- DB_UPGRADE = DbConstants.DB_UPGRADE;
-
- // These constants are not assigned, but rather checked.
- // Having initialized constants for these values allows
- // them to be used as case values in switch statements.
- //
- check_constant(DB_INCOMPLETE, DbConstants.DB_INCOMPLETE);
- check_constant(DB_KEYEMPTY, DbConstants.DB_KEYEMPTY);
- check_constant(DB_KEYEXIST, DbConstants.DB_KEYEXIST);
- check_constant(DB_LOCK_DEADLOCK, DbConstants.DB_LOCK_DEADLOCK);
- check_constant(DB_LOCK_NOTGRANTED, DbConstants.DB_LOCK_NOTGRANTED);
- check_constant(DB_NOSERVER, DbConstants.DB_NOSERVER);
- check_constant(DB_NOSERVER_HOME, DbConstants.DB_NOSERVER_HOME);
- check_constant(DB_NOSERVER_ID, DbConstants.DB_NOSERVER_ID);
- check_constant(DB_NOTFOUND, DbConstants.DB_NOTFOUND);
- check_constant(DB_OLD_VERSION, DbConstants.DB_OLD_VERSION);
- check_constant(DB_RUNRECOVERY, DbConstants.DB_RUNRECOVERY);
- check_constant(DB_VERIFY_BAD, DbConstants.DB_VERIFY_BAD);
- check_constant(DB_TXN_BACKWARD_ROLL, DbConstants.DB_TXN_BACKWARD_ROLL);
- check_constant(DB_TXN_FORWARD_ROLL, DbConstants.DB_TXN_FORWARD_ROLL);
- check_constant(DB_TXN_OPENFILES, DbConstants.DB_TXN_OPENFILES);
- check_constant(DB_TXN_REDO, DbConstants.DB_TXN_REDO);
- check_constant(DB_TXN_UNDO, DbConstants.DB_TXN_UNDO);
-
- DB_FORCE = DbConstants.DB_FORCE;
- DB_INIT_CDB = DbConstants.DB_INIT_CDB;
- DB_INIT_LOCK = DbConstants.DB_INIT_LOCK;
- DB_INIT_LOG = DbConstants.DB_INIT_LOG;
- DB_INIT_MPOOL = DbConstants.DB_INIT_MPOOL;
- DB_INIT_TXN = DbConstants.DB_INIT_TXN;
- DB_JOINENV = DbConstants.DB_JOINENV;
- DB_RECOVER = DbConstants.DB_RECOVER;
- DB_RECOVER_FATAL = DbConstants.DB_RECOVER_FATAL;
- DB_SYSTEM_MEM = DbConstants.DB_SYSTEM_MEM;
- DB_TXN_NOSYNC = DbConstants.DB_TXN_NOSYNC;
- DB_USE_ENVIRON = DbConstants.DB_USE_ENVIRON;
- DB_USE_ENVIRON_ROOT = DbConstants.DB_USE_ENVIRON_ROOT;
-
- DB_VERB_CHKPOINT = DbConstants.DB_VERB_CHKPOINT;
- DB_VERB_DEADLOCK = DbConstants.DB_VERB_DEADLOCK;
- DB_VERB_RECOVERY = DbConstants.DB_VERB_RECOVERY;
- DB_VERB_WAITSFOR = DbConstants.DB_VERB_WAITSFOR;
-
- DB_LOCK_NORUN = DbConstants.DB_LOCK_NORUN;
- DB_LOCK_DEFAULT = DbConstants.DB_LOCK_DEFAULT;
- DB_LOCK_OLDEST = DbConstants.DB_LOCK_OLDEST;
- DB_LOCK_RANDOM = DbConstants.DB_LOCK_RANDOM;
- DB_LOCK_YOUNGEST = DbConstants.DB_LOCK_YOUNGEST;
-
- DB_DUP = DbConstants.DB_DUP;
- DB_DUPSORT = DbConstants.DB_DUPSORT;
- DB_RECNUM = DbConstants.DB_RECNUM;
- DB_RENUMBER = DbConstants.DB_RENUMBER;
- DB_REVSPLITOFF = DbConstants.DB_REVSPLITOFF;
- DB_SNAPSHOT = DbConstants.DB_SNAPSHOT;
-
- DB_JOIN_NOSORT = DbConstants.DB_JOIN_NOSORT;
-
- DB_NOORDERCHK = DbConstants.DB_NOORDERCHK;
- DB_ORDERCHKONLY = DbConstants.DB_ORDERCHKONLY;
- DB_SALVAGE = DbConstants.DB_SALVAGE;
- DB_AGGRESSIVE = DbConstants.DB_AGGRESSIVE;
-
- DB_LOCK_NOWAIT = DbConstants.DB_LOCK_NOWAIT;
- DB_LOCK_CONFLICT = DbConstants.DB_LOCK_CONFLICT;
-
- DB_ARCH_ABS = DbConstants.DB_ARCH_ABS;
- DB_ARCH_DATA = DbConstants.DB_ARCH_DATA;
- DB_ARCH_LOG = DbConstants.DB_ARCH_LOG;
-
- DB_AFTER = DbConstants.DB_AFTER;
- DB_APPEND = DbConstants.DB_APPEND;
- DB_BEFORE = DbConstants.DB_BEFORE;
- DB_CACHED_COUNTS = DbConstants.DB_CACHED_COUNTS;
- DB_CHECKPOINT = DbConstants.DB_CHECKPOINT;
- DB_CONSUME = DbConstants.DB_CONSUME;
- DB_CONSUME_WAIT = DbConstants.DB_CONSUME_WAIT;
- DB_CURLSN = DbConstants.DB_CURLSN;
- DB_CURRENT = DbConstants.DB_CURRENT;
- DB_FIRST = DbConstants.DB_FIRST;
- DB_FLUSH = DbConstants.DB_FLUSH;
- DB_GET_BOTH = DbConstants.DB_GET_BOTH;
- DB_GET_RECNO = DbConstants.DB_GET_RECNO;
- DB_JOIN_ITEM = DbConstants.DB_JOIN_ITEM;
- DB_KEYFIRST = DbConstants.DB_KEYFIRST;
- DB_KEYLAST = DbConstants.DB_KEYLAST;
- DB_LAST = DbConstants.DB_LAST;
- DB_NEXT = DbConstants.DB_NEXT;
- DB_NEXT_DUP = DbConstants.DB_NEXT_DUP;
- DB_NEXT_NODUP = DbConstants.DB_NEXT_NODUP;
- DB_NODUPDATA = DbConstants.DB_NODUPDATA;
- DB_NOOVERWRITE = DbConstants.DB_NOOVERWRITE;
- DB_NOSYNC = DbConstants.DB_NOSYNC;
- DB_POSITION = DbConstants.DB_POSITION;
- DB_PREV = DbConstants.DB_PREV;
- DB_PREV_NODUP = DbConstants.DB_PREV_NODUP;
- DB_RECORDCOUNT = DbConstants.DB_RECORDCOUNT;
- DB_RMW = DbConstants.DB_RMW;
- DB_SET = DbConstants.DB_SET;
- DB_SET_RANGE = DbConstants.DB_SET_RANGE;
- DB_SET_RECNO = DbConstants.DB_SET_RECNO;
- DB_WRITECURSOR = DbConstants.DB_WRITECURSOR;
-
- DB_DBT_MALLOC = DbConstants.DB_DBT_MALLOC;
- DB_DBT_PARTIAL = DbConstants.DB_DBT_PARTIAL;
- DB_DBT_REALLOC = DbConstants.DB_DBT_REALLOC;
- DB_DBT_USERMEM = DbConstants.DB_DBT_USERMEM;
-
- one_time_init();
- }
-}
-
-// end of Db.java
diff --git a/bdb/java/src/com/sleepycat/db/Db.java.in b/bdb/java/src/com/sleepycat/db/Db.java.in
new file mode 100644
index 00000000000..df311795f54
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/Db.java.in
@@ -0,0 +1,761 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: Db.java,v 11.110 2002/09/09 20:47:31 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+import java.io.OutputStream;
+import java.io.FileNotFoundException;
+
+/**
+ *
+ * @author Donald D. Anderson
+ */
+public class Db
+{
+ // BEGIN-JAVA-SPECIAL-CONSTANTS
+ /* DO NOT EDIT: automatically built by dist/s_java. */
+ public static final int DB_BTREE = 1;
+ public static final int DB_DONOTINDEX = -30999;
+ public static final int DB_HASH = 2;
+ public static final int DB_KEYEMPTY = -30998;
+ public static final int DB_KEYEXIST = -30997;
+ public static final int DB_LOCK_DEADLOCK = -30996;
+ public static final int DB_LOCK_NOTGRANTED = -30995;
+ public static final int DB_NOSERVER = -30994;
+ public static final int DB_NOSERVER_HOME = -30993;
+ public static final int DB_NOSERVER_ID = -30992;
+ public static final int DB_NOTFOUND = -30991;
+ public static final int DB_OLD_VERSION = -30990;
+ public static final int DB_PAGE_NOTFOUND = -30989;
+ public static final int DB_QUEUE = 4;
+ public static final int DB_RECNO = 3;
+ public static final int DB_REP_DUPMASTER = -30988;
+ public static final int DB_REP_HOLDELECTION = -30987;
+ public static final int DB_REP_NEWMASTER = -30986;
+ public static final int DB_REP_NEWSITE = -30985;
+ public static final int DB_REP_OUTDATED = -30984;
+ public static final int DB_RUNRECOVERY = -30982;
+ public static final int DB_SECONDARY_BAD = -30981;
+ public static final int DB_TXN_ABORT = 0;
+ public static final int DB_TXN_APPLY = 1;
+ public static final int DB_TXN_BACKWARD_ROLL = 3;
+ public static final int DB_TXN_FORWARD_ROLL = 4;
+ public static final int DB_TXN_PRINT = 8;
+ public static final int DB_UNKNOWN = 5;
+ public static final int DB_VERIFY_BAD = -30980;
+ public static final int DB_AFTER;
+ public static final int DB_AGGRESSIVE;
+ public static final int DB_APPEND;
+ public static final int DB_ARCH_ABS;
+ public static final int DB_ARCH_DATA;
+ public static final int DB_ARCH_LOG;
+ public static final int DB_AUTO_COMMIT;
+ public static final int DB_BEFORE;
+ public static final int DB_CACHED_COUNTS;
+ public static final int DB_CDB_ALLDB;
+ public static final int DB_CHKSUM_SHA1;
+ public static final int DB_CLIENT;
+ public static final int DB_CONSUME;
+ public static final int DB_CONSUME_WAIT;
+ public static final int DB_CREATE;
+ public static final int DB_CURRENT;
+ public static final int DB_CXX_NO_EXCEPTIONS;
+ public static final int DB_DBT_MALLOC;
+ public static final int DB_DBT_PARTIAL;
+ public static final int DB_DBT_REALLOC;
+ public static final int DB_DBT_USERMEM;
+ public static final int DB_DIRECT;
+ public static final int DB_DIRECT_DB;
+ public static final int DB_DIRECT_LOG;
+ public static final int DB_DIRTY_READ;
+ public static final int DB_DUP;
+ public static final int DB_DUPSORT;
+ public static final int DB_EID_BROADCAST;
+ public static final int DB_EID_INVALID;
+ public static final int DB_ENCRYPT;
+ public static final int DB_ENCRYPT_AES;
+ public static final int DB_EXCL;
+ public static final int DB_FAST_STAT;
+ public static final int DB_FIRST;
+ public static final int DB_FLUSH;
+ public static final int DB_FORCE;
+ public static final int DB_GET_BOTH;
+ public static final int DB_GET_BOTH_RANGE;
+ public static final int DB_GET_RECNO;
+ public static final int DB_INIT_CDB;
+ public static final int DB_INIT_LOCK;
+ public static final int DB_INIT_LOG;
+ public static final int DB_INIT_MPOOL;
+ public static final int DB_INIT_TXN;
+ public static final int DB_JOINENV;
+ public static final int DB_JOIN_ITEM;
+ public static final int DB_JOIN_NOSORT;
+ public static final int DB_KEYFIRST;
+ public static final int DB_KEYLAST;
+ public static final int DB_LAST;
+ public static final int DB_LOCKDOWN;
+ public static final int DB_LOCK_DEFAULT;
+ public static final int DB_LOCK_EXPIRE;
+ public static final int DB_LOCK_GET;
+ public static final int DB_LOCK_GET_TIMEOUT;
+ public static final int DB_LOCK_IREAD;
+ public static final int DB_LOCK_IWR;
+ public static final int DB_LOCK_IWRITE;
+ public static final int DB_LOCK_MAXLOCKS;
+ public static final int DB_LOCK_MINLOCKS;
+ public static final int DB_LOCK_MINWRITE;
+ public static final int DB_LOCK_NOWAIT;
+ public static final int DB_LOCK_OLDEST;
+ public static final int DB_LOCK_PUT;
+ public static final int DB_LOCK_PUT_ALL;
+ public static final int DB_LOCK_PUT_OBJ;
+ public static final int DB_LOCK_RANDOM;
+ public static final int DB_LOCK_READ;
+ public static final int DB_LOCK_TIMEOUT;
+ public static final int DB_LOCK_WRITE;
+ public static final int DB_LOCK_YOUNGEST;
+ public static final int DB_MULTIPLE;
+ public static final int DB_MULTIPLE_KEY;
+ public static final int DB_NEXT;
+ public static final int DB_NEXT_DUP;
+ public static final int DB_NEXT_NODUP;
+ public static final int DB_NODUPDATA;
+ public static final int DB_NOLOCKING;
+ public static final int DB_NOMMAP;
+ public static final int DB_NOORDERCHK;
+ public static final int DB_NOOVERWRITE;
+ public static final int DB_NOPANIC;
+ public static final int DB_NOSYNC;
+ public static final int DB_ODDFILESIZE;
+ public static final int DB_ORDERCHKONLY;
+ public static final int DB_OVERWRITE;
+ public static final int DB_PANIC_ENVIRONMENT;
+ public static final int DB_POSITION;
+ public static final int DB_PREV;
+ public static final int DB_PREV_NODUP;
+ public static final int DB_PRINTABLE;
+ public static final int DB_PRIORITY_DEFAULT;
+ public static final int DB_PRIORITY_HIGH;
+ public static final int DB_PRIORITY_LOW;
+ public static final int DB_PRIORITY_VERY_HIGH;
+ public static final int DB_PRIORITY_VERY_LOW;
+ public static final int DB_PRIVATE;
+ public static final int DB_RDONLY;
+ public static final int DB_RECNUM;
+ public static final int DB_RECORDCOUNT;
+ public static final int DB_RECOVER;
+ public static final int DB_RECOVER_FATAL;
+ public static final int DB_REGION_INIT;
+ public static final int DB_RENUMBER;
+ public static final int DB_REP_CLIENT;
+ public static final int DB_REP_LOGSONLY;
+ public static final int DB_REP_MASTER;
+ public static final int DB_REP_PERMANENT;
+ public static final int DB_REP_UNAVAIL;
+ public static final int DB_REVSPLITOFF;
+ public static final int DB_RMW;
+ public static final int DB_SALVAGE;
+ public static final int DB_SET;
+ public static final int DB_SET_LOCK_TIMEOUT;
+ public static final int DB_SET_RANGE;
+ public static final int DB_SET_RECNO;
+ public static final int DB_SET_TXN_TIMEOUT;
+ public static final int DB_SNAPSHOT;
+ public static final int DB_STAT_CLEAR;
+ public static final int DB_SYSTEM_MEM;
+ public static final int DB_THREAD;
+ public static final int DB_TRUNCATE;
+ public static final int DB_TXN_NOSYNC;
+ public static final int DB_TXN_NOWAIT;
+ public static final int DB_TXN_SYNC;
+ public static final int DB_TXN_WRITE_NOSYNC;
+ public static final int DB_UPGRADE;
+ public static final int DB_USE_ENVIRON;
+ public static final int DB_USE_ENVIRON_ROOT;
+ public static final int DB_VERB_CHKPOINT;
+ public static final int DB_VERB_DEADLOCK;
+ public static final int DB_VERB_RECOVERY;
+ public static final int DB_VERB_REPLICATION;
+ public static final int DB_VERB_WAITSFOR;
+ public static final int DB_VERIFY;
+ public static final int DB_VERSION_MAJOR;
+ public static final int DB_VERSION_MINOR;
+ public static final int DB_VERSION_PATCH;
+ public static final int DB_WRITECURSOR;
+ public static final int DB_XA_CREATE;
+ public static final int DB_XIDDATASIZE;
+ public static final int DB_YIELDCPU;
+ // END-JAVA-SPECIAL-CONSTANTS
+
+ // Note: the env can be null
+ //
+ public Db(DbEnv env, int flags)
+ throws DbException
+ {
+ constructor_env_ = env;
+ _init(env, flags);
+ if (env == null) {
+ dbenv_ = new DbEnv(this);
+ }
+ else {
+ dbenv_ = env;
+ }
+ dbenv_._add_db(this);
+ }
+
+ //
+ // Our parent DbEnv is notifying us that the environment is closing.
+ //
+ /*package*/ void _notify_dbenv_close()
+ {
+ dbenv_ = null;
+ _notify_internal();
+ }
+
+ private native void _init(DbEnv env, int flags)
+ throws DbException;
+
+ private native void _notify_internal();
+
+ // methods
+ //
+
+ public synchronized void associate(DbTxn txn, Db secondary,
+ DbSecondaryKeyCreate key_creator,
+ int flags)
+ throws DbException
+ {
+ secondary.secondary_key_create_ = key_creator;
+ _associate(txn, secondary, key_creator, flags);
+ }
+
+ public native void _associate(DbTxn txn, Db secondary,
+ DbSecondaryKeyCreate key_creator, int flags)
+ throws DbException;
+
+ public synchronized int close(int flags)
+ throws DbException
+ {
+ try {
+ dbenv_._remove_db(this);
+ return _close(flags);
+ }
+ finally {
+ if (constructor_env_ == null) {
+ dbenv_._notify_db_close();
+ }
+ dbenv_ = null;
+ }
+ }
+
+ public native int _close(int flags)
+ throws DbException;
+
+ public native Dbc cursor(DbTxn txnid, int flags)
+ throws DbException;
+
+ public native int del(DbTxn txnid, Dbt key, int flags)
+ throws DbException;
+
+ public native void err(int errcode, String message);
+
+ public native void errx(String message);
+
+ public native int fd()
+ throws DbException;
+
+ // overrides Object.finalize
+ protected void finalize()
+ throws Throwable
+ {
+ if (dbenv_ == null)
+ _finalize(null, null);
+ else
+ _finalize(dbenv_.errcall_, dbenv_.errpfx_);
+ }
+
+ protected native void _finalize(DbErrcall errcall, String errpfx)
+ throws Throwable;
+
+ // returns: 0, DB_NOTFOUND, or throws error
+ public native int get(DbTxn txnid, Dbt key, Dbt data, int flags)
+ throws DbException;
+
+ public native boolean get_byteswapped();
+
+ public native /*DBTYPE*/ int get_type();
+
+ public native Dbc join(Dbc curslist[], int flags)
+ throws DbException;
+
+ public native void key_range(DbTxn txnid, Dbt key,
+ DbKeyRange range, int flags)
+ throws DbException;
+
+ public synchronized void open(DbTxn txnid, String file,
+ String database, /*DBTYPE*/ int type,
+ int flags, int mode)
+ throws DbException, FileNotFoundException
+ {
+ _open(txnid, file, database, type, flags, mode);
+ }
+
+ // (Internal)
+ public native void _open(DbTxn txnid, String file,
+ String database, /*DBTYPE*/ int type,
+ int flags, int mode)
+ throws DbException, FileNotFoundException;
+
+
+ // returns: 0, DB_NOTFOUND, or throws error
+ public native int pget(DbTxn txnid, Dbt key, Dbt pkey, Dbt data, int flags)
+ throws DbException;
+
+ // returns: 0, DB_KEYEXIST, or throws error
+ public native int put(DbTxn txnid, Dbt key, Dbt data, int flags)
+ throws DbException;
+
+ public synchronized void rename(String file, String database,
+ String newname, int flags)
+ throws DbException, FileNotFoundException
+ {
+ try {
+ _rename(file, database, newname, flags);
+ }
+ finally {
+ if (constructor_env_ == null) {
+ dbenv_._notify_db_close();
+ }
+ dbenv_ = null;
+ }
+ }
+
+ public native void _rename(String file, String database,
+ String newname, int flags)
+ throws DbException, FileNotFoundException;
+
+
+ public synchronized void remove(String file,
+ String database, int flags)
+ throws DbException, FileNotFoundException
+ {
+ try {
+ _remove(file, database, flags);
+ }
+ finally {
+ if (constructor_env_ == null) {
+ dbenv_._notify_db_close();
+ }
+ dbenv_ = null;
+ }
+ }
+
+ public native void _remove(String file, String database,
+ int flags)
+ throws DbException, FileNotFoundException;
+
+ // Comparison function.
+ public void set_append_recno(DbAppendRecno append_recno)
+ throws DbException
+ {
+ append_recno_ = append_recno;
+ append_recno_changed(append_recno);
+ }
+
+ // (Internal)
+ private native void append_recno_changed(DbAppendRecno append_recno)
+ throws DbException;
+
+ // Comparison function.
+ public void set_bt_compare(DbBtreeCompare bt_compare)
+ throws DbException
+ {
+ bt_compare_ = bt_compare;
+ bt_compare_changed(bt_compare);
+ }
+
+ // (Internal)
+ private native void bt_compare_changed(DbBtreeCompare bt_compare)
+ throws DbException;
+
+ // Maximum keys per page.
+ public native void set_bt_maxkey(int maxkey)
+ throws DbException;
+
+ // Minimum keys per page.
+ public native void set_bt_minkey(int minkey)
+ throws DbException;
+
+ // Prefix function.
+ public void set_bt_prefix(DbBtreePrefix bt_prefix)
+ throws DbException
+ {
+ bt_prefix_ = bt_prefix;
+ bt_prefix_changed(bt_prefix);
+ }
+
+ // (Internal)
+ private native void bt_prefix_changed(DbBtreePrefix bt_prefix)
+ throws DbException;
+
+ // Set cache size
+ public native void set_cachesize(int gbytes, int bytes, int ncaches)
+ throws DbException;
+
+ // Set cache priority
+ public native void set_cache_priority(/* DB_CACHE_PRIORITY */ int priority)
+ throws DbException;
+
+ // Duplication resolution
+ public void set_dup_compare(DbDupCompare dup_compare)
+ throws DbException
+ {
+ dup_compare_ = dup_compare;
+ dup_compare_changed(dup_compare);
+ }
+
+ // (Internal)
+ private native void dup_compare_changed(DbDupCompare dup_compare)
+ throws DbException;
+
+ // Encryption
+ public native void set_encrypt(String passwd, /*u_int32_t*/ int flags)
+ throws DbException;
+
+ // Error message callback.
+ public void set_errcall(DbErrcall errcall)
+ {
+ if (dbenv_ != null)
+ dbenv_.set_errcall(errcall);
+ }
+
+ // Error stream.
+ public void set_error_stream(OutputStream s)
+ {
+ DbOutputStreamErrcall errcall = new DbOutputStreamErrcall(s);
+ set_errcall(errcall);
+ }
+
+ // Error message prefix.
+ public void set_errpfx(String errpfx)
+ {
+ if (dbenv_ != null)
+ dbenv_.set_errpfx(errpfx);
+ }
+
+
+ // Feedback
+ public void set_feedback(DbFeedback feedback)
+ throws DbException
+ {
+ feedback_ = feedback;
+ feedback_changed(feedback);
+ }
+
+ // (Internal)
+ private native void feedback_changed(DbFeedback feedback)
+ throws DbException;
+
+ // Flags.
+ public native void set_flags(/*u_int32_t*/ int flags)
+ throws DbException;
+
+ // Internal - only intended for testing purposes in the Java RPC server
+ public native int get_flags_raw()
+ throws DbException;
+
+ // Fill factor.
+ public native void set_h_ffactor(/*unsigned*/ int h_ffactor)
+ throws DbException;
+
+ // Hash function.
+ public void set_h_hash(DbHash h_hash)
+ throws DbException
+ {
+ h_hash_ = h_hash;
+ hash_changed(h_hash);
+ }
+
+ // (Internal)
+ private native void hash_changed(DbHash hash)
+ throws DbException;
+
+ // Number of elements.
+ public native void set_h_nelem(/*unsigned*/ int h_nelem)
+ throws DbException;
+
+ // Byte order.
+ public native void set_lorder(int lorder)
+ throws DbException;
+
+ // Underlying page size.
+ public native void set_pagesize(/*size_t*/ long pagesize)
+ throws DbException;
+
+ // Variable-length delimiting byte.
+ public native void set_re_delim(int re_delim)
+ throws DbException;
+
+ // Length for fixed-length records.
+ public native void set_re_len(/*u_int32_t*/ int re_len)
+ throws DbException;
+
+ // Fixed-length padding byte.
+ public native void set_re_pad(int re_pad)
+ throws DbException;
+
+ // Source file name.
+ public native void set_re_source(String re_source)
+ throws DbException;
+
+ // Extent size of Queue
+ public native void set_q_extentsize(/*u_int32_t*/ int extent_size)
+ throws DbException;
+
+ // returns a DbBtreeStat or DbHashStat
+ public native Object stat(int flags)
+ throws DbException;
+
+ public native void sync(int flags)
+ throws DbException;
+
+ public native int truncate(DbTxn txnid, int flags)
+ throws DbException;
+
+ public native void upgrade(String name, int flags)
+ throws DbException;
+
+ public native void verify(String name, String subdb,
+ OutputStream outstr, int flags)
+ throws DbException;
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // private data
+ //
+ private long private_dbobj_ = 0;
+ private long private_info_ = 0;
+ private DbEnv dbenv_ = null;
+ private DbEnv constructor_env_ = null;
+ private DbFeedback feedback_ = null;
+ private DbAppendRecno append_recno_ = null;
+ private DbBtreeCompare bt_compare_ = null;
+ private DbBtreePrefix bt_prefix_ = null;
+ private DbDupCompare dup_compare_ = null;
+ private DbHash h_hash_ = null;
+ private DbSecondaryKeyCreate secondary_key_create_ = null;
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // static methods and data that implement
+ // loading the native library and doing any
+ // extra sanity checks on startup.
+ //
+ private static boolean already_loaded_ = false;
+
+ public static void load_db()
+ {
+ if (already_loaded_)
+ return;
+
+ // An alternate library name can be specified via a property.
+ //
+ String override;
+
+ if ((override = System.getProperty("sleepycat.db.libfile")) != null) {
+ System.load(override);
+ }
+ else if ((override = System.getProperty("sleepycat.db.libname")) != null) {
+ System.loadLibrary(override);
+ }
+ else {
+ String os = System.getProperty("os.name");
+ if (os != null && os.startsWith("Windows")) {
+ // library name is "libdb_java30.dll" (for example) on Win/*
+ System.loadLibrary("libdb_java" +
+ DbConstants.DB_VERSION_MAJOR +
+ DbConstants.DB_VERSION_MINOR);
+ }
+ else {
+ // library name is "libdb_java-3.0.so" (for example) on UNIX
+ // Note: "db_java" isn't good enough;
+ // some Unixes require us to use the explicit SONAME.
+ System.loadLibrary("db_java-" +
+ DbConstants.DB_VERSION_MAJOR + "." +
+ DbConstants.DB_VERSION_MINOR);
+ }
+ }
+
+ already_loaded_ = true;
+ }
+
+ static private native void one_time_init();
+
+ static private void check_constant(int c1, int c2)
+ {
+ if (c1 != c2) {
+ System.err.println("Db: constant mismatch");
+ Thread.dumpStack();
+ System.exit(1);
+ }
+ }
+
+ static {
+ Db.load_db();
+
+ // BEGIN-JAVA-CONSTANT-INITIALIZATION
+ /* DO NOT EDIT: automatically built by dist/s_java. */
+ DB_AFTER = DbConstants.DB_AFTER;
+ DB_AGGRESSIVE = DbConstants.DB_AGGRESSIVE;
+ DB_APPEND = DbConstants.DB_APPEND;
+ DB_ARCH_ABS = DbConstants.DB_ARCH_ABS;
+ DB_ARCH_DATA = DbConstants.DB_ARCH_DATA;
+ DB_ARCH_LOG = DbConstants.DB_ARCH_LOG;
+ DB_AUTO_COMMIT = DbConstants.DB_AUTO_COMMIT;
+ DB_BEFORE = DbConstants.DB_BEFORE;
+ DB_CACHED_COUNTS = DbConstants.DB_CACHED_COUNTS;
+ DB_CDB_ALLDB = DbConstants.DB_CDB_ALLDB;
+ DB_CHKSUM_SHA1 = DbConstants.DB_CHKSUM_SHA1;
+ DB_CLIENT = DbConstants.DB_CLIENT;
+ DB_CONSUME = DbConstants.DB_CONSUME;
+ DB_CONSUME_WAIT = DbConstants.DB_CONSUME_WAIT;
+ DB_CREATE = DbConstants.DB_CREATE;
+ DB_CURRENT = DbConstants.DB_CURRENT;
+ DB_CXX_NO_EXCEPTIONS = DbConstants.DB_CXX_NO_EXCEPTIONS;
+ DB_DBT_MALLOC = DbConstants.DB_DBT_MALLOC;
+ DB_DBT_PARTIAL = DbConstants.DB_DBT_PARTIAL;
+ DB_DBT_REALLOC = DbConstants.DB_DBT_REALLOC;
+ DB_DBT_USERMEM = DbConstants.DB_DBT_USERMEM;
+ DB_DIRECT = DbConstants.DB_DIRECT;
+ DB_DIRECT_DB = DbConstants.DB_DIRECT_DB;
+ DB_DIRECT_LOG = DbConstants.DB_DIRECT_LOG;
+ DB_DIRTY_READ = DbConstants.DB_DIRTY_READ;
+ DB_DUP = DbConstants.DB_DUP;
+ DB_DUPSORT = DbConstants.DB_DUPSORT;
+ DB_EID_BROADCAST = DbConstants.DB_EID_BROADCAST;
+ DB_EID_INVALID = DbConstants.DB_EID_INVALID;
+ DB_ENCRYPT = DbConstants.DB_ENCRYPT;
+ DB_ENCRYPT_AES = DbConstants.DB_ENCRYPT_AES;
+ DB_EXCL = DbConstants.DB_EXCL;
+ DB_FAST_STAT = DbConstants.DB_FAST_STAT;
+ DB_FIRST = DbConstants.DB_FIRST;
+ DB_FLUSH = DbConstants.DB_FLUSH;
+ DB_FORCE = DbConstants.DB_FORCE;
+ DB_GET_BOTH = DbConstants.DB_GET_BOTH;
+ DB_GET_BOTH_RANGE = DbConstants.DB_GET_BOTH_RANGE;
+ DB_GET_RECNO = DbConstants.DB_GET_RECNO;
+ DB_INIT_CDB = DbConstants.DB_INIT_CDB;
+ DB_INIT_LOCK = DbConstants.DB_INIT_LOCK;
+ DB_INIT_LOG = DbConstants.DB_INIT_LOG;
+ DB_INIT_MPOOL = DbConstants.DB_INIT_MPOOL;
+ DB_INIT_TXN = DbConstants.DB_INIT_TXN;
+ DB_JOINENV = DbConstants.DB_JOINENV;
+ DB_JOIN_ITEM = DbConstants.DB_JOIN_ITEM;
+ DB_JOIN_NOSORT = DbConstants.DB_JOIN_NOSORT;
+ DB_KEYFIRST = DbConstants.DB_KEYFIRST;
+ DB_KEYLAST = DbConstants.DB_KEYLAST;
+ DB_LAST = DbConstants.DB_LAST;
+ DB_LOCKDOWN = DbConstants.DB_LOCKDOWN;
+ DB_LOCK_DEFAULT = DbConstants.DB_LOCK_DEFAULT;
+ DB_LOCK_EXPIRE = DbConstants.DB_LOCK_EXPIRE;
+ DB_LOCK_GET = DbConstants.DB_LOCK_GET;
+ DB_LOCK_GET_TIMEOUT = DbConstants.DB_LOCK_GET_TIMEOUT;
+ DB_LOCK_IREAD = DbConstants.DB_LOCK_IREAD;
+ DB_LOCK_IWR = DbConstants.DB_LOCK_IWR;
+ DB_LOCK_IWRITE = DbConstants.DB_LOCK_IWRITE;
+ DB_LOCK_MAXLOCKS = DbConstants.DB_LOCK_MAXLOCKS;
+ DB_LOCK_MINLOCKS = DbConstants.DB_LOCK_MINLOCKS;
+ DB_LOCK_MINWRITE = DbConstants.DB_LOCK_MINWRITE;
+ DB_LOCK_NOWAIT = DbConstants.DB_LOCK_NOWAIT;
+ DB_LOCK_OLDEST = DbConstants.DB_LOCK_OLDEST;
+ DB_LOCK_PUT = DbConstants.DB_LOCK_PUT;
+ DB_LOCK_PUT_ALL = DbConstants.DB_LOCK_PUT_ALL;
+ DB_LOCK_PUT_OBJ = DbConstants.DB_LOCK_PUT_OBJ;
+ DB_LOCK_RANDOM = DbConstants.DB_LOCK_RANDOM;
+ DB_LOCK_READ = DbConstants.DB_LOCK_READ;
+ DB_LOCK_TIMEOUT = DbConstants.DB_LOCK_TIMEOUT;
+ DB_LOCK_WRITE = DbConstants.DB_LOCK_WRITE;
+ DB_LOCK_YOUNGEST = DbConstants.DB_LOCK_YOUNGEST;
+ DB_MULTIPLE = DbConstants.DB_MULTIPLE;
+ DB_MULTIPLE_KEY = DbConstants.DB_MULTIPLE_KEY;
+ DB_NEXT = DbConstants.DB_NEXT;
+ DB_NEXT_DUP = DbConstants.DB_NEXT_DUP;
+ DB_NEXT_NODUP = DbConstants.DB_NEXT_NODUP;
+ DB_NODUPDATA = DbConstants.DB_NODUPDATA;
+ DB_NOLOCKING = DbConstants.DB_NOLOCKING;
+ DB_NOMMAP = DbConstants.DB_NOMMAP;
+ DB_NOORDERCHK = DbConstants.DB_NOORDERCHK;
+ DB_NOOVERWRITE = DbConstants.DB_NOOVERWRITE;
+ DB_NOPANIC = DbConstants.DB_NOPANIC;
+ DB_NOSYNC = DbConstants.DB_NOSYNC;
+ DB_ODDFILESIZE = DbConstants.DB_ODDFILESIZE;
+ DB_ORDERCHKONLY = DbConstants.DB_ORDERCHKONLY;
+ DB_OVERWRITE = DbConstants.DB_OVERWRITE;
+ DB_PANIC_ENVIRONMENT = DbConstants.DB_PANIC_ENVIRONMENT;
+ DB_POSITION = DbConstants.DB_POSITION;
+ DB_PREV = DbConstants.DB_PREV;
+ DB_PREV_NODUP = DbConstants.DB_PREV_NODUP;
+ DB_PRINTABLE = DbConstants.DB_PRINTABLE;
+ DB_PRIORITY_DEFAULT = DbConstants.DB_PRIORITY_DEFAULT;
+ DB_PRIORITY_HIGH = DbConstants.DB_PRIORITY_HIGH;
+ DB_PRIORITY_LOW = DbConstants.DB_PRIORITY_LOW;
+ DB_PRIORITY_VERY_HIGH = DbConstants.DB_PRIORITY_VERY_HIGH;
+ DB_PRIORITY_VERY_LOW = DbConstants.DB_PRIORITY_VERY_LOW;
+ DB_PRIVATE = DbConstants.DB_PRIVATE;
+ DB_RDONLY = DbConstants.DB_RDONLY;
+ DB_RECNUM = DbConstants.DB_RECNUM;
+ DB_RECORDCOUNT = DbConstants.DB_RECORDCOUNT;
+ DB_RECOVER = DbConstants.DB_RECOVER;
+ DB_RECOVER_FATAL = DbConstants.DB_RECOVER_FATAL;
+ DB_REGION_INIT = DbConstants.DB_REGION_INIT;
+ DB_RENUMBER = DbConstants.DB_RENUMBER;
+ DB_REP_CLIENT = DbConstants.DB_REP_CLIENT;
+ DB_REP_LOGSONLY = DbConstants.DB_REP_LOGSONLY;
+ DB_REP_MASTER = DbConstants.DB_REP_MASTER;
+ DB_REP_PERMANENT = DbConstants.DB_REP_PERMANENT;
+ DB_REP_UNAVAIL = DbConstants.DB_REP_UNAVAIL;
+ DB_REVSPLITOFF = DbConstants.DB_REVSPLITOFF;
+ DB_RMW = DbConstants.DB_RMW;
+ DB_SALVAGE = DbConstants.DB_SALVAGE;
+ DB_SET = DbConstants.DB_SET;
+ DB_SET_LOCK_TIMEOUT = DbConstants.DB_SET_LOCK_TIMEOUT;
+ DB_SET_RANGE = DbConstants.DB_SET_RANGE;
+ DB_SET_RECNO = DbConstants.DB_SET_RECNO;
+ DB_SET_TXN_TIMEOUT = DbConstants.DB_SET_TXN_TIMEOUT;
+ DB_SNAPSHOT = DbConstants.DB_SNAPSHOT;
+ DB_STAT_CLEAR = DbConstants.DB_STAT_CLEAR;
+ DB_SYSTEM_MEM = DbConstants.DB_SYSTEM_MEM;
+ DB_THREAD = DbConstants.DB_THREAD;
+ DB_TRUNCATE = DbConstants.DB_TRUNCATE;
+ DB_TXN_NOSYNC = DbConstants.DB_TXN_NOSYNC;
+ DB_TXN_NOWAIT = DbConstants.DB_TXN_NOWAIT;
+ DB_TXN_SYNC = DbConstants.DB_TXN_SYNC;
+ DB_TXN_WRITE_NOSYNC = DbConstants.DB_TXN_WRITE_NOSYNC;
+ DB_UPGRADE = DbConstants.DB_UPGRADE;
+ DB_USE_ENVIRON = DbConstants.DB_USE_ENVIRON;
+ DB_USE_ENVIRON_ROOT = DbConstants.DB_USE_ENVIRON_ROOT;
+ DB_VERB_CHKPOINT = DbConstants.DB_VERB_CHKPOINT;
+ DB_VERB_DEADLOCK = DbConstants.DB_VERB_DEADLOCK;
+ DB_VERB_RECOVERY = DbConstants.DB_VERB_RECOVERY;
+ DB_VERB_REPLICATION = DbConstants.DB_VERB_REPLICATION;
+ DB_VERB_WAITSFOR = DbConstants.DB_VERB_WAITSFOR;
+ DB_VERIFY = DbConstants.DB_VERIFY;
+ DB_VERSION_MAJOR = DbConstants.DB_VERSION_MAJOR;
+ DB_VERSION_MINOR = DbConstants.DB_VERSION_MINOR;
+ DB_VERSION_PATCH = DbConstants.DB_VERSION_PATCH;
+ DB_WRITECURSOR = DbConstants.DB_WRITECURSOR;
+ DB_XA_CREATE = DbConstants.DB_XA_CREATE;
+ DB_XIDDATASIZE = DbConstants.DB_XIDDATASIZE;
+ DB_YIELDCPU = DbConstants.DB_YIELDCPU;
+ // END-JAVA-CONSTANT-INITIALIZATION
+
+ one_time_init();
+ }
+}
+// end of Db.java
diff --git a/bdb/java/src/com/sleepycat/db/DbAppDispatch.java b/bdb/java/src/com/sleepycat/db/DbAppDispatch.java
new file mode 100644
index 00000000000..de72771f3e9
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbAppDispatch.java
@@ -0,0 +1,22 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbAppDispatch.java,v 11.6 2002/02/26 16:23:02 krinsky Exp $
+ */
+
+package com.sleepycat.db;
+
+/*
+ * This interface is used by DbEnv.set_app_dispatch()
+ *
+ */
+public interface DbAppDispatch
+{
+ // The value of recops is one of the Db.DB_TXN_* constants
+ public abstract int app_dispatch(DbEnv env, Dbt dbt, DbLsn lsn, int recops);
+}
+
+// end of DbAppDispatch.java
diff --git a/bdb/java/src/com/sleepycat/db/DbAppendRecno.java b/bdb/java/src/com/sleepycat/db/DbAppendRecno.java
index ffe40e95f9e..c9d205ec74d 100644
--- a/bdb/java/src/com/sleepycat/db/DbAppendRecno.java
+++ b/bdb/java/src/com/sleepycat/db/DbAppendRecno.java
@@ -1,17 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbAppendRecno.java,v 11.1 2000/07/31 20:28:30 dda Exp $
+ * $Id: DbAppendRecno.java,v 11.5 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by Db.set_append_recno()
- *
+ *
*/
public interface DbAppendRecno
{
diff --git a/bdb/java/src/com/sleepycat/db/DbBtreeCompare.java b/bdb/java/src/com/sleepycat/db/DbBtreeCompare.java
index 2e5306af232..d738998cfb5 100644
--- a/bdb/java/src/com/sleepycat/db/DbBtreeCompare.java
+++ b/bdb/java/src/com/sleepycat/db/DbBtreeCompare.java
@@ -1,17 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbBtreeCompare.java,v 11.2 2000/07/04 20:53:19 dda Exp $
+ * $Id: DbBtreeCompare.java,v 11.6 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_bt_compare()
- *
+ *
*/
public interface DbBtreeCompare
{
diff --git a/bdb/java/src/com/sleepycat/db/DbBtreePrefix.java b/bdb/java/src/com/sleepycat/db/DbBtreePrefix.java
index 27e63054339..4f18d8feb11 100644
--- a/bdb/java/src/com/sleepycat/db/DbBtreePrefix.java
+++ b/bdb/java/src/com/sleepycat/db/DbBtreePrefix.java
@@ -1,17 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbBtreePrefix.java,v 11.2 2000/07/04 20:53:19 dda Exp $
+ * $Id: DbBtreePrefix.java,v 11.6 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_bt_prefix()
- *
+ *
*/
public interface DbBtreePrefix
{
diff --git a/bdb/java/src/com/sleepycat/db/DbBtreeStat.java b/bdb/java/src/com/sleepycat/db/DbBtreeStat.java
deleted file mode 100644
index 8dea8da107c..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbBtreeStat.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbBtreeStat.java,v 11.5 2000/05/04 02:54:55 dda Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * Db.stat() method.
- */
-public class DbBtreeStat
-{
- public int bt_magic; // Magic number.
- public int bt_version; // Version number.
- public int bt_metaflags; // Meta-data flags.
- public int bt_nkeys; // Number of unique keys.
- public int bt_ndata; // Number of data items.
- public int bt_pagesize; // Page size.
- public int bt_maxkey; // Maxkey value.
- public int bt_minkey; // Minkey value.
- public int bt_re_len; // Fixed-length record length.
- public int bt_re_pad; // Fixed-length record pad.
- public int bt_levels; // Tree levels.
- public int bt_int_pg; // Internal pages.
- public int bt_leaf_pg; // Leaf pages.
- public int bt_dup_pg; // Duplicate pages.
- public int bt_over_pg; // Overflow pages.
- public int bt_free; // Pages on the free list.
- public int bt_int_pgfree; // Bytes free in internal pages.
- public int bt_leaf_pgfree; // Bytes free in leaf pages.
- public int bt_dup_pgfree; // Bytes free in duplicate pages.
- public int bt_over_pgfree; // Bytes free in overflow pages.
-}
-
-// end of DbBtreeStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbClient.java b/bdb/java/src/com/sleepycat/db/DbClient.java
new file mode 100644
index 00000000000..3b9b349c841
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbClient.java
@@ -0,0 +1,21 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbClient.java,v 11.4 2002/01/11 15:52:33 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/*
+ * This interface is used by DbEnv.set_rpc_server().
+ * It is a placeholder for a future capability.
+ *
+ */
+public interface DbClient
+{
+}
+
+// end of DbClient.java
diff --git a/bdb/java/src/com/sleepycat/db/DbDeadlockException.java b/bdb/java/src/com/sleepycat/db/DbDeadlockException.java
index beab2ad62fa..2540e22a782 100644
--- a/bdb/java/src/com/sleepycat/db/DbDeadlockException.java
+++ b/bdb/java/src/com/sleepycat/db/DbDeadlockException.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbDeadlockException.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbDeadlockException.java,v 11.6 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbDupCompare.java b/bdb/java/src/com/sleepycat/db/DbDupCompare.java
index 3d4b5a736f8..b014c76594c 100644
--- a/bdb/java/src/com/sleepycat/db/DbDupCompare.java
+++ b/bdb/java/src/com/sleepycat/db/DbDupCompare.java
@@ -1,17 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbDupCompare.java,v 11.2 2000/07/04 20:53:19 dda Exp $
+ * $Id: DbDupCompare.java,v 11.6 2002/01/11 15:52:34 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_dup_compare()
- *
+ *
*/
public interface DbDupCompare
{
diff --git a/bdb/java/src/com/sleepycat/db/DbEnv.java b/bdb/java/src/com/sleepycat/db/DbEnv.java
index 6e9ce7ae337..f5a2e25f61b 100644
--- a/bdb/java/src/com/sleepycat/db/DbEnv.java
+++ b/bdb/java/src/com/sleepycat/db/DbEnv.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbEnv.java,v 11.25 2001/01/04 14:23:30 dda Exp $
+ * $Id: DbEnv.java,v 11.58 2002/08/29 14:22:22 margo Exp $
*/
package com.sleepycat.db;
@@ -29,7 +29,7 @@ public class DbEnv
// the set_* access methods below, and finally open
// the environment by calling open().
//
- public DbEnv(int flags)
+ public DbEnv(int flags) throws DbException
{
constructor_flags_ = flags;
_init(errstream_, constructor_flags_);
@@ -62,7 +62,7 @@ public class DbEnv
{
dblist_.addElement(db);
}
-
+
//
// Remove from the private list of Db's.
//
@@ -70,7 +70,7 @@ public class DbEnv
{
dblist_.removeElement(db);
}
-
+
//
// Iterate all the Db's in the list, and
// notify them that the environment is closing,
@@ -85,7 +85,7 @@ public class DbEnv
}
dblist_.removeAllElements();
}
-
+
// close discards any internal memory.
// After using close, the DbEnv can be reopened.
//
@@ -100,6 +100,14 @@ public class DbEnv
private native void _close(int flags)
throws DbException;
+ public native void dbremove(DbTxn txn, String name, String subdb,
+ int flags)
+ throws DbException;
+
+ public native void dbrename(DbTxn txn, String name, String subdb,
+ String newname, int flags)
+ throws DbException;
+
public native void err(int errcode, String message);
public native void errx(String message);
@@ -117,9 +125,11 @@ public class DbEnv
throws Throwable;
// (Internal)
- private native void _init(DbErrcall errcall, int flags);
+ // called during constructor
+ private native void _init(DbErrcall errcall, int flags) throws DbException;
// (Internal)
+ // called when DbEnv is constructed as part of Db constructor.
private native void _init_using_db(DbErrcall errcall, Db db);
/*package*/ native void _notify_db_close();
@@ -144,6 +154,10 @@ public class DbEnv
public native void set_cachesize(int gbytes, int bytes, int ncaches)
throws DbException;
+ // Encryption
+ public native void set_encrypt(String passwd, /*u_int32_t*/ int flags)
+ throws DbException;
+
// Error message callback.
public void set_errcall(DbErrcall errcall)
{
@@ -170,7 +184,7 @@ public class DbEnv
private native void _set_errpfx(String errpfx);
// Feedback
- public void set_feedback(DbFeedback feedback)
+ public void set_feedback(DbEnvFeedback feedback)
throws DbException
{
feedback_ = feedback;
@@ -178,18 +192,18 @@ public class DbEnv
}
// (Internal)
- private native void feedback_changed(DbFeedback feedback)
+ private native void feedback_changed(DbEnvFeedback feedback)
throws DbException;
// Generate debugging messages.
- public native void set_verbose(int which, int onoff)
+ public native void set_verbose(int which, boolean onoff)
throws DbException;
public native void set_data_dir(String data_dir)
throws DbException;
// Log buffer size.
- public native void set_lg_bsize(/*u_int32_t*/ int lg_max)
+ public native void set_lg_bsize(/*u_int32_t*/ int lg_bsize)
throws DbException;
// Log directory.
@@ -200,6 +214,10 @@ public class DbEnv
public native void set_lg_max(/*u_int32_t*/ int lg_max)
throws DbException;
+ // Log region size.
+ public native void set_lg_regionmax(/*u_int32_t*/ int lg_regionmax)
+ throws DbException;
+
// Two dimensional conflict matrix.
public native void set_lk_conflicts(byte[][] lk_conflicts)
throws DbException;
@@ -231,55 +249,51 @@ public class DbEnv
public native void set_mp_mmapsize(/*size_t*/ long mmapsize)
throws DbException;
- public native void set_mutexlocks(int mutexlocks)
+ public native void set_flags(int flags, boolean onoff)
throws DbException;
- public native static void set_pageyield(int pageyield)
- throws DbException;
+ public native void set_rep_limit(int gbytes, int bytes) throws DbException;
- public native static void set_panicstate(int panicstate)
- throws DbException;
-
- public void set_recovery_init(DbRecoveryInit recovery_init)
+ public void set_rep_transport(int envid, DbRepTransport transport)
throws DbException
{
- recovery_init_ = recovery_init;
- recovery_init_changed(recovery_init);
+ rep_transport_ = transport;
+ rep_transport_changed(envid, transport);
}
// (Internal)
- private native void recovery_init_changed(DbRecoveryInit recovery_init)
+ private native void rep_transport_changed(int envid,
+ DbRepTransport transport)
throws DbException;
- public native static void set_region_init(int region_init)
- throws DbException;
-
- public native void set_flags(int flags, int onoff)
- throws DbException;
-
- public native void set_server(String host, long cl_timeout,
- long sv_timeout, int flags)
+ public native void set_rpc_server(DbClient client, String host,
+ long cl_timeout, long sv_timeout,
+ int flags)
throws DbException;
public native void set_shm_key(long shm_key)
throws DbException;
- public native static void set_tas_spins(int tas_spins)
+ public native void set_tas_spins(int tas_spins)
throws DbException;
+ public native void set_timeout(/*db_timeout_t*/ long timeout,
+ /*u_int32_t*/ int flags)
+ throws DbException;
+
public native void set_tmp_dir(String tmp_dir)
throws DbException;
// Feedback
- public void set_tx_recover(DbTxnRecover tx_recover)
+ public void set_app_dispatch(DbAppDispatch app_dispatch)
throws DbException
{
- tx_recover_ = tx_recover;
- tx_recover_changed(tx_recover);
+ app_dispatch_ = app_dispatch;
+ app_dispatch_changed(app_dispatch);
}
// (Internal)
- private native void tx_recover_changed(DbTxnRecover tx_recover)
+ private native void app_dispatch_changed(DbAppDispatch app_dispatch)
throws DbException;
// Maximum number of transactions.
@@ -316,55 +330,80 @@ public class DbEnv
/*db_lockmode_t*/ int lock_mode)
throws DbException;
+ public native void lock_put(DbLock lock)
+ throws DbException;
+
public native /*u_int32_t*/ int lock_id()
throws DbException;
- public native DbLockStat lock_stat()
+ public native void lock_id_free(/*u_int32_t*/ int id)
+ throws DbException;
+
+ public native DbLockStat lock_stat(/*u_int32_t*/ int flags)
throws DbException;
+ public native void lock_vec(/*u_int32_t*/ int locker,
+ int flags,
+ DbLockRequest[] list,
+ int offset,
+ int count)
+ throws DbException;
+
public native String[] log_archive(int flags)
throws DbException;
public native static int log_compare(DbLsn lsn0, DbLsn lsn1);
+ public native DbLogc log_cursor(int flags)
+ throws DbException;
+
public native String log_file(DbLsn lsn)
throws DbException;
public native void log_flush(DbLsn lsn)
throws DbException;
- public native void log_get(DbLsn lsn, Dbt data, int flags)
+ public native void log_put(DbLsn lsn, Dbt data, int flags)
throws DbException;
- public native void log_put(DbLsn lsn, Dbt data, int flags)
+ public native DbLogStat log_stat(/*u_int32_t*/ int flags)
throws DbException;
- public native DbLogStat log_stat()
+ public native DbMpoolStat memp_stat(/*u_int32_t*/ int flags)
throws DbException;
- public native void log_register(Db dbp, String name)
+ public native DbMpoolFStat[] memp_fstat(/*u_int32_t*/ int flags)
throws DbException;
- public native void log_unregister(Db dbp)
+ public native int memp_trickle(int pct)
throws DbException;
- public native DbMpoolStat memp_stat()
+ public native int rep_elect(int nsites, int pri, int timeout)
throws DbException;
- public native DbMpoolFStat[] memp_fstat()
+ public static class RepProcessMessage {
+ public int envid;
+ }
+ public native int rep_process_message(Dbt control, Dbt rec,
+ RepProcessMessage result)
throws DbException;
- public native int memp_trickle(int pct)
+ public native void rep_start(Dbt cookie, int flags)
+ throws DbException;
+
+ public native DbRepStat rep_stat(/*u_int32_t*/ int flags)
throws DbException;
public native DbTxn txn_begin(DbTxn pid, int flags)
throws DbException;
- public native int txn_checkpoint(int kbyte, int min, int flags)
+ public native void txn_checkpoint(int kbyte, int min, int flags)
throws DbException;
+ public native DbPreplist[] txn_recover(int count, int flags)
+ throws DbException;
- public native DbTxnStat txn_stat()
+ public native DbTxnStat txn_stat(/*u_int32_t*/ int flags)
throws DbException;
////////////////////////////////////////////////////////////////
@@ -375,9 +414,9 @@ public class DbEnv
private long private_info_ = 0;
private int constructor_flags_ = 0;
private Vector dblist_ = new Vector(); // Db's that are open
- private DbFeedback feedback_ = null;
- private DbRecoveryInit recovery_init_ = null;
- private DbTxnRecover tx_recover_ = null;
+ private DbEnvFeedback feedback_ = null;
+ private DbRepTransport rep_transport_ = null;
+ private DbAppDispatch app_dispatch_ = null;
private DbOutputStreamErrcall errstream_ =
new DbOutputStreamErrcall(System.err);
/*package*/ DbErrcall errcall_ = errstream_;
@@ -386,7 +425,6 @@ public class DbEnv
static {
Db.load_db();
}
-
}
// end of DbEnv.java
diff --git a/bdb/java/src/com/sleepycat/db/DbEnvFeedback.java b/bdb/java/src/com/sleepycat/db/DbEnvFeedback.java
index 9eec2b819f6..feef750f186 100644
--- a/bdb/java/src/com/sleepycat/db/DbEnvFeedback.java
+++ b/bdb/java/src/com/sleepycat/db/DbEnvFeedback.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbEnvFeedback.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbEnvFeedback.java,v 11.6 2002/01/11 15:52:34 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbErrcall.java b/bdb/java/src/com/sleepycat/db/DbErrcall.java
index 62d3a3e08b3..4db12772ccd 100644
--- a/bdb/java/src/com/sleepycat/db/DbErrcall.java
+++ b/bdb/java/src/com/sleepycat/db/DbErrcall.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbErrcall.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbErrcall.java,v 11.6 2002/01/11 15:52:35 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbException.java b/bdb/java/src/com/sleepycat/db/DbException.java
index ed4d020b677..132ea868f14 100644
--- a/bdb/java/src/com/sleepycat/db/DbException.java
+++ b/bdb/java/src/com/sleepycat/db/DbException.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbException.java,v 11.4 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbException.java,v 11.7 2002/01/11 15:52:35 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbFeedback.java b/bdb/java/src/com/sleepycat/db/DbFeedback.java
index d932d951a6f..38d7346e03e 100644
--- a/bdb/java/src/com/sleepycat/db/DbFeedback.java
+++ b/bdb/java/src/com/sleepycat/db/DbFeedback.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbFeedback.java,v 11.4 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbFeedback.java,v 11.7 2002/01/11 15:52:35 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbHash.java b/bdb/java/src/com/sleepycat/db/DbHash.java
index a72c2070b59..22781a11929 100644
--- a/bdb/java/src/com/sleepycat/db/DbHash.java
+++ b/bdb/java/src/com/sleepycat/db/DbHash.java
@@ -1,17 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbHash.java,v 11.1 2000/07/04 20:53:19 dda Exp $
+ * $Id: DbHash.java,v 11.5 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_bt_compare()
- *
+ *
*/
public interface DbHash
{
diff --git a/bdb/java/src/com/sleepycat/db/DbHashStat.java b/bdb/java/src/com/sleepycat/db/DbHashStat.java
deleted file mode 100644
index 62154344732..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbHashStat.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbHashStat.java,v 11.6 2000/05/04 02:54:55 dda Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * Db.stat() method.
- */
-public class DbHashStat
-{
- public int hash_magic; // Magic number.
- public int hash_version; // Version number.
- public int hash_metaflags; // Metadata flags.
- public int hash_nkeys; // Number of unique keys.
- public int hash_ndata; // Number of data items.
- public int hash_pagesize; // Page size.
- public int hash_nelem; // Original nelem specified.
- public int hash_ffactor; // Fill factor specified at create.
- public int hash_buckets; // Number of hash buckets.
- public int hash_free; // Pages on the free list.
- public int hash_bfree; // Bytes free on bucket pages.
- public int hash_bigpages; // Number of big key/data pages.
- public int hash_big_bfree; // Bytes free on big item pages.
- public int hash_overflows; // Number of overflow pages.
- public int hash_ovfl_free; // Bytes free on ovfl pages.
- public int hash_dup; // Number of dup pages.
- public int hash_dup_free; // Bytes free on duplicate pages.
-}
-
-// end of DbHashStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbKeyRange.java b/bdb/java/src/com/sleepycat/db/DbKeyRange.java
index 6a86afd9109..aa5dc16eeda 100644
--- a/bdb/java/src/com/sleepycat/db/DbKeyRange.java
+++ b/bdb/java/src/com/sleepycat/db/DbKeyRange.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbKeyRange.java,v 1.1 2000/04/12 15:07:02 dda Exp $
+ * $Id: DbKeyRange.java,v 1.4 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbLock.java b/bdb/java/src/com/sleepycat/db/DbLock.java
index bc467913e92..ee021a856b8 100644
--- a/bdb/java/src/com/sleepycat/db/DbLock.java
+++ b/bdb/java/src/com/sleepycat/db/DbLock.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbLock.java,v 11.4 2000/05/25 04:18:13 dda Exp $
+ * $Id: DbLock.java,v 11.8 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
@@ -18,11 +18,6 @@ public class DbLock
protected native void finalize()
throws Throwable;
- // methods
- //
- public native void put(DbEnv env)
- throws DbException;
-
// get/set methods
//
diff --git a/bdb/java/src/com/sleepycat/db/DbLockNotGrantedException.java b/bdb/java/src/com/sleepycat/db/DbLockNotGrantedException.java
new file mode 100644
index 00000000000..0fa434c72ee
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbLockNotGrantedException.java
@@ -0,0 +1,57 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbLockNotGrantedException.java,v 11.3 2002/01/11 15:52:36 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+public class DbLockNotGrantedException extends DbException {
+ public DbLockNotGrantedException(String message,
+ int op, int mode, Dbt obj,
+ DbLock lock, int index)
+ {
+ super(message, Db.DB_LOCK_NOTGRANTED);
+ this.op = op;
+ this.mode = mode;
+ this.obj = obj;
+ this.lock = lock;
+ this.index = index;
+ }
+
+ public int get_op()
+ {
+ return op;
+ }
+
+ public int get_mode()
+ {
+ return mode;
+ }
+
+ public Dbt get_obj()
+ {
+ return obj;
+ }
+
+ public DbLock get_lock()
+ {
+ return lock;
+ }
+
+ public int get_index()
+ {
+ return index;
+ }
+
+ private int op;
+ private int mode;
+ private Dbt obj;
+ private DbLock lock;
+ private int index;
+
+}
+
diff --git a/bdb/java/src/com/sleepycat/db/DbLockRequest.java b/bdb/java/src/com/sleepycat/db/DbLockRequest.java
new file mode 100644
index 00000000000..2ea2fe148ea
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbLockRequest.java
@@ -0,0 +1,67 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbLockRequest.java,v 11.4 2002/01/16 07:45:24 mjc Exp $
+ */
+
+package com.sleepycat.db;
+
+public class DbLockRequest
+{
+ public DbLockRequest(int op, int mode, Dbt obj, DbLock lock)
+ {
+ this.op = op;
+ this.mode = mode;
+ this.obj = obj;
+ this.lock = lock;
+ }
+
+ public int get_op()
+ {
+ return op;
+ }
+
+ public void set_op(int op)
+ {
+ this.op = op;
+ }
+
+ public int get_mode()
+ {
+ return mode;
+ }
+
+ public void set_mode(int mode)
+ {
+ this.mode = mode;
+ }
+
+ public Dbt get_obj()
+ {
+ return obj;
+ }
+
+ public void set_obj(Dbt obj)
+ {
+ this.obj = obj;
+ }
+
+ public DbLock get_lock()
+ {
+ return lock;
+ }
+
+ public void set_lock(DbLock lock)
+ {
+ this.lock = lock;
+ }
+
+ private /* db_lockop_t */ int op;
+ private /* db_lockmode_t */ int mode;
+ private /* db_timeout_t */ int timeout;
+ private Dbt obj;
+ private DbLock lock;
+}
diff --git a/bdb/java/src/com/sleepycat/db/DbLockStat.java b/bdb/java/src/com/sleepycat/db/DbLockStat.java
deleted file mode 100644
index f23f2ad5d49..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbLockStat.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbLockStat.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * DbLockTab.stat() method.
- */
-public class DbLockStat
-{
- public int st_maxlocks; // Maximum number of locks in table.
- public int st_nmodes; // Number of lock modes.
- public int st_nlockers; // Number of lockers.
- public int st_nconflicts; // Number of lock conflicts.
- public int st_nrequests; // Number of lock gets.
- public int st_nreleases; // Number of lock puts.
- public int st_ndeadlocks; // Number of lock deadlocks.
- public int st_region_wait; // Region lock granted after wait.
- public int st_region_nowait; // Region lock granted without wait.
- public int st_regsize; // Region size.
-}
-
-// end of DbLockStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbLogStat.java b/bdb/java/src/com/sleepycat/db/DbLogStat.java
deleted file mode 100644
index d708f1c4148..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbLogStat.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbLogStat.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * DbLog.stat() method.
- */
-public class DbLogStat
-{
- public int st_magic; // Log file magic number.
- public int st_version; // Log file version number.
- public int st_mode; // Log file mode.
- public int st_lg_max; // Maximum log file size.
- public int st_w_bytes; // Bytes to log.
- public int st_w_mbytes; // Megabytes to log.
- public int st_wc_bytes; // Bytes to log since checkpoint.
- public int st_wc_mbytes; // Megabytes to log since checkpoint.
- public int st_wcount; // Total syncs to the log.
- public int st_scount; // Total writes to the log.
- public int st_region_wait; // Region lock granted after wait.
- public int st_region_nowait; // Region lock granted without wait.
- public int st_cur_file; // Current log file number.
- public int st_cur_offset; // Current log file offset.
- public int st_regsize; // Region size.
-}
-
-// end of DbLogStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbLogc.java b/bdb/java/src/com/sleepycat/db/DbLogc.java
new file mode 100644
index 00000000000..34368199d5e
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbLogc.java
@@ -0,0 +1,39 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbLogc.java,v 11.3 2002/01/11 15:52:37 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/**
+ *
+ * @author Donald D. Anderson
+ */
+public class DbLogc
+{
+ // methods
+ //
+ public native void close(int flags)
+ throws DbException;
+
+ // returns: 0, DB_NOTFOUND, or throws error
+ public native int get(DbLsn lsn, Dbt data, int flags)
+ throws DbException;
+
+ protected native void finalize()
+ throws Throwable;
+
+ // private data
+ //
+ private long private_dbobj_ = 0;
+
+ static {
+ Db.load_db();
+ }
+}
+
+// end of DbLogc.java
diff --git a/bdb/java/src/com/sleepycat/db/DbLsn.java b/bdb/java/src/com/sleepycat/db/DbLsn.java
index ff36ac61c99..c9e01225e3f 100644
--- a/bdb/java/src/com/sleepycat/db/DbLsn.java
+++ b/bdb/java/src/com/sleepycat/db/DbLsn.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbLsn.java,v 11.5 2000/09/11 16:21:37 dda Exp $
+ * $Id: DbLsn.java,v 11.8 2002/01/11 15:52:37 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbMemoryException.java b/bdb/java/src/com/sleepycat/db/DbMemoryException.java
index 67a29a1f16f..a5f66674c89 100644
--- a/bdb/java/src/com/sleepycat/db/DbMemoryException.java
+++ b/bdb/java/src/com/sleepycat/db/DbMemoryException.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbMemoryException.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbMemoryException.java,v 11.7 2002/01/11 15:52:37 bostic Exp $
*/
package com.sleepycat.db;
@@ -23,6 +23,27 @@ public class DbMemoryException extends DbException
{
super(s, errno);
}
+
+ public void set_dbt(Dbt dbt)
+ {
+ this.dbt = dbt;
+ }
+
+ public Dbt get_dbt()
+ {
+ return dbt;
+ }
+
+ /* Override of DbException.toString():
+ * the extra verbage that comes from DbEnv.strerror(ENOMEM)
+ * is not helpful.
+ */
+ public String toString()
+ {
+ return getMessage();
+ }
+
+ Dbt dbt = null;
}
// end of DbMemoryException.java
diff --git a/bdb/java/src/com/sleepycat/db/DbMpoolFStat.java b/bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
deleted file mode 100644
index 44497b3bf74..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbMpoolFStat.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * DbMpool.fstat() method.
- */
-public class DbMpoolFStat
-{
- public String file_name; // File name.
- public int st_pagesize; // Page size.
- public int st_cache_hit; // Pages found in the cache.
- public int st_cache_miss; // Pages not found in the cache.
- public int st_map; // Pages from mapped files.
- public int st_page_create; // Pages created in the cache.
- public int st_page_in; // Pages read in.
- public int st_page_out; // Pages written out.
-}
-
-// end of DbMpoolFStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbMpoolStat.java b/bdb/java/src/com/sleepycat/db/DbMpoolStat.java
index 8a6d75e367b..d2d854a8b8d 100644
--- a/bdb/java/src/com/sleepycat/db/DbMpoolStat.java
+++ b/bdb/java/src/com/sleepycat/db/DbMpoolStat.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbMpoolStat.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbMpoolStat.java,v 11.7 2002/01/11 15:52:38 bostic Exp $
*/
package com.sleepycat.db;
@@ -15,10 +15,6 @@ package com.sleepycat.db;
*/
public class DbMpoolStat
{
- /**
- * @deprecated As of Berkeley DB 2.8.2, cachesize for mpool unavailable.
- */
- public int st_cachesize; // Cache size.
public int st_cache_hit; // Pages found in the cache.
public int st_cache_miss; // Pages not found in the cache.
public int st_map; // Pages from mapped files.
diff --git a/bdb/java/src/com/sleepycat/db/DbMultipleDataIterator.java b/bdb/java/src/com/sleepycat/db/DbMultipleDataIterator.java
new file mode 100644
index 00000000000..3c948ad37cd
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbMultipleDataIterator.java
@@ -0,0 +1,46 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbMultipleDataIterator.java,v 1.5 2002/01/11 15:52:38 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/**
+ *
+ * @author David M. Krinsky
+ */
+public class DbMultipleDataIterator extends DbMultipleIterator
+{
+ // public methods
+ public DbMultipleDataIterator(Dbt data)
+ {
+ super(data);
+ }
+
+ public boolean next(Dbt data)
+ {
+ int dataoff = DbUtil.array2int(buf, pos);
+
+ // crack out the data offset and length.
+ if (dataoff < 0) {
+ return (false);
+ }
+
+ pos -= int32sz;
+ int datasz = DbUtil.array2int(buf, pos);
+
+ pos -= int32sz;
+
+ data.set_data(buf);
+ data.set_size(datasz);
+ data.set_offset(dataoff);
+
+ return (true);
+ }
+}
+
+// end of DbMultipleDataIterator.java
diff --git a/bdb/java/src/com/sleepycat/db/DbMultipleIterator.java b/bdb/java/src/com/sleepycat/db/DbMultipleIterator.java
new file mode 100644
index 00000000000..0a28d9507a1
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbMultipleIterator.java
@@ -0,0 +1,51 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbMultipleIterator.java,v 1.5 2002/01/11 15:52:38 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/**
+ *
+ * @author David M. Krinsky
+ */
+// DbMultipleIterator is a shared package-private base class for the three
+// types of bulk-return Iterator; it should never be instantiated directly,
+// but it handles the functionality shared by its subclasses.
+class DbMultipleIterator
+{
+ // Package-private methods and members: used by our subclasses.
+
+ // Called implicitly by the subclass
+ DbMultipleIterator(Dbt data)
+ {
+ buf = data.get_data();
+ size = data.get_ulen();
+ // The offset will always be zero from the front of the buffer
+ // DB returns, and the buffer is opaque, so don't bother
+ // handling an offset.
+
+ // The initial position is pointing at the last u_int32_t
+ // in the buffer.
+ pos = size - int32sz;
+ }
+
+ // The C macros use sizeof(u_int32_t). Fortunately, java ints
+ // are always four bytes. Make this a constant just for form's sake.
+ static final int int32sz = 4;
+
+ // Current position within the buffer; equivalent to "pointer"
+ // in the DB_MULTIPLE macros.
+ int pos;
+
+ // A reference to the encoded buffer returned from the original
+ // Db/Dbc.get call on the data Dbt, and its size.
+ byte[] buf;
+ int size;
+}
+
+// end of DbMultipleIterator.java
diff --git a/bdb/java/src/com/sleepycat/db/DbMultipleKeyDataIterator.java b/bdb/java/src/com/sleepycat/db/DbMultipleKeyDataIterator.java
new file mode 100644
index 00000000000..0edae5801d4
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbMultipleKeyDataIterator.java
@@ -0,0 +1,56 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbMultipleKeyDataIterator.java,v 1.5 2002/01/11 15:52:39 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/**
+ *
+ * @author David M. Krinsky
+ */
+public class DbMultipleKeyDataIterator extends DbMultipleIterator
+{
+ // public methods
+ public DbMultipleKeyDataIterator(Dbt data)
+ {
+ super(data);
+ }
+
+ public boolean next(Dbt key, Dbt data)
+ {
+ int keyoff = DbUtil.array2int(buf, pos);
+
+ // crack out the key and data offsets and lengths.
+ if (keyoff < 0) {
+ return (false);
+ }
+
+ pos -= int32sz;
+ int keysz = DbUtil.array2int(buf, pos);
+
+ pos -= int32sz;
+ int dataoff = DbUtil.array2int(buf, pos);
+
+ pos -= int32sz;
+ int datasz = DbUtil.array2int(buf, pos);
+
+ pos -= int32sz;
+
+ key.set_data(buf);
+ key.set_size(keysz);
+ key.set_offset(keyoff);
+
+ data.set_data(buf);
+ data.set_size(datasz);
+ data.set_offset(dataoff);
+
+ return (true);
+ }
+}
+
+// end of DbMultipleKeyDataIterator.java
diff --git a/bdb/java/src/com/sleepycat/db/DbMultipleRecnoDataIterator.java b/bdb/java/src/com/sleepycat/db/DbMultipleRecnoDataIterator.java
new file mode 100644
index 00000000000..a4a578ed170
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbMultipleRecnoDataIterator.java
@@ -0,0 +1,51 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbMultipleRecnoDataIterator.java,v 1.5 2002/01/11 15:52:39 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/**
+ *
+ * @author David M. Krinsky
+ */
+public class DbMultipleRecnoDataIterator extends DbMultipleIterator
+{
+ // public methods
+ public DbMultipleRecnoDataIterator(Dbt data)
+ {
+ super(data);
+ }
+
+ public boolean next(Dbt key, Dbt data)
+ {
+ int keyoff = DbUtil.array2int(buf, pos);
+
+ // crack out the key offset and the data offset and length.
+ if (keyoff < 0) {
+ return (false);
+ }
+
+ pos -= int32sz;
+ int dataoff = DbUtil.array2int(buf, pos);
+
+ pos -= int32sz;
+ int datasz = DbUtil.array2int(buf, pos);
+
+ pos -= int32sz;
+
+ key.set_recno_key_from_buffer(buf, keyoff);
+
+ data.set_data(buf);
+ data.set_size(datasz);
+ data.set_offset(dataoff);
+
+ return (true);
+ }
+}
+
+// end of DbMultipleRecnoDataIterator.java
diff --git a/bdb/java/src/com/sleepycat/db/DbOutputStreamErrcall.java b/bdb/java/src/com/sleepycat/db/DbOutputStreamErrcall.java
index 4f962d9a334..7343caa8238 100644
--- a/bdb/java/src/com/sleepycat/db/DbOutputStreamErrcall.java
+++ b/bdb/java/src/com/sleepycat/db/DbOutputStreamErrcall.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbOutputStreamErrcall.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbOutputStreamErrcall.java,v 11.6 2002/01/11 15:52:39 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbPreplist.java b/bdb/java/src/com/sleepycat/db/DbPreplist.java
new file mode 100644
index 00000000000..e5fffa77e1e
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbPreplist.java
@@ -0,0 +1,22 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbPreplist.java,v 11.3 2002/01/11 15:52:40 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/*
+ * This is filled in and returned by the
+ * DbEnv.txn_recover() method.
+ */
+public class DbPreplist
+{
+ public DbTxn txn;
+ public byte gid[];
+}
+
+// end of DbPreplist.java
diff --git a/bdb/java/src/com/sleepycat/db/DbQueueStat.java b/bdb/java/src/com/sleepycat/db/DbQueueStat.java
deleted file mode 100644
index 652878b1adb..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbQueueStat.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbQueueStat.java,v 11.5 2000/11/07 18:45:27 dda Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * Db.stat() method.
- */
-public class DbQueueStat
-{
- public int qs_magic; // Magic number.
- public int qs_version; // Version number.
- public int qs_metaflags; // Metadata flags.
- public int qs_nkeys; // Number of unique keys.
- public int qs_ndata; // Number of data items.
- public int qs_pagesize; // Page size.
- public int qs_pages; // Data pages.
- public int qs_re_len; // Fixed-length record length.
- public int qs_re_pad; // Fixed-length record pad.
- public int qs_pgfree; // Bytes free in data pages.
- public int qs_first_recno; // First not deleted record.
- public int qs_cur_recno; // Last allocated record number.
-}
-
-// end of DbQueueStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbRecoveryInit.java b/bdb/java/src/com/sleepycat/db/DbRecoveryInit.java
deleted file mode 100644
index b32eebcaa6c..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbRecoveryInit.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbRecoveryInit.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
- */
-
-package com.sleepycat.db;
-
-/**
- *
- * @author Donald D. Anderson
- */
-public interface DbRecoveryInit
-{
- // methods
- //
- public abstract void recovery_init(DbEnv dbenv);
-}
-
-// end of DbRecoveryInit.java
diff --git a/bdb/java/src/com/sleepycat/db/DbRepTransport.java b/bdb/java/src/com/sleepycat/db/DbRepTransport.java
new file mode 100644
index 00000000000..441c783b890
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbRepTransport.java
@@ -0,0 +1,19 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbRepTransport.java,v 11.2 2002/01/11 15:52:40 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/*
+ * This is used as a callback by DbEnv.set_rep_transport.
+ */
+public interface DbRepTransport
+{
+ public int send(DbEnv env, Dbt control, Dbt rec, int flags, int envid)
+ throws DbException;
+}
diff --git a/bdb/java/src/com/sleepycat/db/DbRunRecoveryException.java b/bdb/java/src/com/sleepycat/db/DbRunRecoveryException.java
index 78736b6ed1e..32f2727a78b 100644
--- a/bdb/java/src/com/sleepycat/db/DbRunRecoveryException.java
+++ b/bdb/java/src/com/sleepycat/db/DbRunRecoveryException.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbRunRecoveryException.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
+ * $Id: DbRunRecoveryException.java,v 11.6 2002/01/11 15:52:40 bostic Exp $
*/
package com.sleepycat.db;
diff --git a/bdb/java/src/com/sleepycat/db/DbSecondaryKeyCreate.java b/bdb/java/src/com/sleepycat/db/DbSecondaryKeyCreate.java
new file mode 100644
index 00000000000..ca2acde1b03
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbSecondaryKeyCreate.java
@@ -0,0 +1,22 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbSecondaryKeyCreate.java,v 11.3 2002/01/11 15:52:40 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/*
+ * This is used as a callback by Db.associate.
+ */
+public interface DbSecondaryKeyCreate
+{
+ public int secondary_key_create(Db secondary, Dbt key,
+ Dbt data, Dbt result)
+ throws DbException;
+}
+
+// end of DbSecondaryKeyCreate.java
diff --git a/bdb/java/src/com/sleepycat/db/DbTxn.java b/bdb/java/src/com/sleepycat/db/DbTxn.java
index 201ff94c8f3..d3906d112c0 100644
--- a/bdb/java/src/com/sleepycat/db/DbTxn.java
+++ b/bdb/java/src/com/sleepycat/db/DbTxn.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: DbTxn.java,v 11.5 2000/05/25 04:18:13 dda Exp $
+ * $Id: DbTxn.java,v 11.17 2002/08/29 14:22:22 margo Exp $
*/
package com.sleepycat.db;
@@ -23,14 +23,44 @@ public class DbTxn
public native void commit(int flags)
throws DbException;
+ public native void discard(int flags)
+ throws DbException;
+
public native /*u_int32_t*/ int id()
throws DbException;
- public native void prepare()
+ public native void prepare(byte[] gid)
throws DbException;
- protected native void finalize()
- throws Throwable;
+ public native void set_timeout(/*db_timeout_t*/ long timeout,
+ /*u_int32_t*/ int flags)
+ throws DbException;
+
+ // We override Object.equals because it is possible for
+ // the Java API to create multiple DbTxns that reference
+ // the same underlying object. This can happen for example
+ // during DbEnv.txn_recover().
+ //
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+
+ if (obj != null && (obj instanceof DbTxn)) {
+ DbTxn that = (DbTxn)obj;
+ return (this.private_dbobj_ == that.private_dbobj_);
+ }
+ return false;
+ }
+
+ // We must override Object.hashCode whenever we override
+ // Object.equals() to enforce the maxim that equal objects
+ // have the same hashcode.
+ //
+ public int hashCode()
+ {
+ return ((int)private_dbobj_ ^ (int)(private_dbobj_ >> 32));
+ }
// get/set methods
//
diff --git a/bdb/java/src/com/sleepycat/db/DbTxnRecover.java b/bdb/java/src/com/sleepycat/db/DbTxnRecover.java
deleted file mode 100644
index ee47935941d..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbTxnRecover.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbTxnRecover.java,v 11.1 2000/06/29 18:08:17 dda Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This interface is used by DbEnv.set_tx_recover()
- *
- */
-public interface DbTxnRecover
-{
- // The value of recops is one of the Db.DB_TXN_* constants
- public abstract int tx_recover(DbEnv env, Dbt dbt, DbLsn lsn, int recops);
-}
-
-// end of DbBtreeCompare.java
diff --git a/bdb/java/src/com/sleepycat/db/DbTxnStat.java b/bdb/java/src/com/sleepycat/db/DbTxnStat.java
deleted file mode 100644
index e72addb00b1..00000000000
--- a/bdb/java/src/com/sleepycat/db/DbTxnStat.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: DbTxnStat.java,v 11.3 2000/02/14 02:59:56 bostic Exp $
- */
-
-package com.sleepycat.db;
-
-/*
- * This is filled in and returned by the
- * DbTxnMgr.fstat() method.
- */
-public class DbTxnStat
-{
- public static class Active {
- public int txnid; // Transaction ID
- public int parentid; // Transaction ID of parent
- public DbLsn lsn; // Lsn of the begin record
- };
-
- public DbLsn st_last_ckp; // lsn of the last checkpoint
- public DbLsn st_pending_ckp; // last checkpoint did not finish
- public long st_time_ckp; // time of last checkpoint (UNIX secs)
- public int st_last_txnid; // last transaction id given out
- public int st_maxtxns; // maximum number of active txns
- public int st_naborts; // number of aborted transactions
- public int st_nbegins; // number of begun transactions
- public int st_ncommits; // number of committed transactions
- public int st_nactive; // number of active transactions
- public int st_maxnactive; // maximum active transactions
- public Active st_txnarray[]; // array of active transactions
- public int st_region_wait; // Region lock granted after wait.
- public int st_region_nowait; // Region lock granted without wait.
- public int st_regsize; // Region size.
-}
-
-// end of DbTxnStat.java
diff --git a/bdb/java/src/com/sleepycat/db/DbUtil.java b/bdb/java/src/com/sleepycat/db/DbUtil.java
new file mode 100644
index 00000000000..30ca93d03cc
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/DbUtil.java
@@ -0,0 +1,98 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbUtil.java,v 11.5 2002/01/11 15:52:41 bostic Exp $
+ */
+
+package com.sleepycat.db;
+
+/**
+ *
+ * @author David M. Krinsky
+ */
+
+// DbUtil is a simple, package-private wrapper class that holds a few
+// static utility functions other parts of the package share and that don't
+// have a good home elsewhere. (For now, that's limited to byte-array-to-int
+// conversion and back.)
+
+class DbUtil
+{
+ // Get the u_int32_t stored beginning at offset "offset" into
+ // array "arr". We have to do the conversion manually since it's
+ // a C-native int, and we're not really supposed to make this kind of
+ // cast in Java.
+ static int array2int(byte[] arr, int offset)
+ {
+ int b1, b2, b3, b4;
+ int pos = offset;
+
+ // Get the component bytes; b4 is most significant, b1 least.
+ if (big_endian) {
+ b4 = arr[pos++];
+ b3 = arr[pos++];
+ b2 = arr[pos++];
+ b1 = arr[pos];
+ } else {
+ b1 = arr[pos++];
+ b2 = arr[pos++];
+ b3 = arr[pos++];
+ b4 = arr[pos];
+ }
+
+ // Bytes are signed. Convert [-128, -1] to [128, 255].
+ if (b1 < 0) { b1 += 256; }
+ if (b2 < 0) { b2 += 256; }
+ if (b3 < 0) { b3 += 256; }
+ if (b4 < 0) { b4 += 256; }
+
+ // Put the bytes in their proper places in an int.
+ b2 <<= 8;
+ b3 <<= 16;
+ b4 <<= 24;
+
+ // Return their sum.
+ return (b1 + b2 + b3 + b4);
+ }
+
+ // Store the specified u_int32_t, with endianness appropriate
+ // to the platform we're running on, into four consecutive bytes of
+ // the specified byte array, starting from the specified offset.
+ static void int2array(int n, byte[] arr, int offset)
+ {
+ int b1, b2, b3, b4;
+ int pos = offset;
+
+ b1 = n & 0xff;
+ b2 = (n >> 8) & 0xff;
+ b3 = (n >> 16) & 0xff;
+ b4 = (n >> 24) & 0xff;
+
+ // Bytes are signed. Convert [128, 255] to [-128, -1].
+ if (b1 >= 128) { b1 -= 256; }
+ if (b2 >= 128) { b2 -= 256; }
+ if (b3 >= 128) { b3 -= 256; }
+ if (b4 >= 128) { b4 -= 256; }
+
+ // Put the bytes in the appropriate place in the array.
+ if (big_endian) {
+ arr[pos++] = (byte)b4;
+ arr[pos++] = (byte)b3;
+ arr[pos++] = (byte)b2;
+ arr[pos] = (byte)b1;
+ } else {
+ arr[pos++] = (byte)b1;
+ arr[pos++] = (byte)b2;
+ arr[pos++] = (byte)b3;
+ arr[pos] = (byte)b4;
+ }
+ }
+
+ private static final boolean big_endian = is_big_endian();
+ private static native boolean is_big_endian();
+}
+
+// end of DbUtil.java
diff --git a/bdb/java/src/com/sleepycat/db/Dbc.java b/bdb/java/src/com/sleepycat/db/Dbc.java
index b097cbad802..60c00b1deb7 100644
--- a/bdb/java/src/com/sleepycat/db/Dbc.java
+++ b/bdb/java/src/com/sleepycat/db/Dbc.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: Dbc.java,v 11.5 2000/05/25 04:18:13 dda Exp $
+ * $Id: Dbc.java,v 11.9 2002/01/11 15:52:41 bostic Exp $
*/
package com.sleepycat.db;
@@ -34,6 +34,10 @@ public class Dbc
public native int get(Dbt key, Dbt data, int flags)
throws DbException;
+ // returns: 0, DB_NOTFOUND, or throws error
+ public native int pget(Dbt key, Dbt pkey, Dbt data, int flags)
+ throws DbException;
+
// returns: 0, DB_KEYEXIST, or throws error
public native int put(Dbt key, Dbt data, int flags)
throws DbException;
diff --git a/bdb/java/src/com/sleepycat/db/Dbt.java b/bdb/java/src/com/sleepycat/db/Dbt.java
index bbb478cd542..f51d0419963 100644
--- a/bdb/java/src/com/sleepycat/db/Dbt.java
+++ b/bdb/java/src/com/sleepycat/db/Dbt.java
@@ -1,14 +1,19 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
*
- * $Id: Dbt.java,v 11.6 2000/06/16 03:34:01 dda Exp $
+ * $Id: Dbt.java,v 11.15 2002/09/04 00:37:25 mjc Exp $
*/
package com.sleepycat.db;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
/**
*
* @author Donald D. Anderson
@@ -18,6 +23,34 @@ public class Dbt
// methods
//
+ public Dbt(byte[] data)
+ {
+ init();
+ this.data = data;
+ if (data != null) {
+ this.size = data.length;
+ }
+ }
+
+ public Dbt(byte[] data, int off, int len)
+ {
+ init();
+ this.data = data;
+ this.offset = off;
+ this.size = len;
+ }
+
+ public Dbt()
+ {
+ init();
+ }
+
+ public Dbt(Object serialobj) throws java.io.IOException
+ {
+ init();
+ this.set_object(serialobj);
+ }
+
protected native void finalize()
throws Throwable;
@@ -25,86 +58,173 @@ public class Dbt
//
// key/data
+ public byte[] get_data()
+ {
+ // In certain circumstances, like callbacks to
+ // user code that have Dbt args, we do not create
+ // data arrays until the user explicitly does a get_data.
+ // This saves us from needlessly creating objects
+ // (potentially large arrays) that may never be accessed.
+ //
+ if (must_create_data) {
+ data = create_data();
+ must_create_data = false;
+ }
+ return data;
+ }
public void set_data(byte[] data)
{
- // internal_set_data is separated from set_data in case
- // we want to have set_data automatically set some other
- // fields (size, etc.) someday.
- //
- internal_set_data(data);
+ this.data = data;
+ this.must_create_data = false;
}
- public native byte[] get_data();
- private native void internal_set_data(byte[] data);
- // These are not in the original DB interface,
- // but they can be used to get/set the offset
+ // get_offset/set_offset is unique to the Java portion
+ // of the DB APIs. They can be used to get/set the offset
// into the attached byte array.
//
- public native void set_offset(int off);
- public native int get_offset();
+ public int get_offset()
+ {
+ return offset;
+ }
+
+ public void set_offset(int offset)
+ {
+ this.offset = offset;
+ }
// key/data length
- public native /*u_int32_t*/ int get_size();
- public native void set_size(/*u_int32_t*/ int size);
+ public /*u_int32_t*/ int get_size()
+ {
+ return size;
+ }
+
+ public void set_size(/*u_int32_t*/ int size)
+ {
+ this.size = size;
+ }
// RO: length of user buffer.
- public native /*u_int32_t*/ int get_ulen();
- public native void set_ulen(/*u_int32_t*/ int ulen);
+ public /*u_int32_t*/ int get_ulen()
+ {
+ return ulen;
+ }
+
+ public void set_ulen(/*u_int32_t*/ int ulen)
+ {
+ this.ulen = ulen;
+ }
+
// RO: get/put record length.
- public native /*u_int32_t*/ int get_dlen();
- public native void set_dlen(/*u_int32_t*/ int dlen);
+ public /*u_int32_t*/ int get_dlen()
+ {
+ return dlen;
+ }
+
+ public void set_dlen(/*u_int32_t*/ int dlen)
+ {
+ this.dlen = dlen;
+ }
// RO: get/put record offset.
- public native /*u_int32_t*/ int get_doff();
- public native void set_doff(/*u_int32_t*/ int doff);
+ public /*u_int32_t*/ int get_doff()
+ {
+ return doff;
+ }
+
+ public void set_doff(/*u_int32_t*/ int doff)
+ {
+ this.doff = doff;
+ }
// flags
- public native /*u_int32_t*/ int get_flags();
- public native void set_flags(/*u_int32_t*/ int flags);
+ public /*u_int32_t*/ int get_flags()
+ {
+ return flags;
+ }
+
+ public void set_flags(/*u_int32_t*/ int flags)
+ {
+ this.flags = flags;
+ }
+
+ // Helper methods to get/set a Dbt from a serializable object.
+ public Object get_object() throws java.io.IOException,
+ java.lang.ClassNotFoundException
+ {
+ ByteArrayInputStream bytestream = new ByteArrayInputStream(get_data());
+ ObjectInputStream ois = new ObjectInputStream(bytestream);
+ Object serialobj = ois.readObject();
+ ois.close();
+ bytestream.close();
+ return (serialobj);
+ }
+
+ public void set_object(Object serialobj) throws java.io.IOException
+ {
+ ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bytestream);
+ oos.writeObject(serialobj);
+ oos.close();
+ byte[] buf = bytestream.toByteArray();
+ bytestream.close();
+ set_data(buf);
+ set_offset(0);
+ set_size(buf.length);
+ }
// These are not in the original DB interface.
// They can be used to set the recno key for a Dbt.
- // Note: you must set the data field to an array of
- // at least four bytes before calling either of these.
- //
- public native void set_recno_key_data(int recno);
- public native int get_recno_key_data();
-
- public Dbt(byte[] data)
+ // Note: if data is less than (offset + 4) bytes, these
+ // methods may throw an ArrayIndexException. get_recno_key_data()
+ // will additionally throw a NullPointerException if data is null.
+ public void set_recno_key_data(int recno)
{
- init();
- internal_set_data(data);
- if (data != null)
- set_size(data.length);
+ if (data == null) {
+ data = new byte[4];
+ size = 4;
+ offset = 0;
+ }
+ DbUtil.int2array(recno, data, offset);
}
- public Dbt(byte[] data, int off, int len)
+ public int get_recno_key_data()
{
- this(data);
- set_ulen(len);
- set_offset(off);
+ return (DbUtil.array2int(data, offset));
}
- public Dbt()
+ // Used internally by DbMultipleRecnoIterator
+ //
+ /*package*/ void set_recno_key_from_buffer(byte[] data, int offset)
{
- init();
+ this.data = data;
+ this.offset = offset;
+ this.size = 4;
+ }
+
+ static {
+ Db.load_db();
}
// private methods
//
private native void init();
+ private native byte[] create_data();
// private data
//
private long private_dbobj_ = 0;
- static {
- Db.load_db();
- }
+ private byte[] data = null;
+ private int offset = 0;
+ private int size = 0;
+ private int ulen = 0;
+ private int dlen = 0;
+ private int doff = 0;
+ private int flags = 0;
+ private boolean must_create_data = false;
}
-
// end of Dbt.java
diff --git a/bdb/java/src/com/sleepycat/db/xa/DbXAResource.java b/bdb/java/src/com/sleepycat/db/xa/DbXAResource.java
new file mode 100644
index 00000000000..3a996c0d045
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/xa/DbXAResource.java
@@ -0,0 +1,190 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbXAResource.java,v 1.2 2002/08/09 01:54:57 bostic Exp $
+ */
+
+package com.sleepycat.db.xa;
+
+import com.sleepycat.db.Db;
+import com.sleepycat.db.DbEnv;
+import com.sleepycat.db.DbTxn;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.Xid;
+
+public class DbXAResource implements XAResource
+{
+ public DbXAResource(String home, int rmid, int flags)
+ throws XAException
+ {
+ this.home = home;
+ this.rmid = rmid;
+
+ // We force single-threading for calls to _init/_close.
+ // This makes our internal code much easier, and
+ // should not be a performance burden.
+ synchronized (DbXAResource.class) {
+ _init(home, rmid, flags);
+ }
+ }
+
+ //
+ // Alternate constructor for convenience.
+ // Uses an rmid that is unique within this JVM,
+ // numbered started at 0.
+ //
+ public DbXAResource(String home)
+ throws XAException
+ {
+ this(home, get_unique_rmid(), 0);
+ }
+
+ private native void _init(String home, int rmid, int flags);
+
+ public void close(int flags)
+ throws XAException
+ {
+ // We force single-threading for calls to _init/_close.
+ // This makes our internal code much easier, and
+ // should not be a performance burden.
+ synchronized (DbXAResource.class) {
+ _close(home, rmid, flags);
+ }
+ }
+
+ private native void _close(String home, int rmid, int flags);
+
+ public void commit(Xid xid, boolean onePhase)
+ throws XAException
+ {
+ _commit(xid, rmid, onePhase);
+ }
+
+ private native void _commit(Xid xid, int rmid, boolean onePhase);
+
+ public void end(Xid xid, int flags)
+ throws XAException
+ {
+ _end(xid, rmid, flags);
+ }
+
+ private native void _end(Xid xid, int rmid, int flags);
+
+ public void forget(Xid xid)
+ throws XAException
+ {
+ _forget(xid, rmid);
+ }
+
+ private native void _forget(Xid xid, int rmid);
+
+ public int getTransactionTimeout()
+ throws XAException
+ {
+ return transactionTimeout;
+ }
+
+ public boolean isSameRM(XAResource xares)
+ throws XAException
+ {
+ if (!(xares instanceof DbXAResource))
+ return false;
+ return (this.rmid == ((DbXAResource)xares).rmid);
+ }
+
+ public int prepare(Xid xid)
+ throws XAException
+ {
+ return _prepare(xid, rmid);
+ }
+
+ private native int _prepare(Xid xid, int rmid);
+
+ public Xid [] recover(int flag)
+ throws XAException
+ {
+ return _recover(rmid, flag);
+ }
+
+ private native Xid[] _recover(int rmid, int flags);
+
+ public void rollback(Xid xid)
+ throws XAException
+ {
+ _rollback(xid, rmid);
+ System.err.println("DbXAResource.rollback returned");
+ }
+
+ private native void _rollback(Xid xid, int rmid);
+
+ public boolean setTransactionTimeout(int seconds)
+ throws XAException
+ {
+ // XXX we are not using the transaction timeout.
+ transactionTimeout = seconds;
+ return true;
+ }
+
+ public void start(Xid xid, int flags)
+ throws XAException
+ {
+ _start(xid, rmid, flags);
+ }
+
+ private native void _start(Xid xid, int rmid, int flags);
+
+ private static synchronized int get_unique_rmid()
+ {
+ return unique_rmid++;
+ }
+
+ public interface DbAttach
+ {
+ public DbEnv get_env();
+ public DbTxn get_txn();
+ }
+
+ protected static class DbAttachImpl implements DbAttach
+ {
+ private DbEnv env;
+ private DbTxn txn;
+
+ DbAttachImpl(DbEnv env, DbTxn txn)
+ {
+ this.env = env;
+ this.txn = txn;
+ }
+
+ public DbTxn get_txn()
+ {
+ return txn;
+ }
+
+ public DbEnv get_env()
+ {
+ return env;
+ }
+ }
+
+ public static native DbAttach xa_attach(Xid xid, Integer rmid);
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // private data
+ //
+ private long private_dbobj_ = 0;
+ private int transactionTimeout = 0;
+ private String home;
+ private int rmid;
+
+ private static int unique_rmid = 0;
+
+ static
+ {
+ Db.load_db();
+ }
+}
diff --git a/bdb/java/src/com/sleepycat/db/xa/DbXid.java b/bdb/java/src/com/sleepycat/db/xa/DbXid.java
new file mode 100644
index 00000000000..ba03d3ebf3e
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/db/xa/DbXid.java
@@ -0,0 +1,49 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbXid.java,v 1.2 2002/08/09 01:54:58 bostic Exp $
+ */
+
+package com.sleepycat.db.xa;
+
+import com.sleepycat.db.DbException;
+import com.sleepycat.db.DbTxn;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.Xid;
+
+public class DbXid implements Xid
+{
+ public DbXid(int formatId, byte[] gtrid, byte[] bqual)
+ throws XAException
+ {
+ this.formatId = formatId;
+ this.gtrid = gtrid;
+ this.bqual = bqual;
+ }
+
+ public int getFormatId()
+ {
+ return formatId;
+ }
+
+ public byte[] getGlobalTransactionId()
+ {
+ return gtrid;
+ }
+
+ public byte[] getBranchQualifier()
+ {
+ return bqual;
+ }
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // private data
+ //
+ private byte[] gtrid;
+ private byte[] bqual;
+ private int formatId;
+}
diff --git a/bdb/java/src/com/sleepycat/examples/AccessExample.java b/bdb/java/src/com/sleepycat/examples/AccessExample.java
index f3a98c2c7d5..ea3d5f342ed 100644
--- a/bdb/java/src/com/sleepycat/examples/AccessExample.java
+++ b/bdb/java/src/com/sleepycat/examples/AccessExample.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: AccessExample.java,v 11.5 2000/12/13 07:09:42 krinsky Exp $
+ * $Id: AccessExample.java,v 11.12 2002/02/05 22:27:13 mjc Exp $
*/
package com.sleepycat.examples;
@@ -24,12 +24,6 @@ class AccessExample
{
}
- private static void usage()
- {
- System.err.println("usage: AccessExample\n");
- System.exit(1);
- }
-
public static void main(String argv[])
{
try
@@ -101,7 +95,7 @@ class AccessExample
Db table = new Db(null, 0);
table.set_error_stream(System.err);
table.set_errpfx("AccessExample");
- table.open(FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+ table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
//
// Insert records into the database, where the key is the user
@@ -124,7 +118,7 @@ class AccessExample
try
{
int err;
- if ((err = table.put(null,
+ if ((err = table.put(null,
key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
System.out.println("Key " + line + " already exists.");
}
@@ -174,8 +168,9 @@ class AccessExample
void setString(String value)
{
- set_data(value.getBytes());
- set_size(value.length());
+ byte[] data = value.getBytes();
+ set_data(data);
+ set_size(data.length);
}
String getString()
diff --git a/bdb/java/src/com/sleepycat/examples/BtRecExample.java b/bdb/java/src/com/sleepycat/examples/BtRecExample.java
index 5101f676a0b..68365600748 100644
--- a/bdb/java/src/com/sleepycat/examples/BtRecExample.java
+++ b/bdb/java/src/com/sleepycat/examples/BtRecExample.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: BtRecExample.java,v 11.6 2000/02/19 20:58:02 bostic Exp $
+ * $Id: BtRecExample.java,v 11.11 2002/02/05 22:27:13 mjc Exp $
*/
package com.sleepycat.examples;
@@ -41,7 +41,7 @@ public class BtRecExample
dbp.set_pagesize(1024); // 1K page sizes.
dbp.set_flags(Db.DB_RECNUM); // Record numbers.
- dbp.open(database, null, Db.DB_BTREE, Db.DB_CREATE, 0664);
+ dbp.open(null, database, null, Db.DB_BTREE, Db.DB_CREATE, 0664);
//
// Insert records into the database, where the key is the word
@@ -177,36 +177,26 @@ public class BtRecExample
// Open the word database.
FileReader freader = new FileReader(wordlist);
- BtRecExample app = new BtRecExample(new BufferedReader(freader));
+ BtRecExample app = new BtRecExample(new BufferedReader(freader));
- // Close the word database.
+ // Close the word database.
freader.close();
freader = null;
app.stats();
app.run();
- }
- catch (FileNotFoundException fnfe) {
+ } catch (FileNotFoundException fnfe) {
System.err.println(progname + ": unexpected open error " + fnfe);
System.exit (1);
- }
- catch (IOException ioe) {
+ } catch (IOException ioe) {
System.err.println(progname + ": open " + wordlist + ": " + ioe);
System.exit (1);
+ } catch (DbException dbe) {
+ System.err.println("Exception: " + dbe);
+ System.exit(dbe.get_errno());
}
- catch (DbException dbe) {
- System.err.println("Exception: " + dbe);
- System.exit(dbe.get_errno());
- }
- System.exit(0);
- }
-
- void
- usage()
- {
- System.err.println("usage: " + progname);
- System.exit(1);
+ System.exit(0);
}
// Prompts for a line, and keeps prompting until a non blank
@@ -279,10 +269,11 @@ public class BtRecExample
void setString(String value)
{
- set_data(value.getBytes());
- set_size(value.length());
+ byte[] data = value.getBytes();
+ set_data(data);
+ set_size(data.length);
// must set ulen because sometimes a string is returned
- set_ulen(value.length());
+ set_ulen(data.length);
}
String getString()
@@ -329,8 +320,9 @@ public class BtRecExample
void setString(String value)
{
- set_data(value.getBytes());
- set_size(value.length());
+ byte[] data = value.getBytes();
+ set_data(data);
+ set_size(data.length);
}
int getRecno()
diff --git a/bdb/java/src/com/sleepycat/examples/BulkAccessExample.java b/bdb/java/src/com/sleepycat/examples/BulkAccessExample.java
new file mode 100644
index 00000000000..e6690197105
--- /dev/null
+++ b/bdb/java/src/com/sleepycat/examples/BulkAccessExample.java
@@ -0,0 +1,198 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: BulkAccessExample.java,v 1.6 2002/02/05 22:27:13 mjc Exp $
+ */
+
+package com.sleepycat.examples;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+class BulkAccessExample
+{
+ private static final String FileName = "access.db";
+
+ public BulkAccessExample()
+ {
+ }
+
+ public static void main(String argv[])
+ {
+ try
+ {
+ BulkAccessExample app = new BulkAccessExample();
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("BulkAccessExample: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("BulkAccessExample: " + fnfe.toString());
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ // Prompts for a line, and keeps prompting until a non blank
+ // line is returned. Returns null on error.
+ //
+ static public String askForLine(InputStreamReader reader,
+ PrintStream out, String prompt)
+ {
+ String result = "";
+ while (result != null && result.length() == 0) {
+ out.print(prompt);
+ out.flush();
+ result = getLine(reader);
+ }
+ return result;
+ }
+
+ // Not terribly efficient, but does the job.
+ // Works for reading a line from stdin or a file.
+ // Returns null on EOF. If EOF appears in the middle
+ // of a line, returns that line, then null on next call.
+ //
+ static public String getLine(InputStreamReader reader)
+ {
+ StringBuffer b = new StringBuffer();
+ int c;
+ try {
+ while ((c = reader.read()) != -1 && c != '\n') {
+ if (c != '\r')
+ b.append((char)c);
+ }
+ }
+ catch (IOException ioe) {
+ c = -1;
+ }
+
+ if (c == -1 && b.length() == 0)
+ return null;
+ else
+ return b.toString();
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ Db table = new Db(null, 0);
+ table.set_error_stream(System.err);
+ table.set_errpfx("BulkAccessExample");
+ table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ InputStreamReader reader = new InputStreamReader(System.in);
+
+ for (;;) {
+ String line = askForLine(reader, System.out, "input> ");
+ if (line == null)
+ break;
+
+ String reversed = (new StringBuffer(line)).reverse().toString();
+
+ // See definition of StringDbt below
+ //
+ StringDbt key = new StringDbt(line);
+ StringDbt data = new StringDbt(reversed);
+
+ try
+ {
+ int err;
+ if ((err = table.put(null,
+ key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
+ System.out.println("Key " + line + " already exists.");
+ }
+ }
+ catch (DbException dbe)
+ {
+ System.out.println(dbe.toString());
+ }
+ System.out.println("");
+ }
+
+ // Acquire a cursor for the table and two Dbts.
+ Dbc dbc = table.cursor(null, 0);
+ Dbt foo = new Dbt();
+ foo.set_flags(Db.DB_DBT_MALLOC);
+
+ Dbt bulk_data = new Dbt();
+
+ // Set Db.DB_DBT_USERMEM on the data Dbt; Db.DB_MULTIPLE_KEY requires
+ // it. Then allocate a byte array of a reasonable size; we'll
+ // go through the database in chunks this big.
+ bulk_data.set_flags(Db.DB_DBT_USERMEM);
+ bulk_data.set_data(new byte[1000000]);
+ bulk_data.set_ulen(1000000);
+
+
+ // Walk through the table, printing the key/data pairs.
+ //
+ while (dbc.get(foo, bulk_data, Db.DB_NEXT | Db.DB_MULTIPLE_KEY) == 0)
+ {
+ DbMultipleKeyDataIterator iterator;
+ iterator = new DbMultipleKeyDataIterator(bulk_data);
+
+ StringDbt key, data;
+ key = new StringDbt();
+ data = new StringDbt();
+
+ while (iterator.next(key, data)) {
+ System.out.println(key.getString() + " : " + data.getString());
+ }
+ }
+ dbc.close();
+ table.close(0);
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ byte[] data = value.getBytes();
+ set_data(data);
+ set_size(data.length);
+ }
+
+ String getString()
+ {
+ return new String(get_data(), get_offset(), get_size());
+ }
+ }
+}
diff --git a/bdb/java/src/com/sleepycat/examples/EnvExample.java b/bdb/java/src/com/sleepycat/examples/EnvExample.java
index f1b855836c5..acbd9f59621 100644
--- a/bdb/java/src/com/sleepycat/examples/EnvExample.java
+++ b/bdb/java/src/com/sleepycat/examples/EnvExample.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: EnvExample.java,v 11.7 2000/09/25 13:16:51 dda Exp $
+ * $Id: EnvExample.java,v 11.9 2002/01/11 15:52:42 bostic Exp $
*/
package com.sleepycat.examples;
diff --git a/bdb/java/src/com/sleepycat/examples/LockExample.java b/bdb/java/src/com/sleepycat/examples/LockExample.java
index 33b7d0538ce..d450193146a 100644
--- a/bdb/java/src/com/sleepycat/examples/LockExample.java
+++ b/bdb/java/src/com/sleepycat/examples/LockExample.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: LockExample.java,v 11.5 2001/01/04 14:23:30 dda Exp $
+ * $Id: LockExample.java,v 11.8 2002/01/11 15:52:43 bostic Exp $
*/
package com.sleepycat.examples;
@@ -150,7 +150,7 @@ class LockExample extends DbEnv
}
did_get = false;
DbLock lock = (DbLock)locks.elementAt(lockid);
- lock.put(this);
+ lock_put(lock);
}
System.out.println("Lock #" + lockid + " " +
(did_get ? "granted" : "released"));
diff --git a/bdb/java/src/com/sleepycat/examples/TpcbExample.java b/bdb/java/src/com/sleepycat/examples/TpcbExample.java
index 29a90790801..aa9d10b37bc 100644
--- a/bdb/java/src/com/sleepycat/examples/TpcbExample.java
+++ b/bdb/java/src/com/sleepycat/examples/TpcbExample.java
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: TpcbExample.java,v 11.9 2000/04/01 15:52:15 dda Exp $
+ * $Id: TpcbExample.java,v 11.16 2002/02/13 06:08:35 mjc Exp $
*/
package com.sleepycat.examples;
@@ -82,6 +82,10 @@ class TpcbExample extends DbEnv
set_errpfx(progname);
set_cachesize(0, cachesize == 0 ? 4 * 1024 * 1024 : cachesize, 0);
+ if ((flags & (Db.DB_TXN_NOSYNC)) != 0)
+ set_flags(Db.DB_TXN_NOSYNC, true);
+ flags &= ~(Db.DB_TXN_NOSYNC);
+
int local_flags = flags | Db.DB_CREATE;
if (initializing)
local_flags |= Db.DB_INIT_MPOOL;
@@ -117,8 +121,8 @@ class TpcbExample extends DbEnv
try {
dbp = new Db(this, 0);
dbp.set_h_nelem(h_nelem);
- dbp.open("account", null,
- Db.DB_HASH, Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
+ dbp.open(null, "account", null, Db.DB_HASH,
+ Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e1) {
@@ -154,8 +158,8 @@ class TpcbExample extends DbEnv
dbp.set_h_ffactor(1);
dbp.set_pagesize(512);
- dbp.open("branch", null,
- Db.DB_HASH, Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
+ dbp.open(null, "branch", null, Db.DB_HASH,
+ Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e3) {
@@ -191,8 +195,8 @@ class TpcbExample extends DbEnv
dbp.set_h_ffactor(0);
dbp.set_pagesize(512);
- dbp.open("teller", null,
- Db.DB_HASH, Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
+ dbp.open(null, "teller", null, Db.DB_HASH,
+ Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e5) {
@@ -218,8 +222,8 @@ class TpcbExample extends DbEnv
try {
dbp = new Db(this, 0);
dbp.set_re_len(HISTORY_LEN);
- dbp.open("history", null,
- Db.DB_RECNO, Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
+ dbp.open(null, "history", null, Db.DB_RECNO,
+ Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e7) {
@@ -349,13 +353,17 @@ class TpcbExample extends DbEnv
int err;
try {
adb = new Db(this, 0);
- adb.open("account", null, Db.DB_UNKNOWN, 0, 0);
+ adb.open(null, "account", null, Db.DB_UNKNOWN,
+ Db.DB_AUTO_COMMIT, 0);
bdb = new Db(this, 0);
- bdb.open("branch", null, Db.DB_UNKNOWN, 0, 0);
+ bdb.open(null, "branch", null, Db.DB_UNKNOWN,
+ Db.DB_AUTO_COMMIT, 0);
tdb = new Db(this, 0);
- tdb.open("teller", null, Db.DB_UNKNOWN, 0, 0);
+ tdb.open(null, "teller", null, Db.DB_UNKNOWN,
+ Db.DB_AUTO_COMMIT, 0);
hdb = new Db(this, 0);
- hdb.open("history", null, Db.DB_UNKNOWN, 0, 0);
+ hdb.open(null, "history", null, Db.DB_UNKNOWN,
+ Db.DB_AUTO_COMMIT, 0);
}
catch (DbException dbe) {
errExit(dbe, "Open of db files failed");
@@ -494,7 +502,11 @@ class TpcbExample extends DbEnv
tcurs.close();
hcurs.close();
- t.commit(0);
+ // null out t in advance; if the commit fails,
+ // we don't want to abort it in the catch clause.
+ DbTxn tmptxn = t;
+ t = null;
+ tmptxn.commit(0);
// END TIMING
return (0);
@@ -634,9 +646,9 @@ class TpcbExample extends DbEnv
history = history == 0 ? HISTORY : history;
if (verbose)
- System.out.println((long)accounts + " Accounts "
- + String.valueOf(branches) + " Branches "
- + String.valueOf(tellers) + " Tellers "
+ System.out.println((long)accounts + " Accounts, "
+ + String.valueOf(branches) + " Branches, "
+ + String.valueOf(tellers) + " Tellers, "
+ String.valueOf(history) + " History");
if (iflag) {
diff --git a/bdb/libdb_java/checkapi.prl b/bdb/libdb_java/checkapi.prl
index 25882c056cc..a27b8ffd107 100644
--- a/bdb/libdb_java/checkapi.prl
+++ b/bdb/libdb_java/checkapi.prl
@@ -30,7 +30,7 @@ nextline:
$def = "";
}
if ($in_def == 1) {
- $def .= $_;
+ $def .= " $_";
}
if (/\)/) {
$line = "";
@@ -42,6 +42,8 @@ nextline:
# remove comments
s@/\*[^*]*\*/@@g;
s@[ ][ ]*@ @g;
+ s@^[ ]@@g;
+ s@[ ]$@@g;
s@JNIEnv *\* *@JNIEnv @g;
s@([,*()]) @\1@g;
s@ ([,*()])@\1@g;
diff --git a/bdb/libdb_java/com_sleepycat_db_Db.h b/bdb/libdb_java/com_sleepycat_db_Db.h
index d9e1f1cbbc7..0787ae87aed 100644
--- a/bdb/libdb_java/com_sleepycat_db_Db.h
+++ b/bdb/libdb_java/com_sleepycat_db_Db.h
@@ -3,10 +3,211 @@
/* Header for class com_sleepycat_db_Db */
#ifndef _Included_com_sleepycat_db_Db
-#define _Included_com_sleepycat_db_Db
+#define _Included_com_sleepycat_db_Db
#ifdef __cplusplus
extern "C" {
#endif
+#undef com_sleepycat_db_Db_DB_BTREE
+#define com_sleepycat_db_Db_DB_BTREE 1L
+#undef com_sleepycat_db_Db_DB_DONOTINDEX
+#define com_sleepycat_db_Db_DB_DONOTINDEX -30999L
+#undef com_sleepycat_db_Db_DB_HASH
+#define com_sleepycat_db_Db_DB_HASH 2L
+#undef com_sleepycat_db_Db_DB_KEYEMPTY
+#define com_sleepycat_db_Db_DB_KEYEMPTY -30998L
+#undef com_sleepycat_db_Db_DB_KEYEXIST
+#define com_sleepycat_db_Db_DB_KEYEXIST -30997L
+#undef com_sleepycat_db_Db_DB_LOCK_DEADLOCK
+#define com_sleepycat_db_Db_DB_LOCK_DEADLOCK -30996L
+#undef com_sleepycat_db_Db_DB_LOCK_NOTGRANTED
+#define com_sleepycat_db_Db_DB_LOCK_NOTGRANTED -30995L
+#undef com_sleepycat_db_Db_DB_NOSERVER
+#define com_sleepycat_db_Db_DB_NOSERVER -30994L
+#undef com_sleepycat_db_Db_DB_NOSERVER_HOME
+#define com_sleepycat_db_Db_DB_NOSERVER_HOME -30993L
+#undef com_sleepycat_db_Db_DB_NOSERVER_ID
+#define com_sleepycat_db_Db_DB_NOSERVER_ID -30992L
+#undef com_sleepycat_db_Db_DB_NOTFOUND
+#define com_sleepycat_db_Db_DB_NOTFOUND -30991L
+#undef com_sleepycat_db_Db_DB_OLD_VERSION
+#define com_sleepycat_db_Db_DB_OLD_VERSION -30990L
+#undef com_sleepycat_db_Db_DB_PAGE_NOTFOUND
+#define com_sleepycat_db_Db_DB_PAGE_NOTFOUND -30989L
+#undef com_sleepycat_db_Db_DB_QUEUE
+#define com_sleepycat_db_Db_DB_QUEUE 4L
+#undef com_sleepycat_db_Db_DB_RECNO
+#define com_sleepycat_db_Db_DB_RECNO 3L
+#undef com_sleepycat_db_Db_DB_REP_DUPMASTER
+#define com_sleepycat_db_Db_DB_REP_DUPMASTER -30988L
+#undef com_sleepycat_db_Db_DB_REP_HOLDELECTION
+#define com_sleepycat_db_Db_DB_REP_HOLDELECTION -30987L
+#undef com_sleepycat_db_Db_DB_REP_NEWMASTER
+#define com_sleepycat_db_Db_DB_REP_NEWMASTER -30986L
+#undef com_sleepycat_db_Db_DB_REP_NEWSITE
+#define com_sleepycat_db_Db_DB_REP_NEWSITE -30985L
+#undef com_sleepycat_db_Db_DB_REP_OUTDATED
+#define com_sleepycat_db_Db_DB_REP_OUTDATED -30984L
+#undef com_sleepycat_db_Db_DB_RUNRECOVERY
+#define com_sleepycat_db_Db_DB_RUNRECOVERY -30982L
+#undef com_sleepycat_db_Db_DB_SECONDARY_BAD
+#define com_sleepycat_db_Db_DB_SECONDARY_BAD -30981L
+#undef com_sleepycat_db_Db_DB_TXN_ABORT
+#define com_sleepycat_db_Db_DB_TXN_ABORT 0L
+#undef com_sleepycat_db_Db_DB_TXN_APPLY
+#define com_sleepycat_db_Db_DB_TXN_APPLY 1L
+#undef com_sleepycat_db_Db_DB_TXN_BACKWARD_ROLL
+#define com_sleepycat_db_Db_DB_TXN_BACKWARD_ROLL 3L
+#undef com_sleepycat_db_Db_DB_TXN_FORWARD_ROLL
+#define com_sleepycat_db_Db_DB_TXN_FORWARD_ROLL 4L
+#undef com_sleepycat_db_Db_DB_TXN_PRINT
+#define com_sleepycat_db_Db_DB_TXN_PRINT 8L
+#undef com_sleepycat_db_Db_DB_UNKNOWN
+#define com_sleepycat_db_Db_DB_UNKNOWN 5L
+#undef com_sleepycat_db_Db_DB_VERIFY_BAD
+#define com_sleepycat_db_Db_DB_VERIFY_BAD -30980L
+/* Inaccessible static: DB_AFTER */
+/* Inaccessible static: DB_AGGRESSIVE */
+/* Inaccessible static: DB_APPEND */
+/* Inaccessible static: DB_ARCH_ABS */
+/* Inaccessible static: DB_ARCH_DATA */
+/* Inaccessible static: DB_ARCH_LOG */
+/* Inaccessible static: DB_AUTO_COMMIT */
+/* Inaccessible static: DB_BEFORE */
+/* Inaccessible static: DB_CACHED_COUNTS */
+/* Inaccessible static: DB_CDB_ALLDB */
+/* Inaccessible static: DB_CHKSUM_SHA1 */
+/* Inaccessible static: DB_CLIENT */
+/* Inaccessible static: DB_CONSUME */
+/* Inaccessible static: DB_CONSUME_WAIT */
+/* Inaccessible static: DB_CREATE */
+/* Inaccessible static: DB_CURRENT */
+/* Inaccessible static: DB_CXX_NO_EXCEPTIONS */
+/* Inaccessible static: DB_DBT_MALLOC */
+/* Inaccessible static: DB_DBT_PARTIAL */
+/* Inaccessible static: DB_DBT_REALLOC */
+/* Inaccessible static: DB_DBT_USERMEM */
+/* Inaccessible static: DB_DIRECT */
+/* Inaccessible static: DB_DIRECT_DB */
+/* Inaccessible static: DB_DIRECT_LOG */
+/* Inaccessible static: DB_DIRTY_READ */
+/* Inaccessible static: DB_DUP */
+/* Inaccessible static: DB_DUPSORT */
+/* Inaccessible static: DB_EID_BROADCAST */
+/* Inaccessible static: DB_EID_INVALID */
+/* Inaccessible static: DB_ENCRYPT */
+/* Inaccessible static: DB_ENCRYPT_AES */
+/* Inaccessible static: DB_EXCL */
+/* Inaccessible static: DB_FAST_STAT */
+/* Inaccessible static: DB_FIRST */
+/* Inaccessible static: DB_FLUSH */
+/* Inaccessible static: DB_FORCE */
+/* Inaccessible static: DB_GET_BOTH */
+/* Inaccessible static: DB_GET_BOTH_RANGE */
+/* Inaccessible static: DB_GET_RECNO */
+/* Inaccessible static: DB_INIT_CDB */
+/* Inaccessible static: DB_INIT_LOCK */
+/* Inaccessible static: DB_INIT_LOG */
+/* Inaccessible static: DB_INIT_MPOOL */
+/* Inaccessible static: DB_INIT_TXN */
+/* Inaccessible static: DB_JOINENV */
+/* Inaccessible static: DB_JOIN_ITEM */
+/* Inaccessible static: DB_JOIN_NOSORT */
+/* Inaccessible static: DB_KEYFIRST */
+/* Inaccessible static: DB_KEYLAST */
+/* Inaccessible static: DB_LAST */
+/* Inaccessible static: DB_LOCKDOWN */
+/* Inaccessible static: DB_LOCK_DEFAULT */
+/* Inaccessible static: DB_LOCK_EXPIRE */
+/* Inaccessible static: DB_LOCK_GET */
+/* Inaccessible static: DB_LOCK_GET_TIMEOUT */
+/* Inaccessible static: DB_LOCK_IREAD */
+/* Inaccessible static: DB_LOCK_IWR */
+/* Inaccessible static: DB_LOCK_IWRITE */
+/* Inaccessible static: DB_LOCK_MAXLOCKS */
+/* Inaccessible static: DB_LOCK_MINLOCKS */
+/* Inaccessible static: DB_LOCK_MINWRITE */
+/* Inaccessible static: DB_LOCK_NOWAIT */
+/* Inaccessible static: DB_LOCK_OLDEST */
+/* Inaccessible static: DB_LOCK_PUT */
+/* Inaccessible static: DB_LOCK_PUT_ALL */
+/* Inaccessible static: DB_LOCK_PUT_OBJ */
+/* Inaccessible static: DB_LOCK_RANDOM */
+/* Inaccessible static: DB_LOCK_READ */
+/* Inaccessible static: DB_LOCK_TIMEOUT */
+/* Inaccessible static: DB_LOCK_WRITE */
+/* Inaccessible static: DB_LOCK_YOUNGEST */
+/* Inaccessible static: DB_MULTIPLE */
+/* Inaccessible static: DB_MULTIPLE_KEY */
+/* Inaccessible static: DB_NEXT */
+/* Inaccessible static: DB_NEXT_DUP */
+/* Inaccessible static: DB_NEXT_NODUP */
+/* Inaccessible static: DB_NODUPDATA */
+/* Inaccessible static: DB_NOLOCKING */
+/* Inaccessible static: DB_NOMMAP */
+/* Inaccessible static: DB_NOORDERCHK */
+/* Inaccessible static: DB_NOOVERWRITE */
+/* Inaccessible static: DB_NOPANIC */
+/* Inaccessible static: DB_NOSYNC */
+/* Inaccessible static: DB_ODDFILESIZE */
+/* Inaccessible static: DB_ORDERCHKONLY */
+/* Inaccessible static: DB_OVERWRITE */
+/* Inaccessible static: DB_PANIC_ENVIRONMENT */
+/* Inaccessible static: DB_POSITION */
+/* Inaccessible static: DB_PREV */
+/* Inaccessible static: DB_PREV_NODUP */
+/* Inaccessible static: DB_PRINTABLE */
+/* Inaccessible static: DB_PRIORITY_DEFAULT */
+/* Inaccessible static: DB_PRIORITY_HIGH */
+/* Inaccessible static: DB_PRIORITY_LOW */
+/* Inaccessible static: DB_PRIORITY_VERY_HIGH */
+/* Inaccessible static: DB_PRIORITY_VERY_LOW */
+/* Inaccessible static: DB_PRIVATE */
+/* Inaccessible static: DB_RDONLY */
+/* Inaccessible static: DB_RECNUM */
+/* Inaccessible static: DB_RECORDCOUNT */
+/* Inaccessible static: DB_RECOVER */
+/* Inaccessible static: DB_RECOVER_FATAL */
+/* Inaccessible static: DB_REGION_INIT */
+/* Inaccessible static: DB_RENUMBER */
+/* Inaccessible static: DB_REP_CLIENT */
+/* Inaccessible static: DB_REP_LOGSONLY */
+/* Inaccessible static: DB_REP_MASTER */
+/* Inaccessible static: DB_REP_PERMANENT */
+/* Inaccessible static: DB_REP_UNAVAIL */
+/* Inaccessible static: DB_REVSPLITOFF */
+/* Inaccessible static: DB_RMW */
+/* Inaccessible static: DB_SALVAGE */
+/* Inaccessible static: DB_SET */
+/* Inaccessible static: DB_SET_LOCK_TIMEOUT */
+/* Inaccessible static: DB_SET_RANGE */
+/* Inaccessible static: DB_SET_RECNO */
+/* Inaccessible static: DB_SET_TXN_TIMEOUT */
+/* Inaccessible static: DB_SNAPSHOT */
+/* Inaccessible static: DB_STAT_CLEAR */
+/* Inaccessible static: DB_SYSTEM_MEM */
+/* Inaccessible static: DB_THREAD */
+/* Inaccessible static: DB_TRUNCATE */
+/* Inaccessible static: DB_TXN_NOSYNC */
+/* Inaccessible static: DB_TXN_NOWAIT */
+/* Inaccessible static: DB_TXN_SYNC */
+/* Inaccessible static: DB_TXN_WRITE_NOSYNC */
+/* Inaccessible static: DB_UPGRADE */
+/* Inaccessible static: DB_USE_ENVIRON */
+/* Inaccessible static: DB_USE_ENVIRON_ROOT */
+/* Inaccessible static: DB_VERB_CHKPOINT */
+/* Inaccessible static: DB_VERB_DEADLOCK */
+/* Inaccessible static: DB_VERB_RECOVERY */
+/* Inaccessible static: DB_VERB_REPLICATION */
+/* Inaccessible static: DB_VERB_WAITSFOR */
+/* Inaccessible static: DB_VERIFY */
+/* Inaccessible static: DB_VERSION_MAJOR */
+/* Inaccessible static: DB_VERSION_MINOR */
+/* Inaccessible static: DB_VERSION_PATCH */
+/* Inaccessible static: DB_WRITECURSOR */
+/* Inaccessible static: DB_XA_CREATE */
+/* Inaccessible static: DB_XIDDATASIZE */
+/* Inaccessible static: DB_YIELDCPU */
+/* Inaccessible static: already_loaded_ */
/*
* Class: com_sleepycat_db_Db
* Method: _init
@@ -25,6 +226,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1notify_1internal
/*
* Class: com_sleepycat_db_Db
+ * Method: _associate
+ * Signature: (Lcom/sleepycat/db/DbTxn;Lcom/sleepycat/db/Db;Lcom/sleepycat/db/DbSecondaryKeyCreate;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1associate
+ (JNIEnv *, jobject, jobject, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_Db
* Method: _close
* Signature: (I)I
*/
@@ -122,10 +331,18 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_key_1range
/*
* Class: com_sleepycat_db_Db
* Method: _open
- * Signature: (Ljava/lang/String;Ljava/lang/String;III)V
+ * Signature: (Lcom/sleepycat/db/DbTxn;Ljava/lang/String;Ljava/lang/String;III)V
*/
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1open
- (JNIEnv *, jobject, jstring, jstring, jint, jint, jint);
+ (JNIEnv *, jobject, jobject, jstring, jstring, jint, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_Db
+ * Method: pget
+ * Signature: (Lcom/sleepycat/db/DbTxn;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_pget
+ (JNIEnv *, jobject, jobject, jobject, jobject, jobject, jint);
/*
* Class: com_sleepycat_db_Db
@@ -137,18 +354,18 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_put
/*
* Class: com_sleepycat_db_Db
- * Method: rename
+ * Method: _rename
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_rename
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1rename
(JNIEnv *, jobject, jstring, jstring, jstring, jint);
/*
* Class: com_sleepycat_db_Db
- * Method: remove
+ * Method: _remove
* Signature: (Ljava/lang/String;Ljava/lang/String;I)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_remove
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1remove
(JNIEnv *, jobject, jstring, jstring, jint);
/*
@@ -201,6 +418,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1cachesize
/*
* Class: com_sleepycat_db_Db
+ * Method: set_cache_priority
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1cache_1priority
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_Db
* Method: dup_compare_changed
* Signature: (Lcom/sleepycat/db/DbDupCompare;)V
*/
@@ -209,6 +434,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_dup_1compare_1changed
/*
* Class: com_sleepycat_db_Db
+ * Method: set_encrypt
+ * Signature: (Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1encrypt
+ (JNIEnv *, jobject, jstring, jint);
+
+/*
+ * Class: com_sleepycat_db_Db
* Method: feedback_changed
* Signature: (Lcom/sleepycat/db/DbFeedback;)V
*/
@@ -225,6 +458,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1flags
/*
* Class: com_sleepycat_db_Db
+ * Method: get_flags_raw
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get_1flags_1raw
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_sleepycat_db_Db
* Method: set_h_ffactor
* Signature: (I)V
*/
@@ -314,13 +555,21 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_stat
/*
* Class: com_sleepycat_db_Db
* Method: sync
- * Signature: (I)I
+ * Signature: (I)V
*/
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_sync
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_sync
(JNIEnv *, jobject, jint);
/*
* Class: com_sleepycat_db_Db
+ * Method: truncate
+ * Signature: (Lcom/sleepycat/db/DbTxn;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_truncate
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_Db
* Method: upgrade
* Signature: (Ljava/lang/String;I)V
*/
diff --git a/bdb/libdb_java/com_sleepycat_db_DbEnv.h b/bdb/libdb_java/com_sleepycat_db_DbEnv.h
index 4168ea9abe2..f239dfc7593 100644
--- a/bdb/libdb_java/com_sleepycat_db_DbEnv.h
+++ b/bdb/libdb_java/com_sleepycat_db_DbEnv.h
@@ -3,7 +3,7 @@
/* Header for class com_sleepycat_db_DbEnv */
#ifndef _Included_com_sleepycat_db_DbEnv
-#define _Included_com_sleepycat_db_DbEnv
+#define _Included_com_sleepycat_db_DbEnv
#ifdef __cplusplus
extern "C" {
#endif
@@ -17,6 +17,22 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1close
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: dbremove
+ * Signature: (Lcom/sleepycat/db/DbTxn;Ljava/lang/String;Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_dbremove
+ (JNIEnv *, jobject, jobject, jstring, jstring, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
+ * Method: dbrename
+ * Signature: (Lcom/sleepycat/db/DbTxn;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_dbrename
+ (JNIEnv *, jobject, jobject, jstring, jstring, jstring, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: err
* Signature: (ILjava/lang/String;)V
*/
@@ -57,6 +73,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init_1using_1db
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: _init_using_xa
+ * Signature: (Lcom/sleepycat/db/DbErrcall;II)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init_1using_1xa
+ (JNIEnv *, jobject, jobject, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: _notify_db_close
* Signature: ()V
*/
@@ -89,6 +113,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1cachesize
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: set_encrypt
+ * Signature: (Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1encrypt
+ (JNIEnv *, jobject, jstring, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: _set_errcall
* Signature: (Lcom/sleepycat/db/DbErrcall;)V
*/
@@ -106,7 +138,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errpfx
/*
* Class: com_sleepycat_db_DbEnv
* Method: feedback_changed
- * Signature: (Lcom/sleepycat/db/DbFeedback;)V
+ * Signature: (Lcom/sleepycat/db/DbEnvFeedback;)V
*/
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_feedback_1changed
(JNIEnv *, jobject, jobject);
@@ -114,10 +146,10 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_feedback_1changed
/*
* Class: com_sleepycat_db_DbEnv
* Method: set_verbose
- * Signature: (II)V
+ * Signature: (IZ)V
*/
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1verbose
- (JNIEnv *, jobject, jint, jint);
+ (JNIEnv *, jobject, jint, jboolean);
/*
* Class: com_sleepycat_db_DbEnv
@@ -153,6 +185,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lg_1max
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: set_lg_regionmax
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lg_1regionmax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: set_lk_conflicts
* Signature: ([[B)V
*/
@@ -209,59 +249,35 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1mp_1mmapsize
/*
* Class: com_sleepycat_db_DbEnv
- * Method: set_mutexlocks
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1mutexlocks
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_DbEnv
- * Method: set_pageyield
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1pageyield
- (JNIEnv *, jclass, jint);
-
-/*
- * Class: com_sleepycat_db_DbEnv
- * Method: set_panicstate
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1panicstate
- (JNIEnv *, jclass, jint);
-
-/*
- * Class: com_sleepycat_db_DbEnv
- * Method: recovery_init_changed
- * Signature: (Lcom/sleepycat/db/DbRecoveryInit;)V
+ * Method: set_flags
+ * Signature: (IZ)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_recovery_1init_1changed
- (JNIEnv *, jobject, jobject);
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1flags
+ (JNIEnv *, jobject, jint, jboolean);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: set_region_init
- * Signature: (I)V
+ * Method: set_rep_limit
+ * Signature: (II)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1region_1init
- (JNIEnv *, jclass, jint);
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1rep_1limit
+ (JNIEnv *, jobject, jint, jint);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: set_flags
- * Signature: (II)V
+ * Method: rep_transport_changed
+ * Signature: (ILcom/sleepycat/db/DbRepTransport;)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1flags
- (JNIEnv *, jobject, jint, jint);
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_rep_1transport_1changed
+ (JNIEnv *, jobject, jint, jobject);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: set_server
- * Signature: (Ljava/lang/String;JJI)V
+ * Method: set_rpc_server
+ * Signature: (Lcom/sleepycat/db/DbClient;Ljava/lang/String;JJI)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1server
- (JNIEnv *, jobject, jstring, jlong, jlong, jint);
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1rpc_1server
+ (JNIEnv *, jobject, jobject, jstring, jlong, jlong, jint);
/*
* Class: com_sleepycat_db_DbEnv
@@ -277,7 +293,15 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1shm_1key
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1tas_1spins
- (JNIEnv *, jclass, jint);
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
+ * Method: set_timeout
+ * Signature: (JI)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1timeout
+ (JNIEnv *, jobject, jlong, jint);
/*
* Class: com_sleepycat_db_DbEnv
@@ -289,10 +313,10 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1tmp_1dir
/*
* Class: com_sleepycat_db_DbEnv
- * Method: tx_recover_changed
- * Signature: (Lcom/sleepycat/db/DbTxnRecover;)V
+ * Method: app_dispatch_changed
+ * Signature: (Lcom/sleepycat/db/DbAppDispatch;)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_tx_1recover_1changed
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_app_1dispatch_1changed
(JNIEnv *, jobject, jobject);
/*
@@ -369,6 +393,14 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1get
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: lock_put
+ * Signature: (Lcom/sleepycat/db/DbLock;)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_lock_1put
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: lock_id
* Signature: ()I
*/
@@ -377,11 +409,27 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1id
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: lock_id_free
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_lock_1id_1free
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: lock_stat
- * Signature: ()Lcom/sleepycat/db/DbLockStat;
+ * Signature: (I)Lcom/sleepycat/db/DbLockStat;
*/
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1stat
- (JNIEnv *, jobject);
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
+ * Method: lock_vec
+ * Signature: (II[Lcom/sleepycat/db/DbLockRequest;II)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_lock_1vec
+ (JNIEnv *, jobject, jint, jint, jobjectArray, jint, jint);
/*
* Class: com_sleepycat_db_DbEnv
@@ -401,6 +449,14 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_log_1compare
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: log_cursor
+ * Signature: (I)Lcom/sleepycat/db/DbLogc;
+ */
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1cursor
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: log_file
* Signature: (Lcom/sleepycat/db/DbLsn;)Ljava/lang/String;
*/
@@ -417,14 +473,6 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1flush
/*
* Class: com_sleepycat_db_DbEnv
- * Method: log_get
- * Signature: (Lcom/sleepycat/db/DbLsn;Lcom/sleepycat/db/Dbt;I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1get
- (JNIEnv *, jobject, jobject, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_DbEnv
* Method: log_put
* Signature: (Lcom/sleepycat/db/DbLsn;Lcom/sleepycat/db/Dbt;I)V
*/
@@ -434,49 +482,65 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1put
/*
* Class: com_sleepycat_db_DbEnv
* Method: log_stat
- * Signature: ()Lcom/sleepycat/db/DbLogStat;
+ * Signature: (I)Lcom/sleepycat/db/DbLogStat;
*/
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1stat
- (JNIEnv *, jobject);
+ (JNIEnv *, jobject, jint);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: log_register
- * Signature: (Lcom/sleepycat/db/Db;Ljava/lang/String;)V
+ * Method: memp_stat
+ * Signature: (I)Lcom/sleepycat/db/DbMpoolStat;
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1register
- (JNIEnv *, jobject, jobject, jstring);
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_memp_1stat
+ (JNIEnv *, jobject, jint);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: log_unregister
- * Signature: (Lcom/sleepycat/db/Db;)V
+ * Method: memp_fstat
+ * Signature: (I)[Lcom/sleepycat/db/DbMpoolFStat;
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1unregister
- (JNIEnv *, jobject, jobject);
+JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_memp_1fstat
+ (JNIEnv *, jobject, jint);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: memp_stat
- * Signature: ()Lcom/sleepycat/db/DbMpoolStat;
+ * Method: memp_trickle
+ * Signature: (I)I
*/
-JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_memp_1stat
- (JNIEnv *, jobject);
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_memp_1trickle
+ (JNIEnv *, jobject, jint);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: memp_fstat
- * Signature: ()[Lcom/sleepycat/db/DbMpoolFStat;
+ * Method: rep_elect
+ * Signature: (III)I
*/
-JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_memp_1fstat
- (JNIEnv *, jobject);
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_rep_1elect
+ (JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_sleepycat_db_DbEnv
- * Method: memp_trickle
- * Signature: (I)I
+ * Method: rep_process_message
+ * Signature: (Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/DbEnv$RepProcessMessage;)I
*/
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_memp_1trickle
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_rep_1process_1message
+ (JNIEnv *, jobject, jobject, jobject, jobject);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
+ * Method: rep_start
+ * Signature: (Lcom/sleepycat/db/Dbt;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_rep_1start
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
+ * Method: rep_stat
+ * Signature: (I)Lcom/sleepycat/db/DbRepStat;
+ */
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_rep_1stat
(JNIEnv *, jobject, jint);
/*
@@ -490,18 +554,26 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1begin
/*
* Class: com_sleepycat_db_DbEnv
* Method: txn_checkpoint
- * Signature: (III)I
+ * Signature: (III)V
*/
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_txn_1checkpoint
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_txn_1checkpoint
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: com_sleepycat_db_DbEnv
+ * Method: txn_recover
+ * Signature: (II)[Lcom/sleepycat/db/DbPreplist;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_txn_1recover
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_DbEnv
* Method: txn_stat
- * Signature: ()Lcom/sleepycat/db/DbTxnStat;
+ * Signature: (I)Lcom/sleepycat/db/DbTxnStat;
*/
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1stat
- (JNIEnv *, jobject);
+ (JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
diff --git a/bdb/libdb_java/com_sleepycat_db_DbLock.h b/bdb/libdb_java/com_sleepycat_db_DbLock.h
index 8a1c135bb3b..9f3d77d44bc 100644
--- a/bdb/libdb_java/com_sleepycat_db_DbLock.h
+++ b/bdb/libdb_java/com_sleepycat_db_DbLock.h
@@ -3,7 +3,7 @@
/* Header for class com_sleepycat_db_DbLock */
#ifndef _Included_com_sleepycat_db_DbLock
-#define _Included_com_sleepycat_db_DbLock
+#define _Included_com_sleepycat_db_DbLock
#ifdef __cplusplus
extern "C" {
#endif
@@ -15,14 +15,6 @@ extern "C" {
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_finalize
(JNIEnv *, jobject);
-/*
- * Class: com_sleepycat_db_DbLock
- * Method: put
- * Signature: (Lcom/sleepycat/db/DbEnv;)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_put
- (JNIEnv *, jobject, jobject);
-
#ifdef __cplusplus
}
#endif
diff --git a/bdb/libdb_java/com_sleepycat_db_DbLogc.h b/bdb/libdb_java/com_sleepycat_db_DbLogc.h
new file mode 100644
index 00000000000..8d029c761ba
--- /dev/null
+++ b/bdb/libdb_java/com_sleepycat_db_DbLogc.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_sleepycat_db_DbLogc */
+
+#ifndef _Included_com_sleepycat_db_DbLogc
+#define _Included_com_sleepycat_db_DbLogc
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_sleepycat_db_DbLogc
+ * Method: close
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLogc_close
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbLogc
+ * Method: get
+ * Signature: (Lcom/sleepycat/db/DbLsn;Lcom/sleepycat/db/Dbt;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbLogc_get
+ (JNIEnv *, jobject, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbLogc
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLogc_finalize
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/bdb/libdb_java/com_sleepycat_db_DbLsn.h b/bdb/libdb_java/com_sleepycat_db_DbLsn.h
index 093eaf372b5..080fa0a8758 100644
--- a/bdb/libdb_java/com_sleepycat_db_DbLsn.h
+++ b/bdb/libdb_java/com_sleepycat_db_DbLsn.h
@@ -3,7 +3,7 @@
/* Header for class com_sleepycat_db_DbLsn */
#ifndef _Included_com_sleepycat_db_DbLsn
-#define _Included_com_sleepycat_db_DbLsn
+#define _Included_com_sleepycat_db_DbLsn
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/bdb/libdb_java/com_sleepycat_db_DbTxn.h b/bdb/libdb_java/com_sleepycat_db_DbTxn.h
index 4dcf47405c0..59641c041a4 100644
--- a/bdb/libdb_java/com_sleepycat_db_DbTxn.h
+++ b/bdb/libdb_java/com_sleepycat_db_DbTxn.h
@@ -3,7 +3,7 @@
/* Header for class com_sleepycat_db_DbTxn */
#ifndef _Included_com_sleepycat_db_DbTxn
-#define _Included_com_sleepycat_db_DbTxn
+#define _Included_com_sleepycat_db_DbTxn
#ifdef __cplusplus
extern "C" {
#endif
@@ -25,6 +25,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_commit
/*
* Class: com_sleepycat_db_DbTxn
+ * Method: discard
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_discard
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_DbTxn
* Method: id
* Signature: ()I
*/
@@ -34,18 +42,18 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbTxn_id
/*
* Class: com_sleepycat_db_DbTxn
* Method: prepare
- * Signature: ()V
+ * Signature: ([B)V
*/
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_prepare
- (JNIEnv *, jobject);
+ (JNIEnv *, jobject, jbyteArray);
/*
* Class: com_sleepycat_db_DbTxn
- * Method: finalize
- * Signature: ()V
+ * Method: set_timeout
+ * Signature: (JI)V
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_finalize
- (JNIEnv *, jobject);
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_set_1timeout
+ (JNIEnv *, jobject, jlong, jint);
#ifdef __cplusplus
}
diff --git a/bdb/libdb_java/com_sleepycat_db_DbUtil.h b/bdb/libdb_java/com_sleepycat_db_DbUtil.h
new file mode 100644
index 00000000000..7f8495590c0
--- /dev/null
+++ b/bdb/libdb_java/com_sleepycat_db_DbUtil.h
@@ -0,0 +1,22 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_sleepycat_db_DbUtil */
+
+#ifndef _Included_com_sleepycat_db_DbUtil
+#define _Included_com_sleepycat_db_DbUtil
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Inaccessible static: big_endian */
+/*
+ * Class: com_sleepycat_db_DbUtil
+ * Method: is_big_endian
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_sleepycat_db_DbUtil_is_1big_1endian
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/bdb/libdb_java/com_sleepycat_db_Dbc.h b/bdb/libdb_java/com_sleepycat_db_Dbc.h
index e62679c6f66..447ab234844 100644
--- a/bdb/libdb_java/com_sleepycat_db_Dbc.h
+++ b/bdb/libdb_java/com_sleepycat_db_Dbc.h
@@ -3,7 +3,7 @@
/* Header for class com_sleepycat_db_Dbc */
#ifndef _Included_com_sleepycat_db_Dbc
-#define _Included_com_sleepycat_db_Dbc
+#define _Included_com_sleepycat_db_Dbc
#ifdef __cplusplus
extern "C" {
#endif
@@ -49,6 +49,14 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_get
/*
* Class: com_sleepycat_db_Dbc
+ * Method: pget
+ * Signature: (Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_pget
+ (JNIEnv *, jobject, jobject, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_Dbc
* Method: put
* Signature: (Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I
*/
diff --git a/bdb/libdb_java/com_sleepycat_db_Dbt.h b/bdb/libdb_java/com_sleepycat_db_Dbt.h
index cdb58c682c9..c09bd8e6131 100644
--- a/bdb/libdb_java/com_sleepycat_db_Dbt.h
+++ b/bdb/libdb_java/com_sleepycat_db_Dbt.h
@@ -3,7 +3,7 @@
/* Header for class com_sleepycat_db_Dbt */
#ifndef _Included_com_sleepycat_db_Dbt
-#define _Included_com_sleepycat_db_Dbt
+#define _Included_com_sleepycat_db_Dbt
#ifdef __cplusplus
extern "C" {
#endif
@@ -17,138 +17,18 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_finalize
/*
* Class: com_sleepycat_db_Dbt
- * Method: get_data
- * Signature: ()[B
- */
-JNIEXPORT jbyteArray JNICALL Java_com_sleepycat_db_Dbt_get_1data
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: internal_set_data
- * Signature: ([B)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_internal_1set_1data
- (JNIEnv *, jobject, jbyteArray);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_offset
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1offset
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_offset
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1offset
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_size
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1size
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_size
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1size
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_ulen
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1ulen
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_ulen
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1ulen
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_dlen
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1dlen
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_dlen
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1dlen
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_doff
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1doff
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_doff
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1doff
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_flags
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1flags
- (JNIEnv *, jobject);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_flags
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1flags
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: set_recno_key_data
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1recno_1key_1data
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_sleepycat_db_Dbt
- * Method: get_recno_key_data
- * Signature: ()I
+ * Method: init
+ * Signature: ()V
*/
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1recno_1key_1data
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_init
(JNIEnv *, jobject);
/*
* Class: com_sleepycat_db_Dbt
- * Method: init
- * Signature: ()V
+ * Method: create_data
+ * Signature: ()[B
*/
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_init
+JNIEXPORT jbyteArray JNICALL Java_com_sleepycat_db_Dbt_create_1data
(JNIEnv *, jobject);
#ifdef __cplusplus
diff --git a/bdb/libdb_java/com_sleepycat_db_xa_DbXAResource.h b/bdb/libdb_java/com_sleepycat_db_xa_DbXAResource.h
new file mode 100644
index 00000000000..00e9e2e6893
--- /dev/null
+++ b/bdb/libdb_java/com_sleepycat_db_xa_DbXAResource.h
@@ -0,0 +1,95 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_sleepycat_db_xa_DbXAResource */
+
+#ifndef _Included_com_sleepycat_db_xa_DbXAResource
+#define _Included_com_sleepycat_db_xa_DbXAResource
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Inaccessible static: unique_rmid */
+/* Inaccessible static: class_00024com_00024sleepycat_00024db_00024xa_00024DbXAResource */
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _init
+ * Signature: (Ljava/lang/String;II)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1init
+ (JNIEnv *, jobject, jstring, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _close
+ * Signature: (Ljava/lang/String;II)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1close
+ (JNIEnv *, jobject, jstring, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _commit
+ * Signature: (Ljavax/transaction/xa/Xid;IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1commit
+ (JNIEnv *, jobject, jobject, jint, jboolean);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _end
+ * Signature: (Ljavax/transaction/xa/Xid;II)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1end
+ (JNIEnv *, jobject, jobject, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _forget
+ * Signature: (Ljavax/transaction/xa/Xid;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1forget
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _prepare
+ * Signature: (Ljavax/transaction/xa/Xid;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_xa_DbXAResource__1prepare
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _recover
+ * Signature: (II)[Ljavax/transaction/xa/Xid;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_xa_DbXAResource__1recover
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _rollback
+ * Signature: (Ljavax/transaction/xa/Xid;I)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1rollback
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: _start
+ * Signature: (Ljavax/transaction/xa/Xid;II)V
+ */
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1start
+ (JNIEnv *, jobject, jobject, jint, jint);
+
+/*
+ * Class: com_sleepycat_db_xa_DbXAResource
+ * Method: xa_attach
+ * Signature: (Ljavax/transaction/xa/Xid;Ljava/lang/Integer;)Lcom/sleepycat/db/xa/DbXAResource$DbAttach;
+ */
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_xa_DbXAResource_xa_1attach
+ (JNIEnv *, jclass, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/bdb/libdb_java/java_Db.c b/bdb/libdb_java/java_Db.c
index 5b01e5068d6..465c40f7d5a 100644
--- a/bdb/libdb_java/java_Db.c
+++ b/bdb/libdb_java/java_Db.c
@@ -1,24 +1,25 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_Db.c,v 11.34 2000/11/30 00:58:38 ubell Exp $";
+static const char revid[] = "$Id: java_Db.c,v 11.80 2002/08/29 14:22:23 margo Exp $";
#endif /* not lint */
#include <jni.h>
#include <stdlib.h>
#include <string.h>
-#include "db.h"
#include "db_int.h"
-#include "db_page.h"
-#include "db_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc_auto/db_ext.h"
#include "java_util.h"
+#include "java_stat_auto.h"
#include "com_sleepycat_db_Db.h"
/* This struct is used in Db.verify and its callback */
@@ -30,25 +31,29 @@ struct verify_callback_struct {
jmethodID writemid;
};
-JAVADB_WO_ACCESS_METHOD(Db, jint, flags, DB, flags)
-JAVADB_WO_ACCESS_METHOD(Db, jint, h_1ffactor, DB, h_ffactor)
-JAVADB_WO_ACCESS_METHOD(Db, jint, h_1nelem, DB, h_nelem)
-JAVADB_WO_ACCESS_METHOD(Db, jint, lorder, DB, lorder)
-JAVADB_WO_ACCESS_METHOD(Db, jint, re_1delim, DB, re_delim)
-JAVADB_WO_ACCESS_METHOD(Db, jint, re_1len, DB, re_len)
-JAVADB_WO_ACCESS_METHOD(Db, jint, re_1pad, DB, re_pad)
-JAVADB_WO_ACCESS_METHOD(Db, jint, q_1extentsize, DB, q_extentsize)
-JAVADB_WO_ACCESS_METHOD(Db, jint, bt_1maxkey, DB, bt_maxkey)
-JAVADB_WO_ACCESS_METHOD(Db, jint, bt_1minkey, DB, bt_minkey)
-
-/* This only gets called once ever, at the beginning of execution
+JAVADB_GET_FLD(Db, jint, flags_1raw, DB, flags)
+
+JAVADB_SET_METH(Db, jint, flags, DB, flags)
+JAVADB_SET_METH(Db, jint, h_1ffactor, DB, h_ffactor)
+JAVADB_SET_METH(Db, jint, h_1nelem, DB, h_nelem)
+JAVADB_SET_METH(Db, jint, lorder, DB, lorder)
+JAVADB_SET_METH(Db, jint, re_1delim, DB, re_delim)
+JAVADB_SET_METH(Db, jint, re_1len, DB, re_len)
+JAVADB_SET_METH(Db, jint, re_1pad, DB, re_pad)
+JAVADB_SET_METH(Db, jint, q_1extentsize, DB, q_extentsize)
+JAVADB_SET_METH(Db, jint, bt_1maxkey, DB, bt_maxkey)
+JAVADB_SET_METH(Db, jint, bt_1minkey, DB, bt_minkey)
+
+/*
+ * This only gets called once ever, at the beginning of execution
* and can be used to initialize unchanging methodIds, fieldIds, etc.
*/
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_one_1time_1init
(JNIEnv *jnienv, /*Db.class*/ jclass jthisclass)
{
- COMPQUIET(jnienv, NULL);
COMPQUIET(jthisclass, NULL);
+
+ one_time_init(jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1init
@@ -66,12 +71,31 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1init
err = db_create(&db, dbenv, flags);
if (verify_return(jnienv, err, 0)) {
set_private_dbobj(jnienv, name_DB, jthis, db);
- dbinfo = dbji_construct(jnienv, flags);
+ dbinfo = dbji_construct(jnienv, jthis, flags);
set_private_info(jnienv, name_DB, jthis, dbinfo);
- db->cj_internal = dbinfo;
+ db->api_internal = dbinfo;
}
}
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1associate
+ (JNIEnv *jnienv, /*Db*/ jobject jthis, /* DbTxn */ jobject jtxn,
+ /*Db*/ jobject jsecondary, /*DbSecondaryKeyCreate*/ jobject jcallback,
+ jint flags)
+{
+ DB *db, *secondary;
+ DB_JAVAINFO *second_info;
+ DB_TXN *txn;
+
+ db = get_DB(jnienv, jthis);
+ txn = get_DB_TXN(jnienv, jtxn);
+ secondary = get_DB(jnienv, jsecondary);
+
+ second_info = (DB_JAVAINFO*)secondary->api_internal;
+ dbji_set_assoc_object(second_info, jnienv, db, txn, secondary,
+ jcallback, flags);
+
+}
+
JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db__1close
(JNIEnv *jnienv, /*Db*/ jobject jthis, jint flags)
{
@@ -84,24 +108,22 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db__1close
if (!verify_non_null(jnienv, db))
return (0);
- JAVADB_API_BEGIN(db, jthis);
-
- /* Null out the private data to indicate the DB is invalid.
+ /*
+ * Null out the private data to indicate the DB is invalid.
* We do this in advance to help guard against multithreading
* issues.
*/
set_private_dbobj(jnienv, name_DB, jthis, 0);
err = db->close(db, flags);
- if (err != DB_INCOMPLETE)
- verify_return(jnienv, err, 0);
+ verify_return(jnienv, err, 0);
dbji_dealloc(dbinfo, jnienv);
- /* don't call JAVADB_API_END - db cannot be used */
return (err);
}
-/* We are being notified that the parent DbEnv has closed.
+/*
+ * We are being notified that the parent DbEnv has closed.
* Zero out the pointer to the DB, since it is no longer
* valid, to prevent mistakes. The user will get a null
* pointer exception if they try to use this Db again.
@@ -122,10 +144,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_append_1recno_1changed
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- dbinfo = (DB_JAVAINFO*)db->cj_internal;
+ dbinfo = (DB_JAVAINFO*)db->api_internal;
dbji_set_append_recno_object(dbinfo, jnienv, db, jcallback);
- JAVADB_API_END(db);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1compare_1changed
@@ -138,10 +158,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1compare_1changed
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- dbinfo = (DB_JAVAINFO*)db->cj_internal;
+ dbinfo = (DB_JAVAINFO*)db->api_internal;
dbji_set_bt_compare_object(dbinfo, jnienv, db, jbtcompare);
- JAVADB_API_END(db);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1prefix_1changed
@@ -154,10 +172,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1prefix_1changed
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- dbinfo = (DB_JAVAINFO*)db->cj_internal;
+ dbinfo = (DB_JAVAINFO*)db->api_internal;
dbji_set_bt_prefix_object(dbinfo, jnienv, db, jbtprefix);
- JAVADB_API_END(db);
}
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_cursor
@@ -182,26 +198,23 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_del
int err;
DB_TXN *dbtxnid;
DB *db;
- JDBT dbkey;
+ LOCKED_DBT lkey;
err = 0;
db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
return (0);
- JAVADB_API_BEGIN(db, jthis);
dbtxnid = get_DB_TXN(jnienv, txnid);
- if (jdbt_lock(&dbkey, jnienv, key, inOp) != 0)
+ if (locked_dbt_get(&lkey, jnienv, db->dbenv, key, inOp) != 0)
goto out;
- err = db->del(db, dbtxnid, &dbkey.dbt->dbt, dbflags);
- if (err != DB_NOTFOUND) {
+ err = db->del(db, dbtxnid, &lkey.javainfo->dbt, dbflags);
+ if (!DB_RETOK_DBDEL(err))
verify_return(jnienv, err, 0);
- }
out:
- jdbt_unlock(&dbkey, jnienv);
- JAVADB_API_END(db);
+ locked_dbt_put(&lkey, jnienv, db->dbenv);
return (err);
}
@@ -215,49 +228,43 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_dup_1compare_1changed
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- dbinfo = (DB_JAVAINFO*)db->cj_internal;
+ dbinfo = (DB_JAVAINFO*)db->api_internal;
dbji_set_dup_compare_object(dbinfo, jnienv, db, jdupcompare);
- JAVADB_API_END(db);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_err
(JNIEnv *jnienv, /*Db*/ jobject jthis, jint ecode, jstring msg)
{
DB *db;
- JSTR msg_string;
+ LOCKED_STRING ls_msg;
- if (jstr_lock(&msg_string, jnienv, msg) != 0)
+ if (locked_string_get(&ls_msg, jnienv, msg) != 0)
goto out;
db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
goto out;
- JAVADB_API_BEGIN(db, jthis);
- db->err(db, ecode, msg_string.string);
- JAVADB_API_END(db);
+ db->err(db, ecode, "%s", ls_msg.string);
out:
- jstr_unlock(&msg_string, jnienv);
+ locked_string_put(&ls_msg, jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_errx
(JNIEnv *jnienv, /*Db*/ jobject jthis, jstring msg)
{
- JSTR msg_string;
+ LOCKED_STRING ls_msg;
DB *db = get_DB(jnienv, jthis);
- if (jstr_lock(&msg_string, jnienv, msg) != 0)
+ if (locked_string_get(&ls_msg, jnienv, msg) != 0)
goto out;
if (!verify_non_null(jnienv, db))
goto out;
- JAVADB_API_BEGIN(db, jthis);
- db->errx(db, msg_string.string);
- JAVADB_API_END(db);
+ db->errx(db, "%s", ls_msg.string);
out:
- jstr_unlock(&msg_string, jnienv);
+ locked_string_put(&ls_msg, jnienv);
}
JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_fd
@@ -270,14 +277,31 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_fd
if (!verify_non_null(jnienv, db))
return (0);
- JAVADB_API_BEGIN(db, jthis);
err = db->fd(db, &return_value);
verify_return(jnienv, err, 0);
- JAVADB_API_END(db);
return (return_value);
}
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1encrypt
+ (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring jpasswd, jint flags)
+{
+ int err;
+ DB *db;
+ LOCKED_STRING ls_passwd;
+
+ db = get_DB(jnienv, jthis);
+ if (!verify_non_null(jnienv, db))
+ return;
+ if (locked_string_get(&ls_passwd, jnienv, jpasswd) != 0)
+ goto out;
+
+ err = db->set_encrypt(db, ls_passwd.string, flags);
+ verify_return(jnienv, err, 0);
+
+out: locked_string_put(&ls_passwd, jnienv);
+}
+
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_feedback_1changed
(JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbFeedback*/ jobject jfeedback)
{
@@ -288,10 +312,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_feedback_1changed
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- dbinfo = (DB_JAVAINFO*)db->cj_internal;
+ dbinfo = (DB_JAVAINFO*)db->api_internal;
dbji_set_feedback_object(dbinfo, jnienv, db, jfeedback);
- JAVADB_API_END(db);
}
JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get
@@ -300,16 +322,16 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get
{
int err, op_flags, retry;
DB *db;
+ DB_ENV *dbenv;
OpKind keyop, dataop;
DB_TXN *dbtxnid;
- JDBT dbkey, dbdata;
+ LOCKED_DBT lkey, ldata;
err = 0;
db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
goto out3;
-
- JAVADB_API_BEGIN(db, jthis);
+ dbenv = db->dbenv;
/* Depending on flags, the key may be input/output. */
keyop = inOp;
@@ -325,30 +347,34 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get
dbtxnid = get_DB_TXN(jnienv, txnid);
- if (jdbt_lock(&dbkey, jnienv, key, keyop) != 0)
+ if (locked_dbt_get(&lkey, jnienv, dbenv, key, keyop) != 0)
goto out2;
- if (jdbt_lock(&dbdata, jnienv, data, dataop) != 0)
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, dataop) != 0)
goto out1;
for (retry = 0; retry < 3; retry++) {
- err = db->get(db, dbtxnid, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags);
+ err = db->get(db,
+ dbtxnid, &lkey.javainfo->dbt, &ldata.javainfo->dbt, flags);
- /* If we failed due to lack of memory in our DBT arrays,
+ /*
+ * If we failed due to lack of memory in our DBT arrays,
* retry.
*/
if (err != ENOMEM)
break;
- if (!jdbt_realloc(&dbdata, jnienv))
+ if (!locked_dbt_realloc(&lkey, jnienv, dbenv) &&
+ !locked_dbt_realloc(&ldata, jnienv, dbenv))
break;
}
- if (err != DB_NOTFOUND) {
- verify_return(jnienv, err, 0);
- }
out1:
- jdbt_unlock(&dbdata, jnienv);
+ locked_dbt_put(&ldata, jnienv, dbenv);
out2:
- jdbt_unlock(&dbkey, jnienv);
+ locked_dbt_put(&lkey, jnienv, dbenv);
out3:
- JAVADB_API_END(db);
+ if (!DB_RETOK_DBGET(err)) {
+ if (verify_dbt(jnienv, err, &lkey) &&
+ verify_dbt(jnienv, err, &ldata))
+ verify_return(jnienv, err, 0);
+ }
return (err);
}
@@ -362,10 +388,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_hash_1changed
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- dbinfo = (DB_JAVAINFO*)db->cj_internal;
+ dbinfo = (DB_JAVAINFO*)db->api_internal;
dbji_set_h_hash_object(dbinfo, jnienv, db, jhash);
- JAVADB_API_END(db);
}
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_join
@@ -373,15 +397,25 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_join
jint flags)
{
int err;
- DB *db = get_DB(jnienv, jthis);
- int count = (*jnienv)->GetArrayLength(jnienv, curslist);
- DBC **newlist = (DBC **)malloc(sizeof(DBC *) * (count+1));
+ DB *db;
+ int count;
+ DBC **newlist;
DBC *dbc;
int i;
+ int size;
+
+ db = get_DB(jnienv, jthis);
+ count = (*jnienv)->GetArrayLength(jnienv, curslist);
+ size = sizeof(DBC *) * (count+1);
+ if ((err = __os_malloc(db->dbenv, size, &newlist)) != 0) {
+ if (!verify_return(jnienv, err, 0))
+ return (NULL);
+ }
/* Convert the java array of Dbc's to a C array of DBC's. */
- for (i=0; i<count; i++) {
- jobject jobj = (*jnienv)->GetObjectArrayElement(jnienv, curslist, i);
+ for (i = 0; i < count; i++) {
+ jobject jobj =
+ (*jnienv)->GetObjectArrayElement(jnienv, curslist, i);
if (jobj == 0) {
/*
* An embedded null in the array is treated
@@ -398,39 +432,39 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_join
if (!verify_non_null(jnienv, db))
return (NULL);
- JAVADB_API_BEGIN(db, jthis);
err = db->join(db, newlist, &dbc, flags);
- free(newlist);
verify_return(jnienv, err, 0);
+ __os_free(db->dbenv, newlist);
- JAVADB_API_END(db);
return (get_Dbc(jnienv, dbc));
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_key_1range
- (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject jtxn,
+ (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid,
/*Dbt*/ jobject jkey, jobject /*DbKeyRange*/ range, jint flags)
{
int err;
- DB *db = get_DB(jnienv, jthis);
- DB_TXN *txn = get_DB_TXN(jnienv, jtxn);
- JDBT dbkey;
+ DB *db;
+ DB_TXN *dbtxnid;
+ LOCKED_DBT lkey;
DB_KEY_RANGE result;
jfieldID fid;
jclass krclass;
+ db = get_DB(jnienv, jthis);
+ dbtxnid = get_DB_TXN(jnienv, txnid);
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
if (!verify_non_null(jnienv, range))
return;
- if (jdbt_lock(&dbkey, jnienv, jkey, inOp) != 0)
+ if (locked_dbt_get(&lkey, jnienv, db->dbenv, jkey, inOp) != 0)
goto out;
- err = db->key_range(db, txn, &dbkey.dbt->dbt, &result, flags);
+ err = db->key_range(db, dbtxnid, &lkey.javainfo->dbt, &result, flags);
if (verify_return(jnienv, err, 0)) {
/* fill in the values of the DbKeyRange structure */
- krclass = get_class(jnienv, "DbKeyRange");
+ if ((krclass = get_class(jnienv, "DbKeyRange")) == NULL)
+ return; /* An exception has been posted. */
fid = (*jnienv)->GetFieldID(jnienv, krclass, "less", "D");
(*jnienv)->SetDoubleField(jnienv, range, fid, result.less);
fid = (*jnienv)->GetFieldID(jnienv, krclass, "equal", "D");
@@ -439,8 +473,77 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_key_1range
(*jnienv)->SetDoubleField(jnienv, range, fid, result.greater);
}
out:
- jdbt_unlock(&dbkey, jnienv);
- JAVADB_API_END(db);
+ locked_dbt_put(&lkey, jnienv, db->dbenv);
+}
+
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_pget
+ (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid,
+ /*Dbt*/ jobject key, /*Dbt*/ jobject rkey, /*Dbt*/ jobject data, jint flags)
+{
+ int err, op_flags, retry;
+ DB *db;
+ DB_ENV *dbenv;
+ OpKind keyop, rkeyop, dataop;
+ DB_TXN *dbtxnid;
+ LOCKED_DBT lkey, lrkey, ldata;
+
+ err = 0;
+ db = get_DB(jnienv, jthis);
+ if (!verify_non_null(jnienv, db))
+ goto out4;
+ dbenv = db->dbenv;
+
+ /* Depending on flags, the key may be input/output. */
+ keyop = inOp;
+ rkeyop = outOp;
+ dataop = outOp;
+ op_flags = flags & DB_OPFLAGS_MASK;
+ if (op_flags == DB_SET_RECNO) {
+ keyop = inOutOp;
+ }
+ else if (op_flags == DB_GET_BOTH) {
+ keyop = inOutOp;
+ rkeyop = inOutOp;
+ dataop = inOutOp;
+ }
+
+ dbtxnid = get_DB_TXN(jnienv, txnid);
+
+ if (locked_dbt_get(&lkey, jnienv, dbenv, key, keyop) != 0)
+ goto out3;
+ if (locked_dbt_get(&lrkey, jnienv, dbenv, rkey, rkeyop) != 0)
+ goto out2;
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, dataop) != 0)
+ goto out1;
+ for (retry = 0; retry < 3; retry++) {
+ err = db->pget(db, dbtxnid, &lkey.javainfo->dbt,
+ &lrkey.javainfo->dbt, &ldata.javainfo->dbt, flags);
+
+ /*
+ * If we failed due to lack of memory in our DBT arrays,
+ * retry.
+ */
+ if (err != ENOMEM)
+ break;
+ if (!locked_dbt_realloc(&lkey, jnienv, dbenv) &&
+ !locked_dbt_realloc(&lrkey, jnienv, dbenv) &&
+ !locked_dbt_realloc(&ldata, jnienv, dbenv))
+ break;
+ }
+ out1:
+ locked_dbt_put(&ldata, jnienv, dbenv);
+ out2:
+ locked_dbt_put(&lrkey, jnienv, dbenv);
+ out3:
+ locked_dbt_put(&lkey, jnienv, dbenv);
+ out4:
+ if (!DB_RETOK_DBGET(err)) {
+ if (verify_dbt(jnienv, err, &lkey) &&
+ verify_dbt(jnienv, err, &lrkey) &&
+ verify_dbt(jnienv, err, &ldata))
+ verify_return(jnienv, err, 0);
+ }
+ return (err);
}
JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_put
@@ -449,137 +552,124 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_put
{
int err;
DB *db;
+ DB_ENV *dbenv;
DB_TXN *dbtxnid;
- JDBT dbkey, dbdata;
+ LOCKED_DBT lkey, ldata;
+ OpKind keyop;
err = 0;
db = get_DB(jnienv, jthis);
dbtxnid = get_DB_TXN(jnienv, txnid);
if (!verify_non_null(jnienv, db))
- return (0); /* error will be thrown, retval doesn't matter */
- JAVADB_API_BEGIN(db, jthis);
+ return (0); /* error will be thrown, retval doesn't matter */
+ dbenv = db->dbenv;
- if (jdbt_lock(&dbkey, jnienv, key, inOp) != 0)
+ /*
+ * For DB_APPEND, the key may be output-only; for all other flags,
+ * it's input-only.
+ */
+ if ((flags & DB_OPFLAGS_MASK) == DB_APPEND)
+ keyop = outOp;
+ else
+ keyop = inOp;
+
+ if (locked_dbt_get(&lkey, jnienv, dbenv, key, keyop) != 0)
goto out2;
- if (jdbt_lock(&dbdata, jnienv, data, inOp) != 0)
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, inOp) != 0)
goto out1;
if (!verify_non_null(jnienv, db))
goto out1;
- err = db->put(db, dbtxnid, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags);
- if (err != DB_KEYEXIST) {
+
+ err = db->put(db,
+ dbtxnid, &lkey.javainfo->dbt, &ldata.javainfo->dbt, flags);
+ if (!DB_RETOK_DBPUT(err))
verify_return(jnienv, err, 0);
- }
+
out1:
- jdbt_unlock(&dbdata, jnienv);
+ locked_dbt_put(&ldata, jnienv, dbenv);
out2:
- jdbt_unlock(&dbkey, jnienv);
- JAVADB_API_END(db);
+ locked_dbt_put(&lkey, jnienv, dbenv);
return (err);
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_rename
- (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring file,
- jstring database, jstring newname, jint flags)
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1remove
+ (JNIEnv *jnienv, /*Db*/ jobject jthis,
+ jstring file, jstring database, jint flags)
{
int err;
DB *db;
DB_JAVAINFO *dbinfo;
- JSTR j_file;
- JSTR j_database;
- JSTR j_newname;
+ LOCKED_STRING ls_file;
+ LOCKED_STRING ls_database;
db = get_DB(jnienv, jthis);
dbinfo = get_DB_JAVAINFO(jnienv, jthis);
+
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- if (jstr_lock(&j_file, jnienv, file) != 0)
- goto out3;
- if (jstr_lock(&j_database, jnienv, database) != 0)
+ if (locked_string_get(&ls_file, jnienv, file) != 0)
goto out2;
- if (jstr_lock(&j_newname, jnienv, newname) != 0)
+ if (locked_string_get(&ls_database, jnienv, database) != 0)
goto out1;
+ err = db->remove(db, ls_file.string, ls_database.string, flags);
- err = db->rename(db, j_file.string, j_database.string,
- j_newname.string, flags);
-
- verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND);
- dbji_dealloc(dbinfo, jnienv);
set_private_dbobj(jnienv, name_DB, jthis, 0);
+ verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND);
out1:
- jstr_unlock(&j_newname, jnienv);
+ locked_string_put(&ls_database, jnienv);
out2:
- jstr_unlock(&j_database, jnienv);
- out3:
- jstr_unlock(&j_file, jnienv);
- /* don't call JAVADB_API_END - db cannot be used */
+ locked_string_put(&ls_file, jnienv);
+
+ dbji_dealloc(dbinfo, jnienv);
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_remove
- (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring file,
- jstring database, jint flags)
+JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1rename
+ (JNIEnv *jnienv, /*Db*/ jobject jthis,
+ jstring file, jstring database, jstring newname, jint flags)
{
int err;
- DB *db = get_DB(jnienv, jthis);
- DB_JAVAINFO *dbinfo = get_DB_JAVAINFO(jnienv, jthis);
- JSTR j_file;
- JSTR j_database;
+ DB *db;
+ DB_JAVAINFO *dbinfo;
+ LOCKED_STRING ls_file;
+ LOCKED_STRING ls_database;
+ LOCKED_STRING ls_newname;
+ db = get_DB(jnienv, jthis);
dbinfo = get_DB_JAVAINFO(jnienv, jthis);
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
- if (jstr_lock(&j_file, jnienv, file) != 0)
+ if (locked_string_get(&ls_file, jnienv, file) != 0)
+ goto out3;
+ if (locked_string_get(&ls_database, jnienv, database) != 0)
goto out2;
- if (jstr_lock(&j_database, jnienv, database) != 0)
+ if (locked_string_get(&ls_newname, jnienv, newname) != 0)
goto out1;
- err = db->remove(db, j_file.string, j_database.string, flags);
- set_private_dbobj(jnienv, name_DB, jthis, 0);
+ err = db->rename(db, ls_file.string, ls_database.string,
+ ls_newname.string, flags);
+
verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND);
- dbji_dealloc(dbinfo, jnienv);
+ set_private_dbobj(jnienv, name_DB, jthis, 0);
out1:
- jstr_unlock(&j_database, jnienv);
+ locked_string_put(&ls_newname, jnienv);
out2:
- jstr_unlock(&j_file, jnienv);
- /* don't call JAVADB_API_END - db cannot be used */
-}
-
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_Db_set_1pagesize
- (JNIEnv *jnienv, /*Db*/ jobject jthis, jlong value)
-{
- int err;
- DB *db;
+ locked_string_put(&ls_database, jnienv);
+ out3:
+ locked_string_put(&ls_file, jnienv);
- db = get_DB(jnienv, jthis);
- if (verify_non_null(jnienv, db)) {
- JAVADB_API_BEGIN(db, jthis);
- err = db->set_pagesize(db, (u_int32_t)value);
- verify_return(jnienv, err, 0);
- JAVADB_API_END(db);
- }
+ dbji_dealloc(dbinfo, jnienv);
}
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_Db_set_1cachesize
- (JNIEnv *jnienv, /*Db*/ jobject jthis, jint gbytes, jint bytes,
- jint ncaches)
-{
- int err;
- DB *db;
-
- db = get_DB(jnienv, jthis);
- if (verify_non_null(jnienv, db)) {
- JAVADB_API_BEGIN(db, jthis);
- err = db->set_cachesize(db, gbytes, bytes, ncaches);
- verify_return(jnienv, err, 0);
- JAVADB_API_END(db);
- }
-}
+JAVADB_METHOD(Db_set_1pagesize, (JAVADB_ARGS, jlong pagesize), DB,
+ set_pagesize, (c_this, (u_int32_t)pagesize))
+JAVADB_METHOD(Db_set_1cachesize,
+ (JAVADB_ARGS, jint gbytes, jint bytes, jint ncaches), DB,
+ set_cachesize, (c_this, gbytes, bytes, ncaches))
+JAVADB_METHOD(Db_set_1cache_1priority, (JAVADB_ARGS, jint priority), DB,
+ set_cache_priority, (c_this, (DB_CACHE_PRIORITY)priority))
JNIEXPORT void JNICALL
Java_com_sleepycat_db_Db_set_1re_1source
@@ -590,257 +680,185 @@ JNIEXPORT void JNICALL
db = get_DB(jnienv, jthis);
if (verify_non_null(jnienv, db)) {
- JAVADB_API_BEGIN(db, jthis);
/* XXX does the string from get_c_string ever get freed? */
if (re_source != NULL)
- err = db->set_re_source(db, get_c_string(jnienv, re_source));
+ err = db->set_re_source(db,
+ get_c_string(jnienv, re_source));
else
err = db->set_re_source(db, 0);
verify_return(jnienv, err, 0);
- JAVADB_API_END(db);
}
}
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_stat
(JNIEnv *jnienv, jobject jthis, jint flags)
{
- int err;
- DB *db = get_DB(jnienv, jthis);
- jobject retval = NULL;
- jclass dbclass;
- void *statp = 0;
+ DB *db;
DB_BTREE_STAT *bstp;
DB_HASH_STAT *hstp;
DB_QUEUE_STAT *qstp;
+ DBTYPE dbtype;
+ jobject retval;
+ jclass dbclass;
+ size_t bytesize;
+ void *statp;
+ bytesize = 0;
+ retval = NULL;
+ statp = NULL;
+
+ db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
return (NULL);
- JAVADB_API_BEGIN(db, jthis);
-
- err = db->stat(db, &statp, NULL, flags);
- if (verify_return(jnienv, err, 0)) {
- DBTYPE dbtype = db->get_type(db);
+ if (verify_return(jnienv, db->stat(db, &statp, flags), 0) &&
+ verify_return(jnienv, db->get_type(db, &dbtype), 0)) {
switch (dbtype) {
-
/* Btree and recno share the same stat structure */
case DB_BTREE:
case DB_RECNO:
bstp = (DB_BTREE_STAT *)statp;
+ bytesize = sizeof(DB_BTREE_STAT);
retval = create_default_object(jnienv,
name_DB_BTREE_STAT);
- dbclass = get_class(jnienv, name_DB_BTREE_STAT);
-
- /* Set the individual fields */
- set_int_field(jnienv, dbclass, retval,
- "bt_magic", bstp->bt_magic);
- set_int_field(jnienv, dbclass, retval,
- "bt_version", bstp->bt_version);
- set_int_field(jnienv, dbclass, retval,
- "bt_metaflags", bstp->bt_metaflags);
- set_int_field(jnienv, dbclass, retval,
- "bt_nkeys", bstp->bt_nkeys);
- set_int_field(jnienv, dbclass, retval,
- "bt_ndata", bstp->bt_ndata);
- set_int_field(jnienv, dbclass, retval,
- "bt_pagesize", bstp->bt_pagesize);
- set_int_field(jnienv, dbclass, retval,
- "bt_maxkey", bstp->bt_maxkey);
- set_int_field(jnienv, dbclass, retval,
- "bt_minkey", bstp->bt_minkey);
- set_int_field(jnienv, dbclass, retval,
- "bt_re_len", bstp->bt_re_len);
- set_int_field(jnienv, dbclass, retval,
- "bt_re_pad", bstp->bt_re_pad);
- set_int_field(jnienv, dbclass, retval,
- "bt_levels", bstp->bt_levels);
- set_int_field(jnienv, dbclass, retval,
- "bt_int_pg", bstp->bt_int_pg);
- set_int_field(jnienv, dbclass, retval,
- "bt_leaf_pg", bstp->bt_leaf_pg);
- set_int_field(jnienv, dbclass, retval,
- "bt_dup_pg", bstp->bt_dup_pg);
- set_int_field(jnienv, dbclass, retval,
- "bt_over_pg", bstp->bt_over_pg);
- set_int_field(jnienv, dbclass, retval,
- "bt_free", bstp->bt_free);
- set_int_field(jnienv, dbclass, retval,
- "bt_int_pgfree", bstp->bt_int_pgfree);
- set_int_field(jnienv, dbclass, retval,
- "bt_leaf_pgfree", bstp->bt_leaf_pgfree);
- set_int_field(jnienv, dbclass, retval,
- "bt_dup_pgfree", bstp->bt_dup_pgfree);
- set_int_field(jnienv, dbclass, retval,
- "bt_over_pgfree", bstp->bt_over_pgfree);
+ if ((dbclass =
+ get_class(jnienv, name_DB_BTREE_STAT)) == NULL)
+ break; /* An exception has been posted. */
+ __jv_fill_bt_stat(jnienv, dbclass, retval, bstp);
break;
/* Hash stat structure */
case DB_HASH:
hstp = (DB_HASH_STAT *)statp;
+ bytesize = sizeof(DB_HASH_STAT);
retval = create_default_object(jnienv,
name_DB_HASH_STAT);
- dbclass = get_class(jnienv, name_DB_HASH_STAT);
-
- /* Set the individual fields */
- set_int_field(jnienv, dbclass, retval,
- "hash_magic", hstp->hash_magic);
- set_int_field(jnienv, dbclass, retval,
- "hash_version", hstp->hash_version);
- set_int_field(jnienv, dbclass, retval,
- "hash_metaflags", hstp->hash_metaflags);
- set_int_field(jnienv, dbclass, retval,
- "hash_nkeys", hstp->hash_nkeys);
- set_int_field(jnienv, dbclass, retval,
- "hash_ndata", hstp->hash_ndata);
- set_int_field(jnienv, dbclass, retval,
- "hash_pagesize", hstp->hash_pagesize);
- set_int_field(jnienv, dbclass, retval,
- "hash_nelem", hstp->hash_nelem);
- set_int_field(jnienv, dbclass, retval,
- "hash_ffactor", hstp->hash_ffactor);
- set_int_field(jnienv, dbclass, retval,
- "hash_buckets", hstp->hash_buckets);
- set_int_field(jnienv, dbclass, retval,
- "hash_free", hstp->hash_free);
- set_int_field(jnienv, dbclass, retval,
- "hash_bfree", hstp->hash_bfree);
- set_int_field(jnienv, dbclass, retval,
- "hash_bigpages", hstp->hash_bigpages);
- set_int_field(jnienv, dbclass, retval,
- "hash_big_bfree", hstp->hash_big_bfree);
- set_int_field(jnienv, dbclass, retval,
- "hash_overflows", hstp->hash_overflows);
- set_int_field(jnienv, dbclass, retval,
- "hash_ovfl_free", hstp->hash_ovfl_free);
- set_int_field(jnienv, dbclass, retval,
- "hash_dup", hstp->hash_dup);
- set_int_field(jnienv, dbclass, retval,
- "hash_dup_free", hstp->hash_dup_free);
+ if ((dbclass =
+ get_class(jnienv, name_DB_HASH_STAT)) == NULL)
+ break; /* An exception has been posted. */
+ __jv_fill_h_stat(jnienv, dbclass, retval, hstp);
break;
case DB_QUEUE:
qstp = (DB_QUEUE_STAT *)statp;
+ bytesize = sizeof(DB_QUEUE_STAT);
retval = create_default_object(jnienv,
name_DB_QUEUE_STAT);
- dbclass = get_class(jnienv, name_DB_QUEUE_STAT);
-
- /* Set the individual fields */
- set_int_field(jnienv, dbclass, retval,
- "qs_magic", qstp->qs_magic);
- set_int_field(jnienv, dbclass, retval,
- "qs_version", qstp->qs_version);
- set_int_field(jnienv, dbclass, retval,
- "qs_metaflags", qstp->qs_metaflags);
- set_int_field(jnienv, dbclass, retval,
- "qs_nkeys", qstp->qs_nkeys);
- set_int_field(jnienv, dbclass, retval,
- "qs_ndata", qstp->qs_ndata);
- set_int_field(jnienv, dbclass, retval,
- "qs_pagesize", qstp->qs_pagesize);
- set_int_field(jnienv, dbclass, retval,
- "qs_pages", qstp->qs_pages);
- set_int_field(jnienv, dbclass, retval,
- "qs_re_len", qstp->qs_re_len);
- set_int_field(jnienv, dbclass, retval,
- "qs_re_pad", qstp->qs_re_pad);
- set_int_field(jnienv, dbclass, retval,
- "qs_pgfree", qstp->qs_pgfree);
- set_int_field(jnienv, dbclass, retval,
- "qs_first_recno", qstp->qs_first_recno);
- set_int_field(jnienv, dbclass, retval,
- "qs_cur_recno", qstp->qs_cur_recno);
+ if ((dbclass =
+ get_class(jnienv, name_DB_QUEUE_STAT)) == NULL)
+ break; /* An exception has been posted. */
+
+ __jv_fill_qam_stat(jnienv, dbclass, retval, qstp);
break;
/* That's all the database types we're aware of! */
default:
report_exception(jnienv,
"Db.stat not implemented for types"
- "other than HASH, BTREE and RECNO",
+ " other than BTREE, HASH, QUEUE,"
+ " and RECNO",
EINVAL, 0);
break;
}
- free(statp);
+ if (bytesize != 0)
+ __os_ufree(db->dbenv, statp);
}
- JAVADB_API_END(db);
return (retval);
}
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_sync
- (JNIEnv *jnienv, /*Db*/ jobject jthis, jint flags)
-{
- int err;
- DB *db = get_DB(jnienv, jthis);
-
- if (!verify_non_null(jnienv, db))
- return (0);
- JAVADB_API_BEGIN(db, jthis);
- err = db->sync(db, flags);
- if (err != DB_INCOMPLETE)
- verify_return(jnienv, err, 0);
- JAVADB_API_END(db);
- return (err);
-}
+JAVADB_METHOD(Db_sync, (JAVADB_ARGS, jint flags), DB,
+ sync, (c_this, flags))
JNIEXPORT jboolean JNICALL Java_com_sleepycat_db_Db_get_1byteswapped
(JNIEnv *jnienv, /*Db*/ jobject jthis)
{
DB *db;
- jboolean retval;
+ int err, isbyteswapped;
+
+ /* This value should never be seen, because of the exception. */
+ isbyteswapped = 0;
db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
return (0);
- JAVADB_API_BEGIN(db, jthis);
- retval = db->get_byteswapped(db) ? 1 : 0;
- JAVADB_API_END(db);
- return (retval);
+ err = db->get_byteswapped(db, &isbyteswapped);
+ (void)verify_return(jnienv, err, 0);
+
+ return ((jboolean)isbyteswapped);
}
JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get_1type
(JNIEnv *jnienv, /*Db*/ jobject jthis)
{
DB *db;
+ int err;
+ DBTYPE dbtype;
+
+ /* This value should never be seen, because of the exception. */
+ dbtype = DB_UNKNOWN;
db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
return (0);
- return ((jint)db->type);
+ err = db->get_type(db, &dbtype);
+ (void)verify_return(jnienv, err, 0);
+
+ return ((jint)dbtype);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1open
- (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring file, jstring database,
- jint type, jint flags, jint mode)
+ (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid,
+ jstring file, jstring database, jint type, jint flags, jint mode)
{
int err;
DB *db;
- JSTR dbfile;
- JSTR dbdatabase;
+ DB_TXN *dbtxnid;
+ LOCKED_STRING ls_file;
+ LOCKED_STRING ls_database;
- /* Java is assumed to be threaded. */
+ /* Java is assumed to be threaded */
flags |= DB_THREAD;
db = get_DB(jnienv, jthis);
- if (jstr_lock(&dbfile, jnienv, file) != 0)
+
+ dbtxnid = get_DB_TXN(jnienv, txnid);
+ if (locked_string_get(&ls_file, jnienv, file) != 0)
goto out2;
- if (jstr_lock(&dbdatabase, jnienv, database) != 0)
+ if (locked_string_get(&ls_database, jnienv, database) != 0)
goto out1;
if (verify_non_null(jnienv, db)) {
- JAVADB_API_BEGIN(db, jthis);
- err = db->open(db, dbfile.string, dbdatabase.string,
+ err = db->open(db, dbtxnid, ls_file.string, ls_database.string,
(DBTYPE)type, flags, mode);
verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND);
- JAVADB_API_END(db);
}
out1:
- jstr_unlock(&dbdatabase, jnienv);
+ locked_string_put(&ls_database, jnienv);
out2:
- jstr_unlock(&dbfile, jnienv);
+ locked_string_put(&ls_file, jnienv);
+}
+
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_truncate
+ (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject jtxnid, jint flags)
+{
+ int err;
+ DB *db;
+ u_int32_t count;
+ DB_TXN *dbtxnid;
+
+ db = get_DB(jnienv, jthis);
+ dbtxnid = get_DB_TXN(jnienv, jtxnid);
+ count = 0;
+ if (verify_non_null(jnienv, db)) {
+ err = db->truncate(db, dbtxnid, &count, flags);
+ verify_return(jnienv, err, 0);
+ }
+ return (jint)count;
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_upgrade
@@ -849,18 +867,16 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_upgrade
{
int err;
DB *db = get_DB(jnienv, jthis);
- JSTR j_name;
+ LOCKED_STRING ls_name;
if (verify_non_null(jnienv, db)) {
- JAVADB_API_BEGIN(db, jthis);
- if (jstr_lock(&j_name, jnienv, name) != 0)
+ if (locked_string_get(&ls_name, jnienv, name) != 0)
goto out;
- err = db->upgrade(db, j_name.string, flags);
+ err = db->upgrade(db, ls_name.string, flags);
verify_return(jnienv, err, 0);
- JAVADB_API_END(db);
}
out:
- jstr_unlock(&j_name, jnienv);
+ locked_string_put(&ls_name, jnienv);
}
static int java_verify_callback(void *handle, const void *str_arg)
@@ -868,7 +884,6 @@ static int java_verify_callback(void *handle, const void *str_arg)
char *str;
struct verify_callback_struct *vc;
int len;
- jthrowable except;
JNIEnv *jnienv;
str = (char *)str_arg;
@@ -879,11 +894,15 @@ static int java_verify_callback(void *handle, const void *str_arg)
vc->nbytes = len;
vc->bytes = (*jnienv)->NewByteArray(jnienv, len);
}
- (*jnienv)->SetByteArrayRegion(jnienv, vc->bytes, 0, len, (jbyte*)str);
- (*jnienv)->CallVoidMethod(jnienv, vc->streamobj,
- vc->writemid, vc->bytes, 0, len-1);
- if ((except = (*jnienv)->ExceptionOccurred(jnienv)) != NULL)
+ if (vc->bytes != NULL) {
+ (*jnienv)->SetByteArrayRegion(jnienv, vc->bytes, 0, len,
+ (jbyte*)str);
+ (*jnienv)->CallVoidMethod(jnienv, vc->streamobj,
+ vc->writemid, vc->bytes, 0, len-1);
+ }
+
+ if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
return (EIO);
return (0);
@@ -895,26 +914,25 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_verify
{
int err;
DB *db;
- JSTR j_name;
- JSTR j_subdb;
+ LOCKED_STRING ls_name;
+ LOCKED_STRING ls_subdb;
struct verify_callback_struct vcs;
jclass streamclass;
db = get_DB(jnienv, jthis);
if (!verify_non_null(jnienv, db))
return;
- JAVADB_API_BEGIN(db, jthis);
-
- if (jstr_lock(&j_name, jnienv, name) != 0)
+ if (locked_string_get(&ls_name, jnienv, name) != 0)
goto out2;
- if (jstr_lock(&j_subdb, jnienv, subdb) != 0)
+ if (locked_string_get(&ls_subdb, jnienv, subdb) != 0)
goto out1;
/* set up everything we need for the callbacks */
vcs.env = jnienv;
vcs.streamobj = stream;
vcs.nbytes = 100;
- vcs.bytes = (*jnienv)->NewByteArray(jnienv, vcs.nbytes);
+ if ((vcs.bytes = (*jnienv)->NewByteArray(jnienv, vcs.nbytes)) == NULL)
+ goto out1;
/* get the method ID for OutputStream.write(byte[], int, int); */
streamclass = (*jnienv)->FindClass(jnienv, "java/io/OutputStream");
@@ -922,15 +940,14 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_verify
"write", "([BII)V");
/* invoke verify - this will invoke the callback repeatedly. */
- err = __db_verify_internal(db, j_name.string, j_subdb.string,
+ err = __db_verify_internal(db, ls_name.string, ls_subdb.string,
&vcs, java_verify_callback, flags);
verify_return(jnienv, err, 0);
out1:
- jstr_unlock(&j_subdb, jnienv);
+ locked_string_put(&ls_subdb, jnienv);
out2:
- jstr_unlock(&j_name, jnienv);
- JAVADB_API_END(db);
+ locked_string_put(&ls_name, jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1finalize
@@ -944,7 +961,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1finalize
db = get_DB(jnienv, jthis);
DB_ASSERT(dbinfo != NULL);
- /* Note: We can never be sure if the underlying DB is attached to
+ /*
+ * Note: We can never be sure if the underlying DB is attached to
* a DB_ENV that was already closed. Sure, that's a user error,
* but it shouldn't crash the VM. Therefore, we cannot just
* automatically close if the handle indicates we are not yet
diff --git a/bdb/libdb_java/java_DbEnv.c b/bdb/libdb_java/java_DbEnv.c
index ff9207dd2c8..651c38a0e3d 100644
--- a/bdb/libdb_java/java_DbEnv.c
+++ b/bdb/libdb_java/java_DbEnv.c
@@ -1,40 +1,40 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_DbEnv.c,v 11.37 2001/01/11 18:19:52 bostic Exp $";
+static const char revid[] = "$Id: java_DbEnv.c,v 11.105 2002/08/29 14:22:23 margo Exp $";
#endif /* not lint */
#include <jni.h>
#include <stdlib.h>
#include <string.h>
-#include "db.h"
#include "db_int.h"
#include "java_util.h"
+#include "java_stat_auto.h"
#include "com_sleepycat_db_DbEnv.h"
/* We keep these lined up, and alphabetical by field name,
* for comparison with C++'s list.
*/
-JAVADB_WO_ACCESS_STRING(DbEnv, data_1dir, DB_ENV, data_dir)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lg_1bsize, DB_ENV, lg_bsize)
-JAVADB_WO_ACCESS_STRING(DbEnv, lg_1dir, DB_ENV, lg_dir)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lg_1max, DB_ENV, lg_max)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1detect, DB_ENV, lk_detect)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max, DB_ENV, lk_max)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max_1locks, DB_ENV, lk_max_locks)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max_1lockers, DB_ENV, lk_max_lockers)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max_1objects, DB_ENV, lk_max_objects)
+JAVADB_SET_METH_STR(DbEnv, data_1dir, DB_ENV, data_dir)
+JAVADB_SET_METH(DbEnv, jint, lg_1bsize, DB_ENV, lg_bsize)
+JAVADB_SET_METH_STR(DbEnv, lg_1dir, DB_ENV, lg_dir)
+JAVADB_SET_METH(DbEnv, jint, lg_1max, DB_ENV, lg_max)
+JAVADB_SET_METH(DbEnv, jint, lg_1regionmax, DB_ENV, lg_regionmax)
+JAVADB_SET_METH(DbEnv, jint, lk_1detect, DB_ENV, lk_detect)
+JAVADB_SET_METH(DbEnv, jint, lk_1max, DB_ENV, lk_max)
+JAVADB_SET_METH(DbEnv, jint, lk_1max_1locks, DB_ENV, lk_max_locks)
+JAVADB_SET_METH(DbEnv, jint, lk_1max_1lockers, DB_ENV, lk_max_lockers)
+JAVADB_SET_METH(DbEnv, jint, lk_1max_1objects, DB_ENV, lk_max_objects)
/* mp_mmapsize is declared below, it needs an extra cast */
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, mutexlocks, DB_ENV, mutexlocks)
-JAVADB_WO_ACCESS_STRING(DbEnv, tmp_1dir, DB_ENV, tmp_dir)
-JAVADB_WO_ACCESS_METHOD(DbEnv, jint, tx_1max, DB_ENV, tx_max)
+JAVADB_SET_METH_STR(DbEnv, tmp_1dir, DB_ENV, tmp_dir)
+JAVADB_SET_METH(DbEnv, jint, tx_1max, DB_ENV, tx_max)
static void DbEnv_errcall_callback(const char *prefix, char *message)
{
@@ -42,7 +42,8 @@ static void DbEnv_errcall_callback(const char *prefix, char *message)
DB_ENV_JAVAINFO *envinfo = (DB_ENV_JAVAINFO *)prefix;
jstring pre;
- /* Note: these error cases are "impossible", and would
+ /*
+ * Note: these error cases are "impossible", and would
* normally warrant an exception. However, without
* a jnienv, we cannot throw an exception...
* We don't want to trap or exit, since the point of
@@ -50,7 +51,8 @@ static void DbEnv_errcall_callback(const char *prefix, char *message)
* error situations.
*/
if (envinfo == NULL) {
- /* Something is *really* wrong here, the
+ /*
+ * Something is *really* wrong here, the
* prefix is set in every environment created.
*/
fprintf(stderr, "Error callback failed!\n");
@@ -70,7 +72,7 @@ static void DbEnv_errcall_callback(const char *prefix, char *message)
}
pre = dbjie_get_errpfx(envinfo, jnienv);
- report_errcall(jnienv, dbjie_get_errcall(envinfo), pre, message);
+ report_errcall(jnienv, dbjie_get_errcall(envinfo), pre, message);
}
static void DbEnv_initialize(JNIEnv *jnienv, DB_ENV *dbenv,
@@ -82,15 +84,16 @@ static void DbEnv_initialize(JNIEnv *jnienv, DB_ENV *dbenv,
envinfo = get_DB_ENV_JAVAINFO(jnienv, jenv);
DB_ASSERT(envinfo == NULL);
- envinfo = dbjie_construct(jnienv, jerrcall, is_dbopen);
+ envinfo = dbjie_construct(jnienv, jenv, jerrcall, is_dbopen);
set_private_info(jnienv, name_DB_ENV, jenv, envinfo);
dbenv->set_errpfx(dbenv, (const char*)envinfo);
dbenv->set_errcall(dbenv, DbEnv_errcall_callback);
- dbenv->cj_internal = envinfo;
+ dbenv->api2_internal = envinfo;
set_private_dbobj(jnienv, name_DB_ENV, jenv, dbenv);
}
-/* This is called when this DbEnv was made on behalf of a Db
+/*
+ * This is called when this DbEnv was made on behalf of a Db
* created directly (without a parent DbEnv), and the Db is
* being closed. We'll zero out the pointer to the DB_ENV,
* since it is no longer valid, to prevent mistakes.
@@ -107,7 +110,8 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1notify_1db_1close
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_feedback_1changed
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbFeedback*/ jobject jfeedback)
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis,
+ /*DbEnvFeedback*/ jobject jfeedback)
{
DB_ENV *dbenv;
DB_ENV_JAVAINFO *dbenvinfo;
@@ -118,9 +122,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_feedback_1changed
!verify_non_null(jnienv, dbenvinfo))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
dbjie_set_feedback_object(dbenvinfo, jnienv, dbenv, jfeedback);
- JAVADB_ENV_API_END(dbenv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init
@@ -144,7 +146,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init_1using_1db
db = get_DB(jnienv, jdb);
dbenv = db->dbenv;
- DbEnv_initialize(jnienv, dbenv, jthis, jerrcall, 1);
+ DbEnv_initialize(jnienv, dbenv, jthis, jerrcall, 0);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_open
@@ -153,7 +155,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_open
{
int err;
DB_ENV *dbenv;
- JSTR j_home;
+ LOCKED_STRING ls_home;
DB_ENV_JAVAINFO *dbenvinfo;
dbenv = get_DB_ENV(jnienv, jthis);
@@ -161,18 +163,16 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_open
if (!verify_non_null(jnienv, dbenv) ||
!verify_non_null(jnienv, dbenvinfo))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- if (jstr_lock(&j_home, jnienv, db_home) != 0)
+ if (locked_string_get(&ls_home, jnienv, db_home) != 0)
goto out;
/* Java is assumed to be threaded. */
flags |= DB_THREAD;
- err = dbenv->open(dbenv, j_home.string, flags, mode);
+ err = dbenv->open(dbenv, ls_home.string, flags, mode);
verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND);
out:
- jstr_unlock(&j_home, jnienv);
- JAVADB_ENV_API_END(dbenv);
+ locked_string_put(&ls_home, jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_remove
@@ -180,27 +180,25 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_remove
{
DB_ENV *dbenv;
DB_ENV_JAVAINFO *dbenvinfo;
- JSTR j_home;
+ LOCKED_STRING ls_home;
int err = 0;
dbenv = get_DB_ENV(jnienv, jthis);
dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis);
if (!verify_non_null(jnienv, dbenv))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- if (jstr_lock(&j_home, jnienv, db_home) != 0)
+ if (locked_string_get(&ls_home, jnienv, db_home) != 0)
goto out;
- err = dbenv->remove(dbenv, j_home.string, flags);
+ err = dbenv->remove(dbenv, ls_home.string, flags);
set_private_dbobj(jnienv, name_DB_ENV, jthis, 0);
- if (dbenvinfo != NULL)
- dbjie_dealloc(dbenvinfo, jnienv);
-
verify_return(jnienv, err, 0);
out:
- jstr_unlock(&j_home, jnienv);
- /* don't call JAVADB_ENV_API_END - env cannot be used */
+ locked_string_put(&ls_home, jnienv);
+
+ if (dbenvinfo != NULL)
+ dbjie_dealloc(dbenvinfo, jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1close
@@ -215,8 +213,6 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1close
if (!verify_non_null(jnienv, dbenv))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
err = dbenv->close(dbenv, flags);
set_private_dbobj(jnienv, name_DB_ENV, jthis, 0);
@@ -225,50 +221,101 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1close
/* Throw an exception if the close failed. */
verify_return(jnienv, err, 0);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_dbremove
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbTxn*/ jobject jtxn,
+ jstring name, jstring subdb, jint flags)
+{
+ LOCKED_STRING ls_name, ls_subdb;
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ int err;
+
+ dbenv = get_DB_ENV(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbenv))
+ return;
+ txn = get_DB_TXN(jnienv, jtxn);
+ if (locked_string_get(&ls_name, jnienv, name) != 0)
+ return;
+ if (locked_string_get(&ls_subdb, jnienv, subdb) != 0)
+ goto err1;
+
+ err = dbenv->dbremove(dbenv, txn, ls_name.string, ls_subdb.string,
+ flags);
+
+ /* Throw an exception if the dbremove failed. */
+ verify_return(jnienv, err, 0);
+
+ locked_string_put(&ls_subdb, jnienv);
+err1: locked_string_put(&ls_name, jnienv);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_dbrename
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbTxn*/ jobject jtxn,
+ jstring name, jstring subdb, jstring newname, jint flags)
+{
+ LOCKED_STRING ls_name, ls_subdb, ls_newname;
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ int err;
+
+ dbenv = get_DB_ENV(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbenv))
+ return;
+ txn = get_DB_TXN(jnienv, jtxn);
+ if (locked_string_get(&ls_name, jnienv, name) != 0)
+ return;
+ if (locked_string_get(&ls_subdb, jnienv, subdb) != 0)
+ goto err2;
+ if (locked_string_get(&ls_newname, jnienv, newname) != 0)
+ goto err1;
+
+ err = dbenv->dbrename(dbenv, txn, ls_name.string, ls_subdb.string,
+ ls_newname.string, flags);
+
+ /* Throw an exception if the dbrename failed. */
+ verify_return(jnienv, err, 0);
- /* don't call JAVADB_ENV_API_END - env cannot be used */
+ locked_string_put(&ls_newname, jnienv);
+err1: locked_string_put(&ls_subdb, jnienv);
+err2: locked_string_put(&ls_name, jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_err
(JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint ecode, jstring msg)
{
- JSTR msg_string;
+ LOCKED_STRING ls_msg;
DB_ENV *dbenv;
dbenv = get_DB_ENV(jnienv, jthis);
if (!verify_non_null(jnienv, dbenv))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- if (jstr_lock(&msg_string, jnienv, msg) != 0)
+ if (locked_string_get(&ls_msg, jnienv, msg) != 0)
goto out;
- dbenv->err(dbenv, ecode, msg_string.string);
+ dbenv->err(dbenv, ecode, "%s", ls_msg.string);
out:
- jstr_unlock(&msg_string, jnienv);
- JAVADB_ENV_API_END(dbenv);
+ locked_string_put(&ls_msg, jnienv);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_errx
(JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring msg)
{
- JSTR msg_string;
+ LOCKED_STRING ls_msg;
DB_ENV *dbenv;
dbenv = get_DB_ENV(jnienv, jthis);
if (!verify_non_null(jnienv, dbenv))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- if (jstr_lock(&msg_string, jnienv, msg) != 0)
+ if (locked_string_get(&ls_msg, jnienv, msg) != 0)
goto out;
- dbenv->errx(dbenv, msg_string.string);
+ dbenv->errx(dbenv, "%s", ls_msg.string);
out:
- jstr_unlock(&msg_string, jnienv);
- JAVADB_ENV_API_END(dbenv);
+ locked_string_put(&ls_msg, jnienv);
}
/*static*/
@@ -282,190 +329,255 @@ JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_strerror
return (get_java_string(jnienv, message));
}
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1cachesize
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint gbytes, jint bytes,
- jint ncaches)
+JAVADB_METHOD(DbEnv_set_1cachesize,
+ (JAVADB_ARGS, jint gbytes, jint bytes, jint ncaches), DB_ENV,
+ set_cachesize, (c_this, gbytes, bytes, ncaches))
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1encrypt
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring jpasswd, jint flags)
{
- DB_ENV *dbenv;
int err;
+ DB_ENV *dbenv;
+ LOCKED_STRING ls_passwd;
dbenv = get_DB_ENV(jnienv, jthis);
- if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = dbenv->set_cachesize(dbenv, gbytes, bytes, ncaches);
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
- }
+ if (!verify_non_null(jnienv, dbenv))
+ return;
+ if (locked_string_get(&ls_passwd, jnienv, jpasswd) != 0)
+ goto out;
+
+ err = dbenv->set_encrypt(dbenv, ls_passwd.string, flags);
+ verify_return(jnienv, err, 0);
+
+out: locked_string_put(&ls_passwd, jnienv);
}
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1flags
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags, jint onoff)
+JAVADB_METHOD(DbEnv_set_1flags,
+ (JAVADB_ARGS, jint flags, jboolean onoff), DB_ENV,
+ set_flags, (c_this, flags, onoff ? 1 : 0))
+
+JAVADB_METHOD(DbEnv_set_1mp_1mmapsize, (JAVADB_ARGS, jlong value), DB_ENV,
+ set_mp_mmapsize, (c_this, (size_t)value))
+
+JAVADB_METHOD(DbEnv_set_1tas_1spins, (JAVADB_ARGS, jint spins), DB_ENV,
+ set_tas_spins, (c_this, (u_int32_t)spins))
+
+JAVADB_METHOD(DbEnv_set_1timeout,
+ (JAVADB_ARGS, jlong timeout, jint flags), DB_ENV,
+ set_timeout, (c_this, (u_int32_t)timeout, flags))
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1conflicts
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jobjectArray array)
{
DB_ENV *dbenv;
+ DB_ENV_JAVAINFO *dbenvinfo;
int err;
+ jsize i, len;
+ u_char *newarr;
+ int bytesize;
dbenv = get_DB_ENV(jnienv, jthis);
- if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = dbenv->set_flags(dbenv, flags, onoff);
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
+ dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbenv) ||
+ !verify_non_null(jnienv, dbenvinfo))
+ return;
+
+ len = (*jnienv)->GetArrayLength(jnienv, array);
+ bytesize = sizeof(u_char) * len * len;
+
+ if ((err = __os_malloc(dbenv, bytesize, &newarr)) != 0) {
+ if (!verify_return(jnienv, err, 0))
+ return;
}
+
+ for (i=0; i<len; i++) {
+ jobject subArray =
+ (*jnienv)->GetObjectArrayElement(jnienv, array, i);
+ (*jnienv)->GetByteArrayRegion(jnienv, (jbyteArray)subArray,
+ 0, len,
+ (jbyte *)&newarr[i*len]);
+ }
+ dbjie_set_conflict(dbenvinfo, newarr, bytesize);
+ err = dbenv->set_lk_conflicts(dbenv, newarr, len);
+ verify_return(jnienv, err, 0);
}
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1mp_1mmapsize
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jlong value)
+JNIEXPORT jint JNICALL
+ Java_com_sleepycat_db_DbEnv_rep_1elect
+ (JNIEnv *jnienv, /* DbEnv */ jobject jthis, jint nsites, jint pri,
+ jint timeout)
{
DB_ENV *dbenv;
- int err;
+ int err, id;
- dbenv = get_DB_ENV(jnienv, jthis);
- if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = dbenv->set_mp_mmapsize(dbenv, (size_t)value);
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
- }
-}
+ if (!verify_non_null(jnienv, jthis))
+ return (DB_EID_INVALID);
-/*static*/
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1pageyield
- (JNIEnv *jnienv, jclass jthis_class, jint value)
-{
- int err;
+ dbenv = get_DB_ENV(jnienv, jthis);
- COMPQUIET(jthis_class, NULL);
- err = db_env_set_pageyield(value);
+ err = dbenv->rep_elect(dbenv, (int)nsites,
+ (int)pri, (u_int32_t)timeout, &id);
verify_return(jnienv, err, 0);
+
+ return ((jint)id);
}
-/*static*/
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1panicstate
- (JNIEnv *jnienv, jclass jthis_class, jint value)
+JNIEXPORT jint JNICALL
+ Java_com_sleepycat_db_DbEnv_rep_1process_1message
+ (JNIEnv *jnienv, /* DbEnv */ jobject jthis, /* Dbt */ jobject control,
+ /* Dbt */ jobject rec, /* RepProcessMessage */ jobject result)
{
- int err;
+ DB_ENV *dbenv;
+ LOCKED_DBT cdbt, rdbt;
+ int err, envid;
- COMPQUIET(jthis_class, NULL);
- err = db_env_set_panicstate(value);
- verify_return(jnienv, err, 0);
+ if (!verify_non_null(jnienv, jthis) || !verify_non_null(jnienv, result))
+ return (-1);
+
+ dbenv = get_DB_ENV(jnienv, jthis);
+ err = 0;
+
+ /* The DBTs are always inputs. */
+ if (locked_dbt_get(&cdbt, jnienv, dbenv, control, inOp) != 0)
+ goto out2;
+ if (locked_dbt_get(&rdbt, jnienv, dbenv, rec, inOp) != 0)
+ goto out1;
+
+ envid = (*jnienv)->GetIntField(jnienv,
+ result, fid_RepProcessMessage_envid);
+
+ err = dbenv->rep_process_message(dbenv, &cdbt.javainfo->dbt,
+ &rdbt.javainfo->dbt, &envid);
+
+ if (err == DB_REP_NEWMASTER)
+ (*jnienv)->SetIntField(jnienv,
+ result, fid_RepProcessMessage_envid, envid);
+ else if (!DB_RETOK_REPPMSG(err))
+ verify_return(jnienv, err, 0);
+
+out1: locked_dbt_put(&rdbt, jnienv, dbenv);
+out2: locked_dbt_put(&cdbt, jnienv, dbenv);
+
+ return (err);
}
-/*static*/
JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1region_1init
- (JNIEnv *jnienv, jclass jthis_class, jint value)
+ Java_com_sleepycat_db_DbEnv_rep_1start
+ (JNIEnv *jnienv, /* DbEnv */ jobject jthis, /* Dbt */ jobject cookie,
+ jint flags)
{
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ LOCKED_DBT ldbt;
int err;
- COMPQUIET(jthis_class, NULL);
- err = db_env_set_region_init(value);
+ if (!verify_non_null(jnienv, jthis))
+ return;
+
+ dbenv = get_DB_ENV(jnienv, jthis);
+
+ /* The Dbt cookie may be null; if so, pass in a NULL DBT. */
+ if (cookie != NULL) {
+ if (locked_dbt_get(&ldbt, jnienv, dbenv, cookie, inOp) != 0)
+ goto out;
+ dbtp = &ldbt.javainfo->dbt;
+ } else
+ dbtp = NULL;
+
+ err = dbenv->rep_start(dbenv, dbtp, flags);
verify_return(jnienv, err, 0);
+
+out: if (cookie != NULL)
+ locked_dbt_put(&ldbt, jnienv, dbenv);
}
-/*static*/
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1tas_1spins
- (JNIEnv *jnienv, jclass jthis_class, jint value)
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_rep_1stat
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err;
+ DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
+ DB_REP_STAT *statp = NULL;
+ jobject retval = NULL;
+ jclass dbclass;
- COMPQUIET(jthis_class, NULL);
- err = db_env_set_tas_spins(value);
- verify_return(jnienv, err, 0);
+ if (!verify_non_null(jnienv, dbenv))
+ return (NULL);
+
+ err = dbenv->rep_stat(dbenv, &statp, (u_int32_t)flags);
+ if (verify_return(jnienv, err, 0)) {
+ if ((dbclass = get_class(jnienv, name_DB_REP_STAT)) == NULL ||
+ (retval =
+ create_default_object(jnienv, name_DB_REP_STAT)) == NULL)
+ goto err; /* An exception has been posted. */
+
+ __jv_fill_rep_stat(jnienv, dbclass, retval, statp);
+
+err: __os_ufree(dbenv, statp);
+ }
+ return (retval);
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_recovery_1init_1changed
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbRecoveryInit*/ jobject jrecoveryinit)
+JNIEXPORT void JNICALL
+Java_com_sleepycat_db_DbEnv_set_1rep_1limit
+ (JNIEnv *jnienv, /* DbEnv */ jobject jthis, jint gbytes, jint bytes)
{
DB_ENV *dbenv;
- DB_ENV_JAVAINFO *dbenvinfo;
+ int err;
dbenv = get_DB_ENV(jnienv, jthis);
- dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis);
- if (!verify_non_null(jnienv, dbenv) ||
- !verify_non_null(jnienv, dbenv))
- return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- dbjie_set_recovery_init_object(dbenvinfo, jnienv, dbenv, jrecoveryinit);
- JAVADB_ENV_API_END(dbenv);
+ if (verify_non_null(jnienv, dbenv)) {
+ err = dbenv->set_rep_limit(dbenv,
+ (u_int32_t)gbytes, (u_int32_t)bytes);
+ verify_return(jnienv, err, 0);
+ }
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1conflicts
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jobjectArray array)
+JNIEXPORT void JNICALL
+ Java_com_sleepycat_db_DbEnv_rep_1transport_1changed
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint envid,
+ /* DbRepTransport */ jobject jreptransport)
{
DB_ENV *dbenv;
DB_ENV_JAVAINFO *dbenvinfo;
- int err;
- jsize i, len;
- unsigned char *newarr;
dbenv = get_DB_ENV(jnienv, jthis);
dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis);
if (!verify_non_null(jnienv, dbenv) ||
- !verify_non_null(jnienv, dbenvinfo))
+ !verify_non_null(jnienv, dbenvinfo) ||
+ !verify_non_null(jnienv, jreptransport))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- len = (*jnienv)->GetArrayLength(jnienv, array);
-
- newarr = (unsigned char *)malloc(sizeof(unsigned char) * len * len);
-
- for (i=0; i<len; i++) {
- jobject subArray =
- (*jnienv)->GetObjectArrayElement(jnienv, array, i);
- (*jnienv)->GetByteArrayRegion(jnienv, (jbyteArray)subArray,
- 0, len,
- (jbyte *)&newarr[i*len]);
- }
- dbjie_set_conflict(dbenvinfo, newarr);
- err = dbenv->set_lk_conflicts(dbenv, newarr, len);
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
+ dbjie_set_rep_transport_object(dbenvinfo,
+ jnienv, dbenv, envid, jreptransport);
}
JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1server
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring jhost, jlong tsec,
- jlong ssec, jint flags)
+ Java_com_sleepycat_db_DbEnv_set_1rpc_1server
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbClient*/ jobject jclient,
+ jstring jhost, jlong tsec, jlong ssec, jint flags)
{
int err;
DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
const char *host = (*jnienv)->GetStringUTFChars(jnienv, jhost, NULL);
+ if (jclient != NULL) {
+ report_exception(jnienv, "DbEnv.set_rpc_server client arg "
+ "must be null; reserved for future use",
+ EINVAL, 0);
+ return;
+ }
if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = dbenv->set_server(dbenv, (char *)host,
+ err = dbenv->set_rpc_server(dbenv, NULL, host,
(long)tsec, (long)ssec, flags);
/* Throw an exception if the call failed. */
verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
}
}
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1shm_1key
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jlong shm_key)
-{
- int err;
- DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
-
- if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = dbenv->set_shm_key(dbenv, (long)shm_key);
-
- /* Throw an exception if the call failed. */
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
- }
-}
+JAVADB_METHOD(DbEnv_set_1shm_1key, (JAVADB_ARGS, jlong shm_key), DB_ENV,
+ set_shm_key, (c_this, (long)shm_key))
JNIEXPORT void JNICALL
Java_com_sleepycat_db_DbEnv__1set_1tx_1timestamp
@@ -476,31 +588,16 @@ JNIEXPORT void JNICALL
time_t time = seconds;
if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
err = dbenv->set_tx_timestamp(dbenv, &time);
/* Throw an exception if the call failed. */
verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
}
}
-JNIEXPORT void JNICALL
- Java_com_sleepycat_db_DbEnv_set_1verbose
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint which, jint onoff)
-{
- int err;
- DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
-
- if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = dbenv->set_verbose(dbenv, which, onoff);
-
- /* Throw an exception if the call failed. */
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
- }
-}
+JAVADB_METHOD(DbEnv_set_1verbose,
+ (JAVADB_ARGS, jint which, jboolean onoff), DB_ENV,
+ set_verbose, (c_this, which, onoff ? 1 : 0))
/*static*/
JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1major
@@ -550,15 +647,16 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1id
if (!verify_non_null(jnienv, dbenv))
return (-1);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = lock_id(dbenv, &id);
+ err = dbenv->lock_id(dbenv, &id);
verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
return (id);
}
+JAVADB_METHOD(DbEnv_lock_1id_1free, (JAVADB_ARGS, jint id), DB_ENV,
+ lock_id_free, (c_this, id))
+
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1stat
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis)
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err;
DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
@@ -568,44 +666,18 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1stat
if (!verify_non_null(jnienv, dbenv))
return (NULL);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- /* We cannot use the default allocator (on Win* platforms anyway)
- * because it often causes problems when we free storage
- * in a DLL that was allocated in another DLL. Using
- * our own allocator (ours just calls malloc!) ensures
- * that there is no mismatch.
- */
- err = lock_stat(dbenv, &statp, NULL);
+ err = dbenv->lock_stat(dbenv, &statp, (u_int32_t)flags);
if (verify_return(jnienv, err, 0)) {
- retval = create_default_object(jnienv, name_DB_LOCK_STAT);
- dbclass = get_class(jnienv, name_DB_LOCK_STAT);
+ if ((dbclass = get_class(jnienv, name_DB_LOCK_STAT)) == NULL ||
+ (retval =
+ create_default_object(jnienv, name_DB_LOCK_STAT)) == NULL)
+ goto err; /* An exception has been posted. */
- /* Set the individual fields */
- set_int_field(jnienv, dbclass, retval,
- "st_maxlocks", statp->st_maxlocks);
- set_int_field(jnienv, dbclass, retval,
- "st_nmodes", statp->st_nmodes);
- set_int_field(jnienv, dbclass, retval,
- "st_nlockers", statp->st_nlockers);
- set_int_field(jnienv, dbclass, retval,
- "st_nconflicts", statp->st_nconflicts);
- set_int_field(jnienv, dbclass, retval,
- "st_nrequests", statp->st_nrequests);
- set_int_field(jnienv, dbclass, retval,
- "st_nreleases", statp->st_nreleases);
- set_int_field(jnienv, dbclass, retval,
- "st_ndeadlocks", statp->st_ndeadlocks);
- set_int_field(jnienv, dbclass, retval,
- "st_region_wait", statp->st_region_wait);
- set_int_field(jnienv, dbclass, retval,
- "st_region_nowait", statp->st_region_nowait);
- set_int_field(jnienv, dbclass, retval,
- "st_regsize", statp->st_regsize);
-
- free(statp);
+ __jv_fill_lock_stat(jnienv, dbclass, retval, statp);
+
+err: __os_ufree(dbenv, statp);
}
- JAVADB_ENV_API_END(dbenv);
return (retval);
}
@@ -618,10 +690,8 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1detect
if (!verify_non_null(jnienv, dbenv))
return (0);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = lock_detect(dbenv, atype, flags, &aborted);
+ err = dbenv->lock_detect(dbenv, atype, flags, &aborted);
verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
return (aborted);
}
@@ -632,33 +702,260 @@ JNIEXPORT /*DbLock*/ jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1get
int err;
DB_ENV *dbenv;
DB_LOCK *dblock;
- JDBT dbobj;
+ LOCKED_DBT lobj;
/*DbLock*/ jobject retval;
dbenv = get_DB_ENV(jnienv, jthis);
if (!verify_non_null(jnienv, dbenv))
return (NULL);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- dblock = (DB_LOCK*)malloc(sizeof(DB_LOCK));
+ if ((err = __os_malloc(dbenv, sizeof(DB_LOCK), &dblock)) != 0)
+ if (!verify_return(jnienv, err, 0))
+ return (NULL);
+
memset(dblock, 0, sizeof(DB_LOCK));
err = 0;
retval = NULL;
- if (jdbt_lock(&dbobj, jnienv, obj, inOp) != 0)
+ if (locked_dbt_get(&lobj, jnienv, dbenv, obj, inOp) != 0)
goto out;
- err = lock_get(dbenv, locker, flags, &dbobj.dbt->dbt,
+ err = dbenv->lock_get(dbenv, locker, flags, &lobj.javainfo->dbt,
(db_lockmode_t)lock_mode, dblock);
- if (verify_return(jnienv, err, 0)) {
+
+ if (err == DB_LOCK_NOTGRANTED)
+ report_notgranted_exception(jnienv,
+ "DbEnv.lock_get not granted",
+ DB_LOCK_GET, lock_mode, obj,
+ NULL, -1);
+ else if (verify_return(jnienv, err, 0)) {
retval = create_default_object(jnienv, name_DB_LOCK);
set_private_dbobj(jnienv, name_DB_LOCK, retval, dblock);
}
+
out:
- jdbt_unlock(&dbobj, jnienv);
- JAVADB_ENV_API_END(dbenv);
+ locked_dbt_put(&lobj, jnienv, dbenv);
return (retval);
}
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_lock_1vec
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*u_int32_t*/ jint locker,
+ jint flags, /*const Dbt*/ jobjectArray list, jint offset, jint count)
+{
+ DB_ENV *dbenv;
+ DB_LOCKREQ *lockreq;
+ DB_LOCKREQ *prereq; /* preprocessed requests */
+ DB_LOCKREQ *failedreq;
+ DB_LOCK *lockp;
+ LOCKED_DBT *locked_dbts;
+ int err;
+ int alloc_err;
+ int i;
+ size_t bytesize;
+ size_t ldbtsize;
+ jobject jlockreq;
+ db_lockop_t op;
+ jobject jobj;
+ jobject jlock;
+ int completed;
+
+ dbenv = get_DB_ENV(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbenv))
+ goto out0;
+
+ if ((*jnienv)->GetArrayLength(jnienv, list) < offset + count) {
+ report_exception(jnienv,
+ "DbEnv.lock_vec array not large enough",
+ 0, 0);
+ goto out0;
+ }
+
+ bytesize = sizeof(DB_LOCKREQ) * count;
+ if ((err = __os_malloc(dbenv, bytesize, &lockreq)) != 0) {
+ verify_return(jnienv, err, 0);
+ goto out0;
+ }
+ memset(lockreq, 0, bytesize);
+
+ ldbtsize = sizeof(LOCKED_DBT) * count;
+ if ((err = __os_malloc(dbenv, ldbtsize, &locked_dbts)) != 0) {
+ verify_return(jnienv, err, 0);
+ goto out1;
+ }
+ memset(lockreq, 0, ldbtsize);
+ prereq = &lockreq[0];
+
+ /* fill in the lockreq array */
+ for (i = 0, prereq = &lockreq[0]; i < count; i++, prereq++) {
+ jlockreq = (*jnienv)->GetObjectArrayElement(jnienv, list,
+ offset + i);
+ if (jlockreq == NULL) {
+ report_exception(jnienv,
+ "DbEnv.lock_vec list entry is null",
+ 0, 0);
+ goto out2;
+ }
+ op = (*jnienv)->GetIntField(jnienv, jlockreq,
+ fid_DbLockRequest_op);
+ prereq->op = op;
+
+ switch (op) {
+ case DB_LOCK_GET_TIMEOUT:
+ /* Needed: mode, timeout, obj. Returned: lock. */
+ prereq->op = (*jnienv)->GetIntField(jnienv, jlockreq,
+ fid_DbLockRequest_timeout);
+ /* FALLTHROUGH */
+ case DB_LOCK_GET:
+ /* Needed: mode, obj. Returned: lock. */
+ prereq->mode = (*jnienv)->GetIntField(jnienv, jlockreq,
+ fid_DbLockRequest_mode);
+ jobj = (*jnienv)->GetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_obj);
+ if ((err = locked_dbt_get(&locked_dbts[i], jnienv,
+ dbenv, jobj, inOp)) != 0)
+ goto out2;
+ prereq->obj = &locked_dbts[i].javainfo->dbt;
+ break;
+ case DB_LOCK_PUT:
+ /* Needed: lock. Ignored: mode, obj. */
+ jlock = (*jnienv)->GetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_lock);
+ if (!verify_non_null(jnienv, jlock))
+ goto out2;
+ lockp = get_DB_LOCK(jnienv, jlock);
+ if (!verify_non_null(jnienv, lockp))
+ goto out2;
+
+ prereq->lock = *lockp;
+ break;
+ case DB_LOCK_PUT_ALL:
+ case DB_LOCK_TIMEOUT:
+ /* Needed: (none). Ignored: lock, mode, obj. */
+ break;
+ case DB_LOCK_PUT_OBJ:
+ /* Needed: obj. Ignored: lock, mode. */
+ jobj = (*jnienv)->GetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_obj);
+ if ((err = locked_dbt_get(&locked_dbts[i], jnienv,
+ dbenv, jobj, inOp)) != 0)
+ goto out2;
+ prereq->obj = &locked_dbts[i].javainfo->dbt;
+ break;
+ default:
+ report_exception(jnienv,
+ "DbEnv.lock_vec bad op value",
+ 0, 0);
+ goto out2;
+ }
+ }
+
+ err = dbenv->lock_vec(dbenv, locker, flags, lockreq, count, &failedreq);
+ if (err == 0)
+ completed = count;
+ else
+ completed = failedreq - lockreq;
+
+ /* do post processing for any and all requests that completed */
+ for (i = 0; i < completed; i++) {
+ op = lockreq[i].op;
+ if (op == DB_LOCK_PUT) {
+ /*
+ * After a successful put, the DbLock can no longer
+ * be used, so we release the storage related to it.
+ */
+ jlockreq = (*jnienv)->GetObjectArrayElement(jnienv,
+ list, i + offset);
+ jlock = (*jnienv)->GetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_lock);
+ lockp = get_DB_LOCK(jnienv, jlock);
+ __os_free(NULL, lockp);
+ set_private_dbobj(jnienv, name_DB_LOCK, jlock, 0);
+ }
+ else if (op == DB_LOCK_GET) {
+ /*
+ * Store the lock that was obtained.
+ * We need to create storage for it since
+ * the lockreq array only exists during this
+ * method call.
+ */
+ alloc_err = __os_malloc(dbenv, sizeof(DB_LOCK), &lockp);
+ if (!verify_return(jnienv, alloc_err, 0))
+ goto out2;
+
+ *lockp = lockreq[i].lock;
+
+ jlockreq = (*jnienv)->GetObjectArrayElement(jnienv,
+ list, i + offset);
+ jlock = create_default_object(jnienv, name_DB_LOCK);
+ set_private_dbobj(jnienv, name_DB_LOCK, jlock, lockp);
+ (*jnienv)->SetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_lock,
+ jlock);
+ }
+ }
+
+ /* If one of the locks was not granted, build the exception now. */
+ if (err == DB_LOCK_NOTGRANTED && i < count) {
+ jlockreq = (*jnienv)->GetObjectArrayElement(jnienv,
+ list, i + offset);
+ jobj = (*jnienv)->GetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_obj);
+ jlock = (*jnienv)->GetObjectField(jnienv, jlockreq,
+ fid_DbLockRequest_lock);
+ report_notgranted_exception(jnienv,
+ "DbEnv.lock_vec incomplete",
+ lockreq[i].op,
+ lockreq[i].mode,
+ jobj,
+ jlock,
+ i);
+ }
+ else
+ verify_return(jnienv, err, 0);
+
+ out2:
+ /* Free the dbts that we have locked */
+ for (i = 0 ; i < (prereq - lockreq); i++) {
+ if ((op = lockreq[i].op) == DB_LOCK_GET ||
+ op == DB_LOCK_PUT_OBJ)
+ locked_dbt_put(&locked_dbts[i], jnienv, dbenv);
+ }
+ __os_free(dbenv, locked_dbts);
+
+ out1:
+ __os_free(dbenv, lockreq);
+
+ out0:
+ return;
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_lock_1put
+ (JNIEnv *jnienv, jobject jthis, /*DbLock*/ jobject jlock)
+{
+ int err;
+ DB_ENV *dbenv;
+ DB_LOCK *dblock;
+
+ dbenv = get_DB_ENV(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbenv))
+ return;
+
+ dblock = get_DB_LOCK(jnienv, jlock);
+ if (!verify_non_null(jnienv, dblock))
+ return;
+
+ err = dbenv->lock_put(dbenv, dblock);
+ if (verify_return(jnienv, err, 0)) {
+ /*
+ * After a successful put, the DbLock can no longer
+ * be used, so we release the storage related to it
+ * (allocated in DbEnv.lock_get()).
+ */
+ __os_free(NULL, dblock);
+
+ set_private_dbobj(jnienv, name_DB_LOCK, jlock, 0);
+ }
+}
+
JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_log_1archive
(JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
@@ -672,8 +969,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_log_1archive
strarray = NULL;
if (!verify_non_null(jnienv, dbenv))
return (0);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = log_archive(dbenv, &ret, flags, 0);
+ err = dbenv->log_archive(dbenv, &ret, flags);
if (!verify_return(jnienv, err, 0))
return (0);
@@ -682,16 +978,16 @@ JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_log_1archive
while (ret[len] != NULL)
len++;
stringClass = (*jnienv)->FindClass(jnienv, "java/lang/String");
- strarray = (*jnienv)->NewObjectArray(jnienv, len,
- stringClass, 0);
+ if ((strarray = (*jnienv)->NewObjectArray(jnienv,
+ len, stringClass, 0)) == NULL)
+ goto out;
for (i=0; i<len; i++) {
jstring str = (*jnienv)->NewStringUTF(jnienv, ret[i]);
(*jnienv)->SetObjectArrayElement(jnienv, strarray,
- i, str);
+ i, str);
}
}
- JAVADB_ENV_API_END(dbenv);
- return (strarray);
+out: return (strarray);
}
JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_log_1compare
@@ -708,80 +1004,40 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_log_1compare
return (log_compare(dblsn0, dblsn1));
}
-JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_log_1file
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn)
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1cursor
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err;
+ DB_LOGC *dblogc;
DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
- DB_LSN *dblsn = get_DB_LSN(jnienv, lsn);
- char filename[FILENAME_MAX+1] = "";
if (!verify_non_null(jnienv, dbenv))
return (NULL);
-
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- err = log_file(dbenv, dblsn, filename, FILENAME_MAX);
+ err = dbenv->log_cursor(dbenv, &dblogc, flags);
verify_return(jnienv, err, 0);
- filename[FILENAME_MAX] = '\0'; /* just to be sure */
- JAVADB_ENV_API_END(dbenv);
- return (get_java_string(jnienv, filename));
+ return (get_DbLogc(jnienv, dblogc));
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1flush
+JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_log_1file
(JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn)
{
int err;
DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
DB_LSN *dblsn = get_DB_LSN(jnienv, lsn);
+ char filename[FILENAME_MAX+1] = "";
if (!verify_non_null(jnienv, dbenv))
- return;
-
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
+ return (NULL);
- err = log_flush(dbenv, dblsn);
+ err = dbenv->log_file(dbenv, dblsn, filename, FILENAME_MAX);
verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
+ filename[FILENAME_MAX] = '\0'; /* just to be sure */
+ return (get_java_string(jnienv, filename));
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1get
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn,
- /*DbDbt*/ jobject data, jint flags)
-{
- int err, retry;
- DB_ENV *dbenv;
- DB_LSN *dblsn;
- JDBT dbdata;
-
- dbenv = get_DB_ENV(jnienv, jthis);
- dblsn = get_DB_LSN(jnienv, lsn);
-
- if (!verify_non_null(jnienv, dbenv))
- return;
-
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- if (jdbt_lock(&dbdata, jnienv, data, outOp) != 0)
- goto out;
-
- for (retry = 0; retry < 3; retry++) {
- err = log_get(dbenv, dblsn, &dbdata.dbt->dbt, flags);
- /* If we failed due to lack of memory in our DBT arrays,
- * retry.
- */
- if (err != ENOMEM)
- break;
- if (!jdbt_realloc(&dbdata, jnienv))
- break;
- }
-
- verify_return(jnienv, err, 0);
-
- out:
- jdbt_unlock(&dbdata, jnienv);
- JAVADB_ENV_API_END(dbenv);
-}
+JAVADB_METHOD(DbEnv_log_1flush,
+ (JAVADB_ARGS, /*DbLsn*/ jobject lsn), DB_ENV,
+ log_flush, (c_this, get_DB_LSN(jnienv, lsn)))
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1put
(JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn,
@@ -790,72 +1046,28 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1put
int err;
DB_ENV *dbenv;
DB_LSN *dblsn;
- JDBT dbdata;
+ LOCKED_DBT ldata;
dbenv = get_DB_ENV(jnienv, jthis);
dblsn = get_DB_LSN(jnienv, lsn);
if (!verify_non_null(jnienv, dbenv))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- if (jdbt_lock(&dbdata, jnienv, data, inOp) != 0)
- goto out;
-
- err = log_put(dbenv, dblsn, &dbdata.dbt->dbt, flags);
- verify_return(jnienv, err, 0);
- out:
- jdbt_unlock(&dbdata, jnienv);
- JAVADB_ENV_API_END(dbenv);
-}
-
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1register
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*Db*/ jobject dbp,
- jstring name)
-{
- int err;
- DB_ENV *dbenv;
- DB *dbdb;
- JSTR dbname;
-
- dbenv = get_DB_ENV(jnienv, jthis);
- dbdb = get_DB(jnienv, dbp);
- if (!verify_non_null(jnienv, dbenv))
+ /* log_put's DB_LSN argument may not be NULL. */
+ if (!verify_non_null(jnienv, dblsn))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- if (jstr_lock(&dbname, jnienv, name) != 0)
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, inOp) != 0)
goto out;
- err = log_register(dbenv, dbdb, dbname.string);
+ err = dbenv->log_put(dbenv, dblsn, &ldata.javainfo->dbt, flags);
verify_return(jnienv, err, 0);
out:
- jstr_unlock(&dbname, jnienv);
- JAVADB_ENV_API_END(dbenv);
-}
-
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1unregister
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*Db*/ jobject dbp)
-{
- int err;
- DB_ENV *dbenv;
- DB *dbdb;
-
- dbenv = get_DB_ENV(jnienv, jthis);
- dbdb = get_DB(jnienv, dbp);
- if (!verify_non_null(jnienv, dbenv))
- return;
-
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- err = log_unregister(dbenv, dbdb);
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
+ locked_dbt_put(&ldata, jnienv, dbenv);
}
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1stat
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis)
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err;
DB_ENV *dbenv;
@@ -869,59 +1081,22 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1stat
if (!verify_non_null(jnienv, dbenv))
return (NULL);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- /* We cannot use the default allocator (on Win* platforms anyway)
- * because it often causes problems when we free storage
- * in a DLL that was allocated in another DLL. Using
- * our own allocator (ours just calls malloc!) ensures
- * that there is no mismatch.
- */
- err = log_stat(dbenv, &statp, NULL);
+ err = dbenv->log_stat(dbenv, &statp, (u_int32_t)flags);
if (verify_return(jnienv, err, 0)) {
- retval = create_default_object(jnienv, name_DB_LOG_STAT);
- dbclass = get_class(jnienv, name_DB_LOG_STAT);
+ if ((dbclass = get_class(jnienv, name_DB_LOG_STAT)) == NULL ||
+ (retval =
+ create_default_object(jnienv, name_DB_LOG_STAT)) == NULL)
+ goto err; /* An exception has been posted. */
- /* Set the individual fields */
- set_int_field(jnienv, dbclass, retval,
- "st_magic", statp->st_magic);
- set_int_field(jnienv, dbclass, retval,
- "st_version", statp->st_version);
- set_int_field(jnienv, dbclass, retval,
- "st_mode", statp->st_mode);
- set_int_field(jnienv, dbclass, retval,
- "st_lg_max", statp->st_lg_max);
- set_int_field(jnienv, dbclass, retval,
- "st_w_bytes", statp->st_w_bytes);
- set_int_field(jnienv, dbclass, retval,
- "st_w_mbytes", statp->st_w_mbytes);
- set_int_field(jnienv, dbclass, retval,
- "st_wc_bytes", statp->st_wc_bytes);
- set_int_field(jnienv, dbclass, retval,
- "st_wc_mbytes", statp->st_wc_mbytes);
- set_int_field(jnienv, dbclass, retval,
- "st_wcount", statp->st_wcount);
- set_int_field(jnienv, dbclass, retval,
- "st_scount", statp->st_scount);
- set_int_field(jnienv, dbclass, retval,
- "st_region_wait", statp->st_region_wait);
- set_int_field(jnienv, dbclass, retval,
- "st_region_nowait", statp->st_region_nowait);
- set_int_field(jnienv, dbclass, retval,
- "st_cur_file", statp->st_cur_file);
- set_int_field(jnienv, dbclass, retval,
- "st_cur_offset", statp->st_cur_offset);
- set_int_field(jnienv, dbclass, retval,
- "st_regsize", statp->st_regsize);
-
- free(statp);
+ __jv_fill_log_stat(jnienv, dbclass, retval, statp);
+
+err: __os_ufree(dbenv, statp);
}
- JAVADB_ENV_API_END(dbenv);
return (retval);
}
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_memp_1stat
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis)
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err;
jclass dbclass;
@@ -935,65 +1110,22 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_memp_1stat
if (!verify_non_null(jnienv, dbenv))
return (NULL);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- /* We cannot use the default allocator (on Win* platforms anyway)
- * because it often causes problems when we free storage
- * in a DLL that was allocated in another DLL. Using
- * our own allocator (ours just calls malloc!) ensures
- * that there is no mismatch.
- */
- err = memp_stat(dbenv, &statp, 0, NULL);
+ err = dbenv->memp_stat(dbenv, &statp, 0, (u_int32_t)flags);
if (verify_return(jnienv, err, 0)) {
- retval = create_default_object(jnienv, name_DB_MPOOL_STAT);
- dbclass = get_class(jnienv, name_DB_MPOOL_STAT);
-
- set_int_field(jnienv, dbclass, retval, "st_cachesize", 0);
- set_int_field(jnienv, dbclass, retval,
- "st_cache_hit", statp->st_cache_hit);
- set_int_field(jnienv, dbclass, retval,
- "st_cache_miss", statp->st_cache_miss);
- set_int_field(jnienv, dbclass, retval,
- "st_map", statp->st_map);
- set_int_field(jnienv, dbclass, retval,
- "st_page_create", statp->st_page_create);
- set_int_field(jnienv, dbclass, retval,
- "st_page_in", statp->st_page_in);
- set_int_field(jnienv, dbclass, retval,
- "st_page_out", statp->st_page_out);
- set_int_field(jnienv, dbclass, retval,
- "st_ro_evict", statp->st_ro_evict);
- set_int_field(jnienv, dbclass, retval,
- "st_rw_evict", statp->st_rw_evict);
- set_int_field(jnienv, dbclass, retval,
- "st_hash_buckets", statp->st_hash_buckets);
- set_int_field(jnienv, dbclass, retval,
- "st_hash_searches", statp->st_hash_searches);
- set_int_field(jnienv, dbclass, retval,
- "st_hash_longest", statp->st_hash_longest);
- set_int_field(jnienv, dbclass, retval,
- "st_hash_examined", statp->st_hash_examined);
- set_int_field(jnienv, dbclass, retval,
- "st_page_clean", statp->st_page_clean);
- set_int_field(jnienv, dbclass, retval,
- "st_page_dirty", statp->st_page_dirty);
- set_int_field(jnienv, dbclass, retval,
- "st_page_trickle", statp->st_page_trickle);
- set_int_field(jnienv, dbclass, retval,
- "st_region_wait", statp->st_region_wait);
- set_int_field(jnienv, dbclass, retval,
- "st_region_nowait", statp->st_region_nowait);
- set_int_field(jnienv, dbclass, retval,
- "st_regsize", statp->st_regsize);
-
- free(statp);
+ if ((dbclass = get_class(jnienv, name_DB_MPOOL_STAT)) == NULL ||
+ (retval =
+ create_default_object(jnienv, name_DB_MPOOL_STAT)) == NULL)
+ goto err; /* An exception has been posted. */
+
+ __jv_fill_mpool_stat(jnienv, dbclass, retval, statp);
+
+err: __os_ufree(dbenv, statp);
}
- JAVADB_ENV_API_END(dbenv);
return (retval);
}
JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_memp_1fstat
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis)
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err, i, len;
jclass fstat_class;
@@ -1009,57 +1141,49 @@ JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_memp_1fstat
if (!verify_non_null(jnienv, dbenv))
return (NULL);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- /* We cannot use the default allocator (on Win* platforms anyway)
- * because it often causes problems when we free storage
- * in a DLL that was allocated in another DLL. Using
- * our own allocator (ours just calls malloc!) ensures
- * that there is no mismatch.
- */
- err = memp_stat(dbenv, 0, &fstatp, NULL);
+ err = dbenv->memp_stat(dbenv, 0, &fstatp, (u_int32_t)flags);
if (verify_return(jnienv, err, 0)) {
len = 0;
- while (fstatp[len])
+ while (fstatp[len] != NULL)
len++;
- fstat_class = get_class(jnienv, name_DB_MPOOL_FSTAT);
- retval = (*jnienv)->NewObjectArray(jnienv, len,
- fstat_class, 0);
+ if ((fstat_class =
+ get_class(jnienv, name_DB_MPOOL_FSTAT)) == NULL ||
+ (retval = (*jnienv)->NewObjectArray(jnienv, len,
+ fstat_class, 0)) == NULL)
+ goto err;
for (i=0; i<len; i++) {
- jobject obj = create_default_object(jnienv,
- name_DB_MPOOL_FSTAT);
+ jobject obj;
+ if ((obj = create_default_object(jnienv,
+ name_DB_MPOOL_FSTAT)) == NULL)
+ goto err;
(*jnienv)->SetObjectArrayElement(jnienv, retval,
- i, obj);
+ i, obj);
/* Set the string field. */
- filename_id =
- (*jnienv)->GetFieldID(jnienv, fstat_class,
- "file_name",
- string_signature);
- jfilename =
- get_java_string(jnienv, fstatp[i]->file_name);
+ filename_id = (*jnienv)->GetFieldID(jnienv,
+ fstat_class, "file_name", string_signature);
+ jfilename = get_java_string(jnienv,
+ fstatp[i]->file_name);
(*jnienv)->SetObjectField(jnienv, obj,
- filename_id, jfilename);
-
+ filename_id, jfilename);
set_int_field(jnienv, fstat_class, obj,
- "st_pagesize", fstatp[i]->st_pagesize);
+ "st_pagesize", fstatp[i]->st_pagesize);
set_int_field(jnienv, fstat_class, obj,
- "st_cache_hit", fstatp[i]->st_cache_hit);
+ "st_cache_hit", fstatp[i]->st_cache_hit);
set_int_field(jnienv, fstat_class, obj,
- "st_cache_miss", fstatp[i]->st_cache_miss);
+ "st_cache_miss", fstatp[i]->st_cache_miss);
set_int_field(jnienv, fstat_class, obj,
- "st_map", fstatp[i]->st_map);
+ "st_map", fstatp[i]->st_map);
set_int_field(jnienv, fstat_class, obj,
- "st_page_create", fstatp[i]->st_page_create);
+ "st_page_create", fstatp[i]->st_page_create);
set_int_field(jnienv, fstat_class, obj,
- "st_page_in", fstatp[i]->st_page_in);
+ "st_page_in", fstatp[i]->st_page_in);
set_int_field(jnienv, fstat_class, obj,
- "st_page_out", fstatp[i]->st_page_out);
- free(fstatp[i]);
+ "st_page_out", fstatp[i]->st_page_out);
+ __os_ufree(dbenv, fstatp[i]);
}
- free(fstatp);
+err: __os_ufree(dbenv, fstatp);
}
- JAVADB_ENV_API_END(dbenv);
return (retval);
}
@@ -1071,10 +1195,8 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_memp_1trickle
int result = 0;
if (verify_non_null(jnienv, dbenv)) {
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = memp_trickle(dbenv, pct, &result);
+ err = dbenv->memp_trickle(dbenv, pct, &result);
verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
}
return (result);
}
@@ -1090,36 +1212,21 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1begin
if (!verify_non_null(jnienv, dbenv))
return (0);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
dbpid = get_DB_TXN(jnienv, pid);
result = 0;
- err = txn_begin(dbenv, dbpid, &result, flags);
+ err = dbenv->txn_begin(dbenv, dbpid, &result, flags);
if (!verify_return(jnienv, err, 0))
return (0);
- JAVADB_ENV_API_END(dbenv);
return (get_DbTxn(jnienv, result));
}
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_txn_1checkpoint
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint kbyte, jint min, jint flags)
-{
- int err;
- DB_ENV *dbenv = get_DB_ENV(jnienv, jthis);
-
- if (!verify_non_null(jnienv, dbenv))
- return (0);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- err = txn_checkpoint(dbenv, kbyte, min, flags);
- if (err != DB_INCOMPLETE)
- verify_return(jnienv, err, 0);
- JAVADB_ENV_API_END(dbenv);
- return (err);
-}
+JAVADB_METHOD(DbEnv_txn_1checkpoint,
+ (JAVADB_ARGS, jint kbyte, jint min, jint flags), DB_ENV,
+ txn_checkpoint, (c_this, kbyte, min, flags))
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_tx_1recover_1changed
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbFeedback*/ jobject jtxrecover)
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_app_1dispatch_1changed
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbFeedback*/ jobject jappdispatch)
{
DB_ENV *dbenv;
DB_ENV_JAVAINFO *dbenvinfo;
@@ -1130,13 +1237,96 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_tx_1recover_1changed
!verify_non_null(jnienv, dbenvinfo))
return;
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
- dbjie_set_tx_recover_object(dbenvinfo, jnienv, dbenv, jtxrecover);
- JAVADB_ENV_API_END(dbenv);
+ dbjie_set_app_dispatch_object(dbenvinfo, jnienv, dbenv, jappdispatch);
+}
+
+JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_txn_1recover
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint count, jint flags)
+{
+ int err;
+ DB_ENV *dbenv;
+ DB_PREPLIST *preps;
+ long retcount;
+ int i;
+ char signature[128];
+ size_t bytesize;
+ jobject retval;
+ jobject obj;
+ jobject txnobj;
+ jbyteArray bytearr;
+ jclass preplist_class;
+ jfieldID txn_fieldid;
+ jfieldID gid_fieldid;
+
+ retval = NULL;
+ dbenv = get_DB_ENV(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbenv))
+ return (NULL);
+
+ /*
+ * We need to allocate some local storage for the
+ * returned preplist, and that requires us to do
+ * our own argument validation.
+ */
+ if (count <= 0) {
+ verify_return(jnienv, EINVAL, 0);
+ goto out;
+ }
+
+ bytesize = sizeof(DB_PREPLIST) * count;
+ if ((err = __os_malloc(dbenv, bytesize, &preps)) != 0) {
+ verify_return(jnienv, err, 0);
+ goto out;
+ }
+
+ err = dbenv->txn_recover(dbenv, preps, count, &retcount, flags);
+
+ if (verify_return(jnienv, err, 0)) {
+ if ((preplist_class =
+ get_class(jnienv, name_DB_PREPLIST)) == NULL ||
+ (retval = (*jnienv)->NewObjectArray(jnienv, retcount,
+ preplist_class, 0)) == NULL)
+ goto err;
+
+ (void)snprintf(signature, sizeof(signature),
+ "L%s%s;", DB_PACKAGE_NAME, name_DB_TXN);
+ txn_fieldid = (*jnienv)->GetFieldID(jnienv, preplist_class,
+ "txn", signature);
+ gid_fieldid = (*jnienv)->GetFieldID(jnienv, preplist_class,
+ "gid", "[B");
+
+ for (i=0; i<retcount; i++) {
+ /*
+ * First, make a blank DbPreplist object
+ * and set the array entry.
+ */
+ if ((obj = create_default_object(jnienv,
+ name_DB_PREPLIST)) == NULL)
+ goto err;
+ (*jnienv)->SetObjectArrayElement(jnienv,
+ retval, i, obj);
+
+ /* Set the txn field. */
+ txnobj = get_DbTxn(jnienv, preps[i].txn);
+ (*jnienv)->SetObjectField(jnienv,
+ obj, txn_fieldid, txnobj);
+
+ /* Build the gid array and set the field. */
+ if ((bytearr = (*jnienv)->NewByteArray(jnienv,
+ sizeof(preps[i].gid))) == NULL)
+ goto err;
+ (*jnienv)->SetByteArrayRegion(jnienv, bytearr, 0,
+ sizeof(preps[i].gid), (jbyte *)&preps[i].gid[0]);
+ (*jnienv)->SetObjectField(jnienv, obj,
+ gid_fieldid, bytearr);
+ }
+ }
+err: __os_free(dbenv, preps);
+out: return (retval);
}
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1stat
- (JNIEnv *jnienv, /*DbEnv*/ jobject jthis)
+ (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags)
{
int err;
DB_ENV *dbenv;
@@ -1154,57 +1344,29 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1stat
if (!verify_non_null(jnienv, dbenv))
return (NULL);
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
-
- /* We cannot use the default allocator (on Win* platforms anyway)
- * because it often causes problems when we free storage
- * in a DLL that was allocated in another DLL. Using
- * our own allocator (ours just calls malloc!) ensures
- * that there is no mismatch.
- */
- err = txn_stat(dbenv, &statp, NULL);
+ err = dbenv->txn_stat(dbenv, &statp, (u_int32_t)flags);
if (verify_return(jnienv, err, 0)) {
- retval = create_default_object(jnienv, name_DB_TXN_STAT);
- dbclass = get_class(jnienv, name_DB_TXN_STAT);
+ if ((dbclass = get_class(jnienv, name_DB_TXN_STAT)) == NULL ||
+ (retval =
+ create_default_object(jnienv, name_DB_TXN_STAT)) == NULL)
+ goto err;
/* Set the individual fields */
+ __jv_fill_txn_stat(jnienv, dbclass, retval, statp);
+
+ if ((active_class =
+ get_class(jnienv, name_DB_TXN_STAT_ACTIVE)) == NULL ||
+ (actives = (*jnienv)->NewObjectArray(jnienv,
+ statp->st_nactive, active_class, 0)) == NULL)
+ goto err;
- set_lsn_field(jnienv, dbclass, retval,
- "st_last_ckp", statp->st_last_ckp);
- set_lsn_field(jnienv, dbclass, retval,
- "st_pending_ckp", statp->st_pending_ckp);
- set_long_field(jnienv, dbclass, retval,
- "st_time_ckp", statp->st_time_ckp);
- set_int_field(jnienv, dbclass, retval,
- "st_last_txnid", statp->st_last_txnid);
- set_int_field(jnienv, dbclass, retval,
- "st_maxtxns", statp->st_maxtxns);
- set_int_field(jnienv, dbclass, retval,
- "st_naborts", statp->st_naborts);
- set_int_field(jnienv, dbclass, retval,
- "st_nbegins", statp->st_nbegins);
- set_int_field(jnienv, dbclass, retval,
- "st_ncommits", statp->st_ncommits);
- set_int_field(jnienv, dbclass, retval,
- "st_nactive", statp->st_nactive);
- set_int_field(jnienv, dbclass, retval,
- "st_maxnactive", statp->st_maxnactive);
-
- active_class = get_class(jnienv, name_DB_TXN_STAT_ACTIVE);
- actives =
- (*jnienv)->NewObjectArray(jnienv, statp->st_nactive,
- active_class, 0);
-
- /* Set the st_txnarray field. This is a little more involved
+ /*
+ * Set the st_txnarray field. This is a little more involved
* than other fields, since the type is an array, so none
* of our utility functions help.
*/
- strncpy(active_signature, "[L", sizeof(active_signature));
- strncat(active_signature, DB_PACKAGE_NAME,
- sizeof(active_signature));
- strncat(active_signature, name_DB_TXN_STAT_ACTIVE,
- sizeof(active_signature));
- strncat(active_signature, ";", sizeof(active_signature));
+ (void)snprintf(active_signature, sizeof(active_signature),
+ "[L%s%s;", DB_PACKAGE_NAME, name_DB_TXN_STAT_ACTIVE);
arrid = (*jnienv)->GetFieldID(jnienv, dbclass, "st_txnarray",
active_signature);
@@ -1212,26 +1374,21 @@ JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1stat
/* Now fill the in the elements of st_txnarray. */
for (i=0; i<statp->st_nactive; i++) {
- obj = create_default_object(jnienv, name_DB_TXN_STAT_ACTIVE);
- (*jnienv)->SetObjectArrayElement(jnienv, actives, i, obj);
+ obj = create_default_object(jnienv,
+ name_DB_TXN_STAT_ACTIVE);
+ (*jnienv)->SetObjectArrayElement(jnienv,
+ actives, i, obj);
set_int_field(jnienv, active_class, obj,
"txnid", statp->st_txnarray[i].txnid);
- set_int_field(jnienv, active_class, obj,
- "parentid", statp->st_txnarray[i].parentid);
+ set_int_field(jnienv, active_class, obj, "parentid",
+ statp->st_txnarray[i].parentid);
set_lsn_field(jnienv, active_class, obj,
"lsn", statp->st_txnarray[i].lsn);
}
- set_int_field(jnienv, dbclass, retval,
- "st_region_wait", statp->st_region_wait);
- set_int_field(jnienv, dbclass, retval,
- "st_region_nowait", statp->st_region_nowait);
- set_int_field(jnienv, dbclass, retval,
- "st_regsize", statp->st_regsize);
-
- free(statp);
+
+err: __os_ufree(dbenv, statp);
}
- JAVADB_ENV_API_END(dbenv);
return (retval);
}
@@ -1247,10 +1404,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errcall
if (verify_non_null(jnienv, dbenv) &&
verify_non_null(jnienv, dbenvinfo)) {
-
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
dbjie_set_errcall(dbenvinfo, jnienv, errcall);
- JAVADB_ENV_API_END(dbenv);
}
}
@@ -1265,10 +1419,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errpfx
if (verify_non_null(jnienv, dbenv) &&
verify_non_null(jnienv, dbenvinfo)) {
-
- JAVADB_ENV_API_BEGIN(dbenv, jthis);
dbjie_set_errpfx(dbenvinfo, jnienv, str);
- JAVADB_ENV_API_END(dbenv);
}
}
@@ -1283,8 +1434,7 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1finalize
envinfo = get_DB_ENV_JAVAINFO(jnienv, jthis);
DB_ASSERT(envinfo != NULL);
- /* Note: We detect unclosed DbEnvs and report it.
- */
+ /* Note: We detect and report unclosed DbEnvs. */
if (dbenv != NULL && envinfo != NULL && !dbjie_is_dbopen(envinfo)) {
/* If this error occurs, this object was never closed. */
diff --git a/bdb/libdb_java/java_DbLock.c b/bdb/libdb_java/java_DbLock.c
index 287ca6622e5..00a9836bfa0 100644
--- a/bdb/libdb_java/java_DbLock.c
+++ b/bdb/libdb_java/java_DbLock.c
@@ -1,55 +1,30 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_DbLock.c,v 11.4 2000/11/30 00:58:39 ubell Exp $";
+static const char revid[] = "$Id: java_DbLock.c,v 11.12 2002/02/28 21:27:38 ubell Exp $";
#endif /* not lint */
#include <jni.h>
#include <stdlib.h>
#include <string.h>
-#include "db.h"
+#include "db_int.h"
#include "java_util.h"
#include "com_sleepycat_db_DbLock.h"
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_put
- (JNIEnv *jnienv, jobject jthis, /*DbEnv*/ jobject env)
-{
- int err;
- DB_LOCK *dblock = get_DB_LOCK(jnienv, jthis);
- DB_ENV *dbenv = get_DB_ENV(jnienv, env);
-
- if (!verify_non_null(jnienv, dbenv))
- return;
-
- if (!verify_non_null(jnienv, dblock))
- return;
-
- err = lock_put(dbenv, dblock);
- if (verify_return(jnienv, err, 0)) {
- /* After a successful put, the DbLock can no longer
- * be used, so we release the storage related to it
- * (allocated in DbEnv.lock_get() or lock_tget()).
- */
- free(dblock);
-
- set_private_dbobj(jnienv, name_DB_LOCK, jthis, 0);
- }
-}
-
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_finalize
(JNIEnv *jnienv, jobject jthis)
{
DB_LOCK *dblock = get_DB_LOCK(jnienv, jthis);
if (dblock) {
/* Free any data related to DB_LOCK here */
- free(dblock);
+ __os_free(NULL, dblock);
}
set_private_dbobj(jnienv, name_DB_LOCK, jthis, 0); /* paranoia */
}
diff --git a/bdb/libdb_java/java_DbLogc.c b/bdb/libdb_java/java_DbLogc.c
new file mode 100644
index 00000000000..69294d9baac
--- /dev/null
+++ b/bdb/libdb_java/java_DbLogc.c
@@ -0,0 +1,110 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: java_DbLogc.c,v 11.6 2002/07/02 12:03:03 mjc Exp $";
+#endif /* not lint */
+
+#include <jni.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef DIAGNOSTIC
+#include <stdio.h>
+#endif
+
+#include "db_int.h"
+#include "java_util.h"
+#include "com_sleepycat_db_DbLogc.h"
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLogc_close
+ (JNIEnv *jnienv, jobject jthis, jint flags)
+{
+ int err;
+ DB_LOGC *dblogc = get_DB_LOGC(jnienv, jthis);
+
+ if (!verify_non_null(jnienv, dblogc))
+ return;
+ err = dblogc->close(dblogc, flags);
+ if (verify_return(jnienv, err, 0)) {
+ set_private_dbobj(jnienv, name_DB_LOGC, jthis, 0);
+ }
+}
+
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbLogc_get
+ (JNIEnv *jnienv, jobject jthis,
+ /*DbLsn*/ jobject lsn, /*Dbt*/ jobject data, jint flags)
+{
+ int err, retry;
+ DB_LOGC *dblogc;
+ DB_LSN *dblsn;
+ LOCKED_DBT ldata;
+ OpKind dataop;
+
+ /*
+ * Depending on flags, the user may be supplying the key,
+ * or else we may have to retrieve it.
+ */
+ err = 0;
+ dataop = outOp;
+
+ dblogc = get_DB_LOGC(jnienv, jthis);
+ dblsn = get_DB_LSN(jnienv, lsn);
+ if (locked_dbt_get(&ldata, jnienv, dblogc->dbenv, data, dataop) != 0)
+ goto out1;
+
+ if (!verify_non_null(jnienv, dblogc))
+ goto out1;
+
+ for (retry = 0; retry < 3; retry++) {
+ err = dblogc->get(dblogc, dblsn, &ldata.javainfo->dbt, flags);
+
+ /*
+ * If we failed due to lack of memory in our DBT arrays,
+ * retry.
+ */
+ if (err != ENOMEM)
+ break;
+ if (!locked_dbt_realloc(&ldata, jnienv, dblogc->dbenv))
+ break;
+ }
+ out1:
+ locked_dbt_put(&ldata, jnienv, dblogc->dbenv);
+ if (!DB_RETOK_LGGET(err)) {
+ if (verify_dbt(jnienv, err, &ldata))
+ verify_return(jnienv, err, 0);
+ }
+ return (err);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLogc_finalize
+ (JNIEnv *jnienv, jobject jthis)
+{
+ /*
+ * Free any data related to DB_LOGC here.
+ * If we ever have java-only data embedded in the DB_LOGC
+ * and need to do this, we'll have to track DbLogc's
+ * according to which DbEnv owns them, just as
+ * we track Db's according to which DbEnv owns them.
+ * That's necessary to avoid double freeing that
+ * comes about when closes interact with GC.
+ */
+
+#ifdef DIAGNOSTIC
+ DB_LOGC *dblogc;
+
+ dblogc = get_DB_LOGC(jnienv, jthis);
+ if (dblogc != NULL)
+ fprintf(stderr, "Java API: DbLogc has not been closed\n");
+#else
+
+ COMPQUIET(jnienv, NULL);
+ COMPQUIET(jthis, NULL);
+
+#endif
+}
diff --git a/bdb/libdb_java/java_DbLsn.c b/bdb/libdb_java/java_DbLsn.c
index 8f26f2ecb58..d53082826f4 100644
--- a/bdb/libdb_java/java_DbLsn.c
+++ b/bdb/libdb_java/java_DbLsn.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_DbLsn.c,v 11.5 2000/11/30 00:58:39 ubell Exp $";
+static const char revid[] = "$Id: java_DbLsn.c,v 11.12 2002/05/07 16:12:41 dda Exp $";
#endif /* not lint */
#include <jni.h>
@@ -15,7 +15,6 @@ static const char revid[] = "$Id: java_DbLsn.c,v 11.5 2000/11/30 00:58:39 ubell
#include <string.h>
#include <stdio.h> /* needed for FILENAME_MAX */
-#include "db.h"
#include "db_int.h"
#include "java_util.h"
#include "com_sleepycat_db_DbLsn.h"
@@ -23,8 +22,9 @@ static const char revid[] = "$Id: java_DbLsn.c,v 11.5 2000/11/30 00:58:39 ubell
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLsn_init_1lsn
(JNIEnv *jnienv, /*DbLsn*/ jobject jthis)
{
- /* Note: the DB_LSN object stored in the private_dbobj_
- * is allocated in get_DbLsn().
+ /*
+ * Note: the DB_LSN object stored in the private_dbobj_
+ * is allocated in get_DbLsn() or get_DB_LSN().
*/
COMPQUIET(jnienv, NULL);
@@ -38,6 +38,6 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLsn_finalize
dblsn = get_DB_LSN(jnienv, jthis);
if (dblsn) {
- free(dblsn);
+ (void)__os_free(NULL, dblsn);
}
}
diff --git a/bdb/libdb_java/java_DbTxn.c b/bdb/libdb_java/java_DbTxn.c
index 67c2599a6fc..51195501b77 100644
--- a/bdb/libdb_java/java_DbTxn.c
+++ b/bdb/libdb_java/java_DbTxn.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_DbTxn.c,v 11.3 2000/09/18 18:32:25 dda Exp $";
+static const char revid[] = "$Id: java_DbTxn.c,v 11.16 2002/08/06 05:19:05 bostic Exp $";
#endif /* not lint */
#include <jni.h>
@@ -15,33 +15,16 @@ static const char revid[] = "$Id: java_DbTxn.c,v 11.3 2000/09/18 18:32:25 dda Ex
#include <stdlib.h>
#include <string.h>
-#include "db.h"
+#include "db_int.h"
#include "java_util.h"
#include "com_sleepycat_db_DbTxn.h"
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_abort
- (JNIEnv *jnienv, jobject jthis)
-{
- int err;
- DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis);
- if (!verify_non_null(jnienv, dbtxn))
- return;
-
- err = txn_abort(dbtxn);
- verify_return(jnienv, err, 0);
-}
-
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_commit
- (JNIEnv *jnienv, jobject jthis, jint flags)
-{
- int err;
- DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis);
- if (!verify_non_null(jnienv, dbtxn))
- return;
-
- err = txn_commit(dbtxn, flags);
- verify_return(jnienv, err, 0);
-}
+JAVADB_METHOD(DbTxn_abort, (JAVADB_ARGS), DB_TXN,
+ abort, (c_this))
+JAVADB_METHOD(DbTxn_commit, (JAVADB_ARGS, jint flags), DB_TXN,
+ commit, (c_this, flags))
+JAVADB_METHOD(DbTxn_discard, (JAVADB_ARGS, jint flags), DB_TXN,
+ discard, (c_this, flags))
JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbTxn_id
(JNIEnv *jnienv, jobject jthis)
@@ -51,32 +34,34 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbTxn_id
if (!verify_non_null(jnienv, dbtxn))
return (-1);
- /* No error to check for from txn_id */
- retval = txn_id(dbtxn);
+ /* No error to check for from DB_TXN->id */
+ retval = dbtxn->id(dbtxn);
return (retval);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_prepare
- (JNIEnv *jnienv, jobject jthis)
+ (JNIEnv *jnienv, jobject jthis, jbyteArray gid)
{
int err;
- DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis);
+ DB_TXN *dbtxn;
+ jbyte *c_array;
+
+ dbtxn = get_DB_TXN(jnienv, jthis);
if (!verify_non_null(jnienv, dbtxn))
return;
- err = txn_prepare(dbtxn);
+ if (gid == NULL ||
+ (*jnienv)->GetArrayLength(jnienv, gid) < DB_XIDDATASIZE) {
+ report_exception(jnienv, "DbTxn.prepare gid array "
+ "must be >= 128 bytes", EINVAL, 0);
+ return;
+ }
+ c_array = (*jnienv)->GetByteArrayElements(jnienv, gid, NULL);
+ err = dbtxn->prepare(dbtxn, (u_int8_t *)c_array);
+ (*jnienv)->ReleaseByteArrayElements(jnienv, gid, c_array, 0);
verify_return(jnienv, err, 0);
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_finalize
- (JNIEnv *jnienv, jobject jthis)
-{
- DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis);
- if (dbtxn) {
- /* Free any data related to DB_TXN here
- * Note: we don't make a policy of doing
- * a commit or abort here. The txnmgr
- * should be closed, and DB will clean up.
- */
- }
-}
+JAVADB_METHOD(DbTxn_set_1timeout,
+ (JAVADB_ARGS, jlong timeout, jint flags), DB_TXN,
+ set_timeout, (c_this, (u_int32_t)timeout, flags))
diff --git a/bdb/libdb_java/java_DbUtil.c b/bdb/libdb_java/java_DbUtil.c
new file mode 100644
index 00000000000..edcbc6d9f15
--- /dev/null
+++ b/bdb/libdb_java/java_DbUtil.c
@@ -0,0 +1,27 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: java_DbUtil.c,v 1.5 2002/01/11 15:52:44 bostic Exp $";
+#endif /* not lint */
+
+#include <jni.h>
+
+#include "db_int.h"
+#include "java_util.h"
+#include "com_sleepycat_db_DbUtil.h"
+
+JNIEXPORT jboolean JNICALL
+Java_com_sleepycat_db_DbUtil_is_1big_1endian (JNIEnv *jnienv,
+ jclass jthis_class)
+{
+ COMPQUIET(jnienv, NULL);
+ COMPQUIET(jthis_class, NULL);
+
+ return (__db_isbigendian() ? JNI_TRUE : JNI_FALSE);
+}
diff --git a/bdb/libdb_java/java_DbXAResource.c b/bdb/libdb_java/java_DbXAResource.c
new file mode 100644
index 00000000000..609529bfe83
--- /dev/null
+++ b/bdb/libdb_java/java_DbXAResource.c
@@ -0,0 +1,288 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2001
+ * Sleepycat Software. All rights reserved.
+ */
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: java_DbXAResource.c,v 11.6 2002/08/06 05:19:06 bostic Exp $";
+#endif /* not lint */
+
+#include <jni.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef DIAGNOSTIC
+#include <stdio.h>
+#endif
+
+#include "db_int.h"
+#include "java_util.h"
+#include "dbinc/xa.h"
+#include "dbinc_auto/xa_ext.h"
+#include "com_sleepycat_db_xa_DbXAResource.h"
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1init
+ (JNIEnv *jnienv, jobject jthis, jstring home, jint rmid, jint flags)
+{
+ int err;
+ LOCKED_STRING ls_home;
+ jclass cl;
+ jmethodID mid;
+
+ COMPQUIET(jthis, NULL);
+ if (locked_string_get(&ls_home, jnienv, home) != 0)
+ goto out;
+ if ((err = __db_xa_open((char *)ls_home.string,
+ rmid, flags)) != XA_OK) {
+ verify_return(jnienv, err, EXCEPTION_XA);
+ }
+
+ /*
+ * Now create the DbEnv object, it will get attached
+ * to the DB_ENV just made in __db_xa_open.
+ */
+ if ((cl = get_class(jnienv, name_DB_ENV)) == NULL)
+ goto out;
+
+ mid = (*jnienv)->GetStaticMethodID(jnienv, cl,
+ "_create_DbEnv_for_XA", "(II)V");
+ (*jnienv)->CallStaticVoidMethod(jnienv, cl, mid, 0, rmid);
+
+ out:
+ locked_string_put(&ls_home, jnienv);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1close
+ (JNIEnv *jnienv, jobject jthis, jstring home, jint rmid, jint flags)
+{
+ int err;
+ LOCKED_STRING ls_home;
+
+ COMPQUIET(jthis, NULL);
+ if (locked_string_get(&ls_home, jnienv, home) != 0)
+ goto out;
+ if ((err = __db_xa_close((char *)ls_home.string,
+ rmid, flags)) != XA_OK)
+ verify_return(jnienv, err, EXCEPTION_XA);
+ out:
+ locked_string_put(&ls_home, jnienv);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1commit
+ (JNIEnv *jnienv, jobject jthis, jobject jxid, jint rmid,
+ jboolean onePhase)
+{
+ XID xid;
+ long flags;
+ int err;
+
+ COMPQUIET(jthis, NULL);
+ if (!get_XID(jnienv, jxid, &xid))
+ return;
+ flags = 0;
+ if (onePhase == JNI_TRUE)
+ flags |= TMONEPHASE;
+ if ((err = __db_xa_commit(&xid, rmid, flags)) != XA_OK)
+ verify_return(jnienv, err, EXCEPTION_XA);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1end
+ (JNIEnv *jnienv, jobject jthis, jobject jxid, jint rmid, jint flags)
+{
+ XID xid;
+ int err;
+
+ COMPQUIET(jthis, NULL);
+ if (!get_XID(jnienv, jxid, &xid))
+ return;
+ if ((err = __db_xa_end(&xid, rmid, flags)) != XA_OK)
+ verify_return(jnienv, err, EXCEPTION_XA);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1forget
+ (JNIEnv *jnienv, jobject jthis, jobject jxid, jint rmid)
+{
+ XID xid;
+ int err;
+
+ COMPQUIET(jthis, NULL);
+ if (!get_XID(jnienv, jxid, &xid))
+ return;
+ if ((err = __db_xa_forget(&xid, rmid, 0)) != XA_OK)
+ verify_return(jnienv, err, EXCEPTION_XA);
+}
+
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_xa_DbXAResource__1prepare
+ (JNIEnv *jnienv, jobject jthis, jobject jxid, jint rmid)
+{
+ XID xid;
+ int err;
+
+ COMPQUIET(jthis, NULL);
+ if (!get_XID(jnienv, jxid, &xid))
+ return (0);
+ err = __db_xa_prepare(&xid, rmid, 0);
+ if (err != XA_OK && err != XA_RDONLY)
+ verify_return(jnienv, err, EXCEPTION_XA);
+
+ return (err);
+}
+
+JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_xa_DbXAResource__1recover
+ (JNIEnv *jnienv, jobject jthis, jint rmid, jint flags)
+{
+ XID *xids;
+ int err;
+ int total;
+ int cnt;
+ int i;
+ int curflags;
+ size_t nbytes;
+ jclass xid_class;
+ jmethodID mid;
+ jobject obj;
+ jobjectArray retval;
+
+ COMPQUIET(jthis, NULL);
+ total = 0;
+ cnt = 0;
+ xids = NULL;
+ flags &= ~(DB_FIRST | DB_LAST | DB_NEXT);
+
+ /* Repeatedly call __db_xa_recover to fill up an array of XIDs */
+ curflags = flags | DB_FIRST;
+ do {
+ total += cnt;
+ nbytes = sizeof(XID) * (total + 10);
+ if ((err = __os_realloc(NULL, nbytes, &xids)) != 0) {
+ if (xids != NULL)
+ __os_free(NULL, xids);
+ verify_return(jnienv, XAER_NOTA, EXCEPTION_XA);
+ return (NULL);
+ }
+ cnt = __db_xa_recover(&xids[total], 10, rmid, curflags);
+ curflags = flags | DB_NEXT;
+ } while (cnt > 0);
+
+ if (xids != NULL)
+ __os_free(NULL, xids);
+
+ if (cnt < 0) {
+ verify_return(jnienv, cnt, EXCEPTION_XA);
+ return (NULL);
+ }
+
+ /* Create the java DbXid array and fill it up */
+ if ((xid_class = get_class(jnienv, name_DB_XID)) == NULL)
+ return (NULL);
+ mid = (*jnienv)->GetMethodID(jnienv, xid_class, "<init>",
+ "(I[B[B)V");
+ if ((retval = (*jnienv)->NewObjectArray(jnienv, total, xid_class, 0))
+ == NULL)
+ goto out;
+
+ for (i = 0; i < total; i++) {
+ jobject gtrid;
+ jobject bqual;
+ jsize gtrid_len;
+ jsize bqual_len;
+
+ gtrid_len = (jsize)xids[i].gtrid_length;
+ bqual_len = (jsize)xids[i].bqual_length;
+ gtrid = (*jnienv)->NewByteArray(jnienv, gtrid_len);
+ bqual = (*jnienv)->NewByteArray(jnienv, bqual_len);
+ if (gtrid == NULL || bqual == NULL)
+ goto out;
+ (*jnienv)->SetByteArrayRegion(jnienv, gtrid, 0, gtrid_len,
+ (jbyte *)&xids[i].data[0]);
+ (*jnienv)->SetByteArrayRegion(jnienv, bqual, 0, bqual_len,
+ (jbyte *)&xids[i].data[gtrid_len]);
+ if ((obj = (*jnienv)->NewObject(jnienv, xid_class, mid,
+ (jint)xids[i].formatID, gtrid, bqual)) == NULL)
+ goto out;
+ (*jnienv)->SetObjectArrayElement(jnienv, retval, i, obj);
+ }
+out: return (retval);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1rollback
+ (JNIEnv *jnienv, jobject jthis, jobject jxid, jint rmid)
+{
+ XID xid;
+ int err;
+
+ COMPQUIET(jthis, NULL);
+ if (!get_XID(jnienv, jxid, &xid))
+ return;
+ if ((err = __db_xa_rollback(&xid, rmid, 0)) != XA_OK)
+ verify_return(jnienv, err, EXCEPTION_XA);
+}
+
+JNIEXPORT void JNICALL Java_com_sleepycat_db_xa_DbXAResource__1start
+ (JNIEnv *jnienv, jobject jthis, jobject jxid, jint rmid, jint flags)
+{
+ XID xid;
+ int err;
+
+ COMPQUIET(jthis, NULL);
+ if (!get_XID(jnienv, jxid, &xid))
+ return;
+
+ if ((err = __db_xa_start(&xid, rmid, flags)) != XA_OK)
+ verify_return(jnienv, err, EXCEPTION_XA);
+}
+
+JNIEXPORT jobject JNICALL Java_com_sleepycat_db_xa_DbXAResource_xa_1attach
+ (JNIEnv *jnienv, jclass jthisclass, jobject jxid, jobject jrmid)
+{
+ XID xid;
+ XID *xidp;
+ int ret;
+ DB_ENV *env;
+ DB_TXN *txn;
+ int rmid;
+ int *rmidp;
+ jobject jtxn;
+ jobject jenv;
+ jclass cl;
+ jmethodID mid;
+
+ COMPQUIET(jthisclass, NULL);
+ if (jxid == NULL) {
+ xidp = NULL;
+ }
+ else {
+ xidp = &xid;
+ if (!get_XID(jnienv, jxid, &xid))
+ return (NULL);
+ }
+ if (jrmid == NULL) {
+ rmidp = NULL;
+ }
+ else {
+ rmidp = &rmid;
+ rmid = (int)(*jnienv)->CallIntMethod(jnienv, jrmid,
+ mid_Integer_intValue);
+ }
+
+ if ((ret = db_env_xa_attach(rmidp, xidp, &env, &txn)) != 0) {
+ /*
+ * DB_NOTFOUND is a normal return, it means we
+ * have no current transaction,
+ */
+ if (ret != DB_NOTFOUND)
+ verify_return(jnienv, ret, 0);
+ return (NULL);
+ }
+
+ jenv = ((DB_ENV_JAVAINFO *)env->api2_internal)->jenvref;
+ jtxn = get_DbTxn(jnienv, txn);
+ if ((cl = get_class(jnienv, name_DB_XAATTACH)) == NULL)
+ return (NULL);
+ mid = (*jnienv)->GetMethodID(jnienv, cl, "<init>",
+ "(Lcom/sleepycat/db/DbEnv;Lcom/sleepycat/db/DbTxn;)V");
+ return (*jnienv)->NewObject(jnienv, cl, mid, jenv, jtxn);
+}
diff --git a/bdb/libdb_java/java_Dbc.c b/bdb/libdb_java/java_Dbc.c
index f1d0acdec85..63ab368fc03 100644
--- a/bdb/libdb_java/java_Dbc.c
+++ b/bdb/libdb_java/java_Dbc.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_Dbc.c,v 11.10 2000/10/25 19:54:55 dda Exp $";
+static const char revid[] = "$Id: java_Dbc.c,v 11.23 2002/08/06 05:19:06 bostic Exp $";
#endif /* not lint */
#include <jni.h>
@@ -18,7 +18,6 @@ static const char revid[] = "$Id: java_Dbc.c,v 11.10 2000/10/25 19:54:55 dda Exp
#include <stdio.h>
#endif
-#include "db.h"
#include "db_int.h"
#include "java_util.h"
#include "com_sleepycat_db_Dbc.h"
@@ -51,20 +50,8 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_count
return (count);
}
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_del
- (JNIEnv *jnienv, jobject jthis, jint flags)
-{
- int err;
- DBC *dbc = get_DBC(jnienv, jthis);
-
- if (!verify_non_null(jnienv, dbc))
- return (0);
- err = dbc->c_del(dbc, flags);
- if (err != DB_KEYEMPTY) {
- verify_return(jnienv, err, 0);
- }
- return (err);
-}
+JAVADB_METHOD_INT(Dbc_del, (JAVADB_ARGS, jint flags), DBC,
+ c_del, (c_this, flags), DB_RETOK_DBCDEL)
JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Dbc_dup
(JNIEnv *jnienv, jobject jthis, jint flags)
@@ -88,10 +75,12 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_get
{
int err, retry, op_flags;
DBC *dbc;
- JDBT dbkey, dbdata;
+ DB_ENV *dbenv;
+ LOCKED_DBT lkey, ldata;
OpKind keyop, dataop;
- /* Depending on flags, the user may be supplying the key,
+ /*
+ * Depending on flags, the user may be supplying the key,
* or else we may have to retrieve it.
*/
err = 0;
@@ -106,38 +95,124 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_get
op_flags == DB_SET_RECNO) {
keyop = inOutOp;
}
- else if (op_flags == DB_GET_BOTH) {
+ else if (op_flags == DB_GET_BOTH || op_flags == DB_GET_BOTH_RANGE) {
keyop = inOutOp;
dataop = inOutOp;
}
dbc = get_DBC(jnienv, jthis);
- if (jdbt_lock(&dbkey, jnienv, key, keyop) != 0)
+ if (!verify_non_null(jnienv, dbc))
+ return (0);
+ dbenv = dbc->dbp->dbenv;
+
+ if (locked_dbt_get(&lkey, jnienv, dbenv, key, keyop) != 0)
goto out2;
- if (jdbt_lock(&dbdata, jnienv, data, dataop) != 0)
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, dataop) != 0)
goto out1;
if (!verify_non_null(jnienv, dbc))
goto out1;
for (retry = 0; retry < 3; retry++) {
- err = dbc->c_get(dbc, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags);
+ err = dbc->c_get(dbc,
+ &lkey.javainfo->dbt, &ldata.javainfo->dbt, flags);
- /* If we failed due to lack of memory in our DBT arrays,
+ /*
+ * If we failed due to lack of memory in our DBT arrays,
* retry.
*/
if (err != ENOMEM)
break;
- if (!jdbt_realloc(&dbkey, jnienv) && !jdbt_realloc(&dbdata, jnienv))
+ if (!locked_dbt_realloc(&lkey, jnienv,
+ dbenv) && !locked_dbt_realloc(&ldata, jnienv, dbenv))
break;
}
- if (err != DB_NOTFOUND) {
- verify_return(jnienv, err, 0);
+ out1:
+ locked_dbt_put(&ldata, jnienv, dbenv);
+ out2:
+ locked_dbt_put(&lkey, jnienv, dbenv);
+ if (!DB_RETOK_DBCGET(err)) {
+ if (verify_dbt(jnienv, err, &lkey) &&
+ verify_dbt(jnienv, err, &ldata))
+ verify_return(jnienv, err, 0);
+ }
+ return (err);
+}
+
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_pget
+ (JNIEnv *jnienv, jobject jthis,
+ /*Dbt*/ jobject key, /*Dbt*/ jobject pkey, /*Dbt*/ jobject data, jint flags)
+{
+ int err, retry, op_flags;
+ DBC *dbc;
+ DB_ENV *dbenv;
+ LOCKED_DBT lkey, lpkey, ldata;
+ OpKind keyop, pkeyop, dataop;
+
+ /*
+ * Depending on flags, the user may be supplying the key,
+ * or else we may have to retrieve it.
+ */
+ err = 0;
+ keyop = outOp;
+ pkeyop = outOp;
+ dataop = outOp;
+
+ op_flags = flags & DB_OPFLAGS_MASK;
+ if (op_flags == DB_SET) {
+ keyop = inOp;
+ }
+ else if (op_flags == DB_SET_RANGE ||
+ op_flags == DB_SET_RECNO) {
+ keyop = inOutOp;
+ }
+ else if (op_flags == DB_GET_BOTH || op_flags == DB_GET_BOTH_RANGE) {
+ pkeyop = inOutOp;
+ keyop = inOutOp;
+ dataop = inOutOp;
+ }
+
+ dbc = get_DBC(jnienv, jthis);
+ if (!verify_non_null(jnienv, dbc))
+ return (0);
+ dbenv = dbc->dbp->dbenv;
+ if (locked_dbt_get(&lkey, jnienv, dbenv, key, keyop) != 0)
+ goto out3;
+ if (locked_dbt_get(&lpkey, jnienv, dbenv, pkey, pkeyop) != 0)
+ goto out2;
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, dataop) != 0)
+ goto out1;
+
+ if (!verify_non_null(jnienv, dbc))
+ goto out1;
+
+ for (retry = 0; retry < 3; retry++) {
+ err = dbc->c_pget(dbc, &lkey.javainfo->dbt,
+ &lpkey.javainfo->dbt, &ldata.javainfo->dbt, flags);
+
+ /*
+ * If we failed due to lack of memory in our DBT arrays,
+ * retry.
+ */
+ if (err != ENOMEM)
+ break;
+ if (!locked_dbt_realloc(&lkey, jnienv, dbenv) &&
+ !locked_dbt_realloc(&lpkey, jnienv, dbenv) &&
+ !locked_dbt_realloc(&ldata, jnienv, dbenv))
+ break;
}
out1:
- jdbt_unlock(&dbdata, jnienv);
+ locked_dbt_put(&ldata, jnienv, dbenv);
out2:
- jdbt_unlock(&dbkey, jnienv);
+ locked_dbt_put(&lpkey, jnienv, dbenv);
+ out3:
+ locked_dbt_put(&lkey, jnienv, dbenv);
+ if (!DB_RETOK_DBCGET(err)) {
+ if (verify_dbt(jnienv, err, &lkey) &&
+ verify_dbt(jnienv, err, &lpkey) &&
+ verify_dbt(jnienv, err, &ldata))
+ verify_return(jnienv, err, 0);
+ }
return (err);
}
@@ -147,32 +222,39 @@ JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_put
{
int err;
DBC *dbc;
- JDBT dbkey, dbdata;
+ DB_ENV *dbenv;
+ LOCKED_DBT lkey, ldata;
+ OpKind keyop;
err = 0;
dbc = get_DBC(jnienv, jthis);
- if (jdbt_lock(&dbkey, jnienv, key, inOp) != 0)
+ if (!verify_non_null(jnienv, dbc))
+ return (0);
+ dbenv = dbc->dbp->dbenv;
+ keyop = (dbc->dbp->type == DB_RECNO &&
+ (flags == DB_BEFORE || flags == DB_AFTER)) ? outOp : inOp;
+ if (locked_dbt_get(&lkey, jnienv, dbenv, key, keyop) != 0)
goto out2;
- if (jdbt_lock(&dbdata, jnienv, data, inOp) != 0)
+ if (locked_dbt_get(&ldata, jnienv, dbenv, data, inOp) != 0)
goto out1;
if (!verify_non_null(jnienv, dbc))
goto out1;
- err = dbc->c_put(dbc, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags);
- if (err != DB_KEYEXIST) {
+ err = dbc->c_put(dbc, &lkey.javainfo->dbt, &ldata.javainfo->dbt, flags);
+ if (!DB_RETOK_DBCPUT(err))
verify_return(jnienv, err, 0);
- }
out1:
- jdbt_unlock(&dbdata, jnienv);
+ locked_dbt_put(&ldata, jnienv, dbenv);
out2:
- jdbt_unlock(&dbkey, jnienv);
+ locked_dbt_put(&lkey, jnienv, dbenv);
return (err);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbc_finalize
(JNIEnv *jnienv, jobject jthis)
{
- /* Free any data related to DBC here.
+ /*
+ * Free any data related to DBC here.
* If we ever have java-only data embedded in the DBC
* and need to do this, we'll have to track Dbc's
* according to which Db owns them, just as
diff --git a/bdb/libdb_java/java_Dbt.c b/bdb/libdb_java/java_Dbt.c
index 0e094da6a2d..d21109f3408 100644
--- a/bdb/libdb_java/java_Dbt.c
+++ b/bdb/libdb_java/java_Dbt.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_Dbt.c,v 11.10 2000/10/25 19:54:55 dda Exp $";
+static const char revid[] = "$Id: java_Dbt.c,v 11.18 2002/06/20 11:11:55 mjc Exp $";
#endif /* not lint */
#include <jni.h>
@@ -15,16 +15,10 @@ static const char revid[] = "$Id: java_Dbt.c,v 11.10 2000/10/25 19:54:55 dda Exp
#include <stdlib.h>
#include <string.h>
-#include "db.h"
+#include "db_int.h"
#include "java_util.h"
#include "com_sleepycat_db_Dbt.h"
-JAVADB_RW_ACCESS(Dbt, jint, size, DBT, size)
-JAVADB_RW_ACCESS(Dbt, jint, ulen, DBT, ulen)
-JAVADB_RW_ACCESS(Dbt, jint, dlen, DBT, dlen)
-JAVADB_RW_ACCESS(Dbt, jint, doff, DBT, doff)
-JAVADB_RW_ACCESS(Dbt, jint, flags, DBT, flags)
-
JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_init
(JNIEnv *jnienv, jobject jthis)
{
@@ -34,129 +28,22 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_init
set_private_dbobj(jnienv, name_DBT, jthis, dbtji);
}
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_internal_1set_1data
- (JNIEnv *jnienv, jobject jthis, jbyteArray array)
-{
- DBT_JAVAINFO *db_this;
-
- db_this = get_DBT_JAVAINFO(jnienv, jthis);
- if (verify_non_null(jnienv, db_this)) {
-
- /* If we previously allocated an array for java,
- * must release reference.
- */
- dbjit_release(db_this, jnienv);
-
- /* Make the array a global ref,
- * it won't be GC'd till we release it.
- */
- if (array)
- array = (jbyteArray)NEW_GLOBAL_REF(jnienv, array);
- db_this->array_ = array;
- }
-}
-
-JNIEXPORT jbyteArray JNICALL Java_com_sleepycat_db_Dbt_get_1data
+JNIEXPORT jbyteArray JNICALL Java_com_sleepycat_db_Dbt_create_1data
(JNIEnv *jnienv, jobject jthis)
{
DBT_JAVAINFO *db_this;
- jbyteArray arr;
+ jbyteArray arr = NULL;
int len;
db_this = get_DBT_JAVAINFO(jnienv, jthis);
if (verify_non_null(jnienv, db_this)) {
- /* XXX this will copy the data on each call to get_data,
- * even if it is unchanged.
- */
- if (db_this->create_array_ != 0) {
- /* XXX we should reuse the existing array if we can */
- len = db_this->dbt.size;
- if (db_this->array_ != NULL)
- DELETE_GLOBAL_REF(jnienv, db_this->array_);
- arr = (*jnienv)->NewByteArray(jnienv, len);
- db_this->array_ =
- (jbyteArray)NEW_GLOBAL_REF(jnienv, arr);
- (*jnienv)->SetByteArrayRegion(jnienv, arr, 0, len,
- db_this->dbt.data);
- }
- return (db_this->array_);
- }
- return (0);
-}
-
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1offset
- (JNIEnv *jnienv, jobject jthis, jint offset)
-{
- DBT_JAVAINFO *db_this;
-
- db_this = get_DBT_JAVAINFO(jnienv, jthis);
- if (verify_non_null(jnienv, db_this)) {
- db_this->offset_ = offset;
- }
-}
-
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1offset
- (JNIEnv *jnienv, jobject jthis)
-{
- DBT_JAVAINFO *db_this;
-
- db_this = get_DBT_JAVAINFO(jnienv, jthis);
- if (verify_non_null(jnienv, db_this)) {
- return db_this->offset_;
- }
- return (0);
-}
-
-JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1recno_1key_1data(JNIEnv *jnienv, jobject jthis, jint value)
-{
- JDBT jdbt;
-
- if (jdbt_lock(&jdbt, jnienv, jthis, inOp) != 0)
- goto out;
-
- if (!jdbt.dbt->dbt.data ||
- jdbt.java_array_len_ < sizeof(db_recno_t)) {
- char buf[200];
- sprintf(buf, "set_recno_key_data error: %p %p %d %d",
- &jdbt.dbt->dbt, jdbt.dbt->dbt.data,
- jdbt.dbt->dbt.ulen, sizeof(db_recno_t));
- report_exception(jnienv, buf, 0, 0);
- }
- else {
- *(db_recno_t*)(jdbt.dbt->dbt.data) = value;
+ len = db_this->dbt.size;
+ if ((arr = (*jnienv)->NewByteArray(jnienv, len)) == NULL)
+ goto out;
+ (*jnienv)->SetByteArrayRegion(jnienv, arr, 0, len,
+ db_this->dbt.data);
}
- out:
- jdbt_unlock(&jdbt, jnienv);
-}
-
-JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1recno_1key_1data(JNIEnv *jnienv, jobject jthis)
-{
- jint ret;
- JDBT jdbt;
-
- ret = 0;
-
- /* Although this is kind of like "retrieve", we don't support
- * DB_DBT_MALLOC for this operation, so we tell jdbt_lock
- * that is not a retrieve.
- */
- if (jdbt_lock(&jdbt, jnienv, jthis, inOp) != 0)
- goto out;
-
- if (!jdbt.dbt->dbt.data ||
- jdbt.java_array_len_ < sizeof(db_recno_t)) {
- char buf[200];
- sprintf(buf, "get_recno_key_data error: %p %p %d %d",
- &jdbt.dbt->dbt, jdbt.dbt->dbt.data,
- jdbt.dbt->dbt.ulen, sizeof(db_recno_t));
- report_exception(jnienv, buf, 0, 0);
- }
- else {
- ret = *(db_recno_t*)(jdbt.dbt->dbt.data);
- }
- out:
- jdbt_unlock(&jdbt, jnienv);
- return (ret);
+out: return (arr);
}
JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_finalize
@@ -167,10 +54,6 @@ JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_finalize
dbtji = get_DBT_JAVAINFO(jnienv, jthis);
if (dbtji) {
/* Free any data related to DBT here */
- dbjit_release(dbtji, jnienv);
-
- /* Extra paranoia */
- memset(dbtji, 0, sizeof(DBT_JAVAINFO));
- free(dbtji);
+ dbjit_destroy(dbtji);
}
}
diff --git a/bdb/libdb_java/java_info.c b/bdb/libdb_java/java_info.c
index ccd469fa256..22fcbd23d46 100644
--- a/bdb/libdb_java/java_info.c
+++ b/bdb/libdb_java/java_info.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_info.c,v 11.18 2000/10/28 13:09:39 dda Exp $";
+static const char revid[] = "$Id: java_info.c,v 11.46 2002/08/29 14:22:23 margo Exp $";
#endif /* not lint */
#include <jni.h>
@@ -15,63 +15,74 @@ static const char revid[] = "$Id: java_info.c,v 11.18 2000/10/28 13:09:39 dda Ex
#include <stdlib.h>
#include <string.h>
-#include "db.h"
#include "db_int.h"
#include "java_util.h"
/****************************************************************
*
* Callback functions
- *
*/
+static int Db_assoc_callback(DB *db,
+ const DBT *key,
+ const DBT *data,
+ DBT *retval)
+{
+ DB_JAVAINFO *dbinfo;
+
+ DB_ASSERT(db != NULL);
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ return (dbji_call_assoc(dbinfo, db, dbinfo->jdbref,
+ key, data, retval));
+}
+
static void Db_feedback_callback(DB *db, int opcode, int percent)
{
DB_JAVAINFO *dbinfo;
DB_ASSERT(db != NULL);
- dbinfo = (DB_JAVAINFO *)db->cj_internal;
- dbji_call_feedback(dbinfo, db, dbinfo->jdbref_, opcode, percent);
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ dbji_call_feedback(dbinfo, db, dbinfo->jdbref, opcode, percent);
}
static int Db_append_recno_callback(DB *db, DBT *dbt, db_recno_t recno)
{
DB_JAVAINFO *dbinfo;
- dbinfo = (DB_JAVAINFO *)db->cj_internal;
- return (dbji_call_append_recno(dbinfo, db, dbinfo->jdbref_, dbt, recno));
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ return (dbji_call_append_recno(dbinfo, db, dbinfo->jdbref, dbt, recno));
}
static int Db_bt_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
{
DB_JAVAINFO *dbinfo;
- dbinfo = (DB_JAVAINFO *)db->cj_internal;
- return (dbji_call_bt_compare(dbinfo, db, dbinfo->jdbref_, dbt1, dbt2));
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ return (dbji_call_bt_compare(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
}
static size_t Db_bt_prefix_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
{
DB_JAVAINFO *dbinfo;
- dbinfo = (DB_JAVAINFO *)db->cj_internal;
- return (dbji_call_bt_prefix(dbinfo, db, dbinfo->jdbref_, dbt1, dbt2));
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ return (dbji_call_bt_prefix(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
}
static int Db_dup_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
{
DB_JAVAINFO *dbinfo;
- dbinfo = (DB_JAVAINFO *)db->cj_internal;
- return (dbji_call_dup_compare(dbinfo, db, dbinfo->jdbref_, dbt1, dbt2));
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ return (dbji_call_dup_compare(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
}
static u_int32_t Db_h_hash_callback(DB *db, const void *data, u_int32_t len)
{
DB_JAVAINFO *dbinfo;
- dbinfo = (DB_JAVAINFO *)db->cj_internal;
- return (dbji_call_h_hash(dbinfo, db, dbinfo->jdbref_, data, len));
+ dbinfo = (DB_JAVAINFO *)db->api_internal;
+ return (dbji_call_h_hash(dbinfo, db, dbinfo->jdbref, data, len));
}
static void DbEnv_feedback_callback(DB_ENV *dbenv, int opcode, int percent)
@@ -79,91 +90,87 @@ static void DbEnv_feedback_callback(DB_ENV *dbenv, int opcode, int percent)
DB_ENV_JAVAINFO *dbinfo;
DB_ASSERT(dbenv != NULL);
- dbinfo = (DB_ENV_JAVAINFO *)dbenv->cj_internal;
- dbjie_call_feedback(dbinfo, dbenv, dbinfo->jenvref_, opcode, percent);
+ dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
+ dbjie_call_feedback(dbinfo, dbenv, dbinfo->jenvref, opcode, percent);
}
-static int DbEnv_recovery_init_callback(DB_ENV *dbenv)
+static int DbEnv_rep_transport_callback(DB_ENV *dbenv,
+ const DBT *control, const DBT *rec,
+ int envid, u_int32_t flags)
{
DB_ENV_JAVAINFO *dbinfo;
- dbinfo = (DB_ENV_JAVAINFO *)dbenv->cj_internal;
- return (dbjie_call_recovery_init(dbinfo, dbenv, dbinfo->jenvref_));
+ dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
+ return (dbjie_call_rep_transport(dbinfo, dbenv,
+ dbinfo->jenvref, control, rec, envid, (int)flags));
}
-static int DbEnv_tx_recover_callback(DB_ENV *dbenv, DBT *dbt,
+static int DbEnv_app_dispatch_callback(DB_ENV *dbenv, DBT *dbt,
DB_LSN *lsn, db_recops recops)
{
DB_ENV_JAVAINFO *dbinfo;
DB_ASSERT(dbenv != NULL);
- dbinfo = (DB_ENV_JAVAINFO *)dbenv->cj_internal;
- return dbjie_call_tx_recover(dbinfo, dbenv, dbinfo->jenvref_, dbt,
- lsn, recops);
+ dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
+ return (dbjie_call_app_dispatch(dbinfo, dbenv, dbinfo->jenvref, dbt,
+ lsn, recops));
}
/****************************************************************
*
* Implementation of class DBT_javainfo
- *
*/
DBT_JAVAINFO *
dbjit_construct()
{
DBT_JAVAINFO *dbjit;
+ int err;
+
+ /*XXX should return err*/
+ if ((err = __os_malloc(NULL, sizeof(DBT_JAVAINFO), &dbjit)) != 0)
+ return (NULL);
- dbjit = (DBT_JAVAINFO *)malloc(sizeof(DBT_JAVAINFO));
memset(dbjit, 0, sizeof(DBT_JAVAINFO));
return (dbjit);
}
void dbjit_destroy(DBT_JAVAINFO *dbjit)
{
- /* Sanity check:
- * We cannot delete the global ref because we don't have a JNIEnv.
- */
- if (dbjit->array_ != NULL) {
- fprintf(stderr, "object is not freed\n");
- }
-
+ DB_ASSERT(!F_ISSET(dbjit, DBT_JAVAINFO_LOCKED));
/* Extra paranoia */
- memset(dbjit, 0, sizeof(DB_JAVAINFO));
- free(dbjit);
-}
-
-void dbjit_release(DBT_JAVAINFO *dbjit, JNIEnv *jnienv)
-{
- if (dbjit->array_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjit->array_);
- dbjit->array_ = NULL;
- }
+ memset(dbjit, 0, sizeof(DBT_JAVAINFO));
+ (void)__os_free(NULL, dbjit);
}
/****************************************************************
*
* Implementation of class DB_ENV_JAVAINFO
- *
*/
/* create/initialize an object */
DB_ENV_JAVAINFO *
dbjie_construct(JNIEnv *jnienv,
+ jobject jenv,
jobject default_errcall,
int is_dbopen)
{
DB_ENV_JAVAINFO *dbjie;
+ int err;
- dbjie = (DB_ENV_JAVAINFO *)malloc(sizeof(DB_ENV_JAVAINFO));
+ /*XXX should return err*/
+ if ((err = __os_malloc(NULL, sizeof(DB_ENV_JAVAINFO), &dbjie)) != 0)
+ return (NULL);
memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO));
- dbjie->is_dbopen_ = is_dbopen;
+ dbjie->is_dbopen = is_dbopen;
- if ((*jnienv)->GetJavaVM(jnienv, &dbjie->javavm_) != 0) {
- free(dbjie);
+ if ((*jnienv)->GetJavaVM(jnienv, &dbjie->javavm) != 0) {
+ __os_free(NULL, dbjie);
report_exception(jnienv, "cannot get Java VM", 0, 0);
return (NULL);
}
- /* The default error call just prints to the 'System.err'
+ /*
+ * The default error call just prints to the 'System.err'
* stream. If the user does set_errcall to null, we'll
* want to have a reference to set it back to.
*
@@ -172,42 +179,44 @@ dbjie_construct(JNIEnv *jnienv,
* error prefix, error stream, and user's error callback
* that much easier.
*/
- dbjie->default_errcall_ = NEW_GLOBAL_REF(jnienv, default_errcall);
- dbjie->errcall_ = NEW_GLOBAL_REF(jnienv, default_errcall);
+ dbjie->default_errcall = NEW_GLOBAL_REF(jnienv, default_errcall);
+ dbjie->errcall = NEW_GLOBAL_REF(jnienv, default_errcall);
+ dbjie->jenvref = NEW_GLOBAL_REF(jnienv, jenv);
return (dbjie);
}
/* release all objects held by this this one */
void dbjie_dealloc(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
{
- if (dbjie->recovery_init_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->recovery_init_);
- dbjie->recovery_init_ = NULL;
+ if (dbjie->feedback != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->feedback);
+ dbjie->feedback = NULL;
}
- if (dbjie->feedback_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->feedback_);
- dbjie->feedback_ = NULL;
+ if (dbjie->app_dispatch != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->app_dispatch);
+ dbjie->app_dispatch = NULL;
}
- if (dbjie->tx_recover_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->tx_recover_);
- dbjie->tx_recover_ = NULL;
+ if (dbjie->errcall != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->errcall);
+ dbjie->errcall = NULL;
}
- if (dbjie->errcall_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->errcall_);
- dbjie->errcall_ = NULL;
+ if (dbjie->default_errcall != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->default_errcall);
+ dbjie->default_errcall = NULL;
}
- if (dbjie->default_errcall_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->default_errcall_);
- dbjie->default_errcall_ = NULL;
+ if (dbjie->jenvref != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->jenvref);
+ dbjie->jenvref = NULL;
}
- if (dbjie->conflict_ != NULL) {
- free(dbjie->conflict_);
- dbjie->conflict_ = NULL;
+ if (dbjie->conflict != NULL) {
+ __os_free(NULL, dbjie->conflict);
+ dbjie->conflict = NULL;
+ dbjie->conflict_size = 0;
}
- if (dbjie->errpfx_ != NULL) {
- free(dbjie->errpfx_);
- dbjie->errpfx_ = NULL;
+ if (dbjie->errpfx != NULL) {
+ __os_free(NULL, dbjie->errpfx);
+ dbjie->errpfx = NULL;
}
}
@@ -218,17 +227,19 @@ void dbjie_destroy(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
/* Extra paranoia */
memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO));
- free(dbjie);
+ (void)__os_free(NULL, dbjie);
}
-/* Attach to the current thread that is running and
+/*
+ * Attach to the current thread that is running and
* return that. We use the java virtual machine
* that we saved in the constructor.
*/
JNIEnv *
dbjie_get_jnienv(DB_ENV_JAVAINFO *dbjie)
{
- /* Note:
+ /*
+ * Note:
* Different versions of the JNI disagree on the signature
* for AttachCurrentThread. The most recent documentation
* seems to say that (JNIEnv **) is correct, but newer
@@ -240,10 +251,12 @@ dbjie_get_jnienv(DB_ENV_JAVAINFO *dbjie)
JNIEnv *attachret = 0;
#endif
- /* This should always succeed, as we are called via
+ /*
+ * This should always succeed, as we are called via
* some Java activity. I think therefore I am (a thread).
*/
- if ((*dbjie->javavm_)->AttachCurrentThread(dbjie->javavm_, &attachret, 0) != 0)
+ if ((*dbjie->javavm)->AttachCurrentThread(dbjie->javavm, &attachret, 0)
+ != 0)
return (0);
return ((JNIEnv *)attachret);
@@ -252,40 +265,42 @@ dbjie_get_jnienv(DB_ENV_JAVAINFO *dbjie)
jstring
dbjie_get_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
{
- return (get_java_string(jnienv, dbjie->errpfx_));
+ return (get_java_string(jnienv, dbjie->errpfx));
}
void
dbjie_set_errcall(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jobject new_errcall)
{
- /* If the new_errcall is null, we'll set the error call
+ /*
+ * If the new_errcall is null, we'll set the error call
* to the default one.
*/
if (new_errcall == NULL)
- new_errcall = dbjie->default_errcall_;
+ new_errcall = dbjie->default_errcall;
- DELETE_GLOBAL_REF(jnienv, dbjie->errcall_);
- dbjie->errcall_ = NEW_GLOBAL_REF(jnienv, new_errcall);
+ DELETE_GLOBAL_REF(jnienv, dbjie->errcall);
+ dbjie->errcall = NEW_GLOBAL_REF(jnienv, new_errcall);
}
void
dbjie_set_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jstring errpfx)
{
- if (dbjie->errpfx_ != NULL)
- free(dbjie->errpfx_);
+ if (dbjie->errpfx != NULL)
+ __os_free(NULL, dbjie->errpfx);
if (errpfx)
- dbjie->errpfx_ = get_c_string(jnienv, errpfx);
+ dbjie->errpfx = get_c_string(jnienv, errpfx);
else
- dbjie->errpfx_ = NULL;
+ dbjie->errpfx = NULL;
}
void
-dbjie_set_conflict(DB_ENV_JAVAINFO *dbjie, unsigned char *newarr)
+dbjie_set_conflict(DB_ENV_JAVAINFO *dbjie, u_char *newarr, size_t size)
{
- if (dbjie->conflict_)
- free(dbjie->conflict_);
- dbjie->conflict_ = newarr;
+ if (dbjie->conflict != NULL)
+ (void)__os_free(NULL, dbjie->conflict);
+ dbjie->conflict = newarr;
+ dbjie->conflict_size = size;
}
void dbjie_set_feedback_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
@@ -293,8 +308,8 @@ void dbjie_set_feedback_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
{
int err;
- if (dbjie->feedback_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->feedback_);
+ if (dbjie->feedback != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->feedback);
}
if (jfeedback == NULL) {
if ((err = dbenv->set_feedback(dbenv, NULL)) != 0)
@@ -308,7 +323,7 @@ void dbjie_set_feedback_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
err, 0);
}
- dbjie->feedback_ = NEW_GLOBAL_REF(jnienv, jfeedback);
+ dbjie->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);
}
void dbjie_call_feedback(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
@@ -325,97 +340,107 @@ void dbjie_call_feedback(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
return;
}
- feedback_class = get_class(jnienv, name_DbEnvFeedback);
+ if ((feedback_class =
+ get_class(jnienv, name_DbEnvFeedback)) == NULL) {
+ fprintf(stderr, "Cannot find callback class %s\n",
+ name_DbEnvFeedback);
+ return; /* An exception has been posted. */
+ }
id = (*jnienv)->GetMethodID(jnienv, feedback_class,
"feedback",
"(Lcom/sleepycat/db/DbEnv;II)V");
if (!id) {
- fprintf(stderr, "Cannot find callback class\n");
+ fprintf(stderr, "Cannot find callback method feedback\n");
return;
}
- (*jnienv)->CallVoidMethod(jnienv, dbjie->feedback_, id,
+ (*jnienv)->CallVoidMethod(jnienv, dbjie->feedback, id,
jenv, (jint)opcode, (jint)percent);
}
-void dbjie_set_recovery_init_object(DB_ENV_JAVAINFO *dbjie,
- JNIEnv *jnienv, DB_ENV *dbenv,
- jobject jrecovery_init)
+void dbjie_set_rep_transport_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
+ DB_ENV *dbenv, int id, jobject jtransport)
{
int err;
- if (dbjie->recovery_init_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->recovery_init_);
- }
- if (jrecovery_init == NULL) {
- if ((err = dbenv->set_recovery_init(dbenv, NULL)) != 0)
- report_exception(jnienv, "set_recovery_init failed",
- err, 0);
- }
- else {
- if ((err = dbenv->set_recovery_init(dbenv,
- DbEnv_recovery_init_callback)) != 0)
- report_exception(jnienv, "set_recovery_init failed",
- err, 0);
- }
+ if (dbjie->rep_transport != NULL)
+ DELETE_GLOBAL_REF(jnienv, dbjie->rep_transport);
+
+ err = dbenv->set_rep_transport(dbenv, id,
+ DbEnv_rep_transport_callback);
+ verify_return(jnienv, err, 0);
- dbjie->recovery_init_ = NEW_GLOBAL_REF(jnienv, jrecovery_init);
+ dbjie->rep_transport = NEW_GLOBAL_REF(jnienv, jtransport);
}
-int dbjie_call_recovery_init(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv,
- jobject jenv)
+int dbjie_call_rep_transport(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv,
+ jobject jenv, const DBT *control,
+ const DBT *rec, int flags, int envid)
{
JNIEnv *jnienv;
- jclass recovery_init_class;
- jmethodID id;
+ jclass rep_transport_class;
+ jmethodID jid;
+ jobject jcdbt, jrdbt;
COMPQUIET(dbenv, NULL);
jnienv = dbjie_get_jnienv(dbjie);
if (jnienv == NULL) {
fprintf(stderr, "Cannot attach to current thread!\n");
- return (EINVAL);
+ return (0);
}
- recovery_init_class = get_class(jnienv, name_DbRecoveryInit);
- id = (*jnienv)->GetMethodID(jnienv, recovery_init_class,
- "recovery_init",
- "(Lcom/sleepycat/db/DbEnv;)V");
- if (!id) {
- fprintf(stderr, "Cannot find callback class\n");
- return (EINVAL);
+ if ((rep_transport_class =
+ get_class(jnienv, name_DbRepTransport)) == NULL) {
+ fprintf(stderr, "Cannot find callback class %s\n",
+ name_DbRepTransport);
+ return (0); /* An exception has been posted. */
}
- return (*jnienv)->CallIntMethod(jnienv, dbjie->recovery_init_,
- id, jenv);
+ jid = (*jnienv)->GetMethodID(jnienv, rep_transport_class,
+ "send",
+ "(Lcom/sleepycat/db/DbEnv;"
+ "Lcom/sleepycat/db/Dbt;"
+ "Lcom/sleepycat/db/Dbt;II)I");
+
+ if (!jid) {
+ fprintf(stderr, "Cannot find callback method send\n");
+ return (0);
+ }
+
+ jcdbt = get_const_Dbt(jnienv, control, NULL);
+ jrdbt = get_const_Dbt(jnienv, rec, NULL);
+
+ return (*jnienv)->CallIntMethod(jnienv, dbjie->rep_transport, jid, jenv,
+ jcdbt, jrdbt, flags, envid);
}
-void dbjie_set_tx_recover_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
- DB_ENV *dbenv, jobject jtx_recover)
+void dbjie_set_app_dispatch_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
+ DB_ENV *dbenv, jobject japp_dispatch)
{
int err;
- if (dbjie->tx_recover_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbjie->tx_recover_);
+ if (dbjie->app_dispatch != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbjie->app_dispatch);
}
- if (jtx_recover == NULL) {
- if ((err = dbenv->set_tx_recover(dbenv, NULL)) != 0)
- report_exception(jnienv, "set_tx_recover failed",
+ if (japp_dispatch == NULL) {
+ if ((err = dbenv->set_app_dispatch(dbenv, NULL)) != 0)
+ report_exception(jnienv, "set_app_dispatch failed",
err, 0);
}
else {
- if ((err = dbenv->set_tx_recover(dbenv,
- DbEnv_tx_recover_callback)) != 0)
- report_exception(jnienv, "set_tx_recover failed",
+ if ((err = dbenv->set_app_dispatch(dbenv,
+ DbEnv_app_dispatch_callback)) != 0)
+ report_exception(jnienv, "set_app_dispatch failed",
err, 0);
}
- dbjie->tx_recover_ = NEW_GLOBAL_REF(jnienv, jtx_recover);
+ dbjie->app_dispatch = NEW_GLOBAL_REF(jnienv, japp_dispatch);
}
-int dbjie_call_tx_recover(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
+int dbjie_call_app_dispatch(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
DBT *dbt, DB_LSN *lsn, int recops)
{
JNIEnv *jnienv;
- jclass tx_recover_class;
+ jclass app_dispatch_class;
jmethodID id;
jobject jdbt;
jobject jlsn;
@@ -427,90 +452,104 @@ int dbjie_call_tx_recover(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
return (0);
}
- tx_recover_class = get_class(jnienv, name_DbTxnRecover);
- id = (*jnienv)->GetMethodID(jnienv, tx_recover_class,
- "tx_recover",
+ if ((app_dispatch_class =
+ get_class(jnienv, name_DbTxnRecover)) == NULL) {
+ fprintf(stderr, "Cannot find callback class %s\n",
+ name_DbTxnRecover);
+ return (0); /* An exception has been posted. */
+ }
+ id = (*jnienv)->GetMethodID(jnienv, app_dispatch_class,
+ "app_dispatch",
"(Lcom/sleepycat/db/DbEnv;"
"Lcom/sleepycat/db/Dbt;"
"Lcom/sleepycat/db/DbLsn;"
"I)I");
if (!id) {
- fprintf(stderr, "Cannot find callback class\n");
+ fprintf(stderr, "Cannot find callback method app_dispatch\n");
return (0);
}
- if (dbt == NULL)
- jdbt = NULL;
- else
- jdbt = get_Dbt(jnienv, dbt);
+ jdbt = get_Dbt(jnienv, dbt, NULL);
if (lsn == NULL)
jlsn = NULL;
else
jlsn = get_DbLsn(jnienv, *lsn);
- return (*jnienv)->CallIntMethod(jnienv, dbjie->tx_recover_, id, jenv,
+ return (*jnienv)->CallIntMethod(jnienv, dbjie->app_dispatch, id, jenv,
jdbt, jlsn, recops);
}
jobject dbjie_get_errcall(DB_ENV_JAVAINFO *dbjie)
{
- return (dbjie->errcall_);
+ return (dbjie->errcall);
}
-int dbjie_is_dbopen(DB_ENV_JAVAINFO *dbjie)
+jint dbjie_is_dbopen(DB_ENV_JAVAINFO *dbjie)
{
- return (dbjie->is_dbopen_);
+ return (dbjie->is_dbopen);
}
/****************************************************************
*
* Implementation of class DB_JAVAINFO
- *
*/
-DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jint flags)
+DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jobject jdb, jint flags)
{
DB_JAVAINFO *dbji;
+ int err;
+
+ /*XXX should return err*/
+ if ((err = __os_malloc(NULL, sizeof(DB_JAVAINFO), &dbji)) != 0)
+ return (NULL);
- dbji = (DB_JAVAINFO *)malloc(sizeof(DB_JAVAINFO));
memset(dbji, 0, sizeof(DB_JAVAINFO));
- if ((*jnienv)->GetJavaVM(jnienv, &dbji->javavm_) != 0) {
+ if ((*jnienv)->GetJavaVM(jnienv, &dbji->javavm) != 0) {
report_exception(jnienv, "cannot get Java VM", 0, 0);
- free(dbji);
+ (void)__os_free(NULL, dbji);
return (NULL);
}
- dbji->construct_flags_ = flags;
+ dbji->jdbref = NEW_GLOBAL_REF(jnienv, jdb);
+ dbji->construct_flags = flags;
return (dbji);
}
void
dbji_dealloc(DB_JAVAINFO *dbji, JNIEnv *jnienv)
{
- if (dbji->append_recno_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->append_recno_);
- dbji->append_recno_ = NULL;
+ if (dbji->append_recno != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->append_recno);
+ dbji->append_recno = NULL;
+ }
+ if (dbji->assoc != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->assoc);
+ dbji->assoc = NULL;
+ }
+ if (dbji->bt_compare != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->bt_compare);
+ dbji->bt_compare = NULL;
}
- if (dbji->bt_compare_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->bt_compare_);
- dbji->bt_compare_ = NULL;
+ if (dbji->bt_prefix != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix);
+ dbji->bt_prefix = NULL;
}
- if (dbji->bt_prefix_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix_);
- dbji->bt_prefix_ = NULL;
+ if (dbji->dup_compare != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->dup_compare);
+ dbji->dup_compare = NULL;
}
- if (dbji->dup_compare_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->dup_compare_);
- dbji->dup_compare_ = NULL;
+ if (dbji->feedback != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->feedback);
+ dbji->feedback = NULL;
}
- if (dbji->feedback_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->feedback_);
- dbji->feedback_ = NULL;
+ if (dbji->h_hash != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->h_hash);
+ dbji->h_hash = NULL;
}
- if (dbji->h_hash_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->h_hash_);
- dbji->h_hash_ = NULL;
+ if (dbji->jdbref != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->jdbref);
+ dbji->jdbref = NULL;
}
}
@@ -518,12 +557,13 @@ void
dbji_destroy(DB_JAVAINFO *dbji, JNIEnv *jnienv)
{
dbji_dealloc(dbji, jnienv);
- free(dbji);
+ __os_free(NULL, dbji);
}
JNIEnv *dbji_get_jnienv(DB_JAVAINFO *dbji)
{
- /* Note:
+ /*
+ * Note:
* Different versions of the JNI disagree on the signature
* for AttachCurrentThread. The most recent documentation
* seems to say that (JNIEnv **) is correct, but newer
@@ -535,10 +575,12 @@ JNIEnv *dbji_get_jnienv(DB_JAVAINFO *dbji)
JNIEnv *attachret = 0;
#endif
- /* This should always succeed, as we are called via
+ /*
+ * This should always succeed, as we are called via
* some Java activity. I think therefore I am (a thread).
*/
- if ((*dbji->javavm_)->AttachCurrentThread(dbji->javavm_, &attachret, 0) != 0)
+ if ((*dbji->javavm)->AttachCurrentThread(dbji->javavm, &attachret, 0)
+ != 0)
return (0);
return ((JNIEnv *)attachret);
@@ -546,7 +588,7 @@ JNIEnv *dbji_get_jnienv(DB_JAVAINFO *dbji)
jint dbji_get_flags(DB_JAVAINFO *dbji)
{
- return (dbji->construct_flags_);
+ return (dbji->construct_flags);
}
void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
@@ -554,14 +596,17 @@ void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
{
jclass feedback_class;
- if (dbji->feedback_method_id_ == NULL) {
- feedback_class = get_class(jnienv, name_DbFeedback);
- dbji->feedback_method_id_ =
+ if (dbji->feedback_method_id == NULL) {
+ if ((feedback_class =
+ get_class(jnienv, name_DbFeedback)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->feedback_method_id =
(*jnienv)->GetMethodID(jnienv, feedback_class,
"feedback",
"(Lcom/sleepycat/db/Db;II)V");
- if (dbji->feedback_method_id_ != NULL) {
- /* XXX
+ if (dbji->feedback_method_id == NULL) {
+ /*
+ * XXX
* We should really have a better way
* to translate this to a Java exception class.
* In theory, it shouldn't happen.
@@ -572,8 +617,8 @@ void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
}
}
- if (dbji->feedback_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->feedback_);
+ if (dbji->feedback != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->feedback);
}
if (jfeedback == NULL) {
db->set_feedback(db, NULL);
@@ -582,7 +627,7 @@ void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
db->set_feedback(db, Db_feedback_callback);
}
- dbji->feedback_ = NEW_GLOBAL_REF(jnienv, jfeedback);
+ dbji->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);
}
@@ -598,9 +643,9 @@ void dbji_call_feedback(DB_JAVAINFO *dbji, DB *db, jobject jdb,
return;
}
- DB_ASSERT(dbji->feedback_method_id_ != NULL);
- (*jnienv)->CallVoidMethod(jnienv, dbji->feedback_,
- dbji->feedback_method_id_,
+ DB_ASSERT(dbji->feedback_method_id != NULL);
+ (*jnienv)->CallVoidMethod(jnienv, dbji->feedback,
+ dbji->feedback_method_id,
jdb, (jint)opcode, (jint)percent);
}
@@ -609,15 +654,18 @@ void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
{
jclass append_recno_class;
- if (dbji->append_recno_method_id_ == NULL) {
- append_recno_class = get_class(jnienv, name_DbAppendRecno);
- dbji->append_recno_method_id_ =
+ if (dbji->append_recno_method_id == NULL) {
+ if ((append_recno_class =
+ get_class(jnienv, name_DbAppendRecno)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->append_recno_method_id =
(*jnienv)->GetMethodID(jnienv, append_recno_class,
"db_append_recno",
"(Lcom/sleepycat/db/Db;"
"Lcom/sleepycat/db/Dbt;I)V");
- if (dbji->append_recno_method_id_ == NULL) {
- /* XXX
+ if (dbji->append_recno_method_id == NULL) {
+ /*
+ * XXX
* We should really have a better way
* to translate this to a Java exception class.
* In theory, it shouldn't happen.
@@ -628,8 +676,8 @@ void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
}
}
- if (dbji->append_recno_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->append_recno_);
+ if (dbji->append_recno != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->append_recno);
}
if (jcallback == NULL) {
db->set_append_recno(db, NULL);
@@ -638,51 +686,36 @@ void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
db->set_append_recno(db, Db_append_recno_callback);
}
- dbji->append_recno_ = NEW_GLOBAL_REF(jnienv, jcallback);
+ dbji->append_recno = NEW_GLOBAL_REF(jnienv, jcallback);
}
extern int dbji_call_append_recno(DB_JAVAINFO *dbji, DB *db, jobject jdb,
DBT *dbt, jint recno)
{
JNIEnv *jnienv;
- jobject jdbt;
+ jobject jresult;
DBT_JAVAINFO *dbtji;
- jbyteArray arr;
- unsigned int arraylen;
- unsigned char *data;
+ LOCKED_DBT lresult;
+ DB_ENV *dbenv;
+ u_char *bytearray;
+ int err;
- COMPQUIET(db, NULL);
jnienv = dbji_get_jnienv(dbji);
+ dbenv = db->dbenv;
if (jnienv == NULL) {
fprintf(stderr, "Cannot attach to current thread!\n");
return (0);
}
- /* XXX
- * We should have a pool of Dbt objects used for this purpose
- * instead of creating new ones each time. Because of
- * multithreading, we may need an arbitrary number (more than two).
- * We might also have a byte arrays that grow as needed,
- * so we don't need to allocate those either.
- *
- * Note, we do not set the 'create_array_' flag as on other
- * callbacks as we are creating the array here.
- */
- jdbt = create_default_object(jnienv, name_DBT);
- dbtji = get_DBT_JAVAINFO(jnienv, jdbt);
- memcpy(&dbtji->dbt, dbt, sizeof(DBT));
- dbtji->dbt.data = NULL;
- arr = (*jnienv)->NewByteArray(jnienv, dbt->size);
- (*jnienv)->SetByteArrayRegion(jnienv, arr, 0, dbt->size,
- (jbyte *)dbt->data);
- dbtji->array_ = (jbyteArray)NEW_GLOBAL_REF(jnienv, arr);
-
- DB_ASSERT(dbji->append_recno_method_id_ != NULL);
- (*jnienv)->CallVoidMethod(jnienv, dbji->append_recno_,
- dbji->append_recno_method_id_,
- jdb, jdbt, recno);
-
- /* The underlying C API requires that an errno be returned
+ jresult = get_Dbt(jnienv, dbt, &dbtji);
+
+ DB_ASSERT(dbji->append_recno_method_id != NULL);
+ (*jnienv)->CallVoidMethod(jnienv, dbji->append_recno,
+ dbji->append_recno_method_id,
+ jdb, jresult, recno);
+
+ /*
+ * The underlying C API requires that an errno be returned
* on error. Java users know nothing of errnos, so we
* allow them to throw exceptions instead. We leave the
* exception in place and return DB_JAVA_CALLBACK to the C API
@@ -701,26 +734,146 @@ extern int dbji_call_append_recno(DB_JAVAINFO *dbji, DB *db, jobject jdb,
if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
return (DB_JAVA_CALLBACK);
- if (dbtji->array_ == NULL) {
- report_exception(jnienv, "Dbt.data is null", 0, 0);
- return (EFAULT);
+ /*
+ * Now get the DBT back from java, because the user probably
+ * changed it. We'll have to copy back the array too and let
+ * our caller free it.
+ *
+ * We expect that the user *has* changed the DBT (why else would
+ * they set up an append_recno callback?) so we don't
+ * worry about optimizing the unchanged case.
+ */
+ if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0)
+ return (err);
+
+ memcpy(dbt, &lresult.javainfo->dbt, sizeof(DBT));
+ if ((err = __os_malloc(dbenv, dbt->size, &bytearray)) != 0)
+ goto out;
+
+ memcpy(bytearray, dbt->data, dbt->size);
+ dbt->data = bytearray;
+ dbt->flags |= DB_DBT_APPMALLOC;
+
+ out:
+ locked_dbt_put(&lresult, jnienv, dbenv);
+ return (err);
+}
+
+void dbji_set_assoc_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
+ DB *db, DB_TXN *txn, DB *second,
+ jobject jcallback, int flags)
+{
+ jclass assoc_class;
+ int err;
+
+ if (dbji->assoc_method_id == NULL) {
+ if ((assoc_class =
+ get_class(jnienv, name_DbSecondaryKeyCreate)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->assoc_method_id =
+ (*jnienv)->GetMethodID(jnienv, assoc_class,
+ "secondary_key_create",
+ "(Lcom/sleepycat/db/Db;"
+ "Lcom/sleepycat/db/Dbt;"
+ "Lcom/sleepycat/db/Dbt;"
+ "Lcom/sleepycat/db/Dbt;)I");
+ if (dbji->assoc_method_id == NULL) {
+ /*
+ * XXX
+ * We should really have a better way
+ * to translate this to a Java exception class.
+ * In theory, it shouldn't happen.
+ */
+ report_exception(jnienv, "Cannot find callback method",
+ EFAULT, 0);
+ return;
+ }
}
- arraylen = (*jnienv)->GetArrayLength(jnienv, dbtji->array_);
- if (dbtji->offset_ < 0 ) {
- report_exception(jnienv, "Dbt.offset illegal", 0, 0);
- return (EFAULT);
+ if (dbji->assoc != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->assoc);
+ dbji->assoc = NULL;
}
- if (dbt->ulen + dbtji->offset_ > arraylen) {
- report_exception(jnienv,
- "Dbt.ulen + Dbt.offset greater than array length", 0, 0);
- return (EFAULT);
+
+ if (jcallback == NULL)
+ err = db->associate(db, txn, second, NULL, flags);
+ else
+ err = db->associate(db, txn, second, Db_assoc_callback, flags);
+
+ if (verify_return(jnienv, err, 0))
+ dbji->assoc = NEW_GLOBAL_REF(jnienv, jcallback);
+}
+
+extern int dbji_call_assoc(DB_JAVAINFO *dbji, DB *db, jobject jdb,
+ const DBT *key, const DBT *value, DBT *result)
+{
+ JNIEnv *jnienv;
+ jobject jresult;
+ LOCKED_DBT lresult;
+ DB_ENV *dbenv;
+ int err;
+ int sz;
+ u_char *bytearray;
+ jint retval;
+
+ jnienv = dbji_get_jnienv(dbji);
+ if (jnienv == NULL) {
+ fprintf(stderr, "Cannot attach to current thread!\n");
+ return (0);
}
- data = (*jnienv)->GetByteArrayElements(jnienv, dbtji->array_,
- (jboolean *)0);
- dbt->data = data + dbtji->offset_;
- return (0);
+ DB_ASSERT(dbji->assoc_method_id != NULL);
+
+ dbenv = db->dbenv;
+ jresult = create_default_object(jnienv, name_DBT);
+
+ retval = (*jnienv)->CallIntMethod(jnienv, dbji->assoc,
+ dbji->assoc_method_id, jdb,
+ get_const_Dbt(jnienv, key, NULL),
+ get_const_Dbt(jnienv, value, NULL),
+ jresult);
+ if (retval != 0)
+ return (retval);
+
+ if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
+ return (DB_JAVA_CALLBACK);
+
+ if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0)
+ return (err);
+
+ sz = lresult.javainfo->dbt.size;
+ if (sz > 0) {
+ bytearray = (u_char *)lresult.javainfo->dbt.data;
+
+ /*
+ * If the byte array is in the range of one of the
+ * arrays passed to us we can use it directly.
+ * If not, we must create our own array and
+ * fill it in with the java array. Since
+ * the java array may disappear and we don't
+ * want to keep its memory locked indefinitely,
+ * we cannot just pin the array.
+ *
+ * XXX consider pinning the array, and having
+ * some way for the C layer to notify the java
+ * layer when it can be unpinned.
+ */
+ if ((bytearray < (u_char *)key->data ||
+ bytearray + sz > (u_char *)key->data + key->size) &&
+ (bytearray < (u_char *)value->data ||
+ bytearray + sz > (u_char *)value->data + value->size)) {
+
+ result->flags |= DB_DBT_APPMALLOC;
+ if ((err = __os_malloc(dbenv, sz, &bytearray)) != 0)
+ goto out;
+ memcpy(bytearray, lresult.javainfo->dbt.data, sz);
+ }
+ result->data = bytearray;
+ result->size = sz;
+ }
+ out:
+ locked_dbt_put(&lresult, jnienv, dbenv);
+ return (err);
}
void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
@@ -728,16 +881,19 @@ void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
{
jclass bt_compare_class;
- if (dbji->bt_compare_method_id_ == NULL) {
- bt_compare_class = get_class(jnienv, name_DbBtreeCompare);
- dbji->bt_compare_method_id_ =
+ if (dbji->bt_compare_method_id == NULL) {
+ if ((bt_compare_class =
+ get_class(jnienv, name_DbBtreeCompare)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->bt_compare_method_id =
(*jnienv)->GetMethodID(jnienv, bt_compare_class,
"bt_compare",
"(Lcom/sleepycat/db/Db;"
"Lcom/sleepycat/db/Dbt;"
"Lcom/sleepycat/db/Dbt;)I");
- if (dbji->bt_compare_method_id_ == NULL) {
- /* XXX
+ if (dbji->bt_compare_method_id == NULL) {
+ /*
+ * XXX
* We should really have a better way
* to translate this to a Java exception class.
* In theory, it shouldn't happen.
@@ -748,8 +904,8 @@ void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
}
}
- if (dbji->bt_compare_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->bt_compare_);
+ if (dbji->bt_compare != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->bt_compare);
}
if (jcompare == NULL) {
db->set_bt_compare(db, NULL);
@@ -758,7 +914,7 @@ void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
db->set_bt_compare(db, Db_bt_compare_callback);
}
- dbji->bt_compare_ = NEW_GLOBAL_REF(jnienv, jcompare);
+ dbji->bt_compare = NEW_GLOBAL_REF(jnienv, jcompare);
}
int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
@@ -766,7 +922,6 @@ int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
{
JNIEnv *jnienv;
jobject jdbt1, jdbt2;
- DBT_JAVAINFO *dbtji1, *dbtji2;
COMPQUIET(db, NULL);
jnienv = dbji_get_jnienv(dbji);
@@ -775,25 +930,12 @@ int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
return (0);
}
- /* XXX
- * We should have a pool of Dbt objects used for this purpose
- * instead of creating new ones each time. Because of
- * multithreading, we may need an arbitrary number (more than two).
- * We might also have a byte arrays that grow as needed,
- * so we don't need to allocate those either.
- */
- jdbt1 = create_default_object(jnienv, name_DBT);
- jdbt2 = create_default_object(jnienv, name_DBT);
- dbtji1 = get_DBT_JAVAINFO(jnienv, jdbt1);
- memcpy(&dbtji1->dbt, dbt1, sizeof(DBT));
- dbtji1->create_array_ = 1;
- dbtji2 = get_DBT_JAVAINFO(jnienv, jdbt2);
- memcpy(&dbtji2->dbt, dbt2, sizeof(DBT));
- dbtji2->create_array_ = 1;
-
- DB_ASSERT(dbji->bt_compare_method_id_ != NULL);
- return (*jnienv)->CallIntMethod(jnienv, dbji->bt_compare_,
- dbji->bt_compare_method_id_,
+ jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
+ jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
+
+ DB_ASSERT(dbji->bt_compare_method_id != NULL);
+ return (*jnienv)->CallIntMethod(jnienv, dbji->bt_compare,
+ dbji->bt_compare_method_id,
jdb, jdbt1, jdbt2);
}
@@ -802,16 +944,19 @@ void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
{
jclass bt_prefix_class;
- if (dbji->bt_prefix_method_id_ == NULL) {
- bt_prefix_class = get_class(jnienv, name_DbBtreePrefix);
- dbji->bt_prefix_method_id_ =
+ if (dbji->bt_prefix_method_id == NULL) {
+ if ((bt_prefix_class =
+ get_class(jnienv, name_DbBtreePrefix)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->bt_prefix_method_id =
(*jnienv)->GetMethodID(jnienv, bt_prefix_class,
"bt_prefix",
"(Lcom/sleepycat/db/Db;"
"Lcom/sleepycat/db/Dbt;"
"Lcom/sleepycat/db/Dbt;)I");
- if (dbji->bt_prefix_method_id_ == NULL) {
- /* XXX
+ if (dbji->bt_prefix_method_id == NULL) {
+ /*
+ * XXX
* We should really have a better way
* to translate this to a Java exception class.
* In theory, it shouldn't happen.
@@ -822,8 +967,8 @@ void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
}
}
- if (dbji->bt_prefix_ != NULL) {
- DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix_);
+ if (dbji->bt_prefix != NULL) {
+ DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix);
}
if (jprefix == NULL) {
db->set_bt_prefix(db, NULL);
@@ -832,7 +977,7 @@ void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
db->set_bt_prefix(db, Db_bt_prefix_callback);
}
- dbji->bt_prefix_ = NEW_GLOBAL_REF(jnienv, jprefix);
+ dbji->bt_prefix = NEW_GLOBAL_REF(jnienv, jprefix);
}
size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb,
@@ -840,7 +985,6 @@ size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb,
{
JNIEnv *jnienv;
jobject jdbt1, jdbt2;
- DBT_JAVAINFO *dbtji1, *dbtji2;
COMPQUIET(db, NULL);
jnienv = dbji_get_jnienv(dbji);
@@ -849,25 +993,12 @@ size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb,
return (0);
}
- /* XXX
- * We should have a pool of Dbt objects used for this purpose
- * instead of creating new ones each time. Because of
- * multithreading, we may need an arbitrary number (more than two).
- * We might also have a byte arrays that grow as needed,
- * so we don't need to allocate those either.
- */
- jdbt1 = create_default_object(jnienv, name_DBT);
- jdbt2 = create_default_object(jnienv, name_DBT);
- dbtji1 = get_DBT_JAVAINFO(jnienv, jdbt1);
- memcpy(&dbtji1->dbt, dbt1, sizeof(DBT));
- dbtji1->create_array_ = 1;
- dbtji2 = get_DBT_JAVAINFO(jnienv, jdbt2);
- memcpy(&dbtji2->dbt, dbt2, sizeof(DBT));
- dbtji2->create_array_ = 1;
-
- DB_ASSERT(dbji->bt_prefix_method_id_ != NULL);
- return (size_t)(*jnienv)->CallIntMethod(jnienv, dbji->bt_prefix_,
- dbji->bt_prefix_method_id_,
+ jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
+ jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
+
+ DB_ASSERT(dbji->bt_prefix_method_id != NULL);
+ return (size_t)(*jnienv)->CallIntMethod(jnienv, dbji->bt_prefix,
+ dbji->bt_prefix_method_id,
jdb, jdbt1, jdbt2);
}
@@ -876,16 +1007,19 @@ void dbji_set_dup_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
{
jclass dup_compare_class;
- if (dbji->dup_compare_method_id_ == NULL) {
- dup_compare_class = get_class(jnienv, name_DbDupCompare);
- dbji->dup_compare_method_id_ =
+ if (dbji->dup_compare_method_id == NULL) {
+ if ((dup_compare_class =
+ get_class(jnienv, name_DbDupCompare)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->dup_compare_method_id =
(*jnienv)->GetMethodID(jnienv, dup_compare_class,
"dup_compare",
"(Lcom/sleepycat/db/Db;"
"Lcom/sleepycat/db/Dbt;"
"Lcom/sleepycat/db/Dbt;)I");
- if (dbji->dup_compare_method_id_ == NULL) {
- /* XXX
+ if (dbji->dup_compare_method_id == NULL) {
+ /*
+ * XXX
* We should really have a better way
* to translate this to a Java exception class.
* In theory, it shouldn't happen.
@@ -896,15 +1030,15 @@ void dbji_set_dup_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
}
}
- if (dbji->dup_compare_ != NULL)
- DELETE_GLOBAL_REF(jnienv, dbji->dup_compare_);
+ if (dbji->dup_compare != NULL)
+ DELETE_GLOBAL_REF(jnienv, dbji->dup_compare);
if (jcompare == NULL)
db->set_dup_compare(db, NULL);
else
db->set_dup_compare(db, Db_dup_compare_callback);
- dbji->dup_compare_ = NEW_GLOBAL_REF(jnienv, jcompare);
+ dbji->dup_compare = NEW_GLOBAL_REF(jnienv, jcompare);
}
int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
@@ -912,7 +1046,6 @@ int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
{
JNIEnv *jnienv;
jobject jdbt1, jdbt2;
- DBT_JAVAINFO *dbtji1, *dbtji2;
COMPQUIET(db, NULL);
jnienv = dbji_get_jnienv(dbji);
@@ -921,25 +1054,12 @@ int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
return (0);
}
- /* XXX
- * We should have a pool of Dbt objects used for this purpose
- * instead of creating new ones each time. Because of
- * multithreading, we may need an arbitrary number (more than two).
- * We might also have a byte arrays that grow as needed,
- * so we don't need to allocate those either.
- */
- jdbt1 = create_default_object(jnienv, name_DBT);
- jdbt2 = create_default_object(jnienv, name_DBT);
- dbtji1 = get_DBT_JAVAINFO(jnienv, jdbt1);
- memcpy(&dbtji1->dbt, dbt1, sizeof(DBT));
- dbtji1->create_array_ = 1;
- dbtji2 = get_DBT_JAVAINFO(jnienv, jdbt2);
- memcpy(&dbtji2->dbt, dbt2, sizeof(DBT));
- dbtji2->create_array_ = 1;
-
- DB_ASSERT(dbji->dup_compare_method_id_ != NULL);
- return (*jnienv)->CallIntMethod(jnienv, dbji->dup_compare_,
- dbji->dup_compare_method_id_,
+ jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
+ jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
+
+ DB_ASSERT(dbji->dup_compare_method_id != NULL);
+ return (*jnienv)->CallIntMethod(jnienv, dbji->dup_compare,
+ dbji->dup_compare_method_id,
jdb, jdbt1, jdbt2);
}
@@ -948,15 +1068,18 @@ void dbji_set_h_hash_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
{
jclass h_hash_class;
- if (dbji->h_hash_method_id_ == NULL) {
- h_hash_class = get_class(jnienv, name_DbHash);
- dbji->h_hash_method_id_ =
+ if (dbji->h_hash_method_id == NULL) {
+ if ((h_hash_class =
+ get_class(jnienv, name_DbHash)) == NULL)
+ return; /* An exception has been posted. */
+ dbji->h_hash_method_id =
(*jnienv)->GetMethodID(jnienv, h_hash_class,
"hash",
"(Lcom/sleepycat/db/Db;"
"[BI)I");
- if (dbji->h_hash_method_id_ == NULL) {
- /* XXX
+ if (dbji->h_hash_method_id == NULL) {
+ /*
+ * XXX
* We should really have a better way
* to translate this to a Java exception class.
* In theory, it shouldn't happen.
@@ -967,22 +1090,22 @@ void dbji_set_h_hash_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
}
}
- if (dbji->h_hash_ != NULL)
- DELETE_GLOBAL_REF(jnienv, dbji->h_hash_);
+ if (dbji->h_hash != NULL)
+ DELETE_GLOBAL_REF(jnienv, dbji->h_hash);
if (jhash == NULL)
db->set_h_hash(db, NULL);
else
db->set_h_hash(db, Db_h_hash_callback);
- dbji->h_hash_ = NEW_GLOBAL_REF(jnienv, jhash);
+ dbji->h_hash = NEW_GLOBAL_REF(jnienv, jhash);
}
int dbji_call_h_hash(DB_JAVAINFO *dbji, DB *db, jobject jdb,
const void *data, int len)
{
JNIEnv *jnienv;
- jbyteArray jarray;
+ jbyteArray jdata;
COMPQUIET(db, NULL);
jnienv = dbji_get_jnienv(dbji);
@@ -991,11 +1114,12 @@ int dbji_call_h_hash(DB_JAVAINFO *dbji, DB *db, jobject jdb,
return (0);
}
- DB_ASSERT(dbji->h_hash_method_id_ != NULL);
+ DB_ASSERT(dbji->h_hash_method_id != NULL);
- jarray = (*jnienv)->NewByteArray(jnienv, len);
- (*jnienv)->SetByteArrayRegion(jnienv, jarray, 0, len, (void *)data);
- return (*jnienv)->CallIntMethod(jnienv, dbji->h_hash_,
- dbji->h_hash_method_id_,
- jdb, jarray, len);
+ if ((jdata = (*jnienv)->NewByteArray(jnienv, len)) == NULL)
+ return (0); /* An exception has been posted by the JVM */
+ (*jnienv)->SetByteArrayRegion(jnienv, jdata, 0, len, (void *)data);
+ return (*jnienv)->CallIntMethod(jnienv, dbji->h_hash,
+ dbji->h_hash_method_id,
+ jdb, jdata, len);
}
diff --git a/bdb/libdb_java/java_info.h b/bdb/libdb_java/java_info.h
index 69032be80e6..bda83db420e 100644
--- a/bdb/libdb_java/java_info.h
+++ b/bdb/libdb_java/java_info.h
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: java_info.h,v 11.17 2000/07/31 20:28:30 dda Exp $
+ * $Id: java_info.h,v 11.35 2002/08/29 14:22:23 margo Exp $
*/
#ifndef _JAVA_INFO_H_
@@ -36,16 +36,22 @@
typedef struct _dbt_javainfo
{
DBT dbt;
- DB *db_; /* associated DB */
- jobject dbtref_; /* the java Dbt object */
- jbyteArray array_;
- int offset_;
- int create_array_; /* flag to create the array as needed */
+ DB *db; /* associated DB */
+ jobject dbtref; /* the java Dbt object */
+ jbyteArray array; /* the java array object -
+ this is only valid during the API call */
+ int offset; /* offset into the Java array */
+
+#define DBT_JAVAINFO_LOCKED 0x01 /* a LOCKED_DBT has been created */
+ u_int32_t flags;
}
-DBT_JAVAINFO; /* used with all 'dbtji' functions */
+DBT_JAVAINFO; /* used with all 'dbtji' functions */
+/* create/initialize a DBT_JAVAINFO object */
extern DBT_JAVAINFO *dbjit_construct();
-extern void dbjit_release(DBT_JAVAINFO *dbjit, JNIEnv *jnienv);
+
+/* free this DBT_JAVAINFO, releasing anything allocated on its behalf */
+extern void dbjit_destroy(DBT_JAVAINFO *dbjit);
/****************************************************************
*
@@ -82,22 +88,25 @@ extern void dbjit_release(DBT_JAVAINFO *dbjit, JNIEnv *jnienv);
*/
typedef struct _db_env_javainfo
{
- JavaVM *javavm_;
- int is_dbopen_;
- char *errpfx_;
- jobject jdbref_; /* temporary reference */
- jobject jenvref_; /* temporary reference */
- jobject default_errcall_; /* global reference */
- jobject errcall_; /* global reference */
- jobject feedback_; /* global reference */
- jobject tx_recover_; /* global reference */
- jobject recovery_init_; /* global reference */
- unsigned char *conflict_;
+ JavaVM *javavm;
+ int is_dbopen;
+ char *errpfx;
+ jobject jenvref; /* global reference */
+ jobject default_errcall; /* global reference */
+ jobject errcall; /* global reference */
+ jobject feedback; /* global reference */
+ jobject rep_transport; /* global reference */
+ jobject app_dispatch; /* global reference */
+ jobject recovery_init; /* global reference */
+ u_char *conflict;
+ size_t conflict_size;
+ jint construct_flags;
}
-DB_ENV_JAVAINFO; /* used with all 'dbjie' functions */
+DB_ENV_JAVAINFO; /* used with all 'dbjie' functions */
/* create/initialize an object */
extern DB_ENV_JAVAINFO *dbjie_construct(JNIEnv *jnienv,
+ jobject jenv,
jobject default_errcall,
int is_dbopen);
@@ -115,7 +124,7 @@ extern void dbjie_set_errpfx(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
extern jstring dbjie_get_errpfx(DB_ENV_JAVAINFO *, JNIEnv *jnienv);
extern void dbjie_set_errcall(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
jobject new_errcall);
-extern void dbjie_set_conflict(DB_ENV_JAVAINFO *, unsigned char *v);
+extern void dbjie_set_conflict(DB_ENV_JAVAINFO *, u_char *v, size_t sz);
extern void dbjie_set_feedback_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
DB_ENV *dbenv, jobject value);
extern void dbjie_call_feedback(DB_ENV_JAVAINFO *, DB_ENV *dbenv, jobject jenv,
@@ -124,13 +133,18 @@ extern void dbjie_set_recovery_init_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
DB_ENV *dbenv, jobject value);
extern int dbjie_call_recovery_init(DB_ENV_JAVAINFO *, DB_ENV *dbenv,
jobject jenv);
-extern void dbjie_set_tx_recover_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
+extern void dbjie_set_rep_transport_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
+ DB_ENV *dbenv, int id, jobject obj);
+extern int dbjie_call_rep_transport(DB_ENV_JAVAINFO *, DB_ENV *dbenv,
+ jobject jenv, const DBT *control,
+ const DBT *rec, int envid, int flags);
+extern void dbjie_set_app_dispatch_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv,
DB_ENV *dbenv, jobject value);
-extern int dbjie_call_tx_recover(DB_ENV_JAVAINFO *,
+extern int dbjie_call_app_dispatch(DB_ENV_JAVAINFO *,
DB_ENV *dbenv, jobject jenv,
DBT *dbt, DB_LSN *lsn, int recops);
extern jobject dbjie_get_errcall(DB_ENV_JAVAINFO *) ;
-extern int dbjie_is_dbopen(DB_ENV_JAVAINFO *);
+extern jint dbjie_is_dbopen(DB_ENV_JAVAINFO *);
/****************************************************************
*
@@ -147,25 +161,27 @@ extern int dbjie_is_dbopen(DB_ENV_JAVAINFO *);
*/
typedef struct _db_javainfo
{
- JavaVM *javavm_;
- jobject jdbref_; /* temporary reference during callback */
- jobject feedback_; /* global reference */
- jobject append_recno_; /* global reference */
- jobject bt_compare_; /* global reference */
- jobject bt_prefix_; /* global reference */
- jobject dup_compare_; /* global reference */
- jobject h_hash_; /* global reference */
- jmethodID feedback_method_id_;
- jmethodID append_recno_method_id_;
- jmethodID bt_compare_method_id_;
- jmethodID bt_prefix_method_id_;
- jmethodID dup_compare_method_id_;
- jmethodID h_hash_method_id_;
- jint construct_flags_;
+ JavaVM *javavm;
+ jobject jdbref; /* global reference */
+ jobject append_recno; /* global reference */
+ jobject assoc; /* global reference */
+ jobject bt_compare; /* global reference */
+ jobject bt_prefix; /* global reference */
+ jobject dup_compare; /* global reference */
+ jobject feedback; /* global reference */
+ jobject h_hash; /* global reference */
+ jmethodID append_recno_method_id;
+ jmethodID assoc_method_id;
+ jmethodID bt_compare_method_id;
+ jmethodID bt_prefix_method_id;
+ jmethodID dup_compare_method_id;
+ jmethodID feedback_method_id;
+ jmethodID h_hash_method_id;
+ jint construct_flags;
} DB_JAVAINFO;
/* create/initialize an object */
-extern DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jint flags);
+extern DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jobject jdb, jint flags);
/* release all objects held by this this one */
extern void dbji_dealloc(DB_JAVAINFO *, JNIEnv *jnienv);
@@ -184,6 +200,11 @@ extern void dbji_call_feedback(DB_JAVAINFO *, DB *db, jobject jdb,
extern void dbji_set_append_recno_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value);
extern int dbji_call_append_recno(DB_JAVAINFO *, DB *db, jobject jdb,
DBT *dbt, jint recno);
+extern void dbji_set_assoc_object(DB_JAVAINFO *, JNIEnv *jnienv,
+ DB *db, DB_TXN *txn, DB *second,
+ jobject value, int flags);
+extern int dbji_call_assoc(DB_JAVAINFO *, DB *db, jobject jdb,
+ const DBT *key, const DBT* data, DBT *result);
extern void dbji_set_bt_compare_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value);
extern int dbji_call_bt_compare(DB_JAVAINFO *, DB *db, jobject jdb,
const DBT *dbt1, const DBT *dbt2);
diff --git a/bdb/libdb_java/java_locked.c b/bdb/libdb_java/java_locked.c
index a5603df5d60..9534a387b40 100644
--- a/bdb/libdb_java/java_locked.c
+++ b/bdb/libdb_java/java_locked.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_locked.c,v 11.11 2000/10/25 19:54:55 dda Exp $";
+static const char revid[] = "$Id: java_locked.c,v 11.32 2002/08/06 05:19:07 bostic Exp $";
#endif /* not lint */
#include <jni.h>
@@ -15,280 +15,307 @@ static const char revid[] = "$Id: java_locked.c,v 11.11 2000/10/25 19:54:55 dda
#include <stdlib.h>
#include <string.h>
-#include "db.h"
+#include "db_int.h"
#include "java_util.h"
/****************************************************************
*
- * Implementation of class LockedDBT
- *
+ * Implementation of functions to manipulate LOCKED_DBT.
*/
int
-jdbt_lock(JDBT *jdbt, JNIEnv *jnienv, jobject obj, OpKind kind)
+locked_dbt_get(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv,
+ jobject jdbt, OpKind kind)
{
DBT *dbt;
- jdbt->obj_ = obj;
- jdbt->do_realloc_ = 0;
- jdbt->kind_ = kind;
- jdbt->java_array_len_= 0;
- jdbt->java_data_ = 0;
- jdbt->before_data_ = 0;
- jdbt->has_error_ = 0;
- jdbt->dbt = (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj);
-
- if (!verify_non_null(jnienv, jdbt->dbt)) {
- jdbt->has_error_ = 1;
+ COMPQUIET(dbenv, NULL);
+ ldbt->jdbt = jdbt;
+ ldbt->java_array_len = 0;
+ ldbt->flags = 0;
+ ldbt->kind = kind;
+ ldbt->java_data = 0;
+ ldbt->before_data = 0;
+ ldbt->javainfo =
+ (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, jdbt);
+
+ if (!verify_non_null(jnienv, ldbt->javainfo)) {
+ report_exception(jnienv, "Dbt is gc'ed?", 0, 0);
+ F_SET(ldbt, LOCKED_ERROR);
return (EINVAL);
}
- dbt = &jdbt->dbt->dbt;
-
- if (kind == outOp &&
- (dbt->flags & (DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC)) == 0) {
- report_exception(jnienv,
- "Dbt.flags must be set to Db.DB_DBT_USERMEM, "
- "Db.DB_DBT_MALLOC or Db.DB_DBT_REALLOC",
- 0, 0);
- jdbt->has_error_ = 1;
+ if (F_ISSET(ldbt->javainfo, DBT_JAVAINFO_LOCKED)) {
+ report_exception(jnienv, "Dbt is already in use", 0, 0);
+ F_SET(ldbt, LOCKED_ERROR);
return (EINVAL);
}
+ dbt = &ldbt->javainfo->dbt;
- /* If this is requested to be realloc, we cannot use the
- * underlying realloc, because the array we will pass in
- * is not allocated by us, but the Java VM, so it cannot
- * be successfully realloced. We simulate the reallocation,
- * by using USERMEM and reallocating the java array when a
- * ENOMEM error occurs. We change the flags during the operation,
- * and they are reset when the operation completes (in the
- * LockedDBT destructor.
+ if ((*jnienv)->GetBooleanField(jnienv,
+ jdbt, fid_Dbt_must_create_data) != 0)
+ F_SET(ldbt, LOCKED_CREATE_DATA);
+ else
+ ldbt->javainfo->array =
+ (*jnienv)->GetObjectField(jnienv, jdbt, fid_Dbt_data);
+
+ dbt->size = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_size);
+ dbt->ulen = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_ulen);
+ dbt->dlen = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_dlen);
+ dbt->doff = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_doff);
+ dbt->flags = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_flags);
+ ldbt->javainfo->offset = (*jnienv)->GetIntField(jnienv, jdbt,
+ fid_Dbt_offset);
+
+ /*
+ * If no flags are set, use default behavior of DB_DBT_MALLOC.
+ * We can safely set dbt->flags because flags will never be copied
+ * back to the Java Dbt.
+ */
+ if (kind != inOp &&
+ !F_ISSET(dbt, DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC))
+ F_SET(dbt, DB_DBT_MALLOC);
+
+ /*
+ * If this is requested to be realloc with an existing array,
+ * we cannot use the underlying realloc, because the array we
+ * will pass in is allocated by the Java VM, not us, so it
+ * cannot be realloced. We simulate the reallocation by using
+ * USERMEM and reallocating the java array when a ENOMEM error
+ * occurs. We change the flags during the operation, and they
+ * are reset when the operation completes (in locked_dbt_put).
*/
- if ((dbt->flags & DB_DBT_REALLOC) != 0) {
- dbt->flags &= ~DB_DBT_REALLOC;
- dbt->flags |= DB_DBT_USERMEM;
- jdbt->do_realloc_ = 1;
+ if (F_ISSET(dbt, DB_DBT_REALLOC) && ldbt->javainfo->array != NULL) {
+ F_CLR(dbt, DB_DBT_REALLOC);
+ F_SET(dbt, DB_DBT_USERMEM);
+ F_SET(ldbt, LOCKED_REALLOC_NONNULL);
}
- if ((dbt->flags & DB_DBT_USERMEM) || kind != outOp) {
+ if ((F_ISSET(dbt, DB_DBT_USERMEM) || kind != outOp) &&
+ !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
- /* If writing with DB_DBT_USERMEM/REALLOC
+ /*
+ * If writing with DB_DBT_USERMEM
* or it's a set (or get/set) operation,
* then the data should point to a java array.
* Note that outOp means data is coming out of the database
* (it's a get). inOp means data is going into the database
* (either a put, or a key input).
*/
- if (!jdbt->dbt->array_) {
+ if (!ldbt->javainfo->array) {
report_exception(jnienv, "Dbt.data is null", 0, 0);
- jdbt->has_error_ = 1;
+ F_SET(ldbt, LOCKED_ERROR);
return (EINVAL);
}
/* Verify other parameters */
- jdbt->java_array_len_ = (*jnienv)->GetArrayLength(jnienv, jdbt->dbt->array_);
- if (jdbt->dbt->offset_ < 0 ) {
+ ldbt->java_array_len = (*jnienv)->GetArrayLength(jnienv,
+ ldbt->javainfo->array);
+ if (ldbt->javainfo->offset < 0 ) {
report_exception(jnienv, "Dbt.offset illegal", 0, 0);
- jdbt->has_error_ = 1;
+ F_SET(ldbt, LOCKED_ERROR);
return (EINVAL);
}
- if (dbt->ulen + jdbt->dbt->offset_ > jdbt->java_array_len_) {
+ if (dbt->size + ldbt->javainfo->offset > ldbt->java_array_len) {
report_exception(jnienv,
- "Dbt.ulen + Dbt.offset greater than array length", 0, 0);
- jdbt->has_error_ = 1;
+ "Dbt.size + Dbt.offset greater than array length",
+ 0, 0);
+ F_SET(ldbt, LOCKED_ERROR);
return (EINVAL);
}
- jdbt->java_data_ = (*jnienv)->GetByteArrayElements(jnienv, jdbt->dbt->array_,
- (jboolean *)0);
- dbt->data = jdbt->before_data_ = jdbt->java_data_ + jdbt->dbt->offset_;
+ ldbt->java_data = (*jnienv)->GetByteArrayElements(jnienv,
+ ldbt->javainfo->array,
+ (jboolean *)0);
+
+ dbt->data = ldbt->before_data = ldbt->java_data +
+ ldbt->javainfo->offset;
}
- else {
+ else if (!F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
- /* If writing with DB_DBT_MALLOC, then the data is
- * allocated by DB.
+ /*
+ * If writing with DB_DBT_MALLOC or DB_DBT_REALLOC with
+ * a null array, then the data is allocated by DB.
*/
- dbt->data = jdbt->before_data_ = 0;
+ dbt->data = ldbt->before_data = 0;
}
+
+ /*
+ * RPC makes the assumption that if dbt->size is non-zero, there
+ * is data to copy from dbt->data. We may have set dbt->size
+ * to a non-zero integer above but decided not to point
+ * dbt->data at anything. (One example is if we're doing an outOp
+ * with an already-used Dbt whose values we expect to just
+ * overwrite.)
+ *
+ * Clean up the dbt fields so we don't run into trouble.
+ * (Note that doff, dlen, and flags all may contain meaningful
+ * values.)
+ */
+ if (dbt->data == NULL)
+ dbt->size = dbt->ulen = 0;
+
+ F_SET(ldbt->javainfo, DBT_JAVAINFO_LOCKED);
return (0);
}
-/* The LockedDBT destructor is called when the java handler returns
- * to the user, since that's when the LockedDBT objects go out of scope.
- * Since it is thus called after any call to the underlying database,
- * it copies any information from temporary structures back to user
- * accessible arrays, and of course must free memory and remove references.
+/*
+ * locked_dbt_put must be called for any LOCKED_DBT struct before a
+ * java handler returns to the user. It can be thought of as the
+ * LOCKED_DBT destructor. It copies any information from temporary
+ * structures back to user accessible arrays, and of course must free
+ * memory and remove references. The LOCKED_DBT itself is not freed,
+ * as it is expected to be a stack variable.
+ *
+ * Note that after this call, the LOCKED_DBT can still be used in
+ * limited ways, e.g. to look at values in the C DBT.
*/
void
-jdbt_unlock(JDBT *jdbt, JNIEnv *jnienv)
+locked_dbt_put(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv)
{
DBT *dbt;
- dbt = &jdbt->dbt->dbt;
+ dbt = &ldbt->javainfo->dbt;
- /* Fix up the flags if we changed them. */
- if (jdbt->do_realloc_) {
- dbt->flags &= ~DB_DBT_USERMEM;
- dbt->flags |= DB_DBT_REALLOC;
- }
+ /*
+ * If the error flag was set, we never succeeded
+ * in allocating storage.
+ */
+ if (F_ISSET(ldbt, LOCKED_ERROR))
+ return;
- if ((dbt->flags & (DB_DBT_USERMEM | DB_DBT_REALLOC)) ||
- jdbt->kind_ == inOp) {
+ if (((F_ISSET(dbt, DB_DBT_USERMEM) ||
+ F_ISSET(ldbt, LOCKED_REALLOC_NONNULL)) ||
+ ldbt->kind == inOp) && !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
- /* If writing with DB_DBT_USERMEM/REALLOC or it's a set
+ /*
+ * If writing with DB_DBT_USERMEM or it's a set
* (or get/set) operation, then the data may be already in
* the java array, in which case, we just need to release it.
* If DB didn't put it in the array (indicated by the
* dbt->data changing), we need to do that
*/
- if (jdbt->before_data_ != jdbt->java_data_) {
+ if (ldbt->before_data != ldbt->java_data) {
(*jnienv)->SetByteArrayRegion(jnienv,
- jdbt->dbt->array_,
- jdbt->dbt->offset_,
+ ldbt->javainfo->array,
+ ldbt->javainfo->offset,
dbt->ulen,
- jdbt->before_data_);
+ ldbt->before_data);
}
- (*jnienv)->ReleaseByteArrayElements(jnienv, jdbt->dbt->array_, jdbt->java_data_, 0);
+ (*jnienv)->ReleaseByteArrayElements(jnienv,
+ ldbt->javainfo->array,
+ ldbt->java_data, 0);
dbt->data = 0;
}
- if ((dbt->flags & DB_DBT_MALLOC) && jdbt->kind_ != inOp) {
-
- /* If writing with DB_DBT_MALLOC, then the data was allocated
- * by DB. If dbt->data is zero, it means an error occurred
- * (and should have been already reported).
+ else if (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC) &&
+ ldbt->kind != inOp && !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
+
+ /*
+ * If writing with DB_DBT_MALLOC, or DB_DBT_REALLOC
+ * with a zero buffer, then the data was allocated by
+ * DB. If dbt->data is zero, it means an error
+ * occurred (and should have been already reported).
*/
if (dbt->data) {
- /* Release any old references. */
- dbjit_release(jdbt->dbt, jnienv);
-
- /* In the case of SET_RANGE, the key is inOutOp
+ /*
+ * In the case of SET_RANGE, the key is inOutOp
* and when not found, its data will be left as
* its original value. Only copy and free it
* here if it has been allocated by DB
* (dbt->data has changed).
*/
- if (dbt->data != jdbt->before_data_) {
- jdbt->dbt->array_ = (jbyteArray)
- NEW_GLOBAL_REF(jnienv,
- (*jnienv)->NewByteArray(jnienv,
- dbt->size));
- jdbt->dbt->offset_ = 0;
+ if (dbt->data != ldbt->before_data) {
+ jbyteArray newarr;
+
+ if ((newarr = (*jnienv)->NewByteArray(jnienv,
+ dbt->size)) == NULL) {
+ /* The JVM has posted an exception. */
+ F_SET(ldbt, LOCKED_ERROR);
+ return;
+ }
+ (*jnienv)->SetObjectField(jnienv, ldbt->jdbt,
+ fid_Dbt_data,
+ newarr);
+ ldbt->javainfo->offset = 0;
(*jnienv)->SetByteArrayRegion(jnienv,
- jdbt->dbt->array_, 0, dbt->size,
+ newarr, 0, dbt->size,
(jbyte *)dbt->data);
- free(dbt->data);
+ (void)__os_ufree(dbenv, dbt->data);
dbt->data = 0;
}
}
}
+
+ /*
+ * The size field may have changed after a DB API call,
+ * so we set that back too.
+ */
+ (*jnienv)->SetIntField(jnienv, ldbt->jdbt, fid_Dbt_size, dbt->size);
+ ldbt->javainfo->array = NULL;
+ F_CLR(ldbt->javainfo, DBT_JAVAINFO_LOCKED);
}
-/* Realloc the java array to receive data if the DBT was marked
- * for realloc, and the last operation set the size field to an
- * amount greater than ulen.
+/*
+ * Realloc the java array to receive data if the DBT used
+ * DB_DBT_REALLOC flag with a non-null data array, and the last
+ * operation set the size field to an amount greater than ulen.
+ * Return 1 if these conditions are met, otherwise 0. This is used
+ * internally to simulate the operations needed for DB_DBT_REALLOC.
*/
-int jdbt_realloc(JDBT *jdbt, JNIEnv *jnienv)
+int locked_dbt_realloc(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv)
{
DBT *dbt;
- dbt = &jdbt->dbt->dbt;
+ COMPQUIET(dbenv, NULL);
+ dbt = &ldbt->javainfo->dbt;
- if (!jdbt->do_realloc_ || jdbt->has_error_ || dbt->size <= dbt->ulen)
+ if (!F_ISSET(ldbt, LOCKED_REALLOC_NONNULL) ||
+ F_ISSET(ldbt, LOCKED_ERROR) || dbt->size <= dbt->ulen)
return (0);
- (*jnienv)->ReleaseByteArrayElements(jnienv, jdbt->dbt->array_, jdbt->java_data_, 0);
- dbjit_release(jdbt->dbt, jnienv);
+ (*jnienv)->ReleaseByteArrayElements(jnienv, ldbt->javainfo->array,
+ ldbt->java_data, 0);
- /* We allocate a new array of the needed size.
+ /*
+ * We allocate a new array of the needed size.
* We'll set the offset to 0, as the old offset
* really doesn't make any sense.
*/
- jdbt->java_array_len_ = dbt->ulen = dbt->size;
- jdbt->dbt->offset_ = 0;
- jdbt->dbt->array_ = (jbyteArray)
- NEW_GLOBAL_REF(jnienv, (*jnienv)->NewByteArray(jnienv, dbt->size));
-
- jdbt->java_data_ = (*jnienv)->GetByteArrayElements(jnienv,
- jdbt->dbt->array_,
- (jboolean *)0);
- dbt->data = jdbt->before_data_ = jdbt->java_data_;
+ if ((ldbt->javainfo->array = (*jnienv)->NewByteArray(jnienv,
+ dbt->size)) == NULL) {
+ F_SET(ldbt, LOCKED_ERROR);
+ return (0);
+ }
+
+ ldbt->java_array_len = dbt->ulen = dbt->size;
+ ldbt->javainfo->offset = 0;
+ (*jnienv)->SetObjectField(jnienv, ldbt->jdbt, fid_Dbt_data,
+ ldbt->javainfo->array);
+ ldbt->java_data = (*jnienv)->GetByteArrayElements(jnienv,
+ ldbt->javainfo->array, (jboolean *)0);
+ memcpy(ldbt->java_data, ldbt->before_data, dbt->ulen);
+ dbt->data = ldbt->before_data = ldbt->java_data;
return (1);
}
/****************************************************************
*
- * Implementation of class JSTR
- *
+ * Implementation of functions to manipulate LOCKED_STRING.
*/
int
-jstr_lock(JSTR *js, JNIEnv *jnienv, jstring jstr)
+locked_string_get(LOCKED_STRING *ls, JNIEnv *jnienv, jstring jstr)
{
- js->jstr_ = jstr;
+ ls->jstr = jstr;
if (jstr == 0)
- js->string = 0;
+ ls->string = 0;
else
- js->string = (*jnienv)->GetStringUTFChars(jnienv, jstr,
+ ls->string = (*jnienv)->GetStringUTFChars(jnienv, jstr,
(jboolean *)0);
return (0);
}
-void jstr_unlock(JSTR *js, JNIEnv *jnienv)
+void locked_string_put(LOCKED_STRING *ls, JNIEnv *jnienv)
{
- if (js->jstr_)
- (*jnienv)->ReleaseStringUTFChars(jnienv, js->jstr_, js->string);
-}
-
-/****************************************************************
- *
- * Implementation of class JSTRARRAY
- *
- */
-int
-jstrarray_lock(JSTRARRAY *jsa, JNIEnv *jnienv, jobjectArray arr)
-{
- int i;
-
- jsa->arr_ = arr;
- jsa->array = 0;
-
- if (arr != 0) {
- int count = (*jnienv)->GetArrayLength(jnienv, arr);
- const char **new_array =
- (const char **)malloc((sizeof(const char *))*(count+1));
- for (i=0; i<count; i++) {
- jstring jstr = (jstring)(*jnienv)->GetObjectArrayElement(jnienv, arr, i);
- if (jstr == 0) {
- /*
- * An embedded null in the string array
- * is treated as an endpoint.
- */
- new_array[i] = 0;
- break;
- }
- else {
- new_array[i] =
- (*jnienv)->GetStringUTFChars(jnienv, jstr, (jboolean *)0);
- }
- }
- new_array[count] = 0;
- jsa->array = new_array;
- }
- return (0);
-}
-
-void jstrarray_unlock(JSTRARRAY *jsa, JNIEnv *jnienv)
-{
- int i;
- jstring jstr;
-
- if (jsa->arr_) {
- int count = (*jnienv)->GetArrayLength(jnienv, jsa->arr_);
- for (i=0; i<count; i++) {
- if (jsa->array[i] == 0)
- break;
- jstr = (jstring)(*jnienv)->GetObjectArrayElement(jnienv, jsa->arr_, i);
- (*jnienv)->ReleaseStringUTFChars(jnienv, jstr, jsa->array[i]);
- }
- free((void*)jsa->array);
- }
+ if (ls->jstr)
+ (*jnienv)->ReleaseStringUTFChars(jnienv, ls->jstr, ls->string);
}
diff --git a/bdb/libdb_java/java_locked.h b/bdb/libdb_java/java_locked.h
index 9b88cdd0619..a79d929abee 100644
--- a/bdb/libdb_java/java_locked.h
+++ b/bdb/libdb_java/java_locked.h
@@ -1,98 +1,82 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: java_locked.h,v 11.9 2000/10/25 19:54:55 dda Exp $
+ * $Id: java_locked.h,v 11.18 2002/05/07 16:12:42 dda Exp $
*/
#ifndef _JAVA_LOCKED_H_
#define _JAVA_LOCKED_H_
/*
- * Used internally by LockedDBT constructor.
+ * Used as argument to locked_dbt_get().
*/
typedef enum _OpKind {
- inOp, /* setting data in database (passing data in) */
- outOp, /* getting data from database to user memory */
- inOutOp /* both getting/setting data */
+ inOp, /* setting data in database (passing data in) */
+ outOp, /* getting data from database to user memory */
+ inOutOp /* both getting/setting data */
} OpKind;
/*
+ * LOCKED_DBT
*
- * Declaration of JDBT
- *
- * A JDBT object exists during a
- * single native call to the DB API. Its constructor's job is
- * to temporarily convert any java array found in the DBT_JAVAINFO
- * to actual bytes in memory that remain locked in place. These
- * bytes are used during the call to the underlying DB C layer,
- * and are released and/or copied back by the destructor.
- * Thus, a LockedDBT must be declared as a stack object to
- * function properly.
+ * A stack variable LOCKED_DBT should be declared for each Dbt used in a
+ * native call to the DB API. Before the DBT can be used, locked_dbt_get()
+ * must be called to temporarily convert any java array found in the
+ * Dbt (which has a pointer to a DBT_JAVAINFO struct) to actual bytes
+ * in memory that remain locked in place. These bytes are used during
+ * the call to the DB C API, and are released and/or copied back when
+ * locked_dbt_put is called.
*/
-typedef struct _jdbt
+typedef struct _locked_dbt
{
- /* these are accessed externally to ldbt_ functions */
- DBT_JAVAINFO *dbt;
- unsigned int java_array_len_;
+ /* these are accessed externally to locked_dbt_ functions */
+ DBT_JAVAINFO *javainfo;
+ unsigned int java_array_len;
+ jobject jdbt;
- /* these are for used internally by ldbt_ functions */
- jobject obj_;
- jbyte *java_data_;
- jbyte *before_data_;
- int has_error_;
- int do_realloc_;
- OpKind kind_;
-} JDBT;
+ /* these are for used internally by locked_dbt_ functions */
+ jbyte *java_data;
+ jbyte *before_data;
+ OpKind kind;
-extern int jdbt_lock(JDBT *, JNIEnv *jnienv, jobject obj, OpKind kind);
-extern void jdbt_unlock(JDBT *, JNIEnv *jnienv); /* this unlocks and frees the memory */
-extern int jdbt_realloc(JDBT *, JNIEnv *jnienv); /* returns 1 if reallocation took place */
+#define LOCKED_ERROR 0x01 /* error occurred */
+#define LOCKED_CREATE_DATA 0x02 /* must create data on the fly */
+#define LOCKED_REALLOC_NONNULL 0x04 /* DB_DBT_REALLOC flag, nonnull data */
+ u_int32_t flags;
+} LOCKED_DBT;
-/****************************************************************
- *
- * Declaration of JSTR
- *
- * A JSTR exists temporarily to convert a java jstring object
- * to a char *. Because the memory for the char * string is
- * managed by the JVM, it must be released when we are done
- * looking at it. Typically, jstr_lock() is called at the
- * beginning of a function for each jstring object, and jstr_unlock
- * is called at the end of each function for each JSTR.
- */
-typedef struct _jstr
-{
- /* this accessed externally to jstr_ functions */
- const char *string;
+/* Fill the LOCKED_DBT struct and lock the Java byte array */
+extern int locked_dbt_get(LOCKED_DBT *, JNIEnv *, DB_ENV *, jobject, OpKind);
- /* this is used internally by jstr_ functions */
- jstring jstr_;
-} JSTR;
+/* unlock the Java byte array */
+extern void locked_dbt_put(LOCKED_DBT *, JNIEnv *, DB_ENV *);
-extern int jstr_lock(JSTR *, JNIEnv *jnienv, jstring jstr);
-extern void jstr_unlock(JSTR *, JNIEnv *jnienv); /* this unlocks and frees mem */
+/* realloc the Java byte array */
+extern int locked_dbt_realloc(LOCKED_DBT *, JNIEnv *, DB_ENV *);
-/****************************************************************
- *
- * Declaration of class LockedStrarray
+/*
+ * LOCKED_STRING
*
- * Given a java jobjectArray object (that must be a String[]),
- * we extract the individual strings and build a const char **
- * When the LockedStrarray object is destroyed, the individual
- * strings are released.
+ * A LOCKED_STRING exists temporarily to convert a java jstring object
+ * to a char *. Because the memory for the char * string is
+ * managed by the JVM, it must be released when we are done
+ * looking at it. Typically, locked_string_get() is called at the
+ * beginning of a function for each jstring object, and locked_string_put
+ * is called at the end of each function for each LOCKED_STRING.
*/
-typedef struct _jstrarray
+typedef struct _locked_string
{
- /* this accessed externally to jstrarray_ functions */
- const char **array;
+ /* this accessed externally to locked_string_ functions */
+ const char *string;
- /* this is used internally by jstrarray_ functions */
- jobjectArray arr_;
-} JSTRARRAY;
+ /* this is used internally by locked_string_ functions */
+ jstring jstr;
+} LOCKED_STRING;
-extern int jstrarray_lock(JSTRARRAY *, JNIEnv *jnienv, jobjectArray arr);
-extern void jstrarray_unlock(JSTRARRAY *, JNIEnv *jnienv); /* this unlocks and frees mem */
+extern int locked_string_get(LOCKED_STRING *, JNIEnv *jnienv, jstring jstr);
+extern void locked_string_put(LOCKED_STRING *, JNIEnv *jnienv); /* this unlocks and frees mem */
#endif /* !_JAVA_LOCKED_H_ */
diff --git a/bdb/libdb_java/java_util.c b/bdb/libdb_java/java_util.c
index f42ceafbee8..5a538ee0785 100644
--- a/bdb/libdb_java/java_util.c
+++ b/bdb/libdb_java/java_util.c
@@ -1,21 +1,19 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: java_util.c,v 11.17 2000/10/28 13:09:39 dda Exp $";
+static const char revid[] = "$Id: java_util.c,v 11.49 2002/09/13 03:09:30 mjc Exp $";
#endif /* not lint */
#include <jni.h>
#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include "db.h"
+#include "db_int.h"
#include "java_util.h"
#ifdef DB_WIN32
@@ -32,17 +30,22 @@ const char * const name_DB_EXCEPTION = "DbException";
const char * const name_DB_HASH_STAT = "DbHashStat";
const char * const name_DB_LOCK = "DbLock";
const char * const name_DB_LOCK_STAT = "DbLockStat";
+const char * const name_DB_LOCKNOTGRANTED_EX = "DbLockNotGrantedException";
+const char * const name_DB_LOGC = "DbLogc";
const char * const name_DB_LOG_STAT = "DbLogStat";
const char * const name_DB_LSN = "DbLsn";
const char * const name_DB_MEMORY_EX = "DbMemoryException";
const char * const name_DB_MPOOL_FSTAT = "DbMpoolFStat";
const char * const name_DB_MPOOL_STAT = "DbMpoolStat";
+const char * const name_DB_PREPLIST = "DbPreplist";
const char * const name_DB_QUEUE_STAT = "DbQueueStat";
+const char * const name_DB_REP_STAT = "DbRepStat";
const char * const name_DB_RUNRECOVERY_EX = "DbRunRecoveryException";
const char * const name_DBT = "Dbt";
const char * const name_DB_TXN = "DbTxn";
const char * const name_DB_TXN_STAT = "DbTxnStat";
const char * const name_DB_TXN_STAT_ACTIVE = "DbTxnStat$Active";
+const char * const name_DB_UTIL = "DbUtil";
const char * const name_DbAppendRecno = "DbAppendRecno";
const char * const name_DbBtreeCompare = "DbBtreeCompare";
const char * const name_DbBtreePrefix = "DbBtreePrefix";
@@ -50,24 +53,84 @@ const char * const name_DbDupCompare = "DbDupCompare";
const char * const name_DbEnvFeedback = "DbEnvFeedback";
const char * const name_DbErrcall = "DbErrcall";
const char * const name_DbHash = "DbHash";
+const char * const name_DbLockRequest = "DbLockRequest";
const char * const name_DbFeedback = "DbFeedback";
const char * const name_DbRecoveryInit = "DbRecoveryInit";
+const char * const name_DbRepTransport = "DbRepTransport";
+const char * const name_DbSecondaryKeyCreate = "DbSecondaryKeyCreate";
const char * const name_DbTxnRecover = "DbTxnRecover";
+const char * const name_RepElectResult = "DbEnv$RepElectResult";
+const char * const name_RepProcessMessage = "DbEnv$RepProcessMessage";
const char * const string_signature = "Ljava/lang/String;";
+jfieldID fid_Dbt_data;
+jfieldID fid_Dbt_offset;
+jfieldID fid_Dbt_size;
+jfieldID fid_Dbt_ulen;
+jfieldID fid_Dbt_dlen;
+jfieldID fid_Dbt_doff;
+jfieldID fid_Dbt_flags;
+jfieldID fid_Dbt_private_dbobj_;
+jfieldID fid_Dbt_must_create_data;
+jfieldID fid_DbLockRequest_op;
+jfieldID fid_DbLockRequest_mode;
+jfieldID fid_DbLockRequest_timeout;
+jfieldID fid_DbLockRequest_obj;
+jfieldID fid_DbLockRequest_lock;
+jfieldID fid_RepProcessMessage_envid;
+
/****************************************************************
*
* Utility functions used by "glue" functions.
- *
*/
-/* Get the private data from a Db* object that points back to a C DB_* object.
+/*
+ * Do any one time initialization, especially initializing any
+ * unchanging methodIds, fieldIds, etc.
+ */
+void one_time_init(JNIEnv *jnienv)
+{
+ jclass cl;
+
+ if ((cl = get_class(jnienv, name_DBT)) == NULL)
+ return; /* An exception has been posted. */
+ fid_Dbt_data = (*jnienv)->GetFieldID(jnienv, cl, "data", "[B");
+ fid_Dbt_offset = (*jnienv)->GetFieldID(jnienv, cl, "offset", "I");
+ fid_Dbt_size = (*jnienv)->GetFieldID(jnienv, cl, "size", "I");
+ fid_Dbt_ulen = (*jnienv)->GetFieldID(jnienv, cl, "ulen", "I");
+ fid_Dbt_dlen = (*jnienv)->GetFieldID(jnienv, cl, "dlen", "I");
+ fid_Dbt_doff = (*jnienv)->GetFieldID(jnienv, cl, "doff", "I");
+ fid_Dbt_flags = (*jnienv)->GetFieldID(jnienv, cl, "flags", "I");
+ fid_Dbt_must_create_data = (*jnienv)->GetFieldID(jnienv, cl,
+ "must_create_data", "Z");
+ fid_Dbt_private_dbobj_ =
+ (*jnienv)->GetFieldID(jnienv, cl, "private_dbobj_", "J");
+
+ if ((cl = get_class(jnienv, name_DbLockRequest)) == NULL)
+ return; /* An exception has been posted. */
+ fid_DbLockRequest_op = (*jnienv)->GetFieldID(jnienv, cl, "op", "I");
+ fid_DbLockRequest_mode = (*jnienv)->GetFieldID(jnienv, cl, "mode", "I");
+ fid_DbLockRequest_timeout =
+ (*jnienv)->GetFieldID(jnienv, cl, "timeout", "I");
+ fid_DbLockRequest_obj = (*jnienv)->GetFieldID(jnienv, cl, "obj",
+ "Lcom/sleepycat/db/Dbt;");
+ fid_DbLockRequest_lock = (*jnienv)->GetFieldID(jnienv, cl, "lock",
+ "Lcom/sleepycat/db/DbLock;");
+
+ if ((cl = get_class(jnienv, name_RepProcessMessage)) == NULL)
+ return; /* An exception has been posted. */
+ fid_RepProcessMessage_envid =
+ (*jnienv)->GetFieldID(jnienv, cl, "envid", "I");
+}
+
+/*
+ * Get the private data from a Db* object that points back to a C DB_* object.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
void *get_private_dbobj(JNIEnv *jnienv, const char *classname,
- jobject obj)
+ jobject obj)
{
jclass dbClass;
jfieldID id;
@@ -76,18 +139,20 @@ void *get_private_dbobj(JNIEnv *jnienv, const char *classname,
if (!obj)
return (0);
- dbClass = get_class(jnienv, classname);
+ if ((dbClass = get_class(jnienv, classname)) == NULL)
+ return (NULL); /* An exception has been posted. */
id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_dbobj_", "J");
lp.java_long = (*jnienv)->GetLongField(jnienv, obj, id);
return (lp.ptr);
}
-/* Set the private data in a Db* object that points back to a C DB_* object.
+/*
+ * Set the private data in a Db* object that points back to a C DB_* object.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
void set_private_dbobj(JNIEnv *jnienv, const char *classname,
- jobject obj, void *value)
+ jobject obj, void *value)
{
long_to_ptr lp;
jclass dbClass;
@@ -95,12 +160,14 @@ void set_private_dbobj(JNIEnv *jnienv, const char *classname,
lp.java_long = 0; /* no junk in case sizes mismatch */
lp.ptr = value;
- dbClass = get_class(jnienv, classname);
+ if ((dbClass = get_class(jnienv, classname)) == NULL)
+ return; /* An exception has been posted. */
id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_dbobj_", "J");
(*jnienv)->SetLongField(jnienv, obj, id, lp.java_long);
}
-/* Get the private data in a Db/DbEnv object that holds additional 'side data'.
+/*
+ * Get the private data in a Db/DbEnv object that holds additional 'side data'.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
@@ -112,15 +179,17 @@ void *get_private_info(JNIEnv *jnienv, const char *classname,
long_to_ptr lp;
if (!obj)
- return (0);
+ return (NULL);
- dbClass = get_class(jnienv, classname);
+ if ((dbClass = get_class(jnienv, classname)) == NULL)
+ return (NULL); /* An exception has been posted. */
id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_info_", "J");
lp.java_long = (*jnienv)->GetLongField(jnienv, obj, id);
return (lp.ptr);
}
-/* Set the private data in a Db/DbEnv object that holds additional 'side data'.
+/*
+ * Set the private data in a Db/DbEnv object that holds additional 'side data'.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
@@ -133,7 +202,8 @@ void set_private_info(JNIEnv *jnienv, const char *classname,
lp.java_long = 0; /* no junk in case sizes mismatch */
lp.ptr = value;
- dbClass = get_class(jnienv, classname);
+ if ((dbClass = get_class(jnienv, classname)) == NULL)
+ return; /* An exception has been posted. */
id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_info_", "J");
(*jnienv)->SetLongField(jnienv, obj, id, lp.java_long);
}
@@ -144,19 +214,48 @@ void set_private_info(JNIEnv *jnienv, const char *classname,
*/
jclass get_class(JNIEnv *jnienv, const char *classname)
{
- /* Note: PERFORMANCE: It should be possible to cache jclass's.
+ /*
+ * Note: PERFORMANCE: It should be possible to cache jclass's.
* If we do a NewGlobalRef on each one, we can keep them
* around in a table. A jclass is a jobject, and
* since NewGlobalRef returns a jobject, it isn't
* technically right, but it would likely work with
* most implementations. Possibly make it configurable.
*/
- char fullname[128] = DB_PACKAGE_NAME;
- strncat(fullname, classname, sizeof(fullname));
+ char fullname[128];
+
+ (void)snprintf(fullname, sizeof(fullname),
+ "%s%s", DB_PACKAGE_NAME, classname);
return ((*jnienv)->FindClass(jnienv, fullname));
}
-/* Set an individual field in a Db* object.
+/*
+ * Given a fully qualified name (e.g. "java.util.Hashtable")
+ * return the jclass object. If it can't be found, an
+ * exception is raised and NULL is return.
+ * This is appropriate to be used for classes that may
+ * not be present.
+ */
+jclass get_fully_qualified_class(JNIEnv *jnienv, const char *classname)
+{
+ jclass result;
+
+ result = ((*jnienv)->FindClass(jnienv, classname));
+ if (result == NULL) {
+ jclass cnfe;
+ char message[1024];
+
+ cnfe = (*jnienv)->FindClass(jnienv,
+ "java/lang/ClassNotFoundException");
+ strncpy(message, classname, sizeof(message));
+ strncat(message, ": class not found", sizeof(message));
+ (*jnienv)->ThrowNew(jnienv, cnfe, message);
+ }
+ return (result);
+}
+
+/*
+ * Set an individual field in a Db* object.
* The field must be a DB object type.
*/
void set_object_field(JNIEnv *jnienv, jclass class_of_this,
@@ -166,36 +265,39 @@ void set_object_field(JNIEnv *jnienv, jclass class_of_this,
char signature[512];
jfieldID id;
- strncpy(signature, "L", sizeof(signature));
- strncat(signature, DB_PACKAGE_NAME, sizeof(signature));
- strncat(signature, object_classname, sizeof(signature));
- strncat(signature, ";", sizeof(signature));
-
- id = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, signature);
+ (void)snprintf(signature, sizeof(signature),
+ "L%s%s;", DB_PACKAGE_NAME, object_classname);
+ id = (*jnienv)->GetFieldID(
+ jnienv, class_of_this, name_of_field, signature);
(*jnienv)->SetObjectField(jnienv, jthis, id, obj);
}
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be an integer type.
*/
void set_int_field(JNIEnv *jnienv, jclass class_of_this,
jobject jthis, const char *name_of_field, jint value)
{
- jfieldID id = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "I");
+ jfieldID id =
+ (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "I");
(*jnienv)->SetIntField(jnienv, jthis, id, value);
}
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be an integer type.
*/
void set_long_field(JNIEnv *jnienv, jclass class_of_this,
jobject jthis, const char *name_of_field, jlong value)
{
- jfieldID id = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "J");
+ jfieldID id = (*jnienv)->GetFieldID(jnienv, class_of_this,
+ name_of_field, "J");
(*jnienv)->SetLongField(jnienv, jthis, id, value);
}
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be an integer type.
*/
void set_lsn_field(JNIEnv *jnienv, jclass class_of_this,
@@ -205,89 +307,144 @@ void set_lsn_field(JNIEnv *jnienv, jclass class_of_this,
name_of_field, get_DbLsn(jnienv, value));
}
-/* Report an exception back to the java side.
+/*
+ * Report an exception back to the java side.
*/
-void report_exception(JNIEnv *jnienv, const char *text, int err,
- unsigned long expect_mask)
+void report_exception(JNIEnv *jnienv, const char *text,
+ int err, unsigned long expect_mask)
{
jstring textString;
jclass dbexcept;
jclass javaexcept;
- jmethodID constructId;
jthrowable obj;
textString = NULL;
dbexcept = NULL;
javaexcept = NULL;
- constructId = NULL;
- obj = NULL;
switch (err) {
- /* DB_JAVA_CALLBACK is returned by dbji_call_append_recno()
- * (the append_recno callback) when the Java version of the
- * callback has thrown an exception, and we want to pass the
- * exception on. The exception has already been thrown, we
+ /*
+ * DB_JAVA_CALLBACK is returned by
+ * dbji_call_append_recno() (the append_recno callback)
+ * when the Java version of the callback has thrown
+ * an exception, and we want to pass the exception on.
+ * The exception has already been thrown, we
* don't want to throw a new one.
*/
- case DB_JAVA_CALLBACK:
- break;
- case ENOMEM:
- dbexcept = get_class(jnienv, name_DB_MEMORY_EX);
- break;
- case ENOENT:
- /* In this case there is a corresponding standard java
- * exception type that we'll use. First we make sure
- * that the calling function expected this kind of error,
- * if not we give an 'internal error' DbException, since
- * we must not throw an exception type that isn't
- * declared in the signature.
- *
- * We'll make this a little more general if/when we add
- * more java standard exceptions.
- */
- if ((expect_mask & EXCEPTION_FILE_NOT_FOUND) == 0) {
- char errstr[1024];
-
- strncpy(errstr, "internal error: unexpected errno: ",
- sizeof(errstr));
- strncat(errstr, text, sizeof(errstr));
- textString = get_java_string(jnienv, errstr);
+ case DB_JAVA_CALLBACK:
+ break;
+ case ENOENT:
+ /*
+ * In this case there is a corresponding
+ * standard java exception type that we'll use.
+ * First we make sure that the calling function
+ * expected this kind of error, if not we give
+ * an 'internal error' DbException, since
+ * we must not throw an exception type that isn't
+ * declared in the signature.
+ *
+ * We'll make this a little more general if/when
+ * we add more java standard exceptions.
+ */
+ if ((expect_mask & EXCEPTION_FILE_NOT_FOUND) != 0) {
+ javaexcept = (*jnienv)->FindClass(jnienv,
+ "java/io/FileNotFoundException");
+ }
+ else {
+ char errstr[1024];
+
+ snprintf(errstr, sizeof(errstr),
+ "internal error: unexpected errno: %s",
+ text);
+ textString = get_java_string(jnienv,
+ errstr);
+ dbexcept = get_class(jnienv,
+ name_DB_EXCEPTION);
+ }
+ break;
+ case DB_RUNRECOVERY:
+ dbexcept = get_class(jnienv,
+ name_DB_RUNRECOVERY_EX);
+ break;
+ case DB_LOCK_DEADLOCK:
+ dbexcept = get_class(jnienv, name_DB_DEADLOCK_EX);
+ break;
+ default:
dbexcept = get_class(jnienv, name_DB_EXCEPTION);
- }
- else {
- javaexcept =
- (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException");
- }
- break;
- case DB_RUNRECOVERY:
- dbexcept = get_class(jnienv, name_DB_RUNRECOVERY_EX);
- break;
- case DB_LOCK_DEADLOCK:
- dbexcept = get_class(jnienv, name_DB_DEADLOCK_EX);
- break;
- default:
- dbexcept = get_class(jnienv, name_DB_EXCEPTION);
- break;
+ break;
}
if (dbexcept != NULL) {
if (textString == NULL)
textString = get_java_string(jnienv, text);
- constructId = (*jnienv)->GetMethodID(jnienv, dbexcept,
- "<init>",
- "(Ljava/lang/String;I)V");
- obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept,
- constructId, textString,
- err);
- (*jnienv)->Throw(jnienv, obj);
+ if ((obj = create_exception(jnienv, textString, err, dbexcept))
+ != NULL)
+ (*jnienv)->Throw(jnienv, obj);
+ /* Otherwise, an exception has been posted. */
}
- else if (javaexcept != NULL) {
- javaexcept =
- (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException");
+ else if (javaexcept != NULL)
(*jnienv)->ThrowNew(jnienv, javaexcept, text);
+ else
+ fprintf(stderr,
+ "report_exception: failed to create an exception\n");
+}
+
+/*
+ * Report an exception back to the java side, for the specific
+ * case of DB_LOCK_NOTGRANTED, as more things are added to the
+ * constructor of this type of exception.
+ */
+void report_notgranted_exception(JNIEnv *jnienv, const char *text,
+ db_lockop_t op, db_lockmode_t mode,
+ jobject jdbt, jobject jlock, int index)
+{
+ jstring textString;
+ jclass dbexcept;
+ jthrowable obj;
+ jmethodID mid;
+
+ if ((dbexcept = get_class(jnienv, name_DB_LOCKNOTGRANTED_EX)) == NULL)
+ return; /* An exception has been posted. */
+ textString = get_java_string(jnienv, text);
+
+ mid = (*jnienv)->GetMethodID(jnienv, dbexcept, "<init>",
+ "(Ljava/lang/String;II"
+ "Lcom/sleepycat/db/Dbt;"
+ "Lcom/sleepycat/db/DbLock;I)V");
+ if ((obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept,
+ mid, textString, op, mode, jdbt, jlock, index)) != NULL)
+ (*jnienv)->Throw(jnienv, obj);
+ else
+ fprintf(stderr,
+ "report_notgranted_exception: failed to create an exception\n");
+}
+
+/*
+ * Create an exception object and return it.
+ * The given class must have a constructor that has a
+ * constructor with args (java.lang.String text, int errno);
+ * DbException and its subclasses fit this bill.
+ */
+jobject create_exception(JNIEnv *jnienv, jstring text,
+ int err, jclass dbexcept)
+{
+ jthrowable obj;
+ jmethodID mid;
+
+ mid = (*jnienv)->GetMethodID(jnienv, dbexcept, "<init>",
+ "(Ljava/lang/String;I)V");
+ if (mid != NULL)
+ obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept, mid,
+ text, err);
+ else {
+ fprintf(stderr, "Cannot get exception init method ID!\n");
+ obj = NULL;
}
+
+ return (obj);
}
-/* Report an error via the errcall mechanism.
+/*
+ * Report an error via the errcall mechanism.
*/
void report_errcall(JNIEnv *jnienv, jobject errcall,
jstring prefix, const char *message)
@@ -296,7 +453,8 @@ void report_errcall(JNIEnv *jnienv, jobject errcall,
jclass errcall_class;
jstring msg;
- errcall_class = get_class(jnienv, name_DbErrcall);
+ if ((errcall_class = get_class(jnienv, name_DbErrcall)) == NULL)
+ return; /* An exception has been posted. */
msg = get_java_string(jnienv, message);
id = (*jnienv)->GetMethodID(jnienv, errcall_class,
@@ -311,7 +469,8 @@ void report_errcall(JNIEnv *jnienv, jobject errcall,
(*jnienv)->CallVoidMethod(jnienv, errcall, id, prefix, msg);
}
-/* If the object is null, report an exception and return false (0),
+/*
+ * If the object is null, report an exception and return false (0),
* otherwise return true (1).
*/
int verify_non_null(JNIEnv *jnienv, void *obj)
@@ -323,29 +482,70 @@ int verify_non_null(JNIEnv *jnienv, void *obj)
return (1);
}
-/* If the error code is non-zero, report an exception and return false (0),
+/*
+ * If the error code is non-zero, report an exception and return false (0),
* otherwise return true (1).
*/
int verify_return(JNIEnv *jnienv, int err, unsigned long expect_mask)
{
if (err == 0)
- return 1;
+ return (1);
report_exception(jnienv, db_strerror(err), err, expect_mask);
- return 0;
+ return (0);
}
-/* Create an object of the given class, calling its default constructor.
+/*
+ * Verify that there was no memory error due to undersized Dbt.
+ * If there is report a DbMemoryException, with the Dbt attached
+ * and return false (0), otherwise return true (1).
+ */
+int verify_dbt(JNIEnv *jnienv, int err, LOCKED_DBT *ldbt)
+{
+ DBT *dbt;
+ jobject exception;
+ jstring text;
+ jclass dbexcept;
+ jmethodID mid;
+
+ if (err != ENOMEM)
+ return (1);
+
+ dbt = &ldbt->javainfo->dbt;
+ if (!F_ISSET(dbt, DB_DBT_USERMEM) || dbt->size <= dbt->ulen)
+ return (1);
+
+ /* Create/throw an exception of type DbMemoryException */
+ if ((dbexcept = get_class(jnienv, name_DB_MEMORY_EX)) == NULL)
+ return (1); /* An exception has been posted. */
+ text = get_java_string(jnienv,
+ "Dbt not large enough for available data");
+ exception = create_exception(jnienv, text, ENOMEM, dbexcept);
+
+ /* Attach the dbt to the exception */
+ mid = (*jnienv)->GetMethodID(jnienv, dbexcept, "set_dbt",
+ "(L" DB_PACKAGE_NAME "Dbt;)V");
+ (*jnienv)->CallVoidMethod(jnienv, exception, mid, ldbt->jdbt);
+ (*jnienv)->Throw(jnienv, exception);
+ return (0);
+}
+
+/*
+ * Create an object of the given class, calling its default constructor.
*/
jobject create_default_object(JNIEnv *jnienv, const char *class_name)
{
- jclass dbclass = get_class(jnienv, class_name);
- jmethodID id = (*jnienv)->GetMethodID(jnienv, dbclass, "<init>", "()V");
- jobject object = (*jnienv)->NewObject(jnienv, dbclass, id);
- return (object);
+ jmethodID id;
+ jclass dbclass;
+
+ if ((dbclass = get_class(jnienv, class_name)) == NULL)
+ return (NULL); /* An exception has been posted. */
+ id = (*jnienv)->GetMethodID(jnienv, dbclass, "<init>", "()V");
+ return ((*jnienv)->NewObject(jnienv, dbclass, id));
}
-/* Convert an DB object to a Java encapsulation of that object.
+/*
+ * Convert an DB object to a Java encapsulation of that object.
* Note: This implementation creates a new Java object on each call,
* so it is generally useful when a new DB object has just been created.
*/
@@ -361,20 +561,24 @@ jobject convert_object(JNIEnv *jnienv, const char *class_name, void *dbobj)
return (jo);
}
-/* Create a copy of the string
+/*
+ * Create a copy of the string
*/
char *dup_string(const char *str)
{
int len;
char *retval;
+ int err;
len = strlen(str) + 1;
- retval = (char *)malloc(sizeof(char)*len);
+ if ((err = __os_malloc(NULL, sizeof(char)*len, &retval)) != 0)
+ return (NULL);
strncpy(retval, str, len);
return (retval);
}
-/* Create a java string from the given string
+/*
+ * Create a java string from the given string
*/
jstring get_java_string(JNIEnv *jnienv, const char* string)
{
@@ -383,21 +587,23 @@ jstring get_java_string(JNIEnv *jnienv, const char* string)
return ((*jnienv)->NewStringUTF(jnienv, string));
}
-/* Create a malloc'ed copy of the java string.
+/*
+ * Create a copy of the java string using __os_malloc.
* Caller must free it.
*/
char *get_c_string(JNIEnv *jnienv, jstring jstr)
{
- const jbyte *utf;
+ const char *utf;
char *retval;
utf = (*jnienv)->GetStringUTFChars(jnienv, jstr, NULL);
- retval = dup_string((const char *)utf);
+ retval = dup_string(utf);
(*jnienv)->ReleaseStringUTFChars(jnienv, jstr, utf);
- return retval;
+ return (retval);
}
-/* Convert a java object to the various C pointers they represent.
+/*
+ * Convert a java object to the various C pointers they represent.
*/
DB *get_DB(JNIEnv *jnienv, jobject obj)
{
@@ -406,7 +612,8 @@ DB *get_DB(JNIEnv *jnienv, jobject obj)
DB_BTREE_STAT *get_DB_BTREE_STAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_BTREE_STAT *)get_private_dbobj(jnienv, name_DB_BTREE_STAT, obj));
+ return ((DB_BTREE_STAT *)
+ get_private_dbobj(jnienv, name_DB_BTREE_STAT, obj));
}
DBC *get_DBC(JNIEnv *jnienv, jobject obj)
@@ -426,7 +633,8 @@ DB_ENV_JAVAINFO *get_DB_ENV_JAVAINFO(JNIEnv *jnienv, jobject obj)
DB_HASH_STAT *get_DB_HASH_STAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_HASH_STAT *)get_private_dbobj(jnienv, name_DB_HASH_STAT, obj));
+ return ((DB_HASH_STAT *)
+ get_private_dbobj(jnienv, name_DB_HASH_STAT, obj));
}
DB_JAVAINFO *get_DB_JAVAINFO(JNIEnv *jnienv, jobject obj)
@@ -439,29 +647,71 @@ DB_LOCK *get_DB_LOCK(JNIEnv *jnienv, jobject obj)
return ((DB_LOCK *)get_private_dbobj(jnienv, name_DB_LOCK, obj));
}
-DB_LOG_STAT *get_DB_LOG_STAT(JNIEnv *jnienv, jobject obj)
+DB_LOGC *get_DB_LOGC(JNIEnv *jnienv, jobject obj)
{
- return ((DB_LOG_STAT *)get_private_dbobj(jnienv, name_DB_LOG_STAT, obj));
+ return ((DB_LOGC *)get_private_dbobj(jnienv, name_DB_LOGC, obj));
}
-DB_LSN *get_DB_LSN(JNIEnv *jnienv, jobject obj)
+DB_LOG_STAT *get_DB_LOG_STAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_LSN *)get_private_dbobj(jnienv, name_DB_LSN, obj));
+ return ((DB_LOG_STAT *)
+ get_private_dbobj(jnienv, name_DB_LOG_STAT, obj));
+}
+
+DB_LSN *get_DB_LSN(JNIEnv *jnienv, /* DbLsn */ jobject obj) {
+ /*
+ * DbLsns that are created from within java (new DbLsn()) rather
+ * than from within C (get_DbLsn()) may not have a "private" DB_LSN
+ * structure allocated for them yet. We can't do this in the
+ * actual constructor (init_lsn()), because there's no way to pass
+ * in an initializing value in, and because the get_DbLsn()/
+ * convert_object() code path needs a copy of the pointer before
+ * the constructor gets called. Thus, get_DbLsn() allocates and
+ * fills a DB_LSN for the object it's about to create.
+ *
+ * Since "new DbLsn()" may reasonably be passed as an argument to
+ * functions such as DbEnv.log_put(), though, we need to make sure
+ * that DB_LSN's get allocated when the object was created from
+ * Java, too. Here, we lazily allocate a new private DB_LSN if
+ * and only if it turns out that we don't already have one.
+ *
+ * The only exception is if the DbLsn object is a Java null
+ * (in which case the jobject will also be NULL). Then a NULL
+ * DB_LSN is legitimate.
+ */
+ DB_LSN *lsnp;
+ int err;
+
+ if (obj == NULL)
+ return (NULL);
+
+ lsnp = (DB_LSN *)get_private_dbobj(jnienv, name_DB_LSN, obj);
+ if (lsnp == NULL) {
+ if ((err = __os_malloc(NULL, sizeof(DB_LSN), &lsnp)) != 0)
+ return (NULL);
+ memset(lsnp, 0, sizeof(DB_LSN));
+ set_private_dbobj(jnienv, name_DB_LSN, obj, lsnp);
+ }
+
+ return (lsnp);
}
DB_MPOOL_FSTAT *get_DB_MPOOL_FSTAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_MPOOL_FSTAT *)get_private_dbobj(jnienv, name_DB_MPOOL_FSTAT, obj));
+ return ((DB_MPOOL_FSTAT *)
+ get_private_dbobj(jnienv, name_DB_MPOOL_FSTAT, obj));
}
DB_MPOOL_STAT *get_DB_MPOOL_STAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_MPOOL_STAT *)get_private_dbobj(jnienv, name_DB_MPOOL_STAT, obj));
+ return ((DB_MPOOL_STAT *)
+ get_private_dbobj(jnienv, name_DB_MPOOL_STAT, obj));
}
DB_QUEUE_STAT *get_DB_QUEUE_STAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_QUEUE_STAT *)get_private_dbobj(jnienv, name_DB_QUEUE_STAT, obj));
+ return ((DB_QUEUE_STAT *)
+ get_private_dbobj(jnienv, name_DB_QUEUE_STAT, obj));
}
DB_TXN *get_DB_TXN(JNIEnv *jnienv, jobject obj)
@@ -471,7 +721,8 @@ DB_TXN *get_DB_TXN(JNIEnv *jnienv, jobject obj)
DB_TXN_STAT *get_DB_TXN_STAT(JNIEnv *jnienv, jobject obj)
{
- return ((DB_TXN_STAT *)get_private_dbobj(jnienv, name_DB_TXN_STAT, obj));
+ return ((DB_TXN_STAT *)
+ get_private_dbobj(jnienv, name_DB_TXN_STAT, obj));
}
DBT *get_DBT(JNIEnv *jnienv, jobject obj)
@@ -490,7 +741,8 @@ DBT_JAVAINFO *get_DBT_JAVAINFO(JNIEnv *jnienv, jobject obj)
return ((DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj));
}
-/* Convert a C pointer to the various Java objects they represent.
+/*
+ * Convert a C pointer to the various Java objects they represent.
*/
jobject get_DbBtreeStat(JNIEnv *jnienv, DB_BTREE_STAT *dbobj)
{
@@ -507,27 +759,109 @@ jobject get_DbHashStat(JNIEnv *jnienv, DB_HASH_STAT *dbobj)
return (convert_object(jnienv, name_DB_HASH_STAT, dbobj));
}
+jobject get_DbLogc(JNIEnv *jnienv, DB_LOGC *dbobj)
+{
+ return (convert_object(jnienv, name_DB_LOGC, dbobj));
+}
+
jobject get_DbLogStat(JNIEnv *jnienv, DB_LOG_STAT *dbobj)
{
return (convert_object(jnienv, name_DB_LOG_STAT, dbobj));
}
-/* LSNs are different since they are really normally
+/*
+ * LSNs are different since they are really normally
* treated as by-value objects. We actually create
* a pointer to the LSN and store that, deleting it
* when the LSN is GC'd.
*/
jobject get_DbLsn(JNIEnv *jnienv, DB_LSN dbobj)
{
- DB_LSN *lsnp = (DB_LSN *)malloc(sizeof(DB_LSN));
+ DB_LSN *lsnp;
+ int err;
+
+ if ((err = __os_malloc(NULL, sizeof(DB_LSN), &lsnp)) != 0)
+ return (NULL);
+
memset(lsnp, 0, sizeof(DB_LSN));
*lsnp = dbobj;
return (convert_object(jnienv, name_DB_LSN, lsnp));
}
-jobject get_Dbt(JNIEnv *jnienv, DBT *dbt)
+/*
+ * Shared code for get_Dbt and get_const_Dbt.
+ *
+ * XXX
+ * Currently we make no distinction in implementation of these
+ * two kinds of Dbts, although in the future we may want to.
+ * (It's probably easier to make the optimizations listed below
+ * with readonly Dbts).
+ *
+ * Dbt's created via this function are only used for a short lifetime,
+ * during callback functions. In the future, we should consider taking
+ * advantage of this by having a pool of Dbt objects instead of creating
+ * new ones each time. Because of multithreading, we may need an
+ * arbitrary number. We might also have sharing of the byte arrays
+ * used by the Dbts.
+ */
+static jobject get_Dbt_shared(JNIEnv *jnienv, const DBT *dbt, int readonly,
+ DBT_JAVAINFO **ret_info)
+{
+ jobject jdbt;
+ DBT_JAVAINFO *dbtji;
+
+ COMPQUIET(readonly, 0);
+
+ /* A NULL DBT should become a null Dbt. */
+ if (dbt == NULL)
+ return (NULL);
+
+ /*
+ * Note that a side effect of creating a Dbt object
+ * is the creation of the attached DBT_JAVAINFO object
+ * (see the native implementation of Dbt.init())
+ * A DBT_JAVAINFO object contains its own DBT.
+ */
+ jdbt = create_default_object(jnienv, name_DBT);
+ dbtji = get_DBT_JAVAINFO(jnienv, jdbt);
+ memcpy(&dbtji->dbt, dbt, sizeof(DBT));
+
+ /*
+ * Set the boolean indicator so that the Java side knows to
+ * call back when it wants to look at the array. This avoids
+ * needlessly creating/copying arrays that may never be looked at.
+ */
+ (*jnienv)->SetBooleanField(jnienv, jdbt, fid_Dbt_must_create_data, 1);
+ (*jnienv)->SetIntField(jnienv, jdbt, fid_Dbt_size, dbt->size);
+
+ if (ret_info != NULL)
+ *ret_info = dbtji;
+ return (jdbt);
+}
+
+/*
+ * Get a writeable Dbt.
+ *
+ * Currently we're sharing code with get_const_Dbt.
+ * It really shouldn't be this way, we have a DBT that we can
+ * change, and have some mechanism for copying back
+ * any changes to the original DBT.
+ */
+jobject get_Dbt(JNIEnv *jnienv, DBT *dbt,
+ DBT_JAVAINFO **ret_info)
+{
+ return (get_Dbt_shared(jnienv, dbt, 0, ret_info));
+}
+
+/*
+ * Get a Dbt that we promise not to change, or at least
+ * if there are changes, they don't matter and won't get
+ * seen by anyone.
+ */
+jobject get_const_Dbt(JNIEnv *jnienv, const DBT *dbt,
+ DBT_JAVAINFO **ret_info)
{
- return (convert_object(jnienv, name_DBT, dbt));
+ return (get_Dbt_shared(jnienv, dbt, 1, ret_info));
}
jobject get_DbMpoolFStat(JNIEnv *jnienv, DB_MPOOL_FSTAT *dbobj)
diff --git a/bdb/libdb_java/java_util.h b/bdb/libdb_java/java_util.h
index eb47dc67629..08187f6b51f 100644
--- a/bdb/libdb_java/java_util.h
+++ b/bdb/libdb_java/java_util.h
@@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: java_util.h,v 11.22 2001/01/11 18:19:53 bostic Exp $
+ * $Id: java_util.h,v 11.44 2002/08/29 14:22:24 margo Exp $
*/
#ifndef _JAVA_UTIL_H_
@@ -12,7 +12,8 @@
#ifdef _MSC_VER
-/* These are level 4 warnings that are explicitly disabled.
+/*
+ * These are level 4 warnings that are explicitly disabled.
* With Visual C++, by default you do not see above level 3 unless
* you use /W4. But we like to compile with the highest level
* warnings to catch other errors.
@@ -35,15 +36,15 @@
#include "db_config.h"
#include "db.h"
+#include "db_int.h"
+#include <jni.h>
#include "java_info.h"
#include "java_locked.h"
-#include <jni.h>
#include <string.h> /* needed for memset */
#define DB_PACKAGE_NAME "com/sleepycat/db/"
-/* Union to convert longs to pointers (see {get,set}_private_dbobj).
- */
+/* Union to convert longs to pointers (see {get,set}_private_dbobj). */
typedef union {
jlong java_long;
void *ptr;
@@ -52,13 +53,13 @@ typedef union {
/****************************************************************
*
* Utility functions and definitions used by "glue" functions.
- *
*/
#define NOT_IMPLEMENTED(str) \
report_exception(jnienv, str /*concatenate*/ ": not implemented", 0)
-/* Get, delete a global reference.
+/*
+ * Get, delete a global reference.
* Making this operation a function call allows for
* easier tracking for debugging. Global references
* are mostly grabbed at 'open' and 'close' points,
@@ -78,7 +79,7 @@ static void wrdebug(const char *str)
static jobject debug_new_global_ref(JNIEnv *jnienv, jobject obj, const char *s)
{
wrdebug(s);
- return (*jnienv)->NewGlobalRef(jnienv, obj);
+ return ((*jnienv)->NewGlobalRef(jnienv, obj));
}
static void debug_delete_global_ref(JNIEnv *jnienv, jobject obj, const char *s)
@@ -97,28 +98,45 @@ static void debug_delete_global_ref(JNIEnv *jnienv, jobject obj, const char *s)
#define wrdebug(x)
#endif
-/* Get the private data from a Db* object that points back to a C DB_* object.
+/*
+ * Do any one time initialization, especially initializing any
+ * unchanging methodIds, fieldIds, etc.
+ */
+void one_time_init(JNIEnv *jnienv);
+
+/*
+ * Get the current JNIEnv from the java VM.
+ * If the jvm argument is null, uses the default
+ * jvm stored during the first invocation.
+ */
+JNIEnv *get_jnienv(JavaVM *jvm);
+
+/*
+ * Get the private data from a Db* object that points back to a C DB_* object.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
void *get_private_dbobj(JNIEnv *jnienv, const char *classname,
jobject obj);
-/* Set the private data in a Db* object that points back to a C DB_* object.
+/*
+ * Set the private data in a Db* object that points back to a C DB_* object.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
void set_private_dbobj(JNIEnv *jnienv, const char *classname,
jobject obj, void *value);
-/* Get the private data in a Db/DbEnv object that holds additional 'side data'.
+/*
+ * Get the private data in a Db/DbEnv object that holds additional 'side data'.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
void *get_private_info(JNIEnv *jnienv, const char *classname,
jobject obj);
-/* Set the private data in a Db/DbEnv object that holds additional 'side data'.
+/*
+ * Set the private data in a Db/DbEnv object that holds additional 'side data'.
* The private data is stored in the object as a Java long (64 bits),
* which is long enough to store a pointer on current architectures.
*/
@@ -126,84 +144,126 @@ void set_private_info(JNIEnv *jnienv, const char *classname,
jobject obj, void *value);
/*
- * Given a non-qualified name (e.g. "foo"), get the class handl
+ * Given a non-qualified name (e.g. "foo"), get the class handle
* for the fully qualified name (e.g. "com.sleepycat.db.foo")
*/
jclass get_class(JNIEnv *jnienv, const char *classname);
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be a DB object type.
*/
void set_object_field(JNIEnv *jnienv, jclass class_of_this,
jobject jthis, const char *object_classname,
const char *name_of_field, jobject obj);
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be an integer type.
*/
void set_int_field(JNIEnv *jnienv, jclass class_of_this,
jobject jthis, const char *name_of_field, jint value);
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be an integer type.
*/
void set_long_field(JNIEnv *jnienv, jclass class_of_this,
jobject jthis, const char *name_of_field, jlong value);
-/* Set an individual field in a Db* object.
+/*
+ * Set an individual field in a Db* object.
* The field must be an DbLsn type.
*/
void set_lsn_field(JNIEnv *jnienv, jclass class_of_this,
jobject jthis, const char *name_of_field, DB_LSN value);
-/* Values of expect_mask
+/*
+ * Values of flags for verify_return() and report_exception().
+ * These indicate what sort of exceptions the method may throw
+ * (in addition to DbException).
+ */
+static const u_int32_t EXCEPTION_FILE_NOT_FOUND = 0x0001; /*FileNotFound*/
+
+/*
+ * Report an exception back to the java side.
+ */
+void report_exception(JNIEnv *jnienv, const char *text,
+ int err, unsigned long expect_mask);
+
+/*
+ * Report an exception back to the java side, for the specific
+ * case of DB_LOCK_NOTGRANTED, as more things are added to the
+ * constructor of this type of exception.
*/
-static const int EXCEPTION_FILE_NOT_FOUND = 0x0001;
+void report_notgranted_exception(JNIEnv *jnienv, const char *text,
+ db_lockop_t op, db_lockmode_t mode,
+ jobject jdbt, jobject jlock, int index);
-/* Report an exception back to the java side.
+/*
+ * Create an exception object and return it.
+ * The given class must have a constructor that has a
+ * constructor with args (java.lang.String text, int errno);
+ * DbException and its subclasses fit this bill.
*/
-void report_exception(JNIEnv *jnienv, const char *text, int err,
- unsigned long expect_mask);
+jobject create_exception(JNIEnv *jnienv, jstring text,
+ int err, jclass dbexcept);
-/* Report an error via the errcall mechanism.
+/*
+ * Report an error via the errcall mechanism.
*/
void report_errcall(JNIEnv *jnienv, jobject errcall,
jstring prefix, const char *message);
-/* If the object is null, report an exception and return false (0),
+/*
+ * If the object is null, report an exception and return false (0),
* otherwise return true (1).
*/
int verify_non_null(JNIEnv *jnienv, void *obj);
-/* If the error code is non-zero, report an exception and return false (0),
+/*
+ * If the error code is non-zero, report an exception and return false (0),
* otherwise return true (1).
*/
-int verify_return(JNIEnv *jnienv, int err, unsigned long expect_mask);
+int verify_return(JNIEnv *jnienv, int err, unsigned long flags);
-/* Create an object of the given class, calling its default constructor.
+/*
+ * Verify that there was no memory error due to undersized Dbt.
+ * If there is report a DbMemoryException, with the Dbt attached
+ * and return false (0), otherwise return true (1).
+ */
+int verify_dbt(JNIEnv *jnienv, int err, LOCKED_DBT *locked_dbt);
+
+/*
+ * Create an object of the given class, calling its default constructor.
*/
jobject create_default_object(JNIEnv *jnienv, const char *class_name);
-/* Convert an DB object to a Java encapsulation of that object.
+/*
+ * Create a Dbt object, , calling its default constructor.
+ */
+jobject create_dbt(JNIEnv *jnienv, const char *class_name);
+
+/*
+ * Convert an DB object to a Java encapsulation of that object.
* Note: This implementation creates a new Java object on each call,
* so it is generally useful when a new DB object has just been created.
*/
jobject convert_object(JNIEnv *jnienv, const char *class_name, void *dbobj);
-/* Create a copy of the string
- */
-char *dup_string(const char *str);
-
-/* Create a malloc'ed copy of the java string.
+/*
+ * Create a copy of the java string using __os_malloc.
* Caller must free it.
*/
char *get_c_string(JNIEnv *jnienv, jstring jstr);
-/* Create a java string from the given string
+/*
+ * Create a java string from the given string
*/
jstring get_java_string(JNIEnv *jnienv, const char* string);
-/* Convert a java object to the various C pointers they represent.
+/*
+ * Convert a java object to the various C pointers they represent.
*/
DB *get_DB (JNIEnv *jnienv, jobject obj);
DB_BTREE_STAT *get_DB_BTREE_STAT (JNIEnv *jnienv, jobject obj);
@@ -213,6 +273,7 @@ DB_ENV_JAVAINFO *get_DB_ENV_JAVAINFO (JNIEnv *jnienv, jobject obj);
DB_HASH_STAT *get_DB_HASH_STAT (JNIEnv *jnienv, jobject obj);
DB_JAVAINFO *get_DB_JAVAINFO (JNIEnv *jnienv, jobject obj);
DB_LOCK *get_DB_LOCK (JNIEnv *jnienv, jobject obj);
+DB_LOGC *get_DB_LOGC (JNIEnv *jnienv, jobject obj);
DB_LOG_STAT *get_DB_LOG_STAT (JNIEnv *jnienv, jobject obj);
DB_LSN *get_DB_LSN (JNIEnv *jnienv, jobject obj);
DB_MPOOL_FSTAT *get_DB_MPOOL_FSTAT(JNIEnv *jnienv, jobject obj);
@@ -223,17 +284,20 @@ DB_TXN_STAT *get_DB_TXN_STAT (JNIEnv *jnienv, jobject obj);
DBT *get_DBT (JNIEnv *jnienv, jobject obj);
DBT_JAVAINFO *get_DBT_JAVAINFO (JNIEnv *jnienv, jobject obj);
-/* From a C object, create a Java object.
+/*
+ * From a C object, create a Java object.
*/
jobject get_DbBtreeStat (JNIEnv *jnienv, DB_BTREE_STAT *dbobj);
jobject get_Dbc (JNIEnv *jnienv, DBC *dbobj);
jobject get_DbHashStat (JNIEnv *jnienv, DB_HASH_STAT *dbobj);
+jobject get_DbLogc (JNIEnv *jnienv, DB_LOGC *dbobj);
jobject get_DbLogStat (JNIEnv *jnienv, DB_LOG_STAT *dbobj);
jobject get_DbLsn (JNIEnv *jnienv, DB_LSN dbobj);
jobject get_DbMpoolStat (JNIEnv *jnienv, DB_MPOOL_STAT *dbobj);
jobject get_DbMpoolFStat (JNIEnv *jnienv, DB_MPOOL_FSTAT *dbobj);
jobject get_DbQueueStat (JNIEnv *jnienv, DB_QUEUE_STAT *dbobj);
-jobject get_Dbt (JNIEnv *jnienv, DBT *dbt);
+jobject get_const_Dbt (JNIEnv *jnienv, const DBT *dbt, DBT_JAVAINFO **retp);
+jobject get_Dbt (JNIEnv *jnienv, DBT *dbt, DBT_JAVAINFO **retp);
jobject get_DbTxn (JNIEnv *jnienv, DB_TXN *dbobj);
jobject get_DbTxnStat (JNIEnv *jnienv, DB_TXN_STAT *dbobj);
@@ -247,17 +311,22 @@ extern const char * const name_DB_EXCEPTION;
extern const char * const name_DB_HASH_STAT;
extern const char * const name_DB_LOCK;
extern const char * const name_DB_LOCK_STAT;
+extern const char * const name_DB_LOGC;
extern const char * const name_DB_LOG_STAT;
extern const char * const name_DB_LSN;
extern const char * const name_DB_MEMORY_EX;
extern const char * const name_DB_MPOOL_FSTAT;
extern const char * const name_DB_MPOOL_STAT;
+extern const char * const name_DB_LOCKNOTGRANTED_EX;
+extern const char * const name_DB_PREPLIST;
extern const char * const name_DB_QUEUE_STAT;
+extern const char * const name_DB_REP_STAT;
extern const char * const name_DB_RUNRECOVERY_EX;
extern const char * const name_DBT;
extern const char * const name_DB_TXN;
extern const char * const name_DB_TXN_STAT;
extern const char * const name_DB_TXN_STAT_ACTIVE;
+extern const char * const name_DB_UTIL;
extern const char * const name_DbAppendRecno;
extern const char * const name_DbBtreeCompare;
extern const char * const name_DbBtreePrefix;
@@ -267,93 +336,106 @@ extern const char * const name_DbErrcall;
extern const char * const name_DbFeedback;
extern const char * const name_DbHash;
extern const char * const name_DbRecoveryInit;
+extern const char * const name_DbRepTransport;
+extern const char * const name_DbSecondaryKeyCreate;
extern const char * const name_DbTxnRecover;
+extern const char * const name_RepElectResult;
+extern const char * const name_RepProcessMessage;
extern const char * const string_signature;
-#define JAVADB_RO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \
-JNIEXPORT j_fieldtype JNICALL \
- Java_com_sleepycat_db_##j_class##_get_1##j_field \
- (JNIEnv *jnienv, jobject jthis) \
-{ \
- c_type *db_this = get_##c_type(jnienv, jthis); \
- \
- if (verify_non_null(jnienv, db_this)) { \
- return db_this->c_field; \
- } \
- return 0; \
+extern jfieldID fid_Dbt_data;
+extern jfieldID fid_Dbt_offset;
+extern jfieldID fid_Dbt_size;
+extern jfieldID fid_Dbt_ulen;
+extern jfieldID fid_Dbt_dlen;
+extern jfieldID fid_Dbt_doff;
+extern jfieldID fid_Dbt_flags;
+extern jfieldID fid_Dbt_must_create_data;
+extern jfieldID fid_DbLockRequest_op;
+extern jfieldID fid_DbLockRequest_mode;
+extern jfieldID fid_DbLockRequest_timeout;
+extern jfieldID fid_DbLockRequest_obj;
+extern jfieldID fid_DbLockRequest_lock;
+extern jfieldID fid_RepProcessMessage_envid;
+
+#define JAVADB_ARGS JNIEnv *jnienv, jobject jthis
+
+#define JAVADB_GET_FLD(j_class, j_fieldtype, j_field, c_type, c_field) \
+JNIEXPORT j_fieldtype JNICALL \
+ Java_com_sleepycat_db_##j_class##_get_1##j_field \
+ (JAVADB_ARGS) \
+{ \
+ c_type *db= get_##c_type(jnienv, jthis); \
+ \
+ if (verify_non_null(jnienv, db)) \
+ return (db->c_field); \
+ return (0); \
}
-#define JAVADB_WO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \
-JNIEXPORT void JNICALL \
- Java_com_sleepycat_db_##j_class##_set_1##j_field \
- (JNIEnv *jnienv, jobject jthis, j_fieldtype value) \
-{ \
- c_type *db_this = get_##c_type(jnienv, jthis); \
- \
- if (verify_non_null(jnienv, db_this)) { \
- db_this->c_field = value; \
- } \
+#define JAVADB_SET_FLD(j_class, j_fieldtype, j_field, c_type, c_field) \
+JNIEXPORT void JNICALL \
+ Java_com_sleepycat_db_##j_class##_set_1##j_field \
+ (JAVADB_ARGS, j_fieldtype value) \
+{ \
+ c_type *db= get_##c_type(jnienv, jthis); \
+ \
+ if (verify_non_null(jnienv, db)) \
+ db->c_field = value; \
}
-/* This is a variant of the JAVADB_WO_ACCESS macro to define a simple set_
- * method using a C "method" call. These should be used with set_
- * methods that cannot invoke java 'callbacks' (no set_ method currently
- * does that). That assumption allows us to optimize (and simplify)
- * by not calling API_BEGIN/END macros.
- */
-#define JAVADB_WO_ACCESS_METHOD(j_class, j_fieldtype, \
- j_field, c_type, c_field) \
-JNIEXPORT void JNICALL \
- Java_com_sleepycat_db_##j_class##_set_1##j_field \
- (JNIEnv *jnienv, jobject jthis, j_fieldtype value) \
-{ \
- c_type *db_this; \
- int err; \
- \
- db_this = get_##c_type(jnienv, jthis); \
- if (verify_non_null(jnienv, db_this)) { \
- err = db_this->set_##c_field(db_this, value); \
- verify_return(jnienv, err, 0); \
- } \
+#define JAVADB_METHOD(_meth, _argspec, c_type, c_meth, _args) \
+JNIEXPORT void JNICALL Java_com_sleepycat_db_##_meth _argspec \
+{ \
+ c_type *c_this = get_##c_type(jnienv, jthis); \
+ int ret; \
+ \
+ if (!verify_non_null(jnienv, c_this)) \
+ return; \
+ ret = c_this->c_meth _args; \
+ if (!DB_RETOK_STD(ret)) \
+ report_exception(jnienv, db_strerror(ret), ret, 0); \
}
-#define JAVADB_RW_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \
- JAVADB_RO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \
- JAVADB_WO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field)
-
-#define JAVADB_WO_ACCESS_STRING(j_class, j_field, c_type, c_field) \
-JNIEXPORT void JNICALL \
- Java_com_sleepycat_db_##j_class##_set_1##j_field \
- (JNIEnv *jnienv, jobject jthis, jstring value) \
-{ \
- c_type *db_this; \
- int err; \
- \
- db_this = get_##c_type(jnienv, jthis); \
- if (verify_non_null(jnienv, db_this)) { \
- err = db_this->set_##c_field(db_this, \
- (*jnienv)->GetStringUTFChars(jnienv, value, NULL)); \
- verify_return(jnienv, err, 0); \
- } \
+#define JAVADB_METHOD_INT(_meth, _argspec, c_type, c_meth, _args, _retok) \
+JNIEXPORT jint JNICALL Java_com_sleepycat_db_##_meth _argspec \
+{ \
+ c_type *c_this = get_##c_type(jnienv, jthis); \
+ int ret; \
+ \
+ if (!verify_non_null(jnienv, c_this)) \
+ return (0); \
+ ret = c_this->c_meth _args; \
+ if (!_retok(ret)) \
+ report_exception(jnienv, db_strerror(ret), ret, 0); \
+ return ((jint)ret); \
}
-#define JAVADB_API_BEGIN(db, jthis) \
- if ((db) != NULL) \
- ((DB_JAVAINFO*)(db)->cj_internal)->jdbref_ = \
- ((DB_ENV_JAVAINFO*)((db)->dbenv->cj_internal))->jdbref_ = (jthis)
+#define JAVADB_SET_METH(j_class, j_type, j_fld, c_type, c_field) \
+ JAVADB_METHOD(j_class##_set_1##j_fld, (JAVADB_ARGS, j_type val), c_type, \
+ set_##c_field, (c_this, val))
-#define JAVADB_API_END(db) \
- if ((db) != NULL) \
- ((DB_JAVAINFO*)(db)->cj_internal)->jdbref_ = \
- ((DB_ENV_JAVAINFO*)((db)->dbenv->cj_internal))->jdbref_ = 0
+#define JAVADB_SET_METH_STR(j_class, j_fld, c_type, c_field) \
+ JAVADB_METHOD(j_class##_set_1##j_fld, (JAVADB_ARGS, jstring val), c_type, \
+ set_##c_field, (c_this, (*jnienv)->GetStringUTFChars(jnienv, val, NULL)))
-#define JAVADB_ENV_API_BEGIN(dbenv, jthis) \
- if ((dbenv) != NULL) \
- ((DB_ENV_JAVAINFO*)((dbenv)->cj_internal))->jenvref_ = (jthis)
-#define JAVADB_ENV_API_END(dbenv) \
- if ((dbenv) != NULL) \
- ((DB_ENV_JAVAINFO*)((dbenv)->cj_internal))->jenvref_ = 0
+/*
+ * These macros are used by code generated by the s_java script.
+ */
+#define JAVADB_STAT_INT(env, cl, jobj, statp, name) \
+ set_int_field(jnienv, cl, jobj, #name, statp->name)
+
+#define JAVADB_STAT_LSN(env, cl, jobj, statp, name) \
+ set_lsn_field(jnienv, cl, jobj, #name, statp->name)
+
+#define JAVADB_STAT_LONG(env, cl, jobj, statp, name) \
+ set_long_field(jnienv, cl, jobj, #name, statp->name)
+
+/*
+ * We build the active list separately.
+ */
+#define JAVADB_STAT_ACTIVE(env, cl, jobj, statp, name) \
+ do {} while(0)
#endif /* !_JAVA_UTIL_H_ */
diff --git a/bdb/lock/Design b/bdb/lock/Design
index ac8f0b02fbf..f0bb5c6e99c 100644
--- a/bdb/lock/Design
+++ b/bdb/lock/Design
@@ -1,7 +1,15 @@
-# $Id: Design,v 11.3 2000/02/19 20:58:03 bostic Exp $
+# $Id: Design,v 11.5 2002/02/01 19:07:18 bostic Exp $
Synchronization in the Locking Subsystem
+This is a document that describes how we implemented fine-grain locking
+in the lock manager (that is, locking on a hash bucket level instead of
+locking the entire region). We found that the increase in concurrency
+was not sufficient to warrant the increase in complexity or the additional
+cost of performing each lock operation. Therefore, we don't use this
+any more. Should we have to do fine-grain locking in a future release,
+this would be a reasonable starting point.
+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1. Data structures
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
diff --git a/bdb/lock/lock.c b/bdb/lock/lock.c
index 8d246f7ded3..8eda155b822 100644
--- a/bdb/lock/lock.c
+++ b/bdb/lock/lock.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock.c,v 11.40 2000/12/19 23:18:58 ubell Exp $";
+static const char revid[] = "$Id: lock.c,v 11.108 2002/08/06 06:11:34 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,118 +17,183 @@ static const char revid[] = "$Id: lock.c,v 11.40 2000/12/19 23:18:58 ubell Exp $
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "log.h"
-#include "db_am.h"
-#include "txn.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
static int __lock_checklocker __P((DB_LOCKTAB *,
- struct __db_lock *, u_int32_t, u_int32_t, int *));
-static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t,
- u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
-static int __lock_is_parent __P((DB_LOCKTAB *, u_int32_t, DB_LOCKER *));
-static int __lock_put_internal __P((DB_LOCKTAB *,
- struct __db_lock *, u_int32_t, u_int32_t));
-static int __lock_put_nolock __P((DB_ENV *, DB_LOCK *, int *, int));
-static void __lock_remove_waiter __P((DB_ENV *,
- DB_LOCKOBJ *, struct __db_lock *, db_status_t));
+ struct __db_lock *, u_int32_t, u_int32_t));
+static void __lock_expires __P((DB_ENV *, db_timeval_t *, db_timeout_t));
+static void __lock_freelocker
+ __P((DB_LOCKTAB *, DB_LOCKREGION *, DB_LOCKER *, u_int32_t));
+static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, u_int32_t,
+ const DBT *, db_lockmode_t, db_timeout_t, DB_LOCK *));
+static int __lock_getobj
+ __P((DB_LOCKTAB *, const DBT *, u_int32_t, int, DB_LOCKOBJ **));
+static int __lock_is_parent __P((DB_LOCKTAB *, u_int32_t, DB_LOCKER *));
+static int __lock_put_internal __P((DB_LOCKTAB *,
+ struct __db_lock *, u_int32_t, u_int32_t));
+static int __lock_put_nolock __P((DB_ENV *, DB_LOCK *, int *, u_int32_t));
+static void __lock_remove_waiter __P((DB_LOCKTAB *,
+ DB_LOCKOBJ *, struct __db_lock *, db_status_t));
+static int __lock_trade __P((DB_ENV *, DB_LOCK *, u_int32_t));
static const char __db_lock_err[] = "Lock table is out of available %s";
static const char __db_lock_invalid[] = "%s: Lock is no longer valid";
static const char __db_locker_invalid[] = "Locker is not valid";
/*
- * lock_id --
+ * __lock_id --
* Generate a unique locker id.
+ *
+ * PUBLIC: int __lock_id __P((DB_ENV *, u_int32_t *));
*/
int
-lock_id(dbenv, idp)
+__lock_id(dbenv, idp)
DB_ENV *dbenv;
u_int32_t *idp;
{
+ DB_LOCKER *lk;
DB_LOCKTAB *lt;
DB_LOCKREGION *region;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_id(dbenv, idp));
-#endif
+ u_int32_t *ids, locker_ndx;
+ int nids, ret;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_id", DB_INIT_LOCK);
lt = dbenv->lk_handle;
region = lt->reginfo.primary;
+ ret = 0;
/*
- * Note that we are letting locker IDs wrap.
- *
- * This is potentially dangerous in that it's conceivable that you
- * could be allocating a new locker id and still have someone using
- * it. However, the alternatives are that we keep a bitmap of
- * locker ids or we forbid wrapping. Both are probably bad. The
- * bitmap of locker ids will take up 64 MB of space. Forbidding
- * wrapping means that we'll run out of locker IDs after 2 billion.
- * In order for the wrap bug to fire, we'd need to have something
- * that stayed open while 2 billion locker ids were used up. Since
- * we cache cursors it means that something would have to stay open
- * sufficiently long that we open and close a lot of files and a
- * lot of cursors within them. Betting that this won't happen seems
- * to the lesser of the evils.
+ * Allocate a new lock id. If we wrap around then we
+ * find the minimum currently in use and make sure we
+ * can stay below that. This code is similar to code
+ * in __txn_begin_int for recovering txn ids.
*/
LOCKREGION(dbenv, lt);
- if (region->id >= DB_LOCK_MAXID)
- region->id = 0;
- *idp = ++region->id;
- UNLOCKREGION(dbenv, lt);
+ /*
+ * Our current valid range can span the maximum valid value, so check
+ * for it and wrap manually.
+ */
+ if (region->stat.st_id == DB_LOCK_MAXID &&
+ region->stat.st_cur_maxid != DB_LOCK_MAXID)
+ region->stat.st_id = DB_LOCK_INVALIDID;
+ if (region->stat.st_id == region->stat.st_cur_maxid) {
+ if ((ret = __os_malloc(dbenv,
+ sizeof(u_int32_t) * region->stat.st_nlockers, &ids)) != 0)
+ goto err;
+ nids = 0;
+ for (lk = SH_TAILQ_FIRST(&region->lockers, __db_locker);
+ lk != NULL;
+ lk = SH_TAILQ_NEXT(lk, ulinks, __db_locker))
+ ids[nids++] = lk->id;
+ region->stat.st_id = DB_LOCK_INVALIDID;
+ region->stat.st_cur_maxid = DB_LOCK_MAXID;
+ if (nids != 0)
+ __db_idspace(ids, nids,
+ &region->stat.st_id, &region->stat.st_cur_maxid);
+ __os_free(dbenv, ids);
+ }
+ *idp = ++region->stat.st_id;
- return (0);
+ /* Allocate a locker for this id. */
+ LOCKER_LOCK(lt, region, *idp, locker_ndx);
+ ret = __lock_getlocker(lt, *idp, locker_ndx, 1, &lk);
+
+err: UNLOCKREGION(dbenv, lt);
+
+ return (ret);
}
/*
- * Vector lock routine. This function takes a set of operations
- * and performs them all at once. In addition, lock_vec provides
- * functionality for lock inheritance, releasing all locks for a
- * given locker (used during transaction commit/abort), releasing
- * all locks on a given object, and generating debugging information.
+ * __lock_id_free --
+ * Free a locker id.
+ *
+ * PUBLIC: int __lock_id_free __P((DB_ENV *, u_int32_t));
*/
int
-lock_vec(dbenv, locker, flags, list, nlist, elistp)
+__lock_id_free(dbenv, id)
+ DB_ENV *dbenv;
+ u_int32_t id;
+{
+ DB_LOCKER *sh_locker;
+ DB_LOCKTAB *lt;
+ DB_LOCKREGION *region;
+ u_int32_t locker_ndx;
+ int ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_id_free", DB_INIT_LOCK);
+
+ lt = dbenv->lk_handle;
+ region = lt->reginfo.primary;
+
+ LOCKREGION(dbenv, lt);
+ LOCKER_LOCK(lt, region, id, locker_ndx);
+ if ((ret =
+ __lock_getlocker(lt, id, locker_ndx, 0, &sh_locker)) != 0)
+ goto err;
+ if (sh_locker == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ if (sh_locker->nlocks != 0) {
+ __db_err(dbenv, "Locker still has locks");
+ ret = EINVAL;
+ goto err;
+ }
+
+ __lock_freelocker(lt, region, sh_locker, locker_ndx);
+
+err: UNLOCKREGION(dbenv, lt);
+ return (ret);
+}
+
+/*
+ * __lock_vec --
+ * Vector lock routine. This function takes a set of operations
+ * and performs them all at once. In addition, lock_vec provides
+ * functionality for lock inheritance, releasing all locks for a
+ * given locker (used during transaction commit/abort), releasing
+ * all locks on a given object, and generating debugging information.
+ *
+ * PUBLIC: int __lock_vec __P((DB_ENV *,
+ * PUBLIC: u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
+ */
+int
+__lock_vec(dbenv, locker, flags, list, nlist, elistp)
DB_ENV *dbenv;
u_int32_t locker, flags;
int nlist;
DB_LOCKREQ *list, **elistp;
{
struct __db_lock *lp, *next_lock;
+ DB_LOCK lock;
DB_LOCKER *sh_locker, *sh_parent;
DB_LOCKOBJ *obj, *sh_obj;
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
u_int32_t lndx, ndx;
- int did_abort, i, ret, run_dd;
+ int did_abort, i, ret, run_dd, upgrade, writes;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_vec(dbenv, locker,
- flags, list, nlist, elistp));
-#endif
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_vec", DB_INIT_LOCK);
+
+ /* Check if locks have been globally turned off. */
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+ return (0);
/* Validate arguments. */
- if ((ret = __db_fchk(dbenv, "lock_vec", flags, DB_LOCK_NOWAIT)) != 0)
+ if ((ret = __db_fchk(dbenv, "DB_ENV->lock_vec",
+ flags, DB_LOCK_FREE_LOCKER | DB_LOCK_NOWAIT)) != 0)
return (ret);
lt = dbenv->lk_handle;
@@ -138,13 +203,14 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
LOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
for (i = 0, ret = 0; i < nlist && ret == 0; i++)
switch (list[i].op) {
+ case DB_LOCK_GET_TIMEOUT:
+ LF_SET(DB_LOCK_SET_TIMEOUT);
case DB_LOCK_GET:
ret = __lock_get_internal(dbenv->lk_handle,
- locker, flags,
- list[i].obj, list[i].mode, &list[i].lock);
+ locker, flags, list[i].obj,
+ list[i].mode, list[i].timeout, &list[i].lock);
break;
case DB_LOCK_INHERIT:
-
/*
* Get the committing locker and mark it as deleted.
* This allows us to traverse the locker links without
@@ -159,7 +225,7 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
sh_locker == NULL ||
F_ISSET(sh_locker, DB_LOCKER_DELETED)) {
if (ret == 0 && sh_locker != NULL)
- ret = EACCES;
+ ret = EINVAL;
__db_err(dbenv, __db_locker_invalid);
break;
}
@@ -182,8 +248,8 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
if (F_ISSET(sh_parent, DB_LOCKER_DELETED)) {
if (ret == 0) {
__db_err(dbenv,
- "Parent locker is not valid");
- ret = EACCES;
+ "Parent locker is not valid");
+ ret = EINVAL;
}
break;
}
@@ -203,15 +269,21 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
LF_ISSET(DB_LOCK_NOWAITERS));
}
+ /* Transfer child counts to parent. */
+ sh_parent->nlocks += sh_locker->nlocks;
+ sh_parent->nwrites += sh_locker->nwrites;
+
/* Now free the original locker. */
ret = __lock_checklocker(lt,
- NULL, locker, DB_LOCK_IGNOREDEL, NULL);
+ NULL, locker, DB_LOCK_IGNOREDEL);
break;
case DB_LOCK_PUT:
- ret =
- __lock_put_nolock(dbenv, &list[i].lock, &run_dd, 0);
+ ret = __lock_put_nolock(dbenv,
+ &list[i].lock, &run_dd, flags);
break;
case DB_LOCK_PUT_ALL:
+ case DB_LOCK_PUT_READ:
+ case DB_LOCK_UPGRADE_WRITE:
/*
* Get the locker and mark it as deleted. This
* allows us to traverse the locker links without
@@ -232,23 +304,79 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
* to do.
*/
break;
+ upgrade = 0;
+ writes = 1;
+ if (list[i].op == DB_LOCK_PUT_READ)
+ writes = 0;
+ else if (list[i].op == DB_LOCK_UPGRADE_WRITE) {
+ if (F_ISSET(sh_locker, DB_LOCKER_DIRTY))
+ upgrade = 1;
+ writes = 0;
+ }
+
F_SET(sh_locker, DB_LOCKER_DELETED);
/* Now traverse the locks, releasing each one. */
for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
- lp != NULL;
- lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) {
- SH_LIST_REMOVE(lp, locker_links, __db_lock);
- sh_obj =
- (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
- SHOBJECT_LOCK(lt, region, sh_obj, lndx);
- ret = __lock_put_internal(lt,
- lp, lndx, DB_LOCK_FREE | DB_LOCK_DOALL);
- if (ret != 0)
- break;
+ lp != NULL;) {
+ sh_obj = (DB_LOCKOBJ *)
+ ((u_int8_t *)lp + lp->obj);
+ if (writes == 1 || lp->mode == DB_LOCK_READ) {
+ SH_LIST_REMOVE(lp,
+ locker_links, __db_lock);
+ sh_obj = (DB_LOCKOBJ *)
+ ((u_int8_t *)lp + lp->obj);
+ SHOBJECT_LOCK(lt, region, sh_obj, lndx);
+ /*
+ * We are not letting lock_put_internal
+ * unlink the lock, so we'll have to
+ * update counts here.
+ */
+ sh_locker->nlocks--;
+ if (IS_WRITELOCK(lp->mode))
+ sh_locker->nwrites--;
+ ret = __lock_put_internal(lt, lp,
+ lndx, DB_LOCK_FREE | DB_LOCK_DOALL);
+ if (ret != 0)
+ break;
+ lp = SH_LIST_FIRST(
+ &sh_locker->heldby, __db_lock);
+ } else
+ lp = SH_LIST_NEXT(lp,
+ locker_links, __db_lock);
+ }
+ switch (list[i].op) {
+ case DB_LOCK_UPGRADE_WRITE:
+ if (upgrade != 1)
+ goto up_done;
+ for (lp = SH_LIST_FIRST(
+ &sh_locker->heldby, __db_lock);
+ lp != NULL;
+ lp = SH_LIST_NEXT(lp,
+ locker_links, __db_lock)) {
+ if (ret != 0)
+ break;
+ lock.off = R_OFFSET(&lt->reginfo, lp);
+ lock.gen = lp->gen;
+ F_SET(sh_locker, DB_LOCKER_INABORT);
+ ret = __lock_get_internal(lt,
+ locker, DB_LOCK_UPGRADE,
+ NULL, DB_LOCK_WRITE, 0, &lock);
+ }
+ up_done:
+ /* FALL THROUGH */
+ case DB_LOCK_PUT_READ:
+ F_CLR(sh_locker, DB_LOCKER_DELETED);
+ break;
+
+ case DB_LOCK_PUT_ALL:
+ if (ret == 0)
+ ret = __lock_checklocker(lt,
+ NULL, locker, DB_LOCK_IGNOREDEL);
+ break;
+ default:
+ break;
}
- ret = __lock_checklocker(lt,
- NULL, locker, DB_LOCK_IGNOREDEL, NULL);
break;
case DB_LOCK_PUT_OBJ:
/* Remove all the locks associated with an object. */
@@ -269,8 +397,9 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
for (lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock);
ret == 0 && lp != NULL;
lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock))
- ret = __lock_put_internal(lt,
- lp, ndx, DB_LOCK_NOPROMOTE | DB_LOCK_DOALL);
+ ret = __lock_put_internal(lt, lp, ndx,
+ DB_LOCK_UNLINK |
+ DB_LOCK_NOPROMOTE | DB_LOCK_DOALL);
/*
* On the last time around, the object will get
@@ -281,18 +410,43 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
ret == 0 && lp != NULL;
lp = next_lock) {
next_lock = SH_TAILQ_NEXT(lp, links, __db_lock);
- ret = __lock_put_internal(lt,
- lp, ndx, DB_LOCK_NOPROMOTE | DB_LOCK_DOALL);
+ ret = __lock_put_internal(lt, lp, ndx,
+ DB_LOCK_UNLINK |
+ DB_LOCK_NOPROMOTE | DB_LOCK_DOALL);
}
break;
+
+ case DB_LOCK_TIMEOUT:
+ ret = __lock_set_timeout(dbenv,
+ locker, 0, DB_SET_TXN_NOW);
+ region->need_dd = 1;
+ break;
+
+ case DB_LOCK_TRADE:
+ /*
+ * INTERNAL USE ONLY.
+ * Change the holder of the lock described in
+ * list[i].lock to the locker-id specified by
+ * the locker parameter.
+ */
+ /*
+ * You had better know what you're doing here.
+ * We are trading locker-id's on a lock to
+ * facilitate file locking on open DB handles.
+ * We do not do any conflict checking on this,
+ * so heaven help you if you use this flag under
+ * any other circumstances.
+ */
+ ret = __lock_trade(dbenv, &list[i].lock, locker);
+ break;
#ifdef DEBUG
case DB_LOCK_DUMP:
/* Find the locker. */
LOCKER_LOCK(lt, region, locker, ndx);
if ((ret = __lock_getlocker(lt,
- locker, ndx, 0, &sh_locker)) != 0
- || sh_locker == NULL
- || F_ISSET(sh_locker, DB_LOCKER_DELETED))
+ locker, ndx, 0, &sh_locker)) != 0 ||
+ sh_locker == NULL ||
+ F_ISSET(sh_locker, DB_LOCKER_DELETED))
break;
for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
@@ -309,14 +463,12 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
break;
}
- if (ret == 0 && region->need_dd && region->detect != DB_LOCK_NORUN) {
+ if (ret == 0 && region->need_dd && region->detect != DB_LOCK_NORUN)
run_dd = 1;
- region->need_dd = 0;
- }
UNLOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
if (run_dd)
- (void)lock_detect(dbenv, 0, region->detect, &did_abort);
+ (void)dbenv->lock_detect(dbenv, 0, region->detect, &did_abort);
if (ret != 0 && elistp != NULL)
*elistp = &list[i - 1];
@@ -327,14 +479,17 @@ lock_vec(dbenv, locker, flags, list, nlist, elistp)
/*
* Lock acquisition routines. There are two library interfaces:
*
- * lock_get --
+ * __lock_get --
* original lock get interface that takes a locker id.
*
* All the work for lock_get (and for the GET option of lock_vec) is done
* inside of lock_get_internal.
+ *
+ * PUBLIC: int __lock_get __P((DB_ENV *,
+ * PUBLIC: u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
*/
int
-lock_get(dbenv, locker, flags, obj, lock_mode, lock)
+__lock_get(dbenv, locker, flags, obj, lock_mode, lock)
DB_ENV *dbenv;
u_int32_t locker, flags;
const DBT *obj;
@@ -343,95 +498,103 @@ lock_get(dbenv, locker, flags, obj, lock_mode, lock)
{
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_get(dbenv, locker,
- flags, obj, lock_mode, lock));
-#endif
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_get", DB_INIT_LOCK);
if (IS_RECOVERING(dbenv)) {
- lock->off = LOCK_INVALID;
+ LOCK_INIT(*lock);
return (0);
}
/* Validate arguments. */
- if ((ret = __db_fchk(dbenv,
- "lock_get", flags,
+ if ((ret = __db_fchk(dbenv, "DB_ENV->lock_get", flags,
DB_LOCK_NOWAIT | DB_LOCK_UPGRADE | DB_LOCK_SWITCH)) != 0)
return (ret);
LOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
ret = __lock_get_internal(dbenv->lk_handle,
- locker, flags, obj, lock_mode, lock);
+ locker, flags, obj, lock_mode, 0, lock);
UNLOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
return (ret);
}
static int
-__lock_get_internal(lt, locker, flags, obj, lock_mode, lock)
+__lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
DB_LOCKTAB *lt;
u_int32_t locker, flags;
const DBT *obj;
db_lockmode_t lock_mode;
+ db_timeout_t timeout;
DB_LOCK *lock;
{
- struct __db_lock *newl, *lp;
+ struct __db_lock *newl, *lp, *wwrite;
DB_ENV *dbenv;
DB_LOCKER *sh_locker;
DB_LOCKOBJ *sh_obj;
DB_LOCKREGION *region;
- u_int32_t locker_ndx;
- int did_abort, freed, ihold, on_locker_list, no_dd, ret;
+ u_int32_t locker_ndx, obj_ndx;
+ int did_abort, ihold, on_locker_list, no_dd, ret;
- no_dd = ret = 0;
- on_locker_list = 0;
- region = lt->reginfo.primary;
dbenv = lt->dbenv;
+ region = lt->reginfo.primary;
+ on_locker_list = no_dd = ret = 0;
+
+ /* Check if locks have been globally turned off. */
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+ return (0);
/*
- * If we are not going to reuse this lock, initialize
- * the offset to invalid so that if we fail it
- * will not look like a valid lock.
+ * If we are not going to reuse this lock, initialize the offset to
+ * invalid so that if we fail it will not look like a valid lock.
*/
if (!LF_ISSET(DB_LOCK_UPGRADE | DB_LOCK_SWITCH))
- lock->off = LOCK_INVALID;
+ LOCK_INIT(*lock);
- /*
- * Check that the lock mode is valid.
- */
- if ((u_int32_t)lock_mode >= region->nmodes) {
- __db_err(dbenv,
- "lock_get: invalid lock mode %lu\n", (u_long)lock_mode);
+ /* Check that the lock mode is valid. */
+ if ((u_int32_t)lock_mode >= region->stat.st_nmodes) {
+ __db_err(dbenv, "DB_ENV->lock_get: invalid lock mode %lu",
+ (u_long)lock_mode);
return (EINVAL);
}
/* Allocate a new lock. Optimize for the common case of a grant. */
- region->nrequests++;
+ region->stat.st_nrequests++;
if ((newl = SH_TAILQ_FIRST(&region->free_locks, __db_lock)) != NULL)
SH_TAILQ_REMOVE(&region->free_locks, newl, links, __db_lock);
if (newl == NULL) {
__db_err(dbenv, __db_lock_err, "locks");
return (ENOMEM);
}
- if (++region->nlocks > region->maxnlocks)
- region->maxnlocks = region->nlocks;
+ if (++region->stat.st_nlocks > region->stat.st_maxnlocks)
+ region->stat.st_maxnlocks = region->stat.st_nlocks;
- /* Allocate a new object. */
- OBJECT_LOCK(lt, region, obj, lock->ndx);
- if ((ret = __lock_getobj(lt, obj, lock->ndx, 1, &sh_obj)) != 0)
- goto err;
+ if (obj == NULL) {
+ DB_ASSERT(LOCK_ISSET(*lock));
+ lp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
+ sh_obj = (DB_LOCKOBJ *) ((u_int8_t *)lp + lp->obj);
+ } else {
+ /* Allocate a shared memory new object. */
+ OBJECT_LOCK(lt, region, obj, lock->ndx);
+ if ((ret = __lock_getobj(lt, obj, lock->ndx, 1, &sh_obj)) != 0)
+ goto err;
+ }
/* Get the locker, we may need it to find our parent. */
LOCKER_LOCK(lt, region, locker, locker_ndx);
- if ((ret =
- __lock_getlocker(lt, locker, locker_ndx, 1, &sh_locker)) != 0) {
+ if ((ret = __lock_getlocker(lt, locker,
+ locker_ndx, locker > DB_LOCK_MAXID ? 1 : 0, &sh_locker)) != 0) {
/*
- * XXX: Margo
- * CLEANUP the object and the lock.
+ * XXX We cannot tell if we created the object or not,
+ * so we don't kow if we should free it or not.
*/
- return (ret);
+ goto err;
+ }
+
+ if (sh_locker == NULL) {
+ __db_err(dbenv, "Locker does not exist");
+ ret = EINVAL;
+ goto err;
}
/*
@@ -460,11 +623,11 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lock)
if (LF_ISSET(DB_LOCK_SWITCH))
goto put_lock;
+ wwrite = NULL;
for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock);
lp != NULL;
lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
- if (locker == lp->holder ||
- __lock_is_parent(lt, lp->holder, sh_locker)) {
+ if (locker == lp->holder) {
if (lp->mode == lock_mode &&
lp->status == DB_LSTAT_HELD) {
if (LF_ISSET(DB_LOCK_UPGRADE))
@@ -473,20 +636,46 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lock)
/*
* Lock is held, so we can increment the
* reference count and return this lock.
+ * We do not count reference increments
+ * towards the locks held by the locker.
*/
lp->refcount++;
lock->off = R_OFFSET(&lt->reginfo, lp);
lock->gen = lp->gen;
+ lock->mode = lp->mode;
ret = 0;
goto done;
- } else
+ } else {
ihold = 1;
- } else if (CONFLICTS(lt, region, lp->mode, lock_mode))
+ if (lock_mode == DB_LOCK_WRITE &&
+ lp->mode == DB_LOCK_WWRITE)
+ wwrite = lp;
+ }
+ } else if (__lock_is_parent(lt, lp->holder, sh_locker))
+ ihold = 1;
+ else if (CONFLICTS(lt, region, lp->mode, lock_mode))
break;
}
/*
+ * If we are looking to upgrade a WWRITE to a WRITE lock
+ * and there were no conflicting locks then we can just
+ * upgrade this lock to the one we want.
+ */
+ if (wwrite != NULL && lp == NULL) {
+ lp = wwrite;
+ lp->mode = lock_mode;
+ lp->refcount++;
+ lock->off = R_OFFSET(&lt->reginfo, lp);
+ lock->gen = lp->gen;
+ lock->mode = lp->mode;
+
+ ret = 0;
+ goto done;
+ }
+
+ /*
* Make the new lock point to the new object, initialize fields.
*
* This lock is not linked in anywhere, so we can muck with it
@@ -542,10 +731,10 @@ put_lock:
SH_TAILQ_INSERT_TAIL(&sh_obj->waiters, newl, links);
} else {
ret = DB_LOCK_NOTGRANTED;
- if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL
- && LOCKER_FREEABLE(sh_locker))
- __lock_freelocker( lt, region, sh_locker, locker_ndx);
- region->nnowaits++;
+ if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL &&
+ LF_ISSET(DB_LOCK_FREE_LOCKER))
+ __lock_freelocker(lt, region, sh_locker, locker_ndx);
+ region->stat.st_nnowaits++;
goto err;
}
@@ -556,9 +745,9 @@ llist:
* detector, save that information.
*/
on_locker_list = 1;
- no_dd = sh_locker->master_locker == INVALID_ROFF
- && SH_LIST_FIRST(&sh_locker->child_locker, __db_locker) == NULL
- && SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL;
+ no_dd = sh_locker->master_locker == INVALID_ROFF &&
+ SH_LIST_FIRST(&sh_locker->child_locker, __db_locker) == NULL &&
+ SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL;
SH_LIST_INSERT_HEAD(&sh_locker->heldby, newl, locker_links, __db_lock);
@@ -573,9 +762,60 @@ llist:
* block.
*/
newl->status = DB_LSTAT_WAITING;
- region->nconflicts++;
- if (region->detect == DB_LOCK_NORUN)
- region->need_dd = 1;
+ region->stat.st_nconflicts++;
+ region->need_dd = 1;
+ /*
+ * First check to see if this txn has expired.
+ * If not then see if the lock timeout is past
+ * the expiration of the txn, if it is, use
+ * the txn expiration time. lk_expire is passed
+ * to avoid an extra call to get the time.
+ */
+ if (__lock_expired(dbenv,
+ &sh_locker->lk_expire, &sh_locker->tx_expire)) {
+ newl->status = DB_LSTAT_ABORTED;
+ region->stat.st_ndeadlocks++;
+ region->stat.st_ntxntimeouts++;
+
+ /*
+ * Remove the lock from the wait queue and if
+ * this was the only lock on the wait queue remove
+ * this object from the deadlock detector object
+ * list.
+ */
+ SH_LIST_REMOVE(newl, locker_links, __db_lock);
+ SH_TAILQ_REMOVE(
+ &sh_obj->waiters, newl, links, __db_lock);
+ if (SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL)
+ SH_TAILQ_REMOVE(&region->dd_objs,
+ sh_obj, dd_links, __db_lockobj);
+
+ /* Clear the timeout, we are done. */
+ LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+ goto expired;
+ }
+
+ /*
+ * If a timeout was specified in this call then it
+ * takes priority. If a lock timeout has been specified
+ * for this transaction then use that, otherwise use
+ * the global timeout value.
+ */
+ if (!LF_ISSET(DB_LOCK_SET_TIMEOUT)) {
+ if (F_ISSET(sh_locker, DB_LOCKER_TIMEOUT))
+ timeout = sh_locker->lk_timeout;
+ else
+ timeout = region->lk_timeout;
+ }
+ if (timeout != 0)
+ __lock_expires(dbenv, &sh_locker->lk_expire, timeout);
+ else
+ LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
+
+ if (LOCK_TIME_ISVALID(&sh_locker->tx_expire) &&
+ (timeout == 0 || __lock_expired(dbenv,
+ &sh_locker->lk_expire, &sh_locker->tx_expire)))
+ sh_locker->lk_expire = sh_locker->tx_expire;
UNLOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
/*
@@ -583,22 +823,41 @@ llist:
* detector should be run.
*/
if (region->detect != DB_LOCK_NORUN && !no_dd)
- (void)lock_detect(dbenv, 0, region->detect, &did_abort);
+ (void)dbenv->lock_detect(
+ dbenv, 0, region->detect, &did_abort);
- MUTEX_LOCK(dbenv, &newl->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &newl->mutex);
LOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
+expired: /* Turn off lock timeout. */
+ LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
+
if (newl->status != DB_LSTAT_PENDING) {
- (void)__lock_checklocker(lt,
- newl, newl->holder, 0, &freed);
+ (void)__lock_checklocker(lt, newl, newl->holder, 0);
switch (newl->status) {
case DB_LSTAT_ABORTED:
on_locker_list = 0;
ret = DB_LOCK_DEADLOCK;
break;
- case DB_LSTAT_NOGRANT:
- ret = DB_LOCK_NOTGRANTED;
+ case DB_LSTAT_NOTEXIST:
+ ret = DB_LOCK_NOTEXIST;
break;
+ case DB_LSTAT_EXPIRED:
+ SHOBJECT_LOCK(lt,
+ region, sh_obj, obj_ndx);
+ if ((ret = __lock_put_internal(
+ lt, newl, obj_ndx, 0) != 0))
+ goto err;
+ if (LOCK_TIME_EQUAL(
+ &sh_locker->lk_expire,
+ &sh_locker->tx_expire)) {
+ region->stat.st_ndeadlocks++;
+ region->stat.st_ntxntimeouts++;
+ return (DB_LOCK_DEADLOCK);
+ } else {
+ region->stat.st_nlocktimeouts++;
+ return (DB_LOCK_NOTGRANTED);
+ }
default:
ret = EINVAL;
break;
@@ -624,6 +883,10 @@ llist:
lock->off = R_OFFSET(&lt->reginfo, newl);
lock->gen = newl->gen;
+ lock->mode = newl->mode;
+ sh_locker->nlocks++;
+ if (IS_WRITELOCK(newl->mode))
+ sh_locker->nwrites++;
return (0);
@@ -631,18 +894,21 @@ upgrade:/*
* This was an upgrade, so return the new lock to the free list and
* upgrade the mode of the original lock.
*/
- ((struct __db_lock *)R_ADDR(&lt->reginfo, lock->off))->mode = lock_mode;
+ lp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
+ if (IS_WRITELOCK(lock_mode) && !IS_WRITELOCK(lp->mode))
+ sh_locker->nwrites++;
+ lp->mode = lock_mode;
ret = 0;
/* FALLTHROUGH */
done:
err: newl->status = DB_LSTAT_FREE;
+ region->stat.st_nlocks--;
if (on_locker_list) {
SH_LIST_REMOVE(newl, locker_links, __db_lock);
}
SH_TAILQ_INSERT_HEAD(&region->free_locks, newl, links, __db_lock);
- region->nlocks--;
return (ret);
}
@@ -651,21 +917,20 @@ err: newl->status = DB_LSTAT_FREE;
*
* The user callable one is lock_put and the three we use internally are
* __lock_put_nolock, __lock_put_internal and __lock_downgrade.
+ *
+ * PUBLIC: int __lock_put __P((DB_ENV *, DB_LOCK *));
*/
int
-lock_put(dbenv, lock)
+__lock_put(dbenv, lock)
DB_ENV *dbenv;
DB_LOCK *lock;
{
DB_LOCKTAB *lt;
int ret, run_dd;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_put(dbenv, lock));
-#endif
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_LOCK->lock_put", DB_INIT_LOCK);
if (IS_RECOVERING(dbenv))
return (0);
@@ -676,8 +941,14 @@ lock_put(dbenv, lock)
ret = __lock_put_nolock(dbenv, lock, &run_dd, 0);
UNLOCKREGION(dbenv, lt);
+ /*
+ * Only run the lock detector if put told us to AND we are running
+ * in auto-detect mode. If we are not running in auto-detect, then
+ * a call to lock_detect here will 0 the need_dd bit, but will not
+ * actually abort anything.
+ */
if (ret == 0 && run_dd)
- (void)lock_detect(dbenv, 0,
+ (void)dbenv->lock_detect(dbenv, 0,
((DB_LOCKREGION *)lt->reginfo.primary)->detect, NULL);
return (ret);
}
@@ -687,41 +958,43 @@ __lock_put_nolock(dbenv, lock, runp, flags)
DB_ENV *dbenv;
DB_LOCK *lock;
int *runp;
- int flags;
+ u_int32_t flags;
{
struct __db_lock *lockp;
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
- u_int32_t locker;
int ret;
+ /* Check if locks have been globally turned off. */
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+ return (0);
+
lt = dbenv->lk_handle;
region = lt->reginfo.primary;
lockp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
- lock->off = LOCK_INVALID;
+ LOCK_INIT(*lock);
if (lock->gen != lockp->gen) {
- __db_err(dbenv, __db_lock_invalid, "lock_put");
- return (EACCES);
+ __db_err(dbenv, __db_lock_invalid, "DB_LOCK->lock_put");
+ return (EINVAL);
}
- locker = lockp->holder;
ret = __lock_put_internal(lt,
lockp, lock->ndx, flags | DB_LOCK_UNLINK | DB_LOCK_FREE);
*runp = 0;
- if (ret == 0 && region->need_dd && region->detect != DB_LOCK_NORUN) {
+ if (ret == 0 && region->need_dd && region->detect != DB_LOCK_NORUN)
*runp = 1;
- region->need_dd = 0;
- }
return (ret);
}
/*
* __lock_downgrade --
- * Used by the concurrent access product to downgrade write locks
- * back to iwrite locks.
+ * Used to downgrade locks. Currently this is used in two places,
+ * 1) by the concurrent access product to downgrade write locks
+ * back to iwrite locks and 2) to downgrade write-handle locks to read-handle
+ * locks at the end of an open/create.
*
* PUBLIC: int __lock_downgrade __P((DB_ENV *,
* PUBLIC: DB_LOCK *, db_lockmode_t, u_int32_t));
@@ -734,14 +1007,21 @@ __lock_downgrade(dbenv, lock, new_mode, flags)
u_int32_t flags;
{
struct __db_lock *lockp;
+ DB_LOCKER *sh_locker;
DB_LOCKOBJ *obj;
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
+ u_int32_t indx;
int ret;
COMPQUIET(flags, 0);
PANIC_CHECK(dbenv);
+ ret = 0;
+
+ /* Check if locks have been globally turned off. */
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+ return (0);
lt = dbenv->lk_handle;
region = lt->reginfo.primary;
@@ -751,9 +1031,24 @@ __lock_downgrade(dbenv, lock, new_mode, flags)
lockp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
if (lock->gen != lockp->gen) {
__db_err(dbenv, __db_lock_invalid, "lock_downgrade");
- ret = EACCES;
+ ret = EINVAL;
+ goto out;
+ }
+
+ LOCKER_LOCK(lt, region, lockp->holder, indx);
+
+ if ((ret = __lock_getlocker(lt, lockp->holder,
+ indx, 0, &sh_locker)) != 0 || sh_locker == NULL) {
+ if (ret == 0)
+ ret = EINVAL;
+ __db_err(dbenv, __db_locker_invalid);
goto out;
}
+ if (IS_WRITELOCK(lockp->mode) && !IS_WRITELOCK(new_mode))
+ sh_locker->nwrites--;
+
+ if (new_mode == DB_LOCK_WWRITE)
+ F_SET(sh_locker, DB_LOCKER_DIRTY);
lockp->mode = new_mode;
@@ -761,25 +1056,23 @@ __lock_downgrade(dbenv, lock, new_mode, flags)
obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);
(void)__lock_promote(lt, obj, LF_ISSET(DB_LOCK_NOWAITERS));
- ++region->nreleases;
out: UNLOCKREGION(dbenv, lt);
- return (0);
+ return (ret);
}
static int
__lock_put_internal(lt, lockp, obj_ndx, flags)
DB_LOCKTAB *lt;
struct __db_lock *lockp;
- u_int32_t obj_ndx;
- u_int32_t flags;
+ u_int32_t obj_ndx, flags;
{
DB_LOCKOBJ *sh_obj;
DB_LOCKREGION *region;
- int no_reclaim, ret, state_changed;
+ int ret, state_changed;
region = lt->reginfo.primary;
- no_reclaim = ret = state_changed = 0;
+ ret = state_changed = 0;
if (!OBJ_LINKS_VALID(lockp)) {
/*
@@ -791,14 +1084,14 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
lockp->status = DB_LSTAT_FREE;
SH_TAILQ_INSERT_HEAD(
&region->free_locks, lockp, links, __db_lock);
- region->nlocks--;
+ region->stat.st_nlocks--;
return (0);
}
if (LF_ISSET(DB_LOCK_DOALL))
- region->nreleases += lockp->refcount;
+ region->stat.st_nreleases += lockp->refcount;
else
- region->nreleases++;
+ region->stat.st_nreleases++;
if (!LF_ISSET(DB_LOCK_DOALL) && lockp->refcount > 1) {
lockp->refcount--;
@@ -812,8 +1105,8 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);
/* Remove this lock from its holders/waitlist. */
- if (lockp->status != DB_LSTAT_HELD)
- __lock_remove_waiter(lt->dbenv, sh_obj, lockp, DB_LSTAT_FREE);
+ if (lockp->status != DB_LSTAT_HELD && lockp->status != DB_LSTAT_PENDING)
+ __lock_remove_waiter(lt, sh_obj, lockp, DB_LSTAT_FREE);
else {
SH_TAILQ_REMOVE(&sh_obj->holders, lockp, links, __db_lock);
lockp->links.stqe_prev = -1;
@@ -822,15 +1115,15 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
if (LF_ISSET(DB_LOCK_NOPROMOTE))
state_changed = 0;
else
- state_changed =
- __lock_promote(lt, sh_obj, LF_ISSET(DB_LOCK_NOWAITERS));
+ state_changed = __lock_promote(lt,
+ sh_obj, LF_ISSET(DB_LOCK_REMOVE | DB_LOCK_NOWAITERS));
if (LF_ISSET(DB_LOCK_UNLINK))
- ret = __lock_checklocker(lt, lockp, lockp->holder, flags, NULL);
+ ret = __lock_checklocker(lt, lockp, lockp->holder, flags);
/* Check if object should be reclaimed. */
- if (SH_TAILQ_FIRST(&sh_obj->holders, __db_lock) == NULL
- && SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL) {
+ if (SH_TAILQ_FIRST(&sh_obj->holders, __db_lock) == NULL &&
+ SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL) {
HASHREMOVE_EL(lt->obj_tab,
obj_ndx, __db_lockobj, links, sh_obj);
if (sh_obj->lockobj.size > sizeof(sh_obj->objdata))
@@ -838,7 +1131,7 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
SH_DBT_PTR(&sh_obj->lockobj));
SH_TAILQ_INSERT_HEAD(
&region->free_objs, sh_obj, links, __db_lockobj);
- region->nobjects--;
+ region->stat.st_nobjects--;
state_changed = 1;
}
@@ -847,7 +1140,7 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
lockp->status = DB_LSTAT_FREE;
SH_TAILQ_INSERT_HEAD(
&region->free_locks, lockp, links, __db_lock);
- region->nlocks--;
+ region->stat.st_nlocks--;
}
/*
@@ -872,11 +1165,10 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
* Must be called without the locker's lock set.
*/
static int
-__lock_checklocker(lt, lockp, locker, flags, freed)
+__lock_checklocker(lt, lockp, locker, flags)
DB_LOCKTAB *lt;
struct __db_lock *lockp;
u_int32_t locker, flags;
- int *freed;
{
DB_ENV *dbenv;
DB_LOCKER *sh_locker;
@@ -888,17 +1180,14 @@ __lock_checklocker(lt, lockp, locker, flags, freed)
region = lt->reginfo.primary;
ret = 0;
- if (freed != NULL)
- *freed = 0;
-
LOCKER_LOCK(lt, region, locker, indx);
/* If the locker's list is NULL, free up the locker. */
if ((ret = __lock_getlocker(lt,
locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL) {
if (ret == 0)
- ret = EACCES;
- __db_err(lt->dbenv, __db_locker_invalid);
+ ret = EINVAL;
+ __db_err(dbenv, __db_locker_invalid);
goto freelock;
}
@@ -908,22 +1197,25 @@ __lock_checklocker(lt, lockp, locker, flags, freed)
goto freelock;
}
- if (LF_ISSET(DB_LOCK_UNLINK))
+ if (LF_ISSET(DB_LOCK_UNLINK)) {
SH_LIST_REMOVE(lockp, locker_links, __db_lock);
+ if (lockp->status == DB_LSTAT_HELD) {
+ sh_locker->nlocks--;
+ if (IS_WRITELOCK(lockp->mode))
+ sh_locker->nwrites--;
+ }
+ }
- if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL
- && LOCKER_FREEABLE(sh_locker)) {
+ if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL &&
+ LF_ISSET(DB_LOCK_FREE_LOCKER))
__lock_freelocker( lt, region, sh_locker, indx);
- if (freed != NULL)
- *freed = 1;
- }
freelock:
if (LF_ISSET(DB_LOCK_FREE)) {
lockp->status = DB_LSTAT_FREE;
SH_TAILQ_INSERT_HEAD(
&region->free_locks, lockp, links, __db_lock);
- region->nlocks--;
+ region->stat.st_nlocks--;
}
return (ret);
@@ -1019,11 +1311,9 @@ __lock_freefamilylocker(lt, locker)
LOCKER_LOCK(lt, region, locker, indx);
if ((ret = __lock_getlocker(lt,
- locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL) {
- if (ret == 0)
- ret = EACCES;
+ locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL)
goto freelock;
- }
+
if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) != NULL) {
ret = EINVAL;
__db_err(dbenv, "Freeing locker with locks");
@@ -1046,11 +1336,8 @@ freelock:
* common code for deleting a locker.
*
* This must be called with the locker bucket locked.
- *
- * PUBLIC: void __lock_freelocker __P((DB_LOCKTAB *,
- * PUBLIC: DB_LOCKREGION *, DB_LOCKER *, u_int32_t));
*/
-void
+static void
__lock_freelocker(lt, region, sh_locker, indx)
DB_LOCKTAB *lt;
DB_LOCKREGION *region;
@@ -1062,7 +1349,123 @@ __lock_freelocker(lt, region, sh_locker, indx)
lt->locker_tab, indx, __db_locker, links, sh_locker);
SH_TAILQ_INSERT_HEAD(
&region->free_lockers, sh_locker, links, __db_locker);
- region->nlockers--;
+ SH_TAILQ_REMOVE(&region->lockers, sh_locker, ulinks, __db_locker);
+ region->stat.st_nlockers--;
+}
+
+/*
+ * __lock_set_timeout
+ * -- set timeout values in shared memory.
+ * This is called from the transaction system.
+ * We either set the time that this tranaction expires or the
+ * amount of time that a lock for this transaction is permitted
+ * to wait.
+ *
+ * PUBLIC: int __lock_set_timeout __P(( DB_ENV *,
+ * PUBLIC: u_int32_t, db_timeout_t, u_int32_t));
+ */
+int
+__lock_set_timeout(dbenv, locker, timeout, op)
+ DB_ENV *dbenv;
+ u_int32_t locker;
+ db_timeout_t timeout;
+ u_int32_t op;
+{
+ DB_LOCKER *sh_locker;
+ DB_LOCKREGION *region;
+ DB_LOCKTAB *lt;
+ u_int32_t locker_ndx;
+ int ret;
+
+ lt = dbenv->lk_handle;
+ region = lt->reginfo.primary;
+ LOCKREGION(dbenv, lt);
+
+ LOCKER_LOCK(lt, region, locker, locker_ndx);
+ ret = __lock_getlocker(lt, locker, locker_ndx, 1, &sh_locker);
+ UNLOCKREGION(dbenv, lt);
+ if (ret != 0)
+ return (ret);
+
+ if (op == DB_SET_TXN_TIMEOUT) {
+ if (timeout == 0)
+ LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+ else
+ __lock_expires(dbenv, &sh_locker->tx_expire, timeout);
+ } else if (op == DB_SET_LOCK_TIMEOUT) {
+ sh_locker->lk_timeout = timeout;
+ F_SET(sh_locker, DB_LOCKER_TIMEOUT);
+ } else if (op == DB_SET_TXN_NOW) {
+ LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+ __lock_expires(dbenv, &sh_locker->tx_expire, 0);
+ sh_locker->lk_expire = sh_locker->tx_expire;
+ } else
+ return (EINVAL);
+
+ return (0);
+}
+
+/*
+ * __lock_inherit_timeout
+ * -- inherit timeout values from parent locker.
+ * This is called from the transaction system. This will
+ * return EINVAL if the parent does not exist or did not
+ * have a current txn timeout set.
+ *
+ * PUBLIC: int __lock_inherit_timeout __P(( DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__lock_inherit_timeout(dbenv, parent, locker)
+ DB_ENV *dbenv;
+ u_int32_t parent, locker;
+{
+ DB_LOCKER *parent_locker, *sh_locker;
+ DB_LOCKREGION *region;
+ DB_LOCKTAB *lt;
+ u_int32_t locker_ndx;
+ int ret;
+
+ lt = dbenv->lk_handle;
+ region = lt->reginfo.primary;
+ ret = 0;
+ LOCKREGION(dbenv, lt);
+
+ /* If the parent does not exist, we are done. */
+ LOCKER_LOCK(lt, region, parent, locker_ndx);
+ if ((ret = __lock_getlocker(lt,
+ parent, locker_ndx, 0, &parent_locker)) != 0)
+ goto err;
+
+ /*
+ * If the parent is not there yet, thats ok. If it
+ * does not have any timouts set, then avoid creating
+ * the child locker at this point.
+ */
+ if (parent_locker == NULL ||
+ (LOCK_TIME_ISVALID(&parent_locker->tx_expire) &&
+ !F_ISSET(parent_locker, DB_LOCKER_TIMEOUT))) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ LOCKER_LOCK(lt, region, locker, locker_ndx);
+ if ((ret = __lock_getlocker(lt,
+ locker, locker_ndx, 1, &sh_locker)) != 0)
+ goto err;
+
+ sh_locker->tx_expire = parent_locker->tx_expire;
+
+ if (F_ISSET(parent_locker, DB_LOCKER_TIMEOUT)) {
+ sh_locker->lk_timeout = parent_locker->lk_timeout;
+ F_SET(sh_locker, DB_LOCKER_TIMEOUT);
+ if (!LOCK_TIME_ISVALID(&parent_locker->tx_expire))
+ ret = EINVAL;
+ }
+
+done:
+err:
+ UNLOCKREGION(dbenv, lt);
+ return (ret);
}
/*
@@ -1101,13 +1504,13 @@ __lock_getlocker(lt, locker, indx, create, retp)
/* Create new locker and then insert it into hash table. */
if ((sh_locker = SH_TAILQ_FIRST(
&region->free_lockers, __db_locker)) == NULL) {
- __db_err(lt->dbenv, __db_lock_err, "locker entries");
+ __db_err(dbenv, __db_lock_err, "locker entries");
return (ENOMEM);
}
SH_TAILQ_REMOVE(
&region->free_lockers, sh_locker, links, __db_locker);
- if (++region->nlockers > region->maxnlockers)
- region->maxnlockers = region->nlockers;
+ if (++region->stat.st_nlockers > region->stat.st_maxnlockers)
+ region->stat.st_maxnlockers = region->stat.st_nlockers;
sh_locker->id = locker;
sh_locker->dd_id = 0;
@@ -1116,8 +1519,18 @@ __lock_getlocker(lt, locker, indx, create, retp)
SH_LIST_INIT(&sh_locker->child_locker);
sh_locker->flags = 0;
SH_LIST_INIT(&sh_locker->heldby);
+ sh_locker->nlocks = 0;
+ sh_locker->nwrites = 0;
+ sh_locker->lk_timeout = 0;
+ LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+ if (locker < TXN_MINIMUM && region->tx_timeout != 0)
+ __lock_expires(dbenv,
+ &sh_locker->tx_expire, region->tx_timeout);
+ LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
HASHINSERT(lt->locker_tab, indx, __db_locker, links, sh_locker);
+ SH_TAILQ_INSERT_HEAD(&region->lockers,
+ sh_locker, ulinks, __db_locker);
}
*retp = sh_locker;
@@ -1131,11 +1544,8 @@ __lock_getlocker(lt, locker, indx, create, retp)
* the table.
*
* This must be called with the object bucket locked.
- *
- * PUBLIC: int __lock_getobj __P((DB_LOCKTAB *,
- * PUBLIC: const DBT *, u_int32_t, int, DB_LOCKOBJ **));
*/
-int
+static int
__lock_getobj(lt, obj, ndx, create, retp)
DB_LOCKTAB *lt;
const DBT *obj;
@@ -1185,8 +1595,8 @@ __lock_getobj(lt, obj, ndx, create, retp)
SH_TAILQ_REMOVE(
&region->free_objs, sh_obj, links, __db_lockobj);
- if (++region->nobjects > region->maxnobjects)
- region->maxnobjects = region->nobjects;
+ if (++region->stat.st_nobjects > region->stat.st_maxnobjects)
+ region->stat.st_maxnobjects = region->stat.st_nobjects;
SH_TAILQ_INIT(&sh_obj->waiters);
SH_TAILQ_INIT(&sh_obj->holders);
@@ -1220,7 +1630,7 @@ __lock_is_parent(lt, locker, sh_locker)
parent = sh_locker;
while (parent->parent_locker != INVALID_ROFF) {
parent = (DB_LOCKER *)
- R_ADDR(&lt->reginfo, parent->parent_locker);
+ R_ADDR(&lt->reginfo, parent->parent_locker);
if (parent->id == locker)
return (1);
}
@@ -1234,13 +1644,13 @@ __lock_is_parent(lt, locker, sh_locker)
* Look through the waiters and holders lists and decide which (if any)
* locks can be promoted. Promote any that are eligible.
*
- * PUBLIC: int __lock_promote __P((DB_LOCKTAB *, DB_LOCKOBJ *, int));
+ * PUBLIC: int __lock_promote __P((DB_LOCKTAB *, DB_LOCKOBJ *, u_int32_t));
*/
int
-__lock_promote(lt, obj, not_waiters)
+__lock_promote(lt, obj, flags)
DB_LOCKTAB *lt;
DB_LOCKOBJ *obj;
- int not_waiters;
+ u_int32_t flags;
{
struct __db_lock *lp_w, *lp_h, *next_waiter;
DB_LOCKER *sh_locker;
@@ -1270,16 +1680,25 @@ __lock_promote(lt, obj, not_waiters)
lp_w = next_waiter) {
had_waiters = 1;
next_waiter = SH_TAILQ_NEXT(lp_w, links, __db_lock);
+
+ /* Waiter may have aborted or expired. */
+ if (lp_w->status != DB_LSTAT_WAITING)
+ continue;
/* Are we switching locks? */
- if (not_waiters && lp_w->mode == DB_LOCK_WAIT)
+ if (LF_ISSET(DB_LOCK_NOWAITERS) && lp_w->mode == DB_LOCK_WAIT)
continue;
+
+ if (LF_ISSET(DB_LOCK_REMOVE)) {
+ __lock_remove_waiter(lt, obj, lp_w, DB_LSTAT_NOTEXIST);
+ continue;
+ }
for (lp_h = SH_TAILQ_FIRST(&obj->holders, __db_lock);
lp_h != NULL;
lp_h = SH_TAILQ_NEXT(lp_h, links, __db_lock)) {
if (lp_h->holder != lp_w->holder &&
CONFLICTS(lt, region, lp_h->mode, lp_w->mode)) {
-
- LOCKER_LOCK(lt, region, lp_w->holder, locker_ndx);
+ LOCKER_LOCK(lt,
+ region, lp_w->holder, locker_ndx);
if ((__lock_getlocker(lt, lp_w->holder,
locker_ndx, 0, &sh_locker)) != 0) {
DB_ASSERT(0);
@@ -1323,19 +1742,26 @@ __lock_promote(lt, obj, not_waiters)
* This must be called with the Object bucket locked.
*/
static void
-__lock_remove_waiter(dbenv, sh_obj, lockp, status)
- DB_ENV *dbenv;
+__lock_remove_waiter(lt, sh_obj, lockp, status)
+ DB_LOCKTAB *lt;
DB_LOCKOBJ *sh_obj;
struct __db_lock *lockp;
db_status_t status;
{
+ DB_LOCKREGION *region;
int do_wakeup;
+ region = lt->reginfo.primary;
+
do_wakeup = lockp->status == DB_LSTAT_WAITING;
SH_TAILQ_REMOVE(&sh_obj->waiters, lockp, links, __db_lock);
lockp->links.stqe_prev = -1;
lockp->status = status;
+ if (SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL)
+ SH_TAILQ_REMOVE(
+ &region->dd_objs,
+ sh_obj, dd_links, __db_lockobj);
/*
* Wake whoever is waiting on this lock.
@@ -1344,96 +1770,105 @@ __lock_remove_waiter(dbenv, sh_obj, lockp, status)
* keep the compiler quiet.
*/
if (do_wakeup)
- MUTEX_UNLOCK(dbenv, &lockp->mutex);
+ MUTEX_UNLOCK(lt->dbenv, &lockp->mutex);
}
/*
- * __lock_printlock --
- *
- * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
+ * __lock_expires -- set the expire time given the time to live.
+ * We assume that if timevalp is set then it contains "now".
+ * This avoids repeated system calls to get the time.
*/
-void
-__lock_printlock(lt, lp, ispgno)
- DB_LOCKTAB *lt;
- struct __db_lock *lp;
- int ispgno;
+static void
+__lock_expires(dbenv, timevalp, timeout)
+ DB_ENV *dbenv;
+ db_timeval_t *timevalp;
+ db_timeout_t timeout;
{
- DB_LOCKOBJ *lockobj;
- db_pgno_t pgno;
- u_int32_t *fidp;
- u_int8_t *ptr, type;
- const char *mode, *status;
-
- switch (lp->mode) {
- case DB_LOCK_IREAD:
- mode = "IREAD";
- break;
- case DB_LOCK_IWR:
- mode = "IWR";
- break;
- case DB_LOCK_IWRITE:
- mode = "IWRITE";
- break;
- case DB_LOCK_NG:
- mode = "NG";
- break;
- case DB_LOCK_READ:
- mode = "READ";
- break;
- case DB_LOCK_WRITE:
- mode = "WRITE";
- break;
- case DB_LOCK_WAIT:
- mode = "WAIT";
- break;
- default:
- mode = "UNKNOWN";
- break;
- }
- switch (lp->status) {
- case DB_LSTAT_ABORTED:
- status = "ABORT";
- break;
- case DB_LSTAT_ERR:
- status = "ERROR";
- break;
- case DB_LSTAT_FREE:
- status = "FREE";
- break;
- case DB_LSTAT_HELD:
- status = "HELD";
- break;
- case DB_LSTAT_NOGRANT:
- status = "NONE";
- break;
- case DB_LSTAT_WAITING:
- status = "WAIT";
- break;
- case DB_LSTAT_PENDING:
- status = "PENDING";
- break;
- default:
- status = "UNKNOWN";
- break;
+ if (!LOCK_TIME_ISVALID(timevalp))
+ __os_clock(dbenv, &timevalp->tv_sec, &timevalp->tv_usec);
+ if (timeout > 1000000) {
+ timevalp->tv_sec += timeout / 1000000;
+ timevalp->tv_usec += timeout % 1000000;
+ } else
+ timevalp->tv_usec += timeout;
+
+ if (timevalp->tv_usec > 1000000) {
+ timevalp->tv_sec++;
+ timevalp->tv_usec -= 1000000;
}
- printf("\t%lx\t%s\t%lu\t%s\t",
- (u_long)lp->holder, mode, (u_long)lp->refcount, status);
-
- lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
- ptr = SH_DBT_PTR(&lockobj->lockobj);
- if (ispgno && lockobj->lockobj.size == sizeof(struct __db_ilock)) {
- /* Assume this is a DBT lock. */
- memcpy(&pgno, ptr, sizeof(db_pgno_t));
- fidp = (u_int32_t *)(ptr + sizeof(db_pgno_t));
- type = *(u_int8_t *)(ptr + sizeof(db_pgno_t) + DB_FILE_ID_LEN);
- printf("%s %lu (%lu %lu %lu %lu %lu)\n",
- type == DB_PAGE_LOCK ? "page" : "record",
- (u_long)pgno,
- (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
- (u_long)fidp[3], (u_long)fidp[4]);
- } else {
- printf("0x%lx ", (u_long)R_OFFSET(&lt->reginfo, lockobj));
- __db_pr(ptr, lockobj->lockobj.size);
- printf("\n");
+}
+
+/*
+ * __lock_expired -- determine if a lock has expired.
+ *
+ * PUBLIC: int __lock_expired __P((DB_ENV *, db_timeval_t *, db_timeval_t *));
+ */
+int
+__lock_expired(dbenv, now, timevalp)
+ DB_ENV *dbenv;
+ db_timeval_t *now, *timevalp;
+{
+ if (!LOCK_TIME_ISVALID(timevalp))
+ return (0);
+
+ if (!LOCK_TIME_ISVALID(now))
+ __os_clock(dbenv, &now->tv_sec, &now->tv_usec);
+
+ return (now->tv_sec > timevalp->tv_sec ||
+ (now->tv_sec == timevalp->tv_sec &&
+ now->tv_usec >= timevalp->tv_usec));
+}
+
+/*
+ * __lock_trade --
+ *
+ * Trade locker ids on a lock. This is used to reassign file locks from
+ * a transactional locker id to a long-lived locker id. This should be
+ * called with the region mutex held.
+ */
+static int
+__lock_trade(dbenv, lock, new_locker)
+ DB_ENV *dbenv;
+ DB_LOCK *lock;
+ u_int32_t new_locker;
+{
+ struct __db_lock *lp;
+ DB_LOCKREGION *region;
+ DB_LOCKTAB *lt;
+ DB_LOCKER *sh_locker;
+ int ret;
+ u_int32_t locker_ndx;
+
+ lt = dbenv->lk_handle;
+ region = lt->reginfo.primary;
+
+ lp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
+
+ /* If the lock is already released, simply return. */
+ if (lp->gen != lock->gen)
+ return (DB_NOTFOUND);
+
+ /* Make sure that we can get new locker and add this lock to it. */
+ LOCKER_LOCK(lt, region, new_locker, locker_ndx);
+ if ((ret =
+ __lock_getlocker(lt, new_locker, locker_ndx, 0, &sh_locker)) != 0)
+ return (ret);
+
+ if (sh_locker == NULL) {
+ __db_err(dbenv, "Locker does not exist");
+ return (EINVAL);
}
+
+ /* Remove the lock from its current locker. */
+ if ((ret = __lock_checklocker(lt, lp, lp->holder, DB_LOCK_UNLINK)) != 0)
+ return (ret);
+
+ /* Add lock to its new locker. */
+ SH_LIST_INSERT_HEAD(&sh_locker->heldby, lp, locker_links, __db_lock);
+ sh_locker->nlocks++;
+ if (IS_WRITELOCK(lp->mode))
+ sh_locker->nwrites++;
+ lp->holder = new_locker;
+
+ return (0);
}
diff --git a/bdb/lock/lock_conflict.c b/bdb/lock/lock_conflict.c
deleted file mode 100644
index 2d7945fe201..00000000000
--- a/bdb/lock/lock_conflict.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: lock_conflict.c,v 11.6 2000/12/12 17:38:13 bostic Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-#endif
-
-#include "db_int.h"
-
-/*
- * The conflict arrays are set up such that the row is the lock you
- * are holding and the column is the lock that is desired.
- */
-
-const u_int8_t db_riw_conflicts[] = {
- /* N S X WT IX IS SIX */
- /* N */ 0, 0, 0, 0, 0, 0, 0,
- /* S */ 0, 0, 1, 0, 1, 0, 1,
- /* X */ 0, 1, 1, 1, 1, 1, 1,
- /* WT */ 0, 0, 0, 0, 0, 0, 0,
- /* IX */ 0, 1, 1, 0, 0, 0, 0,
- /* IS */ 0, 0, 1, 0, 0, 0, 0,
- /* SIX */ 0, 1, 1, 0, 0, 0, 0
-};
diff --git a/bdb/lock/lock_deadlock.c b/bdb/lock/lock_deadlock.c
index 1f37db3890e..d1461b89a4f 100644
--- a/bdb/lock/lock_deadlock.c
+++ b/bdb/lock/lock_deadlock.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock_deadlock.c,v 11.23 2000/12/08 20:15:31 ubell Exp $";
+static const char revid[] = "$Id: lock_deadlock.c,v 11.54 2002/08/06 05:05:21 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,19 +17,11 @@ static const char revid[] = "$Id: lock_deadlock.c,v 11.23 2000/12/08 20:15:31 ub
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "txn.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/txn.h"
+#include "dbinc/rep.h"
#define ISSET_MAP(M, N) ((M)[(N) / 32] & (1 << (N) % 32))
@@ -51,6 +43,8 @@ static const char revid[] = "$Id: lock_deadlock.c,v 11.23 2000/12/08 20:15:31 ub
typedef struct {
int valid;
+ int self_wait;
+ u_int32_t count;
u_int32_t id;
u_int32_t last_lock;
u_int32_t last_locker_id;
@@ -58,152 +52,232 @@ typedef struct {
} locker_info;
static int __dd_abort __P((DB_ENV *, locker_info *));
-static int __dd_build
- __P((DB_ENV *, u_int32_t **, u_int32_t *, locker_info **));
-static int __dd_find
- __P((DB_ENV *,u_int32_t *, locker_info *, u_int32_t, u_int32_t ***));
+static int __dd_build __P((DB_ENV *,
+ u_int32_t, u_int32_t **, u_int32_t *, u_int32_t *, locker_info **));
+static int __dd_find __P((DB_ENV *,
+ u_int32_t *, locker_info *, u_int32_t, u_int32_t, u_int32_t ***));
+static int __dd_isolder __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+static int __dd_verify __P((locker_info *, u_int32_t *, u_int32_t *,
+ u_int32_t *, u_int32_t, u_int32_t, u_int32_t));
#ifdef DIAGNOSTIC
-static void __dd_debug __P((DB_ENV *, locker_info *, u_int32_t *, u_int32_t));
+static void __dd_debug
+ __P((DB_ENV *, locker_info *, u_int32_t *, u_int32_t, u_int32_t));
#endif
+/*
+ * lock_detect --
+ *
+ * PUBLIC: int __lock_detect __P((DB_ENV *, u_int32_t, u_int32_t, int *));
+ */
int
-lock_detect(dbenv, flags, atype, abortp)
+__lock_detect(dbenv, flags, atype, abortp)
DB_ENV *dbenv;
u_int32_t flags, atype;
int *abortp;
{
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
+ DB_TXNMGR *tmgr;
locker_info *idmap;
- u_int32_t *bitmap, **deadp, **free_me, i, killid, nentries, nlockers;
- int do_pass, ret;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_detect(dbenv, flags, atype, abortp));
-#endif
+ u_int32_t *bitmap, *copymap, **deadp, **free_me, *tmpmap;
+ u_int32_t i, keeper, killid, limit, nalloc, nlockers;
+ u_int32_t lock_max, txn_max;
+ int ret;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_detect", DB_INIT_LOCK);
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "DB_ENV->lock_detect", flags, 0)) != 0)
+ return (ret);
+ switch (atype) {
+ case DB_LOCK_DEFAULT:
+ case DB_LOCK_EXPIRE:
+ case DB_LOCK_MAXLOCKS:
+ case DB_LOCK_MINLOCKS:
+ case DB_LOCK_MINWRITE:
+ case DB_LOCK_OLDEST:
+ case DB_LOCK_RANDOM:
+ case DB_LOCK_YOUNGEST:
+ break;
+ default:
+ __db_err(dbenv,
+ "DB_ENV->lock_detect: unknown deadlock detection mode specified");
+ return (EINVAL);
+ }
+
+ /*
+ * If this environment is a replication client, then we must use the
+ * MINWRITE detection discipline.
+ */
+ if (__rep_is_client(dbenv))
+ atype = DB_LOCK_MINWRITE;
+
+ free_me = NULL;
lt = dbenv->lk_handle;
if (abortp != NULL)
*abortp = 0;
- /* Validate arguments. */
- if ((ret =
- __db_fchk(dbenv, "lock_detect", flags, DB_LOCK_CONFLICT)) != 0)
- return (ret);
-
/* Check if a detector run is necessary. */
LOCKREGION(dbenv, lt);
- if (LF_ISSET(DB_LOCK_CONFLICT)) {
- /* Make a pass every time a lock waits. */
- region = lt->reginfo.primary;
- do_pass = region->need_dd != 0;
- if (!do_pass) {
- UNLOCKREGION(dbenv, lt);
- return (0);
- }
+ /* Make a pass only if auto-detect would run. */
+ region = lt->reginfo.primary;
+
+ if (region->need_dd == 0) {
+ UNLOCKREGION(dbenv, lt);
+ return (0);
}
+ /* Reset need_dd, so we know we've run the detector. */
+ region->need_dd = 0;
+
/* Build the waits-for bitmap. */
- ret = __dd_build(dbenv, &bitmap, &nlockers, &idmap);
+ ret = __dd_build(dbenv, atype, &bitmap, &nlockers, &nalloc, &idmap);
+ lock_max = region->stat.st_cur_maxid;
UNLOCKREGION(dbenv, lt);
- if (ret != 0)
+
+ /*
+ * We need the cur_maxid from the txn region as well. In order
+ * to avoid tricky synchronization between the lock and txn
+ * regions, we simply unlock the lock region and then lock the
+ * txn region. This introduces a small window during which the
+ * transaction system could then wrap. We're willing to return
+ * the wrong answer for "oldest" or "youngest" in those rare
+ * circumstances.
+ */
+ tmgr = dbenv->tx_handle;
+ if (tmgr != NULL) {
+ R_LOCK(dbenv, &tmgr->reginfo);
+ txn_max = ((DB_TXNREGION *)tmgr->reginfo.primary)->cur_maxid;
+ R_UNLOCK(dbenv, &tmgr->reginfo);
+ } else
+ txn_max = TXN_MAXIMUM;
+ if (ret != 0 || atype == DB_LOCK_EXPIRE)
return (ret);
if (nlockers == 0)
return (0);
#ifdef DIAGNOSTIC
if (FLD_ISSET(dbenv->verbose, DB_VERB_WAITSFOR))
- __dd_debug(dbenv, idmap, bitmap, nlockers);
+ __dd_debug(dbenv, idmap, bitmap, nlockers, nalloc);
#endif
+ /* Now duplicate the bitmaps so we can verify deadlock participants. */
+ if ((ret = __os_calloc(dbenv, (size_t)nlockers,
+ sizeof(u_int32_t) * nalloc, &copymap)) != 0)
+ goto err;
+ memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc);
+
+ if ((ret = __os_calloc(dbenv, sizeof(u_int32_t), nalloc, &tmpmap)) != 0)
+ goto err1;
+
/* Find a deadlock. */
- if ((ret = __dd_find(dbenv, bitmap, idmap, nlockers, &deadp)) != 0)
+ if ((ret =
+ __dd_find(dbenv, bitmap, idmap, nlockers, nalloc, &deadp)) != 0)
return (ret);
- nentries = ALIGN(nlockers, 32) / 32;
killid = BAD_KILLID;
free_me = deadp;
for (; *deadp != NULL; deadp++) {
if (abortp != NULL)
++*abortp;
- switch (atype) { /* Kill someone. */
- case DB_LOCK_OLDEST:
- /*
- * Find the first bit set in the current
- * array and then look for a lower tid in
- * the array.
- */
- for (i = 0; i < nlockers; i++)
- if (ISSET_MAP(*deadp, i)) {
- killid = i;
- break;
+ killid = (u_int32_t)((*deadp - bitmap) / nalloc);
+ limit = killid;
+ keeper = BAD_KILLID;
- }
- /*
- * It's conceivable that under XA, the locker could
- * have gone away.
- */
- if (killid == BAD_KILLID)
- break;
-
- /*
- * The oldest transaction has the lowest
- * transaction id.
- */
- for (i = killid + 1; i < nlockers; i++)
- if (ISSET_MAP(*deadp, i) &&
- idmap[i].id < idmap[killid].id)
- killid = i;
- break;
- case DB_LOCK_DEFAULT:
- case DB_LOCK_RANDOM:
- /*
- * We are trying to calculate the id of the
- * locker whose entry is indicated by deadlock.
- */
- killid = (*deadp - bitmap) / nentries;
+ if (atype == DB_LOCK_DEFAULT || atype == DB_LOCK_RANDOM)
+ goto dokill;
+ /*
+ * It's conceivable that under XA, the locker could
+ * have gone away.
+ */
+ if (killid == BAD_KILLID)
break;
- case DB_LOCK_YOUNGEST:
- /*
- * Find the first bit set in the current
- * array and then look for a lower tid in
- * the array.
- */
- for (i = 0; i < nlockers; i++)
- if (ISSET_MAP(*deadp, i)) {
- killid = i;
- break;
- }
- /*
- * It's conceivable that under XA, the locker could
- * have gone away.
- */
- if (killid == BAD_KILLID)
- break;
+ /*
+ * Start with the id that we know is deadlocked
+ * and then examine all other set bits and see
+ * if any are a better candidate for abortion
+ * and that they are genuinely part of the
+ * deadlock. The definition of "best":
+ * OLDEST: smallest id
+ * YOUNGEST: largest id
+ * MAXLOCKS: maximum count
+ * MINLOCKS: minimum count
+ * MINWRITE: minimum count
+ */
- /*
- * The youngest transaction has the highest
- * transaction id.
- */
- for (i = killid + 1; i < nlockers; i++)
- if (ISSET_MAP(*deadp, i) &&
- idmap[i].id > idmap[killid].id)
- killid = i;
- break;
- default:
- killid = BAD_KILLID;
- ret = EINVAL;
+ for (i = (killid + 1) % nlockers;
+ i != limit;
+ i = (i + 1) % nlockers) {
+ if (!ISSET_MAP(*deadp, i))
+ continue;
+ switch (atype) {
+ case DB_LOCK_OLDEST:
+ if (__dd_isolder(idmap[killid].id,
+ idmap[i].id, lock_max, txn_max))
+ continue;
+ keeper = i;
+ break;
+ case DB_LOCK_YOUNGEST:
+ if (__dd_isolder(idmap[i].id,
+ idmap[killid].id, lock_max, txn_max))
+ continue;
+ keeper = i;
+ break;
+ case DB_LOCK_MAXLOCKS:
+ if (idmap[i].count < idmap[killid].count)
+ continue;
+ keeper = i;
+ break;
+ case DB_LOCK_MINLOCKS:
+ case DB_LOCK_MINWRITE:
+ if (idmap[i].count > idmap[killid].count)
+ continue;
+ keeper = i;
+ break;
+ default:
+ killid = BAD_KILLID;
+ ret = EINVAL;
+ goto dokill;
+ }
+ if (__dd_verify(idmap, *deadp,
+ tmpmap, copymap, nlockers, nalloc, i))
+ killid = i;
}
- if (killid == BAD_KILLID)
+dokill: if (killid == BAD_KILLID)
continue;
+ /*
+ * There are cases in which our general algorithm will
+ * fail. Returning 1 from verify indicates that the
+ * particular locker is not only involved in a deadlock,
+ * but that killing him will allow others to make forward
+ * progress. Unfortunately, there are cases where we need
+ * to abort someone, but killing them will not necessarily
+ * ensure forward progress (imagine N readers all trying to
+ * acquire a write lock). In such a scenario, we'll have
+ * gotten all the way through the loop, we will have found
+ * someone to keep (keeper will be valid), but killid will
+ * still be the initial deadlocker. In this case, if the
+ * initial killid satisfies __dd_verify, kill it, else abort
+ * keeper and indicate that we need to run deadlock detection
+ * again.
+ */
+
+ if (keeper != BAD_KILLID && killid == limit &&
+ __dd_verify(idmap, *deadp,
+ tmpmap, copymap, nlockers, nalloc, killid) == 0) {
+ LOCKREGION(dbenv, lt);
+ region->need_dd = 1;
+ UNLOCKREGION(dbenv, lt);
+ killid = keeper;
+ }
+
/* Kill the locker with lockid idmap[killid]. */
if ((ret = __dd_abort(dbenv, &idmap[killid])) != 0) {
/*
@@ -221,9 +295,13 @@ lock_detect(dbenv, flags, atype, abortp)
__db_err(dbenv,
"Aborting locker %lx", (u_long)idmap[killid].id);
}
- __os_free(free_me, 0);
- __os_free(bitmap, 0);
- __os_free(idmap, 0);
+ __os_free(dbenv, tmpmap);
+err1: __os_free(dbenv, copymap);
+
+err: if (free_me != NULL)
+ __os_free(dbenv, free_me);
+ __os_free(dbenv, bitmap);
+ __os_free(dbenv, idmap);
return (ret);
}
@@ -236,9 +314,9 @@ lock_detect(dbenv, flags, atype, abortp)
# define DD_INVALID_ID ((u_int32_t) -1)
static int
-__dd_build(dbenv, bmp, nlockers, idmap)
+__dd_build(dbenv, atype, bmp, nlockers, allocp, idmap)
DB_ENV *dbenv;
- u_int32_t **bmp, *nlockers;
+ u_int32_t atype, **bmp, *nlockers, *allocp;
locker_info **idmap;
{
struct __db_lock *lp;
@@ -247,12 +325,30 @@ __dd_build(dbenv, bmp, nlockers, idmap)
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
locker_info *id_array;
- u_int32_t *bitmap, count, dd, *entryp, i, id, ndx, nentries, *tmpmap;
+ db_timeval_t now;
+ u_int32_t *bitmap, count, dd, *entryp, id, ndx, nentries, *tmpmap;
u_int8_t *pptr;
- int is_first, ret;
+ int expire_only, is_first, need_timeout, ret;
lt = dbenv->lk_handle;
region = lt->reginfo.primary;
+ LOCK_SET_TIME_INVALID(&now);
+ need_timeout = 0;
+ expire_only = atype == DB_LOCK_EXPIRE;
+
+ /*
+ * While we always check for expired timeouts, if we are called
+ * with DB_LOCK_EXPIRE, then we are only checking for timeouts
+ * (i.e., not doing deadlock detection at all). If we aren't
+ * doing real deadlock detection, then we can skip a significant,
+ * amount of the processing. In particular we do not build
+ * the conflict array and our caller needs to expect this.
+ */
+ if (expire_only) {
+ count = 0;
+ nentries = 0;
+ goto obj_loop;
+ }
/*
* We'll check how many lockers there are, add a few more in for
@@ -260,8 +356,7 @@ __dd_build(dbenv, bmp, nlockers, idmap)
* verify that we have enough room when we go back in and get the
* mutex the second time.
*/
-retry: count = region->nlockers;
- region->need_dd = 0;
+retry: count = region->stat.st_nlockers;
if (count == 0) {
*nlockers = 0;
@@ -271,7 +366,7 @@ retry: count = region->nlockers;
if (FLD_ISSET(dbenv->verbose, DB_VERB_DEADLOCK))
__db_err(dbenv, "%lu lockers", (u_long)count);
- count += 40;
+ count += 20;
nentries = ALIGN(count, 32) / 32;
/*
@@ -287,38 +382,46 @@ retry: count = region->nlockers;
if ((ret = __os_calloc(dbenv,
sizeof(u_int32_t), nentries, &tmpmap)) != 0) {
- __os_free(bitmap, sizeof(u_int32_t) * nentries);
+ __os_free(dbenv, bitmap);
return (ret);
}
if ((ret = __os_calloc(dbenv,
(size_t)count, sizeof(locker_info), &id_array)) != 0) {
- __os_free(bitmap, count * sizeof(u_int32_t) * nentries);
- __os_free(tmpmap, sizeof(u_int32_t) * nentries);
+ __os_free(dbenv, bitmap);
+ __os_free(dbenv, tmpmap);
return (ret);
}
/*
* Now go back in and actually fill in the matrix.
*/
- if (region->nlockers > count) {
- __os_free(bitmap, count * sizeof(u_int32_t) * nentries);
- __os_free(tmpmap, sizeof(u_int32_t) * nentries);
- __os_free(id_array, count * sizeof(locker_info));
+ if (region->stat.st_nlockers > count) {
+ __os_free(dbenv, bitmap);
+ __os_free(dbenv, tmpmap);
+ __os_free(dbenv, id_array);
goto retry;
}
/*
* First we go through and assign each locker a deadlock detector id.
*/
- for (id = 0, i = 0; i < region->locker_t_size; i++) {
- for (lip = SH_TAILQ_FIRST(&lt->locker_tab[i], __db_locker);
- lip != NULL; lip = SH_TAILQ_NEXT(lip, links, __db_locker))
- if (lip->master_locker == INVALID_ROFF) {
- lip->dd_id = id++;
- id_array[lip->dd_id].id = lip->id;
- } else
- lip->dd_id = DD_INVALID_ID;
+ for (id = 0, lip = SH_TAILQ_FIRST(&region->lockers, __db_locker);
+ lip != NULL;
+ lip = SH_TAILQ_NEXT(lip, ulinks, __db_locker)) {
+ if (F_ISSET(lip, DB_LOCKER_INABORT))
+ continue;
+ if (lip->master_locker == INVALID_ROFF) {
+ lip->dd_id = id++;
+ id_array[lip->dd_id].id = lip->id;
+ if (atype == DB_LOCK_MINLOCKS ||
+ atype == DB_LOCK_MAXLOCKS)
+ id_array[lip->dd_id].count = lip->nlocks;
+ if (atype == DB_LOCK_MINWRITE)
+ id_array[lip->dd_id].count = lip->nwrites;
+ } else
+ lip->dd_id = DD_INVALID_ID;
+
}
/*
@@ -328,8 +431,11 @@ retry: count = region->nlockers;
* list and add an entry in the waitsfor matrix for each waiter/holder
* combination.
*/
+obj_loop:
for (op = SH_TAILQ_FIRST(&region->dd_objs, __db_lockobj);
op != NULL; op = SH_TAILQ_NEXT(op, dd_links, __db_lockobj)) {
+ if (expire_only)
+ goto look_waiters;
CLEAR_MAP(tmpmap, nentries);
/*
@@ -343,11 +449,20 @@ retry: count = region->nlockers;
if ((ret = __lock_getlocker(lt,
lp->holder, ndx, 0, &lockerp)) != 0)
continue;
- if (lockerp->dd_id == DD_INVALID_ID)
- dd = ((DB_LOCKER *)
- R_ADDR(&lt->reginfo,
- lockerp->master_locker))->dd_id;
- else
+ if (F_ISSET(lockerp, DB_LOCKER_INABORT))
+ continue;
+
+ if (lockerp->dd_id == DD_INVALID_ID) {
+ dd = ((DB_LOCKER *)R_ADDR(&lt->reginfo,
+ lockerp->master_locker))->dd_id;
+ lockerp->dd_id = dd;
+ if (atype == DB_LOCK_MINLOCKS ||
+ atype == DB_LOCK_MAXLOCKS)
+ id_array[dd].count += lockerp->nlocks;
+ if (atype == DB_LOCK_MINWRITE)
+ id_array[dd].count += lockerp->nwrites;
+
+ } else
dd = lockerp->dd_id;
id_array[dd].valid = 1;
@@ -363,6 +478,7 @@ retry: count = region->nlockers;
* Next, for each waiter, we set its row in the matrix
* equal to the map of holders we set up above.
*/
+look_waiters:
for (is_first = 1,
lp = SH_TAILQ_FIRST(&op->waiters, __db_lock);
lp != NULL;
@@ -372,11 +488,30 @@ retry: count = region->nlockers;
if ((ret = __lock_getlocker(lt,
lp->holder, ndx, 0, &lockerp)) != 0)
continue;
- if (lockerp->dd_id == DD_INVALID_ID)
- dd = ((DB_LOCKER *)
- R_ADDR(&lt->reginfo,
- lockerp->master_locker))->dd_id;
- else
+ if (lp->status == DB_LSTAT_WAITING) {
+ if (__lock_expired(dbenv,
+ &now, &lockerp->lk_expire)) {
+ lp->status = DB_LSTAT_EXPIRED;
+ MUTEX_UNLOCK(dbenv, &lp->mutex);
+ continue;
+ }
+ need_timeout =
+ LOCK_TIME_ISVALID(&lockerp->lk_expire);
+ }
+
+ if (expire_only)
+ continue;
+
+ if (lockerp->dd_id == DD_INVALID_ID) {
+ dd = ((DB_LOCKER *)R_ADDR(&lt->reginfo,
+ lockerp->master_locker))->dd_id;
+ lockerp->dd_id = dd;
+ if (atype == DB_LOCK_MINLOCKS ||
+ atype == DB_LOCK_MAXLOCKS)
+ id_array[dd].count += lockerp->nlocks;
+ if (atype == DB_LOCK_MINWRITE)
+ id_array[dd].count += lockerp->nwrites;
+ } else
dd = lockerp->dd_id;
id_array[dd].valid = 1;
@@ -396,11 +531,19 @@ retry: count = region->nlockers;
* else on the queue, then we have to keep
* it and we have an automatic deadlock.
*/
- if (is_first)
+ if (is_first) {
+ if (ISSET_MAP(entryp, dd))
+ id_array[dd].self_wait = 1;
CLR_MAP(entryp, dd);
+ }
}
}
+ if (expire_only) {
+ region->need_dd = need_timeout;
+ return (0);
+ }
+
/* Now for each locker; record its last lock. */
for (id = 0; id < count; id++) {
if (!id_array[id].valid)
@@ -423,7 +566,7 @@ retry: count = region->nlockers;
do {
lp = SH_LIST_FIRST(&child->heldby, __db_lock);
if (lp != NULL &&
- lp->status == DB_LSTAT_WAITING) {
+ lp->status == DB_LSTAT_WAITING) {
id_array[id].last_locker_id = child->id;
goto get_lock;
}
@@ -445,8 +588,11 @@ retry: count = region->nlockers;
}
}
- /* Pass complete, reset the deadlock detector bit. */
- region->need_dd = 0;
+ /*
+ * Pass complete, reset the deadlock detector bit,
+ * unless we have pending timeouts.
+ */
+ region->need_dd = need_timeout;
/*
* Now we can release everything except the bitmap matrix that we
@@ -455,18 +601,19 @@ retry: count = region->nlockers;
*nlockers = id;
*idmap = id_array;
*bmp = bitmap;
- __os_free(tmpmap, sizeof(u_int32_t) * nentries);
+ *allocp = nentries;
+ __os_free(dbenv, tmpmap);
return (0);
}
static int
-__dd_find(dbenv, bmp, idmap, nlockers, deadp)
+__dd_find(dbenv, bmp, idmap, nlockers, nalloc, deadp)
DB_ENV *dbenv;
- u_int32_t *bmp, nlockers;
+ u_int32_t *bmp, nlockers, nalloc;
locker_info *idmap;
u_int32_t ***deadp;
{
- u_int32_t i, j, k, nentries, *mymap, *tmpmap;
+ u_int32_t i, j, k, *mymap, *tmpmap;
u_int32_t **retp;
int ndead, ndeadalloc, ret;
@@ -476,15 +623,14 @@ __dd_find(dbenv, bmp, idmap, nlockers, deadp)
ndeadalloc = INITIAL_DEAD_ALLOC;
ndead = 0;
if ((ret = __os_malloc(dbenv,
- ndeadalloc * sizeof(u_int32_t *), NULL, &retp)) != 0)
+ ndeadalloc * sizeof(u_int32_t *), &retp)) != 0)
return (ret);
/*
* For each locker, OR in the bits from the lockers on which that
* locker is waiting.
*/
- nentries = ALIGN(nlockers, 32) / 32;
- for (mymap = bmp, i = 0; i < nlockers; i++, mymap += nentries) {
+ for (mymap = bmp, i = 0; i < nlockers; i++, mymap += nalloc) {
if (!idmap[i].valid)
continue;
for (j = 0; j < nlockers; j++) {
@@ -492,8 +638,8 @@ __dd_find(dbenv, bmp, idmap, nlockers, deadp)
continue;
/* Find the map for this bit. */
- tmpmap = bmp + (nentries * j);
- OR_MAP(mymap, tmpmap, nentries);
+ tmpmap = bmp + (nalloc * j);
+ OR_MAP(mymap, tmpmap, nalloc);
if (!ISSET_MAP(mymap, i))
continue;
@@ -506,7 +652,7 @@ __dd_find(dbenv, bmp, idmap, nlockers, deadp)
*/
if (__os_realloc(dbenv,
ndeadalloc * sizeof(u_int32_t),
- NULL, &retp) != 0) {
+ &retp) != 0) {
retp[ndead] = NULL;
*deadp = retp;
return (0);
@@ -543,6 +689,7 @@ __dd_abort(dbenv, info)
region = lt->reginfo.primary;
LOCKREGION(dbenv, lt);
+
/* Find the locker's last lock. */
LOCKER_LOCK(lt, region, info->last_locker_id, ndx);
if ((ret = __lock_getlocker(lt,
@@ -552,18 +699,12 @@ __dd_abort(dbenv, info)
goto out;
}
- lockp = SH_LIST_FIRST(&lockerp->heldby, __db_lock);
-
- /*
- * It's possible that this locker was already aborted. If that's
- * the case, make sure that we remove its locker from the hash table.
- */
- if (lockp == NULL) {
- if (LOCKER_FREEABLE(lockerp)) {
- __lock_freelocker(lt, region, lockerp, ndx);
- goto out;
- }
- } else if (R_OFFSET(&lt->reginfo, lockp) != info->last_lock ||
+ /* It's possible that this locker was already aborted. */
+ if ((lockp = SH_LIST_FIRST(&lockerp->heldby, __db_lock)) == NULL) {
+ ret = DB_ALREADY_ABORTED;
+ goto out;
+ }
+ if (R_OFFSET(&lt->reginfo, lockp) != info->last_lock ||
lockp->status != DB_LSTAT_WAITING) {
ret = DB_ALREADY_ABORTED;
goto out;
@@ -589,7 +730,7 @@ __dd_abort(dbenv, info)
ret = __lock_promote(lt, sh_obj, 0);
MUTEX_UNLOCK(dbenv, &lockp->mutex);
- region->ndeadlocks++;
+ region->stat.st_ndeadlocks++;
UNLOCKREGION(dbenv, lt);
return (0);
@@ -600,13 +741,12 @@ out: UNLOCKREGION(dbenv, lt);
#ifdef DIAGNOSTIC
static void
-__dd_debug(dbenv, idmap, bitmap, nlockers)
+__dd_debug(dbenv, idmap, bitmap, nlockers, nalloc)
DB_ENV *dbenv;
locker_info *idmap;
- u_int32_t *bitmap, nlockers;
+ u_int32_t *bitmap, nlockers, nalloc;
{
- u_int32_t i, j, *mymap, nentries;
- int ret;
+ u_int32_t i, j, *mymap;
char *msgbuf;
__db_err(dbenv, "Waitsfor array\nWaiter:\tWaiting on:");
@@ -614,11 +754,10 @@ __dd_debug(dbenv, idmap, bitmap, nlockers)
/* Allocate space to print 10 bytes per item waited on. */
#undef MSGBUF_LEN
#define MSGBUF_LEN ((nlockers + 1) * 10 + 64)
- if ((ret = __os_malloc(dbenv, MSGBUF_LEN, NULL, &msgbuf)) != 0)
+ if (__os_malloc(dbenv, MSGBUF_LEN, &msgbuf) != 0)
return;
- nentries = ALIGN(nlockers, 32) / 32;
- for (mymap = bitmap, i = 0; i < nlockers; i++, mymap += nentries) {
+ for (mymap = bitmap, i = 0; i < nlockers; i++, mymap += nalloc) {
if (!idmap[i].valid)
continue;
sprintf(msgbuf, /* Waiter. */
@@ -632,6 +771,116 @@ __dd_debug(dbenv, idmap, bitmap, nlockers)
__db_err(dbenv, msgbuf);
}
- __os_free(msgbuf, MSGBUF_LEN);
+ __os_free(dbenv, msgbuf);
}
#endif
+
+/*
+ * Given a bitmap that contains a deadlock, verify that the bit
+ * specified in the which parameter indicates a transaction that
+ * is actually deadlocked. Return 1 if really deadlocked, 0 otherwise.
+ * deadmap is the array that identified the deadlock.
+ * tmpmap is a copy of the initial bitmaps from the dd_build phase
+ * origmap is a temporary bit map into which we can OR things
+ * nlockers is the number of actual lockers under consideration
+ * nalloc is the number of words allocated for the bitmap
+ * which is the locker in question
+ */
+static int
+__dd_verify(idmap, deadmap, tmpmap, origmap, nlockers, nalloc, which)
+ locker_info *idmap;
+ u_int32_t *deadmap, *tmpmap, *origmap;
+ u_int32_t nlockers, nalloc, which;
+{
+ u_int32_t *tmap;
+ u_int32_t j;
+ int count;
+
+ memset(tmpmap, 0, sizeof(u_int32_t) * nalloc);
+
+ /*
+ * In order for "which" to be actively involved in
+ * the deadlock, removing him from the evaluation
+ * must remove the deadlock. So, we OR together everyone
+ * except which; if all the participants still have their
+ * bits set, then the deadlock persists and which does
+ * not participate. If the deadlock does not persist
+ * then "which" does participate.
+ */
+ count = 0;
+ for (j = 0; j < nlockers; j++) {
+ if (!ISSET_MAP(deadmap, j) || j == which)
+ continue;
+
+ /* Find the map for this bit. */
+ tmap = origmap + (nalloc * j);
+
+ /*
+ * We special case the first waiter who is also a holder, so
+ * we don't automatically call that a deadlock. However, if
+ * it really is a deadlock, we need the bit set now so that
+ * we treat the first waiter like other waiters.
+ */
+ if (idmap[j].self_wait)
+ SET_MAP(tmap, j);
+ OR_MAP(tmpmap, tmap, nalloc);
+ count++;
+ }
+
+ if (count == 1)
+ return (1);
+
+ /*
+ * Now check the resulting map and see whether
+ * all participants still have their bit set.
+ */
+ for (j = 0; j < nlockers; j++) {
+ if (!ISSET_MAP(deadmap, j) || j == which)
+ continue;
+ if (!ISSET_MAP(tmpmap, j))
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * __dd_isolder --
+ *
+ * Figure out the relative age of two lockers. We make all lockers
+ * older than all transactions, because that's how it's worked
+ * historically (because lockers are lower ids).
+ */
+static int
+__dd_isolder(a, b, lock_max, txn_max)
+ u_int32_t a, b;
+ u_int32_t lock_max, txn_max;
+{
+ u_int32_t max;
+
+ /* Check for comparing lock-id and txnid. */
+ if (a <= DB_LOCK_MAXID && b > DB_LOCK_MAXID)
+ return (1);
+ if (b <= DB_LOCK_MAXID && a > DB_LOCK_MAXID)
+ return (0);
+
+ /* In the same space; figure out which one. */
+ max = txn_max;
+ if (a <= DB_LOCK_MAXID)
+ max = lock_max;
+
+ /*
+ * We can't get a 100% correct ordering, because we don't know
+ * where the current interval started and if there were older
+ * lockers outside the interval. We do the best we can.
+ */
+
+ /*
+ * Check for a wrapped case with ids above max.
+ */
+ if (a > max && b < max)
+ return (1);
+ if (b > max && a < max)
+ return (0);
+
+ return (a < b);
+}
diff --git a/bdb/lock/lock_method.c b/bdb/lock/lock_method.c
index 46ed9e5166f..72703e253bc 100644
--- a/bdb/lock/lock_method.c
+++ b/bdb/lock/lock_method.c
@@ -1,33 +1,126 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock_method.c,v 11.5 2000/12/21 19:16:42 bostic Exp $";
+static const char revid[] = "$Id: lock_method.c,v 11.30 2002/03/27 04:32:20 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
+
#include <string.h>
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+
+#ifdef HAVE_RPC
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
+#endif
+
+static int __lock_set_lk_conflicts __P((DB_ENV *, u_int8_t *, int));
+static int __lock_set_lk_detect __P((DB_ENV *, u_int32_t));
+static int __lock_set_lk_max __P((DB_ENV *, u_int32_t));
+static int __lock_set_lk_max_lockers __P((DB_ENV *, u_int32_t));
+static int __lock_set_lk_max_locks __P((DB_ENV *, u_int32_t));
+static int __lock_set_lk_max_objects __P((DB_ENV *, u_int32_t));
+static int __lock_set_env_timeout __P((DB_ENV *, db_timeout_t, u_int32_t));
+
+/*
+ * __lock_dbenv_create --
+ * Lock specific creation of the DB_ENV structure.
+ *
+ * PUBLIC: void __lock_dbenv_create __P((DB_ENV *));
+ */
+void
+__lock_dbenv_create(dbenv)
+ DB_ENV *dbenv;
+{
+ /*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ */
+
+ dbenv->lk_max = DB_LOCK_DEFAULT_N;
+ dbenv->lk_max_lockers = DB_LOCK_DEFAULT_N;
+ dbenv->lk_max_objects = DB_LOCK_DEFAULT_N;
+
+#ifdef HAVE_RPC
+ if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+ dbenv->set_lk_conflicts = __dbcl_set_lk_conflict;
+ dbenv->set_lk_detect = __dbcl_set_lk_detect;
+ dbenv->set_lk_max = __dbcl_set_lk_max;
+ dbenv->set_lk_max_lockers = __dbcl_set_lk_max_lockers;
+ dbenv->set_lk_max_locks = __dbcl_set_lk_max_locks;
+ dbenv->set_lk_max_objects = __dbcl_set_lk_max_objects;
+ dbenv->lock_detect = __dbcl_lock_detect;
+ dbenv->lock_dump_region = NULL;
+ dbenv->lock_get = __dbcl_lock_get;
+ dbenv->lock_id = __dbcl_lock_id;
+ dbenv->lock_id_free = __dbcl_lock_id_free;
+ dbenv->lock_put = __dbcl_lock_put;
+ dbenv->lock_stat = __dbcl_lock_stat;
+ dbenv->lock_vec = __dbcl_lock_vec;
+ } else
+#endif
+ {
+ dbenv->set_lk_conflicts = __lock_set_lk_conflicts;
+ dbenv->set_lk_detect = __lock_set_lk_detect;
+ dbenv->set_lk_max = __lock_set_lk_max;
+ dbenv->set_lk_max_lockers = __lock_set_lk_max_lockers;
+ dbenv->set_lk_max_locks = __lock_set_lk_max_locks;
+ dbenv->set_lk_max_objects = __lock_set_lk_max_objects;
+ dbenv->set_timeout = __lock_set_env_timeout;
+ dbenv->lock_detect = __lock_detect;
+ dbenv->lock_dump_region = __lock_dump_region;
+ dbenv->lock_get = __lock_get;
+ dbenv->lock_id = __lock_id;
+ dbenv->lock_id_free = __lock_id_free;
+#ifdef CONFIG_TEST
+ dbenv->lock_id_set = __lock_id_set;
+#endif
+ dbenv->lock_put = __lock_put;
+ dbenv->lock_stat = __lock_stat;
+ dbenv->lock_vec = __lock_vec;
+ dbenv->lock_downgrade = __lock_downgrade;
+ }
+}
+
+/*
+ * __lock_dbenv_close --
+ * Lock specific destruction of the DB_ENV structure.
+ *
+ * PUBLIC: void __lock_dbenv_close __P((DB_ENV *));
+ */
+void
+__lock_dbenv_close(dbenv)
+ DB_ENV *dbenv;
+{
+ if (dbenv->lk_conflicts != NULL) {
+ __os_free(dbenv, dbenv->lk_conflicts);
+ dbenv->lk_conflicts = NULL;
+ }
+}
/*
* __lock_set_lk_conflicts
* Set the conflicts matrix.
- *
- * PUBLIC: int __lock_set_lk_conflicts __P((DB_ENV *, u_int8_t *, int));
*/
-int
+static int
__lock_set_lk_conflicts(dbenv, lk_conflicts, lk_modes)
DB_ENV *dbenv;
u_int8_t *lk_conflicts;
@@ -38,12 +131,11 @@ __lock_set_lk_conflicts(dbenv, lk_conflicts, lk_modes)
ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_conflicts");
if (dbenv->lk_conflicts != NULL) {
- __os_free(dbenv->lk_conflicts,
- dbenv->lk_modes * dbenv->lk_modes);
+ __os_free(dbenv, dbenv->lk_conflicts);
dbenv->lk_conflicts = NULL;
}
if ((ret = __os_malloc(dbenv,
- lk_modes * lk_modes, NULL, &dbenv->lk_conflicts)) != 0)
+ lk_modes * lk_modes, &dbenv->lk_conflicts)) != 0)
return (ret);
memcpy(dbenv->lk_conflicts, lk_conflicts, lk_modes * lk_modes);
dbenv->lk_modes = lk_modes;
@@ -54,10 +146,8 @@ __lock_set_lk_conflicts(dbenv, lk_conflicts, lk_modes)
/*
* __lock_set_lk_detect
* Set the automatic deadlock detection.
- *
- * PUBLIC: int __lock_set_lk_detect __P((DB_ENV *, u_int32_t));
*/
-int
+static int
__lock_set_lk_detect(dbenv, lk_detect)
DB_ENV *dbenv;
u_int32_t lk_detect;
@@ -66,11 +156,17 @@ __lock_set_lk_detect(dbenv, lk_detect)
switch (lk_detect) {
case DB_LOCK_DEFAULT:
+ case DB_LOCK_EXPIRE:
+ case DB_LOCK_MAXLOCKS:
+ case DB_LOCK_MINLOCKS:
+ case DB_LOCK_MINWRITE:
case DB_LOCK_OLDEST:
case DB_LOCK_RANDOM:
case DB_LOCK_YOUNGEST:
break;
default:
+ __db_err(dbenv,
+ "DB_ENV->set_lk_detect: unknown deadlock detection mode specified");
return (EINVAL);
}
dbenv->lk_detect = lk_detect;
@@ -80,10 +176,8 @@ __lock_set_lk_detect(dbenv, lk_detect)
/*
* __lock_set_lk_max
* Set the lock table size.
- *
- * PUBLIC: int __lock_set_lk_max __P((DB_ENV *, u_int32_t));
*/
-int
+static int
__lock_set_lk_max(dbenv, lk_max)
DB_ENV *dbenv;
u_int32_t lk_max;
@@ -99,10 +193,8 @@ __lock_set_lk_max(dbenv, lk_max)
/*
* __lock_set_lk_max_locks
* Set the lock table size.
- *
- * PUBLIC: int __lock_set_lk_max_locks __P((DB_ENV *, u_int32_t));
*/
-int
+static int
__lock_set_lk_max_locks(dbenv, lk_max)
DB_ENV *dbenv;
u_int32_t lk_max;
@@ -116,10 +208,8 @@ __lock_set_lk_max_locks(dbenv, lk_max)
/*
* __lock_set_lk_max_lockers
* Set the lock table size.
- *
- * PUBLIC: int __lock_set_lk_max_lockers __P((DB_ENV *, u_int32_t));
*/
-int
+static int
__lock_set_lk_max_lockers(dbenv, lk_max)
DB_ENV *dbenv;
u_int32_t lk_max;
@@ -133,10 +223,8 @@ __lock_set_lk_max_lockers(dbenv, lk_max)
/*
* __lock_set_lk_max_objects
* Set the lock table size.
- *
- * PUBLIC: int __lock_set_lk_max_objects __P((DB_ENV *, u_int32_t));
*/
-int
+static int
__lock_set_lk_max_objects(dbenv, lk_max)
DB_ENV *dbenv;
u_int32_t lk_max;
@@ -146,3 +234,42 @@ __lock_set_lk_max_objects(dbenv, lk_max)
dbenv->lk_max_objects = lk_max;
return (0);
}
+
+/*
+ * __lock_set_env_timeout
+ * Set the lock environment timeout.
+ */
+static int
+__lock_set_env_timeout(dbenv, timeout, flags)
+ DB_ENV *dbenv;
+ db_timeout_t timeout;
+ u_int32_t flags;
+{
+ DB_LOCKREGION *region;
+
+ region = NULL;
+ if (F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
+ if (!LOCKING_ON(dbenv))
+ return (__db_env_config(
+ dbenv, "set_timeout", DB_INIT_LOCK));
+ region = ((DB_LOCKTAB *)dbenv->lk_handle)->reginfo.primary;
+ }
+
+ switch (flags) {
+ case DB_SET_LOCK_TIMEOUT:
+ dbenv->lk_timeout = timeout;
+ if (region != NULL)
+ region->lk_timeout = timeout;
+ break;
+ case DB_SET_TXN_TIMEOUT:
+ dbenv->tx_timeout = timeout;
+ if (region != NULL)
+ region->tx_timeout = timeout;
+ break;
+ default:
+ return (__db_ferr(dbenv, "DB_ENV->set_timeout", 0));
+ /* NOTREACHED */
+ }
+
+ return (0);
+}
diff --git a/bdb/lock/lock_region.c b/bdb/lock/lock_region.c
index 5ca91a9951d..6df6937e873 100644
--- a/bdb/lock/lock_region.c
+++ b/bdb/lock/lock_region.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock_region.c,v 11.41 2000/12/20 21:53:04 ubell Exp $";
+static const char revid[] = "$Id: lock_region.c,v 11.69 2002/08/06 05:05:22 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,95 +17,50 @@ static const char revid[] = "$Id: lock_region.c,v 11.41 2000/12/20 21:53:04 ubel
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
static int __lock_init __P((DB_ENV *, DB_LOCKTAB *));
static size_t
__lock_region_size __P((DB_ENV *));
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
static size_t __lock_region_maint __P((DB_ENV *));
#endif
/*
- * This conflict array is used for concurrent db access (CDB). It
- * uses the same locks as the db_rw_conflict array, but adds an IW
- * mode to be used for write cursors.
+ * The conflict arrays are set up such that the row is the lock you are
+ * holding and the column is the lock that is desired.
*/
-#define DB_LOCK_CDB_N 5
-static u_int8_t const db_cdb_conflicts[] = {
- /* N R W WT IW*/
- /* N */ 0, 0, 0, 0, 0,
- /* R */ 0, 0, 1, 0, 0,
- /* W */ 0, 1, 1, 1, 1,
- /* WT */ 0, 0, 0, 0, 0,
- /* IW */ 0, 0, 1, 0, 1,
+#define DB_LOCK_RIW_N 9
+static const u_int8_t db_riw_conflicts[] = {
+/* N R W WT IW IR RIW DR WW */
+/* N */ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* R */ 0, 0, 1, 0, 1, 0, 1, 0, 1,
+/* W */ 0, 1, 1, 1, 1, 1, 1, 1, 1,
+/* WT */ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* IW */ 0, 1, 1, 0, 0, 0, 0, 1, 1,
+/* IR */ 0, 0, 1, 0, 0, 0, 0, 0, 1,
+/* RIW */ 0, 1, 1, 0, 0, 0, 0, 1, 1,
+/* DR */ 0, 0, 1, 0, 1, 0, 1, 0, 0,
+/* WW */ 0, 1, 1, 0, 1, 1, 1, 0, 1
};
/*
- * __lock_dbenv_create --
- * Lock specific creation of the DB_ENV structure.
- *
- * PUBLIC: void __lock_dbenv_create __P((DB_ENV *));
+ * This conflict array is used for concurrent db access (CDB). It uses
+ * the same locks as the db_riw_conflicts array, but adds an IW mode to
+ * be used for write cursors.
*/
-void
-__lock_dbenv_create(dbenv)
- DB_ENV *dbenv;
-{
- dbenv->lk_max = DB_LOCK_DEFAULT_N;
- dbenv->lk_max_lockers = DB_LOCK_DEFAULT_N;
- dbenv->lk_max_objects = DB_LOCK_DEFAULT_N;
-
- dbenv->set_lk_conflicts = __lock_set_lk_conflicts;
- dbenv->set_lk_detect = __lock_set_lk_detect;
- dbenv->set_lk_max = __lock_set_lk_max;
- dbenv->set_lk_max_locks = __lock_set_lk_max_locks;
- dbenv->set_lk_max_lockers = __lock_set_lk_max_lockers;
- dbenv->set_lk_max_objects = __lock_set_lk_max_objects;
-
-#ifdef HAVE_RPC
- /*
- * If we have a client, overwrite what we just set up to point
- * to the client functions.
- */
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
- dbenv->set_lk_conflicts = __dbcl_set_lk_conflict;
- dbenv->set_lk_detect = __dbcl_set_lk_detect;
- dbenv->set_lk_max = __dbcl_set_lk_max;
- dbenv->set_lk_max_locks = __dbcl_set_lk_max_locks;
- dbenv->set_lk_max_lockers = __dbcl_set_lk_max_lockers;
- dbenv->set_lk_max_objects = __dbcl_set_lk_max_objects;
- }
-#endif
-}
-
-/*
- * __lock_dbenv_close --
- * Lock specific destruction of the DB_ENV structure.
- *
- * PUBLIC: void __lock_dbenv_close __P((DB_ENV *));
- */
-void
-__lock_dbenv_close(dbenv)
- DB_ENV *dbenv;
-{
- if (!F_ISSET(dbenv, DB_ENV_USER_ALLOC) && dbenv->lk_conflicts != NULL) {
- __os_free(dbenv->lk_conflicts,
- dbenv->lk_modes * dbenv->lk_modes);
- dbenv->lk_conflicts = NULL;
- }
-}
+#define DB_LOCK_CDB_N 5
+static const u_int8_t db_cdb_conflicts[] = {
+ /* N R W WT IW */
+ /* N */ 0, 0, 0, 0, 0,
+ /* R */ 0, 0, 1, 0, 0,
+ /* W */ 0, 1, 1, 1, 1,
+ /* WT */ 0, 0, 0, 0, 0,
+ /* IW */ 0, 0, 1, 0, 1
+};
/*
* __lock_open --
@@ -167,6 +122,15 @@ __lock_open(dbenv)
region->detect = dbenv->lk_detect;
}
+ /*
+ * A process joining the region may have reset the lock and transaction
+ * timeouts.
+ */
+ if (dbenv->lk_timeout != 0)
+ region->lk_timeout = dbenv->lk_timeout;
+ if (dbenv->tx_timeout != 0)
+ region->tx_timeout = dbenv->tx_timeout;
+
/* Set remaining pointers into region. */
lt->conflicts = (u_int8_t *)R_ADDR(&lt->reginfo, region->conf_off);
lt->obj_tab = (DB_HASHTAB *)R_ADDR(&lt->reginfo, region->obj_off);
@@ -183,7 +147,7 @@ err: if (lt->reginfo.addr != NULL) {
R_UNLOCK(dbenv, &lt->reginfo);
(void)__db_r_detach(dbenv, &lt->reginfo, 0);
}
- __os_free(lt, sizeof(*lt));
+ __os_free(dbenv, lt);
return (ret);
}
@@ -201,7 +165,7 @@ __lock_init(dbenv, lt)
DB_LOCKER *lidp;
DB_LOCKOBJ *op;
DB_LOCKREGION *region;
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
size_t maint_size;
#endif
u_int32_t i, lk_modes;
@@ -229,25 +193,19 @@ __lock_init(dbenv, lt)
lk_conflicts = dbenv->lk_conflicts;
}
- region->id = 0;
region->need_dd = 0;
region->detect = DB_LOCK_NORUN;
- region->maxlocks = dbenv->lk_max;
- region->maxlockers = dbenv->lk_max_lockers;
- region->maxobjects = dbenv->lk_max_objects;
+ region->lk_timeout = dbenv->lk_timeout;
+ region->tx_timeout = dbenv->tx_timeout;
region->locker_t_size = __db_tablesize(dbenv->lk_max_lockers);
region->object_t_size = __db_tablesize(dbenv->lk_max_objects);
- region->nmodes = lk_modes;
- region->nlocks = 0;
- region->maxnlocks = 0;
- region->nlockers = 0;
- region->maxnlockers = 0;
- region->nobjects = 0;
- region->maxnobjects = 0;
- region->nconflicts = 0;
- region->nrequests = 0;
- region->nreleases = 0;
- region->ndeadlocks = 0;
+ memset(&region->stat, 0, sizeof(region->stat));
+ region->stat.st_id = 0;
+ region->stat.st_cur_maxid = DB_LOCK_MAXID;
+ region->stat.st_maxlocks = dbenv->lk_max;
+ region->stat.st_maxlockers = dbenv->lk_max_lockers;
+ region->stat.st_maxobjects = dbenv->lk_max_objects;
+ region->stat.st_nmodes = lk_modes;
/* Allocate room for the conflict matrix and initialize it. */
if ((ret =
@@ -270,7 +228,7 @@ __lock_init(dbenv, lt)
__db_hashinit(addr, region->locker_t_size);
region->locker_off = R_OFFSET(&lt->reginfo, addr);
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
maint_size = __lock_region_maint(dbenv);
/* Allocate room for the locker maintenance info and initialize it. */
if ((ret = __db_shalloc(lt->reginfo.addr,
@@ -286,25 +244,23 @@ __lock_init(dbenv, lt)
* the mutex.
*/
SH_TAILQ_INIT(&region->free_locks);
- for (i = 0; i < region->maxlocks; ++i) {
+ for (i = 0; i < region->stat.st_maxlocks; ++i) {
if ((ret = __db_shalloc(lt->reginfo.addr,
sizeof(struct __db_lock), MUTEX_ALIGN, &lp)) != 0)
goto mem_err;
lp->status = DB_LSTAT_FREE;
- lp->gen=0;
- if ((ret = __db_shmutex_init(dbenv, &lp->mutex,
- R_OFFSET(&lt->reginfo, &lp->mutex) + DB_FCNTL_OFF_LOCK,
- MUTEX_SELF_BLOCK, &lt->reginfo,
- (REGMAINT *)R_ADDR(&lt->reginfo, region->maint_off))) != 0)
+ lp->gen = 0;
+ if ((ret = __db_mutex_setup(dbenv, &lt->reginfo, &lp->mutex,
+ MUTEX_NO_RLOCK | MUTEX_SELF_BLOCK)) != 0)
return (ret);
- MUTEX_LOCK(dbenv, &lp->mutex, lt->dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &lp->mutex);
SH_TAILQ_INSERT_HEAD(&region->free_locks, lp, links, __db_lock);
}
/* Initialize objects onto a free list. */
SH_TAILQ_INIT(&region->dd_objs);
SH_TAILQ_INIT(&region->free_objs);
- for (i = 0; i < region->maxobjects; ++i) {
+ for (i = 0; i < region->stat.st_maxobjects; ++i) {
if ((ret = __db_shalloc(lt->reginfo.addr,
sizeof(DB_LOCKOBJ), 0, &op)) != 0)
goto mem_err;
@@ -313,13 +269,15 @@ __lock_init(dbenv, lt)
}
/* Initialize lockers onto a free list. */
+ SH_TAILQ_INIT(&region->lockers);
SH_TAILQ_INIT(&region->free_lockers);
- for (i = 0; i < region->maxlockers; ++i) {
+ for (i = 0; i < region->stat.st_maxlockers; ++i) {
if ((ret = __db_shalloc(lt->reginfo.addr,
sizeof(DB_LOCKER), 0, &lidp)) != 0) {
-mem_err: __db_err(dbenv, "Unable to allocate memory for the lock table");
- return (ret);
- }
+mem_err: __db_err(dbenv,
+ "Unable to allocate memory for the lock table");
+ return (ret);
+ }
SH_TAILQ_INSERT_HEAD(
&region->free_lockers, lidp, links, __db_locker);
}
@@ -328,13 +286,14 @@ mem_err: __db_err(dbenv, "Unable to allocate memory for the lock table");
}
/*
- * __lock_close --
- * Internal version of lock_close: only called from db_appinit.
+ * __lock_dbenv_refresh --
+ * Clean up after the lock system on a close or failed open. Called
+ * only from __dbenv_refresh. (Formerly called __lock_close.)
*
- * PUBLIC: int __lock_close __P((DB_ENV *));
+ * PUBLIC: int __lock_dbenv_refresh __P((DB_ENV *));
*/
int
-__lock_close(dbenv)
+__lock_dbenv_refresh(dbenv)
DB_ENV *dbenv;
{
DB_LOCKTAB *lt;
@@ -345,7 +304,7 @@ __lock_close(dbenv)
/* Detach from the region. */
ret = __db_r_detach(dbenv, &lt->reginfo, 0);
- __os_free(lt, sizeof(*lt));
+ __os_free(dbenv, lt);
dbenv->lk_handle = NULL;
return (ret);
@@ -369,17 +328,19 @@ __lock_region_size(dbenv)
retval += __db_shalloc_size(sizeof(DB_LOCKREGION), 1);
retval += __db_shalloc_size(dbenv->lk_modes * dbenv->lk_modes, 1);
retval += __db_shalloc_size(
- __db_tablesize(dbenv->lk_max_lockers) * (sizeof(DB_HASHTAB)), 1);
+ __db_tablesize(dbenv->lk_max_lockers) * (sizeof(DB_HASHTAB)), 1);
retval += __db_shalloc_size(
- __db_tablesize(dbenv->lk_max_objects) * (sizeof(DB_HASHTAB)), 1);
-#ifdef MUTEX_SYSTEM_RESOURCES
+ __db_tablesize(dbenv->lk_max_objects) * (sizeof(DB_HASHTAB)), 1);
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
retval +=
__db_shalloc_size(sizeof(REGMAINT) + __lock_region_maint(dbenv), 1);
#endif
retval += __db_shalloc_size(
- sizeof(struct __db_lock), MUTEX_ALIGN) * dbenv->lk_max;
- retval += __db_shalloc_size(sizeof(DB_LOCKOBJ), 1) * dbenv->lk_max_objects;
- retval += __db_shalloc_size(sizeof(DB_LOCKER), 1) * dbenv->lk_max_lockers;
+ sizeof(struct __db_lock), MUTEX_ALIGN) * dbenv->lk_max;
+ retval += __db_shalloc_size(
+ sizeof(DB_LOCKOBJ), 1) * dbenv->lk_max_objects;
+ retval += __db_shalloc_size(
+ sizeof(DB_LOCKER), 1) * dbenv->lk_max_lockers;
/*
* Include 16 bytes of string space per lock. DB doesn't use it
@@ -393,7 +354,7 @@ __lock_region_size(dbenv)
return (retval);
}
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
/*
* __lock_region_maint --
* Return the amount of space needed for region maintenance info.
@@ -404,7 +365,7 @@ __lock_region_maint(dbenv)
{
size_t s;
- s = sizeof(MUTEX *) * dbenv->lk_max;
+ s = sizeof(DB_MUTEX *) * dbenv->lk_max;
return (s);
}
#endif
@@ -420,12 +381,37 @@ __lock_region_destroy(dbenv, infop)
DB_ENV *dbenv;
REGINFO *infop;
{
- DB_LOCKREGION *region;
+ __db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
+ ((DB_LOCKREGION *)R_ADDR(infop, infop->rp->primary))->maint_off));
COMPQUIET(dbenv, NULL);
- region = R_ADDR(infop, infop->rp->primary);
+ COMPQUIET(infop, NULL);
+}
+
+#ifdef CONFIG_TEST
+/*
+ * __lock_id_set --
+ * Set the current locker ID and current maximum unused ID (for
+ * testing purposes only).
+ *
+ * PUBLIC: int __lock_id_set __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__lock_id_set(dbenv, cur_id, max_id)
+ DB_ENV *dbenv;
+ u_int32_t cur_id, max_id;
+{
+ DB_LOCKTAB *lt;
+ DB_LOCKREGION *region;
- __db_shlocks_destroy(infop,
- (REGMAINT *)R_ADDR(infop, region->maint_off));
- return;
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "lock_id_set", DB_INIT_LOCK);
+
+ lt = dbenv->lk_handle;
+ region = lt->reginfo.primary;
+ region->stat.st_id = cur_id;
+ region->stat.st_cur_maxid = max_id;
+
+ return (0);
}
+#endif
diff --git a/bdb/lock/lock_stat.c b/bdb/lock/lock_stat.c
index ed5b60d0d7a..0bef3e18021 100644
--- a/bdb/lock/lock_stat.c
+++ b/bdb/lock/lock_stat.c
@@ -1,94 +1,105 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock_stat.c,v 11.4 2000/12/08 20:15:31 ubell Exp $";
+static const char revid[] = "$Id: lock_stat.c,v 11.32 2002/08/14 20:08:51 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-
-#include <ctype.h>
+#include <string.h>
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
+#include <ctype.h>
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/db_am.h"
static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKER *, FILE *));
static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *));
-static const char *
- __lock_dump_status __P((db_status_t));
+static void __lock_printheader __P((void));
/*
- * lock_stat --
+ * __lock_stat --
* Return LOCK statistics.
+ *
+ * PUBLIC: int __lock_stat __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
*/
int
-lock_stat(dbenv, statp, db_malloc)
+__lock_stat(dbenv, statp, flags)
DB_ENV *dbenv;
DB_LOCK_STAT **statp;
- void *(*db_malloc) __P((size_t));
+ u_int32_t flags;
{
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
- DB_LOCK_STAT *stats;
+ DB_LOCK_STAT *stats, tmp;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_stat(dbenv, statp, db_malloc));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_stat", DB_INIT_LOCK);
*statp = NULL;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->lock_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
lt = dbenv->lk_handle;
- if ((ret = __os_malloc(dbenv, sizeof(*stats), db_malloc, &stats)) != 0)
+ if ((ret = __os_umalloc(dbenv, sizeof(*stats), &stats)) != 0)
return (ret);
/* Copy out the global statistics. */
R_LOCK(dbenv, &lt->reginfo);
region = lt->reginfo.primary;
- stats->st_lastid = region->id;
- stats->st_maxlocks = region->maxlocks;
- stats->st_maxlockers = region->maxlockers;
- stats->st_maxobjects = region->maxobjects;
- stats->st_nmodes = region->nmodes;
- stats->st_nlockers = region->nlockers;
- stats->st_maxnlockers = region->maxnlockers;
- stats->st_nobjects = region->nobjects;
- stats->st_maxnobjects = region->maxnobjects;
- stats->st_nlocks = region->nlocks;
- stats->st_maxnlocks = region->maxnlocks;
- stats->st_nconflicts = region->nconflicts;
- stats->st_nrequests = region->nrequests;
- stats->st_nreleases = region->nreleases;
- stats->st_nnowaits = region->nnowaits;
- stats->st_ndeadlocks = region->ndeadlocks;
+ memcpy(stats, &region->stat, sizeof(*stats));
+ stats->st_locktimeout = region->lk_timeout;
+ stats->st_txntimeout = region->tx_timeout;
stats->st_region_wait = lt->reginfo.rp->mutex.mutex_set_wait;
stats->st_region_nowait = lt->reginfo.rp->mutex.mutex_set_nowait;
stats->st_regsize = lt->reginfo.rp->size;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ tmp = region->stat;
+ memset(&region->stat, 0, sizeof(region->stat));
+ lt->reginfo.rp->mutex.mutex_set_wait = 0;
+ lt->reginfo.rp->mutex.mutex_set_nowait = 0;
+
+ region->stat.st_id = tmp.st_id;
+ region->stat.st_cur_maxid = tmp.st_cur_maxid;
+ region->stat.st_maxlocks = tmp.st_maxlocks;
+ region->stat.st_maxlockers = tmp.st_maxlockers;
+ region->stat.st_maxobjects = tmp.st_maxobjects;
+ region->stat.st_nlocks =
+ region->stat.st_maxnlocks = tmp.st_nlocks;
+ region->stat.st_nlockers =
+ region->stat.st_maxnlockers = tmp.st_nlockers;
+ region->stat.st_nobjects =
+ region->stat.st_maxnobjects = tmp.st_nobjects;
+ region->stat.st_nmodes = tmp.st_nmodes;
+ }
R_UNLOCK(dbenv, &lt->reginfo);
@@ -97,30 +108,34 @@ lock_stat(dbenv, statp, db_malloc)
}
#define LOCK_DUMP_CONF 0x001 /* Conflict matrix. */
-#define LOCK_DUMP_FREE 0x002 /* Display lock free list. */
-#define LOCK_DUMP_LOCKERS 0x004 /* Display lockers. */
-#define LOCK_DUMP_MEM 0x008 /* Display region memory. */
-#define LOCK_DUMP_OBJECTS 0x010 /* Display objects. */
-#define LOCK_DUMP_ALL 0x01f /* Display all. */
+#define LOCK_DUMP_LOCKERS 0x002 /* Display lockers. */
+#define LOCK_DUMP_MEM 0x004 /* Display region memory. */
+#define LOCK_DUMP_OBJECTS 0x008 /* Display objects. */
+#define LOCK_DUMP_PARAMS 0x010 /* Display params. */
+#define LOCK_DUMP_ALL /* All */ \
+ (LOCK_DUMP_CONF | LOCK_DUMP_LOCKERS | LOCK_DUMP_MEM | \
+ LOCK_DUMP_OBJECTS | LOCK_DUMP_PARAMS)
/*
* __lock_dump_region --
*
- * PUBLIC: void __lock_dump_region __P((DB_ENV *, char *, FILE *));
+ * PUBLIC: int __lock_dump_region __P((DB_ENV *, char *, FILE *));
*/
-void
+int
__lock_dump_region(dbenv, area, fp)
DB_ENV *dbenv;
char *area;
FILE *fp;
{
- struct __db_lock *lp;
DB_LOCKER *lip;
DB_LOCKOBJ *op;
DB_LOCKREGION *lrp;
DB_LOCKTAB *lt;
u_int32_t flags, i, j;
- int label;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "lock_dump_region", DB_INIT_LOCK);
/* Make it easy to call from the debugger. */
if (fp == NULL)
@@ -134,9 +149,6 @@ __lock_dump_region(dbenv, area, fp)
case 'c':
LF_SET(LOCK_DUMP_CONF);
break;
- case 'f':
- LF_SET(LOCK_DUMP_FREE);
- break;
case 'l':
LF_SET(LOCK_DUMP_LOCKERS);
break;
@@ -146,91 +158,67 @@ __lock_dump_region(dbenv, area, fp)
case 'o':
LF_SET(LOCK_DUMP_OBJECTS);
break;
+ case 'p':
+ LF_SET(LOCK_DUMP_PARAMS);
+ break;
}
lt = dbenv->lk_handle;
lrp = lt->reginfo.primary;
LOCKREGION(dbenv, lt);
- fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
- fprintf(fp, "%s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu\n",
- "locker table size", (u_long)lrp->locker_t_size,
- "object table size", (u_long)lrp->object_t_size,
- "obj_off", (u_long)lrp->obj_off,
- "osynch_off", (u_long)lrp->osynch_off,
- "locker_off", (u_long)lrp->locker_off,
- "lsynch_off", (u_long)lrp->lsynch_off,
- "need_dd", (u_long)lrp->need_dd);
+ if (LF_ISSET(LOCK_DUMP_PARAMS)) {
+ fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
+ fprintf(fp,
+ "%s: %lu, %s: %lu, %s: %lu,\n%s: %lu, %s: %lu, %s: %lu, %s: %lu\n",
+ "locker table size", (u_long)lrp->locker_t_size,
+ "object table size", (u_long)lrp->object_t_size,
+ "obj_off", (u_long)lrp->obj_off,
+ "osynch_off", (u_long)lrp->osynch_off,
+ "locker_off", (u_long)lrp->locker_off,
+ "lsynch_off", (u_long)lrp->lsynch_off,
+ "need_dd", (u_long)lrp->need_dd);
+ }
if (LF_ISSET(LOCK_DUMP_CONF)) {
fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE);
- for (i = 0; i < lrp->nmodes; i++) {
- for (j = 0; j < lrp->nmodes; j++)
- fprintf(fp, "%lu\t",
- (u_long)lt->conflicts[i * lrp->nmodes + j]);
+ for (i = 0; i < lrp->stat.st_nmodes; i++) {
+ for (j = 0; j < lrp->stat.st_nmodes; j++)
+ fprintf(fp, "%lu\t", (u_long)
+ lt->conflicts[i * lrp->stat.st_nmodes + j]);
fprintf(fp, "\n");
}
}
if (LF_ISSET(LOCK_DUMP_LOCKERS)) {
- fprintf(fp, "%s\nLocker hash buckets\n", DB_LINE);
- for (i = 0; i < lrp->locker_t_size; i++) {
- label = 1;
+ fprintf(fp, "%s\nLocks grouped by lockers\n", DB_LINE);
+ __lock_printheader();
+ for (i = 0; i < lrp->locker_t_size; i++)
for (lip =
SH_TAILQ_FIRST(&lt->locker_tab[i], __db_locker);
lip != NULL;
lip = SH_TAILQ_NEXT(lip, links, __db_locker)) {
- if (label) {
- fprintf(fp, "Bucket %lu:\n", (u_long)i);
- label = 0;
- }
__lock_dump_locker(lt, lip, fp);
}
- }
}
if (LF_ISSET(LOCK_DUMP_OBJECTS)) {
- fprintf(fp, "%s\nObject hash buckets\n", DB_LINE);
+ fprintf(fp, "%s\nLocks grouped by object\n", DB_LINE);
+ __lock_printheader();
for (i = 0; i < lrp->object_t_size; i++) {
- label = 1;
for (op = SH_TAILQ_FIRST(&lt->obj_tab[i], __db_lockobj);
op != NULL;
- op = SH_TAILQ_NEXT(op, links, __db_lockobj)) {
- if (label) {
- fprintf(fp, "Bucket %lu:\n", (u_long)i);
- label = 0;
- }
+ op = SH_TAILQ_NEXT(op, links, __db_lockobj))
__lock_dump_object(lt, op, fp);
- }
}
}
- if (LF_ISSET(LOCK_DUMP_FREE)) {
- fprintf(fp, "%s\nLock free list\n", DB_LINE);
- for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
- lp != NULL;
- lp = SH_TAILQ_NEXT(lp, links, __db_lock))
- fprintf(fp, "0x%lx: %lu\t%lu\t%s\t0x%lx\n", (u_long)lp,
- (u_long)lp->holder, (u_long)lp->mode,
- __lock_dump_status(lp->status), (u_long)lp->obj);
-
- fprintf(fp, "%s\nObject free list\n", DB_LINE);
- for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
- op != NULL;
- op = SH_TAILQ_NEXT(op, links, __db_lockobj))
- fprintf(fp, "0x%lx\n", (u_long)op);
-
- fprintf(fp, "%s\nLocker free list\n", DB_LINE);
- for (lip = SH_TAILQ_FIRST(&lrp->free_lockers, __db_locker);
- lip != NULL;
- lip = SH_TAILQ_NEXT(lip, links, __db_locker))
- fprintf(fp, "0x%lx\n", (u_long)lip);
- }
-
if (LF_ISSET(LOCK_DUMP_MEM))
__db_shalloc_dump(lt->reginfo.addr, fp);
UNLOCKREGION(dbenv, lt);
+
+ return (0);
}
static void
@@ -240,16 +228,35 @@ __lock_dump_locker(lt, lip, fp)
FILE *fp;
{
struct __db_lock *lp;
+ time_t s;
+ char buf[64];
- fprintf(fp, "L %lx [%ld]", (u_long)lip->id, (long)lip->dd_id);
+ fprintf(fp, "%8lx dd=%2ld locks held %-4d write locks %-4d",
+ (u_long)lip->id, (long)lip->dd_id, lip->nlocks, lip->nwrites);
fprintf(fp, " %s ", F_ISSET(lip, DB_LOCKER_DELETED) ? "(D)" : " ");
+ if (LOCK_TIME_ISVALID(&lip->tx_expire)) {
+ s = lip->tx_expire.tv_sec;
+ strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
+ fprintf(fp,
+ " expires %s.%lu", buf, (u_long)lip->tx_expire.tv_usec);
+ }
+ if (F_ISSET(lip, DB_LOCKER_TIMEOUT))
+ fprintf(fp, " lk timeout %u", lip->lk_timeout);
+ if (LOCK_TIME_ISVALID(&lip->lk_expire)) {
+ s = lip->lk_expire.tv_sec;
+ strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
+ fprintf(fp,
+ " lk expires %s.%lu", buf, (u_long)lip->lk_expire.tv_usec);
+ }
+ fprintf(fp, "\n");
- if ((lp = SH_LIST_FIRST(&lip->heldby, __db_lock)) == NULL)
- fprintf(fp, "\n");
- else
+ lp = SH_LIST_FIRST(&lip->heldby, __db_lock);
+ if (lp != NULL) {
for (; lp != NULL;
lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
__lock_printlock(lt, lp, 1);
+ fprintf(fp, "\n");
+ }
}
static void
@@ -259,50 +266,133 @@ __lock_dump_object(lt, op, fp)
FILE *fp;
{
struct __db_lock *lp;
- u_int32_t j;
- u_int8_t *ptr;
- u_int ch;
-
- ptr = SH_DBT_PTR(&op->lockobj);
- for (j = 0; j < op->lockobj.size; ptr++, j++) {
- ch = *ptr;
- fprintf(fp, isprint(ch) ? "%c" : "\\%o", ch);
- }
- fprintf(fp, "\n");
- fprintf(fp, "H:");
for (lp =
SH_TAILQ_FIRST(&op->holders, __db_lock);
lp != NULL;
lp = SH_TAILQ_NEXT(lp, links, __db_lock))
__lock_printlock(lt, lp, 1);
- lp = SH_TAILQ_FIRST(&op->waiters, __db_lock);
- if (lp != NULL) {
- fprintf(fp, "\nW:");
- for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock))
- __lock_printlock(lt, lp, 1);
- }
+ for (lp =
+ SH_TAILQ_FIRST(&op->waiters, __db_lock);
+ lp != NULL;
+ lp = SH_TAILQ_NEXT(lp, links, __db_lock))
+ __lock_printlock(lt, lp, 1);
+
+ fprintf(fp, "\n");
}
-static const char *
-__lock_dump_status(status)
- db_status_t status;
+/*
+ * __lock_printheader --
+ */
+static void
+__lock_printheader()
{
- switch (status) {
+ printf("%-8s %-6s %-6s %-10s %s\n",
+ "Locker", "Mode",
+ "Count", "Status", "----------- Object ----------");
+}
+
+/*
+ * __lock_printlock --
+ *
+ * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
+ */
+void
+__lock_printlock(lt, lp, ispgno)
+ DB_LOCKTAB *lt;
+ struct __db_lock *lp;
+ int ispgno;
+{
+ DB_LOCKOBJ *lockobj;
+ db_pgno_t pgno;
+ u_int32_t *fidp, type;
+ u_int8_t *ptr;
+ char *namep;
+ const char *mode, *status;
+
+ switch (lp->mode) {
+ case DB_LOCK_DIRTY:
+ mode = "DIRTY_READ";
+ break;
+ case DB_LOCK_IREAD:
+ mode = "IREAD";
+ break;
+ case DB_LOCK_IWR:
+ mode = "IWR";
+ break;
+ case DB_LOCK_IWRITE:
+ mode = "IWRITE";
+ break;
+ case DB_LOCK_NG:
+ mode = "NG";
+ break;
+ case DB_LOCK_READ:
+ mode = "READ";
+ break;
+ case DB_LOCK_WRITE:
+ mode = "WRITE";
+ break;
+ case DB_LOCK_WWRITE:
+ mode = "WAS_WRITE";
+ break;
+ case DB_LOCK_WAIT:
+ mode = "WAIT";
+ break;
+ default:
+ mode = "UNKNOWN";
+ break;
+ }
+ switch (lp->status) {
case DB_LSTAT_ABORTED:
- return ("aborted");
+ status = "ABORT";
+ break;
case DB_LSTAT_ERR:
- return ("err");
+ status = "ERROR";
+ break;
case DB_LSTAT_FREE:
- return ("free");
+ status = "FREE";
+ break;
case DB_LSTAT_HELD:
- return ("held");
- case DB_LSTAT_NOGRANT:
- return ("nogrant");
- case DB_LSTAT_PENDING:
- return ("pending");
+ status = "HELD";
+ break;
case DB_LSTAT_WAITING:
- return ("waiting");
+ status = "WAIT";
+ break;
+ case DB_LSTAT_PENDING:
+ status = "PENDING";
+ break;
+ case DB_LSTAT_EXPIRED:
+ status = "EXPIRED";
+ break;
+ default:
+ status = "UNKNOWN";
+ break;
+ }
+ printf("%8lx %-6s %6lu %-10s ",
+ (u_long)lp->holder, mode, (u_long)lp->refcount, status);
+
+ lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
+ ptr = SH_DBT_PTR(&lockobj->lockobj);
+ if (ispgno && lockobj->lockobj.size == sizeof(struct __db_ilock)) {
+ /* Assume this is a DBT lock. */
+ memcpy(&pgno, ptr, sizeof(db_pgno_t));
+ fidp = (u_int32_t *)(ptr + sizeof(db_pgno_t));
+ type = *(u_int32_t *)(ptr + sizeof(db_pgno_t) + DB_FILE_ID_LEN);
+ if (__dbreg_get_name(lt->dbenv, (u_int8_t *)fidp, &namep) != 0)
+ namep = NULL;
+ if (namep == NULL)
+ printf("(%lx %lx %lx %lx %lx)",
+ (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
+ (u_long)fidp[3], (u_long)fidp[4]);
+ else
+ printf("%-20s", namep);
+ printf("%-7s %lu\n",
+ type == DB_PAGE_LOCK ? "page" :
+ type == DB_RECORD_LOCK ? "record" : "handle",
+ (u_long)pgno);
+ } else {
+ printf("0x%lx ", (u_long)R_OFFSET(&lt->reginfo, lockobj));
+ __db_pr(ptr, lockobj->lockobj.size, stdout);
+ printf("\n");
}
- return ("unknown status");
}
diff --git a/bdb/lock/lock_util.c b/bdb/lock/lock_util.c
index fd5c6ad90cb..260f021b1ee 100644
--- a/bdb/lock/lock_util.c
+++ b/bdb/lock/lock_util.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock_util.c,v 11.5 2000/07/04 18:28:24 bostic Exp $";
+static const char revid[] = "$Id: lock_util.c,v 11.8 2002/03/27 04:32:20 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,10 +18,10 @@ static const char revid[] = "$Id: lock_util.c,v 11.5 2000/07/04 18:28:24 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "hash.h"
-#include "lock.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
/*
* __lock_cmp --
diff --git a/bdb/log/log.c b/bdb/log/log.c
index 8ddb7bcaf7d..f57caeccb95 100644
--- a/bdb/log/log.c
+++ b/bdb/log/log.c
@@ -1,40 +1,34 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: log.c,v 11.42 2001/01/15 16:42:37 bostic Exp $";
+static const char revid[] = "$Id: log.c,v 11.111 2002/08/16 00:27:44 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "log.h"
-#include "db_dispatch.h"
-#include "txn.h"
-#include "txn_auto.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
static int __log_init __P((DB_ENV *, DB_LOG *));
static int __log_recover __P((DB_LOG *));
+static size_t __log_region_size __P((DB_ENV *));
+static int __log_zero __P((DB_ENV *, DB_LSN *, DB_LSN *));
/*
* __log_open --
@@ -49,16 +43,10 @@ __log_open(dbenv)
DB_LOG *dblp;
LOG *lp;
int ret;
- u_int8_t *readbufp;
-
- readbufp = NULL;
/* Create/initialize the DB_LOG structure. */
if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOG), &dblp)) != 0)
return (ret);
- if ((ret = __os_calloc(dbenv, 1, dbenv->lg_bsize, &readbufp)) != 0)
- goto err;
- ZERO_LSN(dblp->c_lsn);
dblp->dbenv = dbenv;
/* Join/create the log region. */
@@ -69,40 +57,66 @@ __log_open(dbenv)
if (F_ISSET(dbenv, DB_ENV_CREATE))
F_SET(&dblp->reginfo, REGION_CREATE_OK);
if ((ret = __db_r_attach(
- dbenv, &dblp->reginfo, LG_BASE_REGION_SIZE + dbenv->lg_bsize)) != 0)
+ dbenv, &dblp->reginfo, __log_region_size(dbenv))) != 0)
goto err;
- dblp->readbufp = readbufp;
-
/* If we created the region, initialize it. */
- if (F_ISSET(&dblp->reginfo, REGION_CREATE) &&
- (ret = __log_init(dbenv, dblp)) != 0)
- goto err;
+ if (F_ISSET(&dblp->reginfo, REGION_CREATE))
+ if ((ret = __log_init(dbenv, dblp)) != 0)
+ goto err;
/* Set the local addresses. */
lp = dblp->reginfo.primary =
R_ADDR(&dblp->reginfo, dblp->reginfo.rp->primary);
- dblp->bufp = R_ADDR(&dblp->reginfo, lp->buffer_off);
/*
* If the region is threaded, then we have to lock both the handles
* and the region, and we need to allocate a mutex for that purpose.
*/
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if ((ret = __db_mutex_alloc(
- dbenv, &dblp->reginfo, &dblp->mutexp)) != 0)
- goto err;
- if ((ret = __db_mutex_init(
- dbenv, dblp->mutexp, 0, MUTEX_THREAD)) != 0)
+ if (F_ISSET(dbenv, DB_ENV_THREAD) &&
+ (ret = __db_mutex_setup(dbenv, &dblp->reginfo, &dblp->mutexp,
+ MUTEX_ALLOC | MUTEX_NO_RLOCK)) != 0)
+ goto err;
+
+ /* Initialize the rest of the structure. */
+ dblp->bufp = R_ADDR(&dblp->reginfo, lp->buffer_off);
+
+ /*
+ * Set the handle -- we may be about to run recovery, which allocates
+ * log cursors. Log cursors require logging be already configured,
+ * and the handle being set is what demonstrates that.
+ *
+ * If we created the region, run recovery. If that fails, make sure
+ * we reset the log handle before cleaning up, otherwise we will try
+ * and clean up again in the mainline DB_ENV initialization code.
+ */
+ dbenv->lg_handle = dblp;
+
+ if (F_ISSET(&dblp->reginfo, REGION_CREATE)) {
+ if ((ret = __log_recover(dblp)) != 0) {
+ dbenv->lg_handle = NULL;
goto err;
+ }
+
+ /*
+ * We first take the log file size from the environment, if
+ * specified. If that wasn't set, recovery may have set it
+ * from the persistent information in a log file header. If
+ * that didn't set it either, we default.
+ */
+ if (lp->log_size == 0)
+ lp->log_size = lp->log_nsize = LG_MAX_DEFAULT;
+ } else {
+ /*
+ * A process joining the region may have reset the log file
+ * size, too. If so, it only affects the next log file we
+ * create.
+ */
+ if (dbenv->lg_size != 0)
+ lp->log_nsize = dbenv->lg_size;
}
R_UNLOCK(dbenv, &dblp->reginfo);
-
- dblp->r_file = 0;
- dblp->r_off = 0;
- dblp->r_size = 0;
- dbenv->lg_handle = dblp;
return (0);
err: if (dblp->reginfo.addr != NULL) {
@@ -112,11 +126,11 @@ err: if (dblp->reginfo.addr != NULL) {
(void)__db_r_detach(dbenv, &dblp->reginfo, 0);
}
- if (readbufp != NULL)
- __os_free(readbufp, dbenv->lg_bsize);
if (dblp->mutexp != NULL)
__db_mutex_free(dbenv, &dblp->reginfo, dblp->mutexp);
- __os_free(dblp, sizeof(*dblp));
+
+ __os_free(dbenv, dblp);
+
return (ret);
}
@@ -129,9 +143,13 @@ __log_init(dbenv, dblp)
DB_ENV *dbenv;
DB_LOG *dblp;
{
+ DB_MUTEX *flush_mutexp;
LOG *region;
int ret;
void *p;
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ u_int8_t *addr;
+#endif
if ((ret = __db_shalloc(dblp->reginfo.addr,
sizeof(*region), 0, &dblp->reginfo.primary)) != 0)
@@ -141,15 +159,55 @@ __log_init(dbenv, dblp)
region = dblp->reginfo.primary;
memset(region, 0, sizeof(*region));
- region->persist.lg_max = dbenv->lg_max;
- region->persist.magic = DB_LOGMAGIC;
- region->persist.version = DB_LOGVERSION;
- region->persist.mode = dbenv->db_mode;
+ region->fid_max = 0;
SH_TAILQ_INIT(&region->fq);
+ region->free_fid_stack = INVALID_ROFF;
+ region->free_fids = region->free_fids_alloced = 0;
/* Initialize LOG LSNs. */
- region->lsn.file = 1;
- region->lsn.offset = 0;
+ INIT_LSN(region->lsn);
+ INIT_LSN(region->ready_lsn);
+ INIT_LSN(region->t_lsn);
+
+ /*
+ * It's possible to be waiting for an LSN of [1][0], if a replication
+ * client gets the first log record out of order. An LSN of [0][0]
+ * signifies that we're not waiting.
+ */
+ ZERO_LSN(region->waiting_lsn);
+
+ /*
+ * Log makes note of the fact that it ran into a checkpoint on
+ * startup if it did so, as a recovery optimization. A zero
+ * LSN signifies that it hasn't found one [yet].
+ */
+ ZERO_LSN(region->cached_ckp_lsn);
+
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ /* Allocate room for the log maintenance info and initialize it. */
+ if ((ret = __db_shalloc(dblp->reginfo.addr,
+ sizeof(REGMAINT) + LG_MAINT_SIZE, 0, &addr)) != 0)
+ goto mem_err;
+ __db_maintinit(&dblp->reginfo, addr, LG_MAINT_SIZE);
+ region->maint_off = R_OFFSET(&dblp->reginfo, addr);
+#endif
+
+ if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, &region->fq_mutex,
+ MUTEX_NO_RLOCK)) != 0)
+ return (ret);
+
+ /*
+ * We must create a place for the flush mutex separately; mutexes have
+ * to be aligned to MUTEX_ALIGN, and the only way to guarantee that is
+ * to make sure they're at the beginning of a shalloc'ed chunk.
+ */
+ if ((ret = __db_shalloc(dblp->reginfo.addr,
+ sizeof(DB_MUTEX), MUTEX_ALIGN, &flush_mutexp)) != 0)
+ goto mem_err;
+ if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, flush_mutexp,
+ MUTEX_NO_RLOCK)) != 0)
+ return (ret);
+ region->flush_mutex_off = R_OFFSET(&dblp->reginfo, flush_mutexp);
/* Initialize the buffer. */
if ((ret =
@@ -159,9 +217,23 @@ mem_err: __db_err(dbenv, "Unable to allocate memory for the log buffer");
}
region->buffer_size = dbenv->lg_bsize;
region->buffer_off = R_OFFSET(&dblp->reginfo, p);
+ region->log_size = region->log_nsize = dbenv->lg_size;
- /* Try and recover any previous log files before releasing the lock. */
- return (__log_recover(dblp));
+ /* Initialize the commit Queue. */
+ SH_TAILQ_INIT(&region->free_commits);
+ SH_TAILQ_INIT(&region->commits);
+ region->ncommit = 0;
+
+ /*
+ * Fill in the log's persistent header. Don't fill in the log file
+ * sizes, as they may change at any time and so have to be filled in
+ * as each log file is created.
+ */
+ region->persist.magic = DB_LOGMAGIC;
+ region->persist.version = DB_LOGVERSION;
+ region->persist.mode = (u_int32_t)dbenv->db_mode;
+
+ return (0);
}
/*
@@ -173,12 +245,16 @@ __log_recover(dblp)
DB_LOG *dblp;
{
DBT dbt;
+ DB_ENV *dbenv;
+ DB_LOGC *logc;
DB_LSN lsn;
LOG *lp;
- int cnt, found_checkpoint, ret;
- u_int32_t chk;
+ u_int32_t cnt, rectype;
+ int ret;
logfile_validity status;
+ logc = NULL;
+ dbenv = dblp->dbenv;
lp = dblp->reginfo.primary;
/*
@@ -192,8 +268,9 @@ __log_recover(dblp)
/*
* If the last file is an old version, readable or no, start a new
- * file. Don't bother finding checkpoints; if we didn't take a
- * checkpoint right before upgrading, the user screwed up anyway.
+ * file. Don't bother finding the end of the last log file;
+ * we assume that it's valid in its entirety, since the user
+ * should have shut down cleanly or run recovery before upgrading.
*/
if (status == DB_LV_OLD_READABLE || status == DB_LV_OLD_UNREADABLE) {
lp->lsn.file = lp->s_lsn.file = cnt + 1;
@@ -213,25 +290,35 @@ __log_recover(dblp)
lsn.file = cnt;
lsn.offset = 0;
- /* Set the cursor. Shouldn't fail; leave error messages on. */
- memset(&dbt, 0, sizeof(dbt));
- if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0)
+ /*
+ * Allocate a cursor and set it to the first record. This shouldn't
+ * fail, leave error messages on.
+ */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
return (ret);
+ F_SET(logc, DB_LOG_LOCKED);
+ memset(&dbt, 0, sizeof(dbt));
+ if ((ret = logc->get(logc, &lsn, &dbt, DB_SET)) != 0)
+ goto err;
/*
- * Read to the end of the file, saving checkpoints. This will fail
- * at some point, so turn off error messages.
+ * Read to the end of the file. This may fail at some point, so
+ * turn off error messages.
*/
- found_checkpoint = 0;
- while (__log_get(dblp, &lsn, &dbt, DB_NEXT, 1) == 0) {
+ F_SET(logc, DB_LOG_SILENT_ERR);
+ while (logc->get(logc, &lsn, &dbt, DB_NEXT) == 0) {
if (dbt.size < sizeof(u_int32_t))
continue;
- memcpy(&chk, dbt.data, sizeof(u_int32_t));
- if (chk == DB_txn_ckp) {
- lp->chkpt_lsn = lsn;
- found_checkpoint = 1;
- }
+ memcpy(&rectype, dbt.data, sizeof(u_int32_t));
+ if (rectype == DB___txn_ckp)
+ /*
+ * If we happen to run into a checkpoint, cache its
+ * LSN so that the transaction system doesn't have
+ * to walk this log file again looking for it.
+ */
+ lp->cached_ckp_lsn = lsn;
}
+ F_CLR(logc, DB_LOG_SILENT_ERR);
/*
* We now know where the end of the log is. Set the first LSN that
@@ -240,59 +327,24 @@ __log_recover(dblp)
*/
lp->lsn = lsn;
lp->s_lsn = lsn;
- lp->lsn.offset += dblp->c_len;
- lp->s_lsn.offset += dblp->c_len;
+ lp->lsn.offset += logc->c_len;
+ lp->s_lsn.offset += logc->c_len;
/* Set up the current buffer information, too. */
- lp->len = dblp->c_len;
+ lp->len = logc->c_len;
lp->b_off = 0;
lp->w_off = lp->lsn.offset;
- /*
- * It's possible that we didn't find a checkpoint because there wasn't
- * one in the last log file. Start searching.
- */
- if (!found_checkpoint && cnt > 1) {
- lsn.file = cnt;
- lsn.offset = 0;
-
- /* Set the cursor. Shouldn't fail, leave error messages on. */
- if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0)
- return (ret);
-
- /*
- * Read to the end of the file, saving checkpoints. Again,
- * this can fail if there are no checkpoints in any log file,
- * so turn error messages off.
- */
- while (__log_get(dblp, &lsn, &dbt, DB_PREV, 1) == 0) {
- if (dbt.size < sizeof(u_int32_t))
- continue;
- memcpy(&chk, dbt.data, sizeof(u_int32_t));
- if (chk == DB_txn_ckp) {
- lp->chkpt_lsn = lsn;
- found_checkpoint = 1;
- break;
- }
- }
- }
-
- /* If we never find a checkpoint, that's okay, just 0 it out. */
- if (!found_checkpoint)
-skipsearch: ZERO_LSN(lp->chkpt_lsn);
-
- /*
- * Reset the cursor lsn to the beginning of the log, so that an
- * initial call to DB_NEXT does the right thing.
- */
- ZERO_LSN(dblp->c_lsn);
-
- if (FLD_ISSET(dblp->dbenv->verbose, DB_VERB_RECOVERY))
- __db_err(dblp->dbenv,
+skipsearch:
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))
+ __db_err(dbenv,
"Finding last valid log LSN: file: %lu offset %lu",
(u_long)lp->lsn.file, (u_long)lp->lsn.offset);
- return (0);
+err: if (logc != NULL)
+ (void)logc->close(logc, 0);
+
+ return (ret);
}
/*
@@ -301,20 +353,23 @@ skipsearch: ZERO_LSN(lp->chkpt_lsn);
* the number of the first readable log file, else it will contain the number
* of the last log file (which may be too old to read).
*
- * PUBLIC: int __log_find __P((DB_LOG *, int, int *, logfile_validity *));
+ * PUBLIC: int __log_find __P((DB_LOG *, int, u_int32_t *, logfile_validity *));
*/
int
__log_find(dblp, find_first, valp, statusp)
DB_LOG *dblp;
- int find_first, *valp;
+ int find_first;
+ u_int32_t *valp;
logfile_validity *statusp;
{
+ DB_ENV *dbenv;
logfile_validity logval_status, status;
u_int32_t clv, logval;
int cnt, fcnt, ret;
const char *dir;
- char **names, *p, *q, savech;
+ char *c, **names, *p, *q, savech;
+ dbenv = dblp->dbenv;
logval_status = status = DB_LV_NONEXISTENT;
/* Return a value of 0 as the log file number on failure. */
@@ -333,7 +388,7 @@ __log_find(dblp, find_first, valp, statusp)
}
/* Get the list of file names. */
- ret = __os_dirlist(dblp->dbenv, dir, &names, &fcnt);
+ ret = __os_dirlist(dbenv, dir, &names, &fcnt);
/*
* !!!
@@ -345,8 +400,8 @@ __log_find(dblp, find_first, valp, statusp)
*q = savech;
if (ret != 0) {
- __db_err(dblp->dbenv, "%s: %s", dir, db_strerror(ret));
- __os_freestr(p);
+ __db_err(dbenv, "%s: %s", dir, db_strerror(ret));
+ __os_free(dbenv, p);
return (ret);
}
@@ -356,74 +411,92 @@ __log_find(dblp, find_first, valp, statusp)
continue;
/*
+ * Names of the form log\.[0-9]* are reserved for DB. Other
+ * names sharing LFPREFIX, such as "log.db", are legal.
+ */
+ for (c = names[cnt] + sizeof(LFPREFIX) - 1; *c != '\0'; c++)
+ if (!isdigit((int)*c))
+ break;
+ if (*c != '\0')
+ continue;
+
+ /*
* Use atol, not atoi; if an "int" is 16-bits, the largest
* log file name won't fit.
*/
clv = atol(names[cnt] + (sizeof(LFPREFIX) - 1));
+
+ /*
+ * If searching for the first log file, we want to return the
+ * oldest log file we can read, or, if no readable log files
+ * exist, the newest log file we can't read (the crossover
+ * point between the old and new versions of the log file).
+ *
+ * If we're searching for the last log file, we want to return
+ * the newest log file, period.
+ *
+ * Readable log files should never preceede unreadable log
+ * files, that would mean the admin seriously screwed up.
+ */
if (find_first) {
- if (logval != 0 && clv > logval)
+ if (logval != 0 &&
+ status != DB_LV_OLD_UNREADABLE && clv > logval)
continue;
} else
if (logval != 0 && clv < logval)
continue;
- /*
- * Take note of whether the log file logval is
- * an old version or incompletely initialized.
- */
- if ((ret = __log_valid(dblp, clv, 1, &status)) != 0)
+ if ((ret = __log_valid(dblp, clv, 1, &status)) != 0) {
+ __db_err(dbenv, "Invalid log file: %s: %s",
+ names[cnt], db_strerror(ret));
goto err;
+ }
switch (status) {
+ case DB_LV_NONEXISTENT:
+ /* __log_valid never returns DB_LV_NONEXISTENT. */
+ DB_ASSERT(0);
+ break;
case DB_LV_INCOMPLETE:
/*
- * It's acceptable for the last log file to
- * have been incompletely initialized--it's possible
- * to create a log file but not write anything to it,
- * and recovery needs to gracefully handle this.
- *
- * Just ignore it; we don't want to return this
- * as a valid log file.
+ * The last log file may not have been initialized --
+ * it's possible to create a log file but not write
+ * anything to it. If performing recovery (that is,
+ * if find_first isn't set), ignore the file, it's
+ * not interesting. If we're searching for the first
+ * log record, return the file (assuming we don't find
+ * something better), as the "real" first log record
+ * is likely to be in the log buffer, and we want to
+ * set the file LSN for our return.
*/
+ if (find_first)
+ goto found;
break;
- case DB_LV_NONEXISTENT:
- /* Should never happen. */
- DB_ASSERT(0);
+ case DB_LV_OLD_UNREADABLE:
+ /*
+ * If we're searching for the first log file, then we
+ * only want this file if we don't yet have a file or
+ * already have an unreadable file and this one is
+ * newer than that one. If we're searching for the
+ * last log file, we always want this file because we
+ * wouldn't be here if it wasn't newer than our current
+ * choice.
+ */
+ if (!find_first || logval == 0 ||
+ (status == DB_LV_OLD_UNREADABLE && clv > logval))
+ goto found;
break;
case DB_LV_NORMAL:
case DB_LV_OLD_READABLE:
- logval = clv;
+found: logval = clv;
logval_status = status;
break;
- case DB_LV_OLD_UNREADABLE:
- /*
- * Continue; we want the oldest valid log,
- * and clv is too old to be useful. We don't
- * want it to supplant logval if we're looking for
- * the oldest valid log, but we do want to return
- * it if it's the last log file--we want the very
- * last file number, so that our caller can
- * start a new file after it.
- *
- * The code here assumes that there will never
- * be a too-old log that's preceded by a log
- * of the current version, but in order to
- * attain that state of affairs the user
- * would have had to really seriously screw
- * up; I think we can safely assume this won't
- * happen.
- */
- if (!find_first) {
- logval = clv;
- logval_status = status;
- }
- break;
}
}
*valp = logval;
-err: __os_dirfree(names, fcnt);
- __os_freestr(p);
+err: __os_dirfree(dbenv, names, fcnt);
+ __os_free(dbenv, p);
*statusp = logval_status;
return (ret);
@@ -446,30 +519,48 @@ __log_valid(dblp, number, set_persist, statusp)
int set_persist;
logfile_validity *statusp;
{
+ DB_CIPHER *db_cipher;
+ DB_ENV *dbenv;
DB_FH fh;
+ HDR *hdr;
LOG *region;
- LOGP persist;
- char *fname;
- int ret;
+ LOGP *persist;
logfile_validity status;
- size_t nw;
+ size_t hdrsize, nw, recsize;
+ int is_hmac, need_free, ret;
+ u_int8_t *tmp;
+ char *fname;
+ dbenv = dblp->dbenv;
+ db_cipher = dbenv->crypto_handle;
+ persist = NULL;
status = DB_LV_NORMAL;
/* Try to open the log file. */
if ((ret = __log_name(dblp,
number, &fname, &fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
- __os_freestr(fname);
+ __os_free(dbenv, fname);
return (ret);
}
+ need_free = 0;
+ hdrsize = HDR_NORMAL_SZ;
+ is_hmac = 0;
+ recsize = sizeof(LOGP);
+ if (CRYPTO_ON(dbenv)) {
+ hdrsize = HDR_CRYPTO_SZ;
+ recsize = sizeof(LOGP);
+ recsize += db_cipher->adj_size(recsize);
+ is_hmac = 1;
+ }
+ if ((ret = __os_calloc(dbenv, 1, recsize + hdrsize, &tmp)) != 0)
+ return (ret);
+ need_free = 1;
+ hdr = (HDR *)tmp;
+ persist = (LOGP *)(tmp + hdrsize);
/* Try to read the header. */
- if ((ret =
- __os_seek(dblp->dbenv,
- &fh, 0, 0, sizeof(HDR), 0, DB_OS_SEEK_SET)) != 0 ||
- (ret =
- __os_read(dblp->dbenv, &fh, &persist, sizeof(LOGP), &nw)) != 0 ||
- nw != sizeof(LOGP)) {
+ if ((ret = __os_read(dbenv, &fh, tmp, recsize + hdrsize, &nw)) != 0 ||
+ nw != recsize + hdrsize) {
if (ret == 0)
status = DB_LV_INCOMPLETE;
else
@@ -477,19 +568,63 @@ __log_valid(dblp, number, set_persist, statusp)
* The error was a fatal read error, not just an
* incompletely initialized log file.
*/
- __db_err(dblp->dbenv, "Ignoring log file: %s: %s",
+ __db_err(dbenv, "Ignoring log file: %s: %s",
fname, db_strerror(ret));
- (void)__os_closehandle(&fh);
+ (void)__os_closehandle(dbenv, &fh);
goto err;
}
- (void)__os_closehandle(&fh);
+ (void)__os_closehandle(dbenv, &fh);
+
+ /*
+ * Now we have to validate the persistent record. We have
+ * several scenarios we have to deal with:
+ *
+ * 1. User has crypto turned on:
+ * - They're reading an old, unencrypted log file
+ * . We will fail the record size match check below.
+ * - They're reading a current, unencrypted log file
+ * . We will fail the record size match check below.
+ * - They're reading an old, encrypted log file [NOT YET]
+ * . After decryption we'll fail the version check. [NOT YET]
+ * - They're reading a current, encrypted log file
+ * . We should proceed as usual.
+ * 2. User has crypto turned off:
+ * - They're reading an old, unencrypted log file
+ * . We will fail the version check.
+ * - They're reading a current, unencrypted log file
+ * . We should proceed as usual.
+ * - They're reading an old, encrypted log file [NOT YET]
+ * . We'll fail the magic number check (it is encrypted).
+ * - They're reading a current, encrypted log file
+ * . We'll fail the magic number check (it is encrypted).
+ */
+ if (CRYPTO_ON(dbenv)) {
+ /*
+ * If we are trying to decrypt an unencrypted log
+ * we can only detect that by having an unreasonable
+ * data length for our persistent data.
+ */
+ if ((hdr->len - hdrsize) != sizeof(LOGP)) {
+ __db_err(dbenv, "log record size mismatch");
+ goto err;
+ }
+ /* Check the checksum and decrypt. */
+ if ((ret = __db_check_chksum(dbenv, db_cipher, &hdr->chksum[0],
+ (u_int8_t *)persist, hdr->len - hdrsize, is_hmac)) != 0) {
+ __db_err(dbenv, "log record checksum mismatch");
+ goto err;
+ }
+ if ((ret = db_cipher->decrypt(dbenv, db_cipher->data,
+ &hdr->iv[0], (u_int8_t *)persist, hdr->len - hdrsize)) != 0)
+ goto err;
+ }
/* Validate the header. */
- if (persist.magic != DB_LOGMAGIC) {
- __db_err(dblp->dbenv,
+ if (persist->magic != DB_LOGMAGIC) {
+ __db_err(dbenv,
"Ignoring log file: %s: magic number %lx, not %lx",
- fname, (u_long)persist.magic, (u_long)DB_LOGMAGIC);
+ fname, (u_long)persist->magic, (u_long)DB_LOGMAGIC);
ret = EINVAL;
goto err;
}
@@ -499,135 +634,162 @@ __log_valid(dblp, number, set_persist, statusp)
* belongs to an unreadable or readable old version; leave it
* alone if and only if the log file version is the current one.
*/
- if (persist.version > DB_LOGVERSION) {
+ if (persist->version > DB_LOGVERSION) {
/* This is a fatal error--the log file is newer than DB. */
- __db_err(dblp->dbenv,
+ __db_err(dbenv,
"Ignoring log file: %s: unsupported log version %lu",
- fname, (u_long)persist.version);
+ fname, (u_long)persist->version);
ret = EINVAL;
goto err;
- } else if (persist.version < DB_LOGOLDVER) {
+ } else if (persist->version < DB_LOGOLDVER) {
status = DB_LV_OLD_UNREADABLE;
/*
* We don't want to set persistent info based on an
* unreadable region, so jump to "err".
*/
goto err;
- } else if (persist.version < DB_LOGVERSION)
+ } else if (persist->version < DB_LOGVERSION)
status = DB_LV_OLD_READABLE;
/*
- * If the log is thus far readable and we're doing system
- * initialization, set the region's persistent information
- * based on the headers.
+ * Only if we have a current log do we verify the checksum.
+ * We could not check the checksum before checking the magic
+ * and version because old log hdrs have the length and checksum
+ * in a different location.
+ */
+ if (!CRYPTO_ON(dbenv) && ((ret = __db_check_chksum(dbenv,
+ db_cipher, &hdr->chksum[0], (u_int8_t *)persist,
+ hdr->len - hdrsize, is_hmac)) != 0)) {
+ __db_err(dbenv, "log record checksum mismatch");
+ goto err;
+ }
+
+ /*
+ * If the log is readable so far and we're doing system initialization,
+ * set the region's persistent information based on the headers.
+ *
+ * Always set the current log file size. Only set the next log file's
+ * size if the application hasn't set it already.
+ *
+ * XXX
+ * Always use the persistent header's mode, regardless of what was set
+ * in the current environment. We've always done it this way, but it's
+ * probably a bug -- I can't think of a way not-changing the mode would
+ * be a problem, though.
*/
if (set_persist) {
region = dblp->reginfo.primary;
- region->persist.lg_max = persist.lg_max;
- region->persist.mode = persist.mode;
+ region->log_size = persist->log_size;
+ if (region->log_nsize == 0)
+ region->log_nsize = persist->log_size;
+ region->persist.mode = persist->mode;
}
-err: __os_freestr(fname);
+err: __os_free(dbenv, fname);
+ if (need_free)
+ __os_free(dbenv, tmp);
*statusp = status;
return (ret);
}
/*
- * __log_close --
- * Internal version of log_close: only called from dbenv_refresh.
+ * __log_dbenv_refresh --
+ * Clean up after the log system on a close or failed open. Called only
+ * from __dbenv_refresh. (Formerly called __log_close.)
*
- * PUBLIC: int __log_close __P((DB_ENV *));
+ * PUBLIC: int __log_dbenv_refresh __P((DB_ENV *));
*/
int
-__log_close(dbenv)
+__log_dbenv_refresh(dbenv)
DB_ENV *dbenv;
{
DB_LOG *dblp;
int ret, t_ret;
- ret = 0;
dblp = dbenv->lg_handle;
/* We may have opened files as part of XA; if so, close them. */
F_SET(dblp, DBLOG_RECOVER);
- __log_close_files(dbenv);
+ ret = __dbreg_close_files(dbenv);
/* Discard the per-thread lock. */
if (dblp->mutexp != NULL)
__db_mutex_free(dbenv, &dblp->reginfo, dblp->mutexp);
/* Detach from the region. */
- ret = __db_r_detach(dbenv, &dblp->reginfo, 0);
+ if ((t_ret =
+ __db_r_detach(dbenv, &dblp->reginfo, 0)) != 0 && ret == 0)
+ ret = t_ret;
/* Close open files, release allocated memory. */
if (F_ISSET(&dblp->lfh, DB_FH_VALID) &&
- (t_ret = __os_closehandle(&dblp->lfh)) != 0 && ret == 0)
- ret = t_ret;
- if (dblp->c_dbt.data != NULL)
- __os_free(dblp->c_dbt.data, dblp->c_dbt.ulen);
- if (F_ISSET(&dblp->c_fh, DB_FH_VALID) &&
- (t_ret = __os_closehandle(&dblp->c_fh)) != 0 && ret == 0)
+ (t_ret = __os_closehandle(dbenv, &dblp->lfh)) != 0 && ret == 0)
ret = t_ret;
if (dblp->dbentry != NULL)
- __os_free(dblp->dbentry,
- (dblp->dbentry_cnt * sizeof(DB_ENTRY)));
- if (dblp->readbufp != NULL)
- __os_free(dblp->readbufp, dbenv->lg_bsize);
+ __os_free(dbenv, dblp->dbentry);
- __os_free(dblp, sizeof(*dblp));
+ __os_free(dbenv, dblp);
dbenv->lg_handle = NULL;
return (ret);
}
/*
- * log_stat --
- * Return LOG statistics.
+ * __log_stat --
+ * Return log statistics.
+ *
+ * PUBLIC: int __log_stat __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
*/
int
-log_stat(dbenv, statp, db_malloc)
+__log_stat(dbenv, statp, flags)
DB_ENV *dbenv;
DB_LOG_STAT **statp;
- void *(*db_malloc) __P((size_t));
+ u_int32_t flags;
{
DB_LOG *dblp;
DB_LOG_STAT *stats;
LOG *region;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_stat(dbenv, statp, db_malloc));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_stat", DB_INIT_LOG);
*statp = NULL;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->log_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
dblp = dbenv->lg_handle;
region = dblp->reginfo.primary;
- if ((ret = __os_malloc(dbenv,
- sizeof(DB_LOG_STAT), db_malloc, &stats)) != 0)
+ if ((ret = __os_umalloc(dbenv, sizeof(DB_LOG_STAT), &stats)) != 0)
return (ret);
/* Copy out the global statistics. */
R_LOCK(dbenv, &dblp->reginfo);
*stats = region->stat;
+ if (LF_ISSET(DB_STAT_CLEAR))
+ memset(&region->stat, 0, sizeof(region->stat));
stats->st_magic = region->persist.magic;
stats->st_version = region->persist.version;
stats->st_mode = region->persist.mode;
stats->st_lg_bsize = region->buffer_size;
- stats->st_lg_max = region->persist.lg_max;
+ stats->st_lg_size = region->log_nsize;
stats->st_region_wait = dblp->reginfo.rp->mutex.mutex_set_wait;
stats->st_region_nowait = dblp->reginfo.rp->mutex.mutex_set_nowait;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ dblp->reginfo.rp->mutex.mutex_set_wait = 0;
+ dblp->reginfo.rp->mutex.mutex_set_nowait = 0;
+ }
stats->st_regsize = dblp->reginfo.rp->size;
stats->st_cur_file = region->lsn.file;
stats->st_cur_offset = region->lsn.offset;
+ stats->st_disk_file = region->s_lsn.file;
+ stats->st_disk_offset = region->s_lsn.offset;
R_UNLOCK(dbenv, &dblp->reginfo);
@@ -636,22 +798,287 @@ log_stat(dbenv, statp, db_malloc)
}
/*
- * __log_lastckp --
- * Return the current chkpt_lsn, so that we can store it in
- * the transaction region and keep the chain of checkpoints
- * unbroken across environment recreates.
+ * __log_get_cached_ckp_lsn --
+ * Retrieve any last checkpoint LSN that we may have found on startup.
+ *
+ * PUBLIC: void __log_get_cached_ckp_lsn __P((DB_ENV *, DB_LSN *));
+ */
+void
+__log_get_cached_ckp_lsn(dbenv, ckp_lsnp)
+ DB_ENV *dbenv;
+ DB_LSN *ckp_lsnp;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+
+ dblp = (DB_LOG *)dbenv->lg_handle;
+ lp = (LOG *)dblp->reginfo.primary;
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ *ckp_lsnp = lp->cached_ckp_lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+}
+
+/*
+ * __log_region_size --
+ * Return the amount of space needed for the log region.
+ * Make the region large enough to hold txn_max transaction
+ * detail structures plus some space to hold thread handles
+ * and the beginning of the shalloc region and anything we
+ * need for mutex system resource recording.
+ */
+static size_t
+__log_region_size(dbenv)
+ DB_ENV *dbenv;
+{
+ size_t s;
+
+ s = dbenv->lg_regionmax + dbenv->lg_bsize;
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ if (F_ISSET(dbenv, DB_ENV_THREAD))
+ s += sizeof(REGMAINT) + LG_MAINT_SIZE;
+#endif
+ return (s);
+}
+
+/*
+ * __log_region_destroy
+ * Destroy any region maintenance info.
+ *
+ * PUBLIC: void __log_region_destroy __P((DB_ENV *, REGINFO *));
+ */
+void
+__log_region_destroy(dbenv, infop)
+ DB_ENV *dbenv;
+ REGINFO *infop;
+{
+ __db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
+ ((LOG *)R_ADDR(infop, infop->rp->primary))->maint_off));
+
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(infop, NULL);
+}
+
+/*
+ * __log_vtruncate
+ * This is a virtual truncate. We set up the log indicators to
+ * make everyone believe that the given record is the last one in the
+ * log. Returns with the next valid LSN (i.e., the LSN of the next
+ * record to be written). This is used in replication to discard records
+ * in the log file that do not agree with the master.
+ *
+ * PUBLIC: int __log_vtruncate __P((DB_ENV *, DB_LSN *, DB_LSN *));
+ */
+int
+__log_vtruncate(dbenv, lsn, ckplsn)
+ DB_ENV *dbenv;
+ DB_LSN *lsn, *ckplsn;
+{
+ DBT log_dbt;
+ DB_FH fh;
+ DB_LOG *dblp;
+ DB_LOGC *logc;
+ DB_LSN end_lsn;
+ LOG *lp;
+ u_int32_t bytes, c_len;
+ int fn, ret, t_ret;
+ char *fname;
+
+ /* Need to find out the length of this soon-to-be-last record. */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ memset(&log_dbt, 0, sizeof(log_dbt));
+ ret = logc->get(logc, lsn, &log_dbt, DB_SET);
+ c_len = logc->c_len;
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (ret != 0)
+ return (ret);
+
+ /* Now do the truncate. */
+ dblp = (DB_LOG *)dbenv->lg_handle;
+ lp = (LOG *)dblp->reginfo.primary;
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ end_lsn = lp->lsn;
+ lp->lsn = *lsn;
+ lp->len = c_len;
+ lp->lsn.offset += lp->len;
+
+ /*
+ * I am going to assume that the number of bytes written since
+ * the last checkpoint doesn't exceed a 32-bit number.
+ */
+ DB_ASSERT(lp->lsn.file >= ckplsn->file);
+ bytes = 0;
+ if (ckplsn->file != lp->lsn.file) {
+ bytes = lp->log_size - ckplsn->offset;
+ if (lp->lsn.file > ckplsn->file + 1)
+ bytes += lp->log_size *
+ (lp->lsn.file - ckplsn->file - 1);
+ bytes += lp->lsn.offset;
+ } else
+ bytes = lp->lsn.offset - ckplsn->offset;
+
+ lp->stat.st_wc_mbytes += bytes / MEGABYTE;
+ lp->stat.st_wc_bytes += bytes % MEGABYTE;
+
+ /*
+ * If the saved lsn is greater than our new end of log, reset it
+ * to our current end of log.
+ */
+ if (log_compare(&lp->s_lsn, lsn) > 0)
+ lp->s_lsn = lp->lsn;
+
+ /*
+ * If the new end of log is in the middle of the buffer,
+ * don't change the w_off or f_lsn. If the new end is
+ * before the w_off then reset w_off and f_lsn to the new
+ * end of log.
+ */
+ if (lp->w_off >= lp->lsn.offset) {
+ lp->f_lsn = lp->lsn;
+ lp->w_off = lp->lsn.offset;
+ lp->b_off = 0;
+ } else
+ lp->b_off = lp->lsn.offset - lp->w_off;
+
+ ZERO_LSN(lp->waiting_lsn);
+ lp->ready_lsn = lp->lsn;
+ lp->wait_recs = 0;
+ lp->rcvd_recs = 0;
+
+ /* Now throw away any extra log files that we have around. */
+ for (fn = lp->lsn.file + 1;; fn++) {
+ if (__log_name(dblp, fn, &fname, &fh, DB_OSO_RDONLY) != 0) {
+ __os_free(dbenv, fname);
+ break;
+ }
+ (void)__os_closehandle(dbenv, &fh);
+ ret = __os_unlink(dbenv, fname);
+ __os_free(dbenv, fname);
+ if (ret != 0)
+ goto err;
+ }
+
+ /* Truncate the log to the new point. */
+ if ((ret = __log_zero(dbenv, &lp->lsn, &end_lsn)) != 0)
+ goto err;
+
+err: R_UNLOCK(dbenv, &dblp->reginfo);
+ return (ret);
+}
+
+/*
+ * __log_is_outdated --
+ * Used by the replication system to identify if a client's logs
+ * are too old. The log represented by dbenv is compared to the file
+ * number passed in fnum. If the log file fnum does not exist and is
+ * lower-numbered than the current logs, the we return *outdatedp non
+ * zero, else we return it 0.
*
- * PUBLIC: int __log_lastckp __P((DB_ENV *, DB_LSN *));
+ * PUBLIC: int __log_is_outdated __P((DB_ENV *dbenv,
+ * PUBLIC: u_int32_t fnum, int *outdatedp));
*/
int
-__log_lastckp(dbenv, lsnp)
+__log_is_outdated(dbenv, fnum, outdatedp)
DB_ENV *dbenv;
- DB_LSN *lsnp;
+ u_int32_t fnum;
+ int *outdatedp;
{
+ DB_LOG *dblp;
LOG *lp;
+ char *name;
+ int ret;
+ u_int32_t cfile;
- lp = (LOG *)(((DB_LOG *)dbenv->lg_handle)->reginfo.primary);
+ dblp = dbenv->lg_handle;
+ *outdatedp = 0;
+
+ if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)
+ return (ret);
+
+ /* If the file exists, we're just fine. */
+ if (__os_exists(name, NULL) == 0)
+ goto out;
+
+ /*
+ * It didn't exist, decide if the file number is too big or
+ * too little. If it's too little, then we need to indicate
+ * that the LSN is outdated.
+ */
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp = (LOG *)dblp->reginfo.primary;
+ cfile = lp->lsn.file;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ if (cfile > fnum)
+ *outdatedp = 1;
+out: __os_free(dbenv, name);
+ return (ret);
+}
+
+/*
+ * __log_zero --
+ * Zero out the tail of a log after a truncate.
+ */
+static int
+__log_zero(dbenv, from_lsn, to_lsn)
+ DB_ENV *dbenv;
+ DB_LSN *from_lsn, *to_lsn;
+{
+ char *lname;
+ DB_LOG *dblp;
+ LOG *lp;
+ int ret;
+ size_t nbytes, len, nw;
+ u_int8_t buf[4096];
+ u_int32_t mbytes, bytes;
+
+ dblp = dbenv->lg_handle;
+ lp = (LOG *)dblp->reginfo.primary;
+ lname = NULL;
+
+ if (dblp->lfname != lp->lsn.file) {
+ if (F_ISSET(&dblp->lfh, DB_FH_VALID))
+ (void)__os_closehandle(dbenv, &dblp->lfh);
+ dblp->lfname = lp->lsn.file;
+ }
+
+ if (from_lsn->file != to_lsn->file) {
+ /* We removed some log files; have to 0 to end of file. */
+ if (!F_ISSET(&dblp->lfh, DB_FH_VALID) && (ret =
+ __log_name(dblp, dblp->lfname, &lname, &dblp->lfh, 0)) != 0)
+ return (ret);
+ if ((ret = __os_ioinfo(dbenv,
+ NULL, &dblp->lfh, &mbytes, &bytes, NULL)) != 0)
+ goto err;
+ len = mbytes * MEGABYTE + bytes - from_lsn->offset;
+ } else if (to_lsn->offset <= from_lsn->offset)
+ return (0);
+ else
+ len = to_lsn->offset = from_lsn->offset;
+
+ memset(buf, 0, sizeof(buf));
+
+ /* Initialize the write position. */
+ if (!F_ISSET(&dblp->lfh, DB_FH_VALID) &&
+ (ret = __log_name(dblp, dblp->lfname, &lname, &dblp->lfh, 0)) != 0)
+ goto err;
+
+ if ((ret = __os_seek(dbenv,
+ &dblp->lfh, 0, 0, from_lsn->offset, 0, DB_OS_SEEK_SET)) != 0)
+ return (ret);
+
+ while (len > 0) {
+ nbytes = len > sizeof(buf) ? sizeof(buf) : len;
+ if ((ret =
+ __os_write(dbenv, &dblp->lfh, buf, nbytes, &nw)) != 0)
+ return (ret);
+ len -= nbytes;
+ }
+err: if (lname != NULL)
+ __os_free(dbenv, lname);
- *lsnp = lp->chkpt_lsn;
return (0);
}
diff --git a/bdb/log/log.src b/bdb/log/log.src
deleted file mode 100644
index a92fae8de26..00000000000
--- a/bdb/log/log.src
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * $Id: log.src,v 10.12 2000/02/17 20:24:10 bostic Exp $
- */
-
-PREFIX log
-
-INCLUDE #include "db_config.h"
-INCLUDE
-INCLUDE #ifndef NO_SYSTEM_INCLUDES
-INCLUDE #include <sys/types.h>
-INCLUDE
-INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
-INCLUDE #include <string.h>
-INCLUDE #endif
-INCLUDE
-INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "log.h"
-INCLUDE #include "txn.h"
-INCLUDE
-
-/* Used for registering name/id translations at open or close. */
-DEPRECATED register1 1
-ARG opcode u_int32_t lu
-DBT name DBT s
-DBT uid DBT s
-ARG fileid int32_t ld
-ARG ftype DBTYPE lx
-END
-
-BEGIN register 2
-ARG opcode u_int32_t lu
-DBT name DBT s
-DBT uid DBT s
-ARG fileid int32_t ld
-ARG ftype DBTYPE lx
-ARG meta_pgno db_pgno_t lu
-END
diff --git a/bdb/log/log_archive.c b/bdb/log/log_archive.c
index 83728c79e55..19e1af5a93e 100644
--- a/bdb/log/log_archive.c
+++ b/bdb/log/log_archive.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: log_archive.c,v 11.13 2000/11/30 00:58:40 ubell Exp $";
+static const char revid[] = "$Id: log_archive.c,v 11.39 2002/08/06 05:00:31 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,50 +19,41 @@ static const char revid[] = "$Id: log_archive.c,v 11.13 2000/11/30 00:58:40 ubel
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_dispatch.h"
-#include "log.h"
-#include "clib_ext.h" /* XXX: needed for getcwd. */
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_page.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
+#include "dbinc/txn.h"
static int __absname __P((DB_ENV *, char *, char *, char **));
-static int __build_data __P((DB_ENV *, char *, char ***, void *(*)(size_t)));
+static int __build_data __P((DB_ENV *, char *, char ***));
static int __cmpfunc __P((const void *, const void *));
-static int __usermem __P((DB_ENV *, char ***, void *(*)(size_t)));
+static int __usermem __P((DB_ENV *, char ***));
/*
- * log_archive --
+ * __log_archive --
* Supporting function for db_archive(1).
+ *
+ * PUBLIC: int __log_archive __P((DB_ENV *, char **[], u_int32_t));
*/
int
-log_archive(dbenv, listp, flags, db_malloc)
+__log_archive(dbenv, listp, flags)
DB_ENV *dbenv;
char ***listp;
u_int32_t flags;
- void *(*db_malloc) __P((size_t));
{
DBT rec;
DB_LOG *dblp;
+ DB_LOGC *logc;
DB_LSN stable_lsn;
- u_int32_t fnum;
- int array_size, n, ret;
+ __txn_ckp_args *ckp_args;
char **array, **arrayp, *name, *p, *pref, buf[MAXPATHLEN];
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_archive(dbenv, listp, flags, db_malloc));
-#endif
+ int array_size, db_arch_abs, n, ret;
+ u_int32_t fnum;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_archive", DB_INIT_LOG);
name = NULL;
dblp = dbenv->lg_handle;
@@ -70,15 +61,24 @@ log_archive(dbenv, listp, flags, db_malloc)
#define OKFLAGS (DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)
if (flags != 0) {
- if ((ret =
- __db_fchk(dbenv, "log_archive", flags, OKFLAGS)) != 0)
+ if ((ret = __db_fchk(
+ dbenv, "DB_ENV->log_archive", flags, OKFLAGS)) != 0)
return (ret);
- if ((ret =
- __db_fcchk(dbenv,
- "log_archive", flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0)
+ if ((ret = __db_fcchk(dbenv, "DB_ENV->log_archive",
+ flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0)
return (ret);
}
+ if (LF_ISSET(DB_ARCH_ABS)) {
+ db_arch_abs = 1;
+ LF_CLR(DB_ARCH_ABS);
+ } else
+ db_arch_abs = 0;
+
+ if (flags == 0 || flags == DB_ARCH_DATA)
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->tx_handle, "DB_ENV->log_archive", DB_INIT_TXN);
+
/*
* Get the absolute pathname of the current directory. It would
* be nice to get the shortest pathname of the database directory,
@@ -88,7 +88,7 @@ log_archive(dbenv, listp, flags, db_malloc)
* Can't trust getcwd(3) to set a valid errno. If it doesn't, just
* guess that we ran out of memory.
*/
- if (LF_ISSET(DB_ARCH_ABS)) {
+ if (db_arch_abs) {
__os_set_errno(0);
if ((pref = getcwd(buf, sizeof(buf))) == NULL) {
if (__os_get_errno() == 0)
@@ -98,31 +98,55 @@ log_archive(dbenv, listp, flags, db_malloc)
} else
pref = NULL;
- switch (LF_ISSET(~DB_ARCH_ABS)) {
+ switch (flags) {
case DB_ARCH_DATA:
- return (__build_data(dbenv, pref, listp, db_malloc));
+ return (__build_data(dbenv, pref, listp));
case DB_ARCH_LOG:
memset(&rec, 0, sizeof(rec));
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- F_SET(&rec, DB_DBT_MALLOC);
- if ((ret = log_get(dbenv, &stable_lsn, &rec, DB_LAST)) != 0)
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+#ifdef UMRW
+ ZERO_LSN(stable_lsn);
+#endif
+ ret = logc->get(logc, &stable_lsn, &rec, DB_LAST);
+ (void)logc->close(logc, 0);
+ if (ret != 0)
return (ret);
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- __os_free(rec.data, rec.size);
fnum = stable_lsn.file;
break;
case 0:
- if ((ret = __log_findckp(dbenv, &stable_lsn)) != 0) {
+ memset(&rec, 0, sizeof(rec));
+ if (__txn_getckp(dbenv, &stable_lsn) != 0) {
/*
- * A return of DB_NOTFOUND means that we didn't find
- * any records in the log (so we are not going to be
- * deleting any log files).
+ * A failure return means that there's no checkpoint
+ * in the log (so we are not going to be deleting
+ * any log files).
*/
- if (ret != DB_NOTFOUND)
- return (ret);
*listp = NULL;
return (0);
}
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ if ((ret = logc->get(logc, &stable_lsn, &rec, DB_SET)) != 0 ||
+ (ret = __txn_ckp_read(dbenv, rec.data, &ckp_args)) != 0) {
+ /*
+ * A return of DB_NOTFOUND may only mean that the
+ * checkpoint LSN is before the beginning of the
+ * log files that we still have. This is not
+ * an error; it just means our work is done.
+ */
+ if (ret == DB_NOTFOUND) {
+ *listp = NULL;
+ ret = 0;
+ }
+ (void)logc->close(logc, 0);
+ return (ret);
+ }
+ if ((ret = logc->close(logc, 0)) != 0)
+ return (ret);
+ stable_lsn = ckp_args->ckp_lsn;
+ __os_free(dbenv, ckp_args);
+
/* Remove any log files before the last stable LSN. */
fnum = stable_lsn.file - 1;
break;
@@ -130,9 +154,9 @@ log_archive(dbenv, listp, flags, db_malloc)
#define LIST_INCREMENT 64
/* Get some initial space. */
- array_size = 10;
+ array_size = 64;
if ((ret = __os_malloc(dbenv,
- sizeof(char *) * array_size, NULL, &array)) != 0)
+ sizeof(char *) * array_size, &array)) != 0)
return (ret);
array[0] = NULL;
@@ -143,27 +167,27 @@ log_archive(dbenv, listp, flags, db_malloc)
if (__os_exists(name, NULL) != 0) {
if (LF_ISSET(DB_ARCH_LOG) && fnum == stable_lsn.file)
continue;
- __os_freestr(name);
+ __os_free(dbenv, name);
name = NULL;
break;
}
- if (n >= array_size - 1) {
+ if (n >= array_size - 2) {
array_size += LIST_INCREMENT;
if ((ret = __os_realloc(dbenv,
- sizeof(char *) * array_size, NULL, &array)) != 0)
+ sizeof(char *) * array_size, &array)) != 0)
goto err;
}
- if (LF_ISSET(DB_ARCH_ABS)) {
+ if (db_arch_abs) {
if ((ret = __absname(dbenv,
pref, name, &array[n])) != 0)
goto err;
- __os_freestr(name);
+ __os_free(dbenv, name);
} else if ((p = __db_rpath(name)) != NULL) {
if ((ret = __os_strdup(dbenv, p + 1, &array[n])) != 0)
goto err;
- __os_freestr(name);
+ __os_free(dbenv, name);
} else
array[n] = name;
@@ -182,7 +206,7 @@ log_archive(dbenv, listp, flags, db_malloc)
qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
/* Rework the memory. */
- if ((ret = __usermem(dbenv, &array, db_malloc)) != 0)
+ if ((ret = __usermem(dbenv, &array)) != 0)
goto err;
*listp = array;
@@ -190,11 +214,11 @@ log_archive(dbenv, listp, flags, db_malloc)
err: if (array != NULL) {
for (arrayp = array; *arrayp != NULL; ++arrayp)
- __os_freestr(*arrayp);
- __os_free(array, sizeof(char *) * array_size);
+ __os_free(dbenv, *arrayp);
+ __os_free(dbenv, array);
}
if (name != NULL)
- __os_freestr(name);
+ __os_free(dbenv, name);
return (ret);
}
@@ -203,73 +227,89 @@ err: if (array != NULL) {
* Build a list of datafiles for return.
*/
static int
-__build_data(dbenv, pref, listp, db_malloc)
+__build_data(dbenv, pref, listp)
DB_ENV *dbenv;
char *pref, ***listp;
- void *(*db_malloc) __P((size_t));
{
DBT rec;
+ DB_LOGC *logc;
DB_LSN lsn;
- __log_register_args *argp;
+ __dbreg_register_args *argp;
u_int32_t rectype;
- int array_size, last, n, nxt, ret;
- char **array, **arrayp, *p, *real_name;
+ int array_size, last, n, nxt, ret, t_ret;
+ char **array, **arrayp, **list, **lp, *p, *real_name;
/* Get some initial space. */
- array_size = 10;
+ array_size = 64;
if ((ret = __os_malloc(dbenv,
- sizeof(char *) * array_size, NULL, &array)) != 0)
+ sizeof(char *) * array_size, &array)) != 0)
return (ret);
array[0] = NULL;
memset(&rec, 0, sizeof(rec));
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- F_SET(&rec, DB_DBT_MALLOC);
- for (n = 0, ret = log_get(dbenv, &lsn, &rec, DB_FIRST);
- ret == 0; ret = log_get(dbenv, &lsn, &rec, DB_NEXT)) {
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ for (n = 0; (ret = logc->get(logc, &lsn, &rec, DB_PREV)) == 0;) {
if (rec.size < sizeof(rectype)) {
ret = EINVAL;
- __db_err(dbenv, "log_archive: bad log record");
- goto lg_free;
+ __db_err(dbenv, "DB_ENV->log_archive: bad log record");
+ goto free_continue;
}
memcpy(&rectype, rec.data, sizeof(rectype));
- if (rectype != DB_log_register) {
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- __os_free(rec.data, rec.size);
- rec.data = NULL;
- }
+ if (rectype != DB___dbreg_register)
continue;
- }
- if ((ret = __log_register_read(dbenv, rec.data, &argp)) != 0) {
+ if ((ret =
+ __dbreg_register_read(dbenv, rec.data, &argp)) != 0) {
ret = EINVAL;
__db_err(dbenv,
- "log_archive: unable to read log record");
- goto lg_free;
+ "DB_ENV->log_archive: unable to read log record");
+ goto free_continue;
}
- if (n >= array_size - 1) {
+ if (n >= array_size - 2) {
array_size += LIST_INCREMENT;
if ((ret = __os_realloc(dbenv,
- sizeof(char *) * array_size, NULL, &array)) != 0)
- goto lg_free;
+ sizeof(char *) * array_size, &array)) != 0)
+ goto free_continue;
}
if ((ret = __os_strdup(dbenv,
- argp->name.data, &array[n])) != 0) {
-lg_free: if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
- __os_free(rec.data, rec.size);
- goto err1;
- }
-
- array[++n] = NULL;
- __os_free(argp, 0);
-
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- __os_free(rec.data, rec.size);
- rec.data = NULL;
+ argp->name.data, &array[n++])) != 0)
+ goto free_continue;
+ array[n] = NULL;
+
+ if (argp->ftype == DB_QUEUE) {
+ if ((ret = __qam_extent_names(dbenv,
+ argp->name.data, &list)) != 0)
+ goto q_err;
+ for (lp = list;
+ lp != NULL && *lp != NULL; lp++) {
+ if (n >= array_size - 2) {
+ array_size += LIST_INCREMENT;
+ if ((ret = __os_realloc(dbenv,
+ sizeof(char *) *
+ array_size, &array)) != 0)
+ goto q_err;
+ }
+ if ((ret =
+ __os_strdup(dbenv, *lp, &array[n++])) != 0)
+ goto q_err;
+ array[n] = NULL;
+ }
+q_err: if (list != NULL)
+ __os_free(dbenv, list);
}
+free_continue: __os_free(dbenv, argp);
+ if (ret != 0)
+ break;
}
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (ret != 0)
+ goto err1;
/* If there's nothing to return, we're done. */
if (n == 0) {
@@ -297,34 +337,34 @@ lg_free: if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
}
for (++nxt; nxt < n &&
strcmp(array[last], array[nxt]) == 0; ++nxt) {
- __os_freestr(array[nxt]);
+ __os_free(dbenv, array[nxt]);
array[nxt] = NULL;
}
/* Get the real name. */
if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, array[last], 0, NULL, &real_name)) != 0)
+ DB_APP_DATA, array[last], 0, NULL, &real_name)) != 0)
goto err2;
/* If the file doesn't exist, ignore it. */
if (__os_exists(real_name, NULL) != 0) {
- __os_freestr(real_name);
- __os_freestr(array[last]);
+ __os_free(dbenv, real_name);
+ __os_free(dbenv, array[last]);
array[last] = NULL;
continue;
}
/* Rework the name as requested by the user. */
- __os_freestr(array[last]);
+ __os_free(dbenv, array[last]);
array[last] = NULL;
if (pref != NULL) {
ret = __absname(dbenv, pref, real_name, &array[last]);
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
if (ret != 0)
goto err2;
} else if ((p = __db_rpath(real_name)) != NULL) {
ret = __os_strdup(dbenv, p + 1, &array[last]);
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
if (ret != 0)
goto err2;
} else
@@ -336,7 +376,7 @@ lg_free: if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
array[last] = NULL;
/* Rework the memory. */
- if ((ret = __usermem(dbenv, &array, db_malloc)) != 0)
+ if ((ret = __usermem(dbenv, &array)) != 0)
goto err1;
*listp = array;
@@ -349,13 +389,13 @@ err2: /*
*/
if (array != NULL)
for (; nxt < n; ++nxt)
- __os_freestr(array[nxt]);
+ __os_free(dbenv, array[nxt]);
/* FALLTHROUGH */
err1: if (array != NULL) {
for (arrayp = array; *arrayp != NULL; ++arrayp)
- __os_freestr(*arrayp);
- __os_free(array, array_size * sizeof(char *));
+ __os_free(dbenv, *arrayp);
+ __os_free(dbenv, array);
}
return (ret);
}
@@ -379,7 +419,7 @@ __absname(dbenv, pref, name, newnamep)
/* Malloc space for concatenating the two. */
if ((ret = __os_malloc(dbenv,
- l_pref + l_name + 2, NULL, &newname)) != 0)
+ l_pref + l_name + 2, &newname)) != 0)
return (ret);
*newnamep = newname;
@@ -400,10 +440,9 @@ __absname(dbenv, pref, name, newnamep)
* If the user has their own malloc routine, use it.
*/
static int
-__usermem(dbenv, listp, db_malloc)
+__usermem(dbenv, listp)
DB_ENV *dbenv;
char ***listp;
- void *(*db_malloc) __P((size_t));
{
size_t len;
int ret;
@@ -415,7 +454,7 @@ __usermem(dbenv, listp, db_malloc)
len += sizeof(char *);
/* Allocate it and set up the pointers. */
- if ((ret = __os_malloc(dbenv, len, db_malloc, &array)) != 0)
+ if ((ret = __os_umalloc(dbenv, len, &array)) != 0)
return (ret);
strp = (char *)(array + (orig - *listp) + 1);
@@ -427,13 +466,13 @@ __usermem(dbenv, listp, db_malloc)
*arrayp = strp;
strp += len + 1;
- __os_freestr(*orig);
+ __os_free(dbenv, *orig);
}
/* NULL-terminate the list. */
*arrayp = NULL;
- __os_free(*listp, 0);
+ __os_free(dbenv, *listp);
*listp = array;
return (0);
diff --git a/bdb/log/log_compare.c b/bdb/log/log_compare.c
index 9bc3c028a5f..115f9c21b76 100644
--- a/bdb/log/log_compare.c
+++ b/bdb/log/log_compare.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: log_compare.c,v 11.3 2000/02/14 02:59:59 bostic Exp $";
+static const char revid[] = "$Id: log_compare.c,v 11.6 2002/01/11 15:52:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,6 +19,8 @@ static const char revid[] = "$Id: log_compare.c,v 11.3 2000/02/14 02:59:59 bosti
/*
* log_compare --
* Compare two LSN's; return 1, 0, -1 if first is >, == or < second.
+ *
+ * EXTERN: int log_compare __P((const DB_LSN *, const DB_LSN *));
*/
int
log_compare(lsn0, lsn1)
diff --git a/bdb/log/log_findckp.c b/bdb/log/log_findckp.c
deleted file mode 100644
index b1e8fddbdb7..00000000000
--- a/bdb/log/log_findckp.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: log_findckp.c,v 11.5 2000/11/30 00:58:40 ubell Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <string.h>
-#endif
-
-#include "db_int.h"
-#include "log.h"
-#include "txn.h"
-
-/*
- * __log_findckp --
- *
- * Looks for the most recent checkpoint that occurs before the most recent
- * checkpoint LSN, subject to the constraint that there must be at least two
- * checkpoints. The reason you need two checkpoints is that you might have
- * crashed during the most recent one and may not have a copy of all the
- * open files. This is the point from which recovery can start and the
- * point up to which archival/truncation can take place. Checkpoints in
- * the log look like:
- *
- * -------------------------------------------------------------------
- * | ckp A, ckplsn 100 | .... record .... | ckp B, ckplsn 600 | ...
- * -------------------------------------------------------------------
- * LSN 500 LSN 1000
- *
- * If we read what log returns from using the DB_CKP parameter to logput,
- * we'll get the record at LSN 1000. The checkpoint LSN there is 600.
- * Now we have to scan backwards looking for a checkpoint before LSN 600.
- * We find one at 500. This means that we can truncate the log before
- * 500 or run recovery beginning at 500.
- *
- * Returns 0 if we find a suitable checkpoint or we retrieved the first
- * record in the log from which to start. Returns DB_NOTFOUND if there
- * are no log records, errno on error.
- *
- * PUBLIC: int __log_findckp __P((DB_ENV *, DB_LSN *));
- */
-int
-__log_findckp(dbenv, lsnp)
- DB_ENV *dbenv;
- DB_LSN *lsnp;
-{
- DBT data;
- DB_LSN ckp_lsn, final_ckp, last_ckp, next_lsn;
- __txn_ckp_args *ckp_args;
- int ret;
-
- /*
- * Need to find the appropriate point from which to begin
- * recovery.
- */
- memset(&data, 0, sizeof(data));
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- F_SET(&data, DB_DBT_MALLOC);
- ZERO_LSN(ckp_lsn);
- if ((ret = log_get(dbenv, &last_ckp, &data, DB_CHECKPOINT)) != 0) {
- if (ret == ENOENT)
- goto get_first;
- else
- return (ret);
- }
- final_ckp = last_ckp;
-
- next_lsn = last_ckp;
- do {
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- __os_free(data.data, data.size);
-
- if ((ret = log_get(dbenv, &next_lsn, &data, DB_SET)) != 0)
- return (ret);
- if ((ret = __txn_ckp_read(dbenv, data.data, &ckp_args)) != 0) {
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- __os_free(data.data, data.size);
- return (ret);
- }
- if (IS_ZERO_LSN(ckp_lsn))
- ckp_lsn = ckp_args->ckp_lsn;
- if (FLD_ISSET(dbenv->verbose, DB_VERB_CHKPOINT)) {
- __db_err(dbenv, "Checkpoint at: [%lu][%lu]",
- (u_long)last_ckp.file, (u_long)last_ckp.offset);
- __db_err(dbenv, "Checkpoint LSN: [%lu][%lu]",
- (u_long)ckp_args->ckp_lsn.file,
- (u_long)ckp_args->ckp_lsn.offset);
- __db_err(dbenv, "Previous checkpoint: [%lu][%lu]",
- (u_long)ckp_args->last_ckp.file,
- (u_long)ckp_args->last_ckp.offset);
- }
- last_ckp = next_lsn;
- next_lsn = ckp_args->last_ckp;
- __os_free(ckp_args, sizeof(*ckp_args));
-
- /*
- * Keep looping until either you 1) run out of checkpoints,
- * 2) you've found a checkpoint before the most recent
- * checkpoint's LSN and you have at least 2 checkpoints.
- */
- } while (!IS_ZERO_LSN(next_lsn) &&
- (log_compare(&last_ckp, &ckp_lsn) > 0 ||
- log_compare(&final_ckp, &last_ckp) == 0));
-
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- __os_free(data.data, data.size);
-
- /*
- * At this point, either, next_lsn is ZERO or ckp_lsn is the
- * checkpoint lsn and last_ckp is the LSN of the last checkpoint
- * before ckp_lsn. If the compare in the loop is still true, then
- * next_lsn must be 0 and we need to roll forward from the
- * beginning of the log.
- */
- if (log_compare(&last_ckp, &ckp_lsn) >= 0 ||
- log_compare(&final_ckp, &last_ckp) == 0) {
-get_first: if ((ret = log_get(dbenv, &last_ckp, &data, DB_FIRST)) != 0)
- return (ret);
- if (F_ISSET(dbenv, DB_ENV_THREAD))
- __os_free(data.data, data.size);
- }
- *lsnp = last_ckp;
-
- return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0);
-}
diff --git a/bdb/log/log_get.c b/bdb/log/log_get.c
index b75d50a62fd..c8b028da0fb 100644
--- a/bdb/log/log_get.c
+++ b/bdb/log/log_get.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: log_get.c,v 11.32 2001/01/11 18:19:53 bostic Exp $";
+static const char revid[] = "$Id: log_get.c,v 11.81 2002/08/14 20:09:27 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,81 +17,175 @@ static const char revid[] = "$Id: log_get.c,v 11.32 2001/01/11 18:19:53 bostic E
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_page.h"
-#include "log.h"
-#include "hash.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hmac.h"
+#include "dbinc/log.h"
+#include "dbinc/hash.h"
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+typedef enum { L_ALREADY, L_ACQUIRED, L_NONE } RLOCK;
+
+static int __log_c_close __P((DB_LOGC *, u_int32_t));
+static int __log_c_get __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
+static int __log_c_get_int __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
+static int __log_c_hdrchk __P((DB_LOGC *, HDR *, int *));
+static int __log_c_incursor __P((DB_LOGC *, DB_LSN *, HDR *, u_int8_t **));
+static int __log_c_inregion __P((DB_LOGC *,
+ DB_LSN *, RLOCK *, DB_LSN *, HDR *, u_int8_t **));
+static int __log_c_io __P((DB_LOGC *,
+ u_int32_t, u_int32_t, void *, size_t *, int *));
+static int __log_c_ondisk __P((DB_LOGC *,
+ DB_LSN *, DB_LSN *, int, HDR *, u_int8_t **, int *));
+static int __log_c_set_maxrec __P((DB_LOGC *, char *));
+static int __log_c_shortread __P((DB_LOGC *, int));
/*
- * log_get --
- * Get a log record.
+ * __log_cursor --
+ * Create a log cursor.
+ *
+ * PUBLIC: int __log_cursor __P((DB_ENV *, DB_LOGC **, u_int32_t));
*/
int
-log_get(dbenv, alsn, dbt, flags)
+__log_cursor(dbenv, logcp, flags)
+ DB_ENV *dbenv;
+ DB_LOGC **logcp;
+ u_int32_t flags;
+{
+ DB_LOGC *logc;
+ int ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_cursor", DB_INIT_LOG);
+
+ *logcp = NULL;
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "DB_ENV->log_cursor", flags, 0)) != 0)
+ return (ret);
+
+ /* Allocate memory for the cursor. */
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOGC), &logc)) != 0)
+ goto err;
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &logc->c_fh)) != 0)
+ goto err;
+
+ logc->bp_size = DB_LOGC_BUF_SIZE;
+ if ((ret = __os_malloc(dbenv, logc->bp_size, &logc->bp)) != 0)
+ goto err;
+
+ logc->dbenv = dbenv;
+ logc->close = __log_c_close;
+ logc->get = __log_c_get;
+
+ *logcp = logc;
+ return (0);
+
+err: if (logc != NULL) {
+ if (logc->c_fh != NULL)
+ __os_free(dbenv, logc->c_fh);
+ __os_free(dbenv, logc);
+ }
+
+ return (ret);
+}
+
+/*
+ * __log_c_close --
+ * Close a log cursor.
+ */
+static int
+__log_c_close(logc, flags)
+ DB_LOGC *logc;
+ u_int32_t flags;
+{
DB_ENV *dbenv;
+ int ret;
+
+ dbenv = logc->dbenv;
+
+ PANIC_CHECK(dbenv);
+ if ((ret = __db_fchk(dbenv, "DB_LOGC->close", flags, 0)) != 0)
+ return (ret);
+
+ if (F_ISSET(logc->c_fh, DB_FH_VALID))
+ (void)__os_closehandle(dbenv, logc->c_fh);
+
+ if (logc->c_dbt.data != NULL)
+ __os_free(dbenv, logc->c_dbt.data);
+
+ __os_free(dbenv, logc->bp);
+ __os_free(dbenv, logc->c_fh);
+ __os_free(dbenv, logc);
+
+ return (0);
+}
+
+/*
+ * __log_c_get --
+ * Get a log record.
+ */
+static int
+__log_c_get(logc, alsn, dbt, flags)
+ DB_LOGC *logc;
DB_LSN *alsn;
DBT *dbt;
u_int32_t flags;
{
- DB_LOG *dblp;
+ DB_ENV *dbenv;
DB_LSN saved_lsn;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_get(dbenv, alsn, dbt, flags));
-#endif
+ dbenv = logc->dbenv;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
/* Validate arguments. */
- if (flags != DB_CHECKPOINT && flags != DB_CURRENT &&
- flags != DB_FIRST && flags != DB_LAST &&
- flags != DB_NEXT && flags != DB_PREV && flags != DB_SET)
- return (__db_ferr(dbenv, "log_get", 1));
-
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if (flags == DB_NEXT || flags == DB_PREV || flags == DB_CURRENT)
- return (__db_ferr(dbenv, "log_get", 1));
- if (!F_ISSET(dbt,
- DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM))
- return (__db_ferr(dbenv, "threaded data", 1));
+ switch (flags) {
+ case DB_CURRENT:
+ case DB_FIRST:
+ case DB_LAST:
+ case DB_NEXT:
+ case DB_PREV:
+ break;
+ case DB_SET:
+ if (IS_ZERO_LSN(*alsn)) {
+ __db_err(dbenv, "DB_LOGC->get: invalid LSN");
+ return (EINVAL);
+ }
+ break;
+ default:
+ return (__db_ferr(dbenv, "DB_LOGC->get", 1));
}
- dblp = dbenv->lg_handle;
- R_LOCK(dbenv, &dblp->reginfo);
-
/*
- * The alsn field is only initialized if DB_SET is the flag, so this
- * assignment causes uninitialized memory complaints for other flag
- * values.
+ * On error, we take care not to overwrite the caller's LSN. This
+ * is because callers looking for the end of the log loop using the
+ * DB_NEXT flag, and expect to take the last successful lsn out of
+ * the passed-in structure after DB_LOGC->get fails with DB_NOTFOUND.
+ *
+ * !!!
+ * This line is often flagged an uninitialized memory read during a
+ * Purify or similar tool run, as the application didn't initialize
+ * *alsn. If the application isn't setting the DB_SET flag, there is
+ * no reason it should have initialized *alsn, but we can't know that
+ * and we want to make sure we never overwrite whatever the application
+ * put in there.
*/
-#ifdef UMRW
- if (flags == DB_SET)
- saved_lsn = *alsn;
- else
- ZERO_LSN(saved_lsn);
-#else
saved_lsn = *alsn;
-#endif
/*
- * If we get one of the log's header records, repeat the operation.
- * This assumes that applications don't ever request the log header
- * records by LSN, but that seems reasonable to me.
+ * If we get one of the log's header records as a result of doing a
+ * DB_FIRST, DB_NEXT, DB_LAST or DB_PREV, repeat the operation, log
+ * file header records aren't useful to applications.
*/
- if ((ret = __log_get(dblp,
- alsn, dbt, flags, 0)) == 0 && alsn->offset == 0) {
+ if ((ret = __log_c_get_int(logc, alsn, dbt, flags)) != 0) {
+ *alsn = saved_lsn;
+ return (ret);
+ }
+ if (alsn->offset == 0 && (flags == DB_FIRST ||
+ flags == DB_NEXT || flags == DB_LAST || flags == DB_PREV)) {
switch (flags) {
case DB_FIRST:
flags = DB_NEXT;
@@ -101,92 +195,100 @@ log_get(dbenv, alsn, dbt, flags)
break;
}
if (F_ISSET(dbt, DB_DBT_MALLOC)) {
- __os_free(dbt->data, dbt->size);
+ __os_free(dbenv, dbt->data);
dbt->data = NULL;
}
- ret = __log_get(dblp, alsn, dbt, flags, 0);
+ if ((ret = __log_c_get_int(logc, alsn, dbt, flags)) != 0) {
+ *alsn = saved_lsn;
+ return (ret);
+ }
}
- if (ret != 0)
- *alsn = saved_lsn;
- R_UNLOCK(dbenv, &dblp->reginfo);
-
- return (ret);
+ return (0);
}
/*
- * __log_get --
+ * __log_c_get_int --
* Get a log record; internal version.
- *
- * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
*/
-int
-__log_get(dblp, alsn, dbt, flags, silent)
- DB_LOG *dblp;
+static int
+__log_c_get_int(logc, alsn, dbt, flags)
+ DB_LOGC *logc;
DB_LSN *alsn;
DBT *dbt;
u_int32_t flags;
- int silent;
{
+ DB_CIPHER *db_cipher;
DB_ENV *dbenv;
- DB_LSN nlsn;
+ DB_LOG *dblp;
+ DB_LSN last_lsn, nlsn;
HDR hdr;
LOG *lp;
- const char *fail;
- char *np, *tbuf;
- int cnt, ret;
+ RLOCK rlock;
logfile_validity status;
- size_t len, nr;
- u_int32_t offset;
- u_int8_t *p;
- void *shortp, *readp;
+ u_int32_t cnt;
+ u_int8_t *rp;
+ int eof, is_hmac, ret;
+ dbenv = logc->dbenv;
+ dblp = dbenv->lg_handle;
lp = dblp->reginfo.primary;
- fail = np = tbuf = NULL;
- dbenv = dblp->dbenv;
+ is_hmac = 0;
- nlsn = dblp->c_lsn;
+ /*
+ * We don't acquire the log region lock until we need it, and we
+ * release it as soon as we're done.
+ */
+ rlock = F_ISSET(logc, DB_LOG_LOCKED) ? L_ALREADY : L_NONE;
+
+ nlsn = logc->c_lsn;
switch (flags) {
- case DB_CHECKPOINT:
- nlsn = lp->chkpt_lsn;
- if (IS_ZERO_LSN(nlsn)) {
- /* No db_err. The caller may expect this. */
- ret = ENOENT;
- goto err2;
- }
- break;
case DB_NEXT: /* Next log record. */
if (!IS_ZERO_LSN(nlsn)) {
/* Increment the cursor by the cursor record size. */
- nlsn.offset += dblp->c_len;
+ nlsn.offset += logc->c_len;
break;
}
+ flags = DB_FIRST;
/* FALLTHROUGH */
- case DB_FIRST: /* Find the first log record. */
+ case DB_FIRST: /* First log record. */
/* Find the first log file. */
if ((ret = __log_find(dblp, 1, &cnt, &status)) != 0)
- goto err2;
+ goto err;
/*
- * We want any readable version, so either DB_LV_NORMAL
- * or DB_LV_OLD_READABLE is acceptable here. If it's
- * not one of those two, there is no first log record that
- * we can read.
+ * DB_LV_INCOMPLETE:
+ * Theoretically, the log file we want could be created
+ * but not yet written, the "first" log record must be
+ * in the log buffer.
+ * DB_LV_NORMAL:
+ * DB_LV_OLD_READABLE:
+ * We found a log file we can read.
+ * DB_LV_NONEXISTENT:
+ * No log files exist, the "first" log record must be in
+ * the log buffer.
+ * DB_LV_OLD_UNREADABLE:
+ * No readable log files exist, we're at the cross-over
+ * point between two versions. The "first" log record
+ * must be in the log buffer.
*/
- if (status != DB_LV_NORMAL && status != DB_LV_OLD_READABLE) {
- ret = DB_NOTFOUND;
- goto err2;
+ switch (status) {
+ case DB_LV_INCOMPLETE:
+ DB_ASSERT(lp->lsn.file == cnt);
+ /* FALLTHROUGH */
+ case DB_LV_NORMAL:
+ case DB_LV_OLD_READABLE:
+ nlsn.file = cnt;
+ break;
+ case DB_LV_NONEXISTENT:
+ nlsn.file = 1;
+ DB_ASSERT(lp->lsn.file == nlsn.file);
+ break;
+ case DB_LV_OLD_UNREADABLE:
+ nlsn.file = cnt + 1;
+ DB_ASSERT(lp->lsn.file == nlsn.file);
+ break;
}
-
- /*
- * We may have only entered records in the buffer, and not
- * yet written a log file. If no log files were found and
- * there's anything in the buffer, it belongs to file 1.
- */
- if (cnt == 0)
- cnt = 1;
-
- nlsn.file = cnt;
nlsn.offset = 0;
break;
case DB_CURRENT: /* Current log record. */
@@ -197,21 +299,28 @@ __log_get(dblp, alsn, dbt, flags, silent)
if (nlsn.offset == 0) {
if (nlsn.file == 1 ||
__log_valid(dblp,
- nlsn.file - 1, 0, &status) != 0)
- return (DB_NOTFOUND);
+ nlsn.file - 1, 0, &status) != 0) {
+ ret = DB_NOTFOUND;
+ goto err;
+ }
if (status != DB_LV_NORMAL &&
- status != DB_LV_OLD_READABLE)
- return (DB_NOTFOUND);
+ status != DB_LV_OLD_READABLE) {
+ ret = DB_NOTFOUND;
+ goto err;
+ }
--nlsn.file;
- nlsn.offset = dblp->c_off;
- } else
- nlsn.offset = dblp->c_off;
+ }
+ nlsn.offset = logc->c_prev;
break;
}
/* FALLTHROUGH */
case DB_LAST: /* Last log record. */
+ if (rlock == L_NONE) {
+ rlock = L_ACQUIRED;
+ R_LOCK(dbenv, &dblp->reginfo);
+ }
nlsn.file = lp->lsn.file;
nlsn.offset = lp->lsn.offset - lp->len;
break;
@@ -225,241 +334,725 @@ next_file: ++nlsn.file;
nlsn.offset = 0;
}
- /* Return 1 if the request is past the end of the log. */
- if (nlsn.file > lp->lsn.file ||
- (nlsn.file == lp->lsn.file && nlsn.offset >= lp->lsn.offset))
- return (DB_NOTFOUND);
+ /*
+ * The above switch statement should have set nlsn to the lsn of
+ * the requested record.
+ */
- /* If we've switched files, discard the current file handle. */
- if (dblp->c_lsn.file != nlsn.file &&
- F_ISSET(&dblp->c_fh, DB_FH_VALID)) {
- (void)__os_closehandle(&dblp->c_fh);
+ if (CRYPTO_ON(dbenv)) {
+ hdr.size = HDR_CRYPTO_SZ;
+ is_hmac = 1;
+ } else {
+ hdr.size = HDR_NORMAL_SZ;
+ is_hmac = 0;
}
-
- /* If the entire record is in the in-memory buffer, copy it out. */
- if (nlsn.file == lp->lsn.file && nlsn.offset >= lp->w_off) {
- /* Copy the header. */
- p = dblp->bufp + (nlsn.offset - lp->w_off);
- memcpy(&hdr, p, sizeof(HDR));
-
- /* Copy the record. */
- len = hdr.len - sizeof(HDR);
- if ((ret = __db_retcopy(NULL, dbt, p + sizeof(HDR),
- len, &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
- goto err2;
+ /* Check to see if the record is in the cursor's buffer. */
+ if ((ret = __log_c_incursor(logc, &nlsn, &hdr, &rp)) != 0)
+ goto err;
+ if (rp != NULL)
goto cksum;
- }
- shortp = NULL;
+ /*
+ * Look to see if we're moving backward in the log with the last record
+ * coming from the disk -- it means the record can't be in the region's
+ * buffer. Else, check the region's buffer.
+ *
+ * If the record isn't in the region's buffer, we're going to have to
+ * read the record from disk. We want to make a point of not reading
+ * past the end of the logical log (after recovery, there may be data
+ * after the end of the logical log, not to mention the log file may
+ * have been pre-allocated). So, zero out last_lsn, and initialize it
+ * inside __log_c_inregion -- if it's still zero when we check it in
+ * __log_c_ondisk, that's OK, it just means the logical end of the log
+ * isn't an issue for this request.
+ */
+ ZERO_LSN(last_lsn);
+ if (!F_ISSET(logc, DB_LOG_DISK) ||
+ log_compare(&nlsn, &logc->c_lsn) > 0) {
+ F_CLR(logc, DB_LOG_DISK);
- /* Acquire a file descriptor. */
- if (!F_ISSET(&dblp->c_fh, DB_FH_VALID)) {
- if ((ret = __log_name(dblp, nlsn.file,
- &np, &dblp->c_fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
- fail = np;
- goto err1;
- }
- __os_freestr(np);
- np = NULL;
+ if ((ret = __log_c_inregion(logc,
+ &nlsn, &rlock, &last_lsn, &hdr, &rp)) != 0)
+ goto err;
+ if (rp != NULL)
+ goto cksum;
}
- /* See if we've already read this */
- if (nlsn.file == dblp->r_file && nlsn.offset > dblp->r_off
- && nlsn.offset + sizeof(HDR) < dblp->r_off + dblp->r_size)
- goto got_header;
-
/*
- * Seek to the header offset and read the header. Because the file
- * may be pre-allocated, we have to make sure that we're not reading
- * past the information in the start of the in-memory buffer.
+ * We have to read from an on-disk file to retrieve the record.
+ * If we ever can't retrieve the record at offset 0, we're done,
+ * return EOF/DB_NOTFOUND.
+ *
+ * Discard the region lock if we're still holding it, the on-disk
+ * reading routines don't need it.
*/
-
- readp = &hdr;
- offset = nlsn.offset;
- if (nlsn.file == lp->lsn.file && offset + sizeof(HDR) > lp->w_off)
- nr = lp->w_off - offset;
- else if (dblp->readbufp == NULL)
- nr = sizeof(HDR);
- else {
- nr = lp->buffer_size;
- readp = dblp->readbufp;
- dblp->r_file = nlsn.file;
- /* Going backwards. Put the current in the middle. */
- if (flags == DB_PREV || flags == DB_LAST) {
- if (offset <= lp->buffer_size/2)
- offset = 0;
- else
- offset = offset - lp->buffer_size/2;
- }
- if (nlsn.file == lp->lsn.file && offset + nr > lp->lsn.offset)
- nr = lp->lsn.offset - offset;
- dblp->r_off = offset;
+ if (rlock == L_ACQUIRED) {
+ rlock = L_NONE;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ }
+ if ((ret = __log_c_ondisk(
+ logc, &nlsn, &last_lsn, flags, &hdr, &rp, &eof)) != 0)
+ goto err;
+ if (eof == 1) {
+ /*
+ * Only DB_NEXT automatically moves to the next file, and
+ * it only happens once.
+ */
+ if (flags != DB_NEXT || nlsn.offset == 0)
+ return (DB_NOTFOUND);
+ goto next_file;
}
+ F_SET(logc, DB_LOG_DISK);
- if ((ret = __os_seek(dblp->dbenv,
- &dblp->c_fh, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {
- fail = "seek";
- goto err1;
+cksum: /*
+ * Discard the region lock if we're still holding it. (The path to
+ * get here is that we acquired the lock because of the caller's
+ * flag argument, but we found the record in the cursor's buffer.
+ * Improbable, but it's easy to avoid.
+ */
+ if (rlock == L_ACQUIRED) {
+ rlock = L_NONE;
+ R_UNLOCK(dbenv, &dblp->reginfo);
}
- if ((ret = __os_read(dblp->dbenv, &dblp->c_fh, readp, nr, &nr)) != 0) {
- fail = "read";
- goto err1;
+
+ /*
+ * Checksum: there are two types of errors -- a configuration error
+ * or a checksum mismatch. The former is always bad. The latter is
+ * OK if we're searching for the end of the log, and very, very bad
+ * if we're reading random log records.
+ */
+ db_cipher = dbenv->crypto_handle;
+ if ((ret = __db_check_chksum(dbenv, db_cipher,
+ hdr.chksum, rp + hdr.size, hdr.len - hdr.size, is_hmac)) != 0) {
+ if (F_ISSET(logc, DB_LOG_SILENT_ERR)) {
+ if (ret == 0 || ret == -1)
+ ret = EIO;
+ } else if (ret == -1) {
+ __db_err(dbenv,
+ "DB_LOGC->get: log record checksum mismatch");
+ __db_err(dbenv,
+ "DB_LOGC->get: catastrophic recovery may be required");
+ ret = __db_panic(dbenv, DB_RUNRECOVERY);
+ }
+ goto err;
}
- if (nr < sizeof(HDR)) {
- /* If read returns EOF, try the next file. */
- if (nr == 0) {
- if (flags != DB_NEXT || nlsn.file == lp->lsn.file)
- goto corrupt;
+
+ /*
+ * If we got a 0-length record, that means we're in the midst of
+ * some bytes that got 0'd as the result of a vtruncate. We're
+ * going to have to retry.
+ */
+ if (hdr.len == 0) {
+ switch (flags) {
+ case DB_FIRST:
+ case DB_NEXT:
+ /* Zero'd records always indicate the end of a file. */
goto next_file;
+
+ case DB_LAST:
+ case DB_PREV:
+ /*
+ * We should never get here. If we recover a log
+ * file with 0's at the end, we'll treat the 0'd
+ * headers as the end of log and ignore them. If
+ * we're reading backwards from another file, then
+ * the first record in that new file should have its
+ * prev field set correctly.
+ */
+ __db_err(dbenv,
+ "Encountered zero length records while traversing backwards");
+ DB_ASSERT(0);
+ case DB_SET:
+ default:
+ /* Return the 0-length record. */
+ break;
}
+ }
- if (dblp->readbufp != NULL)
- memcpy((u_int8_t *) &hdr, readp, nr);
+ /* Copy the record into the user's DBT. */
+ if ((ret = __db_retcopy(dbenv, dbt, rp + hdr.size,
+ (u_int32_t)(hdr.len - hdr.size),
+ &logc->c_dbt.data, &logc->c_dbt.ulen)) != 0)
+ goto err;
+ if (CRYPTO_ON(dbenv)) {
+ if ((ret = db_cipher->decrypt(dbenv, db_cipher->data,
+ hdr.iv, dbt->data, hdr.len - hdr.size)) != 0) {
+ ret = EAGAIN;
+ goto err;
+ }
/*
- * If read returns a short count the rest of the record has
- * to be in the in-memory buffer.
+ * Return the original log record size to the user,
+ * even though we've allocated more than that, possibly.
+ * The log record is decrypted in the user dbt, not in
+ * the buffer, so we must do this here after decryption,
+ * not adjust the len passed to the __db_retcopy call.
*/
- if (lp->b_off < sizeof(HDR) - nr)
- goto corrupt;
+ dbt->size = hdr.orig_size;
+ }
- /* Get the rest of the header from the in-memory buffer. */
- memcpy((u_int8_t *)&hdr + nr, dblp->bufp, sizeof(HDR) - nr);
+ /* Update the cursor and the returned LSN. */
+ *alsn = nlsn;
+ logc->c_lsn = nlsn;
+ logc->c_len = hdr.len;
+ logc->c_prev = hdr.prev;
- if (hdr.len == 0)
- goto next_file;
+err: if (rlock == L_ACQUIRED)
+ R_UNLOCK(dbenv, &dblp->reginfo);
- shortp = dblp->bufp + (sizeof(HDR) - nr);
- }
+ return (ret);
+}
- else if (dblp->readbufp != NULL) {
- dblp->r_size = nr;
-got_header: memcpy((u_int8_t *)&hdr,
- dblp->readbufp + (nlsn.offset - dblp->r_off), sizeof(HDR));
- }
+/*
+ * __log_c_incursor --
+ * Check to see if the requested record is in the cursor's buffer.
+ */
+static int
+__log_c_incursor(logc, lsn, hdr, pp)
+ DB_LOGC *logc;
+ DB_LSN *lsn;
+ HDR *hdr;
+ u_int8_t **pp;
+{
+ u_int8_t *p;
+
+ *pp = NULL;
/*
- * Check for buffers of 0's, that's what we usually see during recovery,
- * although it's certainly not something on which we can depend. Check
- * for impossibly large records. The malloc should fail later, but we
- * have customers that run mallocs that handle allocation failure as a
- * fatal error.
+ * Test to see if the requested LSN could be part of the cursor's
+ * buffer.
+ *
+ * The record must be part of the same file as the cursor's buffer.
+ * The record must start at a byte offset equal to or greater than
+ * the cursor buffer.
+ * The record must not start at a byte offset after the cursor
+ * buffer's end.
*/
- if (hdr.len == 0)
- goto next_file;
- if (hdr.len <= sizeof(HDR) || hdr.len > lp->persist.lg_max)
- goto corrupt;
- len = hdr.len - sizeof(HDR);
-
- /* If we've already moved to the in-memory buffer, fill from there. */
- if (shortp != NULL) {
- if (lp->b_off < ((u_int8_t *)shortp - dblp->bufp) + len)
- goto corrupt;
- if ((ret = __db_retcopy(NULL, dbt, shortp, len,
- &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
- goto err2;
- goto cksum;
- }
+ if (logc->bp_lsn.file != lsn->file)
+ return (0);
+ if (logc->bp_lsn.offset > lsn->offset)
+ return (0);
+ if (logc->bp_lsn.offset + logc->bp_rlen <= lsn->offset + hdr->size)
+ return (0);
- if (dblp->readbufp != NULL) {
- if (nlsn.offset + hdr.len < dblp->r_off + dblp->r_size) {
- if ((ret = __db_retcopy(NULL, dbt, dblp->readbufp +
- (nlsn.offset - dblp->r_off) + sizeof(HDR),
- len, &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
- goto err2;
- goto cksum;
- } else if ((ret = __os_seek(dblp->dbenv, &dblp->c_fh, 0,
- 0, nlsn.offset + sizeof(HDR), 0, DB_OS_SEEK_SET)) != 0) {
- fail = "seek";
- goto err1;
- }
+ /*
+ * Read the record's header and check if the record is entirely held
+ * in the buffer. If the record is not entirely held, get it again.
+ * (The only advantage in having part of the record locally is that
+ * we might avoid a system call because we already have the HDR in
+ * memory.)
+ *
+ * If the header check fails for any reason, it must be because the
+ * LSN is bogus. Fail hard.
+ */
+ p = logc->bp + (lsn->offset - logc->bp_lsn.offset);
+ memcpy(hdr, p, hdr->size);
+ if (__log_c_hdrchk(logc, hdr, NULL))
+ return (DB_NOTFOUND);
+ if (logc->bp_lsn.offset + logc->bp_rlen <= lsn->offset + hdr->len)
+ return (0);
+
+ *pp = p; /* Success. */
+
+ return (0);
+}
+
+/*
+ * __log_c_inregion --
+ * Check to see if the requested record is in the region's buffer.
+ */
+static int
+__log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
+ DB_LOGC *logc;
+ DB_LSN *lsn, *last_lsn;
+ RLOCK *rlockp;
+ HDR *hdr;
+ u_int8_t **pp;
+{
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ LOG *lp;
+ size_t len, nr;
+ u_int32_t b_disk, b_region;
+ int ret;
+ u_int8_t *p;
+
+ dbenv = logc->dbenv;
+ dblp = dbenv->lg_handle;
+ lp = ((DB_LOG *)logc->dbenv->lg_handle)->reginfo.primary;
+
+ ret = 0;
+ *pp = NULL;
+
+ /* If we haven't yet acquired the log region lock, do so. */
+ if (*rlockp == L_NONE) {
+ *rlockp = L_ACQUIRED;
+ R_LOCK(dbenv, &dblp->reginfo);
}
/*
- * Allocate temporary memory to hold the record.
+ * The routines to read from disk must avoid reading past the logical
+ * end of the log, so pass that information back to it.
*
- * XXX
- * We're calling malloc(3) with a region locked. This isn't
- * a good idea.
+ * Since they're reading directly from the disk, they must also avoid
+ * reading past the offset we've written out. If the log was
+ * truncated, it's possible that there are zeroes or garbage on
+ * disk after this offset, and the logical end of the log can
+ * come later than this point if the log buffer isn't empty.
*/
- if ((ret = __os_malloc(dbenv, len, NULL, &tbuf)) != 0)
- goto err1;
+ *last_lsn = lp->lsn;
+ if (last_lsn->offset > lp->w_off)
+ last_lsn->offset = lp->w_off;
/*
- * Read the record into the buffer. If read returns a short count,
- * there was an error or the rest of the record is in the in-memory
- * buffer. Note, the information may be garbage if we're in recovery,
- * so don't read past the end of the buffer's memory.
- *
- * Because the file may be pre-allocated, we have to make sure that
- * we're not reading past the information in the start of the in-memory
+ * Test to see if the requested LSN could be part of the region's
* buffer.
+ *
+ * During recovery, we read the log files getting the information to
+ * initialize the region. In that case, the region's lsn field will
+ * not yet have been filled in, use only the disk.
+ *
+ * The record must not start at a byte offset after the region buffer's
+ * end, since that means the request is for a record after the end of
+ * the log. Do this test even if the region's buffer is empty -- after
+ * recovery, the log files may continue past the declared end-of-log,
+ * and the disk reading routine will incorrectly attempt to read the
+ * remainder of the log.
+ *
+ * Otherwise, test to see if the region's buffer actually has what we
+ * want:
+ *
+ * The buffer must have some useful content.
+ * The record must be in the same file as the region's buffer and must
+ * start at a byte offset equal to or greater than the region's buffer.
+ */
+ if (IS_ZERO_LSN(lp->lsn))
+ return (0);
+ if (lsn->file > lp->lsn.file ||
+ (lsn->file == lp->lsn.file && lsn->offset >= lp->lsn.offset))
+ return (DB_NOTFOUND);
+ if (lp->b_off == 0)
+ return (0);
+ if (lsn->file < lp->f_lsn.file || lsn->offset < lp->f_lsn.offset)
+ return (0);
+
+ /*
+ * The current contents of the cursor's buffer will be useless for a
+ * future call -- trash it rather than try and make it look correct.
+ */
+ ZERO_LSN(logc->bp_lsn);
+
+ /*
+ * If the requested LSN is greater than the region buffer's first
+ * byte, we know the entire record is in the buffer.
+ *
+ * If the header check fails for any reason, it must be because the
+ * LSN is bogus. Fail hard.
*/
- if (nlsn.file == lp->lsn.file &&
- nlsn.offset + sizeof(HDR) + len > lp->w_off)
- nr = lp->w_off - (nlsn.offset + sizeof(HDR));
+ if (lsn->offset > lp->f_lsn.offset) {
+ p = dblp->bufp + (lsn->offset - lp->w_off);
+ memcpy(hdr, p, hdr->size);
+ if (__log_c_hdrchk(logc, hdr, NULL))
+ return (DB_NOTFOUND);
+ if (logc->bp_size <= hdr->len) {
+ len = ALIGN(hdr->len * 2, 128);
+ if ((ret =
+ __os_realloc(logc->dbenv, len, &logc->bp)) != 0)
+ return (ret);
+ logc->bp_size = (u_int32_t)len;
+ }
+ memcpy(logc->bp, p, hdr->len);
+ *pp = logc->bp;
+ return (0);
+ }
+
+ /*
+ * There's a partial record, that is, the requested record starts
+ * in a log file and finishes in the region buffer. We have to
+ * find out how many bytes of the record are in the region buffer
+ * so we can copy them out into the cursor buffer. First, check
+ * to see if the requested record is the only record in the region
+ * buffer, in which case we should copy the entire region buffer.
+ *
+ * Else, walk back through the region's buffer to find the first LSN
+ * after the record that crosses the buffer boundary -- we can detect
+ * that LSN, because its "prev" field will reference the record we
+ * want. The bytes we need to copy from the region buffer are the
+ * bytes up to the record we find. The bytes we'll need to allocate
+ * to hold the log record are the bytes between the two offsets.
+ */
+ b_disk = lp->w_off - lsn->offset;
+ if (lp->b_off <= lp->len)
+ b_region = (u_int32_t)lp->b_off;
else
- nr = len;
- if ((ret = __os_read(dblp->dbenv, &dblp->c_fh, tbuf, nr, &nr)) != 0) {
- fail = "read";
- goto err1;
+ for (p = dblp->bufp + (lp->b_off - lp->len);;) {
+ memcpy(hdr, p, hdr->size);
+ if (hdr->prev == lsn->offset) {
+ b_region = (u_int32_t)(p - dblp->bufp);
+ break;
+ }
+ p = dblp->bufp + (hdr->prev - lp->w_off);
+ }
+
+ /*
+ * If we don't have enough room for the record, we have to allocate
+ * space. We have to do it while holding the region lock, which is
+ * truly annoying, but there's no way around it. This call is why
+ * we allocate cursor buffer space when allocating the cursor instead
+ * of waiting.
+ */
+ if (logc->bp_size <= b_region + b_disk) {
+ len = ALIGN((b_region + b_disk) * 2, 128);
+ if ((ret = __os_realloc(logc->dbenv, len, &logc->bp)) != 0)
+ return (ret);
+ logc->bp_size = (u_int32_t)len;
}
- if (len - nr > lp->buffer_size)
- goto corrupt;
- if (nr != len) {
- if (lp->b_off < len - nr)
- goto corrupt;
-
- /* Get the rest of the record from the in-memory buffer. */
- memcpy((u_int8_t *)tbuf + nr, dblp->bufp, len - nr);
+
+ /* Copy the region's bytes to the end of the cursor's buffer. */
+ p = (logc->bp + logc->bp_size) - b_region;
+ memcpy(p, dblp->bufp, b_region);
+
+ /* Release the region lock. */
+ if (*rlockp == L_ACQUIRED) {
+ *rlockp = L_NONE;
+ R_UNLOCK(dbenv, &dblp->reginfo);
}
- /* Copy the record into the user's DBT. */
- if ((ret = __db_retcopy(NULL, dbt, tbuf, len,
- &dblp->c_dbt.data, &dblp->c_dbt.ulen)) != 0)
- goto err2;
- __os_free(tbuf, 0);
- tbuf = NULL;
+ /*
+ * Read the rest of the information from disk. Neither short reads
+ * or EOF are acceptable, the bytes we want had better be there.
+ */
+ if (b_disk != 0) {
+ p -= b_disk;
+ nr = b_disk;
+ if ((ret = __log_c_io(
+ logc, lsn->file, lsn->offset, p, &nr, NULL)) != 0)
+ return (ret);
+ if (nr < b_disk)
+ return (__log_c_shortread(logc, 0));
+ }
-cksum: /*
- * If the user specified a partial record read, the checksum can't
- * match. It's not an obvious thing to do, but a user testing for
- * the length of a record might do it.
+ /* Copy the header information into the caller's structure. */
+ memcpy(hdr, p, hdr->size);
+
+ *pp = p;
+ return (0);
+}
+
+/*
+ * __log_c_ondisk --
+ * Read a record off disk.
+ */
+static int
+__log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
+ DB_LOGC *logc;
+ DB_LSN *lsn, *last_lsn;
+ int flags, *eofp;
+ HDR *hdr;
+ u_int8_t **pp;
+{
+ DB_ENV *dbenv;
+ size_t len, nr;
+ u_int32_t offset;
+ int ret;
+
+ dbenv = logc->dbenv;
+ *eofp = 0;
+
+ nr = hdr->size;
+ if ((ret =
+ __log_c_io(logc, lsn->file, lsn->offset, hdr, &nr, eofp)) != 0)
+ return (ret);
+ if (*eofp)
+ return (0);
+
+ /* If we read 0 bytes, assume we've hit EOF. */
+ if (nr == 0) {
+ *eofp = 1;
+ return (0);
+ }
+
+ /* Check the HDR. */
+ if ((ret = __log_c_hdrchk(logc, hdr, eofp)) != 0)
+ return (ret);
+ if (*eofp)
+ return (0);
+
+ /* Otherwise, we should have gotten the bytes we wanted. */
+ if (nr < hdr->size)
+ return (__log_c_shortread(logc, 0));
+
+ /*
+ * Regardless of how we return, the previous contents of the cursor's
+ * buffer are useless -- trash it.
*/
- if (!F_ISSET(dbt, DB_DBT_PARTIAL) &&
- hdr.cksum != __ham_func4(NULL, dbt->data, dbt->size)) {
- if (!silent)
- __db_err(dbenv, "log_get: checksum mismatch");
- goto corrupt;
+ ZERO_LSN(logc->bp_lsn);
+
+ /*
+ * Otherwise, we now (finally!) know how big the record is. (Maybe
+ * we should have just stuck the length of the record into the LSN!?)
+ * Make sure we have enough space.
+ */
+ if (logc->bp_size <= hdr->len) {
+ len = ALIGN(hdr->len * 2, 128);
+ if ((ret = __os_realloc(dbenv, len, &logc->bp)) != 0)
+ return (ret);
+ logc->bp_size = (u_int32_t)len;
}
- /* Update the cursor and the return lsn. */
- dblp->c_off = hdr.prev;
- dblp->c_len = hdr.len;
- dblp->c_lsn = nlsn;
- *alsn = nlsn;
+ /*
+ * If we're moving forward in the log file, read this record in at the
+ * beginning of the buffer. Otherwise, read this record in at the end
+ * of the buffer, making sure we don't try and read before the start
+ * of the file. (We prefer positioning at the end because transaction
+ * aborts use DB_SET to move backward through the log and we might get
+ * lucky.)
+ *
+ * Read a buffer's worth, without reading past the logical EOF. The
+ * last_lsn may be a zero LSN, but that's OK, the test works anyway.
+ */
+ if (flags == DB_FIRST || flags == DB_NEXT)
+ offset = lsn->offset;
+ else if (lsn->offset + hdr->len < logc->bp_size)
+ offset = 0;
+ else
+ offset = (lsn->offset + hdr->len) - logc->bp_size;
+
+ nr = logc->bp_size;
+ if (lsn->file == last_lsn->file && offset + nr >= last_lsn->offset)
+ nr = last_lsn->offset - offset;
+
+ if ((ret =
+ __log_c_io(logc, lsn->file, offset, logc->bp, &nr, eofp)) != 0)
+ return (ret);
+
+ /*
+ * We should have at least gotten the bytes up-to-and-including the
+ * record we're reading.
+ */
+ if (nr < (lsn->offset + hdr->len) - offset)
+ return (__log_c_shortread(logc, 1));
+
+ /* Set up the return information. */
+ logc->bp_rlen = (u_int32_t)nr;
+ logc->bp_lsn.file = lsn->file;
+ logc->bp_lsn.offset = offset;
+ *pp = logc->bp + (lsn->offset - offset);
+
+ return (0);
+}
+
+/*
+ * __log_c_hdrchk --
+ *
+ * Check for corrupted HDRs before we use them to allocate memory or find
+ * records.
+ *
+ * If the log files were pre-allocated, a zero-filled HDR structure is the
+ * logical file end. However, we can see buffers filled with 0's during
+ * recovery, too (because multiple log buffers were written asynchronously,
+ * and one made it to disk before a different one that logically precedes
+ * it in the log file.
+ *
+ * XXX
+ * I think there's a potential pre-allocation recovery flaw here -- if we
+ * fail to write a buffer at the end of a log file (by scheduling its
+ * write asynchronously, and it never making it to disk), then succeed in
+ * writing a log file block to a subsequent log file, I don't think we will
+ * detect that the buffer of 0's should have marked the end of the log files
+ * during recovery. I think we may need to always write some garbage after
+ * each block write if we pre-allocate log files. (At the moment, we do not
+ * pre-allocate, so this isn't currently an issue.)
+ *
+ * Check for impossibly large records. The malloc should fail later, but we
+ * have customers that run mallocs that treat all allocation failures as fatal
+ * errors.
+ *
+ * Note that none of this is necessarily something awful happening. We let
+ * the application hand us any LSN they want, and it could be a pointer into
+ * the middle of a log record, there's no way to tell.
+ */
+static int
+__log_c_hdrchk(logc, hdr, eofp)
+ DB_LOGC *logc;
+ HDR *hdr;
+ int *eofp;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ dbenv = logc->dbenv;
+
+ /* Sanity check the log record's size. */
+ if (hdr->len <= hdr->size)
+ goto err;
+ /*
+ * If the cursor's max-record value isn't yet set, it means we aren't
+ * reading these records from a log file and no check is necessary.
+ */
+ if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec) {
+ /*
+ * If we fail the check, there's the pathological case that
+ * we're reading the last file, it's growing, and our initial
+ * check information was wrong. Get it again, to be sure.
+ */
+ if ((ret = __log_c_set_maxrec(logc, NULL)) != 0) {
+ __db_err(dbenv, "DB_LOGC->get: %s", db_strerror(ret));
+ return (ret);
+ }
+ if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec)
+ goto err;
+ }
+
+ if (eofp != NULL) {
+ if (hdr->prev == 0 && hdr->chksum[0] == 0 && hdr->len == 0) {
+ *eofp = 1;
+ return (0);
+ }
+ *eofp = 0;
+ }
return (0);
-corrupt:/*
- * This is the catchall -- for some reason we didn't find enough
- * information or it wasn't reasonable information, and it wasn't
- * because a system call failed.
+err: if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
+ __db_err(dbenv, "DB_LOGC->get: invalid log record header");
+ return (EIO);
+}
+
+/*
+ * __log_c_io --
+ * Read records from a log file.
+ */
+static int
+__log_c_io(logc, fnum, offset, p, nrp, eofp)
+ DB_LOGC *logc;
+ u_int32_t fnum, offset;
+ void *p;
+ size_t *nrp;
+ int *eofp;
+{
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ int ret;
+ char *np;
+
+ dbenv = logc->dbenv;
+ dblp = dbenv->lg_handle;
+
+ /*
+ * If we've switched files, discard the current file handle and acquire
+ * a new one.
*/
- ret = EIO;
- fail = "read";
+ if (F_ISSET(logc->c_fh, DB_FH_VALID) && logc->bp_lsn.file != fnum)
+ if ((ret = __os_closehandle(dbenv, logc->c_fh)) != 0)
+ return (ret);
+ if (!F_ISSET(logc->c_fh, DB_FH_VALID)) {
+ if ((ret = __log_name(dblp, fnum,
+ &np, logc->c_fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
+ /*
+ * If we're allowed to return EOF, assume that's the
+ * problem, set the EOF status flag and return 0.
+ */
+ if (eofp != NULL) {
+ *eofp = 1;
+ ret = 0;
+ } else if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
+ __db_err(dbenv, "DB_LOGC->get: %s: %s",
+ np, db_strerror(ret));
+ __os_free(dbenv, np);
+ return (ret);
+ }
-err1: if (!silent) {
- if (fail == NULL)
- __db_err(dbenv, "log_get: %s", db_strerror(ret));
- else
+ if ((ret = __log_c_set_maxrec(logc, np)) != 0) {
__db_err(dbenv,
- "log_get: %s: %s", fail, db_strerror(ret));
+ "DB_LOGC->get: %s: %s", np, db_strerror(ret));
+ __os_free(dbenv, np);
+ return (ret);
+ }
+ __os_free(dbenv, np);
}
-err2: if (np != NULL)
- __os_freestr(np);
- if (tbuf != NULL)
- __os_free(tbuf, 0);
- return (ret);
+ /* Seek to the record's offset. */
+ if ((ret = __os_seek(dbenv,
+ logc->c_fh, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {
+ if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
+ __db_err(dbenv,
+ "DB_LOGC->get: seek: %s", db_strerror(ret));
+ return (ret);
+ }
+
+ /* Read the data. */
+ if ((ret = __os_read(dbenv, logc->c_fh, p, *nrp, nrp)) != 0) {
+ if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
+ __db_err(dbenv,
+ "DB_LOGC->get: read: %s", db_strerror(ret));
+ return (ret);
+ }
+
+ return (0);
+}
+
+/*
+ * __log_c_shortread --
+ * Read was short -- return a consistent error message and error.
+ */
+static int
+__log_c_shortread(logc, silent)
+ DB_LOGC *logc;
+ int silent;
+{
+ if (!silent || !F_ISSET(logc, DB_LOG_SILENT_ERR))
+ __db_err(logc->dbenv, "DB_LOGC->get: short read");
+ return (EIO);
+}
+
+/*
+ * __log_c_set_maxrec --
+ * Bound the maximum log record size in a log file.
+ */
+static int
+__log_c_set_maxrec(logc, np)
+ DB_LOGC *logc;
+ char *np;
+{
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ LOG *lp;
+ u_int32_t mbytes, bytes;
+ int ret;
+
+ dbenv = logc->dbenv;
+ dblp = dbenv->lg_handle;
+
+ /*
+ * We don't want to try and allocate huge chunks of memory because
+ * applications with error-checking malloc's often consider that a
+ * hard failure. If we're about to look at a corrupted record with
+ * a bizarre size, we need to know before trying to allocate space
+ * to hold it. We could read the persistent data at the beginning
+ * of the file but that's hard -- we may have to decrypt it, checksum
+ * it and so on. Stat the file instead.
+ */
+ if ((ret =
+ __os_ioinfo(dbenv, np, logc->c_fh, &mbytes, &bytes, NULL)) != 0)
+ return (ret);
+
+ logc->bp_maxrec = mbytes * MEGABYTE + bytes;
+
+ /*
+ * If reading from the log file currently being written, we could get
+ * an incorrect size, that is, if the cursor was opened on the file
+ * when it had only a few hundred bytes, and then the cursor used to
+ * move forward in the file, after more log records were written, the
+ * original stat value would be wrong. Use the maximum of the current
+ * log file size and the size of the buffer -- that should represent
+ * the max of any log record currently in the file.
+ *
+ * The log buffer size is set when the environment is opened and never
+ * changed, we don't need a lock on it.
+ */
+ lp = dblp->reginfo.primary;
+ logc->bp_maxrec += lp->buffer_size;
+
+ return (0);
}
diff --git a/bdb/log/log_method.c b/bdb/log/log_method.c
index 883f485d891..42adaf11c6c 100644
--- a/bdb/log/log_method.c
+++ b/bdb/log/log_method.c
@@ -1,38 +1,39 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: log_method.c,v 11.14 2000/11/30 00:58:40 ubell Exp $";
+static const char revid[] = "$Id: log_method.c,v 11.32 2002/05/30 22:16:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "log.h"
+#include "dbinc/log.h"
#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
#endif
-static int __log_set_lg_max __P((DB_ENV *, u_int32_t));
static int __log_set_lg_bsize __P((DB_ENV *, u_int32_t));
static int __log_set_lg_dir __P((DB_ENV *, const char *));
+static int __log_set_lg_max __P((DB_ENV *, u_int32_t));
+static int __log_set_lg_regionmax __P((DB_ENV *, u_int32_t));
/*
* __log_dbenv_create --
@@ -44,13 +45,16 @@ void
__log_dbenv_create(dbenv)
DB_ENV *dbenv;
{
- dbenv->lg_bsize = LG_BSIZE_DEFAULT;
- dbenv->set_lg_bsize = __log_set_lg_bsize;
+ /*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ */
- dbenv->lg_max = LG_MAX_DEFAULT;
- dbenv->set_lg_max = __log_set_lg_max;
+ dbenv->lg_bsize = LG_BSIZE_DEFAULT;
+ dbenv->lg_regionmax = LG_BASE_REGION_SIZE;
- dbenv->set_lg_dir = __log_set_lg_dir;
#ifdef HAVE_RPC
/*
* If we have a client, overwrite what we just setup to
@@ -58,10 +62,29 @@ __log_dbenv_create(dbenv)
*/
if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
dbenv->set_lg_bsize = __dbcl_set_lg_bsize;
- dbenv->set_lg_max = __dbcl_set_lg_max;
dbenv->set_lg_dir = __dbcl_set_lg_dir;
- }
+ dbenv->set_lg_max = __dbcl_set_lg_max;
+ dbenv->set_lg_regionmax = __dbcl_set_lg_regionmax;
+ dbenv->log_archive = __dbcl_log_archive;
+ dbenv->log_cursor = __dbcl_log_cursor;
+ dbenv->log_file = __dbcl_log_file;
+ dbenv->log_flush = __dbcl_log_flush;
+ dbenv->log_put = __dbcl_log_put;
+ dbenv->log_stat = __dbcl_log_stat;
+ } else
#endif
+ {
+ dbenv->set_lg_bsize = __log_set_lg_bsize;
+ dbenv->set_lg_dir = __log_set_lg_dir;
+ dbenv->set_lg_max = __log_set_lg_max;
+ dbenv->set_lg_regionmax = __log_set_lg_regionmax;
+ dbenv->log_archive = __log_archive;
+ dbenv->log_cursor = __log_cursor;
+ dbenv->log_file = __log_file;
+ dbenv->log_flush = __log_flush;
+ dbenv->log_put = __log_put;
+ dbenv->log_stat = __log_stat;
+ }
}
/*
@@ -73,10 +96,16 @@ __log_set_lg_bsize(dbenv, lg_bsize)
DB_ENV *dbenv;
u_int32_t lg_bsize;
{
+ u_int32_t lg_max;
+
ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lg_bsize");
+ if (lg_bsize == 0)
+ lg_bsize = LG_BSIZE_DEFAULT;
+
/* Let's not be silly. */
- if (lg_bsize > dbenv->lg_max / 4) {
+ lg_max = dbenv->lg_size == 0 ? LG_MAX_DEFAULT : dbenv->lg_size;
+ if (lg_bsize > lg_max / 4) {
__db_err(dbenv, "log buffer size must be <= log file size / 4");
return (EINVAL);
}
@@ -94,15 +123,53 @@ __log_set_lg_max(dbenv, lg_max)
DB_ENV *dbenv;
u_int32_t lg_max;
{
- ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lg_max");
+ LOG *region;
+
+ if (lg_max == 0)
+ lg_max = LG_MAX_DEFAULT;
+
+ if (F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
+ if (!LOGGING_ON(dbenv))
+ return (__db_env_config(
+ dbenv, "set_lg_max", DB_INIT_LOG));
+ region = ((DB_LOG *)dbenv->lg_handle)->reginfo.primary;
+
+ /* Let's not be silly. */
+ if (lg_max < region->buffer_size * 4)
+ goto err;
+ region->log_nsize = lg_max;
+ } else {
+ /* Let's not be silly. */
+ if (lg_max < dbenv->lg_bsize * 4)
+ goto err;
+ dbenv->lg_size = lg_max;
+ }
+
+ return (0);
+
+err: __db_err(dbenv, "log file size must be >= log buffer size * 4");
+ return (EINVAL);
+}
+
+/*
+ * __log_set_lg_regionmax --
+ * Set the region size.
+ */
+static int
+__log_set_lg_regionmax(dbenv, lg_regionmax)
+ DB_ENV *dbenv;
+ u_int32_t lg_regionmax;
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lg_regionmax");
/* Let's not be silly. */
- if (lg_max < dbenv->lg_bsize * 4) {
- __db_err(dbenv, "log file size must be >= log buffer size * 4");
+ if (lg_regionmax != 0 && lg_regionmax < LG_BASE_REGION_SIZE) {
+ __db_err(dbenv,
+ "log file size must be >= %d", LG_BASE_REGION_SIZE);
return (EINVAL);
}
- dbenv->lg_max = lg_max;
+ dbenv->lg_regionmax = lg_regionmax;
return (0);
}
@@ -116,6 +183,6 @@ __log_set_lg_dir(dbenv, dir)
const char *dir;
{
if (dbenv->db_log_dir != NULL)
- __os_freestr(dbenv->db_log_dir);
+ __os_free(dbenv, dbenv->db_log_dir);
return (__os_strdup(dbenv, dir, &dbenv->db_log_dir));
}
diff --git a/bdb/log/log_put.c b/bdb/log/log_put.c
index c61f53e6c3d..64276fa8315 100644
--- a/bdb/log/log_put.c
+++ b/bdb/log/log_put.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: log_put.c,v 11.26 2000/11/30 00:58:40 ubell Exp $";
+static const char revid[] = "$Id: log_put.c,v 11.112 2002/09/10 02:39:26 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -29,109 +29,426 @@ static const char revid[] = "$Id: log_put.c,v 11.26 2000/11/30 00:58:40 ubell Ex
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_page.h"
-#include "log.h"
-#include "hash.h"
-#include "clib_ext.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/log.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+static int __log_encrypt_record __P((DB_ENV *, DBT *, HDR *, u_int32_t));
static int __log_fill __P((DB_LOG *, DB_LSN *, void *, u_int32_t));
-static int __log_flush __P((DB_LOG *, const DB_LSN *));
+static int __log_flush_commit __P((DB_ENV *, const DB_LSN *, u_int32_t));
+static int __log_flush_int __P((DB_LOG *, const DB_LSN *, int));
static int __log_newfh __P((DB_LOG *));
-static int __log_putr __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
-static int __log_open_files __P((DB_ENV *));
+static int __log_put_next __P((DB_ENV *,
+ DB_LSN *, const DBT *, HDR *, DB_LSN *));
+static int __log_putr __P((DB_LOG *,
+ DB_LSN *, const DBT *, u_int32_t, HDR *));
static int __log_write __P((DB_LOG *, void *, u_int32_t));
/*
- * log_put --
- * Write a log record.
+ * __log_put --
+ * Write a log record. This is the public interface, DB_ENV->log_put.
+ *
+ * PUBLIC: int __log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
*/
int
-log_put(dbenv, lsn, dbt, flags)
+__log_put(dbenv, lsnp, udbt, flags)
DB_ENV *dbenv;
- DB_LSN *lsn;
- const DBT *dbt;
+ DB_LSN *lsnp;
+ const DBT *udbt;
u_int32_t flags;
{
+ DB_CIPHER *db_cipher;
+ DBT *dbt, t;
DB_LOG *dblp;
- int ret;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_put(dbenv, lsn, dbt, flags));
-#endif
+ DB_LSN lsn, old_lsn;
+ HDR hdr;
+ LOG *lp;
+ u_int32_t do_flush, op, writeonly;
+ int lock_held, need_free, ret;
+ u_int8_t *key;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_put", DB_INIT_LOG);
/* Validate arguments. */
- if (flags != 0 && flags != DB_CHECKPOINT &&
- flags != DB_CURLSN && flags != DB_FLUSH)
- return (__db_ferr(dbenv, "log_put", 0));
+ op = DB_OPFLAGS_MASK & flags;
+ if (op != 0 && op != DB_COMMIT)
+ return (__db_ferr(dbenv, "DB_ENV->log_put", 0));
+
+ /* Check for allowed bit-flags. */
+ if (LF_ISSET(~(DB_OPFLAGS_MASK |
+ DB_FLUSH | DB_NOCOPY | DB_PERMANENT | DB_WRNOSYNC)))
+ return (__db_ferr(dbenv, "DB_ENV->log_put", 0));
+
+ /* DB_WRNOSYNC and DB_FLUSH are mutually exclusive. */
+ if (LF_ISSET(DB_WRNOSYNC) && LF_ISSET(DB_FLUSH))
+ return (__db_ferr(dbenv, "DB_ENV->log_put", 1));
+
+ /* Replication clients should never write log records. */
+ if (F_ISSET(dbenv, DB_ENV_REP_CLIENT) ||
+ F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) {
+ __db_err(dbenv,
+ "DB_ENV->log_put is illegal on replication clients");
+ return (EINVAL);
+ }
dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ db_cipher = dbenv->crypto_handle;
+ dbt = &t;
+ t = *udbt;
+ lock_held = need_free = 0;
+ do_flush = LF_ISSET(DB_FLUSH);
+ writeonly = LF_ISSET(DB_WRNOSYNC);
+
+ /*
+ * If we are coming from the logging code, we use an internal
+ * flag, DB_NOCOPY, because we know we can overwrite/encrypt
+ * the log record in place. Otherwise, if a user called log_put
+ * then we must copy it to new memory so that we know we can
+ * write it.
+ *
+ * We also must copy it to new memory if we are a replication
+ * master so that we retain an unencrypted copy of the log
+ * record to send to clients.
+ */
+ if (!LF_ISSET(DB_NOCOPY) || F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+ if (CRYPTO_ON(dbenv))
+ t.size += db_cipher->adj_size(udbt->size);
+ if ((ret = __os_calloc(dbenv, 1, t.size, &t.data)) != 0)
+ goto err;
+ need_free = 1;
+ memcpy(t.data, udbt->data, udbt->size);
+ }
+ if ((ret = __log_encrypt_record(dbenv, dbt, &hdr, udbt->size)) != 0)
+ goto err;
+ if (CRYPTO_ON(dbenv))
+ key = db_cipher->mac_key;
+ else
+ key = NULL;
+ /* Otherwise, we actually have a record to put. Put it. */
+
+ /* Before we grab the region lock, calculate the record's checksum. */
+ __db_chksum(dbt->data, dbt->size, key, hdr.chksum);
+
R_LOCK(dbenv, &dblp->reginfo);
- ret = __log_put(dbenv, lsn, dbt, flags);
- R_UNLOCK(dbenv, &dblp->reginfo);
+ lock_held = 1;
+
+ ZERO_LSN(old_lsn);
+ if ((ret = __log_put_next(dbenv, &lsn, dbt, &hdr, &old_lsn)) != 0)
+ goto err;
+
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+ /*
+ * Replication masters need to drop the lock to send
+ * messages, but we want to drop and reacquire it a minimal
+ * number of times.
+ */
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ lock_held = 0;
+
+ /*
+ * If we changed files and we're in a replicated
+ * environment, we need to inform our clients now that
+ * we've dropped the region lock.
+ *
+ * Note that a failed NEWFILE send is a dropped message
+ * that our client can handle, so we can ignore it. It's
+ * possible that the record we already put is a commit, so
+ * we don't just want to return failure.
+ */
+ if (!IS_ZERO_LSN(old_lsn))
+ (void)__rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_NEWFILE, &old_lsn, NULL, 0);
+
+ /*
+ * Then send the log record itself on to our clients.
+ *
+ * If the send fails and we're a commit or checkpoint,
+ * there's nothing we can do; the record's in the log.
+ * Flush it, even if we're running with TXN_NOSYNC, on the
+ * grounds that it should be in durable form somewhere.
+ */
+ /*
+ * !!!
+ * In the crypto case, we MUST send the udbt, not the
+ * now-encrypted dbt. Clients have no way to decrypt
+ * without the header.
+ */
+ if ((__rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_LOG, &lsn, udbt, flags) != 0) &&
+ LF_ISSET(DB_PERMANENT))
+ do_flush |= DB_FLUSH;
+ }
+
+ /*
+ * If needed, do a flush. Note that failures at this point
+ * are only permissible if we know we haven't written a commit
+ * record; __log_flush_commit is responsible for enforcing this.
+ *
+ * If a flush is not needed, see if WRITE_NOSYNC was set and we
+ * need to write out the log buffer.
+ */
+ if (do_flush || writeonly) {
+ if (!lock_held) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ lock_held = 1;
+ }
+ if (do_flush)
+ ret = __log_flush_commit(dbenv, &lsn, flags);
+ else if (lp->b_off != 0)
+ /*
+ * writeonly: if there's anything in the current
+ * log buffer, we need to write it out.
+ */
+ if ((ret = __log_write(dblp,
+ dblp->bufp, (u_int32_t)lp->b_off)) == 0)
+ lp->b_off = 0;
+ }
+
+err: if (lock_held)
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (need_free)
+ __os_free(dbenv, dbt->data);
+
+ if (ret == 0)
+ *lsnp = lsn;
+
return (ret);
}
/*
- * __log_put --
- * Write a log record; internal version.
+ * __log_txn_lsn --
*
- * PUBLIC: int __log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
+ * PUBLIC: void __log_txn_lsn
+ * PUBLIC: __P((DB_ENV *, DB_LSN *, u_int32_t *, u_int32_t *));
*/
-int
-__log_put(dbenv, lsn, dbt, flags)
+void
+__log_txn_lsn(dbenv, lsnp, mbytesp, bytesp)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+ u_int32_t *mbytesp, *bytesp;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ R_LOCK(dbenv, &dblp->reginfo);
+
+ /*
+ * We are trying to get the LSN of the last entry in the log. We use
+ * this in two places: 1) DB_ENV->txn_checkpiont uses it as a first
+ * value when trying to compute an LSN such that all transactions begun
+ * before it are complete. 2) DB_ENV->txn_begin uses it as the
+ * begin_lsn.
+ *
+ * Typically, it's easy to get the last written LSN, you simply look
+ * at the current log pointer and back up the number of bytes of the
+ * last log record. However, if the last thing we did was write the
+ * log header of a new log file, then, this doesn't work, so we return
+ * the first log record that will be written in this new file.
+ */
+ *lsnp = lp->lsn;
+ if (lp->lsn.offset > lp->len)
+ lsnp->offset -= lp->len;
+
+ /*
+ * Since we're holding the log region lock, return the bytes put into
+ * the log since the last checkpoint, transaction checkpoint needs it.
+ *
+ * We add the current buffer offset so as to count bytes that have not
+ * yet been written, but are sitting in the log buffer.
+ */
+ if (mbytesp != NULL) {
+ *mbytesp = lp->stat.st_wc_mbytes;
+ *bytesp = (u_int32_t)(lp->stat.st_wc_bytes + lp->b_off);
+
+ lp->stat.st_wc_mbytes = lp->stat.st_wc_bytes = 0;
+ }
+
+ R_UNLOCK(dbenv, &dblp->reginfo);
+}
+
+/*
+ * __log_put_next --
+ * Put the given record as the next in the log, wherever that may
+ * turn out to be.
+ */
+static int
+__log_put_next(dbenv, lsn, dbt, hdr, old_lsnp)
DB_ENV *dbenv;
DB_LSN *lsn;
const DBT *dbt;
- u_int32_t flags;
+ HDR *hdr;
+ DB_LSN *old_lsnp;
{
- DBT t;
DB_LOG *dblp;
+ DB_LSN old_lsn;
LOG *lp;
- u_int32_t lastoff;
- int ret;
+ int newfile, ret;
dblp = dbenv->lg_handle;
lp = dblp->reginfo.primary;
/*
- * If the application just wants to know where we are, fill in
- * the information. Currently used by the transaction manager
- * to avoid writing TXN_begin records.
+ * Save a copy of lp->lsn before we might decide to switch log
+ * files and change it. If we do switch log files, and we're
+ * doing replication, we'll need to tell our clients about the
+ * switch, and they need to receive a NEWFILE message
+ * with this "would-be" LSN in order to know they're not
+ * missing any log records.
*/
- if (flags == DB_CURLSN) {
- lsn->file = lp->lsn.file;
- lsn->offset = lp->lsn.offset;
- return (0);
- }
+ old_lsn = lp->lsn;
+ newfile = 0;
- /* If this information won't fit in the file, swap files. */
- if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) {
- if (sizeof(HDR) +
- sizeof(LOGP) + dbt->size > lp->persist.lg_max) {
+ /*
+ * If this information won't fit in the file, or if we're a
+ * replication client environment and have been told to do so,
+ * swap files.
+ */
+ if (lp->lsn.offset == 0 ||
+ lp->lsn.offset + hdr->size + dbt->size > lp->log_size) {
+ if (hdr->size + sizeof(LOGP) + dbt->size > lp->log_size) {
__db_err(dbenv,
- "log_put: record larger than maximum file size");
+ "DB_ENV->log_put: record larger than maximum file size");
return (EINVAL);
}
- /* Flush the log. */
- if ((ret = __log_flush(dblp, NULL)) != 0)
+ if ((ret = __log_newfile(dblp, NULL)) != 0)
return (ret);
/*
+ * Flag that we switched files, in case we're a master
+ * and need to send this information to our clients.
+ * We postpone doing the actual send until we can
+ * safely release the log region lock and are doing so
+ * anyway.
+ */
+ newfile = 1;
+
+ if (dbenv->db_noticecall != NULL)
+ dbenv->db_noticecall(dbenv, DB_NOTICE_LOGFILE_CHANGED);
+ }
+
+ /*
+ * The offset into the log file at this point is the LSN where
+ * we're about to put this record, and is the LSN the caller wants.
+ */
+ *lsn = lp->lsn;
+
+ /* If we switched log files, let our caller know where. */
+ if (newfile)
+ *old_lsnp = old_lsn;
+
+ /* Actually put the record. */
+ return (__log_putr(dblp, lsn, dbt, lp->lsn.offset - lp->len, hdr));
+}
+
+/*
+ * __log_flush_commit --
+ * Flush a record for which the DB_FLUSH flag to log_put has been set.
+ */
+static int
+__log_flush_commit(dbenv, lsnp, flags)
+ DB_ENV *dbenv;
+ const DB_LSN *lsnp;
+ u_int32_t flags;
+{
+ DB_LOG *dblp;
+ DB_LSN flush_lsn;
+ LOG *lp;
+ int ret;
+ u_int32_t op;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ flush_lsn = *lsnp;
+ op = DB_OPFLAGS_MASK & flags;
+
+ if ((ret = __log_flush_int(dblp, &flush_lsn, 1)) == 0)
+ return (0);
+
+ /*
+ * If a flush supporting a transaction commit fails, we must abort the
+ * transaction. (If we aren't doing a commit, return the failure; if
+ * if the commit we care about made it to disk successfully, we just
+ * ignore the failure, because there's no way to undo the commit.)
+ */
+ if (op != DB_COMMIT)
+ return (ret);
+
+ if (flush_lsn.file != lp->lsn.file || flush_lsn.offset < lp->w_off)
+ return (0);
+
+ /*
+ * Else, make sure that the commit record does not get out after we
+ * abort the transaction. Do this by overwriting the commit record
+ * in the buffer. (Note that other commits in this buffer will wait
+ * wait until a sucessful write happens, we do not wake them.) We
+ * point at the right part of the buffer and write an abort record
+ * over the commit. We must then try and flush the buffer again,
+ * since the interesting part of the buffer may have actually made
+ * it out to disk before there was a failure, we can't know for sure.
+ */
+ if (__txn_force_abort(dbenv,
+ dblp->bufp + flush_lsn.offset - lp->w_off) == 0)
+ (void)__log_flush_int(dblp, &flush_lsn, 0);
+
+ return (ret);
+}
+
+/*
+ * __log_newfile --
+ * Initialize and switch to a new log file. (Note that this is
+ * called both when no log yet exists and when we fill a log file.)
+ *
+ * PUBLIC: int __log_newfile __P((DB_LOG *, DB_LSN *));
+ */
+int
+__log_newfile(dblp, lsnp)
+ DB_LOG *dblp;
+ DB_LSN *lsnp;
+{
+ DB_CIPHER *db_cipher;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DBT t;
+ HDR hdr;
+ LOG *lp;
+ int need_free, ret;
+ u_int32_t lastoff;
+ size_t tsize;
+ u_int8_t *tmp;
+
+ dbenv = dblp->dbenv;
+ lp = dblp->reginfo.primary;
+
+ /* If we're not at the beginning of a file already, start a new one. */
+ if (lp->lsn.offset != 0) {
+ /*
+ * Flush the log so this file is out and can be closed. We
+ * cannot release the region lock here because we need to
+ * protect the end of the file while we switch. In
+ * particular, a thread with a smaller record than ours
+ * could detect that there is space in the log. Even
+ * blocking that event by declaring the file full would
+ * require all threads to wait here so that the lsn.file
+ * can be moved ahead after the flush completes. This
+ * probably can be changed if we had an lsn for the
+ * previous file and one for the curent, but it does not
+ * seem like this would get much more throughput, if any.
+ */
+ if ((ret = __log_flush_int(dblp, NULL, 0)) != 0)
+ return (ret);
+
+ DB_ASSERT(lp->b_off == 0);
+ /*
* Save the last known offset from the previous file, we'll
* need it to initialize the persistent header information.
*/
@@ -143,78 +460,50 @@ __log_put(dbenv, lsn, dbt, flags)
/* Reset the file write offset. */
lp->w_off = 0;
-
- if (dbenv->db_noticecall != NULL)
- dbenv->db_noticecall(dbenv, DB_NOTICE_LOGFILE_CHANGED);
} else
lastoff = 0;
- /* Initialize the LSN information returned to the user. */
- lsn->file = lp->lsn.file;
- lsn->offset = lp->lsn.offset;
-
/*
* Insert persistent information as the first record in every file.
* Note that the previous length is wrong for the very first record
* of the log, but that's okay, we check for it during retrieval.
*/
- if (lp->lsn.offset == 0) {
- t.data = &lp->persist;
- t.size = sizeof(LOGP);
- if ((ret = __log_putr(dblp, lsn,
- &t, lastoff == 0 ? 0 : lastoff - lp->len)) != 0)
- return (ret);
-
- /*
- * Record files open in this log.
- * If we are recovering then we are in the
- * process of outputting the files, don't do
- * it again.
- */
- if (!F_ISSET(dblp, DBLOG_RECOVER) &&
- (ret = __log_open_files(dbenv)) != 0)
- return (ret);
+ DB_ASSERT(lp->b_off == 0);
- /* Update the LSN information returned to the user. */
- lsn->file = lp->lsn.file;
- lsn->offset = lp->lsn.offset;
- }
+ memset(&t, 0, sizeof(t));
+ memset(&hdr, 0, sizeof(HDR));
- /* Write the application's log record. */
- if ((ret = __log_putr(dblp, lsn, dbt, lp->lsn.offset - lp->len)) != 0)
+ need_free = 0;
+ tsize = sizeof(LOGP);
+ db_cipher = dbenv->crypto_handle;
+ if (CRYPTO_ON(dbenv))
+ tsize += db_cipher->adj_size(tsize);
+ if ((ret = __os_calloc(dbenv, 1, tsize, &tmp)) != 0)
return (ret);
+ lp->persist.log_size = lp->log_size = lp->log_nsize;
+ memcpy(tmp, &lp->persist, sizeof(LOGP));
+ t.data = tmp;
+ t.size = (u_int32_t)tsize;
+ need_free = 1;
- /*
- * On a checkpoint, we:
- * Put out the checkpoint record (above).
- * Save the LSN of the checkpoint in the shared region.
- * Append the set of file name information into the log.
- */
- if (flags == DB_CHECKPOINT) {
- lp->chkpt_lsn = *lsn;
- if ((ret = __log_open_files(dbenv)) != 0)
- return (ret);
- }
+ if ((ret =
+ __log_encrypt_record(dbenv, &t, &hdr, (u_int32_t)tsize)) != 0)
+ goto err;
+ __db_chksum(t.data, t.size,
+ (CRYPTO_ON(dbenv)) ? db_cipher->mac_key : NULL, hdr.chksum);
+ lsn = lp->lsn;
+ if ((ret = __log_putr(dblp, &lsn,
+ &t, lastoff == 0 ? 0 : lastoff - lp->len, &hdr)) != 0)
+ goto err;
- /*
- * On a checkpoint or when flush is requested, we:
- * Flush the current buffer contents to disk.
- * Sync the log to disk.
- */
- if (flags == DB_FLUSH || flags == DB_CHECKPOINT)
- if ((ret = __log_flush(dblp, NULL)) != 0)
- return (ret);
+ /* Update the LSN information returned to the caller. */
+ if (lsnp != NULL)
+ *lsnp = lp->lsn;
- /*
- * On a checkpoint, we:
- * Save the time the checkpoint was written.
- * Reset the bytes written since the last checkpoint.
- */
- if (flags == DB_CHECKPOINT) {
- (void)time(&lp->chkpt);
- lp->stat.st_wc_bytes = lp->stat.st_wc_mbytes = 0;
- }
- return (0);
+err:
+ if (need_free)
+ __os_free(dbenv, tmp);
+ return (ret);
}
/*
@@ -222,100 +511,253 @@ __log_put(dbenv, lsn, dbt, flags)
* Actually put a record into the log.
*/
static int
-__log_putr(dblp, lsn, dbt, prev)
+__log_putr(dblp, lsn, dbt, prev, h)
DB_LOG *dblp;
DB_LSN *lsn;
const DBT *dbt;
u_int32_t prev;
+ HDR *h;
{
- HDR hdr;
+ DB_CIPHER *db_cipher;
+ DB_ENV *dbenv;
+ DB_LSN f_lsn;
LOG *lp;
- int ret;
+ HDR tmp, *hdr;
+ int ret, t_ret;
+ size_t b_off, nr;
+ u_int32_t w_off;
+ dbenv = dblp->dbenv;
lp = dblp->reginfo.primary;
/*
+ * If we weren't given a header, use a local one.
+ */
+ db_cipher = dbenv->crypto_handle;
+ if (h == NULL) {
+ hdr = &tmp;
+ memset(hdr, 0, sizeof(HDR));
+ if (CRYPTO_ON(dbenv))
+ hdr->size = HDR_CRYPTO_SZ;
+ else
+ hdr->size = HDR_NORMAL_SZ;
+ } else
+ hdr = h;
+
+ /* Save our position in case we fail. */
+ b_off = lp->b_off;
+ w_off = lp->w_off;
+ f_lsn = lp->f_lsn;
+
+ /*
* Initialize the header. If we just switched files, lsn.offset will
* be 0, and what we really want is the offset of the previous record
* in the previous file. Fortunately, prev holds the value we want.
*/
- hdr.prev = prev;
- hdr.len = sizeof(HDR) + dbt->size;
- hdr.cksum = __ham_func4(NULL, dbt->data, dbt->size);
+ hdr->prev = prev;
+ hdr->len = (u_int32_t)hdr->size + dbt->size;
- if ((ret = __log_fill(dblp, lsn, &hdr, sizeof(HDR))) != 0)
- return (ret);
- lp->len = sizeof(HDR);
- lp->lsn.offset += sizeof(HDR);
+ /*
+ * If we were passed in a nonzero checksum, our caller calculated
+ * the checksum before acquiring the log mutex, as an optimization.
+ *
+ * If our caller calculated a real checksum of 0, we'll needlessly
+ * recalculate it. C'est la vie; there's no out-of-bounds value
+ * here.
+ */
+ if (hdr->chksum[0] == 0)
+ __db_chksum(dbt->data, dbt->size,
+ (CRYPTO_ON(dbenv)) ? db_cipher->mac_key : NULL,
+ hdr->chksum);
+
+ if ((ret = __log_fill(dblp, lsn, hdr, (u_int32_t)hdr->size)) != 0)
+ goto err;
if ((ret = __log_fill(dblp, lsn, dbt->data, dbt->size)) != 0)
- return (ret);
- lp->len += dbt->size;
- lp->lsn.offset += dbt->size;
+ goto err;
+
+ lp->len = (u_int32_t)(hdr->size + dbt->size);
+ lp->lsn.offset += (u_int32_t)(hdr->size + dbt->size);
return (0);
+err:
+ /*
+ * If we wrote more than one buffer before failing, get the
+ * first one back. The extra buffers will fail the checksums
+ * and be ignored.
+ */
+ if (w_off + lp->buffer_size < lp->w_off) {
+ if ((t_ret =
+ __os_seek(dbenv,
+ &dblp->lfh, 0, 0, w_off, 0, DB_OS_SEEK_SET)) != 0 ||
+ (t_ret = __os_read(dbenv, &dblp->lfh, dblp->bufp,
+ b_off, &nr)) != 0)
+ return (__db_panic(dbenv, t_ret));
+ if (nr != b_off) {
+ __db_err(dbenv, "Short read while restoring log");
+ return (__db_panic(dbenv, EIO));
+ }
+ }
+
+ /* Reset to where we started. */
+ lp->w_off = w_off;
+ lp->b_off = b_off;
+ lp->f_lsn = f_lsn;
+
+ return (ret);
}
/*
- * log_flush --
+ * __log_flush --
* Write all records less than or equal to the specified LSN.
+ *
+ * PUBLIC: int __log_flush __P((DB_ENV *, const DB_LSN *));
*/
int
-log_flush(dbenv, lsn)
+__log_flush(dbenv, lsn)
DB_ENV *dbenv;
const DB_LSN *lsn;
{
DB_LOG *dblp;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_flush(dbenv, lsn));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_flush", DB_INIT_LOG);
dblp = dbenv->lg_handle;
R_LOCK(dbenv, &dblp->reginfo);
- ret = __log_flush(dblp, lsn);
+ ret = __log_flush_int(dblp, lsn, 1);
R_UNLOCK(dbenv, &dblp->reginfo);
return (ret);
}
/*
- * __log_flush --
+ * __log_flush_int --
* Write all records less than or equal to the specified LSN; internal
* version.
*/
static int
-__log_flush(dblp, lsn)
+__log_flush_int(dblp, lsnp, release)
DB_LOG *dblp;
- const DB_LSN *lsn;
+ const DB_LSN *lsnp;
+ int release;
{
- DB_LSN t_lsn;
+ DB_ENV *dbenv;
+ DB_LSN flush_lsn, f_lsn;
+ DB_MUTEX *flush_mutexp;
LOG *lp;
- int current, ret;
+ int current, do_flush, first, ret;
+ size_t b_off;
+ struct __db_commit *commit;
+ u_int32_t ncommit, w_off;
ret = 0;
+ ncommit = 0;
+ dbenv = dblp->dbenv;
lp = dblp->reginfo.primary;
+ flush_mutexp = R_ADDR(&dblp->reginfo, lp->flush_mutex_off);
/*
* If no LSN specified, flush the entire log by setting the flush LSN
* to the last LSN written in the log. Otherwise, check that the LSN
* isn't a non-existent record for the log.
*/
- if (lsn == NULL) {
- t_lsn.file = lp->lsn.file;
- t_lsn.offset = lp->lsn.offset - lp->len;
- lsn = &t_lsn;
- } else
- if (lsn->file > lp->lsn.file ||
- (lsn->file == lp->lsn.file &&
- lsn->offset > lp->lsn.offset - lp->len)) {
- __db_err(dblp->dbenv,
- "log_flush: LSN past current end-of-log");
- return (EINVAL);
- }
+ if (lsnp == NULL) {
+ flush_lsn.file = lp->lsn.file;
+ flush_lsn.offset = lp->lsn.offset - lp->len;
+ } else if (lsnp->file > lp->lsn.file ||
+ (lsnp->file == lp->lsn.file &&
+ lsnp->offset > lp->lsn.offset - lp->len)) {
+ __db_err(dbenv,
+ "DB_ENV->log_flush: LSN past current end-of-log");
+ return (EINVAL);
+ } else {
+ /*
+ * See if we need to wait. s_lsn is not locked so some
+ * care is needed. The sync point can only move forward.
+ * If the file we want is in the past we are done.
+ * If the file numbers are the same check the offset.
+ * If this fails check the file numbers again since the
+ * offset might have changed while we were looking.
+ * This all assumes we can read an integer in one
+ * state or the other, not in transition.
+ */
+ if (lp->s_lsn.file > lsnp->file)
+ return (0);
+
+ if (lp->s_lsn.file == lsnp->file &&
+ lp->s_lsn.offset > lsnp->offset)
+ return (0);
+
+ if (lp->s_lsn.file > lsnp->file)
+ return (0);
+
+ flush_lsn = *lsnp;
+ }
+
+ /*
+ * If a flush is in progress and we're allowed to do so, drop
+ * the region lock and block waiting for the next flush.
+ */
+ if (release && lp->in_flush != 0) {
+ if ((commit = SH_TAILQ_FIRST(
+ &lp->free_commits, __db_commit)) == NULL) {
+ if ((ret =
+ __db_shalloc(dblp->reginfo.addr,
+ sizeof(struct __db_commit),
+ MUTEX_ALIGN, &commit)) != 0)
+ goto flush;
+ memset(commit, 0, sizeof(*commit));
+ if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo,
+ &commit->mutex, MUTEX_SELF_BLOCK |
+ MUTEX_NO_RLOCK)) != 0) {
+ __db_shalloc_free(dblp->reginfo.addr, commit);
+ return (ret);
+ }
+ MUTEX_LOCK(dbenv, &commit->mutex);
+ } else
+ SH_TAILQ_REMOVE(
+ &lp->free_commits, commit, links, __db_commit);
+
+ lp->ncommit++;
+
+ /*
+ * Flushes may be requested out of LSN order; be
+ * sure we only move lp->t_lsn forward.
+ */
+ if (log_compare(&lp->t_lsn, &flush_lsn) < 0)
+ lp->t_lsn = flush_lsn;
+
+ commit->lsn = flush_lsn;
+ SH_TAILQ_INSERT_HEAD(
+ &lp->commits, commit, links, __db_commit);
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ /* Wait here for the in-progress flush to finish. */
+ MUTEX_LOCK(dbenv, &commit->mutex);
+ R_LOCK(dbenv, &dblp->reginfo);
+
+ lp->ncommit--;
+ /*
+ * Grab the flag before freeing the struct to see if
+ * we need to flush the log to commit. If so,
+ * use the maximal lsn for any committing thread.
+ */
+ do_flush = F_ISSET(commit, DB_COMMIT_FLUSH);
+ F_CLR(commit, DB_COMMIT_FLUSH);
+ SH_TAILQ_INSERT_HEAD(
+ &lp->free_commits, commit, links, __db_commit);
+ if (do_flush) {
+ lp->in_flush--;
+ flush_lsn = lp->t_lsn;
+ } else
+ return (0);
+ }
+
+ /*
+ * Protect flushing with its own mutex so we can release
+ * the region lock except during file switches.
+ */
+flush: MUTEX_LOCK(dbenv, flush_mutexp);
/*
* If the LSN is less than or equal to the last-sync'd LSN, we're done.
@@ -323,9 +765,12 @@ __log_flush(dblp, lsn)
* after the byte we absolutely know was written to disk, so the test
* is <, not <=.
*/
- if (lsn->file < lp->s_lsn.file ||
- (lsn->file == lp->s_lsn.file && lsn->offset < lp->s_lsn.offset))
- return (0);
+ if (flush_lsn.file < lp->s_lsn.file ||
+ (flush_lsn.file == lp->s_lsn.file &&
+ flush_lsn.offset < lp->s_lsn.offset)) {
+ MUTEX_UNLOCK(dbenv, flush_mutexp);
+ goto done;
+ }
/*
* We may need to write the current buffer. We have to write the
@@ -333,9 +778,12 @@ __log_flush(dblp, lsn)
* buffer's starting LSN.
*/
current = 0;
- if (lp->b_off != 0 && log_compare(lsn, &lp->f_lsn) >= 0) {
- if ((ret = __log_write(dblp, dblp->bufp, lp->b_off)) != 0)
- return (ret);
+ if (lp->b_off != 0 && log_compare(&flush_lsn, &lp->f_lsn) >= 0) {
+ if ((ret = __log_write(dblp,
+ dblp->bufp, (u_int32_t)lp->b_off)) != 0) {
+ MUTEX_UNLOCK(dbenv, flush_mutexp);
+ goto done;
+ }
lp->b_off = 0;
current = 1;
@@ -348,23 +796,90 @@ __log_flush(dblp, lsn)
* buffer, don't bother. We have nothing to write and nothing to
* sync.
*/
- if (dblp->lfname != lp->lsn.file) {
- if (!current)
- return (0);
- if ((ret = __log_newfh(dblp)) != 0)
- return (ret);
- }
+ if (!F_ISSET(&dblp->lfh, DB_FH_VALID) || dblp->lfname != lp->lsn.file)
+ if (!current || (ret = __log_newfh(dblp)) != 0) {
+ MUTEX_UNLOCK(dbenv, flush_mutexp);
+ goto done;
+ }
+
+ /*
+ * We are going to flush, release the region.
+ * First get the current state of the buffer since
+ * another write may come in, but we may not flush it.
+ */
+ b_off = lp->b_off;
+ w_off = lp->w_off;
+ f_lsn = lp->f_lsn;
+ lp->in_flush++;
+ if (release)
+ R_UNLOCK(dbenv, &dblp->reginfo);
/* Sync all writes to disk. */
- if ((ret = __os_fsync(dblp->dbenv, &dblp->lfh)) != 0)
- return (__db_panic(dblp->dbenv, ret));
+ if ((ret = __os_fsync(dbenv, &dblp->lfh)) != 0) {
+ MUTEX_UNLOCK(dbenv, flush_mutexp);
+ if (release)
+ R_LOCK(dbenv, &dblp->reginfo);
+ ret = __db_panic(dbenv, ret);
+ return (ret);
+ }
+
+ /*
+ * Set the last-synced LSN.
+ * This value must be set to the LSN past the last complete
+ * record that has been flushed. This is at least the first
+ * lsn, f_lsn. If the buffer is empty, b_off == 0, then
+ * we can move up to write point since the first lsn is not
+ * set for the new buffer.
+ */
+ lp->s_lsn = f_lsn;
+ if (b_off == 0)
+ lp->s_lsn.offset = w_off;
+
+ MUTEX_UNLOCK(dbenv, flush_mutexp);
+ if (release)
+ R_LOCK(dbenv, &dblp->reginfo);
+
+ lp->in_flush--;
++lp->stat.st_scount;
- /* Set the last-synced LSN, using the on-disk write offset. */
- lp->s_lsn.file = lp->f_lsn.file;
- lp->s_lsn.offset = lp->w_off;
+ /*
+ * How many flush calls (usually commits) did this call actually sync?
+ * At least one, if it got here.
+ */
+ ncommit = 1;
+done:
+ if (lp->ncommit != 0) {
+ first = 1;
+ for (commit = SH_TAILQ_FIRST(&lp->commits, __db_commit);
+ commit != NULL;
+ commit = SH_TAILQ_NEXT(commit, links, __db_commit))
+ if (log_compare(&lp->s_lsn, &commit->lsn) > 0) {
+ MUTEX_UNLOCK(dbenv, &commit->mutex);
+ SH_TAILQ_REMOVE(
+ &lp->commits, commit, links, __db_commit);
+ ncommit++;
+ } else if (first == 1) {
+ F_SET(commit, DB_COMMIT_FLUSH);
+ MUTEX_UNLOCK(dbenv, &commit->mutex);
+ SH_TAILQ_REMOVE(
+ &lp->commits, commit, links, __db_commit);
+ /*
+ * This thread will wake and flush.
+ * If another thread commits and flushes
+ * first we will waste a trip trough the
+ * mutex.
+ */
+ lp->in_flush++;
+ first = 0;
+ }
+ }
+ if (lp->stat.st_maxcommitperflush < ncommit)
+ lp->stat.st_maxcommitperflush = ncommit;
+ if (lp->stat.st_mincommitperflush > ncommit ||
+ lp->stat.st_mincommitperflush == 0)
+ lp->stat.st_mincommitperflush = ncommit;
- return (0);
+ return (ret);
}
/*
@@ -415,7 +930,7 @@ __log_fill(dblp, lsn, addr, len)
nw = remain > len ? len : remain;
memcpy(dblp->bufp + lp->b_off, addr, nw);
addr = (u_int8_t *)addr + nw;
- len -= nw;
+ len -= (u_int32_t)nw;
lp->b_off += nw;
/* If we fill the buffer, flush it. */
@@ -439,15 +954,18 @@ __log_write(dblp, addr, len)
void *addr;
u_int32_t len;
{
+ DB_ENV *dbenv;
LOG *lp;
size_t nw;
int ret;
+ dbenv = dblp->dbenv;
+ lp = dblp->reginfo.primary;
+
/*
* If we haven't opened the log file yet or the current one
* has changed, acquire a new log file.
*/
- lp = dblp->reginfo.primary;
if (!F_ISSET(&dblp->lfh, DB_FH_VALID) || dblp->lfname != lp->lsn.file)
if ((ret = __log_newfh(dblp)) != 0)
return (ret);
@@ -457,14 +975,10 @@ __log_write(dblp, addr, len)
* since we last did).
*/
if ((ret =
- __os_seek(dblp->dbenv,
+ __os_seek(dbenv,
&dblp->lfh, 0, 0, lp->w_off, 0, DB_OS_SEEK_SET)) != 0 ||
- (ret = __os_write(dblp->dbenv, &dblp->lfh, addr, len, &nw)) != 0)
- return (__db_panic(dblp->dbenv, ret));
- if (nw != len) {
- __db_err(dblp->dbenv, "Short write while writing log");
- return (EIO);
- }
+ (ret = __os_write(dbenv, &dblp->lfh, addr, len, &nw)) != 0)
+ return (ret);
/* Reset the buffer offset and update the seek offset. */
lp->w_off += len;
@@ -484,11 +998,13 @@ __log_write(dblp, addr, len)
}
/*
- * log_file --
+ * __log_file --
* Map a DB_LSN to a file name.
+ *
+ * PUBLIC: int __log_file __P((DB_ENV *, const DB_LSN *, char *, size_t));
*/
int
-log_file(dbenv, lsn, namep, len)
+__log_file(dbenv, lsn, namep, len)
DB_ENV *dbenv;
const DB_LSN *lsn;
char *namep;
@@ -498,13 +1014,9 @@ log_file(dbenv, lsn, namep, len)
int ret;
char *name;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_file(dbenv, lsn, namep, len));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_file", DB_INIT_LOG);
dblp = dbenv->lg_handle;
R_LOCK(dbenv, &dblp->reginfo);
@@ -516,11 +1028,11 @@ log_file(dbenv, lsn, namep, len)
/* Check to make sure there's enough room and copy the name. */
if (len < strlen(name) + 1) {
*namep = '\0';
- __db_err(dbenv, "log_file: name buffer is too short");
+ __db_err(dbenv, "DB_ENV->log_file: name buffer is too short");
return (EINVAL);
}
(void)strcpy(namep, name);
- __os_freestr(name);
+ __os_free(dbenv, name);
return (0);
}
@@ -533,19 +1045,21 @@ static int
__log_newfh(dblp)
DB_LOG *dblp;
{
+ DB_ENV *dbenv;
LOG *lp;
int ret;
char *name;
+ dbenv = dblp->dbenv;
+ lp = dblp->reginfo.primary;
+
/* Close any previous file descriptor. */
if (F_ISSET(&dblp->lfh, DB_FH_VALID))
- (void)__os_closehandle(&dblp->lfh);
-
- /* Get the path of the new file and open it. */
- lp = dblp->reginfo.primary;
- dblp->lfname = lp->lsn.file;
+ (void)__os_closehandle(dbenv, &dblp->lfh);
/*
+ * Get the path of the new file and open it.
+ *
* Adding DB_OSO_LOG to the flags may add additional platform-specific
* optimizations. On WinNT, the logfile is preallocated, which may
* have a time penalty at startup, but have better overall throughput.
@@ -557,14 +1071,16 @@ __log_newfh(dblp)
* maximum size down into the Windows __os_open routine, because it
* wants to pre-allocate it.
*/
- dblp->lfh.log_size = dblp->dbenv->lg_max;
+ dblp->lfname = lp->lsn.file;
+ dblp->lfh.log_size = lp->log_size;
if ((ret = __log_name(dblp, dblp->lfname,
&name, &dblp->lfh,
- DB_OSO_CREATE |/* DB_OSO_LOG |*/ DB_OSO_SEQ)) != 0)
- __db_err(dblp->dbenv,
- "log_put: %s: %s", name, db_strerror(ret));
+ DB_OSO_CREATE |/* DB_OSO_LOG |*/ DB_OSO_SEQ |
+ (F_ISSET(dbenv, DB_ENV_DIRECT_LOG) ? DB_OSO_DIRECT : 0))) != 0)
+ __db_err(dbenv,
+ "DB_ENV->log_put: %s: %s", name, db_strerror(ret));
- __os_freestr(name);
+ __os_free(dbenv, name);
return (ret);
}
@@ -582,11 +1098,13 @@ __log_name(dblp, filenumber, namep, fhp, flags)
char **namep;
DB_FH *fhp;
{
+ DB_ENV *dbenv;
LOG *lp;
int ret;
char *oname;
char old[sizeof(LFPREFIX) + 5 + 20], new[sizeof(LFPREFIX) + 10 + 20];
+ dbenv = dblp->dbenv;
lp = dblp->reginfo.primary;
/*
@@ -608,13 +1126,12 @@ __log_name(dblp, filenumber, namep, fhp, flags)
* file, return regardless.
*/
(void)snprintf(new, sizeof(new), LFNAME, filenumber);
- if ((ret = __db_appname(dblp->dbenv,
- DB_APP_LOG, NULL, new, 0, NULL, namep)) != 0 || fhp == NULL)
+ if ((ret = __db_appname(dbenv,
+ DB_APP_LOG, new, 0, NULL, namep)) != 0 || fhp == NULL)
return (ret);
/* Open the new-style file -- if we succeed, we're done. */
- if ((ret = __os_open(dblp->dbenv,
- *namep, flags, lp->persist.mode, fhp)) == 0)
+ if ((ret = __os_open(dbenv, *namep, flags, lp->persist.mode, fhp)) == 0)
return (0);
/*
@@ -622,15 +1139,14 @@ __log_name(dblp, filenumber, namep, fhp, flags)
* the caller isn't interested in old-style files.
*/
if (!LF_ISSET(DB_OSO_RDONLY)) {
- __db_err(dblp->dbenv,
+ __db_err(dbenv,
"%s: log file open failed: %s", *namep, db_strerror(ret));
- return (__db_panic(dblp->dbenv, ret));
+ return (__db_panic(dbenv, ret));
}
/* Create an old-style file name. */
(void)snprintf(old, sizeof(old), LFNAME_V1, filenumber);
- if ((ret = __db_appname(dblp->dbenv,
- DB_APP_LOG, NULL, old, 0, NULL, &oname)) != 0)
+ if ((ret = __db_appname(dbenv, DB_APP_LOG, old, 0, NULL, &oname)) != 0)
goto err;
/*
@@ -638,9 +1154,9 @@ __log_name(dblp, filenumber, namep, fhp, flags)
* space allocated for the new-style name and return the old-style
* name to the caller.
*/
- if ((ret = __os_open(dblp->dbenv,
+ if ((ret = __os_open(dbenv,
oname, flags, lp->persist.mode, fhp)) == 0) {
- __os_freestr(*namep);
+ __os_free(dbenv, *namep);
*namep = oname;
return (0);
}
@@ -653,52 +1169,82 @@ __log_name(dblp, filenumber, namep, fhp, flags)
* old-style name, but we expected it to exist and we weren't just
* looking for any log file. That's not a likely error.
*/
-err: __os_freestr(oname);
+err: __os_free(dbenv, oname);
return (ret);
}
-static int
-__log_open_files(dbenv)
+/*
+ * __log_rep_put --
+ * Short-circuit way for replication clients to put records into the
+ * log. Replication clients' logs need to be laid out exactly their masters'
+ * are, so we let replication take responsibility for when the log gets
+ * flushed, when log switches files, etc. This is just a thin PUBLIC wrapper
+ * for __log_putr with a slightly prettier interface.
+ *
+ * Note that the log region mutex should be held when this is called.
+ *
+ * PUBLIC: int __log_rep_put __P((DB_ENV *, DB_LSN *, const DBT *));
+ */
+int
+__log_rep_put(dbenv, lsnp, rec)
DB_ENV *dbenv;
+ DB_LSN *lsnp;
+ const DBT *rec;
{
+ DB_CIPHER *db_cipher;
DB_LOG *dblp;
- DB_LSN r_unused;
- DBT fid_dbt, t;
- FNAME *fnp;
+ HDR hdr;
+ DBT *dbt, t;
LOG *lp;
- int ret;
+ int need_free, ret;
dblp = dbenv->lg_handle;
lp = dblp->reginfo.primary;
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
- if (fnp->ref == 0) /* Entry not in use. */
- continue;
- if (fnp->name_off != INVALID_ROFF) {
- memset(&t, 0, sizeof(t));
- t.data = R_ADDR(&dblp->reginfo, fnp->name_off);
- t.size = strlen(t.data) + 1;
- }
- memset(&fid_dbt, 0, sizeof(fid_dbt));
- fid_dbt.data = fnp->ufid;
- fid_dbt.size = DB_FILE_ID_LEN;
- /*
- * Output LOG_CHECKPOINT records which will be
- * processed during the OPENFILES pass of recovery.
- * At the end of recovery we want to output the
- * files that were open so that a future recovery
- * run will have the correct files open during
- * a backward pass. For this we output LOG_CLOSE
- * records so that the files will be closed on
- * the forward pass.
- */
- if ((ret = __log_register_log(dbenv,
- NULL, &r_unused, 0,
- F_ISSET(dblp, DBLOG_RECOVER) ? LOG_CLOSE : LOG_CHECKPOINT,
- fnp->name_off == INVALID_ROFF ? NULL : &t,
- &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno)) != 0)
+ memset(&hdr, 0, sizeof(HDR));
+ t = *rec;
+ dbt = &t;
+ need_free = 0;
+ db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+ if (CRYPTO_ON(dbenv))
+ t.size += db_cipher->adj_size(rec->size);
+ if ((ret = __os_calloc(dbenv, 1, t.size, &t.data)) != 0)
+ goto err;
+ need_free = 1;
+ memcpy(t.data, rec->data, rec->size);
+
+ if ((ret = __log_encrypt_record(dbenv, dbt, &hdr, rec->size)) != 0)
+ goto err;
+ __db_chksum(t.data, t.size,
+ (CRYPTO_ON(dbenv)) ? db_cipher->mac_key : NULL, hdr.chksum);
+
+ DB_ASSERT(log_compare(lsnp, &lp->lsn) == 0);
+ ret = __log_putr(dblp, lsnp, dbt, lp->lsn.offset - lp->len, &hdr);
+err:
+ if (need_free)
+ __os_free(dbenv, t.data);
+ return (ret);
+}
+
+static int
+__log_encrypt_record(dbenv, dbt, hdr, orig)
+ DB_ENV *dbenv;
+ DBT *dbt;
+ HDR *hdr;
+ u_int32_t orig;
+{
+ DB_CIPHER *db_cipher;
+ int ret;
+
+ if (CRYPTO_ON(dbenv)) {
+ db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+ hdr->size = HDR_CRYPTO_SZ;
+ hdr->orig_size = orig;
+ if ((ret = db_cipher->encrypt(dbenv, db_cipher->data,
+ hdr->iv, dbt->data, dbt->size)) != 0)
return (ret);
+ } else {
+ hdr->size = HDR_NORMAL_SZ;
}
return (0);
}
diff --git a/bdb/log/log_rec.c b/bdb/log/log_rec.c
deleted file mode 100644
index 493dd06d4c6..00000000000
--- a/bdb/log/log_rec.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1995, 1996
- * The President and Fellows of Harvard University. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: log_rec.c,v 11.48 2001/01/11 18:19:53 bostic Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <string.h>
-#endif
-
-#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "log.h"
-
-static int __log_check_master __P((DB_ENV *, u_int8_t *, char *));
-static int __log_do_open __P((DB_ENV *, DB_LOG *,
- u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
-static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
-
-/*
- * PUBLIC: int __log_register_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__log_register_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- DB_ENTRY *dbe;
- DB_LOG *logp;
- DB *dbp;
- __log_register_args *argp;
- int do_rem, ret, t_ret;
-
- logp = dbenv->lg_handle;
- dbp = NULL;
-
-#ifdef DEBUG_RECOVER
- REC_PRINT(__log_register_print);
-#endif
- COMPQUIET(lsnp, NULL);
-
- if ((ret = __log_register_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
-
- if ((argp->opcode == LOG_OPEN &&
- (DB_REDO(op) || op == DB_TXN_OPENFILES)) ||
- (argp->opcode == LOG_CLOSE && DB_UNDO(op))) {
- /*
- * If we are redoing an open or undoing a close, then we need
- * to open a file. We must open the file even if
- * the meta page is not yet written as we may be creating it.
- */
- if (op == DB_TXN_OPENFILES)
- F_SET(logp, DBLOG_FORCE_OPEN);
- ret = __log_open_file(dbenv, logp, argp);
- F_CLR(logp, DBLOG_FORCE_OPEN);
- if (ret == ENOENT || ret == EINVAL) {
- if (op == DB_TXN_OPENFILES && argp->name.size != 0 &&
- (ret = __db_txnlist_delete(dbenv, info,
- argp->name.data, argp->fileid, 0)) != 0)
- goto out;
- ret = 0;
- }
- } else if (argp->opcode != LOG_CHECKPOINT) {
- /*
- * If we are undoing an open, then we need to close the file.
- *
- * If the file is deleted, then we can just ignore this close.
- * Otherwise, we should usually have a valid dbp we should
- * close or whose reference count should be decremented.
- * However, if we shut down without closing a file, we may, in
- * fact, not have the file open, and that's OK.
- */
- do_rem = 0;
- MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
- if (argp->fileid < logp->dbentry_cnt) {
- dbe = &logp->dbentry[argp->fileid];
-
- DB_ASSERT(dbe->refcount == 1);
-
- ret = __db_txnlist_close(info,
- argp->fileid, dbe->count);
- if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL)
- (void)log_unregister(dbenv, dbp);
- do_rem = 1;
- }
- MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
- if (do_rem) {
- (void)__log_rem_logid(logp, dbp, argp->fileid);
- /*
- * If remove or rename has closed the file, don't
- * sync.
- */
- if (dbp != NULL &&
- (t_ret = dbp->close(dbp,
- dbp->mpf == NULL ? DB_NOSYNC : 0)) != 0 && ret == 0)
- ret = t_ret;
- }
- } else if (DB_UNDO(op) || op == DB_TXN_OPENFILES) {
- /*
- * It's a checkpoint and we are rolling backward. It
- * is possible that the system was shut down and thus
- * ended with a stable checkpoint; this file was never
- * closed and has therefore not been reopened yet. If
- * so, we need to try to open it.
- */
- ret = __log_open_file(dbenv, logp, argp);
- if (ret == ENOENT || ret == EINVAL) {
- if (argp->name.size != 0 && (ret =
- __db_txnlist_delete(dbenv, info,
- argp->name.data, argp->fileid, 0)) != 0)
- goto out;
- ret = 0;
- }
- }
-
-out: if (argp != NULL)
- __os_free(argp, 0);
- return (ret);
-}
-
-/*
- * __log_open_file --
- * Called during log_register recovery. Make sure that we have an
- * entry in the dbentry table for this ndx. Returns 0 on success,
- * non-zero on error.
- */
-static int
-__log_open_file(dbenv, lp, argp)
- DB_ENV *dbenv;
- DB_LOG *lp;
- __log_register_args *argp;
-{
- DB_ENTRY *dbe;
- DB *dbp;
-
- /*
- * We never re-open temporary files. Temp files are only
- * useful during aborts in which case the dbp was entered
- * when the file was registered. During recovery, we treat
- * temp files as properly deleted files, allowing the open to
- * fail and not reporting any errors when recovery fails to
- * get a valid dbp from db_fileid_to_db.
- */
- if (argp->name.size == 0) {
- (void)__log_add_logid(dbenv, lp, NULL, argp->fileid);
- return (ENOENT);
- }
-
- /*
- * Because of reference counting, we cannot automatically close files
- * during recovery, so when we're opening, we have to check that the
- * name we are opening is what we expect. If it's not, then we close
- * the old file and open the new one.
- */
- MUTEX_THREAD_LOCK(dbenv, lp->mutexp);
- if (argp->fileid < lp->dbentry_cnt)
- dbe = &lp->dbentry[argp->fileid];
- else
- dbe = NULL;
-
- if (dbe != NULL) {
- dbe->deleted = 0;
- if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
- if (dbp->meta_pgno != argp->meta_pgno ||
- memcmp(dbp->fileid,
- argp->uid.data, DB_FILE_ID_LEN) != 0) {
- MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
- goto reopen;
- }
- if (!F_ISSET(lp, DBLOG_RECOVER))
- dbe->refcount++;
- MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
- return (0);
- }
- }
-
- MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
- if (0) {
-reopen: (void)log_unregister(dbp->dbenv, dbp);
- (void)__log_rem_logid(lp, dbp, argp->fileid);
- dbp->close(dbp, 0);
- }
-
- return (__log_do_open(dbenv, lp,
- argp->uid.data, argp->name.data,
- argp->ftype, argp->fileid, argp->meta_pgno));
-}
-
-/*
- * log_reopen_file -- close and reopen a db file.
- * Must be called when a metadata page changes.
- *
- * PUBLIC: int __log_reopen_file __P((DB_ENV *,
- * PUBLIC: char *, int32_t, u_int8_t *, db_pgno_t));
- *
- */
-int
-__log_reopen_file(dbenv, name, ndx, fileid, meta_pgno)
- DB_ENV *dbenv;
- char *name;
- int32_t ndx;
- u_int8_t *fileid;
- db_pgno_t meta_pgno;
-{
- DB *dbp;
- DB_LOG *logp;
- DBTYPE ftype;
- FNAME *fnp;
- LOG *lp;
- char *tmp_name;
- int ret;
-
- logp = dbenv->lg_handle;
-
- if (name == NULL) {
- R_LOCK(dbenv, &logp->reginfo);
-
- lp = logp->reginfo.primary;
-
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
- if (fnp->ref == 0) /* Entry not in use. */
- continue;
- if (memcmp(fnp->ufid, fileid, DB_FILE_ID_LEN) == 0)
- break;
- }
-
- if (fnp == 0 || fnp->name_off == INVALID_ROFF) {
- __db_err(dbenv,
- "metasub recover: non-existent file id");
- return (EINVAL);
- }
-
- name = R_ADDR(&logp->reginfo, fnp->name_off);
- ret = __os_strdup(dbenv, name, &tmp_name);
- R_UNLOCK(dbenv, &logp->reginfo);
- if (ret != 0)
- goto out;
- name = tmp_name;
- } else
- tmp_name = NULL;
-
- if ((ret = __db_fileid_to_db(dbenv, &dbp, ndx, 0)) != 0)
- goto out;
- ftype = dbp->type;
- (void)log_unregister(dbenv, dbp);
- (void)__log_rem_logid(logp, dbp, ndx);
- (void)dbp->close(dbp, 0);
-
- ret = __log_do_open(dbenv, logp, fileid, name, ftype, ndx, meta_pgno);
-
- if (tmp_name != NULL)
- __os_free(tmp_name, 0);
-
-out: return (ret);
-}
-
-/*
- * __log_do_open --
- * Open files referenced in the log. This is the part of the open that
- * is not protected by the thread mutex.
- */
-static int
-__log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno)
- DB_ENV *dbenv;
- DB_LOG *lp;
- u_int8_t *uid;
- char *name;
- DBTYPE ftype;
- int32_t ndx;
- db_pgno_t meta_pgno;
-{
- DB *dbp;
- int ret;
- u_int8_t zeroid[DB_FILE_ID_LEN];
-
- if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0)
- return (ret);
-
- dbp->log_fileid = ndx;
-
- /*
- * This is needed to signal to the locking routines called while
- * opening databases that we are potentially undoing a transaction
- * from an XA process. Since the XA process does not share
- * locks with the aborting transaction this prevents us from
- * deadlocking during the open during rollback.
- * Because this routine is called either during recovery or during an
- * XA_ABORT, we can safely set DB_AM_RECOVER in the dbp since it
- * will not be shared with other threads.
- */
- F_SET(dbp, DB_AM_RECOVER);
- if (meta_pgno != PGNO_BASE_MD)
- memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
- dbp->type = ftype;
- if ((ret =
- __db_dbopen(dbp, name, 0, __db_omode("rw----"), meta_pgno)) == 0) {
- /*
- * Verify that we are opening the same file that we were
- * referring to when we wrote this log record.
- */
- if (meta_pgno != PGNO_BASE_MD &&
- __log_check_master(dbenv, uid, name) != 0)
- goto not_right;
- if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) {
- memset(zeroid, 0, DB_FILE_ID_LEN);
- if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
- goto not_right;
- memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
- }
- if (IS_RECOVERING(dbenv)) {
- (void)log_register(dbp->dbenv, dbp, name);
- (void)__log_add_logid(dbenv, lp, dbp, ndx);
- }
- return (0);
- }
-
-not_right:
- (void)dbp->close(dbp, 0);
- (void)__log_add_logid(dbenv, lp, NULL, ndx);
-
- return (ENOENT);
-}
-
-static int
-__log_check_master(dbenv, uid, name)
- DB_ENV *dbenv;
- u_int8_t *uid;
- char *name;
-{
- DB *dbp;
- int ret;
-
- ret = 0;
- if ((ret = db_create(&dbp, dbenv, 0)) != 0)
- return (ret);
- dbp->type = DB_BTREE;
- ret = __db_dbopen(dbp, name, 0, __db_omode("rw----"), PGNO_BASE_MD);
-
- if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
- ret = EINVAL;
-
- (void) dbp->close(dbp, 0);
- return (ret);
-}
-
-/*
- * __log_add_logid --
- * Adds a DB entry to the log's DB entry table.
- *
- * PUBLIC: int __log_add_logid __P((DB_ENV *, DB_LOG *, DB *, int32_t));
- */
-int
-__log_add_logid(dbenv, logp, dbp, ndx)
- DB_ENV *dbenv;
- DB_LOG *logp;
- DB *dbp;
- int32_t ndx;
-{
- DB *dbtmp;
- int32_t i;
- int ret;
-
- ret = 0;
-
- MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
-
- /*
- * Check if we need to grow the table. Note, ndx is 0-based (the
- * index into the DB entry table) an dbentry_cnt is 1-based, the
- * number of available slots.
- */
- if (logp->dbentry_cnt <= ndx) {
- if ((ret = __os_realloc(dbenv,
- (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
- NULL, &logp->dbentry)) != 0)
- goto err;
-
- /*
- * We have moved the head of the queue.
- * Fix up the queue header of an empty queue or the previous
- * pointer of the first element.
- */
- for (i = 0; i < logp->dbentry_cnt; i++) {
- if ((dbtmp =
- TAILQ_FIRST(&logp->dbentry[i].dblist)) == NULL)
- TAILQ_INIT(&logp->dbentry[i].dblist);
- else
- TAILQ_REINSERT_HEAD(
- &logp->dbentry[i].dblist, dbtmp, links);
- }
-
- /* Initialize the new entries. */
- for (i = logp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) {
- logp->dbentry[i].count = 0;
- TAILQ_INIT(&logp->dbentry[i].dblist);
- logp->dbentry[i].deleted = 0;
- logp->dbentry[i].refcount = 0;
- }
-
- logp->dbentry_cnt = i;
- }
-
- if (logp->dbentry[ndx].deleted == 0 &&
- TAILQ_FIRST(&logp->dbentry[ndx].dblist) == NULL) {
- logp->dbentry[ndx].count = 0;
- if (dbp != NULL)
- TAILQ_INSERT_HEAD(&logp->dbentry[ndx].dblist,
- dbp, links);
- logp->dbentry[ndx].deleted = dbp == NULL;
- logp->dbentry[ndx].refcount = 1;
- } else if (!F_ISSET(logp, DBLOG_RECOVER)) {
- if (dbp != NULL)
- TAILQ_INSERT_HEAD(&logp->dbentry[ndx].dblist,
- dbp, links);
- logp->dbentry[ndx].refcount++;
- }
-
-err: MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
- return (ret);
-}
-
-/*
- * __db_fileid_to_db --
- * Return the DB corresponding to the specified fileid.
- *
- * PUBLIC: int __db_fileid_to_db __P((DB_ENV *, DB **, int32_t, int));
- */
-int
-__db_fileid_to_db(dbenv, dbpp, ndx, inc)
- DB_ENV *dbenv;
- DB **dbpp;
- int32_t ndx;
- int inc;
-{
- DB_LOG *logp;
- DB *dbp;
- FNAME *fname;
- int ret;
- char *name;
-
- ret = 0;
- logp = dbenv->lg_handle;
-
- MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
-
- /*
- * Under XA, a process different than the one issuing DB operations
- * may abort a transaction. In this case, recovery routines are run
- * by a process that does not necessarily have the file open, so we
- * we must open the file explicitly.
- */
- if (ndx >= logp->dbentry_cnt ||
- (!logp->dbentry[ndx].deleted &&
- (dbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) == NULL)) {
- if (F_ISSET(logp, DBLOG_RECOVER)) {
- ret = ENOENT;
- goto err;
- }
- if (__log_lid_to_fname(logp, ndx, &fname) != 0) {
- /* Couldn't find entry; this is a fatal error. */
- __db_err(dbenv, "Missing log fileid entry");
- ret = EINVAL;
- goto err;
- }
- name = R_ADDR(&logp->reginfo, fname->name_off);
-
- /*
- * __log_do_open is called without protection of the
- * log thread lock.
- */
- MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
-
- /*
- * At this point, we are not holding the thread lock, so exit
- * directly instead of going through the exit code at the
- * bottom. If the __log_do_open succeeded, then we don't need
- * to do any of the remaining error checking at the end of this
- * routine.
- */
- if ((ret = __log_do_open(dbenv, logp,
- fname->ufid, name, fname->s_type,
- ndx, fname->meta_pgno)) != 0)
- return (ret);
-
- *dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
- return (0);
- }
-
- /*
- * Return DB_DELETED if the file has been deleted (it's not an error).
- */
- if (logp->dbentry[ndx].deleted) {
- ret = DB_DELETED;
- if (inc)
- logp->dbentry[ndx].count++;
- goto err;
- }
-
- /*
- * Otherwise return 0, but if we don't have a corresponding DB, it's
- * an error.
- */
- if ((*dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) == NULL)
- ret = ENOENT;
-
-err: MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
- return (ret);
-}
-
-/*
- * __log_close_files --
- * Close files that were opened by the recovery daemon. We sync the
- * file, unless its mpf pointer has been NULLed by a db_remove or
- * db_rename. We may not have flushed the log_register record that
- * closes the file.
- *
- * PUBLIC: void __log_close_files __P((DB_ENV *));
- */
-void
-__log_close_files(dbenv)
- DB_ENV *dbenv;
-{
- DB_ENTRY *dbe;
- DB_LOG *logp;
- DB *dbp;
- int32_t i;
-
- logp = dbenv->lg_handle;
- MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
- for (i = 0; i < logp->dbentry_cnt; i++) {
- dbe = &logp->dbentry[i];
- while ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
- (void)log_unregister(dbenv, dbp);
- TAILQ_REMOVE(&dbe->dblist, dbp, links);
- (void)dbp->close(dbp, dbp->mpf == NULL ? DB_NOSYNC : 0);
- }
- dbe->deleted = 0;
- dbe->refcount = 0;
- }
- MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
-}
-
-/*
- * __log_rem_logid
- * Remove an entry from the log table. Find the appropriate DB and
- * unlink it from the linked list off the table. If the DB is NULL, treat
- * this as a simple refcount decrement.
- *
- * PUBLIC: void __log_rem_logid __P((DB_LOG *, DB *, int32_t));
- */
-void
-__log_rem_logid(logp, dbp, ndx)
- DB_LOG *logp;
- DB *dbp;
- int32_t ndx;
-{
- DB *xdbp;
-
- MUTEX_THREAD_LOCK(logp->dbenv, logp->mutexp);
- if (--logp->dbentry[ndx].refcount == 0) {
- TAILQ_INIT(&logp->dbentry[ndx].dblist);
- logp->dbentry[ndx].deleted = 0;
- } else if (dbp != NULL)
- for (xdbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
- xdbp != NULL;
- xdbp = TAILQ_NEXT(xdbp, links))
- if (xdbp == dbp) {
- TAILQ_REMOVE(&logp->dbentry[ndx].dblist,
- xdbp, links);
- break;
- }
-
- MUTEX_THREAD_UNLOCK(logp->dbenv, logp->mutexp);
-}
-
-/*
- * __log_lid_to_fname --
- * Traverse the shared-memory region looking for the entry that
- * matches the passed log fileid. Returns 0 on success; -1 on error.
- * PUBLIC: int __log_lid_to_fname __P((DB_LOG *, int32_t, FNAME **));
- */
-int
-__log_lid_to_fname(dblp, lid, fnamep)
- DB_LOG *dblp;
- int32_t lid;
- FNAME **fnamep;
-{
- FNAME *fnp;
- LOG *lp;
-
- lp = dblp->reginfo.primary;
-
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
- if (fnp->ref == 0) /* Entry not in use. */
- continue;
- if (fnp->id == lid) {
- *fnamep = fnp;
- return (0);
- }
- }
- return (-1);
-}
diff --git a/bdb/log/log_register.c b/bdb/log/log_register.c
deleted file mode 100644
index 1e0e523d8b9..00000000000
--- a/bdb/log/log_register.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: log_register.c,v 11.35 2001/01/10 16:04:19 bostic Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <string.h>
-#endif
-
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
-#include "db_int.h"
-#include "log.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
-
-/*
- * log_register --
- * Register a file name.
- */
-int
-log_register(dbenv, dbp, name)
- DB_ENV *dbenv;
- DB *dbp;
- const char *name;
-{
- DBT fid_dbt, r_name;
- DB_LOG *dblp;
- DB_LSN r_unused;
- FNAME *found_fnp, *fnp, *recover_fnp, *reuse_fnp;
- LOG *lp;
- size_t len;
- int32_t maxid;
- int inserted, ok, ret;
- void *namep;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_register(dbenv, dbp, name));
-#endif
-
- PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
-
- dblp = dbenv->lg_handle;
- lp = dblp->reginfo.primary;
- fnp = reuse_fnp = NULL;
- inserted = ret = 0;
- namep = NULL;
-
- /* Check the arguments. */
- if (dbp->type != DB_BTREE && dbp->type != DB_QUEUE &&
- dbp->type != DB_HASH && dbp->type != DB_RECNO) {
- __db_err(dbenv, "log_register: unknown DB file type");
- return (EINVAL);
- }
-
- R_LOCK(dbenv, &dblp->reginfo);
-
- /*
- * See if we've already got this file in the log, finding the
- * (maximum+1) in-use file id and some available file id (if we
- * find an available fid, we'll use it, else we'll have to allocate
- * one after the maximum that we found).
- */
- ok = 0;
- found_fnp = recover_fnp = NULL;
- for (maxid = 0, fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
- if (F_ISSET(dblp, DBLOG_RECOVER) && fnp->id == dbp->log_fileid)
- recover_fnp = fnp;
- if (fnp->ref == 0) { /* Entry is not in use. */
- if (reuse_fnp == NULL)
- reuse_fnp = fnp;
- continue;
- }
- if (memcmp(dbp->fileid, fnp->ufid, DB_FILE_ID_LEN) == 0) {
- if (fnp->meta_pgno == 0) {
- if (fnp->locked == 1) {
- __db_err(dbenv, "File is locked");
- return (EINVAL);
- }
- if (found_fnp != NULL) {
- fnp = found_fnp;
- goto found;
- }
- ok = 1;
- }
- if (dbp->meta_pgno == fnp->meta_pgno) {
- if (F_ISSET(dblp, DBLOG_RECOVER)) {
- if (fnp->id != dbp->log_fileid) {
- /*
- * If we are in recovery, there
- * is only one dbp on the list.
- * If the refcount goes to 0,
- * we will clear the list. If
- * it doesn't, we want to leave
- * the dbp where it is, so
- * passing a NULL to rem_logid
- * is correct.
- */
- __log_rem_logid(dblp,
- NULL, fnp->id);
- if (recover_fnp != NULL)
- break;
- continue;
- }
- fnp->ref = 1;
- goto found;
- }
- ++fnp->ref;
- if (ok)
- goto found;
- found_fnp = fnp;
- }
- }
- if (maxid <= fnp->id)
- maxid = fnp->id + 1;
- }
- if ((fnp = found_fnp) != NULL)
- goto found;
-
- /* Fill in fnp structure. */
- if (recover_fnp != NULL) /* This has the right number */
- fnp = recover_fnp;
- else if (reuse_fnp != NULL) /* Reuse existing one. */
- fnp = reuse_fnp;
- else { /* Allocate a new one. */
- if ((ret = __db_shalloc(dblp->reginfo.addr,
- sizeof(FNAME), 0, &fnp)) != 0)
- goto mem_err;
- fnp->id = maxid;
- }
-
- if (F_ISSET(dblp, DBLOG_RECOVER))
- fnp->id = dbp->log_fileid;
-
- fnp->ref = 1;
- fnp->locked = 0;
- fnp->s_type = dbp->type;
- memcpy(fnp->ufid, dbp->fileid, DB_FILE_ID_LEN);
- fnp->meta_pgno = dbp->meta_pgno;
-
- if (name != NULL) {
- len = strlen(name) + 1;
- if ((ret =
- __db_shalloc(dblp->reginfo.addr, len, 0, &namep)) != 0) {
-mem_err: __db_err(dbenv,
- "Unable to allocate memory to register %s", name);
- goto err;
- }
- fnp->name_off = R_OFFSET(&dblp->reginfo, namep);
- memcpy(namep, name, len);
- } else
- fnp->name_off = INVALID_ROFF;
-
- /* Only do the insert if we allocated a new fnp. */
- if (reuse_fnp == NULL && recover_fnp == NULL)
- SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
- inserted = 1;
-
- /* Log the registry. */
- if (!F_ISSET(dblp, DBLOG_RECOVER)) {
- /*
- * We allow logging on in-memory databases, so the name here
- * could be NULL.
- */
- if (name != NULL) {
- r_name.data = (void *)name;
- r_name.size = strlen(name) + 1;
- }
- memset(&fid_dbt, 0, sizeof(fid_dbt));
- fid_dbt.data = dbp->fileid;
- fid_dbt.size = DB_FILE_ID_LEN;
- if ((ret = __log_register_log(dbenv, NULL, &r_unused,
- 0, LOG_OPEN, name == NULL ? NULL : &r_name,
- &fid_dbt, fnp->id, dbp->type, dbp->meta_pgno)) != 0)
- goto err;
- }
-
-found: /*
- * If we found the entry in the shared area, then the file is
- * already open, so there is no need to log the open. We only
- * log the open and closes on the first open and last close.
- */
- if (!F_ISSET(dblp, DBLOG_RECOVER) &&
- (ret = __log_add_logid(dbenv, dblp, dbp, fnp->id)) != 0)
- goto err;
-
- if (!F_ISSET(dblp, DBLOG_RECOVER))
- dbp->log_fileid = fnp->id;
-
- if (0) {
-err: if (inserted)
- SH_TAILQ_REMOVE(&lp->fq, fnp, q, __fname);
- if (namep != NULL)
- __db_shalloc_free(dblp->reginfo.addr, namep);
- if (fnp != NULL)
- __db_shalloc_free(dblp->reginfo.addr, fnp);
- }
-
- R_UNLOCK(dbenv, &dblp->reginfo);
-
- return (ret);
-}
-
-/*
- * log_unregister --
- * Discard a registered file name.
- */
-int
-log_unregister(dbenv, dbp)
- DB_ENV *dbenv;
- DB *dbp;
-{
- int ret;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_unregister(dbenv, dbp));
-#endif
-
- PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG);
-
- ret = __log_filelist_update(dbenv, dbp, dbp->log_fileid, NULL, NULL);
- dbp->log_fileid = DB_LOGFILEID_INVALID;
- return (ret);
-}
-
-/*
- * PUBLIC: int __log_filelist_update
- * PUBLIC: __P((DB_ENV *, DB *, int32_t, const char *, int *));
- *
- * Utility player for updating and logging the file list. Called
- * for 3 reasons:
- * 1) mark file closed: newname == NULL.
- * 2) change filename: newname != NULL.
- * 3) from recovery to verify & change filename if necessary, set != NULL.
- */
-int
-__log_filelist_update(dbenv, dbp, fid, newname, set)
- DB_ENV *dbenv;
- DB *dbp;
- int32_t fid;
- const char *newname;
- int *set;
-{
- DBT fid_dbt, r_name;
- DB_LOG *dblp;
- DB_LSN r_unused;
- FNAME *fnp;
- LOG *lp;
- u_int32_t len, newlen;
- int ret;
- void *namep;
-
- ret = 0;
- dblp = dbenv->lg_handle;
- lp = dblp->reginfo.primary;
-
- R_LOCK(dbenv, &dblp->reginfo);
-
- /* Find the entry in the log. */
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname))
- if (fid == fnp->id)
- break;
- if (fnp == NULL) {
- __db_err(dbenv, "log_unregister: non-existent file id");
- ret = EINVAL;
- goto ret1;
- }
-
- /*
- * Log the unregistry only if this is the last one and we are
- * really closing the file or if this is an abort of a created
- * file and we need to make sure there is a record in the log.
- */
- namep = NULL;
- len = 0;
- if (fnp->name_off != INVALID_ROFF) {
- namep = R_ADDR(&dblp->reginfo, fnp->name_off);
- len = strlen(namep) + 1;
- }
- if (!F_ISSET(dblp, DBLOG_RECOVER) && fnp->ref == 1) {
- if (namep != NULL) {
- memset(&r_name, 0, sizeof(r_name));
- r_name.data = namep;
- r_name.size = len;
- }
- memset(&fid_dbt, 0, sizeof(fid_dbt));
- fid_dbt.data = fnp->ufid;
- fid_dbt.size = DB_FILE_ID_LEN;
- if ((ret = __log_register_log(dbenv, NULL, &r_unused,
- 0, LOG_CLOSE,
- fnp->name_off == INVALID_ROFF ? NULL : &r_name,
- &fid_dbt, fid, fnp->s_type, fnp->meta_pgno))
- != 0)
- goto ret1;
- }
-
- /*
- * If we are changing the name we must log this fact.
- */
- if (newname != NULL) {
- DB_ASSERT(fnp->ref == 1);
- newlen = strlen(newname) + 1;
- if (!F_ISSET(dblp, DBLOG_RECOVER)) {
- r_name.data = (void *) newname;
- r_name.size = newlen;
- if ((ret = __log_register_log(dbenv,
- NULL, &r_unused, 0, LOG_OPEN, &r_name, &fid_dbt,
- fnp->id, fnp->s_type, fnp->meta_pgno)) != 0)
- goto ret1;
- }
-
- /*
- * Check to see if the name is already correct.
- */
- if (set != NULL) {
- if (len != newlen || memcmp(namep, newname, len) != 0)
- *set = 1;
- else {
- *set = 0;
- goto ret1;
- }
- }
-
- /*
- * Change the name, realloc memory if necessary
- */
- if (len < newlen) {
- __db_shalloc_free(dblp->reginfo.addr,
- R_ADDR(&dblp->reginfo, fnp->name_off));
- if ((ret = __db_shalloc(
- dblp->reginfo.addr, newlen, 0, &namep)) != 0) {
- __db_err(dbenv,
- "Unable to allocate memory to register %s",
- newname);
- goto ret1;
- }
- fnp->name_off = R_OFFSET(&dblp->reginfo, namep);
- } else
- namep = R_ADDR(&dblp->reginfo, fnp->name_off);
- memcpy(namep, newname, newlen);
- } else {
-
- /*
- * If more than 1 reference, just decrement the reference
- * and return. Otherwise, free the name if one exists.
- */
- DB_ASSERT(fnp->ref >= 1);
- --fnp->ref;
- if (fnp->ref == 0) {
- if (fnp->name_off != INVALID_ROFF)
- __db_shalloc_free(dblp->reginfo.addr,
- R_ADDR(&dblp->reginfo, fnp->name_off));
- fnp->name_off = INVALID_ROFF;
- }
-
- /*
- * Remove from the process local table. If this
- * operation is taking place during recovery, then
- * the logid was never added to the table, so do not remove it.
- */
- if (!F_ISSET(dblp, DBLOG_RECOVER))
- __log_rem_logid(dblp, dbp, fid);
- }
-
-ret1: R_UNLOCK(dbenv, &dblp->reginfo);
- return (ret);
-}
-
-/*
- * __log_file_lock -- lock a file for single access
- * This only works if logging is on.
- *
- * PUBLIC: int __log_file_lock __P((DB *));
- */
-int
-__log_file_lock(dbp)
- DB *dbp;
-{
- DB_ENV *dbenv;
- DB_LOG *dblp;
- FNAME *fnp;
- LOG *lp;
- int ret;
-
- dbenv = dbp->dbenv;
- dblp = dbenv->lg_handle;
- lp = dblp->reginfo.primary;
-
- ret = 0;
- R_LOCK(dbenv, &dblp->reginfo);
-
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
- if (fnp->ref == 0)
- continue;
-
- if (!memcmp(dbp->fileid, fnp->ufid, DB_FILE_ID_LEN)) {
- if (fnp->meta_pgno == 0) {
- if (fnp->ref != 1)
- goto err;
-
- fnp->locked = 1;
- } else {
-err: __db_err(dbp->dbenv, "File is open");
- ret = EINVAL;
- goto done;
- }
-
- }
- }
-done: R_UNLOCK(dbenv, &dblp->reginfo);
- return (ret);
-}
diff --git a/bdb/mp/Design b/bdb/mp/Design
deleted file mode 100644
index 1b26aae6cba..00000000000
--- a/bdb/mp/Design
+++ /dev/null
@@ -1,52 +0,0 @@
-$Id: Design,v 11.2 1999/11/21 23:08:27 bostic Exp $
-
-There are three ways we do locking in the mpool code:
-
-Locking a handle mutex to provide concurrency for DB_THREAD operations.
-Locking the region mutex to provide mutual exclusion while reading and
- writing structures in the shared region.
-Locking buffer header mutexes during I/O.
-
-The first will not be further described here. We use the shared mpool
-region lock to provide mutual exclusion while reading/modifying all of
-the data structures, including the buffer headers. We use a per-buffer
-header lock to wait on buffer I/O. The order of locking is as follows:
-
-Searching for a buffer:
- Acquire the region lock.
- Find the buffer header.
- Increment the reference count (guarantee the buffer stays).
- While the BH_LOCKED flag is set (I/O is going on) {
- Release the region lock.
- Explicitly yield the processor if it's not the first pass
- through this loop, otherwise, we can simply spin because
- we'll be simply switching between the two locks.
- Request the buffer lock.
- The I/O will complete...
- Acquire the buffer lock.
- Release the buffer lock.
- Acquire the region lock.
- }
- Return the buffer.
-
-Reading/writing a buffer:
- Acquire the region lock.
- Find/create the buffer header.
- If reading, increment the reference count (guarantee the buffer stays).
- Set the BH_LOCKED flag.
- Acquire the buffer lock (guaranteed not to block).
- Release the region lock.
- Do the I/O and/or initialize the buffer contents.
- Release the buffer lock.
- At this point, the buffer lock is available, but the logical
- operation (flagged by BH_LOCKED) is not yet completed. For
- this reason, among others, threads checking the BH_LOCKED flag
- must loop around their test.
- Acquire the region lock.
- Clear the BH_LOCKED flag.
- Release the region lock.
- Return/discard the buffer.
-
-Pointers to DB_MPOOL, MPOOL, DB_MPOOLFILE and MPOOLFILE structures are
-not reacquired when a region lock is reacquired because they couldn't
-have been closed/discarded and because they never move in memory.
diff --git a/bdb/mp/mp_alloc.c b/bdb/mp/mp_alloc.c
index 731f569f57f..96dd612d7ba 100644
--- a/bdb/mp/mp_alloc.c
+++ b/bdb/mp/mp_alloc.c
@@ -1,22 +1,31 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_alloc.c,v 11.7 2000/04/20 21:14:18 bostic Exp $";
+static const char revid[] = "$Id: mp_alloc.c,v 11.31 2002/08/14 17:21:37 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <string.h>
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
+
+typedef struct {
+ DB_MPOOL_HASH *bucket;
+ u_int32_t priority;
+} HS;
+
+static void __memp_bad_buffer __P((DB_MPOOL_HASH *));
+static void __memp_reset_lru __P((DB_ENV *, REGINFO *, MPOOL *));
/*
* __memp_alloc --
@@ -34,14 +43,32 @@ __memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
roff_t *offsetp;
void *retp;
{
- BH *bhp, *nbhp;
+ BH *bhp;
+ DB_ENV *dbenv;
+ DB_MPOOL_HASH *dbht, *hp, *hp_end, *hp_tmp;
+ DB_MUTEX *mutexp;
MPOOL *c_mp;
MPOOLFILE *bh_mfp;
- size_t total;
- int nomore, restart, ret, wrote;
+ size_t freed_space;
+ u_int32_t buckets, buffers, high_priority, max_na, priority;
+ int aggressive, ret;
void *p;
+ dbenv = dbmp->dbenv;
c_mp = memreg->primary;
+ dbht = R_ADDR(memreg, c_mp->htab);
+ hp_end = &dbht[c_mp->htab_buckets];
+
+ buckets = buffers = 0;
+ aggressive = 0;
+
+ c_mp->stat.st_alloc++;
+
+ /*
+ * Get aggressive if we've tried to flush the number of pages as are
+ * in the system without finding space.
+ */
+ max_na = 5 * c_mp->htab_buckets;
/*
* If we're allocating a buffer, and the one we're discarding is the
@@ -53,100 +80,363 @@ __memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
if (mfp != NULL)
len = (sizeof(BH) - sizeof(u_int8_t)) + mfp->stat.st_pagesize;
- nomore = 0;
+ R_LOCK(dbenv, memreg);
+
+ /*
+ * On every buffer allocation we update the buffer generation number
+ * and check for wraparound.
+ */
+ if (++c_mp->lru_count == UINT32_T_MAX)
+ __memp_reset_lru(dbenv, memreg, c_mp);
+
+ /*
+ * Anything newer than 1/10th of the buffer pool is ignored during
+ * allocation (unless allocation starts failing).
+ */
+ DB_ASSERT(c_mp->lru_count > c_mp->stat.st_pages / 10);
+ high_priority = c_mp->lru_count - c_mp->stat.st_pages / 10;
+
+ /*
+ * First we try to allocate from free memory. If that fails, scan the
+ * buffer pool to find buffers with low priorities. We consider small
+ * sets of hash buckets each time to limit the amount of work needing
+ * to be done. This approximates LRU, but not very well. We either
+ * find a buffer of the same size to use, or we will free 3 times what
+ * we need in the hopes it will coalesce into a contiguous chunk of the
+ * right size. In the latter case we branch back here and try again.
+ */
alloc: if ((ret = __db_shalloc(memreg->addr, len, MUTEX_ALIGN, &p)) == 0) {
- if (offsetp != NULL)
+ if (mfp != NULL)
+ c_mp->stat.st_pages++;
+ R_UNLOCK(dbenv, memreg);
+
+found: if (offsetp != NULL)
*offsetp = R_OFFSET(memreg, p);
*(void **)retp = p;
+
+ /*
+ * Update the search statistics.
+ *
+ * We're not holding the region locked here, these statistics
+ * can't be trusted.
+ */
+ if (buckets != 0) {
+ if (buckets > c_mp->stat.st_alloc_max_buckets)
+ c_mp->stat.st_alloc_max_buckets = buckets;
+ c_mp->stat.st_alloc_buckets += buckets;
+ }
+ if (buffers != 0) {
+ if (buffers > c_mp->stat.st_alloc_max_pages)
+ c_mp->stat.st_alloc_max_pages = buffers;
+ c_mp->stat.st_alloc_pages += buffers;
+ }
return (0);
}
- if (nomore) {
- __db_err(dbmp->dbenv,
- "Unable to allocate %lu bytes from mpool shared region: %s\n",
- (u_long)len, db_strerror(ret));
- return (ret);
- }
-retry: /* Find a buffer we can flush; pure LRU. */
- restart = total = 0;
- for (bhp =
- SH_TAILQ_FIRST(&c_mp->bhq, __bh); bhp != NULL; bhp = nbhp) {
- nbhp = SH_TAILQ_NEXT(bhp, q, __bh);
+ /*
+ * We re-attempt the allocation every time we've freed 3 times what
+ * we need. Reset our free-space counter.
+ */
+ freed_space = 0;
- /* Ignore pinned or locked (I/O in progress) buffers. */
- if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED))
+ /*
+ * Walk the hash buckets and find the next two with potentially useful
+ * buffers. Free the buffer with the lowest priority from the buckets'
+ * chains.
+ */
+ for (hp_tmp = NULL;;) {
+ /* Check for wrap around. */
+ hp = &dbht[c_mp->last_checked++];
+ if (hp >= hp_end) {
+ c_mp->last_checked = 0;
+
+ /*
+ * If we've gone through all of the hash buckets, try
+ * an allocation. If the cache is small, the old page
+ * size is small, and the new page size is large, we
+ * might have freed enough memory (but not 3 times the
+ * memory).
+ */
+ goto alloc;
+ }
+
+ /*
+ * Skip empty buckets.
+ *
+ * We can check for empty buckets before locking as we
+ * only care if the pointer is zero or non-zero.
+ */
+ if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL)
continue;
- /* Find the associated MPOOLFILE. */
- bh_mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
+ /*
+ * The failure mode is when there are too many buffers we can't
+ * write or there's not enough memory in the system. We don't
+ * have a metric for deciding if allocation has no possible way
+ * to succeed, so we don't ever fail, we assume memory will be
+ * available if we wait long enough.
+ *
+ * Get aggressive if we've tried to flush 5 times the number of
+ * hash buckets as are in the system -- it's possible we have
+ * been repeatedly trying to flush the same buffers, although
+ * it's unlikely. Aggressive means:
+ *
+ * a: set a flag to attempt to flush high priority buffers as
+ * well as other buffers.
+ * b: sync the mpool to force out queue extent pages. While we
+ * might not have enough space for what we want and flushing
+ * is expensive, why not?
+ * c: sleep for a second -- hopefully someone else will run and
+ * free up some memory. Try to allocate memory too, in case
+ * the other thread returns its memory to the region.
+ * d: look at a buffer in every hash bucket rather than choose
+ * the more preferable of two.
+ *
+ * !!!
+ * This test ignores pathological cases like no buffers in the
+ * system -- that shouldn't be possible.
+ */
+ if ((++buckets % max_na) == 0) {
+ aggressive = 1;
- /* Write the page if it's dirty. */
- if (F_ISSET(bhp, BH_DIRTY)) {
- ++bhp->ref;
- if ((ret = __memp_bhwrite(dbmp,
- bh_mfp, bhp, &restart, &wrote)) != 0)
- return (ret);
- --bhp->ref;
+ R_UNLOCK(dbenv, memreg);
- /*
- * Another process may have acquired this buffer and
- * incremented the ref count after we wrote it.
- */
- if (bhp->ref != 0)
- goto retry;
+ (void)__memp_sync_int(
+ dbenv, NULL, 0, DB_SYNC_ALLOC, NULL);
+
+ (void)__os_sleep(dbenv, 1, 0);
+
+ R_LOCK(dbenv, memreg);
+ goto alloc;
+ }
+
+ if (!aggressive) {
+ /* Skip high priority buckets. */
+ if (hp->hash_priority > high_priority)
+ continue;
/*
- * If we wrote the page, continue and free the buffer.
- * We don't have to rewalk the list to acquire the
- * buffer because it was never available for any other
- * process to modify it.
- *
- * If we didn't write the page, but we discarded and
- * reacquired the region lock, restart the list walk.
- *
- * If we neither wrote the buffer nor discarded the
- * region lock, continue down the buffer list.
+ * Find two buckets and select the one with the lowest
+ * priority. Performance testing shows that looking
+ * at two improves the LRUness and looking at more only
+ * does a little better.
*/
- if (wrote)
- ++c_mp->stat.st_rw_evict;
- else {
- if (restart)
- goto retry;
+ if (hp_tmp == NULL) {
+ hp_tmp = hp;
continue;
}
+ if (hp->hash_priority > hp_tmp->hash_priority)
+ hp = hp_tmp;
+ hp_tmp = NULL;
+ }
+
+ /* Remember the priority of the buffer we're looking for. */
+ priority = hp->hash_priority;
+
+ /* Unlock the region and lock the hash bucket. */
+ R_UNLOCK(dbenv, memreg);
+ mutexp = &hp->hash_mutex;
+ MUTEX_LOCK(dbenv, mutexp);
+
+#ifdef DIAGNOSTIC
+ __memp_check_order(hp);
+#endif
+ /*
+ * The lowest priority page is first in the bucket, as they are
+ * maintained in sorted order.
+ *
+ * The buffer may have been freed or its priority changed while
+ * we switched from the region lock to the hash lock. If so,
+ * we have to restart. We will still take the first buffer on
+ * the bucket's list, though, if it has a low enough priority.
+ */
+ if ((bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) == NULL ||
+ bhp->ref != 0 || bhp->priority > priority)
+ goto next_hb;
+
+ buffers++;
+
+ /* Find the associated MPOOLFILE. */
+ bh_mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
+
+ /* If the page is dirty, pin it and write it. */
+ ret = 0;
+ if (F_ISSET(bhp, BH_DIRTY)) {
+ ++bhp->ref;
+ ret = __memp_bhwrite(dbmp, hp, bh_mfp, bhp, 0);
+ --bhp->ref;
+ if (ret == 0)
+ ++c_mp->stat.st_rw_evict;
} else
++c_mp->stat.st_ro_evict;
/*
+ * If a write fails for any reason, we can't proceed.
+ *
+ * We released the hash bucket lock while doing I/O, so another
+ * thread may have acquired this buffer and incremented the ref
+ * count after we wrote it, in which case we can't have it.
+ *
+ * If there's a write error, avoid selecting this buffer again
+ * by making it the bucket's least-desirable buffer.
+ */
+ if (ret != 0 || bhp->ref != 0) {
+ if (ret != 0 && aggressive)
+ __memp_bad_buffer(hp);
+ goto next_hb;
+ }
+
+ /*
* Check to see if the buffer is the size we're looking for.
- * If it is, simply reuse it.
+ * If so, we can simply reuse it. Else, free the buffer and
+ * its space and keep looking.
*/
if (mfp != NULL &&
mfp->stat.st_pagesize == bh_mfp->stat.st_pagesize) {
- __memp_bhfree(dbmp, bhp, 0);
+ __memp_bhfree(dbmp, hp, bhp, 0);
- if (offsetp != NULL)
- *offsetp = R_OFFSET(memreg, bhp);
- *(void **)retp = bhp;
- return (0);
+ p = bhp;
+ goto found;
}
- /* Note how much space we've freed, and free the buffer. */
- total += __db_shsizeof(bhp);
- __memp_bhfree(dbmp, bhp, 1);
+ freed_space += __db_shsizeof(bhp);
+ __memp_bhfree(dbmp, hp, bhp, 1);
/*
- * Retry as soon as we've freed up sufficient space. If we
- * have to coalesce of memory to satisfy the request, don't
- * try until it's likely (possible?) that we'll succeed.
+ * Unlock this hash bucket and re-acquire the region lock. If
+ * we're reaching here as a result of calling memp_bhfree, the
+ * hash bucket lock has already been discarded.
*/
- if (total >= 3 * len)
+ if (0) {
+next_hb: MUTEX_UNLOCK(dbenv, mutexp);
+ }
+ R_LOCK(dbenv, memreg);
+
+ /*
+ * Retry the allocation as soon as we've freed up sufficient
+ * space. We're likely to have to coalesce of memory to
+ * satisfy the request, don't try until it's likely (possible?)
+ * we'll succeed.
+ */
+ if (freed_space >= 3 * len)
goto alloc;
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * __memp_bad_buffer --
+ * Make the first buffer in a hash bucket the least desirable buffer.
+ */
+static void
+__memp_bad_buffer(hp)
+ DB_MPOOL_HASH *hp;
+{
+ BH *bhp, *t_bhp;
+ u_int32_t priority;
+
+ /* Remove the first buffer from the bucket. */
+ bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+ SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
+
+ /*
+ * Find the highest priority buffer in the bucket. Buffers are
+ * sorted by priority, so it's the last one in the bucket.
+ *
+ * XXX
+ * Should use SH_TAILQ_LAST, but I think that macro is broken.
+ */
+ priority = bhp->priority;
+ for (t_bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+ t_bhp != NULL; t_bhp = SH_TAILQ_NEXT(t_bhp, hq, __bh))
+ priority = t_bhp->priority;
+
+ /*
+ * Set our buffer's priority to be just as bad, and append it to
+ * the bucket.
+ */
+ bhp->priority = priority;
+ SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
- /* Restart the walk if we discarded the region lock. */
- if (restart)
- goto retry;
+ /* Reset the hash bucket's priority. */
+ hp->hash_priority = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
+}
+
+/*
+ * __memp_reset_lru --
+ * Reset the cache LRU counter.
+ */
+static void
+__memp_reset_lru(dbenv, memreg, c_mp)
+ DB_ENV *dbenv;
+ REGINFO *memreg;
+ MPOOL *c_mp;
+{
+ BH *bhp;
+ DB_MPOOL_HASH *hp;
+ int bucket;
+
+ /*
+ * Update the counter so all future allocations will start at the
+ * bottom.
+ */
+ c_mp->lru_count -= MPOOL_BASE_DECREMENT;
+
+ /* Release the region lock. */
+ R_UNLOCK(dbenv, memreg);
+
+ /* Adjust the priority of every buffer in the system. */
+ for (hp = R_ADDR(memreg, c_mp->htab),
+ bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
+ /*
+ * Skip empty buckets.
+ *
+ * We can check for empty buckets before locking as we
+ * only care if the pointer is zero or non-zero.
+ */
+ if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL)
+ continue;
+
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
+ for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+ bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+ if (bhp->priority != UINT32_T_MAX &&
+ bhp->priority > MPOOL_BASE_DECREMENT)
+ bhp->priority -= MPOOL_BASE_DECREMENT;
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
}
- nomore = 1;
- goto alloc;
+
+ /* Reacquire the region lock. */
+ R_LOCK(dbenv, memreg);
+}
+
+#ifdef DIAGNOSTIC
+/*
+ * __memp_check_order --
+ * Verify the priority ordering of a hash bucket chain.
+ *
+ * PUBLIC: #ifdef DIAGNOSTIC
+ * PUBLIC: void __memp_check_order __P((DB_MPOOL_HASH *));
+ * PUBLIC: #endif
+ */
+void
+__memp_check_order(hp)
+ DB_MPOOL_HASH *hp;
+{
+ BH *bhp;
+ u_int32_t priority;
+
+ /*
+ * Assumes the hash bucket is locked.
+ */
+ if ((bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) == NULL)
+ return;
+
+ DB_ASSERT(bhp->priority == hp->hash_priority);
+
+ for (priority = bhp->priority;
+ (bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) != NULL;
+ priority = bhp->priority)
+ DB_ASSERT(priority <= bhp->priority);
}
+#endif
diff --git a/bdb/mp/mp_bh.c b/bdb/mp/mp_bh.c
index e802b165b2d..85d15218abf 100644
--- a/bdb/mp/mp_bh.c
+++ b/bdb/mp/mp_bh.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_bh.c,v 11.25 2001/01/10 04:50:53 ubell Exp $";
+static const char revid[] = "$Id: mp_bh.c,v 11.71 2002/09/04 19:06:45 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,40 +18,41 @@ static const char revid[] = "$Id: mp_bh.c,v 11.25 2001/01/10 04:50:53 ubell Exp
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
-#include "log.h"
-#include "db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
+#include "dbinc/log.h"
+#include "dbinc/db_page.h"
+static int __memp_pgwrite
+ __P((DB_MPOOL *, DB_MPOOLFILE *, DB_MPOOL_HASH *, BH *));
static int __memp_upgrade __P((DB_MPOOL *, DB_MPOOLFILE *, MPOOLFILE *));
/*
* __memp_bhwrite --
- * Write the page associated with a given bucket header.
+ * Write the page associated with a given buffer header.
*
- * PUBLIC: int __memp_bhwrite
- * PUBLIC: __P((DB_MPOOL *, MPOOLFILE *, BH *, int *, int *));
+ * PUBLIC: int __memp_bhwrite __P((DB_MPOOL *,
+ * PUBLIC: DB_MPOOL_HASH *, MPOOLFILE *, BH *, int));
*/
int
-__memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
+__memp_bhwrite(dbmp, hp, mfp, bhp, open_extents)
DB_MPOOL *dbmp;
+ DB_MPOOL_HASH *hp;
MPOOLFILE *mfp;
BH *bhp;
- int *restartp, *wrotep;
+ int open_extents;
{
+ DB_ENV *dbenv;
DB_MPOOLFILE *dbmfp;
DB_MPREG *mpreg;
- int incremented, ret;
+ int local_open, incremented, ret;
- if (restartp != NULL)
- *restartp = 0;
- if (wrotep != NULL)
- *wrotep = 0;
- incremented = 0;
+ dbenv = dbmp->dbenv;
+ local_open = incremented = 0;
/*
- * If the file has been removed or is a closed temporary file, Jump
- * right ahead and pretend that we've found the file we want-- the
+ * If the file has been removed or is a closed temporary file, jump
+ * right ahead and pretend that we've found the file we want -- the
* page-write function knows how to handle the fact that we don't have
* (or need!) any real file descriptor information.
*/
@@ -66,52 +67,60 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
* If we find a descriptor on the file that's not open for writing, we
* try and upgrade it to make it writeable. If that fails, we're done.
*/
- MUTEX_THREAD_LOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
if (dbmfp->mfp == mfp) {
if (F_ISSET(dbmfp, MP_READONLY) &&
- __memp_upgrade(dbmp, dbmfp, mfp)) {
- MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
- return (0);
+ !F_ISSET(dbmfp, MP_UPGRADE) &&
+ (F_ISSET(dbmfp, MP_UPGRADE_FAIL) ||
+ __memp_upgrade(dbmp, dbmfp, mfp))) {
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+ return (EPERM);
}
/*
* Increment the reference count -- see the comment in
- * memp_fclose().
+ * __memp_fclose_int().
*/
++dbmfp->ref;
incremented = 1;
break;
}
- MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+
if (dbmfp != NULL)
goto found;
/*
* !!!
+ * It's the caller's choice if we're going to open extent files.
+ */
+ if (!open_extents && F_ISSET(mfp, MP_EXTENT))
+ return (EPERM);
+
+ /*
+ * !!!
* Don't try to attach to temporary files. There are two problems in
* trying to do that. First, if we have different privileges than the
* process that "owns" the temporary file, we might create the backing
* disk file such that the owning process couldn't read/write its own
- * buffers, e.g., memp_trickle() running as root creating a file owned
+ * buffers, e.g., memp_trickle running as root creating a file owned
* as root, mode 600. Second, if the temporary file has already been
* created, we don't have any way of finding out what its real name is,
* and, even if we did, it was already unlinked (so that it won't be
* left if the process dies horribly). This decision causes a problem,
* however: if the temporary file consumes the entire buffer cache,
* and the owner doesn't flush the buffers to disk, we could end up
- * with resource starvation, and the memp_trickle() thread couldn't do
+ * with resource starvation, and the memp_trickle thread couldn't do
* anything about it. That's a pretty unlikely scenario, though.
*
- * Note that we should never get here when the temporary file
- * in question has already been closed in another process, in which
- * case it should be marked MP_DEADFILE.
+ * Note we should never get here when the temporary file in question
+ * has already been closed in another process, in which case it should
+ * be marked MP_DEADFILE.
*/
- if (F_ISSET(mfp, MP_TEMP)) {
- DB_ASSERT(!F_ISSET(mfp, MP_DEADFILE));
- return (0);
- }
+ if (F_ISSET(mfp, MP_TEMP))
+ return (EPERM);
/*
* It's not a page from a file we've opened. If the file requires
@@ -120,14 +129,14 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
* nothing we can do.
*/
if (mfp->ftype != 0) {
- MUTEX_THREAD_LOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
for (mpreg = LIST_FIRST(&dbmp->dbregq);
mpreg != NULL; mpreg = LIST_NEXT(mpreg, q))
if (mpreg->ftype == mfp->ftype)
break;
- MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
if (mpreg == NULL)
- return (0);
+ return (EPERM);
}
/*
@@ -138,17 +147,24 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
* There's no negative cache, so we may repeatedly try and open files
* that we have previously tried (and failed) to open.
*/
- if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp->reginfo, mfp->path_off),
- 0, 0, mfp->stat.st_pagesize, 0, NULL, &dbmfp) != 0)
- return (0);
+ if ((ret = dbenv->memp_fcreate(dbenv, &dbmfp, 0)) != 0)
+ return (ret);
+ if ((ret = __memp_fopen_int(dbmfp, mfp,
+ R_ADDR(dbmp->reginfo, mfp->path_off),
+ 0, 0, mfp->stat.st_pagesize)) != 0) {
+ (void)dbmfp->close(dbmfp, 0);
+ return (ret);
+ }
+ local_open = 1;
-found: ret = __memp_pgwrite(dbmp, dbmfp, bhp, restartp, wrotep);
+found: ret = __memp_pgwrite(dbmp, dbmfp, hp, bhp);
- if (incremented) {
- MUTEX_THREAD_LOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+ if (incremented)
--dbmfp->ref;
- MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
- }
+ else if (local_open)
+ F_SET(dbmfp, MP_FLUSH);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
return (ret);
}
@@ -157,11 +173,12 @@ found: ret = __memp_pgwrite(dbmp, dbmfp, bhp, restartp, wrotep);
* __memp_pgread --
* Read a page from a file.
*
- * PUBLIC: int __memp_pgread __P((DB_MPOOLFILE *, BH *, int));
+ * PUBLIC: int __memp_pgread __P((DB_MPOOLFILE *, DB_MUTEX *, BH *, int));
*/
int
-__memp_pgread(dbmfp, bhp, can_create)
+__memp_pgread(dbmfp, mutexp, bhp, can_create)
DB_MPOOLFILE *dbmfp;
+ DB_MUTEX *mutexp;
BH *bhp;
int can_create;
{
@@ -169,171 +186,129 @@ __memp_pgread(dbmfp, bhp, can_create)
DB_ENV *dbenv;
DB_MPOOL *dbmp;
MPOOLFILE *mfp;
- size_t len, pagesize;
- size_t nr;
- int created, ret;
+ size_t len, nr, pagesize;
+ int ret;
dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
mfp = dbmfp->mfp;
pagesize = mfp->stat.st_pagesize;
+ /* We should never be called with a dirty or a locked buffer. */
+ DB_ASSERT(!F_ISSET(bhp, BH_DIRTY | BH_DIRTY_CREATE | BH_LOCKED));
+
+ /* Lock the buffer and swap the hash bucket lock for the buffer lock. */
F_SET(bhp, BH_LOCKED | BH_TRASH);
- MUTEX_LOCK(dbenv, &bhp->mutex, dbenv->lockfhp);
- R_UNLOCK(dbenv, dbmp->reginfo);
+ MUTEX_LOCK(dbenv, &bhp->mutex);
+ MUTEX_UNLOCK(dbenv, mutexp);
/*
* Temporary files may not yet have been created. We don't create
* them now, we create them when the pages have to be flushed.
*/
nr = 0;
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID)) {
- /*
- * Ignore read errors if we have permission to create the page.
- * Assume that the page doesn't exist, and that we'll create it
- * when we write it out.
- *
- * XXX
- * Theoretically, we could overwrite a page of data if it were
- * possible for a file to be successfully opened for reading
- * and then for the read to fail. Shouldn't ever happen, but
- * it might be worth checking to see if the offset is past the
- * known end-of-file.
- */
- db_io.fhp = &dbmfp->fh;
+ if (F_ISSET(dbmfp->fhp, DB_FH_VALID)) {
+ db_io.fhp = dbmfp->fhp;
db_io.mutexp = dbmfp->mutexp;
db_io.pagesize = db_io.bytes = pagesize;
db_io.pgno = bhp->pgno;
db_io.buf = bhp->buf;
- ret = __os_io(dbenv, &db_io, DB_IO_READ, &nr);
- } else
- ret = 0;
+ /*
+ * The page may not exist; if it doesn't, nr may well be 0,
+ * but we expect the underlying OS calls not to return an
+ * error code in this case.
+ */
+ if ((ret = __os_io(dbenv, &db_io, DB_IO_READ, &nr)) != 0)
+ goto err;
+ }
- created = 0;
if (nr < pagesize) {
- if (can_create)
- created = 1;
- else {
- /*
- * If we had a short read, ret may be 0. This may not
- * be an error -- in particular DB recovery processing
- * may request pages that have never been written to
- * disk, in which case we won't find the page. So, the
- * caller must know how to handle the error.
- */
- if (ret == 0)
- ret = EIO;
+ /*
+ * Don't output error messages for short reads. In particular,
+ * DB recovery processing may request pages never written to
+ * disk or for which only some part have been written to disk,
+ * in which case we won't find the page. The caller must know
+ * how to handle the error.
+ */
+ if (can_create == 0) {
+ ret = DB_PAGE_NOTFOUND;
goto err;
}
- }
- /*
- * Clear any bytes we didn't read that need to be cleared. If we're
- * running in diagnostic mode, smash any bytes on the page that are
- * unknown quantities for the caller.
- */
- if (nr != pagesize) {
+ /* Clear any bytes that need to be cleared. */
len = mfp->clear_len == 0 ? pagesize : mfp->clear_len;
- if (nr < len)
- memset(bhp->buf + nr, 0, len - nr);
-#ifdef DIAGNOSTIC
- if (nr > len)
- len = nr;
+ memset(bhp->buf, 0, len);
+
+#if defined(DIAGNOSTIC) || defined(UMRW)
+ /*
+ * If we're running in diagnostic mode, corrupt any bytes on
+ * the page that are unknown quantities for the caller.
+ */
if (len < pagesize)
memset(bhp->buf + len, CLEAR_BYTE, pagesize - len);
#endif
- }
+ ++mfp->stat.st_page_create;
+ } else
+ ++mfp->stat.st_page_in;
/* Call any pgin function. */
ret = mfp->ftype == 0 ? 0 : __memp_pg(dbmfp, bhp, 1);
- /* Unlock the buffer and reacquire the region lock. */
+ /* Unlock the buffer and reacquire the hash bucket lock. */
err: MUTEX_UNLOCK(dbenv, &bhp->mutex);
- R_LOCK(dbenv, dbmp->reginfo);
+ MUTEX_LOCK(dbenv, mutexp);
/*
* If no errors occurred, the data is now valid, clear the BH_TRASH
* flag; regardless, clear the lock bit and let other threads proceed.
*/
F_CLR(bhp, BH_LOCKED);
- if (ret == 0) {
+ if (ret == 0)
F_CLR(bhp, BH_TRASH);
- /* Update the statistics. */
- if (created)
- ++mfp->stat.st_page_create;
- else
- ++mfp->stat.st_page_in;
- }
-
return (ret);
}
/*
* __memp_pgwrite --
* Write a page to a file.
- *
- * PUBLIC: int __memp_pgwrite
- * PUBLIC: __P((DB_MPOOL *, DB_MPOOLFILE *, BH *, int *, int *));
*/
-int
-__memp_pgwrite(dbmp, dbmfp, bhp, restartp, wrotep)
+static int
+__memp_pgwrite(dbmp, dbmfp, hp, bhp)
DB_MPOOL *dbmp;
DB_MPOOLFILE *dbmfp;
+ DB_MPOOL_HASH *hp;
BH *bhp;
- int *restartp, *wrotep;
{
DB_ENV *dbenv;
DB_IO db_io;
DB_LSN lsn;
- MPOOL *c_mp, *mp;
MPOOLFILE *mfp;
size_t nw;
- int callpgin, dosync, ret, syncfail;
- const char *fail;
+ int callpgin, ret;
dbenv = dbmp->dbenv;
- mp = dbmp->reginfo[0].primary;
mfp = dbmfp == NULL ? NULL : dbmfp->mfp;
-
- if (restartp != NULL)
- *restartp = 0;
- if (wrotep != NULL)
- *wrotep = 0;
- callpgin = 0;
+ callpgin = ret = 0;
/*
- * Check the dirty bit -- this buffer may have been written since we
- * decided to write it.
+ * We should never be called with a clean or trash buffer.
+ * The sync code does call us with already locked buffers.
*/
- if (!F_ISSET(bhp, BH_DIRTY)) {
- if (wrotep != NULL)
- *wrotep = 1;
- return (0);
- }
-
- MUTEX_LOCK(dbenv, &bhp->mutex, dbenv->lockfhp);
+ DB_ASSERT(F_ISSET(bhp, BH_DIRTY));
+ DB_ASSERT(!F_ISSET(bhp, BH_TRASH));
/*
- * If there were two writers, we may have just been waiting while the
- * other writer completed I/O on this buffer. Check the dirty bit one
- * more time.
+ * If we have not already traded the hash bucket lock for the buffer
+ * lock, do so now.
*/
- if (!F_ISSET(bhp, BH_DIRTY)) {
- MUTEX_UNLOCK(dbenv, &bhp->mutex);
-
- if (wrotep != NULL)
- *wrotep = 1;
- return (0);
+ if (!F_ISSET(bhp, BH_LOCKED)) {
+ F_SET(bhp, BH_LOCKED);
+ MUTEX_LOCK(dbenv, &bhp->mutex);
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
}
- F_SET(bhp, BH_LOCKED);
- R_UNLOCK(dbenv, dbmp->reginfo);
-
- if (restartp != NULL)
- *restartp = 1;
-
/*
* It's possible that the underlying file doesn't exist, either
* because of an outright removal or because it was a temporary
@@ -347,155 +322,122 @@ __memp_pgwrite(dbmp, dbmfp, bhp, restartp, wrotep)
goto file_dead;
/*
- * Ensure the appropriate log records are on disk. If the page is
- * being written as part of a sync operation, the flush has already
- * been done, unless it was written by the application *after* the
- * sync was scheduled.
+ * If the page is in a file for which we have LSN information, we have
+ * to ensure the appropriate log records are on disk.
*/
- if (LOGGING_ON(dbenv) &&
- (!F_ISSET(bhp, BH_SYNC) || F_ISSET(bhp, BH_SYNC_LOGFLSH))) {
+ if (LOGGING_ON(dbenv) && mfp->lsn_off != -1) {
memcpy(&lsn, bhp->buf + mfp->lsn_off, sizeof(DB_LSN));
- if ((ret = log_flush(dbenv, &lsn)) != 0)
+ if ((ret = dbenv->log_flush(dbenv, &lsn)) != 0)
goto err;
}
- DB_ASSERT(!LOGGING_ON(dbenv) ||
- log_compare(&((LOG *)((DB_LOG *)
- dbenv->lg_handle)->reginfo.primary)->s_lsn, &LSN(bhp->buf)) > 0);
+
+#ifdef DIAGNOSTIC
+ /*
+ * Verify write-ahead logging semantics.
+ *
+ * !!!
+ * One special case. There is a single field on the meta-data page,
+ * the last-page-number-in-the-file field, for which we do not log
+ * changes. If the page was originally created in a database that
+ * didn't have logging turned on, we can see a page marked dirty but
+ * for which no corresponding log record has been written. However,
+ * the only way that a page can be created for which there isn't a
+ * previous log record and valid LSN is when the page was created
+ * without logging turned on, and so we check for that special-case
+ * LSN value.
+ */
+ if (LOGGING_ON(dbenv) && !IS_NOT_LOGGED_LSN(LSN(bhp->buf))) {
+ /*
+ * There is a potential race here. If we are in the midst of
+ * switching log files, it's possible we could test against the
+ * old file and the new offset in the log region's LSN. If we
+ * fail the first test, acquire the log mutex and check again.
+ */
+ DB_LOG *dblp;
+ LOG *lp;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ if (!IS_NOT_LOGGED_LSN(LSN(bhp->buf)) &&
+ log_compare(&lp->s_lsn, &LSN(bhp->buf)) <= 0) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ DB_ASSERT(log_compare(&lp->s_lsn, &LSN(bhp->buf)) > 0);
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ }
+ }
+#endif
/*
* Call any pgout function. We set the callpgin flag so that we flag
* that the contents of the buffer will need to be passed through pgin
* before they are reused.
*/
- if (mfp->ftype == 0)
- ret = 0;
- else {
+ if (mfp->ftype != 0) {
callpgin = 1;
if ((ret = __memp_pg(dbmfp, bhp, 0)) != 0)
goto err;
}
/* Temporary files may not yet have been created. */
- if (!F_ISSET(&dbmfp->fh, DB_FH_VALID)) {
+ if (!F_ISSET(dbmfp->fhp, DB_FH_VALID)) {
MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
- if (!F_ISSET(&dbmfp->fh, DB_FH_VALID) &&
- ((ret = __db_appname(dbenv, DB_APP_TMP, NULL, NULL,
- DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_TEMP,
- &dbmfp->fh, NULL)) != 0 ||
- !F_ISSET(&dbmfp->fh, DB_FH_VALID))) {
- MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+ ret = F_ISSET(dbmfp->fhp, DB_FH_VALID) ? 0 :
+ __db_appname(dbenv, DB_APP_TMP, NULL,
+ F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_OSO_DIRECT : 0,
+ dbmfp->fhp, NULL);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+ if (ret != 0) {
__db_err(dbenv,
"unable to create temporary backing file");
goto err;
}
- MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
}
/* Write the page. */
- db_io.fhp = &dbmfp->fh;
+ db_io.fhp = dbmfp->fhp;
db_io.mutexp = dbmfp->mutexp;
db_io.pagesize = db_io.bytes = mfp->stat.st_pagesize;
db_io.pgno = bhp->pgno;
db_io.buf = bhp->buf;
if ((ret = __os_io(dbenv, &db_io, DB_IO_WRITE, &nw)) != 0) {
- ret = __db_panic(dbenv, ret);
- fail = "write";
- goto syserr;
- }
- if (nw != mfp->stat.st_pagesize) {
- ret = EIO;
- fail = "write";
- goto syserr;
+ __db_err(dbenv, "%s: write failed for page %lu",
+ __memp_fn(dbmfp), (u_long)bhp->pgno);
+ goto err;
}
+ ++mfp->stat.st_page_out;
+err:
file_dead:
/*
* !!!
* Once we pass this point, dbmfp and mfp may be NULL, we may not have
* a valid file reference.
*
- * Unlock the buffer and reacquire the region lock.
+ * Unlock the buffer and reacquire the hash lock.
*/
MUTEX_UNLOCK(dbenv, &bhp->mutex);
- R_LOCK(dbenv, dbmp->reginfo);
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
/*
- * Clean up the flags based on a successful write.
- *
* If we rewrote the page, it will need processing by the pgin
* routine before reuse.
*/
if (callpgin)
F_SET(bhp, BH_CALLPGIN);
- F_CLR(bhp, BH_DIRTY | BH_LOCKED);
/*
- * If we write a buffer for which a checkpoint is waiting, update
- * the count of pending buffers (both in the mpool as a whole and
- * for this file). If the count for this file goes to zero, set a
- * flag so we flush the writes.
+ * Update the hash bucket statistics, reset the flags.
+ * If we were successful, the page is no longer dirty.
*/
- dosync = 0;
- if (F_ISSET(bhp, BH_SYNC)) {
- F_CLR(bhp, BH_SYNC | BH_SYNC_LOGFLSH);
-
- --mp->lsn_cnt;
- if (mfp != NULL)
- dosync = --mfp->lsn_cnt == 0 ? 1 : 0;
- }
-
- /* Update the page clean/dirty statistics. */
- c_mp = BH_TO_CACHE(dbmp, bhp);
- ++c_mp->stat.st_page_clean;
- --c_mp->stat.st_page_dirty;
-
- /* Update I/O statistics. */
- if (mfp != NULL)
- ++mfp->stat.st_page_out;
+ if (ret == 0) {
+ DB_ASSERT(hp->hash_page_dirty != 0);
+ --hp->hash_page_dirty;
- /*
- * Do the sync after everything else has been updated, so any incoming
- * checkpoint doesn't see inconsistent information.
- *
- * XXX:
- * Don't lock the region around the sync, fsync(2) has no atomicity
- * issues.
- *
- * XXX:
- * We ignore errors from the sync -- it makes no sense to return an
- * error to the calling process, so set a flag causing the checkpoint
- * to be retried later. There is a possibility, of course, that a
- * subsequent checkpoint was started and that we're going to force it
- * to fail. That should be unlikely, and fixing it would be difficult.
- */
- if (dosync) {
- R_UNLOCK(dbenv, dbmp->reginfo);
- syncfail = __os_fsync(dbenv, &dbmfp->fh) != 0;
- R_LOCK(dbenv, dbmp->reginfo);
- if (syncfail)
- F_SET(mp, MP_LSN_RETRY);
+ F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE);
}
- if (wrotep != NULL)
- *wrotep = 1;
-
- return (0);
-
-syserr: __db_err(dbenv, "%s: %s failed for page %lu",
- __memp_fn(dbmfp), fail, (u_long)bhp->pgno);
-
-err: /* Unlock the buffer and reacquire the region lock. */
- MUTEX_UNLOCK(dbenv, &bhp->mutex);
- R_LOCK(dbenv, dbmp->reginfo);
-
- /*
- * Clean up the flags based on a failure.
- *
- * The page remains dirty but we remove our lock. If we rewrote the
- * page, it will need processing by the pgin routine before reuse.
- */
- if (callpgin)
- F_SET(bhp, BH_CALLPGIN);
+ /* Regardless, clear any sync wait-for count and remove our lock. */
+ bhp->ref_sync = 0;
F_CLR(bhp, BH_LOCKED);
return (ret);
@@ -514,15 +456,17 @@ __memp_pg(dbmfp, bhp, is_pgin)
int is_pgin;
{
DBT dbt, *dbtp;
+ DB_ENV *dbenv;
DB_MPOOL *dbmp;
DB_MPREG *mpreg;
MPOOLFILE *mfp;
int ftype, ret;
dbmp = dbmfp->dbmp;
+ dbenv = dbmp->dbenv;
mfp = dbmfp->mfp;
- MUTEX_THREAD_LOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
ftype = mfp->ftype;
for (mpreg = LIST_FIRST(&dbmp->dbregq);
@@ -536,28 +480,28 @@ __memp_pg(dbmfp, bhp, is_pgin)
dbt.data = R_ADDR(dbmp->reginfo, mfp->pgcookie_off);
dbtp = &dbt;
}
- MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
if (is_pgin) {
if (mpreg->pgin != NULL &&
- (ret = mpreg->pgin(dbmp->dbenv,
+ (ret = mpreg->pgin(dbenv,
bhp->pgno, bhp->buf, dbtp)) != 0)
goto err;
} else
if (mpreg->pgout != NULL &&
- (ret = mpreg->pgout(dbmp->dbenv,
+ (ret = mpreg->pgout(dbenv,
bhp->pgno, bhp->buf, dbtp)) != 0)
goto err;
break;
}
if (mpreg == NULL)
- MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
return (0);
-err: MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
- __db_err(dbmp->dbenv, "%s: %s failed for page %lu",
+err: MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+ __db_err(dbenv, "%s: %s failed for page %lu",
__memp_fn(dbmfp), is_pgin ? "pgin" : "pgout", (u_long)bhp->pgno);
return (ret);
}
@@ -566,55 +510,78 @@ err: MUTEX_THREAD_UNLOCK(dbmp->dbenv, dbmp->mutexp);
* __memp_bhfree --
* Free a bucket header and its referenced data.
*
- * PUBLIC: void __memp_bhfree __P((DB_MPOOL *, BH *, int));
+ * PUBLIC: void __memp_bhfree __P((DB_MPOOL *, DB_MPOOL_HASH *, BH *, int));
*/
void
-__memp_bhfree(dbmp, bhp, free_mem)
+__memp_bhfree(dbmp, hp, bhp, free_mem)
DB_MPOOL *dbmp;
+ DB_MPOOL_HASH *hp;
BH *bhp;
int free_mem;
{
- DB_HASHTAB *dbht;
+ DB_ENV *dbenv;
MPOOL *c_mp, *mp;
MPOOLFILE *mfp;
- int n_bucket, n_cache;
+ u_int32_t n_cache;
+ /*
+ * Assumes the hash bucket is locked and the MPOOL is not.
+ */
+ dbenv = dbmp->dbenv;
mp = dbmp->reginfo[0].primary;
- c_mp = BH_TO_CACHE(dbmp, bhp);
- n_cache = NCACHE(mp, bhp->pgno);
- n_bucket = NBUCKET(c_mp, bhp->mf_offset, bhp->pgno);
- dbht = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
+ n_cache = NCACHE(mp, bhp->mf_offset, bhp->pgno);
- /* Delete the buffer header from the hash bucket queue. */
- SH_TAILQ_REMOVE(&dbht[n_bucket], bhp, hq, __bh);
+ /*
+ * Delete the buffer header from the hash bucket queue and reset
+ * the hash bucket's priority, if necessary.
+ */
+ SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
+ if (bhp->priority == hp->hash_priority)
+ hp->hash_priority =
+ SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL ?
+ 0 : SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
- /* Delete the buffer header from the LRU queue. */
- SH_TAILQ_REMOVE(&c_mp->bhq, bhp, q, __bh);
+ /*
+ * Discard the hash bucket's mutex, it's no longer needed, and
+ * we don't want to be holding it when acquiring other locks.
+ */
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
- /* Clear the mutex this buffer recorded */
- __db_shlocks_clear(&bhp->mutex, &dbmp->reginfo[n_cache],
- (REGMAINT *)R_ADDR(&dbmp->reginfo[n_cache], mp->maint_off));
/*
* Find the underlying MPOOLFILE and decrement its reference count.
* If this is its last reference, remove it.
*/
mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
+ MUTEX_LOCK(dbenv, &mfp->mutex);
if (--mfp->block_cnt == 0 && mfp->mpf_cnt == 0)
__memp_mf_discard(dbmp, mfp);
+ else
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
+
+ R_LOCK(dbenv, &dbmp->reginfo[n_cache]);
+
+ /*
+ * Clear the mutex this buffer recorded; requires the region lock
+ * be held.
+ */
+ __db_shlocks_clear(&bhp->mutex, &dbmp->reginfo[n_cache],
+ (REGMAINT *)R_ADDR(&dbmp->reginfo[n_cache], mp->maint_off));
/*
- * If we're not reusing it immediately, free the buffer header
+ * If we're not reusing the buffer immediately, free the buffer header
* and data for real.
*/
if (free_mem) {
- --c_mp->stat.st_page_clean;
__db_shalloc_free(dbmp->reginfo[n_cache].addr, bhp);
+ c_mp = dbmp->reginfo[n_cache].primary;
+ c_mp->stat.st_pages--;
}
+ R_UNLOCK(dbenv, &dbmp->reginfo[n_cache]);
}
/*
* __memp_upgrade --
- * Upgrade a file descriptor from readonly to readwrite.
+ * Upgrade a file descriptor from read-only to read-write.
*/
static int
__memp_upgrade(dbmp, dbmfp, mfp)
@@ -622,41 +589,58 @@ __memp_upgrade(dbmp, dbmfp, mfp)
DB_MPOOLFILE *dbmfp;
MPOOLFILE *mfp;
{
- DB_FH fh;
+ DB_ENV *dbenv;
+ DB_FH *fhp, *tfhp;
int ret;
char *rpath;
- /*
- * !!!
- * We expect the handle to already be locked.
- */
-
- /* Check to see if we've already upgraded. */
- if (F_ISSET(dbmfp, MP_UPGRADE))
- return (0);
-
- /* Check to see if we've already failed. */
- if (F_ISSET(dbmfp, MP_UPGRADE_FAIL))
- return (1);
+ dbenv = dbmp->dbenv;
+ fhp = NULL;
+ rpath = NULL;
/*
* Calculate the real name for this file and try to open it read/write.
* We know we have a valid pathname for the file because it's the only
* way we could have gotten a file descriptor of any kind.
*/
- if ((ret = __db_appname(dbmp->dbenv, DB_APP_DATA,
- NULL, R_ADDR(dbmp->reginfo, mfp->path_off), 0, NULL, &rpath)) != 0)
- return (ret);
- if (__os_open(dbmp->dbenv, rpath, 0, 0, &fh) != 0) {
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &fhp)) != 0)
+ goto err;
+
+ if ((ret = __db_appname(dbenv, DB_APP_DATA,
+ R_ADDR(dbmp->reginfo, mfp->path_off), 0, NULL, &rpath)) != 0)
+ goto err;
+
+ if (__os_open(dbenv, rpath,
+ F_ISSET(mfp, MP_DIRECT) ? DB_OSO_DIRECT : 0, 0, fhp) != 0) {
F_SET(dbmfp, MP_UPGRADE_FAIL);
- ret = 1;
- } else {
- /* Swap the descriptors and set the upgrade flag. */
- (void)__os_closehandle(&dbmfp->fh);
- dbmfp->fh = fh;
- F_SET(dbmfp, MP_UPGRADE);
- ret = 0;
+ goto err;
}
- __os_freestr(rpath);
+
+ /*
+ * Swap the descriptors and set the upgrade flag.
+ *
+ * XXX
+ * There is a race here. If another process schedules a read using the
+ * existing file descriptor and is swapped out before making the system
+ * call, this code could theoretically close the file descriptor out
+ * from under it. While it's very unlikely, this code should still be
+ * rewritten.
+ */
+ tfhp = dbmfp->fhp;
+ dbmfp->fhp = fhp;
+ fhp = tfhp;
+
+ (void)__os_closehandle(dbenv, fhp);
+ F_SET(dbmfp, MP_UPGRADE);
+
+ ret = 0;
+ if (0) {
+err: ret = 1;
+ }
+ if (fhp != NULL)
+ __os_free(dbenv, fhp);
+ if (rpath != NULL)
+ __os_free(dbenv, rpath);
+
return (ret);
}
diff --git a/bdb/mp/mp_fget.c b/bdb/mp/mp_fget.c
index 1bff5e136ab..be0785a2184 100644
--- a/bdb/mp/mp_fget.c
+++ b/bdb/mp/mp_fget.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_fget.c,v 11.28 2001/01/10 04:50:53 ubell Exp $";
+static const char revid[] = "$Id: mp_fget.c,v 11.68 2002/08/06 04:58:09 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,51 +16,54 @@ static const char revid[] = "$Id: mp_fget.c,v 11.28 2001/01/10 04:50:53 ubell Ex
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
+#ifdef HAVE_FILESYSTEM_NOTZERO
+static int __memp_fs_notzero
+ __P((DB_ENV *, DB_MPOOLFILE *, MPOOLFILE *, db_pgno_t *));
#endif
/*
- * memp_fget --
+ * __memp_fget --
* Get a page from the file.
+ *
+ * PUBLIC: int __memp_fget
+ * PUBLIC: __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
*/
int
-memp_fget(dbmfp, pgnoaddr, flags, addrp)
+__memp_fget(dbmfp, pgnoaddr, flags, addrp)
DB_MPOOLFILE *dbmfp;
db_pgno_t *pgnoaddr;
u_int32_t flags;
void *addrp;
{
- BH *bhp;
+ enum { FIRST_FOUND, FIRST_MISS, SECOND_FOUND, SECOND_MISS } state;
+ BH *alloc_bhp, *bhp;
DB_ENV *dbenv;
DB_MPOOL *dbmp;
- DB_HASHTAB *dbht;
+ DB_MPOOL_HASH *hp;
MPOOL *c_mp, *mp;
MPOOLFILE *mfp;
- size_t n_bucket, n_cache, mf_offset;
- u_int32_t st_hsearch;
- int b_incr, first, ret;
+ roff_t mf_offset;
+ u_int32_t n_cache, st_hsearch;
+ int b_incr, extending, first, ret;
+
+ *(void **)addrp = NULL;
dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
- mp = dbmp->reginfo[0].primary;
- mfp = dbmfp->mfp;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fget(dbmfp, pgnoaddr, flags, addrp));
-#endif
PANIC_CHECK(dbenv);
+ mp = dbmp->reginfo[0].primary;
+ mfp = dbmfp->mfp;
+ mf_offset = R_OFFSET(dbmp->reginfo, mfp);
+ alloc_bhp = bhp = NULL;
+ hp = NULL;
+ b_incr = extending = ret = 0;
+
/*
* Validate arguments.
*
@@ -74,100 +77,35 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
* is to keep database files small. It's sleazy as hell, but we catch
* any attempt to actually write the file in memp_fput().
*/
-#define OKFLAGS \
- (DB_MPOOL_CREATE | DB_MPOOL_LAST | \
- DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP | DB_MPOOL_EXTENT)
+#define OKFLAGS (DB_MPOOL_CREATE | DB_MPOOL_LAST | DB_MPOOL_NEW)
if (flags != 0) {
if ((ret = __db_fchk(dbenv, "memp_fget", flags, OKFLAGS)) != 0)
return (ret);
- switch (flags & ~DB_MPOOL_EXTENT) {
+ switch (flags) {
case DB_MPOOL_CREATE:
+ break;
case DB_MPOOL_LAST:
+ /* Get the last page number in the file. */
+ if (flags == DB_MPOOL_LAST) {
+ R_LOCK(dbenv, dbmp->reginfo);
+ *pgnoaddr = mfp->last_pgno;
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ }
+ break;
case DB_MPOOL_NEW:
- case DB_MPOOL_NEW_GROUP:
- case 0:
+ /*
+ * If always creating a page, skip the first search
+ * of the hash bucket.
+ */
+ if (flags == DB_MPOOL_NEW)
+ goto alloc;
break;
default:
return (__db_ferr(dbenv, "memp_fget", 1));
}
}
-#ifdef DIAGNOSTIC
- /*
- * XXX
- * We want to switch threads as often as possible. Yield every time
- * we get a new page to ensure contention.
- */
- if (DB_GLOBAL(db_pageyield))
- __os_yield(dbenv, 1);
-#endif
-
- /* Initialize remaining local variables. */
- mf_offset = R_OFFSET(dbmp->reginfo, mfp);
- bhp = NULL;
- st_hsearch = 0;
- b_incr = ret = 0;
-
- R_LOCK(dbenv, dbmp->reginfo);
-
- /*
- * Check for the new, last or last + 1 page requests.
- *
- * Examine and update the file's last_pgno value. We don't care if
- * the last_pgno value immediately changes due to another thread --
- * at this instant in time, the value is correct. We do increment the
- * current last_pgno value if the thread is asking for a new page,
- * however, to ensure that two threads creating pages don't get the
- * same one.
- *
- * If we create a page, there is the potential that a page after it
- * in the file will be written before it will be written. Recovery
- * depends on pages that are "created" in the file by subsequent pages
- * being written be zeroed out, not have random garbage. Ensure that
- * the OS agrees.
- *
- * !!!
- * DB_MPOOL_NEW_GROUP is undocumented -- the hash access method needs
- * to allocate contiguous groups of pages in order to do subdatabases.
- * We return the first page in the group, but the caller must put an
- * LSN on the *last* page and write it, otherwise after a crash we may
- * not create all of the pages we need to create.
- */
- if (LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP)) {
- if (LF_ISSET(DB_MPOOL_NEW)) {
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID) && (ret =
- __os_fpinit(dbenv, &dbmfp->fh, mfp->last_pgno + 1,
- 1, mfp->stat.st_pagesize)) != 0) {
- R_UNLOCK(dbenv, dbmp->reginfo);
- return (ret);
- }
- ++mfp->last_pgno;
- }
- if (LF_ISSET(DB_MPOOL_NEW_GROUP)) {
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID) && (ret =
- __os_fpinit(dbenv, &dbmfp->fh, mfp->last_pgno + 1,
- (int)*pgnoaddr, mfp->stat.st_pagesize)) != 0) {
- R_UNLOCK(dbenv, dbmp->reginfo);
- return (ret);
- }
- mfp->last_pgno += *pgnoaddr;
- }
- *pgnoaddr = mfp->last_pgno;
- }
-
- /*
- * Determine the hash bucket where this page will live, and get local
- * pointers to the cache and its hash table.
- */
- n_cache = NCACHE(mp, *pgnoaddr);
- c_mp = dbmp->reginfo[n_cache].primary;
- n_bucket = NBUCKET(c_mp, mf_offset, *pgnoaddr);
- dbht = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
-
- if (LF_ISSET(DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP))
- goto alloc;
-
/*
* If mmap'ing the file and the page is not past the end of the file,
* just return a pointer.
@@ -183,235 +121,534 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
* goes through the cache. All pages previously returned will be safe,
* as long as the correct locking protocol was observed.
*
- * XXX
* We don't discard the map because we don't know when all of the
* pages will have been discarded from the process' address space.
* It would be possible to do so by reference counting the open
* pages from the mmap, but it's unclear to me that it's worth it.
*/
- if (dbmfp->addr != NULL && F_ISSET(mfp, MP_CAN_MMAP)) {
- if (*pgnoaddr > mfp->orig_last_pgno) {
- /*
- * !!!
- * See the comment above about non-existent pages and
- * the hash access method.
- */
- if (!LF_ISSET(DB_MPOOL_CREATE)) {
- if (!LF_ISSET(DB_MPOOL_EXTENT))
- __db_err(dbenv,
- "%s: page %lu doesn't exist",
- __memp_fn(dbmfp), (u_long)*pgnoaddr);
- ret = EINVAL;
- goto err;
- }
- } else {
- *(void **)addrp =
- R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
- ++mfp->stat.st_map;
- goto done;
- }
+ if (dbmfp->addr != NULL &&
+ F_ISSET(mfp, MP_CAN_MMAP) && *pgnoaddr <= mfp->orig_last_pgno) {
+ *(void **)addrp =
+ R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
+ ++mfp->stat.st_map;
+ return (0);
}
+hb_search:
+ /*
+ * Determine the cache and hash bucket where this page lives and get
+ * local pointers to them. Reset on each pass through this code, the
+ * page number can change.
+ */
+ n_cache = NCACHE(mp, mf_offset, *pgnoaddr);
+ c_mp = dbmp->reginfo[n_cache].primary;
+ hp = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
+ hp = &hp[NBUCKET(c_mp, mf_offset, *pgnoaddr)];
+
/* Search the hash chain for the page. */
- for (bhp = SH_TAILQ_FIRST(&dbht[n_bucket], __bh);
+retry: st_hsearch = 0;
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
+ for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) {
++st_hsearch;
if (bhp->pgno != *pgnoaddr || bhp->mf_offset != mf_offset)
continue;
- /* Increment the reference count. */
+ /*
+ * Increment the reference count. We may discard the hash
+ * bucket lock as we evaluate and/or read the buffer, so we
+ * need to ensure it doesn't move and its contents remain
+ * unchanged.
+ */
if (bhp->ref == UINT16_T_MAX) {
__db_err(dbenv,
"%s: page %lu: reference count overflow",
__memp_fn(dbmfp), (u_long)bhp->pgno);
ret = EINVAL;
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
goto err;
}
-
- /*
- * Increment the reference count. We may discard the region
- * lock as we evaluate and/or read the buffer, so we need to
- * ensure that it doesn't move and that its contents remain
- * unchanged.
- */
++bhp->ref;
b_incr = 1;
/*
- * Any buffer we find might be trouble.
- *
* BH_LOCKED --
- * I/O is in progress. Because we've incremented the buffer
- * reference count, we know the buffer can't move. Unlock
- * the region lock, wait for the I/O to complete, and reacquire
- * the region.
+ * I/O is in progress or sync is waiting on the buffer to write
+ * it. Because we've incremented the buffer reference count,
+ * we know the buffer can't move. Unlock the bucket lock, wait
+ * for the buffer to become available, reacquire the bucket.
*/
- for (first = 1; F_ISSET(bhp, BH_LOCKED); first = 0) {
- R_UNLOCK(dbenv, dbmp->reginfo);
+ for (first = 1; F_ISSET(bhp, BH_LOCKED) &&
+ !F_ISSET(dbenv, DB_ENV_NOLOCKING); first = 0) {
+ /*
+ * If someone is trying to sync this buffer and the
+ * buffer is hot, they may never get in. Give up
+ * and try again.
+ */
+ if (!first && bhp->ref_sync != 0) {
+ --bhp->ref;
+ b_incr = 0;
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+ __os_yield(dbenv, 1);
+ goto retry;
+ }
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
/*
- * Explicitly yield the processor if it's not the first
- * pass through this loop -- if we don't, we might end
- * up running to the end of our CPU quantum as we will
- * simply be swapping between the two locks.
+ * Explicitly yield the processor if not the first pass
+ * through this loop -- if we don't, we might run to the
+ * end of our CPU quantum as we will simply be swapping
+ * between the two locks.
*/
if (!first)
__os_yield(dbenv, 1);
- MUTEX_LOCK(dbenv, &bhp->mutex, dbenv->lockfhp);
+ MUTEX_LOCK(dbenv, &bhp->mutex);
/* Wait for I/O to finish... */
MUTEX_UNLOCK(dbenv, &bhp->mutex);
- R_LOCK(dbenv, dbmp->reginfo);
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
+ }
+
+ ++mfp->stat.st_cache_hit;
+ break;
+ }
+
+ /*
+ * Update the hash bucket search statistics -- do now because our next
+ * search may be for a different bucket.
+ */
+ ++c_mp->stat.st_hash_searches;
+ if (st_hsearch > c_mp->stat.st_hash_longest)
+ c_mp->stat.st_hash_longest = st_hsearch;
+ c_mp->stat.st_hash_examined += st_hsearch;
+
+ /*
+ * There are 4 possible paths to this location:
+ *
+ * FIRST_MISS:
+ * Didn't find the page in the hash bucket on our first pass:
+ * bhp == NULL, alloc_bhp == NULL
+ *
+ * FIRST_FOUND:
+ * Found the page in the hash bucket on our first pass:
+ * bhp != NULL, alloc_bhp == NULL
+ *
+ * SECOND_FOUND:
+ * Didn't find the page in the hash bucket on the first pass,
+ * allocated space, and found the page in the hash bucket on
+ * our second pass:
+ * bhp != NULL, alloc_bhp != NULL
+ *
+ * SECOND_MISS:
+ * Didn't find the page in the hash bucket on the first pass,
+ * allocated space, and didn't find the page in the hash bucket
+ * on our second pass:
+ * bhp == NULL, alloc_bhp != NULL
+ */
+ state = bhp == NULL ?
+ (alloc_bhp == NULL ? FIRST_MISS : SECOND_MISS) :
+ (alloc_bhp == NULL ? FIRST_FOUND : SECOND_FOUND);
+ switch (state) {
+ case FIRST_FOUND:
+ /* We found the buffer in our first check -- we're done. */
+ break;
+ case FIRST_MISS:
+ /*
+ * We didn't find the buffer in our first check. Figure out
+ * if the page exists, and allocate structures so we can add
+ * the page to the buffer pool.
+ */
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+
+alloc: /*
+ * If DB_MPOOL_NEW is set, we have to allocate a page number.
+ * If neither DB_MPOOL_CREATE or DB_MPOOL_CREATE is set, then
+ * it's an error to try and get a page past the end of file.
+ */
+ COMPQUIET(n_cache, 0);
+
+ extending = ret = 0;
+ R_LOCK(dbenv, dbmp->reginfo);
+ switch (flags) {
+ case DB_MPOOL_NEW:
+ extending = 1;
+ *pgnoaddr = mfp->last_pgno + 1;
+ break;
+ case DB_MPOOL_CREATE:
+ extending = *pgnoaddr > mfp->last_pgno;
+ break;
+ default:
+ ret = *pgnoaddr > mfp->last_pgno ? DB_PAGE_NOTFOUND : 0;
+ break;
}
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ if (ret != 0)
+ goto err;
/*
- * BH_TRASH --
- * The contents of the buffer are garbage. Shouldn't happen,
- * and this read is likely to fail, but might as well try.
+ * !!!
+ * In the DB_MPOOL_NEW code path, mf_offset and n_cache have
+ * not yet been initialized.
*/
- if (F_ISSET(bhp, BH_TRASH))
- goto reread;
+ mf_offset = R_OFFSET(dbmp->reginfo, mfp);
+ n_cache = NCACHE(mp, mf_offset, *pgnoaddr);
+ /* Allocate a new buffer header and data space. */
+ if ((ret = __memp_alloc(dbmp,
+ &dbmp->reginfo[n_cache], mfp, 0, NULL, &alloc_bhp)) != 0)
+ goto err;
+#ifdef DIAGNOSTIC
+ if ((db_alignp_t)alloc_bhp->buf & (sizeof(size_t) - 1)) {
+ __db_err(dbenv,
+ "Error: buffer data is NOT size_t aligned");
+ ret = EINVAL;
+ goto err;
+ }
+#endif
/*
- * BH_CALLPGIN --
- * The buffer was converted so it could be written, and the
- * contents need to be converted again.
+ * If we are extending the file, we'll need the region lock
+ * again.
*/
- if (F_ISSET(bhp, BH_CALLPGIN)) {
- if ((ret = __memp_pg(dbmfp, bhp, 1)) != 0)
+ if (extending)
+ R_LOCK(dbenv, dbmp->reginfo);
+
+ /*
+ * DB_MPOOL_NEW does not guarantee you a page unreferenced by
+ * any other thread of control. (That guarantee is interesting
+ * for DB_MPOOL_NEW, unlike DB_MPOOL_CREATE, because the caller
+ * did not specify the page number, and so, may reasonably not
+ * have any way to lock the page outside of mpool.) Regardless,
+ * if we allocate the page, and some other thread of control
+ * requests the page by number, we will not detect that and the
+ * thread of control that allocated using DB_MPOOL_NEW may not
+ * have a chance to initialize the page. (Note: we *could*
+ * detect this case if we set a flag in the buffer header which
+ * guaranteed that no gets of the page would succeed until the
+ * reference count went to 0, that is, until the creating page
+ * put the page.) What we do guarantee is that if two threads
+ * of control are both doing DB_MPOOL_NEW calls, they won't
+ * collide, that is, they won't both get the same page.
+ *
+ * There's a possibility that another thread allocated the page
+ * we were planning to allocate while we were off doing buffer
+ * allocation. We can do that by making sure the page number
+ * we were going to use is still available. If it's not, then
+ * we check to see if the next available page number hashes to
+ * the same mpool region as the old one -- if it does, we can
+ * continue, otherwise, we have to start over.
+ */
+ if (flags == DB_MPOOL_NEW && *pgnoaddr != mfp->last_pgno + 1) {
+ *pgnoaddr = mfp->last_pgno + 1;
+ if (n_cache != NCACHE(mp, mf_offset, *pgnoaddr)) {
+ __db_shalloc_free(
+ dbmp->reginfo[n_cache].addr, alloc_bhp);
+ /*
+ * flags == DB_MPOOL_NEW, so extending is set
+ * and we're holding the region locked.
+ */
+ R_UNLOCK(dbenv, dbmp->reginfo);
+
+ alloc_bhp = NULL;
+ goto alloc;
+ }
+ }
+
+ /*
+ * We released the region lock, so another thread might have
+ * extended the file. Update the last_pgno and initialize
+ * the file, as necessary, if we extended the file.
+ */
+ if (extending) {
+#ifdef HAVE_FILESYSTEM_NOTZERO
+ if (*pgnoaddr > mfp->last_pgno &&
+ __os_fs_notzero() &&
+ F_ISSET(dbmfp->fhp, DB_FH_VALID))
+ ret = __memp_fs_notzero(
+ dbenv, dbmfp, mfp, pgnoaddr);
+ else
+ ret = 0;
+#endif
+ if (ret == 0 && *pgnoaddr > mfp->last_pgno)
+ mfp->last_pgno = *pgnoaddr;
+
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ if (ret != 0)
goto err;
- F_CLR(bhp, BH_CALLPGIN);
}
+ goto hb_search;
+ case SECOND_FOUND:
+ /*
+ * We allocated buffer space for the requested page, but then
+ * found the page in the buffer cache on our second check.
+ * That's OK -- we can use the page we found in the pool,
+ * unless DB_MPOOL_NEW is set.
+ *
+ * Free the allocated memory, we no longer need it. Since we
+ * can't acquire the region lock while holding the hash bucket
+ * lock, we have to release the hash bucket and re-acquire it.
+ * That's OK, because we have the buffer pinned down.
+ */
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+ R_LOCK(dbenv, &dbmp->reginfo[n_cache]);
+ __db_shalloc_free(dbmp->reginfo[n_cache].addr, alloc_bhp);
+ alloc_bhp = NULL;
+ R_UNLOCK(dbenv, &dbmp->reginfo[n_cache]);
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
- ++mfp->stat.st_cache_hit;
- *(void **)addrp = bhp->buf;
- goto done;
- }
+ /*
+ * We can't use the page we found in the pool if DB_MPOOL_NEW
+ * was set. (For details, see the above comment beginning
+ * "DB_MPOOL_NEW does not guarantee you a page unreferenced by
+ * any other thread of control".) If DB_MPOOL_NEW is set, we
+ * release our pin on this particular buffer, and try to get
+ * another one.
+ */
+ if (flags == DB_MPOOL_NEW) {
+ --bhp->ref;
+ b_incr = 0;
+ goto alloc;
+ }
+ break;
+ case SECOND_MISS:
+ /*
+ * We allocated buffer space for the requested page, and found
+ * the page still missing on our second pass through the buffer
+ * cache. Instantiate the page.
+ */
+ bhp = alloc_bhp;
+ alloc_bhp = NULL;
-alloc: /* Allocate new buffer header and data space. */
- if ((ret = __memp_alloc(dbmp,
- &dbmp->reginfo[n_cache], mfp, 0, NULL, &bhp)) != 0)
- goto err;
+ /*
+ * Initialize all the BH and hash bucket fields so we can call
+ * __memp_bhfree if an error occurs.
+ *
+ * Append the buffer to the tail of the bucket list and update
+ * the hash bucket's priority.
+ */
+ b_incr = 1;
+
+ memset(bhp, 0, sizeof(BH));
+ bhp->ref = 1;
+ bhp->priority = UINT32_T_MAX;
+ bhp->pgno = *pgnoaddr;
+ bhp->mf_offset = mf_offset;
+ SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
+ hp->hash_priority =
+ SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
+
+ /* If we extended the file, make sure the page is never lost. */
+ if (extending) {
+ ++hp->hash_page_dirty;
+ F_SET(bhp, BH_DIRTY | BH_DIRTY_CREATE);
+ }
- ++c_mp->stat.st_page_clean;
+ /*
+ * If we created the page, zero it out. If we didn't create
+ * the page, read from the backing file.
+ *
+ * !!!
+ * DB_MPOOL_NEW doesn't call the pgin function.
+ *
+ * If DB_MPOOL_CREATE is used, then the application's pgin
+ * function has to be able to handle pages of 0's -- if it
+ * uses DB_MPOOL_NEW, it can detect all of its page creates,
+ * and not bother.
+ *
+ * If we're running in diagnostic mode, smash any bytes on the
+ * page that are unknown quantities for the caller.
+ *
+ * Otherwise, read the page into memory, optionally creating it
+ * if DB_MPOOL_CREATE is set.
+ */
+ if (extending) {
+ if (mfp->clear_len == 0)
+ memset(bhp->buf, 0, mfp->stat.st_pagesize);
+ else {
+ memset(bhp->buf, 0, mfp->clear_len);
+#if defined(DIAGNOSTIC) || defined(UMRW)
+ memset(bhp->buf + mfp->clear_len, CLEAR_BYTE,
+ mfp->stat.st_pagesize - mfp->clear_len);
+#endif
+ }
- /*
- * Initialize the BH fields so that we can call the __memp_bhfree
- * routine if an error occurs.
- */
- memset(bhp, 0, sizeof(BH));
- bhp->ref = 1;
- bhp->pgno = *pgnoaddr;
- bhp->mf_offset = mf_offset;
+ if (flags == DB_MPOOL_CREATE && mfp->ftype != 0)
+ F_SET(bhp, BH_CALLPGIN);
- /* Increment the count of buffers referenced by this MPOOLFILE. */
- ++mfp->block_cnt;
+ ++mfp->stat.st_page_create;
+ } else {
+ F_SET(bhp, BH_TRASH);
+ ++mfp->stat.st_cache_miss;
+ }
- /*
- * Prepend the bucket header to the head of the appropriate MPOOL
- * bucket hash list. Append the bucket header to the tail of the
- * MPOOL LRU chain.
- */
- SH_TAILQ_INSERT_HEAD(&dbht[n_bucket], bhp, hq, __bh);
- SH_TAILQ_INSERT_TAIL(&c_mp->bhq, bhp, q);
+ /* Increment buffer count referenced by MPOOLFILE. */
+ MUTEX_LOCK(dbenv, &mfp->mutex);
+ ++mfp->block_cnt;
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
-#ifdef DIAGNOSTIC
- if ((db_alignp_t)bhp->buf & (sizeof(size_t) - 1)) {
- __db_err(dbenv, "Internal error: BH data NOT size_t aligned.");
- ret = EINVAL;
- __memp_bhfree(dbmp, bhp, 1);
- goto err;
+ /*
+ * Initialize the mutex. This is the last initialization step,
+ * because it's the only one that can fail, and everything else
+ * must be set up or we can't jump to the err label because it
+ * will call __memp_bhfree.
+ */
+ if ((ret = __db_mutex_setup(dbenv,
+ &dbmp->reginfo[n_cache], &bhp->mutex, 0)) != 0)
+ goto err;
}
-#endif
- if ((ret = __db_shmutex_init(dbenv, &bhp->mutex,
- R_OFFSET(dbmp->reginfo, &bhp->mutex) + DB_FCNTL_OFF_MPOOL,
- 0, &dbmp->reginfo[n_cache],
- (REGMAINT *)R_ADDR(&dbmp->reginfo[n_cache], c_mp->maint_off)))
- != 0) {
- __memp_bhfree(dbmp, bhp, 1);
- goto err;
+ DB_ASSERT(bhp->ref != 0);
+
+ /*
+ * If we're the only reference, update buffer and bucket priorities.
+ * We may be about to release the hash bucket lock, and everything
+ * should be correct, first. (We've already done this if we created
+ * the buffer, so there is no need to do it again.)
+ */
+ if (state != SECOND_MISS && bhp->ref == 1) {
+ bhp->priority = UINT32_T_MAX;
+ SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
+ SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
+ hp->hash_priority =
+ SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
}
/*
- * If we created the page, zero it out and continue.
- *
- * !!!
- * Note: DB_MPOOL_NEW specifically doesn't call the pgin function.
- * If DB_MPOOL_CREATE is used, then the application's pgin function
- * has to be able to handle pages of 0's -- if it uses DB_MPOOL_NEW,
- * it can detect all of its page creates, and not bother.
+ * BH_TRASH --
+ * The buffer we found may need to be filled from the disk.
*
- * If we're running in diagnostic mode, smash any bytes on the
- * page that are unknown quantities for the caller.
- *
- * Otherwise, read the page into memory, optionally creating it if
- * DB_MPOOL_CREATE is set.
+ * It's possible for the read function to fail, which means we fail as
+ * well. Note, the __memp_pgread() function discards and reacquires
+ * the hash lock, so the buffer must be pinned down so that it cannot
+ * move and its contents are unchanged. Discard the buffer on failure
+ * unless another thread is waiting on our I/O to complete. It's OK to
+ * leave the buffer around, as the waiting thread will see the BH_TRASH
+ * flag set, and will also attempt to discard it. If there's a waiter,
+ * we need to decrement our reference count.
*/
- if (LF_ISSET(DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP)) {
- if (mfp->clear_len == 0)
- memset(bhp->buf, 0, mfp->stat.st_pagesize);
- else {
- memset(bhp->buf, 0, mfp->clear_len);
-#ifdef DIAGNOSTIC
- memset(bhp->buf + mfp->clear_len, CLEAR_BYTE,
- mfp->stat.st_pagesize - mfp->clear_len);
-#endif
- }
+ if (F_ISSET(bhp, BH_TRASH) &&
+ (ret = __memp_pgread(dbmfp,
+ &hp->hash_mutex, bhp, LF_ISSET(DB_MPOOL_CREATE) ? 1 : 0)) != 0)
+ goto err;
- ++mfp->stat.st_page_create;
- } else {
- /*
- * It's possible for the read function to fail, which means
- * that we fail as well. Note, the __memp_pgread() function
- * discards the region lock, so the buffer must be pinned
- * down so that it cannot move and its contents are unchanged.
- */
-reread: if ((ret = __memp_pgread(dbmfp,
- bhp, LF_ISSET(DB_MPOOL_CREATE|DB_MPOOL_EXTENT))) != 0) {
- /*
- * !!!
- * Discard the buffer unless another thread is waiting
- * on our I/O to complete. Regardless, the header has
- * the BH_TRASH flag set.
- */
- if (bhp->ref == 1)
- __memp_bhfree(dbmp, bhp, 1);
+ /*
+ * BH_CALLPGIN --
+ * The buffer was processed for being written to disk, and now has
+ * to be re-converted for use.
+ */
+ if (F_ISSET(bhp, BH_CALLPGIN)) {
+ if ((ret = __memp_pg(dbmfp, bhp, 1)) != 0)
goto err;
- }
-
- ++mfp->stat.st_cache_miss;
+ F_CLR(bhp, BH_CALLPGIN);
}
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+
+#ifdef DIAGNOSTIC
+ /* Update the file's pinned reference count. */
+ R_LOCK(dbenv, dbmp->reginfo);
+ ++dbmfp->pinref;
+ R_UNLOCK(dbenv, dbmp->reginfo);
+
/*
- * If we're returning a page after our current notion of the last-page,
- * update our information. Note, there's no way to un-instantiate this
- * page, it's going to exist whether it's returned to us dirty or not.
+ * We want to switch threads as often as possible, and at awkward
+ * times. Yield every time we get a new page to ensure contention.
*/
- if (bhp->pgno > mfp->last_pgno)
- mfp->last_pgno = bhp->pgno;
+ if (F_ISSET(dbenv, DB_ENV_YIELDCPU))
+ __os_yield(dbenv, 1);
+#endif
*(void **)addrp = bhp->buf;
+ return (0);
-done: /* Update the chain search statistics. */
- if (st_hsearch) {
- ++c_mp->stat.st_hash_searches;
- if (st_hsearch > c_mp->stat.st_hash_longest)
- c_mp->stat.st_hash_longest = st_hsearch;
- c_mp->stat.st_hash_examined += st_hsearch;
+err: /*
+ * Discard our reference. If we're the only reference, discard the
+ * the buffer entirely. If we held a reference to a buffer, we are
+ * also still holding the hash bucket mutex.
+ */
+ if (b_incr) {
+ if (bhp->ref == 1)
+ (void)__memp_bhfree(dbmp, hp, bhp, 1);
+ else {
+ --bhp->ref;
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+ }
}
- ++dbmfp->pinref;
+ /* If alloc_bhp is set, free the memory. */
+ if (alloc_bhp != NULL)
+ __db_shalloc_free(dbmp->reginfo[n_cache].addr, alloc_bhp);
- R_UNLOCK(dbenv, dbmp->reginfo);
+ return (ret);
+}
- return (0);
+#ifdef HAVE_FILESYSTEM_NOTZERO
+/*
+ * __memp_fs_notzero --
+ * Initialize the underlying allocated pages in the file.
+ */
+static int
+__memp_fs_notzero(dbenv, dbmfp, mfp, pgnoaddr)
+ DB_ENV *dbenv;
+ DB_MPOOLFILE *dbmfp;
+ MPOOLFILE *mfp;
+ db_pgno_t *pgnoaddr;
+{
+ DB_IO db_io;
+ u_int32_t i, npages;
+ size_t nw;
+ int ret;
+ u_int8_t *page;
+ char *fail;
-err: /* Discard our reference. */
- if (b_incr)
- --bhp->ref;
- R_UNLOCK(dbenv, dbmp->reginfo);
+ /*
+ * Pages allocated by writing pages past end-of-file are not zeroed,
+ * on some systems. Recovery could theoretically be fooled by a page
+ * showing up that contained garbage. In order to avoid this, we
+ * have to write the pages out to disk, and flush them. The reason
+ * for the flush is because if we don't sync, the allocation of another
+ * page subsequent to this one might reach the disk first, and if we
+ * crashed at the right moment, leave us with this page as the one
+ * allocated by writing a page past it in the file.
+ *
+ * Hash is the only access method that allocates groups of pages. We
+ * know that it will use the existence of the last page in a group to
+ * signify that the entire group is OK; so, write all the pages but
+ * the last one in the group, flush them to disk, and then write the
+ * last one to disk and flush it.
+ */
+ if ((ret = __os_calloc(dbenv, 1, mfp->stat.st_pagesize, &page)) != 0)
+ return (ret);
+
+ db_io.fhp = dbmfp->fhp;
+ db_io.mutexp = dbmfp->mutexp;
+ db_io.pagesize = db_io.bytes = mfp->stat.st_pagesize;
+ db_io.buf = page;
+
+ npages = *pgnoaddr - mfp->last_pgno;
+ for (i = 1; i < npages; ++i) {
+ db_io.pgno = mfp->last_pgno + i;
+ if ((ret = __os_io(dbenv, &db_io, DB_IO_WRITE, &nw)) != 0) {
+ fail = "write";
+ goto err;
+ }
+ }
+ if (i != 1 && (ret = __os_fsync(dbenv, dbmfp->fhp)) != 0) {
+ fail = "sync";
+ goto err;
+ }
- *(void **)addrp = NULL;
+ db_io.pgno = mfp->last_pgno + npages;
+ if ((ret = __os_io(dbenv, &db_io, DB_IO_WRITE, &nw)) != 0) {
+ fail = "write";
+ goto err;
+ }
+ if ((ret = __os_fsync(dbenv, dbmfp->fhp)) != 0) {
+ fail = "sync";
+err: __db_err(dbenv, "%s: %s failed for page %lu",
+ __memp_fn(dbmfp), fail, (u_long)db_io.pgno);
+ }
+
+ __os_free(dbenv, page);
return (ret);
}
+#endif
diff --git a/bdb/mp/mp_fopen.c b/bdb/mp/mp_fopen.c
index 3611ded18f4..8fdefb0f5e9 100644
--- a/bdb/mp/mp_fopen.c
+++ b/bdb/mp/mp_fopen.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_fopen.c,v 11.41 2001/01/10 04:50:53 ubell Exp $";
+static const char revid[] = "$Id: mp_fopen.c,v 11.90 2002/08/26 15:22:01 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,311 +16,558 @@ static const char revid[] = "$Id: mp_fopen.c,v 11.41 2001/01/10 04:50:53 ubell E
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
-
-static int __memp_mf_open __P((DB_MPOOL *, const char *,
- size_t, db_pgno_t, DB_MPOOL_FINFO *, u_int32_t, MPOOLFILE **));
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
+
+static int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t));
+static int __memp_fopen __P((DB_MPOOLFILE *,
+ const char *, u_int32_t, int, size_t));
+static void __memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+static void __memp_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *));
+static void __memp_refcnt __P((DB_MPOOLFILE *, db_pgno_t *));
+static int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t));
+static int __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+static int __memp_set_ftype __P((DB_MPOOLFILE *, int));
+static int __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t));
+static int __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *));
+static int __memp_set_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY));
+static void __memp_set_unlink __P((DB_MPOOLFILE *, int));
+
+/* Initialization methods cannot be called after open is called. */
+#define MPF_ILLEGAL_AFTER_OPEN(dbmfp, name) \
+ if (F_ISSET(dbmfp, MP_OPEN_CALLED)) \
+ return (__db_mi_open((dbmfp)->dbmp->dbenv, name, 1));
/*
- * MEMP_FREMOVE --
- * Discard an MPOOLFILE and any buffers it references: update the flags
- * so we never try to write buffers associated with the file, nor can we
- * find it when looking for files to join. In addition, clear the ftype
- * field, there's no reason to post-process pages, they can be discarded
- * by any thread.
- */
-#define MEMP_FREMOVE(mfp) { \
- mfp->ftype = 0; \
- F_SET(mfp, MP_DEADFILE); \
-}
-
-/*
- * memp_fopen --
- * Open a backing file for the memory pool.
+ * __memp_fcreate --
+ * Create a DB_MPOOLFILE handle.
+ *
+ * PUBLIC: int __memp_fcreate __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
*/
int
-memp_fopen(dbenv, path, flags, mode, pagesize, finfop, retp)
+__memp_fcreate(dbenv, retp, flags)
DB_ENV *dbenv;
- const char *path;
- u_int32_t flags;
- int mode;
- size_t pagesize;
- DB_MPOOL_FINFO *finfop;
DB_MPOOLFILE **retp;
+ u_int32_t flags;
{
DB_MPOOL *dbmp;
+ DB_MPOOLFILE *dbmfp;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fopen(dbenv, path, flags,
- mode, pagesize, finfop, retp));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->mp_handle, "memp_fcreate", DB_INIT_MPOOL);
dbmp = dbenv->mp_handle;
/* Validate arguments. */
- if ((ret = __db_fchk(dbenv, "memp_fopen", flags,
- DB_CREATE |
- DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0)
+ if ((ret = __db_fchk(dbenv, "memp_fcreate", flags, 0)) != 0)
return (ret);
- /* Require a non-zero pagesize. */
- if (pagesize == 0 ||
- (finfop != NULL && finfop->clear_len > pagesize)) {
- __db_err(dbenv, "memp_fopen: illegal page size.");
- return (EINVAL);
+ /* Allocate and initialize the per-process structure. */
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
+ return (ret);
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &dbmfp->fhp)) != 0)
+ goto err;
+
+ /* Allocate and initialize a mutex if necessary. */
+ if (F_ISSET(dbenv, DB_ENV_THREAD) &&
+ (ret = __db_mutex_setup(dbenv, dbmp->reginfo, &dbmfp->mutexp,
+ MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+ goto err;
+
+ dbmfp->ref = 1;
+ dbmfp->lsn_offset = -1;
+ dbmfp->dbmp = dbmp;
+ dbmfp->mfp = INVALID_ROFF;
+
+ dbmfp->close = __memp_fclose;
+ dbmfp->get = __memp_fget;
+ dbmfp->get_fileid = __memp_get_fileid;
+ dbmfp->last_pgno = __memp_last_pgno;
+ dbmfp->open = __memp_fopen;
+ dbmfp->put = __memp_fput;
+ dbmfp->refcnt = __memp_refcnt;
+ dbmfp->set = __memp_fset;
+ dbmfp->set_clear_len = __memp_set_clear_len;
+ dbmfp->set_fileid = __memp_set_fileid;
+ dbmfp->set_ftype = __memp_set_ftype;
+ dbmfp->set_lsn_offset = __memp_set_lsn_offset;
+ dbmfp->set_pgcookie = __memp_set_pgcookie;
+ dbmfp->set_priority = __memp_set_priority;
+ dbmfp->set_unlink = __memp_set_unlink;
+ dbmfp->sync = __memp_fsync;
+
+ *retp = dbmfp;
+ return (0);
+
+err: if (dbmfp != NULL) {
+ if (dbmfp->fhp != NULL)
+ (void)__os_free(dbenv, dbmfp->fhp);
+ (void)__os_free(dbenv, dbmfp);
}
+ return (ret);
+}
- return (__memp_fopen(dbmp,
- NULL, path, flags, mode, pagesize, 1, finfop, retp));
+/*
+ * __memp_set_clear_len --
+ * Set the clear length.
+ */
+static int
+__memp_set_clear_len(dbmfp, clear_len)
+ DB_MPOOLFILE *dbmfp;
+ u_int32_t clear_len;
+{
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_clear_len");
+
+ dbmfp->clear_len = clear_len;
+ return (0);
}
/*
- * __memp_set_unlink -- set unlink on last close flag.
- *
- * PUBLIC: void __memp_set_unlink __P((DB_MPOOLFILE *));
+ * __memp_set_fileid --
+ * Set the file ID.
*/
-void
-__memp_set_unlink(dbmpf)
- DB_MPOOLFILE *dbmpf;
+static int
+__memp_set_fileid(dbmfp, fileid)
+ DB_MPOOLFILE *dbmfp;
+ u_int8_t *fileid;
{
- DB_MPOOL *dbmp;
- dbmp = dbmpf->dbmp;
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_fileid");
- R_LOCK(dbmp->dbenv, dbmp->reginfo);
- F_SET(dbmpf->mfp, MP_UNLINK);
- R_UNLOCK(dbmp->dbenv, dbmp->reginfo);
+ /*
+ * XXX
+ * This is dangerous -- we're saving the caller's pointer instead
+ * of allocating memory and copying the contents.
+ */
+ dbmfp->fileid = fileid;
+ return (0);
}
/*
- * __memp_clear_unlink -- clear unlink on last close flag.
- *
- * PUBLIC: void __memp_clear_unlink __P((DB_MPOOLFILE *));
+ * __memp_set_ftype --
+ * Set the file type (as registered).
*/
-void
-__memp_clear_unlink(dbmpf)
- DB_MPOOLFILE *dbmpf;
+static int
+__memp_set_ftype(dbmfp, ftype)
+ DB_MPOOLFILE *dbmfp;
+ int ftype;
{
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_ftype");
+
+ dbmfp->ftype = ftype;
+ return (0);
+}
+
+/*
+ * __memp_set_lsn_offset --
+ * Set the page's LSN offset.
+ */
+static int
+__memp_set_lsn_offset(dbmfp, lsn_offset)
+ DB_MPOOLFILE *dbmfp;
+ int32_t lsn_offset;
+{
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_lsn_offset");
+
+ dbmfp->lsn_offset = lsn_offset;
+ return (0);
+}
+
+/*
+ * __memp_set_pgcookie --
+ * Set the pgin/pgout cookie.
+ */
+static int
+__memp_set_pgcookie(dbmfp, pgcookie)
+ DB_MPOOLFILE *dbmfp;
+ DBT *pgcookie;
+{
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_pgcookie");
+
+ dbmfp->pgcookie = pgcookie;
+ return (0);
+}
+
+/*
+ * __memp_set_priority --
+ * Set the cache priority for pages from this file.
+ */
+static int
+__memp_set_priority(dbmfp, priority)
+ DB_MPOOLFILE *dbmfp;
+ DB_CACHE_PRIORITY priority;
+{
+ switch (priority) {
+ case DB_PRIORITY_VERY_LOW:
+ dbmfp->mfp->priority = MPOOL_PRI_VERY_LOW;
+ break;
+ case DB_PRIORITY_LOW:
+ dbmfp->mfp->priority = MPOOL_PRI_LOW;
+ break;
+ case DB_PRIORITY_DEFAULT:
+ dbmfp->mfp->priority = MPOOL_PRI_DEFAULT;
+ break;
+ case DB_PRIORITY_HIGH:
+ dbmfp->mfp->priority = MPOOL_PRI_HIGH;
+ break;
+ case DB_PRIORITY_VERY_HIGH:
+ dbmfp->mfp->priority = MPOOL_PRI_VERY_HIGH;
+ break;
+ default:
+ __db_err(dbmfp->dbmp->dbenv,
+ "Unknown priority value: %d", priority);
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+/*
+ * __memp_fopen --
+ * Open a backing file for the memory pool.
+ */
+static int
+__memp_fopen(dbmfp, path, flags, mode, pagesize)
+ DB_MPOOLFILE *dbmfp;
+ const char *path;
+ u_int32_t flags;
+ int mode;
+ size_t pagesize;
+{
+ DB_ENV *dbenv;
DB_MPOOL *dbmp;
- dbmp = dbmpf->dbmp;
+ int ret;
+
+ dbmp = dbmfp->dbmp;
+ dbenv = dbmp->dbenv;
+
+ PANIC_CHECK(dbenv);
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "memp_fopen", flags,
+ DB_CREATE | DB_DIRECT | DB_EXTENT |
+ DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0)
+ return (ret);
/*
- * This bit is protected in the queue code because the metapage
- * is locked so we can avoid geting the region lock.
- * If this gets used from other than the queue code, we cannot.
+ * Require a non-zero, power-of-two pagesize, smaller than the
+ * clear length.
*/
- if (!F_ISSET(dbmpf->mfp, MP_UNLINK))
- return;
- R_LOCK(dbmp->dbenv, dbmp->reginfo);
- F_CLR(dbmpf->mfp, MP_UNLINK);
- R_UNLOCK(dbmp->dbenv, dbmp->reginfo);
+ if (pagesize == 0 || !POWER_OF_TWO(pagesize)) {
+ __db_err(dbenv,
+ "memp_fopen: page sizes must be a power-of-2");
+ return (EINVAL);
+ }
+ if (dbmfp->clear_len > pagesize) {
+ __db_err(dbenv,
+ "memp_fopen: clear length larger than page size");
+ return (EINVAL);
+ }
+
+ /* Read-only checks, and local flag. */
+ if (LF_ISSET(DB_RDONLY) && path == NULL) {
+ __db_err(dbenv,
+ "memp_fopen: temporary files can't be readonly");
+ return (EINVAL);
+ }
+
+ return (__memp_fopen_int(dbmfp, NULL, path, flags, mode, pagesize));
}
/*
- * __memp_fopen --
+ * __memp_fopen_int --
* Open a backing file for the memory pool; internal version.
*
- * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
- * PUBLIC: u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
+ * PUBLIC: int __memp_fopen_int __P((DB_MPOOLFILE *,
+ * PUBLIC: MPOOLFILE *, const char *, u_int32_t, int, size_t));
*/
int
-__memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp)
- DB_MPOOL *dbmp;
+__memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
+ DB_MPOOLFILE *dbmfp;
MPOOLFILE *mfp;
const char *path;
u_int32_t flags;
- int mode, needlock;
+ int mode;
size_t pagesize;
- DB_MPOOL_FINFO *finfop;
- DB_MPOOLFILE **retp;
{
DB_ENV *dbenv;
- DB_MPOOLFILE *dbmfp;
- DB_MPOOL_FINFO finfo;
+ DB_MPOOL *dbmp;
+ MPOOL *mp;
db_pgno_t last_pgno;
size_t maxmap;
u_int32_t mbytes, bytes, oflags;
- int ret;
+ int mfp_alloc, ret;
u_int8_t idbuf[DB_FILE_ID_LEN];
char *rpath;
+ void *p;
+ dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
- ret = 0;
+ mp = dbmp->reginfo[0].primary;
+ mfp_alloc = ret = 0;
rpath = NULL;
/*
- * If mfp is provided, we take the DB_MPOOL_FINFO information from
- * the mfp. We don't bother initializing everything, because some
- * of them are expensive to acquire. If no mfp is provided and the
- * finfop argument is NULL, we default the values.
+ * Set the page size so os_open can decide whether to turn buffering
+ * off if the DB_DIRECT_DB flag is set.
*/
- if (finfop == NULL) {
- memset(&finfo, 0, sizeof(finfo));
- if (mfp != NULL) {
- finfo.ftype = mfp->ftype;
- finfo.pgcookie = NULL;
- finfo.fileid = NULL;
- finfo.lsn_offset = mfp->lsn_off;
- finfo.clear_len = mfp->clear_len;
- } else {
- finfo.ftype = 0;
- finfo.pgcookie = NULL;
- finfo.fileid = NULL;
- finfo.lsn_offset = -1;
- finfo.clear_len = 0;
- }
- finfop = &finfo;
- }
+ dbmfp->fhp->pagesize = (u_int32_t)pagesize;
- /* Allocate and initialize the per-process structure. */
- if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
- return (ret);
- dbmfp->dbmp = dbmp;
- dbmfp->ref = 1;
- if (LF_ISSET(DB_RDONLY))
+ /*
+ * If it's a temporary file, delay the open until we actually need
+ * to write the file, and we know we can't join any existing files.
+ */
+ if (path == NULL)
+ goto alloc;
+
+ /*
+ * Get the real name for this file and open it. If it's a Queue extent
+ * file, it may not exist, and that's OK.
+ */
+ oflags = 0;
+ if (LF_ISSET(DB_CREATE))
+ oflags |= DB_OSO_CREATE;
+ if (LF_ISSET(DB_DIRECT))
+ oflags |= DB_OSO_DIRECT;
+ if (LF_ISSET(DB_RDONLY)) {
F_SET(dbmfp, MP_READONLY);
+ oflags |= DB_OSO_RDONLY;
+ }
+ if ((ret =
+ __db_appname(dbenv, DB_APP_DATA, path, 0, NULL, &rpath)) != 0)
+ goto err;
+ if ((ret = __os_open(dbenv, rpath, oflags, mode, dbmfp->fhp)) != 0) {
+ if (!LF_ISSET(DB_EXTENT))
+ __db_err(dbenv, "%s: %s", rpath, db_strerror(ret));
+ goto err;
+ }
- if (path == NULL) {
- if (LF_ISSET(DB_RDONLY)) {
- __db_err(dbenv,
- "memp_fopen: temporary files can't be readonly");
- ret = EINVAL;
- goto err;
- }
- last_pgno = 0;
- } else {
- /* Get the real name for this file and open it. */
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, path, 0, NULL, &rpath)) != 0)
- goto err;
- oflags = 0;
- if (LF_ISSET(DB_CREATE))
- oflags |= DB_OSO_CREATE;
- if (LF_ISSET(DB_RDONLY))
- oflags |= DB_OSO_RDONLY;
- if ((ret =
- __os_open(dbenv, rpath, oflags, mode, &dbmfp->fh)) != 0) {
- if (!LF_ISSET(DB_EXTENT))
- __db_err(dbenv,
- "%s: %s", rpath, db_strerror(ret));
+ /*
+ * Figure out the file's size.
+ *
+ * !!!
+ * We can't use off_t's here, or in any code in the mainline library
+ * for that matter. (We have to use them in the os stubs, of course,
+ * as there are system calls that take them as arguments.) The reason
+ * is some customers build in environments where an off_t is 32-bits,
+ * but still run where offsets are 64-bits, and they pay us a lot of
+ * money.
+ */
+ if ((ret = __os_ioinfo(
+ dbenv, rpath, dbmfp->fhp, &mbytes, &bytes, NULL)) != 0) {
+ __db_err(dbenv, "%s: %s", rpath, db_strerror(ret));
+ goto err;
+ }
+
+ /*
+ * Get the file id if we weren't given one. Generated file id's
+ * don't use timestamps, otherwise there'd be no chance of any
+ * other process joining the party.
+ */
+ if (dbmfp->fileid == NULL) {
+ if ((ret = __os_fileid(dbenv, rpath, 0, idbuf)) != 0)
goto err;
- }
+ dbmfp->fileid = idbuf;
+ }
+
+ /*
+ * If our caller knows what mfp we're using, increment the ref count,
+ * no need to search.
+ *
+ * We don't need to acquire a lock other than the mfp itself, because
+ * we know there's another reference and it's not going away.
+ */
+ if (mfp != NULL) {
+ MUTEX_LOCK(dbenv, &mfp->mutex);
+ ++mfp->mpf_cnt;
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
+ goto check_map;
+ }
+
+ /*
+ * If not creating a temporary file, walk the list of MPOOLFILE's,
+ * looking for a matching file. Files backed by temporary files
+ * or previously removed files can't match.
+ *
+ * DB_TRUNCATE support.
+ *
+ * The fileID is a filesystem unique number (e.g., a UNIX dev/inode
+ * pair) plus a timestamp. If files are removed and created in less
+ * than a second, the fileID can be repeated. The problem with
+ * repetition happens when the file that previously had the fileID
+ * value still has pages in the pool, since we don't want to use them
+ * to satisfy requests for the new file.
+ *
+ * Because the DB_TRUNCATE flag reuses the dev/inode pair, repeated
+ * opens with that flag set guarantees matching fileIDs when the
+ * machine can open a file and then re-open with truncate within a
+ * second. For this reason, we pass that flag down, and, if we find
+ * a matching entry, we ensure that it's never found again, and we
+ * create a new entry for the current request.
+ */
+ R_LOCK(dbenv, dbmp->reginfo);
+ for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
+ mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
+ /* Skip dead files and temporary files. */
+ if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
+ continue;
+
+ /* Skip non-matching files. */
+ if (memcmp(dbmfp->fileid, R_ADDR(dbmp->reginfo,
+ mfp->fileid_off), DB_FILE_ID_LEN) != 0)
+ continue;
/*
- * Don't permit files that aren't a multiple of the pagesize,
- * and find the number of the last page in the file, all the
- * time being careful not to overflow 32 bits.
+ * If the file is being truncated, remove it from the system
+ * and create a new entry.
*
* !!!
- * We can't use off_t's here, or in any code in the mainline
- * library for that matter. (We have to use them in the os
- * stubs, of course, as there are system calls that take them
- * as arguments.) The reason is that some customers build in
- * environments where an off_t is 32-bits, but still run where
- * offsets are 64-bits, and they pay us a lot of money.
+ * We should be able to set mfp to NULL and break out of the
+ * loop, but I like the idea of checking all the entries.
*/
- if ((ret = __os_ioinfo(dbenv, rpath,
- &dbmfp->fh, &mbytes, &bytes, NULL)) != 0) {
- __db_err(dbenv, "%s: %s", rpath, db_strerror(ret));
- goto err;
+ if (LF_ISSET(DB_TRUNCATE)) {
+ MUTEX_LOCK(dbenv, &mfp->mutex);
+ MPOOLFILE_IGNORE(mfp);
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
+ continue;
}
/*
- * If we're doing a verify, we might have to cope with
- * a truncated file; if the file size is not a multiple
- * of the page size, round down to a page--we'll
- * take care of the partial page outside the memp system.
+ * Some things about a file cannot be changed: the clear length,
+ * page size, or lSN location.
+ *
+ * The file type can change if the application's pre- and post-
+ * processing needs change. For example, an application that
+ * created a hash subdatabase in a database that was previously
+ * all btree.
+ *
+ * XXX
+ * We do not check to see if the pgcookie information changed,
+ * or update it if it is, this might be a bug.
*/
+ if (dbmfp->clear_len != mfp->clear_len ||
+ pagesize != mfp->stat.st_pagesize ||
+ dbmfp->lsn_offset != mfp->lsn_off) {
+ __db_err(dbenv,
+ "%s: clear length, page size or LSN location changed",
+ path);
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ ret = EINVAL;
+ goto err;
+ }
+
+ if (dbmfp->ftype != 0)
+ mfp->ftype = dbmfp->ftype;
+
+ MUTEX_LOCK(dbenv, &mfp->mutex);
+ ++mfp->mpf_cnt;
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
+ break;
+ }
+ R_UNLOCK(dbenv, dbmp->reginfo);
+
+ if (mfp != NULL)
+ goto check_map;
+
+alloc: /* Allocate and initialize a new MPOOLFILE. */
+ if ((ret = __memp_alloc(
+ dbmp, dbmp->reginfo, NULL, sizeof(MPOOLFILE), NULL, &mfp)) != 0)
+ goto err;
+ mfp_alloc = 1;
+ memset(mfp, 0, sizeof(MPOOLFILE));
+ mfp->mpf_cnt = 1;
+ mfp->ftype = dbmfp->ftype;
+ mfp->stat.st_pagesize = pagesize;
+ mfp->lsn_off = dbmfp->lsn_offset;
+ mfp->clear_len = dbmfp->clear_len;
+
+ if (LF_ISSET(DB_DIRECT))
+ F_SET(mfp, MP_DIRECT);
+ if (LF_ISSET(DB_EXTENT))
+ F_SET(mfp, MP_EXTENT);
+ F_SET(mfp, MP_CAN_MMAP);
- /* Page sizes have to be a power-of-two, ignore mbytes. */
+ if (path == NULL)
+ F_SET(mfp, MP_TEMP);
+ else {
+ /*
+ * Don't permit files that aren't a multiple of the pagesize,
+ * and find the number of the last page in the file, all the
+ * time being careful not to overflow 32 bits.
+ *
+ * During verify or recovery, we might have to cope with a
+ * truncated file; if the file size is not a multiple of the
+ * page size, round down to a page, we'll take care of the
+ * partial page outside the mpool system.
+ */
if (bytes % pagesize != 0) {
if (LF_ISSET(DB_ODDFILESIZE))
- /*
- * If we're doing a verify, we might
- * have to cope with a truncated file;
- * round down, we'll worry about the partial
- * page outside the memp system.
- */
- bytes -= (bytes % pagesize);
+ bytes -= (u_int32_t)(bytes % pagesize);
else {
__db_err(dbenv,
- "%s: file size not a multiple of the pagesize",
- rpath);
+ "%s: file size not a multiple of the pagesize", rpath);
ret = EINVAL;
goto err;
}
}
- last_pgno = mbytes * (MEGABYTE / pagesize);
- last_pgno += bytes / pagesize;
-
- /* Correction: page numbers are zero-based, not 1-based. */
+ /*
+ * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a
+ * page get, we have to increment the last page in the file.
+ * Figure it out and save it away.
+ *
+ * Note correction: page numbers are zero-based, not 1-based.
+ */
+ last_pgno = (db_pgno_t)(mbytes * (MEGABYTE / pagesize));
+ last_pgno += (db_pgno_t)(bytes / pagesize);
if (last_pgno != 0)
--last_pgno;
+ mfp->orig_last_pgno = mfp->last_pgno = last_pgno;
- /*
- * Get the file id if we weren't given one. Generated file id's
- * don't use timestamps, otherwise there'd be no chance of any
- * other process joining the party.
- */
- if (finfop->fileid == NULL) {
- if ((ret = __os_fileid(dbenv, rpath, 0, idbuf)) != 0)
- goto err;
- finfop->fileid = idbuf;
- }
- }
+ /* Copy the file path into shared memory. */
+ if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
+ NULL, strlen(path) + 1, &mfp->path_off, &p)) != 0)
+ goto err;
+ memcpy(p, path, strlen(path) + 1);
- /*
- * If we weren't provided an underlying shared object to join with,
- * find/allocate the shared file objects. Also allocate space for
- * for the per-process thread lock.
- */
- if (needlock)
- R_LOCK(dbenv, dbmp->reginfo);
- if (mfp == NULL)
- ret = __memp_mf_open(
- dbmp, path, pagesize, last_pgno, finfop, flags, &mfp);
- else {
- ++mfp->mpf_cnt;
- ret = 0;
+ /* Copy the file identification string into shared memory. */
+ if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
+ NULL, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0)
+ goto err;
+ memcpy(p, dbmfp->fileid, DB_FILE_ID_LEN);
}
- if (needlock)
- R_UNLOCK(dbenv, dbmp->reginfo);
- if (ret != 0)
- goto err;
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if ((ret = __db_mutex_alloc(
- dbenv, dbmp->reginfo, &dbmfp->mutexp)) != 0)
- goto err;
- if ((ret = __db_mutex_init(
- dbenv, dbmfp->mutexp, 0, MUTEX_THREAD)) != 0)
+ /* Copy the page cookie into shared memory. */
+ if (dbmfp->pgcookie == NULL || dbmfp->pgcookie->size == 0) {
+ mfp->pgcookie_len = 0;
+ mfp->pgcookie_off = 0;
+ } else {
+ if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
+ NULL, dbmfp->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
goto err;
-
- /* XXX: KEITH: CLOSE THE FILE ON FAILURE? */
+ memcpy(p, dbmfp->pgcookie->data, dbmfp->pgcookie->size);
+ mfp->pgcookie_len = dbmfp->pgcookie->size;
}
- dbmfp->mfp = mfp;
+ /*
+ * Prepend the MPOOLFILE to the list of MPOOLFILE's.
+ */
+ R_LOCK(dbenv, dbmp->reginfo);
+ ret = __db_mutex_setup(dbenv, dbmp->reginfo, &mfp->mutex,
+ MUTEX_NO_RLOCK);
+ if (ret == 0)
+ SH_TAILQ_INSERT_HEAD(&mp->mpfq, mfp, q, __mpoolfile);
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ if (ret != 0)
+ goto err;
+check_map:
/*
* If a file:
- * + is read-only
* + isn't temporary
+ * + is read-only
* + doesn't require any pgin/pgout support
* + the DB_NOMMAP flag wasn't set (in either the file open or
* the environment in which it was opened)
@@ -332,20 +579,19 @@ __memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp)
* NFS mounted partition, and we can fail in buffer I/O just as easily
* as here.
*
- * XXX
* We'd like to test to see if the file is too big to mmap. Since we
* don't know what size or type off_t's or size_t's are, or the largest
* unsigned integral type is, or what random insanity the local C
* compiler will perpetrate, doing the comparison in a portable way is
* flatly impossible. Hope that mmap fails if the file is too large.
*/
-#define DB_MAXMMAPSIZE (10 * 1024 * 1024) /* 10 Mb. */
+#define DB_MAXMMAPSIZE (10 * 1024 * 1024) /* 10 MB. */
if (F_ISSET(mfp, MP_CAN_MMAP)) {
- if (!F_ISSET(dbmfp, MP_READONLY))
- F_CLR(mfp, MP_CAN_MMAP);
if (path == NULL)
F_CLR(mfp, MP_CAN_MMAP);
- if (finfop->ftype != 0)
+ if (!F_ISSET(dbmfp, MP_READONLY))
+ F_CLR(mfp, MP_CAN_MMAP);
+ if (dbmfp->ftype != 0)
F_CLR(mfp, MP_CAN_MMAP);
if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP))
F_CLR(mfp, MP_CAN_MMAP);
@@ -354,260 +600,239 @@ __memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp)
if (mbytes > maxmap / MEGABYTE ||
(mbytes == maxmap / MEGABYTE && bytes >= maxmap % MEGABYTE))
F_CLR(mfp, MP_CAN_MMAP);
- }
- dbmfp->addr = NULL;
- if (F_ISSET(mfp, MP_CAN_MMAP)) {
- dbmfp->len = (size_t)mbytes * MEGABYTE + bytes;
- if (__os_mapfile(dbenv, rpath,
- &dbmfp->fh, dbmfp->len, 1, &dbmfp->addr) != 0) {
- dbmfp->addr = NULL;
- F_CLR(mfp, MP_CAN_MMAP);
+
+ dbmfp->addr = NULL;
+ if (F_ISSET(mfp, MP_CAN_MMAP)) {
+ dbmfp->len = (size_t)mbytes * MEGABYTE + bytes;
+ if (__os_mapfile(dbenv, rpath,
+ dbmfp->fhp, dbmfp->len, 1, &dbmfp->addr) != 0) {
+ dbmfp->addr = NULL;
+ F_CLR(mfp, MP_CAN_MMAP);
+ }
}
}
- if (rpath != NULL)
- __os_freestr(rpath);
+ dbmfp->mfp = mfp;
+
+ F_SET(dbmfp, MP_OPEN_CALLED);
+
+ /* Add the file to the process' list of DB_MPOOLFILEs. */
MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
- *retp = dbmfp;
- return (0);
+ if (0) {
+err: if (F_ISSET(dbmfp->fhp, DB_FH_VALID))
+ (void)__os_closehandle(dbenv, dbmfp->fhp);
+
+ if (mfp_alloc) {
+ R_LOCK(dbenv, dbmp->reginfo);
+ if (mfp->path_off != 0)
+ __db_shalloc_free(dbmp->reginfo[0].addr,
+ R_ADDR(dbmp->reginfo, mfp->path_off));
+ if (mfp->fileid_off != 0)
+ __db_shalloc_free(dbmp->reginfo[0].addr,
+ R_ADDR(dbmp->reginfo, mfp->fileid_off));
+ __db_shalloc_free(dbmp->reginfo[0].addr, mfp);
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ }
-err: /*
- * Note that we do not have to free the thread mutex, because we
- * never get to here after we have successfully allocated it.
- */
- if (rpath != NULL)
- __os_freestr(rpath);
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID))
- (void)__os_closehandle(&dbmfp->fh);
- if (dbmfp != NULL) {
- if (dbmfp->mutexp != NULL)
- __db_mutex_free(dbenv, dbmp->reginfo, dbmfp->mutexp);
- __os_free(dbmfp, sizeof(DB_MPOOLFILE));
}
+ if (rpath != NULL)
+ __os_free(dbenv, rpath);
return (ret);
}
/*
- * __memp_mf_open --
- * Open an MPOOLFILE.
+ * __memp_get_fileid --
+ * Return the file ID.
+ *
+ * XXX
+ * Undocumented interface: DB private.
*/
-static int
-__memp_mf_open(dbmp, path, pagesize, last_pgno, finfop, flags, retp)
- DB_MPOOL *dbmp;
- const char *path;
- size_t pagesize;
- db_pgno_t last_pgno;
- DB_MPOOL_FINFO *finfop;
- u_int32_t flags;
- MPOOLFILE **retp;
+static void
+__memp_get_fileid(dbmfp, fidp)
+ DB_MPOOLFILE *dbmfp;
+ u_int8_t *fidp;
{
- MPOOL *mp;
- MPOOLFILE *mfp;
- int ret;
- void *p;
-
-#define ISTEMPORARY (path == NULL)
-
/*
- * If not creating a temporary file, walk the list of MPOOLFILE's,
- * looking for a matching file. Files backed by temporary files
- * or previously removed files can't match.
- *
- * DB_TRUNCATE support.
+ * No lock needed -- we're using the handle, it had better not
+ * be going away.
*
- * The fileID is a filesystem unique number (e.g., a UNIX dev/inode
- * pair) plus a timestamp. If files are removed and created in less
- * than a second, the fileID can be repeated. The problem with
- * repetition happens when the file that previously had the fileID
- * value still has pages in the pool, since we don't want to use them
- * to satisfy requests for the new file.
- *
- * Because the DB_TRUNCATE flag reuses the dev/inode pair, repeated
- * opens with that flag set guarantees matching fileIDs when the
- * machine can open a file and then re-open with truncate within a
- * second. For this reason, we pass that flag down, and, if we find
- * a matching entry, we ensure that it's never found again, and we
- * create a new entry for the current request.
+ * !!!
+ * Get the fileID out of the region, not out of the DB_MPOOLFILE
+ * structure because the DB_MPOOLFILE reference is possibly short
+ * lived, and isn't to be trusted.
*/
- if (!ISTEMPORARY) {
- mp = dbmp->reginfo[0].primary;
- for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
- mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
- if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
- continue;
- if (memcmp(finfop->fileid, R_ADDR(dbmp->reginfo,
- mfp->fileid_off), DB_FILE_ID_LEN) == 0) {
- if (LF_ISSET(DB_TRUNCATE)) {
- MEMP_FREMOVE(mfp);
- continue;
- }
- if (finfop->clear_len != mfp->clear_len ||
- pagesize != mfp->stat.st_pagesize) {
- __db_err(dbmp->dbenv,
- "%s: page size or clear length changed",
- path);
- return (EINVAL);
- }
-
- /*
- * It's possible that our needs for pre- and
- * post-processing are changing. For example,
- * an application created a hash subdatabase
- * in a database that was previously all btree.
- */
- if (finfop->ftype != 0)
- mfp->ftype = finfop->ftype;
-
- ++mfp->mpf_cnt;
-
- *retp = mfp;
- return (0);
- }
- }
- }
+ memcpy(fidp, R_ADDR(
+ dbmfp->dbmp->reginfo, dbmfp->mfp->fileid_off), DB_FILE_ID_LEN);
+}
- /* Allocate a new MPOOLFILE. */
- if ((ret = __memp_alloc(
- dbmp, dbmp->reginfo, NULL, sizeof(MPOOLFILE), NULL, &mfp)) != 0)
- goto mem_err;
- *retp = mfp;
+/*
+ * __memp_last_pgno --
+ * Return the page number of the last page in the file.
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+static void
+__memp_last_pgno(dbmfp, pgnoaddr)
+ DB_MPOOLFILE *dbmfp;
+ db_pgno_t *pgnoaddr;
+{
+ DB_ENV *dbenv;
+ DB_MPOOL *dbmp;
- /* Initialize the structure. */
- memset(mfp, 0, sizeof(MPOOLFILE));
- mfp->mpf_cnt = 1;
- mfp->ftype = finfop->ftype;
- mfp->lsn_off = finfop->lsn_offset;
- mfp->clear_len = finfop->clear_len;
+ dbmp = dbmfp->dbmp;
+ dbenv = dbmp->dbenv;
- /*
- * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a memp_fget,
- * we have to know the last page in the file. Figure it out and save
- * it away.
- */
- mfp->stat.st_pagesize = pagesize;
- mfp->orig_last_pgno = mfp->last_pgno = last_pgno;
+ R_LOCK(dbenv, dbmp->reginfo);
+ *pgnoaddr = dbmfp->mfp->last_pgno;
+ R_UNLOCK(dbenv, dbmp->reginfo);
+}
- if (ISTEMPORARY)
- F_SET(mfp, MP_TEMP);
- else {
- /* Copy the file path into shared memory. */
- if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
- NULL, strlen(path) + 1, &mfp->path_off, &p)) != 0)
- goto err;
- memcpy(p, path, strlen(path) + 1);
+/*
+ * __memp_refcnt --
+ * Return the current reference count.
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+static void
+__memp_refcnt(dbmfp, cntp)
+ DB_MPOOLFILE *dbmfp;
+ db_pgno_t *cntp;
+{
+ DB_ENV *dbenv;
- /* Copy the file identification string into shared memory. */
- if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
- NULL, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0)
- goto err;
- memcpy(p, finfop->fileid, DB_FILE_ID_LEN);
+ dbenv = dbmfp->dbmp->dbenv;
- F_SET(mfp, MP_CAN_MMAP);
- }
+ MUTEX_LOCK(dbenv, &dbmfp->mfp->mutex);
+ *cntp = dbmfp->mfp->mpf_cnt;
+ MUTEX_UNLOCK(dbenv, &dbmfp->mfp->mutex);
+}
- /* Copy the page cookie into shared memory. */
- if (finfop->pgcookie == NULL || finfop->pgcookie->size == 0) {
- mfp->pgcookie_len = 0;
- mfp->pgcookie_off = 0;
- } else {
- if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
- NULL, finfop->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
- goto err;
- memcpy(p, finfop->pgcookie->data, finfop->pgcookie->size);
- mfp->pgcookie_len = finfop->pgcookie->size;
- }
+/*
+ * __memp_set_unlink --
+ * Set unlink on last close flag.
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+static void
+__memp_set_unlink(dbmpf, set)
+ DB_MPOOLFILE *dbmpf;
+ int set;
+{
+ DB_ENV *dbenv;
- /* Prepend the MPOOLFILE to the list of MPOOLFILE's. */
- mp = dbmp->reginfo[0].primary;
- SH_TAILQ_INSERT_HEAD(&mp->mpfq, mfp, q, __mpoolfile);
+ dbenv = dbmpf->dbmp->dbenv;
- if (0) {
-err: if (mfp->path_off != 0)
- __db_shalloc_free(dbmp->reginfo[0].addr,
- R_ADDR(dbmp->reginfo, mfp->path_off));
- if (mfp->fileid_off != 0)
- __db_shalloc_free(dbmp->reginfo[0].addr,
- R_ADDR(dbmp->reginfo, mfp->fileid_off));
- if (mfp != NULL)
- __db_shalloc_free(dbmp->reginfo[0].addr, mfp);
-mem_err: __db_err(dbmp->dbenv,
- "Unable to allocate memory for mpool file");
- }
- return (ret);
+ MUTEX_LOCK(dbenv, &dbmpf->mfp->mutex);
+ if (set)
+ F_SET(dbmpf->mfp, MP_UNLINK);
+ else
+ F_CLR(dbmpf->mfp, MP_UNLINK);
+ MUTEX_UNLOCK(dbenv, &dbmpf->mfp->mutex);
}
/*
* memp_fclose --
* Close a backing file for the memory pool.
*/
+static int
+__memp_fclose(dbmfp, flags)
+ DB_MPOOLFILE *dbmfp;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ int ret, t_ret;
+
+ dbenv = dbmfp->dbmp->dbenv;
+
+ PANIC_CHECK(dbenv);
+
+ /*
+ * XXX
+ * DB_MPOOL_DISCARD: Undocumented flag: DB private.
+ */
+ ret = __db_fchk(dbenv, "DB_MPOOLFILE->close", flags, DB_MPOOL_DISCARD);
+
+ if ((t_ret = __memp_fclose_int(dbmfp, flags)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
+
+/*
+ * __memp_fclose_int --
+ * Internal version of __memp_fclose.
+ *
+ * PUBLIC: int __memp_fclose_int __P((DB_MPOOLFILE *, u_int32_t));
+ */
int
-memp_fclose(dbmfp)
+__memp_fclose_int(dbmfp, flags)
DB_MPOOLFILE *dbmfp;
+ u_int32_t flags;
{
DB_ENV *dbenv;
DB_MPOOL *dbmp;
MPOOLFILE *mfp;
char *rpath;
- int ret, t_ret;
+ int deleted, ret, t_ret;
dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
ret = 0;
- PANIC_CHECK(dbenv);
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fclose(dbmfp));
-#endif
-
/*
- * Remove the DB_MPOOLFILE from the queue. This has to happen before
- * we perform any action that can fail, otherwise __memp_close may
- * loop infinitely when calling us to discard all of the DB_MPOOLFILEs.
+ * We have to reference count DB_MPOOLFILE structures as other threads
+ * in the process may be using them. Here's the problem:
+ *
+ * Thread A opens a database.
+ * Thread B uses thread A's DB_MPOOLFILE to write a buffer
+ * in order to free up memory in the mpool cache.
+ * Thread A closes the database while thread B is using the
+ * DB_MPOOLFILE structure.
+ *
+ * By opening all databases before creating any threads, and closing
+ * the databases after all the threads have exited, applications get
+ * better performance and avoid the problem path entirely.
+ *
+ * Regardless, holding the DB_MPOOLFILE to flush a dirty buffer is a
+ * short-term lock, even in worst case, since we better be the only
+ * thread of control using the DB_MPOOLFILE structure to read pages
+ * *into* the cache. Wait until we're the only reference holder and
+ * remove the DB_MPOOLFILE structure from the list, so nobody else can
+ * find it. We do this, rather than have the last reference holder
+ * (whoever that might be) discard the DB_MPOOLFILE structure, because
+ * we'd rather write error messages to the application in the close
+ * routine, not in the checkpoint/sync routine.
+ *
+ * !!!
+ * It's possible the DB_MPOOLFILE was never added to the DB_MPOOLFILE
+ * file list, check the DB_OPEN_CALLED flag to be sure.
*/
- for (;;) {
+ for (deleted = 0;;) {
MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
-
- /*
- * We have to reference count DB_MPOOLFILE structures as other
- * threads may be using them. The problem only happens if the
- * application makes a bad design choice. Here's the path:
- *
- * Thread A opens a database.
- * Thread B uses thread A's DB_MPOOLFILE to write a buffer
- * in order to free up memory in the mpool cache.
- * Thread A closes the database while thread B is using the
- * DB_MPOOLFILE structure.
- *
- * By opening all databases before creating the threads, and
- * closing them after the threads have exited, applications
- * get better performance and avoid the problem path entirely.
- *
- * Regardless, holding the DB_MPOOLFILE to flush a dirty buffer
- * is a short-term lock, even in worst case, since we better be
- * the only thread of control using the DB_MPOOLFILE structure
- * to read pages *into* the cache. Wait until we're the only
- * reference holder and remove the DB_MPOOLFILE structure from
- * the list, so nobody else can even find it.
- */
if (dbmfp->ref == 1) {
- TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);
- break;
+ if (F_ISSET(dbmfp, MP_OPEN_CALLED))
+ TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);
+ deleted = 1;
}
MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
- (void)__os_sleep(dbenv, 1, 0);
+ if (deleted)
+ break;
+ __os_sleep(dbenv, 1, 0);
}
- MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
/* Complain if pinned blocks never returned. */
- if (dbmfp->pinref != 0)
+ if (dbmfp->pinref != 0) {
__db_err(dbenv, "%s: close: %lu blocks left pinned",
__memp_fn(dbmfp), (u_long)dbmfp->pinref);
+ ret = __db_panic(dbenv, DB_RUNRECOVERY);
+ }
/* Discard any mmap information. */
if (dbmfp->addr != NULL &&
@@ -615,11 +840,11 @@ memp_fclose(dbmfp)
__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(ret));
/* Close the file; temporary files may not yet have been created. */
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID) &&
- (t_ret = __os_closehandle(&dbmfp->fh)) != 0) {
+ if (F_ISSET(dbmfp->fhp, DB_FH_VALID) &&
+ (t_ret = __os_closehandle(dbenv, dbmfp->fhp)) != 0) {
__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(t_ret));
- if (ret != 0)
- t_ret = ret;
+ if (ret == 0)
+ ret = t_ret;
}
/* Discard the thread mutex. */
@@ -628,38 +853,51 @@ memp_fclose(dbmfp)
/*
* Discard our reference on the the underlying MPOOLFILE, and close
- * it if it's no longer useful to anyone.
- *
- * If we're not discarding it, and it's a temp file, this means
- * all the outstanding references belong to unflushed buffers.
- * (A temp file can only be referenced by one DB_MPOOLFILE).
- * We don't care about preserving any of those buffers, so mark
- * the MPOOLFILE as dead so that when we try to flush them,
- * even the dirty ones just get discarded.
+ * it if it's no longer useful to anyone. It possible the open of
+ * the file never happened or wasn't successful, in which case, mpf
+ * will be NULL;
*/
- R_LOCK(dbenv, dbmp->reginfo);
- mfp = dbmfp->mfp;
- if (--mfp->mpf_cnt == 0) {
+ if ((mfp = dbmfp->mfp) == NULL)
+ goto done;
+
+ /*
+ * If it's a temp file, all outstanding references belong to unflushed
+ * buffers. (A temp file can only be referenced by one DB_MPOOLFILE).
+ * We don't care about preserving any of those buffers, so mark the
+ * MPOOLFILE as dead so that even the dirty ones just get discarded
+ * when we try to flush them.
+ */
+ deleted = 0;
+ MUTEX_LOCK(dbenv, &mfp->mutex);
+ if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) {
+ if (LF_ISSET(DB_MPOOL_DISCARD) ||
+ F_ISSET(mfp, MP_TEMP | MP_UNLINK))
+ MPOOLFILE_IGNORE(mfp);
if (F_ISSET(mfp, MP_UNLINK)) {
- MEMP_FREMOVE(mfp);
if ((t_ret = __db_appname(dbmp->dbenv,
- DB_APP_DATA, NULL, R_ADDR(dbmp->reginfo,
+ DB_APP_DATA, R_ADDR(dbmp->reginfo,
mfp->path_off), 0, NULL, &rpath)) != 0 && ret == 0)
ret = t_ret;
- if (t_ret == 0 && (t_ret =
- __os_unlink(dbmp->dbenv, rpath) != 0 && ret == 0))
+ if (t_ret == 0) {
+ if ((t_ret = __os_unlink(
+ dbmp->dbenv, rpath) != 0) && ret == 0)
+ ret = t_ret;
+ __os_free(dbenv, rpath);
+ }
+ }
+ if (mfp->block_cnt == 0) {
+ if ((t_ret =
+ __memp_mf_discard(dbmp, mfp)) != 0 && ret == 0)
ret = t_ret;
- __os_free(rpath, 0);
+ deleted = 1;
}
- if (mfp->block_cnt == 0)
- __memp_mf_discard(dbmp, mfp);
}
- else if (F_ISSET(mfp, MP_TEMP))
- MEMP_FREMOVE(mfp);
- R_UNLOCK(dbenv, dbmp->reginfo);
+ if (deleted == 0)
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
/* Discard the DB_MPOOLFILE structure. */
- __os_free(dbmfp, sizeof(DB_MPOOLFILE));
+done: __os_free(dbenv, dbmfp->fhp);
+ __os_free(dbenv, dbmfp);
return (ret);
}
@@ -668,20 +906,69 @@ memp_fclose(dbmfp)
* __memp_mf_discard --
* Discard an MPOOLFILE.
*
- * PUBLIC: void __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *));
+ * PUBLIC: int __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *));
*/
-void
+int
__memp_mf_discard(dbmp, mfp)
DB_MPOOL *dbmp;
MPOOLFILE *mfp;
{
+ DB_ENV *dbenv;
+ DB_FH fh;
+ DB_MPOOL_STAT *sp;
MPOOL *mp;
+ char *rpath;
+ int ret;
+ dbenv = dbmp->dbenv;
mp = dbmp->reginfo[0].primary;
+ ret = 0;
+
+ /*
+ * Expects caller to be holding the MPOOLFILE mutex.
+ *
+ * When discarding a file, we have to flush writes from it to disk.
+ * The scenario is that dirty buffers from this file need to be
+ * flushed to satisfy a future checkpoint, but when the checkpoint
+ * calls mpool sync, the sync code won't know anything about them.
+ */
+ if (!F_ISSET(mfp, MP_DEADFILE) &&
+ (ret = __db_appname(dbenv, DB_APP_DATA,
+ R_ADDR(dbmp->reginfo, mfp->path_off), 0, NULL, &rpath)) == 0) {
+ if ((ret = __os_open(dbenv, rpath, 0, 0, &fh)) == 0) {
+ ret = __os_fsync(dbenv, &fh);
+ (void)__os_closehandle(dbenv, &fh);
+ }
+ __os_free(dbenv, rpath);
+ }
+
+ /*
+ * We have to release the MPOOLFILE lock before acquiring the region
+ * lock so that we don't deadlock. Make sure nobody ever looks at
+ * this structure again.
+ */
+ MPOOLFILE_IGNORE(mfp);
+
+ /* Discard the mutex we're holding. */
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
/* Delete from the list of MPOOLFILEs. */
+ R_LOCK(dbenv, dbmp->reginfo);
SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile);
+ /* Copy the statistics into the region. */
+ sp = &mp->stat;
+ sp->st_cache_hit += mfp->stat.st_cache_hit;
+ sp->st_cache_miss += mfp->stat.st_cache_miss;
+ sp->st_map += mfp->stat.st_map;
+ sp->st_page_create += mfp->stat.st_page_create;
+ sp->st_page_in += mfp->stat.st_page_in;
+ sp->st_page_out += mfp->stat.st_page_out;
+
+ /* Clear the mutex this MPOOLFILE recorded. */
+ __db_shlocks_clear(&mfp->mutex, dbmp->reginfo,
+ (REGMAINT *)R_ADDR(dbmp->reginfo, mp->maint_off));
+
/* Free the space. */
if (mfp->path_off != 0)
__db_shalloc_free(dbmp->reginfo[0].addr,
@@ -693,35 +980,10 @@ __memp_mf_discard(dbmp, mfp)
__db_shalloc_free(dbmp->reginfo[0].addr,
R_ADDR(dbmp->reginfo, mfp->pgcookie_off));
__db_shalloc_free(dbmp->reginfo[0].addr, mfp);
-}
-
-/*
- * __memp_fremove --
- * Remove an underlying file from the system.
- *
- * PUBLIC: int __memp_fremove __P((DB_MPOOLFILE *));
- */
-int
-__memp_fremove(dbmfp)
- DB_MPOOLFILE *dbmfp;
-{
- DB_ENV *dbenv;
- DB_MPOOL *dbmp;
- MPOOLFILE *mfp;
-
- dbmp = dbmfp->dbmp;
- dbenv = dbmp->dbenv;
- mfp = dbmfp->mfp;
-
- PANIC_CHECK(dbenv);
-
- R_LOCK(dbenv, dbmp->reginfo);
-
- MEMP_FREMOVE(mfp);
R_UNLOCK(dbenv, dbmp->reginfo);
- return (0);
+ return (ret);
}
/*
diff --git a/bdb/mp/mp_fput.c b/bdb/mp/mp_fput.c
index be03b721f36..271e44a4ef8 100644
--- a/bdb/mp/mp_fput.c
+++ b/bdb/mp/mp_fput.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_fput.c,v 11.16 2000/11/30 00:58:41 ubell Exp $";
+static const char revid[] = "$Id: mp_fput.c,v 11.36 2002/08/09 19:04:11 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -15,43 +15,32 @@ static const char revid[] = "$Id: mp_fput.c,v 11.16 2000/11/30 00:58:41 ubell Ex
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
/*
- * memp_fput --
+ * __memp_fput --
* Mpool file put function.
+ *
+ * PUBLIC: int __memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
*/
int
-memp_fput(dbmfp, pgaddr, flags)
+__memp_fput(dbmfp, pgaddr, flags)
DB_MPOOLFILE *dbmfp;
void *pgaddr;
u_int32_t flags;
{
- BH *bhp;
+ BH *argbhp, *bhp, *prev;
DB_ENV *dbenv;
DB_MPOOL *dbmp;
- MPOOL *c_mp, *mp;
- int ret, wrote;
+ DB_MPOOL_HASH *hp;
+ MPOOL *c_mp;
+ u_int32_t n_cache;
+ int adjust, ret;
dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
- mp = dbmp->reginfo[0].primary;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fput(dbmfp, pgaddr, flags));
-#endif
PANIC_CHECK(dbenv);
@@ -72,17 +61,6 @@ memp_fput(dbmfp, pgaddr, flags)
}
}
- R_LOCK(dbenv, dbmp->reginfo);
-
- /* Decrement the pinned reference count. */
- if (dbmfp->pinref == 0) {
- __db_err(dbenv,
- "%s: more pages returned than retrieved", __memp_fn(dbmfp));
- R_UNLOCK(dbenv, dbmp->reginfo);
- return (EINVAL);
- } else
- --dbmfp->pinref;
-
/*
* If we're mapping the file, there's nothing to do. Because we can
* stop mapping the file at any time, we have to check on each buffer
@@ -90,97 +68,135 @@ memp_fput(dbmfp, pgaddr, flags)
* region.
*/
if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr &&
- (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) {
- R_UNLOCK(dbenv, dbmp->reginfo);
+ (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len)
return (0);
+
+#ifdef DIAGNOSTIC
+ /*
+ * Decrement the per-file pinned buffer count (mapped pages aren't
+ * counted).
+ */
+ R_LOCK(dbenv, dbmp->reginfo);
+ if (dbmfp->pinref == 0) {
+ ret = EINVAL;
+ __db_err(dbenv,
+ "%s: more pages returned than retrieved", __memp_fn(dbmfp));
+ } else {
+ ret = 0;
+ --dbmfp->pinref;
}
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ if (ret != 0)
+ return (ret);
+#endif
- /* Convert the page address to a buffer header. */
+ /* Convert a page address to a buffer header and hash bucket. */
bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf));
+ n_cache = NCACHE(dbmp->reginfo[0].primary, bhp->mf_offset, bhp->pgno);
+ c_mp = dbmp->reginfo[n_cache].primary;
+ hp = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
+ hp = &hp[NBUCKET(c_mp, bhp->mf_offset, bhp->pgno)];
- /* Convert the buffer header to a cache. */
- c_mp = BH_TO_CACHE(dbmp, bhp);
-
-/* UNLOCK THE REGION, LOCK THE CACHE. */
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
/* Set/clear the page bits. */
- if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) {
- ++c_mp->stat.st_page_clean;
- --c_mp->stat.st_page_dirty;
+ if (LF_ISSET(DB_MPOOL_CLEAN) &&
+ F_ISSET(bhp, BH_DIRTY) && !F_ISSET(bhp, BH_DIRTY_CREATE)) {
+ DB_ASSERT(hp->hash_page_dirty != 0);
+ --hp->hash_page_dirty;
F_CLR(bhp, BH_DIRTY);
}
if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) {
- --c_mp->stat.st_page_clean;
- ++c_mp->stat.st_page_dirty;
+ ++hp->hash_page_dirty;
F_SET(bhp, BH_DIRTY);
}
if (LF_ISSET(DB_MPOOL_DISCARD))
F_SET(bhp, BH_DISCARD);
/*
- * If the page is dirty and being scheduled to be written as part of
- * a checkpoint, we no longer know that the log is up-to-date.
- */
- if (F_ISSET(bhp, BH_DIRTY) && F_ISSET(bhp, BH_SYNC))
- F_SET(bhp, BH_SYNC_LOGFLSH);
-
- /*
* Check for a reference count going to zero. This can happen if the
* application returns a page twice.
*/
if (bhp->ref == 0) {
__db_err(dbenv, "%s: page %lu: unpinned page returned",
__memp_fn(dbmfp), (u_long)bhp->pgno);
- R_UNLOCK(dbenv, dbmp->reginfo);
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
return (EINVAL);
}
/*
- * If more than one reference to the page, we're done. Ignore the
- * discard flags (for now) and leave it at its position in the LRU
- * chain. The rest gets done at last reference close.
+ * If more than one reference to the page or a reference other than a
+ * thread waiting to flush the buffer to disk, we're done. Ignore the
+ * discard flags (for now) and leave the buffer's priority alone.
*/
- if (--bhp->ref > 0) {
- R_UNLOCK(dbenv, dbmp->reginfo);
+ if (--bhp->ref > 1 || (bhp->ref == 1 && !F_ISSET(bhp, BH_LOCKED))) {
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
return (0);
}
+ /* Update priority values. */
+ if (F_ISSET(bhp, BH_DISCARD) ||
+ dbmfp->mfp->priority == MPOOL_PRI_VERY_LOW)
+ bhp->priority = 0;
+ else {
+ /*
+ * We don't lock the LRU counter or the stat.st_pages field, if
+ * we get garbage (which won't happen on a 32-bit machine), it
+ * only means a buffer has the wrong priority.
+ */
+ bhp->priority = c_mp->lru_count;
+
+ adjust = 0;
+ if (dbmfp->mfp->priority != 0)
+ adjust =
+ (int)c_mp->stat.st_pages / dbmfp->mfp->priority;
+ if (F_ISSET(bhp, BH_DIRTY))
+ adjust += c_mp->stat.st_pages / MPOOL_PRI_DIRTY;
+
+ if (adjust > 0) {
+ if (UINT32_T_MAX - bhp->priority <= (u_int32_t)adjust)
+ bhp->priority += adjust;
+ } else if (adjust < 0)
+ if (bhp->priority > (u_int32_t)-adjust)
+ bhp->priority += adjust;
+ }
+
/*
- * Move the buffer to the head/tail of the LRU chain. We do this
- * before writing the buffer for checkpoint purposes, as the write
- * can discard the region lock and allow another process to acquire
- * buffer. We could keep that from happening, but there seems no
- * reason to do so.
+ * Buffers on hash buckets are sorted by priority -- move the buffer
+ * to the correct position in the list.
*/
- SH_TAILQ_REMOVE(&c_mp->bhq, bhp, q, __bh);
- if (F_ISSET(bhp, BH_DISCARD))
- SH_TAILQ_INSERT_HEAD(&c_mp->bhq, bhp, q, __bh);
+ argbhp = bhp;
+ SH_TAILQ_REMOVE(&hp->hash_bucket, argbhp, hq, __bh);
+
+ prev = NULL;
+ for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+ bhp != NULL; prev = bhp, bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+ if (bhp->priority > argbhp->priority)
+ break;
+ if (prev == NULL)
+ SH_TAILQ_INSERT_HEAD(&hp->hash_bucket, argbhp, hq, __bh);
else
- SH_TAILQ_INSERT_TAIL(&c_mp->bhq, bhp, q);
+ SH_TAILQ_INSERT_AFTER(&hp->hash_bucket, prev, argbhp, hq, __bh);
+
+ /* Reset the hash bucket's priority. */
+ hp->hash_priority = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
+
+#ifdef DIAGNOSTIC
+ __memp_check_order(hp);
+#endif
/*
- * If this buffer is scheduled for writing because of a checkpoint, we
- * need to write it (if it's dirty), or update the checkpoint counters
- * (if it's not dirty). If we try to write it and can't, that's not
- * necessarily an error as it's not completely unreasonable that the
- * application have permission to write the underlying file, but set a
- * flag so that the next time the memp_sync function is called we try
- * writing it there, as the checkpoint thread of control better be able
- * to write all of the files.
+ * The sync code has a separate counter for buffers on which it waits.
+ * It reads that value without holding a lock so we update it as the
+ * last thing we do. Once that value goes to 0, we won't see another
+ * reference to that buffer being returned to the cache until the sync
+ * code has finished, so we're safe as long as we don't let the value
+ * go to 0 before we finish with the buffer.
*/
- if (F_ISSET(bhp, BH_SYNC)) {
- if (F_ISSET(bhp, BH_DIRTY)) {
- if (__memp_bhwrite(dbmp,
- dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote)
- F_SET(mp, MP_LSN_RETRY);
- } else {
- F_CLR(bhp, BH_SYNC);
-
- --mp->lsn_cnt;
- --dbmfp->mfp->lsn_cnt;
- }
- }
+ if (F_ISSET(argbhp, BH_LOCKED) && argbhp->ref_sync != 0)
+ --argbhp->ref_sync;
+
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
- R_UNLOCK(dbenv, dbmp->reginfo);
return (0);
}
diff --git a/bdb/mp/mp_fset.c b/bdb/mp/mp_fset.c
index 08313c9b6f5..65cd6286ac9 100644
--- a/bdb/mp/mp_fset.c
+++ b/bdb/mp/mp_fset.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_fset.c,v 11.13 2000/11/30 00:58:41 ubell Exp $";
+static const char revid[] = "$Id: mp_fset.c,v 11.25 2002/05/03 15:21:17 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -15,25 +15,18 @@ static const char revid[] = "$Id: mp_fset.c,v 11.13 2000/11/30 00:58:41 ubell Ex
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
/*
- * memp_fset --
+ * __memp_fset --
* Mpool page set-flag routine.
+ *
+ * PUBLIC: int __memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
*/
int
-memp_fset(dbmfp, pgaddr, flags)
+__memp_fset(dbmfp, pgaddr, flags)
DB_MPOOLFILE *dbmfp;
void *pgaddr;
u_int32_t flags;
@@ -41,17 +34,13 @@ memp_fset(dbmfp, pgaddr, flags)
BH *bhp;
DB_ENV *dbenv;
DB_MPOOL *dbmp;
- MPOOL *c_mp, *mp;
+ DB_MPOOL_HASH *hp;
+ MPOOL *c_mp;
+ u_int32_t n_cache;
int ret;
dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
- mp = dbmp->reginfo[0].primary;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fset(dbmfp, pgaddr, flags));
-#endif
PANIC_CHECK(dbenv);
@@ -60,7 +49,7 @@ memp_fset(dbmfp, pgaddr, flags)
return (__db_ferr(dbenv, "memp_fset", 1));
if ((ret = __db_fchk(dbenv, "memp_fset", flags,
- DB_MPOOL_DIRTY | DB_MPOOL_CLEAN | DB_MPOOL_DISCARD)) != 0)
+ DB_MPOOL_CLEAN | DB_MPOOL_DIRTY | DB_MPOOL_DISCARD)) != 0)
return (ret);
if ((ret = __db_fcchk(dbenv, "memp_fset",
flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0)
@@ -72,27 +61,29 @@ memp_fset(dbmfp, pgaddr, flags)
return (EACCES);
}
- /* Convert the page address to a buffer header. */
+ /* Convert the page address to a buffer header and hash bucket. */
bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf));
-
- /* Convert the buffer header to a cache. */
- c_mp = BH_TO_CACHE(dbmp, bhp);
-
- R_LOCK(dbenv, dbmp->reginfo);
-
- if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) {
- ++c_mp->stat.st_page_clean;
- --c_mp->stat.st_page_dirty;
+ n_cache = NCACHE(dbmp->reginfo[0].primary, bhp->mf_offset, bhp->pgno);
+ c_mp = dbmp->reginfo[n_cache].primary;
+ hp = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
+ hp = &hp[NBUCKET(c_mp, bhp->mf_offset, bhp->pgno)];
+
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
+
+ /* Set/clear the page bits. */
+ if (LF_ISSET(DB_MPOOL_CLEAN) &&
+ F_ISSET(bhp, BH_DIRTY) && !F_ISSET(bhp, BH_DIRTY_CREATE)) {
+ DB_ASSERT(hp->hash_page_dirty != 0);
+ --hp->hash_page_dirty;
F_CLR(bhp, BH_DIRTY);
}
if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) {
- --c_mp->stat.st_page_clean;
- ++c_mp->stat.st_page_dirty;
+ ++hp->hash_page_dirty;
F_SET(bhp, BH_DIRTY);
}
if (LF_ISSET(DB_MPOOL_DISCARD))
F_SET(bhp, BH_DISCARD);
- R_UNLOCK(dbenv, dbmp->reginfo);
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
return (0);
}
diff --git a/bdb/mp/mp_method.c b/bdb/mp/mp_method.c
index 85a6239b032..38f0a645f16 100644
--- a/bdb/mp/mp_method.c
+++ b/bdb/mp/mp_method.c
@@ -1,30 +1,30 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_method.c,v 11.10 2000/04/04 20:12:04 bostic Exp $";
+static const char revid[] = "$Id: mp_method.c,v 11.29 2002/03/27 04:32:27 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
#endif
static int __memp_set_cachesize __P((DB_ENV *, u_int32_t, u_int32_t, int));
@@ -41,29 +41,46 @@ __memp_dbenv_create(dbenv)
DB_ENV *dbenv;
{
/*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ *
* We default to 32 8K pages. We don't default to a flat 256K, because
* some systems require significantly more memory to hold 32 pages than
* others. For example, HP-UX with POSIX pthreads needs 88 bytes for
* a POSIX pthread mutex and almost 200 bytes per buffer header, while
- * Solaris needs 24 and 52 bytes for the same structures.
+ * Solaris needs 24 and 52 bytes for the same structures. The minimum
+ * number of hash buckets is 37. These contain a mutex also.
*/
- dbenv->mp_bytes = 32 * ((8 * 1024) + sizeof(BH));
+ dbenv->mp_bytes =
+ 32 * ((8 * 1024) + sizeof(BH)) + 37 * sizeof(DB_MPOOL_HASH);
dbenv->mp_ncache = 1;
- dbenv->set_mp_mmapsize = __memp_set_mp_mmapsize;
- dbenv->set_cachesize = __memp_set_cachesize;
-
-#ifdef HAVE_RPC
- /*
- * If we have a client, overwrite what we just setup to
- * point to client functions.
- */
+#ifdef HAVE_RPC
if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
dbenv->set_cachesize = __dbcl_env_cachesize;
dbenv->set_mp_mmapsize = __dbcl_set_mp_mmapsize;
- }
+ dbenv->memp_dump_region = NULL;
+ dbenv->memp_fcreate = __dbcl_memp_fcreate;
+ dbenv->memp_nameop = NULL;
+ dbenv->memp_register = __dbcl_memp_register;
+ dbenv->memp_stat = __dbcl_memp_stat;
+ dbenv->memp_sync = __dbcl_memp_sync;
+ dbenv->memp_trickle = __dbcl_memp_trickle;
+ } else
#endif
-
+ {
+ dbenv->set_cachesize = __memp_set_cachesize;
+ dbenv->set_mp_mmapsize = __memp_set_mp_mmapsize;
+ dbenv->memp_dump_region = __memp_dump_region;
+ dbenv->memp_fcreate = __memp_fcreate;
+ dbenv->memp_nameop = __memp_nameop;
+ dbenv->memp_register = __memp_register;
+ dbenv->memp_stat = __memp_stat;
+ dbenv->memp_sync = __memp_sync;
+ dbenv->memp_trickle = __memp_trickle;
+ }
}
/*
@@ -78,26 +95,50 @@ __memp_set_cachesize(dbenv, gbytes, bytes, ncache)
{
ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_cachesize");
- dbenv->mp_gbytes = gbytes + bytes / GIGABYTE;
- dbenv->mp_bytes = bytes % GIGABYTE;
- dbenv->mp_ncache = ncache == 0 ? 1 : ncache;
+ /* Normalize the values. */
+ if (ncache == 0)
+ ncache = 1;
/*
- * If the application requested less than 500Mb, increase the
- * cachesize by 25% to account for our overhead. (I'm guessing
- * that caches over 500Mb are specifically sized, i.e., it's
- * a large server and the application actually knows how much
- * memory is available.)
+ * You can only store 4GB-1 in an unsigned 32-bit value, so correct for
+ * applications that specify 4GB cache sizes -- we know what they meant.
+ */
+ if (gbytes / ncache == 4 && bytes == 0) {
+ --gbytes;
+ bytes = GIGABYTE - 1;
+ } else {
+ gbytes += bytes / GIGABYTE;
+ bytes %= GIGABYTE;
+ }
+
+ /* Avoid too-large cache sizes, they result in a region size of zero. */
+ if (gbytes / ncache > 4 || (gbytes / ncache == 4 && bytes != 0)) {
+ __db_err(dbenv, "individual cache size too large");
+ return (EINVAL);
+ }
+
+ /*
+ * If the application requested less than 500Mb, increase the cachesize
+ * by 25% and factor in the size of the hash buckets to account for our
+ * overhead. (I'm guessing caches over 500Mb are specifically sized,
+ * that is, it's a large server and the application actually knows how
+ * much memory is available. We only document the 25% overhead number,
+ * not the hash buckets, but I don't see a reason to confuse the issue,
+ * it shouldn't matter to an application.)
*
* There is a minimum cache size, regardless.
*/
- if (dbenv->mp_gbytes == 0) {
- if (dbenv->mp_bytes < 500 * MEGABYTE)
- dbenv->mp_bytes += dbenv->mp_bytes / 4;
- if (dbenv->mp_bytes < DB_CACHESIZE_MIN)
- dbenv->mp_bytes = DB_CACHESIZE_MIN;
+ if (gbytes == 0) {
+ if (bytes < 500 * MEGABYTE)
+ bytes += (bytes / 4) + 37 * sizeof(DB_MPOOL_HASH);
+ if (bytes / ncache < DB_CACHESIZE_MIN)
+ bytes = ncache * DB_CACHESIZE_MIN;
}
+ dbenv->mp_gbytes = gbytes;
+ dbenv->mp_bytes = bytes;
+ dbenv->mp_ncache = ncache;
+
return (0);
}
diff --git a/bdb/mp/mp_region.c b/bdb/mp/mp_region.c
index 4b85466ce63..06eca2f8646 100644
--- a/bdb/mp/mp_region.c
+++ b/bdb/mp/mp_region.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_region.c,v 11.26 2000/11/30 00:58:41 ubell Exp $";
+static const char revid[] = "$Id: mp_region.c,v 11.49 2002/05/07 18:42:20 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,11 +17,11 @@ static const char revid[] = "$Id: mp_region.c,v 11.26 2000/11/30 00:58:41 ubell
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
static int __mpool_init __P((DB_ENV *, DB_MPOOL *, int, int));
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
static size_t __mpool_region_maint __P((REGINFO *));
#endif
@@ -119,6 +119,8 @@ __memp_open(dbenv)
regids[i] = dbmp->reginfo[i].id;
}
+
+ R_UNLOCK(dbenv, dbmp->reginfo);
} else {
/*
* Determine how many regions there are going to be, allocate
@@ -135,6 +137,19 @@ __memp_open(dbenv)
dbmp->reginfo[i].id = INVALID_REGION_ID;
dbmp->reginfo[0] = reginfo;
+ /*
+ * We have to unlock the primary mpool region before we attempt
+ * to join the additional mpool regions. If we don't, we can
+ * deadlock. The scenario is that we hold the primary mpool
+ * region lock. We then try to attach to an additional mpool
+ * region, which requires the acquisition/release of the main
+ * region lock (to search the list of regions). If another
+ * thread of control already holds the main region lock and is
+ * waiting on our primary mpool region lock, we'll deadlock.
+ * See [#4696] for more information.
+ */
+ R_UNLOCK(dbenv, dbmp->reginfo);
+
/* Join remaining regions. */
regids = R_ADDR(dbmp->reginfo, mp->regids);
for (i = 1; i < dbmp->nreg; ++i) {
@@ -155,17 +170,10 @@ __memp_open(dbenv)
R_ADDR(&dbmp->reginfo[i], dbmp->reginfo[i].rp->primary);
/* If the region is threaded, allocate a mutex to lock the handles. */
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if ((ret = __db_mutex_alloc(
- dbenv, dbmp->reginfo, &dbmp->mutexp)) != 0) {
- goto err;
- }
- if ((ret =
- __db_mutex_init(dbenv, dbmp->mutexp, 0, MUTEX_THREAD)) != 0)
- goto err;
- }
-
- R_UNLOCK(dbenv, dbmp->reginfo);
+ if (F_ISSET(dbenv, DB_ENV_THREAD) &&
+ (ret = __db_mutex_setup(dbenv, dbmp->reginfo, &dbmp->mutexp,
+ MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+ goto err;
dbenv->mp_handle = dbmp;
return (0);
@@ -180,12 +188,11 @@ err: if (dbmp->reginfo != NULL && dbmp->reginfo[0].addr != NULL) {
if (dbmp->reginfo[i].id != INVALID_REGION_ID)
(void)__db_r_detach(
dbenv, &dbmp->reginfo[i], 0);
- __os_free(dbmp->reginfo,
- dbmp->nreg * sizeof(*dbmp->reginfo));
+ __os_free(dbenv, dbmp->reginfo);
}
if (dbmp->mutexp != NULL)
__db_mutex_free(dbenv, dbmp->reginfo, dbmp->mutexp);
- __os_free(dbmp, sizeof(*dbmp));
+ __os_free(dbenv, dbmp);
return (ret);
}
@@ -199,13 +206,13 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
DB_MPOOL *dbmp;
int reginfo_off, htab_buckets;
{
- DB_HASHTAB *htab;
+ DB_MPOOL_HASH *htab;
MPOOL *mp;
REGINFO *reginfo;
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
size_t maint_size;
#endif
- int ret;
+ int i, ret;
void *p;
mp = NULL;
@@ -218,7 +225,7 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
mp = reginfo->primary;
memset(mp, 0, sizeof(*mp));
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
maint_size = __mpool_region_maint(reginfo);
/* Allocate room for the maintenance info and initialize it. */
if ((ret = __db_shalloc(reginfo->addr,
@@ -231,14 +238,7 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
if (reginfo_off == 0) {
SH_TAILQ_INIT(&mp->mpfq);
- if ((ret = __db_shmutex_init(dbenv, &mp->sync_mutex,
- R_OFFSET(dbmp->reginfo, &mp->sync_mutex) +
- DB_FCNTL_OFF_MPOOL, 0, dbmp->reginfo,
- (REGMAINT *)R_ADDR(dbmp->reginfo, mp->maint_off))) != 0)
- goto err;
-
ZERO_LSN(mp->lsn);
- mp->lsn_cnt = 0;
mp->nreg = dbmp->nreg;
if ((ret = __db_shalloc(dbmp->reginfo[0].addr,
@@ -247,32 +247,41 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
mp->regids = R_OFFSET(dbmp->reginfo, p);
}
- SH_TAILQ_INIT(&mp->bhq);
-
/* Allocate hash table space and initialize it. */
if ((ret = __db_shalloc(reginfo->addr,
- htab_buckets * sizeof(DB_HASHTAB), 0, &htab)) != 0)
+ htab_buckets * sizeof(DB_MPOOL_HASH), 0, &htab)) != 0)
goto mem_err;
- __db_hashinit(htab, htab_buckets);
mp->htab = R_OFFSET(reginfo, htab);
- mp->htab_buckets = htab_buckets;
+ for (i = 0; i < htab_buckets; i++) {
+ if ((ret = __db_mutex_setup(dbenv,
+ reginfo, &htab[i].hash_mutex,
+ MUTEX_NO_RLOCK)) != 0)
+ return (ret);
+ SH_TAILQ_INIT(&htab[i].hash_bucket);
+ htab[i].hash_page_dirty = htab[i].hash_priority = 0;
+ }
+ mp->htab_buckets = mp->stat.st_hash_buckets = htab_buckets;
+ /*
+ * Only the environment creator knows the total cache size, fill in
+ * those statistics now.
+ */
+ mp->stat.st_gbytes = dbenv->mp_gbytes;
+ mp->stat.st_bytes = dbenv->mp_bytes;
return (0);
mem_err:__db_err(dbenv, "Unable to allocate memory for mpool region");
-err: if (reginfo->primary != NULL)
- __db_shalloc_free(reginfo->addr, reginfo->primary);
return (ret);
}
/*
- * __memp_close --
- * Internal version of memp_close: only called from DB_ENV->close.
+ * __memp_dbenv_refresh --
+ * Clean up after the mpool system on a close or failed open.
*
- * PUBLIC: int __memp_close __P((DB_ENV *));
+ * PUBLIC: int __memp_dbenv_refresh __P((DB_ENV *));
*/
int
-__memp_close(dbenv)
+__memp_dbenv_refresh(dbenv)
DB_ENV *dbenv;
{
DB_MPOOL *dbmp;
@@ -287,12 +296,12 @@ __memp_close(dbenv)
/* Discard DB_MPREGs. */
while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
LIST_REMOVE(mpreg, q);
- __os_free(mpreg, sizeof(DB_MPREG));
+ __os_free(dbenv, mpreg);
}
/* Discard DB_MPOOLFILEs. */
while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
- if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0)
+ if ((t_ret = __memp_fclose_int(dbmfp, 0)) != 0 && ret == 0)
ret = t_ret;
/* Discard the thread mutex. */
@@ -305,14 +314,14 @@ __memp_close(dbenv)
dbenv, &dbmp->reginfo[i], 0)) != 0 && ret == 0)
ret = t_ret;
- __os_free(dbmp->reginfo, dbmp->nreg * sizeof(*dbmp->reginfo));
- __os_free(dbmp, sizeof(*dbmp));
+ __os_free(dbenv, dbmp->reginfo);
+ __os_free(dbenv, dbmp);
dbenv->mp_handle = NULL;
return (ret);
}
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
/*
* __mpool_region_maint --
* Return the amount of space needed for region maintenance info.
@@ -328,9 +337,11 @@ __mpool_region_maint(infop)
/*
* For mutex maintenance we need one mutex per possible page.
* Compute the maximum number of pages this cache can have.
- * Also add in an mpool mutex.
+ * Also add in an mpool mutex and mutexes for all dbenv and db
+ * handles.
*/
numlocks = ((infop->rp->size / DB_MIN_PGSIZE) + 1);
+ numlocks += DB_MAX_HANDLES;
s = sizeof(roff_t) * numlocks;
return (s);
}
@@ -347,11 +358,109 @@ __mpool_region_destroy(dbenv, infop)
DB_ENV *dbenv;
REGINFO *infop;
{
- MPOOL *mp;
+ __db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
+ ((MPOOL *)R_ADDR(infop, infop->rp->primary))->maint_off));
COMPQUIET(dbenv, NULL);
- mp = R_ADDR(infop, infop->rp->primary);
+ COMPQUIET(infop, NULL);
+}
+
+/*
+ * __memp_nameop
+ * Remove or rename a file in the pool.
+ *
+ * PUBLIC: int __memp_nameop __P((DB_ENV *,
+ * PUBLIC: u_int8_t *, const char *, const char *, const char *));
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+int
+__memp_nameop(dbenv, fileid, newname, fullold, fullnew)
+ DB_ENV *dbenv;
+ u_int8_t *fileid;
+ const char *newname, *fullold, *fullnew;
+{
+ DB_MPOOL *dbmp;
+ MPOOL *mp;
+ MPOOLFILE *mfp;
+ roff_t newname_off;
+ int locked, ret;
+ void *p;
+
+ locked = 0;
+ dbmp = NULL;
- __db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop, mp->maint_off));
- return;
+ if (!MPOOL_ON(dbenv))
+ goto fsop;
+
+ dbmp = dbenv->mp_handle;
+ mp = dbmp->reginfo[0].primary;
+
+ /*
+ * Remove or rename a file that the mpool might know about. We assume
+ * that the fop layer has the file locked for exclusive access, so we
+ * don't worry about locking except for the mpool mutexes. Checkpoint
+ * can happen at any time, independent of file locking, so we have to
+ * do the actual unlink or rename system call to avoid any race.
+ *
+ * If this is a rename, allocate first, because we can't recursively
+ * grab the region lock.
+ */
+ if (newname == NULL)
+ p = NULL;
+ else {
+ if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
+ NULL, strlen(newname) + 1, &newname_off, &p)) != 0)
+ return (ret);
+ memcpy(p, newname, strlen(newname) + 1);
+ }
+
+ locked = 1;
+ R_LOCK(dbenv, dbmp->reginfo);
+
+ /*
+ * Find the file -- if mpool doesn't know about this file, that's not
+ * an error-- we may not have it open.
+ */
+ for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
+ mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
+ /* Ignore non-active files. */
+ if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
+ continue;
+
+ /* Ignore non-matching files. */
+ if (memcmp(fileid, R_ADDR(
+ dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0)
+ continue;
+
+ /* If newname is NULL, we're removing the file. */
+ if (newname == NULL) {
+ MUTEX_LOCK(dbenv, &mfp->mutex);
+ MPOOLFILE_IGNORE(mfp);
+ MUTEX_UNLOCK(dbenv, &mfp->mutex);
+ } else {
+ /*
+ * Else, it's a rename. We've allocated memory
+ * for the new name. Swap it with the old one.
+ */
+ p = R_ADDR(dbmp->reginfo, mfp->path_off);
+ mfp->path_off = newname_off;
+ }
+ break;
+ }
+
+ /* Delete the memory we no longer need. */
+ if (p != NULL)
+ __db_shalloc_free(dbmp->reginfo[0].addr, p);
+
+fsop: if (newname == NULL)
+ (void)__os_unlink(dbenv, fullold);
+ else
+ (void)__os_rename(dbenv, fullold, fullnew, 1);
+
+ if (locked)
+ R_UNLOCK(dbenv, dbmp->reginfo);
+
+ return (0);
}
diff --git a/bdb/mp/mp_register.c b/bdb/mp/mp_register.c
index 27859f69d7b..46eefad986f 100644
--- a/bdb/mp/mp_register.c
+++ b/bdb/mp/mp_register.c
@@ -1,38 +1,33 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_register.c,v 11.12 2000/11/15 19:25:39 sue Exp $";
+static const char revid[] = "$Id: mp_register.c,v 11.21 2002/03/27 04:32:27 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
/*
* memp_register --
* Register a file type's pgin, pgout routines.
+ *
+ * PUBLIC: int __memp_register __P((DB_ENV *, int,
+ * PUBLIC: int (*)(DB_ENV *, db_pgno_t, void *, DBT *),
+ * PUBLIC: int (*)(DB_ENV *, db_pgno_t, void *, DBT *)));
*/
int
-memp_register(dbenv, ftype, pgin, pgout)
+__memp_register(dbenv, ftype, pgin, pgout)
DB_ENV *dbenv;
int ftype;
int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *));
@@ -42,13 +37,9 @@ memp_register(dbenv, ftype, pgin, pgout)
DB_MPREG *mpreg;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_register(dbenv, ftype, pgin, pgout));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->mp_handle, "DB_ENV->memp_register", DB_INIT_MPOOL);
dbmp = dbenv->mp_handle;
@@ -70,7 +61,7 @@ memp_register(dbenv, ftype, pgin, pgout)
return (0);
/* New entry. */
- if ((ret = __os_malloc(dbenv, sizeof(DB_MPREG), NULL, &mpreg)) != 0)
+ if ((ret = __os_malloc(dbenv, sizeof(DB_MPREG), &mpreg)) != 0)
return (ret);
mpreg->ftype = ftype;
diff --git a/bdb/mp/mp_stat.c b/bdb/mp/mp_stat.c
index 7982513448d..12e72b91d70 100644
--- a/bdb/mp/mp_stat.c
+++ b/bdb/mp/mp_stat.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_stat.c,v 11.21 2001/01/09 16:59:30 bostic Exp $";
+static const char revid[] = "$Id: mp_stat.c,v 11.51 2002/08/06 06:13:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,123 +18,150 @@ static const char revid[] = "$Id: mp_stat.c,v 11.21 2001/01/09 16:59:30 bostic E
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "db_am.h"
-#include "mp.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/mp.h"
-static void __memp_dumpcache
- __P((DB_MPOOL *, REGINFO *, size_t *, FILE *, u_int32_t));
+static void __memp_dumpcache __P((DB_ENV *,
+ DB_MPOOL *, REGINFO *, size_t *, FILE *, u_int32_t));
static void __memp_pbh __P((DB_MPOOL *, BH *, size_t *, FILE *));
+static void __memp_stat_wait __P((REGINFO *, MPOOL *, DB_MPOOL_STAT *, int));
/*
- * memp_stat --
+ * __memp_stat --
* Display MPOOL statistics.
+ *
+ * PUBLIC: int __memp_stat
+ * PUBLIC: __P((DB_ENV *, DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
*/
int
-memp_stat(dbenv, gspp, fspp, db_malloc)
+__memp_stat(dbenv, gspp, fspp, flags)
DB_ENV *dbenv;
DB_MPOOL_STAT **gspp;
DB_MPOOL_FSTAT ***fspp;
- void *(*db_malloc) __P((size_t));
+ u_int32_t flags;
{
DB_MPOOL *dbmp;
DB_MPOOL_FSTAT **tfsp, *tstruct;
DB_MPOOL_STAT *sp;
MPOOL *c_mp, *mp;
MPOOLFILE *mfp;
- char *tname;
- size_t len, nlen;
- u_int32_t i;
+ size_t len, nlen, pagesize;
+ u_int32_t pages, i;
int ret;
- char *name;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_stat(dbenv, gspp, fspp, db_malloc));
-#endif
+ char *name, *tname;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->mp_handle, "memp_stat", DB_INIT_MPOOL);
+
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->memp_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
dbmp = dbenv->mp_handle;
- sp = NULL;
+ mp = dbmp->reginfo[0].primary;
/* Global statistics. */
- mp = dbmp->reginfo[0].primary;
if (gspp != NULL) {
*gspp = NULL;
- if ((ret = __os_calloc(dbenv, 1, sizeof(**gspp), gspp)) != 0)
+ if ((ret = __os_umalloc(dbenv, sizeof(**gspp), gspp)) != 0)
return (ret);
+ memset(*gspp, 0, sizeof(**gspp));
sp = *gspp;
/*
* Initialization and information that is not maintained on
* a per-cache basis.
*/
- sp->st_hash_longest = 0;
- sp->st_region_wait = dbmp->reginfo[0].rp->mutex.mutex_set_wait;
- sp->st_region_nowait =
- dbmp->reginfo[0].rp->mutex.mutex_set_nowait;
- sp->st_gbytes = dbenv->mp_gbytes;
- sp->st_bytes = dbenv->mp_bytes;
+ c_mp = dbmp->reginfo[0].primary;
+ sp->st_gbytes = c_mp->stat.st_gbytes;
+ sp->st_bytes = c_mp->stat.st_bytes;
sp->st_ncache = dbmp->nreg;
sp->st_regsize = dbmp->reginfo[0].rp->size;
- R_LOCK(dbenv, dbmp->reginfo);
-
/* Walk the cache list and accumulate the global information. */
for (i = 0; i < mp->nreg; ++i) {
c_mp = dbmp->reginfo[i].primary;
+
+ sp->st_map += c_mp->stat.st_map;
sp->st_cache_hit += c_mp->stat.st_cache_hit;
sp->st_cache_miss += c_mp->stat.st_cache_miss;
- sp->st_map += c_mp->stat.st_map;
sp->st_page_create += c_mp->stat.st_page_create;
sp->st_page_in += c_mp->stat.st_page_in;
sp->st_page_out += c_mp->stat.st_page_out;
sp->st_ro_evict += c_mp->stat.st_ro_evict;
sp->st_rw_evict += c_mp->stat.st_rw_evict;
+ sp->st_page_trickle += c_mp->stat.st_page_trickle;
+ sp->st_pages += c_mp->stat.st_pages;
+ /*
+ * st_page_dirty calculated by __memp_stat_hash
+ * st_page_clean calculated here
+ */
+ __memp_stat_hash(
+ &dbmp->reginfo[i], c_mp, &sp->st_page_dirty);
+ sp->st_page_clean = sp->st_pages - sp->st_page_dirty;
sp->st_hash_buckets += c_mp->stat.st_hash_buckets;
sp->st_hash_searches += c_mp->stat.st_hash_searches;
- if (c_mp->stat.st_hash_longest > sp->st_hash_longest)
- sp->st_hash_longest =
- c_mp->stat.st_hash_longest;
+ sp->st_hash_longest += c_mp->stat.st_hash_longest;
sp->st_hash_examined += c_mp->stat.st_hash_examined;
- sp->st_page_clean += c_mp->stat.st_page_clean;
- sp->st_page_dirty += c_mp->stat.st_page_dirty;
- sp->st_page_trickle += c_mp->stat.st_page_trickle;
- sp->st_region_wait += c_mp->stat.st_region_wait;
- sp->st_region_nowait += c_mp->stat.st_region_nowait;
+ /*
+ * st_hash_nowait calculated by __memp_stat_wait
+ * st_hash_wait
+ */
+ __memp_stat_wait(&dbmp->reginfo[i], c_mp, sp, flags);
+ sp->st_region_nowait +=
+ dbmp->reginfo[i].rp->mutex.mutex_set_nowait;
+ sp->st_region_wait +=
+ dbmp->reginfo[i].rp->mutex.mutex_set_wait;
+ sp->st_alloc += c_mp->stat.st_alloc;
+ sp->st_alloc_buckets += c_mp->stat.st_alloc_buckets;
+ if (sp->st_alloc_max_buckets <
+ c_mp->stat.st_alloc_max_buckets)
+ sp->st_alloc_max_buckets =
+ c_mp->stat.st_alloc_max_buckets;
+ sp->st_alloc_pages += c_mp->stat.st_alloc_pages;
+ if (sp->st_alloc_max_pages <
+ c_mp->stat.st_alloc_max_pages)
+ sp->st_alloc_max_pages =
+ c_mp->stat.st_alloc_max_pages;
+
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ dbmp->reginfo[i].rp->mutex.mutex_set_wait = 0;
+ dbmp->reginfo[i].rp->mutex.mutex_set_nowait = 0;
+ pages = c_mp->stat.st_pages;
+ memset(&c_mp->stat, 0, sizeof(c_mp->stat));
+ c_mp->stat.st_hash_buckets = c_mp->htab_buckets;
+ c_mp->stat.st_pages = pages;
+ }
}
/*
- * We have duplicate statistics fields in the cache and
- * per-file structures. The counters are only incremented
- * in the per-file structures, though. The intent is that
- * if we ever flush files from the pool we can save their
- * last known totals in the cache structure.
+ * We have duplicate statistics fields in per-file structures
+ * and the cache. The counters are only incremented in the
+ * per-file structures, except if a file is flushed from the
+ * mpool, at which time we copy its information into the cache
+ * statistics. We added the cache information above, now we
+ * add the per-file information.
*/
+ R_LOCK(dbenv, dbmp->reginfo);
for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
+ sp->st_map += mfp->stat.st_map;
sp->st_cache_hit += mfp->stat.st_cache_hit;
sp->st_cache_miss += mfp->stat.st_cache_miss;
- sp->st_map += mfp->stat.st_map;
sp->st_page_create += mfp->stat.st_page_create;
sp->st_page_in += mfp->stat.st_page_in;
sp->st_page_out += mfp->stat.st_page_out;
+ if (fspp == NULL && LF_ISSET(DB_STAT_CLEAR)) {
+ pagesize = mfp->stat.st_pagesize;
+ memset(&mfp->stat, 0, sizeof(mfp->stat));
+ mfp->stat.st_pagesize = pagesize;
+ }
}
-
R_UNLOCK(dbenv, dbmp->reginfo);
}
@@ -142,9 +169,8 @@ memp_stat(dbenv, gspp, fspp, db_malloc)
if (fspp != NULL) {
*fspp = NULL;
- R_LOCK(dbenv, dbmp->reginfo);
-
/* Count the MPOOLFILE structures. */
+ R_LOCK(dbenv, dbmp->reginfo);
for (i = 0, len = 0,
mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
mfp != NULL;
@@ -153,18 +179,15 @@ memp_stat(dbenv, gspp, fspp, db_malloc)
sizeof(DB_MPOOL_FSTAT) +
strlen(__memp_fns(dbmp, mfp)) + 1;
len += sizeof(DB_MPOOL_FSTAT *); /* Trailing NULL */
-
R_UNLOCK(dbenv, dbmp->reginfo);
- if (len == 0)
+ if (i == 0)
return (0);
/* Allocate space */
- if ((ret = __os_malloc(dbenv, len, db_malloc, fspp)) != 0)
+ if ((ret = __os_umalloc(dbenv, len, fspp)) != 0)
return (ret);
- R_LOCK(dbenv, dbmp->reginfo);
-
/*
* Build each individual entry. We assume that an array of
* pointers are aligned correctly to be followed by an array
@@ -179,20 +202,30 @@ memp_stat(dbenv, gspp, fspp, db_malloc)
tstruct = (DB_MPOOL_FSTAT *)(tfsp + i + 1);
tname = (char *)(tstruct + i);
+ /*
+ * Files may have been opened since we counted, don't walk
+ * off the end of the allocated space.
+ */
+ R_LOCK(dbenv, dbmp->reginfo);
for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
- mfp != NULL;
+ mfp != NULL && i-- > 0;
++tfsp, ++tstruct, tname += nlen,
mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
name = __memp_fns(dbmp, mfp);
nlen = strlen(name) + 1;
*tfsp = tstruct;
*tstruct = mfp->stat;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ pagesize = mfp->stat.st_pagesize;
+ memset(&mfp->stat, 0, sizeof(mfp->stat));
+ mfp->stat.st_pagesize = pagesize;
+ }
tstruct->file_name = tname;
memcpy(tname, name, nlen);
}
- *tfsp = NULL;
-
R_UNLOCK(dbenv, dbmp->reginfo);
+
+ *tfsp = NULL;
}
return (0);
}
@@ -200,7 +233,6 @@ memp_stat(dbenv, gspp, fspp, db_malloc)
#define FMAP_ENTRIES 200 /* Files we map. */
#define MPOOL_DUMP_HASH 0x01 /* Debug hash chains. */
-#define MPOOL_DUMP_LRU 0x02 /* Debug LRU chains. */
#define MPOOL_DUMP_MEM 0x04 /* Debug region memory. */
#define MPOOL_DUMP_ALL 0x07 /* Debug all. */
@@ -208,14 +240,23 @@ memp_stat(dbenv, gspp, fspp, db_malloc)
* __memp_dump_region --
* Display MPOOL structures.
*
- * PUBLIC: void __memp_dump_region __P((DB_ENV *, char *, FILE *));
+ * PUBLIC: int __memp_dump_region __P((DB_ENV *, char *, FILE *));
*/
-void
+int
__memp_dump_region(dbenv, area, fp)
DB_ENV *dbenv;
char *area;
FILE *fp;
{
+ static const FN fn[] = {
+ { MP_CAN_MMAP, "mmapped" },
+ { MP_DEADFILE, "dead" },
+ { MP_DIRECT, "no buffer" },
+ { MP_EXTENT, "extent" },
+ { MP_TEMP, "temporary" },
+ { MP_UNLINK, "unlink" },
+ { 0, NULL }
+ };
DB_MPOOL *dbmp;
DB_MPOOLFILE *dbmfp;
MPOOL *mp;
@@ -225,6 +266,10 @@ __memp_dump_region(dbenv, area, fp)
int cnt;
u_int8_t *p;
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->mp_handle, "memp_dump_region", DB_INIT_MPOOL);
+
dbmp = dbenv->mp_handle;
/* Make it easy to call from the debugger. */
@@ -239,40 +284,42 @@ __memp_dump_region(dbenv, area, fp)
case 'h':
LF_SET(MPOOL_DUMP_HASH);
break;
- case 'l':
- LF_SET(MPOOL_DUMP_LRU);
- break;
case 'm':
LF_SET(MPOOL_DUMP_MEM);
break;
}
- R_LOCK(dbenv, dbmp->reginfo);
-
mp = dbmp->reginfo[0].primary;
/* Display MPOOL structures. */
(void)fprintf(fp, "%s\nPool (region addr 0x%lx)\n",
- DB_LINE, (u_long)dbmp->reginfo[0].addr);
+ DB_LINE, P_TO_ULONG(dbmp->reginfo[0].addr));
/* Display the MPOOLFILE structures. */
- cnt = 0;
- for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
+ R_LOCK(dbenv, dbmp->reginfo);
+ for (cnt = 0, mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) {
- (void)fprintf(fp, "File #%d: %s: type %ld, %s\n\t [UID: ",
- cnt + 1, __memp_fns(dbmp, mfp), (long)mfp->ftype,
- F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write");
+ (void)fprintf(fp, "File #%d: %s: pagesize %lu\n", cnt + 1,
+ __memp_fns(dbmp, mfp), (u_long)mfp->stat.st_pagesize);
+ (void)fprintf(fp, "\t type %ld; ref %lu; blocks %lu; last %lu;",
+ (long)mfp->ftype, (u_long)mfp->mpf_cnt,
+ (u_long)mfp->block_cnt, (u_long)mfp->last_pgno);
+ __db_prflags(mfp->flags, fn, fp);
+
+ (void)fprintf(fp, "\n\t UID: ");
p = R_ADDR(dbmp->reginfo, mfp->fileid_off);
- for (i = 0; i < DB_FILE_ID_LEN; ++i) {
- (void)fprintf(fp, "%x", *p++);
+ for (i = 0; i < DB_FILE_ID_LEN; ++i, ++p) {
+ (void)fprintf(fp, "%x", (u_int)*p);
if (i < DB_FILE_ID_LEN - 1)
(void)fprintf(fp, " ");
}
- (void)fprintf(fp, "]\n");
+ (void)fprintf(fp, "\n");
if (cnt < FMAP_ENTRIES)
fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
}
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
(void)fprintf(fp, "File #%d: %s: per-process, %s\n",
@@ -281,6 +328,7 @@ __memp_dump_region(dbenv, area, fp)
if (cnt < FMAP_ENTRIES)
fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
}
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
if (cnt < FMAP_ENTRIES)
fmap[cnt] = INVALID_ROFF;
else
@@ -289,13 +337,14 @@ __memp_dump_region(dbenv, area, fp)
/* Dump the memory pools. */
for (i = 0; i < mp->nreg; ++i) {
(void)fprintf(fp, "%s\nCache #%d:\n", DB_LINE, i + 1);
- __memp_dumpcache(dbmp, &dbmp->reginfo[i], fmap, fp, flags);
+ __memp_dumpcache(
+ dbenv, dbmp, &dbmp->reginfo[i], fmap, fp, flags);
}
- R_UNLOCK(dbenv, dbmp->reginfo);
-
/* Flush in case we're debugging. */
(void)fflush(fp);
+
+ return (0);
}
/*
@@ -303,7 +352,8 @@ __memp_dump_region(dbenv, area, fp)
* Display statistics for a cache.
*/
static void
-__memp_dumpcache(dbmp, reginfo, fmap, fp, flags)
+__memp_dumpcache(dbenv, dbmp, reginfo, fmap, fp, flags)
+ DB_ENV *dbenv;
DB_MPOOL *dbmp;
REGINFO *reginfo;
size_t *fmap;
@@ -311,7 +361,7 @@ __memp_dumpcache(dbmp, reginfo, fmap, fp, flags)
u_int32_t flags;
{
BH *bhp;
- DB_HASHTAB *dbht;
+ DB_MPOOL_HASH *hp;
MPOOL *c_mp;
int bucket;
@@ -320,27 +370,24 @@ __memp_dumpcache(dbmp, reginfo, fmap, fp, flags)
/* Display the hash table list of BH's. */
if (LF_ISSET(MPOOL_DUMP_HASH)) {
(void)fprintf(fp,
- "%s\nBH hash table (%lu hash slots)\npageno, file, ref, address\n",
+ "%s\nBH hash table (%lu hash slots)\nbucket (priority):\n",
DB_LINE, (u_long)c_mp->htab_buckets);
- for (dbht = R_ADDR(reginfo, c_mp->htab),
- bucket = 0; bucket < c_mp->htab_buckets; ++dbht, ++bucket) {
- if (SH_TAILQ_FIRST(dbht, __bh) != NULL)
- (void)fprintf(fp, "%lu:\n", (u_long)bucket);
- for (bhp = SH_TAILQ_FIRST(dbht, __bh);
- bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+ (void)fprintf(fp,
+ "\tpageno, file, ref, address [LSN] priority\n");
+
+ for (hp = R_ADDR(reginfo, c_mp->htab),
+ bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
+ if ((bhp =
+ SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) != NULL)
+ (void)fprintf(fp, "%lu (%u):\n",
+ (u_long)bucket, hp->hash_priority);
+ for (; bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
__memp_pbh(dbmp, bhp, fmap, fp);
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
}
}
- /* Display the LRU list of BH's. */
- if (LF_ISSET(MPOOL_DUMP_LRU)) {
- (void)fprintf(fp, "%s\nBH LRU list\n", DB_LINE);
- (void)fprintf(fp, "pageno, file, ref, address\n");
- for (bhp = SH_TAILQ_FIRST(&c_mp->bhq, __bh);
- bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
- __memp_pbh(dbmp, bhp, fmap, fp);
- }
-
/* Dump the memory pool. */
if (LF_ISSET(MPOOL_DUMP_MEM))
__db_shalloc_dump(reginfo->addr, fp);
@@ -360,10 +407,9 @@ __memp_pbh(dbmp, bhp, fmap, fp)
static const FN fn[] = {
{ BH_CALLPGIN, "callpgin" },
{ BH_DIRTY, "dirty" },
+ { BH_DIRTY_CREATE, "created" },
{ BH_DISCARD, "discard" },
{ BH_LOCKED, "locked" },
- { BH_SYNC, "sync" },
- { BH_SYNC_LOGFLSH, "sync:logflush" },
{ BH_TRASH, "trash" },
{ 0, NULL }
};
@@ -374,15 +420,72 @@ __memp_pbh(dbmp, bhp, fmap, fp)
break;
if (fmap[i] == INVALID_ROFF)
- (void)fprintf(fp, " %4lu, %lu, %2lu, %lu",
+ (void)fprintf(fp, "\t%5lu, %lu, %2lu, %8lu [%lu,%lu] %lu",
(u_long)bhp->pgno, (u_long)bhp->mf_offset,
- (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp));
+ (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp),
+ (u_long)LSN(bhp->buf).file, (u_long)LSN(bhp->buf).offset,
+ (u_long)bhp->priority);
else
- (void)fprintf(fp, " %4lu, #%d, %2lu, %lu",
+ (void)fprintf(fp, "\t%5lu, #%d, %2lu, %8lu [%lu,%lu] %lu",
(u_long)bhp->pgno, i + 1,
- (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp));
+ (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp),
+ (u_long)LSN(bhp->buf).file, (u_long)LSN(bhp->buf).offset,
+ (u_long)bhp->priority);
__db_prflags(bhp->flags, fn, fp);
(void)fprintf(fp, "\n");
}
+
+/*
+ * __memp_stat_hash --
+ * Total hash bucket stats (other than mutex wait) into the region.
+ *
+ * PUBLIC: void __memp_stat_hash __P((REGINFO *, MPOOL *, u_int32_t *));
+ */
+void
+__memp_stat_hash(reginfo, mp, dirtyp)
+ REGINFO *reginfo;
+ MPOOL *mp;
+ u_int32_t *dirtyp;
+{
+ DB_MPOOL_HASH *hp;
+ u_int32_t dirty;
+ int i;
+
+ hp = R_ADDR(reginfo, mp->htab);
+ for (i = 0, dirty = 0; i < mp->htab_buckets; i++, hp++)
+ dirty += hp->hash_page_dirty;
+ *dirtyp = dirty;
+}
+
+/*
+ * __memp_stat_wait --
+ * Total hash bucket wait stats into the region.
+ */
+static void
+__memp_stat_wait(reginfo, mp, mstat, flags)
+ REGINFO *reginfo;
+ MPOOL *mp;
+ DB_MPOOL_STAT *mstat;
+ int flags;
+{
+ DB_MPOOL_HASH *hp;
+ DB_MUTEX *mutexp;
+ int i;
+
+ mstat->st_hash_max_wait = 0;
+ hp = R_ADDR(reginfo, mp->htab);
+ for (i = 0; i < mp->htab_buckets; i++, hp++) {
+ mutexp = &hp->hash_mutex;
+ mstat->st_hash_nowait += mutexp->mutex_set_nowait;
+ mstat->st_hash_wait += mutexp->mutex_set_wait;
+ if (mutexp->mutex_set_wait > mstat->st_hash_max_wait)
+ mstat->st_hash_max_wait = mutexp->mutex_set_wait;
+
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ mutexp->mutex_set_wait = 0;
+ mutexp->mutex_set_nowait = 0;
+ }
+ }
+}
diff --git a/bdb/mp/mp_sync.c b/bdb/mp/mp_sync.c
index 1b0751db709..03b42208b39 100644
--- a/bdb/mp/mp_sync.c
+++ b/bdb/mp/mp_sync.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_sync.c,v 11.29 2001/01/11 18:19:53 bostic Exp $";
+static const char revid[] = "$Id: mp_sync.c,v 11.64 2002/08/25 16:00:27 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,339 +16,92 @@ static const char revid[] = "$Id: mp_sync.c,v 11.29 2001/01/11 18:19:53 bostic E
#include <stdlib.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+typedef struct {
+ DB_MPOOL_HASH *track_hp; /* Hash bucket. */
+
+ roff_t track_off; /* Page file offset. */
+ db_pgno_t track_pgno; /* Page number. */
+} BH_TRACK;
static int __bhcmp __P((const void *, const void *));
-static int __memp_fsync __P((DB_MPOOLFILE *));
-static int __memp_sballoc __P((DB_ENV *, BH ***, u_int32_t *));
+static int __memp_close_flush_files __P((DB_ENV *, DB_MPOOL *));
+static int __memp_sync_files __P((DB_ENV *, DB_MPOOL *));
/*
- * memp_sync --
+ * __memp_sync --
* Mpool sync function.
+ *
+ * PUBLIC: int __memp_sync __P((DB_ENV *, DB_LSN *));
*/
int
-memp_sync(dbenv, lsnp)
+__memp_sync(dbenv, lsnp)
DB_ENV *dbenv;
DB_LSN *lsnp;
{
- BH *bhp, **bharray;
DB_MPOOL *dbmp;
- DB_LSN tlsn;
- MPOOL *c_mp, *mp;
- MPOOLFILE *mfp;
- u_int32_t ar_cnt, i, ndirty;
- int ret, retry_done, retry_need, wrote;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_sync(dbenv, lsnp));
-#endif
+ MPOOL *mp;
+ int ret;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
-
- dbmp = dbenv->mp_handle;
- mp = dbmp->reginfo[0].primary;
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->mp_handle, "memp_sync", DB_INIT_MPOOL);
/*
- * If no LSN is provided, flush the entire cache.
- *
- * !!!
- * Our current behavior is to flush the entire cache, so there's
- * nothing special we have to do here other than deal with NULL
- * pointers.
+ * If no LSN is provided, flush the entire cache (reasonable usage
+ * even if there's no log subsystem configured).
*/
- if (lsnp == NULL) {
- ZERO_LSN(tlsn);
- lsnp = &tlsn;
- F_SET(mp, MP_LSN_RETRY);
- } else if (!LOGGING_ON(dbenv)) {
- __db_err(dbenv, "memp_sync: requires logging");
- return (EINVAL);
- }
+ if (lsnp != NULL)
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "memp_sync", DB_INIT_LOG);
- /*
- * Sync calls are single-threaded so that we don't have multiple
- * threads, with different checkpoint LSNs, walking the caches
- * and updating the checkpoint LSNs and how many buffers remain
- * to be written for the checkpoint. This shouldn't be a problem,
- * any application that has multiple checkpoint threads isn't what
- * I'd call trustworthy.
- */
- MUTEX_LOCK(dbenv, &mp->sync_mutex, dbenv->lockfhp);
+ dbmp = dbenv->mp_handle;
+ mp = dbmp->reginfo[0].primary;
- /*
- * If the application is asking about a previous call to memp_sync(),
- * and we haven't found any buffers that the application holding the
- * pin couldn't write, return yes or no based on the current count.
- * Note, if the application is asking about a LSN *smaller* than one
- * we've already handled or are currently handling, then we return a
- * result based on the count for the larger LSN.
- */
- R_LOCK(dbenv, dbmp->reginfo);
- if (!IS_ZERO_LSN(*lsnp) &&
- !F_ISSET(mp, MP_LSN_RETRY) && log_compare(lsnp, &mp->lsn) <= 0) {
- if (mp->lsn_cnt == 0) {
+ /* If we've flushed to the requested LSN, return that information. */
+ if (lsnp != NULL) {
+ R_LOCK(dbenv, dbmp->reginfo);
+ if (log_compare(lsnp, &mp->lsn) <= 0) {
*lsnp = mp->lsn;
- ret = 0;
- } else
- ret = DB_INCOMPLETE;
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ return (0);
+ }
R_UNLOCK(dbenv, dbmp->reginfo);
- MUTEX_UNLOCK(dbenv, &mp->sync_mutex);
- return (ret);
}
- /*
- * Allocate room for a list of buffers, and decide how many buffers
- * we can pin down.
- *
- * !!!
- * Note: __memp_sballoc has released the region lock if we're not
- * continuing forward.
- */
- if ((ret =
- __memp_sballoc(dbenv, &bharray, &ndirty)) != 0 || ndirty == 0) {
- MUTEX_UNLOCK(dbenv, &mp->sync_mutex);
+ if ((ret = __memp_sync_int(dbenv, NULL, 0, DB_SYNC_CACHE, NULL)) != 0)
return (ret);
- }
- retry_done = 0;
-retry: retry_need = 0;
- /*
- * Start a new checkpoint.
- *
- * Save the LSN. We know that it's a new LSN, a retry, or larger than
- * the one for which we were already doing a checkpoint. (BTW, I don't
- * expect to see multiple LSN's from the same or multiple processes,
- * but You Just Never Know. Responding as if they all called with the
- * largest of the LSNs specified makes everything work.)
- *
- * We don't currently use the LSN we save. We could potentially save
- * the last-written LSN in each buffer header and use it to determine
- * what buffers need to be written. The problem with this is that it's
- * sizeof(LSN) more bytes of buffer header. We currently write all the
- * dirty buffers instead, but with a sufficiently large cache that's
- * going to be a problem.
- */
- mp->lsn = *lsnp;
-
- /*
- * Clear the global count of buffers waiting to be written, walk the
- * list of files clearing the count of buffers waiting to be written.
- *
- * Clear the retry flag.
- */
- mp->lsn_cnt = 0;
- for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
- mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
- mfp->lsn_cnt = 0;
- F_CLR(mp, MP_LSN_RETRY);
-
- /*
- * Walk each cache's list of buffers and mark all dirty buffers to be
- * written and all pinned buffers to be potentially written (we can't
- * know if they'll need to be written until the holder returns them to
- * the cache). We do this in one pass while holding the region locked
- * so that processes can't make new buffers dirty, causing us to never
- * finish. Since the application may have restarted the sync using a
- * different LSN value, clear any BH_SYNC | BH_SYNC_LOGFLSH flags that
- * appear leftover from previous calls.
- *
- * Keep a count of the total number of buffers we need to write in
- * MPOOL->lsn_cnt, and for each file, in MPOOLFILE->lsn_count.
- */
- for (ar_cnt = 0, i = 0; i < mp->nreg; ++i) {
- c_mp = dbmp->reginfo[i].primary;
- for (bhp = SH_TAILQ_FIRST(&c_mp->bhq, __bh);
- bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) {
- if (F_ISSET(bhp, BH_DIRTY) || bhp->ref != 0) {
- F_SET(bhp, BH_SYNC);
-
- ++mp->lsn_cnt;
-
- mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
- ++mfp->lsn_cnt;
-
- /*
- * If the buffer isn't being used, we can write
- * it immediately, so increment its reference
- * count to lock it down, and save a reference
- * to it.
- *
- * If we've run out space to store buffer refs,
- * we're screwed. We don't want to realloc the
- * array while holding a region lock, so we set
- * a flag and deal with it later.
- */
- if (bhp->ref == 0) {
- ++bhp->ref;
- bharray[ar_cnt] = bhp;
-
- if (++ar_cnt >= ndirty) {
- retry_need = 1;
- break;
- }
- }
- } else
- if (F_ISSET(bhp, BH_SYNC))
- F_CLR(bhp, BH_SYNC | BH_SYNC_LOGFLSH);
- }
- if (ar_cnt >= ndirty)
- break;
- }
-
- /* If there no buffers we can write immediately, we're done. */
- if (ar_cnt == 0) {
- ret = mp->lsn_cnt ? DB_INCOMPLETE : 0;
- goto done;
- }
-
- R_UNLOCK(dbenv, dbmp->reginfo);
-
- /*
- * Sort the buffers we're going to write immediately.
- *
- * We try and write the buffers in file/page order: it should reduce
- * seeks by the underlying filesystem and possibly reduce the actual
- * number of writes.
- */
- if (ar_cnt > 1)
- qsort(bharray, ar_cnt, sizeof(BH *), __bhcmp);
-
- /*
- * Flush the log. We have to ensure the log records reflecting the
- * changes on the database pages we're writing have already made it
- * to disk. We usually do that as we write each page, but if we
- * are going to write a large number of pages, repeatedly acquiring
- * the log region lock is going to be expensive. Flush the entire
- * log now, so that sync doesn't require any more log flushes.
- */
- if (LOGGING_ON(dbenv) && (ret = log_flush(dbenv, NULL)) != 0)
- goto done;
-
- R_LOCK(dbenv, dbmp->reginfo);
-
- /* Walk the array, writing buffers. */
- for (i = 0; i < ar_cnt; ++i) {
- /*
- * It's possible for a thread to have gotten the buffer since
- * we listed it for writing. If the reference count is still
- * 1, we're the only ones using the buffer, go ahead and write.
- * If it's >1, then skip the buffer and assume that it will be
- * written when it's returned to the cache.
- */
- if (bharray[i]->ref > 1) {
- --bharray[i]->ref;
- continue;
- }
-
- /* Write the buffer. */
- mfp = R_ADDR(dbmp->reginfo, bharray[i]->mf_offset);
- ret = __memp_bhwrite(dbmp, mfp, bharray[i], NULL, &wrote);
-
- /* Release the buffer. */
- --bharray[i]->ref;
-
- if (ret == 0 && wrote)
- continue;
-
- /*
- * Any process syncing the shared memory buffer pool had best
- * be able to write to any underlying file. Be understanding,
- * but firm, on this point.
- */
- if (ret == 0) {
- __db_err(dbenv, "%s: unable to flush page: %lu",
- __memp_fns(dbmp, mfp), (u_long)bharray[i]->pgno);
- ret = EPERM;
- }
-
- /*
- * On error, clear MPOOL->lsn and set MP_LSN_RETRY so that no
- * future checkpoint return can depend on this failure. Clear
- * the buffer's BH_SYNC flag, because it's used to determine
- * if lsn_cnt values are incremented/decremented. Don't bother
- * to reset/clear:
- *
- * MPOOL->lsn_cnt
- * MPOOLFILE->lsn_cnt
- *
- * they don't make any difference.
- */
- ZERO_LSN(mp->lsn);
- F_SET(mp, MP_LSN_RETRY);
-
- /* Release any buffers we're still pinning down. */
- while (++i < ar_cnt) {
- bhp = bharray[i];
- --bhp->ref;
- F_CLR(bhp, BH_SYNC | BH_SYNC_LOGFLSH);
- }
-
- goto done;
- }
-
- ret = mp->lsn_cnt != 0 ? DB_INCOMPLETE : 0;
-
- /*
- * If there were too many buffers and we're not returning an error, we
- * re-try the checkpoint once -- since we allocated 80% of the total
- * buffer count, once should be enough. If it still doesn't work, some
- * other thread of control is dirtying buffers as fast as we're writing
- * them, and we might as well give up for now. In the latter case, set
- * the global retry flag, we'll have to start from scratch on the next
- * checkpoint.
- */
- if (retry_need) {
- if (retry_done) {
- ret = DB_INCOMPLETE;
- F_SET(mp, MP_LSN_RETRY);
- } else {
- retry_done = 1;
- goto retry;
- }
+ if (lsnp != NULL) {
+ R_LOCK(dbenv, dbmp->reginfo);
+ if (log_compare(lsnp, &mp->lsn) > 0)
+ mp->lsn = *lsnp;
+ R_UNLOCK(dbenv, dbmp->reginfo);
}
-done: R_UNLOCK(dbenv, dbmp->reginfo);
- MUTEX_UNLOCK(dbenv, &mp->sync_mutex);
-
- __os_free(bharray, ndirty * sizeof(BH *));
-
- return (ret);
+ return (0);
}
/*
- * memp_fsync --
+ * __memp_fsync --
* Mpool file sync function.
+ *
+ * PUBLIC: int __memp_fsync __P((DB_MPOOLFILE *));
*/
int
-memp_fsync(dbmfp)
+__memp_fsync(dbmfp)
DB_MPOOLFILE *dbmfp;
{
DB_ENV *dbenv;
DB_MPOOL *dbmp;
- int is_tmp;
dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fsync(dbmfp));
-#endif
-
PANIC_CHECK(dbenv);
/*
@@ -359,13 +112,10 @@ memp_fsync(dbmfp)
if (F_ISSET(dbmfp, MP_READONLY))
return (0);
- R_LOCK(dbenv, dbmp->reginfo);
- is_tmp = F_ISSET(dbmfp->mfp, MP_TEMP);
- R_UNLOCK(dbenv, dbmp->reginfo);
- if (is_tmp)
+ if (F_ISSET(dbmfp->mfp, MP_TEMP))
return (0);
- return (__memp_fsync(dbmfp));
+ return (__memp_sync_int(dbenv, dbmfp, 0, DB_SYNC_FILE, NULL));
}
/*
@@ -379,6 +129,7 @@ __mp_xxx_fh(dbmfp, fhp)
DB_MPOOLFILE *dbmfp;
DB_FH **fhp;
{
+ DB_ENV *dbenv;
/*
* This is a truly spectacular layering violation, intended ONLY to
* support compatibility for the DB 1.85 DB->fd call.
@@ -393,239 +144,457 @@ __mp_xxx_fh(dbmfp, fhp)
* because we want to write to the backing file regardless so that
* we get a file descriptor to return.
*/
- *fhp = &dbmfp->fh;
- return (F_ISSET(&dbmfp->fh, DB_FH_VALID) ? 0 : __memp_fsync(dbmfp));
+ *fhp = dbmfp->fhp;
+ if (F_ISSET(dbmfp->fhp, DB_FH_VALID))
+ return (0);
+ dbenv = dbmfp->dbmp->dbenv;
+
+ return (__memp_sync_int(dbenv, dbmfp, 0, DB_SYNC_FILE, NULL));
}
/*
- * __memp_fsync --
- * Mpool file internal sync function.
+ * __memp_sync_int --
+ * Mpool sync internal function.
+ *
+ * PUBLIC: int __memp_sync_int
+ * PUBLIC: __P((DB_ENV *, DB_MPOOLFILE *, int, db_sync_op, int *));
*/
-static int
-__memp_fsync(dbmfp)
+int
+__memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
+ DB_ENV *dbenv;
DB_MPOOLFILE *dbmfp;
+ int ar_max, *wrotep;
+ db_sync_op op;
{
- BH *bhp, **bharray;
- DB_ENV *dbenv;
+ BH *bhp;
+ BH_TRACK *bharray;
DB_MPOOL *dbmp;
+ DB_MPOOL_HASH *hp;
+ DB_MUTEX *mutexp;
MPOOL *c_mp, *mp;
- size_t mf_offset;
- u_int32_t ar_cnt, i, ndirty;
- int incomplete, ret, retry_done, retry_need, wrote;
+ MPOOLFILE *mfp;
+ u_int32_t n_cache;
+ int ar_cnt, hb_lock, i, pass, remaining, ret, t_ret, wait_cnt, wrote;
- dbmp = dbmfp->dbmp;
- dbenv = dbmp->dbenv;
+ dbmp = dbenv->mp_handle;
mp = dbmp->reginfo[0].primary;
-
- R_LOCK(dbenv, dbmp->reginfo);
+ pass = wrote = 0;
/*
- * Allocate room for a list of buffers, and decide how many buffers
- * we can pin down.
- *
- * !!!
- * Note: __memp_sballoc has released our region lock if we're not
- * continuing forward.
+ * If the caller does not specify how many pages assume one
+ * per bucket.
*/
+ if (ar_max == 0)
+ ar_max = mp->nreg * mp->htab_buckets;
+
if ((ret =
- __memp_sballoc(dbenv, &bharray, &ndirty)) != 0 || ndirty == 0)
+ __os_malloc(dbenv, ar_max * sizeof(BH_TRACK), &bharray)) != 0)
return (ret);
- retry_done = 0;
-retry: retry_need = 0;
/*
* Walk each cache's list of buffers and mark all dirty buffers to be
- * written and all pinned buffers to be potentially written (we can't
- * know if they'll need to be written until the holder returns them to
- * the cache). We do this in one pass while holding the region locked
- * so that processes can't make new buffers dirty, causing us to never
- * finish.
+ * written and all pinned buffers to be potentially written, depending
+ * on our flags.
*/
- mf_offset = R_OFFSET(dbmp->reginfo, dbmfp->mfp);
- for (ar_cnt = 0, incomplete = 0, i = 0; i < mp->nreg; ++i) {
- c_mp = dbmp->reginfo[i].primary;
- for (bhp = SH_TAILQ_FIRST(&c_mp->bhq, __bh);
- bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) {
- if (!F_ISSET(bhp, BH_DIRTY) ||
- bhp->mf_offset != mf_offset)
- continue;
- if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED)) {
- incomplete = 1;
- continue;
- }
+ for (ar_cnt = 0, n_cache = 0; n_cache < mp->nreg; ++n_cache) {
+ c_mp = dbmp->reginfo[n_cache].primary;
+ hp = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
+ for (i = 0; i < c_mp->htab_buckets; i++, hp++) {
/*
- * If the buffer isn't being used, we can write
- * it immediately, so increment its reference
- * count to lock it down, and save a reference
- * to it.
- *
- * If we've run out space to store buffer refs,
- * we're screwed. We don't want to realloc the
- * array while holding a region lock, so we set
- * a flag and deal with it later.
+ * We can check for empty buckets before locking as we
+ * only care if the pointer is zero or non-zero. We
+ * can ignore empty buckets because we only need write
+ * buffers that were dirty before we started.
*/
- ++bhp->ref;
- bharray[ar_cnt] = bhp;
- if (++ar_cnt >= ndirty) {
- retry_need = 1;
- break;
+ if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL)
+ continue;
+
+ MUTEX_LOCK(dbenv, &hp->hash_mutex);
+ for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+ bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) {
+ /* Always ignore unreferenced, clean pages. */
+ if (bhp->ref == 0 && !F_ISSET(bhp, BH_DIRTY))
+ continue;
+
+ /*
+ * Checkpoints have to wait on all pinned pages,
+ * as pages may be marked dirty when returned to
+ * the cache.
+ *
+ * File syncs only wait on pages both pinned and
+ * dirty. (We don't care if pages are marked
+ * dirty when returned to the cache, that means
+ * there's another writing thread and flushing
+ * the cache for this handle is meaningless.)
+ */
+ if (op == DB_SYNC_FILE &&
+ !F_ISSET(bhp, BH_DIRTY))
+ continue;
+
+ mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
+
+ /*
+ * Ignore temporary files -- this means you
+ * can't even flush temporary files by handle.
+ * (Checkpoint doesn't require temporary files
+ * be flushed and the underlying buffer write
+ * write routine may not be able to write it
+ * anyway.)
+ */
+ if (F_ISSET(mfp, MP_TEMP))
+ continue;
+
+ /*
+ * If we're flushing a specific file, see if
+ * this page is from that file.
+ */
+ if (dbmfp != NULL && mfp != dbmfp->mfp)
+ continue;
+
+ /*
+ * Ignore files that aren't involved in DB's
+ * transactional operations during checkpoints.
+ */
+ if (dbmfp == NULL && mfp->lsn_off == -1)
+ continue;
+
+ /* Track the buffer, we want it. */
+ bharray[ar_cnt].track_hp = hp;
+ bharray[ar_cnt].track_pgno = bhp->pgno;
+ bharray[ar_cnt].track_off = bhp->mf_offset;
+ ar_cnt++;
+
+ if (ar_cnt >= ar_max) {
+ if ((ret = __os_realloc(dbenv,
+ (ar_max * 2) * sizeof(BH_TRACK),
+ &bharray)) != 0)
+ break;
+ ar_max *= 2;
+ }
}
+ MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+
+ if (ret != 0)
+ goto err;
}
- if (ar_cnt >= ndirty)
- break;
}
- /* If there no buffers we can write immediately, we're done. */
- if (ar_cnt == 0) {
- ret = 0;
+ /* If there no buffers to write, we're done. */
+ if (ar_cnt == 0)
goto done;
- }
- R_UNLOCK(dbenv, dbmp->reginfo);
-
- /* Sort the buffers we're going to write. */
+ /*
+ * Write the buffers in file/page order, trying to reduce seeks by the
+ * filesystem and, when pages are smaller than filesystem block sizes,
+ * reduce the actual number of writes.
+ */
if (ar_cnt > 1)
- qsort(bharray, ar_cnt, sizeof(BH *), __bhcmp);
+ qsort(bharray, ar_cnt, sizeof(BH_TRACK), __bhcmp);
- R_LOCK(dbenv, dbmp->reginfo);
+ /*
+ * If we're trickling buffers, only write enough to reach the correct
+ * percentage for this region. We may not write enough if the dirty
+ * buffers have an unbalanced distribution among the regions, but that
+ * seems unlikely.
+ */
+ if (op == DB_SYNC_TRICKLE && ar_cnt > ar_max / (int)mp->nreg)
+ ar_cnt = ar_max / (int)mp->nreg;
+
+ /*
+ * Flush the log. We have to ensure the log records reflecting the
+ * changes on the database pages we're writing have already made it
+ * to disk. We still have to check the log each time we write a page
+ * (because pages we are about to write may be modified after we have
+ * flushed the log), but in general this will at least avoid any I/O
+ * on the log's part.
+ */
+ if (LOGGING_ON(dbenv) && (ret = dbenv->log_flush(dbenv, NULL)) != 0)
+ goto err;
+
+ /*
+ * Walk the array, writing buffers. When we write a buffer, we NULL
+ * out its hash bucket pointer so we don't process a slot more than
+ * once.
+ */
+ for (remaining = ar_cnt, i = pass = 0; remaining > 0; ++i) {
+ if (i >= ar_cnt) {
+ i = 0;
+ ++pass;
+ __os_sleep(dbenv, 1, 0);
+ }
+ if ((hp = bharray[i].track_hp) == NULL)
+ continue;
+
+ /* Lock the hash bucket and find the buffer. */
+ mutexp = &hp->hash_mutex;
+ MUTEX_LOCK(dbenv, mutexp);
+ for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+ bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+ if (bhp->pgno == bharray[i].track_pgno &&
+ bhp->mf_offset == bharray[i].track_off)
+ break;
- /* Walk the array, writing buffers. */
- for (i = 0; i < ar_cnt;) {
/*
- * It's possible for a thread to have gotten the buffer since
- * we listed it for writing. If the reference count is still
- * 1, we're the only ones using the buffer, go ahead and write.
- * If it's >1, then skip the buffer and assume that it will be
- * written when it's returned to the cache.
+ * If we can't find the buffer we're done, somebody else had
+ * to have written it.
+ *
+ * If the buffer isn't pinned or dirty, we're done, there's
+ * no work needed.
*/
- if (bharray[i]->ref > 1) {
- incomplete = 1;
- --bharray[i++]->ref;
+ if (bhp == NULL || (bhp->ref == 0 && !F_ISSET(bhp, BH_DIRTY))) {
+ MUTEX_UNLOCK(dbenv, mutexp);
+ --remaining;
+ bharray[i].track_hp = NULL;
continue;
}
- /* Write the buffer. */
- ret = __memp_pgwrite(dbmp, dbmfp, bharray[i], NULL, &wrote);
+ /*
+ * If the buffer is locked by another thread, ignore it, we'll
+ * come back to it.
+ *
+ * If the buffer is pinned and it's only the first or second
+ * time we have looked at it, ignore it, we'll come back to
+ * it.
+ *
+ * In either case, skip the buffer if we're not required to
+ * write it.
+ */
+ if (F_ISSET(bhp, BH_LOCKED) || (bhp->ref != 0 && pass < 2)) {
+ MUTEX_UNLOCK(dbenv, mutexp);
+ if (op != DB_SYNC_CACHE && op != DB_SYNC_FILE) {
+ --remaining;
+ bharray[i].track_hp = NULL;
+ }
+ continue;
+ }
+
+ /*
+ * The buffer is either pinned or dirty.
+ *
+ * Set the sync wait-for count, used to count down outstanding
+ * references to this buffer as they are returned to the cache.
+ */
+ bhp->ref_sync = bhp->ref;
- /* Release the buffer. */
- --bharray[i++]->ref;
+ /* Pin the buffer into memory and lock it. */
+ ++bhp->ref;
+ F_SET(bhp, BH_LOCKED);
+ MUTEX_LOCK(dbenv, &bhp->mutex);
- if (ret == 0) {
- if (!wrote)
- incomplete = 1;
- continue;
+ /*
+ * Unlock the hash bucket and wait for the wait-for count to
+ * go to 0. No new thread can acquire the buffer because we
+ * have it locked.
+ *
+ * If a thread attempts to re-pin a page, the wait-for count
+ * will never go to 0 (the thread spins on our buffer lock,
+ * while we spin on the thread's ref count). Give up if we
+ * don't get the buffer in 3 seconds, we can try again later.
+ *
+ * If, when the wait-for count goes to 0, the buffer is found
+ * to be dirty, write it.
+ */
+ MUTEX_UNLOCK(dbenv, mutexp);
+ for (wait_cnt = 1;
+ bhp->ref_sync != 0 && wait_cnt < 4; ++wait_cnt)
+ __os_sleep(dbenv, 1, 0);
+ MUTEX_LOCK(dbenv, mutexp);
+ hb_lock = 1;
+
+ /*
+ * If the ref_sync count has gone to 0, we're going to be done
+ * with this buffer no matter what happens.
+ */
+ if (bhp->ref_sync == 0) {
+ --remaining;
+ bharray[i].track_hp = NULL;
}
/*
- * On error:
+ * If the ref_sync count has gone to 0 and the buffer is still
+ * dirty, we write it. We only try to write the buffer once.
+ * Any process checkpointing or trickle-flushing the pool
+ * must be able to write any underlying file -- if the write
+ * fails, error out. It would be very strange if file sync
+ * failed to write, but we don't care if it happens.
+ */
+ if (bhp->ref_sync == 0 && F_ISSET(bhp, BH_DIRTY)) {
+ hb_lock = 0;
+ MUTEX_UNLOCK(dbenv, mutexp);
+
+ mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
+ if ((ret = __memp_bhwrite(dbmp, hp, mfp, bhp, 1)) == 0)
+ ++wrote;
+ else if (op == DB_SYNC_CACHE || op == DB_SYNC_TRICKLE)
+ __db_err(dbenv, "%s: unable to flush page: %lu",
+ __memp_fns(dbmp, mfp), (u_long)bhp->pgno);
+ else
+ ret = 0;
+ }
+
+ /*
+ * If ref_sync count never went to 0, the buffer was written
+ * by another thread, or the write failed, we still have the
+ * buffer locked.
+ *
+ * We may or may not currently hold the hash bucket mutex. If
+ * the __memp_bhwrite -> __memp_pgwrite call was successful,
+ * then __memp_pgwrite will have swapped the buffer lock for
+ * the hash lock. All other call paths will leave us without
+ * the hash bucket lock.
*
- * Release any buffers we're still pinning down.
+ * The order of mutexes above was to acquire the buffer lock
+ * while holding the hash bucket lock. Don't deadlock here,
+ * release the buffer lock and then acquire the hash bucket
+ * lock.
*/
- while (i < ar_cnt)
- --bharray[i++]->ref;
- break;
- }
+ if (F_ISSET(bhp, BH_LOCKED)) {
+ F_CLR(bhp, BH_LOCKED);
+ MUTEX_UNLOCK(dbenv, &bhp->mutex);
- /*
- * If there were too many buffers and we're not returning an error, we
- * re-try the flush once -- since we allocated 80% of the total
- * buffer count, once should be enough. If it still doesn't work, some
- * other thread of control is dirtying buffers as fast as we're writing
- * them, and we might as well give up.
- */
- if (retry_need) {
- if (retry_done)
- incomplete = 1;
- else {
- retry_done = 1;
- goto retry;
+ if (!hb_lock)
+ MUTEX_LOCK(dbenv, mutexp);
}
- }
-done: R_UNLOCK(dbenv, dbmp->reginfo);
+ /*
+ * Reset the ref_sync count regardless of our success, we're
+ * done with this buffer for now.
+ */
+ bhp->ref_sync = 0;
+
+ /* Discard our reference and unlock the bucket. */
+ --bhp->ref;
+ MUTEX_UNLOCK(dbenv, mutexp);
- __os_free(bharray, ndirty * sizeof(BH *));
+ if (ret != 0)
+ break;
+ }
+
+done: /* If we've opened files to flush pages, close them. */
+ if ((t_ret = __memp_close_flush_files(dbenv, dbmp)) != 0 && ret == 0)
+ ret = t_ret;
/*
- * Sync the underlying file as the last thing we do, so that the OS
- * has a maximal opportunity to flush buffers before we request it.
- *
- * !!!:
- * Don't lock the region around the sync, fsync(2) has no atomicity
- * issues.
+ * If doing a checkpoint or flushing a file for the application, we
+ * have to force the pages to disk. We don't do this as we go along
+ * because we want to give the OS as much time as possible to lazily
+ * flush, and because we have to flush files that might not even have
+ * had dirty buffers in the cache, so we have to walk the files list.
*/
- if (ret == 0)
- ret = incomplete ?
- DB_INCOMPLETE : __os_fsync(dbenv, &dbmfp->fh);
+ if (ret == 0 && (op == DB_SYNC_CACHE || op == DB_SYNC_FILE)) {
+ if (dbmfp == NULL)
+ ret = __memp_sync_files(dbenv, dbmp);
+ else
+ ret = __os_fsync(dbenv, dbmfp->fhp);
+ }
+
+err: __os_free(dbenv, bharray);
+ if (wrotep != NULL)
+ *wrotep = wrote;
return (ret);
}
/*
- * __memp_sballoc --
- * Allocate room for a list of buffers.
+ * __memp_sync_files --
+ * Sync all the files in the environment, open or not.
*/
-static int
-__memp_sballoc(dbenv, bharrayp, ndirtyp)
+static
+int __memp_sync_files(dbenv, dbmp)
DB_ENV *dbenv;
- BH ***bharrayp;
- u_int32_t *ndirtyp;
-{
DB_MPOOL *dbmp;
- MPOOL *c_mp, *mp;
- u_int32_t i, nclean, ndirty, maxpin;
- int ret;
+{
+ DB_MPOOLFILE *dbmfp;
+ MPOOL *mp;
+ MPOOLFILE *mfp;
+ int ret, t_ret;
- dbmp = dbenv->mp_handle;
+ ret = 0;
mp = dbmp->reginfo[0].primary;
- /*
- * We don't want to hold the region lock while we write the buffers,
- * so only lock it while we create a list.
- *
- * Walk through the list of caches, figuring out how many buffers
- * we're going to need.
- *
- * Make a point of not holding the region lock across the library
- * allocation call.
- */
- for (nclean = ndirty = 0, i = 0; i < mp->nreg; ++i) {
- c_mp = dbmp->reginfo[i].primary;
- ndirty += c_mp->stat.st_page_dirty;
- nclean += c_mp->stat.st_page_clean;
+ R_LOCK(dbenv, dbmp->reginfo);
+ for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
+ mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
+ if (mfp->stat.st_page_out == 0 ||
+ F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
+ continue;
+
+ /* Look for an already open handle. */
+ ret = 0;
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+ for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
+ dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
+ if (dbmfp->mfp == mfp) {
+ ret = __os_fsync(dbenv, dbmfp->fhp);
+ break;
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+ if (ret != 0)
+ goto err;
+
+ /* If we don't find one, open one. */
+ if (dbmfp == NULL) {
+ if ((ret = dbenv->memp_fcreate(dbenv, &dbmfp, 0)) != 0)
+ goto err;
+ ret = __memp_fopen_int(
+ dbmfp, mfp, R_ADDR(dbmp->reginfo, mfp->path_off),
+ 0, 0, mfp->stat.st_pagesize);
+ if (ret == 0)
+ ret = __os_fsync(dbenv, dbmfp->fhp);
+ if ((t_ret =
+ __memp_fclose_int(dbmfp, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (ret != 0)
+ goto err;
+ }
}
- R_UNLOCK(dbenv, dbmp->reginfo);
- if (ndirty == 0) {
- *ndirtyp = 0;
- return (0);
+
+ if (0) {
+err: __db_err(dbenv, "%s: cannot sync: %s",
+ R_ADDR(dbmp->reginfo, mfp->path_off), db_strerror(ret));
}
+ R_UNLOCK(dbenv, dbmp->reginfo);
- /*
- * We don't want to pin down the entire buffer cache, otherwise we'll
- * starve threads needing new pages. Don't pin down more than 80% of
- * the cache, making sure that we don't screw up just because only a
- * few pages have been created.
- */
- maxpin = ((ndirty + nclean) * 8) / 10;
- if (maxpin < 10)
- maxpin = 10;
+ return (ret);
+}
+
+/*
+ * __memp_close_flush_files --
+ * Close files opened only to flush buffers.
+ */
+static int
+__memp_close_flush_files(dbenv, dbmp)
+ DB_ENV *dbenv;
+ DB_MPOOL *dbmp;
+{
+ DB_MPOOLFILE *dbmfp;
+ int ret;
/*
- * Get a good-sized block of memory to hold buffer pointers, we don't
- * want to run out, but correct if we want to allocate more than we
- * would be allowed to store, regardless.
+ * The routine exists because we must close files opened by sync to
+ * flush buffers. There are two cases: first, extent files have to
+ * be closed so they may be removed when empty. Second, regular
+ * files have to be closed so we don't run out of descriptors (for
+ * example, and application partitioning its data into databases
+ * based on timestamps, so there's a continually increasing set of
+ * files).
+ *
+ * We mark files opened in the __memp_bhwrite() function with the
+ * MP_FLUSH flag. Here we walk through our file descriptor list,
+ * and, if a file was opened by __memp_bhwrite(), we close it.
*/
- ndirty += ndirty / 2 + 10;
- if (ndirty > maxpin)
- ndirty = maxpin;
- if ((ret =
- __os_malloc(dbenv, ndirty * sizeof(BH *), NULL, bharrayp)) != 0)
- return (ret);
-
- *ndirtyp = ndirty;
-
- R_LOCK(dbenv, dbmp->reginfo);
+retry: MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+ for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
+ dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
+ if (F_ISSET(dbmfp, MP_FLUSH)) {
+ F_CLR(dbmfp, MP_FLUSH);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+ if ((ret = __memp_fclose_int(dbmfp, 0)) != 0)
+ return (ret);
+ goto retry;
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
return (0);
}
@@ -634,15 +603,15 @@ static int
__bhcmp(p1, p2)
const void *p1, *p2;
{
- BH *bhp1, *bhp2;
+ BH_TRACK *bhp1, *bhp2;
- bhp1 = *(BH * const *)p1;
- bhp2 = *(BH * const *)p2;
+ bhp1 = (BH_TRACK *)p1;
+ bhp2 = (BH_TRACK *)p2;
/* Sort by file (shared memory pool offset). */
- if (bhp1->mf_offset < bhp2->mf_offset)
+ if (bhp1->track_off < bhp2->track_off)
return (-1);
- if (bhp1->mf_offset > bhp2->mf_offset)
+ if (bhp1->track_off > bhp2->track_off)
return (1);
/*
@@ -650,9 +619,9 @@ __bhcmp(p1, p2)
* Defend against badly written quicksort code calling the comparison
* function with two identical pointers (e.g., WATCOM C++ (Power++)).
*/
- if (bhp1->pgno < bhp2->pgno)
+ if (bhp1->track_pgno < bhp2->track_pgno)
return (-1);
- if (bhp1->pgno > bhp2->pgno)
+ if (bhp1->track_pgno > bhp2->track_pgno)
return (1);
return (0);
}
diff --git a/bdb/mp/mp_trickle.c b/bdb/mp/mp_trickle.c
index f937805cf40..71077ab60cc 100644
--- a/bdb/mp/mp_trickle.c
+++ b/bdb/mp/mp_trickle.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mp_trickle.c,v 11.12 2000/11/30 00:58:41 ubell Exp $";
+static const char revid[] = "$Id: mp_trickle.c,v 11.24 2002/08/06 06:13:53 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,42 +16,29 @@ static const char revid[] = "$Id: mp_trickle.c,v 11.12 2000/11/30 00:58:41 ubell
#include <stdlib.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "mp.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
-
-static int __memp_trick __P((DB_ENV *, int, int, int *));
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
/*
- * memp_trickle --
+ * __memp_trickle --
* Keep a specified percentage of the buffers clean.
+ *
+ * PUBLIC: int __memp_trickle __P((DB_ENV *, int, int *));
*/
int
-memp_trickle(dbenv, pct, nwrotep)
+__memp_trickle(dbenv, pct, nwrotep)
DB_ENV *dbenv;
int pct, *nwrotep;
{
DB_MPOOL *dbmp;
- MPOOL *mp;
- u_int32_t i;
- int ret;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_trickle(dbenv, pct, nwrotep));
-#endif
+ MPOOL *c_mp, *mp;
+ u_int32_t clean, dirty, i, total, dtmp;
+ int ret, wrote;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->mp_handle, "memp_trickle", DB_INIT_MPOOL);
dbmp = dbenv->mp_handle;
mp = dbmp->reginfo[0].primary;
@@ -62,88 +49,35 @@ memp_trickle(dbenv, pct, nwrotep)
if (pct < 1 || pct > 100)
return (EINVAL);
- R_LOCK(dbenv, dbmp->reginfo);
-
- /* Loop through the caches... */
- for (ret = 0, i = 0; i < mp->nreg; ++i)
- if ((ret = __memp_trick(dbenv, i, pct, nwrotep)) != 0)
- break;
-
- R_UNLOCK(dbenv, dbmp->reginfo);
- return (ret);
-}
-
-/*
- * __memp_trick --
- * Trickle a single cache.
- */
-static int
-__memp_trick(dbenv, ncache, pct, nwrotep)
- DB_ENV *dbenv;
- int ncache, pct, *nwrotep;
-{
- BH *bhp;
- DB_MPOOL *dbmp;
- MPOOL *c_mp;
- MPOOLFILE *mfp;
- db_pgno_t pgno;
- u_long total;
- int ret, wrote;
-
- dbmp = dbenv->mp_handle;
- c_mp = dbmp->reginfo[ncache].primary;
-
/*
- * If there are sufficient clean buffers, or no buffers or no dirty
+ * If there are sufficient clean buffers, no buffers or no dirty
* buffers, we're done.
*
* XXX
- * Using st_page_clean and st_page_dirty is our only choice at the
- * moment, but it's not as correct as we might like in the presence
- * of pools with more than one buffer size, as a free 512-byte buffer
- * isn't the same as a free 8K buffer.
+ * Using hash_page_dirty is our only choice at the moment, but it's not
+ * as correct as we might like in the presence of pools having more
+ * than one page size, as a free 512B buffer isn't the same as a free
+ * 8KB buffer.
+ *
+ * Loop through the caches counting total/dirty buffers.
*/
-loop: total = c_mp->stat.st_page_clean + c_mp->stat.st_page_dirty;
- if (total == 0 || c_mp->stat.st_page_dirty == 0 ||
- (c_mp->stat.st_page_clean * 100) / total >= (u_long)pct)
- return (0);
-
- /* Loop until we write a buffer. */
- for (bhp = SH_TAILQ_FIRST(&c_mp->bhq, __bh);
- bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) {
- if (bhp->ref != 0 ||
- !F_ISSET(bhp, BH_DIRTY) || F_ISSET(bhp, BH_LOCKED))
- continue;
-
- mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
-
- /*
- * We can't write to temporary files -- see the comment in
- * mp_bh.c:__memp_bhwrite().
- */
- if (F_ISSET(mfp, MP_TEMP))
- continue;
+ for (ret = 0, i = dirty = total = 0; i < mp->nreg; ++i) {
+ c_mp = dbmp->reginfo[i].primary;
+ total += c_mp->stat.st_pages;
+ __memp_stat_hash(&dbmp->reginfo[i], c_mp, &dtmp);
+ dirty += dtmp;
+ }
- pgno = bhp->pgno;
- if ((ret = __memp_bhwrite(dbmp, mfp, bhp, NULL, &wrote)) != 0)
- return (ret);
+ clean = total - dirty;
+ if (clean == total || (clean * 100) / total >= (u_long)pct)
+ return (0);
- /*
- * Any process syncing the shared memory buffer pool had better
- * be able to write to any underlying file. Be understanding,
- * but firm, on this point.
- */
- if (!wrote) {
- __db_err(dbenv, "%s: unable to flush page: %lu",
- __memp_fns(dbmp, mfp), (u_long)pgno);
- return (EPERM);
- }
+ if (nwrotep == NULL)
+ nwrotep = &wrote;
+ ret = __memp_sync_int(dbenv, NULL,
+ ((total * pct) / 100) - clean, DB_SYNC_TRICKLE, nwrotep);
- ++c_mp->stat.st_page_trickle;
- if (nwrotep != NULL)
- ++*nwrotep;
- goto loop;
- }
+ mp->stat.st_page_trickle += *nwrotep;
- return (0);
+ return (ret);
}
diff --git a/bdb/mutex/mut_fcntl.c b/bdb/mutex/mut_fcntl.c
index 02f4d4044f8..2fdf9eff7ef 100644
--- a/bdb/mutex/mut_fcntl.c
+++ b/bdb/mutex/mut_fcntl.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mut_fcntl.c,v 11.11 2001/01/11 18:19:53 bostic Exp $";
+static const char revid[] = "$Id: mut_fcntl.c,v 11.21 2002/05/31 19:37:45 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -26,15 +26,26 @@ static const char revid[] = "$Id: mut_fcntl.c,v 11.11 2001/01/11 18:19:53 bostic
* __db_fcntl_mutex_init --
* Initialize a DB mutex structure.
*
- * PUBLIC: int __db_fcntl_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t));
+ * PUBLIC: int __db_fcntl_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
*/
int
__db_fcntl_mutex_init(dbenv, mutexp, offset)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
u_int32_t offset;
{
+ u_int32_t save;
+
+ /*
+ * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+ * mutex allocation code (__db_mutex_alloc/free). Preserve only that
+ * flag. This is safe because even if this flag was never explicitly
+ * set, but happened to be set in memory, it will never be checked or
+ * acted upon.
+ */
+ save = F_ISSET(mutexp, MUTEX_MPOOL);
memset(mutexp, 0, sizeof(*mutexp));
+ F_SET(mutexp, save);
/*
* This is where we decide to ignore locks we don't need to set -- if
@@ -46,7 +57,7 @@ __db_fcntl_mutex_init(dbenv, mutexp, offset)
}
mutexp->off = offset;
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
mutexp->reg_off = INVALID_ROFF;
#endif
F_SET(mutexp, MUTEX_INITED);
@@ -58,18 +69,17 @@ __db_fcntl_mutex_init(dbenv, mutexp, offset)
* __db_fcntl_mutex_lock
* Lock on a mutex, blocking if necessary.
*
- * PUBLIC: int __db_fcntl_mutex_lock __P((DB_ENV *, MUTEX *, DB_FH *));
+ * PUBLIC: int __db_fcntl_mutex_lock __P((DB_ENV *, DB_MUTEX *));
*/
int
-__db_fcntl_mutex_lock(dbenv, mutexp, fhp)
+__db_fcntl_mutex_lock(dbenv, mutexp)
DB_ENV *dbenv;
- MUTEX *mutexp;
- DB_FH *fhp;
+ DB_MUTEX *mutexp;
{
struct flock k_lock;
int locked, ms, waited;
- if (!dbenv->db_mutexlocks)
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
return (0);
/* Initialize the lock. */
@@ -91,18 +101,18 @@ __db_fcntl_mutex_lock(dbenv, mutexp, fhp)
/* Acquire an exclusive kernel lock. */
k_lock.l_type = F_WRLCK;
- if (fcntl(fhp->fd, F_SETLKW, &k_lock))
+ if (fcntl(dbenv->lockfhp->fd, F_SETLKW, &k_lock))
return (__os_get_errno());
/* If the resource is still available, it's ours. */
if (mutexp->pid == 0) {
locked = 1;
- mutexp->pid = (u_int32_t)getpid();
+ __os_id(&mutexp->pid);
}
/* Release the kernel lock. */
k_lock.l_type = F_UNLCK;
- if (fcntl(fhp->fd, F_SETLK, &k_lock))
+ if (fcntl(dbenv->lockfhp->fd, F_SETLK, &k_lock))
return (__os_get_errno());
/*
@@ -129,14 +139,14 @@ __db_fcntl_mutex_lock(dbenv, mutexp, fhp)
* __db_fcntl_mutex_unlock --
* Release a lock.
*
- * PUBLIC: int __db_fcntl_mutex_unlock __P((DB_ENV *, MUTEX *));
+ * PUBLIC: int __db_fcntl_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
*/
int
__db_fcntl_mutex_unlock(dbenv, mutexp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
- if (!dbenv->db_mutexlocks)
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
return (0);
#ifdef DIAGNOSTIC
@@ -160,13 +170,13 @@ __db_fcntl_mutex_unlock(dbenv, mutexp)
/*
* __db_fcntl_mutex_destroy --
- * Destroy a MUTEX.
+ * Destroy a DB_MUTEX.
*
- * PUBLIC: int __db_fcntl_mutex_destroy __P((MUTEX *));
+ * PUBLIC: int __db_fcntl_mutex_destroy __P((DB_MUTEX *));
*/
int
__db_fcntl_mutex_destroy(mutexp)
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
COMPQUIET(mutexp, NULL);
diff --git a/bdb/mutex/mut_pthread.c b/bdb/mutex/mut_pthread.c
index 3de4abcefc5..4a55ce0ca03 100644
--- a/bdb/mutex/mut_pthread.c
+++ b/bdb/mutex/mut_pthread.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mut_pthread.c,v 11.33 2001/01/09 00:56:16 ubell Exp $";
+static const char revid[] = "$Id: mut_pthread.c,v 11.53 2002/08/13 19:56:47 sue Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -36,7 +36,11 @@ static const char revid[] = "$Id: mut_pthread.c,v 11.33 2001/01/09 00:56:16 ubel
#define pthread_mutex_lock _lwp_mutex_lock
#define pthread_mutex_trylock _lwp_mutex_trylock
#define pthread_mutex_unlock _lwp_mutex_unlock
-#define pthread_self _lwp_self
+/*
+ * _lwp_self returns the LWP process ID which isn't a unique per-thread
+ * identifier. Use pthread_self instead, it appears to work even if we
+ * are not a pthreads application.
+ */
#define pthread_mutex_destroy(x) 0
#endif
#ifdef HAVE_MUTEX_UI_THREADS
@@ -53,20 +57,31 @@ static const char revid[] = "$Id: mut_pthread.c,v 11.33 2001/01/09 00:56:16 ubel
/*
* __db_pthread_mutex_init --
- * Initialize a MUTEX.
+ * Initialize a DB_MUTEX.
*
- * PUBLIC: int __db_pthread_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t));
+ * PUBLIC: int __db_pthread_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
*/
int
__db_pthread_mutex_init(dbenv, mutexp, flags)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
u_int32_t flags;
{
+ u_int32_t save;
int ret;
ret = 0;
+
+ /*
+ * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+ * mutex allocation code (__db_mutex_alloc/free). Preserve only that
+ * flag. This is safe because even if this flag was never explicitly
+ * set, but happened to be set in memory, it will never be checked or
+ * acted upon.
+ */
+ save = F_ISSET(mutexp, MUTEX_MPOOL);
memset(mutexp, 0, sizeof(*mutexp));
+ F_SET(mutexp, save);
/*
* If this is a thread lock or the process has told us that there are
@@ -81,7 +96,6 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
F_SET(mutexp, MUTEX_IGNORE);
return (0);
}
- F_SET(mutexp, MUTEX_THREAD);
}
#ifdef HAVE_MUTEX_PTHREADS
@@ -89,18 +103,13 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
pthread_condattr_t condattr, *condattrp = NULL;
pthread_mutexattr_t mutexattr, *mutexattrp = NULL;
- if (!F_ISSET(mutexp, MUTEX_THREAD)) {
- ret = pthread_condattr_init(&condattr);
- if (ret == 0)
- ret = pthread_condattr_setpshared(
- &condattr, PTHREAD_PROCESS_SHARED);
- condattrp = &condattr;
-
- if (ret == 0)
- ret = pthread_mutexattr_init(&mutexattr);
+ if (!LF_ISSET(MUTEX_THREAD)) {
+ ret = pthread_mutexattr_init(&mutexattr);
+#ifndef HAVE_MUTEX_THREAD_ONLY
if (ret == 0)
ret = pthread_mutexattr_setpshared(
&mutexattr, PTHREAD_PROCESS_SHARED);
+#endif
mutexattrp = &mutexattr;
}
@@ -108,14 +117,27 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
ret = pthread_mutex_init(&mutexp->mutex, mutexattrp);
if (mutexattrp != NULL)
pthread_mutexattr_destroy(mutexattrp);
- if (LF_ISSET(MUTEX_SELF_BLOCK)) {
+ if (ret == 0 && LF_ISSET(MUTEX_SELF_BLOCK)) {
+ if (!LF_ISSET(MUTEX_THREAD)) {
+ ret = pthread_condattr_init(&condattr);
+#ifndef HAVE_MUTEX_THREAD_ONLY
+ if (ret == 0) {
+ condattrp = &condattr;
+ ret = pthread_condattr_setpshared(
+ &condattr, PTHREAD_PROCESS_SHARED);
+ }
+#endif
+ }
+
if (ret == 0)
ret = pthread_cond_init(&mutexp->cond, condattrp);
F_SET(mutexp, MUTEX_SELF_BLOCK);
if (condattrp != NULL)
- pthread_condattr_destroy(condattrp);
- }}
+ (void)pthread_condattr_destroy(condattrp);
+ }
+
+ }
#endif
#ifdef HAVE_MUTEX_SOLARIS_LWP
/*
@@ -126,7 +148,7 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
* initialization values doesn't have surrounding braces. There's not
* much we can do.
*/
- if (F_ISSET(mutexp, MUTEX_THREAD)) {
+ if (LF_ISSET(MUTEX_THREAD)) {
static lwp_mutex_t mi = DEFAULTMUTEX;
mutexp->mutex = mi;
@@ -136,7 +158,7 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
mutexp->mutex = mi;
}
if (LF_ISSET(MUTEX_SELF_BLOCK)) {
- if (F_ISSET(mutexp, MUTEX_THREAD)) {
+ if (LF_ISSET(MUTEX_THREAD)) {
static lwp_cond_t ci = DEFAULTCV;
mutexp->cond = ci;
@@ -152,7 +174,7 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
{
int type;
- type = F_ISSET(mutexp, MUTEX_THREAD) ? USYNC_THREAD : USYNC_PROCESS;
+ type = LF_ISSET(MUTEX_THREAD) ? USYNC_THREAD : USYNC_PROCESS;
ret = mutex_init(&mutexp->mutex, type, NULL);
if (ret == 0 && LF_ISSET(MUTEX_SELF_BLOCK)) {
@@ -162,12 +184,15 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
}}
#endif
- mutexp->spins = __os_spin();
-#ifdef MUTEX_SYSTEM_RESOURCES
+ mutexp->spins = __os_spin(dbenv);
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
mutexp->reg_off = INVALID_ROFF;
#endif
if (ret == 0)
F_SET(mutexp, MUTEX_INITED);
+ else
+ __db_err(dbenv,
+ "unable to initialize mutex: %s", strerror(ret));
return (ret);
}
@@ -176,17 +201,17 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
* __db_pthread_mutex_lock
* Lock on a mutex, logically blocking if necessary.
*
- * PUBLIC: int __db_pthread_mutex_lock __P((DB_ENV *, MUTEX *));
+ * PUBLIC: int __db_pthread_mutex_lock __P((DB_ENV *, DB_MUTEX *));
*/
int
__db_pthread_mutex_lock(dbenv, mutexp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
u_int32_t nspins;
int i, ret, waited;
- if (!dbenv->db_mutexlocks || F_ISSET(mutexp, MUTEX_IGNORE))
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
/* Attempt to acquire the resource for N spins. */
@@ -195,7 +220,7 @@ __db_pthread_mutex_lock(dbenv, mutexp)
break;
if (nspins == 0 && (ret = pthread_mutex_lock(&mutexp->mutex)) != 0)
- return (ret);
+ goto err;
if (F_ISSET(mutexp, MUTEX_SELF_BLOCK)) {
for (waited = 0; mutexp->locked != 0; waited = 1) {
@@ -210,8 +235,14 @@ __db_pthread_mutex_lock(dbenv, mutexp)
* call, and Solaris delivers the signal to the wrong
* LWP.
*/
- if (ret != 0 && ret != ETIME && ret != ETIMEDOUT)
+ if (ret != 0 && ret != EINTR &&
+#ifdef ETIME
+ ret != ETIME &&
+#endif
+ ret != ETIMEDOUT) {
+ (void)pthread_mutex_unlock(&mutexp->mutex);
return (ret);
+ }
}
if (waited)
@@ -238,11 +269,14 @@ __db_pthread_mutex_lock(dbenv, mutexp)
ret = pthread_mutex_unlock(&mutexp->mutex);
} while (ret == EFAULT && --i > 0);
if (ret != 0)
- return (ret);
+ goto err;
} else {
if (nspins == mutexp->spins)
++mutexp->mutex_set_nowait;
- else
+ else if (nspins > 0) {
+ ++mutexp->mutex_set_spin;
+ mutexp->mutex_set_spins += mutexp->spins - nspins;
+ } else
++mutexp->mutex_set_wait;
#ifdef DIAGNOSTIC
if (mutexp->locked) {
@@ -257,22 +291,25 @@ __db_pthread_mutex_lock(dbenv, mutexp)
#endif
}
return (0);
+
+err: __db_err(dbenv, "unable to lock mutex: %s", strerror(ret));
+ return (ret);
}
/*
* __db_pthread_mutex_unlock --
* Release a lock.
*
- * PUBLIC: int __db_pthread_mutex_unlock __P((DB_ENV *, MUTEX *));
+ * PUBLIC: int __db_pthread_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
*/
int
__db_pthread_mutex_unlock(dbenv, mutexp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
int i, ret;
- if (!dbenv->db_mutexlocks || F_ISSET(mutexp, MUTEX_IGNORE))
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
#ifdef DIAGNOSTIC
@@ -282,47 +319,43 @@ __db_pthread_mutex_unlock(dbenv, mutexp)
if (F_ISSET(mutexp, MUTEX_SELF_BLOCK)) {
if ((ret = pthread_mutex_lock(&mutexp->mutex)) != 0)
- return (ret);
+ goto err;
mutexp->locked = 0;
if ((ret = pthread_cond_signal(&mutexp->cond)) != 0)
return (ret);
- /* See comment above; workaround for [#2471]. */
- i = PTHREAD_UNLOCK_ATTEMPTS;
- do {
- ret = pthread_mutex_unlock(&mutexp->mutex);
- } while (ret == EFAULT && --i > 0);
- if (ret != 0)
- return (ret);
- } else {
+ } else
mutexp->locked = 0;
- /* See comment above; workaround for [#2471]. */
- i = PTHREAD_UNLOCK_ATTEMPTS;
- do {
- ret = pthread_mutex_unlock(&mutexp->mutex);
- } while (ret == EFAULT && --i > 0);
- if (ret != 0)
- return (ret);
- }
+ /* See comment above; workaround for [#2471]. */
+ i = PTHREAD_UNLOCK_ATTEMPTS;
+ do {
+ ret = pthread_mutex_unlock(&mutexp->mutex);
+ } while (ret == EFAULT && --i > 0);
+ return (ret);
- return (0);
+err: __db_err(dbenv, "unable to unlock mutex: %s", strerror(ret));
+ return (ret);
}
/*
* __db_pthread_mutex_destroy --
- * Destroy a MUTEX.
+ * Destroy a DB_MUTEX.
*
- * PUBLIC: int __db_pthread_mutex_destroy __P((MUTEX *));
+ * PUBLIC: int __db_pthread_mutex_destroy __P((DB_MUTEX *));
*/
int
__db_pthread_mutex_destroy(mutexp)
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
+ int ret;
+
if (F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
- return (pthread_mutex_destroy(&mutexp->mutex));
+ if ((ret = pthread_mutex_destroy(&mutexp->mutex)) != 0)
+ __db_err(NULL, "unable to destroy mutex: %s", strerror(ret));
+ return (ret);
}
diff --git a/bdb/mutex/mut_tas.c b/bdb/mutex/mut_tas.c
index 4b0db4bdf05..c24e09473ca 100644
--- a/bdb/mutex/mut_tas.c
+++ b/bdb/mutex/mut_tas.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mut_tas.c,v 11.18 2000/11/30 00:58:41 ubell Exp $";
+static const char revid[] = "$Id: mut_tas.c,v 11.32 2002/05/07 18:42:21 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -25,32 +25,33 @@ static const char revid[] = "$Id: mut_tas.c,v 11.18 2000/11/30 00:58:41 ubell Ex
#define LOAD_ACTUAL_MUTEX_CODE
#include "db_int.h"
-#ifdef DIAGNOSTIC
-#undef MSG1
-#define MSG1 "mutex_lock: ERROR: lock currently in use: pid: %lu.\n"
-#undef MSG2
-#define MSG2 "mutex_unlock: ERROR: lock already unlocked\n"
-#ifndef STDERR_FILENO
-#define STDERR_FILENO 2
-#endif
-#endif
-
/*
* __db_tas_mutex_init --
- * Initialize a MUTEX.
+ * Initialize a DB_MUTEX.
*
- * PUBLIC: int __db_tas_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t));
+ * PUBLIC: int __db_tas_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
*/
int
__db_tas_mutex_init(dbenv, mutexp, flags)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
u_int32_t flags;
{
+ u_int32_t save;
+
/* Check alignment. */
DB_ASSERT(((db_alignp_t)mutexp & (MUTEX_ALIGN - 1)) == 0);
+ /*
+ * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+ * mutex allocation code (__db_mutex_alloc/free). Preserve only that
+ * flag. This is safe because even if this flag was never explicitly
+ * set, but happened to be set in memory, it will never be checked or
+ * acted upon.
+ */
+ save = F_ISSET(mutexp, MUTEX_MPOOL);
memset(mutexp, 0, sizeof(*mutexp));
+ F_SET(mutexp, save);
/*
* If this is a thread lock or the process has told us that there are
@@ -65,15 +66,14 @@ __db_tas_mutex_init(dbenv, mutexp, flags)
F_SET(mutexp, MUTEX_IGNORE);
return (0);
}
- F_SET(mutexp, MUTEX_THREAD);
}
/* Initialize the lock. */
if (MUTEX_INIT(&mutexp->tas))
return (__os_get_errno());
- mutexp->spins = __os_spin();
-#ifdef MUTEX_SYSTEM_RESOURCES
+ mutexp->spins = __os_spin(dbenv);
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
mutexp->reg_off = INVALID_ROFF;
#endif
F_SET(mutexp, MUTEX_INITED);
@@ -85,17 +85,17 @@ __db_tas_mutex_init(dbenv, mutexp, flags)
* __db_tas_mutex_lock
* Lock on a mutex, logically blocking if necessary.
*
- * PUBLIC: int __db_tas_mutex_lock __P((DB_ENV *, MUTEX *));
+ * PUBLIC: int __db_tas_mutex_lock __P((DB_ENV *, DB_MUTEX *));
*/
int
__db_tas_mutex_lock(dbenv, mutexp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
u_long ms;
int nspins;
- if (!dbenv->db_mutexlocks || F_ISSET(mutexp, MUTEX_IGNORE))
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
ms = 1;
@@ -119,7 +119,7 @@ relock:
* happened to initialize or use one of them.)
*/
if (mutexp->locked != 0) {
- mutexp->locked = (u_int32_t)getpid();
+ __os_id(&mutexp->locked);
goto relock;
}
/*
@@ -129,15 +129,13 @@ relock:
*/
#endif
#ifdef DIAGNOSTIC
- if (mutexp->locked != 0) {
- char msgbuf[128];
- (void)snprintf(msgbuf,
- sizeof(msgbuf), MSG1, (u_long)mutexp->locked);
- (void)write(STDERR_FILENO, msgbuf, strlen(msgbuf));
- }
+ if (mutexp->locked != 0)
+ __db_err(dbenv,
+ "__db_tas_mutex_lock: ERROR: lock currently in use: ID: %lu",
+ (u_long)mutexp->locked);
#endif
#if defined(DIAGNOSTIC) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
- mutexp->locked = (u_int32_t)getpid();
+ __os_id(&mutexp->locked);
#endif
if (ms == 1)
++mutexp->mutex_set_nowait;
@@ -158,19 +156,20 @@ relock:
* __db_tas_mutex_unlock --
* Release a lock.
*
- * PUBLIC: int __db_tas_mutex_unlock __P((DB_ENV *, MUTEX *));
+ * PUBLIC: int __db_tas_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
*/
int
__db_tas_mutex_unlock(dbenv, mutexp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
- if (!dbenv->db_mutexlocks || F_ISSET(mutexp, MUTEX_IGNORE))
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
#ifdef DIAGNOSTIC
if (!mutexp->locked)
- (void)write(STDERR_FILENO, MSG2, sizeof(MSG2) - 1);
+ __db_err(dbenv,
+ "__db_tas_mutex_unlock: ERROR: lock already unlocked");
#endif
#if defined(DIAGNOSTIC) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
mutexp->locked = 0;
@@ -183,13 +182,13 @@ __db_tas_mutex_unlock(dbenv, mutexp)
/*
* __db_tas_mutex_destroy --
- * Destroy a MUTEX.
+ * Destroy a DB_MUTEX.
*
- * PUBLIC: int __db_tas_mutex_destroy __P((MUTEX *));
+ * PUBLIC: int __db_tas_mutex_destroy __P((DB_MUTEX *));
*/
int
__db_tas_mutex_destroy(mutexp)
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
if (F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
diff --git a/bdb/mutex/mut_win32.c b/bdb/mutex/mut_win32.c
new file mode 100644
index 00000000000..49eb20a6ecf
--- /dev/null
+++ b/bdb/mutex/mut_win32.c
@@ -0,0 +1,257 @@
+/*
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: mut_win32.c,v 1.8 2002/09/10 02:37:25 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+#endif
+
+/*
+ * This is where we load in the actual test-and-set mutex code.
+ */
+#define LOAD_ACTUAL_MUTEX_CODE
+#include "db_int.h"
+
+/* We don't want to run this code even in "ordinary" diagnostic mode. */
+#undef MUTEX_DIAG
+
+#define GET_HANDLE(mutexp, event) do { \
+ char idbuf[13]; \
+ \
+ if (F_ISSET(mutexp, MUTEX_THREAD)) { \
+ event = mutexp->event; \
+ return (0); \
+ } \
+ \
+ snprintf(idbuf, sizeof idbuf, "db.m%08x", mutexp->id); \
+ event = CreateEvent(NULL, FALSE, FALSE, idbuf); \
+ if (event == NULL) \
+ return (__os_win32_errno()); \
+} while (0)
+
+#define RELEASE_HANDLE(mutexp, event) \
+ if (!F_ISSET(mutexp, MUTEX_THREAD) && event != NULL) { \
+ CloseHandle(event); \
+ event = NULL; \
+ }
+
+/*
+ * __db_win32_mutex_init --
+ * Initialize a DB_MUTEX.
+ *
+ * PUBLIC: int __db_win32_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
+ */
+int
+__db_win32_mutex_init(dbenv, mutexp, flags)
+ DB_ENV *dbenv;
+ DB_MUTEX *mutexp;
+ u_int32_t flags;
+{
+ u_int32_t save;
+
+ /*
+ * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+ * mutex allocation code (__db_mutex_alloc/free). Preserve only that
+ * flag. This is safe because even if this flag was never explicitly
+ * set, but happened to be set in memory, it will never be checked or
+ * acted upon.
+ */
+ save = F_ISSET(mutexp, MUTEX_MPOOL);
+ memset(mutexp, 0, sizeof(*mutexp));
+ F_SET(mutexp, save);
+
+ /*
+ * If this is a thread lock or the process has told us that there are
+ * no other processes in the environment, use thread-only locks, they
+ * are faster in some cases.
+ *
+ * This is where we decide to ignore locks we don't need to set -- if
+ * the application isn't threaded, there aren't any threads to block.
+ */
+ if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+ if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
+ F_SET(mutexp, MUTEX_IGNORE);
+ return (0);
+ }
+ F_SET(mutexp, MUTEX_THREAD);
+ mutexp->event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (mutexp->event == NULL)
+ return (__os_win32_errno());
+ } else
+ mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
+
+ mutexp->spins = __os_spin(dbenv);
+ F_SET(mutexp, MUTEX_INITED);
+
+ return (0);
+}
+
+/*
+ * __db_win32_mutex_lock
+ * Lock on a mutex, logically blocking if necessary.
+ *
+ * PUBLIC: int __db_win32_mutex_lock __P((DB_ENV *, DB_MUTEX *));
+ */
+int
+__db_win32_mutex_lock(dbenv, mutexp)
+ DB_ENV *dbenv;
+ DB_MUTEX *mutexp;
+{
+ HANDLE event;
+ int ret, ms, nspins;
+#ifdef MUTEX_DIAG
+ LARGE_INTEGER now;
+#endif
+
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
+ return (0);
+
+ event = NULL;
+ ms = 50;
+ ret = 0;
+
+loop: /* Attempt to acquire the resource for N spins. */
+ for (nspins = mutexp->spins; nspins > 0; --nspins) {
+ if (!MUTEX_SET(&mutexp->tas))
+ continue;
+
+#ifdef DIAGNOSTIC
+ if (mutexp->locked)
+ __db_err(dbenv,
+ "__db_win32_mutex_lock: mutex double-locked!");
+
+ __os_id(&mutexp->locked);
+#endif
+
+ if (event == NULL)
+ ++mutexp->mutex_set_nowait;
+ else {
+ ++mutexp->mutex_set_wait;
+ RELEASE_HANDLE(mutexp, event);
+ InterlockedDecrement(&mutexp->nwaiters);
+#ifdef MUTEX_DIAG
+ if (ret != WAIT_OBJECT_0) {
+ QueryPerformanceCounter(&now);
+ printf("[%I64d]: Lost signal on mutex %p, "
+ "id %d, ms %d\n",
+ now.QuadPart, mutexp, mutexp->id, ms);
+ }
+#endif
+ }
+
+ return (0);
+ }
+
+ /*
+ * Yield the processor; wait 50 ms initially, up to 1 second. This
+ * loop is needed to work around a race where the signal from the
+ * unlocking thread gets lost. We start at 50 ms because it's unlikely
+ * to happen often and we want to avoid wasting CPU.
+ */
+ if (event == NULL) {
+#ifdef MUTEX_DIAG
+ QueryPerformanceCounter(&now);
+ printf("[%I64d]: Waiting on mutex %p, id %d\n",
+ now.QuadPart, mutexp, mutexp->id);
+#endif
+ InterlockedIncrement(&mutexp->nwaiters);
+ GET_HANDLE(mutexp, event);
+ }
+ if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED)
+ return (__os_win32_errno());
+ if ((ms <<= 1) > MS_PER_SEC)
+ ms = MS_PER_SEC;
+
+ goto loop;
+}
+
+/*
+ * __db_win32_mutex_unlock --
+ * Release a lock.
+ *
+ * PUBLIC: int __db_win32_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
+ */
+int
+__db_win32_mutex_unlock(dbenv, mutexp)
+ DB_ENV *dbenv;
+ DB_MUTEX *mutexp;
+{
+ int ret;
+ HANDLE event;
+#ifdef MUTEX_DIAG
+ LARGE_INTEGER now;
+#endif
+
+ if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
+ return (0);
+
+#ifdef DIAGNOSTIC
+ if (!mutexp->tas || !mutexp->locked)
+ __db_err(dbenv,
+ "__db_win32_mutex_unlock: ERROR: lock already unlocked");
+
+ mutexp->locked = 0;
+#endif
+ MUTEX_UNSET(&mutexp->tas);
+
+ ret = 0;
+
+ if (mutexp->nwaiters > 0) {
+ GET_HANDLE(mutexp, event);
+
+#ifdef MUTEX_DIAG
+ QueryPerformanceCounter(&now);
+ printf("[%I64d]: Signalling mutex %p, id %d\n",
+ now.QuadPart, mutexp, mutexp->id);
+#endif
+ if (!PulseEvent(event))
+ ret = __os_win32_errno();
+
+ RELEASE_HANDLE(mutexp, event);
+ }
+
+#ifdef DIAGNOSTIC
+ if (ret != 0)
+ __db_err(dbenv,
+ "__db_win32_mutex_unlock: ERROR: unlock failed");
+#endif
+
+ return (ret);
+}
+
+/*
+ * __db_win32_mutex_destroy --
+ * Destroy a DB_MUTEX.
+ *
+ * PUBLIC: int __db_win32_mutex_destroy __P((DB_MUTEX *));
+ */
+int
+__db_win32_mutex_destroy(mutexp)
+ DB_MUTEX *mutexp;
+{
+ int ret;
+
+ if (F_ISSET(mutexp, MUTEX_IGNORE) || !F_ISSET(mutexp, MUTEX_THREAD))
+ return (0);
+
+ ret = 0;
+ if (mutexp->event != NULL) {
+ if (!CloseHandle(mutexp->event))
+ ret = __os_win32_errno();
+ mutexp->event = NULL;
+ }
+
+ return (ret);
+}
diff --git a/bdb/mutex/mutex.c b/bdb/mutex/mutex.c
index acc4af9bfcc..5418764a889 100644
--- a/bdb/mutex/mutex.c
+++ b/bdb/mutex/mutex.c
@@ -1,58 +1,152 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: mutex.c,v 11.14 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: mutex.c,v 11.37 2002/05/31 19:37:46 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <string.h>
#endif
#include "db_int.h"
+#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES)
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/txn.h"
+#endif
+
+static int __db_mutex_alloc_int __P((DB_ENV *, REGINFO *, DB_MUTEX **));
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+static REGMAINT * __db_mutex_maint __P((DB_ENV *, REGINFO *));
+#endif
+
/*
- * __db_mutex_alloc --
- * Allocate and initialize a mutex.
+ * __db_mutex_setup --
+ * External interface to allocate, and/or initialize, record
+ * mutexes.
*
- * PUBLIC: int __db_mutex_alloc __P((DB_ENV *, REGINFO *, MUTEX **));
+ * PUBLIC: int __db_mutex_setup __P((DB_ENV *, REGINFO *, void *, u_int32_t));
*/
int
-__db_mutex_alloc(dbenv, infop, storep)
+__db_mutex_setup(dbenv, infop, ptr, flags)
DB_ENV *dbenv;
REGINFO *infop;
- MUTEX **storep;
+ void *ptr;
+ u_int32_t flags;
{
+ DB_MUTEX *mutex;
+ REGMAINT *maint;
+ u_int32_t iflags, offset;
int ret;
+ ret = 0;
/*
- * If the architecture supports mutexes in heap memory, use that
- * memory. If it doesn't, we have to allocate space in a region.
- *
- * XXX
- * There's a nasty starvation issue here for applications running
- * on systems that don't support mutexes in heap memory. If the
- * normal state of the entire region is dirty (e.g., mpool), then
- * we can run out of memory to allocate for mutexes when new files
- * are opened in the pool. We're not trying to fix this for now,
- * because the only known system where we can see this failure at
- * the moment is HP-UX 10.XX.
+ * If they indicated the region is not locked, then lock it.
+ * This is only needed when we have unusual mutex resources.
+ * (I.e. MUTEX_NO_MALLOC_LOCKS or HAVE_MUTEX_SYSTEM_RESOURCES)
*/
-#ifdef MUTEX_NO_MALLOC_LOCKS
- R_LOCK(dbenv, infop);
- ret = __db_shalloc(infop->addr, sizeof(MUTEX), MUTEX_ALIGN, storep);
- R_UNLOCK(dbenv, infop);
+#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES)
+ if (!LF_ISSET(MUTEX_NO_RLOCK))
+ R_LOCK(dbenv, infop);
+#endif
+ /*
+ * Allocate the mutex if they asked us to.
+ */
+ mutex = NULL;
+ if (LF_ISSET(MUTEX_ALLOC)) {
+ if ((ret = __db_mutex_alloc_int(dbenv, infop, ptr)) != 0)
+ goto err;
+ mutex = *(DB_MUTEX **)ptr;
+ } else
+ mutex = (DB_MUTEX *)ptr;
+
+ /*
+ * Set up to initialize the mutex.
+ */
+ iflags = LF_ISSET(MUTEX_THREAD | MUTEX_SELF_BLOCK);
+ switch (infop->type) {
+ case REGION_TYPE_LOCK:
+ offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_LOCK;
+ break;
+ case REGION_TYPE_MPOOL:
+ offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_MPOOL;
+ break;
+ default:
+ offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_GEN;
+ break;
+ }
+ maint = NULL;
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ if (!LF_ISSET(MUTEX_NO_RECORD))
+ maint = (REGMAINT *)__db_mutex_maint(dbenv, infop);
+#endif
+
+ ret = __db_mutex_init(dbenv, mutex, offset, iflags, infop, maint);
+err:
+#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES)
+ if (!LF_ISSET(MUTEX_NO_RLOCK))
+ R_UNLOCK(dbenv, infop);
+#endif
+ /*
+ * If we allocated the mutex but had an error on init'ing,
+ * then we must free it before returning.
+ * !!!
+ * Free must be done after releasing region lock.
+ */
+ if (ret != 0 && LF_ISSET(MUTEX_ALLOC) && mutex != NULL) {
+ __db_mutex_free(dbenv, infop, mutex);
+ *(DB_MUTEX **)ptr = NULL;
+ }
+ return (ret);
+}
+
+/*
+ * __db_mutex_alloc_int --
+ * Allocate and initialize a mutex.
+ */
+static int
+__db_mutex_alloc_int(dbenv, infop, storep)
+ DB_ENV *dbenv;
+ REGINFO *infop;
+ DB_MUTEX **storep;
+{
+ int ret;
+
+ /*
+ * If the architecture supports mutexes in heap memory, use heap memory.
+ * If it doesn't, we have to allocate space in a region. If allocation
+ * in the region fails, fallback to allocating from the mpool region,
+ * because it's big, it almost always exists and if it's entirely dirty,
+ * we can free buffers until memory is available.
+ */
+#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES)
+ ret = __db_shalloc(infop->addr, sizeof(DB_MUTEX), MUTEX_ALIGN, storep);
+
+ if (ret == ENOMEM && MPOOL_ON(dbenv)) {
+ DB_MPOOL *dbmp;
+
+ dbmp = dbenv->mp_handle;
+ if ((ret = __memp_alloc(dbmp,
+ dbmp->reginfo, NULL, sizeof(DB_MUTEX), NULL, storep)) == 0)
+ (*storep)->flags = MUTEX_MPOOL;
+ } else
+ (*storep)->flags = 0;
#else
COMPQUIET(dbenv, NULL);
COMPQUIET(infop, NULL);
- ret = __os_calloc(dbenv, 1, sizeof(MUTEX), storep);
+ ret = __os_calloc(dbenv, 1, sizeof(DB_MUTEX), storep);
#endif
if (ret != 0)
__db_err(dbenv, "Unable to allocate memory for mutex");
@@ -63,41 +157,47 @@ __db_mutex_alloc(dbenv, infop, storep)
* __db_mutex_free --
* Free a mutex.
*
- * PUBLIC: void __db_mutex_free __P((DB_ENV *, REGINFO *, MUTEX *));
+ * PUBLIC: void __db_mutex_free __P((DB_ENV *, REGINFO *, DB_MUTEX *));
*/
void
__db_mutex_free(dbenv, infop, mutexp)
DB_ENV *dbenv;
REGINFO *infop;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
{
+#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES)
+ R_LOCK(dbenv, infop);
+#if defined(HAVE_MUTEX_SYSTEM_RESOURCES)
if (F_ISSET(mutexp, MUTEX_INITED))
- __db_mutex_destroy(mutexp);
+ __db_shlocks_clear(mutexp, infop, NULL);
+#endif
+ if (F_ISSET(mutexp, MUTEX_MPOOL)) {
+ DB_MPOOL *dbmp;
-#ifdef MUTEX_NO_MALLOC_LOCKS
- R_LOCK(dbenv, infop);
- __db_shalloc_free(infop->addr, mutexp);
+ dbmp = dbenv->mp_handle;
+ R_LOCK(dbenv, dbmp->reginfo);
+ __db_shalloc_free(dbmp->reginfo[0].addr, mutexp);
+ R_UNLOCK(dbenv, dbmp->reginfo);
+ } else
+ __db_shalloc_free(infop->addr, mutexp);
R_UNLOCK(dbenv, infop);
#else
COMPQUIET(dbenv, NULL);
COMPQUIET(infop, NULL);
- __os_free(mutexp, sizeof(*mutexp));
+ __os_free(dbenv, mutexp);
#endif
}
-#ifdef MUTEX_SYSTEM_RESOURCES
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
/*
* __db_shreg_locks_record --
* Record an entry in the shared locks area.
* Region lock must be held in caller.
- *
- * PUBLIC: int __db_shreg_locks_record __P((DB_ENV *, MUTEX *, REGINFO *,
- * PUBLIC: REGMAINT *));
*/
-int
+static int
__db_shreg_locks_record(dbenv, mutexp, infop, rp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
REGINFO *infop;
REGMAINT *rp;
{
@@ -110,7 +210,7 @@ __db_shreg_locks_record(dbenv, mutexp, infop, rp)
i = (roff_t *)R_ADDR(infop, rp->regmutex_hint) - &rp->regmutexes[0];
if (rp->regmutexes[i] != INVALID_ROFF) {
/*
- * Our hint failed, search for a open slot.
+ * Our hint failed, search for an open slot.
*/
rp->stat.st_hint_miss++;
for (i = 0; i < rp->reglocks; i++)
@@ -140,29 +240,33 @@ __db_shreg_locks_record(dbenv, mutexp, infop, rp)
/*
* __db_shreg_locks_clear --
* Erase an entry in the shared locks area.
- * Region lock must be held in caller.
*
- * PUBLIC: void __db_shreg_locks_clear __P((MUTEX *, REGINFO *, REGMAINT *));
+ * PUBLIC: void __db_shreg_locks_clear __P((DB_MUTEX *, REGINFO *, REGMAINT *));
*/
void
__db_shreg_locks_clear(mutexp, infop, rp)
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
REGINFO *infop;
REGMAINT *rp;
{
+ /*
+ * !!!
+ * Assumes the caller's region lock is held.
+ */
if (!F_ISSET(mutexp, MUTEX_INITED))
return;
/*
- * This function is generally only called on a forcible
- * remove of an environment. We recorded our index in
- * the mutex. Find it and clear it.
+ * This function is generally only called on a forcible remove of an
+ * environment. We recorded our index in the mutex, find and clear it.
*/
DB_ASSERT(mutexp->reg_off != INVALID_ROFF);
DB_ASSERT(*(roff_t *)R_ADDR(infop, mutexp->reg_off) == \
R_OFFSET(infop, mutexp));
*(roff_t *)R_ADDR(infop, mutexp->reg_off) = 0;
- rp->regmutex_hint = mutexp->reg_off;
- rp->stat.st_clears++;
+ if (rp != NULL) {
+ rp->regmutex_hint = mutexp->reg_off;
+ rp->stat.st_clears++;
+ }
mutexp->reg_off = INVALID_ROFF;
__db_mutex_destroy(mutexp);
}
@@ -186,7 +290,7 @@ __db_shreg_locks_destroy(infop, rp)
for (i = 0; i < rp->reglocks; i++)
if (rp->regmutexes[i] != 0) {
rp->stat.st_destroys++;
- __db_mutex_destroy((MUTEX *)R_ADDR(infop,
+ __db_mutex_destroy((DB_MUTEX *)R_ADDR(infop,
rp->regmutexes[i]));
}
}
@@ -195,13 +299,13 @@ __db_shreg_locks_destroy(infop, rp)
* __db_shreg_mutex_init --
* Initialize a shared memory mutex.
*
- * PUBLIC: int __db_shreg_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t,
+ * PUBLIC: int __db_shreg_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t,
* PUBLIC: u_int32_t, REGINFO *, REGMAINT *));
*/
int
__db_shreg_mutex_init(dbenv, mutexp, offset, flags, infop, rp)
DB_ENV *dbenv;
- MUTEX *mutexp;
+ DB_MUTEX *mutexp;
u_int32_t offset;
u_int32_t flags;
REGINFO *infop;
@@ -209,18 +313,23 @@ __db_shreg_mutex_init(dbenv, mutexp, offset, flags, infop, rp)
{
int ret;
- if ((ret = __db_mutex_init(dbenv, mutexp, offset, flags)) != 0)
+ if ((ret = __db_mutex_init_int(dbenv, mutexp, offset, flags)) != 0)
+ return (ret);
+ /*
+ * Some mutexes cannot be recorded, but we want one interface.
+ * So, if we have no REGMAINT, then just return.
+ */
+ if (rp == NULL)
return (ret);
/*
* !!!
- * Since __db_mutex_init is a macro, we may not be
+ * Since __db_mutex_init_int is a macro, we may not be
* using the 'offset' as it is only used for one type
* of mutex. We COMPQUIET it here, after the call above.
*/
COMPQUIET(offset, 0);
+ ret = __db_shreg_locks_record(dbenv, mutexp, infop, rp);
- if (!F_ISSET(mutexp, MUTEX_THREAD))
- ret = __db_shreg_locks_record(dbenv, mutexp, infop, rp);
/*
* If we couldn't record it and we are returning an error,
* we need to destroy the mutex we just created.
@@ -244,10 +353,43 @@ __db_shreg_maintinit(infop, addr, size)
size_t size;
{
REGMAINT *rp;
+ u_int32_t i;
rp = (REGMAINT *)addr;
memset(addr, 0, sizeof(REGMAINT));
rp->reglocks = size / sizeof(roff_t);
rp->regmutex_hint = R_OFFSET(infop, &rp->regmutexes[0]);
+ for (i = 0; i < rp->reglocks; i++)
+ rp->regmutexes[i] = INVALID_ROFF;
+}
+
+static REGMAINT *
+__db_mutex_maint(dbenv, infop)
+ DB_ENV *dbenv;
+ REGINFO *infop;
+{
+ roff_t moff;
+
+ switch (infop->type) {
+ case REGION_TYPE_LOCK:
+ moff = ((DB_LOCKREGION *)R_ADDR(infop,
+ infop->rp->primary))->maint_off;
+ break;
+ case REGION_TYPE_LOG:
+ moff = ((LOG *)R_ADDR(infop, infop->rp->primary))->maint_off;
+ break;
+ case REGION_TYPE_MPOOL:
+ moff = ((MPOOL *)R_ADDR(infop, infop->rp->primary))->maint_off;
+ break;
+ case REGION_TYPE_TXN:
+ moff = ((DB_TXNREGION *)R_ADDR(infop,
+ infop->rp->primary))->maint_off;
+ break;
+ default:
+ __db_err(dbenv,
+ "Attempting to record mutex in a region not set up to do so");
+ return (NULL);
+ }
+ return ((REGMAINT *)R_ADDR(infop, moff));
}
-#endif /* MUTEX_SYSTEM_RESOURCES */
+#endif /* HAVE_MUTEX_SYSTEM_RESOURCES */
diff --git a/bdb/mutex/tm.c b/bdb/mutex/tm.c
new file mode 100644
index 00000000000..4af1b1907a8
--- /dev/null
+++ b/bdb/mutex/tm.c
@@ -0,0 +1,627 @@
+/*
+ * Standalone mutex tester for Berkeley DB mutexes.
+ */
+#include "db_config.h"
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+#include <pthread.h>
+#endif
+
+#include "db_int.h"
+
+void exec_proc();
+void tm_file_init();
+void map_file();
+void run_proc();
+void *run_thread();
+void *run_thread_wake();
+void tm_mutex_destroy();
+void tm_mutex_init();
+void tm_mutex_stats();
+void unmap_file();
+
+#define MUTEX_WAKEME 0x80 /* Wake-me flag. */
+
+DB_ENV dbenv; /* Fake out DB. */
+size_t len; /* Backing file size. */
+int align; /* Mutex alignment in file. */
+int quit; /* End-of-test flag. */
+char *file = "mutex.file"; /* Backing file. */
+
+int maxlocks = 20; /* -l: Backing locks. */
+int nlocks = 10000; /* -n: Locks per processes. */
+int nprocs = 20; /* -p: Processes. */
+int child; /* -s: Slave. */
+int nthreads = 1; /* -t: Threads. */
+int verbose; /* -v: Verbosity. */
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern int optind;
+ extern char *optarg;
+ pid_t pid;
+ int ch, eval, i, status;
+ char *tmpath;
+
+ tmpath = argv[0];
+ while ((ch = getopt(argc, argv, "l:n:p:st:v")) != EOF)
+ switch(ch) {
+ case 'l':
+ maxlocks = atoi(optarg);
+ break;
+ case 'n':
+ nlocks = atoi(optarg);
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ break;
+ case 's':
+ child = 1;
+ break;
+ case 't':
+ nthreads = atoi(optarg);
+#if !defined(HAVE_MUTEX_PTHREADS) && !defined(BUILD_PTHREADS_ANYWAY)
+ if (nthreads != 1) {
+ (void)fprintf(stderr,
+ "tm: pthreads not available or not compiled for this platform.\n");
+ return (EXIT_FAILURE);
+ }
+#endif
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ (void)fprintf(stderr,
+ "usage: tm [-v] [-l maxlocks] [-n locks] [-p procs] [-t threads]\n");
+ return (EXIT_FAILURE);
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * The file layout:
+ * DB_MUTEX[1] per-thread mutex array lock
+ * DB_MUTEX[nthreads] per-thread mutex array
+ * DB_MUTEX[maxlocks] per-lock mutex array
+ * u_long[maxlocks][2] per-lock ID array
+ */
+ align = ALIGN(sizeof(DB_MUTEX) * 2, MUTEX_ALIGN);
+ len =
+ align * (1 + nthreads + maxlocks) + sizeof(u_long) * maxlocks * 2;
+ printf(
+ "mutex alignment %d, structure alignment %d, backing file %lu bytes\n",
+ MUTEX_ALIGN, align, (u_long)len);
+
+ if (child) {
+ run_proc();
+ return (EXIT_SUCCESS);
+ }
+
+ tm_file_init();
+ tm_mutex_init();
+
+ printf(
+ "%d proc, %d threads/proc, %d lock requests from %d locks:\n",
+ nprocs, nthreads, nlocks, maxlocks);
+ for (i = 0; i < nprocs; ++i)
+ switch (fork()) {
+ case -1:
+ perror("fork");
+ return (EXIT_FAILURE);
+ case 0:
+ exec_proc(tmpath);
+ break;
+ default:
+ break;
+ }
+
+ eval = EXIT_SUCCESS;
+ while ((pid = wait(&status)) != (pid_t)-1) {
+ fprintf(stderr,
+ "%lu: exited %d\n", (u_long)pid, WEXITSTATUS(status));
+ if (WEXITSTATUS(status) != 0)
+ eval = EXIT_FAILURE;
+ }
+
+ tm_mutex_stats();
+ tm_mutex_destroy();
+
+ printf("tm: exit status: %s\n",
+ eval == EXIT_SUCCESS ? "success" : "failed!");
+ return (eval);
+}
+
+void
+exec_proc(tmpath)
+ char *tmpath;
+{
+ char *argv[10], **ap, b_l[10], b_n[10], b_t[10];
+
+ ap = &argv[0];
+ *ap++ = "tm";
+ sprintf(b_l, "-l%d", maxlocks);
+ *ap++ = b_l;
+ sprintf(b_n, "-n%d", nlocks);
+ *ap++ = b_n;
+ *ap++ = "-s";
+ sprintf(b_t, "-t%d", nthreads);
+ *ap++ = b_t;
+ if (verbose)
+ *ap++ = "-v";
+
+ *ap = NULL;
+ execvp(tmpath, argv);
+
+ fprintf(stderr, "%s: %s\n", tmpath, strerror(errno));
+ exit(EXIT_FAILURE);
+}
+
+void
+run_proc()
+{
+#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+ pthread_t *kidsp, wakep;
+ int i, status;
+ void *retp;
+#endif
+ __os_sleep(&dbenv, 3, 0); /* Let everyone catch up. */
+
+ srand((u_int)time(NULL) / getpid()); /* Initialize random numbers. */
+
+ if (nthreads == 1) /* Simple case. */
+ exit((int)run_thread((void *)0));
+
+#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+ /*
+ * Spawn off threads. We have nthreads all locking and going to
+ * sleep, and one other thread cycling through and waking them up.
+ */
+ if ((kidsp =
+ (pthread_t *)calloc(sizeof(pthread_t), nthreads)) == NULL) {
+ fprintf(stderr, "tm: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < nthreads; i++)
+ if ((errno = pthread_create(
+ &kidsp[i], NULL, run_thread, (void *)i)) != 0) {
+ fprintf(stderr, "tm: failed spawning thread %d: %s\n",
+ i, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if ((errno = pthread_create(
+ &wakep, NULL, run_thread_wake, (void *)0)) != 0) {
+ fprintf(stderr, "tm: failed spawning wakeup thread: %s\n",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Wait for the threads to exit. */
+ status = 0;
+ for (i = 0; i < nthreads; i++) {
+ pthread_join(kidsp[i], &retp);
+ if (retp != NULL) {
+ fprintf(stderr,
+ "tm: thread %d exited with error\n", i);
+ status = EXIT_FAILURE;
+ }
+ }
+ free(kidsp);
+
+ /* Signal wakeup thread to stop. */
+ quit = 1;
+ pthread_join(wakep, &retp);
+ if (retp != NULL) {
+ fprintf(stderr, "tm: wakeup thread exited with error\n");
+ status = EXIT_FAILURE;
+ }
+
+ exit(status);
+#endif
+}
+
+void *
+run_thread(arg)
+ void *arg;
+{
+ DB_MUTEX *gm_addr, *lm_addr, *tm_addr, *mp;
+ u_long gid1, gid2, *id_addr;
+ int fd, i, lock, id, nl, remap;
+
+ /* Set local and global per-thread ID. */
+ id = (int)arg;
+ gid1 = (u_long)getpid();
+#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+ gid2 = (u_long)pthread_self();
+#else
+ gid2 = 0;
+#endif
+ printf("\tPID: %lu; TID: %lx; ID: %d\n", gid1, gid2, id);
+
+ nl = nlocks;
+ for (gm_addr = NULL, remap = 0;;) {
+ /* Map in the file as necessary. */
+ if (gm_addr == NULL) {
+ map_file(&gm_addr, &tm_addr, &lm_addr, &id_addr, &fd);
+ remap = (rand() % 100) + 35;
+ }
+
+ /* Select and acquire a data lock. */
+ lock = rand() % maxlocks;
+ mp = (DB_MUTEX *)((u_int8_t *)lm_addr + lock * align);
+ if (verbose)
+ printf("%lu/%lx: %03d\n", gid1, gid2, lock);
+
+ if (__db_mutex_lock(&dbenv, mp)) {
+ fprintf(stderr,
+ "%lu/%lx: never got lock\n", gid1, gid2);
+ return ((void *)EXIT_FAILURE);
+ }
+ if (id_addr[lock * 2] != 0) {
+ fprintf(stderr,
+ "RACE! (%lu/%lx granted lock %d held by %lu/%lx)\n",
+ gid1, gid2,
+ lock, id_addr[lock * 2], id_addr[lock * 2 + 1]);
+ return ((void *)EXIT_FAILURE);
+ }
+ id_addr[lock * 2] = gid1;
+ id_addr[lock * 2 + 1] = gid2;
+
+ /*
+ * Pretend to do some work, periodically checking to see if
+ * we still hold the mutex.
+ */
+ for (i = 0; i < 3; ++i) {
+ __os_sleep(&dbenv, 0, rand() % 3);
+ if (id_addr[lock * 2] != gid1 ||
+ id_addr[lock * 2 + 1] != gid2) {
+ fprintf(stderr,
+ "RACE! (%lu/%lx stole lock %d from %lu/%lx)\n",
+ id_addr[lock * 2],
+ id_addr[lock * 2 + 1], lock, gid1, gid2);
+ return ((void *)EXIT_FAILURE);
+ }
+ }
+
+#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+ /*
+ * Test self-blocking and unlocking by other threads/processes:
+ *
+ * acquire the global lock
+ * set our wakeup flag
+ * release the global lock
+ * acquire our per-thread lock
+ *
+ * The wakeup thread will wake us up.
+ */
+ if (__db_mutex_lock(&dbenv, gm_addr)) {
+ fprintf(stderr, "%lu/%lx: global lock\n", gid1, gid2);
+ return ((void *)EXIT_FAILURE);
+ }
+ mp = (DB_MUTEX *)((u_int8_t *)tm_addr + id * align);
+ F_SET(mp, MUTEX_WAKEME);
+ if (__db_mutex_unlock(&dbenv, gm_addr)) {
+ fprintf(stderr,
+ "%lu/%lx: per-thread wakeup failed\n", gid1, gid2);
+ return ((void *)EXIT_FAILURE);
+ }
+ if (__db_mutex_lock(&dbenv, mp)) {
+ fprintf(stderr,
+ "%lu/%lx: per-thread lock\n", gid1, gid2);
+ return ((void *)EXIT_FAILURE);
+ }
+ /* Time passes... */
+ if (F_ISSET(mp, MUTEX_WAKEME)) {
+ fprintf(stderr, "%lu/%lx: %03d wakeup flag still set\n",
+ gid1, gid2, id);
+ return ((void *)EXIT_FAILURE);
+ }
+#endif
+
+ /* Release the data lock. */
+ id_addr[lock * 2] = id_addr[lock * 2 + 1] = 0;
+ mp = (DB_MUTEX *)((u_int8_t *)lm_addr + lock * align);
+ if (__db_mutex_unlock(&dbenv, mp)) {
+ fprintf(stderr, "%lu/%lx: wakeup failed\n", gid1, gid2);
+ return ((void *)EXIT_FAILURE);
+ }
+
+ if (--nl % 100 == 0)
+ fprintf(stderr, "%lu/%lx: %d\n", gid1, gid2, nl);
+
+ if (nl == 0 || --remap == 0) {
+ unmap_file((void *)gm_addr, fd);
+ gm_addr = NULL;
+
+ if (nl == 0)
+ break;
+
+ __os_sleep(&dbenv, rand() % 3, 0);
+ }
+ }
+
+ return (NULL);
+}
+
+#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+/*
+ * run_thread_wake --
+ * Thread to wake up other threads that are sleeping.
+ */
+void *
+run_thread_wake(arg)
+ void *arg;
+{
+ DB_MUTEX *gm_addr, *tm_addr, *mp;
+ int fd, id;
+
+ arg = NULL;
+ map_file(&gm_addr, &tm_addr, NULL, NULL, &fd);
+
+ /* Loop, waking up sleepers and periodically sleeping ourselves. */
+ while (!quit) {
+ id = 0;
+
+ /* Acquire the global lock. */
+retry: if (__db_mutex_lock(&dbenv, gm_addr)) {
+ fprintf(stderr, "wt: global lock failed\n");
+ return ((void *)EXIT_FAILURE);
+ }
+
+next: mp = (DB_MUTEX *)((u_int8_t *)tm_addr + id * align);
+ if (F_ISSET(mp, MUTEX_WAKEME)) {
+ F_CLR(mp, MUTEX_WAKEME);
+ if (__db_mutex_unlock(&dbenv, mp)) {
+ fprintf(stderr, "wt: wakeup failed\n");
+ return ((void *)EXIT_FAILURE);
+ }
+ }
+
+ if (++id < nthreads && id % 3 != 0)
+ goto next;
+
+ if (__db_mutex_unlock(&dbenv, gm_addr)) {
+ fprintf(stderr, "wt: global unlock failed\n");
+ return ((void *)EXIT_FAILURE);
+ }
+
+ __os_sleep(&dbenv, 0, 500);
+
+ if (id < nthreads)
+ goto retry;
+ }
+ return (NULL);
+}
+#endif
+
+/*
+ * tm_file_init --
+ * Initialize the backing file.
+ */
+void
+tm_file_init()
+{
+ int fd;
+
+
+ /* Initialize the backing file. */
+ printf("Create the backing file...\n");
+#ifdef HAVE_QNX
+ (void)shm_unlink(file);
+ if ((fd = shm_open(file, O_CREAT | O_RDWR | O_TRUNC,
+#else
+ (void)remove(file);
+ if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC,
+#endif
+
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) {
+ (void)fprintf(stderr, "%s: open: %s\n", file, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (lseek(fd, (off_t)len, SEEK_SET) != len || write(fd, &fd, 1) != 1) {
+ (void)fprintf(stderr,
+ "%s: seek/write: %s\n", file, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ (void)close(fd);
+}
+
+/*
+ * tm_mutex_init --
+ * Initialize the mutexes.
+ */
+void
+tm_mutex_init()
+{
+ DB_MUTEX *gm_addr, *lm_addr, *mp, *tm_addr;
+ int fd, i;
+
+ map_file(&gm_addr, &tm_addr, &lm_addr, NULL, &fd);
+
+ printf("Initialize the global mutex...\n");
+ if (__db_mutex_init_int(&dbenv, gm_addr, 0, 0)) {
+ fprintf(stderr,
+ "__db_mutex_init (global): %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Initialize the per-thread mutexes...\n");
+ for (i = 1, mp = tm_addr;
+ i <= nthreads; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) {
+ if (__db_mutex_init_int(&dbenv, mp, 0, MUTEX_SELF_BLOCK)) {
+ fprintf(stderr, "__db_mutex_init (per-thread %d): %s\n",
+ i, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (__db_mutex_lock(&dbenv, mp)) {
+ fprintf(stderr,
+ "__db_mutex_init (per-thread %d) lock: %s\n",
+ i, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf("Initialize the per-lock mutexes...\n");
+ for (i = 1, mp = lm_addr;
+ i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align))
+ if (__db_mutex_init_int(&dbenv, mp, 0, 0)) {
+ fprintf(stderr, "__db_mutex_init (per-lock: %d): %s\n",
+ i, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ unmap_file((void *)gm_addr, fd);
+}
+
+/*
+ * tm_mutex_destroy --
+ * Destroy the mutexes.
+ */
+void
+tm_mutex_destroy()
+{
+ DB_MUTEX *gm_addr, *lm_addr, *mp, *tm_addr;
+ int fd, i;
+
+ map_file(&gm_addr, &tm_addr, &lm_addr, NULL, &fd);
+
+ printf("Destroy the global mutex...\n");
+ if (__db_mutex_destroy(gm_addr)) {
+ fprintf(stderr,
+ "__db_mutex_destroy (global): %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Destroy the per-thread mutexes...\n");
+ for (i = 1, mp = tm_addr;
+ i <= nthreads; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) {
+ if (__db_mutex_destroy(mp)) {
+ fprintf(stderr,
+ "__db_mutex_destroy (per-thread %d): %s\n",
+ i, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf("Destroy the per-lock mutexes...\n");
+ for (i = 1, mp = lm_addr;
+ i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align))
+ if (__db_mutex_destroy(mp)) {
+ fprintf(stderr,
+ "__db_mutex_destroy (per-lock: %d): %s\n",
+ i, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ unmap_file((void *)gm_addr, fd);
+#ifdef HAVE_QNX
+ (void)shm_unlink(file);
+#endif
+}
+
+/*
+ * tm_mutex_stats --
+ * Display mutex statistics.
+ */
+void
+tm_mutex_stats()
+{
+ DB_MUTEX *gm_addr, *lm_addr, *mp;
+ int fd, i;
+
+ map_file(&gm_addr, NULL, &lm_addr, NULL, &fd);
+
+ printf("Per-lock mutex statistics...\n");
+ for (i = 1, mp = lm_addr;
+ i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align))
+ printf("mutex %2d: wait: %lu; no wait %lu\n", i,
+ (u_long)mp->mutex_set_wait, (u_long)mp->mutex_set_nowait);
+
+ unmap_file((void *)gm_addr, fd);
+}
+
+/*
+ * map_file --
+ * Map in the backing file.
+ */
+void
+map_file(gm_addrp, tm_addrp, lm_addrp, id_addrp, fdp)
+ DB_MUTEX **gm_addrp, **tm_addrp, **lm_addrp;
+ u_long **id_addrp;
+ int *fdp;
+{
+ void *maddr;
+ int fd;
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (void *)-1
+#endif
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifdef HAVE_QNX
+ if ((fd = shm_open(file, O_RDWR, 0)) == -1) {
+#else
+ if ((fd = open(file, O_RDWR, 0)) == -1) {
+#endif
+ fprintf(stderr, "%s: open %s\n", file, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ maddr = mmap(NULL, len,
+ PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, (off_t)0);
+ if (maddr == MAP_FAILED) {
+ fprintf(stderr, "%s: mmap: %s\n", file, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (gm_addrp != NULL)
+ *gm_addrp = (DB_MUTEX *)maddr;
+ maddr = (u_int8_t *)maddr + align;
+ if (tm_addrp != NULL)
+ *tm_addrp = (DB_MUTEX *)maddr;
+ maddr = (u_int8_t *)maddr + align * nthreads;
+ if (lm_addrp != NULL)
+ *lm_addrp = (DB_MUTEX *)maddr;
+ maddr = (u_int8_t *)maddr + align * maxlocks;
+ if (id_addrp != NULL)
+ *id_addrp = (u_long *)maddr;
+ if (fdp != NULL)
+ *fdp = fd;
+}
+
+/*
+ * unmap_file --
+ * Discard backing file map.
+ */
+void
+unmap_file(maddr, fd)
+ void *maddr;
+ int fd;
+{
+ if (munmap(maddr, len) != 0) {
+ fprintf(stderr, "munmap: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (close(fd) != 0) {
+ fprintf(stderr, "close: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+}
diff --git a/bdb/mutex/uts4_cc.s b/bdb/mutex/uts4_cc.s
index ee5f4143bde..9ebc45aad54 100644
--- a/bdb/mutex/uts4_cc.s
+++ b/bdb/mutex/uts4_cc.s
@@ -1,3 +1,9 @@
+ / See the file LICENSE for redistribution information.
+ /
+ / Copyright (c) 1997-2002
+ / Sleepycat Software. All rights reserved.
+ /
+ / $Id: uts4_cc.s,v 11.2 2002/04/25 13:42:14 bostic Exp $
/
/ int uts_lock ( int *p, int i );
/ Update the lock word pointed to by p with the
diff --git a/bdb/os/os_abs.c b/bdb/os/os_abs.c
index 04be9873360..cd7d0a5d2be 100644
--- a/bdb/os/os_abs.c
+++ b/bdb/os/os_abs.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_abs.c,v 11.3 2000/02/14 03:00:04 bostic Exp $";
+static const char revid[] = "$Id: os_abs.c,v 11.5 2002/01/11 15:52:58 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
diff --git a/bdb/os/os_alloc.c b/bdb/os/os_alloc.c
index ee4a0f3c91f..5b38cc7d6f1 100644
--- a/bdb/os/os_alloc.c
+++ b/bdb/os/os_alloc.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_alloc.c,v 11.18 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: os_alloc.c,v 11.32 2002/08/06 04:57:07 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,10 +19,14 @@ static const char revid[] = "$Id: os_alloc.c,v 11.18 2000/11/30 00:58:42 ubell E
#endif
#include "db_int.h"
-#include "os_jump.h"
#ifdef DIAGNOSTIC
-static void __os_guard __P((void));
+static void __os_guard __P((DB_ENV *));
+
+union __db_alloc {
+ size_t size;
+ double align;
+};
#endif
/*
@@ -37,12 +41,150 @@ static void __os_guard __P((void));
* !!!
* Correct for systems that don't set errno when malloc and friends fail.
*
+ * !!!
+ * There is no circumstance in which we can call __os_umalloc, __os_urealloc
+ * or __os_ufree without an environment handle, as we need one to determine
+ * whether or not to use an application-specified malloc function. If we
+ * don't have an environment handle, we should be calling __os_XXX instead.
+ * Make DIAGNOSTIC blow up if we get this wrong.
+ *
* Out of memory.
* We wish to hold the whole sky,
* But we never will.
*/
/*
+ * __os_umalloc --
+ * A malloc(3) function that will use, in order of preference,
+ * the allocation function specified to the DB handle, the DB_ENV
+ * handle, or __os_malloc.
+ *
+ * PUBLIC: int __os_umalloc __P((DB_ENV *, size_t, void *));
+ */
+int
+__os_umalloc(dbenv, size, storep)
+ DB_ENV *dbenv;
+ size_t size;
+ void *storep;
+{
+ int ret;
+
+ /* Require an environment handle. */
+ DB_ASSERT(dbenv != NULL);
+
+ /* Never allocate 0 bytes -- some C libraries don't like it. */
+ if (size == 0)
+ ++size;
+
+ if (dbenv == NULL || dbenv->db_malloc == NULL) {
+ if (DB_GLOBAL(j_malloc) != NULL)
+ *(void **)storep = DB_GLOBAL(j_malloc)(size);
+ else
+ *(void **)storep = malloc(size);
+ if (*(void **)storep == NULL) {
+ /*
+ * Correct error return, see __os_malloc.
+ */
+ if ((ret = __os_get_errno()) == 0) {
+ ret = ENOMEM;
+ __os_set_errno(ENOMEM);
+ }
+ __db_err(dbenv,
+ "malloc: %s: %lu", strerror(ret), (u_long)size);
+ return (ret);
+ }
+ return (0);
+ }
+
+ if ((*(void **)storep = dbenv->db_malloc(size)) == NULL) {
+ __db_err(dbenv, "User-specified malloc function returned NULL");
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+/*
+ * __os_urealloc --
+ * realloc(3) counterpart to __os_umalloc.
+ *
+ * PUBLIC: int __os_urealloc __P((DB_ENV *, size_t, void *));
+ */
+int
+__os_urealloc(dbenv, size, storep)
+ DB_ENV *dbenv;
+ size_t size;
+ void *storep;
+{
+ int ret;
+ void *ptr;
+
+ ptr = *(void **)storep;
+
+ /* Require an environment handle. */
+ DB_ASSERT(dbenv != NULL);
+
+ /* Never allocate 0 bytes -- some C libraries don't like it. */
+ if (size == 0)
+ ++size;
+
+ if (dbenv == NULL || dbenv->db_realloc == NULL) {
+ if (ptr == NULL)
+ return (__os_umalloc(dbenv, size, storep));
+
+ if (DB_GLOBAL(j_realloc) != NULL)
+ *(void **)storep = DB_GLOBAL(j_realloc)(ptr, size);
+ else
+ *(void **)storep = realloc(ptr, size);
+ if (*(void **)storep == NULL) {
+ /*
+ * Correct errno, see __os_realloc.
+ */
+ if ((ret = __os_get_errno()) == 0) {
+ ret = ENOMEM;
+ __os_set_errno(ENOMEM);
+ }
+ __db_err(dbenv,
+ "realloc: %s: %lu", strerror(ret), (u_long)size);
+ return (ret);
+ }
+ return (0);
+ }
+
+ if ((*(void **)storep = dbenv->db_realloc(ptr, size)) == NULL) {
+ __db_err(dbenv,
+ "User-specified realloc function returned NULL");
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+/*
+ * __os_ufree --
+ * free(3) counterpart to __os_umalloc.
+ *
+ * PUBLIC: int __os_ufree __P((DB_ENV *, void *));
+ */
+int
+__os_ufree(dbenv, ptr)
+ DB_ENV *dbenv;
+ void *ptr;
+{
+ /* Require an environment handle. */
+ DB_ASSERT(dbenv != NULL);
+
+ if (dbenv != NULL && dbenv->db_free != NULL)
+ dbenv->db_free(ptr);
+ else if (DB_GLOBAL(j_free) != NULL)
+ DB_GLOBAL(j_free)(ptr);
+ else
+ free(ptr);
+
+ return (0);
+}
+
+/*
* __os_strdup --
* The strdup(3) function for DB.
*
@@ -61,7 +203,7 @@ __os_strdup(dbenv, str, storep)
*(void **)storep = NULL;
size = strlen(str) + 1;
- if ((ret = __os_malloc(dbenv, size, NULL, &p)) != 0)
+ if ((ret = __os_malloc(dbenv, size, &p)) != 0)
return (ret);
memcpy(p, str, size);
@@ -86,7 +228,7 @@ __os_calloc(dbenv, num, size, storep)
int ret;
size *= num;
- if ((ret = __os_malloc(dbenv, size, NULL, &p)) != 0)
+ if ((ret = __os_malloc(dbenv, size, &p)) != 0)
return (ret);
memset(p, 0, size);
@@ -99,13 +241,13 @@ __os_calloc(dbenv, num, size, storep)
* __os_malloc --
* The malloc(3) function for DB.
*
- * PUBLIC: int __os_malloc __P((DB_ENV *, size_t, void *(*)(size_t), void *));
+ * PUBLIC: int __os_malloc __P((DB_ENV *, size_t, void *));
*/
int
-__os_malloc(dbenv, size, db_malloc, storep)
+__os_malloc(dbenv, size, storep)
DB_ENV *dbenv;
size_t size;
- void *(*db_malloc) __P((size_t)), *storep;
+ void *storep;
{
int ret;
void *p;
@@ -115,24 +257,26 @@ __os_malloc(dbenv, size, db_malloc, storep)
/* Never allocate 0 bytes -- some C libraries don't like it. */
if (size == 0)
++size;
+
#ifdef DIAGNOSTIC
- else
- ++size; /* Add room for a guard byte. */
+ /* Add room for size and a guard byte. */
+ size += sizeof(union __db_alloc) + 1;
#endif
- /* Some C libraries don't correctly set errno when malloc(3) fails. */
- __os_set_errno(0);
- if (db_malloc != NULL)
- p = db_malloc(size);
- else if (__db_jump.j_malloc != NULL)
- p = __db_jump.j_malloc(size);
+ if (DB_GLOBAL(j_malloc) != NULL)
+ p = DB_GLOBAL(j_malloc)(size);
else
p = malloc(size);
if (p == NULL) {
- ret = __os_get_errno();
- if (ret == 0) {
- __os_set_errno(ENOMEM);
+ /*
+ * Some C libraries don't correctly set errno when malloc(3)
+ * fails. We'd like to 0 out errno before calling malloc,
+ * but it turns out that setting errno is quite expensive on
+ * Windows/NT in an MT environment.
+ */
+ if ((ret = __os_get_errno()) == 0) {
ret = ENOMEM;
+ __os_set_errno(ENOMEM);
}
__db_err(dbenv,
"malloc: %s: %lu", strerror(ret), (u_long)size);
@@ -143,15 +287,12 @@ __os_malloc(dbenv, size, db_malloc, storep)
/*
* Guard bytes: if #DIAGNOSTIC is defined, we allocate an additional
* byte after the memory and set it to a special value that we check
- * for when the memory is free'd. This is fine for structures, but
- * not quite so fine for strings. There are places in DB where memory
- * is allocated sufficient to hold the largest possible string that
- * we'll see, and then only some subset of the memory is used. To
- * support this usage, the __os_freestr() function checks the byte
- * after the string's nul, which may or may not be the last byte in
- * the originally allocated memory.
+ * for when the memory is free'd.
*/
- memset(p, CLEAR_BYTE, size); /* Initialize guard byte. */
+ ((u_int8_t *)p)[size - 1] = CLEAR_BYTE;
+
+ ((union __db_alloc *)p)->size = size;
+ p = &((union __db_alloc *)p)[1];
#endif
*(void **)storep = p;
@@ -162,46 +303,50 @@ __os_malloc(dbenv, size, db_malloc, storep)
* __os_realloc --
* The realloc(3) function for DB.
*
- * PUBLIC: int __os_realloc __P((DB_ENV *,
- * PUBLIC: size_t, void *(*)(void *, size_t), void *));
+ * PUBLIC: int __os_realloc __P((DB_ENV *, size_t, void *));
*/
int
-__os_realloc(dbenv, size, db_realloc, storep)
+__os_realloc(dbenv, size, storep)
DB_ENV *dbenv;
size_t size;
- void *(*db_realloc) __P((void *, size_t)), *storep;
+ void *storep;
{
int ret;
void *p, *ptr;
ptr = *(void **)storep;
- /* If we haven't yet allocated anything yet, simply call malloc. */
- if (ptr == NULL && db_realloc == NULL)
- return (__os_malloc(dbenv, size, NULL, storep));
-
/* Never allocate 0 bytes -- some C libraries don't like it. */
if (size == 0)
++size;
+
+ /* If we haven't yet allocated anything yet, simply call malloc. */
+ if (ptr == NULL)
+ return (__os_malloc(dbenv, size, storep));
+
#ifdef DIAGNOSTIC
- else
- ++size; /* Add room for a guard byte. */
+ /* Add room for size and a guard byte. */
+ size += sizeof(union __db_alloc) + 1;
+
+ /* Back up to the real begining */
+ ptr = &((union __db_alloc *)ptr)[-1];
#endif
/*
- * Some C libraries don't correctly set errno when realloc(3) fails.
- *
* Don't overwrite the original pointer, there are places in DB we
* try to continue after realloc fails.
*/
- __os_set_errno(0);
- if (db_realloc != NULL)
- p = db_realloc(ptr, size);
- else if (__db_jump.j_realloc != NULL)
- p = __db_jump.j_realloc(ptr, size);
+ if (DB_GLOBAL(j_realloc) != NULL)
+ p = DB_GLOBAL(j_realloc)(ptr, size);
else
p = realloc(ptr, size);
if (p == NULL) {
+ /*
+ * Some C libraries don't correctly set errno when malloc(3)
+ * fails. We'd like to 0 out errno before calling malloc,
+ * but it turns out that setting errno is quite expensive on
+ * Windows/NT in an MT environment.
+ */
if ((ret = __os_get_errno()) == 0) {
ret = ENOMEM;
__os_set_errno(ENOMEM);
@@ -212,6 +357,9 @@ __os_realloc(dbenv, size, db_realloc, storep)
}
#ifdef DIAGNOSTIC
((u_int8_t *)p)[size - 1] = CLEAR_BYTE; /* Initialize guard byte. */
+
+ ((union __db_alloc *)p)->size = size;
+ p = &((union __db_alloc *)p)[1];
#endif
*(void **)storep = p;
@@ -223,64 +371,35 @@ __os_realloc(dbenv, size, db_realloc, storep)
* __os_free --
* The free(3) function for DB.
*
- * PUBLIC: void __os_free __P((void *, size_t));
- */
-void
-__os_free(ptr, size)
- void *ptr;
- size_t size;
-{
-#ifdef DIAGNOSTIC
- if (size != 0) {
- /*
- * Check that the guard byte (one past the end of the memory) is
- * still CLEAR_BYTE.
- */
- if (((u_int8_t *)ptr)[size] != CLEAR_BYTE)
- __os_guard();
-
- /* Clear memory. */
- if (size != 0)
- memset(ptr, CLEAR_BYTE, size);
- }
-#else
- COMPQUIET(size, 0);
-#endif
-
- if (__db_jump.j_free != NULL)
- __db_jump.j_free(ptr);
- else
- free(ptr);
-}
-
-/*
- * __os_freestr --
- * The free(3) function for DB, freeing a string.
- *
- * PUBLIC: void __os_freestr __P((void *));
+ * PUBLIC: void __os_free __P((DB_ENV *, void *));
*/
void
-__os_freestr(ptr)
+__os_free(dbenv, ptr)
+ DB_ENV *dbenv;
void *ptr;
{
#ifdef DIAGNOSTIC
- size_t size;
-
- size = strlen(ptr) + 1;
-
+ int size;
/*
* Check that the guard byte (one past the end of the memory) is
* still CLEAR_BYTE.
*/
- if (((u_int8_t *)ptr)[size] != CLEAR_BYTE)
- __os_guard();
+ if (ptr == NULL)
+ return;
+
+ ptr = &((union __db_alloc *)ptr)[-1];
+ size = ((union __db_alloc *)ptr)->size;
+ if (((u_int8_t *)ptr)[size - 1] != CLEAR_BYTE)
+ __os_guard(dbenv);
/* Clear memory. */
- memset(ptr, CLEAR_BYTE, size);
+ if (size != 0)
+ memset(ptr, CLEAR_BYTE, size);
#endif
+ COMPQUIET(dbenv, NULL);
- if (__db_jump.j_free != NULL)
- __db_jump.j_free(ptr);
+ if (DB_GLOBAL(j_free) != NULL)
+ DB_GLOBAL(j_free)(ptr);
else
free(ptr);
}
@@ -291,13 +410,10 @@ __os_freestr(ptr)
* Complain and abort.
*/
static void
-__os_guard()
+__os_guard(dbenv)
+ DB_ENV *dbenv;
{
- /*
- * Eventually, once we push a DB_ENV handle down to these
- * routines, we should use the standard output channels.
- */
- fprintf(stderr, "Guard byte incorrect during free.\n");
+ __db_err(dbenv, "Guard byte incorrect during free");
abort();
/* NOTREACHED */
}
diff --git a/bdb/os/os_clock.c b/bdb/os/os_clock.c
new file mode 100644
index 00000000000..8da02cf6f9c
--- /dev/null
+++ b/bdb/os/os_clock.c
@@ -0,0 +1,92 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_clock.c,v 1.9 2002/03/29 20:46:44 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif /* HAVE_SYS_TIME_H */
+#endif /* TIME_WITH SYS_TIME */
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_clock --
+ * Return the current time-of-day clock in seconds and microseconds.
+ *
+ * PUBLIC: int __os_clock __P((DB_ENV *, u_int32_t *, u_int32_t *));
+ */
+int
+__os_clock(dbenv, secsp, usecsp)
+ DB_ENV *dbenv;
+ u_int32_t *secsp, *usecsp; /* Seconds and microseconds. */
+{
+#if defined(HAVE_GETTIMEOFDAY)
+ struct timeval tp;
+ int ret;
+
+retry: if (gettimeofday(&tp, NULL) != 0) {
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
+ __db_err(dbenv, "gettimeofday: %s", strerror(ret));
+ return (ret);
+ }
+
+ if (secsp != NULL)
+ *secsp = tp.tv_sec;
+ if (usecsp != NULL)
+ *usecsp = tp.tv_usec;
+#endif
+#if !defined(HAVE_GETTIMEOFDAY) && defined(HAVE_CLOCK_GETTIME)
+ struct timespec tp;
+ int ret;
+
+retry: if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
+ __db_err(dbenv, "clock_gettime: %s", strerror(ret));
+ return (ret);
+ }
+
+ if (secsp != NULL)
+ *secsp = tp.tv_sec;
+ if (usecsp != NULL)
+ *usecsp = tp.tv_nsec / 1000;
+#endif
+#if !defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_CLOCK_GETTIME)
+ time_t now;
+ int ret;
+
+ if (time(&now) == (time_t)-1) {
+ ret = __os_get_errno();
+ __db_err(dbenv, "time: %s", strerror(ret));
+ return (ret);
+ }
+
+ if (secsp != NULL)
+ *secsp = now;
+ if (usecsp != NULL)
+ *usecsp = 0;
+#endif
+ return (0);
+}
diff --git a/bdb/os/os_config.c b/bdb/os/os_config.c
new file mode 100644
index 00000000000..b64952a8302
--- /dev/null
+++ b/bdb/os/os_config.c
@@ -0,0 +1,31 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_config.c,v 11.13 2002/01/31 19:54:12 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_fs_notzero --
+ * Return 1 if allocated filesystem blocks are not zeroed.
+ *
+ * PUBLIC: int __os_fs_notzero __P((void));
+ */
+int
+__os_fs_notzero()
+{
+ /* Most filesystems zero out implicitly created pages. */
+ return (0);
+}
diff --git a/bdb/os/os_dir.c b/bdb/os/os_dir.c
index 50d00a5562f..3f59a23d963 100644
--- a/bdb/os/os_dir.c
+++ b/bdb/os/os_dir.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_dir.c,v 11.8 2000/06/27 17:29:52 sue Exp $";
+static const char revid[] = "$Id: os_dir.c,v 11.14 2002/07/12 18:56:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -34,7 +34,6 @@ static const char revid[] = "$Id: os_dir.c,v 11.8 2000/06/27 17:29:52 sue Exp $"
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_dirlist --
@@ -54,8 +53,8 @@ __os_dirlist(dbenv, dir, namesp, cntp)
int arraysz, cnt, ret;
char **names;
- if (__db_jump.j_dirlist != NULL)
- return (__db_jump.j_dirlist(dir, namesp, cntp));
+ if (DB_GLOBAL(j_dirlist) != NULL)
+ return (DB_GLOBAL(j_dirlist)(dir, namesp, cntp));
#ifdef HAVE_VXWORKS
if ((dirp = opendir((char *)dir)) == NULL)
@@ -68,7 +67,7 @@ __os_dirlist(dbenv, dir, namesp, cntp)
if (cnt >= arraysz) {
arraysz += 100;
if ((ret = __os_realloc(dbenv,
- arraysz * sizeof(names[0]), NULL, &names)) != 0)
+ arraysz * sizeof(names[0]), &names)) != 0)
goto nomem;
}
if ((ret = __os_strdup(dbenv, dp->d_name, &names[cnt])) != 0)
@@ -81,7 +80,7 @@ __os_dirlist(dbenv, dir, namesp, cntp)
return (0);
nomem: if (names != NULL)
- __os_dirfree(names, cnt);
+ __os_dirfree(dbenv, names, cnt);
if (dirp != NULL)
(void)closedir(dirp);
return (ret);
@@ -91,18 +90,19 @@ nomem: if (names != NULL)
* __os_dirfree --
* Free the list of files.
*
- * PUBLIC: void __os_dirfree __P((char **, int));
+ * PUBLIC: void __os_dirfree __P((DB_ENV *, char **, int));
*/
void
-__os_dirfree(names, cnt)
+__os_dirfree(dbenv, names, cnt)
+ DB_ENV *dbenv;
char **names;
int cnt;
{
- if (__db_jump.j_dirfree != NULL)
- __db_jump.j_dirfree(names, cnt);
+ if (DB_GLOBAL(j_dirfree) != NULL)
+ DB_GLOBAL(j_dirfree)(names, cnt);
else {
while (cnt > 0)
- __os_free(names[--cnt], 0);
- __os_free(names, 0);
+ __os_free(dbenv, names[--cnt]);
+ __os_free(dbenv, names);
}
}
diff --git a/bdb/os/os_errno.c b/bdb/os/os_errno.c
index f9b60f6354e..4b40f88d177 100644
--- a/bdb/os/os_errno.c
+++ b/bdb/os/os_errno.c
@@ -1,32 +1,52 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_errno.c,v 11.3 2000/02/14 03:00:05 bostic Exp $";
+static const char revid[] = "$Id: os_errno.c,v 11.8 2002/01/11 15:52:59 bostic Exp $";
#endif /* not lint */
-#ifndef NO_SYSTEM_INCLUDES
-#include <errno.h>
-#endif
-
#include "db_int.h"
/*
+ * __os_get_errno_ret_zero --
+ * Return the value of errno, even if it's zero.
+ *
+ * PUBLIC: int __os_get_errno_ret_zero __P((void));
+ */
+int
+__os_get_errno_ret_zero()
+{
+ /* This routine must be able to return the same value repeatedly. */
+ return (errno);
+}
+
+/*
* __os_get_errno --
- * Return the value of errno.
+ * Return the value of errno, or EAGAIN if errno is zero.
*
* PUBLIC: int __os_get_errno __P((void));
*/
int
__os_get_errno()
{
- /* This routine must be able to return the same value repeatedly. */
+ /*
+ * This routine must be able to return the same value repeatedly.
+ *
+ * We've seen cases where system calls failed but errno was never set.
+ * This version of __os_get_errno() sets errno to EAGAIN if it's not
+ * already set, to work around that problem. For obvious reasons, we
+ * can only call this function if we know an error has occurred, that
+ * is, we can't test errno for a non-zero value after this call.
+ */
+ if (errno == 0)
+ __os_set_errno(EAGAIN);
+
return (errno);
}
diff --git a/bdb/os/os_fid.c b/bdb/os/os_fid.c
index f853f6a8dba..125e6f0712c 100644
--- a/bdb/os/os_fid.c
+++ b/bdb/os/os_fid.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_fid.c,v 11.7 2000/10/26 14:17:05 bostic Exp $";
+static const char revid[] = "$Id: os_fid.c,v 11.14 2002/08/26 14:37:38 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -26,6 +26,7 @@ static const char revid[] = "$Id: os_fid.c,v 11.7 2000/10/26 14:17:05 bostic Exp
#endif
#endif
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
@@ -37,7 +38,12 @@ static u_int32_t fid_serial = SERIAL_INIT;
/*
* __os_fileid --
- * Return a unique identifier for a file.
+ * Return a unique identifier for a file. The structure
+ * of a fileid is: ino(4) dev(4) time(4) pid(4) extra(4).
+ * For real files, which have a backing inode and device, the first
+ * 16 bytes are filled in and the extra bytes are left 0. For
+ * temporary files, the inode and device fields are left blank and
+ * the extra four bytes are filled in with a random value.
*
* PUBLIC: int __os_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
*/
@@ -58,12 +64,14 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
memset(fidp, 0, DB_FILE_ID_LEN);
/* On POSIX/UNIX, use a dev/inode pair. */
+retry:
#ifdef HAVE_VXWORKS
- if (stat((char *)fname, &sb)) {
+ if (stat((char *)fname, &sb) != 0) {
#else
- if (stat(fname, &sb)) {
+ if (stat(fname, &sb) != 0) {
#endif
- ret = __os_get_errno();
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
__db_err(dbenv, "%s: %s", fname, strerror(ret));
return (ret);
}
@@ -83,7 +91,7 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
* interesting properties in base 2.
*/
if (fid_serial == SERIAL_INIT)
- fid_serial = (u_int32_t)getpid();
+ __os_id(&fid_serial);
else
fid_serial += 100000;
diff --git a/bdb/os/os_finit.c b/bdb/os/os_finit.c
deleted file mode 100644
index 23b606ecb2c..00000000000
--- a/bdb/os/os_finit.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: os_finit.c,v 11.8 2000/11/30 00:58:42 ubell Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <string.h>
-#endif
-
-#include "db_int.h"
-
-/*
- * __os_finit --
- * Initialize a regular file, optionally zero-filling it as well.
- *
- * PUBLIC: int __os_finit __P((DB_ENV *, DB_FH *, size_t, int));
- */
-int
-__os_finit(dbenv, fhp, size, zerofill)
- DB_ENV *dbenv;
- DB_FH *fhp;
- size_t size;
- int zerofill;
-{
- db_pgno_t pages;
- size_t i;
- size_t nw;
- u_int32_t relative;
- int ret;
- char buf[OS_VMPAGESIZE];
-
- /* Write nuls to the new bytes. */
- memset(buf, 0, sizeof(buf));
-
- /*
- * Extend the region by writing the last page. If the region is >4Gb,
- * increment may be larger than the maximum possible seek "relative"
- * argument, as it's an unsigned 32-bit value. Break the offset into
- * pages of 1MB each so that we don't overflow (2^20 + 2^32 is bigger
- * than any memory I expect to see for awhile).
- */
- if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_END)) != 0)
- return (ret);
- pages = (size - OS_VMPAGESIZE) / MEGABYTE;
- relative = (size - OS_VMPAGESIZE) % MEGABYTE;
- if ((ret = __os_seek(dbenv,
- fhp, MEGABYTE, pages, relative, 0, DB_OS_SEEK_CUR)) != 0)
- return (ret);
- if ((ret = __os_write(dbenv, fhp, buf, sizeof(buf), &nw)) != 0)
- return (ret);
- if (nw != sizeof(buf))
- return (EIO);
-
- /*
- * We may want to guarantee that there is enough disk space for the
- * file, so we also write a byte to each page. We write the byte
- * because reading it is insufficient on systems smart enough not to
- * instantiate disk pages to satisfy a read (e.g., Solaris).
- */
- if (zerofill) {
- pages = size / MEGABYTE;
- relative = size % MEGABYTE;
- if ((ret = __os_seek(dbenv, fhp,
- MEGABYTE, pages, relative, 1, DB_OS_SEEK_END)) != 0)
- return (ret);
-
- /* Write a byte to each page. */
- for (i = 0; i < size; i += OS_VMPAGESIZE) {
- if ((ret = __os_write(dbenv, fhp, buf, 1, &nw)) != 0)
- return (ret);
- if (nw != 1)
- return (EIO);
- if ((ret = __os_seek(dbenv, fhp,
- 0, 0, OS_VMPAGESIZE - 1, 0, DB_OS_SEEK_CUR)) != 0)
- return (ret);
- }
- }
- return (0);
-}
-
-/*
- * __os_fpinit --
- * Initialize a page in a regular file.
- *
- * PUBLIC: int __os_fpinit __P((DB_ENV *, DB_FH *, db_pgno_t, int, int));
- */
-int
-__os_fpinit(dbenv, fhp, pgno, pagecount, pagesize)
- DB_ENV *dbenv;
- DB_FH *fhp;
- db_pgno_t pgno;
- int pagecount, pagesize;
-{
- COMPQUIET(dbenv, NULL);
- COMPQUIET(fhp, NULL);
- COMPQUIET(pgno, 0);
- COMPQUIET(pagecount, 0);
- COMPQUIET(pagesize, 0);
-
- return (0);
-}
diff --git a/bdb/os/os_fsync.c b/bdb/os/os_fsync.c
index f5fd5f56abd..46ab4885a16 100644
--- a/bdb/os/os_fsync.c
+++ b/bdb/os/os_fsync.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_fsync.c,v 11.9 2000/04/04 23:29:20 ubell Exp $";
+static const char revid[] = "$Id: os_fsync.c,v 11.14 2002/07/12 18:56:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,6 @@ static const char revid[] = "$Id: os_fsync.c,v 11.9 2000/04/04 23:29:20 ubell Ex
#endif
#include "db_int.h"
-#include "os_jump.h"
#ifdef HAVE_VXWORKS
#include "ioLib.h"
@@ -79,12 +78,12 @@ __os_fsync(dbenv, fhp)
if (F_ISSET(fhp, DB_FH_NOSYNC))
return (0);
- ret = __db_jump.j_fsync != NULL ?
- __db_jump.j_fsync(fhp->fd) : fsync(fhp->fd);
+ do {
+ ret = DB_GLOBAL(j_fsync) != NULL ?
+ DB_GLOBAL(j_fsync)(fhp->fd) : fsync(fhp->fd);
+ } while (ret != 0 && (ret = __os_get_errno()) == EINTR);
- if (ret != 0) {
- ret = __os_get_errno();
+ if (ret != 0)
__db_err(dbenv, "fsync %s", strerror(ret));
- }
return (ret);
}
diff --git a/bdb/os/os_handle.c b/bdb/os/os_handle.c
index d85b13a6602..5f617085e5d 100644
--- a/bdb/os/os_handle.c
+++ b/bdb/os/os_handle.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_handle.c,v 11.19 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: os_handle.c,v 11.28 2002/07/12 18:56:50 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,6 @@ static const char revid[] = "$Id: os_handle.c,v 11.19 2000/11/30 00:58:42 ubell
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_openhandle --
@@ -43,29 +42,32 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
memset(fhp, 0, sizeof(*fhp));
/* If the application specified an interface, use it. */
- if (__db_jump.j_open != NULL) {
- if ((fhp->fd = __db_jump.j_open(name, flags, mode)) == -1)
+ if (DB_GLOBAL(j_open) != NULL) {
+ if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1)
return (__os_get_errno());
F_SET(fhp, DB_FH_VALID);
return (0);
}
- for (ret = 0, nrepeat = 1; nrepeat < 4; ++nrepeat) {
+ for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
+ ret = 0;
#ifdef HAVE_VXWORKS
/*
* VxWorks does not support O_CREAT on open, you have to use
* creat() instead. (It does not support O_EXCL or O_TRUNC
* either, even though they are defined "for future support".)
- * If O_EXCL is specified, single thread and try to open the
- * file. If successful, return EEXIST. Otherwise, call creat
- * and then end single threading.
+ * We really want the POSIX behavior that if O_CREAT is set,
+ * we open if it exists, or create it if it doesn't exist.
+ * If O_CREAT is specified, single thread and try to open the
+ * file. If successful, and O_EXCL return EEXIST. If
+ * unsuccessful call creat and then end single threading.
*/
if (LF_ISSET(O_CREAT)) {
DB_BEGIN_SINGLE_THREAD;
newflags = flags & ~(O_CREAT | O_EXCL);
- if (LF_ISSET(O_EXCL)) {
- if ((fhp->fd =
- open(name, newflags, mode)) != -1) {
+ if ((fhp->fd =
+ open(name, newflags, mode)) != -1) {
+ if (LF_ISSET(O_EXCL)) {
/*
* If we get here, we want O_EXCL
* create, and it exists. Close and
@@ -84,8 +86,8 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
* verify we truly got the equivalent of
* ENOENT.
*/
- }
- fhp->fd = creat(name, newflags);
+ } else
+ fhp->fd = creat(name, newflags);
DB_END_SINGLE_THREAD;
} else
@@ -118,6 +120,15 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
(void)__os_sleep(dbenv, nrepeat * 2, 0);
continue;
}
+
+ /*
+ * If it was an EINTR it's reasonable to retry
+ * immediately, and arbitrarily often.
+ */
+ if (ret == EINTR) {
+ --nrepeat;
+ continue;
+ }
} else {
#if defined(HAVE_FCNTL_F_SETFD)
/* Deny file descriptor access to any child process. */
@@ -125,7 +136,7 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
ret = __os_get_errno();
__db_err(dbenv, "fcntl(F_SETFD): %s",
strerror(ret));
- (void)__os_closehandle(fhp);
+ (void)__os_closehandle(dbenv, fhp);
} else
#endif
F_SET(fhp, DB_FH_VALID);
@@ -140,10 +151,11 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
* __os_closehandle --
* Close a file.
*
- * PUBLIC: int __os_closehandle __P((DB_FH *));
+ * PUBLIC: int __os_closehandle __P((DB_ENV *, DB_FH *));
*/
int
-__os_closehandle(fhp)
+__os_closehandle(dbenv, fhp)
+ DB_ENV *dbenv;
DB_FH *fhp;
{
int ret;
@@ -151,8 +163,16 @@ __os_closehandle(fhp)
/* Don't close file descriptors that were never opened. */
DB_ASSERT(F_ISSET(fhp, DB_FH_VALID) && fhp->fd != -1);
- ret = __db_jump.j_close != NULL ?
- __db_jump.j_close(fhp->fd) : close(fhp->fd);
+ do {
+ ret = DB_GLOBAL(j_close) != NULL ?
+ DB_GLOBAL(j_close)(fhp->fd) : close(fhp->fd);
+ } while (ret != 0 && (ret = __os_get_errno()) == EINTR);
+
+ /* Unlink the file if we haven't already done so. */
+ if (F_ISSET(fhp, DB_FH_UNLINK)) {
+ (void)__os_unlink(dbenv, fhp->name);
+ (void)__os_free(dbenv, fhp->name);
+ }
/*
* Smash the POSIX file descriptor -- it's never tested, but we want
@@ -161,5 +181,5 @@ __os_closehandle(fhp)
fhp->fd = -1;
F_CLR(fhp, DB_FH_VALID);
- return (ret == 0 ? 0 : __os_get_errno());
+ return (ret);
}
diff --git a/bdb/os/os_id.c b/bdb/os/os_id.c
new file mode 100644
index 00000000000..c242bb12e23
--- /dev/null
+++ b/bdb/os/os_id.c
@@ -0,0 +1,47 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_id.c,v 1.2 2002/01/11 15:52:59 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_id --
+ * Return a 32-bit value identifying the current thread of control.
+ *
+ * PUBLIC: void __os_id __P((u_int32_t *));
+ */
+void
+__os_id(idp)
+ u_int32_t *idp;
+{
+ /*
+ * By default, use the process ID.
+ *
+ * getpid() returns a pid_t which we convert to a u_int32_t. I have
+ * not yet seen a system where a pid_t has 64-bits, but I'm sure they
+ * exist. Since we're returning only the bottom 32-bits, you cannot
+ * use the return of __os_id to reference a process (for example, you
+ * cannot send a signal to the value returned by __os_id). To send a
+ * signal to the current process, use raise(3) instead.
+ */
+#ifdef HAVE_VXWORKS
+ *idp = taskIdSelf();
+#else
+ *idp = getpid();
+#endif
+}
diff --git a/bdb/os/os_map.c b/bdb/os/os_map.c
index bb96a917d87..6d385b6a84d 100644
--- a/bdb/os/os_map.c
+++ b/bdb/os/os_map.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_map.c,v 11.32 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: os_map.c,v 11.44 2002/07/12 18:56:51 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -26,9 +26,6 @@ static const char revid[] = "$Id: os_map.c,v 11.32 2000/11/30 00:58:42 ubell Exp
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_ext.h"
-#include "os_jump.h"
#ifdef HAVE_MMAP
static int __os_map __P((DB_ENV *, char *, DB_FH *, size_t, int, int, void **));
@@ -143,12 +140,13 @@ __os_r_sysattach(dbenv, infop, rp)
int ret;
/*
- * Try to open/create the shared region file. We DO NOT need to
- * ensure that multiple threads/processes attempting to
- * simultaneously create the region are properly ordered,
- * our caller has already taken care of that.
+ * Try to open/create the shared region file. We DO NOT need to ensure
+ * that multiple threads/processes attempting to simultaneously create
+ * the region are properly ordered, our caller has already taken care
+ * of that.
*/
- if ((ret = __os_open(dbenv, infop->name, DB_OSO_REGION |
+ if ((ret = __os_open(dbenv, infop->name,
+ DB_OSO_REGION | DB_OSO_DIRECT |
(F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE : 0),
infop->mode, &fh)) != 0)
__db_err(dbenv, "%s: %s", infop->name, db_strerror(ret));
@@ -161,15 +159,16 @@ __os_r_sysattach(dbenv, infop, rp)
* point, *badly* merged VM/buffer cache systems.
*/
if (ret == 0 && F_ISSET(infop, REGION_CREATE))
- ret = __os_finit(dbenv,
- &fh, rp->size, DB_GLOBAL(db_region_init));
+ ret = __db_fileinit(dbenv,
+ &fh, rp->size, F_ISSET(dbenv, DB_ENV_REGION_INIT) ? 1 : 0);
/* Map the file in. */
if (ret == 0)
ret = __os_map(dbenv,
infop->name, &fh, rp->size, 1, 0, &infop->addr);
- (void)__os_closehandle(&fh);
+ if (F_ISSET(&fh, DB_FH_VALID))
+ (void)__os_closehandle(dbenv, &fh);
return (ret);
}
@@ -295,17 +294,25 @@ __os_unmapfile(dbenv, addr, len)
size_t len;
{
/* If the user replaced the map call, call through their interface. */
- if (__db_jump.j_unmap != NULL)
- return (__db_jump.j_unmap(addr, len));
+ if (DB_GLOBAL(j_unmap) != NULL)
+ return (DB_GLOBAL(j_unmap)(addr, len));
#ifdef HAVE_MMAP
#ifdef HAVE_MUNLOCK
if (F_ISSET(dbenv, DB_ENV_LOCKDOWN))
- (void)munlock(addr, len);
+ while (munlock(addr, len) != 0 && __os_get_errno() == EINTR)
+ ;
#else
COMPQUIET(dbenv, NULL);
#endif
- return (munmap(addr, len) ? __os_get_errno() : 0);
+ {
+ int ret;
+
+ while ((ret = munmap(addr, len)) != 0 &&
+ __os_get_errno() == EINTR)
+ ;
+ return (ret ? __os_get_errno() : 0);
+ }
#else
COMPQUIET(dbenv, NULL);
@@ -331,8 +338,8 @@ __os_map(dbenv, path, fhp, len, is_region, is_rdonly, addrp)
int flags, prot, ret;
/* If the user replaced the map call, call through their interface. */
- if (__db_jump.j_map != NULL)
- return (__db_jump.j_map
+ if (DB_GLOBAL(j_map) != NULL)
+ return (DB_GLOBAL(j_map)
(path, len, is_region, is_rdonly, addrp));
/*
diff --git a/bdb/os/os_method.c b/bdb/os/os_method.c
index 0e2bd394792..04367654efa 100644
--- a/bdb/os/os_method.c
+++ b/bdb/os/os_method.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_method.c,v 11.6 2000/11/15 19:25:39 sue Exp $";
+static const char revid[] = "$Id: os_method.c,v 11.15 2002/07/12 18:56:51 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,191 +16,219 @@ static const char revid[] = "$Id: os_method.c,v 11.6 2000/11/15 19:25:39 sue Exp
#endif
#include "db_int.h"
-#include "os_jump.h"
-
-struct __db_jumptab __db_jump;
+/*
+ * EXTERN: int db_env_set_func_close __P((int (*)(int)));
+ */
int
db_env_set_func_close(func_close)
int (*func_close) __P((int));
{
- __db_jump.j_close = func_close;
+ DB_GLOBAL(j_close) = func_close;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_dirfree __P((void (*)(char **, int)));
+ */
int
db_env_set_func_dirfree(func_dirfree)
void (*func_dirfree) __P((char **, int));
{
- __db_jump.j_dirfree = func_dirfree;
+ DB_GLOBAL(j_dirfree) = func_dirfree;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_dirlist
+ * EXTERN: __P((int (*)(const char *, char ***, int *)));
+ */
int
db_env_set_func_dirlist(func_dirlist)
int (*func_dirlist) __P((const char *, char ***, int *));
{
- __db_jump.j_dirlist = func_dirlist;
+ DB_GLOBAL(j_dirlist) = func_dirlist;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_exists __P((int (*)(const char *, int *)));
+ */
int
db_env_set_func_exists(func_exists)
int (*func_exists) __P((const char *, int *));
{
- __db_jump.j_exists = func_exists;
+ DB_GLOBAL(j_exists) = func_exists;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_free __P((void (*)(void *)));
+ */
int
db_env_set_func_free(func_free)
void (*func_free) __P((void *));
{
- __db_jump.j_free = func_free;
+ DB_GLOBAL(j_free) = func_free;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_fsync __P((int (*)(int)));
+ */
int
db_env_set_func_fsync(func_fsync)
int (*func_fsync) __P((int));
{
- __db_jump.j_fsync = func_fsync;
+ DB_GLOBAL(j_fsync) = func_fsync;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_ioinfo __P((int (*)(const char *,
+ * EXTERN: int, u_int32_t *, u_int32_t *, u_int32_t *)));
+ */
int
db_env_set_func_ioinfo(func_ioinfo)
int (*func_ioinfo)
__P((const char *, int, u_int32_t *, u_int32_t *, u_int32_t *));
{
- __db_jump.j_ioinfo = func_ioinfo;
+ DB_GLOBAL(j_ioinfo) = func_ioinfo;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_malloc __P((void *(*)(size_t)));
+ */
int
db_env_set_func_malloc(func_malloc)
void *(*func_malloc) __P((size_t));
{
- __db_jump.j_malloc = func_malloc;
+ DB_GLOBAL(j_malloc) = func_malloc;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_map
+ * EXTERN: __P((int (*)(char *, size_t, int, int, void **)));
+ */
int
db_env_set_func_map(func_map)
int (*func_map) __P((char *, size_t, int, int, void **));
{
- __db_jump.j_map = func_map;
+ DB_GLOBAL(j_map) = func_map;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_open __P((int (*)(const char *, int, ...)));
+ */
int
db_env_set_func_open(func_open)
int (*func_open) __P((const char *, int, ...));
{
- __db_jump.j_open = func_open;
+ DB_GLOBAL(j_open) = func_open;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_read __P((ssize_t (*)(int, void *, size_t)));
+ */
int
db_env_set_func_read(func_read)
ssize_t (*func_read) __P((int, void *, size_t));
{
- __db_jump.j_read = func_read;
+ DB_GLOBAL(j_read) = func_read;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_realloc __P((void *(*)(void *, size_t)));
+ */
int
db_env_set_func_realloc(func_realloc)
void *(*func_realloc) __P((void *, size_t));
{
- __db_jump.j_realloc = func_realloc;
+ DB_GLOBAL(j_realloc) = func_realloc;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_rename
+ * EXTERN: __P((int (*)(const char *, const char *)));
+ */
int
db_env_set_func_rename(func_rename)
int (*func_rename) __P((const char *, const char *));
{
- __db_jump.j_rename = func_rename;
+ DB_GLOBAL(j_rename) = func_rename;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_seek
+ * EXTERN: __P((int (*)(int, size_t, db_pgno_t, u_int32_t, int, int)));
+ */
int
db_env_set_func_seek(func_seek)
int (*func_seek) __P((int, size_t, db_pgno_t, u_int32_t, int, int));
{
- __db_jump.j_seek = func_seek;
+ DB_GLOBAL(j_seek) = func_seek;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_sleep __P((int (*)(u_long, u_long)));
+ */
int
db_env_set_func_sleep(func_sleep)
int (*func_sleep) __P((u_long, u_long));
{
- __db_jump.j_sleep = func_sleep;
+ DB_GLOBAL(j_sleep) = func_sleep;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_unlink __P((int (*)(const char *)));
+ */
int
db_env_set_func_unlink(func_unlink)
int (*func_unlink) __P((const char *));
{
- __db_jump.j_unlink = func_unlink;
+ DB_GLOBAL(j_unlink) = func_unlink;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_unmap __P((int (*)(void *, size_t)));
+ */
int
db_env_set_func_unmap(func_unmap)
int (*func_unmap) __P((void *, size_t));
{
- __db_jump.j_unmap = func_unmap;
+ DB_GLOBAL(j_unmap) = func_unmap;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_write
+ * EXTERN: __P((ssize_t (*)(int, const void *, size_t)));
+ */
int
db_env_set_func_write(func_write)
ssize_t (*func_write) __P((int, const void *, size_t));
{
- __db_jump.j_write = func_write;
+ DB_GLOBAL(j_write) = func_write;
return (0);
}
+/*
+ * EXTERN: int db_env_set_func_yield __P((int (*)(void)));
+ */
int
db_env_set_func_yield(func_yield)
int (*func_yield) __P((void));
{
- __db_jump.j_yield = func_yield;
- return (0);
-}
-
-int
-db_env_set_pageyield(onoff)
- int onoff;
-{
- DB_GLOBAL(db_pageyield) = onoff;
- return (0);
-}
-
-int
-db_env_set_panicstate(onoff)
- int onoff;
-{
- DB_GLOBAL(db_panic) = onoff;
- return (0);
-}
-
-int
-db_env_set_region_init(onoff)
- int onoff;
-{
- DB_GLOBAL(db_region_init) = onoff;
- return (0);
-}
-
-int
-db_env_set_tas_spins(tas_spins)
- u_int32_t tas_spins;
-{
- DB_GLOBAL(db_tas_spins) = tas_spins;
+ DB_GLOBAL(j_yield) = func_yield;
return (0);
}
diff --git a/bdb/os/os_oflags.c b/bdb/os/os_oflags.c
index fd413bdacbe..f75178de75e 100644
--- a/bdb/os/os_oflags.c
+++ b/bdb/os/os_oflags.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_oflags.c,v 11.6 2000/10/27 20:32:02 dda Exp $";
+static const char revid[] = "$Id: os_oflags.c,v 11.9 2002/01/11 15:53:00 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -72,23 +72,35 @@ __db_omode(perm)
{
int mode;
-#ifndef S_IRUSR
#ifdef DB_WIN32
+#ifndef S_IRUSR
#define S_IRUSR S_IREAD /* R for owner */
+#endif
+#ifndef S_IWUSR
#define S_IWUSR S_IWRITE /* W for owner */
+#endif
+#ifndef S_IRGRP
#define S_IRGRP 0 /* R for group */
+#endif
+#ifndef S_IWGRP
#define S_IWGRP 0 /* W for group */
+#endif
+#ifndef S_IROTH
#define S_IROTH 0 /* R for other */
+#endif
+#ifndef S_IWOTH
#define S_IWOTH 0 /* W for other */
+#endif
#else
+#ifndef S_IRUSR
#define S_IRUSR 0000400 /* R for owner */
#define S_IWUSR 0000200 /* W for owner */
#define S_IRGRP 0000040 /* R for group */
#define S_IWGRP 0000020 /* W for group */
#define S_IROTH 0000004 /* R for other */
#define S_IWOTH 0000002 /* W for other */
-#endif /* DB_WIN32 */
#endif
+#endif /* DB_WIN32 */
mode = 0;
if (perm[0] == 'r')
mode |= S_IRUSR;
diff --git a/bdb/os/os_open.c b/bdb/os/os_open.c
index cdc75cd737b..0a4dbadc6e8 100644
--- a/bdb/os/os_open.c
+++ b/bdb/os/os_open.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_open.c,v 11.21 2001/01/11 18:19:53 bostic Exp $";
+static const char revid[] = "$Id: os_open.c,v 11.37 2002/06/21 20:35:16 sandstro Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -42,6 +42,15 @@ __os_open(dbenv, name, flags, mode, fhp)
oflags = 0;
+#ifdef DIAGNOSTIC
+#define OKFLAGS \
+ (DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_LOG | \
+ DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | DB_OSO_TEMP | \
+ DB_OSO_TRUNC)
+ if ((ret = __db_fchk(dbenv, "__os_open", flags, OKFLAGS)) != 0)
+ return (ret);
+#endif
+
#if defined(O_BINARY)
/*
* If there's a binary-mode open flag, set it, we never want any
@@ -84,6 +93,11 @@ __os_open(dbenv, name, flags, mode, fhp)
if (LF_ISSET(DB_OSO_TRUNC))
oflags |= O_TRUNC;
+#ifdef HAVE_O_DIRECT
+ if (LF_ISSET(DB_OSO_DIRECT))
+ oflags |= O_DIRECT;
+#endif
+
#ifdef HAVE_QNX
if (LF_ISSET(DB_OSO_REGION))
return (__os_region_open(dbenv, name, oflags, mode, fhp));
@@ -92,6 +106,11 @@ __os_open(dbenv, name, flags, mode, fhp)
if ((ret = __os_openhandle(dbenv, name, oflags, mode, fhp)) != 0)
return (ret);
+#ifdef HAVE_DIRECTIO
+ if (LF_ISSET(DB_OSO_DIRECT))
+ (void)directio(fhp->fd, DIRECTIO_ON);
+#endif
+
/*
* Delete any temporary file.
*
@@ -102,8 +121,18 @@ __os_open(dbenv, name, flags, mode, fhp)
* reasonable way to avoid the race (playing signal games isn't worth
* the portability nightmare), so we just live with it.
*/
- if (LF_ISSET(DB_OSO_TEMP))
+ if (LF_ISSET(DB_OSO_TEMP)) {
+#if defined(HAVE_UNLINK_WITH_OPEN_FAILURE) || defined(CONFIG_TEST)
+ if ((ret = __os_strdup(dbenv, name, &fhp->name)) != 0) {
+ (void)__os_closehandle(dbenv, fhp);
+ (void)__os_unlink(dbenv, name);
+ return (ret);
+ }
+ F_SET(fhp, DB_FH_UNLINK);
+#else
(void)__os_unlink(dbenv, name);
+#endif
+ }
return (0);
}
@@ -136,7 +165,7 @@ __os_region_open(dbenv, name, oflags, mode, fhp)
if (fcntl(fhp->fd, F_SETFD, 1) == -1) {
ret = __os_get_errno();
__db_err(dbenv, "fcntl(F_SETFD): %s", strerror(ret));
- __os_closehandle(fhp);
+ __os_closehandle(dbenv, fhp);
} else
#endif
F_SET(fhp, DB_FH_VALID);
@@ -147,7 +176,7 @@ __os_region_open(dbenv, name, oflags, mode, fhp)
*/
err:
if (newname != NULL)
- __os_free(newname, 0);
+ __os_free(dbenv, newname);
return (ret);
}
@@ -155,7 +184,9 @@ err:
* __os_shmname --
* Translate a pathname into a shm_open memory object name.
*
+ * PUBLIC: #ifdef HAVE_QNX
* PUBLIC: int __os_shmname __P((DB_ENV *, const char *, char **));
+ * PUBLIC: #endif
*/
int
__os_shmname(dbenv, name, newnamep)
@@ -206,7 +237,7 @@ __os_shmname(dbenv, name, newnamep)
* If we have a path component, copy and return it.
*/
ret = __os_strdup(dbenv, p, newnamep);
- __os_free(tmpname, 0);
+ __os_free(dbenv, tmpname);
return (ret);
}
@@ -215,11 +246,11 @@ __os_shmname(dbenv, name, newnamep)
* Add a leading slash, and copy the remainder.
*/
size = strlen(tmpname) + 2;
- if ((ret = __os_malloc(dbenv, size, NULL, &p)) != 0)
+ if ((ret = __os_malloc(dbenv, size, &p)) != 0)
return (ret);
p[0] = '/';
memcpy(&p[1], tmpname, size-1);
- __os_free(tmpname, 0);
+ __os_free(dbenv, tmpname);
*newnamep = p;
return (0);
}
diff --git a/bdb/os/os_region.c b/bdb/os/os_region.c
index 1e36fc2cbe0..6529f708b2c 100644
--- a/bdb/os/os_region.c
+++ b/bdb/os/os_region.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_region.c,v 11.9 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: os_region.c,v 11.15 2002/07/12 18:56:51 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,7 +17,6 @@ static const char revid[] = "$Id: os_region.c,v 11.9 2000/11/30 00:58:42 ubell E
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_r_attach --
@@ -70,7 +69,7 @@ __os_r_attach(dbenv, infop, rp)
}
#endif
if ((ret =
- __os_malloc(dbenv, rp->size, NULL, &infop->addr)) != 0)
+ __os_malloc(dbenv, rp->size, &infop->addr)) != 0)
return (ret);
#if defined(UMRW) && !defined(DIAGNOSTIC)
memset(infop->addr, CLEAR_BYTE, rp->size);
@@ -79,8 +78,8 @@ __os_r_attach(dbenv, infop, rp)
}
/* If the user replaced the map call, call through their interface. */
- if (__db_jump.j_map != NULL)
- return (__db_jump.j_map(infop->name,
+ if (DB_GLOBAL(j_map) != NULL)
+ return (DB_GLOBAL(j_map)(infop->name,
rp->size, 1, 0, &infop->addr));
return (__os_r_sysattach(dbenv, infop, rp));
@@ -104,13 +103,13 @@ __os_r_detach(dbenv, infop, destroy)
/* If a region is private, free the memory. */
if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
- __os_free(infop->addr, rp->size);
+ __os_free(dbenv, infop->addr);
return (0);
}
/* If the user replaced the map call, call through their interface. */
- if (__db_jump.j_unmap != NULL)
- return (__db_jump.j_unmap(infop->addr, rp->size));
+ if (DB_GLOBAL(j_unmap) != NULL)
+ return (DB_GLOBAL(j_unmap)(infop->addr, rp->size));
return (__os_r_sysdetach(dbenv, infop, destroy));
}
diff --git a/bdb/os/os_rename.c b/bdb/os/os_rename.c
index 8108bba67d9..2569a9c3186 100644
--- a/bdb/os/os_rename.c
+++ b/bdb/os/os_rename.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_rename.c,v 11.6 2000/04/14 16:56:33 ubell Exp $";
+static const char revid[] = "$Id: os_rename.c,v 11.12 2002/07/12 18:56:52 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,28 +19,29 @@ static const char revid[] = "$Id: os_rename.c,v 11.6 2000/04/14 16:56:33 ubell E
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_rename --
- * Rename a file.
+ * Rename a file. If flags is non-zero, then errors are OK and we
+ * should not output an error message.
*
- * PUBLIC: int __os_rename __P((DB_ENV *, const char *, const char *));
+ * PUBLIC: int __os_rename __P((DB_ENV *,
+ * PUBLIC: const char *, const char *, u_int32_t));
*/
int
-__os_rename(dbenv, old, new)
+__os_rename(dbenv, old, new, flags)
DB_ENV *dbenv;
const char *old, *new;
+ u_int32_t flags;
{
int ret;
- ret = __db_jump.j_rename != NULL ?
- __db_jump.j_rename(old, new) : rename(old, new);
-
- if (ret == -1) {
- ret = __os_get_errno();
- __db_err(dbenv, "Rename %s %s: %s", old, new, strerror(ret));
- }
+ do {
+ ret = DB_GLOBAL(j_rename) != NULL ?
+ DB_GLOBAL(j_rename)(old, new) : rename(old, new);
+ } while (ret != 0 && (ret = __os_get_errno()) == EINTR);
+ if (ret != 0 && flags == 0)
+ __db_err(dbenv, "rename %s %s: %s", old, new, strerror(ret));
return (ret);
}
diff --git a/bdb/os/os_root.c b/bdb/os/os_root.c
index 753285c1be6..cd5bfc352e9 100644
--- a/bdb/os/os_root.c
+++ b/bdb/os/os_root.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_root.c,v 11.4 2000/02/14 03:00:05 bostic Exp $";
+static const char revid[] = "$Id: os_root.c,v 11.6 2002/01/11 15:53:01 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
diff --git a/bdb/os/os_rpath.c b/bdb/os/os_rpath.c
index 75d394ef210..b9ccba01bd5 100644
--- a/bdb/os/os_rpath.c
+++ b/bdb/os/os_rpath.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_rpath.c,v 11.5 2000/06/30 13:40:30 sue Exp $";
+static const char revid[] = "$Id: os_rpath.c,v 11.7 2002/01/11 15:53:01 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
diff --git a/bdb/os/os_rw.c b/bdb/os/os_rw.c
index 7e8e1255d6b..9a79342c7b8 100644
--- a/bdb/os/os_rw.c
+++ b/bdb/os/os_rw.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_rw.c,v 11.15 2000/11/15 19:25:39 sue Exp $";
+static const char revid[] = "$Id: os_rw.c,v 11.24 2002/07/12 18:56:52 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,7 +19,6 @@ static const char revid[] = "$Id: os_rw.c,v 11.15 2000/11/15 19:25:39 sue Exp $"
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_io --
@@ -39,13 +38,13 @@ __os_io(dbenv, db_iop, op, niop)
#if defined(HAVE_PREAD) && defined(HAVE_PWRITE)
switch (op) {
case DB_IO_READ:
- if (__db_jump.j_read != NULL)
+ if (DB_GLOBAL(j_read) != NULL)
goto slow;
*niop = pread(db_iop->fhp->fd, db_iop->buf,
db_iop->bytes, (off_t)db_iop->pgno * db_iop->pagesize);
break;
case DB_IO_WRITE:
- if (__db_jump.j_write != NULL)
+ if (DB_GLOBAL(j_write) != NULL)
goto slow;
*niop = pwrite(db_iop->fhp->fd, db_iop->buf,
db_iop->bytes, (off_t)db_iop->pgno * db_iop->pagesize);
@@ -98,10 +97,11 @@ __os_read(dbenv, fhp, addr, len, nrp)
for (taddr = addr,
offset = 0; offset < len; taddr += nr, offset += nr) {
- if ((nr = __db_jump.j_read != NULL ?
- __db_jump.j_read(fhp->fd, taddr, len - offset) :
+retry: if ((nr = DB_GLOBAL(j_read) != NULL ?
+ DB_GLOBAL(j_read)(fhp->fd, taddr, len - offset) :
read(fhp->fd, taddr, len - offset)) < 0) {
- ret = __os_get_errno();
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
__db_err(dbenv, "read: 0x%x, %lu: %s", taddr,
(u_long)len-offset, strerror(ret));
return (ret);
@@ -134,10 +134,11 @@ __os_write(dbenv, fhp, addr, len, nwp)
for (taddr = addr,
offset = 0; offset < len; taddr += nw, offset += nw)
- if ((nw = __db_jump.j_write != NULL ?
- __db_jump.j_write(fhp->fd, taddr, len - offset) :
+retry: if ((nw = DB_GLOBAL(j_write) != NULL ?
+ DB_GLOBAL(j_write)(fhp->fd, taddr, len - offset) :
write(fhp->fd, taddr, len - offset)) < 0) {
- ret = __os_get_errno();
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
__db_err(dbenv, "write: 0x%x, %lu: %s", taddr,
(u_long)len-offset, strerror(ret));
return (ret);
diff --git a/bdb/os/os_seek.c b/bdb/os/os_seek.c
index 1c4dc2238e1..5b2aa45d5dd 100644
--- a/bdb/os/os_seek.c
+++ b/bdb/os/os_seek.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_seek.c,v 11.12 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: os_seek.c,v 11.18 2002/07/12 18:56:52 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,6 @@ static const char revid[] = "$Id: os_seek.c,v 11.12 2000/11/30 00:58:42 ubell Ex
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_seek --
@@ -56,15 +55,17 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
return (EINVAL);
}
- if (__db_jump.j_seek != NULL)
- ret = __db_jump.j_seek(fhp->fd,
+ if (DB_GLOBAL(j_seek) != NULL)
+ ret = DB_GLOBAL(j_seek)(fhp->fd,
pgsize, pageno, relative, isrewind, whence);
else {
offset = (off_t)pgsize * pageno + relative;
if (isrewind)
offset = -offset;
- ret =
- lseek(fhp->fd, offset, whence) == -1 ? __os_get_errno() : 0;
+ do {
+ ret = lseek(fhp->fd, offset, whence) == -1 ?
+ __os_get_errno() : 0;
+ } while (ret == EINTR);
}
if (ret != 0)
diff --git a/bdb/os/os_sleep.c b/bdb/os/os_sleep.c
index 137cd73b708..42d496dbae7 100644
--- a/bdb/os/os_sleep.c
+++ b/bdb/os/os_sleep.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_sleep.c,v 11.7 2000/04/07 14:26:36 bostic Exp $";
+static const char revid[] = "$Id: os_sleep.c,v 11.15 2002/07/12 18:56:52 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -21,6 +21,7 @@ static const char revid[] = "$Id: os_sleep.c,v 11.7 2000/04/07 14:26:36 bostic E
#ifdef HAVE_VXWORKS
#include <sys/times.h>
#include <time.h>
+#include <selectLib.h>
#else
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
@@ -39,7 +40,6 @@ static const char revid[] = "$Id: os_sleep.c,v 11.7 2000/04/07 14:26:36 bostic E
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_sleep --
@@ -59,8 +59,8 @@ __os_sleep(dbenv, secs, usecs)
for (; usecs >= 1000000; usecs -= 1000000)
++secs;
- if (__db_jump.j_sleep != NULL)
- return (__db_jump.j_sleep(secs, usecs));
+ if (DB_GLOBAL(j_sleep) != NULL)
+ return (DB_GLOBAL(j_sleep)(secs, usecs));
/*
* It's important that we yield the processor here so that other
@@ -68,7 +68,10 @@ __os_sleep(dbenv, secs, usecs)
*/
t.tv_sec = secs;
t.tv_usec = usecs;
- ret = select(0, NULL, NULL, NULL, &t) == -1 ? __os_get_errno() : 0;
+ do {
+ ret = select(0, NULL, NULL, NULL, &t) == -1 ?
+ __os_get_errno() : 0;
+ } while (ret == EINTR);
if (ret != 0)
__db_err(dbenv, "select: %s", strerror(ret));
diff --git a/bdb/os/os_spin.c b/bdb/os/os_spin.c
index b0800b98830..fb36977cb44 100644
--- a/bdb/os/os_spin.c
+++ b/bdb/os/os_spin.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_spin.c,v 11.5 2000/03/30 01:46:42 ubell Exp $";
+static const char revid[] = "$Id: os_spin.c,v 11.13 2002/08/07 02:02:07 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -22,9 +22,10 @@ static const char revid[] = "$Id: os_spin.c,v 11.5 2000/03/30 01:46:42 ubell Exp
#endif
#include "db_int.h"
-#include "os_jump.h"
#if defined(HAVE_PSTAT_GETDYNAMIC)
+static int __os_pstat_getdynamic __P((void));
+
/*
* __os_pstat_getdynamic --
* HP/UX.
@@ -40,6 +41,8 @@ __os_pstat_getdynamic()
#endif
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+static int __os_sysconf __P((void));
+
/*
* __os_sysconf --
* Solaris, Linux.
@@ -47,9 +50,9 @@ __os_pstat_getdynamic()
static int
__os_sysconf()
{
- int nproc;
+ long nproc;
- return ((nproc = sysconf(_SC_NPROCESSORS_ONLN)) > 1 ? nproc : 1);
+ return ((nproc = sysconf(_SC_NPROCESSORS_ONLN)) > 1 ? (int)nproc : 1);
}
#endif
@@ -57,10 +60,11 @@ __os_sysconf()
* __os_spin --
* Return the number of default spins before blocking.
*
- * PUBLIC: int __os_spin __P((void));
+ * PUBLIC: int __os_spin __P((DB_ENV *));
*/
int
-__os_spin()
+__os_spin(dbenv)
+ DB_ENV *dbenv;
{
/*
* If the application specified a value or we've already figured it
@@ -71,25 +75,25 @@ __os_spin()
* it can be expensive (e.g., requiring multiple filesystem accesses
* under Debian Linux).
*/
- if (DB_GLOBAL(db_tas_spins) != 0)
- return (DB_GLOBAL(db_tas_spins));
+ if (dbenv->tas_spins != 0)
+ return (dbenv->tas_spins);
- DB_GLOBAL(db_tas_spins) = 1;
+ dbenv->tas_spins = 1;
#if defined(HAVE_PSTAT_GETDYNAMIC)
- DB_GLOBAL(db_tas_spins) = __os_pstat_getdynamic();
+ dbenv->tas_spins = __os_pstat_getdynamic();
#endif
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
- DB_GLOBAL(db_tas_spins) = __os_sysconf();
+ dbenv->tas_spins = __os_sysconf();
#endif
/*
* Spin 50 times per processor, we have anecdotal evidence that this
* is a reasonable value.
*/
- if (DB_GLOBAL(db_tas_spins) != 1)
- DB_GLOBAL(db_tas_spins) *= 50;
+ if (dbenv->tas_spins != 1)
+ dbenv->tas_spins *= 50;
- return (DB_GLOBAL(db_tas_spins));
+ return (dbenv->tas_spins);
}
/*
@@ -103,7 +107,7 @@ __os_yield(dbenv, usecs)
DB_ENV *dbenv;
u_long usecs;
{
- if (__db_jump.j_yield != NULL && __db_jump.j_yield() == 0)
+ if (DB_GLOBAL(j_yield) != NULL && DB_GLOBAL(j_yield)() == 0)
return;
- __os_sleep(dbenv, 0, usecs);
+ (void)__os_sleep(dbenv, 0, usecs);
}
diff --git a/bdb/os/os_stat.c b/bdb/os/os_stat.c
index 1590e8ecd77..c3510e36f5d 100644
--- a/bdb/os/os_stat.c
+++ b/bdb/os/os_stat.c
@@ -1,24 +1,24 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_stat.c,v 11.8 2000/10/27 20:32:02 dda Exp $";
+static const char revid[] = "$Id: os_stat.c,v 11.20 2002/07/12 18:56:53 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <sys/stat.h>
+
#include <string.h>
#endif
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_exists --
@@ -31,20 +31,29 @@ __os_exists(path, isdirp)
const char *path;
int *isdirp;
{
+ int ret;
struct stat sb;
- if (__db_jump.j_exists != NULL)
- return (__db_jump.j_exists(path, isdirp));
+ if (DB_GLOBAL(j_exists) != NULL)
+ return (DB_GLOBAL(j_exists)(path, isdirp));
+ do {
+ ret =
#ifdef HAVE_VXWORKS
- if (stat((char *)path, &sb) != 0)
+ stat((char *)path, &sb);
#else
- if (stat(path, &sb) != 0)
+ stat(path, &sb);
#endif
- return (__os_get_errno());
+ if (ret != 0)
+ ret = __os_get_errno();
+ } while (ret == EINTR);
+
+ if (ret != 0)
+ return (ret);
#if !defined(S_ISDIR) || defined(STAT_MACROS_BROKEN)
-#ifdef DB_WIN32
+#undef S_ISDIR
+#ifdef _S_IFDIR
#define S_ISDIR(m) (_S_IFDIR & (m))
#else
#define S_ISDIR(m) (((m) & 0170000) == 0040000)
@@ -74,21 +83,23 @@ __os_ioinfo(dbenv, path, fhp, mbytesp, bytesp, iosizep)
int ret;
struct stat sb;
- if (__db_jump.j_ioinfo != NULL)
- return (__db_jump.j_ioinfo(path,
+ if (DB_GLOBAL(j_ioinfo) != NULL)
+ return (DB_GLOBAL(j_ioinfo)(path,
fhp->fd, mbytesp, bytesp, iosizep));
+retry:
if (fstat(fhp->fd, &sb) == -1) {
- ret = __os_get_errno();
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
__db_err(dbenv, "fstat: %s", strerror(ret));
return (ret);
}
/* Return the size of the file. */
if (mbytesp != NULL)
- *mbytesp = sb.st_size / MEGABYTE;
+ *mbytesp = (u_int32_t)(sb.st_size / MEGABYTE);
if (bytesp != NULL)
- *bytesp = sb.st_size % MEGABYTE;
+ *bytesp = (u_int32_t)(sb.st_size % MEGABYTE);
/*
* Return the underlying filesystem blocksize, if available.
@@ -97,7 +108,7 @@ __os_ioinfo(dbenv, path, fhp, mbytesp, bytesp, iosizep)
* Check for a 0 size -- the HP MPE/iX architecture has st_blksize,
* but it's always 0.
*/
-#ifdef HAVE_ST_BLKSIZE
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
if (iosizep != NULL && (*iosizep = sb.st_blksize) == 0)
*iosizep = DB_DEF_IOSIZE;
#else
diff --git a/bdb/os/os_tmpdir.c b/bdb/os/os_tmpdir.c
index 0dff5c5b7f0..94645af5e71 100644
--- a/bdb/os/os_tmpdir.c
+++ b/bdb/os/os_tmpdir.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_tmpdir.c,v 11.16 2001/01/08 20:42:06 bostic Exp $";
+static const char revid[] = "$Id: os_tmpdir.c,v 11.19 2002/01/11 15:53:02 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -37,6 +37,8 @@ __os_tmpdir(dbenv, flags)
DB_ENV *dbenv;
u_int32_t flags;
{
+ int isdir;
+
/*
* !!!
* Don't change this to:
@@ -96,7 +98,7 @@ __os_tmpdir(dbenv, flags)
#endif
#ifdef DB_WIN32
/* Get the path to the temporary directory. */
- {int isdir, len;
+ {int len;
char *eos, temp[MAXPATHLEN + 1];
if ((len = GetTempPath(sizeof(temp) - 1, temp)) > 2) {
@@ -113,7 +115,7 @@ __os_tmpdir(dbenv, flags)
/* Step through the static list looking for a possibility. */
for (lp = list; *lp != NULL; ++lp)
- if (__os_exists(*lp, NULL) == 0)
+ if (__os_exists(*lp, &isdir) == 0 && isdir != 0)
return (__os_strdup(dbenv, *lp, &dbenv->db_tmp_dir));
return (0);
}
diff --git a/bdb/os/os_unlink.c b/bdb/os/os_unlink.c
index 56c401fe342..28b03afd1aa 100644
--- a/bdb/os/os_unlink.c
+++ b/bdb/os/os_unlink.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_unlink.c,v 11.13 2000/11/30 00:58:42 ubell Exp $";
+static const char revid[] = "$Id: os_unlink.c,v 11.24 2002/07/12 18:56:53 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,7 +19,42 @@ static const char revid[] = "$Id: os_unlink.c,v 11.13 2000/11/30 00:58:42 ubell
#endif
#include "db_int.h"
-#include "os_jump.h"
+
+/*
+ * __os_region_unlink --
+ * Remove a shared memory object file.
+ *
+ * PUBLIC: int __os_region_unlink __P((DB_ENV *, const char *));
+ */
+int
+__os_region_unlink(dbenv, path)
+ DB_ENV *dbenv;
+ const char *path;
+{
+#ifdef HAVE_QNX
+ int ret;
+ char *newname;
+
+ if ((ret = __os_shmname(dbenv, path, &newname)) != 0)
+ goto err;
+
+ if ((ret = shm_unlink(newname)) != 0) {
+ ret = __os_get_errno();
+ if (ret != ENOENT)
+ __db_err(dbenv, "shm_unlink: %s: %s",
+ newname, strerror(ret));
+ }
+err:
+ if (newname != NULL)
+ __os_free(dbenv, newname);
+ return (ret);
+#else
+ if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
+ (void)__db_overwrite(dbenv, path);
+
+ return (__os_unlink(dbenv, path));
+#endif
+}
/*
* __os_unlink --
@@ -34,15 +69,16 @@ __os_unlink(dbenv, path)
{
int ret;
- ret = __db_jump.j_unlink != NULL ?
- __db_jump.j_unlink(path) :
+retry: ret = DB_GLOBAL(j_unlink) != NULL ?
+ DB_GLOBAL(j_unlink)(path) :
#ifdef HAVE_VXWORKS
unlink((char *)path);
#else
unlink(path);
#endif
if (ret == -1) {
- ret = __os_get_errno();
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
/*
* XXX
* We really shouldn't be looking at this value ourselves,
@@ -66,41 +102,8 @@ __os_unlink(dbenv, path)
/* FALLTHROUGH */
#endif
if (ret != ENOENT)
- __db_err(dbenv, "Unlink: %s: %s", path, strerror(ret));
+ __db_err(dbenv, "unlink: %s: %s", path, strerror(ret));
}
return (ret);
}
-
-/*
- * __os_region_unlink --
- * Remove a shared memory object file.
- *
- * PUBLIC: int __os_region_unlink __P((DB_ENV *, const char *));
- */
-int
-__os_region_unlink(dbenv, path)
- DB_ENV *dbenv;
- const char *path;
-{
-#ifdef HAVE_QNX
- int ret;
- char *newname;
-
- if ((ret = __os_shmname(dbenv, path, &newname)) != 0)
- goto err;
-
- if ((ret = shm_unlink(newname)) != 0) {
- ret = __os_get_errno();
- if (ret != ENOENT)
- __db_err(dbenv, "Shm_unlink: %s: %s",
- newname, strerror(ret));
- }
-err:
- if (newname != NULL)
- __os_free(newname, 0);
- return (ret);
-#else
- return (__os_unlink(dbenv, path));
-#endif
-}
diff --git a/bdb/os_vxworks/os_abs.c b/bdb/os_vxworks/os_abs.c
deleted file mode 100644
index 162a556d3fa..00000000000
--- a/bdb/os_vxworks/os_abs.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997, 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: os_abs.c,v 1.4 2000/08/09 19:09:48 sue Exp $";
-#endif /* not lint */
-
-#include "db_int.h"
-#include "iosLib.h"
-
-/*
- * __os_abspath --
- * Return if a path is an absolute path.
- */
-int
-__os_abspath(path)
- const char *path;
-{
- DEV_HDR *dummy;
- char *ptail;
-
- /*
- * VxWorks devices can be rooted at any name at all.
- * Use iosDevFind() to see if name matches any of our devices.
- */
- if ((dummy = iosDevFind((char *)path, &ptail)) == NULL)
- return (0);
- /*
- * If the routine used the default device, then we are not
- * an abs path.
- */
- if (ptail == path)
- return (0);
- /*
- * If the path starts with a '/', then we are an absolute path,
- * using the host machine, otherwise we are not.
- */
- return (path[0] == '/');
-}
diff --git a/bdb/os_vxworks/os_finit.c b/bdb/os_vxworks/os_finit.c
deleted file mode 100644
index 305f52f0996..00000000000
--- a/bdb/os_vxworks/os_finit.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: os_finit.c,v 1.1 2000/06/21 20:05:18 sue Exp $";
-#endif /* not lint */
-
-#include "db_int.h"
-
-/*
- * __os_fpinit --
- * Initialize a page in a regular file.
- *
- * PUBLIC: int __os_fpinit __P((DB_ENV *, DB_FH *, db_pgno_t, int, int));
- */
-int
-__os_fpinit(dbenv, fhp, pgno, pagecount, pagesize)
- DB_ENV *dbenv;
- DB_FH *fhp;
- db_pgno_t pgno;
- int pagecount, pagesize;
-{
- size_t nw, totalbytes, curbytes;
- int ret;
- char buf[1024];
-
- /*
- * Some VxWorks FS drivers do not zero-fill pages that were never
- * explicitly written to the file, they give you random garbage,
- * and that breaks DB.
- */
- if ((ret = __os_seek(dbenv,
- fhp, pagesize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
- return (ret);
-
- memset(buf, 0, sizeof(buf));
- totalbytes = pagecount * pagesize;
-
- while (totalbytes > 0) {
- if (totalbytes > sizeof(buf))
- curbytes = sizeof(buf);
- else
- curbytes = totalbytes;
- if ((ret = __os_write(dbenv, fhp, buf, curbytes, &nw)) != 0)
- return (ret);
- if (nw != curbytes)
- return (EIO);
- totalbytes -= curbytes;
- }
- return (0);
-}
diff --git a/bdb/os_vxworks/os_map.c b/bdb/os_vxworks/os_map.c
deleted file mode 100644
index 7397995d1d1..00000000000
--- a/bdb/os_vxworks/os_map.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1998, 1999, 2000
- * Sleepycat Software. All rights reserved.
- *
- * This code is derived from software contributed to Sleepycat Software by
- * Frederick G.M. Roeber of Netscape Communications Corp.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: os_map.c,v 1.14 2000/12/04 19:01:43 sue Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-#include <string.h>
-#endif
-
-#include "db_int.h"
-#include "common_ext.h"
-
-/*
- * DB uses memory-mapped files for two things:
- * faster access of read-only databases, and
- * shared memory for process synchronization and locking.
- * The code carefully does not mix the two uses. The first-case uses are
- * actually written such that memory-mapping isn't really required -- it's
- * merely a convenience -- so we don't have to worry much about it. In the
- * second case, it's solely used as a shared memory mechanism, so that's
- * all we have to replace.
- *
- * All memory in VxWorks is shared, and a task can allocate memory and keep
- * notes. So I merely have to allocate memory, remember the "filename" for
- * that memory, and issue small-integer segment IDs which index the list of
- * these shared-memory segments. Subsequent opens are checked against the
- * list of already open segments.
- */
-typedef struct {
- void *segment; /* Segment address. */
- u_int32_t size; /* Segment size. */
- char *name; /* Segment name. */
- long segid; /* Segment ID. */
-} os_segdata_t;
-
-static os_segdata_t *__os_segdata; /* Segment table. */
-static int __os_segdata_size; /* Segment table size. */
-
-#define OS_SEGDATA_STARTING_SIZE 16
-#define OS_SEGDATA_INCREMENT 16
-
-static int __os_segdata_allocate
- __P((DB_ENV *, const char *, REGINFO *, REGION *));
-static int __os_segdata_find_byname
- __P((DB_ENV *, const char *, REGINFO *, REGION *));
-static int __os_segdata_init __P((DB_ENV *));
-static int __os_segdata_new __P((DB_ENV *, int *));
-static int __os_segdata_release __P((DB_ENV *, REGION *, int));
-
-/*
- * __os_r_sysattach --
- * Create/join a shared memory region.
- *
- * PUBLIC: int __os_r_sysattach __P((DB_ENV *, REGINFO *, REGION *));
- */
-int
-__os_r_sysattach(dbenv, infop, rp)
- DB_ENV *dbenv;
- REGINFO *infop;
- REGION *rp;
-{
- int ret;
-
- if (__os_segdata == NULL)
- __os_segdata_init(dbenv);
-
- DB_BEGIN_SINGLE_THREAD;
-
- /* Try to find an already existing segment. */
- ret = __os_segdata_find_byname(dbenv, infop->name, infop, rp);
-
- /*
- * If we are trying to join a region, it is easy, either we
- * found it and we return, or we didn't find it and we return
- * an error that it doesn't exist.
- */
- if (!F_ISSET(infop, REGION_CREATE)) {
- if (ret != 0) {
- __db_err(dbenv, "segment %s does not exist",
- infop->name);
- ret = EAGAIN;
- }
- goto out;
- }
-
- /*
- * If we get here, we are trying to create the region.
- * There are several things to consider:
- * - if we have an error (not a found or not-found value), return.
- * - they better have shm_key set.
- * - if the region is already there (ret == 0 from above),
- * assume the application crashed and we're restarting.
- * Delete the old region.
- * - try to create the region.
- */
- if (ret != 0 && ret != ENOENT)
- goto out;
-
- if (dbenv->shm_key == INVALID_REGION_SEGID) {
- __db_err(dbenv, "no base shared memory ID specified");
- ret = EAGAIN;
- goto out;
- }
- if (ret == 0 && __os_segdata_release(dbenv, rp, 1) != 0) {
- __db_err(dbenv,
- "key: %ld: shared memory region already exists",
- dbenv->shm_key + (infop->id - 1));
- ret = EAGAIN;
- goto out;
- }
-
- ret = __os_segdata_allocate(dbenv, infop->name, infop, rp);
-out:
- DB_END_SINGLE_THREAD;
- return (ret);
-}
-
-/*
- * __os_r_sysdetach --
- * Detach from a shared region.
- *
- * PUBLIC: int __os_r_sysdetach __P((DB_ENV *, REGINFO *, int));
- */
-int
-__os_r_sysdetach(dbenv, infop, destroy)
- DB_ENV *dbenv;
- REGINFO *infop;
- int destroy;
-{
- /*
- * If just detaching, there is no mapping to discard.
- * If destroying, remove the region.
- */
- if (destroy)
- return (__os_segdata_release(dbenv, infop->rp, 0));
- return (0);
-}
-
-/*
- * __os_mapfile --
- * Map in a shared memory file.
- *
- * PUBLIC: int __os_mapfile __P((DB_ENV *,
- * PUBLIC: char *, DB_FH *, size_t, int, void **));
- */
-int
-__os_mapfile(dbenv, path, fhp, len, is_rdonly, addrp)
- DB_ENV *dbenv;
- char *path;
- DB_FH *fhp;
- int is_rdonly;
- size_t len;
- void **addrp;
-{
- /* We cannot map in regular files in VxWorks. */
- COMPQUIET(dbenv, NULL);
- COMPQUIET(path, NULL);
- COMPQUIET(fhp, NULL);
- COMPQUIET(is_rdonly, 0);
- COMPQUIET(len, 0);
- COMPQUIET(addrp, NULL);
- return (EINVAL);
-}
-
-/*
- * __os_unmapfile --
- * Unmap the shared memory file.
- *
- * PUBLIC: int __os_unmapfile __P((DB_ENV *, void *, size_t));
- */
-int
-__os_unmapfile(dbenv, addr, len)
- DB_ENV *dbenv;
- void *addr;
- size_t len;
-{
- /* We cannot map in regular files in VxWorks. */
- COMPQUIET(addr, NULL);
- COMPQUIET(len, 0);
- return (EINVAL);
-}
-
-/*
- * __os_segdata_init --
- * Initializes the library's table of shared memory segments.
- * Called once on the first time through __os_segdata_new().
- */
-static int
-__os_segdata_init(dbenv)
- DB_ENV *dbenv;
-{
- int ret;
-
- if (__os_segdata != NULL) {
- __db_err(dbenv, "shared memory segment already exists");
- return (EEXIST);
- }
-
- /*
- * The lock init call returns a locked lock.
- */
- DB_BEGIN_SINGLE_THREAD;
- __os_segdata_size = OS_SEGDATA_STARTING_SIZE;
- ret = __os_calloc(dbenv,
- __os_segdata_size, sizeof(os_segdata_t), &__os_segdata);
- DB_END_SINGLE_THREAD;
- return (ret);
-}
-
-/*
- * __os_segdata_destroy --
- * Destroys the library's table of shared memory segments. It also
- * frees all linked data: the segments themselves, and their names.
- * Currently not called. This function should be called if the
- * user creates a function to unload or shutdown.
- *
- * PUBLIC: int __os_segdata_destroy __P((void));
- */
-int
-__os_segdata_destroy()
-{
- os_segdata_t *p;
- int i;
-
- if (__os_segdata == NULL)
- return (0);
-
- DB_BEGIN_SINGLE_THREAD;
- for (i = 0; i < __os_segdata_size; i++) {
- p = &__os_segdata[i];
- if (p->name != NULL) {
- __os_freestr(p->name);
- p->name = NULL;
- }
- if (p->segment != NULL) {
- __os_free(p->segment, p->size);
- p->segment = NULL;
- }
- p->size = 0;
- }
-
- __os_free(__os_segdata, __os_segdata_size * sizeof(os_segdata_t));
- __os_segdata = NULL;
- __os_segdata_size = 0;
- DB_END_SINGLE_THREAD;
-
- return (0);
-}
-
-/*
- * __os_segdata_allocate --
- * Creates a new segment of the specified size, optionally with the
- * specified name.
- *
- * Assumes it is called with the SEGDATA lock taken.
- */
-static int
-__os_segdata_allocate(dbenv, name, infop, rp)
- DB_ENV *dbenv;
- const char *name;
- REGINFO *infop;
- REGION *rp;
-{
- os_segdata_t *p;
- int id, ret;
-
- if ((ret = __os_segdata_new(dbenv, &id)) != 0)
- return (ret);
-
- p = &__os_segdata[id];
- if ((ret = __os_calloc(dbenv, 1, rp->size, &p->segment)) != 0)
- return (ret);
- if ((ret = __os_strdup(dbenv, name, &p->name)) != 0) {
- __os_free(p->segment, rp->size);
- p->segment = NULL;
- return (ret);
- }
- p->size = rp->size;
- p->segid = dbenv->shm_key + infop->id - 1;
-
- infop->addr = p->segment;
- rp->segid = id;
-
- return (0);
-}
-
-/*
- * __os_segdata_new --
- * Finds a new segdata slot. Does not initialise it, so the fd returned
- * is only valid until you call this again.
- *
- * Assumes it is called with the SEGDATA lock taken.
- */
-static int
-__os_segdata_new(dbenv, segidp)
- DB_ENV *dbenv;
- int *segidp;
-{
- os_segdata_t *p;
- int i, newsize, ret;
-
- if (__os_segdata == NULL) {
- __db_err(dbenv, "shared memory segment not initialized");
- return (EAGAIN);
- }
-
- for (i = 0; i < __os_segdata_size; i++) {
- p = &__os_segdata[i];
- if (p->segment == NULL) {
- *segidp = i;
- return (0);
- }
- }
-
- /*
- * No more free slots, expand.
- */
- newsize = __os_segdata_size + OS_SEGDATA_INCREMENT;
- if ((ret = __os_realloc(dbenv, newsize * sizeof(os_segdata_t),
- NULL, &__os_segdata)) != 0)
- return (ret);
- memset(&__os_segdata[__os_segdata_size],
- 0, OS_SEGDATA_INCREMENT * sizeof(os_segdata_t));
-
- *segidp = __os_segdata_size;
- __os_segdata_size = newsize;
-
- return (0);
-}
-
-/*
- * __os_segdata_find_byname --
- * Finds a segment by its name and shm_key.
- *
- * Assumes it is called with the SEGDATA lock taken.
- *
- * PUBLIC: __os_segdata_find_byname
- * PUBLIC: __P((DB_ENV *, const char *, REGINFO *, REGION *));
- */
-static int
-__os_segdata_find_byname(dbenv, name, infop, rp)
- DB_ENV *dbenv;
- const char *name;
- REGINFO *infop;
- REGION *rp;
-{
- os_segdata_t *p;
- long segid;
- int i;
-
- if (__os_segdata == NULL) {
- __db_err(dbenv, "shared memory segment not initialized");
- return (EAGAIN);
- }
-
- if (name == NULL) {
- __db_err(dbenv, "no segment name given");
- return (EAGAIN);
- }
-
- /*
- * If we are creating the region, compute the segid.
- * If we are joining the region, we use the segid in the
- * index we are given.
- */
- if (F_ISSET(infop, REGION_CREATE))
- segid = dbenv->shm_key + (infop->id - 1);
- else {
- if (rp->segid >= __os_segdata_size ||
- rp->segid == INVALID_REGION_SEGID) {
- __db_err(dbenv, "Invalid segment id given");
- return (EAGAIN);
- }
- segid = __os_segdata[rp->segid].segid;
- }
- for (i = 0; i < __os_segdata_size; i++) {
- p = &__os_segdata[i];
- if (p->name != NULL && strcmp(name, p->name) == 0 &&
- p->segid == segid) {
- infop->addr = p->segment;
- rp->segid = i;
- return (0);
- }
- }
- return (ENOENT);
-}
-
-/*
- * __os_segdata_release --
- * Free a segdata entry.
- */
-static int
-__os_segdata_release(dbenv, rp, is_locked)
- DB_ENV *dbenv;
- REGION *rp;
- int is_locked;
-{
- os_segdata_t *p;
-
- if (__os_segdata == NULL) {
- __db_err(dbenv, "shared memory segment not initialized");
- return (EAGAIN);
- }
-
- if (rp->segid < 0 || rp->segid >= __os_segdata_size) {
- __db_err(dbenv, "segment id %ld out of range", rp->segid);
- return (EINVAL);
- }
-
- if (is_locked == 0)
- DB_BEGIN_SINGLE_THREAD;
- p = &__os_segdata[rp->segid];
- if (p->name != NULL) {
- __os_freestr(p->name);
- p->name = NULL;
- }
- if (p->segment != NULL) {
- __os_free(p->segment, p->size);
- p->segment = NULL;
- }
- p->size = 0;
- if (is_locked == 0)
- DB_END_SINGLE_THREAD;
-
- /* Any shrink-table logic could go here */
-
- return (0);
-}
diff --git a/bdb/os_vxworks/os_vx_abs.c b/bdb/os_vxworks/os_vx_abs.c
new file mode 100644
index 00000000000..93e9be7269b
--- /dev/null
+++ b/bdb/os_vxworks/os_vx_abs.c
@@ -0,0 +1,45 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_vx_abs.c,v 1.7 2002/01/11 15:53:02 bostic Exp $";
+#endif /* not lint */
+
+#include "db_int.h"
+#include "iosLib.h"
+
+/*
+ * __os_abspath --
+ * Return if a path is an absolute path.
+ */
+int
+__os_abspath(path)
+ const char *path;
+{
+ DEV_HDR *dummy;
+ char *ptail;
+
+ /*
+ * VxWorks devices can be rooted at any name at all.
+ * Use iosDevFind() to see if name matches any of our devices.
+ */
+ if ((dummy = iosDevFind((char *)path, &ptail)) == NULL)
+ return (0);
+ /*
+ * If the routine used a device, then ptail points to the
+ * rest and we are an abs path.
+ */
+ if (ptail != path)
+ return (1);
+ /*
+ * If the path starts with a '/', then we are an absolute path,
+ * using the host machine, otherwise we are not.
+ */
+ return (path[0] == '/');
+}
diff --git a/bdb/os_vxworks/os_vx_config.c b/bdb/os_vxworks/os_vx_config.c
new file mode 100644
index 00000000000..810983b38ff
--- /dev/null
+++ b/bdb/os_vxworks/os_vx_config.c
@@ -0,0 +1,31 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_vx_config.c,v 1.4 2002/01/11 15:53:03 bostic Exp $";
+#endif /* not lint */
+
+#include "db_int.h"
+
+/*
+ * __os_fs_notzero --
+ * Return 1 if allocated filesystem blocks are not zeroed.
+ *
+ * PUBLIC: int __os_fs_notzero __P((void));
+ */
+int
+__os_fs_notzero()
+{
+ /*
+ * Some VxWorks FS drivers do not zero-fill pages that were never
+ * explicitly written to the file, they give you random garbage,
+ * and that breaks Berkeley DB.
+ */
+ return (1);
+}
diff --git a/bdb/os_vxworks/os_vx_map.c b/bdb/os_vxworks/os_vx_map.c
new file mode 100644
index 00000000000..8ad4f0765ce
--- /dev/null
+++ b/bdb/os_vxworks/os_vx_map.c
@@ -0,0 +1,441 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * This code is derived from software contributed to Sleepycat Software by
+ * Frederick G.M. Roeber of Netscape Communications Corp.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_vx_map.c,v 1.21 2002/03/06 19:36:58 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * DB uses memory-mapped files for two things:
+ * faster access of read-only databases, and
+ * shared memory for process synchronization and locking.
+ * The code carefully does not mix the two uses. The first-case uses are
+ * actually written such that memory-mapping isn't really required -- it's
+ * merely a convenience -- so we don't have to worry much about it. In the
+ * second case, it's solely used as a shared memory mechanism, so that's
+ * all we have to replace.
+ *
+ * All memory in VxWorks is shared, and a task can allocate memory and keep
+ * notes. So I merely have to allocate memory, remember the "filename" for
+ * that memory, and issue small-integer segment IDs which index the list of
+ * these shared-memory segments. Subsequent opens are checked against the
+ * list of already open segments.
+ */
+typedef struct {
+ void *segment; /* Segment address. */
+ u_int32_t size; /* Segment size. */
+ char *name; /* Segment name. */
+ long segid; /* Segment ID. */
+} os_segdata_t;
+
+static os_segdata_t *__os_segdata; /* Segment table. */
+static int __os_segdata_size; /* Segment table size. */
+
+#define OS_SEGDATA_STARTING_SIZE 16
+#define OS_SEGDATA_INCREMENT 16
+
+static int __os_segdata_allocate
+ __P((DB_ENV *, const char *, REGINFO *, REGION *));
+static int __os_segdata_find_byname
+ __P((DB_ENV *, const char *, REGINFO *, REGION *));
+static int __os_segdata_init __P((DB_ENV *));
+static int __os_segdata_new __P((DB_ENV *, int *));
+static int __os_segdata_release __P((DB_ENV *, REGION *, int));
+
+/*
+ * __os_r_sysattach --
+ * Create/join a shared memory region.
+ *
+ * PUBLIC: int __os_r_sysattach __P((DB_ENV *, REGINFO *, REGION *));
+ */
+int
+__os_r_sysattach(dbenv, infop, rp)
+ DB_ENV *dbenv;
+ REGINFO *infop;
+ REGION *rp;
+{
+ int ret;
+
+ if (__os_segdata == NULL)
+ __os_segdata_init(dbenv);
+
+ DB_BEGIN_SINGLE_THREAD;
+
+ /* Try to find an already existing segment. */
+ ret = __os_segdata_find_byname(dbenv, infop->name, infop, rp);
+
+ /*
+ * If we are trying to join a region, it is easy, either we
+ * found it and we return, or we didn't find it and we return
+ * an error that it doesn't exist.
+ */
+ if (!F_ISSET(infop, REGION_CREATE)) {
+ if (ret != 0) {
+ __db_err(dbenv, "segment %s does not exist",
+ infop->name);
+ ret = EAGAIN;
+ }
+ goto out;
+ }
+
+ /*
+ * If we get here, we are trying to create the region.
+ * There are several things to consider:
+ * - if we have an error (not a found or not-found value), return.
+ * - they better have shm_key set.
+ * - if the region is already there (ret == 0 from above),
+ * assume the application crashed and we're restarting.
+ * Delete the old region.
+ * - try to create the region.
+ */
+ if (ret != 0 && ret != ENOENT)
+ goto out;
+
+ if (dbenv->shm_key == INVALID_REGION_SEGID) {
+ __db_err(dbenv, "no base shared memory ID specified");
+ ret = EAGAIN;
+ goto out;
+ }
+ if (ret == 0 && __os_segdata_release(dbenv, rp, 1) != 0) {
+ __db_err(dbenv,
+ "key: %ld: shared memory region already exists",
+ dbenv->shm_key + (infop->id - 1));
+ ret = EAGAIN;
+ goto out;
+ }
+
+ ret = __os_segdata_allocate(dbenv, infop->name, infop, rp);
+out:
+ DB_END_SINGLE_THREAD;
+ return (ret);
+}
+
+/*
+ * __os_r_sysdetach --
+ * Detach from a shared region.
+ *
+ * PUBLIC: int __os_r_sysdetach __P((DB_ENV *, REGINFO *, int));
+ */
+int
+__os_r_sysdetach(dbenv, infop, destroy)
+ DB_ENV *dbenv;
+ REGINFO *infop;
+ int destroy;
+{
+ /*
+ * If just detaching, there is no mapping to discard.
+ * If destroying, remove the region.
+ */
+ if (destroy)
+ return (__os_segdata_release(dbenv, infop->rp, 0));
+ return (0);
+}
+
+/*
+ * __os_mapfile --
+ * Map in a shared memory file.
+ *
+ * PUBLIC: int __os_mapfile __P((DB_ENV *,
+ * PUBLIC: char *, DB_FH *, size_t, int, void **));
+ */
+int
+__os_mapfile(dbenv, path, fhp, len, is_rdonly, addrp)
+ DB_ENV *dbenv;
+ char *path;
+ DB_FH *fhp;
+ int is_rdonly;
+ size_t len;
+ void **addrp;
+{
+ /* We cannot map in regular files in VxWorks. */
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(path, NULL);
+ COMPQUIET(fhp, NULL);
+ COMPQUIET(is_rdonly, 0);
+ COMPQUIET(len, 0);
+ COMPQUIET(addrp, NULL);
+ return (EINVAL);
+}
+
+/*
+ * __os_unmapfile --
+ * Unmap the shared memory file.
+ *
+ * PUBLIC: int __os_unmapfile __P((DB_ENV *, void *, size_t));
+ */
+int
+__os_unmapfile(dbenv, addr, len)
+ DB_ENV *dbenv;
+ void *addr;
+ size_t len;
+{
+ /* We cannot map in regular files in VxWorks. */
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(addr, NULL);
+ COMPQUIET(len, 0);
+ return (EINVAL);
+}
+
+/*
+ * __os_segdata_init --
+ * Initializes the library's table of shared memory segments.
+ * Called once on the first time through __os_segdata_new().
+ */
+static int
+__os_segdata_init(dbenv)
+ DB_ENV *dbenv;
+{
+ int ret;
+
+ if (__os_segdata != NULL) {
+ __db_err(dbenv, "shared memory segment already exists");
+ return (EEXIST);
+ }
+
+ /*
+ * The lock init call returns a locked lock.
+ */
+ DB_BEGIN_SINGLE_THREAD;
+ __os_segdata_size = OS_SEGDATA_STARTING_SIZE;
+ ret = __os_calloc(dbenv,
+ __os_segdata_size, sizeof(os_segdata_t), &__os_segdata);
+ DB_END_SINGLE_THREAD;
+ return (ret);
+}
+
+/*
+ * __os_segdata_destroy --
+ * Destroys the library's table of shared memory segments. It also
+ * frees all linked data: the segments themselves, and their names.
+ * Currently not called. This function should be called if the
+ * user creates a function to unload or shutdown.
+ *
+ * PUBLIC: int __os_segdata_destroy __P((DB_ENV *));
+ */
+int
+__os_segdata_destroy(dbenv)
+ DB_ENV *dbenv;
+{
+ os_segdata_t *p;
+ int i;
+
+ if (__os_segdata == NULL)
+ return (0);
+
+ DB_BEGIN_SINGLE_THREAD;
+ for (i = 0; i < __os_segdata_size; i++) {
+ p = &__os_segdata[i];
+ if (p->name != NULL) {
+ __os_free(dbenv, p->name);
+ p->name = NULL;
+ }
+ if (p->segment != NULL) {
+ __os_free(dbenv, p->segment);
+ p->segment = NULL;
+ }
+ p->size = 0;
+ }
+
+ __os_free(dbenv, __os_segdata);
+ __os_segdata = NULL;
+ __os_segdata_size = 0;
+ DB_END_SINGLE_THREAD;
+
+ return (0);
+}
+
+/*
+ * __os_segdata_allocate --
+ * Creates a new segment of the specified size, optionally with the
+ * specified name.
+ *
+ * Assumes it is called with the SEGDATA lock taken.
+ */
+static int
+__os_segdata_allocate(dbenv, name, infop, rp)
+ DB_ENV *dbenv;
+ const char *name;
+ REGINFO *infop;
+ REGION *rp;
+{
+ os_segdata_t *p;
+ int id, ret;
+
+ if ((ret = __os_segdata_new(dbenv, &id)) != 0)
+ return (ret);
+
+ p = &__os_segdata[id];
+ if ((ret = __os_calloc(dbenv, 1, rp->size, &p->segment)) != 0)
+ return (ret);
+ if ((ret = __os_strdup(dbenv, name, &p->name)) != 0) {
+ __os_free(dbenv, p->segment);
+ p->segment = NULL;
+ return (ret);
+ }
+ p->size = rp->size;
+ p->segid = dbenv->shm_key + infop->id - 1;
+
+ infop->addr = p->segment;
+ rp->segid = id;
+
+ return (0);
+}
+
+/*
+ * __os_segdata_new --
+ * Finds a new segdata slot. Does not initialise it, so the fd returned
+ * is only valid until you call this again.
+ *
+ * Assumes it is called with the SEGDATA lock taken.
+ */
+static int
+__os_segdata_new(dbenv, segidp)
+ DB_ENV *dbenv;
+ int *segidp;
+{
+ os_segdata_t *p;
+ int i, newsize, ret;
+
+ if (__os_segdata == NULL) {
+ __db_err(dbenv, "shared memory segment not initialized");
+ return (EAGAIN);
+ }
+
+ for (i = 0; i < __os_segdata_size; i++) {
+ p = &__os_segdata[i];
+ if (p->segment == NULL) {
+ *segidp = i;
+ return (0);
+ }
+ }
+
+ /*
+ * No more free slots, expand.
+ */
+ newsize = __os_segdata_size + OS_SEGDATA_INCREMENT;
+ if ((ret = __os_realloc(dbenv, newsize * sizeof(os_segdata_t),
+ &__os_segdata)) != 0)
+ return (ret);
+ memset(&__os_segdata[__os_segdata_size],
+ 0, OS_SEGDATA_INCREMENT * sizeof(os_segdata_t));
+
+ *segidp = __os_segdata_size;
+ __os_segdata_size = newsize;
+
+ return (0);
+}
+
+/*
+ * __os_segdata_find_byname --
+ * Finds a segment by its name and shm_key.
+ *
+ * Assumes it is called with the SEGDATA lock taken.
+ *
+ * PUBLIC: __os_segdata_find_byname
+ * PUBLIC: __P((DB_ENV *, const char *, REGINFO *, REGION *));
+ */
+static int
+__os_segdata_find_byname(dbenv, name, infop, rp)
+ DB_ENV *dbenv;
+ const char *name;
+ REGINFO *infop;
+ REGION *rp;
+{
+ os_segdata_t *p;
+ long segid;
+ int i;
+
+ if (__os_segdata == NULL) {
+ __db_err(dbenv, "shared memory segment not initialized");
+ return (EAGAIN);
+ }
+
+ if (name == NULL) {
+ __db_err(dbenv, "no segment name given");
+ return (EAGAIN);
+ }
+
+ /*
+ * If we are creating the region, compute the segid.
+ * If we are joining the region, we use the segid in the
+ * index we are given.
+ */
+ if (F_ISSET(infop, REGION_CREATE))
+ segid = dbenv->shm_key + (infop->id - 1);
+ else {
+ if (rp->segid >= __os_segdata_size ||
+ rp->segid == INVALID_REGION_SEGID) {
+ __db_err(dbenv, "Invalid segment id given");
+ return (EAGAIN);
+ }
+ segid = __os_segdata[rp->segid].segid;
+ }
+ for (i = 0; i < __os_segdata_size; i++) {
+ p = &__os_segdata[i];
+ if (p->name != NULL && strcmp(name, p->name) == 0 &&
+ p->segid == segid) {
+ infop->addr = p->segment;
+ rp->segid = i;
+ return (0);
+ }
+ }
+ return (ENOENT);
+}
+
+/*
+ * __os_segdata_release --
+ * Free a segdata entry.
+ */
+static int
+__os_segdata_release(dbenv, rp, is_locked)
+ DB_ENV *dbenv;
+ REGION *rp;
+ int is_locked;
+{
+ os_segdata_t *p;
+
+ if (__os_segdata == NULL) {
+ __db_err(dbenv, "shared memory segment not initialized");
+ return (EAGAIN);
+ }
+
+ if (rp->segid < 0 || rp->segid >= __os_segdata_size) {
+ __db_err(dbenv, "segment id %ld out of range", rp->segid);
+ return (EINVAL);
+ }
+
+ if (is_locked == 0)
+ DB_BEGIN_SINGLE_THREAD;
+ p = &__os_segdata[rp->segid];
+ if (p->name != NULL) {
+ __os_free(dbenv, p->name);
+ p->name = NULL;
+ }
+ if (p->segment != NULL) {
+ __os_free(dbenv, p->segment);
+ p->segment = NULL;
+ }
+ p->size = 0;
+ if (is_locked == 0)
+ DB_END_SINGLE_THREAD;
+
+ /* Any shrink-table logic could go here */
+
+ return (0);
+}
diff --git a/bdb/os_win32/os_abs.c b/bdb/os_win32/os_abs.c
index 7b1e3fd05d5..c8bead83ec3 100644
--- a/bdb/os_win32/os_abs.c
+++ b/bdb/os_win32/os_abs.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_abs.c,v 11.3 2000/02/14 03:00:06 bostic Exp $";
+static const char revid[] = "$Id: os_abs.c,v 11.5 2002/01/11 15:53:05 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
diff --git a/bdb/os_win32/os_clock.c b/bdb/os_win32/os_clock.c
new file mode 100644
index 00000000000..1bf154f9da9
--- /dev/null
+++ b/bdb/os_win32/os_clock.c
@@ -0,0 +1,37 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_clock.c,v 1.7 2002/07/12 18:56:53 bostic Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <string.h>
+
+#include "db_int.h"
+
+/*
+ * __os_clock --
+ * Return the current time-of-day clock in seconds and microseconds.
+ */
+int
+__os_clock(dbenv, secsp, usecsp)
+ DB_ENV *dbenv;
+ u_int32_t *secsp, *usecsp; /* Seconds and microseconds. */
+{
+ struct _timeb now;
+
+ _ftime(&now);
+ if (secsp != NULL)
+ *secsp = (u_int32_t)now.time;
+ if (usecsp != NULL)
+ *usecsp = now.millitm * 1000;
+ return (0);
+}
diff --git a/bdb/os_win32/os_config.c b/bdb/os_win32/os_config.c
new file mode 100644
index 00000000000..a2c220daf1a
--- /dev/null
+++ b/bdb/os_win32/os_config.c
@@ -0,0 +1,29 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_config.c,v 11.13 2002/01/11 15:53:06 bostic Exp $";
+#endif /* not lint */
+
+#include "db_int.h"
+
+/*
+ * __os_fs_notzero --
+ * Return 1 if allocated filesystem blocks are not zeroed.
+ */
+int
+__os_fs_notzero()
+{
+ /*
+ * Windows/NT zero-fills pages that were never explicitly written to
+ * the file. Windows 95/98 gives you random garbage, and that breaks
+ * Berkeley DB.
+ */
+ return (__os_is_winnt() ? 0 : 1);
+}
diff --git a/bdb/os_win32/os_dir.c b/bdb/os_win32/os_dir.c
index d37b7601051..3f47c4960b0 100644
--- a/bdb/os_win32/os_dir.c
+++ b/bdb/os_win32/os_dir.c
@@ -1,18 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_dir.c,v 11.4 2000/03/28 21:50:17 ubell Exp $";
+static const char revid[] = "$Id: os_dir.c,v 11.12 2002/07/12 18:56:54 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_dirlist --
@@ -26,12 +25,16 @@ __os_dirlist(dbenv, dir, namesp, cntp)
int *cntp;
{
struct _finddata_t fdata;
+#ifdef _WIN64
+ intptr_t dirhandle;
+#else
long dirhandle;
+#endif
int arraysz, cnt, finished, ret;
char **names, filespec[MAXPATHLEN];
- if (__db_jump.j_dirlist != NULL)
- return (__db_jump.j_dirlist(dir, namesp, cntp));
+ if (DB_GLOBAL(j_dirlist) != NULL)
+ return (DB_GLOBAL(j_dirlist)(dir, namesp, cntp));
(void)snprintf(filespec, sizeof(filespec), "%s/*", dir);
if ((dirhandle = _findfirst(filespec, &fdata)) == -1)
@@ -43,12 +46,12 @@ __os_dirlist(dbenv, dir, namesp, cntp)
if (cnt >= arraysz) {
arraysz += 100;
if ((ret = __os_realloc(dbenv,
- arraysz * sizeof(names[0]), NULL, &names)) != 0)
+ arraysz * sizeof(names[0]), &names)) != 0)
goto nomem;
}
if ((ret = __os_strdup(dbenv, fdata.name, &names[cnt])) != 0)
goto nomem;
- if (_findnext(dirhandle,&fdata) != 0)
+ if (_findnext(dirhandle, &fdata) != 0)
finished = 1;
}
_findclose(dirhandle);
@@ -58,7 +61,7 @@ __os_dirlist(dbenv, dir, namesp, cntp)
return (0);
nomem: if (names != NULL)
- __os_dirfree(names, cnt);
+ __os_dirfree(dbenv, names, cnt);
return (ret);
}
@@ -67,16 +70,17 @@ nomem: if (names != NULL)
* Free the list of files.
*/
void
-__os_dirfree(names, cnt)
+__os_dirfree(dbenv, names, cnt)
+ DB_ENV *dbenv;
char **names;
int cnt;
{
- if (__db_jump.j_dirfree != NULL) {
- __db_jump.j_dirfree(names, cnt);
+ if (DB_GLOBAL(j_dirfree) != NULL) {
+ DB_GLOBAL(j_dirfree)(names, cnt);
return;
}
while (cnt > 0)
- __os_free(names[--cnt], 0);
- __os_free(names, 0);
+ __os_free(dbenv, names[--cnt]);
+ __os_free(dbenv, names);
}
diff --git a/bdb/os_win32/os_errno.c b/bdb/os_win32/os_errno.c
index 8324826b6f9..d6fac82e6f3 100644
--- a/bdb/os_win32/os_errno.c
+++ b/bdb/os_win32/os_errno.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_errno.c,v 11.5 2000/11/30 00:58:43 ubell Exp $";
+static const char revid[] = "$Id: os_errno.c,v 11.10 2002/07/12 04:05:00 mjc Exp $";
#endif /* not lint */
#include "db_int.h"
@@ -58,13 +58,7 @@ __os_win32_errno(void)
DWORD last_error;
int ret;
- /*
- * It's possible that errno was set after the error.
- * The caller must take care to set it to 0 before
- * any system operation.
- */
- if (__os_get_errno() != 0)
- return (__os_get_errno());
+ /* Ignore errno - we used to check it here. */
last_error = GetLastError();
@@ -113,6 +107,7 @@ __os_win32_errno(void)
break;
case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
ret = EEXIST;
break;
@@ -133,6 +128,10 @@ __os_win32_errno(void)
ret = EBUSY;
break;
+ case ERROR_RETRY:
+ ret = EINTR;
+ break;
+
case 0:
ret = EFAULT;
break;
diff --git a/bdb/os_win32/os_fid.c b/bdb/os_win32/os_fid.c
index c66ac52102b..1190ad26e81 100644
--- a/bdb/os_win32/os_fid.c
+++ b/bdb/os_win32/os_fid.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_fid.c,v 11.7 2000/10/26 14:18:08 bostic Exp $";
+static const char revid[] = "$Id: os_fid.c,v 11.15 2002/08/26 14:37:39 margo Exp $";
#endif /* not lint */
#include "db_int.h"
@@ -40,10 +40,11 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
* Can't think of a better solution right now.
*/
DB_FH fh;
- HANDLE handle;
BY_HANDLE_FILE_INFORMATION fi;
BOOL retval = FALSE;
+ DB_ASSERT(fname != NULL);
+
/* Clear the buffer. */
memset(fidp, 0, DB_FILE_ID_LEN);
@@ -62,7 +63,7 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
* interesting properties in base 2.
*/
if (fid_serial == SERIAL_INIT)
- fid_serial = (u_int32_t)getpid();
+ __os_id(&fid_serial);
else
fid_serial += 100000;
@@ -74,15 +75,11 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
return (ret);
/* File open, get its info */
- handle = (HANDLE)_get_osfhandle(fh.fd);
- if (handle == INVALID_HANDLE_VALUE)
+ if ((retval = GetFileInformationByHandle(fh.handle, &fi)) == FALSE)
ret = __os_win32_errno();
- else
- if ((retval = GetFileInformationByHandle(handle, &fi)) == FALSE)
- ret = __os_win32_errno();
- __os_closehandle(&fh);
+ __os_closehandle(dbenv, &fh);
- if (handle == INVALID_HANDLE_VALUE || retval == FALSE)
+ if (retval == FALSE)
return (ret);
/*
@@ -113,6 +110,7 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
tmp = (u_int32_t)fi.nFileIndexHigh;
for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
*fidp++ = *p++;
+
if (unique_okay) {
/*
* Use the system time to try to get a unique value
diff --git a/bdb/os_win32/os_finit.c b/bdb/os_win32/os_finit.c
deleted file mode 100644
index 61d2a33c7b4..00000000000
--- a/bdb/os_win32/os_finit.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1999, 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: os_finit.c,v 11.9 2000/03/29 20:50:52 ubell Exp $";
-#endif /* not lint */
-
-#include "db_int.h"
-
-/*
- * __os_fpinit --
- * Initialize a page in a regular file.
- *
- * PUBLIC: int __os_fpinit __P((DB_ENV *, DB_FH *, db_pgno_t, int, int));
- */
-int
-__os_fpinit(dbenv, fhp, pgno, pagecount, pagesize)
- DB_ENV *dbenv;
- DB_FH *fhp;
- db_pgno_t pgno;
- int pagecount, pagesize;
-{
- size_t nw, totalbytes, curbytes;
- int ret;
- char buf[1024];
-
- /*
- * Windows/NT zero-fills pages that were never explicitly written to
- * the file. Windows 95/98 gives you random garbage, and that breaks
- * DB.
- */
- if (__os_is_winnt())
- return (0);
-
- if ((ret = __os_seek(dbenv,
- fhp, pagesize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
- return (ret);
-
- memset(buf, 0, sizeof(buf));
- totalbytes = pagecount * pagesize;
-
- while (totalbytes > 0) {
- if (totalbytes > sizeof(buf))
- curbytes = sizeof(buf);
- else
- curbytes = totalbytes;
- if ((ret = __os_write(dbenv, fhp, buf, curbytes, &nw)) != 0)
- return (ret);
- if (nw != curbytes)
- return (EIO);
- totalbytes -= curbytes;
- }
- return (0);
-}
diff --git a/bdb/os_win32/os_fsync.c b/bdb/os_win32/os_fsync.c
new file mode 100644
index 00000000000..6fd3e1dcdf4
--- /dev/null
+++ b/bdb/os_win32/os_fsync.c
@@ -0,0 +1,59 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_fsync.c,v 11.15 2002/07/12 18:56:54 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <fcntl.h> /* XXX: Required by __hp3000s900 */
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_fsync --
+ * Flush a file descriptor.
+ *
+ * PUBLIC: int __os_fsync __P((DB_ENV *, DB_FH *));
+ */
+int
+__os_fsync(dbenv, fhp)
+ DB_ENV *dbenv;
+ DB_FH *fhp;
+{
+ BOOL success;
+ int ret;
+
+ /*
+ * Do nothing if the file descriptor has been marked as not requiring
+ * any sync to disk.
+ */
+ if (F_ISSET(fhp, DB_FH_NOSYNC))
+ return (0);
+
+ ret = 0;
+ do {
+ if (DB_GLOBAL(j_fsync) != NULL)
+ success = (DB_GLOBAL(j_fsync)(fhp->fd) == 0);
+ else {
+ success = FlushFileBuffers(fhp->handle);
+ if (!success)
+ __os_set_errno(__os_win32_errno());
+ }
+ } while (!success && (ret = __os_get_errno()) == EINTR);
+
+ if (ret != 0)
+ __db_err(dbenv, "fsync %s", strerror(ret));
+ return (ret);
+}
diff --git a/bdb/os_win32/os_handle.c b/bdb/os_win32/os_handle.c
new file mode 100644
index 00000000000..7db9c3da977
--- /dev/null
+++ b/bdb/os_win32/os_handle.c
@@ -0,0 +1,126 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1998-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_handle.c,v 11.30 2002/07/12 18:56:54 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_openhandle --
+ * Open a file, using POSIX 1003.1 open flags.
+ *
+ * PUBLIC: int __os_openhandle __P((DB_ENV *, const char *, int, int, DB_FH *));
+ */
+int
+__os_openhandle(dbenv, name, flags, mode, fhp)
+ DB_ENV *dbenv;
+ const char *name;
+ int flags, mode;
+ DB_FH *fhp;
+{
+ int ret, nrepeat;
+
+ memset(fhp, 0, sizeof(*fhp));
+ fhp->handle = INVALID_HANDLE_VALUE;
+
+ /* If the application specified an interface, use it. */
+ if (DB_GLOBAL(j_open) != NULL) {
+ if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1)
+ return (__os_get_errno());
+ F_SET(fhp, DB_FH_VALID);
+ return (0);
+ }
+
+ for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
+ ret = 0;
+ fhp->fd = open(name, flags, mode);
+
+ if (fhp->fd == -1) {
+ /*
+ * If it's a "temporary" error, we retry up to 3 times,
+ * waiting up to 12 seconds. While it's not a problem
+ * if we can't open a database, an inability to open a
+ * log file is cause for serious dismay.
+ */
+ ret = __os_get_errno();
+ if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) {
+ (void)__os_sleep(dbenv, nrepeat * 2, 0);
+ continue;
+ }
+
+ /*
+ * If it was an EINTR it's reasonable to retry
+ * immediately, and arbitrarily often.
+ */
+ if (ret == EINTR) {
+ --nrepeat;
+ continue;
+ }
+ } else {
+ F_SET(fhp, DB_FH_VALID);
+ }
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * __os_closehandle --
+ * Close a file.
+ *
+ * PUBLIC: int __os_closehandle __P((DB_ENV *, DB_FH *));
+ */
+int
+__os_closehandle(dbenv, fhp)
+ DB_ENV *dbenv;
+ DB_FH *fhp;
+{
+ BOOL success;
+ int ret;
+
+ COMPQUIET(dbenv, NULL);
+ /* Don't close file descriptors that were never opened. */
+ DB_ASSERT(F_ISSET(fhp, DB_FH_VALID) &&
+ ((fhp->fd != -1) || (fhp->handle != INVALID_HANDLE_VALUE)));
+
+ ret = 0;
+
+ do {
+ if (DB_GLOBAL(j_close) != NULL)
+ success = (DB_GLOBAL(j_close)(fhp->fd) == 0);
+ else if (fhp->handle != INVALID_HANDLE_VALUE) {
+ success = CloseHandle(fhp->handle);
+ if (!success)
+ __os_set_errno(__os_win32_errno());
+ }
+ else
+ success = (close(fhp->fd) == 0);
+ } while (!success && (ret = __os_get_errno()) == EINTR);
+
+ /*
+ * Smash the POSIX file descriptor -- it's never tested, but we want
+ * to catch any mistakes.
+ */
+ fhp->fd = -1;
+ fhp->handle = INVALID_HANDLE_VALUE;
+ F_CLR(fhp, DB_FH_VALID);
+
+ return (ret);
+}
diff --git a/bdb/os_win32/os_map.c b/bdb/os_win32/os_map.c
index d7b2839ed29..1f16c9fead4 100644
--- a/bdb/os_win32/os_map.c
+++ b/bdb/os_win32/os_map.c
@@ -1,22 +1,21 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_map.c,v 11.22 2000/10/26 14:18:08 bostic Exp $";
+static const char revid[] = "$Id: os_map.c,v 11.38 2002/09/10 02:35:48 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
-#include "os_jump.h"
static int __os_map
__P((DB_ENV *, char *, REGINFO *, DB_FH *, size_t, int, int, int, void **));
-static int __os_unique_name __P((char *, int, char *));
+static int __os_unique_name __P((char *, HANDLE, char *, size_t));
/*
* __os_r_sysattach --
@@ -37,6 +36,7 @@ __os_r_sysattach(dbenv, infop, rp)
* properly ordered, our caller has already taken care of that.
*/
if ((ret = __os_open(dbenv, infop->name,
+ DB_OSO_DIRECT |
F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE: 0,
infop->mode, &fh)) != 0) {
__db_err(dbenv, "%s: %s", infop->name, db_strerror(ret));
@@ -63,7 +63,7 @@ __os_r_sysattach(dbenv, infop, rp)
if (ret == 0 && is_system == 1)
rp->segid = 1;
- (void)__os_closehandle(&fh);
+ (void)__os_closehandle(dbenv, &fh);
return (ret);
}
@@ -82,17 +82,19 @@ __os_r_sysdetach(dbenv, infop, destroy)
if (infop->wnt_handle != NULL) {
(void)CloseHandle(*((HANDLE*)(infop->wnt_handle)));
- __os_free(infop->wnt_handle, sizeof(HANDLE));
+ __os_free(dbenv, infop->wnt_handle);
}
- __os_set_errno(0);
ret = !UnmapViewOfFile(infop->addr) ? __os_win32_errno() : 0;
if (ret != 0)
__db_err(dbenv, "UnmapViewOfFile: %s", strerror(ret));
- if (F_ISSET(dbenv, DB_ENV_SYSTEM_MEM) && destroy &&
- (t_ret = __os_unlink(dbenv, infop->name)) != 0 && ret == 0)
- ret = t_ret;
+ if (!F_ISSET(dbenv, DB_ENV_SYSTEM_MEM) && destroy) {
+ if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
+ (void)__db_overwrite(dbenv, infop->name);
+ if ((t_ret = __os_unlink(dbenv, infop->name)) != 0 && ret == 0)
+ ret = t_ret;
+ }
return (ret);
}
@@ -111,8 +113,8 @@ __os_mapfile(dbenv, path, fhp, len, is_rdonly, addr)
void **addr;
{
/* If the user replaced the map call, call through their interface. */
- if (__db_jump.j_map != NULL)
- return (__db_jump.j_map(path, len, 0, is_rdonly, addr));
+ if (DB_GLOBAL(j_map) != NULL)
+ return (DB_GLOBAL(j_map)(path, len, 0, is_rdonly, addr));
return (__os_map(dbenv, path, NULL, fhp, len, 0, 0, is_rdonly, addr));
}
@@ -128,10 +130,9 @@ __os_unmapfile(dbenv, addr, len)
size_t len;
{
/* If the user replaced the map call, call through their interface. */
- if (__db_jump.j_unmap != NULL)
- return (__db_jump.j_unmap(addr, len));
+ if (DB_GLOBAL(j_unmap) != NULL)
+ return (DB_GLOBAL(j_unmap)(addr, len));
- __os_set_errno(0);
return (!UnmapViewOfFile(addr) ? __os_win32_errno() : 0);
}
@@ -151,23 +152,55 @@ __os_unmapfile(dbenv, addr, len)
* foo.bar == Foo.Bar (FAT file system)
* foo.bar != Foo.Bar (NTFS)
*
- * The best solution is to use the identifying number in the file
+ * The best solution is to use the file index, found in the file
* information structure (similar to UNIX inode #).
+ *
+ * When a file is deleted, its file index may be reused,
+ * but if the unique name has not gone from its namespace,
+ * we may get a conflict. So to ensure some tie in to the
+ * original pathname, we also use the creation time and the
+ * file basename. This is not a perfect system, but it
+ * should work for all but anamolous test cases.
+ *
*/
static int
-__os_unique_name(orig_path, fd, result_path)
+__os_unique_name(orig_path, hfile, result_path, result_path_len)
char *orig_path, *result_path;
- int fd;
+ HANDLE hfile;
+ size_t result_path_len;
{
BY_HANDLE_FILE_INFORMATION fileinfo;
+ char *basename, *p;
- __os_set_errno(0);
- if (!GetFileInformationByHandle(
- (HANDLE)_get_osfhandle(fd), &fileinfo))
+ /*
+ * In Windows, pathname components are delimited by '/' or '\', and
+ * if neither is present, we need to strip off leading drive letter
+ * (e.g. c:foo.txt).
+ */
+ basename = strrchr(orig_path, '/');
+ p = strrchr(orig_path, '\\');
+ if (basename == NULL || (p != NULL && p > basename))
+ basename = p;
+ if (basename == NULL)
+ basename = strrchr(orig_path, ':');
+
+ if (basename == NULL)
+ basename = orig_path;
+ else
+ basename++;
+
+ if (!GetFileInformationByHandle(hfile, &fileinfo))
return (__os_win32_errno());
- (void)sprintf(result_path, "%ld.%ld.%ld",
+
+ (void)snprintf(result_path, result_path_len,
+ "__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s",
fileinfo.dwVolumeSerialNumber,
- fileinfo.nFileIndexHigh, fileinfo.nFileIndexLow);
+ fileinfo.nFileIndexHigh,
+ fileinfo.nFileIndexLow,
+ fileinfo.ftCreationTime.dwHighDateTime,
+ fileinfo.ftCreationTime.dwHighDateTime,
+ basename);
+
return (0);
}
@@ -187,10 +220,9 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
{
HANDLE hMemory;
REGENV *renv;
- int ret;
- void *pMemory;
+ int ret, use_pagefile;
char shmem_name[MAXPATHLEN];
- int use_pagefile;
+ void *pMemory;
ret = 0;
if (infop != NULL)
@@ -202,12 +234,9 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
* If creating a region in system space, get a matching name in the
* paging file namespace.
*/
- if (use_pagefile) {
- (void)strcpy(shmem_name, "__db_shmem.");
- if ((ret = __os_unique_name(path, fhp->fd,
- &shmem_name[strlen(shmem_name)])) != 0)
- return (ret);
- }
+ if (use_pagefile && (ret = __os_unique_name(
+ path, fhp->handle, shmem_name, sizeof(shmem_name))) != 0)
+ return (ret);
/*
* XXX
@@ -235,7 +264,6 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
* the section.
*/
hMemory = NULL;
- __os_set_errno(0);
if (use_pagefile)
hMemory = OpenFileMapping(
is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
@@ -244,24 +272,23 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
if (hMemory == NULL)
hMemory = CreateFileMapping(
- use_pagefile ?
- (HANDLE)0xFFFFFFFF : (HANDLE)_get_osfhandle(fhp->fd),
+ use_pagefile ? (HANDLE)-1 : fhp->handle,
0,
is_rdonly ? PAGE_READONLY : PAGE_READWRITE,
- 0, len,
+ 0, (DWORD)len,
use_pagefile ? shmem_name : NULL);
if (hMemory == NULL) {
- __db_err(dbenv,
- "OpenFileMapping: %s", strerror(__os_win32_errno()));
- return (__os_win32_errno());
+ ret = __os_win32_errno();
+ __db_err(dbenv, "OpenFileMapping: %s", strerror(ret));
+ return (ret);
}
pMemory = MapViewOfFile(hMemory,
(is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 0, 0, len);
if (pMemory == NULL) {
- __db_err(dbenv,
- "MapViewOfFile: %s", strerror(__os_win32_errno()));
- return (__os_win32_errno());
+ ret = __os_win32_errno();
+ __db_err(dbenv, "MapViewOfFile: %s", strerror(ret));
+ return (ret);
}
/*
@@ -279,8 +306,8 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
* errors, it just means we leak the memory.
*/
if (use_pagefile && infop != NULL) {
- if (__os_malloc(NULL,
- sizeof(HANDLE), NULL, &infop->wnt_handle) == 0)
+ if (__os_malloc(dbenv,
+ sizeof(HANDLE), &infop->wnt_handle) == 0)
memcpy(infop->wnt_handle, &hMemory, sizeof(HANDLE));
} else
CloseHandle(hMemory);
@@ -295,7 +322,7 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
* the REGINFO structure so that they do so.
*/
renv = (REGENV *)pMemory;
- if (renv->magic == 0)
+ if (renv->magic == 0) {
if (F_ISSET(infop, REGION_CREATE_OK))
F_SET(infop, REGION_CREATE);
else {
@@ -303,6 +330,7 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
pMemory = NULL;
ret = EAGAIN;
}
+ }
}
*addr = pMemory;
diff --git a/bdb/os_win32/os_open.c b/bdb/os_win32/os_open.c
index 7ecd96126df..c8bae54d585 100644
--- a/bdb/os_win32/os_open.c
+++ b/bdb/os_win32/os_open.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_open.c,v 11.9 2000/11/30 00:58:43 ubell Exp $";
+static const char revid[] = "$Id: os_open.c,v 11.21 2002/07/12 18:56:55 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -21,9 +21,6 @@ static const char revid[] = "$Id: os_open.c,v 11.9 2000/11/30 00:58:43 ubell Exp
#endif
#include "db_int.h"
-#include "os_jump.h"
-
-int __os_win32_errno __P((void));
/*
* __os_open --
@@ -38,17 +35,26 @@ __os_open(dbenv, name, flags, mode, fhp)
DB_FH *fhp;
{
DWORD bytesWritten;
- HANDLE wh;
- u_int32_t log_size;
+ u_int32_t log_size, pagesize, sectorsize;
int access, attr, oflags, share, createflag;
int ret, nrepeat;
+ char *drive, dbuf[4]; /* <letter><colon><slosh><nul> */
+
+#ifdef DIAGNOSTIC
+#define OKFLAGS \
+ (DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_LOG | \
+ DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | DB_OSO_TEMP | \
+ DB_OSO_TRUNC)
+ if ((ret = __db_fchk(dbenv, "__os_open", flags, OKFLAGS)) != 0)
+ return (ret);
+#endif
/*
* The "public" interface to the __os_open routine passes around POSIX
* 1003.1 flags, not DB flags. If the user has defined their own open
* interface, use the POSIX flags.
*/
- if (__db_jump.j_open != NULL) {
+ if (DB_GLOBAL(j_open) != NULL) {
oflags = O_BINARY | O_NOINHERIT;
if (LF_ISSET(DB_OSO_CREATE))
@@ -76,10 +82,15 @@ __os_open(dbenv, name, flags, mode, fhp)
return (__os_openhandle(dbenv, name, oflags, mode, fhp));
}
+ ret = 0;
+
if (LF_ISSET(DB_OSO_LOG))
log_size = fhp->log_size; /* XXX: Gag. */
+ pagesize = fhp->pagesize;
+
memset(fhp, 0, sizeof(*fhp));
+ fhp->fd = -1;
/*
* Otherwise, use the Windows/32 CreateFile interface so that we can
@@ -97,8 +108,6 @@ __os_open(dbenv, name, flags, mode, fhp)
* largely meaningless on FAT, the most common file system, which
* only has a "readable" and "writeable" flag, applying to all users.
*/
- wh = INVALID_HANDLE_VALUE;
-
access = GENERIC_READ;
if (!LF_ISSET(DB_OSO_RDONLY))
access |= GENERIC_WRITE;
@@ -134,11 +143,28 @@ __os_open(dbenv, name, flags, mode, fhp)
if (LF_ISSET(DB_OSO_TEMP))
attr |= FILE_FLAG_DELETE_ON_CLOSE;
- for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
- ret = 0;
- __os_set_errno(0);
- wh = CreateFile(name, access, share, NULL, createflag, attr, 0);
- if (wh == INVALID_HANDLE_VALUE) {
+ /*
+ * We can turn filesystem buffering off if the page size is a
+ * multiple of the disk's sector size. To find the sector size,
+ * we call GetDiskFreeSpace, which expects a drive name like "d:\\"
+ * or NULL for the current disk (i.e., a relative path)
+ */
+ if (LF_ISSET(DB_OSO_DIRECT) && pagesize != 0 && name[0] != '\0') {
+ if (name[1] == ':') {
+ drive = dbuf;
+ snprintf(dbuf, sizeof(dbuf), "%c:\\", name[0]);
+ } else
+ drive = NULL;
+
+ if (GetDiskFreeSpace(drive, NULL, &sectorsize, NULL, NULL) &&
+ pagesize % sectorsize == 0)
+ attr |= FILE_FLAG_NO_BUFFERING;
+ }
+
+ for (nrepeat = 1;; ++nrepeat) {
+ fhp->handle =
+ CreateFile(name, access, share, NULL, createflag, attr, 0);
+ if (fhp->handle == INVALID_HANDLE_VALUE) {
/*
* If it's a "temporary" error, we retry up to 3 times,
* waiting up to 12 seconds. While it's not a problem
@@ -146,13 +172,13 @@ __os_open(dbenv, name, flags, mode, fhp)
* log file is cause for serious dismay.
*/
ret = __os_win32_errno();
- if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) {
- (void)__os_sleep(dbenv, nrepeat * 2, 0);
- continue;
- }
- goto err;
- }
- break;
+ if ((ret != ENFILE && ret != EMFILE && ret != ENOSPC) ||
+ nrepeat > 3)
+ goto err;
+
+ (void)__os_sleep(dbenv, nrepeat * 2, 0);
+ } else
+ break;
}
/*
@@ -163,39 +189,29 @@ __os_open(dbenv, name, flags, mode, fhp)
* This strategy only works for Win/NT; Win/9X does not
* guarantee that the logs will be zero filled.
*/
- if (LF_ISSET(DB_OSO_LOG) && log_size != 0 &&
- __os_is_winnt()) {
- if (SetFilePointer(wh,
+ if (LF_ISSET(DB_OSO_LOG) && log_size != 0 && __os_is_winnt()) {
+ if (SetFilePointer(fhp->handle,
log_size - 1, NULL, FILE_BEGIN) == (DWORD)-1)
goto err;
- if (WriteFile(wh, "\x00", 1, &bytesWritten, NULL) == 0)
+ if (WriteFile(fhp->handle, "\x00", 1, &bytesWritten, NULL) == 0)
goto err;
if (bytesWritten != 1)
goto err;
- if (SetEndOfFile(wh) == 0)
+ if (SetEndOfFile(fhp->handle) == 0)
goto err;
- if (SetFilePointer(wh, 0, NULL, FILE_BEGIN) == (DWORD)-1)
+ if (SetFilePointer(
+ fhp->handle, 0, NULL, FILE_BEGIN) == (DWORD)-1)
goto err;
- if (FlushFileBuffers(wh) == 0)
+ if (FlushFileBuffers(fhp->handle) == 0)
goto err;
}
- /*
- * We acquire a POSIX file descriptor as this allows us to use the
- * general UNIX I/O routines instead of writing Windows specific
- * ones. Closing that file descriptor is sufficient to close the
- * Windows HANDLE.
- */
- fhp->fd =
- _open_osfhandle((long)wh, LF_ISSET(DB_OSO_RDONLY) ? O_RDONLY : 0);
- fhp->handle = wh;
F_SET(fhp, DB_FH_VALID);
-
return (0);
err: if (ret == 0)
ret = __os_win32_errno();
- if (wh != INVALID_HANDLE_VALUE)
- (void)CloseHandle(wh);
+ if (fhp->handle != INVALID_HANDLE_VALUE)
+ (void)CloseHandle(fhp->handle);
return (ret);
}
diff --git a/bdb/os_win32/os_rename.c b/bdb/os_win32/os_rename.c
index cd53ec02022..ba14cb73bb0 100644
--- a/bdb/os_win32/os_rename.c
+++ b/bdb/os_win32/os_rename.c
@@ -1,57 +1,74 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_rename.c,v 1.2 2000/06/13 19:52:19 dda Exp $";
+static const char revid[] = "$Id: os_rename.c,v 1.12 2002/07/12 18:56:55 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_rename --
* Rename a file.
*/
int
-__os_rename(dbenv, old, new)
+__os_rename(dbenv, oldname, newname, flags)
DB_ENV *dbenv;
- const char *old, *new;
+ const char *oldname, *newname;
+ u_int32_t flags;
{
int ret;
+ char oldbuf[MAX_PATH], newbuf[MAX_PATH];
ret = 0;
- if (__db_jump.j_rename != NULL) {
- if (__db_jump.j_rename(old, new) == -1)
+ if (DB_GLOBAL(j_rename) != NULL) {
+ if (DB_GLOBAL(j_rename)(oldname, newname) == -1)
ret = __os_get_errno();
+ goto done;
}
- else {
- /* Normally we would use a single MoveFileEx call with
- * MOVEFILE_REPLACE_EXISTING flag to simulate Unix rename().
- * But if the target file exists, and the two files' 8.3
- * names are identical, a Windows bug causes the target file
- * to be deleted, but the original file will not be renamed,
- * and an ENOENT error will be returned. (See MSDN for a
- * description of the bug).
- *
- * After the failed call, a MoveFile seems to perform
- * the rename correctly (even another call to MoveFileEx
- * does not)! The expense of this extra call only occurs
- * on systems with the bug: Windows/98, for one, but
- * apparently not Windows/NT and Windows/2000.
- */
- if (MoveFileEx(old, new, MOVEFILE_REPLACE_EXISTING) != TRUE)
- ret = __os_win32_errno();
- if ((ret == ENOENT || ret == EIO) && MoveFile(old, new) == TRUE)
- ret = 0;
+
+ if (!MoveFile(oldname, newname))
+ ret = __os_win32_errno();
+
+ if (ret == EEXIST) {
+ ret = 0;
+ if (__os_is_winnt()) {
+ if (!MoveFileEx(
+ oldname, newname, MOVEFILE_REPLACE_EXISTING))
+ ret = __os_win32_errno();
+ } else {
+ /*
+ * There is no MoveFileEx for Win9x/Me, so we have to
+ * do the best we can.
+ */
+ if (!GetLongPathName(oldname, oldbuf, sizeof oldbuf) ||
+ !GetLongPathName(newname, newbuf, sizeof newbuf)) {
+ ret = __os_win32_errno();
+ goto done;
+ }
+
+ /*
+ * If the old and new names differ only in case, we're
+ * done.
+ */
+ if (strcasecmp(oldbuf, newbuf) == 0)
+ goto done;
+
+ (void)DeleteFile(newname);
+ if (!MoveFile(oldname, newname))
+ ret = __os_win32_errno();
+ }
}
- if (ret != 0)
- __db_err(dbenv, "Rename %s %s: %s", old, new, strerror(ret));
+
+done: if (ret != 0 && flags == 0)
+ __db_err(dbenv,
+ "Rename %s %s: %s", oldname, newname, strerror(ret));
return (ret);
}
diff --git a/bdb/os_win32/os_rw.c b/bdb/os_win32/os_rw.c
new file mode 100644
index 00000000000..63d1f715c53
--- /dev/null
+++ b/bdb/os_win32/os_rw.c
@@ -0,0 +1,182 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_rw.c,v 11.28 2002/08/06 04:56:19 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_io --
+ * Do an I/O.
+ *
+ * PUBLIC: int __os_io __P((DB_ENV *, DB_IO *, int, size_t *));
+ */
+int
+__os_io(dbenv, db_iop, op, niop)
+ DB_ENV *dbenv;
+ DB_IO *db_iop;
+ int op;
+ size_t *niop;
+{
+ int ret;
+
+ if (__os_is_winnt()) {
+ ULONG64 off = (ULONG64)db_iop->pagesize * db_iop->pgno;
+ OVERLAPPED over;
+ DWORD nbytes;
+ over.Offset = (DWORD)(off & 0xffffffff);
+ over.OffsetHigh = (DWORD)(off >> 32);
+ over.hEvent = 0; /* we don't want asynchronous notifications */
+
+ switch (op) {
+ case DB_IO_READ:
+ if (DB_GLOBAL(j_read) != NULL)
+ goto slow;
+ if (!ReadFile(db_iop->fhp->handle,
+ db_iop->buf, (DWORD)db_iop->bytes, &nbytes, &over))
+ goto slow;
+ break;
+ case DB_IO_WRITE:
+ if (DB_GLOBAL(j_write) != NULL)
+ goto slow;
+ if (!WriteFile(db_iop->fhp->handle,
+ db_iop->buf, (DWORD)db_iop->bytes, &nbytes, &over))
+ goto slow;
+ break;
+ }
+ if (nbytes == db_iop->bytes) {
+ *niop = (size_t)nbytes;
+ return (0);
+ }
+ }
+
+slow: MUTEX_THREAD_LOCK(dbenv, db_iop->mutexp);
+
+ if ((ret = __os_seek(dbenv, db_iop->fhp,
+ db_iop->pagesize, db_iop->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
+ goto err;
+
+ switch (op) {
+ case DB_IO_READ:
+ ret = __os_read(dbenv,
+ db_iop->fhp, db_iop->buf, db_iop->bytes, niop);
+ break;
+ case DB_IO_WRITE:
+ ret = __os_write(dbenv,
+ db_iop->fhp, db_iop->buf, db_iop->bytes, niop);
+ break;
+ }
+
+err: MUTEX_THREAD_UNLOCK(dbenv, db_iop->mutexp);
+
+ return (ret);
+}
+
+/*
+ * __os_read --
+ * Read from a file handle.
+ *
+ * PUBLIC: int __os_read __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
+ */
+int
+__os_read(dbenv, fhp, addr, len, nrp)
+ DB_ENV *dbenv;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nrp;
+{
+ size_t offset;
+ DWORD nr;
+ int ret;
+ BOOL success;
+ u_int8_t *taddr;
+
+ for (taddr = addr,
+ offset = 0; offset < len; taddr += nr, offset += nr) {
+retry: if (DB_GLOBAL(j_read) != NULL) {
+ nr = (DWORD)DB_GLOBAL(j_read)(fhp->fd,
+ taddr, len - offset);
+ success = (nr >= 0);
+ } else {
+ success = ReadFile(fhp->handle,
+ taddr, (DWORD)(len - offset), &nr, NULL);
+ if (!success)
+ __os_set_errno(__os_win32_errno());
+ }
+
+ if (!success) {
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
+ __db_err(dbenv, "read: 0x%lx, %lu: %s",
+ P_TO_ULONG(taddr),
+ (u_long)len - offset, strerror(ret));
+ return (ret);
+ }
+ if (nr == 0)
+ break;
+ }
+ *nrp = taddr - (u_int8_t *)addr;
+ return (0);
+}
+
+/*
+ * __os_write --
+ * Write to a file handle.
+ *
+ * PUBLIC: int __os_write __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
+ */
+int
+__os_write(dbenv, fhp, addr, len, nwp)
+ DB_ENV *dbenv;
+ DB_FH *fhp;
+ void *addr;
+ size_t len;
+ size_t *nwp;
+{
+ size_t offset;
+ DWORD nw;
+ int ret;
+ BOOL success;
+ u_int8_t *taddr;
+
+ for (taddr = addr,
+ offset = 0; offset < len; taddr += nw, offset += nw) {
+retry: if (DB_GLOBAL(j_write) != NULL) {
+ nw = (DWORD)DB_GLOBAL(j_write)(fhp->fd,
+ taddr, len - offset);
+ success = (nw >= 0);
+ } else {
+ success = WriteFile(fhp->handle,
+ taddr, (DWORD)(len - offset), &nw, NULL);
+ if (!success)
+ __os_set_errno(__os_win32_errno());
+ }
+
+ if (!success) {
+ if ((ret = __os_get_errno()) == EINTR)
+ goto retry;
+ __db_err(dbenv, "write: 0x%x, %lu: %s", taddr,
+ (u_long)len-offset, strerror(ret));
+ return (ret);
+ }
+ }
+
+ *nwp = len;
+ return (0);
+}
diff --git a/bdb/os_win32/os_seek.c b/bdb/os_win32/os_seek.c
index 8cf3c98aa91..40140f51534 100644
--- a/bdb/os_win32/os_seek.c
+++ b/bdb/os_win32/os_seek.c
@@ -1,18 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_seek.c,v 11.8 2000/05/17 19:30:19 bostic Exp $";
+static const char revid[] = "$Id: os_seek.c,v 11.17 2002/08/06 04:56:20 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_seek --
@@ -28,32 +27,56 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
int isrewind;
DB_OS_SEEK db_whence;
{
- __int64 offset;
+ /* Yes, this really is how Microsoft have designed their API */
+ union {
+ __int64 bigint;
+ struct {
+ unsigned long low;
+ long high;
+ };
+ } offset;
int ret, whence;
+ DWORD from;
- switch (db_whence) {
- case DB_OS_SEEK_CUR:
- whence = SEEK_CUR;
- break;
- case DB_OS_SEEK_END:
- whence = SEEK_END;
- break;
- case DB_OS_SEEK_SET:
- whence = SEEK_SET;
- break;
- default:
- return (EINVAL);
- }
+ if (DB_GLOBAL(j_seek) != NULL) {
+ switch (db_whence) {
+ case DB_OS_SEEK_CUR:
+ whence = SEEK_CUR;
+ break;
+ case DB_OS_SEEK_END:
+ whence = SEEK_END;
+ break;
+ case DB_OS_SEEK_SET:
+ whence = SEEK_SET;
+ break;
+ default:
+ return (EINVAL);
+ }
- if (__db_jump.j_seek != NULL)
- ret = __db_jump.j_seek(fhp->fd, pgsize, pageno,
+ ret = DB_GLOBAL(j_seek)(fhp->fd, pgsize, pageno,
relative, isrewind, whence);
- else {
- offset = (__int64)pgsize * pageno + relative;
+ } else {
+ switch (db_whence) {
+ case DB_OS_SEEK_CUR:
+ from = FILE_CURRENT;
+ break;
+ case DB_OS_SEEK_END:
+ from = FILE_END;
+ break;
+ case DB_OS_SEEK_SET:
+ from = FILE_BEGIN;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ offset.bigint = (__int64)pgsize * pageno + relative;
if (isrewind)
- offset = -offset;
- ret = _lseeki64(
- fhp->fd, offset, whence) == -1 ? __os_get_errno() : 0;
+ offset.bigint = -offset.bigint;
+
+ ret = (SetFilePointer(fhp->handle,
+ offset.low, &offset.high, from) == (DWORD) - 1) ?
+ __os_win32_errno() : 0;
}
if (ret != 0)
diff --git a/bdb/os_win32/os_sleep.c b/bdb/os_win32/os_sleep.c
index f0248a583de..12b4a7dbc2d 100644
--- a/bdb/os_win32/os_sleep.c
+++ b/bdb/os_win32/os_sleep.c
@@ -1,18 +1,17 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_sleep.c,v 11.4 2000/03/30 01:46:43 ubell Exp $";
+static const char revid[] = "$Id: os_sleep.c,v 11.8 2002/07/12 18:56:56 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_sleep --
@@ -29,8 +28,8 @@ __os_sleep(dbenv, secs, usecs)
for (; usecs >= 1000000; ++secs, usecs -= 1000000)
;
- if (__db_jump.j_sleep != NULL)
- return (__db_jump.j_sleep(secs, usecs));
+ if (DB_GLOBAL(j_sleep) != NULL)
+ return (DB_GLOBAL(j_sleep)(secs, usecs));
/*
* It's important that we yield the processor here so that other
diff --git a/bdb/os_win32/os_spin.c b/bdb/os_win32/os_spin.c
index f250c523d14..eb50b3b53ff 100644
--- a/bdb/os_win32/os_spin.c
+++ b/bdb/os_win32/os_spin.c
@@ -1,25 +1,25 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_spin.c,v 11.6 2000/05/17 19:30:19 bostic Exp $";
+static const char revid[] = "$Id: os_spin.c,v 11.11 2002/07/12 18:56:56 bostic Exp $";
#endif /* not lint */
#include "db_int.h"
-#include "os_jump.h"
/*
* __os_spin --
* Return the number of default spins before blocking.
*/
int
-__os_spin()
+__os_spin(dbenv)
+ DB_ENV *dbenv;
{
SYSTEM_INFO SystemInfo;
@@ -27,8 +27,8 @@ __os_spin()
* If the application specified a value or we've already figured it
* out, return it.
*/
- if (DB_GLOBAL(db_tas_spins) != 0)
- return (DB_GLOBAL(db_tas_spins));
+ if (dbenv->tas_spins != 0)
+ return (dbenv->tas_spins);
/* Get the number of processors */
GetSystemInfo(&SystemInfo);
@@ -38,10 +38,10 @@ __os_spin()
* is a reasonable value.
*/
if (SystemInfo.dwNumberOfProcessors > 1)
- DB_GLOBAL(db_tas_spins) = 50 * SystemInfo.dwNumberOfProcessors;
+ dbenv->tas_spins = 50 * SystemInfo.dwNumberOfProcessors;
else
- DB_GLOBAL(db_tas_spins) = 1;
- return (DB_GLOBAL(db_tas_spins));
+ dbenv->tas_spins = 1;
+ return (dbenv->tas_spins);
}
/*
@@ -53,7 +53,7 @@ __os_yield(dbenv, usecs)
DB_ENV *dbenv;
u_long usecs;
{
- if (__db_jump.j_yield != NULL && __db_jump.j_yield() == 0)
+ if (DB_GLOBAL(j_yield) != NULL && DB_GLOBAL(j_yield)() == 0)
return;
__os_sleep(dbenv, 0, usecs);
}
diff --git a/bdb/os_win32/os_stat.c b/bdb/os_win32/os_stat.c
new file mode 100644
index 00000000000..c1cba698bea
--- /dev/null
+++ b/bdb/os_win32/os_stat.c
@@ -0,0 +1,100 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: os_stat.c,v 11.22 2002/07/12 18:56:56 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_exists --
+ * Return if the file exists.
+ *
+ * PUBLIC: int __os_exists __P((const char *, int *));
+ */
+int
+__os_exists(path, isdirp)
+ const char *path;
+ int *isdirp;
+{
+ int ret;
+ DWORD attrs;
+
+ if (DB_GLOBAL(j_exists) != NULL)
+ return (DB_GLOBAL(j_exists)(path, isdirp));
+
+ ret = 0;
+ do {
+ attrs = GetFileAttributes(path);
+ if (attrs == (DWORD)-1)
+ ret = __os_win32_errno();
+ } while (ret == EINTR);
+
+ if (ret != 0)
+ return (ret);
+
+ if (isdirp != NULL)
+ *isdirp = (attrs & FILE_ATTRIBUTE_DIRECTORY);
+
+ return (0);
+}
+
+/*
+ * __os_ioinfo --
+ * Return file size and I/O size; abstracted to make it easier
+ * to replace.
+ *
+ * PUBLIC: int __os_ioinfo __P((DB_ENV *, const char *,
+ * PUBLIC: DB_FH *, u_int32_t *, u_int32_t *, u_int32_t *));
+ */
+int
+__os_ioinfo(dbenv, path, fhp, mbytesp, bytesp, iosizep)
+ DB_ENV *dbenv;
+ const char *path;
+ DB_FH *fhp;
+ u_int32_t *mbytesp, *bytesp, *iosizep;
+{
+ int ret;
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ unsigned __int64 filesize;
+
+ if (DB_GLOBAL(j_ioinfo) != NULL)
+ return (DB_GLOBAL(j_ioinfo)(path,
+ fhp->fd, mbytesp, bytesp, iosizep));
+
+retry: if (!GetFileInformationByHandle(fhp->handle, &bhfi)) {
+ if ((ret = __os_win32_errno()) == EINTR)
+ goto retry;
+ __db_err(dbenv,
+ "GetFileInformationByHandle: %s", strerror(ret));
+ return (ret);
+ }
+
+ filesize = ((unsigned __int64)bhfi.nFileSizeHigh << 32) +
+ bhfi.nFileSizeLow;
+
+ /* Return the size of the file. */
+ if (mbytesp != NULL)
+ *mbytesp = (u_int32_t)(filesize / MEGABYTE);
+ if (bytesp != NULL)
+ *bytesp = (u_int32_t)(filesize % MEGABYTE);
+
+ /* The filesystem blocksize is not easily available. */
+ if (iosizep != NULL)
+ *iosizep = DB_DEF_IOSIZE;
+ return (0);
+}
diff --git a/bdb/os_win32/os_type.c b/bdb/os_win32/os_type.c
index a82fc4b1d4e..583da0aaf1e 100644
--- a/bdb/os_win32/os_type.c
+++ b/bdb/os_win32/os_type.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: os_type.c,v 11.3 2000/02/14 03:00:07 bostic Exp $";
+static const char revid[] = "$Id: os_type.c,v 11.6 2002/01/11 15:53:08 bostic Exp $";
#endif /* not lint */
/*
@@ -26,10 +26,11 @@ __os_is_winnt()
* The value of __os_type is computed only once, and cached to
* avoid the overhead of repeated calls to GetVersion().
*/
- if (__os_type == -1)
+ if (__os_type == -1) {
if ((GetVersion() & 0x80000000) == 0)
__os_type = 1;
else
__os_type = 0;
+ }
return (__os_type);
}
diff --git a/bdb/patches/log-corruption.patch b/bdb/patches/log-corruption.patch
deleted file mode 100644
index 16c37ff7c06..00000000000
--- a/bdb/patches/log-corruption.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-# This patch fixes a bug caused mysqld to get a core dump while
-# bdb tries to resolve the log file after mysqld was killed with kill -9.
-#
-# Author: Michael Ubell, Sleepycat Software
-# Mon, 26 Feb 2001 12:56:23 -0500 (EST)
-#
-
-*** log/log_rec.c 2001/02/08 03:05:01 11.50
---- log/log_rec.c 2001/02/24 00:42:46 11.51
-***************
-*** 50,55 ****
---- 50,56 ----
- #include "db_am.h"
- #include "log.h"
-
-+ static int __log_check_master __P((DB_ENV *, u_int8_t *, char *));
- static int __log_do_open __P((DB_ENV *, DB_LOG *,
- u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
- static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
-***************
-*** 341,346 ****
---- 342,350 ----
- * Verify that we are opening the same file that we were
- * referring to when we wrote this log record.
- */
-+ if (meta_pgno != PGNO_BASE_MD &&
-+ __log_check_master(dbenv, uid, name) != 0)
-+ goto not_right;
- if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) {
- memset(zeroid, 0, DB_FILE_ID_LEN);
- if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
-***************
-*** 359,364 ****
---- 363,390 ----
- (void)__log_add_logid(dbenv, lp, NULL, ndx);
-
- return (ENOENT);
-+ }
-+
-+ static int
-+ __log_check_master(dbenv, uid, name)
-+ DB_ENV *dbenv;
-+ u_int8_t *uid;
-+ char *name;
-+ {
-+ DB *dbp;
-+ int ret;
-+
-+ ret = 0;
-+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
-+ return (ret);
-+ dbp->type = DB_BTREE;
-+ ret = __db_dbopen(dbp, name, 0, __db_omode("rw----"), PGNO_BASE_MD);
-+
-+ if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
-+ ret = EINVAL;
-+
-+ (void) dbp->close(dbp, 0);
-+ return (ret);
- }
-
- /*
diff --git a/bdb/perl.BerkeleyDB/BerkeleyDB.pm b/bdb/perl.BerkeleyDB/BerkeleyDB.pm
deleted file mode 100644
index cc172a2bd22..00000000000
--- a/bdb/perl.BerkeleyDB/BerkeleyDB.pm
+++ /dev/null
@@ -1,1227 +0,0 @@
-
-package BerkeleyDB;
-
-
-# Copyright (c) 1997-2001 Paul Marquess. All rights reserved.
-# This program is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-
-# The documentation for this module is at the bottom of this file,
-# after the line __END__.
-
-BEGIN { require 5.004_04 }
-
-use strict;
-use Carp;
-use vars qw($VERSION @ISA @EXPORT $AUTOLOAD);
-
-$VERSION = '0.13';
-
-require Exporter;
-require DynaLoader;
-require AutoLoader;
-use IO ;
-
-@ISA = qw(Exporter DynaLoader);
-# Items to export into callers namespace by default. Note: do not export
-# names by default without a very good reason. Use EXPORT_OK instead.
-# Do not simply export all your public functions/methods/constants.
-@EXPORT = qw(
-
- DB_AFTER
- DB_APPEND
- DB_ARCH_ABS
- DB_ARCH_DATA
- DB_ARCH_LOG
- DB_BEFORE
- DB_BTREE
- DB_BTREEMAGIC
- DB_BTREEOLDVER
- DB_BTREEVERSION
- DB_CHECKPOINT
- DB_CONSUME
- DB_CREATE
- DB_CURLSN
- DB_CURRENT
- DB_DBT_MALLOC
- DB_DBT_PARTIAL
- DB_DBT_USERMEM
- DB_DELETED
- DB_DELIMITER
- DB_DUP
- DB_DUPSORT
- DB_ENV_APPINIT
- DB_ENV_STANDALONE
- DB_ENV_THREAD
- DB_EXCL
- DB_FILE_ID_LEN
- DB_FIRST
- DB_FIXEDLEN
- DB_FLUSH
- DB_FORCE
- DB_GET_BOTH
- DB_GET_RECNO
- DB_HASH
- DB_HASHMAGIC
- DB_HASHOLDVER
- DB_HASHVERSION
- DB_INCOMPLETE
- DB_INIT_CDB
- DB_INIT_LOCK
- DB_INIT_LOG
- DB_INIT_MPOOL
- DB_INIT_TXN
- DB_JOIN_ITEM
- DB_KEYEMPTY
- DB_KEYEXIST
- DB_KEYFIRST
- DB_KEYLAST
- DB_LAST
- DB_LOCKMAGIC
- DB_LOCKVERSION
- DB_LOCK_CONFLICT
- DB_LOCK_DEADLOCK
- DB_LOCK_DEFAULT
- DB_LOCK_GET
- DB_LOCK_NORUN
- DB_LOCK_NOTGRANTED
- DB_LOCK_NOTHELD
- DB_LOCK_NOWAIT
- DB_LOCK_OLDEST
- DB_LOCK_RANDOM
- DB_LOCK_RIW_N
- DB_LOCK_RW_N
- DB_LOCK_YOUNGEST
- DB_LOGMAGIC
- DB_LOGOLDVER
- DB_MAX_PAGES
- DB_MAX_RECORDS
- DB_MPOOL_CLEAN
- DB_MPOOL_CREATE
- DB_MPOOL_DIRTY
- DB_MPOOL_DISCARD
- DB_MPOOL_LAST
- DB_MPOOL_NEW
- DB_MPOOL_PRIVATE
- DB_MUTEXDEBUG
- DB_MUTEXLOCKS
- DB_NEEDSPLIT
- DB_NEXT
- DB_NEXT_DUP
- DB_NOMMAP
- DB_NOOVERWRITE
- DB_NOSYNC
- DB_NOTFOUND
- DB_PAD
- DB_PAGEYIELD
- DB_POSITION
- DB_PREV
- DB_PRIVATE
- DB_QUEUE
- DB_RDONLY
- DB_RECNO
- DB_RECNUM
- DB_RECORDCOUNT
- DB_RECOVER
- DB_RECOVER_FATAL
- DB_REGISTERED
- DB_RENUMBER
- DB_RMW
- DB_RUNRECOVERY
- DB_SEQUENTIAL
- DB_SET
- DB_SET_RANGE
- DB_SET_RECNO
- DB_SNAPSHOT
- DB_SWAPBYTES
- DB_TEMPORARY
- DB_THREAD
- DB_TRUNCATE
- DB_TXNMAGIC
- DB_TXNVERSION
- DB_TXN_BACKWARD_ROLL
- DB_TXN_CKP
- DB_TXN_FORWARD_ROLL
- DB_TXN_LOCK_2PL
- DB_TXN_LOCK_MASK
- DB_TXN_LOCK_OPTIMIST
- DB_TXN_LOCK_OPTIMISTIC
- DB_TXN_LOG_MASK
- DB_TXN_LOG_REDO
- DB_TXN_LOG_UNDO
- DB_TXN_LOG_UNDOREDO
- DB_TXN_NOSYNC
- DB_TXN_NOWAIT
- DB_TXN_OPENFILES
- DB_TXN_REDO
- DB_TXN_SYNC
- DB_TXN_UNDO
- DB_USE_ENVIRON
- DB_USE_ENVIRON_ROOT
- DB_VERSION_MAJOR
- DB_VERSION_MINOR
- DB_VERSION_PATCH
- DB_WRITECURSOR
- );
-
-sub AUTOLOAD {
- # This AUTOLOAD is used to 'autoload' constants from the constant()
- # XS function. If a constant is not found then control is passed
- # to the AUTOLOAD in AutoLoader.
-
- my $constname;
- ($constname = $AUTOLOAD) =~ s/.*:://;
- my $val = constant($constname, @_ ? $_[0] : 0);
- if ($! != 0) {
- if ($! =~ /Invalid/) {
- $AutoLoader::AUTOLOAD = $AUTOLOAD;
- goto &AutoLoader::AUTOLOAD;
- }
- else {
- croak "Your vendor has not defined BerkeleyDB macro $constname";
- }
- }
- eval "sub $AUTOLOAD { $val }";
- goto &$AUTOLOAD;
-}
-
-bootstrap BerkeleyDB $VERSION;
-
-# Preloaded methods go here.
-
-
-sub ParseParameters($@)
-{
- my ($default, @rest) = @_ ;
- my (%got) = %$default ;
- my (@Bad) ;
- my ($key, $value) ;
- my $sub = (caller(1))[3] ;
- my %options = () ;
- local ($Carp::CarpLevel) = 1 ;
-
- # allow the options to be passed as a hash reference or
- # as the complete hash.
- if (@rest == 1) {
-
- croak "$sub: parameter is not a reference to a hash"
- if ref $rest[0] ne "HASH" ;
-
- %options = %{ $rest[0] } ;
- }
- elsif (@rest >= 2) {
- %options = @rest ;
- }
-
- while (($key, $value) = each %options)
- {
- $key =~ s/^-// ;
-
- if (exists $default->{$key})
- { $got{$key} = $value }
- else
- { push (@Bad, $key) }
- }
-
- if (@Bad) {
- my ($bad) = join(", ", @Bad) ;
- croak "unknown key value(s) @Bad" ;
- }
-
- return \%got ;
-}
-
-use UNIVERSAL qw( isa ) ;
-
-sub env_remove
-{
- # Usage:
- #
- # $env = new BerkeleyDB::Env
- # [ -Home => $path, ]
- # [ -Config => { name => value, name => value }
- # [ -Flags => DB_INIT_LOCK| ]
- # ;
-
- my $got = BerkeleyDB::ParseParameters({
- Home => undef,
- Flags => 0,
- Config => undef,
- }, @_) ;
-
- if (defined $got->{ErrFile}) {
- if (!isaFilehandle($got->{ErrFile})) {
- my $handle = new IO::File ">$got->{ErrFile}"
- or croak "Cannot open file $got->{ErrFile}: $!\n" ;
- $got->{ErrFile} = $handle ;
- }
- }
-
-
- if (defined $got->{Config}) {
- croak("Config parameter must be a hash reference")
- if ! ref $got->{Config} eq 'HASH' ;
-
- @BerkeleyDB::a = () ;
- my $k = "" ; my $v = "" ;
- while (($k, $v) = each %{$got->{Config}}) {
- push @BerkeleyDB::a, "$k\t$v" ;
- }
-
- $got->{"Config"} = pack("p*", @BerkeleyDB::a, undef)
- if @BerkeleyDB::a ;
- }
-
- return _env_remove($got) ;
-}
-
-sub db_remove
-{
- my $got = BerkeleyDB::ParseParameters(
- {
- Filename => undef,
- Subname => undef,
- Flags => 0,
- Env => undef,
- }, @_) ;
-
- croak("Must specify a filename")
- if ! defined $got->{Filename} ;
-
- croak("Env not of type BerkeleyDB::Env")
- if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-
- return _db_remove($got);
-}
-
-package BerkeleyDB::Env ;
-
-use UNIVERSAL qw( isa ) ;
-use Carp ;
-use vars qw( %valid_config_keys ) ;
-
-sub isaFilehandle
-{
- my $fh = shift ;
-
- return ((isa($fh,'GLOB') or isa(\$fh,'GLOB')) and defined fileno($fh) )
-
-}
-
-%valid_config_keys = map { $_, 1 } qw( DB_DATA_DIR DB_LOG_DIR DB_TEMP_DIR ) ;
-
-sub new
-{
- # Usage:
- #
- # $env = new BerkeleyDB::Env
- # [ -Home => $path, ]
- # [ -Mode => mode, ]
- # [ -Config => { name => value, name => value }
- # [ -ErrFile => filename or filehandle, ]
- # [ -ErrPrefix => "string", ]
- # [ -Flags => DB_INIT_LOCK| ]
- # [ -Cachesize => number ]
- # [ -LockDetect => ]
- # [ -Verbose => boolean ]
- # ;
-
- my $pkg = shift ;
- my $got = BerkeleyDB::ParseParameters({
- Home => undef,
- Server => undef,
- Mode => 0666,
- ErrFile => undef,
- ErrPrefix => undef,
- Flags => 0,
- Cachesize => 0,
- LockDetect => 0,
- Verbose => 0,
- Config => undef,
- }, @_) ;
-
- if (defined $got->{ErrFile}) {
- if (!isaFilehandle($got->{ErrFile})) {
- my $handle = new IO::File ">$got->{ErrFile}"
- or croak "Cannot open file $got->{ErrFile}: $!\n" ;
- $got->{ErrFile} = $handle ;
- }
- }
-
-
- my %config ;
- if (defined $got->{Config}) {
- croak("Config parameter must be a hash reference")
- if ! ref $got->{Config} eq 'HASH' ;
-
- %config = %{ $got->{Config} } ;
- @BerkeleyDB::a = () ;
- my $k = "" ; my $v = "" ;
- while (($k, $v) = each %config) {
- if ($BerkeleyDB::db_version >= 3.1 && ! $valid_config_keys{$k} ) {
- $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ;
- croak $BerkeleyDB::Error ;
- }
- push @BerkeleyDB::a, "$k\t$v" ;
- }
-
- $got->{"Config"} = pack("p*", @BerkeleyDB::a, undef)
- if @BerkeleyDB::a ;
- }
-
- my ($addr) = _db_appinit($pkg, $got) ;
- my $obj ;
- $obj = bless [$addr] , $pkg if $addr ;
- if ($obj && $BerkeleyDB::db_version >= 3.1 && keys %config) {
- my ($k, $v);
- while (($k, $v) = each %config) {
- if ($k eq 'DB_DATA_DIR')
- { $obj->set_data_dir($v) }
- elsif ($k eq 'DB_LOG_DIR')
- { $obj->set_lg_dir($v) }
- elsif ($k eq 'DB_TEMP_DIR')
- { $obj->set_tmp_dir($v) }
- else {
- $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ;
- croak $BerkeleyDB::Error
- }
- }
- }
- return $obj ;
-}
-
-
-sub TxnMgr
-{
- my $env = shift ;
- my ($addr) = $env->_TxnMgr() ;
- my $obj ;
- $obj = bless [$addr, $env] , "BerkeleyDB::TxnMgr" if $addr ;
- return $obj ;
-}
-
-sub txn_begin
-{
- my $env = shift ;
- my ($addr) = $env->_txn_begin(@_) ;
- my $obj ;
- $obj = bless [$addr, $env] , "BerkeleyDB::Txn" if $addr ;
- return $obj ;
-}
-
-sub DESTROY
-{
- my $self = shift ;
- $self->_DESTROY() ;
-}
-
-package BerkeleyDB::Hash ;
-
-use vars qw(@ISA) ;
-@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
-use UNIVERSAL qw( isa ) ;
-use Carp ;
-
-sub new
-{
- my $self = shift ;
- my $got = BerkeleyDB::ParseParameters(
- {
- # Generic Stuff
- Filename => undef,
- Subname => undef,
- #Flags => BerkeleyDB::DB_CREATE(),
- Flags => 0,
- Property => 0,
- Mode => 0666,
- Cachesize => 0,
- Lorder => 0,
- Pagesize => 0,
- Env => undef,
- #Tie => undef,
- Txn => undef,
-
- # Hash specific
- Ffactor => 0,
- Nelem => 0,
- Hash => undef,
- DupCompare => undef,
-
- # BerkeleyDB specific
- ReadKey => undef,
- WriteKey => undef,
- ReadValue => undef,
- WriteValue => undef,
- }, @_) ;
-
- croak("Env not of type BerkeleyDB::Env")
- if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-
- croak("Txn not of type BerkeleyDB::Txn")
- if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
-
- croak("-Tie needs a reference to a hash")
- if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
-
- my ($addr) = _db_open_hash($self, $got);
- my $obj ;
- if ($addr) {
- $obj = bless [$addr] , $self ;
- push @{ $obj }, $got->{Env} if $got->{Env} ;
- $obj->Txn($got->{Txn}) if $got->{Txn} ;
- }
- return $obj ;
-}
-
-*TIEHASH = \&new ;
-
-
-package BerkeleyDB::Btree ;
-
-use vars qw(@ISA) ;
-@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
-use UNIVERSAL qw( isa ) ;
-use Carp ;
-
-sub new
-{
- my $self = shift ;
- my $got = BerkeleyDB::ParseParameters(
- {
- # Generic Stuff
- Filename => undef,
- Subname => undef,
- #Flags => BerkeleyDB::DB_CREATE(),
- Flags => 0,
- Property => 0,
- Mode => 0666,
- Cachesize => 0,
- Lorder => 0,
- Pagesize => 0,
- Env => undef,
- #Tie => undef,
- Txn => undef,
-
- # Btree specific
- Minkey => 0,
- Compare => undef,
- DupCompare => undef,
- Prefix => undef,
- }, @_) ;
-
- croak("Env not of type BerkeleyDB::Env")
- if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-
- croak("Txn not of type BerkeleyDB::Txn")
- if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
-
- croak("-Tie needs a reference to a hash")
- if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
-
- my ($addr) = _db_open_btree($self, $got);
- my $obj ;
- if ($addr) {
- $obj = bless [$addr] , $self ;
- push @{ $obj }, $got->{Env} if $got->{Env} ;
- $obj->Txn($got->{Txn}) if $got->{Txn} ;
- }
- return $obj ;
-}
-
-*BerkeleyDB::Btree::TIEHASH = \&BerkeleyDB::Btree::new ;
-
-
-package BerkeleyDB::Recno ;
-
-use vars qw(@ISA) ;
-@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
-use UNIVERSAL qw( isa ) ;
-use Carp ;
-
-sub new
-{
- my $self = shift ;
- my $got = BerkeleyDB::ParseParameters(
- {
- # Generic Stuff
- Filename => undef,
- Subname => undef,
- #Flags => BerkeleyDB::DB_CREATE(),
- Flags => 0,
- Property => 0,
- Mode => 0666,
- Cachesize => 0,
- Lorder => 0,
- Pagesize => 0,
- Env => undef,
- #Tie => undef,
- Txn => undef,
-
- # Recno specific
- Delim => undef,
- Len => undef,
- Pad => undef,
- Source => undef,
- ArrayBase => 1, # lowest index in array
- }, @_) ;
-
- croak("Env not of type BerkeleyDB::Env")
- if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-
- croak("Txn not of type BerkeleyDB::Txn")
- if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
-
- croak("Tie needs a reference to an array")
- if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
-
- croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
- if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
-
-
- $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
-
- my ($addr) = _db_open_recno($self, $got);
- my $obj ;
- if ($addr) {
- $obj = bless [$addr] , $self ;
- push @{ $obj }, $got->{Env} if $got->{Env} ;
- $obj->Txn($got->{Txn}) if $got->{Txn} ;
- }
- return $obj ;
-}
-
-*BerkeleyDB::Recno::TIEARRAY = \&BerkeleyDB::Recno::new ;
-*BerkeleyDB::Recno::db_stat = \&BerkeleyDB::Btree::db_stat ;
-
-package BerkeleyDB::Queue ;
-
-use vars qw(@ISA) ;
-@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
-use UNIVERSAL qw( isa ) ;
-use Carp ;
-
-sub new
-{
- my $self = shift ;
- my $got = BerkeleyDB::ParseParameters(
- {
- # Generic Stuff
- Filename => undef,
- Subname => undef,
- #Flags => BerkeleyDB::DB_CREATE(),
- Flags => 0,
- Property => 0,
- Mode => 0666,
- Cachesize => 0,
- Lorder => 0,
- Pagesize => 0,
- Env => undef,
- #Tie => undef,
- Txn => undef,
-
- # Queue specific
- Len => undef,
- Pad => undef,
- ArrayBase => 1, # lowest index in array
- ExtentSize => undef,
- }, @_) ;
-
- croak("Env not of type BerkeleyDB::Env")
- if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-
- croak("Txn not of type BerkeleyDB::Txn")
- if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
-
- croak("Tie needs a reference to an array")
- if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
-
- croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
- if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
-
-
- my ($addr) = _db_open_queue($self, $got);
- my $obj ;
- if ($addr) {
- $obj = bless [$addr] , $self ;
- push @{ $obj }, $got->{Env} if $got->{Env} ;
- $obj->Txn($got->{Txn}) if $got->{Txn} ;
- }
- return $obj ;
-}
-
-*BerkeleyDB::Queue::TIEARRAY = \&BerkeleyDB::Queue::new ;
-
-## package BerkeleyDB::Text ;
-##
-## use vars qw(@ISA) ;
-## @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
-## use UNIVERSAL qw( isa ) ;
-## use Carp ;
-##
-## sub new
-## {
-## my $self = shift ;
-## my $got = BerkeleyDB::ParseParameters(
-## {
-## # Generic Stuff
-## Filename => undef,
-## #Flags => BerkeleyDB::DB_CREATE(),
-## Flags => 0,
-## Property => 0,
-## Mode => 0666,
-## Cachesize => 0,
-## Lorder => 0,
-## Pagesize => 0,
-## Env => undef,
-## #Tie => undef,
-## Txn => undef,
-##
-## # Recno specific
-## Delim => undef,
-## Len => undef,
-## Pad => undef,
-## Btree => undef,
-## }, @_) ;
-##
-## croak("Env not of type BerkeleyDB::Env")
-## if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-##
-## croak("Txn not of type BerkeleyDB::Txn")
-## if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
-##
-## croak("-Tie needs a reference to an array")
-## if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
-##
-## # rearange for recno
-## $got->{Source} = $got->{Filename} if defined $got->{Filename} ;
-## delete $got->{Filename} ;
-## $got->{Fname} = $got->{Btree} if defined $got->{Btree} ;
-## return BerkeleyDB::Recno::_db_open_recno($self, $got);
-## }
-##
-## *BerkeleyDB::Text::TIEARRAY = \&BerkeleyDB::Text::new ;
-## *BerkeleyDB::Text::db_stat = \&BerkeleyDB::Btree::db_stat ;
-
-package BerkeleyDB::Unknown ;
-
-use vars qw(@ISA) ;
-@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
-use UNIVERSAL qw( isa ) ;
-use Carp ;
-
-sub new
-{
- my $self = shift ;
- my $got = BerkeleyDB::ParseParameters(
- {
- # Generic Stuff
- Filename => undef,
- Subname => undef,
- #Flags => BerkeleyDB::DB_CREATE(),
- Flags => 0,
- Property => 0,
- Mode => 0666,
- Cachesize => 0,
- Lorder => 0,
- Pagesize => 0,
- Env => undef,
- #Tie => undef,
- Txn => undef,
-
- }, @_) ;
-
- croak("Env not of type BerkeleyDB::Env")
- if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
-
- croak("Txn not of type BerkeleyDB::Txn")
- if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
-
- croak("-Tie needs a reference to a hash")
- if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
-
- my ($addr, $type) = _db_open_unknown($got);
- my $obj ;
- if ($addr) {
- $obj = bless [$addr], "BerkeleyDB::$type" ;
- push @{ $obj }, $got->{Env} if $got->{Env} ;
- $obj->Txn($got->{Txn}) if $got->{Txn} ;
- }
- return $obj ;
-}
-
-
-package BerkeleyDB::_tiedHash ;
-
-use Carp ;
-
-#sub TIEHASH
-#{
-# my $self = shift ;
-# my $db_object = shift ;
-#
-#print "Tiehash REF=[$self] [" . (ref $self) . "]\n" ;
-#
-# return bless { Obj => $db_object}, $self ;
-#}
-
-sub Tie
-{
- # Usage:
- #
- # $db->Tie \%hash ;
- #
-
- my $self = shift ;
-
- #print "Tie method REF=[$self] [" . (ref $self) . "]\n" ;
-
- croak("usage \$x->Tie \\%hash\n") unless @_ ;
- my $ref = shift ;
-
- croak("Tie needs a reference to a hash")
- if defined $ref and $ref !~ /HASH/ ;
-
- #tie %{ $ref }, ref($self), $self ;
- tie %{ $ref }, "BerkeleyDB::_tiedHash", $self ;
- return undef ;
-}
-
-
-sub TIEHASH
-{
- my $self = shift ;
- my $db_object = shift ;
- #return bless $db_object, 'BerkeleyDB::Common' ;
- return $db_object ;
-}
-
-sub STORE
-{
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
-
- $self->db_put($key, $value) ;
-}
-
-sub FETCH
-{
- my $self = shift ;
- my $key = shift ;
- my $value = undef ;
- $self->db_get($key, $value) ;
-
- return $value ;
-}
-
-sub EXISTS
-{
- my $self = shift ;
- my $key = shift ;
- my $value = undef ;
- $self->db_get($key, $value) == 0 ;
-}
-
-sub DELETE
-{
- my $self = shift ;
- my $key = shift ;
- $self->db_del($key) ;
-}
-
-sub CLEAR
-{
- my $self = shift ;
- my ($key, $value) = (0, 0) ;
- my $cursor = $self->db_cursor() ;
- while ($cursor->c_get($key, $value, BerkeleyDB::DB_PREV()) == 0)
- { $cursor->c_del() }
- #1 while $cursor->c_del() == 0 ;
- # cursor will self-destruct
-}
-
-#sub DESTROY
-#{
-# my $self = shift ;
-# print "BerkeleyDB::_tieHash::DESTROY\n" ;
-# $self->{Cursor}->c_close() if $self->{Cursor} ;
-#}
-
-package BerkeleyDB::_tiedArray ;
-
-use Carp ;
-
-sub Tie
-{
- # Usage:
- #
- # $db->Tie \@array ;
- #
-
- my $self = shift ;
-
- #print "Tie method REF=[$self] [" . (ref $self) . "]\n" ;
-
- croak("usage \$x->Tie \\%hash\n") unless @_ ;
- my $ref = shift ;
-
- croak("Tie needs a reference to an array")
- if defined $ref and $ref !~ /ARRAY/ ;
-
- #tie %{ $ref }, ref($self), $self ;
- tie @{ $ref }, "BerkeleyDB::_tiedArray", $self ;
- return undef ;
-}
-
-
-#sub TIEARRAY
-#{
-# my $self = shift ;
-# my $db_object = shift ;
-#
-#print "Tiearray REF=[$self] [" . (ref $self) . "]\n" ;
-#
-# return bless { Obj => $db_object}, $self ;
-#}
-
-sub TIEARRAY
-{
- my $self = shift ;
- my $db_object = shift ;
- #return bless $db_object, 'BerkeleyDB::Common' ;
- return $db_object ;
-}
-
-sub STORE
-{
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
-
- $self->db_put($key, $value) ;
-}
-
-sub FETCH
-{
- my $self = shift ;
- my $key = shift ;
- my $value = undef ;
- $self->db_get($key, $value) ;
-
- return $value ;
-}
-
-*CLEAR = \&BerkeleyDB::_tiedHash::CLEAR ;
-*FIRSTKEY = \&BerkeleyDB::_tiedHash::FIRSTKEY ;
-*NEXTKEY = \&BerkeleyDB::_tiedHash::NEXTKEY ;
-
-sub EXTEND {} # don't do anything with EXTEND
-
-
-sub SHIFT
-{
- my $self = shift;
- my ($key, $value) = (0, 0) ;
- my $cursor = $self->db_cursor() ;
- return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) != 0 ;
- return undef if $cursor->c_del() != 0 ;
-
- return $value ;
-}
-
-
-sub UNSHIFT
-{
- my $self = shift;
- croak "unshift is unsupported with Queue databases"
- if $self->type == BerkeleyDB::DB_QUEUE() ;
- if (@_)
- {
- my ($key, $value) = (0, 0) ;
- my $cursor = $self->db_cursor() ;
- if ($cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) == 0)
- {
- foreach $value (reverse @_)
- {
- $key = 0 ;
- $cursor->c_put($key, $value, BerkeleyDB::DB_BEFORE()) ;
- }
- }
- }
-}
-
-sub PUSH
-{
- my $self = shift;
- if (@_)
- {
- my ($key, $value) = (0, 0) ;
- my $cursor = $self->db_cursor() ;
- if ($cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) == 0)
- {
- foreach $value (@_)
- {
- ++ $key ;
- $self->db_put($key, $value) ;
- }
- }
-
-# can use this when DB_APPEND is fixed.
-# foreach $value (@_)
-# {
-# my $status = $cursor->c_put($key, $value, BerkeleyDB::DB_AFTER()) ;
-#print "[$status]\n" ;
-# }
- }
-}
-
-sub POP
-{
- my $self = shift;
- my ($key, $value) = (0, 0) ;
- my $cursor = $self->db_cursor() ;
- return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) != 0 ;
- return undef if $cursor->c_del() != 0 ;
-
- return $value ;
-}
-
-sub SPLICE
-{
- my $self = shift;
- croak "SPLICE is not implemented yet" ;
-}
-
-*shift = \&SHIFT ;
-*unshift = \&UNSHIFT ;
-*push = \&PUSH ;
-*pop = \&POP ;
-*clear = \&CLEAR ;
-*length = \&FETCHSIZE ;
-
-sub STORESIZE
-{
- croak "STORESIZE is not implemented yet" ;
-#print "STORESIZE @_\n" ;
-# my $self = shift;
-# my $length = shift ;
-# my $current_length = $self->FETCHSIZE() ;
-#print "length is $current_length\n";
-#
-# if ($length < $current_length) {
-#print "Make smaller $length < $current_length\n" ;
-# my $key ;
-# for ($key = $current_length - 1 ; $key >= $length ; -- $key)
-# { $self->db_del($key) }
-# }
-# elsif ($length > $current_length) {
-#print "Make larger $length > $current_length\n" ;
-# $self->db_put($length-1, "") ;
-# }
-# else { print "stay the same\n" }
-
-}
-
-
-
-#sub DESTROY
-#{
-# my $self = shift ;
-# print "BerkeleyDB::_tieArray::DESTROY\n" ;
-#}
-
-
-package BerkeleyDB::Common ;
-
-
-use Carp ;
-
-sub DESTROY
-{
- my $self = shift ;
- $self->_DESTROY() ;
-}
-
-sub Txn
-{
- my $self = shift ;
- my $txn = shift ;
- #print "BerkeleyDB::Common::Txn db [$self] txn [$txn]\n" ;
- if ($txn) {
- $self->_Txn($txn) ;
- push @{ $txn }, $self ;
- }
- else {
- $self->_Txn() ;
- }
- #print "end BerkeleyDB::Common::Txn \n";
-}
-
-
-sub get_dup
-{
- croak "Usage: \$db->get_dup(key [,flag])\n"
- unless @_ == 2 or @_ == 3 ;
-
- my $db = shift ;
- my $key = shift ;
- my $flag = shift ;
- my $value = 0 ;
- my $origkey = $key ;
- my $wantarray = wantarray ;
- my %values = () ;
- my @values = () ;
- my $counter = 0 ;
- my $status = 0 ;
- my $cursor = $db->db_cursor() ;
-
- # iterate through the database until either EOF ($status == 0)
- # or a different key is encountered ($key ne $origkey).
- for ($status = $cursor->c_get($key, $value, BerkeleyDB::DB_SET()) ;
- $status == 0 and $key eq $origkey ;
- $status = $cursor->c_get($key, $value, BerkeleyDB::DB_NEXT()) ) {
- # save the value or count number of matches
- if ($wantarray) {
- if ($flag)
- { ++ $values{$value} }
- else
- { push (@values, $value) }
- }
- else
- { ++ $counter }
-
- }
-
- return ($wantarray ? ($flag ? %values : @values) : $counter) ;
-}
-
-sub db_cursor
-{
- my $db = shift ;
- my ($addr) = $db->_db_cursor(@_) ;
- my $obj ;
- $obj = bless [$addr, $db] , "BerkeleyDB::Cursor" if $addr ;
- return $obj ;
-}
-
-sub db_join
-{
- croak 'Usage: $db->BerkeleyDB::Common::db_join([cursors], flags=0)'
- if @_ < 2 || @_ > 3 ;
- my $db = shift ;
- my ($addr) = $db->_db_join(@_) ;
- my $obj ;
- $obj = bless [$addr, $db] , "BerkeleyDB::Cursor" if $addr ;
- return $obj ;
-}
-
-package BerkeleyDB::Cursor ;
-
-sub c_close
-{
- my $cursor = shift ;
- $cursor->[1] = "" ;
- return $cursor->_c_close() ;
-}
-
-sub c_dup
-{
- my $cursor = shift ;
- my ($addr) = $cursor->_c_dup(@_) ;
- my $obj ;
- $obj = bless [$addr, $cursor->[1]] , "BerkeleyDB::Cursor" if $addr ;
- return $obj ;
-}
-
-sub DESTROY
-{
- my $self = shift ;
- $self->_DESTROY() ;
-}
-
-package BerkeleyDB::TxnMgr ;
-
-sub DESTROY
-{
- my $self = shift ;
- $self->_DESTROY() ;
-}
-
-sub txn_begin
-{
- my $txnmgr = shift ;
- my ($addr) = $txnmgr->_txn_begin(@_) ;
- my $obj ;
- $obj = bless [$addr, $txnmgr] , "BerkeleyDB::Txn" if $addr ;
- return $obj ;
-}
-
-package BerkeleyDB::Txn ;
-
-sub Txn
-{
- my $self = shift ;
- my $db ;
- # keep a reference to each db in the txn object
- foreach $db (@_) {
- $db->_Txn($self) ;
- push @{ $self}, $db ;
- }
-}
-
-sub txn_commit
-{
- my $self = shift ;
- $self->disassociate() ;
- my $status = $self->_txn_commit() ;
- return $status ;
-}
-
-sub txn_abort
-{
- my $self = shift ;
- $self->disassociate() ;
- my $status = $self->_txn_abort() ;
- return $status ;
-}
-
-sub disassociate
-{
- my $self = shift ;
- my $db ;
- while ( @{ $self } > 2) {
- $db = pop @{ $self } ;
- $db->Txn() ;
- }
- #print "end disassociate\n" ;
-}
-
-
-sub DESTROY
-{
- my $self = shift ;
-
- $self->disassociate() ;
- # first close the close the transaction
- $self->_DESTROY() ;
-}
-
-package BerkeleyDB::Term ;
-
-END
-{
- close_everything() ;
-}
-
-
-package BerkeleyDB ;
-
-
-
-# Autoload methods go after =cut, and are processed by the autosplit program.
-
-1;
-__END__
-
-
diff --git a/bdb/perl.BerkeleyDB/BerkeleyDB.pod b/bdb/perl.BerkeleyDB/BerkeleyDB.pod
deleted file mode 100644
index 2c5c3feb51e..00000000000
--- a/bdb/perl.BerkeleyDB/BerkeleyDB.pod
+++ /dev/null
@@ -1,1751 +0,0 @@
-=head1 NAME
-
-BerkeleyDB - Perl extension for Berkeley DB version 2 or 3
-
-=head1 SYNOPSIS
-
- use BerkeleyDB;
-
- $env = new BerkeleyDB::Env [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Hash', [OPTIONS] ;
- $db = new BerkeleyDB::Hash [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
- $db = new BerkeleyDB::Btree [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
- $db = new BerkeleyDB::Recno [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
- $db = new BerkeleyDB::Queue [OPTIONS] ;
-
- $db = new BerkeleyDB::Unknown [OPTIONS] ;
-
- $status = BerkeleyDB::db_remove [OPTIONS]
-
- $hash{$key} = $value ;
- $value = $hash{$key} ;
- each %hash ;
- keys %hash ;
- values %hash ;
-
- $status = $db->db_get()
- $status = $db->db_put() ;
- $status = $db->db_del() ;
- $status = $db->db_sync() ;
- $status = $db->db_close() ;
- $hash_ref = $db->db_stat() ;
- $status = $db->db_key_range();
- $type = $db->type() ;
- $status = $db->status() ;
- $boolean = $db->byteswapped() ;
-
- ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
- ($flag, $old_offset, $old_length) = $db->partial_clear() ;
-
- $cursor = $db->db_cursor([$flags]) ;
- $newcursor = $cursor->c_dup([$flags]);
- $status = $cursor->c_get() ;
- $status = $cursor->c_put() ;
- $status = $cursor->c_del() ;
- $status = $cursor->c_count() ;
- $status = $cursor->status() ;
- $status = $cursor->c_close() ;
-
- $cursor = $db->db_join() ;
- $status = $cursor->c_get() ;
- $status = $cursor->c_close() ;
-
- $status = $env->txn_checkpoint()
- $hash_ref = $env->txn_stat()
- $status = $env->setmutexlocks()
-
- $txn = $env->txn_begin() ;
- $status = $txn->txn_prepare()
- $status = $txn->txn_commit()
- $status = $txn->txn_abort()
- $status = $txn->txn_id()
-
- $BerkeleyDB::Error
- $BerkeleyDB::db_version
-
- # DBM Filters
- $old_filter = $db->filter_store_key ( sub { ... } ) ;
- $old_filter = $db->filter_store_value( sub { ... } ) ;
- $old_filter = $db->filter_fetch_key ( sub { ... } ) ;
- $old_filter = $db->filter_fetch_value( sub { ... } ) ;
-
- # deprecated, but supported
- $txn_mgr = $env->TxnMgr();
- $status = $txn_mgr->txn_checkpoint()
- $hash_ref = $txn_mgr->txn_stat()
- $txn = $txn_mgr->txn_begin() ;
-
-=head1 DESCRIPTION
-
-B<NOTE: This document is still under construction. Expect it to be
-incomplete in places.>
-
-This Perl module provides an interface to most of the functionality
-available in Berkeley DB versions 2 and 3. In general it is safe to assume
-that the interface provided here to be identical to the Berkeley DB
-interface. The main changes have been to make the Berkeley DB API work
-in a Perl way. Note that if you are using Berkeley DB 2.x, the new
-features available in Berkeley DB 3.x are not available via this module.
-
-The reader is expected to be familiar with the Berkeley DB
-documentation. Where the interface provided here is identical to the
-Berkeley DB library and the... TODO
-
-The B<db_appinit>, B<db_cursor>, B<db_open> and B<db_txn> man pages are
-particularly relevant.
-
-The interface to Berkeley DB is implemented with a number of Perl
-classes.
-
-=head1 ENV CLASS
-
-The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB
-function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and
-B<DBENV-E<gt>open> in Berkeley DB 3.x. Its purpose is to initialise a
-number of sub-systems that can then be used in a consistent way in all
-the databases you make use of the environment.
-
-If you don't intend using transactions, locking or logging, then you
-shouldn't need to make use of B<BerkeleyDB::Env>.
-
-=head2 Synopsis
-
- $env = new BerkeleyDB::Env
- [ -Home => $path, ]
- [ -Server => $name, ]
- [ -CacheSize => $number, ]
- [ -Config => { name => value, name => value }, ]
- [ -ErrFile => filename or filehandle, ]
- [ -ErrPrefix => "string", ]
- [ -Flags => number, ]
- [ -LockDetect => number, ]
- [ -Verbose => boolean, ]
-
-=over 5
-
-All the parameters to the BerkeleyDB::Env constructor are optional.
-
-=item -Home
-
-If present, this parameter should point to an existing directory. Any
-files that I<aren't> specified with an absolute path in the sub-systems
-that are initialised by the BerkeleyDB::Env class will be assumed to
-live in the B<Home> directory.
-
-For example, in the code fragment below the database "fred.db" will be
-opened in the directory "/home/databases" because it was specified as a
-relative path, but "joe.db" will be opened in "/other" because it was
-part of an absolute path.
-
- $env = new BerkeleyDB::Env
- -Home => "/home/databases"
- ...
-
- $db1 = new BerkeleyDB::Hash
- -Filename = "fred.db",
- -Env => $env
- ...
-
- $db2 = new BerkeleyDB::Hash
- -Filename = "/other/joe.db",
- -Env => $env
- ...
-
-=item -Server
-
-If present, this parameter should be the hostname of a server that is running
-the Berkeley DB RPC server. All databases will be accessed via the RPC server.
-
-=item -Cachesize
-
-If present, this parameter sets the size of the environments shared memory
-buffer pool.
-
-=item -Config
-
-This is a variation on the C<-Home> parameter, but it allows finer
-control of where specific types of files will be stored.
-
-The parameter expects a reference to a hash. Valid keys are:
-B<DB_DATA_DIR>, B<DB_LOG_DIR> and B<DB_TMP_DIR>
-
-The code below shows an example of how it can be used.
-
- $env = new BerkeleyDB::Env
- -Config => { DB_DATA_DIR => "/home/databases",
- DB_LOG_DIR => "/home/logs",
- DB_TMP_DIR => "/home/tmp"
- }
- ...
-
-=item -ErrFile
-
-Expects either the name of a file or a reference to a filehandle. Any
-errors generated internally by Berkeley DB will be logged to this file.
-
-=item -ErrPrefix
-
-Allows a prefix to be added to the error messages before they are sent
-to B<-ErrFile>.
-
-=item -Flags
-
-The B<Flags> parameter specifies both which sub-systems to initialise,
-as well as a number of environment-wide options.
-See the Berkeley DB documentation for more details of these options.
-
-Any of the following can be specified by OR'ing them:
-
-B<DB_CREATE>
-
-If any of the files specified do not already exist, create them.
-
-B<DB_INIT_CDB>
-
-Initialise the Concurrent Access Methods
-
-B<DB_INIT_LOCK>
-
-Initialise the Locking sub-system.
-
-B<DB_INIT_LOG>
-
-Initialise the Logging sub-system.
-
-B<DB_INIT_MPOOL>
-
-Initialise the ...
-
-B<DB_INIT_TXN>
-
-Initialise the ...
-
-B<DB_MPOOL_PRIVATE>
-
-Initialise the ...
-
-B<DB_INIT_MPOOL> is also specified.
-
-Initialise the ...
-
-B<DB_NOMMAP>
-
-Initialise the ...
-
-B<DB_RECOVER>
-
-
-
-B<DB_RECOVER_FATAL>
-
-B<DB_THREAD>
-
-B<DB_TXN_NOSYNC>
-
-B<DB_USE_ENVIRON>
-
-B<DB_USE_ENVIRON_ROOT>
-
-=item -LockDetect
-
-Specifies what to do when a lock conflict occurs. The value should be one of
-
-B<DB_LOCK_DEFAULT>
-
-B<DB_LOCK_OLDEST>
-
-B<DB_LOCK_RANDOM>
-
-B<DB_LOCK_YOUNGEST>
-
-=item -Verbose
-
-Add extra debugging information to the messages sent to B<-ErrFile>.
-
-=back
-
-=head2 Methods
-
-The environment class has the following methods:
-
-=over 5
-
-=item $env->errPrefix("string") ;
-
-This method is identical to the B<-ErrPrefix> flag. It allows the
-error prefix string to be changed dynamically.
-
-=item $txn = $env->TxnMgr()
-
-Constructor for creating a B<TxnMgr> object.
-See L<"TRANSACTIONS"> for more details of using transactions.
-
-This method is deprecated. Access the transaction methods using the B<txn_>
-methods below from the environment object directly.
-
-=item $env->txn_begin()
-
-TODO
-
-=item $env->txn_stat()
-
-TODO
-
-=item $env->txn_checkpoint()
-
-TODO
-
-=item $env->status()
-
-Returns the status of the last BerkeleyDB::Env method.
-
-=item $env->setmutexlocks()
-
-Only available in Berkeley Db 3.0 or greater. Calls
-B<db_env_set_mutexlocks> when used with Berkeley DB 3.1.x. When used with
-Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>.
-
-=back
-
-=head2 Examples
-
-TODO.
-
-=head1 THE DATABASE CLASSES
-
-B<BerkeleyDB> supports the following database formats:
-
-=over 5
-
-=item B<BerkeleyDB::Hash>
-
-This database type allows arbitrary key/value pairs to be stored in data
-files. This is equivalent to the functionality provided by other
-hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
-the files created using B<BerkeleyDB::Hash> are not compatible with any
-of the other packages mentioned.
-
-A default hashing algorithm, which will be adequate for most applications,
-is built into BerkeleyDB. If you do need to use your own hashing algorithm
-it is possible to write your own in Perl and have B<BerkeleyDB> use
-it instead.
-
-=item B<BerkeleyDB::Btree>
-
-The Btree format allows arbitrary key/value pairs to be stored in a
-B+tree.
-
-As with the B<BerkeleyDB::Hash> format, it is possible to provide a
-user defined Perl routine to perform the comparison of keys. By default,
-though, the keys are stored in lexical order.
-
-=item B<BerkeleyDB::Recno>
-
-TODO.
-
-
-=item B<BerkeleyDB::Queue>
-
-TODO.
-
-=item B<BerkeleyDB::Unknown>
-
-This isn't a database format at all. It is used when you want to open an
-existing Berkeley DB database without having to know what type is it.
-
-=back
-
-
-Each of the database formats described above is accessed via a
-corresponding B<BerkeleyDB> class. These will be described in turn in
-the next sections.
-
-=head1 BerkeleyDB::Hash
-
-Equivalent to calling B<db_open> with type B<DB_HASH> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_HASH> in
-Berkeley DB 3.x.
-
-Two forms of constructor are supported:
-
- $db = new BerkeleyDB::Hash
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Hash specific
- [ -Ffactor => number,]
- [ -Nelem => number,]
- [ -Hash => code reference,]
- [ -DupCompare => code reference,]
-
-and this
-
- [$db =] tie %hash, 'BerkeleyDB::Hash',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Hash specific
- [ -Ffactor => number,]
- [ -Nelem => number,]
- [ -Hash => code reference,]
- [ -DupCompare => code reference,]
-
-
-When the "tie" interface is used, reading from and writing to the database
-is achieved via the tied hash. In this case the database operates like
-a Perl associative array that happens to be stored on disk.
-
-In addition to the high-level tied hash interface, it is possible to
-make use of the underlying methods provided by Berkeley DB
-
-=head2 Options
-
-In addition to the standard set of options (see L<COMMON OPTIONS>)
-B<BerkeleyDB::Hash> supports these options:
-
-=over 5
-
-=item -Property
-
-Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
-following values:
-
-B<DB_DUP>
-
-When creating a new database, this flag enables the storing of duplicate
-keys in the database. If B<DB_DUPSORT> is not specified as well, the
-duplicates are stored in the order they are created in the database.
-
-B<DB_DUPSORT>
-
-Enables the sorting of duplicate keys in the database. Ignored if
-B<DB_DUP> isn't also specified.
-
-=item -Ffactor
-
-=item -Nelem
-
-See the Berkeley DB documentation for details of these options.
-
-=item -Hash
-
-Allows you to provide a user defined hash function. If not specified,
-a default hash function is used. Here is a template for a user-defined
-hash function
-
- sub hash
- {
- my ($data) = shift ;
- ...
- # return the hash value for $data
- return $hash ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Hash => \&hash,
- ...
-
-See L<""> for an example.
-
-=item -DupCompare
-
-Used in conjunction with the B<DB_DUPOSRT> flag.
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Property => DB_DUP|DB_DUPSORT,
- -DupCompare => \&compare,
- ...
-
-=back
-
-
-=head2 Methods
-
-B<BerkeleyDB::Hash> only supports the standard database methods.
-See L<COMMON DATABASE METHODS>.
-
-=head2 A Simple Tied Hash Example
-
- use strict ;
- use BerkeleyDB ;
- use vars qw( %h $k $v ) ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $h{"apple"} = "red" ;
- $h{"orange"} = "orange" ;
- $h{"banana"} = "yellow" ;
- $h{"tomato"} = "red" ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $h{"banana"} ;
-
- # Delete a key/value pair.
- delete $h{"apple"} ;
-
- # print the contents of the file
- while (($k, $v) = each %h)
- { print "$k -> $v\n" }
-
- untie %h ;
-
-here is the output:
-
- Banana Exists
-
- orange -> orange
- tomato -> red
- banana -> yellow
-
-Note that the like ordinary associative arrays, the order of the keys
-retrieved from a Hash database are in an apparently random order.
-
-=head2 Another Simple Hash Example
-
-Do the same as the previous example but not using tie.
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("apple", "red") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("banana", "yellow") ;
- $db->db_put("tomato", "red") ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;
-
- # Delete a key/value pair.
- $db->db_del("apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
-
-=head2 Duplicate keys
-
-The code below is a variation on the examples above. This time the hash has
-been inverted. The key this time is colour and the value is the fruit name.
-The B<DB_DUP> flag has been specified to allow duplicates.
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_DUP
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("red", "apple") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("green", "banana") ;
- $db->db_put("yellow", "banana") ;
- $db->db_put("red", "tomato") ;
- $db->db_put("green", "apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
-
-here is the output:
-
- orange -> orange
- yellow -> banana
- red -> apple
- red -> tomato
- green -> banana
- green -> apple
-
-=head2 Sorting Duplicate Keys
-
-In the previous example, when there were duplicate keys, the values are
-sorted in the order they are stored in. The code below is
-identical to the previous example except the B<DB_DUPSORT> flag is
-specified.
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_DUP | DB_DUPSORT
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("red", "apple") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("green", "banana") ;
- $db->db_put("yellow", "banana") ;
- $db->db_put("red", "tomato") ;
- $db->db_put("green", "apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
-
-Notice that in the output below the duplicate values are sorted.
-
- orange -> orange
- yellow -> banana
- red -> apple
- red -> tomato
- green -> apple
- green -> banana
-
-=head2 Custom Sorting Duplicate Keys
-
-Another variation
-
-TODO
-
-=head2 Changing the hash
-
-TODO
-
-=head2 Using db_stat
-
-TODO
-
-=head1 BerkeleyDB::Btree
-
-Equivalent to calling B<db_open> with type B<DB_BTREE> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_BTREE> in
-Berkeley DB 3.x.
-
-Two forms of constructor are supported:
-
-
- $db = new BerkeleyDB::Btree
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Btree specific
- [ -Minkey => number,]
- [ -Compare => code reference,]
- [ -DupCompare => code reference,]
- [ -Prefix => code reference,]
-
-and this
-
- [$db =] tie %hash, 'BerkeleyDB::Btree',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Btree specific
- [ -Minkey => number,]
- [ -Compare => code reference,]
- [ -DupCompare => code reference,]
- [ -Prefix => code reference,]
-
-=head2 Options
-
-In addition to the standard set of options (see L<COMMON OPTIONS>)
-B<BerkeleyDB::Btree> supports these options:
-
-=over 5
-
-=item -Property
-
-Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
-following values:
-
-B<DB_DUP>
-
-When creating a new database, this flag enables the storing of duplicate
-keys in the database. If B<DB_DUPSORT> is not specified as well, the
-duplicates are stored in the order they are created in the database.
-
-B<DB_DUPSORT>
-
-Enables the sorting of duplicate keys in the database. Ignored if
-B<DB_DUP> isn't also specified.
-
-=item Minkey
-
-TODO
-
-=item Compare
-
-Allow you to override the default sort order used in the database. See
-L<"Changing the sort order"> for an example.
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Compare => \&compare,
- ...
-
-=item Prefix
-
- sub prefix
- {
- my ($key, $key2) = @_ ;
- ...
- # return number of bytes of $key2 which are
- # necessary to determine that it is greater than $key1
- return $bytes ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Prefix => \&prefix,
- ...
-=item DupCompare
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -DupCompare => \&compare,
- ...
-
-=back
-
-=head2 Methods
-
-B<BerkeleyDB::Btree> supports the following database methods.
-See also L<COMMON DATABASE METHODS>.
-
-All the methods below return 0 to indicate success.
-
-=over 5
-
-=item $status = $db->db_key_range($key, $less, $equal, $greater [, $flags])
-
-Given a key, C<$key>, this method returns the proportion of keys less than
-C<$key> in C<$less>, the proportion equal to C<$key> in C<$equal> and the
-proportion greater than C<$key> in C<$greater>.
-
-The proportion is returned as a double in the range 0.0 to 1.0.
-
-=back
-
-=head2 A Simple Btree Example
-
-The code below is a simple example of using a btree database.
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "tree" ;
- unlink $filename ;
- my %h ;
- tie %h, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
-
-Here is the output from the code above. The keys have been sorted using
-Berkeley DB's default sorting algorithm.
-
- Smith
- Wall
- mouse
-
-
-=head2 Changing the sort order
-
-It is possible to supply your own sorting algorithm if the one that Berkeley
-DB used isn't suitable. The code below is identical to the previous example
-except for the case insensitive compare function.
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "tree" ;
- unlink $filename ;
- my %h ;
- tie %h, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Compare => sub { lc $_[0] cmp lc $_[1] }
- or die "Cannot open $filename: $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
-
-Here is the output from the code above.
-
- mouse
- Smith
- Wall
-
-There are a few point to bear in mind if you want to change the
-ordering in a BTREE database:
-
-=over 5
-
-=item 1.
-
-The new compare function must be specified when you create the database.
-
-=item 2.
-
-You cannot change the ordering once the database has been created. Thus
-you must use the same compare function every time you access the
-database.
-
-=back
-
-=head2 Using db_stat
-
-TODO
-
-=head1 BerkeleyDB::Recno
-
-Equivalent to calling B<db_open> with type B<DB_RECNO> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_RECNO> in
-Berkeley DB 3.x.
-
-Two forms of constructor are supported:
-
- $db = new BerkeleyDB::Recno
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Recno specific
- [ -Delim => byte,]
- [ -Len => number,]
- [ -Pad => byte,]
- [ -Source => filename,]
-
-and this
-
- [$db =] tie @arry, 'BerkeleyDB::Recno',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Recno specific
- [ -Delim => byte,]
- [ -Len => number,]
- [ -Pad => byte,]
- [ -Source => filename,]
-
-=head2 A Recno Example
-
-Here is a simple example that uses RECNO (if you are using a version
-of Perl earlier than 5.004_57 this example won't work -- see
-L<Extra RECNO Methods> for a workaround).
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- tie @h, 'BerkeleyDB::Recno',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_RENUMBER
- or die "Cannot open $filename: $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- push @h, "green", "black" ;
-
- my $elements = scalar @h ;
- print "The array contains $elements entries\n" ;
-
- my $last = pop @h ;
- print "popped $last\n" ;
-
- unshift @h, "white" ;
- my $first = shift @h ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- untie @h ;
-
-Here is the output from the script:
-
- The array contains 5 entries
- popped black
- shifted white
- Element 1 Exists with value blue
- The last element is green
- The 2nd last element is yellow
-
-=head1 BerkeleyDB::Queue
-
-Equivalent to calling B<db_create> followed by B<DB-E<gt>open> with
-type B<DB_QUEUE> in Berkeley DB 3.x. This database format isn't available if
-you use Berkeley DB 2.x.
-
-Two forms of constructor are supported:
-
- $db = new BerkeleyDB::Queue
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Queue specific
- [ -Len => number,]
- [ -Pad => byte,]
- [ -ExtentSize => number, ]
-
-and this
-
- [$db =] tie @arry, 'BerkeleyDB::Queue',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Queue specific
- [ -Len => number,]
- [ -Pad => byte,]
-
-
-=head1 BerkeleyDB::Unknown
-
-This class is used to open an existing database.
-
-Equivalent to calling B<db_open> with type B<DB_UNKNOWN> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_UNKNOWN> in
-Berkeley DB 3.x.
-
-The constructor looks like this:
-
- $db = new BerkeleyDB::Unknown
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
-
-
-=head2 An example
-
-=head1 COMMON OPTIONS
-
-All database access class constructors support the common set of
-options defined below. All are optional.
-
-=over 5
-
-=item -Filename
-
-The database filename. If no filename is specified, a temporary file will
-be created and removed once the program terminates.
-
-=item -Subname
-
-Specifies the name of the sub-database to open.
-This option is only valid if you are using Berkeley DB 3.x.
-
-=item -Flags
-
-Specify how the database will be opened/created. The valid flags are:
-
-B<DB_CREATE>
-
-Create any underlying files, as necessary. If the files do not already
-exist and the B<DB_CREATE> flag is not specified, the call will fail.
-
-B<DB_NOMMAP>
-
-Not supported by BerkeleyDB.
-
-B<DB_RDONLY>
-
-Opens the database in read-only mode.
-
-B<DB_THREAD>
-
-Not supported by BerkeleyDB.
-
-B<DB_TRUNCATE>
-
-If the database file already exists, remove all the data before
-opening it.
-
-=item -Mode
-
-Determines the file protection when the database is created. Defaults
-to 0666.
-
-=item -Cachesize
-
-=item -Lorder
-
-=item -Pagesize
-
-=item -Env
-
-When working under a Berkeley DB environment, this parameter
-
-Defaults to no environment.
-
-=item -Txn
-
-TODO.
-
-=back
-
-=head1 COMMON DATABASE METHODS
-
-All the database interfaces support the common set of methods defined
-below.
-
-All the methods below return 0 to indicate success.
-
-=head2 $status = $db->db_get($key, $value [, $flags])
-
-Given a key (C<$key>) this method reads the value associated with it
-from the database. If it exists, the value read from the database is
-returned in the C<$value> parameter.
-
-The B<$flags> parameter is optional. If present, it must be set to B<one>
-of the following values:
-
-=over 5
-
-=item B<DB_GET_BOTH>
-
-When the B<DB_GET_BOTH> flag is specified, B<db_get> checks for the
-existence of B<both> the C<$key> B<and> C<$value> in the database.
-
-=item B<DB_SET_RECNO>
-
-TODO.
-
-=back
-
-In addition, the following value may be set by logically OR'ing it into
-the B<$flags> parameter:
-
-=over 5
-
-=item B<DB_RMW>
-
-TODO
-
-=back
-
-
-=head2 $status = $db->db_put($key, $value [, $flags])
-
-Stores a key/value pair in the database.
-
-The B<$flags> parameter is optional. If present it must be set to B<one>
-of the following values:
-
-=over 5
-
-=item B<DB_APPEND>
-
-This flag is only applicable when accessing a B<BerkeleyDB::Recno>
-database.
-
-TODO.
-
-
-=item B<DB_NOOVERWRITE>
-
-If this flag is specified and C<$key> already exists in the database,
-the call to B<db_put> will return B<DB_KEYEXIST>.
-
-=back
-
-=head2 $status = $db->db_del($key [, $flags])
-
-Deletes a key/value pair in the database associated with C<$key>.
-If duplicate keys are enabled in the database, B<db_del> will delete
-B<all> key/value pairs with key C<$key>.
-
-The B<$flags> parameter is optional and is currently unused.
-
-=head2 $status = $db->db_sync()
-
-If any parts of the database are in memory, write them to the database.
-
-=head2 $cursor = $db->db_cursor([$flags])
-
-Creates a cursor object. This is used to access the contents of the
-database sequentially. See L<CURSORS> for details of the methods
-available when working with cursors.
-
-The B<$flags> parameter is optional. If present it must be set to B<one>
-of the following values:
-
-=over 5
-
-=item B<DB_RMW>
-
-TODO.
-
-=back
-
-=head2 ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
-
-TODO
-
-=head2 ($flag, $old_offset, $old_length) = $db->partial_clear() ;
-
-TODO
-
-=head2 $db->byteswapped()
-
-TODO
-
-=head2 $db->type()
-
-Returns the type of the database. The possible return code are B<DB_HASH>
-for a B<BerkeleyDB::Hash> database, B<DB_BTREE> for a B<BerkeleyDB::Btree>
-database and B<DB_RECNO> for a B<BerkeleyDB::Recno> database. This method
-is typically used when a database has been opened with
-B<BerkeleyDB::Unknown>.
-
-=item $ref = $db->db_stat()
-
-Returns a reference to an associative array containing information about
-the database. The keys of the associative array correspond directly to the
-names of the fields defined in the Berkeley DB documentation. For example,
-in the DB documentation, the field B<bt_version> stores the version of the
-Btree database. Assuming you called B<db_stat> on a Btree database the
-equivalent field would be accessed as follows:
-
- $version = $ref->{'bt_version'} ;
-
-If you are using Berkeley DB 3.x, this method will work will all database
-formats. When DB 2.x is used, it only works with B<BerkeleyDB::Btree>.
-
-=head2 $status = $db->status()
-
-Returns the status of the last C<$db> method called.
-
-=head1 CURSORS
-
-A cursor is used whenever you want to access the contents of a database
-in sequential order.
-A cursor object is created with the C<db_cursor>
-
-A cursor object has the following methods available:
-
-=head2 $newcursor = $cursor->c_dup($flags)
-
-Creates a duplicate of C<$cursor>. This method needs Berkeley DB 3.0.x or better.
-
-The C<$flags> parameter is optional and can take the following value:
-
-=over 5
-
-=item DB_POSITION
-
-When present this flag will position the new cursor at the same place as the
-existing cursor.
-
-=back
-
-=head2 $status = $cursor->c_get($key, $value, $flags)
-
-Reads a key/value pair from the database, returning the data in C<$key>
-and C<$value>. The key/value pair actually read is controlled by the
-C<$flags> parameter, which can take B<one> of the following values:
-
-=over 5
-
-=item B<DB_FIRST>
-
-Set the cursor to point to the first key/value pair in the
-database. Return the key/value pair in C<$key> and C<$value>.
-
-=item B<DB_LAST>
-
-Set the cursor to point to the last key/value pair in the database. Return
-the key/value pair in C<$key> and C<$value>.
-
-=item B<DB_NEXT>
-
-If the cursor is already pointing to a key/value pair, it will be
-incremented to point to the next key/value pair and return its contents.
-
-If the cursor isn't initialised, B<DB_NEXT> works just like B<DB_FIRST>.
-
-If the cursor is already positioned at the last key/value pair, B<c_get>
-will return B<DB_NOTFOUND>.
-
-=item B<DB_NEXT_DUP>
-
-This flag is only valid when duplicate keys have been enabled in
-a database.
-If the cursor is already pointing to a key/value pair and the key of
-the next key/value pair is identical, the cursor will be incremented to
-point to it and their contents returned.
-
-=item B<DB_PREV>
-
-If the cursor is already pointing to a key/value pair, it will be
-decremented to point to the previous key/value pair and return its
-contents.
-
-If the cursor isn't initialised, B<DB_PREV> works just like B<DB_LAST>.
-
-If the cursor is already positioned at the first key/value pair, B<c_get>
-will return B<DB_NOTFOUND>.
-
-=item B<DB_CURRENT>
-
-If the cursor has been set to point to a key/value pair, return their
-contents.
-If the key/value pair referenced by the cursor has been deleted, B<c_get>
-will return B<DB_KEYEMPTY>.
-
-=item B<DB_SET>
-
-Set the cursor to point to the key/value pair referenced by B<$key>
-and return the value in B<$value>.
-
-=item B<DB_SET_RANGE>
-
-This flag is a variation on the B<DB_SET> flag. As well as returning
-the value, it also returns the key, via B<$key>.
-When used with a B<BerkeleyDB::Btree> database the key matched by B<c_get>
-will be the shortest key (in length) which is greater than or equal to
-the key supplied, via B<$key>. This allows partial key searches.
-See ??? for an example of how to use this flag.
-
-=item B<DB_GET_BOTH>
-
-Another variation on B<DB_SET>. This one returns both the key and
-the value.
-
-=item B<DB_SET_RECNO>
-
-TODO.
-
-=item B<DB_GET_RECNO>
-
-TODO.
-
-=back
-
-In addition, the following value may be set by logically OR'ing it into
-the B<$flags> parameter:
-
-=over 5
-
-=item B<DB_RMW>
-
-TODO.
-
-=back
-
-=head2 $status = $cursor->c_put($key, $value, $flags)
-
-Stores the key/value pair in the database. The position that the data is
-stored in the database is controlled by the C<$flags> parameter, which
-must take B<one> of the following values:
-
-=over 5
-
-=item B<DB_AFTER>
-
-When used with a Btree or Hash database, a duplicate of the key referenced
-by the current cursor position will be created and the contents of
-B<$value> will be associated with it - B<$key> is ignored.
-The new key/value pair will be stored immediately after the current
-cursor position.
-Obviously the database has to have been opened with B<DB_DUP>.
-
-When used with a Recno ... TODO
-
-
-=item B<DB_BEFORE>
-
-When used with a Btree or Hash database, a duplicate of the key referenced
-by the current cursor position will be created and the contents of
-B<$value> will be associated with it - B<$key> is ignored.
-The new key/value pair will be stored immediately before the current
-cursor position.
-Obviously the database has to have been opened with B<DB_DUP>.
-
-When used with a Recno ... TODO
-
-=item B<DB_CURRENT>
-
-If the cursor has been initialised, replace the value of the key/value
-pair stored in the database with the contents of B<$value>.
-
-=item B<DB_KEYFIRST>
-
-Only valid with a Btree or Hash database. This flag is only really
-used when duplicates are enabled in the database and sorted duplicates
-haven't been specified.
-In this case the key/value pair will be inserted as the first entry in
-the duplicates for the particular key.
-
-=item B<DB_KEYLAST>
-
-Only valid with a Btree or Hash database. This flag is only really
-used when duplicates are enabled in the database and sorted duplicates
-haven't been specified.
-In this case the key/value pair will be inserted as the last entry in
-the duplicates for the particular key.
-
-=back
-
-=head2 $status = $cursor->c_del([$flags])
-
-This method deletes the key/value pair associated with the current cursor
-position. The cursor position will not be changed by this operation, so
-any subsequent cursor operation must first initialise the cursor to
-point to a valid key/value pair.
-
-If the key/value pair associated with the cursor have already been
-deleted, B<c_del> will return B<DB_KEYEMPTY>.
-
-The B<$flags> parameter is not used at present.
-
-=head2 $status = $cursor->c_del($cnt [, $flags])
-
-Stores the number of duplicates at the current cursor position in B<$cnt>.
-
-The B<$flags> parameter is not used at present. This method needs
-Berkeley DB 3.1 or better.
-
-=head2 $status = $cursor->status()
-
-Returns the status of the last cursor method as a dual type.
-
-=head2 Cursor Examples
-
-TODO
-
-Iterating from first to last, then in reverse.
-
-examples of each of the flags.
-
-=head1 JOIN
-
-Join support for BerkeleyDB is in progress. Watch this space.
-
-TODO
-
-=head1 TRANSACTIONS
-
-TODO.
-
-=head1 DBM Filters
-
-A DBM Filter is a piece of code that is be used when you I<always>
-want to make the same transformation to all keys and/or values in a DBM
-database. All of the database classes (BerkeleyDB::Hash,
-BerkeleyDB::Btree and BerkeleyDB::Recno) support DBM Filters.
-
-There are four methods associated with DBM Filters. All work
-identically, and each is used to install (or uninstall) a single DBM
-Filter. Each expects a single parameter, namely a reference to a sub.
-The only difference between them is the place that the filter is
-installed.
-
-To summarise:
-
-=over 5
-
-=item B<filter_store_key>
-
-If a filter has been installed with this method, it will be invoked
-every time you write a key to a DBM database.
-
-=item B<filter_store_value>
-
-If a filter has been installed with this method, it will be invoked
-every time you write a value to a DBM database.
-
-
-=item B<filter_fetch_key>
-
-If a filter has been installed with this method, it will be invoked
-every time you read a key from a DBM database.
-
-=item B<filter_fetch_value>
-
-If a filter has been installed with this method, it will be invoked
-every time you read a value from a DBM database.
-
-=back
-
-You can use any combination of the methods, from none, to all four.
-
-All filter methods return the existing filter, if present, or C<undef>
-in not.
-
-To delete a filter pass C<undef> to it.
-
-=head2 The Filter
-
-When each filter is called by Perl, a local copy of C<$_> will contain
-the key or value to be filtered. Filtering is achieved by modifying
-the contents of C<$_>. The return code from the filter is ignored.
-
-=head2 An Example -- the NULL termination problem.
-
-Consider the following scenario. You have a DBM database that you need
-to share with a third-party C application. The C application assumes
-that I<all> keys and values are NULL terminated. Unfortunately when
-Perl writes to DBM databases it doesn't use NULL termination, so your
-Perl application will have to manage NULL termination itself. When you
-write to the database you will have to use something like this:
-
- $hash{"$key\0"} = "$value\0" ;
-
-Similarly the NULL needs to be taken into account when you are considering
-the length of existing keys/values.
-
-It would be much better if you could ignore the NULL terminations issue
-in the main application code and have a mechanism that automatically
-added the terminating NULL to all keys and values whenever you write to
-the database and have them removed when you read from the database. As I'm
-sure you have already guessed, this is a problem that DBM Filters can
-fix very easily.
-
- use strict ;
- use BerkeleyDB ;
-
- my %hash ;
- my $filename = "filt.db" ;
- unlink $filename ;
-
- my $db = tie %hash, 'BerkeleyDB::Hash',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- # Install DBM Filters
- $db->filter_fetch_key ( sub { s/\0$// } ) ;
- $db->filter_store_key ( sub { $_ .= "\0" } ) ;
- $db->filter_fetch_value( sub { s/\0$// } ) ;
- $db->filter_store_value( sub { $_ .= "\0" } ) ;
-
- $hash{"abc"} = "def" ;
- my $a = $hash{"ABC"} ;
- # ...
- undef $db ;
- untie %hash ;
-
-Hopefully the contents of each of the filters should be
-self-explanatory. Both "fetch" filters remove the terminating NULL,
-and both "store" filters add a terminating NULL.
-
-
-=head2 Another Example -- Key is a C int.
-
-Here is another real-life example. By default, whenever Perl writes to
-a DBM database it always writes the key and value as strings. So when
-you use this:
-
- $hash{12345} = "something" ;
-
-the key 12345 will get stored in the DBM database as the 5 byte string
-"12345". If you actually want the key to be stored in the DBM database
-as a C int, you will have to use C<pack> when writing, and C<unpack>
-when reading.
-
-Here is a DBM Filter that does it:
-
- use strict ;
- use BerkeleyDB ;
- my %hash ;
- my $filename = "filt.db" ;
- unlink $filename ;
-
-
- my $db = tie %hash, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
- $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
- $hash{123} = "def" ;
- # ...
- undef $db ;
- untie %hash ;
-
-This time only two filters have been used -- we only need to manipulate
-the contents of the key, so it wasn't necessary to install any value
-filters.
-
-=head1 Using BerkeleyDB with MLDBM
-
-Both BerkeleyDB::Hash and BerkeleyDB::Btree can be used with the MLDBM
-module. The code fragment below shows how to open associate MLDBM with
-BerkeleyDB::Btree. To use BerkeleyDB::Hash just replace
-BerkeleyDB::Btree with BerkeleyDB::Hash.
-
- use strict ;
- use BerkeleyDB ;
- use MLDBM qw(BerkeleyDB::Btree) ;
- use Data::Dumper;
-
- my $filename = 'testmldbm' ;
- my %o ;
-
- unlink $filename ;
- tie %o, 'MLDBM', -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open database '$filename: $!\n";
-
-See the MLDBM documentation for information on how to use the module
-and for details of its limitations.
-
-=head1 EXAMPLES
-
-TODO.
-
-=head1 HINTS & TIPS
-
-=head2 Sharing Databases With C Applications
-
-There is no technical reason why a Berkeley DB database cannot be
-shared by both a Perl and a C application.
-
-The vast majority of problems that are reported in this area boil down
-to the fact that C strings are NULL terminated, whilst Perl strings
-are not. See L<An Example -- the NULL termination problem.> in the DBM
-FILTERS section for a generic way to work around this problem.
-
-
-=head2 The untie Gotcha
-
-TODO
-
-=head1 COMMON QUESTIONS
-
-This section attempts to answer some of the more common questions that
-I get asked.
-
-
-=head2 Relationship with DB_File
-
-Before Berkeley DB 2.x was written there was only one Perl module that
-interfaced to Berkeley DB. That module is called B<DB_File>. Although
-B<DB_File> can be build with Berkeley DB 1.x, 2.x or 3.x, it only provides
-an interface to the functionality available in Berkeley DB 1.x. That
-means that it doesn't support transactions, locking or any of the other
-new features available in DB 2.x or 3.x.
-
-=head2 How do I store Perl data structures with BerkeleyDB?
-
-See L<Using BerkeleyDB with MLDBM>.
-
-=head1 HISTORY
-
-See the Changes file.
-
-=head1 AVAILABILITY
-
-The most recent version of B<BerkeleyDB> can always be found
-on CPAN (see L<perlmod/CPAN> for details), in the directory
-F<modules/by-module/BerkeleyDB>.
-
-The official web site for Berkeley DB is F<http://www.sleepycat.com>.
-
-=head1 COPYRIGHT
-
-Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This program
-is free software; you can redistribute it and/or modify it under the
-same terms as Perl itself.
-
-Although B<BerkeleyDB> is covered by the Perl license, the library it
-makes use of, namely Berkeley DB, is not. Berkeley DB has its own
-copyright and its own license. Please take the time to read it.
-
-Here are few words taken from the Berkeley DB FAQ (at
-F<http://www.sleepycat.com>) regarding the license:
-
- Do I have to license DB to use it in Perl scripts?
-
- No. The Berkeley DB license requires that software that uses
- Berkeley DB be freely redistributable. In the case of Perl, that
- software is Perl, and not your scripts. Any Perl scripts that you
- write are your property, including scripts that make use of Berkeley
- DB. Neither the Perl license nor the Berkeley DB license
- place any restriction on what you may do with them.
-
-If you are in any doubt about the license situation, contact either the
-Berkeley DB authors or the author of BerkeleyDB.
-See L<"AUTHOR"> for details.
-
-
-=head1 AUTHOR
-
-Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt>.
-
-Questions about Berkeley DB may be addressed to E<lt>db@sleepycat.comE<gt>.
-
-=head1 SEE ALSO
-
-perl(1), DB_File, Berkeley DB.
-
-=cut
diff --git a/bdb/perl.BerkeleyDB/BerkeleyDB.pod.P b/bdb/perl.BerkeleyDB/BerkeleyDB.pod.P
deleted file mode 100644
index 2bcff2d99d1..00000000000
--- a/bdb/perl.BerkeleyDB/BerkeleyDB.pod.P
+++ /dev/null
@@ -1,1518 +0,0 @@
-=head1 NAME
-
-BerkeleyDB - Perl extension for Berkeley DB version 2 or 3
-
-=head1 SYNOPSIS
-
- use BerkeleyDB;
-
- $env = new BerkeleyDB::Env [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Hash', [OPTIONS] ;
- $db = new BerkeleyDB::Hash [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
- $db = new BerkeleyDB::Btree [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
- $db = new BerkeleyDB::Recno [OPTIONS] ;
-
- $db = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
- $db = new BerkeleyDB::Queue [OPTIONS] ;
-
- $db = new BerkeleyDB::Unknown [OPTIONS] ;
-
- $status = BerkeleyDB::db_remove [OPTIONS]
-
- $hash{$key} = $value ;
- $value = $hash{$key} ;
- each %hash ;
- keys %hash ;
- values %hash ;
-
- $status = $db->db_get()
- $status = $db->db_put() ;
- $status = $db->db_del() ;
- $status = $db->db_sync() ;
- $status = $db->db_close() ;
- $hash_ref = $db->db_stat() ;
- $status = $db->db_key_range();
- $type = $db->type() ;
- $status = $db->status() ;
- $boolean = $db->byteswapped() ;
-
- ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
- ($flag, $old_offset, $old_length) = $db->partial_clear() ;
-
- $cursor = $db->db_cursor([$flags]) ;
- $newcursor = $cursor->c_dup([$flags]);
- $status = $cursor->c_get() ;
- $status = $cursor->c_put() ;
- $status = $cursor->c_del() ;
- $status = $cursor->c_count() ;
- $status = $cursor->status() ;
- $status = $cursor->c_close() ;
-
- $cursor = $db->db_join() ;
- $status = $cursor->c_get() ;
- $status = $cursor->c_close() ;
-
- $status = $env->txn_checkpoint()
- $hash_ref = $env->txn_stat()
- $status = $env->setmutexlocks()
-
- $txn = $env->txn_begin() ;
- $status = $txn->txn_prepare()
- $status = $txn->txn_commit()
- $status = $txn->txn_abort()
- $status = $txn->txn_id()
-
- $BerkeleyDB::Error
- $BerkeleyDB::db_version
-
- # DBM Filters
- $old_filter = $db->filter_store_key ( sub { ... } ) ;
- $old_filter = $db->filter_store_value( sub { ... } ) ;
- $old_filter = $db->filter_fetch_key ( sub { ... } ) ;
- $old_filter = $db->filter_fetch_value( sub { ... } ) ;
-
- # deprecated, but supported
- $txn_mgr = $env->TxnMgr();
- $status = $txn_mgr->txn_checkpoint()
- $hash_ref = $txn_mgr->txn_stat()
- $txn = $txn_mgr->txn_begin() ;
-
-=head1 DESCRIPTION
-
-B<NOTE: This document is still under construction. Expect it to be
-incomplete in places.>
-
-This Perl module provides an interface to most of the functionality
-available in Berkeley DB versions 2 and 3. In general it is safe to assume
-that the interface provided here to be identical to the Berkeley DB
-interface. The main changes have been to make the Berkeley DB API work
-in a Perl way. Note that if you are using Berkeley DB 2.x, the new
-features available in Berkeley DB 3.x are not available via this module.
-
-The reader is expected to be familiar with the Berkeley DB
-documentation. Where the interface provided here is identical to the
-Berkeley DB library and the... TODO
-
-The B<db_appinit>, B<db_cursor>, B<db_open> and B<db_txn> man pages are
-particularly relevant.
-
-The interface to Berkeley DB is implemented with a number of Perl
-classes.
-
-=head1 ENV CLASS
-
-The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB
-function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and
-B<DBENV-E<gt>open> in Berkeley DB 3.x. Its purpose is to initialise a
-number of sub-systems that can then be used in a consistent way in all
-the databases you make use of the environment.
-
-If you don't intend using transactions, locking or logging, then you
-shouldn't need to make use of B<BerkeleyDB::Env>.
-
-=head2 Synopsis
-
- $env = new BerkeleyDB::Env
- [ -Home => $path, ]
- [ -Server => $name, ]
- [ -CacheSize => $number, ]
- [ -Config => { name => value, name => value }, ]
- [ -ErrFile => filename or filehandle, ]
- [ -ErrPrefix => "string", ]
- [ -Flags => number, ]
- [ -LockDetect => number, ]
- [ -Verbose => boolean, ]
-
-=over 5
-
-All the parameters to the BerkeleyDB::Env constructor are optional.
-
-=item -Home
-
-If present, this parameter should point to an existing directory. Any
-files that I<aren't> specified with an absolute path in the sub-systems
-that are initialised by the BerkeleyDB::Env class will be assumed to
-live in the B<Home> directory.
-
-For example, in the code fragment below the database "fred.db" will be
-opened in the directory "/home/databases" because it was specified as a
-relative path, but "joe.db" will be opened in "/other" because it was
-part of an absolute path.
-
- $env = new BerkeleyDB::Env
- -Home => "/home/databases"
- ...
-
- $db1 = new BerkeleyDB::Hash
- -Filename = "fred.db",
- -Env => $env
- ...
-
- $db2 = new BerkeleyDB::Hash
- -Filename = "/other/joe.db",
- -Env => $env
- ...
-
-=item -Server
-
-If present, this parameter should be the hostname of a server that is running
-the Berkeley DB RPC server. All databases will be accessed via the RPC server.
-
-=item -Cachesize
-
-If present, this parameter sets the size of the environments shared memory
-buffer pool.
-
-=item -Config
-
-This is a variation on the C<-Home> parameter, but it allows finer
-control of where specific types of files will be stored.
-
-The parameter expects a reference to a hash. Valid keys are:
-B<DB_DATA_DIR>, B<DB_LOG_DIR> and B<DB_TMP_DIR>
-
-The code below shows an example of how it can be used.
-
- $env = new BerkeleyDB::Env
- -Config => { DB_DATA_DIR => "/home/databases",
- DB_LOG_DIR => "/home/logs",
- DB_TMP_DIR => "/home/tmp"
- }
- ...
-
-=item -ErrFile
-
-Expects either the name of a file or a reference to a filehandle. Any
-errors generated internally by Berkeley DB will be logged to this file.
-
-=item -ErrPrefix
-
-Allows a prefix to be added to the error messages before they are sent
-to B<-ErrFile>.
-
-=item -Flags
-
-The B<Flags> parameter specifies both which sub-systems to initialise,
-as well as a number of environment-wide options.
-See the Berkeley DB documentation for more details of these options.
-
-Any of the following can be specified by OR'ing them:
-
-B<DB_CREATE>
-
-If any of the files specified do not already exist, create them.
-
-B<DB_INIT_CDB>
-
-Initialise the Concurrent Access Methods
-
-B<DB_INIT_LOCK>
-
-Initialise the Locking sub-system.
-
-B<DB_INIT_LOG>
-
-Initialise the Logging sub-system.
-
-B<DB_INIT_MPOOL>
-
-Initialise the ...
-
-B<DB_INIT_TXN>
-
-Initialise the ...
-
-B<DB_MPOOL_PRIVATE>
-
-Initialise the ...
-
-B<DB_INIT_MPOOL> is also specified.
-
-Initialise the ...
-
-B<DB_NOMMAP>
-
-Initialise the ...
-
-B<DB_RECOVER>
-
-
-
-B<DB_RECOVER_FATAL>
-
-B<DB_THREAD>
-
-B<DB_TXN_NOSYNC>
-
-B<DB_USE_ENVIRON>
-
-B<DB_USE_ENVIRON_ROOT>
-
-=item -LockDetect
-
-Specifies what to do when a lock conflict occurs. The value should be one of
-
-B<DB_LOCK_DEFAULT>
-
-B<DB_LOCK_OLDEST>
-
-B<DB_LOCK_RANDOM>
-
-B<DB_LOCK_YOUNGEST>
-
-=item -Verbose
-
-Add extra debugging information to the messages sent to B<-ErrFile>.
-
-=back
-
-=head2 Methods
-
-The environment class has the following methods:
-
-=over 5
-
-=item $env->errPrefix("string") ;
-
-This method is identical to the B<-ErrPrefix> flag. It allows the
-error prefix string to be changed dynamically.
-
-=item $txn = $env->TxnMgr()
-
-Constructor for creating a B<TxnMgr> object.
-See L<"TRANSACTIONS"> for more details of using transactions.
-
-This method is deprecated. Access the transaction methods using the B<txn_>
-methods below from the environment object directly.
-
-=item $env->txn_begin()
-
-TODO
-
-=item $env->txn_stat()
-
-TODO
-
-=item $env->txn_checkpoint()
-
-TODO
-
-=item $env->status()
-
-Returns the status of the last BerkeleyDB::Env method.
-
-=item $env->setmutexlocks()
-
-Only available in Berkeley Db 3.0 or greater. Calls
-B<db_env_set_mutexlocks> when used with Berkeley DB 3.1.x. When used with
-Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>.
-
-=back
-
-=head2 Examples
-
-TODO.
-
-=head1 THE DATABASE CLASSES
-
-B<BerkeleyDB> supports the following database formats:
-
-=over 5
-
-=item B<BerkeleyDB::Hash>
-
-This database type allows arbitrary key/value pairs to be stored in data
-files. This is equivalent to the functionality provided by other
-hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
-the files created using B<BerkeleyDB::Hash> are not compatible with any
-of the other packages mentioned.
-
-A default hashing algorithm, which will be adequate for most applications,
-is built into BerkeleyDB. If you do need to use your own hashing algorithm
-it is possible to write your own in Perl and have B<BerkeleyDB> use
-it instead.
-
-=item B<BerkeleyDB::Btree>
-
-The Btree format allows arbitrary key/value pairs to be stored in a
-B+tree.
-
-As with the B<BerkeleyDB::Hash> format, it is possible to provide a
-user defined Perl routine to perform the comparison of keys. By default,
-though, the keys are stored in lexical order.
-
-=item B<BerkeleyDB::Recno>
-
-TODO.
-
-
-=item B<BerkeleyDB::Queue>
-
-TODO.
-
-=item B<BerkeleyDB::Unknown>
-
-This isn't a database format at all. It is used when you want to open an
-existing Berkeley DB database without having to know what type is it.
-
-=back
-
-
-Each of the database formats described above is accessed via a
-corresponding B<BerkeleyDB> class. These will be described in turn in
-the next sections.
-
-=head1 BerkeleyDB::Hash
-
-Equivalent to calling B<db_open> with type B<DB_HASH> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_HASH> in
-Berkeley DB 3.x.
-
-Two forms of constructor are supported:
-
- $db = new BerkeleyDB::Hash
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Hash specific
- [ -Ffactor => number,]
- [ -Nelem => number,]
- [ -Hash => code reference,]
- [ -DupCompare => code reference,]
-
-and this
-
- [$db =] tie %hash, 'BerkeleyDB::Hash',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Hash specific
- [ -Ffactor => number,]
- [ -Nelem => number,]
- [ -Hash => code reference,]
- [ -DupCompare => code reference,]
-
-
-When the "tie" interface is used, reading from and writing to the database
-is achieved via the tied hash. In this case the database operates like
-a Perl associative array that happens to be stored on disk.
-
-In addition to the high-level tied hash interface, it is possible to
-make use of the underlying methods provided by Berkeley DB
-
-=head2 Options
-
-In addition to the standard set of options (see L<COMMON OPTIONS>)
-B<BerkeleyDB::Hash> supports these options:
-
-=over 5
-
-=item -Property
-
-Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
-following values:
-
-B<DB_DUP>
-
-When creating a new database, this flag enables the storing of duplicate
-keys in the database. If B<DB_DUPSORT> is not specified as well, the
-duplicates are stored in the order they are created in the database.
-
-B<DB_DUPSORT>
-
-Enables the sorting of duplicate keys in the database. Ignored if
-B<DB_DUP> isn't also specified.
-
-=item -Ffactor
-
-=item -Nelem
-
-See the Berkeley DB documentation for details of these options.
-
-=item -Hash
-
-Allows you to provide a user defined hash function. If not specified,
-a default hash function is used. Here is a template for a user-defined
-hash function
-
- sub hash
- {
- my ($data) = shift ;
- ...
- # return the hash value for $data
- return $hash ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Hash => \&hash,
- ...
-
-See L<""> for an example.
-
-=item -DupCompare
-
-Used in conjunction with the B<DB_DUPOSRT> flag.
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Property => DB_DUP|DB_DUPSORT,
- -DupCompare => \&compare,
- ...
-
-=back
-
-
-=head2 Methods
-
-B<BerkeleyDB::Hash> only supports the standard database methods.
-See L<COMMON DATABASE METHODS>.
-
-=head2 A Simple Tied Hash Example
-
-## simpleHash
-
-here is the output:
-
- Banana Exists
-
- orange -> orange
- tomato -> red
- banana -> yellow
-
-Note that the like ordinary associative arrays, the order of the keys
-retrieved from a Hash database are in an apparently random order.
-
-=head2 Another Simple Hash Example
-
-Do the same as the previous example but not using tie.
-
-## simpleHash2
-
-=head2 Duplicate keys
-
-The code below is a variation on the examples above. This time the hash has
-been inverted. The key this time is colour and the value is the fruit name.
-The B<DB_DUP> flag has been specified to allow duplicates.
-
-##dupHash
-
-here is the output:
-
- orange -> orange
- yellow -> banana
- red -> apple
- red -> tomato
- green -> banana
- green -> apple
-
-=head2 Sorting Duplicate Keys
-
-In the previous example, when there were duplicate keys, the values are
-sorted in the order they are stored in. The code below is
-identical to the previous example except the B<DB_DUPSORT> flag is
-specified.
-
-##dupSortHash
-
-Notice that in the output below the duplicate values are sorted.
-
- orange -> orange
- yellow -> banana
- red -> apple
- red -> tomato
- green -> apple
- green -> banana
-
-=head2 Custom Sorting Duplicate Keys
-
-Another variation
-
-TODO
-
-=head2 Changing the hash
-
-TODO
-
-=head2 Using db_stat
-
-TODO
-
-=head1 BerkeleyDB::Btree
-
-Equivalent to calling B<db_open> with type B<DB_BTREE> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_BTREE> in
-Berkeley DB 3.x.
-
-Two forms of constructor are supported:
-
-
- $db = new BerkeleyDB::Btree
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Btree specific
- [ -Minkey => number,]
- [ -Compare => code reference,]
- [ -DupCompare => code reference,]
- [ -Prefix => code reference,]
-
-and this
-
- [$db =] tie %hash, 'BerkeleyDB::Btree',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Btree specific
- [ -Minkey => number,]
- [ -Compare => code reference,]
- [ -DupCompare => code reference,]
- [ -Prefix => code reference,]
-
-=head2 Options
-
-In addition to the standard set of options (see L<COMMON OPTIONS>)
-B<BerkeleyDB::Btree> supports these options:
-
-=over 5
-
-=item -Property
-
-Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
-following values:
-
-B<DB_DUP>
-
-When creating a new database, this flag enables the storing of duplicate
-keys in the database. If B<DB_DUPSORT> is not specified as well, the
-duplicates are stored in the order they are created in the database.
-
-B<DB_DUPSORT>
-
-Enables the sorting of duplicate keys in the database. Ignored if
-B<DB_DUP> isn't also specified.
-
-=item Minkey
-
-TODO
-
-=item Compare
-
-Allow you to override the default sort order used in the database. See
-L<"Changing the sort order"> for an example.
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Compare => \&compare,
- ...
-
-=item Prefix
-
- sub prefix
- {
- my ($key, $key2) = @_ ;
- ...
- # return number of bytes of $key2 which are
- # necessary to determine that it is greater than $key1
- return $bytes ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Prefix => \&prefix,
- ...
-=item DupCompare
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -DupCompare => \&compare,
- ...
-
-=back
-
-=head2 Methods
-
-B<BerkeleyDB::Btree> supports the following database methods.
-See also L<COMMON DATABASE METHODS>.
-
-All the methods below return 0 to indicate success.
-
-=over 5
-
-=item $status = $db->db_key_range($key, $less, $equal, $greater [, $flags])
-
-Given a key, C<$key>, this method returns the proportion of keys less than
-C<$key> in C<$less>, the proportion equal to C<$key> in C<$equal> and the
-proportion greater than C<$key> in C<$greater>.
-
-The proportion is returned as a double in the range 0.0 to 1.0.
-
-=back
-
-=head2 A Simple Btree Example
-
-The code below is a simple example of using a btree database.
-
-## btreeSimple
-
-Here is the output from the code above. The keys have been sorted using
-Berkeley DB's default sorting algorithm.
-
- Smith
- Wall
- mouse
-
-
-=head2 Changing the sort order
-
-It is possible to supply your own sorting algorithm if the one that Berkeley
-DB used isn't suitable. The code below is identical to the previous example
-except for the case insensitive compare function.
-
-## btreeSortOrder
-
-Here is the output from the code above.
-
- mouse
- Smith
- Wall
-
-There are a few point to bear in mind if you want to change the
-ordering in a BTREE database:
-
-=over 5
-
-=item 1.
-
-The new compare function must be specified when you create the database.
-
-=item 2.
-
-You cannot change the ordering once the database has been created. Thus
-you must use the same compare function every time you access the
-database.
-
-=back
-
-=head2 Using db_stat
-
-TODO
-
-=head1 BerkeleyDB::Recno
-
-Equivalent to calling B<db_open> with type B<DB_RECNO> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_RECNO> in
-Berkeley DB 3.x.
-
-Two forms of constructor are supported:
-
- $db = new BerkeleyDB::Recno
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Recno specific
- [ -Delim => byte,]
- [ -Len => number,]
- [ -Pad => byte,]
- [ -Source => filename,]
-
-and this
-
- [$db =] tie @arry, 'BerkeleyDB::Recno',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Recno specific
- [ -Delim => byte,]
- [ -Len => number,]
- [ -Pad => byte,]
- [ -Source => filename,]
-
-=head2 A Recno Example
-
-Here is a simple example that uses RECNO (if you are using a version
-of Perl earlier than 5.004_57 this example won't work -- see
-L<Extra RECNO Methods> for a workaround).
-
-## simpleRecno
-
-Here is the output from the script:
-
- The array contains 5 entries
- popped black
- shifted white
- Element 1 Exists with value blue
- The last element is green
- The 2nd last element is yellow
-
-=head1 BerkeleyDB::Queue
-
-Equivalent to calling B<db_create> followed by B<DB-E<gt>open> with
-type B<DB_QUEUE> in Berkeley DB 3.x. This database format isn't available if
-you use Berkeley DB 2.x.
-
-Two forms of constructor are supported:
-
- $db = new BerkeleyDB::Queue
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Queue specific
- [ -Len => number,]
- [ -Pad => byte,]
- [ -ExtentSize => number, ]
-
-and this
-
- [$db =] tie @arry, 'BerkeleyDB::Queue',
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
- # BerkeleyDB::Queue specific
- [ -Len => number,]
- [ -Pad => byte,]
-
-
-=head1 BerkeleyDB::Unknown
-
-This class is used to open an existing database.
-
-Equivalent to calling B<db_open> with type B<DB_UNKNOWN> in Berkeley DB 2.x and
-calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_UNKNOWN> in
-Berkeley DB 3.x.
-
-The constructor looks like this:
-
- $db = new BerkeleyDB::Unknown
- [ -Filename => "filename", ]
- [ -Subname => "sub-database name", ]
- [ -Flags => flags,]
- [ -Property => flags,]
- [ -Mode => number,]
- [ -Cachesize => number,]
- [ -Lorder => number,]
- [ -Pagesize => number,]
- [ -Env => $env,]
- [ -Txn => $txn,]
-
-
-=head2 An example
-
-=head1 COMMON OPTIONS
-
-All database access class constructors support the common set of
-options defined below. All are optional.
-
-=over 5
-
-=item -Filename
-
-The database filename. If no filename is specified, a temporary file will
-be created and removed once the program terminates.
-
-=item -Subname
-
-Specifies the name of the sub-database to open.
-This option is only valid if you are using Berkeley DB 3.x.
-
-=item -Flags
-
-Specify how the database will be opened/created. The valid flags are:
-
-B<DB_CREATE>
-
-Create any underlying files, as necessary. If the files do not already
-exist and the B<DB_CREATE> flag is not specified, the call will fail.
-
-B<DB_NOMMAP>
-
-Not supported by BerkeleyDB.
-
-B<DB_RDONLY>
-
-Opens the database in read-only mode.
-
-B<DB_THREAD>
-
-Not supported by BerkeleyDB.
-
-B<DB_TRUNCATE>
-
-If the database file already exists, remove all the data before
-opening it.
-
-=item -Mode
-
-Determines the file protection when the database is created. Defaults
-to 0666.
-
-=item -Cachesize
-
-=item -Lorder
-
-=item -Pagesize
-
-=item -Env
-
-When working under a Berkeley DB environment, this parameter
-
-Defaults to no environment.
-
-=item -Txn
-
-TODO.
-
-=back
-
-=head1 COMMON DATABASE METHODS
-
-All the database interfaces support the common set of methods defined
-below.
-
-All the methods below return 0 to indicate success.
-
-=head2 $status = $db->db_get($key, $value [, $flags])
-
-Given a key (C<$key>) this method reads the value associated with it
-from the database. If it exists, the value read from the database is
-returned in the C<$value> parameter.
-
-The B<$flags> parameter is optional. If present, it must be set to B<one>
-of the following values:
-
-=over 5
-
-=item B<DB_GET_BOTH>
-
-When the B<DB_GET_BOTH> flag is specified, B<db_get> checks for the
-existence of B<both> the C<$key> B<and> C<$value> in the database.
-
-=item B<DB_SET_RECNO>
-
-TODO.
-
-=back
-
-In addition, the following value may be set by logically OR'ing it into
-the B<$flags> parameter:
-
-=over 5
-
-=item B<DB_RMW>
-
-TODO
-
-=back
-
-
-=head2 $status = $db->db_put($key, $value [, $flags])
-
-Stores a key/value pair in the database.
-
-The B<$flags> parameter is optional. If present it must be set to B<one>
-of the following values:
-
-=over 5
-
-=item B<DB_APPEND>
-
-This flag is only applicable when accessing a B<BerkeleyDB::Recno>
-database.
-
-TODO.
-
-
-=item B<DB_NOOVERWRITE>
-
-If this flag is specified and C<$key> already exists in the database,
-the call to B<db_put> will return B<DB_KEYEXIST>.
-
-=back
-
-=head2 $status = $db->db_del($key [, $flags])
-
-Deletes a key/value pair in the database associated with C<$key>.
-If duplicate keys are enabled in the database, B<db_del> will delete
-B<all> key/value pairs with key C<$key>.
-
-The B<$flags> parameter is optional and is currently unused.
-
-=head2 $status = $db->db_sync()
-
-If any parts of the database are in memory, write them to the database.
-
-=head2 $cursor = $db->db_cursor([$flags])
-
-Creates a cursor object. This is used to access the contents of the
-database sequentially. See L<CURSORS> for details of the methods
-available when working with cursors.
-
-The B<$flags> parameter is optional. If present it must be set to B<one>
-of the following values:
-
-=over 5
-
-=item B<DB_RMW>
-
-TODO.
-
-=back
-
-=head2 ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
-
-TODO
-
-=head2 ($flag, $old_offset, $old_length) = $db->partial_clear() ;
-
-TODO
-
-=head2 $db->byteswapped()
-
-TODO
-
-=head2 $db->type()
-
-Returns the type of the database. The possible return code are B<DB_HASH>
-for a B<BerkeleyDB::Hash> database, B<DB_BTREE> for a B<BerkeleyDB::Btree>
-database and B<DB_RECNO> for a B<BerkeleyDB::Recno> database. This method
-is typically used when a database has been opened with
-B<BerkeleyDB::Unknown>.
-
-=item $ref = $db->db_stat()
-
-Returns a reference to an associative array containing information about
-the database. The keys of the associative array correspond directly to the
-names of the fields defined in the Berkeley DB documentation. For example,
-in the DB documentation, the field B<bt_version> stores the version of the
-Btree database. Assuming you called B<db_stat> on a Btree database the
-equivalent field would be accessed as follows:
-
- $version = $ref->{'bt_version'} ;
-
-If you are using Berkeley DB 3.x, this method will work will all database
-formats. When DB 2.x is used, it only works with B<BerkeleyDB::Btree>.
-
-=head2 $status = $db->status()
-
-Returns the status of the last C<$db> method called.
-
-=head1 CURSORS
-
-A cursor is used whenever you want to access the contents of a database
-in sequential order.
-A cursor object is created with the C<db_cursor>
-
-A cursor object has the following methods available:
-
-=head2 $newcursor = $cursor->c_dup($flags)
-
-Creates a duplicate of C<$cursor>. This method needs Berkeley DB 3.0.x or better.
-
-The C<$flags> parameter is optional and can take the following value:
-
-=over 5
-
-=item DB_POSITION
-
-When present this flag will position the new cursor at the same place as the
-existing cursor.
-
-=back
-
-=head2 $status = $cursor->c_get($key, $value, $flags)
-
-Reads a key/value pair from the database, returning the data in C<$key>
-and C<$value>. The key/value pair actually read is controlled by the
-C<$flags> parameter, which can take B<one> of the following values:
-
-=over 5
-
-=item B<DB_FIRST>
-
-Set the cursor to point to the first key/value pair in the
-database. Return the key/value pair in C<$key> and C<$value>.
-
-=item B<DB_LAST>
-
-Set the cursor to point to the last key/value pair in the database. Return
-the key/value pair in C<$key> and C<$value>.
-
-=item B<DB_NEXT>
-
-If the cursor is already pointing to a key/value pair, it will be
-incremented to point to the next key/value pair and return its contents.
-
-If the cursor isn't initialised, B<DB_NEXT> works just like B<DB_FIRST>.
-
-If the cursor is already positioned at the last key/value pair, B<c_get>
-will return B<DB_NOTFOUND>.
-
-=item B<DB_NEXT_DUP>
-
-This flag is only valid when duplicate keys have been enabled in
-a database.
-If the cursor is already pointing to a key/value pair and the key of
-the next key/value pair is identical, the cursor will be incremented to
-point to it and their contents returned.
-
-=item B<DB_PREV>
-
-If the cursor is already pointing to a key/value pair, it will be
-decremented to point to the previous key/value pair and return its
-contents.
-
-If the cursor isn't initialised, B<DB_PREV> works just like B<DB_LAST>.
-
-If the cursor is already positioned at the first key/value pair, B<c_get>
-will return B<DB_NOTFOUND>.
-
-=item B<DB_CURRENT>
-
-If the cursor has been set to point to a key/value pair, return their
-contents.
-If the key/value pair referenced by the cursor has been deleted, B<c_get>
-will return B<DB_KEYEMPTY>.
-
-=item B<DB_SET>
-
-Set the cursor to point to the key/value pair referenced by B<$key>
-and return the value in B<$value>.
-
-=item B<DB_SET_RANGE>
-
-This flag is a variation on the B<DB_SET> flag. As well as returning
-the value, it also returns the key, via B<$key>.
-When used with a B<BerkeleyDB::Btree> database the key matched by B<c_get>
-will be the shortest key (in length) which is greater than or equal to
-the key supplied, via B<$key>. This allows partial key searches.
-See ??? for an example of how to use this flag.
-
-=item B<DB_GET_BOTH>
-
-Another variation on B<DB_SET>. This one returns both the key and
-the value.
-
-=item B<DB_SET_RECNO>
-
-TODO.
-
-=item B<DB_GET_RECNO>
-
-TODO.
-
-=back
-
-In addition, the following value may be set by logically OR'ing it into
-the B<$flags> parameter:
-
-=over 5
-
-=item B<DB_RMW>
-
-TODO.
-
-=back
-
-=head2 $status = $cursor->c_put($key, $value, $flags)
-
-Stores the key/value pair in the database. The position that the data is
-stored in the database is controlled by the C<$flags> parameter, which
-must take B<one> of the following values:
-
-=over 5
-
-=item B<DB_AFTER>
-
-When used with a Btree or Hash database, a duplicate of the key referenced
-by the current cursor position will be created and the contents of
-B<$value> will be associated with it - B<$key> is ignored.
-The new key/value pair will be stored immediately after the current
-cursor position.
-Obviously the database has to have been opened with B<DB_DUP>.
-
-When used with a Recno ... TODO
-
-
-=item B<DB_BEFORE>
-
-When used with a Btree or Hash database, a duplicate of the key referenced
-by the current cursor position will be created and the contents of
-B<$value> will be associated with it - B<$key> is ignored.
-The new key/value pair will be stored immediately before the current
-cursor position.
-Obviously the database has to have been opened with B<DB_DUP>.
-
-When used with a Recno ... TODO
-
-=item B<DB_CURRENT>
-
-If the cursor has been initialised, replace the value of the key/value
-pair stored in the database with the contents of B<$value>.
-
-=item B<DB_KEYFIRST>
-
-Only valid with a Btree or Hash database. This flag is only really
-used when duplicates are enabled in the database and sorted duplicates
-haven't been specified.
-In this case the key/value pair will be inserted as the first entry in
-the duplicates for the particular key.
-
-=item B<DB_KEYLAST>
-
-Only valid with a Btree or Hash database. This flag is only really
-used when duplicates are enabled in the database and sorted duplicates
-haven't been specified.
-In this case the key/value pair will be inserted as the last entry in
-the duplicates for the particular key.
-
-=back
-
-=head2 $status = $cursor->c_del([$flags])
-
-This method deletes the key/value pair associated with the current cursor
-position. The cursor position will not be changed by this operation, so
-any subsequent cursor operation must first initialise the cursor to
-point to a valid key/value pair.
-
-If the key/value pair associated with the cursor have already been
-deleted, B<c_del> will return B<DB_KEYEMPTY>.
-
-The B<$flags> parameter is not used at present.
-
-=head2 $status = $cursor->c_del($cnt [, $flags])
-
-Stores the number of duplicates at the current cursor position in B<$cnt>.
-
-The B<$flags> parameter is not used at present. This method needs
-Berkeley DB 3.1 or better.
-
-=head2 $status = $cursor->status()
-
-Returns the status of the last cursor method as a dual type.
-
-=head2 Cursor Examples
-
-TODO
-
-Iterating from first to last, then in reverse.
-
-examples of each of the flags.
-
-=head1 JOIN
-
-Join support for BerkeleyDB is in progress. Watch this space.
-
-TODO
-
-=head1 TRANSACTIONS
-
-TODO.
-
-=head1 DBM Filters
-
-A DBM Filter is a piece of code that is be used when you I<always>
-want to make the same transformation to all keys and/or values in a DBM
-database. All of the database classes (BerkeleyDB::Hash,
-BerkeleyDB::Btree and BerkeleyDB::Recno) support DBM Filters.
-
-There are four methods associated with DBM Filters. All work
-identically, and each is used to install (or uninstall) a single DBM
-Filter. Each expects a single parameter, namely a reference to a sub.
-The only difference between them is the place that the filter is
-installed.
-
-To summarise:
-
-=over 5
-
-=item B<filter_store_key>
-
-If a filter has been installed with this method, it will be invoked
-every time you write a key to a DBM database.
-
-=item B<filter_store_value>
-
-If a filter has been installed with this method, it will be invoked
-every time you write a value to a DBM database.
-
-
-=item B<filter_fetch_key>
-
-If a filter has been installed with this method, it will be invoked
-every time you read a key from a DBM database.
-
-=item B<filter_fetch_value>
-
-If a filter has been installed with this method, it will be invoked
-every time you read a value from a DBM database.
-
-=back
-
-You can use any combination of the methods, from none, to all four.
-
-All filter methods return the existing filter, if present, or C<undef>
-in not.
-
-To delete a filter pass C<undef> to it.
-
-=head2 The Filter
-
-When each filter is called by Perl, a local copy of C<$_> will contain
-the key or value to be filtered. Filtering is achieved by modifying
-the contents of C<$_>. The return code from the filter is ignored.
-
-=head2 An Example -- the NULL termination problem.
-
-Consider the following scenario. You have a DBM database that you need
-to share with a third-party C application. The C application assumes
-that I<all> keys and values are NULL terminated. Unfortunately when
-Perl writes to DBM databases it doesn't use NULL termination, so your
-Perl application will have to manage NULL termination itself. When you
-write to the database you will have to use something like this:
-
- $hash{"$key\0"} = "$value\0" ;
-
-Similarly the NULL needs to be taken into account when you are considering
-the length of existing keys/values.
-
-It would be much better if you could ignore the NULL terminations issue
-in the main application code and have a mechanism that automatically
-added the terminating NULL to all keys and values whenever you write to
-the database and have them removed when you read from the database. As I'm
-sure you have already guessed, this is a problem that DBM Filters can
-fix very easily.
-
-## nullFilter
-
-Hopefully the contents of each of the filters should be
-self-explanatory. Both "fetch" filters remove the terminating NULL,
-and both "store" filters add a terminating NULL.
-
-
-=head2 Another Example -- Key is a C int.
-
-Here is another real-life example. By default, whenever Perl writes to
-a DBM database it always writes the key and value as strings. So when
-you use this:
-
- $hash{12345} = "something" ;
-
-the key 12345 will get stored in the DBM database as the 5 byte string
-"12345". If you actually want the key to be stored in the DBM database
-as a C int, you will have to use C<pack> when writing, and C<unpack>
-when reading.
-
-Here is a DBM Filter that does it:
-
-## intFilter
-
-This time only two filters have been used -- we only need to manipulate
-the contents of the key, so it wasn't necessary to install any value
-filters.
-
-=head1 Using BerkeleyDB with MLDBM
-
-Both BerkeleyDB::Hash and BerkeleyDB::Btree can be used with the MLDBM
-module. The code fragment below shows how to open associate MLDBM with
-BerkeleyDB::Btree. To use BerkeleyDB::Hash just replace
-BerkeleyDB::Btree with BerkeleyDB::Hash.
-
- use strict ;
- use BerkeleyDB ;
- use MLDBM qw(BerkeleyDB::Btree) ;
- use Data::Dumper;
-
- my $filename = 'testmldbm' ;
- my %o ;
-
- unlink $filename ;
- tie %o, 'MLDBM', -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open database '$filename: $!\n";
-
-See the MLDBM documentation for information on how to use the module
-and for details of its limitations.
-
-=head1 EXAMPLES
-
-TODO.
-
-=head1 HINTS & TIPS
-
-=head2 Sharing Databases With C Applications
-
-There is no technical reason why a Berkeley DB database cannot be
-shared by both a Perl and a C application.
-
-The vast majority of problems that are reported in this area boil down
-to the fact that C strings are NULL terminated, whilst Perl strings
-are not. See L<An Example -- the NULL termination problem.> in the DBM
-FILTERS section for a generic way to work around this problem.
-
-
-=head2 The untie Gotcha
-
-TODO
-
-=head1 COMMON QUESTIONS
-
-This section attempts to answer some of the more common questions that
-I get asked.
-
-
-=head2 Relationship with DB_File
-
-Before Berkeley DB 2.x was written there was only one Perl module that
-interfaced to Berkeley DB. That module is called B<DB_File>. Although
-B<DB_File> can be build with Berkeley DB 1.x, 2.x or 3.x, it only provides
-an interface to the functionality available in Berkeley DB 1.x. That
-means that it doesn't support transactions, locking or any of the other
-new features available in DB 2.x or 3.x.
-
-=head2 How do I store Perl data structures with BerkeleyDB?
-
-See L<Using BerkeleyDB with MLDBM>.
-
-=head1 HISTORY
-
-See the Changes file.
-
-=head1 AVAILABILITY
-
-The most recent version of B<BerkeleyDB> can always be found
-on CPAN (see L<perlmod/CPAN> for details), in the directory
-F<modules/by-module/BerkeleyDB>.
-
-The official web site for Berkeley DB is F<http://www.sleepycat.com>.
-
-=head1 COPYRIGHT
-
-Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This program
-is free software; you can redistribute it and/or modify it under the
-same terms as Perl itself.
-
-Although B<BerkeleyDB> is covered by the Perl license, the library it
-makes use of, namely Berkeley DB, is not. Berkeley DB has its own
-copyright and its own license. Please take the time to read it.
-
-Here are few words taken from the Berkeley DB FAQ (at
-F<http://www.sleepycat.com>) regarding the license:
-
- Do I have to license DB to use it in Perl scripts?
-
- No. The Berkeley DB license requires that software that uses
- Berkeley DB be freely redistributable. In the case of Perl, that
- software is Perl, and not your scripts. Any Perl scripts that you
- write are your property, including scripts that make use of Berkeley
- DB. Neither the Perl license nor the Berkeley DB license
- place any restriction on what you may do with them.
-
-If you are in any doubt about the license situation, contact either the
-Berkeley DB authors or the author of BerkeleyDB.
-See L<"AUTHOR"> for details.
-
-
-=head1 AUTHOR
-
-Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt>.
-
-Questions about Berkeley DB may be addressed to E<lt>db@sleepycat.comE<gt>.
-
-=head1 SEE ALSO
-
-perl(1), DB_File, Berkeley DB.
-
-=cut
diff --git a/bdb/perl.BerkeleyDB/BerkeleyDB.xs b/bdb/perl.BerkeleyDB/BerkeleyDB.xs
deleted file mode 100644
index 19126c98b53..00000000000
--- a/bdb/perl.BerkeleyDB/BerkeleyDB.xs
+++ /dev/null
@@ -1,3927 +0,0 @@
-/*
-
- BerkeleyDB.xs -- Perl 5 interface to Berkeley DB version 2 & 3
-
- written by Paul Marquess <Paul.Marquess@btinternet.com>
-
- All comments/suggestions/problems are welcome
-
- Copyright (c) 1997-2001 Paul Marquess. All rights reserved.
- This program is free software; you can redistribute it and/or
- modify it under the same terms as Perl itself.
-
- Please refer to the COPYRIGHT section in
-
- Changes:
- 0.01 - First Alpha Release
- 0.02 -
-
-*/
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#define PERL_POLLUTE
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
- * shortly #included by the <db.h>) __attribute__ to the possibly
- * already defined __attribute__, for example by GNUC or by Perl. */
-
-#undef __attribute__
-
-#ifndef PERL_VERSION
-# include "patchlevel.h"
-# define PERL_REVISION 5
-# define PERL_VERSION PATCHLEVEL
-# define PERL_SUBVERSION SUBVERSION
-#endif
-
-#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
-
-# define PL_sv_undef sv_undef
-# define PL_na na
-# define PL_dirty dirty
-
-#endif
-
-#include <db.h>
-
-#if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0)
-# define IS_DB_3_0
-#endif
-
-#if DB_VERSION_MAJOR >= 3
-# define AT_LEAST_DB_3
-#endif
-
-#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 1)
-# define AT_LEAST_DB_3_1
-#endif
-
-#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
-# define AT_LEAST_DB_3_2
-#endif
-
-/* need to define DEFSV & SAVE_DEFSV for older version of Perl */
-#ifndef DEFSV
-# define DEFSV GvSV(defgv)
-#endif
-
-#ifndef SAVE_DEFSV
-# define SAVE_DEFSV SAVESPTR(GvSV(defgv))
-#endif
-
-#ifndef pTHX
-# define pTHX
-# define pTHX_
-# define aTHX
-# define aTHX_
-#endif
-
-#ifndef dTHR
-# define dTHR
-#endif
-
-#ifndef newSVpvn
-# define newSVpvn(a,b) newSVpv(a,b)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#define DBM_FILTERING
-#define STRICT_CLOSE
-/* #define ALLOW_RECNO_OFFSET */
-/* #define TRACE */
-
-#if DB_VERSION_MAJOR == 2 && ! defined(DB_LOCK_DEADLOCK)
-# define DB_LOCK_DEADLOCK EAGAIN
-#endif /* DB_VERSION_MAJOR == 2 */
-
-#if DB_VERSION_MAJOR == 2
-# define DB_QUEUE 4
-#endif /* DB_VERSION_MAJOR == 2 */
-
-#ifdef AT_LEAST_DB_3_2
-# define DB_callback DB * db,
-#else
-# define DB_callback
-#endif
-
-#if DB_VERSION_MAJOR > 2
-typedef struct {
- int db_lorder;
- size_t db_cachesize;
- size_t db_pagesize;
-
-
- void *(*db_malloc) __P((size_t));
- int (*dup_compare)
- __P((DB_callback const DBT *, const DBT *));
-
- u_int32_t bt_maxkey;
- u_int32_t bt_minkey;
- int (*bt_compare)
- __P((DB_callback const DBT *, const DBT *));
- size_t (*bt_prefix)
- __P((DB_callback const DBT *, const DBT *));
-
- u_int32_t h_ffactor;
- u_int32_t h_nelem;
- u_int32_t (*h_hash)
- __P((DB_callback const void *, u_int32_t));
-
- int re_pad;
- int re_delim;
- u_int32_t re_len;
- char *re_source;
-
-#define DB_DELIMITER 0x0001
-#define DB_FIXEDLEN 0x0008
-#define DB_PAD 0x0010
- u_int32_t flags;
- u_int32_t q_extentsize;
-} DB_INFO ;
-
-#endif /* DB_VERSION_MAJOR > 2 */
-
-typedef struct {
- int Status ;
- /* char ErrBuff[1000] ; */
- SV * ErrPrefix ;
- SV * ErrHandle ;
- DB_ENV * Env ;
- int open_dbs ;
- int TxnMgrStatus ;
- int active ;
- bool txn_enabled ;
- } BerkeleyDB_ENV_type ;
-
-
-typedef struct {
- DBTYPE type ;
- bool recno_or_queue ;
- char * filename ;
- BerkeleyDB_ENV_type * parent_env ;
- DB * dbp ;
- SV * compare ;
- SV * dup_compare ;
- SV * prefix ;
- SV * hash ;
- int Status ;
- DB_INFO * info ;
- DBC * cursor ;
- DB_TXN * txn ;
- int open_cursors ;
- u_int32_t partial ;
- u_int32_t dlen ;
- u_int32_t doff ;
- int active ;
-#ifdef ALLOW_RECNO_OFFSET
- int array_base ;
-#endif
-#ifdef DBM_FILTERING
- SV * filter_fetch_key ;
- SV * filter_store_key ;
- SV * filter_fetch_value ;
- SV * filter_store_value ;
- int filtering ;
-#endif
- } BerkeleyDB_type;
-
-
-typedef struct {
- DBTYPE type ;
- bool recno_or_queue ;
- char * filename ;
- DB * dbp ;
- SV * compare ;
- SV * dup_compare ;
- SV * prefix ;
- SV * hash ;
- int Status ;
- DB_INFO * info ;
- DBC * cursor ;
- DB_TXN * txn ;
- BerkeleyDB_type * parent_db ;
- u_int32_t partial ;
- u_int32_t dlen ;
- u_int32_t doff ;
- int active ;
-#ifdef ALLOW_RECNO_OFFSET
- int array_base ;
-#endif
-#ifdef DBM_FILTERING
- SV * filter_fetch_key ;
- SV * filter_store_key ;
- SV * filter_fetch_value ;
- SV * filter_store_value ;
- int filtering ;
-#endif
- } BerkeleyDB_Cursor_type;
-
-typedef struct {
- BerkeleyDB_ENV_type * env ;
- } BerkeleyDB_TxnMgr_type ;
-
-#if 1
-typedef struct {
- int Status ;
- DB_TXN * txn ;
- int active ;
- } BerkeleyDB_Txn_type ;
-#else
-typedef DB_TXN BerkeleyDB_Txn_type ;
-#endif
-
-typedef BerkeleyDB_ENV_type * BerkeleyDB__Env ;
-typedef BerkeleyDB_ENV_type * BerkeleyDB__Env__Raw ;
-typedef BerkeleyDB_ENV_type * BerkeleyDB__Env__Inner ;
-typedef BerkeleyDB_type * BerkeleyDB ;
-typedef void * BerkeleyDB__Raw ;
-typedef BerkeleyDB_type * BerkeleyDB__Common ;
-typedef BerkeleyDB_type * BerkeleyDB__Common__Raw ;
-typedef BerkeleyDB_type * BerkeleyDB__Common__Inner ;
-typedef BerkeleyDB_type * BerkeleyDB__Hash ;
-typedef BerkeleyDB_type * BerkeleyDB__Hash__Raw ;
-typedef BerkeleyDB_type * BerkeleyDB__Btree ;
-typedef BerkeleyDB_type * BerkeleyDB__Btree__Raw ;
-typedef BerkeleyDB_type * BerkeleyDB__Recno ;
-typedef BerkeleyDB_type * BerkeleyDB__Recno__Raw ;
-typedef BerkeleyDB_type * BerkeleyDB__Queue ;
-typedef BerkeleyDB_type * BerkeleyDB__Queue__Raw ;
-typedef BerkeleyDB_Cursor_type BerkeleyDB__Cursor_type ;
-typedef BerkeleyDB_Cursor_type * BerkeleyDB__Cursor ;
-typedef BerkeleyDB_Cursor_type * BerkeleyDB__Cursor__Raw ;
-typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr ;
-typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr__Raw ;
-typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr__Inner ;
-typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn ;
-typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn__Raw ;
-typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn__Inner ;
-#if 0
-typedef DB_LOG * BerkeleyDB__Log ;
-typedef DB_LOCKTAB * BerkeleyDB__Lock ;
-#endif
-typedef DBT DBTKEY ;
-typedef DBT DBT_OPT ;
-typedef DBT DBT_B ;
-typedef DBT DBTKEY_B ;
-typedef DBT DBTVALUE ;
-typedef void * PV_or_NULL ;
-typedef PerlIO * IO_or_NULL ;
-typedef int DualType ;
-
-static void
-hash_delete(char * hash, IV key);
-
-#ifdef TRACE
-# define Trace(x) printf x
-#else
-# define Trace(x)
-#endif
-
-#ifdef ALLOW_RECNO_OFFSET
-# define RECNO_BASE db->array_base
-#else
-# define RECNO_BASE 1
-#endif
-
-#if DB_VERSION_MAJOR == 2
-# define flagSet_DB2(i, f) i |= f
-#else
-# define flagSet_DB2(i, f)
-#endif
-
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
-# define flagSet(bitmask) (flags & (bitmask))
-#else
-# define flagSet(bitmask) ((flags & DB_OPFLAGS_MASK) == (bitmask))
-#endif
-
-#ifdef DBM_FILTERING
-#define ckFilter(arg,type,name) \
- if (db->type) { \
- SV * save_defsv ; \
- /* printf("filtering %s\n", name) ;*/ \
- if (db->filtering) \
- softCrash("recursion detected in %s", name) ; \
- db->filtering = TRUE ; \
- save_defsv = newSVsv(DEFSV) ; \
- sv_setsv(DEFSV, arg) ; \
- PUSHMARK(sp) ; \
- (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
- sv_setsv(arg, DEFSV) ; \
- sv_setsv(DEFSV, save_defsv) ; \
- SvREFCNT_dec(save_defsv) ; \
- db->filtering = FALSE ; \
- /*printf("end of filtering %s\n", name) ;*/ \
- }
-#else
-#define ckFilter(type, sv, name)
-#endif
-
-#define ERR_BUFF "BerkeleyDB::Error"
-
-#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
- Zero(to,1,typ))
-
-#define DBT_clear(x) Zero(&x, 1, DBT) ;
-
-#if 1
-#define getInnerObject(x) SvIV(*av_fetch((AV*)SvRV(x), 0, FALSE))
-#else
-#define getInnerObject(x) SvIV((SV*)SvRV(sv))
-#endif
-
-#define my_sv_setpvn(sv, d, s) (s ? sv_setpvn(sv, d, s) : sv_setpv(sv, "") )
-
-#define SetValue_iv(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
- i = SvIV(sv)
-#define SetValue_io(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
- i = IoOFP(sv_2io(sv))
-#define SetValue_sv(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
- i = sv
-#define SetValue_pv(i, k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
- i = (t)SvPV(sv,PL_na)
-#define SetValue_pvx(i, k, t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
- i = (t)SvPVX(sv)
-#define SetValue_ov(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\
- IV tmp = getInnerObject(sv) ; \
- i = (t) tmp ; \
- }
-
-#define SetValue_ovx(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\
- HV * hv = (HV *)GetInternalObject(sv); \
- SV ** svp = hv_fetch(hv, "db", 2, FALSE);\
- IV tmp = SvIV(*svp); \
- i = (t) tmp ; \
- }
-
-#define SetValue_ovX(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\
- IV tmp = SvIV(GetInternalObject(sv));\
- i = (t) tmp ; \
- }
-
-#define LastDBerror DB_RUNRECOVERY
-
-#define setDUALerrno(var, err) \
- sv_setnv(var, (double)err) ; \
- sv_setpv(var, ((err) ? db_strerror(err) : "")) ;\
- SvNOK_on(var);
-
-#define OutputValue(arg, name) \
- { if (RETVAL == 0) { \
- my_sv_setpvn(arg, name.data, name.size) ; \
- ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
- } \
- }
-
-#define OutputValue_B(arg, name) \
- { if (RETVAL == 0) { \
- if (db->type == DB_BTREE && \
- flagSet(DB_GET_RECNO)){ \
- sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \
- } \
- else { \
- my_sv_setpvn(arg, name.data, name.size) ; \
- } \
- ckFilter(arg, filter_fetch_value, "filter_fetch_value"); \
- } \
- }
-
-#define OutputKey(arg, name) \
- { if (RETVAL == 0) \
- { \
- if (!db->recno_or_queue) { \
- my_sv_setpvn(arg, name.data, name.size); \
- } \
- else \
- sv_setiv(arg, (I32)*(I32*)name.data - RECNO_BASE); \
- ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \
- } \
- }
-
-#define OutputKey_B(arg, name) \
- { if (RETVAL == 0) \
- { \
- if (db->recno_or_queue || \
- (db->type == DB_BTREE && \
- flagSet(DB_GET_RECNO))){ \
- sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \
- } \
- else { \
- my_sv_setpvn(arg, name.data, name.size); \
- } \
- ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \
- } \
- }
-
-#define SetPartial(data,db) \
- data.flags = db->partial ; \
- data.dlen = db->dlen ; \
- data.doff = db->doff ;
-
-#define ckActive(active, type) \
- { \
- if (!active) \
- softCrash("%s is already closed", type) ; \
- }
-
-#define ckActive_Environment(a) ckActive(a, "Environment")
-#define ckActive_TxnMgr(a) ckActive(a, "Transaction Manager")
-#define ckActive_Transaction(a) ckActive(a, "Transaction")
-#define ckActive_Database(a) ckActive(a, "Database")
-#define ckActive_Cursor(a) ckActive(a, "Cursor")
-
-/* Internal Global Data */
-static db_recno_t Value ;
-static db_recno_t zero = 0 ;
-static BerkeleyDB CurrentDB ;
-static DBTKEY empty ;
-static char ErrBuff[1000] ;
-
-static char *
-my_strdup(const char *s)
-{
- if (s == NULL)
- return NULL ;
-
- {
- MEM_SIZE l = strlen(s);
- char *s1 = (char *)safemalloc(l);
-
- Copy(s, s1, (MEM_SIZE)l, char);
- return s1;
- }
-}
-
-#if DB_VERSION_MAJOR == 2
-static char *
-db_strerror(int err)
-{
- if (err == 0)
- return "" ;
-
- if (err > 0)
- return Strerror(err) ;
-
- switch (err) {
- case DB_INCOMPLETE:
- return ("DB_INCOMPLETE: Sync was unable to complete");
- case DB_KEYEMPTY:
- return ("DB_KEYEMPTY: Non-existent key/data pair");
- case DB_KEYEXIST:
- return ("DB_KEYEXIST: Key/data pair already exists");
- case DB_LOCK_DEADLOCK:
- return (
- "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
- case DB_LOCK_NOTGRANTED:
- return ("DB_LOCK_NOTGRANTED: Lock not granted");
- case DB_LOCK_NOTHELD:
- return ("DB_LOCK_NOTHELD: Lock not held by locker");
- case DB_NOTFOUND:
- return ("DB_NOTFOUND: No matching key/data pair found");
- case DB_RUNRECOVERY:
- return ("DB_RUNRECOVERY: Fatal error, run database recovery");
- default:
- return "Unknown Error" ;
-
- }
-}
-#endif /* DB_VERSION_MAJOR == 2 */
-
-static char *
-my_db_strerror(int err)
-{
- static char buffer[1000] ;
- SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
- sprintf(buffer, "%d: %s", err, db_strerror(err)) ;
- if (err && sv) {
- strcat(buffer, ", ") ;
- strcat(buffer, SvPVX(sv)) ;
- }
- return buffer;
-}
-
-static void
-close_everything(void)
-{
- dTHR;
- Trace(("close_everything\n")) ;
- /* Abort All Transactions */
- {
- BerkeleyDB__Txn__Raw tid ;
- HE * he ;
- I32 len ;
- HV * hv = perl_get_hv("BerkeleyDB::Term::Txn", TRUE);
- I32 ret = hv_iterinit(hv) ;
- int all = 0 ;
- int closed = 0 ;
- Trace(("BerkeleyDB::Term::close_all_txns dirty=%d\n", PL_dirty)) ;
- while ( he = hv_iternext(hv) ) {
- tid = * (BerkeleyDB__Txn__Raw *) (IV) hv_iterkey(he, &len) ;
- Trace((" Aborting Transaction [%d] in [%d] Active [%d]\n", tid->txn, tid, tid->active));
- if (tid->active) {
- txn_abort(tid->txn);
- ++ closed ;
- }
- tid->active = FALSE ;
- ++ all ;
- }
- Trace(("End of BerkeleyDB::Term::close_all_txns aborted %d of %d transactios\n",closed, all)) ;
- }
-
- /* Close All Cursors */
- {
- BerkeleyDB__Cursor db ;
- HE * he ;
- I32 len ;
- HV * hv = perl_get_hv("BerkeleyDB::Term::Cursor", TRUE);
- I32 ret = hv_iterinit(hv) ;
- int all = 0 ;
- int closed = 0 ;
- Trace(("BerkeleyDB::Term::close_all_cursors \n")) ;
- while ( he = hv_iternext(hv) ) {
- db = * (BerkeleyDB__Cursor*) (IV) hv_iterkey(he, &len) ;
- Trace((" Closing Cursor [%d] in [%d] Active [%d]\n", db->cursor, db, db->active));
- if (db->active) {
- ((db->cursor)->c_close)(db->cursor) ;
- ++ closed ;
- }
- db->active = FALSE ;
- ++ all ;
- }
- Trace(("End of BerkeleyDB::Term::close_all_cursors closed %d of %d cursors\n",closed, all)) ;
- }
-
- /* Close All Databases */
- {
- BerkeleyDB db ;
- HE * he ;
- I32 len ;
- HV * hv = perl_get_hv("BerkeleyDB::Term::Db", TRUE);
- I32 ret = hv_iterinit(hv) ;
- int all = 0 ;
- int closed = 0 ;
- Trace(("BerkeleyDB::Term::close_all_dbs\n" )) ;
- while ( he = hv_iternext(hv) ) {
- db = * (BerkeleyDB*) (IV) hv_iterkey(he, &len) ;
- Trace((" Closing Database [%d] in [%d] Active [%d]\n", db->dbp, db, db->active));
- if (db->active) {
- (db->dbp->close)(db->dbp, 0) ;
- ++ closed ;
- }
- db->active = FALSE ;
- ++ all ;
- }
- Trace(("End of BerkeleyDB::Term::close_all_dbs closed %d of %d dbs\n",closed, all)) ;
- }
-
- /* Close All Environments */
- {
- BerkeleyDB__Env env ;
- HE * he ;
- I32 len ;
- HV * hv = perl_get_hv("BerkeleyDB::Term::Env", TRUE);
- I32 ret = hv_iterinit(hv) ;
- int all = 0 ;
- int closed = 0 ;
- Trace(("BerkeleyDB::Term::close_all_envs\n")) ;
- while ( he = hv_iternext(hv) ) {
- env = * (BerkeleyDB__Env*) (IV) hv_iterkey(he, &len) ;
- Trace((" Closing Environment [%d] in [%d] Active [%d]\n", env->Env, env, env->active));
- if (env->active) {
-#if DB_VERSION_MAJOR == 2
- db_appexit(env->Env) ;
-#else
- (env->Env->close)(env->Env, 0) ;
-#endif
- ++ closed ;
- }
- env->active = FALSE ;
- ++ all ;
- }
- Trace(("End of BerkeleyDB::Term::close_all_envs closed %d of %d dbs\n",closed, all)) ;
- }
-
- Trace(("end close_everything\n")) ;
-
-}
-
-static void
-destroyDB(BerkeleyDB db)
-{
- dTHR;
- if (! PL_dirty && db->active) {
- -- db->open_cursors ;
- ((db->dbp)->close)(db->dbp, 0) ;
- }
- if (db->hash)
- SvREFCNT_dec(db->hash) ;
- if (db->compare)
- SvREFCNT_dec(db->compare) ;
- if (db->dup_compare)
- SvREFCNT_dec(db->dup_compare) ;
- if (db->prefix)
- SvREFCNT_dec(db->prefix) ;
-#ifdef DBM_FILTERING
- if (db->filter_fetch_key)
- SvREFCNT_dec(db->filter_fetch_key) ;
- if (db->filter_store_key)
- SvREFCNT_dec(db->filter_store_key) ;
- if (db->filter_fetch_value)
- SvREFCNT_dec(db->filter_fetch_value) ;
- if (db->filter_store_value)
- SvREFCNT_dec(db->filter_store_value) ;
-#endif
- hash_delete("BerkeleyDB::Term::Db", (IV)db) ;
- if (db->filename)
- Safefree(db->filename) ;
- Safefree(db) ;
-}
-
-static void
-softCrash(const char *pat, ...)
-{
- char buffer1 [500] ;
- char buffer2 [500] ;
- va_list args;
- va_start(args, pat);
-
- Trace(("softCrash: %s\n", pat)) ;
-
-#define ABORT_PREFIX "BerkeleyDB Aborting: "
-
- /* buffer = (char*) safemalloc(strlen(pat) + strlen(ABORT_PREFIX) + 1) ; */
- strcpy(buffer1, ABORT_PREFIX) ;
- strcat(buffer1, pat) ;
-
- vsprintf(buffer2, buffer1, args) ;
-
- croak(buffer2);
-
- /* NOTREACHED */
- va_end(args);
-}
-
-
-static I32
-GetArrayLength(BerkeleyDB db)
-{
- DBT key ;
- DBT value ;
- int RETVAL = 0 ;
- DBC * cursor ;
-
- DBT_clear(key) ;
- DBT_clear(value) ;
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
- if ( ((db->dbp)->cursor)(db->dbp, db->txn, &cursor) == 0 )
-#else
- if ( ((db->dbp)->cursor)(db->dbp, db->txn, &cursor, 0) == 0 )
-#endif
- {
- RETVAL = cursor->c_get(cursor, &key, &value, DB_LAST) ;
- if (RETVAL == 0)
- RETVAL = *(I32 *)key.data ;
- else /* No key means empty file */
- RETVAL = 0 ;
- cursor->c_close(cursor) ;
- }
-
- Trace(("GetArrayLength got %d\n", RETVAL)) ;
- return ((I32)RETVAL) ;
-}
-
-#if 0
-
-#define GetRecnoKey(db, value) _GetRecnoKey(db, value)
-
-static db_recno_t
-_GetRecnoKey(BerkeleyDB db, I32 value)
-{
- Trace(("GetRecnoKey start value = %d\n", value)) ;
- if (db->recno_or_queue && value < 0) {
- /* Get the length of the array */
- I32 length = GetArrayLength(db) ;
-
- /* check for attempt to write before start of array */
- if (length + value + RECNO_BASE <= 0)
- softCrash("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
-
- value = length + value + RECNO_BASE ;
- }
- else
- ++ value ;
-
- Trace(("GetRecnoKey end value = %d\n", value)) ;
-
- return value ;
-}
-
-#else /* ! 0 */
-
-#if 0
-#ifdef ALLOW_RECNO_OFFSET
-#define GetRecnoKey(db, value) _GetRecnoKey(db, value)
-
-static db_recno_t
-_GetRecnoKey(BerkeleyDB db, I32 value)
-{
- if (value + RECNO_BASE < 1)
- softCrash("key value %d < base (%d)", (value), RECNO_BASE?0:1) ;
- return value + RECNO_BASE ;
-}
-
-#else
-#endif /* ALLOW_RECNO_OFFSET */
-#endif /* 0 */
-
-#define GetRecnoKey(db, value) ((value) + RECNO_BASE )
-
-#endif /* 0 */
-
-static SV *
-GetInternalObject(SV * sv)
-{
- SV * info = (SV*) NULL ;
- SV * s ;
- MAGIC * mg ;
-
- Trace(("in GetInternalObject %d\n", sv)) ;
- if (sv == NULL || !SvROK(sv))
- return NULL ;
-
- s = SvRV(sv) ;
- if (SvMAGICAL(s))
- {
- if (SvTYPE(s) == SVt_PVHV || SvTYPE(s) == SVt_PVAV)
- mg = mg_find(s, 'P') ;
- else
- mg = mg_find(s, 'q') ;
-
- /* all this testing is probably overkill, but till I know more
- about global destruction it stays.
- */
- /* if (mg && mg->mg_obj && SvRV(mg->mg_obj) && SvPVX(SvRV(mg->mg_obj))) */
- if (mg && mg->mg_obj && SvRV(mg->mg_obj) )
- info = SvRV(mg->mg_obj) ;
- else
- info = s ;
- }
-
- Trace(("end of GetInternalObject %d\n", info)) ;
- return info ;
-}
-
-static int
-btree_compare(DB_callback const DBT * key1, const DBT * key2 )
-{
- dSP ;
- void * data1, * data2 ;
- int retval ;
- int count ;
-
- data1 = key1->data ;
- data2 = key2->data ;
-
-#ifndef newSVpvn
- /* As newSVpv will assume that the data pointer is a null terminated C
- string if the size parameter is 0, make sure that data points to an
- empty string if the length is 0
- */
- if (key1->size == 0)
- data1 = "" ;
- if (key2->size == 0)
- data2 = "" ;
-#endif
-
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
- EXTEND(SP,2) ;
- PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
- PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->compare, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- softCrash ("in btree_compare - expected 1 return value from compare sub, got %d", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
- return (retval) ;
-
-}
-
-static int
-dup_compare(DB_callback const DBT * key1, const DBT * key2 )
-{
- dSP ;
- void * data1, * data2 ;
- int retval ;
- int count ;
-
- Trace(("In dup_compare \n")) ;
- if (!CurrentDB)
- softCrash("Internal Error - No CurrentDB in dup_compare") ;
- if (CurrentDB->dup_compare == NULL)
- softCrash("in dup_compare: no callback specified for database '%s'", CurrentDB->filename) ;
-
- data1 = key1->data ;
- data2 = key2->data ;
-
-#ifndef newSVpvn
- /* As newSVpv will assume that the data pointer is a null terminated C
- string if the size parameter is 0, make sure that data points to an
- empty string if the length is 0
- */
- if (key1->size == 0)
- data1 = "" ;
- if (key2->size == 0)
- data2 = "" ;
-#endif
-
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
- EXTEND(SP,2) ;
- PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
- PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->dup_compare, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- softCrash ("dup_compare: expected 1 return value from compare sub, got %d", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
- return (retval) ;
-
-}
-
-static size_t
-btree_prefix(DB_callback const DBT * key1, const DBT * key2 )
-{
- dSP ;
- void * data1, * data2 ;
- int retval ;
- int count ;
-
- data1 = key1->data ;
- data2 = key2->data ;
-
-#ifndef newSVpvn
- /* As newSVpv will assume that the data pointer is a null terminated C
- string if the size parameter is 0, make sure that data points to an
- empty string if the length is 0
- */
- if (key1->size == 0)
- data1 = "" ;
- if (key2->size == 0)
- data2 = "" ;
-#endif
-
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
- EXTEND(SP,2) ;
- PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
- PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- softCrash ("btree_prefix: expected 1 return value from prefix sub, got %d", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
-
- return (retval) ;
-}
-
-static u_int32_t
-hash_cb(DB_callback const void * data, u_int32_t size)
-{
- dSP ;
- int retval ;
- int count ;
-
-#ifndef newSVpvn
- if (size == 0)
- data = "" ;
-#endif
-
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
-
- XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->hash, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- softCrash ("hash_cb: expected 1 return value from hash sub, got %d", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
-
- return (retval) ;
-}
-
-static void
-db_errcall_cb(const char * db_errpfx, char * buffer)
-{
-#if 0
-
- if (db_errpfx == NULL)
- db_errpfx = "" ;
- if (buffer == NULL )
- buffer = "" ;
- ErrBuff[0] = '\0';
- if (strlen(db_errpfx) + strlen(buffer) + 3 <= 1000) {
- if (*db_errpfx != '\0') {
- strcat(ErrBuff, db_errpfx) ;
- strcat(ErrBuff, ": ") ;
- }
- strcat(ErrBuff, buffer) ;
- }
-
-#endif
-
- SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
- if (sv) {
- if (db_errpfx)
- sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
- else
- sv_setpv(sv, buffer) ;
- }
-}
-
-static SV *
-readHash(HV * hash, char * key)
-{
- SV ** svp;
- svp = hv_fetch(hash, key, strlen(key), FALSE);
- if (svp && SvOK(*svp))
- return *svp ;
- return NULL ;
-}
-
-static void
-hash_delete(char * hash, IV key)
-{
- HV * hv = perl_get_hv(hash, TRUE);
- (void) hv_delete(hv, (char*)&key, sizeof(key), G_DISCARD);
-}
-
-static void
-hash_store_iv(char * hash, IV key, IV value)
-{
- HV * hv = perl_get_hv(hash, TRUE);
- SV ** ret = hv_store(hv, (char*)&key, sizeof(key), newSViv(value), 0);
- /* printf("hv_store returned %d\n", ret) ; */
-}
-
-static void
-hv_store_iv(HV * hash, char * key, IV value)
-{
- hv_store(hash, key, strlen(key), newSViv(value), 0);
-}
-
-static BerkeleyDB
-my_db_open(
- BerkeleyDB db ,
- SV * ref,
- SV * ref_dbenv ,
- BerkeleyDB__Env dbenv ,
- const char * file,
- const char * subname,
- DBTYPE type,
- int flags,
- int mode,
- DB_INFO * info
- )
-{
- DB_ENV * env = NULL ;
- BerkeleyDB RETVAL = NULL ;
- DB * dbp ;
- int Status ;
-
- Trace(("_db_open(dbenv[%lu] ref_dbenv [%lu] file[%s] subname [%s] type[%d] flags[%d] mode[%d]\n",
- dbenv, ref_dbenv, file, subname, type, flags, mode)) ;
-
- CurrentDB = db ;
- if (dbenv)
- env = dbenv->Env ;
-
-#if DB_VERSION_MAJOR == 2
- if (subname)
- softCrash("Subname needs Berkeley DB 3 or better") ;
-#endif
-
-#if DB_VERSION_MAJOR > 2
- Status = db_create(&dbp, env, 0) ;
- Trace(("db_create returned %s\n", my_db_strerror(Status))) ;
- if (Status)
- return RETVAL ;
-
- if (info->re_source) {
- Status = dbp->set_re_source(dbp, info->re_source) ;
- Trace(("set_re_source [%s] returned %s\n",
- info->re_source, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->db_cachesize) {
- Status = dbp->set_cachesize(dbp, 0, info->db_cachesize, 0) ;
- Trace(("set_cachesize [%d] returned %s\n",
- info->db_cachesize, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->db_lorder) {
- Status = dbp->set_lorder(dbp, info->db_lorder) ;
- Trace(("set_lorder [%d] returned %s\n",
- info->db_lorder, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->db_pagesize) {
- Status = dbp->set_pagesize(dbp, info->db_pagesize) ;
- Trace(("set_pagesize [%d] returned %s\n",
- info->db_pagesize, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->h_ffactor) {
- Status = dbp->set_h_ffactor(dbp, info->h_ffactor) ;
- Trace(("set_h_ffactor [%d] returned %s\n",
- info->h_ffactor, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->h_nelem) {
- Status = dbp->set_h_nelem(dbp, info->h_nelem) ;
- Trace(("set_h_nelem [%d] returned %s\n",
- info->h_nelem, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->bt_minkey) {
- Status = dbp->set_bt_minkey(dbp, info->bt_minkey) ;
- Trace(("set_bt_minkey [%d] returned %s\n",
- info->bt_minkey, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->bt_compare) {
- Status = dbp->set_bt_compare(dbp, info->bt_compare) ;
- Trace(("set_bt_compare [%d] returned %s\n",
- info->bt_compare, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->h_hash) {
- Status = dbp->set_h_hash(dbp, info->h_hash) ;
- Trace(("set_h_hash [%d] returned %s\n",
- info->h_hash, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->dup_compare) {
- Status = dbp->set_dup_compare(dbp, info->dup_compare) ;
- Trace(("set_dup_compare [%d] returned %s\n",
- info->dup_compare, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->bt_prefix) {
- Status = dbp->set_bt_prefix(dbp, info->bt_prefix) ;
- Trace(("set_bt_prefix [%d] returned %s\n",
- info->bt_prefix, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->re_len) {
- Status = dbp->set_re_len(dbp, info->re_len) ;
- Trace(("set_re_len [%d] returned %s\n",
- info->re_len, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->re_delim) {
- Status = dbp->set_re_delim(dbp, info->re_delim) ;
- Trace(("set_re_delim [%d] returned %s\n",
- info->re_delim, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->re_pad) {
- Status = dbp->set_re_pad(dbp, info->re_pad) ;
- Trace(("set_re_pad [%d] returned %s\n",
- info->re_pad, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->flags) {
- Status = dbp->set_flags(dbp, info->flags) ;
- Trace(("set_flags [%d] returned %s\n",
- info->flags, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
- }
-
- if (info->q_extentsize) {
-#ifdef AT_LEAST_DB_3_2
- Status = dbp->set_q_extentsize(dbp, info->q_extentsize) ;
- Trace(("set_flags [%d] returned %s\n",
- info->flags, my_db_strerror(Status)));
- if (Status)
- return RETVAL ;
-#else
- softCrash("-ExtentSize needs at least Berkeley DB 3.2.x") ;
-#endif
- }
-
- if ((Status = (dbp->open)(dbp, file, subname, type, flags, mode)) == 0) {
-#else /* DB_VERSION_MAJOR == 2 */
- if ((Status = db_open(file, type, flags, mode, env, info, &dbp)) == 0) {
-#endif /* DB_VERSION_MAJOR == 2 */
-
- Trace(("db_opened\n"));
- RETVAL = db ;
- RETVAL->dbp = dbp ;
-#if DB_VERSION_MAJOR == 2
- RETVAL->type = dbp->type ;
-#else /* DB_VERSION_MAJOR > 2 */
- RETVAL->type = dbp->get_type(dbp) ;
-#endif /* DB_VERSION_MAJOR > 2 */
- RETVAL->recno_or_queue = (RETVAL->type == DB_RECNO ||
- RETVAL->type == DB_QUEUE) ;
- RETVAL->filename = my_strdup(file) ;
- RETVAL->Status = Status ;
- RETVAL->active = TRUE ;
- hash_store_iv("BerkeleyDB::Term::Db", (IV)RETVAL, 1) ;
- Trace((" storing %d %d in BerkeleyDB::Term::Db\n", RETVAL, dbp)) ;
- if (dbenv) {
- RETVAL->parent_env = dbenv ;
- dbenv->Status = Status ;
- ++ dbenv->open_dbs ;
- }
- }
- else {
-#if DB_VERSION_MAJOR > 2
- (dbp->close)(dbp, 0) ;
-#endif
- destroyDB(db) ;
- Trace(("db open returned %s\n", my_db_strerror(Status))) ;
- }
-
- return RETVAL ;
-}
-
-static double
-constant(char * name, int arg)
-{
- errno = 0;
- switch (*name) {
- case 'A':
- break;
- case 'B':
- break;
- case 'C':
- break;
- case 'D':
- if (strEQ(name, "DB_AFTER"))
-#ifdef DB_AFTER
- return DB_AFTER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_APPEND"))
-#ifdef DB_APPEND
- return DB_APPEND;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_ARCH_ABS"))
-#ifdef DB_ARCH_ABS
- return DB_ARCH_ABS;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_ARCH_DATA"))
-#ifdef DB_ARCH_DATA
- return DB_ARCH_DATA;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_ARCH_LOG"))
-#ifdef DB_ARCH_LOG
- return DB_ARCH_LOG;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_BEFORE"))
-#ifdef DB_BEFORE
- return DB_BEFORE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_BTREE"))
- return DB_BTREE;
- if (strEQ(name, "DB_BTREEMAGIC"))
-#ifdef DB_BTREEMAGIC
- return DB_BTREEMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_BTREEOLDVER"))
-#ifdef DB_BTREEOLDVER
- return DB_BTREEOLDVER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_BTREEVERSION"))
-#ifdef DB_BTREEVERSION
- return DB_BTREEVERSION;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_CHECKPOINT"))
-#ifdef DB_CHECKPOINT
- return DB_CHECKPOINT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_CONSUME"))
-#ifdef DB_CONSUME
- return DB_CONSUME;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_CREATE"))
-#ifdef DB_CREATE
- return DB_CREATE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_CURLSN"))
-#ifdef DB_CURLSN
- return DB_CURLSN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_CURRENT"))
-#ifdef DB_CURRENT
- return DB_CURRENT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DBT_MALLOC"))
-#ifdef DB_DBT_MALLOC
- return DB_DBT_MALLOC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DBT_PARTIAL"))
-#ifdef DB_DBT_PARTIAL
- return DB_DBT_PARTIAL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DBT_USERMEM"))
-#ifdef DB_DBT_USERMEM
- return DB_DBT_USERMEM;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DELETED"))
-#ifdef DB_DELETED
- return DB_DELETED;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DELIMITER"))
-#ifdef DB_DELIMITER
- return DB_DELIMITER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DUP"))
-#ifdef DB_DUP
- return DB_DUP;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_DUPSORT"))
-#ifdef DB_DUPSORT
- return DB_DUPSORT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_ENV_APPINIT"))
-#ifdef DB_ENV_APPINIT
- return DB_ENV_APPINIT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_ENV_STANDALONE"))
-#ifdef DB_ENV_STANDALONE
- return DB_ENV_STANDALONE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_ENV_THREAD"))
-#ifdef DB_ENV_THREAD
- return DB_ENV_THREAD;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_EXCL"))
-#ifdef DB_EXCL
- return DB_EXCL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_FILE_ID_LEN"))
-#ifdef DB_FILE_ID_LEN
- return DB_FILE_ID_LEN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_FIRST"))
-#ifdef DB_FIRST
- return DB_FIRST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_FIXEDLEN"))
-#ifdef DB_FIXEDLEN
- return DB_FIXEDLEN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_FLUSH"))
-#ifdef DB_FLUSH
- return DB_FLUSH;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_FORCE"))
-#ifdef DB_FORCE
- return DB_FORCE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_GET_BOTH"))
-#ifdef DB_GET_BOTH
- return DB_GET_BOTH;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_GET_RECNO"))
-#ifdef DB_GET_RECNO
- return DB_GET_RECNO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_HASH"))
- return DB_HASH;
- if (strEQ(name, "DB_HASHMAGIC"))
-#ifdef DB_HASHMAGIC
- return DB_HASHMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_HASHOLDVER"))
-#ifdef DB_HASHOLDVER
- return DB_HASHOLDVER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_HASHVERSION"))
-#ifdef DB_HASHVERSION
- return DB_HASHVERSION;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_INCOMPLETE"))
-#ifdef DB_INCOMPLETE
- return DB_INCOMPLETE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_INIT_CDB"))
-#ifdef DB_INIT_CDB
- return DB_INIT_CDB;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_INIT_LOCK"))
-#ifdef DB_INIT_LOCK
- return DB_INIT_LOCK;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_INIT_LOG"))
-#ifdef DB_INIT_LOG
- return DB_INIT_LOG;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_INIT_MPOOL"))
-#ifdef DB_INIT_MPOOL
- return DB_INIT_MPOOL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_INIT_TXN"))
-#ifdef DB_INIT_TXN
- return DB_INIT_TXN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_JOIN_ITEM"))
-#ifdef DB_JOIN_ITEM
- return DB_JOIN_ITEM;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_KEYEMPTY"))
-#ifdef DB_KEYEMPTY
- return DB_KEYEMPTY;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_KEYEXIST"))
-#ifdef DB_KEYEXIST
- return DB_KEYEXIST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_KEYFIRST"))
-#ifdef DB_KEYFIRST
- return DB_KEYFIRST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_KEYLAST"))
-#ifdef DB_KEYLAST
- return DB_KEYLAST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LAST"))
-#ifdef DB_LAST
- return DB_LAST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCKMAGIC"))
-#ifdef DB_LOCKMAGIC
- return DB_LOCKMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCKVERSION"))
-#ifdef DB_LOCKVERSION
- return DB_LOCKVERSION;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_CONFLICT"))
-#ifdef DB_LOCK_CONFLICT
- return DB_LOCK_CONFLICT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_DEADLOCK"))
-#ifdef DB_LOCK_DEADLOCK
- return DB_LOCK_DEADLOCK;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_DEFAULT"))
-#ifdef DB_LOCK_DEFAULT
- return DB_LOCK_DEFAULT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_GET"))
- return DB_LOCK_GET;
- if (strEQ(name, "DB_LOCK_NORUN"))
-#ifdef DB_LOCK_NORUN
- return DB_LOCK_NORUN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_NOTGRANTED"))
-#ifdef DB_LOCK_NOTGRANTED
- return DB_LOCK_NOTGRANTED;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_NOTHELD"))
-#ifdef DB_LOCK_NOTHELD
- return DB_LOCK_NOTHELD;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_NOWAIT"))
-#ifdef DB_LOCK_NOWAIT
- return DB_LOCK_NOWAIT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_OLDEST"))
-#ifdef DB_LOCK_OLDEST
- return DB_LOCK_OLDEST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_RANDOM"))
-#ifdef DB_LOCK_RANDOM
- return DB_LOCK_RANDOM;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_RIW_N"))
-#ifdef DB_LOCK_RIW_N
- return DB_LOCK_RIW_N;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_RW_N"))
-#ifdef DB_LOCK_RW_N
- return DB_LOCK_RW_N;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOCK_YOUNGEST"))
-#ifdef DB_LOCK_YOUNGEST
- return DB_LOCK_YOUNGEST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOGMAGIC"))
-#ifdef DB_LOGMAGIC
- return DB_LOGMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_LOGOLDVER"))
-#ifdef DB_LOGOLDVER
- return DB_LOGOLDVER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MAX_PAGES"))
-#ifdef DB_MAX_PAGES
- return DB_MAX_PAGES;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MAX_RECORDS"))
-#ifdef DB_MAX_RECORDS
- return DB_MAX_RECORDS;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_CLEAN"))
-#ifdef DB_MPOOL_CLEAN
- return DB_MPOOL_CLEAN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_CREATE"))
-#ifdef DB_MPOOL_CREATE
- return DB_MPOOL_CREATE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_DIRTY"))
-#ifdef DB_MPOOL_DIRTY
- return DB_MPOOL_DIRTY;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_DISCARD"))
-#ifdef DB_MPOOL_DISCARD
- return DB_MPOOL_DISCARD;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_LAST"))
-#ifdef DB_MPOOL_LAST
- return DB_MPOOL_LAST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_NEW"))
-#ifdef DB_MPOOL_NEW
- return DB_MPOOL_NEW;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MPOOL_PRIVATE"))
-#ifdef DB_MPOOL_PRIVATE
- return DB_MPOOL_PRIVATE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MUTEXDEBUG"))
-#ifdef DB_MUTEXDEBUG
- return DB_MUTEXDEBUG;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_MUTEXLOCKS"))
-#ifdef DB_MUTEXLOCKS
- return DB_MUTEXLOCKS;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NEEDSPLIT"))
-#ifdef DB_NEEDSPLIT
- return DB_NEEDSPLIT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NEXT"))
-#ifdef DB_NEXT
- return DB_NEXT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NEXT_DUP"))
-#ifdef DB_NEXT_DUP
- return DB_NEXT_DUP;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NOMMAP"))
-#ifdef DB_NOMMAP
- return DB_NOMMAP;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NOOVERWRITE"))
-#ifdef DB_NOOVERWRITE
- return DB_NOOVERWRITE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NOSYNC"))
-#ifdef DB_NOSYNC
- return DB_NOSYNC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_NOTFOUND"))
-#ifdef DB_NOTFOUND
- return DB_NOTFOUND;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_PAD"))
-#ifdef DB_PAD
- return DB_PAD;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_PAGEYIELD"))
-#ifdef DB_PAGEYIELD
- return DB_PAGEYIELD;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_POSITION"))
-#ifdef DB_POSITION
- return DB_POSITION;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_PREV"))
-#ifdef DB_PREV
- return DB_PREV;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_PRIVATE"))
-#ifdef DB_PRIVATE
- return DB_PRIVATE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_QUEUE"))
- return DB_QUEUE;
- if (strEQ(name, "DB_RDONLY"))
-#ifdef DB_RDONLY
- return DB_RDONLY;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RECNO"))
- return DB_RECNO;
- if (strEQ(name, "DB_RECNUM"))
-#ifdef DB_RECNUM
- return DB_RECNUM;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RECORDCOUNT"))
-#ifdef DB_RECORDCOUNT
- return DB_RECORDCOUNT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RECOVER"))
-#ifdef DB_RECOVER
- return DB_RECOVER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RECOVER_FATAL"))
-#ifdef DB_RECOVER_FATAL
- return DB_RECOVER_FATAL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_REGISTERED"))
-#ifdef DB_REGISTERED
- return DB_REGISTERED;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RENUMBER"))
-#ifdef DB_RENUMBER
- return DB_RENUMBER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RMW"))
-#ifdef DB_RMW
- return DB_RMW;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_RUNRECOVERY"))
-#ifdef DB_RUNRECOVERY
- return DB_RUNRECOVERY;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SEQUENTIAL"))
-#ifdef DB_SEQUENTIAL
- return DB_SEQUENTIAL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SET"))
-#ifdef DB_SET
- return DB_SET;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SET_RANGE"))
-#ifdef DB_SET_RANGE
- return DB_SET_RANGE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SET_RECNO"))
-#ifdef DB_SET_RECNO
- return DB_SET_RECNO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SNAPSHOT"))
-#ifdef DB_SNAPSHOT
- return DB_SNAPSHOT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SWAPBYTES"))
-#ifdef DB_SWAPBYTES
- return DB_SWAPBYTES;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TEMPORARY"))
-#ifdef DB_TEMPORARY
- return DB_TEMPORARY;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_THREAD"))
-#ifdef DB_THREAD
- return DB_THREAD;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TRUNCATE"))
-#ifdef DB_TRUNCATE
- return DB_TRUNCATE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXNMAGIC"))
-#ifdef DB_TXNMAGIC
- return DB_TXNMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXNVERSION"))
-#ifdef DB_TXNVERSION
- return DB_TXNVERSION;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_BACKWARD_ROLL"))
- return DB_TXN_BACKWARD_ROLL;
- if (strEQ(name, "DB_TXN_CKP"))
-#ifdef DB_TXN_CKP
- return DB_TXN_CKP;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_FORWARD_ROLL"))
- return DB_TXN_FORWARD_ROLL;
- if (strEQ(name, "DB_TXN_LOCK_2PL"))
-#ifdef DB_TXN_LOCK_2PL
- return DB_TXN_LOCK_2PL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOCK_MASK"))
-#ifdef DB_TXN_LOCK_MASK
- return DB_TXN_LOCK_MASK;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOCK_OPTIMIST"))
-#ifdef DB_TXN_LOCK_OPTIMIST
- return DB_TXN_LOCK_OPTIMIST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOCK_OPTIMISTIC"))
-#ifdef DB_TXN_LOCK_OPTIMISTIC
- return DB_TXN_LOCK_OPTIMISTIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOG_MASK"))
-#ifdef DB_TXN_LOG_MASK
- return DB_TXN_LOG_MASK;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOG_REDO"))
-#ifdef DB_TXN_LOG_REDO
- return DB_TXN_LOG_REDO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOG_UNDO"))
-#ifdef DB_TXN_LOG_UNDO
- return DB_TXN_LOG_UNDO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_LOG_UNDOREDO"))
-#ifdef DB_TXN_LOG_UNDOREDO
- return DB_TXN_LOG_UNDOREDO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_NOSYNC"))
-#ifdef DB_TXN_NOSYNC
- return DB_TXN_NOSYNC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_NOWAIT"))
-#ifdef DB_TXN_NOWAIT
- return DB_TXN_NOWAIT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_OPENFILES"))
- return DB_TXN_OPENFILES;
- if (strEQ(name, "DB_TXN_REDO"))
-#ifdef DB_TXN_REDO
- return DB_TXN_REDO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_SYNC"))
-#ifdef DB_TXN_SYNC
- return DB_TXN_SYNC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN_UNDO"))
-#ifdef DB_TXN_UNDO
- return DB_TXN_UNDO;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_UNKNOWN"))
- return DB_UNKNOWN;
- if (strEQ(name, "DB_USE_ENVIRON"))
-#ifdef DB_USE_ENVIRON
- return DB_USE_ENVIRON;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_USE_ENVIRON_ROOT"))
-#ifdef DB_USE_ENVIRON_ROOT
- return DB_USE_ENVIRON_ROOT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_VERSION_MAJOR"))
-#ifdef DB_VERSION_MAJOR
- return DB_VERSION_MAJOR;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_VERSION_MINOR"))
-#ifdef DB_VERSION_MINOR
- return DB_VERSION_MINOR;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_VERSION_PATCH"))
-#ifdef DB_VERSION_PATCH
- return DB_VERSION_PATCH;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_WRITECURSOR"))
-#ifdef DB_WRITECURSOR
- return DB_WRITECURSOR;
-#else
- goto not_there;
-#endif
- break;
- case 'E':
- break;
- case 'F':
- break;
- case 'G':
- break;
- case 'H':
- break;
- case 'I':
- break;
- case 'J':
- break;
- case 'K':
- break;
- case 'L':
- break;
- case 'M':
- break;
- case 'N':
- break;
- case 'O':
- break;
- case 'P':
- break;
- case 'Q':
- break;
- case 'R':
- break;
- case 'S':
- break;
- case 'T':
- break;
- case 'U':
- break;
- case 'V':
- break;
- case 'W':
- break;
- case 'X':
- break;
- case 'Y':
- break;
- case 'Z':
- break;
- case 'a':
- break;
- case 'b':
- break;
- case 'c':
- break;
- case 'd':
- break;
- case 'e':
- break;
- case 'f':
- break;
- case 'g':
- break;
- case 'h':
- break;
- case 'i':
- break;
- case 'j':
- break;
- case 'k':
- break;
- case 'l':
- break;
- case 'm':
- break;
- case 'n':
- break;
- case 'o':
- break;
- case 'p':
- break;
- case 'q':
- break;
- case 'r':
- break;
- case 's':
- break;
- case 't':
- break;
- case 'u':
- break;
- case 'v':
- break;
- case 'w':
- break;
- case 'x':
- break;
- case 'y':
- break;
- case 'z':
- break;
- }
- errno = EINVAL;
- return 0;
-
-not_there:
- errno = ENOENT;
- return 0;
-}
-
-
-MODULE = BerkeleyDB PACKAGE = BerkeleyDB PREFIX = env_
-
-char *
-DB_VERSION_STRING()
- CODE:
- RETVAL = DB_VERSION_STRING ;
- OUTPUT:
- RETVAL
-
-
-double
-constant(name,arg)
- char * name
- int arg
-
-#define env_db_version(maj, min, patch) db_version(&maj, &min, &patch)
-char *
-env_db_version(maj, min, patch)
- int maj
- int min
- int patch
- OUTPUT:
- RETVAL
- maj
- min
- patch
-
-int
-db_value_set(value, which)
- int value
- int which
- NOT_IMPLEMENTED_YET
-
-
-DualType
-_db_remove(ref)
- SV * ref
- CODE:
- {
-#if DB_VERSION_MAJOR == 2
- softCrash("BerkeleyDB::db_remove needs Berkeley DB 3.x or better") ;
-#else
- HV * hash ;
- DB * dbp ;
- SV * sv ;
- const char * db ;
- const char * subdb = NULL ;
- BerkeleyDB__Env env = NULL ;
- DB_ENV * dbenv = NULL ;
- u_int32_t flags = 0 ;
-
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(db, "Filename", char *) ;
- SetValue_pv(subdb, "Subname", char *) ;
- SetValue_iv(flags, "Flags") ;
- SetValue_ov(env, "Env", BerkeleyDB__Env) ;
- if (env)
- dbenv = env->Env ;
- RETVAL = db_create(&dbp, dbenv, 0) ;
- if (RETVAL == 0) {
- RETVAL = dbp->remove(dbp, db, subdb, flags) ;
- }
-#endif
- }
- OUTPUT:
- RETVAL
-
-MODULE = BerkeleyDB::Env PACKAGE = BerkeleyDB::Env PREFIX = env_
-
-
-BerkeleyDB::Env::Raw
-_db_appinit(self, ref)
- char * self
- SV * ref
- CODE:
- {
- HV * hash ;
- SV * sv ;
- char * home = NULL ;
- char * server = NULL ;
- char ** config = NULL ;
- int flags = 0 ;
- int cachesize = 0 ;
- int lk_detect = 0 ;
- int mode = 0 ;
- SV * errprefix = NULL;
- DB_ENV * env ;
- int status ;
-
- Trace(("in _db_appinit [%s] %d\n", self, ref)) ;
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(home, "Home", char *) ;
- SetValue_pv(config, "Config", char **) ;
- SetValue_sv(errprefix, "ErrPrefix") ;
- SetValue_iv(flags, "Flags") ;
- SetValue_pv(server, "Server", char *) ;
- SetValue_iv(cachesize, "Cachesize") ;
- SetValue_iv(lk_detect, "LockDetect") ;
-#ifndef AT_LEAST_DB_3_1
- if (server)
- softCrash("-Server needs Berkeley DB 3.1 or better") ;
-#endif /* ! AT_LEAST_DB_3_1 */
- Trace(("_db_appinit(config=[%d], home=[%s],errprefix=[%s],flags=[%d]\n",
- config, home, errprefix, flags)) ;
-#ifdef TRACE
- if (config) {
- int i ;
- for (i = 0 ; i < 10 ; ++ i) {
- if (config[i] == NULL) {
- printf(" End\n") ;
- break ;
- }
- printf(" config = [%s]\n", config[i]) ;
- }
- }
-#endif /* TRACE */
- ZMALLOC(RETVAL, BerkeleyDB_ENV_type) ;
- if (flags & DB_INIT_TXN)
- RETVAL->txn_enabled = TRUE ;
-#if DB_VERSION_MAJOR == 2
- ZMALLOC(RETVAL->Env, DB_ENV) ;
- env = RETVAL->Env ;
- {
- /* Take a copy of the error prefix */
- if (errprefix) {
- Trace(("copying errprefix\n" )) ;
- RETVAL->ErrPrefix = newSVsv(errprefix) ;
- SvPOK_only(RETVAL->ErrPrefix) ;
- }
- if (RETVAL->ErrPrefix)
- RETVAL->Env->db_errpfx = SvPVX(RETVAL->ErrPrefix) ;
-
- if ((sv = readHash(hash, "ErrFile")) && sv != &PL_sv_undef) {
- env->db_errfile = IoOFP(sv_2io(sv)) ;
- RETVAL->ErrHandle = newRV(sv) ;
- }
- /* SetValue_io(RETVAL->Env.db_errfile, "ErrFile") ; */
- SetValue_iv(env->db_verbose, "Verbose") ;
- /* env->db_errbuf = RETVAL->ErrBuff ; */
- env->db_errcall = db_errcall_cb ;
- RETVAL->active = TRUE ;
- status = db_appinit(home, config, env, flags) ;
- Trace((" status = %d env %d Env %d\n", status, RETVAL, env)) ;
- if (status == 0)
- hash_store_iv("BerkeleyDB::Term::Env", (IV)RETVAL, 1) ;
- else {
- if (RETVAL->ErrHandle)
- SvREFCNT_dec(RETVAL->ErrHandle) ;
- if (RETVAL->ErrPrefix)
- SvREFCNT_dec(RETVAL->ErrPrefix) ;
- Safefree(RETVAL->Env) ;
- Safefree(RETVAL) ;
- RETVAL = NULL ;
- }
- }
-#else /* DB_VERSION_MAJOR > 2 */
-#ifndef AT_LEAST_DB_3_1
-# define DB_CLIENT 0
-#endif
- status = db_env_create(&RETVAL->Env, server ? DB_CLIENT : 0) ;
- Trace(("db_env_create flags = %d returned %s\n", flags,
- my_db_strerror(status))) ;
- env = RETVAL->Env ;
- if (status == 0 && cachesize) {
- status = env->set_cachesize(env, 0, cachesize, 0) ;
- Trace(("set_cachesize [%d] returned %s\n",
- cachesize, my_db_strerror(status)));
- }
-
- if (status == 0 && lk_detect) {
- status = env->set_lk_detect(env, lk_detect) ;
- Trace(("set_lk_detect [%d] returned %s\n",
- lk_detect, my_db_strerror(status)));
- }
-#ifdef AT_LEAST_DB_3_1
- /* set the server */
- if (server && status == 0)
- {
- status = env->set_server(env, server, 0, 0, 0);
- Trace(("ENV->set_server server = %s returned %s\n", server,
- my_db_strerror(status))) ;
- }
-#endif
- if (status == 0)
- {
- /* Take a copy of the error prefix */
- if (errprefix) {
- Trace(("copying errprefix\n" )) ;
- RETVAL->ErrPrefix = newSVsv(errprefix) ;
- SvPOK_only(RETVAL->ErrPrefix) ;
- }
- if (RETVAL->ErrPrefix)
- env->set_errpfx(env, SvPVX(RETVAL->ErrPrefix)) ;
-
- if ((sv = readHash(hash, "ErrFile")) && sv != &PL_sv_undef) {
- env->set_errfile(env, IoOFP(sv_2io(sv))) ;
- RETVAL->ErrHandle = newRV(sv) ;
- }
- /* SetValue_iv(RETVAL->Env.db_verbose, "Verbose") ; */ /* TODO */
- SetValue_iv(mode, "Mode") ;
- /* RETVAL->Env.db_errbuf = RETVAL->ErrBuff ; */
- env->set_errcall(env, db_errcall_cb) ;
- RETVAL->active = TRUE ;
-#ifdef IS_DB_3_0
- status = (env->open)(env, home, config, flags, mode) ;
-#else /* > 3.0 */
- status = (env->open)(env, home, flags, mode) ;
-#endif
- Trace(("ENV->open returned %s\n", my_db_strerror(status))) ;
- }
-
- if (status == 0)
- hash_store_iv("BerkeleyDB::Term::Env", (IV)RETVAL, 1) ;
- else {
- (env->close)(env, 0) ;
- if (RETVAL->ErrHandle)
- SvREFCNT_dec(RETVAL->ErrHandle) ;
- if (RETVAL->ErrPrefix)
- SvREFCNT_dec(RETVAL->ErrPrefix) ;
- Safefree(RETVAL) ;
- RETVAL = NULL ;
- }
-#endif /* DB_VERSION_MAJOR > 2 */
- }
- OUTPUT:
- RETVAL
-
-BerkeleyDB::Txn::Raw
-_txn_begin(env, pid=NULL, flags=0)
- BerkeleyDB::Env env
- BerkeleyDB::Txn pid
- u_int32_t flags
- CODE:
- {
- DB_TXN *txn ;
- DB_TXN *p_id = NULL ;
- Trace(("txn_begin pid %d, flags %d\n", pid, flags)) ;
-#if DB_VERSION_MAJOR == 2
- if (env->Env->tx_info == NULL)
- softCrash("Transaction Manager not enabled") ;
-#endif
- if (!env->txn_enabled)
- softCrash("Transaction Manager not enabled") ;
- if (pid)
- p_id = pid->txn ;
- env->TxnMgrStatus =
-#if DB_VERSION_MAJOR == 2
- txn_begin(env->Env->tx_info, p_id, &txn) ;
-#else
- txn_begin(env->Env, p_id, &txn, flags) ;
-#endif
- if (env->TxnMgrStatus == 0) {
- ZMALLOC(RETVAL, BerkeleyDB_Txn_type) ;
- RETVAL->txn = txn ;
- RETVAL->active = TRUE ;
- Trace(("_txn_begin created txn [%d] in [%d]\n", txn, RETVAL));
- hash_store_iv("BerkeleyDB::Term::Txn", (IV)RETVAL, 1) ;
- }
- else
- RETVAL = NULL ;
- }
- OUTPUT:
- RETVAL
-
-
-#if DB_VERSION_MAJOR == 2
-# define env_txn_checkpoint(e,k,m) txn_checkpoint(e->Env->tx_info, k, m)
-#else /* DB 3.0 or better */
-# ifdef AT_LEAST_DB_3_1
-# define env_txn_checkpoint(e,k,m) txn_checkpoint(e->Env, k, m, 0)
-# else
-# define env_txn_checkpoint(e,k,m) txn_checkpoint(e->Env, k, m)
-# endif
-#endif
-DualType
-env_txn_checkpoint(env, kbyte, min)
- BerkeleyDB::Env env
- long kbyte
- long min
-
-HV *
-txn_stat(env)
- BerkeleyDB::Env env
- HV * RETVAL = NULL ;
- CODE:
- {
- DB_TXN_STAT * stat ;
-#if DB_VERSION_MAJOR == 2
- if(txn_stat(env->Env->tx_info, &stat, safemalloc) == 0) {
-#else
- if(txn_stat(env->Env, &stat, safemalloc) == 0) {
-#endif
- RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
- hv_store_iv(RETVAL, "st_time_ckp", stat->st_time_ckp) ;
- hv_store_iv(RETVAL, "st_last_txnid", stat->st_last_txnid) ;
- hv_store_iv(RETVAL, "st_maxtxns", stat->st_maxtxns) ;
- hv_store_iv(RETVAL, "st_naborts", stat->st_naborts) ;
- hv_store_iv(RETVAL, "st_nbegins", stat->st_nbegins) ;
- hv_store_iv(RETVAL, "st_ncommits", stat->st_ncommits) ;
- hv_store_iv(RETVAL, "st_nactive", stat->st_nactive) ;
-#if DB_VERSION_MAJOR > 2
- hv_store_iv(RETVAL, "st_maxnactive", stat->st_maxnactive) ;
- hv_store_iv(RETVAL, "st_regsize", stat->st_regsize) ;
- hv_store_iv(RETVAL, "st_region_wait", stat->st_region_wait) ;
- hv_store_iv(RETVAL, "st_region_nowait", stat->st_region_nowait) ;
-#endif
- safefree(stat) ;
- }
- }
- OUTPUT:
- RETVAL
-
-#define EnDis(x) ((x) ? "Enabled" : "Disabled")
-void
-printEnv(env)
- BerkeleyDB::Env env
- INIT:
- ckActive_Environment(env->active) ;
- CODE:
-#if 0
- printf("env [0x%X]\n", env) ;
- printf(" ErrPrefix [%s]\n", env->ErrPrefix
- ? SvPVX(env->ErrPrefix) : 0) ;
- printf(" DB_ENV\n") ;
- printf(" db_lorder [%d]\n", env->Env.db_lorder) ;
- printf(" db_home [%s]\n", env->Env.db_home) ;
- printf(" db_data_dir [%s]\n", env->Env.db_data_dir) ;
- printf(" db_log_dir [%s]\n", env->Env.db_log_dir) ;
- printf(" db_tmp_dir [%s]\n", env->Env.db_tmp_dir) ;
- printf(" lk_info [%s]\n", EnDis(env->Env.lk_info)) ;
- printf(" lk_max [%d]\n", env->Env.lk_max) ;
- printf(" lg_info [%s]\n", EnDis(env->Env.lg_info)) ;
- printf(" lg_max [%d]\n", env->Env.lg_max) ;
- printf(" mp_info [%s]\n", EnDis(env->Env.mp_info)) ;
- printf(" mp_size [%d]\n", env->Env.mp_size) ;
- printf(" tx_info [%s]\n", EnDis(env->Env.tx_info)) ;
- printf(" tx_max [%d]\n", env->Env.tx_max) ;
- printf(" flags [%d]\n", env->Env.flags) ;
- printf("\n") ;
-#endif
-
-SV *
-errPrefix(env, prefix)
- BerkeleyDB::Env env
- SV * prefix
- INIT:
- ckActive_Environment(env->active) ;
- CODE:
- if (env->ErrPrefix) {
- RETVAL = newSVsv(env->ErrPrefix) ;
- SvPOK_only(RETVAL) ;
- sv_setsv(env->ErrPrefix, prefix) ;
- }
- else {
- RETVAL = NULL ;
- env->ErrPrefix = newSVsv(prefix) ;
- }
- SvPOK_only(env->ErrPrefix) ;
-#if DB_VERSION_MAJOR == 2
- env->Env->db_errpfx = SvPVX(env->ErrPrefix) ;
-#else
- env->Env->set_errpfx(env->Env, SvPVX(env->ErrPrefix)) ;
-#endif
- OUTPUT:
- RETVAL
-
-DualType
-status(env)
- BerkeleyDB::Env env
- CODE:
- RETVAL = env->Status ;
- OUTPUT:
- RETVAL
-
-DualType
-db_appexit(env)
- BerkeleyDB::Env env
- INIT:
- ckActive_Environment(env->active) ;
- CODE:
-#ifdef STRICT_CLOSE
- if (env->open_dbs)
- softCrash("attempted to close an environment with %d open database(s)",
- env->open_dbs) ;
-#endif /* STRICT_CLOSE */
-#if DB_VERSION_MAJOR == 2
- RETVAL = db_appexit(env->Env) ;
-#else
- RETVAL = (env->Env->close)(env->Env, 0) ;
-#endif
- env->active = FALSE ;
- hash_delete("BerkeleyDB::Term::Env", (IV)env) ;
- OUTPUT:
- RETVAL
-
-
-void
-_DESTROY(env)
- BerkeleyDB::Env env
- int RETVAL = 0 ;
- CODE:
- Trace(("In BerkeleyDB::Env::DESTROY\n"));
- Trace((" env %ld Env %ld dirty %d\n", env, &env->Env, PL_dirty)) ;
- if (env->active)
-#if DB_VERSION_MAJOR == 2
- db_appexit(env->Env) ;
-#else
- (env->Env->close)(env->Env, 0) ;
-#endif
- if (env->ErrHandle)
- SvREFCNT_dec(env->ErrHandle) ;
- if (env->ErrPrefix)
- SvREFCNT_dec(env->ErrPrefix) ;
-#if DB_VERSION_MAJOR == 2
- Safefree(env->Env) ;
-#endif
- Safefree(env) ;
- hash_delete("BerkeleyDB::Term::Env", (IV)env) ;
- Trace(("End of BerkeleyDB::Env::DESTROY %d\n", RETVAL)) ;
-
-BerkeleyDB::TxnMgr::Raw
-_TxnMgr(env)
- BerkeleyDB::Env env
- INIT:
- ckActive_Environment(env->active) ;
- if (!env->txn_enabled)
- softCrash("Transaction Manager not enabled") ;
- CODE:
- ZMALLOC(RETVAL, BerkeleyDB_TxnMgr_type) ;
- RETVAL->env = env ;
- /* hash_store_iv("BerkeleyDB::Term::TxnMgr", (IV)txn, 1) ; */
- OUTPUT:
- RETVAL
-
-int
-set_data_dir(env, dir)
- BerkeleyDB::Env env
- char * dir
- INIT:
- ckActive_Database(env->active) ;
- CODE:
-#ifndef AT_LEAST_DB_3_1
- softCrash("$env->set_data_dir needs Berkeley DB 3.1 or better") ;
-#else
- RETVAL = env->Status = env->Env->set_data_dir(env->Env, dir);
-#endif
- OUTPUT:
- RETVAL
-
-int
-set_lg_dir(env, dir)
- BerkeleyDB::Env env
- char * dir
- INIT:
- ckActive_Database(env->active) ;
- CODE:
-#ifndef AT_LEAST_DB_3_1
- softCrash("$env->set_lg_dir needs Berkeley DB 3.1 or better") ;
-#else
- RETVAL = env->Status = env->Env->set_lg_dir(env->Env, dir);
-#endif
- OUTPUT:
- RETVAL
-
-int
-set_tmp_dir(env, dir)
- BerkeleyDB::Env env
- char * dir
- INIT:
- ckActive_Database(env->active) ;
- CODE:
-#ifndef AT_LEAST_DB_3_1
- softCrash("$env->set_tmp_dir needs Berkeley DB 3.1 or better") ;
-#else
- RETVAL = env->Status = env->Env->set_tmp_dir(env->Env, dir);
-#endif
- OUTPUT:
- RETVAL
-
-int
-set_mutexlocks(env, do_lock)
- BerkeleyDB::Env env
- int do_lock
- INIT:
- ckActive_Database(env->active) ;
- CODE:
-#ifndef AT_LEAST_DB_3
- softCrash("$env->set_setmutexlocks needs Berkeley DB 3.0 or better") ;
-#else
-#if defined(IS_DB_3_0) || defined(AT_LEAST_DB_3_2)
- RETVAL = env->Status = env->Env->set_mutexlocks(env->Env, do_lock);
-#else /* DB 3.1 */
- RETVAL = env->Status = db_env_set_mutexlocks(do_lock);
-#endif
-#endif
- OUTPUT:
- RETVAL
-
-MODULE = BerkeleyDB::Term PACKAGE = BerkeleyDB::Term
-
-void
-close_everything()
-
-#define safeCroak(string) softCrash(string)
-void
-safeCroak(string)
- char * string
-
-MODULE = BerkeleyDB::Hash PACKAGE = BerkeleyDB::Hash PREFIX = hash_
-
-BerkeleyDB::Hash::Raw
-_db_open_hash(self, ref)
- char * self
- SV * ref
- CODE:
- {
- HV * hash ;
- SV * sv ;
- DB_INFO info ;
- BerkeleyDB__Env dbenv = NULL;
- SV * ref_dbenv = NULL;
- const char * file = NULL ;
- const char * subname = NULL ;
- int flags = 0 ;
- int mode = 0 ;
- BerkeleyDB db ;
-
- Trace(("_db_open_hash start\n")) ;
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(file, "Filename", char *) ;
- SetValue_pv(subname, "Subname", char *) ;
- SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
- ref_dbenv = sv ;
- SetValue_iv(flags, "Flags") ;
- SetValue_iv(mode, "Mode") ;
-
- Zero(&info, 1, DB_INFO) ;
- SetValue_iv(info.db_cachesize, "Cachesize") ;
- SetValue_iv(info.db_lorder, "Lorder") ;
- SetValue_iv(info.db_pagesize, "Pagesize") ;
- SetValue_iv(info.h_ffactor, "Ffactor") ;
- SetValue_iv(info.h_nelem, "Nelem") ;
- SetValue_iv(info.flags, "Property") ;
- ZMALLOC(db, BerkeleyDB_type) ;
- if ((sv = readHash(hash, "Hash")) && sv != &PL_sv_undef) {
- info.h_hash = hash_cb ;
- db->hash = newSVsv(sv) ;
- }
- /* DB_DUPSORT was introduced in DB 2.5.9 */
- if ((sv = readHash(hash, "DupCompare")) && sv != &PL_sv_undef) {
-#ifdef DB_DUPSORT
- info.dup_compare = dup_compare ;
- db->dup_compare = newSVsv(sv) ;
- info.flags |= DB_DUP|DB_DUPSORT ;
-#else
- croak("DupCompare needs Berkeley DB 2.5.9 or later") ;
-#endif
- }
- RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_HASH, flags, mode, &info) ;
- Trace(("_db_open_hash end\n")) ;
- }
- OUTPUT:
- RETVAL
-
-
-HV *
-db_stat(db, flags=0)
- BerkeleyDB::Common db
- int flags
- HV * RETVAL = NULL ;
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- {
-#if DB_VERSION_MAJOR == 2
- softCrash("$db->db_stat for a Hash needs Berkeley DB 3.x or better") ;
-#else
- DB_HASH_STAT * stat ;
- db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
- if (db->Status == 0) {
- RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
- hv_store_iv(RETVAL, "hash_magic", stat->hash_magic) ;
- hv_store_iv(RETVAL, "hash_version", stat->hash_version);
- hv_store_iv(RETVAL, "hash_pagesize", stat->hash_pagesize);
-#ifdef AT_LEAST_DB_3_1
- hv_store_iv(RETVAL, "hash_nkeys", stat->hash_nkeys);
- hv_store_iv(RETVAL, "hash_ndata", stat->hash_ndata);
-#else
- hv_store_iv(RETVAL, "hash_nrecs", stat->hash_nrecs);
-#endif
- hv_store_iv(RETVAL, "hash_nelem", stat->hash_nelem);
- hv_store_iv(RETVAL, "hash_ffactor", stat->hash_ffactor);
- hv_store_iv(RETVAL, "hash_buckets", stat->hash_buckets);
- hv_store_iv(RETVAL, "hash_free", stat->hash_free);
- hv_store_iv(RETVAL, "hash_bfree", stat->hash_bfree);
- hv_store_iv(RETVAL, "hash_bigpages", stat->hash_bigpages);
- hv_store_iv(RETVAL, "hash_big_bfree", stat->hash_big_bfree);
- hv_store_iv(RETVAL, "hash_overflows", stat->hash_overflows);
- hv_store_iv(RETVAL, "hash_ovfl_free", stat->hash_ovfl_free);
- hv_store_iv(RETVAL, "hash_dup", stat->hash_dup);
- hv_store_iv(RETVAL, "hash_dup_free", stat->hash_dup_free);
-#if DB_VERSION_MAJOR >= 3
- hv_store_iv(RETVAL, "hash_metaflags", stat->hash_metaflags);
-#endif
- safefree(stat) ;
- }
-#endif
- }
- OUTPUT:
- RETVAL
-
-
-MODULE = BerkeleyDB::Unknown PACKAGE = BerkeleyDB::Unknown PREFIX = hash_
-
-void
-_db_open_unknown(ref)
- SV * ref
- PPCODE:
- {
- HV * hash ;
- SV * sv ;
- DB_INFO info ;
- BerkeleyDB__Env dbenv = NULL;
- SV * ref_dbenv = NULL;
- const char * file = NULL ;
- const char * subname = NULL ;
- int flags = 0 ;
- int mode = 0 ;
- BerkeleyDB db ;
- BerkeleyDB RETVAL ;
- static char * Names[] = {"", "Btree", "Hash", "Recno"} ;
-
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(file, "Filename", char *) ;
- SetValue_pv(subname, "Subname", char *) ;
- SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
- ref_dbenv = sv ;
- SetValue_iv(flags, "Flags") ;
- SetValue_iv(mode, "Mode") ;
-
- Zero(&info, 1, DB_INFO) ;
- SetValue_iv(info.db_cachesize, "Cachesize") ;
- SetValue_iv(info.db_lorder, "Lorder") ;
- SetValue_iv(info.db_pagesize, "Pagesize") ;
- SetValue_iv(info.h_ffactor, "Ffactor") ;
- SetValue_iv(info.h_nelem, "Nelem") ;
- SetValue_iv(info.flags, "Property") ;
- ZMALLOC(db, BerkeleyDB_type) ;
-
- RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_UNKNOWN, flags, mode, &info) ;
- XPUSHs(sv_2mortal(newSViv((IV)RETVAL)));
- if (RETVAL)
- XPUSHs(sv_2mortal(newSVpv(Names[RETVAL->type], 0))) ;
- else
- XPUSHs(sv_2mortal(newSViv((IV)NULL)));
- }
-
-
-
-MODULE = BerkeleyDB::Btree PACKAGE = BerkeleyDB::Btree PREFIX = btree_
-
-BerkeleyDB::Btree::Raw
-_db_open_btree(self, ref)
- char * self
- SV * ref
- CODE:
- {
- HV * hash ;
- SV * sv ;
- DB_INFO info ;
- BerkeleyDB__Env dbenv = NULL;
- SV * ref_dbenv = NULL;
- const char * file = NULL ;
- const char * subname = NULL ;
- int flags = 0 ;
- int mode = 0 ;
- BerkeleyDB db ;
-
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(file, "Filename", char*) ;
- SetValue_pv(subname, "Subname", char *) ;
- SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
- ref_dbenv = sv ;
- SetValue_iv(flags, "Flags") ;
- SetValue_iv(mode, "Mode") ;
-
- Zero(&info, 1, DB_INFO) ;
- SetValue_iv(info.db_cachesize, "Cachesize") ;
- SetValue_iv(info.db_lorder, "Lorder") ;
- SetValue_iv(info.db_pagesize, "Pagesize") ;
- SetValue_iv(info.bt_minkey, "Minkey") ;
- SetValue_iv(info.flags, "Property") ;
- ZMALLOC(db, BerkeleyDB_type) ;
- if ((sv = readHash(hash, "Compare")) && sv != &PL_sv_undef) {
- info.bt_compare = btree_compare ;
- db->compare = newSVsv(sv) ;
- }
- /* DB_DUPSORT was introduced in DB 2.5.9 */
- if ((sv = readHash(hash, "DupCompare")) && sv != &PL_sv_undef) {
-#ifdef DB_DUPSORT
- info.dup_compare = dup_compare ;
- db->dup_compare = newSVsv(sv) ;
- info.flags |= DB_DUP|DB_DUPSORT ;
-#else
- softCrash("DupCompare needs Berkeley DB 2.5.9 or later") ;
-#endif
- }
- if ((sv = readHash(hash, "Prefix")) && sv != &PL_sv_undef) {
- info.bt_prefix = btree_prefix ;
- db->prefix = newSVsv(sv) ;
- }
-
- RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_BTREE, flags, mode, &info) ;
- }
- OUTPUT:
- RETVAL
-
-
-HV *
-db_stat(db, flags=0)
- BerkeleyDB::Common db
- int flags
- HV * RETVAL = NULL ;
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- {
- DB_BTREE_STAT * stat ;
- db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
- if (db->Status == 0) {
- RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
- hv_store_iv(RETVAL, "bt_magic", stat->bt_magic);
- hv_store_iv(RETVAL, "bt_version", stat->bt_version);
-#if DB_VERSION_MAJOR > 2
- hv_store_iv(RETVAL, "bt_metaflags", stat->bt_metaflags) ;
- hv_store_iv(RETVAL, "bt_flags", stat->bt_metaflags) ;
-#else
- hv_store_iv(RETVAL, "bt_flags", stat->bt_flags) ;
-#endif
- hv_store_iv(RETVAL, "bt_maxkey", stat->bt_maxkey) ;
- hv_store_iv(RETVAL, "bt_minkey", stat->bt_minkey);
- hv_store_iv(RETVAL, "bt_re_len", stat->bt_re_len);
- hv_store_iv(RETVAL, "bt_re_pad", stat->bt_re_pad);
- hv_store_iv(RETVAL, "bt_pagesize", stat->bt_pagesize);
- hv_store_iv(RETVAL, "bt_levels", stat->bt_levels);
-#ifdef AT_LEAST_DB_3_1
- hv_store_iv(RETVAL, "bt_nkeys", stat->bt_nkeys);
- hv_store_iv(RETVAL, "bt_ndata", stat->bt_ndata);
-#else
- hv_store_iv(RETVAL, "bt_nrecs", stat->bt_nrecs);
-#endif
- hv_store_iv(RETVAL, "bt_int_pg", stat->bt_int_pg);
- hv_store_iv(RETVAL, "bt_leaf_pg", stat->bt_leaf_pg);
- hv_store_iv(RETVAL, "bt_dup_pg", stat->bt_dup_pg);
- hv_store_iv(RETVAL, "bt_over_pg", stat->bt_over_pg);
- hv_store_iv(RETVAL, "bt_free", stat->bt_free);
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
- hv_store_iv(RETVAL, "bt_freed", stat->bt_freed);
- hv_store_iv(RETVAL, "bt_pfxsaved", stat->bt_pfxsaved);
- hv_store_iv(RETVAL, "bt_split", stat->bt_split);
- hv_store_iv(RETVAL, "bt_rootsplit", stat->bt_rootsplit);
- hv_store_iv(RETVAL, "bt_fastsplit", stat->bt_fastsplit);
- hv_store_iv(RETVAL, "bt_added", stat->bt_added);
- hv_store_iv(RETVAL, "bt_deleted", stat->bt_deleted);
- hv_store_iv(RETVAL, "bt_get", stat->bt_get);
- hv_store_iv(RETVAL, "bt_cache_hit", stat->bt_cache_hit);
- hv_store_iv(RETVAL, "bt_cache_miss", stat->bt_cache_miss);
-#endif
- hv_store_iv(RETVAL, "bt_int_pgfree", stat->bt_int_pgfree);
- hv_store_iv(RETVAL, "bt_leaf_pgfree", stat->bt_leaf_pgfree);
- hv_store_iv(RETVAL, "bt_dup_pgfree", stat->bt_dup_pgfree);
- hv_store_iv(RETVAL, "bt_over_pgfree", stat->bt_over_pgfree);
- safefree(stat) ;
- }
- }
- OUTPUT:
- RETVAL
-
-
-MODULE = BerkeleyDB::Recno PACKAGE = BerkeleyDB::Recno PREFIX = recno_
-
-BerkeleyDB::Recno::Raw
-_db_open_recno(self, ref)
- char * self
- SV * ref
- CODE:
- {
- HV * hash ;
- SV * sv ;
- DB_INFO info ;
- BerkeleyDB__Env dbenv = NULL;
- SV * ref_dbenv = NULL;
- const char * file = NULL ;
- const char * subname = NULL ;
- int flags = 0 ;
- int mode = 0 ;
- BerkeleyDB db ;
-
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(file, "Fname", char*) ;
- SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
- ref_dbenv = sv ;
- SetValue_iv(flags, "Flags") ;
- SetValue_iv(mode, "Mode") ;
-
- Zero(&info, 1, DB_INFO) ;
- SetValue_iv(info.db_cachesize, "Cachesize") ;
- SetValue_iv(info.db_lorder, "Lorder") ;
- SetValue_iv(info.db_pagesize, "Pagesize") ;
- SetValue_iv(info.bt_minkey, "Minkey") ;
-
- SetValue_iv(info.flags, "Property") ;
- SetValue_pv(info.re_source, "Source", char*) ;
- if ((sv = readHash(hash, "Len")) && sv != &PL_sv_undef) {
- info.re_len = SvIV(sv) ; ;
- flagSet_DB2(info.flags, DB_FIXEDLEN) ;
- }
- if ((sv = readHash(hash, "Delim")) && sv != &PL_sv_undef) {
- info.re_delim = SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ;
- flagSet_DB2(info.flags, DB_DELIMITER) ;
- }
- if ((sv = readHash(hash, "Pad")) && sv != &PL_sv_undef) {
- info.re_pad = (u_int32_t)SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ;
- flagSet_DB2(info.flags, DB_PAD) ;
- }
- ZMALLOC(db, BerkeleyDB_type) ;
-#ifdef ALLOW_RECNO_OFFSET
- SetValue_iv(db->array_base, "ArrayBase") ;
- db->array_base = (db->array_base == 0 ? 1 : 0) ;
-#endif /* ALLOW_RECNO_OFFSET */
-
- RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_RECNO, flags, mode, &info) ;
- }
- OUTPUT:
- RETVAL
-
-
-MODULE = BerkeleyDB::Queue PACKAGE = BerkeleyDB::Queue PREFIX = recno_
-
-BerkeleyDB::Queue::Raw
-_db_open_queue(self, ref)
- char * self
- SV * ref
- CODE:
- {
-#ifndef AT_LEAST_DB_3
- softCrash("BerkeleyDB::Queue needs Berkeley DB 3.0.x or better");
-#else
- HV * hash ;
- SV * sv ;
- DB_INFO info ;
- BerkeleyDB__Env dbenv = NULL;
- SV * ref_dbenv = NULL;
- const char * file = NULL ;
- const char * subname = NULL ;
- int flags = 0 ;
- int mode = 0 ;
- BerkeleyDB db ;
-
- hash = (HV*) SvRV(ref) ;
- SetValue_pv(file, "Fname", char*) ;
- SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
- ref_dbenv = sv ;
- SetValue_iv(flags, "Flags") ;
- SetValue_iv(mode, "Mode") ;
-
- Zero(&info, 1, DB_INFO) ;
- SetValue_iv(info.db_cachesize, "Cachesize") ;
- SetValue_iv(info.db_lorder, "Lorder") ;
- SetValue_iv(info.db_pagesize, "Pagesize") ;
- SetValue_iv(info.bt_minkey, "Minkey") ;
- SetValue_iv(info.q_extentsize, "ExtentSize") ;
-
-
- SetValue_iv(info.flags, "Property") ;
- if ((sv = readHash(hash, "Len")) && sv != &PL_sv_undef) {
- info.re_len = SvIV(sv) ; ;
- flagSet_DB2(info.flags, DB_PAD) ;
- }
- if ((sv = readHash(hash, "Pad")) && sv != &PL_sv_undef) {
- info.re_pad = (u_int32_t)SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ;
- flagSet_DB2(info.flags, DB_PAD) ;
- }
- ZMALLOC(db, BerkeleyDB_type) ;
-#ifdef ALLOW_RECNO_OFFSET
- SetValue_iv(db->array_base, "ArrayBase") ;
- db->array_base = (db->array_base == 0 ? 1 : 0) ;
-#endif /* ALLOW_RECNO_OFFSET */
-
- RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_QUEUE, flags, mode, &info) ;
-#endif
- }
- OUTPUT:
- RETVAL
-
-HV *
-db_stat(db, flags=0)
- BerkeleyDB::Common db
- int flags
- HV * RETVAL = NULL ;
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- {
-#if DB_VERSION_MAJOR == 2
- softCrash("$db->db_stat for a Queue needs Berkeley DB 3.x or better") ;
-#else /* Berkeley DB 3, or better */
- DB_QUEUE_STAT * stat ;
- db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
- if (db->Status == 0) {
- RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
- hv_store_iv(RETVAL, "qs_magic", stat->qs_magic) ;
- hv_store_iv(RETVAL, "qs_version", stat->qs_version);
-#ifdef AT_LEAST_DB_3_1
- hv_store_iv(RETVAL, "qs_nkeys", stat->qs_nkeys);
- hv_store_iv(RETVAL, "qs_ndata", stat->qs_ndata);
-#else
- hv_store_iv(RETVAL, "qs_nrecs", stat->qs_nrecs);
-#endif
- hv_store_iv(RETVAL, "qs_pages", stat->qs_pages);
- hv_store_iv(RETVAL, "qs_pagesize", stat->qs_pagesize);
- hv_store_iv(RETVAL, "qs_pgfree", stat->qs_pgfree);
- hv_store_iv(RETVAL, "qs_re_len", stat->qs_re_len);
- hv_store_iv(RETVAL, "qs_re_pad", stat->qs_re_pad);
-#ifdef AT_LEAST_DB_3_2
-#else
- hv_store_iv(RETVAL, "qs_start", stat->qs_start);
-#endif
- hv_store_iv(RETVAL, "qs_first_recno", stat->qs_first_recno);
- hv_store_iv(RETVAL, "qs_cur_recno", stat->qs_cur_recno);
-#if DB_VERSION_MAJOR >= 3
- hv_store_iv(RETVAL, "qs_metaflags", stat->qs_metaflags);
-#endif
- safefree(stat) ;
- }
-#endif
- }
- OUTPUT:
- RETVAL
-
-
-MODULE = BerkeleyDB::Common PACKAGE = BerkeleyDB::Common PREFIX = dab_
-
-
-DualType
-db_close(db,flags=0)
- BerkeleyDB::Common db
- int flags
- INIT:
- ckActive_Database(db->active) ;
- CurrentDB = db ;
- CODE:
- Trace(("BerkeleyDB::Common::db_close %d\n", db));
-#ifdef STRICT_CLOSE
- if (db->txn)
- softCrash("attempted to close a database while a transaction was still open") ;
- if (db->open_cursors)
- softCrash("attempted to close a database with %d open cursor(s)",
- db->open_cursors) ;
-#endif /* STRICT_CLOSE */
- RETVAL = db->Status = ((db->dbp)->close)(db->dbp, flags) ;
- if (db->parent_env && db->parent_env->open_dbs)
- -- db->parent_env->open_dbs ;
- db->active = FALSE ;
- hash_delete("BerkeleyDB::Term::Db", (IV)db) ;
- -- db->open_cursors ;
- Trace(("end of BerkeleyDB::Common::db_close\n"));
- OUTPUT:
- RETVAL
-
-void
-dab__DESTROY(db)
- BerkeleyDB::Common db
- CODE:
- CurrentDB = db ;
- Trace(("In BerkeleyDB::Common::_DESTROY db %d dirty=%d\n", db, PL_dirty)) ;
- destroyDB(db) ;
- Trace(("End of BerkeleyDB::Common::DESTROY \n")) ;
-
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
-#define db_cursor(db, txn, cur,flags) ((db->dbp)->cursor)(db->dbp, txn, cur)
-#else
-#define db_cursor(db, txn, cur,flags) ((db->dbp)->cursor)(db->dbp, txn, cur,flags)
-#endif
-BerkeleyDB::Cursor::Raw
-_db_cursor(db, flags=0)
- BerkeleyDB::Common db
- u_int32_t flags
- BerkeleyDB::Cursor RETVAL = NULL ;
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- {
- DBC * cursor ;
- CurrentDB = db ;
- if ((db->Status = db_cursor(db, db->txn, &cursor, flags)) == 0){
- ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
- db->open_cursors ++ ;
- RETVAL->parent_db = db ;
- RETVAL->cursor = cursor ;
- RETVAL->dbp = db->dbp ;
- RETVAL->type = db->type ;
- RETVAL->recno_or_queue = db->recno_or_queue ;
- RETVAL->filename = my_strdup(db->filename) ;
- RETVAL->compare = db->compare ;
- RETVAL->dup_compare = db->dup_compare ;
- RETVAL->prefix = db->prefix ;
- RETVAL->hash = db->hash ;
- RETVAL->partial = db->partial ;
- RETVAL->doff = db->doff ;
- RETVAL->dlen = db->dlen ;
- RETVAL->active = TRUE ;
-#ifdef ALLOW_RECNO_OFFSET
- RETVAL->array_base = db->array_base ;
-#endif /* ALLOW_RECNO_OFFSET */
-#ifdef DBM_FILTERING
- RETVAL->filtering = FALSE ;
- RETVAL->filter_fetch_key = db->filter_fetch_key ;
- RETVAL->filter_store_key = db->filter_store_key ;
- RETVAL->filter_fetch_value = db->filter_fetch_value ;
- RETVAL->filter_store_value = db->filter_store_value ;
-#endif
- /* RETVAL->info ; */
- hash_store_iv("BerkeleyDB::Term::Cursor", (IV)RETVAL, 1) ;
- }
- }
- OUTPUT:
- RETVAL
-
-BerkeleyDB::Cursor::Raw
-_db_join(db, cursors, flags=0)
- BerkeleyDB::Common db
- AV * cursors
- u_int32_t flags
- BerkeleyDB::Cursor RETVAL = NULL ;
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- {
-#if DB_VERSION_MAJOR == 2 && (DB_VERSION_MINOR < 5 || (DB_VERSION_MINOR == 5 && DB_VERSION_PATCH < 2))
- softCrash("join needs Berkeley DB 2.5.2 or later") ;
-#else /* Berkeley DB >= 2.5.2 */
- DBC * join_cursor ;
- DBC ** cursor_list ;
- I32 count = av_len(cursors) + 1 ;
- int i ;
- CurrentDB = db ;
- if (count < 1 )
- softCrash("db_join: No cursors in parameter list") ;
- cursor_list = (DBC **)safemalloc(sizeof(DBC*) * (count + 1));
- for (i = 0 ; i < count ; ++i) {
- SV * obj = (SV*) * av_fetch(cursors, i, FALSE) ;
- BerkeleyDB__Cursor cur = (BerkeleyDB__Cursor) getInnerObject(obj) ;
- cursor_list[i] = cur->cursor ;
- }
- cursor_list[i] = NULL ;
-#if DB_VERSION_MAJOR == 2
- if ((db->Status = ((db->dbp)->join)(db->dbp, cursor_list, flags, &join_cursor)) == 0){
-#else
- if ((db->Status = ((db->dbp)->join)(db->dbp, cursor_list, &join_cursor, flags)) == 0){
-#endif
- ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
- db->open_cursors ++ ;
- RETVAL->parent_db = db ;
- RETVAL->cursor = join_cursor ;
- RETVAL->dbp = db->dbp ;
- RETVAL->type = db->type ;
- RETVAL->filename = my_strdup(db->filename) ;
- RETVAL->compare = db->compare ;
- RETVAL->dup_compare = db->dup_compare ;
- RETVAL->prefix = db->prefix ;
- RETVAL->hash = db->hash ;
- RETVAL->partial = db->partial ;
- RETVAL->doff = db->doff ;
- RETVAL->dlen = db->dlen ;
- RETVAL->active = TRUE ;
-#ifdef ALLOW_RECNO_OFFSET
- RETVAL->array_base = db->array_base ;
-#endif /* ALLOW_RECNO_OFFSET */
-#ifdef DBM_FILTERING
- RETVAL->filtering = FALSE ;
- RETVAL->filter_fetch_key = db->filter_fetch_key ;
- RETVAL->filter_store_key = db->filter_store_key ;
- RETVAL->filter_fetch_value = db->filter_fetch_value ;
- RETVAL->filter_store_value = db->filter_store_value ;
-#endif
- /* RETVAL->info ; */
- hash_store_iv("BerkeleyDB::Term::Cursor", (IV)RETVAL, 1) ;
- }
- safefree(cursor_list) ;
-#endif /* Berkeley DB >= 2.5.2 */
- }
- OUTPUT:
- RETVAL
-
-int
-ArrayOffset(db)
- BerkeleyDB::Common db
- INIT:
- ckActive_Database(db->active) ;
- CODE:
-#ifdef ALLOW_RECNO_OFFSET
- RETVAL = db->array_base ? 0 : 1 ;
-#else
- RETVAL = 0 ;
-#endif /* ALLOW_RECNO_OFFSET */
- OUTPUT:
- RETVAL
-
-int
-type(db)
- BerkeleyDB::Common db
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- RETVAL = db->type ;
- OUTPUT:
- RETVAL
-
-int
-byteswapped(db)
- BerkeleyDB::Common db
- INIT:
- ckActive_Database(db->active) ;
- CODE:
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
- softCrash("byteswapped needs Berkeley DB 2.5 or later") ;
-#else
-#if DB_VERSION_MAJOR == 2
- RETVAL = db->dbp->byteswapped ;
-#else
- RETVAL = db->dbp->get_byteswapped(db->dbp) ;
-#endif
-#endif
- OUTPUT:
- RETVAL
-
-DualType
-status(db)
- BerkeleyDB::Common db
- CODE:
- RETVAL = db->Status ;
- OUTPUT:
- RETVAL
-
-#ifdef DBM_FILTERING
-
-#define setFilter(ftype) \
- { \
- if (db->ftype) \
- RETVAL = sv_mortalcopy(db->ftype) ; \
- ST(0) = RETVAL ; \
- if (db->ftype && (code == &PL_sv_undef)) { \
- SvREFCNT_dec(db->ftype) ; \
- db->ftype = NULL ; \
- } \
- else if (code) { \
- if (db->ftype) \
- sv_setsv(db->ftype, code) ; \
- else \
- db->ftype = newSVsv(code) ; \
- } \
- }
-
-
-SV *
-filter_fetch_key(db, code)
- BerkeleyDB::Common db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_fetch_key) ;
-
-SV *
-filter_store_key(db, code)
- BerkeleyDB::Common db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_store_key) ;
-
-SV *
-filter_fetch_value(db, code)
- BerkeleyDB::Common db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_fetch_value) ;
-
-SV *
-filter_store_value(db, code)
- BerkeleyDB::Common db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_store_value) ;
-
-#endif /* DBM_FILTERING */
-
-void
-partial_set(db, offset, length)
- BerkeleyDB::Common db
- u_int32_t offset
- u_int32_t length
- INIT:
- ckActive_Database(db->active) ;
- PPCODE:
- if (GIMME == G_ARRAY) {
- XPUSHs(sv_2mortal(newSViv(db->partial == DB_DBT_PARTIAL))) ;
- XPUSHs(sv_2mortal(newSViv(db->doff))) ;
- XPUSHs(sv_2mortal(newSViv(db->dlen))) ;
- }
- db->partial = DB_DBT_PARTIAL ;
- db->doff = offset ;
- db->dlen = length ;
-
-
-void
-partial_clear(db)
- BerkeleyDB::Common db
- INIT:
- ckActive_Database(db->active) ;
- PPCODE:
- if (GIMME == G_ARRAY) {
- XPUSHs(sv_2mortal(newSViv(db->partial == DB_DBT_PARTIAL))) ;
- XPUSHs(sv_2mortal(newSViv(db->doff))) ;
- XPUSHs(sv_2mortal(newSViv(db->dlen))) ;
- }
- db->partial =
- db->doff =
- db->dlen = 0 ;
-
-
-#define db_del(db, key, flags) \
- (db->Status = ((db->dbp)->del)(db->dbp, db->txn, &key, flags))
-DualType
-db_del(db, key, flags=0)
- BerkeleyDB::Common db
- DBTKEY key
- u_int flags
- INIT:
- ckActive_Database(db->active) ;
- CurrentDB = db ;
-
-
-#define db_get(db, key, data, flags) \
- (db->Status = ((db->dbp)->get)(db->dbp, db->txn, &key, &data, flags))
-DualType
-db_get(db, key, data, flags=0)
- BerkeleyDB::Common db
- u_int flags
- DBTKEY_B key
- DBT_OPT data
- INIT:
- ckActive_Database(db->active) ;
- CurrentDB = db ;
- SetPartial(data,db) ;
- OUTPUT:
- key if (flagSet(DB_SET_RECNO)) OutputValue(ST(1), key) ;
- data
-
-#define db_put(db,key,data,flag) \
- (db->Status = (db->dbp->put)(db->dbp,db->txn,&key,&data,flag))
-DualType
-db_put(db, key, data, flags=0)
- BerkeleyDB::Common db
- DBTKEY key
- DBT data
- u_int flags
- INIT:
- ckActive_Database(db->active) ;
- CurrentDB = db ;
- /* SetPartial(data,db) ; */
- OUTPUT:
- key if (flagSet(DB_APPEND)) OutputKey(ST(1), key) ;
-
-#define db_key_range(db, key, range, flags) \
- (db->Status = ((db->dbp)->key_range)(db->dbp, db->txn, &key, &range, flags))
-DualType
-db_key_range(db, key, less, equal, greater, flags=0)
- BerkeleyDB::Common db
- DBTKEY_B key
- double less = NO_INIT
- double equal = NO_INIT
- double greater = NO_INIT
- u_int32_t flags
- CODE:
- {
-#ifndef AT_LEAST_DB_3_1
- softCrash("key_range needs Berkeley DB 3.1.x or later") ;
-#else
- DB_KEY_RANGE range ;
- range.less = range.equal = range.greater = 0.0 ;
- ckActive_Database(db->active) ;
- CurrentDB = db ;
- RETVAL = db_key_range(db, key, range, flags);
- if (RETVAL == 0) {
- less = range.less ;
- equal = range.equal;
- greater = range.greater;
- }
-#endif
- }
- OUTPUT:
- RETVAL
- less
- equal
- greater
-
-
-#define db_fd(d, x) (db->Status = (db->dbp->fd)(db->dbp, &x))
-DualType
-db_fd(db)
- BerkeleyDB::Common db
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- CurrentDB = db ;
- db_fd(db, RETVAL) ;
- OUTPUT:
- RETVAL
-
-
-#define db_sync(db, fl) (db->Status = (db->dbp->sync)(db->dbp, fl))
-DualType
-db_sync(db, flags=0)
- BerkeleyDB::Common db
- u_int flags
- INIT:
- ckActive_Database(db->active) ;
- CurrentDB = db ;
-
-void
-_Txn(db, txn=NULL)
- BerkeleyDB::Common db
- BerkeleyDB::Txn txn
- INIT:
- ckActive_Database(db->active) ;
- CODE:
- if (txn) {
- Trace(("_Txn(%d in %d) active [%d]\n", txn->txn, txn, txn->active));
- ckActive_Transaction(txn->active) ;
- db->txn = txn->txn ;
- }
- else {
- Trace(("_Txn(undef) \n"));
- db->txn = NULL ;
- }
-
-
-
-
-MODULE = BerkeleyDB::Cursor PACKAGE = BerkeleyDB::Cursor PREFIX = cu_
-
-BerkeleyDB::Cursor::Raw
-_c_dup(db, flags=0)
- BerkeleyDB::Cursor db
- u_int32_t flags
- BerkeleyDB::Cursor RETVAL = NULL ;
- INIT:
- CurrentDB = db->parent_db ;
- ckActive_Database(db->active) ;
- CODE:
- {
-#ifndef AT_LEAST_DB_3
- softCrash("c_dup needs at least Berkeley DB 3.0.x");
-#else
- DBC * newcursor ;
- db->Status = ((db->cursor)->c_dup)(db->cursor, &newcursor, flags) ;
- if (db->Status == 0){
- ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
- db->parent_db->open_cursors ++ ;
- RETVAL->parent_db = db->parent_db ;
- RETVAL->cursor = newcursor ;
- RETVAL->dbp = db->dbp ;
- RETVAL->type = db->type ;
- RETVAL->recno_or_queue = db->recno_or_queue ;
- RETVAL->filename = my_strdup(db->filename) ;
- RETVAL->compare = db->compare ;
- RETVAL->dup_compare = db->dup_compare ;
- RETVAL->prefix = db->prefix ;
- RETVAL->hash = db->hash ;
- RETVAL->partial = db->partial ;
- RETVAL->doff = db->doff ;
- RETVAL->dlen = db->dlen ;
- RETVAL->active = TRUE ;
-#ifdef ALLOW_RECNO_OFFSET
- RETVAL->array_base = db->array_base ;
-#endif /* ALLOW_RECNO_OFFSET */
-#ifdef DBM_FILTERING
- RETVAL->filtering = FALSE ;
- RETVAL->filter_fetch_key = db->filter_fetch_key ;
- RETVAL->filter_store_key = db->filter_store_key ;
- RETVAL->filter_fetch_value = db->filter_fetch_value ;
- RETVAL->filter_store_value = db->filter_store_value ;
-#endif /* DBM_FILTERING */
- /* RETVAL->info ; */
- hash_store_iv("BerkeleyDB::Term::Cursor", (IV)RETVAL, 1) ;
- }
-#endif
- }
- OUTPUT:
- RETVAL
-
-DualType
-_c_close(db)
- BerkeleyDB::Cursor db
- INIT:
- CurrentDB = db->parent_db ;
- ckActive_Cursor(db->active) ;
- hash_delete("BerkeleyDB::Term::Cursor", (IV)db) ;
- CODE:
- RETVAL = db->Status =
- ((db->cursor)->c_close)(db->cursor) ;
- db->active = FALSE ;
- if (db->parent_db->open_cursors)
- -- db->parent_db->open_cursors ;
- OUTPUT:
- RETVAL
-
-void
-_DESTROY(db)
- BerkeleyDB::Cursor db
- CODE:
- CurrentDB = db->parent_db ;
- Trace(("In BerkeleyDB::Cursor::_DESTROY db %d dirty=%d active=%d\n", db, PL_dirty, db->active));
- hash_delete("BerkeleyDB::Term::Cursor", (IV)db) ;
- if (db->active)
- ((db->cursor)->c_close)(db->cursor) ;
- if (db->parent_db->open_cursors)
- -- db->parent_db->open_cursors ;
- Safefree(db->filename) ;
- Safefree(db) ;
- Trace(("End of BerkeleyDB::Cursor::_DESTROY\n")) ;
-
-DualType
-status(db)
- BerkeleyDB::Cursor db
- CODE:
- RETVAL = db->Status ;
- OUTPUT:
- RETVAL
-
-
-#define cu_c_del(c,f) (c->Status = ((c->cursor)->c_del)(c->cursor,f))
-DualType
-cu_c_del(db, flags=0)
- BerkeleyDB::Cursor db
- int flags
- INIT:
- CurrentDB = db->parent_db ;
- ckActive_Cursor(db->active) ;
- OUTPUT:
- RETVAL
-
-
-#define cu_c_get(c,k,d,f) (c->Status = (c->cursor->c_get)(c->cursor,&k,&d,f))
-DualType
-cu_c_get(db, key, data, flags=0)
- BerkeleyDB::Cursor db
- int flags
- DBTKEY_B key
- DBT_B data
- INIT:
- Trace(("c_get db [%d] flags [%d]\n", db, flags)) ;
- CurrentDB = db->parent_db ;
- ckActive_Cursor(db->active) ;
- SetPartial(data,db) ;
- Trace(("c_get end\n")) ;
- OUTPUT:
- RETVAL
- key
- data if (! flagSet(DB_JOIN_ITEM)) OutputValue_B(ST(2), data) ;
-
-
-#define cu_c_put(c,k,d,f) (c->Status = (c->cursor->c_put)(c->cursor,&k,&d,f))
-DualType
-cu_c_put(db, key, data, flags=0)
- BerkeleyDB::Cursor db
- DBTKEY key
- DBT data
- int flags
- INIT:
- CurrentDB = db->parent_db ;
- ckActive_Cursor(db->active) ;
- /* SetPartial(data,db) ; */
- OUTPUT:
- RETVAL
-
-#define cu_c_count(c,p,f) (c->Status = (c->cursor->c_count)(c->cursor,&p,f))
-DualType
-cu_c_count(db, count, flags=0)
- BerkeleyDB::Cursor db
- u_int32_t count = NO_INIT
- int flags
- CODE:
-#ifndef AT_LEAST_DB_3_1
- softCrash("c_count needs at least Berkeley DB 3.1.x");
-#else
- Trace(("c_get count [%d] flags [%d]\n", db, flags)) ;
- CurrentDB = db->parent_db ;
- ckActive_Cursor(db->active) ;
- RETVAL = cu_c_count(db, count, flags) ;
- Trace((" c_count got %d duplicates\n", count)) ;
-#endif
- OUTPUT:
- RETVAL
- count
-
-MODULE = BerkeleyDB::TxnMgr PACKAGE = BerkeleyDB::TxnMgr PREFIX = xx_
-
-BerkeleyDB::Txn::Raw
-_txn_begin(txnmgr, pid=NULL, flags=0)
- BerkeleyDB::TxnMgr txnmgr
- BerkeleyDB::Txn pid
- u_int32_t flags
- CODE:
- {
- DB_TXN *txn ;
- DB_TXN *p_id = NULL ;
-#if DB_VERSION_MAJOR == 2
- if (txnmgr->env->Env->tx_info == NULL)
- softCrash("Transaction Manager not enabled") ;
-#endif
- if (pid)
- p_id = pid->txn ;
- txnmgr->env->TxnMgrStatus =
-#if DB_VERSION_MAJOR == 2
- txn_begin(txnmgr->env->Env->tx_info, p_id, &txn) ;
-#else
- txn_begin(txnmgr->env->Env, p_id, &txn, flags) ;
-#endif
- if (txnmgr->env->TxnMgrStatus == 0) {
- ZMALLOC(RETVAL, BerkeleyDB_Txn_type) ;
- RETVAL->txn = txn ;
- RETVAL->active = TRUE ;
- Trace(("_txn_begin created txn [%d] in [%d]\n", txn, RETVAL));
- hash_store_iv("BerkeleyDB::Term::Txn", (IV)RETVAL, 1) ;
- }
- else
- RETVAL = NULL ;
- }
- OUTPUT:
- RETVAL
-
-
-DualType
-status(mgr)
- BerkeleyDB::TxnMgr mgr
- CODE:
- RETVAL = mgr->env->TxnMgrStatus ;
- OUTPUT:
- RETVAL
-
-
-void
-_DESTROY(mgr)
- BerkeleyDB::TxnMgr mgr
- CODE:
- Trace(("In BerkeleyDB::TxnMgr::DESTROY dirty=%d\n", PL_dirty)) ;
- Safefree(mgr) ;
- Trace(("End of BerkeleyDB::TxnMgr::DESTROY\n")) ;
-
-DualType
-txn_close(txnp)
- BerkeleyDB::TxnMgr txnp
- NOT_IMPLEMENTED_YET
-
-
-#if DB_VERSION_MAJOR == 2
-# define xx_txn_checkpoint(t,k,m) txn_checkpoint(t->env->Env->tx_info, k, m)
-#else
-# ifdef AT_LEAST_DB_3_1
-# define xx_txn_checkpoint(t,k,m) txn_checkpoint(t->env->Env, k, m, 0)
-# else
-# define xx_txn_checkpoint(t,k,m) txn_checkpoint(t->env->Env, k, m)
-# endif
-#endif
-DualType
-xx_txn_checkpoint(txnp, kbyte, min)
- BerkeleyDB::TxnMgr txnp
- long kbyte
- long min
-
-HV *
-txn_stat(txnp)
- BerkeleyDB::TxnMgr txnp
- HV * RETVAL = NULL ;
- CODE:
- {
- DB_TXN_STAT * stat ;
-#if DB_VERSION_MAJOR == 2
- if(txn_stat(txnp->env->Env->tx_info, &stat, safemalloc) == 0) {
-#else
- if(txn_stat(txnp->env->Env, &stat, safemalloc) == 0) {
-#endif
- RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
- hv_store_iv(RETVAL, "st_time_ckp", stat->st_time_ckp) ;
- hv_store_iv(RETVAL, "st_last_txnid", stat->st_last_txnid) ;
- hv_store_iv(RETVAL, "st_maxtxns", stat->st_maxtxns) ;
- hv_store_iv(RETVAL, "st_naborts", stat->st_naborts) ;
- hv_store_iv(RETVAL, "st_nbegins", stat->st_nbegins) ;
- hv_store_iv(RETVAL, "st_ncommits", stat->st_ncommits) ;
- hv_store_iv(RETVAL, "st_nactive", stat->st_nactive) ;
-#if DB_VERSION_MAJOR > 2
- hv_store_iv(RETVAL, "st_maxnactive", stat->st_maxnactive) ;
- hv_store_iv(RETVAL, "st_regsize", stat->st_regsize) ;
- hv_store_iv(RETVAL, "st_region_wait", stat->st_region_wait) ;
- hv_store_iv(RETVAL, "st_region_nowait", stat->st_region_nowait) ;
-#endif
- safefree(stat) ;
- }
- }
- OUTPUT:
- RETVAL
-
-
-BerkeleyDB::TxnMgr
-txn_open(dir, flags, mode, dbenv)
- const char * dir
- int flags
- int mode
- BerkeleyDB::Env dbenv
- NOT_IMPLEMENTED_YET
-
-
-MODULE = BerkeleyDB::Txn PACKAGE = BerkeleyDB::Txn PREFIX = xx_
-
-DualType
-status(tid)
- BerkeleyDB::Txn tid
- CODE:
- RETVAL = tid->Status ;
- OUTPUT:
- RETVAL
-
-int
-_DESTROY(tid)
- BerkeleyDB::Txn tid
- CODE:
- Trace(("In BerkeleyDB::Txn::_DESTROY txn [%d] active [%d] dirty=%d\n", tid->txn, tid->active, PL_dirty)) ;
- if (tid->active)
- txn_abort(tid->txn) ;
- RETVAL = (int)tid ;
- hash_delete("BerkeleyDB::Term::Txn", (IV)tid) ;
- Safefree(tid) ;
- Trace(("End of BerkeleyDB::Txn::DESTROY\n")) ;
- OUTPUT:
- RETVAL
-
-#define xx_txn_unlink(d,f,e) txn_unlink(d,f,&(e->Env))
-DualType
-xx_txn_unlink(dir, force, dbenv)
- const char * dir
- int force
- BerkeleyDB::Env dbenv
- NOT_IMPLEMENTED_YET
-
-#define xx_txn_prepare(t) (t->Status = txn_prepare(t->txn))
-DualType
-xx_txn_prepare(tid)
- BerkeleyDB::Txn tid
- INIT:
- ckActive_Transaction(tid->active) ;
-
-#if DB_VERSION_MAJOR == 2
-# define _txn_commit(t,flags) (t->Status = txn_commit(t->txn))
-#else
-# define _txn_commit(t, flags) (t->Status = txn_commit(t->txn, flags))
-#endif
-DualType
-_txn_commit(tid, flags=0)
- BerkeleyDB::Txn tid
- u_int32_t flags
- INIT:
- ckActive_Transaction(tid->active) ;
- hash_delete("BerkeleyDB::Term::Txn", (IV)tid) ;
- tid->active = FALSE ;
-
-#define _txn_abort(t) (t->Status = txn_abort(t->txn))
-DualType
-_txn_abort(tid)
- BerkeleyDB::Txn tid
- INIT:
- ckActive_Transaction(tid->active) ;
- hash_delete("BerkeleyDB::Term::Txn", (IV)tid) ;
- tid->active = FALSE ;
-
-#define xx_txn_id(t) txn_id(t->txn)
-u_int32_t
-xx_txn_id(tid)
- BerkeleyDB::Txn tid
-
-MODULE = BerkeleyDB::_tiedHash PACKAGE = BerkeleyDB::_tiedHash
-
-int
-FIRSTKEY(db)
- BerkeleyDB::Common db
- CODE:
- {
- DBTKEY key ;
- DBT value ;
- DBC * cursor ;
-
- /*
- TODO!
- set partial value to 0 - to eliminate the retrieval of
- the value need to store any existing partial settings &
- restore at the end.
-
- */
- CurrentDB = db ;
- DBT_clear(key) ;
- DBT_clear(value) ;
- /* If necessary create a cursor for FIRSTKEY/NEXTKEY use */
- if (!db->cursor &&
- (db->Status = db_cursor(db, db->txn, &cursor, 0)) == 0 )
- db->cursor = cursor ;
-
- if (db->cursor)
- RETVAL = (db->Status) =
- ((db->cursor)->c_get)(db->cursor, &key, &value, DB_FIRST);
- else
- RETVAL = db->Status ;
- /* check for end of cursor */
- if (RETVAL == DB_NOTFOUND) {
- ((db->cursor)->c_close)(db->cursor) ;
- db->cursor = NULL ;
- }
- ST(0) = sv_newmortal();
- OutputKey(ST(0), key)
- }
-
-
-
-int
-NEXTKEY(db, key)
- BerkeleyDB::Common db
- DBTKEY key
- CODE:
- {
- DBT value ;
-
- CurrentDB = db ;
- DBT_clear(value) ;
- key.flags = 0 ;
- RETVAL = (db->Status) =
- ((db->cursor)->c_get)(db->cursor, &key, &value, DB_NEXT);
-
- /* check for end of cursor */
- if (RETVAL == DB_NOTFOUND) {
- ((db->cursor)->c_close)(db->cursor) ;
- db->cursor = NULL ;
- }
- ST(0) = sv_newmortal();
- OutputKey(ST(0), key)
- }
-
-MODULE = BerkeleyDB::_tiedArray PACKAGE = BerkeleyDB::_tiedArray
-
-I32
-FETCHSIZE(db)
- BerkeleyDB::Common db
- CODE:
- CurrentDB = db ;
- RETVAL = GetArrayLength(db) ;
- OUTPUT:
- RETVAL
-
-
-MODULE = BerkeleyDB PACKAGE = BerkeleyDB
-
-BOOT:
- {
- SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;
- SV * version_sv = perl_get_sv("BerkeleyDB::db_version", GV_ADD|GV_ADDMULTI) ;
- SV * ver_sv = perl_get_sv("BerkeleyDB::db_ver", GV_ADD|GV_ADDMULTI) ;
- int Major, Minor, Patch ;
- (void)db_version(&Major, &Minor, &Patch) ;
- /* Check that the versions of db.h and libdb.a are the same */
- if (Major != DB_VERSION_MAJOR || Minor != DB_VERSION_MINOR
- || Patch != DB_VERSION_PATCH)
- croak("\nBerkeleyDB needs compatible versions of libdb & db.h\n\tyou have db.h version %d.%d.%d and libdb version %d.%d.%d\n",
- DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
- Major, Minor, Patch) ;
-
- if (Major < 2 || (Major == 2 && Minor < 6))
- {
- croak("BerkeleyDB needs Berkeley DB 2.6 or greater. This is %d.%d.%d\n",
- Major, Minor, Patch) ;
- }
- sv_setpvf(version_sv, "%d.%d", Major, Minor) ;
- sv_setpvf(ver_sv, "%d.%03d%03d", Major, Minor, Patch) ;
- sv_setpv(sv_err, "");
-
- DBT_clear(empty) ;
- empty.data = &zero ;
- empty.size = sizeof(db_recno_t) ;
- empty.flags = 0 ;
-
- }
-
diff --git a/bdb/perl.BerkeleyDB/Changes b/bdb/perl.BerkeleyDB/Changes
deleted file mode 100644
index dcaccd4d0c7..00000000000
--- a/bdb/perl.BerkeleyDB/Changes
+++ /dev/null
@@ -1,112 +0,0 @@
-Revision history for Perl extension BerkeleyDB.
-
-0.01 23 October 1997
- * first alpha release as BerkDB.
-
-0.02 30 October 1997
- * renamed module to BerkeleyDB
- * fixed a few bugs & added more tests
-
-0.03 5 May 1998
- * fixed db_get with DB_SET_RECNO
- * fixed c_get with DB_SET_RECNO and DB_GET_RECNO
- * implemented BerkeleyDB::Unknown
- * implemented BerkeleyDB::Recno, including push, pop etc
- modified the txn support.
-
-0.04 19 May 1998
- * Define DEFSV & SAVE_DEFSV if not already defined. This allows
- the module to be built with Perl 5.004_04.
-
-0.05 9 November 1998
- * Added a note to README about how to build Berkeley DB 2.x
- when using HP-UX.
- * Minor modifications to get the module to build with DB 2.5.x
-
-0.06 19 December 1998
- * Minor modifications to get the module to build with DB 2.6.x
- * Added support for DB 2.6.x's Concurrent Access Method, DB_INIT_CDB.
-
-0.07 21st September 1999
- * Numerous small bug fixes.
- * Added support for sorting duplicate values DB_DUPSORT.
- * Added support for DB_GET_BOTH & DB_NEXT_DUP.
- * Added get_dup (from DB_File).
- * beefed up the documentation.
- * Forgot to add the DB_INIT_CDB in BerkeleyDB.pm in previous release.
- * Merged the DBM Filter code from DB_File into BerkeleyDB.
- * Fixed a nasty bug where a closed transaction was still used with
- with dp_put, db_get etc.
- * Added logic to gracefully close everything whenever a fatal error
- happens. Previously the plug was just pulled.
- * It is now a fatal error to explicitly close an environment if there
- is still an open database; a database when there are open cursors or
- an open transaction; and a cursor if there is an open transaction.
- Using object destruction doesn't have this issue, as object
- references will ensure everything gets closed in the correct order.
- * The BOOT code now checks that the version of db.h & libdb are the
- same - this seems to be a common problem on Linux.
- * MLDBM support added.
- * Support for the new join cursor added.
- * Builds with Berkeley DB 3.x
- * Updated dbinfo for Berkeley DB 3.x file formats.
- * Deprecated the TxnMgr class. As with Berkeley DB version 3,
- txn_begin etc are now accessed via the environment object.
-
-0.08 28nd November 1999
- * More documentation updates
- * Changed reference to files in /tmp in examples.t
- * Fixed a typo in softCrash that caused problems when building
- with a thread-enabled Perl.
- * BerkeleyDB::Error wasn't initialised properly.
- * ANSI-ified all the static C functions in BerkeleyDB.xs
- * Added support for the following DB 3.x features:
- + The Queue database type
- + db_remove
- + subdatabases
- + db_stat for Hash & Queue
-
-0.09 29th November 1999
- * the queue.t & subdb.t test harnesses were outputting a few
- spurious warnings. This has been fixed.
-
-0.10 8th December 1999
- * The DESTROY method was missing for BerkeleyDB::Env. This resulted in
- a memory leak. Fixed.
- * If opening an environment or database failed, there was a small
- memory leak. This has been fixed.
- * A thread-enabled Perl it could core when a database was closed.
- Problem traced to the strdup function.
-
-0.11 4th June 2000
- * When built with Berkeley Db 3.x there can be a clash with the close
- macro.
- * Typo in the definition of DB_WRITECURSOR
- * The flags parameter wasn't getting sent to db_cursor
- * Plugged small memory leak in db_cursor (DESTROY wasn't freeing
- memory)
- * Can be built with Berkeley DB 3.1
-
-
-0.12 2nd August 2000
- * Serious bug with get fixed. Spotted by Sleepycat.
- * Added hints file for Solaris & Irix (courtesy of Albert Chin-A-Young)
-
-0.13 15th January 2001
- * Added support to allow this module to build with Berkeley DB 3.2
- * Updated dbinfo to support Berkeley DB 3.1 & 3.2 file format
- changes.
- * Documented the Solaris 2.7 core dump problem in README.
- * Tidied up the test harness to fix a problem on Solaris where the
- "fred" directory wasn't being deleted when it should have been.
- * two calls to "open" clashed with a win32 macro.
- * size argument for hash_cb is different for Berkeley DB 3.x
- * Documented the issue of building on Linux.
- * Added -Server, -CacheSize & -LockDetect options
- [original patch supplied by Graham Barr]
- * Added support for set_mutexlocks, c_count, set_q_extentsize,
- key_range, c_dup
- * Dropped the "attempted to close a Cursor with an open transaction"
- error in c_close. The correct behaviour is that the cursor
- should be closed before committing/aborting the transaction.
-
diff --git a/bdb/perl.BerkeleyDB/MANIFEST b/bdb/perl.BerkeleyDB/MANIFEST
deleted file mode 100644
index 3b8a820d56e..00000000000
--- a/bdb/perl.BerkeleyDB/MANIFEST
+++ /dev/null
@@ -1,49 +0,0 @@
-BerkeleyDB.pm
-BerkeleyDB.pod
-BerkeleyDB.pod.P
-BerkeleyDB.xs
-BerkeleyDB/Btree.pm
-BerkeleyDB/Hash.pm
-Changes
-config.in
-dbinfo
-hints/solaris.pl
-hints/irix_6_5.pl
-Makefile.PL
-MANIFEST
-mkconsts
-mkpod
-README
-t/btree.t
-t/db-3.0.t
-t/db-3.1.t
-t/db-3.2.t
-t/destroy.t
-t/env.t
-t/examples.t
-t/examples.t.T
-t/examples3.t
-t/examples3.t.T
-t/filter.t
-t/hash.t
-t/join.t
-t/mldbm.t
-t/queue.t
-t/recno.t
-t/strict.t
-t/subdb.t
-t/txn.t
-t/unknown.t
-Todo
-typemap
-patches/5.004
-patches/5.004_01
-patches/5.004_02
-patches/5.004_03
-patches/5.004_04
-patches/5.004_05
-patches/5.005
-patches/5.005_01
-patches/5.005_02
-patches/5.005_03
-patches/5.6.0
diff --git a/bdb/perl.BerkeleyDB/Makefile.PL b/bdb/perl.BerkeleyDB/Makefile.PL
deleted file mode 100644
index 399a6761886..00000000000
--- a/bdb/perl.BerkeleyDB/Makefile.PL
+++ /dev/null
@@ -1,112 +0,0 @@
-#! perl -w
-
-# It should not be necessary to edit this file. The configuration for
-# BerkeleyDB is controlled from the file config.in
-
-
-BEGIN { die "BerkeleyDB needs Perl 5.004_04 or greater" if $] < 5.004_04 ; }
-
-use strict ;
-use ExtUtils::MakeMaker ;
-
-my $LIB_DIR ;
-my $INC_DIR ;
-my $DB_NAME ;
-my $LIBS ;
-
-ParseCONFIG() ;
-
-if (defined $DB_NAME)
- { $LIBS = $DB_NAME }
-else {
- if ($^O eq 'MSWin32')
- { $LIBS = '-llibdb' }
- else
- { $LIBS = '-ldb' }
-}
-
-# OS2 is a special case, so check for it now.
-my $OS2 = "" ;
-$OS2 = "-DOS2" if $^O eq 'os2' ;
-
-WriteMakefile(
- NAME => 'BerkeleyDB',
- LIBS => ["-L${LIB_DIR} $LIBS"],
- MAN3PODS => ' ', # Pods will be built by installman.
- INC => "-I$INC_DIR",
- VERSION_FROM => 'BerkeleyDB.pm',
- XSPROTOARG => '-noprototypes',
- DEFINE => "$OS2",
- #'macro' => { INSTALLDIRS => 'perl' },
- 'dist' => {COMPRESS=>'gzip', SUFFIX=>'gz'},
- ($] >= 5.005
- ? (ABSTRACT_FROM => 'BerkeleyDB.pod',
- AUTHOR => 'Paul Marquess <Paul.Marquess@btinternet.com>')
- : ()
- ),
- );
-
-
-sub MY::postamble {
- '
-$(NAME).pod: $(NAME).pod.P t/examples.t.T t/examples3.t.T mkpod
- perl ./mkpod
-
-$(NAME).xs: typemap
- @$(TOUCH) $(NAME).xs
-
-Makefile: config.in
-
-
-' ;
-}
-
-sub ParseCONFIG
-{
- my ($k, $v) ;
- my @badkey = () ;
- my %Info = () ;
- my @Options = qw( INCLUDE LIB DBNAME ) ;
- my %ValidOption = map {$_, 1} @Options ;
- my %Parsed = %ValidOption ;
- my $CONFIG = 'config.in' ;
-
- print "Parsing $CONFIG...\n" ;
-
- # DBNAME is optional, so pretend it has been parsed.
- delete $Parsed{'DBNAME'} ;
-
- open(F, "$CONFIG") or die "Cannot open file $CONFIG: $!\n" ;
- while (<F>) {
- s/^\s*|\s*$//g ;
- next if /^\s*$/ or /^\s*#/ ;
- s/\s*#\s*$// ;
-
- ($k, $v) = split(/\s+=\s+/, $_, 2) ;
- $k = uc $k ;
- if ($ValidOption{$k}) {
- delete $Parsed{$k} ;
- $Info{$k} = $v ;
- }
- else {
- push(@badkey, $k) ;
- }
- }
- close F ;
-
- print "Unknown keys in $CONFIG ignored [@badkey]\n"
- if @badkey ;
-
- # check parsed values
- my @missing = () ;
- die "The following keys are missing from $CONFIG file: [@missing]\n"
- if @missing = keys %Parsed ;
-
- $INC_DIR = $ENV{'BERKELEYDB_INCLUDE'} || $Info{'INCLUDE'} ;
- $LIB_DIR = $ENV{'BERKELEYDB_LIB'} || $Info{'LIB'} ;
- $DB_NAME = $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
- print "Looks Good.\n" ;
-
-}
-
-# end of file Makefile.PL
diff --git a/bdb/perl.BerkeleyDB/README b/bdb/perl.BerkeleyDB/README
deleted file mode 100644
index aa905fa8011..00000000000
--- a/bdb/perl.BerkeleyDB/README
+++ /dev/null
@@ -1,464 +0,0 @@
- BerkeleyDB
-
- Version 0.13
-
- 15th Jan 2001
-
- Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This
- program is free software; you can redistribute it and/or modify
- it under the same terms as Perl itself.
-
-
-DESCRIPTION
------------
-
-BerkeleyDB is a module which allows Perl programs to make use of the
-facilities provided by Berkeley DB version 2 or 3. (Note: if you want
-to use version 1 of Berkeley DB with Perl you need the DB_File module).
-
-Berkeley DB is a C library which provides a consistent interface to a
-number of database formats. BerkeleyDB provides an interface to all
-four of the database types (hash, btree, queue and recno) currently
-supported by Berkeley DB.
-
-For further details see the documentation in the file BerkeleyDB.pod.
-
-PREREQUISITES
--------------
-
-Before you can build BerkeleyDB you need to have the following
-installed on your system:
-
- * Perl 5.004_04 or greater.
-
- * Berkeley DB Version 2.6.4 or greater
-
- The official web site for Berkeley DB is http://www.sleepycat.com
-
- The latest version of Berkeley DB is always available there. It
- is recommended that you use the most recent version available at
- the Sleepycat site.
-
- The one exception to this advice is where you want to use BerkeleyDB
- to access database files created by a third-party application,
- like Sendmail. In these cases you must build BerkeleyDB with a
- compatible version of Berkeley DB.
-
-
-BUILDING THE MODULE
--------------------
-
-Assuming you have met all the prerequisites, building the module should
-be relatively straightforward.
-
-Step 1 : If you are running Solaris 2.5, 2.7 or HP-UX 10 read either
- the Solaris Notes or HP-UX Notes sections below.
- If you are running Linux please read the Linux Notes section
- before proceeding.
-
-
-Step 2 : Edit the file config.in to suit you local installation.
- Instructions are given in the file.
-
-Step 3 : Build and test the module using this sequence of commands:
-
- perl Makefile.PL
- make
- make test
-
-INSTALLATION
-------------
-
- make install
-
-TROUBLESHOOTING
-===============
-
-Here are some of the problems that people encounter when building BerkeleyDB.
-
-Missing db.h or libdb.a
------------------------
-
-If you get an error like this:
-
- cc -c -I./libraries/ -Dbool=char -DHAS_BOOL -I/usr/local/include -O2
- -DVERSION=\"0.07\" -DXS_VERSION=\"0.07\" -fpic
- -I/usr/local/lib/perl5/5.00503/i586-linux/CORE BerkeleyDB.c
- BerkeleyDB.xs:52: db.h: No such file or directory
-
-or this:
-
- cc -c -I./libraries/2.7.5 -Dbool=char -DHAS_BOOL -I/usr/local/include -O2
- -DVERSION=\"0.07\" -DXS_VERSION=\"0.07\" -fpic
- -I/usr/local/lib/perl5/5.00503/i586-linux/CORE BerkeleyDB.c
- LD_RUN_PATH="/lib" cc -o blib/arch/auto/BerkeleyDB/BerkeleyDB.so -shared
- -L/usr/local/lib BerkeleyDB.o
- -L/home/paul/perl/ext/BerkDB/BerkeleyDB/libraries -ldb
- ld: cannot open -ldb: No such file or directory
-
-This symptom can imply:
-
- 1. You don't have Berkeley DB installed on your system at all.
- Solution: get & install Berkeley DB.
-
- 2. You do have Berkeley DB installed, but it isn't in a standard place.
- Solution: Edit config.in and set the LIB and INCLUDE variables to point
- to the directories where libdb.a and db.h are installed.
-
-Wrong db.h
-----------
-
-If you get an error like this when building this module:
-
- cc -c -I./libraries/ -Dbool=char -DHAS_BOOL -I/usr/local/include -O2
- -DVERSION=\"0.07\" -DXS_VERSION=\"0.07\" -fpic
- -I/usr/local/lib/perl5/5.00503/i586-linux/CORE BerkeleyDB.c
- BerkeleyDB.xs:93: parse error before `DB_INFO'
- BerkeleyDB.xs:93: warning: no semicolon at end of struct or union
- BerkeleyDB.xs:94: warning: data definition has no type or storage class
- BerkeleyDB.xs:95: parse error before `0x80000000'
- BerkeleyDB.xs:110: parse error before `}'
- BerkeleyDB.xs:110: warning: data definition has no type or storage class
- BerkeleyDB.xs:117: parse error before `DB_ENV'
- ...
-
-This error usually happens when if you only have Berkeley DB version 1
-on your system or you have both version 1 and version 2 (or 3) of Berkeley
-DB installed on your system. When building BerkeleyDB it attempts
-to use the db.h for Berkeley DB version 1. This perl module can only
-be built with Berkeley DB version 2 or 3.
-
-This symptom can imply:
-
- 1. You don't have Berkeley DB version 2 or 3 installed on your system
- at all.
- Solution: get & install Berkeley DB.
-
- 2. You do have Berkeley DB 2 or 3 installed, but it isn't in a standard
- place.
- Solution: Edit config.in and set the LIB and INCLUDE variables
- to point to the directories where libdb.a and db.h are
- installed.
-
-Undefined Symbol: txn_stat
---------------------------
-
-BerkeleyDB seems to have built correctly, but you get an error like this
-when you run the test harness:
-
- $ make test
- PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00503
- -Iblib/arch -Iblib/lib -I/usr/local/lib/perl5/5.00503/i586-linux
- -I/usr/local/lib/perl5/5.00503 -e 'use Test::Harness qw(&runtests $verbose);
- $verbose=0; runtests @ARGV;' t/*.t
- t/btree.............Can't load 'blib/arch/auto/BerkeleyDB/BerkeleyDB.so' for
- module BerkeleyDB: blib/arch/auto/BerkeleyDB/BerkeleyDB.so:
- undefined symbol: txn_stat
- at /usr/local/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.
- ...
-
-This error usually happens when you have both version 1 and version
-2 (or 3) of Berkeley DB installed on your system and BerkeleyDB attempts
-to build using the db.h for Berkeley DB version 2/3 and the version 1
-library. Unfortunately the two versions aren't compatible with each
-other. BerkeleyDB can only be built with Berkeley DB version 2 or 3.
-
-Solution: Setting the LIB & INCLUDE variables in config.in to point to the
- correct directories can sometimes be enough to fix this
- problem. If that doesn't work the easiest way to fix the
- problem is to either delete or temporarily rename the copies
- of db.h and libdb.a that you don't want BerkeleyDB to use.
-
-Undefined Symbol: db_appinit
-----------------------------
-
-BerkeleyDB seems to have built correctly, but you get an error like this
-when you run the test harness:
-
- $ make test
- PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00561 -Iblib/arch
- -Iblib/lib -I/home/paul/perl/install/5.005_61/lib/5.00561/i586-linux
- -I/home/paul/perl/install/5.005_61/lib/5.00561 -e 'use Test::Harness
- qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
- t/btree.............Can't load 'blib/arch/auto/BerkeleyDB/BerkeleyDB.so' for
- module BerkeleyDB: blib/arch/auto/BerkeleyDB/BerkeleyDB.so:
- undefined symbol: db_appinit
- at /home/paul/perl/install/5.005_61/lib/5.00561/i586-linux/DynaLoader.pm
- ...
-
-
-This error usually happens when you have both version 2 and version
-3 of Berkeley DB installed on your system and BerkeleyDB attempts
-to build using the db.h for Berkeley DB version 2 and the version 3
-library. Unfortunately the two versions aren't compatible with each
-other.
-
-Solution: Setting the LIB & INCLUDE variables in config.in to point to the
- correct directories can sometimes be enough to fix this
- problem. If that doesn't work the easiest way to fix the
- problem is to either delete or temporarily rename the copies
- of db.h and libdb.a that you don't want BerkeleyDB to use.
-
-Undefined Symbol: db_create
----------------------------
-
-BerkeleyDB seems to have built correctly, but you get an error like this
-when you run the test harness:
-
- $ make test
- PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00561 -Iblib/arch
- -Iblib/lib -I/home/paul/perl/install/5.005_61/lib/5.00561/i586-linux
- -I/home/paul/perl/install/5.005_61/lib/5.00561 -e 'use Test::Harness
- qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
- t/btree.............Can't load 'blib/arch/auto/BerkeleyDB/BerkeleyDB.so' for
- module BerkeleyDB: blib/arch/auto/BerkeleyDB/BerkeleyDB.so:
- undefined symbol: db_create
- at /home/paul/perl/install/5.005_61/lib/5.00561/i586-linux/DynaLoader.pm
- ...
-
-This error usually happens when you have both version 2 and version
-3 of Berkeley DB installed on your system and BerkeleyDB attempts
-to build using the db.h for Berkeley DB version 3 and the version 2
-library. Unfortunately the two versions aren't compatible with each
-other.
-
-Solution: Setting the LIB & INCLUDE variables in config.in to point to the
- correct directories can sometimes be enough to fix this
- problem. If that doesn't work the easiest way to fix the
- problem is to either delete or temporarily rename the copies
- of db.h and libdb.a that you don't want BerkeleyDB to use.
-
-
-Incompatible versions of db.h and libdb
----------------------------------------
-
-BerkeleyDB seems to have built correctly, but you get an error like this
-when you run the test harness:
-
- $ make test
- PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00503
- -Iblib/arch -Iblib/lib -I/usr/local/lib/perl5/5.00503/i586-linux
- -I/usr/local/lib/perl5/5.00503 -e 'use Test::Harness qw(&runtests $verbose);
- $verbose=0; runtests @ARGV;' t/*.t
- t/btree.............
- BerkeleyDB needs compatible versions of libdb & db.h
- you have db.h version 2.6.4 and libdb version 2.7.5
- BEGIN failed--compilation aborted at t/btree.t line 25.
- dubious
- Test returned status 255 (wstat 65280, 0xff00)
- ...
-
-Another variation on the theme of having two versions of Berkeley DB on
-your system.
-
-Solution: Setting the LIB & INCLUDE variables in config.in to point to the
- correct directories can sometimes be enough to fix this
- problem. If that doesn't work the easiest way to fix the
- problem is to either delete or temporarily rename the copies
- of db.h and libdb.a that you don't want BerkeleyDB to use.
- If you are running Linux, please read the Linux Notes section below.
-
-
-Linux Notes
------------
-
-Newer versions of Linux (e.g. RedHat 6, SuSe 6) ship with a C library
-that has version 2.x of Berkeley DB linked into it. This makes it
-difficult to build this module with anything other than the version of
-Berkeley DB that shipped with your Linux release. If you do try to use
-a different version of Berkeley DB you will most likely get the error
-described in the "Incompatible versions of db.h and libdb" section of
-this file.
-
-To make matters worse, prior to Perl 5.6.1, the perl binary itself
-*always* included the Berkeley DB library.
-
-If you want to use a newer version of Berkeley DB with this module, the
-easiest solution is to use Perl 5.6.1 (or better) and Berkeley DB 3.x
-(or better).
-
-There are two approaches you can use to get older versions of Perl to
-work with specific versions of Berkeley DB. Both have their advantages
-and disadvantages.
-
-The first approach will only work when you want to build a version of
-Perl older than 5.6.1 along with Berkeley DB 3.x. If you want to use
-Berkeley DB 2.x, you must use the next approach. This approach involves
-rebuilding your existing version of Perl after applying an unofficial
-patch. The "patches" directory in the this module's source distribution
-contains a number of patch files. There is one patch file for every
-stable version of Perl since 5.004. Apply the appropriate patch to your
-Perl source tree before re-building and installing Perl from scratch.
-For example, assuming you are in the top-level source directory for
-Perl 5.6.0, the command below will apply the necessary patch. Remember
-to replace the path shown below with one that points to this module's
-patches directory.
-
- patch -p1 -N </path/to/BerkeleyDB/patches/5.6.0
-
-Now rebuild & install perl. You should now have a perl binary that can
-be used to build this module. Follow the instructions in "BUILDING THE
-MODULE", remembering to set the INCLUDE and LIB variables in config.in.
-
-
-The second approach will work with both Berkeley DB 2.x and 3.x.
-Start by building Berkeley DB as a shared library. This is from
-the Berkeley DB build instructions:
-
- Building Shared Libraries for the GNU GCC compiler
-
- If you're using gcc and there's no better shared library example for
- your architecture, the following shared library build procedure will
- probably work.
-
- Add the -fpic option to the CFLAGS value in the Makefile.
-
- Rebuild all of your .o files. This will create a Berkeley DB library
- that contains .o files with PIC code. To build the shared library,
- then take the following steps in the library build directory:
-
- % mkdir tmp
- % cd tmp
- % ar xv ../libdb.a
- % gcc -shared -o libdb.so *.o
- % mv libdb.so ..
- % cd ..
- % rm -rf tmp
-
- Note, you may have to change the gcc line depending on the
- requirements of your system.
-
- The file libdb.so is your shared library
-
-Once you have built libdb.so, you will need to store it somewhere safe.
-
- cp libdb.so /usr/local/BerkeleyDB/lib
-
-If you now set the LD_PRELOAD environment variable to point to this
-shared library, Perl will use it instead of the version of Berkeley DB
-that shipped with your Linux distribution.
-
- export LD_PRELOAD=/usr/local/BerkeleyDB/lib/libdb.so
-
-Finally follow the instructions in "BUILDING THE MODULE" to build,
-test and install this module. Don't forget to set the INCLUDE and LIB
-variables in config.in.
-
-Remember, you will need to have the LD_PRELOAD variable set anytime you
-want to use Perl with Berkeley DB. Also note that if you have LD_PRELOAD
-permanently set it will affect ALL commands you execute. This may be a
-problem if you run any commands that access a database created by the
-version of Berkeley DB that shipped with your Linux distribution.
-
-
-
-Solaris 2.5 Notes
------------------
-
-If you are running Solaris 2.5, and you get this error when you run the
-BerkeleyDB test harness:
-
- libc internal error: _rmutex_unlock: rmutex not held.
-
-you probably need to install a Sun patch. It has been reported that
-Sun patch 103187-25 (or later revisions) fixes this problem.
-
-To find out if you have the patch installed, the command "showrev -p"
-will display the patches that are currently installed on your system.
-
-Solaris 2.7 Notes
------------------
-
-If you are running Solaris 2.7 and all the tests in the test harness
-generate a core dump, try applying Sun patch 106980-09 (or better).
-
-To find out if you have the patch installed, the command "showrev -p"
-will display the patches that are currently installed on your system.
-
-
-HP-UX Notes
------------
-
-Some people running HP-UX 10 have reported getting an error like this
-when building this module with the native HP-UX compiler.
-
- ld: (Warning) At least one PA 2.0 object file (BerkeleyDB.o) was detected.
- The linked output may not run on a PA 1.x system.
- ld: Invalid loader fixup for symbol "$000000A5".
-
-If this is the case for you, Berkeley DB needs to be recompiled with
-the +z or +Z option and the resulting library placed in a .sl file. The
-following steps should do the trick:
-
- 1: Configure the Berkeley DB distribution with the +z or +Z C compiler
- flag:
-
- env "CFLAGS=+z" ../dist/configure ...
-
- 2: Edit the Berkeley DB Makefile and change:
-
- "libdb= libdb.a" to "libdb= libdb.sl".
-
- 3: Build and install the Berkeley DB distribution as usual.
-
-
-
-FEEDBACK
---------
-
-How to report a problem with BerkeleyDB.
-
-To help me help you, I need of the following information:
-
- 1. The version of Perl and the operating system name and version you
- are running. The complete output from running "perl -V" will tell
- me all I need to know.
- If your perl does not understand the "-V" option is too old.
- BerkeleyDB needs Perl version 5.004_04 or better.
-
- 2. The version of BerkeleyDB you have. If you have successfully
- installed BerkeleyDB, this one-liner will tell you:
-
- perl -MBerkeleyDB -e 'print "BerkeleyDB ver $BerkeleyDB::VERSION\n"'
-
- If you haven't installed BerkeleyDB then search BerkeleyDB.pm for a
- line like this:
-
- $VERSION = "1.20" ;
-
- 3. The version of Berkeley DB you have installed. If you have
- successfully installed BerkeleyDB, this one-liner will tell you:
-
- perl -MBerkeleyDB -e 'print BerkeleyDB::DB_VERSION_STRING."\n"'
-
- If you haven't installed BerkeleyDB then search db.h for a line
- like this:
-
- #define DB_VERSION_STRING
-
- 4. If you are having problems building BerkeleyDB, send me a complete
- log of what happened.
-
- 5. Now the difficult one. If you think you have found a bug in
- BerkeleyDB and you want me to fix it, you will *greatly* enhance
- the chances of me being able to track it down by sending me a small
- self-contained Perl script that illustrates the problem you are
- encountering. Include a summary of what you think the problem is
- and a log of what happens when you run the script, in case I can't
- reproduce your problem on my system. If possible, don't have the
- script dependent on an existing 20Meg database. If the script you
- send me can create the database itself then that is preferred.
-
- I realise that in some cases this is easier said than done, so if
- you can only reproduce the problem in your existing script, then
- you can post me that if you want. Just don't expect me to find your
- problem in a hurry, or at all. :-)
-
-
-CHANGES
--------
-
-See the Changes file.
-
-Paul Marquess <Paul.Marquess@btinternet.com>
-
diff --git a/bdb/perl.BerkeleyDB/config.in b/bdb/perl.BerkeleyDB/config.in
deleted file mode 100644
index c23e6689cb3..00000000000
--- a/bdb/perl.BerkeleyDB/config.in
+++ /dev/null
@@ -1,51 +0,0 @@
-# Filename: config.in
-#
-# written by Paul Marquess <Paul.Marquess@btinternet.com>
-
-# 1. Where is the file db.h?
-#
-# Change the path below to point to the directory where db.h is
-# installed on your system.
-
-#INCLUDE = /usr/local/include
-#INCLUDE = /usr/local/BerkeleyDB/include
-#INCLUDE = ./libraries/2.7.5
-#INCLUDE = ./libraries/3.0.55
-#INCLUDE = ./libraries/3.1.17
-INCLUDE = ./libraries/3.2.7
-
-# 2. Where is libdb?
-#
-# Change the path below to point to the directory where libdb is
-# installed on your system.
-
-#LIB = /usr/local/lib
-#LIB = /usr/local/BerkeleyDB/lib
-#LIB = ./libraries/2.7.5
-#LIB = ./libraries/3.0.55
-#LIB = ./libraries/3.1.17
-LIB = ./libraries/3.2.7
-
-# 3. Is the library called libdb?
-#
-# If you have copies of both 1.x and 2.x Berkeley DB installed on
-# your system it can sometimes be tricky to make sure you are using
-# the correct one. Renaming one (or creating a symbolic link) to
-# include the version number of the library can help.
-#
-# For example, if you have Berkeley DB 2.6.4 you could rename the
-# Berkeley DB library from libdb.a to libdb-2.6.4.a and change the
-# DBNAME line below to look like this:
-#
-# DBNAME = -ldb-2.6.4
-#
-# Note: If you are building this module with Win32, -llibdb will be
-# used by default.
-#
-# If you have changed the name of the library, uncomment the line
-# below (by removing the leading #) and edit the line to use the name
-# you have picked.
-
-#DBNAME = -ldb-3.0
-
-# end of file config.in
diff --git a/bdb/perl.BerkeleyDB/dbinfo b/bdb/perl.BerkeleyDB/dbinfo
deleted file mode 100755
index 415411aff8e..00000000000
--- a/bdb/perl.BerkeleyDB/dbinfo
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/local/bin/perl
-
-# Name: dbinfo -- identify berkeley DB version used to create
-# a database file
-#
-# Author: Paul Marquess <Paul.Marquess@btinternet.com>
-# Version: 1.03
-# Date 17th September 2000
-#
-# Copyright (c) 1998-2001 Paul Marquess. All rights reserved.
-# This program is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-
-# Todo: Print more stats on a db file, e.g. no of records
-# add log/txn/lock files
-
-use strict ;
-
-my %Data =
- (
- 0x053162 => {
- Type => "Btree",
- Versions =>
- {
- 1 => "Unknown (older than 1.71)",
- 2 => "Unknown (older than 1.71)",
- 3 => "1.71 -> 1.85, 1.86",
- 4 => "Unknown",
- 5 => "2.0.0 -> 2.3.0",
- 6 => "2.3.1 -> 2.7.7",
- 7 => "3.0.x",
- 8 => "3.1.x or greater",
- }
- },
- 0x061561 => {
- Type => "Hash",
- Versions =>
- {
- 1 => "Unknown (older than 1.71)",
- 2 => "1.71 -> 1.85",
- 3 => "1.86",
- 4 => "2.0.0 -> 2.1.0",
- 5 => "2.2.6 -> 2.7.7",
- 6 => "3.0.x",
- 7 => "3.1.x or greater",
- }
- },
- 0x042253 => {
- Type => "Queue",
- Versions =>
- {
- 1 => "3.0.x",
- 2 => "3.1.x",
- 3 => "3.2.x or greater",
- }
- },
- ) ;
-
-die "Usage: dbinfo file\n" unless @ARGV == 1 ;
-
-print "testing file $ARGV[0]...\n\n" ;
-open (F, "<$ARGV[0]") or die "Cannot open file $ARGV[0]: $!\n" ;
-
-my $buff ;
-read F, $buff, 20 ;
-
-my (@info) = unpack("NNNNN", $buff) ;
-my (@info1) = unpack("VVVVV", $buff) ;
-my ($magic, $version, $endian) ;
-
-if ($Data{$info[0]}) # first try DB 1.x format
-{
- $magic = $info[0] ;
- $version = $info[1] ;
- $endian = "Unknown" ;
-}
-elsif ($Data{$info[3]}) # next DB 2.x big endian
-{
- $magic = $info[3] ;
- $version = $info[4] ;
- $endian = "Big Endian" ;
-}
-elsif ($Data{$info1[3]}) # next DB 2.x little endian
-{
- $magic = $info1[3] ;
- $version = $info1[4] ;
- $endian = "Little Endian" ;
-}
-else
- { die "not a Berkeley DB database file.\n" }
-
-my $type = $Data{$magic} ;
-$magic = sprintf "%06X", $magic ;
-
-my $ver_string = "Unknown" ;
-$ver_string = $type->{Versions}{$version}
- if defined $type->{Versions}{$version} ;
-
-print <<EOM ;
-File Type: Berkeley DB $type->{Type} file.
-File Version ID: $version
-Built with Berkeley DB: $ver_string
-Byte Order: $endian
-Magic: $magic
-EOM
-
-close F ;
-
-exit ;
diff --git a/bdb/perl.BerkeleyDB/mkconsts b/bdb/perl.BerkeleyDB/mkconsts
deleted file mode 100644
index 24ef4fca7b2..00000000000
--- a/bdb/perl.BerkeleyDB/mkconsts
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/perl
-
-%constants = (
- # Symbol 0 = define, 1 = enum
- DB_AFTER => 0,
- DB_APPEND => 0,
- DB_ARCH_ABS => 0,
- DB_ARCH_DATA => 0,
- DB_ARCH_LOG => 0,
- DB_BEFORE => 0,
- DB_BTREE => 1,
- DB_BTREEMAGIC => 0,
- DB_BTREEOLDVER => 0,
- DB_BTREEVERSION => 0,
- DB_CHECKPOINT => 0,
- DB_CONSUME => 0,
- DB_CREATE => 0,
- DB_CURLSN => 0,
- DB_CURRENT => 0,
- DB_DBT_MALLOC => 0,
- DB_DBT_PARTIAL => 0,
- DB_DBT_USERMEM => 0,
- DB_DELETED => 0,
- DB_DELIMITER => 0,
- DB_DUP => 0,
- DB_DUPSORT => 0,
- DB_ENV_APPINIT => 0,
- DB_ENV_STANDALONE => 0,
- DB_ENV_THREAD => 0,
- DB_EXCL => 0,
- DB_FILE_ID_LEN => 0,
- DB_FIRST => 0,
- DB_FIXEDLEN => 0,
- DB_FLUSH => 0,
- DB_FORCE => 0,
- DB_GET_BOTH => 0,
- DB_GET_RECNO => 0,
- DB_HASH => 1,
- DB_HASHMAGIC => 0,
- DB_HASHOLDVER => 0,
- DB_HASHVERSION => 0,
- DB_INCOMPLETE => 0,
- DB_INIT_CDB => 0,
- DB_INIT_LOCK => 0,
- DB_INIT_LOG => 0,
- DB_INIT_MPOOL => 0,
- DB_INIT_TXN => 0,
- DB_JOIN_ITEM => 0,
- DB_KEYEMPTY => 0,
- DB_KEYEXIST => 0,
- DB_KEYFIRST => 0,
- DB_KEYLAST => 0,
- DB_LAST => 0,
- DB_LOCK_CONFLICT => 0,
- DB_LOCK_DEADLOCK => 0,
- DB_LOCK_DEFAULT => 0,
- DB_LOCK_GET => 1,
- DB_LOCK_NORUN => 0,
- DB_LOCK_NOTGRANTED => 0,
- DB_LOCK_NOTHELD => 0,
- DB_LOCK_NOWAIT => 0,
- DB_LOCK_OLDEST => 0,
- DB_LOCK_RANDOM => 0,
- DB_LOCK_RIW_N => 0,
- DB_LOCK_RW_N => 0,
- DB_LOCK_YOUNGEST => 0,
- DB_LOCKMAGIC => 0,
- DB_LOCKVERSION => 0,
- DB_LOGMAGIC => 0,
- DB_LOGOLDVER => 0,
- DB_MAX_PAGES => 0,
- DB_MAX_RECORDS => 0,
- DB_MPOOL_CLEAN => 0,
- DB_MPOOL_CREATE => 0,
- DB_MPOOL_DIRTY => 0,
- DB_MPOOL_DISCARD => 0,
- DB_MPOOL_LAST => 0,
- DB_MPOOL_NEW => 0,
- DB_MPOOL_PRIVATE => 0,
- DB_MUTEXDEBUG => 0,
- DB_MUTEXLOCKS => 0,
- DB_NEEDSPLIT => 0,
- DB_NEXT => 0,
- DB_NEXT_DUP => 0,
- DB_NOMMAP => 0,
- DB_NOOVERWRITE => 0,
- DB_NOSYNC => 0,
- DB_NOTFOUND => 0,
- DB_PAD => 0,
- DB_PAGEYIELD => 0,
- DB_POSITION => 0,
- DB_PREV => 0,
- DB_PRIVATE => 0,
- DB_QUEUE => 1,
- DB_RDONLY => 0,
- DB_RECNO => 1,
- DB_RECNUM => 0,
- DB_RECORDCOUNT => 0,
- DB_RECOVER => 0,
- DB_RECOVER_FATAL => 0,
- DB_REGISTERED => 0,
- DB_RENUMBER => 0,
- DB_RMW => 0,
- DB_RUNRECOVERY => 0,
- DB_SEQUENTIAL => 0,
- DB_SET => 0,
- DB_SET_RANGE => 0,
- DB_SET_RECNO => 0,
- DB_SNAPSHOT => 0,
- DB_SWAPBYTES => 0,
- DB_TEMPORARY => 0,
- DB_THREAD => 0,
- DB_TRUNCATE => 0,
- DB_TXN_ABORT => 1,
- DB_TXN_BACKWARD_ROLL => 1,
- DB_TXN_CKP => 0,
- DB_TXN_FORWARD_ROLL => 1,
- DB_TXN_LOCK_2PL => 0,
- DB_TXN_LOCK_MASK => 0,
- DB_TXN_LOCK_OPTIMISTIC => 0,
- DB_TXN_LOG_MASK => 0,
- DB_TXN_LOG_REDO => 0,
- DB_TXN_LOG_UNDO => 0,
- DB_TXN_LOG_UNDOREDO => 0,
- DB_TXN_NOSYNC => 0,
- DB_TXN_NOWAIT => 0,
- DB_TXN_SYNC => 0,
- DB_TXN_OPENFILES => 1,
- DB_TXN_REDO => 0,
- DB_TXN_UNDO => 0,
- DB_TXNMAGIC => 0,
- DB_TXNVERSION => 0,
- DB_TXN_LOCK_OPTIMIST => 0,
- DB_UNKNOWN => 1,
- DB_USE_ENVIRON => 0,
- DB_USE_ENVIRON_ROOT => 0,
- DB_VERSION_MAJOR => 0,
- DB_VERSION_MINOR => 0,
- DB_VERSION_PATCH => 0,
- DB_WRITECURSOR => 0,
- ) ;
-
-sub OutputXS
-{
- # skip to the marker
- if (0) {
- while (<>)
- {
- last if /^MARKER/ ;
- print ;
- }
- }
-
- foreach my $key (sort keys %constants)
- {
- my $isEnum = $constants{$key} ;
-
- if ($isEnum) {
- print <<EOM
- if (strEQ(name, "$key"))
- return $key;
-EOM
- }
- else
- {
- print <<EOM
- if (strEQ(name, "$key"))
-#ifdef $key
- return $key;
-#else
- goto not_there;
-#endif
-EOM
- }
-
- }
-
- if (0) {
- while (<>)
- {
- print ;
- }
- }
-}
-
-sub OutputPM
-{
- # skip to the marker
- if (0) {
- while (<>)
- {
- last if /^MARKER/ ;
- print ;
- }
- }
-
- foreach my $key (sort keys %constants)
- {
- print "\t$key\n";
- }
-
- if (0) {
- while (<>)
- {
- print ;
- }
- }
-}
-
-OutputXS() if $ARGV[0] =~ /xs/i ;
-OutputPM() if $ARGV[0] =~ /pm/i ;
diff --git a/bdb/perl.BerkeleyDB/t/btree.t b/bdb/perl.BerkeleyDB/t/btree.t
deleted file mode 100644
index 97bb3257c97..00000000000
--- a/bdb/perl.BerkeleyDB/t/btree.t
+++ /dev/null
@@ -1,976 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-#use Config;
-#
-#BEGIN {
-# if(-d "lib" && -f "TEST") {
-# if ($Config{'extensions'} !~ /\bBerkeleyDB\b/ ) {
-# print "1..74\n";
-# exit 0;
-# }
-# }
-#}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..243\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
-) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-# Check for invalid parameters
-{
- # Check for invalid parameters
- my $db ;
- eval ' $db = new BerkeleyDB::Btree -Stupid => 3 ; ' ;
- ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' $db = new BerkeleyDB::Btree -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
- ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
-
- eval ' $db = new BerkeleyDB::Btree -Env => 2 ' ;
- ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-
- eval ' $db = new BerkeleyDB::Btree -Txn => "x" ' ;
- ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
-
- my $obj = bless [], "main" ;
- eval ' $db = new BerkeleyDB::Btree -Env => $obj ' ;
- ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-}
-
-# Now check the interface to Btree
-
-{
- my $lex = new LexFile $Dfile ;
-
- ok 6, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my $value ;
- my $status ;
- ok 7, $db->db_put("some key", "some value") == 0 ;
- ok 8, $db->status() == 0 ;
- ok 9, $db->db_get("some key", $value) == 0 ;
- ok 10, $value eq "some value" ;
- ok 11, $db->db_put("key", "value") == 0 ;
- ok 12, $db->db_get("key", $value) == 0 ;
- ok 13, $value eq "value" ;
- ok 14, $db->db_del("some key") == 0 ;
- ok 15, ($status = $db->db_get("some key", $value)) == DB_NOTFOUND ;
- ok 16, $db->status() == DB_NOTFOUND ;
- ok 17, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
-
- ok 18, $db->db_sync() == 0 ;
-
- # Check NOOVERWRITE will make put fail when attempting to overwrite
- # an existing record.
-
- ok 19, $db->db_put( 'key', 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
- ok 20, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
- ok 21, $db->status() == DB_KEYEXIST ;
-
-
- # check that the value of the key has not been changed by the
- # previous test
- ok 22, $db->db_get("key", $value) == 0 ;
- ok 23, $value eq "value" ;
-
- # test DB_GET_BOTH
- my ($k, $v) = ("key", "value") ;
- ok 24, $db->db_get($k, $v, DB_GET_BOTH) == 0 ;
-
- ($k, $v) = ("key", "fred") ;
- ok 25, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
- ($k, $v) = ("another", "value") ;
- ok 26, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
-
-}
-
-{
- # Check simple env works with a hash.
- my $lex = new LexFile $Dfile ;
-
- my $home = "./fred" ;
- ok 27, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
-
- ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
- -Home => $home ;
- ok 29, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
- -Env => $env,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my $value ;
- ok 30, $db->db_put("some key", "some value") == 0 ;
- ok 31, $db->db_get("some key", $value) == 0 ;
- ok 32, $value eq "some value" ;
- undef $db ;
- undef $env ;
- rmtree $home ;
-}
-
-
-{
- # cursors
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my ($k, $v) ;
- ok 33, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => 2,
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (($k, $v) = each %data) {
- $ret += $db->db_put($k, $v) ;
- }
- ok 34, $ret == 0 ;
-
- # create the cursor
- ok 35, my $cursor = $db->db_cursor() ;
-
- $k = $v = "" ;
- my %copy = %data ;
- my $extras = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- if ( $copy{$k} eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
- ok 36, $cursor->status() == DB_NOTFOUND ;
- ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'};
- ok 38, keys %copy == 0 ;
- ok 39, $extras == 0 ;
-
- # sequence backwards
- %copy = %data ;
- $extras = 0 ;
- my $status ;
- for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_PREV)) {
- if ( $copy{$k} eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
- ok 40, $status == DB_NOTFOUND ;
- ok 41, $status eq $DB_errors{'DB_NOTFOUND'};
- ok 42, $cursor->status() == $status ;
- ok 43, $cursor->status() eq $status ;
- ok 44, keys %copy == 0 ;
- ok 45, $extras == 0 ;
-
- ($k, $v) = ("green", "house") ;
- ok 46, $cursor->c_get($k, $v, DB_GET_BOTH) == 0 ;
-
- ($k, $v) = ("green", "door") ;
- ok 47, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
- ($k, $v) = ("black", "house") ;
- ok 48, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
-}
-
-{
- # Tied Hash interface
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 49, tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # check "each" with an empty database
- my $count = 0 ;
- while (my ($k, $v) = each %hash) {
- ++ $count ;
- }
- ok 50, (tied %hash)->status() == DB_NOTFOUND ;
- ok 51, $count == 0 ;
-
- # Add a k/v pair
- my $value ;
- $hash{"some key"} = "some value";
- ok 52, (tied %hash)->status() == 0 ;
- ok 53, $hash{"some key"} eq "some value";
- ok 54, defined $hash{"some key"} ;
- ok 55, (tied %hash)->status() == 0 ;
- ok 56, exists $hash{"some key"} ;
- ok 57, !defined $hash{"jimmy"} ;
- ok 58, (tied %hash)->status() == DB_NOTFOUND ;
- ok 59, !exists $hash{"jimmy"} ;
- ok 60, (tied %hash)->status() == DB_NOTFOUND ;
-
- delete $hash{"some key"} ;
- ok 61, (tied %hash)->status() == 0 ;
- ok 62, ! defined $hash{"some key"} ;
- ok 63, (tied %hash)->status() == DB_NOTFOUND ;
- ok 64, ! exists $hash{"some key"} ;
- ok 65, (tied %hash)->status() == DB_NOTFOUND ;
-
- $hash{1} = 2 ;
- $hash{10} = 20 ;
- $hash{1000} = 2000 ;
-
- my ($keys, $values) = (0,0);
- $count = 0 ;
- while (my ($k, $v) = each %hash) {
- $keys += $k ;
- $values += $v ;
- ++ $count ;
- }
- ok 66, $count == 3 ;
- ok 67, $keys == 1011 ;
- ok 68, $values == 2022 ;
-
- # now clear the hash
- %hash = () ;
- ok 69, keys %hash == 0 ;
-
- untie %hash ;
-}
-
-{
- # override default compare
- my $lex = new LexFile $Dfile, $Dfile2, $Dfile3 ;
- my $value ;
- my (%h, %g, %k) ;
- my @Keys = qw( 0123 12 -1234 9 987654321 def ) ;
- ok 70, tie %h, "BerkeleyDB::Btree", -Filename => $Dfile,
- -Compare => sub { $_[0] <=> $_[1] },
- -Flags => DB_CREATE ;
-
- ok 71, tie %g, 'BerkeleyDB::Btree', -Filename => $Dfile2,
- -Compare => sub { $_[0] cmp $_[1] },
- -Flags => DB_CREATE ;
-
- ok 72, tie %k, 'BerkeleyDB::Btree', -Filename => $Dfile3,
- -Compare => sub { length $_[0] <=> length $_[1] },
- -Flags => DB_CREATE ;
-
- my @srt_1 ;
- { local $^W = 0 ;
- @srt_1 = sort { $a <=> $b } @Keys ;
- }
- my @srt_2 = sort { $a cmp $b } @Keys ;
- my @srt_3 = sort { length $a <=> length $b } @Keys ;
-
- foreach (@Keys) {
- local $^W = 0 ;
- $h{$_} = 1 ;
- $g{$_} = 1 ;
- $k{$_} = 1 ;
- }
-
- sub ArrayCompare
- {
- my($a, $b) = @_ ;
-
- return 0 if @$a != @$b ;
-
- foreach (1 .. length @$a)
- {
- return 0 unless $$a[$_] eq $$b[$_] ;
- }
-
- 1 ;
- }
-
- ok 73, ArrayCompare (\@srt_1, [keys %h]);
- ok 74, ArrayCompare (\@srt_2, [keys %g]);
- ok 75, ArrayCompare (\@srt_3, [keys %k]);
-
-}
-
-{
- # override default compare, with duplicates, don't sort values
- my $lex = new LexFile $Dfile, $Dfile2, $Dfile3 ;
- my $value ;
- my (%h, %g, %k) ;
- my @Keys = qw( 0123 9 12 -1234 9 987654321 def ) ;
- my @Values = qw( 1 0 3 dd x abc 0 ) ;
- ok 76, tie %h, "BerkeleyDB::Btree", -Filename => $Dfile,
- -Compare => sub { $_[0] <=> $_[1] },
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- ok 77, tie %g, 'BerkeleyDB::Btree', -Filename => $Dfile2,
- -Compare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- ok 78, tie %k, 'BerkeleyDB::Btree', -Filename => $Dfile3,
- -Compare => sub { length $_[0] <=> length $_[1] },
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- my @srt_1 ;
- { local $^W = 0 ;
- @srt_1 = sort { $a <=> $b } @Keys ;
- }
- my @srt_2 = sort { $a cmp $b } @Keys ;
- my @srt_3 = sort { length $a <=> length $b } @Keys ;
-
- foreach (@Keys) {
- local $^W = 0 ;
- my $value = shift @Values ;
- $h{$_} = $value ;
- $g{$_} = $value ;
- $k{$_} = $value ;
- }
-
- sub getValues
- {
- my $hash = shift ;
- my $db = tied %$hash ;
- my $cursor = $db->db_cursor() ;
- my @values = () ;
- my ($k, $v) = (0,0) ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- push @values, $v ;
- }
- return @values ;
- }
-
- ok 79, ArrayCompare (\@srt_1, [keys %h]);
- ok 80, ArrayCompare (\@srt_2, [keys %g]);
- ok 81, ArrayCompare (\@srt_3, [keys %k]);
- ok 82, ArrayCompare ([qw(dd 0 0 x 3 1 abc)], [getValues \%h]);
- ok 83, ArrayCompare ([qw(dd 1 0 3 x abc 0)], [getValues \%g]);
- ok 84, ArrayCompare ([qw(0 x 3 0 1 dd abc)], [getValues \%k]);
-
- # test DB_DUP_NEXT
- ok 85, my $cur = (tied %g)->db_cursor() ;
- my ($k, $v) = (9, "") ;
- ok 86, $cur->c_get($k, $v, DB_SET) == 0 ;
- ok 87, $k == 9 && $v == 0 ;
- ok 88, $cur->c_get($k, $v, DB_NEXT_DUP) == 0 ;
- ok 89, $k == 9 && $v eq "x" ;
- ok 90, $cur->c_get($k, $v, DB_NEXT_DUP) == DB_NOTFOUND ;
-}
-
-{
- # override default compare, with duplicates, sort values
- my $lex = new LexFile $Dfile, $Dfile2;
- my $value ;
- my (%h, %g) ;
- my @Keys = qw( 0123 9 12 -1234 9 987654321 9 def ) ;
- my @Values = qw( 1 11 3 dd x abc 2 0 ) ;
- ok 91, tie %h, "BerkeleyDB::Btree", -Filename => $Dfile,
- -Compare => sub { $_[0] <=> $_[1] },
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- ok 92, tie %g, 'BerkeleyDB::Btree', -Filename => $Dfile2,
- -Compare => sub { $_[0] cmp $_[1] },
- -DupCompare => sub { $_[0] <=> $_[1] },
- -Property => DB_DUP,
-
-
-
- -Flags => DB_CREATE ;
-
- my @srt_1 ;
- { local $^W = 0 ;
- @srt_1 = sort { $a <=> $b } @Keys ;
- }
- my @srt_2 = sort { $a cmp $b } @Keys ;
-
- foreach (@Keys) {
- local $^W = 0 ;
- my $value = shift @Values ;
- $h{$_} = $value ;
- $g{$_} = $value ;
- }
-
- ok 93, ArrayCompare (\@srt_1, [keys %h]);
- ok 94, ArrayCompare (\@srt_2, [keys %g]);
- ok 95, ArrayCompare ([qw(dd 1 3 x 2 11 abc 0)], [getValues \%g]);
- ok 96, ArrayCompare ([qw(dd 0 11 2 x 3 1 abc)], [getValues \%h]);
-
-}
-
-{
- # get_dup etc
- my $lex = new LexFile $Dfile;
- my %hh ;
-
- ok 97, my $YY = tie %hh, "BerkeleyDB::Btree", -Filename => $Dfile,
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- $hh{'Wall'} = 'Larry' ;
- $hh{'Wall'} = 'Stone' ; # Note the duplicate key
- $hh{'Wall'} = 'Brick' ; # Note the duplicate key
- $hh{'Smith'} = 'John' ;
- $hh{'mouse'} = 'mickey' ;
-
- # first work in scalar context
- ok 98, scalar $YY->get_dup('Unknown') == 0 ;
- ok 99, scalar $YY->get_dup('Smith') == 1 ;
- ok 100, scalar $YY->get_dup('Wall') == 3 ;
-
- # now in list context
- my @unknown = $YY->get_dup('Unknown') ;
- ok 101, "@unknown" eq "" ;
-
- my @smith = $YY->get_dup('Smith') ;
- ok 102, "@smith" eq "John" ;
-
- {
- my @wall = $YY->get_dup('Wall') ;
- my %wall ;
- @wall{@wall} = @wall ;
- ok 103, (@wall == 3 && $wall{'Larry'} && $wall{'Stone'} && $wall{'Brick'});
- }
-
- # hash
- my %unknown = $YY->get_dup('Unknown', 1) ;
- ok 104, keys %unknown == 0 ;
-
- my %smith = $YY->get_dup('Smith', 1) ;
- ok 105, keys %smith == 1 && $smith{'John'} ;
-
- my %wall = $YY->get_dup('Wall', 1) ;
- ok 106, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1
- && $wall{'Brick'} == 1 ;
-
- undef $YY ;
- untie %hh ;
-
-}
-
-{
- # in-memory file
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $fd ;
- my $value ;
- ok 107, my $db = tie %hash, 'BerkeleyDB::Btree' ;
-
- ok 108, $db->db_put("some key", "some value") == 0 ;
- ok 109, $db->db_get("some key", $value) == 0 ;
- ok 110, $value eq "some value" ;
-
-}
-
-{
- # partial
- # check works via API
-
- my $lex = new LexFile $Dfile ;
- my $value ;
- ok 111, my $db = new BerkeleyDB::Btree, -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db->db_put($k, $v) ;
- }
- ok 112, $ret == 0 ;
-
-
- # do a partial get
- my ($pon, $off, $len) = $db->partial_set(0,2) ;
- ok 113, ! $pon && $off == 0 && $len == 0 ;
- ok 114, $db->db_get("red", $value) == 0 && $value eq "bo" ;
- ok 115, $db->db_get("green", $value) == 0 && $value eq "ho" ;
- ok 116, $db->db_get("blue", $value) == 0 && $value eq "se" ;
-
- # do a partial get, off end of data
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 117, $pon ;
- ok 118, $off == 0 ;
- ok 119, $len == 2 ;
- ok 120, $db->db_get("red", $value) == 0 && $value eq "t" ;
- ok 121, $db->db_get("green", $value) == 0 && $value eq "se" ;
- ok 122, $db->db_get("blue", $value) == 0 && $value eq "" ;
-
- # switch of partial mode
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 123, $pon ;
- ok 124, $off == 3 ;
- ok 125, $len == 2 ;
- ok 126, $db->db_get("red", $value) == 0 && $value eq "boat" ;
- ok 127, $db->db_get("green", $value) == 0 && $value eq "house" ;
- ok 128, $db->db_get("blue", $value) == 0 && $value eq "sea" ;
-
- # now partial put
- $db->partial_set(0,2) ;
- ok 129, $db->db_put("red", "") == 0 ;
- ok 130, $db->db_put("green", "AB") == 0 ;
- ok 131, $db->db_put("blue", "XYZ") == 0 ;
- ok 132, $db->db_put("new", "KLM") == 0 ;
-
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 133, $pon ;
- ok 134, $off == 0 ;
- ok 135, $len == 2 ;
- ok 136, $db->db_get("red", $value) == 0 && $value eq "at" ;
- ok 137, $db->db_get("green", $value) == 0 && $value eq "ABuse" ;
- ok 138, $db->db_get("blue", $value) == 0 && $value eq "XYZa" ;
- ok 139, $db->db_get("new", $value) == 0 && $value eq "KLM" ;
-
- # now partial put
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 140, ! $pon ;
- ok 141, $off == 0 ;
- ok 142, $len == 0 ;
- ok 143, $db->db_put("red", "PPP") == 0 ;
- ok 144, $db->db_put("green", "Q") == 0 ;
- ok 145, $db->db_put("blue", "XYZ") == 0 ;
- ok 146, $db->db_put("new", "TU") == 0 ;
-
- $db->partial_clear() ;
- ok 147, $db->db_get("red", $value) == 0 && $value eq "at\0PPP" ;
- ok 148, $db->db_get("green", $value) == 0 && $value eq "ABuQ" ;
- ok 149, $db->db_get("blue", $value) == 0 && $value eq "XYZXYZ" ;
- ok 150, $db->db_get("new", $value) == 0 && $value eq "KLMTU" ;
-}
-
-{
- # partial
- # check works via tied hash
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
- ok 151, my $db = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- while (my ($k, $v) = each %data) {
- $hash{$k} = $v ;
- }
-
-
- # do a partial get
- $db->partial_set(0,2) ;
- ok 152, $hash{"red"} eq "bo" ;
- ok 153, $hash{"green"} eq "ho" ;
- ok 154, $hash{"blue"} eq "se" ;
-
- # do a partial get, off end of data
- $db->partial_set(3,2) ;
- ok 155, $hash{"red"} eq "t" ;
- ok 156, $hash{"green"} eq "se" ;
- ok 157, $hash{"blue"} eq "" ;
-
- # switch of partial mode
- $db->partial_clear() ;
- ok 158, $hash{"red"} eq "boat" ;
- ok 159, $hash{"green"} eq "house" ;
- ok 160, $hash{"blue"} eq "sea" ;
-
- # now partial put
- $db->partial_set(0,2) ;
- ok 161, $hash{"red"} = "" ;
- ok 162, $hash{"green"} = "AB" ;
- ok 163, $hash{"blue"} = "XYZ" ;
- ok 164, $hash{"new"} = "KLM" ;
-
- $db->partial_clear() ;
- ok 165, $hash{"red"} eq "at" ;
- ok 166, $hash{"green"} eq "ABuse" ;
- ok 167, $hash{"blue"} eq "XYZa" ;
- ok 168, $hash{"new"} eq "KLM" ;
-
- # now partial put
- $db->partial_set(3,2) ;
- ok 169, $hash{"red"} = "PPP" ;
- ok 170, $hash{"green"} = "Q" ;
- ok 171, $hash{"blue"} = "XYZ" ;
- ok 172, $hash{"new"} = "TU" ;
-
- $db->partial_clear() ;
- ok 173, $hash{"red"} eq "at\0PPP" ;
- ok 174, $hash{"green"} eq "ABuQ" ;
- ok 175, $hash{"blue"} eq "XYZXYZ" ;
- ok 176, $hash{"new"} eq "KLMTU" ;
-}
-
-{
- # transaction
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 177, mkdir($home, 0777) ;
- ok 178, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 179, my $txn = $env->txn_begin() ;
- ok 180, my $db1 = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 181, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 182, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 183, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- #ok 151, $txn->txn_abort() == 0 ;
- ok 184, (my $Z = $txn->txn_abort()) == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 185, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 186, $count == 0 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $env ;
- untie %hash ;
- rmtree $home ;
-}
-
-{
- # DB_DUP
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 187, my $db = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- $hash{'Wall'} = 'Larry' ;
- $hash{'Wall'} = 'Stone' ;
- $hash{'Smith'} = 'John' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'mouse'} = 'mickey' ;
-
- ok 188, keys %hash == 6 ;
-
- # create a cursor
- ok 189, my $cursor = $db->db_cursor() ;
-
- my $key = "Wall" ;
- my $value ;
- ok 190, $cursor->c_get($key, $value, DB_SET) == 0 ;
- ok 191, $key eq "Wall" && $value eq "Larry" ;
- ok 192, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 193, $key eq "Wall" && $value eq "Stone" ;
- ok 194, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 195, $key eq "Wall" && $value eq "Brick" ;
- ok 196, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 197, $key eq "Wall" && $value eq "Brick" ;
-
- my $ref = $db->db_stat() ;
- ok 198, ($ref->{bt_flags} | DB_DUP) == DB_DUP ;
-
- undef $db ;
- undef $cursor ;
- untie %hash ;
-
-}
-
-{
- # db_stat
-
- my $lex = new LexFile $Dfile ;
- my $recs = ($BerkeleyDB::db_version >= 3.1 ? "bt_ndata" : "bt_nrecs") ;
- my %hash ;
- my ($k, $v) ;
- ok 199, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
- -Flags => DB_CREATE,
- -Minkey =>3 ,
- -Pagesize => 2 **12
- ;
-
- my $ref = $db->db_stat() ;
- ok 200, $ref->{$recs} == 0;
- ok 201, $ref->{'bt_minkey'} == 3;
- ok 202, $ref->{'bt_pagesize'} == 2 ** 12;
-
- # create some data
- my %data = (
- "red" => 2,
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (($k, $v) = each %data) {
- $ret += $db->db_put($k, $v) ;
- }
- ok 203, $ret == 0 ;
-
- $ref = $db->db_stat() ;
- ok 204, $ref->{$recs} == 3;
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use BerkeleyDB;
- @ISA=qw(BerkeleyDB::Btree);
- @EXPORT = @BerkeleyDB::EXPORT ;
-
- sub db_put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::db_put($key, $value * 3) ;
- }
-
- sub db_get {
- my $self = shift ;
- $self->SUPER::db_get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok 205, $@ eq "" ;
- my %h ;
- my $X ;
- eval '
- $X = tie(%h, "SubDB", -Filename => "dbbtree.tmp",
- -Flags => DB_CREATE,
- -Mode => 0640 );
- ' ;
-
- main::ok 206, $@ eq "" ;
-
- my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
- main::ok 207, $@ eq "" ;
- main::ok 208, $ret == 7 ;
-
- my $value = 0;
- $ret = eval '$X->db_put("joe", 4) ; $X->db_get("joe", $value) ; return $value' ;
- main::ok 209, $@ eq "" ;
- main::ok 210, $ret == 10 ;
-
- $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
- main::ok 211, $@ eq "" ;
- main::ok 212, $ret == 1 ;
-
- $ret = eval '$X->A_new_method("joe") ' ;
- main::ok 213, $@ eq "" ;
- main::ok 214, $ret eq "[[10]]" ;
-
- unlink "SubDB.pm", "dbbtree.tmp" ;
-
-}
-
-{
- # DB_RECNUM, DB_SET_RECNO & DB_GET_RECNO
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my ($k, $v) = ("", "");
- ok 215, my $db = new BerkeleyDB::Btree
- -Filename => $Dfile,
- -Flags => DB_CREATE,
- -Property => DB_RECNUM ;
-
-
- # create some data
- my @data = (
- "A zero",
- "B one",
- "C two",
- "D three",
- "E four"
- ) ;
-
- my $ix = 0 ;
- my $ret = 0 ;
- foreach (@data) {
- $ret += $db->db_put($_, $ix) ;
- ++ $ix ;
- }
- ok 216, $ret == 0 ;
-
- # db_get & DB_SET_RECNO
- $k = 1 ;
- ok 217, $db->db_get($k, $v, DB_SET_RECNO) == 0;
- ok 218, $k eq "B one" && $v == 1 ;
-
- $k = 3 ;
- ok 219, $db->db_get($k, $v, DB_SET_RECNO) == 0;
- ok 220, $k eq "D three" && $v == 3 ;
-
- $k = 4 ;
- ok 221, $db->db_get($k, $v, DB_SET_RECNO) == 0;
- ok 222, $k eq "E four" && $v == 4 ;
-
- $k = 0 ;
- ok 223, $db->db_get($k, $v, DB_SET_RECNO) == 0;
- ok 224, $k eq "A zero" && $v == 0 ;
-
- # cursor & DB_SET_RECNO
-
- # create the cursor
- ok 225, my $cursor = $db->db_cursor() ;
-
- $k = 2 ;
- ok 226, $db->db_get($k, $v, DB_SET_RECNO) == 0;
- ok 227, $k eq "C two" && $v == 2 ;
-
- $k = 0 ;
- ok 228, $cursor->c_get($k, $v, DB_SET_RECNO) == 0;
- ok 229, $k eq "A zero" && $v == 0 ;
-
- $k = 3 ;
- ok 230, $db->db_get($k, $v, DB_SET_RECNO) == 0;
- ok 231, $k eq "D three" && $v == 3 ;
-
- # cursor & DB_GET_RECNO
- ok 232, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
- ok 233, $k eq "A zero" && $v == 0 ;
- ok 234, $cursor->c_get($k, $v, DB_GET_RECNO) == 0;
- ok 235, $v == 0 ;
-
- ok 236, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 237, $k eq "B one" && $v == 1 ;
- ok 238, $cursor->c_get($k, $v, DB_GET_RECNO) == 0;
- ok 239, $v == 1 ;
-
- ok 240, $cursor->c_get($k, $v, DB_LAST) == 0 ;
- ok 241, $k eq "E four" && $v == 4 ;
- ok 242, $cursor->c_get($k, $v, DB_GET_RECNO) == 0;
- ok 243, $v == 4 ;
-
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/db-3.0.t b/bdb/perl.BerkeleyDB/t/db-3.0.t
deleted file mode 100644
index 9c324dc7bab..00000000000
--- a/bdb/perl.BerkeleyDB/t/db-3.0.t
+++ /dev/null
@@ -1,128 +0,0 @@
-#!./perl -w
-
-# ID: 1.2, 7/17/97
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3) {
- print "1..0 # Skipped - this needs Berkeley DB 3.x or better\n" ;
- exit 0 ;
- }
-}
-
-print "1..14\n";
-
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-
-my $Dfile = "dbhash.tmp";
-
-umask(0);
-
-{
- # set_mutexlocks
-
- my $home = "./fred" ;
- ok 1, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- mkdir "./fred", 0777 ;
- chdir "./fred" ;
- ok 2, my $env = new BerkeleyDB::Env -Flags => DB_CREATE ;
- ok 3, $env->set_mutexlocks(0) == 0 ;
- chdir ".." ;
- undef $env ;
- rmtree $home ;
-}
-
-{
- # c_dup
-
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my ($k, $v) ;
- ok 4, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => 2,
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (($k, $v) = each %data) {
- $ret += $db->db_put($k, $v) ;
- }
- ok 5, $ret == 0 ;
-
- # create a cursor
- ok 6, my $cursor = $db->db_cursor() ;
-
- # point to a specific k/v pair
- $k = "green" ;
- ok 7, $cursor->c_get($k, $v, DB_SET) == 0 ;
- ok 8, $v eq "house" ;
-
- # duplicate the cursor
- my $dup_cursor = $cursor->c_dup(DB_POSITION);
- ok 9, $dup_cursor ;
-
- # move original cursor off green/house
- $cursor->c_get($k, $v, DB_NEXT) ;
- ok 10, $k ne "green" ;
- ok 11, $v ne "house" ;
-
- # duplicate cursor should still be on green/house
- ok 12, $dup_cursor->c_get($k, $v, DB_CURRENT) == 0;
- ok 13, $k eq "green" ;
- ok 14, $v eq "house" ;
-
-}
diff --git a/bdb/perl.BerkeleyDB/t/db-3.1.t b/bdb/perl.BerkeleyDB/t/db-3.1.t
deleted file mode 100644
index 35076b6cd49..00000000000
--- a/bdb/perl.BerkeleyDB/t/db-3.1.t
+++ /dev/null
@@ -1,172 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-#use Config;
-#
-#BEGIN {
-# if(-d "lib" && -f "TEST") {
-# if ($Config{'extensions'} !~ /\bBerkeleyDB\b/ ) {
-# print "1..74\n";
-# exit 0;
-# }
-# }
-#}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3.1) {
- print "1..0 # Skipping test, this needs Berkeley DB 3.1.x or better\n" ;
- exit 0 ;
- }
-}
-
-print "1..25\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
-) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-
-{
- # c_count
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 1, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- $hash{'Wall'} = 'Larry' ;
- $hash{'Wall'} = 'Stone' ;
- $hash{'Smith'} = 'John' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'mouse'} = 'mickey' ;
-
- ok 2, keys %hash == 6 ;
-
- # create a cursor
- ok 3, my $cursor = $db->db_cursor() ;
-
- my $key = "Wall" ;
- my $value ;
- ok 4, $cursor->c_get($key, $value, DB_SET) == 0 ;
- ok 5, $key eq "Wall" && $value eq "Larry" ;
-
- my $count ;
- ok 6, $cursor->c_count($count) == 0 ;
- ok 7, $count == 4 ;
-
- $key = "Smith" ;
- ok 8, $cursor->c_get($key, $value, DB_SET) == 0 ;
- ok 9, $key eq "Smith" && $value eq "John" ;
-
- ok 10, $cursor->c_count($count) == 0 ;
- ok 11, $count == 1 ;
-
-
- undef $db ;
- undef $cursor ;
- untie %hash ;
-
-}
-
-{
- # db_key_range
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 12, my $db = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- $hash{'Wall'} = 'Larry' ;
- $hash{'Wall'} = 'Stone' ;
- $hash{'Smith'} = 'John' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'mouse'} = 'mickey' ;
-
- ok 13, keys %hash == 6 ;
-
- my $key = "Wall" ;
- my ($less, $equal, $greater) ;
- ok 14, $db->db_key_range($key, $less, $equal, $greater) == 0 ;
-
- ok 15, $less != 0 ;
- ok 16, $equal != 0 ;
- ok 17, $greater != 0 ;
-
- $key = "Smith" ;
- ok 18, $db->db_key_range($key, $less, $equal, $greater) == 0 ;
-
- ok 19, $less == 0 ;
- ok 20, $equal != 0 ;
- ok 21, $greater != 0 ;
-
- $key = "NotThere" ;
- ok 22, $db->db_key_range($key, $less, $equal, $greater) == 0 ;
-
- ok 23, $less == 0 ;
- ok 24, $equal == 0 ;
- ok 25, $greater == 1 ;
-
- undef $db ;
- untie %hash ;
-
-}
diff --git a/bdb/perl.BerkeleyDB/t/db-3.2.t b/bdb/perl.BerkeleyDB/t/db-3.2.t
deleted file mode 100644
index 0cff248733c..00000000000
--- a/bdb/perl.BerkeleyDB/t/db-3.2.t
+++ /dev/null
@@ -1,90 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-#use Config;
-#
-#BEGIN {
-# if(-d "lib" && -f "TEST") {
-# if ($Config{'extensions'} !~ /\bBerkeleyDB\b/ ) {
-# print "1..74\n";
-# exit 0;
-# }
-# }
-#}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3.2) {
- print "1..0 # Skipping test, this needs Berkeley DB 3.2.x or better\n" ;
- exit 0 ;
- }
-}
-
-print "1..1\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
-) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-
-{
- # set_q_extentsize
-
- ok 1, 1 ;
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/destroy.t b/bdb/perl.BerkeleyDB/t/destroy.t
deleted file mode 100644
index e3a1e2a97c6..00000000000
--- a/bdb/perl.BerkeleyDB/t/destroy.t
+++ /dev/null
@@ -1,141 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..13\n";
-
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-
-my $Dfile = "dbhash.tmp";
-my $home = "./fred" ;
-
-umask(0);
-
-{
- # let object destroction kill everything
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- rmtree $home if -e $home ;
- ok 1, mkdir($home, 0777) ;
- ok 2, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 3, my $txn = $env->txn_begin() ;
- ok 4, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 5, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 6, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 7, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- ok 8, $txn->txn_abort() == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 9, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 10, $count == 0 ;
-
- #undef $txn ;
- #undef $cursor ;
- #undef $db1 ;
- #undef $env ;
- #untie %hash ;
-
-}
-{
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $cursor ;
- my ($k, $v) = ("", "") ;
- ok 11, my $db1 = tie %hash, 'BerkeleyDB::Hash',
- -Filename => $Dfile,
- -Flags => DB_CREATE ;
- my $count = 0 ;
- # sequence forwards
- ok 12, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 13, $count == 0 ;
-}
-
-rmtree $home ;
-
diff --git a/bdb/perl.BerkeleyDB/t/env.t b/bdb/perl.BerkeleyDB/t/env.t
deleted file mode 100644
index 5d0197f85c0..00000000000
--- a/bdb/perl.BerkeleyDB/t/env.t
+++ /dev/null
@@ -1,279 +0,0 @@
-#!./perl -w
-
-# ID: 1.2, 7/17/97
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..52\n";
-
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-
-my $Dfile = "dbhash.tmp";
-
-umask(0);
-
-{
- # db version stuff
- my ($major, $minor, $patch) = (0, 0, 0) ;
-
- ok 1, my $VER = BerkeleyDB::DB_VERSION_STRING ;
- ok 2, my $ver = BerkeleyDB::db_version($major, $minor, $patch) ;
- ok 3, $VER eq $ver ;
- ok 4, $major > 1 ;
- ok 5, defined $minor ;
- ok 6, defined $patch ;
-}
-
-{
- # Check for invalid parameters
- my $env ;
- eval ' $env = new BerkeleyDB::Env( -Stupid => 3) ; ' ;
- ok 7, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' $env = new BerkeleyDB::Env( -Bad => 2, -Home => "/tmp", -Stupid => 3) ; ' ;
- ok 8, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
-
- eval ' $env = new BerkeleyDB::Env (-Config => {"fred" => " "} ) ; ' ;
- ok 9, !$env ;
- ok 10, $BerkeleyDB::Error =~ /^illegal name-value pair/ ;
-}
-
-{
- # create a very simple environment
- my $home = "./fred" ;
- ok 11, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- mkdir "./fred", 0777 ;
- chdir "./fred" ;
- ok 12, my $env = new BerkeleyDB::Env -Flags => DB_CREATE ;
- chdir ".." ;
- undef $env ;
- rmtree $home ;
-}
-
-{
- # create an environment with a Home
- my $home = "./fred" ;
- ok 13, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- ok 14, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE ;
-
- undef $env ;
- rmtree $home ;
-}
-
-{
- # make new fail.
- my $home = "./not_there" ;
- rmtree $home ;
- ok 15, ! -d $home ;
- my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_INIT_LOCK ;
- ok 16, ! $env ;
- ok 17, $! != 0 ;
-
- rmtree $home ;
-}
-
-{
- # Config
- use Cwd ;
- my $cwd = cwd() ;
- my $home = "$cwd/fred" ;
- my $data_dir = "$home/data_dir" ;
- my $log_dir = "$home/log_dir" ;
- my $data_file = "data.db" ;
- ok 18, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- ok 19, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
- ok 20, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
- my $env = new BerkeleyDB::Env -Home => $home,
- -Config => { DB_DATA_DIR => $data_dir,
- DB_LOG_DIR => $log_dir
- },
- -Flags => DB_CREATE|DB_INIT_TXN|DB_INIT_LOG|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 21, $env ;
-
- ok 22, my $txn = $env->txn_begin() ;
-
- my %hash ;
- ok 23, tie %hash, 'BerkeleyDB::Hash', -Filename => $data_file,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
- $hash{"abc"} = 123 ;
- $hash{"def"} = 456 ;
-
- $txn->txn_commit() ;
-
- untie %hash ;
-
- undef $txn ;
- undef $env ;
- rmtree $home ;
-}
-
-{
- # -ErrFile with a filename
- my $errfile = "./errfile" ;
- my $home = "./fred" ;
- ok 24, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- my $lex = new LexFile $errfile ;
- ok 25, my $env = new BerkeleyDB::Env( -ErrFile => $errfile,
- -Flags => DB_CREATE,
- -Home => $home) ;
- my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Env => $env,
- -Flags => -1;
- ok 26, !$db ;
-
- ok 27, $BerkeleyDB::Error =~ /^illegal flag specified to (db_open|DB->open)/;
- ok 28, -e $errfile ;
- my $contents = docat($errfile) ;
- chomp $contents ;
- ok 29, $BerkeleyDB::Error eq $contents ;
-
- undef $env ;
- rmtree $home ;
-}
-
-{
- # -ErrFile with a filehandle
- use IO ;
- my $home = "./fred" ;
- ok 30, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- my $errfile = "./errfile" ;
- my $lex = new LexFile $errfile ;
- ok 31, my $ef = new IO::File ">$errfile" ;
- ok 32, my $env = new BerkeleyDB::Env( -ErrFile => $ef ,
- -Flags => DB_CREATE,
- -Home => $home) ;
- my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Env => $env,
- -Flags => -1;
- ok 33, !$db ;
-
- ok 34, $BerkeleyDB::Error =~ /^illegal flag specified to (db_open|DB->open)/;
- $ef->close() ;
- ok 35, -e $errfile ;
- my $contents = "" ;
- $contents = docat($errfile) ;
- chomp $contents ;
- ok 36, $BerkeleyDB::Error eq $contents ;
- undef $env ;
- rmtree $home ;
-}
-
-{
- # -ErrPrefix
- use IO ;
- my $home = "./fred" ;
- ok 37, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- my $errfile = "./errfile" ;
- my $lex = new LexFile $errfile ;
- ok 38, my $env = new BerkeleyDB::Env( -ErrFile => $errfile,
- -ErrPrefix => "PREFIX",
- -Flags => DB_CREATE,
- -Home => $home) ;
- my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Env => $env,
- -Flags => -1;
- ok 39, !$db ;
-
- ok 40, $BerkeleyDB::Error =~ /^PREFIX: illegal flag specified to (db_open|DB->open)/;
- ok 41, -e $errfile ;
- my $contents = docat($errfile) ;
- chomp $contents ;
- ok 42, $BerkeleyDB::Error eq $contents ;
-
- # change the prefix on the fly
- my $old = $env->errPrefix("NEW ONE") ;
- ok 43, $old eq "PREFIX" ;
-
- $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Env => $env,
- -Flags => -1;
- ok 44, !$db ;
- ok 45, $BerkeleyDB::Error =~ /^NEW ONE: illegal flag specified to (db_open|DB->open)/;
- $contents = docat($errfile) ;
- chomp $contents ;
- ok 46, $contents =~ /$BerkeleyDB::Error$/ ;
- undef $env ;
- rmtree $home ;
-}
-
-{
- # test db_appexit
- use Cwd ;
- my $cwd = cwd() ;
- my $home = "$cwd/fred" ;
- my $data_dir = "$home/data_dir" ;
- my $log_dir = "$home/log_dir" ;
- my $data_file = "data.db" ;
- ok 47, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
- ok 48, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
- ok 49, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
- my $env = new BerkeleyDB::Env -Home => $home,
- -Config => { DB_DATA_DIR => $data_dir,
- DB_LOG_DIR => $log_dir
- },
- -Flags => DB_CREATE|DB_INIT_TXN|DB_INIT_LOG|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 50, $env ;
-
- ok 51, my $txn_mgr = $env->TxnMgr() ;
-
- ok 52, $env->db_appexit() == 0 ;
-
- #rmtree $home ;
-}
-
-# test -Verbose
-# test -Flags
-# db_value_set
diff --git a/bdb/perl.BerkeleyDB/t/examples.t b/bdb/perl.BerkeleyDB/t/examples.t
deleted file mode 100644
index 4b6702d540a..00000000000
--- a/bdb/perl.BerkeleyDB/t/examples.t
+++ /dev/null
@@ -1,482 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..7\n";
-
-my $FA = 0 ;
-
-{
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- $FA = 0 ;
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
-}
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT> || "" ;
- close(CAT);
- return $result;
-}
-
-sub docat_del
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file: $!";
- my $result = <CAT> || "" ;
- close(CAT);
- unlink $file ;
- return $result;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-my $redirect = "xyzt" ;
-
-
-{
-my $x = $BerkeleyDB::Error;
-my $redirect = "xyzt" ;
- {
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
- use vars qw( %h $k $v ) ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $h{"apple"} = "red" ;
- $h{"orange"} = "orange" ;
- $h{"banana"} = "yellow" ;
- $h{"tomato"} = "red" ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $h{"banana"} ;
-
- # Delete a key/value pair.
- delete $h{"apple"} ;
-
- # print the contents of the file
- while (($k, $v) = each %h)
- { print "$k -> $v\n" }
-
- untie %h ;
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(1, docat_del($redirect) eq <<'EOM') ;
-Banana Exists
-
-orange -> orange
-tomato -> red
-banana -> yellow
-EOM
-
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("apple", "red") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("banana", "yellow") ;
- $db->db_put("tomato", "red") ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;
-
- # Delete a key/value pair.
- $db->db_del("apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(2, docat_del($redirect) eq <<'EOM') ;
-Banana Exists
-
-orange -> orange
-tomato -> red
-banana -> yellow
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "tree" ;
- unlink $filename ;
- my %h ;
- tie %h, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(3, docat_del($redirect) eq <<'EOM') ;
-Smith
-Wall
-mouse
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "tree" ;
- unlink $filename ;
- my %h ;
- tie %h, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Compare => sub { lc $_[0] cmp lc $_[1] }
- or die "Cannot open $filename: $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(4, docat_del($redirect) eq <<'EOM') ;
-mouse
-Smith
-Wall
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
-
- my %hash ;
- my $filename = "filt.db" ;
- unlink $filename ;
-
- my $db = tie %hash, 'BerkeleyDB::Hash',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- # Install DBM Filters
- $db->filter_fetch_key ( sub { s/\0$// } ) ;
- $db->filter_store_key ( sub { $_ .= "\0" } ) ;
- $db->filter_fetch_value( sub { s/\0$// } ) ;
- $db->filter_store_value( sub { $_ .= "\0" } ) ;
-
- $hash{"abc"} = "def" ;
- my $a = $hash{"ABC"} ;
- # ...
- undef $db ;
- untie %hash ;
- $db = tie %hash, 'BerkeleyDB::Hash',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
- while (($k, $v) = each %hash)
- { print "$k -> $v\n" }
- undef $db ;
- untie %hash ;
-
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(5, docat_del($redirect) eq <<"EOM") ;
-abc\x00 -> def\x00
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
- my %hash ;
- my $filename = "filt.db" ;
- unlink $filename ;
-
-
- my $db = tie %hash, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
- $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
- $hash{123} = "def" ;
- # ...
- undef $db ;
- untie %hash ;
- $db = tie %hash, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot Open $filename: $!\n" ;
- while (($k, $v) = each %hash)
- { print "$k -> $v\n" }
- undef $db ;
- untie %hash ;
-
- unlink $filename ;
- }
-
- my $val = pack("i", 123) ;
- #print "[" . docat($redirect) . "]\n" ;
- ok(6, docat_del($redirect) eq <<"EOM") ;
-$val -> def
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- if ($FA) {
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- tie @h, 'BerkeleyDB::Recno',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_RENUMBER
- or die "Cannot open $filename: $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- push @h, "green", "black" ;
-
- my $elements = scalar @h ;
- print "The array contains $elements entries\n" ;
-
- my $last = pop @h ;
- print "popped $last\n" ;
-
- unshift @h, "white" ;
- my $first = shift @h ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- untie @h ;
- unlink $filename ;
- } else {
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- my $db = tie @h, 'BerkeleyDB::Recno',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_RENUMBER
- or die "Cannot open $filename: $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- $db->push("green", "black") ;
-
- my $elements = $db->length() ;
- print "The array contains $elements entries\n" ;
-
- my $last = $db->pop ;
- print "popped $last\n" ;
-
- $db->unshift("white") ;
- my $first = $db->shift ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- undef $db ;
- untie @h ;
- unlink $filename ;
- }
-
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(7, docat_del($redirect) eq <<"EOM") ;
-The array contains 5 entries
-popped black
-shifted white
-Element 1 Exists with value blue
-EOM
-
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/examples.t.T b/bdb/perl.BerkeleyDB/t/examples.t.T
deleted file mode 100644
index fe0922318ca..00000000000
--- a/bdb/perl.BerkeleyDB/t/examples.t.T
+++ /dev/null
@@ -1,496 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..7\n";
-
-my $FA = 0 ;
-
-{
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- $FA = 0 ;
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
-}
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT> || "" ;
- close(CAT);
- return $result;
-}
-
-sub docat_del
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file: $!";
- my $result = <CAT> || "" ;
- close(CAT);
- unlink $file ;
- return $result;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-my $redirect = "xyzt" ;
-
-
-{
-my $x = $BerkeleyDB::Error;
-my $redirect = "xyzt" ;
- {
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN simpleHash
- use strict ;
- use BerkeleyDB ;
- use vars qw( %h $k $v ) ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- tie %h, "BerkeleyDB::Hash",
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $h{"apple"} = "red" ;
- $h{"orange"} = "orange" ;
- $h{"banana"} = "yellow" ;
- $h{"tomato"} = "red" ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $h{"banana"} ;
-
- # Delete a key/value pair.
- delete $h{"apple"} ;
-
- # print the contents of the file
- while (($k, $v) = each %h)
- { print "$k -> $v\n" }
-
- untie %h ;
-## END simpleHash
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(1, docat_del($redirect) eq <<'EOM') ;
-Banana Exists
-
-orange -> orange
-tomato -> red
-banana -> yellow
-EOM
-
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN simpleHash2
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("apple", "red") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("banana", "yellow") ;
- $db->db_put("tomato", "red") ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;
-
- # Delete a key/value pair.
- $db->db_del("apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
-## END simpleHash2
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(2, docat_del($redirect) eq <<'EOM') ;
-Banana Exists
-
-orange -> orange
-tomato -> red
-banana -> yellow
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN btreeSimple
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "tree" ;
- unlink $filename ;
- my %h ;
- tie %h, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
-## END btreeSimple
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(3, docat_del($redirect) eq <<'EOM') ;
-Smith
-Wall
-mouse
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN btreeSortOrder
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "tree" ;
- unlink $filename ;
- my %h ;
- tie %h, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Compare => sub { lc $_[0] cmp lc $_[1] }
- or die "Cannot open $filename: $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
-## END btreeSortOrder
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(4, docat_del($redirect) eq <<'EOM') ;
-mouse
-Smith
-Wall
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN nullFilter
- use strict ;
- use BerkeleyDB ;
-
- my %hash ;
- my $filename = "filt.db" ;
- unlink $filename ;
-
- my $db = tie %hash, 'BerkeleyDB::Hash',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- # Install DBM Filters
- $db->filter_fetch_key ( sub { s/\0$// } ) ;
- $db->filter_store_key ( sub { $_ .= "\0" } ) ;
- $db->filter_fetch_value( sub { s/\0$// } ) ;
- $db->filter_store_value( sub { $_ .= "\0" } ) ;
-
- $hash{"abc"} = "def" ;
- my $a = $hash{"ABC"} ;
- # ...
- undef $db ;
- untie %hash ;
-## END nullFilter
- $db = tie %hash, 'BerkeleyDB::Hash',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
- while (($k, $v) = each %hash)
- { print "$k -> $v\n" }
- undef $db ;
- untie %hash ;
-
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(5, docat_del($redirect) eq <<"EOM") ;
-abc\x00 -> def\x00
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN intFilter
- use strict ;
- use BerkeleyDB ;
- my %hash ;
- my $filename = "filt.db" ;
- unlink $filename ;
-
-
- my $db = tie %hash, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot open $filename: $!\n" ;
-
- $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
- $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
- $hash{123} = "def" ;
- # ...
- undef $db ;
- untie %hash ;
-## END intFilter
- $db = tie %hash, 'BerkeleyDB::Btree',
- -Filename => $filename,
- -Flags => DB_CREATE
- or die "Cannot Open $filename: $!\n" ;
- while (($k, $v) = each %hash)
- { print "$k -> $v\n" }
- undef $db ;
- untie %hash ;
-
- unlink $filename ;
- }
-
- my $val = pack("i", 123) ;
- #print "[" . docat($redirect) . "]\n" ;
- ok(6, docat_del($redirect) eq <<"EOM") ;
-$val -> def
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- if ($FA) {
-## BEGIN simpleRecno
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- tie @h, 'BerkeleyDB::Recno',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_RENUMBER
- or die "Cannot open $filename: $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- push @h, "green", "black" ;
-
- my $elements = scalar @h ;
- print "The array contains $elements entries\n" ;
-
- my $last = pop @h ;
- print "popped $last\n" ;
-
- unshift @h, "white" ;
- my $first = shift @h ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- untie @h ;
-## END simpleRecno
- unlink $filename ;
- } else {
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- my $db = tie @h, 'BerkeleyDB::Recno',
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_RENUMBER
- or die "Cannot open $filename: $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- $db->push("green", "black") ;
-
- my $elements = $db->length() ;
- print "The array contains $elements entries\n" ;
-
- my $last = $db->pop ;
- print "popped $last\n" ;
-
- $db->unshift("white") ;
- my $first = $db->shift ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- undef $db ;
- untie @h ;
- unlink $filename ;
- }
-
- }
-
- #print "[" . docat($redirect) . "]\n" ;
- ok(7, docat_del($redirect) eq <<"EOM") ;
-The array contains 5 entries
-popped black
-shifted white
-Element 1 Exists with value blue
-EOM
-
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/examples3.t b/bdb/perl.BerkeleyDB/t/examples3.t
deleted file mode 100644
index 9cc1fa72c29..00000000000
--- a/bdb/perl.BerkeleyDB/t/examples3.t
+++ /dev/null
@@ -1,213 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3) {
- print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
- exit 0 ;
- }
-}
-
-
-print "1..2\n";
-
-my $FA = 0 ;
-
-{
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- $FA = 0 ;
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
-}
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT> || "" ;
- close(CAT);
- return $result;
-}
-
-sub docat_del
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file: $!";
- my $result = <CAT> || "" ;
- close(CAT);
- unlink $file ;
- return $result;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-my $redirect = "xyzt" ;
-
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_DUP
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("red", "apple") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("green", "banana") ;
- $db->db_put("yellow", "banana") ;
- $db->db_put("red", "tomato") ;
- $db->db_put("green", "apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(1, docat_del($redirect) eq <<'EOM') ;
-orange -> orange
-yellow -> banana
-red -> apple
-red -> tomato
-green -> banana
-green -> apple
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_DUP | DB_DUPSORT
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("red", "apple") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("green", "banana") ;
- $db->db_put("yellow", "banana") ;
- $db->db_put("red", "tomato") ;
- $db->db_put("green", "apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(2, docat_del($redirect) eq <<'EOM') ;
-orange -> orange
-yellow -> banana
-red -> apple
-red -> tomato
-green -> apple
-green -> banana
-EOM
-
-}
-
-
diff --git a/bdb/perl.BerkeleyDB/t/examples3.t.T b/bdb/perl.BerkeleyDB/t/examples3.t.T
deleted file mode 100644
index 573c04903e3..00000000000
--- a/bdb/perl.BerkeleyDB/t/examples3.t.T
+++ /dev/null
@@ -1,217 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3) {
- print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
- exit 0 ;
- }
-}
-
-
-print "1..2\n";
-
-my $FA = 0 ;
-
-{
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- $FA = 0 ;
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
-}
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT> || "" ;
- close(CAT);
- return $result;
-}
-
-sub docat_del
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file: $!";
- my $result = <CAT> || "" ;
- close(CAT);
- unlink $file ;
- return $result;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-my $redirect = "xyzt" ;
-
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN dupHash
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_DUP
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("red", "apple") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("green", "banana") ;
- $db->db_put("yellow", "banana") ;
- $db->db_put("red", "tomato") ;
- $db->db_put("green", "apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
-## END dupHash
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(1, docat_del($redirect) eq <<'EOM') ;
-orange -> orange
-yellow -> banana
-red -> apple
-red -> tomato
-green -> banana
-green -> apple
-EOM
-
-}
-
-{
-my $redirect = "xyzt" ;
- {
-
- my $redirectObj = new Redirect $redirect ;
-
-## BEGIN dupSortHash
- use strict ;
- use BerkeleyDB ;
-
- my $filename = "fruit" ;
- unlink $filename ;
- my $db = new BerkeleyDB::Hash
- -Filename => $filename,
- -Flags => DB_CREATE,
- -Property => DB_DUP | DB_DUPSORT
- or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
-
- # Add a few key/value pairs to the file
- $db->db_put("red", "apple") ;
- $db->db_put("orange", "orange") ;
- $db->db_put("green", "banana") ;
- $db->db_put("yellow", "banana") ;
- $db->db_put("red", "tomato") ;
- $db->db_put("green", "apple") ;
-
- # print the contents of the file
- my ($k, $v) = ("", "") ;
- my $cursor = $db->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { print "$k -> $v\n" }
-
- undef $cursor ;
- undef $db ;
-## END dupSortHash
- unlink $filename ;
- }
-
- #print "[" . docat($redirect) . "]" ;
- ok(2, docat_del($redirect) eq <<'EOM') ;
-orange -> orange
-yellow -> banana
-red -> apple
-red -> tomato
-green -> apple
-green -> banana
-EOM
-
-}
-
-
diff --git a/bdb/perl.BerkeleyDB/t/filter.t b/bdb/perl.BerkeleyDB/t/filter.t
deleted file mode 100644
index 8bcdc7f3f90..00000000000
--- a/bdb/perl.BerkeleyDB/t/filter.t
+++ /dev/null
@@ -1,244 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..46\n";
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-my $Dfile = "dbhash.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-{
- # DBM Filter tests
- use strict ;
- my (%h, $db) ;
- my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- unlink $Dfile;
-
- sub checkOutput
- {
- my($fk, $sk, $fv, $sv) = @_ ;
- return
- $fetch_key eq $fk && $store_key eq $sk &&
- $fetch_value eq $fv && $store_value eq $sv &&
- $_ eq 'original' ;
- }
-
- ok 1, $db = tie %h, 'BerkeleyDB::Hash',
- -Filename => $Dfile,
- -Flags => DB_CREATE;
-
- $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
- $db->filter_store_key (sub { $store_key = $_ }) ;
- $db->filter_fetch_value (sub { $fetch_value = $_}) ;
- $db->filter_store_value (sub { $store_value = $_ }) ;
-
- $_ = "original" ;
-
- $h{"fred"} = "joe" ;
- # fk sk fv sv
- ok 2, checkOutput( "", "fred", "", "joe") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 3, $h{"fred"} eq "joe";
- # fk sk fv sv
- ok 4, checkOutput( "", "fred", "joe", "") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 5, $db->FIRSTKEY() eq "fred" ;
- # fk sk fv sv
- ok 6, checkOutput( "fred", "", "", "") ;
-
- # replace the filters, but remember the previous set
- my ($old_fk) = $db->filter_fetch_key
- (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
- my ($old_sk) = $db->filter_store_key
- (sub { $_ = lc $_ ; $store_key = $_ }) ;
- my ($old_fv) = $db->filter_fetch_value
- (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
- my ($old_sv) = $db->filter_store_value
- (sub { s/o/x/g; $store_value = $_ }) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"Fred"} = "Joe" ;
- # fk sk fv sv
- ok 7, checkOutput( "", "fred", "", "Jxe") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 8, $h{"Fred"} eq "[Jxe]";
- # fk sk fv sv
- ok 9, checkOutput( "", "fred", "[Jxe]", "") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 10, $db->FIRSTKEY() eq "FRED" ;
- # fk sk fv sv
- ok 11, checkOutput( "FRED", "", "", "") ;
-
- # put the original filters back
- $db->filter_fetch_key ($old_fk);
- $db->filter_store_key ($old_sk);
- $db->filter_fetch_value ($old_fv);
- $db->filter_store_value ($old_sv);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"fred"} = "joe" ;
- ok 12, checkOutput( "", "fred", "", "joe") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 13, $h{"fred"} eq "joe";
- ok 14, checkOutput( "", "fred", "joe", "") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 15, $db->FIRSTKEY() eq "fred" ;
- ok 16, checkOutput( "fred", "", "", "") ;
-
- # delete the filters
- $db->filter_fetch_key (undef);
- $db->filter_store_key (undef);
- $db->filter_fetch_value (undef);
- $db->filter_store_value (undef);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"fred"} = "joe" ;
- ok 17, checkOutput( "", "", "", "") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 18, $h{"fred"} eq "joe";
- ok 19, checkOutput( "", "", "", "") ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok 20, $db->FIRSTKEY() eq "fred" ;
- ok 21, checkOutput( "", "", "", "") ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter with a closure
-
- use strict ;
- my (%h, $db) ;
-
- unlink $Dfile;
- ok 22, $db = tie %h, 'BerkeleyDB::Hash',
- -Filename => $Dfile,
- -Flags => DB_CREATE;
-
- my %result = () ;
-
- sub Closure
- {
- my ($name) = @_ ;
- my $count = 0 ;
- my @kept = () ;
-
- return sub { ++$count ;
- push @kept, $_ ;
- $result{$name} = "$name - $count: [@kept]" ;
- }
- }
-
- $db->filter_store_key(Closure("store key")) ;
- $db->filter_store_value(Closure("store value")) ;
- $db->filter_fetch_key(Closure("fetch key")) ;
- $db->filter_fetch_value(Closure("fetch value")) ;
-
- $_ = "original" ;
-
- $h{"fred"} = "joe" ;
- ok 23, $result{"store key"} eq "store key - 1: [fred]" ;
- ok 24, $result{"store value"} eq "store value - 1: [joe]" ;
- ok 25, ! defined $result{"fetch key"} ;
- ok 26, ! defined $result{"fetch value"} ;
- ok 27, $_ eq "original" ;
-
- ok 28, $db->FIRSTKEY() eq "fred" ;
- ok 29, $result{"store key"} eq "store key - 1: [fred]" ;
- ok 30, $result{"store value"} eq "store value - 1: [joe]" ;
- ok 31, $result{"fetch key"} eq "fetch key - 1: [fred]" ;
- ok 32, ! defined $result{"fetch value"} ;
- ok 33, $_ eq "original" ;
-
- $h{"jim"} = "john" ;
- ok 34, $result{"store key"} eq "store key - 2: [fred jim]" ;
- ok 35, $result{"store value"} eq "store value - 2: [joe john]" ;
- ok 36, $result{"fetch key"} eq "fetch key - 1: [fred]" ;
- ok 37, ! defined $result{"fetch value"} ;
- ok 38, $_ eq "original" ;
-
- ok 39, $h{"fred"} eq "joe" ;
- ok 40, $result{"store key"} eq "store key - 3: [fred jim fred]" ;
- ok 41, $result{"store value"} eq "store value - 2: [joe john]" ;
- ok 42, $result{"fetch key"} eq "fetch key - 1: [fred]" ;
- ok 43, $result{"fetch value"} eq "fetch value - 1: [joe]" ;
- ok 44, $_ eq "original" ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter recursion detection
- use strict ;
- my (%h, $db) ;
- unlink $Dfile;
-
- ok 45, $db = tie %h, 'BerkeleyDB::Hash',
- -Filename => $Dfile,
- -Flags => DB_CREATE;
-
- $db->filter_store_key (sub { $_ = $h{$_} }) ;
-
- eval '$h{1} = 1234' ;
- ok 46, $@ =~ /^BerkeleyDB Aborting: recursion detected in filter_store_key at/ ;
- #print "[$@]\n" ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/hash.t b/bdb/perl.BerkeleyDB/t/hash.t
deleted file mode 100644
index 1a42c60acb2..00000000000
--- a/bdb/perl.BerkeleyDB/t/hash.t
+++ /dev/null
@@ -1,777 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-#use Config;
-#
-#BEGIN {
-# if(-d "lib" && -f "TEST") {
-# if ($Config{'extensions'} !~ /\bBerkeleyDB\b/ ) {
-# print "1..74\n";
-# exit 0;
-# }
-# }
-#}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..210\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
-) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-# Check for invalid parameters
-{
- # Check for invalid parameters
- my $db ;
- eval ' $db = new BerkeleyDB::Hash -Stupid => 3 ; ' ;
- ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' $db = new BerkeleyDB::Hash -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
- ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
-
- eval ' $db = new BerkeleyDB::Hash -Env => 2 ' ;
- ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-
- eval ' $db = new BerkeleyDB::Hash -Txn => "fred" ' ;
- ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
-
- my $obj = bless [], "main" ;
- eval ' $db = new BerkeleyDB::Hash -Env => $obj ' ;
- ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-}
-
-# Now check the interface to HASH
-
-{
- my $lex = new LexFile $Dfile ;
-
- ok 6, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my $value ;
- my $status ;
- ok 7, $db->db_put("some key", "some value") == 0 ;
- ok 8, $db->status() == 0 ;
- ok 9, $db->db_get("some key", $value) == 0 ;
- ok 10, $value eq "some value" ;
- ok 11, $db->db_put("key", "value") == 0 ;
- ok 12, $db->db_get("key", $value) == 0 ;
- ok 13, $value eq "value" ;
- ok 14, $db->db_del("some key") == 0 ;
- ok 15, ($status = $db->db_get("some key", $value)) == DB_NOTFOUND ;
- ok 16, $status eq $DB_errors{'DB_NOTFOUND'} ;
- ok 17, $db->status() == DB_NOTFOUND ;
- ok 18, $db->status() eq $DB_errors{'DB_NOTFOUND'};
-
- ok 19, $db->db_sync() == 0 ;
-
- # Check NOOVERWRITE will make put fail when attempting to overwrite
- # an existing record.
-
- ok 20, $db->db_put( 'key', 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
- ok 21, $db->status() eq $DB_errors{'DB_KEYEXIST'};
- ok 22, $db->status() == DB_KEYEXIST ;
-
- # check that the value of the key has not been changed by the
- # previous test
- ok 23, $db->db_get("key", $value) == 0 ;
- ok 24, $value eq "value" ;
-
- # test DB_GET_BOTH
- my ($k, $v) = ("key", "value") ;
- ok 25, $db->db_get($k, $v, DB_GET_BOTH) == 0 ;
-
- ($k, $v) = ("key", "fred") ;
- ok 26, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
- ($k, $v) = ("another", "value") ;
- ok 27, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
-
-}
-
-{
- # Check simple env works with a hash.
- my $lex = new LexFile $Dfile ;
-
- my $home = "./fred" ;
- ok 28, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
-
- ok 29, my $env = new BerkeleyDB::Env -Flags => DB_CREATE| DB_INIT_MPOOL,
- -Home => $home ;
- ok 30, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Env => $env,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my $value ;
- ok 31, $db->db_put("some key", "some value") == 0 ;
- ok 32, $db->db_get("some key", $value) == 0 ;
- ok 33, $value eq "some value" ;
- undef $db ;
- undef $env ;
- rmtree $home ;
-}
-
-{
- # override default hash
- my $lex = new LexFile $Dfile ;
- my $value ;
- $::count = 0 ;
- ok 34, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Hash => sub { ++$::count ; length $_[0] },
- -Flags => DB_CREATE ;
-
- ok 35, $db->db_put("some key", "some value") == 0 ;
- ok 36, $db->db_get("some key", $value) == 0 ;
- ok 37, $value eq "some value" ;
- ok 38, $::count > 0 ;
-
-}
-
-{
- # cursors
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my ($k, $v) ;
- ok 39, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => 2,
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (($k, $v) = each %data) {
- $ret += $db->db_put($k, $v) ;
- }
- ok 40, $ret == 0 ;
-
- # create the cursor
- ok 41, my $cursor = $db->db_cursor() ;
-
- $k = $v = "" ;
- my %copy = %data ;
- my $extras = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- if ( $copy{$k} eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
- ok 42, $cursor->status() == DB_NOTFOUND ;
- ok 43, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
- ok 44, keys %copy == 0 ;
- ok 45, $extras == 0 ;
-
- # sequence backwards
- %copy = %data ;
- $extras = 0 ;
- my $status ;
- for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_PREV)) {
- if ( $copy{$k} eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
- ok 46, $status == DB_NOTFOUND ;
- ok 47, $status eq $DB_errors{'DB_NOTFOUND'} ;
- ok 48, $cursor->status() == $status ;
- ok 49, $cursor->status() eq $status ;
- ok 50, keys %copy == 0 ;
- ok 51, $extras == 0 ;
-
- ($k, $v) = ("green", "house") ;
- ok 52, $cursor->c_get($k, $v, DB_GET_BOTH) == 0 ;
-
- ($k, $v) = ("green", "door") ;
- ok 53, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
- ($k, $v) = ("black", "house") ;
- ok 54, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
-
-}
-
-{
- # Tied Hash interface
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 55, tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # check "each" with an empty database
- my $count = 0 ;
- while (my ($k, $v) = each %hash) {
- ++ $count ;
- }
- ok 56, (tied %hash)->status() == DB_NOTFOUND ;
- ok 57, $count == 0 ;
-
- # Add a k/v pair
- my $value ;
- $hash{"some key"} = "some value";
- ok 58, (tied %hash)->status() == 0 ;
- ok 59, $hash{"some key"} eq "some value";
- ok 60, defined $hash{"some key"} ;
- ok 61, (tied %hash)->status() == 0 ;
- ok 62, exists $hash{"some key"} ;
- ok 63, !defined $hash{"jimmy"} ;
- ok 64, (tied %hash)->status() == DB_NOTFOUND ;
- ok 65, !exists $hash{"jimmy"} ;
- ok 66, (tied %hash)->status() == DB_NOTFOUND ;
-
- delete $hash{"some key"} ;
- ok 67, (tied %hash)->status() == 0 ;
- ok 68, ! defined $hash{"some key"} ;
- ok 69, (tied %hash)->status() == DB_NOTFOUND ;
- ok 70, ! exists $hash{"some key"} ;
- ok 71, (tied %hash)->status() == DB_NOTFOUND ;
-
- $hash{1} = 2 ;
- $hash{10} = 20 ;
- $hash{1000} = 2000 ;
-
- my ($keys, $values) = (0,0);
- $count = 0 ;
- while (my ($k, $v) = each %hash) {
- $keys += $k ;
- $values += $v ;
- ++ $count ;
- }
- ok 72, $count == 3 ;
- ok 73, $keys == 1011 ;
- ok 74, $values == 2022 ;
-
- # now clear the hash
- %hash = () ;
- ok 75, keys %hash == 0 ;
-
- untie %hash ;
-}
-
-{
- # in-memory file
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $fd ;
- my $value ;
- ok 76, my $db = tie %hash, 'BerkeleyDB::Hash' ;
-
- ok 77, $db->db_put("some key", "some value") == 0 ;
- ok 78, $db->db_get("some key", $value) == 0 ;
- ok 79, $value eq "some value" ;
-
- undef $db ;
- untie %hash ;
-}
-
-{
- # partial
- # check works via API
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
- ok 80, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db->db_put($k, $v) ;
- }
- ok 81, $ret == 0 ;
-
-
- # do a partial get
- my($pon, $off, $len) = $db->partial_set(0,2) ;
- ok 82, $pon == 0 && $off == 0 && $len == 0 ;
- ok 83, ( $db->db_get("red", $value) == 0) && $value eq "bo" ;
- ok 84, ( $db->db_get("green", $value) == 0) && $value eq "ho" ;
- ok 85, ( $db->db_get("blue", $value) == 0) && $value eq "se" ;
-
- # do a partial get, off end of data
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 86, $pon ;
- ok 87, $off == 0 ;
- ok 88, $len == 2 ;
- ok 89, $db->db_get("red", $value) == 0 && $value eq "t" ;
- ok 90, $db->db_get("green", $value) == 0 && $value eq "se" ;
- ok 91, $db->db_get("blue", $value) == 0 && $value eq "" ;
-
- # switch of partial mode
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 92, $pon ;
- ok 93, $off == 3 ;
- ok 94, $len == 2 ;
- ok 95, $db->db_get("red", $value) == 0 && $value eq "boat" ;
- ok 96, $db->db_get("green", $value) == 0 && $value eq "house" ;
- ok 97, $db->db_get("blue", $value) == 0 && $value eq "sea" ;
-
- # now partial put
- ($pon, $off, $len) = $db->partial_set(0,2) ;
- ok 98, ! $pon ;
- ok 99, $off == 0 ;
- ok 100, $len == 0 ;
- ok 101, $db->db_put("red", "") == 0 ;
- ok 102, $db->db_put("green", "AB") == 0 ;
- ok 103, $db->db_put("blue", "XYZ") == 0 ;
- ok 104, $db->db_put("new", "KLM") == 0 ;
-
- $db->partial_clear() ;
- ok 105, $db->db_get("red", $value) == 0 && $value eq "at" ;
- ok 106, $db->db_get("green", $value) == 0 && $value eq "ABuse" ;
- ok 107, $db->db_get("blue", $value) == 0 && $value eq "XYZa" ;
- ok 108, $db->db_get("new", $value) == 0 && $value eq "KLM" ;
-
- # now partial put
- $db->partial_set(3,2) ;
- ok 109, $db->db_put("red", "PPP") == 0 ;
- ok 110, $db->db_put("green", "Q") == 0 ;
- ok 111, $db->db_put("blue", "XYZ") == 0 ;
- ok 112, $db->db_put("new", "--") == 0 ;
-
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 113, $pon ;
- ok 114, $off == 3 ;
- ok 115, $len == 2 ;
- ok 116, $db->db_get("red", $value) == 0 && $value eq "at\0PPP" ;
- ok 117, $db->db_get("green", $value) == 0 && $value eq "ABuQ" ;
- ok 118, $db->db_get("blue", $value) == 0 && $value eq "XYZXYZ" ;
- ok 119, $db->db_get("new", $value) == 0 && $value eq "KLM--" ;
-}
-
-{
- # partial
- # check works via tied hash
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
- ok 120, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- while (my ($k, $v) = each %data) {
- $hash{$k} = $v ;
- }
-
-
- # do a partial get
- $db->partial_set(0,2) ;
- ok 121, $hash{"red"} eq "bo" ;
- ok 122, $hash{"green"} eq "ho" ;
- ok 123, $hash{"blue"} eq "se" ;
-
- # do a partial get, off end of data
- $db->partial_set(3,2) ;
- ok 124, $hash{"red"} eq "t" ;
- ok 125, $hash{"green"} eq "se" ;
- ok 126, $hash{"blue"} eq "" ;
-
- # switch of partial mode
- $db->partial_clear() ;
- ok 127, $hash{"red"} eq "boat" ;
- ok 128, $hash{"green"} eq "house" ;
- ok 129, $hash{"blue"} eq "sea" ;
-
- # now partial put
- $db->partial_set(0,2) ;
- ok 130, $hash{"red"} = "" ;
- ok 131, $hash{"green"} = "AB" ;
- ok 132, $hash{"blue"} = "XYZ" ;
- ok 133, $hash{"new"} = "KLM" ;
-
- $db->partial_clear() ;
- ok 134, $hash{"red"} eq "at" ;
- ok 135, $hash{"green"} eq "ABuse" ;
- ok 136, $hash{"blue"} eq "XYZa" ;
- ok 137, $hash{"new"} eq "KLM" ;
-
- # now partial put
- $db->partial_set(3,2) ;
- ok 138, $hash{"red"} = "PPP" ;
- ok 139, $hash{"green"} = "Q" ;
- ok 140, $hash{"blue"} = "XYZ" ;
- ok 141, $hash{"new"} = "TU" ;
-
- $db->partial_clear() ;
- ok 142, $hash{"red"} eq "at\0PPP" ;
- ok 143, $hash{"green"} eq "ABuQ" ;
- ok 144, $hash{"blue"} eq "XYZXYZ" ;
- ok 145, $hash{"new"} eq "KLMTU" ;
-}
-
-{
- # transaction
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 146, mkdir($home, 0777) ;
- ok 147, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 148, my $txn = $env->txn_begin() ;
- ok 149, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 150, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 151, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 152, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- ok 153, $txn->txn_abort() == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 154, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 155, $count == 0 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $env ;
- untie %hash ;
- rmtree $home ;
-}
-
-
-{
- # DB_DUP
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 156, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- $hash{'Wall'} = 'Larry' ;
- $hash{'Wall'} = 'Stone' ;
- $hash{'Smith'} = 'John' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'Wall'} = 'Brick' ;
- $hash{'mouse'} = 'mickey' ;
-
- ok 157, keys %hash == 6 ;
-
- # create a cursor
- ok 158, my $cursor = $db->db_cursor() ;
-
- my $key = "Wall" ;
- my $value ;
- ok 159, $cursor->c_get($key, $value, DB_SET) == 0 ;
- ok 160, $key eq "Wall" && $value eq "Larry" ;
- ok 161, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 162, $key eq "Wall" && $value eq "Stone" ;
- ok 163, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 164, $key eq "Wall" && $value eq "Brick" ;
- ok 165, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 166, $key eq "Wall" && $value eq "Brick" ;
-
- #my $ref = $db->db_stat() ;
- #ok 143, $ref->{bt_flags} | DB_DUP ;
-
- # test DB_DUP_NEXT
- my ($k, $v) = ("Wall", "") ;
- ok 167, $cursor->c_get($k, $v, DB_SET) == 0 ;
- ok 168, $k eq "Wall" && $v eq "Larry" ;
- ok 169, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
- ok 170, $k eq "Wall" && $v eq "Stone" ;
- ok 171, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
- ok 172, $k eq "Wall" && $v eq "Brick" ;
- ok 173, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
- ok 174, $k eq "Wall" && $v eq "Brick" ;
- ok 175, $cursor->c_get($k, $v, DB_NEXT_DUP) == DB_NOTFOUND ;
-
-
- undef $db ;
- undef $cursor ;
- untie %hash ;
-
-}
-
-{
- # DB_DUP & DupCompare
- my $lex = new LexFile $Dfile, $Dfile2;
- my ($key, $value) ;
- my (%h, %g) ;
- my @Keys = qw( 0123 9 12 -1234 9 987654321 9 def ) ;
- my @Values = qw( 1 11 3 dd x abc 2 0 ) ;
-
- ok 176, tie %h, "BerkeleyDB::Hash", -Filename => $Dfile,
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP|DB_DUPSORT,
- -Flags => DB_CREATE ;
-
- ok 177, tie %g, 'BerkeleyDB::Hash', -Filename => $Dfile2,
- -DupCompare => sub { $_[0] <=> $_[1] },
- -Property => DB_DUP|DB_DUPSORT,
- -Flags => DB_CREATE ;
-
- foreach (@Keys) {
- local $^W = 0 ;
- my $value = shift @Values ;
- $h{$_} = $value ;
- $g{$_} = $value ;
- }
-
- ok 178, my $cursor = (tied %h)->db_cursor() ;
- $key = 9 ; $value = "";
- ok 179, $cursor->c_get($key, $value, DB_SET) == 0 ;
- ok 180, $key == 9 && $value eq 11 ;
- ok 181, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 182, $key == 9 && $value == 2 ;
- ok 183, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 184, $key == 9 && $value eq "x" ;
-
- $cursor = (tied %g)->db_cursor() ;
- $key = 9 ;
- ok 185, $cursor->c_get($key, $value, DB_SET) == 0 ;
- ok 186, $key == 9 && $value eq "x" ;
- ok 187, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 188, $key == 9 && $value == 2 ;
- ok 189, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
- ok 190, $key == 9 && $value == 11 ;
-
-
-}
-
-{
- # get_dup etc
- my $lex = new LexFile $Dfile;
- my %hh ;
-
- ok 191, my $YY = tie %hh, "BerkeleyDB::Hash", -Filename => $Dfile,
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP,
- -Flags => DB_CREATE ;
-
- $hh{'Wall'} = 'Larry' ;
- $hh{'Wall'} = 'Stone' ; # Note the duplicate key
- $hh{'Wall'} = 'Brick' ; # Note the duplicate key
- $hh{'Smith'} = 'John' ;
- $hh{'mouse'} = 'mickey' ;
-
- # first work in scalar context
- ok 192, scalar $YY->get_dup('Unknown') == 0 ;
- ok 193, scalar $YY->get_dup('Smith') == 1 ;
- ok 194, scalar $YY->get_dup('Wall') == 3 ;
-
- # now in list context
- my @unknown = $YY->get_dup('Unknown') ;
- ok 195, "@unknown" eq "" ;
-
- my @smith = $YY->get_dup('Smith') ;
- ok 196, "@smith" eq "John" ;
-
- {
- my @wall = $YY->get_dup('Wall') ;
- my %wall ;
- @wall{@wall} = @wall ;
- ok 197, (@wall == 3 && $wall{'Larry'}
- && $wall{'Stone'} && $wall{'Brick'});
- }
-
- # hash
- my %unknown = $YY->get_dup('Unknown', 1) ;
- ok 198, keys %unknown == 0 ;
-
- my %smith = $YY->get_dup('Smith', 1) ;
- ok 199, keys %smith == 1 && $smith{'John'} ;
-
- my %wall = $YY->get_dup('Wall', 1) ;
- ok 200, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1
- && $wall{'Brick'} == 1 ;
-
- undef $YY ;
- untie %hh ;
-
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use BerkeleyDB;
- @ISA=qw(BerkeleyDB::Hash);
- @EXPORT = @BerkeleyDB::EXPORT ;
-
- sub db_put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::db_put($key, $value * 3) ;
- }
-
- sub db_get {
- my $self = shift ;
- $self->SUPER::db_get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok 201, $@ eq "" ;
- my %h ;
- my $X ;
- eval '
- $X = tie(%h, "SubDB", -Filename => "dbhash.tmp",
- -Flags => DB_CREATE,
- -Mode => 0640 );
- ' ;
-
- main::ok 202, $@ eq "" ;
-
- my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
- main::ok 203, $@ eq "" ;
- main::ok 204, $ret == 7 ;
-
- my $value = 0;
- $ret = eval '$X->db_put("joe", 4) ; $X->db_get("joe", $value) ; return $value' ;
- main::ok 205, $@ eq "" ;
- main::ok 206, $ret == 10 ;
-
- $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
- main::ok 207, $@ eq "" ;
- main::ok 208, $ret == 1 ;
-
- $ret = eval '$X->A_new_method("joe") ' ;
- main::ok 209, $@ eq "" ;
- main::ok 210, $ret eq "[[10]]" ;
-
- unlink "SubDB.pm", "dbhash.tmp" ;
-
-}
diff --git a/bdb/perl.BerkeleyDB/t/join.t b/bdb/perl.BerkeleyDB/t/join.t
deleted file mode 100644
index f986d76f734..00000000000
--- a/bdb/perl.BerkeleyDB/t/join.t
+++ /dev/null
@@ -1,270 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-if ($BerkeleyDB::db_ver < 2.005002)
-{
- print "1..0 # Skip: join needs Berkeley DB 2.5.2 or later\n" ;
- exit 0 ;
-}
-
-
-print "1..37\n";
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-my $Dfile1 = "dbhash1.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile1, $Dfile2, $Dfile3 ;
-
-umask(0) ;
-
-sub addData
-{
- my $db = shift ;
- my @data = @_ ;
- die "addData odd data\n" unless @data /2 != 0 ;
- my ($k, $v) ;
- my $ret = 0 ;
- while (@data) {
- $k = shift @data ;
- $v = shift @data ;
- $ret += $db->db_put($k, $v) ;
- }
-
- return ($ret == 0) ;
-}
-
-{
- # error cases
- my $lex = new LexFile $Dfile1, $Dfile2, $Dfile3 ;
- my %hash1 ;
- my $value ;
- my $status ;
- my $cursor ;
-
- ok 1, my $db1 = tie %hash1, 'BerkeleyDB::Hash',
- -Filename => $Dfile1,
- -Flags => DB_CREATE,
- -DupCompare => sub { $_[0] lt $_[1] },
- -Property => DB_DUP|DB_DUPSORT ;
-
- # no cursors supplied
- eval '$cursor = $db1->db_join() ;' ;
- ok 2, $@ =~ /Usage: \$db->BerkeleyDB::Common::db_join\Q([cursors], flags=0)/;
-
- # empty list
- eval '$cursor = $db1->db_join([]) ;' ;
- ok 3, $@ =~ /db_join: No cursors in parameter list/;
-
- # cursor list, isn't a []
- eval '$cursor = $db1->db_join({}) ;' ;
- ok 4, $@ =~ /cursors is not an array reference at/ ;
-
- eval '$cursor = $db1->db_join(\1) ;' ;
- ok 5, $@ =~ /cursors is not an array reference at/ ;
-
-}
-
-{
- # test a 2-way & 3-way join
-
- my $lex = new LexFile $Dfile1, $Dfile2, $Dfile3 ;
- my %hash1 ;
- my %hash2 ;
- my %hash3 ;
- my $value ;
- my $status ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 6, mkdir($home, 0777) ;
- ok 7, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN
- |DB_INIT_MPOOL;
- #|DB_INIT_MPOOL| DB_INIT_LOCK;
- ok 8, my $txn = $env->txn_begin() ;
- ok 9, my $db1 = tie %hash1, 'BerkeleyDB::Hash',
- -Filename => $Dfile1,
- -Flags => DB_CREATE,
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP|DB_DUPSORT,
- -Env => $env,
- -Txn => $txn ;
- ;
-
- ok 10, my $db2 = tie %hash2, 'BerkeleyDB::Hash',
- -Filename => $Dfile2,
- -Flags => DB_CREATE,
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP|DB_DUPSORT,
- -Env => $env,
- -Txn => $txn ;
-
- ok 11, my $db3 = tie %hash3, 'BerkeleyDB::Btree',
- -Filename => $Dfile3,
- -Flags => DB_CREATE,
- -DupCompare => sub { $_[0] cmp $_[1] },
- -Property => DB_DUP|DB_DUPSORT,
- -Env => $env,
- -Txn => $txn ;
-
-
- ok 12, addData($db1, qw( apple Convenience
- peach Shopway
- pear Farmer
- raspberry Shopway
- strawberry Shopway
- gooseberry Farmer
- blueberry Farmer
- ));
-
- ok 13, addData($db2, qw( red apple
- red raspberry
- red strawberry
- yellow peach
- yellow pear
- green gooseberry
- blue blueberry)) ;
-
- ok 14, addData($db3, qw( expensive apple
- reasonable raspberry
- expensive strawberry
- reasonable peach
- reasonable pear
- expensive gooseberry
- reasonable blueberry)) ;
-
- ok 15, my $cursor2 = $db2->db_cursor() ;
- my $k = "red" ;
- my $v = "" ;
- ok 16, $cursor2->c_get($k, $v, DB_SET) == 0 ;
-
- # Two way Join
- ok 17, my $cursor1 = $db1->db_join([$cursor2]) ;
-
- my %expected = qw( apple Convenience
- raspberry Shopway
- strawberry Shopway
- ) ;
-
- # sequence forwards
- while ($cursor1->c_get($k, $v) == 0) {
- delete $expected{$k}
- if defined $expected{$k} && $expected{$k} eq $v ;
- #print "[$k] [$v]\n" ;
- }
- ok 18, keys %expected == 0 ;
- ok 19, $cursor1->status() == DB_NOTFOUND ;
-
- # Three way Join
- ok 20, $cursor2 = $db2->db_cursor() ;
- $k = "red" ;
- $v = "" ;
- ok 21, $cursor2->c_get($k, $v, DB_SET) == 0 ;
-
- ok 22, my $cursor3 = $db3->db_cursor() ;
- $k = "expensive" ;
- $v = "" ;
- ok 23, $cursor3->c_get($k, $v, DB_SET) == 0 ;
- ok 24, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
-
- %expected = qw( apple Convenience
- strawberry Shopway
- ) ;
-
- # sequence forwards
- while ($cursor1->c_get($k, $v) == 0) {
- delete $expected{$k}
- if defined $expected{$k} && $expected{$k} eq $v ;
- #print "[$k] [$v]\n" ;
- }
- ok 25, keys %expected == 0 ;
- ok 26, $cursor1->status() == DB_NOTFOUND ;
-
- # test DB_JOIN_ITEM
- # #################
- ok 27, $cursor2 = $db2->db_cursor() ;
- $k = "red" ;
- $v = "" ;
- ok 28, $cursor2->c_get($k, $v, DB_SET) == 0 ;
-
- ok 29, $cursor3 = $db3->db_cursor() ;
- $k = "expensive" ;
- $v = "" ;
- ok 30, $cursor3->c_get($k, $v, DB_SET) == 0 ;
- ok 31, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
-
- %expected = qw( apple 1
- strawberry 1
- ) ;
-
- # sequence forwards
- $k = "" ;
- $v = "" ;
- while ($cursor1->c_get($k, $v, DB_JOIN_ITEM) == 0) {
- delete $expected{$k}
- if defined $expected{$k} ;
- #print "[$k]\n" ;
- }
- ok 32, keys %expected == 0 ;
- ok 33, $cursor1->status() == DB_NOTFOUND ;
-
- ok 34, $cursor1->c_close() == 0 ;
- ok 35, $cursor2->c_close() == 0 ;
- ok 36, $cursor3->c_close() == 0 ;
-
- ok 37, ($status = $txn->txn_commit) == 0;
-
- undef $txn ;
- #undef $cursor1;
- #undef $cursor2;
- #undef $cursor3;
- undef $db1 ;
- undef $db2 ;
- undef $db3 ;
- undef $env ;
- untie %hash1 ;
- untie %hash2 ;
- untie %hash3 ;
- rmtree $home ;
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/mldbm.t b/bdb/perl.BerkeleyDB/t/mldbm.t
deleted file mode 100644
index eb6673b35f5..00000000000
--- a/bdb/perl.BerkeleyDB/t/mldbm.t
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/perl -w
-
-BEGIN
-{
- if ($] < 5.005) {
- print "1..0 # This is Perl $], skipping test\n" ;
- exit 0 ;
- }
-
- eval { require Data::Dumper ; };
- if ($@) {
- print "1..0 # Data::Dumper is not installed on this system.\n";
- exit 0 ;
- }
- if ($Data::Dumper::VERSION < 2.08) {
- print "1..0 # Data::Dumper 2.08 or better required (found $Data::Dumper::VERSION).\n";
- exit 0 ;
- }
- eval { require MLDBM ; };
- if ($@) {
- print "1..0 # MLDBM is not installed on this system.\n";
- exit 0 ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-print "1..12\n";
-
-{
-package BTREE ;
-
-use BerkeleyDB ;
-use MLDBM qw(BerkeleyDB::Btree) ;
-use Data::Dumper;
-
-$filename = 'testmldbm' ;
-
-unlink $filename ;
-$MLDBM::UseDB = "BerkeleyDB::Btree" ;
-$db = tie %o, MLDBM, -Filename => $filename,
- -Flags => DB_CREATE
- or die $!;
-::ok 1, $db ;
-::ok 2, $db->type() == DB_BTREE ;
-
-$c = [\'c'];
-$b = {};
-$a = [1, $b, $c];
-$b->{a} = $a;
-$b->{b} = $a->[1];
-$b->{c} = $a->[2];
-@o{qw(a b c)} = ($a, $b, $c);
-$o{d} = "{once upon a time}";
-$o{e} = 1024;
-$o{f} = 1024.1024;
-$first = Data::Dumper->new([@o{qw(a b c)}], [qw(a b c)])->Quotekeys(0)->Dump;
-$second = <<'EOT';
-$a = [
- 1,
- {
- a => $a,
- b => $a->[1],
- c => [
- \'c'
- ]
- },
- $a->[1]{c}
- ];
-$b = {
- a => [
- 1,
- $b,
- [
- \'c'
- ]
- ],
- b => $b,
- c => $b->{a}[2]
- };
-$c = [
- \'c'
- ];
-EOT
-
-::ok 3, $first eq $second ;
-::ok 4, $o{d} eq "{once upon a time}" ;
-::ok 5, $o{e} == 1024 ;
-::ok 6, $o{f} eq 1024.1024 ;
-
-unlink $filename ;
-}
-
-{
-
-package HASH ;
-
-use BerkeleyDB ;
-use MLDBM qw(BerkeleyDB::Hash) ;
-use Data::Dumper;
-
-$filename = 'testmldbm' ;
-
-unlink $filename ;
-$MLDBM::UseDB = "BerkeleyDB::Hash" ;
-$db = tie %o, MLDBM, -Filename => $filename,
- -Flags => DB_CREATE
- or die $!;
-::ok 7, $db ;
-::ok 8, $db->type() == DB_HASH ;
-
-
-$c = [\'c'];
-$b = {};
-$a = [1, $b, $c];
-$b->{a} = $a;
-$b->{b} = $a->[1];
-$b->{c} = $a->[2];
-@o{qw(a b c)} = ($a, $b, $c);
-$o{d} = "{once upon a time}";
-$o{e} = 1024;
-$o{f} = 1024.1024;
-$first = Data::Dumper->new([@o{qw(a b c)}], [qw(a b c)])->Quotekeys(0)->Dump;
-$second = <<'EOT';
-$a = [
- 1,
- {
- a => $a,
- b => $a->[1],
- c => [
- \'c'
- ]
- },
- $a->[1]{c}
- ];
-$b = {
- a => [
- 1,
- $b,
- [
- \'c'
- ]
- ],
- b => $b,
- c => $b->{a}[2]
- };
-$c = [
- \'c'
- ];
-EOT
-
-::ok 9, $first eq $second ;
-::ok 10, $o{d} eq "{once upon a time}" ;
-::ok 11, $o{e} == 1024 ;
-::ok 12, $o{f} eq 1024.1024 ;
-
-unlink $filename ;
-
-}
diff --git a/bdb/perl.BerkeleyDB/t/queue.t b/bdb/perl.BerkeleyDB/t/queue.t
deleted file mode 100644
index 0f459a43a69..00000000000
--- a/bdb/perl.BerkeleyDB/t/queue.t
+++ /dev/null
@@ -1,837 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3) {
- print "1..0 # Skipping test, Queue needs Berkeley DB 3.x or better\n" ;
- exit 0 ;
- }
-}
-
-print "1..197\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION'=> "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY'=> "DB_RUNRECOVERY: Fatal error, run database recovery",
- ) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-sub touch
-{
- my $file = shift ;
- open(CAT,">$file") || die "Cannot open $file:$!";
- close(CAT);
-}
-
-sub joiner
-{
- my $db = shift ;
- my $sep = shift ;
- my ($k, $v) = (0, "") ;
- my @data = () ;
-
- my $cursor = $db->db_cursor() or return () ;
- for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_NEXT)) {
- push @data, $v ;
- }
-
- (scalar(@data), join($sep, @data)) ;
-}
-
-sub countRecords
-{
- my $db = shift ;
- my ($k, $v) = (0,0) ;
- my ($count) = 0 ;
- my ($cursor) = $db->db_cursor() ;
- #for ($status = $cursor->c_get($k, $v, DB_FIRST) ;
-# $status == 0 ;
-# $status = $cursor->c_get($k, $v, DB_NEXT) )
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { ++ $count }
-
- return $count ;
-}
-
-sub fillout
-{
- my $var = shift ;
- my $length = shift ;
- my $pad = shift || " " ;
- my $template = $pad x $length ;
- substr($template, 0, length($var)) = $var ;
- return $template ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-# Check for invalid parameters
-{
- # Check for invalid parameters
- my $db ;
- eval ' $db = new BerkeleyDB::Queue -Stupid => 3 ; ' ;
- ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' $db = new BerkeleyDB::Queue -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
- ok 2, $@ =~ /unknown key value\(s\) / ;
-
- eval ' $db = new BerkeleyDB::Queue -Env => 2 ' ;
- ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-
- eval ' $db = new BerkeleyDB::Queue -Txn => "x" ' ;
- ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
-
- my $obj = bless [], "main" ;
- eval ' $db = new BerkeleyDB::Queue -Env => $obj ' ;
- ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-}
-
-# Now check the interface to Queue
-
-{
- my $lex = new LexFile $Dfile ;
- my $rec_len = 10 ;
- my $pad = "x" ;
-
- ok 6, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
- -Flags => DB_CREATE,
- -Len => $rec_len,
- -Pad => $pad;
-
- # Add a k/v pair
- my $value ;
- my $status ;
- ok 7, $db->db_put(1, "some value") == 0 ;
- ok 8, $db->status() == 0 ;
- ok 9, $db->db_get(1, $value) == 0 ;
- ok 10, $value eq fillout("some value", $rec_len, $pad) ;
- ok 11, $db->db_put(2, "value") == 0 ;
- ok 12, $db->db_get(2, $value) == 0 ;
- ok 13, $value eq fillout("value", $rec_len, $pad) ;
- ok 14, $db->db_del(1) == 0 ;
- ok 15, ($status = $db->db_get(1, $value)) == DB_KEYEMPTY ;
- ok 16, $db->status() == DB_KEYEMPTY ;
- ok 17, $db->status() eq $DB_errors{'DB_KEYEMPTY'} ;
-
- ok 18, ($status = $db->db_get(7, $value)) == DB_NOTFOUND ;
- ok 19, $db->status() == DB_NOTFOUND ;
- ok 20, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
-
- ok 21, $db->db_sync() == 0 ;
-
- # Check NOOVERWRITE will make put fail when attempting to overwrite
- # an existing record.
-
- ok 22, $db->db_put( 2, 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
- ok 23, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
- ok 24, $db->status() == DB_KEYEXIST ;
-
-
- # check that the value of the key has not been changed by the
- # previous test
- ok 25, $db->db_get(2, $value) == 0 ;
- ok 26, $value eq fillout("value", $rec_len, $pad) ;
-
-
-}
-
-
-{
- # Check simple env works with a array.
- # and pad defaults to space
- my $lex = new LexFile $Dfile ;
-
- my $home = "./fred" ;
- my $rec_len = 11 ;
- ok 27, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
-
- ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
- -Home => $home ;
-
- ok 29, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
- -Env => $env,
- -Flags => DB_CREATE,
- -Len => $rec_len;
-
- # Add a k/v pair
- my $value ;
- ok 30, $db->db_put(1, "some value") == 0 ;
- ok 31, $db->db_get(1, $value) == 0 ;
- ok 32, $value eq fillout("some value", $rec_len) ;
- undef $db ;
- undef $env ;
- rmtree $home ;
-}
-
-
-{
- # cursors
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my ($k, $v) ;
- my $rec_len = 5 ;
- ok 33, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Len => $rec_len;
-
- # create some data
- my @data = (
- "red" ,
- "green" ,
- "blue" ,
- ) ;
-
- my $i ;
- my %data ;
- my $ret = 0 ;
- for ($i = 0 ; $i < @data ; ++$i) {
- $ret += $db->db_put($i, $data[$i]) ;
- $data{$i} = $data[$i] ;
- }
- ok 34, $ret == 0 ;
-
- # create the cursor
- ok 35, my $cursor = $db->db_cursor() ;
-
- $k = 0 ; $v = "" ;
- my %copy = %data;
- my $extras = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- {
- if ( fillout($copy{$k}, $rec_len) eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
-
- ok 36, $cursor->status() == DB_NOTFOUND ;
- ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
- ok 38, keys %copy == 0 ;
- ok 39, $extras == 0 ;
-
- # sequence backwards
- %copy = %data ;
- $extras = 0 ;
- my $status ;
- for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_PREV)) {
- if ( fillout($copy{$k}, $rec_len) eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
- ok 40, $status == DB_NOTFOUND ;
- ok 41, $status eq $DB_errors{'DB_NOTFOUND'} ;
- ok 42, $cursor->status() == $status ;
- ok 43, $cursor->status() eq $status ;
- ok 44, keys %copy == 0 ;
- ok 45, $extras == 0 ;
-}
-
-{
- # Tied Array interface
-
- # full tied array support started in Perl 5.004_57
- # just double check.
- my $FA = 0 ;
- {
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
- }
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my $db ;
- my $rec_len = 10 ;
- ok 46, $db = tie @array, 'BerkeleyDB::Queue', -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Len => $rec_len;
-
- ok 47, my $cursor = (tied @array)->db_cursor() ;
- # check the database is empty
- my $count = 0 ;
- my ($k, $v) = (0,"") ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 48, $cursor->status() == DB_NOTFOUND ;
- ok 49, $count == 0 ;
-
- ok 50, @array == 0 ;
-
- # Add a k/v pair
- my $value ;
- $array[1] = "some value";
- ok 51, (tied @array)->status() == 0 ;
- ok 52, $array[1] eq fillout("some value", $rec_len);
- ok 53, defined $array[1];
- ok 54, (tied @array)->status() == 0 ;
- ok 55, !defined $array[3];
- ok 56, (tied @array)->status() == DB_NOTFOUND ;
-
- ok 57, (tied @array)->db_del(1) == 0 ;
- ok 58, (tied @array)->status() == 0 ;
- ok 59, ! defined $array[1];
- ok 60, (tied @array)->status() == DB_KEYEMPTY ;
-
- $array[1] = 2 ;
- $array[10] = 20 ;
- $array[1000] = 2000 ;
-
- my ($keys, $values) = (0,0);
- $count = 0 ;
- for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_NEXT)) {
- $keys += $k ;
- $values += $v ;
- ++ $count ;
- }
- ok 61, $count == 3 ;
- ok 62, $keys == 1011 ;
- ok 63, $values == 2022 ;
-
- # unshift isn't allowed
-# eval {
-# $FA ? unshift @array, "red", "green", "blue"
-# : $db->unshift("red", "green", "blue" ) ;
-# } ;
-# ok 64, $@ =~ /^unshift is unsupported with Queue databases/ ;
- $array[0] = "red" ;
- $array[1] = "green" ;
- $array[2] = "blue" ;
- $array[4] = 2 ;
- ok 64, $array[0] eq fillout("red", $rec_len) ;
- ok 65, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
- ok 66, $k == 0 ;
- ok 67, $v eq fillout("red", $rec_len) ;
- ok 68, $array[1] eq fillout("green", $rec_len) ;
- ok 69, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 70, $k == 1 ;
- ok 71, $v eq fillout("green", $rec_len) ;
- ok 72, $array[2] eq fillout("blue", $rec_len) ;
- ok 73, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 74, $k == 2 ;
- ok 75, $v eq fillout("blue", $rec_len) ;
- ok 76, $array[4] == 2 ;
- ok 77, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 78, $k == 4 ;
- ok 79, $v == 2 ;
-
- # shift
- ok 80, ($FA ? shift @array : $db->shift()) eq fillout("red", $rec_len) ;
- ok 81, ($FA ? shift @array : $db->shift()) eq fillout("green", $rec_len) ;
- ok 82, ($FA ? shift @array : $db->shift()) eq fillout("blue", $rec_len) ;
- ok 83, ($FA ? shift @array : $db->shift()) == 2 ;
-
- # push
- $FA ? push @array, "the", "end"
- : $db->push("the", "end") ;
- ok 84, $cursor->c_get($k, $v, DB_LAST) == 0 ;
- ok 85, $k == 1002 ;
- ok 86, $v eq fillout("end", $rec_len) ;
- ok 87, $cursor->c_get($k, $v, DB_PREV) == 0 ;
- ok 88, $k == 1001 ;
- ok 89, $v eq fillout("the", $rec_len) ;
- ok 90, $cursor->c_get($k, $v, DB_PREV) == 0 ;
- ok 91, $k == 1000 ;
- ok 92, $v == 2000 ;
-
- # pop
- ok 93, ( $FA ? pop @array : $db->pop ) eq fillout("end", $rec_len) ;
- ok 94, ( $FA ? pop @array : $db->pop ) eq fillout("the", $rec_len) ;
- ok 95, ( $FA ? pop @array : $db->pop ) == 2000 ;
-
- # now clear the array
- $FA ? @array = ()
- : $db->clear() ;
- ok 96, $cursor->c_get($k, $v, DB_FIRST) == DB_NOTFOUND ;
-
- undef $cursor ;
- undef $db ;
- untie @array ;
-}
-
-{
- # in-memory file
-
- my @array ;
- my $fd ;
- my $value ;
- my $rec_len = 15 ;
- ok 97, my $db = tie @array, 'BerkeleyDB::Queue',
- -Len => $rec_len;
-
- ok 98, $db->db_put(1, "some value") == 0 ;
- ok 99, $db->db_get(1, $value) == 0 ;
- ok 100, $value eq fillout("some value", $rec_len) ;
-
-}
-
-{
- # partial
- # check works via API
-
- my $lex = new LexFile $Dfile ;
- my $value ;
- my $rec_len = 8 ;
- ok 101, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Len => $rec_len,
- -Pad => " " ;
-
- # create some data
- my @data = (
- "",
- "boat",
- "house",
- "sea",
- ) ;
-
- my $ret = 0 ;
- my $i ;
- for ($i = 0 ; $i < @data ; ++$i) {
- my $r = $db->db_put($i, $data[$i]) ;
- $ret += $r ;
- }
- ok 102, $ret == 0 ;
-
- # do a partial get
- my ($pon, $off, $len) = $db->partial_set(0,2) ;
- ok 103, ! $pon && $off == 0 && $len == 0 ;
- ok 104, $db->db_get(1, $value) == 0 && $value eq "bo" ;
- ok 105, $db->db_get(2, $value) == 0 && $value eq "ho" ;
- ok 106, $db->db_get(3, $value) == 0 && $value eq "se" ;
-
- # do a partial get, off end of data
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 107, $pon ;
- ok 108, $off == 0 ;
- ok 109, $len == 2 ;
- ok 110, $db->db_get(1, $value) == 0 && $value eq fillout("t", 2) ;
- ok 111, $db->db_get(2, $value) == 0 && $value eq "se" ;
- ok 112, $db->db_get(3, $value) == 0 && $value eq " " ;
-
- # switch of partial mode
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 113, $pon ;
- ok 114, $off == 3 ;
- ok 115, $len == 2 ;
- ok 116, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
- ok 117, $db->db_get(2, $value) == 0 && $value eq fillout("house", $rec_len) ;
- ok 118, $db->db_get(3, $value) == 0 && $value eq fillout("sea", $rec_len) ;
-
- # now partial put
- $db->partial_set(0,2) ;
- ok 119, $db->db_put(1, "") != 0 ;
- ok 120, $db->db_put(2, "AB") == 0 ;
- ok 121, $db->db_put(3, "XY") == 0 ;
- ok 122, $db->db_put(4, "KLM") != 0 ;
- ok 123, $db->db_put(4, "KL") == 0 ;
-
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 124, $pon ;
- ok 125, $off == 0 ;
- ok 126, $len == 2 ;
- ok 127, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
- ok 128, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse", $rec_len) ;
- ok 129, $db->db_get(3, $value) == 0 && $value eq fillout("XYa", $rec_len) ;
- ok 130, $db->db_get(4, $value) == 0 && $value eq fillout("KL", $rec_len) ;
-
- # now partial put
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 131, ! $pon ;
- ok 132, $off == 0 ;
- ok 133, $len == 0 ;
- ok 134, $db->db_put(1, "PP") == 0 ;
- ok 135, $db->db_put(2, "Q") != 0 ;
- ok 136, $db->db_put(3, "XY") == 0 ;
- ok 137, $db->db_put(4, "TU") == 0 ;
-
- $db->partial_clear() ;
- ok 138, $db->db_get(1, $value) == 0 && $value eq fillout("boaPP", $rec_len) ;
- ok 139, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse",$rec_len) ;
- ok 140, $db->db_get(3, $value) == 0 && $value eq fillout("XYaXY", $rec_len) ;
- ok 141, $db->db_get(4, $value) == 0 && $value eq fillout("KL TU", $rec_len) ;
-}
-
-{
- # partial
- # check works via tied array
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my $value ;
- my $rec_len = 8 ;
- ok 142, my $db = tie @array, 'BerkeleyDB::Queue', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Len => $rec_len,
- -Pad => " " ;
-
- # create some data
- my @data = (
- "",
- "boat",
- "house",
- "sea",
- ) ;
-
- my $i ;
- my $status = 0 ;
- for ($i = 1 ; $i < @data ; ++$i) {
- $array[$i] = $data[$i] ;
- $status += $db->status() ;
- }
-
- ok 143, $status == 0 ;
-
- # do a partial get
- $db->partial_set(0,2) ;
- ok 144, $array[1] eq fillout("bo", 2) ;
- ok 145, $array[2] eq fillout("ho", 2) ;
- ok 146, $array[3] eq fillout("se", 2) ;
-
- # do a partial get, off end of data
- $db->partial_set(3,2) ;
- ok 147, $array[1] eq fillout("t", 2) ;
- ok 148, $array[2] eq fillout("se", 2) ;
- ok 149, $array[3] eq fillout("", 2) ;
-
- # switch of partial mode
- $db->partial_clear() ;
- ok 150, $array[1] eq fillout("boat", $rec_len) ;
- ok 151, $array[2] eq fillout("house", $rec_len) ;
- ok 152, $array[3] eq fillout("sea", $rec_len) ;
-
- # now partial put
- $db->partial_set(0,2) ;
- $array[1] = "" ;
- ok 153, $db->status() != 0 ;
- $array[2] = "AB" ;
- ok 154, $db->status() == 0 ;
- $array[3] = "XY" ;
- ok 155, $db->status() == 0 ;
- $array[4] = "KL" ;
- ok 156, $db->status() == 0 ;
-
- $db->partial_clear() ;
- ok 157, $array[1] eq fillout("boat", $rec_len) ;
- ok 158, $array[2] eq fillout("ABuse", $rec_len) ;
- ok 159, $array[3] eq fillout("XYa", $rec_len) ;
- ok 160, $array[4] eq fillout("KL", $rec_len) ;
-
- # now partial put
- $db->partial_set(3,2) ;
- $array[1] = "PP" ;
- ok 161, $db->status() == 0 ;
- $array[2] = "Q" ;
- ok 162, $db->status() != 0 ;
- $array[3] = "XY" ;
- ok 163, $db->status() == 0 ;
- $array[4] = "TU" ;
- ok 164, $db->status() == 0 ;
-
- $db->partial_clear() ;
- ok 165, $array[1] eq fillout("boaPP", $rec_len) ;
- ok 166, $array[2] eq fillout("ABuse", $rec_len) ;
- ok 167, $array[3] eq fillout("XYaXY", $rec_len) ;
- ok 168, $array[4] eq fillout("KL TU", $rec_len) ;
-}
-
-{
- # transaction
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 169, mkdir($home, 0777) ;
- my $rec_len = 9 ;
- ok 170, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 171, my $txn = $env->txn_begin() ;
- ok 172, my $db1 = tie @array, 'BerkeleyDB::Queue',
- -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ,
- -Len => $rec_len,
- -Pad => " " ;
-
-
- # create some data
- my @data = (
- "boat",
- "house",
- "sea",
- ) ;
-
- my $ret = 0 ;
- my $i ;
- for ($i = 0 ; $i < @data ; ++$i) {
- $ret += $db1->db_put($i, $data[$i]) ;
- }
- ok 173, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 174, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = (0, "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 175, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- ok 176, $txn->txn_abort() == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 177, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 178, $count == 0 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $env ;
- untie @array ;
- rmtree $home ;
-}
-
-
-{
- # db_stat
-
- my $lex = new LexFile $Dfile ;
- my $recs = ($BerkeleyDB::db_version >= 3.1 ? "qs_ndata" : "qs_nrecs") ;
- my @array ;
- my ($k, $v) ;
- my $rec_len = 7 ;
- ok 179, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
- -Flags => DB_CREATE,
- -Pagesize => 4 * 1024,
- -Len => $rec_len,
- -Pad => " "
- ;
-
- my $ref = $db->db_stat() ;
- ok 180, $ref->{$recs} == 0;
- ok 181, $ref->{'qs_pagesize'} == 4 * 1024;
-
- # create some data
- my @data = (
- 2,
- "house",
- "sea",
- ) ;
-
- my $ret = 0 ;
- my $i ;
- for ($i = $db->ArrayOffset ; @data ; ++$i) {
- $ret += $db->db_put($i, shift @data) ;
- }
- ok 182, $ret == 0 ;
-
- $ref = $db->db_stat() ;
- ok 183, $ref->{$recs} == 3;
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use BerkeleyDB;
- @ISA=qw(BerkeleyDB::Queue);
- @EXPORT = @BerkeleyDB::EXPORT ;
-
- sub db_put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::db_put($key, $value * 3) ;
- }
-
- sub db_get {
- my $self = shift ;
- $self->SUPER::db_get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok 184, $@ eq "" ;
- my @h ;
- my $X ;
- my $rec_len = 34 ;
- eval '
- $X = tie(@h, "SubDB", -Filename => "dbbtree.tmp",
- -Flags => DB_CREATE,
- -Mode => 0640 ,
- -Len => $rec_len,
- -Pad => " "
- );
- ' ;
-
- main::ok 185, $@ eq "" ;
-
- my $ret = eval '$h[1] = 3 ; return $h[1] ' ;
- main::ok 186, $@ eq "" ;
- main::ok 187, $ret == 7 ;
-
- my $value = 0;
- $ret = eval '$X->db_put(1, 4) ; $X->db_get(1, $value) ; return $value' ;
- main::ok 188, $@ eq "" ;
- main::ok 189, $ret == 10 ;
-
- $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
- main::ok 190, $@ eq "" ;
- main::ok 191, $ret == 1 ;
-
- $ret = eval '$X->A_new_method(1) ' ;
- main::ok 192, $@ eq "" ;
- main::ok 193, $ret eq "[[10]]" ;
-
- unlink "SubDB.pm", "dbbtree.tmp" ;
-
-}
-
-{
- # DB_APPEND
-
- my $lex = new LexFile $Dfile;
- my @array ;
- my $value ;
- my $rec_len = 21 ;
- ok 194, my $db = tie @array, 'BerkeleyDB::Queue',
- -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Len => $rec_len,
- -Pad => " " ;
-
- # create a few records
- $array[1] = "def" ;
- $array[3] = "ghi" ;
-
- my $k = 0 ;
- ok 195, $db->db_put($k, "fred", DB_APPEND) == 0 ;
- ok 196, $k == 4 ;
- ok 197, $array[4] eq fillout("fred", $rec_len) ;
-
- undef $db ;
- untie @array ;
-}
-
-__END__
-
-
-# TODO
-#
-# DB_DELIMETER DB_FIXEDLEN DB_PAD DB_SNAPSHOT with partial records
diff --git a/bdb/perl.BerkeleyDB/t/recno.t b/bdb/perl.BerkeleyDB/t/recno.t
deleted file mode 100644
index 0f210f540c3..00000000000
--- a/bdb/perl.BerkeleyDB/t/recno.t
+++ /dev/null
@@ -1,967 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..218\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
-) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-sub touch
-{
- my $file = shift ;
- open(CAT,">$file") || die "Cannot open $file:$!";
- close(CAT);
-}
-
-sub joiner
-{
- my $db = shift ;
- my $sep = shift ;
- my ($k, $v) = (0, "") ;
- my @data = () ;
-
- my $cursor = $db->db_cursor() or return () ;
- for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_NEXT)) {
- push @data, $v ;
- }
-
- (scalar(@data), join($sep, @data)) ;
-}
-
-sub countRecords
-{
- my $db = shift ;
- my ($k, $v) = (0,0) ;
- my ($count) = 0 ;
- my ($cursor) = $db->db_cursor() ;
- #for ($status = $cursor->c_get($k, $v, DB_FIRST) ;
-# $status == 0 ;
-# $status = $cursor->c_get($k, $v, DB_NEXT) )
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- { ++ $count }
-
- return $count ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-# Check for invalid parameters
-{
- # Check for invalid parameters
- my $db ;
- eval ' $db = new BerkeleyDB::Recno -Stupid => 3 ; ' ;
- ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' $db = new BerkeleyDB::Recno -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
- ok 2, $@ =~ /unknown key value\(s\) / ;
-
- eval ' $db = new BerkeleyDB::Recno -Env => 2 ' ;
- ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-
- eval ' $db = new BerkeleyDB::Recno -Txn => "x" ' ;
- ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
-
- my $obj = bless [], "main" ;
- eval ' $db = new BerkeleyDB::Recno -Env => $obj ' ;
- ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-}
-
-# Now check the interface to Recno
-
-{
- my $lex = new LexFile $Dfile ;
-
- ok 6, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my $value ;
- my $status ;
- ok 7, $db->db_put(1, "some value") == 0 ;
- ok 8, $db->status() == 0 ;
- ok 9, $db->db_get(1, $value) == 0 ;
- ok 10, $value eq "some value" ;
- ok 11, $db->db_put(2, "value") == 0 ;
- ok 12, $db->db_get(2, $value) == 0 ;
- ok 13, $value eq "value" ;
- ok 14, $db->db_del(1) == 0 ;
- ok 15, ($status = $db->db_get(1, $value)) == DB_KEYEMPTY ;
- ok 16, $db->status() == DB_KEYEMPTY ;
- ok 17, $db->status() eq $DB_errors{'DB_KEYEMPTY'} ;
-
- ok 18, ($status = $db->db_get(7, $value)) == DB_NOTFOUND ;
- ok 19, $db->status() == DB_NOTFOUND ;
- ok 20, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
-
- ok 21, $db->db_sync() == 0 ;
-
- # Check NOOVERWRITE will make put fail when attempting to overwrite
- # an existing record.
-
- ok 22, $db->db_put( 2, 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
- ok 23, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
- ok 24, $db->status() == DB_KEYEXIST ;
-
-
- # check that the value of the key has not been changed by the
- # previous test
- ok 25, $db->db_get(2, $value) == 0 ;
- ok 26, $value eq "value" ;
-
-
-}
-
-
-{
- # Check simple env works with a array.
- my $lex = new LexFile $Dfile ;
-
- my $home = "./fred" ;
- ok 27, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
-
- ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
- -Home => $home ;
-
- ok 29, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
- -Env => $env,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my $value ;
- ok 30, $db->db_put(1, "some value") == 0 ;
- ok 31, $db->db_get(1, $value) == 0 ;
- ok 32, $value eq "some value" ;
- undef $db ;
- undef $env ;
- rmtree $home ;
-}
-
-
-{
- # cursors
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my ($k, $v) ;
- ok 33, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ;
-
- # create some data
- my @data = (
- "red" ,
- "green" ,
- "blue" ,
- ) ;
-
- my $i ;
- my %data ;
- my $ret = 0 ;
- for ($i = 0 ; $i < @data ; ++$i) {
- $ret += $db->db_put($i, $data[$i]) ;
- $data{$i} = $data[$i] ;
- }
- ok 34, $ret == 0 ;
-
- # create the cursor
- ok 35, my $cursor = $db->db_cursor() ;
-
- $k = 0 ; $v = "" ;
- my %copy = %data;
- my $extras = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0)
- {
- if ( $copy{$k} eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
-
- ok 36, $cursor->status() == DB_NOTFOUND ;
- ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
- ok 38, keys %copy == 0 ;
- ok 39, $extras == 0 ;
-
- # sequence backwards
- %copy = %data ;
- $extras = 0 ;
- my $status ;
- for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_PREV)) {
- if ( $copy{$k} eq $v )
- { delete $copy{$k} }
- else
- { ++ $extras }
- }
- ok 40, $status == DB_NOTFOUND ;
- ok 41, $status eq $DB_errors{'DB_NOTFOUND'} ;
- ok 42, $cursor->status() == $status ;
- ok 43, $cursor->status() eq $status ;
- ok 44, keys %copy == 0 ;
- ok 45, $extras == 0 ;
-}
-
-{
- # Tied Array interface
-
- # full tied array support started in Perl 5.004_57
- # just double check.
- my $FA = 0 ;
- {
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
- }
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my $db ;
- ok 46, $db = tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -Property => DB_RENUMBER,
- -ArrayBase => 0,
- -Flags => DB_CREATE ;
-
- ok 47, my $cursor = (tied @array)->db_cursor() ;
- # check the database is empty
- my $count = 0 ;
- my ($k, $v) = (0,"") ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 48, $cursor->status() == DB_NOTFOUND ;
- ok 49, $count == 0 ;
-
- ok 50, @array == 0 ;
-
- # Add a k/v pair
- my $value ;
- $array[1] = "some value";
- ok 51, (tied @array)->status() == 0 ;
- ok 52, $array[1] eq "some value";
- ok 53, defined $array[1];
- ok 54, (tied @array)->status() == 0 ;
- ok 55, !defined $array[3];
- ok 56, (tied @array)->status() == DB_NOTFOUND ;
-
- ok 57, (tied @array)->db_del(1) == 0 ;
- ok 58, (tied @array)->status() == 0 ;
- ok 59, ! defined $array[1];
- ok 60, (tied @array)->status() == DB_NOTFOUND ;
-
- $array[1] = 2 ;
- $array[10] = 20 ;
- $array[1000] = 2000 ;
-
- my ($keys, $values) = (0,0);
- $count = 0 ;
- for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
- $status == 0 ;
- $status = $cursor->c_get($k, $v, DB_NEXT)) {
- $keys += $k ;
- $values += $v ;
- ++ $count ;
- }
- ok 61, $count == 3 ;
- ok 62, $keys == 1011 ;
- ok 63, $values == 2022 ;
-
- # unshift
- $FA ? unshift @array, "red", "green", "blue"
- : $db->unshift("red", "green", "blue" ) ;
- ok 64, $array[1] eq "red" ;
- ok 65, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
- ok 66, $k == 1 ;
- ok 67, $v eq "red" ;
- ok 68, $array[2] eq "green" ;
- ok 69, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 70, $k == 2 ;
- ok 71, $v eq "green" ;
- ok 72, $array[3] eq "blue" ;
- ok 73, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 74, $k == 3 ;
- ok 75, $v eq "blue" ;
- ok 76, $array[4] == 2 ;
- ok 77, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
- ok 78, $k == 4 ;
- ok 79, $v == 2 ;
-
- # shift
- ok 80, ($FA ? shift @array : $db->shift()) eq "red" ;
- ok 81, ($FA ? shift @array : $db->shift()) eq "green" ;
- ok 82, ($FA ? shift @array : $db->shift()) eq "blue" ;
- ok 83, ($FA ? shift @array : $db->shift()) == 2 ;
-
- # push
- $FA ? push @array, "the", "end"
- : $db->push("the", "end") ;
- ok 84, $cursor->c_get($k, $v, DB_LAST) == 0 ;
- ok 85, $k == 1001 ;
- ok 86, $v eq "end" ;
- ok 87, $cursor->c_get($k, $v, DB_PREV) == 0 ;
- ok 88, $k == 1000 ;
- ok 89, $v eq "the" ;
- ok 90, $cursor->c_get($k, $v, DB_PREV) == 0 ;
- ok 91, $k == 999 ;
- ok 92, $v == 2000 ;
-
- # pop
- ok 93, ( $FA ? pop @array : $db->pop ) eq "end" ;
- ok 94, ( $FA ? pop @array : $db->pop ) eq "the" ;
- ok 95, ( $FA ? pop @array : $db->pop ) == 2000 ;
-
- # now clear the array
- $FA ? @array = ()
- : $db->clear() ;
- ok 96, $cursor->c_get($k, $v, DB_FIRST) == DB_NOTFOUND ;
-
- undef $cursor ;
- undef $db ;
- untie @array ;
-}
-
-{
- # in-memory file
-
- my @array ;
- my $fd ;
- my $value ;
- ok 97, my $db = tie @array, 'BerkeleyDB::Recno' ;
-
- ok 98, $db->db_put(1, "some value") == 0 ;
- ok 99, $db->db_get(1, $value) == 0 ;
- ok 100, $value eq "some value" ;
-
-}
-
-{
- # partial
- # check works via API
-
- my $lex = new LexFile $Dfile ;
- my $value ;
- ok 101, my $db = new BerkeleyDB::Recno, -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my @data = (
- "",
- "boat",
- "house",
- "sea",
- ) ;
-
- my $ret = 0 ;
- my $i ;
- for ($i = 1 ; $i < @data ; ++$i) {
- $ret += $db->db_put($i, $data[$i]) ;
- }
- ok 102, $ret == 0 ;
-
-
- # do a partial get
- my ($pon, $off, $len) = $db->partial_set(0,2) ;
- ok 103, ! $pon && $off == 0 && $len == 0 ;
- ok 104, $db->db_get(1, $value) == 0 && $value eq "bo" ;
- ok 105, $db->db_get(2, $value) == 0 && $value eq "ho" ;
- ok 106, $db->db_get(3, $value) == 0 && $value eq "se" ;
-
- # do a partial get, off end of data
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 107, $pon ;
- ok 108, $off == 0 ;
- ok 109, $len == 2 ;
- ok 110, $db->db_get(1, $value) == 0 && $value eq "t" ;
- ok 111, $db->db_get(2, $value) == 0 && $value eq "se" ;
- ok 112, $db->db_get(3, $value) == 0 && $value eq "" ;
-
- # switch of partial mode
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 113, $pon ;
- ok 114, $off == 3 ;
- ok 115, $len == 2 ;
- ok 116, $db->db_get(1, $value) == 0 && $value eq "boat" ;
- ok 117, $db->db_get(2, $value) == 0 && $value eq "house" ;
- ok 118, $db->db_get(3, $value) == 0 && $value eq "sea" ;
-
- # now partial put
- $db->partial_set(0,2) ;
- ok 119, $db->db_put(1, "") == 0 ;
- ok 120, $db->db_put(2, "AB") == 0 ;
- ok 121, $db->db_put(3, "XYZ") == 0 ;
- ok 122, $db->db_put(4, "KLM") == 0 ;
-
- ($pon, $off, $len) = $db->partial_clear() ;
- ok 123, $pon ;
- ok 124, $off == 0 ;
- ok 125, $len == 2 ;
- ok 126, $db->db_get(1, $value) == 0 && $value eq "at" ;
- ok 127, $db->db_get(2, $value) == 0 && $value eq "ABuse" ;
- ok 128, $db->db_get(3, $value) == 0 && $value eq "XYZa" ;
- ok 129, $db->db_get(4, $value) == 0 && $value eq "KLM" ;
-
- # now partial put
- ($pon, $off, $len) = $db->partial_set(3,2) ;
- ok 130, ! $pon ;
- ok 131, $off == 0 ;
- ok 132, $len == 0 ;
- ok 133, $db->db_put(1, "PPP") == 0 ;
- ok 134, $db->db_put(2, "Q") == 0 ;
- ok 135, $db->db_put(3, "XYZ") == 0 ;
- ok 136, $db->db_put(4, "TU") == 0 ;
-
- $db->partial_clear() ;
- ok 137, $db->db_get(1, $value) == 0 && $value eq "at\0PPP" ;
- ok 138, $db->db_get(2, $value) == 0 && $value eq "ABuQ" ;
- ok 139, $db->db_get(3, $value) == 0 && $value eq "XYZXYZ" ;
- ok 140, $db->db_get(4, $value) == 0 && $value eq "KLMTU" ;
-}
-
-{
- # partial
- # check works via tied array
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my $value ;
- ok 141, my $db = tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create some data
- my @data = (
- "",
- "boat",
- "house",
- "sea",
- ) ;
-
- my $i ;
- for ($i = 1 ; $i < @data ; ++$i) {
- $array[$i] = $data[$i] ;
- }
-
-
- # do a partial get
- $db->partial_set(0,2) ;
- ok 142, $array[1] eq "bo" ;
- ok 143, $array[2] eq "ho" ;
- ok 144, $array[3] eq "se" ;
-
- # do a partial get, off end of data
- $db->partial_set(3,2) ;
- ok 145, $array[1] eq "t" ;
- ok 146, $array[2] eq "se" ;
- ok 147, $array[3] eq "" ;
-
- # switch of partial mode
- $db->partial_clear() ;
- ok 148, $array[1] eq "boat" ;
- ok 149, $array[2] eq "house" ;
- ok 150, $array[3] eq "sea" ;
-
- # now partial put
- $db->partial_set(0,2) ;
- ok 151, $array[1] = "" ;
- ok 152, $array[2] = "AB" ;
- ok 153, $array[3] = "XYZ" ;
- ok 154, $array[4] = "KLM" ;
-
- $db->partial_clear() ;
- ok 155, $array[1] eq "at" ;
- ok 156, $array[2] eq "ABuse" ;
- ok 157, $array[3] eq "XYZa" ;
- ok 158, $array[4] eq "KLM" ;
-
- # now partial put
- $db->partial_set(3,2) ;
- ok 159, $array[1] = "PPP" ;
- ok 160, $array[2] = "Q" ;
- ok 161, $array[3] = "XYZ" ;
- ok 162, $array[4] = "TU" ;
-
- $db->partial_clear() ;
- ok 163, $array[1] eq "at\0PPP" ;
- ok 164, $array[2] eq "ABuQ" ;
- ok 165, $array[3] eq "XYZXYZ" ;
- ok 166, $array[4] eq "KLMTU" ;
-}
-
-{
- # transaction
-
- my $lex = new LexFile $Dfile ;
- my @array ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 167, mkdir($home, 0777) ;
- ok 168, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 169, my $txn = $env->txn_begin() ;
- ok 170, my $db1 = tie @array, 'BerkeleyDB::Recno',
- -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my @data = (
- "boat",
- "house",
- "sea",
- ) ;
-
- my $ret = 0 ;
- my $i ;
- for ($i = 0 ; $i < @data ; ++$i) {
- $ret += $db1->db_put($i, $data[$i]) ;
- }
- ok 171, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 172, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = (0, "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 173, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- ok 174, $txn->txn_abort() == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 175, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 176, $count == 0 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $env ;
- untie @array ;
- rmtree $home ;
-}
-
-
-{
- # db_stat
-
- my $lex = new LexFile $Dfile ;
- my $recs = ($BerkeleyDB::db_version >= 3.1 ? "bt_ndata" : "bt_nrecs") ;
- my @array ;
- my ($k, $v) ;
- ok 177, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
- -Flags => DB_CREATE,
- -Pagesize => 4 * 1024,
- ;
-
- my $ref = $db->db_stat() ;
- ok 178, $ref->{$recs} == 0;
- ok 179, $ref->{'bt_pagesize'} == 4 * 1024;
-
- # create some data
- my @data = (
- 2,
- "house",
- "sea",
- ) ;
-
- my $ret = 0 ;
- my $i ;
- for ($i = $db->ArrayOffset ; @data ; ++$i) {
- $ret += $db->db_put($i, shift @data) ;
- }
- ok 180, $ret == 0 ;
-
- $ref = $db->db_stat() ;
- ok 181, $ref->{$recs} == 3;
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use BerkeleyDB;
- @ISA=qw(BerkeleyDB::Recno);
- @EXPORT = @BerkeleyDB::EXPORT ;
-
- sub db_put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::db_put($key, $value * 3) ;
- }
-
- sub db_get {
- my $self = shift ;
- $self->SUPER::db_get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok 182, $@ eq "" ;
- my @h ;
- my $X ;
- eval '
- $X = tie(@h, "SubDB", -Filename => "dbbtree.tmp",
- -Flags => DB_CREATE,
- -Mode => 0640 );
- ' ;
-
- main::ok 183, $@ eq "" ;
-
- my $ret = eval '$h[1] = 3 ; return $h[1] ' ;
- main::ok 184, $@ eq "" ;
- main::ok 185, $ret == 7 ;
-
- my $value = 0;
- $ret = eval '$X->db_put(1, 4) ; $X->db_get(1, $value) ; return $value' ;
- main::ok 186, $@ eq "" ;
- main::ok 187, $ret == 10 ;
-
- $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
- main::ok 188, $@ eq "" ;
- main::ok 189, $ret == 1 ;
-
- $ret = eval '$X->A_new_method(1) ' ;
- main::ok 190, $@ eq "" ;
- main::ok 191, $ret eq "[[10]]" ;
-
- unlink "SubDB.pm", "dbbtree.tmp" ;
-
-}
-
-{
- # variable length records, DB_DELIMETER -- defaults to \n
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 192, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Source => $Dfile2 ;
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 193, $x eq "abc\ndef\n\nghi\n" ;
-}
-
-{
- # variable length records, change DB_DELIMETER
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 194, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Source => $Dfile2 ,
- -Delim => "-";
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 195, $x eq "abc-def--ghi-";
-}
-
-{
- # fixed length records, default DB_PAD
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 196, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Len => 5,
- -Source => $Dfile2 ;
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 197, $x eq "abc def ghi " ;
-}
-
-{
- # fixed length records, change Pad
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 198, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Len => 5,
- -Pad => "-",
- -Source => $Dfile2 ;
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 199, $x eq "abc--def-------ghi--" ;
-}
-
-{
- # DB_RENUMBER
-
- my $lex = new LexFile $Dfile;
- my @array ;
- my $value ;
- ok 200, my $db = tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
- -Property => DB_RENUMBER,
- -ArrayBase => 0,
- -Flags => DB_CREATE ;
- # create a few records
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
-
- ok 201, my ($length, $joined) = joiner($db, "|") ;
- ok 202, $length == 3 ;
- ok 203, $joined eq "abc|def|ghi";
-
- ok 204, $db->db_del(1) == 0 ;
- ok 205, ($length, $joined) = joiner($db, "|") ;
- ok 206, $length == 2 ;
- ok 207, $joined eq "abc|ghi";
-
- undef $db ;
- untie @array ;
-
-}
-
-{
- # DB_APPEND
-
- my $lex = new LexFile $Dfile;
- my @array ;
- my $value ;
- ok 208, my $db = tie @array, 'BerkeleyDB::Recno',
- -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # create a few records
- $array[1] = "def" ;
- $array[3] = "ghi" ;
-
- my $k = 0 ;
- ok 209, $db->db_put($k, "fred", DB_APPEND) == 0 ;
- ok 210, $k == 4 ;
-
- undef $db ;
- untie @array ;
-}
-
-{
- # in-memory Btree with an associated text file
-
- my $lex = new LexFile $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 211, tie @array, 'BerkeleyDB::Recno', -Source => $Dfile2 ,
- -ArrayBase => 0,
- -Property => DB_RENUMBER,
- -Flags => DB_CREATE ;
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 212, $x eq "abc\ndef\n\nghi\n" ;
-}
-
-{
- # in-memory, variable length records, change DB_DELIMETER
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 213, tie @array, 'BerkeleyDB::Recno',
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Source => $Dfile2 ,
- -Property => DB_RENUMBER,
- -Delim => "-";
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 214, $x eq "abc-def--ghi-";
-}
-
-{
- # in-memory, fixed length records, default DB_PAD
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 215, tie @array, 'BerkeleyDB::Recno', -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Property => DB_RENUMBER,
- -Len => 5,
- -Source => $Dfile2 ;
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 216, $x eq "abc def ghi " ;
-}
-
-{
- # in-memory, fixed length records, change Pad
-
- my $lex = new LexFile $Dfile, $Dfile2 ;
- touch $Dfile2 ;
- my @array ;
- my $value ;
- ok 217, tie @array, 'BerkeleyDB::Recno',
- -ArrayBase => 0,
- -Flags => DB_CREATE ,
- -Property => DB_RENUMBER,
- -Len => 5,
- -Pad => "-",
- -Source => $Dfile2 ;
- $array[0] = "abc" ;
- $array[1] = "def" ;
- $array[3] = "ghi" ;
- untie @array ;
-
- my $x = docat($Dfile2) ;
- ok 218, $x eq "abc--def-------ghi--" ;
-}
-
-__END__
-
-
-# TODO
-#
-# DB_DELIMETER DB_FIXEDLEN DB_PAD DB_SNAPSHOT with partial records
diff --git a/bdb/perl.BerkeleyDB/t/strict.t b/bdb/perl.BerkeleyDB/t/strict.t
deleted file mode 100644
index 0a856bbb1c6..00000000000
--- a/bdb/perl.BerkeleyDB/t/strict.t
+++ /dev/null
@@ -1,220 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..44\n";
-
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-
-my $Dfile = "dbhash.tmp";
-my $home = "./fred" ;
-
-umask(0);
-
-{
- # closing a database & an environment in the correct order.
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $status ;
-
- rmtree $home if -e $home ;
- ok 1, mkdir($home, 0777) ;
- ok 2, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
-
- ok 3, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env;
-
- ok 4, $db1->db_close() == 0 ;
-
- eval { $status = $env->db_appexit() ; } ;
- ok 5, $status == 0 ;
- ok 6, $@ eq "" ;
- #print "[$@]\n" ;
-
- rmtree $home if -e $home ;
-}
-
-{
- # closing an environment with an open database
- my $lex = new LexFile $Dfile ;
- my %hash ;
-
- rmtree $home if -e $home ;
- ok 7, mkdir($home, 0777) ;
- ok 8, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
-
- ok 9, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env;
-
- eval { $env->db_appexit() ; } ;
- ok 10, $@ =~ /BerkeleyDB Aborting: attempted to close an environment with 1 open database/ ;
- #print "[$@]\n" ;
-
- undef $db1 ;
- untie %hash ;
- undef $env ;
- rmtree $home if -e $home ;
-}
-
-{
- # closing a transaction & a database
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $status ;
-
- rmtree $home if -e $home ;
- ok 11, mkdir($home, 0777) ;
- ok 12, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
-
- ok 13, my $txn = $env->txn_begin() ;
- ok 14, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
- ok 15, $txn->txn_commit() == 0 ;
- eval { $status = $db->db_close() ; } ;
- ok 16, $status == 0 ;
- ok 17, $@ eq "" ;
- eval { $status = $env->db_appexit() ; } ;
- ok 18, $status == 0 ;
- ok 19, $@ eq "" ;
- #print "[$@]\n" ;
-}
-
-{
- # closing a database with an open transaction
- my $lex = new LexFile $Dfile ;
- my %hash ;
-
- rmtree $home if -e $home ;
- ok 20, mkdir($home, 0777) ;
- ok 21, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
-
- ok 22, my $txn = $env->txn_begin() ;
- ok 23, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
- eval { $db->db_close() ; } ;
- ok 24, $@ =~ /BerkeleyDB Aborting: attempted to close a database while a transaction was still open at/ ;
- #print "[$@]\n" ;
-}
-
-{
- # closing a cursor & a database
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $status ;
- ok 25, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ;
- ok 26, my $cursor = $db->db_cursor() ;
- ok 27, $cursor->c_close() == 0 ;
- eval { $status = $db->db_close() ; } ;
- ok 28, $status == 0 ;
- ok 29, $@ eq "" ;
- #print "[$@]\n" ;
- rmtree $home if -e $home ;
-}
-
-{
- # closing a database with an open cursor
- my $lex = new LexFile $Dfile ;
- my %hash ;
- ok 30, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ;
- ok 31, my $cursor = $db->db_cursor() ;
- eval { $db->db_close() ; } ;
- ok 32, $@ =~ /\QBerkeleyDB Aborting: attempted to close a database with 1 open cursor(s) at/;
- #print "[$@]\n" ;
- rmtree $home if -e $home ;
-}
-
-{
- # closing a transaction & a cursor
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $status ;
-
- rmtree $home if -e $home ;
- ok 33, mkdir($home, 0777) ;
- ok 34, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 35, my $txn = $env->txn_begin() ;
- ok 36, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
- ok 37, my $cursor = $db->db_cursor() ;
- eval { $status = $cursor->c_close() ; } ;
- ok 38, $status == 0 ;
- ok 39, ($status = $txn->txn_commit()) == 0 ;
- ok 40, $@ eq "" ;
- eval { $status = $db->db_close() ; } ;
- ok 41, $status == 0 ;
- ok 42, $@ eq "" ;
- eval { $status = $env->db_appexit() ; } ;
- ok 43, $status == 0 ;
- ok 44, $@ eq "" ;
- #print "[$@]\n" ;
- rmtree $home if -e $home ;
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/subdb.t b/bdb/perl.BerkeleyDB/t/subdb.t
deleted file mode 100644
index 290e5d691e4..00000000000
--- a/bdb/perl.BerkeleyDB/t/subdb.t
+++ /dev/null
@@ -1,296 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-BEGIN
-{
- if ($BerkeleyDB::db_version < 3) {
- print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
- exit 0 ;
- }
-}
-
-print "1..43\n";
-
-my %DB_errors = (
- 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
- 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
- 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
- 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
- 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
- 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
- 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
- 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
- ) ;
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub addData
-{
- my $db = shift ;
- my @data = @_ ;
- die "addData odd data\n" unless @data /2 != 0 ;
- my ($k, $v) ;
- my $ret = 0 ;
- while (@data) {
- $k = shift @data ;
- $v = shift @data ;
- $ret += $db->db_put($k, $v) ;
- }
-
- return ($ret == 0) ;
-}
-
-my $Dfile = "dbhash.tmp";
-my $Dfile2 = "dbhash2.tmp";
-my $Dfile3 = "dbhash3.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-# Berkeley DB 3.x specific functionality
-
-# Check for invalid parameters
-{
- # Check for invalid parameters
- my $db ;
- eval ' BerkeleyDB::db_remove -Stupid => 3 ; ' ;
- ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' BerkeleyDB::db_remove -Bad => 2, -Filename => "fred", -Stupid => 3; ' ;
- ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
-
- eval ' BerkeleyDB::db_remove -Filename => "a", -Env => 2 ' ;
- ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-
- eval ' BerkeleyDB::db_remove -Subname => "a"' ;
- ok 4, $@ =~ /^Must specify a filename/ ;
-
- my $obj = bless [], "main" ;
- eval ' BerkeleyDB::db_remove -Filename => "x", -Env => $obj ' ;
- ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-}
-
-{
- # subdatabases
-
- # opening a subdatabse in an exsiting database that doesn't have
- # subdatabases at all should fail
-
- my $lex = new LexFile $Dfile ;
-
- ok 6, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my %data = qw(
- red sky
- blue sea
- black heart
- yellow belley
- green grass
- ) ;
-
- ok 7, addData($db, %data) ;
-
- undef $db ;
-
- $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Subname => "fred" ;
- ok 8, ! $db ;
-
- ok 9, -e $Dfile ;
- ok 10, ! BerkeleyDB::db_remove(-Filename => $Dfile) ;
-}
-
-{
- # subdatabases
-
- # opening a subdatabse in an exsiting database that does have
- # subdatabases at all, but not this one
-
- my $lex = new LexFile $Dfile ;
-
- ok 11, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Subname => "fred" ,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my %data = qw(
- red sky
- blue sea
- black heart
- yellow belley
- green grass
- ) ;
-
- ok 12, addData($db, %data) ;
-
- undef $db ;
-
- $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Subname => "joe" ;
-
- ok 13, !$db ;
-
-}
-
-{
- # subdatabases
-
- my $lex = new LexFile $Dfile ;
-
- ok 14, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Subname => "fred" ,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my %data = qw(
- red sky
- blue sea
- black heart
- yellow belley
- green grass
- ) ;
-
- ok 15, addData($db, %data) ;
-
- undef $db ;
-
- ok 16, $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Subname => "fred" ;
-
- ok 17, my $cursor = $db->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $status ;
- while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
- if ($data{$k} eq $v) {
- delete $data{$k} ;
- }
- }
- ok 18, $status == DB_NOTFOUND ;
- ok 19, keys %data == 0 ;
-}
-
-{
- # subdatabases
-
- # opening a database with multiple subdatabases - handle should be a list
- # of the subdatabase names
-
- my $lex = new LexFile $Dfile ;
-
- ok 20, my $db1 = new BerkeleyDB::Hash -Filename => $Dfile,
- -Subname => "fred" ,
- -Flags => DB_CREATE ;
-
- ok 21, my $db2 = new BerkeleyDB::Btree -Filename => $Dfile,
- -Subname => "joe" ,
- -Flags => DB_CREATE ;
-
- # Add a k/v pair
- my %data = qw(
- red sky
- blue sea
- black heart
- yellow belley
- green grass
- ) ;
-
- ok 22, addData($db1, %data) ;
- ok 23, addData($db2, %data) ;
-
- undef $db1 ;
- undef $db2 ;
-
- ok 24, my $db = new BerkeleyDB::Unknown -Filename => $Dfile ,
- -Flags => DB_RDONLY ;
-
- #my $type = $db->type() ; print "type $type\n" ;
- ok 25, my $cursor = $db->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $status ;
- my @dbnames = () ;
- while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
- push @dbnames, $k ;
- }
- ok 26, $status == DB_NOTFOUND ;
- ok 27, join(",", sort @dbnames) eq "fred,joe" ;
- undef $db ;
-
- ok 28, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "harry") != 0;
- ok 29, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "fred") == 0 ;
-
- # should only be one subdatabase
- ok 30, $db = new BerkeleyDB::Unknown -Filename => $Dfile ,
- -Flags => DB_RDONLY ;
-
- ok 31, $cursor = $db->db_cursor() ;
- @dbnames = () ;
- while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
- push @dbnames, $k ;
- }
- ok 32, $status == DB_NOTFOUND ;
- ok 33, join(",", sort @dbnames) eq "joe" ;
- undef $db ;
-
- # can't delete an already deleted subdatabase
- ok 34, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "fred") != 0;
-
- ok 35, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "joe") == 0 ;
-
- # should only be one subdatabase
- ok 36, $db = new BerkeleyDB::Unknown -Filename => $Dfile ,
- -Flags => DB_RDONLY ;
-
- ok 37, $cursor = $db->db_cursor() ;
- @dbnames = () ;
- while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
- push @dbnames, $k ;
- }
- ok 38, $status == DB_NOTFOUND ;
- ok 39, @dbnames == 0 ;
- undef $db ;
-
- ok 40, -e $Dfile ;
- ok 41, BerkeleyDB::db_remove(-Filename => $Dfile) == 0 ;
- ok 42, ! -e $Dfile ;
- ok 43, BerkeleyDB::db_remove(-Filename => $Dfile) != 0 ;
-}
-
-# db_remove with env
diff --git a/bdb/perl.BerkeleyDB/t/txn.t b/bdb/perl.BerkeleyDB/t/txn.t
deleted file mode 100644
index 6bef1887ea3..00000000000
--- a/bdb/perl.BerkeleyDB/t/txn.t
+++ /dev/null
@@ -1,354 +0,0 @@
-#!./perl -w
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..50\n";
-
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-
-my $Dfile = "dbhash.tmp";
-
-umask(0);
-
-{
- # error cases
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 1, mkdir($home, 0777) ;
- ok 2, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE| DB_INIT_MPOOL;
- eval { $env->txn_begin() ; } ;
- ok 3, $@ =~ /^BerkeleyDB Aborting: Transaction Manager not enabled at/ ;
-
- eval { my $txn_mgr = $env->TxnMgr() ; } ;
- ok 4, $@ =~ /^BerkeleyDB Aborting: Transaction Manager not enabled at/ ;
- undef $env ;
- rmtree $home ;
-
-}
-
-{
- # transaction - abort works
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 5, mkdir($home, 0777) ;
- ok 6, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 7, my $txn = $env->txn_begin() ;
- ok 8, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 9, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 10, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 11, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- ok 12, $txn->txn_abort() == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 13, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 14, $count == 0 ;
-
- my $stat = $env->txn_stat() ;
- ok 15, $stat->{'st_naborts'} == 1 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $env ;
- untie %hash ;
- rmtree $home ;
-}
-
-{
- # transaction - abort works via txnmgr
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 16, mkdir($home, 0777) ;
- ok 17, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 18, my $txn_mgr = $env->TxnMgr() ;
- ok 19, my $txn = $txn_mgr->txn_begin() ;
- ok 20, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 21, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 22, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 23, $count == 3 ;
- undef $cursor ;
-
- # now abort the transaction
- ok 24, $txn->txn_abort() == 0 ;
-
- # there shouldn't be any records in the database
- $count = 0 ;
- # sequence forwards
- ok 25, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 26, $count == 0 ;
-
- my $stat = $txn_mgr->txn_stat() ;
- ok 27, $stat->{'st_naborts'} == 1 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $txn_mgr ;
- undef $env ;
- untie %hash ;
- rmtree $home ;
-}
-
-{
- # transaction - commit works
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 28, mkdir($home, 0777) ;
- ok 29, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 30, my $txn = $env->txn_begin() ;
- ok 31, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 32, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 33, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 34, $count == 3 ;
- undef $cursor ;
-
- # now commit the transaction
- ok 35, $txn->txn_commit() == 0 ;
-
- $count = 0 ;
- # sequence forwards
- ok 36, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 37, $count == 3 ;
-
- my $stat = $env->txn_stat() ;
- ok 38, $stat->{'st_naborts'} == 0 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $env ;
- untie %hash ;
- rmtree $home ;
-}
-
-{
- # transaction - commit works via txnmgr
-
- my $lex = new LexFile $Dfile ;
- my %hash ;
- my $value ;
-
- my $home = "./fred" ;
- rmtree $home if -e $home ;
- ok 39, mkdir($home, 0777) ;
- ok 40, my $env = new BerkeleyDB::Env -Home => $home,
- -Flags => DB_CREATE|DB_INIT_TXN|
- DB_INIT_MPOOL|DB_INIT_LOCK ;
- ok 41, my $txn_mgr = $env->TxnMgr() ;
- ok 42, my $txn = $txn_mgr->txn_begin() ;
- ok 43, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
- -Flags => DB_CREATE ,
- -Env => $env,
- -Txn => $txn ;
-
-
- # create some data
- my %data = (
- "red" => "boat",
- "green" => "house",
- "blue" => "sea",
- ) ;
-
- my $ret = 0 ;
- while (my ($k, $v) = each %data) {
- $ret += $db1->db_put($k, $v) ;
- }
- ok 44, $ret == 0 ;
-
- # should be able to see all the records
-
- ok 45, my $cursor = $db1->db_cursor() ;
- my ($k, $v) = ("", "") ;
- my $count = 0 ;
- # sequence forwards
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 46, $count == 3 ;
- undef $cursor ;
-
- # now commit the transaction
- ok 47, $txn->txn_commit() == 0 ;
-
- $count = 0 ;
- # sequence forwards
- ok 48, $cursor = $db1->db_cursor() ;
- while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
- ++ $count ;
- }
- ok 49, $count == 3 ;
-
- my $stat = $txn_mgr->txn_stat() ;
- ok 50, $stat->{'st_naborts'} == 0 ;
-
- undef $txn ;
- undef $cursor ;
- undef $db1 ;
- undef $txn_mgr ;
- undef $env ;
- untie %hash ;
- rmtree $home ;
-}
-
diff --git a/bdb/perl.BerkeleyDB/t/unknown.t b/bdb/perl.BerkeleyDB/t/unknown.t
deleted file mode 100644
index e72021f0b18..00000000000
--- a/bdb/perl.BerkeleyDB/t/unknown.t
+++ /dev/null
@@ -1,212 +0,0 @@
-#!./perl -w
-
-# ID: %I%, %G%
-
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use BerkeleyDB;
-use File::Path qw(rmtree);
-
-print "1..41\n";
-
-{
- package LexFile ;
-
- sub new
- {
- my $self = shift ;
- unlink @_ ;
- bless [ @_ ], $self ;
- }
-
- sub DESTROY
- {
- my $self = shift ;
- unlink @{ $self } ;
- }
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub writeFile
-{
- my $name = shift ;
- open(FH, ">$name") or return 0 ;
- print FH @_ ;
- close FH ;
- return 1 ;
-}
-
-my $Dfile = "dbhash.tmp";
-unlink $Dfile;
-
-umask(0) ;
-
-
-# Check for invalid parameters
-{
- # Check for invalid parameters
- my $db ;
- eval ' $db = new BerkeleyDB::Unknown -Stupid => 3 ; ' ;
- ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
-
- eval ' $db = new BerkeleyDB::Unknown -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
- ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
-
- eval ' $db = new BerkeleyDB::Unknown -Env => 2 ' ;
- ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-
- eval ' $db = new BerkeleyDB::Unknown -Txn => "fred" ' ;
- ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
-
- my $obj = bless [], "main" ;
- eval ' $db = new BerkeleyDB::Unknown -Env => $obj ' ;
- ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
-}
-
-# check the interface to a rubbish database
-{
- # first an empty file
- my $lex = new LexFile $Dfile ;
- ok 6, writeFile($Dfile, "") ;
-
- ok 7, ! (new BerkeleyDB::Unknown -Filename => $Dfile);
-
- # now a non-database file
- writeFile($Dfile, "\x2af6") ;
- ok 8, ! (new BerkeleyDB::Unknown -Filename => $Dfile);
-}
-
-# check the interface to a Hash database
-
-{
- my $lex = new LexFile $Dfile ;
-
- # create a hash database
- ok 9, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a few k/v pairs
- my $value ;
- my $status ;
- ok 10, $db->db_put("some key", "some value") == 0 ;
- ok 11, $db->db_put("key", "value") == 0 ;
-
- # close the database
- undef $db ;
-
- # now open it with Unknown
- ok 12, $db = new BerkeleyDB::Unknown -Filename => $Dfile;
-
- ok 13, $db->type() == DB_HASH ;
- ok 14, $db->db_get("some key", $value) == 0 ;
- ok 15, $value eq "some value" ;
- ok 16, $db->db_get("key", $value) == 0 ;
- ok 17, $value eq "value" ;
-
- my @array ;
- eval { $db->Tie(\@array)} ;
- ok 18, $@ =~ /^Tie needs a reference to a hash/ ;
-
- my %hash ;
- $db->Tie(\%hash) ;
- ok 19, $hash{"some key"} eq "some value" ;
-
-}
-
-# check the interface to a Btree database
-
-{
- my $lex = new LexFile $Dfile ;
-
- # create a hash database
- ok 20, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a few k/v pairs
- my $value ;
- my $status ;
- ok 21, $db->db_put("some key", "some value") == 0 ;
- ok 22, $db->db_put("key", "value") == 0 ;
-
- # close the database
- undef $db ;
-
- # now open it with Unknown
- # create a hash database
- ok 23, $db = new BerkeleyDB::Unknown -Filename => $Dfile;
-
- ok 24, $db->type() == DB_BTREE ;
- ok 25, $db->db_get("some key", $value) == 0 ;
- ok 26, $value eq "some value" ;
- ok 27, $db->db_get("key", $value) == 0 ;
- ok 28, $value eq "value" ;
-
-
- my @array ;
- eval { $db->Tie(\@array)} ;
- ok 29, $@ =~ /^Tie needs a reference to a hash/ ;
-
- my %hash ;
- $db->Tie(\%hash) ;
- ok 30, $hash{"some key"} eq "some value" ;
-
-
-}
-
-# check the interface to a Recno database
-
-{
- my $lex = new LexFile $Dfile ;
-
- # create a recno database
- ok 31, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
- -Flags => DB_CREATE ;
-
- # Add a few k/v pairs
- my $value ;
- my $status ;
- ok 32, $db->db_put(0, "some value") == 0 ;
- ok 33, $db->db_put(1, "value") == 0 ;
-
- # close the database
- undef $db ;
-
- # now open it with Unknown
- # create a hash database
- ok 34, $db = new BerkeleyDB::Unknown -Filename => $Dfile;
-
- ok 35, $db->type() == DB_RECNO ;
- ok 36, $db->db_get(0, $value) == 0 ;
- ok 37, $value eq "some value" ;
- ok 38, $db->db_get(1, $value) == 0 ;
- ok 39, $value eq "value" ;
-
-
- my %hash ;
- eval { $db->Tie(\%hash)} ;
- ok 40, $@ =~ /^Tie needs a reference to an array/ ;
-
- my @array ;
- $db->Tie(\@array) ;
- ok 41, $array[1] eq "value" ;
-
-
-}
-
-# check i/f to text
diff --git a/bdb/perl.BerkeleyDB/typemap b/bdb/perl.BerkeleyDB/typemap
deleted file mode 100644
index d6c4c7647ce..00000000000
--- a/bdb/perl.BerkeleyDB/typemap
+++ /dev/null
@@ -1,275 +0,0 @@
-# typemap for Perl 5 interface to Berkeley DB version 2 & 3
-#
-# SCCS: %I%, %G%
-#
-# written by Paul Marquess <Paul.Marquess@btinternet.com>
-#
-#################################### DB SECTION
-#
-#
-
-void * T_PV
-u_int T_U_INT
-u_int32_t T_U_INT
-const char * T_PV_NULL
-PV_or_NULL T_PV_NULL
-IO_or_NULL T_IO_NULL
-
-AV * T_AV
-
-BerkeleyDB T_PTROBJ
-BerkeleyDB::Common T_PTROBJ_AV
-BerkeleyDB::Hash T_PTROBJ_AV
-BerkeleyDB::Btree T_PTROBJ_AV
-BerkeleyDB::Recno T_PTROBJ_AV
-BerkeleyDB::Queue T_PTROBJ_AV
-BerkeleyDB::Cursor T_PTROBJ_AV
-BerkeleyDB::TxnMgr T_PTROBJ_AV
-BerkeleyDB::Txn T_PTROBJ_AV
-BerkeleyDB::Log T_PTROBJ_AV
-BerkeleyDB::Lock T_PTROBJ_AV
-BerkeleyDB::Env T_PTROBJ_AV
-
-BerkeleyDB::Raw T_RAW
-BerkeleyDB::Common::Raw T_RAW
-BerkeleyDB::Hash::Raw T_RAW
-BerkeleyDB::Btree::Raw T_RAW
-BerkeleyDB::Recno::Raw T_RAW
-BerkeleyDB::Queue::Raw T_RAW
-BerkeleyDB::Cursor::Raw T_RAW
-BerkeleyDB::TxnMgr::Raw T_RAW
-BerkeleyDB::Txn::Raw T_RAW
-BerkeleyDB::Log::Raw T_RAW
-BerkeleyDB::Lock::Raw T_RAW
-BerkeleyDB::Env::Raw T_RAW
-
-BerkeleyDB::Env::Inner T_INNER
-BerkeleyDB::Common::Inner T_INNER
-BerkeleyDB::Txn::Inner T_INNER
-BerkeleyDB::TxnMgr::Inner T_INNER
-# BerkeleyDB__Env T_PTR
-DBT T_dbtdatum
-DBT_OPT T_dbtdatum_opt
-DBT_B T_dbtdatum_btree
-DBTKEY T_dbtkeydatum
-DBTKEY_B T_dbtkeydatum_btree
-DBTYPE T_U_INT
-DualType T_DUAL
-BerkeleyDB_type * T_IV
-BerkeleyDB_ENV_type * T_IV
-BerkeleyDB_TxnMgr_type * T_IV
-BerkeleyDB_Txn_type * T_IV
-BerkeleyDB__Cursor_type * T_IV
-DB * T_IV
-
-INPUT
-
-T_AV
- if (SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV)
- /* if (sv_isa($arg, \"${ntype}\")) */
- $var = (AV*)SvRV($arg);
- else
- croak(\"$var is not an array reference\")
-
-T_RAW
- $var = ($type)SvIV($arg)
-
-T_U_INT
- $var = SvUV($arg)
-
-T_SV_REF_NULL
- if ($arg == &PL_sv_undef)
- $var = NULL ;
- else if (sv_derived_from($arg, \"${ntype}\")) {
- IV tmp = SvIV((SV *)GetInternalObject($arg));
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-T_HV_REF_NULL
- if ($arg == &PL_sv_undef)
- $var = NULL ;
- else if (sv_derived_from($arg, \"${ntype}\")) {
- HV * hv = (HV *)GetInternalObject($arg);
- SV ** svp = hv_fetch(hv, \"db\", 2, FALSE);
- IV tmp = SvIV(*svp);
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-T_HV_REF
- if (sv_derived_from($arg, \"${ntype}\")) {
- HV * hv = (HV *)GetInternalObject($arg);
- SV ** svp = hv_fetch(hv, \"db\", 2, FALSE);
- IV tmp = SvIV(*svp);
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-
-T_P_REF
- if (sv_derived_from($arg, \"${ntype}\")) {
- IV tmp = SvIV((SV*)SvRV($arg));
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-
-T_INNER
- {
- HV * hv = (HV *)SvRV($arg);
- SV ** svp = hv_fetch(hv, \"db\", 2, FALSE);
- IV tmp = SvIV(*svp);
- $var = ($type) tmp;
- }
-
-T_PV_NULL
- if ($arg == &PL_sv_undef)
- $var = NULL ;
- else {
- $var = ($type)SvPV($arg,PL_na) ;
- if (PL_na == 0)
- $var = NULL ;
- }
-
-T_IO_NULL
- if ($arg == &PL_sv_undef)
- $var = NULL ;
- else
- $var = IoOFP(sv_2io($arg))
-
-T_PTROBJ_NULL
- if ($arg == &PL_sv_undef)
- $var = NULL ;
- else if (sv_derived_from($arg, \"${ntype}\")) {
- IV tmp = SvIV((SV*)SvRV($arg));
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-T_PTROBJ_SELF
- if ($arg == &PL_sv_undef)
- $var = NULL ;
- else if (sv_derived_from($arg, \"${ntype}\")) {
- IV tmp = SvIV((SV*)SvRV($arg));
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-T_PTROBJ_AV
- if ($arg == &PL_sv_undef || $arg == NULL)
- $var = NULL ;
- else if (sv_derived_from($arg, \"${ntype}\")) {
- IV tmp = getInnerObject($arg) ;
- $var = ($type) tmp;
- }
- else
- croak(\"$var is not of type ${ntype}\")
-
-T_dbtkeydatum
- ckFilter($arg, filter_store_key, \"filter_store_key\");
- DBT_clear($var) ;
- if (db->recno_or_queue) {
- Value = GetRecnoKey(db, SvIV($arg)) ;
- $var.data = & Value;
- $var.size = (int)sizeof(db_recno_t);
- }
- else {
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- }
-
-T_dbtkeydatum_btree
- ckFilter($arg, filter_store_key, \"filter_store_key\");
- DBT_clear($var) ;
- if (db->recno_or_queue ||
- (db->type == DB_BTREE && flagSet(DB_SET_RECNO))) {
- Value = GetRecnoKey(db, SvIV($arg)) ;
- $var.data = & Value;
- $var.size = (int)sizeof(db_recno_t);
- }
- else {
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- }
-
-T_dbtdatum
- ckFilter($arg, filter_store_value, \"filter_store_value\");
- DBT_clear($var) ;
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- $var.flags = db->partial ;
- $var.dlen = db->dlen ;
- $var.doff = db->doff ;
-
-T_dbtdatum_opt
- DBT_clear($var) ;
- if (flagSet(DB_GET_BOTH)) {
- ckFilter($arg, filter_store_value, \"filter_store_value\");
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- $var.flags = db->partial ;
- $var.dlen = db->dlen ;
- $var.doff = db->doff ;
- }
-
-T_dbtdatum_btree
- DBT_clear($var) ;
- if (flagSet(DB_GET_BOTH)) {
- ckFilter($arg, filter_store_value, \"filter_store_value\");
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- $var.flags = db->partial ;
- $var.dlen = db->dlen ;
- $var.doff = db->doff ;
- }
-
-
-OUTPUT
-
-T_RAW
- sv_setiv($arg, (IV)$var);
-
-T_SV_REF_NULL
- sv_setiv($arg, (IV)$var);
-
-T_HV_REF_NULL
- sv_setiv($arg, (IV)$var);
-
-T_HV_REF
- sv_setiv($arg, (IV)$var);
-
-T_P_REF
- sv_setiv($arg, (IV)$var);
-
-T_DUAL
- setDUALerrno($arg, $var) ;
-
-T_U_INT
- sv_setuv($arg, (UV)$var);
-
-T_PV_NULL
- sv_setpv((SV*)$arg, $var);
-
-T_dbtkeydatum_btree
- OutputKey_B($arg, $var)
-T_dbtkeydatum
- OutputKey($arg, $var)
-T_dbtdatum
- OutputValue($arg, $var)
-T_dbtdatum_opt
- OutputValue($arg, $var)
-T_dbtdatum_btree
- OutputValue_B($arg, $var)
-
-T_PTROBJ_NULL
- sv_setref_pv($arg, \"${ntype}\", (void*)$var);
-
-T_PTROBJ_SELF
- sv_setref_pv($arg, self, (void*)$var);
diff --git a/bdb/perl.DB_File/Changes b/bdb/perl.DB_File/Changes
deleted file mode 100644
index b8684cac3de..00000000000
--- a/bdb/perl.DB_File/Changes
+++ /dev/null
@@ -1,343 +0,0 @@
-
-0.1
-
- First Release.
-
-0.2
-
- When DB_File is opening a database file it no longer terminates the
- process if dbopen returned an error. This allows file protection
- errors to be caught at run time. Thanks to Judith Grass
- <grass@cybercash.com> for spotting the bug.
-
-0.3
-
- Added prototype support for multiple btree compare callbacks.
-
-1.0
-
- DB_File has been in use for over a year. To reflect that, the
- version number has been incremented to 1.0.
-
- Added complete support for multiple concurrent callbacks.
-
- Using the push method on an empty list didn't work properly. This
- has been fixed.
-
-1.01
-
- Fixed a core dump problem with SunOS.
-
- The return value from TIEHASH wasn't set to NULL when dbopen
- returned an error.
-
-1.02
-
- Merged OS/2 specific code into DB_File.xs
-
- Removed some redundant code in DB_File.xs.
-
- Documentation update.
-
- Allow negative subscripts with RECNO interface.
-
- Changed the default flags from O_RDWR to O_CREAT|O_RDWR.
-
- The example code which showed how to lock a database needed a call
- to sync added. Without it the resultant database file was empty.
-
- Added get_dup method.
-
-1.03
-
- Documentation update.
-
- DB_File now imports the constants (O_RDWR, O_CREAT etc.) from Fcntl
- automatically.
-
- The standard hash function exists is now supported.
-
- Modified the behavior of get_dup. When it returns an associative
- array, the value is the count of the number of matching BTREE
- values.
-
-1.04
-
- Minor documentation changes.
-
- Fixed a bug in hash_cb. Patches supplied by Dave Hammen,
- <hammen@gothamcity.jsc.nasa.govt>.
-
- Fixed a bug with the constructors for DB_File::HASHINFO,
- DB_File::BTREEINFO and DB_File::RECNOINFO. Also tidied up the
- constructors to make them -w clean.
-
- Reworked part of the test harness to be more locale friendly.
-
-1.05
-
- Made all scripts in the documentation strict and -w clean.
-
- Added logic to DB_File.xs to allow the module to be built after
- Perl is installed.
-
-1.06
-
- Minor namespace cleanup: Localized PrintBtree.
-
-1.07
-
- Fixed bug with RECNO, where bval wasn't defaulting to "\n".
-
-1.08
-
- Documented operation of bval.
-
-1.09
-
- Minor bug fix in DB_File::HASHINFO, DB_File::RECNOINFO and
- DB_File::BTREEINFO.
-
- Changed default mode to 0666.
-
-1.10
-
- Fixed fd method so that it still returns -1 for in-memory files
- when db 1.86 is used.
-
-1.11
-
- Documented the untie gotcha.
-
-1.12
-
- Documented the incompatibility with version 2 of Berkeley DB.
-
-1.13
-
- Minor changes to DB_FIle.xs and DB_File.pm
-
-1.14
-
- Made it illegal to tie an associative array to a RECNO database and
- an ordinary array to a HASH or BTREE database.
-
-1.15
-
- Patch from Gisle Aas <gisle@aas.no> to suppress "use of undefined
- value" warning with db_get and db_seq.
-
- Patch from Gisle Aas <gisle@aas.no> to make DB_File export only the
- O_* constants from Fcntl.
-
- Removed the DESTROY method from the DB_File::HASHINFO module.
-
- Previously DB_File hard-wired the class name of any object that it
- created to "DB_File". This makes sub-classing difficult. Now
- DB_File creats objects in the namespace of the package it has been
- inherited into.
-
-
-1.16
-
- A harmless looking tab was causing Makefile.PL to fail on AIX 3.2.5
-
- Small fix for the AIX strict C compiler XLC which doesn't like
- __attribute__ being defined via proto.h and redefined via db.h. Fix
- courtesy of Jarkko Hietaniemi.
-
-1.50
-
- DB_File can now build with either DB 1.x or 2.x, but not both at
- the same time.
-
-1.51
-
- Fixed the test harness so that it doesn't expect DB_File to have
- been installed by the main Perl build.
-
-
- Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
-
-1.52
-
- Patch from Nick Ing-Simmons now allows DB_File to build on NT.
- Merged 1.15 patch.
-
-1.53
-
- Added DB_RENUMBER to flags for recno.
-
-1.54
-
- Fixed a small bug in the test harness when run under win32
- The emulation of fd when useing DB 2.x was busted.
-
-1.55
- Merged 1.16 changes.
-
-1.56
- Documented the Solaris 2.5 mutex bug
-
-1.57
- If Perl has been compiled with Threads support,the symbol op will be
- defined. This clashes with a field name in db.h, so it needs to be
- #undef'ed before db.h is included.
-
-1.58
- Tied Array support was enhanced in Perl 5.004_57. DB_File now
- supports PUSH,POP,SHIFT,UNSHIFT & STORESIZE.
-
- Fixed a problem with the use of sv_setpvn. When the size is
- specified as 0, it does a strlen on the data. This was ok for DB
- 1.x, but isn't for DB 2.x.
-
-1.59
- Updated the license section.
-
- Berkeley DB 2.4.10 disallows zero length keys. Tests 32 & 42 in
- db-btree.t and test 27 in db-hash.t failed because of this change.
- Those tests have been zapped.
-
- Added dbinfo to the distribution.
-
-1.60
- Changed the test to check for full tied array support
-
-1.61 19th November 1998
-
- Added a note to README about how to build Berkeley DB 2.x when
- using HP-UX.
- Minor modifications to get the module to build with DB 2.5.x
- Fixed a typo in the definition of O_RDONLY, courtesy of Mark Kettenis.
-
-1.62 30th November 1998
-
- Added hints/dynixptx.pl.
- Fixed typemap -- 1.61 used PL_na instead of na
-
-1.63 19th December 1998
-
- * Fix to allow DB 2.6.x to build with DB_File
- * Documentation updated to use push,pop etc in the RECNO example &
- to include the find_dup & del_dup methods.
-
-1.64 21st February 1999
-
- * Tidied the 1.x to 2.x flag mapping code.
- * Added a patch from Mark Kettenis <kettenis@wins.uva.nl> to fix a flag
- mapping problem with O_RDONLY on the Hurd
- * Updated the message that db-recno.t prints when tests 51, 53 or 55 fail.
-
-1.65 6th March 1999
-
- * Fixed a bug in the recno PUSH logic.
- * The BOOT version check now needs 2.3.4 when using Berkeley DB version 2
-
-1.66 15th March 1999
-
- * Added DBM Filter code
-
-1.67 6th June 1999
-
- * Added DBM Filter documentation to DB_File.pm
-
- * Fixed DBM Filter code to work with 5.004
-
- * A few instances of newSVpvn were used in 1.66. This isn't available in
- Perl 5.004_04 or earlier. Replaced with newSVpv.
-
-1.68 22nd July 1999
-
- * Merged changes from 5.005_58
-
- * Fixed a bug in R_IBEFORE & R_IAFTER procesing in Berkeley DB
- 2 databases.
-
- * Added some of the examples in the POD into the test harness.
-
-1.69 3rd August 1999
-
- * fixed a bug in push -- DB_APPEND wasn't working properly.
-
- * Fixed the R_SETCURSOR bug introduced in 1.68
-
- * Added a new Perl variable $DB_File::db_ver
-
-1.70 4th August 1999
-
- * Initialise $DB_File::db_ver and $DB_File::db_version with
- GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
-
- * Added a BOOT check to test for equivalent versions of db.h &
- libdb.a/so.
-
-1.71 7th September 1999
-
- * Fixed a bug that prevented 1.70 from compiling under win32
-
- * Updated to support Berkeley DB 3.x
-
- * Updated dbinfo for Berkeley DB 3.x file formats.
-
-1.72 16th January 2000
-
- * Added hints/sco.pl
-
- * The module will now use XSLoader when it is available. When it
- isn't it will use DynaLoader.
-
- * The locking section in DB_File.pm has been discredited. Many thanks
- to David Harris for spotting the underlying problem, contributing
- the updates to the documentation and writing DB_File::Lock (available
- on CPAN).
-
-1.73 31st May 2000
-
- * Added support in version.c for building with threaded Perl.
-
- * Berkeley DB 3.1 has reenabled support for null keys. The test
- harness has been updated to reflect this.
-
-1.74 10th December 2000
-
- * A "close" call in DB_File.xs needed parenthesised to stop win32 from
- thinking it was one of its macros.
-
- * Updated dbinfo to support Berkeley DB 3.1 file format changes.
-
- * DB_File.pm & the test hasness now use the warnings pragma (when
- available).
-
- * Included Perl core patch 7703 -- size argument for hash_cb is different
- for Berkeley DB 3.x
-
- * Included Perl core patch 7801 -- Give __getBerkeleyDBInfo the ANSI C
- treatment.
-
- * @a = () produced the warning 'Argument "" isn't numeric in entersub'
- This has been fixed. Thanks to Edward Avis for spotting this bug.
-
- * Added note about building under Linux. Included patches.
-
- * Included Perl core patch 8068 -- fix for bug 20001013.009
- When run with warnings enabled "$hash{XX} = undef " produced an
- "Uninitialized value" warning. This has been fixed.
-
-1.75 17th December 2000
-
- * Fixed perl core patch 7703
-
- * Added suppport to allow DB_File to be built with Berkeley DB 3.2 --
- btree_compare, btree_prefix and hash_cb needed to be changed.
-
- * Updated dbinfo to support Berkeley DB 3.2 file format changes.
-
-
-1.76 15th January 2001
-
- * Added instructions for using LD_PRELOAD to get Berkeley DB 2.x to work
- with DB_File on Linux. Thanks to Norbert Bollow for sending details of
- this approach.
-
-
diff --git a/bdb/perl.DB_File/DB_File.pm b/bdb/perl.DB_File/DB_File.pm
deleted file mode 100644
index e9b6a40d7e3..00000000000
--- a/bdb/perl.DB_File/DB_File.pm
+++ /dev/null
@@ -1,2072 +0,0 @@
-# DB_File.pm -- Perl 5 interface to Berkeley DB
-#
-# written by Paul Marquess (Paul.Marquess@btinternet.com)
-# last modified 15th January 2001
-# version 1.76
-#
-# Copyright (c) 1995-2001 Paul Marquess. All rights reserved.
-# This program is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-
-
-package DB_File::HASHINFO ;
-
-require 5.003 ;
-
-use warnings;
-use strict;
-use Carp;
-require Tie::Hash;
-@DB_File::HASHINFO::ISA = qw(Tie::Hash);
-
-sub new
-{
- my $pkg = shift ;
- my %x ;
- tie %x, $pkg ;
- bless \%x, $pkg ;
-}
-
-
-sub TIEHASH
-{
- my $pkg = shift ;
-
- bless { VALID => { map {$_, 1}
- qw( bsize ffactor nelem cachesize hash lorder)
- },
- GOT => {}
- }, $pkg ;
-}
-
-
-sub FETCH
-{
- my $self = shift ;
- my $key = shift ;
-
- return $self->{GOT}{$key} if exists $self->{VALID}{$key} ;
-
- my $pkg = ref $self ;
- croak "${pkg}::FETCH - Unknown element '$key'" ;
-}
-
-
-sub STORE
-{
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
-
- if ( exists $self->{VALID}{$key} )
- {
- $self->{GOT}{$key} = $value ;
- return ;
- }
-
- my $pkg = ref $self ;
- croak "${pkg}::STORE - Unknown element '$key'" ;
-}
-
-sub DELETE
-{
- my $self = shift ;
- my $key = shift ;
-
- if ( exists $self->{VALID}{$key} )
- {
- delete $self->{GOT}{$key} ;
- return ;
- }
-
- my $pkg = ref $self ;
- croak "DB_File::HASHINFO::DELETE - Unknown element '$key'" ;
-}
-
-sub EXISTS
-{
- my $self = shift ;
- my $key = shift ;
-
- exists $self->{VALID}{$key} ;
-}
-
-sub NotHere
-{
- my $self = shift ;
- my $method = shift ;
-
- croak ref($self) . " does not define the method ${method}" ;
-}
-
-sub FIRSTKEY { my $self = shift ; $self->NotHere("FIRSTKEY") }
-sub NEXTKEY { my $self = shift ; $self->NotHere("NEXTKEY") }
-sub CLEAR { my $self = shift ; $self->NotHere("CLEAR") }
-
-package DB_File::RECNOINFO ;
-
-use warnings;
-use strict ;
-
-@DB_File::RECNOINFO::ISA = qw(DB_File::HASHINFO) ;
-
-sub TIEHASH
-{
- my $pkg = shift ;
-
- bless { VALID => { map {$_, 1}
- qw( bval cachesize psize flags lorder reclen bfname )
- },
- GOT => {},
- }, $pkg ;
-}
-
-package DB_File::BTREEINFO ;
-
-use warnings;
-use strict ;
-
-@DB_File::BTREEINFO::ISA = qw(DB_File::HASHINFO) ;
-
-sub TIEHASH
-{
- my $pkg = shift ;
-
- bless { VALID => { map {$_, 1}
- qw( flags cachesize maxkeypage minkeypage psize
- compare prefix lorder )
- },
- GOT => {},
- }, $pkg ;
-}
-
-
-package DB_File ;
-
-use warnings;
-use strict;
-use vars qw($VERSION @ISA @EXPORT $AUTOLOAD $DB_BTREE $DB_HASH $DB_RECNO
- $db_version $use_XSLoader
- ) ;
-use Carp;
-
-
-$VERSION = "1.76" ;
-
-#typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
-$DB_BTREE = new DB_File::BTREEINFO ;
-$DB_HASH = new DB_File::HASHINFO ;
-$DB_RECNO = new DB_File::RECNOINFO ;
-
-require Tie::Hash;
-require Exporter;
-use AutoLoader;
-BEGIN {
- $use_XSLoader = 1 ;
- eval { require XSLoader } ;
-
- if ($@) {
- $use_XSLoader = 0 ;
- require DynaLoader;
- @ISA = qw(DynaLoader);
- }
-}
-
-push @ISA, qw(Tie::Hash Exporter);
-@EXPORT = qw(
- $DB_BTREE $DB_HASH $DB_RECNO
-
- BTREEMAGIC
- BTREEVERSION
- DB_LOCK
- DB_SHMEM
- DB_TXN
- HASHMAGIC
- HASHVERSION
- MAX_PAGE_NUMBER
- MAX_PAGE_OFFSET
- MAX_REC_NUMBER
- RET_ERROR
- RET_SPECIAL
- RET_SUCCESS
- R_CURSOR
- R_DUP
- R_FIRST
- R_FIXEDLEN
- R_IAFTER
- R_IBEFORE
- R_LAST
- R_NEXT
- R_NOKEY
- R_NOOVERWRITE
- R_PREV
- R_RECNOSYNC
- R_SETCURSOR
- R_SNAPSHOT
- __R_UNUSED
-
-);
-
-sub AUTOLOAD {
- my($constname);
- ($constname = $AUTOLOAD) =~ s/.*:://;
- my $val = constant($constname, @_ ? $_[0] : 0);
- if ($! != 0) {
- if ($! =~ /Invalid/ || $!{EINVAL}) {
- $AutoLoader::AUTOLOAD = $AUTOLOAD;
- goto &AutoLoader::AUTOLOAD;
- }
- else {
- my($pack,$file,$line) = caller;
- croak "Your vendor has not defined DB macro $constname, used at $file line $line.
-";
- }
- }
- eval "sub $AUTOLOAD { $val }";
- goto &$AUTOLOAD;
-}
-
-
-eval {
- # Make all Fcntl O_XXX constants available for importing
- require Fcntl;
- my @O = grep /^O_/, @Fcntl::EXPORT;
- Fcntl->import(@O); # first we import what we want to export
- push(@EXPORT, @O);
-};
-
-if ($use_XSLoader)
- { XSLoader::load("DB_File", $VERSION)}
-else
- { bootstrap DB_File $VERSION }
-
-# Preloaded methods go here. Autoload methods go after __END__, and are
-# processed by the autosplit program.
-
-sub tie_hash_or_array
-{
- my (@arg) = @_ ;
- my $tieHASH = ( (caller(1))[3] =~ /TIEHASH/ ) ;
-
- $arg[4] = tied %{ $arg[4] }
- if @arg >= 5 && ref $arg[4] && $arg[4] =~ /=HASH/ && tied %{ $arg[4] } ;
-
- # make recno in Berkeley DB version 2 work like recno in version 1.
- if ($db_version > 1 and defined $arg[4] and $arg[4] =~ /RECNO/ and
- $arg[1] and ! -e $arg[1]) {
- open(FH, ">$arg[1]") or return undef ;
- close FH ;
- chmod $arg[3] ? $arg[3] : 0666 , $arg[1] ;
- }
-
- DoTie_($tieHASH, @arg) ;
-}
-
-sub TIEHASH
-{
- tie_hash_or_array(@_) ;
-}
-
-sub TIEARRAY
-{
- tie_hash_or_array(@_) ;
-}
-
-sub CLEAR
-{
- my $self = shift;
- my $key = 0 ;
- my $value = "" ;
- my $status = $self->seq($key, $value, R_FIRST());
- my @keys;
-
- while ($status == 0) {
- push @keys, $key;
- $status = $self->seq($key, $value, R_NEXT());
- }
- foreach $key (reverse @keys) {
- my $s = $self->del($key);
- }
-}
-
-sub EXTEND { }
-
-sub STORESIZE
-{
- my $self = shift;
- my $length = shift ;
- my $current_length = $self->length() ;
-
- if ($length < $current_length) {
- my $key ;
- for ($key = $current_length - 1 ; $key >= $length ; -- $key)
- { $self->del($key) }
- }
- elsif ($length > $current_length) {
- $self->put($length-1, "") ;
- }
-}
-
-sub find_dup
-{
- croak "Usage: \$db->find_dup(key,value)\n"
- unless @_ == 3 ;
-
- my $db = shift ;
- my ($origkey, $value_wanted) = @_ ;
- my ($key, $value) = ($origkey, 0);
- my ($status) = 0 ;
-
- for ($status = $db->seq($key, $value, R_CURSOR() ) ;
- $status == 0 ;
- $status = $db->seq($key, $value, R_NEXT() ) ) {
-
- return 0 if $key eq $origkey and $value eq $value_wanted ;
- }
-
- return $status ;
-}
-
-sub del_dup
-{
- croak "Usage: \$db->del_dup(key,value)\n"
- unless @_ == 3 ;
-
- my $db = shift ;
- my ($key, $value) = @_ ;
- my ($status) = $db->find_dup($key, $value) ;
- return $status if $status != 0 ;
-
- $status = $db->del($key, R_CURSOR() ) ;
- return $status ;
-}
-
-sub get_dup
-{
- croak "Usage: \$db->get_dup(key [,flag])\n"
- unless @_ == 2 or @_ == 3 ;
-
- my $db = shift ;
- my $key = shift ;
- my $flag = shift ;
- my $value = 0 ;
- my $origkey = $key ;
- my $wantarray = wantarray ;
- my %values = () ;
- my @values = () ;
- my $counter = 0 ;
- my $status = 0 ;
-
- # iterate through the database until either EOF ($status == 0)
- # or a different key is encountered ($key ne $origkey).
- for ($status = $db->seq($key, $value, R_CURSOR()) ;
- $status == 0 and $key eq $origkey ;
- $status = $db->seq($key, $value, R_NEXT()) ) {
-
- # save the value or count number of matches
- if ($wantarray) {
- if ($flag)
- { ++ $values{$value} }
- else
- { push (@values, $value) }
- }
- else
- { ++ $counter }
-
- }
-
- return ($wantarray ? ($flag ? %values : @values) : $counter) ;
-}
-
-
-1;
-__END__
-
-=head1 NAME
-
-DB_File - Perl5 access to Berkeley DB version 1.x
-
-=head1 SYNOPSIS
-
- use DB_File ;
-
- [$X =] tie %hash, 'DB_File', [$filename, $flags, $mode, $DB_HASH] ;
- [$X =] tie %hash, 'DB_File', $filename, $flags, $mode, $DB_BTREE ;
- [$X =] tie @array, 'DB_File', $filename, $flags, $mode, $DB_RECNO ;
-
- $status = $X->del($key [, $flags]) ;
- $status = $X->put($key, $value [, $flags]) ;
- $status = $X->get($key, $value [, $flags]) ;
- $status = $X->seq($key, $value, $flags) ;
- $status = $X->sync([$flags]) ;
- $status = $X->fd ;
-
- # BTREE only
- $count = $X->get_dup($key) ;
- @list = $X->get_dup($key) ;
- %list = $X->get_dup($key, 1) ;
- $status = $X->find_dup($key, $value) ;
- $status = $X->del_dup($key, $value) ;
-
- # RECNO only
- $a = $X->length;
- $a = $X->pop ;
- $X->push(list);
- $a = $X->shift;
- $X->unshift(list);
-
- # DBM Filters
- $old_filter = $db->filter_store_key ( sub { ... } ) ;
- $old_filter = $db->filter_store_value( sub { ... } ) ;
- $old_filter = $db->filter_fetch_key ( sub { ... } ) ;
- $old_filter = $db->filter_fetch_value( sub { ... } ) ;
-
- untie %hash ;
- untie @array ;
-
-=head1 DESCRIPTION
-
-B<DB_File> is a module which allows Perl programs to make use of the
-facilities provided by Berkeley DB version 1.x (if you have a newer
-version of DB, see L<Using DB_File with Berkeley DB version 2 or 3>).
-It is assumed that you have a copy of the Berkeley DB manual pages at
-hand when reading this documentation. The interface defined here
-mirrors the Berkeley DB interface closely.
-
-Berkeley DB is a C library which provides a consistent interface to a
-number of database formats. B<DB_File> provides an interface to all
-three of the database types currently supported by Berkeley DB.
-
-The file types are:
-
-=over 5
-
-=item B<DB_HASH>
-
-This database type allows arbitrary key/value pairs to be stored in data
-files. This is equivalent to the functionality provided by other
-hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
-the files created using DB_HASH are not compatible with any of the
-other packages mentioned.
-
-A default hashing algorithm, which will be adequate for most
-applications, is built into Berkeley DB. If you do need to use your own
-hashing algorithm it is possible to write your own in Perl and have
-B<DB_File> use it instead.
-
-=item B<DB_BTREE>
-
-The btree format allows arbitrary key/value pairs to be stored in a
-sorted, balanced binary tree.
-
-As with the DB_HASH format, it is possible to provide a user defined
-Perl routine to perform the comparison of keys. By default, though, the
-keys are stored in lexical order.
-
-=item B<DB_RECNO>
-
-DB_RECNO allows both fixed-length and variable-length flat text files
-to be manipulated using the same key/value pair interface as in DB_HASH
-and DB_BTREE. In this case the key will consist of a record (line)
-number.
-
-=back
-
-=head2 Using DB_File with Berkeley DB version 2 or 3
-
-Although B<DB_File> is intended to be used with Berkeley DB version 1,
-it can also be used with version 2.or 3 In this case the interface is
-limited to the functionality provided by Berkeley DB 1.x. Anywhere the
-version 2 or 3 interface differs, B<DB_File> arranges for it to work
-like version 1. This feature allows B<DB_File> scripts that were built
-with version 1 to be migrated to version 2 or 3 without any changes.
-
-If you want to make use of the new features available in Berkeley DB
-2.x or greater, use the Perl module B<BerkeleyDB> instead.
-
-B<Note:> The database file format has changed in both Berkeley DB
-version 2 and 3. If you cannot recreate your databases, you must dump
-any existing databases with the C<db_dump185> utility that comes with
-Berkeley DB.
-Once you have rebuilt DB_File to use Berkeley DB version 2 or 3, your
-databases can be recreated using C<db_load>. Refer to the Berkeley DB
-documentation for further details.
-
-Please read L<"COPYRIGHT"> before using version 2.x or 3.x of Berkeley
-DB with DB_File.
-
-=head2 Interface to Berkeley DB
-
-B<DB_File> allows access to Berkeley DB files using the tie() mechanism
-in Perl 5 (for full details, see L<perlfunc/tie()>). This facility
-allows B<DB_File> to access Berkeley DB files using either an
-associative array (for DB_HASH & DB_BTREE file types) or an ordinary
-array (for the DB_RECNO file type).
-
-In addition to the tie() interface, it is also possible to access most
-of the functions provided in the Berkeley DB API directly.
-See L<THE API INTERFACE>.
-
-=head2 Opening a Berkeley DB Database File
-
-Berkeley DB uses the function dbopen() to open or create a database.
-Here is the C prototype for dbopen():
-
- DB*
- dbopen (const char * file, int flags, int mode,
- DBTYPE type, const void * openinfo)
-
-The parameter C<type> is an enumeration which specifies which of the 3
-interface methods (DB_HASH, DB_BTREE or DB_RECNO) is to be used.
-Depending on which of these is actually chosen, the final parameter,
-I<openinfo> points to a data structure which allows tailoring of the
-specific interface method.
-
-This interface is handled slightly differently in B<DB_File>. Here is
-an equivalent call using B<DB_File>:
-
- tie %array, 'DB_File', $filename, $flags, $mode, $DB_HASH ;
-
-The C<filename>, C<flags> and C<mode> parameters are the direct
-equivalent of their dbopen() counterparts. The final parameter $DB_HASH
-performs the function of both the C<type> and C<openinfo> parameters in
-dbopen().
-
-In the example above $DB_HASH is actually a pre-defined reference to a
-hash object. B<DB_File> has three of these pre-defined references.
-Apart from $DB_HASH, there is also $DB_BTREE and $DB_RECNO.
-
-The keys allowed in each of these pre-defined references is limited to
-the names used in the equivalent C structure. So, for example, the
-$DB_HASH reference will only allow keys called C<bsize>, C<cachesize>,
-C<ffactor>, C<hash>, C<lorder> and C<nelem>.
-
-To change one of these elements, just assign to it like this:
-
- $DB_HASH->{'cachesize'} = 10000 ;
-
-The three predefined variables $DB_HASH, $DB_BTREE and $DB_RECNO are
-usually adequate for most applications. If you do need to create extra
-instances of these objects, constructors are available for each file
-type.
-
-Here are examples of the constructors and the valid options available
-for DB_HASH, DB_BTREE and DB_RECNO respectively.
-
- $a = new DB_File::HASHINFO ;
- $a->{'bsize'} ;
- $a->{'cachesize'} ;
- $a->{'ffactor'};
- $a->{'hash'} ;
- $a->{'lorder'} ;
- $a->{'nelem'} ;
-
- $b = new DB_File::BTREEINFO ;
- $b->{'flags'} ;
- $b->{'cachesize'} ;
- $b->{'maxkeypage'} ;
- $b->{'minkeypage'} ;
- $b->{'psize'} ;
- $b->{'compare'} ;
- $b->{'prefix'} ;
- $b->{'lorder'} ;
-
- $c = new DB_File::RECNOINFO ;
- $c->{'bval'} ;
- $c->{'cachesize'} ;
- $c->{'psize'} ;
- $c->{'flags'} ;
- $c->{'lorder'} ;
- $c->{'reclen'} ;
- $c->{'bfname'} ;
-
-The values stored in the hashes above are mostly the direct equivalent
-of their C counterpart. Like their C counterparts, all are set to a
-default values - that means you don't have to set I<all> of the
-values when you only want to change one. Here is an example:
-
- $a = new DB_File::HASHINFO ;
- $a->{'cachesize'} = 12345 ;
- tie %y, 'DB_File', "filename", $flags, 0777, $a ;
-
-A few of the options need extra discussion here. When used, the C
-equivalent of the keys C<hash>, C<compare> and C<prefix> store pointers
-to C functions. In B<DB_File> these keys are used to store references
-to Perl subs. Below are templates for each of the subs:
-
- sub hash
- {
- my ($data) = @_ ;
- ...
- # return the hash value for $data
- return $hash ;
- }
-
- sub compare
- {
- my ($key, $key2) = @_ ;
- ...
- # return 0 if $key1 eq $key2
- # -1 if $key1 lt $key2
- # 1 if $key1 gt $key2
- return (-1 , 0 or 1) ;
- }
-
- sub prefix
- {
- my ($key, $key2) = @_ ;
- ...
- # return number of bytes of $key2 which are
- # necessary to determine that it is greater than $key1
- return $bytes ;
- }
-
-See L<Changing the BTREE sort order> for an example of using the
-C<compare> template.
-
-If you are using the DB_RECNO interface and you intend making use of
-C<bval>, you should check out L<The 'bval' Option>.
-
-=head2 Default Parameters
-
-It is possible to omit some or all of the final 4 parameters in the
-call to C<tie> and let them take default values. As DB_HASH is the most
-common file format used, the call:
-
- tie %A, "DB_File", "filename" ;
-
-is equivalent to:
-
- tie %A, "DB_File", "filename", O_CREAT|O_RDWR, 0666, $DB_HASH ;
-
-It is also possible to omit the filename parameter as well, so the
-call:
-
- tie %A, "DB_File" ;
-
-is equivalent to:
-
- tie %A, "DB_File", undef, O_CREAT|O_RDWR, 0666, $DB_HASH ;
-
-See L<In Memory Databases> for a discussion on the use of C<undef>
-in place of a filename.
-
-=head2 In Memory Databases
-
-Berkeley DB allows the creation of in-memory databases by using NULL
-(that is, a C<(char *)0> in C) in place of the filename. B<DB_File>
-uses C<undef> instead of NULL to provide this functionality.
-
-=head1 DB_HASH
-
-The DB_HASH file format is probably the most commonly used of the three
-file formats that B<DB_File> supports. It is also very straightforward
-to use.
-
-=head2 A Simple Example
-
-This example shows how to create a database, add key/value pairs to the
-database, delete keys/value pairs and finally how to enumerate the
-contents of the database.
-
- use warnings ;
- use strict ;
- use DB_File ;
- use vars qw( %h $k $v ) ;
-
- unlink "fruit" ;
- tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH
- or die "Cannot open file 'fruit': $!\n";
-
- # Add a few key/value pairs to the file
- $h{"apple"} = "red" ;
- $h{"orange"} = "orange" ;
- $h{"banana"} = "yellow" ;
- $h{"tomato"} = "red" ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $h{"banana"} ;
-
- # Delete a key/value pair.
- delete $h{"apple"} ;
-
- # print the contents of the file
- while (($k, $v) = each %h)
- { print "$k -> $v\n" }
-
- untie %h ;
-
-here is the output:
-
- Banana Exists
-
- orange -> orange
- tomato -> red
- banana -> yellow
-
-Note that the like ordinary associative arrays, the order of the keys
-retrieved is in an apparently random order.
-
-=head1 DB_BTREE
-
-The DB_BTREE format is useful when you want to store data in a given
-order. By default the keys will be stored in lexical order, but as you
-will see from the example shown in the next section, it is very easy to
-define your own sorting function.
-
-=head2 Changing the BTREE sort order
-
-This script shows how to override the default sorting algorithm that
-BTREE uses. Instead of using the normal lexical ordering, a case
-insensitive compare function will be used.
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- my %h ;
-
- sub Compare
- {
- my ($key1, $key2) = @_ ;
- "\L$key1" cmp "\L$key2" ;
- }
-
- # specify the Perl sub that will do the comparison
- $DB_BTREE->{'compare'} = \&Compare ;
-
- unlink "tree" ;
- tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open file 'tree': $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
-
-Here is the output from the code above.
-
- mouse
- Smith
- Wall
-
-There are a few point to bear in mind if you want to change the
-ordering in a BTREE database:
-
-=over 5
-
-=item 1.
-
-The new compare function must be specified when you create the database.
-
-=item 2.
-
-You cannot change the ordering once the database has been created. Thus
-you must use the same compare function every time you access the
-database.
-
-=back
-
-=head2 Handling Duplicate Keys
-
-The BTREE file type optionally allows a single key to be associated
-with an arbitrary number of values. This option is enabled by setting
-the flags element of C<$DB_BTREE> to R_DUP when creating the database.
-
-There are some difficulties in using the tied hash interface if you
-want to manipulate a BTREE database with duplicate keys. Consider this
-code:
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename %h ) ;
-
- $filename = "tree" ;
- unlink $filename ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- # Add some key/value pairs to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Wall'} = 'Brick' ; # Note the duplicate key
- $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
-
- # iterate through the associative array
- # and print each key/value pair.
- foreach (sort keys %h)
- { print "$_ -> $h{$_}\n" }
-
- untie %h ;
-
-Here is the output:
-
- Smith -> John
- Wall -> Larry
- Wall -> Larry
- Wall -> Larry
- mouse -> mickey
-
-As you can see 3 records have been successfully created with key C<Wall>
-- the only thing is, when they are retrieved from the database they
-I<seem> to have the same value, namely C<Larry>. The problem is caused
-by the way that the associative array interface works. Basically, when
-the associative array interface is used to fetch the value associated
-with a given key, it will only ever retrieve the first value.
-
-Although it may not be immediately obvious from the code above, the
-associative array interface can be used to write values with duplicate
-keys, but it cannot be used to read them back from the database.
-
-The way to get around this problem is to use the Berkeley DB API method
-called C<seq>. This method allows sequential access to key/value
-pairs. See L<THE API INTERFACE> for details of both the C<seq> method
-and the API in general.
-
-Here is the script above rewritten using the C<seq> API method.
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h $status $key $value) ;
-
- $filename = "tree" ;
- unlink $filename ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- # Add some key/value pairs to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Wall'} = 'Brick' ; # Note the duplicate key
- $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
-
- # iterate through the btree using seq
- # and print each key/value pair.
- $key = $value = 0 ;
- for ($status = $x->seq($key, $value, R_FIRST) ;
- $status == 0 ;
- $status = $x->seq($key, $value, R_NEXT) )
- { print "$key -> $value\n" }
-
- undef $x ;
- untie %h ;
-
-that prints:
-
- Smith -> John
- Wall -> Brick
- Wall -> Brick
- Wall -> Larry
- mouse -> mickey
-
-This time we have got all the key/value pairs, including the multiple
-values associated with the key C<Wall>.
-
-To make life easier when dealing with duplicate keys, B<DB_File> comes with
-a few utility methods.
-
-=head2 The get_dup() Method
-
-The C<get_dup> method assists in
-reading duplicate values from BTREE databases. The method can take the
-following forms:
-
- $count = $x->get_dup($key) ;
- @list = $x->get_dup($key) ;
- %list = $x->get_dup($key, 1) ;
-
-In a scalar context the method returns the number of values associated
-with the key, C<$key>.
-
-In list context, it returns all the values which match C<$key>. Note
-that the values will be returned in an apparently random order.
-
-In list context, if the second parameter is present and evaluates
-TRUE, the method returns an associative array. The keys of the
-associative array correspond to the values that matched in the BTREE
-and the values of the array are a count of the number of times that
-particular value occurred in the BTREE.
-
-So assuming the database created above, we can use C<get_dup> like
-this:
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h ) ;
-
- $filename = "tree" ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- my $cnt = $x->get_dup("Wall") ;
- print "Wall occurred $cnt times\n" ;
-
- my %hash = $x->get_dup("Wall", 1) ;
- print "Larry is there\n" if $hash{'Larry'} ;
- print "There are $hash{'Brick'} Brick Walls\n" ;
-
- my @list = sort $x->get_dup("Wall") ;
- print "Wall => [@list]\n" ;
-
- @list = $x->get_dup("Smith") ;
- print "Smith => [@list]\n" ;
-
- @list = $x->get_dup("Dog") ;
- print "Dog => [@list]\n" ;
-
-
-and it will print:
-
- Wall occurred 3 times
- Larry is there
- There are 2 Brick Walls
- Wall => [Brick Brick Larry]
- Smith => [John]
- Dog => []
-
-=head2 The find_dup() Method
-
- $status = $X->find_dup($key, $value) ;
-
-This method checks for the existence of a specific key/value pair. If the
-pair exists, the cursor is left pointing to the pair and the method
-returns 0. Otherwise the method returns a non-zero value.
-
-Assuming the database from the previous example:
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h $found) ;
-
- my $filename = "tree" ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
- print "Larry Wall is $found there\n" ;
-
- $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
- print "Harry Wall is $found there\n" ;
-
- undef $x ;
- untie %h ;
-
-prints this
-
- Larry Wall is there
- Harry Wall is not there
-
-
-=head2 The del_dup() Method
-
- $status = $X->del_dup($key, $value) ;
-
-This method deletes a specific key/value pair. It returns
-0 if they exist and have been deleted successfully.
-Otherwise the method returns a non-zero value.
-
-Again assuming the existence of the C<tree> database
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h $found) ;
-
- my $filename = "tree" ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- $x->del_dup("Wall", "Larry") ;
-
- $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
- print "Larry Wall is $found there\n" ;
-
- undef $x ;
- untie %h ;
-
-prints this
-
- Larry Wall is not there
-
-=head2 Matching Partial Keys
-
-The BTREE interface has a feature which allows partial keys to be
-matched. This functionality is I<only> available when the C<seq> method
-is used along with the R_CURSOR flag.
-
- $x->seq($key, $value, R_CURSOR) ;
-
-Here is the relevant quote from the dbopen man page where it defines
-the use of the R_CURSOR flag with seq:
-
- Note, for the DB_BTREE access method, the returned key is not
- necessarily an exact match for the specified key. The returned key
- is the smallest key greater than or equal to the specified key,
- permitting partial key matches and range searches.
-
-In the example script below, the C<match> sub uses this feature to find
-and print the first matching key/value pair given a partial key.
-
- use warnings ;
- use strict ;
- use DB_File ;
- use Fcntl ;
-
- use vars qw($filename $x %h $st $key $value) ;
-
- sub match
- {
- my $key = shift ;
- my $value = 0;
- my $orig_key = $key ;
- $x->seq($key, $value, R_CURSOR) ;
- print "$orig_key\t-> $key\t-> $value\n" ;
- }
-
- $filename = "tree" ;
- unlink $filename ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- # Add some key/value pairs to the file
- $h{'mouse'} = 'mickey' ;
- $h{'Wall'} = 'Larry' ;
- $h{'Walls'} = 'Brick' ;
- $h{'Smith'} = 'John' ;
-
-
- $key = $value = 0 ;
- print "IN ORDER\n" ;
- for ($st = $x->seq($key, $value, R_FIRST) ;
- $st == 0 ;
- $st = $x->seq($key, $value, R_NEXT) )
-
- { print "$key -> $value\n" }
-
- print "\nPARTIAL MATCH\n" ;
-
- match "Wa" ;
- match "A" ;
- match "a" ;
-
- undef $x ;
- untie %h ;
-
-Here is the output:
-
- IN ORDER
- Smith -> John
- Wall -> Larry
- Walls -> Brick
- mouse -> mickey
-
- PARTIAL MATCH
- Wa -> Wall -> Larry
- A -> Smith -> John
- a -> mouse -> mickey
-
-=head1 DB_RECNO
-
-DB_RECNO provides an interface to flat text files. Both variable and
-fixed length records are supported.
-
-In order to make RECNO more compatible with Perl, the array offset for
-all RECNO arrays begins at 0 rather than 1 as in Berkeley DB.
-
-As with normal Perl arrays, a RECNO array can be accessed using
-negative indexes. The index -1 refers to the last element of the array,
--2 the second last, and so on. Attempting to access an element before
-the start of the array will raise a fatal run-time error.
-
-=head2 The 'bval' Option
-
-The operation of the bval option warrants some discussion. Here is the
-definition of bval from the Berkeley DB 1.85 recno manual page:
-
- The delimiting byte to be used to mark the end of a
- record for variable-length records, and the pad charac-
- ter for fixed-length records. If no value is speci-
- fied, newlines (``\n'') are used to mark the end of
- variable-length records and fixed-length records are
- padded with spaces.
-
-The second sentence is wrong. In actual fact bval will only default to
-C<"\n"> when the openinfo parameter in dbopen is NULL. If a non-NULL
-openinfo parameter is used at all, the value that happens to be in bval
-will be used. That means you always have to specify bval when making
-use of any of the options in the openinfo parameter. This documentation
-error will be fixed in the next release of Berkeley DB.
-
-That clarifies the situation with regards Berkeley DB itself. What
-about B<DB_File>? Well, the behavior defined in the quote above is
-quite useful, so B<DB_File> conforms to it.
-
-That means that you can specify other options (e.g. cachesize) and
-still have bval default to C<"\n"> for variable length records, and
-space for fixed length records.
-
-=head2 A Simple Example
-
-Here is a simple example that uses RECNO (if you are using a version
-of Perl earlier than 5.004_57 this example won't work -- see
-L<Extra RECNO Methods> for a workaround).
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO
- or die "Cannot open file 'text': $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- push @h, "green", "black" ;
-
- my $elements = scalar @h ;
- print "The array contains $elements entries\n" ;
-
- my $last = pop @h ;
- print "popped $last\n" ;
-
- unshift @h, "white" ;
- my $first = shift @h ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- # use a negative index
- print "The last element is $h[-1]\n" ;
- print "The 2nd last element is $h[-2]\n" ;
-
- untie @h ;
-
-Here is the output from the script:
-
- The array contains 5 entries
- popped black
- shifted white
- Element 1 Exists with value blue
- The last element is green
- The 2nd last element is yellow
-
-=head2 Extra RECNO Methods
-
-If you are using a version of Perl earlier than 5.004_57, the tied
-array interface is quite limited. In the example script above
-C<push>, C<pop>, C<shift>, C<unshift>
-or determining the array length will not work with a tied array.
-
-To make the interface more useful for older versions of Perl, a number
-of methods are supplied with B<DB_File> to simulate the missing array
-operations. All these methods are accessed via the object returned from
-the tie call.
-
-Here are the methods:
-
-=over 5
-
-=item B<$X-E<gt>push(list) ;>
-
-Pushes the elements of C<list> to the end of the array.
-
-=item B<$value = $X-E<gt>pop ;>
-
-Removes and returns the last element of the array.
-
-=item B<$X-E<gt>shift>
-
-Removes and returns the first element of the array.
-
-=item B<$X-E<gt>unshift(list) ;>
-
-Pushes the elements of C<list> to the start of the array.
-
-=item B<$X-E<gt>length>
-
-Returns the number of elements in the array.
-
-=back
-
-=head2 Another Example
-
-Here is a more complete example that makes use of some of the methods
-described above. It also makes use of the API interface directly (see
-L<THE API INTERFACE>).
-
- use warnings ;
- use strict ;
- use vars qw(@h $H $file $i) ;
- use DB_File ;
- use Fcntl ;
-
- $file = "text" ;
-
- unlink $file ;
-
- $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0640, $DB_RECNO
- or die "Cannot open file $file: $!\n" ;
-
- # first create a text file to play with
- $h[0] = "zero" ;
- $h[1] = "one" ;
- $h[2] = "two" ;
- $h[3] = "three" ;
- $h[4] = "four" ;
-
-
- # Print the records in order.
- #
- # The length method is needed here because evaluating a tied
- # array in a scalar context does not return the number of
- # elements in the array.
-
- print "\nORIGINAL\n" ;
- foreach $i (0 .. $H->length - 1) {
- print "$i: $h[$i]\n" ;
- }
-
- # use the push & pop methods
- $a = $H->pop ;
- $H->push("last") ;
- print "\nThe last record was [$a]\n" ;
-
- # and the shift & unshift methods
- $a = $H->shift ;
- $H->unshift("first") ;
- print "The first record was [$a]\n" ;
-
- # Use the API to add a new record after record 2.
- $i = 2 ;
- $H->put($i, "Newbie", R_IAFTER) ;
-
- # and a new record before record 1.
- $i = 1 ;
- $H->put($i, "New One", R_IBEFORE) ;
-
- # delete record 3
- $H->del(3) ;
-
- # now print the records in reverse order
- print "\nREVERSE\n" ;
- for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
- { print "$i: $h[$i]\n" }
-
- # same again, but use the API functions instead
- print "\nREVERSE again\n" ;
- my ($s, $k, $v) = (0, 0, 0) ;
- for ($s = $H->seq($k, $v, R_LAST) ;
- $s == 0 ;
- $s = $H->seq($k, $v, R_PREV))
- { print "$k: $v\n" }
-
- undef $H ;
- untie @h ;
-
-and this is what it outputs:
-
- ORIGINAL
- 0: zero
- 1: one
- 2: two
- 3: three
- 4: four
-
- The last record was [four]
- The first record was [zero]
-
- REVERSE
- 5: last
- 4: three
- 3: Newbie
- 2: one
- 1: New One
- 0: first
-
- REVERSE again
- 5: last
- 4: three
- 3: Newbie
- 2: one
- 1: New One
- 0: first
-
-Notes:
-
-=over 5
-
-=item 1.
-
-Rather than iterating through the array, C<@h> like this:
-
- foreach $i (@h)
-
-it is necessary to use either this:
-
- foreach $i (0 .. $H->length - 1)
-
-or this:
-
- for ($a = $H->get($k, $v, R_FIRST) ;
- $a == 0 ;
- $a = $H->get($k, $v, R_NEXT) )
-
-=item 2.
-
-Notice that both times the C<put> method was used the record index was
-specified using a variable, C<$i>, rather than the literal value
-itself. This is because C<put> will return the record number of the
-inserted line via that parameter.
-
-=back
-
-=head1 THE API INTERFACE
-
-As well as accessing Berkeley DB using a tied hash or array, it is also
-possible to make direct use of most of the API functions defined in the
-Berkeley DB documentation.
-
-To do this you need to store a copy of the object returned from the tie.
-
- $db = tie %hash, "DB_File", "filename" ;
-
-Once you have done that, you can access the Berkeley DB API functions
-as B<DB_File> methods directly like this:
-
- $db->put($key, $value, R_NOOVERWRITE) ;
-
-B<Important:> If you have saved a copy of the object returned from
-C<tie>, the underlying database file will I<not> be closed until both
-the tied variable is untied and all copies of the saved object are
-destroyed.
-
- use DB_File ;
- $db = tie %hash, "DB_File", "filename"
- or die "Cannot tie filename: $!" ;
- ...
- undef $db ;
- untie %hash ;
-
-See L<The untie() Gotcha> for more details.
-
-All the functions defined in L<dbopen> are available except for
-close() and dbopen() itself. The B<DB_File> method interface to the
-supported functions have been implemented to mirror the way Berkeley DB
-works whenever possible. In particular note that:
-
-=over 5
-
-=item *
-
-The methods return a status value. All return 0 on success.
-All return -1 to signify an error and set C<$!> to the exact
-error code. The return code 1 generally (but not always) means that the
-key specified did not exist in the database.
-
-Other return codes are defined. See below and in the Berkeley DB
-documentation for details. The Berkeley DB documentation should be used
-as the definitive source.
-
-=item *
-
-Whenever a Berkeley DB function returns data via one of its parameters,
-the equivalent B<DB_File> method does exactly the same.
-
-=item *
-
-If you are careful, it is possible to mix API calls with the tied
-hash/array interface in the same piece of code. Although only a few of
-the methods used to implement the tied interface currently make use of
-the cursor, you should always assume that the cursor has been changed
-any time the tied hash/array interface is used. As an example, this
-code will probably not do what you expect:
-
- $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
- or die "Cannot tie $filename: $!" ;
-
- # Get the first key/value pair and set the cursor
- $X->seq($key, $value, R_FIRST) ;
-
- # this line will modify the cursor
- $count = scalar keys %x ;
-
- # Get the second key/value pair.
- # oops, it didn't, it got the last key/value pair!
- $X->seq($key, $value, R_NEXT) ;
-
-The code above can be rearranged to get around the problem, like this:
-
- $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
- or die "Cannot tie $filename: $!" ;
-
- # this line will modify the cursor
- $count = scalar keys %x ;
-
- # Get the first key/value pair and set the cursor
- $X->seq($key, $value, R_FIRST) ;
-
- # Get the second key/value pair.
- # worked this time.
- $X->seq($key, $value, R_NEXT) ;
-
-=back
-
-All the constants defined in L<dbopen> for use in the flags parameters
-in the methods defined below are also available. Refer to the Berkeley
-DB documentation for the precise meaning of the flags values.
-
-Below is a list of the methods available.
-
-=over 5
-
-=item B<$status = $X-E<gt>get($key, $value [, $flags]) ;>
-
-Given a key (C<$key>) this method reads the value associated with it
-from the database. The value read from the database is returned in the
-C<$value> parameter.
-
-If the key does not exist the method returns 1.
-
-No flags are currently defined for this method.
-
-=item B<$status = $X-E<gt>put($key, $value [, $flags]) ;>
-
-Stores the key/value pair in the database.
-
-If you use either the R_IAFTER or R_IBEFORE flags, the C<$key> parameter
-will have the record number of the inserted key/value pair set.
-
-Valid flags are R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE and
-R_SETCURSOR.
-
-=item B<$status = $X-E<gt>del($key [, $flags]) ;>
-
-Removes all key/value pairs with key C<$key> from the database.
-
-A return code of 1 means that the requested key was not in the
-database.
-
-R_CURSOR is the only valid flag at present.
-
-=item B<$status = $X-E<gt>fd ;>
-
-Returns the file descriptor for the underlying database.
-
-See L<Locking: The Trouble with fd> for an explanation for why you should
-not use C<fd> to lock your database.
-
-=item B<$status = $X-E<gt>seq($key, $value, $flags) ;>
-
-This interface allows sequential retrieval from the database. See
-L<dbopen> for full details.
-
-Both the C<$key> and C<$value> parameters will be set to the key/value
-pair read from the database.
-
-The flags parameter is mandatory. The valid flag values are R_CURSOR,
-R_FIRST, R_LAST, R_NEXT and R_PREV.
-
-=item B<$status = $X-E<gt>sync([$flags]) ;>
-
-Flushes any cached buffers to disk.
-
-R_RECNOSYNC is the only valid flag at present.
-
-=back
-
-=head1 DBM FILTERS
-
-A DBM Filter is a piece of code that is be used when you I<always>
-want to make the same transformation to all keys and/or values in a
-DBM database.
-
-There are four methods associated with DBM Filters. All work identically,
-and each is used to install (or uninstall) a single DBM Filter. Each
-expects a single parameter, namely a reference to a sub. The only
-difference between them is the place that the filter is installed.
-
-To summarise:
-
-=over 5
-
-=item B<filter_store_key>
-
-If a filter has been installed with this method, it will be invoked
-every time you write a key to a DBM database.
-
-=item B<filter_store_value>
-
-If a filter has been installed with this method, it will be invoked
-every time you write a value to a DBM database.
-
-
-=item B<filter_fetch_key>
-
-If a filter has been installed with this method, it will be invoked
-every time you read a key from a DBM database.
-
-=item B<filter_fetch_value>
-
-If a filter has been installed with this method, it will be invoked
-every time you read a value from a DBM database.
-
-=back
-
-You can use any combination of the methods, from none, to all four.
-
-All filter methods return the existing filter, if present, or C<undef>
-in not.
-
-To delete a filter pass C<undef> to it.
-
-=head2 The Filter
-
-When each filter is called by Perl, a local copy of C<$_> will contain
-the key or value to be filtered. Filtering is achieved by modifying
-the contents of C<$_>. The return code from the filter is ignored.
-
-=head2 An Example -- the NULL termination problem.
-
-Consider the following scenario. You have a DBM database
-that you need to share with a third-party C application. The C application
-assumes that I<all> keys and values are NULL terminated. Unfortunately
-when Perl writes to DBM databases it doesn't use NULL termination, so
-your Perl application will have to manage NULL termination itself. When
-you write to the database you will have to use something like this:
-
- $hash{"$key\0"} = "$value\0" ;
-
-Similarly the NULL needs to be taken into account when you are considering
-the length of existing keys/values.
-
-It would be much better if you could ignore the NULL terminations issue
-in the main application code and have a mechanism that automatically
-added the terminating NULL to all keys and values whenever you write to
-the database and have them removed when you read from the database. As I'm
-sure you have already guessed, this is a problem that DBM Filters can
-fix very easily.
-
- use warnings ;
- use strict ;
- use DB_File ;
-
- my %hash ;
- my $filename = "/tmp/filt" ;
- unlink $filename ;
-
- my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
- or die "Cannot open $filename: $!\n" ;
-
- # Install DBM Filters
- $db->filter_fetch_key ( sub { s/\0$// } ) ;
- $db->filter_store_key ( sub { $_ .= "\0" } ) ;
- $db->filter_fetch_value( sub { s/\0$// } ) ;
- $db->filter_store_value( sub { $_ .= "\0" } ) ;
-
- $hash{"abc"} = "def" ;
- my $a = $hash{"ABC"} ;
- # ...
- undef $db ;
- untie %hash ;
-
-Hopefully the contents of each of the filters should be
-self-explanatory. Both "fetch" filters remove the terminating NULL,
-and both "store" filters add a terminating NULL.
-
-
-=head2 Another Example -- Key is a C int.
-
-Here is another real-life example. By default, whenever Perl writes to
-a DBM database it always writes the key and value as strings. So when
-you use this:
-
- $hash{12345} = "soemthing" ;
-
-the key 12345 will get stored in the DBM database as the 5 byte string
-"12345". If you actually want the key to be stored in the DBM database
-as a C int, you will have to use C<pack> when writing, and C<unpack>
-when reading.
-
-Here is a DBM Filter that does it:
-
- use warnings ;
- use strict ;
- use DB_File ;
- my %hash ;
- my $filename = "/tmp/filt" ;
- unlink $filename ;
-
-
- my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
- or die "Cannot open $filename: $!\n" ;
-
- $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
- $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
- $hash{123} = "def" ;
- # ...
- undef $db ;
- untie %hash ;
-
-This time only two filters have been used -- we only need to manipulate
-the contents of the key, so it wasn't necessary to install any value
-filters.
-
-=head1 HINTS AND TIPS
-
-
-=head2 Locking: The Trouble with fd
-
-Until version 1.72 of this module, the recommended technique for locking
-B<DB_File> databases was to flock the filehandle returned from the "fd"
-function. Unfortunately this technique has been shown to be fundamentally
-flawed (Kudos to David Harris for tracking this down). Use it at your own
-peril!
-
-The locking technique went like this.
-
- $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0644)
- || die "dbcreat /tmp/foo.db $!";
- $fd = $db->fd;
- open(DB_FH, "+<&=$fd") || die "dup $!";
- flock (DB_FH, LOCK_EX) || die "flock: $!";
- ...
- $db{"Tom"} = "Jerry" ;
- ...
- flock(DB_FH, LOCK_UN);
- undef $db;
- untie %db;
- close(DB_FH);
-
-In simple terms, this is what happens:
-
-=over 5
-
-=item 1.
-
-Use "tie" to open the database.
-
-=item 2.
-
-Lock the database with fd & flock.
-
-=item 3.
-
-Read & Write to the database.
-
-=item 4.
-
-Unlock and close the database.
-
-=back
-
-Here is the crux of the problem. A side-effect of opening the B<DB_File>
-database in step 2 is that an initial block from the database will get
-read from disk and cached in memory.
-
-To see why this is a problem, consider what can happen when two processes,
-say "A" and "B", both want to update the same B<DB_File> database
-using the locking steps outlined above. Assume process "A" has already
-opened the database and has a write lock, but it hasn't actually updated
-the database yet (it has finished step 2, but not started step 3 yet). Now
-process "B" tries to open the same database - step 1 will succeed,
-but it will block on step 2 until process "A" releases the lock. The
-important thing to notice here is that at this point in time both
-processes will have cached identical initial blocks from the database.
-
-Now process "A" updates the database and happens to change some of the
-data held in the initial buffer. Process "A" terminates, flushing
-all cached data to disk and releasing the database lock. At this point
-the database on disk will correctly reflect the changes made by process
-"A".
-
-With the lock released, process "B" can now continue. It also updates the
-database and unfortunately it too modifies the data that was in its
-initial buffer. Once that data gets flushed to disk it will overwrite
-some/all of the changes process "A" made to the database.
-
-The result of this scenario is at best a database that doesn't contain
-what you expect. At worst the database will corrupt.
-
-The above won't happen every time competing process update the same
-B<DB_File> database, but it does illustrate why the technique should
-not be used.
-
-=head2 Safe ways to lock a database
-
-Starting with version 2.x, Berkeley DB has internal support for locking.
-The companion module to this one, B<BerkeleyDB>, provides an interface
-to this locking functionality. If you are serious about locking
-Berkeley DB databases, I strongly recommend using B<BerkeleyDB>.
-
-If using B<BerkeleyDB> isn't an option, there are a number of modules
-available on CPAN that can be used to implement locking. Each one
-implements locking differently and has different goals in mind. It is
-therefore worth knowing the difference, so that you can pick the right
-one for your application. Here are the three locking wrappers:
-
-=over 5
-
-=item B<Tie::DB_Lock>
-
-A B<DB_File> wrapper which creates copies of the database file for
-read access, so that you have a kind of a multiversioning concurrent read
-system. However, updates are still serial. Use for databases where reads
-may be lengthy and consistency problems may occur.
-
-=item B<Tie::DB_LockFile>
-
-A B<DB_File> wrapper that has the ability to lock and unlock the database
-while it is being used. Avoids the tie-before-flock problem by simply
-re-tie-ing the database when you get or drop a lock. Because of the
-flexibility in dropping and re-acquiring the lock in the middle of a
-session, this can be massaged into a system that will work with long
-updates and/or reads if the application follows the hints in the POD
-documentation.
-
-=item B<DB_File::Lock>
-
-An extremely lightweight B<DB_File> wrapper that simply flocks a lockfile
-before tie-ing the database and drops the lock after the untie. Allows
-one to use the same lockfile for multiple databases to avoid deadlock
-problems, if desired. Use for databases where updates are reads are
-quick and simple flock locking semantics are enough.
-
-=back
-
-=head2 Sharing Databases With C Applications
-
-There is no technical reason why a Berkeley DB database cannot be
-shared by both a Perl and a C application.
-
-The vast majority of problems that are reported in this area boil down
-to the fact that C strings are NULL terminated, whilst Perl strings are
-not. See L<DBM FILTERS> for a generic way to work around this problem.
-
-Here is a real example. Netscape 2.0 keeps a record of the locations you
-visit along with the time you last visited them in a DB_HASH database.
-This is usually stored in the file F<~/.netscape/history.db>. The key
-field in the database is the location string and the value field is the
-time the location was last visited stored as a 4 byte binary value.
-
-If you haven't already guessed, the location string is stored with a
-terminating NULL. This means you need to be careful when accessing the
-database.
-
-Here is a snippet of code that is loosely based on Tom Christiansen's
-I<ggh> script (available from your nearest CPAN archive in
-F<authors/id/TOMC/scripts/nshist.gz>).
-
- use warnings ;
- use strict ;
- use DB_File ;
- use Fcntl ;
-
- use vars qw( $dotdir $HISTORY %hist_db $href $binary_time $date ) ;
- $dotdir = $ENV{HOME} || $ENV{LOGNAME};
-
- $HISTORY = "$dotdir/.netscape/history.db";
-
- tie %hist_db, 'DB_File', $HISTORY
- or die "Cannot open $HISTORY: $!\n" ;;
-
- # Dump the complete database
- while ( ($href, $binary_time) = each %hist_db ) {
-
- # remove the terminating NULL
- $href =~ s/\x00$// ;
-
- # convert the binary time into a user friendly string
- $date = localtime unpack("V", $binary_time);
- print "$date $href\n" ;
- }
-
- # check for the existence of a specific key
- # remember to add the NULL
- if ( $binary_time = $hist_db{"http://mox.perl.com/\x00"} ) {
- $date = localtime unpack("V", $binary_time) ;
- print "Last visited mox.perl.com on $date\n" ;
- }
- else {
- print "Never visited mox.perl.com\n"
- }
-
- untie %hist_db ;
-
-=head2 The untie() Gotcha
-
-If you make use of the Berkeley DB API, it is I<very> strongly
-recommended that you read L<perltie/The untie Gotcha>.
-
-Even if you don't currently make use of the API interface, it is still
-worth reading it.
-
-Here is an example which illustrates the problem from a B<DB_File>
-perspective:
-
- use DB_File ;
- use Fcntl ;
-
- my %x ;
- my $X ;
-
- $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_TRUNC
- or die "Cannot tie first time: $!" ;
-
- $x{123} = 456 ;
-
- untie %x ;
-
- tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
- or die "Cannot tie second time: $!" ;
-
- untie %x ;
-
-When run, the script will produce this error message:
-
- Cannot tie second time: Invalid argument at bad.file line 14.
-
-Although the error message above refers to the second tie() statement
-in the script, the source of the problem is really with the untie()
-statement that precedes it.
-
-Having read L<perltie> you will probably have already guessed that the
-error is caused by the extra copy of the tied object stored in C<$X>.
-If you haven't, then the problem boils down to the fact that the
-B<DB_File> destructor, DESTROY, will not be called until I<all>
-references to the tied object are destroyed. Both the tied variable,
-C<%x>, and C<$X> above hold a reference to the object. The call to
-untie() will destroy the first, but C<$X> still holds a valid
-reference, so the destructor will not get called and the database file
-F<tst.fil> will remain open. The fact that Berkeley DB then reports the
-attempt to open a database that is already open via the catch-all
-"Invalid argument" doesn't help.
-
-If you run the script with the C<-w> flag the error message becomes:
-
- untie attempted while 1 inner references still exist at bad.file line 12.
- Cannot tie second time: Invalid argument at bad.file line 14.
-
-which pinpoints the real problem. Finally the script can now be
-modified to fix the original problem by destroying the API object
-before the untie:
-
- ...
- $x{123} = 456 ;
-
- undef $X ;
- untie %x ;
-
- $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
- ...
-
-
-=head1 COMMON QUESTIONS
-
-=head2 Why is there Perl source in my database?
-
-If you look at the contents of a database file created by DB_File,
-there can sometimes be part of a Perl script included in it.
-
-This happens because Berkeley DB uses dynamic memory to allocate
-buffers which will subsequently be written to the database file. Being
-dynamic, the memory could have been used for anything before DB
-malloced it. As Berkeley DB doesn't clear the memory once it has been
-allocated, the unused portions will contain random junk. In the case
-where a Perl script gets written to the database, the random junk will
-correspond to an area of dynamic memory that happened to be used during
-the compilation of the script.
-
-Unless you don't like the possibility of there being part of your Perl
-scripts embedded in a database file, this is nothing to worry about.
-
-=head2 How do I store complex data structures with DB_File?
-
-Although B<DB_File> cannot do this directly, there is a module which
-can layer transparently over B<DB_File> to accomplish this feat.
-
-Check out the MLDBM module, available on CPAN in the directory
-F<modules/by-module/MLDBM>.
-
-=head2 What does "Invalid Argument" mean?
-
-You will get this error message when one of the parameters in the
-C<tie> call is wrong. Unfortunately there are quite a few parameters to
-get wrong, so it can be difficult to figure out which one it is.
-
-Here are a couple of possibilities:
-
-=over 5
-
-=item 1.
-
-Attempting to reopen a database without closing it.
-
-=item 2.
-
-Using the O_WRONLY flag.
-
-=back
-
-=head2 What does "Bareword 'DB_File' not allowed" mean?
-
-You will encounter this particular error message when you have the
-C<strict 'subs'> pragma (or the full strict pragma) in your script.
-Consider this script:
-
- use warnings ;
- use strict ;
- use DB_File ;
- use vars qw(%x) ;
- tie %x, DB_File, "filename" ;
-
-Running it produces the error in question:
-
- Bareword "DB_File" not allowed while "strict subs" in use
-
-To get around the error, place the word C<DB_File> in either single or
-double quotes, like this:
-
- tie %x, "DB_File", "filename" ;
-
-Although it might seem like a real pain, it is really worth the effort
-of having a C<use strict> in all your scripts.
-
-=head1 REFERENCES
-
-Articles that are either about B<DB_File> or make use of it.
-
-=over 5
-
-=item 1.
-
-I<Full-Text Searching in Perl>, Tim Kientzle (tkientzle@ddj.com),
-Dr. Dobb's Journal, Issue 295, January 1999, pp 34-41
-
-=back
-
-=head1 HISTORY
-
-Moved to the Changes file.
-
-=head1 BUGS
-
-Some older versions of Berkeley DB had problems with fixed length
-records using the RECNO file format. This problem has been fixed since
-version 1.85 of Berkeley DB.
-
-I am sure there are bugs in the code. If you do find any, or can
-suggest any enhancements, I would welcome your comments.
-
-=head1 AVAILABILITY
-
-B<DB_File> comes with the standard Perl source distribution. Look in
-the directory F<ext/DB_File>. Given the amount of time between releases
-of Perl the version that ships with Perl is quite likely to be out of
-date, so the most recent version can always be found on CPAN (see
-L<perlmod/CPAN> for details), in the directory
-F<modules/by-module/DB_File>.
-
-This version of B<DB_File> will work with either version 1.x, 2.x or
-3.x of Berkeley DB, but is limited to the functionality provided by
-version 1.
-
-The official web site for Berkeley DB is F<http://www.sleepycat.com>.
-All versions of Berkeley DB are available there.
-
-Alternatively, Berkeley DB version 1 is available at your nearest CPAN
-archive in F<src/misc/db.1.85.tar.gz>.
-
-If you are running IRIX, then get Berkeley DB version 1 from
-F<http://reality.sgi.com/ariel>. It has the patches necessary to
-compile properly on IRIX 5.3.
-
-=head1 COPYRIGHT
-
-Copyright (c) 1995-1999 Paul Marquess. All rights reserved. This program
-is free software; you can redistribute it and/or modify it under the
-same terms as Perl itself.
-
-Although B<DB_File> is covered by the Perl license, the library it
-makes use of, namely Berkeley DB, is not. Berkeley DB has its own
-copyright and its own license. Please take the time to read it.
-
-Here are are few words taken from the Berkeley DB FAQ (at
-F<http://www.sleepycat.com>) regarding the license:
-
- Do I have to license DB to use it in Perl scripts?
-
- No. The Berkeley DB license requires that software that uses
- Berkeley DB be freely redistributable. In the case of Perl, that
- software is Perl, and not your scripts. Any Perl scripts that you
- write are your property, including scripts that make use of
- Berkeley DB. Neither the Perl license nor the Berkeley DB license
- place any restriction on what you may do with them.
-
-If you are in any doubt about the license situation, contact either the
-Berkeley DB authors or the author of DB_File. See L<"AUTHOR"> for details.
-
-
-=head1 SEE ALSO
-
-L<perl(1)>, L<dbopen(3)>, L<hash(3)>, L<recno(3)>, L<btree(3)>,
-L<dbmfilter>
-
-=head1 AUTHOR
-
-The DB_File interface was written by Paul Marquess
-E<lt>Paul.Marquess@btinternet.comE<gt>.
-Questions about the DB system itself may be addressed to
-E<lt>db@sleepycat.com<gt>.
-
-=cut
diff --git a/bdb/perl.DB_File/DB_File.xs b/bdb/perl.DB_File/DB_File.xs
deleted file mode 100644
index 6811342066d..00000000000
--- a/bdb/perl.DB_File/DB_File.xs
+++ /dev/null
@@ -1,2072 +0,0 @@
-/*
-
- DB_File.xs -- Perl 5 interface to Berkeley DB
-
- written by Paul Marquess <Paul.Marquess@btinternet.com>
- last modified 15th January 2001
- version 1.76
-
- All comments/suggestions/problems are welcome
-
- Copyright (c) 1995-2001 Paul Marquess. All rights reserved.
- This program is free software; you can redistribute it and/or
- modify it under the same terms as Perl itself.
-
- Changes:
- 0.1 - Initial Release
- 0.2 - No longer bombs out if dbopen returns an error.
- 0.3 - Added some support for multiple btree compares
- 1.0 - Complete support for multiple callbacks added.
- Fixed a problem with pushing a value onto an empty list.
- 1.01 - Fixed a SunOS core dump problem.
- The return value from TIEHASH wasn't set to NULL when
- dbopen returned an error.
- 1.02 - Use ALIAS to define TIEARRAY.
- Removed some redundant commented code.
- Merged OS2 code into the main distribution.
- Allow negative subscripts with RECNO interface.
- Changed the default flags to O_CREAT|O_RDWR
- 1.03 - Added EXISTS
- 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
- Dave Hammen, hammen@gothamcity.jsc.nasa.gov
- 1.05 - Added logic to allow prefix & hash types to be specified via
- Makefile.PL
- 1.06 - Minor namespace cleanup: Localized PrintBtree.
- 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
- 1.08 - No change to DB_File.xs
- 1.09 - Default mode for dbopen changed to 0666
- 1.10 - Fixed fd method so that it still returns -1 for
- in-memory files when db 1.86 is used.
- 1.11 - No change to DB_File.xs
- 1.12 - No change to DB_File.xs
- 1.13 - Tidied up a few casts.
- 1.14 - Made it illegal to tie an associative array to a RECNO
- database and an ordinary array to a HASH or BTREE database.
- 1.50 - Make work with both DB 1.x or DB 2.x
- 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
- 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of
- undefined value" warning with db_get and db_seq.
- 1.53 - Added DB_RENUMBER to flags for recno.
- 1.54 - Fixed bug in the fd method
- 1.55 - Fix for AIX from Jarkko Hietaniemi
- 1.56 - No change to DB_File.xs
- 1.57 - added the #undef op to allow building with Threads support.
- 1.58 - Fixed a problem with the use of sv_setpvn. When the
- size is specified as 0, it does a strlen on the data.
- This was ok for DB 1.x, but isn't for DB 2.x.
- 1.59 - No change to DB_File.xs
- 1.60 - Some code tidy up
- 1.61 - added flagSet macro for DB 2.5.x
- fixed typo in O_RDONLY test.
- 1.62 - No change to DB_File.xs
- 1.63 - Fix to alllow DB 2.6.x to build.
- 1.64 - Tidied up the 1.x to 2.x flags mapping code.
- Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
- to fix a flag mapping problem with O_RDONLY on the Hurd
- 1.65 - Fixed a bug in the PUSH logic.
- Added BOOT check that using 2.3.4 or greater
- 1.66 - Added DBM filter code
- 1.67 - Backed off the use of newSVpvn.
- Fixed DBM Filter code for Perl 5.004.
- Fixed a small memory leak in the filter code.
- 1.68 - fixed backward compatability bug with R_IAFTER & R_IBEFORE
- merged in the 5.005_58 changes
- 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly.
- Fixed the R_SETCURSOR bug introduced in 1.68
- Added a new Perl variable $DB_File::db_ver
- 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with
- GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
- Added a BOOT check to test for equivalent versions of db.h &
- libdb.a/so.
- 1.71 - Support for Berkeley DB version 3.
- Support for Berkeley DB 2/3's backward compatability mode.
- Rewrote push
- 1.72 - No change to DB_File.xs
- 1.73 - No change to DB_File.xs
- 1.74 - A call to open needed parenthesised to stop it clashing
- with a win32 macro.
- Added Perl core patches 7703 & 7801.
- 1.75 - Fixed Perl core patch 7703.
- Added suppport to allow DB_File to be built with
- Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
- needed to be changed.
- 1.76 - No change to DB_File.xs
-
-*/
-
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-#ifndef PERL_VERSION
-# include "patchlevel.h"
-# define PERL_REVISION 5
-# define PERL_VERSION PATCHLEVEL
-# define PERL_SUBVERSION SUBVERSION
-#endif
-
-#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
-
-# define PL_sv_undef sv_undef
-# define PL_na na
-
-#endif
-
-/* DEFSV appears first in 5.004_56 */
-#ifndef DEFSV
-# define DEFSV GvSV(defgv)
-#endif
-
-/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
- * shortly #included by the <db.h>) __attribute__ to the possibly
- * already defined __attribute__, for example by GNUC or by Perl. */
-
-#undef __attribute__
-
-/* If Perl has been compiled with Threads support,the symbol op will
- be defined here. This clashes with a field name in db.h, so get rid of it.
- */
-#ifdef op
-# undef op
-#endif
-
-#ifdef COMPAT185
-# include <db_185.h>
-#else
-# include <db.h>
-#endif
-
-#ifdef CAN_PROTOTYPE
-extern void __getBerkeleyDBInfo(void);
-#endif
-
-#ifndef pTHX
-# define pTHX
-# define pTHX_
-# define aTHX
-# define aTHX_
-#endif
-
-#ifndef newSVpvn
-# define newSVpvn(a,b) newSVpv(a,b)
-#endif
-
-#include <fcntl.h>
-
-/* #define TRACE */
-#define DBM_FILTERING
-
-#ifdef TRACE
-# define Trace(x) printf x
-#else
-# define Trace(x)
-#endif
-
-
-#define DBT_clear(x) Zero(&x, 1, DBT) ;
-
-#ifdef DB_VERSION_MAJOR
-
-#if DB_VERSION_MAJOR == 2
-# define BERKELEY_DB_1_OR_2
-#endif
-
-#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
-# define AT_LEAST_DB_3_2
-#endif
-
-/* map version 2 features & constants onto their version 1 equivalent */
-
-#ifdef DB_Prefix_t
-# undef DB_Prefix_t
-#endif
-#define DB_Prefix_t size_t
-
-#ifdef DB_Hash_t
-# undef DB_Hash_t
-#endif
-#define DB_Hash_t u_int32_t
-
-/* DBTYPE stays the same */
-/* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
-#if DB_VERSION_MAJOR == 2
- typedef DB_INFO INFO ;
-#else /* DB_VERSION_MAJOR > 2 */
-# define DB_FIXEDLEN (0x8000)
-#endif /* DB_VERSION_MAJOR == 2 */
-
-/* version 2 has db_recno_t in place of recno_t */
-typedef db_recno_t recno_t;
-
-
-#define R_CURSOR DB_SET_RANGE
-#define R_FIRST DB_FIRST
-#define R_IAFTER DB_AFTER
-#define R_IBEFORE DB_BEFORE
-#define R_LAST DB_LAST
-#define R_NEXT DB_NEXT
-#define R_NOOVERWRITE DB_NOOVERWRITE
-#define R_PREV DB_PREV
-
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
-# define R_SETCURSOR 0x800000
-#else
-# define R_SETCURSOR (-100)
-#endif
-
-#define R_RECNOSYNC 0
-#define R_FIXEDLEN DB_FIXEDLEN
-#define R_DUP DB_DUP
-
-
-#define db_HA_hash h_hash
-#define db_HA_ffactor h_ffactor
-#define db_HA_nelem h_nelem
-#define db_HA_bsize db_pagesize
-#define db_HA_cachesize db_cachesize
-#define db_HA_lorder db_lorder
-
-#define db_BT_compare bt_compare
-#define db_BT_prefix bt_prefix
-#define db_BT_flags flags
-#define db_BT_psize db_pagesize
-#define db_BT_cachesize db_cachesize
-#define db_BT_lorder db_lorder
-#define db_BT_maxkeypage
-#define db_BT_minkeypage
-
-
-#define db_RE_reclen re_len
-#define db_RE_flags flags
-#define db_RE_bval re_pad
-#define db_RE_bfname re_source
-#define db_RE_psize db_pagesize
-#define db_RE_cachesize db_cachesize
-#define db_RE_lorder db_lorder
-
-#define TXN NULL,
-
-#define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
-
-
-#define DBT_flags(x) x.flags = 0
-#define DB_flags(x, v) x |= v
-
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
-# define flagSet(flags, bitmask) ((flags) & (bitmask))
-#else
-# define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
-#endif
-
-#else /* db version 1.x */
-
-#define BERKELEY_DB_1
-#define BERKELEY_DB_1_OR_2
-
-typedef union INFO {
- HASHINFO hash ;
- RECNOINFO recno ;
- BTREEINFO btree ;
- } INFO ;
-
-
-#ifdef mDB_Prefix_t
-# ifdef DB_Prefix_t
-# undef DB_Prefix_t
-# endif
-# define DB_Prefix_t mDB_Prefix_t
-#endif
-
-#ifdef mDB_Hash_t
-# ifdef DB_Hash_t
-# undef DB_Hash_t
-# endif
-# define DB_Hash_t mDB_Hash_t
-#endif
-
-#define db_HA_hash hash.hash
-#define db_HA_ffactor hash.ffactor
-#define db_HA_nelem hash.nelem
-#define db_HA_bsize hash.bsize
-#define db_HA_cachesize hash.cachesize
-#define db_HA_lorder hash.lorder
-
-#define db_BT_compare btree.compare
-#define db_BT_prefix btree.prefix
-#define db_BT_flags btree.flags
-#define db_BT_psize btree.psize
-#define db_BT_cachesize btree.cachesize
-#define db_BT_lorder btree.lorder
-#define db_BT_maxkeypage btree.maxkeypage
-#define db_BT_minkeypage btree.minkeypage
-
-#define db_RE_reclen recno.reclen
-#define db_RE_flags recno.flags
-#define db_RE_bval recno.bval
-#define db_RE_bfname recno.bfname
-#define db_RE_psize recno.psize
-#define db_RE_cachesize recno.cachesize
-#define db_RE_lorder recno.lorder
-
-#define TXN
-
-#define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
-#define DBT_flags(x)
-#define DB_flags(x, v)
-#define flagSet(flags, bitmask) ((flags) & (bitmask))
-
-#endif /* db version 1 */
-
-
-
-#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
-#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
-#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
-
-#define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
-#define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
-
-#ifdef DB_VERSION_MAJOR
-#define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
- (db->dbp->close)(db->dbp, 0) )
-#define db_close(db) ((db->dbp)->close)(db->dbp, 0)
-#define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
- ? ((db->cursor)->c_del)(db->cursor, 0) \
- : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
-
-#else /* ! DB_VERSION_MAJOR */
-
-#define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
-#define db_close(db) ((db->dbp)->close)(db->dbp)
-#define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
-#define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
-
-#endif /* ! DB_VERSION_MAJOR */
-
-
-#define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
-
-typedef struct {
- DBTYPE type ;
- DB * dbp ;
- SV * compare ;
- SV * prefix ;
- SV * hash ;
- int in_memory ;
-#ifdef BERKELEY_DB_1_OR_2
- INFO info ;
-#endif
-#ifdef DB_VERSION_MAJOR
- DBC * cursor ;
-#endif
-#ifdef DBM_FILTERING
- SV * filter_fetch_key ;
- SV * filter_store_key ;
- SV * filter_fetch_value ;
- SV * filter_store_value ;
- int filtering ;
-#endif /* DBM_FILTERING */
-
- } DB_File_type;
-
-typedef DB_File_type * DB_File ;
-typedef DBT DBTKEY ;
-
-#ifdef DBM_FILTERING
-
-#define ckFilter(arg,type,name) \
- if (db->type) { \
- SV * save_defsv ; \
- /* printf("filtering %s\n", name) ;*/ \
- if (db->filtering) \
- croak("recursion detected in %s", name) ; \
- db->filtering = TRUE ; \
- save_defsv = newSVsv(DEFSV) ; \
- sv_setsv(DEFSV, arg) ; \
- PUSHMARK(sp) ; \
- (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
- sv_setsv(arg, DEFSV) ; \
- sv_setsv(DEFSV, save_defsv) ; \
- SvREFCNT_dec(save_defsv) ; \
- db->filtering = FALSE ; \
- /*printf("end of filtering %s\n", name) ;*/ \
- }
-
-#else
-
-#define ckFilter(arg,type, name)
-
-#endif /* DBM_FILTERING */
-
-#define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
-
-#define OutputValue(arg, name) \
- { if (RETVAL == 0) { \
- my_sv_setpvn(arg, name.data, name.size) ; \
- ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
- } \
- }
-
-#define OutputKey(arg, name) \
- { if (RETVAL == 0) \
- { \
- if (db->type != DB_RECNO) { \
- my_sv_setpvn(arg, name.data, name.size); \
- } \
- else \
- sv_setiv(arg, (I32)*(I32*)name.data - 1); \
- ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
- } \
- }
-
-
-/* Internal Global Data */
-static recno_t Value ;
-static recno_t zero = 0 ;
-static DB_File CurrentDB ;
-static DBTKEY empty ;
-
-#ifdef DB_VERSION_MAJOR
-
-static int
-#ifdef CAN_PROTOTYPE
-db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
-#else
-db_put(db, key, value, flags)
-DB_File db ;
-DBTKEY key ;
-DBT value ;
-u_int flags ;
-#endif
-{
- int status ;
-
- if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
- DBC * temp_cursor ;
- DBT l_key, l_value;
-
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
- if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
-#else
- if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
-#endif
- return (-1) ;
-
- memset(&l_key, 0, sizeof(l_key));
- l_key.data = key.data;
- l_key.size = key.size;
- memset(&l_value, 0, sizeof(l_value));
- l_value.data = value.data;
- l_value.size = value.size;
-
- if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
- (void)temp_cursor->c_close(temp_cursor);
- return (-1);
- }
-
- status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
- (void)temp_cursor->c_close(temp_cursor);
-
- return (status) ;
- }
-
-
- if (flagSet(flags, R_CURSOR)) {
- return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
- }
-
- if (flagSet(flags, R_SETCURSOR)) {
- if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
- return -1 ;
- return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
-
- }
-
- return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
-
-}
-
-#endif /* DB_VERSION_MAJOR */
-
-
-static int
-#ifdef AT_LEAST_DB_3_2
-
-#ifdef CAN_PROTOTYPE
-btree_compare(DB * db, const DBT *key1, const DBT *key2)
-#else
-btree_compare(db, key1, key2)
-DB * db ;
-const DBT * key1 ;
-const DBT * key2 ;
-#endif /* CAN_PROTOTYPE */
-
-#else /* Berkeley DB < 3.2 */
-
-#ifdef CAN_PROTOTYPE
-btree_compare(const DBT *key1, const DBT *key2)
-#else
-btree_compare(key1, key2)
-const DBT * key1 ;
-const DBT * key2 ;
-#endif
-
-#endif
-
-{
-#ifdef dTHX
- dTHX;
-#endif
- dSP ;
- void * data1, * data2 ;
- int retval ;
- int count ;
-
- data1 = key1->data ;
- data2 = key2->data ;
-
-#ifndef newSVpvn
- /* As newSVpv will assume that the data pointer is a null terminated C
- string if the size parameter is 0, make sure that data points to an
- empty string if the length is 0
- */
- if (key1->size == 0)
- data1 = "" ;
- if (key2->size == 0)
- data2 = "" ;
-#endif
-
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
- EXTEND(SP,2) ;
- PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
- PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->compare, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
- return (retval) ;
-
-}
-
-static DB_Prefix_t
-#ifdef AT_LEAST_DB_3_2
-
-#ifdef CAN_PROTOTYPE
-btree_prefix(DB * db, const DBT *key1, const DBT *key2)
-#else
-btree_prefix(db, key1, key2)
-Db * db ;
-const DBT * key1 ;
-const DBT * key2 ;
-#endif
-
-#else /* Berkeley DB < 3.2 */
-
-#ifdef CAN_PROTOTYPE
-btree_prefix(const DBT *key1, const DBT *key2)
-#else
-btree_prefix(key1, key2)
-const DBT * key1 ;
-const DBT * key2 ;
-#endif
-
-#endif
-{
-#ifdef dTHX
- dTHX;
-#endif
- dSP ;
- void * data1, * data2 ;
- int retval ;
- int count ;
-
- data1 = key1->data ;
- data2 = key2->data ;
-
-#ifndef newSVpvn
- /* As newSVpv will assume that the data pointer is a null terminated C
- string if the size parameter is 0, make sure that data points to an
- empty string if the length is 0
- */
- if (key1->size == 0)
- data1 = "" ;
- if (key2->size == 0)
- data2 = "" ;
-#endif
-
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
- EXTEND(SP,2) ;
- PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
- PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
-
- return (retval) ;
-}
-
-
-#ifdef BERKELEY_DB_1
-# define HASH_CB_SIZE_TYPE size_t
-#else
-# define HASH_CB_SIZE_TYPE u_int32_t
-#endif
-
-static DB_Hash_t
-#ifdef AT_LEAST_DB_3_2
-
-#ifdef CAN_PROTOTYPE
-hash_cb(DB * db, const void *data, u_int32_t size)
-#else
-hash_cb(db, data, size)
-DB * db ;
-const void * data ;
-HASH_CB_SIZE_TYPE size ;
-#endif
-
-#else /* Berkeley DB < 3.2 */
-
-#ifdef CAN_PROTOTYPE
-hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
-#else
-hash_cb(data, size)
-const void * data ;
-HASH_CB_SIZE_TYPE size ;
-#endif
-
-#endif
-{
-#ifdef dTHX
- dTHX;
-#endif
- dSP ;
- int retval ;
- int count ;
-
-#ifndef newSVpvn
- if (size == 0)
- data = "" ;
-#endif
-
- /* DGH - Next two lines added to fix corrupted stack problem */
- ENTER ;
- SAVETMPS;
-
- PUSHMARK(SP) ;
-
- XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
- PUTBACK ;
-
- count = perl_call_sv(CurrentDB->hash, G_SCALAR);
-
- SPAGAIN ;
-
- if (count != 1)
- croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
-
- retval = POPi ;
-
- PUTBACK ;
- FREETMPS ;
- LEAVE ;
-
- return (retval) ;
-}
-
-
-#if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
-
-static void
-#ifdef CAN_PROTOTYPE
-PrintHash(INFO *hash)
-#else
-PrintHash(hash)
-INFO * hash ;
-#endif
-{
- printf ("HASH Info\n") ;
- printf (" hash = %s\n",
- (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
- printf (" bsize = %d\n", hash->db_HA_bsize) ;
- printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
- printf (" nelem = %d\n", hash->db_HA_nelem) ;
- printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
- printf (" lorder = %d\n", hash->db_HA_lorder) ;
-
-}
-
-static void
-#ifdef CAN_PROTOTYPE
-PrintRecno(INFO *recno)
-#else
-PrintRecno(recno)
-INFO * recno ;
-#endif
-{
- printf ("RECNO Info\n") ;
- printf (" flags = %d\n", recno->db_RE_flags) ;
- printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
- printf (" psize = %d\n", recno->db_RE_psize) ;
- printf (" lorder = %d\n", recno->db_RE_lorder) ;
- printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
- printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
- printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
-}
-
-static void
-#ifdef CAN_PROTOTYPE
-PrintBtree(INFO *btree)
-#else
-PrintBtree(btree)
-INFO * btree ;
-#endif
-{
- printf ("BTREE Info\n") ;
- printf (" compare = %s\n",
- (btree->db_BT_compare ? "redefined" : "default")) ;
- printf (" prefix = %s\n",
- (btree->db_BT_prefix ? "redefined" : "default")) ;
- printf (" flags = %d\n", btree->db_BT_flags) ;
- printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
- printf (" psize = %d\n", btree->db_BT_psize) ;
-#ifndef DB_VERSION_MAJOR
- printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
- printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
-#endif
- printf (" lorder = %d\n", btree->db_BT_lorder) ;
-}
-
-#else
-
-#define PrintRecno(recno)
-#define PrintHash(hash)
-#define PrintBtree(btree)
-
-#endif /* TRACE */
-
-
-static I32
-#ifdef CAN_PROTOTYPE
-GetArrayLength(pTHX_ DB_File db)
-#else
-GetArrayLength(db)
-DB_File db ;
-#endif
-{
- DBT key ;
- DBT value ;
- int RETVAL ;
-
- DBT_clear(key) ;
- DBT_clear(value) ;
- RETVAL = do_SEQ(db, key, value, R_LAST) ;
- if (RETVAL == 0)
- RETVAL = *(I32 *)key.data ;
- else /* No key means empty file */
- RETVAL = 0 ;
-
- return ((I32)RETVAL) ;
-}
-
-static recno_t
-#ifdef CAN_PROTOTYPE
-GetRecnoKey(pTHX_ DB_File db, I32 value)
-#else
-GetRecnoKey(db, value)
-DB_File db ;
-I32 value ;
-#endif
-{
- if (value < 0) {
- /* Get the length of the array */
- I32 length = GetArrayLength(aTHX_ db) ;
-
- /* check for attempt to write before start of array */
- if (length + value + 1 <= 0)
- croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
-
- value = length + value + 1 ;
- }
- else
- ++ value ;
-
- return value ;
-}
-
-
-static DB_File
-#ifdef CAN_PROTOTYPE
-ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
-#else
-ParseOpenInfo(isHASH, name, flags, mode, sv)
-int isHASH ;
-char * name ;
-int flags ;
-int mode ;
-SV * sv ;
-#endif
-{
-
-#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
-
- SV ** svp;
- HV * action ;
- DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
- void * openinfo = NULL ;
- INFO * info = &RETVAL->info ;
- STRLEN n_a;
-
-/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
- Zero(RETVAL, 1, DB_File_type) ;
-
- /* Default to HASH */
-#ifdef DBM_FILTERING
- RETVAL->filtering = 0 ;
- RETVAL->filter_fetch_key = RETVAL->filter_store_key =
- RETVAL->filter_fetch_value = RETVAL->filter_store_value =
-#endif /* DBM_FILTERING */
- RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
- RETVAL->type = DB_HASH ;
-
- /* DGH - Next line added to avoid SEGV on existing hash DB */
- CurrentDB = RETVAL;
-
- /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
- RETVAL->in_memory = (name == NULL) ;
-
- if (sv)
- {
- if (! SvROK(sv) )
- croak ("type parameter is not a reference") ;
-
- svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
- if (svp && SvOK(*svp))
- action = (HV*) SvRV(*svp) ;
- else
- croak("internal error") ;
-
- if (sv_isa(sv, "DB_File::HASHINFO"))
- {
-
- if (!isHASH)
- croak("DB_File can only tie an associative array to a DB_HASH database") ;
-
- RETVAL->type = DB_HASH ;
- openinfo = (void*)info ;
-
- svp = hv_fetch(action, "hash", 4, FALSE);
-
- if (svp && SvOK(*svp))
- {
- info->db_HA_hash = hash_cb ;
- RETVAL->hash = newSVsv(*svp) ;
- }
- else
- info->db_HA_hash = NULL ;
-
- svp = hv_fetch(action, "ffactor", 7, FALSE);
- info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "nelem", 5, FALSE);
- info->db_HA_nelem = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "bsize", 5, FALSE);
- info->db_HA_bsize = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "cachesize", 9, FALSE);
- info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "lorder", 6, FALSE);
- info->db_HA_lorder = svp ? SvIV(*svp) : 0;
-
- PrintHash(info) ;
- }
- else if (sv_isa(sv, "DB_File::BTREEINFO"))
- {
- if (!isHASH)
- croak("DB_File can only tie an associative array to a DB_BTREE database");
-
- RETVAL->type = DB_BTREE ;
- openinfo = (void*)info ;
-
- svp = hv_fetch(action, "compare", 7, FALSE);
- if (svp && SvOK(*svp))
- {
- info->db_BT_compare = btree_compare ;
- RETVAL->compare = newSVsv(*svp) ;
- }
- else
- info->db_BT_compare = NULL ;
-
- svp = hv_fetch(action, "prefix", 6, FALSE);
- if (svp && SvOK(*svp))
- {
- info->db_BT_prefix = btree_prefix ;
- RETVAL->prefix = newSVsv(*svp) ;
- }
- else
- info->db_BT_prefix = NULL ;
-
- svp = hv_fetch(action, "flags", 5, FALSE);
- info->db_BT_flags = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "cachesize", 9, FALSE);
- info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
-
-#ifndef DB_VERSION_MAJOR
- svp = hv_fetch(action, "minkeypage", 10, FALSE);
- info->btree.minkeypage = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "maxkeypage", 10, FALSE);
- info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
-#endif
-
- svp = hv_fetch(action, "psize", 5, FALSE);
- info->db_BT_psize = svp ? SvIV(*svp) : 0;
-
- svp = hv_fetch(action, "lorder", 6, FALSE);
- info->db_BT_lorder = svp ? SvIV(*svp) : 0;
-
- PrintBtree(info) ;
-
- }
- else if (sv_isa(sv, "DB_File::RECNOINFO"))
- {
- if (isHASH)
- croak("DB_File can only tie an array to a DB_RECNO database");
-
- RETVAL->type = DB_RECNO ;
- openinfo = (void *)info ;
-
- info->db_RE_flags = 0 ;
-
- svp = hv_fetch(action, "flags", 5, FALSE);
- info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
-
- svp = hv_fetch(action, "reclen", 6, FALSE);
- info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
-
- svp = hv_fetch(action, "cachesize", 9, FALSE);
- info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
-
- svp = hv_fetch(action, "psize", 5, FALSE);
- info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
-
- svp = hv_fetch(action, "lorder", 6, FALSE);
- info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
-
-#ifdef DB_VERSION_MAJOR
- info->re_source = name ;
- name = NULL ;
-#endif
- svp = hv_fetch(action, "bfname", 6, FALSE);
- if (svp && SvOK(*svp)) {
- char * ptr = SvPV(*svp,n_a) ;
-#ifdef DB_VERSION_MAJOR
- name = (char*) n_a ? ptr : NULL ;
-#else
- info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
-#endif
- }
- else
-#ifdef DB_VERSION_MAJOR
- name = NULL ;
-#else
- info->db_RE_bfname = NULL ;
-#endif
-
- svp = hv_fetch(action, "bval", 4, FALSE);
-#ifdef DB_VERSION_MAJOR
- if (svp && SvOK(*svp))
- {
- int value ;
- if (SvPOK(*svp))
- value = (int)*SvPV(*svp, n_a) ;
- else
- value = SvIV(*svp) ;
-
- if (info->flags & DB_FIXEDLEN) {
- info->re_pad = value ;
- info->flags |= DB_PAD ;
- }
- else {
- info->re_delim = value ;
- info->flags |= DB_DELIMITER ;
- }
-
- }
-#else
- if (svp && SvOK(*svp))
- {
- if (SvPOK(*svp))
- info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
- else
- info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
- DB_flags(info->flags, DB_DELIMITER) ;
-
- }
- else
- {
- if (info->db_RE_flags & R_FIXEDLEN)
- info->db_RE_bval = (u_char) ' ' ;
- else
- info->db_RE_bval = (u_char) '\n' ;
- DB_flags(info->flags, DB_DELIMITER) ;
- }
-#endif
-
-#ifdef DB_RENUMBER
- info->flags |= DB_RENUMBER ;
-#endif
-
- PrintRecno(info) ;
- }
- else
- croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
- }
-
-
- /* OS2 Specific Code */
-#ifdef OS2
-#ifdef __EMX__
- flags |= O_BINARY;
-#endif /* __EMX__ */
-#endif /* OS2 */
-
-#ifdef DB_VERSION_MAJOR
-
- {
- int Flags = 0 ;
- int status ;
-
- /* Map 1.x flags to 2.x flags */
- if ((flags & O_CREAT) == O_CREAT)
- Flags |= DB_CREATE ;
-
-#if O_RDONLY == 0
- if (flags == O_RDONLY)
-#else
- if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
-#endif
- Flags |= DB_RDONLY ;
-
-#ifdef O_TRUNC
- if ((flags & O_TRUNC) == O_TRUNC)
- Flags |= DB_TRUNCATE ;
-#endif
-
- status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
- if (status == 0)
-#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
- status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
-#else
- status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
- 0) ;
-#endif
-
- if (status)
- RETVAL->dbp = NULL ;
-
- }
-#else
-
-#if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
- RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
-#else
- RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
-#endif /* DB_LIBRARY_COMPATIBILITY_API */
-
-#endif
-
- return (RETVAL) ;
-
-#else /* Berkeley DB Version > 2 */
-
- SV ** svp;
- HV * action ;
- DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
- DB * dbp ;
- STRLEN n_a;
- int status ;
-
-/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
- Zero(RETVAL, 1, DB_File_type) ;
-
- /* Default to HASH */
-#ifdef DBM_FILTERING
- RETVAL->filtering = 0 ;
- RETVAL->filter_fetch_key = RETVAL->filter_store_key =
- RETVAL->filter_fetch_value = RETVAL->filter_store_value =
-#endif /* DBM_FILTERING */
- RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
- RETVAL->type = DB_HASH ;
-
- /* DGH - Next line added to avoid SEGV on existing hash DB */
- CurrentDB = RETVAL;
-
- /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
- RETVAL->in_memory = (name == NULL) ;
-
- status = db_create(&RETVAL->dbp, NULL,0) ;
- /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
- if (status) {
- RETVAL->dbp = NULL ;
- return (RETVAL) ;
- }
- dbp = RETVAL->dbp ;
-
- if (sv)
- {
- if (! SvROK(sv) )
- croak ("type parameter is not a reference") ;
-
- svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
- if (svp && SvOK(*svp))
- action = (HV*) SvRV(*svp) ;
- else
- croak("internal error") ;
-
- if (sv_isa(sv, "DB_File::HASHINFO"))
- {
-
- if (!isHASH)
- croak("DB_File can only tie an associative array to a DB_HASH database") ;
-
- RETVAL->type = DB_HASH ;
-
- svp = hv_fetch(action, "hash", 4, FALSE);
-
- if (svp && SvOK(*svp))
- {
- (void)dbp->set_h_hash(dbp, hash_cb) ;
- RETVAL->hash = newSVsv(*svp) ;
- }
-
- svp = hv_fetch(action, "ffactor", 7, FALSE);
- if (svp)
- (void)dbp->set_h_ffactor(dbp, SvIV(*svp)) ;
-
- svp = hv_fetch(action, "nelem", 5, FALSE);
- if (svp)
- (void)dbp->set_h_nelem(dbp, SvIV(*svp)) ;
-
- svp = hv_fetch(action, "bsize", 5, FALSE);
- if (svp)
- (void)dbp->set_pagesize(dbp, SvIV(*svp));
-
- svp = hv_fetch(action, "cachesize", 9, FALSE);
- if (svp)
- (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
-
- svp = hv_fetch(action, "lorder", 6, FALSE);
- if (svp)
- (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
-
- PrintHash(info) ;
- }
- else if (sv_isa(sv, "DB_File::BTREEINFO"))
- {
- if (!isHASH)
- croak("DB_File can only tie an associative array to a DB_BTREE database");
-
- RETVAL->type = DB_BTREE ;
-
- svp = hv_fetch(action, "compare", 7, FALSE);
- if (svp && SvOK(*svp))
- {
- (void)dbp->set_bt_compare(dbp, btree_compare) ;
- RETVAL->compare = newSVsv(*svp) ;
- }
-
- svp = hv_fetch(action, "prefix", 6, FALSE);
- if (svp && SvOK(*svp))
- {
- (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
- RETVAL->prefix = newSVsv(*svp) ;
- }
-
- svp = hv_fetch(action, "flags", 5, FALSE);
- if (svp)
- (void)dbp->set_flags(dbp, SvIV(*svp)) ;
-
- svp = hv_fetch(action, "cachesize", 9, FALSE);
- if (svp)
- (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
-
- svp = hv_fetch(action, "psize", 5, FALSE);
- if (svp)
- (void)dbp->set_pagesize(dbp, SvIV(*svp)) ;
-
- svp = hv_fetch(action, "lorder", 6, FALSE);
- if (svp)
- (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
-
- PrintBtree(info) ;
-
- }
- else if (sv_isa(sv, "DB_File::RECNOINFO"))
- {
- int fixed = FALSE ;
-
- if (isHASH)
- croak("DB_File can only tie an array to a DB_RECNO database");
-
- RETVAL->type = DB_RECNO ;
-
- svp = hv_fetch(action, "flags", 5, FALSE);
- if (svp) {
- int flags = SvIV(*svp) ;
- /* remove FIXDLEN, if present */
- if (flags & DB_FIXEDLEN) {
- fixed = TRUE ;
- flags &= ~DB_FIXEDLEN ;
- }
- }
-
- svp = hv_fetch(action, "cachesize", 9, FALSE);
- if (svp) {
- status = dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
- }
-
- svp = hv_fetch(action, "psize", 5, FALSE);
- if (svp) {
- status = dbp->set_pagesize(dbp, SvIV(*svp)) ;
- }
-
- svp = hv_fetch(action, "lorder", 6, FALSE);
- if (svp) {
- status = dbp->set_lorder(dbp, SvIV(*svp)) ;
- }
-
- svp = hv_fetch(action, "bval", 4, FALSE);
- if (svp && SvOK(*svp))
- {
- int value ;
- if (SvPOK(*svp))
- value = (int)*SvPV(*svp, n_a) ;
- else
- value = SvIV(*svp) ;
-
- if (fixed) {
- status = dbp->set_re_pad(dbp, value) ;
- }
- else {
- status = dbp->set_re_delim(dbp, value) ;
- }
-
- }
-
- if (fixed) {
- svp = hv_fetch(action, "reclen", 6, FALSE);
- if (svp) {
- u_int32_t len = (u_int32_t)SvIV(*svp) ;
- status = dbp->set_re_len(dbp, len) ;
- }
- }
-
- if (name != NULL) {
- status = dbp->set_re_source(dbp, name) ;
- name = NULL ;
- }
-
- svp = hv_fetch(action, "bfname", 6, FALSE);
- if (svp && SvOK(*svp)) {
- char * ptr = SvPV(*svp,n_a) ;
- name = (char*) n_a ? ptr : NULL ;
- }
- else
- name = NULL ;
-
-
- status = dbp->set_flags(dbp, DB_RENUMBER) ;
-
- if (flags){
- (void)dbp->set_flags(dbp, flags) ;
- }
- PrintRecno(info) ;
- }
- else
- croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
- }
-
- {
- int Flags = 0 ;
- int status ;
-
- /* Map 1.x flags to 3.x flags */
- if ((flags & O_CREAT) == O_CREAT)
- Flags |= DB_CREATE ;
-
-#if O_RDONLY == 0
- if (flags == O_RDONLY)
-#else
- if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
-#endif
- Flags |= DB_RDONLY ;
-
-#ifdef O_TRUNC
- if ((flags & O_TRUNC) == O_TRUNC)
- Flags |= DB_TRUNCATE ;
-#endif
-
- status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
- Flags, mode) ;
- /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
-
- if (status == 0)
- status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
- 0) ;
- /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
-
- if (status)
- RETVAL->dbp = NULL ;
-
- }
-
- return (RETVAL) ;
-
-#endif /* Berkeley DB Version > 2 */
-
-} /* ParseOpenInfo */
-
-
-static double
-#ifdef CAN_PROTOTYPE
-constant(char *name, int arg)
-#else
-constant(name, arg)
-char *name;
-int arg;
-#endif
-{
- errno = 0;
- switch (*name) {
- case 'A':
- break;
- case 'B':
- if (strEQ(name, "BTREEMAGIC"))
-#ifdef BTREEMAGIC
- return BTREEMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "BTREEVERSION"))
-#ifdef BTREEVERSION
- return BTREEVERSION;
-#else
- goto not_there;
-#endif
- break;
- case 'C':
- break;
- case 'D':
- if (strEQ(name, "DB_LOCK"))
-#ifdef DB_LOCK
- return DB_LOCK;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_SHMEM"))
-#ifdef DB_SHMEM
- return DB_SHMEM;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "DB_TXN"))
-#ifdef DB_TXN
- return (U32)DB_TXN;
-#else
- goto not_there;
-#endif
- break;
- case 'E':
- break;
- case 'F':
- break;
- case 'G':
- break;
- case 'H':
- if (strEQ(name, "HASHMAGIC"))
-#ifdef HASHMAGIC
- return HASHMAGIC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "HASHVERSION"))
-#ifdef HASHVERSION
- return HASHVERSION;
-#else
- goto not_there;
-#endif
- break;
- case 'I':
- break;
- case 'J':
- break;
- case 'K':
- break;
- case 'L':
- break;
- case 'M':
- if (strEQ(name, "MAX_PAGE_NUMBER"))
-#ifdef MAX_PAGE_NUMBER
- return (U32)MAX_PAGE_NUMBER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "MAX_PAGE_OFFSET"))
-#ifdef MAX_PAGE_OFFSET
- return MAX_PAGE_OFFSET;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "MAX_REC_NUMBER"))
-#ifdef MAX_REC_NUMBER
- return (U32)MAX_REC_NUMBER;
-#else
- goto not_there;
-#endif
- break;
- case 'N':
- break;
- case 'O':
- break;
- case 'P':
- break;
- case 'Q':
- break;
- case 'R':
- if (strEQ(name, "RET_ERROR"))
-#ifdef RET_ERROR
- return RET_ERROR;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "RET_SPECIAL"))
-#ifdef RET_SPECIAL
- return RET_SPECIAL;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "RET_SUCCESS"))
-#ifdef RET_SUCCESS
- return RET_SUCCESS;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_CURSOR"))
-#ifdef R_CURSOR
- return R_CURSOR;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_DUP"))
-#ifdef R_DUP
- return R_DUP;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_FIRST"))
-#ifdef R_FIRST
- return R_FIRST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_FIXEDLEN"))
-#ifdef R_FIXEDLEN
- return R_FIXEDLEN;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_IAFTER"))
-#ifdef R_IAFTER
- return R_IAFTER;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_IBEFORE"))
-#ifdef R_IBEFORE
- return R_IBEFORE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_LAST"))
-#ifdef R_LAST
- return R_LAST;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_NEXT"))
-#ifdef R_NEXT
- return R_NEXT;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_NOKEY"))
-#ifdef R_NOKEY
- return R_NOKEY;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_NOOVERWRITE"))
-#ifdef R_NOOVERWRITE
- return R_NOOVERWRITE;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_PREV"))
-#ifdef R_PREV
- return R_PREV;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_RECNOSYNC"))
-#ifdef R_RECNOSYNC
- return R_RECNOSYNC;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_SETCURSOR"))
-#ifdef R_SETCURSOR
- return R_SETCURSOR;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "R_SNAPSHOT"))
-#ifdef R_SNAPSHOT
- return R_SNAPSHOT;
-#else
- goto not_there;
-#endif
- break;
- case 'S':
- break;
- case 'T':
- break;
- case 'U':
- break;
- case 'V':
- break;
- case 'W':
- break;
- case 'X':
- break;
- case 'Y':
- break;
- case 'Z':
- break;
- case '_':
- break;
- }
- errno = EINVAL;
- return 0;
-
-not_there:
- errno = ENOENT;
- return 0;
-}
-
-MODULE = DB_File PACKAGE = DB_File PREFIX = db_
-
-BOOT:
- {
- __getBerkeleyDBInfo() ;
-
- DBT_clear(empty) ;
- empty.data = &zero ;
- empty.size = sizeof(recno_t) ;
- }
-
-double
-constant(name,arg)
- char * name
- int arg
-
-
-DB_File
-db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
- int isHASH
- char * dbtype
- int flags
- int mode
- CODE:
- {
- char * name = (char *) NULL ;
- SV * sv = (SV *) NULL ;
- STRLEN n_a;
-
- if (items >= 3 && SvOK(ST(2)))
- name = (char*) SvPV(ST(2), n_a) ;
-
- if (items == 6)
- sv = ST(5) ;
-
- RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
- if (RETVAL->dbp == NULL)
- RETVAL = NULL ;
- }
- OUTPUT:
- RETVAL
-
-int
-db_DESTROY(db)
- DB_File db
- INIT:
- CurrentDB = db ;
- CLEANUP:
- if (db->hash)
- SvREFCNT_dec(db->hash) ;
- if (db->compare)
- SvREFCNT_dec(db->compare) ;
- if (db->prefix)
- SvREFCNT_dec(db->prefix) ;
-#ifdef DBM_FILTERING
- if (db->filter_fetch_key)
- SvREFCNT_dec(db->filter_fetch_key) ;
- if (db->filter_store_key)
- SvREFCNT_dec(db->filter_store_key) ;
- if (db->filter_fetch_value)
- SvREFCNT_dec(db->filter_fetch_value) ;
- if (db->filter_store_value)
- SvREFCNT_dec(db->filter_store_value) ;
-#endif /* DBM_FILTERING */
- safefree(db) ;
-#ifdef DB_VERSION_MAJOR
- if (RETVAL > 0)
- RETVAL = -1 ;
-#endif
-
-
-int
-db_DELETE(db, key, flags=0)
- DB_File db
- DBTKEY key
- u_int flags
- INIT:
- CurrentDB = db ;
-
-
-int
-db_EXISTS(db, key)
- DB_File db
- DBTKEY key
- CODE:
- {
- DBT value ;
-
- DBT_clear(value) ;
- CurrentDB = db ;
- RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
- }
- OUTPUT:
- RETVAL
-
-int
-db_FETCH(db, key, flags=0)
- DB_File db
- DBTKEY key
- u_int flags
- CODE:
- {
- DBT value ;
-
- DBT_clear(value) ;
- CurrentDB = db ;
- /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
- RETVAL = db_get(db, key, value, flags) ;
- ST(0) = sv_newmortal();
- OutputValue(ST(0), value)
- }
-
-int
-db_STORE(db, key, value, flags=0)
- DB_File db
- DBTKEY key
- DBT value
- u_int flags
- INIT:
- CurrentDB = db ;
-
-
-int
-db_FIRSTKEY(db)
- DB_File db
- CODE:
- {
- DBTKEY key ;
- DBT value ;
-
- DBT_clear(key) ;
- DBT_clear(value) ;
- CurrentDB = db ;
- RETVAL = do_SEQ(db, key, value, R_FIRST) ;
- ST(0) = sv_newmortal();
- OutputKey(ST(0), key) ;
- }
-
-int
-db_NEXTKEY(db, key)
- DB_File db
- DBTKEY key
- CODE:
- {
- DBT value ;
-
- DBT_clear(value) ;
- CurrentDB = db ;
- RETVAL = do_SEQ(db, key, value, R_NEXT) ;
- ST(0) = sv_newmortal();
- OutputKey(ST(0), key) ;
- }
-
-#
-# These would be nice for RECNO
-#
-
-int
-unshift(db, ...)
- DB_File db
- ALIAS: UNSHIFT = 1
- CODE:
- {
- DBTKEY key ;
- DBT value ;
- int i ;
- int One ;
- DB * Db = db->dbp ;
- STRLEN n_a;
-
- DBT_clear(key) ;
- DBT_clear(value) ;
- CurrentDB = db ;
-#ifdef DB_VERSION_MAJOR
- /* get the first value */
- RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
- RETVAL = 0 ;
-#else
- RETVAL = -1 ;
-#endif
- for (i = items-1 ; i > 0 ; --i)
- {
- value.data = SvPV(ST(i), n_a) ;
- value.size = n_a ;
- One = 1 ;
- key.data = &One ;
- key.size = sizeof(int) ;
-#ifdef DB_VERSION_MAJOR
- RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
-#else
- RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
-#endif
- if (RETVAL != 0)
- break;
- }
- }
- OUTPUT:
- RETVAL
-
-I32
-pop(db)
- DB_File db
- ALIAS: POP = 1
- CODE:
- {
- DBTKEY key ;
- DBT value ;
-
- DBT_clear(key) ;
- DBT_clear(value) ;
- CurrentDB = db ;
-
- /* First get the final value */
- RETVAL = do_SEQ(db, key, value, R_LAST) ;
- ST(0) = sv_newmortal();
- /* Now delete it */
- if (RETVAL == 0)
- {
- /* the call to del will trash value, so take a copy now */
- OutputValue(ST(0), value) ;
- RETVAL = db_del(db, key, R_CURSOR) ;
- if (RETVAL != 0)
- sv_setsv(ST(0), &PL_sv_undef);
- }
- }
-
-I32
-shift(db)
- DB_File db
- ALIAS: SHIFT = 1
- CODE:
- {
- DBT value ;
- DBTKEY key ;
-
- DBT_clear(key) ;
- DBT_clear(value) ;
- CurrentDB = db ;
- /* get the first value */
- RETVAL = do_SEQ(db, key, value, R_FIRST) ;
- ST(0) = sv_newmortal();
- /* Now delete it */
- if (RETVAL == 0)
- {
- /* the call to del will trash value, so take a copy now */
- OutputValue(ST(0), value) ;
- RETVAL = db_del(db, key, R_CURSOR) ;
- if (RETVAL != 0)
- sv_setsv (ST(0), &PL_sv_undef) ;
- }
- }
-
-
-I32
-push(db, ...)
- DB_File db
- ALIAS: PUSH = 1
- CODE:
- {
- DBTKEY key ;
- DBT value ;
- DB * Db = db->dbp ;
- int i ;
- STRLEN n_a;
- int keyval ;
-
- DBT_flags(key) ;
- DBT_flags(value) ;
- CurrentDB = db ;
- /* Set the Cursor to the Last element */
- RETVAL = do_SEQ(db, key, value, R_LAST) ;
-#ifndef DB_VERSION_MAJOR
- if (RETVAL >= 0)
-#endif
- {
- if (RETVAL == 0)
- keyval = *(int*)key.data ;
- else
- keyval = 0 ;
- for (i = 1 ; i < items ; ++i)
- {
- value.data = SvPV(ST(i), n_a) ;
- value.size = n_a ;
- ++ keyval ;
- key.data = &keyval ;
- key.size = sizeof(int) ;
- RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
- if (RETVAL != 0)
- break;
- }
- }
- }
- OUTPUT:
- RETVAL
-
-I32
-length(db)
- DB_File db
- ALIAS: FETCHSIZE = 1
- CODE:
- CurrentDB = db ;
- RETVAL = GetArrayLength(aTHX_ db) ;
- OUTPUT:
- RETVAL
-
-
-#
-# Now provide an interface to the rest of the DB functionality
-#
-
-int
-db_del(db, key, flags=0)
- DB_File db
- DBTKEY key
- u_int flags
- CODE:
- CurrentDB = db ;
- RETVAL = db_del(db, key, flags) ;
-#ifdef DB_VERSION_MAJOR
- if (RETVAL > 0)
- RETVAL = -1 ;
- else if (RETVAL == DB_NOTFOUND)
- RETVAL = 1 ;
-#endif
- OUTPUT:
- RETVAL
-
-
-int
-db_get(db, key, value, flags=0)
- DB_File db
- DBTKEY key
- DBT value = NO_INIT
- u_int flags
- CODE:
- CurrentDB = db ;
- DBT_clear(value) ;
- RETVAL = db_get(db, key, value, flags) ;
-#ifdef DB_VERSION_MAJOR
- if (RETVAL > 0)
- RETVAL = -1 ;
- else if (RETVAL == DB_NOTFOUND)
- RETVAL = 1 ;
-#endif
- OUTPUT:
- RETVAL
- value
-
-int
-db_put(db, key, value, flags=0)
- DB_File db
- DBTKEY key
- DBT value
- u_int flags
- CODE:
- CurrentDB = db ;
- RETVAL = db_put(db, key, value, flags) ;
-#ifdef DB_VERSION_MAJOR
- if (RETVAL > 0)
- RETVAL = -1 ;
- else if (RETVAL == DB_KEYEXIST)
- RETVAL = 1 ;
-#endif
- OUTPUT:
- RETVAL
- key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
-
-int
-db_fd(db)
- DB_File db
- int status = 0 ;
- CODE:
- CurrentDB = db ;
-#ifdef DB_VERSION_MAJOR
- RETVAL = -1 ;
- status = (db->in_memory
- ? -1
- : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
- if (status != 0)
- RETVAL = -1 ;
-#else
- RETVAL = (db->in_memory
- ? -1
- : ((db->dbp)->fd)(db->dbp) ) ;
-#endif
- OUTPUT:
- RETVAL
-
-int
-db_sync(db, flags=0)
- DB_File db
- u_int flags
- CODE:
- CurrentDB = db ;
- RETVAL = db_sync(db, flags) ;
-#ifdef DB_VERSION_MAJOR
- if (RETVAL > 0)
- RETVAL = -1 ;
-#endif
- OUTPUT:
- RETVAL
-
-
-int
-db_seq(db, key, value, flags)
- DB_File db
- DBTKEY key
- DBT value = NO_INIT
- u_int flags
- CODE:
- CurrentDB = db ;
- DBT_clear(value) ;
- RETVAL = db_seq(db, key, value, flags);
-#ifdef DB_VERSION_MAJOR
- if (RETVAL > 0)
- RETVAL = -1 ;
- else if (RETVAL == DB_NOTFOUND)
- RETVAL = 1 ;
-#endif
- OUTPUT:
- RETVAL
- key
- value
-
-#ifdef DBM_FILTERING
-
-#define setFilter(type) \
- { \
- if (db->type) \
- RETVAL = sv_mortalcopy(db->type) ; \
- ST(0) = RETVAL ; \
- if (db->type && (code == &PL_sv_undef)) { \
- SvREFCNT_dec(db->type) ; \
- db->type = NULL ; \
- } \
- else if (code) { \
- if (db->type) \
- sv_setsv(db->type, code) ; \
- else \
- db->type = newSVsv(code) ; \
- } \
- }
-
-
-SV *
-filter_fetch_key(db, code)
- DB_File db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_fetch_key) ;
-
-SV *
-filter_store_key(db, code)
- DB_File db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_store_key) ;
-
-SV *
-filter_fetch_value(db, code)
- DB_File db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_fetch_value) ;
-
-SV *
-filter_store_value(db, code)
- DB_File db
- SV * code
- SV * RETVAL = &PL_sv_undef ;
- CODE:
- setFilter(filter_store_value) ;
-
-#endif /* DBM_FILTERING */
diff --git a/bdb/perl.DB_File/MANIFEST b/bdb/perl.DB_File/MANIFEST
deleted file mode 100644
index 0cc30dbfb47..00000000000
--- a/bdb/perl.DB_File/MANIFEST
+++ /dev/null
@@ -1,27 +0,0 @@
-Makefile.PL
-DB_File.pm
-DB_File.xs
-DB_File_BS
-Changes
-config.in
-dbinfo
-hints/dynixptx.pl
-hints/sco.pl
-MANIFEST
-README
-typemap
-t/db-btree.t
-t/db-hash.t
-t/db-recno.t
-version.c
-patches/5.004
-patches/5.004_01
-patches/5.004_02
-patches/5.004_03
-patches/5.004_04
-patches/5.004_05
-patches/5.005
-patches/5.005_01
-patches/5.005_02
-patches/5.005_03
-patches/5.6.0
diff --git a/bdb/perl.DB_File/Makefile.PL b/bdb/perl.DB_File/Makefile.PL
deleted file mode 100644
index 25e707df6ea..00000000000
--- a/bdb/perl.DB_File/Makefile.PL
+++ /dev/null
@@ -1,187 +0,0 @@
-#! perl -w
-use strict ;
-use ExtUtils::MakeMaker 5.16 ;
-use Config ;
-
-my $VER_INFO ;
-my $LIB_DIR ;
-my $INC_DIR ;
-my $DB_NAME ;
-my $LIBS ;
-my $COMPAT185 = "" ;
-
-my @files = ('DB_File.pm', glob "t/*.t") ;
-# See if warnings is available
-eval 'use warnings;';
-if ($@) {
- # not there, so write a dummy warnings.pm
- oldWarnings(@files) ;
-} else {
- # is there,
- newWarnings(@files) ;
-}
-
-ParseCONFIG() ;
-
-if (defined $DB_NAME)
- { $LIBS = $DB_NAME }
-else {
- if ($^O eq 'MSWin32')
- { $LIBS = '-llibdb' }
- else
- { $LIBS = '-ldb' }
-}
-
-# Solaris is special.
-#$LIBS .= " -lthread" if $^O eq 'solaris' ;
-
-# OS2 is a special case, so check for it now.
-my $OS2 = "" ;
-$OS2 = "-DOS2" if $Config{'osname'} eq 'os2' ;
-
-WriteMakefile(
- NAME => 'DB_File',
- LIBS => ["-L${LIB_DIR} $LIBS"],
- MAN3PODS => ' ', # Pods will be built by installman.
- INC => "-I$INC_DIR",
- VERSION_FROM => 'DB_File.pm',
- XSPROTOARG => '-noprototypes',
- DEFINE => "$OS2 $VER_INFO $COMPAT185",
- OBJECT => 'version$(OBJ_EXT) DB_File$(OBJ_EXT)',
- OPTIMIZE => '-g',
- 'macro' => { INSTALLDIRS => 'perl' },
- 'dist' => {COMPRESS=>'gzip', SUFFIX=>'gz'},
- );
-
-
-sub MY::postamble {
- '
-version$(OBJ_EXT): version.c
-
-$(NAME).xs: typemap
- @$(TOUCH) $(NAME).xs
-
-Makefile: config.in
-
-' ;
-}
-
-
-sub ParseCONFIG
-{
- my ($k, $v) ;
- my @badkey = () ;
- my %Info = () ;
- my @Options = qw( INCLUDE LIB PREFIX HASH DBNAME COMPAT185 ) ;
- my %ValidOption = map {$_, 1} @Options ;
- my %Parsed = %ValidOption ;
- my $CONFIG = 'config.in' ;
-
- print "Parsing $CONFIG...\n" ;
-
- # DBNAME & COMPAT185 are optional, so pretend they have
- # been parsed.
- delete $Parsed{'DBNAME'} ;
- delete $Parsed{'COMPAT185'} ;
- $Info{COMPAT185} = "No" ;
-
-
- open(F, "$CONFIG") or die "Cannot open file $CONFIG: $!\n" ;
- while (<F>) {
- s/^\s*|\s*$//g ;
- next if /^\s*$/ or /^\s*#/ ;
- s/\s*#\s*$// ;
-
- ($k, $v) = split(/\s+=\s+/, $_, 2) ;
- $k = uc $k ;
- if ($ValidOption{$k}) {
- delete $Parsed{$k} ;
- $Info{$k} = $v ;
- }
- else {
- push(@badkey, $k) ;
- }
- }
- close F ;
-
- print "Unknown keys in $CONFIG ignored [@badkey]\n"
- if @badkey ;
-
- # check parsed values
- my @missing = () ;
- die "The following keys are missing from $CONFIG file: [@missing]\n"
- if @missing = keys %Parsed ;
-
- $INC_DIR = $ENV{'DB_FILE_INCLUDE'} || $Info{'INCLUDE'} ;
- $LIB_DIR = $ENV{'DB_FILE_LIB'} || $Info{'LIB'} ;
- $DB_NAME = $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
- $COMPAT185 = "-DCOMPAT185 -DDB_LIBRARY_COMPATIBILITY_API"
- if (defined $ENV{'DB_FILE_COMPAT185'} &&
- $ENV{'DB_FILE_COMPAT185'} =~ /^\s*(on|true|1)\s*$/i) ||
- $Info{'COMPAT185'} =~ /^\s*(on|true|1)\s*$/i ;
- my $PREFIX = $Info{'PREFIX'} ;
- my $HASH = $Info{'HASH'} ;
-
- $VER_INFO = "-DmDB_Prefix_t=${PREFIX} -DmDB_Hash_t=${HASH}" ;
-
- print <<EOM if 0 ;
- INCLUDE [$INC_DIR]
- LIB [$LIB_DIR]
- HASH [$HASH]
- PREFIX [$PREFIX]
- DBNAME [$DB_NAME]
-
-EOM
-
- print "Looks Good.\n" ;
-
-}
-
-sub oldWarnings
-{
- local ($^I) = ".bak" ;
- local (@ARGV) = @_ ;
-
- while (<>)
- {
- if (/^__END__/)
- {
- print ;
- my $this = $ARGV ;
- while (<>)
- {
- last if $ARGV ne $this ;
- print ;
- }
- }
-
- s/^(\s*)(no\s+warnings)/${1}local (\$^W) = 0; #$2/ ;
- s/^(\s*)(use\s+warnings)/${1}local (\$^W) = 1; #$2/ ;
- print ;
- }
-}
-
-sub newWarnings
-{
- local ($^I) = ".bak" ;
- local (@ARGV) = @_ ;
-
- while (<>)
- {
- if (/^__END__/)
- {
- my $this = $ARGV ;
- print ;
- while (<>)
- {
- last if $ARGV ne $this ;
- print ;
- }
- }
-
- s/^(\s*)local\s*\(\$\^W\)\s*=\s*\d+\s*;\s*#\s*((no|use)\s+warnings.*)/$1$2/ ;
- print ;
- }
-}
-
-# end of file Makefile.PL
diff --git a/bdb/perl.DB_File/README b/bdb/perl.DB_File/README
deleted file mode 100644
index e780111b2e9..00000000000
--- a/bdb/perl.DB_File/README
+++ /dev/null
@@ -1,396 +0,0 @@
- DB_File
-
- Version 1.76
-
- 15th January 2001
-
- Copyright (c) 1995-2001 Paul Marquess. All rights reserved. This
- program is free software; you can redistribute it and/or modify
- it under the same terms as Perl itself.
-
-
-IMPORTANT NOTICE
-================
-
-If are using the locking technique described in older versions of
-DB_File, please read the section called "Locking: The Trouble with fd"
-in DB_File.pm immediately. The locking method has been found to be
-unsafe. You risk corrupting your data if you continue to use it.
-
-DESCRIPTION
------------
-
-DB_File is a module which allows Perl programs to make use of the
-facilities provided by Berkeley DB version 1. (DB_File can be built
-version 2 or 3 of Berkeley DB, but it will only support the 1.x
-features),
-
-If you want to make use of the new features available in Berkeley DB
-2.x or 3.x, use the Perl module BerkeleyDB instead.
-
-Berkeley DB is a C library which provides a consistent interface to a
-number of database formats. DB_File provides an interface to all three
-of the database types (hash, btree and recno) currently supported by
-Berkeley DB.
-
-For further details see the documentation included at the end of the
-file DB_File.pm.
-
-PREREQUISITES
--------------
-
-Before you can build DB_File you must have the following installed on
-your system:
-
- * Perl 5.004 or greater.
-
- * Berkeley DB.
-
- The official web site for Berkeley DB is http://www.sleepycat.com.
- The latest version of Berkeley DB is always available there. It
- is recommended that you use the most recent version available at
- the Sleepycat site.
-
- The one exception to this advice is where you want to use DB_File
- to access database files created by a third-party application, like
- Sendmail or Netscape. In these cases you must build DB_File with a
- compatible version of Berkeley DB.
-
- If you want to use Berkeley DB 2.x, you must have version 2.3.4
- or greater. If you want to use Berkeley DB 3.x, any version will
- do. For Berkeley DB 1.x, use either version 1.85 or 1.86.
-
-
-BUILDING THE MODULE
--------------------
-
-Assuming you have met all the prerequisites, building the module should
-be relatively straightforward.
-
-Step 1 : If you are running either Solaris 2.5 or HP-UX 10 and want
- to use Berkeley DB version 2 or 3, read either the Solaris Notes
- or HP-UX Notes sections below. If you are running Linux please
- read the Linux Notes section before proceeding.
-
-Step 2 : Edit the file config.in to suit you local installation.
- Instructions are given in the file.
-
-Step 3 : Build and test the module using this sequence of commands:
-
- perl Makefile.PL
- make
- make test
-
-
- NOTE:
- If you have a very old version of Berkeley DB (i.e. pre 1.85),
- three of the tests in the recno test harness may fail (tests 51,
- 53 and 55). You can safely ignore the errors if you're never
- going to use the broken functionality (recno databases with a
- modified bval). Otherwise you'll have to upgrade your DB
- library.
-
-
-INSTALLATION
-------------
-
- make install
-
-
-TROUBLESHOOTING
-===============
-
-Here are some of the common problems people encounter when building
-DB_File.
-
-Missing db.h or libdb.a
------------------------
-
-If you get an error like this:
-
- cc -c -I/usr/local/include -Dbool=char -DHAS_BOOL
- -O2 -DVERSION=\"1.64\" -DXS_VERSION=\"1.64\" -fpic
- -I/usr/local/lib/perl5/i586-linux/5.00404/CORE -DmDB_Prefix_t=size_t
- -DmDB_Hash_t=u_int32_t DB_File.c
- DB_File.xs:101: db.h: No such file or directory
-
-or this:
-
- LD_RUN_PATH="/lib" cc -o blib/arch/auto/DB_File/DB_File.so -shared
- -L/usr/local/lib DB_File.o -L/usr/local/lib -ldb
- ld: cannot open -ldb: No such file or directory
-
-This symptom can imply:
-
- 1. You don't have Berkeley DB installed on your system at all.
- Solution: get & install Berkeley DB.
-
- 2. You do have Berkeley DB installed, but it isn't in a standard place.
- Solution: Edit config.in and set the LIB and INCLUDE variables to point
- to the directories where libdb.a and db.h are installed.
-
-
-Undefined symbol db_version
----------------------------
-
-DB_File seems to have built correctly, but you get an error like this
-when you run the test harness:
-
- $ make test
- PERL_DL_NONLAZY=1 /usr/bin/perl5.00404 -I./blib/arch -I./blib/lib
- -I/usr/local/lib/perl5/i586-linux/5.00404 -I/usr/local/lib/perl5 -e 'use
- Test::Harness qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
- t/db-btree..........Can't load './blib/arch/auto/DB_File/DB_File.so' for
- module DB_File: ./blib/arch/auto/DB_File/DB_File.so: undefined symbol:
- db_version at /usr/local/lib/perl5/i586-linux/5.00404/DynaLoader.pm
- line 166.
-
- at t/db-btree.t line 21
- BEGIN failed--compilation aborted at t/db-btree.t line 21.
- dubious Test returned status 2 (wstat 512, 0x200)
-
-This error usually happens when you have both version 1 and version
-2 of Berkeley DB installed on your system and DB_File attempts to
-build using the db.h for Berkeley DB version 2 and the version 1
-library. Unfortunately the two versions aren't compatible with each
-other. The undefined symbol error is actually caused because Berkeley
-DB version 1 doesn't have the symbol db_version.
-
-Solution: Setting the LIB & INCLUDE variables in config.in to point to the
- correct directories can sometimes be enough to fix this
- problem. If that doesn't work the easiest way to fix the
- problem is to either delete or temporarily rename the copies
- of db.h and libdb.a that you don't want DB_File to use.
-
-Incompatible versions of db.h and libdb
----------------------------------------
-
-BerkeleyDB seems to have built correctly, but you get an error like this
-when you run the test harness:
-
- $ make test
- PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00560 -Iblib/arch
- -Iblib/lib -I/home/paul/perl/install/5.005_60/lib/5.00560/i586-linux
- -I/home/paul/perl/install/5.005_60/lib/5.00560 -e 'use Test::Harness
- qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
- t/db-btree..........
- DB_File needs compatible versions of libdb & db.h
- you have db.h version 2.3.7 and libdb version 2.7.5
- BEGIN failed--compilation aborted at t/db-btree.t line 21.
- ...
-
-Another variation on the theme of having two versions of Berkeley DB on
-your system.
-
-Solution: Setting the LIB & INCLUDE variables in config.in to point to the
- correct directories can sometimes be enough to fix this
- problem. If that doesn't work the easiest way to fix the
- problem is to either delete or temporarily rename the copies
- of db.h and libdb.a that you don't want BerkeleyDB to use.
- If you are running Linux, please read the Linux Notes section
- below.
-
-
-Linux Notes
------------
-
-Newer versions of Linux (e.g. RedHat 6, SuSe 6) ship with a C library
-that has version 2.x of Berkeley DB linked into it. This makes it
-difficult to build this module with anything other than the version of
-Berkeley DB that shipped with your Linux release. If you do try to use
-a different version of Berkeley DB you will most likely get the error
-described in the "Incompatible versions of db.h and libdb" section of
-this file.
-
-To make matters worse, prior to Perl 5.6.1, the perl binary itself
-*always* included the Berkeley DB library.
-
-If you want to use a newer version of Berkeley DB with this module, the
-easiest solution is to use Perl 5.6.1 (or better) and Berkeley DB 3.x
-(or better).
-
-There are two approaches you can use to get older versions of Perl to
-work with specific versions of Berkeley DB. Both have their advantages
-and disadvantages.
-
-The first approach will only work when you want to build a version of
-Perl older than 5.6.1 along with Berkeley DB 3.x. If you want to use
-Berkeley DB 2.x, you must use the next approach. This approach involves
-rebuilding your existing version of Perl after applying an unofficial
-patch. The "patches" directory in the this module's source distribution
-contains a number of patch files. There is one patch file for every
-stable version of Perl since 5.004. Apply the appropriate patch to your
-Perl source tree before re-building and installing Perl from scratch.
-For example, assuming you are in the top-level source directory for
-Perl 5.6.0, the command below will apply the necessary patch. Remember
-to replace the path shown below with one that points to this module's
-patches directory.
-
- patch -p1 -N </path/to/DB_File/patches/5.6.0
-
-Now rebuild & install perl. You should now have a perl binary that can
-be used to build this module. Follow the instructions in "BUILDING THE
-MODULE", remembering to set the INCLUDE and LIB variables in config.in.
-
-
-The second approach will work with both Berkeley DB 2.x and 3.x.
-Start by building Berkeley DB as a shared library. This is from
-the Berkeley DB build instructions:
-
- Building Shared Libraries for the GNU GCC compiler
-
- If you're using gcc and there's no better shared library example for
- your architecture, the following shared library build procedure will
- probably work.
-
- Add the -fpic option to the CFLAGS value in the Makefile.
-
- Rebuild all of your .o files. This will create a Berkeley DB library
- that contains .o files with PIC code. To build the shared library,
- then take the following steps in the library build directory:
-
- % mkdir tmp
- % cd tmp
- % ar xv ../libdb.a
- % gcc -shared -o libdb.so *.o
- % mv libdb.so ..
- % cd ..
- % rm -rf tmp
-
- Note, you may have to change the gcc line depending on the
- requirements of your system.
-
- The file libdb.so is your shared library
-
-Once you have built libdb.so, you will need to store it somewhere safe.
-
- cp libdb.so /usr/local/BerkeleyDB/lib
-
-If you now set the LD_PRELOAD environment variable to point to this
-shared library, Perl will use it instead of the version of Berkeley DB
-that shipped with your Linux distribution.
-
- export LD_PRELOAD=/usr/local/BerkeleyDB/lib/libdb.so
-
-Finally follow the instructions in "BUILDING THE MODULE" to build,
-test and install this module. Don't forget to set the INCLUDE and LIB
-variables in config.in.
-
-Remember, you will need to have the LD_PRELOAD variable set anytime you
-want to use Perl with Berkeley DB. Also note that if you have LD_PRELOAD
-permanently set it will affect ALL commands you execute. This may be a
-problem if you run any commands that access a database created by the
-version of Berkeley DB that shipped with your Linux distribution.
-
-
-Solaris Notes
--------------
-
-If you are running Solaris 2.5, and you get this error when you run the
-DB_File test harness:
-
- libc internal error: _rmutex_unlock: rmutex not held.
-
-you probably need to install a Sun patch. It has been reported that
-Sun patch 103187-25 (or later revisions) fixes this problem.
-
-To find out if you have the patch installed, the command "showrev -p"
-will display the patches that are currently installed on your system.
-
-
-HP-UX Notes
------------
-
-Some people running HP-UX 10 have reported getting an error like this
-when building DB_File with the native HP-UX compiler.
-
- ld: (Warning) At least one PA 2.0 object file (DB_File.o) was detected.
- The linked output may not run on a PA 1.x system.
- ld: Invalid loader fixup for symbol "$000000A5".
-
-If this is the case for you, Berkeley DB needs to be recompiled with
-the +z or +Z option and the resulting library placed in a .sl file. The
-following steps should do the trick:
-
- 1: Configure the Berkeley DB distribution with the +z or +Z C compiler
- flag:
-
- env "CFLAGS=+z" ../dist/configure ...
-
- 2: Edit the Berkeley DB Makefile and change:
-
- "libdb= libdb.a" to "libdb= libdb.sl".
-
-
- 3: Build and install the Berkeley DB distribution as usual.
-
-
-IRIX NOTES
-----------
-
-If you are running IRIX, and want to use Berkeley DB version 1, you can
-get it from http://reality.sgi.com/ariel. It has the patches necessary
-to compile properly on IRIX 5.3.
-
-
-FEEDBACK
-========
-
-How to report a problem with DB_File.
-
-To help me help you, I need the following information:
-
- 1. The version of Perl and the operating system name and version you
- are running. The *complete* output from running "perl -V" will
- tell me all I need to know. Don't edit the output in any way. Note,
- I want you to run "perl -V" and NOT "perl -v".
-
- If your perl does not understand the "-V" option it is too old. DB_File
- needs Perl version 5.004 or better.
-
- 2. The version of DB_File you have.
- If you have successfully installed DB_File, this one-liner will
- tell you:
-
- perl -e 'use DB_File; print "DB_File ver $DB_File::VERSION\n"'
-
- If you haven't installed DB_File then search DB_File.pm for a line
- like this:
-
- $VERSION = "1.20" ;
-
- 3. The version of Berkeley DB you are using.
- If you are using a version older than 1.85, think about upgrading. One
- point to note if you are considering upgrading Berkeley DB - the
- file formats for 1.85, 1.86, 2.0, 3.0 & 3.1 are all different.
-
- If you have successfully installed DB_File, this command will display
- the version of Berkeley DB it was built with:
-
- perl -e 'use DB_File; print "Berkeley DB ver $DB_File::db_ver\n"'
-
- 4. If you are having problems building DB_File, send me a complete log
- of what happened.
-
- 5. Now the difficult one. If you think you have found a bug in DB_File
- and you want me to fix it, you will *greatly* enhance the chances
- of me being able to track it down by sending me a small
- self-contained Perl script that illustrates the problem you are
- encountering. Include a summary of what you think the problem is
- and a log of what happens when you run the script, in case I can't
- reproduce your problem on my system. If possible, don't have the
- script dependent on an existing 20Meg database. If the script you
- send me can create the database itself then that is preferred.
-
- I realise that in some cases this is easier said than done, so if
- you can only reproduce the problem in your existing script, then
- you can post me that if you want. Just don't expect me to find your
- problem in a hurry, or at all. :-)
-
-
-CHANGES
--------
-
-See the Changes file.
-
-Paul Marquess <Paul.Marquess@btinternet.com>
diff --git a/bdb/perl.DB_File/config.in b/bdb/perl.DB_File/config.in
deleted file mode 100644
index 5bda4a66762..00000000000
--- a/bdb/perl.DB_File/config.in
+++ /dev/null
@@ -1,99 +0,0 @@
-# Filename: config.in
-#
-# written by Paul Marquess <Paul.Marquess@btinternet.com>
-# last modified 9th Sept 1997
-# version 1.55
-
-# 1. Where is the file db.h?
-#
-# Change the path below to point to the directory where db.h is
-# installed on your system.
-
-#INCLUDE = /usr/local/include
-#INCLUDE = /usr/local/BerkeleyDB/include
-#INCLUDE = /usr/include
-INCLUDE = ./libraries/3.2.7
-
-# 2. Where is libdb?
-#
-# Change the path below to point to the directory where libdb is
-# installed on your system.
-
-#LIB = /usr/local/lib
-#LIB = /usr/local/BerkeleyDB/lib
-#LIB = /usr/lib
-LIB = ./libraries/3.2.7
-
-# 3. What version of Berkely DB have you got?
-#
-# If you have version 2.0 or greater, you can skip this question.
-#
-# If you have Berkeley DB 1.78 or greater you shouldn't have to
-# change the definitions for PREFIX and HASH below.
-#
-# For older versions of Berkeley DB change both PREFIX and HASH to int.
-# Version 1.71, 1.72 and 1.73 are known to need this change.
-#
-# If you don't know what version you have have a look in the file db.h.
-#
-# Search for the string "DB_VERSION_MAJOR". If it is present, you
-# have Berkeley DB version 2 (or greater).
-#
-# If that didn't work, find the definition of the BTREEINFO typedef.
-# Check the return type from the prefix element. It should look like
-# this in an older copy of db.h:
-#
-# int (*prefix) __P((const DBT *, const DBT *));
-#
-# and like this in a more recent copy:
-#
-# size_t (*prefix) /* prefix function */
-# __P((const DBT *, const DBT *));
-#
-# Change the definition of PREFIX, below, to reflect the return type
-# of the prefix function in your db.h.
-#
-# Now find the definition of the HASHINFO typedef. Check the return
-# type of the hash element. Older versions look like this:
-#
-# int (*hash) __P((const void *, size_t));
-#
-# newer like this:
-#
-# u_int32_t /* hash function */
-# (*hash) __P((const void *, size_t));
-#
-# Change the definition of HASH, below, to reflect the return type of
-# the hash function in your db.h.
-#
-
-PREFIX = size_t
-HASH = u_int32_t
-
-# 4. Is the library called libdb?
-#
-# If you have copies of both 1.x and 2.x Berkeley DB installed on
-# your system it can sometimes be tricky to make sure you are using
-# the correct one. Renaming one (or creating a symbolic link) to
-# include the version number of the library can help.
-#
-# For example, if you have both Berkeley DB 2.3.12 and 1.85 on your
-# system and you want to use the Berkeley DB version 2 library you
-# could rename the version 2 library from libdb.a to libdb-2.3.12.a and
-# change the DBNAME line below to look like this:
-#
-# DBNAME = -ldb-2.3.12
-#
-# That will ensure you are linking the correct version of the DB
-# library.
-#
-# Note: If you are building this module with Win32, -llibdb will be
-# used by default.
-#
-# If you have changed the name of the library, uncomment the line
-# below (by removing the leading #) and edit the line to use the name
-# you have picked.
-
-#DBNAME = -ldb-2.4.10
-
-# end of file config.in
diff --git a/bdb/perl.DB_File/dbinfo b/bdb/perl.DB_File/dbinfo
deleted file mode 100644
index 5a4df15907e..00000000000
--- a/bdb/perl.DB_File/dbinfo
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/local/bin/perl
-
-# Name: dbinfo -- identify berkeley DB version used to create
-# a database file
-#
-# Author: Paul Marquess <Paul.Marquess@btinternet.com>
-# Version: 1.03
-# Date 17th September 2000
-#
-# Copyright (c) 1998-2000 Paul Marquess. All rights reserved.
-# This program is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-
-# Todo: Print more stats on a db file, e.g. no of records
-# add log/txn/lock files
-
-use strict ;
-
-my %Data =
- (
- 0x053162 => {
- Type => "Btree",
- Versions =>
- {
- 1 => "Unknown (older than 1.71)",
- 2 => "Unknown (older than 1.71)",
- 3 => "1.71 -> 1.85, 1.86",
- 4 => "Unknown",
- 5 => "2.0.0 -> 2.3.0",
- 6 => "2.3.1 -> 2.7.7",
- 7 => "3.0.x",
- 8 => "3.1.x or greater",
- }
- },
- 0x061561 => {
- Type => "Hash",
- Versions =>
- {
- 1 => "Unknown (older than 1.71)",
- 2 => "1.71 -> 1.85",
- 3 => "1.86",
- 4 => "2.0.0 -> 2.1.0",
- 5 => "2.2.6 -> 2.7.7",
- 6 => "3.0.x",
- 7 => "3.1.x or greater",
- }
- },
- 0x042253 => {
- Type => "Queue",
- Versions =>
- {
- 1 => "3.0.x",
- 2 => "3.1.x",
- 3 => "3.2.x or greater",
- }
- },
- ) ;
-
-die "Usage: dbinfo file\n" unless @ARGV == 1 ;
-
-print "testing file $ARGV[0]...\n\n" ;
-open (F, "<$ARGV[0]") or die "Cannot open file $ARGV[0]: $!\n" ;
-
-my $buff ;
-read F, $buff, 20 ;
-
-my (@info) = unpack("NNNNN", $buff) ;
-my (@info1) = unpack("VVVVV", $buff) ;
-my ($magic, $version, $endian) ;
-
-if ($Data{$info[0]}) # first try DB 1.x format
-{
- $magic = $info[0] ;
- $version = $info[1] ;
- $endian = "Unknown" ;
-}
-elsif ($Data{$info[3]}) # next DB 2.x big endian
-{
- $magic = $info[3] ;
- $version = $info[4] ;
- $endian = "Big Endian" ;
-}
-elsif ($Data{$info1[3]}) # next DB 2.x little endian
-{
- $magic = $info1[3] ;
- $version = $info1[4] ;
- $endian = "Little Endian" ;
-}
-else
- { die "not a Berkeley DB database file.\n" }
-
-my $type = $Data{$magic} ;
-$magic = sprintf "%06X", $magic ;
-
-my $ver_string = "Unknown" ;
-$ver_string = $type->{Versions}{$version}
- if defined $type->{Versions}{$version} ;
-
-print <<EOM ;
-File Type: Berkeley DB $type->{Type} file.
-File Version ID: $version
-Built with Berkeley DB: $ver_string
-Byte Order: $endian
-Magic: $magic
-EOM
-
-close F ;
-
-exit ;
diff --git a/bdb/perl.DB_File/t/db-btree.t b/bdb/perl.DB_File/t/db-btree.t
deleted file mode 100644
index 377cfe45c9b..00000000000
--- a/bdb/perl.DB_File/t/db-btree.t
+++ /dev/null
@@ -1,1306 +0,0 @@
-#!./perl -w
-
-use warnings;
-use strict;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use Config;
-
-BEGIN {
- if(-d "lib" && -f "TEST") {
- if ($Config{'extensions'} !~ /\bDB_File\b/ ) {
- print "1..157\n";
- exit 0;
- }
- }
-}
-
-use DB_File;
-use Fcntl;
-
-print "1..157\n";
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-sub lexical
-{
- my(@a) = unpack ("C*", $a) ;
- my(@b) = unpack ("C*", $b) ;
-
- my $len = (@a > @b ? @b : @a) ;
- my $i = 0 ;
-
- foreach $i ( 0 .. $len -1) {
- return $a[$i] - $b[$i] if $a[$i] != $b[$i] ;
- }
-
- return @a - @b ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat
-{
- my $file = shift;
- #local $/ = undef unless wantarray ;
- open(CAT,$file) || die "Cannot open $file: $!";
- my @result = <CAT>;
- close(CAT);
- wantarray ? @result : join("", @result) ;
-}
-
-sub docat_del
-{
- my $file = shift;
- #local $/ = undef unless wantarray ;
- open(CAT,$file) || die "Cannot open $file: $!";
- my @result = <CAT>;
- close(CAT);
- unlink $file ;
- wantarray ? @result : join("", @result) ;
-}
-
-
-my $db185mode = ($DB_File::db_version == 1 && ! $DB_File::db_185_compat) ;
-my $null_keys_allowed = ($DB_File::db_ver < 2.004010
- || $DB_File::db_ver >= 3.1 );
-
-my $Dfile = "dbbtree.tmp";
-unlink $Dfile;
-
-umask(0);
-
-# Check the interface to BTREEINFO
-
-my $dbh = new DB_File::BTREEINFO ;
-ok(1, ! defined $dbh->{flags}) ;
-ok(2, ! defined $dbh->{cachesize}) ;
-ok(3, ! defined $dbh->{psize}) ;
-ok(4, ! defined $dbh->{lorder}) ;
-ok(5, ! defined $dbh->{minkeypage}) ;
-ok(6, ! defined $dbh->{maxkeypage}) ;
-ok(7, ! defined $dbh->{compare}) ;
-ok(8, ! defined $dbh->{prefix}) ;
-
-$dbh->{flags} = 3000 ;
-ok(9, $dbh->{flags} == 3000) ;
-
-$dbh->{cachesize} = 9000 ;
-ok(10, $dbh->{cachesize} == 9000);
-
-$dbh->{psize} = 400 ;
-ok(11, $dbh->{psize} == 400) ;
-
-$dbh->{lorder} = 65 ;
-ok(12, $dbh->{lorder} == 65) ;
-
-$dbh->{minkeypage} = 123 ;
-ok(13, $dbh->{minkeypage} == 123) ;
-
-$dbh->{maxkeypage} = 1234 ;
-ok(14, $dbh->{maxkeypage} == 1234 );
-
-$dbh->{compare} = 1234 ;
-ok(15, $dbh->{compare} == 1234) ;
-
-$dbh->{prefix} = 1234 ;
-ok(16, $dbh->{prefix} == 1234 );
-
-# Check that an invalid entry is caught both for store & fetch
-eval '$dbh->{fred} = 1234' ;
-ok(17, $@ =~ /^DB_File::BTREEINFO::STORE - Unknown element 'fred' at/ ) ;
-eval 'my $q = $dbh->{fred}' ;
-ok(18, $@ =~ /^DB_File::BTREEINFO::FETCH - Unknown element 'fred' at/ ) ;
-
-# Now check the interface to BTREE
-
-my ($X, %h) ;
-ok(19, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE )) ;
-
-my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
- $blksize,$blocks) = stat($Dfile);
-ok(20, ($mode & 0777) == ($^O eq 'os2' ? 0666 : 0640) || $^O eq 'amigaos' || $^O eq 'MSWin32');
-
-my ($key, $value, $i);
-while (($key,$value) = each(%h)) {
- $i++;
-}
-ok(21, !$i ) ;
-
-$h{'goner1'} = 'snork';
-
-$h{'abc'} = 'ABC';
-ok(22, $h{'abc'} eq 'ABC' );
-ok(23, ! defined $h{'jimmy'} ) ;
-ok(24, ! exists $h{'jimmy'} ) ;
-ok(25, defined $h{'abc'} ) ;
-
-$h{'def'} = 'DEF';
-$h{'jkl','mno'} = "JKL\034MNO";
-$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5);
-$h{'a'} = 'A';
-
-#$h{'b'} = 'B';
-$X->STORE('b', 'B') ;
-
-$h{'c'} = 'C';
-
-#$h{'d'} = 'D';
-$X->put('d', 'D') ;
-
-$h{'e'} = 'E';
-$h{'f'} = 'F';
-$h{'g'} = 'X';
-$h{'h'} = 'H';
-$h{'i'} = 'I';
-
-$h{'goner2'} = 'snork';
-delete $h{'goner2'};
-
-
-# IMPORTANT - $X must be undefined before the untie otherwise the
-# underlying DB close routine will not get called.
-undef $X ;
-untie(%h);
-
-# tie to the same file again
-ok(26, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE)) ;
-
-# Modify an entry from the previous tie
-$h{'g'} = 'G';
-
-$h{'j'} = 'J';
-$h{'k'} = 'K';
-$h{'l'} = 'L';
-$h{'m'} = 'M';
-$h{'n'} = 'N';
-$h{'o'} = 'O';
-$h{'p'} = 'P';
-$h{'q'} = 'Q';
-$h{'r'} = 'R';
-$h{'s'} = 'S';
-$h{'t'} = 'T';
-$h{'u'} = 'U';
-$h{'v'} = 'V';
-$h{'w'} = 'W';
-$h{'x'} = 'X';
-$h{'y'} = 'Y';
-$h{'z'} = 'Z';
-
-$h{'goner3'} = 'snork';
-
-delete $h{'goner1'};
-$X->DELETE('goner3');
-
-my @keys = keys(%h);
-my @values = values(%h);
-
-ok(27, $#keys == 29 && $#values == 29) ;
-
-$i = 0 ;
-while (($key,$value) = each(%h)) {
- if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) {
- $key =~ y/a-z/A-Z/;
- $i++ if $key eq $value;
- }
-}
-
-ok(28, $i == 30) ;
-
-@keys = ('blurfl', keys(%h), 'dyick');
-ok(29, $#keys == 31) ;
-
-#Check that the keys can be retrieved in order
-my @b = keys %h ;
-my @c = sort lexical @b ;
-ok(30, ArrayCompare(\@b, \@c)) ;
-
-$h{'foo'} = '';
-ok(31, $h{'foo'} eq '' ) ;
-
-# Berkeley DB from version 2.4.10 to 3.0 does not allow null keys.
-# This feature was reenabled in version 3.1 of Berkeley DB.
-my $result = 0 ;
-if ($null_keys_allowed) {
- $h{''} = 'bar';
- $result = ( $h{''} eq 'bar' );
-}
-else
- { $result = 1 }
-ok(32, $result) ;
-
-# check cache overflow and numeric keys and contents
-my $ok = 1;
-for ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; }
-for ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; }
-ok(33, $ok);
-
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
- $blksize,$blocks) = stat($Dfile);
-ok(34, $size > 0 );
-
-@h{0..200} = 200..400;
-my @foo = @h{0..200};
-ok(35, join(':',200..400) eq join(':',@foo) );
-
-# Now check all the non-tie specific stuff
-
-
-# Check R_NOOVERWRITE flag will make put fail when attempting to overwrite
-# an existing record.
-
-my $status = $X->put( 'x', 'newvalue', R_NOOVERWRITE) ;
-ok(36, $status == 1 );
-
-# check that the value of the key 'x' has not been changed by the
-# previous test
-ok(37, $h{'x'} eq 'X' );
-
-# standard put
-$status = $X->put('key', 'value') ;
-ok(38, $status == 0 );
-
-#check that previous put can be retrieved
-$value = 0 ;
-$status = $X->get('key', $value) ;
-ok(39, $status == 0 );
-ok(40, $value eq 'value' );
-
-# Attempting to delete an existing key should work
-
-$status = $X->del('q') ;
-ok(41, $status == 0 );
-if ($null_keys_allowed) {
- $status = $X->del('') ;
-} else {
- $status = 0 ;
-}
-ok(42, $status == 0 );
-
-# Make sure that the key deleted, cannot be retrieved
-ok(43, ! defined $h{'q'}) ;
-ok(44, ! defined $h{''}) ;
-
-undef $X ;
-untie %h ;
-
-ok(45, $X = tie(%h, 'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE ));
-
-# Attempting to delete a non-existant key should fail
-
-$status = $X->del('joe') ;
-ok(46, $status == 1 );
-
-# Check the get interface
-
-# First a non-existing key
-$status = $X->get('aaaa', $value) ;
-ok(47, $status == 1 );
-
-# Next an existing key
-$status = $X->get('a', $value) ;
-ok(48, $status == 0 );
-ok(49, $value eq 'A' );
-
-# seq
-# ###
-
-# use seq to find an approximate match
-$key = 'ke' ;
-$value = '' ;
-$status = $X->seq($key, $value, R_CURSOR) ;
-ok(50, $status == 0 );
-ok(51, $key eq 'key' );
-ok(52, $value eq 'value' );
-
-# seq when the key does not match
-$key = 'zzz' ;
-$value = '' ;
-$status = $X->seq($key, $value, R_CURSOR) ;
-ok(53, $status == 1 );
-
-
-# use seq to set the cursor, then delete the record @ the cursor.
-
-$key = 'x' ;
-$value = '' ;
-$status = $X->seq($key, $value, R_CURSOR) ;
-ok(54, $status == 0 );
-ok(55, $key eq 'x' );
-ok(56, $value eq 'X' );
-$status = $X->del(0, R_CURSOR) ;
-ok(57, $status == 0 );
-$status = $X->get('x', $value) ;
-ok(58, $status == 1 );
-
-# ditto, but use put to replace the key/value pair.
-$key = 'y' ;
-$value = '' ;
-$status = $X->seq($key, $value, R_CURSOR) ;
-ok(59, $status == 0 );
-ok(60, $key eq 'y' );
-ok(61, $value eq 'Y' );
-
-$key = "replace key" ;
-$value = "replace value" ;
-$status = $X->put($key, $value, R_CURSOR) ;
-ok(62, $status == 0 );
-ok(63, $key eq 'replace key' );
-ok(64, $value eq 'replace value' );
-$status = $X->get('y', $value) ;
-ok(65, 1) ; # hard-wire to always pass. the previous test ($status == 1)
- # only worked because of a bug in 1.85/6
-
-# use seq to walk forwards through a file
-
-$status = $X->seq($key, $value, R_FIRST) ;
-ok(66, $status == 0 );
-my $previous = $key ;
-
-$ok = 1 ;
-while (($status = $X->seq($key, $value, R_NEXT)) == 0)
-{
- ($ok = 0), last if ($previous cmp $key) == 1 ;
-}
-
-ok(67, $status == 1 );
-ok(68, $ok == 1 );
-
-# use seq to walk backwards through a file
-$status = $X->seq($key, $value, R_LAST) ;
-ok(69, $status == 0 );
-$previous = $key ;
-
-$ok = 1 ;
-while (($status = $X->seq($key, $value, R_PREV)) == 0)
-{
- ($ok = 0), last if ($previous cmp $key) == -1 ;
- #print "key = [$key] value = [$value]\n" ;
-}
-
-ok(70, $status == 1 );
-ok(71, $ok == 1 );
-
-
-# check seq FIRST/LAST
-
-# sync
-# ####
-
-$status = $X->sync ;
-ok(72, $status == 0 );
-
-
-# fd
-# ##
-
-$status = $X->fd ;
-ok(73, $status != 0 );
-
-
-undef $X ;
-untie %h ;
-
-unlink $Dfile;
-
-# Now try an in memory file
-my $Y;
-ok(74, $Y = tie(%h, 'DB_File',undef, O_RDWR|O_CREAT, 0640, $DB_BTREE ));
-
-# fd with an in memory file should return failure
-$status = $Y->fd ;
-ok(75, $status == -1 );
-
-
-undef $Y ;
-untie %h ;
-
-# Duplicate keys
-my $bt = new DB_File::BTREEINFO ;
-$bt->{flags} = R_DUP ;
-my ($YY, %hh);
-ok(76, $YY = tie(%hh, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $bt )) ;
-
-$hh{'Wall'} = 'Larry' ;
-$hh{'Wall'} = 'Stone' ; # Note the duplicate key
-$hh{'Wall'} = 'Brick' ; # Note the duplicate key
-$hh{'Wall'} = 'Brick' ; # Note the duplicate key and value
-$hh{'Smith'} = 'John' ;
-$hh{'mouse'} = 'mickey' ;
-
-# first work in scalar context
-ok(77, scalar $YY->get_dup('Unknown') == 0 );
-ok(78, scalar $YY->get_dup('Smith') == 1 );
-ok(79, scalar $YY->get_dup('Wall') == 4 );
-
-# now in list context
-my @unknown = $YY->get_dup('Unknown') ;
-ok(80, "@unknown" eq "" );
-
-my @smith = $YY->get_dup('Smith') ;
-ok(81, "@smith" eq "John" );
-
-{
-my @wall = $YY->get_dup('Wall') ;
-my %wall ;
-@wall{@wall} = @wall ;
-ok(82, (@wall == 4 && $wall{'Larry'} && $wall{'Stone'} && $wall{'Brick'}) );
-}
-
-# hash
-my %unknown = $YY->get_dup('Unknown', 1) ;
-ok(83, keys %unknown == 0 );
-
-my %smith = $YY->get_dup('Smith', 1) ;
-ok(84, keys %smith == 1 && $smith{'John'}) ;
-
-my %wall = $YY->get_dup('Wall', 1) ;
-ok(85, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1
- && $wall{'Brick'} == 2);
-
-undef $YY ;
-untie %hh ;
-unlink $Dfile;
-
-
-# test multiple callbacks
-my $Dfile1 = "btree1" ;
-my $Dfile2 = "btree2" ;
-my $Dfile3 = "btree3" ;
-
-my $dbh1 = new DB_File::BTREEINFO ;
-$dbh1->{compare} = sub {
- no warnings 'numeric' ;
- $_[0] <=> $_[1] } ;
-
-my $dbh2 = new DB_File::BTREEINFO ;
-$dbh2->{compare} = sub { $_[0] cmp $_[1] } ;
-
-my $dbh3 = new DB_File::BTREEINFO ;
-$dbh3->{compare} = sub { length $_[0] <=> length $_[1] } ;
-
-
-my (%g, %k);
-tie(%h, 'DB_File',$Dfile1, O_RDWR|O_CREAT, 0640, $dbh1 ) ;
-tie(%g, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) ;
-tie(%k, 'DB_File',$Dfile3, O_RDWR|O_CREAT, 0640, $dbh3 ) ;
-
-my @Keys = qw( 0123 12 -1234 9 987654321 def ) ;
-my (@srt_1, @srt_2, @srt_3);
-{
- no warnings 'numeric' ;
- @srt_1 = sort { $a <=> $b } @Keys ;
-}
-@srt_2 = sort { $a cmp $b } @Keys ;
-@srt_3 = sort { length $a <=> length $b } @Keys ;
-
-foreach (@Keys) {
- $h{$_} = 1 ;
- $g{$_} = 1 ;
- $k{$_} = 1 ;
-}
-
-sub ArrayCompare
-{
- my($a, $b) = @_ ;
-
- return 0 if @$a != @$b ;
-
- foreach (1 .. length @$a)
- {
- return 0 unless $$a[$_] eq $$b[$_] ;
- }
-
- 1 ;
-}
-
-ok(86, ArrayCompare (\@srt_1, [keys %h]) );
-ok(87, ArrayCompare (\@srt_2, [keys %g]) );
-ok(88, ArrayCompare (\@srt_3, [keys %k]) );
-
-untie %h ;
-untie %g ;
-untie %k ;
-unlink $Dfile1, $Dfile2, $Dfile3 ;
-
-# clear
-# #####
-
-ok(89, tie(%h, 'DB_File', $Dfile1, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
-foreach (1 .. 10)
- { $h{$_} = $_ * 100 }
-
-# check that there are 10 elements in the hash
-$i = 0 ;
-while (($key,$value) = each(%h)) {
- $i++;
-}
-ok(90, $i == 10);
-
-# now clear the hash
-%h = () ;
-
-# check it is empty
-$i = 0 ;
-while (($key,$value) = each(%h)) {
- $i++;
-}
-ok(91, $i == 0);
-
-untie %h ;
-unlink $Dfile1 ;
-
-{
- # check that attempting to tie an array to a DB_BTREE will fail
-
- my $filename = "xyz" ;
- my @x ;
- eval { tie @x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE ; } ;
- ok(92, $@ =~ /^DB_File can only tie an associative array to a DB_BTREE database/) ;
- unlink $filename ;
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use warnings ;
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use warnings ;
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use DB_File;
- @ISA=qw(DB_File);
- @EXPORT = @DB_File::EXPORT ;
-
- sub STORE {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::STORE($key, $value * 2) ;
- }
-
- sub FETCH {
- my $self = shift ;
- my $key = shift ;
- $self->SUPER::FETCH($key) - 1 ;
- }
-
- sub put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::put($key, $value * 3) ;
- }
-
- sub get {
- my $self = shift ;
- $self->SUPER::get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok(93, $@ eq "") ;
- my %h ;
- my $X ;
- eval '
- $X = tie(%h, "SubDB","dbbtree.tmp", O_RDWR|O_CREAT, 0640, $DB_BTREE );
- ' ;
-
- main::ok(94, $@ eq "") ;
-
- my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
- main::ok(95, $@ eq "") ;
- main::ok(96, $ret == 5) ;
-
- my $value = 0;
- $ret = eval '$X->put("joe", 4) ; $X->get("joe", $value) ; return $value' ;
- main::ok(97, $@ eq "") ;
- main::ok(98, $ret == 10) ;
-
- $ret = eval ' R_NEXT eq main::R_NEXT ' ;
- main::ok(99, $@ eq "" ) ;
- main::ok(100, $ret == 1) ;
-
- $ret = eval '$X->A_new_method("joe") ' ;
- main::ok(101, $@ eq "") ;
- main::ok(102, $ret eq "[[11]]") ;
-
- undef $X;
- untie(%h);
- unlink "SubDB.pm", "dbbtree.tmp" ;
-
-}
-
-{
- # DBM Filter tests
- use warnings ;
- use strict ;
- my (%h, $db) ;
- my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- unlink $Dfile;
-
- sub checkOutput
- {
- my($fk, $sk, $fv, $sv) = @_ ;
- return
- $fetch_key eq $fk && $store_key eq $sk &&
- $fetch_value eq $fv && $store_value eq $sv &&
- $_ eq 'original' ;
- }
-
- ok(103, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
-
- $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
- $db->filter_store_key (sub { $store_key = $_ }) ;
- $db->filter_fetch_value (sub { $fetch_value = $_}) ;
- $db->filter_store_value (sub { $store_value = $_ }) ;
-
- $_ = "original" ;
-
- $h{"fred"} = "joe" ;
- # fk sk fv sv
- ok(104, checkOutput( "", "fred", "", "joe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(105, $h{"fred"} eq "joe");
- # fk sk fv sv
- ok(106, checkOutput( "", "fred", "joe", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(107, $db->FIRSTKEY() eq "fred") ;
- # fk sk fv sv
- ok(108, checkOutput( "fred", "", "", "")) ;
-
- # replace the filters, but remember the previous set
- my ($old_fk) = $db->filter_fetch_key
- (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
- my ($old_sk) = $db->filter_store_key
- (sub { $_ = lc $_ ; $store_key = $_ }) ;
- my ($old_fv) = $db->filter_fetch_value
- (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
- my ($old_sv) = $db->filter_store_value
- (sub { s/o/x/g; $store_value = $_ }) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"Fred"} = "Joe" ;
- # fk sk fv sv
- ok(109, checkOutput( "", "fred", "", "Jxe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(110, $h{"Fred"} eq "[Jxe]");
- # fk sk fv sv
- ok(111, checkOutput( "", "fred", "[Jxe]", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(112, $db->FIRSTKEY() eq "FRED") ;
- # fk sk fv sv
- ok(113, checkOutput( "FRED", "", "", "")) ;
-
- # put the original filters back
- $db->filter_fetch_key ($old_fk);
- $db->filter_store_key ($old_sk);
- $db->filter_fetch_value ($old_fv);
- $db->filter_store_value ($old_sv);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"fred"} = "joe" ;
- ok(114, checkOutput( "", "fred", "", "joe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(115, $h{"fred"} eq "joe");
- ok(116, checkOutput( "", "fred", "joe", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(117, $db->FIRSTKEY() eq "fred") ;
- ok(118, checkOutput( "fred", "", "", "")) ;
-
- # delete the filters
- $db->filter_fetch_key (undef);
- $db->filter_store_key (undef);
- $db->filter_fetch_value (undef);
- $db->filter_store_value (undef);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"fred"} = "joe" ;
- ok(119, checkOutput( "", "", "", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(120, $h{"fred"} eq "joe");
- ok(121, checkOutput( "", "", "", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(122, $db->FIRSTKEY() eq "fred") ;
- ok(123, checkOutput( "", "", "", "")) ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter with a closure
-
- use warnings ;
- use strict ;
- my (%h, $db) ;
-
- unlink $Dfile;
- ok(124, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
-
- my %result = () ;
-
- sub Closure
- {
- my ($name) = @_ ;
- my $count = 0 ;
- my @kept = () ;
-
- return sub { ++$count ;
- push @kept, $_ ;
- $result{$name} = "$name - $count: [@kept]" ;
- }
- }
-
- $db->filter_store_key(Closure("store key")) ;
- $db->filter_store_value(Closure("store value")) ;
- $db->filter_fetch_key(Closure("fetch key")) ;
- $db->filter_fetch_value(Closure("fetch value")) ;
-
- $_ = "original" ;
-
- $h{"fred"} = "joe" ;
- ok(125, $result{"store key"} eq "store key - 1: [fred]");
- ok(126, $result{"store value"} eq "store value - 1: [joe]");
- ok(127, ! defined $result{"fetch key"} );
- ok(128, ! defined $result{"fetch value"} );
- ok(129, $_ eq "original") ;
-
- ok(130, $db->FIRSTKEY() eq "fred") ;
- ok(131, $result{"store key"} eq "store key - 1: [fred]");
- ok(132, $result{"store value"} eq "store value - 1: [joe]");
- ok(133, $result{"fetch key"} eq "fetch key - 1: [fred]");
- ok(134, ! defined $result{"fetch value"} );
- ok(135, $_ eq "original") ;
-
- $h{"jim"} = "john" ;
- ok(136, $result{"store key"} eq "store key - 2: [fred jim]");
- ok(137, $result{"store value"} eq "store value - 2: [joe john]");
- ok(138, $result{"fetch key"} eq "fetch key - 1: [fred]");
- ok(139, ! defined $result{"fetch value"} );
- ok(140, $_ eq "original") ;
-
- ok(141, $h{"fred"} eq "joe");
- ok(142, $result{"store key"} eq "store key - 3: [fred jim fred]");
- ok(143, $result{"store value"} eq "store value - 2: [joe john]");
- ok(144, $result{"fetch key"} eq "fetch key - 1: [fred]");
- ok(145, $result{"fetch value"} eq "fetch value - 1: [joe]");
- ok(146, $_ eq "original") ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter recursion detection
- use warnings ;
- use strict ;
- my (%h, $db) ;
- unlink $Dfile;
-
- ok(147, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
-
- $db->filter_store_key (sub { $_ = $h{$_} }) ;
-
- eval '$h{1} = 1234' ;
- ok(148, $@ =~ /^recursion detected in filter_store_key at/ );
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-
-{
- # Examples from the POD
-
-
- my $file = "xyzt" ;
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 1
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
-
- my %h ;
-
- sub Compare
- {
- my ($key1, $key2) = @_ ;
- "\L$key1" cmp "\L$key2" ;
- }
-
- # specify the Perl sub that will do the comparison
- $DB_BTREE->{'compare'} = \&Compare ;
-
- unlink "tree" ;
- tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open file 'tree': $!\n" ;
-
- # Add a key/value pair to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
- $h{'duck'} = 'donald' ;
-
- # Delete
- delete $h{"duck"} ;
-
- # Cycle through the keys printing them in order.
- # Note it is not necessary to sort the keys as
- # the btree will have kept them in order automatically.
- foreach (keys %h)
- { print "$_\n" }
-
- untie %h ;
-
- unlink "tree" ;
- }
-
- delete $DB_BTREE->{'compare'} ;
-
- ok(149, docat_del($file) eq <<'EOM') ;
-mouse
-Smith
-Wall
-EOM
-
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 2
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename %h ) ;
-
- $filename = "tree" ;
- unlink $filename ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- # Add some key/value pairs to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Wall'} = 'Brick' ; # Note the duplicate key
- $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
-
- # iterate through the associative array
- # and print each key/value pair.
- foreach (keys %h)
- { print "$_ -> $h{$_}\n" }
-
- untie %h ;
-
- unlink $filename ;
- }
-
- ok(150, docat_del($file) eq ($db185mode ? <<'EOM' : <<'EOM') ) ;
-Smith -> John
-Wall -> Brick
-Wall -> Brick
-Wall -> Brick
-mouse -> mickey
-EOM
-Smith -> John
-Wall -> Larry
-Wall -> Larry
-Wall -> Larry
-mouse -> mickey
-EOM
-
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 3
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h $status $key $value) ;
-
- $filename = "tree" ;
- unlink $filename ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- # Add some key/value pairs to the file
- $h{'Wall'} = 'Larry' ;
- $h{'Wall'} = 'Brick' ; # Note the duplicate key
- $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
- $h{'Smith'} = 'John' ;
- $h{'mouse'} = 'mickey' ;
-
- # iterate through the btree using seq
- # and print each key/value pair.
- $key = $value = 0 ;
- for ($status = $x->seq($key, $value, R_FIRST) ;
- $status == 0 ;
- $status = $x->seq($key, $value, R_NEXT) )
- { print "$key -> $value\n" }
-
-
- undef $x ;
- untie %h ;
- }
-
- ok(151, docat_del($file) eq ($db185mode == 1 ? <<'EOM' : <<'EOM') ) ;
-Smith -> John
-Wall -> Brick
-Wall -> Brick
-Wall -> Larry
-mouse -> mickey
-EOM
-Smith -> John
-Wall -> Larry
-Wall -> Brick
-Wall -> Brick
-mouse -> mickey
-EOM
-
-
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 4
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h ) ;
-
- $filename = "tree" ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- my $cnt = $x->get_dup("Wall") ;
- print "Wall occurred $cnt times\n" ;
-
- my %hash = $x->get_dup("Wall", 1) ;
- print "Larry is there\n" if $hash{'Larry'} ;
- print "There are $hash{'Brick'} Brick Walls\n" ;
-
- my @list = sort $x->get_dup("Wall") ;
- print "Wall => [@list]\n" ;
-
- @list = $x->get_dup("Smith") ;
- print "Smith => [@list]\n" ;
-
- @list = $x->get_dup("Dog") ;
- print "Dog => [@list]\n" ;
-
- undef $x ;
- untie %h ;
- }
-
- ok(152, docat_del($file) eq <<'EOM') ;
-Wall occurred 3 times
-Larry is there
-There are 2 Brick Walls
-Wall => [Brick Brick Larry]
-Smith => [John]
-Dog => []
-EOM
-
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 5
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h $found) ;
-
- my $filename = "tree" ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
- print "Larry Wall is $found there\n" ;
-
- $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
- print "Harry Wall is $found there\n" ;
-
- undef $x ;
- untie %h ;
- }
-
- ok(153, docat_del($file) eq <<'EOM') ;
-Larry Wall is there
-Harry Wall is not there
-EOM
-
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 6
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
-
- use vars qw($filename $x %h $found) ;
-
- my $filename = "tree" ;
-
- # Enable duplicate records
- $DB_BTREE->{'flags'} = R_DUP ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- $x->del_dup("Wall", "Larry") ;
-
- $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
- print "Larry Wall is $found there\n" ;
-
- undef $x ;
- untie %h ;
-
- unlink $filename ;
- }
-
- ok(154, docat_del($file) eq <<'EOM') ;
-Larry Wall is not there
-EOM
-
- {
- my $redirect = new Redirect $file ;
-
- # BTREE example 7
- ###
-
- use warnings FATAL => qw(all) ;
- use strict ;
- use DB_File ;
- use Fcntl ;
-
- use vars qw($filename $x %h $st $key $value) ;
-
- sub match
- {
- my $key = shift ;
- my $value = 0;
- my $orig_key = $key ;
- $x->seq($key, $value, R_CURSOR) ;
- print "$orig_key\t-> $key\t-> $value\n" ;
- }
-
- $filename = "tree" ;
- unlink $filename ;
-
- $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
- or die "Cannot open $filename: $!\n";
-
- # Add some key/value pairs to the file
- $h{'mouse'} = 'mickey' ;
- $h{'Wall'} = 'Larry' ;
- $h{'Walls'} = 'Brick' ;
- $h{'Smith'} = 'John' ;
-
-
- $key = $value = 0 ;
- print "IN ORDER\n" ;
- for ($st = $x->seq($key, $value, R_FIRST) ;
- $st == 0 ;
- $st = $x->seq($key, $value, R_NEXT) )
-
- { print "$key -> $value\n" }
-
- print "\nPARTIAL MATCH\n" ;
-
- match "Wa" ;
- match "A" ;
- match "a" ;
-
- undef $x ;
- untie %h ;
-
- unlink $filename ;
-
- }
-
- ok(155, docat_del($file) eq <<'EOM') ;
-IN ORDER
-Smith -> John
-Wall -> Larry
-Walls -> Brick
-mouse -> mickey
-
-PARTIAL MATCH
-Wa -> Wall -> Larry
-A -> Smith -> John
-a -> mouse -> mickey
-EOM
-
-}
-
-#{
-# # R_SETCURSOR
-# use strict ;
-# my (%h, $db) ;
-# unlink $Dfile;
-#
-# ok(156, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
-#
-# $h{abc} = 33 ;
-# my $k = "newest" ;
-# my $v = 44 ;
-# my $status = $db->put($k, $v, R_SETCURSOR) ;
-# print "status = [$status]\n" ;
-# ok(157, $status == 0) ;
-# $status = $db->del($k, R_CURSOR) ;
-# print "status = [$status]\n" ;
-# ok(158, $status == 0) ;
-# $k = "newest" ;
-# ok(159, $db->get($k, $v, R_CURSOR)) ;
-#
-# ok(160, keys %h == 1) ;
-#
-# undef $db ;
-# untie %h;
-# unlink $Dfile;
-#}
-
-{
- # Bug ID 20001013.009
- #
- # test that $hash{KEY} = undef doesn't produce the warning
- # Use of uninitialized value in null operation
- use warnings ;
- use strict ;
- use DB_File ;
-
- unlink $Dfile;
- my %h ;
- my $a = "";
- local $SIG{__WARN__} = sub {$a = $_[0]} ;
-
- tie %h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_BTREE
- or die "Can't open file: $!\n" ;
- $h{ABC} = undef;
- ok(156, $a eq "") ;
- untie %h ;
- unlink $Dfile;
-}
-
-{
- # test that %hash = () doesn't produce the warning
- # Argument "" isn't numeric in entersub
- use warnings ;
- use strict ;
- use DB_File ;
-
- unlink $Dfile;
- my %h ;
- my $a = "";
- local $SIG{__WARN__} = sub {$a = $_[0]} ;
-
- tie %h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_BTREE
- or die "Can't open file: $!\n" ;
- %h = (); ;
- ok(157, $a eq "") ;
- untie %h ;
- unlink $Dfile;
-}
-
-exit ;
diff --git a/bdb/perl.DB_File/t/db-hash.t b/bdb/perl.DB_File/t/db-hash.t
deleted file mode 100644
index a6efd981004..00000000000
--- a/bdb/perl.DB_File/t/db-hash.t
+++ /dev/null
@@ -1,753 +0,0 @@
-#!./perl
-
-use warnings ;
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use Config;
-
-BEGIN {
- if(-d "lib" && -f "TEST") {
- if ($Config{'extensions'} !~ /\bDB_File\b/ ) {
- print "1..111\n";
- exit 0;
- }
- }
-}
-
-use DB_File;
-use Fcntl;
-
-print "1..111\n";
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat_del
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file: $!";
- my $result = <CAT>;
- close(CAT);
- unlink $file ;
- return $result;
-}
-
-my $Dfile = "dbhash.tmp";
-my $null_keys_allowed = ($DB_File::db_ver < 2.004010
- || $DB_File::db_ver >= 3.1 );
-
-unlink $Dfile;
-
-umask(0);
-
-# Check the interface to HASHINFO
-
-my $dbh = new DB_File::HASHINFO ;
-
-ok(1, ! defined $dbh->{bsize}) ;
-ok(2, ! defined $dbh->{ffactor}) ;
-ok(3, ! defined $dbh->{nelem}) ;
-ok(4, ! defined $dbh->{cachesize}) ;
-ok(5, ! defined $dbh->{hash}) ;
-ok(6, ! defined $dbh->{lorder}) ;
-
-$dbh->{bsize} = 3000 ;
-ok(7, $dbh->{bsize} == 3000 );
-
-$dbh->{ffactor} = 9000 ;
-ok(8, $dbh->{ffactor} == 9000 );
-
-$dbh->{nelem} = 400 ;
-ok(9, $dbh->{nelem} == 400 );
-
-$dbh->{cachesize} = 65 ;
-ok(10, $dbh->{cachesize} == 65 );
-
-$dbh->{hash} = "abc" ;
-ok(11, $dbh->{hash} eq "abc" );
-
-$dbh->{lorder} = 1234 ;
-ok(12, $dbh->{lorder} == 1234 );
-
-# Check that an invalid entry is caught both for store & fetch
-eval '$dbh->{fred} = 1234' ;
-ok(13, $@ =~ /^DB_File::HASHINFO::STORE - Unknown element 'fred' at/ );
-eval 'my $q = $dbh->{fred}' ;
-ok(14, $@ =~ /^DB_File::HASHINFO::FETCH - Unknown element 'fred' at/ );
-
-
-# Now check the interface to HASH
-my ($X, %h);
-ok(15, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
-
-my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
- $blksize,$blocks) = stat($Dfile);
-ok(16, ($mode & 0777) == ($^O eq 'os2' ? 0666 : 0640) || $^O eq 'amigaos' || $^O eq 'MSWin32');
-
-my ($key, $value, $i);
-while (($key,$value) = each(%h)) {
- $i++;
-}
-ok(17, !$i );
-
-$h{'goner1'} = 'snork';
-
-$h{'abc'} = 'ABC';
-ok(18, $h{'abc'} eq 'ABC' );
-ok(19, !defined $h{'jimmy'} );
-ok(20, !exists $h{'jimmy'} );
-ok(21, exists $h{'abc'} );
-
-$h{'def'} = 'DEF';
-$h{'jkl','mno'} = "JKL\034MNO";
-$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5);
-$h{'a'} = 'A';
-
-#$h{'b'} = 'B';
-$X->STORE('b', 'B') ;
-
-$h{'c'} = 'C';
-
-#$h{'d'} = 'D';
-$X->put('d', 'D') ;
-
-$h{'e'} = 'E';
-$h{'f'} = 'F';
-$h{'g'} = 'X';
-$h{'h'} = 'H';
-$h{'i'} = 'I';
-
-$h{'goner2'} = 'snork';
-delete $h{'goner2'};
-
-
-# IMPORTANT - $X must be undefined before the untie otherwise the
-# underlying DB close routine will not get called.
-undef $X ;
-untie(%h);
-
-
-# tie to the same file again, do not supply a type - should default to HASH
-ok(22, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640) );
-
-# Modify an entry from the previous tie
-$h{'g'} = 'G';
-
-$h{'j'} = 'J';
-$h{'k'} = 'K';
-$h{'l'} = 'L';
-$h{'m'} = 'M';
-$h{'n'} = 'N';
-$h{'o'} = 'O';
-$h{'p'} = 'P';
-$h{'q'} = 'Q';
-$h{'r'} = 'R';
-$h{'s'} = 'S';
-$h{'t'} = 'T';
-$h{'u'} = 'U';
-$h{'v'} = 'V';
-$h{'w'} = 'W';
-$h{'x'} = 'X';
-$h{'y'} = 'Y';
-$h{'z'} = 'Z';
-
-$h{'goner3'} = 'snork';
-
-delete $h{'goner1'};
-$X->DELETE('goner3');
-
-my @keys = keys(%h);
-my @values = values(%h);
-
-ok(23, $#keys == 29 && $#values == 29) ;
-
-$i = 0 ;
-while (($key,$value) = each(%h)) {
- if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) {
- $key =~ y/a-z/A-Z/;
- $i++ if $key eq $value;
- }
-}
-
-ok(24, $i == 30) ;
-
-@keys = ('blurfl', keys(%h), 'dyick');
-ok(25, $#keys == 31) ;
-
-$h{'foo'} = '';
-ok(26, $h{'foo'} eq '' );
-
-# Berkeley DB from version 2.4.10 to 3.0 does not allow null keys.
-# This feature was reenabled in version 3.1 of Berkeley DB.
-my $result = 0 ;
-if ($null_keys_allowed) {
- $h{''} = 'bar';
- $result = ( $h{''} eq 'bar' );
-}
-else
- { $result = 1 }
-ok(27, $result) ;
-
-# check cache overflow and numeric keys and contents
-my $ok = 1;
-for ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; }
-for ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; }
-ok(28, $ok );
-
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
- $blksize,$blocks) = stat($Dfile);
-ok(29, $size > 0 );
-
-@h{0..200} = 200..400;
-my @foo = @h{0..200};
-ok(30, join(':',200..400) eq join(':',@foo) );
-
-
-# Now check all the non-tie specific stuff
-
-# Check NOOVERWRITE will make put fail when attempting to overwrite
-# an existing record.
-
-my $status = $X->put( 'x', 'newvalue', R_NOOVERWRITE) ;
-ok(31, $status == 1 );
-
-# check that the value of the key 'x' has not been changed by the
-# previous test
-ok(32, $h{'x'} eq 'X' );
-
-# standard put
-$status = $X->put('key', 'value') ;
-ok(33, $status == 0 );
-
-#check that previous put can be retrieved
-$value = 0 ;
-$status = $X->get('key', $value) ;
-ok(34, $status == 0 );
-ok(35, $value eq 'value' );
-
-# Attempting to delete an existing key should work
-
-$status = $X->del('q') ;
-ok(36, $status == 0 );
-
-# Make sure that the key deleted, cannot be retrieved
-{
- no warnings 'uninitialized' ;
- ok(37, $h{'q'} eq undef );
-}
-
-# Attempting to delete a non-existant key should fail
-
-$status = $X->del('joe') ;
-ok(38, $status == 1 );
-
-# Check the get interface
-
-# First a non-existing key
-$status = $X->get('aaaa', $value) ;
-ok(39, $status == 1 );
-
-# Next an existing key
-$status = $X->get('a', $value) ;
-ok(40, $status == 0 );
-ok(41, $value eq 'A' );
-
-# seq
-# ###
-
-# ditto, but use put to replace the key/value pair.
-
-# use seq to walk backwards through a file - check that this reversed is
-
-# check seq FIRST/LAST
-
-# sync
-# ####
-
-$status = $X->sync ;
-ok(42, $status == 0 );
-
-
-# fd
-# ##
-
-$status = $X->fd ;
-ok(43, $status != 0 );
-
-undef $X ;
-untie %h ;
-
-unlink $Dfile;
-
-# clear
-# #####
-
-ok(44, tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
-foreach (1 .. 10)
- { $h{$_} = $_ * 100 }
-
-# check that there are 10 elements in the hash
-$i = 0 ;
-while (($key,$value) = each(%h)) {
- $i++;
-}
-ok(45, $i == 10);
-
-# now clear the hash
-%h = () ;
-
-# check it is empty
-$i = 0 ;
-while (($key,$value) = each(%h)) {
- $i++;
-}
-ok(46, $i == 0);
-
-untie %h ;
-unlink $Dfile ;
-
-
-# Now try an in memory file
-ok(47, $X = tie(%h, 'DB_File',undef, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
-
-# fd with an in memory file should return fail
-$status = $X->fd ;
-ok(48, $status == -1 );
-
-undef $X ;
-untie %h ;
-
-{
- # check ability to override the default hashing
- my %x ;
- my $filename = "xyz" ;
- my $hi = new DB_File::HASHINFO ;
- $::count = 0 ;
- $hi->{hash} = sub { ++$::count ; length $_[0] } ;
- ok(49, tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $hi ) ;
- $h{"abc"} = 123 ;
- ok(50, $h{"abc"} == 123) ;
- untie %x ;
- unlink $filename ;
- ok(51, $::count >0) ;
-}
-
-{
- # check that attempting to tie an array to a DB_HASH will fail
-
- my $filename = "xyz" ;
- my @x ;
- eval { tie @x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_HASH ; } ;
- ok(52, $@ =~ /^DB_File can only tie an associative array to a DB_HASH database/) ;
- unlink $filename ;
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use warnings ;
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use warnings ;
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use DB_File;
- @ISA=qw(DB_File);
- @EXPORT = @DB_File::EXPORT ;
-
- sub STORE {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::STORE($key, $value * 2) ;
- }
-
- sub FETCH {
- my $self = shift ;
- my $key = shift ;
- $self->SUPER::FETCH($key) - 1 ;
- }
-
- sub put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::put($key, $value * 3) ;
- }
-
- sub get {
- my $self = shift ;
- $self->SUPER::get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok(53, $@ eq "") ;
- my %h ;
- my $X ;
- eval '
- $X = tie(%h, "SubDB","dbhash.tmp", O_RDWR|O_CREAT, 0640, $DB_HASH );
- ' ;
-
- main::ok(54, $@ eq "") ;
-
- my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
- main::ok(55, $@ eq "") ;
- main::ok(56, $ret == 5) ;
-
- my $value = 0;
- $ret = eval '$X->put("joe", 4) ; $X->get("joe", $value) ; return $value' ;
- main::ok(57, $@ eq "") ;
- main::ok(58, $ret == 10) ;
-
- $ret = eval ' R_NEXT eq main::R_NEXT ' ;
- main::ok(59, $@ eq "" ) ;
- main::ok(60, $ret == 1) ;
-
- $ret = eval '$X->A_new_method("joe") ' ;
- main::ok(61, $@ eq "") ;
- main::ok(62, $ret eq "[[11]]") ;
-
- undef $X;
- untie(%h);
- unlink "SubDB.pm", "dbhash.tmp" ;
-
-}
-
-{
- # DBM Filter tests
- use warnings ;
- use strict ;
- my (%h, $db) ;
- my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- unlink $Dfile;
-
- sub checkOutput
- {
- my($fk, $sk, $fv, $sv) = @_ ;
- return
- $fetch_key eq $fk && $store_key eq $sk &&
- $fetch_value eq $fv && $store_value eq $sv &&
- $_ eq 'original' ;
- }
-
- ok(63, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
-
- $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
- $db->filter_store_key (sub { $store_key = $_ }) ;
- $db->filter_fetch_value (sub { $fetch_value = $_}) ;
- $db->filter_store_value (sub { $store_value = $_ }) ;
-
- $_ = "original" ;
-
- $h{"fred"} = "joe" ;
- # fk sk fv sv
- ok(64, checkOutput( "", "fred", "", "joe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(65, $h{"fred"} eq "joe");
- # fk sk fv sv
- ok(66, checkOutput( "", "fred", "joe", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(67, $db->FIRSTKEY() eq "fred") ;
- # fk sk fv sv
- ok(68, checkOutput( "fred", "", "", "")) ;
-
- # replace the filters, but remember the previous set
- my ($old_fk) = $db->filter_fetch_key
- (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
- my ($old_sk) = $db->filter_store_key
- (sub { $_ = lc $_ ; $store_key = $_ }) ;
- my ($old_fv) = $db->filter_fetch_value
- (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
- my ($old_sv) = $db->filter_store_value
- (sub { s/o/x/g; $store_value = $_ }) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"Fred"} = "Joe" ;
- # fk sk fv sv
- ok(69, checkOutput( "", "fred", "", "Jxe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(70, $h{"Fred"} eq "[Jxe]");
- # fk sk fv sv
- ok(71, checkOutput( "", "fred", "[Jxe]", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(72, $db->FIRSTKEY() eq "FRED") ;
- # fk sk fv sv
- ok(73, checkOutput( "FRED", "", "", "")) ;
-
- # put the original filters back
- $db->filter_fetch_key ($old_fk);
- $db->filter_store_key ($old_sk);
- $db->filter_fetch_value ($old_fv);
- $db->filter_store_value ($old_sv);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"fred"} = "joe" ;
- ok(74, checkOutput( "", "fred", "", "joe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(75, $h{"fred"} eq "joe");
- ok(76, checkOutput( "", "fred", "joe", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(77, $db->FIRSTKEY() eq "fred") ;
- ok(78, checkOutput( "fred", "", "", "")) ;
-
- # delete the filters
- $db->filter_fetch_key (undef);
- $db->filter_store_key (undef);
- $db->filter_fetch_value (undef);
- $db->filter_store_value (undef);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h{"fred"} = "joe" ;
- ok(79, checkOutput( "", "", "", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(80, $h{"fred"} eq "joe");
- ok(81, checkOutput( "", "", "", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(82, $db->FIRSTKEY() eq "fred") ;
- ok(83, checkOutput( "", "", "", "")) ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter with a closure
-
- use warnings ;
- use strict ;
- my (%h, $db) ;
-
- unlink $Dfile;
- ok(84, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
-
- my %result = () ;
-
- sub Closure
- {
- my ($name) = @_ ;
- my $count = 0 ;
- my @kept = () ;
-
- return sub { ++$count ;
- push @kept, $_ ;
- $result{$name} = "$name - $count: [@kept]" ;
- }
- }
-
- $db->filter_store_key(Closure("store key")) ;
- $db->filter_store_value(Closure("store value")) ;
- $db->filter_fetch_key(Closure("fetch key")) ;
- $db->filter_fetch_value(Closure("fetch value")) ;
-
- $_ = "original" ;
-
- $h{"fred"} = "joe" ;
- ok(85, $result{"store key"} eq "store key - 1: [fred]");
- ok(86, $result{"store value"} eq "store value - 1: [joe]");
- ok(87, ! defined $result{"fetch key"} );
- ok(88, ! defined $result{"fetch value"} );
- ok(89, $_ eq "original") ;
-
- ok(90, $db->FIRSTKEY() eq "fred") ;
- ok(91, $result{"store key"} eq "store key - 1: [fred]");
- ok(92, $result{"store value"} eq "store value - 1: [joe]");
- ok(93, $result{"fetch key"} eq "fetch key - 1: [fred]");
- ok(94, ! defined $result{"fetch value"} );
- ok(95, $_ eq "original") ;
-
- $h{"jim"} = "john" ;
- ok(96, $result{"store key"} eq "store key - 2: [fred jim]");
- ok(97, $result{"store value"} eq "store value - 2: [joe john]");
- ok(98, $result{"fetch key"} eq "fetch key - 1: [fred]");
- ok(99, ! defined $result{"fetch value"} );
- ok(100, $_ eq "original") ;
-
- ok(101, $h{"fred"} eq "joe");
- ok(102, $result{"store key"} eq "store key - 3: [fred jim fred]");
- ok(103, $result{"store value"} eq "store value - 2: [joe john]");
- ok(104, $result{"fetch key"} eq "fetch key - 1: [fred]");
- ok(105, $result{"fetch value"} eq "fetch value - 1: [joe]");
- ok(106, $_ eq "original") ;
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter recursion detection
- use warnings ;
- use strict ;
- my (%h, $db) ;
- unlink $Dfile;
-
- ok(107, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
-
- $db->filter_store_key (sub { $_ = $h{$_} }) ;
-
- eval '$h{1} = 1234' ;
- ok(108, $@ =~ /^recursion detected in filter_store_key at/ );
-
- undef $db ;
- untie %h;
- unlink $Dfile;
-}
-
-
-{
- # Examples from the POD
-
- my $file = "xyzt" ;
- {
- my $redirect = new Redirect $file ;
-
- use warnings FATAL => qw(all);
- use strict ;
- use DB_File ;
- use vars qw( %h $k $v ) ;
-
- unlink "fruit" ;
- tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH
- or die "Cannot open file 'fruit': $!\n";
-
- # Add a few key/value pairs to the file
- $h{"apple"} = "red" ;
- $h{"orange"} = "orange" ;
- $h{"banana"} = "yellow" ;
- $h{"tomato"} = "red" ;
-
- # Check for existence of a key
- print "Banana Exists\n\n" if $h{"banana"} ;
-
- # Delete a key/value pair.
- delete $h{"apple"} ;
-
- # print the contents of the file
- while (($k, $v) = each %h)
- { print "$k -> $v\n" }
-
- untie %h ;
-
- unlink "fruit" ;
- }
-
- ok(109, docat_del($file) eq <<'EOM') ;
-Banana Exists
-
-orange -> orange
-tomato -> red
-banana -> yellow
-EOM
-
-}
-
-{
- # Bug ID 20001013.009
- #
- # test that $hash{KEY} = undef doesn't produce the warning
- # Use of uninitialized value in null operation
- use warnings ;
- use strict ;
- use DB_File ;
-
- unlink $Dfile;
- my %h ;
- my $a = "";
- local $SIG{__WARN__} = sub {$a = $_[0]} ;
-
- tie %h, 'DB_File', $Dfile or die "Can't open file: $!\n" ;
- $h{ABC} = undef;
- ok(110, $a eq "") ;
- untie %h ;
- unlink $Dfile;
-}
-
-{
- # test that %hash = () doesn't produce the warning
- # Argument "" isn't numeric in entersub
- use warnings ;
- use strict ;
- use DB_File ;
-
- unlink $Dfile;
- my %h ;
- my $a = "";
- local $SIG{__WARN__} = sub {$a = $_[0]} ;
-
- tie %h, 'DB_File', $Dfile or die "Can't open file: $!\n" ;
- %h = (); ;
- ok(111, $a eq "") ;
- untie %h ;
- unlink $Dfile;
-}
-
-exit ;
diff --git a/bdb/perl.DB_File/t/db-recno.t b/bdb/perl.DB_File/t/db-recno.t
deleted file mode 100644
index c64d83b5916..00000000000
--- a/bdb/perl.DB_File/t/db-recno.t
+++ /dev/null
@@ -1,899 +0,0 @@
-#!./perl -w
-
-use warnings;
-use strict ;
-
-BEGIN {
- unless(grep /blib/, @INC) {
- chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
- }
-}
-
-use Config;
-
-BEGIN {
- if(-d "lib" && -f "TEST") {
- if ($Config{'extensions'} !~ /\bDB_File\b/ ) {
- print "1..128\n";
- exit 0;
- }
- }
-}
-
-use DB_File;
-use Fcntl;
-use vars qw($dbh $Dfile $bad_ones $FA) ;
-
-# full tied array support started in Perl 5.004_57
-# Double check to see if it is available.
-
-{
- sub try::TIEARRAY { bless [], "try" }
- sub try::FETCHSIZE { $FA = 1 }
- $FA = 0 ;
- my @a ;
- tie @a, 'try' ;
- my $a = @a ;
-}
-
-
-sub ok
-{
- my $no = shift ;
- my $result = shift ;
-
- print "not " unless $result ;
- print "ok $no\n" ;
-
- return $result ;
-}
-
-{
- package Redirect ;
- use Symbol ;
-
- sub new
- {
- my $class = shift ;
- my $filename = shift ;
- my $fh = gensym ;
- open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
- my $real_stdout = select($fh) ;
- return bless [$fh, $real_stdout ] ;
-
- }
- sub DESTROY
- {
- my $self = shift ;
- close $self->[0] ;
- select($self->[1]) ;
- }
-}
-
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
-sub docat_del
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file: $!";
- my $result = <CAT>;
- close(CAT);
- unlink $file ;
- return $result;
-}
-
-sub bad_one
-{
- print STDERR <<EOM unless $bad_ones++ ;
-#
-# Some older versions of Berkeley DB version 1 will fail tests 51,
-# 53 and 55.
-#
-# You can safely ignore the errors if you're never going to use the
-# broken functionality (recno databases with a modified bval).
-# Otherwise you'll have to upgrade your DB library.
-#
-# If you want to use Berkeley DB version 1, then 1.85 and 1.86 are the
-# last versions that were released. Berkeley DB version 2 is continually
-# being updated -- Check out http://www.sleepycat.com/ for more details.
-#
-EOM
-}
-
-print "1..128\n";
-
-my $Dfile = "recno.tmp";
-unlink $Dfile ;
-
-umask(0);
-
-# Check the interface to RECNOINFO
-
-my $dbh = new DB_File::RECNOINFO ;
-ok(1, ! defined $dbh->{bval}) ;
-ok(2, ! defined $dbh->{cachesize}) ;
-ok(3, ! defined $dbh->{psize}) ;
-ok(4, ! defined $dbh->{flags}) ;
-ok(5, ! defined $dbh->{lorder}) ;
-ok(6, ! defined $dbh->{reclen}) ;
-ok(7, ! defined $dbh->{bfname}) ;
-
-$dbh->{bval} = 3000 ;
-ok(8, $dbh->{bval} == 3000 );
-
-$dbh->{cachesize} = 9000 ;
-ok(9, $dbh->{cachesize} == 9000 );
-
-$dbh->{psize} = 400 ;
-ok(10, $dbh->{psize} == 400 );
-
-$dbh->{flags} = 65 ;
-ok(11, $dbh->{flags} == 65 );
-
-$dbh->{lorder} = 123 ;
-ok(12, $dbh->{lorder} == 123 );
-
-$dbh->{reclen} = 1234 ;
-ok(13, $dbh->{reclen} == 1234 );
-
-$dbh->{bfname} = 1234 ;
-ok(14, $dbh->{bfname} == 1234 );
-
-
-# Check that an invalid entry is caught both for store & fetch
-eval '$dbh->{fred} = 1234' ;
-ok(15, $@ =~ /^DB_File::RECNOINFO::STORE - Unknown element 'fred' at/ );
-eval 'my $q = $dbh->{fred}' ;
-ok(16, $@ =~ /^DB_File::RECNOINFO::FETCH - Unknown element 'fred' at/ );
-
-# Now check the interface to RECNOINFO
-
-my $X ;
-my @h ;
-ok(17, $X = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ;
-
-ok(18, ((stat($Dfile))[2] & 0777) == ($^O eq 'os2' ? 0666 : 0640)
- || $^O eq 'MSWin32' || $^O eq 'amigaos') ;
-
-#my $l = @h ;
-my $l = $X->length ;
-ok(19, ($FA ? @h == 0 : !$l) );
-
-my @data = qw( a b c d ever f g h i j k longername m n o p) ;
-
-$h[0] = shift @data ;
-ok(20, $h[0] eq 'a' );
-
-my $ i;
-foreach (@data)
- { $h[++$i] = $_ }
-
-unshift (@data, 'a') ;
-
-ok(21, defined $h[1] );
-ok(22, ! defined $h[16] );
-ok(23, $FA ? @h == @data : $X->length == @data );
-
-
-# Overwrite an entry & check fetch it
-$h[3] = 'replaced' ;
-$data[3] = 'replaced' ;
-ok(24, $h[3] eq 'replaced' );
-
-#PUSH
-my @push_data = qw(added to the end) ;
-($FA ? push(@h, @push_data) : $X->push(@push_data)) ;
-push (@data, @push_data) ;
-ok(25, $h[++$i] eq 'added' );
-ok(26, $h[++$i] eq 'to' );
-ok(27, $h[++$i] eq 'the' );
-ok(28, $h[++$i] eq 'end' );
-
-# POP
-my $popped = pop (@data) ;
-my $value = ($FA ? pop @h : $X->pop) ;
-ok(29, $value eq $popped) ;
-
-# SHIFT
-$value = ($FA ? shift @h : $X->shift) ;
-my $shifted = shift @data ;
-ok(30, $value eq $shifted );
-
-# UNSHIFT
-
-# empty list
-($FA ? unshift @h : $X->unshift) ;
-ok(31, ($FA ? @h == @data : $X->length == @data ));
-
-my @new_data = qw(add this to the start of the array) ;
-$FA ? unshift (@h, @new_data) : $X->unshift (@new_data) ;
-unshift (@data, @new_data) ;
-ok(32, $FA ? @h == @data : $X->length == @data );
-ok(33, $h[0] eq "add") ;
-ok(34, $h[1] eq "this") ;
-ok(35, $h[2] eq "to") ;
-ok(36, $h[3] eq "the") ;
-ok(37, $h[4] eq "start") ;
-ok(38, $h[5] eq "of") ;
-ok(39, $h[6] eq "the") ;
-ok(40, $h[7] eq "array") ;
-ok(41, $h[8] eq $data[8]) ;
-
-# SPLICE
-
-# Now both arrays should be identical
-
-my $ok = 1 ;
-my $j = 0 ;
-foreach (@data)
-{
- $ok = 0, last if $_ ne $h[$j ++] ;
-}
-ok(42, $ok );
-
-# Neagtive subscripts
-
-# get the last element of the array
-ok(43, $h[-1] eq $data[-1] );
-ok(44, $h[-1] eq $h[ ($FA ? @h : $X->length) -1] );
-
-# get the first element using a negative subscript
-eval '$h[ - ( $FA ? @h : $X->length)] = "abcd"' ;
-ok(45, $@ eq "" );
-ok(46, $h[0] eq "abcd" );
-
-# now try to read before the start of the array
-eval '$h[ - (1 + ($FA ? @h : $X->length))] = 1234' ;
-ok(47, $@ =~ '^Modification of non-creatable array value attempted' );
-
-# IMPORTANT - $X must be undefined before the untie otherwise the
-# underlying DB close routine will not get called.
-undef $X ;
-untie(@h);
-
-unlink $Dfile;
-
-
-{
- # Check bval defaults to \n
-
- my @h = () ;
- my $dbh = new DB_File::RECNOINFO ;
- ok(48, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
- $h[0] = "abc" ;
- $h[1] = "def" ;
- $h[3] = "ghi" ;
- untie @h ;
- my $x = docat($Dfile) ;
- unlink $Dfile;
- ok(49, $x eq "abc\ndef\n\nghi\n") ;
-}
-
-{
- # Change bval
-
- my @h = () ;
- my $dbh = new DB_File::RECNOINFO ;
- $dbh->{bval} = "-" ;
- ok(50, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
- $h[0] = "abc" ;
- $h[1] = "def" ;
- $h[3] = "ghi" ;
- untie @h ;
- my $x = docat($Dfile) ;
- unlink $Dfile;
- my $ok = ($x eq "abc-def--ghi-") ;
- bad_one() unless $ok ;
- ok(51, $ok) ;
-}
-
-{
- # Check R_FIXEDLEN with default bval (space)
-
- my @h = () ;
- my $dbh = new DB_File::RECNOINFO ;
- $dbh->{flags} = R_FIXEDLEN ;
- $dbh->{reclen} = 5 ;
- ok(52, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
- $h[0] = "abc" ;
- $h[1] = "def" ;
- $h[3] = "ghi" ;
- untie @h ;
- my $x = docat($Dfile) ;
- unlink $Dfile;
- my $ok = ($x eq "abc def ghi ") ;
- bad_one() unless $ok ;
- ok(53, $ok) ;
-}
-
-{
- # Check R_FIXEDLEN with user-defined bval
-
- my @h = () ;
- my $dbh = new DB_File::RECNOINFO ;
- $dbh->{flags} = R_FIXEDLEN ;
- $dbh->{bval} = "-" ;
- $dbh->{reclen} = 5 ;
- ok(54, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
- $h[0] = "abc" ;
- $h[1] = "def" ;
- $h[3] = "ghi" ;
- untie @h ;
- my $x = docat($Dfile) ;
- unlink $Dfile;
- my $ok = ($x eq "abc--def-------ghi--") ;
- bad_one() unless $ok ;
- ok(55, $ok) ;
-}
-
-{
- # check that attempting to tie an associative array to a DB_RECNO will fail
-
- my $filename = "xyz" ;
- my %x ;
- eval { tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO ; } ;
- ok(56, $@ =~ /^DB_File can only tie an array to a DB_RECNO database/) ;
- unlink $filename ;
-}
-
-{
- # sub-class test
-
- package Another ;
-
- use warnings ;
- use strict ;
-
- open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
- print FILE <<'EOM' ;
-
- package SubDB ;
-
- use warnings ;
- use strict ;
- use vars qw( @ISA @EXPORT) ;
-
- require Exporter ;
- use DB_File;
- @ISA=qw(DB_File);
- @EXPORT = @DB_File::EXPORT ;
-
- sub STORE {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::STORE($key, $value * 2) ;
- }
-
- sub FETCH {
- my $self = shift ;
- my $key = shift ;
- $self->SUPER::FETCH($key) - 1 ;
- }
-
- sub put {
- my $self = shift ;
- my $key = shift ;
- my $value = shift ;
- $self->SUPER::put($key, $value * 3) ;
- }
-
- sub get {
- my $self = shift ;
- $self->SUPER::get($_[0], $_[1]) ;
- $_[1] -= 2 ;
- }
-
- sub A_new_method
- {
- my $self = shift ;
- my $key = shift ;
- my $value = $self->FETCH($key) ;
- return "[[$value]]" ;
- }
-
- 1 ;
-EOM
-
- close FILE ;
-
- BEGIN { push @INC, '.'; }
- eval 'use SubDB ; ';
- main::ok(57, $@ eq "") ;
- my @h ;
- my $X ;
- eval '
- $X = tie(@h, "SubDB","recno.tmp", O_RDWR|O_CREAT, 0640, $DB_RECNO );
- ' ;
-
- main::ok(58, $@ eq "") ;
-
- my $ret = eval '$h[3] = 3 ; return $h[3] ' ;
- main::ok(59, $@ eq "") ;
- main::ok(60, $ret == 5) ;
-
- my $value = 0;
- $ret = eval '$X->put(1, 4) ; $X->get(1, $value) ; return $value' ;
- main::ok(61, $@ eq "") ;
- main::ok(62, $ret == 10) ;
-
- $ret = eval ' R_NEXT eq main::R_NEXT ' ;
- main::ok(63, $@ eq "" ) ;
- main::ok(64, $ret == 1) ;
-
- $ret = eval '$X->A_new_method(1) ' ;
- main::ok(65, $@ eq "") ;
- main::ok(66, $ret eq "[[11]]") ;
-
- undef $X;
- untie(@h);
- unlink "SubDB.pm", "recno.tmp" ;
-
-}
-
-{
-
- # test $#
- my $self ;
- unlink $Dfile;
- ok(67, $self = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ;
- $h[0] = "abc" ;
- $h[1] = "def" ;
- $h[2] = "ghi" ;
- $h[3] = "jkl" ;
- ok(68, $FA ? $#h == 3 : $self->length() == 4) ;
- undef $self ;
- untie @h ;
- my $x = docat($Dfile) ;
- ok(69, $x eq "abc\ndef\nghi\njkl\n") ;
-
- # $# sets array to same length
- ok(70, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
- if ($FA)
- { $#h = 3 }
- else
- { $self->STORESIZE(4) }
- ok(71, $FA ? $#h == 3 : $self->length() == 4) ;
- undef $self ;
- untie @h ;
- $x = docat($Dfile) ;
- ok(72, $x eq "abc\ndef\nghi\njkl\n") ;
-
- # $# sets array to bigger
- ok(73, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
- if ($FA)
- { $#h = 6 }
- else
- { $self->STORESIZE(7) }
- ok(74, $FA ? $#h == 6 : $self->length() == 7) ;
- undef $self ;
- untie @h ;
- $x = docat($Dfile) ;
- ok(75, $x eq "abc\ndef\nghi\njkl\n\n\n\n") ;
-
- # $# sets array smaller
- ok(76, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
- if ($FA)
- { $#h = 2 }
- else
- { $self->STORESIZE(3) }
- ok(77, $FA ? $#h == 2 : $self->length() == 3) ;
- undef $self ;
- untie @h ;
- $x = docat($Dfile) ;
- ok(78, $x eq "abc\ndef\nghi\n") ;
-
- unlink $Dfile;
-
-
-}
-
-{
- # DBM Filter tests
- use warnings ;
- use strict ;
- my (@h, $db) ;
- my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- unlink $Dfile;
-
- sub checkOutput
- {
- my($fk, $sk, $fv, $sv) = @_ ;
- return
- $fetch_key eq $fk && $store_key eq $sk &&
- $fetch_value eq $fv && $store_value eq $sv &&
- $_ eq 'original' ;
- }
-
- ok(79, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
-
- $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
- $db->filter_store_key (sub { $store_key = $_ }) ;
- $db->filter_fetch_value (sub { $fetch_value = $_}) ;
- $db->filter_store_value (sub { $store_value = $_ }) ;
-
- $_ = "original" ;
-
- $h[0] = "joe" ;
- # fk sk fv sv
- ok(80, checkOutput( "", 0, "", "joe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(81, $h[0] eq "joe");
- # fk sk fv sv
- ok(82, checkOutput( "", 0, "joe", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(83, $db->FIRSTKEY() == 0) ;
- # fk sk fv sv
- ok(84, checkOutput( 0, "", "", "")) ;
-
- # replace the filters, but remember the previous set
- my ($old_fk) = $db->filter_fetch_key
- (sub { ++ $_ ; $fetch_key = $_ }) ;
- my ($old_sk) = $db->filter_store_key
- (sub { $_ *= 2 ; $store_key = $_ }) ;
- my ($old_fv) = $db->filter_fetch_value
- (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
- my ($old_sv) = $db->filter_store_value
- (sub { s/o/x/g; $store_value = $_ }) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h[1] = "Joe" ;
- # fk sk fv sv
- ok(85, checkOutput( "", 2, "", "Jxe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(86, $h[1] eq "[Jxe]");
- # fk sk fv sv
- ok(87, checkOutput( "", 2, "[Jxe]", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(88, $db->FIRSTKEY() == 1) ;
- # fk sk fv sv
- ok(89, checkOutput( 1, "", "", "")) ;
-
- # put the original filters back
- $db->filter_fetch_key ($old_fk);
- $db->filter_store_key ($old_sk);
- $db->filter_fetch_value ($old_fv);
- $db->filter_store_value ($old_sv);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h[0] = "joe" ;
- ok(90, checkOutput( "", 0, "", "joe")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(91, $h[0] eq "joe");
- ok(92, checkOutput( "", 0, "joe", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(93, $db->FIRSTKEY() == 0) ;
- ok(94, checkOutput( 0, "", "", "")) ;
-
- # delete the filters
- $db->filter_fetch_key (undef);
- $db->filter_store_key (undef);
- $db->filter_fetch_value (undef);
- $db->filter_store_value (undef);
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- $h[0] = "joe" ;
- ok(95, checkOutput( "", "", "", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(96, $h[0] eq "joe");
- ok(97, checkOutput( "", "", "", "")) ;
-
- ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
- ok(98, $db->FIRSTKEY() == 0) ;
- ok(99, checkOutput( "", "", "", "")) ;
-
- undef $db ;
- untie @h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter with a closure
-
- use warnings ;
- use strict ;
- my (@h, $db) ;
-
- unlink $Dfile;
- ok(100, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
-
- my %result = () ;
-
- sub Closure
- {
- my ($name) = @_ ;
- my $count = 0 ;
- my @kept = () ;
-
- return sub { ++$count ;
- push @kept, $_ ;
- $result{$name} = "$name - $count: [@kept]" ;
- }
- }
-
- $db->filter_store_key(Closure("store key")) ;
- $db->filter_store_value(Closure("store value")) ;
- $db->filter_fetch_key(Closure("fetch key")) ;
- $db->filter_fetch_value(Closure("fetch value")) ;
-
- $_ = "original" ;
-
- $h[0] = "joe" ;
- ok(101, $result{"store key"} eq "store key - 1: [0]");
- ok(102, $result{"store value"} eq "store value - 1: [joe]");
- ok(103, ! defined $result{"fetch key"} );
- ok(104, ! defined $result{"fetch value"} );
- ok(105, $_ eq "original") ;
-
- ok(106, $db->FIRSTKEY() == 0 ) ;
- ok(107, $result{"store key"} eq "store key - 1: [0]");
- ok(108, $result{"store value"} eq "store value - 1: [joe]");
- ok(109, $result{"fetch key"} eq "fetch key - 1: [0]");
- ok(110, ! defined $result{"fetch value"} );
- ok(111, $_ eq "original") ;
-
- $h[7] = "john" ;
- ok(112, $result{"store key"} eq "store key - 2: [0 7]");
- ok(113, $result{"store value"} eq "store value - 2: [joe john]");
- ok(114, $result{"fetch key"} eq "fetch key - 1: [0]");
- ok(115, ! defined $result{"fetch value"} );
- ok(116, $_ eq "original") ;
-
- ok(117, $h[0] eq "joe");
- ok(118, $result{"store key"} eq "store key - 3: [0 7 0]");
- ok(119, $result{"store value"} eq "store value - 2: [joe john]");
- ok(120, $result{"fetch key"} eq "fetch key - 1: [0]");
- ok(121, $result{"fetch value"} eq "fetch value - 1: [joe]");
- ok(122, $_ eq "original") ;
-
- undef $db ;
- untie @h;
- unlink $Dfile;
-}
-
-{
- # DBM Filter recursion detection
- use warnings ;
- use strict ;
- my (@h, $db) ;
- unlink $Dfile;
-
- ok(123, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
-
- $db->filter_store_key (sub { $_ = $h[0] }) ;
-
- eval '$h[1] = 1234' ;
- ok(124, $@ =~ /^recursion detected in filter_store_key at/ );
-
- undef $db ;
- untie @h;
- unlink $Dfile;
-}
-
-
-{
- # Examples from the POD
-
- my $file = "xyzt" ;
- {
- my $redirect = new Redirect $file ;
-
- use warnings FATAL => qw(all);
- use strict ;
- use DB_File ;
-
- my $filename = "text" ;
- unlink $filename ;
-
- my @h ;
- my $x = tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO
- or die "Cannot open file 'text': $!\n" ;
-
- # Add a few key/value pairs to the file
- $h[0] = "orange" ;
- $h[1] = "blue" ;
- $h[2] = "yellow" ;
-
- $FA ? push @h, "green", "black"
- : $x->push("green", "black") ;
-
- my $elements = $FA ? scalar @h : $x->length ;
- print "The array contains $elements entries\n" ;
-
- my $last = $FA ? pop @h : $x->pop ;
- print "popped $last\n" ;
-
- $FA ? unshift @h, "white"
- : $x->unshift("white") ;
- my $first = $FA ? shift @h : $x->shift ;
- print "shifted $first\n" ;
-
- # Check for existence of a key
- print "Element 1 Exists with value $h[1]\n" if $h[1] ;
-
- # use a negative index
- print "The last element is $h[-1]\n" ;
- print "The 2nd last element is $h[-2]\n" ;
-
- undef $x ;
- untie @h ;
-
- unlink $filename ;
- }
-
- ok(125, docat_del($file) eq <<'EOM') ;
-The array contains 5 entries
-popped black
-shifted white
-Element 1 Exists with value blue
-The last element is green
-The 2nd last element is yellow
-EOM
-
- my $save_output = "xyzt" ;
- {
- my $redirect = new Redirect $save_output ;
-
- use warnings FATAL => qw(all);
- use strict ;
- use vars qw(@h $H $file $i) ;
- use DB_File ;
- use Fcntl ;
-
- $file = "text" ;
-
- unlink $file ;
-
- $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0640, $DB_RECNO
- or die "Cannot open file $file: $!\n" ;
-
- # first create a text file to play with
- $h[0] = "zero" ;
- $h[1] = "one" ;
- $h[2] = "two" ;
- $h[3] = "three" ;
- $h[4] = "four" ;
-
-
- # Print the records in order.
- #
- # The length method is needed here because evaluating a tied
- # array in a scalar context does not return the number of
- # elements in the array.
-
- print "\nORIGINAL\n" ;
- foreach $i (0 .. $H->length - 1) {
- print "$i: $h[$i]\n" ;
- }
-
- # use the push & pop methods
- $a = $H->pop ;
- $H->push("last") ;
- print "\nThe last record was [$a]\n" ;
-
- # and the shift & unshift methods
- $a = $H->shift ;
- $H->unshift("first") ;
- print "The first record was [$a]\n" ;
-
- # Use the API to add a new record after record 2.
- $i = 2 ;
- $H->put($i, "Newbie", R_IAFTER) ;
-
- # and a new record before record 1.
- $i = 1 ;
- $H->put($i, "New One", R_IBEFORE) ;
-
- # delete record 3
- $H->del(3) ;
-
- # now print the records in reverse order
- print "\nREVERSE\n" ;
- for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
- { print "$i: $h[$i]\n" }
-
- # same again, but use the API functions instead
- print "\nREVERSE again\n" ;
- my ($s, $k, $v) = (0, 0, 0) ;
- for ($s = $H->seq($k, $v, R_LAST) ;
- $s == 0 ;
- $s = $H->seq($k, $v, R_PREV))
- { print "$k: $v\n" }
-
- undef $H ;
- untie @h ;
-
- unlink $file ;
- }
-
- ok(126, docat_del($save_output) eq <<'EOM') ;
-
-ORIGINAL
-0: zero
-1: one
-2: two
-3: three
-4: four
-
-The last record was [four]
-The first record was [zero]
-
-REVERSE
-5: last
-4: three
-3: Newbie
-2: one
-1: New One
-0: first
-
-REVERSE again
-5: last
-4: three
-3: Newbie
-2: one
-1: New One
-0: first
-EOM
-
-}
-
-{
- # Bug ID 20001013.009
- #
- # test that $hash{KEY} = undef doesn't produce the warning
- # Use of uninitialized value in null operation
- use warnings ;
- use strict ;
- use DB_File ;
-
- unlink $Dfile;
- my @h ;
- my $a = "";
- local $SIG{__WARN__} = sub {$a = $_[0]} ;
-
- tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_RECNO
- or die "Can't open file: $!\n" ;
- $h[0] = undef;
- ok(127, $a eq "") ;
- untie @h ;
- unlink $Dfile;
-}
-
-{
- # test that %hash = () doesn't produce the warning
- # Argument "" isn't numeric in entersub
- use warnings ;
- use strict ;
- use DB_File ;
- my $a = "";
- local $SIG{__WARN__} = sub {$a = $_[0]} ;
-
- unlink $Dfile;
- my @h ;
-
- tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_RECNO
- or die "Can't open file: $!\n" ;
- @h = (); ;
- ok(128, $a eq "") ;
- untie @h ;
- unlink $Dfile;
-}
-
-exit ;
diff --git a/bdb/perl.DB_File/typemap b/bdb/perl.DB_File/typemap
deleted file mode 100644
index 55439ee76d9..00000000000
--- a/bdb/perl.DB_File/typemap
+++ /dev/null
@@ -1,44 +0,0 @@
-# typemap for Perl 5 interface to Berkeley
-#
-# written by Paul Marquess <Paul.Marquess@btinternet.com>
-# last modified 10th December 2000
-# version 1.74
-#
-#################################### DB SECTION
-#
-#
-
-u_int T_U_INT
-DB_File T_PTROBJ
-DBT T_dbtdatum
-DBTKEY T_dbtkeydatum
-
-INPUT
-T_dbtkeydatum
- ckFilter($arg, filter_store_key, \"filter_store_key\");
- DBT_clear($var) ;
- if (db->type != DB_RECNO) {
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- }
- else {
- Value = GetRecnoKey(aTHX_ db, SvIV($arg)) ;
- $var.data = & Value;
- $var.size = (int)sizeof(recno_t);
- }
-T_dbtdatum
- ckFilter($arg, filter_store_value, \"filter_store_value\");
- DBT_clear($var) ;
- if (SvOK($arg)) {
- $var.data = SvPV($arg, PL_na);
- $var.size = (int)PL_na;
- }
-
-OUTPUT
-
-T_dbtkeydatum
- OutputKey($arg, $var)
-T_dbtdatum
- OutputValue($arg, $var)
-T_PTROBJ
- sv_setref_pv($arg, dbtype, (void*)$var);
diff --git a/bdb/perl.DB_File/version.c b/bdb/perl.DB_File/version.c
deleted file mode 100644
index 82b3e8b27b9..00000000000
--- a/bdb/perl.DB_File/version.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-
- version.c -- Perl 5 interface to Berkeley DB
-
- written by Paul Marquess <Paul.Marquess@btinternet.com>
- last modified 16th January 2000
- version 1.73
-
- All comments/suggestions/problems are welcome
-
- Copyright (c) 1995-2001 Paul Marquess. All rights reserved.
- This program is free software; you can redistribute it and/or
- modify it under the same terms as Perl itself.
-
- Changes:
- 1.71 - Support for Berkeley DB version 3.
- Support for Berkeley DB 2/3's backward compatability mode.
- 1.72 - No change.
- 1.73 - Added support for threading
- 1.74 - Added Perl core patch 7801.
-
-
-*/
-
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-#include <db.h>
-
-void
-#ifdef CAN_PROTOTYPE
-__getBerkeleyDBInfo(void)
-#else
-__getBerkeleyDBInfo()
-#endif
-{
-#ifdef dTHX
- dTHX;
-#endif
- SV * version_sv = perl_get_sv("DB_File::db_version", GV_ADD|GV_ADDMULTI) ;
- SV * ver_sv = perl_get_sv("DB_File::db_ver", GV_ADD|GV_ADDMULTI) ;
- SV * compat_sv = perl_get_sv("DB_File::db_185_compat", GV_ADD|GV_ADDMULTI) ;
-
-#ifdef DB_VERSION_MAJOR
- int Major, Minor, Patch ;
-
- (void)db_version(&Major, &Minor, &Patch) ;
-
- /* Check that the versions of db.h and libdb.a are the same */
- if (Major != DB_VERSION_MAJOR || Minor != DB_VERSION_MINOR
- || Patch != DB_VERSION_PATCH)
- croak("\nDB_File needs compatible versions of libdb & db.h\n\tyou have db.h version %d.%d.%d and libdb version %d.%d.%d\n",
- DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
- Major, Minor, Patch) ;
-
- /* check that libdb is recent enough -- we need 2.3.4 or greater */
- if (Major == 2 && (Minor < 3 || (Minor == 3 && Patch < 4)))
- croak("DB_File needs Berkeley DB 2.3.4 or greater, you have %d.%d.%d\n",
- Major, Minor, Patch) ;
-
- {
- char buffer[40] ;
- sprintf(buffer, "%d.%d", Major, Minor) ;
- sv_setpv(version_sv, buffer) ;
- sprintf(buffer, "%d.%03d%03d", Major, Minor, Patch) ;
- sv_setpv(ver_sv, buffer) ;
- }
-
-#else /* ! DB_VERSION_MAJOR */
- sv_setiv(version_sv, 1) ;
- sv_setiv(ver_sv, 1) ;
-#endif /* ! DB_VERSION_MAJOR */
-
-#ifdef COMPAT185
- sv_setiv(compat_sv, 1) ;
-#else /* ! COMPAT185 */
- sv_setiv(compat_sv, 0) ;
-#endif /* ! COMPAT185 */
-
-}
diff --git a/bdb/perl/BerkeleyDB/BerkeleyDB.pm b/bdb/perl/BerkeleyDB/BerkeleyDB.pm
new file mode 100644
index 00000000000..c56390ba71f
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/BerkeleyDB.pm
@@ -0,0 +1,1506 @@
+
+package BerkeleyDB;
+
+
+# Copyright (c) 1997-2002 Paul Marquess. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+
+# The documentation for this module is at the bottom of this file,
+# after the line __END__.
+
+BEGIN { require 5.004_04 }
+
+use strict;
+use Carp;
+use vars qw($VERSION @ISA @EXPORT $AUTOLOAD
+ $use_XSLoader);
+
+$VERSION = '0.20';
+
+require Exporter;
+#require DynaLoader;
+require AutoLoader;
+
+BEGIN {
+ $use_XSLoader = 1 ;
+ { local $SIG{__DIE__} ; eval { require XSLoader } ; }
+
+ if ($@) {
+ $use_XSLoader = 0 ;
+ require DynaLoader;
+ @ISA = qw(DynaLoader);
+ }
+}
+
+@ISA = qw(Exporter DynaLoader);
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+
+# NOTE -- Do not add to @EXPORT directly. It is written by mkconsts
+@EXPORT = qw(
+ DB_AFTER
+ DB_AGGRESSIVE
+ DB_ALREADY_ABORTED
+ DB_APPEND
+ DB_APPLY_LOGREG
+ DB_APP_INIT
+ DB_ARCH_ABS
+ DB_ARCH_DATA
+ DB_ARCH_LOG
+ DB_AUTO_COMMIT
+ DB_BEFORE
+ DB_BROADCAST_EID
+ DB_BTREE
+ DB_BTREEMAGIC
+ DB_BTREEOLDVER
+ DB_BTREEVERSION
+ DB_CACHED_COUNTS
+ DB_CDB_ALLDB
+ DB_CHECKPOINT
+ DB_CHKSUM_SHA1
+ DB_CLIENT
+ DB_CL_WRITER
+ DB_COMMIT
+ DB_CONSUME
+ DB_CONSUME_WAIT
+ DB_CREATE
+ DB_CURLSN
+ DB_CURRENT
+ DB_CXX_NO_EXCEPTIONS
+ DB_DELETED
+ DB_DELIMITER
+ DB_DIRECT
+ DB_DIRECT_DB
+ DB_DIRECT_LOG
+ DB_DIRTY_READ
+ DB_DONOTINDEX
+ DB_DUP
+ DB_DUPCURSOR
+ DB_DUPSORT
+ DB_EID_BROADCAST
+ DB_EID_INVALID
+ DB_ENCRYPT
+ DB_ENCRYPT_AES
+ DB_ENV_APPINIT
+ DB_ENV_AUTO_COMMIT
+ DB_ENV_CDB
+ DB_ENV_CDB_ALLDB
+ DB_ENV_CREATE
+ DB_ENV_DBLOCAL
+ DB_ENV_DIRECT_DB
+ DB_ENV_DIRECT_LOG
+ DB_ENV_FATAL
+ DB_ENV_LOCKDOWN
+ DB_ENV_LOCKING
+ DB_ENV_LOGGING
+ DB_ENV_NOLOCKING
+ DB_ENV_NOMMAP
+ DB_ENV_NOPANIC
+ DB_ENV_OPEN_CALLED
+ DB_ENV_OVERWRITE
+ DB_ENV_PANIC_OK
+ DB_ENV_PRIVATE
+ DB_ENV_REGION_INIT
+ DB_ENV_REP_CLIENT
+ DB_ENV_REP_LOGSONLY
+ DB_ENV_REP_MASTER
+ DB_ENV_RPCCLIENT
+ DB_ENV_RPCCLIENT_GIVEN
+ DB_ENV_STANDALONE
+ DB_ENV_SYSTEM_MEM
+ DB_ENV_THREAD
+ DB_ENV_TXN
+ DB_ENV_TXN_NOSYNC
+ DB_ENV_TXN_WRITE_NOSYNC
+ DB_ENV_USER_ALLOC
+ DB_ENV_YIELDCPU
+ DB_EXCL
+ DB_EXTENT
+ DB_FAST_STAT
+ DB_FCNTL_LOCKING
+ DB_FILE_ID_LEN
+ DB_FIRST
+ DB_FIXEDLEN
+ DB_FLUSH
+ DB_FORCE
+ DB_GETREC
+ DB_GET_BOTH
+ DB_GET_BOTHC
+ DB_GET_BOTH_RANGE
+ DB_GET_RECNO
+ DB_HANDLE_LOCK
+ DB_HASH
+ DB_HASHMAGIC
+ DB_HASHOLDVER
+ DB_HASHVERSION
+ DB_INCOMPLETE
+ DB_INIT_CDB
+ DB_INIT_LOCK
+ DB_INIT_LOG
+ DB_INIT_MPOOL
+ DB_INIT_TXN
+ DB_INVALID_EID
+ DB_JAVA_CALLBACK
+ DB_JOINENV
+ DB_JOIN_ITEM
+ DB_JOIN_NOSORT
+ DB_KEYEMPTY
+ DB_KEYEXIST
+ DB_KEYFIRST
+ DB_KEYLAST
+ DB_LAST
+ DB_LOCKDOWN
+ DB_LOCKMAGIC
+ DB_LOCKVERSION
+ DB_LOCK_CONFLICT
+ DB_LOCK_DEADLOCK
+ DB_LOCK_DEFAULT
+ DB_LOCK_DUMP
+ DB_LOCK_EXPIRE
+ DB_LOCK_FREE_LOCKER
+ DB_LOCK_GET
+ DB_LOCK_GET_TIMEOUT
+ DB_LOCK_INHERIT
+ DB_LOCK_MAXLOCKS
+ DB_LOCK_MINLOCKS
+ DB_LOCK_MINWRITE
+ DB_LOCK_NORUN
+ DB_LOCK_NOTEXIST
+ DB_LOCK_NOTGRANTED
+ DB_LOCK_NOTHELD
+ DB_LOCK_NOWAIT
+ DB_LOCK_OLDEST
+ DB_LOCK_PUT
+ DB_LOCK_PUT_ALL
+ DB_LOCK_PUT_OBJ
+ DB_LOCK_PUT_READ
+ DB_LOCK_RANDOM
+ DB_LOCK_RECORD
+ DB_LOCK_REMOVE
+ DB_LOCK_RIW_N
+ DB_LOCK_RW_N
+ DB_LOCK_SET_TIMEOUT
+ DB_LOCK_SWITCH
+ DB_LOCK_TIMEOUT
+ DB_LOCK_TRADE
+ DB_LOCK_UPGRADE
+ DB_LOCK_UPGRADE_WRITE
+ DB_LOCK_YOUNGEST
+ DB_LOGC_BUF_SIZE
+ DB_LOGFILEID_INVALID
+ DB_LOGMAGIC
+ DB_LOGOLDVER
+ DB_LOGVERSION
+ DB_LOG_DISK
+ DB_LOG_LOCKED
+ DB_LOG_SILENT_ERR
+ DB_MAX_PAGES
+ DB_MAX_RECORDS
+ DB_MPOOL_CLEAN
+ DB_MPOOL_CREATE
+ DB_MPOOL_DIRTY
+ DB_MPOOL_DISCARD
+ DB_MPOOL_EXTENT
+ DB_MPOOL_LAST
+ DB_MPOOL_NEW
+ DB_MPOOL_NEW_GROUP
+ DB_MPOOL_PRIVATE
+ DB_MULTIPLE
+ DB_MULTIPLE_KEY
+ DB_MUTEXDEBUG
+ DB_MUTEXLOCKS
+ DB_NEEDSPLIT
+ DB_NEXT
+ DB_NEXT_DUP
+ DB_NEXT_NODUP
+ DB_NOCOPY
+ DB_NODUPDATA
+ DB_NOLOCKING
+ DB_NOMMAP
+ DB_NOORDERCHK
+ DB_NOOVERWRITE
+ DB_NOPANIC
+ DB_NORECURSE
+ DB_NOSERVER
+ DB_NOSERVER_HOME
+ DB_NOSERVER_ID
+ DB_NOSYNC
+ DB_NOTFOUND
+ DB_ODDFILESIZE
+ DB_OK_BTREE
+ DB_OK_HASH
+ DB_OK_QUEUE
+ DB_OK_RECNO
+ DB_OLD_VERSION
+ DB_OPEN_CALLED
+ DB_OPFLAGS_MASK
+ DB_ORDERCHKONLY
+ DB_OVERWRITE
+ DB_PAD
+ DB_PAGEYIELD
+ DB_PAGE_LOCK
+ DB_PAGE_NOTFOUND
+ DB_PANIC_ENVIRONMENT
+ DB_PERMANENT
+ DB_POSITION
+ DB_POSITIONI
+ DB_PREV
+ DB_PREV_NODUP
+ DB_PRINTABLE
+ DB_PRIORITY_DEFAULT
+ DB_PRIORITY_HIGH
+ DB_PRIORITY_LOW
+ DB_PRIORITY_VERY_HIGH
+ DB_PRIORITY_VERY_LOW
+ DB_PRIVATE
+ DB_PR_HEADERS
+ DB_PR_PAGE
+ DB_PR_RECOVERYTEST
+ DB_QAMMAGIC
+ DB_QAMOLDVER
+ DB_QAMVERSION
+ DB_QUEUE
+ DB_RDONLY
+ DB_RDWRMASTER
+ DB_RECNO
+ DB_RECNUM
+ DB_RECORDCOUNT
+ DB_RECORD_LOCK
+ DB_RECOVER
+ DB_RECOVER_FATAL
+ DB_REGION_ANON
+ DB_REGION_INIT
+ DB_REGION_MAGIC
+ DB_REGION_NAME
+ DB_REGISTERED
+ DB_RENAMEMAGIC
+ DB_RENUMBER
+ DB_REP_CLIENT
+ DB_REP_DUPMASTER
+ DB_REP_HOLDELECTION
+ DB_REP_LOGSONLY
+ DB_REP_MASTER
+ DB_REP_NEWMASTER
+ DB_REP_NEWSITE
+ DB_REP_OUTDATED
+ DB_REP_PERMANENT
+ DB_REP_UNAVAIL
+ DB_REVSPLITOFF
+ DB_RMW
+ DB_RPC_SERVERPROG
+ DB_RPC_SERVERVERS
+ DB_RUNRECOVERY
+ DB_SALVAGE
+ DB_SECONDARY_BAD
+ DB_SEQUENTIAL
+ DB_SET
+ DB_SET_LOCK_TIMEOUT
+ DB_SET_RANGE
+ DB_SET_RECNO
+ DB_SET_TXN_NOW
+ DB_SET_TXN_TIMEOUT
+ DB_SNAPSHOT
+ DB_STAT_CLEAR
+ DB_SURPRISE_KID
+ DB_SWAPBYTES
+ DB_SYSTEM_MEM
+ DB_TEMPORARY
+ DB_TEST_ELECTINIT
+ DB_TEST_ELECTSEND
+ DB_TEST_ELECTVOTE1
+ DB_TEST_ELECTVOTE2
+ DB_TEST_ELECTWAIT1
+ DB_TEST_ELECTWAIT2
+ DB_TEST_POSTDESTROY
+ DB_TEST_POSTEXTDELETE
+ DB_TEST_POSTEXTOPEN
+ DB_TEST_POSTEXTUNLINK
+ DB_TEST_POSTLOG
+ DB_TEST_POSTLOGMETA
+ DB_TEST_POSTOPEN
+ DB_TEST_POSTRENAME
+ DB_TEST_POSTSYNC
+ DB_TEST_PREDESTROY
+ DB_TEST_PREEXTDELETE
+ DB_TEST_PREEXTOPEN
+ DB_TEST_PREEXTUNLINK
+ DB_TEST_PREOPEN
+ DB_TEST_PRERENAME
+ DB_TEST_SUBDB_LOCKS
+ DB_THREAD
+ DB_TIMEOUT
+ DB_TRUNCATE
+ DB_TXNMAGIC
+ DB_TXNVERSION
+ DB_TXN_ABORT
+ DB_TXN_APPLY
+ DB_TXN_BACKWARD_ALLOC
+ DB_TXN_BACKWARD_ROLL
+ DB_TXN_CKP
+ DB_TXN_FORWARD_ROLL
+ DB_TXN_GETPGNOS
+ DB_TXN_LOCK
+ DB_TXN_LOCK_2PL
+ DB_TXN_LOCK_MASK
+ DB_TXN_LOCK_OPTIMIST
+ DB_TXN_LOCK_OPTIMISTIC
+ DB_TXN_LOG_MASK
+ DB_TXN_LOG_REDO
+ DB_TXN_LOG_UNDO
+ DB_TXN_LOG_UNDOREDO
+ DB_TXN_NOSYNC
+ DB_TXN_NOWAIT
+ DB_TXN_OPENFILES
+ DB_TXN_POPENFILES
+ DB_TXN_PRINT
+ DB_TXN_REDO
+ DB_TXN_SYNC
+ DB_TXN_UNDO
+ DB_TXN_WRITE_NOSYNC
+ DB_UNKNOWN
+ DB_UNRESOLVED_CHILD
+ DB_UPDATE_SECONDARY
+ DB_UPGRADE
+ DB_USE_ENVIRON
+ DB_USE_ENVIRON_ROOT
+ DB_VERB_CHKPOINT
+ DB_VERB_DEADLOCK
+ DB_VERB_RECOVERY
+ DB_VERB_REPLICATION
+ DB_VERB_WAITSFOR
+ DB_VERIFY
+ DB_VERIFY_BAD
+ DB_VERIFY_FATAL
+ DB_VERSION_MAJOR
+ DB_VERSION_MINOR
+ DB_VERSION_PATCH
+ DB_VERSION_STRING
+ DB_VRFY_FLAGMASK
+ DB_WRITECURSOR
+ DB_WRITELOCK
+ DB_WRITEOPEN
+ DB_WRNOSYNC
+ DB_XA_CREATE
+ DB_XIDDATASIZE
+ DB_YIELDCPU
+ );
+
+sub AUTOLOAD {
+ my($constname);
+ ($constname = $AUTOLOAD) =~ s/.*:://;
+ my ($error, $val) = constant($constname);
+ Carp::croak $error if $error;
+ no strict 'refs';
+ *{$AUTOLOAD} = sub { $val };
+ goto &{$AUTOLOAD};
+}
+
+#bootstrap BerkeleyDB $VERSION;
+if ($use_XSLoader)
+ { XSLoader::load("BerkeleyDB", $VERSION)}
+else
+ { bootstrap BerkeleyDB $VERSION }
+
+# Preloaded methods go here.
+
+
+sub ParseParameters($@)
+{
+ my ($default, @rest) = @_ ;
+ my (%got) = %$default ;
+ my (@Bad) ;
+ my ($key, $value) ;
+ my $sub = (caller(1))[3] ;
+ my %options = () ;
+ local ($Carp::CarpLevel) = 1 ;
+
+ # allow the options to be passed as a hash reference or
+ # as the complete hash.
+ if (@rest == 1) {
+
+ croak "$sub: parameter is not a reference to a hash"
+ if ref $rest[0] ne "HASH" ;
+
+ %options = %{ $rest[0] } ;
+ }
+ elsif (@rest >= 2) {
+ %options = @rest ;
+ }
+
+ while (($key, $value) = each %options)
+ {
+ $key =~ s/^-// ;
+
+ if (exists $default->{$key})
+ { $got{$key} = $value }
+ else
+ { push (@Bad, $key) }
+ }
+
+ if (@Bad) {
+ my ($bad) = join(", ", @Bad) ;
+ croak "unknown key value(s) @Bad" ;
+ }
+
+ return \%got ;
+}
+
+use UNIVERSAL qw( isa ) ;
+
+sub env_remove
+{
+ # Usage:
+ #
+ # $env = new BerkeleyDB::Env
+ # [ -Home => $path, ]
+ # [ -Config => { name => value, name => value }
+ # [ -Flags => DB_INIT_LOCK| ]
+ # ;
+
+ my $got = BerkeleyDB::ParseParameters({
+ Home => undef,
+ Flags => 0,
+ Config => undef,
+ }, @_) ;
+
+ if (defined $got->{Config}) {
+ croak("Config parameter must be a hash reference")
+ if ! ref $got->{Config} eq 'HASH' ;
+
+ @BerkeleyDB::a = () ;
+ my $k = "" ; my $v = "" ;
+ while (($k, $v) = each %{$got->{Config}}) {
+ push @BerkeleyDB::a, "$k\t$v" ;
+ }
+
+ $got->{"Config"} = pack("p*", @BerkeleyDB::a, undef)
+ if @BerkeleyDB::a ;
+ }
+
+ return _env_remove($got) ;
+}
+
+sub db_remove
+{
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ Filename => undef,
+ Subname => undef,
+ Flags => 0,
+ Env => undef,
+ }, @_) ;
+
+ croak("Must specify a filename")
+ if ! defined $got->{Filename} ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ return _db_remove($got);
+}
+
+sub db_rename
+{
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ Filename => undef,
+ Subname => undef,
+ Newname => undef,
+ Flags => 0,
+ Env => undef,
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Must specify a filename")
+ if ! defined $got->{Filename} ;
+
+ croak("Must specify a Subname")
+ if ! defined $got->{Subname} ;
+
+ croak("Must specify a Newname")
+ if ! defined $got->{Newname} ;
+
+ return _db_rename($got);
+}
+
+sub db_verify
+{
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ Filename => undef,
+ Subname => undef,
+ Outfile => undef,
+ Flags => 0,
+ Env => undef,
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Must specify a filename")
+ if ! defined $got->{Filename} ;
+
+ return _db_verify($got);
+}
+
+package BerkeleyDB::Env ;
+
+use UNIVERSAL qw( isa ) ;
+use Carp ;
+use vars qw( %valid_config_keys ) ;
+
+sub isaFilehandle
+{
+ my $fh = shift ;
+
+ return ((isa($fh,'GLOB') or isa(\$fh,'GLOB')) and defined fileno($fh) )
+
+}
+
+%valid_config_keys = map { $_, 1 } qw( DB_DATA_DIR DB_LOG_DIR DB_TEMP_DIR
+DB_TMP_DIR ) ;
+
+sub new
+{
+ # Usage:
+ #
+ # $env = new BerkeleyDB::Env
+ # [ -Home => $path, ]
+ # [ -Mode => mode, ]
+ # [ -Config => { name => value, name => value }
+ # [ -ErrFile => filename, ]
+ # [ -ErrPrefix => "string", ]
+ # [ -Flags => DB_INIT_LOCK| ]
+ # [ -Set_Flags => $flags,]
+ # [ -Cachesize => number ]
+ # [ -LockDetect => ]
+ # [ -Verbose => boolean ]
+ # ;
+
+ my $pkg = shift ;
+ my $got = BerkeleyDB::ParseParameters({
+ Home => undef,
+ Server => undef,
+ Mode => 0666,
+ ErrFile => undef,
+ ErrPrefix => undef,
+ Flags => 0,
+ SetFlags => 0,
+ Cachesize => 0,
+ LockDetect => 0,
+ Verbose => 0,
+ Config => undef,
+ }, @_) ;
+
+ if (defined $got->{ErrFile}) {
+ croak("ErrFile parameter must be a file name")
+ if ref $got->{ErrFile} ;
+ #if (!isaFilehandle($got->{ErrFile})) {
+ # my $handle = new IO::File ">$got->{ErrFile}"
+# or croak "Cannot open file $got->{ErrFile}: $!\n" ;
+# $got->{ErrFile} = $handle ;
+# }
+ }
+
+
+ my %config ;
+ if (defined $got->{Config}) {
+ croak("Config parameter must be a hash reference")
+ if ! ref $got->{Config} eq 'HASH' ;
+
+ %config = %{ $got->{Config} } ;
+ @BerkeleyDB::a = () ;
+ my $k = "" ; my $v = "" ;
+ while (($k, $v) = each %config) {
+ if ($BerkeleyDB::db_version >= 3.1 && ! $valid_config_keys{$k} ) {
+ $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ;
+ croak $BerkeleyDB::Error ;
+ }
+ push @BerkeleyDB::a, "$k\t$v" ;
+ }
+
+ $got->{"Config"} = pack("p*", @BerkeleyDB::a, undef)
+ if @BerkeleyDB::a ;
+ }
+
+ my ($addr) = _db_appinit($pkg, $got) ;
+ my $obj ;
+ $obj = bless [$addr] , $pkg if $addr ;
+ if ($obj && $BerkeleyDB::db_version >= 3.1 && keys %config) {
+ my ($k, $v);
+ while (($k, $v) = each %config) {
+ if ($k eq 'DB_DATA_DIR')
+ { $obj->set_data_dir($v) }
+ elsif ($k eq 'DB_LOG_DIR')
+ { $obj->set_lg_dir($v) }
+ elsif ($k eq 'DB_TEMP_DIR' || $k eq 'DB_TMP_DIR')
+ { $obj->set_tmp_dir($v) }
+ else {
+ $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ;
+ croak $BerkeleyDB::Error
+ }
+ }
+ }
+ return $obj ;
+}
+
+
+sub TxnMgr
+{
+ my $env = shift ;
+ my ($addr) = $env->_TxnMgr() ;
+ my $obj ;
+ $obj = bless [$addr, $env] , "BerkeleyDB::TxnMgr" if $addr ;
+ return $obj ;
+}
+
+sub txn_begin
+{
+ my $env = shift ;
+ my ($addr) = $env->_txn_begin(@_) ;
+ my $obj ;
+ $obj = bless [$addr, $env] , "BerkeleyDB::Txn" if $addr ;
+ return $obj ;
+}
+
+sub DESTROY
+{
+ my $self = shift ;
+ $self->_DESTROY() ;
+}
+
+package BerkeleyDB::Hash ;
+
+use vars qw(@ISA) ;
+@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
+use UNIVERSAL qw( isa ) ;
+use Carp ;
+
+sub new
+{
+ my $self = shift ;
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ # Generic Stuff
+ Filename => undef,
+ Subname => undef,
+ #Flags => BerkeleyDB::DB_CREATE(),
+ Flags => 0,
+ Property => 0,
+ Mode => 0666,
+ Cachesize => 0,
+ Lorder => 0,
+ Pagesize => 0,
+ Env => undef,
+ #Tie => undef,
+ Txn => undef,
+
+ # Hash specific
+ Ffactor => 0,
+ Nelem => 0,
+ Hash => undef,
+ DupCompare => undef,
+
+ # BerkeleyDB specific
+ ReadKey => undef,
+ WriteKey => undef,
+ ReadValue => undef,
+ WriteValue => undef,
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Txn not of type BerkeleyDB::Txn")
+ if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
+
+ croak("-Tie needs a reference to a hash")
+ if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
+
+ my ($addr) = _db_open_hash($self, $got);
+ my $obj ;
+ if ($addr) {
+ $obj = bless [$addr] , $self ;
+ push @{ $obj }, $got->{Env} if $got->{Env} ;
+ $obj->Txn($got->{Txn})
+ if $got->{Txn} ;
+ }
+ return $obj ;
+}
+
+*TIEHASH = \&new ;
+
+
+package BerkeleyDB::Btree ;
+
+use vars qw(@ISA) ;
+@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
+use UNIVERSAL qw( isa ) ;
+use Carp ;
+
+sub new
+{
+ my $self = shift ;
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ # Generic Stuff
+ Filename => undef,
+ Subname => undef,
+ #Flags => BerkeleyDB::DB_CREATE(),
+ Flags => 0,
+ Property => 0,
+ Mode => 0666,
+ Cachesize => 0,
+ Lorder => 0,
+ Pagesize => 0,
+ Env => undef,
+ #Tie => undef,
+ Txn => undef,
+
+ # Btree specific
+ Minkey => 0,
+ Compare => undef,
+ DupCompare => undef,
+ Prefix => undef,
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Txn not of type BerkeleyDB::Txn")
+ if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
+
+ croak("-Tie needs a reference to a hash")
+ if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
+
+ my ($addr) = _db_open_btree($self, $got);
+ my $obj ;
+ if ($addr) {
+ $obj = bless [$addr] , $self ;
+ push @{ $obj }, $got->{Env} if $got->{Env} ;
+ $obj->Txn($got->{Txn})
+ if $got->{Txn} ;
+ }
+ return $obj ;
+}
+
+*BerkeleyDB::Btree::TIEHASH = \&BerkeleyDB::Btree::new ;
+
+
+package BerkeleyDB::Recno ;
+
+use vars qw(@ISA) ;
+@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
+use UNIVERSAL qw( isa ) ;
+use Carp ;
+
+sub new
+{
+ my $self = shift ;
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ # Generic Stuff
+ Filename => undef,
+ Subname => undef,
+ #Flags => BerkeleyDB::DB_CREATE(),
+ Flags => 0,
+ Property => 0,
+ Mode => 0666,
+ Cachesize => 0,
+ Lorder => 0,
+ Pagesize => 0,
+ Env => undef,
+ #Tie => undef,
+ Txn => undef,
+
+ # Recno specific
+ Delim => undef,
+ Len => undef,
+ Pad => undef,
+ Source => undef,
+ ArrayBase => 1, # lowest index in array
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Txn not of type BerkeleyDB::Txn")
+ if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
+
+ croak("Tie needs a reference to an array")
+ if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
+
+ croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
+ if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
+
+
+ $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
+
+ my ($addr) = _db_open_recno($self, $got);
+ my $obj ;
+ if ($addr) {
+ $obj = bless [$addr] , $self ;
+ push @{ $obj }, $got->{Env} if $got->{Env} ;
+ $obj->Txn($got->{Txn})
+ if $got->{Txn} ;
+ }
+ return $obj ;
+}
+
+*BerkeleyDB::Recno::TIEARRAY = \&BerkeleyDB::Recno::new ;
+*BerkeleyDB::Recno::db_stat = \&BerkeleyDB::Btree::db_stat ;
+
+package BerkeleyDB::Queue ;
+
+use vars qw(@ISA) ;
+@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
+use UNIVERSAL qw( isa ) ;
+use Carp ;
+
+sub new
+{
+ my $self = shift ;
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ # Generic Stuff
+ Filename => undef,
+ Subname => undef,
+ #Flags => BerkeleyDB::DB_CREATE(),
+ Flags => 0,
+ Property => 0,
+ Mode => 0666,
+ Cachesize => 0,
+ Lorder => 0,
+ Pagesize => 0,
+ Env => undef,
+ #Tie => undef,
+ Txn => undef,
+
+ # Queue specific
+ Len => undef,
+ Pad => undef,
+ ArrayBase => 1, # lowest index in array
+ ExtentSize => undef,
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Txn not of type BerkeleyDB::Txn")
+ if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
+
+ croak("Tie needs a reference to an array")
+ if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
+
+ croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
+ if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
+
+ $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
+
+ my ($addr) = _db_open_queue($self, $got);
+ my $obj ;
+ if ($addr) {
+ $obj = bless [$addr] , $self ;
+ push @{ $obj }, $got->{Env} if $got->{Env} ;
+ $obj->Txn($got->{Txn})
+ if $got->{Txn} ;
+ }
+ return $obj ;
+}
+
+*BerkeleyDB::Queue::TIEARRAY = \&BerkeleyDB::Queue::new ;
+
+sub UNSHIFT
+{
+ my $self = shift;
+ croak "unshift is unsupported with Queue databases";
+}
+
+## package BerkeleyDB::Text ;
+##
+## use vars qw(@ISA) ;
+## @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
+## use UNIVERSAL qw( isa ) ;
+## use Carp ;
+##
+## sub new
+## {
+## my $self = shift ;
+## my $got = BerkeleyDB::ParseParameters(
+## {
+## # Generic Stuff
+## Filename => undef,
+## #Flags => BerkeleyDB::DB_CREATE(),
+## Flags => 0,
+## Property => 0,
+## Mode => 0666,
+## Cachesize => 0,
+## Lorder => 0,
+## Pagesize => 0,
+## Env => undef,
+## #Tie => undef,
+## Txn => undef,
+##
+## # Recno specific
+## Delim => undef,
+## Len => undef,
+## Pad => undef,
+## Btree => undef,
+## }, @_) ;
+##
+## croak("Env not of type BerkeleyDB::Env")
+## if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+##
+## croak("Txn not of type BerkeleyDB::Txn")
+## if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
+##
+## croak("-Tie needs a reference to an array")
+## if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
+##
+## # rearange for recno
+## $got->{Source} = $got->{Filename} if defined $got->{Filename} ;
+## delete $got->{Filename} ;
+## $got->{Fname} = $got->{Btree} if defined $got->{Btree} ;
+## return BerkeleyDB::Recno::_db_open_recno($self, $got);
+## }
+##
+## *BerkeleyDB::Text::TIEARRAY = \&BerkeleyDB::Text::new ;
+## *BerkeleyDB::Text::db_stat = \&BerkeleyDB::Btree::db_stat ;
+
+package BerkeleyDB::Unknown ;
+
+use vars qw(@ISA) ;
+@ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
+use UNIVERSAL qw( isa ) ;
+use Carp ;
+
+sub new
+{
+ my $self = shift ;
+ my $got = BerkeleyDB::ParseParameters(
+ {
+ # Generic Stuff
+ Filename => undef,
+ Subname => undef,
+ #Flags => BerkeleyDB::DB_CREATE(),
+ Flags => 0,
+ Property => 0,
+ Mode => 0666,
+ Cachesize => 0,
+ Lorder => 0,
+ Pagesize => 0,
+ Env => undef,
+ #Tie => undef,
+ Txn => undef,
+
+ }, @_) ;
+
+ croak("Env not of type BerkeleyDB::Env")
+ if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
+
+ croak("Txn not of type BerkeleyDB::Txn")
+ if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
+
+ croak("-Tie needs a reference to a hash")
+ if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
+
+ my ($addr, $type) = _db_open_unknown($got);
+ my $obj ;
+ if ($addr) {
+ $obj = bless [$addr], "BerkeleyDB::$type" ;
+ push @{ $obj }, $got->{Env} if $got->{Env} ;
+ $obj->Txn($got->{Txn})
+ if $got->{Txn} ;
+ }
+ return $obj ;
+}
+
+
+package BerkeleyDB::_tiedHash ;
+
+use Carp ;
+
+#sub TIEHASH
+#{
+# my $self = shift ;
+# my $db_object = shift ;
+#
+#print "Tiehash REF=[$self] [" . (ref $self) . "]\n" ;
+#
+# return bless { Obj => $db_object}, $self ;
+#}
+
+sub Tie
+{
+ # Usage:
+ #
+ # $db->Tie \%hash ;
+ #
+
+ my $self = shift ;
+
+ #print "Tie method REF=[$self] [" . (ref $self) . "]\n" ;
+
+ croak("usage \$x->Tie \\%hash\n") unless @_ ;
+ my $ref = shift ;
+
+ croak("Tie needs a reference to a hash")
+ if defined $ref and $ref !~ /HASH/ ;
+
+ #tie %{ $ref }, ref($self), $self ;
+ tie %{ $ref }, "BerkeleyDB::_tiedHash", $self ;
+ return undef ;
+}
+
+
+sub TIEHASH
+{
+ my $self = shift ;
+ my $db_object = shift ;
+ #return bless $db_object, 'BerkeleyDB::Common' ;
+ return $db_object ;
+}
+
+sub STORE
+{
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+
+ $self->db_put($key, $value) ;
+}
+
+sub FETCH
+{
+ my $self = shift ;
+ my $key = shift ;
+ my $value = undef ;
+ $self->db_get($key, $value) ;
+
+ return $value ;
+}
+
+sub EXISTS
+{
+ my $self = shift ;
+ my $key = shift ;
+ my $value = undef ;
+ $self->db_get($key, $value) == 0 ;
+}
+
+sub DELETE
+{
+ my $self = shift ;
+ my $key = shift ;
+ $self->db_del($key) ;
+}
+
+sub CLEAR
+{
+ my $self = shift ;
+ my ($key, $value) = (0, 0) ;
+ my $cursor = $self->db_cursor() ;
+ while ($cursor->c_get($key, $value, BerkeleyDB::DB_PREV()) == 0)
+ { $cursor->c_del() }
+ #1 while $cursor->c_del() == 0 ;
+ # cursor will self-destruct
+}
+
+#sub DESTROY
+#{
+# my $self = shift ;
+# print "BerkeleyDB::_tieHash::DESTROY\n" ;
+# $self->{Cursor}->c_close() if $self->{Cursor} ;
+#}
+
+package BerkeleyDB::_tiedArray ;
+
+use Carp ;
+
+sub Tie
+{
+ # Usage:
+ #
+ # $db->Tie \@array ;
+ #
+
+ my $self = shift ;
+
+ #print "Tie method REF=[$self] [" . (ref $self) . "]\n" ;
+
+ croak("usage \$x->Tie \\%hash\n") unless @_ ;
+ my $ref = shift ;
+
+ croak("Tie needs a reference to an array")
+ if defined $ref and $ref !~ /ARRAY/ ;
+
+ #tie %{ $ref }, ref($self), $self ;
+ tie @{ $ref }, "BerkeleyDB::_tiedArray", $self ;
+ return undef ;
+}
+
+
+#sub TIEARRAY
+#{
+# my $self = shift ;
+# my $db_object = shift ;
+#
+#print "Tiearray REF=[$self] [" . (ref $self) . "]\n" ;
+#
+# return bless { Obj => $db_object}, $self ;
+#}
+
+sub TIEARRAY
+{
+ my $self = shift ;
+ my $db_object = shift ;
+ #return bless $db_object, 'BerkeleyDB::Common' ;
+ return $db_object ;
+}
+
+sub STORE
+{
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+
+ $self->db_put($key, $value) ;
+}
+
+sub FETCH
+{
+ my $self = shift ;
+ my $key = shift ;
+ my $value = undef ;
+ $self->db_get($key, $value) ;
+
+ return $value ;
+}
+
+*CLEAR = \&BerkeleyDB::_tiedHash::CLEAR ;
+*FIRSTKEY = \&BerkeleyDB::_tiedHash::FIRSTKEY ;
+*NEXTKEY = \&BerkeleyDB::_tiedHash::NEXTKEY ;
+
+sub EXTEND {} # don't do anything with EXTEND
+
+
+sub SHIFT
+{
+ my $self = shift;
+ my ($key, $value) = (0, 0) ;
+ my $cursor = $self->db_cursor() ;
+ return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) != 0 ;
+ return undef if $cursor->c_del() != 0 ;
+
+ return $value ;
+}
+
+
+sub UNSHIFT
+{
+ my $self = shift;
+ if (@_)
+ {
+ my ($key, $value) = (0, 0) ;
+ my $cursor = $self->db_cursor() ;
+ my $status = $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) ;
+ if ($status == 0)
+ {
+ foreach $value (reverse @_)
+ {
+ $key = 0 ;
+ $cursor->c_put($key, $value, BerkeleyDB::DB_BEFORE()) ;
+ }
+ }
+ elsif ($status == BerkeleyDB::DB_NOTFOUND())
+ {
+ $key = 0 ;
+ foreach $value (@_)
+ {
+ $self->db_put($key++, $value) ;
+ }
+ }
+ }
+}
+
+sub PUSH
+{
+ my $self = shift;
+ if (@_)
+ {
+ my ($key, $value) = (-1, 0) ;
+ my $cursor = $self->db_cursor() ;
+ my $status = $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) ;
+ if ($status == 0 || $status == BerkeleyDB::DB_NOTFOUND())
+ {
+ $key = -1 if $status != 0 and $self->type != BerkeleyDB::DB_RECNO() ;
+ foreach $value (@_)
+ {
+ ++ $key ;
+ $status = $self->db_put($key, $value) ;
+ }
+ }
+
+# can use this when DB_APPEND is fixed.
+# foreach $value (@_)
+# {
+# my $status = $cursor->c_put($key, $value, BerkeleyDB::DB_AFTER()) ;
+#print "[$status]\n" ;
+# }
+ }
+}
+
+sub POP
+{
+ my $self = shift;
+ my ($key, $value) = (0, 0) ;
+ my $cursor = $self->db_cursor() ;
+ return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) != 0 ;
+ return undef if $cursor->c_del() != 0 ;
+
+ return $value ;
+}
+
+sub SPLICE
+{
+ my $self = shift;
+ croak "SPLICE is not implemented yet" ;
+}
+
+*shift = \&SHIFT ;
+*unshift = \&UNSHIFT ;
+*push = \&PUSH ;
+*pop = \&POP ;
+*clear = \&CLEAR ;
+*length = \&FETCHSIZE ;
+
+sub STORESIZE
+{
+ croak "STORESIZE is not implemented yet" ;
+#print "STORESIZE @_\n" ;
+# my $self = shift;
+# my $length = shift ;
+# my $current_length = $self->FETCHSIZE() ;
+#print "length is $current_length\n";
+#
+# if ($length < $current_length) {
+#print "Make smaller $length < $current_length\n" ;
+# my $key ;
+# for ($key = $current_length - 1 ; $key >= $length ; -- $key)
+# { $self->db_del($key) }
+# }
+# elsif ($length > $current_length) {
+#print "Make larger $length > $current_length\n" ;
+# $self->db_put($length-1, "") ;
+# }
+# else { print "stay the same\n" }
+
+}
+
+
+
+#sub DESTROY
+#{
+# my $self = shift ;
+# print "BerkeleyDB::_tieArray::DESTROY\n" ;
+#}
+
+
+package BerkeleyDB::Common ;
+
+
+use Carp ;
+
+sub DESTROY
+{
+ my $self = shift ;
+ $self->_DESTROY() ;
+}
+
+sub Txn
+{
+ my $self = shift ;
+ my $txn = shift ;
+ #print "BerkeleyDB::Common::Txn db [$self] txn [$txn]\n" ;
+ if ($txn) {
+ $self->_Txn($txn) ;
+ push @{ $txn }, $self ;
+ }
+ else {
+ $self->_Txn() ;
+ }
+ #print "end BerkeleyDB::Common::Txn \n";
+}
+
+
+sub get_dup
+{
+ croak "Usage: \$db->get_dup(key [,flag])\n"
+ unless @_ == 2 or @_ == 3 ;
+
+ my $db = shift ;
+ my $key = shift ;
+ my $flag = shift ;
+ my $value = 0 ;
+ my $origkey = $key ;
+ my $wantarray = wantarray ;
+ my %values = () ;
+ my @values = () ;
+ my $counter = 0 ;
+ my $status = 0 ;
+ my $cursor = $db->db_cursor() ;
+
+ # iterate through the database until either EOF ($status == 0)
+ # or a different key is encountered ($key ne $origkey).
+ for ($status = $cursor->c_get($key, $value, BerkeleyDB::DB_SET()) ;
+ $status == 0 and $key eq $origkey ;
+ $status = $cursor->c_get($key, $value, BerkeleyDB::DB_NEXT()) ) {
+ # save the value or count number of matches
+ if ($wantarray) {
+ if ($flag)
+ { ++ $values{$value} }
+ else
+ { push (@values, $value) }
+ }
+ else
+ { ++ $counter }
+
+ }
+
+ return ($wantarray ? ($flag ? %values : @values) : $counter) ;
+}
+
+sub db_cursor
+{
+ my $db = shift ;
+ my ($addr) = $db->_db_cursor(@_) ;
+ my $obj ;
+ $obj = bless [$addr, $db] , "BerkeleyDB::Cursor" if $addr ;
+ return $obj ;
+}
+
+sub db_join
+{
+ croak 'Usage: $db->BerkeleyDB::Common::db_join([cursors], flags=0)'
+ if @_ < 2 || @_ > 3 ;
+ my $db = shift ;
+ my ($addr) = $db->_db_join(@_) ;
+ my $obj ;
+ $obj = bless [$addr, $db, $_[0]] , "BerkeleyDB::Cursor" if $addr ;
+ return $obj ;
+}
+
+package BerkeleyDB::Cursor ;
+
+sub c_close
+{
+ my $cursor = shift ;
+ $cursor->[1] = "" ;
+ return $cursor->_c_close() ;
+}
+
+sub c_dup
+{
+ my $cursor = shift ;
+ my ($addr) = $cursor->_c_dup(@_) ;
+ my $obj ;
+ $obj = bless [$addr, $cursor->[1]] , "BerkeleyDB::Cursor" if $addr ;
+ return $obj ;
+}
+
+sub DESTROY
+{
+ my $self = shift ;
+ $self->_DESTROY() ;
+}
+
+package BerkeleyDB::TxnMgr ;
+
+sub DESTROY
+{
+ my $self = shift ;
+ $self->_DESTROY() ;
+}
+
+sub txn_begin
+{
+ my $txnmgr = shift ;
+ my ($addr) = $txnmgr->_txn_begin(@_) ;
+ my $obj ;
+ $obj = bless [$addr, $txnmgr] , "BerkeleyDB::Txn" if $addr ;
+ return $obj ;
+}
+
+package BerkeleyDB::Txn ;
+
+sub Txn
+{
+ my $self = shift ;
+ my $db ;
+ # keep a reference to each db in the txn object
+ foreach $db (@_) {
+ $db->_Txn($self) ;
+ push @{ $self}, $db ;
+ }
+}
+
+sub txn_commit
+{
+ my $self = shift ;
+ $self->disassociate() ;
+ my $status = $self->_txn_commit() ;
+ return $status ;
+}
+
+sub txn_abort
+{
+ my $self = shift ;
+ $self->disassociate() ;
+ my $status = $self->_txn_abort() ;
+ return $status ;
+}
+
+sub disassociate
+{
+ my $self = shift ;
+ my $db ;
+ while ( @{ $self } > 2) {
+ $db = pop @{ $self } ;
+ $db->Txn() ;
+ }
+ #print "end disassociate\n" ;
+}
+
+
+sub DESTROY
+{
+ my $self = shift ;
+
+ $self->disassociate() ;
+ # first close the close the transaction
+ $self->_DESTROY() ;
+}
+
+package BerkeleyDB::Term ;
+
+END
+{
+ close_everything() ;
+}
+
+
+package BerkeleyDB ;
+
+
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+1;
+__END__
+
+
diff --git a/bdb/perl/BerkeleyDB/BerkeleyDB.pod b/bdb/perl/BerkeleyDB/BerkeleyDB.pod
new file mode 100644
index 00000000000..60f30e2abfb
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/BerkeleyDB.pod
@@ -0,0 +1,1792 @@
+=head1 NAME
+
+BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
+
+=head1 SYNOPSIS
+
+ use BerkeleyDB;
+
+ $env = new BerkeleyDB::Env [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Hash', [OPTIONS] ;
+ $db = new BerkeleyDB::Hash [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
+ $db = new BerkeleyDB::Btree [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
+ $db = new BerkeleyDB::Recno [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
+ $db = new BerkeleyDB::Queue [OPTIONS] ;
+
+ $db = new BerkeleyDB::Unknown [OPTIONS] ;
+
+ $status = BerkeleyDB::db_remove [OPTIONS]
+ $status = BerkeleyDB::db_rename [OPTIONS]
+ $status = BerkeleyDB::db_verify [OPTIONS]
+
+ $hash{$key} = $value ;
+ $value = $hash{$key} ;
+ each %hash ;
+ keys %hash ;
+ values %hash ;
+
+ $status = $db->db_get()
+ $status = $db->db_put() ;
+ $status = $db->db_del() ;
+ $status = $db->db_sync() ;
+ $status = $db->db_close() ;
+ $status = $db->db_close() ;
+ $status = $db->db_pget()
+ $hash_ref = $db->db_stat() ;
+ $status = $db->db_key_range();
+ $type = $db->type() ;
+ $status = $db->status() ;
+ $boolean = $db->byteswapped() ;
+ $status = $db->truncate($count) ;
+
+ ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
+ ($flag, $old_offset, $old_length) = $db->partial_clear() ;
+
+ $cursor = $db->db_cursor([$flags]) ;
+ $newcursor = $cursor->c_dup([$flags]);
+ $status = $cursor->c_get() ;
+ $status = $cursor->c_put() ;
+ $status = $cursor->c_del() ;
+ $status = $cursor->c_count() ;
+ $status = $cursor->c_pget() ;
+ $status = $cursor->status() ;
+ $status = $cursor->c_close() ;
+
+ $cursor = $db->db_join() ;
+ $status = $cursor->c_get() ;
+ $status = $cursor->c_close() ;
+
+ $status = $env->txn_checkpoint()
+ $hash_ref = $env->txn_stat()
+ $status = $env->setmutexlocks()
+ $status = $env->set_flags()
+
+ $txn = $env->txn_begin() ;
+ $db->Txn($txn);
+ $txn->Txn($db1, $db2,...);
+ $status = $txn->txn_prepare()
+ $status = $txn->txn_commit()
+ $status = $txn->txn_abort()
+ $status = $txn->txn_id()
+ $status = $txn->txn_discard()
+
+ $status = $env->set_lg_dir();
+ $status = $env->set_lg_bsize();
+ $status = $env->set_lg_max();
+
+ $status = $env->set_data_dir() ;
+ $status = $env->set_tmp_dir() ;
+ $status = $env->set_verbose() ;
+
+ $BerkeleyDB::Error
+ $BerkeleyDB::db_version
+
+ # DBM Filters
+ $old_filter = $db->filter_store_key ( sub { ... } ) ;
+ $old_filter = $db->filter_store_value( sub { ... } ) ;
+ $old_filter = $db->filter_fetch_key ( sub { ... } ) ;
+ $old_filter = $db->filter_fetch_value( sub { ... } ) ;
+
+ # deprecated, but supported
+ $txn_mgr = $env->TxnMgr();
+ $status = $txn_mgr->txn_checkpoint()
+ $hash_ref = $txn_mgr->txn_stat()
+ $txn = $txn_mgr->txn_begin() ;
+
+=head1 DESCRIPTION
+
+B<NOTE: This document is still under construction. Expect it to be
+incomplete in places.>
+
+This Perl module provides an interface to most of the functionality
+available in Berkeley DB versions 2, 3 and 4. In general it is safe to assume
+that the interface provided here to be identical to the Berkeley DB
+interface. The main changes have been to make the Berkeley DB API work
+in a Perl way. Note that if you are using Berkeley DB 2.x, the new
+features available in Berkeley DB 3.x or DB 4.x are not available via
+this module.
+
+The reader is expected to be familiar with the Berkeley DB
+documentation. Where the interface provided here is identical to the
+Berkeley DB library and the... TODO
+
+The B<db_appinit>, B<db_cursor>, B<db_open> and B<db_txn> man pages are
+particularly relevant.
+
+The interface to Berkeley DB is implemented with a number of Perl
+classes.
+
+=head1 ENV CLASS
+
+The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB
+function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and
+B<DBENV-E<gt>open> in Berkeley DB 3.x/4.x. Its purpose is to initialise a
+number of sub-systems that can then be used in a consistent way in all
+the databases you make use of the environment.
+
+If you don't intend using transactions, locking or logging, then you
+shouldn't need to make use of B<BerkeleyDB::Env>.
+
+=head2 Synopsis
+
+ $env = new BerkeleyDB::Env
+ [ -Home => $path, ]
+ [ -Server => $name, ]
+ [ -CacheSize => $number, ]
+ [ -Config => { name => value, name => value }, ]
+ [ -ErrFile => filename, ]
+ [ -ErrPrefix => "string", ]
+ [ -Flags => number, ]
+ [ -SetFlags => bitmask, ]
+ [ -LockDetect => number, ]
+ [ -Verbose => boolean, ]
+
+=over 5
+
+All the parameters to the BerkeleyDB::Env constructor are optional.
+
+=item -Home
+
+If present, this parameter should point to an existing directory. Any
+files that I<aren't> specified with an absolute path in the sub-systems
+that are initialised by the BerkeleyDB::Env class will be assumed to
+live in the B<Home> directory.
+
+For example, in the code fragment below the database "fred.db" will be
+opened in the directory "/home/databases" because it was specified as a
+relative path, but "joe.db" will be opened in "/other" because it was
+part of an absolute path.
+
+ $env = new BerkeleyDB::Env
+ -Home => "/home/databases"
+ ...
+
+ $db1 = new BerkeleyDB::Hash
+ -Filename = "fred.db",
+ -Env => $env
+ ...
+
+ $db2 = new BerkeleyDB::Hash
+ -Filename = "/other/joe.db",
+ -Env => $env
+ ...
+
+=item -Server
+
+If present, this parameter should be the hostname of a server that is running
+the Berkeley DB RPC server. All databases will be accessed via the RPC server.
+
+=item -Cachesize
+
+If present, this parameter sets the size of the environments shared memory
+buffer pool.
+
+=item -Config
+
+This is a variation on the C<-Home> parameter, but it allows finer
+control of where specific types of files will be stored.
+
+The parameter expects a reference to a hash. Valid keys are:
+B<DB_DATA_DIR>, B<DB_LOG_DIR> and B<DB_TMP_DIR>
+
+The code below shows an example of how it can be used.
+
+ $env = new BerkeleyDB::Env
+ -Config => { DB_DATA_DIR => "/home/databases",
+ DB_LOG_DIR => "/home/logs",
+ DB_TMP_DIR => "/home/tmp"
+ }
+ ...
+
+=item -ErrFile
+
+Expects a filenme. Any errors generated internally by Berkeley DB will
+be logged to this file.
+
+=item -ErrPrefix
+
+Allows a prefix to be added to the error messages before they are sent
+to B<-ErrFile>.
+
+=item -Flags
+
+The B<Flags> parameter specifies both which sub-systems to initialise,
+as well as a number of environment-wide options.
+See the Berkeley DB documentation for more details of these options.
+
+Any of the following can be specified by OR'ing them:
+
+B<DB_CREATE>
+
+If any of the files specified do not already exist, create them.
+
+B<DB_INIT_CDB>
+
+Initialise the Concurrent Access Methods
+
+B<DB_INIT_LOCK>
+
+Initialise the Locking sub-system.
+
+B<DB_INIT_LOG>
+
+Initialise the Logging sub-system.
+
+B<DB_INIT_MPOOL>
+
+Initialise the ...
+
+B<DB_INIT_TXN>
+
+Initialise the ...
+
+B<DB_MPOOL_PRIVATE>
+
+Initialise the ...
+
+B<DB_INIT_MPOOL> is also specified.
+
+Initialise the ...
+
+B<DB_NOMMAP>
+
+Initialise the ...
+
+B<DB_RECOVER>
+
+
+
+B<DB_RECOVER_FATAL>
+
+B<DB_THREAD>
+
+B<DB_TXN_NOSYNC>
+
+B<DB_USE_ENVIRON>
+
+B<DB_USE_ENVIRON_ROOT>
+
+=item -SetFlags
+
+Calls ENV->set_flags with the supplied bitmask. Use this when you need to make
+use of DB_ENV->set_flags before DB_ENV->open is called.
+
+Only valid when Berkeley DB 3.x or better is used.
+
+=item -LockDetect
+
+Specifies what to do when a lock conflict occurs. The value should be one of
+
+B<DB_LOCK_DEFAULT>
+
+B<DB_LOCK_OLDEST>
+
+B<DB_LOCK_RANDOM>
+
+B<DB_LOCK_YOUNGEST>
+
+=item -Verbose
+
+Add extra debugging information to the messages sent to B<-ErrFile>.
+
+=back
+
+=head2 Methods
+
+The environment class has the following methods:
+
+=over 5
+
+=item $env->errPrefix("string") ;
+
+This method is identical to the B<-ErrPrefix> flag. It allows the
+error prefix string to be changed dynamically.
+
+=item $env->set_flags(bitmask, 1|0);
+
+=item $txn = $env->TxnMgr()
+
+Constructor for creating a B<TxnMgr> object.
+See L<"TRANSACTIONS"> for more details of using transactions.
+
+This method is deprecated. Access the transaction methods using the B<txn_>
+methods below from the environment object directly.
+
+=item $env->txn_begin()
+
+TODO
+
+=item $env->txn_stat()
+
+TODO
+
+=item $env->txn_checkpoint()
+
+TODO
+
+=item $env->status()
+
+Returns the status of the last BerkeleyDB::Env method.
+
+=item $env->setmutexlocks()
+
+Only available in Berkeley Db 3.0 or greater. Calls
+B<db_env_set_mutexlocks> when used with Berkeley DB 3.1.x. When used with
+Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>.
+
+=back
+
+=head2 Examples
+
+TODO.
+
+=head1 Global Classes
+
+ $status = BerkeleyDB::db_remove [OPTIONS]
+ $status = BerkeleyDB::db_rename [OPTIONS]
+ $status = BerkeleyDB::db_verify [OPTIONS]
+
+=head1 THE DATABASE CLASSES
+
+B<BerkeleyDB> supports the following database formats:
+
+=over 5
+
+=item B<BerkeleyDB::Hash>
+
+This database type allows arbitrary key/value pairs to be stored in data
+files. This is equivalent to the functionality provided by other
+hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
+the files created using B<BerkeleyDB::Hash> are not compatible with any
+of the other packages mentioned.
+
+A default hashing algorithm, which will be adequate for most applications,
+is built into BerkeleyDB. If you do need to use your own hashing algorithm
+it is possible to write your own in Perl and have B<BerkeleyDB> use
+it instead.
+
+=item B<BerkeleyDB::Btree>
+
+The Btree format allows arbitrary key/value pairs to be stored in a
+B+tree.
+
+As with the B<BerkeleyDB::Hash> format, it is possible to provide a
+user defined Perl routine to perform the comparison of keys. By default,
+though, the keys are stored in lexical order.
+
+=item B<BerkeleyDB::Recno>
+
+TODO.
+
+
+=item B<BerkeleyDB::Queue>
+
+TODO.
+
+=item B<BerkeleyDB::Unknown>
+
+This isn't a database format at all. It is used when you want to open an
+existing Berkeley DB database without having to know what type is it.
+
+=back
+
+
+Each of the database formats described above is accessed via a
+corresponding B<BerkeleyDB> class. These will be described in turn in
+the next sections.
+
+=head1 BerkeleyDB::Hash
+
+Equivalent to calling B<db_open> with type B<DB_HASH> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_HASH> in
+Berkeley DB 3.x or greater.
+
+Two forms of constructor are supported:
+
+ $db = new BerkeleyDB::Hash
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Hash specific
+ [ -Ffactor => number,]
+ [ -Nelem => number,]
+ [ -Hash => code reference,]
+ [ -DupCompare => code reference,]
+
+and this
+
+ [$db =] tie %hash, 'BerkeleyDB::Hash',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Hash specific
+ [ -Ffactor => number,]
+ [ -Nelem => number,]
+ [ -Hash => code reference,]
+ [ -DupCompare => code reference,]
+
+
+When the "tie" interface is used, reading from and writing to the database
+is achieved via the tied hash. In this case the database operates like
+a Perl associative array that happens to be stored on disk.
+
+In addition to the high-level tied hash interface, it is possible to
+make use of the underlying methods provided by Berkeley DB
+
+=head2 Options
+
+In addition to the standard set of options (see L<COMMON OPTIONS>)
+B<BerkeleyDB::Hash> supports these options:
+
+=over 5
+
+=item -Property
+
+Used to specify extra flags when opening a database. The following
+flags may be specified by logically OR'ing together one or more of the
+following values:
+
+B<DB_DUP>
+
+When creating a new database, this flag enables the storing of duplicate
+keys in the database. If B<DB_DUPSORT> is not specified as well, the
+duplicates are stored in the order they are created in the database.
+
+B<DB_DUPSORT>
+
+Enables the sorting of duplicate keys in the database. Ignored if
+B<DB_DUP> isn't also specified.
+
+=item -Ffactor
+
+=item -Nelem
+
+See the Berkeley DB documentation for details of these options.
+
+=item -Hash
+
+Allows you to provide a user defined hash function. If not specified,
+a default hash function is used. Here is a template for a user-defined
+hash function
+
+ sub hash
+ {
+ my ($data) = shift ;
+ ...
+ # return the hash value for $data
+ return $hash ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Hash => \&hash,
+ ...
+
+See L<""> for an example.
+
+=item -DupCompare
+
+Used in conjunction with the B<DB_DUPOSRT> flag.
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Property => DB_DUP|DB_DUPSORT,
+ -DupCompare => \&compare,
+ ...
+
+=back
+
+
+=head2 Methods
+
+B<BerkeleyDB::Hash> only supports the standard database methods.
+See L<COMMON DATABASE METHODS>.
+
+=head2 A Simple Tied Hash Example
+
+ use strict ;
+ use BerkeleyDB ;
+ use vars qw( %h $k $v ) ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $h{"apple"} = "red" ;
+ $h{"orange"} = "orange" ;
+ $h{"banana"} = "yellow" ;
+ $h{"tomato"} = "red" ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $h{"banana"} ;
+
+ # Delete a key/value pair.
+ delete $h{"apple"} ;
+
+ # print the contents of the file
+ while (($k, $v) = each %h)
+ { print "$k -> $v\n" }
+
+ untie %h ;
+
+here is the output:
+
+ Banana Exists
+
+ orange -> orange
+ tomato -> red
+ banana -> yellow
+
+Note that the like ordinary associative arrays, the order of the keys
+retrieved from a Hash database are in an apparently random order.
+
+=head2 Another Simple Hash Example
+
+Do the same as the previous example but not using tie.
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("apple", "red") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("banana", "yellow") ;
+ $db->db_put("tomato", "red") ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;
+
+ # Delete a key/value pair.
+ $db->db_del("apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+
+=head2 Duplicate keys
+
+The code below is a variation on the examples above. This time the hash has
+been inverted. The key this time is colour and the value is the fruit name.
+The B<DB_DUP> flag has been specified to allow duplicates.
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_DUP
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("red", "apple") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("green", "banana") ;
+ $db->db_put("yellow", "banana") ;
+ $db->db_put("red", "tomato") ;
+ $db->db_put("green", "apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+
+here is the output:
+
+ orange -> orange
+ yellow -> banana
+ red -> apple
+ red -> tomato
+ green -> banana
+ green -> apple
+
+=head2 Sorting Duplicate Keys
+
+In the previous example, when there were duplicate keys, the values are
+sorted in the order they are stored in. The code below is
+identical to the previous example except the B<DB_DUPSORT> flag is
+specified.
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_DUP | DB_DUPSORT
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("red", "apple") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("green", "banana") ;
+ $db->db_put("yellow", "banana") ;
+ $db->db_put("red", "tomato") ;
+ $db->db_put("green", "apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+
+Notice that in the output below the duplicate values are sorted.
+
+ orange -> orange
+ yellow -> banana
+ red -> apple
+ red -> tomato
+ green -> apple
+ green -> banana
+
+=head2 Custom Sorting Duplicate Keys
+
+Another variation
+
+TODO
+
+=head2 Changing the hash
+
+TODO
+
+=head2 Using db_stat
+
+TODO
+
+=head1 BerkeleyDB::Btree
+
+Equivalent to calling B<db_open> with type B<DB_BTREE> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_BTREE> in
+Berkeley DB 3.x or greater.
+
+Two forms of constructor are supported:
+
+
+ $db = new BerkeleyDB::Btree
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Btree specific
+ [ -Minkey => number,]
+ [ -Compare => code reference,]
+ [ -DupCompare => code reference,]
+ [ -Prefix => code reference,]
+
+and this
+
+ [$db =] tie %hash, 'BerkeleyDB::Btree',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Btree specific
+ [ -Minkey => number,]
+ [ -Compare => code reference,]
+ [ -DupCompare => code reference,]
+ [ -Prefix => code reference,]
+
+=head2 Options
+
+In addition to the standard set of options (see L<COMMON OPTIONS>)
+B<BerkeleyDB::Btree> supports these options:
+
+=over 5
+
+=item -Property
+
+Used to specify extra flags when opening a database. The following
+flags may be specified by logically OR'ing together one or more of the
+following values:
+
+B<DB_DUP>
+
+When creating a new database, this flag enables the storing of duplicate
+keys in the database. If B<DB_DUPSORT> is not specified as well, the
+duplicates are stored in the order they are created in the database.
+
+B<DB_DUPSORT>
+
+Enables the sorting of duplicate keys in the database. Ignored if
+B<DB_DUP> isn't also specified.
+
+=item Minkey
+
+TODO
+
+=item Compare
+
+Allow you to override the default sort order used in the database. See
+L<"Changing the sort order"> for an example.
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Compare => \&compare,
+ ...
+
+=item Prefix
+
+ sub prefix
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return number of bytes of $key2 which are
+ # necessary to determine that it is greater than $key1
+ return $bytes ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Prefix => \&prefix,
+ ...
+=item DupCompare
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -DupCompare => \&compare,
+ ...
+
+=back
+
+=head2 Methods
+
+B<BerkeleyDB::Btree> supports the following database methods.
+See also L<COMMON DATABASE METHODS>.
+
+All the methods below return 0 to indicate success.
+
+=over 5
+
+=item $status = $db->db_key_range($key, $less, $equal, $greater [, $flags])
+
+Given a key, C<$key>, this method returns the proportion of keys less than
+C<$key> in C<$less>, the proportion equal to C<$key> in C<$equal> and the
+proportion greater than C<$key> in C<$greater>.
+
+The proportion is returned as a double in the range 0.0 to 1.0.
+
+=back
+
+=head2 A Simple Btree Example
+
+The code below is a simple example of using a btree database.
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "tree" ;
+ unlink $filename ;
+ my %h ;
+ tie %h, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+
+Here is the output from the code above. The keys have been sorted using
+Berkeley DB's default sorting algorithm.
+
+ Smith
+ Wall
+ mouse
+
+
+=head2 Changing the sort order
+
+It is possible to supply your own sorting algorithm if the one that Berkeley
+DB used isn't suitable. The code below is identical to the previous example
+except for the case insensitive compare function.
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "tree" ;
+ unlink $filename ;
+ my %h ;
+ tie %h, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Compare => sub { lc $_[0] cmp lc $_[1] }
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+
+Here is the output from the code above.
+
+ mouse
+ Smith
+ Wall
+
+There are a few point to bear in mind if you want to change the
+ordering in a BTREE database:
+
+=over 5
+
+=item 1.
+
+The new compare function must be specified when you create the database.
+
+=item 2.
+
+You cannot change the ordering once the database has been created. Thus
+you must use the same compare function every time you access the
+database.
+
+=back
+
+=head2 Using db_stat
+
+TODO
+
+=head1 BerkeleyDB::Recno
+
+Equivalent to calling B<db_open> with type B<DB_RECNO> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_RECNO> in
+Berkeley DB 3.x or greater.
+
+Two forms of constructor are supported:
+
+ $db = new BerkeleyDB::Recno
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Recno specific
+ [ -Delim => byte,]
+ [ -Len => number,]
+ [ -Pad => byte,]
+ [ -Source => filename,]
+
+and this
+
+ [$db =] tie @arry, 'BerkeleyDB::Recno',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Recno specific
+ [ -Delim => byte,]
+ [ -Len => number,]
+ [ -Pad => byte,]
+ [ -Source => filename,]
+
+=head2 A Recno Example
+
+Here is a simple example that uses RECNO (if you are using a version
+of Perl earlier than 5.004_57 this example won't work -- see
+L<Extra RECNO Methods> for a workaround).
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ tie @h, 'BerkeleyDB::Recno',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_RENUMBER
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ push @h, "green", "black" ;
+
+ my $elements = scalar @h ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = pop @h ;
+ print "popped $last\n" ;
+
+ unshift @h, "white" ;
+ my $first = shift @h ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ untie @h ;
+
+Here is the output from the script:
+
+ The array contains 5 entries
+ popped black
+ shifted white
+ Element 1 Exists with value blue
+ The last element is green
+ The 2nd last element is yellow
+
+=head1 BerkeleyDB::Queue
+
+Equivalent to calling B<db_create> followed by B<DB-E<gt>open> with
+type B<DB_QUEUE> in Berkeley DB 3.x or greater. This database format
+isn't available if you use Berkeley DB 2.x.
+
+Two forms of constructor are supported:
+
+ $db = new BerkeleyDB::Queue
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Queue specific
+ [ -Len => number,]
+ [ -Pad => byte,]
+ [ -ExtentSize => number, ]
+
+and this
+
+ [$db =] tie @arry, 'BerkeleyDB::Queue',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Queue specific
+ [ -Len => number,]
+ [ -Pad => byte,]
+
+
+=head1 BerkeleyDB::Unknown
+
+This class is used to open an existing database.
+
+Equivalent to calling B<db_open> with type B<DB_UNKNOWN> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_UNKNOWN> in
+Berkeley DB 3.x or greater.
+
+The constructor looks like this:
+
+ $db = new BerkeleyDB::Unknown
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+
+
+=head2 An example
+
+=head1 COMMON OPTIONS
+
+All database access class constructors support the common set of
+options defined below. All are optional.
+
+=over 5
+
+=item -Filename
+
+The database filename. If no filename is specified, a temporary file will
+be created and removed once the program terminates.
+
+=item -Subname
+
+Specifies the name of the sub-database to open.
+This option is only valid if you are using Berkeley DB 3.x or greater.
+
+=item -Flags
+
+Specify how the database will be opened/created. The valid flags are:
+
+B<DB_CREATE>
+
+Create any underlying files, as necessary. If the files do not already
+exist and the B<DB_CREATE> flag is not specified, the call will fail.
+
+B<DB_NOMMAP>
+
+Not supported by BerkeleyDB.
+
+B<DB_RDONLY>
+
+Opens the database in read-only mode.
+
+B<DB_THREAD>
+
+Not supported by BerkeleyDB.
+
+B<DB_TRUNCATE>
+
+If the database file already exists, remove all the data before
+opening it.
+
+=item -Mode
+
+Determines the file protection when the database is created. Defaults
+to 0666.
+
+=item -Cachesize
+
+=item -Lorder
+
+=item -Pagesize
+
+=item -Env
+
+When working under a Berkeley DB environment, this parameter
+
+Defaults to no environment.
+
+=item -Txn
+
+TODO.
+
+=back
+
+=head1 COMMON DATABASE METHODS
+
+All the database interfaces support the common set of methods defined
+below.
+
+All the methods below return 0 to indicate success.
+
+=head2 $status = $db->db_get($key, $value [, $flags])
+
+Given a key (C<$key>) this method reads the value associated with it
+from the database. If it exists, the value read from the database is
+returned in the C<$value> parameter.
+
+The B<$flags> parameter is optional. If present, it must be set to B<one>
+of the following values:
+
+=over 5
+
+=item B<DB_GET_BOTH>
+
+When the B<DB_GET_BOTH> flag is specified, B<db_get> checks for the
+existence of B<both> the C<$key> B<and> C<$value> in the database.
+
+=item B<DB_SET_RECNO>
+
+TODO.
+
+=back
+
+In addition, the following value may be set by logically OR'ing it into
+the B<$flags> parameter:
+
+=over 5
+
+=item B<DB_RMW>
+
+TODO
+
+=back
+
+
+=head2 $status = $db->db_put($key, $value [, $flags])
+
+Stores a key/value pair in the database.
+
+The B<$flags> parameter is optional. If present it must be set to B<one>
+of the following values:
+
+=over 5
+
+=item B<DB_APPEND>
+
+This flag is only applicable when accessing a B<BerkeleyDB::Recno>
+database.
+
+TODO.
+
+
+=item B<DB_NOOVERWRITE>
+
+If this flag is specified and C<$key> already exists in the database,
+the call to B<db_put> will return B<DB_KEYEXIST>.
+
+=back
+
+=head2 $status = $db->db_del($key [, $flags])
+
+Deletes a key/value pair in the database associated with C<$key>.
+If duplicate keys are enabled in the database, B<db_del> will delete
+B<all> key/value pairs with key C<$key>.
+
+The B<$flags> parameter is optional and is currently unused.
+
+=head2 $status = $db->db_sync()
+
+If any parts of the database are in memory, write them to the database.
+
+=head2 $cursor = $db->db_cursor([$flags])
+
+Creates a cursor object. This is used to access the contents of the
+database sequentially. See L<CURSORS> for details of the methods
+available when working with cursors.
+
+The B<$flags> parameter is optional. If present it must be set to B<one>
+of the following values:
+
+=over 5
+
+=item B<DB_RMW>
+
+TODO.
+
+=back
+
+=head2 ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
+
+TODO
+
+=head2 ($flag, $old_offset, $old_length) = $db->partial_clear() ;
+
+TODO
+
+=head2 $db->byteswapped()
+
+TODO
+
+=head2 $db->type()
+
+Returns the type of the database. The possible return code are B<DB_HASH>
+for a B<BerkeleyDB::Hash> database, B<DB_BTREE> for a B<BerkeleyDB::Btree>
+database and B<DB_RECNO> for a B<BerkeleyDB::Recno> database. This method
+is typically used when a database has been opened with
+B<BerkeleyDB::Unknown>.
+
+=item $ref = $db->db_stat()
+
+Returns a reference to an associative array containing information about
+the database. The keys of the associative array correspond directly to the
+names of the fields defined in the Berkeley DB documentation. For example,
+in the DB documentation, the field B<bt_version> stores the version of the
+Btree database. Assuming you called B<db_stat> on a Btree database the
+equivalent field would be accessed as follows:
+
+ $version = $ref->{'bt_version'} ;
+
+If you are using Berkeley DB 3.x or better, this method will work will
+all database formats. When DB 2.x is used, it only works with
+B<BerkeleyDB::Btree>.
+
+=head2 $status = $db->status()
+
+Returns the status of the last C<$db> method called.
+
+=head2 $status = $db->truncate($count)
+
+Truncates the datatabase and returns the number or records deleted
+in C<$count>.
+
+=head1 CURSORS
+
+A cursor is used whenever you want to access the contents of a database
+in sequential order.
+A cursor object is created with the C<db_cursor>
+
+A cursor object has the following methods available:
+
+=head2 $newcursor = $cursor->c_dup($flags)
+
+Creates a duplicate of C<$cursor>. This method needs Berkeley DB 3.0.x or better.
+
+The C<$flags> parameter is optional and can take the following value:
+
+=over 5
+
+=item DB_POSITION
+
+When present this flag will position the new cursor at the same place as the
+existing cursor.
+
+=back
+
+=head2 $status = $cursor->c_get($key, $value, $flags)
+
+Reads a key/value pair from the database, returning the data in C<$key>
+and C<$value>. The key/value pair actually read is controlled by the
+C<$flags> parameter, which can take B<one> of the following values:
+
+=over 5
+
+=item B<DB_FIRST>
+
+Set the cursor to point to the first key/value pair in the
+database. Return the key/value pair in C<$key> and C<$value>.
+
+=item B<DB_LAST>
+
+Set the cursor to point to the last key/value pair in the database. Return
+the key/value pair in C<$key> and C<$value>.
+
+=item B<DB_NEXT>
+
+If the cursor is already pointing to a key/value pair, it will be
+incremented to point to the next key/value pair and return its contents.
+
+If the cursor isn't initialised, B<DB_NEXT> works just like B<DB_FIRST>.
+
+If the cursor is already positioned at the last key/value pair, B<c_get>
+will return B<DB_NOTFOUND>.
+
+=item B<DB_NEXT_DUP>
+
+This flag is only valid when duplicate keys have been enabled in
+a database.
+If the cursor is already pointing to a key/value pair and the key of
+the next key/value pair is identical, the cursor will be incremented to
+point to it and their contents returned.
+
+=item B<DB_PREV>
+
+If the cursor is already pointing to a key/value pair, it will be
+decremented to point to the previous key/value pair and return its
+contents.
+
+If the cursor isn't initialised, B<DB_PREV> works just like B<DB_LAST>.
+
+If the cursor is already positioned at the first key/value pair, B<c_get>
+will return B<DB_NOTFOUND>.
+
+=item B<DB_CURRENT>
+
+If the cursor has been set to point to a key/value pair, return their
+contents.
+If the key/value pair referenced by the cursor has been deleted, B<c_get>
+will return B<DB_KEYEMPTY>.
+
+=item B<DB_SET>
+
+Set the cursor to point to the key/value pair referenced by B<$key>
+and return the value in B<$value>.
+
+=item B<DB_SET_RANGE>
+
+This flag is a variation on the B<DB_SET> flag. As well as returning
+the value, it also returns the key, via B<$key>.
+When used with a B<BerkeleyDB::Btree> database the key matched by B<c_get>
+will be the shortest key (in length) which is greater than or equal to
+the key supplied, via B<$key>. This allows partial key searches.
+See ??? for an example of how to use this flag.
+
+=item B<DB_GET_BOTH>
+
+Another variation on B<DB_SET>. This one returns both the key and
+the value.
+
+=item B<DB_SET_RECNO>
+
+TODO.
+
+=item B<DB_GET_RECNO>
+
+TODO.
+
+=back
+
+In addition, the following value may be set by logically OR'ing it into
+the B<$flags> parameter:
+
+=over 5
+
+=item B<DB_RMW>
+
+TODO.
+
+=back
+
+=head2 $status = $cursor->c_put($key, $value, $flags)
+
+Stores the key/value pair in the database. The position that the data is
+stored in the database is controlled by the C<$flags> parameter, which
+must take B<one> of the following values:
+
+=over 5
+
+=item B<DB_AFTER>
+
+When used with a Btree or Hash database, a duplicate of the key referenced
+by the current cursor position will be created and the contents of
+B<$value> will be associated with it - B<$key> is ignored.
+The new key/value pair will be stored immediately after the current
+cursor position.
+Obviously the database has to have been opened with B<DB_DUP>.
+
+When used with a Recno ... TODO
+
+
+=item B<DB_BEFORE>
+
+When used with a Btree or Hash database, a duplicate of the key referenced
+by the current cursor position will be created and the contents of
+B<$value> will be associated with it - B<$key> is ignored.
+The new key/value pair will be stored immediately before the current
+cursor position.
+Obviously the database has to have been opened with B<DB_DUP>.
+
+When used with a Recno ... TODO
+
+=item B<DB_CURRENT>
+
+If the cursor has been initialised, replace the value of the key/value
+pair stored in the database with the contents of B<$value>.
+
+=item B<DB_KEYFIRST>
+
+Only valid with a Btree or Hash database. This flag is only really
+used when duplicates are enabled in the database and sorted duplicates
+haven't been specified.
+In this case the key/value pair will be inserted as the first entry in
+the duplicates for the particular key.
+
+=item B<DB_KEYLAST>
+
+Only valid with a Btree or Hash database. This flag is only really
+used when duplicates are enabled in the database and sorted duplicates
+haven't been specified.
+In this case the key/value pair will be inserted as the last entry in
+the duplicates for the particular key.
+
+=back
+
+=head2 $status = $cursor->c_del([$flags])
+
+This method deletes the key/value pair associated with the current cursor
+position. The cursor position will not be changed by this operation, so
+any subsequent cursor operation must first initialise the cursor to
+point to a valid key/value pair.
+
+If the key/value pair associated with the cursor have already been
+deleted, B<c_del> will return B<DB_KEYEMPTY>.
+
+The B<$flags> parameter is not used at present.
+
+=head2 $status = $cursor->c_del($cnt [, $flags])
+
+Stores the number of duplicates at the current cursor position in B<$cnt>.
+
+The B<$flags> parameter is not used at present. This method needs
+Berkeley DB 3.1 or better.
+
+=head2 $status = $cursor->status()
+
+Returns the status of the last cursor method as a dual type.
+
+=head2 Cursor Examples
+
+TODO
+
+Iterating from first to last, then in reverse.
+
+examples of each of the flags.
+
+=head1 JOIN
+
+Join support for BerkeleyDB is in progress. Watch this space.
+
+TODO
+
+=head1 TRANSACTIONS
+
+TODO.
+
+=head1 DBM Filters
+
+A DBM Filter is a piece of code that is be used when you I<always>
+want to make the same transformation to all keys and/or values in a DBM
+database. All of the database classes (BerkeleyDB::Hash,
+BerkeleyDB::Btree and BerkeleyDB::Recno) support DBM Filters.
+
+There are four methods associated with DBM Filters. All work
+identically, and each is used to install (or uninstall) a single DBM
+Filter. Each expects a single parameter, namely a reference to a sub.
+The only difference between them is the place that the filter is
+installed.
+
+To summarise:
+
+=over 5
+
+=item B<filter_store_key>
+
+If a filter has been installed with this method, it will be invoked
+every time you write a key to a DBM database.
+
+=item B<filter_store_value>
+
+If a filter has been installed with this method, it will be invoked
+every time you write a value to a DBM database.
+
+
+=item B<filter_fetch_key>
+
+If a filter has been installed with this method, it will be invoked
+every time you read a key from a DBM database.
+
+=item B<filter_fetch_value>
+
+If a filter has been installed with this method, it will be invoked
+every time you read a value from a DBM database.
+
+=back
+
+You can use any combination of the methods, from none, to all four.
+
+All filter methods return the existing filter, if present, or C<undef>
+in not.
+
+To delete a filter pass C<undef> to it.
+
+=head2 The Filter
+
+When each filter is called by Perl, a local copy of C<$_> will contain
+the key or value to be filtered. Filtering is achieved by modifying
+the contents of C<$_>. The return code from the filter is ignored.
+
+=head2 An Example -- the NULL termination problem.
+
+Consider the following scenario. You have a DBM database that you need
+to share with a third-party C application. The C application assumes
+that I<all> keys and values are NULL terminated. Unfortunately when
+Perl writes to DBM databases it doesn't use NULL termination, so your
+Perl application will have to manage NULL termination itself. When you
+write to the database you will have to use something like this:
+
+ $hash{"$key\0"} = "$value\0" ;
+
+Similarly the NULL needs to be taken into account when you are considering
+the length of existing keys/values.
+
+It would be much better if you could ignore the NULL terminations issue
+in the main application code and have a mechanism that automatically
+added the terminating NULL to all keys and values whenever you write to
+the database and have them removed when you read from the database. As I'm
+sure you have already guessed, this is a problem that DBM Filters can
+fix very easily.
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my %hash ;
+ my $filename = "filt.db" ;
+ unlink $filename ;
+
+ my $db = tie %hash, 'BerkeleyDB::Hash',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ # Install DBM Filters
+ $db->filter_fetch_key ( sub { s/\0$// } ) ;
+ $db->filter_store_key ( sub { $_ .= "\0" } ) ;
+ $db->filter_fetch_value( sub { s/\0$// } ) ;
+ $db->filter_store_value( sub { $_ .= "\0" } ) ;
+
+ $hash{"abc"} = "def" ;
+ my $a = $hash{"ABC"} ;
+ # ...
+ undef $db ;
+ untie %hash ;
+
+Hopefully the contents of each of the filters should be
+self-explanatory. Both "fetch" filters remove the terminating NULL,
+and both "store" filters add a terminating NULL.
+
+
+=head2 Another Example -- Key is a C int.
+
+Here is another real-life example. By default, whenever Perl writes to
+a DBM database it always writes the key and value as strings. So when
+you use this:
+
+ $hash{12345} = "something" ;
+
+the key 12345 will get stored in the DBM database as the 5 byte string
+"12345". If you actually want the key to be stored in the DBM database
+as a C int, you will have to use C<pack> when writing, and C<unpack>
+when reading.
+
+Here is a DBM Filter that does it:
+
+ use strict ;
+ use BerkeleyDB ;
+ my %hash ;
+ my $filename = "filt.db" ;
+ unlink $filename ;
+
+
+ my $db = tie %hash, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
+ $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
+ $hash{123} = "def" ;
+ # ...
+ undef $db ;
+ untie %hash ;
+
+This time only two filters have been used -- we only need to manipulate
+the contents of the key, so it wasn't necessary to install any value
+filters.
+
+=head1 Using BerkeleyDB with MLDBM
+
+Both BerkeleyDB::Hash and BerkeleyDB::Btree can be used with the MLDBM
+module. The code fragment below shows how to open associate MLDBM with
+BerkeleyDB::Btree. To use BerkeleyDB::Hash just replace
+BerkeleyDB::Btree with BerkeleyDB::Hash.
+
+ use strict ;
+ use BerkeleyDB ;
+ use MLDBM qw(BerkeleyDB::Btree) ;
+ use Data::Dumper;
+
+ my $filename = 'testmldbm' ;
+ my %o ;
+
+ unlink $filename ;
+ tie %o, 'MLDBM', -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open database '$filename: $!\n";
+
+See the MLDBM documentation for information on how to use the module
+and for details of its limitations.
+
+=head1 EXAMPLES
+
+TODO.
+
+=head1 HINTS & TIPS
+
+=head2 Sharing Databases With C Applications
+
+There is no technical reason why a Berkeley DB database cannot be
+shared by both a Perl and a C application.
+
+The vast majority of problems that are reported in this area boil down
+to the fact that C strings are NULL terminated, whilst Perl strings
+are not. See L<An Example -- the NULL termination problem.> in the DBM
+FILTERS section for a generic way to work around this problem.
+
+
+=head2 The untie Gotcha
+
+TODO
+
+=head1 COMMON QUESTIONS
+
+This section attempts to answer some of the more common questions that
+I get asked.
+
+
+=head2 Relationship with DB_File
+
+Before Berkeley DB 2.x was written there was only one Perl module that
+interfaced to Berkeley DB. That module is called B<DB_File>. Although
+B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only provides
+an interface to the functionality available in Berkeley DB 1.x. That
+means that it doesn't support transactions, locking or any of the other
+new features available in DB 2.x or better.
+
+=head2 How do I store Perl data structures with BerkeleyDB?
+
+See L<Using BerkeleyDB with MLDBM>.
+
+=head1 HISTORY
+
+See the Changes file.
+
+=head1 AVAILABILITY
+
+The most recent version of B<BerkeleyDB> can always be found
+on CPAN (see L<perlmod/CPAN> for details), in the directory
+F<modules/by-module/BerkeleyDB>.
+
+The official web site for Berkeley DB is F<http://www.sleepycat.com>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program
+is free software; you can redistribute it and/or modify it under the
+same terms as Perl itself.
+
+Although B<BerkeleyDB> is covered by the Perl license, the library it
+makes use of, namely Berkeley DB, is not. Berkeley DB has its own
+copyright and its own license. Please take the time to read it.
+
+Here are few words taken from the Berkeley DB FAQ (at
+F<http://www.sleepycat.com>) regarding the license:
+
+ Do I have to license DB to use it in Perl scripts?
+
+ No. The Berkeley DB license requires that software that uses
+ Berkeley DB be freely redistributable. In the case of Perl, that
+ software is Perl, and not your scripts. Any Perl scripts that you
+ write are your property, including scripts that make use of Berkeley
+ DB. Neither the Perl license nor the Berkeley DB license
+ place any restriction on what you may do with them.
+
+If you are in any doubt about the license situation, contact either the
+Berkeley DB authors or the author of BerkeleyDB.
+See L<"AUTHOR"> for details.
+
+
+=head1 AUTHOR
+
+Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt>.
+
+Questions about Berkeley DB may be addressed to E<lt>db@sleepycat.comE<gt>.
+
+=head1 SEE ALSO
+
+perl(1), DB_File, Berkeley DB.
+
+=cut
diff --git a/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P b/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P
new file mode 100644
index 00000000000..4a848f5388d
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P
@@ -0,0 +1,1559 @@
+=head1 NAME
+
+BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
+
+=head1 SYNOPSIS
+
+ use BerkeleyDB;
+
+ $env = new BerkeleyDB::Env [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Hash', [OPTIONS] ;
+ $db = new BerkeleyDB::Hash [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
+ $db = new BerkeleyDB::Btree [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
+ $db = new BerkeleyDB::Recno [OPTIONS] ;
+
+ $db = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
+ $db = new BerkeleyDB::Queue [OPTIONS] ;
+
+ $db = new BerkeleyDB::Unknown [OPTIONS] ;
+
+ $status = BerkeleyDB::db_remove [OPTIONS]
+ $status = BerkeleyDB::db_rename [OPTIONS]
+ $status = BerkeleyDB::db_verify [OPTIONS]
+
+ $hash{$key} = $value ;
+ $value = $hash{$key} ;
+ each %hash ;
+ keys %hash ;
+ values %hash ;
+
+ $status = $db->db_get()
+ $status = $db->db_put() ;
+ $status = $db->db_del() ;
+ $status = $db->db_sync() ;
+ $status = $db->db_close() ;
+ $status = $db->db_close() ;
+ $status = $db->db_pget()
+ $hash_ref = $db->db_stat() ;
+ $status = $db->db_key_range();
+ $type = $db->type() ;
+ $status = $db->status() ;
+ $boolean = $db->byteswapped() ;
+ $status = $db->truncate($count) ;
+
+ ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
+ ($flag, $old_offset, $old_length) = $db->partial_clear() ;
+
+ $cursor = $db->db_cursor([$flags]) ;
+ $newcursor = $cursor->c_dup([$flags]);
+ $status = $cursor->c_get() ;
+ $status = $cursor->c_put() ;
+ $status = $cursor->c_del() ;
+ $status = $cursor->c_count() ;
+ $status = $cursor->c_pget() ;
+ $status = $cursor->status() ;
+ $status = $cursor->c_close() ;
+
+ $cursor = $db->db_join() ;
+ $status = $cursor->c_get() ;
+ $status = $cursor->c_close() ;
+
+ $status = $env->txn_checkpoint()
+ $hash_ref = $env->txn_stat()
+ $status = $env->setmutexlocks()
+ $status = $env->set_flags()
+
+ $txn = $env->txn_begin() ;
+ $db->Txn($txn);
+ $txn->Txn($db1, $db2,...);
+ $status = $txn->txn_prepare()
+ $status = $txn->txn_commit()
+ $status = $txn->txn_abort()
+ $status = $txn->txn_id()
+ $status = $txn->txn_discard()
+
+ $status = $env->set_lg_dir();
+ $status = $env->set_lg_bsize();
+ $status = $env->set_lg_max();
+
+ $status = $env->set_data_dir() ;
+ $status = $env->set_tmp_dir() ;
+ $status = $env->set_verbose() ;
+
+ $BerkeleyDB::Error
+ $BerkeleyDB::db_version
+
+ # DBM Filters
+ $old_filter = $db->filter_store_key ( sub { ... } ) ;
+ $old_filter = $db->filter_store_value( sub { ... } ) ;
+ $old_filter = $db->filter_fetch_key ( sub { ... } ) ;
+ $old_filter = $db->filter_fetch_value( sub { ... } ) ;
+
+ # deprecated, but supported
+ $txn_mgr = $env->TxnMgr();
+ $status = $txn_mgr->txn_checkpoint()
+ $hash_ref = $txn_mgr->txn_stat()
+ $txn = $txn_mgr->txn_begin() ;
+
+=head1 DESCRIPTION
+
+B<NOTE: This document is still under construction. Expect it to be
+incomplete in places.>
+
+This Perl module provides an interface to most of the functionality
+available in Berkeley DB versions 2, 3 and 4. In general it is safe to assume
+that the interface provided here to be identical to the Berkeley DB
+interface. The main changes have been to make the Berkeley DB API work
+in a Perl way. Note that if you are using Berkeley DB 2.x, the new
+features available in Berkeley DB 3.x or DB 4.x are not available via
+this module.
+
+The reader is expected to be familiar with the Berkeley DB
+documentation. Where the interface provided here is identical to the
+Berkeley DB library and the... TODO
+
+The B<db_appinit>, B<db_cursor>, B<db_open> and B<db_txn> man pages are
+particularly relevant.
+
+The interface to Berkeley DB is implemented with a number of Perl
+classes.
+
+=head1 ENV CLASS
+
+The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB
+function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and
+B<DBENV-E<gt>open> in Berkeley DB 3.x/4.x. Its purpose is to initialise a
+number of sub-systems that can then be used in a consistent way in all
+the databases you make use of the environment.
+
+If you don't intend using transactions, locking or logging, then you
+shouldn't need to make use of B<BerkeleyDB::Env>.
+
+=head2 Synopsis
+
+ $env = new BerkeleyDB::Env
+ [ -Home => $path, ]
+ [ -Server => $name, ]
+ [ -CacheSize => $number, ]
+ [ -Config => { name => value, name => value }, ]
+ [ -ErrFile => filename, ]
+ [ -ErrPrefix => "string", ]
+ [ -Flags => number, ]
+ [ -SetFlags => bitmask, ]
+ [ -LockDetect => number, ]
+ [ -Verbose => boolean, ]
+
+=over 5
+
+All the parameters to the BerkeleyDB::Env constructor are optional.
+
+=item -Home
+
+If present, this parameter should point to an existing directory. Any
+files that I<aren't> specified with an absolute path in the sub-systems
+that are initialised by the BerkeleyDB::Env class will be assumed to
+live in the B<Home> directory.
+
+For example, in the code fragment below the database "fred.db" will be
+opened in the directory "/home/databases" because it was specified as a
+relative path, but "joe.db" will be opened in "/other" because it was
+part of an absolute path.
+
+ $env = new BerkeleyDB::Env
+ -Home => "/home/databases"
+ ...
+
+ $db1 = new BerkeleyDB::Hash
+ -Filename = "fred.db",
+ -Env => $env
+ ...
+
+ $db2 = new BerkeleyDB::Hash
+ -Filename = "/other/joe.db",
+ -Env => $env
+ ...
+
+=item -Server
+
+If present, this parameter should be the hostname of a server that is running
+the Berkeley DB RPC server. All databases will be accessed via the RPC server.
+
+=item -Cachesize
+
+If present, this parameter sets the size of the environments shared memory
+buffer pool.
+
+=item -Config
+
+This is a variation on the C<-Home> parameter, but it allows finer
+control of where specific types of files will be stored.
+
+The parameter expects a reference to a hash. Valid keys are:
+B<DB_DATA_DIR>, B<DB_LOG_DIR> and B<DB_TMP_DIR>
+
+The code below shows an example of how it can be used.
+
+ $env = new BerkeleyDB::Env
+ -Config => { DB_DATA_DIR => "/home/databases",
+ DB_LOG_DIR => "/home/logs",
+ DB_TMP_DIR => "/home/tmp"
+ }
+ ...
+
+=item -ErrFile
+
+Expects a filenme. Any errors generated internally by Berkeley DB will
+be logged to this file.
+
+=item -ErrPrefix
+
+Allows a prefix to be added to the error messages before they are sent
+to B<-ErrFile>.
+
+=item -Flags
+
+The B<Flags> parameter specifies both which sub-systems to initialise,
+as well as a number of environment-wide options.
+See the Berkeley DB documentation for more details of these options.
+
+Any of the following can be specified by OR'ing them:
+
+B<DB_CREATE>
+
+If any of the files specified do not already exist, create them.
+
+B<DB_INIT_CDB>
+
+Initialise the Concurrent Access Methods
+
+B<DB_INIT_LOCK>
+
+Initialise the Locking sub-system.
+
+B<DB_INIT_LOG>
+
+Initialise the Logging sub-system.
+
+B<DB_INIT_MPOOL>
+
+Initialise the ...
+
+B<DB_INIT_TXN>
+
+Initialise the ...
+
+B<DB_MPOOL_PRIVATE>
+
+Initialise the ...
+
+B<DB_INIT_MPOOL> is also specified.
+
+Initialise the ...
+
+B<DB_NOMMAP>
+
+Initialise the ...
+
+B<DB_RECOVER>
+
+
+
+B<DB_RECOVER_FATAL>
+
+B<DB_THREAD>
+
+B<DB_TXN_NOSYNC>
+
+B<DB_USE_ENVIRON>
+
+B<DB_USE_ENVIRON_ROOT>
+
+=item -SetFlags
+
+Calls ENV->set_flags with the supplied bitmask. Use this when you need to make
+use of DB_ENV->set_flags before DB_ENV->open is called.
+
+Only valid when Berkeley DB 3.x or better is used.
+
+=item -LockDetect
+
+Specifies what to do when a lock conflict occurs. The value should be one of
+
+B<DB_LOCK_DEFAULT>
+
+B<DB_LOCK_OLDEST>
+
+B<DB_LOCK_RANDOM>
+
+B<DB_LOCK_YOUNGEST>
+
+=item -Verbose
+
+Add extra debugging information to the messages sent to B<-ErrFile>.
+
+=back
+
+=head2 Methods
+
+The environment class has the following methods:
+
+=over 5
+
+=item $env->errPrefix("string") ;
+
+This method is identical to the B<-ErrPrefix> flag. It allows the
+error prefix string to be changed dynamically.
+
+=item $env->set_flags(bitmask, 1|0);
+
+=item $txn = $env->TxnMgr()
+
+Constructor for creating a B<TxnMgr> object.
+See L<"TRANSACTIONS"> for more details of using transactions.
+
+This method is deprecated. Access the transaction methods using the B<txn_>
+methods below from the environment object directly.
+
+=item $env->txn_begin()
+
+TODO
+
+=item $env->txn_stat()
+
+TODO
+
+=item $env->txn_checkpoint()
+
+TODO
+
+=item $env->status()
+
+Returns the status of the last BerkeleyDB::Env method.
+
+=item $env->setmutexlocks()
+
+Only available in Berkeley Db 3.0 or greater. Calls
+B<db_env_set_mutexlocks> when used with Berkeley DB 3.1.x. When used with
+Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>.
+
+=back
+
+=head2 Examples
+
+TODO.
+
+=head1 Global Classes
+
+ $status = BerkeleyDB::db_remove [OPTIONS]
+ $status = BerkeleyDB::db_rename [OPTIONS]
+ $status = BerkeleyDB::db_verify [OPTIONS]
+
+=head1 THE DATABASE CLASSES
+
+B<BerkeleyDB> supports the following database formats:
+
+=over 5
+
+=item B<BerkeleyDB::Hash>
+
+This database type allows arbitrary key/value pairs to be stored in data
+files. This is equivalent to the functionality provided by other
+hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
+the files created using B<BerkeleyDB::Hash> are not compatible with any
+of the other packages mentioned.
+
+A default hashing algorithm, which will be adequate for most applications,
+is built into BerkeleyDB. If you do need to use your own hashing algorithm
+it is possible to write your own in Perl and have B<BerkeleyDB> use
+it instead.
+
+=item B<BerkeleyDB::Btree>
+
+The Btree format allows arbitrary key/value pairs to be stored in a
+B+tree.
+
+As with the B<BerkeleyDB::Hash> format, it is possible to provide a
+user defined Perl routine to perform the comparison of keys. By default,
+though, the keys are stored in lexical order.
+
+=item B<BerkeleyDB::Recno>
+
+TODO.
+
+
+=item B<BerkeleyDB::Queue>
+
+TODO.
+
+=item B<BerkeleyDB::Unknown>
+
+This isn't a database format at all. It is used when you want to open an
+existing Berkeley DB database without having to know what type is it.
+
+=back
+
+
+Each of the database formats described above is accessed via a
+corresponding B<BerkeleyDB> class. These will be described in turn in
+the next sections.
+
+=head1 BerkeleyDB::Hash
+
+Equivalent to calling B<db_open> with type B<DB_HASH> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_HASH> in
+Berkeley DB 3.x or greater.
+
+Two forms of constructor are supported:
+
+ $db = new BerkeleyDB::Hash
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Hash specific
+ [ -Ffactor => number,]
+ [ -Nelem => number,]
+ [ -Hash => code reference,]
+ [ -DupCompare => code reference,]
+
+and this
+
+ [$db =] tie %hash, 'BerkeleyDB::Hash',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Hash specific
+ [ -Ffactor => number,]
+ [ -Nelem => number,]
+ [ -Hash => code reference,]
+ [ -DupCompare => code reference,]
+
+
+When the "tie" interface is used, reading from and writing to the database
+is achieved via the tied hash. In this case the database operates like
+a Perl associative array that happens to be stored on disk.
+
+In addition to the high-level tied hash interface, it is possible to
+make use of the underlying methods provided by Berkeley DB
+
+=head2 Options
+
+In addition to the standard set of options (see L<COMMON OPTIONS>)
+B<BerkeleyDB::Hash> supports these options:
+
+=over 5
+
+=item -Property
+
+Used to specify extra flags when opening a database. The following
+flags may be specified by logically OR'ing together one or more of the
+following values:
+
+B<DB_DUP>
+
+When creating a new database, this flag enables the storing of duplicate
+keys in the database. If B<DB_DUPSORT> is not specified as well, the
+duplicates are stored in the order they are created in the database.
+
+B<DB_DUPSORT>
+
+Enables the sorting of duplicate keys in the database. Ignored if
+B<DB_DUP> isn't also specified.
+
+=item -Ffactor
+
+=item -Nelem
+
+See the Berkeley DB documentation for details of these options.
+
+=item -Hash
+
+Allows you to provide a user defined hash function. If not specified,
+a default hash function is used. Here is a template for a user-defined
+hash function
+
+ sub hash
+ {
+ my ($data) = shift ;
+ ...
+ # return the hash value for $data
+ return $hash ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Hash => \&hash,
+ ...
+
+See L<""> for an example.
+
+=item -DupCompare
+
+Used in conjunction with the B<DB_DUPOSRT> flag.
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Property => DB_DUP|DB_DUPSORT,
+ -DupCompare => \&compare,
+ ...
+
+=back
+
+
+=head2 Methods
+
+B<BerkeleyDB::Hash> only supports the standard database methods.
+See L<COMMON DATABASE METHODS>.
+
+=head2 A Simple Tied Hash Example
+
+## simpleHash
+
+here is the output:
+
+ Banana Exists
+
+ orange -> orange
+ tomato -> red
+ banana -> yellow
+
+Note that the like ordinary associative arrays, the order of the keys
+retrieved from a Hash database are in an apparently random order.
+
+=head2 Another Simple Hash Example
+
+Do the same as the previous example but not using tie.
+
+## simpleHash2
+
+=head2 Duplicate keys
+
+The code below is a variation on the examples above. This time the hash has
+been inverted. The key this time is colour and the value is the fruit name.
+The B<DB_DUP> flag has been specified to allow duplicates.
+
+##dupHash
+
+here is the output:
+
+ orange -> orange
+ yellow -> banana
+ red -> apple
+ red -> tomato
+ green -> banana
+ green -> apple
+
+=head2 Sorting Duplicate Keys
+
+In the previous example, when there were duplicate keys, the values are
+sorted in the order they are stored in. The code below is
+identical to the previous example except the B<DB_DUPSORT> flag is
+specified.
+
+##dupSortHash
+
+Notice that in the output below the duplicate values are sorted.
+
+ orange -> orange
+ yellow -> banana
+ red -> apple
+ red -> tomato
+ green -> apple
+ green -> banana
+
+=head2 Custom Sorting Duplicate Keys
+
+Another variation
+
+TODO
+
+=head2 Changing the hash
+
+TODO
+
+=head2 Using db_stat
+
+TODO
+
+=head1 BerkeleyDB::Btree
+
+Equivalent to calling B<db_open> with type B<DB_BTREE> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_BTREE> in
+Berkeley DB 3.x or greater.
+
+Two forms of constructor are supported:
+
+
+ $db = new BerkeleyDB::Btree
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Btree specific
+ [ -Minkey => number,]
+ [ -Compare => code reference,]
+ [ -DupCompare => code reference,]
+ [ -Prefix => code reference,]
+
+and this
+
+ [$db =] tie %hash, 'BerkeleyDB::Btree',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Btree specific
+ [ -Minkey => number,]
+ [ -Compare => code reference,]
+ [ -DupCompare => code reference,]
+ [ -Prefix => code reference,]
+
+=head2 Options
+
+In addition to the standard set of options (see L<COMMON OPTIONS>)
+B<BerkeleyDB::Btree> supports these options:
+
+=over 5
+
+=item -Property
+
+Used to specify extra flags when opening a database. The following
+flags may be specified by logically OR'ing together one or more of the
+following values:
+
+B<DB_DUP>
+
+When creating a new database, this flag enables the storing of duplicate
+keys in the database. If B<DB_DUPSORT> is not specified as well, the
+duplicates are stored in the order they are created in the database.
+
+B<DB_DUPSORT>
+
+Enables the sorting of duplicate keys in the database. Ignored if
+B<DB_DUP> isn't also specified.
+
+=item Minkey
+
+TODO
+
+=item Compare
+
+Allow you to override the default sort order used in the database. See
+L<"Changing the sort order"> for an example.
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Compare => \&compare,
+ ...
+
+=item Prefix
+
+ sub prefix
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return number of bytes of $key2 which are
+ # necessary to determine that it is greater than $key1
+ return $bytes ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Prefix => \&prefix,
+ ...
+=item DupCompare
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -DupCompare => \&compare,
+ ...
+
+=back
+
+=head2 Methods
+
+B<BerkeleyDB::Btree> supports the following database methods.
+See also L<COMMON DATABASE METHODS>.
+
+All the methods below return 0 to indicate success.
+
+=over 5
+
+=item $status = $db->db_key_range($key, $less, $equal, $greater [, $flags])
+
+Given a key, C<$key>, this method returns the proportion of keys less than
+C<$key> in C<$less>, the proportion equal to C<$key> in C<$equal> and the
+proportion greater than C<$key> in C<$greater>.
+
+The proportion is returned as a double in the range 0.0 to 1.0.
+
+=back
+
+=head2 A Simple Btree Example
+
+The code below is a simple example of using a btree database.
+
+## btreeSimple
+
+Here is the output from the code above. The keys have been sorted using
+Berkeley DB's default sorting algorithm.
+
+ Smith
+ Wall
+ mouse
+
+
+=head2 Changing the sort order
+
+It is possible to supply your own sorting algorithm if the one that Berkeley
+DB used isn't suitable. The code below is identical to the previous example
+except for the case insensitive compare function.
+
+## btreeSortOrder
+
+Here is the output from the code above.
+
+ mouse
+ Smith
+ Wall
+
+There are a few point to bear in mind if you want to change the
+ordering in a BTREE database:
+
+=over 5
+
+=item 1.
+
+The new compare function must be specified when you create the database.
+
+=item 2.
+
+You cannot change the ordering once the database has been created. Thus
+you must use the same compare function every time you access the
+database.
+
+=back
+
+=head2 Using db_stat
+
+TODO
+
+=head1 BerkeleyDB::Recno
+
+Equivalent to calling B<db_open> with type B<DB_RECNO> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_RECNO> in
+Berkeley DB 3.x or greater.
+
+Two forms of constructor are supported:
+
+ $db = new BerkeleyDB::Recno
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Recno specific
+ [ -Delim => byte,]
+ [ -Len => number,]
+ [ -Pad => byte,]
+ [ -Source => filename,]
+
+and this
+
+ [$db =] tie @arry, 'BerkeleyDB::Recno',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Recno specific
+ [ -Delim => byte,]
+ [ -Len => number,]
+ [ -Pad => byte,]
+ [ -Source => filename,]
+
+=head2 A Recno Example
+
+Here is a simple example that uses RECNO (if you are using a version
+of Perl earlier than 5.004_57 this example won't work -- see
+L<Extra RECNO Methods> for a workaround).
+
+## simpleRecno
+
+Here is the output from the script:
+
+ The array contains 5 entries
+ popped black
+ shifted white
+ Element 1 Exists with value blue
+ The last element is green
+ The 2nd last element is yellow
+
+=head1 BerkeleyDB::Queue
+
+Equivalent to calling B<db_create> followed by B<DB-E<gt>open> with
+type B<DB_QUEUE> in Berkeley DB 3.x or greater. This database format
+isn't available if you use Berkeley DB 2.x.
+
+Two forms of constructor are supported:
+
+ $db = new BerkeleyDB::Queue
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Queue specific
+ [ -Len => number,]
+ [ -Pad => byte,]
+ [ -ExtentSize => number, ]
+
+and this
+
+ [$db =] tie @arry, 'BerkeleyDB::Queue',
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+ # BerkeleyDB::Queue specific
+ [ -Len => number,]
+ [ -Pad => byte,]
+
+
+=head1 BerkeleyDB::Unknown
+
+This class is used to open an existing database.
+
+Equivalent to calling B<db_open> with type B<DB_UNKNOWN> in Berkeley DB 2.x and
+calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_UNKNOWN> in
+Berkeley DB 3.x or greater.
+
+The constructor looks like this:
+
+ $db = new BerkeleyDB::Unknown
+ [ -Filename => "filename", ]
+ [ -Subname => "sub-database name", ]
+ [ -Flags => flags,]
+ [ -Property => flags,]
+ [ -Mode => number,]
+ [ -Cachesize => number,]
+ [ -Lorder => number,]
+ [ -Pagesize => number,]
+ [ -Env => $env,]
+ [ -Txn => $txn,]
+
+
+=head2 An example
+
+=head1 COMMON OPTIONS
+
+All database access class constructors support the common set of
+options defined below. All are optional.
+
+=over 5
+
+=item -Filename
+
+The database filename. If no filename is specified, a temporary file will
+be created and removed once the program terminates.
+
+=item -Subname
+
+Specifies the name of the sub-database to open.
+This option is only valid if you are using Berkeley DB 3.x or greater.
+
+=item -Flags
+
+Specify how the database will be opened/created. The valid flags are:
+
+B<DB_CREATE>
+
+Create any underlying files, as necessary. If the files do not already
+exist and the B<DB_CREATE> flag is not specified, the call will fail.
+
+B<DB_NOMMAP>
+
+Not supported by BerkeleyDB.
+
+B<DB_RDONLY>
+
+Opens the database in read-only mode.
+
+B<DB_THREAD>
+
+Not supported by BerkeleyDB.
+
+B<DB_TRUNCATE>
+
+If the database file already exists, remove all the data before
+opening it.
+
+=item -Mode
+
+Determines the file protection when the database is created. Defaults
+to 0666.
+
+=item -Cachesize
+
+=item -Lorder
+
+=item -Pagesize
+
+=item -Env
+
+When working under a Berkeley DB environment, this parameter
+
+Defaults to no environment.
+
+=item -Txn
+
+TODO.
+
+=back
+
+=head1 COMMON DATABASE METHODS
+
+All the database interfaces support the common set of methods defined
+below.
+
+All the methods below return 0 to indicate success.
+
+=head2 $status = $db->db_get($key, $value [, $flags])
+
+Given a key (C<$key>) this method reads the value associated with it
+from the database. If it exists, the value read from the database is
+returned in the C<$value> parameter.
+
+The B<$flags> parameter is optional. If present, it must be set to B<one>
+of the following values:
+
+=over 5
+
+=item B<DB_GET_BOTH>
+
+When the B<DB_GET_BOTH> flag is specified, B<db_get> checks for the
+existence of B<both> the C<$key> B<and> C<$value> in the database.
+
+=item B<DB_SET_RECNO>
+
+TODO.
+
+=back
+
+In addition, the following value may be set by logically OR'ing it into
+the B<$flags> parameter:
+
+=over 5
+
+=item B<DB_RMW>
+
+TODO
+
+=back
+
+
+=head2 $status = $db->db_put($key, $value [, $flags])
+
+Stores a key/value pair in the database.
+
+The B<$flags> parameter is optional. If present it must be set to B<one>
+of the following values:
+
+=over 5
+
+=item B<DB_APPEND>
+
+This flag is only applicable when accessing a B<BerkeleyDB::Recno>
+database.
+
+TODO.
+
+
+=item B<DB_NOOVERWRITE>
+
+If this flag is specified and C<$key> already exists in the database,
+the call to B<db_put> will return B<DB_KEYEXIST>.
+
+=back
+
+=head2 $status = $db->db_del($key [, $flags])
+
+Deletes a key/value pair in the database associated with C<$key>.
+If duplicate keys are enabled in the database, B<db_del> will delete
+B<all> key/value pairs with key C<$key>.
+
+The B<$flags> parameter is optional and is currently unused.
+
+=head2 $status = $db->db_sync()
+
+If any parts of the database are in memory, write them to the database.
+
+=head2 $cursor = $db->db_cursor([$flags])
+
+Creates a cursor object. This is used to access the contents of the
+database sequentially. See L<CURSORS> for details of the methods
+available when working with cursors.
+
+The B<$flags> parameter is optional. If present it must be set to B<one>
+of the following values:
+
+=over 5
+
+=item B<DB_RMW>
+
+TODO.
+
+=back
+
+=head2 ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
+
+TODO
+
+=head2 ($flag, $old_offset, $old_length) = $db->partial_clear() ;
+
+TODO
+
+=head2 $db->byteswapped()
+
+TODO
+
+=head2 $db->type()
+
+Returns the type of the database. The possible return code are B<DB_HASH>
+for a B<BerkeleyDB::Hash> database, B<DB_BTREE> for a B<BerkeleyDB::Btree>
+database and B<DB_RECNO> for a B<BerkeleyDB::Recno> database. This method
+is typically used when a database has been opened with
+B<BerkeleyDB::Unknown>.
+
+=item $ref = $db->db_stat()
+
+Returns a reference to an associative array containing information about
+the database. The keys of the associative array correspond directly to the
+names of the fields defined in the Berkeley DB documentation. For example,
+in the DB documentation, the field B<bt_version> stores the version of the
+Btree database. Assuming you called B<db_stat> on a Btree database the
+equivalent field would be accessed as follows:
+
+ $version = $ref->{'bt_version'} ;
+
+If you are using Berkeley DB 3.x or better, this method will work will
+all database formats. When DB 2.x is used, it only works with
+B<BerkeleyDB::Btree>.
+
+=head2 $status = $db->status()
+
+Returns the status of the last C<$db> method called.
+
+=head2 $status = $db->truncate($count)
+
+Truncates the datatabase and returns the number or records deleted
+in C<$count>.
+
+=head1 CURSORS
+
+A cursor is used whenever you want to access the contents of a database
+in sequential order.
+A cursor object is created with the C<db_cursor>
+
+A cursor object has the following methods available:
+
+=head2 $newcursor = $cursor->c_dup($flags)
+
+Creates a duplicate of C<$cursor>. This method needs Berkeley DB 3.0.x or better.
+
+The C<$flags> parameter is optional and can take the following value:
+
+=over 5
+
+=item DB_POSITION
+
+When present this flag will position the new cursor at the same place as the
+existing cursor.
+
+=back
+
+=head2 $status = $cursor->c_get($key, $value, $flags)
+
+Reads a key/value pair from the database, returning the data in C<$key>
+and C<$value>. The key/value pair actually read is controlled by the
+C<$flags> parameter, which can take B<one> of the following values:
+
+=over 5
+
+=item B<DB_FIRST>
+
+Set the cursor to point to the first key/value pair in the
+database. Return the key/value pair in C<$key> and C<$value>.
+
+=item B<DB_LAST>
+
+Set the cursor to point to the last key/value pair in the database. Return
+the key/value pair in C<$key> and C<$value>.
+
+=item B<DB_NEXT>
+
+If the cursor is already pointing to a key/value pair, it will be
+incremented to point to the next key/value pair and return its contents.
+
+If the cursor isn't initialised, B<DB_NEXT> works just like B<DB_FIRST>.
+
+If the cursor is already positioned at the last key/value pair, B<c_get>
+will return B<DB_NOTFOUND>.
+
+=item B<DB_NEXT_DUP>
+
+This flag is only valid when duplicate keys have been enabled in
+a database.
+If the cursor is already pointing to a key/value pair and the key of
+the next key/value pair is identical, the cursor will be incremented to
+point to it and their contents returned.
+
+=item B<DB_PREV>
+
+If the cursor is already pointing to a key/value pair, it will be
+decremented to point to the previous key/value pair and return its
+contents.
+
+If the cursor isn't initialised, B<DB_PREV> works just like B<DB_LAST>.
+
+If the cursor is already positioned at the first key/value pair, B<c_get>
+will return B<DB_NOTFOUND>.
+
+=item B<DB_CURRENT>
+
+If the cursor has been set to point to a key/value pair, return their
+contents.
+If the key/value pair referenced by the cursor has been deleted, B<c_get>
+will return B<DB_KEYEMPTY>.
+
+=item B<DB_SET>
+
+Set the cursor to point to the key/value pair referenced by B<$key>
+and return the value in B<$value>.
+
+=item B<DB_SET_RANGE>
+
+This flag is a variation on the B<DB_SET> flag. As well as returning
+the value, it also returns the key, via B<$key>.
+When used with a B<BerkeleyDB::Btree> database the key matched by B<c_get>
+will be the shortest key (in length) which is greater than or equal to
+the key supplied, via B<$key>. This allows partial key searches.
+See ??? for an example of how to use this flag.
+
+=item B<DB_GET_BOTH>
+
+Another variation on B<DB_SET>. This one returns both the key and
+the value.
+
+=item B<DB_SET_RECNO>
+
+TODO.
+
+=item B<DB_GET_RECNO>
+
+TODO.
+
+=back
+
+In addition, the following value may be set by logically OR'ing it into
+the B<$flags> parameter:
+
+=over 5
+
+=item B<DB_RMW>
+
+TODO.
+
+=back
+
+=head2 $status = $cursor->c_put($key, $value, $flags)
+
+Stores the key/value pair in the database. The position that the data is
+stored in the database is controlled by the C<$flags> parameter, which
+must take B<one> of the following values:
+
+=over 5
+
+=item B<DB_AFTER>
+
+When used with a Btree or Hash database, a duplicate of the key referenced
+by the current cursor position will be created and the contents of
+B<$value> will be associated with it - B<$key> is ignored.
+The new key/value pair will be stored immediately after the current
+cursor position.
+Obviously the database has to have been opened with B<DB_DUP>.
+
+When used with a Recno ... TODO
+
+
+=item B<DB_BEFORE>
+
+When used with a Btree or Hash database, a duplicate of the key referenced
+by the current cursor position will be created and the contents of
+B<$value> will be associated with it - B<$key> is ignored.
+The new key/value pair will be stored immediately before the current
+cursor position.
+Obviously the database has to have been opened with B<DB_DUP>.
+
+When used with a Recno ... TODO
+
+=item B<DB_CURRENT>
+
+If the cursor has been initialised, replace the value of the key/value
+pair stored in the database with the contents of B<$value>.
+
+=item B<DB_KEYFIRST>
+
+Only valid with a Btree or Hash database. This flag is only really
+used when duplicates are enabled in the database and sorted duplicates
+haven't been specified.
+In this case the key/value pair will be inserted as the first entry in
+the duplicates for the particular key.
+
+=item B<DB_KEYLAST>
+
+Only valid with a Btree or Hash database. This flag is only really
+used when duplicates are enabled in the database and sorted duplicates
+haven't been specified.
+In this case the key/value pair will be inserted as the last entry in
+the duplicates for the particular key.
+
+=back
+
+=head2 $status = $cursor->c_del([$flags])
+
+This method deletes the key/value pair associated with the current cursor
+position. The cursor position will not be changed by this operation, so
+any subsequent cursor operation must first initialise the cursor to
+point to a valid key/value pair.
+
+If the key/value pair associated with the cursor have already been
+deleted, B<c_del> will return B<DB_KEYEMPTY>.
+
+The B<$flags> parameter is not used at present.
+
+=head2 $status = $cursor->c_del($cnt [, $flags])
+
+Stores the number of duplicates at the current cursor position in B<$cnt>.
+
+The B<$flags> parameter is not used at present. This method needs
+Berkeley DB 3.1 or better.
+
+=head2 $status = $cursor->status()
+
+Returns the status of the last cursor method as a dual type.
+
+=head2 Cursor Examples
+
+TODO
+
+Iterating from first to last, then in reverse.
+
+examples of each of the flags.
+
+=head1 JOIN
+
+Join support for BerkeleyDB is in progress. Watch this space.
+
+TODO
+
+=head1 TRANSACTIONS
+
+TODO.
+
+=head1 DBM Filters
+
+A DBM Filter is a piece of code that is be used when you I<always>
+want to make the same transformation to all keys and/or values in a DBM
+database. All of the database classes (BerkeleyDB::Hash,
+BerkeleyDB::Btree and BerkeleyDB::Recno) support DBM Filters.
+
+There are four methods associated with DBM Filters. All work
+identically, and each is used to install (or uninstall) a single DBM
+Filter. Each expects a single parameter, namely a reference to a sub.
+The only difference between them is the place that the filter is
+installed.
+
+To summarise:
+
+=over 5
+
+=item B<filter_store_key>
+
+If a filter has been installed with this method, it will be invoked
+every time you write a key to a DBM database.
+
+=item B<filter_store_value>
+
+If a filter has been installed with this method, it will be invoked
+every time you write a value to a DBM database.
+
+
+=item B<filter_fetch_key>
+
+If a filter has been installed with this method, it will be invoked
+every time you read a key from a DBM database.
+
+=item B<filter_fetch_value>
+
+If a filter has been installed with this method, it will be invoked
+every time you read a value from a DBM database.
+
+=back
+
+You can use any combination of the methods, from none, to all four.
+
+All filter methods return the existing filter, if present, or C<undef>
+in not.
+
+To delete a filter pass C<undef> to it.
+
+=head2 The Filter
+
+When each filter is called by Perl, a local copy of C<$_> will contain
+the key or value to be filtered. Filtering is achieved by modifying
+the contents of C<$_>. The return code from the filter is ignored.
+
+=head2 An Example -- the NULL termination problem.
+
+Consider the following scenario. You have a DBM database that you need
+to share with a third-party C application. The C application assumes
+that I<all> keys and values are NULL terminated. Unfortunately when
+Perl writes to DBM databases it doesn't use NULL termination, so your
+Perl application will have to manage NULL termination itself. When you
+write to the database you will have to use something like this:
+
+ $hash{"$key\0"} = "$value\0" ;
+
+Similarly the NULL needs to be taken into account when you are considering
+the length of existing keys/values.
+
+It would be much better if you could ignore the NULL terminations issue
+in the main application code and have a mechanism that automatically
+added the terminating NULL to all keys and values whenever you write to
+the database and have them removed when you read from the database. As I'm
+sure you have already guessed, this is a problem that DBM Filters can
+fix very easily.
+
+## nullFilter
+
+Hopefully the contents of each of the filters should be
+self-explanatory. Both "fetch" filters remove the terminating NULL,
+and both "store" filters add a terminating NULL.
+
+
+=head2 Another Example -- Key is a C int.
+
+Here is another real-life example. By default, whenever Perl writes to
+a DBM database it always writes the key and value as strings. So when
+you use this:
+
+ $hash{12345} = "something" ;
+
+the key 12345 will get stored in the DBM database as the 5 byte string
+"12345". If you actually want the key to be stored in the DBM database
+as a C int, you will have to use C<pack> when writing, and C<unpack>
+when reading.
+
+Here is a DBM Filter that does it:
+
+## intFilter
+
+This time only two filters have been used -- we only need to manipulate
+the contents of the key, so it wasn't necessary to install any value
+filters.
+
+=head1 Using BerkeleyDB with MLDBM
+
+Both BerkeleyDB::Hash and BerkeleyDB::Btree can be used with the MLDBM
+module. The code fragment below shows how to open associate MLDBM with
+BerkeleyDB::Btree. To use BerkeleyDB::Hash just replace
+BerkeleyDB::Btree with BerkeleyDB::Hash.
+
+ use strict ;
+ use BerkeleyDB ;
+ use MLDBM qw(BerkeleyDB::Btree) ;
+ use Data::Dumper;
+
+ my $filename = 'testmldbm' ;
+ my %o ;
+
+ unlink $filename ;
+ tie %o, 'MLDBM', -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open database '$filename: $!\n";
+
+See the MLDBM documentation for information on how to use the module
+and for details of its limitations.
+
+=head1 EXAMPLES
+
+TODO.
+
+=head1 HINTS & TIPS
+
+=head2 Sharing Databases With C Applications
+
+There is no technical reason why a Berkeley DB database cannot be
+shared by both a Perl and a C application.
+
+The vast majority of problems that are reported in this area boil down
+to the fact that C strings are NULL terminated, whilst Perl strings
+are not. See L<An Example -- the NULL termination problem.> in the DBM
+FILTERS section for a generic way to work around this problem.
+
+
+=head2 The untie Gotcha
+
+TODO
+
+=head1 COMMON QUESTIONS
+
+This section attempts to answer some of the more common questions that
+I get asked.
+
+
+=head2 Relationship with DB_File
+
+Before Berkeley DB 2.x was written there was only one Perl module that
+interfaced to Berkeley DB. That module is called B<DB_File>. Although
+B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only provides
+an interface to the functionality available in Berkeley DB 1.x. That
+means that it doesn't support transactions, locking or any of the other
+new features available in DB 2.x or better.
+
+=head2 How do I store Perl data structures with BerkeleyDB?
+
+See L<Using BerkeleyDB with MLDBM>.
+
+=head1 HISTORY
+
+See the Changes file.
+
+=head1 AVAILABILITY
+
+The most recent version of B<BerkeleyDB> can always be found
+on CPAN (see L<perlmod/CPAN> for details), in the directory
+F<modules/by-module/BerkeleyDB>.
+
+The official web site for Berkeley DB is F<http://www.sleepycat.com>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program
+is free software; you can redistribute it and/or modify it under the
+same terms as Perl itself.
+
+Although B<BerkeleyDB> is covered by the Perl license, the library it
+makes use of, namely Berkeley DB, is not. Berkeley DB has its own
+copyright and its own license. Please take the time to read it.
+
+Here are few words taken from the Berkeley DB FAQ (at
+F<http://www.sleepycat.com>) regarding the license:
+
+ Do I have to license DB to use it in Perl scripts?
+
+ No. The Berkeley DB license requires that software that uses
+ Berkeley DB be freely redistributable. In the case of Perl, that
+ software is Perl, and not your scripts. Any Perl scripts that you
+ write are your property, including scripts that make use of Berkeley
+ DB. Neither the Perl license nor the Berkeley DB license
+ place any restriction on what you may do with them.
+
+If you are in any doubt about the license situation, contact either the
+Berkeley DB authors or the author of BerkeleyDB.
+See L<"AUTHOR"> for details.
+
+
+=head1 AUTHOR
+
+Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt>.
+
+Questions about Berkeley DB may be addressed to E<lt>db@sleepycat.comE<gt>.
+
+=head1 SEE ALSO
+
+perl(1), DB_File, Berkeley DB.
+
+=cut
diff --git a/bdb/perl/BerkeleyDB/BerkeleyDB.xs b/bdb/perl/BerkeleyDB/BerkeleyDB.xs
new file mode 100644
index 00000000000..531b38a655f
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/BerkeleyDB.xs
@@ -0,0 +1,3643 @@
+/*
+
+ BerkeleyDB.xs -- Perl 5 interface to Berkeley DB version 2 & 3
+
+ written by Paul Marquess <Paul.Marquess@btinternet.com>
+
+ All comments/suggestions/problems are welcome
+
+ Copyright (c) 1997-2002 Paul Marquess. All rights reserved.
+ This program is free software; you can redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+ Please refer to the COPYRIGHT section in
+
+ Changes:
+ 0.01 - First Alpha Release
+ 0.02 -
+
+*/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PERL_POLLUTE
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "ppport.h"
+
+
+/* XSUB.h defines a macro called abort */
+/* This clashes with the txn abort method in Berkeley DB 4.x */
+/* This is a problem with ActivePerl (at least) */
+
+#ifdef _WIN32
+# ifdef abort
+# undef abort
+# endif
+# ifdef fopen
+# undef fopen
+# endif
+# ifdef fclose
+# undef fclose
+# endif
+#endif
+
+/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
+ * shortly #included by the <db.h>) __attribute__ to the possibly
+ * already defined __attribute__, for example by GNUC or by Perl. */
+
+#undef __attribute__
+
+#ifdef USE_PERLIO
+# define GetFILEptr(sv) PerlIO_findFILE(IoOFP(sv_2io(sv)))
+#else
+# define GetFILEptr(sv) IoOFP(sv_2io(sv))
+#endif
+
+#include <db.h>
+
+/* Check the version of Berkeley DB */
+
+#ifndef DB_VERSION_MAJOR
+#ifdef HASHMAGIC
+#error db.h is from Berkeley DB 1.x - need at least Berkeley DB 2.6.4
+#else
+#error db.h is not for Berkeley DB at all.
+#endif
+#endif
+
+#if (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6) ||\
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 6 && DB_VERSION_PATCH < 4)
+# error db.h is from Berkeley DB 2.0-2.5 - need at least Berkeley DB 2.6.4
+#endif
+
+
+#if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0)
+# define IS_DB_3_0_x
+#endif
+
+#if DB_VERSION_MAJOR >= 3
+# define AT_LEAST_DB_3
+#endif
+
+#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 1)
+# define AT_LEAST_DB_3_1
+#endif
+
+#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
+# define AT_LEAST_DB_3_2
+#endif
+
+#if DB_VERSION_MAJOR > 3 || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) ||\
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 2 && DB_VERSION_PATCH >= 6)
+# define AT_LEAST_DB_3_2_6
+#endif
+
+#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3)
+# define AT_LEAST_DB_3_3
+#endif
+
+#if DB_VERSION_MAJOR >= 4
+# define AT_LEAST_DB_4
+#endif
+
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
+# define AT_LEAST_DB_4_1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define DBM_FILTERING
+#define STRICT_CLOSE
+/* #define ALLOW_RECNO_OFFSET */
+/* #define TRACE */
+
+#if DB_VERSION_MAJOR == 2 && ! defined(DB_LOCK_DEADLOCK)
+# define DB_LOCK_DEADLOCK EAGAIN
+#endif /* DB_VERSION_MAJOR == 2 */
+
+#if DB_VERSION_MAJOR == 2
+# define DB_QUEUE 4
+#endif /* DB_VERSION_MAJOR == 2 */
+
+#ifdef AT_LEAST_DB_3_2
+# define DB_callback DB * db,
+#else
+# define DB_callback
+#endif
+
+#if DB_VERSION_MAJOR > 2
+typedef struct {
+ int db_lorder;
+ size_t db_cachesize;
+ size_t db_pagesize;
+
+
+ void *(*db_malloc) __P((size_t));
+ int (*dup_compare)
+ __P((DB_callback const DBT *, const DBT *));
+
+ u_int32_t bt_maxkey;
+ u_int32_t bt_minkey;
+ int (*bt_compare)
+ __P((DB_callback const DBT *, const DBT *));
+ size_t (*bt_prefix)
+ __P((DB_callback const DBT *, const DBT *));
+
+ u_int32_t h_ffactor;
+ u_int32_t h_nelem;
+ u_int32_t (*h_hash)
+ __P((DB_callback const void *, u_int32_t));
+
+ int re_pad;
+ int re_delim;
+ u_int32_t re_len;
+ char *re_source;
+
+#define DB_DELIMITER 0x0001
+#define DB_FIXEDLEN 0x0008
+#define DB_PAD 0x0010
+ u_int32_t flags;
+ u_int32_t q_extentsize;
+} DB_INFO ;
+
+#endif /* DB_VERSION_MAJOR > 2 */
+
+typedef struct {
+ int Status ;
+ /* char ErrBuff[1000] ; */
+ SV * ErrPrefix ;
+ FILE * ErrHandle ;
+ DB_ENV * Env ;
+ int open_dbs ;
+ int TxnMgrStatus ;
+ int active ;
+ bool txn_enabled ;
+ } BerkeleyDB_ENV_type ;
+
+
+typedef struct {
+ DBTYPE type ;
+ bool recno_or_queue ;
+ char * filename ;
+ BerkeleyDB_ENV_type * parent_env ;
+ DB * dbp ;
+ SV * compare ;
+ bool in_compare ;
+ SV * dup_compare ;
+ bool in_dup_compare ;
+ SV * prefix ;
+ bool in_prefix ;
+ SV * hash ;
+ bool in_hash ;
+#ifdef AT_LEAST_DB_3_3
+ SV * associated ;
+ bool secondary_db ;
+#endif
+ int Status ;
+ DB_INFO * info ;
+ DBC * cursor ;
+ DB_TXN * txn ;
+ int open_cursors ;
+ u_int32_t partial ;
+ u_int32_t dlen ;
+ u_int32_t doff ;
+ int active ;
+#ifdef ALLOW_RECNO_OFFSET
+ int array_base ;
+#endif
+#ifdef DBM_FILTERING
+ SV * filter_fetch_key ;
+ SV * filter_store_key ;
+ SV * filter_fetch_value ;
+ SV * filter_store_value ;
+ int filtering ;
+#endif
+ } BerkeleyDB_type;
+
+
+typedef struct {
+ DBTYPE type ;
+ bool recno_or_queue ;
+ char * filename ;
+ DB * dbp ;
+ SV * compare ;
+ SV * dup_compare ;
+ SV * prefix ;
+ SV * hash ;
+#ifdef AT_LEAST_DB_3_3
+ SV * associated ;
+ bool secondary_db ;
+#endif
+ int Status ;
+ DB_INFO * info ;
+ DBC * cursor ;
+ DB_TXN * txn ;
+ BerkeleyDB_type * parent_db ;
+ u_int32_t partial ;
+ u_int32_t dlen ;
+ u_int32_t doff ;
+ int active ;
+#ifdef ALLOW_RECNO_OFFSET
+ int array_base ;
+#endif
+#ifdef DBM_FILTERING
+ SV * filter_fetch_key ;
+ SV * filter_store_key ;
+ SV * filter_fetch_value ;
+ SV * filter_store_value ;
+ int filtering ;
+#endif
+ } BerkeleyDB_Cursor_type;
+
+typedef struct {
+ BerkeleyDB_ENV_type * env ;
+ } BerkeleyDB_TxnMgr_type ;
+
+#if 1
+typedef struct {
+ int Status ;
+ DB_TXN * txn ;
+ int active ;
+ } BerkeleyDB_Txn_type ;
+#else
+typedef DB_TXN BerkeleyDB_Txn_type ;
+#endif
+
+typedef BerkeleyDB_ENV_type * BerkeleyDB__Env ;
+typedef BerkeleyDB_ENV_type * BerkeleyDB__Env__Raw ;
+typedef BerkeleyDB_ENV_type * BerkeleyDB__Env__Inner ;
+typedef BerkeleyDB_type * BerkeleyDB ;
+typedef void * BerkeleyDB__Raw ;
+typedef BerkeleyDB_type * BerkeleyDB__Common ;
+typedef BerkeleyDB_type * BerkeleyDB__Common__Raw ;
+typedef BerkeleyDB_type * BerkeleyDB__Common__Inner ;
+typedef BerkeleyDB_type * BerkeleyDB__Hash ;
+typedef BerkeleyDB_type * BerkeleyDB__Hash__Raw ;
+typedef BerkeleyDB_type * BerkeleyDB__Btree ;
+typedef BerkeleyDB_type * BerkeleyDB__Btree__Raw ;
+typedef BerkeleyDB_type * BerkeleyDB__Recno ;
+typedef BerkeleyDB_type * BerkeleyDB__Recno__Raw ;
+typedef BerkeleyDB_type * BerkeleyDB__Queue ;
+typedef BerkeleyDB_type * BerkeleyDB__Queue__Raw ;
+typedef BerkeleyDB_Cursor_type BerkeleyDB__Cursor_type ;
+typedef BerkeleyDB_Cursor_type * BerkeleyDB__Cursor ;
+typedef BerkeleyDB_Cursor_type * BerkeleyDB__Cursor__Raw ;
+typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr ;
+typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr__Raw ;
+typedef BerkeleyDB_TxnMgr_type * BerkeleyDB__TxnMgr__Inner ;
+typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn ;
+typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn__Raw ;
+typedef BerkeleyDB_Txn_type * BerkeleyDB__Txn__Inner ;
+#if 0
+typedef DB_LOG * BerkeleyDB__Log ;
+typedef DB_LOCKTAB * BerkeleyDB__Lock ;
+#endif
+typedef DBT DBTKEY ;
+typedef DBT DBT_OPT ;
+typedef DBT DBT_B ;
+typedef DBT DBTKEY_B ;
+typedef DBT DBTVALUE ;
+typedef void * PV_or_NULL ;
+typedef PerlIO * IO_or_NULL ;
+typedef int DualType ;
+
+static void
+hash_delete(char * hash, char * key);
+
+#ifdef TRACE
+# define Trace(x) printf x
+#else
+# define Trace(x)
+#endif
+
+#ifdef ALLOW_RECNO_OFFSET
+# define RECNO_BASE db->array_base
+#else
+# define RECNO_BASE 1
+#endif
+
+#if DB_VERSION_MAJOR == 2
+# define flagSet_DB2(i, f) i |= f
+#else
+# define flagSet_DB2(i, f)
+#endif
+
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
+# define flagSet(bitmask) (flags & (bitmask))
+#else
+# define flagSet(bitmask) ((flags & DB_OPFLAGS_MASK) == (bitmask))
+#endif
+
+#if DB_VERSION_MAJOR == 2
+# define BackRef internal
+#else
+# if DB_VERSION_MAJOR == 3 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0)
+# define BackRef cj_internal
+# else
+# define BackRef api_internal
+# endif
+#endif
+
+#define ERR_BUFF "BerkeleyDB::Error"
+
+#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
+ Zero(to,1,typ))
+
+#define DBT_clear(x) Zero(&x, 1, DBT) ;
+
+#if 1
+#define getInnerObject(x) (*av_fetch((AV*)SvRV(x), 0, FALSE))
+#else
+#define getInnerObject(x) ((SV*)SvRV(sv))
+#endif
+
+#define my_sv_setpvn(sv, d, s) (s ? sv_setpvn(sv, d, s) : sv_setpv(sv, "") )
+
+#define SetValue_iv(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
+ i = SvIV(sv)
+#define SetValue_io(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
+ i = GetFILEptr(sv)
+#define SetValue_sv(i, k) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
+ i = sv
+#define SetValue_pv(i, k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
+ i = (t)SvPV(sv,PL_na)
+#define SetValue_pvx(i, k, t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) \
+ i = (t)SvPVX(sv)
+#define SetValue_ov(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\
+ IV tmp = SvIV(getInnerObject(sv)) ; \
+ i = INT2PTR(t, tmp) ; \
+ }
+
+#define SetValue_ovx(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\
+ HV * hv = (HV *)GetInternalObject(sv); \
+ SV ** svp = hv_fetch(hv, "db", 2, FALSE);\
+ IV tmp = SvIV(*svp); \
+ i = INT2PTR(t, tmp) ; \
+ }
+
+#define SetValue_ovX(i,k,t) if ((sv = readHash(hash, k)) && sv != &PL_sv_undef) {\
+ IV tmp = SvIV(GetInternalObject(sv));\
+ i = INT2PTR(t, tmp) ; \
+ }
+
+#define LastDBerror DB_RUNRECOVERY
+
+#define setDUALerrno(var, err) \
+ sv_setnv(var, (double)err) ; \
+ sv_setpv(var, ((err) ? db_strerror(err) : "")) ;\
+ SvNOK_on(var);
+
+#define OutputValue(arg, name) \
+ { if (RETVAL == 0) { \
+ my_sv_setpvn(arg, name.data, name.size) ; \
+ DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
+ } \
+ }
+
+#define OutputValue_B(arg, name) \
+ { if (RETVAL == 0) { \
+ if (db->type == DB_BTREE && \
+ flagSet(DB_GET_RECNO)){ \
+ sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \
+ } \
+ else { \
+ my_sv_setpvn(arg, name.data, name.size) ; \
+ } \
+ DBM_ckFilter(arg, filter_fetch_value, "filter_fetch_value"); \
+ } \
+ }
+
+#define OutputKey(arg, name) \
+ { if (RETVAL == 0) \
+ { \
+ if (!db->recno_or_queue) { \
+ my_sv_setpvn(arg, name.data, name.size); \
+ } \
+ else \
+ sv_setiv(arg, (I32)*(I32*)name.data - RECNO_BASE); \
+ DBM_ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \
+ } \
+ }
+
+#define OutputKey_B(arg, name) \
+ { if (RETVAL == 0) \
+ { \
+ if (db->recno_or_queue || \
+ (db->type == DB_BTREE && \
+ flagSet(DB_GET_RECNO))){ \
+ sv_setiv(arg, (I32)(*(I32*)name.data) - RECNO_BASE); \
+ } \
+ else { \
+ my_sv_setpvn(arg, name.data, name.size); \
+ } \
+ DBM_ckFilter(arg, filter_fetch_key, "filter_fetch_key") ; \
+ } \
+ }
+
+#define SetPartial(data,db) \
+ data.flags = db->partial ; \
+ data.dlen = db->dlen ; \
+ data.doff = db->doff ;
+
+#define ckActive(active, type) \
+ { \
+ if (!active) \
+ softCrash("%s is already closed", type) ; \
+ }
+
+#define ckActive_Environment(a) ckActive(a, "Environment")
+#define ckActive_TxnMgr(a) ckActive(a, "Transaction Manager")
+#define ckActive_Transaction(a) ckActive(a, "Transaction")
+#define ckActive_Database(a) ckActive(a, "Database")
+#define ckActive_Cursor(a) ckActive(a, "Cursor")
+
+/* Internal Global Data */
+static db_recno_t Value ;
+static db_recno_t zero = 0 ;
+static BerkeleyDB CurrentDB ;
+
+static DBTKEY empty ;
+#if 0
+static char ErrBuff[1000] ;
+#endif
+
+#ifdef AT_LEAST_DB_3_3
+# if PERL_REVISION == 5 && PERL_VERSION <= 4
+
+/* saferealloc in perl5.004 will croak if it is given a NULL pointer*/
+void *
+MyRealloc(void * ptr, size_t size)
+{
+ if (ptr == NULL )
+ return safemalloc(size) ;
+ else
+ return saferealloc(ptr, size) ;
+}
+
+# else
+# define MyRealloc saferealloc
+# endif
+#endif
+
+static char *
+my_strdup(const char *s)
+{
+ if (s == NULL)
+ return NULL ;
+
+ {
+ MEM_SIZE l = strlen(s);
+ char *s1 = (char *)safemalloc(l);
+
+ Copy(s, s1, (MEM_SIZE)l, char);
+ return s1;
+ }
+}
+
+#if DB_VERSION_MAJOR == 2
+static char *
+db_strerror(int err)
+{
+ if (err == 0)
+ return "" ;
+
+ if (err > 0)
+ return Strerror(err) ;
+
+ switch (err) {
+ case DB_INCOMPLETE:
+ return ("DB_INCOMPLETE: Sync was unable to complete");
+ case DB_KEYEMPTY:
+ return ("DB_KEYEMPTY: Non-existent key/data pair");
+ case DB_KEYEXIST:
+ return ("DB_KEYEXIST: Key/data pair already exists");
+ case DB_LOCK_DEADLOCK:
+ return (
+ "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
+ case DB_LOCK_NOTGRANTED:
+ return ("DB_LOCK_NOTGRANTED: Lock not granted");
+ case DB_LOCK_NOTHELD:
+ return ("DB_LOCK_NOTHELD: Lock not held by locker");
+ case DB_NOTFOUND:
+ return ("DB_NOTFOUND: No matching key/data pair found");
+ case DB_RUNRECOVERY:
+ return ("DB_RUNRECOVERY: Fatal error, run database recovery");
+ default:
+ return "Unknown Error" ;
+
+ }
+}
+#endif /* DB_VERSION_MAJOR == 2 */
+
+#ifdef TRACE
+#if DB_VERSION_MAJOR > 2
+static char *
+my_db_strerror(int err)
+{
+ static char buffer[1000] ;
+ SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
+ sprintf(buffer, "%d: %s", err, db_strerror(err)) ;
+ if (err && sv) {
+ strcat(buffer, ", ") ;
+ strcat(buffer, SvPVX(sv)) ;
+ }
+ return buffer;
+}
+#endif
+#endif
+
+static void
+close_everything(void)
+{
+ dTHR;
+ Trace(("close_everything\n")) ;
+ /* Abort All Transactions */
+ {
+ BerkeleyDB__Txn__Raw tid ;
+ HE * he ;
+ I32 len ;
+ HV * hv = perl_get_hv("BerkeleyDB::Term::Txn", TRUE);
+ int all = 0 ;
+ int closed = 0 ;
+ (void)hv_iterinit(hv) ;
+ Trace(("BerkeleyDB::Term::close_all_txns dirty=%d\n", PL_dirty)) ;
+ while ( (he = hv_iternext(hv)) ) {
+ tid = * (BerkeleyDB__Txn__Raw *) hv_iterkey(he, &len) ;
+ Trace((" Aborting Transaction [%d] in [%d] Active [%d]\n", tid->txn, tid, tid->active));
+ if (tid->active) {
+#ifdef AT_LEAST_DB_4
+ tid->txn->abort(tid->txn) ;
+#else
+ txn_abort(tid->txn);
+#endif
+ ++ closed ;
+ }
+ tid->active = FALSE ;
+ ++ all ;
+ }
+ Trace(("End of BerkeleyDB::Term::close_all_txns aborted %d of %d transactios\n",closed, all)) ;
+ }
+
+ /* Close All Cursors */
+ {
+ BerkeleyDB__Cursor db ;
+ HE * he ;
+ I32 len ;
+ HV * hv = perl_get_hv("BerkeleyDB::Term::Cursor", TRUE);
+ int all = 0 ;
+ int closed = 0 ;
+ (void) hv_iterinit(hv) ;
+ Trace(("BerkeleyDB::Term::close_all_cursors \n")) ;
+ while ( (he = hv_iternext(hv)) ) {
+ db = * (BerkeleyDB__Cursor*) hv_iterkey(he, &len) ;
+ Trace((" Closing Cursor [%d] in [%d] Active [%d]\n", db->cursor, db, db->active));
+ if (db->active) {
+ ((db->cursor)->c_close)(db->cursor) ;
+ ++ closed ;
+ }
+ db->active = FALSE ;
+ ++ all ;
+ }
+ Trace(("End of BerkeleyDB::Term::close_all_cursors closed %d of %d cursors\n",closed, all)) ;
+ }
+
+ /* Close All Databases */
+ {
+ BerkeleyDB db ;
+ HE * he ;
+ I32 len ;
+ HV * hv = perl_get_hv("BerkeleyDB::Term::Db", TRUE);
+ int all = 0 ;
+ int closed = 0 ;
+ (void)hv_iterinit(hv) ;
+ Trace(("BerkeleyDB::Term::close_all_dbs\n" )) ;
+ while ( (he = hv_iternext(hv)) ) {
+ db = * (BerkeleyDB*) hv_iterkey(he, &len) ;
+ Trace((" Closing Database [%d] in [%d] Active [%d]\n", db->dbp, db, db->active));
+ if (db->active) {
+ (db->dbp->close)(db->dbp, 0) ;
+ ++ closed ;
+ }
+ db->active = FALSE ;
+ ++ all ;
+ }
+ Trace(("End of BerkeleyDB::Term::close_all_dbs closed %d of %d dbs\n",closed, all)) ;
+ }
+
+ /* Close All Environments */
+ {
+ BerkeleyDB__Env env ;
+ HE * he ;
+ I32 len ;
+ HV * hv = perl_get_hv("BerkeleyDB::Term::Env", TRUE);
+ int all = 0 ;
+ int closed = 0 ;
+ (void)hv_iterinit(hv) ;
+ Trace(("BerkeleyDB::Term::close_all_envs\n")) ;
+ while ( (he = hv_iternext(hv)) ) {
+ env = * (BerkeleyDB__Env*) hv_iterkey(he, &len) ;
+ Trace((" Closing Environment [%d] in [%d] Active [%d]\n", env->Env, env, env->active));
+ if (env->active) {
+#if DB_VERSION_MAJOR == 2
+ db_appexit(env->Env) ;
+#else
+ (env->Env->close)(env->Env, 0) ;
+#endif
+ ++ closed ;
+ }
+ env->active = FALSE ;
+ ++ all ;
+ }
+ Trace(("End of BerkeleyDB::Term::close_all_envs closed %d of %d dbs\n",closed, all)) ;
+ }
+
+ Trace(("end close_everything\n")) ;
+
+}
+
+static void
+destroyDB(BerkeleyDB db)
+{
+ dTHR;
+ if (! PL_dirty && db->active) {
+ -- db->open_cursors ;
+ ((db->dbp)->close)(db->dbp, 0) ;
+ }
+ if (db->hash)
+ SvREFCNT_dec(db->hash) ;
+ if (db->compare)
+ SvREFCNT_dec(db->compare) ;
+ if (db->dup_compare)
+ SvREFCNT_dec(db->dup_compare) ;
+#ifdef AT_LEAST_DB_3_3
+ if (db->associated && !db->secondary_db)
+ SvREFCNT_dec(db->associated) ;
+#endif
+ if (db->prefix)
+ SvREFCNT_dec(db->prefix) ;
+#ifdef DBM_FILTERING
+ if (db->filter_fetch_key)
+ SvREFCNT_dec(db->filter_fetch_key) ;
+ if (db->filter_store_key)
+ SvREFCNT_dec(db->filter_store_key) ;
+ if (db->filter_fetch_value)
+ SvREFCNT_dec(db->filter_fetch_value) ;
+ if (db->filter_store_value)
+ SvREFCNT_dec(db->filter_store_value) ;
+#endif
+ hash_delete("BerkeleyDB::Term::Db", (char *)db) ;
+ if (db->filename)
+ Safefree(db->filename) ;
+ Safefree(db) ;
+}
+
+static int
+softCrash(const char *pat, ...)
+{
+ char buffer1 [500] ;
+ char buffer2 [500] ;
+ va_list args;
+ va_start(args, pat);
+
+ Trace(("softCrash: %s\n", pat)) ;
+
+#define ABORT_PREFIX "BerkeleyDB Aborting: "
+
+ /* buffer = (char*) safemalloc(strlen(pat) + strlen(ABORT_PREFIX) + 1) ; */
+ strcpy(buffer1, ABORT_PREFIX) ;
+ strcat(buffer1, pat) ;
+
+ vsprintf(buffer2, buffer1, args) ;
+
+ croak(buffer2);
+
+ /* NOTREACHED */
+ va_end(args);
+ return 1 ;
+}
+
+
+static I32
+GetArrayLength(BerkeleyDB db)
+{
+ DBT key ;
+ DBT value ;
+ int RETVAL = 0 ;
+ DBC * cursor ;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+ if ( ((db->dbp)->cursor)(db->dbp, db->txn, &cursor) == 0 )
+#else
+ if ( ((db->dbp)->cursor)(db->dbp, db->txn, &cursor, 0) == 0 )
+#endif
+ {
+ RETVAL = cursor->c_get(cursor, &key, &value, DB_LAST) ;
+ if (RETVAL == 0)
+ RETVAL = *(I32 *)key.data ;
+ else /* No key means empty file */
+ RETVAL = 0 ;
+ cursor->c_close(cursor) ;
+ }
+
+ Trace(("GetArrayLength got %d\n", RETVAL)) ;
+ return ((I32)RETVAL) ;
+}
+
+#if 0
+
+#define GetRecnoKey(db, value) _GetRecnoKey(db, value)
+
+static db_recno_t
+_GetRecnoKey(BerkeleyDB db, I32 value)
+{
+ Trace(("GetRecnoKey start value = %d\n", value)) ;
+ if (db->recno_or_queue && value < 0) {
+ /* Get the length of the array */
+ I32 length = GetArrayLength(db) ;
+
+ /* check for attempt to write before start of array */
+ if (length + value + RECNO_BASE <= 0)
+ softCrash("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
+
+ value = length + value + RECNO_BASE ;
+ }
+ else
+ ++ value ;
+
+ Trace(("GetRecnoKey end value = %d\n", value)) ;
+
+ return value ;
+}
+
+#else /* ! 0 */
+
+#if 0
+#ifdef ALLOW_RECNO_OFFSET
+#define GetRecnoKey(db, value) _GetRecnoKey(db, value)
+
+static db_recno_t
+_GetRecnoKey(BerkeleyDB db, I32 value)
+{
+ if (value + RECNO_BASE < 1)
+ softCrash("key value %d < base (%d)", (value), RECNO_BASE?0:1) ;
+ return value + RECNO_BASE ;
+}
+
+#else
+#endif /* ALLOW_RECNO_OFFSET */
+#endif /* 0 */
+
+#define GetRecnoKey(db, value) ((value) + RECNO_BASE )
+
+#endif /* 0 */
+
+#if 0
+static SV *
+GetInternalObject(SV * sv)
+{
+ SV * info = (SV*) NULL ;
+ SV * s ;
+ MAGIC * mg ;
+
+ Trace(("in GetInternalObject %d\n", sv)) ;
+ if (sv == NULL || !SvROK(sv))
+ return NULL ;
+
+ s = SvRV(sv) ;
+ if (SvMAGICAL(s))
+ {
+ if (SvTYPE(s) == SVt_PVHV || SvTYPE(s) == SVt_PVAV)
+ mg = mg_find(s, 'P') ;
+ else
+ mg = mg_find(s, 'q') ;
+
+ /* all this testing is probably overkill, but till I know more
+ about global destruction it stays.
+ */
+ /* if (mg && mg->mg_obj && SvRV(mg->mg_obj) && SvPVX(SvRV(mg->mg_obj))) */
+ if (mg && mg->mg_obj && SvRV(mg->mg_obj) )
+ info = SvRV(mg->mg_obj) ;
+ else
+ info = s ;
+ }
+
+ Trace(("end of GetInternalObject %d\n", info)) ;
+ return info ;
+}
+#endif
+
+static int
+btree_compare(DB_callback const DBT * key1, const DBT * key2 )
+{
+ dSP ;
+ char * data1, * data2 ;
+ int retval ;
+ int count ;
+ BerkeleyDB keepDB = CurrentDB ;
+
+ data1 = (char*) key1->data ;
+ data2 = (char*) key2->data ;
+
+#ifndef newSVpvn
+ /* As newSVpv will assume that the data pointer is a null terminated C
+ string if the size parameter is 0, make sure that data points to an
+ empty string if the length is 0
+ */
+ if (key1->size == 0)
+ data1 = "" ;
+ if (key2->size == 0)
+ data2 = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+ EXTEND(SP,2) ;
+ PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
+ PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
+ PUTBACK ;
+
+ count = perl_call_sv(CurrentDB->compare, G_SCALAR);
+
+ SPAGAIN ;
+
+ if (count != 1)
+ softCrash ("in btree_compare - expected 1 return value from compare sub, got %d", count) ;
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+ CurrentDB = keepDB ;
+ return (retval) ;
+
+}
+
+static int
+dup_compare(DB_callback const DBT * key1, const DBT * key2 )
+{
+ dSP ;
+ char * data1, * data2 ;
+ int retval ;
+ int count ;
+ BerkeleyDB keepDB = CurrentDB ;
+
+ Trace(("In dup_compare \n")) ;
+ if (!CurrentDB)
+ softCrash("Internal Error - No CurrentDB in dup_compare") ;
+ if (CurrentDB->dup_compare == NULL)
+ softCrash("in dup_compare: no callback specified for database '%s'", CurrentDB->filename) ;
+
+ data1 = (char*) key1->data ;
+ data2 = (char*) key2->data ;
+
+#ifndef newSVpvn
+ /* As newSVpv will assume that the data pointer is a null terminated C
+ string if the size parameter is 0, make sure that data points to an
+ empty string if the length is 0
+ */
+ if (key1->size == 0)
+ data1 = "" ;
+ if (key2->size == 0)
+ data2 = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+ EXTEND(SP,2) ;
+ PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
+ PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
+ PUTBACK ;
+
+ count = perl_call_sv(CurrentDB->dup_compare, G_SCALAR);
+
+ SPAGAIN ;
+
+ if (count != 1)
+ softCrash ("dup_compare: expected 1 return value from compare sub, got %d", count) ;
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+ CurrentDB = keepDB ;
+ return (retval) ;
+
+}
+
+static size_t
+btree_prefix(DB_callback const DBT * key1, const DBT * key2 )
+{
+ dSP ;
+ char * data1, * data2 ;
+ int retval ;
+ int count ;
+ BerkeleyDB keepDB = CurrentDB ;
+
+ data1 = (char*) key1->data ;
+ data2 = (char*) key2->data ;
+
+#ifndef newSVpvn
+ /* As newSVpv will assume that the data pointer is a null terminated C
+ string if the size parameter is 0, make sure that data points to an
+ empty string if the length is 0
+ */
+ if (key1->size == 0)
+ data1 = "" ;
+ if (key2->size == 0)
+ data2 = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+ EXTEND(SP,2) ;
+ PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
+ PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
+ PUTBACK ;
+
+ count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
+
+ SPAGAIN ;
+
+ if (count != 1)
+ softCrash ("btree_prefix: expected 1 return value from prefix sub, got %d", count) ;
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+ CurrentDB = keepDB ;
+
+ return (retval) ;
+}
+
+static u_int32_t
+hash_cb(DB_callback const void * data, u_int32_t size)
+{
+ dSP ;
+ int retval ;
+ int count ;
+ BerkeleyDB keepDB = CurrentDB ;
+
+#ifndef newSVpvn
+ if (size == 0)
+ data = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+
+ XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
+ PUTBACK ;
+
+ count = perl_call_sv(CurrentDB->hash, G_SCALAR);
+
+ SPAGAIN ;
+
+ if (count != 1)
+ softCrash ("hash_cb: expected 1 return value from hash sub, got %d", count) ;
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+ CurrentDB = keepDB ;
+
+ return (retval) ;
+}
+
+#ifdef AT_LEAST_DB_3_3
+
+static int
+associate_cb(DB_callback const DBT * pkey, const DBT * pdata, DBT * skey)
+{
+ dSP ;
+ char * pk_dat, * pd_dat, *sk_dat ;
+ int retval ;
+ int count ;
+ SV * skey_SV ;
+
+ Trace(("In associate_cb \n")) ;
+ if (((BerkeleyDB)db->BackRef)->associated == NULL){
+ Trace(("No Callback registered\n")) ;
+ return EINVAL ;
+ }
+
+ skey_SV = newSVpv("",0);
+
+
+ pk_dat = (char*) pkey->data ;
+ pd_dat = (char*) pdata->data ;
+
+#ifndef newSVpvn
+ /* As newSVpv will assume that the data pointer is a null terminated C
+ string if the size parameter is 0, make sure that data points to an
+ empty string if the length is 0
+ */
+ if (pkey->size == 0)
+ pk_dat = "" ;
+ if (pdata->size == 0)
+ pd_dat = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+ EXTEND(SP,2) ;
+ PUSHs(sv_2mortal(newSVpvn(pk_dat,pkey->size)));
+ PUSHs(sv_2mortal(newSVpvn(pd_dat,pdata->size)));
+ PUSHs(sv_2mortal(skey_SV));
+ PUTBACK ;
+
+ Trace(("calling associated cb\n"));
+ count = perl_call_sv(((BerkeleyDB)db->BackRef)->associated, G_SCALAR);
+ Trace(("called associated cb\n"));
+
+ SPAGAIN ;
+
+ if (count != 1)
+ softCrash ("associate: expected 1 return value from prefix sub, got %d", count) ;
+
+ retval = POPi ;
+
+ PUTBACK ;
+
+ /* retrieve the secondary key */
+ DBT_clear(*skey);
+ skey->flags = DB_DBT_APPMALLOC;
+ skey->size = SvCUR(skey_SV);
+ skey->data = (char*)safemalloc(skey->size);
+ memcpy(skey->data, SvPVX(skey_SV), skey->size);
+ Trace(("key is %d -- %.*s\n", skey->size, skey->size, skey->data));
+
+ FREETMPS ;
+ LEAVE ;
+
+ return (retval) ;
+}
+
+#endif /* AT_LEAST_DB_3_3 */
+
+static void
+db_errcall_cb(const char * db_errpfx, char * buffer)
+{
+#if 0
+
+ if (db_errpfx == NULL)
+ db_errpfx = "" ;
+ if (buffer == NULL )
+ buffer = "" ;
+ ErrBuff[0] = '\0';
+ if (strlen(db_errpfx) + strlen(buffer) + 3 <= 1000) {
+ if (*db_errpfx != '\0') {
+ strcat(ErrBuff, db_errpfx) ;
+ strcat(ErrBuff, ": ") ;
+ }
+ strcat(ErrBuff, buffer) ;
+ }
+
+#endif
+
+ SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
+ if (sv) {
+ if (db_errpfx)
+ sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
+ else
+ sv_setpv(sv, buffer) ;
+ }
+}
+
+static SV *
+readHash(HV * hash, char * key)
+{
+ SV ** svp;
+ svp = hv_fetch(hash, key, strlen(key), FALSE);
+ if (svp && SvOK(*svp))
+ return *svp ;
+ return NULL ;
+}
+
+static void
+hash_delete(char * hash, char * key)
+{
+ HV * hv = perl_get_hv(hash, TRUE);
+ (void) hv_delete(hv, (char*)&key, sizeof(key), G_DISCARD);
+}
+
+static void
+hash_store_iv(char * hash, char * key, IV value)
+{
+ HV * hv = perl_get_hv(hash, TRUE);
+ (void)hv_store(hv, (char*)&key, sizeof(key), newSViv(value), 0);
+ /* printf("hv_store returned %d\n", ret) ; */
+}
+
+static void
+hv_store_iv(HV * hash, char * key, IV value)
+{
+ hv_store(hash, key, strlen(key), newSViv(value), 0);
+}
+
+static BerkeleyDB
+my_db_open(
+ BerkeleyDB db ,
+ SV * ref,
+ SV * ref_dbenv ,
+ BerkeleyDB__Env dbenv ,
+ BerkeleyDB__Txn txn,
+ const char * file,
+ const char * subname,
+ DBTYPE type,
+ int flags,
+ int mode,
+ DB_INFO * info
+ )
+{
+ DB_ENV * env = NULL ;
+ BerkeleyDB RETVAL = NULL ;
+ DB * dbp ;
+ int Status ;
+ DB_TXN* txnid = NULL ;
+
+ Trace(("_db_open(dbenv[%p] ref_dbenv [%p] file[%s] subname [%s] type[%d] flags[%d] mode[%d]\n",
+ dbenv, ref_dbenv, file, subname, type, flags, mode)) ;
+
+ CurrentDB = db ;
+ if (dbenv)
+ env = dbenv->Env ;
+
+ if (txn)
+ txnid = txn->txn;
+
+ Trace(("_db_open(dbenv[%p] ref_dbenv [%p] txn [%p] file[%s] subname [%s] type[%d] flags[%d] mode[%d]\n",
+ dbenv, ref_dbenv, txn, file, subname, type, flags, mode)) ;
+
+#if DB_VERSION_MAJOR == 2
+ if (subname)
+ softCrash("Subname needs Berkeley DB 3 or better") ;
+#endif
+
+#if DB_VERSION_MAJOR > 2
+ Status = db_create(&dbp, env, 0) ;
+ Trace(("db_create returned %s\n", my_db_strerror(Status))) ;
+ if (Status)
+ return RETVAL ;
+
+#ifdef AT_LEAST_DB_3_3
+ if (! env) {
+ dbp->set_alloc(dbp, safemalloc, MyRealloc, safefree) ;
+ dbp->set_errcall(dbp, db_errcall_cb) ;
+ }
+#endif
+
+ if (info->re_source) {
+ Status = dbp->set_re_source(dbp, info->re_source) ;
+ Trace(("set_re_source [%s] returned %s\n",
+ info->re_source, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->db_cachesize) {
+ Status = dbp->set_cachesize(dbp, 0, info->db_cachesize, 0) ;
+ Trace(("set_cachesize [%d] returned %s\n",
+ info->db_cachesize, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->db_lorder) {
+ Status = dbp->set_lorder(dbp, info->db_lorder) ;
+ Trace(("set_lorder [%d] returned %s\n",
+ info->db_lorder, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->db_pagesize) {
+ Status = dbp->set_pagesize(dbp, info->db_pagesize) ;
+ Trace(("set_pagesize [%d] returned %s\n",
+ info->db_pagesize, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->h_ffactor) {
+ Status = dbp->set_h_ffactor(dbp, info->h_ffactor) ;
+ Trace(("set_h_ffactor [%d] returned %s\n",
+ info->h_ffactor, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->h_nelem) {
+ Status = dbp->set_h_nelem(dbp, info->h_nelem) ;
+ Trace(("set_h_nelem [%d] returned %s\n",
+ info->h_nelem, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->bt_minkey) {
+ Status = dbp->set_bt_minkey(dbp, info->bt_minkey) ;
+ Trace(("set_bt_minkey [%d] returned %s\n",
+ info->bt_minkey, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->bt_compare) {
+ Status = dbp->set_bt_compare(dbp, info->bt_compare) ;
+ Trace(("set_bt_compare [%p] returned %s\n",
+ info->bt_compare, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->h_hash) {
+ Status = dbp->set_h_hash(dbp, info->h_hash) ;
+ Trace(("set_h_hash [%d] returned %s\n",
+ info->h_hash, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->dup_compare) {
+ Status = dbp->set_dup_compare(dbp, info->dup_compare) ;
+ Trace(("set_dup_compare [%d] returned %s\n",
+ info->dup_compare, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->bt_prefix) {
+ Status = dbp->set_bt_prefix(dbp, info->bt_prefix) ;
+ Trace(("set_bt_prefix [%d] returned %s\n",
+ info->bt_prefix, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->re_len) {
+ Status = dbp->set_re_len(dbp, info->re_len) ;
+ Trace(("set_re_len [%d] returned %s\n",
+ info->re_len, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->re_delim) {
+ Status = dbp->set_re_delim(dbp, info->re_delim) ;
+ Trace(("set_re_delim [%d] returned %s\n",
+ info->re_delim, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->re_pad) {
+ Status = dbp->set_re_pad(dbp, info->re_pad) ;
+ Trace(("set_re_pad [%d] returned %s\n",
+ info->re_pad, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->flags) {
+ Status = dbp->set_flags(dbp, info->flags) ;
+ Trace(("set_flags [%d] returned %s\n",
+ info->flags, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+ }
+
+ if (info->q_extentsize) {
+#ifdef AT_LEAST_DB_3_2
+ Status = dbp->set_q_extentsize(dbp, info->q_extentsize) ;
+ Trace(("set_flags [%d] returned %s\n",
+ info->flags, my_db_strerror(Status)));
+ if (Status)
+ return RETVAL ;
+#else
+ softCrash("-ExtentSize needs at least Berkeley DB 3.2.x") ;
+#endif
+ }
+
+#ifdef AT_LEAST_DB_4_1
+ if ((Status = (dbp->open)(dbp, txnid, file, subname, type, flags, mode)) == 0) {
+#else
+ if ((Status = (dbp->open)(dbp, file, subname, type, flags, mode)) == 0) {
+#endif /* AT_LEAST_DB_4_1 */
+#else /* DB_VERSION_MAJOR == 2 */
+ if ((Status = db_open(file, type, flags, mode, env, info, &dbp)) == 0) {
+#endif /* DB_VERSION_MAJOR == 2 */
+
+ Trace(("db_opened ok\n"));
+#ifdef AT_LEAST_DB_3_3
+ dbp->BackRef = db;
+#endif
+ RETVAL = db ;
+ RETVAL->dbp = dbp ;
+ RETVAL->txn = txnid ;
+#if DB_VERSION_MAJOR == 2
+ RETVAL->type = dbp->type ;
+#else /* DB_VERSION_MAJOR > 2 */
+#ifdef AT_LEAST_DB_3_3
+ dbp->get_type(dbp, &RETVAL->type) ;
+#else /* DB 3.0 -> 3.2 */
+ RETVAL->type = dbp->get_type(dbp) ;
+#endif
+#endif /* DB_VERSION_MAJOR > 2 */
+ RETVAL->recno_or_queue = (RETVAL->type == DB_RECNO ||
+ RETVAL->type == DB_QUEUE) ;
+ RETVAL->filename = my_strdup(file) ;
+ RETVAL->Status = Status ;
+ RETVAL->active = TRUE ;
+ hash_store_iv("BerkeleyDB::Term::Db", (char *)RETVAL, 1) ;
+ Trace((" storing %p %p in BerkeleyDB::Term::Db\n", RETVAL, dbp)) ;
+ if (dbenv) {
+ RETVAL->parent_env = dbenv ;
+ dbenv->Status = Status ;
+ ++ dbenv->open_dbs ;
+ }
+ }
+ else {
+#if DB_VERSION_MAJOR > 2
+ (dbp->close)(dbp, 0) ;
+#endif
+ destroyDB(db) ;
+ Trace(("db open returned %s\n", my_db_strerror(Status))) ;
+ }
+
+ return RETVAL ;
+}
+
+
+#include "constants.h"
+
+MODULE = BerkeleyDB PACKAGE = BerkeleyDB PREFIX = env_
+
+INCLUDE: constants.xs
+
+#define env_db_version(maj, min, patch) db_version(&maj, &min, &patch)
+char *
+env_db_version(maj, min, patch)
+ int maj
+ int min
+ int patch
+ OUTPUT:
+ RETVAL
+ maj
+ min
+ patch
+
+int
+db_value_set(value, which)
+ int value
+ int which
+ NOT_IMPLEMENTED_YET
+
+
+DualType
+_db_remove(ref)
+ SV * ref
+ CODE:
+ {
+#if DB_VERSION_MAJOR == 2
+ softCrash("BerkeleyDB::db_remove needs Berkeley DB 3.x or better") ;
+#else
+ HV * hash ;
+ DB * dbp ;
+ SV * sv ;
+ const char * db = NULL ;
+ const char * subdb = NULL ;
+ BerkeleyDB__Env env = NULL ;
+ DB_ENV * dbenv = NULL ;
+ u_int32_t flags = 0 ;
+
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(db, "Filename", char *) ;
+ SetValue_pv(subdb, "Subname", char *) ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_ov(env, "Env", BerkeleyDB__Env) ;
+ if (env)
+ dbenv = env->Env ;
+ RETVAL = db_create(&dbp, dbenv, 0) ;
+ if (RETVAL == 0) {
+ RETVAL = dbp->remove(dbp, db, subdb, flags) ;
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+DualType
+_db_verify(ref)
+ SV * ref
+ CODE:
+ {
+#ifndef AT_LEAST_DB_3_1
+ softCrash("BerkeleyDB::db_verify needs Berkeley DB 3.1.x or better") ;
+#else
+ HV * hash ;
+ DB * dbp ;
+ SV * sv ;
+ const char * db = NULL ;
+ const char * subdb = NULL ;
+ const char * outfile = NULL ;
+ FILE * ofh = NULL;
+ BerkeleyDB__Env env = NULL ;
+ DB_ENV * dbenv = NULL ;
+ u_int32_t flags = 0 ;
+
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(db, "Filename", char *) ;
+ SetValue_pv(subdb, "Subname", char *) ;
+ SetValue_pv(outfile, "Outfile", char *) ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_ov(env, "Env", BerkeleyDB__Env) ;
+ RETVAL = 0;
+ if (outfile){
+ ofh = fopen(outfile, "w");
+ if (! ofh)
+ RETVAL = errno;
+ }
+ if (! RETVAL) {
+ if (env)
+ dbenv = env->Env ;
+ RETVAL = db_create(&dbp, dbenv, 0) ;
+ if (RETVAL == 0) {
+ RETVAL = dbp->verify(dbp, db, subdb, ofh, flags) ;
+ }
+ if (outfile)
+ fclose(ofh);
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+DualType
+_db_rename(ref)
+ SV * ref
+ CODE:
+ {
+#ifndef AT_LEAST_DB_3_1
+ softCrash("BerkeleyDB::db_rename needs Berkeley DB 3.1.x or better") ;
+#else
+ HV * hash ;
+ DB * dbp ;
+ SV * sv ;
+ const char * db = NULL ;
+ const char * subdb = NULL ;
+ const char * newname = NULL ;
+ BerkeleyDB__Env env = NULL ;
+ DB_ENV * dbenv = NULL ;
+ u_int32_t flags = 0 ;
+
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(db, "Filename", char *) ;
+ SetValue_pv(subdb, "Subname", char *) ;
+ SetValue_pv(newname, "Newname", char *) ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_ov(env, "Env", BerkeleyDB__Env) ;
+ if (env)
+ dbenv = env->Env ;
+ RETVAL = db_create(&dbp, dbenv, 0) ;
+ if (RETVAL == 0) {
+ RETVAL = dbp->rename(dbp, db, subdb, newname, flags) ;
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+MODULE = BerkeleyDB::Env PACKAGE = BerkeleyDB::Env PREFIX = env_
+
+
+BerkeleyDB::Env::Raw
+_db_appinit(self, ref)
+ char * self
+ SV * ref
+ CODE:
+ {
+ HV * hash ;
+ SV * sv ;
+ char * home = NULL ;
+ char * errfile = NULL ;
+ char * server = NULL ;
+ char ** config = NULL ;
+ int flags = 0 ;
+ int setflags = 0 ;
+ int cachesize = 0 ;
+ int lk_detect = 0 ;
+ SV * errprefix = NULL;
+ DB_ENV * env ;
+ int status ;
+
+ Trace(("in _db_appinit [%s] %d\n", self, ref)) ;
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(home, "Home", char *) ;
+ SetValue_pv(config, "Config", char **) ;
+ SetValue_sv(errprefix, "ErrPrefix") ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_iv(setflags, "SetFlags") ;
+ SetValue_pv(server, "Server", char *) ;
+ SetValue_iv(cachesize, "Cachesize") ;
+ SetValue_iv(lk_detect, "LockDetect") ;
+#ifndef AT_LEAST_DB_3_2
+ if (setflags)
+ softCrash("-SetFlags needs Berkeley DB 3.x or better") ;
+#endif /* ! AT_LEAST_DB_3 */
+#ifndef AT_LEAST_DB_3_1
+ if (server)
+ softCrash("-Server needs Berkeley DB 3.1 or better") ;
+#endif /* ! AT_LEAST_DB_3_1 */
+ Trace(("_db_appinit(config=[%d], home=[%s],errprefix=[%s],flags=[%d]\n",
+ config, home, errprefix, flags)) ;
+#ifdef TRACE
+ if (config) {
+ int i ;
+ for (i = 0 ; i < 10 ; ++ i) {
+ if (config[i] == NULL) {
+ printf(" End\n") ;
+ break ;
+ }
+ printf(" config = [%s]\n", config[i]) ;
+ }
+ }
+#endif /* TRACE */
+ ZMALLOC(RETVAL, BerkeleyDB_ENV_type) ;
+ if (flags & DB_INIT_TXN)
+ RETVAL->txn_enabled = TRUE ;
+#if DB_VERSION_MAJOR == 2
+ ZMALLOC(RETVAL->Env, DB_ENV) ;
+ env = RETVAL->Env ;
+ {
+ /* Take a copy of the error prefix */
+ if (errprefix) {
+ Trace(("copying errprefix\n" )) ;
+ RETVAL->ErrPrefix = newSVsv(errprefix) ;
+ SvPOK_only(RETVAL->ErrPrefix) ;
+ }
+ if (RETVAL->ErrPrefix)
+ RETVAL->Env->db_errpfx = SvPVX(RETVAL->ErrPrefix) ;
+
+ SetValue_pv(errfile, "ErrFile", char *) ;
+ if (errfile) {
+ RETVAL->ErrHandle = env->db_errfile = fopen(errfile, "w");
+ if (RETVAL->ErrHandle == NULL)
+ croak("Cannot open file %s: %s\n", errfile, Strerror(errno));
+ }
+ SetValue_iv(env->db_verbose, "Verbose") ;
+ env->db_errcall = db_errcall_cb ;
+ RETVAL->active = TRUE ;
+ status = db_appinit(home, config, env, flags) ;
+ Trace((" status = %d env %d Env %d\n", status, RETVAL, env)) ;
+ if (status == 0)
+ hash_store_iv("BerkeleyDB::Term::Env", (char *)RETVAL, 1) ;
+ else {
+ if (RETVAL->ErrHandle)
+ fclose(RETVAL->ErrHandle) ;
+ if (RETVAL->ErrPrefix)
+ SvREFCNT_dec(RETVAL->ErrPrefix) ;
+ Safefree(RETVAL->Env) ;
+ Safefree(RETVAL) ;
+ RETVAL = NULL ;
+ }
+ }
+#else /* DB_VERSION_MAJOR > 2 */
+#ifndef AT_LEAST_DB_3_1
+# define DB_CLIENT 0
+#endif
+ status = db_env_create(&RETVAL->Env, server ? DB_CLIENT : 0) ;
+ Trace(("db_env_create flags = %d returned %s\n", flags,
+ my_db_strerror(status))) ;
+ env = RETVAL->Env ;
+#ifdef AT_LEAST_DB_3_3
+ env->set_alloc(env, safemalloc, MyRealloc, safefree) ;
+#endif
+ if (status == 0 && cachesize) {
+ status = env->set_cachesize(env, 0, cachesize, 0) ;
+ Trace(("set_cachesize [%d] returned %s\n",
+ cachesize, my_db_strerror(status)));
+ }
+
+ if (status == 0 && lk_detect) {
+ status = env->set_lk_detect(env, lk_detect) ;
+ Trace(("set_lk_detect [%d] returned %s\n",
+ lk_detect, my_db_strerror(status)));
+ }
+#ifdef AT_LEAST_DB_4
+ /* set the server */
+ if (server && status == 0)
+ {
+ status = env->set_rpc_server(env, NULL, server, 0, 0, 0);
+ Trace(("ENV->set_rpc_server server = %s returned %s\n", server,
+ my_db_strerror(status))) ;
+ }
+#else
+# if defined(AT_LEAST_DB_3_1) && ! defined(AT_LEAST_DB_4)
+ /* set the server */
+ if (server && status == 0)
+ {
+ status = env->set_server(env, server, 0, 0, 0);
+ Trace(("ENV->set_server server = %s returned %s\n", server,
+ my_db_strerror(status))) ;
+ }
+# endif
+#endif
+#ifdef AT_LEAST_DB_3_2
+ if (setflags && status == 0)
+ {
+ status = env->set_flags(env, setflags, 1);
+ Trace(("ENV->set_flags value = %d returned %s\n", setflags,
+ my_db_strerror(status))) ;
+ }
+#endif
+ if (status == 0)
+ {
+ int mode = 0 ;
+ /* Take a copy of the error prefix */
+ if (errprefix) {
+ Trace(("copying errprefix\n" )) ;
+ RETVAL->ErrPrefix = newSVsv(errprefix) ;
+ SvPOK_only(RETVAL->ErrPrefix) ;
+ }
+ if (RETVAL->ErrPrefix)
+ env->set_errpfx(env, SvPVX(RETVAL->ErrPrefix)) ;
+
+ SetValue_pv(errfile, "ErrFile", char *) ;
+ if (errfile) {
+ RETVAL->ErrHandle = fopen(errfile, "w");
+ if (RETVAL->ErrHandle == NULL)
+ croak("Cannot open file %s: %s\n", errfile, Strerror(errno));
+ env->set_errfile(env, RETVAL->ErrHandle) ;
+ }
+
+ SetValue_iv(mode, "Mode") ;
+ env->set_errcall(env, db_errcall_cb) ;
+ RETVAL->active = TRUE ;
+#ifdef IS_DB_3_0_x
+ status = (env->open)(env, home, config, flags, mode) ;
+#else /* > 3.0 */
+ status = (env->open)(env, home, flags, mode) ;
+#endif
+ Trace(("ENV->open returned %s\n", my_db_strerror(status))) ;
+ }
+
+ if (status == 0)
+ hash_store_iv("BerkeleyDB::Term::Env", (char *)RETVAL, 1) ;
+ else {
+ (env->close)(env, 0) ;
+ if (RETVAL->ErrHandle)
+ fclose(RETVAL->ErrHandle) ;
+ if (RETVAL->ErrPrefix)
+ SvREFCNT_dec(RETVAL->ErrPrefix) ;
+ Safefree(RETVAL) ;
+ RETVAL = NULL ;
+ }
+#endif /* DB_VERSION_MAJOR > 2 */
+ }
+ OUTPUT:
+ RETVAL
+
+void
+log_archive(env, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Env env
+ PPCODE:
+ {
+ char ** list;
+ char ** file;
+ AV * av;
+#ifndef AT_LEAST_DB_3
+ softCrash("log_archive needs at least Berkeley DB 3.x.x");
+#else
+# ifdef AT_LEAST_DB_4
+ env->Status = env->Env->log_archive(env->Env, &list, flags) ;
+# else
+# ifdef AT_LEAST_DB_3_3
+ env->Status = log_archive(env->Env, &list, flags) ;
+# else
+ env->Status = log_archive(env->Env, &list, flags, safemalloc) ;
+# endif
+# endif
+ if (env->Status == 0 && list != NULL)
+ {
+ for (file = list; *file != NULL; ++file)
+ {
+ XPUSHs(sv_2mortal(newSVpv(*file, 0))) ;
+ }
+ safefree(list);
+ }
+#endif
+ }
+
+BerkeleyDB::Txn::Raw
+_txn_begin(env, pid=NULL, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Env env
+ BerkeleyDB::Txn pid
+ CODE:
+ {
+ DB_TXN *txn ;
+ DB_TXN *p_id = NULL ;
+ Trace(("txn_begin pid %d, flags %d\n", pid, flags)) ;
+#if DB_VERSION_MAJOR == 2
+ if (env->Env->tx_info == NULL)
+ softCrash("Transaction Manager not enabled") ;
+#endif
+ if (!env->txn_enabled)
+ softCrash("Transaction Manager not enabled") ;
+ if (pid)
+ p_id = pid->txn ;
+ env->TxnMgrStatus =
+#if DB_VERSION_MAJOR == 2
+ txn_begin(env->Env->tx_info, p_id, &txn) ;
+#else
+# ifdef AT_LEAST_DB_4
+ env->Env->txn_begin(env->Env, p_id, &txn, flags) ;
+# else
+ txn_begin(env->Env, p_id, &txn, flags) ;
+# endif
+#endif
+ if (env->TxnMgrStatus == 0) {
+ ZMALLOC(RETVAL, BerkeleyDB_Txn_type) ;
+ RETVAL->txn = txn ;
+ RETVAL->active = TRUE ;
+ Trace(("_txn_begin created txn [%p] in [%p]\n", txn, RETVAL));
+ hash_store_iv("BerkeleyDB::Term::Txn", (char *)RETVAL, 1) ;
+ }
+ else
+ RETVAL = NULL ;
+ }
+ OUTPUT:
+ RETVAL
+
+
+#if DB_VERSION_MAJOR == 2
+# define env_txn_checkpoint(e,k,m,f) txn_checkpoint(e->Env->tx_info, k, m)
+#else /* DB 3.0 or better */
+# ifdef AT_LEAST_DB_4
+# define env_txn_checkpoint(e,k,m,f) e->Env->txn_checkpoint(e->Env, k, m, f)
+# else
+# ifdef AT_LEAST_DB_3_1
+# define env_txn_checkpoint(e,k,m,f) txn_checkpoint(e->Env, k, m, 0)
+# else
+# define env_txn_checkpoint(e,k,m,f) txn_checkpoint(e->Env, k, m)
+# endif
+# endif
+#endif
+DualType
+env_txn_checkpoint(env, kbyte, min, flags=0)
+ BerkeleyDB::Env env
+ long kbyte
+ long min
+ u_int32_t flags
+
+HV *
+txn_stat(env)
+ BerkeleyDB::Env env
+ HV * RETVAL = NULL ;
+ CODE:
+ {
+ DB_TXN_STAT * stat ;
+#ifdef AT_LEAST_DB_4
+ if(env->Env->txn_stat(env->Env, &stat, 0) == 0) {
+#else
+# ifdef AT_LEAST_DB_3_3
+ if(txn_stat(env->Env, &stat) == 0) {
+# else
+# if DB_VERSION_MAJOR == 2
+ if(txn_stat(env->Env->tx_info, &stat, safemalloc) == 0) {
+# else
+ if(txn_stat(env->Env, &stat, safemalloc) == 0) {
+# endif
+# endif
+#endif
+ RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
+ hv_store_iv(RETVAL, "st_time_ckp", stat->st_time_ckp) ;
+ hv_store_iv(RETVAL, "st_last_txnid", stat->st_last_txnid) ;
+ hv_store_iv(RETVAL, "st_maxtxns", stat->st_maxtxns) ;
+ hv_store_iv(RETVAL, "st_naborts", stat->st_naborts) ;
+ hv_store_iv(RETVAL, "st_nbegins", stat->st_nbegins) ;
+ hv_store_iv(RETVAL, "st_ncommits", stat->st_ncommits) ;
+ hv_store_iv(RETVAL, "st_nactive", stat->st_nactive) ;
+#if DB_VERSION_MAJOR > 2
+ hv_store_iv(RETVAL, "st_maxnactive", stat->st_maxnactive) ;
+ hv_store_iv(RETVAL, "st_regsize", stat->st_regsize) ;
+ hv_store_iv(RETVAL, "st_region_wait", stat->st_region_wait) ;
+ hv_store_iv(RETVAL, "st_region_nowait", stat->st_region_nowait) ;
+#endif
+ safefree(stat) ;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+#define EnDis(x) ((x) ? "Enabled" : "Disabled")
+void
+printEnv(env)
+ BerkeleyDB::Env env
+ INIT:
+ ckActive_Environment(env->active) ;
+ CODE:
+#if 0
+ printf("env [0x%X]\n", env) ;
+ printf(" ErrPrefix [%s]\n", env->ErrPrefix
+ ? SvPVX(env->ErrPrefix) : 0) ;
+ printf(" DB_ENV\n") ;
+ printf(" db_lorder [%d]\n", env->Env.db_lorder) ;
+ printf(" db_home [%s]\n", env->Env.db_home) ;
+ printf(" db_data_dir [%s]\n", env->Env.db_data_dir) ;
+ printf(" db_log_dir [%s]\n", env->Env.db_log_dir) ;
+ printf(" db_tmp_dir [%s]\n", env->Env.db_tmp_dir) ;
+ printf(" lk_info [%s]\n", EnDis(env->Env.lk_info)) ;
+ printf(" lk_max [%d]\n", env->Env.lk_max) ;
+ printf(" lg_info [%s]\n", EnDis(env->Env.lg_info)) ;
+ printf(" lg_max [%d]\n", env->Env.lg_max) ;
+ printf(" mp_info [%s]\n", EnDis(env->Env.mp_info)) ;
+ printf(" mp_size [%d]\n", env->Env.mp_size) ;
+ printf(" tx_info [%s]\n", EnDis(env->Env.tx_info)) ;
+ printf(" tx_max [%d]\n", env->Env.tx_max) ;
+ printf(" flags [%d]\n", env->Env.flags) ;
+ printf("\n") ;
+#endif
+
+SV *
+errPrefix(env, prefix)
+ BerkeleyDB::Env env
+ SV * prefix
+ INIT:
+ ckActive_Environment(env->active) ;
+ CODE:
+ if (env->ErrPrefix) {
+ RETVAL = newSVsv(env->ErrPrefix) ;
+ SvPOK_only(RETVAL) ;
+ sv_setsv(env->ErrPrefix, prefix) ;
+ }
+ else {
+ RETVAL = NULL ;
+ env->ErrPrefix = newSVsv(prefix) ;
+ }
+ SvPOK_only(env->ErrPrefix) ;
+#if DB_VERSION_MAJOR == 2
+ env->Env->db_errpfx = SvPVX(env->ErrPrefix) ;
+#else
+ env->Env->set_errpfx(env->Env, SvPVX(env->ErrPrefix)) ;
+#endif
+ OUTPUT:
+ RETVAL
+
+DualType
+status(env)
+ BerkeleyDB::Env env
+ CODE:
+ RETVAL = env->Status ;
+ OUTPUT:
+ RETVAL
+
+DualType
+db_appexit(env)
+ BerkeleyDB::Env env
+ ALIAS: close =1
+ INIT:
+ ckActive_Environment(env->active) ;
+ CODE:
+#ifdef STRICT_CLOSE
+ if (env->open_dbs)
+ softCrash("attempted to close an environment with %d open database(s)",
+ env->open_dbs) ;
+#endif /* STRICT_CLOSE */
+#if DB_VERSION_MAJOR == 2
+ RETVAL = db_appexit(env->Env) ;
+#else
+ RETVAL = (env->Env->close)(env->Env, 0) ;
+#endif
+ env->active = FALSE ;
+ hash_delete("BerkeleyDB::Term::Env", (char *)env) ;
+ OUTPUT:
+ RETVAL
+
+
+void
+_DESTROY(env)
+ BerkeleyDB::Env env
+ int RETVAL = 0 ;
+ CODE:
+ Trace(("In BerkeleyDB::Env::DESTROY\n"));
+ Trace((" env %ld Env %ld dirty %d\n", env, &env->Env, PL_dirty)) ;
+ if (env->active)
+#if DB_VERSION_MAJOR == 2
+ db_appexit(env->Env) ;
+#else
+ (env->Env->close)(env->Env, 0) ;
+#endif
+ if (env->ErrHandle)
+ fclose(env->ErrHandle) ;
+ if (env->ErrPrefix)
+ SvREFCNT_dec(env->ErrPrefix) ;
+#if DB_VERSION_MAJOR == 2
+ Safefree(env->Env) ;
+#endif
+ Safefree(env) ;
+ hash_delete("BerkeleyDB::Term::Env", (char *)env) ;
+ Trace(("End of BerkeleyDB::Env::DESTROY %d\n", RETVAL)) ;
+
+BerkeleyDB::TxnMgr::Raw
+_TxnMgr(env)
+ BerkeleyDB::Env env
+ INIT:
+ ckActive_Environment(env->active) ;
+ if (!env->txn_enabled)
+ softCrash("Transaction Manager not enabled") ;
+ CODE:
+ ZMALLOC(RETVAL, BerkeleyDB_TxnMgr_type) ;
+ RETVAL->env = env ;
+ /* hash_store_iv("BerkeleyDB::Term::TxnMgr", (char *)txn, 1) ; */
+ OUTPUT:
+ RETVAL
+
+int
+set_lg_dir(env, dir)
+ BerkeleyDB::Env env
+ char * dir
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3_1
+ softCrash("$env->set_lg_dir needs Berkeley DB 3.1 or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_lg_dir(env->Env, dir);
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_lg_bsize(env, bsize)
+ BerkeleyDB::Env env
+ u_int32_t bsize
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3
+ softCrash("$env->set_lg_bsize needs Berkeley DB 3.0.55 or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_lg_bsize(env->Env, bsize);
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_lg_max(env, lg_max)
+ BerkeleyDB::Env env
+ u_int32_t lg_max
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3
+ softCrash("$env->set_lg_max needs Berkeley DB 3.0.55 or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_lg_max(env->Env, lg_max);
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_data_dir(env, dir)
+ BerkeleyDB::Env env
+ char * dir
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3_1
+ softCrash("$env->set_data_dir needs Berkeley DB 3.1 or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_data_dir(env->Env, dir);
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_tmp_dir(env, dir)
+ BerkeleyDB::Env env
+ char * dir
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3_1
+ softCrash("$env->set_tmp_dir needs Berkeley DB 3.1 or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_tmp_dir(env->Env, dir);
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_mutexlocks(env, do_lock)
+ BerkeleyDB::Env env
+ int do_lock
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3
+ softCrash("$env->set_setmutexlocks needs Berkeley DB 3.0 or better") ;
+#else
+# ifdef AT_LEAST_DB_4
+ RETVAL = env->Status = env->Env->set_flags(env->Env, DB_NOLOCKING, do_lock);
+# else
+# if defined(AT_LEAST_DB_3_2_6) || defined(IS_DB_3_0_x)
+ RETVAL = env->Status = env->Env->set_mutexlocks(env->Env, do_lock);
+# else /* DB 3.1 or 3.2.3 */
+ RETVAL = env->Status = db_env_set_mutexlocks(do_lock);
+# endif
+# endif
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_verbose(env, which, onoff)
+ BerkeleyDB::Env env
+ u_int32_t which
+ int onoff
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3
+ softCrash("$env->set_verbose needs Berkeley DB 3.x or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_verbose(env->Env, which, onoff);
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+set_flags(env, flags, onoff)
+ BerkeleyDB::Env env
+ u_int32_t flags
+ int onoff
+ INIT:
+ ckActive_Database(env->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3_2
+ softCrash("$env->set_flags needs Berkeley DB 3.2.x or better") ;
+#else
+ RETVAL = env->Status = env->Env->set_flags(env->Env, flags, onoff);
+#endif
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB::Term PACKAGE = BerkeleyDB::Term
+
+void
+close_everything()
+
+#define safeCroak(string) softCrash(string)
+void
+safeCroak(string)
+ char * string
+
+MODULE = BerkeleyDB::Hash PACKAGE = BerkeleyDB::Hash PREFIX = hash_
+
+BerkeleyDB::Hash::Raw
+_db_open_hash(self, ref)
+ char * self
+ SV * ref
+ CODE:
+ {
+ HV * hash ;
+ SV * sv ;
+ DB_INFO info ;
+ BerkeleyDB__Env dbenv = NULL;
+ SV * ref_dbenv = NULL;
+ const char * file = NULL ;
+ const char * subname = NULL ;
+ int flags = 0 ;
+ int mode = 0 ;
+ BerkeleyDB db ;
+ BerkeleyDB__Txn txn = NULL ;
+
+ Trace(("_db_open_hash start\n")) ;
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(file, "Filename", char *) ;
+ SetValue_pv(subname, "Subname", char *) ;
+ SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
+ SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
+ ref_dbenv = sv ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_iv(mode, "Mode") ;
+
+ Zero(&info, 1, DB_INFO) ;
+ SetValue_iv(info.db_cachesize, "Cachesize") ;
+ SetValue_iv(info.db_lorder, "Lorder") ;
+ SetValue_iv(info.db_pagesize, "Pagesize") ;
+ SetValue_iv(info.h_ffactor, "Ffactor") ;
+ SetValue_iv(info.h_nelem, "Nelem") ;
+ SetValue_iv(info.flags, "Property") ;
+ ZMALLOC(db, BerkeleyDB_type) ;
+ if ((sv = readHash(hash, "Hash")) && sv != &PL_sv_undef) {
+ info.h_hash = hash_cb ;
+ db->hash = newSVsv(sv) ;
+ }
+ /* DB_DUPSORT was introduced in DB 2.5.9 */
+ if ((sv = readHash(hash, "DupCompare")) && sv != &PL_sv_undef) {
+#ifdef DB_DUPSORT
+ info.dup_compare = dup_compare ;
+ db->dup_compare = newSVsv(sv) ;
+ info.flags |= DB_DUP|DB_DUPSORT ;
+#else
+ croak("DupCompare needs Berkeley DB 2.5.9 or later") ;
+#endif
+ }
+ RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_HASH, flags, mode, &info) ;
+ Trace(("_db_open_hash end\n")) ;
+ }
+ OUTPUT:
+ RETVAL
+
+
+HV *
+db_stat(db, flags=0)
+ int flags
+ BerkeleyDB::Common db
+ HV * RETVAL = NULL ;
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ {
+#if DB_VERSION_MAJOR == 2
+ softCrash("$db->db_stat for a Hash needs Berkeley DB 3.x or better") ;
+#else
+ DB_HASH_STAT * stat ;
+#ifdef AT_LEAST_DB_3_3
+ db->Status = ((db->dbp)->stat)(db->dbp, &stat, flags) ;
+#else
+ db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
+#endif
+ if (db->Status == 0) {
+ RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
+ hv_store_iv(RETVAL, "hash_magic", stat->hash_magic) ;
+ hv_store_iv(RETVAL, "hash_version", stat->hash_version);
+ hv_store_iv(RETVAL, "hash_pagesize", stat->hash_pagesize);
+#ifdef AT_LEAST_DB_3_1
+ hv_store_iv(RETVAL, "hash_nkeys", stat->hash_nkeys);
+ hv_store_iv(RETVAL, "hash_ndata", stat->hash_ndata);
+#else
+ hv_store_iv(RETVAL, "hash_nrecs", stat->hash_nrecs);
+#endif
+#ifndef AT_LEAST_DB_3_1
+ hv_store_iv(RETVAL, "hash_nelem", stat->hash_nelem);
+#endif
+ hv_store_iv(RETVAL, "hash_ffactor", stat->hash_ffactor);
+ hv_store_iv(RETVAL, "hash_buckets", stat->hash_buckets);
+ hv_store_iv(RETVAL, "hash_free", stat->hash_free);
+ hv_store_iv(RETVAL, "hash_bfree", stat->hash_bfree);
+ hv_store_iv(RETVAL, "hash_bigpages", stat->hash_bigpages);
+ hv_store_iv(RETVAL, "hash_big_bfree", stat->hash_big_bfree);
+ hv_store_iv(RETVAL, "hash_overflows", stat->hash_overflows);
+ hv_store_iv(RETVAL, "hash_ovfl_free", stat->hash_ovfl_free);
+ hv_store_iv(RETVAL, "hash_dup", stat->hash_dup);
+ hv_store_iv(RETVAL, "hash_dup_free", stat->hash_dup_free);
+#if DB_VERSION_MAJOR >= 3
+ hv_store_iv(RETVAL, "hash_metaflags", stat->hash_metaflags);
+#endif
+ safefree(stat) ;
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB::Unknown PACKAGE = BerkeleyDB::Unknown PREFIX = hash_
+
+void
+_db_open_unknown(ref)
+ SV * ref
+ PPCODE:
+ {
+ HV * hash ;
+ SV * sv ;
+ DB_INFO info ;
+ BerkeleyDB__Env dbenv = NULL;
+ SV * ref_dbenv = NULL;
+ const char * file = NULL ;
+ const char * subname = NULL ;
+ int flags = 0 ;
+ int mode = 0 ;
+ BerkeleyDB db ;
+ BerkeleyDB RETVAL ;
+ BerkeleyDB__Txn txn = NULL ;
+ static char * Names[] = {"", "Btree", "Hash", "Recno"} ;
+
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(file, "Filename", char *) ;
+ SetValue_pv(subname, "Subname", char *) ;
+ SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
+ SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
+ ref_dbenv = sv ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_iv(mode, "Mode") ;
+
+ Zero(&info, 1, DB_INFO) ;
+ SetValue_iv(info.db_cachesize, "Cachesize") ;
+ SetValue_iv(info.db_lorder, "Lorder") ;
+ SetValue_iv(info.db_pagesize, "Pagesize") ;
+ SetValue_iv(info.h_ffactor, "Ffactor") ;
+ SetValue_iv(info.h_nelem, "Nelem") ;
+ SetValue_iv(info.flags, "Property") ;
+ ZMALLOC(db, BerkeleyDB_type) ;
+
+ RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_UNKNOWN, flags, mode, &info) ;
+ XPUSHs(sv_2mortal(newSViv(PTR2IV(RETVAL))));
+ if (RETVAL)
+ XPUSHs(sv_2mortal(newSVpv(Names[RETVAL->type], 0))) ;
+ else
+ XPUSHs(sv_2mortal(newSViv((IV)NULL)));
+ }
+
+
+
+MODULE = BerkeleyDB::Btree PACKAGE = BerkeleyDB::Btree PREFIX = btree_
+
+BerkeleyDB::Btree::Raw
+_db_open_btree(self, ref)
+ char * self
+ SV * ref
+ CODE:
+ {
+ HV * hash ;
+ SV * sv ;
+ DB_INFO info ;
+ BerkeleyDB__Env dbenv = NULL;
+ SV * ref_dbenv = NULL;
+ const char * file = NULL ;
+ const char * subname = NULL ;
+ int flags = 0 ;
+ int mode = 0 ;
+ BerkeleyDB db ;
+ BerkeleyDB__Txn txn = NULL ;
+
+ Trace(("In _db_open_btree\n"));
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(file, "Filename", char*) ;
+ SetValue_pv(subname, "Subname", char *) ;
+ SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
+ SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
+ ref_dbenv = sv ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_iv(mode, "Mode") ;
+
+ Zero(&info, 1, DB_INFO) ;
+ SetValue_iv(info.db_cachesize, "Cachesize") ;
+ SetValue_iv(info.db_lorder, "Lorder") ;
+ SetValue_iv(info.db_pagesize, "Pagesize") ;
+ SetValue_iv(info.bt_minkey, "Minkey") ;
+ SetValue_iv(info.flags, "Property") ;
+ ZMALLOC(db, BerkeleyDB_type) ;
+ if ((sv = readHash(hash, "Compare")) && sv != &PL_sv_undef) {
+ Trace((" Parsed Compare callback\n"));
+ info.bt_compare = btree_compare ;
+ db->compare = newSVsv(sv) ;
+ }
+ /* DB_DUPSORT was introduced in DB 2.5.9 */
+ if ((sv = readHash(hash, "DupCompare")) && sv != &PL_sv_undef) {
+#ifdef DB_DUPSORT
+ Trace((" Parsed DupCompare callback\n"));
+ info.dup_compare = dup_compare ;
+ db->dup_compare = newSVsv(sv) ;
+ info.flags |= DB_DUP|DB_DUPSORT ;
+#else
+ softCrash("DupCompare needs Berkeley DB 2.5.9 or later") ;
+#endif
+ }
+ if ((sv = readHash(hash, "Prefix")) && sv != &PL_sv_undef) {
+ Trace((" Parsed Prefix callback\n"));
+ info.bt_prefix = btree_prefix ;
+ db->prefix = newSVsv(sv) ;
+ }
+
+ RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_BTREE, flags, mode, &info) ;
+ }
+ OUTPUT:
+ RETVAL
+
+
+HV *
+db_stat(db, flags=0)
+ int flags
+ BerkeleyDB::Common db
+ HV * RETVAL = NULL ;
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ {
+ DB_BTREE_STAT * stat ;
+#ifdef AT_LEAST_DB_3_3
+ db->Status = ((db->dbp)->stat)(db->dbp, &stat, flags) ;
+#else
+ db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
+#endif
+ if (db->Status == 0) {
+ RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
+ hv_store_iv(RETVAL, "bt_magic", stat->bt_magic);
+ hv_store_iv(RETVAL, "bt_version", stat->bt_version);
+#if DB_VERSION_MAJOR > 2
+ hv_store_iv(RETVAL, "bt_metaflags", stat->bt_metaflags) ;
+ hv_store_iv(RETVAL, "bt_flags", stat->bt_metaflags) ;
+#else
+ hv_store_iv(RETVAL, "bt_flags", stat->bt_flags) ;
+#endif
+ hv_store_iv(RETVAL, "bt_maxkey", stat->bt_maxkey) ;
+ hv_store_iv(RETVAL, "bt_minkey", stat->bt_minkey);
+ hv_store_iv(RETVAL, "bt_re_len", stat->bt_re_len);
+ hv_store_iv(RETVAL, "bt_re_pad", stat->bt_re_pad);
+ hv_store_iv(RETVAL, "bt_pagesize", stat->bt_pagesize);
+ hv_store_iv(RETVAL, "bt_levels", stat->bt_levels);
+#ifdef AT_LEAST_DB_3_1
+ hv_store_iv(RETVAL, "bt_nkeys", stat->bt_nkeys);
+ hv_store_iv(RETVAL, "bt_ndata", stat->bt_ndata);
+#else
+ hv_store_iv(RETVAL, "bt_nrecs", stat->bt_nrecs);
+#endif
+ hv_store_iv(RETVAL, "bt_int_pg", stat->bt_int_pg);
+ hv_store_iv(RETVAL, "bt_leaf_pg", stat->bt_leaf_pg);
+ hv_store_iv(RETVAL, "bt_dup_pg", stat->bt_dup_pg);
+ hv_store_iv(RETVAL, "bt_over_pg", stat->bt_over_pg);
+ hv_store_iv(RETVAL, "bt_free", stat->bt_free);
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
+ hv_store_iv(RETVAL, "bt_freed", stat->bt_freed);
+ hv_store_iv(RETVAL, "bt_pfxsaved", stat->bt_pfxsaved);
+ hv_store_iv(RETVAL, "bt_split", stat->bt_split);
+ hv_store_iv(RETVAL, "bt_rootsplit", stat->bt_rootsplit);
+ hv_store_iv(RETVAL, "bt_fastsplit", stat->bt_fastsplit);
+ hv_store_iv(RETVAL, "bt_added", stat->bt_added);
+ hv_store_iv(RETVAL, "bt_deleted", stat->bt_deleted);
+ hv_store_iv(RETVAL, "bt_get", stat->bt_get);
+ hv_store_iv(RETVAL, "bt_cache_hit", stat->bt_cache_hit);
+ hv_store_iv(RETVAL, "bt_cache_miss", stat->bt_cache_miss);
+#endif
+ hv_store_iv(RETVAL, "bt_int_pgfree", stat->bt_int_pgfree);
+ hv_store_iv(RETVAL, "bt_leaf_pgfree", stat->bt_leaf_pgfree);
+ hv_store_iv(RETVAL, "bt_dup_pgfree", stat->bt_dup_pgfree);
+ hv_store_iv(RETVAL, "bt_over_pgfree", stat->bt_over_pgfree);
+ safefree(stat) ;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB::Recno PACKAGE = BerkeleyDB::Recno PREFIX = recno_
+
+BerkeleyDB::Recno::Raw
+_db_open_recno(self, ref)
+ char * self
+ SV * ref
+ CODE:
+ {
+ HV * hash ;
+ SV * sv ;
+ DB_INFO info ;
+ BerkeleyDB__Env dbenv = NULL;
+ SV * ref_dbenv = NULL;
+ const char * file = NULL ;
+ const char * subname = NULL ;
+ int flags = 0 ;
+ int mode = 0 ;
+ BerkeleyDB db ;
+ BerkeleyDB__Txn txn = NULL ;
+
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(file, "Fname", char*) ;
+ SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
+ ref_dbenv = sv ;
+ SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_iv(mode, "Mode") ;
+
+ Zero(&info, 1, DB_INFO) ;
+ SetValue_iv(info.db_cachesize, "Cachesize") ;
+ SetValue_iv(info.db_lorder, "Lorder") ;
+ SetValue_iv(info.db_pagesize, "Pagesize") ;
+ SetValue_iv(info.bt_minkey, "Minkey") ;
+
+ SetValue_iv(info.flags, "Property") ;
+ SetValue_pv(info.re_source, "Source", char*) ;
+ if ((sv = readHash(hash, "Len")) && sv != &PL_sv_undef) {
+ info.re_len = SvIV(sv) ; ;
+ flagSet_DB2(info.flags, DB_FIXEDLEN) ;
+ }
+ if ((sv = readHash(hash, "Delim")) && sv != &PL_sv_undef) {
+ info.re_delim = SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ;
+ flagSet_DB2(info.flags, DB_DELIMITER) ;
+ }
+ if ((sv = readHash(hash, "Pad")) && sv != &PL_sv_undef) {
+ info.re_pad = (u_int32_t)SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ;
+ flagSet_DB2(info.flags, DB_PAD) ;
+ }
+ ZMALLOC(db, BerkeleyDB_type) ;
+#ifdef ALLOW_RECNO_OFFSET
+ SetValue_iv(db->array_base, "ArrayBase") ;
+ db->array_base = (db->array_base == 0 ? 1 : 0) ;
+#endif /* ALLOW_RECNO_OFFSET */
+
+ RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_RECNO, flags, mode, &info) ;
+ }
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB::Queue PACKAGE = BerkeleyDB::Queue PREFIX = recno_
+
+BerkeleyDB::Queue::Raw
+_db_open_queue(self, ref)
+ char * self
+ SV * ref
+ CODE:
+ {
+#ifndef AT_LEAST_DB_3
+ softCrash("BerkeleyDB::Queue needs Berkeley DB 3.0.x or better");
+#else
+ HV * hash ;
+ SV * sv ;
+ DB_INFO info ;
+ BerkeleyDB__Env dbenv = NULL;
+ SV * ref_dbenv = NULL;
+ const char * file = NULL ;
+ const char * subname = NULL ;
+ int flags = 0 ;
+ int mode = 0 ;
+ BerkeleyDB db ;
+ BerkeleyDB__Txn txn = NULL ;
+
+ hash = (HV*) SvRV(ref) ;
+ SetValue_pv(file, "Fname", char*) ;
+ SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
+ ref_dbenv = sv ;
+ SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
+ SetValue_iv(flags, "Flags") ;
+ SetValue_iv(mode, "Mode") ;
+
+ Zero(&info, 1, DB_INFO) ;
+ SetValue_iv(info.db_cachesize, "Cachesize") ;
+ SetValue_iv(info.db_lorder, "Lorder") ;
+ SetValue_iv(info.db_pagesize, "Pagesize") ;
+ SetValue_iv(info.bt_minkey, "Minkey") ;
+ SetValue_iv(info.q_extentsize, "ExtentSize") ;
+
+
+ SetValue_iv(info.flags, "Property") ;
+ if ((sv = readHash(hash, "Len")) && sv != &PL_sv_undef) {
+ info.re_len = SvIV(sv) ; ;
+ flagSet_DB2(info.flags, DB_FIXEDLEN) ;
+ }
+ if ((sv = readHash(hash, "Pad")) && sv != &PL_sv_undef) {
+ info.re_pad = (u_int32_t)SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ;
+ flagSet_DB2(info.flags, DB_PAD) ;
+ }
+ ZMALLOC(db, BerkeleyDB_type) ;
+#ifdef ALLOW_RECNO_OFFSET
+ SetValue_iv(db->array_base, "ArrayBase") ;
+ db->array_base = (db->array_base == 0 ? 1 : 0) ;
+#endif /* ALLOW_RECNO_OFFSET */
+
+ RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_QUEUE, flags, mode, &info) ;
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+HV *
+db_stat(db, flags=0)
+ int flags
+ BerkeleyDB::Common db
+ HV * RETVAL = NULL ;
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ {
+#if DB_VERSION_MAJOR == 2
+ softCrash("$db->db_stat for a Queue needs Berkeley DB 3.x or better") ;
+#else /* Berkeley DB 3, or better */
+ DB_QUEUE_STAT * stat ;
+#ifdef AT_LEAST_DB_3_3
+ db->Status = ((db->dbp)->stat)(db->dbp, &stat, flags) ;
+#else
+ db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
+#endif
+ if (db->Status == 0) {
+ RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
+ hv_store_iv(RETVAL, "qs_magic", stat->qs_magic) ;
+ hv_store_iv(RETVAL, "qs_version", stat->qs_version);
+#ifdef AT_LEAST_DB_3_1
+ hv_store_iv(RETVAL, "qs_nkeys", stat->qs_nkeys);
+ hv_store_iv(RETVAL, "qs_ndata", stat->qs_ndata);
+#else
+ hv_store_iv(RETVAL, "qs_nrecs", stat->qs_nrecs);
+#endif
+ hv_store_iv(RETVAL, "qs_pages", stat->qs_pages);
+ hv_store_iv(RETVAL, "qs_pagesize", stat->qs_pagesize);
+ hv_store_iv(RETVAL, "qs_pgfree", stat->qs_pgfree);
+ hv_store_iv(RETVAL, "qs_re_len", stat->qs_re_len);
+ hv_store_iv(RETVAL, "qs_re_pad", stat->qs_re_pad);
+#ifdef AT_LEAST_DB_3_2
+#else
+ hv_store_iv(RETVAL, "qs_start", stat->qs_start);
+#endif
+ hv_store_iv(RETVAL, "qs_first_recno", stat->qs_first_recno);
+ hv_store_iv(RETVAL, "qs_cur_recno", stat->qs_cur_recno);
+#if DB_VERSION_MAJOR >= 3
+ hv_store_iv(RETVAL, "qs_metaflags", stat->qs_metaflags);
+#endif
+ safefree(stat) ;
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB::Common PACKAGE = BerkeleyDB::Common PREFIX = dab_
+
+
+DualType
+db_close(db,flags=0)
+ int flags
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+ CODE:
+ Trace(("BerkeleyDB::Common::db_close %d\n", db));
+#ifdef STRICT_CLOSE
+ if (db->txn)
+ softCrash("attempted to close a database while a transaction was still open") ;
+ if (db->open_cursors)
+ softCrash("attempted to close a database with %d open cursor(s)",
+ db->open_cursors) ;
+#endif /* STRICT_CLOSE */
+ RETVAL = db->Status = ((db->dbp)->close)(db->dbp, flags) ;
+ if (db->parent_env && db->parent_env->open_dbs)
+ -- db->parent_env->open_dbs ;
+ db->active = FALSE ;
+ hash_delete("BerkeleyDB::Term::Db", (char *)db) ;
+ -- db->open_cursors ;
+ Trace(("end of BerkeleyDB::Common::db_close\n"));
+ OUTPUT:
+ RETVAL
+
+void
+dab__DESTROY(db)
+ BerkeleyDB::Common db
+ CODE:
+ CurrentDB = db ;
+ Trace(("In BerkeleyDB::Common::_DESTROY db %d dirty=%d\n", db, PL_dirty)) ;
+ destroyDB(db) ;
+ Trace(("End of BerkeleyDB::Common::DESTROY \n")) ;
+
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+#define db_cursor(db, txn, cur,flags) ((db->dbp)->cursor)(db->dbp, txn, cur)
+#else
+#define db_cursor(db, txn, cur,flags) ((db->dbp)->cursor)(db->dbp, txn, cur,flags)
+#endif
+BerkeleyDB::Cursor::Raw
+_db_cursor(db, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Common db
+ BerkeleyDB::Cursor RETVAL = NULL ;
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ {
+ DBC * cursor ;
+ CurrentDB = db ;
+ if ((db->Status = db_cursor(db, db->txn, &cursor, flags)) == 0){
+ ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
+ db->open_cursors ++ ;
+ RETVAL->parent_db = db ;
+ RETVAL->cursor = cursor ;
+ RETVAL->dbp = db->dbp ;
+ RETVAL->txn = db->txn ;
+ RETVAL->type = db->type ;
+ RETVAL->recno_or_queue = db->recno_or_queue ;
+ RETVAL->filename = my_strdup(db->filename) ;
+ RETVAL->compare = db->compare ;
+ RETVAL->dup_compare = db->dup_compare ;
+#ifdef AT_LEAST_DB_3_3
+ RETVAL->associated = db->associated ;
+ RETVAL->secondary_db = db->secondary_db;
+#endif
+ RETVAL->prefix = db->prefix ;
+ RETVAL->hash = db->hash ;
+ RETVAL->partial = db->partial ;
+ RETVAL->doff = db->doff ;
+ RETVAL->dlen = db->dlen ;
+ RETVAL->active = TRUE ;
+#ifdef ALLOW_RECNO_OFFSET
+ RETVAL->array_base = db->array_base ;
+#endif /* ALLOW_RECNO_OFFSET */
+#ifdef DBM_FILTERING
+ RETVAL->filtering = FALSE ;
+ RETVAL->filter_fetch_key = db->filter_fetch_key ;
+ RETVAL->filter_store_key = db->filter_store_key ;
+ RETVAL->filter_fetch_value = db->filter_fetch_value ;
+ RETVAL->filter_store_value = db->filter_store_value ;
+#endif
+ /* RETVAL->info ; */
+ hash_store_iv("BerkeleyDB::Term::Cursor", (char *)RETVAL, 1) ;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+BerkeleyDB::Cursor::Raw
+_db_join(db, cursors, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Common db
+ AV * cursors
+ BerkeleyDB::Cursor RETVAL = NULL ;
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ {
+#if DB_VERSION_MAJOR == 2 && (DB_VERSION_MINOR < 5 || (DB_VERSION_MINOR == 5 && DB_VERSION_PATCH < 2))
+ softCrash("join needs Berkeley DB 2.5.2 or later") ;
+#else /* Berkeley DB >= 2.5.2 */
+ DBC * join_cursor ;
+ DBC ** cursor_list ;
+ I32 count = av_len(cursors) + 1 ;
+ int i ;
+ CurrentDB = db ;
+ if (count < 1 )
+ softCrash("db_join: No cursors in parameter list") ;
+ cursor_list = (DBC **)safemalloc(sizeof(DBC*) * (count + 1));
+ for (i = 0 ; i < count ; ++i) {
+ SV * obj = (SV*) * av_fetch(cursors, i, FALSE) ;
+ IV tmp = SvIV(getInnerObject(obj)) ;
+ BerkeleyDB__Cursor cur = INT2PTR(BerkeleyDB__Cursor, tmp);
+ cursor_list[i] = cur->cursor ;
+ }
+ cursor_list[i] = NULL ;
+#if DB_VERSION_MAJOR == 2
+ if ((db->Status = ((db->dbp)->join)(db->dbp, cursor_list, flags, &join_cursor)) == 0){
+#else
+ if ((db->Status = ((db->dbp)->join)(db->dbp, cursor_list, &join_cursor, flags)) == 0){
+#endif
+ ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
+ db->open_cursors ++ ;
+ RETVAL->parent_db = db ;
+ RETVAL->cursor = join_cursor ;
+ RETVAL->dbp = db->dbp ;
+ RETVAL->type = db->type ;
+ RETVAL->filename = my_strdup(db->filename) ;
+ RETVAL->compare = db->compare ;
+ RETVAL->dup_compare = db->dup_compare ;
+#ifdef AT_LEAST_DB_3_3
+ RETVAL->associated = db->associated ;
+ RETVAL->secondary_db = db->secondary_db;
+#endif
+ RETVAL->prefix = db->prefix ;
+ RETVAL->hash = db->hash ;
+ RETVAL->partial = db->partial ;
+ RETVAL->doff = db->doff ;
+ RETVAL->dlen = db->dlen ;
+ RETVAL->active = TRUE ;
+#ifdef ALLOW_RECNO_OFFSET
+ RETVAL->array_base = db->array_base ;
+#endif /* ALLOW_RECNO_OFFSET */
+#ifdef DBM_FILTERING
+ RETVAL->filtering = FALSE ;
+ RETVAL->filter_fetch_key = db->filter_fetch_key ;
+ RETVAL->filter_store_key = db->filter_store_key ;
+ RETVAL->filter_fetch_value = db->filter_fetch_value ;
+ RETVAL->filter_store_value = db->filter_store_value ;
+#endif
+ /* RETVAL->info ; */
+ hash_store_iv("BerkeleyDB::Term::Cursor", (char *)RETVAL, 1) ;
+ }
+ safefree(cursor_list) ;
+#endif /* Berkeley DB >= 2.5.2 */
+ }
+ OUTPUT:
+ RETVAL
+
+int
+ArrayOffset(db)
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+#ifdef ALLOW_RECNO_OFFSET
+ RETVAL = db->array_base ? 0 : 1 ;
+#else
+ RETVAL = 0 ;
+#endif /* ALLOW_RECNO_OFFSET */
+ OUTPUT:
+ RETVAL
+
+int
+type(db)
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ RETVAL = db->type ;
+ OUTPUT:
+ RETVAL
+
+int
+byteswapped(db)
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
+ softCrash("byteswapped needs Berkeley DB 2.5 or later") ;
+#else
+#if DB_VERSION_MAJOR == 2
+ RETVAL = db->dbp->byteswapped ;
+#else
+#ifdef AT_LEAST_DB_3_3
+ db->dbp->get_byteswapped(db->dbp, &RETVAL) ;
+#else
+ RETVAL = db->dbp->get_byteswapped(db->dbp) ;
+#endif
+#endif
+#endif
+ OUTPUT:
+ RETVAL
+
+DualType
+status(db)
+ BerkeleyDB::Common db
+ CODE:
+ RETVAL = db->Status ;
+ OUTPUT:
+ RETVAL
+
+#ifdef DBM_FILTERING
+
+#define setFilter(ftype) \
+ { \
+ if (db->ftype) \
+ RETVAL = sv_mortalcopy(db->ftype) ; \
+ ST(0) = RETVAL ; \
+ if (db->ftype && (code == &PL_sv_undef)) { \
+ SvREFCNT_dec(db->ftype) ; \
+ db->ftype = NULL ; \
+ } \
+ else if (code) { \
+ if (db->ftype) \
+ sv_setsv(db->ftype, code) ; \
+ else \
+ db->ftype = newSVsv(code) ; \
+ } \
+ }
+
+
+SV *
+filter_fetch_key(db, code)
+ BerkeleyDB::Common db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_fetch_key, code) ;
+
+SV *
+filter_store_key(db, code)
+ BerkeleyDB::Common db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_store_key, code) ;
+
+SV *
+filter_fetch_value(db, code)
+ BerkeleyDB::Common db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_fetch_value, code) ;
+
+SV *
+filter_store_value(db, code)
+ BerkeleyDB::Common db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_store_value, code) ;
+
+#endif /* DBM_FILTERING */
+
+void
+partial_set(db, offset, length)
+ BerkeleyDB::Common db
+ u_int32_t offset
+ u_int32_t length
+ INIT:
+ ckActive_Database(db->active) ;
+ PPCODE:
+ if (GIMME == G_ARRAY) {
+ XPUSHs(sv_2mortal(newSViv(db->partial == DB_DBT_PARTIAL))) ;
+ XPUSHs(sv_2mortal(newSViv(db->doff))) ;
+ XPUSHs(sv_2mortal(newSViv(db->dlen))) ;
+ }
+ db->partial = DB_DBT_PARTIAL ;
+ db->doff = offset ;
+ db->dlen = length ;
+
+
+void
+partial_clear(db)
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ PPCODE:
+ if (GIMME == G_ARRAY) {
+ XPUSHs(sv_2mortal(newSViv(db->partial == DB_DBT_PARTIAL))) ;
+ XPUSHs(sv_2mortal(newSViv(db->doff))) ;
+ XPUSHs(sv_2mortal(newSViv(db->dlen))) ;
+ }
+ db->partial =
+ db->doff =
+ db->dlen = 0 ;
+
+
+#define db_del(db, key, flags) \
+ (db->Status = ((db->dbp)->del)(db->dbp, db->txn, &key, flags))
+DualType
+db_del(db, key, flags=0)
+ u_int flags
+ BerkeleyDB::Common db
+ DBTKEY key
+ INIT:
+ Trace(("db_del db[%p] in [%p] txn[%p] key[%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, flags)) ;
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+
+
+#ifdef AT_LEAST_DB_3
+# ifdef AT_LEAST_DB_3_2
+# define writeToKey() (flagSet(DB_CONSUME)||flagSet(DB_CONSUME_WAIT)||flagSet(DB_GET_BOTH)||flagSet(DB_SET_RECNO))
+# else
+# define writeToKey() (flagSet(DB_CONSUME)||flagSet(DB_GET_BOTH)||flagSet(DB_SET_RECNO))
+# endif
+#else
+#define writeToKey() (flagSet(DB_GET_BOTH)||flagSet(DB_SET_RECNO))
+#endif
+#define db_get(db, key, data, flags) \
+ (db->Status = ((db->dbp)->get)(db->dbp, db->txn, &key, &data, flags))
+DualType
+db_get(db, key, data, flags=0)
+ u_int flags
+ BerkeleyDB::Common db
+ DBTKEY_B key
+ DBT_OPT data
+ CODE:
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+ SetPartial(data,db) ;
+ Trace(("db_get db[%p] in [%p] txn[%p] key [%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, flags)) ;
+ RETVAL = db_get(db, key, data, flags);
+ Trace((" RETVAL %d\n", RETVAL));
+ OUTPUT:
+ RETVAL
+ key if (writeToKey()) OutputKey(ST(1), key) ;
+ data
+
+#define db_pget(db, key, pkey, data, flags) \
+ (db->Status = ((db->dbp)->pget)(db->dbp, db->txn, &key, &pkey, &data, flags))
+DualType
+db_pget(db, key, pkey, data, flags=0)
+ u_int flags
+ BerkeleyDB::Common db
+ DBTKEY_B key
+ DBTKEY_B pkey = NO_INIT
+ DBT_OPT data
+ CODE:
+#ifndef AT_LEAST_DB_3_3
+ softCrash("db_pget needs at least Berkeley DB 3.3");
+#else
+ Trace(("db_pget db [%p] in [%p] txn [%p] flags [%d]\n", db->dbp, db, db->txn, flags)) ;
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+ SetPartial(data,db) ;
+ DBT_clear(pkey);
+ RETVAL = db_pget(db, key, pkey, data, flags);
+ Trace((" RETVAL %d\n", RETVAL));
+#endif
+ OUTPUT:
+ RETVAL
+ key if (writeToKey()) OutputKey(ST(1), key) ;
+ pkey
+ data
+
+#define db_put(db,key,data,flag) \
+ (db->Status = (db->dbp->put)(db->dbp,db->txn,&key,&data,flag))
+DualType
+db_put(db, key, data, flags=0)
+ u_int flags
+ BerkeleyDB::Common db
+ DBTKEY key
+ DBT data
+ CODE:
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+ /* SetPartial(data,db) ; */
+ Trace(("db_put db[%p] in [%p] txn[%p] key[%.*s] data [%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, data.size, data.data, flags)) ;
+ RETVAL = db_put(db, key, data, flags);
+ Trace((" RETVAL %d\n", RETVAL));
+ OUTPUT:
+ RETVAL
+ key if (flagSet(DB_APPEND)) OutputKey(ST(1), key) ;
+
+#define db_key_range(db, key, range, flags) \
+ (db->Status = ((db->dbp)->key_range)(db->dbp, db->txn, &key, &range, flags))
+DualType
+db_key_range(db, key, less, equal, greater, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Common db
+ DBTKEY_B key
+ double less = 0.0 ;
+ double equal = 0.0 ;
+ double greater = 0.0 ;
+ CODE:
+ {
+#ifndef AT_LEAST_DB_3_1
+ softCrash("key_range needs Berkeley DB 3.1.x or later") ;
+#else
+ DB_KEY_RANGE range ;
+ range.less = range.equal = range.greater = 0.0 ;
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+ RETVAL = db_key_range(db, key, range, flags);
+ if (RETVAL == 0) {
+ less = range.less ;
+ equal = range.equal;
+ greater = range.greater;
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+ less
+ equal
+ greater
+
+
+#define db_fd(d, x) (db->Status = (db->dbp->fd)(db->dbp, &x))
+DualType
+db_fd(db)
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ CurrentDB = db ;
+ db_fd(db, RETVAL) ;
+ OUTPUT:
+ RETVAL
+
+
+#define db_sync(db, fl) (db->Status = (db->dbp->sync)(db->dbp, fl))
+DualType
+db_sync(db, flags=0)
+ u_int flags
+ BerkeleyDB::Common db
+ INIT:
+ ckActive_Database(db->active) ;
+ CurrentDB = db ;
+
+void
+_Txn(db, txn=NULL)
+ BerkeleyDB::Common db
+ BerkeleyDB::Txn txn
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+ if (txn) {
+ Trace(("_Txn[%p] in[%p] active [%d]\n", txn->txn, txn, txn->active));
+ ckActive_Transaction(txn->active) ;
+ db->txn = txn->txn ;
+ }
+ else {
+ Trace(("_Txn[undef] \n"));
+ db->txn = NULL ;
+ }
+
+
+#define db_truncate(db, countp, flags) \
+ (db->Status = ((db->dbp)->truncate)(db->dbp, db->txn, &countp, flags))
+DualType
+truncate(db, countp, flags=0)
+ BerkeleyDB::Common db
+ u_int32_t countp
+ u_int32_t flags
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3_3
+ softCrash("truncate needs Berkeley DB 3.3 or later") ;
+#else
+ CurrentDB = db ;
+ RETVAL = db_truncate(db, countp, flags);
+#endif
+ OUTPUT:
+ RETVAL
+ countp
+
+#ifdef AT_LEAST_DB_4_1
+# define db_associate(db, sec, cb, flags)\
+ (db->Status = ((db->dbp)->associate)(db->dbp, NULL, sec->dbp, &cb, flags))
+#else
+# define db_associate(db, sec, cb, flags)\
+ (db->Status = ((db->dbp)->associate)(db->dbp, sec->dbp, &cb, flags))
+#endif
+DualType
+associate(db, secondary, callback, flags=0)
+ BerkeleyDB::Common db
+ BerkeleyDB::Common secondary
+ SV* callback
+ u_int32_t flags
+ INIT:
+ ckActive_Database(db->active) ;
+ CODE:
+#ifndef AT_LEAST_DB_3_3
+ softCrash("associate needs Berkeley DB 3.3 or later") ;
+#else
+ CurrentDB = db ;
+ /* db->associated = newSVsv(callback) ; */
+ secondary->associated = newSVsv(callback) ;
+ /* secondary->dbp->app_private = secondary->associated ; */
+ secondary->secondary_db = TRUE;
+ RETVAL = db_associate(db, secondary, associate_cb, flags);
+#endif
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB::Cursor PACKAGE = BerkeleyDB::Cursor PREFIX = cu_
+
+BerkeleyDB::Cursor::Raw
+_c_dup(db, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Cursor db
+ BerkeleyDB::Cursor RETVAL = NULL ;
+ INIT:
+ CurrentDB = db->parent_db ;
+ ckActive_Database(db->active) ;
+ CODE:
+ {
+#ifndef AT_LEAST_DB_3
+ softCrash("c_dup needs at least Berkeley DB 3.0.x");
+#else
+ DBC * newcursor ;
+ db->Status = ((db->cursor)->c_dup)(db->cursor, &newcursor, flags) ;
+ if (db->Status == 0){
+ ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
+ db->parent_db->open_cursors ++ ;
+ RETVAL->parent_db = db->parent_db ;
+ RETVAL->cursor = newcursor ;
+ RETVAL->dbp = db->dbp ;
+ RETVAL->type = db->type ;
+ RETVAL->recno_or_queue = db->recno_or_queue ;
+ RETVAL->filename = my_strdup(db->filename) ;
+ RETVAL->compare = db->compare ;
+ RETVAL->dup_compare = db->dup_compare ;
+#ifdef AT_LEAST_DB_3_3
+ RETVAL->associated = db->associated ;
+#endif
+ RETVAL->prefix = db->prefix ;
+ RETVAL->hash = db->hash ;
+ RETVAL->partial = db->partial ;
+ RETVAL->doff = db->doff ;
+ RETVAL->dlen = db->dlen ;
+ RETVAL->active = TRUE ;
+#ifdef ALLOW_RECNO_OFFSET
+ RETVAL->array_base = db->array_base ;
+#endif /* ALLOW_RECNO_OFFSET */
+#ifdef DBM_FILTERING
+ RETVAL->filtering = FALSE ;
+ RETVAL->filter_fetch_key = db->filter_fetch_key ;
+ RETVAL->filter_store_key = db->filter_store_key ;
+ RETVAL->filter_fetch_value = db->filter_fetch_value ;
+ RETVAL->filter_store_value = db->filter_store_value ;
+#endif /* DBM_FILTERING */
+ /* RETVAL->info ; */
+ hash_store_iv("BerkeleyDB::Term::Cursor", (char *)RETVAL, 1) ;
+ }
+#endif
+ }
+ OUTPUT:
+ RETVAL
+
+DualType
+_c_close(db)
+ BerkeleyDB::Cursor db
+ INIT:
+ CurrentDB = db->parent_db ;
+ ckActive_Cursor(db->active) ;
+ hash_delete("BerkeleyDB::Term::Cursor", (char *)db) ;
+ CODE:
+ RETVAL = db->Status =
+ ((db->cursor)->c_close)(db->cursor) ;
+ db->active = FALSE ;
+ if (db->parent_db->open_cursors)
+ -- db->parent_db->open_cursors ;
+ OUTPUT:
+ RETVAL
+
+void
+_DESTROY(db)
+ BerkeleyDB::Cursor db
+ CODE:
+ CurrentDB = db->parent_db ;
+ Trace(("In BerkeleyDB::Cursor::_DESTROY db %d dirty=%d active=%d\n", db, PL_dirty, db->active));
+ hash_delete("BerkeleyDB::Term::Cursor", (char *)db) ;
+ if (db->active)
+ ((db->cursor)->c_close)(db->cursor) ;
+ if (db->parent_db->open_cursors)
+ -- db->parent_db->open_cursors ;
+ Safefree(db->filename) ;
+ Safefree(db) ;
+ Trace(("End of BerkeleyDB::Cursor::_DESTROY\n")) ;
+
+DualType
+status(db)
+ BerkeleyDB::Cursor db
+ CODE:
+ RETVAL = db->Status ;
+ OUTPUT:
+ RETVAL
+
+
+#define cu_c_del(c,f) (c->Status = ((c->cursor)->c_del)(c->cursor,f))
+DualType
+cu_c_del(db, flags=0)
+ int flags
+ BerkeleyDB::Cursor db
+ INIT:
+ CurrentDB = db->parent_db ;
+ ckActive_Cursor(db->active) ;
+ OUTPUT:
+ RETVAL
+
+
+#define cu_c_get(c,k,d,f) (c->Status = (c->cursor->c_get)(c->cursor,&k,&d,f))
+DualType
+cu_c_get(db, key, data, flags=0)
+ int flags
+ BerkeleyDB::Cursor db
+ DBTKEY_B key
+ DBT_B data
+ INIT:
+ Trace(("c_get db [%p] in [%p] flags [%d]\n", db->dbp, db, flags)) ;
+ CurrentDB = db->parent_db ;
+ ckActive_Cursor(db->active) ;
+ SetPartial(data,db) ;
+ Trace(("c_get end\n")) ;
+ OUTPUT:
+ RETVAL
+ key
+ data if (! flagSet(DB_JOIN_ITEM)) OutputValue_B(ST(2), data) ;
+
+#define cu_c_pget(c,k,p,d,f) (c->Status = (c->secondary_db ? (c->cursor->c_pget)(c->cursor,&k,&p,&d,f) : EINVAL))
+DualType
+cu_c_pget(db, key, pkey, data, flags=0)
+ int flags
+ BerkeleyDB::Cursor db
+ DBTKEY_B key
+ DBTKEY_B pkey = NO_INIT
+ DBT_B data
+ CODE:
+#ifndef AT_LEAST_DB_3_3
+ softCrash("db_c_pget needs at least Berkeley DB 3.3");
+#else
+ Trace(("c_pget db [%d] flags [%d]\n", db, flags)) ;
+ CurrentDB = db->parent_db ;
+ ckActive_Cursor(db->active) ;
+ SetPartial(data,db) ;
+ DBT_clear(pkey);
+ RETVAL = cu_c_pget(db, key, pkey, data, flags);
+ Trace(("c_pget end\n")) ;
+#endif
+ OUTPUT:
+ RETVAL
+ key
+ pkey
+ data if (! flagSet(DB_JOIN_ITEM)) OutputValue_B(ST(2), data) ;
+
+
+
+#define cu_c_put(c,k,d,f) (c->Status = (c->cursor->c_put)(c->cursor,&k,&d,f))
+DualType
+cu_c_put(db, key, data, flags=0)
+ int flags
+ BerkeleyDB::Cursor db
+ DBTKEY key
+ DBT data
+ INIT:
+ CurrentDB = db->parent_db ;
+ ckActive_Cursor(db->active) ;
+ /* SetPartial(data,db) ; */
+ OUTPUT:
+ RETVAL
+
+#define cu_c_count(c,p,f) (c->Status = (c->cursor->c_count)(c->cursor,&p,f))
+DualType
+cu_c_count(db, count, flags=0)
+ int flags
+ BerkeleyDB::Cursor db
+ u_int32_t count = NO_INIT
+ CODE:
+#ifndef AT_LEAST_DB_3_1
+ softCrash("c_count needs at least Berkeley DB 3.1.x");
+#else
+ Trace(("c_get count [%d] flags [%d]\n", db, flags)) ;
+ CurrentDB = db->parent_db ;
+ ckActive_Cursor(db->active) ;
+ RETVAL = cu_c_count(db, count, flags) ;
+ Trace((" c_count got %d duplicates\n", count)) ;
+#endif
+ OUTPUT:
+ RETVAL
+ count
+
+MODULE = BerkeleyDB::TxnMgr PACKAGE = BerkeleyDB::TxnMgr PREFIX = xx_
+
+BerkeleyDB::Txn::Raw
+_txn_begin(txnmgr, pid=NULL, flags=0)
+ u_int32_t flags
+ BerkeleyDB::TxnMgr txnmgr
+ BerkeleyDB::Txn pid
+ CODE:
+ {
+ DB_TXN *txn ;
+ DB_TXN *p_id = NULL ;
+#if DB_VERSION_MAJOR == 2
+ if (txnmgr->env->Env->tx_info == NULL)
+ softCrash("Transaction Manager not enabled") ;
+#endif
+ if (pid)
+ p_id = pid->txn ;
+ txnmgr->env->TxnMgrStatus =
+#if DB_VERSION_MAJOR == 2
+ txn_begin(txnmgr->env->Env->tx_info, p_id, &txn) ;
+#else
+# ifdef AT_LEAST_DB_4
+ txnmgr->env->Env->txn_begin(txnmgr->env->Env, p_id, &txn, flags) ;
+# else
+ txn_begin(txnmgr->env->Env, p_id, &txn, flags) ;
+# endif
+#endif
+ if (txnmgr->env->TxnMgrStatus == 0) {
+ ZMALLOC(RETVAL, BerkeleyDB_Txn_type) ;
+ RETVAL->txn = txn ;
+ RETVAL->active = TRUE ;
+ Trace(("_txn_begin created txn [%d] in [%d]\n", txn, RETVAL));
+ hash_store_iv("BerkeleyDB::Term::Txn", (char *)RETVAL, 1) ;
+ }
+ else
+ RETVAL = NULL ;
+ }
+ OUTPUT:
+ RETVAL
+
+
+DualType
+status(mgr)
+ BerkeleyDB::TxnMgr mgr
+ CODE:
+ RETVAL = mgr->env->TxnMgrStatus ;
+ OUTPUT:
+ RETVAL
+
+
+void
+_DESTROY(mgr)
+ BerkeleyDB::TxnMgr mgr
+ CODE:
+ Trace(("In BerkeleyDB::TxnMgr::DESTROY dirty=%d\n", PL_dirty)) ;
+ Safefree(mgr) ;
+ Trace(("End of BerkeleyDB::TxnMgr::DESTROY\n")) ;
+
+DualType
+txn_close(txnp)
+ BerkeleyDB::TxnMgr txnp
+ NOT_IMPLEMENTED_YET
+
+
+#if DB_VERSION_MAJOR == 2
+# define xx_txn_checkpoint(t,k,m,f) txn_checkpoint(t->env->Env->tx_info, k, m)
+#else
+# ifdef AT_LEAST_DB_4
+# define xx_txn_checkpoint(e,k,m,f) e->env->Env->txn_checkpoint(e->env->Env, k, m, f)
+# else
+# ifdef AT_LEAST_DB_3_1
+# define xx_txn_checkpoint(t,k,m,f) txn_checkpoint(t->env->Env, k, m, 0)
+# else
+# define xx_txn_checkpoint(t,k,m,f) txn_checkpoint(t->env->Env, k, m)
+# endif
+# endif
+#endif
+DualType
+xx_txn_checkpoint(txnp, kbyte, min, flags=0)
+ BerkeleyDB::TxnMgr txnp
+ long kbyte
+ long min
+ u_int32_t flags
+
+HV *
+txn_stat(txnp)
+ BerkeleyDB::TxnMgr txnp
+ HV * RETVAL = NULL ;
+ CODE:
+ {
+ DB_TXN_STAT * stat ;
+#ifdef AT_LEAST_DB_4
+ if(txnp->env->Env->txn_stat(txnp->env->Env, &stat, 0) == 0) {
+#else
+# ifdef AT_LEAST_DB_3_3
+ if(txn_stat(txnp->env->Env, &stat) == 0) {
+# else
+# if DB_VERSION_MAJOR == 2
+ if(txn_stat(txnp->env->Env->tx_info, &stat, safemalloc) == 0) {
+# else
+ if(txn_stat(txnp->env->Env, &stat, safemalloc) == 0) {
+# endif
+# endif
+#endif
+ RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
+ hv_store_iv(RETVAL, "st_time_ckp", stat->st_time_ckp) ;
+ hv_store_iv(RETVAL, "st_last_txnid", stat->st_last_txnid) ;
+ hv_store_iv(RETVAL, "st_maxtxns", stat->st_maxtxns) ;
+ hv_store_iv(RETVAL, "st_naborts", stat->st_naborts) ;
+ hv_store_iv(RETVAL, "st_nbegins", stat->st_nbegins) ;
+ hv_store_iv(RETVAL, "st_ncommits", stat->st_ncommits) ;
+ hv_store_iv(RETVAL, "st_nactive", stat->st_nactive) ;
+#if DB_VERSION_MAJOR > 2
+ hv_store_iv(RETVAL, "st_maxnactive", stat->st_maxnactive) ;
+ hv_store_iv(RETVAL, "st_regsize", stat->st_regsize) ;
+ hv_store_iv(RETVAL, "st_region_wait", stat->st_region_wait) ;
+ hv_store_iv(RETVAL, "st_region_nowait", stat->st_region_nowait) ;
+#endif
+ safefree(stat) ;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+
+BerkeleyDB::TxnMgr
+txn_open(dir, flags, mode, dbenv)
+ int flags
+ const char * dir
+ int mode
+ BerkeleyDB::Env dbenv
+ NOT_IMPLEMENTED_YET
+
+
+MODULE = BerkeleyDB::Txn PACKAGE = BerkeleyDB::Txn PREFIX = xx_
+
+DualType
+status(tid)
+ BerkeleyDB::Txn tid
+ CODE:
+ RETVAL = tid->Status ;
+ OUTPUT:
+ RETVAL
+
+int
+_DESTROY(tid)
+ BerkeleyDB::Txn tid
+ CODE:
+ Trace(("In BerkeleyDB::Txn::_DESTROY txn [%d] active [%d] dirty=%d\n", tid->txn, tid->active, PL_dirty)) ;
+ if (tid->active)
+#ifdef AT_LEAST_DB_4
+ tid->txn->abort(tid->txn) ;
+#else
+ txn_abort(tid->txn) ;
+#endif
+ RETVAL = (int)tid ;
+ hash_delete("BerkeleyDB::Term::Txn", (char *)tid) ;
+ Safefree(tid) ;
+ Trace(("End of BerkeleyDB::Txn::DESTROY\n")) ;
+ OUTPUT:
+ RETVAL
+
+#define xx_txn_unlink(d,f,e) txn_unlink(d,f,&(e->Env))
+DualType
+xx_txn_unlink(dir, force, dbenv)
+ const char * dir
+ int force
+ BerkeleyDB::Env dbenv
+ NOT_IMPLEMENTED_YET
+
+#ifdef AT_LEAST_DB_4
+# define xx_txn_prepare(t) (t->Status = t->txn->prepare(t->txn, 0))
+#else
+# ifdef AT_LEAST_DB_3_3
+# define xx_txn_prepare(t) (t->Status = txn_prepare(t->txn, 0))
+# else
+# define xx_txn_prepare(t) (t->Status = txn_prepare(t->txn))
+# endif
+#endif
+DualType
+xx_txn_prepare(tid)
+ BerkeleyDB::Txn tid
+ INIT:
+ ckActive_Transaction(tid->active) ;
+
+#ifdef AT_LEAST_DB_4
+# define _txn_commit(t,flags) (t->Status = t->txn->commit(t->txn, flags))
+#else
+# if DB_VERSION_MAJOR == 2
+# define _txn_commit(t,flags) (t->Status = txn_commit(t->txn))
+# else
+# define _txn_commit(t, flags) (t->Status = txn_commit(t->txn, flags))
+# endif
+#endif
+DualType
+_txn_commit(tid, flags=0)
+ u_int32_t flags
+ BerkeleyDB::Txn tid
+ INIT:
+ ckActive_Transaction(tid->active) ;
+ hash_delete("BerkeleyDB::Term::Txn", (char *)tid) ;
+ tid->active = FALSE ;
+
+#ifdef AT_LEAST_DB_4
+# define _txn_abort(t) (t->Status = t->txn->abort(t->txn))
+#else
+# define _txn_abort(t) (t->Status = txn_abort(t->txn))
+#endif
+DualType
+_txn_abort(tid)
+ BerkeleyDB::Txn tid
+ INIT:
+ ckActive_Transaction(tid->active) ;
+ hash_delete("BerkeleyDB::Term::Txn", (char *)tid) ;
+ tid->active = FALSE ;
+
+#ifdef AT_LEAST_DB_4
+# define _txn_discard(t,f) (t->Status = t->txn->discard(t->txn, f))
+#else
+# ifdef AT_LEAST_DB_3_3_4
+# define _txn_discard(t,f) (t->Status = txn_discard(t->txn, f))
+# else
+# define _txn_discard(t,f) (int)softCrash("txn_discard needs Berkeley DB 3.3.4 or better") ;
+# endif
+#endif
+DualType
+_txn_discard(tid, flags=0)
+ BerkeleyDB::Txn tid
+ u_int32_t flags
+ INIT:
+ ckActive_Transaction(tid->active) ;
+ hash_delete("BerkeleyDB::Term::Txn", (char *)tid) ;
+ tid->active = FALSE ;
+
+#ifdef AT_LEAST_DB_4
+# define xx_txn_id(t) t->txn->id(t->txn)
+#else
+# define xx_txn_id(t) txn_id(t->txn)
+#endif
+u_int32_t
+xx_txn_id(tid)
+ BerkeleyDB::Txn tid
+
+MODULE = BerkeleyDB::_tiedHash PACKAGE = BerkeleyDB::_tiedHash
+
+int
+FIRSTKEY(db)
+ BerkeleyDB::Common db
+ CODE:
+ {
+ DBTKEY key ;
+ DBT value ;
+ DBC * cursor ;
+
+ /*
+ TODO!
+ set partial value to 0 - to eliminate the retrieval of
+ the value need to store any existing partial settings &
+ restore at the end.
+
+ */
+ CurrentDB = db ;
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ /* If necessary create a cursor for FIRSTKEY/NEXTKEY use */
+ if (!db->cursor &&
+ (db->Status = db_cursor(db, db->txn, &cursor, 0)) == 0 )
+ db->cursor = cursor ;
+
+ if (db->cursor)
+ RETVAL = (db->Status) =
+ ((db->cursor)->c_get)(db->cursor, &key, &value, DB_FIRST);
+ else
+ RETVAL = db->Status ;
+ /* check for end of cursor */
+ if (RETVAL == DB_NOTFOUND) {
+ ((db->cursor)->c_close)(db->cursor) ;
+ db->cursor = NULL ;
+ }
+ ST(0) = sv_newmortal();
+ OutputKey(ST(0), key)
+ }
+
+
+
+int
+NEXTKEY(db, key)
+ BerkeleyDB::Common db
+ DBTKEY key = NO_INIT
+ CODE:
+ {
+ DBT value ;
+
+ CurrentDB = db ;
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ key.flags = 0 ;
+ RETVAL = (db->Status) =
+ ((db->cursor)->c_get)(db->cursor, &key, &value, DB_NEXT);
+
+ /* check for end of cursor */
+ if (RETVAL == DB_NOTFOUND) {
+ ((db->cursor)->c_close)(db->cursor) ;
+ db->cursor = NULL ;
+ }
+ ST(0) = sv_newmortal();
+ OutputKey(ST(0), key)
+ }
+
+MODULE = BerkeleyDB::_tiedArray PACKAGE = BerkeleyDB::_tiedArray
+
+I32
+FETCHSIZE(db)
+ BerkeleyDB::Common db
+ CODE:
+ CurrentDB = db ;
+ RETVAL = GetArrayLength(db) ;
+ OUTPUT:
+ RETVAL
+
+
+MODULE = BerkeleyDB PACKAGE = BerkeleyDB
+
+BOOT:
+ {
+ SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;
+ SV * version_sv = perl_get_sv("BerkeleyDB::db_version", GV_ADD|GV_ADDMULTI) ;
+ SV * ver_sv = perl_get_sv("BerkeleyDB::db_ver", GV_ADD|GV_ADDMULTI) ;
+ int Major, Minor, Patch ;
+ (void)db_version(&Major, &Minor, &Patch) ;
+ /* Check that the versions of db.h and libdb.a are the same */
+ if (Major != DB_VERSION_MAJOR || Minor != DB_VERSION_MINOR
+ || Patch != DB_VERSION_PATCH)
+ croak("\nBerkeleyDB needs compatible versions of libdb & db.h\n\tyou have db.h version %d.%d.%d and libdb version %d.%d.%d\n",
+ DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
+ Major, Minor, Patch) ;
+
+ if (Major < 2 || (Major == 2 && Minor < 6))
+ {
+ croak("BerkeleyDB needs Berkeley DB 2.6 or greater. This is %d.%d.%d\n",
+ Major, Minor, Patch) ;
+ }
+ sv_setpvf(version_sv, "%d.%d", Major, Minor) ;
+ sv_setpvf(ver_sv, "%d.%03d%03d", Major, Minor, Patch) ;
+ sv_setpv(sv_err, "");
+
+ DBT_clear(empty) ;
+ empty.data = &zero ;
+ empty.size = sizeof(db_recno_t) ;
+ empty.flags = 0 ;
+
+ }
+
diff --git a/bdb/perl.BerkeleyDB/BerkeleyDB/Btree.pm b/bdb/perl/BerkeleyDB/BerkeleyDB/Btree.pm
index ba9a9c0085d..ba9a9c0085d 100644
--- a/bdb/perl.BerkeleyDB/BerkeleyDB/Btree.pm
+++ b/bdb/perl/BerkeleyDB/BerkeleyDB/Btree.pm
diff --git a/bdb/perl.BerkeleyDB/BerkeleyDB/Hash.pm b/bdb/perl/BerkeleyDB/BerkeleyDB/Hash.pm
index 8e7bc7e78c7..8e7bc7e78c7 100644
--- a/bdb/perl.BerkeleyDB/BerkeleyDB/Hash.pm
+++ b/bdb/perl/BerkeleyDB/BerkeleyDB/Hash.pm
diff --git a/bdb/perl/BerkeleyDB/Changes b/bdb/perl/BerkeleyDB/Changes
new file mode 100644
index 00000000000..cbeb1a34d73
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/Changes
@@ -0,0 +1,167 @@
+Revision history for Perl extension BerkeleyDB.
+
+0.20 2nd September 2002
+
+ * More support for building with Berkeley DB 4.1.x
+ * db->get & db->pget used the wrong output macro for DBM filters
+ bug spotted by Aaron Ross.
+ * db_join didn't keep a reference to the cursors it was joining.
+ Spotted by Winton Davies.
+
+0.19 5th June 2002
+ * Removed the targets that used mkconsts from Makefile.PL. They relied
+ on a module that is not available in all versions of Perl.
+ * added support for env->set_verbose
+ * added support for db->truncate
+ * added support for db->rename via BerkeleyDB::db_rename
+ * added support for db->verify via BerkeleyDB::db_verify
+ * added support for db->associate, db->pget & cursor->c_pget
+ * Builds with Berkeley DB 4.1.x
+
+
+0.18 6th January 2002
+ * Dropped support for ErrFile as a file handle. It was proving too
+ difficult to get at the underlying FILE * in XS.
+ Reported by Jonas Smedegaard (Debian powerpc) & Kenneth Olwing (Win32)
+ * Fixed problem with abort macro in XSUB.h clashing with txn abort
+ method in Berkeley DB 4.x -- patch supplied by Kenneth Olwing.
+ * DB->set_alloc was getting called too late in BerkeleyDB.xs.
+ This was causing problems with ActivePerl -- problem reported
+ by Kenneth Olwing.
+ * When opening a queue, the Len proprty set the DB_PAD flag.
+ Should have been DB_FIXEDLEN. Fix provided by Kenneth Olwing.
+ * Test harness fixes from Kenneth Olwing.
+
+0.17 23 September 2001
+ * Fixed a bug in BerkeleyDB::Recno - reported by Niklas Paulsson.
+ * Added log_archive - patch supplied by Benjamin Holzman
+ * Added txn_discard
+ * Builds with Berkeley DB 4.0.x
+
+0.16 1 August 2001
+ * added support for Berkeley DB 3.3.x (but no support for any of the
+ new features just yet)
+
+0.15 26 April 2001
+ * Fixed a bug in the processing of the flags options in
+ db_key_range.
+ * added support for set_lg_max & set_lg_bsize
+ * allow DB_TMP_DIR and DB_TEMP_DIR
+ * the -Filename parameter to BerkeleyDB::Queue didn't work.
+ * added symbol DB_CONSUME_WAIT
+
+0.14 21st January 2001
+ * Silenced the warnings when build with a 64-bit Perl.
+ * Can now build with DB 3.2.3h (part of MySQL). The test harness
+ takes an age to do the queue test, but it does eventually pass.
+ * Mentioned the problems that occur when perl is built with sfio.
+
+0.13 15th January 2001
+ * Added support to allow this module to build with Berkeley DB 3.2
+ * Updated dbinfo to support Berkeley DB 3.1 & 3.2 file format
+ changes.
+ * Documented the Solaris 2.7 core dump problem in README.
+ * Tidied up the test harness to fix a problem on Solaris where the
+ "fred" directory wasn't being deleted when it should have been.
+ * two calls to "open" clashed with a win32 macro.
+ * size argument for hash_cb is different for Berkeley DB 3.x
+ * Documented the issue of building on Linux.
+ * Added -Server, -CacheSize & -LockDetect options
+ [original patch supplied by Graham Barr]
+ * Added support for set_mutexlocks, c_count, set_q_extentsize,
+ key_range, c_dup
+ * Dropped the "attempted to close a Cursor with an open transaction"
+ error in c_close. The correct behaviour is that the cursor
+ should be closed before committing/aborting the transaction.
+
+0.12 2nd August 2000
+ * Serious bug with get fixed. Spotted by Sleepycat.
+ * Added hints file for Solaris & Irix (courtesy of Albert Chin-A-Young)
+
+0.11 4th June 2000
+ * When built with Berkeley Db 3.x there can be a clash with the close
+ macro.
+ * Typo in the definition of DB_WRITECURSOR
+ * The flags parameter wasn't getting sent to db_cursor
+ * Plugged small memory leak in db_cursor (DESTROY wasn't freeing
+ memory)
+ * Can be built with Berkeley DB 3.1
+
+0.10 8th December 1999
+ * The DESTROY method was missing for BerkeleyDB::Env. This resulted in
+ a memory leak. Fixed.
+ * If opening an environment or database failed, there was a small
+ memory leak. This has been fixed.
+ * A thread-enabled Perl it could core when a database was closed.
+ Problem traced to the strdup function.
+
+0.09 29th November 1999
+ * the queue.t & subdb.t test harnesses were outputting a few
+ spurious warnings. This has been fixed.
+
+0.08 28nd November 1999
+ * More documentation updates
+ * Changed reference to files in /tmp in examples.t
+ * Fixed a typo in softCrash that caused problems when building
+ with a thread-enabled Perl.
+ * BerkeleyDB::Error wasn't initialised properly.
+ * ANSI-ified all the static C functions in BerkeleyDB.xs
+ * Added support for the following DB 3.x features:
+ + The Queue database type
+ + db_remove
+ + subdatabases
+ + db_stat for Hash & Queue
+
+0.07 21st September 1999
+ * Numerous small bug fixes.
+ * Added support for sorting duplicate values DB_DUPSORT.
+ * Added support for DB_GET_BOTH & DB_NEXT_DUP.
+ * Added get_dup (from DB_File).
+ * beefed up the documentation.
+ * Forgot to add the DB_INIT_CDB in BerkeleyDB.pm in previous release.
+ * Merged the DBM Filter code from DB_File into BerkeleyDB.
+ * Fixed a nasty bug where a closed transaction was still used with
+ with dp_put, db_get etc.
+ * Added logic to gracefully close everything whenever a fatal error
+ happens. Previously the plug was just pulled.
+ * It is now a fatal error to explicitly close an environment if there
+ is still an open database; a database when there are open cursors or
+ an open transaction; and a cursor if there is an open transaction.
+ Using object destruction doesn't have this issue, as object
+ references will ensure everything gets closed in the correct order.
+ * The BOOT code now checks that the version of db.h & libdb are the
+ same - this seems to be a common problem on Linux.
+ * MLDBM support added.
+ * Support for the new join cursor added.
+ * Builds with Berkeley DB 3.x
+ * Updated dbinfo for Berkeley DB 3.x file formats.
+ * Deprecated the TxnMgr class. As with Berkeley DB version 3,
+ txn_begin etc are now accessed via the environment object.
+
+0.06 19 December 1998
+ * Minor modifications to get the module to build with DB 2.6.x
+ * Added support for DB 2.6.x's Concurrent Access Method, DB_INIT_CDB.
+
+0.05 9 November 1998
+ * Added a note to README about how to build Berkeley DB 2.x
+ when using HP-UX.
+ * Minor modifications to get the module to build with DB 2.5.x
+
+0.04 19 May 1998
+ * Define DEFSV & SAVE_DEFSV if not already defined. This allows
+ the module to be built with Perl 5.004_04.
+
+0.03 5 May 1998
+ * fixed db_get with DB_SET_RECNO
+ * fixed c_get with DB_SET_RECNO and DB_GET_RECNO
+ * implemented BerkeleyDB::Unknown
+ * implemented BerkeleyDB::Recno, including push, pop etc
+ modified the txn support.
+
+0.02 30 October 1997
+ * renamed module to BerkeleyDB
+ * fixed a few bugs & added more tests
+
+0.01 23 October 1997
+ * first alpha release as BerkDB.
+
diff --git a/bdb/perl/BerkeleyDB/MANIFEST b/bdb/perl/BerkeleyDB/MANIFEST
new file mode 100644
index 00000000000..7da51ef7d7c
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/MANIFEST
@@ -0,0 +1,56 @@
+BerkeleyDB.pm
+BerkeleyDB.pod
+BerkeleyDB.pod.P
+BerkeleyDB.xs
+BerkeleyDB/Btree.pm
+BerkeleyDB/Hash.pm
+Changes
+config.in
+constants.h
+constants.xs
+dbinfo
+hints/dec_osf.pl
+hints/solaris.pl
+hints/irix_6_5.pl
+Makefile.PL
+MANIFEST
+mkconsts
+mkpod
+ppport.h
+README
+t/btree.t
+t/db-3.0.t
+t/db-3.1.t
+t/db-3.2.t
+t/db-3.3.t
+t/destroy.t
+t/env.t
+t/examples.t
+t/examples.t.T
+t/examples3.t
+t/examples3.t.T
+t/filter.t
+t/hash.t
+t/join.t
+t/mldbm.t
+t/queue.t
+t/recno.t
+t/strict.t
+t/subdb.t
+t/txn.t
+t/unknown.t
+t/util.pm
+Todo
+typemap
+patches/5.004
+patches/5.004_01
+patches/5.004_02
+patches/5.004_03
+patches/5.004_04
+patches/5.004_05
+patches/5.005
+patches/5.005_01
+patches/5.005_02
+patches/5.005_03
+patches/5.6.0
+scan
diff --git a/bdb/perl/BerkeleyDB/Makefile.PL b/bdb/perl/BerkeleyDB/Makefile.PL
new file mode 100644
index 00000000000..86da9a845af
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/Makefile.PL
@@ -0,0 +1,123 @@
+#! perl -w
+
+# It should not be necessary to edit this file. The configuration for
+# BerkeleyDB is controlled from the file config.in
+
+
+BEGIN { die "BerkeleyDB needs Perl 5.004_04 or greater" if $] < 5.004_04 ; }
+
+use strict ;
+use ExtUtils::MakeMaker ;
+use Config ;
+
+# Check for the presence of sfio
+if ($Config{'d_sfio'}) {
+ print <<EOM;
+
+WARNING: Perl seems to have been built with SFIO support enabled.
+ Please read the SFIO Notes in the README file.
+
+EOM
+}
+
+my $LIB_DIR ;
+my $INC_DIR ;
+my $DB_NAME ;
+my $LIBS ;
+
+ParseCONFIG() ;
+
+if (defined $DB_NAME)
+ { $LIBS = $DB_NAME }
+else {
+ if ($^O eq 'MSWin32')
+ { $LIBS = '-llibdb' }
+ else
+ { $LIBS = '-ldb' }
+}
+
+# OS2 is a special case, so check for it now.
+my $OS2 = "" ;
+$OS2 = "-DOS2" if $^O eq 'os2' ;
+
+WriteMakefile(
+ NAME => 'BerkeleyDB',
+ LIBS => ["-L${LIB_DIR} $LIBS"],
+ #MAN3PODS => {}, # Pods will be built by installman.
+ INC => "-I$INC_DIR",
+ VERSION_FROM => 'BerkeleyDB.pm',
+ XSPROTOARG => '-noprototypes',
+ DEFINE => "$OS2",
+ #'macro' => { INSTALLDIRS => 'perl' },
+ 'dist' => {COMPRESS=>'gzip', SUFFIX=>'gz'},
+ ($] >= 5.005
+ ? (ABSTRACT_FROM => 'BerkeleyDB.pod',
+ AUTHOR => 'Paul Marquess <Paul.Marquess@btinternet.com>')
+ : ()
+ ),
+ );
+
+
+sub MY::postamble {
+ '
+$(NAME).pod: $(NAME).pod.P t/examples.t.T t/examples3.t.T mkpod
+ perl ./mkpod
+
+$(NAME).xs: typemap
+ $(TOUCH) $(NAME).xs
+
+Makefile: config.in
+
+
+' ;
+}
+
+sub ParseCONFIG
+{
+ my ($k, $v) ;
+ my @badkey = () ;
+ my %Info = () ;
+ my @Options = qw( INCLUDE LIB DBNAME ) ;
+ my %ValidOption = map {$_, 1} @Options ;
+ my %Parsed = %ValidOption ;
+ my $CONFIG = 'config.in' ;
+
+ print "Parsing $CONFIG...\n" ;
+
+ # DBNAME is optional, so pretend it has been parsed.
+ delete $Parsed{'DBNAME'} ;
+
+ open(F, "$CONFIG") or die "Cannot open file $CONFIG: $!\n" ;
+ while (<F>) {
+ s/^\s*|\s*$//g ;
+ next if /^\s*$/ or /^\s*#/ ;
+ s/\s*#\s*$// ;
+
+ ($k, $v) = split(/\s+=\s+/, $_, 2) ;
+ $k = uc $k ;
+ if ($ValidOption{$k}) {
+ delete $Parsed{$k} ;
+ $Info{$k} = $v ;
+ }
+ else {
+ push(@badkey, $k) ;
+ }
+ }
+ close F ;
+
+ print "Unknown keys in $CONFIG ignored [@badkey]\n"
+ if @badkey ;
+
+ # check parsed values
+ my @missing = () ;
+ die "The following keys are missing from $CONFIG file: [@missing]\n"
+ if @missing = keys %Parsed ;
+
+ $INC_DIR = $ENV{'BERKELEYDB_INCLUDE'} || $Info{'INCLUDE'} ;
+ $LIB_DIR = $ENV{'BERKELEYDB_LIB'} || $Info{'LIB'} ;
+ $DB_NAME = $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
+ print "Looks Good.\n" ;
+
+}
+
+# end of file Makefile.PL
diff --git a/bdb/perl/BerkeleyDB/README b/bdb/perl/BerkeleyDB/README
new file mode 100644
index 00000000000..a600e313193
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/README
@@ -0,0 +1,484 @@
+ BerkeleyDB
+
+ Version 0.20
+
+ 2nd Sept 2002
+
+ Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This
+ program is free software; you can redistribute it and/or modify
+ it under the same terms as Perl itself.
+
+
+DESCRIPTION
+-----------
+
+BerkeleyDB is a module which allows Perl programs to make use of the
+facilities provided by Berkeley DB version 2 or greater. (Note: if
+you want to use version 1 of Berkeley DB with Perl you need the DB_File
+module).
+
+Berkeley DB is a C library which provides a consistent interface to a
+number of database formats. BerkeleyDB provides an interface to all
+four of the database types (hash, btree, queue and recno) currently
+supported by Berkeley DB.
+
+For further details see the documentation in the file BerkeleyDB.pod.
+
+PREREQUISITES
+-------------
+
+Before you can build BerkeleyDB you need to have the following
+installed on your system:
+
+ * Perl 5.004_04 or greater.
+
+ * Berkeley DB Version 2.6.4 or greater
+
+ The official web site for Berkeley DB is http://www.sleepycat.com
+
+ The latest version of Berkeley DB is always available there. It
+ is recommended that you use the most recent version available at
+ the Sleepycat site.
+
+ The one exception to this advice is where you want to use BerkeleyDB
+ to access database files created by a third-party application,
+ like Sendmail. In these cases you must build BerkeleyDB with a
+ compatible version of Berkeley DB.
+
+
+BUILDING THE MODULE
+-------------------
+
+Assuming you have met all the prerequisites, building the module should
+be relatively straightforward.
+
+Step 1 : If you are running Solaris 2.5, 2.7 or HP-UX 10 read either
+ the Solaris Notes or HP-UX Notes sections below.
+ If you are running Linux please read the Linux Notes section
+ before proceeding.
+
+
+Step 2 : Edit the file config.in to suit you local installation.
+ Instructions are given in the file.
+
+Step 3 : Build and test the module using this sequence of commands:
+
+ perl Makefile.PL
+ make
+ make test
+
+INSTALLATION
+------------
+
+ make install
+
+TROUBLESHOOTING
+===============
+
+Here are some of the problems that people encounter when building BerkeleyDB.
+
+Missing db.h or libdb.a
+-----------------------
+
+If you get an error like this:
+
+ cc -c -I./libraries/ -Dbool=char -DHAS_BOOL -I/usr/local/include -O2
+ -DVERSION=\"0.07\" -DXS_VERSION=\"0.07\" -fpic
+ -I/usr/local/lib/perl5/5.00503/i586-linux/CORE BerkeleyDB.c
+ BerkeleyDB.xs:52: db.h: No such file or directory
+
+or this:
+
+ cc -c -I./libraries/2.7.5 -Dbool=char -DHAS_BOOL -I/usr/local/include -O2
+ -DVERSION=\"0.07\" -DXS_VERSION=\"0.07\" -fpic
+ -I/usr/local/lib/perl5/5.00503/i586-linux/CORE BerkeleyDB.c
+ LD_RUN_PATH="/lib" cc -o blib/arch/auto/BerkeleyDB/BerkeleyDB.so -shared
+ -L/usr/local/lib BerkeleyDB.o
+ -L/home/paul/perl/ext/BerkDB/BerkeleyDB/libraries -ldb
+ ld: cannot open -ldb: No such file or directory
+
+This symptom can imply:
+
+ 1. You don't have Berkeley DB installed on your system at all.
+ Solution: get & install Berkeley DB.
+
+ 2. You do have Berkeley DB installed, but it isn't in a standard place.
+ Solution: Edit config.in and set the LIB and INCLUDE variables to point
+ to the directories where libdb.a and db.h are installed.
+
+#error db.h is not for Berkeley DB at all.
+------------------------------------------
+
+If you get the error above when building this module it means that there
+is a file called "db.h" on your system that isn't the one that comes
+with Berkeley DB.
+
+Options:
+
+ 1. You don't have Berkeley DB installed on your system at all.
+ Solution: get & install Berkeley DB.
+
+ 2. Edit config.in and make sure the INCLUDE variable points to the
+ directory where the Berkeley DB file db.h is installed.
+
+ 3. If option 2 doesn't work, try tempoarily renaming the db.h file
+ that is causing the error.
+
+#error db.h is for Berkeley DB 1.x - need at least Berkeley DB 2.6.4
+--------------------------------------------------------------------
+
+The error above will occur if there is a copy of the Berkeley DB 1.x
+file db.h on your system.
+
+This error will happen when
+
+ 1. you only have Berkeley DB version 1 on your system.
+ Solution: get & install a newer version of Berkeley DB.
+
+ 2. you have both version 1 and a later version of Berkeley DB
+ installed on your system. When building BerkeleyDB it attempts to
+ use the db.h for Berkeley DB version 1.
+ Solution: Edit config.in and set the LIB and INCLUDE variables
+ to point to the directories where libdb.a and db.h are
+ installed.
+
+
+#error db.h is for Berkeley DB 2.0-2.5 - need at least Berkeley DB 2.6.4
+------------------------------------------------------------------------
+
+The error above will occur if there is a copy of the the file db.h for
+Berkeley DB 2.0 to 2.5 on your system.
+
+This symptom can imply:
+
+ 1. You don't have a new enough version of Berkeley DB.
+ Solution: get & install a newer version of Berkeley DB.
+
+ 2. You have the correct version of Berkeley DB installed, but it isn't
+ in a standard place.
+ Solution: Edit config.in and set the LIB and INCLUDE variables
+ to point to the directories where libdb.a and db.h are
+ installed.
+
+Undefined Symbol: txn_stat
+--------------------------
+
+BerkeleyDB seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ $ make test
+ PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00503
+ -Iblib/arch -Iblib/lib -I/usr/local/lib/perl5/5.00503/i586-linux
+ -I/usr/local/lib/perl5/5.00503 -e 'use Test::Harness qw(&runtests $verbose);
+ $verbose=0; runtests @ARGV;' t/*.t
+ t/btree.............Can't load 'blib/arch/auto/BerkeleyDB/BerkeleyDB.so' for
+ module BerkeleyDB: blib/arch/auto/BerkeleyDB/BerkeleyDB.so:
+ undefined symbol: txn_stat
+ at /usr/local/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.
+ ...
+
+This error usually happens when you have both version 1 and a newer version
+of Berkeley DB installed on your system. BerkeleyDB attempts
+to build using the db.h for Berkeley DB version 2/3/4 and the version 1
+library. Unfortunately the two versions aren't compatible with each
+other. BerkeleyDB can only be built with Berkeley DB version 2, 3 or 4.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want BerkeleyDB to use.
+
+Undefined Symbol: db_appinit
+----------------------------
+
+BerkeleyDB seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ $ make test
+ PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00561 -Iblib/arch
+ -Iblib/lib -I/home/paul/perl/install/5.005_61/lib/5.00561/i586-linux
+ -I/home/paul/perl/install/5.005_61/lib/5.00561 -e 'use Test::Harness
+ qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
+ t/btree.............Can't load 'blib/arch/auto/BerkeleyDB/BerkeleyDB.so' for
+ module BerkeleyDB: blib/arch/auto/BerkeleyDB/BerkeleyDB.so:
+ undefined symbol: db_appinit
+ at /home/paul/perl/install/5.005_61/lib/5.00561/i586-linux/DynaLoader.pm
+ ...
+
+
+This error usually happens when you have both version 2 and version
+3 of Berkeley DB installed on your system and BerkeleyDB attempts
+to build using the db.h for Berkeley DB version 2 and the version 3
+library. Unfortunately the two versions aren't compatible with each
+other.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want BerkeleyDB to use.
+
+Undefined Symbol: db_create
+---------------------------
+
+BerkeleyDB seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ $ make test
+ PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00561 -Iblib/arch
+ -Iblib/lib -I/home/paul/perl/install/5.005_61/lib/5.00561/i586-linux
+ -I/home/paul/perl/install/5.005_61/lib/5.00561 -e 'use Test::Harness
+ qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
+ t/btree.............Can't load 'blib/arch/auto/BerkeleyDB/BerkeleyDB.so' for
+ module BerkeleyDB: blib/arch/auto/BerkeleyDB/BerkeleyDB.so:
+ undefined symbol: db_create
+ at /home/paul/perl/install/5.005_61/lib/5.00561/i586-linux/DynaLoader.pm
+ ...
+
+This error usually happens when you have both version 2 and version
+3 of Berkeley DB installed on your system and BerkeleyDB attempts
+to build using the db.h for Berkeley DB version 3 and the version 2
+library. Unfortunately the two versions aren't compatible with each
+other.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want BerkeleyDB to use.
+
+
+Incompatible versions of db.h and libdb
+---------------------------------------
+
+BerkeleyDB seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ $ make test
+ PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00503
+ -Iblib/arch -Iblib/lib -I/usr/local/lib/perl5/5.00503/i586-linux
+ -I/usr/local/lib/perl5/5.00503 -e 'use Test::Harness qw(&runtests $verbose);
+ $verbose=0; runtests @ARGV;' t/*.t
+ t/btree.............
+ BerkeleyDB needs compatible versions of libdb & db.h
+ you have db.h version 2.6.4 and libdb version 2.7.5
+ BEGIN failed--compilation aborted at t/btree.t line 25.
+ dubious
+ Test returned status 255 (wstat 65280, 0xff00)
+ ...
+
+Another variation on the theme of having two versions of Berkeley DB on
+your system.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want BerkeleyDB to use.
+ If you are running Linux, please read the Linux Notes section below.
+
+
+Linux Notes
+-----------
+
+Newer versions of Linux (e.g. RedHat 6, SuSe 6) ship with a C library
+that has version 2.x of Berkeley DB linked into it. This makes it
+difficult to build this module with anything other than the version of
+Berkeley DB that shipped with your Linux release. If you do try to use
+a different version of Berkeley DB you will most likely get the error
+described in the "Incompatible versions of db.h and libdb" section of
+this file.
+
+To make matters worse, prior to Perl 5.6.1, the perl binary itself
+*always* included the Berkeley DB library.
+
+If you want to use a newer version of Berkeley DB with this module, the
+easiest solution is to use Perl 5.6.1 (or better) and Berkeley DB 3.x
+(or better).
+
+There are two approaches you can use to get older versions of Perl to
+work with specific versions of Berkeley DB. Both have their advantages
+and disadvantages.
+
+The first approach will only work when you want to build a version of
+Perl older than 5.6.1 along with Berkeley DB 3.x. If you want to use
+Berkeley DB 2.x, you must use the next approach. This approach involves
+rebuilding your existing version of Perl after applying an unofficial
+patch. The "patches" directory in the this module's source distribution
+contains a number of patch files. There is one patch file for every
+stable version of Perl since 5.004. Apply the appropriate patch to your
+Perl source tree before re-building and installing Perl from scratch.
+For example, assuming you are in the top-level source directory for
+Perl 5.6.0, the command below will apply the necessary patch. Remember
+to replace the path shown below with one that points to this module's
+patches directory.
+
+ patch -p1 -N </path/to/BerkeleyDB/patches/5.6.0
+
+Now rebuild & install perl. You should now have a perl binary that can
+be used to build this module. Follow the instructions in "BUILDING THE
+MODULE", remembering to set the INCLUDE and LIB variables in config.in.
+
+
+The second approach will work with Berkeley DB 2.x or better.
+Start by building Berkeley DB as a shared library. This is from
+the Berkeley DB build instructions:
+
+ Building Shared Libraries for the GNU GCC compiler
+
+ If you're using gcc and there's no better shared library example for
+ your architecture, the following shared library build procedure will
+ probably work.
+
+ Add the -fpic option to the CFLAGS value in the Makefile.
+
+ Rebuild all of your .o files. This will create a Berkeley DB library
+ that contains .o files with PIC code. To build the shared library,
+ then take the following steps in the library build directory:
+
+ % mkdir tmp
+ % cd tmp
+ % ar xv ../libdb.a
+ % gcc -shared -o libdb.so *.o
+ % mv libdb.so ..
+ % cd ..
+ % rm -rf tmp
+
+ Note, you may have to change the gcc line depending on the
+ requirements of your system.
+
+ The file libdb.so is your shared library
+
+Once you have built libdb.so, you will need to store it somewhere safe.
+
+ cp libdb.so /usr/local/BerkeleyDB/lib
+
+If you now set the LD_PRELOAD environment variable to point to this
+shared library, Perl will use it instead of the version of Berkeley DB
+that shipped with your Linux distribution.
+
+ export LD_PRELOAD=/usr/local/BerkeleyDB/lib/libdb.so
+
+Finally follow the instructions in "BUILDING THE MODULE" to build,
+test and install this module. Don't forget to set the INCLUDE and LIB
+variables in config.in.
+
+Remember, you will need to have the LD_PRELOAD variable set anytime you
+want to use Perl with Berkeley DB. Also note that if you have LD_PRELOAD
+permanently set it will affect ALL commands you execute. This may be a
+problem if you run any commands that access a database created by the
+version of Berkeley DB that shipped with your Linux distribution.
+
+
+
+Solaris 2.5 Notes
+-----------------
+
+If you are running Solaris 2.5, and you get this error when you run the
+BerkeleyDB test harness:
+
+ libc internal error: _rmutex_unlock: rmutex not held.
+
+you probably need to install a Sun patch. It has been reported that
+Sun patch 103187-25 (or later revisions) fixes this problem.
+
+To find out if you have the patch installed, the command "showrev -p"
+will display the patches that are currently installed on your system.
+
+Solaris 2.7 Notes
+-----------------
+
+If you are running Solaris 2.7 and all the tests in the test harness
+generate a core dump, try applying Sun patch 106980-09 (or better).
+
+To find out if you have the patch installed, the command "showrev -p"
+will display the patches that are currently installed on your system.
+
+
+HP-UX Notes
+-----------
+
+Some people running HP-UX 10 have reported getting an error like this
+when building this module with the native HP-UX compiler.
+
+ ld: (Warning) At least one PA 2.0 object file (BerkeleyDB.o) was detected.
+ The linked output may not run on a PA 1.x system.
+ ld: Invalid loader fixup for symbol "$000000A5".
+
+If this is the case for you, Berkeley DB needs to be recompiled with
+the +z or +Z option and the resulting library placed in a .sl file. The
+following steps should do the trick:
+
+ 1: Configure the Berkeley DB distribution with the +z or +Z C compiler
+ flag:
+
+ env "CFLAGS=+z" ../dist/configure ...
+
+ 2: Edit the Berkeley DB Makefile and change:
+
+ "libdb= libdb.a" to "libdb= libdb.sl".
+
+ 3: Build and install the Berkeley DB distribution as usual.
+
+
+
+FEEDBACK
+--------
+
+How to report a problem with BerkeleyDB.
+
+To help me help you, I need of the following information:
+
+ 1. The version of Perl and the operating system name and version you
+ are running. The complete output from running "perl -V" will tell
+ me all I need to know.
+ If your perl does not understand the "-V" option is too old.
+ BerkeleyDB needs Perl version 5.004_04 or better.
+
+ 2. The version of BerkeleyDB you have. If you have successfully
+ installed BerkeleyDB, this one-liner will tell you:
+
+ perl -MBerkeleyDB -e 'print qq{BerkeleyDB ver $BerkeleyDB::VERSION\n}'
+
+ If you haven't installed BerkeleyDB then search BerkeleyDB.pm for a
+ line like this:
+
+ $VERSION = "1.20" ;
+
+ 3. The version of Berkeley DB you have installed. If you have
+ successfully installed BerkeleyDB, this one-liner will tell you:
+
+ perl -MBerkeleyDB -e 'print BerkeleyDB::DB_VERSION_STRING.qq{\n}'
+
+ If you haven't installed BerkeleyDB then search db.h for a line
+ like this:
+
+ #define DB_VERSION_STRING
+
+ 4. If you are having problems building BerkeleyDB, send me a complete
+ log of what happened.
+
+ 5. Now the difficult one. If you think you have found a bug in
+ BerkeleyDB and you want me to fix it, you will *greatly* enhance
+ the chances of me being able to track it down by sending me a small
+ self-contained Perl script that illustrates the problem you are
+ encountering. Include a summary of what you think the problem is
+ and a log of what happens when you run the script, in case I can't
+ reproduce your problem on my system. If possible, don't have the
+ script dependent on an existing 20Meg database. If the script you
+ send me can create the database itself then that is preferred.
+
+ I realise that in some cases this is easier said than done, so if
+ you can only reproduce the problem in your existing script, then
+ you can post me that if you want. Just don't expect me to find your
+ problem in a hurry, or at all. :-)
+
+
+CHANGES
+-------
+
+See the Changes file.
+
+Paul Marquess <Paul.Marquess@btinternet.com>
+
diff --git a/bdb/perl.BerkeleyDB/Todo b/bdb/perl/BerkeleyDB/Todo
index 12d53bcf91c..12d53bcf91c 100644
--- a/bdb/perl.BerkeleyDB/Todo
+++ b/bdb/perl/BerkeleyDB/Todo
diff --git a/bdb/perl/BerkeleyDB/config.in b/bdb/perl/BerkeleyDB/config.in
new file mode 100644
index 00000000000..fd1bb1caede
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/config.in
@@ -0,0 +1,43 @@
+# Filename: config.in
+#
+# written by Paul Marquess <Paul.Marquess@btinternet.com>
+
+# 1. Where is the file db.h?
+#
+# Change the path below to point to the directory where db.h is
+# installed on your system.
+
+INCLUDE = /usr/local/include
+#INCLUDE = /usr/local/BerkeleyDB/include
+
+# 2. Where is libdb?
+#
+# Change the path below to point to the directory where libdb is
+# installed on your system.
+
+LIB = /usr/local/lib
+#LIB = /usr/local/BerkeleyDB/lib
+
+# 3. Is the library called libdb?
+#
+# If you have copies of both 1.x and 2.x Berkeley DB installed on
+# your system it can sometimes be tricky to make sure you are using
+# the correct one. Renaming one (or creating a symbolic link) to
+# include the version number of the library can help.
+#
+# For example, if you have Berkeley DB 2.6.4 you could rename the
+# Berkeley DB library from libdb.a to libdb-2.6.4.a and change the
+# DBNAME line below to look like this:
+#
+# DBNAME = -ldb-2.6.4
+#
+# Note: If you are building this module with Win32, -llibdb will be
+# used by default.
+#
+# If you have changed the name of the library, uncomment the line
+# below (by removing the leading #) and edit the line to use the name
+# you have picked.
+
+#DBNAME = -ldb-3.0
+
+# end of file config.in
diff --git a/bdb/perl/BerkeleyDB/constants.h b/bdb/perl/BerkeleyDB/constants.h
new file mode 100644
index 00000000000..d86cef15513
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/constants.h
@@ -0,0 +1,4046 @@
+#define PERL_constant_NOTFOUND 1
+#define PERL_constant_NOTDEF 2
+#define PERL_constant_ISIV 3
+#define PERL_constant_ISNO 4
+#define PERL_constant_ISNV 5
+#define PERL_constant_ISPV 6
+#define PERL_constant_ISPVN 7
+#define PERL_constant_ISSV 8
+#define PERL_constant_ISUNDEF 9
+#define PERL_constant_ISUV 10
+#define PERL_constant_ISYES 11
+
+#ifndef NVTYPE
+typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it. */
+#endif
+#ifndef aTHX_
+#define aTHX_ /* 5.6 or later define this for threading support. */
+#endif
+#ifndef pTHX_
+#define pTHX_ /* 5.6 or later define this for threading support. */
+#endif
+
+static int
+constant_6 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_DUP DB_PAD DB_RMW DB_SET */
+ /* Offset 3 gives the best switch position. */
+ switch (name[3]) {
+ case 'D':
+ if (memEQ(name, "DB_DUP", 6)) {
+ /* ^ */
+#ifdef DB_DUP
+ *iv_return = DB_DUP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_PAD", 6)) {
+ /* ^ */
+#ifdef DB_PAD
+ *iv_return = DB_PAD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_RMW", 6)) {
+ /* ^ */
+#ifdef DB_RMW
+ *iv_return = DB_RMW;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_SET", 6)) {
+ /* ^ */
+#ifdef DB_SET
+ *iv_return = DB_SET;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_7 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_EXCL DB_HASH DB_LAST DB_NEXT DB_PREV */
+ /* Offset 3 gives the best switch position. */
+ switch (name[3]) {
+ case 'E':
+ if (memEQ(name, "DB_EXCL", 7)) {
+ /* ^ */
+#ifdef DB_EXCL
+ *iv_return = DB_EXCL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'H':
+ if (memEQ(name, "DB_HASH", 7)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_HASH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_LAST", 7)) {
+ /* ^ */
+#ifdef DB_LAST
+ *iv_return = DB_LAST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_NEXT", 7)) {
+ /* ^ */
+#ifdef DB_NEXT
+ *iv_return = DB_NEXT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_PREV", 7)) {
+ /* ^ */
+#ifdef DB_PREV
+ *iv_return = DB_PREV;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_8 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_AFTER DB_BTREE DB_FIRST DB_FLUSH DB_FORCE DB_QUEUE DB_RECNO */
+ /* Offset 4 gives the best switch position. */
+ switch (name[4]) {
+ case 'E':
+ if (memEQ(name, "DB_RECNO", 8)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_RECNO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'F':
+ if (memEQ(name, "DB_AFTER", 8)) {
+ /* ^ */
+#ifdef DB_AFTER
+ *iv_return = DB_AFTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_FIRST", 8)) {
+ /* ^ */
+#ifdef DB_FIRST
+ *iv_return = DB_FIRST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_FLUSH", 8)) {
+ /* ^ */
+#ifdef DB_FLUSH
+ *iv_return = DB_FLUSH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_FORCE", 8)) {
+ /* ^ */
+#ifdef DB_FORCE
+ *iv_return = DB_FORCE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_BTREE", 8)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_BTREE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_QUEUE", 8)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 55)
+ *iv_return = DB_QUEUE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_9 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_APPEND DB_BEFORE DB_CLIENT DB_COMMIT DB_CREATE DB_CURLSN DB_DIRECT
+ DB_EXTENT DB_GETREC DB_NOCOPY DB_NOMMAP DB_NOSYNC DB_RDONLY DB_RECNUM
+ DB_THREAD DB_VERIFY */
+ /* Offset 7 gives the best switch position. */
+ switch (name[7]) {
+ case 'A':
+ if (memEQ(name, "DB_NOMMAP", 9)) {
+ /* ^ */
+#ifdef DB_NOMMAP
+ *iv_return = DB_NOMMAP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_THREAD", 9)) {
+ /* ^ */
+#ifdef DB_THREAD
+ *iv_return = DB_THREAD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'C':
+ if (memEQ(name, "DB_DIRECT", 9)) {
+ /* ^ */
+#ifdef DB_DIRECT
+ *iv_return = DB_DIRECT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_GETREC", 9)) {
+ /* ^ */
+#ifdef DB_GETREC
+ *iv_return = DB_GETREC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'F':
+ if (memEQ(name, "DB_VERIFY", 9)) {
+ /* ^ */
+#ifdef DB_VERIFY
+ *iv_return = DB_VERIFY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_COMMIT", 9)) {
+ /* ^ */
+#ifdef DB_COMMIT
+ *iv_return = DB_COMMIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_RDONLY", 9)) {
+ /* ^ */
+#ifdef DB_RDONLY
+ *iv_return = DB_RDONLY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_APPEND", 9)) {
+ /* ^ */
+#ifdef DB_APPEND
+ *iv_return = DB_APPEND;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_CLIENT", 9)) {
+ /* ^ */
+#ifdef DB_CLIENT
+ *iv_return = DB_CLIENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_EXTENT", 9)) {
+ /* ^ */
+#ifdef DB_EXTENT
+ *iv_return = DB_EXTENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NOSYNC", 9)) {
+ /* ^ */
+#ifdef DB_NOSYNC
+ *iv_return = DB_NOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_NOCOPY", 9)) {
+ /* ^ */
+#ifdef DB_NOCOPY
+ *iv_return = DB_NOCOPY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_BEFORE", 9)) {
+ /* ^ */
+#ifdef DB_BEFORE
+ *iv_return = DB_BEFORE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_CURLSN", 9)) {
+ /* ^ */
+#ifdef DB_CURLSN
+ *iv_return = DB_CURLSN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_CREATE", 9)) {
+ /* ^ */
+#ifdef DB_CREATE
+ *iv_return = DB_CREATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_RECNUM", 9)) {
+ /* ^ */
+#ifdef DB_RECNUM
+ *iv_return = DB_RECNUM;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_10 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_CONSUME DB_CURRENT DB_DELETED DB_DUPSORT DB_ENCRYPT DB_ENV_CDB
+ DB_ENV_TXN DB_JOINENV DB_KEYLAST DB_NOPANIC DB_OK_HASH DB_PRIVATE
+ DB_PR_PAGE DB_RECOVER DB_SALVAGE DB_TIMEOUT DB_TXN_CKP DB_UNKNOWN
+ DB_UPGRADE */
+ /* Offset 8 gives the best switch position. */
+ switch (name[8]) {
+ case 'D':
+ if (memEQ(name, "DB_ENV_CDB", 10)) {
+ /* ^ */
+#ifdef DB_ENV_CDB
+ *iv_return = DB_ENV_CDB;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_UPGRADE", 10)) {
+ /* ^ */
+#ifdef DB_UPGRADE
+ *iv_return = DB_UPGRADE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_DELETED", 10)) {
+ /* ^ */
+#ifdef DB_DELETED
+ *iv_return = DB_DELETED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_RECOVER", 10)) {
+ /* ^ */
+#ifdef DB_RECOVER
+ *iv_return = DB_RECOVER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_PR_PAGE", 10)) {
+ /* ^ */
+#ifdef DB_PR_PAGE
+ *iv_return = DB_PR_PAGE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_SALVAGE", 10)) {
+ /* ^ */
+#ifdef DB_SALVAGE
+ *iv_return = DB_SALVAGE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_NOPANIC", 10)) {
+ /* ^ */
+#ifdef DB_NOPANIC
+ *iv_return = DB_NOPANIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'K':
+ if (memEQ(name, "DB_TXN_CKP", 10)) {
+ /* ^ */
+#ifdef DB_TXN_CKP
+ *iv_return = DB_TXN_CKP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_CONSUME", 10)) {
+ /* ^ */
+#ifdef DB_CONSUME
+ *iv_return = DB_CONSUME;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_CURRENT", 10)) {
+ /* ^ */
+#ifdef DB_CURRENT
+ *iv_return = DB_CURRENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_JOINENV", 10)) {
+ /* ^ */
+#ifdef DB_JOINENV
+ *iv_return = DB_JOINENV;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_ENCRYPT", 10)) {
+ /* ^ */
+#ifdef DB_ENCRYPT
+ *iv_return = DB_ENCRYPT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_DUPSORT", 10)) {
+ /* ^ */
+#ifdef DB_DUPSORT
+ *iv_return = DB_DUPSORT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_KEYLAST", 10)) {
+ /* ^ */
+#ifdef DB_KEYLAST
+ *iv_return = DB_KEYLAST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_OK_HASH", 10)) {
+ /* ^ */
+#ifdef DB_OK_HASH
+ *iv_return = DB_OK_HASH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_PRIVATE", 10)) {
+ /* ^ */
+#ifdef DB_PRIVATE
+ *iv_return = DB_PRIVATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_TIMEOUT", 10)) {
+ /* ^ */
+#ifdef DB_TIMEOUT
+ *iv_return = DB_TIMEOUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'W':
+ if (memEQ(name, "DB_UNKNOWN", 10)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_UNKNOWN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'X':
+ if (memEQ(name, "DB_ENV_TXN", 10)) {
+ /* ^ */
+#ifdef DB_ENV_TXN
+ *iv_return = DB_ENV_TXN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_11 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_APP_INIT DB_ARCH_ABS DB_ARCH_LOG DB_FIXEDLEN DB_GET_BOTH DB_INIT_CDB
+ DB_INIT_LOG DB_INIT_TXN DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_LOCKDOWN
+ DB_LOCK_GET DB_LOCK_PUT DB_LOGMAGIC DB_LOG_DISK DB_MULTIPLE DB_NEXT_DUP
+ DB_NOSERVER DB_NOTFOUND DB_OK_BTREE DB_OK_QUEUE DB_OK_RECNO DB_POSITION
+ DB_QAMMAGIC DB_RENUMBER DB_SNAPSHOT DB_TRUNCATE DB_TXNMAGIC DB_TXN_LOCK
+ DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO DB_WRNOSYNC DB_YIELDCPU */
+ /* Offset 8 gives the best switch position. */
+ switch (name[8]) {
+ case 'A':
+ if (memEQ(name, "DB_ARCH_ABS", 11)) {
+ /* ^ */
+#ifdef DB_ARCH_ABS
+ *iv_return = DB_ARCH_ABS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TRUNCATE", 11)) {
+ /* ^ */
+#ifdef DB_TRUNCATE
+ *iv_return = DB_TRUNCATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'B':
+ if (memEQ(name, "DB_RENUMBER", 11)) {
+ /* ^ */
+#ifdef DB_RENUMBER
+ *iv_return = DB_RENUMBER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'C':
+ if (memEQ(name, "DB_INIT_CDB", 11)) {
+ /* ^ */
+#ifdef DB_INIT_CDB
+ *iv_return = DB_INIT_CDB;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_OK_RECNO", 11)) {
+ /* ^ */
+#ifdef DB_OK_RECNO
+ *iv_return = DB_OK_RECNO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_YIELDCPU", 11)) {
+ /* ^ */
+#ifdef DB_YIELDCPU
+ *iv_return = DB_YIELDCPU;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'D':
+ if (memEQ(name, "DB_NEXT_DUP", 11)) {
+ /* ^ */
+#ifdef DB_NEXT_DUP
+ *iv_return = DB_NEXT_DUP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_OK_QUEUE", 11)) {
+ /* ^ */
+#ifdef DB_OK_QUEUE
+ *iv_return = DB_OK_QUEUE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_REDO", 11)) {
+ /* ^ */
+#ifdef DB_TXN_REDO
+ *iv_return = DB_TXN_REDO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_LOCK_GET", 11)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_LOCK_GET;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOGMAGIC", 11)) {
+ /* ^ */
+#ifdef DB_LOGMAGIC
+ *iv_return = DB_LOGMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_QAMMAGIC", 11)) {
+ /* ^ */
+#ifdef DB_QAMMAGIC
+ *iv_return = DB_QAMMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXNMAGIC", 11)) {
+ /* ^ */
+#ifdef DB_TXNMAGIC
+ *iv_return = DB_TXNMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'H':
+ if (memEQ(name, "DB_SNAPSHOT", 11)) {
+ /* ^ */
+#ifdef DB_SNAPSHOT
+ *iv_return = DB_SNAPSHOT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_KEYEXIST", 11)) {
+ /* ^ */
+#ifdef DB_KEYEXIST
+ *iv_return = DB_KEYEXIST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOG_DISK", 11)) {
+ /* ^ */
+#ifdef DB_LOG_DISK
+ *iv_return = DB_LOG_DISK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_POSITION", 11)) {
+ /* ^ */
+#ifdef DB_POSITION
+ *iv_return = DB_POSITION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_ARCH_LOG", 11)) {
+ /* ^ */
+#ifdef DB_ARCH_LOG
+ *iv_return = DB_ARCH_LOG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_FIXEDLEN", 11)) {
+ /* ^ */
+#ifdef DB_FIXEDLEN
+ *iv_return = DB_FIXEDLEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_INIT_LOG", 11)) {
+ /* ^ */
+#ifdef DB_INIT_LOG
+ *iv_return = DB_INIT_LOG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_APP_INIT", 11)) {
+ /* ^ */
+#ifdef DB_APP_INIT
+ *iv_return = DB_APP_INIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_UNDO", 11)) {
+ /* ^ */
+#ifdef DB_TXN_UNDO
+ *iv_return = DB_TXN_UNDO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_GET_BOTH", 11)) {
+ /* ^ */
+#ifdef DB_GET_BOTH
+ *iv_return = DB_GET_BOTH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCKDOWN", 11)) {
+ /* ^ */
+#ifdef DB_LOCKDOWN
+ *iv_return = DB_LOCKDOWN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_LOCK", 11)) {
+ /* ^ */
+#ifdef DB_TXN_LOCK
+ *iv_return = DB_TXN_LOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_KEYEMPTY", 11)) {
+ /* ^ */
+#ifdef DB_KEYEMPTY
+ *iv_return = DB_KEYEMPTY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_PUT", 11)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_LOCK_PUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MULTIPLE", 11)) {
+ /* ^ */
+#ifdef DB_MULTIPLE
+ *iv_return = DB_MULTIPLE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_KEYFIRST", 11)) {
+ /* ^ */
+#ifdef DB_KEYFIRST
+ *iv_return = DB_KEYFIRST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_OK_BTREE", 11)) {
+ /* ^ */
+#ifdef DB_OK_BTREE
+ *iv_return = DB_OK_BTREE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_INIT_TXN", 11)) {
+ /* ^ */
+#ifdef DB_INIT_TXN
+ *iv_return = DB_INIT_TXN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_NOTFOUND", 11)) {
+ /* ^ */
+#ifdef DB_NOTFOUND
+ *iv_return = DB_NOTFOUND;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'V':
+ if (memEQ(name, "DB_NOSERVER", 11)) {
+ /* ^ */
+#ifdef DB_NOSERVER
+ *iv_return = DB_NOSERVER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'Y':
+ if (memEQ(name, "DB_TXN_SYNC", 11)) {
+ /* ^ */
+#ifdef DB_TXN_SYNC
+ *iv_return = DB_TXN_SYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_WRNOSYNC", 11)) {
+ /* ^ */
+#ifdef DB_WRNOSYNC
+ *iv_return = DB_WRNOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_12 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_ARCH_DATA DB_CDB_ALLDB DB_CL_WRITER DB_DELIMITER DB_DIRECT_DB
+ DB_DUPCURSOR DB_ENV_FATAL DB_FAST_STAT DB_GET_BOTHC DB_GET_RECNO
+ DB_HASHMAGIC DB_INIT_LOCK DB_JOIN_ITEM DB_LOCKMAGIC DB_LOCK_DUMP
+ DB_LOCK_RW_N DB_LOGOLDVER DB_MAX_PAGES DB_MPOOL_NEW DB_NEEDSPLIT
+ DB_NODUPDATA DB_NOLOCKING DB_NORECURSE DB_OVERWRITE DB_PAGEYIELD
+ DB_PAGE_LOCK DB_PERMANENT DB_POSITIONI DB_PRINTABLE DB_QAMOLDVER
+ DB_SET_RANGE DB_SET_RECNO DB_SWAPBYTES DB_TEMPORARY DB_TXN_ABORT
+ DB_TXN_APPLY DB_TXN_PRINT DB_WRITELOCK DB_WRITEOPEN DB_XA_CREATE */
+ /* Offset 3 gives the best switch position. */
+ switch (name[3]) {
+ case 'A':
+ if (memEQ(name, "DB_ARCH_DATA", 12)) {
+ /* ^ */
+#ifdef DB_ARCH_DATA
+ *iv_return = DB_ARCH_DATA;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'C':
+ if (memEQ(name, "DB_CDB_ALLDB", 12)) {
+ /* ^ */
+#ifdef DB_CDB_ALLDB
+ *iv_return = DB_CDB_ALLDB;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_CL_WRITER", 12)) {
+ /* ^ */
+#ifdef DB_CL_WRITER
+ *iv_return = DB_CL_WRITER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'D':
+ if (memEQ(name, "DB_DELIMITER", 12)) {
+ /* ^ */
+#ifdef DB_DELIMITER
+ *iv_return = DB_DELIMITER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_DIRECT_DB", 12)) {
+ /* ^ */
+#ifdef DB_DIRECT_DB
+ *iv_return = DB_DIRECT_DB;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_DUPCURSOR", 12)) {
+ /* ^ */
+#ifdef DB_DUPCURSOR
+ *iv_return = DB_DUPCURSOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_ENV_FATAL", 12)) {
+ /* ^ */
+#ifdef DB_ENV_FATAL
+ *iv_return = DB_ENV_FATAL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'F':
+ if (memEQ(name, "DB_FAST_STAT", 12)) {
+ /* ^ */
+#ifdef DB_FAST_STAT
+ *iv_return = DB_FAST_STAT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_GET_BOTHC", 12)) {
+ /* ^ */
+#ifdef DB_GET_BOTHC
+ *iv_return = DB_GET_BOTHC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_GET_RECNO", 12)) {
+ /* ^ */
+#ifdef DB_GET_RECNO
+ *iv_return = DB_GET_RECNO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'H':
+ if (memEQ(name, "DB_HASHMAGIC", 12)) {
+ /* ^ */
+#ifdef DB_HASHMAGIC
+ *iv_return = DB_HASHMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_INIT_LOCK", 12)) {
+ /* ^ */
+#ifdef DB_INIT_LOCK
+ *iv_return = DB_INIT_LOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'J':
+ if (memEQ(name, "DB_JOIN_ITEM", 12)) {
+ /* ^ */
+#ifdef DB_JOIN_ITEM
+ *iv_return = DB_JOIN_ITEM;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_LOCKMAGIC", 12)) {
+ /* ^ */
+#ifdef DB_LOCKMAGIC
+ *iv_return = DB_LOCKMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_DUMP", 12)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_LOCK_DUMP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_RW_N", 12)) {
+ /* ^ */
+#ifdef DB_LOCK_RW_N
+ *iv_return = DB_LOCK_RW_N;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOGOLDVER", 12)) {
+ /* ^ */
+#ifdef DB_LOGOLDVER
+ *iv_return = DB_LOGOLDVER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_MAX_PAGES", 12)) {
+ /* ^ */
+#ifdef DB_MAX_PAGES
+ *iv_return = DB_MAX_PAGES;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MPOOL_NEW", 12)) {
+ /* ^ */
+#ifdef DB_MPOOL_NEW
+ *iv_return = DB_MPOOL_NEW;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_NEEDSPLIT", 12)) {
+ /* ^ */
+#ifdef DB_NEEDSPLIT
+ *iv_return = DB_NEEDSPLIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NODUPDATA", 12)) {
+ /* ^ */
+#ifdef DB_NODUPDATA
+ *iv_return = DB_NODUPDATA;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NOLOCKING", 12)) {
+ /* ^ */
+#ifdef DB_NOLOCKING
+ *iv_return = DB_NOLOCKING;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NORECURSE", 12)) {
+ /* ^ */
+#ifdef DB_NORECURSE
+ *iv_return = DB_NORECURSE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_OVERWRITE", 12)) {
+ /* ^ */
+#ifdef DB_OVERWRITE
+ *iv_return = DB_OVERWRITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_PAGEYIELD", 12)) {
+ /* ^ */
+#ifdef DB_PAGEYIELD
+ *iv_return = DB_PAGEYIELD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_PAGE_LOCK", 12)) {
+ /* ^ */
+#ifdef DB_PAGE_LOCK
+ *iv_return = DB_PAGE_LOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_PERMANENT", 12)) {
+ /* ^ */
+#ifdef DB_PERMANENT
+ *iv_return = DB_PERMANENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_POSITIONI", 12)) {
+ /* ^ */
+#ifdef DB_POSITIONI
+ *iv_return = DB_POSITIONI;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_PRINTABLE", 12)) {
+ /* ^ */
+#ifdef DB_PRINTABLE
+ *iv_return = DB_PRINTABLE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'Q':
+ if (memEQ(name, "DB_QAMOLDVER", 12)) {
+ /* ^ */
+#ifdef DB_QAMOLDVER
+ *iv_return = DB_QAMOLDVER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_SET_RANGE", 12)) {
+ /* ^ */
+#ifdef DB_SET_RANGE
+ *iv_return = DB_SET_RANGE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_SET_RECNO", 12)) {
+ /* ^ */
+#ifdef DB_SET_RECNO
+ *iv_return = DB_SET_RECNO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_SWAPBYTES", 12)) {
+ /* ^ */
+#ifdef DB_SWAPBYTES
+ *iv_return = DB_SWAPBYTES;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_TEMPORARY", 12)) {
+ /* ^ */
+#ifdef DB_TEMPORARY
+ *iv_return = DB_TEMPORARY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_ABORT", 12)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 12)
+ *iv_return = DB_TXN_ABORT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_APPLY", 12)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 7)
+ *iv_return = DB_TXN_APPLY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_PRINT", 12)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_TXN_PRINT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'W':
+ if (memEQ(name, "DB_WRITELOCK", 12)) {
+ /* ^ */
+#ifdef DB_WRITELOCK
+ *iv_return = DB_WRITELOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_WRITEOPEN", 12)) {
+ /* ^ */
+#ifdef DB_WRITEOPEN
+ *iv_return = DB_WRITEOPEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'X':
+ if (memEQ(name, "DB_XA_CREATE", 12)) {
+ /* ^ */
+#ifdef DB_XA_CREATE
+ *iv_return = DB_XA_CREATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_13 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_AGGRESSIVE DB_BTREEMAGIC DB_CHECKPOINT DB_DIRECT_LOG DB_DIRTY_READ
+ DB_DONOTINDEX DB_ENV_CREATE DB_ENV_NOMMAP DB_ENV_THREAD DB_HASHOLDVER
+ DB_INCOMPLETE DB_INIT_MPOOL DB_LOCK_NORUN DB_LOCK_RIW_N DB_LOCK_TRADE
+ DB_LOGVERSION DB_LOG_LOCKED DB_MPOOL_LAST DB_MUTEXDEBUG DB_MUTEXLOCKS
+ DB_NEXT_NODUP DB_NOORDERCHK DB_PREV_NODUP DB_PR_HEADERS DB_QAMVERSION
+ DB_RDWRMASTER DB_REGISTERED DB_REP_CLIENT DB_REP_MASTER DB_SEQUENTIAL
+ DB_STAT_CLEAR DB_SYSTEM_MEM DB_TXNVERSION DB_TXN_NOSYNC DB_TXN_NOWAIT
+ DB_VERIFY_BAD */
+ /* Offset 5 gives the best switch position. */
+ switch (name[5]) {
+ case 'A':
+ if (memEQ(name, "DB_STAT_CLEAR", 13)) {
+ /* ^ */
+#ifdef DB_STAT_CLEAR
+ *iv_return = DB_STAT_CLEAR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'C':
+ if (memEQ(name, "DB_INCOMPLETE", 13)) {
+ /* ^ */
+#ifdef DB_INCOMPLETE
+ *iv_return = DB_INCOMPLETE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_NORUN", 13)) {
+ /* ^ */
+#ifdef DB_LOCK_NORUN
+ *iv_return = DB_LOCK_NORUN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_RIW_N", 13)) {
+ /* ^ */
+#ifdef DB_LOCK_RIW_N
+ *iv_return = DB_LOCK_RIW_N;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_TRADE", 13)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_LOCK_TRADE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_CHECKPOINT", 13)) {
+ /* ^ */
+#ifdef DB_CHECKPOINT
+ *iv_return = DB_CHECKPOINT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_PREV_NODUP", 13)) {
+ /* ^ */
+#ifdef DB_PREV_NODUP
+ *iv_return = DB_PREV_NODUP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_AGGRESSIVE", 13)) {
+ /* ^ */
+#ifdef DB_AGGRESSIVE
+ *iv_return = DB_AGGRESSIVE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOGVERSION", 13)) {
+ /* ^ */
+#ifdef DB_LOGVERSION
+ *iv_return = DB_LOGVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOG_LOCKED", 13)) {
+ /* ^ */
+#ifdef DB_LOG_LOCKED
+ *iv_return = DB_LOG_LOCKED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REGISTERED", 13)) {
+ /* ^ */
+#ifdef DB_REGISTERED
+ *iv_return = DB_REGISTERED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_INIT_MPOOL", 13)) {
+ /* ^ */
+#ifdef DB_INIT_MPOOL
+ *iv_return = DB_INIT_MPOOL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_QAMVERSION", 13)) {
+ /* ^ */
+#ifdef DB_QAMVERSION
+ *iv_return = DB_QAMVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_DONOTINDEX", 13)) {
+ /* ^ */
+#ifdef DB_DONOTINDEX
+ *iv_return = DB_DONOTINDEX;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXNVERSION", 13)) {
+ /* ^ */
+#ifdef DB_TXNVERSION
+ *iv_return = DB_TXNVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_NOSYNC", 13)) {
+ /* ^ */
+#ifdef DB_TXN_NOSYNC
+ *iv_return = DB_TXN_NOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_NOWAIT", 13)) {
+ /* ^ */
+#ifdef DB_TXN_NOWAIT
+ *iv_return = DB_TXN_NOWAIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_MPOOL_LAST", 13)) {
+ /* ^ */
+#ifdef DB_MPOOL_LAST
+ *iv_return = DB_MPOOL_LAST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NOORDERCHK", 13)) {
+ /* ^ */
+#ifdef DB_NOORDERCHK
+ *iv_return = DB_NOORDERCHK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_REP_CLIENT", 13)) {
+ /* ^ */
+#ifdef DB_REP_CLIENT
+ *iv_return = DB_REP_CLIENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REP_MASTER", 13)) {
+ /* ^ */
+#ifdef DB_REP_MASTER
+ *iv_return = DB_REP_MASTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'Q':
+ if (memEQ(name, "DB_SEQUENTIAL", 13)) {
+ /* ^ */
+#ifdef DB_SEQUENTIAL
+ *iv_return = DB_SEQUENTIAL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_BTREEMAGIC", 13)) {
+ /* ^ */
+#ifdef DB_BTREEMAGIC
+ *iv_return = DB_BTREEMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_DIRECT_LOG", 13)) {
+ /* ^ */
+#ifdef DB_DIRECT_LOG
+ *iv_return = DB_DIRECT_LOG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_DIRTY_READ", 13)) {
+ /* ^ */
+#ifdef DB_DIRTY_READ
+ *iv_return = DB_DIRTY_READ;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERIFY_BAD", 13)) {
+ /* ^ */
+#ifdef DB_VERIFY_BAD
+ *iv_return = DB_VERIFY_BAD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_HASHOLDVER", 13)) {
+ /* ^ */
+#ifdef DB_HASHOLDVER
+ *iv_return = DB_HASHOLDVER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_SYSTEM_MEM", 13)) {
+ /* ^ */
+#ifdef DB_SYSTEM_MEM
+ *iv_return = DB_SYSTEM_MEM;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_MUTEXDEBUG", 13)) {
+ /* ^ */
+#ifdef DB_MUTEXDEBUG
+ *iv_return = DB_MUTEXDEBUG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MUTEXLOCKS", 13)) {
+ /* ^ */
+#ifdef DB_MUTEXLOCKS
+ *iv_return = DB_MUTEXLOCKS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'V':
+ if (memEQ(name, "DB_ENV_CREATE", 13)) {
+ /* ^ */
+#ifdef DB_ENV_CREATE
+ *iv_return = DB_ENV_CREATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ENV_NOMMAP", 13)) {
+ /* ^ */
+#ifdef DB_ENV_NOMMAP
+ *iv_return = DB_ENV_NOMMAP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ENV_THREAD", 13)) {
+ /* ^ */
+#ifdef DB_ENV_THREAD
+ *iv_return = DB_ENV_THREAD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'W':
+ if (memEQ(name, "DB_RDWRMASTER", 13)) {
+ /* ^ */
+#ifdef DB_RDWRMASTER
+ *iv_return = DB_RDWRMASTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'X':
+ if (memEQ(name, "DB_NEXT_NODUP", 13)) {
+ /* ^ */
+#ifdef DB_NEXT_NODUP
+ *iv_return = DB_NEXT_NODUP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_PR_HEADERS", 13)) {
+ /* ^ */
+#ifdef DB_PR_HEADERS
+ *iv_return = DB_PR_HEADERS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_14 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_AUTO_COMMIT DB_BTREEOLDVER DB_CHKSUM_SHA1 DB_EID_INVALID DB_ENCRYPT_AES
+ DB_ENV_APPINIT DB_ENV_DBLOCAL DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_NOPANIC
+ DB_ENV_PRIVATE DB_FILE_ID_LEN DB_HANDLE_LOCK DB_HASHVERSION DB_INVALID_EID
+ DB_JOIN_NOSORT DB_LOCKVERSION DB_LOCK_EXPIRE DB_LOCK_NOWAIT DB_LOCK_OLDEST
+ DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_REMOVE DB_LOCK_SWITCH DB_MAX_RECORDS
+ DB_MPOOL_CLEAN DB_MPOOL_DIRTY DB_NOOVERWRITE DB_NOSERVER_ID DB_ODDFILESIZE
+ DB_OLD_VERSION DB_OPEN_CALLED DB_RECORDCOUNT DB_RECORD_LOCK DB_REGION_ANON
+ DB_REGION_INIT DB_REGION_NAME DB_RENAMEMAGIC DB_REP_NEWSITE DB_REP_UNAVAIL
+ DB_REVSPLITOFF DB_RUNRECOVERY DB_SET_TXN_NOW DB_USE_ENVIRON DB_WRITECURSOR
+ DB_XIDDATASIZE */
+ /* Offset 9 gives the best switch position. */
+ switch (name[9]) {
+ case 'A':
+ if (memEQ(name, "DB_LOCK_RANDOM", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_RANDOM
+ *iv_return = DB_LOCK_RANDOM;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_OPEN_CALLED", 14)) {
+ /* ^ */
+#ifdef DB_OPEN_CALLED
+ *iv_return = DB_OPEN_CALLED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REP_UNAVAIL", 14)) {
+ /* ^ */
+#ifdef DB_REP_UNAVAIL
+ *iv_return = DB_REP_UNAVAIL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_XIDDATASIZE", 14)) {
+ /* ^ */
+#ifdef DB_XIDDATASIZE
+ *iv_return = DB_XIDDATASIZE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'C':
+ if (memEQ(name, "DB_ENV_LOCKING", 14)) {
+ /* ^ */
+#ifdef DB_ENV_LOCKING
+ *iv_return = DB_ENV_LOCKING;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MAX_RECORDS", 14)) {
+ /* ^ */
+#ifdef DB_MAX_RECORDS
+ *iv_return = DB_MAX_RECORDS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MPOOL_CLEAN", 14)) {
+ /* ^ */
+#ifdef DB_MPOOL_CLEAN
+ *iv_return = DB_MPOOL_CLEAN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_RECORDCOUNT", 14)) {
+ /* ^ */
+#ifdef DB_RECORDCOUNT
+ *iv_return = DB_RECORDCOUNT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'D':
+ if (memEQ(name, "DB_FILE_ID_LEN", 14)) {
+ /* ^ */
+#ifdef DB_FILE_ID_LEN
+ *iv_return = DB_FILE_ID_LEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_INVALID_EID", 14)) {
+ /* ^ */
+#ifdef DB_INVALID_EID
+ *iv_return = DB_INVALID_EID;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MPOOL_DIRTY", 14)) {
+ /* ^ */
+#ifdef DB_MPOOL_DIRTY
+ *iv_return = DB_MPOOL_DIRTY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_LOCK_RECORD", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_RECORD
+ *iv_return = DB_LOCK_RECORD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_REMOVE", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_REMOVE
+ *iv_return = DB_LOCK_REMOVE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NOSERVER_ID", 14)) {
+ /* ^ */
+#ifdef DB_NOSERVER_ID
+ *iv_return = DB_NOSERVER_ID;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ODDFILESIZE", 14)) {
+ /* ^ */
+#ifdef DB_ODDFILESIZE
+ *iv_return = DB_ODDFILESIZE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_ENV_LOGGING", 14)) {
+ /* ^ */
+#ifdef DB_ENV_LOGGING
+ *iv_return = DB_ENV_LOGGING;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_ENV_PRIVATE", 14)) {
+ /* ^ */
+#ifdef DB_ENV_PRIVATE
+ *iv_return = DB_ENV_PRIVATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REVSPLITOFF", 14)) {
+ /* ^ */
+#ifdef DB_REVSPLITOFF
+ *iv_return = DB_REVSPLITOFF;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_BTREEOLDVER", 14)) {
+ /* ^ */
+#ifdef DB_BTREEOLDVER
+ *iv_return = DB_BTREEOLDVER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ENV_DBLOCAL", 14)) {
+ /* ^ */
+#ifdef DB_ENV_DBLOCAL
+ *iv_return = DB_ENV_DBLOCAL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_OLDEST", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_OLDEST
+ *iv_return = DB_LOCK_OLDEST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_RENAMEMAGIC", 14)) {
+ /* ^ */
+#ifdef DB_RENAMEMAGIC
+ *iv_return = DB_RENAMEMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_SET_TXN_NOW", 14)) {
+ /* ^ */
+#ifdef DB_SET_TXN_NOW
+ *iv_return = DB_SET_TXN_NOW;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_AUTO_COMMIT", 14)) {
+ /* ^ */
+#ifdef DB_AUTO_COMMIT
+ *iv_return = DB_AUTO_COMMIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_JOIN_NOSORT", 14)) {
+ /* ^ */
+#ifdef DB_JOIN_NOSORT
+ *iv_return = DB_JOIN_NOSORT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_NOWAIT", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_NOWAIT
+ *iv_return = DB_LOCK_NOWAIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_RUNRECOVERY", 14)) {
+ /* ^ */
+#ifdef DB_RUNRECOVERY
+ *iv_return = DB_RUNRECOVERY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_ENV_APPINIT", 14)) {
+ /* ^ */
+#ifdef DB_ENV_APPINIT
+ *iv_return = DB_ENV_APPINIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ENV_NOPANIC", 14)) {
+ /* ^ */
+#ifdef DB_ENV_NOPANIC
+ *iv_return = DB_ENV_NOPANIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_HASHVERSION", 14)) {
+ /* ^ */
+#ifdef DB_HASHVERSION
+ *iv_return = DB_HASHVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCKVERSION", 14)) {
+ /* ^ */
+#ifdef DB_LOCKVERSION
+ *iv_return = DB_LOCKVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_OLD_VERSION", 14)) {
+ /* ^ */
+#ifdef DB_OLD_VERSION
+ *iv_return = DB_OLD_VERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_ENCRYPT_AES", 14)) {
+ /* ^ */
+#ifdef DB_ENCRYPT_AES
+ *iv_return = DB_ENCRYPT_AES;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_WRITECURSOR", 14)) {
+ /* ^ */
+#ifdef DB_WRITECURSOR
+ *iv_return = DB_WRITECURSOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'V':
+ if (memEQ(name, "DB_EID_INVALID", 14)) {
+ /* ^ */
+#ifdef DB_EID_INVALID
+ *iv_return = DB_EID_INVALID;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_USE_ENVIRON", 14)) {
+ /* ^ */
+#ifdef DB_USE_ENVIRON
+ *iv_return = DB_USE_ENVIRON;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'W':
+ if (memEQ(name, "DB_LOCK_SWITCH", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_SWITCH
+ *iv_return = DB_LOCK_SWITCH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_NOOVERWRITE", 14)) {
+ /* ^ */
+#ifdef DB_NOOVERWRITE
+ *iv_return = DB_NOOVERWRITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REP_NEWSITE", 14)) {
+ /* ^ */
+#ifdef DB_REP_NEWSITE
+ *iv_return = DB_REP_NEWSITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'X':
+ if (memEQ(name, "DB_LOCK_EXPIRE", 14)) {
+ /* ^ */
+#ifdef DB_LOCK_EXPIRE
+ *iv_return = DB_LOCK_EXPIRE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_CHKSUM_SHA1", 14)) {
+ /* ^ */
+#ifdef DB_CHKSUM_SHA1
+ *iv_return = DB_CHKSUM_SHA1;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_HANDLE_LOCK", 14)) {
+ /* ^ */
+#ifdef DB_HANDLE_LOCK
+ *iv_return = DB_HANDLE_LOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_RECORD_LOCK", 14)) {
+ /* ^ */
+#ifdef DB_RECORD_LOCK
+ *iv_return = DB_RECORD_LOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REGION_ANON", 14)) {
+ /* ^ */
+#ifdef DB_REGION_ANON
+ *iv_return = DB_REGION_ANON;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REGION_INIT", 14)) {
+ /* ^ */
+#ifdef DB_REGION_INIT
+ *iv_return = DB_REGION_INIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REGION_NAME", 14)) {
+ /* ^ */
+#ifdef DB_REGION_NAME
+ *iv_return = DB_REGION_NAME;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_15 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_APPLY_LOGREG DB_BTREEVERSION DB_CONSUME_WAIT DB_ENV_LOCKDOWN
+ DB_ENV_PANIC_OK DB_ENV_YIELDCPU DB_LOCK_DEFAULT DB_LOCK_INHERIT
+ DB_LOCK_NOTHELD DB_LOCK_PUT_ALL DB_LOCK_PUT_OBJ DB_LOCK_TIMEOUT
+ DB_LOCK_UPGRADE DB_MPOOL_CREATE DB_MPOOL_EXTENT DB_MULTIPLE_KEY
+ DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_PRIORITY_LOW DB_REGION_MAGIC
+ DB_REP_LOGSONLY DB_REP_OUTDATED DB_SURPRISE_KID DB_TEST_POSTLOG
+ DB_TEST_PREOPEN DB_TXN_GETPGNOS DB_TXN_LOCK_2PL DB_TXN_LOG_MASK
+ DB_TXN_LOG_REDO DB_TXN_LOG_UNDO DB_VERIFY_FATAL */
+ /* Offset 10 gives the best switch position. */
+ switch (name[10]) {
+ case 'D':
+ if (memEQ(name, "DB_REP_OUTDATED", 15)) {
+ /* ^ */
+#ifdef DB_REP_OUTDATED
+ *iv_return = DB_REP_OUTDATED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_MULTIPLE_KEY", 15)) {
+ /* ^ */
+#ifdef DB_MULTIPLE_KEY
+ *iv_return = DB_MULTIPLE_KEY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_SURPRISE_KID", 15)) {
+ /* ^ */
+#ifdef DB_SURPRISE_KID
+ *iv_return = DB_SURPRISE_KID;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_PREOPEN", 15)) {
+ /* ^ */
+#ifdef DB_TEST_PREOPEN
+ *iv_return = DB_TEST_PREOPEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'F':
+ if (memEQ(name, "DB_LOCK_DEFAULT", 15)) {
+ /* ^ */
+#ifdef DB_LOCK_DEFAULT
+ *iv_return = DB_LOCK_DEFAULT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERIFY_FATAL", 15)) {
+ /* ^ */
+#ifdef DB_VERIFY_FATAL
+ *iv_return = DB_VERIFY_FATAL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_LOCK_UPGRADE", 15)) {
+ /* ^ */
+#ifdef DB_LOCK_UPGRADE
+ *iv_return = DB_LOCK_UPGRADE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'H':
+ if (memEQ(name, "DB_LOCK_INHERIT", 15)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 7) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 7 && \
+ DB_VERSION_PATCH >= 1)
+ *iv_return = DB_LOCK_INHERIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_ENV_PANIC_OK", 15)) {
+ /* ^ */
+#ifdef DB_ENV_PANIC_OK
+ *iv_return = DB_ENV_PANIC_OK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'K':
+ if (memEQ(name, "DB_ENV_LOCKDOWN", 15)) {
+ /* ^ */
+#ifdef DB_ENV_LOCKDOWN
+ *iv_return = DB_ENV_LOCKDOWN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ORDERCHKONLY", 15)) {
+ /* ^ */
+#ifdef DB_ORDERCHKONLY
+ *iv_return = DB_ORDERCHKONLY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_LOCK_2PL", 15)) {
+ /* ^ */
+#ifdef DB_TXN_LOCK_2PL
+ *iv_return = DB_TXN_LOCK_2PL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_ENV_YIELDCPU", 15)) {
+ /* ^ */
+#ifdef DB_ENV_YIELDCPU
+ *iv_return = DB_ENV_YIELDCPU;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_LOCK_TIMEOUT", 15)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 7)
+ *iv_return = DB_LOCK_TIMEOUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REGION_MAGIC", 15)) {
+ /* ^ */
+#ifdef DB_REGION_MAGIC
+ *iv_return = DB_REGION_MAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_APPLY_LOGREG", 15)) {
+ /* ^ */
+#ifdef DB_APPLY_LOGREG
+ *iv_return = DB_APPLY_LOGREG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_TXN_GETPGNOS", 15)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_TXN_GETPGNOS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_BTREEVERSION", 15)) {
+ /* ^ */
+#ifdef DB_BTREEVERSION
+ *iv_return = DB_BTREEVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MPOOL_CREATE", 15)) {
+ /* ^ */
+#ifdef DB_MPOOL_CREATE
+ *iv_return = DB_MPOOL_CREATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_REP_LOGSONLY", 15)) {
+ /* ^ */
+#ifdef DB_REP_LOGSONLY
+ *iv_return = DB_REP_LOGSONLY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_POSTLOG", 15)) {
+ /* ^ */
+#ifdef DB_TEST_POSTLOG
+ *iv_return = DB_TEST_POSTLOG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_LOCK_NOTHELD", 15)) {
+ /* ^ */
+#ifdef DB_LOCK_NOTHELD
+ *iv_return = DB_LOCK_NOTHELD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_PUT_ALL", 15)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_LOCK_PUT_ALL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_PUT_OBJ", 15)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 2) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 0)
+ *iv_return = DB_LOCK_PUT_OBJ;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'X':
+ if (memEQ(name, "DB_MPOOL_EXTENT", 15)) {
+ /* ^ */
+#ifdef DB_MPOOL_EXTENT
+ *iv_return = DB_MPOOL_EXTENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'Y':
+ if (memEQ(name, "DB_PRIORITY_LOW", 15)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_PRIORITY_LOW;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_CONSUME_WAIT", 15)) {
+ /* ^ */
+#ifdef DB_CONSUME_WAIT
+ *iv_return = DB_CONSUME_WAIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_OPFLAGS_MASK", 15)) {
+ /* ^ */
+#ifdef DB_OPFLAGS_MASK
+ *iv_return = DB_OPFLAGS_MASK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_LOG_MASK", 15)) {
+ /* ^ */
+#ifdef DB_TXN_LOG_MASK
+ *iv_return = DB_TXN_LOG_MASK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_LOG_REDO", 15)) {
+ /* ^ */
+#ifdef DB_TXN_LOG_REDO
+ *iv_return = DB_TXN_LOG_REDO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_LOG_UNDO", 15)) {
+ /* ^ */
+#ifdef DB_TXN_LOG_UNDO
+ *iv_return = DB_TXN_LOG_UNDO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_16 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_BROADCAST_EID DB_CACHED_COUNTS DB_EID_BROADCAST DB_ENV_CDB_ALLDB
+ DB_ENV_DIRECT_DB DB_ENV_NOLOCKING DB_ENV_OVERWRITE DB_ENV_RPCCLIENT
+ DB_FCNTL_LOCKING DB_JAVA_CALLBACK DB_LOCK_CONFLICT DB_LOCK_DEADLOCK
+ DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS DB_LOCK_MINWRITE DB_LOCK_NOTEXIST
+ DB_LOCK_PUT_READ DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE DB_MPOOL_DISCARD
+ DB_MPOOL_PRIVATE DB_NOSERVER_HOME DB_PAGE_NOTFOUND DB_PRIORITY_HIGH
+ DB_RECOVER_FATAL DB_REP_DUPMASTER DB_REP_NEWMASTER DB_REP_PERMANENT
+ DB_SECONDARY_BAD DB_TEST_POSTOPEN DB_TEST_POSTSYNC DB_TXN_LOCK_MASK
+ DB_TXN_OPENFILES DB_VERB_CHKPOINT DB_VERB_DEADLOCK DB_VERB_RECOVERY
+ DB_VERB_WAITSFOR DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH
+ DB_VRFY_FLAGMASK */
+ /* Offset 12 gives the best switch position. */
+ switch (name[12]) {
+ case 'A':
+ if (memEQ(name, "DB_RECOVER_FATAL", 16)) {
+ /* ^ */
+#ifdef DB_RECOVER_FATAL
+ *iv_return = DB_RECOVER_FATAL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERSION_MAJOR", 16)) {
+ /* ^ */
+#ifdef DB_VERSION_MAJOR
+ *iv_return = DB_VERSION_MAJOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERSION_PATCH", 16)) {
+ /* ^ */
+#ifdef DB_VERSION_PATCH
+ *iv_return = DB_VERSION_PATCH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'B':
+ if (memEQ(name, "DB_JAVA_CALLBACK", 16)) {
+ /* ^ */
+#ifdef DB_JAVA_CALLBACK
+ *iv_return = DB_JAVA_CALLBACK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'C':
+ if (memEQ(name, "DB_EID_BROADCAST", 16)) {
+ /* ^ */
+#ifdef DB_EID_BROADCAST
+ *iv_return = DB_EID_BROADCAST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_MPOOL_DISCARD", 16)) {
+ /* ^ */
+#ifdef DB_MPOOL_DISCARD
+ *iv_return = DB_MPOOL_DISCARD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_LOCK_YOUNGEST", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_YOUNGEST
+ *iv_return = DB_LOCK_YOUNGEST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'H':
+ if (memEQ(name, "DB_NOSERVER_HOME", 16)) {
+ /* ^ */
+#ifdef DB_NOSERVER_HOME
+ *iv_return = DB_NOSERVER_HOME;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_PRIORITY_HIGH", 16)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_PRIORITY_HIGH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_ENV_RPCCLIENT", 16)) {
+ /* ^ */
+#ifdef DB_ENV_RPCCLIENT
+ *iv_return = DB_ENV_RPCCLIENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_OPENFILES", 16)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 12)
+ *iv_return = DB_TXN_OPENFILES;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERSION_MINOR", 16)) {
+ /* ^ */
+#ifdef DB_VERSION_MINOR
+ *iv_return = DB_VERSION_MINOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'K':
+ if (memEQ(name, "DB_ENV_NOLOCKING", 16)) {
+ /* ^ */
+#ifdef DB_ENV_NOLOCKING
+ *iv_return = DB_ENV_NOLOCKING;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_FCNTL_LOCKING", 16)) {
+ /* ^ */
+#ifdef DB_FCNTL_LOCKING
+ *iv_return = DB_FCNTL_LOCKING;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_ENV_CDB_ALLDB", 16)) {
+ /* ^ */
+#ifdef DB_ENV_CDB_ALLDB
+ *iv_return = DB_ENV_CDB_ALLDB;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_CONFLICT", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_CONFLICT
+ *iv_return = DB_LOCK_CONFLICT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_DEADLOCK", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_DEADLOCK
+ *iv_return = DB_LOCK_DEADLOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERB_DEADLOCK", 16)) {
+ /* ^ */
+#ifdef DB_VERB_DEADLOCK
+ *iv_return = DB_VERB_DEADLOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_TXN_LOCK_MASK", 16)) {
+ /* ^ */
+#ifdef DB_TXN_LOCK_MASK
+ *iv_return = DB_TXN_LOCK_MASK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VRFY_FLAGMASK", 16)) {
+ /* ^ */
+#ifdef DB_VRFY_FLAGMASK
+ *iv_return = DB_VRFY_FLAGMASK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_REP_PERMANENT", 16)) {
+ /* ^ */
+#ifdef DB_REP_PERMANENT
+ *iv_return = DB_REP_PERMANENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_LOCK_MAXLOCKS", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_MAXLOCKS
+ *iv_return = DB_LOCK_MAXLOCKS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_MINLOCKS", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_MINLOCKS
+ *iv_return = DB_LOCK_MINLOCKS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_PAGE_NOTFOUND", 16)) {
+ /* ^ */
+#ifdef DB_PAGE_NOTFOUND
+ *iv_return = DB_PAGE_NOTFOUND;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_POSTOPEN", 16)) {
+ /* ^ */
+#ifdef DB_TEST_POSTOPEN
+ *iv_return = DB_TEST_POSTOPEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERB_CHKPOINT", 16)) {
+ /* ^ */
+#ifdef DB_VERB_CHKPOINT
+ *iv_return = DB_VERB_CHKPOINT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_ENV_OVERWRITE", 16)) {
+ /* ^ */
+#ifdef DB_ENV_OVERWRITE
+ *iv_return = DB_ENV_OVERWRITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_MINWRITE", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_MINWRITE
+ *iv_return = DB_LOCK_MINWRITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_PUT_READ", 16)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 7)
+ *iv_return = DB_LOCK_PUT_READ;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_LOGC_BUF_SIZE", 16)) {
+ /* ^ */
+#ifdef DB_LOGC_BUF_SIZE
+ *iv_return = DB_LOGC_BUF_SIZE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REP_DUPMASTER", 16)) {
+ /* ^ */
+#ifdef DB_REP_DUPMASTER
+ *iv_return = DB_REP_DUPMASTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_REP_NEWMASTER", 16)) {
+ /* ^ */
+#ifdef DB_REP_NEWMASTER
+ *iv_return = DB_REP_NEWMASTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_POSTSYNC", 16)) {
+ /* ^ */
+#ifdef DB_TEST_POSTSYNC
+ *iv_return = DB_TEST_POSTSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERB_WAITSFOR", 16)) {
+ /* ^ */
+#ifdef DB_VERB_WAITSFOR
+ *iv_return = DB_VERB_WAITSFOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_ENV_DIRECT_DB", 16)) {
+ /* ^ */
+#ifdef DB_ENV_DIRECT_DB
+ *iv_return = DB_ENV_DIRECT_DB;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_CACHED_COUNTS", 16)) {
+ /* ^ */
+#ifdef DB_CACHED_COUNTS
+ *iv_return = DB_CACHED_COUNTS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'V':
+ if (memEQ(name, "DB_MPOOL_PRIVATE", 16)) {
+ /* ^ */
+#ifdef DB_MPOOL_PRIVATE
+ *iv_return = DB_MPOOL_PRIVATE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERB_RECOVERY", 16)) {
+ /* ^ */
+#ifdef DB_VERB_RECOVERY
+ *iv_return = DB_VERB_RECOVERY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'X':
+ if (memEQ(name, "DB_LOCK_NOTEXIST", 16)) {
+ /* ^ */
+#ifdef DB_LOCK_NOTEXIST
+ *iv_return = DB_LOCK_NOTEXIST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_BROADCAST_EID", 16)) {
+ /* ^ */
+#ifdef DB_BROADCAST_EID
+ *iv_return = DB_BROADCAST_EID;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_SECONDARY_BAD", 16)) {
+ /* ^ */
+#ifdef DB_SECONDARY_BAD
+ *iv_return = DB_SECONDARY_BAD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_17 (pTHX_ const char *name, IV *iv_return, const char **pv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_ENV_DIRECT_LOG DB_ENV_REP_CLIENT DB_ENV_REP_MASTER DB_ENV_STANDALONE
+ DB_ENV_SYSTEM_MEM DB_ENV_TXN_NOSYNC DB_ENV_USER_ALLOC DB_GET_BOTH_RANGE
+ DB_LOG_SILENT_ERR DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_TEST_ELECTINIT
+ DB_TEST_ELECTSEND DB_TEST_PRERENAME DB_TXN_POPENFILES DB_VERSION_STRING */
+ /* Offset 14 gives the best switch position. */
+ switch (name[14]) {
+ case 'A':
+ if (memEQ(name, "DB_TEST_PRERENAME", 17)) {
+ /* ^ */
+#ifdef DB_TEST_PRERENAME
+ *iv_return = DB_TEST_PRERENAME;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_ENV_REP_CLIENT", 17)) {
+ /* ^ */
+#ifdef DB_ENV_REP_CLIENT
+ *iv_return = DB_ENV_REP_CLIENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOG_SILENT_ERR", 17)) {
+ /* ^ */
+#ifdef DB_LOG_SILENT_ERR
+ *iv_return = DB_LOG_SILENT_ERR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_RPC_SERVERVERS", 17)) {
+ /* ^ */
+#ifdef DB_RPC_SERVERVERS
+ *iv_return = DB_RPC_SERVERVERS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_ELECTSEND", 17)) {
+ /* ^ */
+#ifdef DB_TEST_ELECTSEND
+ *iv_return = DB_TEST_ELECTSEND;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_VERSION_STRING", 17)) {
+ /* ^ */
+#ifdef DB_VERSION_STRING
+ *pv_return = DB_VERSION_STRING;
+ return PERL_constant_ISPV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_ENV_DIRECT_LOG", 17)) {
+ /* ^ */
+#ifdef DB_ENV_DIRECT_LOG
+ *iv_return = DB_ENV_DIRECT_LOG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ENV_USER_ALLOC", 17)) {
+ /* ^ */
+#ifdef DB_ENV_USER_ALLOC
+ *iv_return = DB_ENV_USER_ALLOC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_POPENFILES", 17)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \
+ DB_VERSION_PATCH >= 4)
+ *iv_return = DB_TXN_POPENFILES;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_ENV_SYSTEM_MEM", 17)) {
+ /* ^ */
+#ifdef DB_ENV_SYSTEM_MEM
+ *iv_return = DB_ENV_SYSTEM_MEM;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_GET_BOTH_RANGE", 17)) {
+ /* ^ */
+#ifdef DB_GET_BOTH_RANGE
+ *iv_return = DB_GET_BOTH_RANGE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_ELECTINIT", 17)) {
+ /* ^ */
+#ifdef DB_TEST_ELECTINIT
+ *iv_return = DB_TEST_ELECTINIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_ENV_STANDALONE", 17)) {
+ /* ^ */
+#ifdef DB_ENV_STANDALONE
+ *iv_return = DB_ENV_STANDALONE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_RPC_SERVERPROG", 17)) {
+ /* ^ */
+#ifdef DB_RPC_SERVERPROG
+ *iv_return = DB_RPC_SERVERPROG;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_ENV_REP_MASTER", 17)) {
+ /* ^ */
+#ifdef DB_ENV_REP_MASTER
+ *iv_return = DB_ENV_REP_MASTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'Y':
+ if (memEQ(name, "DB_ENV_TXN_NOSYNC", 17)) {
+ /* ^ */
+#ifdef DB_ENV_TXN_NOSYNC
+ *iv_return = DB_ENV_TXN_NOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_18 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_ALREADY_ABORTED DB_ENV_AUTO_COMMIT DB_ENV_OPEN_CALLED
+ DB_ENV_REGION_INIT DB_LOCK_NOTGRANTED DB_MPOOL_NEW_GROUP
+ DB_PR_RECOVERYTEST DB_SET_TXN_TIMEOUT DB_TEST_ELECTVOTE1
+ DB_TEST_ELECTVOTE2 DB_TEST_ELECTWAIT1 DB_TEST_ELECTWAIT2
+ DB_TEST_POSTRENAME DB_TEST_PREDESTROY DB_TEST_PREEXTOPEN */
+ /* Offset 13 gives the best switch position. */
+ switch (name[13]) {
+ case 'A':
+ if (memEQ(name, "DB_ENV_OPEN_CALLED", 18)) {
+ /* ^ */
+#ifdef DB_ENV_OPEN_CALLED
+ *iv_return = DB_ENV_OPEN_CALLED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_NOTGRANTED", 18)) {
+ /* ^ */
+#ifdef DB_LOCK_NOTGRANTED
+ *iv_return = DB_LOCK_NOTGRANTED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_TEST_POSTRENAME", 18)) {
+ /* ^ */
+#ifdef DB_TEST_POSTRENAME
+ *iv_return = DB_TEST_POSTRENAME;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_MPOOL_NEW_GROUP", 18)) {
+ /* ^ */
+#ifdef DB_MPOOL_NEW_GROUP
+ *iv_return = DB_MPOOL_NEW_GROUP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "DB_SET_TXN_TIMEOUT", 18)) {
+ /* ^ */
+#ifdef DB_SET_TXN_TIMEOUT
+ *iv_return = DB_SET_TXN_TIMEOUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_ALREADY_ABORTED", 18)) {
+ /* ^ */
+#ifdef DB_ALREADY_ABORTED
+ *iv_return = DB_ALREADY_ABORTED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_ENV_AUTO_COMMIT", 18)) {
+ /* ^ */
+#ifdef DB_ENV_AUTO_COMMIT
+ *iv_return = DB_ENV_AUTO_COMMIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "DB_TEST_PREDESTROY", 18)) {
+ /* ^ */
+#ifdef DB_TEST_PREDESTROY
+ *iv_return = DB_TEST_PREDESTROY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_TEST_PREEXTOPEN", 18)) {
+ /* ^ */
+#ifdef DB_TEST_PREEXTOPEN
+ *iv_return = DB_TEST_PREEXTOPEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'V':
+ if (memEQ(name, "DB_TEST_ELECTVOTE1", 18)) {
+ /* ^ */
+#ifdef DB_TEST_ELECTVOTE1
+ *iv_return = DB_TEST_ELECTVOTE1;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_ELECTVOTE2", 18)) {
+ /* ^ */
+#ifdef DB_TEST_ELECTVOTE2
+ *iv_return = DB_TEST_ELECTVOTE2;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'W':
+ if (memEQ(name, "DB_TEST_ELECTWAIT1", 18)) {
+ /* ^ */
+#ifdef DB_TEST_ELECTWAIT1
+ *iv_return = DB_TEST_ELECTWAIT1;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_ELECTWAIT2", 18)) {
+ /* ^ */
+#ifdef DB_TEST_ELECTWAIT2
+ *iv_return = DB_TEST_ELECTWAIT2;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'Y':
+ if (memEQ(name, "DB_PR_RECOVERYTEST", 18)) {
+ /* ^ */
+#ifdef DB_PR_RECOVERYTEST
+ *iv_return = DB_PR_RECOVERYTEST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_ENV_REGION_INIT", 18)) {
+ /* ^ */
+#ifdef DB_ENV_REGION_INIT
+ *iv_return = DB_ENV_REGION_INIT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_19 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_ENV_REP_LOGSONLY DB_LOCK_FREE_LOCKER DB_LOCK_GET_TIMEOUT
+ DB_LOCK_SET_TIMEOUT DB_PRIORITY_DEFAULT DB_REP_HOLDELECTION
+ DB_SET_LOCK_TIMEOUT DB_TEST_POSTDESTROY DB_TEST_POSTEXTOPEN
+ DB_TEST_POSTLOGMETA DB_TEST_SUBDB_LOCKS DB_TXN_FORWARD_ROLL
+ DB_TXN_LOG_UNDOREDO DB_TXN_WRITE_NOSYNC DB_UNRESOLVED_CHILD
+ DB_UPDATE_SECONDARY DB_USE_ENVIRON_ROOT DB_VERB_REPLICATION */
+ /* Offset 9 gives the best switch position. */
+ switch (name[9]) {
+ case 'C':
+ if (memEQ(name, "DB_SET_LOCK_TIMEOUT", 19)) {
+ /* ^ */
+#ifdef DB_SET_LOCK_TIMEOUT
+ *iv_return = DB_SET_LOCK_TIMEOUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_LOCK_GET_TIMEOUT", 19)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
+ DB_VERSION_PATCH >= 7)
+ *iv_return = DB_LOCK_GET_TIMEOUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_LOCK_SET_TIMEOUT", 19)) {
+ /* ^ */
+#ifdef DB_LOCK_SET_TIMEOUT
+ *iv_return = DB_LOCK_SET_TIMEOUT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_VERB_REPLICATION", 19)) {
+ /* ^ */
+#ifdef DB_VERB_REPLICATION
+ *iv_return = DB_VERB_REPLICATION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'G':
+ if (memEQ(name, "DB_TXN_LOG_UNDOREDO", 19)) {
+ /* ^ */
+#ifdef DB_TXN_LOG_UNDOREDO
+ *iv_return = DB_TXN_LOG_UNDOREDO;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'I':
+ if (memEQ(name, "DB_TXN_WRITE_NOSYNC", 19)) {
+ /* ^ */
+#ifdef DB_TXN_WRITE_NOSYNC
+ *iv_return = DB_TXN_WRITE_NOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_REP_HOLDELECTION", 19)) {
+ /* ^ */
+#ifdef DB_REP_HOLDELECTION
+ *iv_return = DB_REP_HOLDELECTION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_UNRESOLVED_CHILD", 19)) {
+ /* ^ */
+#ifdef DB_UNRESOLVED_CHILD
+ *iv_return = DB_UNRESOLVED_CHILD;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_TEST_POSTDESTROY", 19)) {
+ /* ^ */
+#ifdef DB_TEST_POSTDESTROY
+ *iv_return = DB_TEST_POSTDESTROY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_POSTEXTOPEN", 19)) {
+ /* ^ */
+#ifdef DB_TEST_POSTEXTOPEN
+ *iv_return = DB_TEST_POSTEXTOPEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TEST_POSTLOGMETA", 19)) {
+ /* ^ */
+#ifdef DB_TEST_POSTLOGMETA
+ *iv_return = DB_TEST_POSTLOGMETA;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_ENV_REP_LOGSONLY", 19)) {
+ /* ^ */
+#ifdef DB_ENV_REP_LOGSONLY
+ *iv_return = DB_ENV_REP_LOGSONLY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_LOCK_FREE_LOCKER", 19)) {
+ /* ^ */
+#ifdef DB_LOCK_FREE_LOCKER
+ *iv_return = DB_LOCK_FREE_LOCKER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_FORWARD_ROLL", 19)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 12)
+ *iv_return = DB_TXN_FORWARD_ROLL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_PRIORITY_DEFAULT", 19)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_PRIORITY_DEFAULT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_TEST_SUBDB_LOCKS", 19)) {
+ /* ^ */
+#ifdef DB_TEST_SUBDB_LOCKS
+ *iv_return = DB_TEST_SUBDB_LOCKS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'V':
+ if (memEQ(name, "DB_USE_ENVIRON_ROOT", 19)) {
+ /* ^ */
+#ifdef DB_USE_ENVIRON_ROOT
+ *iv_return = DB_USE_ENVIRON_ROOT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_UPDATE_SECONDARY", 19)) {
+ /* ^ */
+#ifdef DB_UPDATE_SECONDARY
+ *iv_return = DB_UPDATE_SECONDARY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_20 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_CXX_NO_EXCEPTIONS DB_LOGFILEID_INVALID DB_PANIC_ENVIRONMENT
+ DB_PRIORITY_VERY_LOW DB_TEST_PREEXTDELETE DB_TEST_PREEXTUNLINK
+ DB_TXN_BACKWARD_ROLL DB_TXN_LOCK_OPTIMIST */
+ /* Offset 14 gives the best switch position. */
+ switch (name[14]) {
+ case 'D':
+ if (memEQ(name, "DB_TEST_PREEXTDELETE", 20)) {
+ /* ^ */
+#ifdef DB_TEST_PREEXTDELETE
+ *iv_return = DB_TEST_PREEXTDELETE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ if (memEQ(name, "DB_TXN_BACKWARD_ROLL", 20)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 12)
+ *iv_return = DB_TXN_BACKWARD_ROLL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_LOGFILEID_INVALID", 20)) {
+ /* ^ */
+#ifdef DB_LOGFILEID_INVALID
+ *iv_return = DB_LOGFILEID_INVALID;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "DB_PANIC_ENVIRONMENT", 20)) {
+ /* ^ */
+#ifdef DB_PANIC_ENVIRONMENT
+ *iv_return = DB_PANIC_ENVIRONMENT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_CXX_NO_EXCEPTIONS", 20)) {
+ /* ^ */
+#ifdef DB_CXX_NO_EXCEPTIONS
+ *iv_return = DB_CXX_NO_EXCEPTIONS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "DB_PRIORITY_VERY_LOW", 20)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_PRIORITY_VERY_LOW;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "DB_TXN_LOCK_OPTIMIST", 20)) {
+ /* ^ */
+#ifdef DB_TXN_LOCK_OPTIMIST
+ *iv_return = DB_TXN_LOCK_OPTIMIST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'U':
+ if (memEQ(name, "DB_TEST_PREEXTUNLINK", 20)) {
+ /* ^ */
+#ifdef DB_TEST_PREEXTUNLINK
+ *iv_return = DB_TEST_PREEXTUNLINK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_21 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_LOCK_UPGRADE_WRITE DB_PRIORITY_VERY_HIGH DB_TEST_POSTEXTDELETE
+ DB_TEST_POSTEXTUNLINK DB_TXN_BACKWARD_ALLOC */
+ /* Offset 16 gives the best switch position. */
+ switch (name[16]) {
+ case 'A':
+ if (memEQ(name, "DB_TXN_BACKWARD_ALLOC", 21)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_TXN_BACKWARD_ALLOC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'E':
+ if (memEQ(name, "DB_TEST_POSTEXTDELETE", 21)) {
+ /* ^ */
+#ifdef DB_TEST_POSTEXTDELETE
+ *iv_return = DB_TEST_POSTEXTDELETE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "DB_TEST_POSTEXTUNLINK", 21)) {
+ /* ^ */
+#ifdef DB_TEST_POSTEXTUNLINK
+ *iv_return = DB_TEST_POSTEXTUNLINK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'W':
+ if (memEQ(name, "DB_LOCK_UPGRADE_WRITE", 21)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \
+ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \
+ DB_VERSION_PATCH >= 4)
+ *iv_return = DB_LOCK_UPGRADE_WRITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_PRIORITY_VERY_HIGH", 21)) {
+ /* ^ */
+#if (DB_VERSION_MAJOR > 4) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+ DB_VERSION_PATCH >= 17)
+ *iv_return = DB_PRIORITY_VERY_HIGH;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant (pTHX_ const char *name, STRLEN len, IV *iv_return, const char **pv_return) {
+ /* Initially switch on the length of the name. */
+ /* When generated this function returned values for the list of names given
+ in this section of perl code. Rather than manually editing these functions
+ to add or remove constants, which would result in this comment and section
+ of code becoming inaccurate, we recommend that you edit this section of
+ code, and use it to regenerate a new set of constant functions which you
+ then use to replace the originals.
+
+ Regenerate these constant functions by feeding this entire source file to
+ perl -x
+
+#!/home/paul/perl/install/redhat6.1/5.8.0/bin/perl5.8.0 -w
+use ExtUtils::Constant qw (constant_types C_constant XS_constant);
+
+my $types = {map {($_, 1)} qw(IV PV)};
+my @names = (qw(DB_AFTER DB_AGGRESSIVE DB_ALREADY_ABORTED DB_APPEND
+ DB_APPLY_LOGREG DB_APP_INIT DB_ARCH_ABS DB_ARCH_DATA DB_ARCH_LOG
+ DB_AUTO_COMMIT DB_BEFORE DB_BROADCAST_EID DB_BTREEMAGIC
+ DB_BTREEOLDVER DB_BTREEVERSION DB_CACHED_COUNTS DB_CDB_ALLDB
+ DB_CHECKPOINT DB_CHKSUM_SHA1 DB_CLIENT DB_CL_WRITER DB_COMMIT
+ DB_CONSUME DB_CONSUME_WAIT DB_CREATE DB_CURLSN DB_CURRENT
+ DB_CXX_NO_EXCEPTIONS DB_DELETED DB_DELIMITER DB_DIRECT
+ DB_DIRECT_DB DB_DIRECT_LOG DB_DIRTY_READ DB_DONOTINDEX DB_DUP
+ DB_DUPCURSOR DB_DUPSORT DB_EID_BROADCAST DB_EID_INVALID
+ DB_ENCRYPT DB_ENCRYPT_AES DB_ENV_APPINIT DB_ENV_AUTO_COMMIT
+ DB_ENV_CDB DB_ENV_CDB_ALLDB DB_ENV_CREATE DB_ENV_DBLOCAL
+ DB_ENV_DIRECT_DB DB_ENV_DIRECT_LOG DB_ENV_FATAL DB_ENV_LOCKDOWN
+ DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_NOLOCKING DB_ENV_NOMMAP
+ DB_ENV_NOPANIC DB_ENV_OPEN_CALLED DB_ENV_OVERWRITE
+ DB_ENV_PANIC_OK DB_ENV_PRIVATE DB_ENV_REGION_INIT
+ DB_ENV_REP_CLIENT DB_ENV_REP_LOGSONLY DB_ENV_REP_MASTER
+ DB_ENV_RPCCLIENT DB_ENV_RPCCLIENT_GIVEN DB_ENV_STANDALONE
+ DB_ENV_SYSTEM_MEM DB_ENV_THREAD DB_ENV_TXN DB_ENV_TXN_NOSYNC
+ DB_ENV_TXN_WRITE_NOSYNC DB_ENV_USER_ALLOC DB_ENV_YIELDCPU
+ DB_EXCL DB_EXTENT DB_FAST_STAT DB_FCNTL_LOCKING DB_FILE_ID_LEN
+ DB_FIRST DB_FIXEDLEN DB_FLUSH DB_FORCE DB_GETREC DB_GET_BOTH
+ DB_GET_BOTHC DB_GET_BOTH_RANGE DB_GET_RECNO DB_HANDLE_LOCK
+ DB_HASHMAGIC DB_HASHOLDVER DB_HASHVERSION DB_INCOMPLETE
+ DB_INIT_CDB DB_INIT_LOCK DB_INIT_LOG DB_INIT_MPOOL DB_INIT_TXN
+ DB_INVALID_EID DB_JAVA_CALLBACK DB_JOINENV DB_JOIN_ITEM
+ DB_JOIN_NOSORT DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_KEYLAST
+ DB_LAST DB_LOCKDOWN DB_LOCKMAGIC DB_LOCKVERSION DB_LOCK_CONFLICT
+ DB_LOCK_DEADLOCK DB_LOCK_DEFAULT DB_LOCK_EXPIRE
+ DB_LOCK_FREE_LOCKER DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS
+ DB_LOCK_MINWRITE DB_LOCK_NORUN DB_LOCK_NOTEXIST
+ DB_LOCK_NOTGRANTED DB_LOCK_NOTHELD DB_LOCK_NOWAIT DB_LOCK_OLDEST
+ DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_REMOVE DB_LOCK_RIW_N
+ DB_LOCK_RW_N DB_LOCK_SET_TIMEOUT DB_LOCK_SWITCH DB_LOCK_UPGRADE
+ DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE DB_LOGFILEID_INVALID
+ DB_LOGMAGIC DB_LOGOLDVER DB_LOGVERSION DB_LOG_DISK DB_LOG_LOCKED
+ DB_LOG_SILENT_ERR DB_MAX_PAGES DB_MAX_RECORDS DB_MPOOL_CLEAN
+ DB_MPOOL_CREATE DB_MPOOL_DIRTY DB_MPOOL_DISCARD DB_MPOOL_EXTENT
+ DB_MPOOL_LAST DB_MPOOL_NEW DB_MPOOL_NEW_GROUP DB_MPOOL_PRIVATE
+ DB_MULTIPLE DB_MULTIPLE_KEY DB_MUTEXDEBUG DB_MUTEXLOCKS
+ DB_NEEDSPLIT DB_NEXT DB_NEXT_DUP DB_NEXT_NODUP DB_NOCOPY
+ DB_NODUPDATA DB_NOLOCKING DB_NOMMAP DB_NOORDERCHK DB_NOOVERWRITE
+ DB_NOPANIC DB_NORECURSE DB_NOSERVER DB_NOSERVER_HOME
+ DB_NOSERVER_ID DB_NOSYNC DB_NOTFOUND DB_ODDFILESIZE DB_OK_BTREE
+ DB_OK_HASH DB_OK_QUEUE DB_OK_RECNO DB_OLD_VERSION DB_OPEN_CALLED
+ DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_OVERWRITE DB_PAD DB_PAGEYIELD
+ DB_PAGE_LOCK DB_PAGE_NOTFOUND DB_PANIC_ENVIRONMENT DB_PERMANENT
+ DB_POSITION DB_POSITIONI DB_PREV DB_PREV_NODUP DB_PRINTABLE
+ DB_PRIVATE DB_PR_HEADERS DB_PR_PAGE DB_PR_RECOVERYTEST
+ DB_QAMMAGIC DB_QAMOLDVER DB_QAMVERSION DB_RDONLY DB_RDWRMASTER
+ DB_RECNUM DB_RECORDCOUNT DB_RECORD_LOCK DB_RECOVER
+ DB_RECOVER_FATAL DB_REGION_ANON DB_REGION_INIT DB_REGION_MAGIC
+ DB_REGION_NAME DB_REGISTERED DB_RENAMEMAGIC DB_RENUMBER
+ DB_REP_CLIENT DB_REP_DUPMASTER DB_REP_HOLDELECTION
+ DB_REP_LOGSONLY DB_REP_MASTER DB_REP_NEWMASTER DB_REP_NEWSITE
+ DB_REP_OUTDATED DB_REP_PERMANENT DB_REP_UNAVAIL DB_REVSPLITOFF
+ DB_RMW DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_RUNRECOVERY
+ DB_SALVAGE DB_SECONDARY_BAD DB_SEQUENTIAL DB_SET
+ DB_SET_LOCK_TIMEOUT DB_SET_RANGE DB_SET_RECNO DB_SET_TXN_NOW
+ DB_SET_TXN_TIMEOUT DB_SNAPSHOT DB_STAT_CLEAR DB_SURPRISE_KID
+ DB_SWAPBYTES DB_SYSTEM_MEM DB_TEMPORARY DB_TEST_ELECTINIT
+ DB_TEST_ELECTSEND DB_TEST_ELECTVOTE1 DB_TEST_ELECTVOTE2
+ DB_TEST_ELECTWAIT1 DB_TEST_ELECTWAIT2 DB_TEST_POSTDESTROY
+ DB_TEST_POSTEXTDELETE DB_TEST_POSTEXTOPEN DB_TEST_POSTEXTUNLINK
+ DB_TEST_POSTLOG DB_TEST_POSTLOGMETA DB_TEST_POSTOPEN
+ DB_TEST_POSTRENAME DB_TEST_POSTSYNC DB_TEST_PREDESTROY
+ DB_TEST_PREEXTDELETE DB_TEST_PREEXTOPEN DB_TEST_PREEXTUNLINK
+ DB_TEST_PREOPEN DB_TEST_PRERENAME DB_TEST_SUBDB_LOCKS DB_THREAD
+ DB_TIMEOUT DB_TRUNCATE DB_TXNMAGIC DB_TXNVERSION DB_TXN_CKP
+ DB_TXN_LOCK DB_TXN_LOCK_2PL DB_TXN_LOCK_MASK
+ DB_TXN_LOCK_OPTIMIST DB_TXN_LOCK_OPTIMISTIC DB_TXN_LOG_MASK
+ DB_TXN_LOG_REDO DB_TXN_LOG_UNDO DB_TXN_LOG_UNDOREDO
+ DB_TXN_NOSYNC DB_TXN_NOWAIT DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO
+ DB_TXN_WRITE_NOSYNC DB_UNRESOLVED_CHILD DB_UPDATE_SECONDARY
+ DB_UPGRADE DB_USE_ENVIRON DB_USE_ENVIRON_ROOT DB_VERB_CHKPOINT
+ DB_VERB_DEADLOCK DB_VERB_RECOVERY DB_VERB_REPLICATION
+ DB_VERB_WAITSFOR DB_VERIFY DB_VERIFY_BAD DB_VERIFY_FATAL
+ DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH
+ DB_VRFY_FLAGMASK DB_WRITECURSOR DB_WRITELOCK DB_WRITEOPEN
+ DB_WRNOSYNC DB_XA_CREATE DB_XIDDATASIZE DB_YIELDCPU),
+ {name=>"DB_BTREE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_HASH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_LOCK_DUMP", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_LOCK_GET", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_LOCK_GET_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
+ {name=>"DB_LOCK_INHERIT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 7) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 7 && \\\n DB_VERSION_PATCH >= 1)\n", "#endif\n"]},
+ {name=>"DB_LOCK_PUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_LOCK_PUT_ALL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_LOCK_PUT_OBJ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_LOCK_PUT_READ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
+ {name=>"DB_LOCK_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
+ {name=>"DB_LOCK_TRADE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_LOCK_UPGRADE_WRITE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n DB_VERSION_PATCH >= 4)\n", "#endif\n"]},
+ {name=>"DB_PRIORITY_DEFAULT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_PRIORITY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_PRIORITY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_PRIORITY_VERY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_PRIORITY_VERY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_QUEUE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 55)\n", "#endif\n"]},
+ {name=>"DB_RECNO", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_TXN_ABORT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
+ {name=>"DB_TXN_APPLY", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
+ {name=>"DB_TXN_BACKWARD_ALLOC", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_TXN_BACKWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
+ {name=>"DB_TXN_FORWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
+ {name=>"DB_TXN_GETPGNOS", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_TXN_OPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
+ {name=>"DB_TXN_POPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n DB_VERSION_PATCH >= 4)\n", "#endif\n"]},
+ {name=>"DB_TXN_PRINT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+ {name=>"DB_UNKNOWN", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+ {name=>"DB_VERSION_STRING", type=>"PV"});
+
+print constant_types(); # macro defs
+foreach (C_constant ("BerkeleyDB", 'constant', 'IV', $types, undef, 3, @names) ) {
+ print $_, "\n"; # C constant subs
+}
+print "#### XS Section:\n";
+print XS_constant ("BerkeleyDB", $types);
+__END__
+ */
+
+ switch (len) {
+ case 6:
+ return constant_6 (aTHX_ name, iv_return);
+ break;
+ case 7:
+ return constant_7 (aTHX_ name, iv_return);
+ break;
+ case 8:
+ return constant_8 (aTHX_ name, iv_return);
+ break;
+ case 9:
+ return constant_9 (aTHX_ name, iv_return);
+ break;
+ case 10:
+ return constant_10 (aTHX_ name, iv_return);
+ break;
+ case 11:
+ return constant_11 (aTHX_ name, iv_return);
+ break;
+ case 12:
+ return constant_12 (aTHX_ name, iv_return);
+ break;
+ case 13:
+ return constant_13 (aTHX_ name, iv_return);
+ break;
+ case 14:
+ return constant_14 (aTHX_ name, iv_return);
+ break;
+ case 15:
+ return constant_15 (aTHX_ name, iv_return);
+ break;
+ case 16:
+ return constant_16 (aTHX_ name, iv_return);
+ break;
+ case 17:
+ return constant_17 (aTHX_ name, iv_return, pv_return);
+ break;
+ case 18:
+ return constant_18 (aTHX_ name, iv_return);
+ break;
+ case 19:
+ return constant_19 (aTHX_ name, iv_return);
+ break;
+ case 20:
+ return constant_20 (aTHX_ name, iv_return);
+ break;
+ case 21:
+ return constant_21 (aTHX_ name, iv_return);
+ break;
+ case 22:
+ /* Names all of length 22. */
+ /* DB_ENV_RPCCLIENT_GIVEN DB_TXN_LOCK_OPTIMISTIC */
+ /* Offset 8 gives the best switch position. */
+ switch (name[8]) {
+ case 'O':
+ if (memEQ(name, "DB_TXN_LOCK_OPTIMISTIC", 22)) {
+ /* ^ */
+#ifdef DB_TXN_LOCK_OPTIMISTIC
+ *iv_return = DB_TXN_LOCK_OPTIMISTIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "DB_ENV_RPCCLIENT_GIVEN", 22)) {
+ /* ^ */
+#ifdef DB_ENV_RPCCLIENT_GIVEN
+ *iv_return = DB_ENV_RPCCLIENT_GIVEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ break;
+ case 23:
+ if (memEQ(name, "DB_ENV_TXN_WRITE_NOSYNC", 23)) {
+#ifdef DB_ENV_TXN_WRITE_NOSYNC
+ *iv_return = DB_ENV_TXN_WRITE_NOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
diff --git a/bdb/perl/BerkeleyDB/constants.xs b/bdb/perl/BerkeleyDB/constants.xs
new file mode 100644
index 00000000000..1b2c8b2c3c8
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/constants.xs
@@ -0,0 +1,87 @@
+void
+constant(sv)
+ PREINIT:
+#ifdef dXSTARG
+ dXSTARG; /* Faster if we have it. */
+#else
+ dTARGET;
+#endif
+ STRLEN len;
+ int type;
+ IV iv;
+ /* NV nv; Uncomment this if you need to return NVs */
+ const char *pv;
+ INPUT:
+ SV * sv;
+ const char * s = SvPV(sv, len);
+ PPCODE:
+ /* Change this to constant(aTHX_ s, len, &iv, &nv);
+ if you need to return both NVs and IVs */
+ type = constant(aTHX_ s, len, &iv, &pv);
+ /* Return 1 or 2 items. First is error message, or undef if no error.
+ Second, if present, is found value */
+ switch (type) {
+ case PERL_constant_NOTFOUND:
+ sv = sv_2mortal(newSVpvf("%s is not a valid BerkeleyDB macro", s));
+ PUSHs(sv);
+ break;
+ case PERL_constant_NOTDEF:
+ sv = sv_2mortal(newSVpvf(
+ "Your vendor has not defined BerkeleyDB macro %s, used", s));
+ PUSHs(sv);
+ break;
+ case PERL_constant_ISIV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHi(iv);
+ break;
+ /* Uncomment this if you need to return NOs
+ case PERL_constant_ISNO:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHs(&PL_sv_no);
+ break; */
+ /* Uncomment this if you need to return NVs
+ case PERL_constant_ISNV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHn(nv);
+ break; */
+ case PERL_constant_ISPV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHp(pv, strlen(pv));
+ break;
+ /* Uncomment this if you need to return PVNs
+ case PERL_constant_ISPVN:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHp(pv, iv);
+ break; */
+ /* Uncomment this if you need to return SVs
+ case PERL_constant_ISSV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHs(sv);
+ break; */
+ /* Uncomment this if you need to return UNDEFs
+ case PERL_constant_ISUNDEF:
+ break; */
+ /* Uncomment this if you need to return UVs
+ case PERL_constant_ISUV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHu((UV)iv);
+ break; */
+ /* Uncomment this if you need to return YESs
+ case PERL_constant_ISYES:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHs(&PL_sv_yes);
+ break; */
+ default:
+ sv = sv_2mortal(newSVpvf(
+ "Unexpected return type %d while processing BerkeleyDB macro %s, used",
+ type, s));
+ PUSHs(sv);
+ }
diff --git a/bdb/perl/BerkeleyDB/dbinfo b/bdb/perl/BerkeleyDB/dbinfo
new file mode 100755
index 00000000000..af2c45facf5
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/dbinfo
@@ -0,0 +1,112 @@
+#!/usr/local/bin/perl
+
+# Name: dbinfo -- identify berkeley DB version used to create
+# a database file
+#
+# Author: Paul Marquess <Paul.Marquess@btinternet.com>
+# Version: 1.03
+# Date 17th September 2000
+#
+# Copyright (c) 1998-2002 Paul Marquess. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+# Todo: Print more stats on a db file, e.g. no of records
+# add log/txn/lock files
+
+use strict ;
+
+my %Data =
+ (
+ 0x053162 => {
+ Type => "Btree",
+ Versions =>
+ {
+ 1 => "Unknown (older than 1.71)",
+ 2 => "Unknown (older than 1.71)",
+ 3 => "1.71 -> 1.85, 1.86",
+ 4 => "Unknown",
+ 5 => "2.0.0 -> 2.3.0",
+ 6 => "2.3.1 -> 2.7.7",
+ 7 => "3.0.x",
+ 8 => "3.1.x -> 4.0.x",
+ 9 => "4.1.x or greater",
+ }
+ },
+ 0x061561 => {
+ Type => "Hash",
+ Versions =>
+ {
+ 1 => "Unknown (older than 1.71)",
+ 2 => "1.71 -> 1.85",
+ 3 => "1.86",
+ 4 => "2.0.0 -> 2.1.0",
+ 5 => "2.2.6 -> 2.7.7",
+ 6 => "3.0.x",
+ 7 => "3.1.x -> 4.0.x",
+ 8 => "4.1.x or greater",
+ }
+ },
+ 0x042253 => {
+ Type => "Queue",
+ Versions =>
+ {
+ 1 => "3.0.x",
+ 2 => "3.1.x",
+ 3 => "3.2.x -> 4.0.x",
+ 4 => "4.1.x or greater",
+ }
+ },
+ ) ;
+
+die "Usage: dbinfo file\n" unless @ARGV == 1 ;
+
+print "testing file $ARGV[0]...\n\n" ;
+open (F, "<$ARGV[0]") or die "Cannot open file $ARGV[0]: $!\n" ;
+
+my $buff ;
+read F, $buff, 20 ;
+
+my (@info) = unpack("NNNNN", $buff) ;
+my (@info1) = unpack("VVVVV", $buff) ;
+my ($magic, $version, $endian) ;
+
+if ($Data{$info[0]}) # first try DB 1.x format
+{
+ $magic = $info[0] ;
+ $version = $info[1] ;
+ $endian = "Unknown" ;
+}
+elsif ($Data{$info[3]}) # next DB 2.x big endian
+{
+ $magic = $info[3] ;
+ $version = $info[4] ;
+ $endian = "Big Endian" ;
+}
+elsif ($Data{$info1[3]}) # next DB 2.x little endian
+{
+ $magic = $info1[3] ;
+ $version = $info1[4] ;
+ $endian = "Little Endian" ;
+}
+else
+ { die "not a Berkeley DB database file.\n" }
+
+my $type = $Data{$magic} ;
+$magic = sprintf "%06X", $magic ;
+
+my $ver_string = "Unknown" ;
+$ver_string = $type->{Versions}{$version}
+ if defined $type->{Versions}{$version} ;
+
+print <<EOM ;
+File Type: Berkeley DB $type->{Type} file.
+File Version ID: $version
+Built with Berkeley DB: $ver_string
+Byte Order: $endian
+Magic: $magic
+EOM
+
+close F ;
+
+exit ;
diff --git a/bdb/perl/BerkeleyDB/hints/dec_osf.pl b/bdb/perl/BerkeleyDB/hints/dec_osf.pl
new file mode 100644
index 00000000000..6d7faeed2e2
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/hints/dec_osf.pl
@@ -0,0 +1 @@
+$self->{LIBS} = [ "@{$self->{LIBS}} -lpthreads" ];
diff --git a/bdb/perl.BerkeleyDB/hints/irix_6_5.pl b/bdb/perl/BerkeleyDB/hints/irix_6_5.pl
index b531673e6e0..b531673e6e0 100644
--- a/bdb/perl.BerkeleyDB/hints/irix_6_5.pl
+++ b/bdb/perl/BerkeleyDB/hints/irix_6_5.pl
diff --git a/bdb/perl.BerkeleyDB/hints/solaris.pl b/bdb/perl/BerkeleyDB/hints/solaris.pl
index ddd941d634a..ddd941d634a 100644
--- a/bdb/perl.BerkeleyDB/hints/solaris.pl
+++ b/bdb/perl/BerkeleyDB/hints/solaris.pl
diff --git a/bdb/perl/BerkeleyDB/mkconsts b/bdb/perl/BerkeleyDB/mkconsts
new file mode 100644
index 00000000000..7e0964333cc
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/mkconsts
@@ -0,0 +1,770 @@
+#!/usr/bin/perl
+
+use ExtUtils::Constant qw(WriteConstants);
+
+use constant DEFINE => 'define' ;
+use constant STRING => 'string' ;
+use constant IGNORE => 'ignore' ;
+
+%constants = (
+
+ #########
+ # 2.0.0
+ #########
+
+ DBM_INSERT => IGNORE,
+ DBM_REPLACE => IGNORE,
+ DBM_SUFFIX => IGNORE,
+ DB_AFTER => DEFINE,
+ DB_AM_DUP => IGNORE,
+ DB_AM_INMEM => IGNORE,
+ DB_AM_LOCKING => IGNORE,
+ DB_AM_LOGGING => IGNORE,
+ DB_AM_MLOCAL => IGNORE,
+ DB_AM_PGDEF => IGNORE,
+ DB_AM_RDONLY => IGNORE,
+ DB_AM_RECOVER => IGNORE,
+ DB_AM_SWAP => IGNORE,
+ DB_AM_TXN => IGNORE,
+ DB_APP_INIT => DEFINE,
+ DB_BEFORE => DEFINE,
+ DB_BTREEMAGIC => DEFINE,
+ DB_BTREEVERSION => DEFINE,
+ DB_BT_DELIMITER => IGNORE,
+ DB_BT_EOF => IGNORE,
+ DB_BT_FIXEDLEN => IGNORE,
+ DB_BT_PAD => IGNORE,
+ DB_BT_SNAPSHOT => IGNORE,
+ DB_CHECKPOINT => DEFINE,
+ DB_CREATE => DEFINE,
+ DB_CURRENT => DEFINE,
+ DB_DBT_INTERNAL => IGNORE,
+ DB_DBT_MALLOC => IGNORE,
+ DB_DBT_PARTIAL => IGNORE,
+ DB_DBT_USERMEM => IGNORE,
+ DB_DELETED => DEFINE,
+ DB_DELIMITER => DEFINE,
+ DB_DUP => DEFINE,
+ DB_EXCL => DEFINE,
+ DB_FIRST => DEFINE,
+ DB_FIXEDLEN => DEFINE,
+ DB_FLUSH => DEFINE,
+ DB_HASHMAGIC => DEFINE,
+ DB_HASHVERSION => DEFINE,
+ DB_HS_DIRTYMETA => IGNORE,
+ DB_INCOMPLETE => DEFINE,
+ DB_INIT_LOCK => DEFINE,
+ DB_INIT_LOG => DEFINE,
+ DB_INIT_MPOOL => DEFINE,
+ DB_INIT_TXN => DEFINE,
+ DB_KEYEXIST => DEFINE,
+ DB_KEYFIRST => DEFINE,
+ DB_KEYLAST => DEFINE,
+ DB_LAST => DEFINE,
+ DB_LOCKMAGIC => DEFINE,
+ DB_LOCKVERSION => DEFINE,
+ DB_LOCK_DEADLOCK => DEFINE,
+ DB_LOCK_NOTGRANTED => DEFINE,
+ DB_LOCK_NOTHELD => DEFINE,
+ DB_LOCK_NOWAIT => DEFINE,
+ DB_LOCK_RIW_N => DEFINE,
+ DB_LOCK_RW_N => DEFINE,
+ DB_LOGMAGIC => DEFINE,
+ DB_LOGVERSION => DEFINE,
+ DB_MAX_PAGES => DEFINE,
+ DB_MAX_RECORDS => DEFINE,
+ DB_MPOOL_CLEAN => DEFINE,
+ DB_MPOOL_CREATE => DEFINE,
+ DB_MPOOL_DIRTY => DEFINE,
+ DB_MPOOL_DISCARD => DEFINE,
+ DB_MPOOL_LAST => DEFINE,
+ DB_MPOOL_NEW => DEFINE,
+ DB_MPOOL_PRIVATE => DEFINE,
+ DB_MUTEXDEBUG => DEFINE,
+ DB_NEEDSPLIT => DEFINE,
+ DB_NEXT => DEFINE,
+ DB_NOOVERWRITE => DEFINE,
+ DB_NORECURSE => DEFINE,
+ DB_NOSYNC => DEFINE,
+ DB_NOTFOUND => DEFINE,
+ DB_PAD => DEFINE,
+ DB_PREV => DEFINE,
+ DB_RDONLY => DEFINE,
+ DB_REGISTERED => DEFINE,
+ DB_RE_MODIFIED => IGNORE,
+ DB_SET => DEFINE,
+ DB_SET_RANGE => DEFINE,
+ DB_SNAPSHOT => DEFINE,
+ DB_SWAPBYTES => DEFINE,
+ DB_TRUNCATE => DEFINE,
+ DB_TXNMAGIC => DEFINE,
+ DB_TXNVERSION => DEFINE,
+ DB_TXN_BACKWARD_ROLL => DEFINE,
+ DB_TXN_FORWARD_ROLL => DEFINE,
+ DB_TXN_LOCK_2PL => DEFINE,
+ DB_TXN_LOCK_MASK => DEFINE,
+ DB_TXN_LOCK_OPTIMISTIC => DEFINE,
+ DB_TXN_LOG_MASK => DEFINE,
+ DB_TXN_LOG_REDO => DEFINE,
+ DB_TXN_LOG_UNDO => DEFINE,
+ DB_TXN_LOG_UNDOREDO => DEFINE,
+ DB_TXN_OPENFILES => DEFINE,
+ DB_TXN_REDO => DEFINE,
+ DB_TXN_UNDO => DEFINE,
+ DB_USE_ENVIRON => DEFINE,
+ DB_USE_ENVIRON_ROOT => DEFINE,
+ DB_VERSION_MAJOR => DEFINE,
+ DB_VERSION_MINOR => DEFINE,
+ DB_VERSION_PATCH => DEFINE,
+ DB_VERSION_STRING => STRING,
+ _DB_H_ => IGNORE,
+ __BIT_TYPES_DEFINED__ => IGNORE,
+ const => IGNORE,
+
+ # enum DBTYPE
+ DB_BTREE => '2.0.0',
+ DB_HASH => '2.0.0',
+ DB_RECNO => '2.0.0',
+ DB_UNKNOWN => '2.0.0',
+
+ # enum db_lockop_t
+ DB_LOCK_DUMP => '2.0.0',
+ DB_LOCK_GET => '2.0.0',
+ DB_LOCK_PUT => '2.0.0',
+ DB_LOCK_PUT_ALL => '2.0.0',
+ DB_LOCK_PUT_OBJ => '2.0.0',
+
+ # enum db_lockmode_t
+ DB_LOCK_NG => IGNORE, # 2.0.0
+ DB_LOCK_READ => IGNORE, # 2.0.0
+ DB_LOCK_WRITE => IGNORE, # 2.0.0
+ DB_LOCK_IREAD => IGNORE, # 2.0.0
+ DB_LOCK_IWRITE => IGNORE, # 2.0.0
+ DB_LOCK_IWR => IGNORE, # 2.0.0
+
+ # enum ACTION
+ FIND => IGNORE, # 2.0.0
+ ENTER => IGNORE, # 2.0.0
+
+ #########
+ # 2.0.3
+ #########
+
+ DB_SEQUENTIAL => DEFINE,
+ DB_TEMPORARY => DEFINE,
+
+ #########
+ # 2.1.0
+ #########
+
+ DB_NOMMAP => DEFINE,
+
+ #########
+ # 2.2.6
+ #########
+
+ DB_AM_THREAD => IGNORE,
+ DB_ARCH_ABS => DEFINE,
+ DB_ARCH_DATA => DEFINE,
+ DB_ARCH_LOG => DEFINE,
+ DB_LOCK_CONFLICT => DEFINE,
+ DB_LOCK_DEFAULT => DEFINE,
+ DB_LOCK_NORUN => DEFINE,
+ DB_LOCK_OLDEST => DEFINE,
+ DB_LOCK_RANDOM => DEFINE,
+ DB_LOCK_YOUNGEST => DEFINE,
+ DB_RECOVER => DEFINE,
+ DB_RECOVER_FATAL => DEFINE,
+ DB_THREAD => DEFINE,
+ DB_TXN_NOSYNC => DEFINE,
+
+ #########
+ # 2.3.0
+ #########
+
+ DB_BTREEOLDVER => DEFINE,
+ DB_BT_RECNUM => IGNORE,
+ DB_FILE_ID_LEN => DEFINE,
+ DB_GETREC => DEFINE,
+ DB_HASHOLDVER => DEFINE,
+ DB_KEYEMPTY => DEFINE,
+ DB_LOGOLDVER => DEFINE,
+ DB_RECNUM => DEFINE,
+ DB_RECORDCOUNT => DEFINE,
+ DB_RENUMBER => DEFINE,
+ DB_RE_DELIMITER => IGNORE,
+ DB_RE_FIXEDLEN => IGNORE,
+ DB_RE_PAD => IGNORE,
+ DB_RE_RENUMBER => IGNORE,
+ DB_RE_SNAPSHOT => IGNORE,
+
+ #########
+ # 2.3.1
+ #########
+
+ DB_GET_RECNO => DEFINE,
+ DB_SET_RECNO => DEFINE,
+
+ #########
+ # 2.3.3
+ #########
+
+ DB_APPEND => DEFINE,
+
+ #########
+ # 2.3.6
+ #########
+
+ DB_TXN_CKP => DEFINE,
+
+ #########
+ # 2.3.11
+ #########
+
+ DB_ENV_APPINIT => DEFINE,
+ DB_ENV_STANDALONE => DEFINE,
+ DB_ENV_THREAD => DEFINE,
+
+ #########
+ # 2.3.12
+ #########
+
+ DB_FUNC_CALLOC => IGNORE,
+ DB_FUNC_CLOSE => IGNORE,
+ DB_FUNC_DIRFREE => IGNORE,
+ DB_FUNC_DIRLIST => IGNORE,
+ DB_FUNC_EXISTS => IGNORE,
+ DB_FUNC_FREE => IGNORE,
+ DB_FUNC_FSYNC => IGNORE,
+ DB_FUNC_IOINFO => IGNORE,
+ DB_FUNC_MALLOC => IGNORE,
+ DB_FUNC_MAP => IGNORE,
+ DB_FUNC_OPEN => IGNORE,
+ DB_FUNC_READ => IGNORE,
+ DB_FUNC_REALLOC => IGNORE,
+ DB_FUNC_SEEK => IGNORE,
+ DB_FUNC_SLEEP => IGNORE,
+ DB_FUNC_STRDUP => IGNORE,
+ DB_FUNC_UNLINK => IGNORE,
+ DB_FUNC_UNMAP => IGNORE,
+ DB_FUNC_WRITE => IGNORE,
+ DB_FUNC_YIELD => IGNORE,
+
+ #########
+ # 2.3.14
+ #########
+
+ DB_TSL_SPINS => IGNORE,
+
+ #########
+ # 2.3.16
+ #########
+
+ DB_DBM_HSEARCH => IGNORE,
+ firstkey => IGNORE,
+ hdestroy => IGNORE,
+
+ #########
+ # 2.4.10
+ #########
+
+ DB_CURLSN => DEFINE,
+ DB_FUNC_RUNLINK => IGNORE,
+ DB_REGION_ANON => DEFINE,
+ DB_REGION_INIT => DEFINE,
+ DB_REGION_NAME => DEFINE,
+ DB_TXN_LOCK_OPTIMIST => DEFINE,
+ __CURRENTLY_UNUSED => IGNORE,
+
+ # enum db_status_t
+ DB_LSTAT_ABORTED => IGNORE, # 2.4.10
+ DB_LSTAT_ERR => IGNORE, # 2.4.10
+ DB_LSTAT_FREE => IGNORE, # 2.4.10
+ DB_LSTAT_HELD => IGNORE, # 2.4.10
+ DB_LSTAT_NOGRANT => IGNORE, # 2.4.10
+ DB_LSTAT_PENDING => IGNORE, # 2.4.10
+ DB_LSTAT_WAITING => IGNORE, # 2.4.10
+
+ #########
+ # 2.4.14
+ #########
+
+ DB_MUTEXLOCKS => DEFINE,
+ DB_PAGEYIELD => DEFINE,
+ __UNUSED_100 => IGNORE,
+ __UNUSED_4000 => IGNORE,
+
+ #########
+ # 2.5.2
+ #########
+
+ DBC_CONTINUE => IGNORE,
+ DBC_KEYSET => IGNORE,
+ DBC_RECOVER => IGNORE,
+ DBC_RMW => IGNORE,
+ DB_DBM_ERROR => IGNORE,
+ DB_GET_BOTH => DEFINE,
+ DB_NEXT_DUP => DEFINE,
+ DB_OPFLAGS_MASK => DEFINE,
+ DB_RMW => DEFINE,
+ DB_RUNRECOVERY => DEFINE,
+ dbmclose => IGNORE,
+
+ #########
+ # 2.5.9
+ #########
+
+ DB_DUPSORT => DEFINE,
+ DB_JOIN_ITEM => DEFINE,
+
+ #########
+ # 2.6.4
+ #########
+
+ DBC_WRITER => IGNORE,
+ DB_AM_CDB => IGNORE,
+ DB_ENV_CDB => DEFINE,
+ DB_INIT_CDB => DEFINE,
+ DB_LOCK_UPGRADE => DEFINE,
+ DB_WRITELOCK => DEFINE,
+
+ #########
+ # 2.7.1
+ #########
+
+
+ # enum db_lockop_t
+ DB_LOCK_INHERIT => '2.7.1',
+
+ #########
+ # 2.7.7
+ #########
+
+ DB_FCNTL_LOCKING => DEFINE,
+
+ #########
+ # 3.0.55
+ #########
+
+ DBC_WRITECURSOR => IGNORE,
+ DB_AM_DISCARD => IGNORE,
+ DB_AM_SUBDB => IGNORE,
+ DB_BT_REVSPLIT => IGNORE,
+ DB_CONSUME => DEFINE,
+ DB_CXX_NO_EXCEPTIONS => DEFINE,
+ DB_DBT_REALLOC => IGNORE,
+ DB_DUPCURSOR => DEFINE,
+ DB_ENV_CREATE => DEFINE,
+ DB_ENV_DBLOCAL => DEFINE,
+ DB_ENV_LOCKDOWN => DEFINE,
+ DB_ENV_LOCKING => DEFINE,
+ DB_ENV_LOGGING => DEFINE,
+ DB_ENV_NOMMAP => DEFINE,
+ DB_ENV_OPEN_CALLED => DEFINE,
+ DB_ENV_PRIVATE => DEFINE,
+ DB_ENV_SYSTEM_MEM => DEFINE,
+ DB_ENV_TXN => DEFINE,
+ DB_ENV_TXN_NOSYNC => DEFINE,
+ DB_ENV_USER_ALLOC => DEFINE,
+ DB_FORCE => DEFINE,
+ DB_LOCKDOWN => DEFINE,
+ DB_LOCK_RECORD => DEFINE,
+ DB_LOGFILEID_INVALID => DEFINE,
+ DB_MPOOL_NEW_GROUP => DEFINE,
+ DB_NEXT_NODUP => DEFINE,
+ DB_OK_BTREE => DEFINE,
+ DB_OK_HASH => DEFINE,
+ DB_OK_QUEUE => DEFINE,
+ DB_OK_RECNO => DEFINE,
+ DB_OLD_VERSION => DEFINE,
+ DB_OPEN_CALLED => DEFINE,
+ DB_PAGE_LOCK => DEFINE,
+ DB_POSITION => DEFINE,
+ DB_POSITIONI => DEFINE,
+ DB_PRIVATE => DEFINE,
+ DB_QAMMAGIC => DEFINE,
+ DB_QAMOLDVER => DEFINE,
+ DB_QAMVERSION => DEFINE,
+ DB_RECORD_LOCK => DEFINE,
+ DB_REVSPLITOFF => DEFINE,
+ DB_SYSTEM_MEM => DEFINE,
+ DB_TEST_POSTLOG => DEFINE,
+ DB_TEST_POSTLOGMETA => DEFINE,
+ DB_TEST_POSTOPEN => DEFINE,
+ DB_TEST_POSTRENAME => DEFINE,
+ DB_TEST_POSTSYNC => DEFINE,
+ DB_TEST_PREOPEN => DEFINE,
+ DB_TEST_PRERENAME => DEFINE,
+ DB_TXN_NOWAIT => DEFINE,
+ DB_TXN_SYNC => DEFINE,
+ DB_UPGRADE => DEFINE,
+ DB_VERB_CHKPOINT => DEFINE,
+ DB_VERB_DEADLOCK => DEFINE,
+ DB_VERB_RECOVERY => DEFINE,
+ DB_VERB_WAITSFOR => DEFINE,
+ DB_WRITECURSOR => DEFINE,
+ DB_XA_CREATE => DEFINE,
+
+ # enum DBTYPE
+ DB_QUEUE => '3.0.55',
+
+ #########
+ # 3.1.12
+ #########
+
+ DBC_ACTIVE => IGNORE,
+ DBC_OPD => IGNORE,
+ DBC_TRANSIENT => IGNORE,
+ DBC_WRITEDUP => IGNORE,
+ DB_AGGRESSIVE => DEFINE,
+ DB_AM_DUPSORT => IGNORE,
+ DB_CACHED_COUNTS => DEFINE,
+ DB_CLIENT => DEFINE,
+ DB_DBT_DUPOK => IGNORE,
+ DB_DBT_ISSET => IGNORE,
+ DB_ENV_RPCCLIENT => DEFINE,
+ DB_GET_BOTHC => DEFINE,
+ DB_JOIN_NOSORT => DEFINE,
+ DB_NODUPDATA => DEFINE,
+ DB_NOORDERCHK => DEFINE,
+ DB_NOSERVER => DEFINE,
+ DB_NOSERVER_HOME => DEFINE,
+ DB_NOSERVER_ID => DEFINE,
+ DB_ODDFILESIZE => DEFINE,
+ DB_ORDERCHKONLY => DEFINE,
+ DB_PREV_NODUP => DEFINE,
+ DB_PR_HEADERS => DEFINE,
+ DB_PR_PAGE => DEFINE,
+ DB_PR_RECOVERYTEST => DEFINE,
+ DB_RDWRMASTER => DEFINE,
+ DB_SALVAGE => DEFINE,
+ DB_VERIFY_BAD => DEFINE,
+ DB_VERIFY_FATAL => DEFINE,
+ DB_VRFY_FLAGMASK => DEFINE,
+
+ # enum db_recops
+ DB_TXN_ABORT => '3.1.12',
+ DB_TXN_BACKWARD_ROLL => '3.1.12',
+ DB_TXN_FORWARD_ROLL => '3.1.12',
+ DB_TXN_OPENFILES => '3.1.12',
+
+ #########
+ # 3.2.3
+ #########
+
+ DBC_COMPENSATE => IGNORE,
+ DB_AM_VERIFYING => IGNORE,
+ DB_CDB_ALLDB => DEFINE,
+ DB_ENV_CDB_ALLDB => DEFINE,
+ DB_EXTENT => DEFINE,
+ DB_JOINENV => DEFINE,
+ DB_LOCK_SWITCH => DEFINE,
+ DB_MPOOL_EXTENT => DEFINE,
+ DB_REGION_MAGIC => DEFINE,
+ DB_UNRESOLVED_CHILD => DEFINE,
+ DB_VERIFY => DEFINE,
+
+ # enum db_notices
+ DB_NOTICE_LOGFILE_CHANGED => IGNORE, # 3.2.3
+
+ #########
+ # 3.2.6
+ #########
+
+ DB_ALREADY_ABORTED => DEFINE,
+ DB_CONSUME_WAIT => DEFINE,
+ DB_JAVA_CALLBACK => DEFINE,
+ DB_TEST_POSTEXTDELETE => DEFINE,
+ DB_TEST_POSTEXTOPEN => DEFINE,
+ DB_TEST_POSTEXTUNLINK => DEFINE,
+ DB_TEST_PREEXTDELETE => DEFINE,
+ DB_TEST_PREEXTOPEN => DEFINE,
+ DB_TEST_PREEXTUNLINK => DEFINE,
+
+ # enum db_lockmode_t
+ DB_LOCK_WAIT => IGNORE, # 3.2.6
+
+ #########
+ # 3.3.4
+ #########
+
+ DBC_DIRTY_READ => IGNORE,
+ DBC_MULTIPLE => IGNORE,
+ DBC_MULTIPLE_KEY => IGNORE,
+ DB_AM_DIRTY => IGNORE,
+ DB_AM_SECONDARY => IGNORE,
+ DB_COMMIT => DEFINE,
+ DB_DBT_APPMALLOC => IGNORE,
+ DB_DIRTY_READ => DEFINE,
+ DB_DONOTINDEX => DEFINE,
+ DB_ENV_PANIC_OK => DEFINE,
+ DB_ENV_RPCCLIENT_GIVEN => DEFINE,
+ DB_FAST_STAT => DEFINE,
+ DB_LOCK_MAXLOCKS => DEFINE,
+ DB_LOCK_MINLOCKS => DEFINE,
+ DB_LOCK_MINWRITE => DEFINE,
+ DB_MULTIPLE => DEFINE,
+ DB_MULTIPLE_KEY => DEFINE,
+ DB_PAGE_NOTFOUND => DEFINE,
+ DB_RPC_SERVERPROG => DEFINE,
+ DB_RPC_SERVERVERS => DEFINE,
+ DB_UPDATE_SECONDARY => DEFINE,
+ DB_XIDDATASIZE => DEFINE,
+
+ # enum db_recops
+ DB_TXN_POPENFILES => '3.3.4',
+
+ # enum db_lockop_t
+ DB_LOCK_UPGRADE_WRITE => '3.3.4',
+
+ # enum db_lockmode_t
+ DB_LOCK_DIRTY => IGNORE, # 3.3.4
+ DB_LOCK_WWRITE => IGNORE, # 3.3.4
+
+ #########
+ # 3.3.11
+ #########
+
+ DB_SECONDARY_BAD => DEFINE,
+ DB_SURPRISE_KID => DEFINE,
+ DB_TEST_POSTDESTROY => DEFINE,
+ DB_TEST_PREDESTROY => DEFINE,
+
+ #########
+ # 4.0.7
+ #########
+
+ DB_APPLY_LOGREG => DEFINE,
+ DB_BROADCAST_EID => DEFINE,
+ DB_CL_WRITER => DEFINE,
+ DB_ENV_NOLOCKING => DEFINE,
+ DB_ENV_NOPANIC => DEFINE,
+ DB_ENV_REGION_INIT => DEFINE,
+ DB_ENV_REP_CLIENT => DEFINE,
+ DB_ENV_REP_LOGSONLY => DEFINE,
+ DB_ENV_REP_MASTER => DEFINE,
+ DB_ENV_YIELDCPU => DEFINE,
+ DB_GET_BOTH_RANGE => DEFINE,
+ DB_INVALID_EID => DEFINE,
+ DB_LOCK_EXPIRE => DEFINE,
+ DB_LOCK_FREE_LOCKER => DEFINE,
+ DB_LOCK_SET_TIMEOUT => DEFINE,
+ DB_LOGC_BUF_SIZE => DEFINE,
+ DB_LOG_DISK => DEFINE,
+ DB_LOG_LOCKED => DEFINE,
+ DB_LOG_SILENT_ERR => DEFINE,
+ DB_NOLOCKING => DEFINE,
+ DB_NOPANIC => DEFINE,
+ DB_PANIC_ENVIRONMENT => DEFINE,
+ DB_REP_CLIENT => DEFINE,
+ DB_REP_DUPMASTER => DEFINE,
+ DB_REP_HOLDELECTION => DEFINE,
+ DB_REP_LOGSONLY => DEFINE,
+ DB_REP_MASTER => DEFINE,
+ DB_REP_NEWMASTER => DEFINE,
+ DB_REP_NEWSITE => DEFINE,
+ DB_REP_OUTDATED => DEFINE,
+ DB_REP_PERMANENT => DEFINE,
+ DB_REP_UNAVAIL => DEFINE,
+ DB_SET_LOCK_TIMEOUT => DEFINE,
+ DB_SET_TXN_NOW => DEFINE,
+ DB_SET_TXN_TIMEOUT => DEFINE,
+ DB_STAT_CLEAR => DEFINE,
+ DB_TIMEOUT => DEFINE,
+ DB_YIELDCPU => DEFINE,
+ MP_FLUSH => IGNORE,
+ MP_OPEN_CALLED => IGNORE,
+ MP_READONLY => IGNORE,
+ MP_UPGRADE => IGNORE,
+ MP_UPGRADE_FAIL => IGNORE,
+ TXN_CHILDCOMMIT => IGNORE,
+ TXN_COMPENSATE => IGNORE,
+ TXN_DIRTY_READ => IGNORE,
+ TXN_LOCKTIMEOUT => IGNORE,
+ TXN_MALLOC => IGNORE,
+ TXN_NOSYNC => IGNORE,
+ TXN_NOWAIT => IGNORE,
+ TXN_SYNC => IGNORE,
+
+ # enum db_recops
+ DB_TXN_APPLY => '4.0.7',
+
+ # enum db_lockop_t
+ DB_LOCK_GET_TIMEOUT => '4.0.7',
+ DB_LOCK_PUT_READ => '4.0.7',
+ DB_LOCK_TIMEOUT => '4.0.7',
+
+ # enum db_status_t
+ DB_LSTAT_EXPIRED => IGNORE, # 4.0.7
+
+ #########
+ # 4.0.14
+ #########
+
+ DB_EID_BROADCAST => DEFINE,
+ DB_EID_INVALID => DEFINE,
+ DB_VERB_REPLICATION => DEFINE,
+
+ #########
+ # 4.1.17
+ #########
+
+ DBC_OWN_LID => IGNORE,
+ DB_AM_CHKSUM => IGNORE,
+ DB_AM_CL_WRITER => IGNORE,
+ DB_AM_COMPENSATE => IGNORE,
+ DB_AM_CREATED => IGNORE,
+ DB_AM_CREATED_MSTR => IGNORE,
+ DB_AM_DBM_ERROR => IGNORE,
+ DB_AM_DELIMITER => IGNORE,
+ DB_AM_ENCRYPT => IGNORE,
+ DB_AM_FIXEDLEN => IGNORE,
+ DB_AM_IN_RENAME => IGNORE,
+ DB_AM_OPEN_CALLED => IGNORE,
+ DB_AM_PAD => IGNORE,
+ DB_AM_RECNUM => IGNORE,
+ DB_AM_RENUMBER => IGNORE,
+ DB_AM_REVSPLITOFF => IGNORE,
+ DB_AM_SNAPSHOT => IGNORE,
+ DB_AUTO_COMMIT => DEFINE,
+ DB_CHKSUM_SHA1 => DEFINE,
+ DB_DIRECT => DEFINE,
+ DB_DIRECT_DB => DEFINE,
+ DB_DIRECT_LOG => DEFINE,
+ DB_ENCRYPT => DEFINE,
+ DB_ENCRYPT_AES => DEFINE,
+ DB_ENV_AUTO_COMMIT => DEFINE,
+ DB_ENV_DIRECT_DB => DEFINE,
+ DB_ENV_DIRECT_LOG => DEFINE,
+ DB_ENV_FATAL => DEFINE,
+ DB_ENV_OVERWRITE => DEFINE,
+ DB_ENV_TXN_WRITE_NOSYNC => DEFINE,
+ DB_HANDLE_LOCK => DEFINE,
+ DB_LOCK_NOTEXIST => DEFINE,
+ DB_LOCK_REMOVE => DEFINE,
+ DB_NOCOPY => DEFINE,
+ DB_OVERWRITE => DEFINE,
+ DB_PERMANENT => DEFINE,
+ DB_PRINTABLE => DEFINE,
+ DB_RENAMEMAGIC => DEFINE,
+ DB_TEST_ELECTINIT => DEFINE,
+ DB_TEST_ELECTSEND => DEFINE,
+ DB_TEST_ELECTVOTE1 => DEFINE,
+ DB_TEST_ELECTVOTE2 => DEFINE,
+ DB_TEST_ELECTWAIT1 => DEFINE,
+ DB_TEST_ELECTWAIT2 => DEFINE,
+ DB_TEST_SUBDB_LOCKS => DEFINE,
+ DB_TXN_LOCK => DEFINE,
+ DB_TXN_WRITE_NOSYNC => DEFINE,
+ DB_WRITEOPEN => DEFINE,
+ DB_WRNOSYNC => DEFINE,
+ _DB_EXT_PROT_IN_ => IGNORE,
+
+ # enum db_lockop_t
+ DB_LOCK_TRADE => '4.1.17',
+
+ # enum db_status_t
+ DB_LSTAT_NOTEXIST => IGNORE, # 4.1.17
+
+ # enum DB_CACHE_PRIORITY
+ DB_PRIORITY_VERY_LOW => '4.1.17',
+ DB_PRIORITY_LOW => '4.1.17',
+ DB_PRIORITY_DEFAULT => '4.1.17',
+ DB_PRIORITY_HIGH => '4.1.17',
+ DB_PRIORITY_VERY_HIGH => '4.1.17',
+
+ # enum db_recops
+ DB_TXN_BACKWARD_ALLOC => '4.1.17',
+ DB_TXN_GETPGNOS => '4.1.17',
+ DB_TXN_PRINT => '4.1.17',
+
+ ) ;
+
+sub enum_Macro
+{
+ my $str = shift ;
+ my ($major, $minor, $patch) = split /\./, $str ;
+
+ my $macro =
+ "#if (DB_VERSION_MAJOR > $major) || \\\n" .
+ " (DB_VERSION_MAJOR == $major && DB_VERSION_MINOR > $minor) || \\\n" .
+ " (DB_VERSION_MAJOR == $major && DB_VERSION_MINOR == $minor && \\\n" .
+ " DB_VERSION_PATCH >= $patch)\n" ;
+
+ return $macro;
+
+}
+
+sub OutputXS
+{
+
+ my @names = () ;
+
+ foreach my $key (sort keys %constants)
+ {
+ my $val = $constants{$key} ;
+ next if $val eq IGNORE;
+
+ if ($val eq STRING)
+ { push @names, { name => $key, type => "PV" } }
+ elsif ($val eq DEFINE)
+ { push @names, $key }
+ else
+ { push @names, { name => $key, macro => [enum_Macro($val), "#endif\n"] } }
+ }
+
+ warn "Updating constants.xs & constants.h...\n";
+ WriteConstants(
+ NAME => BerkeleyDB,
+ NAMES => \@names,
+ C_FILE => 'constants.h',
+ XS_FILE => 'constants.xs',
+ ) ;
+}
+
+sub OutputPM
+{
+ my $filename = 'BerkeleyDB.pm';
+ warn "Updating $filename...\n";
+ open IN, "<$filename" || die "Cannot open $filename: $!\n";
+ open OUT, ">$filename.tmp" || die "Cannot open $filename.tmp: $!\n";
+
+ my $START = '@EXPORT = qw(' ;
+ my $START_re = quotemeta $START ;
+ my $END = ');';
+ my $END_re = quotemeta $END ;
+
+ # skip to the @EXPORT declaration
+ OUTER: while (<IN>)
+ {
+ if ( /^\s*$START_re/ )
+ {
+ # skip to the end marker.
+ while (<IN>)
+ { last OUTER if /^\s*$END_re/ }
+ }
+ print OUT ;
+ }
+
+ print OUT "$START\n";
+ foreach my $key (sort keys %constants)
+ {
+ next if $constants{$key} eq IGNORE;
+ print OUT "\t$key\n";
+ }
+ print OUT "\t$END\n";
+
+ while (<IN>)
+ {
+ print OUT ;
+ }
+
+ close IN;
+ close OUT;
+
+ rename $filename, "$filename.bak" || die "Cannot rename $filename: $!\n" ;
+ rename "$filename.tmp", $filename || die "Cannot rename $filename.tmp: $!\n" ;
+}
+
+OutputXS() ;
+OutputPM() ;
diff --git a/bdb/perl.BerkeleyDB/mkpod b/bdb/perl/BerkeleyDB/mkpod
index 44bbf3fbf4f..44bbf3fbf4f 100755
--- a/bdb/perl.BerkeleyDB/mkpod
+++ b/bdb/perl/BerkeleyDB/mkpod
diff --git a/bdb/perl.BerkeleyDB/patches/5.004 b/bdb/perl/BerkeleyDB/patches/5.004
index 143ec95afbc..143ec95afbc 100644
--- a/bdb/perl.BerkeleyDB/patches/5.004
+++ b/bdb/perl/BerkeleyDB/patches/5.004
diff --git a/bdb/perl.BerkeleyDB/patches/5.004_01 b/bdb/perl/BerkeleyDB/patches/5.004_01
index 1b05eb4e02b..1b05eb4e02b 100644
--- a/bdb/perl.BerkeleyDB/patches/5.004_01
+++ b/bdb/perl/BerkeleyDB/patches/5.004_01
diff --git a/bdb/perl.BerkeleyDB/patches/5.004_02 b/bdb/perl/BerkeleyDB/patches/5.004_02
index 238f8737941..238f8737941 100644
--- a/bdb/perl.BerkeleyDB/patches/5.004_02
+++ b/bdb/perl/BerkeleyDB/patches/5.004_02
diff --git a/bdb/perl.BerkeleyDB/patches/5.004_03 b/bdb/perl/BerkeleyDB/patches/5.004_03
index 06331eac922..06331eac922 100644
--- a/bdb/perl.BerkeleyDB/patches/5.004_03
+++ b/bdb/perl/BerkeleyDB/patches/5.004_03
diff --git a/bdb/perl.BerkeleyDB/patches/5.004_04 b/bdb/perl/BerkeleyDB/patches/5.004_04
index a227dc700d9..a227dc700d9 100644
--- a/bdb/perl.BerkeleyDB/patches/5.004_04
+++ b/bdb/perl/BerkeleyDB/patches/5.004_04
diff --git a/bdb/perl.BerkeleyDB/patches/5.004_05 b/bdb/perl/BerkeleyDB/patches/5.004_05
index 51c8bf35009..51c8bf35009 100644
--- a/bdb/perl.BerkeleyDB/patches/5.004_05
+++ b/bdb/perl/BerkeleyDB/patches/5.004_05
diff --git a/bdb/perl.BerkeleyDB/patches/5.005 b/bdb/perl/BerkeleyDB/patches/5.005
index effee3e8275..effee3e8275 100644
--- a/bdb/perl.BerkeleyDB/patches/5.005
+++ b/bdb/perl/BerkeleyDB/patches/5.005
diff --git a/bdb/perl.BerkeleyDB/patches/5.005_01 b/bdb/perl/BerkeleyDB/patches/5.005_01
index 2a05dd545f6..2a05dd545f6 100644
--- a/bdb/perl.BerkeleyDB/patches/5.005_01
+++ b/bdb/perl/BerkeleyDB/patches/5.005_01
diff --git a/bdb/perl.BerkeleyDB/patches/5.005_02 b/bdb/perl/BerkeleyDB/patches/5.005_02
index 5dd57ddc03f..5dd57ddc03f 100644
--- a/bdb/perl.BerkeleyDB/patches/5.005_02
+++ b/bdb/perl/BerkeleyDB/patches/5.005_02
diff --git a/bdb/perl.BerkeleyDB/patches/5.005_03 b/bdb/perl/BerkeleyDB/patches/5.005_03
index 115f9f5b909..115f9f5b909 100644
--- a/bdb/perl.BerkeleyDB/patches/5.005_03
+++ b/bdb/perl/BerkeleyDB/patches/5.005_03
diff --git a/bdb/perl.BerkeleyDB/patches/5.6.0 b/bdb/perl/BerkeleyDB/patches/5.6.0
index 1f9b3b620de..1f9b3b620de 100644
--- a/bdb/perl.BerkeleyDB/patches/5.6.0
+++ b/bdb/perl/BerkeleyDB/patches/5.6.0
diff --git a/bdb/perl/BerkeleyDB/ppport.h b/bdb/perl/BerkeleyDB/ppport.h
new file mode 100644
index 00000000000..0887c2159a9
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/ppport.h
@@ -0,0 +1,329 @@
+/* This file is Based on output from
+ * Perl/Pollution/Portability Version 2.0000 */
+
+#ifndef _P_P_PORTABILITY_H_
+#define _P_P_PORTABILITY_H_
+
+#ifndef PERL_REVISION
+# ifndef __PATCHLEVEL_H_INCLUDED__
+# include "patchlevel.h"
+# endif
+# ifndef PERL_REVISION
+# define PERL_REVISION (5)
+ /* Replace: 1 */
+# define PERL_VERSION PATCHLEVEL
+# define PERL_SUBVERSION SUBVERSION
+ /* Replace PERL_PATCHLEVEL with PERL_VERSION */
+ /* Replace: 0 */
+# endif
+#endif
+
+#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
+
+#ifndef ERRSV
+# define ERRSV perl_get_sv("@",FALSE)
+#endif
+
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
+/* Replace: 1 */
+# define PL_Sv Sv
+# define PL_compiling compiling
+# define PL_copline copline
+# define PL_curcop curcop
+# define PL_curstash curstash
+# define PL_defgv defgv
+# define PL_dirty dirty
+# define PL_hints hints
+# define PL_na na
+# define PL_perldb perldb
+# define PL_rsfp_filters rsfp_filters
+# define PL_rsfp rsfp
+# define PL_stdingv stdingv
+# define PL_sv_no sv_no
+# define PL_sv_undef sv_undef
+# define PL_sv_yes sv_yes
+/* Replace: 0 */
+#endif
+
+#ifndef pTHX
+# define pTHX
+# define pTHX_
+# define aTHX
+# define aTHX_
+#endif
+
+#ifndef PTR2IV
+# define PTR2IV(d) (IV)(d)
+#endif
+
+#ifndef INT2PTR
+# define INT2PTR(any,d) (any)(d)
+#endif
+
+#ifndef dTHR
+# ifdef WIN32
+# define dTHR extern int Perl___notused
+# else
+# define dTHR extern int errno
+# endif
+#endif
+
+#ifndef boolSV
+# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
+#endif
+
+#ifndef gv_stashpvn
+# define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
+#endif
+
+#ifndef newSVpvn
+# define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0))
+#endif
+
+#ifndef newRV_inc
+/* Replace: 1 */
+# define newRV_inc(sv) newRV(sv)
+/* Replace: 0 */
+#endif
+
+/* DEFSV appears first in 5.004_56 */
+#ifndef DEFSV
+# define DEFSV GvSV(PL_defgv)
+#endif
+
+#ifndef SAVE_DEFSV
+# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv))
+#endif
+
+#ifndef newRV_noinc
+# ifdef __GNUC__
+# define newRV_noinc(sv) \
+ ({ \
+ SV *nsv = (SV*)newRV(sv); \
+ SvREFCNT_dec(sv); \
+ nsv; \
+ })
+# else
+# if defined(CRIPPLED_CC) || defined(USE_THREADS)
+static SV * newRV_noinc (SV * sv)
+{
+ SV *nsv = (SV*)newRV(sv);
+ SvREFCNT_dec(sv);
+ return nsv;
+}
+# else
+# define newRV_noinc(sv) \
+ ((PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv)
+# endif
+# endif
+#endif
+
+/* Provide: newCONSTSUB */
+
+/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))
+
+#if defined(NEED_newCONSTSUB)
+static
+#else
+extern void newCONSTSUB _((HV * stash, char * name, SV *sv));
+#endif
+
+#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
+void
+newCONSTSUB(stash,name,sv)
+HV *stash;
+char *name;
+SV *sv;
+{
+ U32 oldhints = PL_hints;
+ HV *old_cop_stash = PL_curcop->cop_stash;
+ HV *old_curstash = PL_curstash;
+ line_t oldline = PL_curcop->cop_line;
+ PL_curcop->cop_line = PL_copline;
+
+ PL_hints &= ~HINT_BLOCK_SCOPE;
+ if (stash)
+ PL_curstash = PL_curcop->cop_stash = stash;
+
+ newSUB(
+
+#if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22))
+ /* before 5.003_22 */
+ start_subparse(),
+#else
+# if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22)
+ /* 5.003_22 */
+ start_subparse(0),
+# else
+ /* 5.003_23 onwards */
+ start_subparse(FALSE, 0),
+# endif
+#endif
+
+ newSVOP(OP_CONST, 0, newSVpv(name,0)),
+ newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */
+ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+ );
+
+ PL_hints = oldhints;
+ PL_curcop->cop_stash = old_cop_stash;
+ PL_curstash = old_curstash;
+ PL_curcop->cop_line = oldline;
+}
+#endif
+
+#endif /* newCONSTSUB */
+
+
+#ifndef START_MY_CXT
+
+/*
+ * Boilerplate macros for initializing and accessing interpreter-local
+ * data from C. All statics in extensions should be reworked to use
+ * this, if you want to make the extension thread-safe. See ext/re/re.xs
+ * for an example of the use of these macros.
+ *
+ * Code that uses these macros is responsible for the following:
+ * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
+ * 2. Declare a typedef named my_cxt_t that is a structure that contains
+ * all the data that needs to be interpreter-local.
+ * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
+ * 4. Use the MY_CXT_INIT macro such that it is called exactly once
+ * (typically put in the BOOT: section).
+ * 5. Use the members of the my_cxt_t structure everywhere as
+ * MY_CXT.member.
+ * 6. Use the dMY_CXT macro (a declaration) in all the functions that
+ * access MY_CXT.
+ */
+
+#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
+ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
+
+/* This must appear in all extensions that define a my_cxt_t structure,
+ * right after the definition (i.e. at file scope). The non-threads
+ * case below uses it to declare the data as static. */
+#define START_MY_CXT
+
+#if PERL_REVISION == 5 && \
+ (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
+/* Fetches the SV that keeps the per-interpreter data. */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE)
+#else /* >= perl5.004_68 */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
+ sizeof(MY_CXT_KEY)-1, TRUE)
+#endif /* < perl5.004_68 */
+
+/* This declaration should be used within all functions that use the
+ * interpreter-local data. */
+#define dMY_CXT \
+ dMY_CXT_SV; \
+ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
+
+/* Creates and zeroes the per-interpreter data.
+ * (We allocate my_cxtp in a Perl SV so that it will be released when
+ * the interpreter goes away.) */
+#define MY_CXT_INIT \
+ dMY_CXT_SV; \
+ /* newSV() allocates one more than needed */ \
+ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+ Zero(my_cxtp, 1, my_cxt_t); \
+ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
+
+/* This macro must be used to access members of the my_cxt_t structure.
+ * e.g. MYCXT.some_data */
+#define MY_CXT (*my_cxtp)
+
+/* Judicious use of these macros can reduce the number of times dMY_CXT
+ * is used. Use is similar to pTHX, aTHX etc. */
+#define pMY_CXT my_cxt_t *my_cxtp
+#define pMY_CXT_ pMY_CXT,
+#define _pMY_CXT ,pMY_CXT
+#define aMY_CXT my_cxtp
+#define aMY_CXT_ aMY_CXT,
+#define _aMY_CXT ,aMY_CXT
+
+#else /* single interpreter */
+
+#ifndef NOOP
+# define NOOP (void)0
+#endif
+
+#ifdef HASATTRIBUTE
+# define PERL_UNUSED_DECL __attribute__((unused))
+#else
+# define PERL_UNUSED_DECL
+#endif
+
+#ifndef dNOOP
+# define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#define START_MY_CXT static my_cxt_t my_cxt;
+#define dMY_CXT_SV dNOOP
+#define dMY_CXT dNOOP
+#define MY_CXT_INIT NOOP
+#define MY_CXT my_cxt
+
+#define pMY_CXT void
+#define pMY_CXT_
+#define _pMY_CXT
+#define aMY_CXT
+#define aMY_CXT_
+#define _aMY_CXT
+
+#endif
+
+#endif /* START_MY_CXT */
+
+
+#ifndef DBM_setFilter
+
+/*
+ The DBM_setFilter & DBM_ckFilter macros are only used by
+ the *DB*_File modules
+*/
+
+#define DBM_setFilter(db_type,code) \
+ { \
+ if (db_type) \
+ RETVAL = sv_mortalcopy(db_type) ; \
+ ST(0) = RETVAL ; \
+ if (db_type && (code == &PL_sv_undef)) { \
+ SvREFCNT_dec(db_type) ; \
+ db_type = NULL ; \
+ } \
+ else if (code) { \
+ if (db_type) \
+ sv_setsv(db_type, code) ; \
+ else \
+ db_type = newSVsv(code) ; \
+ } \
+ }
+
+#define DBM_ckFilter(arg,type,name) \
+ if (db->type) { \
+ if (db->filtering) { \
+ croak("recursion detected in %s", name) ; \
+ } \
+ ENTER ; \
+ SAVETMPS ; \
+ SAVEINT(db->filtering) ; \
+ db->filtering = TRUE ; \
+ SAVESPTR(DEFSV) ; \
+ DEFSV = arg ; \
+ SvTEMP_off(arg) ; \
+ PUSHMARK(SP) ; \
+ PUTBACK ; \
+ (void) perl_call_sv(db->type, G_DISCARD); \
+ SPAGAIN ; \
+ PUTBACK ; \
+ FREETMPS ; \
+ LEAVE ; \
+ }
+
+#endif /* DBM_setFilter */
+
+#endif /* _P_P_PORTABILITY_H_ */
diff --git a/bdb/perl/BerkeleyDB/scan b/bdb/perl/BerkeleyDB/scan
new file mode 100644
index 00000000000..eb064950b2e
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/scan
@@ -0,0 +1,229 @@
+#!/usr/local/bin/perl
+
+my $ignore_re = '^(' . join("|",
+ qw(
+ _
+ [a-z]
+ DBM
+ DBC
+ DB_AM_
+ DB_BT_
+ DB_RE_
+ DB_HS_
+ DB_FUNC_
+ DB_DBT_
+ DB_DBM
+ DB_TSL
+ MP
+ TXN
+ )) . ')' ;
+
+my %ignore_def = map {$_, 1} qw() ;
+
+%ignore_enums = map {$_, 1} qw( ACTION db_status_t db_notices db_lockmode_t ) ;
+
+my $filler = ' ' x 26 ;
+
+chdir "libraries" || die "Cannot chdir into './libraries': $!\n";
+
+foreach my $name (sort tuple glob "[2-9]*")
+{
+ my $inc = "$name/include/db.h" ;
+ next unless -f $inc ;
+
+ my $file = readFile($inc) ;
+ StripCommentsAndStrings($file) ;
+ my $result = scan($name, $file) ;
+ print "\n\t#########\n\t# $name\n\t#########\n\n$result"
+ if $result;
+}
+exit ;
+
+
+sub scan
+{
+ my $version = shift ;
+ my $file = shift ;
+
+ my %seen_define = () ;
+ my $result = "" ;
+
+ if (1) {
+ # Preprocess all tri-graphs
+ # including things stuck in quoted string constants.
+ $file =~ s/\?\?=/#/g; # | ??=| #|
+ $file =~ s/\?\?\!/|/g; # | ??!| ||
+ $file =~ s/\?\?'/^/g; # | ??'| ^|
+ $file =~ s/\?\?\(/[/g; # | ??(| [|
+ $file =~ s/\?\?\)/]/g; # | ??)| ]|
+ $file =~ s/\?\?\-/~/g; # | ??-| ~|
+ $file =~ s/\?\?\//\\/g; # | ??/| \|
+ $file =~ s/\?\?</{/g; # | ??<| {|
+ $file =~ s/\?\?>/}/g; # | ??>| }|
+ }
+
+ while ( $file =~ /^\s*#\s*define\s+([\$\w]+)\b(?!\()\s*(.*)/gm )
+ {
+ my $def = $1;
+ my $rest = $2;
+ my $ignore = 0 ;
+
+ $ignore = 1 if $ignore_def{$def} || $def =~ /$ignore_re/o ;
+
+ # Cannot do: (-1) and ((LHANDLE)3) are OK:
+ #print("Skip non-wordy $def => $rest\n"),
+
+ $rest =~ s/\s*$//;
+ #next if $rest =~ /[^\w\$]/;
+
+ #print "Matched $_ ($def)\n" ;
+
+ next if $before{$def} ++ ;
+
+ if ($ignore)
+ { $seen_define{$def} = 'IGNORE' }
+ elsif ($rest =~ /"/)
+ { $seen_define{$def} = 'STRING' }
+ else
+ { $seen_define{$def} = 'DEFINE' }
+ }
+
+ foreach $define (sort keys %seen_define)
+ {
+ my $out = $filler ;
+ substr($out,0, length $define) = $define;
+ $result .= "\t$out => $seen_define{$define},\n" ;
+ }
+
+ while ($file =~ /\btypedef\s+enum\s*{(.*?)}\s*(\w+)/gs )
+ {
+ my $enum = $1 ;
+ my $name = $2 ;
+ my $ignore = 0 ;
+
+ $ignore = 1 if $ignore_enums{$name} ;
+
+ #$enum =~ s/\s*=\s*\S+\s*(,?)\s*\n/$1/g;
+ $enum =~ s/^\s*//;
+ $enum =~ s/\s*$//;
+
+ my @tokens = map { s/\s*=.*// ; $_} split /\s*,\s*/, $enum ;
+ my @new = grep { ! $Enums{$_}++ } @tokens ;
+ if (@new)
+ {
+ my $value ;
+ if ($ignore)
+ { $value = "IGNORE, # $version" }
+ else
+ { $value = "'$version'," }
+
+ $result .= "\n\t# enum $name\n";
+ my $out = $filler ;
+ foreach $name (@new)
+ {
+ $out = $filler ;
+ substr($out,0, length $name) = $name;
+ $result .= "\t$out => $value\n" ;
+ }
+ }
+ }
+
+ return $result ;
+}
+
+
+sub StripCommentsAndStrings
+{
+
+ # Strip C & C++ coments
+ # From the perlfaq
+ $_[0] =~
+
+ s{
+ /\* ## Start of /* ... */ comment
+ [^*]*\*+ ## Non-* followed by 1-or-more *'s
+ (
+ [^/*][^*]*\*+
+ )* ## 0-or-more things which don't start with /
+ ## but do end with '*'
+ / ## End of /* ... */ comment
+
+ | ## OR C++ Comment
+ // ## Start of C++ comment //
+ [^\n]* ## followed by 0-or-more non end of line characters
+
+ | ## OR various things which aren't comments:
+
+ (
+ " ## Start of " ... " string
+ (
+ \\. ## Escaped char
+ | ## OR
+ [^"\\] ## Non "\
+ )*
+ " ## End of " ... " string
+
+ | ## OR
+
+ ' ## Start of ' ... ' string
+ (
+ \\. ## Escaped char
+ | ## OR
+ [^'\\] ## Non '\
+ )*
+ ' ## End of ' ... ' string
+
+ | ## OR
+
+ . ## Anything other char
+ [^/"'\\]* ## Chars which doesn't start a comment, string or escape
+ )
+ }{$2}gxs;
+
+
+
+ # Remove double-quoted strings.
+ #$_[0] =~ s#"(\\.|[^"\\])*"##g;
+
+ # Remove single-quoted strings.
+ #$_[0] =~ s#'(\\.|[^'\\])*'##g;
+
+ # Remove leading whitespace.
+ $_[0] =~ s/\A\s+//m ;
+
+ # Remove trailing whitespace.
+ $_[0] =~ s/\s+\Z//m ;
+
+ # Replace all multiple whitespace by a single space.
+ #$_[0] =~ s/\s+/ /g ;
+}
+
+
+sub readFile
+{
+ my $filename = shift ;
+ open F, "<$filename" || die "Cannot open $filename: $!\n" ;
+ local $/ ;
+ my $x = <F> ;
+ close F ;
+ return $x ;
+}
+
+sub tuple
+{
+ my (@a) = split(/\./, $a) ;
+ my (@b) = split(/\./, $b) ;
+ if (@a != @b) {
+ my $diff = @a - @b ;
+ push @b, (0 x $diff) if $diff > 0 ;
+ push @a, (0 x -$diff) if $diff < 0 ;
+ }
+ foreach $A (@a) {
+ $B = shift @b ;
+ $A == $B or return $A <=> $B ;
+ }
+ return 0;
+}
+
+__END__
+
diff --git a/bdb/perl/BerkeleyDB/t/btree.t b/bdb/perl/BerkeleyDB/t/btree.t
new file mode 100644
index 00000000000..fd6ed8f1268
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/btree.t
@@ -0,0 +1,931 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..244\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+
+# Check for invalid parameters
+{
+ # Check for invalid parameters
+ my $db ;
+ eval ' $db = new BerkeleyDB::Btree -Stupid => 3 ; ' ;
+ ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' $db = new BerkeleyDB::Btree -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
+ ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
+
+ eval ' $db = new BerkeleyDB::Btree -Env => 2 ' ;
+ ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+
+ eval ' $db = new BerkeleyDB::Btree -Txn => "x" ' ;
+ ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
+
+ my $obj = bless [], "main" ;
+ eval ' $db = new BerkeleyDB::Btree -Env => $obj ' ;
+ ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+}
+
+# Now check the interface to Btree
+
+{
+ my $lex = new LexFile $Dfile ;
+
+ ok 6, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my $value ;
+ my $status ;
+ ok 7, $db->db_put("some key", "some value") == 0 ;
+ ok 8, $db->status() == 0 ;
+ ok 9, $db->db_get("some key", $value) == 0 ;
+ ok 10, $value eq "some value" ;
+ ok 11, $db->db_put("key", "value") == 0 ;
+ ok 12, $db->db_get("key", $value) == 0 ;
+ ok 13, $value eq "value" ;
+ ok 14, $db->db_del("some key") == 0 ;
+ ok 15, ($status = $db->db_get("some key", $value)) == DB_NOTFOUND ;
+ ok 16, $db->status() == DB_NOTFOUND ;
+ ok 17, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
+
+ ok 18, $db->db_sync() == 0 ;
+
+ # Check NOOVERWRITE will make put fail when attempting to overwrite
+ # an existing record.
+
+ ok 19, $db->db_put( 'key', 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
+ ok 20, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
+ ok 21, $db->status() == DB_KEYEXIST ;
+
+
+ # check that the value of the key has not been changed by the
+ # previous test
+ ok 22, $db->db_get("key", $value) == 0 ;
+ ok 23, $value eq "value" ;
+
+ # test DB_GET_BOTH
+ my ($k, $v) = ("key", "value") ;
+ ok 24, $db->db_get($k, $v, DB_GET_BOTH) == 0 ;
+
+ ($k, $v) = ("key", "fred") ;
+ ok 25, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+ ($k, $v) = ("another", "value") ;
+ ok 26, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+
+}
+
+{
+ # Check simple env works with a hash.
+ my $lex = new LexFile $Dfile ;
+
+ my $home = "./fred" ;
+ ok 27, my $lexD = new LexDir($home) ;
+
+ ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
+ -Home => $home ;
+ ok 29, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
+ -Env => $env,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my $value ;
+ ok 30, $db->db_put("some key", "some value") == 0 ;
+ ok 31, $db->db_get("some key", $value) == 0 ;
+ ok 32, $value eq "some value" ;
+ undef $db ;
+ undef $env ;
+}
+
+
+{
+ # cursors
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my ($k, $v) ;
+ ok 33, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my %data = (
+ "red" => 2,
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (($k, $v) = each %data) {
+ $ret += $db->db_put($k, $v) ;
+ }
+ ok 34, $ret == 0 ;
+
+ # create the cursor
+ ok 35, my $cursor = $db->db_cursor() ;
+
+ $k = $v = "" ;
+ my %copy = %data ;
+ my $extras = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ if ( $copy{$k} eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+ ok 36, $cursor->status() == DB_NOTFOUND ;
+ ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'};
+ ok 38, keys %copy == 0 ;
+ ok 39, $extras == 0 ;
+
+ # sequence backwards
+ %copy = %data ;
+ $extras = 0 ;
+ my $status ;
+ for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_PREV)) {
+ if ( $copy{$k} eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+ ok 40, $status == DB_NOTFOUND ;
+ ok 41, $status eq $DB_errors{'DB_NOTFOUND'};
+ ok 42, $cursor->status() == $status ;
+ ok 43, $cursor->status() eq $status ;
+ ok 44, keys %copy == 0 ;
+ ok 45, $extras == 0 ;
+
+ ($k, $v) = ("green", "house") ;
+ ok 46, $cursor->c_get($k, $v, DB_GET_BOTH) == 0 ;
+
+ ($k, $v) = ("green", "door") ;
+ ok 47, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+ ($k, $v) = ("black", "house") ;
+ ok 48, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+}
+
+{
+ # Tied Hash interface
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ ok 49, tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # check "each" with an empty database
+ my $count = 0 ;
+ while (my ($k, $v) = each %hash) {
+ ++ $count ;
+ }
+ ok 50, (tied %hash)->status() == DB_NOTFOUND ;
+ ok 51, $count == 0 ;
+
+ # Add a k/v pair
+ my $value ;
+ $hash{"some key"} = "some value";
+ ok 52, (tied %hash)->status() == 0 ;
+ ok 53, $hash{"some key"} eq "some value";
+ ok 54, defined $hash{"some key"} ;
+ ok 55, (tied %hash)->status() == 0 ;
+ ok 56, exists $hash{"some key"} ;
+ ok 57, !defined $hash{"jimmy"} ;
+ ok 58, (tied %hash)->status() == DB_NOTFOUND ;
+ ok 59, !exists $hash{"jimmy"} ;
+ ok 60, (tied %hash)->status() == DB_NOTFOUND ;
+
+ delete $hash{"some key"} ;
+ ok 61, (tied %hash)->status() == 0 ;
+ ok 62, ! defined $hash{"some key"} ;
+ ok 63, (tied %hash)->status() == DB_NOTFOUND ;
+ ok 64, ! exists $hash{"some key"} ;
+ ok 65, (tied %hash)->status() == DB_NOTFOUND ;
+
+ $hash{1} = 2 ;
+ $hash{10} = 20 ;
+ $hash{1000} = 2000 ;
+
+ my ($keys, $values) = (0,0);
+ $count = 0 ;
+ while (my ($k, $v) = each %hash) {
+ $keys += $k ;
+ $values += $v ;
+ ++ $count ;
+ }
+ ok 66, $count == 3 ;
+ ok 67, $keys == 1011 ;
+ ok 68, $values == 2022 ;
+
+ # now clear the hash
+ %hash = () ;
+ ok 69, keys %hash == 0 ;
+
+ untie %hash ;
+}
+
+{
+ # override default compare
+ my $lex = new LexFile $Dfile, $Dfile2, $Dfile3 ;
+ my $value ;
+ my (%h, %g, %k) ;
+ my @Keys = qw( 0123 12 -1234 9 987654321 def ) ;
+ ok 70, tie %h, "BerkeleyDB::Btree", -Filename => $Dfile,
+ -Compare => sub { $_[0] <=> $_[1] },
+ -Flags => DB_CREATE ;
+
+ ok 71, tie %g, 'BerkeleyDB::Btree', -Filename => $Dfile2,
+ -Compare => sub { $_[0] cmp $_[1] },
+ -Flags => DB_CREATE ;
+
+ ok 72, tie %k, 'BerkeleyDB::Btree', -Filename => $Dfile3,
+ -Compare => sub { length $_[0] <=> length $_[1] },
+ -Flags => DB_CREATE ;
+
+ my @srt_1 ;
+ { local $^W = 0 ;
+ @srt_1 = sort { $a <=> $b } @Keys ;
+ }
+ my @srt_2 = sort { $a cmp $b } @Keys ;
+ my @srt_3 = sort { length $a <=> length $b } @Keys ;
+
+ foreach (@Keys) {
+ local $^W = 0 ;
+ $h{$_} = 1 ;
+ $g{$_} = 1 ;
+ $k{$_} = 1 ;
+ }
+
+ sub ArrayCompare
+ {
+ my($a, $b) = @_ ;
+
+ return 0 if @$a != @$b ;
+
+ foreach (1 .. length @$a)
+ {
+ return 0 unless $$a[$_] eq $$b[$_] ;
+ }
+
+ 1 ;
+ }
+
+ ok 73, ArrayCompare (\@srt_1, [keys %h]);
+ ok 74, ArrayCompare (\@srt_2, [keys %g]);
+ ok 75, ArrayCompare (\@srt_3, [keys %k]);
+
+}
+
+{
+ # override default compare, with duplicates, don't sort values
+ my $lex = new LexFile $Dfile, $Dfile2, $Dfile3 ;
+ my $value ;
+ my (%h, %g, %k) ;
+ my @Keys = qw( 0123 9 12 -1234 9 987654321 def ) ;
+ my @Values = qw( 1 0 3 dd x abc 0 ) ;
+ ok 76, tie %h, "BerkeleyDB::Btree", -Filename => $Dfile,
+ -Compare => sub { $_[0] <=> $_[1] },
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ ok 77, tie %g, 'BerkeleyDB::Btree', -Filename => $Dfile2,
+ -Compare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ ok 78, tie %k, 'BerkeleyDB::Btree', -Filename => $Dfile3,
+ -Compare => sub { length $_[0] <=> length $_[1] },
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ my @srt_1 ;
+ { local $^W = 0 ;
+ @srt_1 = sort { $a <=> $b } @Keys ;
+ }
+ my @srt_2 = sort { $a cmp $b } @Keys ;
+ my @srt_3 = sort { length $a <=> length $b } @Keys ;
+
+ foreach (@Keys) {
+ local $^W = 0 ;
+ my $value = shift @Values ;
+ $h{$_} = $value ;
+ $g{$_} = $value ;
+ $k{$_} = $value ;
+ }
+
+ sub getValues
+ {
+ my $hash = shift ;
+ my $db = tied %$hash ;
+ my $cursor = $db->db_cursor() ;
+ my @values = () ;
+ my ($k, $v) = (0,0) ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ push @values, $v ;
+ }
+ return @values ;
+ }
+
+ ok 79, ArrayCompare (\@srt_1, [keys %h]);
+ ok 80, ArrayCompare (\@srt_2, [keys %g]);
+ ok 81, ArrayCompare (\@srt_3, [keys %k]);
+ ok 82, ArrayCompare ([qw(dd 0 0 x 3 1 abc)], [getValues \%h]);
+ ok 83, ArrayCompare ([qw(dd 1 0 3 x abc 0)], [getValues \%g]);
+ ok 84, ArrayCompare ([qw(0 x 3 0 1 dd abc)], [getValues \%k]);
+
+ # test DB_DUP_NEXT
+ ok 85, my $cur = (tied %g)->db_cursor() ;
+ my ($k, $v) = (9, "") ;
+ ok 86, $cur->c_get($k, $v, DB_SET) == 0 ;
+ ok 87, $k == 9 && $v == 0 ;
+ ok 88, $cur->c_get($k, $v, DB_NEXT_DUP) == 0 ;
+ ok 89, $k == 9 && $v eq "x" ;
+ ok 90, $cur->c_get($k, $v, DB_NEXT_DUP) == DB_NOTFOUND ;
+}
+
+{
+ # override default compare, with duplicates, sort values
+ my $lex = new LexFile $Dfile, $Dfile2;
+ my $value ;
+ my (%h, %g) ;
+ my @Keys = qw( 0123 9 12 -1234 9 987654321 9 def ) ;
+ my @Values = qw( 1 11 3 dd x abc 2 0 ) ;
+ ok 91, tie %h, "BerkeleyDB::Btree", -Filename => $Dfile,
+ -Compare => sub { $_[0] <=> $_[1] },
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ ok 92, tie %g, 'BerkeleyDB::Btree', -Filename => $Dfile2,
+ -Compare => sub { $_[0] cmp $_[1] },
+ -DupCompare => sub { $_[0] <=> $_[1] },
+ -Property => DB_DUP,
+
+
+
+ -Flags => DB_CREATE ;
+
+ my @srt_1 ;
+ { local $^W = 0 ;
+ @srt_1 = sort { $a <=> $b } @Keys ;
+ }
+ my @srt_2 = sort { $a cmp $b } @Keys ;
+
+ foreach (@Keys) {
+ local $^W = 0 ;
+ my $value = shift @Values ;
+ $h{$_} = $value ;
+ $g{$_} = $value ;
+ }
+
+ ok 93, ArrayCompare (\@srt_1, [keys %h]);
+ ok 94, ArrayCompare (\@srt_2, [keys %g]);
+ ok 95, ArrayCompare ([qw(dd 1 3 x 2 11 abc 0)], [getValues \%g]);
+ ok 96, ArrayCompare ([qw(dd 0 11 2 x 3 1 abc)], [getValues \%h]);
+
+}
+
+{
+ # get_dup etc
+ my $lex = new LexFile $Dfile;
+ my %hh ;
+
+ ok 97, my $YY = tie %hh, "BerkeleyDB::Btree", -Filename => $Dfile,
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ $hh{'Wall'} = 'Larry' ;
+ $hh{'Wall'} = 'Stone' ; # Note the duplicate key
+ $hh{'Wall'} = 'Brick' ; # Note the duplicate key
+ $hh{'Smith'} = 'John' ;
+ $hh{'mouse'} = 'mickey' ;
+
+ # first work in scalar context
+ ok 98, scalar $YY->get_dup('Unknown') == 0 ;
+ ok 99, scalar $YY->get_dup('Smith') == 1 ;
+ ok 100, scalar $YY->get_dup('Wall') == 3 ;
+
+ # now in list context
+ my @unknown = $YY->get_dup('Unknown') ;
+ ok 101, "@unknown" eq "" ;
+
+ my @smith = $YY->get_dup('Smith') ;
+ ok 102, "@smith" eq "John" ;
+
+ {
+ my @wall = $YY->get_dup('Wall') ;
+ my %wall ;
+ @wall{@wall} = @wall ;
+ ok 103, (@wall == 3 && $wall{'Larry'} && $wall{'Stone'} && $wall{'Brick'});
+ }
+
+ # hash
+ my %unknown = $YY->get_dup('Unknown', 1) ;
+ ok 104, keys %unknown == 0 ;
+
+ my %smith = $YY->get_dup('Smith', 1) ;
+ ok 105, keys %smith == 1 && $smith{'John'} ;
+
+ my %wall = $YY->get_dup('Wall', 1) ;
+ ok 106, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1
+ && $wall{'Brick'} == 1 ;
+
+ undef $YY ;
+ untie %hh ;
+
+}
+
+{
+ # in-memory file
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $fd ;
+ my $value ;
+ ok 107, my $db = tie %hash, 'BerkeleyDB::Btree' ;
+
+ ok 108, $db->db_put("some key", "some value") == 0 ;
+ ok 109, $db->db_get("some key", $value) == 0 ;
+ ok 110, $value eq "some value" ;
+
+}
+
+{
+ # partial
+ # check works via API
+
+ my $lex = new LexFile $Dfile ;
+ my $value ;
+ ok 111, my $db = new BerkeleyDB::Btree, -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db->db_put($k, $v) ;
+ }
+ ok 112, $ret == 0 ;
+
+
+ # do a partial get
+ my ($pon, $off, $len) = $db->partial_set(0,2) ;
+ ok 113, ! $pon && $off == 0 && $len == 0 ;
+ ok 114, $db->db_get("red", $value) == 0 && $value eq "bo" ;
+ ok 115, $db->db_get("green", $value) == 0 && $value eq "ho" ;
+ ok 116, $db->db_get("blue", $value) == 0 && $value eq "se" ;
+
+ # do a partial get, off end of data
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 117, $pon ;
+ ok 118, $off == 0 ;
+ ok 119, $len == 2 ;
+ ok 120, $db->db_get("red", $value) == 0 && $value eq "t" ;
+ ok 121, $db->db_get("green", $value) == 0 && $value eq "se" ;
+ ok 122, $db->db_get("blue", $value) == 0 && $value eq "" ;
+
+ # switch of partial mode
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 123, $pon ;
+ ok 124, $off == 3 ;
+ ok 125, $len == 2 ;
+ ok 126, $db->db_get("red", $value) == 0 && $value eq "boat" ;
+ ok 127, $db->db_get("green", $value) == 0 && $value eq "house" ;
+ ok 128, $db->db_get("blue", $value) == 0 && $value eq "sea" ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ ok 129, $db->db_put("red", "") == 0 ;
+ ok 130, $db->db_put("green", "AB") == 0 ;
+ ok 131, $db->db_put("blue", "XYZ") == 0 ;
+ ok 132, $db->db_put("new", "KLM") == 0 ;
+
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 133, $pon ;
+ ok 134, $off == 0 ;
+ ok 135, $len == 2 ;
+ ok 136, $db->db_get("red", $value) == 0 && $value eq "at" ;
+ ok 137, $db->db_get("green", $value) == 0 && $value eq "ABuse" ;
+ ok 138, $db->db_get("blue", $value) == 0 && $value eq "XYZa" ;
+ ok 139, $db->db_get("new", $value) == 0 && $value eq "KLM" ;
+
+ # now partial put
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 140, ! $pon ;
+ ok 141, $off == 0 ;
+ ok 142, $len == 0 ;
+ ok 143, $db->db_put("red", "PPP") == 0 ;
+ ok 144, $db->db_put("green", "Q") == 0 ;
+ ok 145, $db->db_put("blue", "XYZ") == 0 ;
+ ok 146, $db->db_put("new", "TU") == 0 ;
+
+ $db->partial_clear() ;
+ ok 147, $db->db_get("red", $value) == 0 && $value eq "at\0PPP" ;
+ ok 148, $db->db_get("green", $value) == 0 && $value eq "ABuQ" ;
+ ok 149, $db->db_get("blue", $value) == 0 && $value eq "XYZXYZ" ;
+ ok 150, $db->db_get("new", $value) == 0 && $value eq "KLMTU" ;
+}
+
+{
+ # partial
+ # check works via tied hash
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+ ok 151, my $db = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ while (my ($k, $v) = each %data) {
+ $hash{$k} = $v ;
+ }
+
+
+ # do a partial get
+ $db->partial_set(0,2) ;
+ ok 152, $hash{"red"} eq "bo" ;
+ ok 153, $hash{"green"} eq "ho" ;
+ ok 154, $hash{"blue"} eq "se" ;
+
+ # do a partial get, off end of data
+ $db->partial_set(3,2) ;
+ ok 155, $hash{"red"} eq "t" ;
+ ok 156, $hash{"green"} eq "se" ;
+ ok 157, $hash{"blue"} eq "" ;
+
+ # switch of partial mode
+ $db->partial_clear() ;
+ ok 158, $hash{"red"} eq "boat" ;
+ ok 159, $hash{"green"} eq "house" ;
+ ok 160, $hash{"blue"} eq "sea" ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ ok 161, $hash{"red"} = "" ;
+ ok 162, $hash{"green"} = "AB" ;
+ ok 163, $hash{"blue"} = "XYZ" ;
+ ok 164, $hash{"new"} = "KLM" ;
+
+ $db->partial_clear() ;
+ ok 165, $hash{"red"} eq "at" ;
+ ok 166, $hash{"green"} eq "ABuse" ;
+ ok 167, $hash{"blue"} eq "XYZa" ;
+ ok 168, $hash{"new"} eq "KLM" ;
+
+ # now partial put
+ $db->partial_set(3,2) ;
+ ok 169, $hash{"red"} = "PPP" ;
+ ok 170, $hash{"green"} = "Q" ;
+ ok 171, $hash{"blue"} = "XYZ" ;
+ ok 172, $hash{"new"} = "TU" ;
+
+ $db->partial_clear() ;
+ ok 173, $hash{"red"} eq "at\0PPP" ;
+ ok 174, $hash{"green"} eq "ABuQ" ;
+ ok 175, $hash{"blue"} eq "XYZXYZ" ;
+ ok 176, $hash{"new"} eq "KLMTU" ;
+}
+
+{
+ # transaction
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 177, my $lexD = new LexDir($home) ;
+ ok 178, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 179, my $txn = $env->txn_begin() ;
+ ok 180, my $db1 = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ ok 181, (my $Z = $txn->txn_commit()) == 0 ;
+ ok 182, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 183, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 184, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 185, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ #ok 151, $txn->txn_abort() == 0 ;
+ ok 186, ($Z = $txn->txn_abort()) == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 187, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 188, $count == 0 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $env ;
+ untie %hash ;
+}
+
+{
+ # DB_DUP
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ ok 189, my $db = tie %hash, 'BerkeleyDB::Btree', -Filename => $Dfile,
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ $hash{'Wall'} = 'Larry' ;
+ $hash{'Wall'} = 'Stone' ;
+ $hash{'Smith'} = 'John' ;
+ $hash{'Wall'} = 'Brick' ;
+ $hash{'Wall'} = 'Brick' ;
+ $hash{'mouse'} = 'mickey' ;
+
+ ok 190, keys %hash == 6 ;
+
+ # create a cursor
+ ok 191, my $cursor = $db->db_cursor() ;
+
+ my $key = "Wall" ;
+ my $value ;
+ ok 192, $cursor->c_get($key, $value, DB_SET) == 0 ;
+ ok 193, $key eq "Wall" && $value eq "Larry" ;
+ ok 194, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 195, $key eq "Wall" && $value eq "Stone" ;
+ ok 196, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 197, $key eq "Wall" && $value eq "Brick" ;
+ ok 198, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 199, $key eq "Wall" && $value eq "Brick" ;
+
+ #my $ref = $db->db_stat() ;
+ #ok 200, ($ref->{bt_flags} | DB_DUP) == DB_DUP ;
+#print "bt_flags " . $ref->{bt_flags} . " DB_DUP " . DB_DUP ."\n";
+
+ undef $db ;
+ undef $cursor ;
+ untie %hash ;
+
+}
+
+{
+ # db_stat
+
+ my $lex = new LexFile $Dfile ;
+ my $recs = ($BerkeleyDB::db_version >= 3.1 ? "bt_ndata" : "bt_nrecs") ;
+ my %hash ;
+ my ($k, $v) ;
+ ok 200, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
+ -Flags => DB_CREATE,
+ -Minkey =>3 ,
+ -Pagesize => 2 **12
+ ;
+
+ my $ref = $db->db_stat() ;
+ ok 201, $ref->{$recs} == 0;
+ ok 202, $ref->{'bt_minkey'} == 3;
+ ok 203, $ref->{'bt_pagesize'} == 2 ** 12;
+
+ # create some data
+ my %data = (
+ "red" => 2,
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (($k, $v) = each %data) {
+ $ret += $db->db_put($k, $v) ;
+ }
+ ok 204, $ret == 0 ;
+
+ $ref = $db->db_stat() ;
+ ok 205, $ref->{$recs} == 3;
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use strict ;
+ use vars qw( @ISA @EXPORT) ;
+
+ require Exporter ;
+ use BerkeleyDB;
+ @ISA=qw(BerkeleyDB::Btree);
+ @EXPORT = @BerkeleyDB::EXPORT ;
+
+ sub db_put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::db_put($key, $value * 3) ;
+ }
+
+ sub db_get {
+ my $self = shift ;
+ $self->SUPER::db_get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE ;
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok 206, $@ eq "" ;
+ my %h ;
+ my $X ;
+ eval '
+ $X = tie(%h, "SubDB", -Filename => "dbbtree.tmp",
+ -Flags => DB_CREATE,
+ -Mode => 0640 );
+ ' ;
+
+ main::ok 207, $@ eq "" && $X ;
+
+ my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
+ main::ok 208, $@ eq "" ;
+ main::ok 209, $ret == 7 ;
+
+ my $value = 0;
+ $ret = eval '$X->db_put("joe", 4) ; $X->db_get("joe", $value) ; return $value' ;
+ main::ok 210, $@ eq "" ;
+ main::ok 211, $ret == 10 ;
+
+ $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
+ main::ok 212, $@ eq "" ;
+ main::ok 213, $ret == 1 ;
+
+ $ret = eval '$X->A_new_method("joe") ' ;
+ main::ok 214, $@ eq "" ;
+ main::ok 215, $ret eq "[[10]]" ;
+
+ undef $X;
+ untie %h;
+ unlink "SubDB.pm", "dbbtree.tmp" ;
+
+}
+
+{
+ # DB_RECNUM, DB_SET_RECNO & DB_GET_RECNO
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my ($k, $v) = ("", "");
+ ok 216, my $db = new BerkeleyDB::Btree
+ -Filename => $Dfile,
+ -Flags => DB_CREATE,
+ -Property => DB_RECNUM ;
+
+
+ # create some data
+ my @data = (
+ "A zero",
+ "B one",
+ "C two",
+ "D three",
+ "E four"
+ ) ;
+
+ my $ix = 0 ;
+ my $ret = 0 ;
+ foreach (@data) {
+ $ret += $db->db_put($_, $ix) ;
+ ++ $ix ;
+ }
+ ok 217, $ret == 0 ;
+
+ # db_get & DB_SET_RECNO
+ $k = 1 ;
+ ok 218, $db->db_get($k, $v, DB_SET_RECNO) == 0;
+ ok 219, $k eq "B one" && $v == 1 ;
+
+ $k = 3 ;
+ ok 220, $db->db_get($k, $v, DB_SET_RECNO) == 0;
+ ok 221, $k eq "D three" && $v == 3 ;
+
+ $k = 4 ;
+ ok 222, $db->db_get($k, $v, DB_SET_RECNO) == 0;
+ ok 223, $k eq "E four" && $v == 4 ;
+
+ $k = 0 ;
+ ok 224, $db->db_get($k, $v, DB_SET_RECNO) == 0;
+ ok 225, $k eq "A zero" && $v == 0 ;
+
+ # cursor & DB_SET_RECNO
+
+ # create the cursor
+ ok 226, my $cursor = $db->db_cursor() ;
+
+ $k = 2 ;
+ ok 227, $db->db_get($k, $v, DB_SET_RECNO) == 0;
+ ok 228, $k eq "C two" && $v == 2 ;
+
+ $k = 0 ;
+ ok 229, $cursor->c_get($k, $v, DB_SET_RECNO) == 0;
+ ok 230, $k eq "A zero" && $v == 0 ;
+
+ $k = 3 ;
+ ok 231, $db->db_get($k, $v, DB_SET_RECNO) == 0;
+ ok 232, $k eq "D three" && $v == 3 ;
+
+ # cursor & DB_GET_RECNO
+ ok 233, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
+ ok 234, $k eq "A zero" && $v == 0 ;
+ ok 235, $cursor->c_get($k, $v, DB_GET_RECNO) == 0;
+ ok 236, $v == 0 ;
+
+ ok 237, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 238, $k eq "B one" && $v == 1 ;
+ ok 239, $cursor->c_get($k, $v, DB_GET_RECNO) == 0;
+ ok 240, $v == 1 ;
+
+ ok 241, $cursor->c_get($k, $v, DB_LAST) == 0 ;
+ ok 242, $k eq "E four" && $v == 4 ;
+ ok 243, $cursor->c_get($k, $v, DB_GET_RECNO) == 0;
+ ok 244, $v == 4 ;
+
+}
+
diff --git a/bdb/perl/BerkeleyDB/t/destroy.t b/bdb/perl/BerkeleyDB/t/destroy.t
new file mode 100644
index 00000000000..7457d36c583
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/destroy.t
@@ -0,0 +1,105 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..15\n";
+
+my $Dfile = "dbhash.tmp";
+my $home = "./fred" ;
+
+umask(0);
+
+{
+ # let object destruction kill everything
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ ok 1, my $lexD = new LexDir($home) ;
+ ok 2, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 3, my $txn = $env->txn_begin() ;
+ ok 4, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ ok 5, $txn->txn_commit() == 0 ;
+ ok 6, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 7, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 8, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 9, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ ok 10, $txn->txn_abort() == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 11, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 12, $count == 0 ;
+
+ #undef $txn ;
+ #undef $cursor ;
+ #undef $db1 ;
+ #undef $env ;
+ #untie %hash ;
+
+}
+
+{
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $cursor ;
+ my ($k, $v) = ("", "") ;
+ ok 13, my $db1 = tie %hash, 'BerkeleyDB::Hash',
+ -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+ my $count = 0 ;
+ # sequence forwards
+ ok 14, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 15, $count == 0 ;
+}
+
+
diff --git a/bdb/perl/BerkeleyDB/t/env.t b/bdb/perl/BerkeleyDB/t/env.t
new file mode 100644
index 00000000000..3905abfae43
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/env.t
@@ -0,0 +1,217 @@
+#!./perl -w
+
+# ID: 1.2, 7/17/97
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..47\n";
+
+my $Dfile = "dbhash.tmp";
+
+umask(0);
+
+{
+ # db version stuff
+ my ($major, $minor, $patch) = (0, 0, 0) ;
+
+ ok 1, my $VER = BerkeleyDB::DB_VERSION_STRING ;
+ ok 2, my $ver = BerkeleyDB::db_version($major, $minor, $patch) ;
+ ok 3, $VER eq $ver ;
+ ok 4, $major > 1 ;
+ ok 5, defined $minor ;
+ ok 6, defined $patch ;
+}
+
+{
+ # Check for invalid parameters
+ my $env ;
+ eval ' $env = new BerkeleyDB::Env( -Stupid => 3) ; ' ;
+ ok 7, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' $env = new BerkeleyDB::Env( -Bad => 2, -Home => "/tmp", -Stupid => 3) ; ' ;
+ ok 8, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
+
+ eval ' $env = new BerkeleyDB::Env (-Config => {"fred" => " "} ) ; ' ;
+ ok 9, !$env ;
+ ok 10, $BerkeleyDB::Error =~ /^illegal name-value pair/ ;
+}
+
+{
+ # create a very simple environment
+ my $home = "./fred" ;
+ ok 11, my $lexD = new LexDir($home) ;
+ chdir "./fred" ;
+ ok 12, my $env = new BerkeleyDB::Env -Flags => DB_CREATE ;
+ chdir ".." ;
+ undef $env ;
+}
+
+{
+ # create an environment with a Home
+ my $home = "./fred" ;
+ ok 13, my $lexD = new LexDir($home) ;
+ ok 14, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE ;
+
+ undef $env ;
+}
+
+{
+ # make new fail.
+ my $home = "./not_there" ;
+ rmtree $home ;
+ ok 15, ! -d $home ;
+ my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_INIT_LOCK ;
+ ok 16, ! $env ;
+ ok 17, $! != 0 || $^E != 0 ;
+
+ rmtree $home ;
+}
+
+{
+ # Config
+ use Cwd ;
+ my $cwd = cwd() ;
+ my $home = "$cwd/fred" ;
+ my $data_dir = "$home/data_dir" ;
+ my $log_dir = "$home/log_dir" ;
+ my $data_file = "data.db" ;
+ ok 18, my $lexD = new LexDir($home) ;
+ ok 19, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
+ ok 20, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
+ my $env = new BerkeleyDB::Env -Home => $home,
+ -Config => { DB_DATA_DIR => $data_dir,
+ DB_LOG_DIR => $log_dir
+ },
+ -Flags => DB_CREATE|DB_INIT_TXN|DB_INIT_LOG|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 21, $env ;
+
+ ok 22, my $txn = $env->txn_begin() ;
+
+ my %hash ;
+ ok 23, tie %hash, 'BerkeleyDB::Hash', -Filename => $data_file,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ $hash{"abc"} = 123 ;
+ $hash{"def"} = 456 ;
+
+ $txn->txn_commit() ;
+
+ untie %hash ;
+
+ undef $txn ;
+ undef $env ;
+}
+
+{
+ # -ErrFile with a filename
+ my $errfile = "./errfile" ;
+ my $home = "./fred" ;
+ ok 24, my $lexD = new LexDir($home) ;
+ my $lex = new LexFile $errfile ;
+ ok 25, my $env = new BerkeleyDB::Env( -ErrFile => $errfile,
+ -Flags => DB_CREATE,
+ -Home => $home) ;
+ my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Env => $env,
+ -Flags => -1;
+ ok 26, !$db ;
+
+ ok 27, $BerkeleyDB::Error =~ /^illegal flag specified to (db_open|DB->open)/;
+ ok 28, -e $errfile ;
+ my $contents = docat($errfile) ;
+ chomp $contents ;
+ ok 29, $BerkeleyDB::Error eq $contents ;
+
+ undef $env ;
+}
+
+{
+ # -ErrFile with a filehandle/reference -- should fail
+ my $home = "./fred" ;
+ ok 30, my $lexD = new LexDir($home) ;
+ eval { my $env = new BerkeleyDB::Env( -ErrFile => [],
+ -Flags => DB_CREATE,
+ -Home => $home) ; };
+ ok 31, $@ =~ /ErrFile parameter must be a file name/;
+}
+
+{
+ # -ErrPrefix
+ use IO ;
+ my $home = "./fred" ;
+ ok 32, my $lexD = new LexDir($home) ;
+ my $errfile = "./errfile" ;
+ my $lex = new LexFile $errfile ;
+ ok 33, my $env = new BerkeleyDB::Env( -ErrFile => $errfile,
+ -ErrPrefix => "PREFIX",
+ -Flags => DB_CREATE,
+ -Home => $home) ;
+ my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Env => $env,
+ -Flags => -1;
+ ok 34, !$db ;
+
+ ok 35, $BerkeleyDB::Error =~ /^PREFIX: illegal flag specified to (db_open|DB->open)/;
+ ok 36, -e $errfile ;
+ my $contents = docat($errfile) ;
+ chomp $contents ;
+ ok 37, $BerkeleyDB::Error eq $contents ;
+
+ # change the prefix on the fly
+ my $old = $env->errPrefix("NEW ONE") ;
+ ok 38, $old eq "PREFIX" ;
+
+ $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Env => $env,
+ -Flags => -1;
+ ok 39, !$db ;
+ ok 40, $BerkeleyDB::Error =~ /^NEW ONE: illegal flag specified to (db_open|DB->open)/;
+ $contents = docat($errfile) ;
+ chomp $contents ;
+ ok 41, $contents =~ /$BerkeleyDB::Error$/ ;
+ undef $env ;
+}
+
+{
+ # test db_appexit
+ use Cwd ;
+ my $cwd = cwd() ;
+ my $home = "$cwd/fred" ;
+ my $data_dir = "$home/data_dir" ;
+ my $log_dir = "$home/log_dir" ;
+ my $data_file = "data.db" ;
+ ok 42, my $lexD = new LexDir($home);
+ ok 43, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
+ ok 44, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
+ my $env = new BerkeleyDB::Env -Home => $home,
+ -Config => { DB_DATA_DIR => $data_dir,
+ DB_LOG_DIR => $log_dir
+ },
+ -Flags => DB_CREATE|DB_INIT_TXN|DB_INIT_LOG|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 45, $env ;
+
+ ok 46, my $txn_mgr = $env->TxnMgr() ;
+
+ ok 47, $env->db_appexit() == 0 ;
+
+}
+
+# test -Verbose
+# test -Flags
+# db_value_set
diff --git a/bdb/perl/BerkeleyDB/t/examples.t b/bdb/perl/BerkeleyDB/t/examples.t
new file mode 100644
index 00000000000..69b7f8ff8c5
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/examples.t
@@ -0,0 +1,401 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util;
+
+print "1..7\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+my $redirect = "xyzt" ;
+
+
+{
+my $x = $BerkeleyDB::Error;
+my $redirect = "xyzt" ;
+ {
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+ use vars qw( %h $k $v ) ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $h{"apple"} = "red" ;
+ $h{"orange"} = "orange" ;
+ $h{"banana"} = "yellow" ;
+ $h{"tomato"} = "red" ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $h{"banana"} ;
+
+ # Delete a key/value pair.
+ delete $h{"apple"} ;
+
+ # print the contents of the file
+ while (($k, $v) = each %h)
+ { print "$k -> $v\n" }
+
+ untie %h ;
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(1, docat_del($redirect) eq <<'EOM') ;
+Banana Exists
+
+orange -> orange
+tomato -> red
+banana -> yellow
+EOM
+
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("apple", "red") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("banana", "yellow") ;
+ $db->db_put("tomato", "red") ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;
+
+ # Delete a key/value pair.
+ $db->db_del("apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(2, docat_del($redirect) eq <<'EOM') ;
+Banana Exists
+
+orange -> orange
+tomato -> red
+banana -> yellow
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "tree" ;
+ unlink $filename ;
+ my %h ;
+ tie %h, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(3, docat_del($redirect) eq <<'EOM') ;
+Smith
+Wall
+mouse
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "tree" ;
+ unlink $filename ;
+ my %h ;
+ tie %h, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Compare => sub { lc $_[0] cmp lc $_[1] }
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(4, docat_del($redirect) eq <<'EOM') ;
+mouse
+Smith
+Wall
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my %hash ;
+ my $filename = "filt.db" ;
+ unlink $filename ;
+
+ my $db = tie %hash, 'BerkeleyDB::Hash',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ # Install DBM Filters
+ $db->filter_fetch_key ( sub { s/\0$// } ) ;
+ $db->filter_store_key ( sub { $_ .= "\0" } ) ;
+ $db->filter_fetch_value( sub { s/\0$// } ) ;
+ $db->filter_store_value( sub { $_ .= "\0" } ) ;
+
+ $hash{"abc"} = "def" ;
+ my $a = $hash{"ABC"} ;
+ # ...
+ undef $db ;
+ untie %hash ;
+ $db = tie %hash, 'BerkeleyDB::Hash',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+ while (($k, $v) = each %hash)
+ { print "$k -> $v\n" }
+ undef $db ;
+ untie %hash ;
+
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(5, docat_del($redirect) eq <<"EOM") ;
+abc\x00 -> def\x00
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+ my %hash ;
+ my $filename = "filt.db" ;
+ unlink $filename ;
+
+
+ my $db = tie %hash, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
+ $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
+ $hash{123} = "def" ;
+ # ...
+ undef $db ;
+ untie %hash ;
+ $db = tie %hash, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot Open $filename: $!\n" ;
+ while (($k, $v) = each %hash)
+ { print "$k -> $v\n" }
+ undef $db ;
+ untie %hash ;
+
+ unlink $filename ;
+ }
+
+ my $val = pack("i", 123) ;
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(6, docat_del($redirect) eq <<"EOM") ;
+$val -> def
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ if ($FA) {
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ tie @h, 'BerkeleyDB::Recno',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_RENUMBER
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ push @h, "green", "black" ;
+
+ my $elements = scalar @h ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = pop @h ;
+ print "popped $last\n" ;
+
+ unshift @h, "white" ;
+ my $first = shift @h ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ untie @h ;
+ unlink $filename ;
+ } else {
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ my $db = tie @h, 'BerkeleyDB::Recno',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_RENUMBER
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ $db->push("green", "black") ;
+
+ my $elements = $db->length() ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = $db->pop ;
+ print "popped $last\n" ;
+
+ $db->unshift("white") ;
+ my $first = $db->shift ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ undef $db ;
+ untie @h ;
+ unlink $filename ;
+ }
+
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(7, docat_del($redirect) eq <<"EOM") ;
+The array contains 5 entries
+popped black
+shifted white
+Element 1 Exists with value blue
+EOM
+
+}
+
diff --git a/bdb/perl/BerkeleyDB/t/examples.t.T b/bdb/perl/BerkeleyDB/t/examples.t.T
new file mode 100644
index 00000000000..fe9bdf76b06
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/examples.t.T
@@ -0,0 +1,415 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util;
+
+print "1..7\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+my $redirect = "xyzt" ;
+
+
+{
+my $x = $BerkeleyDB::Error;
+my $redirect = "xyzt" ;
+ {
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN simpleHash
+ use strict ;
+ use BerkeleyDB ;
+ use vars qw( %h $k $v ) ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ tie %h, "BerkeleyDB::Hash",
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $h{"apple"} = "red" ;
+ $h{"orange"} = "orange" ;
+ $h{"banana"} = "yellow" ;
+ $h{"tomato"} = "red" ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $h{"banana"} ;
+
+ # Delete a key/value pair.
+ delete $h{"apple"} ;
+
+ # print the contents of the file
+ while (($k, $v) = each %h)
+ { print "$k -> $v\n" }
+
+ untie %h ;
+## END simpleHash
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(1, docat_del($redirect) eq <<'EOM') ;
+Banana Exists
+
+orange -> orange
+tomato -> red
+banana -> yellow
+EOM
+
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN simpleHash2
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("apple", "red") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("banana", "yellow") ;
+ $db->db_put("tomato", "red") ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;
+
+ # Delete a key/value pair.
+ $db->db_del("apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+## END simpleHash2
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(2, docat_del($redirect) eq <<'EOM') ;
+Banana Exists
+
+orange -> orange
+tomato -> red
+banana -> yellow
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN btreeSimple
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "tree" ;
+ unlink $filename ;
+ my %h ;
+ tie %h, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+## END btreeSimple
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(3, docat_del($redirect) eq <<'EOM') ;
+Smith
+Wall
+mouse
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN btreeSortOrder
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "tree" ;
+ unlink $filename ;
+ my %h ;
+ tie %h, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Compare => sub { lc $_[0] cmp lc $_[1] }
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+## END btreeSortOrder
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(4, docat_del($redirect) eq <<'EOM') ;
+mouse
+Smith
+Wall
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN nullFilter
+ use strict ;
+ use BerkeleyDB ;
+
+ my %hash ;
+ my $filename = "filt.db" ;
+ unlink $filename ;
+
+ my $db = tie %hash, 'BerkeleyDB::Hash',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ # Install DBM Filters
+ $db->filter_fetch_key ( sub { s/\0$// } ) ;
+ $db->filter_store_key ( sub { $_ .= "\0" } ) ;
+ $db->filter_fetch_value( sub { s/\0$// } ) ;
+ $db->filter_store_value( sub { $_ .= "\0" } ) ;
+
+ $hash{"abc"} = "def" ;
+ my $a = $hash{"ABC"} ;
+ # ...
+ undef $db ;
+ untie %hash ;
+## END nullFilter
+ $db = tie %hash, 'BerkeleyDB::Hash',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+ while (($k, $v) = each %hash)
+ { print "$k -> $v\n" }
+ undef $db ;
+ untie %hash ;
+
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(5, docat_del($redirect) eq <<"EOM") ;
+abc\x00 -> def\x00
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN intFilter
+ use strict ;
+ use BerkeleyDB ;
+ my %hash ;
+ my $filename = "filt.db" ;
+ unlink $filename ;
+
+
+ my $db = tie %hash, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot open $filename: $!\n" ;
+
+ $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
+ $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
+ $hash{123} = "def" ;
+ # ...
+ undef $db ;
+ untie %hash ;
+## END intFilter
+ $db = tie %hash, 'BerkeleyDB::Btree',
+ -Filename => $filename,
+ -Flags => DB_CREATE
+ or die "Cannot Open $filename: $!\n" ;
+ while (($k, $v) = each %hash)
+ { print "$k -> $v\n" }
+ undef $db ;
+ untie %hash ;
+
+ unlink $filename ;
+ }
+
+ my $val = pack("i", 123) ;
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(6, docat_del($redirect) eq <<"EOM") ;
+$val -> def
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ if ($FA) {
+## BEGIN simpleRecno
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ tie @h, 'BerkeleyDB::Recno',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_RENUMBER
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ push @h, "green", "black" ;
+
+ my $elements = scalar @h ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = pop @h ;
+ print "popped $last\n" ;
+
+ unshift @h, "white" ;
+ my $first = shift @h ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ untie @h ;
+## END simpleRecno
+ unlink $filename ;
+ } else {
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ my $db = tie @h, 'BerkeleyDB::Recno',
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_RENUMBER
+ or die "Cannot open $filename: $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ $db->push("green", "black") ;
+
+ my $elements = $db->length() ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = $db->pop ;
+ print "popped $last\n" ;
+
+ $db->unshift("white") ;
+ my $first = $db->shift ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ undef $db ;
+ untie @h ;
+ unlink $filename ;
+ }
+
+ }
+
+ #print "[" . docat($redirect) . "]\n" ;
+ ok(7, docat_del($redirect) eq <<"EOM") ;
+The array contains 5 entries
+popped black
+shifted white
+Element 1 Exists with value blue
+EOM
+
+}
+
diff --git a/bdb/perl/BerkeleyDB/t/examples3.t b/bdb/perl/BerkeleyDB/t/examples3.t
new file mode 100644
index 00000000000..22e94b770e1
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/examples3.t
@@ -0,0 +1,132 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util;
+
+BEGIN
+{
+ if ($BerkeleyDB::db_version < 3) {
+ print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
+ exit 0 ;
+ }
+}
+
+
+print "1..2\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+my $redirect = "xyzt" ;
+
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_DUP
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("red", "apple") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("green", "banana") ;
+ $db->db_put("yellow", "banana") ;
+ $db->db_put("red", "tomato") ;
+ $db->db_put("green", "apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(1, docat_del($redirect) eq <<'EOM') ;
+orange -> orange
+yellow -> banana
+red -> apple
+red -> tomato
+green -> banana
+green -> apple
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_DUP | DB_DUPSORT
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("red", "apple") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("green", "banana") ;
+ $db->db_put("yellow", "banana") ;
+ $db->db_put("red", "tomato") ;
+ $db->db_put("green", "apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(2, docat_del($redirect) eq <<'EOM') ;
+orange -> orange
+yellow -> banana
+red -> apple
+red -> tomato
+green -> apple
+green -> banana
+EOM
+
+}
+
+
diff --git a/bdb/perl/BerkeleyDB/t/examples3.t.T b/bdb/perl/BerkeleyDB/t/examples3.t.T
new file mode 100644
index 00000000000..5eeaa14d00c
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/examples3.t.T
@@ -0,0 +1,136 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util;
+
+BEGIN
+{
+ if ($BerkeleyDB::db_version < 3) {
+ print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
+ exit 0 ;
+ }
+}
+
+
+print "1..2\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+my $redirect = "xyzt" ;
+
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN dupHash
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_DUP
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("red", "apple") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("green", "banana") ;
+ $db->db_put("yellow", "banana") ;
+ $db->db_put("red", "tomato") ;
+ $db->db_put("green", "apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+## END dupHash
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(1, docat_del($redirect) eq <<'EOM') ;
+orange -> orange
+yellow -> banana
+red -> apple
+red -> tomato
+green -> banana
+green -> apple
+EOM
+
+}
+
+{
+my $redirect = "xyzt" ;
+ {
+
+ my $redirectObj = new Redirect $redirect ;
+
+## BEGIN dupSortHash
+ use strict ;
+ use BerkeleyDB ;
+
+ my $filename = "fruit" ;
+ unlink $filename ;
+ my $db = new BerkeleyDB::Hash
+ -Filename => $filename,
+ -Flags => DB_CREATE,
+ -Property => DB_DUP | DB_DUPSORT
+ or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;
+
+ # Add a few key/value pairs to the file
+ $db->db_put("red", "apple") ;
+ $db->db_put("orange", "orange") ;
+ $db->db_put("green", "banana") ;
+ $db->db_put("yellow", "banana") ;
+ $db->db_put("red", "tomato") ;
+ $db->db_put("green", "apple") ;
+
+ # print the contents of the file
+ my ($k, $v) = ("", "") ;
+ my $cursor = $db->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { print "$k -> $v\n" }
+
+ undef $cursor ;
+ undef $db ;
+## END dupSortHash
+ unlink $filename ;
+ }
+
+ #print "[" . docat($redirect) . "]" ;
+ ok(2, docat_del($redirect) eq <<'EOM') ;
+orange -> orange
+yellow -> banana
+red -> apple
+red -> tomato
+green -> apple
+green -> banana
+EOM
+
+}
+
+
diff --git a/bdb/perl/BerkeleyDB/t/filter.t b/bdb/perl/BerkeleyDB/t/filter.t
new file mode 100644
index 00000000000..47a7c107acf
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/filter.t
@@ -0,0 +1,217 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..46\n";
+
+my $Dfile = "dbhash.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok 1, $db = tie %h, 'BerkeleyDB::Hash',
+ -Filename => $Dfile,
+ -Flags => DB_CREATE;
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok 2, checkOutput( "", "fred", "", "joe") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 3, $h{"fred"} eq "joe";
+ # fk sk fv sv
+ ok 4, checkOutput( "", "fred", "joe", "") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 5, $db->FIRSTKEY() eq "fred" ;
+ # fk sk fv sv
+ ok 6, checkOutput( "fred", "", "", "") ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok 7, checkOutput( "", "fred", "", "Jxe") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 8, $h{"Fred"} eq "[Jxe]";
+ # fk sk fv sv
+ ok 9, checkOutput( "", "fred", "[Jxe]", "") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 10, $db->FIRSTKEY() eq "FRED" ;
+ # fk sk fv sv
+ ok 11, checkOutput( "FRED", "", "", "") ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok 12, checkOutput( "", "fred", "", "joe") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 13, $h{"fred"} eq "joe";
+ ok 14, checkOutput( "", "fred", "joe", "") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 15, $db->FIRSTKEY() eq "fred" ;
+ ok 16, checkOutput( "fred", "", "", "") ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok 17, checkOutput( "", "", "", "") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 18, $h{"fred"} eq "joe";
+ ok 19, checkOutput( "", "", "", "") ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok 20, $db->FIRSTKEY() eq "fred" ;
+ ok 21, checkOutput( "", "", "", "") ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink $Dfile;
+ ok 22, $db = tie %h, 'BerkeleyDB::Hash',
+ -Filename => $Dfile,
+ -Flags => DB_CREATE;
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok 23, $result{"store key"} eq "store key - 1: [fred]" ;
+ ok 24, $result{"store value"} eq "store value - 1: [joe]" ;
+ ok 25, ! defined $result{"fetch key"} ;
+ ok 26, ! defined $result{"fetch value"} ;
+ ok 27, $_ eq "original" ;
+
+ ok 28, $db->FIRSTKEY() eq "fred" ;
+ ok 29, $result{"store key"} eq "store key - 1: [fred]" ;
+ ok 30, $result{"store value"} eq "store value - 1: [joe]" ;
+ ok 31, $result{"fetch key"} eq "fetch key - 1: [fred]" ;
+ ok 32, ! defined $result{"fetch value"} ;
+ ok 33, $_ eq "original" ;
+
+ $h{"jim"} = "john" ;
+ ok 34, $result{"store key"} eq "store key - 2: [fred jim]" ;
+ ok 35, $result{"store value"} eq "store value - 2: [joe john]" ;
+ ok 36, $result{"fetch key"} eq "fetch key - 1: [fred]" ;
+ ok 37, ! defined $result{"fetch value"} ;
+ ok 38, $_ eq "original" ;
+
+ ok 39, $h{"fred"} eq "joe" ;
+ ok 40, $result{"store key"} eq "store key - 3: [fred jim fred]" ;
+ ok 41, $result{"store value"} eq "store value - 2: [joe john]" ;
+ ok 42, $result{"fetch key"} eq "fetch key - 1: [fred]" ;
+ ok 43, $result{"fetch value"} eq "fetch value - 1: [joe]" ;
+ ok 44, $_ eq "original" ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok 45, $db = tie %h, 'BerkeleyDB::Hash',
+ -Filename => $Dfile,
+ -Flags => DB_CREATE;
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok 46, $@ =~ /^BerkeleyDB Aborting: recursion detected in filter_store_key at/ ;
+ #print "[$@]\n" ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
diff --git a/bdb/perl/BerkeleyDB/t/hash.t b/bdb/perl/BerkeleyDB/t/hash.t
new file mode 100644
index 00000000000..0e683851c3d
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/hash.t
@@ -0,0 +1,728 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..212\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+
+# Check for invalid parameters
+{
+ # Check for invalid parameters
+ my $db ;
+ eval ' $db = new BerkeleyDB::Hash -Stupid => 3 ; ' ;
+ ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' $db = new BerkeleyDB::Hash -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
+ ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
+
+ eval ' $db = new BerkeleyDB::Hash -Env => 2 ' ;
+ ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+
+ eval ' $db = new BerkeleyDB::Hash -Txn => "fred" ' ;
+ ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
+
+ my $obj = bless [], "main" ;
+ eval ' $db = new BerkeleyDB::Hash -Env => $obj ' ;
+ ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+}
+
+# Now check the interface to HASH
+
+{
+ my $lex = new LexFile $Dfile ;
+
+ ok 6, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my $value ;
+ my $status ;
+ ok 7, $db->db_put("some key", "some value") == 0 ;
+ ok 8, $db->status() == 0 ;
+ ok 9, $db->db_get("some key", $value) == 0 ;
+ ok 10, $value eq "some value" ;
+ ok 11, $db->db_put("key", "value") == 0 ;
+ ok 12, $db->db_get("key", $value) == 0 ;
+ ok 13, $value eq "value" ;
+ ok 14, $db->db_del("some key") == 0 ;
+ ok 15, ($status = $db->db_get("some key", $value)) == DB_NOTFOUND ;
+ ok 16, $status eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 17, $db->status() == DB_NOTFOUND ;
+ ok 18, $db->status() eq $DB_errors{'DB_NOTFOUND'};
+
+ ok 19, $db->db_sync() == 0 ;
+
+ # Check NOOVERWRITE will make put fail when attempting to overwrite
+ # an existing record.
+
+ ok 20, $db->db_put( 'key', 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
+ ok 21, $db->status() eq $DB_errors{'DB_KEYEXIST'};
+ ok 22, $db->status() == DB_KEYEXIST ;
+
+ # check that the value of the key has not been changed by the
+ # previous test
+ ok 23, $db->db_get("key", $value) == 0 ;
+ ok 24, $value eq "value" ;
+
+ # test DB_GET_BOTH
+ my ($k, $v) = ("key", "value") ;
+ ok 25, $db->db_get($k, $v, DB_GET_BOTH) == 0 ;
+
+ ($k, $v) = ("key", "fred") ;
+ ok 26, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+ ($k, $v) = ("another", "value") ;
+ ok 27, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+
+}
+
+{
+ # Check simple env works with a hash.
+ my $lex = new LexFile $Dfile ;
+
+ my $home = "./fred" ;
+ ok 28, my $lexD = new LexDir($home);
+
+ ok 29, my $env = new BerkeleyDB::Env -Flags => DB_CREATE| DB_INIT_MPOOL,
+ -Home => $home ;
+ ok 30, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Env => $env,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my $value ;
+ ok 31, $db->db_put("some key", "some value") == 0 ;
+ ok 32, $db->db_get("some key", $value) == 0 ;
+ ok 33, $value eq "some value" ;
+ undef $db ;
+ undef $env ;
+}
+
+{
+ # override default hash
+ my $lex = new LexFile $Dfile ;
+ my $value ;
+ $::count = 0 ;
+ ok 34, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Hash => sub { ++$::count ; length $_[0] },
+ -Flags => DB_CREATE ;
+
+ ok 35, $db->db_put("some key", "some value") == 0 ;
+ ok 36, $db->db_get("some key", $value) == 0 ;
+ ok 37, $value eq "some value" ;
+ ok 38, $::count > 0 ;
+
+}
+
+{
+ # cursors
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my ($k, $v) ;
+ ok 39, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my %data = (
+ "red" => 2,
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (($k, $v) = each %data) {
+ $ret += $db->db_put($k, $v) ;
+ }
+ ok 40, $ret == 0 ;
+
+ # create the cursor
+ ok 41, my $cursor = $db->db_cursor() ;
+
+ $k = $v = "" ;
+ my %copy = %data ;
+ my $extras = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ if ( $copy{$k} eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+ ok 42, $cursor->status() == DB_NOTFOUND ;
+ ok 43, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 44, keys %copy == 0 ;
+ ok 45, $extras == 0 ;
+
+ # sequence backwards
+ %copy = %data ;
+ $extras = 0 ;
+ my $status ;
+ for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_PREV)) {
+ if ( $copy{$k} eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+ ok 46, $status == DB_NOTFOUND ;
+ ok 47, $status eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 48, $cursor->status() == $status ;
+ ok 49, $cursor->status() eq $status ;
+ ok 50, keys %copy == 0 ;
+ ok 51, $extras == 0 ;
+
+ ($k, $v) = ("green", "house") ;
+ ok 52, $cursor->c_get($k, $v, DB_GET_BOTH) == 0 ;
+
+ ($k, $v) = ("green", "door") ;
+ ok 53, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+ ($k, $v) = ("black", "house") ;
+ ok 54, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
+
+}
+
+{
+ # Tied Hash interface
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ ok 55, tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # check "each" with an empty database
+ my $count = 0 ;
+ while (my ($k, $v) = each %hash) {
+ ++ $count ;
+ }
+ ok 56, (tied %hash)->status() == DB_NOTFOUND ;
+ ok 57, $count == 0 ;
+
+ # Add a k/v pair
+ my $value ;
+ $hash{"some key"} = "some value";
+ ok 58, (tied %hash)->status() == 0 ;
+ ok 59, $hash{"some key"} eq "some value";
+ ok 60, defined $hash{"some key"} ;
+ ok 61, (tied %hash)->status() == 0 ;
+ ok 62, exists $hash{"some key"} ;
+ ok 63, !defined $hash{"jimmy"} ;
+ ok 64, (tied %hash)->status() == DB_NOTFOUND ;
+ ok 65, !exists $hash{"jimmy"} ;
+ ok 66, (tied %hash)->status() == DB_NOTFOUND ;
+
+ delete $hash{"some key"} ;
+ ok 67, (tied %hash)->status() == 0 ;
+ ok 68, ! defined $hash{"some key"} ;
+ ok 69, (tied %hash)->status() == DB_NOTFOUND ;
+ ok 70, ! exists $hash{"some key"} ;
+ ok 71, (tied %hash)->status() == DB_NOTFOUND ;
+
+ $hash{1} = 2 ;
+ $hash{10} = 20 ;
+ $hash{1000} = 2000 ;
+
+ my ($keys, $values) = (0,0);
+ $count = 0 ;
+ while (my ($k, $v) = each %hash) {
+ $keys += $k ;
+ $values += $v ;
+ ++ $count ;
+ }
+ ok 72, $count == 3 ;
+ ok 73, $keys == 1011 ;
+ ok 74, $values == 2022 ;
+
+ # now clear the hash
+ %hash = () ;
+ ok 75, keys %hash == 0 ;
+
+ untie %hash ;
+}
+
+{
+ # in-memory file
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $fd ;
+ my $value ;
+ ok 76, my $db = tie %hash, 'BerkeleyDB::Hash' ;
+
+ ok 77, $db->db_put("some key", "some value") == 0 ;
+ ok 78, $db->db_get("some key", $value) == 0 ;
+ ok 79, $value eq "some value" ;
+
+ undef $db ;
+ untie %hash ;
+}
+
+{
+ # partial
+ # check works via API
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+ ok 80, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db->db_put($k, $v) ;
+ }
+ ok 81, $ret == 0 ;
+
+
+ # do a partial get
+ my($pon, $off, $len) = $db->partial_set(0,2) ;
+ ok 82, $pon == 0 && $off == 0 && $len == 0 ;
+ ok 83, ( $db->db_get("red", $value) == 0) && $value eq "bo" ;
+ ok 84, ( $db->db_get("green", $value) == 0) && $value eq "ho" ;
+ ok 85, ( $db->db_get("blue", $value) == 0) && $value eq "se" ;
+
+ # do a partial get, off end of data
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 86, $pon ;
+ ok 87, $off == 0 ;
+ ok 88, $len == 2 ;
+ ok 89, $db->db_get("red", $value) == 0 && $value eq "t" ;
+ ok 90, $db->db_get("green", $value) == 0 && $value eq "se" ;
+ ok 91, $db->db_get("blue", $value) == 0 && $value eq "" ;
+
+ # switch of partial mode
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 92, $pon ;
+ ok 93, $off == 3 ;
+ ok 94, $len == 2 ;
+ ok 95, $db->db_get("red", $value) == 0 && $value eq "boat" ;
+ ok 96, $db->db_get("green", $value) == 0 && $value eq "house" ;
+ ok 97, $db->db_get("blue", $value) == 0 && $value eq "sea" ;
+
+ # now partial put
+ ($pon, $off, $len) = $db->partial_set(0,2) ;
+ ok 98, ! $pon ;
+ ok 99, $off == 0 ;
+ ok 100, $len == 0 ;
+ ok 101, $db->db_put("red", "") == 0 ;
+ ok 102, $db->db_put("green", "AB") == 0 ;
+ ok 103, $db->db_put("blue", "XYZ") == 0 ;
+ ok 104, $db->db_put("new", "KLM") == 0 ;
+
+ $db->partial_clear() ;
+ ok 105, $db->db_get("red", $value) == 0 && $value eq "at" ;
+ ok 106, $db->db_get("green", $value) == 0 && $value eq "ABuse" ;
+ ok 107, $db->db_get("blue", $value) == 0 && $value eq "XYZa" ;
+ ok 108, $db->db_get("new", $value) == 0 && $value eq "KLM" ;
+
+ # now partial put
+ $db->partial_set(3,2) ;
+ ok 109, $db->db_put("red", "PPP") == 0 ;
+ ok 110, $db->db_put("green", "Q") == 0 ;
+ ok 111, $db->db_put("blue", "XYZ") == 0 ;
+ ok 112, $db->db_put("new", "--") == 0 ;
+
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 113, $pon ;
+ ok 114, $off == 3 ;
+ ok 115, $len == 2 ;
+ ok 116, $db->db_get("red", $value) == 0 && $value eq "at\0PPP" ;
+ ok 117, $db->db_get("green", $value) == 0 && $value eq "ABuQ" ;
+ ok 118, $db->db_get("blue", $value) == 0 && $value eq "XYZXYZ" ;
+ ok 119, $db->db_get("new", $value) == 0 && $value eq "KLM--" ;
+}
+
+{
+ # partial
+ # check works via tied hash
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+ ok 120, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ while (my ($k, $v) = each %data) {
+ $hash{$k} = $v ;
+ }
+
+
+ # do a partial get
+ $db->partial_set(0,2) ;
+ ok 121, $hash{"red"} eq "bo" ;
+ ok 122, $hash{"green"} eq "ho" ;
+ ok 123, $hash{"blue"} eq "se" ;
+
+ # do a partial get, off end of data
+ $db->partial_set(3,2) ;
+ ok 124, $hash{"red"} eq "t" ;
+ ok 125, $hash{"green"} eq "se" ;
+ ok 126, $hash{"blue"} eq "" ;
+
+ # switch of partial mode
+ $db->partial_clear() ;
+ ok 127, $hash{"red"} eq "boat" ;
+ ok 128, $hash{"green"} eq "house" ;
+ ok 129, $hash{"blue"} eq "sea" ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ ok 130, $hash{"red"} = "" ;
+ ok 131, $hash{"green"} = "AB" ;
+ ok 132, $hash{"blue"} = "XYZ" ;
+ ok 133, $hash{"new"} = "KLM" ;
+
+ $db->partial_clear() ;
+ ok 134, $hash{"red"} eq "at" ;
+ ok 135, $hash{"green"} eq "ABuse" ;
+ ok 136, $hash{"blue"} eq "XYZa" ;
+ ok 137, $hash{"new"} eq "KLM" ;
+
+ # now partial put
+ $db->partial_set(3,2) ;
+ ok 138, $hash{"red"} = "PPP" ;
+ ok 139, $hash{"green"} = "Q" ;
+ ok 140, $hash{"blue"} = "XYZ" ;
+ ok 141, $hash{"new"} = "TU" ;
+
+ $db->partial_clear() ;
+ ok 142, $hash{"red"} eq "at\0PPP" ;
+ ok 143, $hash{"green"} eq "ABuQ" ;
+ ok 144, $hash{"blue"} eq "XYZXYZ" ;
+ ok 145, $hash{"new"} eq "KLMTU" ;
+}
+
+{
+ # transaction
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 146, my $lexD = new LexDir($home);
+ ok 147, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 148, my $txn = $env->txn_begin() ;
+ ok 149, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+
+ ok 150, $txn->txn_commit() == 0 ;
+ ok 151, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 152, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 153, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 154, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ ok 155, $txn->txn_abort() == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 156, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 157, $count == 0 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $env ;
+ untie %hash ;
+}
+
+
+{
+ # DB_DUP
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ ok 158, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ $hash{'Wall'} = 'Larry' ;
+ $hash{'Wall'} = 'Stone' ;
+ $hash{'Smith'} = 'John' ;
+ $hash{'Wall'} = 'Brick' ;
+ $hash{'Wall'} = 'Brick' ;
+ $hash{'mouse'} = 'mickey' ;
+
+ ok 159, keys %hash == 6 ;
+
+ # create a cursor
+ ok 160, my $cursor = $db->db_cursor() ;
+
+ my $key = "Wall" ;
+ my $value ;
+ ok 161, $cursor->c_get($key, $value, DB_SET) == 0 ;
+ ok 162, $key eq "Wall" && $value eq "Larry" ;
+ ok 163, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 164, $key eq "Wall" && $value eq "Stone" ;
+ ok 165, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 166, $key eq "Wall" && $value eq "Brick" ;
+ ok 167, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 168, $key eq "Wall" && $value eq "Brick" ;
+
+ #my $ref = $db->db_stat() ;
+ #ok 143, $ref->{bt_flags} | DB_DUP ;
+
+ # test DB_DUP_NEXT
+ my ($k, $v) = ("Wall", "") ;
+ ok 169, $cursor->c_get($k, $v, DB_SET) == 0 ;
+ ok 170, $k eq "Wall" && $v eq "Larry" ;
+ ok 171, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
+ ok 172, $k eq "Wall" && $v eq "Stone" ;
+ ok 173, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
+ ok 174, $k eq "Wall" && $v eq "Brick" ;
+ ok 175, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
+ ok 176, $k eq "Wall" && $v eq "Brick" ;
+ ok 177, $cursor->c_get($k, $v, DB_NEXT_DUP) == DB_NOTFOUND ;
+
+
+ undef $db ;
+ undef $cursor ;
+ untie %hash ;
+
+}
+
+{
+ # DB_DUP & DupCompare
+ my $lex = new LexFile $Dfile, $Dfile2;
+ my ($key, $value) ;
+ my (%h, %g) ;
+ my @Keys = qw( 0123 9 12 -1234 9 987654321 9 def ) ;
+ my @Values = qw( 1 11 3 dd x abc 2 0 ) ;
+
+ ok 178, tie %h, "BerkeleyDB::Hash", -Filename => $Dfile,
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP|DB_DUPSORT,
+ -Flags => DB_CREATE ;
+
+ ok 179, tie %g, 'BerkeleyDB::Hash', -Filename => $Dfile2,
+ -DupCompare => sub { $_[0] <=> $_[1] },
+ -Property => DB_DUP|DB_DUPSORT,
+ -Flags => DB_CREATE ;
+
+ foreach (@Keys) {
+ local $^W = 0 ;
+ my $value = shift @Values ;
+ $h{$_} = $value ;
+ $g{$_} = $value ;
+ }
+
+ ok 180, my $cursor = (tied %h)->db_cursor() ;
+ $key = 9 ; $value = "";
+ ok 181, $cursor->c_get($key, $value, DB_SET) == 0 ;
+ ok 182, $key == 9 && $value eq 11 ;
+ ok 183, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 184, $key == 9 && $value == 2 ;
+ ok 185, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 186, $key == 9 && $value eq "x" ;
+
+ $cursor = (tied %g)->db_cursor() ;
+ $key = 9 ;
+ ok 187, $cursor->c_get($key, $value, DB_SET) == 0 ;
+ ok 188, $key == 9 && $value eq "x" ;
+ ok 189, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 190, $key == 9 && $value == 2 ;
+ ok 191, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
+ ok 192, $key == 9 && $value == 11 ;
+
+
+}
+
+{
+ # get_dup etc
+ my $lex = new LexFile $Dfile;
+ my %hh ;
+
+ ok 193, my $YY = tie %hh, "BerkeleyDB::Hash", -Filename => $Dfile,
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP,
+ -Flags => DB_CREATE ;
+
+ $hh{'Wall'} = 'Larry' ;
+ $hh{'Wall'} = 'Stone' ; # Note the duplicate key
+ $hh{'Wall'} = 'Brick' ; # Note the duplicate key
+ $hh{'Smith'} = 'John' ;
+ $hh{'mouse'} = 'mickey' ;
+
+ # first work in scalar context
+ ok 194, scalar $YY->get_dup('Unknown') == 0 ;
+ ok 195, scalar $YY->get_dup('Smith') == 1 ;
+ ok 196, scalar $YY->get_dup('Wall') == 3 ;
+
+ # now in list context
+ my @unknown = $YY->get_dup('Unknown') ;
+ ok 197, "@unknown" eq "" ;
+
+ my @smith = $YY->get_dup('Smith') ;
+ ok 198, "@smith" eq "John" ;
+
+ {
+ my @wall = $YY->get_dup('Wall') ;
+ my %wall ;
+ @wall{@wall} = @wall ;
+ ok 199, (@wall == 3 && $wall{'Larry'}
+ && $wall{'Stone'} && $wall{'Brick'});
+ }
+
+ # hash
+ my %unknown = $YY->get_dup('Unknown', 1) ;
+ ok 200, keys %unknown == 0 ;
+
+ my %smith = $YY->get_dup('Smith', 1) ;
+ ok 201, keys %smith == 1 && $smith{'John'} ;
+
+ my %wall = $YY->get_dup('Wall', 1) ;
+ ok 202, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1
+ && $wall{'Brick'} == 1 ;
+
+ undef $YY ;
+ untie %hh ;
+
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use strict ;
+ use vars qw( @ISA @EXPORT) ;
+
+ require Exporter ;
+ use BerkeleyDB;
+ @ISA=qw(BerkeleyDB::Hash);
+ @EXPORT = @BerkeleyDB::EXPORT ;
+
+ sub db_put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::db_put($key, $value * 3) ;
+ }
+
+ sub db_get {
+ my $self = shift ;
+ $self->SUPER::db_get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE ;
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok 203, $@ eq "" ;
+ my %h ;
+ my $X ;
+ eval '
+ $X = tie(%h, "SubDB", -Filename => "dbhash.tmp",
+ -Flags => DB_CREATE,
+ -Mode => 0640 );
+ ' ;
+
+ main::ok 204, $@ eq "" ;
+
+ my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
+ main::ok 205, $@ eq "" ;
+ main::ok 206, $ret == 7 ;
+
+ my $value = 0;
+ $ret = eval '$X->db_put("joe", 4) ; $X->db_get("joe", $value) ; return $value' ;
+ main::ok 207, $@ eq "" ;
+ main::ok 208, $ret == 10 ;
+
+ $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
+ main::ok 209, $@ eq "" ;
+ main::ok 210, $ret == 1 ;
+
+ $ret = eval '$X->A_new_method("joe") ' ;
+ main::ok 211, $@ eq "" ;
+ main::ok 212, $ret eq "[[10]]" ;
+
+ unlink "SubDB.pm", "dbhash.tmp" ;
+
+}
diff --git a/bdb/perl/BerkeleyDB/t/join.t b/bdb/perl/BerkeleyDB/t/join.t
new file mode 100644
index 00000000000..ed9b6a269cb
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/join.t
@@ -0,0 +1,225 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+if ($BerkeleyDB::db_ver < 2.005002)
+{
+ print "1..0 # Skip: join needs Berkeley DB 2.5.2 or later\n" ;
+ exit 0 ;
+}
+
+
+print "1..37\n";
+
+my $Dfile1 = "dbhash1.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile1, $Dfile2, $Dfile3 ;
+
+umask(0) ;
+
+{
+ # error cases
+ my $lex = new LexFile $Dfile1, $Dfile2, $Dfile3 ;
+ my %hash1 ;
+ my $value ;
+ my $status ;
+ my $cursor ;
+
+ ok 1, my $db1 = tie %hash1, 'BerkeleyDB::Hash',
+ -Filename => $Dfile1,
+ -Flags => DB_CREATE,
+ -DupCompare => sub { $_[0] lt $_[1] },
+ -Property => DB_DUP|DB_DUPSORT ;
+
+ # no cursors supplied
+ eval '$cursor = $db1->db_join() ;' ;
+ ok 2, $@ =~ /Usage: \$db->BerkeleyDB::Common::db_join\Q([cursors], flags=0)/;
+
+ # empty list
+ eval '$cursor = $db1->db_join([]) ;' ;
+ ok 3, $@ =~ /db_join: No cursors in parameter list/;
+
+ # cursor list, isn't a []
+ eval '$cursor = $db1->db_join({}) ;' ;
+ ok 4, $@ =~ /cursors is not an array reference at/ ;
+
+ eval '$cursor = $db1->db_join(\1) ;' ;
+ ok 5, $@ =~ /cursors is not an array reference at/ ;
+
+}
+
+{
+ # test a 2-way & 3-way join
+
+ my $lex = new LexFile $Dfile1, $Dfile2, $Dfile3 ;
+ my %hash1 ;
+ my %hash2 ;
+ my %hash3 ;
+ my $value ;
+ my $status ;
+
+ my $home = "./fred" ;
+ ok 6, my $lexD = new LexDir($home);
+ ok 7, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN
+ |DB_INIT_MPOOL;
+ #|DB_INIT_MPOOL| DB_INIT_LOCK;
+ ok 8, my $txn = $env->txn_begin() ;
+ ok 9, my $db1 = tie %hash1, 'BerkeleyDB::Hash',
+ -Filename => $Dfile1,
+ -Flags => DB_CREATE,
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP|DB_DUPSORT,
+ -Env => $env,
+ -Txn => $txn ;
+ ;
+
+ ok 10, my $db2 = tie %hash2, 'BerkeleyDB::Hash',
+ -Filename => $Dfile2,
+ -Flags => DB_CREATE,
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP|DB_DUPSORT,
+ -Env => $env,
+ -Txn => $txn ;
+
+ ok 11, my $db3 = tie %hash3, 'BerkeleyDB::Btree',
+ -Filename => $Dfile3,
+ -Flags => DB_CREATE,
+ -DupCompare => sub { $_[0] cmp $_[1] },
+ -Property => DB_DUP|DB_DUPSORT,
+ -Env => $env,
+ -Txn => $txn ;
+
+
+ ok 12, addData($db1, qw( apple Convenience
+ peach Shopway
+ pear Farmer
+ raspberry Shopway
+ strawberry Shopway
+ gooseberry Farmer
+ blueberry Farmer
+ ));
+
+ ok 13, addData($db2, qw( red apple
+ red raspberry
+ red strawberry
+ yellow peach
+ yellow pear
+ green gooseberry
+ blue blueberry)) ;
+
+ ok 14, addData($db3, qw( expensive apple
+ reasonable raspberry
+ expensive strawberry
+ reasonable peach
+ reasonable pear
+ expensive gooseberry
+ reasonable blueberry)) ;
+
+ ok 15, my $cursor2 = $db2->db_cursor() ;
+ my $k = "red" ;
+ my $v = "" ;
+ ok 16, $cursor2->c_get($k, $v, DB_SET) == 0 ;
+
+ # Two way Join
+ ok 17, my $cursor1 = $db1->db_join([$cursor2]) ;
+
+ my %expected = qw( apple Convenience
+ raspberry Shopway
+ strawberry Shopway
+ ) ;
+
+ # sequence forwards
+ while ($cursor1->c_get($k, $v) == 0) {
+ delete $expected{$k}
+ if defined $expected{$k} && $expected{$k} eq $v ;
+ #print "[$k] [$v]\n" ;
+ }
+ ok 18, keys %expected == 0 ;
+ ok 19, $cursor1->status() == DB_NOTFOUND ;
+
+ # Three way Join
+ ok 20, $cursor2 = $db2->db_cursor() ;
+ $k = "red" ;
+ $v = "" ;
+ ok 21, $cursor2->c_get($k, $v, DB_SET) == 0 ;
+
+ ok 22, my $cursor3 = $db3->db_cursor() ;
+ $k = "expensive" ;
+ $v = "" ;
+ ok 23, $cursor3->c_get($k, $v, DB_SET) == 0 ;
+ ok 24, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
+
+ %expected = qw( apple Convenience
+ strawberry Shopway
+ ) ;
+
+ # sequence forwards
+ while ($cursor1->c_get($k, $v) == 0) {
+ delete $expected{$k}
+ if defined $expected{$k} && $expected{$k} eq $v ;
+ #print "[$k] [$v]\n" ;
+ }
+ ok 25, keys %expected == 0 ;
+ ok 26, $cursor1->status() == DB_NOTFOUND ;
+
+ # test DB_JOIN_ITEM
+ # #################
+ ok 27, $cursor2 = $db2->db_cursor() ;
+ $k = "red" ;
+ $v = "" ;
+ ok 28, $cursor2->c_get($k, $v, DB_SET) == 0 ;
+
+ ok 29, $cursor3 = $db3->db_cursor() ;
+ $k = "expensive" ;
+ $v = "" ;
+ ok 30, $cursor3->c_get($k, $v, DB_SET) == 0 ;
+ ok 31, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
+
+ %expected = qw( apple 1
+ strawberry 1
+ ) ;
+
+ # sequence forwards
+ $k = "" ;
+ $v = "" ;
+ while ($cursor1->c_get($k, $v, DB_JOIN_ITEM) == 0) {
+ delete $expected{$k}
+ if defined $expected{$k} ;
+ #print "[$k]\n" ;
+ }
+ ok 32, keys %expected == 0 ;
+ ok 33, $cursor1->status() == DB_NOTFOUND ;
+
+ ok 34, $cursor1->c_close() == 0 ;
+ ok 35, $cursor2->c_close() == 0 ;
+ ok 36, $cursor3->c_close() == 0 ;
+
+ ok 37, ($status = $txn->txn_commit) == 0;
+
+ undef $txn ;
+ #undef $cursor1;
+ #undef $cursor2;
+ #undef $cursor3;
+ undef $db1 ;
+ undef $db2 ;
+ undef $db3 ;
+ undef $env ;
+ untie %hash1 ;
+ untie %hash2 ;
+ untie %hash3 ;
+}
+print "# at the end\n";
diff --git a/bdb/perl/BerkeleyDB/t/mldbm.t b/bdb/perl/BerkeleyDB/t/mldbm.t
new file mode 100644
index 00000000000..d35f7e15895
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/mldbm.t
@@ -0,0 +1,161 @@
+#!/usr/bin/perl -w
+
+use strict ;
+
+BEGIN
+{
+ if ($] < 5.005) {
+ print "1..0 # This is Perl $], skipping test\n" ;
+ exit 0 ;
+ }
+
+ eval { require Data::Dumper ; };
+ if ($@) {
+ print "1..0 # Data::Dumper is not installed on this system.\n";
+ exit 0 ;
+ }
+ if ($Data::Dumper::VERSION < 2.08) {
+ print "1..0 # Data::Dumper 2.08 or better required (found $Data::Dumper::VERSION).\n";
+ exit 0 ;
+ }
+ eval { require MLDBM ; };
+ if ($@) {
+ print "1..0 # MLDBM is not installed on this system.\n";
+ exit 0 ;
+ }
+}
+
+use t::util ;
+
+print "1..12\n";
+
+{
+ package BTREE ;
+
+ use BerkeleyDB ;
+ use MLDBM qw(BerkeleyDB::Btree) ;
+ use Data::Dumper;
+
+ my $filename = "";
+ my $lex = new LexFile $filename;
+
+ $MLDBM::UseDB = "BerkeleyDB::Btree" ;
+ my %o ;
+ my $db = tie %o, 'MLDBM', -Filename => $filename,
+ -Flags => DB_CREATE
+ or die $!;
+ ::ok 1, $db ;
+ ::ok 2, $db->type() == DB_BTREE ;
+
+ my $c = [\'c'];
+ my $b = {};
+ my $a = [1, $b, $c];
+ $b->{a} = $a;
+ $b->{b} = $a->[1];
+ $b->{c} = $a->[2];
+ @o{qw(a b c)} = ($a, $b, $c);
+ $o{d} = "{once upon a time}";
+ $o{e} = 1024;
+ $o{f} = 1024.1024;
+ my $first = Data::Dumper->new([@o{qw(a b c)}], [qw(a b c)])->Quotekeys(0)->Dump;
+ my $second = <<'EOT';
+$a = [
+ 1,
+ {
+ a => $a,
+ b => $a->[1],
+ c => [
+ \'c'
+ ]
+ },
+ $a->[1]{c}
+ ];
+$b = {
+ a => [
+ 1,
+ $b,
+ [
+ \'c'
+ ]
+ ],
+ b => $b,
+ c => $b->{a}[2]
+ };
+$c = [
+ \'c'
+ ];
+EOT
+
+ ::ok 3, $first eq $second ;
+ ::ok 4, $o{d} eq "{once upon a time}" ;
+ ::ok 5, $o{e} == 1024 ;
+ ::ok 6, $o{f} eq 1024.1024 ;
+
+}
+
+{
+
+ package HASH ;
+
+ use BerkeleyDB ;
+ use MLDBM qw(BerkeleyDB::Hash) ;
+ use Data::Dumper;
+
+ my $filename = "";
+ my $lex = new LexFile $filename;
+
+ unlink $filename ;
+ $MLDBM::UseDB = "BerkeleyDB::Hash" ;
+ my %o ;
+ my $db = tie %o, 'MLDBM', -Filename => $filename,
+ -Flags => DB_CREATE
+ or die $!;
+ ::ok 7, $db ;
+ ::ok 8, $db->type() == DB_HASH ;
+
+
+ my $c = [\'c'];
+ my $b = {};
+ my $a = [1, $b, $c];
+ $b->{a} = $a;
+ $b->{b} = $a->[1];
+ $b->{c} = $a->[2];
+ @o{qw(a b c)} = ($a, $b, $c);
+ $o{d} = "{once upon a time}";
+ $o{e} = 1024;
+ $o{f} = 1024.1024;
+ my $first = Data::Dumper->new([@o{qw(a b c)}], [qw(a b c)])->Quotekeys(0)->Dump;
+ my $second = <<'EOT';
+$a = [
+ 1,
+ {
+ a => $a,
+ b => $a->[1],
+ c => [
+ \'c'
+ ]
+ },
+ $a->[1]{c}
+ ];
+$b = {
+ a => [
+ 1,
+ $b,
+ [
+ \'c'
+ ]
+ ],
+ b => $b,
+ c => $b->{a}[2]
+ };
+$c = [
+ \'c'
+ ];
+EOT
+
+ ::ok 9, $first eq $second ;
+ ::ok 10, $o{d} eq "{once upon a time}" ;
+ ::ok 11, $o{e} == 1024 ;
+ ::ok 12, $o{f} eq 1024.1024 ;
+
+}
diff --git a/bdb/perl/BerkeleyDB/t/queue.t b/bdb/perl/BerkeleyDB/t/queue.t
new file mode 100644
index 00000000000..86add129ca4
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/queue.t
@@ -0,0 +1,763 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+BEGIN
+{
+ if ($BerkeleyDB::db_version < 3.3) {
+ print "1..0 # Skipping test, Queue needs Berkeley DB 3.3.x or better\n" ;
+ exit 0 ;
+ }
+}
+
+print "1..201\n";
+
+sub fillout
+{
+ my $var = shift ;
+ my $length = shift ;
+ my $pad = shift || " " ;
+ my $template = $pad x $length ;
+ substr($template, 0, length($var)) = $var ;
+ return $template ;
+}
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+
+# Check for invalid parameters
+{
+ # Check for invalid parameters
+ my $db ;
+ eval ' $db = new BerkeleyDB::Queue -Stupid => 3 ; ' ;
+ ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' $db = new BerkeleyDB::Queue -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
+ ok 2, $@ =~ /unknown key value\(s\) / ;
+
+ eval ' $db = new BerkeleyDB::Queue -Env => 2 ' ;
+ ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+
+ eval ' $db = new BerkeleyDB::Queue -Txn => "x" ' ;
+ ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
+
+ my $obj = bless [], "main" ;
+ eval ' $db = new BerkeleyDB::Queue -Env => $obj ' ;
+ ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+}
+
+# Now check the interface to Queue
+
+{
+ my $lex = new LexFile $Dfile ;
+ my $rec_len = 10 ;
+ my $pad = "x" ;
+
+ ok 6, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
+ -Flags => DB_CREATE,
+ -Len => $rec_len,
+ -Pad => $pad;
+
+ # Add a k/v pair
+ my $value ;
+ my $status ;
+ ok 7, $db->db_put(1, "some value") == 0 ;
+ ok 8, $db->status() == 0 ;
+ ok 9, $db->db_get(1, $value) == 0 ;
+ ok 10, $value eq fillout("some value", $rec_len, $pad) ;
+ ok 11, $db->db_put(2, "value") == 0 ;
+ ok 12, $db->db_get(2, $value) == 0 ;
+ ok 13, $value eq fillout("value", $rec_len, $pad) ;
+ ok 14, $db->db_del(1) == 0 ;
+ ok 15, ($status = $db->db_get(1, $value)) == DB_KEYEMPTY ;
+ ok 16, $db->status() == DB_KEYEMPTY ;
+ ok 17, $db->status() eq $DB_errors{'DB_KEYEMPTY'} ;
+
+ ok 18, ($status = $db->db_get(7, $value)) == DB_NOTFOUND ;
+ ok 19, $db->status() == DB_NOTFOUND ;
+ ok 20, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
+
+ ok 21, $db->db_sync() == 0 ;
+
+ # Check NOOVERWRITE will make put fail when attempting to overwrite
+ # an existing record.
+
+ ok 22, $db->db_put( 2, 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
+ ok 23, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
+ ok 24, $db->status() == DB_KEYEXIST ;
+
+
+ # check that the value of the key has not been changed by the
+ # previous test
+ ok 25, $db->db_get(2, $value) == 0 ;
+ ok 26, $value eq fillout("value", $rec_len, $pad) ;
+
+
+}
+
+
+{
+ # Check simple env works with a array.
+ # and pad defaults to space
+ my $lex = new LexFile $Dfile ;
+
+ my $home = "./fred" ;
+ my $rec_len = 11 ;
+ ok 27, my $lexD = new LexDir($home);
+
+ ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
+ -Home => $home ;
+ ok 29, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
+ -Env => $env,
+ -Flags => DB_CREATE,
+ -Len => $rec_len;
+
+ # Add a k/v pair
+ my $value ;
+ ok 30, $db->db_put(1, "some value") == 0 ;
+ ok 31, $db->db_get(1, $value) == 0 ;
+ ok 32, $value eq fillout("some value", $rec_len) ;
+ undef $db ;
+ undef $env ;
+}
+
+
+{
+ # cursors
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my ($k, $v) ;
+ my $rec_len = 5 ;
+ ok 33, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Len => $rec_len;
+
+ # create some data
+ my @data = (
+ "red" ,
+ "green" ,
+ "blue" ,
+ ) ;
+
+ my $i ;
+ my %data ;
+ my $ret = 0 ;
+ for ($i = 0 ; $i < @data ; ++$i) {
+ $ret += $db->db_put($i, $data[$i]) ;
+ $data{$i} = $data[$i] ;
+ }
+ ok 34, $ret == 0 ;
+
+ # create the cursor
+ ok 35, my $cursor = $db->db_cursor() ;
+
+ $k = 0 ; $v = "" ;
+ my %copy = %data;
+ my $extras = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ {
+ if ( fillout($copy{$k}, $rec_len) eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+
+ ok 36, $cursor->status() == DB_NOTFOUND ;
+ ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 38, keys %copy == 0 ;
+ ok 39, $extras == 0 ;
+
+ # sequence backwards
+ %copy = %data ;
+ $extras = 0 ;
+ my $status ;
+ for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_PREV)) {
+ if ( fillout($copy{$k}, $rec_len) eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+ ok 40, $status == DB_NOTFOUND ;
+ ok 41, $status eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 42, $cursor->status() == $status ;
+ ok 43, $cursor->status() eq $status ;
+ ok 44, keys %copy == 0 ;
+ ok 45, $extras == 0 ;
+}
+
+{
+ # Tied Array interface
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $db ;
+ my $rec_len = 10 ;
+ ok 46, $db = tie @array, 'BerkeleyDB::Queue', -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Len => $rec_len;
+
+ ok 47, my $cursor = (tied @array)->db_cursor() ;
+ # check the database is empty
+ my $count = 0 ;
+ my ($k, $v) = (0,"") ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 48, $cursor->status() == DB_NOTFOUND ;
+ ok 49, $count == 0 ;
+
+ ok 50, @array == 0 ;
+
+ # Add a k/v pair
+ my $value ;
+ $array[1] = "some value";
+ ok 51, (tied @array)->status() == 0 ;
+ ok 52, $array[1] eq fillout("some value", $rec_len);
+ ok 53, defined $array[1];
+ ok 54, (tied @array)->status() == 0 ;
+ ok 55, !defined $array[3];
+ ok 56, (tied @array)->status() == DB_NOTFOUND ;
+
+ ok 57, (tied @array)->db_del(1) == 0 ;
+ ok 58, (tied @array)->status() == 0 ;
+ ok 59, ! defined $array[1];
+ ok 60, (tied @array)->status() == DB_KEYEMPTY ;
+
+ $array[1] = 2 ;
+ $array[10] = 20 ;
+ $array[1000] = 2000 ;
+
+ my ($keys, $values) = (0,0);
+ $count = 0 ;
+ for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_NEXT)) {
+ $keys += $k ;
+ $values += $v ;
+ ++ $count ;
+ }
+ ok 61, $count == 3 ;
+ ok 62, $keys == 1011 ;
+ ok 63, $values == 2022 ;
+
+ # unshift isn't allowed
+# eval {
+# $FA ? unshift @array, "red", "green", "blue"
+# : $db->unshift("red", "green", "blue" ) ;
+# } ;
+# ok 64, $@ =~ /^unshift is unsupported with Queue databases/ ;
+ $array[0] = "red" ;
+ $array[1] = "green" ;
+ $array[2] = "blue" ;
+ $array[4] = 2 ;
+ ok 64, $array[0] eq fillout("red", $rec_len) ;
+ ok 65, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
+ ok 66, $k == 0 ;
+ ok 67, $v eq fillout("red", $rec_len) ;
+ ok 68, $array[1] eq fillout("green", $rec_len) ;
+ ok 69, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 70, $k == 1 ;
+ ok 71, $v eq fillout("green", $rec_len) ;
+ ok 72, $array[2] eq fillout("blue", $rec_len) ;
+ ok 73, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 74, $k == 2 ;
+ ok 75, $v eq fillout("blue", $rec_len) ;
+ ok 76, $array[4] == 2 ;
+ ok 77, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 78, $k == 4 ;
+ ok 79, $v == 2 ;
+
+ # shift
+ ok 80, ($FA ? shift @array : $db->shift()) eq fillout("red", $rec_len) ;
+ ok 81, ($FA ? shift @array : $db->shift()) eq fillout("green", $rec_len) ;
+ ok 82, ($FA ? shift @array : $db->shift()) eq fillout("blue", $rec_len) ;
+ ok 83, ($FA ? shift @array : $db->shift()) == 2 ;
+
+ # push
+ $FA ? push @array, "the", "end"
+ : $db->push("the", "end") ;
+ ok 84, $cursor->c_get($k, $v, DB_LAST) == 0 ;
+ ok 85, $k == 1002 ;
+ ok 86, $v eq fillout("end", $rec_len) ;
+ ok 87, $cursor->c_get($k, $v, DB_PREV) == 0 ;
+ ok 88, $k == 1001 ;
+ ok 89, $v eq fillout("the", $rec_len) ;
+ ok 90, $cursor->c_get($k, $v, DB_PREV) == 0 ;
+ ok 91, $k == 1000 ;
+ ok 92, $v == 2000 ;
+
+ # pop
+ ok 93, ( $FA ? pop @array : $db->pop ) eq fillout("end", $rec_len) ;
+ ok 94, ( $FA ? pop @array : $db->pop ) eq fillout("the", $rec_len) ;
+ ok 95, ( $FA ? pop @array : $db->pop ) == 2000 ;
+
+ # now clear the array
+ $FA ? @array = ()
+ : $db->clear() ;
+ ok 96, $cursor->c_get($k, $v, DB_FIRST) == DB_NOTFOUND ;
+
+ undef $cursor ;
+ undef $db ;
+ untie @array ;
+}
+
+{
+ # in-memory file
+
+ my @array ;
+ my $fd ;
+ my $value ;
+ my $rec_len = 15 ;
+ ok 97, my $db = tie @array, 'BerkeleyDB::Queue',
+ -Len => $rec_len;
+
+ ok 98, $db->db_put(1, "some value") == 0 ;
+ ok 99, $db->db_get(1, $value) == 0 ;
+ ok 100, $value eq fillout("some value", $rec_len) ;
+
+}
+
+{
+ # partial
+ # check works via API
+
+ my $lex = new LexFile $Dfile ;
+ my $value ;
+ my $rec_len = 8 ;
+ ok 101, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Len => $rec_len,
+ -Pad => " " ;
+
+ # create some data
+ my @data = (
+ "",
+ "boat",
+ "house",
+ "sea",
+ ) ;
+
+ my $ret = 0 ;
+ my $i ;
+ for ($i = 0 ; $i < @data ; ++$i) {
+ my $r = $db->db_put($i, $data[$i]) ;
+ $ret += $r ;
+ }
+ ok 102, $ret == 0 ;
+
+ # do a partial get
+ my ($pon, $off, $len) = $db->partial_set(0,2) ;
+ ok 103, ! $pon && $off == 0 && $len == 0 ;
+ ok 104, $db->db_get(1, $value) == 0 && $value eq "bo" ;
+ ok 105, $db->db_get(2, $value) == 0 && $value eq "ho" ;
+ ok 106, $db->db_get(3, $value) == 0 && $value eq "se" ;
+
+ # do a partial get, off end of data
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 107, $pon ;
+ ok 108, $off == 0 ;
+ ok 109, $len == 2 ;
+ ok 110, $db->db_get(1, $value) == 0 && $value eq fillout("t", 2) ;
+ ok 111, $db->db_get(2, $value) == 0 && $value eq "se" ;
+ ok 112, $db->db_get(3, $value) == 0 && $value eq " " ;
+
+ # switch of partial mode
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 113, $pon ;
+ ok 114, $off == 3 ;
+ ok 115, $len == 2 ;
+ ok 116, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
+ ok 117, $db->db_get(2, $value) == 0 && $value eq fillout("house", $rec_len) ;
+ ok 118, $db->db_get(3, $value) == 0 && $value eq fillout("sea", $rec_len) ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ ok 119, $db->db_put(1, "") != 0 ;
+ ok 120, $db->db_put(2, "AB") == 0 ;
+ ok 121, $db->db_put(3, "XY") == 0 ;
+ ok 122, $db->db_put(4, "KLM") != 0 ;
+ ok 123, $db->db_put(4, "KL") == 0 ;
+
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 124, $pon ;
+ ok 125, $off == 0 ;
+ ok 126, $len == 2 ;
+ ok 127, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
+ ok 128, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse", $rec_len) ;
+ ok 129, $db->db_get(3, $value) == 0 && $value eq fillout("XYa", $rec_len) ;
+ ok 130, $db->db_get(4, $value) == 0 && $value eq fillout("KL", $rec_len) ;
+
+ # now partial put
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 131, ! $pon ;
+ ok 132, $off == 0 ;
+ ok 133, $len == 0 ;
+ ok 134, $db->db_put(1, "PP") == 0 ;
+ ok 135, $db->db_put(2, "Q") != 0 ;
+ ok 136, $db->db_put(3, "XY") == 0 ;
+ ok 137, $db->db_put(4, "TU") == 0 ;
+
+ $db->partial_clear() ;
+ ok 138, $db->db_get(1, $value) == 0 && $value eq fillout("boaPP", $rec_len) ;
+ ok 139, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse",$rec_len) ;
+ ok 140, $db->db_get(3, $value) == 0 && $value eq fillout("XYaXY", $rec_len) ;
+ ok 141, $db->db_get(4, $value) == 0 && $value eq fillout("KL TU", $rec_len) ;
+}
+
+{
+ # partial
+ # check works via tied array
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $value ;
+ my $rec_len = 8 ;
+ ok 142, my $db = tie @array, 'BerkeleyDB::Queue', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Len => $rec_len,
+ -Pad => " " ;
+
+ # create some data
+ my @data = (
+ "",
+ "boat",
+ "house",
+ "sea",
+ ) ;
+
+ my $i ;
+ my $status = 0 ;
+ for ($i = 1 ; $i < @data ; ++$i) {
+ $array[$i] = $data[$i] ;
+ $status += $db->status() ;
+ }
+
+ ok 143, $status == 0 ;
+
+ # do a partial get
+ $db->partial_set(0,2) ;
+ ok 144, $array[1] eq fillout("bo", 2) ;
+ ok 145, $array[2] eq fillout("ho", 2) ;
+ ok 146, $array[3] eq fillout("se", 2) ;
+
+ # do a partial get, off end of data
+ $db->partial_set(3,2) ;
+ ok 147, $array[1] eq fillout("t", 2) ;
+ ok 148, $array[2] eq fillout("se", 2) ;
+ ok 149, $array[3] eq fillout("", 2) ;
+
+ # switch of partial mode
+ $db->partial_clear() ;
+ ok 150, $array[1] eq fillout("boat", $rec_len) ;
+ ok 151, $array[2] eq fillout("house", $rec_len) ;
+ ok 152, $array[3] eq fillout("sea", $rec_len) ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ $array[1] = "" ;
+ ok 153, $db->status() != 0 ;
+ $array[2] = "AB" ;
+ ok 154, $db->status() == 0 ;
+ $array[3] = "XY" ;
+ ok 155, $db->status() == 0 ;
+ $array[4] = "KL" ;
+ ok 156, $db->status() == 0 ;
+
+ $db->partial_clear() ;
+ ok 157, $array[1] eq fillout("boat", $rec_len) ;
+ ok 158, $array[2] eq fillout("ABuse", $rec_len) ;
+ ok 159, $array[3] eq fillout("XYa", $rec_len) ;
+ ok 160, $array[4] eq fillout("KL", $rec_len) ;
+
+ # now partial put
+ $db->partial_set(3,2) ;
+ $array[1] = "PP" ;
+ ok 161, $db->status() == 0 ;
+ $array[2] = "Q" ;
+ ok 162, $db->status() != 0 ;
+ $array[3] = "XY" ;
+ ok 163, $db->status() == 0 ;
+ $array[4] = "TU" ;
+ ok 164, $db->status() == 0 ;
+
+ $db->partial_clear() ;
+ ok 165, $array[1] eq fillout("boaPP", $rec_len) ;
+ ok 166, $array[2] eq fillout("ABuse", $rec_len) ;
+ ok 167, $array[3] eq fillout("XYaXY", $rec_len) ;
+ ok 168, $array[4] eq fillout("KL TU", $rec_len) ;
+}
+
+{
+ # transaction
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 169, my $lexD = new LexDir($home);
+ my $rec_len = 9 ;
+ ok 170, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 171, my $txn = $env->txn_begin() ;
+ ok 172, my $db1 = tie @array, 'BerkeleyDB::Queue',
+ -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ,
+ -Len => $rec_len,
+ -Pad => " " ;
+
+
+ ok 173, $txn->txn_commit() == 0 ;
+ ok 174, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my @data = (
+ "boat",
+ "house",
+ "sea",
+ ) ;
+
+ my $ret = 0 ;
+ my $i ;
+ for ($i = 0 ; $i < @data ; ++$i) {
+ $ret += $db1->db_put($i, $data[$i]) ;
+ }
+ ok 175, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 176, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = (0, "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 177, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ ok 178, $txn->txn_abort() == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 179, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 180, $count == 0 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $env ;
+ untie @array ;
+}
+
+
+{
+ # db_stat
+
+ my $lex = new LexFile $Dfile ;
+ my $recs = ($BerkeleyDB::db_version >= 3.1 ? "qs_ndata" : "qs_nrecs") ;
+ my @array ;
+ my ($k, $v) ;
+ my $rec_len = 7 ;
+ ok 181, my $db = new BerkeleyDB::Queue -Filename => $Dfile,
+ -Flags => DB_CREATE,
+ -Pagesize => 4 * 1024,
+ -Len => $rec_len,
+ -Pad => " "
+ ;
+
+ my $ref = $db->db_stat() ;
+ ok 182, $ref->{$recs} == 0;
+ ok 183, $ref->{'qs_pagesize'} == 4 * 1024;
+
+ # create some data
+ my @data = (
+ 2,
+ "house",
+ "sea",
+ ) ;
+
+ my $ret = 0 ;
+ my $i ;
+ for ($i = $db->ArrayOffset ; @data ; ++$i) {
+ $ret += $db->db_put($i, shift @data) ;
+ }
+ ok 184, $ret == 0 ;
+
+ $ref = $db->db_stat() ;
+ ok 185, $ref->{$recs} == 3;
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use strict ;
+ use vars qw( @ISA @EXPORT) ;
+
+ require Exporter ;
+ use BerkeleyDB;
+ @ISA=qw(BerkeleyDB::Queue);
+ @EXPORT = @BerkeleyDB::EXPORT ;
+
+ sub db_put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::db_put($key, $value * 3) ;
+ }
+
+ sub db_get {
+ my $self = shift ;
+ $self->SUPER::db_get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE ;
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok 186, $@ eq "" ;
+ my @h ;
+ my $X ;
+ my $rec_len = 34 ;
+ eval '
+ $X = tie(@h, "SubDB", -Filename => "dbqueue.tmp",
+ -Flags => DB_CREATE,
+ -Mode => 0640 ,
+ -Len => $rec_len,
+ -Pad => " "
+ );
+ ' ;
+
+ main::ok 187, $@ eq "" ;
+
+ my $ret = eval '$h[1] = 3 ; return $h[1] ' ;
+ main::ok 188, $@ eq "" ;
+ main::ok 189, $ret == 7 ;
+
+ my $value = 0;
+ $ret = eval '$X->db_put(1, 4) ; $X->db_get(1, $value) ; return $value' ;
+ main::ok 190, $@ eq "" ;
+ main::ok 191, $ret == 10 ;
+
+ $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
+ main::ok 192, $@ eq "" ;
+ main::ok 193, $ret == 1 ;
+
+ $ret = eval '$X->A_new_method(1) ' ;
+ main::ok 194, $@ eq "" ;
+ main::ok 195, $ret eq "[[10]]" ;
+
+ undef $X ;
+ untie @h ;
+ unlink "SubDB.pm", "dbqueue.tmp" ;
+
+}
+
+{
+ # DB_APPEND
+
+ my $lex = new LexFile $Dfile;
+ my @array ;
+ my $value ;
+ my $rec_len = 21 ;
+ ok 196, my $db = tie @array, 'BerkeleyDB::Queue',
+ -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Len => $rec_len,
+ -Pad => " " ;
+
+ # create a few records
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+
+ my $k = 0 ;
+ ok 197, $db->db_put($k, "fred", DB_APPEND) == 0 ;
+ ok 198, $k == 4 ;
+ ok 199, $array[4] eq fillout("fred", $rec_len) ;
+
+ undef $db ;
+ untie @array ;
+}
+
+{
+ # 23 Sept 2001 -- push into an empty array
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $db ;
+ my $rec_len = 21 ;
+ ok 200, $db = tie @array, 'BerkeleyDB::Queue',
+ -Flags => DB_CREATE ,
+ -ArrayBase => 0,
+ -Len => $rec_len,
+ -Pad => " " ,
+ -Filename => $Dfile ;
+ $FA ? push @array, "first"
+ : $db->push("first") ;
+
+ ok 201, ($FA ? pop @array : $db->pop()) eq fillout("first", $rec_len) ;
+
+ undef $db;
+ untie @array ;
+
+}
+
+__END__
+
+
+# TODO
+#
+# DB_DELIMETER DB_FIXEDLEN DB_PAD DB_SNAPSHOT with partial records
diff --git a/bdb/perl/BerkeleyDB/t/recno.t b/bdb/perl/BerkeleyDB/t/recno.t
new file mode 100644
index 00000000000..64b1803f736
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/recno.t
@@ -0,0 +1,913 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..226\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+# Check for invalid parameters
+{
+ # Check for invalid parameters
+ my $db ;
+ eval ' $db = new BerkeleyDB::Recno -Stupid => 3 ; ' ;
+ ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' $db = new BerkeleyDB::Recno -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
+ ok 2, $@ =~ /unknown key value\(s\) / ;
+
+ eval ' $db = new BerkeleyDB::Recno -Env => 2 ' ;
+ ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+
+ eval ' $db = new BerkeleyDB::Recno -Txn => "x" ' ;
+ ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
+
+ my $obj = bless [], "main" ;
+ eval ' $db = new BerkeleyDB::Recno -Env => $obj ' ;
+ ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+}
+
+# Now check the interface to Recno
+
+{
+ my $lex = new LexFile $Dfile ;
+
+ ok 6, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my $value ;
+ my $status ;
+ ok 7, $db->db_put(1, "some value") == 0 ;
+ ok 8, $db->status() == 0 ;
+ ok 9, $db->db_get(1, $value) == 0 ;
+ ok 10, $value eq "some value" ;
+ ok 11, $db->db_put(2, "value") == 0 ;
+ ok 12, $db->db_get(2, $value) == 0 ;
+ ok 13, $value eq "value" ;
+ ok 14, $db->db_del(1) == 0 ;
+ ok 15, ($status = $db->db_get(1, $value)) == DB_KEYEMPTY ;
+ ok 16, $db->status() == DB_KEYEMPTY ;
+ ok 17, $db->status() eq $DB_errors{'DB_KEYEMPTY'} ;
+
+ ok 18, ($status = $db->db_get(7, $value)) == DB_NOTFOUND ;
+ ok 19, $db->status() == DB_NOTFOUND ;
+ ok 20, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
+
+ ok 21, $db->db_sync() == 0 ;
+
+ # Check NOOVERWRITE will make put fail when attempting to overwrite
+ # an existing record.
+
+ ok 22, $db->db_put( 2, 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
+ ok 23, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
+ ok 24, $db->status() == DB_KEYEXIST ;
+
+
+ # check that the value of the key has not been changed by the
+ # previous test
+ ok 25, $db->db_get(2, $value) == 0 ;
+ ok 26, $value eq "value" ;
+
+
+}
+
+
+{
+ # Check simple env works with a array.
+ my $lex = new LexFile $Dfile ;
+
+ my $home = "./fred" ;
+ ok 27, my $lexD = new LexDir($home);
+
+ ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
+ -Home => $home ;
+
+ ok 29, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
+ -Env => $env,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my $value ;
+ ok 30, $db->db_put(1, "some value") == 0 ;
+ ok 31, $db->db_get(1, $value) == 0 ;
+ ok 32, $value eq "some value" ;
+ undef $db ;
+ undef $env ;
+}
+
+
+{
+ # cursors
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my ($k, $v) ;
+ ok 33, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my @data = (
+ "red" ,
+ "green" ,
+ "blue" ,
+ ) ;
+
+ my $i ;
+ my %data ;
+ my $ret = 0 ;
+ for ($i = 0 ; $i < @data ; ++$i) {
+ $ret += $db->db_put($i, $data[$i]) ;
+ $data{$i} = $data[$i] ;
+ }
+ ok 34, $ret == 0 ;
+
+ # create the cursor
+ ok 35, my $cursor = $db->db_cursor() ;
+
+ $k = 0 ; $v = "" ;
+ my %copy = %data;
+ my $extras = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ {
+ if ( $copy{$k} eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+
+ ok 36, $cursor->status() == DB_NOTFOUND ;
+ ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 38, keys %copy == 0 ;
+ ok 39, $extras == 0 ;
+
+ # sequence backwards
+ %copy = %data ;
+ $extras = 0 ;
+ my $status ;
+ for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_PREV)) {
+ if ( $copy{$k} eq $v )
+ { delete $copy{$k} }
+ else
+ { ++ $extras }
+ }
+ ok 40, $status == DB_NOTFOUND ;
+ ok 41, $status eq $DB_errors{'DB_NOTFOUND'} ;
+ ok 42, $cursor->status() == $status ;
+ ok 43, $cursor->status() eq $status ;
+ ok 44, keys %copy == 0 ;
+ ok 45, $extras == 0 ;
+}
+
+{
+ # Tied Array interface
+
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $db ;
+ ok 46, $db = tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -Property => DB_RENUMBER,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ;
+
+ ok 47, my $cursor = (tied @array)->db_cursor() ;
+ # check the database is empty
+ my $count = 0 ;
+ my ($k, $v) = (0,"") ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 48, $cursor->status() == DB_NOTFOUND ;
+ ok 49, $count == 0 ;
+
+ ok 50, @array == 0 ;
+
+ # Add a k/v pair
+ my $value ;
+ $array[1] = "some value";
+ ok 51, (tied @array)->status() == 0 ;
+ ok 52, $array[1] eq "some value";
+ ok 53, defined $array[1];
+ ok 54, (tied @array)->status() == 0 ;
+ ok 55, !defined $array[3];
+ ok 56, (tied @array)->status() == DB_NOTFOUND ;
+
+ ok 57, (tied @array)->db_del(1) == 0 ;
+ ok 58, (tied @array)->status() == 0 ;
+ ok 59, ! defined $array[1];
+ ok 60, (tied @array)->status() == DB_NOTFOUND ;
+
+ $array[1] = 2 ;
+ $array[10] = 20 ;
+ $array[1000] = 2000 ;
+
+ my ($keys, $values) = (0,0);
+ $count = 0 ;
+ for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_NEXT)) {
+ $keys += $k ;
+ $values += $v ;
+ ++ $count ;
+ }
+ ok 61, $count == 3 ;
+ ok 62, $keys == 1011 ;
+ ok 63, $values == 2022 ;
+
+ # unshift
+ $FA ? unshift @array, "red", "green", "blue"
+ : $db->unshift("red", "green", "blue" ) ;
+ ok 64, $array[1] eq "red" ;
+ ok 65, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
+ ok 66, $k == 1 ;
+ ok 67, $v eq "red" ;
+ ok 68, $array[2] eq "green" ;
+ ok 69, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 70, $k == 2 ;
+ ok 71, $v eq "green" ;
+ ok 72, $array[3] eq "blue" ;
+ ok 73, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 74, $k == 3 ;
+ ok 75, $v eq "blue" ;
+ ok 76, $array[4] == 2 ;
+ ok 77, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+ ok 78, $k == 4 ;
+ ok 79, $v == 2 ;
+
+ # shift
+ ok 80, ($FA ? shift @array : $db->shift()) eq "red" ;
+ ok 81, ($FA ? shift @array : $db->shift()) eq "green" ;
+ ok 82, ($FA ? shift @array : $db->shift()) eq "blue" ;
+ ok 83, ($FA ? shift @array : $db->shift()) == 2 ;
+
+ # push
+ $FA ? push @array, "the", "end"
+ : $db->push("the", "end") ;
+ ok 84, $cursor->c_get($k, $v, DB_LAST) == 0 ;
+ ok 85, $k == 1001 ;
+ ok 86, $v eq "end" ;
+ ok 87, $cursor->c_get($k, $v, DB_PREV) == 0 ;
+ ok 88, $k == 1000 ;
+ ok 89, $v eq "the" ;
+ ok 90, $cursor->c_get($k, $v, DB_PREV) == 0 ;
+ ok 91, $k == 999 ;
+ ok 92, $v == 2000 ;
+
+ # pop
+ ok 93, ( $FA ? pop @array : $db->pop ) eq "end" ;
+ ok 94, ( $FA ? pop @array : $db->pop ) eq "the" ;
+ ok 95, ( $FA ? pop @array : $db->pop ) == 2000 ;
+
+ # now clear the array
+ $FA ? @array = ()
+ : $db->clear() ;
+ ok 96, $cursor->c_get($k, $v, DB_FIRST) == DB_NOTFOUND ;
+
+ undef $cursor ;
+ undef $db ;
+ untie @array ;
+}
+
+{
+ # in-memory file
+
+ my @array ;
+ my $fd ;
+ my $value ;
+ ok 97, my $db = tie @array, 'BerkeleyDB::Recno' ;
+
+ ok 98, $db->db_put(1, "some value") == 0 ;
+ ok 99, $db->db_get(1, $value) == 0 ;
+ ok 100, $value eq "some value" ;
+
+}
+
+{
+ # partial
+ # check works via API
+
+ my $lex = new LexFile $Dfile ;
+ my $value ;
+ ok 101, my $db = new BerkeleyDB::Recno, -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my @data = (
+ "",
+ "boat",
+ "house",
+ "sea",
+ ) ;
+
+ my $ret = 0 ;
+ my $i ;
+ for ($i = 1 ; $i < @data ; ++$i) {
+ $ret += $db->db_put($i, $data[$i]) ;
+ }
+ ok 102, $ret == 0 ;
+
+
+ # do a partial get
+ my ($pon, $off, $len) = $db->partial_set(0,2) ;
+ ok 103, ! $pon && $off == 0 && $len == 0 ;
+ ok 104, $db->db_get(1, $value) == 0 && $value eq "bo" ;
+ ok 105, $db->db_get(2, $value) == 0 && $value eq "ho" ;
+ ok 106, $db->db_get(3, $value) == 0 && $value eq "se" ;
+
+ # do a partial get, off end of data
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 107, $pon ;
+ ok 108, $off == 0 ;
+ ok 109, $len == 2 ;
+ ok 110, $db->db_get(1, $value) == 0 && $value eq "t" ;
+ ok 111, $db->db_get(2, $value) == 0 && $value eq "se" ;
+ ok 112, $db->db_get(3, $value) == 0 && $value eq "" ;
+
+ # switch of partial mode
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 113, $pon ;
+ ok 114, $off == 3 ;
+ ok 115, $len == 2 ;
+ ok 116, $db->db_get(1, $value) == 0 && $value eq "boat" ;
+ ok 117, $db->db_get(2, $value) == 0 && $value eq "house" ;
+ ok 118, $db->db_get(3, $value) == 0 && $value eq "sea" ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ ok 119, $db->db_put(1, "") == 0 ;
+ ok 120, $db->db_put(2, "AB") == 0 ;
+ ok 121, $db->db_put(3, "XYZ") == 0 ;
+ ok 122, $db->db_put(4, "KLM") == 0 ;
+
+ ($pon, $off, $len) = $db->partial_clear() ;
+ ok 123, $pon ;
+ ok 124, $off == 0 ;
+ ok 125, $len == 2 ;
+ ok 126, $db->db_get(1, $value) == 0 && $value eq "at" ;
+ ok 127, $db->db_get(2, $value) == 0 && $value eq "ABuse" ;
+ ok 128, $db->db_get(3, $value) == 0 && $value eq "XYZa" ;
+ ok 129, $db->db_get(4, $value) == 0 && $value eq "KLM" ;
+
+ # now partial put
+ ($pon, $off, $len) = $db->partial_set(3,2) ;
+ ok 130, ! $pon ;
+ ok 131, $off == 0 ;
+ ok 132, $len == 0 ;
+ ok 133, $db->db_put(1, "PPP") == 0 ;
+ ok 134, $db->db_put(2, "Q") == 0 ;
+ ok 135, $db->db_put(3, "XYZ") == 0 ;
+ ok 136, $db->db_put(4, "TU") == 0 ;
+
+ $db->partial_clear() ;
+ ok 137, $db->db_get(1, $value) == 0 && $value eq "at\0PPP" ;
+ ok 138, $db->db_get(2, $value) == 0 && $value eq "ABuQ" ;
+ ok 139, $db->db_get(3, $value) == 0 && $value eq "XYZXYZ" ;
+ ok 140, $db->db_get(4, $value) == 0 && $value eq "KLMTU" ;
+}
+
+{
+ # partial
+ # check works via tied array
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $value ;
+ ok 141, my $db = tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create some data
+ my @data = (
+ "",
+ "boat",
+ "house",
+ "sea",
+ ) ;
+
+ my $i ;
+ for ($i = 1 ; $i < @data ; ++$i) {
+ $array[$i] = $data[$i] ;
+ }
+
+
+ # do a partial get
+ $db->partial_set(0,2) ;
+ ok 142, $array[1] eq "bo" ;
+ ok 143, $array[2] eq "ho" ;
+ ok 144, $array[3] eq "se" ;
+
+ # do a partial get, off end of data
+ $db->partial_set(3,2) ;
+ ok 145, $array[1] eq "t" ;
+ ok 146, $array[2] eq "se" ;
+ ok 147, $array[3] eq "" ;
+
+ # switch of partial mode
+ $db->partial_clear() ;
+ ok 148, $array[1] eq "boat" ;
+ ok 149, $array[2] eq "house" ;
+ ok 150, $array[3] eq "sea" ;
+
+ # now partial put
+ $db->partial_set(0,2) ;
+ ok 151, $array[1] = "" ;
+ ok 152, $array[2] = "AB" ;
+ ok 153, $array[3] = "XYZ" ;
+ ok 154, $array[4] = "KLM" ;
+
+ $db->partial_clear() ;
+ ok 155, $array[1] eq "at" ;
+ ok 156, $array[2] eq "ABuse" ;
+ ok 157, $array[3] eq "XYZa" ;
+ ok 158, $array[4] eq "KLM" ;
+
+ # now partial put
+ $db->partial_set(3,2) ;
+ ok 159, $array[1] = "PPP" ;
+ ok 160, $array[2] = "Q" ;
+ ok 161, $array[3] = "XYZ" ;
+ ok 162, $array[4] = "TU" ;
+
+ $db->partial_clear() ;
+ ok 163, $array[1] eq "at\0PPP" ;
+ ok 164, $array[2] eq "ABuQ" ;
+ ok 165, $array[3] eq "XYZXYZ" ;
+ ok 166, $array[4] eq "KLMTU" ;
+}
+
+{
+ # transaction
+
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 167, my $lexD = new LexDir($home);
+ ok 168, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 169, my $txn = $env->txn_begin() ;
+ ok 170, my $db1 = tie @array, 'BerkeleyDB::Recno',
+ -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+
+ ok 171, $txn->txn_commit() == 0 ;
+ ok 172, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my @data = (
+ "boat",
+ "house",
+ "sea",
+ ) ;
+
+ my $ret = 0 ;
+ my $i ;
+ for ($i = 0 ; $i < @data ; ++$i) {
+ $ret += $db1->db_put($i, $data[$i]) ;
+ }
+ ok 173, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 174, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = (0, "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 175, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ ok 176, $txn->txn_abort() == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 177, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 178, $count == 0 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $env ;
+ untie @array ;
+}
+
+
+{
+ # db_stat
+
+ my $lex = new LexFile $Dfile ;
+ my $recs = ($BerkeleyDB::db_version >= 3.1 ? "bt_ndata" : "bt_nrecs") ;
+ my @array ;
+ my ($k, $v) ;
+ ok 179, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
+ -Flags => DB_CREATE,
+ -Pagesize => 4 * 1024,
+ ;
+
+ my $ref = $db->db_stat() ;
+ ok 180, $ref->{$recs} == 0;
+ ok 181, $ref->{'bt_pagesize'} == 4 * 1024;
+
+ # create some data
+ my @data = (
+ 2,
+ "house",
+ "sea",
+ ) ;
+
+ my $ret = 0 ;
+ my $i ;
+ for ($i = $db->ArrayOffset ; @data ; ++$i) {
+ $ret += $db->db_put($i, shift @data) ;
+ }
+ ok 182, $ret == 0 ;
+
+ $ref = $db->db_stat() ;
+ ok 183, $ref->{$recs} == 3;
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use strict ;
+ use vars qw( @ISA @EXPORT) ;
+
+ require Exporter ;
+ use BerkeleyDB;
+ @ISA=qw(BerkeleyDB::Recno);
+ @EXPORT = @BerkeleyDB::EXPORT ;
+
+ sub db_put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::db_put($key, $value * 3) ;
+ }
+
+ sub db_get {
+ my $self = shift ;
+ $self->SUPER::db_get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE ;
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok 184, $@ eq "" ;
+ my @h ;
+ my $X ;
+ eval '
+ $X = tie(@h, "SubDB", -Filename => "dbrecno.tmp",
+ -Flags => DB_CREATE,
+ -Mode => 0640 );
+ ' ;
+
+ main::ok 185, $@ eq "" ;
+
+ my $ret = eval '$h[1] = 3 ; return $h[1] ' ;
+ main::ok 186, $@ eq "" ;
+ main::ok 187, $ret == 7 ;
+
+ my $value = 0;
+ $ret = eval '$X->db_put(1, 4) ; $X->db_get(1, $value) ; return $value' ;
+ main::ok 188, $@ eq "" ;
+ main::ok 189, $ret == 10 ;
+
+ $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
+ main::ok 190, $@ eq "" ;
+ main::ok 191, $ret == 1 ;
+
+ $ret = eval '$X->A_new_method(1) ' ;
+ main::ok 192, $@ eq "" ;
+ main::ok 193, $ret eq "[[10]]" ;
+
+ undef $X;
+ untie @h;
+ unlink "SubDB.pm", "dbrecno.tmp" ;
+
+}
+
+{
+ # variable length records, DB_DELIMETER -- defaults to \n
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 194, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Source => $Dfile2 ;
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 195, $x eq "abc\ndef\n\nghi\n" ;
+}
+
+{
+ # variable length records, change DB_DELIMETER
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 196, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Source => $Dfile2 ,
+ -Delim => "-";
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 197, $x eq "abc-def--ghi-";
+}
+
+{
+ # fixed length records, default DB_PAD
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 198, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Len => 5,
+ -Source => $Dfile2 ;
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 199, $x eq "abc def ghi " ;
+}
+
+{
+ # fixed length records, change Pad
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 200, tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Len => 5,
+ -Pad => "-",
+ -Source => $Dfile2 ;
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 201, $x eq "abc--def-------ghi--" ;
+}
+
+{
+ # DB_RENUMBER
+
+ my $lex = new LexFile $Dfile;
+ my @array ;
+ my $value ;
+ ok 202, my $db = tie @array, 'BerkeleyDB::Recno', -Filename => $Dfile,
+ -Property => DB_RENUMBER,
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ;
+ # create a few records
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+
+ ok 203, my ($length, $joined) = joiner($db, "|") ;
+ ok 204, $length == 3 ;
+ ok 205, $joined eq "abc|def|ghi";
+
+ ok 206, $db->db_del(1) == 0 ;
+ ok 207, ($length, $joined) = joiner($db, "|") ;
+ ok 208, $length == 2 ;
+ ok 209, $joined eq "abc|ghi";
+
+ undef $db ;
+ untie @array ;
+
+}
+
+{
+ # DB_APPEND
+
+ my $lex = new LexFile $Dfile;
+ my @array ;
+ my $value ;
+ ok 210, my $db = tie @array, 'BerkeleyDB::Recno',
+ -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # create a few records
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+
+ my $k = 0 ;
+ ok 211, $db->db_put($k, "fred", DB_APPEND) == 0 ;
+ ok 212, $k == 4 ;
+
+ undef $db ;
+ untie @array ;
+}
+
+{
+ # in-memory Btree with an associated text file
+
+ my $lex = new LexFile $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 213, tie @array, 'BerkeleyDB::Recno', -Source => $Dfile2 ,
+ -ArrayBase => 0,
+ -Property => DB_RENUMBER,
+ -Flags => DB_CREATE ;
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 214, $x eq "abc\ndef\n\nghi\n" ;
+}
+
+{
+ # in-memory, variable length records, change DB_DELIMETER
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 215, tie @array, 'BerkeleyDB::Recno',
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Source => $Dfile2 ,
+ -Property => DB_RENUMBER,
+ -Delim => "-";
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 216, $x eq "abc-def--ghi-";
+}
+
+{
+ # in-memory, fixed length records, default DB_PAD
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 217, tie @array, 'BerkeleyDB::Recno', -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Property => DB_RENUMBER,
+ -Len => 5,
+ -Source => $Dfile2 ;
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 218, $x eq "abc def ghi " ;
+}
+
+{
+ # in-memory, fixed length records, change Pad
+
+ my $lex = new LexFile $Dfile, $Dfile2 ;
+ touch $Dfile2 ;
+ my @array ;
+ my $value ;
+ ok 219, tie @array, 'BerkeleyDB::Recno',
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Property => DB_RENUMBER,
+ -Len => 5,
+ -Pad => "-",
+ -Source => $Dfile2 ;
+ $array[0] = "abc" ;
+ $array[1] = "def" ;
+ $array[3] = "ghi" ;
+ untie @array ;
+
+ my $x = docat($Dfile2) ;
+ ok 220, $x eq "abc--def-------ghi--" ;
+}
+
+{
+ # 23 Sept 2001 -- push into an empty array
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $db ;
+ ok 221, $db = tie @array, 'BerkeleyDB::Recno',
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Property => DB_RENUMBER,
+ -Filename => $Dfile ;
+ $FA ? push @array, "first"
+ : $db->push("first") ;
+
+ ok 222, $array[0] eq "first" ;
+ ok 223, $FA ? pop @array : $db->pop() eq "first" ;
+
+ undef $db;
+ untie @array ;
+
+}
+
+{
+ # 23 Sept 2001 -- unshift into an empty array
+ my $lex = new LexFile $Dfile ;
+ my @array ;
+ my $db ;
+ ok 224, $db = tie @array, 'BerkeleyDB::Recno',
+ -ArrayBase => 0,
+ -Flags => DB_CREATE ,
+ -Property => DB_RENUMBER,
+ -Filename => $Dfile ;
+ $FA ? unshift @array, "first"
+ : $db->unshift("first") ;
+
+ ok 225, $array[0] eq "first" ;
+ ok 226, ($FA ? shift @array : $db->shift()) eq "first" ;
+
+ undef $db;
+ untie @array ;
+
+}
+__END__
+
+
+# TODO
+#
+# DB_DELIMETER DB_FIXEDLEN DB_PAD DB_SNAPSHOT with partial records
diff --git a/bdb/perl/BerkeleyDB/t/strict.t b/bdb/perl/BerkeleyDB/t/strict.t
new file mode 100644
index 00000000000..ab41d44cb41
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/strict.t
@@ -0,0 +1,174 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..44\n";
+
+my $Dfile = "dbhash.tmp";
+my $home = "./fred" ;
+
+umask(0);
+
+{
+ # closing a database & an environment in the correct order.
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $status ;
+
+ ok 1, my $lexD = new LexDir($home);
+ ok 2, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+
+ ok 3, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env;
+
+ ok 4, $db1->db_close() == 0 ;
+
+ eval { $status = $env->db_appexit() ; } ;
+ ok 5, $status == 0 ;
+ ok 6, $@ eq "" ;
+ #print "[$@]\n" ;
+
+}
+
+{
+ # closing an environment with an open database
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+
+ ok 7, my $lexD = new LexDir($home);
+ ok 8, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+
+ ok 9, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env;
+
+ eval { $env->db_appexit() ; } ;
+ ok 10, $@ =~ /BerkeleyDB Aborting: attempted to close an environment with 1 open database/ ;
+ #print "[$@]\n" ;
+
+ undef $db1 ;
+ untie %hash ;
+ undef $env ;
+}
+
+{
+ # closing a transaction & a database
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $status ;
+
+ ok 11, my $lexD = new LexDir($home);
+ ok 12, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+
+ ok 13, my $txn = $env->txn_begin() ;
+ ok 14, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ ok 15, $txn->txn_commit() == 0 ;
+ eval { $status = $db->db_close() ; } ;
+ ok 16, $status == 0 ;
+ ok 17, $@ eq "" ;
+ #print "[$@]\n" ;
+ eval { $status = $env->db_appexit() ; } ;
+ ok 18, $status == 0 ;
+ ok 19, $@ eq "" ;
+ #print "[$@]\n" ;
+}
+
+{
+ # closing a database with an open transaction
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+
+ ok 20, my $lexD = new LexDir($home);
+ ok 21, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+
+ ok 22, my $txn = $env->txn_begin() ;
+ ok 23, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ eval { $db->db_close() ; } ;
+ ok 24, $@ =~ /BerkeleyDB Aborting: attempted to close a database while a transaction was still open at/ ;
+ #print "[$@]\n" ;
+}
+
+{
+ # closing a cursor & a database
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $status ;
+ ok 25, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+ ok 26, my $cursor = $db->db_cursor() ;
+ ok 27, $cursor->c_close() == 0 ;
+ eval { $status = $db->db_close() ; } ;
+ ok 28, $status == 0 ;
+ ok 29, $@ eq "" ;
+ #print "[$@]\n" ;
+}
+
+{
+ # closing a database with an open cursor
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ ok 30, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+ ok 31, my $cursor = $db->db_cursor() ;
+ eval { $db->db_close() ; } ;
+ ok 32, $@ =~ /\QBerkeleyDB Aborting: attempted to close a database with 1 open cursor(s) at/;
+ #print "[$@]\n" ;
+}
+
+{
+ # closing a transaction & a cursor
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $status ;
+
+ ok 33, my $lexD = new LexDir($home);
+ ok 34, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 35, my $txn = $env->txn_begin() ;
+ ok 36, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+ ok 37, my $cursor = $db->db_cursor() ;
+ eval { $status = $cursor->c_close() ; } ;
+ ok 38, $status == 0 ;
+ ok 39, ($status = $txn->txn_commit()) == 0 ;
+ ok 40, $@ eq "" ;
+ eval { $status = $db->db_close() ; } ;
+ ok 41, $status == 0 ;
+ ok 42, $@ eq "" ;
+ #print "[$@]\n" ;
+ eval { $status = $env->db_appexit() ; } ;
+ ok 43, $status == 0 ;
+ ok 44, $@ eq "" ;
+ #print "[$@]\n" ;
+}
+
diff --git a/bdb/perl/BerkeleyDB/t/subdb.t b/bdb/perl/BerkeleyDB/t/subdb.t
new file mode 100644
index 00000000000..23016d6463f
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/subdb.t
@@ -0,0 +1,243 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+BEGIN
+{
+ if ($BerkeleyDB::db_version < 3) {
+ print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
+ exit 0 ;
+ }
+}
+
+print "1..43\n";
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $Dfile3 = "dbhash3.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+# Berkeley DB 3.x specific functionality
+
+# Check for invalid parameters
+{
+ # Check for invalid parameters
+ my $db ;
+ eval ' BerkeleyDB::db_remove -Stupid => 3 ; ' ;
+ ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' BerkeleyDB::db_remove -Bad => 2, -Filename => "fred", -Stupid => 3; ' ;
+ ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
+
+ eval ' BerkeleyDB::db_remove -Filename => "a", -Env => 2 ' ;
+ ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+
+ eval ' BerkeleyDB::db_remove -Subname => "a"' ;
+ ok 4, $@ =~ /^Must specify a filename/ ;
+
+ my $obj = bless [], "main" ;
+ eval ' BerkeleyDB::db_remove -Filename => "x", -Env => $obj ' ;
+ ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+}
+
+{
+ # subdatabases
+
+ # opening a subdatabse in an exsiting database that doesn't have
+ # subdatabases at all should fail
+
+ my $lex = new LexFile $Dfile ;
+
+ ok 6, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my %data = qw(
+ red sky
+ blue sea
+ black heart
+ yellow belley
+ green grass
+ ) ;
+
+ ok 7, addData($db, %data) ;
+
+ undef $db ;
+
+ $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Subname => "fred" ;
+ ok 8, ! $db ;
+
+ ok 9, -e $Dfile ;
+ ok 10, ! BerkeleyDB::db_remove(-Filename => $Dfile) ;
+}
+
+{
+ # subdatabases
+
+ # opening a subdatabse in an exsiting database that does have
+ # subdatabases at all, but not this one
+
+ my $lex = new LexFile $Dfile ;
+
+ ok 11, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Subname => "fred" ,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my %data = qw(
+ red sky
+ blue sea
+ black heart
+ yellow belley
+ green grass
+ ) ;
+
+ ok 12, addData($db, %data) ;
+
+ undef $db ;
+
+ $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Subname => "joe" ;
+
+ ok 13, !$db ;
+
+}
+
+{
+ # subdatabases
+
+ my $lex = new LexFile $Dfile ;
+
+ ok 14, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Subname => "fred" ,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my %data = qw(
+ red sky
+ blue sea
+ black heart
+ yellow belley
+ green grass
+ ) ;
+
+ ok 15, addData($db, %data) ;
+
+ undef $db ;
+
+ ok 16, $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Subname => "fred" ;
+
+ ok 17, my $cursor = $db->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $status ;
+ while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
+ if ($data{$k} eq $v) {
+ delete $data{$k} ;
+ }
+ }
+ ok 18, $status == DB_NOTFOUND ;
+ ok 19, keys %data == 0 ;
+}
+
+{
+ # subdatabases
+
+ # opening a database with multiple subdatabases - handle should be a list
+ # of the subdatabase names
+
+ my $lex = new LexFile $Dfile ;
+
+ ok 20, my $db1 = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Subname => "fred" ,
+ -Flags => DB_CREATE ;
+
+ ok 21, my $db2 = new BerkeleyDB::Btree -Filename => $Dfile,
+ -Subname => "joe" ,
+ -Flags => DB_CREATE ;
+
+ # Add a k/v pair
+ my %data = qw(
+ red sky
+ blue sea
+ black heart
+ yellow belley
+ green grass
+ ) ;
+
+ ok 22, addData($db1, %data) ;
+ ok 23, addData($db2, %data) ;
+
+ undef $db1 ;
+ undef $db2 ;
+
+ ok 24, my $db = new BerkeleyDB::Unknown -Filename => $Dfile ,
+ -Flags => DB_RDONLY ;
+
+ #my $type = $db->type() ; print "type $type\n" ;
+ ok 25, my $cursor = $db->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $status ;
+ my @dbnames = () ;
+ while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
+ push @dbnames, $k ;
+ }
+ ok 26, $status == DB_NOTFOUND ;
+ ok 27, join(",", sort @dbnames) eq "fred,joe" ;
+ undef $db ;
+
+ ok 28, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "harry") != 0;
+ ok 29, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "fred") == 0 ;
+
+ # should only be one subdatabase
+ ok 30, $db = new BerkeleyDB::Unknown -Filename => $Dfile ,
+ -Flags => DB_RDONLY ;
+
+ ok 31, $cursor = $db->db_cursor() ;
+ @dbnames = () ;
+ while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
+ push @dbnames, $k ;
+ }
+ ok 32, $status == DB_NOTFOUND ;
+ ok 33, join(",", sort @dbnames) eq "joe" ;
+ undef $db ;
+
+ # can't delete an already deleted subdatabase
+ ok 34, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "fred") != 0;
+
+ ok 35, BerkeleyDB::db_remove(-Filename => $Dfile, -Subname => "joe") == 0 ;
+
+ # should only be one subdatabase
+ ok 36, $db = new BerkeleyDB::Unknown -Filename => $Dfile ,
+ -Flags => DB_RDONLY ;
+
+ ok 37, $cursor = $db->db_cursor() ;
+ @dbnames = () ;
+ while (($status = $cursor->c_get($k, $v, DB_NEXT)) == 0) {
+ push @dbnames, $k ;
+ }
+ ok 38, $status == DB_NOTFOUND ;
+ ok 39, @dbnames == 0 ;
+ undef $db ;
+ undef $cursor ;
+
+ ok 40, -e $Dfile ;
+ ok 41, BerkeleyDB::db_remove(-Filename => $Dfile) == 0 ;
+ ok 42, ! -e $Dfile ;
+ ok 43, BerkeleyDB::db_remove(-Filename => $Dfile) != 0 ;
+}
+
+# db_remove with env
diff --git a/bdb/perl/BerkeleyDB/t/txn.t b/bdb/perl/BerkeleyDB/t/txn.t
new file mode 100644
index 00000000000..ba6b636cdc8
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/txn.t
@@ -0,0 +1,320 @@
+#!./perl -w
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..58\n";
+
+my $Dfile = "dbhash.tmp";
+
+umask(0);
+
+{
+ # error cases
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 1, my $lexD = new LexDir($home);
+ ok 2, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE| DB_INIT_MPOOL;
+ eval { $env->txn_begin() ; } ;
+ ok 3, $@ =~ /^BerkeleyDB Aborting: Transaction Manager not enabled at/ ;
+
+ eval { my $txn_mgr = $env->TxnMgr() ; } ;
+ ok 4, $@ =~ /^BerkeleyDB Aborting: Transaction Manager not enabled at/ ;
+ undef $env ;
+
+}
+
+{
+ # transaction - abort works
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 5, my $lexD = new LexDir($home);
+ ok 6, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 7, my $txn = $env->txn_begin() ;
+ ok 8, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+
+ ok 9, $txn->txn_commit() == 0 ;
+ ok 10, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 11, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 12, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 13, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ ok 14, $txn->txn_abort() == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 15, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 16, $count == 0 ;
+
+ my $stat = $env->txn_stat() ;
+ ok 17, $stat->{'st_naborts'} == 1 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $env ;
+ untie %hash ;
+}
+
+{
+ # transaction - abort works via txnmgr
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 18, my $lexD = new LexDir($home);
+ ok 19, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 20, my $txn_mgr = $env->TxnMgr() ;
+ ok 21, my $txn = $txn_mgr->txn_begin() ;
+ ok 22, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ ok 23, $txn->txn_commit() == 0 ;
+ ok 24, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 25, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 26, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 27, $count == 3 ;
+ undef $cursor ;
+
+ # now abort the transaction
+ ok 28, $txn->txn_abort() == 0 ;
+
+ # there shouldn't be any records in the database
+ $count = 0 ;
+ # sequence forwards
+ ok 29, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 30, $count == 0 ;
+
+ my $stat = $txn_mgr->txn_stat() ;
+ ok 31, $stat->{'st_naborts'} == 1 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $txn_mgr ;
+ undef $env ;
+ untie %hash ;
+}
+
+{
+ # transaction - commit works
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 32, my $lexD = new LexDir($home);
+ ok 33, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 34, my $txn = $env->txn_begin() ;
+ ok 35, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+
+ ok 36, $txn->txn_commit() == 0 ;
+ ok 37, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 38, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 39, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 40, $count == 3 ;
+ undef $cursor ;
+
+ # now commit the transaction
+ ok 41, $txn->txn_commit() == 0 ;
+
+ $count = 0 ;
+ # sequence forwards
+ ok 42, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 43, $count == 3 ;
+
+ my $stat = $env->txn_stat() ;
+ ok 44, $stat->{'st_naborts'} == 0 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $env ;
+ untie %hash ;
+}
+
+{
+ # transaction - commit works via txnmgr
+
+ my $lex = new LexFile $Dfile ;
+ my %hash ;
+ my $value ;
+
+ my $home = "./fred" ;
+ ok 45, my $lexD = new LexDir($home);
+ ok 46, my $env = new BerkeleyDB::Env -Home => $home,
+ -Flags => DB_CREATE|DB_INIT_TXN|
+ DB_INIT_MPOOL|DB_INIT_LOCK ;
+ ok 47, my $txn_mgr = $env->TxnMgr() ;
+ ok 48, my $txn = $txn_mgr->txn_begin() ;
+ ok 49, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
+ -Flags => DB_CREATE ,
+ -Env => $env,
+ -Txn => $txn ;
+
+ ok 50, $txn->txn_commit() == 0 ;
+ ok 51, $txn = $env->txn_begin() ;
+ $db1->Txn($txn);
+
+ # create some data
+ my %data = (
+ "red" => "boat",
+ "green" => "house",
+ "blue" => "sea",
+ ) ;
+
+ my $ret = 0 ;
+ while (my ($k, $v) = each %data) {
+ $ret += $db1->db_put($k, $v) ;
+ }
+ ok 52, $ret == 0 ;
+
+ # should be able to see all the records
+
+ ok 53, my $cursor = $db1->db_cursor() ;
+ my ($k, $v) = ("", "") ;
+ my $count = 0 ;
+ # sequence forwards
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 54, $count == 3 ;
+ undef $cursor ;
+
+ # now commit the transaction
+ ok 55, $txn->txn_commit() == 0 ;
+
+ $count = 0 ;
+ # sequence forwards
+ ok 56, $cursor = $db1->db_cursor() ;
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
+ ++ $count ;
+ }
+ ok 57, $count == 3 ;
+
+ my $stat = $txn_mgr->txn_stat() ;
+ ok 58, $stat->{'st_naborts'} == 0 ;
+
+ undef $txn ;
+ undef $cursor ;
+ undef $db1 ;
+ undef $txn_mgr ;
+ undef $env ;
+ untie %hash ;
+}
+
diff --git a/bdb/perl/BerkeleyDB/t/unknown.t b/bdb/perl/BerkeleyDB/t/unknown.t
new file mode 100644
index 00000000000..f2630b585c0
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/unknown.t
@@ -0,0 +1,176 @@
+#!./perl -w
+
+# ID: %I%, %G%
+
+use strict ;
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use BerkeleyDB;
+use t::util ;
+
+print "1..41\n";
+
+my $Dfile = "dbhash.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+
+# Check for invalid parameters
+{
+ # Check for invalid parameters
+ my $db ;
+ eval ' $db = new BerkeleyDB::Unknown -Stupid => 3 ; ' ;
+ ok 1, $@ =~ /unknown key value\(s\) Stupid/ ;
+
+ eval ' $db = new BerkeleyDB::Unknown -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
+ ok 2, $@ =~ /unknown key value\(s\) (Bad |Stupid ){2}/ ;
+
+ eval ' $db = new BerkeleyDB::Unknown -Env => 2 ' ;
+ ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+
+ eval ' $db = new BerkeleyDB::Unknown -Txn => "fred" ' ;
+ ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
+
+ my $obj = bless [], "main" ;
+ eval ' $db = new BerkeleyDB::Unknown -Env => $obj ' ;
+ ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
+}
+
+# check the interface to a rubbish database
+{
+ # first an empty file
+ my $lex = new LexFile $Dfile ;
+ ok 6, writeFile($Dfile, "") ;
+
+ ok 7, ! (new BerkeleyDB::Unknown -Filename => $Dfile);
+
+ # now a non-database file
+ writeFile($Dfile, "\x2af6") ;
+ ok 8, ! (new BerkeleyDB::Unknown -Filename => $Dfile);
+}
+
+# check the interface to a Hash database
+
+{
+ my $lex = new LexFile $Dfile ;
+
+ # create a hash database
+ ok 9, my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a few k/v pairs
+ my $value ;
+ my $status ;
+ ok 10, $db->db_put("some key", "some value") == 0 ;
+ ok 11, $db->db_put("key", "value") == 0 ;
+
+ # close the database
+ undef $db ;
+
+ # now open it with Unknown
+ ok 12, $db = new BerkeleyDB::Unknown -Filename => $Dfile;
+
+ ok 13, $db->type() == DB_HASH ;
+ ok 14, $db->db_get("some key", $value) == 0 ;
+ ok 15, $value eq "some value" ;
+ ok 16, $db->db_get("key", $value) == 0 ;
+ ok 17, $value eq "value" ;
+
+ my @array ;
+ eval { $db->Tie(\@array)} ;
+ ok 18, $@ =~ /^Tie needs a reference to a hash/ ;
+
+ my %hash ;
+ $db->Tie(\%hash) ;
+ ok 19, $hash{"some key"} eq "some value" ;
+
+}
+
+# check the interface to a Btree database
+
+{
+ my $lex = new LexFile $Dfile ;
+
+ # create a hash database
+ ok 20, my $db = new BerkeleyDB::Btree -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a few k/v pairs
+ my $value ;
+ my $status ;
+ ok 21, $db->db_put("some key", "some value") == 0 ;
+ ok 22, $db->db_put("key", "value") == 0 ;
+
+ # close the database
+ undef $db ;
+
+ # now open it with Unknown
+ # create a hash database
+ ok 23, $db = new BerkeleyDB::Unknown -Filename => $Dfile;
+
+ ok 24, $db->type() == DB_BTREE ;
+ ok 25, $db->db_get("some key", $value) == 0 ;
+ ok 26, $value eq "some value" ;
+ ok 27, $db->db_get("key", $value) == 0 ;
+ ok 28, $value eq "value" ;
+
+
+ my @array ;
+ eval { $db->Tie(\@array)} ;
+ ok 29, $@ =~ /^Tie needs a reference to a hash/ ;
+
+ my %hash ;
+ $db->Tie(\%hash) ;
+ ok 30, $hash{"some key"} eq "some value" ;
+
+
+}
+
+# check the interface to a Recno database
+
+{
+ my $lex = new LexFile $Dfile ;
+
+ # create a recno database
+ ok 31, my $db = new BerkeleyDB::Recno -Filename => $Dfile,
+ -Flags => DB_CREATE ;
+
+ # Add a few k/v pairs
+ my $value ;
+ my $status ;
+ ok 32, $db->db_put(0, "some value") == 0 ;
+ ok 33, $db->db_put(1, "value") == 0 ;
+
+ # close the database
+ undef $db ;
+
+ # now open it with Unknown
+ # create a hash database
+ ok 34, $db = new BerkeleyDB::Unknown -Filename => $Dfile;
+
+ ok 35, $db->type() == DB_RECNO ;
+ ok 36, $db->db_get(0, $value) == 0 ;
+ ok 37, $value eq "some value" ;
+ ok 38, $db->db_get(1, $value) == 0 ;
+ ok 39, $value eq "value" ;
+
+
+ my %hash ;
+ eval { $db->Tie(\%hash)} ;
+ ok 40, $@ =~ /^Tie needs a reference to an array/ ;
+
+ my @array ;
+ $db->Tie(\@array) ;
+ ok 41, $array[1] eq "value" ;
+
+
+}
+
+# check i/f to text
diff --git a/bdb/perl/BerkeleyDB/t/util.pm b/bdb/perl/BerkeleyDB/t/util.pm
new file mode 100644
index 00000000000..1a1449751eb
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/t/util.pm
@@ -0,0 +1,220 @@
+package util ;
+
+package main ;
+
+use strict ;
+use BerkeleyDB ;
+use File::Path qw(rmtree);
+use vars qw(%DB_errors $FA) ;
+
+$| = 1;
+
+%DB_errors = (
+ 'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
+ 'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
+ 'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
+ 'DB_LOCK_DEADLOCK' => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
+ 'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
+ 'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
+ 'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
+ 'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
+) ;
+
+# full tied array support started in Perl 5.004_57
+# just double check.
+$FA = 0 ;
+{
+ sub try::TIEARRAY { bless [], "try" }
+ sub try::FETCHSIZE { $FA = 1 }
+ my @a ;
+ tie @a, 'try' ;
+ my $a = @a ;
+}
+
+{
+ package LexFile ;
+
+ use vars qw( $basename @files ) ;
+ $basename = "db0000" ;
+
+ sub new
+ {
+ my $self = shift ;
+ #my @files = () ;
+ foreach (@_)
+ {
+ $_ = $basename ;
+ unlink $basename ;
+ push @files, $basename ;
+ ++ $basename ;
+ }
+ bless [ @files ], $self ;
+ }
+
+ sub DESTROY
+ {
+ my $self = shift ;
+ #unlink @{ $self } ;
+ }
+
+ END
+ {
+ foreach (@files) { unlink $_ }
+ }
+}
+
+
+{
+ package LexDir ;
+
+ use File::Path qw(rmtree);
+
+ use vars qw( $basename %dirs ) ;
+
+ sub new
+ {
+ my $self = shift ;
+ my $dir = shift ;
+
+ rmtree $dir if -e $dir ;
+
+ mkdir $dir, 0777 or return undef ;
+
+ return bless [ $dir ], $self ;
+ }
+
+ sub DESTROY
+ {
+ my $self = shift ;
+ my $dir = $self->[0];
+ #rmtree $dir;
+ $dirs{$dir} ++ ;
+ }
+
+ END
+ {
+ foreach (keys %dirs) {
+ rmtree $_ if -d $_ ;
+ }
+ }
+
+}
+
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file:$!";
+ my $result = <CAT>;
+ close(CAT);
+ return $result;
+}
+
+sub docat_del
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my $result = <CAT> || "" ;
+ close(CAT);
+ unlink $file ;
+ return $result;
+}
+
+sub writeFile
+{
+ my $name = shift ;
+ open(FH, ">$name") or return 0 ;
+ print FH @_ ;
+ close FH ;
+ return 1 ;
+}
+
+sub touch
+{
+ my $file = shift ;
+ open(CAT,">$file") || die "Cannot open $file:$!";
+ close(CAT);
+}
+
+sub joiner
+{
+ my $db = shift ;
+ my $sep = shift ;
+ my ($k, $v) = (0, "") ;
+ my @data = () ;
+
+ my $cursor = $db->db_cursor() or return () ;
+ for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
+ $status == 0 ;
+ $status = $cursor->c_get($k, $v, DB_NEXT)) {
+ push @data, $v ;
+ }
+
+ (scalar(@data), join($sep, @data)) ;
+}
+
+sub countRecords
+{
+ my $db = shift ;
+ my ($k, $v) = (0,0) ;
+ my ($count) = 0 ;
+ my ($cursor) = $db->db_cursor() ;
+ #for ($status = $cursor->c_get($k, $v, DB_FIRST) ;
+# $status == 0 ;
+# $status = $cursor->c_get($k, $v, DB_NEXT) )
+ while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+ { ++ $count }
+
+ return $count ;
+}
+
+sub addData
+{
+ my $db = shift ;
+ my @data = @_ ;
+ die "addData odd data\n" if @data % 2 != 0 ;
+ my ($k, $v) ;
+ my $ret = 0 ;
+ while (@data) {
+ $k = shift @data ;
+ $v = shift @data ;
+ $ret += $db->db_put($k, $v) ;
+ }
+
+ return ($ret == 0) ;
+}
+
+sub ok
+{
+ my $no = shift ;
+ my $result = shift ;
+
+ print "not " unless $result ;
+ print "ok $no\n" ;
+}
+
+
+1;
diff --git a/bdb/perl/BerkeleyDB/typemap b/bdb/perl/BerkeleyDB/typemap
new file mode 100644
index 00000000000..81ead2c36d9
--- /dev/null
+++ b/bdb/perl/BerkeleyDB/typemap
@@ -0,0 +1,275 @@
+# typemap for Perl 5 interface to Berkeley DB version 2 & 3
+#
+# SCCS: %I%, %G%
+#
+# written by Paul Marquess <Paul.Marquess@btinternet.com>
+#
+#################################### DB SECTION
+#
+#
+
+void * T_PV
+u_int T_U_INT
+u_int32_t T_U_INT
+const char * T_PV_NULL
+PV_or_NULL T_PV_NULL
+IO_or_NULL T_IO_NULL
+
+AV * T_AV
+
+BerkeleyDB T_PTROBJ
+BerkeleyDB::Common T_PTROBJ_AV
+BerkeleyDB::Hash T_PTROBJ_AV
+BerkeleyDB::Btree T_PTROBJ_AV
+BerkeleyDB::Recno T_PTROBJ_AV
+BerkeleyDB::Queue T_PTROBJ_AV
+BerkeleyDB::Cursor T_PTROBJ_AV
+BerkeleyDB::TxnMgr T_PTROBJ_AV
+BerkeleyDB::Txn T_PTROBJ_AV
+BerkeleyDB::Log T_PTROBJ_AV
+BerkeleyDB::Lock T_PTROBJ_AV
+BerkeleyDB::Env T_PTROBJ_AV
+
+BerkeleyDB::Raw T_RAW
+BerkeleyDB::Common::Raw T_RAW
+BerkeleyDB::Hash::Raw T_RAW
+BerkeleyDB::Btree::Raw T_RAW
+BerkeleyDB::Recno::Raw T_RAW
+BerkeleyDB::Queue::Raw T_RAW
+BerkeleyDB::Cursor::Raw T_RAW
+BerkeleyDB::TxnMgr::Raw T_RAW
+BerkeleyDB::Txn::Raw T_RAW
+BerkeleyDB::Log::Raw T_RAW
+BerkeleyDB::Lock::Raw T_RAW
+BerkeleyDB::Env::Raw T_RAW
+
+BerkeleyDB::Env::Inner T_INNER
+BerkeleyDB::Common::Inner T_INNER
+BerkeleyDB::Txn::Inner T_INNER
+BerkeleyDB::TxnMgr::Inner T_INNER
+# BerkeleyDB__Env T_PTR
+DBT T_dbtdatum
+DBT_OPT T_dbtdatum_opt
+DBT_B T_dbtdatum_btree
+DBTKEY T_dbtkeydatum
+DBTKEY_B T_dbtkeydatum_btree
+DBTYPE T_U_INT
+DualType T_DUAL
+BerkeleyDB_type * T_IV
+BerkeleyDB_ENV_type * T_IV
+BerkeleyDB_TxnMgr_type * T_IV
+BerkeleyDB_Txn_type * T_IV
+BerkeleyDB__Cursor_type * T_IV
+DB * T_IV
+
+INPUT
+
+T_AV
+ if (SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV)
+ /* if (sv_isa($arg, \"${ntype}\")) */
+ $var = (AV*)SvRV($arg);
+ else
+ croak(\"$var is not an array reference\")
+
+T_RAW
+ $var = INT2PTR($type,SvIV($arg)
+
+T_U_INT
+ $var = SvUV($arg)
+
+T_SV_REF_NULL
+ if ($arg == &PL_sv_undef)
+ $var = NULL ;
+ else if (sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV *)GetInternalObject($arg));
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+T_HV_REF_NULL
+ if ($arg == &PL_sv_undef)
+ $var = NULL ;
+ else if (sv_derived_from($arg, \"${ntype}\")) {
+ HV * hv = (HV *)GetInternalObject($arg);
+ SV ** svp = hv_fetch(hv, \"db\", 2, FALSE);
+ IV tmp = SvIV(*svp);
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+T_HV_REF
+ if (sv_derived_from($arg, \"${ntype}\")) {
+ HV * hv = (HV *)GetInternalObject($arg);
+ SV ** svp = hv_fetch(hv, \"db\", 2, FALSE);
+ IV tmp = SvIV(*svp);
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+
+T_P_REF
+ if (sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+
+T_INNER
+ {
+ HV * hv = (HV *)SvRV($arg);
+ SV ** svp = hv_fetch(hv, \"db\", 2, FALSE);
+ IV tmp = SvIV(*svp);
+ $var = INT2PTR($type, tmp);
+ }
+
+T_PV_NULL
+ if ($arg == &PL_sv_undef)
+ $var = NULL ;
+ else {
+ $var = ($type)SvPV($arg,PL_na) ;
+ if (PL_na == 0)
+ $var = NULL ;
+ }
+
+T_IO_NULL
+ if ($arg == &PL_sv_undef)
+ $var = NULL ;
+ else
+ $var = IoOFP(sv_2io($arg))
+
+T_PTROBJ_NULL
+ if ($arg == &PL_sv_undef)
+ $var = NULL ;
+ else if (sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+T_PTROBJ_SELF
+ if ($arg == &PL_sv_undef)
+ $var = NULL ;
+ else if (sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+T_PTROBJ_AV
+ if ($arg == &PL_sv_undef || $arg == NULL)
+ $var = NULL ;
+ else if (sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV(getInnerObject($arg)) ;
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+T_dbtkeydatum
+ DBM_ckFilter($arg, filter_store_key, \"filter_store_key\");
+ DBT_clear($var) ;
+ if (db->recno_or_queue) {
+ Value = GetRecnoKey(db, SvIV($arg)) ;
+ $var.data = & Value;
+ $var.size = (int)sizeof(db_recno_t);
+ }
+ else {
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ }
+
+T_dbtkeydatum_btree
+ DBM_ckFilter($arg, filter_store_key, \"filter_store_key\");
+ DBT_clear($var) ;
+ if (db->recno_or_queue ||
+ (db->type == DB_BTREE && flagSet(DB_SET_RECNO))) {
+ Value = GetRecnoKey(db, SvIV($arg)) ;
+ $var.data = & Value;
+ $var.size = (int)sizeof(db_recno_t);
+ }
+ else {
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ }
+
+T_dbtdatum
+ DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
+ DBT_clear($var) ;
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ $var.flags = db->partial ;
+ $var.dlen = db->dlen ;
+ $var.doff = db->doff ;
+
+T_dbtdatum_opt
+ DBT_clear($var) ;
+ if (flagSet(DB_GET_BOTH)) {
+ DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ $var.flags = db->partial ;
+ $var.dlen = db->dlen ;
+ $var.doff = db->doff ;
+ }
+
+T_dbtdatum_btree
+ DBT_clear($var) ;
+ if (flagSet(DB_GET_BOTH)) {
+ DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ $var.flags = db->partial ;
+ $var.dlen = db->dlen ;
+ $var.doff = db->doff ;
+ }
+
+
+OUTPUT
+
+T_RAW
+ sv_setiv($arg, PTR2IV($var));
+
+T_SV_REF_NULL
+ sv_setiv($arg, PTR2IV($var));
+
+T_HV_REF_NULL
+ sv_setiv($arg, PTR2IV($var));
+
+T_HV_REF
+ sv_setiv($arg, PTR2IV($var));
+
+T_P_REF
+ sv_setiv($arg, PTR2IV($var));
+
+T_DUAL
+ setDUALerrno($arg, $var) ;
+
+T_U_INT
+ sv_setuv($arg, (UV)$var);
+
+T_PV_NULL
+ sv_setpv((SV*)$arg, $var);
+
+T_dbtkeydatum_btree
+ OutputKey_B($arg, $var)
+T_dbtkeydatum
+ OutputKey($arg, $var)
+T_dbtdatum
+ OutputValue($arg, $var)
+T_dbtdatum_opt
+ OutputValue($arg, $var)
+T_dbtdatum_btree
+ OutputValue_B($arg, $var)
+
+T_PTROBJ_NULL
+ sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+
+T_PTROBJ_SELF
+ sv_setref_pv($arg, self, (void*)$var);
diff --git a/bdb/perl/DB_File/Changes b/bdb/perl/DB_File/Changes
new file mode 100644
index 00000000000..7883cbdfef0
--- /dev/null
+++ b/bdb/perl/DB_File/Changes
@@ -0,0 +1,434 @@
+
+1.805 1st September 2002
+
+ * Added support to allow DB_File to build with Berkeley DB 4.1.X
+
+ * Tightened up the test harness to test that calls to untie don't generate
+ the "untie attempted while %d inner references still exist" warning.
+
+ * added code to guard against calling the callbacks (compare,hash & prefix)
+ recursively.
+
+ * pasing undef for the flags and/or mode when opening a database could cause
+ a "Use of uninitialized value in subroutine entry" warning. Now silenced.
+
+ * DBM filter code beefed up to cope with read-only $_.
+
+1.804 2nd June 2002
+
+ * Perl core patch 14939 added a new warning to "splice". This broke the
+ db-recno test harness. Fixed.
+
+ * merged core patches 16502 & 16540.
+
+1.803 1st March 2002
+
+ * Fixed a problem with db-btree.t where it complained about an "our"
+ variable redeclaation.
+
+ * FETCH, STORE & DELETE don't map the flags parameter into the
+ equivalent Berkeley DB function anymore.
+
+1.802 6th January 2002
+
+ * The message about some test failing in db-recno.t had the wrong test
+ numbers. Fixed.
+
+ * merged core patch 13942.
+
+1.801 26th November 2001
+
+ * Fixed typo in Makefile.PL
+
+ * Added "clean" attribute to Makefile.PL
+
+1.800 23rd November 2001
+
+ * use pport.h for perl backward compatability code.
+
+ * use new ExtUtils::Constant module to generate XS constants.
+
+ * upgrade Makefile.PL upgrade/downgrade code to toggle "our" with
+ "use vars"
+
+1.79 22nd October 2001
+
+ * Added a "local $SIG{__DIE__}" inside the eval that checks for
+ the presence of XSLoader s suggested by Andrew Hryckowin.
+
+ * merged core patch 12277.
+
+ * Changed NEXTKEY to not initialise the input key. It isn't used anyway.
+
+1.79 22nd October 2001
+
+ * Fixed test harness for cygwin
+
+1.78 30th July 2001
+
+ * the test in Makefile.PL for AIX used -plthreads. Should have been
+ -lpthreads
+
+ * merged Core patches
+ 10372, 10335, 10372, 10534, 10549, 10643, 11051, 11194, 11432
+
+ * added documentation patch regarding duplicate keys from Andrew Johnson
+
+
+1.77 26th April 2001
+
+ * AIX is reported to need -lpthreads, so Makefile.PL now checks for
+ AIX and adds it to the link options.
+
+ * Minor documentation updates.
+
+ * Merged Core patch 9176
+
+ * Added a patch from Edward Avis that adds support for splice with
+ recno databases.
+
+ * Modified Makefile.PL to only enable the warnings pragma if using perl
+ 5.6.1 or better.
+
+1.76 15th January 2001
+
+ * Added instructions for using LD_PRELOAD to get Berkeley DB 2.x to work
+ with DB_File on Linux. Thanks to Norbert Bollow for sending details of
+ this approach.
+
+
+1.75 17th December 2000
+
+ * Fixed perl core patch 7703
+
+ * Added suppport to allow DB_File to be built with Berkeley DB 3.2 --
+ btree_compare, btree_prefix and hash_cb needed to be changed.
+
+ * Updated dbinfo to support Berkeley DB 3.2 file format changes.
+
+
+1.74 10th December 2000
+
+ * A "close" call in DB_File.xs needed parenthesised to stop win32 from
+ thinking it was one of its macros.
+
+ * Updated dbinfo to support Berkeley DB 3.1 file format changes.
+
+ * DB_File.pm & the test hasness now use the warnings pragma (when
+ available).
+
+ * Included Perl core patch 7703 -- size argument for hash_cb is different
+ for Berkeley DB 3.x
+
+ * Included Perl core patch 7801 -- Give __getBerkeleyDBInfo the ANSI C
+ treatment.
+
+ * @a = () produced the warning 'Argument "" isn't numeric in entersub'
+ This has been fixed. Thanks to Edward Avis for spotting this bug.
+
+ * Added note about building under Linux. Included patches.
+
+ * Included Perl core patch 8068 -- fix for bug 20001013.009
+ When run with warnings enabled "$hash{XX} = undef " produced an
+ "Uninitialized value" warning. This has been fixed.
+
+1.73 31st May 2000
+
+ * Added support in version.c for building with threaded Perl.
+
+ * Berkeley DB 3.1 has reenabled support for null keys. The test
+ harness has been updated to reflect this.
+
+1.72 16th January 2000
+
+ * Added hints/sco.pl
+
+ * The module will now use XSLoader when it is available. When it
+ isn't it will use DynaLoader.
+
+ * The locking section in DB_File.pm has been discredited. Many thanks
+ to David Harris for spotting the underlying problem, contributing
+ the updates to the documentation and writing DB_File::Lock (available
+ on CPAN).
+
+1.71 7th September 1999
+
+ * Fixed a bug that prevented 1.70 from compiling under win32
+
+ * Updated to support Berkeley DB 3.x
+
+ * Updated dbinfo for Berkeley DB 3.x file formats.
+
+1.70 4th August 1999
+
+ * Initialise $DB_File::db_ver and $DB_File::db_version with
+ GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
+
+ * Added a BOOT check to test for equivalent versions of db.h &
+ libdb.a/so.
+
+1.69 3rd August 1999
+
+ * fixed a bug in push -- DB_APPEND wasn't working properly.
+
+ * Fixed the R_SETCURSOR bug introduced in 1.68
+
+ * Added a new Perl variable $DB_File::db_ver
+
+1.68 22nd July 1999
+
+ * Merged changes from 5.005_58
+
+ * Fixed a bug in R_IBEFORE & R_IAFTER procesing in Berkeley DB
+ 2 databases.
+
+ * Added some of the examples in the POD into the test harness.
+
+1.67 6th June 1999
+
+ * Added DBM Filter documentation to DB_File.pm
+
+ * Fixed DBM Filter code to work with 5.004
+
+ * A few instances of newSVpvn were used in 1.66. This isn't available in
+ Perl 5.004_04 or earlier. Replaced with newSVpv.
+
+1.66 15th March 1999
+
+ * Added DBM Filter code
+
+1.65 6th March 1999
+
+ * Fixed a bug in the recno PUSH logic.
+ * The BOOT version check now needs 2.3.4 when using Berkeley DB version 2
+
+1.64 21st February 1999
+
+ * Tidied the 1.x to 2.x flag mapping code.
+ * Added a patch from Mark Kettenis <kettenis@wins.uva.nl> to fix a flag
+ mapping problem with O_RDONLY on the Hurd
+ * Updated the message that db-recno.t prints when tests 51, 53 or 55 fail.
+
+1.63 19th December 1998
+
+ * Fix to allow DB 2.6.x to build with DB_File
+ * Documentation updated to use push,pop etc in the RECNO example &
+ to include the find_dup & del_dup methods.
+
+1.62 30th November 1998
+
+ Added hints/dynixptx.pl.
+ Fixed typemap -- 1.61 used PL_na instead of na
+
+1.61 19th November 1998
+
+ Added a note to README about how to build Berkeley DB 2.x when
+ using HP-UX.
+ Minor modifications to get the module to build with DB 2.5.x
+ Fixed a typo in the definition of O_RDONLY, courtesy of Mark Kettenis.
+
+1.60
+ Changed the test to check for full tied array support
+
+1.59
+ Updated the license section.
+
+ Berkeley DB 2.4.10 disallows zero length keys. Tests 32 & 42 in
+ db-btree.t and test 27 in db-hash.t failed because of this change.
+ Those tests have been zapped.
+
+ Added dbinfo to the distribution.
+
+1.58
+ Tied Array support was enhanced in Perl 5.004_57. DB_File now
+ supports PUSH,POP,SHIFT,UNSHIFT & STORESIZE.
+
+ Fixed a problem with the use of sv_setpvn. When the size is
+ specified as 0, it does a strlen on the data. This was ok for DB
+ 1.x, but isn't for DB 2.x.
+
+1.57
+ If Perl has been compiled with Threads support,the symbol op will be
+ defined. This clashes with a field name in db.h, so it needs to be
+ #undef'ed before db.h is included.
+
+1.56
+ Documented the Solaris 2.5 mutex bug
+
+1.55
+ Merged 1.16 changes.
+
+1.54
+
+ Fixed a small bug in the test harness when run under win32
+ The emulation of fd when useing DB 2.x was busted.
+
+1.53
+
+ Added DB_RENUMBER to flags for recno.
+
+1.52
+
+ Patch from Nick Ing-Simmons now allows DB_File to build on NT.
+ Merged 1.15 patch.
+
+1.51
+
+ Fixed the test harness so that it doesn't expect DB_File to have
+ been installed by the main Perl build.
+
+
+ Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
+
+1.50
+
+ DB_File can now build with either DB 1.x or 2.x, but not both at
+ the same time.
+
+1.16
+
+ A harmless looking tab was causing Makefile.PL to fail on AIX 3.2.5
+
+ Small fix for the AIX strict C compiler XLC which doesn't like
+ __attribute__ being defined via proto.h and redefined via db.h. Fix
+ courtesy of Jarkko Hietaniemi.
+
+1.15
+
+ Patch from Gisle Aas <gisle@aas.no> to suppress "use of undefined
+ value" warning with db_get and db_seq.
+
+ Patch from Gisle Aas <gisle@aas.no> to make DB_File export only the
+ O_* constants from Fcntl.
+
+ Removed the DESTROY method from the DB_File::HASHINFO module.
+
+ Previously DB_File hard-wired the class name of any object that it
+ created to "DB_File". This makes sub-classing difficult. Now
+ DB_File creats objects in the namespace of the package it has been
+ inherited into.
+
+
+1.14
+
+ Made it illegal to tie an associative array to a RECNO database and
+ an ordinary array to a HASH or BTREE database.
+
+1.13
+
+ Minor changes to DB_FIle.xs and DB_File.pm
+
+1.12
+
+ Documented the incompatibility with version 2 of Berkeley DB.
+
+1.11
+
+ Documented the untie gotcha.
+
+1.10
+
+ Fixed fd method so that it still returns -1 for in-memory files
+ when db 1.86 is used.
+
+1.09
+
+ Minor bug fix in DB_File::HASHINFO, DB_File::RECNOINFO and
+ DB_File::BTREEINFO.
+
+ Changed default mode to 0666.
+
+1.08
+
+ Documented operation of bval.
+
+1.07
+
+ Fixed bug with RECNO, where bval wasn't defaulting to "\n".
+
+1.06
+
+ Minor namespace cleanup: Localized PrintBtree.
+
+1.05
+
+ Made all scripts in the documentation strict and -w clean.
+
+ Added logic to DB_File.xs to allow the module to be built after
+ Perl is installed.
+
+1.04
+
+ Minor documentation changes.
+
+ Fixed a bug in hash_cb. Patches supplied by Dave Hammen,
+ <hammen@gothamcity.jsc.nasa.govt>.
+
+ Fixed a bug with the constructors for DB_File::HASHINFO,
+ DB_File::BTREEINFO and DB_File::RECNOINFO. Also tidied up the
+ constructors to make them -w clean.
+
+ Reworked part of the test harness to be more locale friendly.
+
+1.03
+
+ Documentation update.
+
+ DB_File now imports the constants (O_RDWR, O_CREAT etc.) from Fcntl
+ automatically.
+
+ The standard hash function exists is now supported.
+
+ Modified the behavior of get_dup. When it returns an associative
+ array, the value is the count of the number of matching BTREE
+ values.
+
+1.02
+
+ Merged OS/2 specific code into DB_File.xs
+
+ Removed some redundant code in DB_File.xs.
+
+ Documentation update.
+
+ Allow negative subscripts with RECNO interface.
+
+ Changed the default flags from O_RDWR to O_CREAT|O_RDWR.
+
+ The example code which showed how to lock a database needed a call
+ to sync added. Without it the resultant database file was empty.
+
+ Added get_dup method.
+
+1.01
+
+ Fixed a core dump problem with SunOS.
+
+ The return value from TIEHASH wasn't set to NULL when dbopen
+ returned an error.
+
+1.0
+
+ DB_File has been in use for over a year. To reflect that, the
+ version number has been incremented to 1.0.
+
+ Added complete support for multiple concurrent callbacks.
+
+ Using the push method on an empty list didn't work properly. This
+ has been fixed.
+
+0.3
+
+ Added prototype support for multiple btree compare callbacks.
+
+0.2
+
+ When DB_File is opening a database file it no longer terminates the
+ process if dbopen returned an error. This allows file protection
+ errors to be caught at run time. Thanks to Judith Grass
+ <grass@cybercash.com> for spotting the bug.
+
+0.1
+
+ First Release.
+
diff --git a/bdb/perl/DB_File/DB_File.pm b/bdb/perl/DB_File/DB_File.pm
new file mode 100644
index 00000000000..49004ffa148
--- /dev/null
+++ b/bdb/perl/DB_File/DB_File.pm
@@ -0,0 +1,2291 @@
+# DB_File.pm -- Perl 5 interface to Berkeley DB
+#
+# written by Paul Marquess (Paul.Marquess@btinternet.com)
+# last modified 1st September 2002
+# version 1.805
+#
+# Copyright (c) 1995-2002 Paul Marquess. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+
+package DB_File::HASHINFO ;
+
+require 5.00404;
+
+use warnings;
+use strict;
+use Carp;
+require Tie::Hash;
+@DB_File::HASHINFO::ISA = qw(Tie::Hash);
+
+sub new
+{
+ my $pkg = shift ;
+ my %x ;
+ tie %x, $pkg ;
+ bless \%x, $pkg ;
+}
+
+
+sub TIEHASH
+{
+ my $pkg = shift ;
+
+ bless { VALID => {
+ bsize => 1,
+ ffactor => 1,
+ nelem => 1,
+ cachesize => 1,
+ hash => 2,
+ lorder => 1,
+ },
+ GOT => {}
+ }, $pkg ;
+}
+
+
+sub FETCH
+{
+ my $self = shift ;
+ my $key = shift ;
+
+ return $self->{GOT}{$key} if exists $self->{VALID}{$key} ;
+
+ my $pkg = ref $self ;
+ croak "${pkg}::FETCH - Unknown element '$key'" ;
+}
+
+
+sub STORE
+{
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+
+ my $type = $self->{VALID}{$key};
+
+ if ( $type )
+ {
+ croak "Key '$key' not associated with a code reference"
+ if $type == 2 && !ref $value && ref $value ne 'CODE';
+ $self->{GOT}{$key} = $value ;
+ return ;
+ }
+
+ my $pkg = ref $self ;
+ croak "${pkg}::STORE - Unknown element '$key'" ;
+}
+
+sub DELETE
+{
+ my $self = shift ;
+ my $key = shift ;
+
+ if ( exists $self->{VALID}{$key} )
+ {
+ delete $self->{GOT}{$key} ;
+ return ;
+ }
+
+ my $pkg = ref $self ;
+ croak "DB_File::HASHINFO::DELETE - Unknown element '$key'" ;
+}
+
+sub EXISTS
+{
+ my $self = shift ;
+ my $key = shift ;
+
+ exists $self->{VALID}{$key} ;
+}
+
+sub NotHere
+{
+ my $self = shift ;
+ my $method = shift ;
+
+ croak ref($self) . " does not define the method ${method}" ;
+}
+
+sub FIRSTKEY { my $self = shift ; $self->NotHere("FIRSTKEY") }
+sub NEXTKEY { my $self = shift ; $self->NotHere("NEXTKEY") }
+sub CLEAR { my $self = shift ; $self->NotHere("CLEAR") }
+
+package DB_File::RECNOINFO ;
+
+use warnings;
+use strict ;
+
+@DB_File::RECNOINFO::ISA = qw(DB_File::HASHINFO) ;
+
+sub TIEHASH
+{
+ my $pkg = shift ;
+
+ bless { VALID => { map {$_, 1}
+ qw( bval cachesize psize flags lorder reclen bfname )
+ },
+ GOT => {},
+ }, $pkg ;
+}
+
+package DB_File::BTREEINFO ;
+
+use warnings;
+use strict ;
+
+@DB_File::BTREEINFO::ISA = qw(DB_File::HASHINFO) ;
+
+sub TIEHASH
+{
+ my $pkg = shift ;
+
+ bless { VALID => {
+ flags => 1,
+ cachesize => 1,
+ maxkeypage => 1,
+ minkeypage => 1,
+ psize => 1,
+ compare => 2,
+ prefix => 2,
+ lorder => 1,
+ },
+ GOT => {},
+ }, $pkg ;
+}
+
+
+package DB_File ;
+
+use warnings;
+use strict;
+our ($VERSION, @ISA, @EXPORT, $AUTOLOAD, $DB_BTREE, $DB_HASH, $DB_RECNO);
+our ($db_version, $use_XSLoader, $splice_end_array);
+use Carp;
+
+
+$VERSION = "1.805" ;
+
+{
+ local $SIG{__WARN__} = sub {$splice_end_array = "@_";};
+ my @a =(1); splice(@a, 3);
+ $splice_end_array =
+ ($splice_end_array =~ /^splice\(\) offset past end of array at /);
+}
+
+#typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+$DB_BTREE = new DB_File::BTREEINFO ;
+$DB_HASH = new DB_File::HASHINFO ;
+$DB_RECNO = new DB_File::RECNOINFO ;
+
+require Tie::Hash;
+require Exporter;
+use AutoLoader;
+BEGIN {
+ $use_XSLoader = 1 ;
+ { local $SIG{__DIE__} ; eval { require XSLoader } ; }
+
+ if ($@) {
+ $use_XSLoader = 0 ;
+ require DynaLoader;
+ @ISA = qw(DynaLoader);
+ }
+}
+
+push @ISA, qw(Tie::Hash Exporter);
+@EXPORT = qw(
+ $DB_BTREE $DB_HASH $DB_RECNO
+
+ BTREEMAGIC
+ BTREEVERSION
+ DB_LOCK
+ DB_SHMEM
+ DB_TXN
+ HASHMAGIC
+ HASHVERSION
+ MAX_PAGE_NUMBER
+ MAX_PAGE_OFFSET
+ MAX_REC_NUMBER
+ RET_ERROR
+ RET_SPECIAL
+ RET_SUCCESS
+ R_CURSOR
+ R_DUP
+ R_FIRST
+ R_FIXEDLEN
+ R_IAFTER
+ R_IBEFORE
+ R_LAST
+ R_NEXT
+ R_NOKEY
+ R_NOOVERWRITE
+ R_PREV
+ R_RECNOSYNC
+ R_SETCURSOR
+ R_SNAPSHOT
+ __R_UNUSED
+
+);
+
+sub AUTOLOAD {
+ my($constname);
+ ($constname = $AUTOLOAD) =~ s/.*:://;
+ my ($error, $val) = constant($constname);
+ Carp::croak $error if $error;
+ no strict 'refs';
+ *{$AUTOLOAD} = sub { $val };
+ goto &{$AUTOLOAD};
+}
+
+
+eval {
+ # Make all Fcntl O_XXX constants available for importing
+ require Fcntl;
+ my @O = grep /^O_/, @Fcntl::EXPORT;
+ Fcntl->import(@O); # first we import what we want to export
+ push(@EXPORT, @O);
+};
+
+if ($use_XSLoader)
+ { XSLoader::load("DB_File", $VERSION)}
+else
+ { bootstrap DB_File $VERSION }
+
+# Preloaded methods go here. Autoload methods go after __END__, and are
+# processed by the autosplit program.
+
+sub tie_hash_or_array
+{
+ my (@arg) = @_ ;
+ my $tieHASH = ( (caller(1))[3] =~ /TIEHASH/ ) ;
+
+ $arg[4] = tied %{ $arg[4] }
+ if @arg >= 5 && ref $arg[4] && $arg[4] =~ /=HASH/ && tied %{ $arg[4] } ;
+
+ $arg[2] = O_CREAT()|O_RDWR() if @arg >=3 && ! defined $arg[2];
+ $arg[3] = 0666 if @arg >=4 && ! defined $arg[3];
+
+ # make recno in Berkeley DB version 2 work like recno in version 1.
+ if ($db_version > 1 and defined $arg[4] and $arg[4] =~ /RECNO/ and
+ $arg[1] and ! -e $arg[1]) {
+ open(FH, ">$arg[1]") or return undef ;
+ close FH ;
+ chmod $arg[3] ? $arg[3] : 0666 , $arg[1] ;
+ }
+
+ DoTie_($tieHASH, @arg) ;
+}
+
+sub TIEHASH
+{
+ tie_hash_or_array(@_) ;
+}
+
+sub TIEARRAY
+{
+ tie_hash_or_array(@_) ;
+}
+
+sub CLEAR
+{
+ my $self = shift;
+ my $key = 0 ;
+ my $value = "" ;
+ my $status = $self->seq($key, $value, R_FIRST());
+ my @keys;
+
+ while ($status == 0) {
+ push @keys, $key;
+ $status = $self->seq($key, $value, R_NEXT());
+ }
+ foreach $key (reverse @keys) {
+ my $s = $self->del($key);
+ }
+}
+
+sub EXTEND { }
+
+sub STORESIZE
+{
+ my $self = shift;
+ my $length = shift ;
+ my $current_length = $self->length() ;
+
+ if ($length < $current_length) {
+ my $key ;
+ for ($key = $current_length - 1 ; $key >= $length ; -- $key)
+ { $self->del($key) }
+ }
+ elsif ($length > $current_length) {
+ $self->put($length-1, "") ;
+ }
+}
+
+
+sub SPLICE
+{
+ my $self = shift;
+ my $offset = shift;
+ if (not defined $offset) {
+ warnings::warnif('uninitialized', 'Use of uninitialized value in splice');
+ $offset = 0;
+ }
+
+ my $length = @_ ? shift : 0;
+ # Carping about definedness comes _after_ the OFFSET sanity check.
+ # This is so we get the same error messages as Perl's splice().
+ #
+
+ my @list = @_;
+
+ my $size = $self->FETCHSIZE();
+
+ # 'If OFFSET is negative then it start that far from the end of
+ # the array.'
+ #
+ if ($offset < 0) {
+ my $new_offset = $size + $offset;
+ if ($new_offset < 0) {
+ die "Modification of non-creatable array value attempted, "
+ . "subscript $offset";
+ }
+ $offset = $new_offset;
+ }
+
+ if (not defined $length) {
+ warnings::warnif('uninitialized', 'Use of uninitialized value in splice');
+ $length = 0;
+ }
+
+ if ($offset > $size) {
+ $offset = $size;
+ warnings::warnif('misc', 'splice() offset past end of array')
+ if $splice_end_array;
+ }
+
+ # 'If LENGTH is omitted, removes everything from OFFSET onward.'
+ if (not defined $length) {
+ $length = $size - $offset;
+ }
+
+ # 'If LENGTH is negative, leave that many elements off the end of
+ # the array.'
+ #
+ if ($length < 0) {
+ $length = $size - $offset + $length;
+
+ if ($length < 0) {
+ # The user must have specified a length bigger than the
+ # length of the array passed in. But perl's splice()
+ # doesn't catch this, it just behaves as for length=0.
+ #
+ $length = 0;
+ }
+ }
+
+ if ($length > $size - $offset) {
+ $length = $size - $offset;
+ }
+
+ # $num_elems holds the current number of elements in the database.
+ my $num_elems = $size;
+
+ # 'Removes the elements designated by OFFSET and LENGTH from an
+ # array,'...
+ #
+ my @removed = ();
+ foreach (0 .. $length - 1) {
+ my $old;
+ my $status = $self->get($offset, $old);
+ if ($status != 0) {
+ my $msg = "error from Berkeley DB on get($offset, \$old)";
+ if ($status == 1) {
+ $msg .= ' (no such element?)';
+ }
+ else {
+ $msg .= ": error status $status";
+ if (defined $! and $! ne '') {
+ $msg .= ", message $!";
+ }
+ }
+ die $msg;
+ }
+ push @removed, $old;
+
+ $status = $self->del($offset);
+ if ($status != 0) {
+ my $msg = "error from Berkeley DB on del($offset)";
+ if ($status == 1) {
+ $msg .= ' (no such element?)';
+ }
+ else {
+ $msg .= ": error status $status";
+ if (defined $! and $! ne '') {
+ $msg .= ", message $!";
+ }
+ }
+ die $msg;
+ }
+
+ -- $num_elems;
+ }
+
+ # ...'and replaces them with the elements of LIST, if any.'
+ my $pos = $offset;
+ while (defined (my $elem = shift @list)) {
+ my $old_pos = $pos;
+ my $status;
+ if ($pos >= $num_elems) {
+ $status = $self->put($pos, $elem);
+ }
+ else {
+ $status = $self->put($pos, $elem, $self->R_IBEFORE);
+ }
+
+ if ($status != 0) {
+ my $msg = "error from Berkeley DB on put($pos, $elem, ...)";
+ if ($status == 1) {
+ $msg .= ' (no such element?)';
+ }
+ else {
+ $msg .= ", error status $status";
+ if (defined $! and $! ne '') {
+ $msg .= ", message $!";
+ }
+ }
+ die $msg;
+ }
+
+ die "pos unexpectedly changed from $old_pos to $pos with R_IBEFORE"
+ if $old_pos != $pos;
+
+ ++ $pos;
+ ++ $num_elems;
+ }
+
+ if (wantarray) {
+ # 'In list context, returns the elements removed from the
+ # array.'
+ #
+ return @removed;
+ }
+ elsif (defined wantarray and not wantarray) {
+ # 'In scalar context, returns the last element removed, or
+ # undef if no elements are removed.'
+ #
+ if (@removed) {
+ my $last = pop @removed;
+ return "$last";
+ }
+ else {
+ return undef;
+ }
+ }
+ elsif (not defined wantarray) {
+ # Void context
+ }
+ else { die }
+}
+sub ::DB_File::splice { &SPLICE }
+
+sub find_dup
+{
+ croak "Usage: \$db->find_dup(key,value)\n"
+ unless @_ == 3 ;
+
+ my $db = shift ;
+ my ($origkey, $value_wanted) = @_ ;
+ my ($key, $value) = ($origkey, 0);
+ my ($status) = 0 ;
+
+ for ($status = $db->seq($key, $value, R_CURSOR() ) ;
+ $status == 0 ;
+ $status = $db->seq($key, $value, R_NEXT() ) ) {
+
+ return 0 if $key eq $origkey and $value eq $value_wanted ;
+ }
+
+ return $status ;
+}
+
+sub del_dup
+{
+ croak "Usage: \$db->del_dup(key,value)\n"
+ unless @_ == 3 ;
+
+ my $db = shift ;
+ my ($key, $value) = @_ ;
+ my ($status) = $db->find_dup($key, $value) ;
+ return $status if $status != 0 ;
+
+ $status = $db->del($key, R_CURSOR() ) ;
+ return $status ;
+}
+
+sub get_dup
+{
+ croak "Usage: \$db->get_dup(key [,flag])\n"
+ unless @_ == 2 or @_ == 3 ;
+
+ my $db = shift ;
+ my $key = shift ;
+ my $flag = shift ;
+ my $value = 0 ;
+ my $origkey = $key ;
+ my $wantarray = wantarray ;
+ my %values = () ;
+ my @values = () ;
+ my $counter = 0 ;
+ my $status = 0 ;
+
+ # iterate through the database until either EOF ($status == 0)
+ # or a different key is encountered ($key ne $origkey).
+ for ($status = $db->seq($key, $value, R_CURSOR()) ;
+ $status == 0 and $key eq $origkey ;
+ $status = $db->seq($key, $value, R_NEXT()) ) {
+
+ # save the value or count number of matches
+ if ($wantarray) {
+ if ($flag)
+ { ++ $values{$value} }
+ else
+ { push (@values, $value) }
+ }
+ else
+ { ++ $counter }
+
+ }
+
+ return ($wantarray ? ($flag ? %values : @values) : $counter) ;
+}
+
+
+1;
+__END__
+
+=head1 NAME
+
+DB_File - Perl5 access to Berkeley DB version 1.x
+
+=head1 SYNOPSIS
+
+ use DB_File;
+
+ [$X =] tie %hash, 'DB_File', [$filename, $flags, $mode, $DB_HASH] ;
+ [$X =] tie %hash, 'DB_File', $filename, $flags, $mode, $DB_BTREE ;
+ [$X =] tie @array, 'DB_File', $filename, $flags, $mode, $DB_RECNO ;
+
+ $status = $X->del($key [, $flags]) ;
+ $status = $X->put($key, $value [, $flags]) ;
+ $status = $X->get($key, $value [, $flags]) ;
+ $status = $X->seq($key, $value, $flags) ;
+ $status = $X->sync([$flags]) ;
+ $status = $X->fd ;
+
+ # BTREE only
+ $count = $X->get_dup($key) ;
+ @list = $X->get_dup($key) ;
+ %list = $X->get_dup($key, 1) ;
+ $status = $X->find_dup($key, $value) ;
+ $status = $X->del_dup($key, $value) ;
+
+ # RECNO only
+ $a = $X->length;
+ $a = $X->pop ;
+ $X->push(list);
+ $a = $X->shift;
+ $X->unshift(list);
+ @r = $X->splice(offset, length, elements);
+
+ # DBM Filters
+ $old_filter = $db->filter_store_key ( sub { ... } ) ;
+ $old_filter = $db->filter_store_value( sub { ... } ) ;
+ $old_filter = $db->filter_fetch_key ( sub { ... } ) ;
+ $old_filter = $db->filter_fetch_value( sub { ... } ) ;
+
+ untie %hash ;
+ untie @array ;
+
+=head1 DESCRIPTION
+
+B<DB_File> is a module which allows Perl programs to make use of the
+facilities provided by Berkeley DB version 1.x (if you have a newer
+version of DB, see L<Using DB_File with Berkeley DB version 2 or greater>).
+It is assumed that you have a copy of the Berkeley DB manual pages at
+hand when reading this documentation. The interface defined here
+mirrors the Berkeley DB interface closely.
+
+Berkeley DB is a C library which provides a consistent interface to a
+number of database formats. B<DB_File> provides an interface to all
+three of the database types currently supported by Berkeley DB.
+
+The file types are:
+
+=over 5
+
+=item B<DB_HASH>
+
+This database type allows arbitrary key/value pairs to be stored in data
+files. This is equivalent to the functionality provided by other
+hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
+the files created using DB_HASH are not compatible with any of the
+other packages mentioned.
+
+A default hashing algorithm, which will be adequate for most
+applications, is built into Berkeley DB. If you do need to use your own
+hashing algorithm it is possible to write your own in Perl and have
+B<DB_File> use it instead.
+
+=item B<DB_BTREE>
+
+The btree format allows arbitrary key/value pairs to be stored in a
+sorted, balanced binary tree.
+
+As with the DB_HASH format, it is possible to provide a user defined
+Perl routine to perform the comparison of keys. By default, though, the
+keys are stored in lexical order.
+
+=item B<DB_RECNO>
+
+DB_RECNO allows both fixed-length and variable-length flat text files
+to be manipulated using the same key/value pair interface as in DB_HASH
+and DB_BTREE. In this case the key will consist of a record (line)
+number.
+
+=back
+
+=head2 Using DB_File with Berkeley DB version 2 or greater
+
+Although B<DB_File> is intended to be used with Berkeley DB version 1,
+it can also be used with version 2, 3 or 4. In this case the interface is
+limited to the functionality provided by Berkeley DB 1.x. Anywhere the
+version 2 or greater interface differs, B<DB_File> arranges for it to work
+like version 1. This feature allows B<DB_File> scripts that were built
+with version 1 to be migrated to version 2 or greater without any changes.
+
+If you want to make use of the new features available in Berkeley DB
+2.x or greater, use the Perl module B<BerkeleyDB> instead.
+
+B<Note:> The database file format has changed multiple times in Berkeley
+DB version 2, 3 and 4. If you cannot recreate your databases, you
+must dump any existing databases with either the C<db_dump> or the
+C<db_dump185> utility that comes with Berkeley DB.
+Once you have rebuilt DB_File to use Berkeley DB version 2 or greater,
+your databases can be recreated using C<db_load>. Refer to the Berkeley DB
+documentation for further details.
+
+Please read L<"COPYRIGHT"> before using version 2.x or greater of Berkeley
+DB with DB_File.
+
+=head2 Interface to Berkeley DB
+
+B<DB_File> allows access to Berkeley DB files using the tie() mechanism
+in Perl 5 (for full details, see L<perlfunc/tie()>). This facility
+allows B<DB_File> to access Berkeley DB files using either an
+associative array (for DB_HASH & DB_BTREE file types) or an ordinary
+array (for the DB_RECNO file type).
+
+In addition to the tie() interface, it is also possible to access most
+of the functions provided in the Berkeley DB API directly.
+See L<THE API INTERFACE>.
+
+=head2 Opening a Berkeley DB Database File
+
+Berkeley DB uses the function dbopen() to open or create a database.
+Here is the C prototype for dbopen():
+
+ DB*
+ dbopen (const char * file, int flags, int mode,
+ DBTYPE type, const void * openinfo)
+
+The parameter C<type> is an enumeration which specifies which of the 3
+interface methods (DB_HASH, DB_BTREE or DB_RECNO) is to be used.
+Depending on which of these is actually chosen, the final parameter,
+I<openinfo> points to a data structure which allows tailoring of the
+specific interface method.
+
+This interface is handled slightly differently in B<DB_File>. Here is
+an equivalent call using B<DB_File>:
+
+ tie %array, 'DB_File', $filename, $flags, $mode, $DB_HASH ;
+
+The C<filename>, C<flags> and C<mode> parameters are the direct
+equivalent of their dbopen() counterparts. The final parameter $DB_HASH
+performs the function of both the C<type> and C<openinfo> parameters in
+dbopen().
+
+In the example above $DB_HASH is actually a pre-defined reference to a
+hash object. B<DB_File> has three of these pre-defined references.
+Apart from $DB_HASH, there is also $DB_BTREE and $DB_RECNO.
+
+The keys allowed in each of these pre-defined references is limited to
+the names used in the equivalent C structure. So, for example, the
+$DB_HASH reference will only allow keys called C<bsize>, C<cachesize>,
+C<ffactor>, C<hash>, C<lorder> and C<nelem>.
+
+To change one of these elements, just assign to it like this:
+
+ $DB_HASH->{'cachesize'} = 10000 ;
+
+The three predefined variables $DB_HASH, $DB_BTREE and $DB_RECNO are
+usually adequate for most applications. If you do need to create extra
+instances of these objects, constructors are available for each file
+type.
+
+Here are examples of the constructors and the valid options available
+for DB_HASH, DB_BTREE and DB_RECNO respectively.
+
+ $a = new DB_File::HASHINFO ;
+ $a->{'bsize'} ;
+ $a->{'cachesize'} ;
+ $a->{'ffactor'};
+ $a->{'hash'} ;
+ $a->{'lorder'} ;
+ $a->{'nelem'} ;
+
+ $b = new DB_File::BTREEINFO ;
+ $b->{'flags'} ;
+ $b->{'cachesize'} ;
+ $b->{'maxkeypage'} ;
+ $b->{'minkeypage'} ;
+ $b->{'psize'} ;
+ $b->{'compare'} ;
+ $b->{'prefix'} ;
+ $b->{'lorder'} ;
+
+ $c = new DB_File::RECNOINFO ;
+ $c->{'bval'} ;
+ $c->{'cachesize'} ;
+ $c->{'psize'} ;
+ $c->{'flags'} ;
+ $c->{'lorder'} ;
+ $c->{'reclen'} ;
+ $c->{'bfname'} ;
+
+The values stored in the hashes above are mostly the direct equivalent
+of their C counterpart. Like their C counterparts, all are set to a
+default values - that means you don't have to set I<all> of the
+values when you only want to change one. Here is an example:
+
+ $a = new DB_File::HASHINFO ;
+ $a->{'cachesize'} = 12345 ;
+ tie %y, 'DB_File', "filename", $flags, 0777, $a ;
+
+A few of the options need extra discussion here. When used, the C
+equivalent of the keys C<hash>, C<compare> and C<prefix> store pointers
+to C functions. In B<DB_File> these keys are used to store references
+to Perl subs. Below are templates for each of the subs:
+
+ sub hash
+ {
+ my ($data) = @_ ;
+ ...
+ # return the hash value for $data
+ return $hash ;
+ }
+
+ sub compare
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return 0 if $key1 eq $key2
+ # -1 if $key1 lt $key2
+ # 1 if $key1 gt $key2
+ return (-1 , 0 or 1) ;
+ }
+
+ sub prefix
+ {
+ my ($key, $key2) = @_ ;
+ ...
+ # return number of bytes of $key2 which are
+ # necessary to determine that it is greater than $key1
+ return $bytes ;
+ }
+
+See L<Changing the BTREE sort order> for an example of using the
+C<compare> template.
+
+If you are using the DB_RECNO interface and you intend making use of
+C<bval>, you should check out L<The 'bval' Option>.
+
+=head2 Default Parameters
+
+It is possible to omit some or all of the final 4 parameters in the
+call to C<tie> and let them take default values. As DB_HASH is the most
+common file format used, the call:
+
+ tie %A, "DB_File", "filename" ;
+
+is equivalent to:
+
+ tie %A, "DB_File", "filename", O_CREAT|O_RDWR, 0666, $DB_HASH ;
+
+It is also possible to omit the filename parameter as well, so the
+call:
+
+ tie %A, "DB_File" ;
+
+is equivalent to:
+
+ tie %A, "DB_File", undef, O_CREAT|O_RDWR, 0666, $DB_HASH ;
+
+See L<In Memory Databases> for a discussion on the use of C<undef>
+in place of a filename.
+
+=head2 In Memory Databases
+
+Berkeley DB allows the creation of in-memory databases by using NULL
+(that is, a C<(char *)0> in C) in place of the filename. B<DB_File>
+uses C<undef> instead of NULL to provide this functionality.
+
+=head1 DB_HASH
+
+The DB_HASH file format is probably the most commonly used of the three
+file formats that B<DB_File> supports. It is also very straightforward
+to use.
+
+=head2 A Simple Example
+
+This example shows how to create a database, add key/value pairs to the
+database, delete keys/value pairs and finally how to enumerate the
+contents of the database.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+ our (%h, $k, $v) ;
+
+ unlink "fruit" ;
+ tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH
+ or die "Cannot open file 'fruit': $!\n";
+
+ # Add a few key/value pairs to the file
+ $h{"apple"} = "red" ;
+ $h{"orange"} = "orange" ;
+ $h{"banana"} = "yellow" ;
+ $h{"tomato"} = "red" ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $h{"banana"} ;
+
+ # Delete a key/value pair.
+ delete $h{"apple"} ;
+
+ # print the contents of the file
+ while (($k, $v) = each %h)
+ { print "$k -> $v\n" }
+
+ untie %h ;
+
+here is the output:
+
+ Banana Exists
+
+ orange -> orange
+ tomato -> red
+ banana -> yellow
+
+Note that the like ordinary associative arrays, the order of the keys
+retrieved is in an apparently random order.
+
+=head1 DB_BTREE
+
+The DB_BTREE format is useful when you want to store data in a given
+order. By default the keys will be stored in lexical order, but as you
+will see from the example shown in the next section, it is very easy to
+define your own sorting function.
+
+=head2 Changing the BTREE sort order
+
+This script shows how to override the default sorting algorithm that
+BTREE uses. Instead of using the normal lexical ordering, a case
+insensitive compare function will be used.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my %h ;
+
+ sub Compare
+ {
+ my ($key1, $key2) = @_ ;
+ "\L$key1" cmp "\L$key2" ;
+ }
+
+ # specify the Perl sub that will do the comparison
+ $DB_BTREE->{'compare'} = \&Compare ;
+
+ unlink "tree" ;
+ tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open file 'tree': $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+
+Here is the output from the code above.
+
+ mouse
+ Smith
+ Wall
+
+There are a few point to bear in mind if you want to change the
+ordering in a BTREE database:
+
+=over 5
+
+=item 1.
+
+The new compare function must be specified when you create the database.
+
+=item 2.
+
+You cannot change the ordering once the database has been created. Thus
+you must use the same compare function every time you access the
+database.
+
+=item 3
+
+Duplicate keys are entirely defined by the comparison function.
+In the case-insensitive example above, the keys: 'KEY' and 'key'
+would be considered duplicates, and assigning to the second one
+would overwrite the first. If duplicates are allowed for (with the
+R_DUPS flag discussed below), only a single copy of duplicate keys
+is stored in the database --- so (again with example above) assigning
+three values to the keys: 'KEY', 'Key', and 'key' would leave just
+the first key: 'KEY' in the database with three values. For some
+situations this results in information loss, so care should be taken
+to provide fully qualified comparison functions when necessary.
+For example, the above comparison routine could be modified to
+additionally compare case-sensitively if two keys are equal in the
+case insensitive comparison:
+
+ sub compare {
+ my($key1, $key2) = @_;
+ lc $key1 cmp lc $key2 ||
+ $key1 cmp $key2;
+ }
+
+And now you will only have duplicates when the keys themselves
+are truly the same. (note: in versions of the db library prior to
+about November 1996, such duplicate keys were retained so it was
+possible to recover the original keys in sets of keys that
+compared as equal).
+
+
+=back
+
+=head2 Handling Duplicate Keys
+
+The BTREE file type optionally allows a single key to be associated
+with an arbitrary number of values. This option is enabled by setting
+the flags element of C<$DB_BTREE> to R_DUP when creating the database.
+
+There are some difficulties in using the tied hash interface if you
+want to manipulate a BTREE database with duplicate keys. Consider this
+code:
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, %h) ;
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+
+ # iterate through the associative array
+ # and print each key/value pair.
+ foreach (sort keys %h)
+ { print "$_ -> $h{$_}\n" }
+
+ untie %h ;
+
+Here is the output:
+
+ Smith -> John
+ Wall -> Larry
+ Wall -> Larry
+ Wall -> Larry
+ mouse -> mickey
+
+As you can see 3 records have been successfully created with key C<Wall>
+- the only thing is, when they are retrieved from the database they
+I<seem> to have the same value, namely C<Larry>. The problem is caused
+by the way that the associative array interface works. Basically, when
+the associative array interface is used to fetch the value associated
+with a given key, it will only ever retrieve the first value.
+
+Although it may not be immediately obvious from the code above, the
+associative array interface can be used to write values with duplicate
+keys, but it cannot be used to read them back from the database.
+
+The way to get around this problem is to use the Berkeley DB API method
+called C<seq>. This method allows sequential access to key/value
+pairs. See L<THE API INTERFACE> for details of both the C<seq> method
+and the API in general.
+
+Here is the script above rewritten using the C<seq> API method.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h, $status, $key, $value) ;
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+
+ # iterate through the btree using seq
+ # and print each key/value pair.
+ $key = $value = 0 ;
+ for ($status = $x->seq($key, $value, R_FIRST) ;
+ $status == 0 ;
+ $status = $x->seq($key, $value, R_NEXT) )
+ { print "$key -> $value\n" }
+
+ undef $x ;
+ untie %h ;
+
+that prints:
+
+ Smith -> John
+ Wall -> Brick
+ Wall -> Brick
+ Wall -> Larry
+ mouse -> mickey
+
+This time we have got all the key/value pairs, including the multiple
+values associated with the key C<Wall>.
+
+To make life easier when dealing with duplicate keys, B<DB_File> comes with
+a few utility methods.
+
+=head2 The get_dup() Method
+
+The C<get_dup> method assists in
+reading duplicate values from BTREE databases. The method can take the
+following forms:
+
+ $count = $x->get_dup($key) ;
+ @list = $x->get_dup($key) ;
+ %list = $x->get_dup($key, 1) ;
+
+In a scalar context the method returns the number of values associated
+with the key, C<$key>.
+
+In list context, it returns all the values which match C<$key>. Note
+that the values will be returned in an apparently random order.
+
+In list context, if the second parameter is present and evaluates
+TRUE, the method returns an associative array. The keys of the
+associative array correspond to the values that matched in the BTREE
+and the values of the array are a count of the number of times that
+particular value occurred in the BTREE.
+
+So assuming the database created above, we can use C<get_dup> like
+this:
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h) ;
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ my $cnt = $x->get_dup("Wall") ;
+ print "Wall occurred $cnt times\n" ;
+
+ my %hash = $x->get_dup("Wall", 1) ;
+ print "Larry is there\n" if $hash{'Larry'} ;
+ print "There are $hash{'Brick'} Brick Walls\n" ;
+
+ my @list = sort $x->get_dup("Wall") ;
+ print "Wall => [@list]\n" ;
+
+ @list = $x->get_dup("Smith") ;
+ print "Smith => [@list]\n" ;
+
+ @list = $x->get_dup("Dog") ;
+ print "Dog => [@list]\n" ;
+
+
+and it will print:
+
+ Wall occurred 3 times
+ Larry is there
+ There are 2 Brick Walls
+ Wall => [Brick Brick Larry]
+ Smith => [John]
+ Dog => []
+
+=head2 The find_dup() Method
+
+ $status = $X->find_dup($key, $value) ;
+
+This method checks for the existence of a specific key/value pair. If the
+pair exists, the cursor is left pointing to the pair and the method
+returns 0. Otherwise the method returns a non-zero value.
+
+Assuming the database from the previous example:
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h, $found) ;
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
+ print "Larry Wall is $found there\n" ;
+
+ $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
+ print "Harry Wall is $found there\n" ;
+
+ undef $x ;
+ untie %h ;
+
+prints this
+
+ Larry Wall is there
+ Harry Wall is not there
+
+
+=head2 The del_dup() Method
+
+ $status = $X->del_dup($key, $value) ;
+
+This method deletes a specific key/value pair. It returns
+0 if they exist and have been deleted successfully.
+Otherwise the method returns a non-zero value.
+
+Again assuming the existence of the C<tree> database
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h, $found) ;
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ $x->del_dup("Wall", "Larry") ;
+
+ $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
+ print "Larry Wall is $found there\n" ;
+
+ undef $x ;
+ untie %h ;
+
+prints this
+
+ Larry Wall is not there
+
+=head2 Matching Partial Keys
+
+The BTREE interface has a feature which allows partial keys to be
+matched. This functionality is I<only> available when the C<seq> method
+is used along with the R_CURSOR flag.
+
+ $x->seq($key, $value, R_CURSOR) ;
+
+Here is the relevant quote from the dbopen man page where it defines
+the use of the R_CURSOR flag with seq:
+
+ Note, for the DB_BTREE access method, the returned key is not
+ necessarily an exact match for the specified key. The returned key
+ is the smallest key greater than or equal to the specified key,
+ permitting partial key matches and range searches.
+
+In the example script below, the C<match> sub uses this feature to find
+and print the first matching key/value pair given a partial key.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+ use Fcntl ;
+
+ my ($filename, $x, %h, $st, $key, $value) ;
+
+ sub match
+ {
+ my $key = shift ;
+ my $value = 0;
+ my $orig_key = $key ;
+ $x->seq($key, $value, R_CURSOR) ;
+ print "$orig_key\t-> $key\t-> $value\n" ;
+ }
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'mouse'} = 'mickey' ;
+ $h{'Wall'} = 'Larry' ;
+ $h{'Walls'} = 'Brick' ;
+ $h{'Smith'} = 'John' ;
+
+
+ $key = $value = 0 ;
+ print "IN ORDER\n" ;
+ for ($st = $x->seq($key, $value, R_FIRST) ;
+ $st == 0 ;
+ $st = $x->seq($key, $value, R_NEXT) )
+
+ { print "$key -> $value\n" }
+
+ print "\nPARTIAL MATCH\n" ;
+
+ match "Wa" ;
+ match "A" ;
+ match "a" ;
+
+ undef $x ;
+ untie %h ;
+
+Here is the output:
+
+ IN ORDER
+ Smith -> John
+ Wall -> Larry
+ Walls -> Brick
+ mouse -> mickey
+
+ PARTIAL MATCH
+ Wa -> Wall -> Larry
+ A -> Smith -> John
+ a -> mouse -> mickey
+
+=head1 DB_RECNO
+
+DB_RECNO provides an interface to flat text files. Both variable and
+fixed length records are supported.
+
+In order to make RECNO more compatible with Perl, the array offset for
+all RECNO arrays begins at 0 rather than 1 as in Berkeley DB.
+
+As with normal Perl arrays, a RECNO array can be accessed using
+negative indexes. The index -1 refers to the last element of the array,
+-2 the second last, and so on. Attempting to access an element before
+the start of the array will raise a fatal run-time error.
+
+=head2 The 'bval' Option
+
+The operation of the bval option warrants some discussion. Here is the
+definition of bval from the Berkeley DB 1.85 recno manual page:
+
+ The delimiting byte to be used to mark the end of a
+ record for variable-length records, and the pad charac-
+ ter for fixed-length records. If no value is speci-
+ fied, newlines (``\n'') are used to mark the end of
+ variable-length records and fixed-length records are
+ padded with spaces.
+
+The second sentence is wrong. In actual fact bval will only default to
+C<"\n"> when the openinfo parameter in dbopen is NULL. If a non-NULL
+openinfo parameter is used at all, the value that happens to be in bval
+will be used. That means you always have to specify bval when making
+use of any of the options in the openinfo parameter. This documentation
+error will be fixed in the next release of Berkeley DB.
+
+That clarifies the situation with regards Berkeley DB itself. What
+about B<DB_File>? Well, the behavior defined in the quote above is
+quite useful, so B<DB_File> conforms to it.
+
+That means that you can specify other options (e.g. cachesize) and
+still have bval default to C<"\n"> for variable length records, and
+space for fixed length records.
+
+Also note that the bval option only allows you to specify a single byte
+as a delimeter.
+
+=head2 A Simple Example
+
+Here is a simple example that uses RECNO (if you are using a version
+of Perl earlier than 5.004_57 this example won't work -- see
+L<Extra RECNO Methods> for a workaround).
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_RECNO
+ or die "Cannot open file 'text': $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ push @h, "green", "black" ;
+
+ my $elements = scalar @h ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = pop @h ;
+ print "popped $last\n" ;
+
+ unshift @h, "white" ;
+ my $first = shift @h ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ # use a negative index
+ print "The last element is $h[-1]\n" ;
+ print "The 2nd last element is $h[-2]\n" ;
+
+ untie @h ;
+
+Here is the output from the script:
+
+ The array contains 5 entries
+ popped black
+ shifted white
+ Element 1 Exists with value blue
+ The last element is green
+ The 2nd last element is yellow
+
+=head2 Extra RECNO Methods
+
+If you are using a version of Perl earlier than 5.004_57, the tied
+array interface is quite limited. In the example script above
+C<push>, C<pop>, C<shift>, C<unshift>
+or determining the array length will not work with a tied array.
+
+To make the interface more useful for older versions of Perl, a number
+of methods are supplied with B<DB_File> to simulate the missing array
+operations. All these methods are accessed via the object returned from
+the tie call.
+
+Here are the methods:
+
+=over 5
+
+=item B<$X-E<gt>push(list) ;>
+
+Pushes the elements of C<list> to the end of the array.
+
+=item B<$value = $X-E<gt>pop ;>
+
+Removes and returns the last element of the array.
+
+=item B<$X-E<gt>shift>
+
+Removes and returns the first element of the array.
+
+=item B<$X-E<gt>unshift(list) ;>
+
+Pushes the elements of C<list> to the start of the array.
+
+=item B<$X-E<gt>length>
+
+Returns the number of elements in the array.
+
+=item B<$X-E<gt>splice(offset, length, elements);>
+
+Returns a splice of the the array.
+
+=back
+
+=head2 Another Example
+
+Here is a more complete example that makes use of some of the methods
+described above. It also makes use of the API interface directly (see
+L<THE API INTERFACE>).
+
+ use warnings ;
+ use strict ;
+ my (@h, $H, $file, $i) ;
+ use DB_File ;
+ use Fcntl ;
+
+ $file = "text" ;
+
+ unlink $file ;
+
+ $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0666, $DB_RECNO
+ or die "Cannot open file $file: $!\n" ;
+
+ # first create a text file to play with
+ $h[0] = "zero" ;
+ $h[1] = "one" ;
+ $h[2] = "two" ;
+ $h[3] = "three" ;
+ $h[4] = "four" ;
+
+
+ # Print the records in order.
+ #
+ # The length method is needed here because evaluating a tied
+ # array in a scalar context does not return the number of
+ # elements in the array.
+
+ print "\nORIGINAL\n" ;
+ foreach $i (0 .. $H->length - 1) {
+ print "$i: $h[$i]\n" ;
+ }
+
+ # use the push & pop methods
+ $a = $H->pop ;
+ $H->push("last") ;
+ print "\nThe last record was [$a]\n" ;
+
+ # and the shift & unshift methods
+ $a = $H->shift ;
+ $H->unshift("first") ;
+ print "The first record was [$a]\n" ;
+
+ # Use the API to add a new record after record 2.
+ $i = 2 ;
+ $H->put($i, "Newbie", R_IAFTER) ;
+
+ # and a new record before record 1.
+ $i = 1 ;
+ $H->put($i, "New One", R_IBEFORE) ;
+
+ # delete record 3
+ $H->del(3) ;
+
+ # now print the records in reverse order
+ print "\nREVERSE\n" ;
+ for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
+ { print "$i: $h[$i]\n" }
+
+ # same again, but use the API functions instead
+ print "\nREVERSE again\n" ;
+ my ($s, $k, $v) = (0, 0, 0) ;
+ for ($s = $H->seq($k, $v, R_LAST) ;
+ $s == 0 ;
+ $s = $H->seq($k, $v, R_PREV))
+ { print "$k: $v\n" }
+
+ undef $H ;
+ untie @h ;
+
+and this is what it outputs:
+
+ ORIGINAL
+ 0: zero
+ 1: one
+ 2: two
+ 3: three
+ 4: four
+
+ The last record was [four]
+ The first record was [zero]
+
+ REVERSE
+ 5: last
+ 4: three
+ 3: Newbie
+ 2: one
+ 1: New One
+ 0: first
+
+ REVERSE again
+ 5: last
+ 4: three
+ 3: Newbie
+ 2: one
+ 1: New One
+ 0: first
+
+Notes:
+
+=over 5
+
+=item 1.
+
+Rather than iterating through the array, C<@h> like this:
+
+ foreach $i (@h)
+
+it is necessary to use either this:
+
+ foreach $i (0 .. $H->length - 1)
+
+or this:
+
+ for ($a = $H->get($k, $v, R_FIRST) ;
+ $a == 0 ;
+ $a = $H->get($k, $v, R_NEXT) )
+
+=item 2.
+
+Notice that both times the C<put> method was used the record index was
+specified using a variable, C<$i>, rather than the literal value
+itself. This is because C<put> will return the record number of the
+inserted line via that parameter.
+
+=back
+
+=head1 THE API INTERFACE
+
+As well as accessing Berkeley DB using a tied hash or array, it is also
+possible to make direct use of most of the API functions defined in the
+Berkeley DB documentation.
+
+To do this you need to store a copy of the object returned from the tie.
+
+ $db = tie %hash, "DB_File", "filename" ;
+
+Once you have done that, you can access the Berkeley DB API functions
+as B<DB_File> methods directly like this:
+
+ $db->put($key, $value, R_NOOVERWRITE) ;
+
+B<Important:> If you have saved a copy of the object returned from
+C<tie>, the underlying database file will I<not> be closed until both
+the tied variable is untied and all copies of the saved object are
+destroyed.
+
+ use DB_File ;
+ $db = tie %hash, "DB_File", "filename"
+ or die "Cannot tie filename: $!" ;
+ ...
+ undef $db ;
+ untie %hash ;
+
+See L<The untie() Gotcha> for more details.
+
+All the functions defined in L<dbopen> are available except for
+close() and dbopen() itself. The B<DB_File> method interface to the
+supported functions have been implemented to mirror the way Berkeley DB
+works whenever possible. In particular note that:
+
+=over 5
+
+=item *
+
+The methods return a status value. All return 0 on success.
+All return -1 to signify an error and set C<$!> to the exact
+error code. The return code 1 generally (but not always) means that the
+key specified did not exist in the database.
+
+Other return codes are defined. See below and in the Berkeley DB
+documentation for details. The Berkeley DB documentation should be used
+as the definitive source.
+
+=item *
+
+Whenever a Berkeley DB function returns data via one of its parameters,
+the equivalent B<DB_File> method does exactly the same.
+
+=item *
+
+If you are careful, it is possible to mix API calls with the tied
+hash/array interface in the same piece of code. Although only a few of
+the methods used to implement the tied interface currently make use of
+the cursor, you should always assume that the cursor has been changed
+any time the tied hash/array interface is used. As an example, this
+code will probably not do what you expect:
+
+ $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
+ or die "Cannot tie $filename: $!" ;
+
+ # Get the first key/value pair and set the cursor
+ $X->seq($key, $value, R_FIRST) ;
+
+ # this line will modify the cursor
+ $count = scalar keys %x ;
+
+ # Get the second key/value pair.
+ # oops, it didn't, it got the last key/value pair!
+ $X->seq($key, $value, R_NEXT) ;
+
+The code above can be rearranged to get around the problem, like this:
+
+ $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
+ or die "Cannot tie $filename: $!" ;
+
+ # this line will modify the cursor
+ $count = scalar keys %x ;
+
+ # Get the first key/value pair and set the cursor
+ $X->seq($key, $value, R_FIRST) ;
+
+ # Get the second key/value pair.
+ # worked this time.
+ $X->seq($key, $value, R_NEXT) ;
+
+=back
+
+All the constants defined in L<dbopen> for use in the flags parameters
+in the methods defined below are also available. Refer to the Berkeley
+DB documentation for the precise meaning of the flags values.
+
+Below is a list of the methods available.
+
+=over 5
+
+=item B<$status = $X-E<gt>get($key, $value [, $flags]) ;>
+
+Given a key (C<$key>) this method reads the value associated with it
+from the database. The value read from the database is returned in the
+C<$value> parameter.
+
+If the key does not exist the method returns 1.
+
+No flags are currently defined for this method.
+
+=item B<$status = $X-E<gt>put($key, $value [, $flags]) ;>
+
+Stores the key/value pair in the database.
+
+If you use either the R_IAFTER or R_IBEFORE flags, the C<$key> parameter
+will have the record number of the inserted key/value pair set.
+
+Valid flags are R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE and
+R_SETCURSOR.
+
+=item B<$status = $X-E<gt>del($key [, $flags]) ;>
+
+Removes all key/value pairs with key C<$key> from the database.
+
+A return code of 1 means that the requested key was not in the
+database.
+
+R_CURSOR is the only valid flag at present.
+
+=item B<$status = $X-E<gt>fd ;>
+
+Returns the file descriptor for the underlying database.
+
+See L<Locking: The Trouble with fd> for an explanation for why you should
+not use C<fd> to lock your database.
+
+=item B<$status = $X-E<gt>seq($key, $value, $flags) ;>
+
+This interface allows sequential retrieval from the database. See
+L<dbopen> for full details.
+
+Both the C<$key> and C<$value> parameters will be set to the key/value
+pair read from the database.
+
+The flags parameter is mandatory. The valid flag values are R_CURSOR,
+R_FIRST, R_LAST, R_NEXT and R_PREV.
+
+=item B<$status = $X-E<gt>sync([$flags]) ;>
+
+Flushes any cached buffers to disk.
+
+R_RECNOSYNC is the only valid flag at present.
+
+=back
+
+=head1 DBM FILTERS
+
+A DBM Filter is a piece of code that is be used when you I<always>
+want to make the same transformation to all keys and/or values in a
+DBM database.
+
+There are four methods associated with DBM Filters. All work identically,
+and each is used to install (or uninstall) a single DBM Filter. Each
+expects a single parameter, namely a reference to a sub. The only
+difference between them is the place that the filter is installed.
+
+To summarise:
+
+=over 5
+
+=item B<filter_store_key>
+
+If a filter has been installed with this method, it will be invoked
+every time you write a key to a DBM database.
+
+=item B<filter_store_value>
+
+If a filter has been installed with this method, it will be invoked
+every time you write a value to a DBM database.
+
+
+=item B<filter_fetch_key>
+
+If a filter has been installed with this method, it will be invoked
+every time you read a key from a DBM database.
+
+=item B<filter_fetch_value>
+
+If a filter has been installed with this method, it will be invoked
+every time you read a value from a DBM database.
+
+=back
+
+You can use any combination of the methods, from none, to all four.
+
+All filter methods return the existing filter, if present, or C<undef>
+in not.
+
+To delete a filter pass C<undef> to it.
+
+=head2 The Filter
+
+When each filter is called by Perl, a local copy of C<$_> will contain
+the key or value to be filtered. Filtering is achieved by modifying
+the contents of C<$_>. The return code from the filter is ignored.
+
+=head2 An Example -- the NULL termination problem.
+
+Consider the following scenario. You have a DBM database
+that you need to share with a third-party C application. The C application
+assumes that I<all> keys and values are NULL terminated. Unfortunately
+when Perl writes to DBM databases it doesn't use NULL termination, so
+your Perl application will have to manage NULL termination itself. When
+you write to the database you will have to use something like this:
+
+ $hash{"$key\0"} = "$value\0" ;
+
+Similarly the NULL needs to be taken into account when you are considering
+the length of existing keys/values.
+
+It would be much better if you could ignore the NULL terminations issue
+in the main application code and have a mechanism that automatically
+added the terminating NULL to all keys and values whenever you write to
+the database and have them removed when you read from the database. As I'm
+sure you have already guessed, this is a problem that DBM Filters can
+fix very easily.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ my %hash ;
+ my $filename = "/tmp/filt" ;
+ unlink $filename ;
+
+ my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
+ or die "Cannot open $filename: $!\n" ;
+
+ # Install DBM Filters
+ $db->filter_fetch_key ( sub { s/\0$// } ) ;
+ $db->filter_store_key ( sub { $_ .= "\0" } ) ;
+ $db->filter_fetch_value( sub { s/\0$// } ) ;
+ $db->filter_store_value( sub { $_ .= "\0" } ) ;
+
+ $hash{"abc"} = "def" ;
+ my $a = $hash{"ABC"} ;
+ # ...
+ undef $db ;
+ untie %hash ;
+
+Hopefully the contents of each of the filters should be
+self-explanatory. Both "fetch" filters remove the terminating NULL,
+and both "store" filters add a terminating NULL.
+
+
+=head2 Another Example -- Key is a C int.
+
+Here is another real-life example. By default, whenever Perl writes to
+a DBM database it always writes the key and value as strings. So when
+you use this:
+
+ $hash{12345} = "soemthing" ;
+
+the key 12345 will get stored in the DBM database as the 5 byte string
+"12345". If you actually want the key to be stored in the DBM database
+as a C int, you will have to use C<pack> when writing, and C<unpack>
+when reading.
+
+Here is a DBM Filter that does it:
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+ my %hash ;
+ my $filename = "/tmp/filt" ;
+ unlink $filename ;
+
+
+ my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
+ or die "Cannot open $filename: $!\n" ;
+
+ $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ;
+ $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ;
+ $hash{123} = "def" ;
+ # ...
+ undef $db ;
+ untie %hash ;
+
+This time only two filters have been used -- we only need to manipulate
+the contents of the key, so it wasn't necessary to install any value
+filters.
+
+=head1 HINTS AND TIPS
+
+
+=head2 Locking: The Trouble with fd
+
+Until version 1.72 of this module, the recommended technique for locking
+B<DB_File> databases was to flock the filehandle returned from the "fd"
+function. Unfortunately this technique has been shown to be fundamentally
+flawed (Kudos to David Harris for tracking this down). Use it at your own
+peril!
+
+The locking technique went like this.
+
+ $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0666)
+ || die "dbcreat /tmp/foo.db $!";
+ $fd = $db->fd;
+ open(DB_FH, "+<&=$fd") || die "dup $!";
+ flock (DB_FH, LOCK_EX) || die "flock: $!";
+ ...
+ $db{"Tom"} = "Jerry" ;
+ ...
+ flock(DB_FH, LOCK_UN);
+ undef $db;
+ untie %db;
+ close(DB_FH);
+
+In simple terms, this is what happens:
+
+=over 5
+
+=item 1.
+
+Use "tie" to open the database.
+
+=item 2.
+
+Lock the database with fd & flock.
+
+=item 3.
+
+Read & Write to the database.
+
+=item 4.
+
+Unlock and close the database.
+
+=back
+
+Here is the crux of the problem. A side-effect of opening the B<DB_File>
+database in step 2 is that an initial block from the database will get
+read from disk and cached in memory.
+
+To see why this is a problem, consider what can happen when two processes,
+say "A" and "B", both want to update the same B<DB_File> database
+using the locking steps outlined above. Assume process "A" has already
+opened the database and has a write lock, but it hasn't actually updated
+the database yet (it has finished step 2, but not started step 3 yet). Now
+process "B" tries to open the same database - step 1 will succeed,
+but it will block on step 2 until process "A" releases the lock. The
+important thing to notice here is that at this point in time both
+processes will have cached identical initial blocks from the database.
+
+Now process "A" updates the database and happens to change some of the
+data held in the initial buffer. Process "A" terminates, flushing
+all cached data to disk and releasing the database lock. At this point
+the database on disk will correctly reflect the changes made by process
+"A".
+
+With the lock released, process "B" can now continue. It also updates the
+database and unfortunately it too modifies the data that was in its
+initial buffer. Once that data gets flushed to disk it will overwrite
+some/all of the changes process "A" made to the database.
+
+The result of this scenario is at best a database that doesn't contain
+what you expect. At worst the database will corrupt.
+
+The above won't happen every time competing process update the same
+B<DB_File> database, but it does illustrate why the technique should
+not be used.
+
+=head2 Safe ways to lock a database
+
+Starting with version 2.x, Berkeley DB has internal support for locking.
+The companion module to this one, B<BerkeleyDB>, provides an interface
+to this locking functionality. If you are serious about locking
+Berkeley DB databases, I strongly recommend using B<BerkeleyDB>.
+
+If using B<BerkeleyDB> isn't an option, there are a number of modules
+available on CPAN that can be used to implement locking. Each one
+implements locking differently and has different goals in mind. It is
+therefore worth knowing the difference, so that you can pick the right
+one for your application. Here are the three locking wrappers:
+
+=over 5
+
+=item B<Tie::DB_Lock>
+
+A B<DB_File> wrapper which creates copies of the database file for
+read access, so that you have a kind of a multiversioning concurrent read
+system. However, updates are still serial. Use for databases where reads
+may be lengthy and consistency problems may occur.
+
+=item B<Tie::DB_LockFile>
+
+A B<DB_File> wrapper that has the ability to lock and unlock the database
+while it is being used. Avoids the tie-before-flock problem by simply
+re-tie-ing the database when you get or drop a lock. Because of the
+flexibility in dropping and re-acquiring the lock in the middle of a
+session, this can be massaged into a system that will work with long
+updates and/or reads if the application follows the hints in the POD
+documentation.
+
+=item B<DB_File::Lock>
+
+An extremely lightweight B<DB_File> wrapper that simply flocks a lockfile
+before tie-ing the database and drops the lock after the untie. Allows
+one to use the same lockfile for multiple databases to avoid deadlock
+problems, if desired. Use for databases where updates are reads are
+quick and simple flock locking semantics are enough.
+
+=back
+
+=head2 Sharing Databases With C Applications
+
+There is no technical reason why a Berkeley DB database cannot be
+shared by both a Perl and a C application.
+
+The vast majority of problems that are reported in this area boil down
+to the fact that C strings are NULL terminated, whilst Perl strings are
+not. See L<DBM FILTERS> for a generic way to work around this problem.
+
+Here is a real example. Netscape 2.0 keeps a record of the locations you
+visit along with the time you last visited them in a DB_HASH database.
+This is usually stored in the file F<~/.netscape/history.db>. The key
+field in the database is the location string and the value field is the
+time the location was last visited stored as a 4 byte binary value.
+
+If you haven't already guessed, the location string is stored with a
+terminating NULL. This means you need to be careful when accessing the
+database.
+
+Here is a snippet of code that is loosely based on Tom Christiansen's
+I<ggh> script (available from your nearest CPAN archive in
+F<authors/id/TOMC/scripts/nshist.gz>).
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+ use Fcntl ;
+
+ my ($dotdir, $HISTORY, %hist_db, $href, $binary_time, $date) ;
+ $dotdir = $ENV{HOME} || $ENV{LOGNAME};
+
+ $HISTORY = "$dotdir/.netscape/history.db";
+
+ tie %hist_db, 'DB_File', $HISTORY
+ or die "Cannot open $HISTORY: $!\n" ;;
+
+ # Dump the complete database
+ while ( ($href, $binary_time) = each %hist_db ) {
+
+ # remove the terminating NULL
+ $href =~ s/\x00$// ;
+
+ # convert the binary time into a user friendly string
+ $date = localtime unpack("V", $binary_time);
+ print "$date $href\n" ;
+ }
+
+ # check for the existence of a specific key
+ # remember to add the NULL
+ if ( $binary_time = $hist_db{"http://mox.perl.com/\x00"} ) {
+ $date = localtime unpack("V", $binary_time) ;
+ print "Last visited mox.perl.com on $date\n" ;
+ }
+ else {
+ print "Never visited mox.perl.com\n"
+ }
+
+ untie %hist_db ;
+
+=head2 The untie() Gotcha
+
+If you make use of the Berkeley DB API, it is I<very> strongly
+recommended that you read L<perltie/The untie Gotcha>.
+
+Even if you don't currently make use of the API interface, it is still
+worth reading it.
+
+Here is an example which illustrates the problem from a B<DB_File>
+perspective:
+
+ use DB_File ;
+ use Fcntl ;
+
+ my %x ;
+ my $X ;
+
+ $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_TRUNC
+ or die "Cannot tie first time: $!" ;
+
+ $x{123} = 456 ;
+
+ untie %x ;
+
+ tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
+ or die "Cannot tie second time: $!" ;
+
+ untie %x ;
+
+When run, the script will produce this error message:
+
+ Cannot tie second time: Invalid argument at bad.file line 14.
+
+Although the error message above refers to the second tie() statement
+in the script, the source of the problem is really with the untie()
+statement that precedes it.
+
+Having read L<perltie> you will probably have already guessed that the
+error is caused by the extra copy of the tied object stored in C<$X>.
+If you haven't, then the problem boils down to the fact that the
+B<DB_File> destructor, DESTROY, will not be called until I<all>
+references to the tied object are destroyed. Both the tied variable,
+C<%x>, and C<$X> above hold a reference to the object. The call to
+untie() will destroy the first, but C<$X> still holds a valid
+reference, so the destructor will not get called and the database file
+F<tst.fil> will remain open. The fact that Berkeley DB then reports the
+attempt to open a database that is already open via the catch-all
+"Invalid argument" doesn't help.
+
+If you run the script with the C<-w> flag the error message becomes:
+
+ untie attempted while 1 inner references still exist at bad.file line 12.
+ Cannot tie second time: Invalid argument at bad.file line 14.
+
+which pinpoints the real problem. Finally the script can now be
+modified to fix the original problem by destroying the API object
+before the untie:
+
+ ...
+ $x{123} = 456 ;
+
+ undef $X ;
+ untie %x ;
+
+ $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
+ ...
+
+
+=head1 COMMON QUESTIONS
+
+=head2 Why is there Perl source in my database?
+
+If you look at the contents of a database file created by DB_File,
+there can sometimes be part of a Perl script included in it.
+
+This happens because Berkeley DB uses dynamic memory to allocate
+buffers which will subsequently be written to the database file. Being
+dynamic, the memory could have been used for anything before DB
+malloced it. As Berkeley DB doesn't clear the memory once it has been
+allocated, the unused portions will contain random junk. In the case
+where a Perl script gets written to the database, the random junk will
+correspond to an area of dynamic memory that happened to be used during
+the compilation of the script.
+
+Unless you don't like the possibility of there being part of your Perl
+scripts embedded in a database file, this is nothing to worry about.
+
+=head2 How do I store complex data structures with DB_File?
+
+Although B<DB_File> cannot do this directly, there is a module which
+can layer transparently over B<DB_File> to accomplish this feat.
+
+Check out the MLDBM module, available on CPAN in the directory
+F<modules/by-module/MLDBM>.
+
+=head2 What does "Invalid Argument" mean?
+
+You will get this error message when one of the parameters in the
+C<tie> call is wrong. Unfortunately there are quite a few parameters to
+get wrong, so it can be difficult to figure out which one it is.
+
+Here are a couple of possibilities:
+
+=over 5
+
+=item 1.
+
+Attempting to reopen a database without closing it.
+
+=item 2.
+
+Using the O_WRONLY flag.
+
+=back
+
+=head2 What does "Bareword 'DB_File' not allowed" mean?
+
+You will encounter this particular error message when you have the
+C<strict 'subs'> pragma (or the full strict pragma) in your script.
+Consider this script:
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+ my %x ;
+ tie %x, DB_File, "filename" ;
+
+Running it produces the error in question:
+
+ Bareword "DB_File" not allowed while "strict subs" in use
+
+To get around the error, place the word C<DB_File> in either single or
+double quotes, like this:
+
+ tie %x, "DB_File", "filename" ;
+
+Although it might seem like a real pain, it is really worth the effort
+of having a C<use strict> in all your scripts.
+
+=head1 REFERENCES
+
+Articles that are either about B<DB_File> or make use of it.
+
+=over 5
+
+=item 1.
+
+I<Full-Text Searching in Perl>, Tim Kientzle (tkientzle@ddj.com),
+Dr. Dobb's Journal, Issue 295, January 1999, pp 34-41
+
+=back
+
+=head1 HISTORY
+
+Moved to the Changes file.
+
+=head1 BUGS
+
+Some older versions of Berkeley DB had problems with fixed length
+records using the RECNO file format. This problem has been fixed since
+version 1.85 of Berkeley DB.
+
+I am sure there are bugs in the code. If you do find any, or can
+suggest any enhancements, I would welcome your comments.
+
+=head1 AVAILABILITY
+
+B<DB_File> comes with the standard Perl source distribution. Look in
+the directory F<ext/DB_File>. Given the amount of time between releases
+of Perl the version that ships with Perl is quite likely to be out of
+date, so the most recent version can always be found on CPAN (see
+L<perlmod/CPAN> for details), in the directory
+F<modules/by-module/DB_File>.
+
+This version of B<DB_File> will work with either version 1.x, 2.x or
+3.x of Berkeley DB, but is limited to the functionality provided by
+version 1.
+
+The official web site for Berkeley DB is F<http://www.sleepycat.com>.
+All versions of Berkeley DB are available there.
+
+Alternatively, Berkeley DB version 1 is available at your nearest CPAN
+archive in F<src/misc/db.1.85.tar.gz>.
+
+If you are running IRIX, then get Berkeley DB version 1 from
+F<http://reality.sgi.com/ariel>. It has the patches necessary to
+compile properly on IRIX 5.3.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program
+is free software; you can redistribute it and/or modify it under the
+same terms as Perl itself.
+
+Although B<DB_File> is covered by the Perl license, the library it
+makes use of, namely Berkeley DB, is not. Berkeley DB has its own
+copyright and its own license. Please take the time to read it.
+
+Here are are few words taken from the Berkeley DB FAQ (at
+F<http://www.sleepycat.com>) regarding the license:
+
+ Do I have to license DB to use it in Perl scripts?
+
+ No. The Berkeley DB license requires that software that uses
+ Berkeley DB be freely redistributable. In the case of Perl, that
+ software is Perl, and not your scripts. Any Perl scripts that you
+ write are your property, including scripts that make use of
+ Berkeley DB. Neither the Perl license nor the Berkeley DB license
+ place any restriction on what you may do with them.
+
+If you are in any doubt about the license situation, contact either the
+Berkeley DB authors or the author of DB_File. See L<"AUTHOR"> for details.
+
+
+=head1 SEE ALSO
+
+L<perl(1)>, L<dbopen(3)>, L<hash(3)>, L<recno(3)>, L<btree(3)>,
+L<dbmfilter>
+
+=head1 AUTHOR
+
+The DB_File interface was written by Paul Marquess
+E<lt>Paul.Marquess@btinternet.comE<gt>.
+Questions about the DB system itself may be addressed to
+E<lt>db@sleepycat.com<gt>.
+
+=cut
diff --git a/bdb/perl/DB_File/DB_File.xs b/bdb/perl/DB_File/DB_File.xs
new file mode 100644
index 00000000000..fba8dede791
--- /dev/null
+++ b/bdb/perl/DB_File/DB_File.xs
@@ -0,0 +1,1951 @@
+/*
+
+ DB_File.xs -- Perl 5 interface to Berkeley DB
+
+ written by Paul Marquess <Paul.Marquess@btinternet.com>
+ last modified 1st September 2002
+ version 1.805
+
+ All comments/suggestions/problems are welcome
+
+ Copyright (c) 1995-2002 Paul Marquess. All rights reserved.
+ This program is free software; you can redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+ Changes:
+ 0.1 - Initial Release
+ 0.2 - No longer bombs out if dbopen returns an error.
+ 0.3 - Added some support for multiple btree compares
+ 1.0 - Complete support for multiple callbacks added.
+ Fixed a problem with pushing a value onto an empty list.
+ 1.01 - Fixed a SunOS core dump problem.
+ The return value from TIEHASH wasn't set to NULL when
+ dbopen returned an error.
+ 1.02 - Use ALIAS to define TIEARRAY.
+ Removed some redundant commented code.
+ Merged OS2 code into the main distribution.
+ Allow negative subscripts with RECNO interface.
+ Changed the default flags to O_CREAT|O_RDWR
+ 1.03 - Added EXISTS
+ 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
+ Dave Hammen, hammen@gothamcity.jsc.nasa.gov
+ 1.05 - Added logic to allow prefix & hash types to be specified via
+ Makefile.PL
+ 1.06 - Minor namespace cleanup: Localized PrintBtree.
+ 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
+ 1.08 - No change to DB_File.xs
+ 1.09 - Default mode for dbopen changed to 0666
+ 1.10 - Fixed fd method so that it still returns -1 for
+ in-memory files when db 1.86 is used.
+ 1.11 - No change to DB_File.xs
+ 1.12 - No change to DB_File.xs
+ 1.13 - Tidied up a few casts.
+ 1.14 - Made it illegal to tie an associative array to a RECNO
+ database and an ordinary array to a HASH or BTREE database.
+ 1.50 - Make work with both DB 1.x or DB 2.x
+ 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
+ 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of
+ undefined value" warning with db_get and db_seq.
+ 1.53 - Added DB_RENUMBER to flags for recno.
+ 1.54 - Fixed bug in the fd method
+ 1.55 - Fix for AIX from Jarkko Hietaniemi
+ 1.56 - No change to DB_File.xs
+ 1.57 - added the #undef op to allow building with Threads support.
+ 1.58 - Fixed a problem with the use of sv_setpvn. When the
+ size is specified as 0, it does a strlen on the data.
+ This was ok for DB 1.x, but isn't for DB 2.x.
+ 1.59 - No change to DB_File.xs
+ 1.60 - Some code tidy up
+ 1.61 - added flagSet macro for DB 2.5.x
+ fixed typo in O_RDONLY test.
+ 1.62 - No change to DB_File.xs
+ 1.63 - Fix to alllow DB 2.6.x to build.
+ 1.64 - Tidied up the 1.x to 2.x flags mapping code.
+ Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
+ to fix a flag mapping problem with O_RDONLY on the Hurd
+ 1.65 - Fixed a bug in the PUSH logic.
+ Added BOOT check that using 2.3.4 or greater
+ 1.66 - Added DBM filter code
+ 1.67 - Backed off the use of newSVpvn.
+ Fixed DBM Filter code for Perl 5.004.
+ Fixed a small memory leak in the filter code.
+ 1.68 - fixed backward compatability bug with R_IAFTER & R_IBEFORE
+ merged in the 5.005_58 changes
+ 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly.
+ Fixed the R_SETCURSOR bug introduced in 1.68
+ Added a new Perl variable $DB_File::db_ver
+ 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with
+ GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
+ Added a BOOT check to test for equivalent versions of db.h &
+ libdb.a/so.
+ 1.71 - Support for Berkeley DB version 3.
+ Support for Berkeley DB 2/3's backward compatability mode.
+ Rewrote push
+ 1.72 - No change to DB_File.xs
+ 1.73 - No change to DB_File.xs
+ 1.74 - A call to open needed parenthesised to stop it clashing
+ with a win32 macro.
+ Added Perl core patches 7703 & 7801.
+ 1.75 - Fixed Perl core patch 7703.
+ Added suppport to allow DB_File to be built with
+ Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
+ needed to be changed.
+ 1.76 - No change to DB_File.xs
+ 1.77 - Tidied up a few types used in calling newSVpvn.
+ 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included.
+ 1.79 - NEXTKEY ignores the input key.
+ Added lots of casts
+ 1.800 - Moved backward compatability code into ppport.h.
+ Use the new constants code.
+ 1.801 - No change to DB_File.xs
+ 1.802 - No change to DB_File.xs
+ 1.803 - FETCH, STORE & DELETE don't map the flags parameter
+ into the equivalent Berkeley DB function anymore.
+ 1.804 - no change.
+ 1.805 - recursion detection added to the callbacks
+ Support for 4.1.X added.
+ Filter code can now cope with read-only $_
+
+*/
+
+#define PERL_NO_GET_CONTEXT
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#ifdef _NOT_CORE
+# include "ppport.h"
+#endif
+
+/* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
+ DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
+
+/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
+ * shortly #included by the <db.h>) __attribute__ to the possibly
+ * already defined __attribute__, for example by GNUC or by Perl. */
+
+/* #if DB_VERSION_MAJOR_CFG < 2 */
+#ifndef DB_VERSION_MAJOR
+# undef __attribute__
+#endif
+
+#ifdef COMPAT185
+# include <db_185.h>
+#else
+# include <db.h>
+#endif
+
+/* Wall starts with 5.7.x */
+
+#if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
+
+/* Since we dropped the gccish definition of __attribute__ we will want
+ * to redefine dNOOP, however (so that dTHX continues to work). Yes,
+ * all this means that we can't do attribute checking on the DB_File,
+ * boo, hiss. */
+# ifndef DB_VERSION_MAJOR
+
+# undef dNOOP
+# define dNOOP extern int Perl___notused
+
+ /* Ditto for dXSARGS. */
+# undef dXSARGS
+# define dXSARGS \
+ dSP; dMARK; \
+ I32 ax = mark - PL_stack_base + 1; \
+ I32 items = sp - mark
+
+# endif
+
+/* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
+# undef dXSI32
+# define dXSI32 dNOOP
+
+#endif /* Perl >= 5.7 */
+
+#include <fcntl.h>
+
+/* #define TRACE */
+
+#ifdef TRACE
+# define Trace(x) printf x
+#else
+# define Trace(x)
+#endif
+
+
+#define DBT_clear(x) Zero(&x, 1, DBT) ;
+
+#ifdef DB_VERSION_MAJOR
+
+#if DB_VERSION_MAJOR == 2
+# define BERKELEY_DB_1_OR_2
+#endif
+
+#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
+# define AT_LEAST_DB_3_2
+#endif
+
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
+# define AT_LEAST_DB_4_1
+#endif
+
+/* map version 2 features & constants onto their version 1 equivalent */
+
+#ifdef DB_Prefix_t
+# undef DB_Prefix_t
+#endif
+#define DB_Prefix_t size_t
+
+#ifdef DB_Hash_t
+# undef DB_Hash_t
+#endif
+#define DB_Hash_t u_int32_t
+
+/* DBTYPE stays the same */
+/* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
+#if DB_VERSION_MAJOR == 2
+ typedef DB_INFO INFO ;
+#else /* DB_VERSION_MAJOR > 2 */
+# define DB_FIXEDLEN (0x8000)
+#endif /* DB_VERSION_MAJOR == 2 */
+
+/* version 2 has db_recno_t in place of recno_t */
+typedef db_recno_t recno_t;
+
+
+#define R_CURSOR DB_SET_RANGE
+#define R_FIRST DB_FIRST
+#define R_IAFTER DB_AFTER
+#define R_IBEFORE DB_BEFORE
+#define R_LAST DB_LAST
+#define R_NEXT DB_NEXT
+#define R_NOOVERWRITE DB_NOOVERWRITE
+#define R_PREV DB_PREV
+
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
+# define R_SETCURSOR 0x800000
+#else
+# define R_SETCURSOR (-100)
+#endif
+
+#define R_RECNOSYNC 0
+#define R_FIXEDLEN DB_FIXEDLEN
+#define R_DUP DB_DUP
+
+
+#define db_HA_hash h_hash
+#define db_HA_ffactor h_ffactor
+#define db_HA_nelem h_nelem
+#define db_HA_bsize db_pagesize
+#define db_HA_cachesize db_cachesize
+#define db_HA_lorder db_lorder
+
+#define db_BT_compare bt_compare
+#define db_BT_prefix bt_prefix
+#define db_BT_flags flags
+#define db_BT_psize db_pagesize
+#define db_BT_cachesize db_cachesize
+#define db_BT_lorder db_lorder
+#define db_BT_maxkeypage
+#define db_BT_minkeypage
+
+
+#define db_RE_reclen re_len
+#define db_RE_flags flags
+#define db_RE_bval re_pad
+#define db_RE_bfname re_source
+#define db_RE_psize db_pagesize
+#define db_RE_cachesize db_cachesize
+#define db_RE_lorder db_lorder
+
+#define TXN NULL,
+
+#define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
+
+
+#define DBT_flags(x) x.flags = 0
+#define DB_flags(x, v) x |= v
+
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
+# define flagSet(flags, bitmask) ((flags) & (bitmask))
+#else
+# define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
+#endif
+
+#else /* db version 1.x */
+
+#define BERKELEY_DB_1
+#define BERKELEY_DB_1_OR_2
+
+typedef union INFO {
+ HASHINFO hash ;
+ RECNOINFO recno ;
+ BTREEINFO btree ;
+ } INFO ;
+
+
+#ifdef mDB_Prefix_t
+# ifdef DB_Prefix_t
+# undef DB_Prefix_t
+# endif
+# define DB_Prefix_t mDB_Prefix_t
+#endif
+
+#ifdef mDB_Hash_t
+# ifdef DB_Hash_t
+# undef DB_Hash_t
+# endif
+# define DB_Hash_t mDB_Hash_t
+#endif
+
+#define db_HA_hash hash.hash
+#define db_HA_ffactor hash.ffactor
+#define db_HA_nelem hash.nelem
+#define db_HA_bsize hash.bsize
+#define db_HA_cachesize hash.cachesize
+#define db_HA_lorder hash.lorder
+
+#define db_BT_compare btree.compare
+#define db_BT_prefix btree.prefix
+#define db_BT_flags btree.flags
+#define db_BT_psize btree.psize
+#define db_BT_cachesize btree.cachesize
+#define db_BT_lorder btree.lorder
+#define db_BT_maxkeypage btree.maxkeypage
+#define db_BT_minkeypage btree.minkeypage
+
+#define db_RE_reclen recno.reclen
+#define db_RE_flags recno.flags
+#define db_RE_bval recno.bval
+#define db_RE_bfname recno.bfname
+#define db_RE_psize recno.psize
+#define db_RE_cachesize recno.cachesize
+#define db_RE_lorder recno.lorder
+
+#define TXN
+
+#define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
+#define DBT_flags(x)
+#define DB_flags(x, v)
+#define flagSet(flags, bitmask) ((flags) & (bitmask))
+
+#endif /* db version 1 */
+
+
+
+#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
+#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
+#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
+
+#define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
+#define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
+
+#ifdef DB_VERSION_MAJOR
+#define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\
+ (db->dbp->close)(db->dbp, 0) ))
+#define db_close(db) ((db->dbp)->close)(db->dbp, 0)
+#define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
+ ? ((db->cursor)->c_del)(db->cursor, 0) \
+ : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
+
+#else /* ! DB_VERSION_MAJOR */
+
+#define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp))
+#define db_close(db) ((db->dbp)->close)(db->dbp)
+#define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
+#define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
+
+#endif /* ! DB_VERSION_MAJOR */
+
+
+#define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
+
+typedef struct {
+ DBTYPE type ;
+ DB * dbp ;
+ SV * compare ;
+ bool in_compare ;
+ SV * prefix ;
+ bool in_prefix ;
+ SV * hash ;
+ bool in_hash ;
+ bool aborted ;
+ int in_memory ;
+#ifdef BERKELEY_DB_1_OR_2
+ INFO info ;
+#endif
+#ifdef DB_VERSION_MAJOR
+ DBC * cursor ;
+#endif
+ SV * filter_fetch_key ;
+ SV * filter_store_key ;
+ SV * filter_fetch_value ;
+ SV * filter_store_value ;
+ int filtering ;
+
+ } DB_File_type;
+
+typedef DB_File_type * DB_File ;
+typedef DBT DBTKEY ;
+
+#define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
+
+#define OutputValue(arg, name) \
+ { if (RETVAL == 0) { \
+ my_sv_setpvn(arg, name.data, name.size) ; \
+ TAINT; \
+ SvTAINTED_on(arg); \
+ DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
+ } \
+ }
+
+#define OutputKey(arg, name) \
+ { if (RETVAL == 0) \
+ { \
+ if (db->type != DB_RECNO) { \
+ my_sv_setpvn(arg, name.data, name.size); \
+ } \
+ else \
+ sv_setiv(arg, (I32)*(I32*)name.data - 1); \
+ TAINT; \
+ SvTAINTED_on(arg); \
+ DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
+ } \
+ }
+
+#define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
+
+#ifdef CAN_PROTOTYPE
+extern void __getBerkeleyDBInfo(void);
+#endif
+
+/* Internal Global Data */
+
+#define MY_CXT_KEY "DB_File::_guts" XS_VERSION
+
+typedef struct {
+ recno_t x_Value;
+ recno_t x_zero;
+ DB_File x_CurrentDB;
+ DBTKEY x_empty;
+} my_cxt_t;
+
+START_MY_CXT
+
+#define Value (MY_CXT.x_Value)
+#define zero (MY_CXT.x_zero)
+#define CurrentDB (MY_CXT.x_CurrentDB)
+#define empty (MY_CXT.x_empty)
+
+#define ERR_BUFF "DB_File::Error"
+
+#ifdef DB_VERSION_MAJOR
+
+static int
+#ifdef CAN_PROTOTYPE
+db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
+#else
+db_put(db, key, value, flags)
+DB_File db ;
+DBTKEY key ;
+DBT value ;
+u_int flags ;
+#endif
+{
+ int status ;
+
+ if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
+ DBC * temp_cursor ;
+ DBT l_key, l_value;
+
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+ if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
+#else
+ if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
+#endif
+ return (-1) ;
+
+ memset(&l_key, 0, sizeof(l_key));
+ l_key.data = key.data;
+ l_key.size = key.size;
+ memset(&l_value, 0, sizeof(l_value));
+ l_value.data = value.data;
+ l_value.size = value.size;
+
+ if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
+ (void)temp_cursor->c_close(temp_cursor);
+ return (-1);
+ }
+
+ status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
+ (void)temp_cursor->c_close(temp_cursor);
+
+ return (status) ;
+ }
+
+
+ if (flagSet(flags, R_CURSOR)) {
+ return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
+ }
+
+ if (flagSet(flags, R_SETCURSOR)) {
+ if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
+ return -1 ;
+ return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
+
+ }
+
+ return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
+
+}
+
+#endif /* DB_VERSION_MAJOR */
+
+static void
+tidyUp(DB_File db)
+{
+ /* db_DESTROY(db); */
+ db->aborted = TRUE ;
+}
+
+
+static int
+#ifdef AT_LEAST_DB_3_2
+
+#ifdef CAN_PROTOTYPE
+btree_compare(DB * db, const DBT *key1, const DBT *key2)
+#else
+btree_compare(db, key1, key2)
+DB * db ;
+const DBT * key1 ;
+const DBT * key2 ;
+#endif /* CAN_PROTOTYPE */
+
+#else /* Berkeley DB < 3.2 */
+
+#ifdef CAN_PROTOTYPE
+btree_compare(const DBT *key1, const DBT *key2)
+#else
+btree_compare(key1, key2)
+const DBT * key1 ;
+const DBT * key2 ;
+#endif
+
+#endif
+
+{
+#ifdef dTHX
+ dTHX;
+#endif
+ dSP ;
+ dMY_CXT ;
+ void * data1, * data2 ;
+ int retval ;
+ int count ;
+ DB_File keep_CurrentDB = CurrentDB;
+
+
+ if (CurrentDB->in_compare) {
+ tidyUp(CurrentDB);
+ croak ("DB_File btree_compare: recursion detected\n") ;
+ }
+
+ data1 = (char *) key1->data ;
+ data2 = (char *) key2->data ;
+
+#ifndef newSVpvn
+ /* As newSVpv will assume that the data pointer is a null terminated C
+ string if the size parameter is 0, make sure that data points to an
+ empty string if the length is 0
+ */
+ if (key1->size == 0)
+ data1 = "" ;
+ if (key2->size == 0)
+ data2 = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+ EXTEND(SP,2) ;
+ PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
+ PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
+ PUTBACK ;
+
+ CurrentDB->in_compare = TRUE;
+
+ count = perl_call_sv(CurrentDB->compare, G_SCALAR);
+
+ CurrentDB = keep_CurrentDB;
+ CurrentDB->in_compare = FALSE;
+
+ SPAGAIN ;
+
+ if (count != 1){
+ tidyUp(CurrentDB);
+ croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
+ }
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+
+ return (retval) ;
+
+}
+
+static DB_Prefix_t
+#ifdef AT_LEAST_DB_3_2
+
+#ifdef CAN_PROTOTYPE
+btree_prefix(DB * db, const DBT *key1, const DBT *key2)
+#else
+btree_prefix(db, key1, key2)
+Db * db ;
+const DBT * key1 ;
+const DBT * key2 ;
+#endif
+
+#else /* Berkeley DB < 3.2 */
+
+#ifdef CAN_PROTOTYPE
+btree_prefix(const DBT *key1, const DBT *key2)
+#else
+btree_prefix(key1, key2)
+const DBT * key1 ;
+const DBT * key2 ;
+#endif
+
+#endif
+{
+#ifdef dTHX
+ dTHX;
+#endif
+ dSP ;
+ dMY_CXT ;
+ char * data1, * data2 ;
+ int retval ;
+ int count ;
+ DB_File keep_CurrentDB = CurrentDB;
+
+ if (CurrentDB->in_prefix){
+ tidyUp(CurrentDB);
+ croak ("DB_File btree_prefix: recursion detected\n") ;
+ }
+
+ data1 = (char *) key1->data ;
+ data2 = (char *) key2->data ;
+
+#ifndef newSVpvn
+ /* As newSVpv will assume that the data pointer is a null terminated C
+ string if the size parameter is 0, make sure that data points to an
+ empty string if the length is 0
+ */
+ if (key1->size == 0)
+ data1 = "" ;
+ if (key2->size == 0)
+ data2 = "" ;
+#endif
+
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+ EXTEND(SP,2) ;
+ PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
+ PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
+ PUTBACK ;
+
+ CurrentDB->in_prefix = TRUE;
+
+ count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
+
+ CurrentDB = keep_CurrentDB;
+ CurrentDB->in_prefix = FALSE;
+
+ SPAGAIN ;
+
+ if (count != 1){
+ tidyUp(CurrentDB);
+ croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
+ }
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+
+ return (retval) ;
+}
+
+
+#ifdef BERKELEY_DB_1
+# define HASH_CB_SIZE_TYPE size_t
+#else
+# define HASH_CB_SIZE_TYPE u_int32_t
+#endif
+
+static DB_Hash_t
+#ifdef AT_LEAST_DB_3_2
+
+#ifdef CAN_PROTOTYPE
+hash_cb(DB * db, const void *data, u_int32_t size)
+#else
+hash_cb(db, data, size)
+DB * db ;
+const void * data ;
+HASH_CB_SIZE_TYPE size ;
+#endif
+
+#else /* Berkeley DB < 3.2 */
+
+#ifdef CAN_PROTOTYPE
+hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
+#else
+hash_cb(data, size)
+const void * data ;
+HASH_CB_SIZE_TYPE size ;
+#endif
+
+#endif
+{
+#ifdef dTHX
+ dTHX;
+#endif
+ dSP ;
+ dMY_CXT;
+ int retval ;
+ int count ;
+ DB_File keep_CurrentDB = CurrentDB;
+
+ if (CurrentDB->in_hash){
+ tidyUp(CurrentDB);
+ croak ("DB_File hash callback: recursion detected\n") ;
+ }
+
+#ifndef newSVpvn
+ if (size == 0)
+ data = "" ;
+#endif
+
+ /* DGH - Next two lines added to fix corrupted stack problem */
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
+
+ XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
+ PUTBACK ;
+
+ keep_CurrentDB->in_hash = TRUE;
+
+ count = perl_call_sv(CurrentDB->hash, G_SCALAR);
+
+ CurrentDB = keep_CurrentDB;
+ CurrentDB->in_hash = FALSE;
+
+ SPAGAIN ;
+
+ if (count != 1){
+ tidyUp(CurrentDB);
+ croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
+ }
+
+ retval = POPi ;
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
+
+ return (retval) ;
+}
+
+static void
+#ifdef CAN_PROTOTYPE
+db_errcall_cb(const char * db_errpfx, char * buffer)
+#else
+db_errcall_cb(db_errpfx, buffer)
+const char * db_errpfx;
+char * buffer;
+#endif
+{
+ SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
+ if (sv) {
+ if (db_errpfx)
+ sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
+ else
+ sv_setpv(sv, buffer) ;
+ }
+}
+
+#if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
+
+static void
+#ifdef CAN_PROTOTYPE
+PrintHash(INFO *hash)
+#else
+PrintHash(hash)
+INFO * hash ;
+#endif
+{
+ printf ("HASH Info\n") ;
+ printf (" hash = %s\n",
+ (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
+ printf (" bsize = %d\n", hash->db_HA_bsize) ;
+ printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
+ printf (" nelem = %d\n", hash->db_HA_nelem) ;
+ printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
+ printf (" lorder = %d\n", hash->db_HA_lorder) ;
+
+}
+
+static void
+#ifdef CAN_PROTOTYPE
+PrintRecno(INFO *recno)
+#else
+PrintRecno(recno)
+INFO * recno ;
+#endif
+{
+ printf ("RECNO Info\n") ;
+ printf (" flags = %d\n", recno->db_RE_flags) ;
+ printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
+ printf (" psize = %d\n", recno->db_RE_psize) ;
+ printf (" lorder = %d\n", recno->db_RE_lorder) ;
+ printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
+ printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
+ printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
+}
+
+static void
+#ifdef CAN_PROTOTYPE
+PrintBtree(INFO *btree)
+#else
+PrintBtree(btree)
+INFO * btree ;
+#endif
+{
+ printf ("BTREE Info\n") ;
+ printf (" compare = %s\n",
+ (btree->db_BT_compare ? "redefined" : "default")) ;
+ printf (" prefix = %s\n",
+ (btree->db_BT_prefix ? "redefined" : "default")) ;
+ printf (" flags = %d\n", btree->db_BT_flags) ;
+ printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
+ printf (" psize = %d\n", btree->db_BT_psize) ;
+#ifndef DB_VERSION_MAJOR
+ printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
+ printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
+#endif
+ printf (" lorder = %d\n", btree->db_BT_lorder) ;
+}
+
+#else
+
+#define PrintRecno(recno)
+#define PrintHash(hash)
+#define PrintBtree(btree)
+
+#endif /* TRACE */
+
+
+static I32
+#ifdef CAN_PROTOTYPE
+GetArrayLength(pTHX_ DB_File db)
+#else
+GetArrayLength(db)
+DB_File db ;
+#endif
+{
+ DBT key ;
+ DBT value ;
+ int RETVAL ;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ RETVAL = do_SEQ(db, key, value, R_LAST) ;
+ if (RETVAL == 0)
+ RETVAL = *(I32 *)key.data ;
+ else /* No key means empty file */
+ RETVAL = 0 ;
+
+ return ((I32)RETVAL) ;
+}
+
+static recno_t
+#ifdef CAN_PROTOTYPE
+GetRecnoKey(pTHX_ DB_File db, I32 value)
+#else
+GetRecnoKey(db, value)
+DB_File db ;
+I32 value ;
+#endif
+{
+ if (value < 0) {
+ /* Get the length of the array */
+ I32 length = GetArrayLength(aTHX_ db) ;
+
+ /* check for attempt to write before start of array */
+ if (length + value + 1 <= 0) {
+ tidyUp(db);
+ croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
+ }
+
+ value = length + value + 1 ;
+ }
+ else
+ ++ value ;
+
+ return value ;
+}
+
+
+static DB_File
+#ifdef CAN_PROTOTYPE
+ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
+#else
+ParseOpenInfo(isHASH, name, flags, mode, sv)
+int isHASH ;
+char * name ;
+int flags ;
+int mode ;
+SV * sv ;
+#endif
+{
+
+#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
+
+ SV ** svp;
+ HV * action ;
+ DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
+ void * openinfo = NULL ;
+ INFO * info = &RETVAL->info ;
+ STRLEN n_a;
+ dMY_CXT;
+
+/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
+ Zero(RETVAL, 1, DB_File_type) ;
+
+ /* Default to HASH */
+ RETVAL->filtering = 0 ;
+ RETVAL->filter_fetch_key = RETVAL->filter_store_key =
+ RETVAL->filter_fetch_value = RETVAL->filter_store_value =
+ RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
+ RETVAL->type = DB_HASH ;
+
+ /* DGH - Next line added to avoid SEGV on existing hash DB */
+ CurrentDB = RETVAL;
+
+ /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
+ RETVAL->in_memory = (name == NULL) ;
+
+ if (sv)
+ {
+ if (! SvROK(sv) )
+ croak ("type parameter is not a reference") ;
+
+ svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
+ if (svp && SvOK(*svp))
+ action = (HV*) SvRV(*svp) ;
+ else
+ croak("internal error") ;
+
+ if (sv_isa(sv, "DB_File::HASHINFO"))
+ {
+
+ if (!isHASH)
+ croak("DB_File can only tie an associative array to a DB_HASH database") ;
+
+ RETVAL->type = DB_HASH ;
+ openinfo = (void*)info ;
+
+ svp = hv_fetch(action, "hash", 4, FALSE);
+
+ if (svp && SvOK(*svp))
+ {
+ info->db_HA_hash = hash_cb ;
+ RETVAL->hash = newSVsv(*svp) ;
+ }
+ else
+ info->db_HA_hash = NULL ;
+
+ svp = hv_fetch(action, "ffactor", 7, FALSE);
+ info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "nelem", 5, FALSE);
+ info->db_HA_nelem = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "bsize", 5, FALSE);
+ info->db_HA_bsize = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "cachesize", 9, FALSE);
+ info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "lorder", 6, FALSE);
+ info->db_HA_lorder = svp ? SvIV(*svp) : 0;
+
+ PrintHash(info) ;
+ }
+ else if (sv_isa(sv, "DB_File::BTREEINFO"))
+ {
+ if (!isHASH)
+ croak("DB_File can only tie an associative array to a DB_BTREE database");
+
+ RETVAL->type = DB_BTREE ;
+ openinfo = (void*)info ;
+
+ svp = hv_fetch(action, "compare", 7, FALSE);
+ if (svp && SvOK(*svp))
+ {
+ info->db_BT_compare = btree_compare ;
+ RETVAL->compare = newSVsv(*svp) ;
+ }
+ else
+ info->db_BT_compare = NULL ;
+
+ svp = hv_fetch(action, "prefix", 6, FALSE);
+ if (svp && SvOK(*svp))
+ {
+ info->db_BT_prefix = btree_prefix ;
+ RETVAL->prefix = newSVsv(*svp) ;
+ }
+ else
+ info->db_BT_prefix = NULL ;
+
+ svp = hv_fetch(action, "flags", 5, FALSE);
+ info->db_BT_flags = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "cachesize", 9, FALSE);
+ info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
+
+#ifndef DB_VERSION_MAJOR
+ svp = hv_fetch(action, "minkeypage", 10, FALSE);
+ info->btree.minkeypage = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "maxkeypage", 10, FALSE);
+ info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
+#endif
+
+ svp = hv_fetch(action, "psize", 5, FALSE);
+ info->db_BT_psize = svp ? SvIV(*svp) : 0;
+
+ svp = hv_fetch(action, "lorder", 6, FALSE);
+ info->db_BT_lorder = svp ? SvIV(*svp) : 0;
+
+ PrintBtree(info) ;
+
+ }
+ else if (sv_isa(sv, "DB_File::RECNOINFO"))
+ {
+ if (isHASH)
+ croak("DB_File can only tie an array to a DB_RECNO database");
+
+ RETVAL->type = DB_RECNO ;
+ openinfo = (void *)info ;
+
+ info->db_RE_flags = 0 ;
+
+ svp = hv_fetch(action, "flags", 5, FALSE);
+ info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
+
+ svp = hv_fetch(action, "reclen", 6, FALSE);
+ info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
+
+ svp = hv_fetch(action, "cachesize", 9, FALSE);
+ info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
+
+ svp = hv_fetch(action, "psize", 5, FALSE);
+ info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
+
+ svp = hv_fetch(action, "lorder", 6, FALSE);
+ info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
+
+#ifdef DB_VERSION_MAJOR
+ info->re_source = name ;
+ name = NULL ;
+#endif
+ svp = hv_fetch(action, "bfname", 6, FALSE);
+ if (svp && SvOK(*svp)) {
+ char * ptr = SvPV(*svp,n_a) ;
+#ifdef DB_VERSION_MAJOR
+ name = (char*) n_a ? ptr : NULL ;
+#else
+ info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
+#endif
+ }
+ else
+#ifdef DB_VERSION_MAJOR
+ name = NULL ;
+#else
+ info->db_RE_bfname = NULL ;
+#endif
+
+ svp = hv_fetch(action, "bval", 4, FALSE);
+#ifdef DB_VERSION_MAJOR
+ if (svp && SvOK(*svp))
+ {
+ int value ;
+ if (SvPOK(*svp))
+ value = (int)*SvPV(*svp, n_a) ;
+ else
+ value = SvIV(*svp) ;
+
+ if (info->flags & DB_FIXEDLEN) {
+ info->re_pad = value ;
+ info->flags |= DB_PAD ;
+ }
+ else {
+ info->re_delim = value ;
+ info->flags |= DB_DELIMITER ;
+ }
+
+ }
+#else
+ if (svp && SvOK(*svp))
+ {
+ if (SvPOK(*svp))
+ info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
+ else
+ info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
+ DB_flags(info->flags, DB_DELIMITER) ;
+
+ }
+ else
+ {
+ if (info->db_RE_flags & R_FIXEDLEN)
+ info->db_RE_bval = (u_char) ' ' ;
+ else
+ info->db_RE_bval = (u_char) '\n' ;
+ DB_flags(info->flags, DB_DELIMITER) ;
+ }
+#endif
+
+#ifdef DB_RENUMBER
+ info->flags |= DB_RENUMBER ;
+#endif
+
+ PrintRecno(info) ;
+ }
+ else
+ croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
+ }
+
+
+ /* OS2 Specific Code */
+#ifdef OS2
+#ifdef __EMX__
+ flags |= O_BINARY;
+#endif /* __EMX__ */
+#endif /* OS2 */
+
+#ifdef DB_VERSION_MAJOR
+
+ {
+ int Flags = 0 ;
+ int status ;
+
+ /* Map 1.x flags to 2.x flags */
+ if ((flags & O_CREAT) == O_CREAT)
+ Flags |= DB_CREATE ;
+
+#if O_RDONLY == 0
+ if (flags == O_RDONLY)
+#else
+ if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
+#endif
+ Flags |= DB_RDONLY ;
+
+#ifdef O_TRUNC
+ if ((flags & O_TRUNC) == O_TRUNC)
+ Flags |= DB_TRUNCATE ;
+#endif
+
+ status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
+ if (status == 0)
+#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+ status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
+#else
+ status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
+ 0) ;
+#endif
+
+ if (status)
+ RETVAL->dbp = NULL ;
+
+ }
+#else
+
+#if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
+ RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
+#else
+ RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
+#endif /* DB_LIBRARY_COMPATIBILITY_API */
+
+#endif
+
+ return (RETVAL) ;
+
+#else /* Berkeley DB Version > 2 */
+
+ SV ** svp;
+ HV * action ;
+ DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
+ DB * dbp ;
+ STRLEN n_a;
+ int status ;
+ dMY_CXT;
+
+/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
+ Zero(RETVAL, 1, DB_File_type) ;
+
+ /* Default to HASH */
+ RETVAL->filtering = 0 ;
+ RETVAL->filter_fetch_key = RETVAL->filter_store_key =
+ RETVAL->filter_fetch_value = RETVAL->filter_store_value =
+ RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
+ RETVAL->type = DB_HASH ;
+
+ /* DGH - Next line added to avoid SEGV on existing hash DB */
+ CurrentDB = RETVAL;
+
+ /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
+ RETVAL->in_memory = (name == NULL) ;
+
+ status = db_create(&RETVAL->dbp, NULL,0) ;
+ /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
+ if (status) {
+ RETVAL->dbp = NULL ;
+ return (RETVAL) ;
+ }
+ dbp = RETVAL->dbp ;
+
+ if (sv)
+ {
+ if (! SvROK(sv) )
+ croak ("type parameter is not a reference") ;
+
+ svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
+ if (svp && SvOK(*svp))
+ action = (HV*) SvRV(*svp) ;
+ else
+ croak("internal error") ;
+
+ if (sv_isa(sv, "DB_File::HASHINFO"))
+ {
+
+ if (!isHASH)
+ croak("DB_File can only tie an associative array to a DB_HASH database") ;
+
+ RETVAL->type = DB_HASH ;
+
+ svp = hv_fetch(action, "hash", 4, FALSE);
+
+ if (svp && SvOK(*svp))
+ {
+ (void)dbp->set_h_hash(dbp, hash_cb) ;
+ RETVAL->hash = newSVsv(*svp) ;
+ }
+
+ svp = hv_fetch(action, "ffactor", 7, FALSE);
+ if (svp)
+ (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
+
+ svp = hv_fetch(action, "nelem", 5, FALSE);
+ if (svp)
+ (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
+
+ svp = hv_fetch(action, "bsize", 5, FALSE);
+ if (svp)
+ (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
+
+ svp = hv_fetch(action, "cachesize", 9, FALSE);
+ if (svp)
+ (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
+
+ svp = hv_fetch(action, "lorder", 6, FALSE);
+ if (svp)
+ (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
+
+ PrintHash(info) ;
+ }
+ else if (sv_isa(sv, "DB_File::BTREEINFO"))
+ {
+ if (!isHASH)
+ croak("DB_File can only tie an associative array to a DB_BTREE database");
+
+ RETVAL->type = DB_BTREE ;
+
+ svp = hv_fetch(action, "compare", 7, FALSE);
+ if (svp && SvOK(*svp))
+ {
+ (void)dbp->set_bt_compare(dbp, btree_compare) ;
+ RETVAL->compare = newSVsv(*svp) ;
+ }
+
+ svp = hv_fetch(action, "prefix", 6, FALSE);
+ if (svp && SvOK(*svp))
+ {
+ (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
+ RETVAL->prefix = newSVsv(*svp) ;
+ }
+
+ svp = hv_fetch(action, "flags", 5, FALSE);
+ if (svp)
+ (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
+
+ svp = hv_fetch(action, "cachesize", 9, FALSE);
+ if (svp)
+ (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
+
+ svp = hv_fetch(action, "psize", 5, FALSE);
+ if (svp)
+ (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
+
+ svp = hv_fetch(action, "lorder", 6, FALSE);
+ if (svp)
+ (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
+
+ PrintBtree(info) ;
+
+ }
+ else if (sv_isa(sv, "DB_File::RECNOINFO"))
+ {
+ int fixed = FALSE ;
+
+ if (isHASH)
+ croak("DB_File can only tie an array to a DB_RECNO database");
+
+ RETVAL->type = DB_RECNO ;
+
+ svp = hv_fetch(action, "flags", 5, FALSE);
+ if (svp) {
+ int flags = SvIV(*svp) ;
+ /* remove FIXDLEN, if present */
+ if (flags & DB_FIXEDLEN) {
+ fixed = TRUE ;
+ flags &= ~DB_FIXEDLEN ;
+ }
+ }
+
+ svp = hv_fetch(action, "cachesize", 9, FALSE);
+ if (svp) {
+ status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
+ }
+
+ svp = hv_fetch(action, "psize", 5, FALSE);
+ if (svp) {
+ status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
+ }
+
+ svp = hv_fetch(action, "lorder", 6, FALSE);
+ if (svp) {
+ status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
+ }
+
+ svp = hv_fetch(action, "bval", 4, FALSE);
+ if (svp && SvOK(*svp))
+ {
+ int value ;
+ if (SvPOK(*svp))
+ value = (int)*SvPV(*svp, n_a) ;
+ else
+ value = (int)SvIV(*svp) ;
+
+ if (fixed) {
+ status = dbp->set_re_pad(dbp, value) ;
+ }
+ else {
+ status = dbp->set_re_delim(dbp, value) ;
+ }
+
+ }
+
+ if (fixed) {
+ svp = hv_fetch(action, "reclen", 6, FALSE);
+ if (svp) {
+ u_int32_t len = my_SvUV32(*svp) ;
+ status = dbp->set_re_len(dbp, len) ;
+ }
+ }
+
+ if (name != NULL) {
+ status = dbp->set_re_source(dbp, name) ;
+ name = NULL ;
+ }
+
+ svp = hv_fetch(action, "bfname", 6, FALSE);
+ if (svp && SvOK(*svp)) {
+ char * ptr = SvPV(*svp,n_a) ;
+ name = (char*) n_a ? ptr : NULL ;
+ }
+ else
+ name = NULL ;
+
+
+ status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
+
+ if (flags){
+ (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
+ }
+ PrintRecno(info) ;
+ }
+ else
+ croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
+ }
+
+ {
+ u_int32_t Flags = 0 ;
+ int status ;
+
+ /* Map 1.x flags to 3.x flags */
+ if ((flags & O_CREAT) == O_CREAT)
+ Flags |= DB_CREATE ;
+
+#if O_RDONLY == 0
+ if (flags == O_RDONLY)
+#else
+ if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
+#endif
+ Flags |= DB_RDONLY ;
+
+#ifdef O_TRUNC
+ if ((flags & O_TRUNC) == O_TRUNC)
+ Flags |= DB_TRUNCATE ;
+#endif
+
+#ifdef AT_LEAST_DB_4_1
+ status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
+ Flags, mode) ;
+#else
+ status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
+ Flags, mode) ;
+#endif
+ /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
+
+ if (status == 0) {
+ RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;
+
+ status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
+ 0) ;
+ /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
+ }
+
+ if (status)
+ RETVAL->dbp = NULL ;
+
+ }
+
+ return (RETVAL) ;
+
+#endif /* Berkeley DB Version > 2 */
+
+} /* ParseOpenInfo */
+
+
+#include "constants.h"
+
+MODULE = DB_File PACKAGE = DB_File PREFIX = db_
+
+INCLUDE: constants.xs
+
+BOOT:
+ {
+ SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;
+ MY_CXT_INIT;
+ __getBerkeleyDBInfo() ;
+
+ DBT_clear(empty) ;
+ empty.data = &zero ;
+ empty.size = sizeof(recno_t) ;
+ }
+
+
+
+DB_File
+db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
+ int isHASH
+ char * dbtype
+ int flags
+ int mode
+ CODE:
+ {
+ char * name = (char *) NULL ;
+ SV * sv = (SV *) NULL ;
+ STRLEN n_a;
+
+ if (items >= 3 && SvOK(ST(2)))
+ name = (char*) SvPV(ST(2), n_a) ;
+
+ if (items == 6)
+ sv = ST(5) ;
+
+ RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
+ if (RETVAL->dbp == NULL)
+ RETVAL = NULL ;
+ }
+ OUTPUT:
+ RETVAL
+
+int
+db_DESTROY(db)
+ DB_File db
+ PREINIT:
+ dMY_CXT;
+ INIT:
+ CurrentDB = db ;
+ Trace(("DESTROY %p\n", db));
+ CLEANUP:
+ Trace(("DESTROY %p done\n", db));
+ if (db->hash)
+ SvREFCNT_dec(db->hash) ;
+ if (db->compare)
+ SvREFCNT_dec(db->compare) ;
+ if (db->prefix)
+ SvREFCNT_dec(db->prefix) ;
+ if (db->filter_fetch_key)
+ SvREFCNT_dec(db->filter_fetch_key) ;
+ if (db->filter_store_key)
+ SvREFCNT_dec(db->filter_store_key) ;
+ if (db->filter_fetch_value)
+ SvREFCNT_dec(db->filter_fetch_value) ;
+ if (db->filter_store_value)
+ SvREFCNT_dec(db->filter_store_value) ;
+ safefree(db) ;
+#ifdef DB_VERSION_MAJOR
+ if (RETVAL > 0)
+ RETVAL = -1 ;
+#endif
+
+
+int
+db_DELETE(db, key, flags=0)
+ DB_File db
+ DBTKEY key
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ INIT:
+ CurrentDB = db ;
+
+
+int
+db_EXISTS(db, key)
+ DB_File db
+ DBTKEY key
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ {
+ DBT value ;
+
+ DBT_clear(value) ;
+ CurrentDB = db ;
+ RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+db_FETCH(db, key, flags=0)
+ DB_File db
+ DBTKEY key
+ u_int flags
+ PREINIT:
+ dMY_CXT ;
+ int RETVAL ;
+ CODE:
+ {
+ DBT value ;
+
+ DBT_clear(value) ;
+ CurrentDB = db ;
+ RETVAL = db_get(db, key, value, flags) ;
+ ST(0) = sv_newmortal();
+ OutputValue(ST(0), value)
+ }
+
+int
+db_STORE(db, key, value, flags=0)
+ DB_File db
+ DBTKEY key
+ DBT value
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ INIT:
+ CurrentDB = db ;
+
+
+void
+db_FIRSTKEY(db)
+ DB_File db
+ PREINIT:
+ dMY_CXT ;
+ int RETVAL ;
+ CODE:
+ {
+ DBTKEY key ;
+ DBT value ;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ CurrentDB = db ;
+ RETVAL = do_SEQ(db, key, value, R_FIRST) ;
+ ST(0) = sv_newmortal();
+ OutputKey(ST(0), key) ;
+ }
+
+void
+db_NEXTKEY(db, key)
+ DB_File db
+ DBTKEY key = NO_INIT
+ PREINIT:
+ dMY_CXT ;
+ int RETVAL ;
+ CODE:
+ {
+ DBT value ;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ CurrentDB = db ;
+ RETVAL = do_SEQ(db, key, value, R_NEXT) ;
+ ST(0) = sv_newmortal();
+ OutputKey(ST(0), key) ;
+ }
+
+#
+# These would be nice for RECNO
+#
+
+int
+unshift(db, ...)
+ DB_File db
+ ALIAS: UNSHIFT = 1
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ {
+ DBTKEY key ;
+ DBT value ;
+ int i ;
+ int One ;
+ STRLEN n_a;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ CurrentDB = db ;
+#ifdef DB_VERSION_MAJOR
+ /* get the first value */
+ RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
+ RETVAL = 0 ;
+#else
+ RETVAL = -1 ;
+#endif
+ for (i = items-1 ; i > 0 ; --i)
+ {
+ value.data = SvPV(ST(i), n_a) ;
+ value.size = n_a ;
+ One = 1 ;
+ key.data = &One ;
+ key.size = sizeof(int) ;
+#ifdef DB_VERSION_MAJOR
+ RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
+#else
+ RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
+#endif
+ if (RETVAL != 0)
+ break;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+void
+pop(db)
+ DB_File db
+ PREINIT:
+ dMY_CXT;
+ ALIAS: POP = 1
+ PREINIT:
+ I32 RETVAL;
+ CODE:
+ {
+ DBTKEY key ;
+ DBT value ;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ CurrentDB = db ;
+
+ /* First get the final value */
+ RETVAL = do_SEQ(db, key, value, R_LAST) ;
+ ST(0) = sv_newmortal();
+ /* Now delete it */
+ if (RETVAL == 0)
+ {
+ /* the call to del will trash value, so take a copy now */
+ OutputValue(ST(0), value) ;
+ RETVAL = db_del(db, key, R_CURSOR) ;
+ if (RETVAL != 0)
+ sv_setsv(ST(0), &PL_sv_undef);
+ }
+ }
+
+void
+shift(db)
+ DB_File db
+ PREINIT:
+ dMY_CXT;
+ ALIAS: SHIFT = 1
+ PREINIT:
+ I32 RETVAL;
+ CODE:
+ {
+ DBT value ;
+ DBTKEY key ;
+
+ DBT_clear(key) ;
+ DBT_clear(value) ;
+ CurrentDB = db ;
+ /* get the first value */
+ RETVAL = do_SEQ(db, key, value, R_FIRST) ;
+ ST(0) = sv_newmortal();
+ /* Now delete it */
+ if (RETVAL == 0)
+ {
+ /* the call to del will trash value, so take a copy now */
+ OutputValue(ST(0), value) ;
+ RETVAL = db_del(db, key, R_CURSOR) ;
+ if (RETVAL != 0)
+ sv_setsv (ST(0), &PL_sv_undef) ;
+ }
+ }
+
+
+I32
+push(db, ...)
+ DB_File db
+ PREINIT:
+ dMY_CXT;
+ ALIAS: PUSH = 1
+ CODE:
+ {
+ DBTKEY key ;
+ DBT value ;
+ DB * Db = db->dbp ;
+ int i ;
+ STRLEN n_a;
+ int keyval ;
+
+ DBT_flags(key) ;
+ DBT_flags(value) ;
+ CurrentDB = db ;
+ /* Set the Cursor to the Last element */
+ RETVAL = do_SEQ(db, key, value, R_LAST) ;
+#ifndef DB_VERSION_MAJOR
+ if (RETVAL >= 0)
+#endif
+ {
+ if (RETVAL == 0)
+ keyval = *(int*)key.data ;
+ else
+ keyval = 0 ;
+ for (i = 1 ; i < items ; ++i)
+ {
+ value.data = SvPV(ST(i), n_a) ;
+ value.size = n_a ;
+ ++ keyval ;
+ key.data = &keyval ;
+ key.size = sizeof(int) ;
+ RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
+ if (RETVAL != 0)
+ break;
+ }
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+I32
+length(db)
+ DB_File db
+ PREINIT:
+ dMY_CXT;
+ ALIAS: FETCHSIZE = 1
+ CODE:
+ CurrentDB = db ;
+ RETVAL = GetArrayLength(aTHX_ db) ;
+ OUTPUT:
+ RETVAL
+
+
+#
+# Now provide an interface to the rest of the DB functionality
+#
+
+int
+db_del(db, key, flags=0)
+ DB_File db
+ DBTKEY key
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ CurrentDB = db ;
+ RETVAL = db_del(db, key, flags) ;
+#ifdef DB_VERSION_MAJOR
+ if (RETVAL > 0)
+ RETVAL = -1 ;
+ else if (RETVAL == DB_NOTFOUND)
+ RETVAL = 1 ;
+#endif
+ OUTPUT:
+ RETVAL
+
+
+int
+db_get(db, key, value, flags=0)
+ DB_File db
+ DBTKEY key
+ DBT value = NO_INIT
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ CurrentDB = db ;
+ DBT_clear(value) ;
+ RETVAL = db_get(db, key, value, flags) ;
+#ifdef DB_VERSION_MAJOR
+ if (RETVAL > 0)
+ RETVAL = -1 ;
+ else if (RETVAL == DB_NOTFOUND)
+ RETVAL = 1 ;
+#endif
+ OUTPUT:
+ RETVAL
+ value
+
+int
+db_put(db, key, value, flags=0)
+ DB_File db
+ DBTKEY key
+ DBT value
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ CurrentDB = db ;
+ RETVAL = db_put(db, key, value, flags) ;
+#ifdef DB_VERSION_MAJOR
+ if (RETVAL > 0)
+ RETVAL = -1 ;
+ else if (RETVAL == DB_KEYEXIST)
+ RETVAL = 1 ;
+#endif
+ OUTPUT:
+ RETVAL
+ key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
+
+int
+db_fd(db)
+ DB_File db
+ PREINIT:
+ dMY_CXT ;
+ CODE:
+ CurrentDB = db ;
+#ifdef DB_VERSION_MAJOR
+ RETVAL = -1 ;
+ {
+ int status = 0 ;
+ status = (db->in_memory
+ ? -1
+ : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
+ if (status != 0)
+ RETVAL = -1 ;
+ }
+#else
+ RETVAL = (db->in_memory
+ ? -1
+ : ((db->dbp)->fd)(db->dbp) ) ;
+#endif
+ OUTPUT:
+ RETVAL
+
+int
+db_sync(db, flags=0)
+ DB_File db
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ CurrentDB = db ;
+ RETVAL = db_sync(db, flags) ;
+#ifdef DB_VERSION_MAJOR
+ if (RETVAL > 0)
+ RETVAL = -1 ;
+#endif
+ OUTPUT:
+ RETVAL
+
+
+int
+db_seq(db, key, value, flags)
+ DB_File db
+ DBTKEY key
+ DBT value = NO_INIT
+ u_int flags
+ PREINIT:
+ dMY_CXT;
+ CODE:
+ CurrentDB = db ;
+ DBT_clear(value) ;
+ RETVAL = db_seq(db, key, value, flags);
+#ifdef DB_VERSION_MAJOR
+ if (RETVAL > 0)
+ RETVAL = -1 ;
+ else if (RETVAL == DB_NOTFOUND)
+ RETVAL = 1 ;
+#endif
+ OUTPUT:
+ RETVAL
+ key
+ value
+
+SV *
+filter_fetch_key(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_fetch_key, code) ;
+
+SV *
+filter_store_key(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_store_key, code) ;
+
+SV *
+filter_fetch_value(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_fetch_value, code) ;
+
+SV *
+filter_store_value(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ DBM_setFilter(db->filter_store_value, code) ;
+
diff --git a/bdb/perl.DB_File/DB_File_BS b/bdb/perl/DB_File/DB_File_BS
index 9282c498811..9282c498811 100644
--- a/bdb/perl.DB_File/DB_File_BS
+++ b/bdb/perl/DB_File/DB_File_BS
diff --git a/bdb/perl/DB_File/MANIFEST b/bdb/perl/DB_File/MANIFEST
new file mode 100644
index 00000000000..b3e1a7bd85b
--- /dev/null
+++ b/bdb/perl/DB_File/MANIFEST
@@ -0,0 +1,30 @@
+Changes
+DB_File.pm
+DB_File.xs
+DB_File_BS
+MANIFEST
+Makefile.PL
+README
+config.in
+dbinfo
+fallback.h
+fallback.xs
+hints/dynixptx.pl
+hints/sco.pl
+patches/5.004
+patches/5.004_01
+patches/5.004_02
+patches/5.004_03
+patches/5.004_04
+patches/5.004_05
+patches/5.005
+patches/5.005_01
+patches/5.005_02
+patches/5.005_03
+patches/5.6.0
+ppport.h
+t/db-btree.t
+t/db-hash.t
+t/db-recno.t
+typemap
+version.c
diff --git a/bdb/perl/DB_File/Makefile.PL b/bdb/perl/DB_File/Makefile.PL
new file mode 100644
index 00000000000..4c1565d8d01
--- /dev/null
+++ b/bdb/perl/DB_File/Makefile.PL
@@ -0,0 +1,330 @@
+#! perl -w
+
+use strict ;
+use ExtUtils::MakeMaker 5.16 ;
+use Config ;
+
+die "DB_File needs Perl 5.004_05 or better. This is $]\n"
+ if $] <= 5.00404;
+
+my $VER_INFO ;
+my $LIB_DIR ;
+my $INC_DIR ;
+my $DB_NAME ;
+my $LIBS ;
+my $COMPAT185 = "" ;
+
+ParseCONFIG() ;
+
+my @files = ('DB_File.pm', glob "t/*.t") ;
+UpDowngrade(@files);
+
+if (defined $DB_NAME)
+ { $LIBS = $DB_NAME }
+else {
+ if ($^O eq 'MSWin32')
+ { $LIBS = '-llibdb' }
+ else
+ { $LIBS = '-ldb' }
+}
+
+# Solaris is special.
+#$LIBS .= " -lthread" if $^O eq 'solaris' ;
+
+# AIX is special.
+$LIBS .= " -lpthread" if $^O eq 'aix' ;
+
+# OS2 is a special case, so check for it now.
+my $OS2 = "" ;
+$OS2 = "-DOS2" if $Config{'osname'} eq 'os2' ;
+
+WriteMakefile(
+ NAME => 'DB_File',
+ LIBS => ["-L${LIB_DIR} $LIBS"],
+ #MAN3PODS => {}, # Pods will be built by installman.
+ INC => "-I$INC_DIR",
+ VERSION_FROM => 'DB_File.pm',
+ XSPROTOARG => '-noprototypes',
+ DEFINE => "-D_NOT_CORE $OS2 $VER_INFO $COMPAT185",
+ OBJECT => 'version$(OBJ_EXT) DB_File$(OBJ_EXT)',
+ #OPTIMIZE => '-g',
+ 'depend' => { 'Makefile' => 'config.in',
+ 'version$(OBJ_EXT)' => 'version.c'},
+ 'clean' => { FILES => 'constants.h constants.xs' },
+ 'macro' => { INSTALLDIRS => 'perl', my_files => "@files" },
+ 'dist' => { COMPRESS => 'gzip', SUFFIX => 'gz',
+ DIST_DEFAULT => 'MyDoubleCheck tardist'},
+ );
+
+
+my @names = qw(
+ BTREEMAGIC
+ BTREEVERSION
+ DB_LOCK
+ DB_SHMEM
+ DB_TXN
+ HASHMAGIC
+ HASHVERSION
+ MAX_PAGE_NUMBER
+ MAX_PAGE_OFFSET
+ MAX_REC_NUMBER
+ RET_ERROR
+ RET_SPECIAL
+ RET_SUCCESS
+ R_CURSOR
+ R_DUP
+ R_FIRST
+ R_FIXEDLEN
+ R_IAFTER
+ R_IBEFORE
+ R_LAST
+ R_NEXT
+ R_NOKEY
+ R_NOOVERWRITE
+ R_PREV
+ R_RECNOSYNC
+ R_SETCURSOR
+ R_SNAPSHOT
+ __R_UNUSED
+ );
+
+if (eval {require ExtUtils::Constant; 1}) {
+ # Check the constants above all appear in @EXPORT in DB_File.pm
+ my %names = map { $_, 1} @names;
+ open F, "<DB_File.pm" or die "Cannot open DB_File.pm: $!\n";
+ while (<F>)
+ {
+ last if /^\s*\@EXPORT\s+=\s+qw\(/ ;
+ }
+
+ while (<F>)
+ {
+ last if /^\s*\)/ ;
+ /(\S+)/ ;
+ delete $names{$1} if defined $1 ;
+ }
+ close F ;
+
+ if ( keys %names )
+ {
+ my $missing = join ("\n\t", sort keys %names) ;
+ die "The following names are missing from \@EXPORT in DB_File.pm\n" .
+ "\t$missing\n" ;
+ }
+
+
+ ExtUtils::Constant::WriteConstants(
+ NAME => 'DB_File',
+ NAMES => \@names,
+ C_FILE => 'constants.h',
+ XS_FILE => 'constants.xs',
+
+ );
+}
+else {
+ use File::Copy;
+ copy ('fallback.h', 'constants.h')
+ or die "Can't copy fallback.h to constants.h: $!";
+ copy ('fallback.xs', 'constants.xs')
+ or die "Can't copy fallback.xs to constants.xs: $!";
+}
+
+exit;
+
+
+sub MY::postamble { <<'EOM' } ;
+
+MyDoubleCheck:
+ @echo Checking config.in is setup for a release
+ @(grep "^LIB.*/usr/local/BerkeleyDB" config.in && \
+ grep "^INCLUDE.*/usr/local/BerkeleyDB" config.in && \
+ grep "^#DBNAME.*" config.in) >/dev/null || \
+ (echo config.in needs fixing ; exit 1)
+ @echo config.in is ok
+ @echo
+ @echo Checking DB_File.xs is ok for a release.
+ @(perl -ne ' exit 1 if /^\s*#\s*define\s+TRACE/ ; ' DB_File.xs || \
+ (echo DB_File.xs needs fixing ; exit 1))
+ @echo DB_File.xs is ok
+ @echo
+ @echo Checking for $$^W in files: $(my_files)
+ @perl -ne ' \
+ exit 1 if /^\s*local\s*\(\s*\$$\^W\s*\)/;' $(my_files) || \
+ (echo found unexpected $$^W ; exit 1)
+ @echo No $$^W found.
+ @echo
+ @echo Checking for 'use vars' in files: $(my_files)
+ @perl -ne ' \
+ exit 0 if /^__(DATA|END)__/; \
+ exit 1 if /^\s*use\s+vars/;' $(my_files) || \
+ (echo found unexpected "use vars"; exit 1)
+ @echo No 'use vars' found.
+ @echo
+ @echo All files are OK for a release.
+ @echo
+
+EOM
+
+
+
+sub ParseCONFIG
+{
+ my ($k, $v) ;
+ my @badkey = () ;
+ my %Info = () ;
+ my @Options = qw( INCLUDE LIB PREFIX HASH DBNAME COMPAT185 ) ;
+ my %ValidOption = map {$_, 1} @Options ;
+ my %Parsed = %ValidOption ;
+ my $CONFIG = 'config.in' ;
+
+ print "Parsing $CONFIG...\n" ;
+
+ # DBNAME & COMPAT185 are optional, so pretend they have
+ # been parsed.
+ delete $Parsed{'DBNAME'} ;
+ delete $Parsed{'COMPAT185'} ;
+ $Info{COMPAT185} = "No" ;
+
+
+ open(F, "$CONFIG") or die "Cannot open file $CONFIG: $!\n" ;
+ while (<F>) {
+ s/^\s*|\s*$//g ;
+ next if /^\s*$/ or /^\s*#/ ;
+ s/\s*#\s*$// ;
+
+ ($k, $v) = split(/\s+=\s+/, $_, 2) ;
+ $k = uc $k ;
+ if ($ValidOption{$k}) {
+ delete $Parsed{$k} ;
+ $Info{$k} = $v ;
+ }
+ else {
+ push(@badkey, $k) ;
+ }
+ }
+ close F ;
+
+ print "Unknown keys in $CONFIG ignored [@badkey]\n"
+ if @badkey ;
+
+ # check parsed values
+ my @missing = () ;
+ die "The following keys are missing from $CONFIG file: [@missing]\n"
+ if @missing = keys %Parsed ;
+
+ $INC_DIR = $ENV{'DB_FILE_INCLUDE'} || $Info{'INCLUDE'} ;
+ $LIB_DIR = $ENV{'DB_FILE_LIB'} || $Info{'LIB'} ;
+ $DB_NAME = $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
+ $COMPAT185 = "-DCOMPAT185 -DDB_LIBRARY_COMPATIBILITY_API"
+ if (defined $ENV{'DB_FILE_COMPAT185'} &&
+ $ENV{'DB_FILE_COMPAT185'} =~ /^\s*(on|true|1)\s*$/i) ||
+ $Info{'COMPAT185'} =~ /^\s*(on|true|1)\s*$/i ;
+ my $PREFIX = $Info{'PREFIX'} ;
+ my $HASH = $Info{'HASH'} ;
+
+ $VER_INFO = "-DmDB_Prefix_t=${PREFIX} -DmDB_Hash_t=${HASH}" ;
+
+ print <<EOM if 0 ;
+ INCLUDE [$INC_DIR]
+ LIB [$LIB_DIR]
+ HASH [$HASH]
+ PREFIX [$PREFIX]
+ DBNAME [$DB_NAME]
+
+EOM
+
+ print "Looks Good.\n" ;
+
+}
+
+sub UpDowngrade
+{
+ my @files = @_ ;
+
+ # our is stable from 5.6.0 onward
+ # warnings is stable from 5.6.1 onward
+
+ # Note: this code assumes that each statement it modifies is not
+ # split across multiple lines.
+
+
+ my $warn_sub ;
+ my $our_sub ;
+
+ if ($] < 5.006001) {
+ # From: use|no warnings "blah"
+ # To: local ($^W) = 1; # use|no warnings "blah"
+ #
+ # and
+ #
+ # From: warnings::warnif(x,y);
+ # To: $^W && carp(y); # warnif -- x
+ $warn_sub = sub {
+ s/^(\s*)(no\s+warnings)/${1}local (\$^W) = 0; #$2/ ;
+ s/^(\s*)(use\s+warnings)/${1}local (\$^W) = 1; #$2/ ;
+
+ s/^(\s*)warnings::warnif\s*\((.*?)\s*,\s*(.*?)\)\s*;/${1}\$^W && carp($3); # warnif - $2/ ;
+ };
+ }
+ else {
+ # From: local ($^W) = 1; # use|no warnings "blah"
+ # To: use|no warnings "blah"
+ #
+ # and
+ #
+ # From: $^W && carp(y); # warnif -- x
+ # To: warnings::warnif(x,y);
+ $warn_sub = sub {
+ s/^(\s*)local\s*\(\$\^W\)\s*=\s*\d+\s*;\s*#\s*((no|use)\s+warnings.*)/$1$2/ ;
+ s/^(\s*)\$\^W\s+\&\&\s*carp\s*\((.*?)\)\s*;\s*#\s*warnif\s*-\s*(.*)/${1}warnings::warnif($3, $2);/ ;
+ };
+ }
+
+ if ($] < 5.006000) {
+ $our_sub = sub {
+ if ( /^(\s*)our\s+\(\s*([^)]+\s*)\)/ ) {
+ my $indent = $1;
+ my $vars = join ' ', split /\s*,\s*/, $2;
+ $_ = "${indent}use vars qw($vars);\n";
+ }
+ };
+ }
+ else {
+ $our_sub = sub {
+ if ( /^(\s*)use\s+vars\s+qw\((.*?)\)/ ) {
+ my $indent = $1;
+ my $vars = join ', ', split ' ', $2;
+ $_ = "${indent}our ($vars);\n";
+ }
+ };
+ }
+
+ foreach (@files)
+ { doUpDown($our_sub, $warn_sub, $_) }
+}
+
+
+sub doUpDown
+{
+ my $our_sub = shift;
+ my $warn_sub = shift;
+
+ local ($^I) = ".bak" ;
+ local (@ARGV) = shift;
+
+ while (<>)
+ {
+ print, last if /^__(END|DATA)__/ ;
+
+ &{ $our_sub }();
+ &{ $warn_sub }();
+ print ;
+ }
+
+ return if eof ;
+
+ while (<>)
+ { print }
+}
+
+# end of file Makefile.PL
diff --git a/bdb/perl/DB_File/README b/bdb/perl/DB_File/README
new file mode 100644
index 00000000000..b09aa9d8aee
--- /dev/null
+++ b/bdb/perl/DB_File/README
@@ -0,0 +1,458 @@
+ DB_File
+
+ Version 1.805
+
+ 1st Sep 2002
+
+ Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This
+ program is free software; you can redistribute it and/or modify
+ it under the same terms as Perl itself.
+
+
+IMPORTANT NOTICE
+================
+
+If are using the locking technique described in older versions of
+DB_File, please read the section called "Locking: The Trouble with fd"
+in DB_File.pm immediately. The locking method has been found to be
+unsafe. You risk corrupting your data if you continue to use it.
+
+DESCRIPTION
+-----------
+
+DB_File is a module which allows Perl programs to make use of the
+facilities provided by Berkeley DB version 1. (DB_File can be built
+version 2, 3 or 4 of Berkeley DB, but it will only support the 1.x
+features),
+
+If you want to make use of the new features available in Berkeley DB
+2.x, 3.x or 4.x, use the Perl module BerkeleyDB instead.
+
+Berkeley DB is a C library which provides a consistent interface to a
+number of database formats. DB_File provides an interface to all three
+of the database types (hash, btree and recno) currently supported by
+Berkeley DB.
+
+For further details see the documentation included at the end of the
+file DB_File.pm.
+
+PREREQUISITES
+-------------
+
+Before you can build DB_File you must have the following installed on
+your system:
+
+ * Perl 5.004_05 or greater.
+
+ * Berkeley DB.
+
+ The official web site for Berkeley DB is http://www.sleepycat.com.
+ The latest version of Berkeley DB is always available there. It
+ is recommended that you use the most recent version available at
+ the Sleepycat site.
+
+ The one exception to this advice is where you want to use DB_File
+ to access database files created by a third-party application, like
+ Sendmail or Netscape. In these cases you must build DB_File with a
+ compatible version of Berkeley DB.
+
+ If you want to use Berkeley DB 2.x, you must have version 2.3.4
+ or greater. If you want to use Berkeley DB 3.x or 4.x, any version
+ will do. For Berkeley DB 1.x, use either version 1.85 or 1.86.
+
+
+BUILDING THE MODULE
+-------------------
+
+Assuming you have met all the prerequisites, building the module should
+be relatively straightforward.
+
+Step 1 : If you are running either Solaris 2.5 or HP-UX 10 and want
+ to use Berkeley DB version 2, 3 or 4, read either the Solaris Notes
+ or HP-UX Notes sections below. If you are running Linux please
+ read the Linux Notes section before proceeding.
+
+Step 2 : Edit the file config.in to suit you local installation.
+ Instructions are given in the file.
+
+Step 3 : Build and test the module using this sequence of commands:
+
+ perl Makefile.PL
+ make
+ make test
+
+
+ NOTE:
+ If you have a very old version of Berkeley DB (i.e. pre 1.85),
+ three of the tests in the recno test harness may fail (tests 51,
+ 53 and 55). You can safely ignore the errors if you're never
+ going to use the broken functionality (recno databases with a
+ modified bval). Otherwise you'll have to upgrade your DB
+ library.
+
+
+INSTALLATION
+------------
+
+ make install
+
+
+TROUBLESHOOTING
+===============
+
+Here are some of the common problems people encounter when building
+DB_File.
+
+Missing db.h or libdb.a
+-----------------------
+
+If you get an error like this:
+
+ cc -c -I/usr/local/include -Dbool=char -DHAS_BOOL
+ -O2 -DVERSION=\"1.64\" -DXS_VERSION=\"1.64\" -fpic
+ -I/usr/local/lib/perl5/i586-linux/5.00404/CORE -DmDB_Prefix_t=size_t
+ -DmDB_Hash_t=u_int32_t DB_File.c
+ DB_File.xs:101: db.h: No such file or directory
+
+or this:
+
+ LD_RUN_PATH="/lib" cc -o blib/arch/auto/DB_File/DB_File.so -shared
+ -L/usr/local/lib DB_File.o -L/usr/local/lib -ldb
+ ld: cannot open -ldb: No such file or directory
+
+This symptom can imply:
+
+ 1. You don't have Berkeley DB installed on your system at all.
+ Solution: get & install Berkeley DB.
+
+ 2. You do have Berkeley DB installed, but it isn't in a standard place.
+ Solution: Edit config.in and set the LIB and INCLUDE variables to point
+ to the directories where libdb.a and db.h are installed.
+
+
+Undefined symbol db_version
+---------------------------
+
+DB_File seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ $ make test
+ PERL_DL_NONLAZY=1 /usr/bin/perl5.00404 -I./blib/arch -I./blib/lib
+ -I/usr/local/lib/perl5/i586-linux/5.00404 -I/usr/local/lib/perl5 -e 'use
+ Test::Harness qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
+ t/db-btree..........Can't load './blib/arch/auto/DB_File/DB_File.so' for
+ module DB_File: ./blib/arch/auto/DB_File/DB_File.so: undefined symbol:
+ db_version at /usr/local/lib/perl5/i586-linux/5.00404/DynaLoader.pm
+ line 166.
+
+ at t/db-btree.t line 21
+ BEGIN failed--compilation aborted at t/db-btree.t line 21.
+ dubious Test returned status 2 (wstat 512, 0x200)
+
+This error usually happens when you have both version 1 and version
+2 of Berkeley DB installed on your system and DB_File attempts to
+build using the db.h for Berkeley DB version 2 and the version 1
+library. Unfortunately the two versions aren't compatible with each
+other. The undefined symbol error is actually caused because Berkeley
+DB version 1 doesn't have the symbol db_version.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want DB_File to use.
+
+
+Undefined symbol dbopen
+-----------------------
+
+DB_File seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ ...
+ t/db-btree..........Can't load 'blib/arch/auto/DB_File/DB_File.so' for
+ module DB_File: blib/arch/auto/DB_File/DB_File.so: undefined symbol:
+ dbopen at /usr/local/lib/perl5/5.6.1/i586-linux/DynaLoader.pm line 206.
+ at t/db-btree.t line 23
+ Compilation failed in require at t/db-btree.t line 23.
+ ...
+
+This error usually happens when you have both version 1 and a more recent
+version of Berkeley DB installed on your system and DB_File attempts
+to build using the db.h for Berkeley DB version 1 and the newer version
+library. Unfortunately the two versions aren't compatible with each
+other. The undefined symbol error is actually caused because versions
+of Berkeley DB newer than version 1 doesn't have the symbol dbopen.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want DB_File to use.
+
+
+Incompatible versions of db.h and libdb
+---------------------------------------
+
+BerkeleyDB seems to have built correctly, but you get an error like this
+when you run the test harness:
+
+ $ make test
+ PERL_DL_NONLAZY=1 /home/paul/perl/install/bin/perl5.00560 -Iblib/arch
+ -Iblib/lib -I/home/paul/perl/install/5.005_60/lib/5.00560/i586-linux
+ -I/home/paul/perl/install/5.005_60/lib/5.00560 -e 'use Test::Harness
+ qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
+ t/db-btree..........
+ DB_File needs compatible versions of libdb & db.h
+ you have db.h version 2.3.7 and libdb version 2.7.5
+ BEGIN failed--compilation aborted at t/db-btree.t line 21.
+ ...
+
+Another variation on the theme of having two versions of Berkeley DB on
+your system.
+
+Solution: Setting the LIB & INCLUDE variables in config.in to point to the
+ correct directories can sometimes be enough to fix this
+ problem. If that doesn't work the easiest way to fix the
+ problem is to either delete or temporarily rename the copies
+ of db.h and libdb.a that you don't want BerkeleyDB to use.
+ If you are running Linux, please read the Linux Notes section
+ below.
+
+
+Linux Notes
+-----------
+
+Newer versions of Linux (e.g. RedHat 6, SuSe 6) ship with a C library
+that has version 2.x of Berkeley DB linked into it. This makes it
+difficult to build this module with anything other than the version of
+Berkeley DB that shipped with your Linux release. If you do try to use
+a different version of Berkeley DB you will most likely get the error
+described in the "Incompatible versions of db.h and libdb" section of
+this file.
+
+To make matters worse, prior to Perl 5.6.1, the perl binary itself
+*always* included the Berkeley DB library.
+
+If you want to use a newer version of Berkeley DB with this module, the
+easiest solution is to use Perl 5.6.1 (or better) and Berkeley DB 3.x
+(or better).
+
+There are two approaches you can use to get older versions of Perl to
+work with specific versions of Berkeley DB. Both have their advantages
+and disadvantages.
+
+The first approach will only work when you want to build a version of
+Perl older than 5.6.1 along with Berkeley DB 3.x. If you want to use
+Berkeley DB 2.x, you must use the next approach. This approach involves
+rebuilding your existing version of Perl after applying an unofficial
+patch. The "patches" directory in the this module's source distribution
+contains a number of patch files. There is one patch file for every
+stable version of Perl since 5.004. Apply the appropriate patch to your
+Perl source tree before re-building and installing Perl from scratch.
+For example, assuming you are in the top-level source directory for
+Perl 5.6.0, the command below will apply the necessary patch. Remember
+to replace the path shown below with one that points to this module's
+patches directory.
+
+ patch -p1 -N </path/to/DB_File/patches/5.6.0
+
+Now rebuild & install perl. You should now have a perl binary that can
+be used to build this module. Follow the instructions in "BUILDING THE
+MODULE", remembering to set the INCLUDE and LIB variables in config.in.
+
+
+The second approach will work with both Berkeley DB 2.x and 3.x.
+Start by building Berkeley DB as a shared library. This is from
+the Berkeley DB build instructions:
+
+ Building Shared Libraries for the GNU GCC compiler
+
+ If you're using gcc and there's no better shared library example for
+ your architecture, the following shared library build procedure will
+ probably work.
+
+ Add the -fpic option to the CFLAGS value in the Makefile.
+
+ Rebuild all of your .o files. This will create a Berkeley DB library
+ that contains .o files with PIC code. To build the shared library,
+ then take the following steps in the library build directory:
+
+ % mkdir tmp
+ % cd tmp
+ % ar xv ../libdb.a
+ % gcc -shared -o libdb.so *.o
+ % mv libdb.so ..
+ % cd ..
+ % rm -rf tmp
+
+ Note, you may have to change the gcc line depending on the
+ requirements of your system.
+
+ The file libdb.so is your shared library
+
+Once you have built libdb.so, you will need to store it somewhere safe.
+
+ cp libdb.so /usr/local/BerkeleyDB/lib
+
+If you now set the LD_PRELOAD environment variable to point to this
+shared library, Perl will use it instead of the version of Berkeley DB
+that shipped with your Linux distribution.
+
+ export LD_PRELOAD=/usr/local/BerkeleyDB/lib/libdb.so
+
+Finally follow the instructions in "BUILDING THE MODULE" to build,
+test and install this module. Don't forget to set the INCLUDE and LIB
+variables in config.in.
+
+Remember, you will need to have the LD_PRELOAD variable set anytime you
+want to use Perl with Berkeley DB. Also note that if you have LD_PRELOAD
+permanently set it will affect ALL commands you execute. This may be a
+problem if you run any commands that access a database created by the
+version of Berkeley DB that shipped with your Linux distribution.
+
+
+Solaris Notes
+-------------
+
+If you are running Solaris 2.5, and you get this error when you run the
+DB_File test harness:
+
+ libc internal error: _rmutex_unlock: rmutex not held.
+
+you probably need to install a Sun patch. It has been reported that
+Sun patch 103187-25 (or later revisions) fixes this problem.
+
+To find out if you have the patch installed, the command "showrev -p"
+will display the patches that are currently installed on your system.
+
+
+HP-UX 10 Notes
+--------------
+
+Some people running HP-UX 10 have reported getting an error like this
+when building DB_File with the native HP-UX compiler.
+
+ ld: (Warning) At least one PA 2.0 object file (DB_File.o) was detected.
+ The linked output may not run on a PA 1.x system.
+ ld: Invalid loader fixup for symbol "$000000A5".
+
+If this is the case for you, Berkeley DB needs to be recompiled with
+the +z or +Z option and the resulting library placed in a .sl file. The
+following steps should do the trick:
+
+ 1: Configure the Berkeley DB distribution with the +z or +Z C compiler
+ flag:
+
+ env "CFLAGS=+z" ../dist/configure ...
+
+ 2: Edit the Berkeley DB Makefile and change:
+
+ "libdb= libdb.a" to "libdb= libdb.sl".
+
+
+ 3: Build and install the Berkeley DB distribution as usual.
+
+HP-UX 11 Notes
+--------------
+
+Some people running the combination of HP-UX 11 and Berkeley DB 2.7.7 have
+reported getting this error when the run the test harness for DB_File
+
+ ...
+ lib/db-btree.........Can't call method "DELETE" on an undefined value at lib/db-btree.t line 216.
+ FAILED at test 26
+ lib/db-hash..........Can't call method "DELETE" on an undefined value at lib/db-hash.t line 183.
+ FAILED at test 22
+ ...
+
+The fix for this is to rebuild and install Berkeley DB with the bigfile
+option disabled.
+
+
+IRIX NOTES
+----------
+
+If you are running IRIX, and want to use Berkeley DB version 1, you can
+get it from http://reality.sgi.com/ariel. It has the patches necessary
+to compile properly on IRIX 5.3.
+
+
+FEEDBACK
+========
+
+How to report a problem with DB_File.
+
+When reporting any problem, I need the information requested below.
+
+ 1. The *complete* output from running this
+
+ perl -V
+
+ Do not edit the output in any way.
+ Note, I want you to run "perl -V" and NOT "perl -v".
+
+ If your perl does not understand the "-V" option it is too
+ old. DB_File needs Perl version 5.00405 or better.
+
+ 2. The version of DB_File you have.
+ If you have successfully installed DB_File, this one-liner will
+ tell you:
+
+ perl -e 'use DB_File; print qq{DB_File ver $DB_File::VERSION\n}'
+
+ If you haven't installed DB_File then search DB_File.pm for a line
+ like this:
+
+ $VERSION = "1.20" ;
+
+ 3. The version of Berkeley DB you are using.
+ If you are using a version older than 1.85, think about upgrading. One
+ point to note if you are considering upgrading Berkeley DB - the
+ file formats for 1.85, 1.86, 2.0, 3.0 & 3.1 are all different.
+
+ If you have successfully installed DB_File, this command will display
+ the version of Berkeley DB it was built with:
+
+ perl -e 'use DB_File; print qq{Berkeley DB ver $DB_File::db_ver\n}'
+
+ 4. A copy the file config.in from the DB_File main source directory.
+
+ 5. A listing of directories where Berkeley DB is installed.
+ For example, if Berkeley DB is installed in /usr/BerkeleDB/lib and
+ /usr/BerkeleyDB/include, I need the output from running this
+
+ ls -l /usr/BerkeleyDB/lib
+ ls -l /usr/BerkeleyDB/include
+
+ 6. If you are having problems building DB_File, send me a complete log
+ of what happened. Start by unpacking the DB_File module into a fresh
+ directory and keep a log of all the steps
+
+ [edit config.in, if necessary]
+ perl Makefile.PL
+ make
+ make test TEST_VERBOSE=1
+
+ 7. Now the difficult one. If you think you have found a bug in DB_File
+ and you want me to fix it, you will *greatly* enhance the chances
+ of me being able to track it down by sending me a small
+ self-contained Perl script that illustrates the problem you are
+ encountering. Include a summary of what you think the problem is
+ and a log of what happens when you run the script, in case I can't
+ reproduce your problem on my system. If possible, don't have the
+ script dependent on an existing 20Meg database. If the script you
+ send me can create the database itself then that is preferred.
+
+ I realise that in some cases this is easier said than done, so if
+ you can only reproduce the problem in your existing script, then
+ you can post me that if you want. Just don't expect me to find your
+ problem in a hurry, or at all. :-)
+
+
+CHANGES
+-------
+
+See the Changes file.
+
+Paul Marquess <Paul.Marquess@btinternet.com>
diff --git a/bdb/perl/DB_File/config.in b/bdb/perl/DB_File/config.in
new file mode 100644
index 00000000000..292b09a5fb3
--- /dev/null
+++ b/bdb/perl/DB_File/config.in
@@ -0,0 +1,97 @@
+# Filename: config.in
+#
+# written by Paul Marquess <Paul.Marquess@btinternet.com>
+# last modified 9th Sept 1997
+# version 1.55
+
+# 1. Where is the file db.h?
+#
+# Change the path below to point to the directory where db.h is
+# installed on your system.
+
+INCLUDE = /usr/local/BerkeleyDB/include
+#INCLUDE = /usr/local/include
+#INCLUDE = /usr/include
+
+# 2. Where is libdb?
+#
+# Change the path below to point to the directory where libdb is
+# installed on your system.
+
+LIB = /usr/local/BerkeleyDB/lib
+#LIB = /usr/local/lib
+#LIB = /usr/lib
+
+# 3. What version of Berkely DB have you got?
+#
+# If you have version 2.0 or greater, you can skip this question.
+#
+# If you have Berkeley DB 1.78 or greater you shouldn't have to
+# change the definitions for PREFIX and HASH below.
+#
+# For older versions of Berkeley DB change both PREFIX and HASH to int.
+# Version 1.71, 1.72 and 1.73 are known to need this change.
+#
+# If you don't know what version you have have a look in the file db.h.
+#
+# Search for the string "DB_VERSION_MAJOR". If it is present, you
+# have Berkeley DB version 2 (or greater).
+#
+# If that didn't work, find the definition of the BTREEINFO typedef.
+# Check the return type from the prefix element. It should look like
+# this in an older copy of db.h:
+#
+# int (*prefix) __P((const DBT *, const DBT *));
+#
+# and like this in a more recent copy:
+#
+# size_t (*prefix) /* prefix function */
+# __P((const DBT *, const DBT *));
+#
+# Change the definition of PREFIX, below, to reflect the return type
+# of the prefix function in your db.h.
+#
+# Now find the definition of the HASHINFO typedef. Check the return
+# type of the hash element. Older versions look like this:
+#
+# int (*hash) __P((const void *, size_t));
+#
+# newer like this:
+#
+# u_int32_t /* hash function */
+# (*hash) __P((const void *, size_t));
+#
+# Change the definition of HASH, below, to reflect the return type of
+# the hash function in your db.h.
+#
+
+PREFIX = size_t
+HASH = u_int32_t
+
+# 4. Is the library called libdb?
+#
+# If you have copies of both 1.x and 2.x Berkeley DB installed on
+# your system it can sometimes be tricky to make sure you are using
+# the correct one. Renaming one (or creating a symbolic link) to
+# include the version number of the library can help.
+#
+# For example, if you have both Berkeley DB 2.3.12 and 1.85 on your
+# system and you want to use the Berkeley DB version 2 library you
+# could rename the version 2 library from libdb.a to libdb-2.3.12.a and
+# change the DBNAME line below to look like this:
+#
+# DBNAME = -ldb-2.3.12
+#
+# That will ensure you are linking the correct version of the DB
+# library.
+#
+# Note: If you are building this module with Win32, -llibdb will be
+# used by default.
+#
+# If you have changed the name of the library, uncomment the line
+# below (by removing the leading #) and edit the line to use the name
+# you have picked.
+
+#DBNAME = -ldb-2.4.10
+
+# end of file config.in
diff --git a/bdb/perl/DB_File/dbinfo b/bdb/perl/DB_File/dbinfo
new file mode 100644
index 00000000000..af2c45facf5
--- /dev/null
+++ b/bdb/perl/DB_File/dbinfo
@@ -0,0 +1,112 @@
+#!/usr/local/bin/perl
+
+# Name: dbinfo -- identify berkeley DB version used to create
+# a database file
+#
+# Author: Paul Marquess <Paul.Marquess@btinternet.com>
+# Version: 1.03
+# Date 17th September 2000
+#
+# Copyright (c) 1998-2002 Paul Marquess. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+# Todo: Print more stats on a db file, e.g. no of records
+# add log/txn/lock files
+
+use strict ;
+
+my %Data =
+ (
+ 0x053162 => {
+ Type => "Btree",
+ Versions =>
+ {
+ 1 => "Unknown (older than 1.71)",
+ 2 => "Unknown (older than 1.71)",
+ 3 => "1.71 -> 1.85, 1.86",
+ 4 => "Unknown",
+ 5 => "2.0.0 -> 2.3.0",
+ 6 => "2.3.1 -> 2.7.7",
+ 7 => "3.0.x",
+ 8 => "3.1.x -> 4.0.x",
+ 9 => "4.1.x or greater",
+ }
+ },
+ 0x061561 => {
+ Type => "Hash",
+ Versions =>
+ {
+ 1 => "Unknown (older than 1.71)",
+ 2 => "1.71 -> 1.85",
+ 3 => "1.86",
+ 4 => "2.0.0 -> 2.1.0",
+ 5 => "2.2.6 -> 2.7.7",
+ 6 => "3.0.x",
+ 7 => "3.1.x -> 4.0.x",
+ 8 => "4.1.x or greater",
+ }
+ },
+ 0x042253 => {
+ Type => "Queue",
+ Versions =>
+ {
+ 1 => "3.0.x",
+ 2 => "3.1.x",
+ 3 => "3.2.x -> 4.0.x",
+ 4 => "4.1.x or greater",
+ }
+ },
+ ) ;
+
+die "Usage: dbinfo file\n" unless @ARGV == 1 ;
+
+print "testing file $ARGV[0]...\n\n" ;
+open (F, "<$ARGV[0]") or die "Cannot open file $ARGV[0]: $!\n" ;
+
+my $buff ;
+read F, $buff, 20 ;
+
+my (@info) = unpack("NNNNN", $buff) ;
+my (@info1) = unpack("VVVVV", $buff) ;
+my ($magic, $version, $endian) ;
+
+if ($Data{$info[0]}) # first try DB 1.x format
+{
+ $magic = $info[0] ;
+ $version = $info[1] ;
+ $endian = "Unknown" ;
+}
+elsif ($Data{$info[3]}) # next DB 2.x big endian
+{
+ $magic = $info[3] ;
+ $version = $info[4] ;
+ $endian = "Big Endian" ;
+}
+elsif ($Data{$info1[3]}) # next DB 2.x little endian
+{
+ $magic = $info1[3] ;
+ $version = $info1[4] ;
+ $endian = "Little Endian" ;
+}
+else
+ { die "not a Berkeley DB database file.\n" }
+
+my $type = $Data{$magic} ;
+$magic = sprintf "%06X", $magic ;
+
+my $ver_string = "Unknown" ;
+$ver_string = $type->{Versions}{$version}
+ if defined $type->{Versions}{$version} ;
+
+print <<EOM ;
+File Type: Berkeley DB $type->{Type} file.
+File Version ID: $version
+Built with Berkeley DB: $ver_string
+Byte Order: $endian
+Magic: $magic
+EOM
+
+close F ;
+
+exit ;
diff --git a/bdb/perl/DB_File/fallback.h b/bdb/perl/DB_File/fallback.h
new file mode 100644
index 00000000000..0213308a0ee
--- /dev/null
+++ b/bdb/perl/DB_File/fallback.h
@@ -0,0 +1,455 @@
+#define PERL_constant_NOTFOUND 1
+#define PERL_constant_NOTDEF 2
+#define PERL_constant_ISIV 3
+#define PERL_constant_ISNO 4
+#define PERL_constant_ISNV 5
+#define PERL_constant_ISPV 6
+#define PERL_constant_ISPVN 7
+#define PERL_constant_ISSV 8
+#define PERL_constant_ISUNDEF 9
+#define PERL_constant_ISUV 10
+#define PERL_constant_ISYES 11
+
+#ifndef NVTYPE
+typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it. */
+#endif
+#ifndef aTHX_
+#define aTHX_ /* 5.6 or later define this for threading support. */
+#endif
+#ifndef pTHX_
+#define pTHX_ /* 5.6 or later define this for threading support. */
+#endif
+
+static int
+constant_6 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_TXN R_LAST R_NEXT R_PREV */
+ /* Offset 2 gives the best switch position. */
+ switch (name[2]) {
+ case 'L':
+ if (memEQ(name, "R_LAST", 6)) {
+ /* ^ */
+#ifdef R_LAST
+ *iv_return = R_LAST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "R_NEXT", 6)) {
+ /* ^ */
+#ifdef R_NEXT
+ *iv_return = R_NEXT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "R_PREV", 6)) {
+ /* ^ */
+#ifdef R_PREV
+ *iv_return = R_PREV;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case '_':
+ if (memEQ(name, "DB_TXN", 6)) {
+ /* ^ */
+#ifdef DB_TXN
+ *iv_return = DB_TXN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_7 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_LOCK R_FIRST R_NOKEY */
+ /* Offset 3 gives the best switch position. */
+ switch (name[3]) {
+ case 'I':
+ if (memEQ(name, "R_FIRST", 7)) {
+ /* ^ */
+#ifdef R_FIRST
+ *iv_return = R_FIRST;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "DB_LOCK", 7)) {
+ /* ^ */
+#ifdef DB_LOCK
+ *iv_return = DB_LOCK;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "R_NOKEY", 7)) {
+ /* ^ */
+#ifdef R_NOKEY
+ *iv_return = R_NOKEY;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_8 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ DB_SHMEM R_CURSOR R_IAFTER */
+ /* Offset 5 gives the best switch position. */
+ switch (name[5]) {
+ case 'M':
+ if (memEQ(name, "DB_SHMEM", 8)) {
+ /* ^ */
+#ifdef DB_SHMEM
+ *iv_return = DB_SHMEM;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "R_CURSOR", 8)) {
+ /* ^ */
+#ifdef R_CURSOR
+ *iv_return = R_CURSOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'T':
+ if (memEQ(name, "R_IAFTER", 8)) {
+ /* ^ */
+#ifdef R_IAFTER
+ *iv_return = R_IAFTER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_9 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ HASHMAGIC RET_ERROR R_IBEFORE */
+ /* Offset 7 gives the best switch position. */
+ switch (name[7]) {
+ case 'I':
+ if (memEQ(name, "HASHMAGIC", 9)) {
+ /* ^ */
+#ifdef HASHMAGIC
+ *iv_return = HASHMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "RET_ERROR", 9)) {
+ /* ^ */
+#ifdef RET_ERROR
+ *iv_return = RET_ERROR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "R_IBEFORE", 9)) {
+ /* ^ */
+#ifdef R_IBEFORE
+ *iv_return = R_IBEFORE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_10 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ BTREEMAGIC R_FIXEDLEN R_SNAPSHOT __R_UNUSED */
+ /* Offset 5 gives the best switch position. */
+ switch (name[5]) {
+ case 'E':
+ if (memEQ(name, "R_FIXEDLEN", 10)) {
+ /* ^ */
+#ifdef R_FIXEDLEN
+ *iv_return = R_FIXEDLEN;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'M':
+ if (memEQ(name, "BTREEMAGIC", 10)) {
+ /* ^ */
+#ifdef BTREEMAGIC
+ *iv_return = BTREEMAGIC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "__R_UNUSED", 10)) {
+ /* ^ */
+#ifdef __R_UNUSED
+ *iv_return = __R_UNUSED;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'P':
+ if (memEQ(name, "R_SNAPSHOT", 10)) {
+ /* ^ */
+#ifdef R_SNAPSHOT
+ *iv_return = R_SNAPSHOT;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_11 (pTHX_ const char *name, IV *iv_return) {
+ /* When generated this function returned values for the list of names given
+ here. However, subsequent manual editing may have added or removed some.
+ HASHVERSION RET_SPECIAL RET_SUCCESS R_RECNOSYNC R_SETCURSOR */
+ /* Offset 10 gives the best switch position. */
+ switch (name[10]) {
+ case 'C':
+ if (memEQ(name, "R_RECNOSYNC", 11)) {
+ /* ^ */
+#ifdef R_RECNOSYNC
+ *iv_return = R_RECNOSYNC;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'L':
+ if (memEQ(name, "RET_SPECIAL", 11)) {
+ /* ^ */
+#ifdef RET_SPECIAL
+ *iv_return = RET_SPECIAL;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'N':
+ if (memEQ(name, "HASHVERSION", 11)) {
+ /* ^ */
+#ifdef HASHVERSION
+ *iv_return = HASHVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'R':
+ if (memEQ(name, "R_SETCURSOR", 11)) {
+ /* ^ */
+#ifdef R_SETCURSOR
+ *iv_return = R_SETCURSOR;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'S':
+ if (memEQ(name, "RET_SUCCESS", 11)) {
+ /* ^ */
+#ifdef RET_SUCCESS
+ *iv_return = RET_SUCCESS;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
+static int
+constant (pTHX_ const char *name, STRLEN len, IV *iv_return) {
+ /* Initially switch on the length of the name. */
+ /* When generated this function returned values for the list of names given
+ in this section of perl code. Rather than manually editing these functions
+ to add or remove constants, which would result in this comment and section
+ of code becoming inaccurate, we recommend that you edit this section of
+ code, and use it to regenerate a new set of constant functions which you
+ then use to replace the originals.
+
+ Regenerate these constant functions by feeding this entire source file to
+ perl -x
+
+#!bleedperl -w
+use ExtUtils::Constant qw (constant_types C_constant XS_constant);
+
+my $types = {map {($_, 1)} qw(IV)};
+my @names = (qw(BTREEMAGIC BTREEVERSION DB_LOCK DB_SHMEM DB_TXN HASHMAGIC
+ HASHVERSION MAX_PAGE_NUMBER MAX_PAGE_OFFSET MAX_REC_NUMBER
+ RET_ERROR RET_SPECIAL RET_SUCCESS R_CURSOR R_DUP R_FIRST
+ R_FIXEDLEN R_IAFTER R_IBEFORE R_LAST R_NEXT R_NOKEY
+ R_NOOVERWRITE R_PREV R_RECNOSYNC R_SETCURSOR R_SNAPSHOT
+ __R_UNUSED));
+
+print constant_types(); # macro defs
+foreach (C_constant ("DB_File", 'constant', 'IV', $types, undef, 3, @names) ) {
+ print $_, "\n"; # C constant subs
+}
+print "#### XS Section:\n";
+print XS_constant ("DB_File", $types);
+__END__
+ */
+
+ switch (len) {
+ case 5:
+ if (memEQ(name, "R_DUP", 5)) {
+#ifdef R_DUP
+ *iv_return = R_DUP;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 6:
+ return constant_6 (aTHX_ name, iv_return);
+ break;
+ case 7:
+ return constant_7 (aTHX_ name, iv_return);
+ break;
+ case 8:
+ return constant_8 (aTHX_ name, iv_return);
+ break;
+ case 9:
+ return constant_9 (aTHX_ name, iv_return);
+ break;
+ case 10:
+ return constant_10 (aTHX_ name, iv_return);
+ break;
+ case 11:
+ return constant_11 (aTHX_ name, iv_return);
+ break;
+ case 12:
+ if (memEQ(name, "BTREEVERSION", 12)) {
+#ifdef BTREEVERSION
+ *iv_return = BTREEVERSION;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 13:
+ if (memEQ(name, "R_NOOVERWRITE", 13)) {
+#ifdef R_NOOVERWRITE
+ *iv_return = R_NOOVERWRITE;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 14:
+ if (memEQ(name, "MAX_REC_NUMBER", 14)) {
+#ifdef MAX_REC_NUMBER
+ *iv_return = MAX_REC_NUMBER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 15:
+ /* Names all of length 15. */
+ /* MAX_PAGE_NUMBER MAX_PAGE_OFFSET */
+ /* Offset 9 gives the best switch position. */
+ switch (name[9]) {
+ case 'N':
+ if (memEQ(name, "MAX_PAGE_NUMBER", 15)) {
+ /* ^ */
+#ifdef MAX_PAGE_NUMBER
+ *iv_return = MAX_PAGE_NUMBER;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ case 'O':
+ if (memEQ(name, "MAX_PAGE_OFFSET", 15)) {
+ /* ^ */
+#ifdef MAX_PAGE_OFFSET
+ *iv_return = MAX_PAGE_OFFSET;
+ return PERL_constant_ISIV;
+#else
+ return PERL_constant_NOTDEF;
+#endif
+ }
+ break;
+ }
+ break;
+ }
+ return PERL_constant_NOTFOUND;
+}
+
diff --git a/bdb/perl/DB_File/fallback.xs b/bdb/perl/DB_File/fallback.xs
new file mode 100644
index 00000000000..8650cdf7646
--- /dev/null
+++ b/bdb/perl/DB_File/fallback.xs
@@ -0,0 +1,88 @@
+void
+constant(sv)
+ PREINIT:
+#ifdef dXSTARG
+ dXSTARG; /* Faster if we have it. */
+#else
+ dTARGET;
+#endif
+ STRLEN len;
+ int type;
+ IV iv;
+ /* NV nv; Uncomment this if you need to return NVs */
+ /* const char *pv; Uncomment this if you need to return PVs */
+ INPUT:
+ SV * sv;
+ const char * s = SvPV(sv, len);
+ PPCODE:
+ /* Change this to constant(aTHX_ s, len, &iv, &nv);
+ if you need to return both NVs and IVs */
+ type = constant(aTHX_ s, len, &iv);
+ /* Return 1 or 2 items. First is error message, or undef if no error.
+ Second, if present, is found value */
+ switch (type) {
+ case PERL_constant_NOTFOUND:
+ sv = sv_2mortal(newSVpvf("%s is not a valid DB_File macro", s));
+ PUSHs(sv);
+ break;
+ case PERL_constant_NOTDEF:
+ sv = sv_2mortal(newSVpvf(
+ "Your vendor has not defined DB_File macro %s, used", s));
+ PUSHs(sv);
+ break;
+ case PERL_constant_ISIV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHi(iv);
+ break;
+ /* Uncomment this if you need to return NOs
+ case PERL_constant_ISNO:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHs(&PL_sv_no);
+ break; */
+ /* Uncomment this if you need to return NVs
+ case PERL_constant_ISNV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHn(nv);
+ break; */
+ /* Uncomment this if you need to return PVs
+ case PERL_constant_ISPV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHp(pv, strlen(pv));
+ break; */
+ /* Uncomment this if you need to return PVNs
+ case PERL_constant_ISPVN:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHp(pv, iv);
+ break; */
+ /* Uncomment this if you need to return SVs
+ case PERL_constant_ISSV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHs(sv);
+ break; */
+ /* Uncomment this if you need to return UNDEFs
+ case PERL_constant_ISUNDEF:
+ break; */
+ /* Uncomment this if you need to return UVs
+ case PERL_constant_ISUV:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHu((UV)iv);
+ break; */
+ /* Uncomment this if you need to return YESs
+ case PERL_constant_ISYES:
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ PUSHs(&PL_sv_yes);
+ break; */
+ default:
+ sv = sv_2mortal(newSVpvf(
+ "Unexpected return type %d while processing DB_File macro %s, used",
+ type, s));
+ PUSHs(sv);
+ }
diff --git a/bdb/perl.DB_File/hints/dynixptx.pl b/bdb/perl/DB_File/hints/dynixptx.pl
index bb5ffa56e6b..bb5ffa56e6b 100644
--- a/bdb/perl.DB_File/hints/dynixptx.pl
+++ b/bdb/perl/DB_File/hints/dynixptx.pl
diff --git a/bdb/perl.DB_File/hints/sco.pl b/bdb/perl/DB_File/hints/sco.pl
index ff604409496..ff604409496 100644
--- a/bdb/perl.DB_File/hints/sco.pl
+++ b/bdb/perl/DB_File/hints/sco.pl
diff --git a/bdb/perl.DB_File/patches/5.004 b/bdb/perl/DB_File/patches/5.004
index 143ec95afbc..143ec95afbc 100644
--- a/bdb/perl.DB_File/patches/5.004
+++ b/bdb/perl/DB_File/patches/5.004
diff --git a/bdb/perl.DB_File/patches/5.004_01 b/bdb/perl/DB_File/patches/5.004_01
index 1b05eb4e02b..1b05eb4e02b 100644
--- a/bdb/perl.DB_File/patches/5.004_01
+++ b/bdb/perl/DB_File/patches/5.004_01
diff --git a/bdb/perl.DB_File/patches/5.004_02 b/bdb/perl/DB_File/patches/5.004_02
index 238f8737941..238f8737941 100644
--- a/bdb/perl.DB_File/patches/5.004_02
+++ b/bdb/perl/DB_File/patches/5.004_02
diff --git a/bdb/perl.DB_File/patches/5.004_03 b/bdb/perl/DB_File/patches/5.004_03
index 06331eac922..06331eac922 100644
--- a/bdb/perl.DB_File/patches/5.004_03
+++ b/bdb/perl/DB_File/patches/5.004_03
diff --git a/bdb/perl.DB_File/patches/5.004_04 b/bdb/perl/DB_File/patches/5.004_04
index a227dc700d9..a227dc700d9 100644
--- a/bdb/perl.DB_File/patches/5.004_04
+++ b/bdb/perl/DB_File/patches/5.004_04
diff --git a/bdb/perl.DB_File/patches/5.004_05 b/bdb/perl/DB_File/patches/5.004_05
index 51c8bf35009..51c8bf35009 100644
--- a/bdb/perl.DB_File/patches/5.004_05
+++ b/bdb/perl/DB_File/patches/5.004_05
diff --git a/bdb/perl.DB_File/patches/5.005 b/bdb/perl/DB_File/patches/5.005
index effee3e8275..effee3e8275 100644
--- a/bdb/perl.DB_File/patches/5.005
+++ b/bdb/perl/DB_File/patches/5.005
diff --git a/bdb/perl.DB_File/patches/5.005_01 b/bdb/perl/DB_File/patches/5.005_01
index 2a05dd545f6..2a05dd545f6 100644
--- a/bdb/perl.DB_File/patches/5.005_01
+++ b/bdb/perl/DB_File/patches/5.005_01
diff --git a/bdb/perl.DB_File/patches/5.005_02 b/bdb/perl/DB_File/patches/5.005_02
index 5dd57ddc03f..5dd57ddc03f 100644
--- a/bdb/perl.DB_File/patches/5.005_02
+++ b/bdb/perl/DB_File/patches/5.005_02
diff --git a/bdb/perl.DB_File/patches/5.005_03 b/bdb/perl/DB_File/patches/5.005_03
index 115f9f5b909..115f9f5b909 100644
--- a/bdb/perl.DB_File/patches/5.005_03
+++ b/bdb/perl/DB_File/patches/5.005_03
diff --git a/bdb/perl.DB_File/patches/5.6.0 b/bdb/perl/DB_File/patches/5.6.0
index 1f9b3b620de..1f9b3b620de 100644
--- a/bdb/perl.DB_File/patches/5.6.0
+++ b/bdb/perl/DB_File/patches/5.6.0
diff --git a/bdb/perl/DB_File/ppport.h b/bdb/perl/DB_File/ppport.h
new file mode 100644
index 00000000000..0887c2159a9
--- /dev/null
+++ b/bdb/perl/DB_File/ppport.h
@@ -0,0 +1,329 @@
+/* This file is Based on output from
+ * Perl/Pollution/Portability Version 2.0000 */
+
+#ifndef _P_P_PORTABILITY_H_
+#define _P_P_PORTABILITY_H_
+
+#ifndef PERL_REVISION
+# ifndef __PATCHLEVEL_H_INCLUDED__
+# include "patchlevel.h"
+# endif
+# ifndef PERL_REVISION
+# define PERL_REVISION (5)
+ /* Replace: 1 */
+# define PERL_VERSION PATCHLEVEL
+# define PERL_SUBVERSION SUBVERSION
+ /* Replace PERL_PATCHLEVEL with PERL_VERSION */
+ /* Replace: 0 */
+# endif
+#endif
+
+#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
+
+#ifndef ERRSV
+# define ERRSV perl_get_sv("@",FALSE)
+#endif
+
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
+/* Replace: 1 */
+# define PL_Sv Sv
+# define PL_compiling compiling
+# define PL_copline copline
+# define PL_curcop curcop
+# define PL_curstash curstash
+# define PL_defgv defgv
+# define PL_dirty dirty
+# define PL_hints hints
+# define PL_na na
+# define PL_perldb perldb
+# define PL_rsfp_filters rsfp_filters
+# define PL_rsfp rsfp
+# define PL_stdingv stdingv
+# define PL_sv_no sv_no
+# define PL_sv_undef sv_undef
+# define PL_sv_yes sv_yes
+/* Replace: 0 */
+#endif
+
+#ifndef pTHX
+# define pTHX
+# define pTHX_
+# define aTHX
+# define aTHX_
+#endif
+
+#ifndef PTR2IV
+# define PTR2IV(d) (IV)(d)
+#endif
+
+#ifndef INT2PTR
+# define INT2PTR(any,d) (any)(d)
+#endif
+
+#ifndef dTHR
+# ifdef WIN32
+# define dTHR extern int Perl___notused
+# else
+# define dTHR extern int errno
+# endif
+#endif
+
+#ifndef boolSV
+# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
+#endif
+
+#ifndef gv_stashpvn
+# define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
+#endif
+
+#ifndef newSVpvn
+# define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0))
+#endif
+
+#ifndef newRV_inc
+/* Replace: 1 */
+# define newRV_inc(sv) newRV(sv)
+/* Replace: 0 */
+#endif
+
+/* DEFSV appears first in 5.004_56 */
+#ifndef DEFSV
+# define DEFSV GvSV(PL_defgv)
+#endif
+
+#ifndef SAVE_DEFSV
+# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv))
+#endif
+
+#ifndef newRV_noinc
+# ifdef __GNUC__
+# define newRV_noinc(sv) \
+ ({ \
+ SV *nsv = (SV*)newRV(sv); \
+ SvREFCNT_dec(sv); \
+ nsv; \
+ })
+# else
+# if defined(CRIPPLED_CC) || defined(USE_THREADS)
+static SV * newRV_noinc (SV * sv)
+{
+ SV *nsv = (SV*)newRV(sv);
+ SvREFCNT_dec(sv);
+ return nsv;
+}
+# else
+# define newRV_noinc(sv) \
+ ((PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv)
+# endif
+# endif
+#endif
+
+/* Provide: newCONSTSUB */
+
+/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))
+
+#if defined(NEED_newCONSTSUB)
+static
+#else
+extern void newCONSTSUB _((HV * stash, char * name, SV *sv));
+#endif
+
+#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
+void
+newCONSTSUB(stash,name,sv)
+HV *stash;
+char *name;
+SV *sv;
+{
+ U32 oldhints = PL_hints;
+ HV *old_cop_stash = PL_curcop->cop_stash;
+ HV *old_curstash = PL_curstash;
+ line_t oldline = PL_curcop->cop_line;
+ PL_curcop->cop_line = PL_copline;
+
+ PL_hints &= ~HINT_BLOCK_SCOPE;
+ if (stash)
+ PL_curstash = PL_curcop->cop_stash = stash;
+
+ newSUB(
+
+#if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22))
+ /* before 5.003_22 */
+ start_subparse(),
+#else
+# if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22)
+ /* 5.003_22 */
+ start_subparse(0),
+# else
+ /* 5.003_23 onwards */
+ start_subparse(FALSE, 0),
+# endif
+#endif
+
+ newSVOP(OP_CONST, 0, newSVpv(name,0)),
+ newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */
+ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+ );
+
+ PL_hints = oldhints;
+ PL_curcop->cop_stash = old_cop_stash;
+ PL_curstash = old_curstash;
+ PL_curcop->cop_line = oldline;
+}
+#endif
+
+#endif /* newCONSTSUB */
+
+
+#ifndef START_MY_CXT
+
+/*
+ * Boilerplate macros for initializing and accessing interpreter-local
+ * data from C. All statics in extensions should be reworked to use
+ * this, if you want to make the extension thread-safe. See ext/re/re.xs
+ * for an example of the use of these macros.
+ *
+ * Code that uses these macros is responsible for the following:
+ * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
+ * 2. Declare a typedef named my_cxt_t that is a structure that contains
+ * all the data that needs to be interpreter-local.
+ * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
+ * 4. Use the MY_CXT_INIT macro such that it is called exactly once
+ * (typically put in the BOOT: section).
+ * 5. Use the members of the my_cxt_t structure everywhere as
+ * MY_CXT.member.
+ * 6. Use the dMY_CXT macro (a declaration) in all the functions that
+ * access MY_CXT.
+ */
+
+#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
+ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
+
+/* This must appear in all extensions that define a my_cxt_t structure,
+ * right after the definition (i.e. at file scope). The non-threads
+ * case below uses it to declare the data as static. */
+#define START_MY_CXT
+
+#if PERL_REVISION == 5 && \
+ (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
+/* Fetches the SV that keeps the per-interpreter data. */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE)
+#else /* >= perl5.004_68 */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
+ sizeof(MY_CXT_KEY)-1, TRUE)
+#endif /* < perl5.004_68 */
+
+/* This declaration should be used within all functions that use the
+ * interpreter-local data. */
+#define dMY_CXT \
+ dMY_CXT_SV; \
+ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
+
+/* Creates and zeroes the per-interpreter data.
+ * (We allocate my_cxtp in a Perl SV so that it will be released when
+ * the interpreter goes away.) */
+#define MY_CXT_INIT \
+ dMY_CXT_SV; \
+ /* newSV() allocates one more than needed */ \
+ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+ Zero(my_cxtp, 1, my_cxt_t); \
+ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
+
+/* This macro must be used to access members of the my_cxt_t structure.
+ * e.g. MYCXT.some_data */
+#define MY_CXT (*my_cxtp)
+
+/* Judicious use of these macros can reduce the number of times dMY_CXT
+ * is used. Use is similar to pTHX, aTHX etc. */
+#define pMY_CXT my_cxt_t *my_cxtp
+#define pMY_CXT_ pMY_CXT,
+#define _pMY_CXT ,pMY_CXT
+#define aMY_CXT my_cxtp
+#define aMY_CXT_ aMY_CXT,
+#define _aMY_CXT ,aMY_CXT
+
+#else /* single interpreter */
+
+#ifndef NOOP
+# define NOOP (void)0
+#endif
+
+#ifdef HASATTRIBUTE
+# define PERL_UNUSED_DECL __attribute__((unused))
+#else
+# define PERL_UNUSED_DECL
+#endif
+
+#ifndef dNOOP
+# define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#define START_MY_CXT static my_cxt_t my_cxt;
+#define dMY_CXT_SV dNOOP
+#define dMY_CXT dNOOP
+#define MY_CXT_INIT NOOP
+#define MY_CXT my_cxt
+
+#define pMY_CXT void
+#define pMY_CXT_
+#define _pMY_CXT
+#define aMY_CXT
+#define aMY_CXT_
+#define _aMY_CXT
+
+#endif
+
+#endif /* START_MY_CXT */
+
+
+#ifndef DBM_setFilter
+
+/*
+ The DBM_setFilter & DBM_ckFilter macros are only used by
+ the *DB*_File modules
+*/
+
+#define DBM_setFilter(db_type,code) \
+ { \
+ if (db_type) \
+ RETVAL = sv_mortalcopy(db_type) ; \
+ ST(0) = RETVAL ; \
+ if (db_type && (code == &PL_sv_undef)) { \
+ SvREFCNT_dec(db_type) ; \
+ db_type = NULL ; \
+ } \
+ else if (code) { \
+ if (db_type) \
+ sv_setsv(db_type, code) ; \
+ else \
+ db_type = newSVsv(code) ; \
+ } \
+ }
+
+#define DBM_ckFilter(arg,type,name) \
+ if (db->type) { \
+ if (db->filtering) { \
+ croak("recursion detected in %s", name) ; \
+ } \
+ ENTER ; \
+ SAVETMPS ; \
+ SAVEINT(db->filtering) ; \
+ db->filtering = TRUE ; \
+ SAVESPTR(DEFSV) ; \
+ DEFSV = arg ; \
+ SvTEMP_off(arg) ; \
+ PUSHMARK(SP) ; \
+ PUTBACK ; \
+ (void) perl_call_sv(db->type, G_DISCARD); \
+ SPAGAIN ; \
+ PUTBACK ; \
+ FREETMPS ; \
+ LEAVE ; \
+ }
+
+#endif /* DBM_setFilter */
+
+#endif /* _P_P_PORTABILITY_H_ */
diff --git a/bdb/perl/DB_File/t/db-btree.t b/bdb/perl/DB_File/t/db-btree.t
new file mode 100644
index 00000000000..a990a5c4ba5
--- /dev/null
+++ b/bdb/perl/DB_File/t/db-btree.t
@@ -0,0 +1,1489 @@
+#!./perl -w
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use warnings;
+use strict;
+use Config;
+
+BEGIN {
+ if(-d "lib" && -f "TEST") {
+ if ($Config{'extensions'} !~ /\bDB_File\b/ ) {
+ print "1..0 # Skip: DB_File was not built\n";
+ exit 0;
+ }
+ }
+ if ($^O eq 'darwin'
+ && $Config{db_version_major} == 1
+ && $Config{db_version_minor} == 0
+ && $Config{db_version_patch} == 0) {
+ warn <<EOM;
+#
+# This test is known to crash in Mac OS X versions 10.1.4 (or earlier)
+# because of the buggy Berkeley DB version included with the OS.
+#
+EOM
+ }
+}
+
+use DB_File;
+use Fcntl;
+
+print "1..177\n";
+
+sub ok
+{
+ my $no = shift ;
+ my $result = shift ;
+
+ print "not " unless $result ;
+ print "ok $no\n" ;
+}
+
+sub lexical
+{
+ my(@a) = unpack ("C*", $a) ;
+ my(@b) = unpack ("C*", $b) ;
+
+ my $len = (@a > @b ? @b : @a) ;
+ my $i = 0 ;
+
+ foreach $i ( 0 .. $len -1) {
+ return $a[$i] - $b[$i] if $a[$i] != $b[$i] ;
+ }
+
+ return @a - @b ;
+}
+
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat
+{
+ my $file = shift;
+ local $/ = undef ;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my $result = <CAT>;
+ close(CAT);
+ $result = normalise($result) ;
+ return $result ;
+}
+
+sub docat_del
+{
+ my $file = shift;
+ my $result = docat($file);
+ unlink $file ;
+ return $result ;
+}
+
+sub normalise
+{
+ my $data = shift ;
+ $data =~ s#\r\n#\n#g
+ if $^O eq 'cygwin' ;
+
+ return $data ;
+}
+
+sub safeUntie
+{
+ my $hashref = shift ;
+ my $no_inner = 1;
+ local $SIG{__WARN__} = sub {-- $no_inner } ;
+ untie %$hashref;
+ return $no_inner;
+}
+
+
+
+my $db185mode = ($DB_File::db_version == 1 && ! $DB_File::db_185_compat) ;
+my $null_keys_allowed = ($DB_File::db_ver < 2.004010
+ || $DB_File::db_ver >= 3.1 );
+
+my $Dfile = "dbbtree.tmp";
+unlink $Dfile;
+
+umask(0);
+
+# Check the interface to BTREEINFO
+
+my $dbh = new DB_File::BTREEINFO ;
+ok(1, ! defined $dbh->{flags}) ;
+ok(2, ! defined $dbh->{cachesize}) ;
+ok(3, ! defined $dbh->{psize}) ;
+ok(4, ! defined $dbh->{lorder}) ;
+ok(5, ! defined $dbh->{minkeypage}) ;
+ok(6, ! defined $dbh->{maxkeypage}) ;
+ok(7, ! defined $dbh->{compare}) ;
+ok(8, ! defined $dbh->{prefix}) ;
+
+$dbh->{flags} = 3000 ;
+ok(9, $dbh->{flags} == 3000) ;
+
+$dbh->{cachesize} = 9000 ;
+ok(10, $dbh->{cachesize} == 9000);
+
+$dbh->{psize} = 400 ;
+ok(11, $dbh->{psize} == 400) ;
+
+$dbh->{lorder} = 65 ;
+ok(12, $dbh->{lorder} == 65) ;
+
+$dbh->{minkeypage} = 123 ;
+ok(13, $dbh->{minkeypage} == 123) ;
+
+$dbh->{maxkeypage} = 1234 ;
+ok(14, $dbh->{maxkeypage} == 1234 );
+
+# Check that an invalid entry is caught both for store & fetch
+eval '$dbh->{fred} = 1234' ;
+ok(15, $@ =~ /^DB_File::BTREEINFO::STORE - Unknown element 'fred' at/ ) ;
+eval 'my $q = $dbh->{fred}' ;
+ok(16, $@ =~ /^DB_File::BTREEINFO::FETCH - Unknown element 'fred' at/ ) ;
+
+# Now check the interface to BTREE
+
+my ($X, %h) ;
+ok(17, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE )) ;
+die "Could not tie: $!" unless $X;
+
+my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
+ $blksize,$blocks) = stat($Dfile);
+
+my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ;
+
+ok(18, ($mode & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640)
+ || $noMode{$^O} );
+
+my ($key, $value, $i);
+while (($key,$value) = each(%h)) {
+ $i++;
+}
+ok(19, !$i ) ;
+
+$h{'goner1'} = 'snork';
+
+$h{'abc'} = 'ABC';
+ok(20, $h{'abc'} eq 'ABC' );
+ok(21, ! defined $h{'jimmy'} ) ;
+ok(22, ! exists $h{'jimmy'} ) ;
+ok(23, defined $h{'abc'} ) ;
+
+$h{'def'} = 'DEF';
+$h{'jkl','mno'} = "JKL\034MNO";
+$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5);
+$h{'a'} = 'A';
+
+#$h{'b'} = 'B';
+$X->STORE('b', 'B') ;
+
+$h{'c'} = 'C';
+
+#$h{'d'} = 'D';
+$X->put('d', 'D') ;
+
+$h{'e'} = 'E';
+$h{'f'} = 'F';
+$h{'g'} = 'X';
+$h{'h'} = 'H';
+$h{'i'} = 'I';
+
+$h{'goner2'} = 'snork';
+delete $h{'goner2'};
+
+
+# IMPORTANT - $X must be undefined before the untie otherwise the
+# underlying DB close routine will not get called.
+undef $X ;
+untie(%h);
+
+# tie to the same file again
+ok(24, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE)) ;
+
+# Modify an entry from the previous tie
+$h{'g'} = 'G';
+
+$h{'j'} = 'J';
+$h{'k'} = 'K';
+$h{'l'} = 'L';
+$h{'m'} = 'M';
+$h{'n'} = 'N';
+$h{'o'} = 'O';
+$h{'p'} = 'P';
+$h{'q'} = 'Q';
+$h{'r'} = 'R';
+$h{'s'} = 'S';
+$h{'t'} = 'T';
+$h{'u'} = 'U';
+$h{'v'} = 'V';
+$h{'w'} = 'W';
+$h{'x'} = 'X';
+$h{'y'} = 'Y';
+$h{'z'} = 'Z';
+
+$h{'goner3'} = 'snork';
+
+delete $h{'goner1'};
+$X->DELETE('goner3');
+
+my @keys = keys(%h);
+my @values = values(%h);
+
+ok(25, $#keys == 29 && $#values == 29) ;
+
+$i = 0 ;
+while (($key,$value) = each(%h)) {
+ if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) {
+ $key =~ y/a-z/A-Z/;
+ $i++ if $key eq $value;
+ }
+}
+
+ok(26, $i == 30) ;
+
+@keys = ('blurfl', keys(%h), 'dyick');
+ok(27, $#keys == 31) ;
+
+#Check that the keys can be retrieved in order
+my @b = keys %h ;
+my @c = sort lexical @b ;
+ok(28, ArrayCompare(\@b, \@c)) ;
+
+$h{'foo'} = '';
+ok(29, $h{'foo'} eq '' ) ;
+
+# Berkeley DB from version 2.4.10 to 3.0 does not allow null keys.
+# This feature was reenabled in version 3.1 of Berkeley DB.
+my $result = 0 ;
+if ($null_keys_allowed) {
+ $h{''} = 'bar';
+ $result = ( $h{''} eq 'bar' );
+}
+else
+ { $result = 1 }
+ok(30, $result) ;
+
+# check cache overflow and numeric keys and contents
+my $ok = 1;
+for ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; }
+for ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; }
+ok(31, $ok);
+
+($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
+ $blksize,$blocks) = stat($Dfile);
+ok(32, $size > 0 );
+
+@h{0..200} = 200..400;
+my @foo = @h{0..200};
+ok(33, join(':',200..400) eq join(':',@foo) );
+
+# Now check all the non-tie specific stuff
+
+
+# Check R_NOOVERWRITE flag will make put fail when attempting to overwrite
+# an existing record.
+
+my $status = $X->put( 'x', 'newvalue', R_NOOVERWRITE) ;
+ok(34, $status == 1 );
+
+# check that the value of the key 'x' has not been changed by the
+# previous test
+ok(35, $h{'x'} eq 'X' );
+
+# standard put
+$status = $X->put('key', 'value') ;
+ok(36, $status == 0 );
+
+#check that previous put can be retrieved
+$value = 0 ;
+$status = $X->get('key', $value) ;
+ok(37, $status == 0 );
+ok(38, $value eq 'value' );
+
+# Attempting to delete an existing key should work
+
+$status = $X->del('q') ;
+ok(39, $status == 0 );
+if ($null_keys_allowed) {
+ $status = $X->del('') ;
+} else {
+ $status = 0 ;
+}
+ok(40, $status == 0 );
+
+# Make sure that the key deleted, cannot be retrieved
+ok(41, ! defined $h{'q'}) ;
+ok(42, ! defined $h{''}) ;
+
+undef $X ;
+untie %h ;
+
+ok(43, $X = tie(%h, 'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE ));
+
+# Attempting to delete a non-existant key should fail
+
+$status = $X->del('joe') ;
+ok(44, $status == 1 );
+
+# Check the get interface
+
+# First a non-existing key
+$status = $X->get('aaaa', $value) ;
+ok(45, $status == 1 );
+
+# Next an existing key
+$status = $X->get('a', $value) ;
+ok(46, $status == 0 );
+ok(47, $value eq 'A' );
+
+# seq
+# ###
+
+# use seq to find an approximate match
+$key = 'ke' ;
+$value = '' ;
+$status = $X->seq($key, $value, R_CURSOR) ;
+ok(48, $status == 0 );
+ok(49, $key eq 'key' );
+ok(50, $value eq 'value' );
+
+# seq when the key does not match
+$key = 'zzz' ;
+$value = '' ;
+$status = $X->seq($key, $value, R_CURSOR) ;
+ok(51, $status == 1 );
+
+
+# use seq to set the cursor, then delete the record @ the cursor.
+
+$key = 'x' ;
+$value = '' ;
+$status = $X->seq($key, $value, R_CURSOR) ;
+ok(52, $status == 0 );
+ok(53, $key eq 'x' );
+ok(54, $value eq 'X' );
+$status = $X->del(0, R_CURSOR) ;
+ok(55, $status == 0 );
+$status = $X->get('x', $value) ;
+ok(56, $status == 1 );
+
+# ditto, but use put to replace the key/value pair.
+$key = 'y' ;
+$value = '' ;
+$status = $X->seq($key, $value, R_CURSOR) ;
+ok(57, $status == 0 );
+ok(58, $key eq 'y' );
+ok(59, $value eq 'Y' );
+
+$key = "replace key" ;
+$value = "replace value" ;
+$status = $X->put($key, $value, R_CURSOR) ;
+ok(60, $status == 0 );
+ok(61, $key eq 'replace key' );
+ok(62, $value eq 'replace value' );
+$status = $X->get('y', $value) ;
+ok(63, 1) ; # hard-wire to always pass. the previous test ($status == 1)
+ # only worked because of a bug in 1.85/6
+
+# use seq to walk forwards through a file
+
+$status = $X->seq($key, $value, R_FIRST) ;
+ok(64, $status == 0 );
+my $previous = $key ;
+
+$ok = 1 ;
+while (($status = $X->seq($key, $value, R_NEXT)) == 0)
+{
+ ($ok = 0), last if ($previous cmp $key) == 1 ;
+}
+
+ok(65, $status == 1 );
+ok(66, $ok == 1 );
+
+# use seq to walk backwards through a file
+$status = $X->seq($key, $value, R_LAST) ;
+ok(67, $status == 0 );
+$previous = $key ;
+
+$ok = 1 ;
+while (($status = $X->seq($key, $value, R_PREV)) == 0)
+{
+ ($ok = 0), last if ($previous cmp $key) == -1 ;
+ #print "key = [$key] value = [$value]\n" ;
+}
+
+ok(68, $status == 1 );
+ok(69, $ok == 1 );
+
+
+# check seq FIRST/LAST
+
+# sync
+# ####
+
+$status = $X->sync ;
+ok(70, $status == 0 );
+
+
+# fd
+# ##
+
+$status = $X->fd ;
+ok(71, $status != 0 );
+
+
+undef $X ;
+untie %h ;
+
+unlink $Dfile;
+
+# Now try an in memory file
+my $Y;
+ok(72, $Y = tie(%h, 'DB_File',undef, O_RDWR|O_CREAT, 0640, $DB_BTREE ));
+
+# fd with an in memory file should return failure
+$status = $Y->fd ;
+ok(73, $status == -1 );
+
+
+undef $Y ;
+untie %h ;
+
+# Duplicate keys
+my $bt = new DB_File::BTREEINFO ;
+$bt->{flags} = R_DUP ;
+my ($YY, %hh);
+ok(74, $YY = tie(%hh, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $bt )) ;
+
+$hh{'Wall'} = 'Larry' ;
+$hh{'Wall'} = 'Stone' ; # Note the duplicate key
+$hh{'Wall'} = 'Brick' ; # Note the duplicate key
+$hh{'Wall'} = 'Brick' ; # Note the duplicate key and value
+$hh{'Smith'} = 'John' ;
+$hh{'mouse'} = 'mickey' ;
+
+# first work in scalar context
+ok(75, scalar $YY->get_dup('Unknown') == 0 );
+ok(76, scalar $YY->get_dup('Smith') == 1 );
+ok(77, scalar $YY->get_dup('Wall') == 4 );
+
+# now in list context
+my @unknown = $YY->get_dup('Unknown') ;
+ok(78, "@unknown" eq "" );
+
+my @smith = $YY->get_dup('Smith') ;
+ok(79, "@smith" eq "John" );
+
+{
+my @wall = $YY->get_dup('Wall') ;
+my %wall ;
+@wall{@wall} = @wall ;
+ok(80, (@wall == 4 && $wall{'Larry'} && $wall{'Stone'} && $wall{'Brick'}) );
+}
+
+# hash
+my %unknown = $YY->get_dup('Unknown', 1) ;
+ok(81, keys %unknown == 0 );
+
+my %smith = $YY->get_dup('Smith', 1) ;
+ok(82, keys %smith == 1 && $smith{'John'}) ;
+
+my %wall = $YY->get_dup('Wall', 1) ;
+ok(83, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1
+ && $wall{'Brick'} == 2);
+
+undef $YY ;
+untie %hh ;
+unlink $Dfile;
+
+
+# test multiple callbacks
+my $Dfile1 = "btree1" ;
+my $Dfile2 = "btree2" ;
+my $Dfile3 = "btree3" ;
+
+my $dbh1 = new DB_File::BTREEINFO ;
+$dbh1->{compare} = sub {
+ no warnings 'numeric' ;
+ $_[0] <=> $_[1] } ;
+
+my $dbh2 = new DB_File::BTREEINFO ;
+$dbh2->{compare} = sub { $_[0] cmp $_[1] } ;
+
+my $dbh3 = new DB_File::BTREEINFO ;
+$dbh3->{compare} = sub { length $_[0] <=> length $_[1] } ;
+
+
+my (%g, %k);
+tie(%h, 'DB_File',$Dfile1, O_RDWR|O_CREAT, 0640, $dbh1 ) or die $!;
+tie(%g, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) or die $!;
+tie(%k, 'DB_File',$Dfile3, O_RDWR|O_CREAT, 0640, $dbh3 ) or die $!;
+
+my @Keys = qw( 0123 12 -1234 9 987654321 def ) ;
+my (@srt_1, @srt_2, @srt_3);
+{
+ no warnings 'numeric' ;
+ @srt_1 = sort { $a <=> $b } @Keys ;
+}
+@srt_2 = sort { $a cmp $b } @Keys ;
+@srt_3 = sort { length $a <=> length $b } @Keys ;
+
+foreach (@Keys) {
+ $h{$_} = 1 ;
+ $g{$_} = 1 ;
+ $k{$_} = 1 ;
+}
+
+sub ArrayCompare
+{
+ my($a, $b) = @_ ;
+
+ return 0 if @$a != @$b ;
+
+ foreach (1 .. length @$a)
+ {
+ return 0 unless $$a[$_] eq $$b[$_] ;
+ }
+
+ 1 ;
+}
+
+ok(84, ArrayCompare (\@srt_1, [keys %h]) );
+ok(85, ArrayCompare (\@srt_2, [keys %g]) );
+ok(86, ArrayCompare (\@srt_3, [keys %k]) );
+
+untie %h ;
+untie %g ;
+untie %k ;
+unlink $Dfile1, $Dfile2, $Dfile3 ;
+
+# clear
+# #####
+
+ok(87, tie(%h, 'DB_File', $Dfile1, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+foreach (1 .. 10)
+ { $h{$_} = $_ * 100 }
+
+# check that there are 10 elements in the hash
+$i = 0 ;
+while (($key,$value) = each(%h)) {
+ $i++;
+}
+ok(88, $i == 10);
+
+# now clear the hash
+%h = () ;
+
+# check it is empty
+$i = 0 ;
+while (($key,$value) = each(%h)) {
+ $i++;
+}
+ok(89, $i == 0);
+
+untie %h ;
+unlink $Dfile1 ;
+
+{
+ # check that attempting to tie an array to a DB_BTREE will fail
+
+ my $filename = "xyz" ;
+ my @x ;
+ eval { tie @x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE ; } ;
+ ok(90, $@ =~ /^DB_File can only tie an associative array to a DB_BTREE database/) ;
+ unlink $filename ;
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use warnings ;
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use warnings ;
+ use strict ;
+ our (@ISA, @EXPORT);
+
+ require Exporter ;
+ use DB_File;
+ @ISA=qw(DB_File);
+ @EXPORT = @DB_File::EXPORT ;
+
+ sub STORE {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::STORE($key, $value * 2) ;
+ }
+
+ sub FETCH {
+ my $self = shift ;
+ my $key = shift ;
+ $self->SUPER::FETCH($key) - 1 ;
+ }
+
+ sub put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::put($key, $value * 3) ;
+ }
+
+ sub get {
+ my $self = shift ;
+ $self->SUPER::get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE ;
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok(91, $@ eq "") ;
+ my %h ;
+ my $X ;
+ eval '
+ $X = tie(%h, "SubDB","dbbtree.tmp", O_RDWR|O_CREAT, 0640, $DB_BTREE );
+ ' ;
+
+ main::ok(92, $@ eq "") ;
+
+ my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
+ main::ok(93, $@ eq "") ;
+ main::ok(94, $ret == 5) ;
+
+ my $value = 0;
+ $ret = eval '$X->put("joe", 4) ; $X->get("joe", $value) ; return $value' ;
+ main::ok(95, $@ eq "") ;
+ main::ok(96, $ret == 10) ;
+
+ $ret = eval ' R_NEXT eq main::R_NEXT ' ;
+ main::ok(97, $@ eq "" ) ;
+ main::ok(98, $ret == 1) ;
+
+ $ret = eval '$X->A_new_method("joe") ' ;
+ main::ok(99, $@ eq "") ;
+ main::ok(100, $ret eq "[[11]]") ;
+
+ undef $X;
+ untie(%h);
+ unlink "SubDB.pm", "dbbtree.tmp" ;
+
+}
+
+{
+ # DBM Filter tests
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok(101, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(102, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(103, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(104, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(105, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(106, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(107, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(108, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(109, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(110, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(111, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(112, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(113, $h{"fred"} eq "joe");
+ ok(114, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(115, $db->FIRSTKEY() eq "fred") ;
+ ok(116, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(117, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(118, $h{"fred"} eq "joe");
+ ok(119, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(120, $db->FIRSTKEY() eq "fred") ;
+ ok(121, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+
+ unlink $Dfile;
+ ok(122, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(123, $result{"store key"} eq "store key - 1: [fred]");
+ ok(124, $result{"store value"} eq "store value - 1: [joe]");
+ ok(125, ! defined $result{"fetch key"} );
+ ok(126, ! defined $result{"fetch value"} );
+ ok(127, $_ eq "original") ;
+
+ ok(128, $db->FIRSTKEY() eq "fred") ;
+ ok(129, $result{"store key"} eq "store key - 1: [fred]");
+ ok(130, $result{"store value"} eq "store value - 1: [joe]");
+ ok(131, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(132, ! defined $result{"fetch value"} );
+ ok(133, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(134, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(135, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(136, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(137, ! defined $result{"fetch value"} );
+ ok(138, $_ eq "original") ;
+
+ ok(139, $h{"fred"} eq "joe");
+ ok(140, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(141, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(142, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(143, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(144, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok(145, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(146, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+
+{
+ # Examples from the POD
+
+
+ my $file = "xyzt" ;
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 1
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+
+ my %h ;
+
+ sub Compare
+ {
+ my ($key1, $key2) = @_ ;
+ "\L$key1" cmp "\L$key2" ;
+ }
+
+ # specify the Perl sub that will do the comparison
+ $DB_BTREE->{'compare'} = \&Compare ;
+
+ unlink "tree" ;
+ tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open file 'tree': $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+
+ unlink "tree" ;
+ }
+
+ delete $DB_BTREE->{'compare'} ;
+
+ ok(147, docat_del($file) eq <<'EOM') ;
+mouse
+Smith
+Wall
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 2
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, %h);
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+
+ # iterate through the associative array
+ # and print each key/value pair.
+ foreach (keys %h)
+ { print "$_ -> $h{$_}\n" }
+
+ untie %h ;
+
+ unlink $filename ;
+ }
+
+ ok(148, docat_del($file) eq ($db185mode ? <<'EOM' : <<'EOM') ) ;
+Smith -> John
+Wall -> Brick
+Wall -> Brick
+Wall -> Brick
+mouse -> mickey
+EOM
+Smith -> John
+Wall -> Larry
+Wall -> Larry
+Wall -> Larry
+mouse -> mickey
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 3
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h, $status, $key, $value);
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+
+ # iterate through the btree using seq
+ # and print each key/value pair.
+ $key = $value = 0 ;
+ for ($status = $x->seq($key, $value, R_FIRST) ;
+ $status == 0 ;
+ $status = $x->seq($key, $value, R_NEXT) )
+ { print "$key -> $value\n" }
+
+
+ undef $x ;
+ untie %h ;
+ }
+
+ ok(149, docat_del($file) eq ($db185mode == 1 ? <<'EOM' : <<'EOM') ) ;
+Smith -> John
+Wall -> Brick
+Wall -> Brick
+Wall -> Larry
+mouse -> mickey
+EOM
+Smith -> John
+Wall -> Larry
+Wall -> Brick
+Wall -> Brick
+mouse -> mickey
+EOM
+
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 4
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h);
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ my $cnt = $x->get_dup("Wall") ;
+ print "Wall occurred $cnt times\n" ;
+
+ my %hash = $x->get_dup("Wall", 1) ;
+ print "Larry is there\n" if $hash{'Larry'} ;
+ print "There are $hash{'Brick'} Brick Walls\n" ;
+
+ my @list = sort $x->get_dup("Wall") ;
+ print "Wall => [@list]\n" ;
+
+ @list = $x->get_dup("Smith") ;
+ print "Smith => [@list]\n" ;
+
+ @list = $x->get_dup("Dog") ;
+ print "Dog => [@list]\n" ;
+
+ undef $x ;
+ untie %h ;
+ }
+
+ ok(150, docat_del($file) eq <<'EOM') ;
+Wall occurred 3 times
+Larry is there
+There are 2 Brick Walls
+Wall => [Brick Brick Larry]
+Smith => [John]
+Dog => []
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 5
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h, $found);
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
+ print "Larry Wall is $found there\n" ;
+
+ $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
+ print "Harry Wall is $found there\n" ;
+
+ undef $x ;
+ untie %h ;
+ }
+
+ ok(151, docat_del($file) eq <<'EOM') ;
+Larry Wall is there
+Harry Wall is not there
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 6
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+
+ my ($filename, $x, %h, $found);
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ $x->del_dup("Wall", "Larry") ;
+
+ $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
+ print "Larry Wall is $found there\n" ;
+
+ undef $x ;
+ untie %h ;
+
+ unlink $filename ;
+ }
+
+ ok(152, docat_del($file) eq <<'EOM') ;
+Larry Wall is not there
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 7
+ ###
+
+ use warnings FATAL => qw(all) ;
+ use strict ;
+ use DB_File ;
+ use Fcntl ;
+
+ my ($filename, $x, %h, $st, $key, $value);
+
+ sub match
+ {
+ my $key = shift ;
+ my $value = 0;
+ my $orig_key = $key ;
+ $x->seq($key, $value, R_CURSOR) ;
+ print "$orig_key\t-> $key\t-> $value\n" ;
+ }
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'mouse'} = 'mickey' ;
+ $h{'Wall'} = 'Larry' ;
+ $h{'Walls'} = 'Brick' ;
+ $h{'Smith'} = 'John' ;
+
+
+ $key = $value = 0 ;
+ print "IN ORDER\n" ;
+ for ($st = $x->seq($key, $value, R_FIRST) ;
+ $st == 0 ;
+ $st = $x->seq($key, $value, R_NEXT) )
+
+ { print "$key -> $value\n" }
+
+ print "\nPARTIAL MATCH\n" ;
+
+ match "Wa" ;
+ match "A" ;
+ match "a" ;
+
+ undef $x ;
+ untie %h ;
+
+ unlink $filename ;
+
+ }
+
+ ok(153, docat_del($file) eq <<'EOM') ;
+IN ORDER
+Smith -> John
+Wall -> Larry
+Walls -> Brick
+mouse -> mickey
+
+PARTIAL MATCH
+Wa -> Wall -> Larry
+A -> Smith -> John
+a -> mouse -> mickey
+EOM
+
+}
+
+#{
+# # R_SETCURSOR
+# use strict ;
+# my (%h, $db) ;
+# unlink $Dfile;
+#
+# ok(156, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+#
+# $h{abc} = 33 ;
+# my $k = "newest" ;
+# my $v = 44 ;
+# my $status = $db->put($k, $v, R_SETCURSOR) ;
+# print "status = [$status]\n" ;
+# ok(157, $status == 0) ;
+# $status = $db->del($k, R_CURSOR) ;
+# print "status = [$status]\n" ;
+# ok(158, $status == 0) ;
+# $k = "newest" ;
+# ok(159, $db->get($k, $v, R_CURSOR)) ;
+#
+# ok(160, keys %h == 1) ;
+#
+# undef $db ;
+# untie %h;
+# unlink $Dfile;
+#}
+
+{
+ # Bug ID 20001013.009
+ #
+ # test that $hash{KEY} = undef doesn't produce the warning
+ # Use of uninitialized value in null operation
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my %h ;
+ my $a = "";
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ tie %h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_BTREE
+ or die "Can't open file: $!\n" ;
+ $h{ABC} = undef;
+ ok(154, $a eq "") ;
+ untie %h ;
+ unlink $Dfile;
+}
+
+{
+ # test that %hash = () doesn't produce the warning
+ # Argument "" isn't numeric in entersub
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my %h ;
+ my $a = "";
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ tie %h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_BTREE
+ or die "Can't open file: $!\n" ;
+ %h = (); ;
+ ok(155, $a eq "") ;
+ untie %h ;
+ unlink $Dfile;
+}
+
+{
+ # When iterating over a tied hash using "each", the key passed to FETCH
+ # will be recycled and passed to NEXTKEY. If a Source Filter modifies the
+ # key in FETCH via a filter_fetch_key method we need to check that the
+ # modified key doesn't get passed to NEXTKEY.
+ # Also Test "keys" & "values" while we are at it.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my $bad_key = 0 ;
+ my %h = () ;
+ my $db ;
+ ok(156, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+ $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}) ;
+ $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/ ; $_ =~ s/^Alpha_/Beta_/}) ;
+
+ $h{'Alpha_ABC'} = 2 ;
+ $h{'Alpha_DEF'} = 5 ;
+
+ ok(157, $h{'Alpha_ABC'} == 2);
+ ok(158, $h{'Alpha_DEF'} == 5);
+
+ my ($k, $v) = ("","");
+ while (($k, $v) = each %h) {}
+ ok(159, $bad_key == 0);
+
+ $bad_key = 0 ;
+ foreach $k (keys %h) {}
+ ok(160, $bad_key == 0);
+
+ $bad_key = 0 ;
+ foreach $v (values %h) {}
+ ok(161, $bad_key == 0);
+
+ undef $db ;
+ untie %h ;
+ unlink $Dfile;
+}
+
+{
+ # now an error to pass 'compare' a non-code reference
+ my $dbh = new DB_File::BTREEINFO ;
+
+ eval { $dbh->{compare} = 2 };
+ ok(162, $@ =~ /^Key 'compare' not associated with a code reference at/);
+
+ eval { $dbh->{prefix} = 2 };
+ ok(163, $@ =~ /^Key 'prefix' not associated with a code reference at/);
+
+}
+
+
+{
+ # recursion detection in btree
+ my %hash ;
+ unlink $Dfile;
+ my $dbh = new DB_File::BTREEINFO ;
+ $dbh->{compare} = sub { $hash{3} = 4 ; length $_[0] } ;
+
+
+ my (%h);
+ ok(164, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) );
+
+ eval { $hash{1} = 2;
+ $hash{4} = 5;
+ };
+
+ ok(165, $@ =~ /^DB_File btree_compare: recursion detected/);
+ {
+ no warnings;
+ untie %hash;
+ }
+ unlink $Dfile;
+}
+
+{
+ # Check that two callbacks don't interact
+ my %hash1 ;
+ my %hash2 ;
+ my $h1_count = 0;
+ my $h2_count = 0;
+ unlink $Dfile, $Dfile2;
+ my $dbh1 = new DB_File::BTREEINFO ;
+ $dbh1->{compare} = sub { ++ $h1_count ; $_[0] cmp $_[1] } ;
+
+ my $dbh2 = new DB_File::BTREEINFO ;
+ $dbh2->{compare} = sub { ;++ $h2_count ; $_[0] cmp $_[1] } ;
+
+
+
+ my (%h);
+ ok(166, tie(%hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh1 ) );
+ ok(167, tie(%hash2, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) );
+
+ $hash1{DEFG} = 5;
+ $hash1{XYZ} = 2;
+ $hash1{ABCDE} = 5;
+
+ $hash2{defg} = 5;
+ $hash2{xyz} = 2;
+ $hash2{abcde} = 5;
+
+ ok(168, $h1_count > 0);
+ ok(169, $h1_count == $h2_count);
+
+ ok(170, safeUntie \%hash1);
+ ok(171, safeUntie \%hash2);
+ unlink $Dfile, $Dfile2;
+}
+
+{
+ # Check that DBM Filter can cope with read-only $_
+
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok(172, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ $db->filter_fetch_key (sub { }) ;
+ $db->filter_store_key (sub { }) ;
+ $db->filter_fetch_value (sub { }) ;
+ $db->filter_store_value (sub { }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(173, $h{"fred"} eq "joe");
+
+ eval { grep { $h{$_} } (1, 2, 3) };
+ ok (174, ! $@);
+
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ $h{"fred"} = "joe" ;
+
+ ok(175, $h{"fred"} eq "joe");
+
+ ok(176, $db->FIRSTKEY() eq "fred") ;
+
+ eval { grep { $h{$_} } (1, 2, 3) };
+ ok (177, ! $@);
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+exit ;
diff --git a/bdb/perl/DB_File/t/db-hash.t b/bdb/perl/DB_File/t/db-hash.t
new file mode 100644
index 00000000000..10623cc82a7
--- /dev/null
+++ b/bdb/perl/DB_File/t/db-hash.t
@@ -0,0 +1,981 @@
+#!./perl
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use warnings;
+use strict;
+use Config;
+
+BEGIN {
+ if(-d "lib" && -f "TEST") {
+ if ($Config{'extensions'} !~ /\bDB_File\b/ ) {
+ print "1..0 # Skip: DB_File was not built\n";
+ exit 0;
+ }
+ }
+}
+
+use DB_File;
+use Fcntl;
+
+print "1..143\n";
+
+sub ok
+{
+ my $no = shift ;
+ my $result = shift ;
+
+ print "not " unless $result ;
+ print "ok $no\n" ;
+}
+
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat_del
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my $result = <CAT>;
+ close(CAT);
+ $result = normalise($result) ;
+ unlink $file ;
+ return $result;
+}
+
+sub normalise
+{
+ my $data = shift ;
+ $data =~ s#\r\n#\n#g
+ if $^O eq 'cygwin' ;
+ return $data ;
+}
+
+sub safeUntie
+{
+ my $hashref = shift ;
+ my $no_inner = 1;
+ local $SIG{__WARN__} = sub {-- $no_inner } ;
+ untie %$hashref;
+ return $no_inner;
+}
+
+
+my $Dfile = "dbhash.tmp";
+my $Dfile2 = "dbhash2.tmp";
+my $null_keys_allowed = ($DB_File::db_ver < 2.004010
+ || $DB_File::db_ver >= 3.1 );
+
+unlink $Dfile;
+
+umask(0);
+
+# Check the interface to HASHINFO
+
+my $dbh = new DB_File::HASHINFO ;
+
+ok(1, ! defined $dbh->{bsize}) ;
+ok(2, ! defined $dbh->{ffactor}) ;
+ok(3, ! defined $dbh->{nelem}) ;
+ok(4, ! defined $dbh->{cachesize}) ;
+ok(5, ! defined $dbh->{hash}) ;
+ok(6, ! defined $dbh->{lorder}) ;
+
+$dbh->{bsize} = 3000 ;
+ok(7, $dbh->{bsize} == 3000 );
+
+$dbh->{ffactor} = 9000 ;
+ok(8, $dbh->{ffactor} == 9000 );
+
+$dbh->{nelem} = 400 ;
+ok(9, $dbh->{nelem} == 400 );
+
+$dbh->{cachesize} = 65 ;
+ok(10, $dbh->{cachesize} == 65 );
+
+my $some_sub = sub {} ;
+$dbh->{hash} = $some_sub;
+ok(11, $dbh->{hash} eq $some_sub );
+
+$dbh->{lorder} = 1234 ;
+ok(12, $dbh->{lorder} == 1234 );
+
+# Check that an invalid entry is caught both for store & fetch
+eval '$dbh->{fred} = 1234' ;
+ok(13, $@ =~ /^DB_File::HASHINFO::STORE - Unknown element 'fred' at/ );
+eval 'my $q = $dbh->{fred}' ;
+ok(14, $@ =~ /^DB_File::HASHINFO::FETCH - Unknown element 'fred' at/ );
+
+
+# Now check the interface to HASH
+my ($X, %h);
+ok(15, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+die "Could not tie: $!" unless $X;
+
+my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
+ $blksize,$blocks) = stat($Dfile);
+
+my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ;
+
+ok(16, ($mode & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640) ||
+ $noMode{$^O} );
+
+my ($key, $value, $i);
+while (($key,$value) = each(%h)) {
+ $i++;
+}
+ok(17, !$i );
+
+$h{'goner1'} = 'snork';
+
+$h{'abc'} = 'ABC';
+ok(18, $h{'abc'} eq 'ABC' );
+ok(19, !defined $h{'jimmy'} );
+ok(20, !exists $h{'jimmy'} );
+ok(21, exists $h{'abc'} );
+
+$h{'def'} = 'DEF';
+$h{'jkl','mno'} = "JKL\034MNO";
+$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5);
+$h{'a'} = 'A';
+
+#$h{'b'} = 'B';
+$X->STORE('b', 'B') ;
+
+$h{'c'} = 'C';
+
+#$h{'d'} = 'D';
+$X->put('d', 'D') ;
+
+$h{'e'} = 'E';
+$h{'f'} = 'F';
+$h{'g'} = 'X';
+$h{'h'} = 'H';
+$h{'i'} = 'I';
+
+$h{'goner2'} = 'snork';
+delete $h{'goner2'};
+
+
+# IMPORTANT - $X must be undefined before the untie otherwise the
+# underlying DB close routine will not get called.
+undef $X ;
+untie(%h);
+
+
+# tie to the same file again, do not supply a type - should default to HASH
+ok(22, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640) );
+
+# Modify an entry from the previous tie
+$h{'g'} = 'G';
+
+$h{'j'} = 'J';
+$h{'k'} = 'K';
+$h{'l'} = 'L';
+$h{'m'} = 'M';
+$h{'n'} = 'N';
+$h{'o'} = 'O';
+$h{'p'} = 'P';
+$h{'q'} = 'Q';
+$h{'r'} = 'R';
+$h{'s'} = 'S';
+$h{'t'} = 'T';
+$h{'u'} = 'U';
+$h{'v'} = 'V';
+$h{'w'} = 'W';
+$h{'x'} = 'X';
+$h{'y'} = 'Y';
+$h{'z'} = 'Z';
+
+$h{'goner3'} = 'snork';
+
+delete $h{'goner1'};
+$X->DELETE('goner3');
+
+my @keys = keys(%h);
+my @values = values(%h);
+
+ok(23, $#keys == 29 && $#values == 29) ;
+
+$i = 0 ;
+while (($key,$value) = each(%h)) {
+ if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) {
+ $key =~ y/a-z/A-Z/;
+ $i++ if $key eq $value;
+ }
+}
+
+ok(24, $i == 30) ;
+
+@keys = ('blurfl', keys(%h), 'dyick');
+ok(25, $#keys == 31) ;
+
+$h{'foo'} = '';
+ok(26, $h{'foo'} eq '' );
+
+# Berkeley DB from version 2.4.10 to 3.0 does not allow null keys.
+# This feature was reenabled in version 3.1 of Berkeley DB.
+my $result = 0 ;
+if ($null_keys_allowed) {
+ $h{''} = 'bar';
+ $result = ( $h{''} eq 'bar' );
+}
+else
+ { $result = 1 }
+ok(27, $result) ;
+
+# check cache overflow and numeric keys and contents
+my $ok = 1;
+for ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; }
+for ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; }
+ok(28, $ok );
+
+($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
+ $blksize,$blocks) = stat($Dfile);
+ok(29, $size > 0 );
+
+@h{0..200} = 200..400;
+my @foo = @h{0..200};
+ok(30, join(':',200..400) eq join(':',@foo) );
+
+
+# Now check all the non-tie specific stuff
+
+# Check NOOVERWRITE will make put fail when attempting to overwrite
+# an existing record.
+
+my $status = $X->put( 'x', 'newvalue', R_NOOVERWRITE) ;
+ok(31, $status == 1 );
+
+# check that the value of the key 'x' has not been changed by the
+# previous test
+ok(32, $h{'x'} eq 'X' );
+
+# standard put
+$status = $X->put('key', 'value') ;
+ok(33, $status == 0 );
+
+#check that previous put can be retrieved
+$value = 0 ;
+$status = $X->get('key', $value) ;
+ok(34, $status == 0 );
+ok(35, $value eq 'value' );
+
+# Attempting to delete an existing key should work
+
+$status = $X->del('q') ;
+ok(36, $status == 0 );
+
+# Make sure that the key deleted, cannot be retrieved
+{
+ no warnings 'uninitialized' ;
+ ok(37, $h{'q'} eq undef );
+}
+
+# Attempting to delete a non-existant key should fail
+
+$status = $X->del('joe') ;
+ok(38, $status == 1 );
+
+# Check the get interface
+
+# First a non-existing key
+$status = $X->get('aaaa', $value) ;
+ok(39, $status == 1 );
+
+# Next an existing key
+$status = $X->get('a', $value) ;
+ok(40, $status == 0 );
+ok(41, $value eq 'A' );
+
+# seq
+# ###
+
+# ditto, but use put to replace the key/value pair.
+
+# use seq to walk backwards through a file - check that this reversed is
+
+# check seq FIRST/LAST
+
+# sync
+# ####
+
+$status = $X->sync ;
+ok(42, $status == 0 );
+
+
+# fd
+# ##
+
+$status = $X->fd ;
+ok(43, $status != 0 );
+
+undef $X ;
+untie %h ;
+
+unlink $Dfile;
+
+# clear
+# #####
+
+ok(44, tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+foreach (1 .. 10)
+ { $h{$_} = $_ * 100 }
+
+# check that there are 10 elements in the hash
+$i = 0 ;
+while (($key,$value) = each(%h)) {
+ $i++;
+}
+ok(45, $i == 10);
+
+# now clear the hash
+%h = () ;
+
+# check it is empty
+$i = 0 ;
+while (($key,$value) = each(%h)) {
+ $i++;
+}
+ok(46, $i == 0);
+
+untie %h ;
+unlink $Dfile ;
+
+
+# Now try an in memory file
+ok(47, $X = tie(%h, 'DB_File',undef, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+# fd with an in memory file should return fail
+$status = $X->fd ;
+ok(48, $status == -1 );
+
+undef $X ;
+untie %h ;
+
+{
+ # check ability to override the default hashing
+ my %x ;
+ my $filename = "xyz" ;
+ my $hi = new DB_File::HASHINFO ;
+ $::count = 0 ;
+ $hi->{hash} = sub { ++$::count ; length $_[0] } ;
+ ok(49, tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $hi ) ;
+ $h{"abc"} = 123 ;
+ ok(50, $h{"abc"} == 123) ;
+ untie %x ;
+ unlink $filename ;
+ ok(51, $::count >0) ;
+}
+
+{
+ # check that attempting to tie an array to a DB_HASH will fail
+
+ my $filename = "xyz" ;
+ my @x ;
+ eval { tie @x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_HASH ; } ;
+ ok(52, $@ =~ /^DB_File can only tie an associative array to a DB_HASH database/) ;
+ unlink $filename ;
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use warnings ;
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use warnings ;
+ use strict ;
+ our (@ISA, @EXPORT);
+
+ require Exporter ;
+ use DB_File;
+ @ISA=qw(DB_File);
+ @EXPORT = @DB_File::EXPORT ;
+
+ sub STORE {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::STORE($key, $value * 2) ;
+ }
+
+ sub FETCH {
+ my $self = shift ;
+ my $key = shift ;
+ $self->SUPER::FETCH($key) - 1 ;
+ }
+
+ sub put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::put($key, $value * 3) ;
+ }
+
+ sub get {
+ my $self = shift ;
+ $self->SUPER::get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE ;
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok(53, $@ eq "") ;
+ my %h ;
+ my $X ;
+ eval '
+ $X = tie(%h, "SubDB","dbhash.tmp", O_RDWR|O_CREAT, 0640, $DB_HASH );
+ ' ;
+
+ main::ok(54, $@ eq "") ;
+
+ my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
+ main::ok(55, $@ eq "") ;
+ main::ok(56, $ret == 5) ;
+
+ my $value = 0;
+ $ret = eval '$X->put("joe", 4) ; $X->get("joe", $value) ; return $value' ;
+ main::ok(57, $@ eq "") ;
+ main::ok(58, $ret == 10) ;
+
+ $ret = eval ' R_NEXT eq main::R_NEXT ' ;
+ main::ok(59, $@ eq "" ) ;
+ main::ok(60, $ret == 1) ;
+
+ $ret = eval '$X->A_new_method("joe") ' ;
+ main::ok(61, $@ eq "") ;
+ main::ok(62, $ret eq "[[11]]") ;
+
+ undef $X;
+ untie(%h);
+ unlink "SubDB.pm", "dbhash.tmp" ;
+
+}
+
+{
+ # DBM Filter tests
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ no warnings 'uninitialized';
+ my($fk, $sk, $fv, $sv) = @_ ;
+
+ print "# Fetch Key : expected '$fk' got '$fetch_key'\n"
+ if $fetch_key ne $fk ;
+ print "# Fetch Value : expected '$fv' got '$fetch_value'\n"
+ if $fetch_value ne $fv ;
+ print "# Store Key : expected '$sk' got '$store_key'\n"
+ if $store_key ne $sk ;
+ print "# Store Value : expected '$sv' got '$store_value'\n"
+ if $store_value ne $sv ;
+ print "# \$_ : expected 'original' got '$_'\n"
+ if $_ ne 'original' ;
+
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok(63, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(64, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(65, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(66, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ my ($k, $v) ;
+ $k = 'fred';
+ ok(67, ! $db->seq($k, $v, R_FIRST) ) ;
+ ok(68, $k eq "fred") ;
+ ok(69, $v eq "joe") ;
+ # fk sk fv sv
+ ok(70, checkOutput( "fred", "fred", "joe", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(71, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(72, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(73, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $k = 'Fred'; $v ='';
+ ok(74, ! $db->seq($k, $v, R_FIRST) ) ;
+ ok(75, $k eq "FRED") ;
+ ok(76, $v eq "[Jxe]") ;
+ # fk sk fv sv
+ ok(77, checkOutput( "FRED", "fred", "[Jxe]", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(78, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(79, $h{"fred"} eq "joe");
+ ok(80, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ #ok(77, $db->FIRSTKEY() eq "fred") ;
+ $k = 'fred';
+ ok(81, ! $db->seq($k, $v, R_FIRST) ) ;
+ ok(82, $k eq "fred") ;
+ ok(83, $v eq "joe") ;
+ # fk sk fv sv
+ ok(84, checkOutput( "fred", "fred", "joe", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(85, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(86, $h{"fred"} eq "joe");
+ ok(87, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $k = 'fred';
+ ok(88, ! $db->seq($k, $v, R_FIRST) ) ;
+ ok(89, $k eq "fred") ;
+ ok(90, $v eq "joe") ;
+ ok(91, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+
+ unlink $Dfile;
+ ok(92, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(93, $result{"store key"} eq "store key - 1: [fred]");
+ ok(94, $result{"store value"} eq "store value - 1: [joe]");
+ ok(95, ! defined $result{"fetch key"} );
+ ok(96, ! defined $result{"fetch value"} );
+ ok(97, $_ eq "original") ;
+
+ ok(98, $db->FIRSTKEY() eq "fred") ;
+ ok(99, $result{"store key"} eq "store key - 1: [fred]");
+ ok(100, $result{"store value"} eq "store value - 1: [joe]");
+ ok(101, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(102, ! defined $result{"fetch value"} );
+ ok(103, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(104, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(105, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(106, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(107, ! defined $result{"fetch value"} );
+ ok(108, $_ eq "original") ;
+
+ ok(109, $h{"fred"} eq "joe");
+ ok(110, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(111, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(112, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(113, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(114, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok(115, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(116, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+
+{
+ # Examples from the POD
+
+ my $file = "xyzt" ;
+ {
+ my $redirect = new Redirect $file ;
+
+ use warnings FATAL => qw(all);
+ use strict ;
+ use DB_File ;
+ our (%h, $k, $v);
+
+ unlink "fruit" ;
+ tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH
+ or die "Cannot open file 'fruit': $!\n";
+
+ # Add a few key/value pairs to the file
+ $h{"apple"} = "red" ;
+ $h{"orange"} = "orange" ;
+ $h{"banana"} = "yellow" ;
+ $h{"tomato"} = "red" ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $h{"banana"} ;
+
+ # Delete a key/value pair.
+ delete $h{"apple"} ;
+
+ # print the contents of the file
+ while (($k, $v) = each %h)
+ { print "$k -> $v\n" }
+
+ untie %h ;
+
+ unlink "fruit" ;
+ }
+
+ ok(117, docat_del($file) eq <<'EOM') ;
+Banana Exists
+
+orange -> orange
+tomato -> red
+banana -> yellow
+EOM
+
+}
+
+{
+ # Bug ID 20001013.009
+ #
+ # test that $hash{KEY} = undef doesn't produce the warning
+ # Use of uninitialized value in null operation
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my %h ;
+ my $a = "";
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ tie %h, 'DB_File', $Dfile or die "Can't open file: $!\n" ;
+ $h{ABC} = undef;
+ ok(118, $a eq "") ;
+ untie %h ;
+ unlink $Dfile;
+}
+
+{
+ # test that %hash = () doesn't produce the warning
+ # Argument "" isn't numeric in entersub
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my %h ;
+ my $a = "";
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ tie %h, 'DB_File', $Dfile or die "Can't open file: $!\n" ;
+ %h = (); ;
+ ok(119, $a eq "") ;
+ untie %h ;
+ unlink $Dfile;
+}
+
+{
+ # When iterating over a tied hash using "each", the key passed to FETCH
+ # will be recycled and passed to NEXTKEY. If a Source Filter modifies the
+ # key in FETCH via a filter_fetch_key method we need to check that the
+ # modified key doesn't get passed to NEXTKEY.
+ # Also Test "keys" & "values" while we are at it.
+
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my $bad_key = 0 ;
+ my %h = () ;
+ my $db ;
+ ok(120, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+ $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}) ;
+ $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/ ; $_ =~ s/^Alpha_/Beta_/}) ;
+
+ $h{'Alpha_ABC'} = 2 ;
+ $h{'Alpha_DEF'} = 5 ;
+
+ ok(121, $h{'Alpha_ABC'} == 2);
+ ok(122, $h{'Alpha_DEF'} == 5);
+
+ my ($k, $v) = ("","");
+ while (($k, $v) = each %h) {}
+ ok(123, $bad_key == 0);
+
+ $bad_key = 0 ;
+ foreach $k (keys %h) {}
+ ok(124, $bad_key == 0);
+
+ $bad_key = 0 ;
+ foreach $v (values %h) {}
+ ok(125, $bad_key == 0);
+
+ undef $db ;
+ untie %h ;
+ unlink $Dfile;
+}
+
+{
+ # now an error to pass 'hash' a non-code reference
+ my $dbh = new DB_File::HASHINFO ;
+
+ eval { $dbh->{hash} = 2 };
+ ok(126, $@ =~ /^Key 'hash' not associated with a code reference at/);
+
+}
+
+{
+ # recursion detection in hash
+ my %hash ;
+ unlink $Dfile;
+ my $dbh = new DB_File::HASHINFO ;
+ $dbh->{hash} = sub { $hash{3} = 4 ; length $_[0] } ;
+
+
+ my (%h);
+ ok(127, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) );
+
+ eval { $hash{1} = 2;
+ $hash{4} = 5;
+ };
+
+ ok(128, $@ =~ /^DB_File hash callback: recursion detected/);
+ {
+ no warnings;
+ untie %hash;
+ }
+ unlink $Dfile;
+}
+
+{
+ # Check that two hash's don't interact
+ my %hash1 ;
+ my %hash2 ;
+ my $h1_count = 0;
+ my $h2_count = 0;
+ unlink $Dfile, $Dfile2;
+ my $dbh1 = new DB_File::HASHINFO ;
+ $dbh1->{hash} = sub { ++ $h1_count ; length $_[0] } ;
+
+ my $dbh2 = new DB_File::HASHINFO ;
+ $dbh2->{hash} = sub { ++ $h2_count ; length $_[0] } ;
+
+
+
+ my (%h);
+ ok(129, tie(%hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh1 ) );
+ ok(130, tie(%hash2, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) );
+
+ $hash1{DEFG} = 5;
+ $hash1{XYZ} = 2;
+ $hash1{ABCDE} = 5;
+
+ $hash2{defg} = 5;
+ $hash2{xyz} = 2;
+ $hash2{abcde} = 5;
+
+ ok(131, $h1_count > 0);
+ ok(132, $h1_count == $h2_count);
+
+ ok(133, safeUntie \%hash1);
+ ok(134, safeUntie \%hash2);
+ unlink $Dfile, $Dfile2;
+}
+
+{
+ # Passing undef for flags and/or mode when calling tie could cause
+ # Use of uninitialized value in subroutine entry
+
+
+ my $warn_count = 0 ;
+ #local $SIG{__WARN__} = sub { ++ $warn_count };
+ my %hash1;
+ unlink $Dfile;
+
+ tie %hash1, 'DB_File',$Dfile, undef;
+ ok(135, $warn_count == 0);
+ $warn_count = 0;
+ tie %hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, undef;
+ ok(136, $warn_count == 0);
+ tie %hash1, 'DB_File',$Dfile, undef, undef;
+ ok(137, $warn_count == 0);
+ $warn_count = 0;
+
+ unlink $Dfile;
+}
+
+{
+ # Check that DBM Filter can cope with read-only $_
+
+ use warnings ;
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok(138, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ $db->filter_fetch_key (sub { }) ;
+ $db->filter_store_key (sub { }) ;
+ $db->filter_fetch_value (sub { }) ;
+ $db->filter_store_value (sub { }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(139, $h{"fred"} eq "joe");
+
+ eval { grep { $h{$_} } (1, 2, 3) };
+ ok (140, ! $@);
+
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ $h{"fred"} = "joe" ;
+
+ ok(141, $h{"fred"} eq "joe");
+
+ ok(142, $db->FIRSTKEY() eq "fred") ;
+
+ eval { grep { $h{$_} } (1, 2, 3) };
+ ok (143, ! $@);
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+exit ;
diff --git a/bdb/perl/DB_File/t/db-recno.t b/bdb/perl/DB_File/t/db-recno.t
new file mode 100644
index 00000000000..5390b549376
--- /dev/null
+++ b/bdb/perl/DB_File/t/db-recno.t
@@ -0,0 +1,1428 @@
+#!./perl -w
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ @INC = '../lib' if -d '../lib';
+ }
+}
+
+use warnings;
+use strict;
+use Config;
+
+BEGIN {
+ if(-d "lib" && -f "TEST") {
+ if ($Config{'extensions'} !~ /\bDB_File\b/ ) {
+ print "1..0 # Skip: DB_File was not built\n";
+ exit 0;
+ }
+ }
+}
+
+use DB_File;
+use Fcntl;
+our ($dbh, $Dfile, $bad_ones, $FA);
+
+# full tied array support started in Perl 5.004_57
+# Double check to see if it is available.
+
+{
+ sub try::TIEARRAY { bless [], "try" }
+ sub try::FETCHSIZE { $FA = 1 }
+ $FA = 0 ;
+ my @a ;
+ tie @a, 'try' ;
+ my $a = @a ;
+}
+
+
+sub ok
+{
+ my $no = shift ;
+ my $result = shift ;
+
+ print "not " unless $result ;
+ print "ok $no\n" ;
+
+ return $result ;
+}
+
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file:$!";
+ my $result = <CAT>;
+ close(CAT);
+ normalise($result) ;
+ return $result;
+}
+
+sub docat_del
+{
+ my $file = shift;
+ my $result = docat($file);
+ unlink $file ;
+ return $result;
+}
+
+sub safeUntie
+{
+ my $hashref = shift ;
+ my $no_inner = 1;
+ local $SIG{__WARN__} = sub {-- $no_inner } ;
+ untie @$hashref;
+ return $no_inner;
+}
+
+sub bad_one
+{
+ unless ($bad_ones++) {
+ print STDERR <<EOM ;
+#
+# Some older versions of Berkeley DB version 1 will fail db-recno
+# tests 61, 63 and 65.
+EOM
+ if ($^O eq 'darwin'
+ && $Config{db_version_major} == 1
+ && $Config{db_version_minor} == 0
+ && $Config{db_version_patch} == 0) {
+ print STDERR <<EOM ;
+#
+# For example Mac OS X 10.1.4 (or earlier) has such an old
+# version of Berkeley DB.
+EOM
+ }
+
+ print STDERR <<EOM ;
+#
+# You can safely ignore the errors if you're never going to use the
+# broken functionality (recno databases with a modified bval).
+# Otherwise you'll have to upgrade your DB library.
+#
+# If you want to use Berkeley DB version 1, then 1.85 and 1.86 are the
+# last versions that were released. Berkeley DB version 2 is continually
+# being updated -- Check out http://www.sleepycat.com/ for more details.
+#
+EOM
+ }
+}
+
+sub normalise
+{
+ return unless $^O eq 'cygwin' ;
+ foreach (@_)
+ { s#\r\n#\n#g }
+}
+
+BEGIN
+{
+ {
+ local $SIG{__DIE__} ;
+ eval { require Data::Dumper ; import Data::Dumper } ;
+ }
+
+ if ($@) {
+ *Dumper = sub { my $a = shift; return "[ @{ $a } ]" } ;
+ }
+}
+
+my $splice_tests = 10 + 12 + 1; # ten regressions, plus the randoms
+my $total_tests = 158 ;
+$total_tests += $splice_tests if $FA ;
+print "1..$total_tests\n";
+
+$Dfile = "recno.tmp";
+unlink $Dfile ;
+
+umask(0);
+
+# Check the interface to RECNOINFO
+
+$dbh = new DB_File::RECNOINFO ;
+ok(1, ! defined $dbh->{bval}) ;
+ok(2, ! defined $dbh->{cachesize}) ;
+ok(3, ! defined $dbh->{psize}) ;
+ok(4, ! defined $dbh->{flags}) ;
+ok(5, ! defined $dbh->{lorder}) ;
+ok(6, ! defined $dbh->{reclen}) ;
+ok(7, ! defined $dbh->{bfname}) ;
+
+$dbh->{bval} = 3000 ;
+ok(8, $dbh->{bval} == 3000 );
+
+$dbh->{cachesize} = 9000 ;
+ok(9, $dbh->{cachesize} == 9000 );
+
+$dbh->{psize} = 400 ;
+ok(10, $dbh->{psize} == 400 );
+
+$dbh->{flags} = 65 ;
+ok(11, $dbh->{flags} == 65 );
+
+$dbh->{lorder} = 123 ;
+ok(12, $dbh->{lorder} == 123 );
+
+$dbh->{reclen} = 1234 ;
+ok(13, $dbh->{reclen} == 1234 );
+
+$dbh->{bfname} = 1234 ;
+ok(14, $dbh->{bfname} == 1234 );
+
+
+# Check that an invalid entry is caught both for store & fetch
+eval '$dbh->{fred} = 1234' ;
+ok(15, $@ =~ /^DB_File::RECNOINFO::STORE - Unknown element 'fred' at/ );
+eval 'my $q = $dbh->{fred}' ;
+ok(16, $@ =~ /^DB_File::RECNOINFO::FETCH - Unknown element 'fred' at/ );
+
+# Now check the interface to RECNOINFO
+
+my $X ;
+my @h ;
+ok(17, $X = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ;
+
+my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ;
+
+ok(18, ((stat($Dfile))[2] & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640)
+ || $noMode{$^O} );
+
+#my $l = @h ;
+my $l = $X->length ;
+ok(19, ($FA ? @h == 0 : !$l) );
+
+my @data = qw( a b c d ever f g h i j k longername m n o p) ;
+
+$h[0] = shift @data ;
+ok(20, $h[0] eq 'a' );
+
+my $ i;
+foreach (@data)
+ { $h[++$i] = $_ }
+
+unshift (@data, 'a') ;
+
+ok(21, defined $h[1] );
+ok(22, ! defined $h[16] );
+ok(23, $FA ? @h == @data : $X->length == @data );
+
+
+# Overwrite an entry & check fetch it
+$h[3] = 'replaced' ;
+$data[3] = 'replaced' ;
+ok(24, $h[3] eq 'replaced' );
+
+#PUSH
+my @push_data = qw(added to the end) ;
+($FA ? push(@h, @push_data) : $X->push(@push_data)) ;
+push (@data, @push_data) ;
+ok(25, $h[++$i] eq 'added' );
+ok(26, $h[++$i] eq 'to' );
+ok(27, $h[++$i] eq 'the' );
+ok(28, $h[++$i] eq 'end' );
+
+# POP
+my $popped = pop (@data) ;
+my $value = ($FA ? pop @h : $X->pop) ;
+ok(29, $value eq $popped) ;
+
+# SHIFT
+$value = ($FA ? shift @h : $X->shift) ;
+my $shifted = shift @data ;
+ok(30, $value eq $shifted );
+
+# UNSHIFT
+
+# empty list
+($FA ? unshift @h,() : $X->unshift) ;
+ok(31, ($FA ? @h == @data : $X->length == @data ));
+
+my @new_data = qw(add this to the start of the array) ;
+$FA ? unshift (@h, @new_data) : $X->unshift (@new_data) ;
+unshift (@data, @new_data) ;
+ok(32, $FA ? @h == @data : $X->length == @data );
+ok(33, $h[0] eq "add") ;
+ok(34, $h[1] eq "this") ;
+ok(35, $h[2] eq "to") ;
+ok(36, $h[3] eq "the") ;
+ok(37, $h[4] eq "start") ;
+ok(38, $h[5] eq "of") ;
+ok(39, $h[6] eq "the") ;
+ok(40, $h[7] eq "array") ;
+ok(41, $h[8] eq $data[8]) ;
+
+# Brief test for SPLICE - more thorough 'soak test' is later.
+my @old;
+if ($FA) {
+ @old = splice(@h, 1, 2, qw(bananas just before));
+}
+else {
+ @old = $X->splice(1, 2, qw(bananas just before));
+}
+ok(42, $h[0] eq "add") ;
+ok(43, $h[1] eq "bananas") ;
+ok(44, $h[2] eq "just") ;
+ok(45, $h[3] eq "before") ;
+ok(46, $h[4] eq "the") ;
+ok(47, $h[5] eq "start") ;
+ok(48, $h[6] eq "of") ;
+ok(49, $h[7] eq "the") ;
+ok(50, $h[8] eq "array") ;
+ok(51, $h[9] eq $data[8]) ;
+$FA ? splice(@h, 1, 3, @old) : $X->splice(1, 3, @old);
+
+# Now both arrays should be identical
+
+my $ok = 1 ;
+my $j = 0 ;
+foreach (@data)
+{
+ $ok = 0, last if $_ ne $h[$j ++] ;
+}
+ok(52, $ok );
+
+# Neagtive subscripts
+
+# get the last element of the array
+ok(53, $h[-1] eq $data[-1] );
+ok(54, $h[-1] eq $h[ ($FA ? @h : $X->length) -1] );
+
+# get the first element using a negative subscript
+eval '$h[ - ( $FA ? @h : $X->length)] = "abcd"' ;
+ok(55, $@ eq "" );
+ok(56, $h[0] eq "abcd" );
+
+# now try to read before the start of the array
+eval '$h[ - (1 + ($FA ? @h : $X->length))] = 1234' ;
+ok(57, $@ =~ '^Modification of non-creatable array value attempted' );
+
+# IMPORTANT - $X must be undefined before the untie otherwise the
+# underlying DB close routine will not get called.
+undef $X ;
+ok(58, safeUntie \@h);
+
+unlink $Dfile;
+
+
+{
+ # Check bval defaults to \n
+
+ my @h = () ;
+ my $dbh = new DB_File::RECNOINFO ;
+ ok(59, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
+ $h[0] = "abc" ;
+ $h[1] = "def" ;
+ $h[3] = "ghi" ;
+ ok(60, safeUntie \@h);
+ my $x = docat($Dfile) ;
+ unlink $Dfile;
+ ok(61, $x eq "abc\ndef\n\nghi\n") ;
+}
+
+{
+ # Change bval
+
+ my @h = () ;
+ my $dbh = new DB_File::RECNOINFO ;
+ $dbh->{bval} = "-" ;
+ ok(62, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
+ $h[0] = "abc" ;
+ $h[1] = "def" ;
+ $h[3] = "ghi" ;
+ ok(63, safeUntie \@h);
+ my $x = docat($Dfile) ;
+ unlink $Dfile;
+ my $ok = ($x eq "abc-def--ghi-") ;
+ bad_one() unless $ok ;
+ ok(64, $ok) ;
+}
+
+{
+ # Check R_FIXEDLEN with default bval (space)
+
+ my @h = () ;
+ my $dbh = new DB_File::RECNOINFO ;
+ $dbh->{flags} = R_FIXEDLEN ;
+ $dbh->{reclen} = 5 ;
+ ok(65, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
+ $h[0] = "abc" ;
+ $h[1] = "def" ;
+ $h[3] = "ghi" ;
+ ok(66, safeUntie \@h);
+ my $x = docat($Dfile) ;
+ unlink $Dfile;
+ my $ok = ($x eq "abc def ghi ") ;
+ bad_one() unless $ok ;
+ ok(67, $ok) ;
+}
+
+{
+ # Check R_FIXEDLEN with user-defined bval
+
+ my @h = () ;
+ my $dbh = new DB_File::RECNOINFO ;
+ $dbh->{flags} = R_FIXEDLEN ;
+ $dbh->{bval} = "-" ;
+ $dbh->{reclen} = 5 ;
+ ok(68, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
+ $h[0] = "abc" ;
+ $h[1] = "def" ;
+ $h[3] = "ghi" ;
+ ok(69, safeUntie \@h);
+ my $x = docat($Dfile) ;
+ unlink $Dfile;
+ my $ok = ($x eq "abc--def-------ghi--") ;
+ bad_one() unless $ok ;
+ ok(70, $ok) ;
+}
+
+{
+ # check that attempting to tie an associative array to a DB_RECNO will fail
+
+ my $filename = "xyz" ;
+ my %x ;
+ eval { tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO ; } ;
+ ok(71, $@ =~ /^DB_File can only tie an array to a DB_RECNO database/) ;
+ unlink $filename ;
+}
+
+{
+ # sub-class test
+
+ package Another ;
+
+ use warnings ;
+ use strict ;
+
+ open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
+ print FILE <<'EOM' ;
+
+ package SubDB ;
+
+ use warnings ;
+ use strict ;
+ our (@ISA, @EXPORT);
+
+ require Exporter ;
+ use DB_File;
+ @ISA=qw(DB_File);
+ @EXPORT = @DB_File::EXPORT ;
+
+ sub STORE {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::STORE($key, $value * 2) ;
+ }
+
+ sub FETCH {
+ my $self = shift ;
+ my $key = shift ;
+ $self->SUPER::FETCH($key) - 1 ;
+ }
+
+ sub put {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = shift ;
+ $self->SUPER::put($key, $value * 3) ;
+ }
+
+ sub get {
+ my $self = shift ;
+ $self->SUPER::get($_[0], $_[1]) ;
+ $_[1] -= 2 ;
+ }
+
+ sub A_new_method
+ {
+ my $self = shift ;
+ my $key = shift ;
+ my $value = $self->FETCH($key) ;
+ return "[[$value]]" ;
+ }
+
+ 1 ;
+EOM
+
+ close FILE or die "Could not close: $!";
+
+ BEGIN { push @INC, '.'; }
+ eval 'use SubDB ; ';
+ main::ok(72, $@ eq "") ;
+ my @h ;
+ my $X ;
+ eval '
+ $X = tie(@h, "SubDB","recno.tmp", O_RDWR|O_CREAT, 0640, $DB_RECNO );
+ ' ;
+ die "Could not tie: $!" unless $X;
+
+ main::ok(73, $@ eq "") ;
+
+ my $ret = eval '$h[3] = 3 ; return $h[3] ' ;
+ main::ok(74, $@ eq "") ;
+ main::ok(75, $ret == 5) ;
+
+ my $value = 0;
+ $ret = eval '$X->put(1, 4) ; $X->get(1, $value) ; return $value' ;
+ main::ok(76, $@ eq "") ;
+ main::ok(77, $ret == 10) ;
+
+ $ret = eval ' R_NEXT eq main::R_NEXT ' ;
+ main::ok(78, $@ eq "" ) ;
+ main::ok(79, $ret == 1) ;
+
+ $ret = eval '$X->A_new_method(1) ' ;
+ main::ok(80, $@ eq "") ;
+ main::ok(81, $ret eq "[[11]]") ;
+
+ undef $X;
+ main::ok(82, main::safeUntie \@h);
+ unlink "SubDB.pm", "recno.tmp" ;
+
+}
+
+{
+
+ # test $#
+ my $self ;
+ unlink $Dfile;
+ ok(83, $self = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ;
+ $h[0] = "abc" ;
+ $h[1] = "def" ;
+ $h[2] = "ghi" ;
+ $h[3] = "jkl" ;
+ ok(84, $FA ? $#h == 3 : $self->length() == 4) ;
+ undef $self ;
+ ok(85, safeUntie \@h);
+ my $x = docat($Dfile) ;
+ ok(86, $x eq "abc\ndef\nghi\njkl\n") ;
+
+ # $# sets array to same length
+ ok(87, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
+ if ($FA)
+ { $#h = 3 }
+ else
+ { $self->STORESIZE(4) }
+ ok(88, $FA ? $#h == 3 : $self->length() == 4) ;
+ undef $self ;
+ ok(89, safeUntie \@h);
+ $x = docat($Dfile) ;
+ ok(90, $x eq "abc\ndef\nghi\njkl\n") ;
+
+ # $# sets array to bigger
+ ok(91, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
+ if ($FA)
+ { $#h = 6 }
+ else
+ { $self->STORESIZE(7) }
+ ok(92, $FA ? $#h == 6 : $self->length() == 7) ;
+ undef $self ;
+ ok(93, safeUntie \@h);
+ $x = docat($Dfile) ;
+ ok(94, $x eq "abc\ndef\nghi\njkl\n\n\n\n") ;
+
+ # $# sets array smaller
+ ok(95, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
+ if ($FA)
+ { $#h = 2 }
+ else
+ { $self->STORESIZE(3) }
+ ok(96, $FA ? $#h == 2 : $self->length() == 3) ;
+ undef $self ;
+ ok(97, safeUntie \@h);
+ $x = docat($Dfile) ;
+ ok(98, $x eq "abc\ndef\nghi\n") ;
+
+ unlink $Dfile;
+
+
+}
+
+{
+ # DBM Filter tests
+ use warnings ;
+ use strict ;
+ my (@h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+
+ print "# Fetch Key : expected '$fk' got '$fetch_key'\n"
+ if $fetch_key ne $fk ;
+ print "# Fetch Value : expected '$fv' got '$fetch_value'\n"
+ if $fetch_value ne $fv ;
+ print "# Store Key : expected '$sk' got '$store_key'\n"
+ if $store_key ne $sk ;
+ print "# Store Value : expected '$sv' got '$store_value'\n"
+ if $store_value ne $sv ;
+ print "# \$_ : expected 'original' got '$_'\n"
+ if $_ ne 'original' ;
+
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok(99, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h[0] = "joe" ;
+ # fk sk fv sv
+ ok(100, checkOutput( "", 0, "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(101, $h[0] eq "joe");
+ # fk sk fv sv
+ ok(102, checkOutput( "", 0, "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(103, $db->FIRSTKEY() == 0) ;
+ # fk sk fv sv
+ ok(104, checkOutput( 0, "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { ++ $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ *= 2 ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h[1] = "Joe" ;
+ # fk sk fv sv
+ ok(105, checkOutput( "", 2, "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(106, $h[1] eq "[Jxe]");
+ # fk sk fv sv
+ ok(107, checkOutput( "", 2, "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(108, $db->FIRSTKEY() == 1) ;
+ # fk sk fv sv
+ ok(109, checkOutput( 1, "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h[0] = "joe" ;
+ ok(110, checkOutput( "", 0, "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(111, $h[0] eq "joe");
+ ok(112, checkOutput( "", 0, "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(113, $db->FIRSTKEY() == 0) ;
+ ok(114, checkOutput( 0, "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h[0] = "joe" ;
+ ok(115, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(116, $h[0] eq "joe");
+ ok(117, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(118, $db->FIRSTKEY() == 0) ;
+ ok(119, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ ok(120, safeUntie \@h);
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use warnings ;
+ use strict ;
+ my (@h, $db) ;
+
+ unlink $Dfile;
+ ok(121, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h[0] = "joe" ;
+ ok(122, $result{"store key"} eq "store key - 1: [0]");
+ ok(123, $result{"store value"} eq "store value - 1: [joe]");
+ ok(124, ! defined $result{"fetch key"} );
+ ok(125, ! defined $result{"fetch value"} );
+ ok(126, $_ eq "original") ;
+
+ ok(127, $db->FIRSTKEY() == 0 ) ;
+ ok(128, $result{"store key"} eq "store key - 1: [0]");
+ ok(129, $result{"store value"} eq "store value - 1: [joe]");
+ ok(130, $result{"fetch key"} eq "fetch key - 1: [0]");
+ ok(131, ! defined $result{"fetch value"} );
+ ok(132, $_ eq "original") ;
+
+ $h[7] = "john" ;
+ ok(133, $result{"store key"} eq "store key - 2: [0 7]");
+ ok(134, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(135, $result{"fetch key"} eq "fetch key - 1: [0]");
+ ok(136, ! defined $result{"fetch value"} );
+ ok(137, $_ eq "original") ;
+
+ ok(138, $h[0] eq "joe");
+ ok(139, $result{"store key"} eq "store key - 3: [0 7 0]");
+ ok(140, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(141, $result{"fetch key"} eq "fetch key - 1: [0]");
+ ok(142, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(143, $_ eq "original") ;
+
+ undef $db ;
+ ok(144, safeUntie \@h);
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use warnings ;
+ use strict ;
+ my (@h, $db) ;
+ unlink $Dfile;
+
+ ok(145, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ $db->filter_store_key (sub { $_ = $h[0] }) ;
+
+ eval '$h[1] = 1234' ;
+ ok(146, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ ok(147, safeUntie \@h);
+ unlink $Dfile;
+}
+
+
+{
+ # Examples from the POD
+
+ my $file = "xyzt" ;
+ {
+ my $redirect = new Redirect $file ;
+
+ use warnings FATAL => qw(all);
+ use strict ;
+ use DB_File ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ my $x = tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO
+ or die "Cannot open file 'text': $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ $FA ? push @h, "green", "black"
+ : $x->push("green", "black") ;
+
+ my $elements = $FA ? scalar @h : $x->length ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = $FA ? pop @h : $x->pop ;
+ print "popped $last\n" ;
+
+ $FA ? unshift @h, "white"
+ : $x->unshift("white") ;
+ my $first = $FA ? shift @h : $x->shift ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ # use a negative index
+ print "The last element is $h[-1]\n" ;
+ print "The 2nd last element is $h[-2]\n" ;
+
+ undef $x ;
+ untie @h ;
+
+ unlink $filename ;
+ }
+
+ ok(148, docat_del($file) eq <<'EOM') ;
+The array contains 5 entries
+popped black
+shifted white
+Element 1 Exists with value blue
+The last element is green
+The 2nd last element is yellow
+EOM
+
+ my $save_output = "xyzt" ;
+ {
+ my $redirect = new Redirect $save_output ;
+
+ use warnings FATAL => qw(all);
+ use strict ;
+ our (@h, $H, $file, $i);
+ use DB_File ;
+ use Fcntl ;
+
+ $file = "text" ;
+
+ unlink $file ;
+
+ $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0640, $DB_RECNO
+ or die "Cannot open file $file: $!\n" ;
+
+ # first create a text file to play with
+ $h[0] = "zero" ;
+ $h[1] = "one" ;
+ $h[2] = "two" ;
+ $h[3] = "three" ;
+ $h[4] = "four" ;
+
+
+ # Print the records in order.
+ #
+ # The length method is needed here because evaluating a tied
+ # array in a scalar context does not return the number of
+ # elements in the array.
+
+ print "\nORIGINAL\n" ;
+ foreach $i (0 .. $H->length - 1) {
+ print "$i: $h[$i]\n" ;
+ }
+
+ # use the push & pop methods
+ $a = $H->pop ;
+ $H->push("last") ;
+ print "\nThe last record was [$a]\n" ;
+
+ # and the shift & unshift methods
+ $a = $H->shift ;
+ $H->unshift("first") ;
+ print "The first record was [$a]\n" ;
+
+ # Use the API to add a new record after record 2.
+ $i = 2 ;
+ $H->put($i, "Newbie", R_IAFTER) ;
+
+ # and a new record before record 1.
+ $i = 1 ;
+ $H->put($i, "New One", R_IBEFORE) ;
+
+ # delete record 3
+ $H->del(3) ;
+
+ # now print the records in reverse order
+ print "\nREVERSE\n" ;
+ for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
+ { print "$i: $h[$i]\n" }
+
+ # same again, but use the API functions instead
+ print "\nREVERSE again\n" ;
+ my ($s, $k, $v) = (0, 0, 0) ;
+ for ($s = $H->seq($k, $v, R_LAST) ;
+ $s == 0 ;
+ $s = $H->seq($k, $v, R_PREV))
+ { print "$k: $v\n" }
+
+ undef $H ;
+ untie @h ;
+
+ unlink $file ;
+ }
+
+ ok(149, docat_del($save_output) eq <<'EOM') ;
+
+ORIGINAL
+0: zero
+1: one
+2: two
+3: three
+4: four
+
+The last record was [four]
+The first record was [zero]
+
+REVERSE
+5: last
+4: three
+3: Newbie
+2: one
+1: New One
+0: first
+
+REVERSE again
+5: last
+4: three
+3: Newbie
+2: one
+1: New One
+0: first
+EOM
+
+}
+
+{
+ # Bug ID 20001013.009
+ #
+ # test that $hash{KEY} = undef doesn't produce the warning
+ # Use of uninitialized value in null operation
+ use warnings ;
+ use strict ;
+ use DB_File ;
+
+ unlink $Dfile;
+ my @h ;
+ my $a = "";
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_RECNO
+ or die "Can't open file: $!\n" ;
+ $h[0] = undef;
+ ok(150, $a eq "") ;
+ ok(151, safeUntie \@h);
+ unlink $Dfile;
+}
+
+{
+ # test that %hash = () doesn't produce the warning
+ # Argument "" isn't numeric in entersub
+ use warnings ;
+ use strict ;
+ use DB_File ;
+ my $a = "";
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ unlink $Dfile;
+ my @h ;
+
+ tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_RECNO
+ or die "Can't open file: $!\n" ;
+ @h = (); ;
+ ok(152, $a eq "") ;
+ ok(153, safeUntie \@h);
+ unlink $Dfile;
+}
+
+{
+ # Check that DBM Filter can cope with read-only $_
+
+ use warnings ;
+ use strict ;
+ my (@h, $db) ;
+ unlink $Dfile;
+
+ ok(154, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ $db->filter_fetch_key (sub { }) ;
+ $db->filter_store_key (sub { }) ;
+ $db->filter_fetch_value (sub { }) ;
+ $db->filter_store_value (sub { }) ;
+
+ $_ = "original" ;
+
+ $h[0] = "joe" ;
+ ok(155, $h[0] eq "joe");
+
+ eval { grep { $h[$_] } (1, 2, 3) };
+ ok (156, ! $@);
+
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ $h[1] = "joe" ;
+
+ ok(157, $h[1] eq "joe");
+
+ eval { grep { $h[$_] } (1, 2, 3) };
+ ok (158, ! $@);
+
+ undef $db ;
+ untie @h;
+ unlink $Dfile;
+}
+
+# Only test splice if this is a newish version of Perl
+exit unless $FA ;
+
+# Test SPLICE
+
+{
+ # check that the splice warnings are under the same lexical control
+ # as their non-tied counterparts.
+
+ use warnings;
+ use strict;
+
+ my $a = '';
+ my @a = (1);
+ local $SIG{__WARN__} = sub {$a = $_[0]} ;
+
+ unlink $Dfile;
+ my @tied ;
+
+ tie @tied, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_RECNO
+ or die "Can't open file: $!\n" ;
+
+ # uninitialized offset
+ use warnings;
+ my $offset ;
+ $a = '';
+ splice(@a, $offset);
+ ok(159, $a =~ /^Use of uninitialized value /);
+ $a = '';
+ splice(@tied, $offset);
+ ok(160, $a =~ /^Use of uninitialized value in splice/);
+
+ no warnings 'uninitialized';
+ $a = '';
+ splice(@a, $offset);
+ ok(161, $a eq '');
+ $a = '';
+ splice(@tied, $offset);
+ ok(162, $a eq '');
+
+ # uninitialized length
+ use warnings;
+ my $length ;
+ $a = '';
+ splice(@a, 0, $length);
+ ok(163, $a =~ /^Use of uninitialized value /);
+ $a = '';
+ splice(@tied, 0, $length);
+ ok(164, $a =~ /^Use of uninitialized value in splice/);
+
+ no warnings 'uninitialized';
+ $a = '';
+ splice(@a, 0, $length);
+ ok(165, $a eq '');
+ $a = '';
+ splice(@tied, 0, $length);
+ ok(166, $a eq '');
+
+ # offset past end of array
+ use warnings;
+ $a = '';
+ splice(@a, 3);
+ my $splice_end_array = ($a =~ /^splice\(\) offset past end of array/);
+ $a = '';
+ splice(@tied, 3);
+ ok(167, !$splice_end_array || $a =~ /^splice\(\) offset past end of array/);
+
+ no warnings 'misc';
+ $a = '';
+ splice(@a, 3);
+ ok(168, $a eq '');
+ $a = '';
+ splice(@tied, 3);
+ ok(169, $a eq '');
+
+ ok(170, safeUntie \@tied);
+ unlink $Dfile;
+}
+
+#
+# These are a few regression tests: bundles of five arguments to pass
+# to test_splice(). The first four arguments correspond to those
+# given to splice(), and the last says which context to call it in
+# (scalar, list or void).
+#
+# The expected result is not needed because we get that by running
+# Perl's built-in splice().
+#
+my @tests = ([ [ 'falsely', 'dinosaur', 'remedy', 'commotion',
+ 'rarely', 'paleness' ],
+ -4, -2,
+ [ 'redoubled', 'Taylorize', 'Zoe', 'halogen' ],
+ 'void' ],
+
+ [ [ 'a' ], -2, 1, [ 'B' ], 'void' ],
+
+ [ [ 'Hartley', 'Islandia', 'assents', 'wishful' ],
+ 0, -4,
+ [ 'maids' ],
+ 'void' ],
+
+ [ [ 'visibility', 'pocketful', 'rectangles' ],
+ -10, 0,
+ [ 'garbages' ],
+ 'void' ],
+
+ [ [ 'sleeplessly' ],
+ 8, -4,
+ [ 'Margery', 'clearing', 'repercussion', 'clubs',
+ 'arise' ],
+ 'void' ],
+
+ [ [ 'chastises', 'recalculates' ],
+ 0, 0,
+ [ 'momentariness', 'mediates', 'accents', 'toils',
+ 'regaled' ],
+ 'void' ],
+
+ [ [ 'b', '' ],
+ 9, 8,
+ [ 'otrb', 'stje', 'ixrpw', 'vxfx', 'lhhf' ],
+ 'scalar' ],
+
+ [ [ 'b', '' ],
+ undef, undef,
+ [ 'otrb', 'stje', 'ixrpw', 'vxfx', 'lhhf' ],
+ 'scalar' ],
+
+ [ [ 'riheb' ], -8, undef, [], 'void' ],
+
+ [ [ 'uft', 'qnxs', '' ],
+ 6, -2,
+ [ 'znp', 'mhnkh', 'bn' ],
+ 'void' ],
+ );
+
+my $testnum = 171;
+my $failed = 0;
+require POSIX; my $tmp = POSIX::tmpnam();
+foreach my $test (@tests) {
+ my $err = test_splice(@$test);
+ if (defined $err) {
+ print STDERR "# failed: ", Dumper($test);
+ print STDERR "# error: $err\n";
+ $failed = 1;
+ ok($testnum++, 0);
+ }
+ else { ok($testnum++, 1) }
+}
+
+if ($failed) {
+ # Not worth running the random ones
+ print STDERR '# skipping ', $testnum++, "\n";
+}
+else {
+ # A thousand randomly-generated tests
+ $failed = 0;
+ srand(0);
+ foreach (0 .. 1000 - 1) {
+ my $test = rand_test();
+ my $err = test_splice(@$test);
+ if (defined $err) {
+ print STDERR "# failed: ", Dumper($test);
+ print STDERR "# error: $err\n";
+ $failed = 1;
+ print STDERR "# skipping any remaining random tests\n";
+ last;
+ }
+ }
+
+ ok($testnum++, not $failed);
+}
+
+die "testnum ($testnum) != total_tests ($total_tests) + 1"
+ if $testnum != $total_tests + 1;
+
+exit ;
+
+# Subroutines for SPLICE testing
+
+# test_splice()
+#
+# Test the new splice() against Perl's built-in one. The first four
+# parameters are those passed to splice(), except that the lists must
+# be (explicitly) passed by reference, and are not actually modified.
+# (It's just a test!) The last argument specifies the context in
+# which to call the functions: 'list', 'scalar', or 'void'.
+#
+# Returns:
+# undef, if the two splices give the same results for the given
+# arguments and context;
+#
+# an error message showing the difference, otherwise.
+#
+# Reads global variable $tmp.
+#
+sub test_splice {
+ die 'usage: test_splice(array, offset, length, list, context)' if @_ != 5;
+ my ($array, $offset, $length, $list, $context) = @_;
+ my @array = @$array;
+ my @list = @$list;
+
+ unlink $tmp;
+
+ my @h;
+ my $H = tie @h, 'DB_File', $tmp, O_CREAT|O_RDWR, 0644, $DB_RECNO
+ or die "cannot open $tmp: $!";
+
+ my $i = 0;
+ foreach ( @array ) { $h[$i++] = $_ }
+
+ return "basic DB_File sanity check failed"
+ if list_diff(\@array, \@h);
+
+ # Output from splice():
+ # Returned value (munged a bit), error msg, warnings
+ #
+ my ($s_r, $s_error, @s_warnings);
+
+ my $gather_warning = sub { push @s_warnings, $_[0] };
+ if ($context eq 'list') {
+ my @r;
+ eval {
+ local $SIG{__WARN__} = $gather_warning;
+ @r = splice @array, $offset, $length, @list;
+ };
+ $s_error = $@;
+ $s_r = \@r;
+ }
+ elsif ($context eq 'scalar') {
+ my $r;
+ eval {
+ local $SIG{__WARN__} = $gather_warning;
+ $r = splice @array, $offset, $length, @list;
+ };
+ $s_error = $@;
+ $s_r = [ $r ];
+ }
+ elsif ($context eq 'void') {
+ eval {
+ local $SIG{__WARN__} = $gather_warning;
+ splice @array, $offset, $length, @list;
+ };
+ $s_error = $@;
+ $s_r = [];
+ }
+ else {
+ die "bad context $context";
+ }
+
+ foreach ($s_error, @s_warnings) {
+ chomp;
+ s/ at \S+ line \d+\.$//;
+ }
+
+ # Now do the same for DB_File's version of splice
+ my ($ms_r, $ms_error, @ms_warnings);
+ $gather_warning = sub { push @ms_warnings, $_[0] };
+ if ($context eq 'list') {
+ my @r;
+ eval {
+ local $SIG{__WARN__} = $gather_warning;
+ @r = splice @h, $offset, $length, @list;
+ };
+ $ms_error = $@;
+ $ms_r = \@r;
+ }
+ elsif ($context eq 'scalar') {
+ my $r;
+ eval {
+ local $SIG{__WARN__} = $gather_warning;
+ $r = splice @h, $offset, $length, @list;
+ };
+ $ms_error = $@;
+ $ms_r = [ $r ];
+ }
+ elsif ($context eq 'void') {
+ eval {
+ local $SIG{__WARN__} = $gather_warning;
+ splice @h, $offset, $length, @list;
+ };
+ $ms_error = $@;
+ $ms_r = [];
+ }
+ else {
+ die "bad context $context";
+ }
+
+ foreach ($ms_error, @ms_warnings) {
+ chomp;
+ s/ at \S+ line \d+\.?.*//s;
+ }
+
+ return "different errors: '$s_error' vs '$ms_error'"
+ if $s_error ne $ms_error;
+ return('different return values: ' . Dumper($s_r) . ' vs ' . Dumper($ms_r))
+ if list_diff($s_r, $ms_r);
+ return('different changed list: ' . Dumper(\@array) . ' vs ' . Dumper(\@h))
+ if list_diff(\@array, \@h);
+
+ if ((scalar @s_warnings) != (scalar @ms_warnings)) {
+ return 'different number of warnings';
+ }
+
+ while (@s_warnings) {
+ my $sw = shift @s_warnings;
+ my $msw = shift @ms_warnings;
+
+ if (defined $sw and defined $msw) {
+ $msw =~ s/ \(.+\)$//;
+ $msw =~ s/ in splice$// if $] < 5.006;
+ if ($sw ne $msw) {
+ return "different warning: '$sw' vs '$msw'";
+ }
+ }
+ elsif (not defined $sw and not defined $msw) {
+ # Okay.
+ }
+ else {
+ return "one warning defined, another undef";
+ }
+ }
+
+ undef $H;
+ untie @h;
+
+ open(TEXT, $tmp) or die "cannot open $tmp: $!";
+ @h = <TEXT>; normalise @h; chomp @h;
+ close TEXT or die "cannot close $tmp: $!";
+ return('list is different when re-read from disk: '
+ . Dumper(\@array) . ' vs ' . Dumper(\@h))
+ if list_diff(\@array, \@h);
+
+ return undef; # success
+}
+
+
+# list_diff()
+#
+# Do two lists differ?
+#
+# Parameters:
+# reference to first list
+# reference to second list
+#
+# Returns true iff they differ. Only works for lists of (string or
+# undef).
+#
+# Surely there is a better way to do this?
+#
+sub list_diff {
+ die 'usage: list_diff(ref to first list, ref to second list)'
+ if @_ != 2;
+ my ($a, $b) = @_;
+ my @a = @$a; my @b = @$b;
+ return 1 if (scalar @a) != (scalar @b);
+ for (my $i = 0; $i < @a; $i++) {
+ my ($ae, $be) = ($a[$i], $b[$i]);
+ if (defined $ae and defined $be) {
+ return 1 if $ae ne $be;
+ }
+ elsif (not defined $ae and not defined $be) {
+ # Two undefined values are 'equal'
+ }
+ else {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+# rand_test()
+#
+# Think up a random ARRAY, OFFSET, LENGTH, LIST, and context.
+# ARRAY or LIST might be empty, and OFFSET or LENGTH might be
+# undefined. Return a 'test' - a listref of these five things.
+#
+sub rand_test {
+ die 'usage: rand_test()' if @_;
+ my @contexts = qw<list scalar void>;
+ my $context = $contexts[int(rand @contexts)];
+ return [ rand_list(),
+ (rand() < 0.5) ? (int(rand(20)) - 10) : undef,
+ (rand() < 0.5) ? (int(rand(20)) - 10) : undef,
+ rand_list(),
+ $context ];
+}
+
+
+sub rand_list {
+ die 'usage: rand_list()' if @_;
+ my @r;
+
+ while (rand() > 0.1 * (scalar @r + 1)) {
+ push @r, rand_word();
+ }
+ return \@r;
+}
+
+
+sub rand_word {
+ die 'usage: rand_word()' if @_;
+ my $r = '';
+ my @chars = qw<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>;
+ while (rand() > 0.1 * (length($r) + 1)) {
+ $r .= $chars[int(rand(scalar @chars))];
+ }
+ return $r;
+}
+
+
diff --git a/bdb/perl/DB_File/typemap b/bdb/perl/DB_File/typemap
new file mode 100644
index 00000000000..8ad7b1282dc
--- /dev/null
+++ b/bdb/perl/DB_File/typemap
@@ -0,0 +1,46 @@
+# typemap for Perl 5 interface to Berkeley
+#
+# written by Paul Marquess <Paul.Marquess@btinternet.com>
+# last modified 10th December 2000
+# version 1.74
+#
+#################################### DB SECTION
+#
+#
+
+u_int T_U_INT
+DB_File T_PTROBJ
+DBT T_dbtdatum
+DBTKEY T_dbtkeydatum
+
+INPUT
+T_dbtkeydatum
+ DBM_ckFilter($arg, filter_store_key, \"filter_store_key\");
+ DBT_clear($var) ;
+ if (SvOK($arg)){
+ if (db->type != DB_RECNO) {
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ }
+ else {
+ Value = GetRecnoKey(aTHX_ db, SvIV($arg)) ;
+ $var.data = & Value;
+ $var.size = (int)sizeof(recno_t);
+ }
+ }
+T_dbtdatum
+ DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
+ DBT_clear($var) ;
+ if (SvOK($arg)) {
+ $var.data = SvPV($arg, PL_na);
+ $var.size = (int)PL_na;
+ }
+
+OUTPUT
+
+T_dbtkeydatum
+ OutputKey($arg, $var)
+T_dbtdatum
+ OutputValue($arg, $var)
+T_PTROBJ
+ sv_setref_pv($arg, dbtype, (void*)$var);
diff --git a/bdb/perl/DB_File/version.c b/bdb/perl/DB_File/version.c
new file mode 100644
index 00000000000..03b17c18e60
--- /dev/null
+++ b/bdb/perl/DB_File/version.c
@@ -0,0 +1,82 @@
+/*
+
+ version.c -- Perl 5 interface to Berkeley DB
+
+ written by Paul Marquess <Paul.Marquess@btinternet.com>
+ last modified 2nd Jan 2002
+ version 1.802
+
+ All comments/suggestions/problems are welcome
+
+ Copyright (c) 1995-2002 Paul Marquess. All rights reserved.
+ This program is free software; you can redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+ Changes:
+ 1.71 - Support for Berkeley DB version 3.
+ Support for Berkeley DB 2/3's backward compatability mode.
+ 1.72 - No change.
+ 1.73 - Added support for threading
+ 1.74 - Added Perl core patch 7801.
+
+
+*/
+
+#define PERL_NO_GET_CONTEXT
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include <db.h>
+
+void
+#ifdef CAN_PROTOTYPE
+__getBerkeleyDBInfo(void)
+#else
+__getBerkeleyDBInfo()
+#endif
+{
+#ifdef dTHX
+ dTHX;
+#endif
+ SV * version_sv = perl_get_sv("DB_File::db_version", GV_ADD|GV_ADDMULTI) ;
+ SV * ver_sv = perl_get_sv("DB_File::db_ver", GV_ADD|GV_ADDMULTI) ;
+ SV * compat_sv = perl_get_sv("DB_File::db_185_compat", GV_ADD|GV_ADDMULTI) ;
+
+#ifdef DB_VERSION_MAJOR
+ int Major, Minor, Patch ;
+
+ (void)db_version(&Major, &Minor, &Patch) ;
+
+ /* Check that the versions of db.h and libdb.a are the same */
+ if (Major != DB_VERSION_MAJOR || Minor != DB_VERSION_MINOR
+ || Patch != DB_VERSION_PATCH)
+ croak("\nDB_File needs compatible versions of libdb & db.h\n\tyou have db.h version %d.%d.%d and libdb version %d.%d.%d\n",
+ DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
+ Major, Minor, Patch) ;
+
+ /* check that libdb is recent enough -- we need 2.3.4 or greater */
+ if (Major == 2 && (Minor < 3 || (Minor == 3 && Patch < 4)))
+ croak("DB_File needs Berkeley DB 2.3.4 or greater, you have %d.%d.%d\n",
+ Major, Minor, Patch) ;
+
+ {
+ char buffer[40] ;
+ sprintf(buffer, "%d.%d", Major, Minor) ;
+ sv_setpv(version_sv, buffer) ;
+ sprintf(buffer, "%d.%03d%03d", Major, Minor, Patch) ;
+ sv_setpv(ver_sv, buffer) ;
+ }
+
+#else /* ! DB_VERSION_MAJOR */
+ sv_setiv(version_sv, 1) ;
+ sv_setiv(ver_sv, 1) ;
+#endif /* ! DB_VERSION_MAJOR */
+
+#ifdef COMPAT185
+ sv_setiv(compat_sv, 1) ;
+#else /* ! COMPAT185 */
+ sv_setiv(compat_sv, 0) ;
+#endif /* ! COMPAT185 */
+
+}
diff --git a/bdb/qam/qam.c b/bdb/qam/qam.c
index 0c9f453044f..b10f8743439 100644
--- a/bdb/qam/qam.c
+++ b/bdb/qam/qam.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam.c,v 11.72 2001/01/16 20:10:55 ubell Exp $";
+static const char revid[] = "$Id: qam.c,v 11.134 2002/08/13 20:46:08 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,20 +18,20 @@ static const char revid[] = "$Id: qam.c,v 11.72 2001/01/16 20:10:55 ubell Exp $"
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "db_am.h"
-#include "mp.h"
-#include "lock.h"
-#include "log.h"
-#include "btree.h"
-#include "qam.h"
-
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
+
+static int __qam_bulk __P((DBC *, DBT *, u_int32_t));
static int __qam_c_close __P((DBC *, db_pgno_t, int *));
static int __qam_c_del __P((DBC *));
static int __qam_c_destroy __P((DBC *));
static int __qam_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __qam_c_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
+static int __qam_consume __P((DBC *, QMETA *, db_recno_t));
static int __qam_getno __P((DB *, const DBT *, db_recno_t *));
/*
@@ -61,17 +61,16 @@ __qam_position(dbc, recnop, mode, exactp)
pg = QAM_RECNO_PAGE(dbp, *recnop);
if ((ret = __db_lget(dbc, 0, pg, mode == QAM_READ ?
- DB_LOCK_READ : DB_LOCK_WRITE, 0, &cp->lock)) != 0)
+ DB_LOCK_READ : DB_LOCK_WRITE, 0, &cp->lock)) != 0)
return (ret);
cp->page = NULL;
*exactp = 0;
if ((ret = __qam_fget(dbp, &pg,
- mode == QAM_WRITE ? DB_MPOOL_CREATE : 0,
- &cp->page)) != 0) {
+ mode == QAM_WRITE ? DB_MPOOL_CREATE : 0, &cp->page)) != 0) {
/* We did not fetch it, we can release the lock. */
(void)__LPUT(dbc, cp->lock);
- cp->lock.off = LOCK_INVALID;
- if (mode != QAM_WRITE && (ret == EINVAL || ret == ENOENT))
+ if (mode != QAM_WRITE &&
+ (ret == DB_PAGE_NOTFOUND || ret == ENOENT))
return (0);
return (ret);
}
@@ -88,7 +87,7 @@ __qam_position(dbc, recnop, mode, exactp)
}
qp = QAM_GET_RECORD(dbp, cp->page, cp->indx);
- *exactp = F_ISSET(qp, QAM_VALID);
+ *exactp = F_ISSET(qp, QAM_VALID) ? 1 : 0;
return (ret);
}
@@ -116,9 +115,9 @@ __qam_pitem(dbc, pagep, indx, recno, data)
DBT olddata, pdata, *datap;
QAMDATA *qp;
QUEUE *t;
- u_int32_t size;
+ u_int32_t alloced;
u_int8_t *dest, *p;
- int alloced, ret;
+ int ret;
alloced = ret = 0;
@@ -131,7 +130,6 @@ __qam_pitem(dbc, pagep, indx, recno, data)
qp = QAM_GET_RECORD(dbp, pagep, indx);
p = qp->data;
- size = data->size;
datap = data;
if (F_ISSET(data, DB_DBT_PARTIAL)) {
if (data->doff + data->dlen > t->re_len) {
@@ -159,12 +157,12 @@ len_err: __db_err(dbp->dbenv,
* to log so that both this and the recovery code is simpler.
*/
- if (DB_LOGGING(dbc) || !F_ISSET(qp, QAM_VALID)) {
+ if (DBC_LOGGING(dbc) || !F_ISSET(qp, QAM_VALID)) {
datap = &pdata;
memset(datap, 0, sizeof(*datap));
if ((ret = __os_malloc(dbp->dbenv,
- t->re_len, NULL, &datap->data)) != 0)
+ t->re_len, &datap->data)) != 0)
return (ret);
alloced = 1;
datap->size = t->re_len;
@@ -188,14 +186,14 @@ len_err: __db_err(dbp->dbenv,
}
no_partial:
- if (DB_LOGGING(dbc)) {
+ if (DBC_LOGGING(dbc)) {
olddata.size = 0;
if (F_ISSET(qp, QAM_SET)) {
olddata.data = qp->data;
olddata.size = t->re_len;
}
- if ((ret = __qam_add_log(dbp->dbenv, dbc->txn, &LSN(pagep),
- 0, dbp->log_fileid, &LSN(pagep), pagep->pgno,
+ if ((ret = __qam_add_log(dbp, dbc->txn, &LSN(pagep),
+ 0, &LSN(pagep), pagep->pgno,
indx, recno, datap, qp->flags,
olddata.size == 0 ? NULL : &olddata)) != 0)
goto err;
@@ -207,7 +205,7 @@ no_partial:
memset(p + datap->size, t->re_pad, t->re_len - datap->size);
err: if (alloced)
- __os_free(datap->data, t->re_len);
+ __os_free(dbp->dbenv, datap->data);
return (ret);
}
@@ -223,23 +221,37 @@ __qam_c_put(dbc, key, data, flags, pgnop)
u_int32_t flags;
db_pgno_t *pgnop;
{
- QUEUE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
QMETA *meta;
+ QUEUE_CURSOR *cp;
db_pgno_t pg;
db_recno_t new_cur, new_first;
u_int32_t opcode;
int exact, ret, t_ret;
- COMPQUIET(key, NULL);
-
dbp = dbc->dbp;
+ mpf = dbp->mpf;
if (pgnop != NULL)
*pgnop = PGNO_INVALID;
cp = (QUEUE_CURSOR *)dbc->internal;
+ switch (flags) {
+ case DB_KEYFIRST:
+ case DB_KEYLAST:
+ if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0)
+ return (ret);
+ /* FALLTHROUGH */
+ case DB_CURRENT:
+ break;
+ default:
+ /* The interface shouldn't let anything else through. */
+ DB_ASSERT(0);
+ return (__db_ferr(dbp->dbenv, "__qam_c_put", flags));
+ }
+
/* Write lock the record. */
if ((ret = __db_lget(dbc,
0, cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0)
@@ -252,29 +264,14 @@ __qam_c_put(dbc, key, data, flags, pgnop)
return (ret);
}
- if (exact && flags == DB_NOOVERWRITE) {
- ret = __TLPUT(dbc, lock);
- /* Doing record locking, release the page lock */
- if ((t_ret = __LPUT(dbc, cp->lock)) == 0)
- cp->lock.off = LOCK_INVALID;
- else
- if (ret == 0)
- ret = t_ret;
- if ((t_ret =
- __qam_fput(dbp, cp->pgno, cp->page, 0)) != 0 && ret == 0)
- ret = t_ret;
- cp->page = NULL;
- return (ret == 0 ? DB_KEYEXIST : ret);
- }
-
/* Put the item on the page. */
ret = __qam_pitem(dbc, (QPAGE *)cp->page, cp->indx, cp->recno, data);
/* Doing record locking, release the page lock */
if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0)
ret = t_ret;
- if ((t_ret =
- __qam_fput(dbp, cp->pgno, cp->page, DB_MPOOL_DIRTY)) && ret == 0)
+ if ((t_ret = __qam_fput(
+ dbp, cp->pgno, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
cp->page = NULL;
cp->lock = lock;
@@ -284,11 +281,15 @@ __qam_c_put(dbc, key, data, flags, pgnop)
/* We may need to reset the head or tail of the queue. */
pg = ((QUEUE *)dbp->q_internal)->q_meta;
- if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0)
+
+ /*
+ * Get the meta page first, we don't want to write lock it while
+ * trying to pin it.
+ */
+ if ((ret = mpf->get(mpf, &pg, 0, &meta)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &meta)) != 0) {
- /* We did not fetch it, we can release the lock. */
- (void)__LPUT(dbc, lock);
+ if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0) {
+ (void)mpf->put(mpf, meta, 0);
return (ret);
}
@@ -313,7 +314,8 @@ __qam_c_put(dbc, key, data, flags, pgnop)
} else {
if (QAM_BEFORE_FIRST(meta, cp->recno) &&
(meta->first_recno <= meta->cur_recno ||
- meta->first_recno - cp->recno < cp->recno - meta->cur_recno)) {
+ meta->first_recno - cp->recno <
+ cp->recno - meta->cur_recno)) {
new_first = cp->recno;
opcode |= QAM_SETFIRST;
}
@@ -321,7 +323,8 @@ __qam_c_put(dbc, key, data, flags, pgnop)
if (meta->cur_recno == cp->recno ||
(QAM_AFTER_CURRENT(meta, cp->recno) &&
(meta->first_recno <= meta->cur_recno ||
- cp->recno - meta->cur_recno <= meta->first_recno - cp->recno))) {
+ cp->recno - meta->cur_recno <=
+ meta->first_recno - cp->recno))) {
new_cur = cp->recno + 1;
if (new_cur == RECNO_OOB)
new_cur++;
@@ -329,10 +332,12 @@ __qam_c_put(dbc, key, data, flags, pgnop)
}
}
- if (opcode != 0 && DB_LOGGING(dbc)) {
- ret = __qam_mvptr_log(dbp->dbenv, dbc->txn, &meta->dbmeta.lsn,
- 0, opcode, dbp->log_fileid, meta->first_recno, new_first,
- meta->cur_recno, new_cur, &meta->dbmeta.lsn);
+ if (opcode != 0 && DBC_LOGGING(dbc)) {
+ ret = __qam_mvptr_log(dbp, dbc->txn, &meta->dbmeta.lsn,
+ 0, opcode, meta->first_recno, new_first,
+ meta->cur_recno, new_cur, &meta->dbmeta.lsn, PGNO_BASE_MD);
+ if (ret != 0)
+ opcode = 0;
}
if (opcode & QAM_SETCUR)
@@ -340,9 +345,8 @@ __qam_c_put(dbc, key, data, flags, pgnop)
if (opcode & QAM_SETFIRST)
meta->first_recno = new_first;
- if ((t_ret =
- memp_fput(dbp->mpf, meta, opcode != 0 ? DB_MPOOL_DIRTY : 0)) != 0 &&
- ret == 0)
+ if ((t_ret = mpf->put(
+ mpf, meta, opcode != 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
ret = t_ret;
/* Don't hold the meta page long term. */
@@ -352,70 +356,42 @@ __qam_c_put(dbc, key, data, flags, pgnop)
}
/*
- * __qam_put --
- * Add a record to the queue.
- * If we are doing anything but appending, just call qam_c_put to do the
- * work. Otherwise we fast path things here.
+ * __qam_append --
+ * Perform a put(DB_APPEND) in queue.
*
- * PUBLIC: int __qam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ * PUBLIC: int __qam_append __P((DBC *, DBT *, DBT *));
*/
int
-__qam_put(dbp, txn, key, data, flags)
- DB *dbp;
- DB_TXN *txn;
+__qam_append(dbc, key, data)
+ DBC *dbc;
DBT *key, *data;
- u_int32_t flags;
{
- QUEUE_CURSOR *cp;
- DBC *dbc;
+ DB *dbp;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
QMETA *meta;
QPAGE *page;
QUEUE *qp;
+ QUEUE_CURSOR *cp;
db_pgno_t pg;
db_recno_t recno;
int ret, t_ret;
- PANIC_CHECK(dbp->dbenv);
- DB_CHECK_TXN(dbp, txn);
-
- /* Allocate a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
-
- DEBUG_LWRITE(dbc, dbc->txn, "qam_put", key, data, flags);
-
+ dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (QUEUE_CURSOR *)dbc->internal;
- /* Check for invalid flags. */
- if ((ret = __db_putchk(dbp,
- key, data, flags, F_ISSET(dbp, DB_AM_RDONLY), 0)) != 0)
- goto done;
-
- /* If not appending, then just call the cursor routine */
- if (flags != DB_APPEND) {
- if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0)
- goto done;
-
- ret = __qam_c_put(dbc, NULL, data, flags, NULL);
- goto done;
- }
-
- /* Write lock the meta page. */
pg = ((QUEUE *)dbp->q_internal)->q_meta;
- if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0)
- goto done;
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &meta)) != 0) {
- /* We did not fetch it, we can release the lock. */
- (void)__LPUT(dbc, lock);
- goto done;
- }
-
- /* Record that we are going to allocate a record. */
- if (DB_LOGGING(dbc)) {
- __qam_inc_log(dbp->dbenv,
- dbc->txn, &meta->dbmeta.lsn,
- 0, dbp->log_fileid, &meta->dbmeta.lsn);
+ /*
+ * Get the meta page first, we don't want to write lock it while
+ * trying to pin it.
+ */
+ if ((ret = mpf->get(mpf, &pg, 0, &meta)) != 0)
+ return (ret);
+ /* Write lock the meta page. */
+ if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0) {
+ (void)mpf->put(mpf, meta, 0);
+ return (ret);
}
/* Get the next record number. */
@@ -436,15 +412,17 @@ __qam_put(dbp, txn, key, data, flags)
meta->first_recno = recno;
/* Lock the record and release meta page lock. */
- if ((ret = __db_lget(dbc,
- 1, recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0)
+ if ((ret = __db_lget(dbc, LCK_COUPLE_ALWAYS,
+ recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0) {
+ (void)__LPUT(dbc, lock);
goto err;
+ }
/*
* The application may modify the data based on the selected record
* number.
*/
- if (flags == DB_APPEND && dbc->dbp->db_append_recno != NULL &&
+ if (dbc->dbp->db_append_recno != NULL &&
(ret = dbc->dbp->db_append_recno(dbc->dbp, data, recno)) != 0) {
(void)__LPUT(dbc, lock);
goto err;
@@ -484,16 +462,20 @@ __qam_put(dbp, txn, key, data, flags)
/* Return the record number to the user. */
if (ret == 0)
- ret = __db_retcopy(dbp, key,
- &recno, sizeof(recno), &dbc->rkey.data, &dbc->rkey.ulen);
+ ret = __db_retcopy(dbp->dbenv, key,
+ &recno, sizeof(recno), &dbc->rkey->data, &dbc->rkey->ulen);
+
+ /* Position the cursor on this record. */
+ cp->recno = recno;
/* See if we are leaving the extent. */
qp = (QUEUE *) dbp->q_internal;
- if (qp->page_ext != 0
- && (recno % (qp->page_ext * qp->rec_page) == 0
- || recno == UINT32_T_MAX)) {
- if ((ret =
- __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0)
+ if (qp->page_ext != 0 &&
+ (recno % (qp->page_ext * qp->rec_page) == 0 ||
+ recno == UINT32_T_MAX)) {
+ if ((ret = __db_lget(dbc,
+ 0, ((QUEUE *)dbp->q_internal)->q_meta,
+ DB_LOCK_WRITE, 0, &lock)) != 0)
goto err;
if (!QAM_AFTER_CURRENT(meta, recno))
ret = __qam_fclose(dbp, pg);
@@ -502,13 +484,7 @@ __qam_put(dbp, txn, key, data, flags)
err:
/* Release the meta page. */
- if ((t_ret
- = memp_fput(dbp->mpf, meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
- ret = t_ret;
-
-done:
- /* Discard the cursor. */
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ if ((t_ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
return (ret);
@@ -522,50 +498,57 @@ static int
__qam_c_del(dbc)
DBC *dbc;
{
- QUEUE_CURSOR *cp;
DB *dbp;
DBT data;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
PAGE *pagep;
QAMDATA *qp;
QMETA *meta;
+ QUEUE_CURSOR *cp;
db_pgno_t pg;
+ db_recno_t first;
int exact, ret, t_ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
cp = (QUEUE_CURSOR *)dbc->internal;
pg = ((QUEUE *)dbp->q_internal)->q_meta;
- if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_READ, 0, &lock)) != 0)
+ /*
+ * Get the meta page first, we don't want to write lock it while
+ * trying to pin it.
+ */
+ if ((ret = mpf->get(mpf, &pg, 0, &meta)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf, &pg, 0, &meta)) != 0) {
- /* We did not fetch it, we can release the lock. */
- (void)__LPUT(dbc, lock);
+ /* Write lock the meta page. */
+ if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_READ, 0, &lock)) != 0) {
+ (void)mpf->put(mpf, meta, 0);
return (ret);
}
if (QAM_NOT_VALID(meta, cp->recno))
ret = DB_NOTFOUND;
+ first = meta->first_recno;
+
/* Don't hold the meta page long term. */
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
- if ((t_ret = memp_fput(dbp->mpf, meta, 0)) != 0 && ret == 0)
- ret = t_ret;
if (ret != 0)
- return (ret);
+ goto err1;
if ((ret = __db_lget(dbc,
0, cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0)
- return (ret);
+ goto err1;
cp->lock_mode = DB_LOCK_WRITE;
/* Find the record ; delete only deletes exact matches. */
if ((ret = __qam_position(dbc,
&cp->recno, QAM_WRITE, &exact)) != 0) {
cp->lock = lock;
- return (ret);
+ goto err1;
}
if (!exact) {
ret = DB_NOTFOUND;
@@ -575,21 +558,18 @@ __qam_c_del(dbc)
pagep = cp->page;
qp = QAM_GET_RECORD(dbp, pagep, cp->indx);
- if (DB_LOGGING(dbc)) {
- if (((QUEUE *)dbp->q_internal)->page_ext == 0
- || ((QUEUE *)dbp->q_internal)->re_len == 0) {
- if ((ret =
- __qam_del_log(dbp->dbenv,
- dbc->txn, &LSN(pagep), 0,
- dbp->log_fileid, &LSN(pagep),
+ if (DBC_LOGGING(dbc)) {
+ if (((QUEUE *)dbp->q_internal)->page_ext == 0 ||
+ ((QUEUE *)dbp->q_internal)->re_len == 0) {
+ if ((ret = __qam_del_log(dbp,
+ dbc->txn, &LSN(pagep), 0, &LSN(pagep),
pagep->pgno, cp->indx, cp->recno)) != 0)
goto err1;
} else {
data.size = ((QUEUE *)dbp->q_internal)->re_len;
data.data = qp->data;
- if ((ret =
- __qam_delext_log(dbp->dbenv, dbc->txn,
- &LSN(pagep), 0, dbp->log_fileid, &LSN(pagep),
+ if ((ret = __qam_delext_log(dbp,
+ dbc->txn, &LSN(pagep), 0, &LSN(pagep),
pagep->pgno, cp->indx, cp->recno, &data)) != 0)
goto err1;
}
@@ -597,60 +577,28 @@ __qam_c_del(dbc)
F_CLR(qp, QAM_VALID);
-err1:
- if ((t_ret = __qam_fput(
- dbp, cp->pgno, cp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0)
- return (ret ? ret : t_ret);
- cp->page = NULL;
- /* Doing record locking, release the page lock */
- if ((t_ret = __LPUT(dbc, cp->lock)) != 0) {
- cp->lock = lock;
- return (ret ? ret : t_ret);
+ if (cp->recno == first) {
+ pg = ((QUEUE *)dbp->q_internal)->q_meta;
+ if ((ret =
+ __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0)
+ goto err1;
+ ret = __qam_consume(dbc, meta, first);
+ if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+ ret = t_ret;
}
- cp->lock = lock;
- return (ret);
-}
-/*
- * __qam_delete --
- * Queue db->del function.
- *
- * PUBLIC: int __qam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
- */
-int
-__qam_delete(dbp, txn, key, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- u_int32_t flags;
-{
- QUEUE_CURSOR *cp;
- DBC *dbc;
- int ret, t_ret;
-
- PANIC_CHECK(dbp->dbenv);
- DB_CHECK_TXN(dbp, txn);
-
- /* Check for invalid flags. */
- if ((ret =
- __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
- return (ret);
-
- /* Acquire a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
-
- DEBUG_LWRITE(dbc, txn, "qam_delete", key, NULL, flags);
-
- cp = (QUEUE_CURSOR *)dbc->internal;
- if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0)
- goto err;
-
- ret = __qam_c_del(dbc);
+err1:
+ if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (cp->page != NULL && (t_ret = __qam_fput(dbp, cp->pgno,
+ cp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
+ ret = t_ret;
+ cp->page = NULL;
- /* Release the cursor. */
-err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ /* Doing record locking, release the page lock */
+ if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0)
ret = t_ret;
+ cp->lock = lock;
return (ret);
}
@@ -671,39 +619,40 @@ __qam_c_get(dbc, key, data, flags, pgnop)
db_pgno_t *pgnop;
{
DB *dbp;
- DB_LOCK lock, pglock, metalock, save_lock;
+ DBC *dbcdup;
DBT tmp;
+ DB_ENV *dbenv;
+ DB_LOCK lock, pglock, metalock;
+ DB_MPOOLFILE *mpf;
PAGE *pg;
QAMDATA *qp;
QMETA *meta;
QUEUE *t;
QUEUE_CURSOR *cp;
- db_indx_t save_indx;
db_lockmode_t lock_mode;
- db_pgno_t metapno, save_page;
- db_recno_t current, first, save_recno;
+ db_pgno_t metapno;
+ db_recno_t first;
qam_position_mode mode;
- u_int32_t rec_extent;
int exact, is_first, locked, ret, t_ret, wait, with_delete;
- int put_mode, meta_dirty, retrying, skip_again, wrapped;
+ int put_mode, meta_dirty, retrying;
- cp = (QUEUE_CURSOR *)dbc->internal;
dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ cp = (QUEUE_CURSOR *)dbc->internal;
- PANIC_CHECK(dbp->dbenv);
+ PANIC_CHECK(dbenv);
wait = 0;
with_delete = 0;
retrying = 0;
- rec_extent = 0;
lock_mode = DB_LOCK_READ;
- mode = QAM_READ;
put_mode = 0;
t_ret = 0;
*pgnop = 0;
pg = NULL;
- skip_again = 0;
+ mode = QAM_READ;
if (F_ISSET(dbc, DBC_RMW)) {
lock_mode = DB_LOCK_WRITE;
mode = QAM_WRITE;
@@ -714,7 +663,9 @@ __qam_c_get(dbc, key, data, flags, pgnop)
flags = DB_CONSUME;
}
if (flags == DB_CONSUME) {
- DB_CHECK_TXN(dbp, dbc->txn);
+ if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
+ return (ret);
+
with_delete = 1;
flags = DB_FIRST;
lock_mode = DB_LOCK_WRITE;
@@ -724,30 +675,30 @@ __qam_c_get(dbc, key, data, flags, pgnop)
DEBUG_LREAD(dbc, dbc->txn, "qam_c_get",
flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
+ /* Make lint and friends happy. */
+ meta_dirty = 0;
+ locked = 0;
+
is_first = 0;
t = (QUEUE *)dbp->q_internal;
- /* get the meta page */
metapno = t->q_meta;
- if ((ret = __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0)
+
+ /*
+ * Get the meta page first, we don't want to write lock it while
+ * trying to pin it. This is because someone my have it pinned
+ * but not locked.
+ */
+ if ((ret = mpf->get(mpf, &metapno, 0, &meta)) != 0)
return (ret);
+ if ((ret = __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0)
+ goto err;
locked = 1;
- if ((ret = memp_fget(dbp->mpf, &metapno, 0, &meta)) != 0) {
- /* We did not fetch it, we can release the lock. */
- (void)__LPUT(dbc, metalock);
- return (ret);
- }
first = 0;
- /* Make lint and friends happy. */
- meta_dirty = 0;
-
/* Release any previous lock if not in a transaction. */
- if (cp->lock.off != LOCK_INVALID) {
- (void)__TLPUT(dbc, cp->lock);
- cp->lock.off = LOCK_INVALID;
- }
+ (void)__TLPUT(dbc, cp->lock);
retry: /* Update the record number. */
switch (flags) {
@@ -778,8 +729,8 @@ retry: /* Update the record number. */
case DB_PREV:
case DB_PREV_NODUP:
if (cp->recno != RECNO_OOB) {
- if (QAM_BEFORE_FIRST(meta, cp->recno)
- || cp->recno == meta->first_recno) {
+ if (QAM_BEFORE_FIRST(meta, cp->recno) ||
+ cp->recno == meta->first_recno) {
ret = DB_NOTFOUND;
goto err;
}
@@ -799,14 +750,15 @@ retry: /* Update the record number. */
if (cp->recno == RECNO_OOB)
cp->recno--;
break;
- case DB_GET_BOTH:
case DB_SET:
case DB_SET_RANGE:
+ case DB_GET_BOTH:
+ case DB_GET_BOTH_RANGE:
if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0)
goto err;
break;
default:
- ret = __db_unknown_flag(dbp->dbenv, "__qam_c_get", flags);
+ ret = __db_unknown_flag(dbenv, "__qam_c_get", flags);
goto err;
}
@@ -830,14 +782,16 @@ retry: /* Update the record number. */
retrying = 1;
goto retry;
}
- if (CDB_LOCKING(dbp->dbenv)) {
- if ((ret = lock_get(dbp->dbenv, dbc->locker,
+ if (CDB_LOCKING(dbenv)) {
+ if ((ret = dbenv->lock_get(
+ dbenv, dbc->locker,
DB_LOCK_SWITCH, &dbc->lock_dbt,
DB_LOCK_WAIT, &dbc->mylock)) != 0)
goto err;
- if ((ret = lock_get(dbp->dbenv, dbc->locker,
- DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE,
- &dbc->mylock)) != 0)
+ if ((ret = dbenv->lock_get(
+ dbenv, dbc->locker,
+ DB_LOCK_UPGRADE, &dbc->lock_dbt,
+ DB_LOCK_WRITE, &dbc->mylock)) != 0)
goto err;
goto retry;
}
@@ -859,7 +813,7 @@ retry: /* Update the record number. */
if ((ret = __db_lget(dbc, 0, metapno,
DB_LOCK_WAIT, DB_LOCK_SWITCH, &metalock)) != 0)
goto err;
- if ((ret = lock_get(dbp->dbenv, dbc->locker,
+ if ((ret = dbenv->lock_get(dbenv, dbc->locker,
DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE,
&metalock)) != 0)
goto err;
@@ -883,11 +837,15 @@ retry: /* Update the record number. */
DB_LOCK_NOWAIT | DB_LOCK_RECORD : DB_LOCK_RECORD,
&lock)) == DB_LOCK_NOTGRANTED && with_delete) {
#ifdef QDEBUG
- __db_logmsg(dbp->dbenv,
+ __db_logmsg(dbenv,
dbc->txn, "Queue S", 0, "%x %d %d %d",
dbc->locker, cp->recno, first, meta->first_recno);
#endif
first = 0;
+ if ((ret =
+ __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0)
+ goto err;
+ locked = 1;
goto retry;
}
@@ -929,9 +887,9 @@ retry: /* Update the record number. */
cp->lock_mode = lock_mode;
if (!exact) {
- if (flags == DB_NEXT || flags == DB_NEXT_NODUP
- || flags == DB_PREV || flags == DB_PREV_NODUP
- || flags == DB_LAST) {
+ if (flags == DB_NEXT || flags == DB_NEXT_NODUP ||
+ flags == DB_PREV || flags == DB_PREV_NODUP ||
+ flags == DB_LAST) {
/* Release locks and try again. */
if (pg != NULL)
(void)__qam_fput(dbp, cp->pgno, pg, 0);
@@ -951,18 +909,20 @@ retry: /* Update the record number. */
}
/* Return the key if the user didn't give us one. */
- if (key != NULL && flags != DB_SET && flags != DB_GET_BOTH &&
- (ret = __db_retcopy(dbp, key, &cp->recno, sizeof(cp->recno),
- &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
- goto err1;
-
- if (key != NULL)
+ if (key != NULL) {
+ if (flags != DB_GET_BOTH && flags != DB_GET_BOTH_RANGE &&
+ flags != DB_SET && flags != DB_SET_RANGE &&
+ (ret = __db_retcopy(dbp->dbenv,
+ key, &cp->recno, sizeof(cp->recno),
+ &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+ goto err1;
F_SET(key, DB_DBT_ISSET);
+ }
qp = QAM_GET_RECORD(dbp, pg, cp->indx);
/* Return the data item. */
- if (flags == DB_GET_BOTH) {
+ if (flags == DB_GET_BOTH || flags == DB_GET_BOTH_RANGE) {
/*
* Need to compare
*/
@@ -973,8 +933,10 @@ retry: /* Update the record number. */
goto err1;
}
}
- if (data != NULL && (ret = __db_retcopy(dbp, data,
- qp->data, t->re_len, &dbc->rdata.data, &dbc->rdata.ulen)) != 0)
+ if (data != NULL &&
+ !F_ISSET(dbc, DBC_MULTIPLE|DBC_MULTIPLE_KEY) &&
+ (ret = __db_retcopy(dbp->dbenv, data,
+ qp->data, t->re_len, &dbc->rdata->data, &dbc->rdata->ulen)) != 0)
goto err1;
if (data != NULL)
@@ -982,18 +944,53 @@ retry: /* Update the record number. */
/* Finally, if we are doing DB_CONSUME mark the record. */
if (with_delete) {
- if (DB_LOGGING(dbc)) {
+ /*
+ * Assert that we're not a secondary index. Doing a DB_CONSUME
+ * on a secondary makes very little sense, since one can't
+ * DB_APPEND there; attempting one should be forbidden by
+ * the interface.
+ */
+ DB_ASSERT(!F_ISSET(dbp, DB_AM_SECONDARY));
+
+ /*
+ * Check and see if we *have* any secondary indices.
+ * If we do, we're a primary, so call __db_c_del_primary
+ * to delete the references to the item we're about to
+ * delete.
+ *
+ * Note that we work on a duplicated cursor, since the
+ * __db_ret work has already been done, so it's not safe
+ * to perform any additional ops on this cursor.
+ */
+ if (LIST_FIRST(&dbp->s_secondaries) != NULL) {
+ if ((ret = __db_c_idup(dbc,
+ &dbcdup, DB_POSITIONI)) != 0)
+ goto err1;
+
+ if ((ret = __db_c_del_primary(dbcdup)) != 0) {
+ /*
+ * The __db_c_del_primary return is more
+ * interesting.
+ */
+ (void)dbcdup->c_close(dbcdup);
+ goto err1;
+ }
+
+ if ((ret = dbcdup->c_close(dbcdup)) != 0)
+ goto err1;
+ }
+
+ if (DBC_LOGGING(dbc)) {
if (t->page_ext == 0 || t->re_len == 0) {
- if ((ret = __qam_del_log(dbp->dbenv, dbc->txn,
- &LSN(pg), 0, dbp->log_fileid, &LSN(pg),
+ if ((ret = __qam_del_log(dbp, dbc->txn,
+ &LSN(pg), 0, &LSN(pg),
pg->pgno, cp->indx, cp->recno)) != 0)
goto err1;
} else {
tmp.data = qp->data;
tmp.size = t->re_len;
- if ((ret =
- __qam_delext_log(dbp->dbenv, dbc->txn,
- &LSN(pg), 0, dbp->log_fileid, &LSN(pg),
+ if ((ret = __qam_delext_log(dbp,
+ dbc->txn, &LSN(pg), 0, &LSN(pg),
pg->pgno, cp->indx, cp->recno, &tmp)) != 0)
goto err1;
}
@@ -1003,7 +1000,7 @@ retry: /* Update the record number. */
put_mode = DB_MPOOL_DIRTY;
if ((ret = __LPUT(dbc, pglock)) != 0)
- goto err;
+ goto err1;
/*
* Now we need to update the metapage
@@ -1021,8 +1018,9 @@ retry: /* Update the record number. */
dbc, 0, metapno, lock_mode, 0, &metalock)) != 0)
goto err1;
locked = 1;
+
#ifdef QDEBUG
- __db_logmsg(dbp->dbenv,
+ __db_logmsg(dbenv,
dbc->txn, "Queue D", 0, "%x %d %d %d",
dbc->locker, cp->recno, first, meta->first_recno);
#endif
@@ -1037,190 +1035,380 @@ retry: /* Update the record number. */
if (first != meta->first_recno)
goto done;
- save_page = cp->pgno;
- save_indx = cp->indx;
- save_recno = cp->recno;
- save_lock = cp->lock;
+ if ((ret = __qam_consume(dbc, meta, first)) != 0)
+ goto err1;
+ }
- /*
- * If we skipped some deleted records, we need to
- * reposition on the first one. Get a lock
- * in case someone is trying to put it back.
- */
- if (first != cp->recno) {
- ret = __db_lget(dbc, 0, first, DB_LOCK_READ,
- DB_LOCK_NOWAIT | DB_LOCK_RECORD, &lock);
- if (ret == DB_LOCK_NOTGRANTED) {
- ret = 0;
- goto done;
- }
- if (ret != 0)
- goto err1;
- if ((ret =
- __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0)
- goto err1;
- cp->page = NULL;
- put_mode = 0;
- if ((ret = __qam_position(dbc,
- &first, QAM_READ, &exact)) != 0 || exact != 0) {
- (void)__LPUT(dbc, lock);
- goto err1;
- }
- if ((ret =__LPUT(dbc, lock)) != 0)
- goto err1;
- if ((ret = __LPUT(dbc, cp->lock)) != 0)
- goto err1;
+done:
+err1: if (cp->page != NULL) {
+ t_ret = __qam_fput(dbp, cp->pgno, cp->page, put_mode);
+
+ if (!ret)
+ ret = t_ret;
+ /* Doing record locking, release the page lock */
+ t_ret = __LPUT(dbc, pglock);
+ cp->page = NULL;
+ }
+
+err: if (!ret)
+ ret = t_ret;
+ if (meta) {
+
+ /* release the meta page */
+ t_ret = mpf->put(mpf, meta, meta_dirty ? DB_MPOOL_DIRTY : 0);
+
+ if (!ret)
+ ret = t_ret;
+
+ /* Don't hold the meta page long term. */
+ if (locked)
+ t_ret = __LPUT(dbc, metalock);
+ }
+ DB_ASSERT(!LOCK_ISSET(metalock));
+
+ /*
+ * There is no need to keep the record locked if we are
+ * not in a transaction.
+ */
+ if (t_ret == 0)
+ t_ret = __TLPUT(dbc, cp->lock);
+
+ return (ret ? ret : t_ret);
+}
+
+/*
+ * __qam_consume -- try to reset the head of the queue.
+ *
+ */
+
+static int
+__qam_consume(dbc, meta, first)
+ DBC *dbc;
+ QMETA *meta;
+ db_recno_t first;
+{
+ DB *dbp;
+ DB_LOCK lock, save_lock;
+ DB_MPOOLFILE *mpf;
+ QUEUE_CURSOR *cp;
+ db_indx_t save_indx;
+ db_pgno_t save_page;
+ db_recno_t current, save_recno;
+ u_int32_t rec_extent;
+ int exact, put_mode, ret, t_ret, wrapped;
+
+ dbp = dbc->dbp;
+ mpf = dbp->mpf;
+ cp = (QUEUE_CURSOR *)dbc->internal;
+ put_mode = DB_MPOOL_DIRTY;
+ ret = t_ret = 0;
+
+ save_page = cp->pgno;
+ save_indx = cp->indx;
+ save_recno = cp->recno;
+ save_lock = cp->lock;
+
+ /*
+ * If we skipped some deleted records, we need to
+ * reposition on the first one. Get a lock
+ * in case someone is trying to put it back.
+ */
+ if (first != cp->recno) {
+ ret = __db_lget(dbc, 0, first, DB_LOCK_READ,
+ DB_LOCK_NOWAIT | DB_LOCK_RECORD, &lock);
+ if (ret == DB_LOCK_NOTGRANTED) {
+ ret = 0;
+ goto done;
}
+ if (ret != 0)
+ goto done;
+ if ((ret =
+ __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0)
+ goto done;
+ cp->page = NULL;
+ put_mode = 0;
+ if ((ret = __qam_position(dbc,
+ &first, QAM_READ, &exact)) != 0 || exact != 0) {
+ (void)__LPUT(dbc, lock);
+ goto done;
+ }
+ if ((ret =__LPUT(dbc, lock)) != 0)
+ goto done;
+ if ((ret = __LPUT(dbc, cp->lock)) != 0)
+ goto done;
+ }
- current = meta->cur_recno;
- wrapped = 0;
- if (first > current)
- wrapped = 1;
- rec_extent = meta->page_ext * meta->rec_page;
+ current = meta->cur_recno;
+ wrapped = 0;
+ if (first > current)
+ wrapped = 1;
+ rec_extent = meta->page_ext * meta->rec_page;
- /* Loop until we find a record or hit current */
- for (;;) {
- /*
- * Check to see if we are moving off the extent
- * and remove the extent.
- * If we are moving off a page we need to
- * get rid of the buffer.
- * Wait for the lagging readers to move off the
- * page.
- */
- if (rec_extent != 0
- && ((exact = first % rec_extent == 0)
- || first % meta->rec_page == 0
- || first == UINT32_T_MAX)) {
- if (exact == 1 && (ret = __db_lget(dbc,
- 0, cp->pgno, DB_LOCK_WRITE, 0, &cp->lock)) != 0)
- break;
+ /* Loop until we find a record or hit current */
+ for (;;) {
+ /*
+ * Check to see if we are moving off the extent
+ * and remove the extent.
+ * If we are moving off a page we need to
+ * get rid of the buffer.
+ * Wait for the lagging readers to move off the
+ * page.
+ */
+ if (cp->page != NULL && rec_extent != 0 &&
+ ((exact = (first % rec_extent == 0)) ||
+ first % meta->rec_page == 0 ||
+ first == UINT32_T_MAX)) {
+ if (exact == 1 && (ret = __db_lget(dbc,
+ 0, cp->pgno, DB_LOCK_WRITE, 0, &cp->lock)) != 0)
+ break;
#ifdef QDEBUG
- __db_logmsg(dbp->dbenv,
- dbc->txn, "Queue R", 0, "%x %d %d %d",
- dbc->locker, cp->pgno, first, meta->first_recno);
+ __db_logmsg(dbp->dbenv,
+ dbc->txn, "Queue R", 0, "%x %d %d %d",
+ dbc->locker, cp->pgno, first, meta->first_recno);
#endif
- put_mode |= DB_MPOOL_DISCARD;
- if ((ret = __qam_fput(dbp,
- cp->pgno, cp->page, put_mode)) != 0)
- break;
- cp->page = NULL;
-
- if (exact == 1) {
- ret = __qam_fremove(dbp, cp->pgno);
- t_ret = __LPUT(dbc, cp->lock);
- }
- if (ret != 0)
- break;
- if (t_ret != 0) {
- ret = t_ret;
- break;
- }
- } else if ((ret =
- __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0)
+ put_mode |= DB_MPOOL_DISCARD;
+ if ((ret = __qam_fput(dbp,
+ cp->pgno, cp->page, put_mode)) != 0)
break;
cp->page = NULL;
- first++;
- if (first == RECNO_OOB) {
- wrapped = 0;
- first++;
- }
-
- /*
- * LOOP EXIT when we come move to the current
- * pointer.
- */
- if (!wrapped && first >= current)
- break;
- ret = __db_lget(dbc, 0, first, DB_LOCK_READ,
- DB_LOCK_NOWAIT | DB_LOCK_RECORD, &lock);
- if (ret == DB_LOCK_NOTGRANTED) {
- ret = 0;
- break;
+ if (exact == 1) {
+ ret = __qam_fremove(dbp, cp->pgno);
+ t_ret = __LPUT(dbc, cp->lock);
}
if (ret != 0)
break;
-
- if ((ret = __qam_position(dbc,
- &first, QAM_READ, &exact)) != 0) {
- (void)__LPUT(dbc, lock);
- break;
- }
- put_mode = 0;
- if ((ret =__LPUT(dbc, lock)) != 0
- || (ret = __LPUT(dbc, cp->lock)) != 0 ||exact) {
- if ((t_ret = __qam_fput(dbp, cp->pgno,
- cp->page, put_mode)) != 0 && ret == 0)
- ret = t_ret;
- cp->page = NULL;
+ if (t_ret != 0) {
+ ret = t_ret;
break;
}
+ } else if (cp->page != NULL && (ret =
+ __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0)
+ break;
+ cp->page = NULL;
+ first++;
+ if (first == RECNO_OOB) {
+ wrapped = 0;
+ first++;
}
- cp->pgno = save_page;
- cp->indx = save_indx;
- cp->recno = save_recno;
- cp->lock = save_lock;
-
/*
- * We have advanced as far as we can.
- * Advance first_recno to this point.
+ * LOOP EXIT when we come move to the current
+ * pointer.
*/
- if (meta->first_recno != first) {
+ if (!wrapped && first >= current)
+ break;
+
+ ret = __db_lget(dbc, 0, first, DB_LOCK_READ,
+ DB_LOCK_NOWAIT | DB_LOCK_RECORD, &lock);
+ if (ret == DB_LOCK_NOTGRANTED) {
+ ret = 0;
+ break;
+ }
+ if (ret != 0)
+ break;
+
+ if ((ret = __qam_position(dbc,
+ &first, QAM_READ, &exact)) != 0) {
+ (void)__LPUT(dbc, lock);
+ break;
+ }
+ put_mode = 0;
+ if ((ret =__LPUT(dbc, lock)) != 0 ||
+ (ret = __LPUT(dbc, cp->lock)) != 0 || exact) {
+ if ((t_ret = __qam_fput(dbp, cp->pgno,
+ cp->page, put_mode)) != 0 && ret == 0)
+ ret = t_ret;
+ cp->page = NULL;
+ break;
+ }
+ }
+
+ cp->pgno = save_page;
+ cp->indx = save_indx;
+ cp->recno = save_recno;
+ cp->lock = save_lock;
+
+ /*
+ * We have advanced as far as we can.
+ * Advance first_recno to this point.
+ */
+ if (ret == 0 && meta->first_recno != first) {
#ifdef QDEBUG
__db_logmsg(dbp->dbenv, dbc->txn, "Queue M",
0, "%x %d %d %d", dbc->locker, cp->recno,
first, meta->first_recno);
#endif
- if (DB_LOGGING(dbc))
- if ((ret =
- __qam_incfirst_log(dbp->dbenv,
- dbc->txn, &meta->dbmeta.lsn, 0,
- dbp->log_fileid, cp->recno)) != 0)
- goto err;
- meta->first_recno = first;
- meta_dirty = 1;
- }
+ if (DBC_LOGGING(dbc))
+ if ((ret = __qam_incfirst_log(dbp,
+ dbc->txn, &meta->dbmeta.lsn, 0,
+ cp->recno, PGNO_BASE_MD)) != 0)
+ goto done;
+ meta->first_recno = first;
+ (void)mpf->set(mpf, meta, DB_MPOOL_DIRTY);
}
done:
-err1: if (cp->page != NULL) {
- t_ret = __qam_fput(dbp, cp->pgno, cp->page, put_mode);
+ return (ret);
+}
- if (!ret)
+static int
+__qam_bulk(dbc, data, flags)
+ DBC *dbc;
+ DBT *data;
+ u_int32_t flags;
+{
+ DB *dbp;
+ DB_LOCK metalock;
+ DB_MPOOLFILE *mpf;
+ PAGE *pg;
+ QMETA *meta;
+ QAMDATA *qp;
+ QUEUE_CURSOR *cp;
+ db_indx_t indx;
+ db_pgno_t metapno;
+ qam_position_mode mode;
+ int32_t *endp, *offp;
+ u_int8_t *dbuf, *dp, *np;
+ int exact, recs, re_len, ret, t_ret, valid;
+ int is_key, need_pg, pagesize, size, space;
+
+ dbp = dbc->dbp;
+ mpf = dbp->mpf;
+ cp = (QUEUE_CURSOR *)dbc->internal;
+
+ mode = QAM_READ;
+ if (F_ISSET(dbc, DBC_RMW))
+ mode = QAM_WRITE;
+
+ pagesize = dbp->pgsize;
+ re_len = ((QUEUE *)dbp->q_internal)->re_len;
+ recs = ((QUEUE *)dbp->q_internal)->rec_page;
+ metapno = ((QUEUE *)dbp->q_internal)->q_meta;
+
+ is_key = LF_ISSET(DB_MULTIPLE_KEY) ? 1 : 0;
+ size = 0;
+
+ if ((ret = __db_lget(dbc, 0, metapno, DB_LOCK_READ, 0, &metalock)) != 0)
+ return (ret);
+ if ((ret = mpf->get(mpf, &metapno, 0, &meta)) != 0) {
+ /* We did not fetch it, we can release the lock. */
+ (void)__LPUT(dbc, metalock);
+ return (ret);
+ }
+
+ dbuf = data->data;
+ np = dp = dbuf;
+
+ /* Keep track of space that is left. There is an termination entry */
+ space = data->ulen;
+ space -= sizeof(*offp);
+
+ /* Build the offset/size table form the end up. */
+ endp = (int32_t *) ((u_int8_t *)dbuf + data->ulen);
+ endp--;
+ offp = endp;
+
+next_pg:
+ if ((ret = __qam_position(dbc, &cp->recno, mode, &exact)) != 0)
+ goto done;
+
+ pg = cp->page;
+ indx = cp->indx;
+ need_pg = 1;
+
+ do {
+ /*
+ * If this page is a nonexistent page at the end of an
+ * extent, pg may be NULL. A NULL page has no valid records,
+ * so just keep looping as though qp exists and isn't QAM_VALID;
+ * calling QAM_GET_RECORD is unsafe.
+ */
+ valid = 0;
+
+ /* Wrap around, skipping zero. */
+ if (cp->recno == RECNO_OOB)
+ cp->recno++;
+ if (pg != NULL) {
+ qp = QAM_GET_RECORD(dbp, pg, indx);
+ if (F_ISSET(qp, QAM_VALID)) {
+ valid = 1;
+ space -= (is_key ? 3 : 2) * sizeof(*offp);
+ if (space < 0)
+ goto get_space;
+ if (need_pg) {
+ dp = np;
+ size = pagesize - QPAGE_SZ(dbp);
+ if (space < size) {
+get_space:
+ if (offp == endp) {
+ data->size =
+ ALIGN(size +
+ pagesize,
+ sizeof(u_int32_t));
+ ret = ENOMEM;
+ break;
+ }
+ if (indx != 0)
+ indx--;
+ cp->recno--;
+ break;
+ }
+ memcpy(dp,
+ (char *)pg + QPAGE_SZ(dbp), size);
+ need_pg = 0;
+ space -= size;
+ np += size;
+ }
+ if (is_key)
+ *offp-- = cp->recno;
+ *offp-- = (int32_t)((u_int8_t*)qp -
+ (u_int8_t*)pg - QPAGE_SZ(dbp) +
+ dp - dbuf + SSZA(QAMDATA, data));
+ *offp-- = re_len;
+ }
+ }
+ if (!valid && is_key == 0) {
+ *offp-- = 0;
+ *offp-- = 0;
+ }
+ cp->recno++;
+ } while (++indx < recs && indx != RECNO_OOB
+ && cp->recno != meta->cur_recno
+ && !QAM_AFTER_CURRENT(meta, cp->recno));
+
+ if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (cp->page != NULL) {
+ if ((t_ret =
+ __qam_fput(dbp, cp->pgno, cp->page, 0)) != 0 && ret == 0)
ret = t_ret;
- /* Doing record locking, release the page lock */
- t_ret = __LPUT(dbc, pglock);
cp->page = NULL;
}
-err: if (!ret)
- ret = t_ret;
- if (meta) {
+ if (ret == 0
+ && (indx >= recs || indx == RECNO_OOB)
+ && cp->recno != meta->cur_recno
+ && !QAM_AFTER_CURRENT(meta, cp->recno))
+ goto next_pg;
- /* release the meta page */
- t_ret = memp_fput(
- dbp->mpf, meta, meta_dirty ? DB_MPOOL_DIRTY : 0);
+ if (is_key == 1)
+ *offp = RECNO_OOB;
+ else
+ *offp = -1;
- if (!ret)
- ret = t_ret;
+done:
+ /* release the meta page */
+ t_ret = mpf->put(mpf, meta, 0);
- /* Don't hold the meta page long term. */
- if (locked)
- t_ret = __LPUT(dbc, metalock);
- }
- DB_ASSERT(metalock.off == LOCK_INVALID);
+ if (!ret)
+ ret = t_ret;
- /*
- * There is no need to keep the record locked if we are
- * not in a transaction.
- */
- if (t_ret == 0)
- t_ret = __TLPUT(dbc, cp->lock);
+ t_ret = __LPUT(dbc, metalock);
- return (ret ? ret : t_ret);
+ return (ret);
}
/*
@@ -1241,15 +1429,12 @@ __qam_c_close(dbc, root_pgno, rmroot)
cp = (QUEUE_CURSOR *)dbc->internal;
/* Discard any locks not acquired inside of a transaction. */
- if (cp->lock.off != LOCK_INVALID) {
- (void)__TLPUT(dbc, cp->lock);
- cp->lock.off = LOCK_INVALID;
- }
+ (void)__TLPUT(dbc, cp->lock);
+ LOCK_INIT(cp->lock);
cp->page = NULL;
cp->pgno = PGNO_INVALID;
cp->indx = 0;
- cp->lock.off = LOCK_INVALID;
cp->lock_mode = DB_LOCK_NG;
cp->recno = RECNO_OOB;
cp->flags = 0;
@@ -1277,7 +1462,7 @@ __qam_c_dup(orig_dbc, new_dbc)
/* reget the long term lock if we are not in a xact */
if (orig_dbc->txn != NULL ||
- !STD_LOCKING(orig_dbc) || orig->lock.off == LOCK_INVALID)
+ !STD_LOCKING(orig_dbc) || !LOCK_ISSET(orig->lock))
return (0);
return (__db_lget(new_dbc,
@@ -1313,8 +1498,10 @@ __qam_c_init(dbc)
dbc->c_count = __db_c_count;
dbc->c_del = __db_c_del;
dbc->c_dup = __db_c_dup;
- dbc->c_get = __db_c_get;
+ dbc->c_get = dbc->c_real_get = __db_c_get;
+ dbc->c_pget = __db_c_pget;
dbc->c_put = __db_c_put;
+ dbc->c_am_bulk = __qam_bulk;
dbc->c_am_close = __qam_c_close;
dbc->c_am_del = __qam_c_del;
dbc->c_am_destroy = __qam_c_destroy;
@@ -1334,7 +1521,7 @@ __qam_c_destroy(dbc)
DBC *dbc;
{
/* Discard the structures. */
- __os_free(dbc->internal, sizeof(QUEUE_CURSOR));
+ __os_free(dbc->dbp->dbenv, dbc->internal);
return (0);
}
@@ -1355,3 +1542,74 @@ __qam_getno(dbp, key, rep)
}
return (0);
}
+
+/*
+ * __qam_truncate --
+ * Truncate a queue database
+ *
+ * PUBLIC: int __qam_truncate __P((DB *, DB_TXN *, u_int32_t *));
+ */
+int
+__qam_truncate(dbp, txn, countp)
+ DB *dbp;
+ DB_TXN *txn;
+ u_int32_t *countp;
+{
+ DBC *dbc;
+ DB_LOCK metalock;
+ DB_MPOOLFILE *mpf;
+ QMETA *meta;
+ db_pgno_t metapno;
+ int count, ret, t_ret;
+
+ mpf = dbp->mpf;
+
+ /* Acquire a cursor. */
+ if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+ return (ret);
+
+ /* Walk the queue, counting rows. */
+ count = 0;
+ while ((ret = __qam_c_get(dbc, NULL, NULL, DB_CONSUME, &metapno)) == 0)
+ count++;
+
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+
+ /* Discard the cursor. */
+ if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (ret != 0)
+ return (ret);
+
+ /* update the meta page */
+ /* get the meta page */
+ metapno = ((QUEUE *)dbp->q_internal)->q_meta;
+ if ((ret =
+ __db_lget(dbc, 0, metapno, DB_LOCK_WRITE, 0, &metalock)) != 0)
+ return (ret);
+
+ if ((ret = mpf->get(mpf, &metapno, 0, &meta)) != 0) {
+ /* We did not fetch it, we can release the lock. */
+ (void)__LPUT(dbc, metalock);
+ return (ret);
+ }
+ if (DBC_LOGGING(dbc)) {
+ ret = __qam_mvptr_log(dbp, dbc->txn, &meta->dbmeta.lsn, 0,
+ QAM_SETCUR | QAM_SETFIRST | QAM_TRUNCATE, meta->first_recno,
+ 1, meta->cur_recno, 1, &meta->dbmeta.lsn, PGNO_BASE_MD);
+ }
+ if (ret == 0)
+ meta->first_recno = meta->cur_recno = 1;
+
+ if ((t_ret =
+ mpf->put(mpf, meta, ret == 0 ? DB_MPOOL_DIRTY: 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+ ret = t_ret;
+
+ *countp = count;
+
+ return (ret);
+}
diff --git a/bdb/qam/qam.src b/bdb/qam/qam.src
index 507d7a65229..f8bf4da4dd0 100644
--- a/bdb/qam/qam.src
+++ b/bdb/qam/qam.src
@@ -1,13 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: qam.src,v 11.15 2001/01/16 20:10:55 ubell Exp $
+ * $Id: qam.src,v 11.28 2002/04/17 19:03:13 krinsky Exp $
*/
-PREFIX qam
+PREFIX __qam
+DBPRIVATE
INCLUDE #include "db_config.h"
INCLUDE
@@ -15,61 +16,55 @@ INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "qam.h"
-INCLUDE #include "txn.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/qam.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
- * inc
- * Used when we increment a record number. These do not actually
- * tell you what record number you got, just that you incremented
- * the record number. These operations are never undone.
- */
-BEGIN inc 76
-ARG fileid int32_t ld
-POINTER lsn DB_LSN * lu
-END
-
-/*
* incfirst
* Used when we increment first_recno.
*/
-BEGIN incfirst 77
-ARG fileid int32_t ld
+BEGIN incfirst 84
+DB fileid int32_t ld
ARG recno db_recno_t lu
+WRLOCK meta_pgno db_pgno_t lu
END
/*
* mvptr
* Used when we change one or both of cur_recno and first_recno.
*/
-BEGIN mvptr 78
+BEGIN mvptr 85
ARG opcode u_int32_t lu
-ARG fileid int32_t ld
+DB fileid int32_t ld
ARG old_first db_recno_t lu
ARG new_first db_recno_t lu
ARG old_cur db_recno_t lu
ARG new_cur db_recno_t lu
POINTER metalsn DB_LSN * lu
+WRLOCK meta_pgno db_pgno_t lu
END
+
/*
* del
* Used when we delete a record.
* recno is the record that is being deleted.
*/
BEGIN del 79
-ARG fileid int32_t ld
+DB fileid int32_t ld
POINTER lsn DB_LSN * lu
-ARG pgno db_pgno_t lu
+WRLOCK pgno db_pgno_t lu
ARG indx u_int32_t lu
ARG recno db_recno_t lu
END
@@ -81,9 +76,9 @@ END
* data is the record itself.
*/
BEGIN add 80
-ARG fileid int32_t ld
+DB fileid int32_t ld
POINTER lsn DB_LSN * lu
-ARG pgno db_pgno_t lu
+WRLOCK pgno db_pgno_t lu
ARG indx u_int32_t lu
ARG recno db_recno_t lu
DBT data DBT s
@@ -92,30 +87,12 @@ DBT olddata DBT s
END
/*
- * delete
- * Used when we remove a Queue extent file.
- */
-BEGIN delete 81
-DBT name DBT s
-POINTER lsn DB_LSN * lu
-END
-
-/*
- * rename
- * Used when we rename a Queue extent file.
- */
-BEGIN rename 82
-DBT name DBT s
-DBT newname DBT s
-END
-
-/*
* delext
* Used when we delete a record in extent based queue.
* recno is the record that is being deleted.
*/
BEGIN delext 83
-ARG fileid int32_t ld
+DB fileid int32_t ld
POINTER lsn DB_LSN * lu
ARG pgno db_pgno_t lu
ARG indx u_int32_t lu
diff --git a/bdb/qam/qam_conv.c b/bdb/qam/qam_conv.c
index 2eb1c7227e6..d89fe06b0cf 100644
--- a/bdb/qam/qam_conv.c
+++ b/bdb/qam/qam_conv.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_conv.c,v 11.6 2000/11/16 23:40:57 ubell Exp $";
+static const char revid[] = "$Id: qam_conv.c,v 11.14 2002/08/06 06:17:02 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,10 +16,9 @@ static const char revid[] = "$Id: qam_conv.c,v 11.6 2000/11/16 23:40:57 ubell Ex
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "qam.h"
-#include "db_swap.h"
-#include "db_am.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/db_am.h"
/*
* __qam_mswap --
@@ -43,6 +42,8 @@ __qam_mswap(pg)
SWAP32(p); /* re_pad */
SWAP32(p); /* rec_page */
SWAP32(p); /* page_ext */
+ p += 91 * sizeof(u_int32_t); /* unused */
+ SWAP32(p); /* crypto_magic */
return (0);
}
@@ -68,7 +69,7 @@ __qam_pgin_out(dbenv, pg, pp, cookie)
COMPQUIET(pg, 0);
COMPQUIET(dbenv, NULL);
pginfo = (DB_PGINFO *)cookie->data;
- if (!pginfo->needswap)
+ if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
h = pp;
diff --git a/bdb/qam/qam_files.c b/bdb/qam/qam_files.c
index e53a3bf24c0..f15a88d546d 100644
--- a/bdb/qam/qam_files.c
+++ b/bdb/qam/qam_files.c
@@ -1,67 +1,65 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_files.c,v 1.16 2001/01/19 18:01:59 bostic Exp $";
+static const char revid[] = "$Id: qam_files.c,v 1.52 2002/08/26 17:52:18 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "db_am.h"
-#include "lock.h"
-#include "btree.h"
-#include "qam.h"
-#include "mp.h"
+#include "dbinc/db_page.h"
+#include "dbinc/qam.h"
+#include "dbinc/db_am.h"
/*
- * __qam_fprobe -- calcluate and open extent
+ * __qam_fprobe -- calculate and open extent
*
- * Calculate which extent the page is in, open and create
- * if necessary.
+ * Calculate which extent the page is in, open and create if necessary.
*
- * PUBLIC: int __qam_fprobe __P((DB *, db_pgno_t, void *, qam_probe_mode, int));
+ * PUBLIC: int __qam_fprobe
+ * PUBLIC: __P((DB *, db_pgno_t, void *, qam_probe_mode, u_int32_t));
*/
-
int
__qam_fprobe(dbp, pgno, addrp, mode, flags)
DB *dbp;
db_pgno_t pgno;
void *addrp;
qam_probe_mode mode;
- int flags;
+ u_int32_t flags;
{
DB_ENV *dbenv;
DB_MPOOLFILE *mpf;
MPFARRAY *array;
QUEUE *qp;
- u_int32_t extid, maxext;
- char buf[256];
- int numext, offset, oldext, openflags, ret;
+ u_int8_t fid[DB_FILE_ID_LEN];
+ u_int32_t extid, maxext, openflags;
+ char buf[MAXPATHLEN];
+ int numext, offset, oldext, ret;
+ dbenv = dbp->dbenv;
qp = (QUEUE *)dbp->q_internal;
+ ret = 0;
+
if (qp->page_ext == 0) {
mpf = dbp->mpf;
- if (mode == QAM_PROBE_GET)
- return (memp_fget(mpf, &pgno, flags, addrp));
- return (memp_fput(mpf, addrp, flags));
+ return (mode == QAM_PROBE_GET ?
+ mpf->get(mpf, &pgno, flags, addrp) :
+ mpf->put(mpf, addrp, flags));
}
- dbenv = dbp->dbenv;
mpf = NULL;
- ret = 0;
/*
* Need to lock long enough to find the mpf or create the file.
@@ -92,36 +90,48 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
/*
* Check to see if the requested extent is outside the range of
- * extents in the array. This is true by defualt if there are
+ * extents in the array. This is true by default if there are
* no extents here yet.
*/
if (offset < 0 || (unsigned) offset >= array->n_extent) {
oldext = array->n_extent;
- numext = array->hi_extent - array->low_extent + 1;
- if (offset < 0
- && (unsigned) -offset + numext <= array->n_extent) {
- /* If we can fit this one in, move the array up */
+ numext = array->hi_extent - array->low_extent + 1;
+ if (offset < 0 &&
+ (unsigned) -offset + numext <= array->n_extent) {
+ /*
+ * If we can fit this one into the existing array by
+ * shifting the existing entries then we do not have
+ * to allocate.
+ */
memmove(&array->mpfarray[-offset],
array->mpfarray, numext
* sizeof(array->mpfarray[0]));
memset(array->mpfarray, 0, -offset
- * sizeof(array->mpfarray[0]));
+ * sizeof(array->mpfarray[0]));
offset = 0;
} else if ((u_int32_t)offset == array->n_extent &&
mode != QAM_PROBE_MPF && array->mpfarray[0].pinref == 0) {
- /* We can close the bottom extent. */
+ /*
+ * If this is at the end of the array and the file at
+ * the begining has a zero pin count we can close
+ * the bottom extent and put this one at the end.
+ */
mpf = array->mpfarray[0].mpf;
- if (mpf != NULL && (ret = memp_fclose(mpf)) != 0)
+ if (mpf != NULL && (ret = mpf->close(mpf, 0)) != 0)
goto err;
memmove(&array->mpfarray[0], &array->mpfarray[1],
- (array->n_extent - 1) * sizeof (array->mpfarray[0]));
+ (array->n_extent - 1) * sizeof(array->mpfarray[0]));
array->low_extent++;
array->hi_extent++;
offset--;
array->mpfarray[offset].mpf = NULL;
array->mpfarray[offset].pinref = 0;
} else {
- /* See if we have wrapped around the queue. */
+ /*
+ * See if we have wrapped around the queue.
+ * If it has then allocate the second array.
+ * Otherwise just expand the one we are using.
+ */
maxext = (u_int32_t) UINT32_T_MAX
/ (qp->page_ext * qp->rec_page);
if ((u_int32_t) abs(offset) >= maxext/2) {
@@ -143,51 +153,73 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
alloc:
if ((ret = __os_realloc(dbenv,
array->n_extent * sizeof(struct __qmpf),
- NULL, &array->mpfarray)) != 0)
+ &array->mpfarray)) != 0)
goto err;
if (offset < 0) {
+ /*
+ * Move the array up and put the new one
+ * in the first slot.
+ */
offset = -offset;
- memmove(&array->mpfarray[offset], array->mpfarray,
+ memmove(&array->mpfarray[offset],
+ array->mpfarray,
numext * sizeof(array->mpfarray[0]));
memset(array->mpfarray, 0,
offset * sizeof(array->mpfarray[0]));
memset(&array->mpfarray[numext + offset], 0,
- (array->n_extent - (numext + offset))
- * sizeof(array->mpfarray[0]));
+ (array->n_extent - (numext + offset))
+ * sizeof(array->mpfarray[0]));
offset = 0;
}
else
+ /* Clear the new part of the array. */
memset(&array->mpfarray[oldext], 0,
(array->n_extent - oldext) *
sizeof(array->mpfarray[0]));
}
}
+ /* Update the low and hi range of saved extents. */
if (extid < array->low_extent)
array->low_extent = extid;
if (extid > array->hi_extent)
array->hi_extent = extid;
+
+ /* If the extent file is not yet open, open it. */
if (array->mpfarray[offset].mpf == NULL) {
- snprintf(buf,
- sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, extid);
+ snprintf(buf, sizeof(buf),
+ QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, extid);
+ if ((ret = dbenv->memp_fcreate(
+ dbenv, &array->mpfarray[offset].mpf, 0)) != 0)
+ goto err;
+ mpf = array->mpfarray[offset].mpf;
+ (void)mpf->set_lsn_offset(mpf, 0);
+ (void)mpf->set_pgcookie(mpf, &qp->pgcookie);
+
+ /* Set up the fileid for this extent. */
+ __qam_exid(dbp, fid, extid);
+ (void)mpf->set_fileid(mpf, fid);
openflags = DB_EXTENT;
if (LF_ISSET(DB_MPOOL_CREATE))
openflags |= DB_CREATE;
if (F_ISSET(dbp, DB_AM_RDONLY))
openflags |= DB_RDONLY;
- qp->finfo.fileid = NULL;
- if ((ret = __memp_fopen(dbenv->mp_handle,
- NULL, buf, openflags, qp->mode, dbp->pgsize,
- 1, &qp->finfo, &array->mpfarray[offset].mpf)) != 0)
+ if (F_ISSET(dbenv, DB_ENV_DIRECT_DB))
+ openflags |= DB_DIRECT;
+ if ((ret = mpf->open(
+ mpf, buf, openflags, qp->mode, dbp->pgsize)) != 0) {
+ array->mpfarray[offset].mpf = NULL;
+ (void)mpf->close(mpf, 0);
goto err;
+ }
}
mpf = array->mpfarray[offset].mpf;
if (mode == QAM_PROBE_GET)
array->mpfarray[offset].pinref++;
if (LF_ISSET(DB_MPOOL_CREATE))
- __memp_clear_unlink(mpf);
+ mpf->set_unlink(mpf, 0);
err:
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
@@ -200,9 +232,8 @@ err:
pgno--;
pgno %= qp->page_ext;
if (mode == QAM_PROBE_GET)
- return (memp_fget(mpf,
- &pgno, flags | DB_MPOOL_EXTENT, addrp));
- ret = memp_fput(mpf, addrp, flags);
+ return (mpf->get(mpf, &pgno, flags, addrp));
+ ret = mpf->put(mpf, addrp, flags);
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
array->mpfarray[offset].pinref--;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
@@ -218,7 +249,6 @@ err:
*
* PUBLIC: int __qam_fclose __P((DB *, db_pgno_t));
*/
-
int
__qam_fclose(dbp, pgnoaddr)
DB *dbp;
@@ -251,12 +281,13 @@ __qam_fclose(dbp, pgnoaddr)
mpf = array->mpfarray[offset].mpf;
array->mpfarray[offset].mpf = NULL;
- ret = memp_fclose(mpf);
+ ret = mpf->close(mpf, 0);
done:
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
return (ret);
}
+
/*
* __qam_fremove -- remove an extent.
*
@@ -266,7 +297,6 @@ done:
*
* PUBLIC: int __qam_fremove __P((DB *, db_pgno_t));
*/
-
int
__qam_fremove(dbp, pgnoaddr)
DB *dbp;
@@ -278,7 +308,7 @@ __qam_fremove(dbp, pgnoaddr)
QUEUE *qp;
u_int32_t extid;
#if CONFIG_TEST
- char buf[256], *real_name;
+ char buf[MAXPATHLEN], *real_name;
#endif
int offset, ret;
@@ -300,22 +330,34 @@ __qam_fremove(dbp, pgnoaddr)
real_name = NULL;
/* Find the real name of the file. */
snprintf(buf, sizeof(buf),
- QUEUE_EXTENT, qp->dir, qp->name, extid);
+ QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, extid);
if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, buf, 0, NULL, &real_name)) != 0)
+ DB_APP_DATA, buf, 0, NULL, &real_name)) != 0)
goto err;
#endif
+ /*
+ * The log must be flushed before the file is deleted. We depend on
+ * the log record of the last delete to recreate the file if we crash.
+ */
+ if (LOGGING_ON(dbenv) && (ret = dbenv->log_flush(dbenv, NULL)) != 0)
+ goto err;
+
mpf = array->mpfarray[offset].mpf;
array->mpfarray[offset].mpf = NULL;
- __memp_set_unlink(mpf);
- if ((ret = memp_fclose(mpf)) != 0)
+ mpf->set_unlink(mpf, 1);
+ if ((ret = mpf->close(mpf, 0)) != 0)
goto err;
+ /*
+ * If the file is at the bottom of the array
+ * shift things down and adjust the end points.
+ */
if (offset == 0) {
memmove(array->mpfarray, &array->mpfarray[1],
(array->hi_extent - array->low_extent)
* sizeof(array->mpfarray[0]));
- array->mpfarray[array->hi_extent - array->low_extent].mpf = NULL;
+ array->mpfarray[
+ array->hi_extent - array->low_extent].mpf = NULL;
if (array->low_extent != array->hi_extent)
array->low_extent++;
} else {
@@ -327,7 +369,7 @@ err:
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
#if CONFIG_TEST
if (real_name != NULL)
- __os_freestr(real_name);
+ __os_free(dbenv, real_name);
#endif
return (ret);
}
@@ -353,6 +395,7 @@ __qam_sync(dbp, flags)
int done, ret;
dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
PANIC_CHECK(dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");
@@ -369,7 +412,7 @@ __qam_sync(dbp, flags)
return (0);
/* Flush any dirty pages from the cache to the backing file. */
- if ((ret = memp_fsync(dbp->mpf)) != 0)
+ if ((ret = mpf->sync(dbp->mpf)) != 0)
return (ret);
qp = (QUEUE *)dbp->q_internal;
@@ -383,7 +426,7 @@ __qam_sync(dbp, flags)
if (filelist == NULL)
return (0);
- __os_free(filelist, 0);
+ __os_free(dbp->dbenv, filelist);
done = 0;
qp = (QUEUE *)dbp->q_internal;
@@ -394,7 +437,7 @@ again:
mpfp = array->mpfarray;
for (i = array->low_extent; i <= array->hi_extent; i++, mpfp++)
if ((mpf = mpfp->mpf) != NULL) {
- if ((ret = memp_fsync(mpf)) != 0)
+ if ((ret = mpf->sync(mpf)) != 0)
goto err;
/*
* If we are the only ones with this file open
@@ -402,7 +445,7 @@ again:
*/
if (mpfp->pinref == 0) {
mpfp->mpf = NULL;
- if ((ret = memp_fclose(mpf)) != 0)
+ if ((ret = mpf->close(mpf, 0)) != 0)
goto err;
}
}
@@ -431,16 +474,19 @@ __qam_gen_filelist(dbp, filelistp)
QUEUE_FILELIST **filelistp;
{
DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
QUEUE *qp;
QMETA *meta;
- db_pgno_t i, last, start, stop;
+ db_pgno_t i, last, start;
db_recno_t current, first;
QUEUE_FILELIST *fp;
int ret;
dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
qp = (QUEUE *)dbp->q_internal;
*filelistp = NULL;
+
if (qp->page_ext == 0)
return (0);
@@ -450,18 +496,14 @@ __qam_gen_filelist(dbp, filelistp)
/* Find out the page number of the last page in the database. */
i = PGNO_BASE_MD;
- if ((ret = memp_fget(dbp->mpf, &i, 0, &meta)) != 0) {
- (void)dbp->close(dbp, 0);
+ if ((ret = mpf->get(mpf, &i, 0, &meta)) != 0)
return (ret);
- }
current = meta->cur_recno;
first = meta->first_recno;
- if ((ret = memp_fput(dbp->mpf, meta, 0)) != 0) {
- (void)dbp->close(dbp, 0);
+ if ((ret = mpf->put(mpf, meta, 0)) != 0)
return (ret);
- }
last = QAM_RECNO_PAGE(dbp, current);
start = QAM_RECNO_PAGE(dbp, first);
@@ -476,14 +518,10 @@ __qam_gen_filelist(dbp, filelistp)
return (ret);
fp = *filelistp;
i = start;
- if (last >= start)
- stop = last;
- else
- stop = QAM_RECNO_PAGE(dbp, UINT32_T_MAX);
-again:
- for (; i <= last; i += qp->page_ext) {
- if ((ret = __qam_fprobe(dbp,
- i, &fp->mpf, QAM_PROBE_MPF, 0)) != 0) {
+
+again: for (; i <= last; i += qp->page_ext) {
+ if ((ret =
+ __qam_fprobe(dbp, i, &fp->mpf, QAM_PROBE_MPF, 0)) != 0) {
if (ret == ENOENT)
continue;
return (ret);
@@ -494,10 +532,111 @@ again:
if (last < start) {
i = 1;
- stop = last;
start = 0;
goto again;
}
return (0);
}
+
+/*
+ * __qam_extent_names -- generate a list of extent files names.
+ *
+ * PUBLIC: int __qam_extent_names __P((DB_ENV *, char *, char ***));
+ */
+int
+__qam_extent_names(dbenv, name, namelistp)
+ DB_ENV *dbenv;
+ char *name;
+ char ***namelistp;
+{
+ DB *dbp;
+ QUEUE *qp;
+ QUEUE_FILELIST *filelist, *fp;
+ char buf[MAXPATHLEN], *dir, **cp, *freep;
+ int cnt, len, ret;
+
+ *namelistp = NULL;
+ filelist = NULL;
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return (ret);
+ if ((ret =
+ __db_open(dbp, NULL, name, NULL, DB_QUEUE, DB_RDONLY, 0)) != 0)
+ return (ret);
+ qp = dbp->q_internal;
+ if (qp->page_ext == 0)
+ goto done;
+
+ if ((ret = __qam_gen_filelist(dbp, &filelist)) != 0)
+ goto done;
+
+ if (filelist == NULL)
+ goto done;
+
+ cnt = 0;
+ for (fp = filelist; fp->mpf != NULL; fp++)
+ cnt++;
+ dir = ((QUEUE *)dbp->q_internal)->dir;
+ name = ((QUEUE *)dbp->q_internal)->name;
+
+ /* QUEUE_EXTENT contains extra chars, but add 6 anyway for the int. */
+ len = (u_int32_t)(cnt * (sizeof(**namelistp)
+ + strlen(QUEUE_EXTENT) + strlen(dir) + strlen(name) + 6));
+
+ if ((ret =
+ __os_malloc(dbp->dbenv, len, namelistp)) != 0)
+ goto done;
+ cp = *namelistp;
+ freep = (char *)(cp + cnt + 1);
+ for (fp = filelist; fp->mpf != NULL; fp++) {
+ snprintf(buf, sizeof(buf),
+ QUEUE_EXTENT, dir, PATH_SEPARATOR[0], name, fp->id);
+ len = (u_int32_t)strlen(buf);
+ *cp++ = freep;
+ strcpy(freep, buf);
+ freep += len + 1;
+ }
+ *cp = NULL;
+
+done:
+ if (filelist != NULL)
+ __os_free(dbp->dbenv, filelist);
+ (void)dbp->close(dbp, DB_NOSYNC);
+
+ return (ret);
+}
+
+/*
+ * __qam_exid --
+ * Generate a fileid for an extent based on the fileid of the main
+ * file. Since we do not log schema creates/deletes explicitly, the log
+ * never captures the fileid of an extent file. In order that masters and
+ * replicas have the same fileids (so they can explicitly delete them), we
+ * use computed fileids for the extent files of Queue files.
+ *
+ * An extent file id retains the low order 12 bytes of the file id and
+ * overwrites the dev/inode fields, placing a 0 in the inode field, and
+ * the extent number in the dev field.
+ *
+ * PUBLIC: void __qam_exid __P((DB *, u_int8_t *, u_int32_t));
+ */
+void
+__qam_exid(dbp, fidp, exnum)
+ DB *dbp;
+ u_int8_t *fidp;
+ u_int32_t exnum;
+{
+ int i;
+ u_int8_t *p;
+
+ /* Copy the fileid from the master. */
+ memcpy(fidp, dbp->fileid, DB_FILE_ID_LEN);
+
+ /* The first four bytes are the inode or the FileIndexLow; 0 it. */
+ for (i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = 0;
+
+ /* The next four bytes are the dev/FileIndexHigh; insert the exnum . */
+ for (p = (u_int8_t *)&exnum, i = sizeof(u_int32_t); i > 0; --i)
+ *fidp++ = *p++;
+}
diff --git a/bdb/qam/qam_method.c b/bdb/qam/qam_method.c
index 1c94f4b8db0..5415fc5d00c 100644
--- a/bdb/qam/qam_method.c
+++ b/bdb/qam/qam_method.c
@@ -1,34 +1,32 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_method.c,v 11.17 2001/01/10 04:50:54 ubell Exp $";
+static const char revid[] = "$Id: qam_method.c,v 11.55 2002/08/26 17:52:19 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+
#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_int.h"
-#include "db_shash.h"
-#include "db_am.h"
-#include "qam.h"
-#include "db.h"
-#include "mp.h"
-#include "lock.h"
-#include "log.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/fop.h"
+#include "dbinc/lock.h"
+#include "dbinc/qam.h"
+#include "dbinc/txn.h"
static int __qam_set_extentsize __P((DB *, u_int32_t));
-static int __qam_remove_callback __P((DB *, void *));
struct __qam_cookie {
DB_LSN lsn;
@@ -77,7 +75,8 @@ __qam_db_close(dbp)
int ret, t_ret;
ret = 0;
- t = dbp->q_internal;
+ if ((t = dbp->q_internal) == NULL)
+ return (0);
array = &t->array1;
again:
@@ -88,10 +87,10 @@ again:
mpf = mpfp->mpf;
mpfp->mpf = NULL;
if (mpf != NULL &&
- (t_ret = memp_fclose(mpf)) != 0 && ret == 0)
+ (t_ret = mpf->close(mpf, 0)) != 0 && ret == 0)
ret = t_ret;
}
- __os_free(array->mpfarray, 0);
+ __os_free(dbp->dbenv, array->mpfarray);
}
if (t->array2.n_extent != 0) {
array = &t->array2;
@@ -100,8 +99,8 @@ again:
}
if (t->path != NULL)
- __os_free(t->path, 0);
- __os_free(t, sizeof(QUEUE));
+ __os_free(dbp->dbenv, t->path);
+ __os_free(dbp->dbenv, t);
dbp->q_internal = NULL;
return (ret);
@@ -115,7 +114,7 @@ __qam_set_extentsize(dbp, extentsize)
DB_ILLEGAL_AFTER_OPEN(dbp, "set_extentsize");
if (extentsize < 1) {
- __db_err(dbp->dbenv, "Extent size must be at least 1.");
+ __db_err(dbp->dbenv, "Extent size must be at least 1");
return (EINVAL);
}
@@ -128,29 +127,35 @@ __qam_set_extentsize(dbp, extentsize)
* __db_prqueue --
* Print out a queue
*
- * PUBLIC: int __db_prqueue __P((DB *, u_int32_t));
+ * PUBLIC: int __db_prqueue __P((DB *, FILE *, u_int32_t));
*/
int
-__db_prqueue(dbp, flags)
+__db_prqueue(dbp, fp, flags)
DB *dbp;
+ FILE *fp;
u_int32_t flags;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
QMETA *meta;
db_pgno_t first, i, last, pg_ext, stop;
- int ret;
+ int ret, t_ret;
+
+ mpf = dbp->mpf;
/* Find out the page number of the last page in the database. */
i = PGNO_BASE_MD;
- if ((ret = memp_fget(dbp->mpf, &i, 0, &meta)) != 0)
+ if ((ret = mpf->get(mpf, &i, 0, &meta)) != 0)
return (ret);
first = QAM_RECNO_PAGE(dbp, meta->first_recno);
last = QAM_RECNO_PAGE(dbp, meta->cur_recno);
- if ((ret = __db_prpage(dbp, (PAGE *)meta, flags)) != 0)
- return (ret);
- if ((ret = memp_fput(dbp->mpf, meta, 0)) != 0)
+ ret = __db_prpage(dbp, (PAGE *)meta, fp, flags);
+ if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (ret != 0)
return (ret);
i = first;
@@ -162,20 +167,20 @@ __db_prqueue(dbp, flags)
/* Dump each page. */
begin:
for (; i <= stop; ++i) {
- if ((ret = __qam_fget(dbp, &i, DB_MPOOL_EXTENT, &h)) != 0) {
+ if ((ret = __qam_fget(dbp, &i, 0, &h)) != 0) {
pg_ext = ((QUEUE *)dbp->q_internal)->page_ext;
if (pg_ext == 0) {
- if (ret == EINVAL && first == last)
+ if (ret == DB_PAGE_NOTFOUND && first == last)
return (0);
return (ret);
}
- if (ret == ENOENT || ret == EINVAL) {
+ if (ret == ENOENT || ret == DB_PAGE_NOTFOUND) {
i += pg_ext - ((i - 1) % pg_ext) - 1;
continue;
}
return (ret);
}
- (void)__db_prpage(dbp, h, flags);
+ (void)__db_prpage(dbp, h, fp, flags);
if ((ret = __qam_fput(dbp, i, h, 0)) != 0)
return (ret);
}
@@ -193,31 +198,31 @@ begin:
* __qam_remove
* Remove method for a Queue.
*
- * PUBLIC: int __qam_remove __P((DB *, const char *,
- * PUBLIC: const char *, DB_LSN *, int (**)(DB *, void*), void **));
+ * PUBLIC: int __qam_remove __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, const char *, DB_LSN *));
*/
int
-__qam_remove(dbp, name, subdb, lsnp, callbackp, cookiep)
+__qam_remove(dbp, txn, name, subdb, lsnp)
DB *dbp;
+ DB_TXN *txn;
const char *name, *subdb;
DB_LSN *lsnp;
- int (**callbackp) __P((DB *, void *));
- void **cookiep;
{
- DBT namedbt;
DB_ENV *dbenv;
- DB_LSN lsn;
+ DB *tmpdbp;
MPFARRAY *ap;
QUEUE *qp;
- int ret;
- char *backup, buf[256], *real_back, *real_name;
QUEUE_FILELIST *filelist, *fp;
- struct __qam_cookie *qam_cookie;
+ int ret, needclose, t_ret;
+ char buf[MAXPATHLEN];
+ u_int8_t fid[DB_FILE_ID_LEN];
+
+ COMPQUIET(lsnp, NULL);
dbenv = dbp->dbenv;
ret = 0;
- backup = real_back = real_name = NULL;
filelist = NULL;
+ needclose = 0;
PANIC_CHECK(dbenv);
@@ -226,148 +231,86 @@ __qam_remove(dbp, name, subdb, lsnp, callbackp, cookiep)
*/
if (subdb != NULL) {
__db_err(dbenv,
- "Queue does not support multiple databases per file.");
+ "Queue does not support multiple databases per file");
ret = EINVAL;
- goto done;
+ goto err;
+ }
+
+ /*
+ * Since regular remove no longer opens the database, we may have
+ * to do it here.
+ */
+ if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
+ tmpdbp = dbp;
+ else {
+ if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
+ return (ret);
+ /*
+ * We need to make sure we don't self-deadlock, so give
+ * this dbp the same locker as the incoming one.
+ */
+ tmpdbp->lid = dbp->lid;
+
+ /*
+ * If this is a transactional dbp and the open fails, then
+ * the transactional abort will close the dbp. If it's not
+ * a transactional open, then we always have to close it
+ * even if the open fails. Once the open has succeeded,
+ * then we will always want to close it.
+ */
+ if (txn == NULL)
+ needclose = 1;
+ if ((ret = tmpdbp->open(tmpdbp,
+ txn, name, NULL, DB_QUEUE, 0, 0)) != 0)
+ goto err;
+ needclose = 1;
}
- qp = (QUEUE *)dbp->q_internal;
+ qp = (QUEUE *)tmpdbp->q_internal;
if (qp->page_ext != 0 &&
- (ret = __qam_gen_filelist(dbp, &filelist)) != 0)
- goto done;
+ (ret = __qam_gen_filelist(tmpdbp, &filelist)) != 0)
+ goto err;
if (filelist == NULL)
- goto done;
+ goto err;
for (fp = filelist; fp->mpf != NULL; fp++) {
- snprintf(buf,
- sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, fp->id);
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, buf, 0, NULL, &real_name)) != 0)
- goto done;
- if (LOGGING_ON(dbenv)) {
- memset(&namedbt, 0, sizeof(namedbt));
- namedbt.data = (char *)buf;
- namedbt.size = strlen(buf) + 1;
-
- if ((ret =
- __qam_delete_log(dbenv, dbp->open_txn,
- &lsn, DB_FLUSH, &namedbt, lsnp)) != 0) {
- __db_err(dbenv,
- "%s: %s", name, db_strerror(ret));
- goto done;
- }
- }
- (void)__memp_fremove(fp->mpf);
- if ((ret = memp_fclose(fp->mpf)) != 0)
- goto done;
+ snprintf(buf, sizeof(buf),
+ QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, fp->id);
+ if ((ret = fp->mpf->close(fp->mpf, DB_MPOOL_DISCARD)) != 0)
+ goto err;
if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
ap = &qp->array1;
else
ap = &qp->array2;
ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
- /* Create name for backup file. */
- if (TXN_ON(dbenv)) {
- if ((ret = __db_backup_name(dbenv,
- buf, &backup, lsnp)) != 0)
- goto done;
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, backup, 0, NULL, &real_back)) != 0)
- goto done;
- if ((ret = __os_rename(dbenv,
- real_name, real_back)) != 0)
- goto done;
- __os_freestr(real_back);
- real_back = NULL;
- }
- else
- if ((ret = __os_unlink(dbenv, real_name)) != 0)
- goto done;
- __os_freestr(real_name);
- real_name = NULL;
- }
- if ((ret= __os_malloc(dbenv,
- sizeof(struct __qam_cookie), NULL, &qam_cookie)) != 0)
- goto done;
- qam_cookie->lsn = *lsnp;
- qam_cookie->filelist = filelist;
- *cookiep = qam_cookie;
- *callbackp = __qam_remove_callback;
-
-done:
- if (ret != 0 && filelist != NULL)
- __os_free(filelist, 0);
- if (real_back != NULL)
- __os_freestr(real_back);
- if (real_name != NULL)
- __os_freestr(real_name);
- if (backup != NULL)
- __os_freestr(backup);
-
- return (ret);
-}
-
-static int
-__qam_remove_callback(dbp, cookie)
- DB *dbp;
- void *cookie;
-{
- DB_ENV *dbenv;
- DB_LSN *lsnp;
- QUEUE *qp;
- QUEUE_FILELIST *filelist, *fp;
- char *backup, buf[256], *real_back;
- int ret;
-
- qp = (QUEUE *)dbp->q_internal;
- if (qp->page_ext == 0)
- return (__os_unlink(dbp->dbenv, cookie));
-
- dbenv = dbp->dbenv;
- lsnp = &((struct __qam_cookie *)cookie)->lsn;
- filelist = fp = ((struct __qam_cookie *)cookie)->filelist;
- real_back = backup = NULL;
- if ((ret =
- __db_backup_name(dbenv, qp->name, &backup, lsnp)) != 0)
- goto err;
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
- goto err;
- if ((ret = __os_unlink(dbp->dbenv, real_back)) != 0)
- goto err;
-
- __os_freestr(backup);
- __os_freestr(real_back);
-
- if (fp == NULL)
- return (0);
-
- for (; fp->mpf != NULL; fp++) {
- snprintf(buf,
- sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, fp->id);
- real_back = backup = NULL;
- if ((ret = __db_backup_name(dbenv, buf, &backup, lsnp)) != 0)
- goto err;
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
+ /* Take care of object reclamation. */
+ __qam_exid(tmpdbp, fid, fp->id);
+ if ((ret = __fop_remove(dbenv,
+ txn, fid, buf, DB_APP_DATA)) != 0)
goto err;
- ret = __os_unlink(dbenv, real_back);
- __os_freestr(real_back);
- __os_freestr(backup);
}
- __os_free(filelist, 0);
- __os_free(cookie, sizeof (struct __qam_cookie));
- return (0);
-
-err:
- if (backup != NULL)
- __os_freestr(backup);
-
- if (real_back != NULL)
- __os_freestr(real_back);
+err: if (filelist != NULL)
+ __os_free(dbenv, filelist);
+ if (needclose) {
+ /*
+ * Since we copied the lid from the dbp, we'd better not
+ * free it here.
+ */
+ tmpdbp->lid = DB_LOCK_INVALIDID;
+
+ /* We need to remove the lockevent we associated with this. */
+ if (txn != NULL)
+ __txn_remlock(dbenv,
+ txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
+
+ if ((t_ret =
+ __db_close_i(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+ }
return (ret);
}
@@ -376,97 +319,95 @@ err:
* __qam_rename
* Rename method for Queue.
*
- * PUBLIC: int __qam_rename __P((DB *,
+ * PUBLIC: int __qam_rename __P((DB *, DB_TXN *,
* PUBLIC: const char *, const char *, const char *));
*/
int
-__qam_rename(dbp, filename, subdb, newname)
+__qam_rename(dbp, txn, filename, subdb, newname)
DB *dbp;
+ DB_TXN *txn;
const char *filename, *subdb, *newname;
{
- DBT namedbt, newnamedbt;
DB_ENV *dbenv;
- DB_LSN newlsn;
+ DB *tmpdbp;
MPFARRAY *ap;
QUEUE *qp;
QUEUE_FILELIST *fp, *filelist;
- char buf[256], nbuf[256], *namep, *real_name, *real_newname;
- int ret;
+ char buf[MAXPATHLEN], nbuf[MAXPATHLEN];
+ char *namep;
+ int ret, needclose, t_ret;
+ u_int8_t fid[DB_FILE_ID_LEN], *fidp;
dbenv = dbp->dbenv;
ret = 0;
- real_name = real_newname = NULL;
filelist = NULL;
-
- qp = (QUEUE *)dbp->q_internal;
+ needclose = 0;
if (subdb != NULL) {
__db_err(dbenv,
- "Queue does not support multiple databases per file.");
+ "Queue does not support multiple databases per file");
ret = EINVAL;
goto err;
}
+
+ /*
+ * Since regular rename no longer opens the database, we may have
+ * to do it here.
+ */
+ if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
+ tmpdbp = dbp;
+ else {
+ if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
+ return (ret);
+ /* Copy the incoming locker so we don't self-deadlock. */
+ tmpdbp->lid = dbp->lid;
+ needclose = 1;
+ if ((ret = tmpdbp->open(tmpdbp, txn, filename, NULL,
+ DB_QUEUE, 0, 0)) != 0)
+ goto err;
+ }
+
+ qp = (QUEUE *)tmpdbp->q_internal;
+
if (qp->page_ext != 0 &&
- (ret = __qam_gen_filelist(dbp, &filelist)) != 0)
+ (ret = __qam_gen_filelist(tmpdbp, &filelist)) != 0)
goto err;
if ((namep = __db_rpath(newname)) != NULL)
newname = namep + 1;
+ fidp = fid;
for (fp = filelist; fp != NULL && fp->mpf != NULL; fp++) {
- if ((ret = __memp_fremove(fp->mpf)) != 0)
- goto err;
- if ((ret = memp_fclose(fp->mpf)) != 0)
+ fp->mpf->get_fileid(fp->mpf, fidp);
+ if ((ret = fp->mpf->close(fp->mpf, DB_MPOOL_DISCARD)) != 0)
goto err;
if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
ap = &qp->array1;
else
ap = &qp->array2;
ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
- snprintf(buf,
- sizeof(buf), QUEUE_EXTENT, qp->dir, qp->name, fp->id);
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, buf, 0, NULL, &real_name)) != 0)
- goto err;
- snprintf(nbuf,
- sizeof(nbuf), QUEUE_EXTENT, qp->dir, newname, fp->id);
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, nbuf, 0, NULL, &real_newname)) != 0)
+ snprintf(buf, sizeof(buf),
+ QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, fp->id);
+ snprintf(nbuf, sizeof(nbuf),
+ QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], newname, fp->id);
+ if ((ret = __fop_rename(dbenv,
+ txn, buf, nbuf, fidp, DB_APP_DATA)) != 0)
goto err;
- if (LOGGING_ON(dbenv)) {
- memset(&namedbt, 0, sizeof(namedbt));
- namedbt.data = (char *)buf;
- namedbt.size = strlen(buf) + 1;
-
- memset(&newnamedbt, 0, sizeof(namedbt));
- newnamedbt.data = (char *)nbuf;
- newnamedbt.size = strlen(nbuf) + 1;
-
- if ((ret =
- __qam_rename_log(dbenv,
- dbp->open_txn, &newlsn, 0,
- &namedbt, &newnamedbt)) != 0) {
- __db_err(dbenv, "%s: %s", filename, db_strerror(ret));
- goto err;
- }
-
- if ((ret = __log_filelist_update(dbenv, dbp,
- dbp->log_fileid, newname, NULL)) != 0)
- goto err;
- }
- if ((ret = __os_rename(dbenv, real_name, real_newname)) != 0)
- goto err;
- __os_freestr(real_name);
- __os_freestr(real_newname);
- real_name = real_newname = NULL;
}
-err:
- if (real_name != NULL)
- __os_freestr(real_name);
- if (real_newname != NULL)
- __os_freestr(real_newname);
- if (filelist != NULL)
- __os_free(filelist, 0);
+err: if (filelist != NULL)
+ __os_free(dbenv, filelist);
+ if (needclose) {
+ /* We copied this, so we mustn't free it. */
+ tmpdbp->lid = DB_LOCK_INVALIDID;
+ /* We need to remove the lockevent we associated with this. */
+ if (txn != NULL)
+ __txn_remlock(dbenv,
+ txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
+
+ if ((t_ret =
+ __db_close_i(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+ }
return (ret);
}
diff --git a/bdb/qam/qam_open.c b/bdb/qam/qam_open.c
index 73346439fd6..efe4dfc540e 100644
--- a/bdb/qam/qam_open.c
+++ b/bdb/qam/qam_open.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_open.c,v 11.31 2000/12/20 17:59:29 ubell Exp $";
+static const char revid[] = "$Id: qam_open.c,v 11.55 2002/09/04 19:06:45 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,174 +18,95 @@ static const char revid[] = "$Id: qam_open.c,v 11.31 2000/12/20 17:59:29 ubell E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "db_swap.h"
-#include "db_am.h"
-#include "lock.h"
-#include "qam.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/qam.h"
+#include "dbinc/fop.h"
+
+static int __qam_init_meta __P((DB *, QMETA *));
/*
* __qam_open
*
- * PUBLIC: int __qam_open __P((DB *, const char *, db_pgno_t, int, u_int32_t));
+ * PUBLIC: int __qam_open __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, db_pgno_t, int, u_int32_t));
*/
int
-__qam_open(dbp, name, base_pgno, mode, flags)
+__qam_open(dbp, txn, name, base_pgno, mode, flags)
DB *dbp;
+ DB_TXN *txn;
const char *name;
db_pgno_t base_pgno;
int mode;
u_int32_t flags;
{
- QUEUE *t;
DBC *dbc;
+ DB_ENV *dbenv;
DB_LOCK metalock;
- DB_LSN orig_lsn;
+ DB_MPOOLFILE *mpf;
QMETA *qmeta;
- int locked;
+ QUEUE *t;
int ret, t_ret;
- ret = 0;
- locked = 0;
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
t = dbp->q_internal;
+ ret = 0;
+ qmeta = NULL;
- if (name == NULL && t->page_ext != 0) {
- __db_err(dbp->dbenv,
- "Extent size may not be specified for in-memory queue database.");
- return (EINVAL);
- }
/* Initialize the remaining fields/methods of the DB. */
- dbp->del = __qam_delete;
- dbp->put = __qam_put;
dbp->stat = __qam_stat;
dbp->sync = __qam_sync;
dbp->db_am_remove = __qam_remove;
dbp->db_am_rename = __qam_rename;
- metalock.off = LOCK_INVALID;
-
/*
* Get a cursor. If DB_CREATE is specified, we may be creating
* pages, and to do that safely in CDB we need a write cursor.
* In STD_LOCKING mode, we'll synchronize using the meta page
* lock instead.
*/
- if ((ret = dbp->cursor(dbp, dbp->open_txn,
- &dbc, LF_ISSET(DB_CREATE) && CDB_LOCKING(dbp->dbenv) ?
- DB_WRITECURSOR : 0)) != 0)
+ if ((ret = dbp->cursor(dbp, txn, &dbc,
+ LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ? DB_WRITECURSOR : 0))
+ != 0)
return (ret);
- /* Get, and optionally create the metadata page. */
+ /*
+ * Get the meta data page. It must exist, because creates of
+ * files/databases come in through the __qam_new_file interface
+ * and queue doesn't support subdatabases.
+ */
if ((ret =
__db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
goto err;
- if ((ret = memp_fget(
- dbp->mpf, &base_pgno, DB_MPOOL_CREATE, (PAGE **)&qmeta)) != 0)
+ if ((ret =
+ mpf->get(mpf, &base_pgno, 0, (PAGE **)&qmeta)) != 0)
goto err;
- /*
- * If the magic number is correct, we're not creating the tree.
- * Correct any fields that may not be right. Note, all of the
- * local flags were set by DB->open.
- */
-again: if (qmeta->dbmeta.magic == DB_QAMMAGIC) {
- t->re_pad = qmeta->re_pad;
- t->re_len = qmeta->re_len;
- t->rec_page = qmeta->rec_page;
- t->page_ext = qmeta->page_ext;
-
- (void)memp_fput(dbp->mpf, (PAGE *)qmeta, 0);
- goto done;
- }
-
- /* If we're doing CDB; we now have to get the write lock. */
- if (CDB_LOCKING(dbp->dbenv)) {
- DB_ASSERT(LF_ISSET(DB_CREATE));
- if ((ret = lock_get(dbp->dbenv, dbc->locker, DB_LOCK_UPGRADE,
- &dbc->lock_dbt, DB_LOCK_WRITE, &dbc->mylock)) != 0)
- goto err;
- }
-
- /*
- * If we are doing locking, relase the read lock
- * and get a write lock. We want to avoid deadlock.
- */
- if (locked == 0 && STD_LOCKING(dbc)) {
- if ((ret = __LPUT(dbc, metalock)) != 0)
- goto err;
- if ((ret = __db_lget(dbc,
- 0, base_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
- goto err;
- locked = 1;
- goto again;
- }
- /* Initialize the tree structure metadata information. */
- orig_lsn = qmeta->dbmeta.lsn;
- memset(qmeta, 0, sizeof(QMETA));
- ZERO_LSN(qmeta->dbmeta.lsn);
- qmeta->dbmeta.pgno = base_pgno;
- qmeta->dbmeta.magic = DB_QAMMAGIC;
- qmeta->dbmeta.version = DB_QAMVERSION;
- qmeta->dbmeta.pagesize = dbp->pgsize;
- qmeta->dbmeta.type = P_QAMMETA;
- qmeta->re_pad = t->re_pad;
- qmeta->re_len = t->re_len;
- qmeta->rec_page = CALC_QAM_RECNO_PER_PAGE(dbp);
- qmeta->cur_recno = 1;
- qmeta->first_recno = 1;
- qmeta->page_ext = t->page_ext;
- t->rec_page = qmeta->rec_page;
- memcpy(qmeta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
-
- /* Verify that we can fit at least one record per page. */
- if (QAM_RECNO_PER_PAGE(dbp) < 1) {
- __db_err(dbp->dbenv,
- "Record size of %lu too large for page size of %lu",
- (u_long)t->re_len, (u_long)dbp->pgsize);
- (void)memp_fput(dbp->mpf, (PAGE *)qmeta, 0);
+ /* If the magic number is incorrect, that's a fatal error. */
+ if (qmeta->dbmeta.magic != DB_QAMMAGIC) {
+ __db_err(dbenv, "%s: unexpected file type or format", name);
ret = EINVAL;
goto err;
}
- if ((ret = __db_log_page(dbp,
- name, &orig_lsn, base_pgno, (PAGE *)qmeta)) != 0)
- goto err;
-
- /* Release the metadata page. */
- if ((ret = memp_fput(dbp->mpf, (PAGE *)qmeta, DB_MPOOL_DIRTY)) != 0)
- goto err;
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOG, ret, name);
-
- /*
- * Flush the metadata page to disk.
- *
- * !!!
- * It's not useful to return not-yet-flushed here -- convert it to
- * an error.
- */
- if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE) {
- __db_err(dbp->dbenv, "Flush of metapage failed");
- ret = EINVAL;
- }
- DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name);
-
-done: t->q_meta = base_pgno;
- t->q_root = base_pgno + 1;
-
/* Setup information needed to open extents. */
- if (t->page_ext != 0) {
- t->finfo.pgcookie = &t->pgcookie;
- t->finfo.fileid = NULL;
- t->finfo.lsn_offset = 0;
+ t->page_ext = qmeta->page_ext;
+ if (t->page_ext != 0) {
t->pginfo.db_pagesize = dbp->pgsize;
- t->pginfo.needswap = F_ISSET(dbp, DB_AM_SWAP);
+ t->pginfo.flags =
+ F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+ t->pginfo.type = dbp->type;
t->pgcookie.data = &t->pginfo;
t->pgcookie.size = sizeof(DB_PGINFO);
if ((ret = __os_strdup(dbp->dbenv, name, &t->path)) != 0)
- goto err;
+ return (ret);
t->dir = t->path;
if ((t->name = __db_rpath(t->path)) == NULL) {
t->name = t->path;
@@ -198,8 +119,22 @@ done: t->q_meta = base_pgno;
t->mode = mode;
}
-err:
-DB_TEST_RECOVERY_LABEL
+ if (name == NULL && t->page_ext != 0) {
+ __db_err(dbenv,
+ "Extent size may not be specified for in-memory queue database");
+ return (EINVAL);
+ }
+
+ t->re_pad = qmeta->re_pad;
+ t->re_len = qmeta->re_len;
+ t->rec_page = qmeta->rec_page;
+
+ t->q_meta = base_pgno;
+ t->q_root = base_pgno + 1;
+
+err: if (qmeta != NULL && (t_ret = mpf->put(mpf, qmeta, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
/* Don't hold the meta page long term. */
(void)__LPUT(dbc, metalock);
@@ -225,6 +160,7 @@ __qam_metachk(dbp, name, qmeta)
int ret;
dbenv = dbp->dbenv;
+ ret = 0;
/*
* At this point, all we know is that the magic number is for a Queue.
@@ -241,6 +177,7 @@ __qam_metachk(dbp, name, qmeta)
name, (u_long)vers);
return (DB_OLD_VERSION);
case 3:
+ case 4:
break;
default:
__db_err(dbenv,
@@ -264,5 +201,131 @@ __qam_metachk(dbp, name, qmeta)
/* Copy the file's ID. */
memcpy(dbp->fileid, qmeta->dbmeta.uid, DB_FILE_ID_LEN);
+ /* Set up AM-specific methods that do not require an open. */
+ dbp->db_am_rename = __qam_rename;
+ dbp->db_am_remove = __qam_remove;
+
+ return (ret);
+}
+
+/*
+ * __qam_init_meta --
+ * Initialize the meta-data for a Queue database.
+ */
+static int
+__qam_init_meta(dbp, meta)
+ DB *dbp;
+ QMETA *meta;
+{
+ QUEUE *t;
+
+ t = dbp->q_internal;
+
+ memset(meta, 0, sizeof(QMETA));
+ LSN_NOT_LOGGED(meta->dbmeta.lsn);
+ meta->dbmeta.pgno = PGNO_BASE_MD;
+ meta->dbmeta.last_pgno = 0;
+ meta->dbmeta.magic = DB_QAMMAGIC;
+ meta->dbmeta.version = DB_QAMVERSION;
+ meta->dbmeta.pagesize = dbp->pgsize;
+ if (F_ISSET(dbp, DB_AM_CHKSUM))
+ FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
+ if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
+ meta->dbmeta.encrypt_alg =
+ ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
+ DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
+ meta->crypto_magic = meta->dbmeta.magic;
+ }
+ meta->dbmeta.type = P_QAMMETA;
+ meta->re_pad = t->re_pad;
+ meta->re_len = t->re_len;
+ meta->rec_page = CALC_QAM_RECNO_PER_PAGE(dbp);
+ meta->cur_recno = 1;
+ meta->first_recno = 1;
+ meta->page_ext = t->page_ext;
+ t->rec_page = meta->rec_page;
+ memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
+
+ /* Verify that we can fit at least one record per page. */
+ if (QAM_RECNO_PER_PAGE(dbp) < 1) {
+ __db_err(dbp->dbenv,
+ "Record size of %lu too large for page size of %lu",
+ (u_long)t->re_len, (u_long)dbp->pgsize);
+ return (EINVAL);
+ }
+
return (0);
}
+
+/*
+ * __qam_new_file --
+ * Create the necessary pages to begin a new queue database file.
+ *
+ * This code appears more complex than it is because of the two cases (named
+ * and unnamed). The way to read the code is that for each page being created,
+ * there are three parts: 1) a "get page" chunk (which either uses malloc'd
+ * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
+ * chunk which either does a fop write or an mpf->put.
+ *
+ * PUBLIC: int __qam_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
+ */
+int
+__qam_new_file(dbp, txn, fhp, name)
+ DB *dbp;
+ DB_TXN *txn;
+ DB_FH *fhp;
+ const char *name;
+{
+ QMETA *meta;
+ DB_ENV *dbenv;
+ DB_MPOOLFILE *mpf;
+ DB_PGINFO pginfo;
+ DBT pdbt;
+ db_pgno_t pgno;
+ int ret;
+ void *buf;
+
+ dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ buf = NULL;
+ meta = NULL;
+
+ /* Build meta-data page. */
+
+ if (name == NULL) {
+ pgno = PGNO_BASE_MD;
+ ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &meta);
+ } else {
+ ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
+ meta = (QMETA *)buf;
+ }
+ if (ret != 0)
+ return (ret);
+
+ if ((ret = __qam_init_meta(dbp, meta)) != 0)
+ goto err;
+
+ if (name == NULL)
+ ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+ else {
+ pginfo.db_pagesize = dbp->pgsize;
+ pginfo.flags =
+ F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+ pginfo.type = DB_QUEUE;
+ pdbt.data = &pginfo;
+ pdbt.size = sizeof(pginfo);
+ if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
+ goto err;
+ ret = __fop_write(dbenv,
+ txn, name, DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
+ }
+ if (ret != 0)
+ goto err;
+ meta = NULL;
+
+err: if (name != NULL)
+ __os_free(dbenv, buf);
+ else if (meta != NULL)
+ (void)mpf->put(mpf, meta, 0);
+ return (ret);
+}
diff --git a/bdb/qam/qam_rec.c b/bdb/qam/qam_rec.c
index 4d330f58651..2c0f1227752 100644
--- a/bdb/qam/qam_rec.c
+++ b/bdb/qam/qam_rec.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_rec.c,v 11.34 2001/01/19 18:01:59 bostic Exp $";
+static const char revid[] = "$Id: qam_rec.c,v 11.69 2002/08/06 06:17:10 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,91 +18,12 @@ static const char revid[] = "$Id: qam_rec.c,v 11.34 2001/01/19 18:01:59 bostic E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "db_am.h"
-#include "qam.h"
-#include "log.h"
-
-/*
- * __qam_inc_recover --
- * Recovery function for inc.
- *
- * PUBLIC: int __qam_inc_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__qam_inc_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __qam_inc_args *argp;
- DB *file_dbp;
- DBC *dbc;
- DB_LOCK lock;
- DB_MPOOLFILE *mpf;
- QMETA *meta;
- db_pgno_t metapg;
- int cmp_p, modified, ret;
-
- COMPQUIET(info, NULL);
- REC_PRINT(__qam_inc_print);
- REC_INTRO(__qam_inc_read, 1);
-
- metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
-
- if ((ret = __db_lget(dbc,
- LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
- goto done;
- if ((ret = memp_fget(mpf, &metapg, 0, &meta)) != 0) {
- if (DB_REDO(op)) {
- if ((ret = memp_fget(mpf,
- &metapg, DB_MPOOL_CREATE, &meta)) != 0) {
- (void)__LPUT(dbc, lock);
- goto out;
- }
- meta->dbmeta.pgno = metapg;
- meta->dbmeta.type = P_QAMMETA;
-
- } else {
- *lsnp = argp->prev_lsn;
- ret = 0;
- (void)__LPUT(dbc, lock);
- goto out;
- }
- }
-
- modified = 0;
- cmp_p = log_compare(&LSN(meta), &argp->lsn);
- CHECK_LSN(op, cmp_p, &LSN(meta), &argp->lsn);
-
- /*
- * The cur_recno never goes backwards. It is a point of
- * contention among appenders. If one fails cur_recno will
- * most likely be beyond that one when it aborts.
- * We move it ahead on either an abort or a commit
- * and make the LSN reflect that fact.
- */
- if (cmp_p == 0) {
- modified = 1;
- meta->cur_recno++;
- if (meta->cur_recno == RECNO_OOB)
- meta->cur_recno++;
- meta->dbmeta.lsn = *lsnp;
- }
- if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)))
- goto out;
-
- (void)__LPUT(dbc, lock);
-
-done: *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: REC_CLOSE;
-}
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
/*
* __qam_incfirst_recover --
@@ -138,9 +59,9 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
if ((ret = __db_lget(dbc,
LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
goto done;
- if ((ret = memp_fget(mpf, &metapg, 0, &meta)) != 0) {
+ if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
if (DB_REDO(op)) {
- if ((ret = memp_fget(mpf,
+ if ((ret = mpf->get(mpf,
&metapg, DB_MPOOL_CREATE, &meta)) != 0) {
(void)__LPUT(dbc, lock);
goto out;
@@ -178,11 +99,11 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
cp = (QUEUE_CURSOR *)dbc->internal;
if (meta->first_recno == RECNO_OOB)
meta->first_recno++;
- while (meta->first_recno != meta->cur_recno
- && !QAM_BEFORE_FIRST(meta, argp->recno + 1)) {
+ while (meta->first_recno != meta->cur_recno &&
+ !QAM_BEFORE_FIRST(meta, argp->recno + 1)) {
if ((ret = __qam_position(dbc,
&meta->first_recno, QAM_READ, &exact)) != 0)
- goto out;
+ goto err;
if (cp->page != NULL)
__qam_fput(file_dbp, cp->pgno, cp->page, 0);
@@ -192,7 +113,7 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
rec_ext != 0 && meta->first_recno % rec_ext == 0)
if ((ret =
__qam_fremove(file_dbp, cp->pgno)) != 0)
- goto out;
+ goto err;
meta->first_recno++;
if (meta->first_recno == RECNO_OOB)
meta->first_recno++;
@@ -200,14 +121,19 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
}
}
- if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)))
- goto out;
+ if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto err1;
(void)__LPUT(dbc, lock);
done: *lsnp = argp->prev_lsn;
ret = 0;
+ if (0) {
+err: (void)mpf->put(mpf, meta, 0);
+err1: (void)__LPUT(dbc, lock);
+ }
+
out: REC_CLOSE;
}
@@ -233,7 +159,7 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf;
QMETA *meta;
db_pgno_t metapg;
- int cmp_p, modified, ret;
+ int cmp_n, cmp_p, modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__qam_mvptr_print);
@@ -244,9 +170,9 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
if ((ret = __db_lget(dbc,
LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
goto done;
- if ((ret = memp_fget(mpf, &metapg, 0, &meta)) != 0) {
+ if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
if (DB_REDO(op)) {
- if ((ret = memp_fget(mpf,
+ if ((ret = mpf->get(mpf,
&metapg, DB_MPOOL_CREATE, &meta)) != 0) {
(void)__LPUT(dbc, lock);
goto out;
@@ -262,13 +188,24 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
}
modified = 0;
- cmp_p = log_compare(&meta->dbmeta.lsn, &argp->metalsn);
+ cmp_n = log_compare(lsnp, &LSN(meta));
+ cmp_p = log_compare(&LSN(meta), &argp->metalsn);
/*
- * We never undo a movement of one of the pointers.
- * Just move them along regardless of abort/commit.
+ * Under normal circumstances, we never undo a movement of one of
+ * the pointers. Just move them along regardless of abort/commit.
+ *
+ * If we're undoing a truncate, we need to reset the pointers to
+ * their state before the truncate.
*/
- if (cmp_p == 0) {
+ if (DB_UNDO(op) && (argp->opcode & QAM_TRUNCATE)) {
+ if (cmp_n == 0) {
+ meta->first_recno = argp->old_first;
+ meta->cur_recno = argp->old_cur;
+ modified = 1;
+ meta->dbmeta.lsn = argp->metalsn;
+ }
+ } else if (cmp_p == 0) {
if (argp->opcode & QAM_SETFIRST)
meta->first_recno = argp->new_first;
@@ -279,7 +216,7 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
meta->dbmeta.lsn = *lsnp;
}
- if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)))
+ if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
(void)__LPUT(dbc, lock);
@@ -289,6 +226,7 @@ done: *lsnp = argp->prev_lsn;
out: REC_CLOSE;
}
+
/*
* __qam_del_recover --
* Recovery function for del.
@@ -321,7 +259,7 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
REC_INTRO(__qam_del_read, 1);
if ((ret = __qam_fget(file_dbp,
- &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
modified = 0;
@@ -338,20 +276,20 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
if ((ret = __db_lget(dbc,
LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
- return (ret);
- if ((ret = memp_fget(file_dbp->mpf, &metapg, 0, &meta)) != 0) {
+ goto err;
+ if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
(void)__LPUT(dbc, lock);
- goto done;
+ goto err;
}
if (meta->first_recno == RECNO_OOB ||
- (QAM_BEFORE_FIRST(meta, argp->recno)
- && (meta->first_recno <= meta->cur_recno
- || meta->first_recno -
+ (QAM_BEFORE_FIRST(meta, argp->recno) &&
+ (meta->first_recno <= meta->cur_recno ||
+ meta->first_recno -
argp->recno < argp->recno - meta->cur_recno))) {
meta->first_recno = argp->recno;
- (void)memp_fput(file_dbp->mpf, meta, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, meta, DB_MPOOL_DIRTY);
} else
- (void)memp_fput(file_dbp->mpf, meta, 0);
+ (void)mpf->put(mpf, meta, 0);
(void)__LPUT(dbc, lock);
/* Need to undo delete - mark the record as present */
@@ -366,7 +304,7 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
* is harmless in queue except when we're determining
* what we need to roll forward during recovery. [#2588]
*/
- if (op == DB_TXN_BACKWARD_ROLL && cmp_n < 0)
+ if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
LSN(pagep) = argp->lsn;
modified = 1;
} else if (cmp_n > 0 && DB_REDO(op)) {
@@ -377,14 +315,18 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
modified = 1;
}
if ((ret = __qam_fput(file_dbp,
- argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)))
+ argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done: *lsnp = argp->prev_lsn;
ret = 0;
+ if (0) {
+err: (void)__qam_fput(file_dbp, argp->pgno, pagep, 0);
+ }
out: REC_CLOSE;
}
+
/*
* __qam_delext_recover --
* Recovery function for del in an extent based queue.
@@ -415,9 +357,19 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
REC_PRINT(__qam_delext_print);
REC_INTRO(__qam_delext_read, 1);
- if ((ret = __qam_fget(file_dbp,
- &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
- goto out;
+ if ((ret = __qam_fget(file_dbp, &argp->pgno, 0, &pagep)) != 0) {
+ if (ret != DB_PAGE_NOTFOUND && ret != ENOENT)
+ goto out;
+ /*
+ * If we are redoing a delete and the page is not there
+ * we are done.
+ */
+ if (DB_REDO(op))
+ goto done;
+ if ((ret = __qam_fget(file_dbp,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+ }
modified = 0;
if (pagep->pgno == PGNO_INVALID) {
@@ -433,25 +385,25 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
if ((ret = __db_lget(dbc,
LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
- return (ret);
- if ((ret = memp_fget(file_dbp->mpf, &metapg, 0, &meta)) != 0) {
+ goto err;
+ if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
(void)__LPUT(dbc, lock);
- goto done;
+ goto err;
}
if (meta->first_recno == RECNO_OOB ||
- (QAM_BEFORE_FIRST(meta, argp->recno)
- && (meta->first_recno <= meta->cur_recno
- || meta->first_recno -
+ (QAM_BEFORE_FIRST(meta, argp->recno) &&
+ (meta->first_recno <= meta->cur_recno ||
+ meta->first_recno -
argp->recno < argp->recno - meta->cur_recno))) {
meta->first_recno = argp->recno;
- (void)memp_fput(file_dbp->mpf, meta, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, meta, DB_MPOOL_DIRTY);
} else
- (void)memp_fput(file_dbp->mpf, meta, 0);
+ (void)mpf->put(mpf, meta, 0);
(void)__LPUT(dbc, lock);
if ((ret = __qam_pitem(dbc, pagep,
argp->indx, argp->recno, &argp->data)) != 0)
- goto done;
+ goto err;
/*
* Move the LSN back to this point; do not move it forward.
@@ -461,7 +413,7 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
* is harmless in queue except when we're determining
* what we need to roll forward during recovery. [#2588]
*/
- if (op == DB_TXN_BACKWARD_ROLL && cmp_n < 0)
+ if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
LSN(pagep) = argp->lsn;
modified = 1;
} else if (cmp_n > 0 && DB_REDO(op)) {
@@ -472,12 +424,15 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
modified = 1;
}
if ((ret = __qam_fput(file_dbp,
- argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)))
+ argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done: *lsnp = argp->prev_lsn;
ret = 0;
+ if (0) {
+err: (void)__qam_fput(file_dbp, argp->pgno, pagep, 0);
+ }
out: REC_CLOSE;
}
@@ -485,7 +440,8 @@ out: REC_CLOSE;
* __qam_add_recover --
* Recovery function for add.
*
- * PUBLIC: int __qam_add_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ * PUBLIC: int __qam_add_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__qam_add_recover(dbenv, dbtp, lsnp, op, info)
@@ -503,16 +459,26 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info)
QMETA *meta;
QPAGE *pagep;
db_pgno_t metapg;
- int cmp_n, modified, ret;
+ int cmp_n, meta_dirty, modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__qam_add_print);
REC_INTRO(__qam_add_read, 1);
modified = 0;
- if ((ret = __qam_fget(file_dbp,
- &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
- goto out;
+ if ((ret = __qam_fget(file_dbp, &argp->pgno, 0, &pagep)) != 0) {
+ if (ret != DB_PAGE_NOTFOUND && ret != ENOENT)
+ goto out;
+ /*
+ * If we are undoing an append and the page is not there
+ * we are done.
+ */
+ if (DB_UNDO(op))
+ goto done;
+ if ((ret = __qam_fget(file_dbp,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+ }
if (pagep->pgno == PGNO_INVALID) {
pagep->pgno = argp->pgno;
@@ -522,25 +488,36 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info)
cmp_n = log_compare(lsnp, &LSN(pagep));
- if (cmp_n > 0 && DB_REDO(op)) {
- /* Need to redo add - put the record on page */
- if ((ret = __qam_pitem(dbc, pagep, argp->indx, argp->recno,
- &argp->data)) != 0)
- goto err;
- LSN(pagep) = *lsnp;
- modified = 1;
- /* Make sure first pointer includes this record. */
+ if (DB_REDO(op)) {
+ /* Fix meta-data page. */
metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
- if ((ret = memp_fget(mpf, &metapg, 0, &meta)) != 0)
+ if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0)
goto err;
+ meta_dirty = 0;
if (QAM_BEFORE_FIRST(meta, argp->recno)) {
meta->first_recno = argp->recno;
- if ((ret = memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0)
- goto err;
- } else
- if ((ret = memp_fput(mpf, meta, 0)) != 0)
- goto err;
+ meta_dirty = 1;
+ }
+ if (argp->recno == meta->cur_recno ||
+ QAM_AFTER_CURRENT(meta, argp->recno)) {
+ meta->cur_recno = argp->recno + 1;
+ meta_dirty = 1;
+ }
+ if ((ret =
+ mpf->put(mpf, meta, meta_dirty? DB_MPOOL_DIRTY : 0)) != 0)
+ goto err;
+ /* Now update the actual page if necessary. */
+ if (cmp_n > 0) {
+ /* Need to redo add - put the record on page */
+ if ((ret = __qam_pitem(dbc,
+ pagep, argp->indx, argp->recno, &argp->data)) != 0)
+ goto err;
+ LSN(pagep) = *lsnp;
+ modified = 1;
+ /* Make sure pointers include this record. */
+ metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
+ }
} else if (DB_UNDO(op)) {
/*
* Need to undo add
@@ -572,161 +549,20 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info)
* is harmless in queue except when we're determining
* what we need to roll forward during recovery. [#2588]
*/
- if (op == DB_TXN_BACKWARD_ROLL && cmp_n < 0)
+ if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
LSN(pagep) = argp->lsn;
}
-err: if ((ret = __qam_fput(file_dbp,
- argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)))
+ if ((ret = __qam_fput(file_dbp,
+ argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done: *lsnp = argp->prev_lsn;
ret = 0;
-out: REC_CLOSE;
-}
-/*
- * __qam_delete_recover --
- * Recovery function for delete of an extent.
- *
- * PUBLIC: int __qam_delete_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__qam_delete_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __qam_delete_args *argp;
- int ret;
- char *backup, *real_back, *real_name;
-
- COMPQUIET(info, NULL);
-
- REC_PRINT(__qam_delete_print);
-
- backup = real_back = real_name = NULL;
- if ((ret = __qam_delete_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
-
- if (DB_REDO(op)) {
- /*
- * On a recovery, as we recreate what was going on, we
- * recreate the creation of the file. And so, even though
- * it committed, we need to delete it. Try to delete it,
- * but it is not an error if that delete fails.
- */
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (__os_exists(real_name, NULL) == 0) {
- if ((ret = __os_unlink(dbenv, real_name)) != 0)
- goto out;
- }
- } else if (DB_UNDO(op)) {
- /*
- * Trying to undo. File may or may not have been deleted.
- * Try to move the backup to the original. If the backup
- * exists, then this is right. If it doesn't exist, then
- * nothing will happen and that's OK.
- */
- if ((ret = __db_backup_name(dbenv, argp->name.data,
- &backup, &argp->lsn)) != 0)
- goto out;
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
- goto out;
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (__os_exists(real_back, NULL) == 0)
- if ((ret =
- __os_rename(dbenv, real_back, real_name)) != 0)
- goto out;
- }
- *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: if (argp != NULL)
- __os_free(argp, 0);
- if (backup != NULL)
- __os_freestr(backup);
- if (real_back != NULL)
- __os_freestr(real_back);
- if (real_name != NULL)
- __os_freestr(real_name);
- return (ret);
-}
-/*
- * __qam_rename_recover --
- * Recovery function for rename.
- *
- * PUBLIC: int __qam_rename_recover
- * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__qam_rename_recover(dbenv, dbtp, lsnp, op, info)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops op;
- void *info;
-{
- __qam_rename_args *argp;
- char *new_name, *real_name;
- int ret;
-
- COMPQUIET(info, NULL);
-
- REC_PRINT(__qam_rename_print);
-
- new_name = real_name = NULL;
-
- if ((ret = __qam_rename_read(dbenv, dbtp->data, &argp)) != 0)
- goto out;
-
- if (DB_REDO(op)) {
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->name.data, 0, NULL, &real_name)) != 0)
- goto out;
- if (__os_exists(real_name, NULL) == 0) {
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, argp->newname.data,
- 0, NULL, &new_name)) != 0)
- goto out;
- if ((ret = __os_rename(dbenv,
- real_name, new_name)) != 0)
- goto out;
- }
- } else {
- if ((ret = __db_appname(dbenv, DB_APP_DATA,
- NULL, argp->newname.data, 0, NULL, &new_name)) != 0)
- goto out;
- if (__os_exists(new_name, NULL) == 0) {
- if ((ret = __db_appname(dbenv,
- DB_APP_DATA, NULL, argp->name.data,
- 0, NULL, &real_name)) != 0)
- goto out;
- if ((ret = __os_rename(dbenv,
- new_name, real_name)) != 0)
- goto out;
- }
+ if (0) {
+err: (void)__qam_fput(file_dbp, argp->pgno, pagep, 0);
}
- *lsnp = argp->prev_lsn;
- ret = 0;
-
-out: if (argp != NULL)
- __os_free(argp, 0);
-
- if (new_name != NULL)
- __os_free(new_name, 0);
-
- if (real_name != NULL)
- __os_free(real_name, 0);
-
- return (ret);
+out: REC_CLOSE;
}
diff --git a/bdb/qam/qam_stat.c b/bdb/qam/qam_stat.c
index 865f477c1eb..57c67da4292 100644
--- a/bdb/qam/qam_stat.c
+++ b/bdb/qam/qam_stat.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_stat.c,v 11.16 2001/01/10 04:50:54 ubell Exp $";
+static const char revid[] = "$Id: qam_stat.c,v 11.32 2002/05/11 13:40:11 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,32 +18,33 @@ static const char revid[] = "$Id: qam_stat.c,v 11.16 2001/01/10 04:50:54 ubell E
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_shash.h"
-#include "db_am.h"
-#include "lock.h"
-#include "qam.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
/*
* __qam_stat --
* Gather/print the qam statistics
*
- * PUBLIC: int __qam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
+ * PUBLIC: int __qam_stat __P((DB *, void *, u_int32_t));
*/
int
-__qam_stat(dbp, spp, db_malloc, flags)
+__qam_stat(dbp, spp, flags)
DB *dbp;
void *spp;
- void *(*db_malloc) __P((size_t));
u_int32_t flags;
{
- QUEUE *t;
DBC *dbc;
DB_LOCK lock;
+ DB_MPOOLFILE *mpf;
DB_QUEUE_STAT *sp;
PAGE *h;
QAMDATA *qp, *ep;
QMETA *meta;
+ QUEUE *t;
db_indx_t indx;
db_pgno_t first, last, pgno, pg_ext, stop;
u_int32_t re_len;
@@ -52,9 +53,10 @@ __qam_stat(dbp, spp, db_malloc, flags)
PANIC_CHECK(dbp->dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
- t = dbp->q_internal;
+ LOCK_INIT(lock);
+ mpf = dbp->mpf;
sp = NULL;
- lock.off = LOCK_INVALID;
+ t = dbp->q_internal;
/* Check for invalid flags. */
if ((ret = __db_statchk(dbp, flags)) != 0)
@@ -70,35 +72,29 @@ __qam_stat(dbp, spp, db_malloc, flags)
DEBUG_LWRITE(dbc, NULL, "qam_stat", NULL, NULL, flags);
/* Allocate and clear the structure. */
- if ((ret = __os_malloc(dbp->dbenv, sizeof(*sp), db_malloc, &sp)) != 0)
+ if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0)
goto err;
memset(sp, 0, sizeof(*sp));
re_len = ((QUEUE *)dbp->q_internal)->re_len;
- if (flags == DB_CACHED_COUNTS) {
- if ((ret = __db_lget(dbc,
- 0, t->q_meta, DB_LOCK_READ, 0, &lock)) != 0)
- goto err;
- if ((ret =
- memp_fget(dbp->mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
- goto err;
- sp->qs_nkeys = meta->dbmeta.key_count;
- sp->qs_ndata = meta->dbmeta.record_count;
-
- goto done;
- }
/* Determine the last page of the database. */
if ((ret = __db_lget(dbc,
0, t->q_meta, DB_LOCK_READ, 0, &lock)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
+ if ((ret = mpf->get(mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
goto err;
+ if (flags == DB_FAST_STAT || flags == DB_CACHED_COUNTS) {
+ sp->qs_nkeys = meta->dbmeta.key_count;
+ sp->qs_ndata = meta->dbmeta.record_count;
+ goto meta_only;
+ }
+
first = QAM_RECNO_PAGE(dbp, meta->first_recno);
last = QAM_RECNO_PAGE(dbp, meta->cur_recno);
- if ((ret = memp_fput(dbp->mpf, meta, 0)) != 0)
+ if ((ret = mpf->put(mpf, meta, 0)) != 0)
goto err;
(void)__LPUT(dbc, lock);
@@ -114,20 +110,23 @@ begin:
/* Walk through the pages and count. */
for (; pgno <= stop; ++pgno) {
if ((ret =
- __db_lget(dbc,
- 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
+ __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
goto err;
- ret = __qam_fget(dbp, &pgno, DB_MPOOL_EXTENT, &h);
+ ret = __qam_fget(dbp, &pgno, 0, &h);
if (ret == ENOENT) {
pgno += pg_ext - 1;
continue;
}
- if (ret == EINVAL) {
+ if (ret == DB_PAGE_NOTFOUND) {
+ if (pg_ext == 0) {
+ if (pgno != stop && first != last)
+ goto err;
+ ret = 0;
+ break;
+ }
pgno += pg_ext - ((pgno - 1) % pg_ext) - 1;
continue;
}
- if (ret == EIO && first == last && pg_ext == 0)
- break;
if (ret != 0)
goto err;
@@ -147,6 +146,8 @@ begin:
goto err;
(void)__LPUT(dbc, lock);
}
+
+ (void)__LPUT(dbc, lock);
if (first > last) {
pgno = 1;
stop = last;
@@ -159,26 +160,28 @@ begin:
0, t->q_meta, F_ISSET(dbp, DB_AM_RDONLY) ?
DB_LOCK_READ : DB_LOCK_WRITE, 0, &lock)) != 0)
goto err;
- if ((ret = memp_fget(dbp->mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
+ if ((ret = mpf->get(mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
goto err;
+ if (!F_ISSET(dbp, DB_AM_RDONLY))
+ meta->dbmeta.key_count =
+ meta->dbmeta.record_count = sp->qs_ndata;
+ sp->qs_nkeys = sp->qs_ndata;
+
+meta_only:
/* Get the metadata fields. */
sp->qs_magic = meta->dbmeta.magic;
sp->qs_version = meta->dbmeta.version;
sp->qs_metaflags = meta->dbmeta.flags;
sp->qs_pagesize = meta->dbmeta.pagesize;
+ sp->qs_extentsize = meta->page_ext;
sp->qs_re_len = meta->re_len;
sp->qs_re_pad = meta->re_pad;
sp->qs_first_recno = meta->first_recno;
sp->qs_cur_recno = meta->cur_recno;
- sp->qs_nkeys = sp->qs_ndata;
- if (!F_ISSET(dbp, DB_AM_RDONLY))
- meta->dbmeta.key_count =
- meta->dbmeta.record_count = sp->qs_ndata;
-done:
/* Discard the meta-data page. */
- if ((ret = memp_fput(dbp->mpf,
+ if ((ret = mpf->put(mpf,
meta, F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY)) != 0)
goto err;
(void)__LPUT(dbc, lock);
@@ -188,11 +191,10 @@ done:
if (0) {
err: if (sp != NULL)
- __os_free(sp, sizeof(*sp));
+ __os_ufree(dbp->dbenv, sp);
}
- if (lock.off != LOCK_INVALID)
- (void)__LPUT(dbc, lock);
+ (void)__LPUT(dbc, lock);
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
diff --git a/bdb/qam/qam_upgrade.c b/bdb/qam/qam_upgrade.c
index f49bfe88d90..6bd79fc948a 100644
--- a/bdb/qam/qam_upgrade.c
+++ b/bdb/qam/qam_upgrade.c
@@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_upgrade.c,v 11.7 2000/11/30 00:58:44 ubell Exp $";
+static const char revid[] = "$Id: qam_upgrade.c,v 11.12 2002/03/29 20:46:48 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,10 +18,7 @@ static const char revid[] = "$Id: qam_upgrade.c,v 11.7 2000/11/30 00:58:44 ubell
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_swap.h"
-#include "db_am.h"
-#include "db_upgrade.h"
+#include "dbinc/db_upgrade.h"
/*
* __qam_31_qammeta --
diff --git a/bdb/qam/qam_verify.c b/bdb/qam/qam_verify.c
index a9a467d6785..5b020c2c335 100644
--- a/bdb/qam/qam_verify.c
+++ b/bdb/qam/qam_verify.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: qam_verify.c,v 1.17 2000/12/12 17:39:35 bostic Exp $";
+static const char revid[] = "$Id: qam_verify.c,v 1.30 2002/06/26 20:49:27 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -17,10 +17,10 @@ static const char revid[] = "$Id: qam_verify.c,v 1.17 2000/12/12 17:39:35 bostic
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_verify.h"
-#include "qam.h"
-#include "db_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_verify.h"
+#include "dbinc/qam.h"
+#include "dbinc/db_am.h"
/*
* __qam_vrfy_meta --
@@ -49,7 +49,9 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
* something very odd is going on.
*/
if (!F_ISSET(pip, VRFY_INCOMPLETE))
- EPRINT((dbp->dbenv, "Queue databases must be one-per-file."));
+ EPRINT((dbp->dbenv,
+ "Page %lu: queue databases must be one-per-file",
+ (u_long)pgno));
/*
* cur_recno/rec_page
@@ -59,8 +61,9 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
if (vdp->last_pgno > 0 && meta->cur_recno > 0 &&
meta->cur_recno - 1 > meta->rec_page * vdp->last_pgno) {
EPRINT((dbp->dbenv,
- "Current recno %lu references record past last page number %lu",
- meta->cur_recno, vdp->last_pgno));
+ "Page %lu: current recno %lu references record past last page number %lu",
+ (u_long)pgno,
+ (u_long)meta->cur_recno, (u_long)vdp->last_pgno));
isbad = 1;
}
@@ -69,10 +72,10 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
* return DB_VERIFY_FATAL
*/
if (ALIGN(meta->re_len + sizeof(QAMDATA) - 1, sizeof(u_int32_t)) *
- meta->rec_page + sizeof(QPAGE) > dbp->pgsize) {
+ meta->rec_page + QPAGE_SZ(dbp) > dbp->pgsize) {
EPRINT((dbp->dbenv,
- "Queue record length %lu impossibly high for page size and records per page",
- meta->re_len));
+ "Page %lu: queue record length %lu too high for page size and recs/page",
+ (u_long)pgno, (u_long)meta->re_len));
ret = DB_VERIFY_FATAL;
goto err;
} else {
@@ -80,7 +83,8 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
vdp->rec_page = meta->rec_page;
}
-err: if ((t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
+err: if ((t_ret =
+ __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
ret = t_ret;
return (ret == 0 && isbad == 1 ? DB_VERIFY_BAD : ret);
}
@@ -114,14 +118,15 @@ __qam_vrfy_data(dbp, vdp, h, pgno, flags)
* some gross games to fake it out.
*/
fakedb.q_internal = &fakeq;
+ fakedb.flags = dbp->flags;
fakeq.re_len = vdp->re_len;
for (i = 0; i < vdp->rec_page; i++) {
qp = QAM_GET_RECORD(&fakedb, h, i);
if ((u_int8_t *)qp >= (u_int8_t *)h + dbp->pgsize) {
EPRINT((dbp->dbenv,
- "Queue record %lu extends past end of page %lu",
- i, pgno));
+ "Page %lu: queue record %lu extends past end of page",
+ (u_long)pgno, (u_long)i));
return (DB_VERIFY_BAD);
}
@@ -129,8 +134,8 @@ __qam_vrfy_data(dbp, vdp, h, pgno, flags)
qflags &= !(QAM_VALID | QAM_SET);
if (qflags != 0) {
EPRINT((dbp->dbenv,
- "Queue record %lu on page %lu has bad flags",
- i, pgno));
+ "Page %lu: queue record %lu has bad flags",
+ (u_long)pgno, (u_long)i));
return (DB_VERIFY_BAD);
}
}
@@ -161,7 +166,8 @@ __qam_vrfy_structure(dbp, vdp, flags)
if (pip->type != P_QAMMETA) {
EPRINT((dbp->dbenv,
- "Queue database has no meta page"));
+ "Page %lu: queue database has no meta page",
+ (u_long)PGNO_BASE_MD));
isbad = 1;
goto err;
}
@@ -174,21 +180,21 @@ __qam_vrfy_structure(dbp, vdp, flags)
if (!LF_ISSET(DB_SALVAGE))
__db_vrfy_struct_feedback(dbp, vdp);
- if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 ||
+ if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
(ret = __db_vrfy_getpageinfo(vdp, i, &pip)) != 0)
return (ret);
if (!F_ISSET(pip, VRFY_IS_ALLZEROES) &&
pip->type != P_QAMDATA) {
EPRINT((dbp->dbenv,
- "Queue database page %lu of incorrect type %lu",
- i, pip->type));
+ "Page %lu: queue database page of incorrect type %lu",
+ (u_long)i, (u_long)pip->type));
isbad = 1;
goto err;
} else if ((ret = __db_vrfy_pgset_inc(vdp->pgset, i)) != 0)
goto err;
}
-err: if ((ret = __db_vrfy_putpageinfo(vdp, pip)) != 0)
+err: if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
return (ret);
return (isbad == 1 ? DB_VERIFY_BAD : 0);
}
diff --git a/bdb/rep/rep_method.c b/bdb/rep/rep_method.c
new file mode 100644
index 00000000000..6773a537f4f
--- /dev/null
+++ b/bdb/rep/rep_method.c
@@ -0,0 +1,1144 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: rep_method.c,v 1.78 2002/09/10 12:58:07 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+
+#ifdef HAVE_RPC
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
+#endif
+
+static int __rep_abort_prepared __P((DB_ENV *));
+static int __rep_bt_cmp __P((DB *, const DBT *, const DBT *));
+static int __rep_client_dbinit __P((DB_ENV *, int));
+static int __rep_elect __P((DB_ENV *, int, int, u_int32_t, int *));
+static int __rep_elect_init __P((DB_ENV *, DB_LSN *, int, int, int, int *));
+static int __rep_flush __P((DB_ENV *));
+static int __rep_restore_prepared __P((DB_ENV *));
+static int __rep_set_limit __P((DB_ENV *, u_int32_t, u_int32_t));
+static int __rep_set_request __P((DB_ENV *, u_int32_t, u_int32_t));
+static int __rep_set_rep_transport __P((DB_ENV *, int,
+ int (*)(DB_ENV *, const DBT *, const DBT *, int, u_int32_t)));
+static int __rep_start __P((DB_ENV *, DBT *, u_int32_t));
+static int __rep_stat __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
+static int __rep_wait __P((DB_ENV *, u_int32_t, int *, u_int32_t));
+
+/*
+ * __rep_dbenv_create --
+ * Replication-specific initialization of the DB_ENV structure.
+ *
+ * PUBLIC: int __rep_dbenv_create __P((DB_ENV *));
+ */
+int
+__rep_dbenv_create(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_REP *db_rep;
+ int ret;
+
+#ifdef HAVE_RPC
+ if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+ COMPQUIET(db_rep, NULL);
+ COMPQUIET(ret, 0);
+ dbenv->rep_elect = __dbcl_rep_elect;
+ dbenv->rep_flush = __dbcl_rep_flush;
+ dbenv->rep_process_message = __dbcl_rep_process_message;
+ dbenv->rep_start = __dbcl_rep_start;
+ dbenv->rep_stat = __dbcl_rep_stat;
+ dbenv->set_rep_limit = __dbcl_rep_set_limit;
+ dbenv->set_rep_request = __dbcl_rep_set_request;
+ dbenv->set_rep_transport = __dbcl_rep_set_rep_transport;
+
+ } else
+#endif
+ {
+ dbenv->rep_elect = __rep_elect;
+ dbenv->rep_flush = __rep_flush;
+ dbenv->rep_process_message = __rep_process_message;
+ dbenv->rep_start = __rep_start;
+ dbenv->rep_stat = __rep_stat;
+ dbenv->set_rep_limit = __rep_set_limit;
+ dbenv->set_rep_request = __rep_set_request;
+ dbenv->set_rep_transport = __rep_set_rep_transport;
+ /*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ */
+
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_REP), &db_rep)) != 0)
+ return (ret);
+ dbenv->rep_handle = db_rep;
+
+ /* Initialize the per-process replication structure. */
+ db_rep->rep_send = NULL;
+ }
+
+ return (0);
+}
+
+/*
+ * __rep_start --
+ * Become a master or client, and start sending messages to participate
+ * in the replication environment. Must be called after the environment
+ * is open.
+ */
+static int
+__rep_start(dbenv, dbt, flags)
+ DB_ENV *dbenv;
+ DBT *dbt;
+ u_int32_t flags;
+{
+ DB_LOG *dblp;
+ DB_LSN lsn;
+ DB_REP *db_rep;
+ REP *rep;
+ int announce, init_db, redo_prepared, ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_ILLEGAL_BEFORE_OPEN(dbenv, "rep_start");
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+
+ if ((ret = __db_fchk(dbenv, "DB_ENV->rep_start", flags,
+ DB_REP_CLIENT | DB_REP_LOGSONLY | DB_REP_MASTER)) != 0)
+ return (ret);
+
+ /* Exactly one of CLIENT and MASTER must be specified. */
+ if ((ret = __db_fcchk(dbenv,
+ "DB_ENV->rep_start", flags, DB_REP_CLIENT, DB_REP_MASTER)) != 0)
+ return (ret);
+ if (!LF_ISSET(DB_REP_CLIENT | DB_REP_MASTER | DB_REP_LOGSONLY)) {
+ __db_err(dbenv,
+ "DB_ENV->rep_start: replication mode must be specified");
+ return (EINVAL);
+ }
+
+ /* Masters can't be logs-only. */
+ if ((ret = __db_fcchk(dbenv,
+ "DB_ENV->rep_start", flags, DB_REP_LOGSONLY, DB_REP_MASTER)) != 0)
+ return (ret);
+
+ /* We need a transport function. */
+ if (db_rep->rep_send == NULL) {
+ __db_err(dbenv,
+ "DB_ENV->set_rep_transport must be called before DB_ENV->rep_start");
+ return (EINVAL);
+ }
+
+ /* We'd better not have any logged files open if we are a client. */
+ if (LF_ISSET(DB_REP_CLIENT) && (ret = __dbreg_nofiles(dbenv)) != 0) {
+ __db_err(dbenv, "DB_ENV->rep_start called with open files");
+ return (ret);
+ }
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ if (rep->eid == DB_EID_INVALID)
+ rep->eid = dbenv->rep_eid;
+
+ if (LF_ISSET(DB_REP_MASTER)) {
+ if (F_ISSET(dbenv, DB_ENV_REP_CLIENT)) {
+ /*
+ * If we're upgrading from having been a client,
+ * preclose, so that we close our temporary database.
+ *
+ * Do not close files that we may have opened while
+ * doing a rep_apply; they'll get closed when we
+ * finally close the environment, but for now, leave
+ * them open, as we don't want to recycle their
+ * fileids, and we may need the handles again if
+ * we become a client and the original master
+ * that opened them becomes a master again.
+ */
+ if ((ret = __rep_preclose(dbenv, 0)) != 0)
+ return (ret);
+
+ /*
+ * Now write a __txn_recycle record so that
+ * clients don't get confused with our txnids
+ * and txnids of previous masters.
+ */
+ F_CLR(dbenv, DB_ENV_REP_CLIENT);
+ if ((ret = __txn_reset(dbenv)) != 0)
+ return (ret);
+ }
+
+ redo_prepared = 0;
+ if (!F_ISSET(rep, REP_F_MASTER)) {
+ /* Master is not yet set. */
+ if (F_ISSET(rep, REP_ISCLIENT)) {
+ F_CLR(rep, REP_ISCLIENT);
+ rep->gen = ++rep->w_gen;
+ redo_prepared = 1;
+ } else if (rep->gen == 0)
+ rep->gen = 1;
+ }
+
+ F_SET(rep, REP_F_MASTER);
+ F_SET(dbenv, DB_ENV_REP_MASTER);
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ dblp = (DB_LOG *)dbenv->lg_handle;
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = ((LOG *)dblp->reginfo.primary)->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ /*
+ * Send the NEWMASTER message, then restore prepared txns
+ * if and only if we just upgraded from being a client.
+ */
+ if ((ret = __rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0)) == 0 &&
+ redo_prepared)
+ ret = __rep_restore_prepared(dbenv);
+ } else {
+ F_CLR(dbenv, DB_ENV_REP_MASTER);
+ F_SET(dbenv, DB_ENV_REP_CLIENT);
+ if (LF_ISSET(DB_REP_LOGSONLY))
+ F_SET(dbenv, DB_ENV_REP_LOGSONLY);
+
+ announce = !F_ISSET(rep, REP_ISCLIENT) ||
+ rep->master_id == DB_EID_INVALID;
+ init_db = 0;
+ if (!F_ISSET(rep, REP_ISCLIENT)) {
+ F_CLR(rep, REP_F_MASTER);
+ if (LF_ISSET(DB_REP_LOGSONLY))
+ F_SET(rep, REP_F_LOGSONLY);
+ else
+ F_SET(rep, REP_F_UPGRADE);
+
+ /*
+ * We initialize the client's generation number to 0.
+ * Upon startup, it looks for a master and updates the
+ * generation number as necessary, exactly as it does
+ * during normal operation and a master failure.
+ */
+ rep->gen = 0;
+ rep->master_id = DB_EID_INVALID;
+ init_db = 1;
+ }
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ /*
+ * Abort any prepared transactions that were restored
+ * by recovery. We won't be able to create any txns of
+ * our own until they're resolved, but we can't resolve
+ * them ourselves; the master has to. If any get
+ * resolved as commits, we'll redo them when commit
+ * records come in. Aborts will simply be ignored.
+ */
+ if ((ret = __rep_abort_prepared(dbenv)) != 0)
+ return (ret);
+
+ if ((ret = __rep_client_dbinit(dbenv, init_db)) != 0)
+ return (ret);
+
+ /*
+ * If this client created a newly replicated environment,
+ * then announce the existence of this client. The master
+ * should respond with a message that will tell this client
+ * the current generation number and the current LSN. This
+ * will allow the client to either perform recovery or
+ * simply join in.
+ */
+ if (announce)
+ ret = __rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_NEWCLIENT, NULL, dbt, 0);
+ }
+ return (ret);
+}
+
+/*
+ * __rep_client_dbinit --
+ *
+ * Initialize the LSN database on the client side. This is called from the
+ * client initialization code. The startup flag value indicates if
+ * this is the first thread/process starting up and therefore should create
+ * the LSN database. This routine must be called once by each process acting
+ * as a client.
+ */
+static int
+__rep_client_dbinit(dbenv, startup)
+ DB_ENV *dbenv;
+ int startup;
+{
+ DB_REP *db_rep;
+ DB *dbp;
+ int ret, t_ret;
+ u_int32_t flags;
+
+ PANIC_CHECK(dbenv);
+ db_rep = dbenv->rep_handle;
+ dbp = NULL;
+
+#define REPDBNAME "__db.rep.db"
+
+ /* Check if this has already been called on this environment. */
+ if (db_rep->rep_db != NULL)
+ return (0);
+
+ MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+
+ if (startup) {
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ goto err;
+ /*
+ * Ignore errors, because if the file doesn't exist, this
+ * is perfectly OK.
+ */
+ (void)dbp->remove(dbp, REPDBNAME, NULL, 0);
+ }
+
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ goto err;
+ if ((ret = dbp->set_bt_compare(dbp, __rep_bt_cmp)) != 0)
+ goto err;
+
+ /* Allow writes to this database on a client. */
+ F_SET(dbp, DB_AM_CL_WRITER);
+
+ flags = (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0) |
+ (startup ? DB_CREATE : 0);
+ if ((ret = dbp->open(dbp, NULL,
+ "__db.rep.db", NULL, DB_BTREE, flags, 0)) != 0)
+ goto err;
+
+ db_rep->rep_db = dbp;
+
+ if (0) {
+err: if (dbp != NULL &&
+ (t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+ ret = t_ret;
+ db_rep->rep_db = NULL;
+ }
+
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+ return (ret);
+}
+
+/*
+ * __rep_bt_cmp --
+ *
+ * Comparison function for the LSN table. We use the entire control
+ * structure as a key (for simplicity, so we don't have to merge the
+ * other fields in the control with the data field), but really only
+ * care about the LSNs.
+ */
+static int
+__rep_bt_cmp(dbp, dbt1, dbt2)
+ DB *dbp;
+ const DBT *dbt1, *dbt2;
+{
+ DB_LSN lsn1, lsn2;
+ REP_CONTROL *rp1, *rp2;
+
+ COMPQUIET(dbp, NULL);
+
+ rp1 = dbt1->data;
+ rp2 = dbt2->data;
+
+ __ua_memcpy(&lsn1, &rp1->lsn, sizeof(DB_LSN));
+ __ua_memcpy(&lsn2, &rp2->lsn, sizeof(DB_LSN));
+
+ if (lsn1.file > lsn2.file)
+ return (1);
+
+ if (lsn1.file < lsn2.file)
+ return (-1);
+
+ if (lsn1.offset > lsn2.offset)
+ return (1);
+
+ if (lsn1.offset < lsn2.offset)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * __rep_abort_prepared --
+ * Abort any prepared transactions that recovery restored.
+ *
+ * This is used by clients that have just run recovery, since
+ * they cannot/should not call txn_recover and handle prepared transactions
+ * themselves.
+ */
+static int
+__rep_abort_prepared(dbenv)
+ DB_ENV *dbenv;
+{
+#define PREPLISTSIZE 50
+ DB_PREPLIST prep[PREPLISTSIZE], *p;
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+ int do_aborts, ret;
+ long count, i;
+ u_int32_t op;
+
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+
+ do_aborts = 0;
+ R_LOCK(dbenv, &mgr->reginfo);
+ if (region->stat.st_nrestores != 0)
+ do_aborts = 1;
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ if (do_aborts) {
+ op = DB_FIRST;
+ do {
+ if ((ret = dbenv->txn_recover(dbenv,
+ prep, PREPLISTSIZE, &count, op)) != 0)
+ return (ret);
+ for (i = 0; i < count; i++) {
+ p = &prep[i];
+ if ((ret = p->txn->abort(p->txn)) != 0)
+ return (ret);
+ }
+ op = DB_NEXT;
+ } while (count == PREPLISTSIZE);
+ }
+
+ return (0);
+}
+
+/*
+ * __rep_restore_prepared --
+ * Restore to a prepared state any prepared but not yet committed
+ * transactions.
+ *
+ * This performs, in effect, a "mini-recovery"; it is called from
+ * __rep_start by newly upgraded masters. There may be transactions that an
+ * old master prepared but did not resolve, which we need to restore to an
+ * active state.
+ */
+static int
+__rep_restore_prepared(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_LOGC *logc;
+ DB_LSN ckp_lsn, lsn;
+ DBT rec;
+ __txn_ckp_args *ckp_args;
+ __txn_regop_args *regop_args;
+ __txn_xa_regop_args *prep_args;
+ int ret, t_ret;
+ u_int32_t hi_txn, low_txn, rectype;
+ void *txninfo;
+
+ txninfo = NULL;
+ ckp_args = NULL;
+ prep_args = NULL;
+ regop_args = NULL;
+ ZERO_LSN(ckp_lsn);
+ ZERO_LSN(lsn);
+
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+
+ /*
+ * We need to consider the set of records between the most recent
+ * checkpoint LSN and the end of the log; any txn in that
+ * range, and only txns in that range, could still have been
+ * active, and thus prepared but not yet committed (PBNYC),
+ * when the old master died.
+ *
+ * Find the most recent checkpoint LSN, and get the record there.
+ * If there is no checkpoint in the log, start off by getting
+ * the very first record in the log instead.
+ */
+ memset(&rec, 0, sizeof(DBT));
+ if ((ret = __txn_getckp(dbenv, &lsn)) == 0) {
+ if ((ret = logc->get(logc, &lsn, &rec, DB_SET)) != 0) {
+ __db_err(dbenv,
+ "Checkpoint record at LSN [%lu][%lu] not found",
+ (u_long)lsn.file, (u_long)lsn.offset);
+ goto err;
+ }
+
+ if ((ret = __txn_ckp_read(dbenv, rec.data, &ckp_args)) != 0) {
+ __db_err(dbenv,
+ "Invalid checkpoint record at [%lu][%lu]",
+ (u_long)lsn.file, (u_long)lsn.offset);
+ goto err;
+ }
+
+ ckp_lsn = ckp_args->ckp_lsn;
+ __os_free(dbenv, ckp_args);
+
+ if ((ret = logc->get(logc, &ckp_lsn, &rec, DB_SET)) != 0) {
+ __db_err(dbenv,
+ "Checkpoint LSN record [%lu][%lu] not found",
+ (u_long)ckp_lsn.file, (u_long)ckp_lsn.offset);
+ goto err;
+ }
+ } else if ((ret = logc->get(logc, &lsn, &rec, DB_FIRST)) != 0) {
+ if (ret == DB_NOTFOUND) {
+ /* An empty log means no PBNYC txns. */
+ ret = 0;
+ goto done;
+ }
+ __db_err(dbenv, "Attempt to get first log record failed");
+ goto err;
+ }
+
+ /*
+ * We use the same txnlist infrastructure that recovery does;
+ * it demands an estimate of the high and low txnids for
+ * initialization.
+ *
+ * First, the low txnid.
+ */
+ do {
+ /* txnid is after rectype, which is a u_int32. */
+ memcpy(&low_txn,
+ (u_int8_t *)rec.data + sizeof(u_int32_t), sizeof(low_txn));
+ if (low_txn != 0)
+ break;
+ } while ((ret = logc->get(logc, &lsn, &rec, DB_NEXT)) == 0);
+
+ /* If there are no txns, there are no PBNYC txns. */
+ if (ret == DB_NOTFOUND) {
+ ret = 0;
+ goto done;
+ } else if (ret != 0)
+ goto err;
+
+ /* Now, the high txnid. */
+ if ((ret = logc->get(logc, &lsn, &rec, DB_LAST)) != 0) {
+ /*
+ * Note that DB_NOTFOUND is unacceptable here because we
+ * had to have looked at some log record to get this far.
+ */
+ __db_err(dbenv, "Final log record not found");
+ goto err;
+ }
+ do {
+ /* txnid is after rectype, which is a u_int32. */
+ memcpy(&hi_txn,
+ (u_int8_t *)rec.data + sizeof(u_int32_t), sizeof(hi_txn));
+ if (hi_txn != 0)
+ break;
+ } while ((ret = logc->get(logc, &lsn, &rec, DB_PREV)) == 0);
+ if (ret == DB_NOTFOUND) {
+ ret = 0;
+ goto done;
+ } else if (ret != 0)
+ goto err;
+
+ /* We have a high and low txnid. Initialise the txn list. */
+ if ((ret =
+ __db_txnlist_init(dbenv, low_txn, hi_txn, NULL, &txninfo)) != 0)
+ goto err;
+
+ /*
+ * Now, walk backward from the end of the log to ckp_lsn. Any
+ * prepares that we hit without first hitting a commit or
+ * abort belong to PBNYC txns, and we need to apply them and
+ * restore them to a prepared state.
+ *
+ * Note that we wind up applying transactions out of order.
+ * Since all PBNYC txns still held locks on the old master and
+ * were isolated, this should be safe.
+ */
+ for (ret = logc->get(logc, &lsn, &rec, DB_LAST);
+ ret == 0 && log_compare(&lsn, &ckp_lsn) > 0;
+ ret = logc->get(logc, &lsn, &rec, DB_PREV)) {
+ memcpy(&rectype, rec.data, sizeof(rectype));
+ switch (rectype) {
+ case DB___txn_regop:
+ /*
+ * It's a commit or abort--but we don't care
+ * which! Just add it to the list of txns
+ * that are resolved.
+ */
+ if ((ret = __txn_regop_read(dbenv, rec.data,
+ &regop_args)) != 0)
+ goto err;
+
+ ret = __db_txnlist_find(dbenv,
+ txninfo, regop_args->txnid->txnid);
+ if (ret == DB_NOTFOUND)
+ ret = __db_txnlist_add(dbenv, txninfo,
+ regop_args->txnid->txnid,
+ regop_args->opcode, &lsn);
+ __os_free(dbenv, regop_args);
+ break;
+ case DB___txn_xa_regop:
+ /*
+ * It's a prepare. If we haven't put the
+ * txn on our list yet, it hasn't been
+ * resolved, so apply and restore it.
+ */
+ if ((ret = __txn_xa_regop_read(dbenv, rec.data,
+ &prep_args)) != 0)
+ goto err;
+ ret = __db_txnlist_find(dbenv, txninfo,
+ prep_args->txnid->txnid);
+ if (ret == DB_NOTFOUND)
+ if ((ret = __rep_process_txn(dbenv, &rec)) == 0)
+ ret = __txn_restore_txn(dbenv,
+ &lsn, prep_args);
+ __os_free(dbenv, prep_args);
+ break;
+ default:
+ continue;
+ }
+ }
+
+ /* It's not an error to have hit the beginning of the log. */
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+
+done:
+err: t_ret = logc->close(logc, 0);
+
+ if (txninfo != NULL)
+ __db_txnlist_end(dbenv, txninfo);
+
+ return (ret == 0 ? t_ret : ret);
+}
+
+/*
+ * __rep_set_limit --
+ * Set a limit on the amount of data that will be sent during a single
+ * invocation of __rep_process_message.
+ */
+static int
+__rep_set_limit(dbenv, gbytes, bytes)
+ DB_ENV *dbenv;
+ u_int32_t gbytes;
+ u_int32_t bytes;
+{
+ DB_REP *db_rep;
+ REP *rep;
+
+ PANIC_CHECK(dbenv);
+
+ if ((db_rep = dbenv->rep_handle) == NULL) {
+ __db_err(dbenv,
+ "DB_ENV->set_rep_limit: database environment not properly initialized");
+ return (__db_panic(dbenv, EINVAL));
+ }
+ rep = db_rep->region;
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ if (bytes > GIGABYTE) {
+ gbytes += bytes / GIGABYTE;
+ bytes = bytes % GIGABYTE;
+ }
+ rep->gbytes = gbytes;
+ rep->bytes = bytes;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ return (0);
+}
+
+/*
+ * __rep_set_request --
+ * Set the minimum and maximum number of log records that we wait
+ * before retransmitting.
+ * UNDOCUMENTED.
+ */
+static int
+__rep_set_request(dbenv, min, max)
+ DB_ENV *dbenv;
+ u_int32_t min;
+ u_int32_t max;
+{
+ LOG *lp;
+ DB_LOG *dblp;
+ DB_REP *db_rep;
+ REP *rep;
+
+ PANIC_CHECK(dbenv);
+
+ if ((db_rep = dbenv->rep_handle) == NULL) {
+ __db_err(dbenv,
+ "DB_ENV->set_rep_request: database environment not properly initialized");
+ return (__db_panic(dbenv, EINVAL));
+ }
+ rep = db_rep->region;
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ rep->request_gap = min;
+ rep->max_gap = max;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ dblp = dbenv->lg_handle;
+ if (dblp != NULL && (lp = dblp->reginfo.primary) != NULL) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp->wait_recs = 0;
+ lp->rcvd_recs = 0;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ }
+
+ return (0);
+}
+
+/*
+ * __rep_set_transport --
+ * Set the transport function for replication.
+ */
+static int
+__rep_set_rep_transport(dbenv, eid, f_send)
+ DB_ENV *dbenv;
+ int eid;
+ int (*f_send) __P((DB_ENV *, const DBT *, const DBT *, int, u_int32_t));
+{
+ DB_REP *db_rep;
+
+ PANIC_CHECK(dbenv);
+
+ if ((db_rep = dbenv->rep_handle) == NULL) {
+ __db_err(dbenv,
+ "DB_ENV->set_rep_transport: database environment not properly initialized");
+ return (__db_panic(dbenv, EINVAL));
+ }
+
+ if (f_send == NULL) {
+ __db_err(dbenv,
+ "DB_ENV->set_rep_transport: no send function specified");
+ return (EINVAL);
+ }
+
+ if (eid < 0) {
+ __db_err(dbenv,
+ "DB_ENV->set_rep_transport: eid must be greater than or equal to 0");
+ return (EINVAL);
+ }
+
+ db_rep->rep_send = f_send;
+
+ dbenv->rep_eid = eid;
+ return (0);
+}
+
+/*
+ * __rep_elect --
+ * Called after master failure to hold/participate in an election for
+ * a new master.
+ */
+static int
+__rep_elect(dbenv, nsites, priority, timeout, eidp)
+ DB_ENV *dbenv;
+ int nsites, priority;
+ u_int32_t timeout;
+ int *eidp;
+{
+ DB_LOG *dblp;
+ DB_LSN lsn;
+ DB_REP *db_rep;
+ REP *rep;
+ int in_progress, ret, send_vote, tiebreaker;
+ u_int32_t pid, sec, usec;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_elect", DB_INIT_TXN);
+
+ /* Error checking. */
+ if (nsites <= 0) {
+ __db_err(dbenv,
+ "DB_ENV->rep_elect: nsites must be greater than 0");
+ return (EINVAL);
+ }
+ if (priority < 0) {
+ __db_err(dbenv,
+ "DB_ENV->rep_elect: priority may not be negative");
+ return (EINVAL);
+ }
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+ dblp = dbenv->lg_handle;
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = ((LOG *)dblp->reginfo.primary)->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ /* Generate a randomized tiebreaker value. */
+ __os_id(&pid);
+ if ((ret = __os_clock(dbenv, &sec, &usec)) != 0)
+ return (ret);
+ tiebreaker = pid ^ sec ^ usec ^ (u_int)rand() ^ P_TO_UINT32(&pid);
+
+ if ((ret = __rep_elect_init(dbenv,
+ &lsn, nsites, priority, tiebreaker, &in_progress)) != 0) {
+ if (ret == DB_REP_NEWMASTER) {
+ ret = 0;
+ *eidp = dbenv->rep_eid;
+ }
+ return (ret);
+ }
+
+ if (!in_progress) {
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "Beginning an election");
+#endif
+ if ((ret = __rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_ELECT, NULL, NULL, 0)) != 0)
+ goto err;
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTSEND, ret, NULL);
+ }
+
+ /* Now send vote */
+ if ((ret =
+ __rep_send_vote(dbenv, &lsn, nsites, priority, tiebreaker)) != 0)
+ goto err;
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTVOTE1, ret, NULL);
+
+ ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE1);
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTWAIT1, ret, NULL);
+ switch (ret) {
+ case 0:
+ /* Check if election complete or phase complete. */
+ if (*eidp != DB_EID_INVALID)
+ return (0);
+ goto phase2;
+ case DB_TIMEOUT:
+ break;
+ default:
+ goto err;
+ }
+ /*
+ * If we got here, we haven't heard from everyone, but we've
+ * run out of time, so it's time to decide if we have enough
+ * votes to pick a winner and if so, to send out a vote to
+ * the winner.
+ */
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ send_vote = DB_EID_INVALID;
+ if (rep->sites > rep->nsites / 2) {
+ /* We think we've seen enough to cast a vote. */
+ send_vote = rep->winner;
+ if (rep->winner == rep->eid)
+ rep->votes++;
+ F_CLR(rep, REP_F_EPHASE1);
+ F_SET(rep, REP_F_EPHASE2);
+ }
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ if (send_vote == DB_EID_INVALID) {
+ /* We do not have enough votes to elect. */
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv,
+ "Not enough votes to elect: received %d of %d",
+ rep->sites, rep->nsites);
+#endif
+ ret = DB_REP_UNAVAIL;
+ goto err;
+
+ }
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION) &&
+ send_vote != rep->eid)
+ __db_err(dbenv, "Sending vote");
+#endif
+
+ if (send_vote != rep->eid && (ret = __rep_send_message(dbenv,
+ send_vote, REP_VOTE2, NULL, NULL, 0)) != 0)
+ goto err;
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTVOTE2, ret, NULL);
+
+phase2: ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE2);
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTWAIT2, ret, NULL);
+ switch (ret) {
+ case 0:
+ return (0);
+ case DB_TIMEOUT:
+ ret = DB_REP_UNAVAIL;
+ break;
+ default:
+ goto err;
+ }
+
+DB_TEST_RECOVERY_LABEL
+err: MUTEX_LOCK(dbenv, db_rep->mutexp);
+ ELECTION_DONE(rep);
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "Ended election with %d", ret);
+#endif
+ return (ret);
+}
+
+/*
+ * __rep_elect_init
+ * Initialize an election. Sets beginp non-zero if the election is
+ * already in progress; makes it 0 otherwise.
+ */
+static int
+__rep_elect_init(dbenv, lsnp, nsites, priority, tiebreaker, beginp)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+ int nsites, priority, tiebreaker, *beginp;
+{
+ DB_REP *db_rep;
+ REP *rep;
+ int ret, *tally;
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+
+ ret = 0;
+
+ /* We may miscount, as we don't hold the replication mutex here. */
+ rep->stat.st_elections++;
+
+ /* If we are already a master; simply broadcast that fact and return. */
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+ (void)__rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_NEWMASTER, lsnp, NULL, 0);
+ rep->stat.st_elections_won++;
+ return (DB_REP_NEWMASTER);
+ }
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ *beginp = IN_ELECTION(rep);
+ if (!*beginp) {
+ /*
+ * Make sure that we always initialize all the election fields
+ * before putting ourselves in an election state. That means
+ * issuing calls that can fail (allocation) before setting all
+ * the variables.
+ */
+ if (nsites > rep->asites &&
+ (ret = __rep_grow_sites(dbenv, nsites)) != 0)
+ goto err;
+ DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTINIT, ret, NULL);
+ rep->nsites = nsites;
+ rep->priority = priority;
+ rep->votes = 0;
+ rep->master_id = DB_EID_INVALID;
+ F_SET(rep, REP_F_EPHASE1);
+
+ /* We have always heard from ourselves. */
+ rep->sites = 1;
+ tally = R_ADDR((REGINFO *)dbenv->reginfo, rep->tally_off);
+ tally[0] = rep->eid;
+
+ if (priority != 0) {
+ /* Make ourselves the winner to start. */
+ rep->winner = rep->eid;
+ rep->w_priority = priority;
+ rep->w_gen = rep->gen;
+ rep->w_lsn = *lsnp;
+ rep->w_tiebreaker = tiebreaker;
+ } else {
+ rep->winner = DB_EID_INVALID;
+ rep->w_priority = 0;
+ rep->w_gen = 0;
+ ZERO_LSN(rep->w_lsn);
+ rep->w_tiebreaker = 0;
+ }
+ }
+DB_TEST_RECOVERY_LABEL
+err: MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (ret);
+}
+
+static int
+__rep_wait(dbenv, timeout, eidp, flags)
+ DB_ENV *dbenv;
+ u_int32_t timeout;
+ int *eidp;
+ u_int32_t flags;
+{
+ DB_REP *db_rep;
+ REP *rep;
+ int done, ret;
+ u_int32_t sleeptime;
+
+ done = 0;
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+
+ /*
+ * The user specifies an overall timeout function, but checking
+ * is cheap and the timeout may be a generous upper bound.
+ * Sleep repeatedly for the smaller of .5s and timeout/10.
+ */
+ sleeptime = (timeout > 5000000) ? 500000 : timeout / 10;
+ if (sleeptime == 0)
+ sleeptime++;
+ while (timeout > 0) {
+ if ((ret = __os_sleep(dbenv, 0, sleeptime)) != 0)
+ return (ret);
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ done = !F_ISSET(rep, flags) && rep->master_id != DB_EID_INVALID;
+
+ *eidp = rep->master_id;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ if (done)
+ return (0);
+
+ if (timeout > sleeptime)
+ timeout -= sleeptime;
+ else
+ timeout = 0;
+ }
+ return (DB_TIMEOUT);
+}
+
+/*
+ * __rep_flush --
+ * Re-push the last log record to all clients, in case they've lost
+ * messages and don't know it.
+ */
+static int
+__rep_flush(dbenv)
+ DB_ENV *dbenv;
+{
+ DBT rec;
+ DB_LOGC *logc;
+ DB_LSN lsn;
+ int ret, t_ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+
+ memset(&rec, 0, sizeof(rec));
+ memset(&lsn, 0, sizeof(lsn));
+
+ if ((ret = logc->get(logc, &lsn, &rec, DB_LAST)) != 0)
+ goto err;
+
+ ret = __rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_LOG, &lsn, &rec, 0);
+
+err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+}
+
+/*
+ * __rep_stat --
+ * Fetch replication statistics.
+ */
+static int
+__rep_stat(dbenv, statp, flags)
+ DB_ENV *dbenv;
+ DB_REP_STAT **statp;
+ u_int32_t flags;
+{
+ DB_LOG *dblp;
+ DB_REP *db_rep;
+ DB_REP_STAT *stats;
+ LOG *lp;
+ REP *rep;
+ u_int32_t queued;
+ int ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ *statp = NULL;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->rep_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
+
+ /* Allocate a stat struct to return to the user. */
+ if ((ret = __os_umalloc(dbenv, sizeof(DB_REP_STAT), &stats)) != 0)
+ return (ret);
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ memcpy(stats, &rep->stat, sizeof(*stats));
+
+ /* Copy out election stats. */
+ if (IN_ELECTION(rep)) {
+ if (F_ISSET(rep, REP_F_EPHASE1))
+ stats->st_election_status = 1;
+ else if (F_ISSET(rep, REP_F_EPHASE2))
+ stats->st_election_status = 2;
+
+ stats->st_election_nsites = rep->sites;
+ stats->st_election_cur_winner = rep->winner;
+ stats->st_election_priority = rep->w_priority;
+ stats->st_election_gen = rep->w_gen;
+ stats->st_election_lsn = rep->w_lsn;
+ stats->st_election_votes = rep->votes;
+ stats->st_election_tiebreaker = rep->w_tiebreaker;
+ }
+
+ /* Copy out other info that's protected by the rep mutex. */
+ stats->st_env_id = rep->eid;
+ stats->st_env_priority = rep->priority;
+ stats->st_nsites = rep->nsites;
+ stats->st_master = rep->master_id;
+ stats->st_gen = rep->gen;
+
+ if (F_ISSET(rep, REP_F_MASTER))
+ stats->st_status = DB_REP_MASTER;
+ else if (F_ISSET(rep, REP_F_LOGSONLY))
+ stats->st_status = DB_REP_LOGSONLY;
+ else if (F_ISSET(rep, REP_F_UPGRADE))
+ stats->st_status = DB_REP_CLIENT;
+ else
+ stats->st_status = 0;
+
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ queued = rep->stat.st_log_queued;
+ memset(&rep->stat, 0, sizeof(rep->stat));
+ rep->stat.st_log_queued = rep->stat.st_log_queued_total =
+ rep->stat.st_log_queued_max = queued;
+ }
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ /*
+ * Log-related replication info is stored in the log system and
+ * protected by the log region lock.
+ */
+ R_LOCK(dbenv, &dblp->reginfo);
+ if (F_ISSET(rep, REP_ISCLIENT)) {
+ stats->st_next_lsn = lp->ready_lsn;
+ stats->st_waiting_lsn = lp->waiting_lsn;
+ } else {
+ if (F_ISSET(rep, REP_F_MASTER))
+ stats->st_next_lsn = lp->lsn;
+ else
+ ZERO_LSN(stats->st_next_lsn);
+ ZERO_LSN(stats->st_waiting_lsn);
+ }
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ *statp = stats;
+ return (0);
+}
diff --git a/bdb/rep/rep_record.c b/bdb/rep/rep_record.c
new file mode 100644
index 00000000000..d3619f509b4
--- /dev/null
+++ b/bdb/rep/rep_record.c
@@ -0,0 +1,1513 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: rep_record.c,v 1.111 2002/09/11 19:39:11 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+
+static int __rep_apply __P((DB_ENV *, REP_CONTROL *, DBT *));
+static int __rep_collect_txn __P((DB_ENV *, DB_LSN *, LSN_COLLECTION *));
+static int __rep_lsn_cmp __P((const void *, const void *));
+static int __rep_newfile __P((DB_ENV *, REP_CONTROL *, DBT *, DB_LSN *));
+
+#define IS_SIMPLE(R) ((R) != DB___txn_regop && \
+ (R) != DB___txn_ckp && (R) != DB___dbreg_register)
+
+/*
+ * __rep_process_message --
+ *
+ * This routine takes an incoming message and processes it.
+ *
+ * control: contains the control fields from the record
+ * rec: contains the actual record
+ * eidp: contains the machine id of the sender of the message;
+ * in the case of a DB_NEWMASTER message, returns the eid
+ * of the new master.
+ *
+ * PUBLIC: int __rep_process_message __P((DB_ENV *, DBT *, DBT *, int *));
+ */
+int
+__rep_process_message(dbenv, control, rec, eidp)
+ DB_ENV *dbenv;
+ DBT *control, *rec;
+ int *eidp;
+{
+ DB_LOG *dblp;
+ DB_LOGC *logc;
+ DB_LSN init_lsn, lsn, newfilelsn, oldfilelsn;
+ DB_REP *db_rep;
+ DBT *d, data_dbt, lsndbt, mylog;
+ LOG *lp;
+ REP *rep;
+ REP_CONTROL *rp;
+ REP_VOTE_INFO *vi;
+ u_int32_t bytes, gen, gbytes, type, unused;
+ int check_limit, cmp, done, do_req, i;
+ int master, old, recovering, ret, t_ret, *tally;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+
+ /* Control argument must be non-Null. */
+ if (control == NULL || control->size == 0) {
+ __db_err(dbenv,
+ "DB_ENV->rep_process_message: control argument must be specified");
+ return (EINVAL);
+ }
+
+ ret = 0;
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ gen = rep->gen;
+ recovering = F_ISSET(rep, REP_F_RECOVER);
+
+ rep->stat.st_msgs_processed++;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ rp = (REP_CONTROL *)control->data;
+
+#if 0
+ __rep_print_message(dbenv, *eidp, rp, "rep_process_message");
+#endif
+
+ /* Complain if we see an improper version number. */
+ if (rp->rep_version != DB_REPVERSION) {
+ __db_err(dbenv,
+ "unexpected replication message version %d, expected %d",
+ rp->rep_version, DB_REPVERSION);
+ return (EINVAL);
+ }
+ if (rp->log_version != DB_LOGVERSION) {
+ __db_err(dbenv,
+ "unexpected log record version %d, expected %d",
+ rp->log_version, DB_LOGVERSION);
+ return (EINVAL);
+ }
+
+ /*
+ * Check for generation number matching. Ignore any old messages
+ * except requests that are indicative of a new client that needs
+ * to get in sync.
+ */
+ if (rp->gen < gen && rp->rectype != REP_ALIVE_REQ &&
+ rp->rectype != REP_NEWCLIENT && rp->rectype != REP_MASTER_REQ) {
+ /*
+ * We don't hold the rep mutex, and could miscount if we race.
+ */
+ rep->stat.st_msgs_badgen++;
+ return (0);
+ }
+ if (rp->gen > gen && rp->rectype != REP_ALIVE &&
+ rp->rectype != REP_NEWMASTER)
+ return (__rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_MASTER_REQ, NULL, NULL, 0));
+
+ /*
+ * We need to check if we're in recovery and if we are
+ * then we need to ignore any messages except VERIFY, VOTE,
+ * ELECT (the master might fail while we are recovering), and
+ * ALIVE_REQ.
+ */
+ if (recovering)
+ switch(rp->rectype) {
+ case REP_ALIVE:
+ case REP_ALIVE_REQ:
+ case REP_ELECT:
+ case REP_NEWCLIENT:
+ case REP_NEWMASTER:
+ case REP_NEWSITE:
+ case REP_VERIFY:
+ R_LOCK(dbenv, &dblp->reginfo);
+ cmp = log_compare(&lp->verify_lsn, &rp->lsn);
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (cmp != 0)
+ goto skip;
+ /* FALLTHROUGH */
+ case REP_VOTE1:
+ case REP_VOTE2:
+ break;
+ default:
+skip: /*
+ * We don't hold the rep mutex, and could
+ * miscount if we race.
+ */
+ rep->stat.st_msgs_recover++;
+
+ /* Check for need to retransmit. */
+ R_LOCK(dbenv, &dblp->reginfo);
+ do_req = *eidp == rep->master_id &&
+ ++lp->rcvd_recs >= lp->wait_recs;
+ if (do_req) {
+ lp->wait_recs *= 2;
+ if (lp->wait_recs + rep->max_gap)
+ lp->wait_recs = rep->max_gap;
+ lp->rcvd_recs = 0;
+ lsn = lp->verify_lsn;
+ }
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (do_req)
+ ret = __rep_send_message(dbenv, *eidp,
+ REP_VERIFY_REQ, &lsn, NULL, 0);
+
+ return (ret);
+ }
+
+ switch(rp->rectype) {
+ case REP_ALIVE:
+ ANYSITE(dbenv);
+ if (rp->gen > gen && rp->flags)
+ return (__rep_new_master(dbenv, rp, *eidp));
+ break;
+ case REP_ALIVE_REQ:
+ ANYSITE(dbenv);
+ dblp = dbenv->lg_handle;
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = ((LOG *)dblp->reginfo.primary)->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (__rep_send_message(dbenv,
+ *eidp, REP_ALIVE, &lsn, NULL,
+ F_ISSET(dbenv, DB_ENV_REP_MASTER) ? 1 : 0));
+ case REP_ALL_REQ:
+ MASTER_ONLY(dbenv);
+ gbytes = bytes = 0;
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ gbytes = rep->gbytes;
+ bytes = rep->bytes;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ check_limit = gbytes != 0 || bytes != 0;
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ memset(&data_dbt, 0, sizeof(data_dbt));
+ oldfilelsn = lsn = rp->lsn;
+ type = REP_LOG;
+ for (ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET);
+ ret == 0 && type == REP_LOG;
+ ret = logc->get(logc, &lsn, &data_dbt, DB_NEXT)) {
+ /*
+ * lsn.offset will only be 0 if this is the
+ * beginning of the log; DB_SET, but not DB_NEXT,
+ * can set the log cursor to [n][0].
+ */
+ if (lsn.offset == 0)
+ ret = __rep_send_message(dbenv, *eidp,
+ REP_NEWFILE, &lsn, NULL, 0);
+ else {
+ /*
+ * DB_NEXT will never run into offsets
+ * of 0; thus, when a log file changes,
+ * we'll have a real log record with
+ * some lsn [n][m], and we'll also want to send
+ * a NEWFILE message with lsn [n][0].
+ * So that the client can detect gaps,
+ * send in the rec parameter the
+ * last LSN in the old file.
+ */
+ if (lsn.file != oldfilelsn.file) {
+ newfilelsn.file = lsn.file;
+ newfilelsn.offset = 0;
+
+ memset(&lsndbt, 0, sizeof(DBT));
+ lsndbt.size = sizeof(DB_LSN);
+ lsndbt.data = &oldfilelsn;
+
+ if ((ret = __rep_send_message(dbenv,
+ *eidp, REP_NEWFILE, &newfilelsn,
+ &lsndbt, 0)) != 0)
+ break;
+ }
+ if (check_limit) {
+ /*
+ * data_dbt.size is only the size of
+ * the log record; it doesn't count
+ * the size of the control structure.
+ * Factor that in as well so we're
+ * not off by a lot if our log
+ * records are small.
+ */
+ while (bytes < data_dbt.size +
+ sizeof(REP_CONTROL)) {
+ if (gbytes > 0) {
+ bytes += GIGABYTE;
+ --gbytes;
+ continue;
+ }
+ /*
+ * We don't hold the rep mutex,
+ * and may miscount.
+ */
+ rep->stat.st_nthrottles++;
+ type = REP_LOG_MORE;
+ goto send;
+ }
+ bytes -= (data_dbt.size +
+ sizeof(REP_CONTROL));
+ }
+send: ret = __rep_send_message(dbenv, *eidp,
+ type, &lsn, &data_dbt, 0);
+ }
+
+ /*
+ * In case we're about to change files and need it
+ * for a NEWFILE message, save the current LSN.
+ */
+ oldfilelsn = lsn;
+ }
+
+ if (ret == DB_NOTFOUND)
+ ret = 0;
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+ case REP_ELECT:
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ rep->gen++;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (__rep_send_message(dbenv,
+ *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+ }
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ ret = IN_ELECTION(rep) ? 0 : DB_REP_HOLDELECTION;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (ret);
+#ifdef NOTYET
+ case REP_FILE: /* TODO */
+ CLIENT_ONLY(dbenv);
+ break;
+ case REP_FILE_REQ:
+ MASTER_ONLY(dbenv);
+ return (__rep_send_file(dbenv, rec, *eidp));
+ break;
+#endif
+ case REP_LOG:
+ case REP_LOG_MORE:
+ CLIENT_ONLY(dbenv);
+ if ((ret = __rep_apply(dbenv, rp, rec)) != 0)
+ return (ret);
+ if (rp->rectype == REP_LOG_MORE) {
+ MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+ master = rep->master_id;
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ ret = __rep_send_message(dbenv, master,
+ REP_ALL_REQ, &lsn, NULL, 0);
+ }
+ return (ret);
+ case REP_LOG_REQ:
+ MASTER_ONLY(dbenv);
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ memset(&data_dbt, 0, sizeof(data_dbt));
+ lsn = rp->lsn;
+
+ /*
+ * There are three different cases here.
+ * 1. We asked for a particular LSN and got it.
+ * 2. We asked for an LSN of X,0 which is invalid and got the
+ * first log record in a particular file.
+ * 3. We asked for an LSN and it's not found because it is
+ * beyond the end of a log file and we need a NEWFILE msg.
+ */
+ ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET);
+ cmp = log_compare(&lsn, &rp->lsn);
+
+ if (ret == 0 && cmp == 0) /* Case 1 */
+ ret = __rep_send_message(dbenv, *eidp,
+ REP_LOG, &rp->lsn, &data_dbt, 0);
+ else if (ret == DB_NOTFOUND ||
+ (ret == 0 && cmp < 0 && rp->lsn.offset == 0))
+ /* Cases 2 and 3: Send a NEWFILE message. */
+ ret = __rep_send_message(dbenv, *eidp,
+ REP_NEWFILE, &lsn, NULL, 0);
+
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+ case REP_NEWSITE:
+ /* We don't hold the rep mutex, and may miscount. */
+ rep->stat.st_newsites++;
+
+ /* This is a rebroadcast; simply tell the application. */
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ (void)__rep_send_message(dbenv,
+ *eidp, REP_NEWMASTER, &lsn, NULL, 0);
+ }
+ return (DB_REP_NEWSITE);
+ case REP_NEWCLIENT:
+ /*
+ * This message was received and should have resulted in the
+ * application entering the machine ID in its machine table.
+ * We respond to this with an ALIVE to send relevant information
+ * to the new client. But first, broadcast the new client's
+ * record to all the clients.
+ */
+ if ((ret = __rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_NEWSITE, &rp->lsn, rec, 0)) != 0)
+ return (ret);
+
+ if (F_ISSET(dbenv, DB_ENV_REP_CLIENT))
+ return (0);
+
+ /* FALLTHROUGH */
+ case REP_MASTER_REQ:
+ ANYSITE(dbenv);
+ if (F_ISSET(dbenv, DB_ENV_REP_CLIENT))
+ return (0);
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (__rep_send_message(dbenv,
+ *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+ case REP_NEWFILE:
+ CLIENT_ONLY(dbenv);
+ return (__rep_apply(dbenv, rp, rec));
+ case REP_NEWMASTER:
+ ANYSITE(dbenv);
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER) &&
+ *eidp != dbenv->rep_eid) {
+ /* We don't hold the rep mutex, and may miscount. */
+ rep->stat.st_dupmasters++;
+ return (DB_REP_DUPMASTER);
+ }
+ return (__rep_new_master(dbenv, rp, *eidp));
+ case REP_PAGE: /* TODO */
+ CLIENT_ONLY(dbenv);
+ break;
+ case REP_PAGE_REQ: /* TODO */
+ MASTER_ONLY(dbenv);
+ break;
+ case REP_PLIST: /* TODO */
+ CLIENT_ONLY(dbenv);
+ break;
+ case REP_PLIST_REQ: /* TODO */
+ MASTER_ONLY(dbenv);
+ break;
+ case REP_VERIFY:
+ CLIENT_ONLY(dbenv);
+ DB_ASSERT((F_ISSET(rep, REP_F_RECOVER) &&
+ !IS_ZERO_LSN(lp->verify_lsn)) ||
+ (!F_ISSET(rep, REP_F_RECOVER) &&
+ IS_ZERO_LSN(lp->verify_lsn)));
+ if (IS_ZERO_LSN(lp->verify_lsn))
+ return (0);
+
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ memset(&mylog, 0, sizeof(mylog));
+ if ((ret = logc->get(logc, &rp->lsn, &mylog, DB_SET)) != 0)
+ goto rep_verify_err;
+ if (mylog.size == rec->size &&
+ memcmp(mylog.data, rec->data, rec->size) == 0) {
+ /*
+ * If we're a logs-only client, we can simply truncate
+ * the log to the point where it last agreed with the
+ * master's; otherwise, recover to that point.
+ */
+ R_LOCK(dbenv, &dblp->reginfo);
+ ZERO_LSN(lp->verify_lsn);
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) {
+ INIT_LSN(init_lsn);
+ if ((ret = dbenv->log_flush(dbenv,
+ &rp->lsn)) != 0 ||
+ (ret = __log_vtruncate(dbenv,
+ &rp->lsn, &init_lsn)) != 0)
+ goto rep_verify_err;
+ } else if ((ret = __db_apprec(dbenv, &rp->lsn, 0)) != 0)
+ goto rep_verify_err;
+
+ /*
+ * The log has been truncated (either by __db_apprec or
+ * directly). We want to make sure we're waiting for
+ * the LSN at the new end-of-log, not some later point.
+ */
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp->ready_lsn = lp->lsn;
+ ZERO_LSN(lp->waiting_lsn);
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ /*
+ * Discard any log records we have queued; we're
+ * about to re-request them, and can't trust the
+ * ones in the queue.
+ */
+ MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+ if ((ret = db_rep->rep_db->truncate(db_rep->rep_db,
+ NULL, &unused, 0)) != 0) {
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+ goto rep_verify_err;
+ }
+ rep->stat.st_log_queued = 0;
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ F_CLR(rep, REP_F_RECOVER);
+
+ /*
+ * If the master_id is invalid, this means that since
+ * the last record was sent, somebody declared an
+ * election and we may not have a master to request
+ * things of.
+ *
+ * This is not an error; when we find a new master,
+ * we'll re-negotiate where the end of the log is and
+ * try to bring ourselves up to date again anyway.
+ */
+ if ((master = rep->master_id) == DB_EID_INVALID) {
+ DB_ASSERT(IN_ELECTION(rep));
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ ret = 0;
+ } else {
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ ret = __rep_send_message(dbenv, master,
+ REP_ALL_REQ, &rp->lsn, NULL, 0);
+ }
+ } else if ((ret =
+ logc->get(logc, &lsn, &mylog, DB_PREV)) == 0) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp->verify_lsn = lsn;
+ lp->rcvd_recs = 0;
+ lp->wait_recs = rep->request_gap;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ ret = __rep_send_message(dbenv,
+ *eidp, REP_VERIFY_REQ, &lsn, NULL, 0);
+ }
+
+rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+ case REP_VERIFY_FAIL:
+ rep->stat.st_outdated++;
+ return (DB_REP_OUTDATED);
+ case REP_VERIFY_REQ:
+ MASTER_ONLY(dbenv);
+ type = REP_VERIFY;
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ d = &data_dbt;
+ memset(d, 0, sizeof(data_dbt));
+ F_SET(logc, DB_LOG_SILENT_ERR);
+ ret = logc->get(logc, &rp->lsn, d, DB_SET);
+ /*
+ * If the LSN was invalid, then we might get a not
+ * found, we might get an EIO, we could get anything.
+ * If we get a DB_NOTFOUND, then there is a chance that
+ * the LSN comes before the first file present in which
+ * case we need to return a fail so that the client can return
+ * a DB_OUTDATED.
+ */
+ if (ret == DB_NOTFOUND &&
+ __log_is_outdated(dbenv, rp->lsn.file, &old) == 0 &&
+ old != 0)
+ type = REP_VERIFY_FAIL;
+
+ if (ret != 0)
+ d = NULL;
+
+ ret = __rep_send_message(dbenv, *eidp, type, &rp->lsn, d, 0);
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+ case REP_VOTE1:
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "Master received vote");
+#endif
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (__rep_send_message(dbenv,
+ *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+ }
+
+ vi = (REP_VOTE_INFO *)rec->data;
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+
+ /*
+ * If you get a vote and you're not in an election, simply
+ * return an indicator to hold an election which will trigger
+ * this site to send its vote again.
+ */
+ if (!IN_ELECTION(rep)) {
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv,
+ "Not in election, but received vote1");
+#endif
+ ret = DB_REP_HOLDELECTION;
+ goto unlock;
+ }
+
+ if (F_ISSET(rep, REP_F_EPHASE2))
+ goto unlock;
+
+ /* Check if this site knows about more sites than we do. */
+ if (vi->nsites > rep->nsites)
+ rep->nsites = vi->nsites;
+
+ /* Check if we've heard from this site already. */
+ tally = R_ADDR((REGINFO *)dbenv->reginfo, rep->tally_off);
+ for (i = 0; i < rep->sites; i++) {
+ if (tally[i] == *eidp)
+ /* Duplicate vote. */
+ goto unlock;
+ }
+
+ /*
+ * We are keeping vote, let's see if that changes our count of
+ * the number of sites.
+ */
+ if (rep->sites + 1 > rep->nsites)
+ rep->nsites = rep->sites + 1;
+ if (rep->nsites > rep->asites &&
+ (ret = __rep_grow_sites(dbenv, rep->nsites)) != 0)
+ goto unlock;
+
+ tally[rep->sites] = *eidp;
+ rep->sites++;
+
+ /*
+ * Change winners if the incoming record has a higher
+ * priority, or an equal priority but a larger LSN, or
+ * an equal priority and LSN but higher "tiebreaker" value.
+ */
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) {
+ __db_err(dbenv,
+ "%s(eid)%d (pri)%d (gen)%d (sites)%d [%d,%d]",
+ "Existing vote: ",
+ rep->winner, rep->w_priority, rep->w_gen,
+ rep->sites, rep->w_lsn.file, rep->w_lsn.offset);
+ __db_err(dbenv,
+ "Incoming vote: (eid)%d (pri)%d (gen)%d [%d,%d]",
+ *eidp, vi->priority, rp->gen, rp->lsn.file,
+ rp->lsn.offset);
+ }
+#endif
+ cmp = log_compare(&rp->lsn, &rep->w_lsn);
+ if (vi->priority > rep->w_priority ||
+ (vi->priority != 0 && vi->priority == rep->w_priority &&
+ (cmp > 0 ||
+ (cmp == 0 && vi->tiebreaker > rep->w_tiebreaker)))) {
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "Accepting new vote");
+#endif
+ rep->winner = *eidp;
+ rep->w_priority = vi->priority;
+ rep->w_lsn = rp->lsn;
+ rep->w_gen = rp->gen;
+ }
+ master = rep->winner;
+ lsn = rep->w_lsn;
+ done = rep->sites == rep->nsites && rep->w_priority != 0;
+ if (done) {
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) {
+ __db_err(dbenv, "Phase1 election done");
+ __db_err(dbenv, "Voting for %d%s",
+ master, master == rep->eid ? "(self)" : "");
+ }
+#endif
+ F_CLR(rep, REP_F_EPHASE1);
+ F_SET(rep, REP_F_EPHASE2);
+ }
+
+ if (done && master == rep->eid) {
+ rep->votes++;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (0);
+ }
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ /* Vote for someone else. */
+ if (done)
+ return (__rep_send_message(dbenv,
+ master, REP_VOTE2, NULL, NULL, 0));
+
+ /* Election is still going on. */
+ break;
+ case REP_VOTE2:
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "We received a vote%s",
+ F_ISSET(dbenv, DB_ENV_REP_MASTER) ?
+ " (master)" : "");
+#endif
+ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ rep->stat.st_elections_won++;
+ return (__rep_send_message(dbenv,
+ *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+ }
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+
+ /* If we have priority 0, we should never get a vote. */
+ DB_ASSERT(rep->priority != 0);
+
+ if (!IN_ELECTION(rep)) {
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "Not in election, got vote");
+#endif
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (DB_REP_HOLDELECTION);
+ }
+ /* avoid counting duplicates. */
+ rep->votes++;
+ done = rep->votes > rep->nsites / 2;
+ if (done) {
+ rep->master_id = rep->eid;
+ rep->gen = rep->w_gen + 1;
+ ELECTION_DONE(rep);
+ F_CLR(rep, REP_F_UPGRADE);
+ F_SET(rep, REP_F_MASTER);
+ *eidp = rep->master_id;
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv,
+ "Got enough votes to win; election done; winner is %d",
+ rep->master_id);
+#endif
+ }
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ if (done) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ lsn = lp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ /* Declare me the winner. */
+#ifdef DIAGNOSTIC
+ if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
+ __db_err(dbenv, "I won, sending NEWMASTER");
+#endif
+ rep->stat.st_elections_won++;
+ if ((ret = __rep_send_message(dbenv, DB_EID_BROADCAST,
+ REP_NEWMASTER, &lsn, NULL, 0)) != 0)
+ break;
+ return (DB_REP_NEWMASTER);
+ }
+ break;
+ default:
+ __db_err(dbenv,
+ "DB_ENV->rep_process_message: unknown replication message: type %lu",
+ (u_long)rp->rectype);
+ return (EINVAL);
+ }
+
+ return (0);
+
+unlock: MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (ret);
+}
+
+/*
+ * __rep_apply --
+ *
+ * Handle incoming log records on a client, applying when possible and
+ * entering into the bookkeeping table otherwise. This is the guts of
+ * the routine that handles the state machine that describes how we
+ * process and manage incoming log records.
+ */
+static int
+__rep_apply(dbenv, rp, rec)
+ DB_ENV *dbenv;
+ REP_CONTROL *rp;
+ DBT *rec;
+{
+ __dbreg_register_args dbreg_args;
+ __txn_ckp_args ckp_args;
+ DB_REP *db_rep;
+ DBT control_dbt, key_dbt, lsn_dbt, nextrec_dbt, rec_dbt;
+ DB *dbp;
+ DBC *dbc;
+ DB_LOG *dblp;
+ DB_LSN ckp_lsn, lsn, newfile_lsn, next_lsn, waiting_lsn;
+ LOG *lp;
+ REP *rep;
+ REP_CONTROL lsn_rc;
+ u_int32_t rectype, txnid;
+ int cmp, do_req, eid, have_mutex, ret, t_ret;
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+ dbp = db_rep->rep_db;
+ dbc = NULL;
+ have_mutex = ret = 0;
+ memset(&control_dbt, 0, sizeof(control_dbt));
+ memset(&rec_dbt, 0, sizeof(rec_dbt));
+
+ /*
+ * If this is a log record and it's the next one in line, simply
+ * write it to the log. If it's a "normal" log record, i.e., not
+ * a COMMIT or CHECKPOINT or something that needs immediate processing,
+ * just return. If it's a COMMIT, CHECKPOINT or LOG_REGISTER (i.e.,
+ * not SIMPLE), handle it now. If it's a NEWFILE record, then we
+ * have to be prepared to deal with a logfile change.
+ */
+ dblp = dbenv->lg_handle;
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp = dblp->reginfo.primary;
+ cmp = log_compare(&rp->lsn, &lp->ready_lsn);
+
+ /*
+ * This is written to assume that you don't end up with a lot of
+ * records after a hole. That is, it optimizes for the case where
+ * there is only a record or two after a hole. If you have a lot
+ * of records after a hole, what you'd really want to do is write
+ * all of them and then process all the commits, checkpoints, etc.
+ * together. That is more complicated processing that we can add
+ * later if necessary.
+ *
+ * That said, I really don't want to do db operations holding the
+ * log mutex, so the synchronization here is tricky.
+ */
+ if (cmp == 0) {
+ /* We got the log record that we are expecting. */
+ if (rp->rectype == REP_NEWFILE) {
+newfile: ret = __rep_newfile(dbenv, rp, rec, &lp->ready_lsn);
+
+ /* Make this evaluate to a simple rectype. */
+ rectype = 0;
+ } else {
+ DB_ASSERT(log_compare(&rp->lsn, &lp->lsn) == 0);
+ ret = __log_rep_put(dbenv, &rp->lsn, rec);
+ lp->ready_lsn = lp->lsn;
+ memcpy(&rectype, rec->data, sizeof(rectype));
+ if (ret == 0)
+ /*
+ * We may miscount if we race, since we
+ * don't currently hold the rep mutex.
+ */
+ rep->stat.st_log_records++;
+ }
+ while (ret == 0 && IS_SIMPLE(rectype) &&
+ log_compare(&lp->ready_lsn, &lp->waiting_lsn) == 0) {
+ /*
+ * We just filled in a gap in the log record stream.
+ * Write subsequent records to the log.
+ */
+gap_check: lp->wait_recs = 0;
+ lp->rcvd_recs = 0;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (have_mutex == 0) {
+ MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+ have_mutex = 1;
+ }
+ if (dbc == NULL &&
+ (ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+ goto err;
+
+ /* The DBTs need to persist through another call. */
+ F_SET(&control_dbt, DB_DBT_REALLOC);
+ F_SET(&rec_dbt, DB_DBT_REALLOC);
+ if ((ret = dbc->c_get(dbc,
+ &control_dbt, &rec_dbt, DB_RMW | DB_FIRST)) != 0)
+ goto err;
+
+ rp = (REP_CONTROL *)control_dbt.data;
+ rec = &rec_dbt;
+ memcpy(&rectype, rec->data, sizeof(rectype));
+ R_LOCK(dbenv, &dblp->reginfo);
+ /*
+ * We need to check again, because it's possible that
+ * some other thread of control changed the waiting_lsn
+ * or removed that record from the database.
+ */
+ if (log_compare(&lp->ready_lsn, &rp->lsn) == 0) {
+ if (rp->rectype != REP_NEWFILE) {
+ DB_ASSERT(log_compare
+ (&rp->lsn, &lp->lsn) == 0);
+ ret = __log_rep_put(dbenv,
+ &rp->lsn, rec);
+ lp->ready_lsn = lp->lsn;
+
+ /*
+ * We may miscount if we race, since we
+ * don't currently hold the rep mutex.
+ */
+ if (ret == 0)
+ rep->stat.st_log_records++;
+ } else {
+ ret = __rep_newfile(dbenv,
+ rp, rec, &lp->ready_lsn);
+ rectype = 0;
+ }
+ waiting_lsn = lp->waiting_lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if ((ret = dbc->c_del(dbc, 0)) != 0)
+ goto err;
+
+ /*
+ * We may miscount, as we don't hold the rep
+ * mutex.
+ */
+ --rep->stat.st_log_queued;
+
+ /*
+ * Update waiting_lsn. We need to move it
+ * forward to the LSN of the next record
+ * in the queue.
+ */
+ memset(&lsn_dbt, 0, sizeof(lsn_dbt));
+ F_SET(&lsn_dbt, DB_DBT_USERMEM);
+ lsn_dbt.data = &lsn_rc;
+ lsn_dbt.ulen = sizeof(lsn_rc);
+ memset(&lsn_rc, 0, sizeof(lsn_rc));
+
+ /*
+ * If the next item in the database is a log
+ * record--the common case--we're not
+ * interested in its contents, just in its LSN.
+ * If it's a newfile message, though, the
+ * data field may be the LSN of the last
+ * record in the old file, and we need to use
+ * that to determine whether or not there's
+ * a gap.
+ *
+ * Optimize both these cases by doing a partial
+ * get of the data item. If it's a newfile
+ * record, we'll get the whole LSN, and if
+ * it's not, we won't waste time allocating.
+ */
+ memset(&nextrec_dbt, 0, sizeof(nextrec_dbt));
+ F_SET(&nextrec_dbt,
+ DB_DBT_USERMEM | DB_DBT_PARTIAL);
+ nextrec_dbt.ulen =
+ nextrec_dbt.dlen = sizeof(newfile_lsn);
+ ZERO_LSN(newfile_lsn);
+ nextrec_dbt.data = &newfile_lsn;
+
+ ret = dbc->c_get(dbc,
+ &lsn_dbt, &nextrec_dbt, DB_NEXT);
+ if (ret != DB_NOTFOUND && ret != 0)
+ goto err;
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ if (ret == DB_NOTFOUND) {
+ /*
+ * Do a quick double-check to make
+ * sure waiting_lsn hasn't changed.
+ * It's possible that between the
+ * DB_NOTFOUND return and the R_LOCK,
+ * some record was added to the
+ * database, and we don't want to lose
+ * sight of the fact that it's there.
+ */
+ if (log_compare(&waiting_lsn,
+ &lp->waiting_lsn) == 0)
+ ZERO_LSN(
+ lp->waiting_lsn);
+
+ /*
+ * Whether or not the current record is
+ * simple, there's no next one, and
+ * therefore we haven't got anything
+ * else to do right now. Break out.
+ */
+ break;
+ }
+
+ DB_ASSERT(lsn_dbt.size == sizeof(lsn_rc));
+
+ /*
+ * NEWFILE records have somewhat convoluted
+ * semantics, so there are five cases
+ * pertaining to what the newly-gotten record
+ * is and what we want to do about it.
+ *
+ * 1) This isn't a NEWFILE record. Advance
+ * waiting_lsn and proceed.
+ *
+ * 2) NEWFILE, no LSN stored as the datum,
+ * lsn_rc.lsn == ready_lsn. The NEWFILE
+ * record is next, so set waiting_lsn =
+ * ready_lsn.
+ *
+ * 3) NEWFILE, no LSN stored as the datum, but
+ * lsn_rc.lsn > ready_lsn. There's still a
+ * gap; set waiting_lsn = lsn_rc.lsn.
+ *
+ * 4) NEWFILE, newfile_lsn in datum, and it's <
+ * ready_lsn. (If the datum is non-empty,
+ * it's the LSN of the last record in a log
+ * file, not the end of the log, and
+ * lsn_rc.lsn is the LSN of the start of
+ * the new file--we didn't have the end of
+ * the old log handy when we sent the
+ * record.) No gap--we're ready to
+ * proceed. Set both waiting and ready_lsn
+ * to lsn_rc.lsn.
+ *
+ * 5) NEWFILE, newfile_lsn in datum, and it's >=
+ * ready_lsn. We're still missing at
+ * least one record; set waiting_lsn,
+ * but not ready_lsn, to lsn_rc.lsn.
+ */
+ if (lsn_rc.rectype == REP_NEWFILE &&
+ nextrec_dbt.size > 0 && log_compare(
+ &newfile_lsn, &lp->ready_lsn) < 0)
+ /* Case 4. */
+ lp->ready_lsn =
+ lp->waiting_lsn = lsn_rc.lsn;
+ else {
+ /* Cases 1, 2, 3, and 5. */
+ DB_ASSERT(log_compare(&lsn_rc.lsn,
+ &lp->ready_lsn) >= 0);
+ lp->waiting_lsn = lsn_rc.lsn;
+ }
+
+ /*
+ * If the current rectype is simple, we're
+ * done with it, and we should check and see
+ * whether the next record queued is the next
+ * one we're ready for. This is just the loop
+ * condition, so we continue.
+ *
+ * Otherwise, we need to break out of this loop
+ * and process this record first.
+ */
+ if (!IS_SIMPLE(rectype))
+ break;
+ }
+ }
+
+ /*
+ * Check if we're at a gap in the table and if so, whether we
+ * need to ask for any records.
+ */
+ do_req = 0;
+ if (!IS_ZERO_LSN(lp->waiting_lsn) &&
+ log_compare(&lp->ready_lsn, &lp->waiting_lsn) != 0) {
+ next_lsn = lp->ready_lsn;
+ do_req = ++lp->rcvd_recs >= lp->wait_recs;
+ if (do_req) {
+ lp->wait_recs = rep->request_gap;
+ lp->rcvd_recs = 0;
+ }
+ }
+
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (dbc != NULL) {
+ if ((ret = dbc->c_close(dbc)) != 0)
+ goto err;
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+ have_mutex = 0;
+ }
+ dbc = NULL;
+
+ if (do_req) {
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ eid = db_rep->region->master_id;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ if (eid != DB_EID_INVALID) {
+ rep->stat.st_log_requested++;
+ if ((ret = __rep_send_message(dbenv,
+ eid, REP_LOG_REQ, &next_lsn, NULL, 0)) != 0)
+ goto err;
+ }
+ }
+ } else if (cmp > 0) {
+ /*
+ * The LSN is higher than the one we were waiting for.
+ * If it is a NEWFILE message, this may not mean that
+ * there's a gap; in some cases, NEWFILE messages contain
+ * the LSN of the beginning of the new file instead
+ * of the end of the old.
+ *
+ * In these cases, the rec DBT will contain the last LSN
+ * of the old file, so we can tell whether there's a gap.
+ */
+ if (rp->rectype == REP_NEWFILE &&
+ rp->lsn.file == lp->ready_lsn.file + 1 &&
+ rp->lsn.offset == 0) {
+ DB_ASSERT(rec != NULL && rec->data != NULL &&
+ rec->size == sizeof(DB_LSN));
+ memcpy(&lsn, rec->data, sizeof(DB_LSN));
+ if (log_compare(&lp->ready_lsn, &lsn) > 0)
+ /*
+ * The last LSN in the old file is smaller
+ * than the one we're expecting, so there's
+ * no gap--the one we're expecting just
+ * doesn't exist.
+ */
+ goto newfile;
+ }
+
+ /*
+ * This record isn't in sequence; add it to the table and
+ * update waiting_lsn if necessary.
+ */
+ memset(&key_dbt, 0, sizeof(key_dbt));
+ key_dbt.data = rp;
+ key_dbt.size = sizeof(*rp);
+ next_lsn = lp->lsn;
+ do_req = 0;
+ if (lp->wait_recs == 0) {
+ /*
+ * This is a new gap. Initialize the number of
+ * records that we should wait before requesting
+ * that it be resent. We grab the limits out of
+ * the rep without the mutex.
+ */
+ lp->wait_recs = rep->request_gap;
+ lp->rcvd_recs = 0;
+ }
+
+ if (++lp->rcvd_recs >= lp->wait_recs) {
+ /*
+ * If we've waited long enough, request the record
+ * and double the wait interval.
+ */
+ do_req = 1;
+ lp->wait_recs <<= 1;
+ lp->rcvd_recs = 0;
+ if (lp->wait_recs > rep->max_gap)
+ lp->wait_recs = rep->max_gap;
+ }
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+ ret = dbp->put(dbp, NULL, &key_dbt, rec, 0);
+ rep->stat.st_log_queued++;
+ rep->stat.st_log_queued_total++;
+ if (rep->stat.st_log_queued_max < rep->stat.st_log_queued)
+ rep->stat.st_log_queued_max = rep->stat.st_log_queued;
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+ if (ret != 0)
+ return (ret);
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ if (IS_ZERO_LSN(lp->waiting_lsn) ||
+ log_compare(&rp->lsn, &lp->waiting_lsn) < 0)
+ lp->waiting_lsn = rp->lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ if (do_req) {
+ /* Request the LSN we are still waiting for. */
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+
+ /* May as well do this after we grab the mutex. */
+ eid = db_rep->region->master_id;
+
+ /*
+ * If the master_id is invalid, this means that since
+ * the last record was sent, somebody declared an
+ * election and we may not have a master to request
+ * things of.
+ *
+ * This is not an error; when we find a new master,
+ * we'll re-negotiate where the end of the log is and
+ * try to to bring ourselves up to date again anyway.
+ */
+ if (eid != DB_EID_INVALID) {
+ rep->stat.st_log_requested++;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ ret = __rep_send_message(dbenv,
+ eid, REP_LOG_REQ, &next_lsn, NULL, 0);
+ } else
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ }
+ return (ret);
+ } else {
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ /*
+ * We may miscount if we race, since we
+ * don't currently hold the rep mutex.
+ */
+ rep->stat.st_log_duplicated++;
+ }
+ if (ret != 0 || cmp < 0 || (cmp == 0 && IS_SIMPLE(rectype)))
+ goto done;
+
+ /*
+ * If we got here, then we've got a log record in rp and rec that
+ * we need to process.
+ */
+ switch(rectype) {
+ case DB___dbreg_register:
+ /*
+ * DB opens occur in the context of a transaction, so we can
+ * simply handle them when we process the transaction. Closes,
+ * however, are not transaction-protected, so we have to
+ * handle them here.
+ *
+ * Note that it should be unsafe for the master to do a close
+ * of a file that was opened in an active transaction, so we
+ * should be guaranteed to get the ordering right.
+ */
+ memcpy(&txnid, (u_int8_t *)rec->data +
+ ((u_int8_t *)&dbreg_args.txnid - (u_int8_t *)&dbreg_args),
+ sizeof(u_int32_t));
+ if (txnid == TXN_INVALID &&
+ !F_ISSET(dbenv, DB_ENV_REP_LOGSONLY))
+ ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+ dbenv->recover_dtab_size, rec, &rp->lsn,
+ DB_TXN_APPLY, NULL);
+ break;
+ case DB___txn_ckp:
+ /* Sync the memory pool. */
+ memcpy(&ckp_lsn, (u_int8_t *)rec->data +
+ ((u_int8_t *)&ckp_args.ckp_lsn - (u_int8_t *)&ckp_args),
+ sizeof(DB_LSN));
+ if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY))
+ ret = dbenv->memp_sync(dbenv, &ckp_lsn);
+ else
+ /*
+ * We ought to make sure the logs on a logs-only
+ * replica get flushed now and again.
+ */
+ ret = dbenv->log_flush(dbenv, &ckp_lsn);
+ /* Update the last_ckp in the txn region. */
+ if (ret == 0)
+ __txn_updateckp(dbenv, &rp->lsn);
+ break;
+ case DB___txn_regop:
+ if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY))
+ do {
+ /*
+ * If an application is doing app-specific
+ * recovery and acquires locks while applying
+ * a transaction, it can deadlock. Any other
+ * locks held by this thread should have been
+ * discarded in the __rep_process_txn error
+ * path, so if we simply retry, we should
+ * eventually succeed.
+ */
+ ret = __rep_process_txn(dbenv, rec);
+ } while (ret == DB_LOCK_DEADLOCK);
+ break;
+ default:
+ goto err;
+ }
+
+ /* Check if we need to go back into the table. */
+ if (ret == 0) {
+ R_LOCK(dbenv, &dblp->reginfo);
+ if (log_compare(&lp->ready_lsn, &lp->waiting_lsn) == 0)
+ goto gap_check;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ }
+
+done:
+err: if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ if (have_mutex)
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+ if (control_dbt.data != NULL)
+ __os_ufree(dbenv, control_dbt.data);
+ if (rec_dbt.data != NULL)
+ __os_ufree(dbenv, rec_dbt.data);
+
+ return (ret);
+}
+
+/*
+ * __rep_process_txn --
+ *
+ * This is the routine that actually gets a transaction ready for
+ * processing.
+ *
+ * PUBLIC: int __rep_process_txn __P((DB_ENV *, DBT *));
+ */
+int
+__rep_process_txn(dbenv, rec)
+ DB_ENV *dbenv;
+ DBT *rec;
+{
+ DBT data_dbt;
+ DB_LOCKREQ req, *lvp;
+ DB_LOGC *logc;
+ DB_LSN prev_lsn, *lsnp;
+ DB_REP *db_rep;
+ LSN_COLLECTION lc;
+ REP *rep;
+ __txn_regop_args *txn_args;
+ __txn_xa_regop_args *prep_args;
+ u_int32_t lockid, op, rectype;
+ int i, ret, t_ret;
+ int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t dtabsize;
+ void *txninfo;
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+
+ logc = NULL;
+ txninfo = NULL;
+ memset(&data_dbt, 0, sizeof(data_dbt));
+ if (F_ISSET(dbenv, DB_ENV_THREAD))
+ F_SET(&data_dbt, DB_DBT_REALLOC);
+
+ /*
+ * There are two phases: First, we have to traverse
+ * backwards through the log records gathering the list
+ * of all LSNs in the transaction. Once we have this information,
+ * we can loop through, acquire the locks we need for each record,
+ * and then apply it.
+ */
+ dtab = NULL;
+
+ /*
+ * We may be passed a prepare (if we're restoring a prepare
+ * on upgrade) instead of a commit (the common case).
+ * Check which and behave appropriately.
+ */
+ memcpy(&rectype, rec->data, sizeof(rectype));
+ memset(&lc, 0, sizeof(lc));
+ if (rectype == DB___txn_regop) {
+ /*
+ * We're the end of a transaction. Make sure this is
+ * really a commit and not an abort!
+ */
+ if ((ret = __txn_regop_read(dbenv, rec->data, &txn_args)) != 0)
+ return (ret);
+ op = txn_args->opcode;
+ prev_lsn = txn_args->prev_lsn;
+ __os_free(dbenv, txn_args);
+ if (op != TXN_COMMIT)
+ return (0);
+ } else {
+ /* We're a prepare. */
+ DB_ASSERT(rectype == DB___txn_xa_regop);
+
+ if ((ret =
+ __txn_xa_regop_read(dbenv, rec->data, &prep_args)) != 0)
+ return (ret);
+ prev_lsn = prep_args->prev_lsn;
+ __os_free(dbenv, prep_args);
+ }
+
+ /* Phase 1. Get a list of the LSNs in this transaction, and sort it. */
+ if ((ret = __rep_collect_txn(dbenv, &prev_lsn, &lc)) != 0)
+ return (ret);
+ qsort(lc.array, lc.nlsns, sizeof(DB_LSN), __rep_lsn_cmp);
+
+ if ((ret = dbenv->lock_id(dbenv, &lockid)) != 0)
+ goto err;
+
+ /* Initialize the getpgno dispatch table. */
+ if ((ret = __rep_lockpgno_init(dbenv, &dtab, &dtabsize)) != 0)
+ goto err;
+
+ /*
+ * The set of records for a transaction may include dbreg_register
+ * records. Create a txnlist so that they can keep track of file
+ * state between records.
+ */
+ if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
+ goto err;
+
+ /* Phase 2: Apply updates. */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ goto err;
+ for (lsnp = &lc.array[0], i = 0; i < lc.nlsns; i++, lsnp++) {
+ if ((ret = __rep_lockpages(dbenv,
+ dtab, dtabsize, lsnp, NULL, NULL, lockid)) != 0)
+ goto err;
+ if ((ret = logc->get(logc, lsnp, &data_dbt, DB_SET)) != 0)
+ goto err;
+ if ((ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+ dbenv->recover_dtab_size, &data_dbt, lsnp,
+ DB_TXN_APPLY, txninfo)) != 0)
+ goto err;
+ }
+
+err: memset(&req, 0, sizeof(req));
+ req.op = DB_LOCK_PUT_ALL;
+ if ((t_ret = dbenv->lock_vec(dbenv, lockid,
+ DB_LOCK_FREE_LOCKER, &req, 1, &lvp)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (lc.nalloc != 0)
+ __os_free(dbenv, lc.array);
+
+ if ((t_ret =
+ dbenv->lock_id_free(dbenv, lockid)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (txninfo != NULL)
+ __db_txnlist_end(dbenv, txninfo);
+
+ if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL)
+ __os_ufree(dbenv, data_dbt.data);
+
+ if (dtab != NULL)
+ __os_free(dbenv, dtab);
+
+ if (ret == 0)
+ /*
+ * We don't hold the rep mutex, and could miscount if we race.
+ */
+ rep->stat.st_txns_applied++;
+
+ return (ret);
+}
+
+/*
+ * __rep_collect_txn
+ * Recursive function that will let us visit every entry in a transaction
+ * chain including all child transactions so that we can then apply
+ * the entire transaction family at once.
+ */
+static int
+__rep_collect_txn(dbenv, lsnp, lc)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+ LSN_COLLECTION *lc;
+{
+ __txn_child_args *argp;
+ DB_LOGC *logc;
+ DB_LSN c_lsn;
+ DBT data;
+ u_int32_t rectype;
+ int nalloc, ret, t_ret;
+
+ memset(&data, 0, sizeof(data));
+ F_SET(&data, DB_DBT_REALLOC);
+
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+
+ while (!IS_ZERO_LSN(*lsnp) &&
+ (ret = logc->get(logc, lsnp, &data, DB_SET)) == 0) {
+ memcpy(&rectype, data.data, sizeof(rectype));
+ if (rectype == DB___txn_child) {
+ if ((ret = __txn_child_read(dbenv,
+ data.data, &argp)) != 0)
+ goto err;
+ c_lsn = argp->c_lsn;
+ *lsnp = argp->prev_lsn;
+ __os_free(dbenv, argp);
+ ret = __rep_collect_txn(dbenv, &c_lsn, lc);
+ } else {
+ if (lc->nalloc < lc->nlsns + 1) {
+ nalloc = lc->nalloc == 0 ? 20 : lc->nalloc * 2;
+ if ((ret = __os_realloc(dbenv,
+ nalloc * sizeof(DB_LSN), &lc->array)) != 0)
+ goto err;
+ lc->nalloc = nalloc;
+ }
+ lc->array[lc->nlsns++] = *lsnp;
+
+ /*
+ * Explicitly copy the previous lsn. The record
+ * starts with a u_int32_t record type, a u_int32_t
+ * txn id, and then the DB_LSN (prev_lsn) that we
+ * want. We copy explicitly because we have no idea
+ * what kind of record this is.
+ */
+ memcpy(lsnp, (u_int8_t *)data.data +
+ sizeof(u_int32_t) + sizeof(u_int32_t),
+ sizeof(DB_LSN));
+ }
+
+ if (ret != 0)
+ goto err;
+ }
+
+err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (data.data != NULL)
+ __os_ufree(dbenv, data.data);
+ return (ret);
+}
+
+/*
+ * __rep_lsn_cmp --
+ * qsort-type-compatible wrapper for log_compare.
+ */
+static int
+__rep_lsn_cmp(lsn1, lsn2)
+ const void *lsn1, *lsn2;
+{
+
+ return (log_compare((DB_LSN *)lsn1, (DB_LSN *)lsn2));
+}
+
+/*
+ * __rep_newfile --
+ * NEWFILE messages can contain either the last LSN of the old file
+ * or the first LSN of the new one, depending on which we have available
+ * when the message is sent. When applying a NEWFILE message, make sure
+ * we haven't already swapped files, as it's possible (given the right sequence
+ * of out-of-order messages) to wind up with a NEWFILE message of each
+ * variety, and __rep_apply won't detect the two as duplicates of each other.
+ */
+static int
+__rep_newfile(dbenv, rc, msgdbt, lsnp)
+ DB_ENV *dbenv;
+ REP_CONTROL *rc;
+ DBT *msgdbt;
+ DB_LSN *lsnp;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+ u_int32_t newfile;
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ /*
+ * A NEWFILE message containing the old file's LSN will be
+ * accompanied by a NULL rec DBT; one containing the new one's LSN
+ * will need to supply the last record in the old file by
+ * sending it in the rec DBT.
+ */
+ if (msgdbt == NULL || msgdbt->size == 0)
+ newfile = rc->lsn.file + 1;
+ else
+ newfile = rc->lsn.file;
+
+ if (newfile > lp->lsn.file)
+ return (__log_newfile(dblp, lsnp));
+ else {
+ /* We've already applied this NEWFILE. Just ignore it. */
+ *lsnp = lp->lsn;
+ return (0);
+ }
+}
diff --git a/bdb/rep/rep_region.c b/bdb/rep/rep_region.c
new file mode 100644
index 00000000000..1ac3fb8a20c
--- /dev/null
+++ b/bdb/rep/rep_region.c
@@ -0,0 +1,187 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: rep_region.c,v 1.29 2002/08/06 04:50:36 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#endif
+
+#include <string.h>
+
+#include "db_int.h"
+#include "dbinc/rep.h"
+#include "dbinc/log.h"
+
+/*
+ * __rep_region_init --
+ * Initialize the shared memory state for the replication system.
+ *
+ * PUBLIC: int __rep_region_init __P((DB_ENV *));
+ */
+int
+__rep_region_init(dbenv)
+ DB_ENV *dbenv;
+{
+ REGENV *renv;
+ REGINFO *infop;
+ DB_MUTEX *db_mutexp;
+ DB_REP *db_rep;
+ REP *rep;
+ int ret;
+
+ db_rep = dbenv->rep_handle;
+ infop = dbenv->reginfo;
+ renv = infop->primary;
+ ret = 0;
+
+ MUTEX_LOCK(dbenv, &renv->mutex);
+ if (renv->rep_off == INVALID_ROFF) {
+ /* Must create the region. */
+ if ((ret = __db_shalloc(infop->addr,
+ sizeof(REP), MUTEX_ALIGN, &rep)) != 0)
+ goto err;
+ memset(rep, 0, sizeof(*rep));
+ rep->tally_off = INVALID_ROFF;
+ renv->rep_off = R_OFFSET(infop, rep);
+
+ if ((ret = __db_mutex_setup(dbenv, infop, &rep->mutex,
+ MUTEX_NO_RECORD)) != 0)
+ goto err;
+
+ /*
+ * We must create a place for the db_mutex separately;
+ * mutexes have to be aligned to MUTEX_ALIGN, and the only way
+ * to guarantee that is to make sure they're at the beginning
+ * of a shalloc'ed chunk.
+ */
+ if ((ret = __db_shalloc(infop->addr, sizeof(DB_MUTEX),
+ MUTEX_ALIGN, &db_mutexp)) != 0)
+ goto err;
+ rep->db_mutex_off = R_OFFSET(infop, db_mutexp);
+
+ /*
+ * Because we have no way to prevent deadlocks and cannot log
+ * changes made to it, we single-thread access to the client
+ * bookkeeping database. This is suboptimal, but it only gets
+ * accessed when messages arrive out-of-order, so it should
+ * stay small and not be used in a high-performance app.
+ */
+ if ((ret = __db_mutex_setup(dbenv, infop, db_mutexp,
+ MUTEX_NO_RECORD)) != 0)
+ goto err;
+
+ /* We have the region; fill in the values. */
+ rep->eid = DB_EID_INVALID;
+ rep->master_id = DB_EID_INVALID;
+ rep->gen = 0;
+
+ /*
+ * Set default values for the min and max log records that we
+ * wait before requesting a missing log record.
+ */
+ rep->request_gap = DB_REP_REQUEST_GAP;
+ rep->max_gap = DB_REP_MAX_GAP;
+ } else
+ rep = R_ADDR(infop, renv->rep_off);
+ MUTEX_UNLOCK(dbenv, &renv->mutex);
+
+ db_rep->mutexp = &rep->mutex;
+ db_rep->db_mutexp = R_ADDR(infop, rep->db_mutex_off);
+ db_rep->region = rep;
+
+ return (0);
+
+err: MUTEX_UNLOCK(dbenv, &renv->mutex);
+ return (ret);
+}
+
+/*
+ * __rep_region_destroy --
+ * Destroy any system resources allocated in the replication region.
+ *
+ * PUBLIC: int __rep_region_destroy __P((DB_ENV *));
+ */
+int
+__rep_region_destroy(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_REP *db_rep;
+ int ret, t_ret;
+
+ ret = t_ret = 0;
+ db_rep = (DB_REP *)dbenv->rep_handle;
+
+ if (db_rep != NULL) {
+ if (db_rep->mutexp != NULL)
+ ret = __db_mutex_destroy(db_rep->mutexp);
+ if (db_rep->db_mutexp != NULL)
+ t_ret = __db_mutex_destroy(db_rep->db_mutexp);
+ }
+
+ return (ret == 0 ? t_ret : ret);
+}
+
+/*
+ * __rep_dbenv_close --
+ * Replication-specific destruction of the DB_ENV structure.
+ *
+ * PUBLIC: int __rep_dbenv_close __P((DB_ENV *));
+ */
+int
+__rep_dbenv_close(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_REP *db_rep;
+
+ db_rep = (DB_REP *)dbenv->rep_handle;
+
+ if (db_rep != NULL) {
+ __os_free(dbenv, db_rep);
+ dbenv->rep_handle = NULL;
+ }
+
+ return (0);
+}
+
+/*
+ * __rep_preclose --
+ * If we are a client, shut down our client database and, if we're
+ * actually closing the environment, close all databases we've opened
+ * while applying messages.
+ *
+ * PUBLIC: int __rep_preclose __P((DB_ENV *, int));
+ */
+int
+__rep_preclose(dbenv, do_closefiles)
+ DB_ENV *dbenv;
+ int do_closefiles;
+{
+ DB *dbp;
+ DB_REP *db_rep;
+ int ret, t_ret;
+
+ ret = t_ret = 0;
+
+ /* If replication is not initialized, we have nothing to do. */
+ if ((db_rep = (DB_REP *)dbenv->rep_handle) == NULL)
+ return (0);
+
+ if ((dbp = db_rep->rep_db) != NULL) {
+ MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+ ret = dbp->close(dbp, 0);
+ db_rep->rep_db = NULL;
+ MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+ }
+
+ if (do_closefiles)
+ t_ret = __dbreg_close_files(dbenv);
+
+ return (ret == 0 ? t_ret : ret);
+}
diff --git a/bdb/rep/rep_util.c b/bdb/rep/rep_util.c
new file mode 100644
index 00000000000..9c99d33ed4a
--- /dev/null
+++ b/bdb/rep/rep_util.c
@@ -0,0 +1,867 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: rep_util.c,v 1.51 2002/09/05 02:30:00 margo Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/fop.h"
+#include "dbinc/hash.h"
+#include "dbinc/log.h"
+#include "dbinc/qam.h"
+#include "dbinc/rep.h"
+#include "dbinc/txn.h"
+
+/*
+ * rep_util.c:
+ * Miscellaneous replication-related utility functions, including
+ * those called by other subsystems.
+ */
+static int __rep_cmp_bylsn __P((const void *, const void *));
+static int __rep_cmp_bypage __P((const void *, const void *));
+
+#ifdef REP_DIAGNOSTIC
+static void __rep_print_logmsg __P((DB_ENV *, const DBT *, DB_LSN *));
+#endif
+
+/*
+ * __rep_check_alloc --
+ * Make sure the array of TXN_REC entries is of at least size n.
+ * (This function is called by the __*_getpgnos() functions in
+ * *.src.)
+ *
+ * PUBLIC: int __rep_check_alloc __P((DB_ENV *, TXN_RECS *, int));
+ */
+int
+__rep_check_alloc(dbenv, r, n)
+ DB_ENV *dbenv;
+ TXN_RECS *r;
+ int n;
+{
+ int nalloc, ret;
+
+ while (r->nalloc < r->npages + n) {
+ nalloc = r->nalloc == 0 ? 20 : r->nalloc * 2;
+
+ if ((ret = __os_realloc(dbenv, nalloc * sizeof(LSN_PAGE),
+ &r->array)) != 0)
+ return (ret);
+
+ r->nalloc = nalloc;
+ }
+
+ return (0);
+}
+
+/*
+ * __rep_send_message --
+ * This is a wrapper for sending a message. It takes care of constructing
+ * the REP_CONTROL structure and calling the user's specified send function.
+ *
+ * PUBLIC: int __rep_send_message __P((DB_ENV *, int,
+ * PUBLIC: u_int32_t, DB_LSN *, const DBT *, u_int32_t));
+ */
+int
+__rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags)
+ DB_ENV *dbenv;
+ int eid;
+ u_int32_t rtype;
+ DB_LSN *lsnp;
+ const DBT *dbtp;
+ u_int32_t flags;
+{
+ DB_REP *db_rep;
+ REP *rep;
+ DBT cdbt, scrap_dbt;
+ REP_CONTROL cntrl;
+ u_int32_t send_flags;
+ int ret;
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+
+ /* Set up control structure. */
+ memset(&cntrl, 0, sizeof(cntrl));
+ if (lsnp == NULL)
+ ZERO_LSN(cntrl.lsn);
+ else
+ cntrl.lsn = *lsnp;
+ cntrl.rectype = rtype;
+ cntrl.flags = flags;
+ cntrl.rep_version = DB_REPVERSION;
+ cntrl.log_version = DB_LOGVERSION;
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ cntrl.gen = rep->gen;
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ memset(&cdbt, 0, sizeof(cdbt));
+ cdbt.data = &cntrl;
+ cdbt.size = sizeof(cntrl);
+
+ /* Don't assume the send function will be tolerant of NULL records. */
+ if (dbtp == NULL) {
+ memset(&scrap_dbt, 0, sizeof(DBT));
+ dbtp = &scrap_dbt;
+ }
+
+ send_flags = (LF_ISSET(DB_PERMANENT) ? DB_REP_PERMANENT : 0);
+
+#if 0
+ __rep_print_message(dbenv, eid, &cntrl, "rep_send_message");
+#endif
+#ifdef REP_DIAGNOSTIC
+ if (rtype == REP_LOG)
+ __rep_print_logmsg(dbenv, dbtp, lsnp);
+#endif
+ ret = db_rep->rep_send(dbenv, &cdbt, dbtp, eid, send_flags);
+
+ /*
+ * We don't hold the rep lock, so this could miscount if we race.
+ * I don't think it's worth grabbing the mutex for that bit of
+ * extra accuracy.
+ */
+ if (ret == 0)
+ rep->stat.st_msgs_sent++;
+ else
+ rep->stat.st_msgs_send_failures++;
+
+ return (ret);
+}
+
+#ifdef REP_DIAGNOSTIC
+
+/*
+ * __rep_print_logmsg --
+ * This is a debugging routine for printing out log records that
+ * we are about to transmit to a client.
+ */
+
+static void
+__rep_print_logmsg(dbenv, logdbt, lsnp)
+ DB_ENV *dbenv;
+ const DBT *logdbt;
+ DB_LSN *lsnp;
+{
+ /* Static structures to hold the printing functions. */
+ static int (**ptab)__P((DB_ENV *,
+ DBT *, DB_LSN *, db_recops, void *)) = NULL;
+ size_t ptabsize = 0;
+
+ if (ptabsize == 0) {
+ /* Initialize the table. */
+ (void)__bam_init_print(dbenv, &ptab, &ptabsize);
+ (void)__crdel_init_print(dbenv, &ptab, &ptabsize);
+ (void)__db_init_print(dbenv, &ptab, &ptabsize);
+ (void)__dbreg_init_print(dbenv, &ptab, &ptabsize);
+ (void)__fop_init_print(dbenv, &ptab, &ptabsize);
+ (void)__qam_init_print(dbenv, &ptab, &ptabsize);
+ (void)__ham_init_print(dbenv, &ptab, &ptabsize);
+ (void)__txn_init_print(dbenv, &ptab, &ptabsize);
+ }
+
+ (void)__db_dispatch(dbenv,
+ ptab, ptabsize, (DBT *)logdbt, lsnp, DB_TXN_PRINT, NULL);
+}
+
+#endif
+/*
+ * __rep_new_master --
+ * Called after a master election to sync back up with a new master.
+ * It's possible that we already know of this new master in which case
+ * we don't need to do anything.
+ *
+ * This is written assuming that this message came from the master; we
+ * need to enforce that in __rep_process_record, but right now, we have
+ * no way to identify the master.
+ *
+ * PUBLIC: int __rep_new_master __P((DB_ENV *, REP_CONTROL *, int));
+ */
+int
+__rep_new_master(dbenv, cntrl, eid)
+ DB_ENV *dbenv;
+ REP_CONTROL *cntrl;
+ int eid;
+{
+ DB_LOG *dblp;
+ DB_LOGC *logc;
+ DB_LSN last_lsn, lsn;
+ DB_REP *db_rep;
+ DBT dbt;
+ LOG *lp;
+ REP *rep;
+ int change, ret, t_ret;
+
+ db_rep = dbenv->rep_handle;
+ rep = db_rep->region;
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ ELECTION_DONE(rep);
+ change = rep->gen != cntrl->gen || rep->master_id != eid;
+ if (change) {
+ rep->gen = cntrl->gen;
+ rep->master_id = eid;
+ F_SET(rep, REP_F_RECOVER);
+ rep->stat.st_master_changes++;
+ }
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ if (!change)
+ return (0);
+
+ /*
+ * If the master changed, we need to start the process of
+ * figuring out what our last valid log record is. However,
+ * if both the master and we agree that the max LSN is 0,0,
+ * then there is no recovery to be done. If we are at 0 and
+ * the master is not, then we just need to request all the log
+ * records from the master.
+ */
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ R_LOCK(dbenv, &dblp->reginfo);
+ last_lsn = lsn = lp->lsn;
+ if (last_lsn.offset > sizeof(LOGP))
+ last_lsn.offset -= lp->len;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if (IS_INIT_LSN(lsn) || IS_ZERO_LSN(lsn)) {
+empty: MUTEX_LOCK(dbenv, db_rep->mutexp);
+ F_CLR(rep, REP_F_RECOVER);
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+
+ if (IS_INIT_LSN(cntrl->lsn))
+ ret = 0;
+ else
+ ret = __rep_send_message(dbenv, rep->master_id,
+ REP_ALL_REQ, &lsn, NULL, 0);
+
+ if (ret == 0)
+ ret = DB_REP_NEWMASTER;
+ return (ret);
+ } else if (last_lsn.offset <= sizeof(LOGP)) {
+ /*
+ * We have just changed log files and need to set lastlsn
+ * to the last record in the previous log files.
+ */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ memset(&dbt, 0, sizeof(dbt));
+ ret = logc->get(logc, &last_lsn, &dbt, DB_LAST);
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (ret == DB_NOTFOUND)
+ goto empty;
+ if (ret != 0)
+ return (ret);
+ }
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp->verify_lsn = last_lsn;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ if ((ret = __rep_send_message(dbenv,
+ eid, REP_VERIFY_REQ, &last_lsn, NULL, 0)) != 0)
+ return (ret);
+
+ return (DB_REP_NEWMASTER);
+}
+
+/*
+ * __rep_lockpgno_init
+ * Create a dispatch table for acquiring locks on each log record.
+ *
+ * PUBLIC: int __rep_lockpgno_init __P((DB_ENV *,
+ * PUBLIC: int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),
+ * PUBLIC: size_t *));
+ */
+int
+__rep_lockpgno_init(dbenv, dtabp, dtabsizep)
+ DB_ENV *dbenv;
+ int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t *dtabsizep;
+{
+ int ret;
+
+ /* Initialize dispatch table. */
+ *dtabsizep = 0;
+ *dtabp = NULL;
+ if ((ret = __bam_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __crdel_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __db_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __dbreg_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __fop_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __qam_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __ham_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
+ (ret = __txn_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0)
+ return (ret);
+
+ return (0);
+}
+
+/*
+ * __rep_unlockpages --
+ * Unlock the pages locked in __rep_lockpages.
+ *
+ * PUBLIC: int __rep_unlockpages __P((DB_ENV *, u_int32_t));
+ */
+int
+__rep_unlockpages(dbenv, lid)
+ DB_ENV *dbenv;
+ u_int32_t lid;
+{
+ DB_LOCKREQ req, *lvp;
+
+ req.op = DB_LOCK_PUT_ALL;
+ return (dbenv->lock_vec(dbenv, lid, 0, &req, 1, &lvp));
+}
+
+/*
+ * __rep_lockpages --
+ * Called to gather and lock pages in preparation for both
+ * single transaction apply as well as client synchronization
+ * with a new master. A non-NULL key_lsn means that we're locking
+ * in order to apply a single log record during client recovery
+ * to the joint LSN. A non-NULL max_lsn means that we are applying
+ * a transaction whose commit is at max_lsn.
+ *
+ * PUBLIC: int __rep_lockpages __P((DB_ENV *,
+ * PUBLIC: int (**)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),
+ * PUBLIC: size_t, DB_LSN *, DB_LSN *, TXN_RECS *, u_int32_t));
+ */
+int
+__rep_lockpages(dbenv, dtab, dtabsize, key_lsn, max_lsn, recs, lid)
+ DB_ENV *dbenv;
+ int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t dtabsize;
+ DB_LSN *key_lsn, *max_lsn;
+ TXN_RECS *recs;
+ u_int32_t lid;
+{
+ DBT data_dbt, lo;
+ DB_LOCK l;
+ DB_LOCKREQ *lvp;
+ DB_LOGC *logc;
+ DB_LSN tmp_lsn;
+ TXN_RECS tmp, *t;
+ db_pgno_t cur_pgno;
+ linfo_t locks;
+ int i, ret, t_ret, unique;
+ u_int32_t cur_fid;
+
+ /*
+ * There are two phases: First, we have to traverse backwards through
+ * the log records gathering the list of all the pages accessed. Once
+ * we have this information we can acquire all the locks we need.
+ */
+
+ /* Initialization */
+ memset(&locks, 0, sizeof(locks));
+ ret = 0;
+
+ t = recs != NULL ? recs : &tmp;
+ t->npages = t->nalloc = 0;
+ t->array = NULL;
+
+ /*
+ * We've got to be in one mode or the other; else life will either
+ * be excessively boring or overly exciting.
+ */
+ DB_ASSERT(key_lsn != NULL || max_lsn != NULL);
+ DB_ASSERT(key_lsn == NULL || max_lsn == NULL);
+
+ /*
+ * Phase 1: Fill in the pgno array.
+ */
+ memset(&data_dbt, 0, sizeof(data_dbt));
+ if (F_ISSET(dbenv, DB_ENV_THREAD))
+ F_SET(&data_dbt, DB_DBT_REALLOC);
+
+ /* Single transaction apply. */
+ if (max_lsn != NULL) {
+ DB_ASSERT(0); /* XXX */
+ /*
+ tmp_lsn = *max_lsn;
+ if ((ret = __rep_apply_thread(dbenv, dtab, dtabsize,
+ &data_dbt, &tmp_lsn, t)) != 0)
+ goto err;
+ */
+ }
+
+ /* In recovery. */
+ if (key_lsn != NULL) {
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ goto err;
+ ret = logc->get(logc, key_lsn, &data_dbt, DB_SET);
+
+ /* Save lsn values, since dispatch functions can change them. */
+ tmp_lsn = *key_lsn;
+ ret = __db_dispatch(dbenv,
+ dtab, dtabsize, &data_dbt, &tmp_lsn, DB_TXN_GETPGNOS, t);
+
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ /*
+ * If ret == DB_DELETED, this record refers to a temporary
+ * file and there's nothing to apply.
+ */
+ if (ret == DB_DELETED) {
+ ret = 0;
+ goto out;
+ } else if (ret != 0)
+ goto err;
+ }
+
+ if (t->npages == 0)
+ goto out;
+
+ /* Phase 2: Write lock all the pages. */
+
+ /* Sort the entries in the array by page number. */
+ qsort(t->array, t->npages, sizeof(LSN_PAGE), __rep_cmp_bypage);
+
+ /* Count the number of unique pages. */
+ cur_fid = DB_LOGFILEID_INVALID;
+ cur_pgno = PGNO_INVALID;
+ unique = 0;
+ for (i = 0; i < t->npages; i++) {
+ if (F_ISSET(&t->array[i], LSN_PAGE_NOLOCK))
+ continue;
+ if (t->array[i].pgdesc.pgno != cur_pgno ||
+ t->array[i].fid != cur_fid) {
+ cur_pgno = t->array[i].pgdesc.pgno;
+ cur_fid = t->array[i].fid;
+ unique++;
+ }
+ }
+
+ if (unique == 0)
+ goto out;
+
+ /* Handle single lock case specially, else allocate space for locks. */
+ if (unique == 1) {
+ memset(&lo, 0, sizeof(lo));
+ lo.data = &t->array[0].pgdesc;
+ lo.size = sizeof(t->array[0].pgdesc);
+ ret = dbenv->lock_get(dbenv, lid, 0, &lo, DB_LOCK_WRITE, &l);
+ goto out2;
+ }
+
+ /* Multi-lock case. */
+ locks.n = unique;
+ if ((ret = __os_calloc(dbenv,
+ unique, sizeof(DB_LOCKREQ), &locks.reqs)) != 0)
+ goto err;
+ if ((ret = __os_calloc(dbenv, unique, sizeof(DBT), &locks.objs)) != 0)
+ goto err;
+
+ unique = 0;
+ cur_fid = DB_LOGFILEID_INVALID;
+ cur_pgno = PGNO_INVALID;
+ for (i = 0; i < t->npages; i++) {
+ if (F_ISSET(&t->array[i], LSN_PAGE_NOLOCK))
+ continue;
+ if (t->array[i].pgdesc.pgno != cur_pgno ||
+ t->array[i].fid != cur_fid) {
+ cur_pgno = t->array[i].pgdesc.pgno;
+ cur_fid = t->array[i].fid;
+ locks.reqs[unique].op = DB_LOCK_GET;
+ locks.reqs[unique].mode = DB_LOCK_WRITE;
+ locks.reqs[unique].obj = &locks.objs[unique];
+ locks.objs[unique].data = &t->array[i].pgdesc;
+ locks.objs[unique].size = sizeof(t->array[i].pgdesc);
+ unique++;
+ }
+ }
+
+ /* Finally, get the locks. */
+ if ((ret =
+ dbenv->lock_vec(dbenv, lid, 0, locks.reqs, unique, &lvp)) != 0) {
+ /*
+ * If we were unsuccessful, unlock any locks we acquired before
+ * the error and return the original error value.
+ */
+ (void)__rep_unlockpages(dbenv, lid);
+ }
+
+err:
+out: if (locks.objs != NULL)
+ __os_free(dbenv, locks.objs);
+ if (locks.reqs != NULL)
+ __os_free(dbenv, locks.reqs);
+
+ /*
+ * Before we return, sort by LSN so that we apply records in the
+ * right order.
+ */
+ qsort(t->array, t->npages, sizeof(LSN_PAGE), __rep_cmp_bylsn);
+
+out2: if ((ret != 0 || recs == NULL) && t->nalloc != 0) {
+ __os_free(dbenv, t->array);
+ t->array = NULL;
+ t->npages = t->nalloc = 0;
+ }
+
+ if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL)
+ __os_ufree(dbenv, data_dbt.data);
+
+ return (ret);
+}
+
+/*
+ * __rep_cmp_bypage and __rep_cmp_bylsn --
+ * Sort functions for qsort. "bypage" sorts first by page numbers and
+ * then by the LSN. "bylsn" sorts first by the LSN, then by page numbers.
+ */
+static int
+__rep_cmp_bypage(a, b)
+ const void *a, *b;
+{
+ LSN_PAGE *ap, *bp;
+
+ ap = (LSN_PAGE *)a;
+ bp = (LSN_PAGE *)b;
+
+ if (ap->fid < bp->fid)
+ return (-1);
+
+ if (ap->fid > bp->fid)
+ return (1);
+
+ if (ap->pgdesc.pgno < bp->pgdesc.pgno)
+ return (-1);
+
+ if (ap->pgdesc.pgno > bp->pgdesc.pgno)
+ return (1);
+
+ if (ap->lsn.file < bp->lsn.file)
+ return (-1);
+
+ if (ap->lsn.file > bp->lsn.file)
+ return (1);
+
+ if (ap->lsn.offset < bp->lsn.offset)
+ return (-1);
+
+ if (ap->lsn.offset > bp->lsn.offset)
+ return (1);
+
+ return (0);
+}
+
+static int
+__rep_cmp_bylsn(a, b)
+ const void *a, *b;
+{
+ LSN_PAGE *ap, *bp;
+
+ ap = (LSN_PAGE *)a;
+ bp = (LSN_PAGE *)b;
+
+ if (ap->lsn.file < bp->lsn.file)
+ return (-1);
+
+ if (ap->lsn.file > bp->lsn.file)
+ return (1);
+
+ if (ap->lsn.offset < bp->lsn.offset)
+ return (-1);
+
+ if (ap->lsn.offset > bp->lsn.offset)
+ return (1);
+
+ if (ap->fid < bp->fid)
+ return (-1);
+
+ if (ap->fid > bp->fid)
+ return (1);
+
+ if (ap->pgdesc.pgno < bp->pgdesc.pgno)
+ return (-1);
+
+ if (ap->pgdesc.pgno > bp->pgdesc.pgno)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * __rep_is_client
+ * Used by other subsystems to figure out if this is a replication
+ * client sites.
+ *
+ * PUBLIC: int __rep_is_client __P((DB_ENV *));
+ */
+int
+__rep_is_client(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_REP *db_rep;
+ REP *rep;
+ int ret;
+
+ if ((db_rep = dbenv->rep_handle) == NULL)
+ return (0);
+ rep = db_rep->region;
+
+ MUTEX_LOCK(dbenv, db_rep->mutexp);
+ ret = F_ISSET(rep, REP_F_UPGRADE | REP_F_LOGSONLY);
+ MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+ return (ret);
+}
+
+/*
+ * __rep_send_vote
+ * Send this site's vote for the election.
+ *
+ * PUBLIC: int __rep_send_vote __P((DB_ENV *, DB_LSN *, int, int, int));
+ */
+int
+__rep_send_vote(dbenv, lsnp, nsites, pri, tiebreaker)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+ int nsites, pri, tiebreaker;
+{
+ DBT vote_dbt;
+ REP_VOTE_INFO vi;
+
+ memset(&vi, 0, sizeof(vi));
+
+ vi.priority = pri;
+ vi.nsites = nsites;
+ vi.tiebreaker = tiebreaker;
+
+ memset(&vote_dbt, 0, sizeof(vote_dbt));
+ vote_dbt.data = &vi;
+ vote_dbt.size = sizeof(vi);
+
+ return (__rep_send_message(dbenv,
+ DB_EID_BROADCAST, REP_VOTE1, lsnp, &vote_dbt, 0));
+}
+
+/*
+ * __rep_grow_sites --
+ * Called to allocate more space in the election tally information.
+ * Called with the rep mutex held. We need to call the region mutex, so
+ * we need to make sure that we *never* acquire those mutexes in the
+ * opposite order.
+ *
+ * PUBLIC: int __rep_grow_sites __P((DB_ENV *dbenv, int nsites));
+ */
+int
+__rep_grow_sites(dbenv, nsites)
+ DB_ENV *dbenv;
+ int nsites;
+{
+ REGENV *renv;
+ REGINFO *infop;
+ REP *rep;
+ int nalloc, ret, *tally;
+
+ rep = ((DB_REP *)dbenv->rep_handle)->region;
+
+ /*
+ * Allocate either twice the current allocation or nsites,
+ * whichever is more.
+ */
+
+ nalloc = 2 * rep->asites;
+ if (nalloc < nsites)
+ nalloc = nsites;
+
+ infop = dbenv->reginfo;
+ renv = infop->primary;
+ MUTEX_LOCK(dbenv, &renv->mutex);
+ if ((ret = __db_shalloc(infop->addr,
+ sizeof(nalloc * sizeof(int)), sizeof(int), &tally)) == 0) {
+ if (rep->tally_off != INVALID_ROFF)
+ __db_shalloc_free(infop->addr,
+ R_ADDR(infop, rep->tally_off));
+ rep->asites = nalloc;
+ rep->nsites = nsites;
+ rep->tally_off = R_OFFSET(infop, tally);
+ }
+ MUTEX_UNLOCK(dbenv, &renv->mutex);
+ return (ret);
+}
+
+#ifdef NOTYET
+static int __rep_send_file __P((DB_ENV *, DBT *, u_int32_t));
+/*
+ * __rep_send_file --
+ * Send an entire file, one block at a time.
+ */
+static int
+__rep_send_file(dbenv, rec, eid)
+ DB_ENV *dbenv;
+ DBT *rec;
+ u_int32_t eid;
+{
+ DB *dbp;
+ DB_LOCK lk;
+ DB_MPOOLFILE *mpf;
+ DBC *dbc;
+ DBT rec_dbt;
+ PAGE *pagep;
+ db_pgno_t last_pgno, pgno;
+ int ret, t_ret;
+
+ dbp = NULL;
+ dbc = NULL;
+ pagep = NULL;
+ mpf = NULL;
+ LOCK_INIT(lk);
+
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ goto err;
+
+ if ((ret = dbp->open(dbp, rec->data, NULL, DB_UNKNOWN, 0, 0)) != 0)
+ goto err;
+
+ if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+ goto err;
+ /*
+ * Force last_pgno to some value that will let us read the meta-dat
+ * page in the following loop.
+ */
+ memset(&rec_dbt, 0, sizeof(rec_dbt));
+ last_pgno = 1;
+ for (pgno = 0; pgno <= last_pgno; pgno++) {
+ if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lk)) != 0)
+ goto err;
+
+ if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0)
+ goto err;
+
+ if (pgno == 0)
+ last_pgno = ((DBMETA *)pagep)->last_pgno;
+
+ rec_dbt.data = pagep;
+ rec_dbt.size = dbp->pgsize;
+ if ((ret = __rep_send_message(dbenv, eid,
+ REP_FILE, NULL, &rec_dbt, pgno == last_pgno)) != 0)
+ goto err;
+ ret = mpf->put(mpf, pagep, 0);
+ pagep = NULL;
+ if (ret != 0)
+ goto err;
+ ret = __LPUT(dbc, lk);
+ LOCK_INIT(lk);
+ if (ret != 0)
+ goto err;
+ }
+
+err: if (LOCK_ISSET(lk) && (t_ret = __LPUT(dbc, lk)) != 0 && ret == 0)
+ ret = t_ret;
+ if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ if (pagep != NULL && (t_ret = mpf->put(mpf, pagep, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ return (ret);
+}
+#endif
+
+#if 0
+/*
+ * PUBLIC: void __rep_print_message __P((DB_ENV *, int, REP_CONTROL *, char *));
+ */
+void
+__rep_print_message(dbenv, eid, rp, str)
+ DB_ENV *dbenv;
+ int eid;
+ REP_CONTROL *rp;
+ char *str;
+{
+ char *type;
+ switch (rp->rectype) {
+ case REP_ALIVE:
+ type = "alive";
+ break;
+ case REP_ALIVE_REQ:
+ type = "alive_req";
+ break;
+ case REP_ALL_REQ:
+ type = "all_req";
+ break;
+ case REP_ELECT:
+ type = "elect";
+ break;
+ case REP_FILE:
+ type = "file";
+ break;
+ case REP_FILE_REQ:
+ type = "file_req";
+ break;
+ case REP_LOG:
+ type = "log";
+ break;
+ case REP_LOG_MORE:
+ type = "log_more";
+ break;
+ case REP_LOG_REQ:
+ type = "log_req";
+ break;
+ case REP_MASTER_REQ:
+ type = "master_req";
+ break;
+ case REP_NEWCLIENT:
+ type = "newclient";
+ break;
+ case REP_NEWFILE:
+ type = "newfile";
+ break;
+ case REP_NEWMASTER:
+ type = "newmaster";
+ break;
+ case REP_NEWSITE:
+ type = "newsite";
+ break;
+ case REP_PAGE:
+ type = "page";
+ break;
+ case REP_PAGE_REQ:
+ type = "page_req";
+ break;
+ case REP_PLIST:
+ type = "plist";
+ break;
+ case REP_PLIST_REQ:
+ type = "plist_req";
+ break;
+ case REP_VERIFY:
+ type = "verify";
+ break;
+ case REP_VERIFY_FAIL:
+ type = "verify_fail";
+ break;
+ case REP_VERIFY_REQ:
+ type = "verify_req";
+ break;
+ case REP_VOTE1:
+ type = "vote1";
+ break;
+ case REP_VOTE2:
+ type = "vote2";
+ break;
+ default:
+ type = "NOTYPE";
+ break;
+ }
+ printf("%s %s: gen = %d eid %d, type %s, LSN [%u][%u]\n",
+ dbenv->db_home, str, rp->gen, eid, type, rp->lsn.file,
+ rp->lsn.offset);
+}
+#endif
diff --git a/bdb/rpc_client/client.c b/bdb/rpc_client/client.c
index 70744f54b4c..b6367e21449 100644
--- a/bdb/rpc_client/client.c
+++ b/bdb/rpc_client/client.c
@@ -1,20 +1,23 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: client.c,v 1.21 2000/11/30 00:58:44 ubell Exp $";
+static const char revid[] = "$Id: client.c,v 1.51 2002/08/06 06:18:15 bostic Exp $";
#endif /* not lint */
#ifdef HAVE_RPC
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#ifdef HAVE_VXWORKS
+#include <rpcLib.h>
+#endif
#include <rpc/rpc.h>
#include <ctype.h>
@@ -22,71 +25,124 @@ static const char revid[] = "$Id: client.c,v 1.21 2000/11/30 00:58:44 ubell Exp
#include <string.h>
#include <unistd.h>
#endif
-#include "db_server.h"
#include "db_int.h"
-#include "txn.h"
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/txn.h"
+
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
+
+static int __dbcl_c_destroy __P((DBC *));
+static int __dbcl_txn_close __P((DB_ENV *));
/*
- * __dbclenv_server --
+ * __dbcl_envrpcserver --
* Initialize an environment's server.
*
- * PUBLIC: int __dbcl_envserver __P((DB_ENV *, char *, long, long, u_int32_t));
+ * PUBLIC: int __dbcl_envrpcserver
+ * PUBLIC: __P((DB_ENV *, void *, const char *, long, long, u_int32_t));
*/
int
-__dbcl_envserver(dbenv, host, tsec, ssec, flags)
+__dbcl_envrpcserver(dbenv, clnt, host, tsec, ssec, flags)
DB_ENV *dbenv;
- char *host;
+ void *clnt;
+ const char *host;
long tsec, ssec;
u_int32_t flags;
{
CLIENT *cl;
- __env_create_msg req;
- __env_create_reply *replyp;
struct timeval tp;
- int ret;
COMPQUIET(flags, 0);
#ifdef HAVE_VXWORKS
- if ((ret = rpcTaskInit()) != 0) {
+ if (rpcTaskInit() != 0) {
__db_err(dbenv, "Could not initialize VxWorks RPC");
return (ERROR);
}
#endif
- if ((cl =
- clnt_create(host, DB_SERVERPROG, DB_SERVERVERS, "tcp")) == NULL) {
- __db_err(dbenv, clnt_spcreateerror(host));
- return (DB_NOSERVER);
+ if (RPC_ON(dbenv)) {
+ __db_err(dbenv, "Already set an RPC handle");
+ return (EINVAL);
}
- dbenv->cl_handle = cl;
-
- if (tsec != 0) {
- tp.tv_sec = tsec;
- tp.tv_usec = 0;
- (void)clnt_control(cl, CLSET_TIMEOUT, (char *)&tp);
- }
-
- req.timeout = ssec;
/*
- * CALL THE SERVER
+ * Only create the client and set its timeout if the user
+ * did not pass us a client structure to begin with.
*/
- if ((replyp = __db_env_create_1(&req, cl)) == NULL) {
- __db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
- return (DB_NOSERVER);
+ if (clnt == NULL) {
+ if ((cl = clnt_create((char *)host, DB_RPC_SERVERPROG,
+ DB_RPC_SERVERVERS, "tcp")) == NULL) {
+ __db_err(dbenv, clnt_spcreateerror((char *)host));
+ return (DB_NOSERVER);
+ }
+ if (tsec != 0) {
+ tp.tv_sec = tsec;
+ tp.tv_usec = 0;
+ (void)clnt_control(cl, CLSET_TIMEOUT, (char *)&tp);
+ }
+ } else {
+ cl = (CLIENT *)clnt;
+ F_SET(dbenv, DB_ENV_RPCCLIENT_GIVEN);
}
+ dbenv->cl_handle = cl;
- /*
- * Process reply and free up our space from request
- * SUCCESS: Store ID from server.
- */
- if ((ret = replyp->status) != 0)
+ return (__dbcl_env_create(dbenv, ssec));
+}
+
+/*
+ * __dbcl_env_open_wrap --
+ * Wrapper function for DB_ENV->open function for clients.
+ * We need a wrapper function to deal with DB_USE_ENVIRON* flags
+ * and we don't want to complicate the generated code for env_open.
+ *
+ * PUBLIC: int __dbcl_env_open_wrap
+ * PUBLIC: __P((DB_ENV *, const char *, u_int32_t, int));
+ */
+int
+__dbcl_env_open_wrap(dbenv, home, flags, mode)
+ DB_ENV * dbenv;
+ const char * home;
+ u_int32_t flags;
+ int mode;
+{
+ int ret;
+
+ if (LF_ISSET(DB_THREAD)) {
+ __db_err(dbenv, "DB_THREAD not allowed on RPC clients");
+ return (EINVAL);
+ }
+ if ((ret = __db_home(dbenv, home, flags)) != 0)
return (ret);
+ return (__dbcl_env_open(dbenv, dbenv->db_home, flags, mode));
+}
- dbenv->cl_id = replyp->envcl_id;
- return (0);
+/*
+ * __dbcl_db_open_wrap --
+ * Wrapper function for DB->open function for clients.
+ * We need a wrapper function to error on DB_THREAD flag.
+ * and we don't want to complicate the generated code.
+ *
+ * PUBLIC: int __dbcl_db_open_wrap
+ * PUBLIC: __P((DB *, DB_TXN *, const char *, const char *,
+ * PUBLIC: DBTYPE, u_int32_t, int));
+ */
+int
+__dbcl_db_open_wrap(dbp, txnp, name, subdb, type, flags, mode)
+ DB * dbp;
+ DB_TXN * txnp;
+ const char * name;
+ const char * subdb;
+ DBTYPE type;
+ u_int32_t flags;
+ int mode;
+{
+ if (LF_ISSET(DB_THREAD)) {
+ __db_err(dbp->dbenv, "DB_THREAD not allowed on RPC clients");
+ return (EINVAL);
+ }
+ return (__dbcl_db_open(dbp, txnp, name, subdb, type, flags, mode));
}
/*
@@ -114,17 +170,50 @@ __dbcl_refresh(dbenv)
ret = __dbcl_txn_close(dbenv);
dbenv->tx_handle = NULL;
}
- if (cl != NULL)
+ if (!F_ISSET(dbenv, DB_ENV_RPCCLIENT_GIVEN) && cl != NULL)
clnt_destroy(cl);
dbenv->cl_handle = NULL;
+ if (dbenv->db_home != NULL) {
+ __os_free(dbenv, dbenv->db_home);
+ dbenv->db_home = NULL;
+ }
+ return (ret);
+}
+
+/*
+ * __dbcl_retcopy --
+ * Copy the returned data into the user's DBT, handling allocation flags,
+ * but not DB_DBT_PARTIAL.
+ *
+ * PUBLIC: int __dbcl_retcopy __P((DB_ENV *, DBT *,
+ * PUBLIC: void *, u_int32_t, void **, u_int32_t *));
+ */
+int
+__dbcl_retcopy(dbenv, dbt, data, len, memp, memsize)
+ DB_ENV *dbenv;
+ DBT *dbt;
+ void *data;
+ u_int32_t len;
+ void **memp;
+ u_int32_t *memsize;
+{
+ int ret;
+ u_int32_t orig_flags;
+
+ /*
+ * The RPC server handles DB_DBT_PARTIAL, so we mask it out here to
+ * avoid the handling of partials in __db_retcopy.
+ */
+ orig_flags = dbt->flags;
+ F_CLR(dbt, DB_DBT_PARTIAL);
+ ret = __db_retcopy(dbenv, dbt, data, len, memp, memsize);
+ dbt->flags = orig_flags;
return (ret);
}
/*
* __dbcl_txn_close --
* Clean up an environment's transactions.
- *
- * PUBLIC: int __dbcl_txn_close __P((DB_ENV *));
*/
int
__dbcl_txn_close(dbenv)
@@ -147,7 +236,7 @@ __dbcl_txn_close(dbenv)
while ((txnp = TAILQ_FIRST(&tmgrp->txn_chain)) != NULL)
__dbcl_txn_end(txnp);
- __os_free(tmgrp, sizeof(*tmgrp));
+ __os_free(dbenv, tmgrp);
return (ret);
}
@@ -187,18 +276,57 @@ __dbcl_txn_end(txnp)
if (txnp->parent != NULL)
TAILQ_REMOVE(&txnp->parent->kids, txnp, klinks);
TAILQ_REMOVE(&mgr->txn_chain, txnp, links);
- __os_free(txnp, sizeof(*txnp));
+ __os_free(dbenv, txnp);
+}
- return;
+/*
+ * __dbcl_txn_setup --
+ * Setup a client transaction structure.
+ *
+ * PUBLIC: void __dbcl_txn_setup __P((DB_ENV *, DB_TXN *, DB_TXN *, u_int32_t));
+ */
+void
+__dbcl_txn_setup(dbenv, txn, parent, id)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB_TXN *parent;
+ u_int32_t id;
+{
+ txn->mgrp = dbenv->tx_handle;
+ txn->parent = parent;
+ txn->txnid = id;
+
+ /*
+ * XXX
+ * In DB library the txn_chain is protected by the mgrp->mutexp.
+ * However, that mutex is implemented in the environments shared
+ * memory region. The client library does not support all of the
+ * region - that just get forwarded to the server. Therefore,
+ * the chain is unprotected here, but properly protected on the
+ * server.
+ */
+ TAILQ_INSERT_TAIL(&txn->mgrp->txn_chain, txn, links);
+
+ TAILQ_INIT(&txn->kids);
+
+ if (parent != NULL)
+ TAILQ_INSERT_HEAD(&parent->kids, txn, klinks);
+
+ txn->abort = __dbcl_txn_abort;
+ txn->commit = __dbcl_txn_commit;
+ txn->discard = __dbcl_txn_discard;
+ txn->id = __txn_id;
+ txn->prepare = __dbcl_txn_prepare;
+ txn->set_timeout = __dbcl_txn_timeout;
+
+ txn->flags = TXN_MALLOC;
}
/*
* __dbcl_c_destroy --
* Destroy a cursor.
- *
- * PUBLIC: int __dbcl_c_destroy __P((DBC *));
*/
-int
+static int
__dbcl_c_destroy(dbc)
DBC *dbc;
{
@@ -207,7 +335,14 @@ __dbcl_c_destroy(dbc)
dbp = dbc->dbp;
TAILQ_REMOVE(&dbp->free_queue, dbc, links);
- __os_free(dbc, sizeof(*dbc));
+ /* Discard any memory used to store returned data. */
+ if (dbc->my_rskey.data != NULL)
+ __os_free(dbc->dbp->dbenv, dbc->my_rskey.data);
+ if (dbc->my_rkey.data != NULL)
+ __os_free(dbc->dbp->dbenv, dbc->my_rkey.data);
+ if (dbc->my_rdata.data != NULL)
+ __os_free(dbc->dbp->dbenv, dbc->my_rdata.data);
+ __os_free(NULL, dbc);
return (0);
}
@@ -219,24 +354,23 @@ __dbcl_c_destroy(dbc)
* PUBLIC: void __dbcl_c_refresh __P((DBC *));
*/
void
-__dbcl_c_refresh(dbcp)
- DBC *dbcp;
+__dbcl_c_refresh(dbc)
+ DBC *dbc;
{
DB *dbp;
- dbp = dbcp->dbp;
- dbcp->flags = 0;
- dbcp->cl_id = 0;
+ dbp = dbc->dbp;
+ dbc->flags = 0;
+ dbc->cl_id = 0;
/*
* If dbp->cursor fails locally, we use a local dbc so that
* we can close it. In that case, dbp will be NULL.
*/
if (dbp != NULL) {
- TAILQ_REMOVE(&dbp->active_queue, dbcp, links);
- TAILQ_INSERT_TAIL(&dbp->free_queue, dbcp, links);
+ TAILQ_REMOVE(&dbp->active_queue, dbc, links);
+ TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
}
- return;
}
/*
@@ -246,13 +380,13 @@ __dbcl_c_refresh(dbcp)
* PUBLIC: int __dbcl_c_setup __P((long, DB *, DBC **));
*/
int
-__dbcl_c_setup(cl_id, dbp, dbcpp)
+__dbcl_c_setup(cl_id, dbp, dbcp)
long cl_id;
DB *dbp;
- DBC **dbcpp;
+ DBC **dbcp;
{
DBC *dbc, tmpdbc;
- int ret, t_ret;
+ int ret;
if ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
TAILQ_REMOVE(&dbp->free_queue, dbc, links);
@@ -260,12 +394,12 @@ __dbcl_c_setup(cl_id, dbp, dbcpp)
if ((ret =
__os_calloc(dbp->dbenv, 1, sizeof(DBC), &dbc)) != 0) {
/*
- * If we die here, set up a tmp dbc to call the
- * server to shut down that cursor.
- */
+ * If we die here, set up a tmp dbc to call the
+ * server to shut down that cursor.
+ */
tmpdbc.dbp = NULL;
tmpdbc.cl_id = cl_id;
- t_ret = __dbcl_dbc_close(&tmpdbc);
+ (void)__dbcl_dbc_close(&tmpdbc);
return (ret);
}
dbc->c_close = __dbcl_dbc_close;
@@ -273,62 +407,14 @@ __dbcl_c_setup(cl_id, dbp, dbcpp)
dbc->c_del = __dbcl_dbc_del;
dbc->c_dup = __dbcl_dbc_dup;
dbc->c_get = __dbcl_dbc_get;
+ dbc->c_pget = __dbcl_dbc_pget;
dbc->c_put = __dbcl_dbc_put;
dbc->c_am_destroy = __dbcl_c_destroy;
}
dbc->cl_id = cl_id;
dbc->dbp = dbp;
TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
- *dbcpp = dbc;
- return (0);
-}
-
-/*
- * __dbcl_retcopy --
- * Copy the returned data into the user's DBT, handling special flags
- * as they apply to a client. Modeled after __db_retcopy().
- *
- * PUBLIC: int __dbcl_retcopy __P((DB_ENV *, DBT *, void *, u_int32_t));
- */
-int
-__dbcl_retcopy(dbenv, dbt, data, len)
- DB_ENV *dbenv;
- DBT *dbt;
- void *data;
- u_int32_t len;
-{
- int ret;
-
- /*
- * No need to handle DB_DBT_PARTIAL here, server already did.
- */
- dbt->size = len;
-
- /*
- * Allocate memory to be owned by the application: DB_DBT_MALLOC
- * and DB_DBT_REALLOC. Always allocate even if we're copying 0 bytes.
- * Or use memory specified by application: DB_DBT_USERMEM.
- */
- if (F_ISSET(dbt, DB_DBT_MALLOC)) {
- if ((ret = __os_malloc(dbenv, len, NULL, &dbt->data)) != 0)
- return (ret);
- } else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
- if ((ret = __os_realloc(dbenv, len, NULL, &dbt->data)) != 0)
- return (ret);
- } else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
- if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
- return (ENOMEM);
- } else {
- /*
- * If no user flags, then set the DBT to point to the
- * returned data pointer and return.
- */
- dbt->data = data;
- return (0);
- }
-
- if (len != 0)
- memcpy(dbt->data, data, len);
+ *dbcp = dbc;
return (0);
}
@@ -363,9 +449,16 @@ __dbcl_dbclose_common(dbp)
TAILQ_INIT(&dbp->free_queue);
TAILQ_INIT(&dbp->active_queue);
+ /* Discard any memory used to store returned data. */
+ if (dbp->my_rskey.data != NULL)
+ __os_free(dbp->dbenv, dbp->my_rskey.data);
+ if (dbp->my_rkey.data != NULL)
+ __os_free(dbp->dbenv, dbp->my_rkey.data);
+ if (dbp->my_rdata.data != NULL)
+ __os_free(dbp->dbenv, dbp->my_rdata.data);
memset(dbp, CLEAR_BYTE, sizeof(*dbp));
- __os_free(dbp, sizeof(*dbp));
+ __os_free(NULL, dbp);
return (ret);
}
#endif /* HAVE_RPC */
diff --git a/bdb/rpc_client/gen_client_ret.c b/bdb/rpc_client/gen_client_ret.c
index 17e3f195fc3..f35589738cd 100644
--- a/bdb/rpc_client/gen_client_ret.c
+++ b/bdb/rpc_client/gen_client_ret.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: gen_client_ret.c,v 1.29 2000/12/31 19:26:23 bostic Exp $";
+static const char revid[] = "$Id: gen_client_ret.c,v 1.57 2002/08/06 06:18:37 bostic Exp $";
#endif /* not lint */
#ifdef HAVE_RPC
@@ -19,17 +19,19 @@ static const char revid[] = "$Id: gen_client_ret.c,v 1.29 2000/12/31 19:26:23 bo
#include <string.h>
#endif
-#include "db_server.h"
#include "db_int.h"
-#include "db_page.h"
-#include "txn.h"
-#include "db_ext.h"
-#include "rpc_client_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/txn.h"
-static void __db_db_stat_statsfree __P((u_int32_t *));
-static int __db_db_stat_statslist __P((__db_stat_statsreplist *, u_int32_t **));
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
+/*
+ * PUBLIC: int __dbcl_env_close_ret
+ * PUBLIC: __P((DB_ENV *, u_int32_t, __env_close_reply *));
+ */
int
__dbcl_env_close_ret(dbenv, flags, replyp)
DB_ENV *dbenv;
@@ -41,13 +43,36 @@ __dbcl_env_close_ret(dbenv, flags, replyp)
COMPQUIET(flags, 0);
ret = __dbcl_refresh(dbenv);
- __os_free(dbenv, sizeof(*dbenv));
+ __os_free(NULL, dbenv);
if (replyp->status == 0 && ret != 0)
return (ret);
else
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_env_create_ret
+ * PUBLIC: __P((DB_ENV *, long, __env_create_reply *));
+ */
+int
+__dbcl_env_create_ret(dbenv, timeout, replyp)
+ DB_ENV * dbenv;
+ long timeout;
+ __env_create_reply *replyp;
+{
+
+ COMPQUIET(timeout, 0);
+
+ if (replyp->status != 0)
+ return (replyp->status);
+ dbenv->cl_id = replyp->envcl_id;
+ return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_open_ret __P((DB_ENV *,
+ * PUBLIC: const char *, u_int32_t, int, __env_open_reply *));
+ */
int
__dbcl_env_open_ret(dbenv, home, flags, mode, replyp)
DB_ENV *dbenv;
@@ -68,6 +93,7 @@ __dbcl_env_open_ret(dbenv, home, flags, mode, replyp)
if (replyp->status != 0)
return (replyp->status);
+ dbenv->cl_id = replyp->envcl_id;
/*
* If the user requested transactions, then we have some
* local client-side setup to do also.
@@ -84,6 +110,10 @@ __dbcl_env_open_ret(dbenv, home, flags, mode, replyp)
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_env_remove_ret
+ * PUBLIC: __P((DB_ENV *, const char *, u_int32_t, __env_remove_reply *));
+ */
int
__dbcl_env_remove_ret(dbenv, home, flags, replyp)
DB_ENV *dbenv;
@@ -97,13 +127,16 @@ __dbcl_env_remove_ret(dbenv, home, flags, replyp)
COMPQUIET(flags, 0);
ret = __dbcl_refresh(dbenv);
- __os_free(dbenv, sizeof(*dbenv));
+ __os_free(NULL, dbenv);
if (replyp->status == 0 && ret != 0)
return (ret);
else
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_txn_abort_ret __P((DB_TXN *, __txn_abort_reply *));
+ */
int
__dbcl_txn_abort_ret(txnp, replyp)
DB_TXN *txnp;
@@ -113,6 +146,10 @@ __dbcl_txn_abort_ret(txnp, replyp)
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_txn_begin_ret __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, DB_TXN **, u_int32_t, __txn_begin_reply *));
+ */
int
__dbcl_txn_begin_ret(envp, parent, txnpp, flags, replyp)
DB_ENV *envp;
@@ -130,29 +167,15 @@ __dbcl_txn_begin_ret(envp, parent, txnpp, flags, replyp)
if ((ret = __os_calloc(envp, 1, sizeof(DB_TXN), &txn)) != 0)
return (ret);
- txn->txnid = replyp->txnidcl_id;
- txn->mgrp = envp->tx_handle;
- txn->parent = parent;
- TAILQ_INIT(&txn->kids);
- txn->flags = TXN_MALLOC;
- if (parent != NULL)
- TAILQ_INSERT_HEAD(&parent->kids, txn, klinks);
-
- /*
- * XXX
- * In DB library the txn_chain is protected by the mgrp->mutexp.
- * However, that mutex is implemented in the environments shared
- * memory region. The client library does not support all of the
- * region - that just get forwarded to the server. Therefore,
- * the chain is unprotected here, but properly protected on the
- * server.
- */
- TAILQ_INSERT_TAIL(&txn->mgrp->txn_chain, txn, links);
-
+ __dbcl_txn_setup(envp, txn, parent, replyp->txnidcl_id);
*txnpp = txn;
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_txn_commit_ret
+ * PUBLIC: __P((DB_TXN *, u_int32_t, __txn_commit_reply *));
+ */
int
__dbcl_txn_commit_ret(txnp, flags, replyp)
DB_TXN *txnp;
@@ -165,6 +188,83 @@ __dbcl_txn_commit_ret(txnp, flags, replyp)
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_txn_discard_ret __P((DB_TXN *, u_int32_t,
+ * PUBLIC: __txn_discard_reply *));
+ */
+int
+__dbcl_txn_discard_ret(txnp, flags, replyp)
+ DB_TXN * txnp;
+ u_int32_t flags;
+ __txn_discard_reply *replyp;
+{
+ COMPQUIET(flags, 0);
+
+ __dbcl_txn_end(txnp);
+ return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_recover_ret __P((DB_ENV *, DB_PREPLIST *, long,
+ * PUBLIC: long *, u_int32_t, __txn_recover_reply *));
+ */
+int
+__dbcl_txn_recover_ret(dbenv, preplist, count, retp, flags, replyp)
+ DB_ENV * dbenv;
+ DB_PREPLIST * preplist;
+ long count;
+ long * retp;
+ u_int32_t flags;
+ __txn_recover_reply *replyp;
+{
+ DB_PREPLIST *prep;
+ DB_TXN *txnarray, *txn;
+ u_int32_t i, *txnid;
+ int ret;
+ u_int8_t *gid;
+
+ COMPQUIET(flags, 0);
+ COMPQUIET(count, 0);
+
+ if (replyp->status != 0)
+ return (replyp->status);
+
+ *retp = (long) replyp->retcount;
+
+ if (replyp->retcount == 0)
+ return (replyp->status);
+
+ if ((ret = __os_calloc(dbenv, replyp->retcount, sizeof(DB_TXN),
+ &txnarray)) != 0)
+ return (ret);
+ /*
+ * We have a bunch of arrays that need to iterate in
+ * lockstep with each other.
+ */
+ i = 0;
+ txn = txnarray;
+ txnid = (u_int32_t *)replyp->txn.txn_val;
+ gid = (u_int8_t *)replyp->gid.gid_val;
+ prep = preplist;
+ while (i++ < replyp->retcount) {
+ __dbcl_txn_setup(dbenv, txn, NULL, *txnid);
+ prep->txn = txn;
+ memcpy(&prep->gid, gid, DB_XIDDATASIZE);
+ /*
+ * Now increment all our array pointers.
+ */
+ txn++;
+ gid += DB_XIDDATASIZE;
+ txnid++;
+ prep++;
+ }
+
+ return (0);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_close_ret __P((DB *, u_int32_t, __db_close_reply *));
+ */
int
__dbcl_db_close_ret(dbp, flags, replyp)
DB *dbp;
@@ -183,6 +283,30 @@ __dbcl_db_close_ret(dbp, flags, replyp)
return (ret);
}
+/*
+ * PUBLIC: int __dbcl_db_create_ret
+ * PUBLIC: __P((DB *, DB_ENV *, u_int32_t, __db_create_reply *));
+ */
+int
+__dbcl_db_create_ret(dbp, dbenv, flags, replyp)
+ DB * dbp;
+ DB_ENV * dbenv;
+ u_int32_t flags;
+ __db_create_reply *replyp;
+{
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(flags, 0);
+
+ if (replyp->status != 0)
+ return (replyp->status);
+ dbp->cl_id = replyp->dbcl_id;
+ return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_ret
+ * PUBLIC: __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t, __db_get_reply *));
+ */
int
__dbcl_db_get_ret(dbp, txnp, key, data, flags, replyp)
DB *dbp;
@@ -206,20 +330,26 @@ __dbcl_db_get_ret(dbp, txnp, key, data, flags, replyp)
oldkey = key->data;
ret = __dbcl_retcopy(dbenv, key, replyp->keydata.keydata_val,
- replyp->keydata.keydata_len);
+ replyp->keydata.keydata_len, &dbp->my_rkey.data,
+ &dbp->my_rkey.ulen);
if (ret)
return (ret);
ret = __dbcl_retcopy(dbenv, data, replyp->datadata.datadata_val,
- replyp->datadata.datadata_len);
+ replyp->datadata.datadata_len, &dbp->my_rdata.data,
+ &dbp->my_rdata.ulen);
/*
* If an error on copying 'data' and we allocated for 'key'
* free it before returning the error.
*/
if (ret && oldkey != NULL)
- __os_free(key->data, key->size);
+ __os_free(dbenv, key->data);
return (ret);
}
+/*
+ * PUBLIC: int __dbcl_db_key_range_ret __P((DB *, DB_TXN *,
+ * PUBLIC: DBT *, DB_KEY_RANGE *, u_int32_t, __db_key_range_reply *));
+ */
int
__dbcl_db_key_range_ret(dbp, txnp, key, range, flags, replyp)
DB *dbp;
@@ -242,32 +372,114 @@ __dbcl_db_key_range_ret(dbp, txnp, key, range, flags, replyp)
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_db_open_ret __P((DB *, DB_TXN *, const char *,
+ * PUBLIC: const char *, DBTYPE, u_int32_t, int, __db_open_reply *));
+ */
int
-__dbcl_db_open_ret(dbp, name, subdb, type, flags, mode, replyp)
+__dbcl_db_open_ret(dbp, txn, name, subdb, type, flags, mode, replyp)
DB *dbp;
+ DB_TXN *txn;
const char *name, *subdb;
DBTYPE type;
u_int32_t flags;
int mode;
__db_open_reply *replyp;
{
+ COMPQUIET(txn, NULL);
COMPQUIET(name, NULL);
COMPQUIET(subdb, NULL);
COMPQUIET(type, 0);
COMPQUIET(flags, 0);
COMPQUIET(mode, 0);
- dbp->type = replyp->type;
+ if (replyp->status == 0) {
+ dbp->cl_id = replyp->dbcl_id;
+ dbp->type = replyp->type;
+ /*
+ * We get back the database's byteorder on the server.
+ * Determine if our byteorder is the same or not by
+ * calling __db_set_lorder.
+ *
+ * XXX
+ * This MUST come before we set the flags because
+ * __db_set_lorder checks that it is called before
+ * the open flag is set.
+ */
+ (void)__db_set_lorder(dbp, replyp->lorder);
+
+ /*
+ * XXX
+ * This is only for Tcl which peeks at the dbp flags.
+ * When dbp->get_flags exists, this should go away.
+ */
+ dbp->flags = replyp->dbflags;
+ }
+ return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_pget_ret __P((DB *, DB_TXN *, DBT *, DBT *, DBT *,
+ * PUBLIC: u_int32_t, __db_pget_reply *));
+ */
+int
+__dbcl_db_pget_ret(dbp, txnp, skey, pkey, data, flags, replyp)
+ DB * dbp;
+ DB_TXN * txnp;
+ DBT * skey;
+ DBT * pkey;
+ DBT * data;
+ u_int32_t flags;
+ __db_pget_reply *replyp;
+{
+ DB_ENV *dbenv;
+ int ret;
+ void *oldskey, *oldpkey;
+
+ COMPQUIET(txnp, NULL);
+ COMPQUIET(flags, 0);
+ ret = 0;
+ if (replyp->status != 0)
+ return (replyp->status);
+
+ dbenv = dbp->dbenv;
+
+ oldskey = skey->data;
+ ret = __dbcl_retcopy(dbenv, skey, replyp->skeydata.skeydata_val,
+ replyp->skeydata.skeydata_len, &dbp->my_rskey.data,
+ &dbp->my_rskey.ulen);
+ if (ret)
+ return (ret);
+
+ oldpkey = pkey->data;
+ ret = __dbcl_retcopy(dbenv, pkey, replyp->pkeydata.pkeydata_val,
+ replyp->pkeydata.pkeydata_len, &dbp->my_rkey.data,
+ &dbp->my_rkey.ulen);
+ if (ret && oldskey != NULL) {
+ __os_free(dbenv, skey->data);
+ return (ret);
+ }
+ ret = __dbcl_retcopy(dbenv, data, replyp->datadata.datadata_val,
+ replyp->datadata.datadata_len, &dbp->my_rdata.data,
+ &dbp->my_rdata.ulen);
/*
- * XXX
- * This is only for Tcl which peeks at the dbp flags.
- * When dbp->get_flags exists, this should go away.
+ * If an error on copying 'data' and we allocated for '*key'
+ * free it before returning the error.
*/
- dbp->flags = replyp->dbflags;
- return (replyp->status);
+ if (ret) {
+ if (oldskey != NULL)
+ __os_free(dbenv, skey->data);
+ if (oldpkey != NULL)
+ __os_free(dbenv, pkey->data);
+ }
+ return (ret);
}
+/*
+ * PUBLIC: int __dbcl_db_put_ret
+ * PUBLIC: __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t, __db_put_reply *));
+ */
int
__dbcl_db_put_ret(dbp, txnp, key, data, flags, replyp)
DB *dbp;
@@ -289,6 +501,10 @@ __dbcl_db_put_ret(dbp, txnp, key, data, flags, replyp)
return (ret);
}
+/*
+ * PUBLIC: int __dbcl_db_remove_ret __P((DB *,
+ * PUBLIC: const char *, const char *, u_int32_t, __db_remove_reply *));
+ */
int
__dbcl_db_remove_ret(dbp, name, subdb, flags, replyp)
DB *dbp;
@@ -310,12 +526,16 @@ __dbcl_db_remove_ret(dbp, name, subdb, flags, replyp)
return (ret);
}
+/*
+ * PUBLIC: int __dbcl_db_rename_ret __P((DB *, const char *,
+ * PUBLIC: const char *, const char *, u_int32_t, __db_rename_reply *));
+ */
int
__dbcl_db_rename_ret(dbp, name, subdb, newname, flags, replyp)
DB *dbp;
const char *name, *subdb, *newname;
u_int32_t flags;
- __db_remove_reply *replyp;
+ __db_rename_reply *replyp;
{
int ret;
@@ -332,82 +552,66 @@ __dbcl_db_rename_ret(dbp, name, subdb, newname, flags, replyp)
return (ret);
}
+/*
+ * PUBLIC: int __dbcl_db_stat_ret
+ * PUBLIC: __P((DB *, void *, u_int32_t, __db_stat_reply *));
+ */
int
-__dbcl_db_stat_ret(dbp, sp, func, flags, replyp)
+__dbcl_db_stat_ret(dbp, sp, flags, replyp)
DB *dbp;
void *sp;
- void *(*func) __P((size_t));
u_int32_t flags;
__db_stat_reply *replyp;
{
- int ret;
- u_int32_t *__db_statslist;
+ int len, ret;
+ u_int32_t i, *q, *p, *retsp;
- COMPQUIET(dbp, NULL);
- COMPQUIET(func, NULL);
COMPQUIET(flags, 0);
- if (replyp->status != 0)
+ if (replyp->status != 0 || sp == NULL)
return (replyp->status);
- if ((ret =
- __db_db_stat_statslist(replyp->statslist, &__db_statslist)) != 0)
- return (ret);
-
- if (sp == NULL)
- __db_db_stat_statsfree(__db_statslist);
- else
- *(u_int32_t **)sp = __db_statslist;
- return (replyp->status);
-}
-
-static int
-__db_db_stat_statslist(locp, ppp)
- __db_stat_statsreplist *locp;
- u_int32_t **ppp;
-{
- u_int32_t *pp;
- int cnt, ret, size;
- __db_stat_statsreplist *nl;
-
- for (cnt = 0, nl = locp; nl != NULL; cnt++, nl = nl->next)
- ;
-
- if (cnt == 0) {
- *ppp = NULL;
- return (0);
- }
- size = sizeof(*pp) * cnt;
- if ((ret = __os_malloc(NULL, size, NULL, ppp)) != 0)
+ len = replyp->stats.stats_len * sizeof(u_int32_t);
+ if ((ret = __os_umalloc(dbp->dbenv, len, &retsp)) != 0)
return (ret);
- memset(*ppp, 0, size);
- for (pp = *ppp, nl = locp; nl != NULL; nl = nl->next, pp++) {
- *pp = *(u_int32_t *)nl->ent.ent_val;
- }
+ for (i = 0, q = retsp, p = (u_int32_t *)replyp->stats.stats_val;
+ i < replyp->stats.stats_len; i++, q++, p++)
+ *q = *p;
+ *(u_int32_t **)sp = retsp;
return (0);
}
-static void
-__db_db_stat_statsfree(pp)
- u_int32_t *pp;
+/*
+ * PUBLIC: int __dbcl_db_truncate_ret __P((DB *, DB_TXN *, u_int32_t *,
+ * PUBLIC: u_int32_t, __db_truncate_reply *));
+ */
+int
+__dbcl_db_truncate_ret(dbp, txnp, countp, flags, replyp)
+ DB *dbp;
+ DB_TXN *txnp;
+ u_int32_t *countp, flags;
+ __db_truncate_reply *replyp;
{
- size_t size;
- u_int32_t *p;
+ COMPQUIET(dbp, NULL);
+ COMPQUIET(txnp, NULL);
+ COMPQUIET(flags, 0);
- if (pp == NULL)
- return;
- size = sizeof(*p);
- for (p = pp; *p != 0; p++)
- size += sizeof(*p);
+ if (replyp->status != 0)
+ return (replyp->status);
+ *countp = replyp->count;
- __os_free(pp, size);
+ return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_db_cursor_ret
+ * PUBLIC: __P((DB *, DB_TXN *, DBC **, u_int32_t, __db_cursor_reply *));
+ */
int
-__dbcl_db_cursor_ret(dbp, txnp, dbcpp, flags, replyp)
+__dbcl_db_cursor_ret(dbp, txnp, dbcp, flags, replyp)
DB *dbp;
DB_TXN *txnp;
- DBC **dbcpp;
+ DBC **dbcp;
u_int32_t flags;
__db_cursor_reply *replyp;
{
@@ -417,13 +621,17 @@ __dbcl_db_cursor_ret(dbp, txnp, dbcpp, flags, replyp)
if (replyp->status != 0)
return (replyp->status);
- return (__dbcl_c_setup(replyp->dbcidcl_id, dbp, dbcpp));
+ return (__dbcl_c_setup(replyp->dbcidcl_id, dbp, dbcp));
}
+/*
+ * PUBLIC: int __dbcl_db_join_ret
+ * PUBLIC: __P((DB *, DBC **, DBC **, u_int32_t, __db_join_reply *));
+ */
int
-__dbcl_db_join_ret(dbp, curs, dbcpp, flags, replyp)
+__dbcl_db_join_ret(dbp, curs, dbcp, flags, replyp)
DB *dbp;
- DBC **curs, **dbcpp;
+ DBC **curs, **dbcp;
u_int32_t flags;
__db_join_reply *replyp;
{
@@ -440,21 +648,25 @@ __dbcl_db_join_ret(dbp, curs, dbcpp, flags, replyp)
* client-side cursor/db relationship to know what cursors
* are open in the db, and to store their ID. Nothing else.
*/
- return (__dbcl_c_setup(replyp->dbcidcl_id, dbp, dbcpp));
+ return (__dbcl_c_setup(replyp->dbcidcl_id, dbp, dbcp));
}
+/*
+ * PUBLIC: int __dbcl_dbc_close_ret __P((DBC *, __dbc_close_reply *));
+ */
int
-__dbcl_dbc_close_ret(dbcp, replyp)
- DBC *dbcp;
+__dbcl_dbc_close_ret(dbc, replyp)
+ DBC *dbc;
__dbc_close_reply *replyp;
{
- DB *dbp;
-
- dbp = dbcp->dbp;
- __dbcl_c_refresh(dbcp);
+ __dbcl_c_refresh(dbc);
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_dbc_count_ret
+ * PUBLIC: __P((DBC *, db_recno_t *, u_int32_t, __dbc_count_reply *));
+ */
int
__dbcl_dbc_count_ret(dbc, countp, flags, replyp)
DBC *dbc;
@@ -472,9 +684,13 @@ __dbcl_dbc_count_ret(dbc, countp, flags, replyp)
return (replyp->status);
}
+/*
+ * PUBLIC: int __dbcl_dbc_dup_ret
+ * PUBLIC: __P((DBC *, DBC **, u_int32_t, __dbc_dup_reply *));
+ */
int
-__dbcl_dbc_dup_ret(dbcp, dbcpp, flags, replyp)
- DBC *dbcp, **dbcpp;
+__dbcl_dbc_dup_ret(dbc, dbcp, flags, replyp)
+ DBC *dbc, **dbcp;
u_int32_t flags;
__dbc_dup_reply *replyp;
{
@@ -483,12 +699,16 @@ __dbcl_dbc_dup_ret(dbcp, dbcpp, flags, replyp)
if (replyp->status != 0)
return (replyp->status);
- return (__dbcl_c_setup(replyp->dbcidcl_id, dbcp->dbp, dbcpp));
+ return (__dbcl_c_setup(replyp->dbcidcl_id, dbc->dbp, dbcp));
}
+/*
+ * PUBLIC: int __dbcl_dbc_get_ret
+ * PUBLIC: __P((DBC *, DBT *, DBT *, u_int32_t, __dbc_get_reply *));
+ */
int
-__dbcl_dbc_get_ret(dbcp, key, data, flags, replyp)
- DBC *dbcp;
+__dbcl_dbc_get_ret(dbc, key, data, flags, replyp)
+ DBC *dbc;
DBT *key, *data;
u_int32_t flags;
__dbc_get_reply *replyp;
@@ -503,27 +723,89 @@ __dbcl_dbc_get_ret(dbcp, key, data, flags, replyp)
if (replyp->status != 0)
return (replyp->status);
- dbenv = dbcp->dbp->dbenv;
+ dbenv = dbc->dbp->dbenv;
oldkey = key->data;
ret = __dbcl_retcopy(dbenv, key, replyp->keydata.keydata_val,
- replyp->keydata.keydata_len);
+ replyp->keydata.keydata_len, &dbc->my_rkey.data,
+ &dbc->my_rkey.ulen);
if (ret)
return (ret);
ret = __dbcl_retcopy(dbenv, data, replyp->datadata.datadata_val,
- replyp->datadata.datadata_len);
+ replyp->datadata.datadata_len, &dbc->my_rdata.data,
+ &dbc->my_rdata.ulen);
/*
* If an error on copying 'data' and we allocated for 'key'
* free it before returning the error.
*/
if (ret && oldkey != NULL)
- __os_free(key->data, key->size);
+ __os_free(dbenv, key->data);
return (ret);
}
+/*
+ * PUBLIC: int __dbcl_dbc_pget_ret __P((DBC *, DBT *, DBT *, DBT *, u_int32_t,
+ * PUBLIC: __dbc_pget_reply *));
+ */
int
-__dbcl_dbc_put_ret(dbcp, key, data, flags, replyp)
- DBC *dbcp;
+__dbcl_dbc_pget_ret(dbc, skey, pkey, data, flags, replyp)
+ DBC * dbc;
+ DBT * skey;
+ DBT * pkey;
+ DBT * data;
+ u_int32_t flags;
+ __dbc_pget_reply *replyp;
+{
+ DB_ENV *dbenv;
+ int ret;
+ void *oldskey, *oldpkey;
+
+ COMPQUIET(flags, 0);
+
+ ret = 0;
+ if (replyp->status != 0)
+ return (replyp->status);
+
+ dbenv = dbc->dbp->dbenv;
+
+ oldskey = skey->data;
+ ret = __dbcl_retcopy(dbenv, skey, replyp->skeydata.skeydata_val,
+ replyp->skeydata.skeydata_len, &dbc->my_rskey.data,
+ &dbc->my_rskey.ulen);
+ if (ret)
+ return (ret);
+
+ oldpkey = pkey->data;
+ ret = __dbcl_retcopy(dbenv, pkey, replyp->pkeydata.pkeydata_val,
+ replyp->pkeydata.pkeydata_len, &dbc->my_rkey.data,
+ &dbc->my_rkey.ulen);
+ if (ret && oldskey != NULL) {
+ __os_free(dbenv, skey->data);
+ return (ret);
+ }
+ ret = __dbcl_retcopy(dbenv, data, replyp->datadata.datadata_val,
+ replyp->datadata.datadata_len, &dbc->my_rdata.data,
+ &dbc->my_rdata.ulen);
+ /*
+ * If an error on copying 'data' and we allocated for '*key'
+ * free it before returning the error.
+ */
+ if (ret) {
+ if (oldskey != NULL)
+ __os_free(dbenv, skey->data);
+ if (oldpkey != NULL)
+ __os_free(dbenv, pkey->data);
+ }
+ return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_put_ret
+ * PUBLIC: __P((DBC *, DBT *, DBT *, u_int32_t, __dbc_put_reply *));
+ */
+int
+__dbcl_dbc_put_ret(dbc, key, data, flags, replyp)
+ DBC *dbc;
DBT *key, *data;
u_int32_t flags;
__dbc_put_reply *replyp;
@@ -533,7 +815,7 @@ __dbcl_dbc_put_ret(dbcp, key, data, flags, replyp)
if (replyp->status != 0)
return (replyp->status);
- if (replyp->status == 0 && dbcp->dbp->type == DB_RECNO &&
+ if (replyp->status == 0 && dbc->dbp->type == DB_RECNO &&
(flags == DB_AFTER || flags == DB_BEFORE))
*(db_recno_t *)key->data =
*(db_recno_t *)replyp->keydata.keydata_val;
diff --git a/bdb/rpc_server/c/db_server_proc.c.in b/bdb/rpc_server/c/db_server_proc.c.in
new file mode 100644
index 00000000000..d5d1f49508a
--- /dev/null
+++ b/bdb/rpc_server/c/db_server_proc.c.in
@@ -0,0 +1,2500 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifdef HAVE_RPC
+#ifndef lint
+static const char revid[] = "$Id: db_server_proc.c,v 1.92 2002/07/29 15:21:20 sue Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#endif
+#include "dbinc_auto/db_server.h"
+
+#include "db_int.h"
+#include "dbinc/db_server_int.h"
+#include "dbinc_auto/rpc_server_ext.h"
+
+/* BEGIN __env_cachesize_proc */
+/*
+ * PUBLIC: void __env_cachesize_proc __P((long, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, __env_cachesize_reply *));
+ */
+void
+__env_cachesize_proc(dbenvcl_id, gbytes, bytes,
+ ncache, replyp)
+ long dbenvcl_id;
+ u_int32_t gbytes;
+ u_int32_t bytes;
+ u_int32_t ncache;
+ __env_cachesize_reply *replyp;
+/* END __env_cachesize_proc */
+{
+ DB_ENV *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ ret = dbenv->set_cachesize(dbenv, gbytes, bytes, ncache);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_close_proc */
+/*
+ * PUBLIC: void __env_close_proc __P((long, u_int32_t, __env_close_reply *));
+ */
+void
+__env_close_proc(dbenvcl_id, flags, replyp)
+ long dbenvcl_id;
+ u_int32_t flags;
+ __env_close_reply *replyp;
+/* END __env_close_proc */
+{
+ ct_entry *dbenv_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ replyp->status = __dbenv_close_int(dbenvcl_id, flags, 0);
+ return;
+}
+
+/* BEGIN __env_create_proc */
+/*
+ * PUBLIC: void __env_create_proc __P((u_int32_t, __env_create_reply *));
+ */
+void
+__env_create_proc(timeout, replyp)
+ u_int32_t timeout;
+ __env_create_reply *replyp;
+/* END __env_create_proc */
+{
+ DB_ENV *dbenv;
+ ct_entry *ctp;
+ int ret;
+
+ ctp = new_ct_ent(&replyp->status);
+ if (ctp == NULL)
+ return;
+ if ((ret = db_env_create(&dbenv, 0)) == 0) {
+ ctp->ct_envp = dbenv;
+ ctp->ct_type = CT_ENV;
+ ctp->ct_parent = NULL;
+ ctp->ct_envparent = ctp;
+ __dbsrv_settimeout(ctp, timeout);
+ __dbsrv_active(ctp);
+ replyp->envcl_id = ctp->ct_id;
+ } else
+ __dbclear_ctp(ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_dbremove_proc */
+/*
+ * PUBLIC: void __env_dbremove_proc __P((long, long, char *, char *, u_int32_t,
+ * PUBLIC: __env_dbremove_reply *));
+ */
+void
+__env_dbremove_proc(dbenvcl_id, txnpcl_id, name,
+ subdb, flags, replyp)
+ long dbenvcl_id;
+ long txnpcl_id;
+ char *name;
+ char *subdb;
+ u_int32_t flags;
+ __env_dbremove_reply *replyp;
+/* END __env_dbremove_proc */
+{
+ int ret;
+ DB_ENV * dbenv;
+ ct_entry *dbenv_ctp;
+ DB_TXN * txnp;
+ ct_entry *txnp_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ ret = dbenv->dbremove(dbenv, txnp, name, subdb, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_dbrename_proc */
+/*
+ * PUBLIC: void __env_dbrename_proc __P((long, long, char *, char *, char *,
+ * PUBLIC: u_int32_t, __env_dbrename_reply *));
+ */
+void
+__env_dbrename_proc(dbenvcl_id, txnpcl_id, name,
+ subdb, newname, flags, replyp)
+ long dbenvcl_id;
+ long txnpcl_id;
+ char *name;
+ char *subdb;
+ char *newname;
+ u_int32_t flags;
+ __env_dbrename_reply *replyp;
+/* END __env_dbrename_proc */
+{
+ int ret;
+ DB_ENV * dbenv;
+ ct_entry *dbenv_ctp;
+ DB_TXN * txnp;
+ ct_entry *txnp_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ ret = dbenv->dbrename(dbenv, txnp, name, subdb, newname, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_encrypt_proc */
+/*
+ * PUBLIC: void __env_encrypt_proc __P((long, char *, u_int32_t,
+ * PUBLIC: __env_encrypt_reply *));
+ */
+void
+__env_encrypt_proc(dbenvcl_id, passwd, flags, replyp)
+ long dbenvcl_id;
+ char *passwd;
+ u_int32_t flags;
+ __env_encrypt_reply *replyp;
+/* END __env_encrypt_proc */
+{
+ int ret;
+ DB_ENV * dbenv;
+ ct_entry *dbenv_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ ret = dbenv->set_encrypt(dbenv, passwd, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_flags_proc */
+/*
+ * PUBLIC: void __env_flags_proc __P((long, u_int32_t, u_int32_t,
+ * PUBLIC: __env_flags_reply *));
+ */
+void
+__env_flags_proc(dbenvcl_id, flags, onoff, replyp)
+ long dbenvcl_id;
+ u_int32_t flags;
+ u_int32_t onoff;
+ __env_flags_reply *replyp;
+/* END __env_flags_proc */
+{
+ DB_ENV *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ ret = dbenv->set_flags(dbenv, flags, onoff);
+ if (onoff)
+ dbenv_ctp->ct_envdp.onflags = flags;
+ else
+ dbenv_ctp->ct_envdp.offflags = flags;
+
+ replyp->status = ret;
+ return;
+}
+/* BEGIN __env_open_proc */
+/*
+ * PUBLIC: void __env_open_proc __P((long, char *, u_int32_t, u_int32_t,
+ * PUBLIC: __env_open_reply *));
+ */
+void
+__env_open_proc(dbenvcl_id, home, flags,
+ mode, replyp)
+ long dbenvcl_id;
+ char *home;
+ u_int32_t flags;
+ u_int32_t mode;
+ __env_open_reply *replyp;
+/* END __env_open_proc */
+{
+ DB_ENV *dbenv;
+ ct_entry *dbenv_ctp, *new_ctp;
+ u_int32_t newflags, shareflags;
+ int ret;
+ home_entry *fullhome;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+ fullhome = get_home(home);
+ if (fullhome == NULL) {
+ ret = DB_NOSERVER_HOME;
+ goto out;
+ }
+
+ /*
+ * If they are using locking do deadlock detection for them,
+ * internally.
+ */
+ if ((flags & DB_INIT_LOCK) &&
+ (ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT)) != 0)
+ goto out;
+
+ if (__dbsrv_verbose) {
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, fullhome->home);
+ }
+
+ /*
+ * Mask off flags we ignore
+ */
+ newflags = (flags & ~DB_SERVER_FLAGMASK);
+ shareflags = (newflags & DB_SERVER_ENVFLAGS);
+ /*
+ * Check now whether we can share a handle for this env.
+ */
+ replyp->envcl_id = dbenvcl_id;
+ if ((new_ctp = __dbsrv_shareenv(dbenv_ctp, fullhome, shareflags))
+ != NULL) {
+ /*
+ * We can share, clean up old ID, set new one.
+ */
+ if (__dbsrv_verbose)
+ printf("Sharing env ID %ld\n", new_ctp->ct_id);
+ replyp->envcl_id = new_ctp->ct_id;
+ ret = __dbenv_close_int(dbenvcl_id, 0, 0);
+ } else {
+ ret = dbenv->open(dbenv, fullhome->home, newflags, mode);
+ dbenv_ctp->ct_envdp.home = fullhome;
+ dbenv_ctp->ct_envdp.envflags = shareflags;
+ }
+out: replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_remove_proc */
+/*
+ * PUBLIC: void __env_remove_proc __P((long, char *, u_int32_t,
+ * PUBLIC: __env_remove_reply *));
+ */
+void
+__env_remove_proc(dbenvcl_id, home, flags, replyp)
+ long dbenvcl_id;
+ char *home;
+ u_int32_t flags;
+ __env_remove_reply *replyp;
+/* END __env_remove_proc */
+{
+ DB_ENV *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+ home_entry *fullhome;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ fullhome = get_home(home);
+ if (fullhome == NULL) {
+ replyp->status = DB_NOSERVER_HOME;
+ return;
+ }
+
+ ret = dbenv->remove(dbenv, fullhome->home, flags);
+ __dbdel_ctp(dbenv_ctp);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_abort_proc */
+/*
+ * PUBLIC: void __txn_abort_proc __P((long, __txn_abort_reply *));
+ */
+void
+__txn_abort_proc(txnpcl_id, replyp)
+ long txnpcl_id;
+ __txn_abort_reply *replyp;
+/* END __txn_abort_proc */
+{
+ DB_TXN *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+ ret = txnp->abort(txnp);
+ __dbdel_ctp(txnp_ctp);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_begin_proc */
+/*
+ * PUBLIC: void __txn_begin_proc __P((long, long, u_int32_t,
+ * PUBLIC: __txn_begin_reply *));
+ */
+void
+__txn_begin_proc(dbenvcl_id, parentcl_id,
+ flags, replyp)
+ long dbenvcl_id;
+ long parentcl_id;
+ u_int32_t flags;
+ __txn_begin_reply *replyp;
+/* END __txn_begin_proc */
+{
+ DB_ENV *dbenv;
+ DB_TXN *parent, *txnp;
+ ct_entry *ctp, *dbenv_ctp, *parent_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+ parent_ctp = NULL;
+
+ ctp = new_ct_ent(&replyp->status);
+ if (ctp == NULL)
+ return;
+
+ if (parentcl_id != 0) {
+ ACTIVATE_CTP(parent_ctp, parentcl_id, CT_TXN);
+ parent = (DB_TXN *)parent_ctp->ct_anyp;
+ ctp->ct_activep = parent_ctp->ct_activep;
+ } else
+ parent = NULL;
+
+ ret = dbenv->txn_begin(dbenv, parent, &txnp, flags);
+ if (ret == 0) {
+ ctp->ct_txnp = txnp;
+ ctp->ct_type = CT_TXN;
+ ctp->ct_parent = parent_ctp;
+ ctp->ct_envparent = dbenv_ctp;
+ replyp->txnidcl_id = ctp->ct_id;
+ __dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
+ __dbsrv_active(ctp);
+ } else
+ __dbclear_ctp(ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_commit_proc */
+/*
+ * PUBLIC: void __txn_commit_proc __P((long, u_int32_t,
+ * PUBLIC: __txn_commit_reply *));
+ */
+void
+__txn_commit_proc(txnpcl_id, flags, replyp)
+ long txnpcl_id;
+ u_int32_t flags;
+ __txn_commit_reply *replyp;
+/* END __txn_commit_proc */
+{
+ DB_TXN *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+ ret = txnp->commit(txnp, flags);
+ __dbdel_ctp(txnp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_discard_proc */
+/*
+ * PUBLIC: void __txn_discard_proc __P((long, u_int32_t,
+ * PUBLIC: __txn_discard_reply *));
+ */
+void
+__txn_discard_proc(txnpcl_id, flags, replyp)
+ long txnpcl_id;
+ u_int32_t flags;
+ __txn_discard_reply *replyp;
+/* END __txn_discard_proc */
+{
+ DB_TXN *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+ ret = txnp->discard(txnp, flags);
+ __dbdel_ctp(txnp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_prepare_proc */
+/*
+ * PUBLIC: void __txn_prepare_proc __P((long, u_int8_t *,
+ * PUBLIC: __txn_prepare_reply *));
+ */
+void
+__txn_prepare_proc(txnpcl_id, gid, replyp)
+ long txnpcl_id;
+ u_int8_t *gid;
+ __txn_prepare_reply *replyp;
+/* END __txn_prepare_proc */
+{
+ DB_TXN *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+ ret = txnp->prepare(txnp, gid);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_recover_proc */
+/*
+ * PUBLIC: void __txn_recover_proc __P((long, u_int32_t, u_int32_t,
+ * PUBLIC: __txn_recover_reply *, int *));
+ */
+void
+__txn_recover_proc(dbenvcl_id, count,
+ flags, replyp, freep)
+ long dbenvcl_id;
+ u_int32_t count;
+ u_int32_t flags;
+ __txn_recover_reply *replyp;
+ int * freep;
+/* END __txn_recover_proc */
+{
+ DB_ENV *dbenv;
+ DB_PREPLIST *dbprep, *p;
+ ct_entry *dbenv_ctp, *ctp;
+ long erri, i, retcount;
+ u_int32_t *txnidp;
+ int ret;
+ u_int8_t *gid;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+ dbprep = NULL;
+ *freep = 0;
+
+ if ((ret =
+ __os_malloc(dbenv, count * sizeof(DB_PREPLIST), &dbprep)) != 0)
+ goto out;
+ if ((ret =
+ dbenv->txn_recover(dbenv, dbprep, count, &retcount, flags)) != 0)
+ goto out;
+ /*
+ * If there is nothing, success, but it's easy.
+ */
+ replyp->retcount = retcount;
+ if (retcount == 0) {
+ replyp->txn.txn_val = NULL;
+ replyp->txn.txn_len = 0;
+ replyp->gid.gid_val = NULL;
+ replyp->gid.gid_len = 0;
+ }
+
+ /*
+ * We have our txn list. Now we need to allocate the space for
+ * the txn ID array and the GID array and set them up.
+ */
+ if ((ret = __os_calloc(dbenv, retcount, sizeof(u_int32_t),
+ &replyp->txn.txn_val)) != 0)
+ goto out;
+ replyp->txn.txn_len = retcount * sizeof(u_int32_t);
+ if ((ret = __os_calloc(dbenv, retcount, DB_XIDDATASIZE,
+ &replyp->gid.gid_val)) != 0) {
+ __os_free(dbenv, replyp->txn.txn_val);
+ goto out;
+ }
+ replyp->gid.gid_len = retcount * DB_XIDDATASIZE;
+
+ /*
+ * Now walk through our results, creating parallel arrays
+ * to send back. For each entry we need to create a new
+ * txn ctp and then fill in the array info.
+ */
+ i = 0;
+ p = dbprep;
+ gid = replyp->gid.gid_val;
+ txnidp = replyp->txn.txn_val;
+ while (i++ < retcount) {
+ ctp = new_ct_ent(&ret);
+ if (ret != 0) {
+ i--;
+ goto out2;
+ }
+ ctp->ct_txnp = p->txn;
+ ctp->ct_type = CT_TXN;
+ ctp->ct_parent = NULL;
+ ctp->ct_envparent = dbenv_ctp;
+ __dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
+ __dbsrv_active(ctp);
+
+ *txnidp = ctp->ct_id;
+ memcpy(gid, p->gid, DB_XIDDATASIZE);
+
+ p++;
+ txnidp++;
+ gid += DB_XIDDATASIZE;
+ }
+ /*
+ * If we get here, we have success and we have to set freep
+ * so it'll get properly freed next time.
+ */
+ *freep = 1;
+out:
+ if (dbprep != NULL)
+ __os_free(dbenv, dbprep);
+ replyp->status = ret;
+ return;
+out2:
+ /*
+ * We had an error in the middle of creating our new txn
+ * ct entries. We have to unwind all that we have done. Ugh.
+ */
+ for (txnidp = replyp->txn.txn_val, erri = 0;
+ erri < i; erri++, txnidp++) {
+ ctp = get_tableent(*txnidp);
+ __dbclear_ctp(ctp);
+ }
+ __os_free(dbenv, replyp->txn.txn_val);
+ __os_free(dbenv, replyp->gid.gid_val);
+ __os_free(dbenv, dbprep);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_bt_maxkey_proc */
+/*
+ * PUBLIC: void __db_bt_maxkey_proc __P((long, u_int32_t,
+ * PUBLIC: __db_bt_maxkey_reply *));
+ */
+void
+__db_bt_maxkey_proc(dbpcl_id, maxkey, replyp)
+ long dbpcl_id;
+ u_int32_t maxkey;
+ __db_bt_maxkey_reply *replyp;
+/* END __db_bt_maxkey_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_bt_maxkey(dbp, maxkey);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_associate_proc */
+/*
+ * PUBLIC: void __db_associate_proc __P((long, long, long, u_int32_t,
+ * PUBLIC: __db_associate_reply *));
+ */
+void
+__db_associate_proc(dbpcl_id, txnpcl_id, sdbpcl_id,
+ flags, replyp)
+ long dbpcl_id;
+ long txnpcl_id;
+ long sdbpcl_id;
+ u_int32_t flags;
+ __db_associate_reply *replyp;
+/* END __db_associate_proc */
+{
+ DB *dbp, *sdbp;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *sdbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ ACTIVATE_CTP(sdbp_ctp, sdbpcl_id, CT_DB);
+ sdbp = (DB *)sdbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+
+ /*
+ * We do not support DB_CREATE for associate. Users
+ * can only access secondary indices on a read-only basis,
+ * so whatever they are looking for needs to be there already.
+ */
+ if (flags != 0)
+ ret = EINVAL;
+ else
+ ret = dbp->associate(dbp, txnp, sdbp, NULL, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_bt_minkey_proc */
+/*
+ * PUBLIC: void __db_bt_minkey_proc __P((long, u_int32_t,
+ * PUBLIC: __db_bt_minkey_reply *));
+ */
+void
+__db_bt_minkey_proc(dbpcl_id, minkey, replyp)
+ long dbpcl_id;
+ u_int32_t minkey;
+ __db_bt_minkey_reply *replyp;
+/* END __db_bt_minkey_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_bt_minkey(dbp, minkey);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_close_proc */
+/*
+ * PUBLIC: void __db_close_proc __P((long, u_int32_t, __db_close_reply *));
+ */
+void
+__db_close_proc(dbpcl_id, flags, replyp)
+ long dbpcl_id;
+ u_int32_t flags;
+ __db_close_reply *replyp;
+/* END __db_close_proc */
+{
+ ct_entry *dbp_ctp;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ replyp->status = __db_close_int(dbpcl_id, flags);
+ return;
+}
+
+/* BEGIN __db_create_proc */
+/*
+ * PUBLIC: void __db_create_proc __P((long, u_int32_t, __db_create_reply *));
+ */
+void
+__db_create_proc(dbenvcl_id, flags, replyp)
+ long dbenvcl_id;
+ u_int32_t flags;
+ __db_create_reply *replyp;
+/* END __db_create_proc */
+{
+ DB *dbp;
+ DB_ENV *dbenv;
+ ct_entry *dbenv_ctp, *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+ dbp_ctp = new_ct_ent(&replyp->status);
+ if (dbp_ctp == NULL)
+ return ;
+ /*
+ * We actually require env's for databases. The client should
+ * have caught it, but just in case.
+ */
+ DB_ASSERT(dbenv != NULL);
+ if ((ret = db_create(&dbp, dbenv, flags)) == 0) {
+ dbp_ctp->ct_dbp = dbp;
+ dbp_ctp->ct_type = CT_DB;
+ dbp_ctp->ct_parent = dbenv_ctp;
+ dbp_ctp->ct_envparent = dbenv_ctp;
+ replyp->dbcl_id = dbp_ctp->ct_id;
+ } else
+ __dbclear_ctp(dbp_ctp);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_del_proc */
+/*
+ * PUBLIC: void __db_del_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, __db_del_reply *));
+ */
+void
+__db_del_proc(dbpcl_id, txnpcl_id, keydlen,
+ keydoff, keyulen, keyflags, keydata,
+ keysize, flags, replyp)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t keydlen;
+ u_int32_t keydoff;
+ u_int32_t keyulen;
+ u_int32_t keyflags;
+ void *keydata;
+ u_int32_t keysize;
+ u_int32_t flags;
+ __db_del_reply *replyp;
+/* END __db_del_proc */
+{
+ DB *dbp;
+ DBT key;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ memset(&key, 0, sizeof(key));
+
+ /* Set up key DBT */
+ key.dlen = keydlen;
+ key.ulen = keyulen;
+ key.doff = keydoff;
+ key.flags = keyflags;
+ key.size = keysize;
+ key.data = keydata;
+
+ ret = dbp->del(dbp, txnp, &key, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_encrypt_proc */
+/*
+ * PUBLIC: void __db_encrypt_proc __P((long, char *, u_int32_t,
+ * PUBLIC: __db_encrypt_reply *));
+ */
+void
+__db_encrypt_proc(dbpcl_id, passwd, flags, replyp)
+ long dbpcl_id;
+ char *passwd;
+ u_int32_t flags;
+ __db_encrypt_reply *replyp;
+/* END __db_encrypt_proc */
+{
+ int ret;
+ DB * dbp;
+ ct_entry *dbp_ctp;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_encrypt(dbp, passwd, flags);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_extentsize_proc */
+/*
+ * PUBLIC: void __db_extentsize_proc __P((long, u_int32_t,
+ * PUBLIC: __db_extentsize_reply *));
+ */
+void
+__db_extentsize_proc(dbpcl_id, extentsize, replyp)
+ long dbpcl_id;
+ u_int32_t extentsize;
+ __db_extentsize_reply *replyp;
+/* END __db_extentsize_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_q_extentsize(dbp, extentsize);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_flags_proc */
+/*
+ * PUBLIC: void __db_flags_proc __P((long, u_int32_t, __db_flags_reply *));
+ */
+void
+__db_flags_proc(dbpcl_id, flags, replyp)
+ long dbpcl_id;
+ u_int32_t flags;
+ __db_flags_reply *replyp;
+/* END __db_flags_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_flags(dbp, flags);
+ dbp_ctp->ct_dbdp.setflags |= flags;
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_get_proc */
+/*
+ * PUBLIC: void __db_get_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *,
+ * PUBLIC: u_int32_t, u_int32_t, __db_get_reply *, int *));
+ */
+void
+__db_get_proc(dbpcl_id, txnpcl_id, keydlen,
+ keydoff, keyulen, keyflags, keydata,
+ keysize, datadlen, datadoff, dataulen,
+ dataflags, datadata, datasize, flags, replyp, freep)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t keydlen;
+ u_int32_t keydoff;
+ u_int32_t keyulen;
+ u_int32_t keyflags;
+ void *keydata;
+ u_int32_t keysize;
+ u_int32_t datadlen;
+ u_int32_t datadoff;
+ u_int32_t dataulen;
+ u_int32_t dataflags;
+ void *datadata;
+ u_int32_t datasize;
+ u_int32_t flags;
+ __db_get_reply *replyp;
+ int * freep;
+/* END __db_get_proc */
+{
+ DB *dbp;
+ DBT key, data;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int key_alloc, bulk_alloc, ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ *freep = 0;
+ bulk_alloc = 0;
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ /* Set up key and data DBT */
+ key.dlen = keydlen;
+ key.doff = keydoff;
+ /*
+ * Ignore memory related flags on server.
+ */
+ key.flags = DB_DBT_MALLOC;
+ if (keyflags & DB_DBT_PARTIAL)
+ key.flags |= DB_DBT_PARTIAL;
+ key.size = keysize;
+ key.ulen = keyulen;
+ key.data = keydata;
+
+ data.dlen = datadlen;
+ data.doff = datadoff;
+ data.ulen = dataulen;
+ /*
+ * Ignore memory related flags on server.
+ */
+ data.size = datasize;
+ data.data = datadata;
+ if (flags & DB_MULTIPLE) {
+ if (data.data == 0) {
+ ret = __os_umalloc(dbp->dbenv,
+ data.ulen, &data.data);
+ if (ret != 0)
+ goto err;
+ bulk_alloc = 1;
+ }
+ data.flags |= DB_DBT_USERMEM;
+ } else
+ data.flags |= DB_DBT_MALLOC;
+ if (dataflags & DB_DBT_PARTIAL)
+ data.flags |= DB_DBT_PARTIAL;
+
+ /* Got all our stuff, now do the get */
+ ret = dbp->get(dbp, txnp, &key, &data, flags);
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (key.data == keydata) {
+ ret = __os_umalloc(dbp->dbenv,
+ key.size, &replyp->keydata.keydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->dbenv, key.data);
+ __os_ufree(dbp->dbenv, data.data);
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->keydata.keydata_val, key.data, key.size);
+ } else
+ replyp->keydata.keydata_val = key.data;
+
+ replyp->keydata.keydata_len = key.size;
+
+ /*
+ * Data
+ */
+ if (data.data == datadata) {
+ ret = __os_umalloc(dbp->dbenv,
+ data.size, &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->dbenv, key.data);
+ __os_ufree(dbp->dbenv, data.data);
+ if (key_alloc)
+ __os_ufree(dbp->dbenv,
+ replyp->keydata.keydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.data,
+ data.size);
+ } else
+ replyp->datadata.datadata_val = data.data;
+ replyp->datadata.datadata_len = data.size;
+ } else {
+err: replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ if (bulk_alloc)
+ __os_ufree(dbp->dbenv, data.data);
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_h_ffactor_proc */
+/*
+ * PUBLIC: void __db_h_ffactor_proc __P((long, u_int32_t,
+ * PUBLIC: __db_h_ffactor_reply *));
+ */
+void
+__db_h_ffactor_proc(dbpcl_id, ffactor, replyp)
+ long dbpcl_id;
+ u_int32_t ffactor;
+ __db_h_ffactor_reply *replyp;
+/* END __db_h_ffactor_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_h_ffactor(dbp, ffactor);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_h_nelem_proc */
+/*
+ * PUBLIC: void __db_h_nelem_proc __P((long, u_int32_t,
+ * PUBLIC: __db_h_nelem_reply *));
+ */
+void
+__db_h_nelem_proc(dbpcl_id, nelem, replyp)
+ long dbpcl_id;
+ u_int32_t nelem;
+ __db_h_nelem_reply *replyp;
+/* END __db_h_nelem_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_h_nelem(dbp, nelem);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_key_range_proc */
+/*
+ * PUBLIC: void __db_key_range_proc __P((long, long, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, u_int32_t, void *, u_int32_t, u_int32_t, __db_key_range_reply *));
+ */
+void
+__db_key_range_proc(dbpcl_id, txnpcl_id, keydlen,
+ keydoff, keyulen, keyflags, keydata,
+ keysize, flags, replyp)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t keydlen;
+ u_int32_t keydoff;
+ u_int32_t keyulen;
+ u_int32_t keyflags;
+ void *keydata;
+ u_int32_t keysize;
+ u_int32_t flags;
+ __db_key_range_reply *replyp;
+/* END __db_key_range_proc */
+{
+ DB *dbp;
+ DBT key;
+ DB_KEY_RANGE range;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ memset(&key, 0, sizeof(key));
+ /* Set up key and data DBT */
+ key.dlen = keydlen;
+ key.ulen = keyulen;
+ key.doff = keydoff;
+ key.size = keysize;
+ key.data = keydata;
+ key.flags = keyflags;
+
+ ret = dbp->key_range(dbp, txnp, &key, &range, flags);
+
+ replyp->status = ret;
+ replyp->less = range.less;
+ replyp->equal = range.equal;
+ replyp->greater = range.greater;
+ return;
+}
+
+/* BEGIN __db_lorder_proc */
+/*
+ * PUBLIC: void __db_lorder_proc __P((long, u_int32_t, __db_lorder_reply *));
+ */
+void
+__db_lorder_proc(dbpcl_id, lorder, replyp)
+ long dbpcl_id;
+ u_int32_t lorder;
+ __db_lorder_reply *replyp;
+/* END __db_lorder_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_lorder(dbp, lorder);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_open_proc */
+/*
+ * PUBLIC: void __db_open_proc __P((long, long, char *, char *, u_int32_t,
+ * PUBLIC: u_int32_t, u_int32_t, __db_open_reply *));
+ */
+void
+__db_open_proc(dbpcl_id, txnpcl_id, name,
+ subdb, type, flags, mode, replyp)
+ long dbpcl_id;
+ long txnpcl_id;
+ char *name;
+ char *subdb;
+ u_int32_t type;
+ u_int32_t flags;
+ u_int32_t mode;
+ __db_open_reply *replyp;
+/* END __db_open_proc */
+{
+ DB *dbp;
+ DB_TXN *txnp;
+ DBTYPE dbtype;
+ ct_entry *dbp_ctp, *new_ctp, *txnp_ctp;
+ int isswapped, ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ replyp->dbcl_id = dbpcl_id;
+ if ((new_ctp = __dbsrv_sharedb(dbp_ctp, name, subdb, type, flags))
+ != NULL) {
+ /*
+ * We can share, clean up old ID, set new one.
+ */
+ if (__dbsrv_verbose)
+ printf("Sharing db ID %ld\n", new_ctp->ct_id);
+ replyp->dbcl_id = new_ctp->ct_id;
+ ret = __db_close_int(dbpcl_id, 0);
+ goto out;
+ }
+ ret = dbp->open(dbp, txnp, name, subdb, (DBTYPE)type, flags, mode);
+ if (ret == 0) {
+ (void)dbp->get_type(dbp, &dbtype);
+ replyp->type = dbtype;
+ /* XXX
+ * Tcl needs to peek at dbp->flags for DB_AM_DUP. Send
+ * this dbp's flags back.
+ */
+ replyp->dbflags = (int) dbp->flags;
+ /*
+ * We need to determine the byte order of the database
+ * and send it back to the client. Determine it by
+ * the server's native order and the swapped value of
+ * the DB itself.
+ */
+ (void)dbp->get_byteswapped(dbp, &isswapped);
+ if (__db_byteorder(NULL, 1234) == 0) {
+ if (isswapped == 0)
+ replyp->lorder = 1234;
+ else
+ replyp->lorder = 4321;
+ } else {
+ if (isswapped == 0)
+ replyp->lorder = 4321;
+ else
+ replyp->lorder = 1234;
+ }
+ dbp_ctp->ct_dbdp.type = dbtype;
+ dbp_ctp->ct_dbdp.dbflags = LF_ISSET(DB_SERVER_DBFLAGS);
+ if (name == NULL)
+ dbp_ctp->ct_dbdp.db = NULL;
+ else if ((ret = __os_strdup(dbp->dbenv, name,
+ &dbp_ctp->ct_dbdp.db)) != 0)
+ goto out;
+ if (subdb == NULL)
+ dbp_ctp->ct_dbdp.subdb = NULL;
+ else if ((ret = __os_strdup(dbp->dbenv, subdb,
+ &dbp_ctp->ct_dbdp.subdb)) != 0)
+ goto out;
+ }
+out:
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_pagesize_proc */
+/*
+ * PUBLIC: void __db_pagesize_proc __P((long, u_int32_t,
+ * PUBLIC: __db_pagesize_reply *));
+ */
+void
+__db_pagesize_proc(dbpcl_id, pagesize, replyp)
+ long dbpcl_id;
+ u_int32_t pagesize;
+ __db_pagesize_reply *replyp;
+/* END __db_pagesize_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_pagesize(dbp, pagesize);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_pget_proc */
+/*
+ * PUBLIC: void __db_pget_proc __P((long, long, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *,
+ * PUBLIC: u_int32_t, u_int32_t, __db_pget_reply *, int *));
+ */
+void
+__db_pget_proc(dbpcl_id, txnpcl_id, skeydlen,
+ skeydoff, skeyulen, skeyflags, skeydata,
+ skeysize, pkeydlen, pkeydoff, pkeyulen,
+ pkeyflags, pkeydata, pkeysize, datadlen,
+ datadoff, dataulen, dataflags, datadata,
+ datasize, flags, replyp, freep)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t skeydlen;
+ u_int32_t skeydoff;
+ u_int32_t skeyulen;
+ u_int32_t skeyflags;
+ void *skeydata;
+ u_int32_t skeysize;
+ u_int32_t pkeydlen;
+ u_int32_t pkeydoff;
+ u_int32_t pkeyulen;
+ u_int32_t pkeyflags;
+ void *pkeydata;
+ u_int32_t pkeysize;
+ u_int32_t datadlen;
+ u_int32_t datadoff;
+ u_int32_t dataulen;
+ u_int32_t dataflags;
+ void *datadata;
+ u_int32_t datasize;
+ u_int32_t flags;
+ __db_pget_reply *replyp;
+ int * freep;
+/* END __db_pget_proc */
+{
+ DB *dbp;
+ DBT skey, pkey, data;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int key_alloc, ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ *freep = 0;
+ memset(&skey, 0, sizeof(skey));
+ memset(&pkey, 0, sizeof(pkey));
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Ignore memory related flags on server.
+ */
+ /* Set up key and data DBT */
+ skey.flags = DB_DBT_MALLOC;
+ skey.dlen = skeydlen;
+ skey.ulen = skeyulen;
+ skey.doff = skeydoff;
+ if (skeyflags & DB_DBT_PARTIAL)
+ skey.flags |= DB_DBT_PARTIAL;
+ skey.size = skeysize;
+ skey.data = skeydata;
+
+ pkey.flags = DB_DBT_MALLOC;
+ pkey.dlen = pkeydlen;
+ pkey.ulen = pkeyulen;
+ pkey.doff = pkeydoff;
+ if (pkeyflags & DB_DBT_PARTIAL)
+ pkey.flags |= DB_DBT_PARTIAL;
+ pkey.size = pkeysize;
+ pkey.data = pkeydata;
+
+ data.flags = DB_DBT_MALLOC;
+ data.dlen = datadlen;
+ data.ulen = dataulen;
+ data.doff = datadoff;
+ if (dataflags & DB_DBT_PARTIAL)
+ data.flags |= DB_DBT_PARTIAL;
+ data.size = datasize;
+ data.data = datadata;
+
+ /* Got all our stuff, now do the get */
+ ret = dbp->pget(dbp, txnp, &skey, &pkey, &data, flags);
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (skey.data == skeydata) {
+ ret = __os_umalloc(dbp->dbenv,
+ skey.size, &replyp->skeydata.skeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->dbenv, skey.data);
+ __os_ufree(dbp->dbenv, pkey.data);
+ __os_ufree(dbp->dbenv, data.data);
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->skeydata.skeydata_val, skey.data,
+ skey.size);
+ } else
+ replyp->skeydata.skeydata_val = skey.data;
+
+ replyp->skeydata.skeydata_len = skey.size;
+
+ /*
+ * Primary key
+ */
+ if (pkey.data == pkeydata) {
+ ret = __os_umalloc(dbp->dbenv,
+ pkey.size, &replyp->pkeydata.pkeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->dbenv, skey.data);
+ __os_ufree(dbp->dbenv, pkey.data);
+ __os_ufree(dbp->dbenv, data.data);
+ if (key_alloc)
+ __os_ufree(dbp->dbenv,
+ replyp->skeydata.skeydata_val);
+ goto err;
+ }
+ /*
+ * We can set it to 2, because they cannot send the
+ * pkey over without sending the skey over too.
+ * So if they did send a pkey, they must have sent
+ * the skey as well.
+ */
+ key_alloc = 2;
+ memcpy(replyp->pkeydata.pkeydata_val, pkey.data,
+ pkey.size);
+ } else
+ replyp->pkeydata.pkeydata_val = pkey.data;
+ replyp->pkeydata.pkeydata_len = pkey.size;
+
+ /*
+ * Data
+ */
+ if (data.data == datadata) {
+ ret = __os_umalloc(dbp->dbenv,
+ data.size, &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->dbenv, skey.data);
+ __os_ufree(dbp->dbenv, pkey.data);
+ __os_ufree(dbp->dbenv, data.data);
+ /*
+ * If key_alloc is 1, just skey needs to be
+ * freed, if key_alloc is 2, both skey and pkey
+ * need to be freed.
+ */
+ if (key_alloc--)
+ __os_ufree(dbp->dbenv,
+ replyp->skeydata.skeydata_val);
+ if (key_alloc)
+ __os_ufree(dbp->dbenv,
+ replyp->pkeydata.pkeydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.data,
+ data.size);
+ } else
+ replyp->datadata.datadata_val = data.data;
+ replyp->datadata.datadata_len = data.size;
+ } else {
+err: replyp->skeydata.skeydata_val = NULL;
+ replyp->skeydata.skeydata_len = 0;
+ replyp->pkeydata.pkeydata_val = NULL;
+ replyp->pkeydata.pkeydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_put_proc */
+/*
+ * PUBLIC: void __db_put_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *,
+ * PUBLIC: u_int32_t, u_int32_t, __db_put_reply *, int *));
+ */
+void
+__db_put_proc(dbpcl_id, txnpcl_id, keydlen,
+ keydoff, keyulen, keyflags, keydata,
+ keysize, datadlen, datadoff, dataulen,
+ dataflags, datadata, datasize, flags, replyp, freep)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t keydlen;
+ u_int32_t keydoff;
+ u_int32_t keyulen;
+ u_int32_t keyflags;
+ void *keydata;
+ u_int32_t keysize;
+ u_int32_t datadlen;
+ u_int32_t datadoff;
+ u_int32_t dataulen;
+ u_int32_t dataflags;
+ void *datadata;
+ u_int32_t datasize;
+ u_int32_t flags;
+ __db_put_reply *replyp;
+ int * freep;
+/* END __db_put_proc */
+{
+ DB *dbp;
+ DBT key, data;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ *freep = 0;
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ /* Set up key and data DBT */
+ key.dlen = keydlen;
+ key.ulen = keyulen;
+ key.doff = keydoff;
+ /*
+ * Ignore memory related flags on server.
+ */
+ key.flags = DB_DBT_MALLOC;
+ if (keyflags & DB_DBT_PARTIAL)
+ key.flags |= DB_DBT_PARTIAL;
+ key.size = keysize;
+ key.data = keydata;
+
+ data.dlen = datadlen;
+ data.ulen = dataulen;
+ data.doff = datadoff;
+ data.flags = dataflags;
+ data.size = datasize;
+ data.data = datadata;
+
+ /* Got all our stuff, now do the put */
+ ret = dbp->put(dbp, txnp, &key, &data, flags);
+ /*
+ * If the client did a DB_APPEND, set up key in reply.
+ * Otherwise just status.
+ */
+ if (ret == 0 && (flags == DB_APPEND)) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ if (key.data == keydata) {
+ ret = __os_umalloc(dbp->dbenv,
+ key.size, &replyp->keydata.keydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->dbenv, key.data);
+ goto err;
+ }
+ memcpy(replyp->keydata.keydata_val, key.data, key.size);
+ } else
+ replyp->keydata.keydata_val = key.data;
+
+ replyp->keydata.keydata_len = key.size;
+ } else {
+err: replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ *freep = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_re_delim_proc */
+/*
+ * PUBLIC: void __db_re_delim_proc __P((long, u_int32_t,
+ * PUBLIC: __db_re_delim_reply *));
+ */
+void
+__db_re_delim_proc(dbpcl_id, delim, replyp)
+ long dbpcl_id;
+ u_int32_t delim;
+ __db_re_delim_reply *replyp;
+/* END __db_re_delim_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_re_delim(dbp, delim);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_re_len_proc */
+/*
+ * PUBLIC: void __db_re_len_proc __P((long, u_int32_t, __db_re_len_reply *));
+ */
+void
+__db_re_len_proc(dbpcl_id, len, replyp)
+ long dbpcl_id;
+ u_int32_t len;
+ __db_re_len_reply *replyp;
+/* END __db_re_len_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_re_len(dbp, len);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_re_pad_proc */
+/*
+ * PUBLIC: void __db_re_pad_proc __P((long, u_int32_t, __db_re_pad_reply *));
+ */
+void
+__db_re_pad_proc(dbpcl_id, pad, replyp)
+ long dbpcl_id;
+ u_int32_t pad;
+ __db_re_pad_reply *replyp;
+/* END __db_re_pad_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_re_pad(dbp, pad);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_remove_proc */
+/*
+ * PUBLIC: void __db_remove_proc __P((long, char *, char *, u_int32_t,
+ * PUBLIC: __db_remove_reply *));
+ */
+void
+__db_remove_proc(dbpcl_id, name, subdb,
+ flags, replyp)
+ long dbpcl_id;
+ char *name;
+ char *subdb;
+ u_int32_t flags;
+ __db_remove_reply *replyp;
+/* END __db_remove_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->remove(dbp, name, subdb, flags);
+ __dbdel_ctp(dbp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_rename_proc */
+/*
+ * PUBLIC: void __db_rename_proc __P((long, char *, char *, char *, u_int32_t,
+ * PUBLIC: __db_rename_reply *));
+ */
+void
+__db_rename_proc(dbpcl_id, name, subdb,
+ newname, flags, replyp)
+ long dbpcl_id;
+ char *name;
+ char *subdb;
+ char *newname;
+ u_int32_t flags;
+ __db_rename_reply *replyp;
+/* END __db_rename_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->rename(dbp, name, subdb, newname, flags);
+ __dbdel_ctp(dbp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_stat_proc */
+/*
+ * PUBLIC: void __db_stat_proc __P((long, u_int32_t, __db_stat_reply *,
+ * PUBLIC: int *));
+ */
+void
+__db_stat_proc(dbpcl_id, flags, replyp, freep)
+ long dbpcl_id;
+ u_int32_t flags;
+ __db_stat_reply *replyp;
+ int * freep;
+/* END __db_stat_proc */
+{
+ DB *dbp;
+ DBTYPE type;
+ ct_entry *dbp_ctp;
+ u_int32_t *q, *p, *retsp;
+ int i, len, ret;
+ void *sp;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->stat(dbp, &sp, flags);
+ replyp->status = ret;
+ if (ret != 0)
+ return;
+ /*
+ * We get here, we have success. Allocate an array so that
+ * we can use the list generator. Generate the reply, free
+ * up the space.
+ */
+ /*
+ * XXX This assumes that all elements of all stat structures
+ * are u_int32_t fields. They are, currently.
+ */
+ (void)dbp->get_type(dbp, &type);
+ if (type == DB_HASH)
+ len = sizeof(DB_HASH_STAT);
+ else if (type == DB_QUEUE)
+ len = sizeof(DB_QUEUE_STAT);
+ else /* BTREE or RECNO are same stats */
+ len = sizeof(DB_BTREE_STAT);
+ replyp->stats.stats_len = len / sizeof(u_int32_t);
+
+ if ((ret = __os_umalloc(dbp->dbenv, len * replyp->stats.stats_len,
+ &retsp)) != 0)
+ goto out;
+ for (i = 0, q = retsp, p = sp; i < len;
+ i++, q++, p++)
+ *q = *p;
+ replyp->stats.stats_val = retsp;
+ __os_ufree(dbp->dbenv, sp);
+ if (ret == 0)
+ *freep = 1;
+out:
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_sync_proc */
+/*
+ * PUBLIC: void __db_sync_proc __P((long, u_int32_t, __db_sync_reply *));
+ */
+void
+__db_sync_proc(dbpcl_id, flags, replyp)
+ long dbpcl_id;
+ u_int32_t flags;
+ __db_sync_reply *replyp;
+/* END __db_sync_proc */
+{
+ DB *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ ret = dbp->sync(dbp, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_truncate_proc */
+/*
+ * PUBLIC: void __db_truncate_proc __P((long, long, u_int32_t,
+ * PUBLIC: __db_truncate_reply *));
+ */
+void
+__db_truncate_proc(dbpcl_id, txnpcl_id,
+ flags, replyp)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t flags;
+ __db_truncate_reply *replyp;
+/* END __db_truncate_proc */
+{
+ DB *dbp;
+ DB_TXN *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ u_int32_t count;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ ret = dbp->truncate(dbp, txnp, &count, flags);
+ replyp->status = ret;
+ if (ret == 0)
+ replyp->count = count;
+ return;
+}
+
+/* BEGIN __db_cursor_proc */
+/*
+ * PUBLIC: void __db_cursor_proc __P((long, long, u_int32_t,
+ * PUBLIC: __db_cursor_reply *));
+ */
+void
+__db_cursor_proc(dbpcl_id, txnpcl_id,
+ flags, replyp)
+ long dbpcl_id;
+ long txnpcl_id;
+ u_int32_t flags;
+ __db_cursor_reply *replyp;
+/* END __db_cursor_proc */
+{
+ DB *dbp;
+ DBC *dbc;
+ DB_TXN *txnp;
+ ct_entry *dbc_ctp, *env_ctp, *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+ dbc_ctp = new_ct_ent(&replyp->status);
+ if (dbc_ctp == NULL)
+ return;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+ dbc_ctp->ct_activep = txnp_ctp->ct_activep;
+ } else
+ txnp = NULL;
+
+ if ((ret = dbp->cursor(dbp, txnp, &dbc, flags)) == 0) {
+ dbc_ctp->ct_dbc = dbc;
+ dbc_ctp->ct_type = CT_CURSOR;
+ dbc_ctp->ct_parent = dbp_ctp;
+ env_ctp = dbp_ctp->ct_envparent;
+ dbc_ctp->ct_envparent = env_ctp;
+ __dbsrv_settimeout(dbc_ctp, env_ctp->ct_timeout);
+ __dbsrv_active(dbc_ctp);
+ replyp->dbcidcl_id = dbc_ctp->ct_id;
+ } else
+ __dbclear_ctp(dbc_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_join_proc */
+/*
+ * PUBLIC: void __db_join_proc __P((long, u_int32_t *, u_int32_t, u_int32_t,
+ * PUBLIC: __db_join_reply *));
+ */
+void
+__db_join_proc(dbpcl_id, curs, curslen,
+ flags, replyp)
+ long dbpcl_id;
+ u_int32_t * curs;
+ u_int32_t curslen;
+ u_int32_t flags;
+ __db_join_reply *replyp;
+/* END __db_join_proc */
+{
+ DB *dbp;
+ DBC **jcurs, **c;
+ DBC *dbc;
+ ct_entry *dbc_ctp, *ctp, *dbp_ctp;
+ size_t size;
+ u_int32_t *cl, i;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (DB *)dbp_ctp->ct_anyp;
+
+ dbc_ctp = new_ct_ent(&replyp->status);
+ if (dbc_ctp == NULL)
+ return;
+
+ size = (curslen + 1) * sizeof(DBC *);
+ if ((ret = __os_calloc(dbp->dbenv,
+ curslen + 1, sizeof(DBC *), &jcurs)) != 0) {
+ replyp->status = ret;
+ __dbclear_ctp(dbc_ctp);
+ return;
+ }
+ /*
+ * If our curslist has a parent txn, we need to use it too
+ * for the activity timeout. All cursors must be part of
+ * the same transaction, so just check the first.
+ */
+ ctp = get_tableent(*curs);
+ DB_ASSERT(ctp->ct_type == CT_CURSOR);
+ /*
+ * If we are using a transaction, set the join activity timer
+ * to point to the parent transaction.
+ */
+ if (ctp->ct_activep != &ctp->ct_active)
+ dbc_ctp->ct_activep = ctp->ct_activep;
+ for (i = 0, cl = curs, c = jcurs; i < curslen; i++, cl++, c++) {
+ ctp = get_tableent(*cl);
+ if (ctp == NULL) {
+ replyp->status = DB_NOSERVER_ID;
+ goto out;
+ }
+ /*
+ * If we are using a txn, the join cursor points to the
+ * transaction timeout. If we are not using a transaction,
+ * then all the curslist cursors must point to the join
+ * cursor's timeout so that we do not timeout any of the
+ * curlist cursors while the join cursor is active.
+ * Change the type of the curslist ctps to CT_JOIN so that
+ * we know they are part of a join list and we can distinguish
+ * them and later restore them when the join cursor is closed.
+ */
+ DB_ASSERT(ctp->ct_type == CT_CURSOR);
+ ctp->ct_type |= CT_JOIN;
+ ctp->ct_origp = ctp->ct_activep;
+ /*
+ * Setting this to the ct_active field of the dbc_ctp is
+ * really just a way to distinguish which join dbc this
+ * cursor is part of. The ct_activep of this cursor is
+ * not used at all during its lifetime as part of a join
+ * cursor.
+ */
+ ctp->ct_activep = &dbc_ctp->ct_active;
+ *c = ctp->ct_dbc;
+ }
+ *c = NULL;
+ if ((ret = dbp->join(dbp, jcurs, &dbc, flags)) == 0) {
+ dbc_ctp->ct_dbc = dbc;
+ dbc_ctp->ct_type = (CT_JOINCUR | CT_CURSOR);
+ dbc_ctp->ct_parent = dbp_ctp;
+ dbc_ctp->ct_envparent = dbp_ctp->ct_envparent;
+ __dbsrv_settimeout(dbc_ctp, dbp_ctp->ct_envparent->ct_timeout);
+ __dbsrv_active(dbc_ctp);
+ replyp->dbcidcl_id = dbc_ctp->ct_id;
+ } else {
+ __dbclear_ctp(dbc_ctp);
+ /*
+ * If we get an error, undo what we did above to any cursors.
+ */
+ for (cl = curs; *cl != 0; cl++) {
+ ctp = get_tableent(*cl);
+ ctp->ct_type = CT_CURSOR;
+ ctp->ct_activep = ctp->ct_origp;
+ }
+ }
+
+ replyp->status = ret;
+out:
+ __os_free(dbp->dbenv, jcurs);
+ return;
+}
+
+/* BEGIN __dbc_close_proc */
+/*
+ * PUBLIC: void __dbc_close_proc __P((long, __dbc_close_reply *));
+ */
+void
+__dbc_close_proc(dbccl_id, replyp)
+ long dbccl_id;
+ __dbc_close_reply *replyp;
+/* END __dbc_close_proc */
+{
+ ct_entry *dbc_ctp;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ replyp->status = __dbc_close_int(dbc_ctp);
+ return;
+}
+
+/* BEGIN __dbc_count_proc */
+/*
+ * PUBLIC: void __dbc_count_proc __P((long, u_int32_t, __dbc_count_reply *));
+ */
+void
+__dbc_count_proc(dbccl_id, flags, replyp)
+ long dbccl_id;
+ u_int32_t flags;
+ __dbc_count_reply *replyp;
+/* END __dbc_count_proc */
+{
+ DBC *dbc;
+ ct_entry *dbc_ctp;
+ db_recno_t num;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+
+ ret = dbc->c_count(dbc, &num, flags);
+ replyp->status = ret;
+ if (ret == 0)
+ replyp->dupcount = num;
+ return;
+}
+
+/* BEGIN __dbc_del_proc */
+/*
+ * PUBLIC: void __dbc_del_proc __P((long, u_int32_t, __dbc_del_reply *));
+ */
+void
+__dbc_del_proc(dbccl_id, flags, replyp)
+ long dbccl_id;
+ u_int32_t flags;
+ __dbc_del_reply *replyp;
+/* END __dbc_del_proc */
+{
+ DBC *dbc;
+ ct_entry *dbc_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+
+ ret = dbc->c_del(dbc, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_dup_proc */
+/*
+ * PUBLIC: void __dbc_dup_proc __P((long, u_int32_t, __dbc_dup_reply *));
+ */
+void
+__dbc_dup_proc(dbccl_id, flags, replyp)
+ long dbccl_id;
+ u_int32_t flags;
+ __dbc_dup_reply *replyp;
+/* END __dbc_dup_proc */
+{
+ DBC *dbc, *newdbc;
+ ct_entry *dbc_ctp, *new_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+
+ new_ctp = new_ct_ent(&replyp->status);
+ if (new_ctp == NULL)
+ return;
+
+ if ((ret = dbc->c_dup(dbc, &newdbc, flags)) == 0) {
+ new_ctp->ct_dbc = newdbc;
+ new_ctp->ct_type = CT_CURSOR;
+ new_ctp->ct_parent = dbc_ctp->ct_parent;
+ new_ctp->ct_envparent = dbc_ctp->ct_envparent;
+ /*
+ * If our cursor has a parent txn, we need to use it too.
+ */
+ if (dbc_ctp->ct_activep != &dbc_ctp->ct_active)
+ new_ctp->ct_activep = dbc_ctp->ct_activep;
+ __dbsrv_settimeout(new_ctp, dbc_ctp->ct_timeout);
+ __dbsrv_active(new_ctp);
+ replyp->dbcidcl_id = new_ctp->ct_id;
+ } else
+ __dbclear_ctp(new_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_get_proc */
+/*
+ * PUBLIC: void __dbc_get_proc __P((long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *,
+ * PUBLIC: u_int32_t, u_int32_t, __dbc_get_reply *, int *));
+ */
+void
+__dbc_get_proc(dbccl_id, keydlen, keydoff,
+ keyulen, keyflags, keydata, keysize,
+ datadlen, datadoff, dataulen, dataflags,
+ datadata, datasize, flags, replyp, freep)
+ long dbccl_id;
+ u_int32_t keydlen;
+ u_int32_t keydoff;
+ u_int32_t keyulen;
+ u_int32_t keyflags;
+ void *keydata;
+ u_int32_t keysize;
+ u_int32_t datadlen;
+ u_int32_t datadoff;
+ u_int32_t dataulen;
+ u_int32_t dataflags;
+ void *datadata;
+ u_int32_t datasize;
+ u_int32_t flags;
+ __dbc_get_reply *replyp;
+ int * freep;
+/* END __dbc_get_proc */
+{
+ DBC *dbc;
+ DBT key, data;
+ DB_ENV *dbenv;
+ ct_entry *dbc_ctp;
+ int key_alloc, bulk_alloc, ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+ dbenv = dbc->dbp->dbenv;
+
+ *freep = 0;
+ bulk_alloc = 0;
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ /* Set up key and data DBT */
+ key.dlen = keydlen;
+ key.ulen = keyulen;
+ key.doff = keydoff;
+ /*
+ * Ignore memory related flags on server.
+ */
+ key.flags = DB_DBT_MALLOC;
+ if (keyflags & DB_DBT_PARTIAL)
+ key.flags |= DB_DBT_PARTIAL;
+ key.size = keysize;
+ key.data = keydata;
+
+ data.dlen = datadlen;
+ data.ulen = dataulen;
+ data.doff = datadoff;
+ data.size = datasize;
+ data.data = datadata;
+ if (flags & DB_MULTIPLE || flags & DB_MULTIPLE_KEY) {
+ if (data.data == 0) {
+ ret = __os_umalloc(dbenv, data.ulen, &data.data);
+ if (ret != 0)
+ goto err;
+ bulk_alloc = 1;
+ }
+ data.flags |= DB_DBT_USERMEM;
+ } else
+ data.flags |= DB_DBT_MALLOC;
+ if (dataflags & DB_DBT_PARTIAL)
+ data.flags |= DB_DBT_PARTIAL;
+
+ /* Got all our stuff, now do the get */
+ ret = dbc->c_get(dbc, &key, &data, flags);
+
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (key.data == keydata) {
+ ret = __os_umalloc(dbenv, key.size,
+ &replyp->keydata.keydata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv, key.data);
+ __os_ufree(dbenv, data.data);
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->keydata.keydata_val, key.data, key.size);
+ } else
+ replyp->keydata.keydata_val = key.data;
+
+ replyp->keydata.keydata_len = key.size;
+
+ /*
+ * Data
+ */
+ if (data.data == datadata) {
+ ret = __os_umalloc(dbenv, data.size,
+ &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv, key.data);
+ __os_ufree(dbenv, data.data);
+ if (key_alloc)
+ __os_ufree(dbenv, replyp->keydata.keydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.data,
+ data.size);
+ } else
+ replyp->datadata.datadata_val = data.data;
+ replyp->datadata.datadata_len = data.size;
+ } else {
+err: replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ if (bulk_alloc)
+ __os_ufree(dbenv, data.data);
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_pget_proc */
+/*
+ * PUBLIC: void __dbc_pget_proc __P((long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *,
+ * PUBLIC: u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *, u_int32_t,
+ * PUBLIC: u_int32_t, __dbc_pget_reply *, int *));
+ */
+void
+__dbc_pget_proc(dbccl_id, skeydlen, skeydoff,
+ skeyulen, skeyflags, skeydata, skeysize,
+ pkeydlen, pkeydoff, pkeyulen, pkeyflags,
+ pkeydata, pkeysize, datadlen, datadoff,
+ dataulen, dataflags, datadata, datasize,
+ flags, replyp, freep)
+ long dbccl_id;
+ u_int32_t skeydlen;
+ u_int32_t skeydoff;
+ u_int32_t skeyulen;
+ u_int32_t skeyflags;
+ void *skeydata;
+ u_int32_t skeysize;
+ u_int32_t pkeydlen;
+ u_int32_t pkeydoff;
+ u_int32_t pkeyulen;
+ u_int32_t pkeyflags;
+ void *pkeydata;
+ u_int32_t pkeysize;
+ u_int32_t datadlen;
+ u_int32_t datadoff;
+ u_int32_t dataulen;
+ u_int32_t dataflags;
+ void *datadata;
+ u_int32_t datasize;
+ u_int32_t flags;
+ __dbc_pget_reply *replyp;
+ int * freep;
+/* END __dbc_pget_proc */
+{
+ DBC *dbc;
+ DBT skey, pkey, data;
+ DB_ENV *dbenv;
+ ct_entry *dbc_ctp;
+ int key_alloc, ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+ dbenv = dbc->dbp->dbenv;
+
+ *freep = 0;
+ memset(&skey, 0, sizeof(skey));
+ memset(&pkey, 0, sizeof(pkey));
+ memset(&data, 0, sizeof(data));
+
+ /*
+ * Ignore memory related flags on server.
+ */
+ /* Set up key and data DBT */
+ skey.flags = DB_DBT_MALLOC;
+ skey.dlen = skeydlen;
+ skey.ulen = skeyulen;
+ skey.doff = skeydoff;
+ if (skeyflags & DB_DBT_PARTIAL)
+ skey.flags |= DB_DBT_PARTIAL;
+ skey.size = skeysize;
+ skey.data = skeydata;
+
+ pkey.flags = DB_DBT_MALLOC;
+ pkey.dlen = pkeydlen;
+ pkey.ulen = pkeyulen;
+ pkey.doff = pkeydoff;
+ if (pkeyflags & DB_DBT_PARTIAL)
+ pkey.flags |= DB_DBT_PARTIAL;
+ pkey.size = pkeysize;
+ pkey.data = pkeydata;
+
+ data.flags = DB_DBT_MALLOC;
+ data.dlen = datadlen;
+ data.ulen = dataulen;
+ data.doff = datadoff;
+ if (dataflags & DB_DBT_PARTIAL)
+ data.flags |= DB_DBT_PARTIAL;
+ data.size = datasize;
+ data.data = datadata;
+
+ /* Got all our stuff, now do the get */
+ ret = dbc->c_pget(dbc, &skey, &pkey, &data, flags);
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (skey.data == skeydata) {
+ ret = __os_umalloc(dbenv,
+ skey.size, &replyp->skeydata.skeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv, skey.data);
+ __os_ufree(dbenv, pkey.data);
+ __os_ufree(dbenv, data.data);
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->skeydata.skeydata_val, skey.data,
+ skey.size);
+ } else
+ replyp->skeydata.skeydata_val = skey.data;
+ replyp->skeydata.skeydata_len = skey.size;
+
+ /*
+ * Primary key
+ */
+ if (pkey.data == pkeydata) {
+ ret = __os_umalloc(dbenv,
+ pkey.size, &replyp->pkeydata.pkeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv, skey.data);
+ __os_ufree(dbenv, pkey.data);
+ __os_ufree(dbenv, data.data);
+ if (key_alloc)
+ __os_ufree(dbenv,
+ replyp->skeydata.skeydata_val);
+ goto err;
+ }
+ /*
+ * We can set it to 2, because they cannot send the
+ * pkey over without sending the skey over too.
+ * So if they did send a pkey, they must have sent
+ * the skey as well.
+ */
+ key_alloc = 2;
+ memcpy(replyp->pkeydata.pkeydata_val, pkey.data,
+ pkey.size);
+ } else
+ replyp->pkeydata.pkeydata_val = pkey.data;
+ replyp->pkeydata.pkeydata_len = pkey.size;
+
+ /*
+ * Data
+ */
+ if (data.data == datadata) {
+ ret = __os_umalloc(dbenv,
+ data.size, &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv, skey.data);
+ __os_ufree(dbenv, pkey.data);
+ __os_ufree(dbenv, data.data);
+ /*
+ * If key_alloc is 1, just skey needs to be
+ * freed, if key_alloc is 2, both skey and pkey
+ * need to be freed.
+ */
+ if (key_alloc--)
+ __os_ufree(dbenv,
+ replyp->skeydata.skeydata_val);
+ if (key_alloc)
+ __os_ufree(dbenv,
+ replyp->pkeydata.pkeydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.data,
+ data.size);
+ } else
+ replyp->datadata.datadata_val = data.data;
+ replyp->datadata.datadata_len = data.size;
+ } else {
+err: replyp->skeydata.skeydata_val = NULL;
+ replyp->skeydata.skeydata_len = 0;
+ replyp->pkeydata.pkeydata_val = NULL;
+ replyp->pkeydata.pkeydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_put_proc */
+/*
+ * PUBLIC: void __dbc_put_proc __P((long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC: u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, void *,
+ * PUBLIC: u_int32_t, u_int32_t, __dbc_put_reply *, int *));
+ */
+void
+__dbc_put_proc(dbccl_id, keydlen, keydoff,
+ keyulen, keyflags, keydata, keysize,
+ datadlen, datadoff, dataulen, dataflags,
+ datadata, datasize, flags, replyp, freep)
+ long dbccl_id;
+ u_int32_t keydlen;
+ u_int32_t keydoff;
+ u_int32_t keyulen;
+ u_int32_t keyflags;
+ void *keydata;
+ u_int32_t keysize;
+ u_int32_t datadlen;
+ u_int32_t datadoff;
+ u_int32_t dataulen;
+ u_int32_t dataflags;
+ void *datadata;
+ u_int32_t datasize;
+ u_int32_t flags;
+ __dbc_put_reply *replyp;
+ int * freep;
+/* END __dbc_put_proc */
+{
+ DB *dbp;
+ DBC *dbc;
+ DBT key, data;
+ ct_entry *dbc_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+ dbp = (DB *)dbc_ctp->ct_parent->ct_anyp;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ /* Set up key and data DBT */
+ key.dlen = keydlen;
+ key.ulen = keyulen;
+ key.doff = keydoff;
+ /*
+ * Ignore memory related flags on server.
+ */
+ key.flags = 0;
+ if (keyflags & DB_DBT_PARTIAL)
+ key.flags |= DB_DBT_PARTIAL;
+ key.size = keysize;
+ key.data = keydata;
+
+ data.dlen = datadlen;
+ data.ulen = dataulen;
+ data.doff = datadoff;
+ data.flags = dataflags;
+ data.size = datasize;
+ data.data = datadata;
+
+ /* Got all our stuff, now do the put */
+ ret = dbc->c_put(dbc, &key, &data, flags);
+
+ *freep = 0;
+ if (ret == 0 && (flags == DB_AFTER || flags == DB_BEFORE) &&
+ dbp->type == DB_RECNO) {
+ /*
+ * We need to xdr_free whatever we are returning, next time.
+ */
+ replyp->keydata.keydata_val = key.data;
+ replyp->keydata.keydata_len = key.size;
+ } else {
+ replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+#endif /* HAVE_RPC */
diff --git a/bdb/rpc_server/c/db_server_util.c b/bdb/rpc_server/c/db_server_util.c
new file mode 100644
index 00000000000..2ea270c2d19
--- /dev/null
+++ b/bdb/rpc_server/c/db_server_util.c
@@ -0,0 +1,815 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_server_util.c,v 1.59 2002/03/27 04:32:50 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <rpc/rpc.h>
+
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+#include "dbinc_auto/db_server.h"
+
+#include "db_int.h"
+#include "dbinc_auto/clib_ext.h"
+#include "dbinc/db_server_int.h"
+#include "dbinc_auto/rpc_server_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+extern int __dbsrv_main __P((void));
+static int add_home __P((char *));
+static int add_passwd __P((char *));
+static int env_recover __P((char *));
+static void __dbclear_child __P((ct_entry *));
+
+static LIST_HEAD(cthead, ct_entry) __dbsrv_head;
+static LIST_HEAD(homehead, home_entry) __dbsrv_home;
+static long __dbsrv_defto = DB_SERVER_TIMEOUT;
+static long __dbsrv_maxto = DB_SERVER_MAXTIMEOUT;
+static long __dbsrv_idleto = DB_SERVER_IDLETIMEOUT;
+static char *logfile = NULL;
+static char *prog;
+
+static void usage __P((char *));
+static void version_check __P((void));
+
+int __dbsrv_verbose = 0;
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern char *optarg;
+ CLIENT *cl;
+ int ch, ret;
+ char *passwd;
+
+ prog = argv[0];
+
+ version_check();
+
+ ret = 0;
+ /*
+ * Check whether another server is running or not. There
+ * is a race condition where two servers could be racing to
+ * register with the portmapper. The goal of this check is to
+ * forbid running additional servers (like those started from
+ * the test suite) if the user is already running one.
+ *
+ * XXX
+ * This does not solve nor prevent two servers from being
+ * started at the same time and running recovery at the same
+ * time on the same environments.
+ */
+ if ((cl = clnt_create("localhost",
+ DB_RPC_SERVERPROG, DB_RPC_SERVERVERS, "tcp")) != NULL) {
+ fprintf(stderr,
+ "%s: Berkeley DB RPC server already running.\n", prog);
+ clnt_destroy(cl);
+ return (EXIT_FAILURE);
+ }
+
+ LIST_INIT(&__dbsrv_home);
+ while ((ch = getopt(argc, argv, "h:I:L:P:t:T:Vv")) != EOF)
+ switch (ch) {
+ case 'h':
+ (void)add_home(optarg);
+ break;
+ case 'I':
+ if (__db_getlong(NULL, prog,
+ optarg, 1, LONG_MAX, &__dbsrv_idleto))
+ return (EXIT_FAILURE);
+ break;
+ case 'L':
+ logfile = optarg;
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ prog, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ if ((ret = add_passwd(passwd)) != 0) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ prog, strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ break;
+ case 't':
+ if (__db_getlong(NULL, prog,
+ optarg, 1, LONG_MAX, &__dbsrv_defto))
+ return (EXIT_FAILURE);
+ break;
+ case 'T':
+ if (__db_getlong(NULL, prog,
+ optarg, 1, LONG_MAX, &__dbsrv_maxto))
+ return (EXIT_FAILURE);
+ break;
+ case 'V':
+ printf("%s\n", db_version(NULL, NULL, NULL));
+ return (EXIT_SUCCESS);
+ case 'v':
+ __dbsrv_verbose = 1;
+ break;
+ default:
+ usage(prog);
+ }
+ /*
+ * Check default timeout against maximum timeout
+ */
+ if (__dbsrv_defto > __dbsrv_maxto)
+ __dbsrv_defto = __dbsrv_maxto;
+
+ /*
+ * Check default timeout against idle timeout
+ * It would be bad to timeout environments sooner than txns.
+ */
+ if (__dbsrv_defto > __dbsrv_idleto)
+ fprintf(stderr,
+ "%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
+ prog, __dbsrv_idleto, __dbsrv_defto);
+
+ LIST_INIT(&__dbsrv_head);
+
+ /*
+ * If a client crashes during an RPC, our reply to it
+ * generates a SIGPIPE. Ignore SIGPIPE so we don't exit unnecessarily.
+ */
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ if (logfile != NULL && __db_util_logset("berkeley_db_svc", logfile))
+ return (EXIT_FAILURE);
+
+ /*
+ * Now that we are ready to start, run recovery on all the
+ * environments specified.
+ */
+ if (env_recover(prog) != 0)
+ return (EXIT_FAILURE);
+
+ /*
+ * We've done our setup, now call the generated server loop
+ */
+ if (__dbsrv_verbose)
+ printf("%s: Ready to receive requests\n", prog);
+ __dbsrv_main();
+
+ /* NOTREACHED */
+ abort();
+}
+
+static void
+usage(prog)
+ char *prog;
+{
+ fprintf(stderr, "usage: %s %s\n\t%s\n", prog,
+ "[-Vv] [-h home] [-P passwd]",
+ "[-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
+ exit(EXIT_FAILURE);
+}
+
+static void
+version_check()
+{
+ int v_major, v_minor, v_patch;
+
+ /* Make sure we're loaded with the right version of the DB library. */
+ (void)db_version(&v_major, &v_minor, &v_patch);
+ if (v_major != DB_VERSION_MAJOR ||
+ v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+ fprintf(stderr,
+ "%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+ prog, DB_VERSION_MAJOR, DB_VERSION_MINOR,
+ DB_VERSION_PATCH, v_major, v_minor, v_patch);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/*
+ * PUBLIC: void __dbsrv_settimeout __P((ct_entry *, u_int32_t));
+ */
+void
+__dbsrv_settimeout(ctp, to)
+ ct_entry *ctp;
+ u_int32_t to;
+{
+ if (to > (u_int32_t)__dbsrv_maxto)
+ ctp->ct_timeout = __dbsrv_maxto;
+ else if (to <= 0)
+ ctp->ct_timeout = __dbsrv_defto;
+ else
+ ctp->ct_timeout = to;
+}
+
+/*
+ * PUBLIC: void __dbsrv_timeout __P((int));
+ */
+void
+__dbsrv_timeout(force)
+ int force;
+{
+ static long to_hint = -1;
+ time_t t;
+ long to;
+ ct_entry *ctp, *nextctp;
+
+ if ((t = time(NULL)) == -1)
+ return;
+
+ /*
+ * Check hint. If hint is further in the future
+ * than now, no work to do.
+ */
+ if (!force && to_hint > 0 && t < to_hint)
+ return;
+ to_hint = -1;
+ /*
+ * Timeout transactions or cursors holding DB resources.
+ * Do this before timing out envs to properly release resources.
+ *
+ * !!!
+ * We can just loop through this list looking for cursors and txns.
+ * We do not need to verify txn and cursor relationships at this
+ * point because we maintain the list in LIFO order *and* we
+ * maintain activity in the ultimate txn parent of any cursor
+ * so either everything in a txn is timing out, or nothing.
+ * So, since we are LIFO, we will correctly close/abort all the
+ * appropriate handles, in the correct order.
+ */
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
+ nextctp = LIST_NEXT(ctp, entries);
+ switch (ctp->ct_type) {
+ case CT_TXN:
+ to = *(ctp->ct_activep) + ctp->ct_timeout;
+ /* TIMEOUT */
+ if (to < t) {
+ if (__dbsrv_verbose)
+ printf("Timing out txn id %ld\n",
+ ctp->ct_id);
+ (void)((DB_TXN *)ctp->ct_anyp)->
+ abort((DB_TXN *)ctp->ct_anyp);
+ __dbdel_ctp(ctp);
+ /*
+ * If we timed out an txn, we may have closed
+ * all sorts of ctp's.
+ * So start over with a guaranteed good ctp.
+ */
+ nextctp = LIST_FIRST(&__dbsrv_head);
+ } else if ((to_hint > 0 && to_hint > to) ||
+ to_hint == -1)
+ to_hint = to;
+ break;
+ case CT_CURSOR:
+ case (CT_JOINCUR | CT_CURSOR):
+ to = *(ctp->ct_activep) + ctp->ct_timeout;
+ /* TIMEOUT */
+ if (to < t) {
+ if (__dbsrv_verbose)
+ printf("Timing out cursor %ld\n",
+ ctp->ct_id);
+ (void)__dbc_close_int(ctp);
+ /*
+ * Start over with a guaranteed good ctp.
+ */
+ nextctp = LIST_FIRST(&__dbsrv_head);
+ } else if ((to_hint > 0 && to_hint > to) ||
+ to_hint == -1)
+ to_hint = to;
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * Timeout idle handles.
+ * If we are forcing a timeout, we'll close all env handles.
+ */
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
+ nextctp = LIST_NEXT(ctp, entries);
+ if (ctp->ct_type != CT_ENV)
+ continue;
+ to = *(ctp->ct_activep) + ctp->ct_idle;
+ /* TIMEOUT */
+ if (to < t || force) {
+ if (__dbsrv_verbose)
+ printf("Timing out env id %ld\n", ctp->ct_id);
+ (void)__dbenv_close_int(ctp->ct_id, 0, 1);
+ /*
+ * If we timed out an env, we may have closed
+ * all sorts of ctp's (maybe even all of them.
+ * So start over with a guaranteed good ctp.
+ */
+ nextctp = LIST_FIRST(&__dbsrv_head);
+ }
+ }
+}
+
+/*
+ * RECURSIVE FUNCTION. We need to clear/free any number of levels of nested
+ * layers.
+ */
+static void
+__dbclear_child(parent)
+ ct_entry *parent;
+{
+ ct_entry *ctp, *nextctp;
+
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = nextctp) {
+ nextctp = LIST_NEXT(ctp, entries);
+ if (ctp->ct_type == 0)
+ continue;
+ if (ctp->ct_parent == parent) {
+ __dbclear_child(ctp);
+ /*
+ * Need to do this here because le_next may
+ * have changed with the recursive call and we
+ * don't want to point to a removed entry.
+ */
+ nextctp = LIST_NEXT(ctp, entries);
+ __dbclear_ctp(ctp);
+ }
+ }
+}
+
+/*
+ * PUBLIC: void __dbclear_ctp __P((ct_entry *));
+ */
+void
+__dbclear_ctp(ctp)
+ ct_entry *ctp;
+{
+ LIST_REMOVE(ctp, entries);
+ __os_free(NULL, ctp);
+}
+
+/*
+ * PUBLIC: void __dbdel_ctp __P((ct_entry *));
+ */
+void
+__dbdel_ctp(parent)
+ ct_entry *parent;
+{
+ __dbclear_child(parent);
+ __dbclear_ctp(parent);
+}
+
+/*
+ * PUBLIC: ct_entry *new_ct_ent __P((int *));
+ */
+ct_entry *
+new_ct_ent(errp)
+ int *errp;
+{
+ time_t t;
+ ct_entry *ctp, *octp;
+ int ret;
+
+ if ((ret = __os_malloc(NULL, sizeof(ct_entry), &ctp)) != 0) {
+ *errp = ret;
+ return (NULL);
+ }
+ memset(ctp, 0, sizeof(ct_entry));
+ /*
+ * Get the time as ID. We may service more than one request per
+ * second however. If we are, then increment id value until we
+ * find an unused one. We insert entries in LRU fashion at the
+ * head of the list. So, if the first entry doesn't match, then
+ * we know for certain that we can use our entry.
+ */
+ if ((t = time(NULL)) == -1) {
+ *errp = __os_get_errno();
+ __os_free(NULL, ctp);
+ return (NULL);
+ }
+ octp = LIST_FIRST(&__dbsrv_head);
+ if (octp != NULL && octp->ct_id >= t)
+ t = octp->ct_id + 1;
+ ctp->ct_id = t;
+ ctp->ct_idle = __dbsrv_idleto;
+ ctp->ct_activep = &ctp->ct_active;
+ ctp->ct_origp = NULL;
+ ctp->ct_refcount = 1;
+
+ LIST_INSERT_HEAD(&__dbsrv_head, ctp, entries);
+ return (ctp);
+}
+
+/*
+ * PUBLIC: ct_entry *get_tableent __P((long));
+ */
+ct_entry *
+get_tableent(id)
+ long id;
+{
+ ct_entry *ctp;
+
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries))
+ if (ctp->ct_id == id)
+ return (ctp);
+ return (NULL);
+}
+
+/*
+ * PUBLIC: ct_entry *__dbsrv_sharedb __P((ct_entry *, const char *,
+ * PUBLIC: const char *, DBTYPE, u_int32_t));
+ */
+ct_entry *
+__dbsrv_sharedb(db_ctp, name, subdb, type, flags)
+ ct_entry *db_ctp;
+ const char *name, *subdb;
+ DBTYPE type;
+ u_int32_t flags;
+{
+ ct_entry *ctp;
+
+ /*
+ * Check if we can share a db handle. Criteria for sharing are:
+ * If any of the non-sharable flags are set, we cannot share.
+ * Must be a db ctp, obviously.
+ * Must share the same env parent.
+ * Must be the same type, or current one DB_UNKNOWN.
+ * Must be same byteorder, or current one must not care.
+ * All flags must match.
+ * Must be same name, but don't share in-memory databases.
+ * Must be same subdb name.
+ */
+ if (flags & DB_SERVER_DBNOSHARE)
+ return (NULL);
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries)) {
+ /*
+ * Skip ourselves.
+ */
+ if (ctp == db_ctp)
+ continue;
+ if (ctp->ct_type != CT_DB)
+ continue;
+ if (ctp->ct_envparent != db_ctp->ct_envparent)
+ continue;
+ if (type != DB_UNKNOWN && ctp->ct_dbdp.type != type)
+ continue;
+ if (ctp->ct_dbdp.dbflags != LF_ISSET(DB_SERVER_DBFLAGS))
+ continue;
+ if (db_ctp->ct_dbdp.setflags != 0 &&
+ ctp->ct_dbdp.setflags != db_ctp->ct_dbdp.setflags)
+ continue;
+ if (name == NULL || ctp->ct_dbdp.db == NULL ||
+ strcmp(name, ctp->ct_dbdp.db) != 0)
+ continue;
+ if (subdb != ctp->ct_dbdp.subdb &&
+ (subdb == NULL || ctp->ct_dbdp.subdb == NULL ||
+ strcmp(subdb, ctp->ct_dbdp.subdb) != 0))
+ continue;
+ /*
+ * If we get here, then we match.
+ */
+ ctp->ct_refcount++;
+ return (ctp);
+ }
+
+ return (NULL);
+}
+
+/*
+ * PUBLIC: ct_entry *__dbsrv_shareenv __P((ct_entry *, home_entry *, u_int32_t));
+ */
+ct_entry *
+__dbsrv_shareenv(env_ctp, home, flags)
+ ct_entry *env_ctp;
+ home_entry *home;
+ u_int32_t flags;
+{
+ ct_entry *ctp;
+
+ /*
+ * Check if we can share an env. Criteria for sharing are:
+ * Must be an env ctp, obviously.
+ * Must share the same home env.
+ * All flags must match.
+ */
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries)) {
+ /*
+ * Skip ourselves.
+ */
+ if (ctp == env_ctp)
+ continue;
+ if (ctp->ct_type != CT_ENV)
+ continue;
+ if (ctp->ct_envdp.home != home)
+ continue;
+ if (ctp->ct_envdp.envflags != flags)
+ continue;
+ if (ctp->ct_envdp.onflags != env_ctp->ct_envdp.onflags)
+ continue;
+ if (ctp->ct_envdp.offflags != env_ctp->ct_envdp.offflags)
+ continue;
+ /*
+ * If we get here, then we match. The only thing left to
+ * check is the timeout. Since the server timeout set by
+ * the client is a hint, for sharing we'll give them the
+ * benefit of the doubt and grant them the longer timeout.
+ */
+ if (ctp->ct_timeout < env_ctp->ct_timeout)
+ ctp->ct_timeout = env_ctp->ct_timeout;
+ ctp->ct_refcount++;
+ return (ctp);
+ }
+
+ return (NULL);
+}
+
+/*
+ * PUBLIC: void __dbsrv_active __P((ct_entry *));
+ */
+void
+__dbsrv_active(ctp)
+ ct_entry *ctp;
+{
+ time_t t;
+ ct_entry *envctp;
+
+ if (ctp == NULL)
+ return;
+ if ((t = time(NULL)) == -1)
+ return;
+ *(ctp->ct_activep) = t;
+ if ((envctp = ctp->ct_envparent) == NULL)
+ return;
+ *(envctp->ct_activep) = t;
+ return;
+}
+
+/*
+ * PUBLIC: int __db_close_int __P((long, u_int32_t));
+ */
+int
+__db_close_int(id, flags)
+ long id;
+ u_int32_t flags;
+{
+ DB *dbp;
+ int ret;
+ ct_entry *ctp;
+
+ ret = 0;
+ ctp = get_tableent(id);
+ if (ctp == NULL)
+ return (DB_NOSERVER_ID);
+ DB_ASSERT(ctp->ct_type == CT_DB);
+ if (__dbsrv_verbose && ctp->ct_refcount != 1)
+ printf("Deref'ing dbp id %ld, refcount %d\n",
+ id, ctp->ct_refcount);
+ if (--ctp->ct_refcount != 0)
+ return (ret);
+ dbp = ctp->ct_dbp;
+ if (__dbsrv_verbose)
+ printf("Closing dbp id %ld\n", id);
+
+ ret = dbp->close(dbp, flags);
+ __dbdel_ctp(ctp);
+ return (ret);
+}
+
+/*
+ * PUBLIC: int __dbc_close_int __P((ct_entry *));
+ */
+int
+__dbc_close_int(dbc_ctp)
+ ct_entry *dbc_ctp;
+{
+ DBC *dbc;
+ int ret;
+ ct_entry *ctp;
+
+ dbc = (DBC *)dbc_ctp->ct_anyp;
+
+ ret = dbc->c_close(dbc);
+ /*
+ * If this cursor is a join cursor then we need to fix up the
+ * cursors that it was joined from so that they are independent again.
+ */
+ if (dbc_ctp->ct_type & CT_JOINCUR)
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries)) {
+ /*
+ * Test if it is a join cursor, and if it is part
+ * of this one.
+ */
+ if ((ctp->ct_type & CT_JOIN) &&
+ ctp->ct_activep == &dbc_ctp->ct_active) {
+ ctp->ct_type &= ~CT_JOIN;
+ ctp->ct_activep = ctp->ct_origp;
+ __dbsrv_active(ctp);
+ }
+ }
+ __dbclear_ctp(dbc_ctp);
+ return (ret);
+
+}
+
+/*
+ * PUBLIC: int __dbenv_close_int __P((long, u_int32_t, int));
+ */
+int
+__dbenv_close_int(id, flags, force)
+ long id;
+ u_int32_t flags;
+ int force;
+{
+ DB_ENV *dbenv;
+ int ret;
+ ct_entry *ctp;
+
+ ret = 0;
+ ctp = get_tableent(id);
+ if (ctp == NULL)
+ return (DB_NOSERVER_ID);
+ DB_ASSERT(ctp->ct_type == CT_ENV);
+ if (__dbsrv_verbose && ctp->ct_refcount != 1)
+ printf("Deref'ing env id %ld, refcount %d\n",
+ id, ctp->ct_refcount);
+ /*
+ * If we are timing out, we need to force the close, no matter
+ * what the refcount.
+ */
+ if (--ctp->ct_refcount != 0 && !force)
+ return (ret);
+ dbenv = ctp->ct_envp;
+ if (__dbsrv_verbose)
+ printf("Closing env id %ld\n", id);
+
+ ret = dbenv->close(dbenv, flags);
+ __dbdel_ctp(ctp);
+ return (ret);
+}
+
+static int
+add_home(home)
+ char *home;
+{
+ home_entry *hp, *homep;
+ int ret;
+
+ if ((ret = __os_malloc(NULL, sizeof(home_entry), &hp)) != 0)
+ return (ret);
+ if ((ret = __os_malloc(NULL, strlen(home)+1, &hp->home)) != 0)
+ return (ret);
+ memcpy(hp->home, home, strlen(home)+1);
+ hp->dir = home;
+ hp->passwd = NULL;
+ /*
+ * This loop is to remove any trailing path separators,
+ * to assure hp->name points to the last component.
+ */
+ hp->name = __db_rpath(home);
+ *(hp->name) = '\0';
+ hp->name++;
+ while (*(hp->name) == '\0') {
+ hp->name = __db_rpath(home);
+ *(hp->name) = '\0';
+ hp->name++;
+ }
+ /*
+ * Now we have successfully added it. Make sure there are no
+ * identical names.
+ */
+ for (homep = LIST_FIRST(&__dbsrv_home); homep != NULL;
+ homep = LIST_NEXT(homep, entries))
+ if (strcmp(homep->name, hp->name) == 0) {
+ printf("Already added home name %s, at directory %s\n",
+ hp->name, homep->dir);
+ __os_free(NULL, hp->home);
+ __os_free(NULL, hp);
+ return (-1);
+ }
+ LIST_INSERT_HEAD(&__dbsrv_home, hp, entries);
+ if (__dbsrv_verbose)
+ printf("Added home %s in dir %s\n", hp->name, hp->dir);
+ return (0);
+}
+
+static int
+add_passwd(passwd)
+ char *passwd;
+{
+ home_entry *hp;
+
+ /*
+ * We add the passwd to the last given home dir. If there
+ * isn't a home dir, or the most recent one already has a
+ * passwd, then there is a user error.
+ */
+ hp = LIST_FIRST(&__dbsrv_home);
+ if (hp == NULL || hp->passwd != NULL)
+ return (EINVAL);
+ /*
+ * We've already strdup'ed the passwd above, so we don't need
+ * to malloc new space, just point to it.
+ */
+ hp->passwd = passwd;
+ return (0);
+}
+
+/*
+ * PUBLIC: home_entry *get_home __P((char *));
+ */
+home_entry *
+get_home(name)
+ char *name;
+{
+ home_entry *hp;
+
+ for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
+ hp = LIST_NEXT(hp, entries))
+ if (strcmp(name, hp->name) == 0)
+ return (hp);
+ return (NULL);
+}
+
+static int
+env_recover(progname)
+ char *progname;
+{
+ DB_ENV *dbenv;
+ home_entry *hp;
+ u_int32_t flags;
+ int exitval, ret;
+
+ for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
+ hp = LIST_NEXT(hp, entries)) {
+ exitval = 0;
+ if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ fprintf(stderr, "%s: db_env_create: %s\n",
+ progname, db_strerror(ret));
+ exit(EXIT_FAILURE);
+ }
+ if (__dbsrv_verbose == 1) {
+ (void)dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
+ (void)dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
+ }
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, progname);
+ if (hp->passwd != NULL)
+ (void)dbenv->set_encrypt(dbenv, hp->passwd,
+ DB_ENCRYPT_AES);
+
+ /*
+ * Initialize the env with DB_RECOVER. That is all we
+ * have to do to run recovery.
+ */
+ if (__dbsrv_verbose)
+ printf("Running recovery on %s\n", hp->home);
+ flags = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
+ DB_INIT_TXN | DB_USE_ENVIRON | DB_RECOVER;
+ if ((ret = dbenv->open(dbenv, hp->home, flags, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB_ENV->open");
+ goto error;
+ }
+
+ if (0) {
+error: exitval = 1;
+ }
+ if ((ret = dbenv->close(dbenv, 0)) != 0) {
+ exitval = 1;
+ fprintf(stderr, "%s: dbenv->close: %s\n",
+ progname, db_strerror(ret));
+ }
+ if (exitval)
+ return (exitval);
+ }
+ return (0);
+}
diff --git a/bdb/rpc_server/clsrv.html b/bdb/rpc_server/clsrv.html
index ae089c4b382..599ad56f557 100644
--- a/bdb/rpc_server/clsrv.html
+++ b/bdb/rpc_server/clsrv.html
@@ -1,52 +1,52 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="GENERATOR" CONTENT="Mozilla/4.08 [en] (X11; I; FreeBSD 3.3-RELEASE i386) [Netscape]">
-</HEAD>
-<BODY>
-
-<CENTER>
-<H1>
-Client/Server Interface for Berkeley DB</H1></CENTER>
-
-<CENTER><I>Susan LoVerso</I>
-<BR><I>sue@sleepycat.com</I>
-<BR><I>Rev 1.3</I>
-<BR><I>1999 Nov 29</I></CENTER>
-
-<P>We provide an interface allowing client/server access to Berkeley DB.&nbsp;&nbsp;
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.76 [en] (X11; U; FreeBSD 4.3-RELEASE i386) [Netscape]">
+</head>
+<body>
+
+<center>
+<h1>
+&nbsp;Client/Server Interface for Berkeley DB</h1></center>
+
+<center><i>Susan LoVerso</i>
+<br><i>sue@sleepycat.com</i>
+<br><i>Rev 1.3</i>
+<br><i>1999 Nov 29</i></center>
+
+<p>We provide an interface allowing client/server access to Berkeley DB.&nbsp;&nbsp;
Our goal is to provide a client and server library to allow users to separate
the functionality of their applications yet still have access to the full
benefits of Berkeley DB.&nbsp; The goal is to provide a totally seamless
interface with minimal modification to existing applications as well.
-<P>The client/server interface for Berkeley DB can be broken up into several
+<p>The client/server interface for Berkeley DB can be broken up into several
layers.&nbsp; At the lowest level there is the transport mechanism to send
out the messages over the network.&nbsp; Above that layer is the messaging
layer to interpret what comes over the wire, and bundle/unbundle message
contents.&nbsp; The next layer is Berkeley DB itself.
-<P>The transport layer uses ONC RPC (RFC 1831) and XDR (RFC 1832).&nbsp;
+<p>The transport layer uses ONC RPC (RFC 1831) and XDR (RFC 1832).&nbsp;
We declare our message types and operations supported by our program and
the RPC library and utilities pretty much take care of the rest.&nbsp;
The
-<I>rpcgen</I> program generates all of the low level code needed.&nbsp;
+<i>rpcgen</i> program generates all of the low level code needed.&nbsp;
We need to define both sides of the RPC.
-<BR>&nbsp;
-<H2>
-<A NAME="DB Modifications"></A>DB Modifications</H2>
+<br>&nbsp;
+<h2>
+<a NAME="DB Modifications"></a>DB Modifications</h2>
To achieve the goal of a seamless interface, it is necessary to impose
a constraint on the application. That constraint is simply that all database
access must be done through an open environment.&nbsp; I.e. this model
does not support standalone databases.&nbsp; The reason for this constraint
is so that we have an environment structure internally to store our connection
to the server.&nbsp; Imposing this constraint means that we can provide
-the seamless interface just by adding a single environment method: <A HREF="../docs/api_c/env_set_server.html">DBENV->set_server()</A>.
-<P>The planned interface for this method is:
-<PRE>DBENV->set_server(dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB_ENV structure */
+the seamless interface just by adding a single environment method: <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>.
+<p>The planned interface for this method is:
+<pre>DBENV->set_rpc_server(dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB_ENV structure */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hostname&nbsp;&nbsp;&nbsp; /* Host of server */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cl_timeout, /* Client timeout (sec) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv_timeout,/* Server timeout (sec) */
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags: unused */</PRE>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags: unused */</pre>
This new method takes the hostname of the server, establishes our connection
and an environment on the server.&nbsp; If a server timeout is specified,
then we send that to the server as well (and the server may or may not
@@ -61,30 +61,30 @@ is currently unused, but exists because we always need to have a placeholder
for flags and it would be used for specifying authentication desired (were
we to provide an authentication scheme at some point) or other uses not
thought of yet!
-<P>This client code is part of the monolithic DB library.&nbsp; The user
-accesses the client functions via a new flag to <A HREF="../docs/api_c/db_env_create.html">db_env_create()</A>.&nbsp;
+<p>This client code is part of the monolithic DB library.&nbsp; The user
+accesses the client functions via a new flag to <a href="../docs/api_c/db_env_create.html">db_env_create()</a>.&nbsp;
That flag is DB_CLIENT.&nbsp; By using this flag the user indicates they
want to have the client methods rather than the standard methods for the
environment.&nbsp; Also by issuing this flag, the user needs to connect
-to the server via the <A HREF="../docs/api_c/env_set_server.html">DBENV->set_server()</A>
+to the server via the <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>
method.
-<P>We need two new fields in the <I>DB_ENV </I>structure.&nbsp; One is
+<p>We need two new fields in the <i>DB_ENV </i>structure.&nbsp; One is
the socket descriptor to communicate to the server, the other field is
-the client identifier the server gives to us.&nbsp; The <I>DB, </I>and<I>
-DBC </I>only need one additional field, the client identifier.&nbsp; The
-<I>DB_TXN</I>
-structure does not need modification, we are overloading the <I>txn_id
-</I>field.
-<H2>
-Issues</H2>
+the client identifier the server gives to us.&nbsp; The <i>DB, </i>and<i>
+DBC </i>only need one additional field, the client identifier.&nbsp; The
+<i>DB_TXN</i>
+structure does not need modification, we are overloading the <i>txn_id
+</i>field.
+<h2>
+Issues</h2>
We need to figure out what to do in case of client and server crashes.&nbsp;
Both the client library and the server program are stateful.&nbsp; They
both consume local resources during the lifetime of the connection.&nbsp;
Should one end drop that connection, the other side needs to release those
resources.
-<P>If the server crashes, then the client will get an error back.&nbsp;
+<p>If the server crashes, then the client will get an error back.&nbsp;
I have chosen to implement time-outs on the client side, using a default
-or allowing the application to specify one through the <A HREF="../docs/api_c/env_set_server.html">DBENV->set_server()</A>
+or allowing the application to specify one through the <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>
method.&nbsp; Either the current operation will time-out waiting for the
reply or the next operation called will time out (or get back some other
kind of error regarding the server's non-existence).&nbsp; In any case,
@@ -102,65 +102,65 @@ on recover.&nbsp; The client can then re-establish its connection and begin
again.&nbsp; This is effectively like beginning over.&nbsp; The client
cannot use ID's from its previous connection to the server.&nbsp; However,
if recovery is run, then consistency is assured.
-<P>If the client crashes, the server needs to somehow figure this out.&nbsp;
+<p>If the client crashes, the server needs to somehow figure this out.&nbsp;
The server is just sitting there waiting for a request to come in.&nbsp;
A server must be able to time-out a client.&nbsp; Similar to ftpd, if a
connection is idle for N seconds, then the server decides the client is
dead and releases that client's resources, aborting any open transactions,
closing any open databases and environments.&nbsp;&nbsp; The server timing
out a client is not a trivial issue however.&nbsp; The generated function
-for the server just calls <I>svc_run()</I>.&nbsp; The server code I write
+for the server just calls <i>svc_run()</i>.&nbsp; The server code I write
contains procedures to do specific things.&nbsp; We do not have access
-to the code calling <I>select()</I>.&nbsp; Timing out the select is not
+to the code calling <i>select()</i>.&nbsp; Timing out the select is not
good enough even if we could do so.&nbsp; We want to time-out idle environments,
not simply cause a time-out if the server is idle a while.&nbsp; See the
-discussion of the <A HREF="#The Server Program">server program</A> for
+discussion of the <a href="#The Server Program">server program</a> for
a description of how we accomplish this.
-<P>Since rpcgen generates the main() function of the server, I do not yet
+<p>Since rpcgen generates the main() function of the server, I do not yet
know how we are going to have the server multi-threaded or multi-process
without changing the generated code.&nbsp; The RPC book indicates that
the only way to accomplish this is through modifying the generated code
-in the server.&nbsp; <B>For the moment we will ignore this issue while
-we get the core server working, as it is only a performance issue.</B>
-<P>We do not do any security or authentication.&nbsp; Someone could get
+in the server.&nbsp; <b>For the moment we will ignore this issue while
+we get the core server working, as it is only a performance issue.</b>
+<p>We do not do any security or authentication.&nbsp; Someone could get
the code and modify it to spoof messages, trick the server, etc.&nbsp;
RPC has some amount of authentication built into it.&nbsp; I haven't yet
looked into it much to know if we want to use it or just point a user at
it.&nbsp; The changes to the client code are fairly minor, the changes
to our server procs are fairly minor.&nbsp; We would have to add code to
-a <I>sed</I> script or <I>awk</I> script to change the generated server
+a <i>sed</i> script or <i>awk</i> script to change the generated server
code (yet again) in the dispatch routine to perform authentication.
-<P>We will need to get an official program number from Sun.&nbsp; We can
-get this by sending mail to <I>rpc@sun.com</I> and presumably at some point
+<p>We will need to get an official program number from Sun.&nbsp; We can
+get this by sending mail to <i>rpc@sun.com</i> and presumably at some point
they will send us back a program number that we will encode into our XDR
description file.&nbsp; Until we release this we can use a program number
in the "user defined" number space.
-<BR>&nbsp;
-<H2>
-<A NAME="The Server Program"></A>The Server Program</H2>
+<br>&nbsp;
+<h2>
+<a NAME="The Server Program"></a>The Server Program</h2>
The server is a standalone program that the user builds and runs, probably
as a daemon like process.&nbsp; This program is linked against the Berkeley
DB library and the RPC library (which is part of the C library on my FreeBSD
-machine, others may have/need <I>-lrpclib</I>).&nbsp; The server basically
+machine, others may have/need <i>-lrpclib</i>).&nbsp; The server basically
is a slave to the client process.&nbsp; All messages from the client are
synchronous and two-way.&nbsp; The server handles messages one at a time,
and sends a reply back before getting another message.&nbsp; There are
no asynchronous messages generated by the server to the client.
-<P>We have made a choice to modify the generated code for the server.&nbsp;
+<p>We have made a choice to modify the generated code for the server.&nbsp;
The changes will be minimal, generally calling functions we write, that
are in other source files.&nbsp; The first change is adding a call to our
time-out function as described below.&nbsp; The second change is changing
-the name of the generated <I>main()</I> function to <I>__dbsrv_main()</I>,
-and adding our own <I>main()</I> function so that we can parse options,
-and set up other initialization we require.&nbsp; I have a <I>sed</I> script
+the name of the generated <i>main()</i> function to <i>__dbsrv_main()</i>,
+and adding our own <i>main()</i> function so that we can parse options,
+and set up other initialization we require.&nbsp; I have a <i>sed</i> script
that is run from the distribution scripts that massages the generated code
to make these minor changes.
-<P>Primarily the code needed for the server is the collection of the specified
+<p>Primarily the code needed for the server is the collection of the specified
RPC functions.&nbsp; Each function receives the structure indicated, and
our code takes out what it needs and passes the information into DB itself.&nbsp;
The server needs to maintain a translation table for identifiers that we
pass back to the client for the environment, transaction and database handles.
-<P>The table that the server maintains, assuming one client per server
+<p>The table that the server maintains, assuming one client per server
process/thread, should contain the handle to the environment, database
or transaction, a link to maintain parent/child relationships between transactions,
or databases and cursors, this handle's identifier, a type so that we can
@@ -169,7 +169,7 @@ handle's environment entry (for time out/activity purposes).&nbsp; The
table contains, in entries used by environments, a time-out value and an
activity time stamp.&nbsp; Its use is described below for timing out idle
clients.
-<P>Here is how we time out clients in the server.&nbsp; We have to modify
+<p>Here is how we time out clients in the server.&nbsp; We have to modify
the generated server code, but only to add one line during the dispatch
function to run the time-out function.&nbsp; The call is made right before
the return of the dispatch function, after the reply is sent to the client,
@@ -181,16 +181,16 @@ we know we do not need to run through the list of open handles.&nbsp; If
the hint is expired, then we go through the list of open environment handles,
and if they are past their expiration, then we close them and clean up.&nbsp;
If they are not, we set up the hint for the next time.
-<P>Each entry in the open handle table has a pointer back to its environment's
+<p>Each entry in the open handle table has a pointer back to its environment's
entry.&nbsp; Every operation within this environment can then update the
single environment activity record.&nbsp; Every environment can have a
-different time-out.&nbsp; The <A HREF="../docs/api_c/env_set_server.html">DBENV->set_server
-</A>call
+different time-out.&nbsp; The <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server
+</a>call
takes a server time-out value.&nbsp; If this value is 0 then a default
(currently 5 minutes) is used.&nbsp; This time-out value is only a hint
to the server.&nbsp; It may choose to disregard this value or set the time-out
based on its own implementation.
-<P>For completeness, the flaws of this time-out implementation should be
+<p>For completeness, the flaws of this time-out implementation should be
pointed out.&nbsp; First, it is possible that a client could crash with
open handles, and no other requests come in to the server.&nbsp; Therefore
the time-out function never gets run and those resources are not released
@@ -205,222 +205,222 @@ of 1 minute.&nbsp; If this environment becomes idle (and other operations
are going on), the time-out function will not release that environment
until the original 5 minute hint expires.&nbsp; This is not a problem since
the resources will eventually be released.
-<P>On a similar note, if a client crashes during an RPC, our reply generates
-a SIGPIPE, and our server crashes unless we catch it.&nbsp; Using <I>signal(SIGPIPE,
-SIG_IGN) </I>we can ignore it, and the server will go on.&nbsp; This is
-a call&nbsp; in our <I>main()</I> function that we write.&nbsp; Eventually
+<p>On a similar note, if a client crashes during an RPC, our reply generates
+a SIGPIPE, and our server crashes unless we catch it.&nbsp; Using <i>signal(SIGPIPE,
+SIG_IGN) </i>we can ignore it, and the server will go on.&nbsp; This is
+a call&nbsp; in our <i>main()</i> function that we write.&nbsp; Eventually
this client's handles would be timed out as described above.&nbsp; We need
this only for the unfortunate window of a client crashing during the RPC.
-<P>The options below are primarily for control of the program itself,.&nbsp;
+<p>The options below are primarily for control of the program itself,.&nbsp;
Details relating to databases and environments should be passed from the
client to the server, since the server can serve many clients, many environments
and many databases.&nbsp; Therefore it makes more sense for the client
to set the cache size of its own environment, rather than setting a default
cachesize on the server that applies as a blanket to any environment it
may be called upon to open.&nbsp; Options are:
-<UL>
-<LI>
-<B>-t&nbsp;</B> to set the default time-out given to an environment.</LI>
+<ul>
+<li>
+<b>-t&nbsp;</b> to set the default time-out given to an environment.</li>
-<LI>
-<B>-T</B> to set the maximum time-out allowed for the server.</LI>
+<li>
+<b>-T</b> to set the maximum time-out allowed for the server.</li>
-<LI>
-<B>-L</B> to log the execution of the server process to a specified file.</LI>
+<li>
+<b>-L</b> to log the execution of the server process to a specified file.</li>
-<LI>
-<B>-v</B> to run in verbose mode.</LI>
+<li>
+<b>-v</b> to run in verbose mode.</li>
-<LI>
-<B>-M</B>&nbsp; to specify the maximum number of outstanding child server
+<li>
+<b>-M</b>&nbsp; to specify the maximum number of outstanding child server
processes/threads we can have at any given time.&nbsp; The default is 10.
-<B>[We
-are not yet doing multiple threads/processes.]</B></LI>
-</UL>
+<b>[We
+are not yet doing multiple threads/processes.]</b></li>
+</ul>
-<H2>
-The Client Code</H2>
+<h2>
+The Client Code</h2>
The client code contains all of the supported functions and methods used
-in this model.&nbsp; There are several methods in the <I>__db_env
-</I>and
-<I>__db</I>
+in this model.&nbsp; There are several methods in the <i>__db_env
+</i>and
+<i>__db</i>
structures that currently do not apply, such as the callbacks.&nbsp; Those
fields that are not applicable to the client model point to NULL to notify
the user of their error.&nbsp; Some method functions remain unchanged,
as well such as the error calls.
-<P>The client code contains each method function that goes along with the
-<A HREF="#Remote Procedure Calls">RPC
-calls</A> described elsewhere.&nbsp; The client library also contains its
-own version of <A HREF="../docs/api_c/env_create.html">db_env_create()</A>,
+<p>The client code contains each method function that goes along with the
+<a href="#Remote Procedure Calls">RPC
+calls</a> described elsewhere.&nbsp; The client library also contains its
+own version of <a href="../docs/api_c/env_create.html">db_env_create()</a>,
which does not result in any messages going over to the server (since we
do not yet know what server we are talking to).&nbsp; This function sets
up the pointers to the correct client functions.
-<P>All of the method functions that handle the messaging have a basic flow
+<p>All of the method functions that handle the messaging have a basic flow
similar to this:
-<UL>
-<LI>
-Local arg parsing that may be needed</LI>
+<ul>
+<li>
+Local arg parsing that may be needed</li>
-<LI>
+<li>
Marshalling the message header and the arguments we need to send to the
-server</LI>
+server</li>
-<LI>
-Sending the message</LI>
+<li>
+Sending the message</li>
-<LI>
-Receiving a reply</LI>
+<li>
+Receiving a reply</li>
-<LI>
-Unmarshalling the reply</LI>
+<li>
+Unmarshalling the reply</li>
-<LI>
-Local results processing that may be needed</LI>
-</UL>
+<li>
+Local results processing that may be needed</li>
+</ul>
-<H2>
-Generated Code</H2>
+<h2>
+Generated Code</h2>
Almost all of the code is generated from a source file describing the interface
-and an <I>awk</I> script.&nbsp;&nbsp; This awk script generates six (6)
+and an <i>awk</i> script.&nbsp;&nbsp; This awk script generates six (6)
files for us.&nbsp; It also modifies one.&nbsp; The files are:
-<OL>
-<LI>
-Client file - The C source file created containing the client code.</LI>
+<ol>
+<li>
+Client file - The C source file created containing the client code.</li>
-<LI>
+<li>
Client template file - The C template source file created containing interfaces
for handling client-local issues such as resource allocation, but with
-a consistent interface with the client code generated.</LI>
+a consistent interface with the client code generated.</li>
-<LI>
-Server file - The C source file created containing the server code.</LI>
+<li>
+Server file - The C source file created containing the server code.</li>
-<LI>
+<li>
Server template file - The C template source file created containing interfaces
for handling server-local issues such as resource allocation, calling into
-the DB library but with a consistent interface with the server code generated.</LI>
+the DB library but with a consistent interface with the server code generated.</li>
-<LI>
-XDR file - The XDR message description file created.</LI>
+<li>
+XDR file - The XDR message description file created.</li>
-<LI>
+<li>
Server sed file - A sed script that contains commands to apply to the server
procedure file (i.e. the real source file that the server template file
becomes) so that minor interface changes can be consistently and easily
-applied to the real code.</LI>
+applied to the real code.</li>
-<LI>
+<li>
Server procedure file - This is the file that is modified by the sed script
-generated.&nbsp; It originated from the server template file.</LI>
-</OL>
-The awk script reads a source file, <I>db_server/rpc.src </I>that describes
+generated.&nbsp; It originated from the server template file.</li>
+</ol>
+The awk script reads a source file, <i>db_server/rpc.src </i>that describes
each operation and what sorts of arguments it takes and what it returns
from the server.&nbsp; The syntax of the source file describes the interface
to that operation.&nbsp; There are four (4) parts to the syntax:
-<OL>
-<LI>
-<B>BEGIN</B> <B><I>function version# codetype</I></B> - begins a new functional
-interface for the given <B><I>function</I></B>.&nbsp; Each function has
-a <B><I>version number</I></B>, currently all of them are at version number
-one (1).&nbsp; The <B><I>code type</I></B> indicates to the awk script
-what kind of code to generate.&nbsp; The choices are:</LI>
-
-<UL>
-<LI>
-<B>CODE </B>- Generate all code, and return a status value.&nbsp; If specified,
+<ol>
+<li>
+<b>BEGIN</b> <b><i>function version# codetype</i></b> - begins a new functional
+interface for the given <b><i>function</i></b>.&nbsp; Each function has
+a <b><i>version number</i></b>, currently all of them are at version number
+one (1).&nbsp; The <b><i>code type</i></b> indicates to the awk script
+what kind of code to generate.&nbsp; The choices are:</li>
+
+<ul>
+<li>
+<b>CODE </b>- Generate all code, and return a status value.&nbsp; If specified,
the client code will simply return the status to the user upon completion
-of the RPC call.</LI>
+of the RPC call.</li>
-<LI>
-<B>RETCODE </B>- Generate all code and call a return function in the client
+<li>
+<b>RETCODE </b>- Generate all code and call a return function in the client
template file to deal with client issues or with other returned items.&nbsp;
If specified, the client code generated will call a function of the form
-<I>__dbcl_&lt;name>_ret()
-</I>where
+<i>__dbcl_&lt;name>_ret()
+</i>where
&lt;name> is replaced with the function name given here.&nbsp; This function
is placed in the template file because this indicates that something special
must occur on return.&nbsp; The arguments to this function are the same
as those for the client function, with the addition of the reply message
-structure.</LI>
+structure.</li>
-<LI>
-<B>NOCLNTCODE - </B>Generate XDR and server code, but no corresponding
+<li>
+<b>NOCLNTCODE - </b>Generate XDR and server code, but no corresponding
client code. (This is used for functions that are not named the same thing
on both sides.&nbsp; The only use of this at the moment is db_env_create
and db_create.&nbsp; The environment create call to the server is actually
-called from the <A HREF="../docs/api_c/env_set_server.html">DBENV->set_server()</A>
+called from the <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>
method.&nbsp; The db_create code exists elsewhere in the library and we
-modify that code for the client call.)</LI>
-</UL>
-
-<LI>
-<B>ARG <I>RPC-type C-type varname [list-type]</I></B>- each line of this
-describes an argument to the function.&nbsp; The argument is called <B><I>varname</I></B>.&nbsp;
-The <B><I>C-type</I></B> given is what it should look like in the C code
-generated, such as <B>DB *, u_int32_t, const char *</B>.&nbsp; The
-<B><I>RPC-type</I></B>
+modify that code for the client call.)</li>
+</ul>
+
+<li>
+<b>ARG <i>RPC-type C-type varname [list-type]</i></b>- each line of this
+describes an argument to the function.&nbsp; The argument is called <b><i>varname</i></b>.&nbsp;
+The <b><i>C-type</i></b> given is what it should look like in the C code
+generated, such as <b>DB *, u_int32_t, const char *</b>.&nbsp; The
+<b><i>RPC-type</i></b>
is an indication about how the RPC request message should be constructed.&nbsp;
-The RPC-types allowed are described below.</LI>
+The RPC-types allowed are described below.</li>
-<LI>
-<B>RET <I>RPC-type C-type varname [list-type]</I></B>- each line of this
+<li>
+<b>RET <i>RPC-type C-type varname [list-type]</i></b>- each line of this
describes what the server should return from this procedure call (in addition
to a status, which is always returned and should not be specified).&nbsp;
-The argument is called <B><I>varname</I></B>.&nbsp; The <B><I>C-type</I></B>
-given is what it should look like in the C code generated, such as <B>DB
-*, u_int32_t, const char *</B>.&nbsp; The <B><I>RPC-type</I></B> is an
+The argument is called <b><i>varname</i></b>.&nbsp; The <b><i>C-type</i></b>
+given is what it should look like in the C code generated, such as <b>DB
+*, u_int32_t, const char *</b>.&nbsp; The <b><i>RPC-type</i></b> is an
indication about how the RPC reply message should be constructed.&nbsp;
-The RPC-types are described below.</LI>
-
-<LI>
-<B>END </B>- End the description of this function.&nbsp; The result is
-that when the awk script encounters the <B>END</B> tag, it now has all
-the information it needs to construct the generated code for this function.</LI>
-</OL>
-The <B><I>RPC-type</I></B> must be one of the following:
-<UL>
-<LI>
-<B>IGNORE </B>- This argument is not passed to the server and should be
-ignored when constructing the XDR code.&nbsp; <B>Only allowed for an ARG
-specfication.</B></LI>
-
-<LI>
-<B>STRING</B> - This argument is a string.</LI>
-
-<LI>
-<B>INT </B>- This argument is an integer of some sort.</LI>
-
-<LI>
-<B>DBT </B>- This argument is a DBT, resulting in its decomposition into
-the request message.</LI>
-
-<LI>
-<B>LIST</B> - This argument is an opaque list passed to the server (NULL-terminated).&nbsp;
-If an argument of this type is given, it must have a <B><I>list-type</I></B>
-specified that is one of:</LI>
-
-<UL>
-<LI>
-<B>STRING</B></LI>
-
-<LI>
-<B>INT</B></LI>
-
-<LI>
-<B>ID</B>.</LI>
-</UL>
-
-<LI>
-<B>ID</B> - This argument is an identifier.</LI>
-</UL>
+The RPC-types are described below.</li>
+
+<li>
+<b>END </b>- End the description of this function.&nbsp; The result is
+that when the awk script encounters the <b>END</b> tag, it now has all
+the information it needs to construct the generated code for this function.</li>
+</ol>
+The <b><i>RPC-type</i></b> must be one of the following:
+<ul>
+<li>
+<b>IGNORE </b>- This argument is not passed to the server and should be
+ignored when constructing the XDR code.&nbsp; <b>Only allowed for an ARG
+specfication.</b></li>
+
+<li>
+<b>STRING</b> - This argument is a string.</li>
+
+<li>
+<b>INT </b>- This argument is an integer of some sort.</li>
+
+<li>
+<b>DBT </b>- This argument is a DBT, resulting in its decomposition into
+the request message.</li>
+
+<li>
+<b>LIST</b> - This argument is an opaque list passed to the server (NULL-terminated).&nbsp;
+If an argument of this type is given, it must have a <b><i>list-type</i></b>
+specified that is one of:</li>
+
+<ul>
+<li>
+<b>STRING</b></li>
+
+<li>
+<b>INT</b></li>
+
+<li>
+<b>ID</b>.</li>
+</ul>
+
+<li>
+<b>ID</b> - This argument is an identifier.</li>
+</ul>
So, for example, the source for the DB->join RPC call looks like:
-<PRE>BEGIN&nbsp;&nbsp; dbjoin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RETCODE
+<pre>BEGIN&nbsp;&nbsp; dbjoin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RETCODE
ARG&nbsp;&nbsp;&nbsp;&nbsp; ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DB *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbp&nbsp;
ARG&nbsp;&nbsp;&nbsp;&nbsp; LIST&nbsp;&nbsp;&nbsp; DBC **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curs&nbsp;&nbsp;&nbsp; ID
ARG&nbsp;&nbsp;&nbsp;&nbsp; IGNORE&nbsp; DBC **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbcpp&nbsp;
ARG&nbsp;&nbsp;&nbsp;&nbsp; INT&nbsp;&nbsp;&nbsp;&nbsp; u_int32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags
RET&nbsp;&nbsp;&nbsp;&nbsp; ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbcid
-END</PRE>
+END</pre>
Our first line tells us we are writing the dbjoin function.&nbsp; It requires
special code on the client so we indicate that with the RETCODE.&nbsp;
This method takes four arguments.&nbsp; For the RPC request we need the
@@ -429,17 +429,17 @@ the cursor list, we ignore the argument to return the cursor handle to
the user, and we pass along the flags.&nbsp; On the return, the reply contains
a status, by default, and additionally, it contains the ID of the newly
created cursor.
-<H2>
-Building and Installing</H2>
+<h2>
+Building and Installing</h2>
I need to verify with Don Anderson, but I believe we should just build
the server program, just like we do for db_stat, db_checkpoint, etc.&nbsp;
Basically it can be treated as a utility program from the building and
installation perspective.
-<P>As mentioned early on, in the section on <A HREF="#DB Modifications">DB
-Modifications</A>, we have a single library, but allowing the user to access
-the client portion by sending a flag to <A HREF="../docs/api_c/env_create.html">db_env_create()</A>.&nbsp;
+<p>As mentioned early on, in the section on <a href="#DB Modifications">DB
+Modifications</a>, we have a single library, but allowing the user to access
+the client portion by sending a flag to <a href="../docs/api_c/env_create.html">db_env_create()</a>.&nbsp;
The Makefile is modified to include the new files.
-<P>Testing is performed in two ways.&nbsp; First I have a new example program,
+<p>Testing is performed in two ways.&nbsp; First I have a new example program,
that should become part of the example directory.&nbsp; It is basically
a merging of ex_access.c and ex_env.c.&nbsp; This example is adequate to
test basic functionality, as it does just does database put/get calls and
@@ -449,5 +449,5 @@ I am going to modify the Tcl interface to accept the server information.&nbsp;
Nothing else should need to change in Tcl.&nbsp; Then we can either write
our own test modules or use a subset of the existing ones to test functionality
on a regular basis.
-</BODY>
-</HTML>
+</body>
+</html>
diff --git a/bdb/rpc_server/cxx/db_server_cxxproc.cpp b/bdb/rpc_server/cxx/db_server_cxxproc.cpp
new file mode 100644
index 00000000000..25278273555
--- /dev/null
+++ b/bdb/rpc_server/cxx/db_server_cxxproc.cpp
@@ -0,0 +1,2200 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifdef HAVE_RPC
+#ifndef lint
+static const char revid[] = "$Id: db_server_cxxproc.cpp,v 1.12 2002/08/09 01:56:08 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#endif
+#include "dbinc_auto/db_server.h"
+
+#include "db_int.h"
+#include "db_cxx.h"
+
+extern "C" {
+#include "dbinc/db_server_int.h"
+#include "dbinc_auto/rpc_server_ext.h"
+}
+
+/* BEGIN __env_cachesize_proc */
+extern "C" void
+__env_cachesize_proc(
+ long dbenvcl_id,
+ u_int32_t gbytes,
+ u_int32_t bytes,
+ u_int32_t ncache,
+ __env_cachesize_reply *replyp)
+/* END __env_cachesize_proc */
+{
+ DbEnv *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+ ret = dbenv->set_cachesize(gbytes, bytes, ncache);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_close_proc */
+extern "C" void
+__env_close_proc(
+ long dbenvcl_id,
+ u_int32_t flags,
+ __env_close_reply *replyp)
+/* END __env_close_proc */
+{
+ ct_entry *dbenv_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ replyp->status = __dbenv_close_int(dbenvcl_id, flags, 0);
+ return;
+}
+
+/* BEGIN __env_create_proc */
+extern "C" void
+__env_create_proc(
+ u_int32_t timeout,
+ __env_create_reply *replyp)
+/* END __env_create_proc */
+{
+ DbEnv *dbenv;
+ ct_entry *ctp;
+
+ ctp = new_ct_ent(&replyp->status);
+ if (ctp == NULL)
+ return;
+
+ dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
+ ctp->ct_envp = dbenv;
+ ctp->ct_type = CT_ENV;
+ ctp->ct_parent = NULL;
+ ctp->ct_envparent = ctp;
+ __dbsrv_settimeout(ctp, timeout);
+ __dbsrv_active(ctp);
+ replyp->envcl_id = ctp->ct_id;
+
+ replyp->status = 0;
+ return;
+}
+
+/* BEGIN __env_dbremove_proc */
+extern "C" void
+__env_dbremove_proc(
+ long dbenvcl_id,
+ long txnpcl_id,
+ char *name,
+ char *subdb,
+ u_int32_t flags,
+ __env_dbremove_reply *replyp)
+/* END __env_dbremove_proc */
+{
+ int ret;
+ DbEnv *dbenv;
+ DbTxn *txnp;
+ ct_entry *dbenv_ctp, *txnp_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ ret = dbenv->dbremove(txnp, name, subdb, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_dbrename_proc */
+void
+__env_dbrename_proc(
+ long dbenvcl_id,
+ long txnpcl_id,
+ char *name,
+ char *subdb,
+ char *newname,
+ u_int32_t flags,
+ __env_dbrename_reply *replyp)
+/* END __env_dbrename_proc */
+{
+ int ret;
+ DbEnv *dbenv;
+ DbTxn *txnp;
+ ct_entry *dbenv_ctp, *txnp_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ ret = dbenv->dbrename(txnp, name, subdb, newname, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_encrypt_proc */
+extern "C" void
+__env_encrypt_proc(
+ long dbenvcl_id,
+ char *passwd,
+ u_int32_t flags,
+ __env_encrypt_reply *replyp)
+/* END __env_encrypt_proc */
+{
+ DbEnv *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+ ret = dbenv->set_encrypt(passwd, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_flags_proc */
+extern "C" void
+__env_flags_proc(
+ long dbenvcl_id,
+ u_int32_t flags,
+ u_int32_t onoff,
+ __env_flags_reply *replyp)
+/* END __env_flags_proc */
+{
+ DbEnv *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+ ret = dbenv->set_flags(flags, onoff);
+ if (onoff)
+ dbenv_ctp->ct_envdp.onflags = flags;
+ else
+ dbenv_ctp->ct_envdp.offflags = flags;
+
+ replyp->status = ret;
+ return;
+}
+/* BEGIN __env_open_proc */
+extern "C" void
+__env_open_proc(
+ long dbenvcl_id,
+ char *home,
+ u_int32_t flags,
+ u_int32_t mode,
+ __env_open_reply *replyp)
+/* END __env_open_proc */
+{
+ DbEnv *dbenv;
+ ct_entry *dbenv_ctp, *new_ctp;
+ u_int32_t newflags, shareflags;
+ int ret;
+ home_entry *fullhome;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+ fullhome = get_home(home);
+ if (fullhome == NULL) {
+ ret = DB_NOSERVER_HOME;
+ goto out;
+ }
+
+ /*
+ * If they are using locking do deadlock detection for them,
+ * internally.
+ */
+ if ((flags & DB_INIT_LOCK) &&
+ (ret = dbenv->set_lk_detect(DB_LOCK_DEFAULT)) != 0)
+ goto out;
+
+ if (__dbsrv_verbose) {
+ dbenv->set_errfile(stderr);
+ dbenv->set_errpfx(fullhome->home);
+ }
+
+ /*
+ * Mask off flags we ignore
+ */
+ newflags = (flags & ~DB_SERVER_FLAGMASK);
+ shareflags = (newflags & DB_SERVER_ENVFLAGS);
+ /*
+ * Check now whether we can share a handle for this env.
+ */
+ replyp->envcl_id = dbenvcl_id;
+ if ((new_ctp = __dbsrv_shareenv(dbenv_ctp, fullhome, shareflags))
+ != NULL) {
+ /*
+ * We can share, clean up old ID, set new one.
+ */
+ if (__dbsrv_verbose)
+ printf("Sharing env ID %ld\n", new_ctp->ct_id);
+ replyp->envcl_id = new_ctp->ct_id;
+ ret = __dbenv_close_int(dbenvcl_id, 0, 0);
+ } else {
+ ret = dbenv->open(fullhome->home, newflags, mode);
+ dbenv_ctp->ct_envdp.home = fullhome;
+ dbenv_ctp->ct_envdp.envflags = shareflags;
+ }
+out: replyp->status = ret;
+ return;
+}
+
+/* BEGIN __env_remove_proc */
+extern "C" void
+__env_remove_proc(
+ long dbenvcl_id,
+ char *home,
+ u_int32_t flags,
+ __env_remove_reply *replyp)
+/* END __env_remove_proc */
+{
+ DbEnv *dbenv;
+ ct_entry *dbenv_ctp;
+ int ret;
+ home_entry *fullhome;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+ fullhome = get_home(home);
+ if (fullhome == NULL) {
+ replyp->status = DB_NOSERVER_HOME;
+ return;
+ }
+
+ ret = dbenv->remove(fullhome->home, flags);
+ __dbdel_ctp(dbenv_ctp);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_abort_proc */
+extern "C" void
+__txn_abort_proc(
+ long txnpcl_id,
+ __txn_abort_reply *replyp)
+/* END __txn_abort_proc */
+{
+ DbTxn *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+
+ ret = txnp->abort();
+ __dbdel_ctp(txnp_ctp);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_begin_proc */
+extern "C" void
+__txn_begin_proc(
+ long dbenvcl_id,
+ long parentcl_id,
+ u_int32_t flags,
+ __txn_begin_reply *replyp)
+/* END __txn_begin_proc */
+{
+ DbEnv *dbenv;
+ DbTxn *parent, *txnp;
+ ct_entry *ctp, *dbenv_ctp, *parent_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+ parent_ctp = NULL;
+
+ ctp = new_ct_ent(&replyp->status);
+ if (ctp == NULL)
+ return;
+
+ if (parentcl_id != 0) {
+ ACTIVATE_CTP(parent_ctp, parentcl_id, CT_TXN);
+ parent = (DbTxn *)parent_ctp->ct_anyp;
+ ctp->ct_activep = parent_ctp->ct_activep;
+ } else
+ parent = NULL;
+
+ ret = dbenv->txn_begin(parent, &txnp, flags);
+ if (ret == 0) {
+ ctp->ct_txnp = txnp;
+ ctp->ct_type = CT_TXN;
+ ctp->ct_parent = parent_ctp;
+ ctp->ct_envparent = dbenv_ctp;
+ replyp->txnidcl_id = ctp->ct_id;
+ __dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
+ __dbsrv_active(ctp);
+ } else
+ __dbclear_ctp(ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_commit_proc */
+extern "C" void
+__txn_commit_proc(
+ long txnpcl_id,
+ u_int32_t flags,
+ __txn_commit_reply *replyp)
+/* END __txn_commit_proc */
+{
+ DbTxn *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+
+ ret = txnp->commit(flags);
+ __dbdel_ctp(txnp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_discard_proc */
+extern "C" void
+__txn_discard_proc(
+ long txnpcl_id,
+ u_int32_t flags,
+ __txn_discard_reply *replyp)
+/* END __txn_discard_proc */
+{
+ DbTxn *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+
+ ret = txnp->discard(flags);
+ __dbdel_ctp(txnp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_prepare_proc */
+extern "C" void
+__txn_prepare_proc(
+ long txnpcl_id,
+ u_int8_t *gid,
+ __txn_prepare_reply *replyp)
+/* END __txn_prepare_proc */
+{
+ DbTxn *txnp;
+ ct_entry *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+
+ ret = txnp->prepare(gid);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __txn_recover_proc */
+extern "C" void
+__txn_recover_proc(
+ long dbenvcl_id,
+ u_int32_t count,
+ u_int32_t flags,
+ __txn_recover_reply *replyp,
+ int * freep)
+/* END __txn_recover_proc */
+{
+ DbEnv *dbenv;
+ DbPreplist *dbprep, *p;
+ ct_entry *dbenv_ctp, *ctp;
+ long erri, i, retcount;
+ u_int32_t *txnidp;
+ int ret;
+ char *gid;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+ *freep = 0;
+
+ if ((ret =
+ __os_malloc(dbenv->get_DB_ENV(), count * sizeof(DbPreplist), &dbprep)) != 0)
+ goto out;
+ if ((ret =
+ dbenv->txn_recover(dbprep, count, &retcount, flags)) != 0)
+ goto out;
+ /*
+ * If there is nothing, success, but it's easy.
+ */
+ replyp->retcount = retcount; // TODO: fix C++ txn_recover
+ if (retcount == 0) {
+ replyp->txn.txn_val = NULL;
+ replyp->txn.txn_len = 0;
+ replyp->gid.gid_val = NULL;
+ replyp->gid.gid_len = 0;
+ }
+
+ /*
+ * We have our txn list. Now we need to allocate the space for
+ * the txn ID array and the GID array and set them up.
+ */
+ if ((ret = __os_calloc(dbenv->get_DB_ENV(), retcount, sizeof(u_int32_t),
+ &replyp->txn.txn_val)) != 0)
+ goto out;
+ replyp->txn.txn_len = retcount * sizeof(u_int32_t);
+ if ((ret = __os_calloc(dbenv->get_DB_ENV(), retcount, DB_XIDDATASIZE,
+ &replyp->gid.gid_val)) != 0) {
+ __os_free(dbenv->get_DB_ENV(), replyp->txn.txn_val);
+ goto out;
+ }
+ replyp->gid.gid_len = retcount * DB_XIDDATASIZE;
+
+ /*
+ * Now walk through our results, creating parallel arrays
+ * to send back. For each entry we need to create a new
+ * txn ctp and then fill in the array info.
+ */
+ i = 0;
+ p = dbprep;
+ gid = replyp->gid.gid_val;
+ txnidp = replyp->txn.txn_val;
+ while (i++ < retcount) {
+ ctp = new_ct_ent(&ret);
+ if (ret != 0) {
+ i--;
+ goto out2;
+ }
+ ctp->ct_txnp = p->txn;
+ ctp->ct_type = CT_TXN;
+ ctp->ct_parent = NULL;
+ ctp->ct_envparent = dbenv_ctp;
+ __dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
+ __dbsrv_active(ctp);
+
+ *txnidp = ctp->ct_id;
+ memcpy(gid, p->gid, DB_XIDDATASIZE);
+
+ p++;
+ txnidp++;
+ gid += DB_XIDDATASIZE;
+ }
+ /*
+ * If we get here, we have success and we have to set freep
+ * so it'll get properly freed next time.
+ */
+ *freep = 1;
+out:
+ if (dbprep != NULL)
+ __os_free(dbenv->get_DB_ENV(), dbprep);
+ replyp->status = ret;
+ return;
+out2:
+ /*
+ * We had an error in the middle of creating our new txn
+ * ct entries. We have to unwind all that we have done. Ugh.
+ */
+ for (txnidp = replyp->txn.txn_val, erri = 0;
+ erri < i; erri++, txnidp++) {
+ ctp = get_tableent(*txnidp);
+ __dbclear_ctp(ctp);
+ }
+ __os_free(dbenv->get_DB_ENV(), replyp->txn.txn_val);
+ __os_free(dbenv->get_DB_ENV(), replyp->gid.gid_val);
+ __os_free(dbenv->get_DB_ENV(), dbprep);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_bt_maxkey_proc */
+extern "C" void
+__db_bt_maxkey_proc(
+ long dbpcl_id,
+ u_int32_t maxkey,
+ __db_bt_maxkey_reply *replyp)
+/* END __db_bt_maxkey_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_bt_maxkey(maxkey);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_associate_proc */
+extern "C" void
+__db_associate_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ long sdbpcl_id,
+ u_int32_t flags,
+ __db_associate_reply *replyp)
+/* END __db_associate_proc */
+{
+ Db *dbp, *sdbp;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *sdbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ ACTIVATE_CTP(sdbp_ctp, sdbpcl_id, CT_DB);
+ sdbp = (Db *)sdbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ /*
+ * We do not support DB_CREATE for associate. Users
+ * can only access secondary indices on a read-only basis,
+ * so whatever they are looking for needs to be there already.
+ */
+ if (flags != 0)
+ ret = EINVAL;
+ else
+ ret = dbp->associate(txnp, sdbp, NULL, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_bt_minkey_proc */
+extern "C" void
+__db_bt_minkey_proc(
+ long dbpcl_id,
+ u_int32_t minkey,
+ __db_bt_minkey_reply *replyp)
+/* END __db_bt_minkey_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_bt_minkey(minkey);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_close_proc */
+extern "C" void
+__db_close_proc(
+ long dbpcl_id,
+ u_int32_t flags,
+ __db_close_reply *replyp)
+/* END __db_close_proc */
+{
+ ct_entry *dbp_ctp;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ replyp->status = __db_close_int(dbpcl_id, flags);
+ return;
+}
+
+/* BEGIN __db_create_proc */
+extern "C" void
+__db_create_proc(
+ long dbenvcl_id,
+ u_int32_t flags,
+ __db_create_reply *replyp)
+/* END __db_create_proc */
+{
+ Db *dbp;
+ DbEnv *dbenv;
+ ct_entry *dbenv_ctp, *dbp_ctp;
+
+ ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+ dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+ dbp_ctp = new_ct_ent(&replyp->status);
+ if (dbp_ctp == NULL)
+ return ;
+ /*
+ * We actually require env's for databases. The client should
+ * have caught it, but just in case.
+ */
+ DB_ASSERT(dbenv != NULL);
+ dbp = new Db(dbenv, flags);
+ dbp_ctp->ct_dbp = dbp;
+ dbp_ctp->ct_type = CT_DB;
+ dbp_ctp->ct_parent = dbenv_ctp;
+ dbp_ctp->ct_envparent = dbenv_ctp;
+ replyp->dbcl_id = dbp_ctp->ct_id;
+ replyp->status = 0;
+ return;
+}
+
+/* BEGIN __db_del_proc */
+extern "C" void
+__db_del_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t keydlen,
+ u_int32_t keydoff,
+ u_int32_t keyulen,
+ u_int32_t keyflags,
+ void *keydata,
+ u_int32_t keysize,
+ u_int32_t flags,
+ __db_del_reply *replyp)
+/* END __db_del_proc */
+{
+ Db *dbp;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ /* Set up key */
+ Dbt key(keydata, keysize);
+ key.set_dlen(keydlen);
+ key.set_ulen(keyulen);
+ key.set_doff(keydoff);
+ key.set_flags(keyflags);
+
+ ret = dbp->del(txnp, &key, flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_encrypt_proc */
+extern "C" void
+__db_encrypt_proc(
+ long dbpcl_id,
+ char *passwd,
+ u_int32_t flags,
+ __db_encrypt_reply *replyp)
+/* END __db_encrypt_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_encrypt(passwd, flags);
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_extentsize_proc */
+extern "C" void
+__db_extentsize_proc(
+ long dbpcl_id,
+ u_int32_t extentsize,
+ __db_extentsize_reply *replyp)
+/* END __db_extentsize_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_q_extentsize(extentsize);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_flags_proc */
+extern "C" void
+__db_flags_proc(
+ long dbpcl_id,
+ u_int32_t flags,
+ __db_flags_reply *replyp)
+/* END __db_flags_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_flags(flags);
+ dbp_ctp->ct_dbdp.setflags = flags;
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_get_proc */
+extern "C" void
+__db_get_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t keydlen,
+ u_int32_t keydoff,
+ u_int32_t keyulen,
+ u_int32_t keyflags,
+ void *keydata,
+ u_int32_t keysize,
+ u_int32_t datadlen,
+ u_int32_t datadoff,
+ u_int32_t dataulen,
+ u_int32_t dataflags,
+ void *datadata,
+ u_int32_t datasize,
+ u_int32_t flags,
+ __db_get_reply *replyp,
+ int * freep)
+/* END __db_get_proc */
+{
+ Db *dbp;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int key_alloc, bulk_alloc, ret;
+ void *tmpdata;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ *freep = 0;
+ bulk_alloc = 0;
+
+ /* Set up key and data */
+ Dbt key(keydata, keysize);
+ key.set_dlen(keydlen);
+ key.set_ulen(keyulen);
+ key.set_doff(keydoff);
+ /*
+ * Ignore memory related flags on server.
+ */
+ key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
+
+ Dbt data(datadata, datasize);
+ data.set_dlen(datadlen);
+ data.set_ulen(dataulen);
+ data.set_doff(datadoff);
+ /*
+ * Ignore memory related flags on server.
+ */
+ dataflags &= DB_DBT_PARTIAL;
+ if (flags & DB_MULTIPLE) {
+ if (data.get_data() == 0) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ dataulen, &tmpdata);
+ if (ret != 0)
+ goto err;
+ data.set_data(tmpdata);
+ bulk_alloc = 1;
+ }
+ dataflags |= DB_DBT_USERMEM;
+ } else
+ dataflags |= DB_DBT_MALLOC;
+ data.set_flags(dataflags);
+
+ /* Got all our stuff, now do the get */
+ ret = dbp->get(txnp, &key, &data, flags);
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (key.get_data() == keydata) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ key.get_size(), &replyp->keydata.keydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->get_DB()->dbenv, key.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, data.get_data());
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->keydata.keydata_val, key.get_data(), key.get_size());
+ } else
+ replyp->keydata.keydata_val = (char *)key.get_data();
+
+ replyp->keydata.keydata_len = key.get_size();
+
+ /*
+ * Data
+ */
+ if (data.get_data() == datadata) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ data.get_size(), &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->get_DB()->dbenv, key.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, data.get_data());
+ if (key_alloc)
+ __os_ufree(dbp->get_DB()->dbenv,
+ replyp->keydata.keydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.get_data(),
+ data.get_size());
+ } else
+ replyp->datadata.datadata_val = (char *)data.get_data();
+ replyp->datadata.datadata_len = data.get_size();
+ } else {
+err: replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ if (bulk_alloc)
+ __os_ufree(dbp->get_DB()->dbenv, data.get_data());
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_h_ffactor_proc */
+extern "C" void
+__db_h_ffactor_proc(
+ long dbpcl_id,
+ u_int32_t ffactor,
+ __db_h_ffactor_reply *replyp)
+/* END __db_h_ffactor_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_h_ffactor(ffactor);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_h_nelem_proc */
+extern "C" void
+__db_h_nelem_proc(
+ long dbpcl_id,
+ u_int32_t nelem,
+ __db_h_nelem_reply *replyp)
+/* END __db_h_nelem_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_h_nelem(nelem);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_key_range_proc */
+extern "C" void
+__db_key_range_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t keydlen,
+ u_int32_t keydoff,
+ u_int32_t keyulen,
+ u_int32_t keyflags,
+ void *keydata,
+ u_int32_t keysize,
+ u_int32_t flags,
+ __db_key_range_reply *replyp)
+/* END __db_key_range_proc */
+{
+ Db *dbp;
+ DB_KEY_RANGE range;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ /* Set up key */
+ Dbt key(keydata, keysize);
+ key.set_dlen(keydlen);
+ key.set_ulen(keyulen);
+ key.set_doff(keydoff);
+ key.set_flags(keyflags);
+
+ ret = dbp->key_range(txnp, &key, &range, flags);
+
+ replyp->status = ret;
+ replyp->less = range.less;
+ replyp->equal = range.equal;
+ replyp->greater = range.greater;
+ return;
+}
+
+/* BEGIN __db_lorder_proc */
+extern "C" void
+__db_lorder_proc(
+ long dbpcl_id,
+ u_int32_t lorder,
+ __db_lorder_reply *replyp)
+/* END __db_lorder_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_lorder(lorder);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_open_proc */
+extern "C" void
+__db_open_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ char *name,
+ char *subdb,
+ u_int32_t type,
+ u_int32_t flags,
+ u_int32_t mode,
+ __db_open_reply *replyp)
+/* END __db_open_proc */
+{
+ Db *dbp;
+ DbTxn *txnp;
+ DBTYPE dbtype;
+ ct_entry *dbp_ctp, *new_ctp, *txnp_ctp;
+ int isswapped, ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ replyp->dbcl_id = dbpcl_id;
+ if ((new_ctp = __dbsrv_sharedb(dbp_ctp, name, subdb, (DBTYPE)type, flags))
+ != NULL) {
+ /*
+ * We can share, clean up old ID, set new one.
+ */
+ if (__dbsrv_verbose)
+ printf("Sharing db ID %ld\n", new_ctp->ct_id);
+ replyp->dbcl_id = new_ctp->ct_id;
+ ret = __db_close_int(dbpcl_id, 0);
+ goto out;
+ }
+ ret = dbp->open(txnp, name, subdb, (DBTYPE)type, flags, mode);
+ if (ret == 0) {
+ (void)dbp->get_type(&dbtype);
+ replyp->type = dbtype;
+ /* XXX
+ * Tcl needs to peek at dbp->flags for DB_AM_DUP. Send
+ * this dbp's flags back.
+ */
+ replyp->dbflags = (int) dbp->get_DB()->flags;
+ /*
+ * We need to determine the byte order of the database
+ * and send it back to the client. Determine it by
+ * the server's native order and the swapped value of
+ * the DB itself.
+ */
+ (void)dbp->get_byteswapped(&isswapped);
+ if (__db_byteorder(NULL, 1234) == 0) {
+ if (isswapped == 0)
+ replyp->lorder = 1234;
+ else
+ replyp->lorder = 4321;
+ } else {
+ if (isswapped == 0)
+ replyp->lorder = 4321;
+ else
+ replyp->lorder = 1234;
+ }
+ dbp_ctp->ct_dbdp.type = dbtype;
+ dbp_ctp->ct_dbdp.dbflags = LF_ISSET(DB_SERVER_DBFLAGS);
+ if (name == NULL)
+ dbp_ctp->ct_dbdp.db = NULL;
+ else if ((ret = __os_strdup(dbp->get_DB()->dbenv, name,
+ &dbp_ctp->ct_dbdp.db)) != 0)
+ goto out;
+ if (subdb == NULL)
+ dbp_ctp->ct_dbdp.subdb = NULL;
+ else if ((ret = __os_strdup(dbp->get_DB()->dbenv, subdb,
+ &dbp_ctp->ct_dbdp.subdb)) != 0)
+ goto out;
+ }
+out:
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_pagesize_proc */
+extern "C" void
+__db_pagesize_proc(
+ long dbpcl_id,
+ u_int32_t pagesize,
+ __db_pagesize_reply *replyp)
+/* END __db_pagesize_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_pagesize(pagesize);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_pget_proc */
+extern "C" void
+__db_pget_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t skeydlen,
+ u_int32_t skeydoff,
+ u_int32_t skeyulen,
+ u_int32_t skeyflags,
+ void *skeydata,
+ u_int32_t skeysize,
+ u_int32_t pkeydlen,
+ u_int32_t pkeydoff,
+ u_int32_t pkeyulen,
+ u_int32_t pkeyflags,
+ void *pkeydata,
+ u_int32_t pkeysize,
+ u_int32_t datadlen,
+ u_int32_t datadoff,
+ u_int32_t dataulen,
+ u_int32_t dataflags,
+ void *datadata,
+ u_int32_t datasize,
+ u_int32_t flags,
+ __db_pget_reply *replyp,
+ int * freep)
+/* END __db_pget_proc */
+{
+ Db *dbp;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int key_alloc, ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ *freep = 0;
+
+ /*
+ * Ignore memory related flags on server.
+ */
+ /* Set up key and data */
+ Dbt skey(skeydata, skeysize);
+ skey.set_dlen(skeydlen);
+ skey.set_ulen(skeyulen);
+ skey.set_doff(skeydoff);
+ skey.set_flags(DB_DBT_MALLOC | (skeyflags & DB_DBT_PARTIAL));
+
+ Dbt pkey(pkeydata, pkeysize);
+ pkey.set_dlen(pkeydlen);
+ pkey.set_ulen(pkeyulen);
+ pkey.set_doff(pkeydoff);
+ pkey.set_flags(DB_DBT_MALLOC | (pkeyflags & DB_DBT_PARTIAL));
+
+ Dbt data(datadata, datasize);
+ data.set_dlen(datadlen);
+ data.set_ulen(dataulen);
+ data.set_doff(datadoff);
+ data.set_flags(DB_DBT_MALLOC | (dataflags & DB_DBT_PARTIAL));
+
+ /* Got all our stuff, now do the get */
+ ret = dbp->pget(txnp, &skey, &pkey, &data, flags);
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (skey.get_data() == skeydata) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ skey.get_size(), &replyp->skeydata.skeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->get_DB()->dbenv, skey.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, pkey.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, data.get_data());
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->skeydata.skeydata_val, skey.get_data(),
+ skey.get_size());
+ } else
+ replyp->skeydata.skeydata_val = (char *)skey.get_data();
+
+ replyp->skeydata.skeydata_len = skey.get_size();
+
+ /*
+ * Primary key
+ */
+ if (pkey.get_data() == pkeydata) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ pkey.get_size(), &replyp->pkeydata.pkeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->get_DB()->dbenv, skey.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, pkey.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, data.get_data());
+ if (key_alloc)
+ __os_ufree(dbp->get_DB()->dbenv,
+ replyp->skeydata.skeydata_val);
+ goto err;
+ }
+ /*
+ * We can set it to 2, because they cannot send the
+ * pkey over without sending the skey over too.
+ * So if they did send a pkey, they must have sent
+ * the skey as well.
+ */
+ key_alloc = 2;
+ memcpy(replyp->pkeydata.pkeydata_val, pkey.get_data(),
+ pkey.get_size());
+ } else
+ replyp->pkeydata.pkeydata_val = (char *)pkey.get_data();
+ replyp->pkeydata.pkeydata_len = pkey.get_size();
+
+ /*
+ * Data
+ */
+ if (data.get_data() == datadata) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ data.get_size(), &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->get_DB()->dbenv, skey.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, pkey.get_data());
+ __os_ufree(dbp->get_DB()->dbenv, data.get_data());
+ /*
+ * If key_alloc is 1, just skey needs to be
+ * freed, if key_alloc is 2, both skey and pkey
+ * need to be freed.
+ */
+ if (key_alloc--)
+ __os_ufree(dbp->get_DB()->dbenv,
+ replyp->skeydata.skeydata_val);
+ if (key_alloc)
+ __os_ufree(dbp->get_DB()->dbenv,
+ replyp->pkeydata.pkeydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.get_data(),
+ data.get_size());
+ } else
+ replyp->datadata.datadata_val = (char *)data.get_data();
+ replyp->datadata.datadata_len = data.get_size();
+ } else {
+err: replyp->skeydata.skeydata_val = NULL;
+ replyp->skeydata.skeydata_len = 0;
+ replyp->pkeydata.pkeydata_val = NULL;
+ replyp->pkeydata.pkeydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_put_proc */
+extern "C" void
+__db_put_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t keydlen,
+ u_int32_t keydoff,
+ u_int32_t keyulen,
+ u_int32_t keyflags,
+ void *keydata,
+ u_int32_t keysize,
+ u_int32_t datadlen,
+ u_int32_t datadoff,
+ u_int32_t dataulen,
+ u_int32_t dataflags,
+ void *datadata,
+ u_int32_t datasize,
+ u_int32_t flags,
+ __db_put_reply *replyp,
+ int * freep)
+/* END __db_put_proc */
+{
+ Db *dbp;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ *freep = 0;
+
+ /* Set up key and data */
+ Dbt key(keydata, keysize);
+ key.set_dlen(keydlen);
+ key.set_ulen(keyulen);
+ key.set_doff(keydoff);
+ key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
+
+ Dbt data(datadata, datasize);
+ data.set_dlen(datadlen);
+ data.set_ulen(dataulen);
+ data.set_doff(datadoff);
+ data.set_flags(dataflags);
+
+ /* Got all our stuff, now do the put */
+ ret = dbp->put(txnp, &key, &data, flags);
+ /*
+ * If the client did a DB_APPEND, set up key in reply.
+ * Otherwise just status.
+ */
+ if (ret == 0 && (flags == DB_APPEND)) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ if (key.get_data() == keydata) {
+ ret = __os_umalloc(dbp->get_DB()->dbenv,
+ key.get_size(), &replyp->keydata.keydata_val);
+ if (ret != 0) {
+ __os_ufree(dbp->get_DB()->dbenv, key.get_data());
+ goto err;
+ }
+ memcpy(replyp->keydata.keydata_val, key.get_data(), key.get_size());
+ } else
+ replyp->keydata.keydata_val = (char *)key.get_data();
+
+ replyp->keydata.keydata_len = key.get_size();
+ } else {
+err: replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ *freep = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_re_delim_proc */
+extern "C" void
+__db_re_delim_proc(
+ long dbpcl_id,
+ u_int32_t delim,
+ __db_re_delim_reply *replyp)
+/* END __db_re_delim_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_re_delim(delim);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_re_len_proc */
+extern "C" void
+__db_re_len_proc(
+ long dbpcl_id,
+ u_int32_t len,
+ __db_re_len_reply *replyp)
+/* END __db_re_len_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_re_len(len);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_re_pad_proc */
+extern "C" void
+__db_re_pad_proc(
+ long dbpcl_id,
+ u_int32_t pad,
+ __db_re_pad_reply *replyp)
+/* END __db_re_pad_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->set_re_pad(pad);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_remove_proc */
+extern "C" void
+__db_remove_proc(
+ long dbpcl_id,
+ char *name,
+ char *subdb,
+ u_int32_t flags,
+ __db_remove_reply *replyp)
+/* END __db_remove_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->remove(name, subdb, flags);
+ __dbdel_ctp(dbp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_rename_proc */
+extern "C" void
+__db_rename_proc(
+ long dbpcl_id,
+ char *name,
+ char *subdb,
+ char *newname,
+ u_int32_t flags,
+ __db_rename_reply *replyp)
+/* END __db_rename_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->rename(name, subdb, newname, flags);
+ __dbdel_ctp(dbp_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_stat_proc */
+extern "C" void
+__db_stat_proc(
+ long dbpcl_id,
+ u_int32_t flags,
+ __db_stat_reply *replyp,
+ int * freep)
+/* END __db_stat_proc */
+{
+ Db *dbp;
+ DBTYPE type;
+ ct_entry *dbp_ctp;
+ u_int32_t *q, *p, *retsp;
+ int i, len, ret;
+ void *sp;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->stat(&sp, flags);
+ replyp->status = ret;
+ if (ret != 0)
+ return;
+ /*
+ * We get here, we have success. Allocate an array so that
+ * we can use the list generator. Generate the reply, free
+ * up the space.
+ */
+ /*
+ * XXX This assumes that all elements of all stat structures
+ * are u_int32_t fields. They are, currently.
+ */
+ (void)dbp->get_type(&type);
+ if (type == DB_HASH)
+ len = sizeof(DB_HASH_STAT);
+ else if (type == DB_QUEUE)
+ len = sizeof(DB_QUEUE_STAT);
+ else /* BTREE or RECNO are same stats */
+ len = sizeof(DB_BTREE_STAT);
+ replyp->stats.stats_len = len / sizeof(u_int32_t);
+
+ if ((ret = __os_umalloc(dbp->get_DB()->dbenv,
+ len * replyp->stats.stats_len, &retsp)) != 0)
+ goto out;
+ for (i = 0, q = retsp, p = (u_int32_t *)sp; i < len;
+ i++, q++, p++)
+ *q = *p;
+ replyp->stats.stats_val = retsp;
+ __os_ufree(dbp->get_DB()->dbenv, sp);
+ if (ret == 0)
+ *freep = 1;
+out:
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_sync_proc */
+extern "C" void
+__db_sync_proc(
+ long dbpcl_id,
+ u_int32_t flags,
+ __db_sync_reply *replyp)
+/* END __db_sync_proc */
+{
+ Db *dbp;
+ ct_entry *dbp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ ret = dbp->sync(flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_truncate_proc */
+extern "C" void
+__db_truncate_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t flags,
+ __db_truncate_reply *replyp)
+/* END __db_truncate_proc */
+{
+ Db *dbp;
+ DbTxn *txnp;
+ ct_entry *dbp_ctp, *txnp_ctp;
+ u_int32_t count;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ } else
+ txnp = NULL;
+
+ ret = dbp->truncate(txnp, &count, flags);
+ replyp->status = ret;
+ if (ret == 0)
+ replyp->count = count;
+ return;
+}
+
+/* BEGIN __db_cursor_proc */
+extern "C" void
+__db_cursor_proc(
+ long dbpcl_id,
+ long txnpcl_id,
+ u_int32_t flags,
+ __db_cursor_reply *replyp)
+/* END __db_cursor_proc */
+{
+ Db *dbp;
+ Dbc *dbc;
+ DbTxn *txnp;
+ ct_entry *dbc_ctp, *env_ctp, *dbp_ctp, *txnp_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+ dbc_ctp = new_ct_ent(&replyp->status);
+ if (dbc_ctp == NULL)
+ return;
+
+ if (txnpcl_id != 0) {
+ ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+ txnp = (DbTxn *)txnp_ctp->ct_anyp;
+ dbc_ctp->ct_activep = txnp_ctp->ct_activep;
+ } else
+ txnp = NULL;
+
+ if ((ret = dbp->cursor(txnp, &dbc, flags)) == 0) {
+ dbc_ctp->ct_dbc = dbc;
+ dbc_ctp->ct_type = CT_CURSOR;
+ dbc_ctp->ct_parent = dbp_ctp;
+ env_ctp = dbp_ctp->ct_envparent;
+ dbc_ctp->ct_envparent = env_ctp;
+ __dbsrv_settimeout(dbc_ctp, env_ctp->ct_timeout);
+ __dbsrv_active(dbc_ctp);
+ replyp->dbcidcl_id = dbc_ctp->ct_id;
+ } else
+ __dbclear_ctp(dbc_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __db_join_proc */
+extern "C" void
+__db_join_proc(
+ long dbpcl_id,
+ u_int32_t *curs,
+ u_int32_t curslen,
+ u_int32_t flags,
+ __db_join_reply *replyp)
+/* END __db_join_proc */
+{
+ Db *dbp;
+ Dbc **jcurs, **c;
+ Dbc *dbc;
+ ct_entry *dbc_ctp, *ctp, *dbp_ctp;
+ size_t size;
+ u_int32_t *cl, i;
+ int ret;
+
+ ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+ dbp = (Db *)dbp_ctp->ct_anyp;
+
+ dbc_ctp = new_ct_ent(&replyp->status);
+ if (dbc_ctp == NULL)
+ return;
+
+ size = (curslen + 1) * sizeof(Dbc *);
+ if ((ret = __os_calloc(dbp->get_DB()->dbenv,
+ curslen + 1, sizeof(Dbc *), &jcurs)) != 0) {
+ replyp->status = ret;
+ __dbclear_ctp(dbc_ctp);
+ return;
+ }
+ /*
+ * If our curslist has a parent txn, we need to use it too
+ * for the activity timeout. All cursors must be part of
+ * the same transaction, so just check the first.
+ */
+ ctp = get_tableent(*curs);
+ DB_ASSERT(ctp->ct_type == CT_CURSOR);
+ /*
+ * If we are using a transaction, set the join activity timer
+ * to point to the parent transaction.
+ */
+ if (ctp->ct_activep != &ctp->ct_active)
+ dbc_ctp->ct_activep = ctp->ct_activep;
+ for (i = 0, cl = curs, c = jcurs; i < curslen; i++, cl++, c++) {
+ ctp = get_tableent(*cl);
+ if (ctp == NULL) {
+ replyp->status = DB_NOSERVER_ID;
+ goto out;
+ }
+ /*
+ * If we are using a txn, the join cursor points to the
+ * transaction timeout. If we are not using a transaction,
+ * then all the curslist cursors must point to the join
+ * cursor's timeout so that we do not timeout any of the
+ * curlist cursors while the join cursor is active.
+ * Change the type of the curslist ctps to CT_JOIN so that
+ * we know they are part of a join list and we can distinguish
+ * them and later restore them when the join cursor is closed.
+ */
+ DB_ASSERT(ctp->ct_type == CT_CURSOR);
+ ctp->ct_type |= CT_JOIN;
+ ctp->ct_origp = ctp->ct_activep;
+ /*
+ * Setting this to the ct_active field of the dbc_ctp is
+ * really just a way to distinguish which join dbc this
+ * cursor is part of. The ct_activep of this cursor is
+ * not used at all during its lifetime as part of a join
+ * cursor.
+ */
+ ctp->ct_activep = &dbc_ctp->ct_active;
+ *c = ctp->ct_dbc;
+ }
+ *c = NULL;
+ if ((ret = dbp->join(jcurs, &dbc, flags)) == 0) {
+ dbc_ctp->ct_dbc = dbc;
+ dbc_ctp->ct_type = (CT_JOINCUR | CT_CURSOR);
+ dbc_ctp->ct_parent = dbp_ctp;
+ dbc_ctp->ct_envparent = dbp_ctp->ct_envparent;
+ __dbsrv_settimeout(dbc_ctp, dbp_ctp->ct_envparent->ct_timeout);
+ __dbsrv_active(dbc_ctp);
+ replyp->dbcidcl_id = dbc_ctp->ct_id;
+ } else {
+ __dbclear_ctp(dbc_ctp);
+ /*
+ * If we get an error, undo what we did above to any cursors.
+ */
+ for (cl = curs; *cl != 0; cl++) {
+ ctp = get_tableent(*cl);
+ ctp->ct_type = CT_CURSOR;
+ ctp->ct_activep = ctp->ct_origp;
+ }
+ }
+
+ replyp->status = ret;
+out:
+ __os_free(dbp->get_DB()->dbenv, jcurs);
+ return;
+}
+
+/* BEGIN __dbc_close_proc */
+extern "C" void
+__dbc_close_proc(
+ long dbccl_id,
+ __dbc_close_reply *replyp)
+/* END __dbc_close_proc */
+{
+ ct_entry *dbc_ctp;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ replyp->status = __dbc_close_int(dbc_ctp);
+ return;
+}
+
+/* BEGIN __dbc_count_proc */
+extern "C" void
+__dbc_count_proc(
+ long dbccl_id,
+ u_int32_t flags,
+ __dbc_count_reply *replyp)
+/* END __dbc_count_proc */
+{
+ Dbc *dbc;
+ ct_entry *dbc_ctp;
+ db_recno_t num;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+
+ ret = dbc->count(&num, flags);
+ replyp->status = ret;
+ if (ret == 0)
+ replyp->dupcount = num;
+ return;
+}
+
+/* BEGIN __dbc_del_proc */
+extern "C" void
+__dbc_del_proc(
+ long dbccl_id,
+ u_int32_t flags,
+ __dbc_del_reply *replyp)
+/* END __dbc_del_proc */
+{
+ Dbc *dbc;
+ ct_entry *dbc_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+
+ ret = dbc->del(flags);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_dup_proc */
+extern "C" void
+__dbc_dup_proc(
+ long dbccl_id,
+ u_int32_t flags,
+ __dbc_dup_reply *replyp)
+/* END __dbc_dup_proc */
+{
+ Dbc *dbc, *newdbc;
+ ct_entry *dbc_ctp, *new_ctp;
+ int ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+
+ new_ctp = new_ct_ent(&replyp->status);
+ if (new_ctp == NULL)
+ return;
+
+ if ((ret = dbc->dup(&newdbc, flags)) == 0) {
+ new_ctp->ct_dbc = newdbc;
+ new_ctp->ct_type = CT_CURSOR;
+ new_ctp->ct_parent = dbc_ctp->ct_parent;
+ new_ctp->ct_envparent = dbc_ctp->ct_envparent;
+ /*
+ * If our cursor has a parent txn, we need to use it too.
+ */
+ if (dbc_ctp->ct_activep != &dbc_ctp->ct_active)
+ new_ctp->ct_activep = dbc_ctp->ct_activep;
+ __dbsrv_settimeout(new_ctp, dbc_ctp->ct_timeout);
+ __dbsrv_active(new_ctp);
+ replyp->dbcidcl_id = new_ctp->ct_id;
+ } else
+ __dbclear_ctp(new_ctp);
+
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_get_proc */
+extern "C" void
+__dbc_get_proc(
+ long dbccl_id,
+ u_int32_t keydlen,
+ u_int32_t keydoff,
+ u_int32_t keyulen,
+ u_int32_t keyflags,
+ void *keydata,
+ u_int32_t keysize,
+ u_int32_t datadlen,
+ u_int32_t datadoff,
+ u_int32_t dataulen,
+ u_int32_t dataflags,
+ void *datadata,
+ u_int32_t datasize,
+ u_int32_t flags,
+ __dbc_get_reply *replyp,
+ int * freep)
+/* END __dbc_get_proc */
+{
+ Dbc *dbc;
+ DbEnv *dbenv;
+ ct_entry *dbc_ctp;
+ int key_alloc, bulk_alloc, ret;
+ void *tmpdata;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+ dbenv = DbEnv::get_DbEnv(((DBC *)dbc)->dbp->dbenv);
+
+ *freep = 0;
+ bulk_alloc = 0;
+
+ /* Set up key and data */
+ Dbt key(keydata, keysize);
+ key.set_dlen(keydlen);
+ key.set_ulen(keyulen);
+ key.set_doff(keydoff);
+ key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
+
+ Dbt data(datadata, datasize);
+ data.set_dlen(datadlen);
+ data.set_ulen(dataulen);
+ data.set_doff(datadoff);
+ dataflags &= DB_DBT_PARTIAL;
+ if (flags & DB_MULTIPLE || flags & DB_MULTIPLE_KEY) {
+ if (data.get_data() == NULL) {
+ ret = __os_umalloc(dbenv->get_DB_ENV(),
+ data.get_ulen(), &tmpdata);
+ if (ret != 0)
+ goto err;
+ data.set_data(tmpdata);
+ bulk_alloc = 1;
+ }
+ dataflags |= DB_DBT_USERMEM;
+ } else
+ dataflags |= DB_DBT_MALLOC;
+ data.set_flags(dataflags);
+
+ /* Got all our stuff, now do the get */
+ ret = dbc->get(&key, &data, flags);
+
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (key.get_data() == keydata) {
+ ret = __os_umalloc(dbenv->get_DB_ENV(), key.get_size(),
+ &replyp->keydata.keydata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv->get_DB_ENV(), key.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), data.get_data());
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->keydata.keydata_val, key.get_data(), key.get_size());
+ } else
+ replyp->keydata.keydata_val = (char *)key.get_data();
+
+ replyp->keydata.keydata_len = key.get_size();
+
+ /*
+ * Data
+ */
+ if (data.get_data() == datadata) {
+ ret = __os_umalloc(dbenv->get_DB_ENV(), data.get_size(),
+ &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv->get_DB_ENV(), key.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), data.get_data());
+ if (key_alloc)
+ __os_ufree(dbenv->get_DB_ENV(),
+ replyp->keydata.keydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.get_data(),
+ data.get_size());
+ } else
+ replyp->datadata.datadata_val = (char *)data.get_data();
+ replyp->datadata.datadata_len = data.get_size();
+ } else {
+err: replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ if (bulk_alloc)
+ __os_ufree(dbenv->get_DB_ENV(), data.get_data());
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_pget_proc */
+extern "C" void
+__dbc_pget_proc(
+ long dbccl_id,
+ u_int32_t skeydlen,
+ u_int32_t skeydoff,
+ u_int32_t skeyulen,
+ u_int32_t skeyflags,
+ void *skeydata,
+ u_int32_t skeysize,
+ u_int32_t pkeydlen,
+ u_int32_t pkeydoff,
+ u_int32_t pkeyulen,
+ u_int32_t pkeyflags,
+ void *pkeydata,
+ u_int32_t pkeysize,
+ u_int32_t datadlen,
+ u_int32_t datadoff,
+ u_int32_t dataulen,
+ u_int32_t dataflags,
+ void *datadata,
+ u_int32_t datasize,
+ u_int32_t flags,
+ __dbc_pget_reply *replyp,
+ int * freep)
+/* END __dbc_pget_proc */
+{
+ Dbc *dbc;
+ DbEnv *dbenv;
+ ct_entry *dbc_ctp;
+ int key_alloc, ret;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+ dbenv = DbEnv::get_DbEnv(((DBC *)dbc)->dbp->dbenv);
+
+ *freep = 0;
+
+ /*
+ * Ignore memory related flags on server.
+ */
+ /* Set up key and data */
+ Dbt skey(skeydata, skeysize);
+ skey.set_dlen(skeydlen);
+ skey.set_ulen(skeyulen);
+ skey.set_doff(skeydoff);
+ skey.set_flags(DB_DBT_MALLOC | (skeyflags & DB_DBT_PARTIAL));
+
+ Dbt pkey(pkeydata, pkeysize);
+ pkey.set_dlen(pkeydlen);
+ pkey.set_ulen(pkeyulen);
+ pkey.set_doff(pkeydoff);
+ pkey.set_flags(DB_DBT_MALLOC | (pkeyflags & DB_DBT_PARTIAL));
+
+ Dbt data(datadata, datasize);
+ data.set_dlen(datadlen);
+ data.set_ulen(dataulen);
+ data.set_doff(datadoff);
+ data.set_flags(DB_DBT_MALLOC | (dataflags & DB_DBT_PARTIAL));
+
+ /* Got all our stuff, now do the get */
+ ret = dbc->pget(&skey, &pkey, &data, flags);
+ /*
+ * Otherwise just status.
+ */
+ if (ret == 0) {
+ /*
+ * XXX
+ * We need to xdr_free whatever we are returning, next time.
+ * However, DB does not allocate a new key if one was given
+ * and we'd be free'ing up space allocated in the request.
+ * So, allocate a new key/data pointer if it is the same one
+ * as in the request.
+ */
+ *freep = 1;
+ /*
+ * Key
+ */
+ key_alloc = 0;
+ if (skey.get_data() == skeydata) {
+ ret = __os_umalloc(dbenv->get_DB_ENV(),
+ skey.get_size(), &replyp->skeydata.skeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv->get_DB_ENV(), skey.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), pkey.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), data.get_data());
+ goto err;
+ }
+ key_alloc = 1;
+ memcpy(replyp->skeydata.skeydata_val, skey.get_data(),
+ skey.get_size());
+ } else
+ replyp->skeydata.skeydata_val = (char *)skey.get_data();
+ replyp->skeydata.skeydata_len = skey.get_size();
+
+ /*
+ * Primary key
+ */
+ if (pkey.get_data() == pkeydata) {
+ ret = __os_umalloc(dbenv->get_DB_ENV(),
+ pkey.get_size(), &replyp->pkeydata.pkeydata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv->get_DB_ENV(), skey.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), pkey.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), data.get_data());
+ if (key_alloc)
+ __os_ufree(dbenv->get_DB_ENV(),
+ replyp->skeydata.skeydata_val);
+ goto err;
+ }
+ /*
+ * We can set it to 2, because they cannot send the
+ * pkey over without sending the skey over too.
+ * So if they did send a pkey, they must have sent
+ * the skey as well.
+ */
+ key_alloc = 2;
+ memcpy(replyp->pkeydata.pkeydata_val, pkey.get_data(),
+ pkey.get_size());
+ } else
+ replyp->pkeydata.pkeydata_val = (char *)pkey.get_data();
+ replyp->pkeydata.pkeydata_len = pkey.get_size();
+
+ /*
+ * Data
+ */
+ if (data.get_data() == datadata) {
+ ret = __os_umalloc(dbenv->get_DB_ENV(),
+ data.get_size(), &replyp->datadata.datadata_val);
+ if (ret != 0) {
+ __os_ufree(dbenv->get_DB_ENV(), skey.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), pkey.get_data());
+ __os_ufree(dbenv->get_DB_ENV(), data.get_data());
+ /*
+ * If key_alloc is 1, just skey needs to be
+ * freed, if key_alloc is 2, both skey and pkey
+ * need to be freed.
+ */
+ if (key_alloc--)
+ __os_ufree(dbenv->get_DB_ENV(),
+ replyp->skeydata.skeydata_val);
+ if (key_alloc)
+ __os_ufree(dbenv->get_DB_ENV(),
+ replyp->pkeydata.pkeydata_val);
+ goto err;
+ }
+ memcpy(replyp->datadata.datadata_val, data.get_data(),
+ data.get_size());
+ } else
+ replyp->datadata.datadata_val = (char *)data.get_data();
+ replyp->datadata.datadata_len = data.get_size();
+ } else {
+err: replyp->skeydata.skeydata_val = NULL;
+ replyp->skeydata.skeydata_len = 0;
+ replyp->pkeydata.pkeydata_val = NULL;
+ replyp->pkeydata.pkeydata_len = 0;
+ replyp->datadata.datadata_val = NULL;
+ replyp->datadata.datadata_len = 0;
+ *freep = 0;
+ }
+ replyp->status = ret;
+ return;
+}
+
+/* BEGIN __dbc_put_proc */
+extern "C" void
+__dbc_put_proc(
+ long dbccl_id,
+ u_int32_t keydlen,
+ u_int32_t keydoff,
+ u_int32_t keyulen,
+ u_int32_t keyflags,
+ void *keydata,
+ u_int32_t keysize,
+ u_int32_t datadlen,
+ u_int32_t datadoff,
+ u_int32_t dataulen,
+ u_int32_t dataflags,
+ void *datadata,
+ u_int32_t datasize,
+ u_int32_t flags,
+ __dbc_put_reply *replyp,
+ int * freep)
+/* END __dbc_put_proc */
+{
+ Db *dbp;
+ Dbc *dbc;
+ ct_entry *dbc_ctp;
+ int ret;
+ DBTYPE dbtype;
+
+ ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+ dbp = (Db *)dbc_ctp->ct_parent->ct_anyp;
+
+ /* Set up key and data */
+ Dbt key(keydata, keysize);
+ key.set_dlen(keydlen);
+ key.set_ulen(keyulen);
+ key.set_doff(keydoff);
+ /*
+ * Ignore memory related flags on server.
+ */
+ key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
+
+ Dbt data(datadata, datasize);
+ data.set_dlen(datadlen);
+ data.set_ulen(dataulen);
+ data.set_doff(datadoff);
+ data.set_flags(dataflags);
+
+ /* Got all our stuff, now do the put */
+ ret = dbc->put(&key, &data, flags);
+
+ *freep = 0;
+ replyp->keydata.keydata_val = NULL;
+ replyp->keydata.keydata_len = 0;
+ if (ret == 0 && (flags == DB_AFTER || flags == DB_BEFORE)) {
+ ret = dbp->get_type(&dbtype);
+ if (ret == 0 && dbtype == DB_RECNO) {
+ /*
+ * We need to xdr_free whatever we are returning, next time.
+ */
+ replyp->keydata.keydata_val = (char *)key.get_data();
+ replyp->keydata.keydata_len = key.get_size();
+ }
+ }
+ replyp->status = ret;
+ return;
+}
+#endif /* HAVE_RPC */
diff --git a/bdb/rpc_server/cxx/db_server_cxxutil.cpp b/bdb/rpc_server/cxx/db_server_cxxutil.cpp
new file mode 100644
index 00000000000..60865264c00
--- /dev/null
+++ b/bdb/rpc_server/cxx/db_server_cxxutil.cpp
@@ -0,0 +1,746 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: db_server_cxxutil.cpp,v 1.8 2002/05/23 07:49:34 mjc Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <rpc/rpc.h>
+
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+#include "dbinc_auto/db_server.h"
+
+#include "db_int.h"
+#include "db_cxx.h"
+#include "dbinc_auto/clib_ext.h"
+
+extern "C" {
+#include "dbinc/db_server_int.h"
+#include "dbinc_auto/rpc_server_ext.h"
+#include "dbinc_auto/common_ext.h"
+
+extern int __dbsrv_main __P((void));
+}
+
+static int add_home __P((char *));
+static int add_passwd __P((char *));
+static int env_recover __P((char *));
+static void __dbclear_child __P((ct_entry *));
+
+static LIST_HEAD(cthead, ct_entry) __dbsrv_head;
+static LIST_HEAD(homehead, home_entry) __dbsrv_home;
+static long __dbsrv_defto = DB_SERVER_TIMEOUT;
+static long __dbsrv_maxto = DB_SERVER_MAXTIMEOUT;
+static long __dbsrv_idleto = DB_SERVER_IDLETIMEOUT;
+static char *logfile = NULL;
+static char *prog;
+
+static void usage __P((char *));
+static void version_check __P((void));
+
+int __dbsrv_verbose = 0;
+
+int
+main(
+ int argc,
+ char **argv)
+{
+ extern char *optarg;
+ CLIENT *cl;
+ int ch, ret;
+ char *passwd;
+
+ prog = argv[0];
+
+ version_check();
+
+ /*
+ * Check whether another server is running or not. There
+ * is a race condition where two servers could be racing to
+ * register with the portmapper. The goal of this check is to
+ * forbid running additional servers (like those started from
+ * the test suite) if the user is already running one.
+ *
+ * XXX
+ * This does not solve nor prevent two servers from being
+ * started at the same time and running recovery at the same
+ * time on the same environments.
+ */
+ if ((cl = clnt_create("localhost",
+ DB_RPC_SERVERPROG, DB_RPC_SERVERVERS, "tcp")) != NULL) {
+ fprintf(stderr,
+ "%s: Berkeley DB RPC server already running.\n", prog);
+ clnt_destroy(cl);
+ return (EXIT_FAILURE);
+ }
+
+ LIST_INIT(&__dbsrv_home);
+ while ((ch = getopt(argc, argv, "h:I:L:P:t:T:Vv")) != EOF)
+ switch (ch) {
+ case 'h':
+ (void)add_home(optarg);
+ break;
+ case 'I':
+ if (__db_getlong(NULL, prog,
+ optarg, 1, LONG_MAX, &__dbsrv_idleto))
+ return (EXIT_FAILURE);
+ break;
+ case 'L':
+ logfile = optarg;
+ break;
+ case 'P':
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ prog, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ if ((ret = add_passwd(passwd)) != 0) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ prog, strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ break;
+ case 't':
+ if (__db_getlong(NULL, prog,
+ optarg, 1, LONG_MAX, &__dbsrv_defto))
+ return (EXIT_FAILURE);
+ break;
+ case 'T':
+ if (__db_getlong(NULL, prog,
+ optarg, 1, LONG_MAX, &__dbsrv_maxto))
+ return (EXIT_FAILURE);
+ break;
+ case 'V':
+ printf("%s\n", db_version(NULL, NULL, NULL));
+ return (EXIT_SUCCESS);
+ case 'v':
+ __dbsrv_verbose = 1;
+ break;
+ default:
+ usage(prog);
+ }
+ /*
+ * Check default timeout against maximum timeout
+ */
+ if (__dbsrv_defto > __dbsrv_maxto)
+ __dbsrv_defto = __dbsrv_maxto;
+
+ /*
+ * Check default timeout against idle timeout
+ * It would be bad to timeout environments sooner than txns.
+ */
+ if (__dbsrv_defto > __dbsrv_idleto)
+ fprintf(stderr,
+ "%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
+ prog, __dbsrv_idleto, __dbsrv_defto);
+
+ LIST_INIT(&__dbsrv_head);
+
+ /*
+ * If a client crashes during an RPC, our reply to it
+ * generates a SIGPIPE. Ignore SIGPIPE so we don't exit unnecessarily.
+ */
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ if (logfile != NULL && __db_util_logset("berkeley_db_svc", logfile))
+ return (EXIT_FAILURE);
+
+ /*
+ * Now that we are ready to start, run recovery on all the
+ * environments specified.
+ */
+ if (env_recover(prog) != 0)
+ return (EXIT_FAILURE);
+
+ /*
+ * We've done our setup, now call the generated server loop
+ */
+ if (__dbsrv_verbose)
+ printf("%s: Ready to receive requests\n", prog);
+ __dbsrv_main();
+
+ /* NOTREACHED */
+ abort();
+}
+
+static void
+usage(char *prog)
+{
+ fprintf(stderr, "usage: %s %s\n\t%s\n", prog,
+ "[-Vv] [-h home] [-P passwd]",
+ "[-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
+ exit(EXIT_FAILURE);
+}
+
+static void
+version_check()
+{
+ int v_major, v_minor, v_patch;
+
+ /* Make sure we're loaded with the right version of the DB library. */
+ (void)db_version(&v_major, &v_minor, &v_patch);
+ if (v_major != DB_VERSION_MAJOR ||
+ v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+ fprintf(stderr,
+ "%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+ prog, DB_VERSION_MAJOR, DB_VERSION_MINOR,
+ DB_VERSION_PATCH, v_major, v_minor, v_patch);
+ exit(EXIT_FAILURE);
+ }
+}
+
+extern "C" void
+__dbsrv_settimeout(
+ ct_entry *ctp,
+ u_int32_t to)
+{
+ if (to > (u_int32_t)__dbsrv_maxto)
+ ctp->ct_timeout = __dbsrv_maxto;
+ else if (to <= 0)
+ ctp->ct_timeout = __dbsrv_defto;
+ else
+ ctp->ct_timeout = to;
+}
+
+extern "C" void
+__dbsrv_timeout(int force)
+{
+ static long to_hint = -1;
+ time_t t;
+ long to;
+ ct_entry *ctp, *nextctp;
+
+ if ((t = time(NULL)) == -1)
+ return;
+
+ /*
+ * Check hint. If hint is further in the future
+ * than now, no work to do.
+ */
+ if (!force && to_hint > 0 && t < to_hint)
+ return;
+ to_hint = -1;
+ /*
+ * Timeout transactions or cursors holding DB resources.
+ * Do this before timing out envs to properly release resources.
+ *
+ * !!!
+ * We can just loop through this list looking for cursors and txns.
+ * We do not need to verify txn and cursor relationships at this
+ * point because we maintain the list in LIFO order *and* we
+ * maintain activity in the ultimate txn parent of any cursor
+ * so either everything in a txn is timing out, or nothing.
+ * So, since we are LIFO, we will correctly close/abort all the
+ * appropriate handles, in the correct order.
+ */
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
+ nextctp = LIST_NEXT(ctp, entries);
+ switch (ctp->ct_type) {
+ case CT_TXN:
+ to = *(ctp->ct_activep) + ctp->ct_timeout;
+ /* TIMEOUT */
+ if (to < t) {
+ if (__dbsrv_verbose)
+ printf("Timing out txn id %ld\n",
+ ctp->ct_id);
+ (void)((DbTxn *)ctp->ct_anyp)->abort();
+ __dbdel_ctp(ctp);
+ /*
+ * If we timed out an txn, we may have closed
+ * all sorts of ctp's.
+ * So start over with a guaranteed good ctp.
+ */
+ nextctp = LIST_FIRST(&__dbsrv_head);
+ } else if ((to_hint > 0 && to_hint > to) ||
+ to_hint == -1)
+ to_hint = to;
+ break;
+ case CT_CURSOR:
+ case (CT_JOINCUR | CT_CURSOR):
+ to = *(ctp->ct_activep) + ctp->ct_timeout;
+ /* TIMEOUT */
+ if (to < t) {
+ if (__dbsrv_verbose)
+ printf("Timing out cursor %ld\n",
+ ctp->ct_id);
+ (void)__dbc_close_int(ctp);
+ /*
+ * Start over with a guaranteed good ctp.
+ */
+ nextctp = LIST_FIRST(&__dbsrv_head);
+ } else if ((to_hint > 0 && to_hint > to) ||
+ to_hint == -1)
+ to_hint = to;
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * Timeout idle handles.
+ * If we are forcing a timeout, we'll close all env handles.
+ */
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
+ nextctp = LIST_NEXT(ctp, entries);
+ if (ctp->ct_type != CT_ENV)
+ continue;
+ to = *(ctp->ct_activep) + ctp->ct_idle;
+ /* TIMEOUT */
+ if (to < t || force) {
+ if (__dbsrv_verbose)
+ printf("Timing out env id %ld\n", ctp->ct_id);
+ (void)__dbenv_close_int(ctp->ct_id, 0, 1);
+ /*
+ * If we timed out an env, we may have closed
+ * all sorts of ctp's (maybe even all of them.
+ * So start over with a guaranteed good ctp.
+ */
+ nextctp = LIST_FIRST(&__dbsrv_head);
+ }
+ }
+}
+
+/*
+ * RECURSIVE FUNCTION. We need to clear/free any number of levels of nested
+ * layers.
+ */
+static void
+__dbclear_child(ct_entry *parent)
+{
+ ct_entry *ctp, *nextctp;
+
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = nextctp) {
+ nextctp = LIST_NEXT(ctp, entries);
+ if (ctp->ct_type == 0)
+ continue;
+ if (ctp->ct_parent == parent) {
+ __dbclear_child(ctp);
+ /*
+ * Need to do this here because le_next may
+ * have changed with the recursive call and we
+ * don't want to point to a removed entry.
+ */
+ nextctp = LIST_NEXT(ctp, entries);
+ __dbclear_ctp(ctp);
+ }
+ }
+}
+
+extern "C" void
+__dbclear_ctp(ct_entry *ctp)
+{
+ LIST_REMOVE(ctp, entries);
+ __os_free(NULL, ctp);
+}
+
+extern "C" void
+__dbdel_ctp(ct_entry *parent)
+{
+ __dbclear_child(parent);
+ __dbclear_ctp(parent);
+}
+
+extern "C" ct_entry *
+new_ct_ent(int *errp)
+{
+ time_t t;
+ ct_entry *ctp, *octp;
+ int ret;
+
+ if ((ret = __os_malloc(NULL, sizeof(ct_entry), &ctp)) != 0) {
+ *errp = ret;
+ return (NULL);
+ }
+ memset(ctp, 0, sizeof(ct_entry));
+ /*
+ * Get the time as ID. We may service more than one request per
+ * second however. If we are, then increment id value until we
+ * find an unused one. We insert entries in LRU fashion at the
+ * head of the list. So, if the first entry doesn't match, then
+ * we know for certain that we can use our entry.
+ */
+ if ((t = time(NULL)) == -1) {
+ *errp = __os_get_errno();
+ __os_free(NULL, ctp);
+ return (NULL);
+ }
+ octp = LIST_FIRST(&__dbsrv_head);
+ if (octp != NULL && octp->ct_id >= t)
+ t = octp->ct_id + 1;
+ ctp->ct_id = t;
+ ctp->ct_idle = __dbsrv_idleto;
+ ctp->ct_activep = &ctp->ct_active;
+ ctp->ct_origp = NULL;
+ ctp->ct_refcount = 1;
+
+ LIST_INSERT_HEAD(&__dbsrv_head, ctp, entries);
+ return (ctp);
+}
+
+extern "C" ct_entry *
+get_tableent(long id)
+{
+ ct_entry *ctp;
+
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries))
+ if (ctp->ct_id == id)
+ return (ctp);
+ return (NULL);
+}
+
+extern "C" ct_entry *
+__dbsrv_sharedb(ct_entry *db_ctp, const char *name, const char *subdb, DBTYPE type, u_int32_t flags)
+{
+ ct_entry *ctp;
+
+ /*
+ * Check if we can share a db handle. Criteria for sharing are:
+ * If any of the non-sharable flags are set, we cannot share.
+ * Must be a db ctp, obviously.
+ * Must share the same env parent.
+ * Must be the same type, or current one DB_UNKNOWN.
+ * Must be same byteorder, or current one must not care.
+ * All flags must match.
+ * Must be same name, but don't share in-memory databases.
+ * Must be same subdb name.
+ */
+ if (flags & DB_SERVER_DBNOSHARE)
+ return (NULL);
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries)) {
+ /*
+ * Skip ourselves.
+ */
+ if (ctp == db_ctp)
+ continue;
+ if (ctp->ct_type != CT_DB)
+ continue;
+ if (ctp->ct_envparent != db_ctp->ct_envparent)
+ continue;
+ if (type != DB_UNKNOWN && ctp->ct_dbdp.type != type)
+ continue;
+ if (ctp->ct_dbdp.dbflags != LF_ISSET(DB_SERVER_DBFLAGS))
+ continue;
+ if (db_ctp->ct_dbdp.setflags != 0 &&
+ ctp->ct_dbdp.setflags != db_ctp->ct_dbdp.setflags)
+ continue;
+ if (name == NULL || ctp->ct_dbdp.db == NULL ||
+ strcmp(name, ctp->ct_dbdp.db) != 0)
+ continue;
+ if (subdb != ctp->ct_dbdp.subdb &&
+ (subdb == NULL || ctp->ct_dbdp.subdb == NULL ||
+ strcmp(subdb, ctp->ct_dbdp.subdb) != 0))
+ continue;
+ /*
+ * If we get here, then we match.
+ */
+ ctp->ct_refcount++;
+ return (ctp);
+ }
+
+ return (NULL);
+}
+
+extern "C" ct_entry *
+__dbsrv_shareenv(ct_entry *env_ctp, home_entry *home, u_int32_t flags)
+{
+ ct_entry *ctp;
+
+ /*
+ * Check if we can share an env. Criteria for sharing are:
+ * Must be an env ctp, obviously.
+ * Must share the same home env.
+ * All flags must match.
+ */
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries)) {
+ /*
+ * Skip ourselves.
+ */
+ if (ctp == env_ctp)
+ continue;
+ if (ctp->ct_type != CT_ENV)
+ continue;
+ if (ctp->ct_envdp.home != home)
+ continue;
+ if (ctp->ct_envdp.envflags != flags)
+ continue;
+ if (ctp->ct_envdp.onflags != env_ctp->ct_envdp.onflags)
+ continue;
+ if (ctp->ct_envdp.offflags != env_ctp->ct_envdp.offflags)
+ continue;
+ /*
+ * If we get here, then we match. The only thing left to
+ * check is the timeout. Since the server timeout set by
+ * the client is a hint, for sharing we'll give them the
+ * benefit of the doubt and grant them the longer timeout.
+ */
+ if (ctp->ct_timeout < env_ctp->ct_timeout)
+ ctp->ct_timeout = env_ctp->ct_timeout;
+ ctp->ct_refcount++;
+ return (ctp);
+ }
+
+ return (NULL);
+}
+
+extern "C" void
+__dbsrv_active(ct_entry *ctp)
+{
+ time_t t;
+ ct_entry *envctp;
+
+ if (ctp == NULL)
+ return;
+ if ((t = time(NULL)) == -1)
+ return;
+ *(ctp->ct_activep) = t;
+ if ((envctp = ctp->ct_envparent) == NULL)
+ return;
+ *(envctp->ct_activep) = t;
+ return;
+}
+
+extern "C" int
+__db_close_int(long id, u_int32_t flags)
+{
+ Db *dbp;
+ int ret;
+ ct_entry *ctp;
+
+ ret = 0;
+ ctp = get_tableent(id);
+ if (ctp == NULL)
+ return (DB_NOSERVER_ID);
+ DB_ASSERT(ctp->ct_type == CT_DB);
+ if (__dbsrv_verbose && ctp->ct_refcount != 1)
+ printf("Deref'ing dbp id %ld, refcount %d\n",
+ id, ctp->ct_refcount);
+ if (--ctp->ct_refcount != 0)
+ return (ret);
+ dbp = ctp->ct_dbp;
+ if (__dbsrv_verbose)
+ printf("Closing dbp id %ld\n", id);
+
+ ret = dbp->close(flags);
+ __dbdel_ctp(ctp);
+ return (ret);
+}
+
+extern "C" int
+__dbc_close_int(ct_entry *dbc_ctp)
+{
+ Dbc *dbc;
+ int ret;
+ ct_entry *ctp;
+
+ dbc = (Dbc *)dbc_ctp->ct_anyp;
+
+ ret = dbc->close();
+ /*
+ * If this cursor is a join cursor then we need to fix up the
+ * cursors that it was joined from so that they are independent again.
+ */
+ if (dbc_ctp->ct_type & CT_JOINCUR)
+ for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
+ ctp = LIST_NEXT(ctp, entries)) {
+ /*
+ * Test if it is a join cursor, and if it is part
+ * of this one.
+ */
+ if ((ctp->ct_type & CT_JOIN) &&
+ ctp->ct_activep == &dbc_ctp->ct_active) {
+ ctp->ct_type &= ~CT_JOIN;
+ ctp->ct_activep = ctp->ct_origp;
+ __dbsrv_active(ctp);
+ }
+ }
+ __dbclear_ctp(dbc_ctp);
+ return (ret);
+
+}
+
+extern "C" int
+__dbenv_close_int(long id, u_int32_t flags, int force)
+{
+ DbEnv *dbenv;
+ int ret;
+ ct_entry *ctp;
+
+ ret = 0;
+ ctp = get_tableent(id);
+ if (ctp == NULL)
+ return (DB_NOSERVER_ID);
+ DB_ASSERT(ctp->ct_type == CT_ENV);
+ if (__dbsrv_verbose && ctp->ct_refcount != 1)
+ printf("Deref'ing env id %ld, refcount %d\n",
+ id, ctp->ct_refcount);
+ /*
+ * If we are timing out, we need to force the close, no matter
+ * what the refcount.
+ */
+ if (--ctp->ct_refcount != 0 && !force)
+ return (ret);
+ dbenv = ctp->ct_envp;
+ if (__dbsrv_verbose)
+ printf("Closing env id %ld\n", id);
+
+ ret = dbenv->close(flags);
+ __dbdel_ctp(ctp);
+ return (ret);
+}
+
+static int
+add_home(char *home)
+{
+ home_entry *hp, *homep;
+ int ret;
+
+ if ((ret = __os_malloc(NULL, sizeof(home_entry), &hp)) != 0)
+ return (ret);
+ if ((ret = __os_malloc(NULL, strlen(home)+1, &hp->home)) != 0)
+ return (ret);
+ memcpy(hp->home, home, strlen(home)+1);
+ hp->dir = home;
+ hp->passwd = NULL;
+ /*
+ * This loop is to remove any trailing path separators,
+ * to assure hp->name points to the last component.
+ */
+ hp->name = __db_rpath(home);
+ *(hp->name) = '\0';
+ hp->name++;
+ while (*(hp->name) == '\0') {
+ hp->name = __db_rpath(home);
+ *(hp->name) = '\0';
+ hp->name++;
+ }
+ /*
+ * Now we have successfully added it. Make sure there are no
+ * identical names.
+ */
+ for (homep = LIST_FIRST(&__dbsrv_home); homep != NULL;
+ homep = LIST_NEXT(homep, entries))
+ if (strcmp(homep->name, hp->name) == 0) {
+ printf("Already added home name %s, at directory %s\n",
+ hp->name, homep->dir);
+ return (-1);
+ }
+ LIST_INSERT_HEAD(&__dbsrv_home, hp, entries);
+ if (__dbsrv_verbose)
+ printf("Added home %s in dir %s\n", hp->name, hp->dir);
+ return (0);
+}
+
+static int
+add_passwd(char *passwd)
+{
+ home_entry *hp;
+
+ /*
+ * We add the passwd to the last given home dir. If there
+ * isn't a home dir, or the most recent one already has a
+ * passwd, then there is a user error.
+ */
+ hp = LIST_FIRST(&__dbsrv_home);
+ if (hp == NULL || hp->passwd != NULL)
+ return (EINVAL);
+ /*
+ * We've already strdup'ed the passwd above, so we don't need
+ * to malloc new space, just point to it.
+ */
+ hp->passwd = passwd;
+ return (0);
+}
+
+extern "C" home_entry *
+get_home(char *name)
+{
+ home_entry *hp;
+
+ for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
+ hp = LIST_NEXT(hp, entries))
+ if (strcmp(name, hp->name) == 0)
+ return (hp);
+ return (NULL);
+}
+
+static int
+env_recover(char *progname)
+{
+ DbEnv *dbenv;
+ home_entry *hp;
+ u_int32_t flags;
+ int exitval, ret;
+
+ for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
+ hp = LIST_NEXT(hp, entries)) {
+ exitval = 0;
+ dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
+ if (__dbsrv_verbose == 1) {
+ (void)dbenv->set_verbose(DB_VERB_RECOVERY, 1);
+ (void)dbenv->set_verbose(DB_VERB_CHKPOINT, 1);
+ }
+ dbenv->set_errfile(stderr);
+ dbenv->set_errpfx(progname);
+ if (hp->passwd != NULL)
+ (void)dbenv->set_encrypt(hp->passwd, DB_ENCRYPT_AES);
+
+ /*
+ * Initialize the env with DB_RECOVER. That is all we
+ * have to do to run recovery.
+ */
+ if (__dbsrv_verbose)
+ printf("Running recovery on %s\n", hp->home);
+ flags = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
+ DB_INIT_TXN | DB_USE_ENVIRON | DB_RECOVER;
+ if ((ret = dbenv->open(hp->home, flags, 0)) != 0) {
+ dbenv->err(ret, "DbEnv->open");
+ goto error;
+ }
+
+ if (0) {
+error: exitval = 1;
+ }
+ if ((ret = dbenv->close(0)) != 0) {
+ exitval = 1;
+ fprintf(stderr, "%s: dbenv->close: %s\n",
+ progname, db_strerror(ret));
+ }
+ if (exitval)
+ return (exitval);
+ }
+ return (0);
+}
diff --git a/bdb/rpc_server/db_server.sed b/bdb/rpc_server/db_server.sed
deleted file mode 100644
index f028f778e21..00000000000
--- a/bdb/rpc_server/db_server.sed
+++ /dev/null
@@ -1,5 +0,0 @@
-1i\
-\#include "db_config.h"\
-\#ifdef HAVE_RPC
-$a\
-\#endif /* HAVE_RPC */
diff --git a/bdb/rpc_server/db_server_proc.c b/bdb/rpc_server/db_server_proc.c
deleted file mode 100644
index 108a00fb371..00000000000
--- a/bdb/rpc_server/db_server_proc.c
+++ /dev/null
@@ -1,1546 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifdef HAVE_RPC
-#ifndef lint
-static const char revid[] = "$Id: db_server_proc.c,v 1.48 2001/01/06 16:08:01 sue Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <rpc/rpc.h>
-
-#include <string.h>
-#endif
-#include "db_server.h"
-
-#include "db_int.h"
-#include "db_server_int.h"
-#include "rpc_server_ext.h"
-
-static int __db_stats_list __P((DB_ENV *,
- __db_stat_statsreplist **, u_int32_t *, int));
-
-/* BEGIN __env_cachesize_1_proc */
-void
-__env_cachesize_1_proc(dbenvcl_id, gbytes, bytes,
- ncache, replyp)
- long dbenvcl_id;
- u_int32_t gbytes;
- u_int32_t bytes;
- u_int32_t ncache;
- __env_cachesize_reply *replyp;
-/* END __env_cachesize_1_proc */
-{
- int ret;
- DB_ENV * dbenv;
- ct_entry *dbenv_ctp;
-
- ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
- dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
-
- ret = dbenv->set_cachesize(dbenv, gbytes, bytes, ncache);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __env_close_1_proc */
-void
-__env_close_1_proc(dbenvcl_id, flags, replyp)
- long dbenvcl_id;
- u_int32_t flags;
- __env_close_reply *replyp;
-/* END __env_close_1_proc */
-{
- replyp->status = __dbenv_close_int(dbenvcl_id, flags);
- return;
-}
-
-/* BEGIN __env_create_1_proc */
-void
-__env_create_1_proc(timeout, replyp)
- u_int32_t timeout;
- __env_create_reply *replyp;
-/* END __env_create_1_proc */
-{
- int ret;
- DB_ENV *dbenv;
- ct_entry *ctp;
-
- ctp = new_ct_ent(&replyp->status);
- if (ctp == NULL)
- return;
- if ((ret = db_env_create(&dbenv, 0)) == 0) {
- ctp->ct_envp = dbenv;
- ctp->ct_type = CT_ENV;
- ctp->ct_parent = NULL;
- ctp->ct_envparent = ctp;
- __dbsrv_settimeout(ctp, timeout);
- __dbsrv_active(ctp);
- replyp->envcl_id = ctp->ct_id;
- } else
- __dbclear_ctp(ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __env_flags_1_proc */
-void
-__env_flags_1_proc(dbenvcl_id, flags, onoff, replyp)
- long dbenvcl_id;
- u_int32_t flags;
- u_int32_t onoff;
- __env_flags_reply *replyp;
-/* END __env_flags_1_proc */
-{
- int ret;
- DB_ENV * dbenv;
- ct_entry *dbenv_ctp;
-
- ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
- dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
-
- ret = dbenv->set_flags(dbenv, flags, onoff);
-
- replyp->status = ret;
- return;
-}
-/* BEGIN __env_open_1_proc */
-void
-__env_open_1_proc(dbenvcl_id, home, flags,
- mode, replyp)
- long dbenvcl_id;
- char *home;
- u_int32_t flags;
- u_int32_t mode;
- __env_open_reply *replyp;
-/* END __env_open_1_proc */
-{
- int ret;
- DB_ENV * dbenv;
- ct_entry *dbenv_ctp;
- char *fullhome;
-
- ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
- dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
- fullhome = get_home(home);
- if (fullhome == NULL) {
- replyp->status = DB_NOSERVER_HOME;
- return;
- }
-
- ret = dbenv->open(dbenv, fullhome, flags, mode);
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __env_remove_1_proc */
-void
-__env_remove_1_proc(dbenvcl_id, home, flags, replyp)
- long dbenvcl_id;
- char *home;
- u_int32_t flags;
- __env_remove_reply *replyp;
-/* END __env_remove_1_proc */
-{
- int ret;
- DB_ENV * dbenv;
- ct_entry *dbenv_ctp;
- char *fullhome;
-
- ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
- dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
- fullhome = get_home(home);
- if (fullhome == NULL) {
- replyp->status = DB_NOSERVER_HOME;
- return;
- }
-
- ret = dbenv->remove(dbenv, fullhome, flags);
- __dbdel_ctp(dbenv_ctp);
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __txn_abort_1_proc */
-void
-__txn_abort_1_proc(txnpcl_id, replyp)
- long txnpcl_id;
- __txn_abort_reply *replyp;
-/* END __txn_abort_1_proc */
-{
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
- int ret;
-
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
-
- ret = txn_abort(txnp);
- __dbdel_ctp(txnp_ctp);
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __txn_begin_1_proc */
-void
-__txn_begin_1_proc(envpcl_id, parentcl_id,
- flags, replyp)
- long envpcl_id;
- long parentcl_id;
- u_int32_t flags;
- __txn_begin_reply *replyp;
-/* END __txn_begin_1_proc */
-{
- int ret;
- DB_ENV * envp;
- ct_entry *envp_ctp;
- DB_TXN * parent;
- ct_entry *parent_ctp;
- DB_TXN *txnp;
- ct_entry *ctp;
-
- ACTIVATE_CTP(envp_ctp, envpcl_id, CT_ENV);
- envp = (DB_ENV *)envp_ctp->ct_anyp;
- parent_ctp = NULL;
-
- ctp = new_ct_ent(&replyp->status);
- if (ctp == NULL)
- return;
-
- if (parentcl_id != 0) {
- ACTIVATE_CTP(parent_ctp, parentcl_id, CT_TXN);
- parent = (DB_TXN *)parent_ctp->ct_anyp;
- ctp->ct_activep = parent_ctp->ct_activep;
- } else
- parent = NULL;
-
- ret = txn_begin(envp, parent, &txnp, flags);
- if (ret == 0) {
- ctp->ct_txnp = txnp;
- ctp->ct_type = CT_TXN;
- ctp->ct_parent = parent_ctp;
- ctp->ct_envparent = envp_ctp;
- replyp->txnidcl_id = ctp->ct_id;
- __dbsrv_settimeout(ctp, envp_ctp->ct_timeout);
- __dbsrv_active(ctp);
- } else
- __dbclear_ctp(ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __txn_commit_1_proc */
-void
-__txn_commit_1_proc(txnpcl_id, flags, replyp)
- long txnpcl_id;
- u_int32_t flags;
- __txn_commit_reply *replyp;
-/* END __txn_commit_1_proc */
-{
- int ret;
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
-
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
-
- ret = txn_commit(txnp, flags);
- __dbdel_ctp(txnp_ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_bt_maxkey_1_proc */
-void
-__db_bt_maxkey_1_proc(dbpcl_id, maxkey, replyp)
- long dbpcl_id;
- u_int32_t maxkey;
- __db_bt_maxkey_reply *replyp;
-/* END __db_bt_maxkey_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_bt_maxkey(dbp, maxkey);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_bt_minkey_1_proc */
-void
-__db_bt_minkey_1_proc(dbpcl_id, minkey, replyp)
- long dbpcl_id;
- u_int32_t minkey;
- __db_bt_minkey_reply *replyp;
-/* END __db_bt_minkey_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_bt_minkey(dbp, minkey);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_close_1_proc */
-void
-__db_close_1_proc(dbpcl_id, flags, replyp)
- long dbpcl_id;
- u_int32_t flags;
- __db_close_reply *replyp;
-/* END __db_close_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->close(dbp, flags);
- __dbdel_ctp(dbp_ctp);
-
- replyp-> status= ret;
- return;
-}
-
-/* BEGIN __db_create_1_proc */
-void
-__db_create_1_proc(flags, envpcl_id, replyp)
- u_int32_t flags;
- long envpcl_id;
- __db_create_reply *replyp;
-/* END __db_create_1_proc */
-{
- int ret;
- DB_ENV * envp;
- DB *dbp;
- ct_entry *envp_ctp, *dbp_ctp;
-
- ACTIVATE_CTP(envp_ctp, envpcl_id, CT_ENV);
- envp = (DB_ENV *)envp_ctp->ct_anyp;
-
- dbp_ctp = new_ct_ent(&replyp->status);
- if (dbp_ctp == NULL)
- return ;
- /*
- * We actually require env's for databases. The client should
- * have caught it, but just in case.
- */
- DB_ASSERT(envp != NULL);
- if ((ret = db_create(&dbp, envp, flags)) == 0) {
- dbp_ctp->ct_dbp = dbp;
- dbp_ctp->ct_type = CT_DB;
- dbp_ctp->ct_parent = envp_ctp;
- dbp_ctp->ct_envparent = envp_ctp;
- replyp->dbpcl_id = dbp_ctp->ct_id;
- } else
- __dbclear_ctp(dbp_ctp);
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_del_1_proc */
-void
-__db_del_1_proc(dbpcl_id, txnpcl_id, keydlen,
- keydoff, keyflags, keydata, keysize,
- flags, replyp)
- long dbpcl_id;
- long txnpcl_id;
- u_int32_t keydlen;
- u_int32_t keydoff;
- u_int32_t keyflags;
- void *keydata;
- u_int32_t keysize;
- u_int32_t flags;
- __db_del_reply *replyp;
-/* END __db_del_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
- DBT key;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
- if (txnpcl_id != 0) {
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
- } else
- txnp = NULL;
-
- memset(&key, 0, sizeof(key));
-
- /* Set up key DBT */
- key.dlen = keydlen;
- key.doff = keydoff;
- key.flags = keyflags;
- key.size = keysize;
- key.data = keydata;
-
- ret = dbp->del(dbp, txnp, &key, flags);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_extentsize_1_proc */
-void
-__db_extentsize_1_proc(dbpcl_id, extentsize, replyp)
- long dbpcl_id;
- u_int32_t extentsize;
- __db_extentsize_reply *replyp;
-/* END __db_extentsize_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_q_extentsize(dbp, extentsize);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_flags_1_proc */
-void
-__db_flags_1_proc(dbpcl_id, flags, replyp)
- long dbpcl_id;
- u_int32_t flags;
- __db_flags_reply *replyp;
-/* END __db_flags_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_flags(dbp, flags);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_get_1_proc */
-void
-__db_get_1_proc(dbpcl_id, txnpcl_id, keydlen,
- keydoff, keyflags, keydata, keysize,
- datadlen, datadoff, dataflags, datadata,
- datasize, flags, replyp, freep)
- long dbpcl_id;
- long txnpcl_id;
- u_int32_t keydlen;
- u_int32_t keydoff;
- u_int32_t keyflags;
- void *keydata;
- u_int32_t keysize;
- u_int32_t datadlen;
- u_int32_t datadoff;
- u_int32_t dataflags;
- void *datadata;
- u_int32_t datasize;
- u_int32_t flags;
- __db_get_reply *replyp;
- int * freep;
-/* END __db_get_1_proc */
-{
- int key_alloc, ret;
- DB * dbp;
- ct_entry *dbp_ctp;
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
- DBT key, data;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
- if (txnpcl_id != 0) {
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
- } else
- txnp = NULL;
-
- *freep = 0;
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
-
- /* Set up key and data DBT */
- key.dlen = keydlen;
- key.doff = keydoff;
- /*
- * Ignore memory related flags on server.
- */
- key.flags = DB_DBT_MALLOC;
- if (keyflags & DB_DBT_PARTIAL)
- key.flags |= DB_DBT_PARTIAL;
- key.size = keysize;
- key.data = keydata;
-
- data.dlen = datadlen;
- data.doff = datadoff;
- /*
- * Ignore memory related flags on server.
- */
- data.flags = DB_DBT_MALLOC;
- if (dataflags & DB_DBT_PARTIAL)
- data.flags |= DB_DBT_PARTIAL;
- data.size = datasize;
- data.data = datadata;
-
- /* Got all our stuff, now do the get */
- ret = dbp->get(dbp, txnp, &key, &data, flags);
- /*
- * Otherwise just status.
- */
- if (ret == 0) {
- /*
- * XXX
- * We need to xdr_free whatever we are returning, next time.
- * However, DB does not allocate a new key if one was given
- * and we'd be free'ing up space allocated in the request.
- * So, allocate a new key/data pointer if it is the same one
- * as in the request.
- */
- *freep = 1;
- /*
- * Key
- */
- key_alloc = 0;
- if (key.data == keydata) {
- ret = __os_malloc(dbp->dbenv,
- key.size, NULL, &replyp->keydata.keydata_val);
- if (ret != 0) {
- __os_free(key.data, key.size);
- __os_free(data.data, data.size);
- goto err;
- }
- key_alloc = 1;
- memcpy(replyp->keydata.keydata_val, key.data, key.size);
- } else
- replyp->keydata.keydata_val = key.data;
-
- replyp->keydata.keydata_len = key.size;
-
- /*
- * Data
- */
- if (data.data == datadata) {
- ret = __os_malloc(dbp->dbenv,
- data.size, NULL, &replyp->datadata.datadata_val);
- if (ret != 0) {
- __os_free(key.data, key.size);
- __os_free(data.data, data.size);
- if (key_alloc)
- __os_free(replyp->keydata.keydata_val,
- key.size);
- goto err;
- }
- memcpy(replyp->datadata.datadata_val, data.data,
- data.size);
- } else
- replyp->datadata.datadata_val = data.data;
- replyp->datadata.datadata_len = data.size;
- } else {
-err: replyp->keydata.keydata_val = NULL;
- replyp->keydata.keydata_len = 0;
- replyp->datadata.datadata_val = NULL;
- replyp->datadata.datadata_len = 0;
- *freep = 0;
- }
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_h_ffactor_1_proc */
-void
-__db_h_ffactor_1_proc(dbpcl_id, ffactor, replyp)
- long dbpcl_id;
- u_int32_t ffactor;
- __db_h_ffactor_reply *replyp;
-/* END __db_h_ffactor_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_h_ffactor(dbp, ffactor);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_h_nelem_1_proc */
-void
-__db_h_nelem_1_proc(dbpcl_id, nelem, replyp)
- long dbpcl_id;
- u_int32_t nelem;
- __db_h_nelem_reply *replyp;
-/* END __db_h_nelem_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_h_nelem(dbp, nelem);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_key_range_1_proc */
-void
-__db_key_range_1_proc(dbpcl_id, txnpcl_id, keydlen,
- keydoff, keyflags, keydata, keysize,
- flags, replyp)
- long dbpcl_id;
- long txnpcl_id;
- u_int32_t keydlen;
- u_int32_t keydoff;
- u_int32_t keyflags;
- void *keydata;
- u_int32_t keysize;
- u_int32_t flags;
- __db_key_range_reply *replyp;
-/* END __db_key_range_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
- DBT key;
- DB_KEY_RANGE range;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
- if (txnpcl_id != 0) {
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
- } else
- txnp = NULL;
-
- memset(&key, 0, sizeof(key));
- /* Set up key and data DBT */
- key.dlen = keydlen;
- key.doff = keydoff;
- key.size = keysize;
- key.data = keydata;
- key.flags = keyflags;
-
- ret = dbp->key_range(dbp, txnp, &key, &range, flags);
-
- replyp->status = ret;
- replyp->less = range.less;
- replyp->equal = range.equal;
- replyp->greater = range.greater;
- return;
-}
-
-/* BEGIN __db_lorder_1_proc */
-void
-__db_lorder_1_proc(dbpcl_id, lorder, replyp)
- long dbpcl_id;
- u_int32_t lorder;
- __db_lorder_reply *replyp;
-/* END __db_lorder_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_lorder(dbp, lorder);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __dbopen_1_proc */
-void
-__db_open_1_proc(dbpcl_id, name, subdb,
- type, flags, mode, replyp)
- long dbpcl_id;
- char *name;
- char *subdb;
- u_int32_t type;
- u_int32_t flags;
- u_int32_t mode;
- __db_open_reply *replyp;
-/* END __db_open_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->open(dbp, name, subdb, (DBTYPE)type, flags, mode);
- if (ret == 0) {
- replyp->type = (int) dbp->get_type(dbp);
- /* XXX
- * Tcl needs to peek at dbp->flags for DB_AM_DUP. Send
- * this dbp's flags back.
- */
- replyp->dbflags = (int) dbp->flags;
- }
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_pagesize_1_proc */
-void
-__db_pagesize_1_proc(dbpcl_id, pagesize, replyp)
- long dbpcl_id;
- u_int32_t pagesize;
- __db_pagesize_reply *replyp;
-/* END __db_pagesize_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_pagesize(dbp, pagesize);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_put_1_proc */
-void
-__db_put_1_proc(dbpcl_id, txnpcl_id, keydlen,
- keydoff, keyflags, keydata, keysize,
- datadlen, datadoff, dataflags, datadata,
- datasize, flags, replyp, freep)
- long dbpcl_id;
- long txnpcl_id;
- u_int32_t keydlen;
- u_int32_t keydoff;
- u_int32_t keyflags;
- void *keydata;
- u_int32_t keysize;
- u_int32_t datadlen;
- u_int32_t datadoff;
- u_int32_t dataflags;
- void *datadata;
- u_int32_t datasize;
- u_int32_t flags;
- __db_put_reply *replyp;
- int * freep;
-/* END __db_put_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
- DBT key, data;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
- if (txnpcl_id != 0) {
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
- } else
- txnp = NULL;
-
- *freep = 0;
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
-
- /* Set up key and data DBT */
- key.dlen = keydlen;
- key.doff = keydoff;
- /*
- * Ignore memory related flags on server.
- */
- key.flags = DB_DBT_MALLOC;
- if (keyflags & DB_DBT_PARTIAL)
- key.flags |= DB_DBT_PARTIAL;
- key.size = keysize;
- key.data = keydata;
-
- data.dlen = datadlen;
- data.doff = datadoff;
- data.flags = dataflags;
- data.size = datasize;
- data.data = datadata;
-
- /* Got all our stuff, now do the put */
- ret = dbp->put(dbp, txnp, &key, &data, flags);
- /*
- * If the client did a DB_APPEND, set up key in reply.
- * Otherwise just status.
- */
- if (ret == 0 && (flags == DB_APPEND)) {
- /*
- * XXX
- * We need to xdr_free whatever we are returning, next time.
- * However, DB does not allocate a new key if one was given
- * and we'd be free'ing up space allocated in the request.
- * So, allocate a new key/data pointer if it is the same one
- * as in the request.
- */
- *freep = 1;
- /*
- * Key
- */
- if (key.data == keydata) {
- ret = __os_malloc(dbp->dbenv,
- key.size, NULL, &replyp->keydata.keydata_val);
- if (ret != 0) {
- __os_free(key.data, key.size);
- goto err;
- }
- memcpy(replyp->keydata.keydata_val, key.data, key.size);
- } else
- replyp->keydata.keydata_val = key.data;
-
- replyp->keydata.keydata_len = key.size;
- } else {
-err: replyp->keydata.keydata_val = NULL;
- replyp->keydata.keydata_len = 0;
- *freep = 0;
- }
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_re_delim_1_proc */
-void
-__db_re_delim_1_proc(dbpcl_id, delim, replyp)
- long dbpcl_id;
- u_int32_t delim;
- __db_re_delim_reply *replyp;
-/* END __db_re_delim_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_re_delim(dbp, delim);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_re_len_1_proc */
-void
-__db_re_len_1_proc(dbpcl_id, len, replyp)
- long dbpcl_id;
- u_int32_t len;
- __db_re_len_reply *replyp;
-/* END __db_re_len_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_re_len(dbp, len);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_re_pad_1_proc */
-void
-__db_re_pad_1_proc(dbpcl_id, pad, replyp)
- long dbpcl_id;
- u_int32_t pad;
- __db_re_pad_reply *replyp;
-/* END __db_re_pad_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->set_re_pad(dbp, pad);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_remove_1_proc */
-void
-__db_remove_1_proc(dbpcl_id, name, subdb,
- flags, replyp)
- long dbpcl_id;
- char *name;
- char *subdb;
- u_int32_t flags;
- __db_remove_reply *replyp;
-/* END __db_remove_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->remove(dbp, name, subdb, flags);
- __dbdel_ctp(dbp_ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_rename_1_proc */
-void
-__db_rename_1_proc(dbpcl_id, name, subdb,
- newname, flags, replyp)
- long dbpcl_id;
- char *name;
- char *subdb;
- char *newname;
- u_int32_t flags;
- __db_rename_reply *replyp;
-/* END __db_rename_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->rename(dbp, name, subdb, newname, flags);
- __dbdel_ctp(dbp_ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_stat_1_proc */
-void
-__db_stat_1_proc(dbpcl_id,
- flags, replyp, freep)
- long dbpcl_id;
- u_int32_t flags;
- __db_stat_reply *replyp;
- int * freep;
-/* END __db_stat_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
- DBTYPE type;
- void *sp;
- int len;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->stat(dbp, &sp, NULL, flags);
- replyp->status = ret;
- if (ret != 0)
- return;
- /*
- * We get here, we have success. Allocate an array so that
- * we can use the list generator. Generate the reply, free
- * up the space.
- */
- /*
- * XXX This assumes that all elements of all stat structures
- * are u_int32_t fields. They are, currently.
- */
- type = dbp->get_type(dbp);
- if (type == DB_HASH)
- len = sizeof(DB_HASH_STAT) / sizeof(u_int32_t);
- else if (type == DB_QUEUE)
- len = sizeof(DB_QUEUE_STAT) / sizeof(u_int32_t);
- else /* BTREE or RECNO are same stats */
- len = sizeof(DB_BTREE_STAT) / sizeof(u_int32_t);
- /*
- * Set up our list of stats.
- */
- ret = __db_stats_list(dbp->dbenv,
- &replyp->statslist, (u_int32_t*)sp, len);
-
- __os_free(sp, 0);
- if (ret == 0)
- *freep = 1;
- replyp->status = ret;
- return;
-}
-
-int
-__db_stats_list(dbenv, locp, pp, len)
- DB_ENV *dbenv;
- __db_stat_statsreplist **locp;
- u_int32_t *pp;
- int len;
-{
- u_int32_t *p, *q;
- int i, ret;
- __db_stat_statsreplist *nl, **nlp;
-
- nlp = locp;
- for (i = 0; i < len; i++) {
- p = pp+i;
- if ((ret = __os_malloc(dbenv, sizeof(*nl), NULL, nlp)) != 0)
- goto out;
- nl = *nlp;
- nl->next = NULL;
- if ((ret = __os_malloc(dbenv,
- sizeof(u_int32_t), NULL, &nl->ent.ent_val)) != 0)
- goto out;
- q = (u_int32_t *)nl->ent.ent_val;
- *q = *p;
- nl->ent.ent_len = sizeof(u_int32_t);
- nlp = &nl->next;
- }
- return (0);
-out:
- __db_stats_freelist(locp);
- return (ret);
-}
-
-/*
- * PUBLIC: void __db_stats_freelist __P((__db_stat_statsreplist **));
- */
-void
-__db_stats_freelist(locp)
- __db_stat_statsreplist **locp;
-{
- __db_stat_statsreplist *nl, *nl1;
-
- for (nl = *locp; nl != NULL; nl = nl1) {
- nl1 = nl->next;
- if (nl->ent.ent_val)
- __os_free(nl->ent.ent_val, nl->ent.ent_len);
- __os_free(nl, sizeof(*nl));
- }
- *locp = NULL;
-}
-
-/* BEGIN __db_swapped_1_proc */
-void
-__db_swapped_1_proc(dbpcl_id, replyp)
- long dbpcl_id;
- __db_swapped_reply *replyp;
-/* END __db_swapped_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->get_byteswapped(dbp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_sync_1_proc */
-void
-__db_sync_1_proc(dbpcl_id, flags, replyp)
- long dbpcl_id;
- u_int32_t flags;
- __db_sync_reply *replyp;
-/* END __db_sync_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- ret = dbp->sync(dbp, flags);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_cursor_1_proc */
-void
-__db_cursor_1_proc(dbpcl_id, txnpcl_id,
- flags, replyp)
- long dbpcl_id;
- long txnpcl_id;
- u_int32_t flags;
- __db_cursor_reply *replyp;
-/* END __db_cursor_1_proc */
-{
- int ret;
- DB * dbp;
- ct_entry *dbp_ctp;
- DB_TXN * txnp;
- ct_entry *txnp_ctp;
- DBC *dbc;
- ct_entry *dbc_ctp, *env_ctp;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
- dbc_ctp = new_ct_ent(&replyp->status);
- if (dbc_ctp == NULL)
- return;
-
- if (txnpcl_id != 0) {
- ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
- txnp = (DB_TXN *)txnp_ctp->ct_anyp;
- dbc_ctp->ct_activep = txnp_ctp->ct_activep;
- } else
- txnp = NULL;
-
- if ((ret = dbp->cursor(dbp, txnp, &dbc, flags)) == 0) {
- dbc_ctp->ct_dbc = dbc;
- dbc_ctp->ct_type = CT_CURSOR;
- dbc_ctp->ct_parent = dbp_ctp;
- env_ctp = dbp_ctp->ct_envparent;
- dbc_ctp->ct_envparent = env_ctp;
- __dbsrv_settimeout(dbc_ctp, env_ctp->ct_timeout);
- __dbsrv_active(dbc_ctp);
- replyp->dbcidcl_id = dbc_ctp->ct_id;
- } else
- __dbclear_ctp(dbc_ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __db_join_1_proc */
-void
-__db_join_1_proc(dbpcl_id, curslist,
- flags, replyp)
- long dbpcl_id;
- u_int32_t * curslist;
- u_int32_t flags;
- __db_join_reply *replyp;
-/* END __db_join_1_proc */
-{
- DB * dbp;
- ct_entry *dbp_ctp;
- DBC *dbc;
- DBC **jcurs, **c;
- ct_entry *dbc_ctp, *ctp;
- size_t size;
- int ret;
- u_int32_t *cl;
-
- ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
- dbp = (DB *)dbp_ctp->ct_anyp;
-
- dbc_ctp = new_ct_ent(&replyp->status);
- if (dbc_ctp == NULL)
- return;
-
- for (size = sizeof(DBC *), cl = curslist; *cl != 0; size += sizeof(DBC *), cl++)
- ;
- if ((ret = __os_malloc(dbp->dbenv, size, NULL, &jcurs)) != 0) {
- replyp->status = ret;
- __dbclear_ctp(dbc_ctp);
- return;
- }
- /*
- * If our curslist has a parent txn, we need to use it too
- * for the activity timeout. All cursors must be part of
- * the same transaction, so just check the first.
- */
- ctp = get_tableent(*curslist);
- DB_ASSERT(ctp->ct_type == CT_CURSOR);
- /*
- * If we are using a transaction, set the join activity timer
- * to point to the parent transaction.
- */
- if (ctp->ct_activep != &ctp->ct_active)
- dbc_ctp->ct_activep = ctp->ct_activep;
- for (cl = curslist, c = jcurs; *cl != 0; cl++, c++) {
- ctp = get_tableent(*cl);
- if (ctp == NULL) {
- replyp->status = DB_NOSERVER_ID;
- goto out;
- }
- /*
- * If we are using a txn, the join cursor points to the
- * transaction timeout. If we are not using a transaction,
- * then all the curslist cursors must point to the join
- * cursor's timeout so that we do not timeout any of the
- * curlist cursors while the join cursor is active.
- * Change the type of the curslist ctps to CT_JOIN so that
- * we know they are part of a join list and we can distinguish
- * them and later restore them when the join cursor is closed.
- */
- DB_ASSERT(ctp->ct_type == CT_CURSOR);
- ctp->ct_type |= CT_JOIN;
- ctp->ct_origp = ctp->ct_activep;
- /*
- * Setting this to the ct_active field of the dbc_ctp is
- * really just a way to distinguish which join dbc this
- * cursor is part of. The ct_activep of this cursor is
- * not used at all during its lifetime as part of a join
- * cursor.
- */
- ctp->ct_activep = &dbc_ctp->ct_active;
- *c = ctp->ct_dbc;
- }
- *c = NULL;
- if ((ret = dbp->join(dbp, jcurs, &dbc, flags)) == 0) {
- dbc_ctp->ct_dbc = dbc;
- dbc_ctp->ct_type = (CT_JOINCUR | CT_CURSOR);
- dbc_ctp->ct_parent = dbp_ctp;
- dbc_ctp->ct_envparent = dbp_ctp->ct_envparent;
- __dbsrv_settimeout(dbc_ctp, dbp_ctp->ct_envparent->ct_timeout);
- __dbsrv_active(dbc_ctp);
- replyp->dbcidcl_id = dbc_ctp->ct_id;
- } else {
- __dbclear_ctp(dbc_ctp);
- /*
- * If we get an error, undo what we did above to any cursors.
- */
- for (cl = curslist; *cl != 0; cl++) {
- ctp = get_tableent(*cl);
- ctp->ct_type = CT_CURSOR;
- ctp->ct_activep = ctp->ct_origp;
- }
- }
-
- replyp->status = ret;
-out:
- __os_free(jcurs, size);
- return;
-}
-
-/* BEGIN __dbc_close_1_proc */
-void
-__dbc_close_1_proc(dbccl_id, replyp)
- long dbccl_id;
- __dbc_close_reply *replyp;
-/* END __dbc_close_1_proc */
-{
- ct_entry *dbc_ctp;
-
- ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
- replyp->status = __dbc_close_int(dbc_ctp);
- return;
-}
-
-/* BEGIN __dbc_count_1_proc */
-void
-__dbc_count_1_proc(dbccl_id, flags, replyp)
- long dbccl_id;
- u_int32_t flags;
- __dbc_count_reply *replyp;
-/* END __dbc_count_1_proc */
-{
- int ret;
- DBC * dbc;
- ct_entry *dbc_ctp;
- db_recno_t num;
-
- ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
- dbc = (DBC *)dbc_ctp->ct_anyp;
-
- ret = dbc->c_count(dbc, &num, flags);
- replyp->status = ret;
- if (ret == 0)
- replyp->dupcount = num;
- return;
-}
-
-/* BEGIN __dbc_del_1_proc */
-void
-__dbc_del_1_proc(dbccl_id, flags, replyp)
- long dbccl_id;
- u_int32_t flags;
- __dbc_del_reply *replyp;
-/* END __dbc_del_1_proc */
-{
- int ret;
- DBC * dbc;
- ct_entry *dbc_ctp;
-
- ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
- dbc = (DBC *)dbc_ctp->ct_anyp;
-
- ret = dbc->c_del(dbc, flags);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __dbc_dup_1_proc */
-void
-__dbc_dup_1_proc(dbccl_id, flags, replyp)
- long dbccl_id;
- u_int32_t flags;
- __dbc_dup_reply *replyp;
-/* END __dbc_dup_1_proc */
-{
- int ret;
- DBC * dbc;
- ct_entry *dbc_ctp;
- DBC *newdbc;
- ct_entry *new_ctp;
-
- ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
- dbc = (DBC *)dbc_ctp->ct_anyp;
-
- new_ctp = new_ct_ent(&replyp->status);
- if (new_ctp == NULL)
- return;
-
- if ((ret = dbc->c_dup(dbc, &newdbc, flags)) == 0) {
- new_ctp->ct_dbc = newdbc;
- new_ctp->ct_type = CT_CURSOR;
- new_ctp->ct_parent = dbc_ctp->ct_parent;
- new_ctp->ct_envparent = dbc_ctp->ct_envparent;
- /*
- * If our cursor has a parent txn, we need to use it too.
- */
- if (dbc_ctp->ct_activep != &dbc_ctp->ct_active)
- new_ctp->ct_activep = dbc_ctp->ct_activep;
- __dbsrv_settimeout(new_ctp, dbc_ctp->ct_timeout);
- __dbsrv_active(new_ctp);
- replyp->dbcidcl_id = new_ctp->ct_id;
- } else
- __dbclear_ctp(new_ctp);
-
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __dbc_get_1_proc */
-void
-__dbc_get_1_proc(dbccl_id, keydlen, keydoff,
- keyflags, keydata, keysize, datadlen,
- datadoff, dataflags, datadata, datasize,
- flags, replyp, freep)
- long dbccl_id;
- u_int32_t keydlen;
- u_int32_t keydoff;
- u_int32_t keyflags;
- void *keydata;
- u_int32_t keysize;
- u_int32_t datadlen;
- u_int32_t datadoff;
- u_int32_t dataflags;
- void *datadata;
- u_int32_t datasize;
- u_int32_t flags;
- __dbc_get_reply *replyp;
- int * freep;
-/* END __dbc_get_1_proc */
-{
- DB_ENV *dbenv;
- DBC *dbc;
- DBT key, data;
- ct_entry *dbc_ctp;
- int key_alloc, ret;
-
- ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
- dbc = (DBC *)dbc_ctp->ct_anyp;
- dbenv = dbc->dbp->dbenv;
-
- *freep = 0;
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
-
- /* Set up key and data DBT */
- key.dlen = keydlen;
- key.doff = keydoff;
- /*
- * Ignore memory related flags on server.
- */
- key.flags = DB_DBT_MALLOC;
- if (keyflags & DB_DBT_PARTIAL)
- key.flags |= DB_DBT_PARTIAL;
- key.size = keysize;
- key.data = keydata;
-
- data.dlen = datadlen;
- data.doff = datadoff;
- data.flags = DB_DBT_MALLOC;
- if (dataflags & DB_DBT_PARTIAL)
- data.flags |= DB_DBT_PARTIAL;
- data.size = datasize;
- data.data = datadata;
-
- /* Got all our stuff, now do the get */
- ret = dbc->c_get(dbc, &key, &data, flags);
-
- /*
- * Otherwise just status.
- */
- if (ret == 0) {
- /*
- * XXX
- * We need to xdr_free whatever we are returning, next time.
- * However, DB does not allocate a new key if one was given
- * and we'd be free'ing up space allocated in the request.
- * So, allocate a new key/data pointer if it is the same one
- * as in the request.
- */
- *freep = 1;
- /*
- * Key
- */
- key_alloc = 0;
- if (key.data == keydata) {
- ret = __os_malloc(dbenv, key.size, NULL,
- &replyp->keydata.keydata_val);
- if (ret != 0) {
- __os_free(key.data, key.size);
- __os_free(data.data, data.size);
- goto err;
- }
- key_alloc = 1;
- memcpy(replyp->keydata.keydata_val, key.data, key.size);
- } else
- replyp->keydata.keydata_val = key.data;
-
- replyp->keydata.keydata_len = key.size;
-
- /*
- * Data
- */
- if (data.data == datadata) {
- ret = __os_malloc(dbenv, data.size, NULL,
- &replyp->datadata.datadata_val);
- if (ret != 0) {
- __os_free(key.data, key.size);
- __os_free(data.data, data.size);
- if (key_alloc)
- __os_free(replyp->keydata.keydata_val,
- key.size);
- goto err;
- }
- memcpy(replyp->datadata.datadata_val, data.data,
- data.size);
- } else
- replyp->datadata.datadata_val = data.data;
- replyp->datadata.datadata_len = data.size;
- } else {
-err: replyp->keydata.keydata_val = NULL;
- replyp->keydata.keydata_len = 0;
- replyp->datadata.datadata_val = NULL;
- replyp->datadata.datadata_len = 0;
- *freep = 0;
- }
- replyp->status = ret;
- return;
-}
-
-/* BEGIN __dbc_put_1_proc */
-void
-__dbc_put_1_proc(dbccl_id, keydlen, keydoff,
- keyflags, keydata, keysize, datadlen,
- datadoff, dataflags, datadata, datasize,
- flags, replyp, freep)
- long dbccl_id;
- u_int32_t keydlen;
- u_int32_t keydoff;
- u_int32_t keyflags;
- void *keydata;
- u_int32_t keysize;
- u_int32_t datadlen;
- u_int32_t datadoff;
- u_int32_t dataflags;
- void *datadata;
- u_int32_t datasize;
- u_int32_t flags;
- __dbc_put_reply *replyp;
- int * freep;
-/* END __dbc_put_1_proc */
-{
- int ret;
- DBC * dbc;
- DB *dbp;
- ct_entry *dbc_ctp;
- DBT key, data;
-
- ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
- dbc = (DBC *)dbc_ctp->ct_anyp;
- dbp = (DB *)dbc_ctp->ct_parent->ct_anyp;
-
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
-
- /* Set up key and data DBT */
- key.dlen = keydlen;
- key.doff = keydoff;
- /*
- * Ignore memory related flags on server.
- */
- key.flags = 0;
- if (keyflags & DB_DBT_PARTIAL)
- key.flags |= DB_DBT_PARTIAL;
- key.size = keysize;
- key.data = keydata;
-
- data.dlen = datadlen;
- data.doff = datadoff;
- data.flags = dataflags;
- data.size = datasize;
- data.data = datadata;
-
- /* Got all our stuff, now do the put */
- ret = dbc->c_put(dbc, &key, &data, flags);
-
- *freep = 0;
- if (ret == 0 && (flags == DB_AFTER || flags == DB_BEFORE) &&
- dbp->type == DB_RECNO) {
- /*
- * We need to xdr_free whatever we are returning, next time.
- */
- replyp->keydata.keydata_val = key.data;
- replyp->keydata.keydata_len = key.size;
- } else {
- replyp->keydata.keydata_val = NULL;
- replyp->keydata.keydata_len = 0;
- }
- replyp->status = ret;
- return;
-}
-#endif /* HAVE_RPC */
diff --git a/bdb/rpc_server/db_server_svc.sed b/bdb/rpc_server/db_server_svc.sed
deleted file mode 100644
index 9d540e51af6..00000000000
--- a/bdb/rpc_server/db_server_svc.sed
+++ /dev/null
@@ -1,5 +0,0 @@
-/^#include <netinet.in.h>/a\
-\extern void __dbsrv_timeout();
-/^ return;/i\
-\ __dbsrv_timeout(0);
-s/^main/void __dbsrv_main/
diff --git a/bdb/rpc_server/db_server_util.c b/bdb/rpc_server/db_server_util.c
deleted file mode 100644
index 862bbd05efb..00000000000
--- a/bdb/rpc_server/db_server_util.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 2000
- * Sleepycat Software. All rights reserved.
- */
-
-#include "db_config.h"
-
-#ifndef lint
-static const char revid[] = "$Id: db_server_util.c,v 1.32 2001/01/18 18:36:59 bostic Exp $";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-#include <rpc/rpc.h>
-
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#endif
-#include "db_server.h"
-
-#include "db_int.h"
-#include "clib_ext.h"
-#include "db_server_int.h"
-#include "rpc_server_ext.h"
-#include "common_ext.h"
-
-extern int __dbsrv_main __P((void));
-static int add_home __P((char *));
-static int env_recover __P((char *));
-static void __dbclear_child __P((ct_entry *));
-
-static LIST_HEAD(cthead, ct_entry) __dbsrv_head;
-static LIST_HEAD(homehead, home_entry) __dbsrv_home;
-static long __dbsrv_defto = DB_SERVER_TIMEOUT;
-static long __dbsrv_maxto = DB_SERVER_MAXTIMEOUT;
-static long __dbsrv_idleto = DB_SERVER_IDLETIMEOUT;
-static char *logfile = NULL;
-static char *prog;
-
-static void usage __P((char *));
-static void version_check __P((void));
-
-int __dbsrv_verbose = 0;
-
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- extern char *optarg;
- extern int optind;
- CLIENT *cl;
- int ch, ret;
-
- prog = argv[0];
-
- version_check();
-
- /*
- * Check whether another server is running or not. There
- * is a race condition where two servers could be racing to
- * register with the portmapper. The goal of this check is to
- * forbid running additional servers (like those started from
- * the test suite) if the user is already running one.
- *
- * XXX
- * This does not solve nor prevent two servers from being
- * started at the same time and running recovery at the same
- * time on the same environments.
- */
- if ((cl = clnt_create("localhost",
- DB_SERVERPROG, DB_SERVERVERS, "tcp")) != NULL) {
- fprintf(stderr,
- "%s: Berkeley DB RPC server already running.\n", prog);
- clnt_destroy(cl);
- exit(1);
- }
-
- LIST_INIT(&__dbsrv_home);
- while ((ch = getopt(argc, argv, "h:I:L:t:T:Vv")) != EOF)
- switch (ch) {
- case 'h':
- (void)add_home(optarg);
- break;
- case 'I':
- (void)__db_getlong(NULL, prog, optarg, 1,
- LONG_MAX, &__dbsrv_idleto);
- break;
- case 'L':
- logfile = optarg;
- break;
- case 't':
- (void)__db_getlong(NULL, prog, optarg, 1,
- LONG_MAX, &__dbsrv_defto);
- break;
- case 'T':
- (void)__db_getlong(NULL, prog, optarg, 1,
- LONG_MAX, &__dbsrv_maxto);
- break;
- case 'V':
- printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
- case 'v':
- __dbsrv_verbose = 1;
- break;
- default:
- usage(prog);
- }
- /*
- * Check default timeout against maximum timeout
- */
- if (__dbsrv_defto > __dbsrv_maxto)
- __dbsrv_defto = __dbsrv_maxto;
-
- /*
- * Check default timeout against idle timeout
- * It would be bad to timeout environments sooner than txns.
- */
- if (__dbsrv_defto > __dbsrv_idleto)
-printf("%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
- prog, __dbsrv_idleto, __dbsrv_defto);
-
- LIST_INIT(&__dbsrv_head);
-
- /*
- * If a client crashes during an RPC, our reply to it
- * generates a SIGPIPE. Ignore SIGPIPE so we don't exit unnecessarily.
- */
-#ifdef SIGPIPE
- signal(SIGPIPE, SIG_IGN);
-#endif
-
- if (logfile != NULL && __db_util_logset("berkeley_db_svc", logfile))
- exit(1);
-
- /*
- * Now that we are ready to start, run recovery on all the
- * environments specified.
- */
- if ((ret = env_recover(prog)) != 0)
- exit(1);
-
- /*
- * We've done our setup, now call the generated server loop
- */
- if (__dbsrv_verbose)
- printf("%s: Ready to receive requests\n", prog);
- __dbsrv_main();
-
- /* NOTREACHED */
- abort();
-}
-
-static void
-usage(prog)
- char *prog;
-{
- fprintf(stderr, "usage: %s %s\n\t%s\n", prog,
- "[-Vv] [-h home]",
- "[-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
- exit(1);
-}
-
-static void
-version_check()
-{
- int v_major, v_minor, v_patch;
-
- /* Make sure we're loaded with the right version of the DB library. */
- (void)db_version(&v_major, &v_minor, &v_patch);
- if (v_major != DB_VERSION_MAJOR ||
- v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
- fprintf(stderr,
- "%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
- prog, DB_VERSION_MAJOR, DB_VERSION_MINOR,
- DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
- }
-}
-
-/*
- * PUBLIC: void __dbsrv_settimeout __P((ct_entry *, u_int32_t));
- */
-void
-__dbsrv_settimeout(ctp, to)
- ct_entry *ctp;
- u_int32_t to;
-{
- if (to > (u_int32_t)__dbsrv_maxto)
- ctp->ct_timeout = __dbsrv_maxto;
- else if (to <= 0)
- ctp->ct_timeout = __dbsrv_defto;
- else
- ctp->ct_timeout = to;
-}
-
-/*
- * PUBLIC: void __dbsrv_timeout __P((int));
- */
-void
-__dbsrv_timeout(force)
- int force;
-{
- static long to_hint = -1;
- DBC *dbcp;
- time_t t;
- long to;
- ct_entry *ctp, *nextctp;
-
- if ((t = time(NULL)) == -1)
- return;
-
- /*
- * Check hint. If hint is further in the future
- * than now, no work to do.
- */
- if (!force && to_hint > 0 && t < to_hint)
- return;
- to_hint = -1;
- /*
- * Timeout transactions or cursors holding DB resources.
- * Do this before timing out envs to properly release resources.
- *
- * !!!
- * We can just loop through this list looking for cursors and txns.
- * We do not need to verify txn and cursor relationships at this
- * point because we maintain the list in LIFO order *and* we
- * maintain activity in the ultimate txn parent of any cursor
- * so either everything in a txn is timing out, or nothing.
- * So, since we are LIFO, we will correctly close/abort all the
- * appropriate handles, in the correct order.
- */
- for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
- nextctp = LIST_NEXT(ctp, entries);
- switch (ctp->ct_type) {
- case CT_TXN:
- to = *(ctp->ct_activep) + ctp->ct_timeout;
- /* TIMEOUT */
- if (to < t) {
- if (__dbsrv_verbose)
- printf("Timing out txn id %ld\n",
- ctp->ct_id);
- (void)txn_abort((DB_TXN *)ctp->ct_anyp);
- __dbdel_ctp(ctp);
- /*
- * If we timed out an txn, we may have closed
- * all sorts of ctp's.
- * So start over with a guaranteed good ctp.
- */
- nextctp = LIST_FIRST(&__dbsrv_head);
- } else if ((to_hint > 0 && to_hint > to) ||
- to_hint == -1)
- to_hint = to;
- break;
- case CT_CURSOR:
- case (CT_JOINCUR | CT_CURSOR):
- to = *(ctp->ct_activep) + ctp->ct_timeout;
- /* TIMEOUT */
- if (to < t) {
- if (__dbsrv_verbose)
- printf("Timing out cursor %ld\n",
- ctp->ct_id);
- dbcp = (DBC *)ctp->ct_anyp;
- (void)__dbc_close_int(ctp);
- /*
- * Start over with a guaranteed good ctp.
- */
- nextctp = LIST_FIRST(&__dbsrv_head);
- } else if ((to_hint > 0 && to_hint > to) ||
- to_hint == -1)
- to_hint = to;
- break;
- default:
- break;
- }
- }
- /*
- * Timeout idle handles.
- * If we are forcing a timeout, we'll close all env handles.
- */
- for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
- nextctp = LIST_NEXT(ctp, entries);
- if (ctp->ct_type != CT_ENV)
- continue;
- to = *(ctp->ct_activep) + ctp->ct_idle;
- /* TIMEOUT */
- if (to < t || force) {
- if (__dbsrv_verbose)
- printf("Timing out env id %ld\n", ctp->ct_id);
- (void)__dbenv_close_int(ctp->ct_id, 0);
- /*
- * If we timed out an env, we may have closed
- * all sorts of ctp's (maybe even all of them.
- * So start over with a guaranteed good ctp.
- */
- nextctp = LIST_FIRST(&__dbsrv_head);
- }
- }
-}
-
-/*
- * RECURSIVE FUNCTION. We need to clear/free any number of levels of nested
- * layers.
- */
-static void
-__dbclear_child(parent)
- ct_entry *parent;
-{
- ct_entry *ctp, *nextctp;
-
- for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
- ctp = nextctp) {
- nextctp = LIST_NEXT(ctp, entries);
- if (ctp->ct_type == 0)
- continue;
- if (ctp->ct_parent == parent) {
- __dbclear_child(ctp);
- /*
- * Need to do this here because le_next may
- * have changed with the recursive call and we
- * don't want to point to a removed entry.
- */
- nextctp = LIST_NEXT(ctp, entries);
- __dbclear_ctp(ctp);
- }
- }
-}
-
-/*
- * PUBLIC: void __dbclear_ctp __P((ct_entry *));
- */
-void
-__dbclear_ctp(ctp)
- ct_entry *ctp;
-{
- LIST_REMOVE(ctp, entries);
- __os_free(ctp, sizeof(ct_entry));
-}
-
-/*
- * PUBLIC: void __dbdel_ctp __P((ct_entry *));
- */
-void
-__dbdel_ctp(parent)
- ct_entry *parent;
-{
- __dbclear_child(parent);
- __dbclear_ctp(parent);
-}
-
-/*
- * PUBLIC: ct_entry *new_ct_ent __P((u_int32_t *));
- */
-ct_entry *
-new_ct_ent(errp)
- u_int32_t *errp;
-{
- time_t t;
- ct_entry *ctp, *octp;
- int ret;
-
- if ((ret = __os_malloc(NULL, sizeof(ct_entry), NULL, &ctp)) != 0) {
- *errp = ret;
- return (NULL);
- }
- /*
- * Get the time as ID. We may service more than one request per
- * second however. If we are, then increment id value until we
- * find an unused one. We insert entries in LRU fashion at the
- * head of the list. So, if the first entry doesn't match, then
- * we know for certain that we can use our entry.
- */
- if ((t = time(NULL)) == -1) {
- *errp = t;
- __os_free(ctp, sizeof(ct_entry));
- return (NULL);
- }
- octp = LIST_FIRST(&__dbsrv_head);
- if (octp != NULL && octp->ct_id >= t)
- t = octp->ct_id + 1;
- ctp->ct_id = t;
- ctp->ct_idle = __dbsrv_idleto;
- ctp->ct_activep = &ctp->ct_active;
- ctp->ct_origp = NULL;
-
- LIST_INSERT_HEAD(&__dbsrv_head, ctp, entries);
- return (ctp);
-}
-
-/*
- * PUBLIC: ct_entry *get_tableent __P((long));
- */
-ct_entry *
-get_tableent(id)
- long id;
-{
- ct_entry *ctp;
-
- for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
- ctp = LIST_NEXT(ctp, entries))
- if (ctp->ct_id == id)
- return (ctp);
- return (NULL);
-}
-
-/*
- * PUBLIC: void __dbsrv_active __P((ct_entry *));
- */
-void
-__dbsrv_active(ctp)
- ct_entry *ctp;
-{
- time_t t;
- ct_entry *envctp;
-
- if (ctp == NULL)
- return;
- if ((t = time(NULL)) == -1)
- return;
- *(ctp->ct_activep) = t;
- if ((envctp = ctp->ct_envparent) == NULL)
- return;
- *(envctp->ct_activep) = t;
- return;
-}
-
-/*
- * PUBLIC: int __dbc_close_int __P((ct_entry *));
- */
-int
-__dbc_close_int(dbc_ctp)
- ct_entry *dbc_ctp;
-{
- DBC *dbc;
- int ret;
- ct_entry *ctp;
-
- dbc = (DBC *)dbc_ctp->ct_anyp;
-
- ret = dbc->c_close(dbc);
- /*
- * If this cursor is a join cursor then we need to fix up the
- * cursors that it was joined from so that they are independent again.
- */
- if (dbc_ctp->ct_type & CT_JOINCUR)
- for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
- ctp = LIST_NEXT(ctp, entries)) {
- /*
- * Test if it is a join cursor, and if it is part
- * of this one.
- */
- if ((ctp->ct_type & CT_JOIN) &&
- ctp->ct_activep == &dbc_ctp->ct_active) {
- ctp->ct_type &= ~CT_JOIN;
- ctp->ct_activep = ctp->ct_origp;
- __dbsrv_active(ctp);
- }
- }
- __dbclear_ctp(dbc_ctp);
- return (ret);
-
-}
-
-/*
- * PUBLIC: int __dbenv_close_int __P((long, int));
- */
-int
-__dbenv_close_int(id, flags)
- long id;
- int flags;
-{
- DB_ENV *dbenv;
- int ret;
- ct_entry *ctp;
-
- ctp = get_tableent(id);
- if (ctp == NULL)
- return (DB_NOSERVER_ID);
- DB_ASSERT(ctp->ct_type == CT_ENV);
- dbenv = ctp->ct_envp;
-
- ret = dbenv->close(dbenv, flags);
- __dbdel_ctp(ctp);
- return (ret);
-}
-
-static int
-add_home(home)
- char *home;
-{
- home_entry *hp, *homep;
- int ret;
-
- if ((ret = __os_malloc(NULL, sizeof(home_entry), NULL, &hp)) != 0)
- return (ret);
- if ((ret = __os_malloc(NULL, strlen(home)+1, NULL, &hp->home)) != 0)
- return (ret);
- memcpy(hp->home, home, strlen(home)+1);
- hp->dir = home;
- /*
- * This loop is to remove any trailing path separators,
- * to assure hp->name points to the last component.
- */
- hp->name = __db_rpath(home);
- *(hp->name) = '\0';
- hp->name++;
- while (*(hp->name) == '\0') {
- hp->name = __db_rpath(home);
- *(hp->name) = '\0';
- hp->name++;
- }
- /*
- * Now we have successfully added it. Make sure there are no
- * identical names.
- */
- for (homep = LIST_FIRST(&__dbsrv_home); homep != NULL;
- homep = LIST_NEXT(homep, entries))
- if (strcmp(homep->name, hp->name) == 0) {
- printf("Already added home name %s, at directory %s\n",
- hp->name, homep->dir);
- return (-1);
- }
- LIST_INSERT_HEAD(&__dbsrv_home, hp, entries);
- if (__dbsrv_verbose)
- printf("Added home %s in dir %s\n", hp->name, hp->dir);
- return (0);
-}
-
-/*
- * PUBLIC: char *get_home __P((char *));
- */
-char *
-get_home(name)
- char *name;
-{
- home_entry *hp;
-
- for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
- hp = LIST_NEXT(hp, entries))
- if (strcmp(name, hp->name) == 0)
- return (hp->home);
- return (NULL);
-}
-
-static int
-env_recover(progname)
- char *progname;
-{
- DB_ENV *dbenv;
- home_entry *hp;
- u_int32_t flags;
- int exitval, ret;
-
- for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
- hp = LIST_NEXT(hp, entries)) {
- exitval = 0;
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
- fprintf(stderr, "%s: db_env_create: %s\n",
- progname, db_strerror(ret));
- exit(1);
- }
- if (__dbsrv_verbose == 1) {
- (void)dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
- (void)dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
- }
- dbenv->set_errfile(dbenv, stderr);
- dbenv->set_errpfx(dbenv, progname);
-
- /*
- * Initialize the env with DB_RECOVER. That is all we
- * have to do to run recovery.
- */
- if (__dbsrv_verbose)
- printf("Running recovery on %s\n", hp->home);
- flags = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
- DB_INIT_TXN | DB_PRIVATE | DB_USE_ENVIRON | DB_RECOVER;
- if ((ret = dbenv->open(dbenv, hp->home, flags, 0)) != 0) {
- dbenv->err(dbenv, ret, "DBENV->open");
- goto error;
- }
-
- if (0) {
-error: exitval = 1;
- }
- if ((ret = dbenv->close(dbenv, 0)) != 0) {
- exitval = 1;
- fprintf(stderr, "%s: dbenv->close: %s\n",
- progname, db_strerror(ret));
- }
- if (exitval)
- return (exitval);
- }
- return (0);
-}
diff --git a/bdb/rpc_server/java/DbDispatcher.java b/bdb/rpc_server/java/DbDispatcher.java
new file mode 100644
index 00000000000..5c5e63fc2ad
--- /dev/null
+++ b/bdb/rpc_server/java/DbDispatcher.java
@@ -0,0 +1,590 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbDispatcher.java,v 1.5 2002/08/09 01:56:08 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import com.sleepycat.db.*;
+import java.io.IOException;
+import org.acplt.oncrpc.OncRpcException;
+
+/**
+ * Dispatcher for RPC messages for the Java RPC server.
+ * These are hooks that translate between RPC msg/reply structures and
+ * DB calls, which keeps the real implementation code in Rpc* classes cleaner.
+ */
+public abstract class DbDispatcher extends DbServerStub
+{
+ abstract int addEnv(RpcDbEnv rdbenv);
+ abstract int addDb(RpcDb rdb);
+ abstract int addTxn(RpcDbTxn rtxn);
+ abstract int addCursor(RpcDbc rdbc);
+ abstract void delEnv(RpcDbEnv rdbenv);
+ abstract void delDb(RpcDb rdb);
+ abstract void delTxn(RpcDbTxn rtxn);
+ abstract void delCursor(RpcDbc rdbc);
+ abstract RpcDbEnv getEnv(int envid);
+ abstract RpcDb getDb(int dbid);
+ abstract RpcDbTxn getTxn(int txnbid);
+ abstract RpcDbc getCursor(int dbcid);
+
+ public DbDispatcher() throws IOException, OncRpcException
+ {
+ super();
+ }
+
+ //// Db methods
+
+ public __db_associate_reply __DB_db_associate_4001(__db_associate_msg args)
+ {
+ __db_associate_reply reply = new __db_associate_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.associate(this, args, reply);
+ return reply;
+ }
+
+ public __db_bt_maxkey_reply __DB_db_bt_maxkey_4001(__db_bt_maxkey_msg args)
+ {
+ __db_bt_maxkey_reply reply = new __db_bt_maxkey_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_bt_maxkey(this, args, reply);
+ return reply;
+ }
+
+ public __db_bt_minkey_reply __DB_db_bt_minkey_4001(__db_bt_minkey_msg args)
+ {
+ __db_bt_minkey_reply reply = new __db_bt_minkey_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_bt_minkey(this, args, reply);
+ return reply;
+ }
+
+ public __db_close_reply __DB_db_close_4001(__db_close_msg args)
+ {
+ __db_close_reply reply = new __db_close_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.close(this, args, reply);
+ return reply;
+ }
+
+ public __db_create_reply __DB_db_create_4001(__db_create_msg args)
+ {
+ __db_create_reply reply = new __db_create_reply();
+ RpcDb rdb = new RpcDb(getEnv(args.dbenvcl_id));
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.create(this, args, reply);
+ return reply;
+ }
+
+ public __db_cursor_reply __DB_db_cursor_4001(__db_cursor_msg args)
+ {
+ __db_cursor_reply reply = new __db_cursor_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.cursor(this, args, reply);
+ return reply;
+ }
+
+ public __db_del_reply __DB_db_del_4001(__db_del_msg args)
+ {
+ __db_del_reply reply = new __db_del_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.del(this, args, reply);
+ return reply;
+ }
+
+ public __db_encrypt_reply __DB_db_encrypt_4001(__db_encrypt_msg args)
+ {
+ __db_encrypt_reply reply = new __db_encrypt_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_encrypt(this, args, reply);
+ return reply;
+ }
+
+ public __db_extentsize_reply __DB_db_extentsize_4001(__db_extentsize_msg args)
+ {
+ __db_extentsize_reply reply = new __db_extentsize_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_q_extentsize(this, args, reply);
+ return reply;
+ }
+
+ public __db_flags_reply __DB_db_flags_4001(__db_flags_msg args)
+ {
+ __db_flags_reply reply = new __db_flags_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_flags(this, args, reply);
+ return reply;
+ }
+
+ public __db_get_reply __DB_db_get_4001(__db_get_msg args)
+ {
+ __db_get_reply reply = new __db_get_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.get(this, args, reply);
+ return reply;
+ }
+
+ public __db_h_ffactor_reply __DB_db_h_ffactor_4001(__db_h_ffactor_msg args)
+ {
+ __db_h_ffactor_reply reply = new __db_h_ffactor_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_h_ffactor(this, args, reply);
+ return reply;
+ }
+
+ public __db_h_nelem_reply __DB_db_h_nelem_4001(__db_h_nelem_msg args)
+ {
+ __db_h_nelem_reply reply = new __db_h_nelem_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_h_nelem(this, args, reply);
+ return reply;
+ }
+
+ public __db_join_reply __DB_db_join_4001(__db_join_msg args)
+ {
+ __db_join_reply reply = new __db_join_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.join(this, args, reply);
+ return reply;
+ }
+
+ public __db_key_range_reply __DB_db_key_range_4001(__db_key_range_msg args)
+ {
+ __db_key_range_reply reply = new __db_key_range_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.key_range(this, args, reply);
+ return reply;
+ }
+
+ public __db_lorder_reply __DB_db_lorder_4001(__db_lorder_msg args)
+ {
+ __db_lorder_reply reply = new __db_lorder_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_lorder(this, args, reply);
+ return reply;
+ }
+
+ public __db_open_reply __DB_db_open_4001(__db_open_msg args)
+ {
+ __db_open_reply reply = new __db_open_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.open(this, args, reply);
+ return reply;
+ }
+
+ public __db_pagesize_reply __DB_db_pagesize_4001(__db_pagesize_msg args)
+ {
+ __db_pagesize_reply reply = new __db_pagesize_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_pagesize(this, args, reply);
+ return reply;
+ }
+
+ public __db_pget_reply __DB_db_pget_4001(__db_pget_msg args)
+ {
+ __db_pget_reply reply = new __db_pget_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.pget(this, args, reply);
+ return reply;
+ }
+
+ public __db_put_reply __DB_db_put_4001(__db_put_msg args)
+ {
+ __db_put_reply reply = new __db_put_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.put(this, args, reply);
+ return reply;
+ }
+
+ public __db_remove_reply __DB_db_remove_4001(__db_remove_msg args)
+ {
+ __db_remove_reply reply = new __db_remove_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.remove(this, args, reply);
+ return reply;
+ }
+
+ public __db_rename_reply __DB_db_rename_4001(__db_rename_msg args)
+ {
+ __db_rename_reply reply = new __db_rename_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.rename(this, args, reply);
+ return reply;
+ }
+
+ public __db_re_delim_reply __DB_db_re_delim_4001(__db_re_delim_msg args)
+ {
+ __db_re_delim_reply reply = new __db_re_delim_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_re_delim(this, args, reply);
+ return reply;
+ }
+
+ public __db_re_len_reply __DB_db_re_len_4001(__db_re_len_msg args)
+ {
+ __db_re_len_reply reply = new __db_re_len_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_re_len(this, args, reply);
+ return reply;
+ }
+
+ public __db_re_pad_reply __DB_db_re_pad_4001(__db_re_pad_msg args)
+ {
+ __db_re_pad_reply reply = new __db_re_pad_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.set_re_pad(this, args, reply);
+ return reply;
+ }
+
+ public __db_stat_reply __DB_db_stat_4001(__db_stat_msg args)
+ {
+ __db_stat_reply reply = new __db_stat_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.stat(this, args, reply);
+ return reply;
+ }
+
+ public __db_sync_reply __DB_db_sync_4001(__db_sync_msg args)
+ {
+ __db_sync_reply reply = new __db_sync_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.sync(this, args, reply);
+ return reply;
+ }
+
+ public __db_truncate_reply __DB_db_truncate_4001(__db_truncate_msg args)
+ {
+ __db_truncate_reply reply = new __db_truncate_reply();
+ RpcDb rdb = getDb(args.dbpcl_id);
+ if (rdb == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdb.truncate(this, args, reply);
+ return reply;
+ }
+
+ //// Cursor methods
+
+ public __dbc_close_reply __DB_dbc_close_4001(__dbc_close_msg args)
+ {
+ __dbc_close_reply reply = new __dbc_close_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.close(this, args, reply);
+ return reply;
+ }
+
+ public __dbc_count_reply __DB_dbc_count_4001(__dbc_count_msg args)
+ {
+ __dbc_count_reply reply = new __dbc_count_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.count(this, args, reply);
+ return reply;
+ }
+
+ public __dbc_del_reply __DB_dbc_del_4001(__dbc_del_msg args)
+ {
+ __dbc_del_reply reply = new __dbc_del_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.del(this, args, reply);
+ return reply;
+ }
+
+ public __dbc_dup_reply __DB_dbc_dup_4001(__dbc_dup_msg args)
+ {
+ __dbc_dup_reply reply = new __dbc_dup_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.dup(this, args, reply);
+ return reply;
+ }
+
+ public __dbc_get_reply __DB_dbc_get_4001(__dbc_get_msg args)
+ {
+ __dbc_get_reply reply = new __dbc_get_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.get(this, args, reply);
+ return reply;
+ }
+
+ public __dbc_pget_reply __DB_dbc_pget_4001(__dbc_pget_msg args) {
+ __dbc_pget_reply reply = new __dbc_pget_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.pget(this, args, reply);
+ return reply;
+ }
+
+ public __dbc_put_reply __DB_dbc_put_4001(__dbc_put_msg args) {
+ __dbc_put_reply reply = new __dbc_put_reply();
+ RpcDbc rdbc = getCursor(args.dbccl_id);
+ if (rdbc == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbc.put(this, args, reply);
+ return reply;
+ }
+
+ //// Environment methods
+
+ public __env_cachesize_reply __DB_env_cachesize_4001(__env_cachesize_msg args)
+ {
+ __env_cachesize_reply reply = new __env_cachesize_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.set_cachesize(this, args, reply);
+ return reply;
+ }
+
+ public __env_close_reply __DB_env_close_4001(__env_close_msg args)
+ {
+ __env_close_reply reply = new __env_close_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.close(this, args, reply);
+ return reply;
+ }
+
+ public __env_create_reply __DB_env_create_4001(__env_create_msg args)
+ {
+ __env_create_reply reply = new __env_create_reply();
+ RpcDbEnv rdbenv = new RpcDbEnv();
+ rdbenv.create(this, args, reply);
+ return reply;
+ }
+
+ public __env_dbremove_reply __DB_env_dbremove_4001(__env_dbremove_msg args)
+ {
+ __env_dbremove_reply reply = new __env_dbremove_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.dbremove(this, args, reply);
+ return reply;
+ }
+
+ public __env_dbrename_reply __DB_env_dbrename_4001(__env_dbrename_msg args)
+ {
+ __env_dbrename_reply reply = new __env_dbrename_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.dbrename(this, args, reply);
+ return reply;
+ }
+
+ public __env_encrypt_reply __DB_env_encrypt_4001(__env_encrypt_msg args)
+ {
+ __env_encrypt_reply reply = new __env_encrypt_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.set_encrypt(this, args, reply);
+ return reply;
+ }
+
+ public __env_flags_reply __DB_env_flags_4001(__env_flags_msg args)
+ {
+ __env_flags_reply reply = new __env_flags_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.set_flags(this, args, reply);
+ return reply;
+ }
+
+ public __env_open_reply __DB_env_open_4001(__env_open_msg args)
+ {
+ __env_open_reply reply = new __env_open_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.open(this, args, reply);
+ return reply;
+ }
+
+ public __env_remove_reply __DB_env_remove_4001(__env_remove_msg args)
+ {
+ __env_remove_reply reply = new __env_remove_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.remove(this, args, reply);
+ return reply;
+ }
+
+ //// Transaction methods
+
+ public __txn_abort_reply __DB_txn_abort_4001(__txn_abort_msg args)
+ {
+ __txn_abort_reply reply = new __txn_abort_reply();
+ RpcDbTxn rdbtxn = getTxn(args.txnpcl_id);
+ if (rdbtxn == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbtxn.abort(this, args, reply);
+ return reply;
+ }
+
+ public __txn_begin_reply __DB_txn_begin_4001(__txn_begin_msg args)
+ {
+ __txn_begin_reply reply = new __txn_begin_reply();
+ RpcDbTxn rdbtxn = new RpcDbTxn(getEnv(args.dbenvcl_id), null);
+ rdbtxn.begin(this, args, reply);
+ return reply;
+ }
+
+ public __txn_commit_reply __DB_txn_commit_4001(__txn_commit_msg args)
+ {
+ __txn_commit_reply reply = new __txn_commit_reply();
+ RpcDbTxn rdbtxn = getTxn(args.txnpcl_id);
+ if (rdbtxn == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbtxn.commit(this, args, reply);
+ return reply;
+ }
+
+ public __txn_discard_reply __DB_txn_discard_4001(__txn_discard_msg args)
+ {
+ __txn_discard_reply reply = new __txn_discard_reply();
+ RpcDbTxn rdbtxn = getTxn(args.txnpcl_id);
+ if (rdbtxn == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbtxn.discard(this, args, reply);
+ return reply;
+ }
+
+ public __txn_prepare_reply __DB_txn_prepare_4001(__txn_prepare_msg args)
+ {
+ __txn_prepare_reply reply = new __txn_prepare_reply();
+ RpcDbTxn rdbtxn = getTxn(args.txnpcl_id);
+ if (rdbtxn == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbtxn.prepare(this, args, reply);
+ return reply;
+ }
+
+ public __txn_recover_reply __DB_txn_recover_4001(__txn_recover_msg args)
+ {
+ __txn_recover_reply reply = new __txn_recover_reply();
+ RpcDbEnv rdbenv = getEnv(args.dbenvcl_id);
+ if (rdbenv == null)
+ reply.status = Db.DB_NOSERVER_ID;
+ else
+ rdbenv.txn_recover(this, args, reply);
+ return reply;
+ }
+}
diff --git a/bdb/rpc_server/java/DbServer.java b/bdb/rpc_server/java/DbServer.java
new file mode 100644
index 00000000000..9b20becbcdc
--- /dev/null
+++ b/bdb/rpc_server/java/DbServer.java
@@ -0,0 +1,301 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: DbServer.java,v 1.5 2002/08/09 01:56:09 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import com.sleepycat.db.*;
+import java.io.*;
+import java.util.*;
+import org.acplt.oncrpc.OncRpcException;
+import org.acplt.oncrpc.server.OncRpcCallInformation;
+
+/**
+ * Main entry point for the Java version of the Berkeley DB RPC server
+ */
+public class DbServer extends DbDispatcher
+{
+ public static long idleto = 10 * 60 * 1000; // 5 minutes
+ public static long defto = 5 * 60 * 1000; // 5 minutes
+ public static long maxto = 60 * 60 * 1000; // 1 hour
+ public static String passwd = null;
+ public static PrintWriter err;
+
+ long now, hint; // updated each operation
+ FreeList env_list = new FreeList();
+ FreeList db_list = new FreeList();
+ FreeList txn_list = new FreeList();
+ FreeList cursor_list = new FreeList();
+
+ public DbServer() throws IOException, OncRpcException
+ {
+ super();
+ init_lists();
+ }
+
+ public void dispatchOncRpcCall(OncRpcCallInformation call, int program,
+ int version, int procedure) throws OncRpcException, IOException
+ {
+ long newnow = System.currentTimeMillis();
+ // DbServer.err.println("Dispatching RPC call " + procedure + " after delay of " + (newnow - now));
+ now = newnow;
+ // DbServer.err.flush();
+ super.dispatchOncRpcCall(call, program, version, procedure);
+
+ try {
+ doTimeouts();
+ } catch(Throwable t) {
+ System.err.println("Caught " + t + " during doTimeouts()");
+ t.printStackTrace(System.err);
+ }
+ }
+
+ // Internal methods to track context
+ private void init_lists()
+ {
+ // We do this so that getEnv/Db/etc(0) == null
+ env_list.add(null);
+ db_list.add(null);
+ txn_list.add(null);
+ cursor_list.add(null);
+ }
+
+ int addEnv(RpcDbEnv rdbenv)
+ {
+ rdbenv.timer.last_access = now;
+ int id = env_list.add(rdbenv);
+ return id;
+ }
+
+ int addDb(RpcDb rdb)
+ {
+ int id = db_list.add(rdb);
+ return id;
+ }
+
+ int addTxn(RpcDbTxn rtxn)
+ {
+ rtxn.timer.last_access = now;
+ int id = txn_list.add(rtxn);
+ return id;
+ }
+
+ int addCursor(RpcDbc rdbc)
+ {
+ rdbc.timer.last_access = now;
+ int id = cursor_list.add(rdbc);
+ return id;
+ }
+
+ void delEnv(RpcDbEnv rdbenv)
+ {
+ // cursors and transactions will already have been cleaned up
+ for(LocalIterator i = db_list.iterator(); i.hasNext(); ) {
+ RpcDb rdb = (RpcDb)i.next();
+ if (rdb != null && rdb.rdbenv == rdbenv)
+ delDb(rdb);
+ }
+
+ env_list.del(rdbenv);
+ rdbenv.dispose();
+ }
+
+ void delDb(RpcDb rdb)
+ {
+ db_list.del(rdb);
+ rdb.dispose();
+
+ for(LocalIterator i = cursor_list.iterator(); i.hasNext(); ) {
+ RpcDbc rdbc = (RpcDbc)i.next();
+ if (rdbc != null && rdbc.timer == rdb)
+ i.remove();
+ }
+ }
+
+ void delTxn(RpcDbTxn rtxn)
+ {
+ txn_list.del(rtxn);
+ rtxn.dispose();
+
+ for(LocalIterator i = cursor_list.iterator(); i.hasNext(); ) {
+ RpcDbc rdbc = (RpcDbc)i.next();
+ if (rdbc != null && rdbc.timer == rtxn)
+ i.remove();
+ }
+
+ for(LocalIterator i = txn_list.iterator(); i.hasNext(); ) {
+ RpcDbTxn rtxn_child = (RpcDbTxn)i.next();
+ if (rtxn_child != null && rtxn_child.timer == rtxn)
+ i.remove();
+ }
+ }
+
+ void delCursor(RpcDbc rdbc)
+ {
+ cursor_list.del(rdbc);
+ rdbc.dispose();
+ }
+
+ RpcDbEnv getEnv(int envid)
+ {
+ RpcDbEnv rdbenv = (RpcDbEnv)env_list.get(envid);
+ if (rdbenv != null)
+ rdbenv.timer.last_access = now;
+ return rdbenv;
+ }
+
+ RpcDb getDb(int dbid)
+ {
+ RpcDb rdb = (RpcDb)db_list.get(dbid);
+ if (rdb != null)
+ rdb.rdbenv.timer.last_access = now;
+ return rdb;
+ }
+
+ RpcDbTxn getTxn(int txnid)
+ {
+ RpcDbTxn rtxn = (RpcDbTxn)txn_list.get(txnid);
+ if (rtxn != null)
+ rtxn.timer.last_access = rtxn.rdbenv.timer.last_access = now;
+ return rtxn;
+ }
+
+ RpcDbc getCursor(int dbcid)
+ {
+ RpcDbc rdbc = (RpcDbc)cursor_list.get(dbcid);
+ if (rdbc != null)
+ rdbc.last_access = rdbc.timer.last_access = rdbc.rdbenv.timer.last_access = now;
+ return rdbc;
+ }
+
+ void doTimeouts()
+ {
+ if (now < hint) {
+ // DbServer.err.println("Skipping cleaner sweep - now = " + now + ", hint = " + hint);
+ return;
+ }
+
+ // DbServer.err.println("Starting a cleaner sweep");
+ hint = now + DbServer.maxto;
+
+ for(LocalIterator i = cursor_list.iterator(); i.hasNext(); ) {
+ RpcDbc rdbc = (RpcDbc)i.next();
+ if (rdbc == null)
+ continue;
+
+ long end_time = rdbc.timer.last_access + rdbc.rdbenv.timeout;
+ // DbServer.err.println("Examining " + rdbc + ", time left = " + (end_time - now));
+ if (end_time < now) {
+ DbServer.err.println("Cleaning up " + rdbc);
+ delCursor(rdbc);
+ } else if (end_time < hint)
+ hint = end_time;
+ }
+
+ for(LocalIterator i = txn_list.iterator(); i.hasNext(); ) {
+ RpcDbTxn rtxn = (RpcDbTxn)i.next();
+ if (rtxn == null)
+ continue;
+
+ long end_time = rtxn.timer.last_access + rtxn.rdbenv.timeout;
+ // DbServer.err.println("Examining " + rtxn + ", time left = " + (end_time - now));
+ if (end_time < now) {
+ DbServer.err.println("Cleaning up " + rtxn);
+ delTxn(rtxn);
+ } else if (end_time < hint)
+ hint = end_time;
+ }
+
+ for(LocalIterator i = env_list.iterator(); i.hasNext(); ) {
+ RpcDbEnv rdbenv = (RpcDbEnv)i.next();
+ if (rdbenv == null)
+ continue;
+
+ long end_time = rdbenv.timer.last_access + rdbenv.idletime;
+ // DbServer.err.println("Examining " + rdbenv + ", time left = " + (end_time - now));
+ if (end_time < now) {
+ DbServer.err.println("Cleaning up " + rdbenv);
+ delEnv(rdbenv);
+ }
+ }
+
+ // if we didn't find anything, reset the hint
+ if (hint == now + DbServer.maxto)
+ hint = 0;
+
+ // DbServer.err.println("Finishing a cleaner sweep");
+ }
+
+ // Some constants that aren't available elsewhere
+ static final int DB_SERVER_FLAGMASK = Db.DB_LOCKDOWN |
+ Db.DB_PRIVATE | Db.DB_RECOVER | Db.DB_RECOVER_FATAL |
+ Db.DB_SYSTEM_MEM | Db.DB_USE_ENVIRON |
+ Db.DB_USE_ENVIRON_ROOT;
+ static final int DB_SERVER_ENVFLAGS = Db.DB_INIT_CDB |
+ Db.DB_INIT_LOCK | Db.DB_INIT_LOG | Db.DB_INIT_MPOOL |
+ Db.DB_INIT_TXN | Db.DB_JOINENV;
+ static final int DB_SERVER_DBFLAGS = Db.DB_DIRTY_READ |
+ Db.DB_NOMMAP | Db.DB_RDONLY;
+ static final int DB_SERVER_DBNOSHARE = Db.DB_EXCL | Db.DB_TRUNCATE;
+
+ public static void main(String[] args)
+ {
+ System.out.println("Starting DbServer...");
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].charAt(0) != '-')
+ usage();
+
+ switch (args[i].charAt(1)) {
+ case 'h':
+ ++i; // add_home(args[++i]);
+ break;
+ case 'I':
+ idleto = Long.parseLong(args[++i]) * 1000L;
+ break;
+ case 'P':
+ passwd = args[++i];
+ break;
+ case 't':
+ defto = Long.parseLong(args[++i]) * 1000L;
+ break;
+ case 'T':
+ maxto = Long.parseLong(args[++i]) * 1000L;
+ break;
+ case 'V':
+ // version;
+ break;
+ case 'v':
+ // verbose
+ break;
+ default:
+ usage();
+ }
+ }
+
+ try {
+ DbServer.err = new PrintWriter(new FileOutputStream("JavaRPCServer.trace", true));
+ DbServer server = new DbServer();
+ server.run();
+ } catch (Throwable e) {
+ System.out.println("DbServer exception:");
+ e.printStackTrace(DbServer.err);
+ } finally {
+ if (DbServer.err != null)
+ DbServer.err.close();
+ }
+
+ System.out.println("DbServer stopped.");
+ }
+
+ static void usage()
+ {
+ System.err.println("usage: java com.sleepycat.db.rpcserver.DbServer \\");
+ System.err.println("[-Vv] [-h home] [-P passwd] [-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
+ System.exit(1);
+ }
+}
diff --git a/bdb/rpc_server/java/FreeList.java b/bdb/rpc_server/java/FreeList.java
new file mode 100644
index 00000000000..e831c466137
--- /dev/null
+++ b/bdb/rpc_server/java/FreeList.java
@@ -0,0 +1,102 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: FreeList.java,v 1.3 2002/08/09 01:56:09 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import java.util.*;
+
+/**
+ * Keep track of a list of objects by id with a free list.
+ * Intentionally package-protected exposure.
+ */
+class FreeList
+{
+ class FreeIndex {
+ int index;
+ FreeIndex(int index) { this.index = index; }
+ int getIndex() { return index; }
+ }
+
+ Vector items = new Vector();
+ FreeIndex free_head = null;
+
+ public synchronized int add(Object obj) {
+ int pos;
+ if (free_head == null) {
+ pos = items.size();
+ items.addElement(obj);
+ if (pos % 1000 == 0)
+ DbServer.err.println(this + " grew to size " + pos);
+ } else {
+ pos = free_head.getIndex();
+ free_head = (FreeIndex)items.elementAt(pos);
+ items.setElementAt(obj, pos);
+ }
+ return pos;
+ }
+
+ public synchronized void del(int pos) {
+ Object obj = items.elementAt(pos);
+ if (obj != null && obj instanceof FreeIndex)
+ throw new NoSuchElementException("index " + pos + " has already been freed");
+ items.setElementAt(free_head, pos);
+ free_head = new FreeIndex(pos);
+ }
+
+ public void del(Object obj) {
+ del(items.indexOf(obj));
+ }
+
+ public Object get(int pos) {
+ Object obj = items.elementAt(pos);
+ if (obj instanceof FreeIndex)
+ obj = null;
+ return obj;
+ }
+
+ public LocalIterator iterator() {
+ return new FreeListIterator();
+ }
+
+ /**
+ * Iterator for a FreeList. Note that this class doesn't implement
+ * java.util.Iterator to maintain compatibility with Java 1.1
+ * Intentionally package-protected exposure.
+ */
+ class FreeListIterator implements LocalIterator {
+ int current;
+
+ FreeListIterator() { current = findNext(-1); }
+
+ private int findNext(int start) {
+ int next = start;
+ while (++next < items.size()) {
+ Object obj = items.elementAt(next);
+ if (obj == null || !(obj instanceof FreeIndex))
+ break;
+ }
+ return next;
+ }
+
+ public boolean hasNext() {
+ return (findNext(current) < items.size());
+ }
+
+ public Object next() {
+ current = findNext(current);
+ if (current == items.size())
+ throw new NoSuchElementException("enumerated past end of FreeList");
+ return items.elementAt(current);
+ }
+
+ public void remove() {
+ del(current);
+ }
+ }
+}
diff --git a/bdb/rpc_server/java/LocalIterator.java b/bdb/rpc_server/java/LocalIterator.java
new file mode 100644
index 00000000000..eecb0b5e78d
--- /dev/null
+++ b/bdb/rpc_server/java/LocalIterator.java
@@ -0,0 +1,23 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: LocalIterator.java,v 1.2 2002/08/09 01:56:09 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import java.util.*;
+
+/**
+ * Iterator interface. Note that this matches java.util.Iterator
+ * but maintains compatibility with Java 1.1
+ * Intentionally package-protected exposure.
+ */
+interface LocalIterator {
+ boolean hasNext();
+ Object next();
+ void remove();
+}
diff --git a/bdb/rpc_server/java/README b/bdb/rpc_server/java/README
new file mode 100644
index 00000000000..c2d8f3abd57
--- /dev/null
+++ b/bdb/rpc_server/java/README
@@ -0,0 +1,24 @@
+Berkeley DB Java RPC server, copyright (C) 2002 Sleepycat Software
+
+The Java implementation of the Berkeley DB RPC server is intended
+primarily for testing purposes. It provides the same interface
+as the C and C++ RPC servers, but is implemented via the Java API
+rather than the C or C++ APIs. This allows the existing Tcl test
+suite to exercise the Java API without modification.
+
+The Java RPC server relies on a Java version of rpcgen to
+automatically generate appropriate Java classes from the RPC
+interface specification (../db_server.x). We use jrpcgen, which
+is part of the Remote Tea for Java project:
+ acplt.plt.rwth-aachen.de/ks/english/remotetea.html
+
+To rebuild the Java stubs from db_server.x, you will need to
+download the full Remote Tea package, but if you just want to
+compile the Java sources and run the Java RPC server, the runtime
+component of Remote Tea is included in oncrpc.jar. Building
+the Java RPC server is automatic when Berkeley DB is configured
+with the both --enable-rpc and --enable-java.
+
+All of the Remote Tea project is licensed under the Library GNU
+Public License, and we have made no modifications to their
+released code.
diff --git a/bdb/rpc_server/java/RpcDb.java b/bdb/rpc_server/java/RpcDb.java
new file mode 100644
index 00000000000..59da9be67dc
--- /dev/null
+++ b/bdb/rpc_server/java/RpcDb.java
@@ -0,0 +1,694 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: RpcDb.java,v 1.8 2002/08/09 01:56:09 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import com.sleepycat.db.*;
+import java.io.IOException;
+import java.io.*;
+import java.util.*;
+
+/**
+ * RPC wrapper around a db object for the Java RPC server.
+ */
+public class RpcDb extends Timer
+{
+ static final byte[] empty = new byte[0];
+ Db db;
+ RpcDbEnv rdbenv;
+ int refcount = 1;
+ String dbname, subdbname;
+ int type, setflags, openflags;
+
+ public RpcDb(RpcDbEnv rdbenv)
+ {
+ this.rdbenv = rdbenv;
+ }
+
+ void dispose()
+ {
+ if (db != null) {
+ try {
+ db.close(0);
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ }
+ db = null;
+ }
+ }
+
+ public void associate(DbDispatcher server,
+ __db_associate_msg args, __db_associate_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ /*
+ * We do not support DB_CREATE for associate. Users
+ * can only access secondary indices on a read-only basis,
+ * so whatever they are looking for needs to be there already.
+ */
+ db.associate(txn, server.getDb(args.sdbpcl_id).db, null, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void close(DbDispatcher server,
+ __db_close_msg args, __db_close_reply reply)
+ {
+ if (--refcount != 0) {
+ reply.status = 0;
+ return;
+ }
+
+ try {
+ db.close(args.flags);
+ db = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } finally {
+ server.delDb(this);
+ }
+ }
+
+ public void create(DbDispatcher server,
+ __db_create_msg args, __db_create_reply reply)
+ {
+ try {
+ db = new Db(server.getEnv(args.dbenvcl_id).dbenv, args.flags);
+ reply.dbcl_id = server.addDb(this);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void cursor(DbDispatcher server,
+ __db_cursor_msg args, __db_cursor_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ Dbc dbc = db.cursor(txn, args.flags);
+ RpcDbc rdbc = new RpcDbc(this, dbc, false);
+ rdbc.timer = (rtxn != null) ? rtxn.timer : this;
+ reply.dbcidcl_id = server.addCursor(rdbc);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void del(DbDispatcher server,
+ __db_del_msg args, __db_del_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ Dbt key = new Dbt(args.keydata);
+ key.set_dlen(args.keydlen);
+ key.set_doff(args.keydoff);
+ key.set_ulen(args.keyulen);
+ key.set_flags(args.keyflags);
+
+ db.del(txn, key, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void get(DbDispatcher server,
+ __db_get_msg args, __db_get_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ Dbt key = new Dbt(args.keydata);
+ key.set_dlen(args.keydlen);
+ key.set_doff(args.keydoff);
+ key.set_ulen(args.keyulen);
+ key.set_flags(Db.DB_DBT_MALLOC |
+ (args.keyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt data = new Dbt(args.datadata);
+ data.set_dlen(args.datadlen);
+ data.set_doff(args.datadoff);
+ data.set_ulen(args.dataulen);
+ if ((args.flags & Db.DB_MULTIPLE) != 0) {
+ if (data.get_data().length == 0)
+ data.set_data(new byte[data.get_ulen()]);
+ data.set_flags(Db.DB_DBT_USERMEM |
+ (args.dataflags & Db.DB_DBT_PARTIAL));
+ } else
+ data.set_flags(Db.DB_DBT_MALLOC |
+ (args.dataflags & Db.DB_DBT_PARTIAL));
+
+ reply.status = db.get(txn, key, data, args.flags);
+
+ if (key.get_data() == args.keydata ||
+ key.get_data().length != key.get_size()) {
+ reply.keydata = new byte[key.get_size()];
+ System.arraycopy(key.get_data(), 0, reply.keydata, 0, key.get_size());
+ } else
+ reply.keydata = key.get_data();
+
+ if (data.get_data() == args.datadata ||
+ data.get_data().length != data.get_size()) {
+ reply.datadata = new byte[data.get_size()];
+ System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
+ } else
+ reply.datadata = data.get_data();
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ reply.keydata = reply.datadata = empty;
+ }
+ }
+
+ public void join(DbDispatcher server,
+ __db_join_msg args, __db_join_reply reply)
+ {
+ try {
+ Dbc[] cursors = new Dbc[args.curs.length + 1];
+ for(int i = 0; i < args.curs.length; i++) {
+ RpcDbc rdbc = server.getCursor(args.curs[i]);
+ if (rdbc == null) {
+ reply.status = Db.DB_NOSERVER_ID;
+ return;
+ }
+ cursors[i] = rdbc.dbc;
+ }
+ cursors[args.curs.length] = null;
+
+ Dbc jdbc = db.join(cursors, args.flags);
+
+ RpcDbc rjdbc = new RpcDbc(this, jdbc, true);
+ /*
+ * If our curslist has a parent txn, we need to use it too
+ * for the activity timeout. All cursors must be part of
+ * the same transaction, so just check the first.
+ */
+ RpcDbc rdbc0 = server.getCursor(args.curs[0]);
+ if (rdbc0.timer != rdbc0)
+ rjdbc.timer = rdbc0.timer;
+
+ /*
+ * All of the curslist cursors must point to the join
+ * cursor's timeout so that we do not timeout any of the
+ * curlist cursors while the join cursor is active.
+ */
+ for(int i = 0; i < args.curs.length; i++) {
+ RpcDbc rdbc = server.getCursor(args.curs[i]);
+ rdbc.orig_timer = rdbc.timer;
+ rdbc.timer = rjdbc;
+ }
+ reply.dbcidcl_id = server.addCursor(rjdbc);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void key_range(DbDispatcher server,
+ __db_key_range_msg args, __db_key_range_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ Dbt key = new Dbt(args.keydata);
+ key.set_dlen(args.keydlen);
+ key.set_doff(args.keydoff);
+ key.set_ulen(args.keyulen);
+ key.set_flags(args.keyflags);
+
+ DbKeyRange range = new DbKeyRange();
+
+ db.key_range(txn, key, range, args.flags);
+ reply.status = 0;
+ reply.less = range.less;
+ reply.equal = range.equal;
+ reply.greater = range.greater;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ private boolean findSharedDb(DbDispatcher server, __db_open_reply reply)
+ throws DbException
+ {
+ RpcDb rdb = null;
+ boolean matchFound = false;
+ LocalIterator i = ((DbServer)server).db_list.iterator();
+
+ while (!matchFound && i.hasNext()) {
+ rdb = (RpcDb)i.next();
+ if (rdb != null && rdb != this && rdb.rdbenv == rdbenv &&
+ (type == Db.DB_UNKNOWN || rdb.type == type) &&
+ openflags == rdb.openflags &&
+ setflags == rdb.setflags &&
+ dbname != null && rdb.dbname != null &&
+ dbname.equals(rdb.dbname) &&
+ (subdbname == rdb.subdbname ||
+ (subdbname != null && rdb.subdbname != null &&
+ subdbname.equals(rdb.subdbname))))
+ matchFound = true;
+ }
+
+ if (matchFound) {
+ ++rdb.refcount;
+ reply.dbcl_id = ((FreeList.FreeListIterator)i).current;
+ reply.type = rdb.db.get_type();
+ reply.dbflags = rdb.db.get_flags_raw();
+ // FIXME: not possible to work out byteorder from Java?
+ reply.lorder = rdb.db.get_byteswapped() ? 4321 : 1234;
+ reply.status = 0;
+
+ DbServer.err.println("Sharing Db: " + reply.dbcl_id);
+ }
+
+ return matchFound;
+ }
+
+ public void open(DbDispatcher server,
+ __db_open_msg args, __db_open_reply reply)
+ {
+ try {
+ dbname = (args.name.length() > 0) ? args.name : null;
+ subdbname = (args.subdb.length() > 0) ? args.subdb : null;
+ type = args.type;
+ openflags = args.flags & DbServer.DB_SERVER_DBFLAGS;
+
+ if (findSharedDb(server, reply)) {
+ db.close(0);
+ db = null;
+ server.delDb(this);
+ } else {
+ DbServer.err.println("Calling db.open(" + null + ", " + dbname + ", " + subdbname + ", " + args.type + ", " + Integer.toHexString(args.flags) + ", " + args.mode + ")");
+ db.open(null, dbname, subdbname, args.type, args.flags, args.mode);
+
+ reply.dbcl_id = args.dbpcl_id;
+ reply.type = this.type = db.get_type();
+ reply.dbflags = db.get_flags_raw();
+ // FIXME: not possible to work out byteorder from Java?
+ reply.lorder = db.get_byteswapped() ? 4321 : 1234;
+ reply.status = 0;
+ }
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } catch(FileNotFoundException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = Db.DB_NOTFOUND;
+ }
+
+ // System.err.println("Db.open: reply.status = " + reply.status + ", reply.dbcl_id = " + reply.dbcl_id);
+ }
+
+ public void pget(DbDispatcher server,
+ __db_pget_msg args, __db_pget_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ Dbt skey = new Dbt(args.skeydata);
+ skey.set_dlen(args.skeydlen);
+ skey.set_doff(args.skeydoff);
+ skey.set_ulen(args.skeyulen);
+ skey.set_flags(Db.DB_DBT_MALLOC |
+ (args.skeyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt pkey = new Dbt(args.pkeydata);
+ pkey.set_dlen(args.pkeydlen);
+ pkey.set_doff(args.pkeydoff);
+ pkey.set_ulen(args.pkeyulen);
+ pkey.set_flags(Db.DB_DBT_MALLOC |
+ (args.pkeyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt data = new Dbt(args.datadata);
+ data.set_dlen(args.datadlen);
+ data.set_doff(args.datadoff);
+ data.set_ulen(args.dataulen);
+ data.set_flags(Db.DB_DBT_MALLOC |
+ (args.dataflags & Db.DB_DBT_PARTIAL));
+
+ db.pget(txn, skey, pkey, data, args.flags);
+
+ if (skey.get_data() == args.skeydata ||
+ skey.get_data().length != skey.get_size()) {
+ reply.skeydata = new byte[skey.get_size()];
+ System.arraycopy(skey.get_data(), 0, reply.skeydata, 0, skey.get_size());
+ } else
+ reply.skeydata = skey.get_data();
+
+ if (pkey.get_data() == args.pkeydata ||
+ pkey.get_data().length != pkey.get_size()) {
+ reply.pkeydata = new byte[pkey.get_size()];
+ System.arraycopy(pkey.get_data(), 0, reply.pkeydata, 0, pkey.get_size());
+ } else
+ reply.pkeydata = pkey.get_data();
+
+ if (data.get_data() == args.datadata ||
+ data.get_data().length != data.get_size()) {
+ reply.datadata = new byte[data.get_size()];
+ System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
+ } else
+ reply.datadata = data.get_data();
+
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ reply.skeydata = reply.pkeydata = reply.datadata = empty;
+ }
+ }
+
+ public void put(DbDispatcher server,
+ __db_put_msg args, __db_put_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+
+ Dbt key = new Dbt(args.keydata);
+ key.set_dlen(args.keydlen);
+ key.set_doff(args.keydoff);
+ key.set_ulen(args.keyulen);
+ key.set_flags(Db.DB_DBT_MALLOC |
+ (args.keyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt data = new Dbt(args.datadata);
+ data.set_dlen(args.datadlen);
+ data.set_doff(args.datadoff);
+ data.set_ulen(args.dataulen);
+ data.set_flags(args.dataflags);
+
+ reply.status = db.put(txn, key, data, args.flags);
+
+ /*
+ * If the client did a DB_APPEND, set up key in reply.
+ * Otherwise just status.
+ */
+ if ((args.flags & Db.DB_APPEND) != 0) {
+ if (key.get_data() == args.keydata ||
+ key.get_data().length != key.get_size()) {
+ reply.keydata = new byte[key.get_size()];
+ System.arraycopy(key.get_data(), 0, reply.keydata, 0, key.get_size());
+ } else
+ reply.keydata = key.get_data();
+ } else
+ reply.keydata = empty;
+ } catch(DbException e) {
+ reply.keydata = empty;
+ reply.status = e.get_errno();
+ DbServer.err.println("Exception, setting status to " + reply.status);
+ e.printStackTrace(DbServer.err);
+ }
+ }
+
+ public void remove(DbDispatcher server,
+ __db_remove_msg args, __db_remove_reply reply)
+ {
+ try {
+ args.name = (args.name.length() > 0) ? args.name : null;
+ args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+ db.remove(args.name, args.subdb, args.flags);
+ db = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } catch(FileNotFoundException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = Db.DB_NOTFOUND;
+ } finally {
+ server.delDb(this);
+ }
+ }
+
+ public void rename(DbDispatcher server,
+ __db_rename_msg args, __db_rename_reply reply)
+ {
+ try {
+ args.name = (args.name.length() > 0) ? args.name : null;
+ args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+ args.newname = (args.newname.length() > 0) ? args.newname : null;
+ db.rename(args.name, args.subdb, args.newname, args.flags);
+ db = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } catch(FileNotFoundException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = Db.DB_NOTFOUND;
+ } finally {
+ server.delDb(this);
+ }
+ }
+
+ public void set_bt_maxkey(DbDispatcher server,
+ __db_bt_maxkey_msg args, __db_bt_maxkey_reply reply)
+ {
+ try {
+ db.set_bt_maxkey(args.maxkey);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_bt_minkey(DbDispatcher server,
+ __db_bt_minkey_msg args, __db_bt_minkey_reply reply)
+ {
+ try {
+ db.set_bt_minkey(args.minkey);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_encrypt(DbDispatcher server,
+ __db_encrypt_msg args, __db_encrypt_reply reply)
+ {
+ try {
+ db.set_encrypt(args.passwd, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_flags(DbDispatcher server,
+ __db_flags_msg args, __db_flags_reply reply)
+ {
+ try {
+ // DbServer.err.println("Calling db.setflags(" + Integer.toHexString(args.flags) + ")");
+ db.set_flags(args.flags);
+ setflags |= args.flags;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_h_ffactor(DbDispatcher server,
+ __db_h_ffactor_msg args, __db_h_ffactor_reply reply)
+ {
+ try {
+ db.set_h_ffactor(args.ffactor);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_h_nelem(DbDispatcher server,
+ __db_h_nelem_msg args, __db_h_nelem_reply reply)
+ {
+ try {
+ db.set_h_nelem(args.nelem);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_lorder(DbDispatcher server,
+ __db_lorder_msg args, __db_lorder_reply reply)
+ {
+ try {
+ db.set_lorder(args.lorder);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_pagesize(DbDispatcher server,
+ __db_pagesize_msg args, __db_pagesize_reply reply)
+ {
+ try {
+ db.set_pagesize(args.pagesize);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_q_extentsize(DbDispatcher server,
+ __db_extentsize_msg args, __db_extentsize_reply reply)
+ {
+ try {
+ db.set_q_extentsize(args.extentsize);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_re_delim(DbDispatcher server,
+ __db_re_delim_msg args, __db_re_delim_reply reply)
+ {
+ try {
+ db.set_re_delim(args.delim);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_re_len(DbDispatcher server,
+ __db_re_len_msg args, __db_re_len_reply reply)
+ {
+ try {
+ db.set_re_len(args.len);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_re_pad(DbDispatcher server,
+ __db_re_pad_msg args, __db_re_pad_reply reply)
+ {
+ try {
+ db.set_re_pad(args.pad);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void stat(DbDispatcher server,
+ __db_stat_msg args, __db_stat_reply reply)
+ {
+ try {
+ Object raw_stat = db.stat(args.flags);
+
+ if (raw_stat instanceof DbHashStat) {
+ DbHashStat hs = (DbHashStat)raw_stat;
+ int[] raw_stats = {
+ hs.hash_magic, hs.hash_version,
+ hs.hash_metaflags, hs.hash_nkeys,
+ hs.hash_ndata, hs.hash_pagesize,
+ hs.hash_ffactor, hs.hash_buckets,
+ hs.hash_free, hs.hash_bfree,
+ hs.hash_bigpages, hs.hash_big_bfree,
+ hs.hash_overflows, hs.hash_ovfl_free,
+ hs.hash_dup, hs.hash_dup_free
+ };
+ reply.stats = raw_stats;
+ } else if (raw_stat instanceof DbQueueStat) {
+ DbQueueStat qs = (DbQueueStat)raw_stat;
+ int[] raw_stats = {
+ qs.qs_magic, qs.qs_version,
+ qs.qs_metaflags, qs.qs_nkeys,
+ qs.qs_ndata, qs.qs_pagesize,
+ qs.qs_extentsize, qs.qs_pages,
+ qs.qs_re_len, qs.qs_re_pad,
+ qs.qs_pgfree, qs.qs_first_recno,
+ qs.qs_cur_recno
+ };
+ reply.stats = raw_stats;
+ } else if (raw_stat instanceof DbBtreeStat) {
+ DbBtreeStat bs = (DbBtreeStat)raw_stat;
+ int[] raw_stats = {
+ bs.bt_magic, bs.bt_version,
+ bs.bt_metaflags, bs.bt_nkeys,
+ bs.bt_ndata, bs.bt_pagesize,
+ bs.bt_maxkey, bs.bt_minkey,
+ bs.bt_re_len, bs.bt_re_pad,
+ bs.bt_levels, bs.bt_int_pg,
+ bs.bt_leaf_pg, bs.bt_dup_pg,
+ bs.bt_over_pg, bs.bt_free,
+ bs.bt_int_pgfree, bs.bt_leaf_pgfree,
+ bs.bt_dup_pgfree, bs.bt_over_pgfree
+ };
+ reply.stats = raw_stats;
+ } else
+ throw new DbException("Invalid return type from db.stat()", Db.DB_NOTFOUND);
+
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ reply.stats = new int[0];
+ }
+ }
+
+ public void sync(DbDispatcher server,
+ __db_sync_msg args, __db_sync_reply reply)
+ {
+ try {
+ db.sync(args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void truncate(DbDispatcher server,
+ __db_truncate_msg args, __db_truncate_reply reply)
+ {
+ try {
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ reply.count = db.truncate(txn, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+}
diff --git a/bdb/rpc_server/java/RpcDbEnv.java b/bdb/rpc_server/java/RpcDbEnv.java
new file mode 100644
index 00000000000..9d9f1ba4324
--- /dev/null
+++ b/bdb/rpc_server/java/RpcDbEnv.java
@@ -0,0 +1,269 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: RpcDbEnv.java,v 1.6 2002/08/23 08:45:59 mjc Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import com.sleepycat.db.*;
+import java.io.IOException;
+import java.io.*;
+import java.util.*;
+
+/**
+ * RPC wrapper around a dbenv for the Java RPC server.
+ */
+public class RpcDbEnv extends Timer
+{
+ DbEnv dbenv;
+ String home;
+ long idletime, timeout;
+ int openflags, onflags, offflags;
+ int refcount = 1;
+
+ void dispose()
+ {
+ if (dbenv != null) {
+ try {
+ dbenv.close(0);
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ }
+ dbenv = null;
+ }
+ }
+
+ public void close(DbDispatcher server,
+ __env_close_msg args, __env_close_reply reply)
+ {
+ if (--refcount != 0) {
+ reply.status = 0;
+ return;
+ }
+
+ try {
+ dbenv.close(args.flags);
+ dbenv = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } finally {
+ server.delEnv(this);
+ }
+ }
+
+ public void create(DbDispatcher server,
+ __env_create_msg args, __env_create_reply reply)
+ {
+ this.idletime = (args.timeout != 0) ? args.timeout : DbServer.idleto;
+ this.timeout = DbServer.defto;
+ try {
+ dbenv = new DbEnv(0);
+ reply.envcl_id = server.addEnv(this);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void dbremove(DbDispatcher server,
+ __env_dbremove_msg args, __env_dbremove_reply reply)
+ {
+ try {
+ args.name = (args.name.length() > 0) ? args.name : null;
+ args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ dbenv.dbremove(txn, args.name, args.subdb, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void dbrename(DbDispatcher server,
+ __env_dbrename_msg args, __env_dbrename_reply reply)
+ {
+ try {
+ args.name = (args.name.length() > 0) ? args.name : null;
+ args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+ args.newname = (args.newname.length() > 0) ? args.newname : null;
+
+ RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+ DbTxn txn = (rtxn != null) ? rtxn.txn : null;
+ dbenv.dbrename(txn, args.name, args.subdb, args.newname, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ private boolean findSharedDbEnv(DbDispatcher server, __env_open_reply reply)
+ throws DbException
+ {
+ RpcDbEnv rdbenv = null;
+ boolean matchFound = false;
+ LocalIterator i = ((DbServer)server).env_list.iterator();
+
+ while (!matchFound && i.hasNext()) {
+ rdbenv = (RpcDbEnv)i.next();
+ if (rdbenv != null && rdbenv != this &&
+ (home == rdbenv.home ||
+ (home != null && home.equals(rdbenv.home))) &&
+ openflags == rdbenv.openflags &&
+ onflags == rdbenv.onflags &&
+ offflags == rdbenv.offflags)
+ matchFound = true;
+ }
+
+ if (matchFound) {
+ /*
+ * The only thing left to check is the timeout.
+ * Since the server timeout set by the client is a hint, for sharing
+ * we'll give them the benefit of the doubt and grant them the
+ * longer timeout.
+ */
+ if (rdbenv.timeout < timeout)
+ rdbenv.timeout = timeout;
+
+ ++rdbenv.refcount;
+ reply.envcl_id = ((FreeList.FreeListIterator)i).current;
+ reply.status = 0;
+
+ DbServer.err.println("Sharing DbEnv: " + reply.envcl_id);
+ }
+
+ return matchFound;
+ }
+
+ public void open(DbDispatcher server,
+ __env_open_msg args, __env_open_reply reply)
+ {
+ try {
+ home = (args.home.length() > 0) ? args.home : null;
+
+ /*
+ * If they are using locking do deadlock detection for them,
+ * internally.
+ */
+ if ((args.flags & Db.DB_INIT_LOCK) != 0)
+ dbenv.set_lk_detect(Db.DB_LOCK_DEFAULT);
+
+ // adjust flags for RPC
+ int newflags = (args.flags & ~DbServer.DB_SERVER_FLAGMASK);
+ openflags = (newflags & DbServer.DB_SERVER_ENVFLAGS);
+
+ if (findSharedDbEnv(server, reply)) {
+ dbenv.close(0);
+ dbenv = null;
+ server.delEnv(this);
+ } else {
+ // TODO: check home?
+ dbenv.open(home, newflags, args.mode);
+ reply.status = 0;
+ reply.envcl_id = args.dbenvcl_id;
+ }
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } catch(FileNotFoundException e) {
+ reply.status = Db.DB_NOTFOUND;
+ }
+
+ // System.err.println("DbEnv.open: reply.status = " + reply.status + ", reply.envcl_id = " + reply.envcl_id);
+ }
+
+ public void remove(DbDispatcher server,
+ __env_remove_msg args, __env_remove_reply reply)
+ {
+ try {
+ args.home = (args.home.length() > 0) ? args.home : null;
+ // TODO: check home?
+
+ dbenv.remove(args.home, args.flags);
+ dbenv = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } catch(FileNotFoundException e) {
+ reply.status = Db.DB_NOTFOUND;
+ } finally {
+ server.delEnv(this);
+ }
+ }
+
+ public void set_cachesize(DbDispatcher server,
+ __env_cachesize_msg args, __env_cachesize_reply reply)
+ {
+ try {
+ dbenv.set_cachesize(args.gbytes, args.bytes, args.ncache);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_encrypt(DbDispatcher server,
+ __env_encrypt_msg args, __env_encrypt_reply reply)
+ {
+ try {
+ dbenv.set_encrypt(args.passwd, args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void set_flags(DbDispatcher server,
+ __env_flags_msg args, __env_flags_reply reply)
+ {
+ try {
+ dbenv.set_flags(args.flags, args.onoff != 0);
+ if (args.onoff != 0)
+ onflags |= args.flags;
+ else
+ offflags |= args.flags;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ // txn_recover implementation
+ public void txn_recover(DbDispatcher server,
+ __txn_recover_msg args, __txn_recover_reply reply)
+ {
+ try {
+ DbPreplist[] prep_list = dbenv.txn_recover(args.count, args.flags);
+ if (prep_list != null && prep_list.length > 0) {
+ int count = prep_list.length;
+ reply.retcount = count;
+ reply.txn = new int[count];
+ reply.gid = new byte[count * Db.DB_XIDDATASIZE];
+
+ for(int i = 0; i < count; i++) {
+ reply.txn[i] = server.addTxn(new RpcDbTxn(this, prep_list[i].txn));
+ System.arraycopy(prep_list[i].gid, 0, reply.gid, i * Db.DB_XIDDATASIZE, Db.DB_XIDDATASIZE);
+ }
+ }
+
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+}
diff --git a/bdb/rpc_server/java/RpcDbTxn.java b/bdb/rpc_server/java/RpcDbTxn.java
new file mode 100644
index 00000000000..a3207b5e35d
--- /dev/null
+++ b/bdb/rpc_server/java/RpcDbTxn.java
@@ -0,0 +1,123 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: RpcDbTxn.java,v 1.2 2002/08/09 01:56:10 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import com.sleepycat.db.*;
+import java.io.IOException;
+import java.io.*;
+import java.util.*;
+
+/**
+ * RPC wrapper around a txn object for the Java RPC server.
+ */
+public class RpcDbTxn extends Timer
+{
+ RpcDbEnv rdbenv;
+ DbTxn txn;
+
+ public RpcDbTxn(RpcDbEnv rdbenv, DbTxn txn)
+ {
+ this.rdbenv = rdbenv;
+ this.txn = txn;
+ }
+
+ void dispose()
+ {
+ if (txn != null) {
+ try {
+ txn.abort();
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ }
+ txn = null;
+ }
+ }
+
+ public void abort(DbDispatcher server,
+ __txn_abort_msg args, __txn_abort_reply reply)
+ {
+ try {
+ txn.abort();
+ txn = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } finally {
+ server.delTxn(this);
+ }
+ }
+
+ public void begin(DbDispatcher server,
+ __txn_begin_msg args, __txn_begin_reply reply)
+ {
+ try {
+ if (rdbenv == null) {
+ reply.status = Db.DB_NOSERVER_ID;
+ return;
+ }
+ DbEnv dbenv = rdbenv.dbenv;
+ RpcDbTxn rparent = server.getTxn(args.parentcl_id);
+ DbTxn parent = (rparent != null) ? rparent.txn : null;
+
+ txn = dbenv.txn_begin(parent, args.flags);
+
+ if (rparent != null)
+ timer = rparent.timer;
+ reply.txnidcl_id = server.addTxn(this);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void commit(DbDispatcher server,
+ __txn_commit_msg args, __txn_commit_reply reply)
+ {
+ try {
+ txn.commit(args.flags);
+ txn = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } finally {
+ server.delTxn(this);
+ }
+ }
+
+ public void discard(DbDispatcher server,
+ __txn_discard_msg args, __txn_discard_reply reply)
+ {
+ try {
+ txn.discard(args.flags);
+ txn = null;
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } finally {
+ server.delTxn(this);
+ }
+ }
+
+ public void prepare(DbDispatcher server,
+ __txn_prepare_msg args, __txn_prepare_reply reply)
+ {
+ try {
+ txn.prepare(args.gid);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+}
diff --git a/bdb/rpc_server/java/RpcDbc.java b/bdb/rpc_server/java/RpcDbc.java
new file mode 100644
index 00000000000..a37b4ee4896
--- /dev/null
+++ b/bdb/rpc_server/java/RpcDbc.java
@@ -0,0 +1,238 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: RpcDbc.java,v 1.3 2002/08/09 01:56:10 bostic Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+import com.sleepycat.db.*;
+import java.io.IOException;
+import java.io.*;
+import java.util.*;
+
+/**
+ * RPC wrapper around a dbc object for the Java RPC server.
+ */
+public class RpcDbc extends Timer
+{
+ static final byte[] empty = new byte[0];
+ RpcDbEnv rdbenv;
+ RpcDb rdb;
+ Dbc dbc;
+ Timer orig_timer;
+ boolean isJoin;
+
+ public RpcDbc(RpcDb rdb, Dbc dbc, boolean isJoin)
+ {
+ this.rdb = rdb;
+ this.rdbenv = rdb.rdbenv;
+ this.dbc = dbc;
+ this.isJoin = isJoin;
+ }
+
+ void dispose()
+ {
+ if (dbc != null) {
+ try {
+ dbc.close();
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ }
+ dbc = null;
+ }
+ }
+
+ public void close(DbDispatcher server,
+ __dbc_close_msg args, __dbc_close_reply reply)
+ {
+ try {
+ dbc.close();
+ dbc = null;
+
+ if (isJoin)
+ for(LocalIterator i = ((DbServer)server).cursor_list.iterator(); i.hasNext(); ) {
+ RpcDbc rdbc = (RpcDbc)i.next();
+ // Unjoin cursors that were joined to create this
+ if (rdbc != null && rdbc.timer == this)
+ rdbc.timer = rdbc.orig_timer;
+ }
+
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ } finally {
+ server.delCursor(this);
+ }
+ }
+
+ public void count(DbDispatcher server,
+ __dbc_count_msg args, __dbc_count_reply reply)
+ {
+ try {
+ reply.dupcount = dbc.count(args.flags);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void del(DbDispatcher server,
+ __dbc_del_msg args, __dbc_del_reply reply)
+ {
+ try {
+ reply.status = dbc.del(args.flags);
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void dup(DbDispatcher server,
+ __dbc_dup_msg args, __dbc_dup_reply reply)
+ {
+ try {
+ Dbc newdbc = dbc.dup(args.flags);
+ RpcDbc rdbc = new RpcDbc(rdb, newdbc, false);
+ /* If this cursor has a parent txn, we need to use it too. */
+ if (timer != this)
+ rdbc.timer = timer;
+ reply.dbcidcl_id = server.addCursor(rdbc);
+ reply.status = 0;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void get(DbDispatcher server,
+ __dbc_get_msg args, __dbc_get_reply reply)
+ {
+ try {
+ Dbt key = new Dbt(args.keydata);
+ key.set_dlen(args.keydlen);
+ key.set_ulen(args.keyulen);
+ key.set_doff(args.keydoff);
+ key.set_flags(Db.DB_DBT_MALLOC |
+ (args.keyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt data = new Dbt(args.datadata);
+ data.set_dlen(args.datadlen);
+ data.set_ulen(args.dataulen);
+ data.set_doff(args.datadoff);
+ if ((args.flags & Db.DB_MULTIPLE) != 0 ||
+ (args.flags & Db.DB_MULTIPLE_KEY) != 0) {
+ if (data.get_data().length == 0)
+ data.set_data(new byte[data.get_ulen()]);
+ data.set_flags(Db.DB_DBT_USERMEM |
+ (args.dataflags & Db.DB_DBT_PARTIAL));
+ } else
+ data.set_flags(Db.DB_DBT_MALLOC |
+ (args.dataflags & Db.DB_DBT_PARTIAL));
+
+ reply.status = dbc.get(key, data, args.flags);
+
+ if (key.get_data() == args.keydata) {
+ reply.keydata = new byte[key.get_size()];
+ System.arraycopy(key.get_data(), 0, reply.keydata, 0, key.get_size());
+ } else
+ reply.keydata = key.get_data();
+
+ if (data.get_data() == args.datadata) {
+ reply.datadata = new byte[data.get_size()];
+ System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
+ } else
+ reply.datadata = data.get_data();
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ reply.keydata = reply.datadata = empty;
+ }
+ }
+
+ public void pget(DbDispatcher server,
+ __dbc_pget_msg args, __dbc_pget_reply reply)
+ {
+ try {
+ Dbt skey = new Dbt(args.skeydata);
+ skey.set_dlen(args.skeydlen);
+ skey.set_doff(args.skeydoff);
+ skey.set_ulen(args.skeyulen);
+ skey.set_flags(Db.DB_DBT_MALLOC |
+ (args.skeyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt pkey = new Dbt(args.pkeydata);
+ pkey.set_dlen(args.pkeydlen);
+ pkey.set_doff(args.pkeydoff);
+ pkey.set_ulen(args.pkeyulen);
+ pkey.set_flags(Db.DB_DBT_MALLOC |
+ (args.pkeyflags & Db.DB_DBT_PARTIAL));
+
+ Dbt data = new Dbt(args.datadata);
+ data.set_dlen(args.datadlen);
+ data.set_doff(args.datadoff);
+ data.set_ulen(args.dataulen);
+ data.set_flags(Db.DB_DBT_MALLOC |
+ (args.dataflags & Db.DB_DBT_PARTIAL));
+
+ reply.status = dbc.pget(skey, pkey, data, args.flags);
+
+ if (skey.get_data() == args.skeydata) {
+ reply.skeydata = new byte[skey.get_size()];
+ System.arraycopy(skey.get_data(), 0, reply.skeydata, 0, skey.get_size());
+ } else
+ reply.skeydata = skey.get_data();
+
+ if (pkey.get_data() == args.pkeydata) {
+ reply.pkeydata = new byte[pkey.get_size()];
+ System.arraycopy(pkey.get_data(), 0, reply.pkeydata, 0, pkey.get_size());
+ } else
+ reply.pkeydata = pkey.get_data();
+
+ if (data.get_data() == args.datadata) {
+ reply.datadata = new byte[data.get_size()];
+ System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
+ } else
+ reply.datadata = data.get_data();
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ }
+ }
+
+ public void put(DbDispatcher server,
+ __dbc_put_msg args, __dbc_put_reply reply)
+ {
+ try {
+ Dbt key = new Dbt(args.keydata);
+ key.set_dlen(args.keydlen);
+ key.set_ulen(args.keyulen);
+ key.set_doff(args.keydoff);
+ key.set_flags(args.keyflags & Db.DB_DBT_PARTIAL);
+
+ Dbt data = new Dbt(args.datadata);
+ data.set_dlen(args.datadlen);
+ data.set_ulen(args.dataulen);
+ data.set_doff(args.datadoff);
+ data.set_flags(args.dataflags);
+
+ reply.status = dbc.put(key, data, args.flags);
+
+ if (reply.status == 0 &&
+ (args.flags == Db.DB_AFTER || args.flags == Db.DB_BEFORE) &&
+ rdb.db.get_type() == Db.DB_RECNO)
+ reply.keydata = key.get_data();
+ else
+ reply.keydata = empty;
+ } catch(DbException e) {
+ e.printStackTrace(DbServer.err);
+ reply.status = e.get_errno();
+ reply.keydata = empty;
+ }
+ }
+}
diff --git a/bdb/rpc_server/java/Timer.java b/bdb/rpc_server/java/Timer.java
new file mode 100644
index 00000000000..e16f3084f95
--- /dev/null
+++ b/bdb/rpc_server/java/Timer.java
@@ -0,0 +1,22 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: Timer.java,v 1.1 2002/01/03 02:59:39 mjc Exp $
+ */
+
+package com.sleepycat.db.rpcserver;
+
+/**
+ * Class to keep track of access times. This is slightly devious by having
+ * both the access_time and a reference to another Timer that can be
+ * used to group/share access times. This is done to keep the Java code
+ * close to the canonical C implementation of the RPC server.
+ */
+public class Timer
+{
+ Timer timer = this;
+ long last_access;
+}
diff --git a/bdb/rpc_server/java/gen/DbServerStub.java b/bdb/rpc_server/java/gen/DbServerStub.java
new file mode 100644
index 00000000000..90fc13a6d9c
--- /dev/null
+++ b/bdb/rpc_server/java/gen/DbServerStub.java
@@ -0,0 +1,495 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+import org.acplt.oncrpc.server.*;
+
+/**
+ */
+public abstract class DbServerStub extends OncRpcServerStub implements OncRpcDispatchable {
+
+ public DbServerStub()
+ throws OncRpcException, IOException {
+ this(0);
+ }
+
+ public DbServerStub(int port)
+ throws OncRpcException, IOException {
+ info = new OncRpcServerTransportRegistrationInfo [] {
+ new OncRpcServerTransportRegistrationInfo(db_server.DB_RPC_SERVERPROG, 4001),
+ };
+ transports = new OncRpcServerTransport [] {
+ new OncRpcUdpServerTransport(this, port, info, 32768),
+ new OncRpcTcpServerTransport(this, port, info, 32768)
+ };
+ }
+
+ public void dispatchOncRpcCall(OncRpcCallInformation call, int program, int version, int procedure)
+ throws OncRpcException, IOException {
+ if ( version == 4001 ) {
+ switch ( procedure ) {
+ case 1: {
+ __env_cachesize_msg args$ = new __env_cachesize_msg();
+ call.retrieveCall(args$);
+ __env_cachesize_reply result$ = __DB_env_cachesize_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 2: {
+ __env_close_msg args$ = new __env_close_msg();
+ call.retrieveCall(args$);
+ __env_close_reply result$ = __DB_env_close_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 3: {
+ __env_create_msg args$ = new __env_create_msg();
+ call.retrieveCall(args$);
+ __env_create_reply result$ = __DB_env_create_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 4: {
+ __env_dbremove_msg args$ = new __env_dbremove_msg();
+ call.retrieveCall(args$);
+ __env_dbremove_reply result$ = __DB_env_dbremove_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 5: {
+ __env_dbrename_msg args$ = new __env_dbrename_msg();
+ call.retrieveCall(args$);
+ __env_dbrename_reply result$ = __DB_env_dbrename_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 6: {
+ __env_encrypt_msg args$ = new __env_encrypt_msg();
+ call.retrieveCall(args$);
+ __env_encrypt_reply result$ = __DB_env_encrypt_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 7: {
+ __env_flags_msg args$ = new __env_flags_msg();
+ call.retrieveCall(args$);
+ __env_flags_reply result$ = __DB_env_flags_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 8: {
+ __env_open_msg args$ = new __env_open_msg();
+ call.retrieveCall(args$);
+ __env_open_reply result$ = __DB_env_open_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 9: {
+ __env_remove_msg args$ = new __env_remove_msg();
+ call.retrieveCall(args$);
+ __env_remove_reply result$ = __DB_env_remove_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 10: {
+ __txn_abort_msg args$ = new __txn_abort_msg();
+ call.retrieveCall(args$);
+ __txn_abort_reply result$ = __DB_txn_abort_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 11: {
+ __txn_begin_msg args$ = new __txn_begin_msg();
+ call.retrieveCall(args$);
+ __txn_begin_reply result$ = __DB_txn_begin_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 12: {
+ __txn_commit_msg args$ = new __txn_commit_msg();
+ call.retrieveCall(args$);
+ __txn_commit_reply result$ = __DB_txn_commit_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 13: {
+ __txn_discard_msg args$ = new __txn_discard_msg();
+ call.retrieveCall(args$);
+ __txn_discard_reply result$ = __DB_txn_discard_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 14: {
+ __txn_prepare_msg args$ = new __txn_prepare_msg();
+ call.retrieveCall(args$);
+ __txn_prepare_reply result$ = __DB_txn_prepare_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 15: {
+ __txn_recover_msg args$ = new __txn_recover_msg();
+ call.retrieveCall(args$);
+ __txn_recover_reply result$ = __DB_txn_recover_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 16: {
+ __db_associate_msg args$ = new __db_associate_msg();
+ call.retrieveCall(args$);
+ __db_associate_reply result$ = __DB_db_associate_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 17: {
+ __db_bt_maxkey_msg args$ = new __db_bt_maxkey_msg();
+ call.retrieveCall(args$);
+ __db_bt_maxkey_reply result$ = __DB_db_bt_maxkey_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 18: {
+ __db_bt_minkey_msg args$ = new __db_bt_minkey_msg();
+ call.retrieveCall(args$);
+ __db_bt_minkey_reply result$ = __DB_db_bt_minkey_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 19: {
+ __db_close_msg args$ = new __db_close_msg();
+ call.retrieveCall(args$);
+ __db_close_reply result$ = __DB_db_close_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 20: {
+ __db_create_msg args$ = new __db_create_msg();
+ call.retrieveCall(args$);
+ __db_create_reply result$ = __DB_db_create_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 21: {
+ __db_del_msg args$ = new __db_del_msg();
+ call.retrieveCall(args$);
+ __db_del_reply result$ = __DB_db_del_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 22: {
+ __db_encrypt_msg args$ = new __db_encrypt_msg();
+ call.retrieveCall(args$);
+ __db_encrypt_reply result$ = __DB_db_encrypt_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 23: {
+ __db_extentsize_msg args$ = new __db_extentsize_msg();
+ call.retrieveCall(args$);
+ __db_extentsize_reply result$ = __DB_db_extentsize_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 24: {
+ __db_flags_msg args$ = new __db_flags_msg();
+ call.retrieveCall(args$);
+ __db_flags_reply result$ = __DB_db_flags_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 25: {
+ __db_get_msg args$ = new __db_get_msg();
+ call.retrieveCall(args$);
+ __db_get_reply result$ = __DB_db_get_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 26: {
+ __db_h_ffactor_msg args$ = new __db_h_ffactor_msg();
+ call.retrieveCall(args$);
+ __db_h_ffactor_reply result$ = __DB_db_h_ffactor_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 27: {
+ __db_h_nelem_msg args$ = new __db_h_nelem_msg();
+ call.retrieveCall(args$);
+ __db_h_nelem_reply result$ = __DB_db_h_nelem_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 28: {
+ __db_key_range_msg args$ = new __db_key_range_msg();
+ call.retrieveCall(args$);
+ __db_key_range_reply result$ = __DB_db_key_range_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 29: {
+ __db_lorder_msg args$ = new __db_lorder_msg();
+ call.retrieveCall(args$);
+ __db_lorder_reply result$ = __DB_db_lorder_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 30: {
+ __db_open_msg args$ = new __db_open_msg();
+ call.retrieveCall(args$);
+ __db_open_reply result$ = __DB_db_open_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 31: {
+ __db_pagesize_msg args$ = new __db_pagesize_msg();
+ call.retrieveCall(args$);
+ __db_pagesize_reply result$ = __DB_db_pagesize_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 32: {
+ __db_pget_msg args$ = new __db_pget_msg();
+ call.retrieveCall(args$);
+ __db_pget_reply result$ = __DB_db_pget_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 33: {
+ __db_put_msg args$ = new __db_put_msg();
+ call.retrieveCall(args$);
+ __db_put_reply result$ = __DB_db_put_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 34: {
+ __db_re_delim_msg args$ = new __db_re_delim_msg();
+ call.retrieveCall(args$);
+ __db_re_delim_reply result$ = __DB_db_re_delim_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 35: {
+ __db_re_len_msg args$ = new __db_re_len_msg();
+ call.retrieveCall(args$);
+ __db_re_len_reply result$ = __DB_db_re_len_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 36: {
+ __db_re_pad_msg args$ = new __db_re_pad_msg();
+ call.retrieveCall(args$);
+ __db_re_pad_reply result$ = __DB_db_re_pad_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 37: {
+ __db_remove_msg args$ = new __db_remove_msg();
+ call.retrieveCall(args$);
+ __db_remove_reply result$ = __DB_db_remove_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 38: {
+ __db_rename_msg args$ = new __db_rename_msg();
+ call.retrieveCall(args$);
+ __db_rename_reply result$ = __DB_db_rename_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 39: {
+ __db_stat_msg args$ = new __db_stat_msg();
+ call.retrieveCall(args$);
+ __db_stat_reply result$ = __DB_db_stat_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 40: {
+ __db_sync_msg args$ = new __db_sync_msg();
+ call.retrieveCall(args$);
+ __db_sync_reply result$ = __DB_db_sync_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 41: {
+ __db_truncate_msg args$ = new __db_truncate_msg();
+ call.retrieveCall(args$);
+ __db_truncate_reply result$ = __DB_db_truncate_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 42: {
+ __db_cursor_msg args$ = new __db_cursor_msg();
+ call.retrieveCall(args$);
+ __db_cursor_reply result$ = __DB_db_cursor_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 43: {
+ __db_join_msg args$ = new __db_join_msg();
+ call.retrieveCall(args$);
+ __db_join_reply result$ = __DB_db_join_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 44: {
+ __dbc_close_msg args$ = new __dbc_close_msg();
+ call.retrieveCall(args$);
+ __dbc_close_reply result$ = __DB_dbc_close_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 45: {
+ __dbc_count_msg args$ = new __dbc_count_msg();
+ call.retrieveCall(args$);
+ __dbc_count_reply result$ = __DB_dbc_count_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 46: {
+ __dbc_del_msg args$ = new __dbc_del_msg();
+ call.retrieveCall(args$);
+ __dbc_del_reply result$ = __DB_dbc_del_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 47: {
+ __dbc_dup_msg args$ = new __dbc_dup_msg();
+ call.retrieveCall(args$);
+ __dbc_dup_reply result$ = __DB_dbc_dup_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 48: {
+ __dbc_get_msg args$ = new __dbc_get_msg();
+ call.retrieveCall(args$);
+ __dbc_get_reply result$ = __DB_dbc_get_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 49: {
+ __dbc_pget_msg args$ = new __dbc_pget_msg();
+ call.retrieveCall(args$);
+ __dbc_pget_reply result$ = __DB_dbc_pget_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ case 50: {
+ __dbc_put_msg args$ = new __dbc_put_msg();
+ call.retrieveCall(args$);
+ __dbc_put_reply result$ = __DB_dbc_put_4001(args$);
+ call.reply(result$);
+ break;
+ }
+ default:
+ call.failProcedureUnavailable();
+ }
+ } else {
+ call.failProcedureUnavailable();
+ }
+ }
+
+ public abstract __env_cachesize_reply __DB_env_cachesize_4001(__env_cachesize_msg arg1);
+
+ public abstract __env_close_reply __DB_env_close_4001(__env_close_msg arg1);
+
+ public abstract __env_create_reply __DB_env_create_4001(__env_create_msg arg1);
+
+ public abstract __env_dbremove_reply __DB_env_dbremove_4001(__env_dbremove_msg arg1);
+
+ public abstract __env_dbrename_reply __DB_env_dbrename_4001(__env_dbrename_msg arg1);
+
+ public abstract __env_encrypt_reply __DB_env_encrypt_4001(__env_encrypt_msg arg1);
+
+ public abstract __env_flags_reply __DB_env_flags_4001(__env_flags_msg arg1);
+
+ public abstract __env_open_reply __DB_env_open_4001(__env_open_msg arg1);
+
+ public abstract __env_remove_reply __DB_env_remove_4001(__env_remove_msg arg1);
+
+ public abstract __txn_abort_reply __DB_txn_abort_4001(__txn_abort_msg arg1);
+
+ public abstract __txn_begin_reply __DB_txn_begin_4001(__txn_begin_msg arg1);
+
+ public abstract __txn_commit_reply __DB_txn_commit_4001(__txn_commit_msg arg1);
+
+ public abstract __txn_discard_reply __DB_txn_discard_4001(__txn_discard_msg arg1);
+
+ public abstract __txn_prepare_reply __DB_txn_prepare_4001(__txn_prepare_msg arg1);
+
+ public abstract __txn_recover_reply __DB_txn_recover_4001(__txn_recover_msg arg1);
+
+ public abstract __db_associate_reply __DB_db_associate_4001(__db_associate_msg arg1);
+
+ public abstract __db_bt_maxkey_reply __DB_db_bt_maxkey_4001(__db_bt_maxkey_msg arg1);
+
+ public abstract __db_bt_minkey_reply __DB_db_bt_minkey_4001(__db_bt_minkey_msg arg1);
+
+ public abstract __db_close_reply __DB_db_close_4001(__db_close_msg arg1);
+
+ public abstract __db_create_reply __DB_db_create_4001(__db_create_msg arg1);
+
+ public abstract __db_del_reply __DB_db_del_4001(__db_del_msg arg1);
+
+ public abstract __db_encrypt_reply __DB_db_encrypt_4001(__db_encrypt_msg arg1);
+
+ public abstract __db_extentsize_reply __DB_db_extentsize_4001(__db_extentsize_msg arg1);
+
+ public abstract __db_flags_reply __DB_db_flags_4001(__db_flags_msg arg1);
+
+ public abstract __db_get_reply __DB_db_get_4001(__db_get_msg arg1);
+
+ public abstract __db_h_ffactor_reply __DB_db_h_ffactor_4001(__db_h_ffactor_msg arg1);
+
+ public abstract __db_h_nelem_reply __DB_db_h_nelem_4001(__db_h_nelem_msg arg1);
+
+ public abstract __db_key_range_reply __DB_db_key_range_4001(__db_key_range_msg arg1);
+
+ public abstract __db_lorder_reply __DB_db_lorder_4001(__db_lorder_msg arg1);
+
+ public abstract __db_open_reply __DB_db_open_4001(__db_open_msg arg1);
+
+ public abstract __db_pagesize_reply __DB_db_pagesize_4001(__db_pagesize_msg arg1);
+
+ public abstract __db_pget_reply __DB_db_pget_4001(__db_pget_msg arg1);
+
+ public abstract __db_put_reply __DB_db_put_4001(__db_put_msg arg1);
+
+ public abstract __db_re_delim_reply __DB_db_re_delim_4001(__db_re_delim_msg arg1);
+
+ public abstract __db_re_len_reply __DB_db_re_len_4001(__db_re_len_msg arg1);
+
+ public abstract __db_re_pad_reply __DB_db_re_pad_4001(__db_re_pad_msg arg1);
+
+ public abstract __db_remove_reply __DB_db_remove_4001(__db_remove_msg arg1);
+
+ public abstract __db_rename_reply __DB_db_rename_4001(__db_rename_msg arg1);
+
+ public abstract __db_stat_reply __DB_db_stat_4001(__db_stat_msg arg1);
+
+ public abstract __db_sync_reply __DB_db_sync_4001(__db_sync_msg arg1);
+
+ public abstract __db_truncate_reply __DB_db_truncate_4001(__db_truncate_msg arg1);
+
+ public abstract __db_cursor_reply __DB_db_cursor_4001(__db_cursor_msg arg1);
+
+ public abstract __db_join_reply __DB_db_join_4001(__db_join_msg arg1);
+
+ public abstract __dbc_close_reply __DB_dbc_close_4001(__dbc_close_msg arg1);
+
+ public abstract __dbc_count_reply __DB_dbc_count_4001(__dbc_count_msg arg1);
+
+ public abstract __dbc_del_reply __DB_dbc_del_4001(__dbc_del_msg arg1);
+
+ public abstract __dbc_dup_reply __DB_dbc_dup_4001(__dbc_dup_msg arg1);
+
+ public abstract __dbc_get_reply __DB_dbc_get_4001(__dbc_get_msg arg1);
+
+ public abstract __dbc_pget_reply __DB_dbc_pget_4001(__dbc_pget_msg arg1);
+
+ public abstract __dbc_put_reply __DB_dbc_put_4001(__dbc_put_msg arg1);
+
+}
+// End of DbServerStub.java
diff --git a/bdb/rpc_server/java/gen/__db_associate_msg.java b/bdb/rpc_server/java/gen/__db_associate_msg.java
new file mode 100644
index 00000000000..8977303b99a
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_associate_msg.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 4/25/02 11:01 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_associate_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int sdbpcl_id;
+ public int flags;
+
+ public __db_associate_msg() {
+ }
+
+ public __db_associate_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(sdbpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ sdbpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_associate_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_associate_reply.java b/bdb/rpc_server/java/gen/__db_associate_reply.java
new file mode 100644
index 00000000000..476d0868b33
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_associate_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_associate_reply implements XdrAble {
+ public int status;
+
+ public __db_associate_reply() {
+ }
+
+ public __db_associate_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_associate_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_bt_maxkey_msg.java b/bdb/rpc_server/java/gen/__db_bt_maxkey_msg.java
new file mode 100644
index 00000000000..007ce16a974
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_bt_maxkey_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_bt_maxkey_msg implements XdrAble {
+ public int dbpcl_id;
+ public int maxkey;
+
+ public __db_bt_maxkey_msg() {
+ }
+
+ public __db_bt_maxkey_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(maxkey);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ maxkey = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_bt_maxkey_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_bt_maxkey_reply.java b/bdb/rpc_server/java/gen/__db_bt_maxkey_reply.java
new file mode 100644
index 00000000000..855573271b3
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_bt_maxkey_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_bt_maxkey_reply implements XdrAble {
+ public int status;
+
+ public __db_bt_maxkey_reply() {
+ }
+
+ public __db_bt_maxkey_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_bt_maxkey_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_bt_minkey_msg.java b/bdb/rpc_server/java/gen/__db_bt_minkey_msg.java
new file mode 100644
index 00000000000..c86ec382456
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_bt_minkey_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_bt_minkey_msg implements XdrAble {
+ public int dbpcl_id;
+ public int minkey;
+
+ public __db_bt_minkey_msg() {
+ }
+
+ public __db_bt_minkey_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(minkey);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ minkey = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_bt_minkey_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_bt_minkey_reply.java b/bdb/rpc_server/java/gen/__db_bt_minkey_reply.java
new file mode 100644
index 00000000000..4d944b6bf33
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_bt_minkey_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_bt_minkey_reply implements XdrAble {
+ public int status;
+
+ public __db_bt_minkey_reply() {
+ }
+
+ public __db_bt_minkey_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_bt_minkey_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_close_msg.java b/bdb/rpc_server/java/gen/__db_close_msg.java
new file mode 100644
index 00000000000..ce8d213701b
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_close_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_close_msg implements XdrAble {
+ public int dbpcl_id;
+ public int flags;
+
+ public __db_close_msg() {
+ }
+
+ public __db_close_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_close_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_close_reply.java b/bdb/rpc_server/java/gen/__db_close_reply.java
new file mode 100644
index 00000000000..a9380e9c053
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_close_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_close_reply implements XdrAble {
+ public int status;
+
+ public __db_close_reply() {
+ }
+
+ public __db_close_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_close_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_create_msg.java b/bdb/rpc_server/java/gen/__db_create_msg.java
new file mode 100644
index 00000000000..d21ca50f807
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_create_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_create_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int flags;
+
+ public __db_create_msg() {
+ }
+
+ public __db_create_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_create_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_create_reply.java b/bdb/rpc_server/java/gen/__db_create_reply.java
new file mode 100644
index 00000000000..e3dcbbab14e
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_create_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_create_reply implements XdrAble {
+ public int status;
+ public int dbcl_id;
+
+ public __db_create_reply() {
+ }
+
+ public __db_create_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(dbcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ dbcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_create_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_cursor_msg.java b/bdb/rpc_server/java/gen/__db_cursor_msg.java
new file mode 100644
index 00000000000..60e09db6ebb
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_cursor_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_cursor_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int flags;
+
+ public __db_cursor_msg() {
+ }
+
+ public __db_cursor_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_cursor_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_cursor_reply.java b/bdb/rpc_server/java/gen/__db_cursor_reply.java
new file mode 100644
index 00000000000..bafd2817c67
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_cursor_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_cursor_reply implements XdrAble {
+ public int status;
+ public int dbcidcl_id;
+
+ public __db_cursor_reply() {
+ }
+
+ public __db_cursor_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(dbcidcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ dbcidcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_cursor_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_del_msg.java b/bdb/rpc_server/java/gen/__db_del_msg.java
new file mode 100644
index 00000000000..fdf47907dd6
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_del_msg.java
@@ -0,0 +1,53 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_del_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int keydlen;
+ public int keydoff;
+ public int keyulen;
+ public int keyflags;
+ public byte [] keydata;
+ public int flags;
+
+ public __db_del_msg() {
+ }
+
+ public __db_del_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(keydlen);
+ xdr.xdrEncodeInt(keydoff);
+ xdr.xdrEncodeInt(keyulen);
+ xdr.xdrEncodeInt(keyflags);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ keydlen = xdr.xdrDecodeInt();
+ keydoff = xdr.xdrDecodeInt();
+ keyulen = xdr.xdrDecodeInt();
+ keyflags = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_del_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_del_reply.java b/bdb/rpc_server/java/gen/__db_del_reply.java
new file mode 100644
index 00000000000..8a55445944f
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_del_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_del_reply implements XdrAble {
+ public int status;
+
+ public __db_del_reply() {
+ }
+
+ public __db_del_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_del_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_encrypt_msg.java b/bdb/rpc_server/java/gen/__db_encrypt_msg.java
new file mode 100644
index 00000000000..46d9f8ee7e8
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_encrypt_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 2/13/02 1:05 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_encrypt_msg implements XdrAble {
+ public int dbpcl_id;
+ public String passwd;
+ public int flags;
+
+ public __db_encrypt_msg() {
+ }
+
+ public __db_encrypt_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeString(passwd);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ passwd = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_encrypt_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_encrypt_reply.java b/bdb/rpc_server/java/gen/__db_encrypt_reply.java
new file mode 100644
index 00000000000..a97cc98c90b
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_encrypt_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 2/13/02 1:05 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_encrypt_reply implements XdrAble {
+ public int status;
+
+ public __db_encrypt_reply() {
+ }
+
+ public __db_encrypt_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_encrypt_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_extentsize_msg.java b/bdb/rpc_server/java/gen/__db_extentsize_msg.java
new file mode 100644
index 00000000000..41a51cff9c4
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_extentsize_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_extentsize_msg implements XdrAble {
+ public int dbpcl_id;
+ public int extentsize;
+
+ public __db_extentsize_msg() {
+ }
+
+ public __db_extentsize_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(extentsize);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ extentsize = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_extentsize_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_extentsize_reply.java b/bdb/rpc_server/java/gen/__db_extentsize_reply.java
new file mode 100644
index 00000000000..409625486c7
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_extentsize_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_extentsize_reply implements XdrAble {
+ public int status;
+
+ public __db_extentsize_reply() {
+ }
+
+ public __db_extentsize_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_extentsize_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_flags_msg.java b/bdb/rpc_server/java/gen/__db_flags_msg.java
new file mode 100644
index 00000000000..d8752e2e4dd
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_flags_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_flags_msg implements XdrAble {
+ public int dbpcl_id;
+ public int flags;
+
+ public __db_flags_msg() {
+ }
+
+ public __db_flags_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_flags_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_flags_reply.java b/bdb/rpc_server/java/gen/__db_flags_reply.java
new file mode 100644
index 00000000000..c4ec253db83
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_flags_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_flags_reply implements XdrAble {
+ public int status;
+
+ public __db_flags_reply() {
+ }
+
+ public __db_flags_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_flags_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_get_msg.java b/bdb/rpc_server/java/gen/__db_get_msg.java
new file mode 100644
index 00000000000..3dfe8e9d86e
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_get_msg.java
@@ -0,0 +1,68 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_get_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int keydlen;
+ public int keydoff;
+ public int keyulen;
+ public int keyflags;
+ public byte [] keydata;
+ public int datadlen;
+ public int datadoff;
+ public int dataulen;
+ public int dataflags;
+ public byte [] datadata;
+ public int flags;
+
+ public __db_get_msg() {
+ }
+
+ public __db_get_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(keydlen);
+ xdr.xdrEncodeInt(keydoff);
+ xdr.xdrEncodeInt(keyulen);
+ xdr.xdrEncodeInt(keyflags);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeInt(datadlen);
+ xdr.xdrEncodeInt(datadoff);
+ xdr.xdrEncodeInt(dataulen);
+ xdr.xdrEncodeInt(dataflags);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ keydlen = xdr.xdrDecodeInt();
+ keydoff = xdr.xdrDecodeInt();
+ keyulen = xdr.xdrDecodeInt();
+ keyflags = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ datadlen = xdr.xdrDecodeInt();
+ datadoff = xdr.xdrDecodeInt();
+ dataulen = xdr.xdrDecodeInt();
+ dataflags = xdr.xdrDecodeInt();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_get_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_get_reply.java b/bdb/rpc_server/java/gen/__db_get_reply.java
new file mode 100644
index 00000000000..64ce525728a
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_get_reply.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_get_reply implements XdrAble {
+ public int status;
+ public byte [] keydata;
+ public byte [] datadata;
+
+ public __db_get_reply() {
+ }
+
+ public __db_get_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ }
+
+}
+// End of __db_get_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_h_ffactor_msg.java b/bdb/rpc_server/java/gen/__db_h_ffactor_msg.java
new file mode 100644
index 00000000000..8d2ed1b1c0b
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_h_ffactor_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_h_ffactor_msg implements XdrAble {
+ public int dbpcl_id;
+ public int ffactor;
+
+ public __db_h_ffactor_msg() {
+ }
+
+ public __db_h_ffactor_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(ffactor);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ ffactor = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_h_ffactor_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_h_ffactor_reply.java b/bdb/rpc_server/java/gen/__db_h_ffactor_reply.java
new file mode 100644
index 00000000000..1885ec50240
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_h_ffactor_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_h_ffactor_reply implements XdrAble {
+ public int status;
+
+ public __db_h_ffactor_reply() {
+ }
+
+ public __db_h_ffactor_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_h_ffactor_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_h_nelem_msg.java b/bdb/rpc_server/java/gen/__db_h_nelem_msg.java
new file mode 100644
index 00000000000..7d084351755
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_h_nelem_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_h_nelem_msg implements XdrAble {
+ public int dbpcl_id;
+ public int nelem;
+
+ public __db_h_nelem_msg() {
+ }
+
+ public __db_h_nelem_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(nelem);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ nelem = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_h_nelem_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_h_nelem_reply.java b/bdb/rpc_server/java/gen/__db_h_nelem_reply.java
new file mode 100644
index 00000000000..20c5c774e69
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_h_nelem_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_h_nelem_reply implements XdrAble {
+ public int status;
+
+ public __db_h_nelem_reply() {
+ }
+
+ public __db_h_nelem_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_h_nelem_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_join_msg.java b/bdb/rpc_server/java/gen/__db_join_msg.java
new file mode 100644
index 00000000000..88c72dbd6ba
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_join_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_join_msg implements XdrAble {
+ public int dbpcl_id;
+ public int [] curs;
+ public int flags;
+
+ public __db_join_msg() {
+ }
+
+ public __db_join_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeIntVector(curs);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ curs = xdr.xdrDecodeIntVector();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_join_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_join_reply.java b/bdb/rpc_server/java/gen/__db_join_reply.java
new file mode 100644
index 00000000000..80980e23d6c
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_join_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_join_reply implements XdrAble {
+ public int status;
+ public int dbcidcl_id;
+
+ public __db_join_reply() {
+ }
+
+ public __db_join_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(dbcidcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ dbcidcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_join_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_key_range_msg.java b/bdb/rpc_server/java/gen/__db_key_range_msg.java
new file mode 100644
index 00000000000..233077e0964
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_key_range_msg.java
@@ -0,0 +1,53 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_key_range_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int keydlen;
+ public int keydoff;
+ public int keyulen;
+ public int keyflags;
+ public byte [] keydata;
+ public int flags;
+
+ public __db_key_range_msg() {
+ }
+
+ public __db_key_range_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(keydlen);
+ xdr.xdrEncodeInt(keydoff);
+ xdr.xdrEncodeInt(keyulen);
+ xdr.xdrEncodeInt(keyflags);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ keydlen = xdr.xdrDecodeInt();
+ keydoff = xdr.xdrDecodeInt();
+ keyulen = xdr.xdrDecodeInt();
+ keyflags = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_key_range_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_key_range_reply.java b/bdb/rpc_server/java/gen/__db_key_range_reply.java
new file mode 100644
index 00000000000..09244c13d1d
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_key_range_reply.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_key_range_reply implements XdrAble {
+ public int status;
+ public double less;
+ public double equal;
+ public double greater;
+
+ public __db_key_range_reply() {
+ }
+
+ public __db_key_range_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDouble(less);
+ xdr.xdrEncodeDouble(equal);
+ xdr.xdrEncodeDouble(greater);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ less = xdr.xdrDecodeDouble();
+ equal = xdr.xdrDecodeDouble();
+ greater = xdr.xdrDecodeDouble();
+ }
+
+}
+// End of __db_key_range_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_lorder_msg.java b/bdb/rpc_server/java/gen/__db_lorder_msg.java
new file mode 100644
index 00000000000..3399ad8daf0
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_lorder_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_lorder_msg implements XdrAble {
+ public int dbpcl_id;
+ public int lorder;
+
+ public __db_lorder_msg() {
+ }
+
+ public __db_lorder_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(lorder);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ lorder = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_lorder_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_lorder_reply.java b/bdb/rpc_server/java/gen/__db_lorder_reply.java
new file mode 100644
index 00000000000..cdcda4d4f43
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_lorder_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_lorder_reply implements XdrAble {
+ public int status;
+
+ public __db_lorder_reply() {
+ }
+
+ public __db_lorder_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_lorder_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_open_msg.java b/bdb/rpc_server/java/gen/__db_open_msg.java
new file mode 100644
index 00000000000..14dbd9e3b0c
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_open_msg.java
@@ -0,0 +1,50 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 2/13/02 1:05 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_open_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public String name;
+ public String subdb;
+ public int type;
+ public int flags;
+ public int mode;
+
+ public __db_open_msg() {
+ }
+
+ public __db_open_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeString(name);
+ xdr.xdrEncodeString(subdb);
+ xdr.xdrEncodeInt(type);
+ xdr.xdrEncodeInt(flags);
+ xdr.xdrEncodeInt(mode);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ name = xdr.xdrDecodeString();
+ subdb = xdr.xdrDecodeString();
+ type = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ mode = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_open_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_open_reply.java b/bdb/rpc_server/java/gen/__db_open_reply.java
new file mode 100644
index 00000000000..d90c3754c2f
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_open_reply.java
@@ -0,0 +1,44 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_open_reply implements XdrAble {
+ public int status;
+ public int dbcl_id;
+ public int type;
+ public int dbflags;
+ public int lorder;
+
+ public __db_open_reply() {
+ }
+
+ public __db_open_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(dbcl_id);
+ xdr.xdrEncodeInt(type);
+ xdr.xdrEncodeInt(dbflags);
+ xdr.xdrEncodeInt(lorder);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ dbcl_id = xdr.xdrDecodeInt();
+ type = xdr.xdrDecodeInt();
+ dbflags = xdr.xdrDecodeInt();
+ lorder = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_open_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_pagesize_msg.java b/bdb/rpc_server/java/gen/__db_pagesize_msg.java
new file mode 100644
index 00000000000..a452ea4e381
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_pagesize_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_pagesize_msg implements XdrAble {
+ public int dbpcl_id;
+ public int pagesize;
+
+ public __db_pagesize_msg() {
+ }
+
+ public __db_pagesize_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(pagesize);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ pagesize = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_pagesize_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_pagesize_reply.java b/bdb/rpc_server/java/gen/__db_pagesize_reply.java
new file mode 100644
index 00000000000..830b2078b34
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_pagesize_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_pagesize_reply implements XdrAble {
+ public int status;
+
+ public __db_pagesize_reply() {
+ }
+
+ public __db_pagesize_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_pagesize_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_pget_msg.java b/bdb/rpc_server/java/gen/__db_pget_msg.java
new file mode 100644
index 00000000000..11d27ca9e46
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_pget_msg.java
@@ -0,0 +1,83 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_pget_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int skeydlen;
+ public int skeydoff;
+ public int skeyulen;
+ public int skeyflags;
+ public byte [] skeydata;
+ public int pkeydlen;
+ public int pkeydoff;
+ public int pkeyulen;
+ public int pkeyflags;
+ public byte [] pkeydata;
+ public int datadlen;
+ public int datadoff;
+ public int dataulen;
+ public int dataflags;
+ public byte [] datadata;
+ public int flags;
+
+ public __db_pget_msg() {
+ }
+
+ public __db_pget_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(skeydlen);
+ xdr.xdrEncodeInt(skeydoff);
+ xdr.xdrEncodeInt(skeyulen);
+ xdr.xdrEncodeInt(skeyflags);
+ xdr.xdrEncodeDynamicOpaque(skeydata);
+ xdr.xdrEncodeInt(pkeydlen);
+ xdr.xdrEncodeInt(pkeydoff);
+ xdr.xdrEncodeInt(pkeyulen);
+ xdr.xdrEncodeInt(pkeyflags);
+ xdr.xdrEncodeDynamicOpaque(pkeydata);
+ xdr.xdrEncodeInt(datadlen);
+ xdr.xdrEncodeInt(datadoff);
+ xdr.xdrEncodeInt(dataulen);
+ xdr.xdrEncodeInt(dataflags);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ skeydlen = xdr.xdrDecodeInt();
+ skeydoff = xdr.xdrDecodeInt();
+ skeyulen = xdr.xdrDecodeInt();
+ skeyflags = xdr.xdrDecodeInt();
+ skeydata = xdr.xdrDecodeDynamicOpaque();
+ pkeydlen = xdr.xdrDecodeInt();
+ pkeydoff = xdr.xdrDecodeInt();
+ pkeyulen = xdr.xdrDecodeInt();
+ pkeyflags = xdr.xdrDecodeInt();
+ pkeydata = xdr.xdrDecodeDynamicOpaque();
+ datadlen = xdr.xdrDecodeInt();
+ datadoff = xdr.xdrDecodeInt();
+ dataulen = xdr.xdrDecodeInt();
+ dataflags = xdr.xdrDecodeInt();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_pget_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_pget_reply.java b/bdb/rpc_server/java/gen/__db_pget_reply.java
new file mode 100644
index 00000000000..86c9c2111b9
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_pget_reply.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_pget_reply implements XdrAble {
+ public int status;
+ public byte [] skeydata;
+ public byte [] pkeydata;
+ public byte [] datadata;
+
+ public __db_pget_reply() {
+ }
+
+ public __db_pget_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDynamicOpaque(skeydata);
+ xdr.xdrEncodeDynamicOpaque(pkeydata);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ skeydata = xdr.xdrDecodeDynamicOpaque();
+ pkeydata = xdr.xdrDecodeDynamicOpaque();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ }
+
+}
+// End of __db_pget_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_put_msg.java b/bdb/rpc_server/java/gen/__db_put_msg.java
new file mode 100644
index 00000000000..b6159cff3a8
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_put_msg.java
@@ -0,0 +1,68 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_put_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int keydlen;
+ public int keydoff;
+ public int keyulen;
+ public int keyflags;
+ public byte [] keydata;
+ public int datadlen;
+ public int datadoff;
+ public int dataulen;
+ public int dataflags;
+ public byte [] datadata;
+ public int flags;
+
+ public __db_put_msg() {
+ }
+
+ public __db_put_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(keydlen);
+ xdr.xdrEncodeInt(keydoff);
+ xdr.xdrEncodeInt(keyulen);
+ xdr.xdrEncodeInt(keyflags);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeInt(datadlen);
+ xdr.xdrEncodeInt(datadoff);
+ xdr.xdrEncodeInt(dataulen);
+ xdr.xdrEncodeInt(dataflags);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ keydlen = xdr.xdrDecodeInt();
+ keydoff = xdr.xdrDecodeInt();
+ keyulen = xdr.xdrDecodeInt();
+ keyflags = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ datadlen = xdr.xdrDecodeInt();
+ datadoff = xdr.xdrDecodeInt();
+ dataulen = xdr.xdrDecodeInt();
+ dataflags = xdr.xdrDecodeInt();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_put_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_put_reply.java b/bdb/rpc_server/java/gen/__db_put_reply.java
new file mode 100644
index 00000000000..fc89ae1c3bd
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_put_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_put_reply implements XdrAble {
+ public int status;
+ public byte [] keydata;
+
+ public __db_put_reply() {
+ }
+
+ public __db_put_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ }
+
+}
+// End of __db_put_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_re_delim_msg.java b/bdb/rpc_server/java/gen/__db_re_delim_msg.java
new file mode 100644
index 00000000000..c386bddd256
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_re_delim_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_re_delim_msg implements XdrAble {
+ public int dbpcl_id;
+ public int delim;
+
+ public __db_re_delim_msg() {
+ }
+
+ public __db_re_delim_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(delim);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ delim = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_re_delim_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_re_delim_reply.java b/bdb/rpc_server/java/gen/__db_re_delim_reply.java
new file mode 100644
index 00000000000..aa8a797f53d
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_re_delim_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_re_delim_reply implements XdrAble {
+ public int status;
+
+ public __db_re_delim_reply() {
+ }
+
+ public __db_re_delim_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_re_delim_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_re_len_msg.java b/bdb/rpc_server/java/gen/__db_re_len_msg.java
new file mode 100644
index 00000000000..664de5c899c
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_re_len_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_re_len_msg implements XdrAble {
+ public int dbpcl_id;
+ public int len;
+
+ public __db_re_len_msg() {
+ }
+
+ public __db_re_len_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(len);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ len = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_re_len_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_re_len_reply.java b/bdb/rpc_server/java/gen/__db_re_len_reply.java
new file mode 100644
index 00000000000..dda27c8c123
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_re_len_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_re_len_reply implements XdrAble {
+ public int status;
+
+ public __db_re_len_reply() {
+ }
+
+ public __db_re_len_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_re_len_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_re_pad_msg.java b/bdb/rpc_server/java/gen/__db_re_pad_msg.java
new file mode 100644
index 00000000000..2c1290b6e74
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_re_pad_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_re_pad_msg implements XdrAble {
+ public int dbpcl_id;
+ public int pad;
+
+ public __db_re_pad_msg() {
+ }
+
+ public __db_re_pad_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(pad);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ pad = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_re_pad_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_re_pad_reply.java b/bdb/rpc_server/java/gen/__db_re_pad_reply.java
new file mode 100644
index 00000000000..f0aaa9a3a70
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_re_pad_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_re_pad_reply implements XdrAble {
+ public int status;
+
+ public __db_re_pad_reply() {
+ }
+
+ public __db_re_pad_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_re_pad_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_remove_msg.java b/bdb/rpc_server/java/gen/__db_remove_msg.java
new file mode 100644
index 00000000000..dfa9066a7ec
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_remove_msg.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_remove_msg implements XdrAble {
+ public int dbpcl_id;
+ public String name;
+ public String subdb;
+ public int flags;
+
+ public __db_remove_msg() {
+ }
+
+ public __db_remove_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeString(name);
+ xdr.xdrEncodeString(subdb);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ name = xdr.xdrDecodeString();
+ subdb = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_remove_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_remove_reply.java b/bdb/rpc_server/java/gen/__db_remove_reply.java
new file mode 100644
index 00000000000..a2b86c04985
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_remove_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_remove_reply implements XdrAble {
+ public int status;
+
+ public __db_remove_reply() {
+ }
+
+ public __db_remove_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_remove_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_rename_msg.java b/bdb/rpc_server/java/gen/__db_rename_msg.java
new file mode 100644
index 00000000000..12b434e3375
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_rename_msg.java
@@ -0,0 +1,44 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_rename_msg implements XdrAble {
+ public int dbpcl_id;
+ public String name;
+ public String subdb;
+ public String newname;
+ public int flags;
+
+ public __db_rename_msg() {
+ }
+
+ public __db_rename_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeString(name);
+ xdr.xdrEncodeString(subdb);
+ xdr.xdrEncodeString(newname);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ name = xdr.xdrDecodeString();
+ subdb = xdr.xdrDecodeString();
+ newname = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_rename_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_rename_reply.java b/bdb/rpc_server/java/gen/__db_rename_reply.java
new file mode 100644
index 00000000000..4e4a22be570
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_rename_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_rename_reply implements XdrAble {
+ public int status;
+
+ public __db_rename_reply() {
+ }
+
+ public __db_rename_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_rename_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_stat_msg.java b/bdb/rpc_server/java/gen/__db_stat_msg.java
new file mode 100644
index 00000000000..af536b5f707
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_stat_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_stat_msg implements XdrAble {
+ public int dbpcl_id;
+ public int flags;
+
+ public __db_stat_msg() {
+ }
+
+ public __db_stat_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_stat_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_stat_reply.java b/bdb/rpc_server/java/gen/__db_stat_reply.java
new file mode 100644
index 00000000000..8df1460149a
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_stat_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_stat_reply implements XdrAble {
+ public int status;
+ public int [] stats;
+
+ public __db_stat_reply() {
+ }
+
+ public __db_stat_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeIntVector(stats);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ stats = xdr.xdrDecodeIntVector();
+ }
+
+}
+// End of __db_stat_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_sync_msg.java b/bdb/rpc_server/java/gen/__db_sync_msg.java
new file mode 100644
index 00000000000..c6594670fc6
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_sync_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_sync_msg implements XdrAble {
+ public int dbpcl_id;
+ public int flags;
+
+ public __db_sync_msg() {
+ }
+
+ public __db_sync_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_sync_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_sync_reply.java b/bdb/rpc_server/java/gen/__db_sync_reply.java
new file mode 100644
index 00000000000..d0a8bc8b196
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_sync_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_sync_reply implements XdrAble {
+ public int status;
+
+ public __db_sync_reply() {
+ }
+
+ public __db_sync_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_sync_reply.java
diff --git a/bdb/rpc_server/java/gen/__db_truncate_msg.java b/bdb/rpc_server/java/gen/__db_truncate_msg.java
new file mode 100644
index 00000000000..38810d65660
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_truncate_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_truncate_msg implements XdrAble {
+ public int dbpcl_id;
+ public int txnpcl_id;
+ public int flags;
+
+ public __db_truncate_msg() {
+ }
+
+ public __db_truncate_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbpcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbpcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_truncate_msg.java
diff --git a/bdb/rpc_server/java/gen/__db_truncate_reply.java b/bdb/rpc_server/java/gen/__db_truncate_reply.java
new file mode 100644
index 00000000000..c4f68869007
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__db_truncate_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __db_truncate_reply implements XdrAble {
+ public int status;
+ public int count;
+
+ public __db_truncate_reply() {
+ }
+
+ public __db_truncate_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(count);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ count = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __db_truncate_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_close_msg.java b/bdb/rpc_server/java/gen/__dbc_close_msg.java
new file mode 100644
index 00000000000..eb1ca7f7e17
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_close_msg.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_close_msg implements XdrAble {
+ public int dbccl_id;
+
+ public __dbc_close_msg() {
+ }
+
+ public __dbc_close_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_close_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_close_reply.java b/bdb/rpc_server/java/gen/__dbc_close_reply.java
new file mode 100644
index 00000000000..47459aace36
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_close_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_close_reply implements XdrAble {
+ public int status;
+
+ public __dbc_close_reply() {
+ }
+
+ public __dbc_close_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_close_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_count_msg.java b/bdb/rpc_server/java/gen/__dbc_count_msg.java
new file mode 100644
index 00000000000..5f554e18a1b
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_count_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_count_msg implements XdrAble {
+ public int dbccl_id;
+ public int flags;
+
+ public __dbc_count_msg() {
+ }
+
+ public __dbc_count_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_count_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_count_reply.java b/bdb/rpc_server/java/gen/__dbc_count_reply.java
new file mode 100644
index 00000000000..4daecdd2296
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_count_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_count_reply implements XdrAble {
+ public int status;
+ public int dupcount;
+
+ public __dbc_count_reply() {
+ }
+
+ public __dbc_count_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(dupcount);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ dupcount = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_count_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_del_msg.java b/bdb/rpc_server/java/gen/__dbc_del_msg.java
new file mode 100644
index 00000000000..bc4bd05f573
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_del_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_del_msg implements XdrAble {
+ public int dbccl_id;
+ public int flags;
+
+ public __dbc_del_msg() {
+ }
+
+ public __dbc_del_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_del_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_del_reply.java b/bdb/rpc_server/java/gen/__dbc_del_reply.java
new file mode 100644
index 00000000000..e55ac9ffaf6
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_del_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_del_reply implements XdrAble {
+ public int status;
+
+ public __dbc_del_reply() {
+ }
+
+ public __dbc_del_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_del_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_dup_msg.java b/bdb/rpc_server/java/gen/__dbc_dup_msg.java
new file mode 100644
index 00000000000..9a3894e6158
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_dup_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_dup_msg implements XdrAble {
+ public int dbccl_id;
+ public int flags;
+
+ public __dbc_dup_msg() {
+ }
+
+ public __dbc_dup_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_dup_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_dup_reply.java b/bdb/rpc_server/java/gen/__dbc_dup_reply.java
new file mode 100644
index 00000000000..6b942f1a61a
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_dup_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_dup_reply implements XdrAble {
+ public int status;
+ public int dbcidcl_id;
+
+ public __dbc_dup_reply() {
+ }
+
+ public __dbc_dup_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(dbcidcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ dbcidcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_dup_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_get_msg.java b/bdb/rpc_server/java/gen/__dbc_get_msg.java
new file mode 100644
index 00000000000..672ace43fdd
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_get_msg.java
@@ -0,0 +1,65 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_get_msg implements XdrAble {
+ public int dbccl_id;
+ public int keydlen;
+ public int keydoff;
+ public int keyulen;
+ public int keyflags;
+ public byte [] keydata;
+ public int datadlen;
+ public int datadoff;
+ public int dataulen;
+ public int dataflags;
+ public byte [] datadata;
+ public int flags;
+
+ public __dbc_get_msg() {
+ }
+
+ public __dbc_get_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ xdr.xdrEncodeInt(keydlen);
+ xdr.xdrEncodeInt(keydoff);
+ xdr.xdrEncodeInt(keyulen);
+ xdr.xdrEncodeInt(keyflags);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeInt(datadlen);
+ xdr.xdrEncodeInt(datadoff);
+ xdr.xdrEncodeInt(dataulen);
+ xdr.xdrEncodeInt(dataflags);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ keydlen = xdr.xdrDecodeInt();
+ keydoff = xdr.xdrDecodeInt();
+ keyulen = xdr.xdrDecodeInt();
+ keyflags = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ datadlen = xdr.xdrDecodeInt();
+ datadoff = xdr.xdrDecodeInt();
+ dataulen = xdr.xdrDecodeInt();
+ dataflags = xdr.xdrDecodeInt();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_get_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_get_reply.java b/bdb/rpc_server/java/gen/__dbc_get_reply.java
new file mode 100644
index 00000000000..8671fec6335
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_get_reply.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_get_reply implements XdrAble {
+ public int status;
+ public byte [] keydata;
+ public byte [] datadata;
+
+ public __dbc_get_reply() {
+ }
+
+ public __dbc_get_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ }
+
+}
+// End of __dbc_get_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_pget_msg.java b/bdb/rpc_server/java/gen/__dbc_pget_msg.java
new file mode 100644
index 00000000000..8ca3c6171a1
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_pget_msg.java
@@ -0,0 +1,80 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_pget_msg implements XdrAble {
+ public int dbccl_id;
+ public int skeydlen;
+ public int skeydoff;
+ public int skeyulen;
+ public int skeyflags;
+ public byte [] skeydata;
+ public int pkeydlen;
+ public int pkeydoff;
+ public int pkeyulen;
+ public int pkeyflags;
+ public byte [] pkeydata;
+ public int datadlen;
+ public int datadoff;
+ public int dataulen;
+ public int dataflags;
+ public byte [] datadata;
+ public int flags;
+
+ public __dbc_pget_msg() {
+ }
+
+ public __dbc_pget_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ xdr.xdrEncodeInt(skeydlen);
+ xdr.xdrEncodeInt(skeydoff);
+ xdr.xdrEncodeInt(skeyulen);
+ xdr.xdrEncodeInt(skeyflags);
+ xdr.xdrEncodeDynamicOpaque(skeydata);
+ xdr.xdrEncodeInt(pkeydlen);
+ xdr.xdrEncodeInt(pkeydoff);
+ xdr.xdrEncodeInt(pkeyulen);
+ xdr.xdrEncodeInt(pkeyflags);
+ xdr.xdrEncodeDynamicOpaque(pkeydata);
+ xdr.xdrEncodeInt(datadlen);
+ xdr.xdrEncodeInt(datadoff);
+ xdr.xdrEncodeInt(dataulen);
+ xdr.xdrEncodeInt(dataflags);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ skeydlen = xdr.xdrDecodeInt();
+ skeydoff = xdr.xdrDecodeInt();
+ skeyulen = xdr.xdrDecodeInt();
+ skeyflags = xdr.xdrDecodeInt();
+ skeydata = xdr.xdrDecodeDynamicOpaque();
+ pkeydlen = xdr.xdrDecodeInt();
+ pkeydoff = xdr.xdrDecodeInt();
+ pkeyulen = xdr.xdrDecodeInt();
+ pkeyflags = xdr.xdrDecodeInt();
+ pkeydata = xdr.xdrDecodeDynamicOpaque();
+ datadlen = xdr.xdrDecodeInt();
+ datadoff = xdr.xdrDecodeInt();
+ dataulen = xdr.xdrDecodeInt();
+ dataflags = xdr.xdrDecodeInt();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_pget_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_pget_reply.java b/bdb/rpc_server/java/gen/__dbc_pget_reply.java
new file mode 100644
index 00000000000..16cc795878d
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_pget_reply.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_pget_reply implements XdrAble {
+ public int status;
+ public byte [] skeydata;
+ public byte [] pkeydata;
+ public byte [] datadata;
+
+ public __dbc_pget_reply() {
+ }
+
+ public __dbc_pget_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDynamicOpaque(skeydata);
+ xdr.xdrEncodeDynamicOpaque(pkeydata);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ skeydata = xdr.xdrDecodeDynamicOpaque();
+ pkeydata = xdr.xdrDecodeDynamicOpaque();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ }
+
+}
+// End of __dbc_pget_reply.java
diff --git a/bdb/rpc_server/java/gen/__dbc_put_msg.java b/bdb/rpc_server/java/gen/__dbc_put_msg.java
new file mode 100644
index 00000000000..98d12423dc5
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_put_msg.java
@@ -0,0 +1,65 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_put_msg implements XdrAble {
+ public int dbccl_id;
+ public int keydlen;
+ public int keydoff;
+ public int keyulen;
+ public int keyflags;
+ public byte [] keydata;
+ public int datadlen;
+ public int datadoff;
+ public int dataulen;
+ public int dataflags;
+ public byte [] datadata;
+ public int flags;
+
+ public __dbc_put_msg() {
+ }
+
+ public __dbc_put_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbccl_id);
+ xdr.xdrEncodeInt(keydlen);
+ xdr.xdrEncodeInt(keydoff);
+ xdr.xdrEncodeInt(keyulen);
+ xdr.xdrEncodeInt(keyflags);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ xdr.xdrEncodeInt(datadlen);
+ xdr.xdrEncodeInt(datadoff);
+ xdr.xdrEncodeInt(dataulen);
+ xdr.xdrEncodeInt(dataflags);
+ xdr.xdrEncodeDynamicOpaque(datadata);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbccl_id = xdr.xdrDecodeInt();
+ keydlen = xdr.xdrDecodeInt();
+ keydoff = xdr.xdrDecodeInt();
+ keyulen = xdr.xdrDecodeInt();
+ keyflags = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ datadlen = xdr.xdrDecodeInt();
+ datadoff = xdr.xdrDecodeInt();
+ dataulen = xdr.xdrDecodeInt();
+ dataflags = xdr.xdrDecodeInt();
+ datadata = xdr.xdrDecodeDynamicOpaque();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __dbc_put_msg.java
diff --git a/bdb/rpc_server/java/gen/__dbc_put_reply.java b/bdb/rpc_server/java/gen/__dbc_put_reply.java
new file mode 100644
index 00000000000..385f9f783fb
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__dbc_put_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __dbc_put_reply implements XdrAble {
+ public int status;
+ public byte [] keydata;
+
+ public __dbc_put_reply() {
+ }
+
+ public __dbc_put_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeDynamicOpaque(keydata);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ keydata = xdr.xdrDecodeDynamicOpaque();
+ }
+
+}
+// End of __dbc_put_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_cachesize_msg.java b/bdb/rpc_server/java/gen/__env_cachesize_msg.java
new file mode 100644
index 00000000000..d1fce1ffa35
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_cachesize_msg.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_cachesize_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int gbytes;
+ public int bytes;
+ public int ncache;
+
+ public __env_cachesize_msg() {
+ }
+
+ public __env_cachesize_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(gbytes);
+ xdr.xdrEncodeInt(bytes);
+ xdr.xdrEncodeInt(ncache);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ gbytes = xdr.xdrDecodeInt();
+ bytes = xdr.xdrDecodeInt();
+ ncache = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_cachesize_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_cachesize_reply.java b/bdb/rpc_server/java/gen/__env_cachesize_reply.java
new file mode 100644
index 00000000000..193f8355d71
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_cachesize_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_cachesize_reply implements XdrAble {
+ public int status;
+
+ public __env_cachesize_reply() {
+ }
+
+ public __env_cachesize_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_cachesize_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_close_msg.java b/bdb/rpc_server/java/gen/__env_close_msg.java
new file mode 100644
index 00000000000..5e657bacfa5
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_close_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_close_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int flags;
+
+ public __env_close_msg() {
+ }
+
+ public __env_close_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_close_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_close_reply.java b/bdb/rpc_server/java/gen/__env_close_reply.java
new file mode 100644
index 00000000000..11e61f7c8c3
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_close_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_close_reply implements XdrAble {
+ public int status;
+
+ public __env_close_reply() {
+ }
+
+ public __env_close_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_close_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_create_msg.java b/bdb/rpc_server/java/gen/__env_create_msg.java
new file mode 100644
index 00000000000..dbe546ae23a
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_create_msg.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_create_msg implements XdrAble {
+ public int timeout;
+
+ public __env_create_msg() {
+ }
+
+ public __env_create_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(timeout);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ timeout = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_create_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_create_reply.java b/bdb/rpc_server/java/gen/__env_create_reply.java
new file mode 100644
index 00000000000..5427fc4bc1e
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_create_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_create_reply implements XdrAble {
+ public int status;
+ public int envcl_id;
+
+ public __env_create_reply() {
+ }
+
+ public __env_create_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(envcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ envcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_create_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_dbremove_msg.java b/bdb/rpc_server/java/gen/__env_dbremove_msg.java
new file mode 100644
index 00000000000..9730a92c590
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_dbremove_msg.java
@@ -0,0 +1,44 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_dbremove_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int txnpcl_id;
+ public String name;
+ public String subdb;
+ public int flags;
+
+ public __env_dbremove_msg() {
+ }
+
+ public __env_dbremove_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeString(name);
+ xdr.xdrEncodeString(subdb);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ name = xdr.xdrDecodeString();
+ subdb = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_dbremove_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_dbremove_reply.java b/bdb/rpc_server/java/gen/__env_dbremove_reply.java
new file mode 100644
index 00000000000..75cc5a940cc
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_dbremove_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_dbremove_reply implements XdrAble {
+ public int status;
+
+ public __env_dbremove_reply() {
+ }
+
+ public __env_dbremove_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_dbremove_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_dbrename_msg.java b/bdb/rpc_server/java/gen/__env_dbrename_msg.java
new file mode 100644
index 00000000000..0bbda262b64
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_dbrename_msg.java
@@ -0,0 +1,47 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_dbrename_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int txnpcl_id;
+ public String name;
+ public String subdb;
+ public String newname;
+ public int flags;
+
+ public __env_dbrename_msg() {
+ }
+
+ public __env_dbrename_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeString(name);
+ xdr.xdrEncodeString(subdb);
+ xdr.xdrEncodeString(newname);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ txnpcl_id = xdr.xdrDecodeInt();
+ name = xdr.xdrDecodeString();
+ subdb = xdr.xdrDecodeString();
+ newname = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_dbrename_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_dbrename_reply.java b/bdb/rpc_server/java/gen/__env_dbrename_reply.java
new file mode 100644
index 00000000000..0cc8882305d
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_dbrename_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_dbrename_reply implements XdrAble {
+ public int status;
+
+ public __env_dbrename_reply() {
+ }
+
+ public __env_dbrename_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_dbrename_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_encrypt_msg.java b/bdb/rpc_server/java/gen/__env_encrypt_msg.java
new file mode 100644
index 00000000000..84e9a36d372
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_encrypt_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 2/13/02 1:05 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_encrypt_msg implements XdrAble {
+ public int dbenvcl_id;
+ public String passwd;
+ public int flags;
+
+ public __env_encrypt_msg() {
+ }
+
+ public __env_encrypt_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeString(passwd);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ passwd = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_encrypt_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_encrypt_reply.java b/bdb/rpc_server/java/gen/__env_encrypt_reply.java
new file mode 100644
index 00000000000..e202a3089d0
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_encrypt_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 2/13/02 1:05 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_encrypt_reply implements XdrAble {
+ public int status;
+
+ public __env_encrypt_reply() {
+ }
+
+ public __env_encrypt_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_encrypt_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_flags_msg.java b/bdb/rpc_server/java/gen/__env_flags_msg.java
new file mode 100644
index 00000000000..25cd5f85f6d
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_flags_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_flags_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int flags;
+ public int onoff;
+
+ public __env_flags_msg() {
+ }
+
+ public __env_flags_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(flags);
+ xdr.xdrEncodeInt(onoff);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ onoff = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_flags_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_flags_reply.java b/bdb/rpc_server/java/gen/__env_flags_reply.java
new file mode 100644
index 00000000000..d348a9224ea
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_flags_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_flags_reply implements XdrAble {
+ public int status;
+
+ public __env_flags_reply() {
+ }
+
+ public __env_flags_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_flags_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_open_msg.java b/bdb/rpc_server/java/gen/__env_open_msg.java
new file mode 100644
index 00000000000..e4649b41f9e
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_open_msg.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_open_msg implements XdrAble {
+ public int dbenvcl_id;
+ public String home;
+ public int flags;
+ public int mode;
+
+ public __env_open_msg() {
+ }
+
+ public __env_open_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeString(home);
+ xdr.xdrEncodeInt(flags);
+ xdr.xdrEncodeInt(mode);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ home = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ mode = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_open_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_open_reply.java b/bdb/rpc_server/java/gen/__env_open_reply.java
new file mode 100644
index 00000000000..1994afb4cf2
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_open_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_open_reply implements XdrAble {
+ public int status;
+ public int envcl_id;
+
+ public __env_open_reply() {
+ }
+
+ public __env_open_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(envcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ envcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_open_reply.java
diff --git a/bdb/rpc_server/java/gen/__env_remove_msg.java b/bdb/rpc_server/java/gen/__env_remove_msg.java
new file mode 100644
index 00000000000..b32d758f0f5
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_remove_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_remove_msg implements XdrAble {
+ public int dbenvcl_id;
+ public String home;
+ public int flags;
+
+ public __env_remove_msg() {
+ }
+
+ public __env_remove_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeString(home);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ home = xdr.xdrDecodeString();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_remove_msg.java
diff --git a/bdb/rpc_server/java/gen/__env_remove_reply.java b/bdb/rpc_server/java/gen/__env_remove_reply.java
new file mode 100644
index 00000000000..19e4d52f662
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__env_remove_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __env_remove_reply implements XdrAble {
+ public int status;
+
+ public __env_remove_reply() {
+ }
+
+ public __env_remove_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __env_remove_reply.java
diff --git a/bdb/rpc_server/java/gen/__txn_abort_msg.java b/bdb/rpc_server/java/gen/__txn_abort_msg.java
new file mode 100644
index 00000000000..ff44c534e46
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_abort_msg.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_abort_msg implements XdrAble {
+ public int txnpcl_id;
+
+ public __txn_abort_msg() {
+ }
+
+ public __txn_abort_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(txnpcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ txnpcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_abort_msg.java
diff --git a/bdb/rpc_server/java/gen/__txn_abort_reply.java b/bdb/rpc_server/java/gen/__txn_abort_reply.java
new file mode 100644
index 00000000000..58f275c1a8f
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_abort_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_abort_reply implements XdrAble {
+ public int status;
+
+ public __txn_abort_reply() {
+ }
+
+ public __txn_abort_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_abort_reply.java
diff --git a/bdb/rpc_server/java/gen/__txn_begin_msg.java b/bdb/rpc_server/java/gen/__txn_begin_msg.java
new file mode 100644
index 00000000000..877031e8d3a
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_begin_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_begin_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int parentcl_id;
+ public int flags;
+
+ public __txn_begin_msg() {
+ }
+
+ public __txn_begin_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(parentcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ parentcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_begin_msg.java
diff --git a/bdb/rpc_server/java/gen/__txn_begin_reply.java b/bdb/rpc_server/java/gen/__txn_begin_reply.java
new file mode 100644
index 00000000000..65a0c4016c2
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_begin_reply.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_begin_reply implements XdrAble {
+ public int status;
+ public int txnidcl_id;
+
+ public __txn_begin_reply() {
+ }
+
+ public __txn_begin_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeInt(txnidcl_id);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ txnidcl_id = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_begin_reply.java
diff --git a/bdb/rpc_server/java/gen/__txn_commit_msg.java b/bdb/rpc_server/java/gen/__txn_commit_msg.java
new file mode 100644
index 00000000000..4b988d0c282
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_commit_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_commit_msg implements XdrAble {
+ public int txnpcl_id;
+ public int flags;
+
+ public __txn_commit_msg() {
+ }
+
+ public __txn_commit_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ txnpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_commit_msg.java
diff --git a/bdb/rpc_server/java/gen/__txn_commit_reply.java b/bdb/rpc_server/java/gen/__txn_commit_reply.java
new file mode 100644
index 00000000000..b26937b82dd
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_commit_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_commit_reply implements XdrAble {
+ public int status;
+
+ public __txn_commit_reply() {
+ }
+
+ public __txn_commit_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_commit_reply.java
diff --git a/bdb/rpc_server/java/gen/__txn_discard_msg.java b/bdb/rpc_server/java/gen/__txn_discard_msg.java
new file mode 100644
index 00000000000..87f5d4f77a7
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_discard_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_discard_msg implements XdrAble {
+ public int txnpcl_id;
+ public int flags;
+
+ public __txn_discard_msg() {
+ }
+
+ public __txn_discard_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ txnpcl_id = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_discard_msg.java
diff --git a/bdb/rpc_server/java/gen/__txn_discard_reply.java b/bdb/rpc_server/java/gen/__txn_discard_reply.java
new file mode 100644
index 00000000000..9792211afcc
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_discard_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_discard_reply implements XdrAble {
+ public int status;
+
+ public __txn_discard_reply() {
+ }
+
+ public __txn_discard_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_discard_reply.java
diff --git a/bdb/rpc_server/java/gen/__txn_prepare_msg.java b/bdb/rpc_server/java/gen/__txn_prepare_msg.java
new file mode 100644
index 00000000000..6e09f2c7771
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_prepare_msg.java
@@ -0,0 +1,35 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_prepare_msg implements XdrAble {
+ public int txnpcl_id;
+ public byte [] gid;
+
+ public __txn_prepare_msg() {
+ }
+
+ public __txn_prepare_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(txnpcl_id);
+ xdr.xdrEncodeOpaque(gid, 128);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ txnpcl_id = xdr.xdrDecodeInt();
+ gid = xdr.xdrDecodeOpaque(128);
+ }
+
+}
+// End of __txn_prepare_msg.java
diff --git a/bdb/rpc_server/java/gen/__txn_prepare_reply.java b/bdb/rpc_server/java/gen/__txn_prepare_reply.java
new file mode 100644
index 00000000000..d7590117952
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_prepare_reply.java
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_prepare_reply implements XdrAble {
+ public int status;
+
+ public __txn_prepare_reply() {
+ }
+
+ public __txn_prepare_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_prepare_reply.java
diff --git a/bdb/rpc_server/java/gen/__txn_recover_msg.java b/bdb/rpc_server/java/gen/__txn_recover_msg.java
new file mode 100644
index 00000000000..65153334403
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_recover_msg.java
@@ -0,0 +1,38 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_recover_msg implements XdrAble {
+ public int dbenvcl_id;
+ public int count;
+ public int flags;
+
+ public __txn_recover_msg() {
+ }
+
+ public __txn_recover_msg(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(dbenvcl_id);
+ xdr.xdrEncodeInt(count);
+ xdr.xdrEncodeInt(flags);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ dbenvcl_id = xdr.xdrDecodeInt();
+ count = xdr.xdrDecodeInt();
+ flags = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_recover_msg.java
diff --git a/bdb/rpc_server/java/gen/__txn_recover_reply.java b/bdb/rpc_server/java/gen/__txn_recover_reply.java
new file mode 100644
index 00000000000..0161ec949da
--- /dev/null
+++ b/bdb/rpc_server/java/gen/__txn_recover_reply.java
@@ -0,0 +1,41 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+public class __txn_recover_reply implements XdrAble {
+ public int status;
+ public int [] txn;
+ public byte [] gid;
+ public int retcount;
+
+ public __txn_recover_reply() {
+ }
+
+ public __txn_recover_reply(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ xdrDecode(xdr);
+ }
+
+ public void xdrEncode(XdrEncodingStream xdr)
+ throws OncRpcException, IOException {
+ xdr.xdrEncodeInt(status);
+ xdr.xdrEncodeIntVector(txn);
+ xdr.xdrEncodeDynamicOpaque(gid);
+ xdr.xdrEncodeInt(retcount);
+ }
+
+ public void xdrDecode(XdrDecodingStream xdr)
+ throws OncRpcException, IOException {
+ status = xdr.xdrDecodeInt();
+ txn = xdr.xdrDecodeIntVector();
+ gid = xdr.xdrDecodeDynamicOpaque();
+ retcount = xdr.xdrDecodeInt();
+ }
+
+}
+// End of __txn_recover_reply.java
diff --git a/bdb/rpc_server/java/gen/db_server.java b/bdb/rpc_server/java/gen/db_server.java
new file mode 100644
index 00000000000..a14a77028a2
--- /dev/null
+++ b/bdb/rpc_server/java/gen/db_server.java
@@ -0,0 +1,67 @@
+/*
+ * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
+ * See http://acplt.org/ks/remotetea.html for details
+ */
+package com.sleepycat.db.rpcserver;
+import org.acplt.oncrpc.*;
+import java.io.IOException;
+
+/**
+ * A collection of constants used by the "db_server" ONC/RPC program.
+ */
+public interface db_server {
+ public static final int __DB_db_close_4001 = 19;
+ public static final int __DB_db_flags_4001 = 24;
+ public static final int __DB_dbc_dup_4001 = 47;
+ public static final int __DB_db_encrypt_4001 = 22;
+ public static final int __DB_env_dbrename_4001 = 5;
+ public static final int __DB_env_remove_4001 = 9;
+ public static final int __DB_dbc_pget_4001 = 49;
+ public static final int __DB_env_cachesize_4001 = 1;
+ public static final int __DB_db_lorder_4001 = 29;
+ public static final int __DB_db_key_range_4001 = 28;
+ public static final int __DB_db_bt_minkey_4001 = 18;
+ public static final int __DB_db_sync_4001 = 40;
+ public static final int __DB_dbc_close_4001 = 44;
+ public static final int __DB_db_join_4001 = 43;
+ public static final int __DB_db_pagesize_4001 = 31;
+ public static final int DB_RPC_SERVERVERS = 4001;
+ public static final int __DB_db_open_4001 = 30;
+ public static final int __DB_dbc_get_4001 = 48;
+ public static final int __DB_db_cursor_4001 = 42;
+ public static final int __DB_txn_commit_4001 = 12;
+ public static final int __DB_dbc_del_4001 = 46;
+ public static final int __DB_env_create_4001 = 3;
+ public static final int __DB_env_open_4001 = 8;
+ public static final int __DB_txn_prepare_4001 = 14;
+ public static final int __DB_db_pget_4001 = 32;
+ public static final int __DB_db_stat_4001 = 39;
+ public static final int __DB_db_h_nelem_4001 = 27;
+ public static final int __DB_db_remove_4001 = 37;
+ public static final int __DB_db_re_delim_4001 = 34;
+ public static final int __DB_db_re_pad_4001 = 36;
+ public static final int __DB_txn_abort_4001 = 10;
+ public static final int __DB_txn_recover_4001 = 15;
+ public static final int __DB_db_get_4001 = 25;
+ public static final int __DB_db_extentsize_4001 = 23;
+ public static final int DB_RPC_SERVERPROG = 351457;
+ public static final int __DB_dbc_put_4001 = 50;
+ public static final int __DB_db_truncate_4001 = 41;
+ public static final int __DB_db_del_4001 = 21;
+ public static final int __DB_db_bt_maxkey_4001 = 17;
+ public static final int __DB_env_dbremove_4001 = 4;
+ public static final int __DB_txn_discard_4001 = 13;
+ public static final int __DB_db_re_len_4001 = 35;
+ public static final int __DB_env_close_4001 = 2;
+ public static final int __DB_env_flags_4001 = 7;
+ public static final int __DB_db_rename_4001 = 38;
+ public static final int __DB_db_associate_4001 = 16;
+ public static final int __DB_txn_begin_4001 = 11;
+ public static final int __DB_env_encrypt_4001 = 6;
+ public static final int __DB_db_h_ffactor_4001 = 26;
+ public static final int __DB_db_put_4001 = 33;
+ public static final int __DB_db_create_4001 = 20;
+ public static final int __DB_dbc_count_4001 = 45;
+}
+// End of db_server.java
diff --git a/bdb/rpc_server/java/jrpcgen.jar b/bdb/rpc_server/java/jrpcgen.jar
new file mode 100644
index 00000000000..338825b848d
--- /dev/null
+++ b/bdb/rpc_server/java/jrpcgen.jar
Binary files differ
diff --git a/bdb/rpc_server/java/oncrpc.jar b/bdb/rpc_server/java/oncrpc.jar
new file mode 100644
index 00000000000..e0f5cfa6966
--- /dev/null
+++ b/bdb/rpc_server/java/oncrpc.jar
Binary files differ
diff --git a/bdb/rpc_server/java/s_jrpcgen b/bdb/rpc_server/java/s_jrpcgen
new file mode 100644
index 00000000000..fed8cbf56bb
--- /dev/null
+++ b/bdb/rpc_server/java/s_jrpcgen
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+java -jar jrpcgen.jar -d gen -noclient -nobackup -p com.sleepycat.db.rpcserver -s DbServerStub ../db_server.x
diff --git a/bdb/rpc_server/rpc.src b/bdb/rpc_server/rpc.src
index 5dd25205136..7afee49b066 100644
--- a/bdb/rpc_server/rpc.src
+++ b/bdb/rpc_server/rpc.src
@@ -1,17 +1,17 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rpc.src,v 1.75 2002/07/18 02:57:19 margo Exp $
#
-# $Id: rpc.src,v 1.30 2000/12/20 21:53:05 ubell Exp $
# Syntax:
-# BEGIN function_name RPC # {CODE | NOCLNTCODE | RETCODE | NOFUNC}
+# BEGIN function_name {CODE | RETCODE | NOFUNC}
# CODE: generate XDR and client code, return status
# Used for functions that just return a status and nothing else.
# RETCODE:generate XDR and client code, call return function
# (generate template return function)
# Used for functions that returns data.
-# NOCLNTCODE: generate only XDR and server functions
-# Used for functions that are "different" on the client.
-# Primarily used for envcreate (which is called from
-# the dbenv->set_server method on the client side) and
-# dbcreate, which is called from non-generated code.
# NOFUNC: generate a client "unsupported function" with right args
# Used for unsupported functions.
#
@@ -19,9 +19,10 @@
# IGNORE: not passed to server
# STRING: string passed to server
# DBT: DBT arg passed to server
-# LIST: opaque list passed to server (NULL-terminated opaque list)
+# LIST: list passed to server (NULL-terminated list of something)
# INT: integer passed to server
# ID: cl_id from arg passed to server
+# GID: global id passed to server
# CONST: do not generate COMPQUIET (for NOFUNC only)
# FUNCPROT prototype
# FUNCARG functiontype
@@ -38,11 +39,11 @@
# All messages automatically return "status" and return that from
# the call to the function. RET's are additional things the server
# may return. RET is like ARG but does not need the IGNORE option.
-# RET {STRING | INT | DBT | LIST | ID} varname [STRING | INT | ID]
+# RET {STRING | INT | DBT | LIST | ID} varname [GID | INT | ID]
# STRING: string from server
# DBT: DBT arg from server
-# LIST: opaque list from server (NULL-terminated opaque list)
-# Must have list type of STRING, ID or INT specified
+# LIST: list from server (NULL-terminated list)
+# Must have list type of GID, ID or INT specified
# INT: integer from server
# ID: id from server stored in cl_id
# END function end.
@@ -50,122 +51,157 @@
#
# Environment functions
#
-BEGIN env_cachesize 1 CODE
+BEGIN env_alloc NOFUNC
+ARG ID DB_ENV * dbenv
+FUNCPROT void *(*)(size_t)
+FUNCARG void *(*func0) __P((size_t))
+FUNCPROT void *(*)(void *, size_t)
+FUNCARG void *(*func1) __P((void *, size_t))
+FUNCPROT void (*)(void *)
+FUNCARG void (*func2) __P((void *))
+END
+BEGIN set_app_dispatch NOFUNC
+ARG ID DB_ENV * dbenv
+FUNCPROT int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)
+FUNCARG int (*func0) __P((DB_ENV *, DBT *, DB_LSN *, db_recops))
+END
+BEGIN env_cachesize CODE
ARG ID DB_ENV * dbenv
ARG INT u_int32_t gbytes
ARG INT u_int32_t bytes
ARG INT int ncache
END
-BEGIN env_close 1 RETCODE
+BEGIN env_close RETCODE
ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
END
-BEGIN env_create 1 NOCLNTCODE
+BEGIN env_create RETCODE
+ARG IGNORE DB_ENV * dbenv
ARG INT long timeout
RET ID long env
END
-BEGIN set_data_dir 1 NOFUNC
+BEGIN set_data_dir NOFUNC
ARG ID DB_ENV * dbenv
ARG STRING const char * dir
END
-BEGIN env_set_feedback 1 NOFUNC
+BEGIN env_dbremove CODE
+ARG ID DB_ENV * dbenv
+ARG ID DB_TXN * txnp
+ARG STRING const char * name
+ARG STRING const char * subdb
+ARG INT u_int32_t flags
+END
+BEGIN env_dbrename CODE
+ARG ID DB_ENV * dbenv
+ARG ID DB_TXN * txnp
+ARG STRING const char * name
+ARG STRING const char * subdb
+ARG STRING const char * newname
+ARG INT u_int32_t flags
+END
+BEGIN env_encrypt CODE
+ARG ID DB_ENV * dbenv
+ARG STRING const char * passwd
+ARG INT u_int32_t flags
+END
+BEGIN env_set_feedback NOFUNC
ARG ID DB_ENV * dbenv
FUNCPROT void (*)(DB_ENV *, int, int)
FUNCARG void (*func0) __P((DB_ENV *, int, int))
END
-BEGIN env_flags 1 CODE
+BEGIN env_flags CODE
ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
ARG INT int onoff
END
-BEGIN set_lg_bsize 1 NOFUNC
+BEGIN set_lg_bsize NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t bsize
END
-BEGIN set_lg_dir 1 NOFUNC
+BEGIN set_lg_dir NOFUNC
ARG ID DB_ENV * dbenv
ARG STRING const char * dir
END
-BEGIN set_lg_max 1 NOFUNC
+BEGIN set_lg_max NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t max
END
-BEGIN set_lk_conflict 1 NOFUNC
+BEGIN set_lg_regionmax NOFUNC
+ARG ID DB_ENV * dbenv
+ARG INT u_int32_t max
+END
+BEGIN set_lk_conflict NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int8_t * conflicts
ARG INT int modes
END
-BEGIN set_lk_detect 1 NOFUNC
+BEGIN set_lk_detect NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t detect
END
-BEGIN set_lk_max 1 NOFUNC
+BEGIN set_lk_max NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t max
END
-BEGIN set_lk_max_locks 1 NOFUNC
+BEGIN set_lk_max_locks NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t max
END
-BEGIN set_lk_max_lockers 1 NOFUNC
+BEGIN set_lk_max_lockers NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t max
END
-BEGIN set_lk_max_objects 1 NOFUNC
+BEGIN set_lk_max_objects NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t max
END
-BEGIN set_mp_mmapsize 1 NOFUNC
+BEGIN set_mp_mmapsize NOFUNC
ARG ID DB_ENV * dbenv
ARG INT size_t mmapsize
END
-BEGIN set_mutex_locks 1 NOFUNC
-ARG ID DB_ENV * dbenv
-ARG INT int do_lock
-END
-BEGIN env_open 1 RETCODE
+BEGIN env_open RETCODE
ARG ID DB_ENV * dbenv
ARG STRING const char * home
ARG INT u_int32_t flags
ARG INT int mode
+RET ID long env
END
-BEGIN env_paniccall 1 NOFUNC
+BEGIN env_paniccall NOFUNC
ARG ID DB_ENV * dbenv
FUNCPROT void (*)(DB_ENV *, int)
FUNCARG void (*func0) __P((DB_ENV *, int))
END
-BEGIN set_recovery_init 1 NOFUNC
-ARG ID DB_ENV * dbenv
-FUNCPROT int (*)(DB_ENV *)
-FUNCARG int (*func0) __P((DB_ENV *))
-END
-BEGIN env_remove 1 RETCODE
+BEGIN env_remove RETCODE
ARG ID DB_ENV * dbenv
ARG STRING const char * home
ARG INT u_int32_t flags
END
-BEGIN set_shm_key 1 NOFUNC
+BEGIN set_shm_key NOFUNC
ARG ID DB_ENV * dbenv
ARG INT long shm_key
END
-BEGIN set_tmp_dir 1 NOFUNC
+BEGIN set_tas_spins NOFUNC
ARG ID DB_ENV * dbenv
-ARG STRING const char * dir
+ARG INT u_int32_t tas_spins
END
-BEGIN set_tx_recover 1 NOFUNC
+BEGIN set_timeout NOFUNC
ARG ID DB_ENV * dbenv
-FUNCPROT int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)
-FUNCARG int (*func0) __P((DB_ENV *, DBT *, DB_LSN *, db_recops))
+ARG INT u_int32_t timeout
+ARG INT u_int32_t flags
+END
+BEGIN set_tmp_dir NOFUNC
+ARG ID DB_ENV * dbenv
+ARG STRING const char * dir
END
-BEGIN set_tx_max 1 NOFUNC
+BEGIN set_tx_max NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t max
END
-BEGIN set_tx_timestamp 1 NOFUNC
+BEGIN set_tx_timestamp NOFUNC
ARG ID DB_ENV * dbenv
ARG INT time_t * max
END
-BEGIN set_verbose 1 NOFUNC
+BEGIN set_verbose NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t which
ARG INT int onoff
@@ -173,100 +209,197 @@ END
#
# Transaction functions
#
-BEGIN txn_abort 1 RETCODE
+BEGIN txn_abort RETCODE
ARG ID DB_TXN * txnp
END
-BEGIN txn_begin 1 RETCODE
-ARG ID DB_ENV * envp
+BEGIN txn_begin RETCODE
+ARG ID DB_ENV * dbenv
ARG ID DB_TXN * parent
ARG IGNORE DB_TXN ** txnpp
ARG INT u_int32_t flags
RET ID long txnid
END
-BEGIN txn_checkpoint 1 NOFUNC
+BEGIN txn_checkpoint NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t kbyte
ARG INT u_int32_t min
+ARG INT u_int32_t flags
+END
+BEGIN txn_commit RETCODE
+ARG ID DB_TXN * txnp
+ARG INT u_int32_t flags
END
-BEGIN txn_commit 1 RETCODE
+BEGIN txn_discard RETCODE
ARG ID DB_TXN * txnp
ARG INT u_int32_t flags
END
-BEGIN txn_prepare 1 NOFUNC
+BEGIN txn_prepare CODE
ARG ID DB_TXN * txnp
+ARG GID u_int8_t * gid
END
-BEGIN txn_stat 1 NOFUNC
+BEGIN txn_recover RETCODE
+ARG ID DB_ENV * dbenv
+ARG IGNORE DB_PREPLIST * preplist
+ARG INT long count
+ARG IGNORE long * retp
+ARG INT u_int32_t flags
+RET LIST DB_TXN * txn ID
+RET LIST u_int8_t * gid GID
+RET INT long retcount
+END
+BEGIN txn_stat NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE DB_TXN_STAT ** statp
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
+ARG INT u_int32_t flags
+END
+BEGIN txn_timeout NOFUNC
+ARG ID DB_TXN * txnp
+ARG INT u_int32_t timeout
+ARG INT u_int32_t flags
+END
+#
+# Replication functions
+#
+BEGIN rep_elect NOFUNC
+ARG ID DB_ENV * dbenv
+ARG INT int nsites
+ARG INT int pri
+ARG INT u_int32_t timeout
+ARG IGNORE int * idp
+END
+BEGIN rep_flush NOFUNC
+ARG ID DB_ENV * dbenv
+END
+BEGIN rep_process_message NOFUNC
+ARG ID DB_ENV * dbenv
+ARG DBT DBT * rec
+ARG DBT DBT * control
+ARG IGNORE int * idp
+END
+BEGIN rep_set_limit NOFUNC
+ARG ID DB_ENV * dbenv
+ARG INT u_int32_t mbytes
+ARG INT u_int32_t bytes
+END
+BEGIN rep_set_request NOFUNC
+ARG ID DB_ENV * dbenv
+ARG INT u_int32_t min
+ARG INT u_int32_t max
+END
+BEGIN rep_set_rep_transport NOFUNC
+ARG ID DB_ENV * dbenv
+ARG INT int id
+FUNCPROT int (*)(DB_ENV *, const DBT *, const DBT *, int, u_int32_t)
+FUNCARG int (*func0) __P((DB_ENV *, const DBT *, const DBT *, int, u_int32_t))
+END
+BEGIN rep_start NOFUNC
+ARG ID DB_ENV * dbenv
+ARG DBT DBT * cdata
+ARG INT u_int32_t flags
+END
+BEGIN rep_stat NOFUNC
+ARG ID DB_ENV * dbenv
+ARG IGNORE DB_REP_STAT ** statp
+ARG INT u_int32_t flags
END
#
# Database functions
#
-BEGIN db_bt_compare 1 NOFUNC
+BEGIN db_alloc NOFUNC
+ARG ID DB * dbp
+FUNCPROT void *(*)(size_t)
+FUNCARG void *(*func0) __P((size_t))
+FUNCPROT void *(*)(void *, size_t)
+FUNCARG void *(*func1) __P((void *, size_t))
+FUNCPROT void (*)(void *)
+FUNCARG void (*func2) __P((void *))
+END
+BEGIN db_associate CODE
+ARG ID DB * dbp
+ARG ID DB_TXN * txnp
+ARG ID DB * sdbp
+FUNCPROT int (*)(DB *, const DBT *, const DBT *, DBT *)
+FUNCARG int (*func0) __P((DB *, const DBT *, const DBT *, DBT *))
+ARG INT u_int32_t flags
+END
+BEGIN db_bt_compare NOFUNC
ARG ID DB * dbp
FUNCPROT int (*)(DB *, const DBT *, const DBT *)
FUNCARG int (*func0) __P((DB *, const DBT *, const DBT *))
END
-BEGIN db_bt_maxkey 1 CODE
+BEGIN db_bt_maxkey CODE
ARG ID DB * dbp
ARG INT u_int32_t maxkey
END
-BEGIN db_bt_minkey 1 CODE
+BEGIN db_bt_minkey CODE
ARG ID DB * dbp
ARG INT u_int32_t minkey
END
-BEGIN db_bt_prefix 1 NOFUNC
+BEGIN db_bt_prefix NOFUNC
ARG ID DB * dbp
FUNCPROT size_t(*)(DB *, const DBT *, const DBT *)
FUNCARG size_t (*func0) __P((DB *, const DBT *, const DBT *))
END
-BEGIN db_set_append_recno 1 NOFUNC
+BEGIN db_set_append_recno NOFUNC
ARG ID DB * dbp
FUNCPROT int (*)(DB *, DBT *, db_recno_t)
FUNCARG int (*func0) __P((DB *, DBT *, db_recno_t))
END
-BEGIN db_cachesize 1 NOFUNC
+BEGIN db_cache_priority NOFUNC
+ARG ID DB * dbp
+ARG INT DB_CACHE_PRIORITY priority
+END
+BEGIN db_cachesize NOFUNC
ARG ID DB * dbp
ARG INT u_int32_t gbytes
ARG INT u_int32_t bytes
ARG INT int ncache
END
-BEGIN db_close 1 RETCODE
+BEGIN db_close RETCODE
ARG ID DB * dbp
ARG INT u_int32_t flags
END
-BEGIN db_create 1 NOCLNTCODE
+BEGIN db_create RETCODE
+ARG IGNORE DB * dbp
+ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
-ARG ID DB_ENV * envp
-RET ID long dbp
+RET ID long db
END
-BEGIN db_del 1 CODE
+BEGIN db_del CODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
ARG INT u_int32_t flags
END
-BEGIN db_extentsize 1 CODE
+BEGIN db_dup_compare NOFUNC
+ARG ID DB * dbp
+FUNCPROT int (*)(DB *, const DBT *, const DBT *)
+FUNCARG int (*func0) __P((DB *, const DBT *, const DBT *))
+END
+BEGIN db_encrypt CODE
+ARG ID DB * dbp
+ARG STRING const char * passwd
+ARG INT u_int32_t flags
+END
+BEGIN db_extentsize CODE
ARG ID DB * dbp
ARG INT u_int32_t extentsize
END
-BEGIN db_fd 1 NOFUNC
+BEGIN db_fd NOFUNC
ARG ID DB * dbp
ARG IGNORE int * fdp
END
-BEGIN db_feedback 1 NOFUNC
+BEGIN db_feedback NOFUNC
ARG ID DB * dbp
FUNCPROT void (*)(DB *, int, int)
FUNCARG void (*func0) __P((DB *, int, int))
END
-BEGIN db_flags 1 CODE
+BEGIN db_flags CODE
ARG ID DB * dbp
ARG INT u_int32_t flags
END
-BEGIN db_get 1 RETCODE
+BEGIN db_get RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
@@ -275,20 +408,20 @@ ARG INT u_int32_t flags
RET DBT DBT * key
RET DBT DBT * data
END
-BEGIN db_h_ffactor 1 CODE
+BEGIN db_h_ffactor CODE
ARG ID DB * dbp
ARG INT u_int32_t ffactor
END
-BEGIN db_h_hash 1 NOFUNC
+BEGIN db_h_hash NOFUNC
ARG ID DB * dbp
FUNCPROT u_int32_t(*)(DB *, const void *, u_int32_t)
FUNCARG u_int32_t (*func0) __P((DB *, const void *, u_int32_t))
END
-BEGIN db_h_nelem 1 CODE
+BEGIN db_h_nelem CODE
ARG ID DB * dbp
ARG INT u_int32_t nelem
END
-BEGIN db_key_range 1 RETCODE
+BEGIN db_key_range RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
@@ -298,139 +431,152 @@ RET DBL double less
RET DBL double equal
RET DBL double greater
END
-BEGIN db_lorder 1 CODE
+BEGIN db_lorder CODE
ARG ID DB * dbp
ARG INT int lorder
END
-BEGIN db_malloc 1 NOFUNC
-ARG ID DB * dbp
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
-END
# XXX
# The line:
# RET INT u_int32_t dbflags
# should go away when a get_flags method exists. It is
# needed now because Tcl looks at dbp->flags.
#
-BEGIN db_open 1 RETCODE
+BEGIN db_open RETCODE
ARG ID DB * dbp
+ARG ID DB_TXN * txnp
ARG STRING const char * name
ARG STRING const char * subdb
ARG INT DBTYPE type
ARG INT u_int32_t flags
ARG INT int mode
+RET ID long db
RET INT DBTYPE type
RET INT u_int32_t dbflags
+RET INT int lorder
END
-BEGIN db_pagesize 1 CODE
+BEGIN db_pagesize CODE
ARG ID DB * dbp
ARG INT u_int32_t pagesize
END
-BEGIN db_panic 1 NOFUNC
+BEGIN db_panic NOFUNC
ARG ID DB * dbp
FUNCPROT void (*)(DB_ENV *, int)
FUNCARG void (*func0) __P((DB_ENV *, int))
END
-BEGIN db_put 1 RETCODE
+BEGIN db_pget RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
-ARG DBT DBT * key
+ARG DBT DBT * skey
+ARG DBT DBT * pkey
ARG DBT DBT * data
ARG INT u_int32_t flags
-RET DBT DBT * key
+RET DBT DBT * skey
+RET DBT DBT * pkey
+RET DBT DBT * data
END
-BEGIN db_realloc 1 NOFUNC
+BEGIN db_put RETCODE
ARG ID DB * dbp
-FUNCPROT void *(*)(void *, size_t)
-FUNCARG void *(*func0) __P((void *, size_t))
+ARG ID DB_TXN * txnp
+ARG DBT DBT * key
+ARG DBT DBT * data
+ARG INT u_int32_t flags
+RET DBT DBT * key
END
-BEGIN db_re_delim 1 CODE
+BEGIN db_re_delim CODE
ARG ID DB * dbp
ARG INT int delim
END
-BEGIN db_re_len 1 CODE
+BEGIN db_re_len CODE
ARG ID DB * dbp
ARG INT u_int32_t len
END
-BEGIN db_re_pad 1 CODE
+BEGIN db_re_pad CODE
ARG ID DB * dbp
ARG INT int pad
END
-BEGIN db_re_source 1 NOFUNC
+BEGIN db_re_source NOFUNC
ARG ID DB * dbp
ARG STRING const char * re_source
END
-BEGIN db_remove 1 RETCODE
+BEGIN db_remove RETCODE
ARG ID DB * dbp
ARG STRING const char * name
ARG STRING const char * subdb
ARG INT u_int32_t flags
END
-BEGIN db_rename 1 RETCODE
+BEGIN db_rename RETCODE
ARG ID DB * dbp
ARG STRING const char * name
ARG STRING const char * subdb
ARG STRING const char * newname
ARG INT u_int32_t flags
END
-BEGIN db_stat 1 RETCODE
+BEGIN db_stat RETCODE
ARG ID DB * dbp
ARG IGNORE void * sp
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
ARG INT u_int32_t flags
RET LIST u_int32_t * stats INT
END
-BEGIN db_swapped 1 CODE
+BEGIN db_sync CODE
ARG ID DB * dbp
+ARG INT u_int32_t flags
+END
+BEGIN db_truncate RETCODE
+ARG ID DB * dbp
+ARG ID DB_TXN * txnp
+ARG IGNORE u_int32_t * countp
+ARG INT u_int32_t flags
+RET INT u_int32_t count
END
-BEGIN db_sync 1 CODE
+BEGIN db_upgrade NOFUNC
ARG ID DB * dbp
+ARG STRING const char * fname
ARG INT u_int32_t flags
END
-BEGIN db_upgrade 1 NOFUNC
+BEGIN db_verify NOFUNC
ARG ID DB * dbp
ARG STRING const char * fname
+ARG STRING const char * subdb
+ARG IGNORE FILE * outfile
ARG INT u_int32_t flags
END
#
# Cursor functions
#
-BEGIN db_cursor 1 RETCODE
+BEGIN db_cursor RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG IGNORE DBC ** dbcpp
ARG INT u_int32_t flags
RET ID long dbcid
END
-BEGIN db_join 1 RETCODE
+BEGIN db_join RETCODE
ARG ID DB * dbp
ARG LIST DBC ** curs ID
ARG IGNORE DBC ** dbcp
ARG INT u_int32_t flags
RET ID long dbcid
END
-BEGIN dbc_close 1 RETCODE
+BEGIN dbc_close RETCODE
ARG ID DBC * dbc
END
-BEGIN dbc_count 1 RETCODE
+BEGIN dbc_count RETCODE
ARG ID DBC * dbc
ARG IGNORE db_recno_t * countp
ARG INT u_int32_t flags
RET INT db_recno_t dupcount
END
-BEGIN dbc_del 1 CODE
+BEGIN dbc_del CODE
ARG ID DBC * dbc
ARG INT u_int32_t flags
END
-BEGIN dbc_dup 1 RETCODE
+BEGIN dbc_dup RETCODE
ARG ID DBC * dbc
ARG IGNORE DBC ** dbcp
ARG INT u_int32_t flags
RET ID long dbcid
END
-BEGIN dbc_get 1 RETCODE
+BEGIN dbc_get RETCODE
ARG ID DBC * dbc
ARG DBT DBT * key
ARG DBT DBT * data
@@ -438,7 +584,17 @@ ARG INT u_int32_t flags
RET DBT DBT * key
RET DBT DBT * data
END
-BEGIN dbc_put 1 RETCODE
+BEGIN dbc_pget RETCODE
+ARG ID DBC * dbc
+ARG DBT DBT * skey
+ARG DBT DBT * pkey
+ARG DBT DBT * data
+ARG INT u_int32_t flags
+RET DBT DBT * skey
+RET DBT DBT * pkey
+RET DBT DBT * data
+END
+BEGIN dbc_put RETCODE
ARG ID DBC * dbc
ARG DBT DBT * key
ARG DBT DBT * data
@@ -452,13 +608,13 @@ END
#
# Locking subsystem
#
-BEGIN lock_detect 1 NOFUNC
+BEGIN lock_detect NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
ARG INT u_int32_t atype
ARG IGNORE int * aborted
END
-BEGIN lock_get 1 NOFUNC
+BEGIN lock_get NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t locker
ARG INT u_int32_t flags
@@ -466,21 +622,24 @@ ARG CONST const DBT * obj
ARG INT db_lockmode_t mode
ARG IGNORE DB_LOCK * lock
END
-BEGIN lock_id 1 NOFUNC
+BEGIN lock_id NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t * idp
END
-BEGIN lock_put 1 NOFUNC
+BEGIN lock_id_free NOFUNC
+ARG ID DB_ENV * dbenv
+ARG INT u_int32_t id
+END
+BEGIN lock_put NOFUNC
ARG ID DB_ENV * dbenv
ARG ID DB_LOCK * lock
END
-BEGIN lock_stat 1 NOFUNC
+BEGIN lock_stat NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE DB_LOCK_STAT ** statp
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
+ARG INT u_int32_t flags
END
-BEGIN lock_vec 1 NOFUNC
+BEGIN lock_vec NOFUNC
ARG ID DB_ENV * dbenv
ARG INT u_int32_t locker
ARG INT u_int32_t flags
@@ -491,89 +650,50 @@ END
#
# Logging subsystem
#
-BEGIN log_archive 1 NOFUNC
+BEGIN log_archive NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE char *** listp
ARG INT u_int32_t flags
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
+END
+BEGIN log_cursor NOFUNC
+ARG ID DB_ENV * dbenv
+ARG IGNORE DB_LOGC ** logcp
+ARG INT u_int32_t flags
END
#
# Don't do log_compare. It doesn't have an env we can get at,
# and it doesn't manipulate DB internal information.
#
-BEGIN log_file 1 NOFUNC
+BEGIN log_file NOFUNC
ARG ID DB_ENV * dbenv
ARG CONST const DB_LSN * lsn
ARG STRING char * namep
ARG INT size_t len
END
-BEGIN log_flush 1 NOFUNC
+BEGIN log_flush NOFUNC
ARG ID DB_ENV * dbenv
ARG CONST const DB_LSN * lsn
END
-BEGIN log_get 1 NOFUNC
-ARG ID DB_ENV * dbenv
-ARG IGNORE DB_LSN * lsn
-ARG DBT DBT * data
-ARG INT u_int32_t flags
-END
-BEGIN log_put 1 NOFUNC
+BEGIN log_put NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE DB_LSN * lsn
-ARG CONST const DBT * data
+ARG DBT const DBT * data
ARG INT u_int32_t flags
END
-BEGIN log_register 1 NOFUNC
-ARG ID DB_ENV * dbenv
-ARG ID DB * dbp
-ARG CONST const char * namep
-END
-BEGIN log_stat 1 NOFUNC
+BEGIN log_stat NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE DB_LOG_STAT ** statp
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
-END
-BEGIN log_unregister 1 NOFUNC
-ARG ID DB_ENV * dbenv
-ARG ID DB * dbp
+ARG INT u_int32_t flags
END
#
# Mpool Subsystem
#
-BEGIN memp_fclose 1 NOFUNC
-ARG ID DB_MPOOLFILE * mpf
-END
-BEGIN memp_fget 1 NOFUNC
-ARG ID DB_MPOOLFILE * mpf
-ARG IGNORE db_pgno_t * pgno
-ARG INT u_int32_t flags
-ARG IGNORE void ** pagep
-END
-BEGIN memp_fopen 1 NOFUNC
+BEGIN memp_fcreate NOFUNC
ARG ID DB_ENV * dbenv
-ARG CONST const char * file
-ARG INT u_int32_t flags
-ARG INT int mode
-ARG INT size_t pagesize
-ARG IGNORE DB_MPOOL_FINFO * finfop
ARG IGNORE DB_MPOOLFILE ** mpf
+ARG IGNORE u_int32_t flags
END
-BEGIN memp_fput 1 NOFUNC
-ARG ID DB_MPOOLFILE * mpf
-ARG IGNORE void * pgaddr
-ARG INT u_int32_t flags
-END
-BEGIN memp_fset 1 NOFUNC
-ARG ID DB_MPOOLFILE * mpf
-ARG IGNORE void * pgaddr
-ARG INT u_int32_t flags
-END
-BEGIN memp_fsync 1 NOFUNC
-ARG ID DB_MPOOLFILE * mpf
-END
-BEGIN memp_register 1 NOFUNC
+BEGIN memp_register NOFUNC
ARG ID DB_ENV * dbenv
ARG INT int ftype
FUNCPROT int (*)(DB_ENV *, db_pgno_t, void *, DBT *)
@@ -581,18 +701,17 @@ FUNCARG int (*func0) __P((DB_ENV *, db_pgno_t, void *, DBT *))
FUNCPROT int (*)(DB_ENV *, db_pgno_t, void *, DBT *)
FUNCARG int (*func1) __P((DB_ENV *, db_pgno_t, void *, DBT *))
END
-BEGIN memp_stat 1 NOFUNC
+BEGIN memp_stat NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE DB_MPOOL_STAT ** gstatp
ARG IGNORE DB_MPOOL_FSTAT *** fstatp
-FUNCPROT void *(*)(size_t)
-FUNCARG void *(*func0) __P((size_t))
+ARG INT u_int32_t flags
END
-BEGIN memp_sync 1 NOFUNC
+BEGIN memp_sync NOFUNC
ARG ID DB_ENV * dbenv
ARG IGNORE DB_LSN * lsn
END
-BEGIN memp_trickle 1 NOFUNC
+BEGIN memp_trickle NOFUNC
ARG ID DB_ENV * dbenv
ARG INT int pct
ARG IGNORE int * nwrotep
diff --git a/bdb/tcl/docs/db.html b/bdb/tcl/docs/db.html
index c75ab6ecf4f..4f04c2c4f96 100644
--- a/bdb/tcl/docs/db.html
+++ b/bdb/tcl/docs/db.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
@@ -8,184 +9,154 @@
<H2>
<A NAME="Database Commands"></A>Database Commands</H2>
-The database commands provide a conduit into the DB method functions.&nbsp;
-They are all fairly straightforward and I describe them in terms of their
-DB functions briefly here, with a link to the DB page where appropriate.&nbsp;
-The first set of commands are those I believe will be the primary functions
-used by most databases.&nbsp; Some are directly related to their DB counterparts,
-and some are higher level functions that are useful to provide the user.
-<P><B>> berkdb open [-env <I>env</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-btree|-hash|-recno|-queue|-unknown]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-create] [-excl] [-nommap] [-rdonly] [-truncate]
-[-mode
-<I>mode</I>] [-errfile <I>filename</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-dup] [-dupsort] [-recnum] [-renumber] [-revsplitoff]
-[-snapshot]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-extent <I>size</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-ffactor <I>density</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-nelem <I>size</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lorder <I>order</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-delim <I>delim</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-len <I>len</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-pad <I>pad</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-source <I>file</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-minkey <I>minkey</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-cachesize {<I>gbytes bytes ncaches</I>}]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-pagesize <I>pagesize</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [--]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [<I>filename </I>[<I>subdbname</I>]]</B>
-<P>This command will invoke the <A HREF="../../docs/api_c/db_create.html">db_create</A>
-function.&nbsp; If the command is given the <B>-env</B> option, then we
-will accordingly creating the database within the context of that environment.&nbsp;
-After it successfully gets a handle to a database, we bind it to a new
-Tcl command of the form <B><I>dbX, </I></B>where X is an integer starting
-at 0 (e.g. <B>db0, db1, </B>etc).&nbsp; We use the <I>Tcl_CreateObjCommand()&nbsp;</I>
-to create the top level database function.&nbsp; It is through this handle
-that the user can access all of the commands described in the <A HREF="#Database Commands">Database
-Commands</A> section.&nbsp; Internally, the database handle is sent as
-the <I>ClientData</I> portion of the new command set so that all future
-database calls access the appropriate handle.
-<P>After parsing all of the optional arguments affecting the setup of the
-database and making the appropriate calls to DB to manipulate those values,
-we open the database for the user. It&nbsp; translates to the
-<A HREF="../../docs/api_c/db_open.html">DB->open</A>
-method call after parsing all of the various optional arguments.&nbsp;
-We automatically set the DB_THREAD flag.&nbsp; The arguments are:
-<UL>
-<LI>
-<B>-- </B>- Terminate the list of options and use remaining arguments as
-the file or subdb names (thus allowing the use of filenames beginning with
-a dash '-')</LI>
-
-<LI>
-<B>-btree</B> - DB_BTREE database</LI>
-
-<LI>
-<B>-hash</B> -&nbsp; DB_HASH database</LI>
-
-<LI>
-<B>-recno&nbsp;</B> - DB_RECNO database</LI>
-
-<LI>
-<B>-queue</B> - DB_QUEUE database</LI>
-
-<LI>
-<B>-create</B> selects the DB_CREATE flag&nbsp; to create underlying files</LI>
-
-<LI>
-<B>-excl</B> selects the DB_EXCL flag&nbsp; to exclusively create underlying
-files</LI>
-
-<LI>
-<B>-nommap</B> selects the DB_NOMMAP flag to forbid mmaping of files</LI>
-
-<LI>
-<B>-rdonly</B> selects the DB_RDONLY flag for opening in read-only mode</LI>
-
-<LI>
-<B>-truncate</B> selects the DB_TRUNCATE flag to truncate the database</LI>
-
-<LI>
-<B>-mode<I> mode</I></B> specifies the mode for created files</LI>
-
-<LI>
-<B>-errfile </B>specifies the error file to use for this environment to
-<B><I>filename</I></B>
-by calling <A HREF="../../docs/api_c/db_set_errfile.html">DB->set_errfile</A><B><I>.
-</I></B>If
-the file already exists then we will append to the end of the file</LI>
-
-<LI>
-<B>-dup </B>selects the DB_DUP flag to permit duplicates in the database</LI>
-
-<LI>
-<B>-dupsort</B> selects the DB_DUPSORT flag to support sorted duplicates</LI>
-
-<LI>
-<B>-recnum</B> selects the DB_RECNUM flag to support record numbers in
-btrees</LI>
-
-<LI>
-<B>-renumber </B>selects the DB_RENUMBER flag to support mutable record
-numbers</LI>
+The database commands provide a fairly straightforward mapping to the
+DB method functions.
-<LI>
-<B>-revsplitoff </B>selects the DB_REVSPLITOFF flag to suppress reverse
-splitting of pages on deletion</LI>
-
-<LI>
-<B>-snapshot </B>selects the DB_SNAPSHOT flag to support database snapshots</LI>
-
-<LI>
-<B>-extent </B>sets the size of a Queue database extent to the given <B><I>size
-</I></B>using
-the <A HREF="../../docs/api_c/db_set_q_extentsize.html">DB->set_q_extentsize</A>
-method</LI>
-
-<LI>
-<B>-ffactor</B> sets the hash table key density to the given <B><I>density
-</I></B>using
-the <A HREF="../../docs/api_c/db_set_h_ffactor.html">DB->set_h_ffactor</A>
-method</LI>
-
-<LI>
-<B>-nelem </B>sets the hash table size estimate to the given <B><I>size
-</I></B>using
-the <A HREF="../../docs/api_c/db_set_h_nelem.html">DB->set_h_nelem</A>
-method</LI>
-
-<LI>
-<B>-lorder </B>sets the byte order for integers stored in the database
-meta-data to the given <B><I>order</I></B> using the <A HREF="../../docs/api_c/db_set_lorder.html">DB->set_lorder</A>
-method</LI>
-
-<LI>
-<B>-delim </B>sets the delimiting byte for variable length records to
-<B><I>delim</I></B>
-using the <A HREF="../../docs/api_c/db_set_re_delim.html">DB->set_re_delim</A>
-method</LI>
-
-<LI>
-<B>-len </B>sets the length of fixed-length records to <B><I>len</I></B>
-using the <A HREF="../../docs/api_c/db_set_re_len.html">DB->set_re_len</A>
-method</LI>
-
-<LI>
-<B>-pad </B>sets the pad character used for fixed length records to
-<B><I>pad</I></B>&nbsp;
-using the <A HREF="../../docs/db_set_re_pad.html">DB->set_re_pad</A> method</LI>
-
-<LI>
-<B>-source </B>sets the backing source file name to <B><I>file</I></B>
-using the <A HREF="../../docs/api_c/db_set_re_source.html">DB->set_re_source</A>
-method</LI>
-
-<LI>
-<B>-minkey </B>sets the minimum number of keys per Btree page to <B><I>minkey</I></B>
-using the <A HREF="../../docs/api_c/db_set_bt_minkey.html">DB->set_bt_minkey</A>
-method</LI>
-
-<LI>
-<B>-cachesize </B>sets the size of the database cache to the size&nbsp;
-specified by <B><I>gbytes </I></B>and <B><I>bytes, </I></B>broken up into
-<B><I>ncaches</I></B>
-number of caches using the <A HREF="../../docs/api_c/db_set_cachesize.html">DB->set_cachesize</A>
-method</LI>
-
-<LI>
-<B>-pagesize </B>sets the size of the database page to <B><I>pagesize </I></B>using
-the <A HREF="../../docs/api_c/db_set_pagesize.html">DB->set_pagesize</A>
-method</LI>
-
-<LI>
-<B><I>filename</I></B> indicates the name of the database</LI>
-
-<LI>
-<B><I>subdbname</I></B> indicate the name of the sub-database</LI>
-</UL>
+<P>
+<B>> berkdb open</B>
+<dl>
+
+<dt><B>[-btcompare <I>proc</I>]</B><dd>
+Sets the Btree comparison function to the Tcl procedure named
+<I>proc</I> using the
+<A HREF="../../docs/api_c/db_set_bt_compare.html">DB->set_bt_compare</A>
+method.
+
+<dt><B>[-btree|-hash|-recno|-queue|-unknown]</B><dd>
+</td><td>
+Select the database type:<br>
+DB_BTREE, DB_HASH, DB_RECNO, DB_QUEUE or DB_UNKNOWN.
+
+
+<dt><B>[-cachesize {<I>gbytes bytes ncaches</I>}]</B><dd>
+Sets the size of the database cache to the size specified by
+<I>gbytes</I> and <I>bytes</I>, broken up into <I>ncaches</I> number of
+caches using the
+<A HREF="../../docs/api_c/db_set_cachesize.html">DB->set_cachesize</A>
+method.
+
+<dt><B>[-create]</B><dd>
+Selects the DB_CREATE flag to create underlying files.
+
+<dt><B>[-delim <I>delim</I>]</B><dd>
+Sets the delimiting byte for variable length records to <I>delim</I>
+using the
+<A HREF="../../docs/api_c/db_set_re_delim.html">DB->set_re_delim</A>
+method.
+
+<dt><B>[-dup]</B><dd>
+Selects the DB_DUP flag to permit duplicates in the database.
+
+<dt><B>[-dupcompare <I>proc</I>]</B><dd>
+Sets the duplicate data comparison function to the Tcl procedure named
+<I>proc</I> using the
+<A HREF="../../docs/api_c/db_set_dup_compare.html">DB->set_dup_compare</A>
+method.
+
+<dt><B>[-dupsort]</B><dd>
+Selects the DB_DUPSORT flag to support sorted duplicates.
+
+<dt><B>[-env <I>env</I>]</B><dd>
+The database environment.
+
+<dt><B>[-errfile <I>filename</I>]</B><dd>
+Specifies the error file to use for this environment to <I>filename</I>
+by calling
+<A HREF="../../docs/api_c/db_set_errfile.html">DB->set_errfile</A>.
+If the file already exists then we will append to the end of the file.
+
+<dt><B>[-excl]</B><dd>
+Selects the DB_EXCL flag to exclusively create underlying files.
+
+<dt><B>[-extent <I>size</I>]</B><dd>
+Sets the size of a Queue database extent to the given <I>size</I> using
+the
+<A HREF="../../docs/api_c/db_set_q_extentsize.html">DB->set_q_extentsize</A>
+method.
+
+<dt><B>[-ffactor <I>density</I>]</B><dd>
+Sets the hash table key density to the given <I>density</I> using the
+<A HREF="../../docs/api_c/db_set_h_ffactor.html">DB->set_h_ffactor</A>
+method.
+
+<dt><B>[-hashproc <I>proc</I>]</B><dd>
+Sets a user-defined hash function to the Tcl procedure named <I>proc</I>
+using the
+<A HREF="../../docs/api_c/db_set_h_hash.html">DB->set_h_hash</A> method.
+
+<dt><B>[-len <I>len</I>]</B><dd>
+Sets the length of fixed-length records to <I>len</I> using the
+<A HREF="../../docs/api_c/db_set_re_len.html">DB->set_re_len</A>
+method.
+
+<dt><B>[-lorder <I>order</I>]</B><dd>
+Sets the byte order for integers stored in the database meta-data to
+the given <I>order</I> using the
+<A HREF="../../docs/api_c/db_set_lorder.html">DB->set_lorder</A>
+method.
+
+<dt><B>[-minkey <I>minkey</I>]</B><dd>
+Sets the minimum number of keys per Btree page to <I>minkey</I> using
+the
+<A HREF="../../docs/api_c/db_set_bt_minkey.html">DB->set_bt_minkey</A>
+method.
+
+<dt><B>[-mode <I>mode</I>]</B><dd>
+Specifies the mode for created files.
+
+<dt><B>[-nelem <I>size</I>]</B><dd>
+Sets the hash table size estimate to the given <I>size</I> using the
+<A HREF="../../docs/api_c/db_set_h_nelem.html">DB->set_h_nelem</A>
+method.
+
+<dt><B>[-nommap]</B><dd>
+Selects the DB_NOMMAP flag to forbid mmaping of files.
+
+<dt><B>[-pad <I>pad</I>]</B><dd>
+Sets the pad character used for fixed length records to <I>pad</I> using
+the
+<A HREF="../../docs/db_set_re_pad.html">DB->set_re_pad</A> method.
+
+<dt><B>[-pagesize <I>pagesize</I>]</B><dd>
+Sets the size of the database page to <I>pagesize</I> using the
+<A HREF="../../docs/api_c/db_set_pagesize.html">DB->set_pagesize</A>
+method.
+
+<dt><B>[-rdonly]</B><dd>
+Selects the DB_RDONLY flag for opening in read-only mode.
+
+<dt><B>[-recnum]</B><dd>
+Selects the DB_RECNUM flag to support record numbers in Btrees.
+
+<dt><B>[-renumber]</B><dd>
+Selects the DB_RENUMBER flag to support mutable record numbers.
+
+<dt><B>[-revsplitoff]</B><dd>
+Selects the DB_REVSPLITOFF flag to suppress reverse splitting of pages
+on deletion.
+
+<dt><B>[-snapshot]</B><dd>
+Selects the DB_SNAPSHOT flag to support database snapshots.
+
+<dt><B>[-source <I>file</I>]</B><dd>
+Sets the backing source file name to <I>file</I> using the
+<A HREF="../../docs/api_c/db_set_re_source.html">DB->set_re_source</A>
+method.
+
+<dt><B>[-truncate]</B><dd>
+Selects the DB_TRUNCATE flag to truncate the database.
+
+<dt><B>[--]</B><dd>
+Terminate the list of options and use remaining arguments as the file
+or subdb names (thus allowing the use of filenames beginning with a dash
+'-').
+
+<dt><B>[<I>filename </I>[<I>subdbname</I>]]</B><dd>
+The names of the database and sub-database.
+</dl>
<HR WIDTH="100%">
-<BR><B>&nbsp;berkdb upgrade [-dupsort] [-env <I>env</I>] [--] [<I>filename</I>]</B>
+<B>> berkdb upgrade [-dupsort] [-env <I>env</I>] [--] [<I>filename</I>]</B>
<P>This command will invoke the <A HREF="../../docs/api_c/db_upgrade.html">DB->upgrade</A>
function.&nbsp; If the command is given the <B>-env</B> option, then we
will accordingly upgrade the database filename within the context of that
@@ -193,14 +164,21 @@ environment. The <B>-dupsort</B> option selects the DB_DUPSORT flag for
upgrading. The use of --<B> </B>terminates the list of options, thus allowing
filenames beginning with a dash.
<P>
-<HR WIDTH="100%"><B>> berkdb verify [-env <I>env</I>] [--] [<I>filename</I>]</B>
+
+<HR WIDTH="100%">
+<B>> berkdb verify [-env <I>env</I>] [--] [<I>filename</I>]</B>
<P>This command will invoke the <A HREF="../../docs/api_c/db_verify.html">DB->verify</A>
function.&nbsp; If the command is given the <B>-env</B> option, then we
will accordingly verify the database filename within the context of that
environment.&nbsp; The use of --<B> </B>terminates the list of options,
thus allowing filenames beginning with a dash.
<P>
-<HR WIDTH="100%"><B>> <I>db</I> join [-nosort] <I>db0.c0 db1.c0</I> ...</B>
+
+<HR WIDTH="100%"><B>> <I>db</I> del</B>
+<P>There are no undocumented options.
+
+<HR WIDTH="100%">
+<B>> <I>db</I> join [-nosort] <I>db0.c0 db1.c0</I> ...</B>
<P>This command will invoke the <A HREF="../../docs/api_c/db_join.html">db_join</A>
function.&nbsp; After it successfully joins a database, we bind it to a
new Tcl command of the form <B><I>dbN.cX, </I></B>where X is an integer
@@ -215,7 +193,33 @@ number of data items they reference.&nbsp; It results in the DB_JOIN_NOSORT
flag being set.</LI>
</UL>
-<HR WIDTH="100%"><B>> <I>db</I> get_join [-nosort] {db key} {db key} ...</B>
+<P>
+This command will invoke the
+<A HREF="../../docs/api_c/db_create.html">db_create</A> function. If
+the command is given the <B>-env</B> option, then we will accordingly
+creating the database within the context of that environment. After it
+successfully gets a handle to a database, we bind it to a new Tcl
+command of the form <B><I>dbX, </I></B>where X is an integer starting
+at 0 (e.g. <B>db0, db1, </B>etc).
+
+<p>
+We use the <I>Tcl_CreateObjCommand()</I> to create the top level
+database function. It is through this handle that the user can access
+all of the commands described in the <A HREF="#Database Commands">
+Database Commands</A> section. Internally, the database handle
+is sent as the <I>ClientData</I> portion of the new command set so that
+all future database calls access the appropriate handle.
+
+<P>
+After parsing all of the optional arguments affecting the setup of the
+database and making the appropriate calls to DB to manipulate those
+values, we open the database for the user. It translates to the
+<A HREF="../../docs/api_c/db_open.html">DB->open</A> method call after
+parsing all of the various optional arguments. We automatically set the
+DB_THREAD flag. The arguments are:
+
+<HR WIDTH="100%">
+<B>> <I>db</I> get_join [-nosort] {db key} {db key} ...</B>
<P>This command performs a join operation on the keys specified and returns
a list of the joined {key data} pairs.
<P>The options are:
@@ -226,41 +230,34 @@ number of data items they reference.&nbsp; It results in the DB_JOIN_NOSORT
flag being set.</LI>
</UL>
-<HR WIDTH="100%"><B>> <I>db</I> keyrange [-txn <I>id</I>] key</B>
+<HR WIDTH="100%">
+<B>> <I>db</I> keyrange [-txn <I>id</I>] key</B>
<P>This command returns the range for the given <B>key</B>.&nbsp; It returns
a list of 3 double elements of the form {<B><I>less equal greater</I></B>}
where <B><I>less</I></B> is the percentage of keys less than the given
key, <B><I>equal</I></B> is the percentage equal to the given key and <B><I>greater</I></B>
is the percentage greater than the given key.&nbsp; If the -txn option
is specified it performs this operation under transaction protection.
-<BR>
-<HR WIDTH="100%"><B>> <I>db</I> put</B>
-<P>The <B>undocumented</B> options are:
-<UL>
-<LI>
-<B>-nodupdata</B> This flag causes DB not to insert the key/data pair if
-it already exists, that is, both the key and data items are already in
-the database. The -nodupdata flag may only be specified if the underlying
-database has been configured to support sorted duplicates.</LI>
-</UL>
-<HR WIDTH="100%"><B>> <I>db</I> stat</B>
+<HR WIDTH="100%"><B>> <I>db</I> put</B>
<P>The <B>undocumented</B> options are:
-<UL>
-<LI>
-<B>-cachedcounts</B> This flag causes DB to return the cached key/record
-counts, similar to the DB_CACHED_COUNTS flags to DB->stat.</LI>
-</UL>
+<dl>
+<dt><B>-nodupdata</B><dd>
+This flag causes DB not to insert the key/data pair if it already
+exists, that is, both the key and data items are already in the
+database. The -nodupdata flag may only be specified if the underlying
+database has been configured to support sorted duplicates.
+</dl>
<HR WIDTH="100%"><B>> <I>dbc</I> put</B>
<P>The <B>undocumented</B> options are:
-<UL>
-<LI>
-<B>-nodupdata</B> This flag causes DB not to insert the key/data pair if
-it already exists, that is, both the key and data items are already in
-the database. The -nodupdata flag may only be specified if the underlying
-database has been configured to support sorted duplicates.</LI>
-</UL>
+<dl>
+<dt><B>-nodupdata</B><dd>
+This flag causes DB not to insert the key/data pair if it already
+exists, that is, both the key and data items are already in the
+database. The -nodupdata flag may only be specified if the underlying
+database has been configured to support sorted duplicates.
+</dl>
</BODY>
</HTML>
diff --git a/bdb/tcl/docs/env.html b/bdb/tcl/docs/env.html
index a1bd08fd163..79c349841ac 100644
--- a/bdb/tcl/docs/env.html
+++ b/bdb/tcl/docs/env.html
@@ -1,303 +1,354 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="GENERATOR" CONTENT="Mozilla/4.08 [en] (X11; I; FreeBSD 3.3-RELEASE i386) [Netscape]">
-</HEAD>
-<BODY>
-
-<H2>
-Environment Commands</H2>
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.75 [en] (X11; U; Linux 2.2.16-22 i686) [Netscape]">
+</head>
+<body>
+
+<h2>
+Environment Commands</h2>
Environments provide a structure for creating a consistent environment
for processes using one or more of the features of Berkeley DB.&nbsp; Unlike
some of the database commands, the environment commands are very low level.
-<BR>
-<HR WIDTH="100%">
-<P>The user may create and open a new DB environment&nbsp; by invoking:
-<P><B>> berkdb env</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-cdb] [-cdb_alldb] [-lock] [-log] [-txn [nosync]]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-create] [-home<I> directory</I>] [-mode <I>mode</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-data_dir <I>directory</I>] [-log_dir <I>directory</I>]
-[-tmp_dir <I>directory</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-nommap] [-private] [-recover] [-recover_fatal]
-[-system_mem] [-errfile <I>filename</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-use_environ] [-use_environ_root] [-verbose
-{<I>which </I>on|off}]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-region_init]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-cachesize {<I>gbytes bytes ncaches</I>}]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-mmapsize<I> size</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-log_max <I>max</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-log_buffer <I>size</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lock_conflict {<I>nmodes </I>{<I>matrix</I>}}]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lock_detect default|oldest|random|youngest]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lock_max <I>max</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lock_max_locks <I>max</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lock_max_lockers <I>max</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-lock_max_objects <I>max</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-txn_max <I>max</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-client_timeout <I>seconds</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-server_timeout <I>seconds</I>]</B>
-<BR><B>&nbsp;&nbsp;&nbsp; [-server <I>hostname</I>]</B>
-<BR>&nbsp;
-<P>This command opens up an environment.&nbsp;&nbsp; We automatically set
+<br>
+<hr WIDTH="100%">
+<p>The user may create and open a new DB environment&nbsp; by invoking:
+<p><b>> berkdb env</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-cdb] [-cdb_alldb] [-lock] [-log] [-txn [nosync]]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-create] [-home<i> directory</i>] [-mode <i>mode</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-data_dir <i>directory</i>] [-log_dir <i>directory</i>]
+[-tmp_dir <i>directory</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-nommap] [-private] [-recover] [-recover_fatal]
+[-system_mem] [-errfile <i>filename</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-use_environ] [-use_environ_root] [-verbose
+{<i>which </i>on|off}]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-region_init]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-cachesize {<i>gbytes bytes ncaches</i>}]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-mmapsize<i> size</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-log_max <i>max</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-log_buffer <i>size</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_conflict {<i>nmodes </i>{<i>matrix</i>}}]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_detect default|oldest|random|youngest]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_max <i>max</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_max_locks <i>max</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_max_lockers <i>max</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_max_objects <i>max</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-lock_timeout <i>timeout</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-overwrite]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-txn_max <i>max</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-txn_timeout <i>timeout</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-client_timeout <i>seconds</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-server_timeout <i>seconds</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-server <i>hostname</i>]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-rep_master] [-rep_client]</b>
+<br><b>&nbsp;&nbsp;&nbsp; [-rep_transport <i>{ machineid sendproc }</i>]</b>
+<br>&nbsp;
+<p>This command opens up an environment.&nbsp;&nbsp; We automatically set
the DB_THREAD and the DB_INIT_MPOOL flags.&nbsp; The arguments are:
-<UL>
-<LI>
-<B>-cdb</B> selects the DB_INIT_CDB flag for Concurrent Data Store</LI>
-
-<LI>
-<B>-cdb_alldb</B> selects the DB_CDB_ALLDB flag for Concurrent Data Store</LI>
-
-<LI>
-<B>-lock</B> selects the DB_INIT_LOCK flag for the locking subsystem</LI>
-
-<LI>
-<B>-log</B> selects the DB_INIT_LOG flag for the logging subsystem</LI>
-
-<LI>
-<B>-txn</B> selects the DB_INIT_TXN, DB_INIT_LOCK and DB_INIT_LOG flags
-for the transaction subsystem.&nbsp; If <B>nosync</B> is specified, then
-it will also select DB_TXN_NOSYNC to indicate no flushes of log on commits</LI>
-
-<LI>
-<B>-create </B>selects the DB_CREATE flag to create underlying files</LI>
-
-<LI>
-<B>-home <I>directory </I></B>selects the home directory of the environment</LI>
-
-<LI>
-<B>-data_dir <I>directory </I></B>selects the data file directory of the
-environment by calling <A HREF="../../docs/api_c/env_set_data_dir.html">DBENV->set_data_dir</A>.</LI>
-
-<LI>
-<B>-log_dir <I>directory </I></B>selects the log file directory of the
-environment&nbsp; by calling <A HREF="../../docs/api_c/env_set_lg_dir.html">DBENV->set_lg_dir</A>.</LI>
-
-<LI>
-<B>-tmp_dir <I>directory </I></B>selects the temporary file directory of
-the environment&nbsp; by calling <A HREF="../../docs/api_c/env_set_tmp_dir.so">DBENV->set_tmp_dir</A>.</LI>
-
-<LI>
-<B>-mode <I>mode </I></B>sets the permissions of created files to <B><I>mode</I></B></LI>
-
-<LI>
-<B>-nommap</B> selects the DB_NOMMAP flag to disallow using mmap'ed files</LI>
-
-<LI>
-<B>-private</B> selects the DB_PRIVATE flag for a private environment</LI>
-
-<LI>
-<B>-recover</B> selects the DB_RECOVER flag for recovery</LI>
-
-<LI>
-<B>-recover_fatal</B> selects the DB_RECOVER_FATAL flag for catastrophic
-recovery</LI>
-
-<LI>
-<B>-system_mem</B> selects the DB_SYSTEM_MEM flag to use system memory</LI>
-
-<LI>
-<B>-errfile </B>specifies the error file to use for this environment to
-<B><I>filename</I></B>
-by calling <A HREF="../../docs/api_c/env_set_errfile.html">DBENV->set_errfile</A><B><I>.
-</I></B>If
-the file already exists then we will append to the end of the file</LI>
-
-<LI>
-<B>-use_environ</B> selects the DB_USE_ENVIRON flag to affect file naming</LI>
-
-<LI>
-<B>-use_environ_root</B> selects the DB_USE_ENVIRON_ROOT flag to have the
-root environment affect file naming</LI>
-
-<LI>
-<B>-verbose</B> produces verbose error output for the given which subsystem,
-using the <A HREF="../../docs/api_c/dbenv_set_verbose.html">DBENV->set_verbose</A>
-method.&nbsp;&nbsp; See the description of <A HREF="#> <env> verbose which on|off">verbose</A>
-below for valid <B><I>which </I></B>values</LI>
-
-<LI>
-<B>-region_init </B>specifies that the user wants to page fault the region
-in on startup using the <A HREF="../../docs/api_c/env_set_region_init.html">DBENV->set_region_init</A>
-method call</LI>
-
-<LI>
-<B>-cachesize </B>sets the size of the database cache to the size&nbsp;
-specified by <B><I>gbytes </I></B>and <B><I>bytes, </I></B>broken up into
-<B><I>ncaches</I></B>
-number of caches using the <A HREF="../../docs/api_c/env_set_cachesize.html">DBENV->set_cachesize</A>
-method</LI>
-
-<LI>
-<B>-mmapsize </B>sets the size of the database page to <B><I>size </I></B>using
-the <A HREF="../../docs/api_c/env_set_mp_mmapsize.html">DBENV->set_mp_mmapsize</A>
-method</LI>
-
-<LI>
-<B>-log_max </B>sets the maximum size of the log file to <B><I>max</I></B>
-using the <A HREF="../../docs/api_c/env_set_lg_max.html">DBENV->set_lg_max</A>
-call</LI>
-
-<LI>
-<B>-log_buffer </B>sets the size of the log file in bytes to <B><I>size</I></B>
-using the <A HREF="../../docs/api_c/env_set_lg_bsize.html">DBENV->set_lg_bsize</A>
-call</LI>
-
-<LI>
-<B>-lock_conflict </B>sets the number of lock modes to <B><I>nmodes</I></B>
-and sets the locking policy for those modes to the <B><I>conflict_matrix</I></B>
-given using the <A HREF="../../docs/api_c/env_set_lk_conflict.html">DBENV->set_lk_conflict</A>
-method call</LI>
-
-<LI>
-<B>-lock_detect </B>sets the deadlock detection policy to the given policy
-using the <A HREF="../../docs/env_set_lk_detect.html">DBENV->set_lk_detect</A>
-method call.&nbsp; The policy choices are:</LI>
-
-<UL>
-<LI>
-<B>default</B> selects the DB_LOCK_DEFAULT policy for default detection</LI>
-
-<LI>
-<B>oldest </B>selects DB_LOCK_OLDEST to abort the oldest locker on a deadlock</LI>
-
-<LI>
-<B>random</B> selects DB_LOCK_RANDOM to abort a random locker on a deadlock</LI>
-
-<LI>
-<B>youngest</B> selects DB_LOCK_YOUNGEST to abort the youngest locker on
-a deadlock</LI>
-</UL>
-
-<LI>
-<B>-lock_max </B>sets the maximum size of the lock table to <B><I>max </I></B>using
-the <A HREF="../../docs/api_c/env_set_lk_max.html">DBENV->set_lk_max</A>
-method call</LI>
-
-<LI>
-<B>-lock_max_locks </B>sets the maximum number of locks to <B><I>max </I></B>using
-the <A HREF="../../docs/api_c/env_set_lk_max_locks.html">DBENV->set_lk_max_locks</A>
-method call</LI>
-
-<LI>
-<B>-lock_max_lockers </B>sets the maximum number of locking entities to
-<B><I>max </I></B>using the <A HREF="../../docs/api_c/env_set_lk_max_lockers.html">DBENV->set_lk_max_lockers</A>
-method call</LI>
-
-<LI>
-<B>-lock_max_objects </B>sets the maximum number of simultaneously locked
-objects to <B><I>max </I></B>using the <A HREF="../../docs/api_c/env_set_lk_max_objects.html">DBENV->set_lk_max_objects</A>
-method call</LI>
-
-<LI>
-<B>-txn_max </B>sets the maximum size of the transaction table to <B><I>max</I></B>
-using the <A HREF="../../docs/api_c/env_set_txn_max.html">DBENV->set_txn_max</A>
-method call</LI>
-
-<LI>
-<B>-client_timeout</B> sets the timeout value for the client waiting for
-a reply from the server for RPC operations to <B><I>seconds</I></B>.</LI>
-
-<LI>
-<B>-server_timeout</B> sets the timeout value for the server to determine
-an idle client is gone to <B><I>seconds</I></B>.</LI>
-
-<LI>
-<B>&nbsp;-server </B>specifies the <B><I>hostname</I></B> of the server
-to connect to in the <A HREF="../../docs/api_c/env_set_server.html">DBENV->set_server</A>
-call.</LI>
-</UL>
-This command will invoke the <A HREF="../../docs/api_c/env_create.html">db_env_create</A>
+<ul>
+<li>
+<b>-cdb</b> selects the DB_INIT_CDB flag for Concurrent Data Store</li>
+
+<li>
+<b>-cdb_alldb</b> selects the DB_CDB_ALLDB flag for Concurrent Data Store</li>
+
+<li>
+<b>-lock</b> selects the DB_INIT_LOCK flag for the locking subsystem</li>
+
+<li>
+<b>-log</b> selects the DB_INIT_LOG flag for the logging subsystem</li>
+
+<li>
+<b>-txn</b> selects the DB_INIT_TXN, DB_INIT_LOCK and DB_INIT_LOG flags
+for the transaction subsystem.&nbsp; If <b>nosync</b> is specified, then
+it will also select DB_TXN_NOSYNC to indicate no flushes of log on commits</li>
+
+<li>
+<b>-create </b>selects the DB_CREATE flag to create underlying files</li>
+
+<li>
+<b>-home <i>directory </i></b>selects the home directory of the environment</li>
+
+<li>
+<b>-data_dir <i>directory </i></b>selects the data file directory of the
+environment by calling <a href="../../docs/api_c/env_set_data_dir.html">DBENV->set_data_dir</a>.</li>
+
+<li>
+<b>-log_dir <i>directory </i></b>selects the log file directory of the
+environment&nbsp; by calling <a href="../../docs/api_c/env_set_lg_dir.html">DBENV->set_lg_dir</a>.</li>
+
+<li>
+<b>-tmp_dir <i>directory </i></b>selects the temporary file directory of
+the environment&nbsp; by calling <a href="../../docs/api_c/env_set_tmp_dir.so">DBENV->set_tmp_dir</a>.</li>
+
+<li>
+<b>-mode <i>mode </i></b>sets the permissions of created files to <b><i>mode</i></b></li>
+
+<li>
+<b>-nommap</b> selects the DB_NOMMAP flag to disallow using mmap'ed files</li>
+
+<li>
+<b>-private</b> selects the DB_PRIVATE flag for a private environment</li>
+
+<li>
+<b>-recover</b> selects the DB_RECOVER flag for recovery</li>
+
+<li>
+<b>-recover_fatal</b> selects the DB_RECOVER_FATAL flag for catastrophic
+recovery</li>
+
+<li>
+<b>-system_mem</b> selects the DB_SYSTEM_MEM flag to use system memory</li>
+
+<li>
+<b>-errfile </b>specifies the error file to use for this environment to
+<b><i>filename</i></b>
+by calling <a href="../../docs/api_c/env_set_errfile.html">DBENV->set_errfile</a><b><i>.
+</i></b>If
+the file already exists then we will append to the end of the file</li>
+
+<li>
+<b>-use_environ</b> selects the DB_USE_ENVIRON flag to affect file naming</li>
+
+<li>
+<b>-use_environ_root</b> selects the DB_USE_ENVIRON_ROOT flag to have the
+root environment affect file naming</li>
+
+<li>
+<b>-verbose</b> produces verbose error output for the given which subsystem,
+using the <a href="../../docs/api_c/dbenv_set_verbose.html">DBENV->set_verbose</a>
+method.&nbsp;&nbsp; See the description of <a href="#> <env> verbose which on|off">verbose</a>
+below for valid <b><i>which </i></b>values</li>
+
+<li>
+<b>-region_init </b>specifies that the user wants to page fault the region
+in on startup using the <a href="../../docs/api_c/env_set_region_init.html">DBENV->set_region_init</a>
+method call</li>
+
+<li>
+<b>-cachesize </b>sets the size of the database cache to the size&nbsp;
+specified by <b><i>gbytes </i></b>and <b><i>bytes, </i></b>broken up into
+<b><i>ncaches</i></b>
+number of caches using the <a href="../../docs/api_c/env_set_cachesize.html">DBENV->set_cachesize</a>
+method</li>
+
+<li>
+<b>-mmapsize </b>sets the size of the database page to <b><i>size </i></b>using
+the <a href="../../docs/api_c/env_set_mp_mmapsize.html">DBENV->set_mp_mmapsize</a>
+method</li>
+
+<li>
+<b>-log_max </b>sets the maximum size of the log file to <b><i>max</i></b>
+using the <a href="../../docs/api_c/env_set_lg_max.html">DBENV->set_lg_max</a>
+call</li>
+
+<li>
+<b>-log_regionmax </b>sets the size of the log region to <b><i>max</i></b>
+using the <a href="../../docs/api_c/env_set_lg_regionmax.html">DBENV->set_lg_regionmax</a>
+call</li>
+
+<li>
+<b>-log_buffer </b>sets the size of the log file in bytes to <b><i>size</i></b>
+using the <a href="../../docs/api_c/env_set_lg_bsize.html">DBENV->set_lg_bsize</a>
+call</li>
+
+<li>
+<b>-lock_conflict </b>sets the number of lock modes to <b><i>nmodes</i></b>
+and sets the locking policy for those modes to the <b><i>conflict_matrix</i></b>
+given using the <a href="../../docs/api_c/env_set_lk_conflict.html">DBENV->set_lk_conflict</a>
+method call</li>
+
+<li>
+<b>-lock_detect </b>sets the deadlock detection policy to the given policy
+using the <a href="../../docs/env_set_lk_detect.html">DBENV->set_lk_detect</a>
+method call.&nbsp; The policy choices are:</li>
+
+<ul>
+<li>
+<b>default</b> selects the DB_LOCK_DEFAULT policy for default detection</li>
+
+<li>
+<b>oldest </b>selects DB_LOCK_OLDEST to abort the oldest locker on a deadlock</li>
+
+<li>
+<b>random</b> selects DB_LOCK_RANDOM to abort a random locker on a deadlock</li>
+
+<li>
+<b>youngest</b> selects DB_LOCK_YOUNGEST to abort the youngest locker on
+a deadlock</li>
+</ul>
+
+<li>
+<b>-lock_max </b>sets the maximum size of the lock table to <b><i>max </i></b>using
+the <a href="../../docs/api_c/env_set_lk_max.html">DBENV->set_lk_max</a>
+method call</li>
+
+<li>
+<b>-lock_max_locks </b>sets the maximum number of locks to <b><i>max </i></b>using
+the <a href="../../docs/api_c/env_set_lk_max_locks.html">DBENV->set_lk_max_locks</a>
+method call</li>
+
+<li>
+<b>-lock_max_lockers </b>sets the maximum number of locking entities to
+<b><i>max
+</i></b>using the <a href="../../docs/api_c/env_set_lk_max_lockers.html">DBENV->set_lk_max_lockers</a>
+method call</li>
+
+<li>
+<b>-lock_max_objects </b>sets the maximum number of simultaneously locked
+objects to <b><i>max </i></b>using the <a href="../../docs/api_c/env_set_lk_max_objects.html">DBENV->set_lk_max_objects</a>
+method call</li>
+
+<li>
+<b>-lock_timeout </b>sets the timeout for locks in the environment</li>
+
+<li>
+<b>-overwrite </b>sets DB_OVERWRITE flag</li>
+
+<li>
+<b>-txn_max </b>sets the maximum size of the transaction table to <b><i>max</i></b>
+using the <a href="../../docs/api_c/env_set_txn_max.html">DBENV->set_txn_max</a>
+method call</li>
+
+<li>
+<b>-txn_timeout </b>sets the timeout for transactions in the environment</li>
+
+<li>
+<b>-client_timeout</b> sets the timeout value for the client waiting for
+a reply from the server for RPC operations to <b><i>seconds</i></b>.</li>
+
+<li>
+<b>-server_timeout</b> sets the timeout value for the server to determine
+an idle client is gone to <b><i>seconds</i></b>.</li>
+
+<li>
+<b>-server </b>specifies the <b><i>hostname</i></b> of the server
+to connect to in the <a href="../../docs/api_c/env_set_server.html">DBENV->set_server</a>
+call.</li>
+
+<li>
+<b>-rep_client </b>sets the newly created environment to be a
+replication client, using the <a href="../../docs/api_c/rep_client.html">
+DBENV->rep_client</a> call.</li>
+
+<li>
+<b>-rep_master </b>sets the newly created environment to be a
+replication master, using the <a href="../../docs/api_c/rep_master.html">
+DBENV->rep_master</a> call.</li>
+
+<li>
+<b>-rep_transport </b>specifies the replication transport function,
+using the
+<a href="../../docs/api_c/rep_transport.html">DBENV->set_rep_transport</a>
+call. This site's machine ID is set to <b><i>machineid</i></b> and
+the send function, a Tcl proc, is set to <b><i>sendproc</i></b>.</li>
+
+</ul>
+
+This command will invoke the <a href="../../docs/api_c/env_create.html">db_env_create</a>
function.&nbsp; After it successfully gets a handle to an environment,
-we bind it to a new Tcl command of the form <B><I>envX</I></B>, where X
-is an integer starting at&nbsp; 0 (e.g. <B>env0, env1, </B>etc).&nbsp;
-We use the <I>Tcl_CreateObjCommand()</I> to create the top level environment
+we bind it to a new Tcl command of the form <b><i>envX</i></b>, where X
+is an integer starting at&nbsp; 0 (e.g. <b>env0, env1, </b>etc).&nbsp;
+We use the <i>Tcl_CreateObjCommand()</i> to create the top level environment
command function.&nbsp; It is through this handle that the user can access
-all the commands described in the <A HREF="#Environment Commands">Environment
-Commands</A> section.&nbsp; Internally, the handle we get back from DB
-will be stored as the <I>ClientData</I> portion of the new command set
+all the commands described in the <a href="#Environment Commands">Environment
+Commands</a> section.&nbsp; Internally, the handle we get back from DB
+will be stored as the <i>ClientData</i> portion of the new command set
so that all future environment calls will have that handle readily available.&nbsp;
-Then we call the <A HREF="../../docs/api_c/env_open.html">DBENV->open</A>
+Then we call the <a href="../../docs/api_c/env_open.html">DBENV->open</a>
method call and possibly some number of setup calls as described above.
-<P>
-<HR WIDTH="100%">
-<BR><A NAME="> <env> verbose which on|off"></A><B>> &lt;env> verbose <I>which</I>
-on|off</B>
-<P>This command controls the use of debugging output for the environment.&nbsp;
-This command directly translates to a call to the <A HREF="../../docs/api_c/dbenv_set_verbose.html">DBENV->set_verbose</A>
+<p>
+<hr WIDTH="100%">
+<br><a NAME="> <env> verbose which on|off"></a><b>> &lt;env> verbose <i>which</i>
+on|off</b>
+<p>This command controls the use of debugging output for the environment.&nbsp;
+This command directly translates to a call to the <a href="../../docs/api_c/dbenv_set_verbose.html">DBENV->set_verbose</a>
method call.&nbsp; It returns either a 0 (for success), a DB error message
or it throws a Tcl error with a system message.&nbsp; The user specifies
-<B><I>which</I></B>
+<b><i>which</i></b>
subsystem to control, and indicates whether debug messages should be turned
-<B>on</B>
-or <B>off</B> for that subsystem.&nbsp; The value of <B><I>which</I></B>
+<b>on</b>
+or <b>off</b> for that subsystem.&nbsp; The value of <b><i>which</i></b>
must be one of the following:
-<UL>
-<LI>
-<B>chkpt</B> - Chooses the checkpointing code by using the DB_VERB_CHKPOINT
-value</LI>
-
-<LI>
-<B>deadlock </B>- Chooses the deadlocking code by using the DB_VERB_DEADLOCK
-value</LI>
-
-<LI>
-<B>recovery </B>- Chooses the recovery code by using the DB_VERB_RECOVERY
-value</LI>
-
-<LI>
-<B>wait </B>- Chooses the waitsfor code by using the DB_VERB_WAITSFOR value</LI>
-</UL>
-
-<HR WIDTH="100%">
-<P><A NAME="> <env> close"></A><B>> &lt;env> close</B>
-<P>This command closes an environment and deletes the handle.&nbsp; This
-command directly translates to a call to the <A HREF="../../docs/api_c/env_close.html">DBENV->close</A>
+<ul>
+<li>
+<b>chkpt</b> - Chooses the checkpointing code by using the DB_VERB_CHKPOINT
+value</li>
+
+<li>
+<b>deadlock </b>- Chooses the deadlocking code by using the DB_VERB_DEADLOCK
+value</li>
+
+<li>
+<b>recovery </b>- Chooses the recovery code by using the DB_VERB_RECOVERY
+value</li>
+
+<li>
+<b>wait </b>- Chooses the waitsfor code by using the DB_VERB_WAITSFOR value</li>
+</ul>
+
+<hr WIDTH="100%">
+<p><a NAME="> <env> close"></a><b>> &lt;env> close</b>
+<p>This command closes an environment and deletes the handle.&nbsp; This
+command directly translates to a call to the <a href="../../docs/api_c/env_close.html">DBENV->close</a>
method call.&nbsp; It returns either a 0 (for success), a DB error message
or it throws a Tcl error with a system message.
-<P>Additionally, since the handle is no longer valid, we will call <I>Tcl_DeleteCommand()
-</I>so
+<p>Additionally, since the handle is no longer valid, we will call <i>Tcl_DeleteCommand()
+</i>so
that further uses of the handle will be dealt with properly by Tcl itself.
-<P>Also, the close command will automatically abort any <A HREF="txn.html">transactions</A>
-and close any <A HREF="mpool.html">mpool</A> memory files.&nbsp; As such
+<p>Also, the close command will automatically abort any <a href="txn.html">transactions</a>
+and close any <a href="mpool.html">mpool</a> memory files.&nbsp; As such
we must maintain a list of open transaction and mpool handles so that we
-can call <I>Tcl_DeleteCommand</I> on those as well.
-<P>
-<HR WIDTH="100%">
-<BR><B>> berkdb envremove [-data_dir <I>directory</I>] [-force] [-home
-<I>directory</I>]
--log_dir <I>directory</I>] [-tmp_dir <I>directory</I>] [-use_environ] [-use_environ_root]</B>
-<P>This command removes the environment if it is not in use and deletes
-the handle.&nbsp; This command directly translates to a call to the <A HREF="../../docs/api_c/env_remove.html">DBENV->remove</A>
+can call <i>Tcl_DeleteCommand</i> on those as well.
+<p>
+<hr WIDTH="100%">
+
+<b>> berkdb envremove<br>
+[-data_dir <i>directory</i>]<br>
+[-force]<br>
+[-home <i>directory</i>]<br>
+[-log_dir <i>directory</i>]<br>
+[-overwrite]<br>
+[-tmp_dir <i>directory</i>]<br>
+[-use_environ]<br>
+[-use_environ_root]</b>
+
+<p>This command removes the environment if it is not in use and deletes
+the handle.&nbsp; This command directly translates to a call to the <a href="../../docs/api_c/env_remove.html">DBENV->remove</a>
method call.&nbsp; It returns either a 0 (for success), a DB error message
or it throws a Tcl error with a system message.&nbsp; The arguments are:
-<UL>
-<LI>
-<B>-force</B> selects the DB_FORCE flag to remove even if other processes
-have the environment open</LI>
+<ul>
+<li>
+<b>-force</b> selects the DB_FORCE flag to remove even if other processes
+have the environment open</li>
+
+<li>
+<b>-home <i>directory</i> </b>specifies the home directory of the environment</li>
-<LI>
-<B>-home <I>directory</I> </B>specifies the home directory of the environment</LI>
+<li>
+<b>-data_dir <i>directory </i></b>selects the data file directory of the
+environment by calling <a href="../../docs/api_c/env_set_data_dir.html">DBENV->set_data_dir</a>.</li>
-<LI>
-<B>-data_dir <I>directory </I></B>selects the data file directory of the
-environment by calling <A HREF="../../docs/api_c/env_set_data_dir.html">DBENV->set_data_dir</A>.</LI>
+<li>
+<b>-log_dir <i>directory </i></b>selects the log file directory of the
+environment&nbsp; by calling <a href="../../docs/api_c/env_set_lg_dir.html">DBENV->set_lg_dir</a>.</li>
-<LI>
-<B>-log_dir <I>directory </I></B>selects the log file directory of the
-environment&nbsp; by calling <A HREF="../../docs/api_c/env_set_lg_dir.html">DBENV->set_lg_dir</A>.</LI>
+<li>
+<b>-overwrite </b>sets DB_OVERWRITE flag</li>
-<LI>
-<B>-tmp_dir <I>directory </I></B>selects the temporary file directory of
-the environment&nbsp; by calling <A HREF="../../docs/api_c/env_set_tmp_dir.so">DBENV->set_tmp_dir</A>.</LI>
+<li>
+<b>-tmp_dir <i>directory </i></b>selects the temporary file directory of
+the environment&nbsp; by calling <a href="../../docs/api_c/env_set_tmp_dir.so">DBENV->set_tmp_dir</a>.</li>
-<LI>
-<B>-use_environ </B>selects the DB_USE_ENVIRON flag to affect file naming</LI>
+<li>
+<b>-use_environ </b>selects the DB_USE_ENVIRON flag to affect file naming</li>
-<LI>
-<B>-use_environ_root</B> selects the DB_USE_ENVIRON_ROOT flag to affect
-file naming</LI>
-</UL>
+<li>
+<b>-use_environ_root</b> selects the DB_USE_ENVIRON_ROOT flag to affect
+file naming</li>
+</ul>
-</BODY>
-</HTML>
+</body>
+</html>
diff --git a/bdb/tcl/docs/historic.html b/bdb/tcl/docs/historic.html
index 216dc456b72..85f474fbc0f 100644
--- a/bdb/tcl/docs/historic.html
+++ b/bdb/tcl/docs/historic.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
diff --git a/bdb/tcl/docs/index.html b/bdb/tcl/docs/index.html
index 2866c1e23db..845b6ca81e2 100644
--- a/bdb/tcl/docs/index.html
+++ b/bdb/tcl/docs/index.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
@@ -29,6 +30,9 @@ Complete Tcl Interface for Berkeley DB</H1></CENTER>
<A HREF="./mpool.html">Memory Pool commands</A></LI>
<LI>
+<A HREF="./rep.html">Replication commands</A></LI>
+
+<LI>
<A HREF="./txn.html">Transaction commands</A></LI>
</UL>
diff --git a/bdb/tcl/docs/library.html b/bdb/tcl/docs/library.html
index abd656d8e5d..bfb1588c3f2 100644
--- a/bdb/tcl/docs/library.html
+++ b/bdb/tcl/docs/library.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
diff --git a/bdb/tcl/docs/lock.html b/bdb/tcl/docs/lock.html
index 87a20e9a6bf..d65142b798b 100644
--- a/bdb/tcl/docs/lock.html
+++ b/bdb/tcl/docs/lock.html
@@ -1,187 +1,207 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="GENERATOR" CONTENT="Mozilla/4.08 [en] (X11; I; FreeBSD 2.2.8-19990120-SNAP i386) [Netscape]">
-</HEAD>
-<BODY>
-
-<H2>
-<A NAME="Locking Commands"></A>Locking Commands</H2>
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.75 [en] (X11; U; Linux 2.2.16-22 i686) [Netscape]">
+</head>
+<body>
+
+<h2>
+<a NAME="Locking Commands"></a>Locking Commands</h2>
Most locking commands work with the environment handle.&nbsp; However,
when a user gets a lock we create a new lock handle that they then use
with in a similar manner to all the other handles to release the lock.&nbsp;
We present the general locking functions first, and then those that manipulate
locks.
-<P><B>> &lt;env> lock_detect [-lock_conflict] [default|oldest|youngest|random]</B>
-<P>This command runs the deadlock detector.&nbsp; It directly translates
-to the <A HREF="../../docs/api_c/lock_detect.html">lock_detect</A> DB call.&nbsp;
+<p><b>> &lt;env> lock_detect [default|oldest|youngest|random]</b>
+<p>This command runs the deadlock detector.&nbsp; It directly translates
+to the <a href="../../docs/api_c/lock_detect.html">lock_detect</a> DB call.&nbsp;
It returns either a 0 (for success), a DB error message or it throws a
Tcl error with a system message.&nbsp; The first argument sets the policy
for deadlock as follows:
-<UL>
-<LI>
-<B>default</B> selects the DB_LOCK_DEFAULT policy for default detection
-(default if not specified)</LI>
-
-<LI>
-<B>oldest </B>selects DB_LOCK_OLDEST to abort the oldest locker on a deadlock</LI>
-
-<LI>
-<B>random</B> selects DB_LOCK_RANDOM to abort a random locker on a deadlock</LI>
-
-<LI>
-<B>youngest</B> selects DB_LOCK_YOUNGEST to abort the youngest locker on
-a deadlock</LI>
-</UL>
-The second argument, <B>-lock_conflict</B>, selects the DB_LOCK_CONFLICT
-flag to only run the detector if a lock conflict has occurred since the
-last time the detector was run.
-<HR WIDTH="100%">
-<BR><B>> &lt;env> lock_stat</B>
-<P>This command returns a list of name/value pairs where the names correspond
+<ul>
+<li>
+<b>default</b> selects the DB_LOCK_DEFAULT policy for default detection
+(default if not specified)</li>
+
+<li>
+<b>oldest </b>selects DB_LOCK_OLDEST to abort the oldest locker on a deadlock</li>
+
+<li>
+<b>random</b> selects DB_LOCK_RANDOM to abort a random locker on a deadlock</li>
+
+<li>
+<b>youngest</b> selects DB_LOCK_YOUNGEST to abort the youngest locker on
+a deadlock</li>
+</ul>
+
+<hr WIDTH="100%">
+<br><b>> &lt;env> lock_stat</b>
+<p>This command returns a list of name/value pairs where the names correspond
to the C-structure field names of DB_LOCK_STAT and the values are the data
-returned.&nbsp; This command is a direct translation of the <A HREF="../../docs/api_c/lock_stat.html">lock_stat</A>
+returned.&nbsp; This command is a direct translation of the <a href="../../docs/api_c/lock_stat.html">lock_stat</a>
DB call.
-<HR WIDTH="100%">
-<BR><A NAME="> <env> lock_id"></A><B>> &lt;env> lock_id</B>
-<P>This command returns a unique locker ID value.&nbsp; It directly translates
-to the <A HREF="../../docs/api_c/lock_id.html">lock_id</A> DB call.
-<HR WIDTH="100%">
-<BR><A NAME="> <env> lock_get"></A><B>> &lt;env> lock_get [-nowait]<I>lockmode
-locker obj</I></B>
-<P>This command gets a lock. It will invoke the <A HREF="../../docs/api_c/lock_get.html">lock_get</A>
+<hr WIDTH="100%">
+<br><a NAME="> <env> lock_id"></a><b>> &lt;env> lock_id</b>
+<p>This command returns a unique locker ID value.&nbsp; It directly translates
+to the <a href="../../docs/api_c/lock_id.html">lock_id</a> DB call.
+<br>
+<hr WIDTH="100%">
+<br><a NAME="> <env> lock_id"></a><b>> &lt;env> lock_id_free&nbsp; </b><i>locker</i>
+<p>This command frees the locker allockated by the lock_id call. It directly
+translates to the&nbsp; <a href="../../docs/api_c/lock_id.html">lock_id_free
+</a>DB
+call.
+<hr WIDTH="100%">
+<br><a NAME="> <env> lock_id"></a><b>> &lt;env> lock_id_set&nbsp; </b><i>current
+max</i>
+<p>This&nbsp; is a diagnostic command to set the locker id that will get
+allocated next and the maximum id that
+<br>will trigger the id reclaim algorithm.
+<hr WIDTH="100%">
+<br><a NAME="> <env> lock_get"></a><b>> &lt;env> lock_get [-nowait]<i>lockmode
+locker obj</i></b>
+<p>This command gets a lock. It will invoke the <a href="../../docs/api_c/lock_get.html">lock_get</a>
function.&nbsp; After it successfully gets a handle to a lock, we bind
-it to a new Tcl command of the form <B><I>$env.lockX</I></B>, where X is
-an integer starting at&nbsp; 0 (e.g. <B>$env.lock0, $env.lock1, </B>etc).&nbsp;
-We use the <I>Tcl_CreateObjCommand()</I> to create the top level locking
+it to a new Tcl command of the form <b><i>$env.lockX</i></b>, where X is
+an integer starting at&nbsp; 0 (e.g. <b>$env.lock0, $env.lock1, </b>etc).&nbsp;
+We use the <i>Tcl_CreateObjCommand()</i> to create the top level locking
command function.&nbsp; It is through this handle that the user can release
the lock.&nbsp; Internally, the handle we get back from DB will be stored
-as the <I>ClientData</I> portion of the new command set so that future
+as the <i>ClientData</i> portion of the new command set so that future
locking calls will have that handle readily available.
-<P>The arguments are:
-<UL>
-<LI>
-<B><I>locker</I></B> specifies the locker ID returned from the <A HREF="#> <env> lock_id">lock_id</A>
-command</LI>
+<p>The arguments are:
+<ul>
+<li>
+<b><i>locker</i></b> specifies the locker ID returned from the <a href="#> <env> lock_id">lock_id</a>
+command</li>
-<LI>
-<B><I>obj</I></B> specifies an object to lock</LI>
+<li>
+<b><i>obj</i></b> specifies an object to lock</li>
-<LI>
-the <B><I>lock mode</I></B> is specified as one of the following:</LI>
+<li>
+the <b><i>lock mode</i></b> is specified as one of the following:</li>
-<UL>
-<LI>
-<B>ng </B>specifies DB_LOCK_NG for not granted (always 0)</LI>
+<ul>
+<li>
+<b>ng </b>specifies DB_LOCK_NG for not granted (always 0)</li>
-<LI>
-<B>read</B> specifies DB_LOCK_READ for a read (shared) lock</LI>
+<li>
+<b>read</b> specifies DB_LOCK_READ for a read (shared) lock</li>
-<LI>
-<B>write</B> specifies DB_LOCK_WRITE for an exclusive write lock</LI>
+<li>
+<b>write</b> specifies DB_LOCK_WRITE for an exclusive write lock</li>
-<LI>
-<B>iwrite </B>specifies DB_LOCK_IWRITE for intent for exclusive write lock</LI>
+<li>
+<b>iwrite </b>specifies DB_LOCK_IWRITE for intent for exclusive write lock</li>
-<LI>
-<B>iread </B>specifies DB_LOCK_IREAD for intent for shared read lock</LI>
+<li>
+<b>iread </b>specifies DB_LOCK_IREAD for intent for shared read lock</li>
-<LI>
-<B>iwr </B>specifies DB_LOCK_IWR for intent for eread and write lock</LI>
-</UL>
+<li>
+<b>iwr </b>specifies DB_LOCK_IWR for intent for eread and write lock</li>
+</ul>
-<LI>
-<B>-nowait</B> selects the DB_LOCK_NOWAIT to indicate that we do not want
-to wait on the lock</LI>
-</UL>
+<li>
+<b>-nowait</b> selects the DB_LOCK_NOWAIT to indicate that we do not want
+to wait on the lock</li>
+</ul>
-<HR WIDTH="100%">
-<BR><B>> &lt;lock> put</B>
-<P>This command releases the lock referenced by the command.&nbsp; It is
-a direct translation of the <A HREF="../../docs/api_c/lock_put.html">lock_put</A>
+<hr WIDTH="100%">
+<br><b>> &lt;lock> put</b>
+<p>This command releases the lock referenced by the command.&nbsp; It is
+a direct translation of the <a href="../../docs/api_c/lock_put.html">lock_put</a>
function.&nbsp; It returns either a 0 (for success), a DB error message
or it throws a Tcl error with a system message.&nbsp; Additionally, since
the handle is no longer valid, we will call
-<I>Tcl_DeleteCommand()
-</I>so
+<i>Tcl_DeleteCommand()
+</i>so
that further uses of the handle will be dealt with properly by Tcl itself.
-<BR>
-<HR WIDTH="100%">
-<BR><A NAME="> <env> lock_vec"></A><B>> &lt;env> lock_vec [-nowait] <I>locker
-</I>{get|put|put_all|put_obj
-[<I>obj</I>] [<I>lockmode</I>] [<I>lock</I>]} ...</B>
-<P>This command performs a series of lock calls.&nbsp; It is a direct translation
-of the <A HREF="../../docs/api_c/lock_vec.html">lock_vec</A> function.&nbsp;
+<br>
+<hr WIDTH="100%">
+<br><a NAME="> <env> lock_vec"></a><b>> &lt;env> lock_vec [-nowait] <i>locker
+</i>{get|put|put_all|put_obj
+[<i>obj</i>] [<i>lockmode</i>] [<i>lock</i>]} ...</b>
+<p>This command performs a series of lock calls.&nbsp; It is a direct translation
+of the <a href="../../docs/api_c/lock_vec.html">lock_vec</a> function.&nbsp;
This command will return a list of the return values from each operation
specified in the argument list.&nbsp; For the 'put' operations the entry
in the return value list is either a 0 (for success) or an error.&nbsp;
-For the 'get' operation, the entry is the lock widget handle, <B>$env.lockN</B>
-(as described above in <A HREF="#> <env> lock_get">&lt;env> lock_get</A>)
+For the 'get' operation, the entry is the lock widget handle, <b>$env.lockN</b>
+(as described above in <a href="#> <env> lock_get">&lt;env> lock_get</a>)
or an error.&nbsp; If an error occurs, the return list will contain the
return values for all the successful operations up the erroneous one and
the error code for that operation.&nbsp; Subsequent operations will be
ignored.
-<P>As for the other operations, if we are doing a 'get' we will create
+<p>As for the other operations, if we are doing a 'get' we will create
the commands and if we are doing a 'put' we will have to delete the commands.&nbsp;
Additionally, we will have to do this after the call to the DB lock_vec
and iterate over the results, creating and/or deleting Tcl commands.&nbsp;
It is possible that we may return a lock widget from a get operation that
-is considered invalid, if, for instance, there was a <B>put_all</B> operation
+is considered invalid, if, for instance, there was a <b>put_all</b> operation
performed later in the vector of operations.&nbsp; The arguments are:
-<UL>
-<LI>
-<B><I>locker</I></B> specifies the locker ID returned from the <A HREF="#> <env> lock_id">lock_id</A>
-command</LI>
+<ul>
+<li>
+<b><i>locker</i></b> specifies the locker ID returned from the <a href="#> <env> lock_id">lock_id</a>
+command</li>
-<LI>
-<B>-nowait</B> selects the DB_LOCK_NOWAIT to indicate that we do not want
-to wait on the lock</LI>
+<li>
+<b>-nowait</b> selects the DB_LOCK_NOWAIT to indicate that we do not want
+to wait on the lock</li>
-<LI>
+<li>
the lock vectors are tuple consisting of {an operation, lock object, lock
-mode, lock handle} where what is required is based on the operation desired:</LI>
-
-<UL>
-<LI>
-<B>get</B> specifes DB_LOCK_GET to get a lock.&nbsp; Requires a tuple <B>{get
-<I>obj</I>
-<I>mode</I>}
-</B>where
-<B><I>mode</I></B>
-is:</LI>
-
-<UL>
-<LI>
-<B>ng </B>specifies DB_LOCK_NG for not granted (always 0)</LI>
-
-<LI>
-<B>read</B> specifies DB_LOCK_READ for a read (shared) lock</LI>
-
-<LI>
-<B>write</B> specifies DB_LOCK_WRITE for an exclusive write lock</LI>
-
-<LI>
-<B>iwrite </B>specifies DB_LOCK_IWRITE for intent for exclusive write lock</LI>
-
-<LI>
-<B>iread </B>specifies DB_LOCK_IREAD for intent for shared read lock</LI>
-
-<LI>
-<B>iwr </B>specifies DB_LOCK_IWR for intent for eread and write lock</LI>
-</UL>
-
-<LI>
-<B>put</B> specifies DB_LOCK_PUT to release a <B><I>lock</I></B>.&nbsp;
-Requires a tuple <B>{put <I>lock}</I></B></LI>
-
-<LI>
-<B>put_all </B>specifies DB_LOCK_PUT_ALL to release all locks held by <B><I>locker</I></B>.&nbsp;
-Requires a tuple <B>{put_all}</B></LI>
-
-<LI>
-<B>put_obj</B> specifies DB_LOCK_PUT_OBJ to release all locks held by <B><I>locker</I></B>
-associated with the given <B><I>obj</I></B>.&nbsp; Requires a tuple <B>{put_obj
-<I>obj</I>}</B></LI>
-</UL>
-</UL>
+mode, lock handle} where what is required is based on the operation desired:</li>
+
+<ul>
+<li>
+<b>get</b> specifes DB_LOCK_GET to get a lock.&nbsp; Requires a tuple <b>{get
+<i>objmode</i>}
+</b>where
+<b><i>mode</i></b>
+is:</li>
+
+<ul>
+<li>
+<b>ng </b>specifies DB_LOCK_NG for not granted (always 0)</li>
+
+<li>
+<b>read</b> specifies DB_LOCK_READ for a read (shared) lock</li>
+
+<li>
+<b>write</b> specifies DB_LOCK_WRITE for an exclusive write lock</li>
+
+<li>
+<b>iwrite </b>specifies DB_LOCK_IWRITE for intent for exclusive write lock</li>
+
+<li>
+<b>iread </b>specifies DB_LOCK_IREAD for intent for shared read lock</li>
+
+<li>
+<b>iwr </b>specifies DB_LOCK_IWR for intent for eread and write lock</li>
+</ul>
+
+<li>
+<b>put</b> specifies DB_LOCK_PUT to release a <b><i>lock</i></b>.&nbsp;
+Requires a tuple <b>{put <i>lock}</i></b></li>
+
+<li>
+<b>put_all </b>specifies DB_LOCK_PUT_ALL to release all locks held by <b><i>locker</i></b>.&nbsp;
+Requires a tuple <b>{put_all}</b></li>
+
+<li>
+<b>put_obj</b> specifies DB_LOCK_PUT_OBJ to release all locks held by <b><i>locker</i></b>
+associated with the given <b><i>obj</i></b>.&nbsp; Requires a tuple <b>{put_obj
+<i>obj}</i></b></li>
+</ul>
+</ul>
+
+<hr WIDTH="100%">
+<br><a NAME="> <env> lock_vec"></a><b>> &lt;env> lock_timeout <i>timeout</i></b>
+<p>This command sets the lock timeout for all future locks in this environment.&nbsp;
+The timeout is in micorseconds.
+<br>&nbsp;
+<br>&nbsp;
+</body>
+</html>
diff --git a/bdb/tcl/docs/log.html b/bdb/tcl/docs/log.html
index 35ecfc2f5f5..49f2f0ad2e0 100644
--- a/bdb/tcl/docs/log.html
+++ b/bdb/tcl/docs/log.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
@@ -100,7 +101,7 @@ given <B><I>lsn</I></B></LI>
<HR WIDTH="100%">
<BR><A NAME="> <env> log_put"></A><B>> &lt;env> log_put<I> </I>[-checkpoint]
-[-curlsn] [-flush] <I>record</I></B>
+[-flush] <I>record</I></B>
<P>This command stores a <B><I>record</I></B> into the log and returns
the LSN of the log record.&nbsp; It is a direct call to the <A HREF="../../docs/api_c/log_put.html">log_put</A>
function.&nbsp; It returns either an LSN or it throws a Tcl error with
@@ -110,29 +111,10 @@ a system message.&nbsp;<B> </B>The arguments are:
<B>-checkpoint </B>selects the DB_CHECKPOINT flag</LI>
<LI>
-<B>-curlsn</B> selects the DB_CURLSN flag to return the LSN of the next
-record</LI>
-
-<LI>
<B>-flush </B>selects the DB_FLUSH flag to flush the log to disk.</LI>
</UL>
<HR WIDTH="100%">
-<BR><A NAME="> <env> log_register"></A><B>> &lt;env> log_register <I>db</I>
-<I>file</I></B>
-<P>This command registers a <B><I>file</I></B> and <B><I>db</I></B> with
-the log manager.&nbsp; It is a direct call to the <A HREF="../../docs/api_c/log_register.html">log_register</A>
-function.&nbsp; It returns either a 0 (for success), a DB error message
-or it throws a Tcl error with a system message.
-<BR>
-<HR WIDTH="100%">
-<BR><A NAME="> <env> log_unregister"></A><B>> &lt;env> log_unregister <I>db</I></B>
-<P>This command unregisters the file specified by the database handle <B><I>db
-</I></B>from the log manager.&nbsp; It is a direct call to the <A HREF="../../docs/api_c/log_unregister.html">log_unregister</A>
-function.&nbsp; It returns either a 0 (for success), a DB error message
-or it throws a Tcl error with a system message.
-<BR>
-<HR WIDTH="100%">
<BR><B>> &lt;env> log_stat</B>
<P>This command returns&nbsp; the statistics associated with the logging
subsystem.&nbsp; It is a direct call to the <A HREF="../../docs/api_c/log_stat.html">log_stat</A>
diff --git a/bdb/tcl/docs/mpool.html b/bdb/tcl/docs/mpool.html
index 666219306ca..7f2359b36e9 100644
--- a/bdb/tcl/docs/mpool.html
+++ b/bdb/tcl/docs/mpool.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
diff --git a/bdb/tcl/docs/rep.html b/bdb/tcl/docs/rep.html
new file mode 100644
index 00000000000..079fe443a63
--- /dev/null
+++ b/bdb/tcl/docs/rep.html
@@ -0,0 +1,51 @@
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Replication commands</title>
+</head>
+<body>
+
+<h2>
+<a NAME="Replication Commands"></a>Replication Commands</h2>
+Replication commands are invoked from the environment handle, after
+it has been opened with the appropriate flags defined
+<a href="./env.html">here</a>.<br>
+<hr WIDTH="100%">
+<p><b>> &lt;env> rep_process_message <i>machid</i> <i>control</i>
+<i>rec</i></b>
+<p>This command processes a single incoming replication message.&nbsp; It
+is a direct translation of the <a
+href="../../docs/api_c/rep_process_message.html">rep_process_message</a>
+function.&nbsp;
+It returns either a 0 (for success), a DB error message or it throws a
+Tcl error with a system message.&nbsp; The arguments are:
+<ul>
+<li>
+<b>machid </b>is the machine ID of the machine that <i>sent</i> this
+message.</li>
+
+<li>
+<b>control</b> is a binary string containing the exact contents of the
+<b><i>control</i></b> argument to the <b><i>sendproc</i></b> function
+that was passed this message on another site.</li>
+
+<li>
+<b>rec</b> is a binary string containing the exact contents of the
+<b><i>rec</i></b> argument to the <b><i>sendproc</i></b> function
+that was passed this message on another site.</li>
+</ul>
+
+<hr WIDTH="100%">
+<br><b>> &lt;env> rep_elect <i>nsites</i> <i>pri</i> <i>wait</i>
+<i>sleep</i></b>
+<p>This command causes a replication election.&nbsp; It is a direct translation
+of the <a href="../../docs/api_c/rep_elect.html">rep_elect</a> function.&nbsp;
+Its arguments, all integers, correspond exactly to that C function's
+parameters.
+It will return a list containing two integers, which contain,
+respectively, the integer values returned in the C function's
+<i><b>midp</b></i> and <i><b>selfp</b></i> parameters.
+</body>
+</html>
diff --git a/bdb/tcl/docs/test.html b/bdb/tcl/docs/test.html
index 10cf09efba7..603ae56a51e 100644
--- a/bdb/tcl/docs/test.html
+++ b/bdb/tcl/docs/test.html
@@ -1,4 +1,5 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
diff --git a/bdb/tcl/docs/txn.html b/bdb/tcl/docs/txn.html
index 863c9a875e6..07c88c0fe1d 100644
--- a/bdb/tcl/docs/txn.html
+++ b/bdb/tcl/docs/txn.html
@@ -1,56 +1,67 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="GENERATOR" CONTENT="Mozilla/4.08 [en] (X11; I; FreeBSD 2.2.8-19990120-SNAP i386) [Netscape]">
-</HEAD>
-<BODY>
+<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--All rights reserved.-->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.75 [en] (X11; U; Linux 2.2.16-22 i686) [Netscape]">
+</head>
+<body>
-<H2>
-<A NAME="Transaction Commands"></A>Transaction Commands</H2>
+<h2>
+<a NAME="Transaction Commands"></a>Transaction Commands</h2>
Transactions are used in a manner similar to the other subsystems.&nbsp;
We create a handle to the transaction and&nbsp; then use it for a variety
of operations.&nbsp; Some of the transaction commands use the environment
instead.&nbsp; Those are presented first.&nbsp; The transaction command
handle returned is the handle used by the various commands that can be
-transaction protected, such as <A HREF="../../docs/api_tcl/db_cursor.html">cursors</A>.<BR>
-
-<HR WIDTH="100%">
-<P><B>> &lt;env> txn_checkpoint [-kbyte <I>kb</I>] [-min <I>min</I>]</B>
-<P>This command causes a checkpoint of the transaction region.&nbsp; It
-is a direct translation of the <A HREF="../../docs/api_c/txn_checkpoint.html">txn_checkpoint
-</A>function.&nbsp;
+transaction protected, such as <a href="../../docs/api_tcl/db_cursor.html">cursors</a>.
+<br>
+<hr WIDTH="100%">
+<p><b>> &lt;env> txn_checkpoint [-kbyte <i>kb</i>] [-min <i>min</i>]</b>
+<p>This command causes a checkpoint of the transaction region.&nbsp; It
+is a direct translation of the <a href="../../docs/api_c/txn_checkpoint.html">txn_checkpoint
+</a>function.&nbsp;
It returns either a 0 (for success), a DB error message or it throws a
Tcl error with a system message.&nbsp; The arguments are:
-<UL>
-<LI>
-<B>-kbyte </B>causes the checkpoint to occur only if <B><I>kb</I></B> kilobytes
-of log data has been written since the last checkpoint</LI>
+<ul>
+<li>
+<b>-kbyte </b>causes the checkpoint to occur only if <b><i>kb</i></b> kilobytes
+of log data has been written since the last checkpoint</li>
-<LI>
-<B>-min</B> causes the checkpoint to occur only if <B><I>min</I></B> minutes
-have passed since the last checkpoint</LI>
-</UL>
+<li>
+<b>-min</b> causes the checkpoint to occur only if <b><i>min</i></b> minutes
+have passed since the last checkpoint</li>
+</ul>
-<HR WIDTH="100%">
-<BR><B>> &lt;env> txn_stat</B>
-<P>This command returns transaction statistics.&nbsp; It is a direct translation
-of the <A HREF="../../docs/api_c/txn_stat.html">txn_stat</A> function.&nbsp;
+<hr WIDTH="100%">
+<br><b>> &lt;env> txn_stat</b>
+<p>This command returns transaction statistics.&nbsp; It is a direct translation
+of the <a href="../../docs/api_c/txn_stat.html">txn_stat</a> function.&nbsp;
It will return a list of name/value pairs that correspond to the DB_TXN_STAT
structure.
-<HR WIDTH="100%">
-<BR><B>>&nbsp; &lt;txn> id</B>
-<P>This command returns the transaction id.&nbsp; It is a direct call to
-the <A HREF="../../docs/api_c/txn_id.html">txn_id</A> function.&nbsp; The
-typical use of this identifier is as the <B><I>locker</I></B> value for
-the <A HREF="lock.html">lock_get</A> and <A HREF="lock.html">lock_vec</A>
+<hr WIDTH="100%">
+<br><b>> &lt;env> txn_id_set&nbsp;</b><i> current max</i>
+<p>This is a diagnosic command that sets the next transaction id to be
+allocated and the maximum transaction
+<br>id, which is the point at which the relcaimation algorthm is triggered.
+<hr WIDTH="100%">
+<br><b>>&nbsp; &lt;txn> id</b>
+<p>This command returns the transaction id.&nbsp; It is a direct call to
+the <a href="../../docs/api_c/txn_id.html">txn_id</a> function.&nbsp; The
+typical use of this identifier is as the <b><i>locker</i></b> value for
+the <a href="lock.html">lock_get</a> and <a href="lock.html">lock_vec</a>
calls.
-<HR WIDTH="100%">
-<BR><B>> &lt;txn> prepare</B>
-<P>This command initiates a two-phase commit.&nbsp; It is a direct call
-to the <A HREF="../../docs/api_c/txn_prepare.html">txn_prepare</A> function.&nbsp;
+<hr WIDTH="100%">
+<br><b>> &lt;txn> prepare</b>
+<p>This command initiates a two-phase commit.&nbsp; It is a direct call
+to the <a href="../../docs/api_c/txn_prepare.html">txn_prepare</a> function.&nbsp;
It returns either a 0 (for success), a DB error message or it throws a
Tcl error with a system message.
-<HR WIDTH="100%">
-</BODY>
-</HTML>
+<hr WIDTH="100%"><a NAME="> <env> lock_vec"></a><b>> &lt;env> txn_timeout
+<i>timeout</i></b>
+<p>This command sets thetransaction timeout for transactions started in
+the future in this environment.&nbsp; The timeout is in micorseconds.
+<br>&nbsp;
+<br>&nbsp;
+</body>
+</html>
diff --git a/bdb/tcl/tcl_compat.c b/bdb/tcl/tcl_compat.c
index 41caee95cc7..e77bc32aedf 100644
--- a/bdb/tcl/tcl_compat.c
+++ b/bdb/tcl/tcl_compat.c
@@ -1,16 +1,18 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_compat.c,v 11.22 2001/01/11 18:19:55 bostic Exp $";
+static const char revid[] = "$Id: tcl_compat.c,v 11.39 2002/08/15 14:05:38 bostic Exp $";
#endif /* not lint */
+#if CONFIG_TEST
+
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
@@ -23,12 +25,7 @@ static const char revid[] = "$Id: tcl_compat.c,v 11.22 2001/01/11 18:19:55 bosti
#define DB_DBM_HSEARCH 1
#include "db_int.h"
-#include "tcl_db.h"
-
-/*
- * Prototypes for procedures defined later in this file:
- */
-static int mutex_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
+#include "dbinc/tcl_db.h"
/*
* bdb_HCommand --
@@ -91,7 +88,7 @@ bdb_HCommand(interp, objc, objv)
if (result == TCL_OK) {
_debug_check();
ret = hcreate(nelem) == 0 ? 1: 0;
- _ReturnSetup(interp, ret, "hcreate");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "hcreate");
}
break;
case HHSEARCH:
@@ -104,17 +101,17 @@ bdb_HCommand(interp, objc, objv)
}
item.key = Tcl_GetStringFromObj(objv[2], NULL);
item.data = Tcl_GetStringFromObj(objv[3], NULL);
- action = 0;
if (Tcl_GetIndexFromObj(interp, objv[4], srchacts,
"action", TCL_EXACT, &actindex) != TCL_OK)
return (IS_HELP(objv[4]));
switch ((enum srchacts)actindex) {
- case ACT_FIND:
- action = FIND;
- break;
case ACT_ENTER:
action = ENTER;
break;
+ default:
+ case ACT_FIND:
+ action = FIND;
+ break;
}
_debug_check();
hres = hsearch(item, action);
@@ -182,7 +179,7 @@ bdb_NdbmOpen(interp, objc, objv, dbpp)
};
u_int32_t open_flags;
- int endarg, i, mode, optindex, read_only, result;
+ int endarg, i, mode, optindex, read_only, result, ret;
char *arg, *db;
result = TCL_OK;
@@ -281,7 +278,9 @@ bdb_NdbmOpen(interp, objc, objv, dbpp)
open_flags |= O_RDWR;
_debug_check();
if ((*dbpp = dbm_open(db, open_flags, mode)) == NULL) {
- result = _ReturnSetup(interp, Tcl_GetErrno(), "db open");
+ ret = Tcl_GetErrno();
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db open");
goto error;
}
return (TCL_OK);
@@ -335,10 +334,13 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
STINSERT, STREPLACE
};
datum key, data;
- int cmdindex, stindex, result, ret;
+ void *dtmp, *ktmp;
+ u_int32_t size;
+ int cmdindex, freedata, freekey, stindex, result, ret;
char *name, *t;
result = TCL_OK;
+ freekey = freedata = 0;
/*
* Get the command name index from the object based on the cmds
* defined above. This SHOULD NOT fail because we already checked
@@ -365,7 +367,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
"Bad interface flag for command", TCL_STATIC);
return (TCL_ERROR);
}
- _ReturnSetup(interp, ret, "dbmclose");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbmclose");
break;
case DBMINIT:
/*
@@ -383,7 +385,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
TCL_STATIC);
return (TCL_ERROR);
}
- _ReturnSetup(interp, ret, "dbminit");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbminit");
break;
case DBMFETCH:
/*
@@ -393,7 +395,14 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
Tcl_WrongNumArgs(interp, 2, objv, "key");
return (TCL_ERROR);
}
- key.dptr = (char *)Tcl_GetByteArrayFromObj(objv[2], &key.dsize);
+ if ((ret = _CopyObjBytes(
+ interp, objv[2], &ktmp, &size, &freekey)) != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "dbm fetch");
+ goto out;
+ }
+ key.dsize = size;
+ key.dptr = (char *)ktmp;
_debug_check();
if (flag == DBTCL_DBM)
data = fetch(key);
@@ -402,16 +411,17 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
else {
Tcl_SetResult(interp,
"Bad interface flag for command", TCL_STATIC);
- return (TCL_ERROR);
+ result = TCL_ERROR;
+ goto out;
}
if (data.dptr == NULL ||
- (ret = __os_malloc(NULL, data.dsize + 1, NULL, &t)) != 0)
+ (ret = __os_malloc(NULL, data.dsize + 1, &t)) != 0)
Tcl_SetResult(interp, "-1", TCL_STATIC);
else {
memcpy(t, data.dptr, data.dsize);
t[data.dsize] = '\0';
Tcl_SetResult(interp, t, TCL_VOLATILE);
- __os_free(t, data.dsize + 1);
+ __os_free(NULL, t);
}
break;
case DBMSTORE:
@@ -426,9 +436,22 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
Tcl_WrongNumArgs(interp, 2, objv, "key data action");
return (TCL_ERROR);
}
- key.dptr = (char *)Tcl_GetByteArrayFromObj(objv[2], &key.dsize);
- data.dptr =
- (char *)Tcl_GetByteArrayFromObj(objv[3], &data.dsize);
+ if ((ret = _CopyObjBytes(
+ interp, objv[2], &ktmp, &size, &freekey)) != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "dbm fetch");
+ goto out;
+ }
+ key.dsize = size;
+ key.dptr = (char *)ktmp;
+ if ((ret = _CopyObjBytes(
+ interp, objv[3], &dtmp, &size, &freedata)) != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "dbm fetch");
+ goto out;
+ }
+ data.dsize = size;
+ data.dptr = (char *)dtmp;
_debug_check();
if (flag == DBTCL_DBM)
ret = store(key, data);
@@ -450,7 +473,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
"Bad interface flag for command", TCL_STATIC);
return (TCL_ERROR);
}
- _ReturnSetup(interp, ret, "store");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "store");
break;
case DBMDELETE:
/*
@@ -460,7 +483,14 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
Tcl_WrongNumArgs(interp, 2, objv, "key");
return (TCL_ERROR);
}
- key.dptr = (char *)Tcl_GetByteArrayFromObj(objv[2], &key.dsize);
+ if ((ret = _CopyObjBytes(
+ interp, objv[2], &ktmp, &size, &freekey)) != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "dbm fetch");
+ goto out;
+ }
+ key.dsize = size;
+ key.dptr = (char *)ktmp;
_debug_check();
if (flag == DBTCL_DBM)
ret = delete(key);
@@ -471,7 +501,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
"Bad interface flag for command", TCL_STATIC);
return (TCL_ERROR);
}
- _ReturnSetup(interp, ret, "delete");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "delete");
break;
case DBMFIRST:
/*
@@ -492,13 +522,13 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
return (TCL_ERROR);
}
if (key.dptr == NULL ||
- (ret = __os_malloc(NULL, key.dsize + 1, NULL, &t)) != 0)
+ (ret = __os_malloc(NULL, key.dsize + 1, &t)) != 0)
Tcl_SetResult(interp, "-1", TCL_STATIC);
else {
memcpy(t, key.dptr, key.dsize);
t[key.dsize] = '\0';
Tcl_SetResult(interp, t, TCL_VOLATILE);
- __os_free(t, key.dsize + 1);
+ __os_free(NULL, t);
}
break;
case DBMNEXT:
@@ -511,8 +541,14 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return (TCL_ERROR);
}
- key.dptr = (char *)
- Tcl_GetByteArrayFromObj(objv[2], &key.dsize);
+ if ((ret = _CopyObjBytes(
+ interp, objv[2], &ktmp, &size, &freekey)) != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "dbm fetch");
+ goto out;
+ }
+ key.dsize = size;
+ key.dptr = (char *)ktmp;
data = nextkey(key);
} else if (flag == DBTCL_NDBM) {
if (objc != 2) {
@@ -526,16 +562,21 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
return (TCL_ERROR);
}
if (data.dptr == NULL ||
- (ret = __os_malloc(NULL, data.dsize + 1, NULL, &t)) != 0)
+ (ret = __os_malloc(NULL, data.dsize + 1, &t)) != 0)
Tcl_SetResult(interp, "-1", TCL_STATIC);
else {
memcpy(t, data.dptr, data.dsize);
t[data.dsize] = '\0';
Tcl_SetResult(interp, t, TCL_VOLATILE);
- __os_free(t, data.dsize + 1);
+ __os_free(NULL, t);
}
break;
}
+out:
+ if (freedata)
+ (void)__os_free(NULL, dtmp);
+ if (freekey)
+ (void)__os_free(NULL, ktmp);
return (result);
}
@@ -636,7 +677,8 @@ ndbm_Cmd(clientData, interp, objc, objv)
_debug_check();
ret = dbm_clearerr(dbp);
if (ret)
- _ReturnSetup(interp, ret, "clearerr");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "clearerr");
else
res = Tcl_NewIntObj(ret);
break;
@@ -688,7 +730,7 @@ ndbm_Cmd(clientData, interp, objc, objv)
_debug_check();
ret = dbm_rdonly(dbp);
if (ret)
- _ReturnSetup(interp, ret, "rdonly");
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "rdonly");
else
res = Tcl_NewIntObj(ret);
break;
@@ -701,355 +743,4 @@ ndbm_Cmd(clientData, interp, objc, objv)
Tcl_SetObjResult(interp, res);
return (result);
}
-
-/*
- * bdb_RandCommand --
- * Implements rand* functions.
- *
- * PUBLIC: int bdb_RandCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- */
-int
-bdb_RandCommand(interp, objc, objv)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
-{
- static char *rcmds[] = {
- "rand", "random_int", "srand",
- NULL
- };
- enum rcmds {
- RRAND, RRAND_INT, RSRAND
- };
- long t;
- int cmdindex, hi, lo, result, ret;
- Tcl_Obj *res;
- char msg[MSG_SIZE];
-
- result = TCL_OK;
- /*
- * Get the command name index from the object based on the cmds
- * defined above. This SHOULD NOT fail because we already checked
- * in the 'berkdb' command.
- */
- if (Tcl_GetIndexFromObj(interp,
- objv[1], rcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
- return (IS_HELP(objv[1]));
-
- res = NULL;
- switch ((enum rcmds)cmdindex) {
- case RRAND:
- /*
- * Must be 0 args. Error if different.
- */
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return (TCL_ERROR);
- }
- ret = rand();
- res = Tcl_NewIntObj(ret);
- break;
- case RRAND_INT:
- /*
- * Must be 4 args. Error if different.
- */
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "lo hi");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &lo);
- if (result != TCL_OK)
- break;
- result = Tcl_GetIntFromObj(interp, objv[3], &hi);
- if (result == TCL_OK) {
-#ifndef RAND_MAX
-#define RAND_MAX 0x7fffffff
-#endif
- t = rand();
- if (t > RAND_MAX) {
- snprintf(msg, MSG_SIZE,
- "Max random is higher than %ld\n",
- (long)RAND_MAX);
- Tcl_SetResult(interp, msg, TCL_VOLATILE);
- result = TCL_ERROR;
- break;
- }
- _debug_check();
- ret = (int)(((double)t / ((double)(RAND_MAX) + 1)) *
- (hi - lo + 1));
- ret += lo;
- res = Tcl_NewIntObj(ret);
- }
- break;
- case RSRAND:
- /*
- * Must be 1 arg. Error if different.
- */
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "seed");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &lo);
- if (result == TCL_OK) {
- srand((u_int)lo);
- res = Tcl_NewIntObj(0);
- }
- break;
- }
- /*
- * Only set result if we have a res. Otherwise, lower
- * functions have already done so.
- */
- if (result == TCL_OK && res)
- Tcl_SetObjResult(interp, res);
- return (result);
-}
-
-/*
- *
- * tcl_Mutex --
- * Opens an env mutex.
- *
- * PUBLIC: int tcl_Mutex __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *,
- * PUBLIC: DBTCL_INFO *));
- */
-int
-tcl_Mutex(interp, objc, objv, envp, envip)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
- DB_ENV *envp; /* Environment pointer */
- DBTCL_INFO *envip; /* Info pointer */
-{
- DBTCL_INFO *ip;
- Tcl_Obj *res;
- _MUTEX_DATA *md;
- int i, mode, nitems, result, ret;
- char newname[MSG_SIZE];
-
- md = NULL;
- result = TCL_OK;
- mode = nitems = ret = 0;
- memset(newname, 0, MSG_SIZE);
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "mode nitems");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &mode);
- if (result != TCL_OK)
- return (TCL_ERROR);
- result = Tcl_GetIntFromObj(interp, objv[3], &nitems);
- if (result != TCL_OK)
- return (TCL_ERROR);
-
- snprintf(newname, sizeof(newname),
- "%s.mutex%d", envip->i_name, envip->i_envmutexid);
- ip = _NewInfo(interp, NULL, newname, I_MUTEX);
- if (ip == NULL) {
- Tcl_SetResult(interp, "Could not set up info",
- TCL_STATIC);
- return (TCL_ERROR);
- }
- /*
- * Set up mutex.
- */
- /*
- * Map in the region.
- *
- * XXX
- * We don't bother doing this "right", i.e., using the shalloc
- * functions, just grab some memory knowing that it's correctly
- * aligned.
- */
- _debug_check();
- if (__os_calloc(NULL, 1, sizeof(_MUTEX_DATA), &md) != 0)
- goto posixout;
- md->env = envp;
- md->n_mutex = nitems;
- md->size = sizeof(_MUTEX_ENTRY) * nitems;
-
- md->reginfo.type = REGION_TYPE_MUTEX;
- md->reginfo.id = INVALID_REGION_TYPE;
- md->reginfo.mode = mode;
- md->reginfo.flags = REGION_CREATE_OK | REGION_JOIN_OK;
- if ((ret = __db_r_attach(envp, &md->reginfo, md->size)) != 0)
- goto posixout;
- md->marray = md->reginfo.addr;
-
- /* Initialize a created region. */
- if (F_ISSET(&md->reginfo, REGION_CREATE))
- for (i = 0; i < nitems; i++) {
- md->marray[i].val = 0;
- if ((ret =
- __db_mutex_init(envp, &md->marray[i].m, i, 0)) != 0)
- goto posixout;
- }
- R_UNLOCK(envp, &md->reginfo);
-
- /*
- * Success. Set up return. Set up new info
- * and command widget for this mutex.
- */
- envip->i_envmutexid++;
- ip->i_parent = envip;
- _SetInfoData(ip, md);
- Tcl_CreateObjCommand(interp, newname,
- (Tcl_ObjCmdProc *)mutex_Cmd, (ClientData)md, NULL);
- res = Tcl_NewStringObj(newname, strlen(newname));
- Tcl_SetObjResult(interp, res);
-
- return (TCL_OK);
-
-posixout:
- if (ret > 0)
- Tcl_PosixError(interp);
- result = _ReturnSetup(interp, ret, "mutex");
- _DeleteInfo(ip);
-
- if (md != NULL) {
- if (md->reginfo.addr != NULL)
- (void)__db_r_detach(md->env,
- &md->reginfo, F_ISSET(&md->reginfo, REGION_CREATE));
- __os_free(md, sizeof(*md));
- }
- return (result);
-}
-
-/*
- * mutex_Cmd --
- * Implements the "mutex" widget.
- */
-static int
-mutex_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Mutex handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
-{
- static char *mxcmds[] = {
- "close",
- "get",
- "getval",
- "release",
- "setval",
- NULL
- };
- enum mxcmds {
- MXCLOSE,
- MXGET,
- MXGETVAL,
- MXRELE,
- MXSETVAL
- };
- DB_ENV *dbenv;
- DBTCL_INFO *envip, *mpip;
- _MUTEX_DATA *mp;
- Tcl_Obj *res;
- int cmdindex, id, result, newval;
-
- Tcl_ResetResult(interp);
- mp = (_MUTEX_DATA *)clientData;
- mpip = _PtrToInfo((void *)mp);
- envip = mpip->i_parent;
- dbenv = envip->i_envp;
- result = TCL_OK;
-
- if (mp == NULL) {
- Tcl_SetResult(interp, "NULL mp pointer", TCL_STATIC);
- return (TCL_ERROR);
- }
- if (mpip == NULL) {
- Tcl_SetResult(interp, "NULL mp info pointer", TCL_STATIC);
- return (TCL_ERROR);
- }
-
- /*
- * Get the command name index from the object based on the dbcmds
- * defined above.
- */
- if (Tcl_GetIndexFromObj(interp,
- objv[1], mxcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
- return (IS_HELP(objv[1]));
-
- res = NULL;
- switch ((enum mxcmds)cmdindex) {
- case MXCLOSE:
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, NULL);
- return (TCL_ERROR);
- }
- _debug_check();
- (void)__db_r_detach(mp->env, &mp->reginfo, 0);
- res = Tcl_NewIntObj(0);
- (void)Tcl_DeleteCommand(interp, mpip->i_name);
- _DeleteInfo(mpip);
- __os_free(mp, sizeof(*mp));
- break;
- case MXRELE:
- /*
- * Check for 1 arg. Error if different.
- */
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "id");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &id);
- if (result != TCL_OK)
- break;
- MUTEX_UNLOCK(dbenv, &mp->marray[id].m);
- res = Tcl_NewIntObj(0);
- break;
- case MXGET:
- /*
- * Check for 1 arg. Error if different.
- */
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "id");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &id);
- if (result != TCL_OK)
- break;
- MUTEX_LOCK(dbenv, &mp->marray[id].m, mp->env->lockfhp);
- res = Tcl_NewIntObj(0);
- break;
- case MXGETVAL:
- /*
- * Check for 1 arg. Error if different.
- */
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "id");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &id);
- if (result != TCL_OK)
- break;
- res = Tcl_NewIntObj(mp->marray[id].val);
- break;
- case MXSETVAL:
- /*
- * Check for 2 args. Error if different.
- */
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "id val");
- return (TCL_ERROR);
- }
- result = Tcl_GetIntFromObj(interp, objv[2], &id);
- if (result != TCL_OK)
- break;
- result = Tcl_GetIntFromObj(interp, objv[3], &newval);
- if (result != TCL_OK)
- break;
- mp->marray[id].val = newval;
- res = Tcl_NewIntObj(0);
- break;
- }
- /*
- * Only set result if we have a res. Otherwise, lower
- * functions have already done so.
- */
- if (result == TCL_OK && res)
- Tcl_SetObjResult(interp, res);
- return (result);
-}
+#endif /* CONFIG_TEST */
diff --git a/bdb/tcl/tcl_db.c b/bdb/tcl/tcl_db.c
index 8e7215a272a..7df2e48311c 100644
--- a/bdb/tcl/tcl_db.c
+++ b/bdb/tcl/tcl_db.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_db.c,v 11.55 2000/11/28 20:12:31 bostic Exp $";
+static const char revid[] = "$Id: tcl_db.c,v 11.107 2002/08/06 06:20:31 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,24 +20,61 @@ static const char revid[] = "$Id: tcl_db.c,v 11.55 2000/11/28 20:12:31 bostic Ex
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/tcl_db.h"
/*
* Prototypes for procedures defined later in this file:
*/
+static int tcl_DbAssociate __P((Tcl_Interp *,
+ int, Tcl_Obj * CONST*, DB *));
static int tcl_DbClose __P((Tcl_Interp *,
int, Tcl_Obj * CONST*, DB *, DBTCL_INFO *));
static int tcl_DbDelete __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
-static int tcl_DbGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
+static int tcl_DbGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *, int));
static int tcl_DbKeyRange __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
static int tcl_DbPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
static int tcl_DbStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
+static int tcl_DbTruncate __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
static int tcl_DbCursor __P((Tcl_Interp *,
int, Tcl_Obj * CONST*, DB *, DBC **));
static int tcl_DbJoin __P((Tcl_Interp *,
int, Tcl_Obj * CONST*, DB *, DBC **));
static int tcl_DbGetjoin __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
static int tcl_DbCount __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
+static int tcl_second_call __P((DB *, const DBT *, const DBT *, DBT *));
+
+/*
+ * _DbInfoDelete --
+ *
+ * PUBLIC: void _DbInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
+ */
+void
+_DbInfoDelete(interp, dbip)
+ Tcl_Interp *interp;
+ DBTCL_INFO *dbip;
+{
+ DBTCL_INFO *nextp, *p;
+ /*
+ * First we have to close any open cursors. Then we close
+ * our db.
+ */
+ for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
+ nextp = LIST_NEXT(p, entries);
+ /*
+ * Check if this is a cursor info structure and if
+ * it is, if it belongs to this DB. If so, remove
+ * its commands and info structure.
+ */
+ if (p->i_parent == dbip && p->i_type == I_DBC) {
+ (void)Tcl_DeleteCommand(interp, p->i_name);
+ _DeleteInfo(p);
+ }
+ }
+ (void)Tcl_DeleteCommand(interp, dbip->i_name);
+ _DeleteInfo(dbip);
+}
/*
*
@@ -54,6 +91,13 @@ db_Cmd(clientData, interp, objc, objv)
Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *dbcmds[] = {
+#if CONFIG_TEST
+ "keyrange",
+ "pget",
+ "rpcid",
+ "test",
+#endif
+ "associate",
"close",
"count",
"cursor",
@@ -63,16 +107,20 @@ db_Cmd(clientData, interp, objc, objv)
"get_type",
"is_byteswapped",
"join",
- "keyrange",
"put",
"stat",
"sync",
-#if CONFIG_TEST
- "test",
-#endif
+ "truncate",
NULL
};
enum dbcmds {
+#if CONFIG_TEST
+ DBKEYRANGE,
+ DBPGET,
+ DBRPCID,
+ DBTEST,
+#endif
+ DBASSOCIATE,
DBCLOSE,
DBCOUNT,
DBCURSOR,
@@ -82,20 +130,18 @@ db_Cmd(clientData, interp, objc, objv)
DBGETTYPE,
DBSWAPPED,
DBJOIN,
- DBKEYRANGE,
DBPUT,
DBSTAT,
- DBSYNC
-#if CONFIG_TEST
- , DBTEST
-#endif
+ DBSYNC,
+ DBTRUNCATE
};
DB *dbp;
DBC *dbc;
DBTCL_INFO *dbip;
DBTCL_INFO *ip;
+ DBTYPE type;
Tcl_Obj *res;
- int cmdindex, result, ret;
+ int cmdindex, isswapped, result, ret;
char newname[MSG_SIZE];
Tcl_ResetResult(interp);
@@ -126,6 +172,34 @@ db_Cmd(clientData, interp, objc, objv)
res = NULL;
switch ((enum dbcmds)cmdindex) {
+#if CONFIG_TEST
+ case DBKEYRANGE:
+ result = tcl_DbKeyRange(interp, objc, objv, dbp);
+ break;
+ case DBPGET:
+ result = tcl_DbGet(interp, objc, objv, dbp, 1);
+ break;
+ case DBRPCID:
+ /*
+ * No args for this. Error if there are some.
+ */
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ /*
+ * !!! Retrieve the client ID from the dbp handle directly.
+ * This is for testing purposes only. It is dbp-private data.
+ */
+ res = Tcl_NewLongObj(dbp->cl_id);
+ break;
+ case DBTEST:
+ result = tcl_EnvTest(interp, objc, objv, dbp->dbenv);
+ break;
+#endif
+ case DBASSOCIATE:
+ result = tcl_DbAssociate(interp, objc, objv, dbp);
+ break;
case DBCLOSE:
result = tcl_DbClose(interp, objc, objv, dbp, dbip);
break;
@@ -133,10 +207,7 @@ db_Cmd(clientData, interp, objc, objv)
result = tcl_DbDelete(interp, objc, objv, dbp);
break;
case DBGET:
- result = tcl_DbGet(interp, objc, objv, dbp);
- break;
- case DBKEYRANGE:
- result = tcl_DbKeyRange(interp, objc, objv, dbp);
+ result = tcl_DbGet(interp, objc, objv, dbp, 0);
break;
case DBPUT:
result = tcl_DbPut(interp, objc, objv, dbp);
@@ -153,8 +224,8 @@ db_Cmd(clientData, interp, objc, objv)
return (TCL_ERROR);
}
_debug_check();
- ret = dbp->get_byteswapped(dbp);
- res = Tcl_NewIntObj(ret);
+ ret = dbp->get_byteswapped(dbp, &isswapped);
+ res = Tcl_NewIntObj(isswapped);
break;
case DBGETTYPE:
/*
@@ -165,14 +236,14 @@ db_Cmd(clientData, interp, objc, objv)
return (TCL_ERROR);
}
_debug_check();
- ret = dbp->get_type(dbp);
- if (ret == DB_BTREE)
+ ret = dbp->get_type(dbp, &type);
+ if (type == DB_BTREE)
res = Tcl_NewStringObj("btree", strlen("btree"));
- else if (ret == DB_HASH)
+ else if (type == DB_HASH)
res = Tcl_NewStringObj("hash", strlen("hash"));
- else if (ret == DB_RECNO)
+ else if (type == DB_RECNO)
res = Tcl_NewStringObj("recno", strlen("recno"));
- else if (ret == DB_QUEUE)
+ else if (type == DB_QUEUE)
res = Tcl_NewStringObj("queue", strlen("queue"));
else {
Tcl_SetResult(interp,
@@ -248,11 +319,9 @@ db_Cmd(clientData, interp, objc, objv)
case DBGETJOIN:
result = tcl_DbGetjoin(interp, objc, objv, dbp);
break;
-#if CONFIG_TEST
- case DBTEST:
- result = tcl_EnvTest(interp, objc, objv, dbp->dbenv);
+ case DBTRUNCATE:
+ result = tcl_DbTruncate(interp, objc, objv, dbp);
break;
-#endif
}
/*
* Only set result if we have a res. Otherwise, lower
@@ -277,7 +346,7 @@ tcl_DbStat(interp, objc, objv, dbp)
DB_HASH_STAT *hsp;
DB_QUEUE_STAT *qsp;
void *sp;
- Tcl_Obj *res;
+ Tcl_Obj *res, *flaglist, *myobjv[2];
DBTYPE type;
u_int32_t flag;
int result, ret;
@@ -287,16 +356,14 @@ tcl_DbStat(interp, objc, objv, dbp)
flag = 0;
if (objc > 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-recordcount?");
+ Tcl_WrongNumArgs(interp, 2, objv, "?-faststat?");
return (TCL_ERROR);
}
if (objc == 3) {
arg = Tcl_GetStringFromObj(objv[2], NULL);
- if (strcmp(arg, "-recordcount") == 0)
- flag = DB_RECORDCOUNT;
- else if (strcmp(arg, "-cachedcounts") == 0)
- flag = DB_CACHED_COUNTS;
+ if (strcmp(arg, "-faststat") == 0)
+ flag = DB_FAST_STAT;
else {
Tcl_SetResult(interp,
"db stat: unknown arg", TCL_STATIC);
@@ -305,17 +372,18 @@ tcl_DbStat(interp, objc, objv, dbp)
}
_debug_check();
- ret = dbp->stat(dbp, &sp, NULL, flag);
- result = _ReturnSetup(interp, ret, "db stat");
+ ret = dbp->stat(dbp, &sp, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db stat");
if (result == TCL_ERROR)
return (result);
- type = dbp->get_type(dbp);
+ (void)dbp->get_type(dbp, &type);
/*
* Have our stats, now construct the name value
* list pairs and free up the memory.
*/
res = Tcl_NewObj();
+
/*
* MAKE_STAT_LIST assumes 'res' and 'error' label.
*/
@@ -326,42 +394,48 @@ tcl_DbStat(interp, objc, objv, dbp)
MAKE_STAT_LIST("Page size", hsp->hash_pagesize);
MAKE_STAT_LIST("Number of keys", hsp->hash_nkeys);
MAKE_STAT_LIST("Number of records", hsp->hash_ndata);
- MAKE_STAT_LIST("Estim. number of elements", hsp->hash_nelem);
MAKE_STAT_LIST("Fill factor", hsp->hash_ffactor);
MAKE_STAT_LIST("Buckets", hsp->hash_buckets);
- MAKE_STAT_LIST("Free pages", hsp->hash_free);
- MAKE_STAT_LIST("Bytes free", hsp->hash_bfree);
- MAKE_STAT_LIST("Number of big pages", hsp->hash_bigpages);
- MAKE_STAT_LIST("Big pages bytes free", hsp->hash_big_bfree);
- MAKE_STAT_LIST("Overflow pages", hsp->hash_overflows);
- MAKE_STAT_LIST("Overflow bytes free", hsp->hash_ovfl_free);
- MAKE_STAT_LIST("Duplicate pages", hsp->hash_dup);
- MAKE_STAT_LIST("Duplicate pages bytes free",
- hsp->hash_dup_free);
+ if (flag != DB_FAST_STAT) {
+ MAKE_STAT_LIST("Free pages", hsp->hash_free);
+ MAKE_STAT_LIST("Bytes free", hsp->hash_bfree);
+ MAKE_STAT_LIST("Number of big pages",
+ hsp->hash_bigpages);
+ MAKE_STAT_LIST("Big pages bytes free",
+ hsp->hash_big_bfree);
+ MAKE_STAT_LIST("Overflow pages", hsp->hash_overflows);
+ MAKE_STAT_LIST("Overflow bytes free",
+ hsp->hash_ovfl_free);
+ MAKE_STAT_LIST("Duplicate pages", hsp->hash_dup);
+ MAKE_STAT_LIST("Duplicate pages bytes free",
+ hsp->hash_dup_free);
+ }
} else if (type == DB_QUEUE) {
qsp = (DB_QUEUE_STAT *)sp;
MAKE_STAT_LIST("Magic", qsp->qs_magic);
MAKE_STAT_LIST("Version", qsp->qs_version);
MAKE_STAT_LIST("Page size", qsp->qs_pagesize);
- MAKE_STAT_LIST("Number of records", qsp->qs_ndata);
- MAKE_STAT_LIST("Number of pages", qsp->qs_pages);
- MAKE_STAT_LIST("Bytes free", qsp->qs_pgfree);
+ MAKE_STAT_LIST("Extent size", qsp->qs_extentsize);
+ MAKE_STAT_LIST("Number of records", qsp->qs_nkeys);
MAKE_STAT_LIST("Record length", qsp->qs_re_len);
MAKE_STAT_LIST("Record pad", qsp->qs_re_pad);
MAKE_STAT_LIST("First record number", qsp->qs_first_recno);
MAKE_STAT_LIST("Last record number", qsp->qs_cur_recno);
+ if (flag != DB_FAST_STAT) {
+ MAKE_STAT_LIST("Number of pages", qsp->qs_pages);
+ MAKE_STAT_LIST("Bytes free", qsp->qs_pgfree);
+ }
} else { /* BTREE and RECNO are same stats */
bsp = (DB_BTREE_STAT *)sp;
+ MAKE_STAT_LIST("Magic", bsp->bt_magic);
+ MAKE_STAT_LIST("Version", bsp->bt_version);
MAKE_STAT_LIST("Number of keys", bsp->bt_nkeys);
MAKE_STAT_LIST("Number of records", bsp->bt_ndata);
- if (flag != DB_RECORDCOUNT) {
- MAKE_STAT_LIST("Magic", bsp->bt_magic);
- MAKE_STAT_LIST("Version", bsp->bt_version);
- MAKE_STAT_LIST("Flags", bsp->bt_metaflags);
- MAKE_STAT_LIST("Minimum keys per page", bsp->bt_minkey);
- MAKE_STAT_LIST("Fixed record length", bsp->bt_re_len);
- MAKE_STAT_LIST("Record pad", bsp->bt_re_pad);
- MAKE_STAT_LIST("Page size", bsp->bt_pagesize);
+ MAKE_STAT_LIST("Minimum keys per page", bsp->bt_minkey);
+ MAKE_STAT_LIST("Fixed record length", bsp->bt_re_len);
+ MAKE_STAT_LIST("Record pad", bsp->bt_re_pad);
+ MAKE_STAT_LIST("Page size", bsp->bt_pagesize);
+ if (flag != DB_FAST_STAT) {
MAKE_STAT_LIST("Levels", bsp->bt_levels);
MAKE_STAT_LIST("Internal pages", bsp->bt_int_pg);
MAKE_STAT_LIST("Leaf pages", bsp->bt_leaf_pg);
@@ -378,9 +452,27 @@ tcl_DbStat(interp, objc, objv, dbp)
bsp->bt_over_pgfree);
}
}
+
+ /*
+ * Construct a {name {flag1 flag2 ... flagN}} list for the
+ * dbp flags. These aren't access-method dependent, but they
+ * include all the interesting flags, and the integer value
+ * isn't useful from Tcl--return the strings instead.
+ */
+ myobjv[0] = Tcl_NewStringObj("Flags", strlen("Flags"));
+ myobjv[1] = _GetFlagsList(interp, dbp->flags, __db_inmemdbflags);
+ flaglist = Tcl_NewListObj(2, myobjv);
+ if (flaglist == NULL) {
+ result = TCL_ERROR;
+ goto error;
+ }
+ if ((result =
+ Tcl_ListObjAppendElement(interp, res, flaglist)) != TCL_OK)
+ goto error;
+
Tcl_SetObjResult(interp, res);
error:
- __os_free(sp, 0);
+ free(sp);
return (result);
}
@@ -395,50 +487,62 @@ tcl_DbClose(interp, objc, objv, dbp, dbip)
DB *dbp; /* Database pointer */
DBTCL_INFO *dbip; /* Info pointer */
{
- DBTCL_INFO *p, *nextp;
+ static char *dbclose[] = {
+ "-nosync", "--", NULL
+ };
+ enum dbclose {
+ TCL_DBCLOSE_NOSYNC,
+ TCL_DBCLOSE_ENDARG
+ };
u_int32_t flag;
- int result, ret;
+ int endarg, i, optindex, result, ret;
char *arg;
result = TCL_OK;
+ endarg = 0;
flag = 0;
- if (objc > 3) {
+ if (objc > 4) {
Tcl_WrongNumArgs(interp, 2, objv, "?-nosync?");
return (TCL_ERROR);
}
- if (objc == 3) {
- arg = Tcl_GetStringFromObj(objv[2], NULL);
- if (strcmp(arg, "-nosync") == 0)
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], dbclose,
+ "option", TCL_EXACT, &optindex) != TCL_OK) {
+ arg = Tcl_GetStringFromObj(objv[i], NULL);
+ if (arg[0] == '-')
+ return (IS_HELP(objv[i]));
+ else
+ Tcl_ResetResult(interp);
+ break;
+ }
+ i++;
+ switch ((enum dbclose)optindex) {
+ case TCL_DBCLOSE_NOSYNC:
flag = DB_NOSYNC;
- else {
- Tcl_SetResult(interp,
- "dbclose: unknown arg", TCL_STATIC);
- return (TCL_ERROR);
+ break;
+ case TCL_DBCLOSE_ENDARG:
+ endarg = 1;
+ break;
}
- }
-
- /*
- * First we have to close any open cursors. Then we close
- * our db.
- */
- for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
- nextp = LIST_NEXT(p, entries);
/*
- * Check if this is a cursor info structure and if
- * it is, if it belongs to this DB. If so, remove
- * its commands and info structure.
+ * If, at any time, parsing the args we get an error,
+ * bail out and return.
*/
- if (p->i_parent == dbip && p->i_type == I_DBC) {
- (void)Tcl_DeleteCommand(interp, p->i_name);
- _DeleteInfo(p);
- }
+ if (result != TCL_OK)
+ return (result);
+ if (endarg)
+ break;
}
- (void)Tcl_DeleteCommand(interp, dbip->i_name);
- _DeleteInfo(dbip);
+ _DbInfoDelete(interp, dbip);
_debug_check();
+
+ /* Paranoia. */
+ dbp->api_internal = NULL;
+
ret = (dbp)->close(dbp, flag);
- result = _ReturnSetup(interp, ret, "db close");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db close");
return (result);
}
@@ -453,16 +557,22 @@ tcl_DbPut(interp, objc, objv, dbp)
DB *dbp; /* Database pointer */
{
static char *dbputopts[] = {
- "-append",
+#if CONFIG_TEST
"-nodupdata",
+#endif
+ "-append",
+ "-auto_commit",
"-nooverwrite",
"-partial",
"-txn",
NULL
};
enum dbputopts {
- DBPUT_APPEND,
+#if CONFIG_TEST
DBGET_NODUPDATA,
+#endif
+ DBPUT_APPEND,
+ DBPUT_AUTO_COMMIT,
DBPUT_NOOVER,
DBPUT_PART,
DBPUT_TXN
@@ -475,9 +585,11 @@ tcl_DbPut(interp, objc, objv, dbp)
DBTYPE type;
DB_TXN *txn;
Tcl_Obj **elemv, *res;
+ void *dtmp, *ktmp;
db_recno_t recno;
u_int32_t flag;
- int elemc, end, i, itmp, optindex, result, ret;
+ int auto_commit, elemc, end, freekey, freedata;
+ int i, optindex, result, ret;
char *arg, msg[MSG_SIZE];
txn = NULL;
@@ -488,6 +600,7 @@ tcl_DbPut(interp, objc, objv, dbp)
return (TCL_ERROR);
}
+ freekey = freedata = 0;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
@@ -496,7 +609,7 @@ tcl_DbPut(interp, objc, objv, dbp)
* and must be setup up to contain a db_recno_t. Otherwise the
* key is a "string".
*/
- type = dbp->get_type(dbp);
+ (void)dbp->get_type(dbp, &type);
/*
* We need to determine where the end of required args are. If we
@@ -527,12 +640,19 @@ tcl_DbPut(interp, objc, objv, dbp)
* defined above.
*/
i = 2;
+ auto_commit = 0;
while (i < end) {
if (Tcl_GetIndexFromObj(interp, objv[i],
dbputopts, "option", TCL_EXACT, &optindex) != TCL_OK)
return (IS_HELP(objv[i]));
i++;
switch ((enum dbputopts)optindex) {
+#if CONFIG_TEST
+ case DBGET_NODUPDATA:
+ FLAG_CHECK(flag);
+ flag = DB_NODUPDATA;
+ break;
+#endif
case DBPUT_TXN:
if (i > (end - 1)) {
Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
@@ -548,14 +668,13 @@ tcl_DbPut(interp, objc, objv, dbp)
result = TCL_ERROR;
}
break;
+ case DBPUT_AUTO_COMMIT:
+ auto_commit = 1;
+ break;
case DBPUT_APPEND:
FLAG_CHECK(flag);
flag = DB_APPEND;
break;
- case DBGET_NODUPDATA:
- FLAG_CHECK(flag);
- flag = DB_NODUPDATA;
- break;
case DBPUT_NOOVER:
FLAG_CHECK(flag);
flag = DB_NOOVERWRITE;
@@ -579,12 +698,10 @@ tcl_DbPut(interp, objc, objv, dbp)
break;
}
data.flags = DB_DBT_PARTIAL;
- result = Tcl_GetIntFromObj(interp, elemv[0], &itmp);
- data.doff = itmp;
+ result = _GetUInt32(interp, elemv[0], &data.doff);
if (result != TCL_OK)
break;
- result = Tcl_GetIntFromObj(interp, elemv[1], &itmp);
- data.dlen = itmp;
+ result = _GetUInt32(interp, elemv[1], &data.dlen);
/*
* NOTE: We don't check result here because all we'd
* do is break anyway, and we are doing that. If you
@@ -597,6 +714,8 @@ tcl_DbPut(interp, objc, objv, dbp)
if (result != TCL_OK)
break;
}
+ if (auto_commit)
+ flag |= DB_AUTO_COMMIT;
if (result == TCL_ERROR)
return (result);
@@ -612,40 +731,41 @@ tcl_DbPut(interp, objc, objv, dbp)
if (flag == DB_APPEND)
recno = 0;
else {
- result = Tcl_GetIntFromObj(interp, objv[objc-2], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp, objv[objc-2], &recno);
if (result != TCL_OK)
return (result);
}
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[objc-2], &itmp);
- key.size = itmp;
+ ret = _CopyObjBytes(interp, objv[objc-2], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBPUT(ret), "db put");
+ return (result);
+ }
+ key.data = ktmp;
}
- /*
- * XXX
- * Tcl 8.1 Tcl_GetByteArrayFromObj/Tcl_GetIntFromObj bug.
- *
- * This line (and the line for key.data above) were moved from
- * the beginning of the function to here.
- *
- * There is a bug in Tcl 8.1 and byte arrays in that if it happens
- * to use an object as both a byte array and something else like
- * an int, and you've done a Tcl_GetByteArrayFromObj, then you
- * do a Tcl_GetIntFromObj, your memory is deleted.
- *
- * Workaround is to make sure all Tcl_GetByteArrayFromObj calls
- * are done last.
- */
- data.data = Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- data.size = itmp;
+ ret = _CopyObjBytes(interp, objv[objc-1], &dtmp,
+ &data.size, &freedata);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBPUT(ret), "db put");
+ goto out;
+ }
+ data.data = dtmp;
_debug_check();
ret = dbp->put(dbp, txn, &key, &data, flag);
- result = _ReturnSetup(interp, ret, "db put");
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBPUT(ret), "db put");
if (ret == 0 &&
(type == DB_RECNO || type == DB_QUEUE) && flag == DB_APPEND) {
- res = Tcl_NewIntObj(recno);
+ res = Tcl_NewLongObj((long)recno);
Tcl_SetObjResult(interp, res);
}
+out:
+ if (freedata)
+ (void)__os_free(dbp->dbenv, dtmp);
+ if (freekey)
+ (void)__os_free(dbp->dbenv, ktmp);
return (result);
}
@@ -653,13 +773,18 @@ tcl_DbPut(interp, objc, objv, dbp)
* tcl_db_get --
*/
static int
-tcl_DbGet(interp, objc, objv, dbp)
+tcl_DbGet(interp, objc, objv, dbp, ispget)
Tcl_Interp *interp; /* Interpreter */
int objc; /* How many arguments? */
Tcl_Obj *CONST objv[]; /* The argument objects */
DB *dbp; /* Database pointer */
+ int ispget; /* 1 for pget, 0 for get */
{
static char *dbgetopts[] = {
+#if CONFIG_TEST
+ "-dirty",
+ "-multi",
+#endif
"-consume",
"-consume_wait",
"-get_both",
@@ -668,9 +793,14 @@ tcl_DbGet(interp, objc, objv, dbp)
"-recno",
"-rmw",
"-txn",
+ "--",
NULL
};
enum dbgetopts {
+#if CONFIG_TEST
+ DBGET_DIRTY,
+ DBGET_MULTI,
+#endif
DBGET_CONSUME,
DBGET_CONSUME_WAIT,
DBGET_BOTH,
@@ -678,21 +808,25 @@ tcl_DbGet(interp, objc, objv, dbp)
DBGET_PART,
DBGET_RECNO,
DBGET_RMW,
- DBGET_TXN
+ DBGET_TXN,
+ DBGET_ENDARG
};
DBC *dbc;
- DBT key, data, save;
+ DBT key, pkey, data, save;
DBTYPE type;
DB_TXN *txn;
Tcl_Obj **elemv, *retlist;
- db_recno_t recno;
- u_int32_t flag, cflag, isdup, rmw;
- int elemc, end, i, itmp, optindex, result, ret, useglob, userecno;
+ void *dtmp, *ktmp;
+ u_int32_t flag, cflag, isdup, mflag, rmw;
+ int bufsize, elemc, end, endarg, freekey, freedata, i;
+ int optindex, result, ret, useglob, useprecno, userecno;
char *arg, *pattern, *prefix, msg[MSG_SIZE];
+ db_recno_t precno, recno;
result = TCL_OK;
- cflag = flag = rmw = 0;
- useglob = userecno = 0;
+ freekey = freedata = 0;
+ cflag = endarg = flag = mflag = rmw = 0;
+ useglob = userecno = useprecno = 0;
txn = NULL;
pattern = prefix = NULL;
@@ -705,23 +839,41 @@ tcl_DbGet(interp, objc, objv, dbp)
memset(&data, 0, sizeof(data));
memset(&save, 0, sizeof(save));
+ /* For the primary key in a pget call. */
+ memset(&pkey, 0, sizeof(pkey));
+
/*
* Get the command name index from the object based on the options
* defined above.
*/
i = 2;
- type = dbp->get_type(dbp);
+ (void)dbp->get_type(dbp, &type);
end = objc;
while (i < end) {
if (Tcl_GetIndexFromObj(interp, objv[i], dbgetopts, "option",
TCL_EXACT, &optindex) != TCL_OK) {
- if (IS_HELP(objv[i]) == TCL_OK)
- return (TCL_OK);
- Tcl_ResetResult(interp);
+ arg = Tcl_GetStringFromObj(objv[i], NULL);
+ if (arg[0] == '-') {
+ result = IS_HELP(objv[i]);
+ goto out;
+ } else
+ Tcl_ResetResult(interp);
break;
}
i++;
switch ((enum dbgetopts)optindex) {
+#if CONFIG_TEST
+ case DBGET_DIRTY:
+ rmw |= DB_DIRTY_READ;
+ break;
+ case DBGET_MULTI:
+ mflag |= DB_MULTIPLE;
+ result = Tcl_GetIntFromObj(interp, objv[i], &bufsize);
+ if (result != TCL_OK)
+ goto out;
+ i++;
+ break;
+#endif
case DBGET_BOTH:
/*
* Change 'end' and make sure we aren't already past
@@ -738,7 +890,7 @@ tcl_DbGet(interp, objc, objv, dbp)
flag = DB_GET_BOTH;
break;
case DBGET_TXN:
- if (i == end - 1) {
+ if (i >= end) {
Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
result = TCL_ERROR;
break;
@@ -773,7 +925,7 @@ tcl_DbGet(interp, objc, objv, dbp)
}
break;
case DBGET_RMW:
- rmw = DB_RMW;
+ rmw |= DB_RMW;
break;
case DBGET_PART:
end = objc - 1;
@@ -795,12 +947,10 @@ tcl_DbGet(interp, objc, objv, dbp)
break;
}
save.flags = DB_DBT_PARTIAL;
- result = Tcl_GetIntFromObj(interp, elemv[0], &itmp);
- save.doff = itmp;
+ result = _GetUInt32(interp, elemv[0], &save.doff);
if (result != TCL_OK)
break;
- result = Tcl_GetIntFromObj(interp, elemv[1], &itmp);
- save.dlen = itmp;
+ result = _GetUInt32(interp, elemv[1], &save.dlen);
/*
* NOTE: We don't check result here because all we'd
* do is break anyway, and we are doing that. If you
@@ -809,15 +959,54 @@ tcl_DbGet(interp, objc, objv, dbp)
* lines above and copy that.)
*/
break;
- }
+ case DBGET_ENDARG:
+ endarg = 1;
+ break;
+ } /* switch */
if (result != TCL_OK)
break;
+ if (endarg)
+ break;
}
if (result != TCL_OK)
goto out;
if (type == DB_RECNO || type == DB_QUEUE)
userecno = 1;
+
+ /*
+ * Check args we have left versus the flags we were given.
+ * We might have 0, 1 or 2 left. If we have 0, it must
+ * be DB_CONSUME*, if 2, then DB_GET_BOTH, all others should
+ * be 1.
+ */
+ if (((flag == DB_CONSUME || flag == DB_CONSUME_WAIT) && i != objc) ||
+ (flag == DB_GET_BOTH && i != objc - 2)) {
+ Tcl_SetResult(interp,
+ "Wrong number of key/data given based on flags specified\n",
+ TCL_STATIC);
+ result = TCL_ERROR;
+ goto out;
+ } else if (flag == 0 && i != objc - 1) {
+ Tcl_SetResult(interp,
+ "Wrong number of key/data given\n", TCL_STATIC);
+ result = TCL_ERROR;
+ goto out;
+ }
+
+ /*
+ * XXX
+ * We technically shouldn't be looking inside the dbp like this,
+ * but this is the only way to figure out whether the primary
+ * key should also be a recno.
+ */
+ if (ispget) {
+ if (dbp->s_primary != NULL &&
+ (dbp->s_primary->type == DB_RECNO ||
+ dbp->s_primary->type == DB_QUEUE))
+ useprecno = 1;
+ }
+
/*
* Check for illegal combos of options.
*/
@@ -862,93 +1051,189 @@ tcl_DbGet(interp, objc, objv, dbp)
* ops that don't require returning multiple items, use DB->get
* instead of a cursor operation.
*/
- if (pattern == NULL && (isdup == 0 ||
+ if (pattern == NULL && (isdup == 0 || mflag != 0 ||
flag == DB_SET_RECNO || flag == DB_GET_BOTH ||
flag == DB_CONSUME || flag == DB_CONSUME_WAIT)) {
if (flag == DB_GET_BOTH) {
if (userecno) {
- result = Tcl_GetIntFromObj(interp,
- objv[(objc - 2)], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp,
+ objv[(objc - 2)], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
- return (result);
+ goto out;
} else {
- key.data =
- Tcl_GetByteArrayFromObj(objv[objc-2],
- &itmp);
- key.size = itmp;
+ /*
+ * Some get calls (SET_*) can change the
+ * key pointers. So, we need to store
+ * the allocated key space in a tmp.
+ */
+ ret = _CopyObjBytes(interp, objv[objc-2],
+ &ktmp, &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBGET(ret), "db get");
+ goto out;
+ }
+ key.data = ktmp;
}
/*
* Already checked args above. Fill in key and save.
* Save is used in the dbp->get call below to fill in
* data.
+ *
+ * If the "data" here is really a primary key--that
+ * is, if we're in a pget--and that primary key
+ * is a recno, treat it appropriately as an int.
*/
- save.data =
- Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- save.size = itmp;
+ if (useprecno) {
+ result = _GetUInt32(interp,
+ objv[objc - 1], &precno);
+ if (result == TCL_OK) {
+ save.data = &precno;
+ save.size = sizeof(db_recno_t);
+ } else
+ goto out;
+ } else {
+ ret = _CopyObjBytes(interp, objv[objc-1],
+ &dtmp, &save.size, &freedata);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBGET(ret), "db get");
+ goto out;
+ }
+ save.data = dtmp;
+ }
} else if (flag != DB_CONSUME && flag != DB_CONSUME_WAIT) {
if (userecno) {
- result = Tcl_GetIntFromObj(
- interp, objv[(objc - 1)], &itmp);
- recno = itmp;
+ result = _GetUInt32(
+ interp, objv[(objc - 1)], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
- return (result);
+ goto out;
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- key.size = itmp;
+ /*
+ * Some get calls (SET_*) can change the
+ * key pointers. So, we need to store
+ * the allocated key space in a tmp.
+ */
+ ret = _CopyObjBytes(interp, objv[objc-1],
+ &ktmp, &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBGET(ret), "db get");
+ goto out;
+ }
+ key.data = ktmp;
+ }
+ if (mflag & DB_MULTIPLE) {
+ if ((ret = __os_malloc(dbp->dbenv,
+ bufsize, &save.data)) != 0) {
+ Tcl_SetResult(interp,
+ db_strerror(ret), TCL_STATIC);
+ goto out;
+ }
+ save.ulen = bufsize;
+ F_CLR(&save, DB_DBT_MALLOC);
+ F_SET(&save, DB_DBT_USERMEM);
}
}
- memset(&data, 0, sizeof(data));
data = save;
- _debug_check();
-
- ret = dbp->get(dbp, txn, &key, &data, flag | rmw);
- result = _ReturnSetup(interp, ret, "db get");
+ if (ispget) {
+ if (flag == DB_GET_BOTH) {
+ pkey.data = save.data;
+ pkey.size = save.size;
+ data.data = NULL;
+ data.size = 0;
+ }
+ F_SET(&pkey, DB_DBT_MALLOC);
+ _debug_check();
+ ret = dbp->pget(dbp,
+ txn, &key, &pkey, &data, flag | rmw);
+ } else {
+ _debug_check();
+ ret = dbp->get(dbp,
+ txn, &key, &data, flag | rmw | mflag);
+ }
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBGET(ret),
+ "db get");
if (ret == 0) {
/*
* Success. Return a list of the form {name value}
* If it was a recno in key.data, we need to convert
* into a string/object representation of that recno.
*/
- if (type == DB_RECNO || type == DB_QUEUE)
- result = _SetListRecnoElem(interp, retlist,
- *(db_recno_t *)key.data, data.data,
- data.size);
- else
- result = _SetListElem(interp, retlist,
- key.data, key.size, data.data, data.size);
- /*
- * Free space from DB_DBT_MALLOC
- */
- __os_free(data.data, data.size);
+ if (mflag & DB_MULTIPLE)
+ result = _SetMultiList(interp,
+ retlist, &key, &data, type, flag);
+ else if (type == DB_RECNO || type == DB_QUEUE)
+ if (ispget)
+ result = _Set3DBTList(interp,
+ retlist, &key, 1, &pkey,
+ useprecno, &data);
+ else
+ result = _SetListRecnoElem(interp,
+ retlist, *(db_recno_t *)key.data,
+ data.data, data.size);
+ else {
+ if (ispget)
+ result = _Set3DBTList(interp,
+ retlist, &key, 0, &pkey,
+ useprecno, &data);
+ else
+ result = _SetListElem(interp, retlist,
+ key.data, key.size,
+ data.data, data.size);
+ }
}
+ /*
+ * Free space from DBT.
+ *
+ * If we set DB_DBT_MALLOC, we need to free the space if
+ * and only if we succeeded (and thus if DB allocated
+ * anything). If DB_DBT_MALLOC is not set, this is a bulk
+ * get buffer, and needs to be freed no matter what.
+ */
+ if (F_ISSET(&data, DB_DBT_MALLOC) && ret == 0)
+ __os_ufree(dbp->dbenv, data.data);
+ else if (!F_ISSET(&data, DB_DBT_MALLOC))
+ __os_free(dbp->dbenv, data.data);
+ if (ispget && ret == 0)
+ __os_ufree(dbp->dbenv, pkey.data);
if (result == TCL_OK)
Tcl_SetObjResult(interp, retlist);
goto out;
}
if (userecno) {
- result = Tcl_GetIntFromObj(interp, objv[(objc - 1)], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp, objv[(objc - 1)], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
- return (result);
+ goto out;
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- key.size = itmp;
+ /*
+ * Some get calls (SET_*) can change the
+ * key pointers. So, we need to store
+ * the allocated key space in a tmp.
+ */
+ ret = _CopyObjBytes(interp, objv[objc-1], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBGET(ret), "db get");
+ return (result);
+ }
+ key.data = ktmp;
}
ret = dbp->cursor(dbp, txn, &dbc, 0);
- result = _ReturnSetup(interp, ret, "db cursor");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db cursor");
if (result == TCL_ERROR)
goto out;
@@ -988,11 +1273,26 @@ tcl_DbGet(interp, objc, objv, dbp)
cflag = DB_SET_RANGE;
} else
cflag = DB_SET;
- _debug_check();
- ret = dbc->c_get(dbc, &key, &data, cflag | rmw);
- result = _ReturnSetup(interp, ret, "db get (cursor)");
+ if (ispget) {
+ _debug_check();
+ F_SET(&pkey, DB_DBT_MALLOC);
+ ret = dbc->c_pget(dbc, &key, &pkey, &data, cflag | rmw);
+ } else {
+ _debug_check();
+ ret = dbc->c_get(dbc, &key, &data, cflag | rmw);
+ }
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBCGET(ret),
+ "db get (cursor)");
if (result == TCL_ERROR)
goto out1;
+ if (ret == 0 && pattern &&
+ memcmp(key.data, prefix, strlen(prefix)) != 0) {
+ /*
+ * Free space from DB_DBT_MALLOC
+ */
+ free(data.data);
+ goto out1;
+ }
if (pattern)
cflag = DB_NEXT;
else
@@ -1002,36 +1302,46 @@ tcl_DbGet(interp, objc, objv, dbp)
/*
* Build up our {name value} sublist
*/
- result = _SetListElem(interp, retlist,
- key.data, key.size,
- data.data, data.size);
+ if (ispget)
+ result = _Set3DBTList(interp, retlist, &key, 0,
+ &pkey, useprecno, &data);
+ else
+ result = _SetListElem(interp, retlist,
+ key.data, key.size, data.data, data.size);
/*
* Free space from DB_DBT_MALLOC
*/
- __os_free(data.data, data.size);
+ if (ispget)
+ free(pkey.data);
+ free(data.data);
if (result != TCL_OK)
break;
/*
* Append {name value} to return list
*/
memset(&key, 0, sizeof(key));
+ memset(&pkey, 0, sizeof(pkey));
memset(&data, 0, sizeof(data));
/*
* Restore any "partial" info we have saved.
*/
data = save;
- ret = dbc->c_get(dbc, &key, &data, cflag | rmw);
+ if (ispget) {
+ F_SET(&pkey, DB_DBT_MALLOC);
+ ret = dbc->c_pget(dbc, &key, &pkey, &data, cflag | rmw);
+ } else
+ ret = dbc->c_get(dbc, &key, &data, cflag | rmw);
if (ret == 0 && pattern &&
memcmp(key.data, prefix, strlen(prefix)) != 0) {
/*
* Free space from DB_DBT_MALLOC
*/
- __os_free(data.data, data.size);
+ free(data.data);
break;
}
}
- dbc->c_close(dbc);
out1:
+ dbc->c_close(dbc);
if (result == TCL_OK)
Tcl_SetObjResult(interp, retlist);
out:
@@ -1041,7 +1351,11 @@ out:
* have multiple nuls at the end, so we free using __os_free().
*/
if (prefix != NULL)
- __os_free(prefix,0);
+ __os_free(dbp->dbenv, prefix);
+ if (freedata)
+ (void)__os_free(dbp->dbenv, dtmp);
+ if (freekey)
+ (void)__os_free(dbp->dbenv, ktmp);
return (result);
}
@@ -1056,11 +1370,13 @@ tcl_DbDelete(interp, objc, objv, dbp)
DB *dbp; /* Database pointer */
{
static char *dbdelopts[] = {
+ "-auto_commit",
"-glob",
"-txn",
NULL
};
enum dbdelopts {
+ DBDEL_AUTO_COMMIT,
DBDEL_GLOB,
DBDEL_TXN
};
@@ -1068,12 +1384,14 @@ tcl_DbDelete(interp, objc, objv, dbp)
DBT key, data;
DBTYPE type;
DB_TXN *txn;
+ void *ktmp;
db_recno_t recno;
- int i, itmp, optindex, result, ret;
+ int freekey, i, optindex, result, ret;
u_int32_t flag;
char *arg, *pattern, *prefix, msg[MSG_SIZE];
result = TCL_OK;
+ freekey = 0;
flag = 0;
pattern = prefix = NULL;
txn = NULL;
@@ -1084,17 +1402,17 @@ tcl_DbDelete(interp, objc, objv, dbp)
memset(&key, 0, sizeof(key));
/*
- * The first arg must be -txn, -glob or a list of keys.
+ * The first arg must be -auto_commit, -glob, -txn or a list of keys.
*/
i = 2;
while (i < objc) {
if (Tcl_GetIndexFromObj(interp, objv[i], dbdelopts, "option",
TCL_EXACT, &optindex) != TCL_OK) {
/*
- * If we don't have a -glob or -txn, then the
- * remaining args must be exact keys.
- * Reset the result so we don't get
- * an errant error message if there is another error.
+ * If we don't have a -auto_commit, -glob or -txn,
+ * then the remaining args must be exact keys.
+ * Reset the result so we don't get an errant error
+ * message if there is another error.
*/
if (IS_HELP(objv[i]) == TCL_OK)
return (TCL_OK);
@@ -1121,6 +1439,9 @@ tcl_DbDelete(interp, objc, objv, dbp)
result = TCL_ERROR;
}
break;
+ case DBDEL_AUTO_COMMIT:
+ flag |= DB_AUTO_COMMIT;
+ break;
case DBDEL_GLOB:
/*
* Get the pattern. Get the prefix and use cursors to
@@ -1143,17 +1464,6 @@ tcl_DbDelete(interp, objc, objv, dbp)
if (result != TCL_OK)
goto out;
-
- /*
- * If we have a pattern AND more keys to process, then there
- * is an error. Either we have some number of exact keys,
- * or we have a pattern.
- */
- if (pattern != NULL && i != objc) {
- Tcl_WrongNumArgs(interp, 2, objv, "?args? -glob pattern | key");
- result = TCL_ERROR;
- goto out;
- }
/*
* XXX
* For consistency with get, we have decided for the moment, to
@@ -1163,11 +1473,33 @@ tcl_DbDelete(interp, objc, objv, dbp)
* than one, and at that time we'd make delete be consistent. In
* any case, the code is already here and there is no need to remove,
* just check that we only have one arg left.
+ *
+ * If we have a pattern AND more keys to process, there is an error.
+ * Either we have some number of exact keys, or we have a pattern.
+ *
+ * If we have a pattern and an auto commit flag, there is an error.
*/
- if (pattern == NULL && i != (objc - 1)) {
- Tcl_WrongNumArgs(interp, 2, objv, "?args? -glob pattern | key");
- result = TCL_ERROR;
- goto out;
+ if (pattern == NULL) {
+ if (i != (objc - 1)) {
+ Tcl_WrongNumArgs(
+ interp, 2, objv, "?args? -glob pattern | key");
+ result = TCL_ERROR;
+ goto out;
+ }
+ } else {
+ if (i != objc) {
+ Tcl_WrongNumArgs(
+ interp, 2, objv, "?args? -glob pattern | key");
+ result = TCL_ERROR;
+ goto out;
+ }
+ if (flag & DB_AUTO_COMMIT) {
+ Tcl_SetResult(interp,
+ "Cannot use -auto_commit and patterns.\n",
+ TCL_STATIC);
+ result = TCL_ERROR;
+ goto out;
+ }
}
/*
@@ -1177,32 +1509,39 @@ tcl_DbDelete(interp, objc, objv, dbp)
* If it is a RECNO database, the key is a record number and must be
* setup up to contain a db_recno_t. Otherwise the key is a "string".
*/
- type = dbp->get_type(dbp);
+ (void)dbp->get_type(dbp, &type);
ret = 0;
while (i < objc && ret == 0) {
memset(&key, 0, sizeof(key));
if (type == DB_RECNO || type == DB_QUEUE) {
- result = Tcl_GetIntFromObj(interp, objv[i++], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp, objv[i++], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
return (result);
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[i++], &itmp);
- key.size = itmp;
+ ret = _CopyObjBytes(interp, objv[i++], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBDEL(ret), "db del");
+ return (result);
+ }
+ key.data = ktmp;
}
_debug_check();
- ret = dbp->del(dbp, txn, &key, 0);
+ ret = dbp->del(dbp, txn, &key, flag);
/*
* If we have any error, set up return result and stop
* processing keys.
*/
+ if (freekey)
+ (void)__os_free(dbp->dbenv, ktmp);
if (ret != 0)
break;
}
- result = _ReturnSetup(interp, ret, "db del");
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBDEL(ret), "db del");
/*
* At this point we've either finished or, if we have a pattern,
@@ -1212,7 +1551,8 @@ tcl_DbDelete(interp, objc, objv, dbp)
if (pattern) {
ret = dbp->cursor(dbp, txn, &dbc, 0);
if (ret != 0) {
- result = _ReturnSetup(interp, ret, "db cursor");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db cursor");
goto out;
}
/*
@@ -1244,7 +1584,8 @@ tcl_DbDelete(interp, objc, objv, dbp)
_debug_check();
ret = dbc->c_del(dbc, 0);
if (ret != 0) {
- result = _ReturnSetup(interp, ret, "db c_del");
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBCDEL(ret), "db c_del");
break;
}
/*
@@ -1262,9 +1603,9 @@ tcl_DbDelete(interp, objc, objv, dbp)
* by copying and condensing another string. Thus prefix may
* have multiple nuls at the end, so we free using __os_free().
*/
- __os_free(prefix,0);
+ __os_free(dbp->dbenv, prefix);
dbc->c_close(dbc);
- result = _ReturnSetup(interp, ret, "db del");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db del");
}
out:
return (result);
@@ -1282,11 +1623,19 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
DBC **dbcp; /* Return cursor pointer */
{
static char *dbcuropts[] = {
- "-txn", "-update",
+#if CONFIG_TEST
+ "-dirty",
+ "-update",
+#endif
+ "-txn",
NULL
};
enum dbcuropts {
- DBCUR_TXN, DBCUR_UPDATE
+#if CONFIG_TEST
+ DBCUR_DIRTY,
+ DBCUR_UPDATE,
+#endif
+ DBCUR_TXN
};
DB_TXN *txn;
u_int32_t flag;
@@ -1296,11 +1645,6 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
result = TCL_OK;
flag = 0;
txn = NULL;
- /*
- * If the user asks for -glob or -recno, it MUST be the second
- * last arg given. If it isn't given, then we must check if
- * they gave us a correct key.
- */
i = 2;
while (i < objc) {
if (Tcl_GetIndexFromObj(interp, objv[i], dbcuropts, "option",
@@ -1310,6 +1654,14 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
}
i++;
switch ((enum dbcuropts)optindex) {
+#if CONFIG_TEST
+ case DBCUR_DIRTY:
+ flag |= DB_DIRTY_READ;
+ break;
+ case DBCUR_UPDATE:
+ flag |= DB_WRITECURSOR;
+ break;
+#endif
case DBCUR_TXN:
if (i == objc) {
Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
@@ -1325,9 +1677,6 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
result = TCL_ERROR;
}
break;
- case DBCUR_UPDATE:
- flag = DB_WRITECURSOR;
- break;
}
if (result != TCL_OK)
break;
@@ -1344,6 +1693,192 @@ out:
}
/*
+ * tcl_DbAssociate --
+ * Call DB->associate().
+ */
+static int
+tcl_DbAssociate(interp, objc, objv, dbp)
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+ DB *dbp;
+{
+ static char *dbaopts[] = {
+ "-auto_commit",
+ "-create",
+ "-txn",
+ NULL
+ };
+ enum dbaopts {
+ DBA_AUTO_COMMIT,
+ DBA_CREATE,
+ DBA_TXN
+ };
+ DB *sdbp;
+ DB_TXN *txn;
+ DBTCL_INFO *sdbip;
+ int i, optindex, result, ret;
+ char *arg, msg[MSG_SIZE];
+ u_int32_t flag;
+
+ txn = NULL;
+ result = TCL_OK;
+ flag = 0;
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "[callback] secondary");
+ return (TCL_ERROR);
+ }
+
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], dbaopts, "option",
+ TCL_EXACT, &optindex) != TCL_OK) {
+ result = IS_HELP(objv[i]);
+ if (result == TCL_OK)
+ return (result);
+ result = TCL_OK;
+ Tcl_ResetResult(interp);
+ break;
+ }
+ i++;
+ switch ((enum dbaopts)optindex) {
+ case DBA_AUTO_COMMIT:
+ flag |= DB_AUTO_COMMIT;
+ break;
+ case DBA_CREATE:
+ flag |= DB_CREATE;
+ break;
+ case DBA_TXN:
+ if (i > (objc - 1)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "Associate: Invalid txn: %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ result = TCL_ERROR;
+ }
+ break;
+ }
+ }
+ if (result != TCL_OK)
+ return (result);
+
+ /*
+ * Better be 1 or 2 args left. The last arg must be the sdb
+ * handle. If 2 args then objc-2 is the callback proc, else
+ * we have a NULL callback.
+ */
+ /* Get the secondary DB handle. */
+ arg = Tcl_GetStringFromObj(objv[objc - 1], NULL);
+ sdbp = NAME_TO_DB(arg);
+ if (sdbp == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "Associate: Invalid database handle: %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ return (TCL_ERROR);
+ }
+
+ /*
+ * The callback is simply a Tcl object containing the name
+ * of the callback proc, which is the second-to-last argument.
+ *
+ * Note that the callback needs to go in the *secondary* DB handle's
+ * info struct; we may have multiple secondaries with different
+ * callbacks.
+ */
+ sdbip = (DBTCL_INFO *)sdbp->api_internal;
+ if (i != objc - 1) {
+ /*
+ * We have 2 args, get the callback.
+ */
+ sdbip->i_second_call = objv[objc - 2];
+ Tcl_IncrRefCount(sdbip->i_second_call);
+
+ /* Now call associate. */
+ _debug_check();
+ ret = dbp->associate(dbp, txn, sdbp, tcl_second_call, flag);
+ } else {
+ /*
+ * We have a NULL callback.
+ */
+ sdbip->i_second_call = NULL;
+ ret = dbp->associate(dbp, txn, sdbp, NULL, flag);
+ }
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "associate");
+
+ return (result);
+}
+
+/*
+ * tcl_second_call --
+ * Callback function for secondary indices. Get the callback
+ * out of ip->i_second_call and call it.
+ */
+static int
+tcl_second_call(dbp, pkey, data, skey)
+ DB *dbp;
+ const DBT *pkey, *data;
+ DBT *skey;
+{
+ DBTCL_INFO *ip;
+ Tcl_Interp *interp;
+ Tcl_Obj *pobj, *dobj, *objv[3];
+ int len, result, ret;
+ void *retbuf, *databuf;
+
+ ip = (DBTCL_INFO *)dbp->api_internal;
+ interp = ip->i_interp;
+ objv[0] = ip->i_second_call;
+
+ /*
+ * Create two ByteArray objects, with the contents of the pkey
+ * and data DBTs that are our inputs.
+ */
+ pobj = Tcl_NewByteArrayObj(pkey->data, pkey->size);
+ Tcl_IncrRefCount(pobj);
+ dobj = Tcl_NewByteArrayObj(data->data, data->size);
+ Tcl_IncrRefCount(dobj);
+
+ objv[1] = pobj;
+ objv[2] = dobj;
+
+ result = Tcl_EvalObjv(interp, 3, objv, 0);
+
+ Tcl_DecrRefCount(pobj);
+ Tcl_DecrRefCount(dobj);
+
+ if (result != TCL_OK) {
+ __db_err(dbp->dbenv,
+ "Tcl callback function failed with code %d", result);
+ return (EINVAL);
+ }
+
+ retbuf =
+ Tcl_GetByteArrayFromObj(Tcl_GetObjResult(interp), &len);
+
+ /*
+ * retbuf is owned by Tcl; copy it into malloc'ed memory.
+ * We need to use __os_umalloc rather than ufree because this will
+ * be freed by DB using __os_ufree--the DB_DBT_APPMALLOC flag
+ * tells DB to free application-allocated memory.
+ */
+ if ((ret = __os_umalloc(dbp->dbenv, len, &databuf)) != 0)
+ return (ret);
+ memcpy(databuf, retbuf, len);
+
+ skey->data = databuf;
+ skey->size = len;
+ F_SET(skey, DB_DBT_APPMALLOC);
+
+ return (0);
+}
+
+/*
* tcl_db_join --
*/
static int
@@ -1399,7 +1934,7 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
* Allocate one more for NULL ptr at end of list.
*/
size = sizeof(DBC *) * ((objc - adj) + 1);
- ret = __os_malloc(dbp->dbenv, size, NULL, &listp);
+ ret = __os_malloc(dbp->dbenv, size, &listp);
if (ret != 0) {
Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
return (TCL_ERROR);
@@ -1420,10 +1955,10 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
listp[j] = NULL;
_debug_check();
ret = dbp->join(dbp, listp, dbcp, flag);
- result = _ReturnSetup(interp, ret, "db join");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db join");
out:
- __os_free(listp, size);
+ __os_free(dbp->dbenv, listp);
return (result);
}
@@ -1438,12 +1973,16 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
DB *dbp; /* Database pointer */
{
static char *dbgetjopts[] = {
+#if CONFIG_TEST
"-nosort",
+#endif
"-txn",
NULL
};
enum dbgetjopts {
+#if CONFIG_TEST
DBGETJ_NOSORT,
+#endif
DBGETJ_TXN
};
DB_TXN *txn;
@@ -1452,12 +1991,14 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
DBC *dbc;
DBT key, data;
Tcl_Obj **elemv, *retlist;
+ void *ktmp;
u_int32_t flag;
- int adj, elemc, i, itmp, j, optindex, result, ret, size;
+ int adj, elemc, freekey, i, j, optindex, result, ret, size;
char *arg, msg[MSG_SIZE];
result = TCL_OK;
flag = 0;
+ freekey = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "{db1 key1} {db2 key2} ...");
return (TCL_ERROR);
@@ -1478,10 +2019,12 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
}
i++;
switch ((enum dbgetjopts)optindex) {
+#if CONFIG_TEST
case DBGETJ_NOSORT:
flag |= DB_JOIN_NOSORT;
adj++;
break;
+#endif
case DBGETJ_TXN:
if (i == objc) {
Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
@@ -1503,7 +2046,7 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
if (result != TCL_OK)
return (result);
size = sizeof(DBC *) * ((objc - adj) + 1);
- ret = __os_malloc(NULL, size, NULL, &listp);
+ ret = __os_malloc(NULL, size, &listp);
if (ret != 0) {
Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
return (TCL_ERROR);
@@ -1535,22 +2078,28 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
goto out;
}
ret = elemdbp->cursor(elemdbp, txn, &listp[j], 0);
- if ((result = _ReturnSetup(interp, ret, "db cursor")) ==
- TCL_ERROR)
+ if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db cursor")) == TCL_ERROR)
goto out;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
- key.data = Tcl_GetByteArrayFromObj(elemv[elemc-1], &itmp);
- key.size = itmp;
+ ret = _CopyObjBytes(interp, elemv[elemc-1], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "db join");
+ goto out;
+ }
+ key.data = ktmp;
ret = (listp[j])->c_get(listp[j], &key, &data, DB_SET);
- if ((result = _ReturnSetup(interp, ret, "db cget")) ==
- TCL_ERROR)
+ if ((result = _ReturnSetup(interp, ret, DB_RETOK_DBCGET(ret),
+ "db cget")) == TCL_ERROR)
goto out;
}
listp[j] = NULL;
_debug_check();
ret = dbp->join(dbp, listp, &dbc, flag);
- result = _ReturnSetup(interp, ret, "db join");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db join");
if (result == TCL_ERROR)
goto out;
@@ -1568,20 +2117,22 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
result = _SetListElem(interp, retlist,
key.data, key.size,
data.data, data.size);
- __os_free(key.data, key.size);
- __os_free(data.data, data.size);
+ free(key.data);
+ free(data.data);
}
}
dbc->c_close(dbc);
if (result == TCL_OK)
Tcl_SetObjResult(interp, retlist);
out:
+ if (freekey)
+ (void)__os_free(dbp->dbenv, ktmp);
while (j) {
if (listp[j])
(listp[j])->c_close(listp[j]);
j--;
}
- __os_free(listp, size);
+ __os_free(dbp->dbenv, listp);
return (result);
}
@@ -1598,11 +2149,13 @@ tcl_DbCount(interp, objc, objv, dbp)
Tcl_Obj *res;
DBC *dbc;
DBT key, data;
+ void *ktmp;
db_recno_t count, recno;
- int itmp, len, result, ret;
+ int freekey, result, ret;
result = TCL_OK;
count = 0;
+ freekey = 0;
res = NULL;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "key");
@@ -1624,21 +2177,27 @@ tcl_DbCount(interp, objc, objv, dbp)
* treat the key as a recno rather than as a byte string.
*/
if (dbp->type == DB_RECNO || dbp->type == DB_QUEUE) {
- result = Tcl_GetIntFromObj(interp, objv[2], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp, objv[2], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
return (result);
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[2], &len);
- key.size = len;
+ ret = _CopyObjBytes(interp, objv[2], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "db count");
+ return (result);
+ }
+ key.data = ktmp;
}
_debug_check();
ret = dbp->cursor(dbp, NULL, &dbc, 0);
if (ret != 0) {
- result = _ReturnSetup(interp, ret, "db cursor");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db cursor");
goto out;
}
/*
@@ -1650,16 +2209,21 @@ tcl_DbCount(interp, objc, objv, dbp)
else {
ret = dbc->c_count(dbc, &count, 0);
if (ret != 0) {
- result = _ReturnSetup(interp, ret, "db cursor");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db c count");
goto out;
}
}
- res = Tcl_NewIntObj(count);
+ res = Tcl_NewLongObj((long)count);
Tcl_SetObjResult(interp, res);
out:
+ if (freekey)
+ (void)__os_free(dbp->dbenv, ktmp);
+ (void)dbc->c_close(dbc);
return (result);
}
+#if CONFIG_TEST
/*
* tcl_DbKeyRange --
*/
@@ -1682,13 +2246,15 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
DBT key;
DBTYPE type;
Tcl_Obj *myobjv[3], *retlist;
+ void *ktmp;
db_recno_t recno;
u_int32_t flag;
- int i, itmp, myobjc, optindex, result, ret;
+ int freekey, i, myobjc, optindex, result, ret;
char *arg, msg[MSG_SIZE];
result = TCL_OK;
flag = 0;
+ freekey = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?-txn id? key");
return (TCL_ERROR);
@@ -1727,7 +2293,7 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
}
if (result != TCL_OK)
return (result);
- type = dbp->get_type(dbp);
+ (void)dbp->get_type(dbp, &type);
ret = 0;
/*
* Make sure we have a key.
@@ -1739,20 +2305,25 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
}
memset(&key, 0, sizeof(key));
if (type == DB_RECNO || type == DB_QUEUE) {
- result = Tcl_GetIntFromObj(interp, objv[i], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp, objv[i], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
return (result);
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[i++], &itmp);
- key.size = itmp;
+ ret = _CopyObjBytes(interp, objv[i++], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "db keyrange");
+ return (result);
+ }
+ key.data = ktmp;
}
_debug_check();
ret = dbp->key_range(dbp, txn, &key, &range, flag);
- result = _ReturnSetup(interp, ret, "db join");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db keyrange");
if (result == TCL_ERROR)
goto out;
@@ -1767,5 +2338,84 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
if (result == TCL_OK)
Tcl_SetObjResult(interp, retlist);
out:
+ if (freekey)
+ (void)__os_free(dbp->dbenv, ktmp);
+ return (result);
+}
+#endif
+
+/*
+ * tcl_DbTruncate --
+ */
+static int
+tcl_DbTruncate(interp, objc, objv, dbp)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB *dbp; /* Database pointer */
+{
+ static char *dbcuropts[] = {
+ "-auto_commit",
+ "-txn",
+ NULL
+ };
+ enum dbcuropts {
+ DBTRUNC_AUTO_COMMIT,
+ DBTRUNC_TXN
+ };
+ DB_TXN *txn;
+ Tcl_Obj *res;
+ u_int32_t count, flag;
+ int i, optindex, result, ret;
+ char *arg, msg[MSG_SIZE];
+
+ txn = NULL;
+ flag = 0;
+ result = TCL_OK;
+
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], dbcuropts, "option",
+ TCL_EXACT, &optindex) != TCL_OK) {
+ result = IS_HELP(objv[i]);
+ goto out;
+ }
+ i++;
+ switch ((enum dbcuropts)optindex) {
+ case DBTRUNC_AUTO_COMMIT:
+ flag |= DB_AUTO_COMMIT;
+ break;
+ case DBTRUNC_TXN:
+ if (i == objc) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "Truncate: Invalid txn: %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ result = TCL_ERROR;
+ }
+ break;
+ }
+ if (result != TCL_OK)
+ break;
+ }
+ if (result != TCL_OK)
+ goto out;
+
+ _debug_check();
+ ret = dbp->truncate(dbp, txn, &count, flag);
+ if (ret != 0)
+ result = _ErrorSetup(interp, ret, "db truncate");
+
+ else {
+ res = Tcl_NewLongObj((long)count);
+ Tcl_SetObjResult(interp, res);
+ }
+out:
return (result);
}
diff --git a/bdb/tcl/tcl_db_pkg.c b/bdb/tcl/tcl_db_pkg.c
index f83b5a7d2a9..ce37598dc1a 100644
--- a/bdb/tcl/tcl_db_pkg.c
+++ b/bdb/tcl/tcl_db_pkg.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_db_pkg.c,v 11.76 2001/01/19 18:02:36 bostic Exp $";
+static const char revid[] = "$Id: tcl_db_pkg.c,v 11.141 2002/08/14 20:15:47 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,10 +19,17 @@ static const char revid[] = "$Id: tcl_db_pkg.c,v 11.76 2001/01/19 18:02:36 bosti
#include <tcl.h>
#endif
+#if CONFIG_TEST
#define DB_DBM_HSEARCH 1
+#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+#include "dbinc/tcl_db.h"
+
+/* XXX we must declare global data in just one place */
+DBTCL_GLOBAL __dbtcl_global;
/*
* Prototypes for procedures defined later in this file:
@@ -40,6 +47,20 @@ static int bdb_DbVerify __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
static int bdb_Version __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
static int bdb_Handles __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
+static int tcl_bt_compare __P((DB *, const DBT *, const DBT *));
+static int tcl_compare_callback __P((DB *, const DBT *, const DBT *,
+ Tcl_Obj *, char *));
+static int tcl_dup_compare __P((DB *, const DBT *, const DBT *));
+static u_int32_t tcl_h_hash __P((DB *, const void *, u_int32_t));
+static int tcl_rep_send __P((DB_ENV *,
+ const DBT *, const DBT *, int, u_int32_t));
+
+#ifdef TEST_ALLOC
+static void * tcl_db_malloc __P((size_t));
+static void * tcl_db_realloc __P((void *, size_t));
+static void tcl_db_free __P((void *));
+#endif
+
/*
* Db_tcl_Init --
*
@@ -96,20 +117,24 @@ berkdb_Cmd(notused, interp, objc, objv)
Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *berkdbcmds[] = {
+#if CONFIG_TEST
+ "dbverify",
+ "handles",
+ "upgrade",
+#endif
"dbremove",
"dbrename",
- "dbverify",
"env",
"envremove",
- "handles",
"open",
- "upgrade",
"version",
+#if CONFIG_TEST
/* All below are compatibility functions */
"hcreate", "hsearch", "hdestroy",
"dbminit", "fetch", "store",
"delete", "firstkey", "nextkey",
"ndbm_open", "dbmclose",
+#endif
/* All below are convenience functions */
"rand", "random_int", "srand",
"debug_check",
@@ -119,28 +144,34 @@ berkdb_Cmd(notused, interp, objc, objv)
* All commands enums below ending in X are compatibility
*/
enum berkdbcmds {
+#if CONFIG_TEST
+ BDB_DBVERIFY,
+ BDB_HANDLES,
+ BDB_UPGRADE,
+#endif
BDB_DBREMOVE,
BDB_DBRENAME,
- BDB_DBVERIFY,
BDB_ENV,
BDB_ENVREMOVE,
- BDB_HANDLES,
BDB_OPEN,
- BDB_UPGRADE,
BDB_VERSION,
+#if CONFIG_TEST
BDB_HCREATEX, BDB_HSEARCHX, BDB_HDESTROYX,
BDB_DBMINITX, BDB_FETCHX, BDB_STOREX,
BDB_DELETEX, BDB_FIRSTKEYX, BDB_NEXTKEYX,
BDB_NDBMOPENX, BDB_DBMCLOSEX,
+#endif
BDB_RANDX, BDB_RAND_INTX, BDB_SRANDX,
BDB_DBGCKX
};
static int env_id = 0;
static int db_id = 0;
- static int ndbm_id = 0;
DB *dbp;
+#if CONFIG_TEST
DBM *ndbmp;
+ static int ndbm_id = 0;
+#endif
DBTCL_INFO *ip;
DB_ENV *envp;
Tcl_Obj *res;
@@ -166,13 +197,21 @@ berkdb_Cmd(notused, interp, objc, objv)
return (IS_HELP(objv[1]));
res = NULL;
switch ((enum berkdbcmds)cmdindex) {
- case BDB_VERSION:
- _debug_check();
- result = bdb_Version(interp, objc, objv);
+#if CONFIG_TEST
+ case BDB_DBVERIFY:
+ result = bdb_DbVerify(interp, objc, objv);
break;
case BDB_HANDLES:
result = bdb_Handles(interp, objc, objv);
break;
+ case BDB_UPGRADE:
+ result = bdb_DbUpgrade(interp, objc, objv);
+ break;
+#endif
+ case BDB_VERSION:
+ _debug_check();
+ result = bdb_Version(interp, objc, objv);
+ break;
case BDB_ENV:
snprintf(newname, sizeof(newname), "env%d", env_id);
ip = _NewInfo(interp, NULL, newname, I_ENV);
@@ -201,12 +240,6 @@ berkdb_Cmd(notused, interp, objc, objv)
case BDB_DBRENAME:
result = bdb_DbRename(interp, objc, objv);
break;
- case BDB_UPGRADE:
- result = bdb_DbUpgrade(interp, objc, objv);
- break;
- case BDB_DBVERIFY:
- result = bdb_DbVerify(interp, objc, objv);
- break;
case BDB_ENVREMOVE:
result = tcl_EnvRemove(interp, objc, objv, NULL, NULL);
break;
@@ -232,6 +265,7 @@ berkdb_Cmd(notused, interp, objc, objv)
result = TCL_ERROR;
}
break;
+#if CONFIG_TEST
case BDB_HCREATEX:
case BDB_HSEARCHX:
case BDB_HDESTROYX:
@@ -268,6 +302,7 @@ berkdb_Cmd(notused, interp, objc, objv)
result = TCL_ERROR;
}
break;
+#endif
case BDB_RANDX:
case BDB_RAND_INTX:
case BDB_SRANDX:
@@ -296,7 +331,7 @@ berkdb_Cmd(notused, interp, objc, objv)
* 1. Call db_env_create to create the env handle.
* 2. Parse args tracking options.
* 3. Make any pre-open setup calls necessary.
- * 4. Call DBENV->open to open the env.
+ * 4. Call DB_ENV->open to open the env.
* 5. Return env widget handle to user.
*/
static int
@@ -308,15 +343,11 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
DB_ENV **env; /* Environment pointer */
{
static char *envopen[] = {
- "-cachesize",
+#if CONFIG_TEST
+ "-auto_commit",
"-cdb",
"-cdb_alldb",
"-client_timeout",
- "-create",
- "-data_dir",
- "-errfile",
- "-errpfx",
- "-home",
"-lock",
"-lock_conflict",
"-lock_detect",
@@ -324,28 +355,46 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
"-lock_max_locks",
"-lock_max_lockers",
"-lock_max_objects",
+ "-lock_timeout",
"-log",
"-log_buffer",
- "-log_dir",
"-log_max",
+ "-log_regionmax",
"-mmapsize",
- "-mode",
"-nommap",
- "-private",
- "-recover",
- "-recover_fatal",
+ "-overwrite",
"-region_init",
+ "-rep_client",
+ "-rep_logsonly",
+ "-rep_master",
+ "-rep_transport",
"-server",
"-server_timeout",
+ "-txn_timeout",
+ "-txn_timestamp",
+ "-verbose",
+ "-wrnosync",
+#endif
+ "-cachesize",
+ "-create",
+ "-data_dir",
+ "-encryptaes",
+ "-encryptany",
+ "-errfile",
+ "-errpfx",
+ "-home",
+ "-log_dir",
+ "-mode",
+ "-private",
+ "-recover",
+ "-recover_fatal",
"-shm_key",
"-system_mem",
"-tmp_dir",
"-txn",
"-txn_max",
- "-txn_timestamp",
"-use_environ",
"-use_environ_root",
- "-verbose",
NULL
};
/*
@@ -354,15 +403,11 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
* which is close to but not quite alphabetical.
*/
enum envopen {
- ENV_CACHESIZE,
+#if CONFIG_TEST
+ ENV_AUTO_COMMIT,
ENV_CDB,
ENV_CDB_ALLDB,
ENV_CLIENT_TO,
- ENV_CREATE,
- ENV_DATA_DIR,
- ENV_ERRFILE,
- ENV_ERRPFX,
- ENV_HOME,
ENV_LOCK,
ENV_CONFLICT,
ENV_DETECT,
@@ -370,52 +415,82 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
ENV_LOCK_MAX_LOCKS,
ENV_LOCK_MAX_LOCKERS,
ENV_LOCK_MAX_OBJECTS,
+ ENV_LOCK_TIMEOUT,
ENV_LOG,
ENV_LOG_BUFFER,
- ENV_LOG_DIR,
ENV_LOG_MAX,
+ ENV_LOG_REGIONMAX,
ENV_MMAPSIZE,
- ENV_MODE,
ENV_NOMMAP,
- ENV_PRIVATE,
- ENV_RECOVER,
- ENV_RECOVER_FATAL,
+ ENV_OVERWRITE,
ENV_REGION_INIT,
+ ENV_REP_CLIENT,
+ ENV_REP_LOGSONLY,
+ ENV_REP_MASTER,
+ ENV_REP_TRANSPORT,
ENV_SERVER,
ENV_SERVER_TO,
+ ENV_TXN_TIMEOUT,
+ ENV_TXN_TIME,
+ ENV_VERBOSE,
+ ENV_WRNOSYNC,
+#endif
+ ENV_CACHESIZE,
+ ENV_CREATE,
+ ENV_DATA_DIR,
+ ENV_ENCRYPT_AES,
+ ENV_ENCRYPT_ANY,
+ ENV_ERRFILE,
+ ENV_ERRPFX,
+ ENV_HOME,
+ ENV_LOG_DIR,
+ ENV_MODE,
+ ENV_PRIVATE,
+ ENV_RECOVER,
+ ENV_RECOVER_FATAL,
ENV_SHM_KEY,
ENV_SYSTEM_MEM,
ENV_TMP_DIR,
ENV_TXN,
ENV_TXN_MAX,
- ENV_TXN_TIME,
ENV_USE_ENVIRON,
- ENV_USE_ENVIRON_ROOT,
- ENV_VERBOSE
+ ENV_USE_ENVIRON_ROOT
};
Tcl_Obj **myobjv, **myobjv1;
- time_t time;
- u_int32_t detect, gbytes, bytes, ncaches, open_flags, set_flag, size;
+ time_t timestamp;
+ u_int32_t detect, gbytes, bytes, ncaches, logbufset, logmaxset;
+ u_int32_t open_flags, rep_flags, set_flags, size, uintarg;
u_int8_t *conflicts;
- int i, intarg, itmp, j, logbufset, logmaxset;
- int mode, myobjc, nmodes, optindex, result, ret, temp;
+ int i, intarg, j, mode, myobjc, nmodes, optindex;
+ int result, ret, temp;
long client_to, server_to, shm;
- char *arg, *home, *server;
+ char *arg, *home, *passwd, *server;
result = TCL_OK;
mode = 0;
- set_flag = 0;
+ rep_flags = set_flags = 0;
home = NULL;
+
/*
* XXX
* If/when our Tcl interface becomes thread-safe, we should enable
- * DB_THREAD here. Note that DB_THREAD currently does not work
- * with log_get -next, -prev; if we wish to enable DB_THREAD,
- * those must either be made thread-safe first or we must come up with
- * a workaround. (We used to specify DB_THREAD if and only if
- * logging was not configured.)
+ * DB_THREAD here in all cases. For now, turn it on only when testing
+ * so that we exercise MUTEX_THREAD_LOCK cases.
+ *
+ * Historically, a key stumbling block was the log_get interface,
+ * which could only do relative operations in a non-threaded
+ * environment. This is no longer an issue, thanks to log cursors,
+ * but we need to look at making sure DBTCL_INFO structs
+ * are safe to share across threads (they're not mutex-protected)
+ * before we declare the Tcl interface thread-safe. Meanwhile,
+ * there's no strong reason to enable DB_THREAD.
*/
- open_flags = DB_JOINENV;
+ open_flags = DB_JOINENV |
+#ifdef TEST_THREAD
+ DB_THREAD;
+#else
+ 0;
+#endif
logmaxset = logbufset = 0;
if (objc <= 2) {
@@ -436,6 +511,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
continue;
}
switch ((enum envopen)optindex) {
+#if CONFIG_TEST
case ENV_SERVER:
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
@@ -465,6 +541,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
result = Tcl_GetLongFromObj(interp, objv[i++],
&client_to);
break;
+#endif
default:
break;
}
@@ -472,10 +549,11 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
if (server != NULL) {
ret = db_env_create(env, DB_CLIENT);
if (ret)
- return (_ReturnSetup(interp, ret, "db_env_create"));
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_env_create"));
(*env)->set_errpfx((*env), ip->i_name);
(*env)->set_errcall((*env), _ErrorFunc);
- if ((ret = (*env)->set_server((*env), server,
+ if ((ret = (*env)->set_rpc_server((*env), NULL, server,
client_to, server_to, 0)) != 0) {
result = TCL_ERROR;
goto error;
@@ -487,17 +565,30 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
*/
ret = db_env_create(env, 0);
if (ret)
- return (_ReturnSetup(interp, ret, "db_env_create"));
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_env_create"));
(*env)->set_errpfx((*env), ip->i_name);
(*env)->set_errcall((*env), _ErrorFunc);
}
+ /* Hang our info pointer on the env handle, so we can do callbacks. */
+ (*env)->app_private = ip;
+
+ /*
+ * Use a Tcl-local alloc and free function so that we're sure to
+ * test whether we use umalloc/ufree in the right places.
+ */
+#ifdef TEST_ALLOC
+ (*env)->set_alloc(*env, tcl_db_malloc, tcl_db_realloc, tcl_db_free);
+#endif
+
/*
* Get the command name index from the object based on the bdbcmds
* defined above.
*/
i = 2;
while (i < objc) {
+ Tcl_ResetResult(interp);
if (Tcl_GetIndexFromObj(interp, objv[i], envopen, "option",
TCL_EXACT, &optindex) != TCL_OK) {
result = IS_HELP(objv[i]);
@@ -505,6 +596,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
}
i++;
switch ((enum envopen)optindex) {
+#if CONFIG_TEST
case ENV_SERVER:
case ENV_SERVER_TO:
case ENV_CLIENT_TO:
@@ -513,208 +605,20 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
*/
i++;
break;
+ case ENV_AUTO_COMMIT:
+ FLD_SET(set_flags, DB_AUTO_COMMIT);
+ break;
case ENV_CDB:
FLD_SET(open_flags, DB_INIT_CDB | DB_INIT_MPOOL);
FLD_CLR(open_flags, DB_JOINENV);
break;
case ENV_CDB_ALLDB:
- FLD_SET(set_flag, DB_CDB_ALLDB);
+ FLD_SET(set_flags, DB_CDB_ALLDB);
break;
case ENV_LOCK:
FLD_SET(open_flags, DB_INIT_LOCK | DB_INIT_MPOOL);
FLD_CLR(open_flags, DB_JOINENV);
break;
- case ENV_LOG:
- FLD_SET(open_flags, DB_INIT_LOG | DB_INIT_MPOOL);
- FLD_CLR(open_flags, DB_JOINENV);
- break;
- case ENV_TXN:
- FLD_SET(open_flags, DB_INIT_LOCK |
- DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN);
- FLD_CLR(open_flags, DB_JOINENV);
- /* Make sure we have an arg to check against! */
- if (i < objc) {
- arg = Tcl_GetStringFromObj(objv[i], NULL);
- if (strcmp(arg, "nosync") == 0) {
- FLD_SET(set_flag, DB_TXN_NOSYNC);
- i++;
- }
- }
- break;
- case ENV_CREATE:
- FLD_SET(open_flags, DB_CREATE | DB_INIT_MPOOL);
- FLD_CLR(open_flags, DB_JOINENV);
- break;
- case ENV_HOME:
- /* Make sure we have an arg to check against! */
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-home dir?");
- result = TCL_ERROR;
- break;
- }
- home = Tcl_GetStringFromObj(objv[i++], NULL);
- break;
- case ENV_MODE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mode mode?");
- result = TCL_ERROR;
- break;
- }
- /*
- * Don't need to check result here because
- * if TCL_ERROR, the error message is already
- * set up, and we'll bail out below. If ok,
- * the mode is set and we go on.
- */
- result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
- break;
- case ENV_NOMMAP:
- FLD_SET(set_flag, DB_NOMMAP);
- break;
- case ENV_PRIVATE:
- FLD_SET(open_flags, DB_PRIVATE | DB_INIT_MPOOL);
- FLD_CLR(open_flags, DB_JOINENV);
- break;
- case ENV_RECOVER:
- FLD_SET(open_flags, DB_RECOVER);
- break;
- case ENV_RECOVER_FATAL:
- FLD_SET(open_flags, DB_RECOVER_FATAL);
- break;
- case ENV_SYSTEM_MEM:
- FLD_SET(open_flags, DB_SYSTEM_MEM);
- break;
- case ENV_USE_ENVIRON_ROOT:
- FLD_SET(open_flags, DB_USE_ENVIRON_ROOT);
- break;
- case ENV_USE_ENVIRON:
- FLD_SET(open_flags, DB_USE_ENVIRON);
- break;
- case ENV_VERBOSE:
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- if (myobjc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-verbose {which on|off}?");
- result = TCL_ERROR;
- break;
- }
- result = tcl_EnvVerbose(interp, *env,
- myobjv[0], myobjv[1]);
- break;
- case ENV_REGION_INIT:
- _debug_check();
- ret = db_env_set_region_init(1);
- result = _ReturnSetup(interp, ret, "region_init");
- break;
- case ENV_CACHESIZE:
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- j = 0;
- if (myobjc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-cachesize {gbytes bytes ncaches}?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, myobjv[0], &itmp);
- gbytes = itmp;
- if (result != TCL_OK)
- break;
- result = Tcl_GetIntFromObj(interp, myobjv[1], &itmp);
- bytes = itmp;
- if (result != TCL_OK)
- break;
- result = Tcl_GetIntFromObj(interp, myobjv[2], &itmp);
- ncaches = itmp;
- if (result != TCL_OK)
- break;
- _debug_check();
- ret = (*env)->set_cachesize(*env, gbytes, bytes,
- ncaches);
- result = _ReturnSetup(interp, ret, "set_cachesize");
- break;
- case ENV_MMAPSIZE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mmapsize size?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_mp_mmapsize(*env,
- (size_t)intarg);
- result = _ReturnSetup(interp, ret, "mmapsize");
- }
- break;
- case ENV_SHM_KEY:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-shm_key key?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetLongFromObj(interp, objv[i++], &shm);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_shm_key(*env, shm);
- result = _ReturnSetup(interp, ret, "shm_key");
- }
- break;
- case ENV_LOG_MAX:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-log_max max?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK && logbufset) {
- _debug_check();
- ret = (*env)->set_lg_max(*env,
- (u_int32_t)intarg);
- result = _ReturnSetup(interp, ret, "log_max");
- logbufset = 0;
- } else
- logmaxset = intarg;
- break;
- case ENV_LOG_BUFFER:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-log_buffer size?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_lg_bsize(*env,
- (u_int32_t)intarg);
- result = _ReturnSetup(interp, ret, "log_bsize");
- logbufset = 1;
- if (logmaxset) {
- _debug_check();
- ret = (*env)->set_lg_max(*env,
- (u_int32_t)logmaxset);
- result = _ReturnSetup(interp, ret,
- "log_max");
- logmaxset = 0;
- logbufset = 0;
- }
- }
- break;
case ENV_CONFLICT:
/*
* Get conflict list. List is:
@@ -747,7 +651,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
break;
}
size = sizeof(u_int8_t) * nmodes*nmodes;
- ret = __os_malloc(*env, size, NULL, &conflicts);
+ ret = __os_malloc(*env, size, &conflicts);
if (ret != 0) {
result = TCL_ERROR;
break;
@@ -757,15 +661,16 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
&temp);
conflicts[j] = temp;
if (result != TCL_OK) {
- __os_free(conflicts, size);
+ __os_free(NULL, conflicts);
break;
}
}
_debug_check();
ret = (*env)->set_lk_conflicts(*env,
(u_int8_t *)conflicts, nmodes);
- __os_free(conflicts, size);
- result = _ReturnSetup(interp, ret, "set_lk_conflicts");
+ __os_free(NULL, conflicts);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_lk_conflicts");
break;
case ENV_DETECT:
if (i >= objc) {
@@ -777,6 +682,14 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
arg = Tcl_GetStringFromObj(objv[i++], NULL);
if (strcmp(arg, "default") == 0)
detect = DB_LOCK_DEFAULT;
+ else if (strcmp(arg, "expire") == 0)
+ detect = DB_LOCK_EXPIRE;
+ else if (strcmp(arg, "maxlocks") == 0)
+ detect = DB_LOCK_MAXLOCKS;
+ else if (strcmp(arg, "minlocks") == 0)
+ detect = DB_LOCK_MINLOCKS;
+ else if (strcmp(arg, "minwrites") == 0)
+ detect = DB_LOCK_MINWRITE;
else if (strcmp(arg, "oldest") == 0)
detect = DB_LOCK_OLDEST;
else if (strcmp(arg, "youngest") == 0)
@@ -791,7 +704,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
}
_debug_check();
ret = (*env)->set_lk_detect(*env, detect);
- result = _ReturnSetup(interp, ret, "lock_detect");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock_detect");
break;
case ENV_LOCK_MAX:
case ENV_LOCK_MAX_LOCKS:
@@ -803,61 +717,373 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+ result = _GetUInt32(interp, objv[i++], &uintarg);
if (result == TCL_OK) {
_debug_check();
switch ((enum envopen)optindex) {
case ENV_LOCK_MAX:
ret = (*env)->set_lk_max(*env,
- (u_int32_t)intarg);
+ uintarg);
break;
case ENV_LOCK_MAX_LOCKS:
ret = (*env)->set_lk_max_locks(*env,
- (u_int32_t)intarg);
+ uintarg);
break;
case ENV_LOCK_MAX_LOCKERS:
ret = (*env)->set_lk_max_lockers(*env,
- (u_int32_t)intarg);
+ uintarg);
break;
case ENV_LOCK_MAX_OBJECTS:
ret = (*env)->set_lk_max_objects(*env,
- (u_int32_t)intarg);
+ uintarg);
break;
default:
break;
}
- result = _ReturnSetup(interp, ret, "lock_max");
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "lock_max");
}
break;
- case ENV_TXN_MAX:
+ case ENV_TXN_TIME:
+ case ENV_TXN_TIMEOUT:
+ case ENV_LOCK_TIMEOUT:
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "?-txn_max max?");
+ "?-txn_timestamp time?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = Tcl_GetLongFromObj(interp, objv[i++],
+ (long *)&timestamp);
+ if (result == TCL_OK) {
+ _debug_check();
+ if (optindex == ENV_TXN_TIME)
+ ret = (*env)->
+ set_tx_timestamp(*env, &timestamp);
+ else
+ ret = (*env)->set_timeout(*env,
+ (db_timeout_t)timestamp,
+ optindex == ENV_TXN_TIMEOUT ?
+ DB_SET_TXN_TIMEOUT :
+ DB_SET_LOCK_TIMEOUT);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "txn_timestamp");
+ }
+ break;
+ case ENV_LOG:
+ FLD_SET(open_flags, DB_INIT_LOG | DB_INIT_MPOOL);
+ FLD_CLR(open_flags, DB_JOINENV);
+ break;
+ case ENV_LOG_BUFFER:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-log_buffer size?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, objv[i++], &uintarg);
+ if (result == TCL_OK) {
+ _debug_check();
+ ret = (*env)->set_lg_bsize(*env, uintarg);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "log_bsize");
+ logbufset = 1;
+ if (logmaxset) {
+ _debug_check();
+ ret = (*env)->set_lg_max(*env,
+ logmaxset);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "log_max");
+ logmaxset = 0;
+ logbufset = 0;
+ }
+ }
+ break;
+ case ENV_LOG_MAX:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-log_max max?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, objv[i++], &uintarg);
+ if (result == TCL_OK && logbufset) {
+ _debug_check();
+ ret = (*env)->set_lg_max(*env, uintarg);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "log_max");
+ logbufset = 0;
+ } else
+ logmaxset = uintarg;
+ break;
+ case ENV_LOG_REGIONMAX:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-log_regionmax size?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, objv[i++], &uintarg);
+ if (result == TCL_OK) {
+ _debug_check();
+ ret = (*env)->set_lg_regionmax(*env, uintarg);
+ result =
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "log_regionmax");
+ }
+ break;
+ case ENV_MMAPSIZE:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-mmapsize size?");
result = TCL_ERROR;
break;
}
result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
if (result == TCL_OK) {
_debug_check();
- ret = (*env)->set_tx_max(*env,
- (u_int32_t)intarg);
- result = _ReturnSetup(interp, ret, "txn_max");
+ ret = (*env)->set_mp_mmapsize(*env,
+ (size_t)intarg);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "mmapsize");
}
break;
- case ENV_TXN_TIME:
+ case ENV_NOMMAP:
+ FLD_SET(set_flags, DB_NOMMAP);
+ break;
+ case ENV_OVERWRITE:
+ FLD_SET(set_flags, DB_OVERWRITE);
+ break;
+ case ENV_REGION_INIT:
+ _debug_check();
+ ret = (*env)->set_flags(*env, DB_REGION_INIT, 1);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "region_init");
+ break;
+ case ENV_REP_CLIENT:
+ rep_flags = DB_REP_CLIENT;
+ break;
+ case ENV_REP_LOGSONLY:
+ rep_flags = DB_REP_LOGSONLY;
+ break;
+ case ENV_REP_MASTER:
+ rep_flags = DB_REP_MASTER;
+ break;
+ case ENV_REP_TRANSPORT:
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "?-txn_timestamp time?");
+ "-rep_transport {envid sendproc}");
result = TCL_ERROR;
break;
}
- result = Tcl_GetLongFromObj(interp, objv[i++],
- (long *)&time);
+
+ /*
+ * Store the objects containing the machine ID
+ * and the procedure name. We don't need to crack
+ * the send procedure out now, but we do convert the
+ * machine ID to an int, since set_rep_transport needs
+ * it. Even so, it'll be easier later to deal with
+ * the Tcl_Obj *, so we save that, not the int.
+ *
+ * Note that we Tcl_IncrRefCount both objects
+ * independently; Tcl is free to discard the list
+ * that they're bundled into.
+ */
+ result = Tcl_ListObjGetElements(interp, objv[i++],
+ &myobjc, &myobjv);
+ if (myobjc != 2) {
+ Tcl_SetResult(interp,
+ "List must be {envid sendproc}",
+ TCL_STATIC);
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * Check that the machine ID is an int. Note that
+ * we do want to use GetIntFromObj; the machine
+ * ID is explicitly an int, not a u_int32_t.
+ */
+ ip->i_rep_eid = myobjv[0];
+ Tcl_IncrRefCount(ip->i_rep_eid);
+ result = Tcl_GetIntFromObj(interp,
+ ip->i_rep_eid, &intarg);
+ if (result != TCL_OK)
+ break;
+
+ ip->i_rep_send = myobjv[1];
+ Tcl_IncrRefCount(ip->i_rep_send);
+ _debug_check();
+ ret = (*env)->set_rep_transport(*env,
+ intarg, tcl_rep_send);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_rep_transport");
+ break;
+ case ENV_VERBOSE:
+ result = Tcl_ListObjGetElements(interp, objv[i],
+ &myobjc, &myobjv);
+ if (result == TCL_OK)
+ i++;
+ else
+ break;
+ if (myobjc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-verbose {which on|off}?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = tcl_EnvVerbose(interp, *env,
+ myobjv[0], myobjv[1]);
+ break;
+ case ENV_WRNOSYNC:
+ FLD_SET(set_flags, DB_TXN_WRITE_NOSYNC);
+ break;
+#endif
+ case ENV_TXN:
+ FLD_SET(open_flags, DB_INIT_LOCK |
+ DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN);
+ FLD_CLR(open_flags, DB_JOINENV);
+ /* Make sure we have an arg to check against! */
+ if (i < objc) {
+ arg = Tcl_GetStringFromObj(objv[i], NULL);
+ if (strcmp(arg, "nosync") == 0) {
+ FLD_SET(set_flags, DB_TXN_NOSYNC);
+ i++;
+ }
+ }
+ break;
+ case ENV_CREATE:
+ FLD_SET(open_flags, DB_CREATE | DB_INIT_MPOOL);
+ FLD_CLR(open_flags, DB_JOINENV);
+ break;
+ case ENV_ENCRYPT_AES:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptaes passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ _debug_check();
+ ret = (*env)->set_encrypt(*env, passwd, DB_ENCRYPT_AES);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ break;
+ case ENV_ENCRYPT_ANY:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptany passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ _debug_check();
+ ret = (*env)->set_encrypt(*env, passwd, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ break;
+ case ENV_HOME:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-home dir?");
+ result = TCL_ERROR;
+ break;
+ }
+ home = Tcl_GetStringFromObj(objv[i++], NULL);
+ break;
+ case ENV_MODE:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-mode mode?");
+ result = TCL_ERROR;
+ break;
+ }
+ /*
+ * Don't need to check result here because
+ * if TCL_ERROR, the error message is already
+ * set up, and we'll bail out below. If ok,
+ * the mode is set and we go on.
+ */
+ result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
+ break;
+ case ENV_PRIVATE:
+ FLD_SET(open_flags, DB_PRIVATE | DB_INIT_MPOOL);
+ FLD_CLR(open_flags, DB_JOINENV);
+ break;
+ case ENV_RECOVER:
+ FLD_SET(open_flags, DB_RECOVER);
+ break;
+ case ENV_RECOVER_FATAL:
+ FLD_SET(open_flags, DB_RECOVER_FATAL);
+ break;
+ case ENV_SYSTEM_MEM:
+ FLD_SET(open_flags, DB_SYSTEM_MEM);
+ break;
+ case ENV_USE_ENVIRON_ROOT:
+ FLD_SET(open_flags, DB_USE_ENVIRON_ROOT);
+ break;
+ case ENV_USE_ENVIRON:
+ FLD_SET(open_flags, DB_USE_ENVIRON);
+ break;
+ case ENV_CACHESIZE:
+ result = Tcl_ListObjGetElements(interp, objv[i],
+ &myobjc, &myobjv);
+ if (result == TCL_OK)
+ i++;
+ else
+ break;
+ if (myobjc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-cachesize {gbytes bytes ncaches}?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, myobjv[0], &gbytes);
+ if (result != TCL_OK)
+ break;
+ result = _GetUInt32(interp, myobjv[1], &bytes);
+ if (result != TCL_OK)
+ break;
+ result = _GetUInt32(interp, myobjv[2], &ncaches);
+ if (result != TCL_OK)
+ break;
+ _debug_check();
+ ret = (*env)->set_cachesize(*env, gbytes, bytes,
+ ncaches);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_cachesize");
+ break;
+ case ENV_SHM_KEY:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-shm_key key?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = Tcl_GetLongFromObj(interp, objv[i++], &shm);
if (result == TCL_OK) {
_debug_check();
- ret = (*env)->set_tx_timestamp(*env, &time);
+ ret = (*env)->set_shm_key(*env, shm);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "shm_key");
+ }
+ break;
+ case ENV_TXN_MAX:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-txn_max max?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, objv[i++], &uintarg);
+ if (result == TCL_OK) {
+ _debug_check();
+ ret = (*env)->set_tx_max(*env, uintarg);
result = _ReturnSetup(interp, ret,
- "txn_timestamp");
+ DB_RETOK_STD(ret), "txn_max");
}
break;
case ENV_ERRFILE:
@@ -891,11 +1117,11 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
* If the user already set one, free it.
*/
if (ip->i_errpfx != NULL)
- __os_freestr(ip->i_errpfx);
+ __os_free(NULL, ip->i_errpfx);
if ((ret =
__os_strdup(*env, arg, &ip->i_errpfx)) != 0) {
result = _ReturnSetup(interp, ret,
- "__os_strdup");
+ DB_RETOK_STD(ret), "__os_strdup");
break;
}
if (ip->i_errpfx != NULL) {
@@ -913,7 +1139,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
arg = Tcl_GetStringFromObj(objv[i++], NULL);
_debug_check();
ret = (*env)->set_data_dir(*env, arg);
- result = _ReturnSetup(interp, ret, "set_data_dir");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_data_dir");
break;
case ENV_LOG_DIR:
if (i >= objc) {
@@ -925,7 +1152,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
arg = Tcl_GetStringFromObj(objv[i++], NULL);
_debug_check();
ret = (*env)->set_lg_dir(*env, arg);
- result = _ReturnSetup(interp, ret, "set_lg_dir");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_lg_dir");
break;
case ENV_TMP_DIR:
if (i >= objc) {
@@ -937,7 +1165,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
arg = Tcl_GetStringFromObj(objv[i++], NULL);
_debug_check();
ret = (*env)->set_tmp_dir(*env, arg);
- result = _ReturnSetup(interp, ret, "set_tmp_dir");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_tmp_dir");
break;
}
/*
@@ -959,15 +1188,17 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
if (logmaxset) {
_debug_check();
ret = (*env)->set_lg_max(*env, (u_int32_t)logmaxset);
- result = _ReturnSetup(interp, ret, "log_max");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "log_max");
}
if (result != TCL_OK)
goto error;
- if (set_flag) {
- ret = (*env)->set_flags(*env, set_flag, 1);
- result = _ReturnSetup(interp, ret, "set_flags");
+ if (set_flags) {
+ ret = (*env)->set_flags(*env, set_flags, 1);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_flags");
if (result == TCL_ERROR)
goto error;
/*
@@ -985,10 +1216,16 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
*/
_debug_check();
ret = (*env)->open(*env, home, open_flags, mode);
- result = _ReturnSetup(interp, ret, "env open");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env open");
-error:
- if (result == TCL_ERROR) {
+ if (rep_flags != 0 && result == TCL_OK) {
+ _debug_check();
+ ret = (*env)->rep_start(*env, NULL, rep_flags);
+ result = _ReturnSetup(interp,
+ ret, DB_RETOK_STD(ret), "rep_start");
+ }
+
+error: if (result == TCL_ERROR) {
if (ip->i_err) {
fclose(ip->i_err);
ip->i_err = NULL;
@@ -1027,12 +1264,28 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
TCL_DB_ENV0
};
static char *bdbopen[] = {
+#if CONFIG_TEST
+ "-btcompare",
+ "-dirty",
+ "-dupcompare",
+ "-hashproc",
+ "-lorder",
+ "-minkey",
+ "-nommap",
+ "-revsplitoff",
+ "-test",
+#endif
+ "-auto_commit",
"-btree",
"-cachesize",
+ "-chksum",
"-create",
"-delim",
"-dup",
"-dupsort",
+ "-encrypt",
+ "-encryptaes",
+ "-encryptany",
"-env",
"-errfile",
"-errpfx",
@@ -1041,11 +1294,8 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
"-ffactor",
"-hash",
"-len",
- "-lorder",
- "-minkey",
"-mode",
"-nelem",
- "-nommap",
"-pad",
"-pagesize",
"-queue",
@@ -1053,22 +1303,37 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
"-recno",
"-recnum",
"-renumber",
- "-revsplitoff",
"-snapshot",
"-source",
"-truncate",
- "-test",
+ "-txn",
"-unknown",
"--",
NULL
};
enum bdbopen {
+#if CONFIG_TEST
+ TCL_DB_BTCOMPARE,
+ TCL_DB_DIRTY,
+ TCL_DB_DUPCOMPARE,
+ TCL_DB_HASHPROC,
+ TCL_DB_LORDER,
+ TCL_DB_MINKEY,
+ TCL_DB_NOMMAP,
+ TCL_DB_REVSPLIT,
+ TCL_DB_TEST,
+#endif
+ TCL_DB_AUTO_COMMIT,
TCL_DB_BTREE,
TCL_DB_CACHESIZE,
+ TCL_DB_CHKSUM,
TCL_DB_CREATE,
TCL_DB_DELIM,
TCL_DB_DUP,
TCL_DB_DUPSORT,
+ TCL_DB_ENCRYPT,
+ TCL_DB_ENCRYPT_AES,
+ TCL_DB_ENCRYPT_ANY,
TCL_DB_ENV,
TCL_DB_ERRFILE,
TCL_DB_ERRPFX,
@@ -1077,11 +1342,8 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
TCL_DB_FFACTOR,
TCL_DB_HASH,
TCL_DB_LEN,
- TCL_DB_LORDER,
- TCL_DB_MINKEY,
TCL_DB_MODE,
TCL_DB_NELEM,
- TCL_DB_NOMMAP,
TCL_DB_PAD,
TCL_DB_PAGESIZE,
TCL_DB_QUEUE,
@@ -1089,28 +1351,27 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
TCL_DB_RECNO,
TCL_DB_RECNUM,
TCL_DB_RENUMBER,
- TCL_DB_REVSPLIT,
TCL_DB_SNAPSHOT,
TCL_DB_SOURCE,
TCL_DB_TRUNCATE,
- TCL_DB_TEST,
+ TCL_DB_TXN,
TCL_DB_UNKNOWN,
TCL_DB_ENDARG
};
DBTCL_INFO *envip, *errip;
+ DB_TXN *txn;
DBTYPE type;
DB_ENV *envp;
Tcl_Obj **myobjv;
- u_int32_t gbytes, bytes, ncaches, open_flags;
- int endarg, i, intarg, itmp, j, mode, myobjc;
- int optindex, result, ret, set_err, set_flag, set_pfx, subdblen;
+ u_int32_t gbytes, bytes, ncaches, open_flags, uintarg;
+ int endarg, i, intarg, mode, myobjc;
+ int optindex, result, ret, set_err, set_flags, set_pfx, subdblen;
u_char *subdbtmp;
- char *arg, *db, *subdb;
- extern u_int32_t __ham_test __P((DB *, const void *, u_int32_t));
+ char *arg, *db, *passwd, *subdb, msg[MSG_SIZE];
type = DB_UNKNOWN;
- endarg = mode = set_err = set_flag = set_pfx = 0;
+ endarg = mode = set_err = set_flags = set_pfx = 0;
result = TCL_OK;
subdbtmp = NULL;
db = subdb = NULL;
@@ -1118,10 +1379,18 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
/*
* XXX
* If/when our Tcl interface becomes thread-safe, we should enable
- * DB_THREAD here. See comment in bdb_EnvOpen().
+ * DB_THREAD here in all cases. See comment in bdb_EnvOpen().
+ * For now, just turn it on when testing so that we exercise
+ * MUTEX_THREAD_LOCK cases.
*/
- open_flags = 0;
+ open_flags =
+#ifdef TEST_THREAD
+ DB_THREAD;
+#else
+ 0;
+#endif
envp = NULL;
+ txn = NULL;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?args?");
@@ -1162,7 +1431,11 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
*/
ret = db_create(dbp, envp, 0);
if (ret)
- return (_ReturnSetup(interp, ret, "db_create"));
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_create"));
+
+ /* Hang our info pointer on the DB handle, so we can do callbacks. */
+ (*dbp)->api_internal = ip;
/*
* XXX Remove restriction when err stuff is not tied to env.
@@ -1193,6 +1466,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
*/
i = 2;
while (i < objc) {
+ Tcl_ResetResult(interp);
if (Tcl_GetIndexFromObj(interp, objv[i], bdbopen, "option",
TCL_EXACT, &optindex) != TCL_OK) {
arg = Tcl_GetStringFromObj(objv[i], NULL);
@@ -1205,12 +1479,134 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
}
i++;
switch ((enum bdbopen)optindex) {
+#if CONFIG_TEST
+ case TCL_DB_BTCOMPARE:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "-btcompare compareproc");
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * Store the object containing the procedure name.
+ * We don't need to crack it out now--we'll want
+ * to bundle it up to pass into Tcl_EvalObjv anyway.
+ * Tcl's object refcounting will--I hope--take care
+ * of the memory management here.
+ */
+ ip->i_btcompare = objv[i++];
+ Tcl_IncrRefCount(ip->i_btcompare);
+ _debug_check();
+ ret = (*dbp)->set_bt_compare(*dbp, tcl_bt_compare);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_bt_compare");
+ break;
+ case TCL_DB_DIRTY:
+ open_flags |= DB_DIRTY_READ;
+ break;
+ case TCL_DB_DUPCOMPARE:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "-dupcompare compareproc");
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * Store the object containing the procedure name.
+ * See TCL_DB_BTCOMPARE.
+ */
+ ip->i_dupcompare = objv[i++];
+ Tcl_IncrRefCount(ip->i_dupcompare);
+ _debug_check();
+ ret = (*dbp)->set_dup_compare(*dbp, tcl_dup_compare);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_dup_compare");
+ break;
+ case TCL_DB_HASHPROC:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "-hashproc hashproc");
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * Store the object containing the procedure name.
+ * See TCL_DB_BTCOMPARE.
+ */
+ ip->i_hashproc = objv[i++];
+ Tcl_IncrRefCount(ip->i_hashproc);
+ _debug_check();
+ ret = (*dbp)->set_h_hash(*dbp, tcl_h_hash);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_h_hash");
+ break;
+ case TCL_DB_LORDER:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "-lorder 1234|4321");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, objv[i++], &uintarg);
+ if (result == TCL_OK) {
+ _debug_check();
+ ret = (*dbp)->set_lorder(*dbp, uintarg);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "set_lorder");
+ }
+ break;
+ case TCL_DB_MINKEY:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "-minkey minkey");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetUInt32(interp, objv[i++], &uintarg);
+ if (result == TCL_OK) {
+ _debug_check();
+ ret = (*dbp)->set_bt_minkey(*dbp, uintarg);
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "set_bt_minkey");
+ }
+ break;
+ case TCL_DB_NOMMAP:
+ open_flags |= DB_NOMMAP;
+ break;
+ case TCL_DB_REVSPLIT:
+ set_flags |= DB_REVSPLITOFF;
+ break;
+ case TCL_DB_TEST:
+ (*dbp)->set_h_hash(*dbp, __ham_test);
+ break;
+#endif
+ case TCL_DB_AUTO_COMMIT:
+ open_flags |= DB_AUTO_COMMIT;
+ break;
case TCL_DB_ENV:
/*
* Already parsed this, skip it and the env pointer.
*/
i++;
continue;
+ case TCL_DB_TXN:
+ if (i > (objc - 1)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "Put: Invalid txn: %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ result = TCL_ERROR;
+ }
+ break;
case TCL_DB_BTREE:
if (type != DB_UNKNOWN) {
Tcl_SetResult(interp,
@@ -1267,9 +1663,6 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
case TCL_DB_TRUNCATE:
open_flags |= DB_TRUNCATE;
break;
- case TCL_DB_TEST:
- (*dbp)->set_h_hash(*dbp, __ham_test);
- break;
case TCL_DB_MODE:
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
@@ -1285,73 +1678,83 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
*/
result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
break;
- case TCL_DB_NOMMAP:
- open_flags |= DB_NOMMAP;
- break;
case TCL_DB_DUP:
- set_flag |= DB_DUP;
+ set_flags |= DB_DUP;
break;
case TCL_DB_DUPSORT:
- set_flag |= DB_DUPSORT;
+ set_flags |= DB_DUPSORT;
break;
case TCL_DB_RECNUM:
- set_flag |= DB_RECNUM;
+ set_flags |= DB_RECNUM;
break;
case TCL_DB_RENUMBER:
- set_flag |= DB_RENUMBER;
- break;
- case TCL_DB_REVSPLIT:
- set_flag |= DB_REVSPLITOFF;
+ set_flags |= DB_RENUMBER;
break;
case TCL_DB_SNAPSHOT:
- set_flag |= DB_SNAPSHOT;
+ set_flags |= DB_SNAPSHOT;
break;
- case TCL_DB_FFACTOR:
+ case TCL_DB_CHKSUM:
+ set_flags |= DB_CHKSUM_SHA1;
+ break;
+ case TCL_DB_ENCRYPT:
+ set_flags |= DB_ENCRYPT;
+ break;
+ case TCL_DB_ENCRYPT_AES:
+ /* Make sure we have an arg to check against! */
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "-ffactor density");
+ "?-encryptaes passwd?");
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*dbp)->set_h_ffactor(*dbp,
- (u_int32_t)intarg);
- result = _ReturnSetup(interp, ret,
- "set_h_ffactor");
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ _debug_check();
+ ret = (*dbp)->set_encrypt(*dbp, passwd, DB_ENCRYPT_AES);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ break;
+ case TCL_DB_ENCRYPT_ANY:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptany passwd?");
+ result = TCL_ERROR;
+ break;
}
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ _debug_check();
+ ret = (*dbp)->set_encrypt(*dbp, passwd, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
break;
- case TCL_DB_NELEM:
+ case TCL_DB_FFACTOR:
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "-nelem nelem");
+ "-ffactor density");
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+ result = _GetUInt32(interp, objv[i++], &uintarg);
if (result == TCL_OK) {
_debug_check();
- ret = (*dbp)->set_h_nelem(*dbp,
- (u_int32_t)intarg);
+ ret = (*dbp)->set_h_ffactor(*dbp, uintarg);
result = _ReturnSetup(interp, ret,
- "set_h_nelem");
+ DB_RETOK_STD(ret), "set_h_ffactor");
}
break;
- case TCL_DB_LORDER:
+ case TCL_DB_NELEM:
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "-lorder 1234|4321");
+ "-nelem nelem");
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+ result = _GetUInt32(interp, objv[i++], &uintarg);
if (result == TCL_OK) {
_debug_check();
- ret = (*dbp)->set_lorder(*dbp,
- (u_int32_t)intarg);
+ ret = (*dbp)->set_h_nelem(*dbp, uintarg);
result = _ReturnSetup(interp, ret,
- "set_lorder");
+ DB_RETOK_STD(ret), "set_h_nelem");
}
break;
case TCL_DB_DELIM:
@@ -1366,7 +1769,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
_debug_check();
ret = (*dbp)->set_re_delim(*dbp, intarg);
result = _ReturnSetup(interp, ret,
- "set_re_delim");
+ DB_RETOK_STD(ret), "set_re_delim");
}
break;
case TCL_DB_LEN:
@@ -1376,13 +1779,12 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+ result = _GetUInt32(interp, objv[i++], &uintarg);
if (result == TCL_OK) {
_debug_check();
- ret = (*dbp)->set_re_len(*dbp,
- (u_int32_t)intarg);
+ ret = (*dbp)->set_re_len(*dbp, uintarg);
result = _ReturnSetup(interp, ret,
- "set_re_len");
+ DB_RETOK_STD(ret), "set_re_len");
}
break;
case TCL_DB_PAD:
@@ -1397,7 +1799,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
_debug_check();
ret = (*dbp)->set_re_pad(*dbp, intarg);
result = _ReturnSetup(interp, ret,
- "set_re_pad");
+ DB_RETOK_STD(ret), "set_re_pad");
}
break;
case TCL_DB_SOURCE:
@@ -1410,7 +1812,8 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
arg = Tcl_GetStringFromObj(objv[i++], NULL);
_debug_check();
ret = (*dbp)->set_re_source(*dbp, arg);
- result = _ReturnSetup(interp, ret, "set_re_source");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_re_source");
break;
case TCL_DB_EXTENT:
if (i >= objc) {
@@ -1419,28 +1822,12 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*dbp)->set_q_extentsize(*dbp,
- (u_int32_t)intarg);
- result = _ReturnSetup(interp, ret,
- "set_q_extentsize");
- }
- break;
- case TCL_DB_MINKEY:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-minkey minkey");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+ result = _GetUInt32(interp, objv[i++], &uintarg);
if (result == TCL_OK) {
_debug_check();
- ret = (*dbp)->set_bt_minkey(*dbp, intarg);
+ ret = (*dbp)->set_q_extentsize(*dbp, uintarg);
result = _ReturnSetup(interp, ret,
- "set_bt_minkey");
+ DB_RETOK_STD(ret), "set_q_extentsize");
}
break;
case TCL_DB_CACHESIZE:
@@ -1448,30 +1835,26 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
&myobjc, &myobjv);
if (result != TCL_OK)
break;
- j = 0;
if (myobjc != 3) {
Tcl_WrongNumArgs(interp, 2, objv,
"?-cachesize {gbytes bytes ncaches}?");
result = TCL_ERROR;
break;
}
- result = Tcl_GetIntFromObj(interp, myobjv[0], &itmp);
- gbytes = itmp;
+ result = _GetUInt32(interp, myobjv[0], &gbytes);
if (result != TCL_OK)
break;
- result = Tcl_GetIntFromObj(interp, myobjv[1], &itmp);
- bytes = itmp;
+ result = _GetUInt32(interp, myobjv[1], &bytes);
if (result != TCL_OK)
break;
- result = Tcl_GetIntFromObj(interp, myobjv[2], &itmp);
- ncaches = itmp;
+ result = _GetUInt32(interp, myobjv[2], &ncaches);
if (result != TCL_OK)
break;
_debug_check();
ret = (*dbp)->set_cachesize(*dbp, gbytes, bytes,
ncaches);
result = _ReturnSetup(interp, ret,
- "set_cachesize");
+ DB_RETOK_STD(ret), "set_cachesize");
break;
case TCL_DB_PAGESIZE:
if (i >= objc) {
@@ -1486,7 +1869,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
ret = (*dbp)->set_pagesize(*dbp,
(size_t)intarg);
result = _ReturnSetup(interp, ret,
- "set pagesize");
+ DB_RETOK_STD(ret), "set pagesize");
}
break;
case TCL_DB_ERRFILE:
@@ -1521,11 +1904,11 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
* If the user already set one, free it.
*/
if (errip->i_errpfx != NULL)
- __os_freestr(errip->i_errpfx);
+ __os_free(NULL, errip->i_errpfx);
if ((ret = __os_strdup((*dbp)->dbenv,
arg, &errip->i_errpfx)) != 0) {
result = _ReturnSetup(interp, ret,
- "__os_strdup");
+ DB_RETOK_STD(ret), "__os_strdup");
break;
}
if (errip->i_errpfx != NULL) {
@@ -1567,7 +1950,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
subdbtmp =
Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
if ((ret = __os_malloc(envp,
- subdblen + 1, NULL, &subdb)) != 0) {
+ subdblen + 1, &subdb)) != 0) {
Tcl_SetResult(interp, db_strerror(ret),
TCL_STATIC);
return (0);
@@ -1576,9 +1959,10 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
subdb[subdblen] = '\0';
}
}
- if (set_flag) {
- ret = (*dbp)->set_flags(*dbp, set_flag);
- result = _ReturnSetup(interp, ret, "set_flags");
+ if (set_flags) {
+ ret = (*dbp)->set_flags(*dbp, set_flags);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_flags");
if (result == TCL_ERROR)
goto error;
/*
@@ -1596,13 +1980,14 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
_debug_check();
/* Open the database. */
- ret = (*dbp)->open(*dbp, db, subdb, type, open_flags, mode);
- result = _ReturnSetup(interp, ret, "db open");
+ ret = (*dbp)->open(*dbp, txn, db, subdb, type, open_flags, mode);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db open");
error:
if (subdb)
- __os_free(subdb, subdblen + 1);
+ __os_free(envp, subdb);
if (result == TCL_ERROR) {
+ (void)(*dbp)->close(*dbp, 0);
/*
* If we opened and set up the error file in the environment
* on this open, but we failed for some other reason, clean
@@ -1619,10 +2004,9 @@ error:
errip->i_err = NULL;
}
if (set_pfx && errip && errip->i_errpfx != NULL) {
- __os_freestr(errip->i_errpfx);
+ __os_free(envp, errip->i_errpfx);
errip->i_errpfx = NULL;
}
- (void)(*dbp)->close(*dbp, 0);
*dbp = NULL;
}
return (result);
@@ -1630,7 +2014,7 @@ error:
/*
* bdb_DbRemove --
- * Implements the DB->remove command.
+ * Implements the DB_ENV->remove and DB->remove command.
*/
static int
bdb_DbRemove(interp, objc, objv)
@@ -1639,24 +2023,41 @@ bdb_DbRemove(interp, objc, objv)
Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *bdbrem[] = {
- "-env", "--", NULL
+ "-auto_commit",
+ "-encrypt",
+ "-encryptaes",
+ "-encryptany",
+ "-env",
+ "-txn",
+ "--",
+ NULL
};
enum bdbrem {
+ TCL_DBREM_AUTOCOMMIT,
+ TCL_DBREM_ENCRYPT,
+ TCL_DBREM_ENCRYPT_AES,
+ TCL_DBREM_ENCRYPT_ANY,
TCL_DBREM_ENV,
+ TCL_DBREM_TXN,
TCL_DBREM_ENDARG
};
- DB_ENV *envp;
DB *dbp;
+ DB_ENV *envp;
+ DB_TXN *txn;
int endarg, i, optindex, result, ret, subdblen;
+ u_int32_t enc_flag, iflags, set_flags;
u_char *subdbtmp;
- char *arg, *db, *subdb;
+ char *arg, *db, msg[MSG_SIZE], *passwd, *subdb;
- envp = NULL;
+ db = subdb = NULL;
dbp = NULL;
+ endarg = 0;
+ envp = NULL;
+ iflags = enc_flag = set_flags = 0;
+ passwd = NULL;
result = TCL_OK;
subdbtmp = NULL;
- db = subdb = NULL;
- endarg = 0;
+ txn = NULL;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?");
@@ -1681,6 +2082,36 @@ bdb_DbRemove(interp, objc, objv)
}
i++;
switch ((enum bdbrem)optindex) {
+ case TCL_DBREM_AUTOCOMMIT:
+ iflags |= DB_AUTO_COMMIT;
+ _debug_check();
+ break;
+ case TCL_DBREM_ENCRYPT:
+ set_flags |= DB_ENCRYPT;
+ _debug_check();
+ break;
+ case TCL_DBREM_ENCRYPT_AES:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptaes passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = DB_ENCRYPT_AES;
+ break;
+ case TCL_DBREM_ENCRYPT_ANY:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptany passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = 0;
+ break;
case TCL_DBREM_ENV:
arg = Tcl_GetStringFromObj(objv[i++], NULL);
envp = NAME_TO_ENV(arg);
@@ -1694,6 +2125,21 @@ bdb_DbRemove(interp, objc, objv)
case TCL_DBREM_ENDARG:
endarg = 1;
break;
+ case TCL_DBREM_TXN:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "Put: Invalid txn: %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ result = TCL_ERROR;
+ }
+ break;
}
/*
* If, at any time, parsing the args we get an error,
@@ -1721,7 +2167,7 @@ bdb_DbRemove(interp, objc, objv)
subdbtmp =
Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
if ((ret = __os_malloc(envp, subdblen + 1,
- NULL, &subdb)) != 0) { Tcl_SetResult(interp,
+ &subdb)) != 0) { Tcl_SetResult(interp,
db_strerror(ret), TCL_STATIC);
return (0);
}
@@ -1733,28 +2179,48 @@ bdb_DbRemove(interp, objc, objv)
result = TCL_ERROR;
goto error;
}
- ret = db_create(&dbp, envp, 0);
- if (ret) {
- result = _ReturnSetup(interp, ret, "db_create");
- goto error;
+ if (envp == NULL) {
+ ret = db_create(&dbp, envp, 0);
+ if (ret) {
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_create");
+ goto error;
+ }
+
+ if (passwd != NULL) {
+ ret = dbp->set_encrypt(dbp, passwd, enc_flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ }
+ if (set_flags != 0) {
+ ret = dbp->set_flags(dbp, set_flags);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_flags");
+ }
}
+
/*
* No matter what, we NULL out dbp after this call.
*/
- ret = dbp->remove(dbp, db, subdb, 0);
- result = _ReturnSetup(interp, ret, "db remove");
+ _debug_check();
+ if (dbp == NULL)
+ ret = envp->dbremove(envp, txn, db, subdb, iflags);
+ else
+ ret = dbp->remove(dbp, db, subdb, 0);
+
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db remove");
dbp = NULL;
error:
if (subdb)
- __os_free(subdb, subdblen + 1);
- if (result == TCL_ERROR && dbp)
+ __os_free(envp, subdb);
+ if (result == TCL_ERROR && dbp != NULL)
(void)dbp->close(dbp, 0);
return (result);
}
/*
* bdb_DbRename --
- * Implements the DB->rename command.
+ * Implements the DBENV->dbrename and DB->rename commands.
*/
static int
bdb_DbRename(interp, objc, objv)
@@ -1763,24 +2229,41 @@ bdb_DbRename(interp, objc, objv)
Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *bdbmv[] = {
- "-env", "--", NULL
+ "-auto_commit",
+ "-encrypt",
+ "-encryptaes",
+ "-encryptany",
+ "-env",
+ "-txn",
+ "--",
+ NULL
};
enum bdbmv {
+ TCL_DBMV_AUTOCOMMIT,
+ TCL_DBMV_ENCRYPT,
+ TCL_DBMV_ENCRYPT_AES,
+ TCL_DBMV_ENCRYPT_ANY,
TCL_DBMV_ENV,
+ TCL_DBMV_TXN,
TCL_DBMV_ENDARG
};
- DB_ENV *envp;
DB *dbp;
+ DB_ENV *envp;
+ DB_TXN *txn;
+ u_int32_t enc_flag, iflags, set_flags;
int endarg, i, newlen, optindex, result, ret, subdblen;
u_char *subdbtmp;
- char *arg, *db, *newname, *subdb;
+ char *arg, *db, msg[MSG_SIZE], *newname, *passwd, *subdb;
- envp = NULL;
+ db = newname = subdb = NULL;
dbp = NULL;
+ endarg = 0;
+ envp = NULL;
+ iflags = enc_flag = set_flags = 0;
+ passwd = NULL;
result = TCL_OK;
subdbtmp = NULL;
- db = newname = subdb = NULL;
- endarg = 0;
+ txn = NULL;
if (objc < 2) {
Tcl_WrongNumArgs(interp,
@@ -1806,6 +2289,36 @@ bdb_DbRename(interp, objc, objv)
}
i++;
switch ((enum bdbmv)optindex) {
+ case TCL_DBMV_AUTOCOMMIT:
+ iflags |= DB_AUTO_COMMIT;
+ _debug_check();
+ break;
+ case TCL_DBMV_ENCRYPT:
+ set_flags |= DB_ENCRYPT;
+ _debug_check();
+ break;
+ case TCL_DBMV_ENCRYPT_AES:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptaes passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = DB_ENCRYPT_AES;
+ break;
+ case TCL_DBMV_ENCRYPT_ANY:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptany passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = 0;
+ break;
case TCL_DBMV_ENV:
arg = Tcl_GetStringFromObj(objv[i++], NULL);
envp = NAME_TO_ENV(arg);
@@ -1819,6 +2332,21 @@ bdb_DbRename(interp, objc, objv)
case TCL_DBMV_ENDARG:
endarg = 1;
break;
+ case TCL_DBMV_TXN:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "Put: Invalid txn: %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ result = TCL_ERROR;
+ }
+ break;
}
/*
* If, at any time, parsing the args we get an error,
@@ -1846,7 +2374,7 @@ bdb_DbRename(interp, objc, objv)
subdbtmp =
Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
if ((ret = __os_malloc(envp, subdblen + 1,
- NULL, &subdb)) != 0) {
+ &subdb)) != 0) {
Tcl_SetResult(interp,
db_strerror(ret), TCL_STATIC);
return (0);
@@ -1857,7 +2385,7 @@ bdb_DbRename(interp, objc, objv)
subdbtmp =
Tcl_GetByteArrayFromObj(objv[i++], &newlen);
if ((ret = __os_malloc(envp, newlen + 1,
- NULL, &newname)) != 0) {
+ &newname)) != 0) {
Tcl_SetResult(interp,
db_strerror(ret), TCL_STATIC);
return (0);
@@ -1865,31 +2393,50 @@ bdb_DbRename(interp, objc, objv)
memcpy(newname, subdbtmp, newlen);
newname[newlen] = '\0';
} else {
- Tcl_WrongNumArgs(interp, 3, objv, "?args? filename ?database? ?newname?");
+ Tcl_WrongNumArgs(
+ interp, 3, objv, "?args? filename ?database? ?newname?");
result = TCL_ERROR;
goto error;
}
- ret = db_create(&dbp, envp, 0);
- if (ret) {
- result = _ReturnSetup(interp, ret, "db_create");
- goto error;
+ if (envp == NULL) {
+ ret = db_create(&dbp, envp, 0);
+ if (ret) {
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_create");
+ goto error;
+ }
+ if (passwd != NULL) {
+ ret = dbp->set_encrypt(dbp, passwd, enc_flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ }
+ if (set_flags != 0) {
+ ret = dbp->set_flags(dbp, set_flags);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_flags");
+ }
}
+
/*
* No matter what, we NULL out dbp after this call.
*/
- ret = dbp->rename(dbp, db, subdb, newname, 0);
- result = _ReturnSetup(interp, ret, "db rename");
+ if (dbp == NULL)
+ ret = envp->dbrename(envp, txn, db, subdb, newname, iflags);
+ else
+ ret = dbp->rename(dbp, db, subdb, newname, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db rename");
dbp = NULL;
error:
if (subdb)
- __os_free(subdb, subdblen + 1);
+ __os_free(envp, subdb);
if (newname)
- __os_free(newname, newlen + 1);
- if (result == TCL_ERROR && dbp)
+ __os_free(envp, newname);
+ if (result == TCL_ERROR && dbp != NULL)
(void)dbp->close(dbp, 0);
return (result);
}
+#if CONFIG_TEST
/*
* bdb_DbVerify --
* Implements the DB->verify command.
@@ -1901,9 +2448,19 @@ bdb_DbVerify(interp, objc, objv)
Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *bdbverify[] = {
- "-env", "-errfile", "-errpfx", "--", NULL
+ "-encrypt",
+ "-encryptaes",
+ "-encryptany",
+ "-env",
+ "-errfile",
+ "-errpfx",
+ "--",
+ NULL
};
enum bdbvrfy {
+ TCL_DBVRFY_ENCRYPT,
+ TCL_DBVRFY_ENCRYPT_AES,
+ TCL_DBVRFY_ENCRYPT_ANY,
TCL_DBVRFY_ENV,
TCL_DBVRFY_ERRFILE,
TCL_DBVRFY_ERRPFX,
@@ -1912,15 +2469,18 @@ bdb_DbVerify(interp, objc, objv)
DB_ENV *envp;
DB *dbp;
FILE *errf;
- int endarg, i, optindex, result, ret, flags;
- char *arg, *db, *errpfx;
+ u_int32_t enc_flag, flags, set_flags;
+ int endarg, i, optindex, result, ret;
+ char *arg, *db, *errpfx, *passwd;
envp = NULL;
dbp = NULL;
+ passwd = NULL;
result = TCL_OK;
db = errpfx = NULL;
errf = NULL;
flags = endarg = 0;
+ enc_flag = set_flags = 0;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?args? filename");
@@ -1945,6 +2505,32 @@ bdb_DbVerify(interp, objc, objv)
}
i++;
switch ((enum bdbvrfy)optindex) {
+ case TCL_DBVRFY_ENCRYPT:
+ set_flags |= DB_ENCRYPT;
+ _debug_check();
+ break;
+ case TCL_DBVRFY_ENCRYPT_AES:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptaes passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = DB_ENCRYPT_AES;
+ break;
+ case TCL_DBVRFY_ENCRYPT_ANY:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-encryptany passwd?");
+ result = TCL_ERROR;
+ break;
+ }
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = 0;
+ break;
case TCL_DBVRFY_ENV:
arg = Tcl_GetStringFromObj(objv[i++], NULL);
envp = NAME_TO_ENV(arg);
@@ -1983,10 +2569,10 @@ bdb_DbVerify(interp, objc, objv)
* If the user already set one, free it.
*/
if (errpfx != NULL)
- __os_freestr(errpfx);
+ __os_free(envp, errpfx);
if ((ret = __os_strdup(NULL, arg, &errpfx)) != 0) {
result = _ReturnSetup(interp, ret,
- "__os_strdup");
+ DB_RETOK_STD(ret), "__os_strdup");
break;
}
break;
@@ -2017,26 +2603,39 @@ bdb_DbVerify(interp, objc, objv)
}
ret = db_create(&dbp, envp, 0);
if (ret) {
- result = _ReturnSetup(interp, ret, "db_create");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_create");
goto error;
}
+ if (passwd != NULL) {
+ ret = dbp->set_encrypt(dbp, passwd, enc_flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ }
+
+ if (set_flags != 0) {
+ ret = dbp->set_flags(dbp, set_flags);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_flags");
+ }
if (errf != NULL)
dbp->set_errfile(dbp, errf);
if (errpfx != NULL)
dbp->set_errpfx(dbp, errpfx);
ret = dbp->verify(dbp, db, NULL, NULL, flags);
- result = _ReturnSetup(interp, ret, "db verify");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db verify");
error:
if (errf != NULL)
fclose(errf);
if (errpfx != NULL)
- __os_freestr(errpfx);
+ __os_free(envp, errpfx);
if (dbp)
(void)dbp->close(dbp, 0);
return (result);
}
+#endif
/*
* bdb_Version --
@@ -2113,6 +2712,7 @@ error:
return (result);
}
+#if CONFIG_TEST
/*
* bdb_Handles --
* Implements the handles command.
@@ -2144,7 +2744,9 @@ bdb_Handles(interp, objc, objv)
Tcl_SetObjResult(interp, res);
return (TCL_OK);
}
+#endif
+#if CONFIG_TEST
/*
* bdb_DbUpgrade --
* Implements the DB->upgrade command.
@@ -2165,7 +2767,8 @@ bdb_DbUpgrade(interp, objc, objv)
};
DB_ENV *envp;
DB *dbp;
- int endarg, i, optindex, result, ret, flags;
+ u_int32_t flags;
+ int endarg, i, optindex, result, ret;
char *arg, *db;
envp = NULL;
@@ -2233,14 +2836,282 @@ bdb_DbUpgrade(interp, objc, objv)
}
ret = db_create(&dbp, envp, 0);
if (ret) {
- result = _ReturnSetup(interp, ret, "db_create");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_create");
goto error;
}
ret = dbp->upgrade(dbp, db, flags);
- result = _ReturnSetup(interp, ret, "db upgrade");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db upgrade");
error:
if (dbp)
(void)dbp->close(dbp, 0);
return (result);
}
+#endif
+
+/*
+ * tcl_bt_compare and tcl_dup_compare --
+ * These two are basically identical internally, so may as well
+ * share code. The only differences are the name used in error
+ * reporting and the Tcl_Obj representing their respective procs.
+ */
+static int
+tcl_bt_compare(dbp, dbta, dbtb)
+ DB *dbp;
+ const DBT *dbta, *dbtb;
+{
+ return (tcl_compare_callback(dbp, dbta, dbtb,
+ ((DBTCL_INFO *)dbp->api_internal)->i_btcompare, "bt_compare"));
+}
+
+static int
+tcl_dup_compare(dbp, dbta, dbtb)
+ DB *dbp;
+ const DBT *dbta, *dbtb;
+{
+ return (tcl_compare_callback(dbp, dbta, dbtb,
+ ((DBTCL_INFO *)dbp->api_internal)->i_dupcompare, "dup_compare"));
+}
+
+/*
+ * tcl_compare_callback --
+ * Tcl callback for set_bt_compare and set_dup_compare. What this
+ * function does is stuff the data fields of the two DBTs into Tcl ByteArray
+ * objects, then call the procedure stored in ip->i_btcompare on the two
+ * objects. Then we return that procedure's result as the comparison.
+ */
+static int
+tcl_compare_callback(dbp, dbta, dbtb, procobj, errname)
+ DB *dbp;
+ const DBT *dbta, *dbtb;
+ Tcl_Obj *procobj;
+ char *errname;
+{
+ DBTCL_INFO *ip;
+ Tcl_Interp *interp;
+ Tcl_Obj *a, *b, *resobj, *objv[3];
+ int result, cmp;
+
+ ip = (DBTCL_INFO *)dbp->api_internal;
+ interp = ip->i_interp;
+ objv[0] = procobj;
+
+ /*
+ * Create two ByteArray objects, with the two data we've been passed.
+ * This will involve a copy, which is unpleasantly slow, but there's
+ * little we can do to avoid this (I think).
+ */
+ a = Tcl_NewByteArrayObj(dbta->data, dbta->size);
+ Tcl_IncrRefCount(a);
+ b = Tcl_NewByteArrayObj(dbtb->data, dbtb->size);
+ Tcl_IncrRefCount(b);
+
+ objv[1] = a;
+ objv[2] = b;
+
+ result = Tcl_EvalObjv(interp, 3, objv, 0);
+ if (result != TCL_OK) {
+ /*
+ * XXX
+ * If this or the next Tcl call fails, we're doomed.
+ * There's no way to return an error from comparison functions,
+ * no way to determine what the correct sort order is, and
+ * so no way to avoid corrupting the database if we proceed.
+ * We could play some games stashing return values on the
+ * DB handle, but it's not worth the trouble--no one with
+ * any sense is going to be using this other than for testing,
+ * and failure typically means that the bt_compare proc
+ * had a syntax error in it or something similarly dumb.
+ *
+ * So, drop core. If we're not running with diagnostic
+ * mode, panic--and always return a negative number. :-)
+ */
+panic: __db_err(dbp->dbenv, "Tcl %s callback failed", errname);
+ DB_ASSERT(0);
+ return (__db_panic(dbp->dbenv, DB_RUNRECOVERY));
+ }
+
+ resobj = Tcl_GetObjResult(interp);
+ result = Tcl_GetIntFromObj(interp, resobj, &cmp);
+ if (result != TCL_OK)
+ goto panic;
+
+ Tcl_DecrRefCount(a);
+ Tcl_DecrRefCount(b);
+ return (cmp);
+}
+
+/*
+ * tcl_h_hash --
+ * Tcl callback for the hashing function. See tcl_compare_callback--
+ * this works much the same way, only we're given a buffer and a length
+ * instead of two DBTs.
+ */
+static u_int32_t
+tcl_h_hash(dbp, buf, len)
+ DB *dbp;
+ const void *buf;
+ u_int32_t len;
+{
+ DBTCL_INFO *ip;
+ Tcl_Interp *interp;
+ Tcl_Obj *objv[2];
+ int result, hval;
+
+ ip = (DBTCL_INFO *)dbp->api_internal;
+ interp = ip->i_interp;
+ objv[0] = ip->i_hashproc;
+
+ /*
+ * Create a ByteArray for the buffer.
+ */
+ objv[1] = Tcl_NewByteArrayObj((void *)buf, len);
+ Tcl_IncrRefCount(objv[1]);
+ result = Tcl_EvalObjv(interp, 2, objv, 0);
+ if (result != TCL_OK) {
+ /*
+ * XXX
+ * We drop core on error. See the comment in
+ * tcl_compare_callback.
+ */
+panic: __db_err(dbp->dbenv, "Tcl h_hash callback failed");
+ DB_ASSERT(0);
+ return (__db_panic(dbp->dbenv, DB_RUNRECOVERY));
+ }
+
+ result = Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &hval);
+ if (result != TCL_OK)
+ goto panic;
+
+ Tcl_DecrRefCount(objv[1]);
+ return (hval);
+}
+
+/*
+ * tcl_rep_send --
+ * Replication send callback.
+ */
+static int
+tcl_rep_send(dbenv, control, rec, eid, flags)
+ DB_ENV *dbenv;
+ const DBT *control, *rec;
+ int eid;
+ u_int32_t flags;
+{
+ DBTCL_INFO *ip;
+ Tcl_Interp *interp;
+ Tcl_Obj *control_o, *eid_o, *origobj, *rec_o, *resobj, *objv[5];
+ int result, ret;
+
+ COMPQUIET(flags, 0);
+
+ ip = (DBTCL_INFO *)dbenv->app_private;
+ interp = ip->i_interp;
+ objv[0] = ip->i_rep_send;
+
+ control_o = Tcl_NewByteArrayObj(control->data, control->size);
+ Tcl_IncrRefCount(control_o);
+
+ rec_o = Tcl_NewByteArrayObj(rec->data, rec->size);
+ Tcl_IncrRefCount(rec_o);
+
+ eid_o = Tcl_NewIntObj(eid);
+ Tcl_IncrRefCount(eid_o);
+
+ objv[1] = control_o;
+ objv[2] = rec_o;
+ objv[3] = ip->i_rep_eid; /* From ID */
+ objv[4] = eid_o; /* To ID */
+
+ /*
+ * We really want to return the original result to the
+ * user. So, save the result obj here, and then after
+ * we've taken care of the Tcl_EvalObjv, set the result
+ * back to this original result.
+ */
+ origobj = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(origobj);
+ result = Tcl_EvalObjv(interp, 5, objv, 0);
+ if (result != TCL_OK) {
+ /*
+ * XXX
+ * This probably isn't the right error behavior, but
+ * this error should only happen if the Tcl callback is
+ * somehow invalid, which is a fatal scripting bug.
+ */
+err: __db_err(dbenv, "Tcl rep_send failure");
+ return (EINVAL);
+ }
+
+ resobj = Tcl_GetObjResult(interp);
+ result = Tcl_GetIntFromObj(interp, resobj, &ret);
+ if (result != TCL_OK)
+ goto err;
+
+ Tcl_SetObjResult(interp, origobj);
+ Tcl_DecrRefCount(origobj);
+ Tcl_DecrRefCount(control_o);
+ Tcl_DecrRefCount(rec_o);
+ Tcl_DecrRefCount(eid_o);
+
+ return (ret);
+}
+
+#ifdef TEST_ALLOC
+/*
+ * tcl_db_malloc, tcl_db_realloc, tcl_db_free --
+ * Tcl-local malloc, realloc, and free functions to use for user data
+ * to exercise umalloc/urealloc/ufree. Allocate the memory as a Tcl object
+ * so we're sure to exacerbate and catch any shared-library issues.
+ */
+static void *
+tcl_db_malloc(size)
+ size_t size;
+{
+ Tcl_Obj *obj;
+ void *buf;
+
+ obj = Tcl_NewObj();
+ if (obj == NULL)
+ return (NULL);
+ Tcl_IncrRefCount(obj);
+
+ Tcl_SetObjLength(obj, size + sizeof(Tcl_Obj *));
+ buf = Tcl_GetString(obj);
+ memcpy(buf, &obj, sizeof(&obj));
+
+ buf = (Tcl_Obj **)buf + 1;
+ return (buf);
+}
+
+static void *
+tcl_db_realloc(ptr, size)
+ void *ptr;
+ size_t size;
+{
+ Tcl_Obj *obj;
+
+ if (ptr == NULL)
+ return (tcl_db_malloc(size));
+
+ obj = *(Tcl_Obj **)((Tcl_Obj **)ptr - 1);
+ Tcl_SetObjLength(obj, size + sizeof(Tcl_Obj *));
+
+ ptr = Tcl_GetString(obj);
+ memcpy(ptr, &obj, sizeof(&obj));
+
+ ptr = (Tcl_Obj **)ptr + 1;
+ return (ptr);
+}
+
+static void
+tcl_db_free(ptr)
+ void *ptr;
+{
+ Tcl_Obj *obj;
+
+ obj = *(Tcl_Obj **)((Tcl_Obj **)ptr - 1);
+ Tcl_DecrRefCount(obj);
+}
+#endif
diff --git a/bdb/tcl/tcl_dbcursor.c b/bdb/tcl/tcl_dbcursor.c
index 26e7b58c64a..fb426e53f48 100644
--- a/bdb/tcl/tcl_dbcursor.c
+++ b/bdb/tcl/tcl_dbcursor.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_dbcursor.c,v 11.26 2001/01/11 18:19:55 bostic Exp $";
+static const char revid[] = "$Id: tcl_dbcursor.c,v 11.51 2002/08/06 06:20:59 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,14 +20,14 @@ static const char revid[] = "$Id: tcl_dbcursor.c,v 11.26 2001/01/11 18:19:55 bos
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/tcl_db.h"
/*
* Prototypes for procedures defined later in this file:
*/
-static int tcl_DbcDup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));
-static int tcl_DbcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));
-static int tcl_DbcPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));
+static int tcl_DbcDup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));
+static int tcl_DbcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *, int));
+static int tcl_DbcPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));
/*
* PUBLIC: int dbc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
@@ -37,12 +37,15 @@ static int tcl_DbcPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));
*/
int
dbc_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Cursor handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ ClientData clientData; /* Cursor handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *dbccmds[] = {
+#if CONFIG_TEST
+ "pget",
+#endif
"close",
"del",
"dup",
@@ -51,6 +54,9 @@ dbc_Cmd(clientData, interp, objc, objv)
NULL
};
enum dbccmds {
+#if CONFIG_TEST
+ DBCPGET,
+#endif
DBCCLOSE,
DBCDELETE,
DBCDUP,
@@ -87,6 +93,11 @@ dbc_Cmd(clientData, interp, objc, objv)
TCL_EXACT, &cmdindex) != TCL_OK)
return (IS_HELP(objv[1]));
switch ((enum dbccmds)cmdindex) {
+#if CONFIG_TEST
+ case DBCPGET:
+ result = tcl_DbcGet(interp, objc, objv, dbc, 1);
+ break;
+#endif
case DBCCLOSE:
/*
* No args for this. Error if there are some.
@@ -97,7 +108,8 @@ dbc_Cmd(clientData, interp, objc, objv)
}
_debug_check();
ret = dbc->c_close(dbc);
- result = _ReturnSetup(interp, ret, "dbc close");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "dbc close");
if (result == TCL_OK) {
(void)Tcl_DeleteCommand(interp, dbip->i_name);
_DeleteInfo(dbip);
@@ -113,13 +125,14 @@ dbc_Cmd(clientData, interp, objc, objv)
}
_debug_check();
ret = dbc->c_del(dbc, 0);
- result = _ReturnSetup(interp, ret, "dbc delete");
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBCDEL(ret),
+ "dbc delete");
break;
case DBCDUP:
result = tcl_DbcDup(interp, objc, objv, dbc);
break;
case DBCGET:
- result = tcl_DbcGet(interp, objc, objv, dbc);
+ result = tcl_DbcGet(interp, objc, objv, dbc, 0);
break;
case DBCPUT:
result = tcl_DbcPut(interp, objc, objv, dbc);
@@ -139,14 +152,26 @@ tcl_DbcPut(interp, objc, objv, dbc)
DBC *dbc; /* Cursor pointer */
{
static char *dbcutopts[] = {
- "-after", "-before", "-current",
- "-keyfirst", "-keylast", "-nodupdata",
+#if CONFIG_TEST
+ "-nodupdata",
+#endif
+ "-after",
+ "-before",
+ "-current",
+ "-keyfirst",
+ "-keylast",
"-partial",
NULL
};
enum dbcutopts {
- DBCPUT_AFTER, DBCPUT_BEFORE, DBCPUT_CURRENT,
- DBCPUT_KEYFIRST,DBCPUT_KEYLAST, DBCPUT_NODUPDATA,
+#if CONFIG_TEST
+ DBCPUT_NODUPDATA,
+#endif
+ DBCPUT_AFTER,
+ DBCPUT_BEFORE,
+ DBCPUT_CURRENT,
+ DBCPUT_KEYFIRST,
+ DBCPUT_KEYLAST,
DBCPUT_PART
};
DB *thisdbp;
@@ -154,12 +179,14 @@ tcl_DbcPut(interp, objc, objv, dbc)
DBTCL_INFO *dbcip, *dbip;
DBTYPE type;
Tcl_Obj **elemv, *res;
+ void *dtmp, *ktmp;
db_recno_t recno;
u_int32_t flag;
- int elemc, i, itmp, optindex, result, ret;
+ int elemc, freekey, freedata, i, optindex, result, ret;
result = TCL_OK;
flag = 0;
+ freekey = freedata = 0;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?-args? ?key?");
@@ -190,6 +217,12 @@ tcl_DbcPut(interp, objc, objv, dbc)
}
i++;
switch ((enum dbcutopts)optindex) {
+#if CONFIG_TEST
+ case DBCPUT_NODUPDATA:
+ FLAG_CHECK(flag);
+ flag = DB_NODUPDATA;
+ break;
+#endif
case DBCPUT_AFTER:
FLAG_CHECK(flag);
flag = DB_AFTER;
@@ -210,10 +243,6 @@ tcl_DbcPut(interp, objc, objv, dbc)
FLAG_CHECK(flag);
flag = DB_KEYLAST;
break;
- case DBCPUT_NODUPDATA:
- FLAG_CHECK(flag);
- flag = DB_NODUPDATA;
- break;
case DBCPUT_PART:
if (i > (objc - 2)) {
Tcl_WrongNumArgs(interp, 2, objv,
@@ -233,12 +262,10 @@ tcl_DbcPut(interp, objc, objv, dbc)
break;
}
data.flags |= DB_DBT_PARTIAL;
- result = Tcl_GetIntFromObj(interp, elemv[0], &itmp);
- data.doff = itmp;
+ result = _GetUInt32(interp, elemv[0], &data.doff);
if (result != TCL_OK)
break;
- result = Tcl_GetIntFromObj(interp, elemv[1], &itmp);
- data.dlen = itmp;
+ result = _GetUInt32(interp, elemv[1], &data.dlen);
/*
* NOTE: We don't check result here because all we'd
* do is break anyway, and we are doing that. If you
@@ -269,7 +296,7 @@ tcl_DbcPut(interp, objc, objv, dbc)
return (result);
}
thisdbp = dbip->i_dbp;
- type = thisdbp->get_type(thisdbp);
+ (void)thisdbp->get_type(thisdbp, &type);
}
/*
* When we get here, we better have:
@@ -300,29 +327,45 @@ tcl_DbcPut(interp, objc, objv, dbc)
goto out;
}
if (type == DB_RECNO || type == DB_QUEUE) {
- result = Tcl_GetIntFromObj(interp, objv[objc-2], &itmp);
- recno = itmp;
+ result = _GetUInt32(interp, objv[objc-2], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
return (result);
} else {
- key.data = Tcl_GetByteArrayFromObj(objv[objc-2], &itmp);
- key.size = itmp;
+ ret = _CopyObjBytes(interp, objv[objc-2], &ktmp,
+ &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBCPUT(ret), "dbc put");
+ return (result);
+ }
+ key.data = ktmp;
}
}
- data.data = Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- data.size = itmp;
+ ret = _CopyObjBytes(interp, objv[objc-1], &dtmp,
+ &data.size, &freedata);
+ data.data = dtmp;
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBCPUT(ret), "dbc put");
+ goto out;
+ }
_debug_check();
ret = dbc->c_put(dbc, &key, &data, flag);
- result = _ReturnSetup(interp, ret, "dbc put");
- if (ret == 0 && (flag == DB_AFTER || flag == DB_BEFORE)
- && type == DB_RECNO) {
- res = Tcl_NewIntObj(*(db_recno_t *)key.data);
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBCPUT(ret),
+ "dbc put");
+ if (ret == 0 &&
+ (flag == DB_AFTER || flag == DB_BEFORE) && type == DB_RECNO) {
+ res = Tcl_NewLongObj((long)*(db_recno_t *)key.data);
Tcl_SetObjResult(interp, res);
}
out:
+ if (freedata)
+ (void)__os_free(NULL, dtmp);
+ if (freekey)
+ (void)__os_free(NULL, ktmp);
return (result);
}
@@ -330,13 +373,20 @@ out:
* tcl_dbc_get --
*/
static int
-tcl_DbcGet(interp, objc, objv, dbc)
+tcl_DbcGet(interp, objc, objv, dbc, ispget)
Tcl_Interp *interp; /* Interpreter */
int objc; /* How many arguments? */
Tcl_Obj *CONST objv[]; /* The argument objects */
DBC *dbc; /* Cursor pointer */
+ int ispget; /* 1 for pget, 0 for get */
{
static char *dbcgetopts[] = {
+#if CONFIG_TEST
+ "-dirty",
+ "-get_both_range",
+ "-multi",
+ "-multi_key",
+#endif
"-current",
"-first",
"-get_both",
@@ -356,6 +406,12 @@ tcl_DbcGet(interp, objc, objv, dbc)
NULL
};
enum dbcgetopts {
+#if CONFIG_TEST
+ DBCGET_DIRTY,
+ DBCGET_BOTH_RANGE,
+ DBCGET_MULTI,
+ DBCGET_MULTI_KEY,
+#endif
DBCGET_CURRENT,
DBCGET_FIRST,
DBCGET_BOTH,
@@ -374,16 +430,18 @@ tcl_DbcGet(interp, objc, objv, dbc)
DBCGET_SETRECNO
};
DB *thisdbp;
- DBT key, data;
+ DBT key, data, pdata;
DBTCL_INFO *dbcip, *dbip;
- DBTYPE type;
+ DBTYPE ptype, type;
Tcl_Obj **elemv, *myobj, *retlist;
- db_recno_t recno;
- u_int32_t flag;
- int elemc, i, itmp, optindex, result, ret;
+ void *dtmp, *ktmp;
+ db_recno_t precno, recno;
+ u_int32_t flag, op;
+ int bufsize, elemc, freekey, freedata, i, optindex, result, ret;
result = TCL_OK;
flag = 0;
+ freekey = freedata = 0;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?-args? ?key?");
@@ -413,63 +471,101 @@ tcl_DbcGet(interp, objc, objv, dbc)
}
i++;
switch ((enum dbcgetopts)optindex) {
+#if CONFIG_TEST
+ case DBCGET_DIRTY:
+ flag |= DB_DIRTY_READ;
+ break;
+ case DBCGET_BOTH_RANGE:
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
+ flag |= DB_GET_BOTH_RANGE;
+ break;
+ case DBCGET_MULTI:
+ flag |= DB_MULTIPLE;
+ result = Tcl_GetIntFromObj(interp, objv[i], &bufsize);
+ if (result != TCL_OK)
+ goto out;
+ i++;
+ break;
+ case DBCGET_MULTI_KEY:
+ flag |= DB_MULTIPLE_KEY;
+ result = Tcl_GetIntFromObj(interp, objv[i], &bufsize);
+ if (result != TCL_OK)
+ goto out;
+ i++;
+ break;
+#endif
case DBCGET_RMW:
flag |= DB_RMW;
break;
case DBCGET_CURRENT:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_CURRENT;
break;
case DBCGET_FIRST:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_FIRST;
break;
case DBCGET_LAST:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_LAST;
break;
case DBCGET_NEXT:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_NEXT;
break;
case DBCGET_PREV:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_PREV;
break;
case DBCGET_PREVNODUP:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_PREV_NODUP;
break;
case DBCGET_NEXTNODUP:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_NEXT_NODUP;
break;
case DBCGET_NEXTDUP:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_NEXT_DUP;
break;
case DBCGET_BOTH:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_GET_BOTH;
break;
case DBCGET_RECNO:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_GET_RECNO;
break;
case DBCGET_JOIN:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_JOIN_ITEM;
break;
case DBCGET_SET:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_SET;
break;
case DBCGET_SETRANGE:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_SET_RANGE;
break;
case DBCGET_SETRECNO:
- FLAG_CHECK2(flag, DB_RMW);
+ FLAG_CHECK2(flag,
+ DB_RMW|DB_MULTIPLE|DB_MULTIPLE_KEY|DB_DIRTY_READ);
flag |= DB_SET_RECNO;
break;
case DBCGET_PART:
@@ -491,12 +587,10 @@ tcl_DbcGet(interp, objc, objv, dbc)
break;
}
data.flags |= DB_DBT_PARTIAL;
- result = Tcl_GetIntFromObj(interp, elemv[0], &itmp);
- data.doff = itmp;
+ result = _GetUInt32(interp, elemv[0], &data.doff);
if (result != TCL_OK)
break;
- result = Tcl_GetIntFromObj(interp, elemv[1], &itmp);
- data.dlen = itmp;
+ result = _GetUInt32(interp, elemv[1], &data.dlen);
/*
* NOTE: We don't check result here because all we'd
* do is break anyway, and we are doing that. If you
@@ -518,9 +612,10 @@ tcl_DbcGet(interp, objc, objv, dbc)
* a string.
*/
dbcip = _PtrToInfo(dbc);
- if (dbcip == NULL)
+ if (dbcip == NULL) {
type = DB_UNKNOWN;
- else {
+ ptype = DB_UNKNOWN;
+ } else {
dbip = dbcip->i_parent;
if (dbip == NULL) {
Tcl_SetResult(interp, "Cursor without parent database",
@@ -529,15 +624,25 @@ tcl_DbcGet(interp, objc, objv, dbc)
goto out;
}
thisdbp = dbip->i_dbp;
- type = thisdbp->get_type(thisdbp);
+ (void)thisdbp->get_type(thisdbp, &type);
+ if (ispget && thisdbp->s_primary != NULL)
+ (void)thisdbp->
+ s_primary->get_type(thisdbp->s_primary, &ptype);
+ else
+ ptype = DB_UNKNOWN;
}
/*
* When we get here, we better have:
- * 2 args, key and data if GET_BOTH was specified.
+ * 2 args, key and data if GET_BOTH/GET_BOTH_RANGE was specified.
* 1 arg if -set, -set_range or -set_recno
* 0 in all other cases.
*/
- if ((flag & DB_OPFLAGS_MASK) == DB_GET_BOTH) {
+ op = flag & DB_OPFLAGS_MASK;
+ switch (op) {
+ case DB_GET_BOTH:
+#if CONFIG_TEST
+ case DB_GET_BOTH_RANGE:
+#endif
if (i != (objc - 2)) {
Tcl_WrongNumArgs(interp, 2, objv,
"?-args? -get_both key data");
@@ -545,82 +650,158 @@ tcl_DbcGet(interp, objc, objv, dbc)
goto out;
} else {
if (type == DB_RECNO || type == DB_QUEUE) {
- result = Tcl_GetIntFromObj(
- interp, objv[objc-2], &itmp);
- recno = itmp;
+ result = _GetUInt32(
+ interp, objv[objc-2], &recno);
if (result == TCL_OK) {
key.data = &recno;
key.size = sizeof(db_recno_t);
} else
goto out;
} else {
- key.data = Tcl_GetByteArrayFromObj(
- objv[objc - 2], &itmp);
- key.size = itmp;
+ /*
+ * Some get calls (SET_*) can change the
+ * key pointers. So, we need to store
+ * the allocated key space in a tmp.
+ */
+ ret = _CopyObjBytes(interp, objv[objc-2],
+ &ktmp, &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBCGET(ret), "dbc get");
+ return (result);
+ }
+ key.data = ktmp;
+ }
+ if (ptype == DB_RECNO || ptype == DB_QUEUE) {
+ result = _GetUInt32(
+ interp, objv[objc-1], &precno);
+ if (result == TCL_OK) {
+ data.data = &precno;
+ data.size = sizeof(db_recno_t);
+ } else
+ goto out;
+ } else {
+ ret = _CopyObjBytes(interp, objv[objc-1],
+ &dtmp, &data.size, &freedata);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBCGET(ret), "dbc get");
+ goto out;
+ }
+ data.data = dtmp;
}
- data.data =
- Tcl_GetByteArrayFromObj(objv[objc - 1], &itmp);
- data.size = itmp;
}
- } else if ((flag & DB_OPFLAGS_MASK) == DB_SET ||
- (flag & DB_OPFLAGS_MASK) == DB_SET_RANGE ||
- (flag & DB_OPFLAGS_MASK) == DB_SET_RECNO) {
+ break;
+ case DB_SET:
+ case DB_SET_RANGE:
+ case DB_SET_RECNO:
if (i != (objc - 1)) {
Tcl_WrongNumArgs(interp, 2, objv, "?-args? key");
result = TCL_ERROR;
goto out;
}
- data.flags |= DB_DBT_MALLOC;
- if ((flag & DB_OPFLAGS_MASK) == DB_SET_RECNO ||
+ if (flag & (DB_MULTIPLE|DB_MULTIPLE_KEY)) {
+ (void)__os_malloc(NULL, bufsize, &data.data);
+ data.ulen = bufsize;
+ data.flags |= DB_DBT_USERMEM;
+ } else
+ data.flags |= DB_DBT_MALLOC;
+ if (op == DB_SET_RECNO ||
type == DB_RECNO || type == DB_QUEUE) {
- result = Tcl_GetIntFromObj(interp,
- objv[objc - 1], (int *)&recno);
+ result = _GetUInt32(interp, objv[objc - 1], &recno);
key.data = &recno;
key.size = sizeof(db_recno_t);
} else {
- key.data =
- Tcl_GetByteArrayFromObj(objv[objc - 1], &itmp);
- key.size = itmp;
+ /*
+ * Some get calls (SET_*) can change the
+ * key pointers. So, we need to store
+ * the allocated key space in a tmp.
+ */
+ ret = _CopyObjBytes(interp, objv[objc-1],
+ &ktmp, &key.size, &freekey);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_DBCGET(ret), "dbc get");
+ return (result);
+ }
+ key.data = ktmp;
}
- } else {
+ break;
+ default:
if (i != objc) {
Tcl_WrongNumArgs(interp, 2, objv, "?-args?");
result = TCL_ERROR;
goto out;
}
key.flags |= DB_DBT_MALLOC;
- data.flags |= DB_DBT_MALLOC;
+ if (flag & (DB_MULTIPLE|DB_MULTIPLE_KEY)) {
+ (void)__os_malloc(NULL, bufsize, &data.data);
+ data.ulen = bufsize;
+ data.flags |= DB_DBT_USERMEM;
+ } else
+ data.flags |= DB_DBT_MALLOC;
}
_debug_check();
- ret = dbc->c_get(dbc, &key, &data, flag);
- result = _ReturnSetup(interp, ret, "dbc get");
+ memset(&pdata, 0, sizeof(DBT));
+ if (ispget) {
+ F_SET(&pdata, DB_DBT_MALLOC);
+ ret = dbc->c_pget(dbc, &key, &data, &pdata, flag);
+ } else
+ ret = dbc->c_get(dbc, &key, &data, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_DBCGET(ret), "dbc get");
if (result == TCL_ERROR)
goto out;
retlist = Tcl_NewListObj(0, NULL);
if (ret == DB_NOTFOUND)
goto out1;
- if ((flag & DB_OPFLAGS_MASK) == DB_GET_RECNO) {
+ if (op == DB_GET_RECNO) {
recno = *((db_recno_t *)data.data);
- myobj = Tcl_NewIntObj((int)recno);
+ myobj = Tcl_NewLongObj((long)recno);
result = Tcl_ListObjAppendElement(interp, retlist, myobj);
} else {
- if ((type == DB_RECNO || type == DB_QUEUE) && key.data != NULL)
- result = _SetListRecnoElem(interp, retlist,
- *(db_recno_t *)key.data, data.data, data.size);
- else
- result = _SetListElem(interp, retlist,
- key.data, key.size, data.data, data.size);
+ if (flag & (DB_MULTIPLE|DB_MULTIPLE_KEY))
+ result = _SetMultiList(interp,
+ retlist, &key, &data, type, flag);
+ else if ((type == DB_RECNO || type == DB_QUEUE) &&
+ key.data != NULL) {
+ if (ispget)
+ result = _Set3DBTList(interp, retlist, &key, 1,
+ &data,
+ (ptype == DB_RECNO || ptype == DB_QUEUE),
+ &pdata);
+ else
+ result = _SetListRecnoElem(interp, retlist,
+ *(db_recno_t *)key.data,
+ data.data, data.size);
+ } else {
+ if (ispget)
+ result = _Set3DBTList(interp, retlist, &key, 0,
+ &data,
+ (ptype == DB_RECNO || ptype == DB_QUEUE),
+ &pdata);
+ else
+ result = _SetListElem(interp, retlist,
+ key.data, key.size, data.data, data.size);
+ }
}
- if (key.flags & DB_DBT_MALLOC)
- __os_free(key.data, key.size);
- if (data.flags & DB_DBT_MALLOC)
- __os_free(data.data, data.size);
+ if (key.data != NULL && F_ISSET(&key, DB_DBT_MALLOC))
+ __os_ufree(dbc->dbp->dbenv, key.data);
+ if (data.data != NULL && F_ISSET(&data, DB_DBT_MALLOC))
+ __os_ufree(dbc->dbp->dbenv, data.data);
+ if (pdata.data != NULL && F_ISSET(&pdata, DB_DBT_MALLOC))
+ __os_ufree(dbc->dbp->dbenv, pdata.data);
out1:
if (result == TCL_OK)
Tcl_SetObjResult(interp, retlist);
out:
+ if (data.data != NULL && flag & (DB_MULTIPLE|DB_MULTIPLE_KEY))
+ __os_free(dbc->dbp->dbenv, data.data);
+ if (freedata)
+ (void)__os_free(NULL, dtmp);
+ if (freekey)
+ (void)__os_free(NULL, ktmp);
return (result);
}
@@ -642,7 +823,6 @@ tcl_DbcDup(interp, objc, objv, dbc)
enum dbcdupopts {
DBCDUP_POS
};
- DB *thisdbp;
DBC *newdbc;
DBTCL_INFO *dbcip, *newdbcip, *dbip;
Tcl_Obj *res;
@@ -709,7 +889,6 @@ tcl_DbcDup(interp, objc, objv, dbc)
result = TCL_ERROR;
goto out;
}
- thisdbp = dbip->i_dbp;
}
/*
* Now duplicate the cursor. If successful, we need to create
@@ -731,7 +910,8 @@ tcl_DbcDup(interp, objc, objv, dbc)
_SetInfoData(newdbcip, newdbc);
Tcl_SetObjResult(interp, res);
} else {
- result = _ReturnSetup(interp, ret, "db dup");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db dup");
_DeleteInfo(newdbcip);
}
} else {
diff --git a/bdb/tcl/tcl_env.c b/bdb/tcl/tcl_env.c
index cb7b0d9744d..cdf4890e9fc 100644
--- a/bdb/tcl/tcl_env.c
+++ b/bdb/tcl/tcl_env.c
@@ -1,30 +1,33 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_env.c,v 11.33 2001/01/11 18:19:55 bostic Exp $";
+static const char revid[] = "$Id: tcl_env.c,v 11.84 2002/08/06 06:21:03 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
+#include <string.h>
#include <tcl.h>
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/tcl_db.h"
/*
* Prototypes for procedures defined later in this file:
*/
-static void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
+static void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
+static int env_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+static int env_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
/*
* PUBLIC: int env_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
@@ -34,86 +37,124 @@ static void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
*/
int
env_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Env handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ ClientData clientData; /* Env handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *envcmds[] = {
- "close",
+#if CONFIG_TEST
+ "attributes",
"lock_detect",
"lock_id",
+ "lock_id_free",
+ "lock_id_set",
"lock_get",
"lock_stat",
+ "lock_timeout",
"lock_vec",
"log_archive",
"log_compare",
+ "log_cursor",
"log_file",
"log_flush",
"log_get",
"log_put",
- "log_register",
"log_stat",
- "log_unregister",
"mpool",
"mpool_stat",
"mpool_sync",
"mpool_trickle",
"mutex",
-#if CONFIG_TEST
+ "rep_elect",
+ "rep_flush",
+ "rep_limit",
+ "rep_process_message",
+ "rep_request",
+ "rep_start",
+ "rep_stat",
+ "rpcid",
"test",
-#endif
- "txn",
"txn_checkpoint",
+ "txn_id_set",
+ "txn_recover",
"txn_stat",
+ "txn_timeout",
"verbose",
+#endif
+ "close",
+ "dbremove",
+ "dbrename",
+ "txn",
NULL
};
enum envcmds {
- ENVCLOSE,
+#if CONFIG_TEST
+ ENVATTR,
ENVLKDETECT,
ENVLKID,
+ ENVLKFREEID,
+ ENVLKSETID,
ENVLKGET,
ENVLKSTAT,
+ ENVLKTIMEOUT,
ENVLKVEC,
ENVLOGARCH,
ENVLOGCMP,
+ ENVLOGCURSOR,
ENVLOGFILE,
ENVLOGFLUSH,
ENVLOGGET,
ENVLOGPUT,
- ENVLOGREG,
ENVLOGSTAT,
- ENVLOGUNREG,
ENVMP,
ENVMPSTAT,
ENVMPSYNC,
ENVTRICKLE,
ENVMUTEX,
-#if CONFIG_TEST
+ ENVREPELECT,
+ ENVREPFLUSH,
+ ENVREPLIMIT,
+ ENVREPPROCMESS,
+ ENVREPREQUEST,
+ ENVREPSTART,
+ ENVREPSTAT,
+ ENVRPCID,
ENVTEST,
-#endif
- ENVTXN,
ENVTXNCKP,
+ ENVTXNSETID,
+ ENVTXNRECOVER,
ENVTXNSTAT,
- ENVVERB
+ ENVTXNTIMEOUT,
+ ENVVERB,
+#endif
+ ENVCLOSE,
+ ENVDBREMOVE,
+ ENVDBRENAME,
+ ENVTXN
};
- DBTCL_INFO *envip;
- DB_ENV *envp;
+ DBTCL_INFO *envip, *logcip;
+ DB_ENV *dbenv;
+ DB_LOGC *logc;
Tcl_Obj *res;
- u_int32_t newval;
+ char newname[MSG_SIZE];
int cmdindex, result, ret;
+ u_int32_t newval;
+#if CONFIG_TEST
+ u_int32_t otherval;
+#endif
Tcl_ResetResult(interp);
- envp = (DB_ENV *)clientData;
- envip = _PtrToInfo((void *)envp);
+ dbenv = (DB_ENV *)clientData;
+ envip = _PtrToInfo((void *)dbenv);
result = TCL_OK;
+ memset(newname, 0, MSG_SIZE);
if (objc <= 1) {
Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
return (TCL_ERROR);
}
- if (envp == NULL) {
+ if (dbenv == NULL) {
Tcl_SetResult(interp, "NULL env pointer", TCL_STATIC);
return (TCL_ERROR);
}
@@ -131,33 +172,15 @@ env_Cmd(clientData, interp, objc, objv)
return (IS_HELP(objv[1]));
res = NULL;
switch ((enum envcmds)cmdindex) {
- case ENVCLOSE:
- /*
- * No args for this. Error if there are some.
- */
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return (TCL_ERROR);
- }
- /*
- * Any transactions will be aborted, and an mpools
- * closed automatically. We must delete any txn
- * and mp widgets we have here too for this env.
- * NOTE: envip is freed when we come back from
- * this function. Set it to NULL to make sure no
- * one tries to use it later.
- */
- _EnvInfoDelete(interp, envip);
- envip = NULL;
- _debug_check();
- ret = envp->close(envp, 0);
- result = _ReturnSetup(interp, ret, "env close");
- break;
+#if CONFIG_TEST
case ENVLKDETECT:
- result = tcl_LockDetect(interp, objc, objv, envp);
+ result = tcl_LockDetect(interp, objc, objv, dbenv);
break;
case ENVLKSTAT:
- result = tcl_LockStat(interp, objc, objv, envp);
+ result = tcl_LockStat(interp, objc, objv, dbenv);
+ break;
+ case ENVLKTIMEOUT:
+ result = tcl_LockTimeout(interp, objc, objv, dbenv);
break;
case ENVLKID:
/*
@@ -168,73 +191,180 @@ env_Cmd(clientData, interp, objc, objv)
return (TCL_ERROR);
}
_debug_check();
- ret = lock_id(envp, &newval);
- result = _ReturnSetup(interp, ret, "lock_id");
+ ret = dbenv->lock_id(dbenv, &newval);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock_id");
if (result == TCL_OK)
- res = Tcl_NewIntObj((int)newval);
+ res = Tcl_NewLongObj((long)newval);
+ break;
+ case ENVLKFREEID:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
+ if (result != TCL_OK)
+ return (result);
+ ret = dbenv->lock_id_free(dbenv, newval);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock id_free");
+ break;
+ case ENVLKSETID:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 4, objv, "current max");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
+ if (result != TCL_OK)
+ return (result);
+ result = Tcl_GetLongFromObj(interp, objv[3], (long *)&otherval);
+ if (result != TCL_OK)
+ return (result);
+ ret = dbenv->lock_id_set(dbenv, newval, otherval);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock id_free");
break;
case ENVLKGET:
- result = tcl_LockGet(interp, objc, objv, envp);
+ result = tcl_LockGet(interp, objc, objv, dbenv);
break;
case ENVLKVEC:
- result = tcl_LockVec(interp, objc, objv, envp);
+ result = tcl_LockVec(interp, objc, objv, dbenv);
break;
case ENVLOGARCH:
- result = tcl_LogArchive(interp, objc, objv, envp);
+ result = tcl_LogArchive(interp, objc, objv, dbenv);
break;
case ENVLOGCMP:
result = tcl_LogCompare(interp, objc, objv);
break;
+ case ENVLOGCURSOR:
+ snprintf(newname, sizeof(newname),
+ "%s.logc%d", envip->i_name, envip->i_envlogcid);
+ logcip = _NewInfo(interp, NULL, newname, I_LOGC);
+ if (logcip != NULL) {
+ ret = dbenv->log_cursor(dbenv, &logc, 0);
+ if (ret == 0) {
+ result = TCL_OK;
+ envip->i_envlogcid++;
+ /*
+ * We do NOT want to set i_parent to
+ * envip here because log cursors are
+ * not "tied" to the env. That is, they
+ * are NOT closed if the env is closed.
+ */
+ Tcl_CreateObjCommand(interp, newname,
+ (Tcl_ObjCmdProc *)logc_Cmd,
+ (ClientData)logc, NULL);
+ res =
+ Tcl_NewStringObj(newname, strlen(newname));
+ _SetInfoData(logcip, logc);
+ } else {
+ _DeleteInfo(logcip);
+ result = _ErrorSetup(interp, ret, "log cursor");
+ }
+ } else {
+ Tcl_SetResult(interp,
+ "Could not set up info", TCL_STATIC);
+ result = TCL_ERROR;
+ }
+ break;
case ENVLOGFILE:
- result = tcl_LogFile(interp, objc, objv, envp);
+ result = tcl_LogFile(interp, objc, objv, dbenv);
break;
case ENVLOGFLUSH:
- result = tcl_LogFlush(interp, objc, objv, envp);
+ result = tcl_LogFlush(interp, objc, objv, dbenv);
break;
case ENVLOGGET:
- result = tcl_LogGet(interp, objc, objv, envp);
+ result = tcl_LogGet(interp, objc, objv, dbenv);
break;
case ENVLOGPUT:
- result = tcl_LogPut(interp, objc, objv, envp);
- break;
- case ENVLOGREG:
- result = tcl_LogRegister(interp, objc, objv, envp);
- break;
- case ENVLOGUNREG:
- result = tcl_LogUnregister(interp, objc, objv, envp);
+ result = tcl_LogPut(interp, objc, objv, dbenv);
break;
case ENVLOGSTAT:
- result = tcl_LogStat(interp, objc, objv, envp);
+ result = tcl_LogStat(interp, objc, objv, dbenv);
break;
case ENVMPSTAT:
- result = tcl_MpStat(interp, objc, objv, envp);
+ result = tcl_MpStat(interp, objc, objv, dbenv);
break;
case ENVMPSYNC:
- result = tcl_MpSync(interp, objc, objv, envp);
+ result = tcl_MpSync(interp, objc, objv, dbenv);
break;
case ENVTRICKLE:
- result = tcl_MpTrickle(interp, objc, objv, envp);
+ result = tcl_MpTrickle(interp, objc, objv, dbenv);
break;
case ENVMP:
- result = tcl_Mp(interp, objc, objv, envp, envip);
+ result = tcl_Mp(interp, objc, objv, dbenv, envip);
+ break;
+ case ENVREPELECT:
+ result = tcl_RepElect(interp, objc, objv, dbenv);
+ break;
+ case ENVREPFLUSH:
+ result = tcl_RepFlush(interp, objc, objv, dbenv);
+ break;
+ case ENVREPLIMIT:
+ result = tcl_RepLimit(interp, objc, objv, dbenv);
+ break;
+ case ENVREPPROCMESS:
+ result = tcl_RepProcessMessage(interp, objc, objv, dbenv);
+ break;
+ case ENVREPREQUEST:
+ result = tcl_RepRequest(interp, objc, objv, dbenv);
+ break;
+ case ENVREPSTART:
+ result = tcl_RepStart(interp, objc, objv, dbenv);
+ break;
+ case ENVREPSTAT:
+ result = tcl_RepStat(interp, objc, objv, dbenv);
+ break;
+ case ENVRPCID:
+ /*
+ * No args for this. Error if there are some.
+ */
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ /*
+ * !!! Retrieve the client ID from the dbp handle directly.
+ * This is for testing purposes only. It is dbp-private data.
+ */
+ res = Tcl_NewLongObj(dbenv->cl_id);
break;
case ENVTXNCKP:
- result = tcl_TxnCheckpoint(interp, objc, objv, envp);
+ result = tcl_TxnCheckpoint(interp, objc, objv, dbenv);
+ break;
+ case ENVTXNSETID:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 4, objv, "current max");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
+ if (result != TCL_OK)
+ return (result);
+ result = Tcl_GetLongFromObj(interp, objv[3], (long *)&otherval);
+ if (result != TCL_OK)
+ return (result);
+ ret = dbenv->txn_id_set(dbenv, newval, otherval);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock id_free");
+ break;
+ case ENVTXNRECOVER:
+ result = tcl_TxnRecover(interp, objc, objv, dbenv, envip);
break;
case ENVTXNSTAT:
- result = tcl_TxnStat(interp, objc, objv, envp);
+ result = tcl_TxnStat(interp, objc, objv, dbenv);
break;
- case ENVTXN:
- result = tcl_Txn(interp, objc, objv, envp, envip);
+ case ENVTXNTIMEOUT:
+ result = tcl_TxnTimeout(interp, objc, objv, dbenv);
break;
case ENVMUTEX:
- result = tcl_Mutex(interp, objc, objv, envp, envip);
+ result = tcl_Mutex(interp, objc, objv, dbenv, envip);
+ break;
+ case ENVATTR:
+ result = tcl_EnvAttr(interp, objc, objv, dbenv);
break;
-#if CONFIG_TEST
case ENVTEST:
- result = tcl_EnvTest(interp, objc, objv, envp);
+ result = tcl_EnvTest(interp, objc, objv, dbenv);
break;
-#endif
case ENVVERB:
/*
* Two args for this. Error if different.
@@ -243,7 +373,40 @@ env_Cmd(clientData, interp, objc, objv)
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return (TCL_ERROR);
}
- result = tcl_EnvVerbose(interp, envp, objv[2], objv[3]);
+ result = tcl_EnvVerbose(interp, dbenv, objv[2], objv[3]);
+ break;
+#endif
+ case ENVCLOSE:
+ /*
+ * No args for this. Error if there are some.
+ */
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ /*
+ * Any transactions will be aborted, and an mpools
+ * closed automatically. We must delete any txn
+ * and mp widgets we have here too for this env.
+ * NOTE: envip is freed when we come back from
+ * this function. Set it to NULL to make sure no
+ * one tries to use it later.
+ */
+ _debug_check();
+ ret = dbenv->close(dbenv, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env close");
+ _EnvInfoDelete(interp, envip);
+ envip = NULL;
+ break;
+ case ENVDBREMOVE:
+ result = env_DbRemove(interp, objc, objv, dbenv);
+ break;
+ case ENVDBRENAME:
+ result = env_DbRename(interp, objc, objv, dbenv);
+ break;
+ case ENVTXN:
+ result = tcl_Txn(interp, objc, objv, dbenv, envip);
break;
}
/*
@@ -262,44 +425,56 @@ env_Cmd(clientData, interp, objc, objv)
* tcl_EnvRemove --
*/
int
-tcl_EnvRemove(interp, objc, objv, envp, envip)
+tcl_EnvRemove(interp, objc, objv, dbenv, envip)
Tcl_Interp *interp; /* Interpreter */
int objc; /* How many arguments? */
Tcl_Obj *CONST objv[]; /* The argument objects */
- DB_ENV *envp; /* Env pointer */
+ DB_ENV *dbenv; /* Env pointer */
DBTCL_INFO *envip; /* Info pointer */
{
static char *envremopts[] = {
+#if CONFIG_TEST
+ "-overwrite",
+ "-server",
+#endif
"-data_dir",
+ "-encryptaes",
+ "-encryptany",
"-force",
"-home",
"-log_dir",
- "-server",
"-tmp_dir",
"-use_environ",
"-use_environ_root",
NULL
};
enum envremopts {
+#if CONFIG_TEST
+ ENVREM_OVERWRITE,
+ ENVREM_SERVER,
+#endif
ENVREM_DATADIR,
+ ENVREM_ENCRYPT_AES,
+ ENVREM_ENCRYPT_ANY,
ENVREM_FORCE,
ENVREM_HOME,
ENVREM_LOGDIR,
- ENVREM_SERVER,
ENVREM_TMPDIR,
ENVREM_USE_ENVIRON,
ENVREM_USE_ENVIRON_ROOT
};
DB_ENV *e;
- u_int32_t cflag, flag, forceflag;
+ u_int32_t cflag, enc_flag, flag, forceflag, sflag;
int i, optindex, result, ret;
- char *datadir, *home, *logdir, *server, *tmpdir;
+ char *datadir, *home, *logdir, *passwd, *server, *tmpdir;
result = TCL_OK;
- cflag = flag = forceflag = 0;
+ cflag = flag = forceflag = sflag = 0;
home = NULL;
+ passwd = NULL;
datadir = logdir = tmpdir = NULL;
server = NULL;
+ enc_flag = 0;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?args?");
@@ -315,30 +490,59 @@ tcl_EnvRemove(interp, objc, objv, envp, envip)
}
i++;
switch ((enum envremopts)optindex) {
- case ENVREM_FORCE:
- forceflag |= DB_FORCE;
+#if CONFIG_TEST
+ case ENVREM_SERVER:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-server name?");
+ result = TCL_ERROR;
+ break;
+ }
+ server = Tcl_GetStringFromObj(objv[i++], NULL);
+ cflag = DB_CLIENT;
break;
- case ENVREM_HOME:
+#endif
+ case ENVREM_ENCRYPT_AES:
/* Make sure we have an arg to check against! */
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "?-home dir?");
+ "?-encryptaes passwd?");
result = TCL_ERROR;
break;
}
- home = Tcl_GetStringFromObj(objv[i++], NULL);
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = DB_ENCRYPT_AES;
break;
- case ENVREM_SERVER:
+ case ENVREM_ENCRYPT_ANY:
/* Make sure we have an arg to check against! */
if (i >= objc) {
Tcl_WrongNumArgs(interp, 2, objv,
- "?-server name?");
+ "?-encryptany passwd?");
result = TCL_ERROR;
break;
}
- server = Tcl_GetStringFromObj(objv[i++], NULL);
- cflag = DB_CLIENT;
+ passwd = Tcl_GetStringFromObj(objv[i++], NULL);
+ enc_flag = 0;
+ break;
+ case ENVREM_FORCE:
+ forceflag |= DB_FORCE;
+ break;
+ case ENVREM_HOME:
+ /* Make sure we have an arg to check against! */
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-home dir?");
+ result = TCL_ERROR;
+ break;
+ }
+ home = Tcl_GetStringFromObj(objv[i++], NULL);
+ break;
+#if CONFIG_TEST
+ case ENVREM_OVERWRITE:
+ sflag |= DB_OVERWRITE;
break;
+#endif
case ENVREM_USE_ENVIRON:
flag |= DB_USE_ENVIRON;
break;
@@ -382,38 +586,56 @@ tcl_EnvRemove(interp, objc, objv, envp, envip)
}
/*
- * If envp is NULL, we don't have an open env and we need to open
+ * If dbenv is NULL, we don't have an open env and we need to open
* one of the user. Don't bother with the info stuff.
*/
- if (envp == NULL) {
+ if (dbenv == NULL) {
if ((ret = db_env_create(&e, cflag)) != 0) {
- result = _ReturnSetup(interp, ret, "db_env_create");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "db_env_create");
goto error;
}
if (server != NULL) {
- ret = e->set_server(e, server, 0, 0, 0);
- result = _ReturnSetup(interp, ret, "set_server");
+ _debug_check();
+ ret = e->set_rpc_server(e, NULL, server, 0, 0, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_rpc_server");
if (result != TCL_OK)
goto error;
}
if (datadir != NULL) {
_debug_check();
ret = e->set_data_dir(e, datadir);
- result = _ReturnSetup(interp, ret, "set_data_dir");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_data_dir");
if (result != TCL_OK)
goto error;
}
if (logdir != NULL) {
_debug_check();
ret = e->set_lg_dir(e, logdir);
- result = _ReturnSetup(interp, ret, "set_log_dir");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_log_dir");
if (result != TCL_OK)
goto error;
}
if (tmpdir != NULL) {
_debug_check();
ret = e->set_tmp_dir(e, tmpdir);
- result = _ReturnSetup(interp, ret, "set_tmp_dir");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_tmp_dir");
+ if (result != TCL_OK)
+ goto error;
+ }
+ if (passwd != NULL) {
+ ret = e->set_encrypt(e, passwd, enc_flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_encrypt");
+ }
+ if (sflag != 0 && (ret = e->set_flags(e, sflag, 1)) != 0) {
+ _debug_check();
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_flags");
if (result != TCL_OK)
goto error;
}
@@ -425,7 +647,7 @@ tcl_EnvRemove(interp, objc, objv, envp, envip)
*/
_EnvInfoDelete(interp, envip);
envip = NULL;
- e = envp;
+ e = dbenv;
}
flag |= forceflag;
@@ -435,7 +657,8 @@ tcl_EnvRemove(interp, objc, objv, envp, envip)
*/
_debug_check();
ret = e->remove(e, home, flag);
- result = _ReturnSetup(interp, ret, "env remove");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env remove");
error:
return (result);
}
@@ -452,7 +675,7 @@ _EnvInfoDelete(interp, envip)
* any open subsystems in this env. We will:
* 1. Abort any transactions (which aborts any nested txns).
* 2. Close any mpools (which will put any pages itself).
- * 3. Put any locks.
+ * 3. Put any locks and close log cursors.
* 4. Close the error file.
*/
for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
@@ -461,6 +684,11 @@ _EnvInfoDelete(interp, envip)
* env. If so, remove its commands and info structure.
* We do not close/abort/whatever here, because we
* don't want to replicate DB behavior.
+ *
+ * NOTE: Only those types that can nest need to be
+ * itemized in the switch below. That is txns and mps.
+ * Other types like log cursors and locks will just
+ * get cleaned up here.
*/
if (p->i_parent == envip) {
switch (p->i_type) {
@@ -486,6 +714,7 @@ _EnvInfoDelete(interp, envip)
_DeleteInfo(envip);
}
+#if CONFIG_TEST
/*
* PUBLIC: int tcl_EnvVerbose __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *,
* PUBLIC: Tcl_Obj *));
@@ -493,9 +722,9 @@ _EnvInfoDelete(interp, envip)
* tcl_EnvVerbose --
*/
int
-tcl_EnvVerbose(interp, envp, which, onoff)
+tcl_EnvVerbose(interp, dbenv, which, onoff)
Tcl_Interp *interp; /* Interpreter */
- DB_ENV *envp; /* Env pointer */
+ DB_ENV *dbenv; /* Env pointer */
Tcl_Obj *which; /* Which subsystem */
Tcl_Obj *onoff; /* On or off */
{
@@ -503,6 +732,7 @@ tcl_EnvVerbose(interp, envp, which, onoff)
"chkpt",
"deadlock",
"recovery",
+ "rep",
"wait",
NULL
};
@@ -510,6 +740,7 @@ tcl_EnvVerbose(interp, envp, which, onoff)
ENVVERB_CHK,
ENVVERB_DEAD,
ENVVERB_REC,
+ ENVVERB_REP,
ENVVERB_WAIT
};
static char *verbonoff[] = {
@@ -538,6 +769,9 @@ tcl_EnvVerbose(interp, envp, which, onoff)
case ENVVERB_REC:
wh = DB_VERB_RECOVERY;
break;
+ case ENVVERB_REP:
+ wh = DB_VERB_REPLICATION;
+ break;
case ENVVERB_WAIT:
wh = DB_VERB_WAITSFOR;
break;
@@ -557,22 +791,107 @@ tcl_EnvVerbose(interp, envp, which, onoff)
default:
return (TCL_ERROR);
}
- ret = envp->set_verbose(envp, wh, on);
- return (_ReturnSetup(interp, ret, "env set verbose"));
+ ret = dbenv->set_verbose(dbenv, wh, on);
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env set verbose"));
}
+#endif
#if CONFIG_TEST
/*
+ * PUBLIC: int tcl_EnvAttr __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+ *
+ * tcl_EnvAttr --
+ * Return a list of the env's attributes
+ */
+int
+tcl_EnvAttr(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv; /* Env pointer */
+{
+ int result;
+ Tcl_Obj *myobj, *retlist;
+
+ result = TCL_OK;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ retlist = Tcl_NewListObj(0, NULL);
+ /*
+ * XXX
+ * We peek at the dbenv to determine what subsystems
+ * we have available in this env.
+ */
+ myobj = Tcl_NewStringObj("-home", strlen("-home"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ myobj = Tcl_NewStringObj(dbenv->db_home, strlen(dbenv->db_home));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ if (CDB_LOCKING(dbenv)) {
+ myobj = Tcl_NewStringObj("-cdb", strlen("-cdb"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ if (CRYPTO_ON(dbenv)) {
+ myobj = Tcl_NewStringObj("-crypto", strlen("-crypto"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ if (LOCKING_ON(dbenv)) {
+ myobj = Tcl_NewStringObj("-lock", strlen("-lock"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ if (LOGGING_ON(dbenv)) {
+ myobj = Tcl_NewStringObj("-log", strlen("-log"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ if (MPOOL_ON(dbenv)) {
+ myobj = Tcl_NewStringObj("-mpool", strlen("-mpool"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ if (RPC_ON(dbenv)) {
+ myobj = Tcl_NewStringObj("-rpc", strlen("-rpc"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ if (TXN_ON(dbenv)) {
+ myobj = Tcl_NewStringObj("-txn", strlen("-txn"));
+ if ((result = Tcl_ListObjAppendElement(interp,
+ retlist, myobj)) != TCL_OK)
+ goto err;
+ }
+ Tcl_SetObjResult(interp, retlist);
+err:
+ return (result);
+}
+
+/*
* PUBLIC: int tcl_EnvTest __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
*
* tcl_EnvTest --
*/
int
-tcl_EnvTest(interp, objc, objv, envp)
+tcl_EnvTest(interp, objc, objv, dbenv)
Tcl_Interp *interp; /* Interpreter */
int objc; /* How many arguments? */
Tcl_Obj *CONST objv[]; /* The argument objects */
- DB_ENV *envp; /* Env pointer */
+ DB_ENV *dbenv; /* Env pointer */
{
static char *envtestcmd[] = {
"abort",
@@ -584,29 +903,44 @@ tcl_EnvTest(interp, objc, objv, envp)
ENVTEST_COPY
};
static char *envtestat[] = {
+ "electinit",
+ "electsend",
+ "electvote1",
+ "electvote2",
+ "electwait1",
+ "electwait2",
"none",
+ "predestroy",
"preopen",
- "prerename",
+ "postdestroy",
"postlog",
"postlogmeta",
"postopen",
- "postrename",
"postsync",
+ "subdb_lock",
NULL
};
enum envtestat {
+ ENVTEST_ELECTINIT,
+ ENVTEST_ELECTSEND,
+ ENVTEST_ELECTVOTE1,
+ ENVTEST_ELECTVOTE2,
+ ENVTEST_ELECTWAIT1,
+ ENVTEST_ELECTWAIT2,
ENVTEST_NONE,
+ ENVTEST_PREDESTROY,
ENVTEST_PREOPEN,
- ENVTEST_PRERENAME,
+ ENVTEST_POSTDESTROY,
ENVTEST_POSTLOG,
ENVTEST_POSTLOGMETA,
ENVTEST_POSTOPEN,
- ENVTEST_POSTRENAME,
- ENVTEST_POSTSYNC
+ ENVTEST_POSTSYNC,
+ ENVTEST_SUBDB_LOCKS
};
int *loc, optindex, result, testval;
result = TCL_OK;
+ loc = NULL;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "abort|copy location");
@@ -623,10 +957,10 @@ tcl_EnvTest(interp, objc, objv, envp)
}
switch ((enum envtestcmd)optindex) {
case ENVTEST_ABORT:
- loc = &envp->test_abort;
+ loc = &dbenv->test_abort;
break;
case ENVTEST_COPY:
- loc = &envp->test_copy;
+ loc = &dbenv->test_copy;
break;
default:
Tcl_SetResult(interp, "Illegal store location", TCL_STATIC);
@@ -642,14 +976,38 @@ tcl_EnvTest(interp, objc, objv, envp)
return (result);
}
switch ((enum envtestat)optindex) {
+ case ENVTEST_ELECTINIT:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_ELECTINIT;
+ break;
+ case ENVTEST_ELECTSEND:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_ELECTSEND;
+ break;
+ case ENVTEST_ELECTVOTE1:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_ELECTVOTE1;
+ break;
+ case ENVTEST_ELECTVOTE2:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_ELECTVOTE2;
+ break;
+ case ENVTEST_ELECTWAIT1:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_ELECTWAIT1;
+ break;
+ case ENVTEST_ELECTWAIT2:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_ELECTWAIT2;
+ break;
case ENVTEST_NONE:
testval = 0;
break;
case ENVTEST_PREOPEN:
testval = DB_TEST_PREOPEN;
break;
- case ENVTEST_PRERENAME:
- testval = DB_TEST_PRERENAME;
+ case ENVTEST_PREDESTROY:
+ testval = DB_TEST_PREDESTROY;
break;
case ENVTEST_POSTLOG:
testval = DB_TEST_POSTLOG;
@@ -660,12 +1018,16 @@ tcl_EnvTest(interp, objc, objv, envp)
case ENVTEST_POSTOPEN:
testval = DB_TEST_POSTOPEN;
break;
- case ENVTEST_POSTRENAME:
- testval = DB_TEST_POSTRENAME;
+ case ENVTEST_POSTDESTROY:
+ testval = DB_TEST_POSTDESTROY;
break;
case ENVTEST_POSTSYNC:
testval = DB_TEST_POSTSYNC;
break;
+ case ENVTEST_SUBDB_LOCKS:
+ DB_ASSERT(loc == &dbenv->test_abort);
+ testval = DB_TEST_SUBDB_LOCKS;
+ break;
default:
Tcl_SetResult(interp, "Illegal test location", TCL_STATIC);
return (TCL_ERROR);
@@ -676,3 +1038,273 @@ tcl_EnvTest(interp, objc, objv, envp)
return (result);
}
#endif
+
+/*
+ * env_DbRemove --
+ * Implements the ENV->dbremove command.
+ */
+static int
+env_DbRemove(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv;
+{
+ static char *envdbrem[] = {
+ "-auto_commit",
+ "-txn",
+ "--",
+ NULL
+ };
+ enum envdbrem {
+ TCL_EDBREM_COMMIT,
+ TCL_EDBREM_TXN,
+ TCL_EDBREM_ENDARG
+ };
+ DB_TXN *txn;
+ u_int32_t flag;
+ int endarg, i, optindex, result, ret, subdblen;
+ u_char *subdbtmp;
+ char *arg, *db, *subdb, msg[MSG_SIZE];
+
+ txn = NULL;
+ result = TCL_OK;
+ subdbtmp = NULL;
+ db = subdb = NULL;
+ endarg = 0;
+ flag = 0;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?");
+ return (TCL_ERROR);
+ }
+
+ /*
+ * We must first parse for the environment flag, since that
+ * is needed for db_create. Then create the db handle.
+ */
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], envdbrem,
+ "option", TCL_EXACT, &optindex) != TCL_OK) {
+ arg = Tcl_GetStringFromObj(objv[i], NULL);
+ if (arg[0] == '-') {
+ result = IS_HELP(objv[i]);
+ goto error;
+ } else
+ Tcl_ResetResult(interp);
+ break;
+ }
+ i++;
+ switch ((enum envdbrem)optindex) {
+ case TCL_EDBREM_COMMIT:
+ flag |= DB_AUTO_COMMIT;
+ break;
+ case TCL_EDBREM_TXN:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "env dbremove: Invalid txn %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ return (TCL_ERROR);
+ }
+ break;
+ case TCL_EDBREM_ENDARG:
+ endarg = 1;
+ break;
+ }
+ /*
+ * If, at any time, parsing the args we get an error,
+ * bail out and return.
+ */
+ if (result != TCL_OK)
+ goto error;
+ if (endarg)
+ break;
+ }
+ if (result != TCL_OK)
+ goto error;
+ /*
+ * Any args we have left, (better be 1 or 2 left) are
+ * file names. If there is 1, a db name, if 2 a db and subdb name.
+ */
+ if ((i != (objc - 1)) || (i != (objc - 2))) {
+ /*
+ * Dbs must be NULL terminated file names, but subdbs can
+ * be anything. Use Strings for the db name and byte
+ * arrays for the subdb.
+ */
+ db = Tcl_GetStringFromObj(objv[i++], NULL);
+ if (i != objc) {
+ subdbtmp =
+ Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
+ if ((ret = __os_malloc(dbenv, subdblen + 1,
+ &subdb)) != 0) {
+ Tcl_SetResult(interp,
+ db_strerror(ret), TCL_STATIC);
+ return (0);
+ }
+ memcpy(subdb, subdbtmp, subdblen);
+ subdb[subdblen] = '\0';
+ }
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?");
+ result = TCL_ERROR;
+ goto error;
+ }
+ ret = dbenv->dbremove(dbenv, txn, db, subdb, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env dbremove");
+error:
+ if (subdb)
+ __os_free(dbenv, subdb);
+ return (result);
+}
+
+/*
+ * env_DbRename --
+ * Implements the ENV->dbrename command.
+ */
+static int
+env_DbRename(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv;
+{
+ static char *envdbmv[] = {
+ "-auto_commit",
+ "-txn",
+ "--",
+ NULL
+ };
+ enum envdbmv {
+ TCL_EDBMV_COMMIT,
+ TCL_EDBMV_TXN,
+ TCL_EDBMV_ENDARG
+ };
+ DB_TXN *txn;
+ u_int32_t flag;
+ int endarg, i, newlen, optindex, result, ret, subdblen;
+ u_char *subdbtmp;
+ char *arg, *db, *newname, *subdb, msg[MSG_SIZE];
+
+ txn = NULL;
+ result = TCL_OK;
+ subdbtmp = NULL;
+ db = newname = subdb = NULL;
+ endarg = 0;
+ flag = 0;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 3, objv,
+ "?args? filename ?database? ?newname?");
+ return (TCL_ERROR);
+ }
+
+ /*
+ * We must first parse for the environment flag, since that
+ * is needed for db_create. Then create the db handle.
+ */
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], envdbmv,
+ "option", TCL_EXACT, &optindex) != TCL_OK) {
+ arg = Tcl_GetStringFromObj(objv[i], NULL);
+ if (arg[0] == '-') {
+ result = IS_HELP(objv[i]);
+ goto error;
+ } else
+ Tcl_ResetResult(interp);
+ break;
+ }
+ i++;
+ switch ((enum envdbmv)optindex) {
+ case TCL_EDBMV_COMMIT:
+ flag |= DB_AUTO_COMMIT;
+ break;
+ case TCL_EDBMV_TXN:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+ result = TCL_ERROR;
+ break;
+ }
+ arg = Tcl_GetStringFromObj(objv[i++], NULL);
+ txn = NAME_TO_TXN(arg);
+ if (txn == NULL) {
+ snprintf(msg, MSG_SIZE,
+ "env dbrename: Invalid txn %s\n", arg);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ return (TCL_ERROR);
+ }
+ break;
+ case TCL_EDBMV_ENDARG:
+ endarg = 1;
+ break;
+ }
+ /*
+ * If, at any time, parsing the args we get an error,
+ * bail out and return.
+ */
+ if (result != TCL_OK)
+ goto error;
+ if (endarg)
+ break;
+ }
+ if (result != TCL_OK)
+ goto error;
+ /*
+ * Any args we have left, (better be 2 or 3 left) are
+ * file names. If there is 2, a db name, if 3 a db and subdb name.
+ */
+ if ((i != (objc - 2)) || (i != (objc - 3))) {
+ /*
+ * Dbs must be NULL terminated file names, but subdbs can
+ * be anything. Use Strings for the db name and byte
+ * arrays for the subdb.
+ */
+ db = Tcl_GetStringFromObj(objv[i++], NULL);
+ if (i == objc - 2) {
+ subdbtmp =
+ Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
+ if ((ret = __os_malloc(dbenv, subdblen + 1,
+ &subdb)) != 0) {
+ Tcl_SetResult(interp,
+ db_strerror(ret), TCL_STATIC);
+ return (0);
+ }
+ memcpy(subdb, subdbtmp, subdblen);
+ subdb[subdblen] = '\0';
+ }
+ subdbtmp =
+ Tcl_GetByteArrayFromObj(objv[i++], &newlen);
+ if ((ret = __os_malloc(dbenv, newlen + 1,
+ &newname)) != 0) {
+ Tcl_SetResult(interp,
+ db_strerror(ret), TCL_STATIC);
+ return (0);
+ }
+ memcpy(newname, subdbtmp, newlen);
+ newname[newlen] = '\0';
+ } else {
+ Tcl_WrongNumArgs(interp, 3, objv,
+ "?args? filename ?database? ?newname?");
+ result = TCL_ERROR;
+ goto error;
+ }
+ ret = dbenv->dbrename(dbenv, txn, db, subdb, newname, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env dbrename");
+error:
+ if (subdb)
+ __os_free(dbenv, subdb);
+ if (newname)
+ __os_free(dbenv, newname);
+ return (result);
+}
diff --git a/bdb/tcl/tcl_internal.c b/bdb/tcl/tcl_internal.c
index bdab60f4ad6..2d6ad4df444 100644
--- a/bdb/tcl/tcl_internal.c
+++ b/bdb/tcl/tcl_internal.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_internal.c,v 11.27 2000/05/22 18:36:51 sue Exp $";
+static const char revid[] = "$Id: tcl_internal.c,v 11.54 2002/08/15 02:47:46 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,10 +20,10 @@ static const char revid[] = "$Id: tcl_internal.c,v 11.27 2000/05/22 18:36:51 sue
#endif
#include "db_int.h"
-#include "tcl_db.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "db_ext.h"
+#include "dbinc/tcl_db.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc_auto/db_ext.h"
/*
*
@@ -46,6 +46,16 @@ static const char revid[] = "$Id: tcl_internal.c,v 11.27 2000/05/22 18:36:51 sue
/*
* Prototypes for procedures defined later in this file:
*/
+static void tcl_flag_callback __P((u_int32_t, const FN *, void *));
+
+/*
+ * Private structure type used to pass both an interp and an object into
+ * a callback's single void *.
+ */
+struct __tcl_callback_bundle {
+ Tcl_Interp *interp;
+ Tcl_Obj *obj;
+};
#define GLOB_CHAR(c) ((c) == '*' || (c) == '?')
@@ -68,14 +78,14 @@ _NewInfo(interp, anyp, name, type)
DBTCL_INFO *p;
int i, ret;
- if ((ret = __os_malloc(NULL, sizeof(DBTCL_INFO), NULL, &p)) != 0) {
+ if ((ret = __os_malloc(NULL, sizeof(DBTCL_INFO), &p)) != 0) {
Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
return (NULL);
}
if ((ret = __os_strdup(NULL, name, &p->i_name)) != 0) {
Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
- __os_free(p, sizeof(DBTCL_INFO));
+ __os_free(NULL, p);
return (NULL);
}
p->i_interp = interp;
@@ -87,6 +97,12 @@ _NewInfo(interp, anyp, name, type)
p->i_err = NULL;
p->i_errpfx = NULL;
p->i_lockobj.data = NULL;
+ p->i_btcompare = NULL;
+ p->i_dupcompare = NULL;
+ p->i_hashproc = NULL;
+ p->i_second_call = NULL;
+ p->i_rep_eid = NULL;
+ p->i_rep_send = NULL;
for (i = 0; i < MAX_ID; i++)
p->i_otherid[i] = 0;
@@ -111,22 +127,6 @@ _NameToPtr(name)
}
/*
- * PUBLIC: char *_PtrToName __P((CONST void *));
- */
-char *
-_PtrToName(ptr)
- CONST void *ptr;
-{
- DBTCL_INFO *p;
-
- for (p = LIST_FIRST(&__db_infohead); p != NULL;
- p = LIST_NEXT(p, entries))
- if (p->i_anyp == ptr)
- return (p->i_name);
- return (NULL);
-}
-
-/*
* PUBLIC: DBTCL_INFO *_PtrToInfo __P((CONST void *));
*/
DBTCL_INFO *
@@ -183,15 +183,27 @@ _DeleteInfo(p)
return;
LIST_REMOVE(p, entries);
if (p->i_lockobj.data != NULL)
- __os_free(p->i_lockobj.data, p->i_lockobj.size);
+ __os_free(NULL, p->i_lockobj.data);
if (p->i_err != NULL) {
fclose(p->i_err);
p->i_err = NULL;
}
if (p->i_errpfx != NULL)
- __os_freestr(p->i_errpfx);
- __os_freestr(p->i_name);
- __os_free(p, sizeof(DBTCL_INFO));
+ __os_free(NULL, p->i_errpfx);
+ if (p->i_btcompare != NULL)
+ Tcl_DecrRefCount(p->i_btcompare);
+ if (p->i_dupcompare != NULL)
+ Tcl_DecrRefCount(p->i_dupcompare);
+ if (p->i_hashproc != NULL)
+ Tcl_DecrRefCount(p->i_hashproc);
+ if (p->i_second_call != NULL)
+ Tcl_DecrRefCount(p->i_second_call);
+ if (p->i_rep_eid != NULL)
+ Tcl_DecrRefCount(p->i_rep_eid);
+ if (p->i_rep_send != NULL)
+ Tcl_DecrRefCount(p->i_rep_send);
+ __os_free(NULL, p->i_name);
+ __os_free(NULL, p);
return;
}
@@ -258,7 +270,7 @@ _SetListRecnoElem(interp, list, elem1, elem2, e2size)
int myobjc;
myobjc = 2;
- myobjv[0] = Tcl_NewIntObj(elem1);
+ myobjv[0] = Tcl_NewLongObj((long)elem1);
myobjv[1] = Tcl_NewByteArrayObj(elem2, e2size);
thislist = Tcl_NewListObj(myobjc, myobjv);
if (thislist == NULL)
@@ -268,6 +280,107 @@ _SetListRecnoElem(interp, list, elem1, elem2, e2size)
}
/*
+ * _Set3DBTList --
+ * This is really analogous to both _SetListElem and
+ * _SetListRecnoElem--it's used for three-DBT lists returned by
+ * DB->pget and DBC->pget(). We'd need a family of four functions
+ * to handle all the recno/non-recno cases, however, so we make
+ * this a little more aware of the internals and do the logic inside.
+ *
+ * XXX
+ * One of these days all these functions should probably be cleaned up
+ * to eliminate redundancy and bring them into the standard DB
+ * function namespace.
+ *
+ * PUBLIC: int _Set3DBTList __P((Tcl_Interp *, Tcl_Obj *, DBT *, int,
+ * PUBLIC: DBT *, int, DBT *));
+ */
+int
+_Set3DBTList(interp, list, elem1, is1recno, elem2, is2recno, elem3)
+ Tcl_Interp *interp;
+ Tcl_Obj *list;
+ DBT *elem1, *elem2, *elem3;
+ int is1recno, is2recno;
+{
+
+ Tcl_Obj *myobjv[3], *thislist;
+
+ if (is1recno)
+ myobjv[0] = Tcl_NewLongObj((long)*(db_recno_t *)elem1->data);
+ else
+ myobjv[0] =
+ Tcl_NewByteArrayObj((u_char *)elem1->data, elem1->size);
+
+ if (is2recno)
+ myobjv[1] = Tcl_NewLongObj((long)*(db_recno_t *)elem2->data);
+ else
+ myobjv[1] =
+ Tcl_NewByteArrayObj((u_char *)elem2->data, elem2->size);
+
+ myobjv[2] = Tcl_NewByteArrayObj((u_char *)elem3->data, elem3->size);
+
+ thislist = Tcl_NewListObj(3, myobjv);
+
+ if (thislist == NULL)
+ return (TCL_ERROR);
+ return (Tcl_ListObjAppendElement(interp, list, thislist));
+}
+
+/*
+ * _SetMultiList -- build a list for return from multiple get.
+ *
+ * PUBLIC: int _SetMultiList __P((Tcl_Interp *,
+ * PUBLIC: Tcl_Obj *, DBT *, DBT*, int, int));
+ */
+int
+_SetMultiList(interp, list, key, data, type, flag)
+ Tcl_Interp *interp;
+ Tcl_Obj *list;
+ DBT *key, *data;
+ int type, flag;
+{
+ db_recno_t recno;
+ u_int32_t dlen, klen;
+ int result;
+ void *pointer, *dp, *kp;
+
+ recno = 0;
+ dlen = 0;
+ kp = NULL;
+
+ DB_MULTIPLE_INIT(pointer, data);
+ result = TCL_OK;
+
+ if (type == DB_RECNO || type == DB_QUEUE)
+ recno = *(db_recno_t *) key->data;
+ else
+ kp = key->data;
+ klen = key->size;
+ do {
+ if (flag & DB_MULTIPLE_KEY) {
+ if (type == DB_RECNO || type == DB_QUEUE)
+ DB_MULTIPLE_RECNO_NEXT(pointer,
+ data, recno, dp, dlen);
+ else
+ DB_MULTIPLE_KEY_NEXT(pointer,
+ data, kp, klen, dp, dlen);
+ } else
+ DB_MULTIPLE_NEXT(pointer, data, dp, dlen);
+
+ if (pointer == NULL)
+ break;
+
+ if (type == DB_RECNO || type == DB_QUEUE) {
+ result =
+ _SetListRecnoElem(interp, list, recno, dp, dlen);
+ recno++;
+ } else
+ result = _SetListElem(interp, list, kp, klen, dp, dlen);
+ } while (result == TCL_OK);
+
+ return (result);
+}
+/*
* PUBLIC: int _GetGlobPrefix __P((char *, char **));
*/
int
@@ -299,12 +412,12 @@ _GetGlobPrefix(pattern, prefix)
}
/*
- * PUBLIC: int _ReturnSetup __P((Tcl_Interp *, int, char *));
+ * PUBLIC: int _ReturnSetup __P((Tcl_Interp *, int, int, char *));
*/
int
-_ReturnSetup(interp, ret, errmsg)
+_ReturnSetup(interp, ret, ok, errmsg)
Tcl_Interp *interp;
- int ret;
+ int ret, ok;
char *errmsg;
{
char *msg;
@@ -327,12 +440,9 @@ _ReturnSetup(interp, ret, errmsg)
msg = db_strerror(ret);
Tcl_AppendResult(interp, msg, NULL);
- switch (ret) {
- case DB_NOTFOUND:
- case DB_KEYEXIST:
- case DB_KEYEMPTY:
+ if (ok)
return (TCL_OK);
- default:
+ else {
Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL);
return (TCL_ERROR);
}
@@ -375,7 +485,7 @@ _ErrorFunc(pfx, msg)
* If we cannot allocate enough to put together the prefix
* and message then give them just the message.
*/
- if (__os_malloc(NULL, size, NULL, &err) != 0) {
+ if (__os_malloc(NULL, size, &err) != 0) {
Tcl_AddErrorInfo(interp, msg);
Tcl_AppendResult(interp, msg, "\n", NULL);
return;
@@ -383,7 +493,7 @@ _ErrorFunc(pfx, msg)
snprintf(err, size, "%s: %s", pfx, msg);
Tcl_AddErrorInfo(interp, err);
Tcl_AppendResult(interp, err, "\n", NULL);
- __os_free(err, size);
+ __os_free(NULL, err);
return;
}
@@ -399,8 +509,9 @@ _GetLsn(interp, obj, lsn)
DB_LSN *lsn;
{
Tcl_Obj **myobjv;
- int itmp, myobjc, result;
char msg[MSG_SIZE];
+ int myobjc, result;
+ u_int32_t tmp;
result = Tcl_ListObjGetElements(interp, obj, &myobjc, &myobjv);
if (result == TCL_ERROR)
@@ -411,15 +522,125 @@ _GetLsn(interp, obj, lsn)
Tcl_SetResult(interp, msg, TCL_VOLATILE);
return (result);
}
- result = Tcl_GetIntFromObj(interp, myobjv[0], &itmp);
+ result = _GetUInt32(interp, myobjv[0], &tmp);
if (result == TCL_ERROR)
return (result);
- lsn->file = itmp;
- result = Tcl_GetIntFromObj(interp, myobjv[1], &itmp);
- lsn->offset = itmp;
+ lsn->file = tmp;
+ result = _GetUInt32(interp, myobjv[1], &tmp);
+ lsn->offset = tmp;
return (result);
}
+/*
+ * _GetUInt32 --
+ * Get a u_int32_t from a Tcl object. Tcl_GetIntFromObj does the
+ * right thing most of the time, but on machines where a long is 8 bytes
+ * and an int is 4 bytes, it errors on integers between the maximum
+ * int32_t and the maximum u_int32_t. This is correct, but we generally
+ * want a u_int32_t in the end anyway, so we use Tcl_GetLongFromObj and do
+ * the bounds checking ourselves.
+ *
+ * This code looks much like Tcl_GetIntFromObj, only with a different
+ * bounds check. It's essentially Tcl_GetUnsignedIntFromObj, which
+ * unfortunately doesn't exist.
+ *
+ * PUBLIC: int _GetUInt32 __P((Tcl_Interp *, Tcl_Obj *, u_int32_t *));
+ */
+int
+_GetUInt32(interp, obj, resp)
+ Tcl_Interp *interp;
+ Tcl_Obj *obj;
+ u_int32_t *resp;
+{
+ int result;
+ long ltmp;
+
+ result = Tcl_GetLongFromObj(interp, obj, &ltmp);
+ if (result != TCL_OK)
+ return (result);
+
+ if ((unsigned long)ltmp != (u_int32_t)ltmp) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "integer value too large for u_int32_t", -1);
+ }
+ return (TCL_ERROR);
+ }
+
+ *resp = (u_int32_t)ltmp;
+ return (TCL_OK);
+}
+
+/*
+ * tcl_flag_callback --
+ * Callback for db_pr.c functions that contain the FN struct mapping
+ * flag values to meaningful strings. This function appends a Tcl_Obj
+ * containing each pertinent flag string to the specified Tcl list.
+ */
+static void
+tcl_flag_callback(flags, fn, vtcbp)
+ u_int32_t flags;
+ const FN *fn;
+ void *vtcbp;
+{
+ const FN *fnp;
+ Tcl_Interp *interp;
+ Tcl_Obj *newobj, *listobj;
+ int result;
+ struct __tcl_callback_bundle *tcbp;
+
+ tcbp = (struct __tcl_callback_bundle *)vtcbp;
+ interp = tcbp->interp;
+ listobj = tcbp->obj;
+
+ for (fnp = fn; fnp->mask != 0; ++fnp)
+ if (LF_ISSET(fnp->mask)) {
+ newobj = Tcl_NewStringObj(fnp->name, strlen(fnp->name));
+ result =
+ Tcl_ListObjAppendElement(interp, listobj, newobj);
+
+ /*
+ * Tcl_ListObjAppendElement is defined to return TCL_OK
+ * unless listobj isn't actually a list (or convertible
+ * into one). If this is the case, we screwed up badly
+ * somehow.
+ */
+ DB_ASSERT(result == TCL_OK);
+ }
+}
+
+/*
+ * _GetFlagsList --
+ * Get a new Tcl object, containing a list of the string values
+ * associated with a particular set of flag values, given a function
+ * that can extract the right names for the right flags.
+ *
+ * PUBLIC: Tcl_Obj *_GetFlagsList __P((Tcl_Interp *, u_int32_t,
+ * PUBLIC: void (*)(u_int32_t, void *,
+ * PUBLIC: void (*)(u_int32_t, const FN *, void *))));
+ */
+Tcl_Obj *
+_GetFlagsList(interp, flags, func)
+ Tcl_Interp *interp;
+ u_int32_t flags;
+ void (*func)
+ __P((u_int32_t, void *, void (*)(u_int32_t, const FN *, void *)));
+{
+ Tcl_Obj *newlist;
+ struct __tcl_callback_bundle tcb;
+
+ newlist = Tcl_NewObj();
+
+ memset(&tcb, 0, sizeof(tcb));
+ tcb.interp = interp;
+ tcb.obj = newlist;
+
+ func(flags, &tcb, tcl_flag_callback);
+
+ return (newlist);
+}
+
int __debug_stop, __debug_on, __debug_print, __debug_test;
/*
@@ -432,9 +653,65 @@ _debug_check()
return;
if (__debug_print != 0) {
- printf("\r%6d:", __debug_on);
+ printf("\r%7d:", __debug_on);
fflush(stdout);
}
if (__debug_on++ == __debug_test || __debug_stop)
__db_loadme();
}
+
+/*
+ * XXX
+ * Tcl 8.1+ Tcl_GetByteArrayFromObj/Tcl_GetIntFromObj bug.
+ *
+ * There is a bug in Tcl 8.1+ and byte arrays in that if it happens
+ * to use an object as both a byte array and something else like
+ * an int, and you've done a Tcl_GetByteArrayFromObj, then you
+ * do a Tcl_GetIntFromObj, your memory is deleted.
+ *
+ * Workaround is for all byte arrays we want to use, if it can be
+ * represented as an integer, we copy it so that we don't lose the
+ * memory.
+ */
+/*
+ * PUBLIC: int _CopyObjBytes __P((Tcl_Interp *, Tcl_Obj *obj, void **,
+ * PUBLIC: u_int32_t *, int *));
+ */
+int
+_CopyObjBytes(interp, obj, newp, sizep, freep)
+ Tcl_Interp *interp;
+ Tcl_Obj *obj;
+ void **newp;
+ u_int32_t *sizep;
+ int *freep;
+{
+ void *tmp, *new;
+ int i, len, ret;
+
+ /*
+ * If the object is not an int, then just return the byte
+ * array because it won't be transformed out from under us.
+ * If it is a number, we need to copy it.
+ */
+ *freep = 0;
+ ret = Tcl_GetIntFromObj(interp, obj, &i);
+ tmp = Tcl_GetByteArrayFromObj(obj, &len);
+ *sizep = len;
+ if (ret == TCL_ERROR) {
+ Tcl_ResetResult(interp);
+ *newp = tmp;
+ return (0);
+ }
+
+ /*
+ * If we get here, we have an integer that might be reused
+ * at some other point so we cannot count on GetByteArray
+ * keeping our pointer valid.
+ */
+ if ((ret = __os_malloc(NULL, len, &new)) != 0)
+ return (ret);
+ memcpy(new, tmp, len);
+ *newp = new;
+ *freep = 1;
+ return (0);
+}
diff --git a/bdb/tcl/tcl_lock.c b/bdb/tcl/tcl_lock.c
index 89f6eeb2b39..6cb96dbb0da 100644
--- a/bdb/tcl/tcl_lock.c
+++ b/bdb/tcl/tcl_lock.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_lock.c,v 11.21 2001/01/11 18:19:55 bostic Exp $";
+static const char revid[] = "$Id: tcl_lock.c,v 11.47 2002/08/08 15:27:10 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,7 @@ static const char revid[] = "$Id: tcl_lock.c,v 11.21 2001/01/11 18:19:55 bostic
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/tcl_db.h"
/*
* Prototypes for procedures defined later in this file:
@@ -31,15 +31,23 @@ static int _GetThisLock __P((Tcl_Interp *, DB_ENV *, u_int32_t,
u_int32_t, DBT *, db_lockmode_t, char *));
static void _LockPutInfo __P((Tcl_Interp *, db_lockop_t, DB_LOCK *,
u_int32_t, DBT *));
-
+#if CONFIG_TEST
static char *lkmode[] = {
- "ng", "read", "write",
- "iwrite", "iread", "iwr",
+ "ng",
+ "read",
+ "write",
+ "iwrite",
+ "iread",
+ "iwr",
NULL
};
enum lkmode {
- LK_NG, LK_READ, LK_WRITE,
- LK_IWRITE, LK_IREAD, LK_IWR
+ LK_NG,
+ LK_READ,
+ LK_WRITE,
+ LK_IWRITE,
+ LK_IREAD,
+ LK_IWR
};
/*
@@ -56,16 +64,22 @@ tcl_LockDetect(interp, objc, objv, envp)
DB_ENV *envp; /* Environment pointer */
{
static char *ldopts[] = {
- "-lock_conflict",
+ "expire",
"default",
+ "maxlocks",
+ "minlocks",
+ "minwrites",
"oldest",
"random",
"youngest",
NULL
};
enum ldopts {
- LD_CONFLICT,
+ LD_EXPIRE,
LD_DEFAULT,
+ LD_MAXLOCKS,
+ LD_MINLOCKS,
+ LD_MINWRITES,
LD_OLDEST,
LD_RANDOM,
LD_YOUNGEST
@@ -82,10 +96,26 @@ tcl_LockDetect(interp, objc, objv, envp)
return (IS_HELP(objv[i]));
i++;
switch ((enum ldopts)optindex) {
+ case LD_EXPIRE:
+ FLAG_CHECK(policy);
+ policy = DB_LOCK_EXPIRE;
+ break;
case LD_DEFAULT:
FLAG_CHECK(policy);
policy = DB_LOCK_DEFAULT;
break;
+ case LD_MAXLOCKS:
+ FLAG_CHECK(policy);
+ policy = DB_LOCK_MAXLOCKS;
+ break;
+ case LD_MINWRITES:
+ FLAG_CHECK(policy);
+ policy = DB_LOCK_MINWRITE;
+ break;
+ case LD_MINLOCKS:
+ FLAG_CHECK(policy);
+ policy = DB_LOCK_MINLOCKS;
+ break;
case LD_OLDEST:
FLAG_CHECK(policy);
policy = DB_LOCK_OLDEST;
@@ -98,15 +128,12 @@ tcl_LockDetect(interp, objc, objv, envp)
FLAG_CHECK(policy);
policy = DB_LOCK_RANDOM;
break;
- case LD_CONFLICT:
- flag |= DB_LOCK_CONFLICT;
- break;
}
}
_debug_check();
- ret = lock_detect(envp, flag, policy, NULL);
- result = _ReturnSetup(interp, ret, "lock detect");
+ ret = envp->lock_detect(envp, flag, policy, NULL);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock detect");
return (result);
}
@@ -132,12 +159,14 @@ tcl_LockGet(interp, objc, objv, envp)
};
DBT obj;
Tcl_Obj *res;
+ void *otmp;
db_lockmode_t mode;
u_int32_t flag, lockid;
- int itmp, optindex, result;
+ int freeobj, optindex, result, ret;
char newname[MSG_SIZE];
result = TCL_OK;
+ freeobj = 0;
memset(newname, 0, MSG_SIZE);
if (objc != 5 && objc != 6) {
Tcl_WrongNumArgs(interp, 2, objv, "?-nowait? mode id obj");
@@ -152,28 +181,19 @@ tcl_LockGet(interp, objc, objv, envp)
memset(&obj, 0, sizeof(obj));
if ((result =
- Tcl_GetIntFromObj(interp, objv[objc-2], &itmp)) != TCL_OK)
+ _GetUInt32(interp, objv[objc-2], &lockid)) != TCL_OK)
return (result);
- lockid = itmp;
- /*
- * XXX
- * Tcl 8.1 Tcl_GetByteArrayFromObj/Tcl_GetIntFromObj bug.
- *
- * The line below was originally before the Tcl_GetIntFromObj.
- *
- * There is a bug in Tcl 8.1 and byte arrays in that if it happens
- * to use an object as both a byte array and something else like
- * an int, and you've done a Tcl_GetByteArrayFromObj, then you
- * do a Tcl_GetIntFromObj, your memory is deleted.
- *
- * Workaround is to make sure all Tcl_GetByteArrayFromObj calls
- * are done last.
- */
- obj.data = Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- obj.size = itmp;
- if ((result = _LockMode(interp, objv[(objc - 3)], &mode)) != TCL_OK)
+ ret = _CopyObjBytes(interp, objv[objc-1], &otmp,
+ &obj.size, &freeobj);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "lock get");
return (result);
+ }
+ obj.data = otmp;
+ if ((result = _LockMode(interp, objv[(objc - 3)], &mode)) != TCL_OK)
+ goto out;
/*
* Any left over arg is the flag.
@@ -195,6 +215,9 @@ tcl_LockGet(interp, objc, objv, envp)
res = Tcl_NewStringObj(newname, strlen(newname));
Tcl_SetObjResult(interp, res);
}
+out:
+ if (freeobj)
+ (void)__os_free(envp, otmp);
return (result);
}
@@ -224,8 +247,8 @@ tcl_LockStat(interp, objc, objv, envp)
return (TCL_ERROR);
}
_debug_check();
- ret = lock_stat(envp, &sp, NULL);
- result = _ReturnSetup(interp, ret, "lock stat");
+ ret = envp->lock_stat(envp, &sp, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock stat");
if (result == TCL_ERROR)
return (result);
/*
@@ -237,9 +260,11 @@ tcl_LockStat(interp, objc, objv, envp)
* MAKE_STAT_LIST assumes 'res' and 'error' label.
*/
MAKE_STAT_LIST("Region size", sp->st_regsize);
- MAKE_STAT_LIST("Max locks", sp->st_maxlocks);
- MAKE_STAT_LIST("Max lockers", sp->st_maxlockers);
- MAKE_STAT_LIST("Max objects", sp->st_maxobjects);
+ MAKE_STAT_LIST("Last allocated locker ID", sp->st_id);
+ MAKE_STAT_LIST("Current maximum unused locker ID", sp->st_cur_maxid);
+ MAKE_STAT_LIST("Maximum locks", sp->st_maxlocks);
+ MAKE_STAT_LIST("Maximum lockers", sp->st_maxlockers);
+ MAKE_STAT_LIST("Maximum objects", sp->st_maxobjects);
MAKE_STAT_LIST("Lock modes", sp->st_nmodes);
MAKE_STAT_LIST("Current number of locks", sp->st_nlocks);
MAKE_STAT_LIST("Maximum number of locks so far", sp->st_maxnlocks);
@@ -250,12 +275,49 @@ tcl_LockStat(interp, objc, objv, envp)
MAKE_STAT_LIST("Number of conflicts", sp->st_nconflicts);
MAKE_STAT_LIST("Lock requests", sp->st_nrequests);
MAKE_STAT_LIST("Lock releases", sp->st_nreleases);
+ MAKE_STAT_LIST("Lock requests that would have waited", sp->st_nnowaits);
MAKE_STAT_LIST("Deadlocks detected", sp->st_ndeadlocks);
MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
+ MAKE_STAT_LIST("Lock timeout value", sp->st_locktimeout);
+ MAKE_STAT_LIST("Number of lock timeouts", sp->st_nlocktimeouts);
+ MAKE_STAT_LIST("Transaction timeout value", sp->st_txntimeout);
+ MAKE_STAT_LIST("Number of transaction timeouts", sp->st_ntxntimeouts);
Tcl_SetObjResult(interp, res);
error:
- __os_free(sp, sizeof(*sp));
+ free(sp);
+ return (result);
+}
+
+/*
+ * tcl_LockTimeout --
+ *
+ * PUBLIC: int tcl_LockTimeout __P((Tcl_Interp *, int,
+ * PUBLIC: Tcl_Obj * CONST*, DB_ENV *));
+ */
+int
+tcl_LockTimeout(interp, objc, objv, envp)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *envp; /* Environment pointer */
+{
+ long timeout;
+ int result, ret;
+
+ /*
+ * One arg, the timeout.
+ */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?timeout?");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetLongFromObj(interp, objv[2], &timeout);
+ if (result != TCL_OK)
+ return (result);
+ _debug_check();
+ ret = envp->set_timeout(envp, (u_int32_t)timeout, DB_SET_LOCK_TIMEOUT);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock timeout");
return (result);
}
@@ -265,10 +327,10 @@ error:
*/
static int
lock_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Lock handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ ClientData clientData; /* Lock handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *lkcmds[] = {
"put",
@@ -315,11 +377,12 @@ lock_Cmd(clientData, interp, objc, objv)
switch ((enum lkcmds)cmdindex) {
case LKPUT:
_debug_check();
- ret = lock_put(env, lock);
- result = _ReturnSetup(interp, ret, "lock put");
+ ret = env->lock_put(env, lock);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock put");
(void)Tcl_DeleteCommand(interp, lkip->i_name);
_DeleteInfo(lkip);
- __os_free(lock, sizeof(DB_LOCK));
+ __os_free(env, lock);
break;
}
return (result);
@@ -332,9 +395,9 @@ lock_Cmd(clientData, interp, objc, objv)
*/
int
tcl_LockVec(interp, objc, objv, envp)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
DB_ENV *envp; /* environment pointer */
{
static char *lvopts[] = {
@@ -345,25 +408,34 @@ tcl_LockVec(interp, objc, objv, envp)
LVNOWAIT
};
static char *lkops[] = {
- "get", "put", "put_all", "put_obj",
+ "get",
+ "put",
+ "put_all",
+ "put_obj",
+ "timeout",
NULL
};
enum lkops {
- LKGET, LKPUT, LKPUTALL, LKPUTOBJ
+ LKGET,
+ LKPUT,
+ LKPUTALL,
+ LKPUTOBJ,
+ LKTIMEOUT
};
DB_LOCK *lock;
DB_LOCKREQ list;
DBT obj;
Tcl_Obj **myobjv, *res, *thisop;
- db_lockmode_t mode;
+ void *otmp;
u_int32_t flag, lockid;
- int i, itmp, myobjc, optindex, result, ret;
+ int freeobj, i, myobjc, optindex, result, ret;
char *lockname, msg[MSG_SIZE], newname[MSG_SIZE];
result = TCL_OK;
memset(newname, 0, MSG_SIZE);
flag = 0;
- mode = 0;
+ freeobj = 0;
+
/*
* If -nowait is given, it MUST be first arg.
*/
@@ -385,10 +457,9 @@ tcl_LockVec(interp, objc, objv, envp)
/*
* Our next arg MUST be the locker ID.
*/
- result = Tcl_GetIntFromObj(interp, objv[i++], &itmp);
+ result = _GetUInt32(interp, objv[i++], &lockid);
if (result != TCL_OK)
return (result);
- lockid = itmp;
/*
* All other remaining args are operation tuples.
@@ -429,26 +500,19 @@ tcl_LockVec(interp, objc, objv, envp)
result = _LockMode(interp, myobjv[2], &list.mode);
if (result != TCL_OK)
goto error;
- /*
- * XXX
- * Tcl 8.1 Tcl_GetByteArrayFromObj/Tcl_GetIntFromObj
- * bug.
- *
- * There is a bug in Tcl 8.1 and byte arrays in that if
- * it happens to use an object as both a byte array and
- * something else like an int, and you've done a
- * Tcl_GetByteArrayFromObj, then you do a
- * Tcl_GetIntFromObj, your memory is deleted.
- *
- * Workaround is to make sure all
- * Tcl_GetByteArrayFromObj calls are done last.
- */
- obj.data = Tcl_GetByteArrayFromObj(myobjv[1], &itmp);
- obj.size = itmp;
+ ret = _CopyObjBytes(interp, myobjv[1], &otmp,
+ &obj.size, &freeobj);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "lock vec");
+ return (result);
+ }
+ obj.data = otmp;
ret = _GetThisLock(interp, envp, lockid, flag,
&obj, list.mode, newname);
if (ret != 0) {
- result = _ReturnSetup(interp, ret, "lock vec");
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "lock vec");
thisop = Tcl_NewIntObj(ret);
(void)Tcl_ListObjAppendElement(interp, res,
thisop);
@@ -456,6 +520,10 @@ tcl_LockVec(interp, objc, objv, envp)
}
thisop = Tcl_NewStringObj(newname, strlen(newname));
(void)Tcl_ListObjAppendElement(interp, res, thisop);
+ if (freeobj) {
+ (void)__os_free(envp, otmp);
+ freeobj = 0;
+ }
continue;
case LKPUT:
if (myobjc != 2) {
@@ -493,17 +561,27 @@ tcl_LockVec(interp, objc, objv, envp)
goto error;
}
list.op = DB_LOCK_PUT_OBJ;
- obj.data = Tcl_GetByteArrayFromObj(myobjv[1], &itmp);
- obj.size = itmp;
+ ret = _CopyObjBytes(interp, myobjv[1], &otmp,
+ &obj.size, &freeobj);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "lock vec");
+ return (result);
+ }
+ obj.data = otmp;
list.obj = &obj;
break;
+ case LKTIMEOUT:
+ list.op = DB_LOCK_TIMEOUT;
+ break;
+
}
/*
* We get here, we have set up our request, now call
* lock_vec.
*/
_debug_check();
- ret = lock_vec(envp, lockid, flag, &list, 1, NULL);
+ ret = envp->lock_vec(envp, lockid, flag, &list, 1, NULL);
/*
* Now deal with whether or not the operation succeeded.
* Get's were done above, all these are only puts.
@@ -511,7 +589,12 @@ tcl_LockVec(interp, objc, objv, envp)
thisop = Tcl_NewIntObj(ret);
result = Tcl_ListObjAppendElement(interp, res, thisop);
if (ret != 0 && result == TCL_OK)
- result = _ReturnSetup(interp, ret, "lock put");
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "lock put");
+ if (freeobj) {
+ (void)__os_free(envp, otmp);
+ freeobj = 0;
+ }
/*
* We did a put of some kind. Since we did that,
* we have to delete the commands associated with
@@ -581,7 +664,7 @@ _LockPutInfo(interp, op, lock, lockid, objp)
found = 1;
if (found) {
(void)Tcl_DeleteCommand(interp, p->i_name);
- __os_free(p->i_lock, sizeof(DB_LOCK));
+ __os_free(NULL, p->i_lock);
_DeleteInfo(p);
}
}
@@ -615,16 +698,16 @@ _GetThisLock(interp, envp, lockid, flag, objp, mode, newname)
TCL_STATIC);
return (TCL_ERROR);
}
- ret = __os_malloc(envp, sizeof(DB_LOCK), NULL, &lock);
+ ret = __os_malloc(envp, sizeof(DB_LOCK), &lock);
if (ret != 0) {
Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
return (TCL_ERROR);
}
_debug_check();
- ret = lock_get(envp, lockid, flag, objp, mode, lock);
- result = _ReturnSetup(interp, ret, "lock get");
+ ret = envp->lock_get(envp, lockid, flag, objp, mode, lock);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock get");
if (result == TCL_ERROR) {
- __os_free(lock, sizeof(DB_LOCK));
+ __os_free(envp, lock);
_DeleteInfo(ip);
return (result);
}
@@ -632,12 +715,12 @@ _GetThisLock(interp, envp, lockid, flag, objp, mode, newname)
* Success. Set up return. Set up new info
* and command widget for this lock.
*/
- ret = __os_malloc(envp, objp->size, NULL, &ip->i_lockobj.data);
+ ret = __os_malloc(envp, objp->size, &ip->i_lockobj.data);
if (ret != 0) {
Tcl_SetResult(interp, "Could not duplicate obj",
TCL_STATIC);
- (void)lock_put(envp, lock);
- __os_free(lock, sizeof(DB_LOCK));
+ (void)envp->lock_put(envp, lock);
+ __os_free(envp, lock);
_DeleteInfo(ip);
result = TCL_ERROR;
goto error;
@@ -653,3 +736,4 @@ _GetThisLock(interp, envp, lockid, flag, objp, mode, newname)
error:
return (result);
}
+#endif
diff --git a/bdb/tcl/tcl_log.c b/bdb/tcl/tcl_log.c
index 20f8e8c0277..be6eebfb013 100644
--- a/bdb/tcl/tcl_log.c
+++ b/bdb/tcl/tcl_log.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_log.c,v 11.21 2000/11/30 00:58:45 ubell Exp $";
+static const char revid[] = "$Id: tcl_log.c,v 11.52 2002/08/14 20:11:57 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,12 @@ static const char revid[] = "$Id: tcl_log.c,v 11.21 2000/11/30 00:58:45 ubell Ex
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/log.h"
+#include "dbinc/tcl_db.h"
+#include "dbinc/txn.h"
+
+#ifdef CONFIG_TEST
+static int tcl_LogcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_LOGC *));
/*
* tcl_LogArchive --
@@ -73,8 +78,8 @@ tcl_LogArchive(interp, objc, objv, envp)
}
_debug_check();
list = NULL;
- ret = log_archive(envp, &list, flag, NULL);
- result = _ReturnSetup(interp, ret, "log archive");
+ ret = envp->log_archive(envp, &list, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log archive");
if (result == TCL_OK) {
res = Tcl_NewListObj(0, NULL);
for (file = list; file != NULL && *file != NULL; file++) {
@@ -86,7 +91,7 @@ tcl_LogArchive(interp, objc, objv, envp)
Tcl_SetObjResult(interp, res);
}
if (list != NULL)
- __os_free(list, 0);
+ __os_ufree(envp, list);
return (result);
}
@@ -166,24 +171,24 @@ tcl_LogFile(interp, objc, objv, envp)
name = NULL;
while (ret == ENOMEM) {
if (name != NULL)
- __os_free(name, len/2);
- ret = __os_malloc(envp, len, NULL, &name);
+ __os_free(envp, name);
+ ret = __os_malloc(envp, len, &name);
if (ret != 0) {
Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
break;
}
_debug_check();
- ret = log_file(envp, &lsn, name, len);
+ ret = envp->log_file(envp, &lsn, name, len);
len *= 2;
}
- result = _ReturnSetup(interp, ret, "log_file");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_file");
if (ret == 0) {
res = Tcl_NewStringObj(name, strlen(name));
Tcl_SetObjResult(interp, res);
}
if (name != NULL)
- __os_free(name, len/2);
+ __os_free(envp, name);
return (result);
}
@@ -222,8 +227,8 @@ tcl_LogFlush(interp, objc, objv, envp)
lsnp = NULL;
_debug_check();
- ret = log_flush(envp, lsnp);
- result = _ReturnSetup(interp, ret, "log_flush");
+ ret = envp->log_flush(envp, lsnp);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_flush");
return (result);
}
@@ -240,111 +245,13 @@ tcl_LogGet(interp, objc, objv, envp)
Tcl_Obj *CONST objv[]; /* The argument objects */
DB_ENV *envp; /* Environment pointer */
{
- static char *loggetopts[] = {
- "-checkpoint", "-current", "-first",
- "-last", "-next", "-prev",
- "-set",
- NULL
- };
- enum loggetopts {
- LOGGET_CKP, LOGGET_CUR, LOGGET_FIRST,
- LOGGET_LAST, LOGGET_NEXT, LOGGET_PREV,
- LOGGET_SET
- };
- DB_LSN lsn;
- DBT data;
- Tcl_Obj *dataobj, *lsnlist, *myobjv[2], *res;
- u_int32_t flag;
- int i, myobjc, optindex, result, ret;
-
- result = TCL_OK;
- flag = 0;
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-args? lsn");
- return (TCL_ERROR);
- }
-
- /*
- * Get the command name index from the object based on the options
- * defined above.
- */
- i = 2;
- while (i < objc) {
- if (Tcl_GetIndexFromObj(interp, objv[i],
- loggetopts, "option", TCL_EXACT, &optindex) != TCL_OK)
- return (IS_HELP(objv[i]));
- i++;
- switch ((enum loggetopts)optindex) {
- case LOGGET_CKP:
- FLAG_CHECK(flag);
- flag |= DB_CHECKPOINT;
- break;
- case LOGGET_CUR:
- FLAG_CHECK(flag);
- flag |= DB_CURRENT;
- break;
- case LOGGET_FIRST:
- FLAG_CHECK(flag);
- flag |= DB_FIRST;
- break;
- case LOGGET_LAST:
- FLAG_CHECK(flag);
- flag |= DB_LAST;
- break;
- case LOGGET_NEXT:
- FLAG_CHECK(flag);
- flag |= DB_NEXT;
- break;
- case LOGGET_PREV:
- FLAG_CHECK(flag);
- flag |= DB_PREV;
- break;
- case LOGGET_SET:
- FLAG_CHECK(flag);
- flag |= DB_SET;
- if (i == objc) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-set lsn?");
- result = TCL_ERROR;
- break;
- }
- result = _GetLsn(interp, objv[i++], &lsn);
- break;
- }
- }
- if (result == TCL_ERROR)
- return (result);
-
- memset(&data, 0, sizeof(data));
- data.flags |= DB_DBT_MALLOC;
- _debug_check();
- ret = log_get(envp, &lsn, &data, flag);
- res = Tcl_NewListObj(0, NULL);
- result = _ReturnSetup(interp, ret, "log_get");
- if (ret == 0) {
- /*
- * Success. Set up return list as {LSN data} where LSN
- * is a sublist {file offset}.
- */
- myobjc = 2;
- myobjv[0] = Tcl_NewIntObj(lsn.file);
- myobjv[1] = Tcl_NewIntObj(lsn.offset);
- lsnlist = Tcl_NewListObj(myobjc, myobjv);
- if (lsnlist == NULL) {
- if (data.data != NULL)
- __os_free(data.data, data.size);
- return (TCL_ERROR);
- }
- result = Tcl_ListObjAppendElement(interp, res, lsnlist);
- dataobj = Tcl_NewStringObj(data.data, data.size);
- result = Tcl_ListObjAppendElement(interp, res, dataobj);
- }
- if (data.data != NULL)
- __os_free(data.data, data.size);
+ COMPQUIET(objv, NULL);
+ COMPQUIET(objc, 0);
+ COMPQUIET(envp, NULL);
- if (result == TCL_OK)
- Tcl_SetObjResult(interp, res);
- return (result);
+ Tcl_SetResult(interp, "FAIL: log_get deprecated\n", TCL_STATIC);
+ return (TCL_ERROR);
}
/*
@@ -361,20 +268,22 @@ tcl_LogPut(interp, objc, objv, envp)
DB_ENV *envp; /* Environment pointer */
{
static char *logputopts[] = {
- "-checkpoint", "-curlsn", "-flush",
+ "-flush",
NULL
};
enum logputopts {
- LOGPUT_CKP, LOGPUT_CUR, LOGPUT_FLUSH
+ LOGPUT_FLUSH
};
DB_LSN lsn;
DBT data;
Tcl_Obj *intobj, *res;
+ void *dtmp;
u_int32_t flag;
- int itmp, optindex, result, ret;
+ int freedata, optindex, result, ret;
result = TCL_OK;
flag = 0;
+ freedata = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?-args? record");
return (TCL_ERROR);
@@ -384,8 +293,14 @@ tcl_LogPut(interp, objc, objv, envp)
* Data/record must be the last arg.
*/
memset(&data, 0, sizeof(data));
- data.data = Tcl_GetByteArrayFromObj(objv[objc-1], &itmp);
- data.size = itmp;
+ ret = _CopyObjBytes(interp, objv[objc-1], &dtmp,
+ &data.size, &freedata);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_STD(ret), "log put");
+ return (result);
+ }
+ data.data = dtmp;
/*
* Get the command name index from the object based on the options
@@ -397,12 +312,6 @@ tcl_LogPut(interp, objc, objv, envp)
return (IS_HELP(objv[2]));
}
switch ((enum logputopts)optindex) {
- case LOGPUT_CKP:
- flag = DB_CHECKPOINT;
- break;
- case LOGPUT_CUR:
- flag = DB_CURLSN;
- break;
case LOGPUT_FLUSH:
flag = DB_FLUSH;
break;
@@ -413,69 +322,20 @@ tcl_LogPut(interp, objc, objv, envp)
return (result);
_debug_check();
- ret = log_put(envp, &lsn, &data, flag);
- result = _ReturnSetup(interp, ret, "log_put");
+ ret = envp->log_put(envp, &lsn, &data, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_put");
if (result == TCL_ERROR)
return (result);
res = Tcl_NewListObj(0, NULL);
- intobj = Tcl_NewIntObj(lsn.file);
+ intobj = Tcl_NewLongObj((long)lsn.file);
result = Tcl_ListObjAppendElement(interp, res, intobj);
- intobj = Tcl_NewIntObj(lsn.offset);
+ intobj = Tcl_NewLongObj((long)lsn.offset);
result = Tcl_ListObjAppendElement(interp, res, intobj);
Tcl_SetObjResult(interp, res);
+ if (freedata)
+ (void)__os_free(NULL, dtmp);
return (result);
}
-
-/*
- * tcl_LogRegister --
- *
- * PUBLIC: int tcl_LogRegister __P((Tcl_Interp *, int,
- * PUBLIC: Tcl_Obj * CONST*, DB_ENV *));
- */
-int
-tcl_LogRegister(interp, objc, objv, envp)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
- DB_ENV *envp; /* Environment pointer */
-{
- DB *dbp;
- Tcl_Obj *res;
- int result, ret;
- char *arg, msg[MSG_SIZE];
-
- result = TCL_OK;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "db filename");
- return (TCL_ERROR);
- }
- /*
- * First comes the DB.
- */
- arg = Tcl_GetStringFromObj(objv[2], NULL);
- dbp = NAME_TO_DB(arg);
- if (dbp == NULL) {
- snprintf(msg, MSG_SIZE,
- "LogRegister: Invalid db: %s\n", arg);
- Tcl_SetResult(interp, msg, TCL_VOLATILE);
- return (TCL_ERROR);
- }
-
- /*
- * Next is the filename.
- */
- arg = Tcl_GetStringFromObj(objv[3], NULL);
-
- _debug_check();
- ret = log_register(envp, dbp, arg);
- result = _ReturnSetup(interp, ret, "log_register");
- if (result == TCL_OK) {
- res = Tcl_NewIntObj((int)dbp->log_fileid);
- Tcl_SetObjResult(interp, res);
- }
- return (result);
-}
-
/*
* tcl_LogStat --
*
@@ -502,8 +362,8 @@ tcl_LogStat(interp, objc, objv, envp)
return (TCL_ERROR);
}
_debug_check();
- ret = log_stat(envp, &sp, NULL);
- result = _ReturnSetup(interp, ret, "log stat");
+ ret = envp->log_stat(envp, &sp, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log stat");
if (result == TCL_ERROR)
return (result);
@@ -520,7 +380,7 @@ tcl_LogStat(interp, objc, objv, envp)
MAKE_STAT_LIST("Region size", sp->st_regsize);
MAKE_STAT_LIST("Log file mode", sp->st_mode);
MAKE_STAT_LIST("Log record cache size", sp->st_lg_bsize);
- MAKE_STAT_LIST("Maximum log file size", sp->st_lg_max);
+ MAKE_STAT_LIST("Current log file size", sp->st_lg_size);
MAKE_STAT_LIST("Mbytes written", sp->st_w_mbytes);
MAKE_STAT_LIST("Bytes written (over Mb)", sp->st_w_bytes);
MAKE_STAT_LIST("Mbytes written since checkpoint", sp->st_wc_mbytes);
@@ -532,50 +392,219 @@ tcl_LogStat(interp, objc, objv, envp)
MAKE_STAT_LIST("Times log flushed", sp->st_scount);
MAKE_STAT_LIST("Current log file number", sp->st_cur_file);
MAKE_STAT_LIST("Current log file offset", sp->st_cur_offset);
+ MAKE_STAT_LIST("On-disk log file number", sp->st_disk_file);
+ MAKE_STAT_LIST("On-disk log file offset", sp->st_disk_offset);
+ MAKE_STAT_LIST("Max commits in a log flush", sp->st_maxcommitperflush);
+ MAKE_STAT_LIST("Min commits in a log flush", sp->st_mincommitperflush);
MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
Tcl_SetObjResult(interp, res);
error:
- __os_free(sp, sizeof(*sp));
+ free(sp);
return (result);
}
/*
- * tcl_LogUnregister --
+ * logc_Cmd --
+ * Implements the log cursor command.
*
- * PUBLIC: int tcl_LogUnregister __P((Tcl_Interp *, int,
- * PUBLIC: Tcl_Obj * CONST*, DB_ENV *));
+ * PUBLIC: int logc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
*/
int
-tcl_LogUnregister(interp, objc, objv, envp)
+logc_Cmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Cursor handle */
Tcl_Interp *interp; /* Interpreter */
int objc; /* How many arguments? */
Tcl_Obj *CONST objv[]; /* The argument objects */
- DB_ENV *envp; /* Environment pointer */
{
- DB *dbp;
- char *arg, msg[MSG_SIZE];
- int result, ret;
+ static char *logccmds[] = {
+ "close",
+ "get",
+ NULL
+ };
+ enum logccmds {
+ LOGCCLOSE,
+ LOGCGET
+ };
+ DB_LOGC *logc;
+ DBTCL_INFO *logcip;
+ int cmdindex, result, ret;
+ Tcl_ResetResult(interp);
+ logc = (DB_LOGC *)clientData;
+ logcip = _PtrToInfo((void *)logc);
result = TCL_OK;
+
+ if (objc <= 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
+ return (TCL_ERROR);
+ }
+ if (logc == NULL) {
+ Tcl_SetResult(interp, "NULL logc pointer", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+ if (logcip == NULL) {
+ Tcl_SetResult(interp, "NULL logc info pointer", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
/*
- * 1 arg for this. Error if more or less.
+ * Get the command name index from the object based on the berkdbcmds
+ * defined above.
*/
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return (TCL_ERROR);
+ if (Tcl_GetIndexFromObj(interp, objv[1], logccmds, "command",
+ TCL_EXACT, &cmdindex) != TCL_OK)
+ return (IS_HELP(objv[1]));
+ switch ((enum logccmds)cmdindex) {
+ case LOGCCLOSE:
+ /*
+ * No args for this. Error if there are some.
+ */
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ _debug_check();
+ ret = logc->close(logc, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "logc close");
+ if (result == TCL_OK) {
+ (void)Tcl_DeleteCommand(interp, logcip->i_name);
+ _DeleteInfo(logcip);
+ }
+ break;
+ case LOGCGET:
+ result = tcl_LogcGet(interp, objc, objv, logc);
+ break;
}
- arg = Tcl_GetStringFromObj(objv[2], NULL);
- dbp = NAME_TO_DB(arg);
- if (dbp == NULL) {
- snprintf(msg, MSG_SIZE,
- "log_unregister: Invalid db identifier: %s\n", arg);
- Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ return (result);
+}
+
+static int
+tcl_LogcGet(interp, objc, objv, logc)
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj * CONST *objv;
+ DB_LOGC *logc;
+{
+ static char *logcgetopts[] = {
+ "-current",
+ "-first",
+ "-last",
+ "-next",
+ "-prev",
+ "-set",
+ NULL
+ };
+ enum logcgetopts {
+ LOGCGET_CURRENT,
+ LOGCGET_FIRST,
+ LOGCGET_LAST,
+ LOGCGET_NEXT,
+ LOGCGET_PREV,
+ LOGCGET_SET
+ };
+ DB_LSN lsn;
+ DBT data;
+ Tcl_Obj *dataobj, *lsnlist, *myobjv[2], *res;
+ u_int32_t flag;
+ int i, myobjc, optindex, result, ret;
+
+ result = TCL_OK;
+ res = NULL;
+ flag = 0;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-args? lsn");
return (TCL_ERROR);
}
+
+ /*
+ * Get the command name index from the object based on the options
+ * defined above.
+ */
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i],
+ logcgetopts, "option", TCL_EXACT, &optindex) != TCL_OK)
+ return (IS_HELP(objv[i]));
+ i++;
+ switch ((enum logcgetopts)optindex) {
+ case LOGCGET_CURRENT:
+ FLAG_CHECK(flag);
+ flag |= DB_CURRENT;
+ break;
+ case LOGCGET_FIRST:
+ FLAG_CHECK(flag);
+ flag |= DB_FIRST;
+ break;
+ case LOGCGET_LAST:
+ FLAG_CHECK(flag);
+ flag |= DB_LAST;
+ break;
+ case LOGCGET_NEXT:
+ FLAG_CHECK(flag);
+ flag |= DB_NEXT;
+ break;
+ case LOGCGET_PREV:
+ FLAG_CHECK(flag);
+ flag |= DB_PREV;
+ break;
+ case LOGCGET_SET:
+ FLAG_CHECK(flag);
+ flag |= DB_SET;
+ if (i == objc) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-set lsn?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = _GetLsn(interp, objv[i++], &lsn);
+ break;
+ }
+ }
+
+ if (result == TCL_ERROR)
+ return (result);
+
+ memset(&data, 0, sizeof(data));
+
_debug_check();
- ret = log_unregister(envp, dbp);
- result = _ReturnSetup(interp, ret, "log_unregister");
+ ret = logc->get(logc, &lsn, &data, flag);
+
+ res = Tcl_NewListObj(0, NULL);
+ if (res == NULL)
+ goto memerr;
+
+ if (ret == 0) {
+ /*
+ * Success. Set up return list as {LSN data} where LSN
+ * is a sublist {file offset}.
+ */
+ myobjc = 2;
+ myobjv[0] = Tcl_NewLongObj((long)lsn.file);
+ myobjv[1] = Tcl_NewLongObj((long)lsn.offset);
+ lsnlist = Tcl_NewListObj(myobjc, myobjv);
+ if (lsnlist == NULL)
+ goto memerr;
+
+ result = Tcl_ListObjAppendElement(interp, res, lsnlist);
+ dataobj = Tcl_NewStringObj(data.data, data.size);
+ if (dataobj == NULL) {
+ goto memerr;
+ }
+ result = Tcl_ListObjAppendElement(interp, res, dataobj);
+ } else
+ result = _ReturnSetup(interp, ret, DB_RETOK_LGGET(ret),
+ "DB_LOGC->get");
+
+ Tcl_SetObjResult(interp, res);
+
+ if (0) {
+memerr: if (res != NULL)
+ Tcl_DecrRefCount(res);
+ Tcl_SetResult(interp, "allocation failed", TCL_STATIC);
+ }
return (result);
}
+#endif
diff --git a/bdb/tcl/tcl_mp.c b/bdb/tcl/tcl_mp.c
index b424deea242..0c4411cb58a 100644
--- a/bdb/tcl/tcl_mp.c
+++ b/bdb/tcl/tcl_mp.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_mp.c,v 11.24 2001/01/09 16:13:59 sue Exp $";
+static const char revid[] = "$Id: tcl_mp.c,v 11.39 2002/08/06 06:21:27 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,7 @@ static const char revid[] = "$Id: tcl_mp.c,v 11.24 2001/01/09 16:13:59 sue Exp $
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/tcl_db.h"
/*
* Prototypes for procedures defined later in this file:
@@ -45,7 +45,7 @@ static int tcl_PgIsset __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
*/
void
_MpInfoDelete(interp, mpip)
- Tcl_Interp *interp; /* Interpreter */
+ Tcl_Interp *interp; /* Interpreter */
DBTCL_INFO *mpip; /* Info for mp */
{
DBTCL_INFO *nextp, *p;
@@ -63,6 +63,7 @@ _MpInfoDelete(interp, mpip)
}
}
+#if CONFIG_TEST
/*
* tcl_MpSync --
*
@@ -76,25 +77,28 @@ tcl_MpSync(interp, objc, objv, envp)
DB_ENV *envp; /* Environment pointer */
{
- DB_LSN lsn;
+ DB_LSN lsn, *lsnp;
int result, ret;
result = TCL_OK;
+ lsnp = NULL;
/*
* No flags, must be 3 args.
*/
- if (objc != 3) {
+ if (objc == 3) {
+ result = _GetLsn(interp, objv[2], &lsn);
+ if (result == TCL_ERROR)
+ return (result);
+ lsnp = &lsn;
+ }
+ else if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, "lsn");
return (TCL_ERROR);
}
- result = _GetLsn(interp, objv[2], &lsn);
- if (result == TCL_ERROR)
- return (result);
-
_debug_check();
- ret = memp_sync(envp, &lsn);
- result = _ReturnSetup(interp, ret, "memp sync");
+ ret = envp->memp_sync(envp, lsnp);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp sync");
return (result);
}
@@ -132,8 +136,8 @@ tcl_MpTrickle(interp, objc, objv, envp)
return (result);
_debug_check();
- ret = memp_trickle(envp, percent, &pages);
- result = _ReturnSetup(interp, ret, "memp trickle");
+ ret = envp->memp_trickle(envp, percent, &pages);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp trickle");
if (result == TCL_ERROR)
return (result);
@@ -264,29 +268,39 @@ tcl_Mp(interp, objc, objv, envp, envip)
TCL_STATIC);
return (TCL_ERROR);
}
+
+ _debug_check();
+ if ((ret = envp->memp_fcreate(envp, &mpf, 0)) != 0) {
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool");
+ _DeleteInfo(ip);
+ goto error;
+ }
+
/*
- * XXX finfop is NULL here. Interface currently doesn't
- * have all the stuff. Should expand interface.
+ * XXX
+ * Interface doesn't currently support DB_MPOOLFILE configuration.
*/
- _debug_check();
- ret = memp_fopen(envp, file, flag, mode, (size_t)pgsize, NULL, &mpf);
- if (ret != 0) {
- result = _ReturnSetup(interp, ret, "mpool");
+ if ((ret = mpf->open(mpf, file, flag, mode, (size_t)pgsize)) != 0) {
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool");
_DeleteInfo(ip);
- } else {
- /*
- * Success. Set up return. Set up new info
- * and command widget for this mpool.
- */
- envip->i_envmpid++;
- ip->i_parent = envip;
- ip->i_pgsz = pgsize;
- _SetInfoData(ip, mpf);
- Tcl_CreateObjCommand(interp, newname,
- (Tcl_ObjCmdProc *)mp_Cmd, (ClientData)mpf, NULL);
- res = Tcl_NewStringObj(newname, strlen(newname));
- Tcl_SetObjResult(interp, res);
+
+ (void)mpf->close(mpf, 0);
+ goto error;
}
+
+ /*
+ * Success. Set up return. Set up new info and command widget for
+ * this mpool.
+ */
+ envip->i_envmpid++;
+ ip->i_parent = envip;
+ ip->i_pgsz = pgsize;
+ _SetInfoData(ip, mpf);
+ Tcl_CreateObjCommand(interp, newname,
+ (Tcl_ObjCmdProc *)mp_Cmd, (ClientData)mpf, NULL);
+ res = Tcl_NewStringObj(newname, strlen(newname));
+ Tcl_SetObjResult(interp, res);
+
error:
return (result);
}
@@ -320,8 +334,8 @@ tcl_MpStat(interp, objc, objv, envp)
return (TCL_ERROR);
}
_debug_check();
- ret = memp_stat(envp, &sp, &fsp, NULL);
- result = _ReturnSetup(interp, ret, "memp stat");
+ ret = envp->memp_stat(envp, &sp, &fsp, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp stat");
if (result == TCL_ERROR)
return (result);
@@ -333,35 +347,48 @@ tcl_MpStat(interp, objc, objv, envp)
/*
* MAKE_STAT_LIST assumes 'res' and 'error' label.
*/
- MAKE_STAT_LIST("Region size", sp->st_regsize);
MAKE_STAT_LIST("Cache size (gbytes)", sp->st_gbytes);
MAKE_STAT_LIST("Cache size (bytes)", sp->st_bytes);
- MAKE_STAT_LIST("Cache hits", sp->st_cache_hit);
- MAKE_STAT_LIST("Cache misses", sp->st_cache_miss);
MAKE_STAT_LIST("Number of caches", sp->st_ncache);
+ MAKE_STAT_LIST("Region size", sp->st_regsize);
MAKE_STAT_LIST("Pages mapped into address space", sp->st_map);
+ MAKE_STAT_LIST("Cache hits", sp->st_cache_hit);
+ MAKE_STAT_LIST("Cache misses", sp->st_cache_miss);
MAKE_STAT_LIST("Pages created", sp->st_page_create);
MAKE_STAT_LIST("Pages read in", sp->st_page_in);
MAKE_STAT_LIST("Pages written", sp->st_page_out);
MAKE_STAT_LIST("Clean page evictions", sp->st_ro_evict);
MAKE_STAT_LIST("Dirty page evictions", sp->st_rw_evict);
+ MAKE_STAT_LIST("Dirty pages trickled", sp->st_page_trickle);
+ MAKE_STAT_LIST("Cached pages", sp->st_pages);
+ MAKE_STAT_LIST("Cached clean pages", sp->st_page_clean);
+ MAKE_STAT_LIST("Cached dirty pages", sp->st_page_dirty);
MAKE_STAT_LIST("Hash buckets", sp->st_hash_buckets);
MAKE_STAT_LIST("Hash lookups", sp->st_hash_searches);
MAKE_STAT_LIST("Longest hash chain found", sp->st_hash_longest);
MAKE_STAT_LIST("Hash elements examined", sp->st_hash_examined);
- MAKE_STAT_LIST("Cached clean pages", sp->st_page_clean);
- MAKE_STAT_LIST("Cached dirty pages", sp->st_page_dirty);
- MAKE_STAT_LIST("Dirty pages trickled", sp->st_page_trickle);
- MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
+ MAKE_STAT_LIST("Number of hash bucket nowaits", sp->st_hash_nowait);
+ MAKE_STAT_LIST("Number of hash bucket waits", sp->st_hash_wait);
+ MAKE_STAT_LIST("Maximum number of hash bucket waits",
+ sp->st_hash_max_wait);
MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
+ MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
+ MAKE_STAT_LIST("Page allocations", sp->st_alloc);
+ MAKE_STAT_LIST("Buckets examined during allocation",
+ sp->st_alloc_buckets);
+ MAKE_STAT_LIST("Maximum buckets examined during allocation",
+ sp->st_alloc_max_buckets);
+ MAKE_STAT_LIST("Pages examined during allocation", sp->st_alloc_pages);
+ MAKE_STAT_LIST("Maximum pages examined during allocation",
+ sp->st_alloc_max_pages);
+
/*
* Save global stat list as res1. The MAKE_STAT_LIST
* macro assumes 'res' so we'll use that to build up
* our per-file sublist.
*/
res1 = res;
- savefsp = fsp;
- for (; fsp != NULL && *fsp != NULL; fsp++) {
+ for (savefsp = fsp; fsp != NULL && *fsp != NULL; fsp++) {
res = Tcl_NewObj();
result = _SetListElem(interp, res, "File Name",
strlen("File Name"), (*fsp)->file_name,
@@ -369,16 +396,16 @@ tcl_MpStat(interp, objc, objv, envp)
if (result != TCL_OK)
goto error;
MAKE_STAT_LIST("Page size", (*fsp)->st_pagesize);
- MAKE_STAT_LIST("Cache Hits", (*fsp)->st_cache_hit);
- MAKE_STAT_LIST("Cache Misses", (*fsp)->st_cache_miss);
MAKE_STAT_LIST("Pages mapped into address space",
(*fsp)->st_map);
+ MAKE_STAT_LIST("Cache hits", (*fsp)->st_cache_hit);
+ MAKE_STAT_LIST("Cache misses", (*fsp)->st_cache_miss);
MAKE_STAT_LIST("Pages created", (*fsp)->st_page_create);
MAKE_STAT_LIST("Pages read in", (*fsp)->st_page_in);
MAKE_STAT_LIST("Pages written", (*fsp)->st_page_out);
/*
- * Now that we have a complete "per-file" stat
- * list, append that to the other list.
+ * Now that we have a complete "per-file" stat list, append
+ * that to the other list.
*/
result = Tcl_ListObjAppendElement(interp, res1, res);
if (result != TCL_OK)
@@ -386,9 +413,9 @@ tcl_MpStat(interp, objc, objv, envp)
}
Tcl_SetObjResult(interp, res1);
error:
- __os_free(sp, sizeof(*sp));
+ free(sp);
if (savefsp != NULL)
- __os_free(savefsp, 0);
+ free(savefsp);
return (result);
}
@@ -398,17 +425,21 @@ error:
*/
static int
mp_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Mp handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ ClientData clientData; /* Mp handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *mpcmds[] = {
- "close", "fsync", "get",
+ "close",
+ "fsync",
+ "get",
NULL
};
enum mpcmds {
- MPCLOSE, MPFSYNC, MPGET
+ MPCLOSE,
+ MPFSYNC,
+ MPGET
};
DB_MPOOLFILE *mp;
int cmdindex, length, result, ret;
@@ -447,8 +478,9 @@ mp_Cmd(clientData, interp, objc, objv)
return (TCL_ERROR);
}
_debug_check();
- ret = memp_fclose(mp);
- result = _ReturnSetup(interp, ret, "mp close");
+ ret = mp->close(mp, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "mp close");
_MpInfoDelete(interp, mpip);
(void)Tcl_DeleteCommand(interp, mpip->i_name);
_DeleteInfo(mpip);
@@ -459,7 +491,7 @@ mp_Cmd(clientData, interp, objc, objv)
return (TCL_ERROR);
}
_debug_check();
- ret = memp_fsync(mp);
+ ret = mp->sync(mp);
res = Tcl_NewIntObj(ret);
break;
case MPGET:
@@ -487,11 +519,15 @@ tcl_MpGet(interp, objc, objv, mp, mpip)
DBTCL_INFO *mpip; /* mp info pointer */
{
static char *mpget[] = {
- "-create", "-last", "-new",
+ "-create",
+ "-last",
+ "-new",
NULL
};
enum mpget {
- MPGET_CREATE, MPGET_LAST, MPGET_NEW
+ MPGET_CREATE,
+ MPGET_LAST,
+ MPGET_NEW
};
DBTCL_INFO *ip;
@@ -559,8 +595,8 @@ tcl_MpGet(interp, objc, objv, mp, mpip)
}
_debug_check();
pgno = ipgno;
- ret = memp_fget(mp, &pgno, flag, &page);
- result = _ReturnSetup(interp, ret, "mpool get");
+ ret = mp->get(mp, &pgno, flag, &page);
+ result = _ReturnSetup(interp, ret, DB_RETOK_MPGET(ret), "mpool get");
if (result == TCL_ERROR)
_DeleteInfo(ip);
else {
@@ -588,10 +624,10 @@ error:
*/
static int
pg_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Page handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ ClientData clientData; /* Page handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *pgcmds[] = {
"init",
@@ -648,7 +684,7 @@ pg_Cmd(clientData, interp, objc, objv)
res = NULL;
switch ((enum pgcmds)cmdindex) {
case PGNUM:
- res = Tcl_NewIntObj(pgip->i_pgno);
+ res = Tcl_NewLongObj((long)pgip->i_pgno);
break;
case PGSIZE:
res = Tcl_NewLongObj(pgip->i_pgsz);
@@ -685,11 +721,15 @@ tcl_Pg(interp, objc, objv, page, mp, pgip, putop)
int putop; /* Operation */
{
static char *pgopt[] = {
- "-clean", "-dirty", "-discard",
+ "-clean",
+ "-dirty",
+ "-discard",
NULL
};
enum pgopt {
- PGCLEAN, PGDIRTY, PGDISCARD
+ PGCLEAN,
+ PGDIRTY,
+ PGDISCARD
};
u_int32_t flag;
int i, optindex, result, ret;
@@ -717,11 +757,11 @@ tcl_Pg(interp, objc, objv, page, mp, pgip, putop)
_debug_check();
if (putop)
- ret = memp_fput(mp, page, flag);
+ ret = mp->put(mp, page, flag);
else
- ret = memp_fset(mp, page, flag);
+ ret = mp->set(mp, page, flag);
- result = _ReturnSetup(interp, ret, "page");
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "page");
if (putop) {
(void)Tcl_DeleteCommand(interp, pgip->i_name);
@@ -756,7 +796,8 @@ tcl_PgInit(interp, objc, objv, page, pgip)
s = Tcl_GetByteArrayFromObj(objv[2], &length);
if (s == NULL)
return (TCL_ERROR);
- memcpy(page, s, ((size_t)length < pgsz) ? length : pgsz);
+ memcpy(page, s,
+ ((size_t)length < pgsz) ? (size_t)length : pgsz);
result = TCL_OK;
} else {
p = (long *)page;
@@ -795,8 +836,8 @@ tcl_PgIsset(interp, objc, objv, page, pgip)
return (TCL_ERROR);
result = TCL_OK;
- if (memcmp(page,
- s, ((size_t)length < pgsz) ? length : pgsz ) != 0) {
+ if (memcmp(page, s,
+ ((size_t)length < pgsz) ? (size_t)length : pgsz ) != 0) {
res = Tcl_NewIntObj(0);
Tcl_SetObjResult(interp, res);
return (result);
@@ -820,3 +861,4 @@ tcl_PgIsset(interp, objc, objv, page, pgip)
Tcl_SetObjResult(interp, res);
return (result);
}
+#endif
diff --git a/bdb/tcl/tcl_rep.c b/bdb/tcl/tcl_rep.c
new file mode 100644
index 00000000000..c72c9971338
--- /dev/null
+++ b/bdb/tcl/tcl_rep.c
@@ -0,0 +1,405 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: tcl_rep.c,v 11.85 2002/08/06 04:45:44 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/tcl_db.h"
+
+#if CONFIG_TEST
+/*
+ * tcl_RepElect --
+ * Call DB_ENV->rep_elect().
+ *
+ * PUBLIC: int tcl_RepElect
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ */
+int
+tcl_RepElect(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv; /* Environment pointer */
+{
+ int eid, nsites, pri, result, ret;
+ u_int32_t timeout;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 5, objv, "nsites pri timeout");
+ return (TCL_ERROR);
+ }
+
+ if ((result = Tcl_GetIntFromObj(interp, objv[2], &nsites)) != TCL_OK)
+ return (result);
+ if ((result = Tcl_GetIntFromObj(interp, objv[3], &pri)) != TCL_OK)
+ return (result);
+ if ((result = _GetUInt32(interp, objv[4], &timeout)) != TCL_OK)
+ return (result);
+
+ _debug_check();
+ if ((ret = dbenv->rep_elect(dbenv, nsites, pri, timeout, &eid)) != 0)
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env rep_elect"));
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(eid));
+
+ return (TCL_OK);
+}
+#endif
+
+#if CONFIG_TEST
+/*
+ * tcl_RepFlush --
+ * Call DB_ENV->rep_flush().
+ *
+ * PUBLIC: int tcl_RepFlush
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ */
+int
+tcl_RepFlush(interp, objc, objv, dbenv)
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+ DB_ENV *dbenv;
+{
+ int ret;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+
+ _debug_check();
+ ret = dbenv->rep_flush(dbenv);
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_flush"));
+}
+#endif
+#if CONFIG_TEST
+/*
+ * tcl_RepLimit --
+ * Call DB_ENV->set_rep_limit().
+ *
+ * PUBLIC: int tcl_RepLimit
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ */
+int
+tcl_RepLimit(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv; /* Environment pointer */
+{
+ int result, ret;
+ u_int32_t bytes, gbytes;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 4, objv, "gbytes bytes");
+ return (TCL_ERROR);
+ }
+
+ if ((result = _GetUInt32(interp, objv[2], &gbytes)) != TCL_OK)
+ return (result);
+ if ((result = _GetUInt32(interp, objv[3], &bytes)) != TCL_OK)
+ return (result);
+
+ _debug_check();
+ if ((ret = dbenv->set_rep_limit(dbenv, gbytes, bytes)) != 0)
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env set_rep_limit"));
+
+ return (_ReturnSetup(interp,
+ ret, DB_RETOK_STD(ret), "env set_rep_limit"));
+}
+#endif
+
+#if CONFIG_TEST
+/*
+ * tcl_RepRequest --
+ * Call DB_ENV->set_rep_request().
+ *
+ * PUBLIC: int tcl_RepRequest
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ */
+int
+tcl_RepRequest(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv; /* Environment pointer */
+{
+ int result, ret;
+ u_int32_t min, max;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 4, objv, "min max");
+ return (TCL_ERROR);
+ }
+
+ if ((result = _GetUInt32(interp, objv[2], &min)) != TCL_OK)
+ return (result);
+ if ((result = _GetUInt32(interp, objv[3], &max)) != TCL_OK)
+ return (result);
+
+ _debug_check();
+ if ((ret = dbenv->set_rep_request(dbenv, min, max)) != 0)
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "env set_rep_request"));
+
+ return (_ReturnSetup(interp,
+ ret, DB_RETOK_STD(ret), "env set_rep_request"));
+}
+#endif
+
+#if CONFIG_TEST
+/*
+ * tcl_RepStart --
+ * Call DB_ENV->rep_start().
+ *
+ * PUBLIC: int tcl_RepStart
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ *
+ * Note that this normally can/should be achieved as an argument to
+ * berkdb env, but we need to test forcible upgrading of clients, which
+ * involves calling this on an open environment handle.
+ */
+int
+tcl_RepStart(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv;
+{
+ static char *tclrpstrt[] = {
+ "-client",
+ "-master",
+ NULL
+ };
+ enum tclrpstrt {
+ TCL_RPSTRT_CLIENT,
+ TCL_RPSTRT_MASTER
+ };
+ char *arg;
+ int i, optindex, ret;
+ u_int32_t flag;
+
+ flag = 0;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, "[-master/-client]");
+ return (TCL_ERROR);
+ }
+
+ i = 2;
+ while (i < objc) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], tclrpstrt,
+ "option", TCL_EXACT, &optindex) != TCL_OK) {
+ arg = Tcl_GetStringFromObj(objv[i], NULL);
+ if (arg[0] == '-')
+ return (IS_HELP(objv[i]));
+ else
+ Tcl_ResetResult(interp);
+ break;
+ }
+ i++;
+ switch ((enum tclrpstrt)optindex) {
+ case TCL_RPSTRT_CLIENT:
+ flag |= DB_REP_CLIENT;
+ break;
+ case TCL_RPSTRT_MASTER:
+ flag |= DB_REP_MASTER;
+ break;
+ }
+ }
+
+ _debug_check();
+ ret = dbenv->rep_start(dbenv, NULL, flag);
+ return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_start"));
+}
+#endif
+
+#if CONFIG_TEST
+/*
+ * tcl_RepProcessMessage --
+ * Call DB_ENV->rep_process_message().
+ *
+ * PUBLIC: int tcl_RepProcessMessage
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ */
+int
+tcl_RepProcessMessage(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv; /* Environment pointer */
+{
+ DBT control, rec;
+ Tcl_Obj *res;
+ void *ctmp, *rtmp;
+ int eid;
+ int freectl, freerec, result, ret;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 5, objv, "id control rec");
+ return (TCL_ERROR);
+ }
+ freectl = freerec = 0;
+
+ memset(&control, 0, sizeof(control));
+ memset(&rec, 0, sizeof(rec));
+
+ if ((result = Tcl_GetIntFromObj(interp, objv[2], &eid)) != TCL_OK)
+ return (result);
+
+ ret = _CopyObjBytes(interp, objv[3], &ctmp,
+ &control.size, &freectl);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_REPPMSG(ret), "rep_proc_msg");
+ return (result);
+ }
+ control.data = ctmp;
+ ret = _CopyObjBytes(interp, objv[4], &rtmp,
+ &rec.size, &freerec);
+ if (ret != 0) {
+ result = _ReturnSetup(interp, ret,
+ DB_RETOK_REPPMSG(ret), "rep_proc_msg");
+ goto out;
+ }
+ rec.data = rtmp;
+ _debug_check();
+ ret = dbenv->rep_process_message(dbenv, &control, &rec, &eid);
+ result = _ReturnSetup(interp, ret, DB_RETOK_REPPMSG(ret),
+ "env rep_process_message");
+
+ /*
+ * If we have a new master, return its environment ID.
+ *
+ * XXX
+ * We should do something prettier to differentiate success
+ * from an env ID, and figure out how to represent HOLDELECTION.
+ */
+ if (result == TCL_OK && ret == DB_REP_NEWMASTER) {
+ res = Tcl_NewIntObj(eid);
+ Tcl_SetObjResult(interp, res);
+ }
+out:
+ if (freectl)
+ (void)__os_free(NULL, ctmp);
+ if (freerec)
+ (void)__os_free(NULL, rtmp);
+
+ return (result);
+}
+#endif
+
+#if CONFIG_TEST
+/*
+ * tcl_RepStat --
+ * Call DB_ENV->rep_stat().
+ *
+ * PUBLIC: int tcl_RepStat
+ * PUBLIC: __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
+ */
+int
+tcl_RepStat(interp, objc, objv, dbenv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *dbenv;
+{
+ DB_REP_STAT *sp;
+ Tcl_Obj *myobjv[2], *res, *thislist, *lsnlist;
+ u_int32_t flag;
+ int myobjc, result, ret;
+ char *arg;
+
+ result = TCL_OK;
+ flag = 0;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ if (objc == 3) {
+ arg = Tcl_GetStringFromObj(objv[2], NULL);
+ if (strcmp(arg, "-clear") == 0)
+ flag = DB_STAT_CLEAR;
+ else {
+ Tcl_SetResult(interp,
+ "db stat: unknown arg", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+ }
+
+ _debug_check();
+ ret = dbenv->rep_stat(dbenv, &sp, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "rep stat");
+ if (result == TCL_ERROR)
+ return (result);
+
+ /*
+ * Have our stats, now construct the name value
+ * list pairs and free up the memory.
+ */
+ res = Tcl_NewObj();
+ /*
+ * MAKE_STAT_* assumes 'res' and 'error' label.
+ */
+ MAKE_STAT_LSN("Next LSN expected", &sp->st_next_lsn);
+ MAKE_STAT_LSN("First missed LSN", &sp->st_waiting_lsn);
+ MAKE_STAT_LIST("Duplicate master conditions", sp->st_dupmasters);
+ MAKE_STAT_LIST("Environment ID", sp->st_env_id);
+ MAKE_STAT_LIST("Environment priority", sp->st_env_priority);
+ MAKE_STAT_LIST("Generation number", sp->st_gen);
+ MAKE_STAT_LIST("Duplicate log records received", sp->st_log_duplicated);
+ MAKE_STAT_LIST("Current log records queued", sp->st_log_queued);
+ MAKE_STAT_LIST("Maximum log records queued", sp->st_log_queued_max);
+ MAKE_STAT_LIST("Total log records queued", sp->st_log_queued_total);
+ MAKE_STAT_LIST("Log records received", sp->st_log_records);
+ MAKE_STAT_LIST("Log records requested", sp->st_log_requested);
+ MAKE_STAT_LIST("Master environment ID", sp->st_master);
+ MAKE_STAT_LIST("Master changes", sp->st_master_changes);
+ MAKE_STAT_LIST("Messages with bad generation number",
+ sp->st_msgs_badgen);
+ MAKE_STAT_LIST("Messages processed", sp->st_msgs_processed);
+ MAKE_STAT_LIST("Messages ignored for recovery", sp->st_msgs_recover);
+ MAKE_STAT_LIST("Message send failures", sp->st_msgs_send_failures);
+ MAKE_STAT_LIST("Messages sent", sp->st_msgs_sent);
+ MAKE_STAT_LIST("New site messages", sp->st_newsites);
+ MAKE_STAT_LIST("Transmission limited", sp->st_nthrottles);
+ MAKE_STAT_LIST("Outdated conditions", sp->st_outdated);
+ MAKE_STAT_LIST("Transactions applied", sp->st_txns_applied);
+ MAKE_STAT_LIST("Elections held", sp->st_elections);
+ MAKE_STAT_LIST("Elections won", sp->st_elections_won);
+ MAKE_STAT_LIST("Election phase", sp->st_election_status);
+ MAKE_STAT_LIST("Election winner", sp->st_election_cur_winner);
+ MAKE_STAT_LIST("Election generation number", sp->st_election_gen);
+ MAKE_STAT_LSN("Election max LSN", &sp->st_election_lsn);
+ MAKE_STAT_LIST("Election sites", sp->st_election_nsites);
+ MAKE_STAT_LIST("Election priority", sp->st_election_priority);
+ MAKE_STAT_LIST("Election tiebreaker", sp->st_election_tiebreaker);
+ MAKE_STAT_LIST("Election votes", sp->st_election_votes);
+
+ Tcl_SetObjResult(interp, res);
+error:
+ free(sp);
+ return (result);
+}
+#endif
diff --git a/bdb/tcl/tcl_txn.c b/bdb/tcl/tcl_txn.c
index dfe6b6cf60f..b5fab637943 100644
--- a/bdb/tcl/tcl_txn.c
+++ b/bdb/tcl/tcl_txn.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1999, 2000
+ * Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: tcl_txn.c,v 11.24 2000/12/31 19:26:23 bostic Exp $";
+static const char revid[] = "$Id: tcl_txn.c,v 11.57 2002/08/06 06:21:36 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -20,13 +20,11 @@ static const char revid[] = "$Id: tcl_txn.c,v 11.24 2000/12/31 19:26:23 bostic E
#endif
#include "db_int.h"
-#include "tcl_db.h"
+#include "dbinc/tcl_db.h"
-/*
- * Prototypes for procedures defined later in this file:
- */
-static int tcl_TxnCommit __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
- DB_TXN *, DBTCL_INFO *));
+static int tcl_TxnCommit __P((Tcl_Interp *,
+ int, Tcl_Obj * CONST *, DB_TXN *, DBTCL_INFO *));
+static int txn_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST *));
/*
* _TxnInfoDelete --
@@ -39,7 +37,7 @@ static int tcl_TxnCommit __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
*/
void
_TxnInfoDelete(interp, txnip)
- Tcl_Interp *interp; /* Interpreter */
+ Tcl_Interp *interp; /* Interpreter */
DBTCL_INFO *txnip; /* Info for txn */
{
DBTCL_INFO *nextp, *p;
@@ -115,8 +113,9 @@ tcl_TxnCheckpoint(interp, objc, objv, envp)
}
}
_debug_check();
- ret = txn_checkpoint(envp, (u_int32_t)kb, (u_int32_t)min, 0);
- result = _ReturnSetup(interp, ret, "txn checkpoint");
+ ret = envp->txn_checkpoint(envp, (u_int32_t)kb, (u_int32_t)min, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn checkpoint");
return (result);
}
@@ -135,6 +134,11 @@ tcl_Txn(interp, objc, objv, envp, envip)
DBTCL_INFO *envip; /* Info pointer */
{
static char *txnopts[] = {
+#if CONFIG_TEST
+ "-dirty",
+ "-lock_timeout",
+ "-txn_timeout",
+#endif
"-nosync",
"-nowait",
"-parent",
@@ -142,16 +146,22 @@ tcl_Txn(interp, objc, objv, envp, envip)
NULL
};
enum txnopts {
- TXN_NOSYNC,
- TXN_NOWAIT,
- TXN_PARENT,
- TXN_SYNC
+#if CONFIG_TEST
+ TXNDIRTY,
+ TXN_LOCK_TIMEOUT,
+ TXN_TIMEOUT,
+#endif
+ TXNNOSYNC,
+ TXNNOWAIT,
+ TXNPARENT,
+ TXNSYNC
};
DBTCL_INFO *ip;
DB_TXN *parent;
DB_TXN *txn;
Tcl_Obj *res;
- u_int32_t flag;
+ db_timeout_t lk_time, tx_time;
+ u_int32_t flag, lk_timeflag, tx_timeflag;
int i, optindex, result, ret;
char *arg, msg[MSG_SIZE], newname[MSG_SIZE];
@@ -160,6 +170,7 @@ tcl_Txn(interp, objc, objv, envp, envip)
parent = NULL;
flag = 0;
+ lk_timeflag = tx_timeflag = 0;
i = 2;
while (i < objc) {
if (Tcl_GetIndexFromObj(interp, objv[i],
@@ -168,7 +179,37 @@ tcl_Txn(interp, objc, objv, envp, envip)
}
i++;
switch ((enum txnopts)optindex) {
- case TXN_PARENT:
+#ifdef CONFIG_TEST
+ case TXNDIRTY:
+ flag |= DB_DIRTY_READ;
+ break;
+ case TXN_LOCK_TIMEOUT:
+ lk_timeflag = DB_SET_LOCK_TIMEOUT;
+ goto getit;
+ case TXN_TIMEOUT:
+ tx_timeflag = DB_SET_TXN_TIMEOUT;
+getit:
+ if (i >= objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-txn_timestamp time?");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetLongFromObj(interp, objv[i++],
+ (long *)(optindex == TXN_LOCK_TIMEOUT ?
+ &lk_time : &tx_time));
+ if (result != TCL_OK)
+ return (TCL_ERROR);
+ break;
+#endif
+ case TXNNOSYNC:
+ FLAG_CHECK2(flag, DB_DIRTY_READ);
+ flag |= DB_TXN_NOSYNC;
+ break;
+ case TXNNOWAIT:
+ FLAG_CHECK2(flag, DB_DIRTY_READ);
+ flag |= DB_TXN_NOWAIT;
+ break;
+ case TXNPARENT:
if (i == objc) {
Tcl_WrongNumArgs(interp, 2, objv,
"?-parent txn?");
@@ -185,18 +226,10 @@ tcl_Txn(interp, objc, objv, envp, envip)
return (TCL_ERROR);
}
break;
- case TXN_NOWAIT:
- FLAG_CHECK(flag);
- flag |= DB_TXN_NOWAIT;
- break;
- case TXN_SYNC:
- FLAG_CHECK(flag);
+ case TXNSYNC:
+ FLAG_CHECK2(flag, DB_DIRTY_READ);
flag |= DB_TXN_SYNC;
break;
- case TXN_NOSYNC:
- FLAG_CHECK(flag);
- flag |= DB_TXN_NOSYNC;
- break;
}
}
snprintf(newname, sizeof(newname), "%s.txn%d",
@@ -208,8 +241,9 @@ tcl_Txn(interp, objc, objv, envp, envip)
return (TCL_ERROR);
}
_debug_check();
- ret = txn_begin(envp, parent, &txn, flag);
- result = _ReturnSetup(interp, ret, "txn");
+ ret = envp->txn_begin(envp, parent, &txn, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn");
if (result == TCL_ERROR)
_DeleteInfo(ip);
else {
@@ -227,6 +261,24 @@ tcl_Txn(interp, objc, objv, envp, envip)
(Tcl_ObjCmdProc *)txn_Cmd, (ClientData)txn, NULL);
res = Tcl_NewStringObj(newname, strlen(newname));
Tcl_SetObjResult(interp, res);
+ if (tx_timeflag != 0) {
+ ret = txn->set_timeout(txn, tx_time, tx_timeflag);
+ if (ret != 0) {
+ result =
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_timeout");
+ _DeleteInfo(ip);
+ }
+ }
+ if (lk_timeflag != 0) {
+ ret = txn->set_timeout(txn, lk_time, lk_timeflag);
+ if (ret != 0) {
+ result =
+ _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "set_timeout");
+ _DeleteInfo(ip);
+ }
+ }
}
return (result);
}
@@ -244,21 +296,6 @@ tcl_TxnStat(interp, objc, objv, envp)
Tcl_Obj *CONST objv[]; /* The argument objects */
DB_ENV *envp; /* Environment pointer */
{
-#define MAKE_STAT_LSN(s, lsn) \
-do { \
- myobjc = 2; \
- myobjv[0] = Tcl_NewIntObj((lsn)->file); \
- myobjv[1] = Tcl_NewIntObj((lsn)->offset); \
- lsnlist = Tcl_NewListObj(myobjc, myobjv); \
- myobjc = 2; \
- myobjv[0] = Tcl_NewStringObj((s), strlen(s)); \
- myobjv[1] = lsnlist; \
- thislist = Tcl_NewListObj(myobjc, myobjv); \
- result = Tcl_ListObjAppendElement(interp, res, thislist); \
- if (result != TCL_OK) \
- goto error; \
-} while (0);
-
DBTCL_INFO *ip;
DB_TXN_ACTIVE *p;
DB_TXN_STAT *sp;
@@ -275,8 +312,9 @@ do { \
return (TCL_ERROR);
}
_debug_check();
- ret = txn_stat(envp, &sp, NULL);
- result = _ReturnSetup(interp, ret, "txn stat");
+ ret = envp->txn_stat(envp, &sp, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn stat");
if (result == TCL_ERROR)
return (result);
@@ -290,14 +328,15 @@ do { \
*/
MAKE_STAT_LIST("Region size", sp->st_regsize);
MAKE_STAT_LSN("LSN of last checkpoint", &sp->st_last_ckp);
- MAKE_STAT_LSN("LSN of pending checkpoint", &sp->st_pending_ckp);
MAKE_STAT_LIST("Time of last checkpoint", sp->st_time_ckp);
MAKE_STAT_LIST("Last txn ID allocated", sp->st_last_txnid);
MAKE_STAT_LIST("Max Txns", sp->st_maxtxns);
MAKE_STAT_LIST("Number aborted txns", sp->st_naborts);
MAKE_STAT_LIST("Number active txns", sp->st_nactive);
+ MAKE_STAT_LIST("Maximum active txns", sp->st_maxnactive);
MAKE_STAT_LIST("Number txns begun", sp->st_nbegins);
MAKE_STAT_LIST("Number committed txns", sp->st_ncommits);
+ MAKE_STAT_LIST("Number restored txns", sp->st_nrestores);
MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
for (i = 0, p = sp->st_txnarray; i < sp->st_nactive; i++, p++)
@@ -306,7 +345,7 @@ do { \
if (ip->i_type != I_TXN)
continue;
if (ip->i_type == I_TXN &&
- (txn_id(ip->i_txnp) == p->txnid)) {
+ (ip->i_txnp->id(ip->i_txnp) == p->txnid)) {
MAKE_STAT_LSN(ip->i_name, &p->lsn);
if (p->parentid != 0)
MAKE_STAT_STRLIST("Parent",
@@ -318,40 +357,78 @@ do { \
}
Tcl_SetObjResult(interp, res);
error:
- __os_free(sp, sizeof(*sp));
+ free(sp);
return (result);
}
/*
- * txn_Cmd --
- * Implements the "txn" widget.
+ * tcl_TxnTimeout --
*
- * PUBLIC: int txn_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
+ * PUBLIC: int tcl_TxnTimeout __P((Tcl_Interp *, int,
+ * PUBLIC: Tcl_Obj * CONST*, DB_ENV *));
*/
int
+tcl_TxnTimeout(interp, objc, objv, envp)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *envp; /* Environment pointer */
+{
+ long timeout;
+ int result, ret;
+
+ /*
+ * One arg, the timeout.
+ */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?timeout?");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetLongFromObj(interp, objv[2], &timeout);
+ if (result != TCL_OK)
+ return (result);
+ _debug_check();
+ ret = envp->set_timeout(envp, (u_int32_t)timeout, DB_SET_TXN_TIMEOUT);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "lock timeout");
+ return (result);
+}
+
+/*
+ * txn_Cmd --
+ * Implements the "txn" widget.
+ */
+static int
txn_Cmd(clientData, interp, objc, objv)
- ClientData clientData; /* Txn handle */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ ClientData clientData; /* Txn handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
{
static char *txncmds[] = {
- "abort",
- "commit",
+#if CONFIG_TEST
+ "discard",
"id",
"prepare",
+#endif
+ "abort",
+ "commit",
NULL
};
enum txncmds {
- TXNABORT,
- TXNCOMMIT,
+#if CONFIG_TEST
+ TXNDISCARD,
TXNID,
- TXNPREPARE
+ TXNPREPARE,
+#endif
+ TXNABORT,
+ TXNCOMMIT
};
DBTCL_INFO *txnip;
DB_TXN *txnp;
Tcl_Obj *res;
int cmdindex, result, ret;
+ u_int8_t *gid;
Tcl_ResetResult(interp);
txnp = (DB_TXN *)clientData;
@@ -376,38 +453,64 @@ txn_Cmd(clientData, interp, objc, objv)
res = NULL;
switch ((enum txncmds)cmdindex) {
+#if CONFIG_TEST
+ case TXNDISCARD:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return (TCL_ERROR);
+ }
+ _debug_check();
+ ret = txnp->discard(txnp, 0);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn discard");
+ _TxnInfoDelete(interp, txnip);
+ (void)Tcl_DeleteCommand(interp, txnip->i_name);
+ _DeleteInfo(txnip);
+ break;
case TXNID:
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return (TCL_ERROR);
}
_debug_check();
- ret = txn_id(txnp);
+ ret = txnp->id(txnp);
res = Tcl_NewIntObj(ret);
break;
case TXNPREPARE:
- if (objc != 2) {
+ if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return (TCL_ERROR);
}
_debug_check();
- ret = txn_prepare(txnp);
- result = _ReturnSetup(interp, ret, "txn prepare");
- break;
- case TXNCOMMIT:
- result = tcl_TxnCommit(interp, objc, objv, txnp, txnip);
+ gid = (u_int8_t *)Tcl_GetByteArrayFromObj(objv[2], NULL);
+ ret = txnp->prepare(txnp, gid);
+ /*
+ * !!!
+ * DB_TXN->prepare commits all outstanding children. But it
+ * does NOT destroy the current txn handle. So, we must call
+ * _TxnInfoDelete to recursively remove all nested txn handles,
+ * we do not call _DeleteInfo on ourselves.
+ */
_TxnInfoDelete(interp, txnip);
- (void)Tcl_DeleteCommand(interp, txnip->i_name);
- _DeleteInfo(txnip);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn prepare");
break;
+#endif
case TXNABORT:
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return (TCL_ERROR);
}
_debug_check();
- ret = txn_abort(txnp);
- result = _ReturnSetup(interp, ret, "txn abort");
+ ret = txnp->abort(txnp);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn abort");
+ _TxnInfoDelete(interp, txnip);
+ (void)Tcl_DeleteCommand(interp, txnip->i_name);
+ _DeleteInfo(txnip);
+ break;
+ case TXNCOMMIT:
+ result = tcl_TxnCommit(interp, objc, objv, txnp, txnip);
_TxnInfoDelete(interp, txnip);
(void)Tcl_DeleteCommand(interp, txnip->i_name);
_DeleteInfo(txnip);
@@ -424,9 +527,9 @@ txn_Cmd(clientData, interp, objc, objv)
static int
tcl_TxnCommit(interp, objc, objv, txnp, txnip)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
DB_TXN *txnp; /* Transaction pointer */
DBTCL_INFO *txnip; /* Info pointer */
{
@@ -467,7 +570,88 @@ tcl_TxnCommit(interp, objc, objv, txnp, txnip)
}
_debug_check();
- ret = txn_commit(txnp, flag);
- result = _ReturnSetup(interp, ret, "txn commit");
+ ret = txnp->commit(txnp, flag);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn commit");
+ return (result);
+}
+
+#if CONFIG_TEST
+/*
+ * tcl_TxnRecover --
+ *
+ * PUBLIC: int tcl_TxnRecover __P((Tcl_Interp *, int,
+ * PUBLIC: Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *));
+ */
+int
+tcl_TxnRecover(interp, objc, objv, envp, envip)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *envp; /* Environment pointer */
+ DBTCL_INFO *envip; /* Info pointer */
+{
+#define DO_PREPLIST(count) \
+for (i = 0; i < count; i++) { \
+ snprintf(newname, sizeof(newname), "%s.txn%d", \
+ envip->i_name, envip->i_envtxnid); \
+ ip = _NewInfo(interp, NULL, newname, I_TXN); \
+ if (ip == NULL) { \
+ Tcl_SetResult(interp, "Could not set up info", \
+ TCL_STATIC); \
+ return (TCL_ERROR); \
+ } \
+ envip->i_envtxnid++; \
+ ip->i_parent = envip; \
+ p = &prep[i]; \
+ _SetInfoData(ip, p->txn); \
+ Tcl_CreateObjCommand(interp, newname, \
+ (Tcl_ObjCmdProc *)txn_Cmd, (ClientData)p->txn, NULL); \
+ result = _SetListElem(interp, res, newname, strlen(newname), \
+ p->gid, DB_XIDDATASIZE); \
+ if (result != TCL_OK) \
+ goto error; \
+}
+
+ DBTCL_INFO *ip;
+ DB_PREPLIST prep[DBTCL_PREP], *p;
+ Tcl_Obj *res;
+ long count, i;
+ int result, ret;
+ char newname[MSG_SIZE];
+
+ result = TCL_OK;
+ /*
+ * No args for this. Error if there are some.
+ */
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ _debug_check();
+ ret = envp->txn_recover(envp, prep, DBTCL_PREP, &count, DB_FIRST);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn recover");
+ if (result == TCL_ERROR)
+ return (result);
+ res = Tcl_NewObj();
+ DO_PREPLIST(count);
+
+ /*
+ * If count returned is the maximum size we have, then there
+ * might be more. Keep going until we get them all.
+ */
+ while (count == DBTCL_PREP) {
+ ret = envp->txn_recover(
+ envp, prep, DBTCL_PREP, &count, DB_NEXT);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+ "txn recover");
+ if (result == TCL_ERROR)
+ return (result);
+ DO_PREPLIST(count);
+ }
+ Tcl_SetObjResult(interp, res);
+error:
return (result);
}
+#endif
diff --git a/bdb/tcl/tcl_util.c b/bdb/tcl/tcl_util.c
new file mode 100644
index 00000000000..3c0665f9e38
--- /dev/null
+++ b/bdb/tcl/tcl_util.c
@@ -0,0 +1,381 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1999-2001
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: tcl_util.c,v 11.35 2002/08/06 06:21:42 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/tcl_db.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+static int mutex_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
+
+/*
+ * bdb_RandCommand --
+ * Implements rand* functions.
+ *
+ * PUBLIC: int bdb_RandCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
+ */
+int
+bdb_RandCommand(interp, objc, objv)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+{
+ static char *rcmds[] = {
+ "rand", "random_int", "srand",
+ NULL
+ };
+ enum rcmds {
+ RRAND, RRAND_INT, RSRAND
+ };
+ long t;
+ int cmdindex, hi, lo, result, ret;
+ Tcl_Obj *res;
+ char msg[MSG_SIZE];
+
+ result = TCL_OK;
+ /*
+ * Get the command name index from the object based on the cmds
+ * defined above. This SHOULD NOT fail because we already checked
+ * in the 'berkdb' command.
+ */
+ if (Tcl_GetIndexFromObj(interp,
+ objv[1], rcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
+ return (IS_HELP(objv[1]));
+
+ res = NULL;
+ switch ((enum rcmds)cmdindex) {
+ case RRAND:
+ /*
+ * Must be 0 args. Error if different.
+ */
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return (TCL_ERROR);
+ }
+ ret = rand();
+ res = Tcl_NewIntObj(ret);
+ break;
+ case RRAND_INT:
+ /*
+ * Must be 4 args. Error if different.
+ */
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "lo hi");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &lo);
+ if (result != TCL_OK)
+ break;
+ result = Tcl_GetIntFromObj(interp, objv[3], &hi);
+ if (result == TCL_OK) {
+#ifndef RAND_MAX
+#define RAND_MAX 0x7fffffff
+#endif
+ t = rand();
+ if (t > RAND_MAX) {
+ snprintf(msg, MSG_SIZE,
+ "Max random is higher than %ld\n",
+ (long)RAND_MAX);
+ Tcl_SetResult(interp, msg, TCL_VOLATILE);
+ result = TCL_ERROR;
+ break;
+ }
+ _debug_check();
+ ret = (int)(((double)t / ((double)(RAND_MAX) + 1)) *
+ (hi - lo + 1));
+ ret += lo;
+ res = Tcl_NewIntObj(ret);
+ }
+ break;
+ case RSRAND:
+ /*
+ * Must be 1 arg. Error if different.
+ */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "seed");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &lo);
+ if (result == TCL_OK) {
+ srand((u_int)lo);
+ res = Tcl_NewIntObj(0);
+ }
+ break;
+ }
+ /*
+ * Only set result if we have a res. Otherwise, lower
+ * functions have already done so.
+ */
+ if (result == TCL_OK && res)
+ Tcl_SetObjResult(interp, res);
+ return (result);
+}
+
+/*
+ *
+ * tcl_Mutex --
+ * Opens an env mutex.
+ *
+ * PUBLIC: int tcl_Mutex __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *,
+ * PUBLIC: DBTCL_INFO *));
+ */
+int
+tcl_Mutex(interp, objc, objv, envp, envip)
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+ DB_ENV *envp; /* Environment pointer */
+ DBTCL_INFO *envip; /* Info pointer */
+{
+ DBTCL_INFO *ip;
+ Tcl_Obj *res;
+ _MUTEX_DATA *md;
+ int i, mode, nitems, result, ret;
+ char newname[MSG_SIZE];
+
+ md = NULL;
+ result = TCL_OK;
+ mode = nitems = ret = 0;
+ memset(newname, 0, MSG_SIZE);
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mode nitems");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &mode);
+ if (result != TCL_OK)
+ return (TCL_ERROR);
+ result = Tcl_GetIntFromObj(interp, objv[3], &nitems);
+ if (result != TCL_OK)
+ return (TCL_ERROR);
+
+ snprintf(newname, sizeof(newname),
+ "%s.mutex%d", envip->i_name, envip->i_envmutexid);
+ ip = _NewInfo(interp, NULL, newname, I_MUTEX);
+ if (ip == NULL) {
+ Tcl_SetResult(interp, "Could not set up info",
+ TCL_STATIC);
+ return (TCL_ERROR);
+ }
+ /*
+ * Set up mutex.
+ */
+ /*
+ * Map in the region.
+ *
+ * XXX
+ * We don't bother doing this "right", i.e., using the shalloc
+ * functions, just grab some memory knowing that it's correctly
+ * aligned.
+ */
+ _debug_check();
+ if (__os_calloc(NULL, 1, sizeof(_MUTEX_DATA), &md) != 0)
+ goto posixout;
+ md->env = envp;
+ md->n_mutex = nitems;
+ md->size = sizeof(_MUTEX_ENTRY) * nitems;
+
+ md->reginfo.type = REGION_TYPE_MUTEX;
+ md->reginfo.id = INVALID_REGION_TYPE;
+ md->reginfo.mode = mode;
+ md->reginfo.flags = REGION_CREATE_OK | REGION_JOIN_OK;
+ if ((ret = __db_r_attach(envp, &md->reginfo, md->size)) != 0)
+ goto posixout;
+ md->marray = md->reginfo.addr;
+
+ /* Initialize a created region. */
+ if (F_ISSET(&md->reginfo, REGION_CREATE))
+ for (i = 0; i < nitems; i++) {
+ md->marray[i].val = 0;
+ if ((ret = __db_mutex_init_int(envp,
+ &md->marray[i].m, i, 0)) != 0)
+ goto posixout;
+ }
+ R_UNLOCK(envp, &md->reginfo);
+
+ /*
+ * Success. Set up return. Set up new info
+ * and command widget for this mutex.
+ */
+ envip->i_envmutexid++;
+ ip->i_parent = envip;
+ _SetInfoData(ip, md);
+ Tcl_CreateObjCommand(interp, newname,
+ (Tcl_ObjCmdProc *)mutex_Cmd, (ClientData)md, NULL);
+ res = Tcl_NewStringObj(newname, strlen(newname));
+ Tcl_SetObjResult(interp, res);
+
+ return (TCL_OK);
+
+posixout:
+ if (ret > 0)
+ Tcl_PosixError(interp);
+ result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mutex");
+ _DeleteInfo(ip);
+
+ if (md != NULL) {
+ if (md->reginfo.addr != NULL)
+ (void)__db_r_detach(md->env,
+ &md->reginfo, F_ISSET(&md->reginfo, REGION_CREATE));
+ __os_free(md->env, md);
+ }
+ return (result);
+}
+
+/*
+ * mutex_Cmd --
+ * Implements the "mutex" widget.
+ */
+static int
+mutex_Cmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Mutex handle */
+ Tcl_Interp *interp; /* Interpreter */
+ int objc; /* How many arguments? */
+ Tcl_Obj *CONST objv[]; /* The argument objects */
+{
+ static char *mxcmds[] = {
+ "close",
+ "get",
+ "getval",
+ "release",
+ "setval",
+ NULL
+ };
+ enum mxcmds {
+ MXCLOSE,
+ MXGET,
+ MXGETVAL,
+ MXRELE,
+ MXSETVAL
+ };
+ DB_ENV *dbenv;
+ DBTCL_INFO *envip, *mpip;
+ _MUTEX_DATA *mp;
+ Tcl_Obj *res;
+ int cmdindex, id, result, newval;
+
+ Tcl_ResetResult(interp);
+ mp = (_MUTEX_DATA *)clientData;
+ mpip = _PtrToInfo((void *)mp);
+ envip = mpip->i_parent;
+ dbenv = envip->i_envp;
+ result = TCL_OK;
+
+ if (mp == NULL) {
+ Tcl_SetResult(interp, "NULL mp pointer", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+ if (mpip == NULL) {
+ Tcl_SetResult(interp, "NULL mp info pointer", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ /*
+ * Get the command name index from the object based on the dbcmds
+ * defined above.
+ */
+ if (Tcl_GetIndexFromObj(interp,
+ objv[1], mxcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
+ return (IS_HELP(objv[1]));
+
+ res = NULL;
+ switch ((enum mxcmds)cmdindex) {
+ case MXCLOSE:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return (TCL_ERROR);
+ }
+ _debug_check();
+ (void)__db_r_detach(mp->env, &mp->reginfo, 0);
+ res = Tcl_NewIntObj(0);
+ (void)Tcl_DeleteCommand(interp, mpip->i_name);
+ _DeleteInfo(mpip);
+ __os_free(mp->env, mp);
+ break;
+ case MXRELE:
+ /*
+ * Check for 1 arg. Error if different.
+ */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "id");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &id);
+ if (result != TCL_OK)
+ break;
+ MUTEX_UNLOCK(dbenv, &mp->marray[id].m);
+ res = Tcl_NewIntObj(0);
+ break;
+ case MXGET:
+ /*
+ * Check for 1 arg. Error if different.
+ */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "id");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &id);
+ if (result != TCL_OK)
+ break;
+ MUTEX_LOCK(dbenv, &mp->marray[id].m);
+ res = Tcl_NewIntObj(0);
+ break;
+ case MXGETVAL:
+ /*
+ * Check for 1 arg. Error if different.
+ */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "id");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &id);
+ if (result != TCL_OK)
+ break;
+ res = Tcl_NewLongObj((long)mp->marray[id].val);
+ break;
+ case MXSETVAL:
+ /*
+ * Check for 2 args. Error if different.
+ */
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "id val");
+ return (TCL_ERROR);
+ }
+ result = Tcl_GetIntFromObj(interp, objv[2], &id);
+ if (result != TCL_OK)
+ break;
+ result = Tcl_GetIntFromObj(interp, objv[3], &newval);
+ if (result != TCL_OK)
+ break;
+ mp->marray[id].val = newval;
+ res = Tcl_NewIntObj(0);
+ break;
+ }
+ /*
+ * Only set result if we have a res. Otherwise, lower
+ * functions have already done so.
+ */
+ if (result == TCL_OK && res)
+ Tcl_SetObjResult(interp, res);
+ return (result);
+}
diff --git a/bdb/test/TESTS b/bdb/test/TESTS
deleted file mode 100644
index a585bdddcde..00000000000
--- a/bdb/test/TESTS
+++ /dev/null
@@ -1,448 +0,0 @@
-# $Id: TESTS,v 11.34 2000/11/06 19:31:56 sue Exp $
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Access method tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-test001 Small keys/data
- Put/get per key
- Dump file
- Close, reopen
- Dump file
-
-test002 Small keys/medium data
- Put/get per key
- Dump file
- Close, reopen
- Dump file
-
-test003 Small keys/large data
- Put/get per key
- Dump file
- Close, reopen
- Dump file
-
-test004 Small keys/medium data
- Put/get per key
- Sequential (cursor) get/delete
-
-test005 Small keys/medium data
- Put/get per key
- Close, reopen
- Sequential (cursor) get/delete
-
-test006 Small keys/medium data
- Put/get per key
- Keyed delete and verify
-
-test007 Small keys/medium data
- Put/get per key
- Close, reopen
- Keyed delete
-
-test008 Small keys/large data
- Put/get per key
- Loop through keys by steps (which change)
- ... delete each key at step
- ... add each key back
- ... change step
- Confirm that overflow pages are getting reused
-
-test009 Small keys/large data
- Same as test008; close and reopen database
-
-test010 Duplicate test
- Small key/data pairs.
-
-test011 Duplicate test
- Small key/data pairs.
- Test DB_KEYFIRST, DB_KEYLAST, DB_BEFORE and DB_AFTER.
- To test off-page duplicates, run with small pagesize.
-
-test012 Large keys/small data
- Same as test003 except use big keys (source files and
- executables) and small data (the file/executable names).
-
-test013 Partial put test
- Overwrite entire records using partial puts. Make sure
- that NOOVERWRITE flag works.
-
-test014 Exercise partial puts on short data
- Run 5 combinations of numbers of characters to replace,
- and number of times to increase the size by.
-
-test015 Partial put test
- Partial put test where the key does not initially exist.
-
-test016 Partial put test
- Partial put where the datum gets shorter as a result of
- the put.
-
-test017 Basic offpage duplicate test.
-
-test018 Offpage duplicate test
- Key_{first,last,before,after} offpage duplicates.
-
-test019 Partial get test.
-
-test020 In-Memory database tests.
-
-test021 Btree range tests.
-
-test022 Test of DB->getbyteswapped().
-
-test023 Duplicate test
- Exercise deletes and cursor operations within a
- duplicate set.
-
-test024 Record number retrieval test.
-
-test025 DB_APPEND flag test.
-
-test026 Small keys/medium data w/duplicates
- Put/get per key.
- Loop through keys -- delete each key
- ... test that cursors delete duplicates correctly
-
-test027 Off-page duplicate test
- Test026 with parameters to force off-page duplicates.
-
-test028 Cursor delete test
- Test put operations after deleting through a cursor.
-
-test029 Record renumbering
-
-test030 DB_NEXT_DUP functionality
-
-test031 Duplicate sorting functionality
- Make sure DB_NODUPDATA works.
-
-test032 DB_GET_BOTH
-
-test033 DB_GET_BOTH without comparison function
-
-test034 Test032 with off-page duplicates
-
-test035 Test033 with off-page duplicates
-
-test036 Test KEYFIRST and KEYLAST when the key doesn't exist
-
-test037 Test DB_RMW
-
-test038 DB_GET_BOTH on deleted items
-
-test039 DB_GET_BOTH on deleted items without comparison function
-
-test040 Test038 with off-page duplicates
-
-test041 Test039 with off-page duplicates
-
-test042 Concurrent Data Store test
-
-test043 Recno renumbering and implicit creation test
-
-test044 Small system integration tests
- Test proper functioning of the checkpoint daemon,
- recovery, transactions, etc.
-
-test045 Small random tester
- Runs a number of random add/delete/retrieve operations.
- Tests both successful conditions and error conditions.
-
-test046 Overwrite test of small/big key/data with cursor checks.
-
-test047 Cursor get test with SET_RANGE option.
-
-test048 Cursor stability across Btree splits.
-
-test049 Cursor operations on unitialized cursors.
-
-test050 Cursor overwrite test for Recno.
-
-test051 Fixed-length record Recno test.
-
-test052 Renumbering record Recno test.
-
-test053 DB_REVSPLITOFF flag test
-
-test054 Cursor maintenance during key/data deletion.
-
-test054 Basic cursor operations.
-
-test055 Cursor maintenance during key deletes.
-
-test056 Cursor maintenance during deletes.
-
-test057 Cursor maintenance during key deletes.
-
-test058 Verify that deleting and reading duplicates results in
- correct ordering.
-
-test059 Cursor ops work with a partial length of 0.
-
-test060 Test of the DB_EXCL flag to DB->open().
-
-test061 Test of txn abort and commit for in-memory databases.
-
-test062 Test of partial puts (using DB_CURRENT) onto duplicate pages.
-
-test063 Test of the DB_RDONLY flag to DB->open
-
-test064 Test of DB->get_type
-
-test065 Test of DB->stat(DB_RECORDCOUNT)
-
-test066 Test of cursor overwrites of DB_CURRENT w/ duplicates.
-
-test067 Test of DB_CURRENT partial puts onto almost empty duplicate
- pages, with and without DB_DUP_SORT.
-
-test068 Test of DB_BEFORE and DB_AFTER with partial puts.
-
-test069 Test of DB_CURRENT partial puts without duplicates--
- test067 w/ small ndups.
-
-test070 Test of DB_CONSUME (Four consumers, 1000 items.)
-
-test071 Test of DB_CONSUME (One consumer, 10000 items.)
-
-test072 Cursor stability test when dups are moved off-page
-
-test073 Test of cursor stability on duplicate pages.
-
-test074 Test of DB_NEXT_NODUP.
-
-test075 Test of DB->rename().
- (formerly test of DB_TRUNCATE cached page invalidation [#1487])
-
-test076 Test creation of many small databases in a single environment.
- [#1528].
-
-test077 Test of DB_GET_RECNO [#1206].
-
-test078 Test of DBC->c_count().
-
-test079 Test of deletes in large trees. (test006 w/ sm. pagesize).
-
-test080 Test of DB->remove()
-
-test081 Test off-page duplicates and overflow pages together with
- very large keys (key/data as file contents).
-
-test082 Test of DB_PREV_NODUP (uses test074).
-
-test083 Test of DB->key_range.
-
-test084 Sanity test of large (64K) pages.
-
-test085 Test of cursor behavior when a cursor is pointing to a deleted
- btree key which then has duplicates added. [#2473]
-
-test086 Test of cursor stability across btree splits/rsplits with
- subtransaction aborts (a variant of test048). [#2373]
-
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Cursor Join.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-jointest Test duplicate assisted joins.
- Executes 1, 2, 3 and 4-way joins with differing
- index orders and selectivity.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Deadlock detection.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-dead001 Use two different configurations to test deadlock
- detection among a variable number of processes. One
- configuration has the processes deadlocked in a ring.
- The other has the processes all deadlocked on a single
- resource.
-
-dead002 Same test as dead001, but use "detect on every collision"
- instead of separate deadlock detector.
-
-dead003 Same test as dead002, but explicitly specify oldest or
- youngest. Verify the correct lock was aborted/granted.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Lock tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-lock001 Basic lock test, gets/puts. Contention without waiting.
-
-lock002 Multi-process lock tests.
-
-lock003 Multiprocess random lock test.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Logging test
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-log001 Read/write log records.
-
-log002 Tests multiple logs
- Log truncation
- lsn comparison and file functionality.
-
-log003 Verify that log_flush is flushing records correctly.
-
-log004 Prev on log when beginning of log has been truncated.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Mpool test
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-memp001 Randomly updates pages.
-
-memp002 Tests multiple processes accessing and modifying the same
- files.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Recovery
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-recd001 Per-operation recovery tests for non-duplicate, non-split
- messages. Makes sure that we exercise redo, undo, and
- do-nothing condition. Any test that appears with the
- message (change state) indicates that we've already run
- the particular test, but we are running it again so that
- we can change the state of the data base to prepare for
- the next test (this applies to all other recovery tests
- as well).
-
-recd002 Split recovery tests. For every known split log message,
- makes sure that we exercise redo, undo, and do-nothing
- condition.
-
-recd003 Duplicate recovery tests. For every known duplicate log
- message, makes sure that we exercise redo, undo, and
- do-nothing condition.
-
-recd004 Big key test where big key gets elevated to internal page.
-
-recd005 Verify reuse of file ids works on catastrophic recovery.
-
-recd006 Nested transactions.
-
-recd007 File create/delete tests.
-
-recd008 Test deeply nested transactions.
-
-recd009 Verify record numbering across split/reverse splits
- and recovery.
-
-recd010 Verify duplicates across split/reverse splits
- and recovery.
-
-recd011 Verify that recovery to a specific timestamp works.
-
-recd012 Test of log file ID management. [#2288]
-
-recd013 Test of cursor adjustment on child transaction aborts. [#2373]
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Subdatabase tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-subdb001 Tests mixing db and subdb operations
- Create a db, add data, try to create a subdb.
- Test naming db and subdb with a leading - for
- correct parsing
- Existence check -- test use of -excl with subdbs
-
-subdb002 Tests basic subdb functionality
- Small keys, small data
- Put/get per key
- Dump file
- Close, reopen
- Dump file
-
-subdb003 Tests many subdbs
- Creates many subdbs and puts a small amount of
- data in each (many defaults to 2000)
-
-subdb004 Tests large subdb names
- subdb name = filecontents,
- key = filename, data = filecontents
- Put/get per key
- Dump file
- Dump subdbs, verify data and subdb name match
-
-subdb005 Tests cursor operations in subdbs
- Put/get per key
- Verify cursor operations work within subdb
- Verify cursor operations do not work across subdbs
-
-subdb006 Tests intra-subdb join
-
-subdb007 Tests page size differences between subdbs
- Open several subdbs, each with a different pagesize
- Small keys, small data
- Put/get per key per subdb
- Dump file, verify per subdb
- Close, reopen per subdb
- Dump file, verify per subdb
-
-subdb008 Tests lorder differences between subdbs
- Open several subdbs, each with a different/random lorder
- Small keys, small data
- Put/get per key per subdb
- Dump file, verify per subdb
- Close, reopen per subdb
- Dump file, verify per subdb
-
-subdb009 Test DB->rename() method for subdbs
-
-subdb010 Test DB->remove() method for subdbs
-
-subdbtest001 Tests multiple access methods in one subdb
- Open several subdbs, each with a different access method
- Small keys, small data
- Put/get per key per subdb
- Dump file, verify per subdb
- Close, reopen per subdb
- Dump file, verify per subdb
-
-subdbtest002 Tests multiple access methods in one subdb access by
- multiple processes
- Open several subdbs, each with a different access method
- Small keys, small data
- Put/get per key per subdb
- Fork off several child procs to each delete selected
- data from their subdb and then exit
- Dump file, verify contents of each subdb is correct
- Close, reopen per subdb
- Dump file, verify per subdb
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Transaction tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-txn001 Begin, commit, abort testing.
-
-txn002 Verify that read-only transactions do not write log records.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Environment tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-env001 Test of env remove interface (formerly env_remove).
-
-env002 Test of DB_LOG_DIR and env name resolution.
-
-env003 Test of DB_TMP_DIR and env name resolution.
-
-env004 Multiple data directories test.
-
-env005 Test for using subsystems without initializing them correctly.
-
-env006 Smoke test that the utilities all run.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-RPC tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-[RPC tests also include running all Access Method tests for all methods
-via an RPC server]
-
-rpc001 Test RPC server timeouts for cursor, txn and env handles.
-
-rpc002 Test unsupported functions
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-Recno backing file tests
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-rsrc001 Basic backing file test (put/get)
-
-rsrc002 Test of set_re_delim
diff --git a/bdb/test/archive.tcl b/bdb/test/archive.tcl
index 9fdbe82d137..9b5e764b2b4 100644
--- a/bdb/test/archive.tcl
+++ b/bdb/test/archive.tcl
@@ -1,33 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: archive.tcl,v 11.14 2000/10/27 13:23:55 sue Exp $
+# $Id: archive.tcl,v 11.20 2002/04/30 19:21:21 sue Exp $
#
# Options are:
# -checkrec <checkpoint frequency"
# -dir <dbhome directory>
# -maxfilesize <maxsize of log file>
-# -stat
-proc archive_usage {} {
- puts "archive -checkrec <checkpt freq> -dir <directory> \
- -maxfilesize <max size of log files>"
-}
-proc archive_command { args } {
- source ./include.tcl
-
- # Catch a list of files output by db_archive.
- catch { eval exec $util_path/db_archive $args } output
-
- if { $is_windows_test == 1 || 1 } {
- # On Windows, convert all filenames to use forward slashes.
- regsub -all {[\\]} $output / output
- }
-
- # Output the [possibly-transformed] list.
- return $output
-}
proc archive { args } {
global alphabet
source ./include.tcl
@@ -35,17 +16,16 @@ proc archive { args } {
# Set defaults
set maxbsize [expr 8 * 1024]
set maxfile [expr 32 * 1024]
- set dostat 0
set checkrec 500
for { set i 0 } { $i < [llength $args] } {incr i} {
switch -regexp -- [lindex $args $i] {
-c.* { incr i; set checkrec [lindex $args $i] }
-d.* { incr i; set testdir [lindex $args $i] }
-m.* { incr i; set maxfile [lindex $args $i] }
- -s.* { set dostat 1 }
default {
- puts -nonewline "FAIL:[timestamp] Usage: "
- archive_usage
+ puts "FAIL:[timestamp] archive usage"
+ puts "usage: archive -checkrec <checkpt freq> \
+ -dir <directory> -maxfilesize <max size of log files>"
return
}
@@ -53,16 +33,20 @@ proc archive { args } {
}
# Clean out old log if it existed
+ puts "Archive: Log archive test"
puts "Unlinking log: error message OK"
env_cleanup $testdir
# Now run the various functionality tests
set eflags "-create -txn -home $testdir \
-log_buffer $maxbsize -log_max $maxfile"
- set dbenv [eval {berkdb env} $eflags]
+ set dbenv [eval {berkdb_env} $eflags]
error_check_bad dbenv $dbenv NULL
error_check_good dbenv [is_substr $dbenv env] 1
+ set logc [$dbenv log_cursor]
+ error_check_good log_cursor [is_valid_logc $logc $dbenv] TRUE
+
# The basic test structure here is that we write a lot of log
# records (enough to fill up 100 log files; each log file it
# small). We take periodic checkpoints. Between each pair
@@ -75,7 +59,7 @@ proc archive { args } {
# open data file and CDx is close datafile.
set baserec "1:$alphabet:2:$alphabet:3:$alphabet:4:$alphabet"
- puts "Archive.a: Writing log records; checkpoint every $checkrec records"
+ puts "\tArchive.a: Writing log records; checkpoint every $checkrec records"
set nrecs $maxfile
set rec 0:$baserec
@@ -111,7 +95,7 @@ proc archive { args } {
if { [expr $i % $checkrec] == 0 } {
# Take a checkpoint
$dbenv txn_checkpoint
- set ckp_file [lindex [lindex [$dbenv log_get -last] 0] 0]
+ set ckp_file [lindex [lindex [$logc get -last] 0] 0]
catch { archive_command -h $testdir -a } res_log_full
if { [string first db_archive $res_log_full] == 0 } {
set res_log_full ""
@@ -125,7 +109,7 @@ proc archive { args } {
res_data_full
catch { archive_command -h $testdir -s } res_data
error_check_good nlogfiles [llength $res_alllog] \
- [lindex [lindex [$dbenv log_get -last] 0] 0]
+ [lindex [lindex [$logc get -last] 0] 0]
error_check_good logs_match [llength $res_log_full] \
[llength $res_log]
error_check_good data_match [llength $res_data_full] \
@@ -206,21 +190,35 @@ proc archive { args } {
}
}
# Commit any transactions still running.
- puts "Archive: Commit any transactions still running."
+ puts "\tArchive.b: Commit any transactions still running."
foreach t $txnlist {
error_check_good txn_commit:$t [$t commit] 0
}
# Close any files that are still open.
- puts "Archive: Close open files."
+ puts "\tArchive.c: Close open files."
foreach d $dblist {
error_check_good db_close:$db [$d close] 0
}
# Close and unlink the file
+ error_check_good log_cursor_close [$logc close] 0
reset_env $dbenv
+}
+
+proc archive_command { args } {
+ source ./include.tcl
+
+ # Catch a list of files output by db_archive.
+ catch { eval exec $util_path/db_archive $args } output
- puts "Archive: Complete."
+ if { $is_windows_test == 1 || 1 } {
+ # On Windows, convert all filenames to use forward slashes.
+ regsub -all {[\\]} $output / output
+ }
+
+ # Output the [possibly-transformed] list.
+ return $output
}
proc min { a b } {
diff --git a/bdb/test/bigfile001.tcl b/bdb/test/bigfile001.tcl
new file mode 100644
index 00000000000..78dcd940f5e
--- /dev/null
+++ b/bdb/test/bigfile001.tcl
@@ -0,0 +1,85 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: bigfile001.tcl,v 11.7 2002/08/10 13:39:26 bostic Exp $
+#
+# TEST bigfile001
+# TEST Create a database greater than 4 GB in size. Close, verify.
+# TEST Grow the database somewhat. Close, reverify. Lather, rinse,
+# TEST repeat. Since it will not work on all systems, this test is
+# TEST not run by default.
+proc bigfile001 { method \
+ { itemsize 4096 } { nitems 1048576 } { growby 5000 } { growtms 2 } args } {
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ puts "Bigfile: $method ($args) $nitems * $itemsize bytes of data"
+
+ env_cleanup $testdir
+
+ # Create the database. Use 64K pages; we want a good fill
+ # factor, and page size doesn't matter much. Use a 50MB
+ # cache; that should be manageable, and will help
+ # performance.
+ set dbname $testdir/big.db
+
+ set db [eval {berkdb_open -create} {-pagesize 65536 \
+ -cachesize {0 50000000 0}} $omethod $args $dbname]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ puts -nonewline "\tBigfile.a: Creating database...0%..."
+ flush stdout
+
+ set data [string repeat z $itemsize]
+
+ set more_than_ten_already 0
+ for { set i 0 } { $i < $nitems } { incr i } {
+ set key key[format %08u $i]
+
+ error_check_good db_put($i) [$db put $key $data] 0
+
+ if { $i % 5000 == 0 } {
+ set pct [expr 100 * $i / $nitems]
+ puts -nonewline "\b\b\b\b\b"
+ if { $pct >= 10 } {
+ if { $more_than_ten_already } {
+ puts -nonewline "\b"
+ } else {
+ set more_than_ten_already 1
+ }
+ }
+
+ puts -nonewline "$pct%..."
+ flush stdout
+ }
+ }
+ puts "\b\b\b\b\b\b100%..."
+ error_check_good db_close [$db close] 0
+
+ puts "\tBigfile.b: Verifying database..."
+ error_check_good verify \
+ [verify_dir $testdir "\t\t" 0 0 1 50000000] 0
+
+ puts "\tBigfile.c: Grow database $growtms times by $growby items"
+
+ for { set j 0 } { $j < $growtms } { incr j } {
+ set db [eval {berkdb_open} {-cachesize {0 50000000 0}} $dbname]
+ error_check_good db_open [is_valid_db $db] TRUE
+ puts -nonewline "\t\tBigfile.c.1: Adding $growby items..."
+ flush stdout
+ for { set i 0 } { $i < $growby } { incr i } {
+ set key key[format %08u $i].$j
+ error_check_good db_put($j.$i) [$db put $key $data] 0
+ }
+ error_check_good db_close [$db close] 0
+ puts "done."
+
+ puts "\t\tBigfile.c.2: Verifying database..."
+ error_check_good verify($j) \
+ [verify_dir $testdir "\t\t\t" 0 0 1 50000000] 0
+ }
+}
diff --git a/bdb/test/bigfile002.tcl b/bdb/test/bigfile002.tcl
new file mode 100644
index 00000000000..f3e6defeaba
--- /dev/null
+++ b/bdb/test/bigfile002.tcl
@@ -0,0 +1,45 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: bigfile002.tcl,v 11.7 2002/08/10 13:39:26 bostic Exp $
+#
+# TEST bigfile002
+# TEST This one should be faster and not require so much disk space,
+# TEST although it doesn't test as extensively. Create an mpool file
+# TEST with 1K pages. Dirty page 6000000. Sync.
+proc bigfile002 { args } {
+ source ./include.tcl
+
+ puts -nonewline \
+ "Bigfile002: Creating large, sparse file through mpool..."
+ flush stdout
+
+ env_cleanup $testdir
+
+ # Create env.
+ set env [berkdb_env -create -home $testdir]
+ error_check_good valid_env [is_valid_env $env] TRUE
+
+ # Create the file.
+ set name big002.file
+ set file [$env mpool -create -pagesize 1024 $name]
+
+ # Dirty page 6000000
+ set pg [$file get -create 6000000]
+ error_check_good pg_init [$pg init A] 0
+ error_check_good pg_set [$pg is_setto A] 1
+
+ # Put page back.
+ error_check_good pg_put [$pg put -dirty] 0
+
+ # Fsync.
+ error_check_good fsync [$file fsync] 0
+
+ puts "succeeded."
+
+ # Close.
+ error_check_good fclose [$file close] 0
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/byteorder.tcl b/bdb/test/byteorder.tcl
index d9e44e1d27d..823ca46270d 100644
--- a/bdb/test/byteorder.tcl
+++ b/bdb/test/byteorder.tcl
@@ -1,23 +1,34 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: byteorder.tcl,v 11.7 2000/11/16 23:56:18 ubell Exp $
+# $Id: byteorder.tcl,v 11.12 2002/07/29 18:09:25 sue Exp $
#
# Byte Order Test
# Use existing tests and run with both byte orders.
proc byteorder { method {nentries 1000} } {
+ source ./include.tcl
puts "Byteorder: $method $nentries"
- eval {test001 $method $nentries 0 "01" -lorder 1234}
- eval {test001 $method $nentries 0 "01" -lorder 4321}
+ eval {test001 $method $nentries 0 "01" 0 -lorder 1234}
+ eval {verify_dir $testdir}
+ eval {test001 $method $nentries 0 "01" 0 -lorder 4321}
+ eval {verify_dir $testdir}
eval {test003 $method -lorder 1234}
+ eval {verify_dir $testdir}
eval {test003 $method -lorder 4321}
+ eval {verify_dir $testdir}
eval {test010 $method $nentries 5 10 -lorder 1234}
+ eval {verify_dir $testdir}
eval {test010 $method $nentries 5 10 -lorder 4321}
+ eval {verify_dir $testdir}
eval {test011 $method $nentries 5 11 -lorder 1234}
+ eval {verify_dir $testdir}
eval {test011 $method $nentries 5 11 -lorder 4321}
+ eval {verify_dir $testdir}
eval {test018 $method $nentries -lorder 1234}
+ eval {verify_dir $testdir}
eval {test018 $method $nentries -lorder 4321}
+ eval {verify_dir $testdir}
}
diff --git a/bdb/test/conscript.tcl b/bdb/test/conscript.tcl
index 11d0eb58e7d..fd12c6e51a0 100644
--- a/bdb/test/conscript.tcl
+++ b/bdb/test/conscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: conscript.tcl,v 11.12 2000/12/01 04:28:36 ubell Exp $
+# $Id: conscript.tcl,v 11.17 2002/03/22 21:43:06 krinsky Exp $
#
# Script for DB_CONSUME test (test070.tcl).
# Usage: conscript dir file runtype nitems outputfile tnum args
@@ -28,17 +28,18 @@ proc consumescript_produce { db_cmd nitems tnum args } {
set ret 0
for { set ndx 0 } { $ndx < $nitems } { incr ndx } {
set oret $ret
+ if { 0xffffffff > 0 && $oret > 0x7fffffff } {
+ incr oret [expr 0 - 0x100000000]
+ }
set ret [$db put -append [chop_data q $mydata]]
error_check_good db_put \
[expr $ret > 0 ? $oret < $ret : \
$oret < 0 ? $oret < $ret : $oret > $ret] 1
}
- # XXX: We permit incomplete syncs because they seem to
- # be unavoidable and not damaging.
+
set ret [catch {$db close} res]
- error_check_good db_close:$pid [expr ($ret == 0) ||\
- ([is_substr $res DB_INCOMPLETE] == 1)] 1
+ error_check_good db_close:$pid $ret 0
puts "\t\tTest0$tnum: Producer $pid finished."
}
@@ -67,10 +68,9 @@ proc consumescript_consume { db_cmd nitems tnum outputfile mode args } {
}
error_check_good output_close:$pid [close $oid] ""
- # XXX: see above note.
+
set ret [catch {$db close} res]
- error_check_good db_close:$pid [expr ($ret == 0) ||\
- ([is_substr $res DB_INCOMPLETE] == 1)] 1
+ error_check_good db_close:$pid $ret 0
puts "\t\tTest0$tnum: Consumer $pid finished."
}
@@ -99,7 +99,7 @@ set args [lindex [lrange $argv 6 end] 0]
set mydata "consumer data"
# Open env
-set dbenv [berkdb env -home $dir ]
+set dbenv [berkdb_env -home $dir ]
error_check_good db_env_create [is_valid_env $dbenv] TRUE
# Figure out db opening command.
diff --git a/bdb/test/dbm.tcl b/bdb/test/dbm.tcl
index 41a5da1f13a..a392c7a9f3a 100644
--- a/bdb/test/dbm.tcl
+++ b/bdb/test/dbm.tcl
@@ -1,16 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: dbm.tcl,v 11.12 2000/08/25 14:21:50 sue Exp $
+# $Id: dbm.tcl,v 11.15 2002/01/11 15:53:19 bostic Exp $
#
-# Historic DBM interface test.
-# Use the first 1000 entries from the dictionary.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Then reopen the file, re-retrieve everything.
-# Finally, delete everything.
+# TEST dbm
+# TEST Historic DBM interface test. Use the first 1000 entries from the
+# TEST dictionary. Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Then reopen the file, re-retrieve everything. Finally, delete
+# TEST everything.
proc dbm { { nentries 1000 } } {
source ./include.tcl
diff --git a/bdb/test/dbscript.tcl b/bdb/test/dbscript.tcl
index 3a51b4363d4..5decc493e9e 100644
--- a/bdb/test/dbscript.tcl
+++ b/bdb/test/dbscript.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: dbscript.tcl,v 11.10 2000/04/21 18:36:21 krinsky Exp $
+# $Id: dbscript.tcl,v 11.14 2002/04/01 16:28:16 bostic Exp $
#
# Random db tester.
# Usage: dbscript file numops min_del max_add key_avg data_avgdups
+# method: method (we pass this in so that fixed-length records work)
# file: db file on which to operate
# numops: number of operations to do
# ncurs: number of cursors
@@ -22,26 +23,25 @@ source ./include.tcl
source $test_path/test.tcl
source $test_path/testutils.tcl
-set alphabet "abcdefghijklmnopqrstuvwxyz"
-
set usage "dbscript file numops ncurs min_del max_add key_avg data_avg dups errpcnt"
# Verify usage
-if { $argc != 9 } {
+if { $argc != 10 } {
puts stderr "FAIL:[timestamp] Usage: $usage"
exit
}
# Initialize arguments
-set file [lindex $argv 0]
-set numops [ lindex $argv 1 ]
-set ncurs [ lindex $argv 2 ]
-set min_del [ lindex $argv 3 ]
-set max_add [ lindex $argv 4 ]
-set key_avg [ lindex $argv 5 ]
-set data_avg [ lindex $argv 6 ]
-set dups [ lindex $argv 7 ]
-set errpct [ lindex $argv 8 ]
+set method [lindex $argv 0]
+set file [lindex $argv 1]
+set numops [ lindex $argv 2 ]
+set ncurs [ lindex $argv 3 ]
+set min_del [ lindex $argv 4 ]
+set max_add [ lindex $argv 5 ]
+set key_avg [ lindex $argv 6 ]
+set data_avg [ lindex $argv 7 ]
+set dups [ lindex $argv 8 ]
+set errpct [ lindex $argv 9 ]
berkdb srand $rand_init
@@ -68,7 +68,7 @@ if {$cerr != 0} {
puts $cret
return
}
-set method [$db get_type]
+# set method [$db get_type]
set record_based [is_record_based $method]
# Initialize globals including data
diff --git a/bdb/test/ddoyscript.tcl b/bdb/test/ddoyscript.tcl
new file mode 100644
index 00000000000..5478a1a98e0
--- /dev/null
+++ b/bdb/test/ddoyscript.tcl
@@ -0,0 +1,172 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: ddoyscript.tcl,v 11.6 2002/02/20 16:35:18 sandstro Exp $
+#
+# Deadlock detector script tester.
+# Usage: ddoyscript dir lockerid numprocs
+# dir: DBHOME directory
+# lockerid: Lock id for this locker
+# numprocs: Total number of processes running
+# myid: id of this process --
+# the order that the processes are created is the same
+# in which their lockerid's were allocated so we know
+# that there is a locker age relationship that is isomorphic
+# with the order releationship of myid's.
+
+source ./include.tcl
+source $test_path/test.tcl
+source $test_path/testutils.tcl
+
+set usage "ddoyscript dir lockerid numprocs oldoryoung"
+
+# Verify usage
+if { $argc != 5 } {
+ puts stderr "FAIL:[timestamp] Usage: $usage"
+ exit
+}
+
+# Initialize arguments
+set dir [lindex $argv 0]
+set lockerid [ lindex $argv 1 ]
+set numprocs [ lindex $argv 2 ]
+set old_or_young [lindex $argv 3]
+set myid [lindex $argv 4]
+
+set myenv [berkdb_env -lock -home $dir -create -mode 0644]
+error_check_bad lock_open $myenv NULL
+error_check_good lock_open [is_substr $myenv "env"] 1
+
+# There are two cases here -- oldest/youngest or a ring locker.
+
+if { $myid == 0 || $myid == [expr $numprocs - 1] } {
+ set waitobj NULL
+ set ret 0
+
+ if { $myid == 0 } {
+ set objid 2
+ if { $old_or_young == "o" } {
+ set waitobj [expr $numprocs - 1]
+ }
+ } else {
+ if { $old_or_young == "y" } {
+ set waitobj 0
+ }
+ set objid 4
+ }
+
+ # Acquire own read lock
+ if {[catch {$myenv lock_get read $lockerid $myid} selflock] != 0} {
+ puts $errorInfo
+ } else {
+ error_check_good selfget:$objid [is_substr $selflock $myenv] 1
+ }
+
+ # Acquire read lock
+ if {[catch {$myenv lock_get read $lockerid $objid} lock1] != 0} {
+ puts $errorInfo
+ } else {
+ error_check_good lockget:$objid [is_substr $lock1 $myenv] 1
+ }
+
+ tclsleep 10
+
+ if { $waitobj == "NULL" } {
+ # Sleep for a good long while
+ tclsleep 90
+ } else {
+ # Acquire write lock
+ if {[catch {$myenv lock_get write $lockerid $waitobj} lock2]
+ != 0} {
+ puts $errorInfo
+ set ret ERROR
+ } else {
+ error_check_good lockget:$waitobj \
+ [is_substr $lock2 $myenv] 1
+
+ # Now release it
+ if {[catch {$lock2 put} err] != 0} {
+ puts $errorInfo
+ set ret ERROR
+ } else {
+ error_check_good lockput:oy:$objid $err 0
+ }
+ }
+
+ }
+
+ # Release self lock
+ if {[catch {$selflock put} err] != 0} {
+ puts $errorInfo
+ if { $ret == 0 } {
+ set ret ERROR
+ }
+ } else {
+ error_check_good selfput:oy:$myid $err 0
+ if { $ret == 0 } {
+ set ret 1
+ }
+ }
+
+ # Release first lock
+ if {[catch {$lock1 put} err] != 0} {
+ puts $errorInfo
+ if { $ret == 0 } {
+ set ret ERROR
+ }
+ } else {
+ error_check_good lockput:oy:$objid $err 0
+ if { $ret == 0 } {
+ set ret 1
+ }
+ }
+
+} else {
+ # Make sure that we succeed if we're locking the same object as
+ # oldest or youngest.
+ if { [expr $myid % 2] == 0 } {
+ set mode read
+ } else {
+ set mode write
+ }
+ # Obtain first lock (should always succeed).
+ if {[catch {$myenv lock_get $mode $lockerid $myid} lock1] != 0} {
+ puts $errorInfo
+ } else {
+ error_check_good lockget:$myid [is_substr $lock1 $myenv] 1
+ }
+
+ tclsleep 30
+
+ set nextobj [expr $myid + 1]
+ if { $nextobj == [expr $numprocs - 1] } {
+ set nextobj 1
+ }
+
+ set ret 1
+ if {[catch {$myenv lock_get write $lockerid $nextobj} lock2] != 0} {
+ if {[string match "*DEADLOCK*" $lock2] == 1} {
+ set ret DEADLOCK
+ } else {
+ set ret ERROR
+ }
+ } else {
+ error_check_good lockget:$nextobj [is_substr $lock2 $myenv] 1
+ }
+
+ # Now release the first lock
+ error_check_good lockput:$lock1 [$lock1 put] 0
+
+ if {$ret == 1} {
+ error_check_bad lockget:$nextobj $lock2 NULL
+ error_check_good lockget:$nextobj [is_substr $lock2 $myenv] 1
+ error_check_good lockput:$lock2 [$lock2 put] 0
+ }
+}
+
+puts $ret
+error_check_good lock_id_free [$myenv lock_id_free $lockerid] 0
+error_check_good envclose [$myenv close] 0
+exit
diff --git a/bdb/test/ddscript.tcl b/bdb/test/ddscript.tcl
index 9b139a4cbc6..621906233a9 100644
--- a/bdb/test/ddscript.tcl
+++ b/bdb/test/ddscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: ddscript.tcl,v 11.7 2000/05/08 19:26:37 sue Exp $
+# $Id: ddscript.tcl,v 11.12 2002/02/20 16:35:18 sandstro Exp $
#
# Deadlock detector script tester.
# Usage: ddscript dir test lockerid objid numprocs
@@ -32,12 +32,13 @@ set lockerid [ lindex $argv 2 ]
set objid [ lindex $argv 3 ]
set numprocs [ lindex $argv 4 ]
-set myenv [berkdb env -lock -home $dir -create -mode 0644]
+set myenv [berkdb_env -lock -home $dir -create -mode 0644 ]
error_check_bad lock_open $myenv NULL
error_check_good lock_open [is_substr $myenv "env"] 1
puts [eval $tnum $myenv $lockerid $objid $numprocs]
+error_check_good lock_id_free [$myenv lock_id_free $lockerid] 0
error_check_good envclose [$myenv close] 0
exit
diff --git a/bdb/test/dead001.tcl b/bdb/test/dead001.tcl
index 9e7c71f6a58..e9853a87e53 100644
--- a/bdb/test/dead001.tcl
+++ b/bdb/test/dead001.tcl
@@ -1,56 +1,67 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: dead001.tcl,v 11.17 2000/11/05 14:23:55 dda Exp $
+# $Id: dead001.tcl,v 11.33 2002/09/05 17:23:05 sandstro Exp $
#
-# Deadlock Test 1.
-# We create various deadlock scenarios for different numbers of lockers
-# and see if we can get the world cleaned up suitably.
-proc dead001 { { procs "2 4 10" } {tests "ring clump" } } {
+# TEST dead001
+# TEST Use two different configurations to test deadlock detection among a
+# TEST variable number of processes. One configuration has the processes
+# TEST deadlocked in a ring. The other has the processes all deadlocked on
+# TEST a single resource.
+proc dead001 { { procs "2 4 10" } {tests "ring clump" } \
+ {timeout 0} {tnum "001"} } {
source ./include.tcl
+ global lock_curid
+ global lock_maxid
- puts "Dead001: Deadlock detector tests"
+ puts "Dead$tnum: Deadlock detector tests"
env_cleanup $testdir
# Create the environment.
- puts "\tDead001.a: creating environment"
- set env [berkdb env -create -mode 0644 -lock -home $testdir]
+ puts "\tDead$tnum.a: creating environment"
+ set env [berkdb_env -create \
+ -mode 0644 -lock -txn_timeout $timeout -home $testdir]
error_check_good lock_env:open [is_valid_env $env] TRUE
- error_check_good lock_env:close [$env close] 0
-
- set dpid [exec $util_path/db_deadlock -vw -h $testdir \
- >& $testdir/dd.out &]
-
foreach t $tests {
- set pidlist ""
foreach n $procs {
+ if {$timeout == 0 } {
+ set dpid [exec $util_path/db_deadlock -vw \
+ -h $testdir >& $testdir/dd.out &]
+ } else {
+ set dpid [exec $util_path/db_deadlock -vw \
+ -ae -h $testdir >& $testdir/dd.out &]
+ }
- sentinel_init
+ sentinel_init
+ set pidlist ""
+ set ret [$env lock_id_set $lock_curid $lock_maxid]
+ error_check_good lock_id_set $ret 0
# Fire off the tests
- puts "\tDead001: $n procs of test $t"
+ puts "\tDead$tnum: $n procs of test $t"
for { set i 0 } { $i < $n } { incr i } {
+ set locker [$env lock_id]
puts "$tclsh_path $test_path/wrap.tcl \
- $testdir/dead001.log.$i \
- ddscript.tcl $testdir $t $i $i $n"
+ $testdir/dead$tnum.log.$i \
+ ddscript.tcl $testdir $t $locker $i $n"
set p [exec $tclsh_path \
$test_path/wrap.tcl \
- ddscript.tcl $testdir/dead001.log.$i \
- $testdir $t $i $i $n &]
+ ddscript.tcl $testdir/dead$tnum.log.$i \
+ $testdir $t $locker $i $n &]
lappend pidlist $p
}
- watch_procs 5
+ watch_procs $pidlist 5
# Now check output
set dead 0
set clean 0
set other 0
for { set i 0 } { $i < $n } { incr i } {
- set did [open $testdir/dead001.log.$i]
+ set did [open $testdir/dead$tnum.log.$i]
while { [gets $did val] != -1 } {
switch $val {
DEADLOCK { incr dead }
@@ -60,17 +71,18 @@ proc dead001 { { procs "2 4 10" } {tests "ring clump" } } {
}
close $did
}
+ tclkill $dpid
puts "dead check..."
- dead_check $t $n $dead $clean $other
+ dead_check $t $n $timeout $dead $clean $other
}
}
- exec $KILL $dpid
# Windows needs files closed before deleting files, so pause a little
- tclsleep 2
+ tclsleep 3
fileremove -f $testdir/dd.out
# Remove log files
for { set i 0 } { $i < $n } { incr i } {
- fileremove -f $testdir/dead001.log.$i
+ fileremove -f $testdir/dead$tnum.log.$i
}
+ error_check_good lock_env:close [$env close] 0
}
diff --git a/bdb/test/dead002.tcl b/bdb/test/dead002.tcl
index 83cc6c7d59b..bc19e7127e5 100644
--- a/bdb/test/dead002.tcl
+++ b/bdb/test/dead002.tcl
@@ -1,52 +1,58 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: dead002.tcl,v 11.15 2000/08/25 14:21:50 sue Exp $
+# $Id: dead002.tcl,v 11.23 2002/09/05 17:23:05 sandstro Exp $
#
-# Deadlock Test 2.
-# Identical to Test 1 except that instead of running a standalone deadlock
-# detector, we create the region with "detect on every wait"
-proc dead002 { { procs "2 4 10" } {tests "ring clump" } } {
+# TEST dead002
+# TEST Same test as dead001, but use "detect on every collision" instead
+# TEST of separate deadlock detector.
+proc dead002 { { procs "2 4 10" } {tests "ring clump" } \
+ {timeout 0} {tnum 002} } {
source ./include.tcl
- puts "Dead002: Deadlock detector tests"
+ puts "Dead$tnum: Deadlock detector tests"
env_cleanup $testdir
# Create the environment.
- puts "\tDead002.a: creating environment"
- set env [berkdb env \
- -create -mode 0644 -home $testdir -lock -lock_detect default]
+ puts "\tDead$tnum.a: creating environment"
+ set lmode "default"
+ if { $timeout != 0 } {
+ set lmode "expire"
+ }
+ set env [berkdb_env \
+ -create -mode 0644 -home $testdir \
+ -lock -txn_timeout $timeout -lock_detect $lmode]
error_check_good lock_env:open [is_valid_env $env] TRUE
- error_check_good lock_env:close [$env close] 0
foreach t $tests {
- set pidlist ""
foreach n $procs {
+ set pidlist ""
sentinel_init
# Fire off the tests
- puts "\tDead002: $n procs of test $t"
+ puts "\tDead$tnum: $n procs of test $t"
for { set i 0 } { $i < $n } { incr i } {
+ set locker [$env lock_id]
puts "$tclsh_path $test_path/wrap.tcl \
- $testdir/dead002.log.$i \
- ddscript.tcl $testdir $t $i $i $n"
+ $testdir/dead$tnum.log.$i \
+ ddscript.tcl $testdir $t $locker $i $n"
set p [exec $tclsh_path \
$test_path/wrap.tcl \
- ddscript.tcl $testdir/dead002.log.$i \
- $testdir $t $i $i $n &]
+ ddscript.tcl $testdir/dead$tnum.log.$i \
+ $testdir $t $locker $i $n &]
lappend pidlist $p
}
- watch_procs 5
+ watch_procs $pidlist 5
# Now check output
set dead 0
set clean 0
set other 0
for { set i 0 } { $i < $n } { incr i } {
- set did [open $testdir/dead002.log.$i]
+ set did [open $testdir/dead$tnum.log.$i]
while { [gets $did val] != -1 } {
switch $val {
DEADLOCK { incr dead }
@@ -56,13 +62,14 @@ proc dead002 { { procs "2 4 10" } {tests "ring clump" } } {
}
close $did
}
- dead_check $t $n $dead $clean $other
+ dead_check $t $n $timeout $dead $clean $other
}
}
fileremove -f $testdir/dd.out
# Remove log files
for { set i 0 } { $i < $n } { incr i } {
- fileremove -f $testdir/dead002.log.$i
+ fileremove -f $testdir/dead$tnum.log.$i
}
+ error_check_good lock_env:close [$env close] 0
}
diff --git a/bdb/test/dead003.tcl b/bdb/test/dead003.tcl
index 4075eb44f86..48088e1427c 100644
--- a/bdb/test/dead003.tcl
+++ b/bdb/test/dead003.tcl
@@ -1,16 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: dead003.tcl,v 1.8 2000/08/25 14:21:50 sue Exp $
+# $Id: dead003.tcl,v 1.17 2002/09/05 17:23:05 sandstro Exp $
#
-# Deadlock Test 3.
-# Test DB_LOCK_OLDEST and DB_LOCK_YOUNGEST
-# Identical to Test 2 except that we create the region with "detect on
-# every wait" with first the "oldest" and then "youngest".
+# TEST dead003
+# TEST
+# TEST Same test as dead002, but explicitly specify DB_LOCK_OLDEST and
+# TEST DB_LOCK_YOUNGEST. Verify the correct lock was aborted/granted.
proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
source ./include.tcl
+ global lock_curid
+ global lock_maxid
set detects { oldest youngest }
puts "Dead003: Deadlock detector tests: $detects"
@@ -19,31 +21,34 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
foreach d $detects {
env_cleanup $testdir
puts "\tDead003.a: creating environment for $d"
- set env [berkdb env \
+ set env [berkdb_env \
-create -mode 0644 -home $testdir -lock -lock_detect $d]
error_check_good lock_env:open [is_valid_env $env] TRUE
- error_check_good lock_env:close [$env close] 0
foreach t $tests {
- set pidlist ""
foreach n $procs {
- sentinel_init
+ set pidlist ""
+ sentinel_init
+ set ret [$env lock_id_set \
+ $lock_curid $lock_maxid]
+ error_check_good lock_id_set $ret 0
# Fire off the tests
puts "\tDead003: $n procs of test $t"
for { set i 0 } { $i < $n } { incr i } {
+ set locker [$env lock_id]
puts "$tclsh_path\
test_path/ddscript.tcl $testdir \
- $t $i $i $n >& \
+ $t $locker $i $n >& \
$testdir/dead003.log.$i"
set p [exec $tclsh_path \
$test_path/wrap.tcl \
ddscript.tcl \
$testdir/dead003.log.$i $testdir \
- $t $i $i $n &]
+ $t $locker $i $n &]
lappend pidlist $p
}
- watch_procs 5
+ watch_procs $pidlist 5
# Now check output
set dead 0
@@ -60,7 +65,7 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
}
close $did
}
- dead_check $t $n $dead $clean $other
+ dead_check $t $n 0 $dead $clean $other
#
# If we get here we know we have the
# correct number of dead/clean procs, as
@@ -88,5 +93,6 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
for { set i 0 } { $i < $n } { incr i } {
fileremove -f $testdir/dead003.log.$i
}
+ error_check_good lock_env:close [$env close] 0
}
}
diff --git a/bdb/test/dead004.tcl b/bdb/test/dead004.tcl
new file mode 100644
index 00000000000..f5306a0d892
--- /dev/null
+++ b/bdb/test/dead004.tcl
@@ -0,0 +1,108 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: dead004.tcl,v 11.11 2002/09/05 17:23:05 sandstro Exp $
+#
+# Deadlock Test 4.
+# This test is designed to make sure that we handle youngest and oldest
+# deadlock detection even when the youngest and oldest transactions in the
+# system are not involved in the deadlock (that is, we want to abort the
+# youngest/oldest which is actually involved in the deadlock, not simply
+# the youngest/oldest in the system).
+# Since this is used for transaction systems, the locker ID is what we
+# use to identify age (smaller number is older).
+#
+# The set up is that we have a total of 6 processes. The oldest (locker 0)
+# and the youngest (locker 5) simply acquire a lock, hold it for a long time
+# and then release it. The rest form a ring, obtaining lock N and requesting
+# a lock on (N+1) mod 4. The deadlock detector ought to pick locker 1 or 4
+# to abort and not 0 or 5.
+
+proc dead004 { } {
+ source ./include.tcl
+ global lock_curid
+ global lock_maxid
+
+ foreach a { o y } {
+ puts "Dead004: Deadlock detector test -a $a"
+ env_cleanup $testdir
+
+ # Create the environment.
+ puts "\tDead004.a: creating environment"
+ set env [berkdb_env -create -mode 0644 -lock -home $testdir]
+ error_check_good lock_env:open [is_valid_env $env] TRUE
+
+ set dpid [exec $util_path/db_deadlock -v -t 5 -a $a \
+ -h $testdir >& $testdir/dd.out &]
+
+ set procs 6
+
+ foreach n $procs {
+
+ sentinel_init
+ set pidlist ""
+ set ret [$env lock_id_set $lock_curid $lock_maxid]
+ error_check_good lock_id_set $ret 0
+
+ # Fire off the tests
+ puts "\tDead004: $n procs"
+ for { set i 0 } { $i < $n } { incr i } {
+ set locker [$env lock_id]
+ puts "$tclsh_path $test_path/wrap.tcl \
+ $testdir/dead004.log.$i \
+ ddoyscript.tcl $testdir $locker $n $a $i"
+ set p [exec $tclsh_path \
+ $test_path/wrap.tcl \
+ ddoyscript.tcl $testdir/dead004.log.$i \
+ $testdir $locker $n $a $i &]
+ lappend pidlist $p
+ }
+ watch_procs $pidlist 5
+
+ }
+ # Now check output
+ set dead 0
+ set clean 0
+ set other 0
+ for { set i 0 } { $i < $n } { incr i } {
+ set did [open $testdir/dead004.log.$i]
+ while { [gets $did val] != -1 } {
+ switch $val {
+ DEADLOCK { incr dead }
+ 1 { incr clean }
+ default { incr other }
+ }
+ }
+ close $did
+ }
+ tclkill $dpid
+
+ puts "dead check..."
+ dead_check oldyoung $n 0 $dead $clean $other
+
+ # Now verify that neither the oldest nor the
+ # youngest were the deadlock.
+ set did [open $testdir/dead004.log.0]
+ error_check_bad file:young [gets $did val] -1
+ error_check_good read:young $val 1
+ close $did
+
+ set did [open $testdir/dead004.log.[expr $procs - 1]]
+ error_check_bad file:old [gets $did val] -1
+ error_check_good read:old $val 1
+ close $did
+
+ # Windows needs files closed before deleting files,
+ # so pause a little
+ tclsleep 2
+ fileremove -f $testdir/dd.out
+
+ # Remove log files
+ for { set i 0 } { $i < $n } { incr i } {
+ fileremove -f $testdir/dead004.log.$i
+ }
+ error_check_good lock_env:close [$env close] 0
+ }
+}
diff --git a/bdb/test/dead005.tcl b/bdb/test/dead005.tcl
new file mode 100644
index 00000000000..71be8b1713f
--- /dev/null
+++ b/bdb/test/dead005.tcl
@@ -0,0 +1,87 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: dead005.tcl,v 11.10 2002/09/05 17:23:05 sandstro Exp $
+#
+# Deadlock Test 5.
+# Test out the minlocks, maxlocks, and minwrites options
+# to the deadlock detector.
+proc dead005 { { procs "4 6 10" } {tests "maxlocks minwrites minlocks" } } {
+ source ./include.tcl
+
+ puts "Dead005: minlocks, maxlocks, and minwrites deadlock detection tests"
+ foreach t $tests {
+ puts "Dead005.$t: creating environment"
+ env_cleanup $testdir
+
+ # Create the environment.
+ set env [berkdb_env -create -mode 0644 -lock -home $testdir]
+ error_check_good lock_env:open [is_valid_env $env] TRUE
+ case $t {
+ minlocks { set to n }
+ maxlocks { set to m }
+ minwrites { set to w }
+ }
+ foreach n $procs {
+ set dpid [exec $util_path/db_deadlock -vw -h $testdir \
+ -a $to >& $testdir/dd.out &]
+ sentinel_init
+ set pidlist ""
+
+ # Fire off the tests
+ puts "\tDead005: $t test with $n procs"
+ for { set i 0 } { $i < $n } { incr i } {
+ set locker [$env lock_id]
+ puts "$tclsh_path $test_path/wrap.tcl \
+ $testdir/dead005.log.$i \
+ ddscript.tcl $testdir $t $locker $i $n"
+ set p [exec $tclsh_path \
+ $test_path/wrap.tcl \
+ ddscript.tcl $testdir/dead005.log.$i \
+ $testdir $t $locker $i $n &]
+ lappend pidlist $p
+ }
+ watch_procs $pidlist 5
+
+ # Now check output
+ set dead 0
+ set clean 0
+ set other 0
+ for { set i 0 } { $i < $n } { incr i } {
+ set did [open $testdir/dead005.log.$i]
+ while { [gets $did val] != -1 } {
+ switch $val {
+ DEADLOCK { incr dead }
+ 1 { incr clean }
+ default { incr other }
+ }
+ }
+ close $did
+ }
+ tclkill $dpid
+ puts "dead check..."
+ dead_check $t $n 0 $dead $clean $other
+ # Now verify that the correct participant
+ # got deadlocked.
+ switch $t {
+ minlocks {set f 0}
+ minwrites {set f 1}
+ maxlocks {set f [expr $n - 1]}
+ }
+ set did [open $testdir/dead005.log.$f]
+ error_check_bad file:$t [gets $did val] -1
+ error_check_good read($f):$t $val DEADLOCK
+ close $did
+ }
+ error_check_good lock_env:close [$env close] 0
+ # Windows needs files closed before deleting them, so pause
+ tclsleep 2
+ fileremove -f $testdir/dd.out
+ # Remove log files
+ for { set i 0 } { $i < $n } { incr i } {
+ fileremove -f $testdir/dead001.log.$i
+ }
+ }
+}
diff --git a/bdb/test/dead006.tcl b/bdb/test/dead006.tcl
new file mode 100644
index 00000000000..b70e011fb74
--- /dev/null
+++ b/bdb/test/dead006.tcl
@@ -0,0 +1,16 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: dead006.tcl,v 1.4 2002/01/11 15:53:21 bostic Exp $
+#
+# TEST dead006
+# TEST use timeouts rather than the normal dd algorithm.
+proc dead006 { { procs "2 4 10" } {tests "ring clump" } \
+ {timeout 1000} {tnum 006} } {
+ source ./include.tcl
+
+ dead001 $procs $tests $timeout $tnum
+ dead002 $procs $tests $timeout $tnum
+}
diff --git a/bdb/test/dead007.tcl b/bdb/test/dead007.tcl
new file mode 100644
index 00000000000..2b6a78cb4b9
--- /dev/null
+++ b/bdb/test/dead007.tcl
@@ -0,0 +1,34 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: dead007.tcl,v 1.3 2002/01/11 15:53:22 bostic Exp $
+#
+# TEST dead007
+# TEST use timeouts rather than the normal dd algorithm.
+proc dead007 { } {
+ source ./include.tcl
+ global lock_curid
+ global lock_maxid
+
+ set save_curid $lock_curid
+ set save_maxid $lock_maxid
+ puts "Dead007.a -- wrap around"
+ set lock_curid [expr $lock_maxid - 2]
+ dead001 "2 10"
+ ## Oldest/youngest breaks when the id wraps
+ # dead003 "4 10"
+ dead004
+
+ puts "Dead007.b -- extend space"
+ set lock_maxid [expr $lock_maxid - 3]
+ set lock_curid [expr $lock_maxid - 1]
+ dead001 "4 10"
+ ## Oldest/youngest breaks when the id wraps
+ # dead003 "10"
+ dead004
+
+ set lock_curid $save_curid
+ set lock_maxid $save_maxid
+}
diff --git a/bdb/test/env001.tcl b/bdb/test/env001.tcl
index 00837330193..781029f6a5c 100644
--- a/bdb/test/env001.tcl
+++ b/bdb/test/env001.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env001.tcl,v 11.21 2000/11/09 19:24:08 sue Exp $
+# $Id: env001.tcl,v 11.26 2002/05/08 19:01:43 margo Exp $
#
-# Test of env remove interface.
+# TEST env001
+# TEST Test of env remove interface (formerly env_remove).
proc env001 { } {
global errorInfo
global errorCode
@@ -20,12 +21,12 @@ proc env001 { } {
# Try opening without Create flag should error
puts "\tEnv001.a: Open without create (should fail)."
- catch {set env [berkdb env -home $testdir]} ret
+ catch {set env [berkdb_env_noerr -home $testdir]} ret
error_check_good env:fail [is_substr $ret "no such file"] 1
# Now try opening with create
puts "\tEnv001.b: Open with create."
- set env [berkdb env -create -mode 0644 -home $testdir]
+ set env [berkdb_env -create -mode 0644 -home $testdir]
error_check_bad env:$testdir $env NULL
error_check_good env:$testdir [is_substr $env "env"] 1
@@ -40,7 +41,7 @@ proc env001 { } {
puts "\tEnv001.d: Remove on closed environments."
if { $is_windows_test != 1 } {
puts "\t\tEnv001.d.1: Verify re-open."
- set env [berkdb env -home $testdir]
+ set env [berkdb_env -home $testdir]
error_check_bad env:$testdir $env NULL
error_check_good env:$testdir [is_substr $env "env"] 1
@@ -56,7 +57,7 @@ proc env001 { } {
puts "\tEnv001.e: Remove on open environments."
puts "\t\tEnv001.e.1: Env is open by single proc,\
remove no force."
- set env [berkdb env -create -mode 0644 -home $testdir]
+ set env [berkdb_env -create -mode 0644 -home $testdir]
error_check_bad env:$testdir $env NULL
error_check_good env:$testdir [is_substr $env "env"] 1
set stat [catch {berkdb envremove -home $testdir} ret]
@@ -68,7 +69,7 @@ proc env001 { } {
"\t\tEnv001.e.2: Env is open by single proc, remove with force."
# Now that envremove doesn't do a close, this won't work on Windows.
if { $is_windows_test != 1 && $is_hp_test != 1} {
- set env [berkdb env -create -mode 0644 -home $testdir]
+ set env [berkdb_env_noerr -create -mode 0644 -home $testdir]
error_check_bad env:$testdir $env NULL
error_check_good env:$testdir [is_substr $env "env"] 1
set stat [catch {berkdb envremove -force -home $testdir} ret]
@@ -77,19 +78,22 @@ proc env001 { } {
# Even though the underlying env is gone, we need to close
# the handle.
#
- catch {$env close}
+ set stat [catch {$env close} ret]
+ error_check_bad env:close_after_remove $stat 0
+ error_check_good env:close_after_remove \
+ [is_substr $ret "recovery"] 1
}
puts "\t\tEnv001.e.3: Env is open by 2 procs, remove no force."
# should fail
- set env [berkdb env -create -mode 0644 -home $testdir]
+ set env [berkdb_env -create -mode 0644 -home $testdir]
error_check_bad env:$testdir $env NULL
error_check_good env:$testdir [is_substr $env "env"] 1
set f1 [open |$tclsh_path r+]
puts $f1 "source $test_path/test.tcl"
- set remote_env [send_cmd $f1 "berkdb env -home $testdir"]
+ set remote_env [send_cmd $f1 "berkdb_env_noerr -home $testdir"]
error_check_good remote:env_open [is_valid_env $remote_env] TRUE
# First close our env, but leave remote open
error_check_good env:close [$env close] 0
@@ -110,13 +114,13 @@ proc env001 { } {
# are open, so we skip this test for Windows. On UNIX, it should
# succeed
if { $is_windows_test != 1 && $is_hp_test != 1 } {
- set env [berkdb env -create -mode 0644 -home $testdir]
+ set env [berkdb_env_noerr -create -mode 0644 -home $testdir]
error_check_bad env:$testdir $env NULL
error_check_good env:$testdir [is_substr $env "env"] 1
set f1 [open |$tclsh_path r+]
puts $f1 "source $test_path/test.tcl"
- set remote_env [send_cmd $f1 "berkdb env -home $testdir"]
+ set remote_env [send_cmd $f1 "berkdb_env -home $testdir"]
error_check_good remote:env_open [is_valid_env $remote_env] TRUE
catch {berkdb envremove -force -home $testdir} ret
@@ -124,7 +128,10 @@ proc env001 { } {
#
# We still need to close our handle.
#
- catch {$env close} ret
+ set stat [catch {$env close} ret]
+ error_check_bad env:close_after_error $stat 0
+ error_check_good env:close_after_error \
+ [is_substr $ret recovery] 1
# Close down remote process
set err [catch { close $f1 } result]
@@ -137,7 +144,7 @@ proc env001 { } {
file mkdir $testdir/NEWDIR
}
set eflags "-create -home $testdir/NEWDIR -mode 0644"
- set env [eval {berkdb env} $eflags]
+ set env [eval {berkdb_env} $eflags]
error_check_bad env:open $env NULL
error_check_good env:close [$env close] 0
error_check_good berkdb:envremove \
diff --git a/bdb/test/env002.tcl b/bdb/test/env002.tcl
index a37ddea17a9..89c44f63a12 100644
--- a/bdb/test/env002.tcl
+++ b/bdb/test/env002.tcl
@@ -1,21 +1,21 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env002.tcl,v 11.11 2000/08/25 14:21:50 sue Exp $
+# $Id: env002.tcl,v 11.15 2002/02/20 16:35:20 sandstro Exp $
#
-# Env Test 002
-# Test set_lg_dir and env name resolution
-# With an environment path specified using -home, and then again
-# with it specified by the environment variable DB_HOME:
-# 1) Make sure that the set_lg_dir option is respected
-# a) as a relative pathname.
-# b) as an absolute pathname.
-# 2) Make sure that the DB_LOG_DIR db_config argument is respected,
-# again as relative and absolute pathnames.
-# 3) Make sure that if -both- db_config and a file are present,
-# only the file is respected (see doc/env/naming.html).
+# TEST env002
+# TEST Test of DB_LOG_DIR and env name resolution.
+# TEST With an environment path specified using -home, and then again
+# TEST with it specified by the environment variable DB_HOME:
+# TEST 1) Make sure that the set_lg_dir option is respected
+# TEST a) as a relative pathname.
+# TEST b) as an absolute pathname.
+# TEST 2) Make sure that the DB_LOG_DIR db_config argument is respected,
+# TEST again as relative and absolute pathnames.
+# TEST 3) Make sure that if -both- db_config and a file are present,
+# TEST only the file is respected (see doc/env/naming.html).
proc env002 { } {
# env002 is essentially just a small driver that runs
# env002_body--formerly the entire test--twice; once, it
@@ -30,7 +30,7 @@ proc env002 { } {
puts "Env002: set_lg_dir test."
- puts "\tEnv002: Running with -home argument to berkdb env."
+ puts "\tEnv002: Running with -home argument to berkdb_env."
env002_body "-home $testdir"
puts "\tEnv002: Running with environment variable DB_HOME set."
@@ -125,8 +125,8 @@ proc env002_run_test { major minor msg env_args log_path} {
# Create an environment, with logging, and scribble some
# stuff in a [btree] database in it.
- # puts [concat {berkdb env -create -log -private} $env_args]
- set dbenv [eval {berkdb env -create -log -private} $env_args]
+ # puts [concat {berkdb_env -create -log -private} $env_args]
+ set dbenv [eval {berkdb_env -create -log -private} $env_args]
error_check_good env_open [is_valid_env $dbenv] TRUE
set db [berkdb_open -env $dbenv -create -btree -mode 0644 $testfile]
error_check_good db_open [is_valid_db $db] TRUE
diff --git a/bdb/test/env003.tcl b/bdb/test/env003.tcl
index 01e0b6188fc..c16b54dd5e0 100644
--- a/bdb/test/env003.tcl
+++ b/bdb/test/env003.tcl
@@ -1,21 +1,21 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env003.tcl,v 11.12 2000/08/25 14:21:50 sue Exp $
+# $Id: env003.tcl,v 11.21 2002/08/08 15:38:06 bostic Exp $
#
-# Env Test 003
-# Test DB_TMP_DIR and env name resolution
-# With an environment path specified using -home, and then again
-# with it specified by the environment variable DB_HOME:
-# 1) Make sure that the DB_TMP_DIR config file option is respected
-# a) as a relative pathname.
-# b) as an absolute pathname.
-# 2) Make sure that the DB_TMP_DIR db_config argument is respected,
-# again as relative and absolute pathnames.
-# 3) Make sure that if -both- db_config and a file are present,
-# only the file is respected (see doc/env/naming.html).
+# TEST env003
+# TEST Test DB_TMP_DIR and env name resolution
+# TEST With an environment path specified using -home, and then again
+# TEST with it specified by the environment variable DB_HOME:
+# TEST 1) Make sure that the DB_TMP_DIR config file option is respected
+# TEST a) as a relative pathname.
+# TEST b) as an absolute pathname.
+# TEST 2) Make sure that the -tmp_dir config option is respected,
+# TEST again as relative and absolute pathnames.
+# TEST 3) Make sure that if -both- -tmp_dir and a file are present,
+# TEST only the file is respected (see doc/env/naming.html).
proc env003 { } {
# env003 is essentially just a small driver that runs
# env003_body twice. First, it supplies a "home" argument
@@ -29,7 +29,7 @@ proc env003 { } {
puts "Env003: DB_TMP_DIR test."
- puts "\tEnv003: Running with -home argument to berkdb env."
+ puts "\tEnv003: Running with -home argument to berkdb_env."
env003_body "-home $testdir"
puts "\tEnv003: Running with environment variable DB_HOME set."
@@ -44,7 +44,6 @@ proc env003 { } {
set env(DB_HOME) $testdir/bogus_home
env003_body "-use_environ -home $testdir"
unset env(DB_HOME)
-
}
proc env003_body { home_arg } {
@@ -52,7 +51,6 @@ proc env003_body { home_arg } {
env_cleanup $testdir
set tmpdir "tmpfiles_in_here"
-
file mkdir $testdir/$tmpdir
# Set up full path to $tmpdir for when we test absolute paths.
@@ -61,63 +59,44 @@ proc env003_body { home_arg } {
set fulltmpdir [pwd]
cd $curdir
- # Run test with the temp dir. nonexistent--it checks for failure.
- env_cleanup $testdir
-
+ # Create DB_CONFIG
env003_make_config $tmpdir
# Run the meat of the test.
env003_run_test a 1 "relative path, config file" $home_arg \
$testdir/$tmpdir
- env_cleanup $testdir
-
env003_make_config $fulltmpdir
# Run the test again
env003_run_test a 2 "absolute path, config file" $home_arg \
$fulltmpdir
- env_cleanup $testdir
-
# Now we try without a config file, but instead with db_config
# relative paths
env003_run_test b 1 "relative path, db_config" "$home_arg \
-tmp_dir $tmpdir -data_dir ." \
$testdir/$tmpdir
- env_cleanup $testdir
-
- # absolute
+ # absolute paths
env003_run_test b 2 "absolute path, db_config" "$home_arg \
-tmp_dir $fulltmpdir -data_dir ." \
$fulltmpdir
- env_cleanup $testdir
-
# Now, set db_config -and- have a # DB_CONFIG file, and make
# sure only the latter is honored.
- # Make a temp directory that actually does exist to supply
- # as a bogus argument--the test checks for -nonexistent- temp
- # dirs., as success is harder to detect.
file mkdir $testdir/bogus
env003_make_config $tmpdir
- # note that we supply an -existent- tmp dir to db_config as
- # a red herring
env003_run_test c 1 "relative path, both db_config and file" \
"$home_arg -tmp_dir $testdir/bogus -data_dir ." \
$testdir/$tmpdir
- env_cleanup $testdir
- file mkdir $fulltmpdir
file mkdir $fulltmpdir/bogus
- env003_make_config $fulltmpdir/nonexistent
+ env003_make_config $fulltmpdir
- # note that we supply an -existent- tmp dir to db_config as
- # a red herring
- env003_run_test c 2 "relative path, both db_config and file" \
+ env003_run_test c 2 "absolute path, both db_config and file" \
"$home_arg -tmp_dir $fulltmpdir/bogus -data_dir ." \
$fulltmpdir
}
@@ -131,40 +110,33 @@ proc env003_run_test { major minor msg env_args tmp_path} {
# Create an environment and small-cached in-memory database to
# use.
- set dbenv [eval {berkdb env -create -home $testdir} $env_args \
- {-cachesize {0 40960 1}}]
+ set dbenv [eval {berkdb_env -create -home $testdir} $env_args \
+ {-cachesize {0 50000 1}}]
error_check_good env_open [is_valid_env $dbenv] TRUE
- set db [berkdb_open_noerr -env $dbenv -create -btree]
+
+ set db [berkdb_open -env $dbenv -create -btree]
error_check_good db_open [is_valid_db $db] TRUE
# Fill the database with more than its cache can fit.
- # !!!
- # This is actually trickier than it sounds. The tempfile
- # gets unlinked as soon as it's created, so there's no straightforward
- # way to check for its existence. Instead, we make sure
- # DB_TMP_DIR points somewhere bogus, and make sure that the temp
- # dir. does -not- exist. But to do this, we have to know
- # which call to DB->put is going to fail--the temp file is
- # created lazily, so the failure only occurs when the cache finally
- # overflows.
- # The data we've conjured up will fit nicely once, but the second
- # call will overflow the cache. Thus we check for success once,
- # then failure.
#
- set key1 "key1"
- set key2 "key2"
- set data [repeat $alphabet 1000]
-
- # First put should succeed.
- error_check_good db_put_1 [$db put $key1 $data] 0
+ # When CONFIG_TEST is defined, the tempfile is left linked so
+ # we can check for its existence. Size the data to overfill
+ # the cache--the temp file is created lazily, so it is created
+ # when the cache overflows.
+ #
+ set key "key"
+ set data [repeat $alphabet 2000]
+ error_check_good db_put [$db put $key $data] 0
- # Second one should return ENOENT.
- set errorCode NONE
- catch {$db put $key2 $data} res
- error_check_good db_put_2 [is_substr $errorCode ENOENT] 1
+ # Check for exactly one temp file.
+ set ret [glob -nocomplain $tmp_path/BDB*]
+ error_check_good temp_file_exists [llength $ret] 1
+ # Can't remove temp file until db is closed on Windows.
error_check_good db_close [$db close] 0
+ fileremove -f $ret
error_check_good env_close [$dbenv close] 0
+
}
proc env003_make_config { tmpdir } {
diff --git a/bdb/test/env004.tcl b/bdb/test/env004.tcl
index 82cc8dd25c7..e93a0d95308 100644
--- a/bdb/test/env004.tcl
+++ b/bdb/test/env004.tcl
@@ -1,13 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env004.tcl,v 11.14 2000/08/25 14:21:50 sue Exp $
+# $Id: env004.tcl,v 11.18 2002/02/20 17:08:21 sandstro Exp $
#
-# Env Test 4
-# Test multiple data directories. Do a bunch of different opens
-# to make sure that the files are detected in different directories.
+# TEST env004
+# TEST Test multiple data directories. Do a bunch of different opens
+# TEST to make sure that the files are detected in different directories.
proc env004 { } {
source ./include.tcl
@@ -38,19 +38,19 @@ proc env004 { } {
set fulldir [pwd]
cd $curdir
- set e [berkdb env -create -private -home $testdir]
+ set e [berkdb_env -create -private -home $testdir]
error_check_good dbenv [is_valid_env $e] TRUE
ddir_test $fulldir $method $e $args
error_check_good env_close [$e close] 0
- puts "\tEnv004.b: Multiple data directories in berkdb env call."
+ puts "\tEnv004.b: Multiple data directories in berkdb_env call."
env_cleanup $testdir
file mkdir $testdir/data1
file mkdir $testdir/data2
file mkdir $testdir/data3
# Now call dbenv with config specified
- set e [berkdb env -create -private \
+ set e [berkdb_env -create -private \
-data_dir . -data_dir data1 -data_dir data2 \
-data_dir data3 -home $testdir]
error_check_good dbenv [is_valid_env $e] TRUE
diff --git a/bdb/test/env005.tcl b/bdb/test/env005.tcl
index 4ad9419936f..03bb1b40b34 100644
--- a/bdb/test/env005.tcl
+++ b/bdb/test/env005.tcl
@@ -1,14 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env005.tcl,v 11.8 2000/08/25 14:21:50 sue Exp $
+# $Id: env005.tcl,v 11.15 2002/02/22 14:28:37 sandstro Exp $
#
-# Env Test 5
-# Test that using subsystems without initializing them correctly
-# returns an error. Cannot test mpool, because it is assumed
-# in the Tcl code.
+# TEST env005
+# TEST Test that using subsystems without initializing them correctly
+# TEST returns an error. Cannot test mpool, because it is assumed in
+# TEST the Tcl code.
proc env005 { } {
source ./include.tcl
@@ -17,7 +17,7 @@ proc env005 { } {
env_cleanup $testdir
puts "\tEnv005.a: Creating env with no subsystems."
- set e [berkdb env -create -home $testdir]
+ set e [berkdb_env_noerr -create -home $testdir]
error_check_good dbenv [is_valid_env $e] TRUE
set db [berkdb_open -create -btree $testdir/env005.db]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -27,17 +27,17 @@ proc env005 { } {
{ "lock_get read 1 1" "Env005.b1"}
{ "lock_id" "Env005.b2"}
{ "lock_stat" "Env005.b3"}
+ { "lock_timeout 100" "Env005.b4"}
{ "log_archive" "Env005.c0"}
- { "log_file {1 1}" "Env005.c1"}
- { "log_flush" "Env005.c2"}
- { "log_get -first" "Env005.c3"}
+ { "log_cursor" "Env005.c1"}
+ { "log_file {1 1}" "Env005.c2"}
+ { "log_flush" "Env005.c3"}
{ "log_put record" "Env005.c4"}
- { "log_register $db xxx" "Env005.c5"}
- { "log_stat" "Env005.c6"}
- { "log_unregister $db" "Env005.c7"}
+ { "log_stat" "Env005.c5"}
{ "txn" "Env005.d0"}
{ "txn_checkpoint" "Env005.d1"}
{ "txn_stat" "Env005.d2"}
+ { "txn_timeout 100" "Env005.d3"}
}
foreach pair $rlist {
diff --git a/bdb/test/env006.tcl b/bdb/test/env006.tcl
index 1a39886cafa..48fc6982772 100644
--- a/bdb/test/env006.tcl
+++ b/bdb/test/env006.tcl
@@ -1,14 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env006.tcl,v 11.5 2000/10/27 13:23:55 sue Exp $
-#
-# Env Test 6
-# DB Utility Check
-# Make sure that all the utilities exist and run.
+# $Id: env006.tcl,v 11.8 2002/01/11 15:53:23 bostic Exp $
#
+# TEST env006
+# TEST Make sure that all the utilities exist and run.
proc env006 { } {
source ./include.tcl
@@ -23,6 +21,8 @@ proc env006 { } {
{ "db_printlog" "Env006.f"}
{ "db_recover" "Env006.g"}
{ "db_stat" "Env006.h"}
+ { "db_upgrade" "Env006.h"}
+ { "db_verify" "Env006.h"}
}
foreach pair $rlist {
set cmd [lindex $pair 0]
diff --git a/bdb/test/env007.tcl b/bdb/test/env007.tcl
index b8ddea75c91..5748d2dbc89 100644
--- a/bdb/test/env007.tcl
+++ b/bdb/test/env007.tcl
@@ -1,17 +1,20 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env007.tcl,v 11.5 2000/08/25 14:21:50 sue Exp $
+# $Id: env007.tcl,v 11.21 2002/08/12 20:49:36 sandstro Exp $
#
-# Env Test 007
-# Test various config file options.
-# 1) Make sure command line option is respected
-# 2) Make sure that config file option is respected
-# 3) Make sure that if -both- DB_CONFIG and the set_<whatever>
-# method is used, only the file is respected.
+# TEST env007
+# TEST Test various DB_CONFIG config file options.
+# TEST 1) Make sure command line option is respected
+# TEST 2) Make sure that config file option is respected
+# TEST 3) Make sure that if -both- DB_CONFIG and the set_<whatever>
+# TEST method is used, only the file is respected.
+# TEST Then test all known config options.
proc env007 { } {
+ global errorInfo
+
# env007 is essentially just a small driver that runs
# env007_body twice. First, it supplies a "set" argument
# to use with environment opens, and the second time it sets
@@ -29,15 +32,19 @@ proc env007 { } {
set rlist {
{ " -txn_max " "set_tx_max" "19" "31" "Env007.a: Txn Max"
"txn_stat" "Max Txns"}
- { " -lock_max " "set_lk_max" "19" "31" "Env007.b: Lock Max"
- "lock_stat" "Max locks"}
- { " -log_buffer " "set_lg_bsize" "65536" "131072" "Env007.c: Log Bsize"
+ { " -lock_max_locks " "set_lk_max_locks" "17" "29" "Env007.b: Lock Max"
+ "lock_stat" "Maximum locks"}
+ { " -lock_max_lockers " "set_lk_max_lockers" "1500" "2000"
+ "Env007.c: Max Lockers" "lock_stat" "Maximum lockers"}
+ { " -lock_max_objects " "set_lk_max_objects" "1500" "2000"
+ "Env007.d: Max Objects" "lock_stat" "Maximum objects"}
+ { " -log_buffer " "set_lg_bsize" "65536" "131072" "Env007.e: Log Bsize"
"log_stat" "Log record cache size"}
- { " -log_max " "set_lg_max" "8388608" "9437184" "Env007.d: Log Max"
- "log_stat" "Maximum log file size"}
+ { " -log_max " "set_lg_max" "8388608" "9437184" "Env007.f: Log Max"
+ "log_stat" "Current log file size"}
}
- set e "berkdb env -create -mode 0644 -home $testdir -log -lock -txn "
+ set e "berkdb_env -create -mode 0644 -home $testdir -log -lock -txn "
foreach item $rlist {
set envarg [lindex $item 0]
set configarg [lindex $item 1]
@@ -72,6 +79,122 @@ proc env007 { } {
env007_check $env $statcmd $statstr $configval
error_check_good envclose:2 [$env close] 0
}
+
+ #
+ # Test all options. For all config options, write it out
+ # to the file and make sure we can open the env. We cannot
+ # necessarily check via stat that it worked but this execs
+ # the config file code itself.
+ #
+ set cfglist {
+ { "set_cachesize" "0 1048576 0" }
+ { "set_data_dir" "." }
+ { "set_flags" "db_cdb_alldb" }
+ { "set_flags" "db_direct_db" }
+ { "set_flags" "db_direct_log" }
+ { "set_flags" "db_nolocking" }
+ { "set_flags" "db_nommap" }
+ { "set_flags" "db_nopanic" }
+ { "set_flags" "db_overwrite" }
+ { "set_flags" "db_region_init" }
+ { "set_flags" "db_txn_nosync" }
+ { "set_flags" "db_txn_write_nosync" }
+ { "set_flags" "db_yieldcpu" }
+ { "set_lg_bsize" "65536" }
+ { "set_lg_dir" "." }
+ { "set_lg_max" "8388608" }
+ { "set_lg_regionmax" "65536" }
+ { "set_lk_detect" "db_lock_default" }
+ { "set_lk_detect" "db_lock_expire" }
+ { "set_lk_detect" "db_lock_maxlocks" }
+ { "set_lk_detect" "db_lock_minlocks" }
+ { "set_lk_detect" "db_lock_minwrite" }
+ { "set_lk_detect" "db_lock_oldest" }
+ { "set_lk_detect" "db_lock_random" }
+ { "set_lk_detect" "db_lock_youngest" }
+ { "set_lk_max" "50" }
+ { "set_lk_max_lockers" "1500" }
+ { "set_lk_max_locks" "29" }
+ { "set_lk_max_objects" "1500" }
+ { "set_lock_timeout" "100" }
+ { "set_mp_mmapsize" "12582912" }
+ { "set_region_init" "1" }
+ { "set_shm_key" "15" }
+ { "set_tas_spins" "15" }
+ { "set_tmp_dir" "." }
+ { "set_tx_max" "31" }
+ { "set_txn_timeout" "100" }
+ { "set_verbose" "db_verb_chkpoint" }
+ { "set_verbose" "db_verb_deadlock" }
+ { "set_verbose" "db_verb_recovery" }
+ { "set_verbose" "db_verb_waitsfor" }
+ }
+
+ puts "\tEnv007.g: Config file settings"
+ set e "berkdb_env -create -mode 0644 -home $testdir -log -lock -txn "
+ foreach item $cfglist {
+ env_cleanup $testdir
+ set configarg [lindex $item 0]
+ set configval [lindex $item 1]
+
+ env007_make_config $configarg $configval
+
+ # verify using just config file
+ puts "\t\t $configarg $configval"
+ set env [eval $e]
+ error_check_good envvalid:1 [is_valid_env $env] TRUE
+ error_check_good envclose:1 [$env close] 0
+ }
+
+ set cfglist {
+ { "set_cachesize" "1048576" }
+ { "set_flags" "db_xxx" }
+ { "set_flags" "1" }
+ { "set_flags" "db_txn_nosync x" }
+ { "set_lg_bsize" "db_xxx" }
+ { "set_lg_max" "db_xxx" }
+ { "set_lg_regionmax" "db_xxx" }
+ { "set_lk_detect" "db_xxx" }
+ { "set_lk_detect" "1" }
+ { "set_lk_detect" "db_lock_youngest x" }
+ { "set_lk_max" "db_xxx" }
+ { "set_lk_max_locks" "db_xxx" }
+ { "set_lk_max_lockers" "db_xxx" }
+ { "set_lk_max_objects" "db_xxx" }
+ { "set_mp_mmapsize" "db_xxx" }
+ { "set_region_init" "db_xxx" }
+ { "set_shm_key" "db_xxx" }
+ { "set_tas_spins" "db_xxx" }
+ { "set_tx_max" "db_xxx" }
+ { "set_verbose" "db_xxx" }
+ { "set_verbose" "1" }
+ { "set_verbose" "db_verb_recovery x" }
+ }
+ puts "\tEnv007.h: Config value errors"
+ set e "berkdb_env_noerr -create -mode 0644 \
+ -home $testdir -log -lock -txn "
+ foreach item $cfglist {
+ set configarg [lindex $item 0]
+ set configval [lindex $item 1]
+
+ env007_make_config $configarg $configval
+
+ # verify using just config file
+ puts "\t\t $configarg $configval"
+ set stat [catch {eval $e} ret]
+ error_check_good envopen $stat 1
+ error_check_good error [is_substr $errorInfo \
+ "incorrect arguments for name-value pair"] 1
+ }
+
+ puts "\tEnv007.i: Config name error set_xxx"
+ set e "berkdb_env_noerr -create -mode 0644 \
+ -home $testdir -log -lock -txn "
+ env007_make_config "set_xxx" 1
+ set stat [catch {eval $e} ret]
+ error_check_good envopen $stat 1
+ error_check_good error [is_substr $errorInfo \
+ "unrecognized name-value pair"] 1
}
proc env007_check { env statcmd statstr testval } {
diff --git a/bdb/test/env008.tcl b/bdb/test/env008.tcl
index 645f07f63d6..dccdb41f612 100644
--- a/bdb/test/env008.tcl
+++ b/bdb/test/env008.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: env008.tcl,v 11.2 2000/10/30 19:00:38 sue Exp $
+# $Id: env008.tcl,v 11.6 2002/02/22 14:29:34 sandstro Exp $
#
-# Test of env and subdirs.
+# TEST env008
+# TEST Test environments and subdirectories.
proc env008 { } {
global errorInfo
global errorCode
@@ -21,9 +22,8 @@ proc env008 { } {
puts "Env008: Test of environments and subdirectories."
- # Try opening without Create flag should error
puts "\tEnv008.a: Create env and db."
- set env [berkdb env -create -mode 0644 -home $testdir -txn]
+ set env [berkdb_env -create -mode 0644 -home $testdir -txn]
error_check_good env [is_valid_env $env] TRUE
puts "\tEnv008.b: Remove db in subdir."
diff --git a/bdb/test/env009.tcl b/bdb/test/env009.tcl
new file mode 100644
index 00000000000..264d5e2dfec
--- /dev/null
+++ b/bdb/test/env009.tcl
@@ -0,0 +1,57 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: env009.tcl,v 11.5 2002/08/12 20:40:36 sandstro Exp $
+#
+# TEST env009
+# TEST Test calls to all the various stat functions. We have several
+# TEST sprinkled throughout the test suite, but this will ensure that
+# TEST we run all of them at least once.
+proc env009 { } {
+ source ./include.tcl
+
+ puts "Env009: Various stat function test."
+
+ env_cleanup $testdir
+ puts "\tEnv009.a: Setting up env and a database."
+
+ set e [berkdb_env -create -home $testdir -txn]
+ error_check_good dbenv [is_valid_env $e] TRUE
+ set dbbt [berkdb_open -create -btree $testdir/env009bt.db]
+ error_check_good dbopen [is_valid_db $dbbt] TRUE
+ set dbh [berkdb_open -create -hash $testdir/env009h.db]
+ error_check_good dbopen [is_valid_db $dbh] TRUE
+ set dbq [berkdb_open -create -btree $testdir/env009q.db]
+ error_check_good dbopen [is_valid_db $dbq] TRUE
+
+ set rlist {
+ { "lock_stat" "Maximum locks" "Env009.b"}
+ { "log_stat" "Magic" "Env009.c"}
+ { "mpool_stat" "Number of caches" "Env009.d"}
+ { "txn_stat" "Max Txns" "Env009.e"}
+ }
+
+ foreach pair $rlist {
+ set cmd [lindex $pair 0]
+ set str [lindex $pair 1]
+ set msg [lindex $pair 2]
+ puts "\t$msg: $cmd"
+ set ret [$e $cmd]
+ error_check_good $cmd [is_substr $ret $str] 1
+ }
+ puts "\tEnv009.f: btree stats"
+ set ret [$dbbt stat]
+ error_check_good $cmd [is_substr $ret "Magic"] 1
+ puts "\tEnv009.g: hash stats"
+ set ret [$dbh stat]
+ error_check_good $cmd [is_substr $ret "Magic"] 1
+ puts "\tEnv009.f: queue stats"
+ set ret [$dbq stat]
+ error_check_good $cmd [is_substr $ret "Magic"] 1
+ error_check_good dbclose [$dbbt close] 0
+ error_check_good dbclose [$dbh close] 0
+ error_check_good dbclose [$dbq close] 0
+ error_check_good envclose [$e close] 0
+}
diff --git a/bdb/test/env010.tcl b/bdb/test/env010.tcl
new file mode 100644
index 00000000000..4444e34e439
--- /dev/null
+++ b/bdb/test/env010.tcl
@@ -0,0 +1,49 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: env010.tcl,v 1.4 2002/02/20 17:08:21 sandstro Exp $
+#
+# TEST env010
+# TEST Run recovery in an empty directory, and then make sure we can still
+# TEST create a database in that directory.
+proc env010 { } {
+ source ./include.tcl
+
+ puts "Env010: Test of recovery in an empty directory."
+
+ # Create a new directory used only for this test
+
+ if { [file exists $testdir/EMPTYDIR] != 1 } {
+ file mkdir $testdir/EMPTYDIR
+ } else {
+ puts "\nDirectory already exists."
+ }
+
+ # Do the test twice, for regular recovery and catastrophic
+ # Open environment and recover, but don't create a database
+
+ foreach rmethod {recover recover_fatal} {
+
+ puts "\tEnv010: Creating env for $rmethod test."
+ env_cleanup $testdir/EMPTYDIR
+ set e [berkdb_env -create -home $testdir/EMPTYDIR -$rmethod]
+ error_check_good dbenv [is_valid_env $e] TRUE
+
+ # Open and close a database
+ # The method doesn't matter, so picked btree arbitrarily
+
+ set db [eval {berkdb_open -env $e \
+ -btree -create -mode 0644} ]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ error_check_good db_close [$db close] 0
+
+ # Close environment
+
+ error_check_good envclose [$e close] 0
+ error_check_good berkdb:envremove \
+ [berkdb envremove -home $testdir/EMPTYDIR] 0
+ }
+ puts "\tEnv010 complete."
+}
diff --git a/bdb/test/env011.tcl b/bdb/test/env011.tcl
new file mode 100644
index 00000000000..4061bb3fe51
--- /dev/null
+++ b/bdb/test/env011.tcl
@@ -0,0 +1,39 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: env011.tcl,v 1.2 2002/02/20 17:08:21 sandstro Exp $
+#
+# TEST env011
+# TEST Run with region overwrite flag.
+proc env011 { } {
+ source ./include.tcl
+
+ puts "Env011: Test of region overwriting."
+ env_cleanup $testdir
+
+ puts "\tEnv011: Creating/closing env for open test."
+ set e [berkdb_env -create -overwrite -home $testdir -txn]
+ error_check_good dbenv [is_valid_env $e] TRUE
+ set db [eval \
+ {berkdb_open -auto_commit -env $e -btree -create -mode 0644} ]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set ret [eval {$db put} -auto_commit "aaa" "data"]
+ error_check_good put $ret 0
+ set ret [eval {$db put} -auto_commit "bbb" "data"]
+ error_check_good put $ret 0
+ error_check_good db_close [$db close] 0
+ error_check_good envclose [$e close] 0
+
+ puts "\tEnv011: Opening the environment with overwrite set."
+ set e [berkdb_env -create -overwrite -home $testdir -txn -recover]
+ error_check_good dbenv [is_valid_env $e] TRUE
+ error_check_good envclose [$e close] 0
+
+ puts "\tEnv011: Removing the environment with overwrite set."
+ error_check_good berkdb:envremove \
+ [berkdb envremove -home $testdir -overwrite] 0
+
+ puts "\tEnv011 complete."
+}
diff --git a/bdb/test/hsearch.tcl b/bdb/test/hsearch.tcl
index 0afee7fb2de..afeed93f74e 100644
--- a/bdb/test/hsearch.tcl
+++ b/bdb/test/hsearch.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: hsearch.tcl,v 11.7 2000/08/25 14:21:50 sue Exp $
+# $Id: hsearch.tcl,v 11.9 2002/01/11 15:53:24 bostic Exp $
#
# Historic Hsearch interface test.
# Use the first 1000 entries from the dictionary.
diff --git a/bdb/test/join.tcl b/bdb/test/join.tcl
index ebf33b8cdf3..87b0d1fae58 100644
--- a/bdb/test/join.tcl
+++ b/bdb/test/join.tcl
@@ -1,19 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: join.tcl,v 11.17 2000/08/25 14:21:51 sue Exp $
+# $Id: join.tcl,v 11.21 2002/02/20 17:08:22 sandstro Exp $
#
-# We'll test 2-way, 3-way, and 4-way joins and figure that if those work,
-# everything else does as well. We'll create test databases called
-# join1.db, join2.db, join3.db, and join4.db. The number on the database
-# describes the duplication -- duplicates are of the form 0, N, 2N, 3N, ...
-# where N is the number of the database. Primary.db is the primary database,
-# and null.db is the database that has no matching duplicates.
-#
-# We should test this on all btrees, all hash, and a combination thereof
-# Join test.
+# TEST jointest
+# TEST Test duplicate assisted joins. Executes 1, 2, 3 and 4-way joins
+# TEST with differing index orders and selectivity.
+# TEST
+# TEST We'll test 2-way, 3-way, and 4-way joins and figure that if those
+# TEST work, everything else does as well. We'll create test databases
+# TEST called join1.db, join2.db, join3.db, and join4.db. The number on
+# TEST the database describes the duplication -- duplicates are of the
+# TEST form 0, N, 2N, 3N, ... where N is the number of the database.
+# TEST Primary.db is the primary database, and null.db is the database
+# TEST that has no matching duplicates.
+# TEST
+# TEST We should test this on all btrees, all hash, and a combination thereof
proc jointest { {psize 8192} {with_dup_dups 0} {flags 0} } {
global testdir
global rand_init
@@ -24,7 +28,7 @@ proc jointest { {psize 8192} {with_dup_dups 0} {flags 0} } {
# Use one environment for all database opens so we don't
# need oodles of regions.
- set env [berkdb env -create -home $testdir]
+ set env [berkdb_env -create -home $testdir]
error_check_good env_open [is_valid_env $env] TRUE
# With the new offpage duplicate code, we don't support
diff --git a/bdb/test/lock001.tcl b/bdb/test/lock001.tcl
index d571a987240..1afcc471fc1 100644
--- a/bdb/test/lock001.tcl
+++ b/bdb/test/lock001.tcl
@@ -1,67 +1,28 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: lock001.tcl,v 11.11 2000/08/25 14:21:51 sue Exp $
+# $Id: lock001.tcl,v 11.19 2002/04/25 19:30:28 sue Exp $
#
-# Test driver for lock tests.
-# General Multi Random
-# Options are:
-# -dir <directory in which to store mpool> Y Y Y
-# -iterations <iterations> Y N Y
-# -ldegree <number of locks per iteration> N N Y
-# -maxlocks <locks in table> Y Y Y
-# -objs <number of objects> N N Y
-# -procs <number of processes to run> N N Y
-# -reads <read ratio> N N Y
-# -seeds <list of seed values for processes> N N Y
-# -wait <wait interval after getting locks> N N Y
-# -conflicts <conflict matrix; a list of lists> Y Y Y
-proc lock_usage {} {
- puts stderr "randomlock\n\t-dir <dir>\n\t-iterations <iterations>"
- puts stderr "\t-conflicts <conflict matrix>"
- puts stderr "\t-ldegree <locks per iteration>\n\t-maxlocks <n>"
- puts stderr "\t-objs <objects>\n\t-procs <nprocs>\n\t-reads <%reads>"
- puts stderr "\t-seeds <list of seeds>\n\t-wait <max wait interval>"
- return
-}
-proc locktest { args } {
+# TEST lock001
+# TEST Make sure that the basic lock tests work. Do some simple gets
+# TEST and puts for a single locker.
+proc lock001 { {iterations 1000} {maxlocks 1000} } {
source ./include.tcl
+ global lock_curid
+ global lock_maxid
+
+ set save_curid $lock_curid
+ set save_maxid $lock_maxid
# Set defaults
# Adjusted to make exact match of isqrt
#set conflicts { 3 0 0 0 0 0 1 0 1 1}
#set conflicts { 3 0 0 0 0 1 0 1 1}
+
set conflicts { 0 0 0 0 0 1 0 1 1}
- set iterations 1000
- set ldegree 5
- set maxlocks 1000
- set objs 75
- set procs 5
- set reads 65
- set seeds {}
- set wait 5
- for { set i 0 } { $i < [llength $args] } {incr i} {
- switch -regexp -- [lindex $args $i] {
- -c.* { incr i; set conflicts [linkdex $args $i] }
- -d.* { incr i; set testdir [lindex $args $i] }
- -i.* { incr i; set iterations [lindex $args $i] }
- -l.* { incr i; set ldegree [lindex $args $i] }
- -m.* { incr i; set maxlocks [lindex $args $i] }
- -o.* { incr i; set objs [lindex $args $i] }
- -p.* { incr i; set procs [lindex $args $i] }
- -r.* { incr i; set reads [lindex $args $i] }
- -s.* { incr i; set seeds [lindex $args $i] }
- -w.* { incr i; set wait [lindex $args $i] }
- default {
- puts -nonewline "FAIL:[timestamp] Usage: "
- lock_usage
- return
- }
- }
- }
set nmodes [isqrt [llength $conflicts]]
# Cleanup
@@ -70,26 +31,15 @@ proc locktest { args } {
# Open the region we'll use for testing.
set eflags "-create -lock -home $testdir -mode 0644 \
-lock_max $maxlocks -lock_conflict {$nmodes {$conflicts}}"
- set env [eval {berkdb env} $eflags]
- lock001 $env $iterations $nmodes
- reset_env $env
- env_cleanup $testdir
-
- lock002 $maxlocks $conflicts
-
- lock003 $testdir $iterations \
- $maxlocks $procs $ldegree $objs $reads $wait $conflicts $seeds
-}
-
-# Make sure that the basic lock tests work. Do some simple gets and puts for
-# a single locker.
-proc lock001 {env iter nmodes} {
- source ./include.tcl
+ set env [eval {berkdb_env} $eflags]
+ error_check_good env [is_valid_env $env] TRUE
+ error_check_good lock_id_set \
+ [$env lock_id_set $lock_curid $lock_maxid] 0
puts "Lock001: test basic lock operations"
- set locker 999
+ set locker [$env lock_id]
# Get and release each type of lock
- puts "Lock001.a: get and release each type of lock"
+ puts "\tLock001.a: get and release each type of lock"
foreach m {ng write read} {
set obj obj$m
set lockp [$env lock_get $m $locker $obj]
@@ -101,7 +51,7 @@ proc lock001 {env iter nmodes} {
# Get a bunch of locks for the same locker; these should work
set obj OBJECT
- puts "Lock001.b: Get a bunch of locks for the same locker"
+ puts "\tLock001.b: Get a bunch of locks for the same locker"
foreach m {ng write read} {
set lockp [$env lock_get $m $locker $obj ]
lappend locklist $lockp
@@ -112,7 +62,7 @@ proc lock001 {env iter nmodes} {
set locklist {}
# Check that reference counted locks work
- puts "Lock001.c: reference counted locks."
+ puts "\tLock001.c: reference counted locks."
for {set i 0} { $i < 10 } {incr i} {
set lockp [$env lock_get -nowait write $locker $obj]
error_check_good lock_get:c [is_blocked $lockp] 0
@@ -131,10 +81,10 @@ proc lock001 {env iter nmodes} {
}
# Change the locker
- set locker [incr locker]
+ set locker [$env lock_id]
set blocklist {}
# Skip NO_LOCK lock.
- puts "Lock001.e: Change the locker, acquire read and write."
+ puts "\tLock001.d: Change the locker, acquire read and write."
foreach i {write read} {
catch {$env lock_get -nowait $i $locker $obj} ret
error_check_good lock_get:e [is_substr $ret "not granted"] 1
@@ -146,7 +96,7 @@ proc lock001 {env iter nmodes} {
# Now re-acquire blocking locks
set locklist {}
- puts "Lock001.f: Re-acquire blocking locks."
+ puts "\tLock001.e: Re-acquire blocking locks."
foreach i {write read} {
set lockp [$env lock_get -nowait $i $locker $obj ]
error_check_good lock_get:f [is_substr $lockp $env] 1
@@ -156,8 +106,10 @@ proc lock001 {env iter nmodes} {
# Now release new locks
release_list $locklist
+ error_check_good free_id [$env lock_id_free $locker] 0
+
+ error_check_good envclose [$env close] 0
- puts "Lock001 Complete."
}
# Blocked locks appear as lockmgrN.lockM\nBLOCKED
diff --git a/bdb/test/lock002.tcl b/bdb/test/lock002.tcl
index b433730b1e6..a1ad8760c9d 100644
--- a/bdb/test/lock002.tcl
+++ b/bdb/test/lock002.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: lock002.tcl,v 11.10 2000/08/25 14:21:51 sue Exp $
+# $Id: lock002.tcl,v 11.19 2002/04/25 19:30:29 sue Exp $
#
-# Exercise basic multi-process aspects of lock.
+# TEST lock002
+# TEST Exercise basic multi-process aspects of lock.
proc lock002 { {maxlocks 1000} {conflicts {0 0 0 0 0 1 0 1 1} } } {
source ./include.tcl
@@ -24,22 +25,25 @@ proc lock002 { {maxlocks 1000} {conflicts {0 0 0 0 0 1 0 1 1} } } {
# detach from it, etc.
proc mlock_open { maxl nmodes conflicts } {
source ./include.tcl
+ global lock_curid
+ global lock_maxid
- puts "Lock002.a multi-process open/close test"
+ puts "\tLock002.a multi-process open/close test"
# Open/Create region here. Then close it and try to open from
# other test process.
- set env_cmd [concat "berkdb env -create -mode 0644 \
+ set env_cmd [concat "berkdb_env -create -mode 0644 \
-lock -lock_max $maxl -lock_conflict" \
[list [list $nmodes $conflicts]] "-home $testdir"]
set local_env [eval $env_cmd]
+ $local_env lock_id_set $lock_curid $lock_maxid
error_check_good env_open [is_valid_env $local_env] TRUE
set ret [$local_env close]
error_check_good env_close $ret 0
# Open from other test process
- set env_cmd "berkdb env -mode 0644 -home $testdir"
+ set env_cmd "berkdb_env -mode 0644 -home $testdir"
set f1 [open |$tclsh_path r+]
puts $f1 "source $test_path/test.tcl"
@@ -58,7 +62,7 @@ proc mlock_open { maxl nmodes conflicts } {
error_check_good remote:lock_close $ret 0
# Try opening for create. Will succeed because region exists.
- set env_cmd [concat "berkdb env -create -mode 0644 \
+ set env_cmd [concat "berkdb_env -create -mode 0644 \
-lock -lock_max $maxl -lock_conflict" \
[list [list $nmodes $conflicts]] "-home $testdir"]
set local_env [eval $env_cmd]
@@ -76,10 +80,10 @@ proc mlock_open { maxl nmodes conflicts } {
proc mlock_wait { } {
source ./include.tcl
- puts "Lock002.b multi-process get/put wait test"
+ puts "\tLock002.b multi-process get/put wait test"
# Open region locally
- set env_cmd "berkdb env -lock -home $testdir"
+ set env_cmd "berkdb_env -lock -home $testdir"
set local_env [eval $env_cmd]
error_check_good env_open [is_valid_env $local_env] TRUE
@@ -95,15 +99,15 @@ proc mlock_wait { } {
# remotely. We hold the locks for several seconds
# so that we can use timestamps to figure out if the
# other process waited.
- set locker 1
- set local_lock [$local_env lock_get write $locker object1]
+ set locker1 [$local_env lock_id]
+ set local_lock [$local_env lock_get write $locker1 object1]
error_check_good lock_get [is_valid_lock $local_lock $local_env] TRUE
# Now request a lock that we expect to hang; generate
# timestamps so we can tell if it actually hangs.
- set locker 2
+ set locker2 [send_cmd $f1 "$remote_env lock_id"]
set remote_lock [send_timed_cmd $f1 1 \
- "set lock \[$remote_env lock_get write $locker object1\]"]
+ "set lock \[$remote_env lock_get write $locker2 object1\]"]
# Now sleep before releasing lock
tclsleep 5
@@ -127,8 +131,7 @@ proc mlock_wait { } {
set ret [send_cmd $f1 "$remote_lock put"]
- set locker 1
- set local_lock [$local_env lock_get write $locker object1]
+ set local_lock [$local_env lock_get write $locker1 object1]
error_check_good lock_get:time \
[expr [expr [timestamp -r] - $start] > 2] 1
error_check_good lock_get:local \
@@ -139,6 +142,8 @@ proc mlock_wait { } {
error_check_good lock_put:remote $result 0
# Clean up remote
+ set result [send_cmd $f1 "$remote_env lock_id_free $locker2" ]
+ error_check_good remote_free_id $result 0
set ret [send_cmd $f1 "reset_env $remote_env"]
close $f1
@@ -146,6 +151,7 @@ proc mlock_wait { } {
# Now close up locally
set ret [$local_lock put]
error_check_good lock_put $ret 0
+ error_check_good lock_id_free [$local_env lock_id_free $locker1] 0
reset_env $local_env
}
diff --git a/bdb/test/lock003.tcl b/bdb/test/lock003.tcl
index 539b6d0ff66..91a8a2e90f6 100644
--- a/bdb/test/lock003.tcl
+++ b/bdb/test/lock003.tcl
@@ -1,48 +1,99 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: lock003.tcl,v 11.16 2000/08/25 14:21:51 sue Exp $
+# $Id: lock003.tcl,v 11.25 2002/09/05 17:23:06 sandstro Exp $
#
-# Exercise multi-process aspects of lock. Generate a bunch of parallel
-# testers that try to randomly obtain locks.
-proc lock003 { dir {iter 500} {max 1000} {procs 5} {ldegree 5} {objs 75} \
- {reads 65} {wait 1} {conflicts { 3 0 0 0 0 0 1 0 1 1}} {seeds {}} } {
+# TEST lock003
+# TEST Exercise multi-process aspects of lock. Generate a bunch of parallel
+# TEST testers that try to randomly obtain locks; make sure that the locks
+# TEST correctly protect corresponding objects.
+proc lock003 { {iter 500} {max 1000} {procs 5} } {
source ./include.tcl
+ global lock_curid
+ global lock_maxid
+
+ set ldegree 5
+ set objs 75
+ set reads 65
+ set wait 1
+ set conflicts { 0 0 0 0 0 1 0 1 1}
+ set seeds {}
puts "Lock003: Multi-process random lock test"
# Clean up after previous runs
- env_cleanup $dir
+ env_cleanup $testdir
# Open/create the lock region
- set e [berkdb env -create -lock -home $dir]
+ puts "\tLock003.a: Create environment"
+ set e [berkdb_env -create -lock -home $testdir]
error_check_good env_open [is_substr $e env] 1
+ $e lock_id_set $lock_curid $lock_maxid
- set ret [$e close]
- error_check_good env_close $ret 0
+ error_check_good env_close [$e close] 0
# Now spawn off processes
set pidlist {}
+
for { set i 0 } {$i < $procs} {incr i} {
if { [llength $seeds] == $procs } {
set s [lindex $seeds $i]
}
- puts "$tclsh_path\
- $test_path/wrap.tcl \
- lockscript.tcl $dir/$i.lockout\
- $dir $iter $objs $wait $ldegree $reads &"
+# puts "$tclsh_path\
+# $test_path/wrap.tcl \
+# lockscript.tcl $testdir/$i.lockout\
+# $testdir $iter $objs $wait $ldegree $reads &"
set p [exec $tclsh_path $test_path/wrap.tcl \
lockscript.tcl $testdir/lock003.$i.out \
- $dir $iter $objs $wait $ldegree $reads &]
+ $testdir $iter $objs $wait $ldegree $reads &]
lappend pidlist $p
}
- puts "Lock003: $procs independent processes now running"
- watch_procs 30 10800
+ puts "\tLock003.b: $procs independent processes now running"
+ watch_procs $pidlist 30 10800
+
+ # Check for test failure
+ set e [eval findfail [glob $testdir/lock003.*.out]]
+ error_check_good "FAIL: error message(s) in log files" $e 0
+
# Remove log files
for { set i 0 } {$i < $procs} {incr i} {
- fileremove -f $dir/$i.lockout
+ fileremove -f $testdir/lock003.$i.out
+ }
+}
+
+# Create and destroy flag files to show we have an object locked, and
+# verify that the correct files exist or don't exist given that we've
+# just read or write locked a file.
+proc lock003_create { rw obj } {
+ source ./include.tcl
+
+ set pref $testdir/L3FLAG
+ set f [open $pref.$rw.[pid].$obj w]
+ close $f
+}
+
+proc lock003_destroy { obj } {
+ source ./include.tcl
+
+ set pref $testdir/L3FLAG
+ set f [glob -nocomplain $pref.*.[pid].$obj]
+ error_check_good l3_destroy [llength $f] 1
+ fileremove $f
+}
+
+proc lock003_vrfy { rw obj } {
+ source ./include.tcl
+
+ set pref $testdir/L3FLAG
+ if { [string compare $rw "write"] == 0 } {
+ set fs [glob -nocomplain $pref.*.*.$obj]
+ error_check_good "number of other locks on $obj" [llength $fs] 0
+ } else {
+ set fs [glob -nocomplain $pref.write.*.$obj]
+ error_check_good "number of write locks on $obj" [llength $fs] 0
}
}
+
diff --git a/bdb/test/lock004.tcl b/bdb/test/lock004.tcl
new file mode 100644
index 00000000000..7fd51ee42f2
--- /dev/null
+++ b/bdb/test/lock004.tcl
@@ -0,0 +1,29 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: lock004.tcl,v 11.5 2002/04/25 19:30:30 sue Exp $
+#
+# TEST lock004
+# TEST Test locker ids wraping around.
+
+proc lock004 {} {
+ source ./include.tcl
+ global lock_curid
+ global lock_maxid
+
+ set save_curid $lock_curid
+ set save_maxid $lock_maxid
+
+ set lock_curid [expr $lock_maxid - 1]
+ puts "Lock004: Locker id wraparound test"
+ puts "\tLock004.a: repeat lock001-lock003 with wraparound lockids"
+
+ lock001
+ lock002
+ lock003
+
+ set lock_curid $save_curid
+ set lock_maxid $save_maxid
+}
diff --git a/bdb/test/lock005.tcl b/bdb/test/lock005.tcl
new file mode 100644
index 00000000000..5afe7344d36
--- /dev/null
+++ b/bdb/test/lock005.tcl
@@ -0,0 +1,177 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2001
+# Sleepycat Software. All rights reserved.
+#
+# $Id: lock005.tcl,v 1.7 2002/08/08 15:38:07 bostic Exp $
+#
+# TEST lock005
+# TEST Check that page locks are being released properly.
+
+proc lock005 { } {
+ source ./include.tcl
+
+ puts "Lock005: Page lock release test"
+
+ # Clean up after previous runs
+ env_cleanup $testdir
+
+ # Open/create the lock region
+ set e [berkdb_env -create -lock -home $testdir -txn -log]
+ error_check_good env_open [is_valid_env $e] TRUE
+
+ # Open/create the database
+ set db [berkdb open -create -auto_commit -env $e -len 10 -queue q.db]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ # Check that records are locking by trying to
+ # fetch a record on the wrong transaction.
+ puts "\tLock005.a: Verify that we are locking"
+
+ # Start the first transaction
+ set txn1 [$e txn -nowait]
+ error_check_good txn_begin [is_valid_txn $txn1 $e] TRUE
+ set ret [catch {$db put -txn $txn1 -append record1} recno1]
+ error_check_good dbput_txn1 $ret 0
+
+ # Start second txn while the first is still running ...
+ set txn2 [$e txn -nowait]
+ error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE
+
+ # ... and try to get a record from the first txn (should fail)
+ set ret [catch {$db get -txn $txn2 $recno1} res]
+ error_check_good dbget_wrong_record \
+ [is_substr $res "Lock not granted"] 1
+
+ # End transactions
+ error_check_good txn1commit [$txn1 commit] 0
+ how_many_locks 1 $e
+ error_check_good txn2commit [$txn2 commit] 0
+ # The number of locks stays the same here because the first
+ # lock is released and the second lock was never granted.
+ how_many_locks 1 $e
+
+ # Test lock behavior for both abort and commit
+ puts "\tLock005.b: Verify locks after abort or commit"
+ foreach endorder {forward reverse} {
+ end_order_test $db $e commit abort $endorder
+ end_order_test $db $e abort commit $endorder
+ end_order_test $db $e commit commit $endorder
+ end_order_test $db $e abort abort $endorder
+ }
+
+ # Clean up
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$e close] 0
+}
+
+proc end_order_test { db e txn1end txn2end endorder } {
+ # Start one transaction
+ set txn1 [$e txn -nowait]
+ error_check_good txn_begin [is_valid_txn $txn1 $e] TRUE
+ set ret [catch {$db put -txn $txn1 -append record1} recno1]
+ error_check_good dbput_txn1 $ret 0
+
+ # Check number of locks
+ how_many_locks 2 $e
+
+ # Start a second transaction while first is still running
+ set txn2 [$e txn -nowait]
+ error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE
+ set ret [catch {$db put -txn $txn2 -append record2} recno2]
+ error_check_good dbput_txn2 $ret 0
+ how_many_locks 3 $e
+
+ # Now commit or abort one txn and make sure the other is okay
+ if {$endorder == "forward"} {
+ # End transaction 1 first
+ puts "\tLock005.b.1: $txn1end txn1 then $txn2end txn2"
+ error_check_good txn_$txn1end [$txn1 $txn1end] 0
+ how_many_locks 2 $e
+
+ # txn1 is now ended, but txn2 is still running
+ set ret1 [catch {$db get -txn $txn2 $recno1} res1]
+ set ret2 [catch {$db get -txn $txn2 $recno2} res2]
+ if { $txn1end == "commit" } {
+ error_check_good txn2_sees_txn1 $ret1 0
+ error_check_good txn2_sees_txn2 $ret2 0
+ } else {
+ # transaction 1 was aborted
+ error_check_good txn2_cantsee_txn1 [llength $res1] 0
+ }
+
+ # End transaction 2 second
+ error_check_good txn_$txn2end [$txn2 $txn2end] 0
+ how_many_locks 1 $e
+
+ # txn1 and txn2 should both now be invalid
+ # The get no longer needs to be transactional
+ set ret3 [catch {$db get $recno1} res3]
+ set ret4 [catch {$db get $recno2} res4]
+
+ if { $txn2end == "commit" } {
+ error_check_good txn2_sees_txn1 $ret3 0
+ error_check_good txn2_sees_txn2 $ret4 0
+ error_check_good txn2_has_record2 \
+ [is_substr $res4 "record2"] 1
+ } else {
+ # transaction 2 was aborted
+ error_check_good txn2_cantsee_txn1 $ret3 0
+ error_check_good txn2_aborted [llength $res4] 0
+ }
+
+ } elseif { $endorder == "reverse" } {
+ # End transaction 2 first
+ puts "\tLock005.b.2: $txn2end txn2 then $txn1end txn1"
+ error_check_good txn_$txn2end [$txn2 $txn2end] 0
+ how_many_locks 2 $e
+
+ # txn2 is ended, but txn1 is still running
+ set ret1 [catch {$db get -txn $txn1 $recno1} res1]
+ set ret2 [catch {$db get -txn $txn1 $recno2} res2]
+ if { $txn2end == "commit" } {
+ error_check_good txn1_sees_txn1 $ret1 0
+ error_check_good txn1_sees_txn2 $ret2 0
+ } else {
+ # transaction 2 was aborted
+ error_check_good txn1_cantsee_txn2 [llength $res2] 0
+ }
+
+ # End transaction 1 second
+ error_check_good txn_$txn1end [$txn1 $txn1end] 0
+ how_many_locks 1 $e
+
+ # txn1 and txn2 should both now be invalid
+ # The get no longer needs to be transactional
+ set ret3 [catch {$db get $recno1} res3]
+ set ret4 [catch {$db get $recno2} res4]
+
+ if { $txn1end == "commit" } {
+ error_check_good txn1_sees_txn1 $ret3 0
+ error_check_good txn1_sees_txn2 $ret4 0
+ error_check_good txn1_has_record1 \
+ [is_substr $res3 "record1"] 1
+ } else {
+ # transaction 1 was aborted
+ error_check_good txn1_cantsee_txn2 $ret4 0
+ error_check_good txn1_aborted [llength $res3] 0
+ }
+ }
+}
+
+proc how_many_locks { expected env } {
+ set stat [$env lock_stat]
+ set str "Current number of locks"
+ set checked 0
+ foreach statpair $stat {
+ if { $checked == 1 } {
+ break
+ }
+ if { [is_substr [lindex $statpair 0] $str] != 0} {
+ set checked 1
+ set nlocks [lindex $statpair 1]
+ error_check_good expected_nlocks $nlocks $expected
+ }
+ }
+ error_check_good checked $checked 1
+}
diff --git a/bdb/test/lockscript.tcl b/bdb/test/lockscript.tcl
index bd07d80b54b..812339a4a70 100644
--- a/bdb/test/lockscript.tcl
+++ b/bdb/test/lockscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: lockscript.tcl,v 11.11 2000/03/24 19:53:39 krinsky Exp $
+# $Id: lockscript.tcl,v 11.17 2002/02/20 17:08:23 sandstro Exp $
#
# Random lock tester.
# Usage: lockscript dir numiters numobjs sleepint degree readratio
@@ -32,25 +32,28 @@ set numobjs [ lindex $argv 2 ]
set sleepint [ lindex $argv 3 ]
set degree [ lindex $argv 4 ]
set readratio [ lindex $argv 5 ]
-set locker [pid]
# Initialize random number generator
global rand_init
berkdb srand $rand_init
+
+catch { berkdb_env -create -lock -home $dir } e
+error_check_good env_open [is_substr $e env] 1
+catch { $e lock_id } locker
+error_check_good locker [is_valid_locker $locker] TRUE
+
puts -nonewline "Beginning execution for $locker: $numiters $numobjs "
puts "$sleepint $degree $readratio"
flush stdout
-set e [berkdb env -create -lock -home $dir]
-error_check_good env_open [is_substr $e env] 1
-
for { set iter 0 } { $iter < $numiters } { incr iter } {
set nlocks [berkdb random_int 1 $degree]
# We will always lock objects in ascending order to avoid
# deadlocks.
set lastobj 1
set locklist {}
+ set objlist {}
for { set lnum 0 } { $lnum < $nlocks } { incr lnum } {
# Pick lock parameters
set obj [berkdb random_int $lastobj $numobjs]
@@ -61,20 +64,46 @@ for { set iter 0 } { $iter < $numiters } { incr iter } {
} else {
set rw write
}
- puts "[timestamp] $locker $lnum: $rw $obj"
+ puts "[timestamp -c] $locker $lnum: $rw $obj"
# Do get; add to list
- set lockp [$e lock_get $rw $locker $obj]
+ catch {$e lock_get $rw $locker $obj} lockp
+ error_check_good lock_get [is_valid_lock $lockp $e] TRUE
+
+ # Create a file to flag that we've a lock of the given
+ # type, after making sure only other read locks exist
+ # (if we're read locking) or no other locks exist (if
+ # we're writing).
+ lock003_vrfy $rw $obj
+ lock003_create $rw $obj
+ lappend objlist [list $obj $rw]
+
lappend locklist $lockp
if {$lastobj > $numobjs} {
break
}
}
# Pick sleep interval
- tclsleep [berkdb random_int 1 $sleepint]
+ puts "[timestamp -c] $locker sleeping"
+ # We used to sleep 1 to $sleepint seconds. This makes the test
+ # run for hours. Instead, make it sleep for 10 to $sleepint * 100
+ # milliseconds, for a maximum sleep time of 0.5 s.
+ after [berkdb random_int 10 [expr $sleepint * 100]]
+ puts "[timestamp -c] $locker awake"
# Now release locks
- puts "[timestamp] $locker released locks"
+ puts "[timestamp -c] $locker released locks"
+
+ # Delete our locking flag files, then reverify. (Note that the
+ # locking flag verification function assumes that our own lock
+ # is not currently flagged.)
+ foreach pair $objlist {
+ set obj [lindex $pair 0]
+ set rw [lindex $pair 1]
+ lock003_destroy $obj
+ lock003_vrfy $rw $obj
+ }
+
release_list $locklist
flush stdout
}
@@ -82,7 +111,7 @@ for { set iter 0 } { $iter < $numiters } { incr iter } {
set ret [$e close]
error_check_good env_close $ret 0
-puts "[timestamp] $locker Complete"
+puts "[timestamp -c] $locker Complete"
flush stdout
exit
diff --git a/bdb/test/log.tcl b/bdb/test/log.tcl
deleted file mode 100644
index c3802d0f971..00000000000
--- a/bdb/test/log.tcl
+++ /dev/null
@@ -1,337 +0,0 @@
-# See the file LICENSE for redistribution information.
-#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
-# Sleepycat Software. All rights reserved.
-#
-# $Id: log.tcl,v 11.17 2000/11/30 20:09:19 dda Exp $
-#
-# Options are:
-# -dir <directory in which to store memp>
-# -maxfilesize <maxsize of log file>
-# -iterations <iterations>
-# -stat
-proc log_usage {} {
- puts "log -dir <directory> -iterations <number of ops> \
- -maxfilesize <max size of log files> -stat"
-}
-proc logtest { args } {
- source ./include.tcl
- global rand_init
-
- # Set defaults
- set iterations 1000
- set maxfile [expr 1024 * 128]
- set dostat 0
- for { set i 0 } { $i < [llength $args] } {incr i} {
- switch -regexp -- [lindex $args $i] {
- -d.* { incr i; set testdir [lindex $args $i] }
- -i.* { incr i; set iterations [lindex $args $i] }
- -m.* { incr i; set maxfile [lindex $args $i] }
- -s.* { set dostat 1 }
- default {
- puts -nonewline "FAIL:[timestamp] Usage: "
- log_usage
- return
- }
- }
- }
- set multi_log [expr 3 * $iterations]
-
- # Clean out old log if it existed
- puts "Unlinking log: error message OK"
- env_cleanup $testdir
-
- # Now run the various functionality tests
- berkdb srand $rand_init
-
- log001 $testdir $maxfile $iterations
- log001 $testdir $maxfile $multi_log
- log002 $testdir $maxfile
- log003 $testdir $maxfile
- log004 $testdir
-}
-
-proc log001 { dir max nrecs } {
- source ./include.tcl
-
- puts "Log001: Basic put/get test"
-
- env_cleanup $dir
-
- set env [berkdb env -log -create -home $dir \
- -mode 0644 -log_max $max]
- error_check_bad log_env:$dir $env NULL
- error_check_good log:$dir [is_substr $env "env"] 1
-
- # We will write records to the log and make sure we can
- # read them back correctly. We'll use a standard pattern
- # repeated some number of times for each record.
-
- set lsn_list {}
- set rec_list {}
- puts "Log001.a: Writing $nrecs log records"
- for { set i 0 } { $i < $nrecs } { incr i } {
- set rec ""
- for { set j 0 } { $j < [expr $i % 10 + 1] } {incr j} {
- set rec $rec$i:logrec:$i
- }
- set lsn [$env log_put $rec]
- error_check_bad log_put [is_substr $lsn log_cmd] 1
- lappend lsn_list $lsn
- lappend rec_list $rec
- }
- puts "Log001.b: Retrieving log records sequentially (forward)"
- set i 0
- for { set grec [$env log_get -first] } { [llength $grec] != 0 } {
- set grec [$env log_get -next]} {
- error_check_good log_get:seq [lindex $grec 1] \
- [lindex $rec_list $i]
- incr i
- }
-
- puts "Log001.c: Retrieving log records sequentially (backward)"
- set i [llength $rec_list]
- for { set grec [$env log_get -last] } { [llength $grec] != 0 } {
- set grec [$env log_get -prev] } {
- incr i -1
- error_check_good \
- log_get:seq [lindex $grec 1] [lindex $rec_list $i]
- }
-
- puts "Log001.d: Retrieving log records sequentially by LSN"
- set i 0
- foreach lsn $lsn_list {
- set grec [$env log_get -set $lsn]
- error_check_good \
- log_get:seq [lindex $grec 1] [lindex $rec_list $i]
- incr i
- }
-
- puts "Log001.e: Retrieving log records randomly by LSN"
- set m [expr [llength $lsn_list] - 1]
- for { set i 0 } { $i < $nrecs } { incr i } {
- set recno [berkdb random_int 0 $m ]
- set lsn [lindex $lsn_list $recno]
- set grec [$env log_get -set $lsn]
- error_check_good \
- log_get:seq [lindex $grec 1] [lindex $rec_list $recno]
- }
-
- # Close and unlink the file
- error_check_good env:close:$env [$env close] 0
- error_check_good envremove:$dir [berkdb envremove -home $dir] 0
-
- puts "Log001 Complete"
-}
-
-proc log002 { dir {max 32768} } {
- source ./include.tcl
-
- puts "Log002: Multiple log test w/trunc, file, compare functionality"
-
- env_cleanup $dir
-
- set env [berkdb env -create -home $dir -mode 0644 -log -log_max $max]
- error_check_bad log_env:$dir $env NULL
- error_check_good log:$dir [is_substr $env "env"] 1
-
- # We'll record every hundred'th record for later use
- set info_list {}
-
- set i 0
- puts "Log002.a: Writing log records"
-
- for {set s 0} { $s < [expr 3 * $max] } { incr s $len } {
- set rec [random_data 120 0 0]
- set len [string length $rec]
- set lsn [$env log_put $rec]
-
- if { [expr $i % 100 ] == 0 } {
- lappend info_list [list $lsn $rec]
- }
- incr i
- }
-
- puts "Log002.b: Checking log_compare"
- set last {0 0}
- foreach p $info_list {
- set l [lindex $p 0]
- if { [llength $last] != 0 } {
- error_check_good \
- log_compare [$env log_compare $l $last] 1
- error_check_good \
- log_compare [$env log_compare $last $l] -1
- error_check_good \
- log_compare [$env log_compare $l $l] 0
- }
- set last $l
- }
-
- puts "Log002.c: Checking log_file"
- set flist [glob $dir/log*]
- foreach p $info_list {
-
- set lsn [lindex $p 0]
- set f [$env log_file $lsn]
-
- # Change all backslash separators on Windows to forward slash
- # separators, which is what the rest of the test suite expects.
- regsub -all {\\} $f {/} f
-
- error_check_bad log_file:$f [lsearch $flist $f] -1
- }
-
- puts "Log002.d: Verifying records"
- for {set i [expr [llength $info_list] - 1] } { $i >= 0 } { incr i -1} {
- set p [lindex $info_list $i]
- set grec [$env log_get -set [lindex $p 0]]
- error_check_good log_get:$env [lindex $grec 1] [lindex $p 1]
- }
-
- # Close and unlink the file
- error_check_good env:close:$env [$env close] 0
- error_check_good envremove:$dir [berkdb envremove -home $dir] 0
-
- puts "Log002 Complete"
-}
-
-proc log003 { dir {max 32768} } {
- source ./include.tcl
-
- puts "Log003: Verify log_flush behavior"
-
- env_cleanup $dir
- set short_rec "abcdefghijklmnopqrstuvwxyz"
- set long_rec [repeat $short_rec 200]
- set very_long_rec [repeat $long_rec 4]
-
- foreach rec "$short_rec $long_rec $very_long_rec" {
- puts "Log003.a: Verify flush on [string length $rec] byte rec"
-
- set env [berkdb env -log -home $dir \
- -create -mode 0644 -log_max $max]
- error_check_bad log_env:$dir $env NULL
- error_check_good log:$dir [is_substr $env "env"] 1
-
- set lsn [$env log_put $rec]
- error_check_bad log_put [lindex $lsn 0] "ERROR:"
- set ret [$env log_flush $lsn]
- error_check_good log_flush $ret 0
-
- # Now, we want to crash the region and recheck. Closing the
- # log does not flush any records, so we'll use a close to
- # do the "crash"
- set ret [$env close]
- error_check_good log_env:close $ret 0
-
- # Now, remove the log region
- #set ret [berkdb envremove -home $dir]
- #error_check_good env:remove $ret 0
-
- # Re-open the log and try to read the record.
- set env [berkdb env -create -home $dir \
- -log -mode 0644 -log_max $max]
- error_check_bad log_env:$dir $env NULL
- error_check_good log:$dir [is_substr $env "env"] 1
-
- set gotrec [$env log_get -first]
- error_check_good lp_get [lindex $gotrec 1] $rec
-
- # Close and unlink the file
- error_check_good env:close:$env [$env close] 0
- error_check_good envremove:$dir [berkdb envremove -home $dir] 0
- log_cleanup $dir
- }
-
- foreach rec "$short_rec $long_rec $very_long_rec" {
- puts "Log003.b: \
- Verify flush on non-last record [string length $rec]"
- set env [berkdb env \
- -create -log -home $dir -mode 0644 -log_max $max]
- error_check_bad log_env:$dir $env NULL
- error_check_good log:$dir [is_substr $env "env"] 1
-
- # Put 10 random records
- for { set i 0 } { $i < 10 } { incr i} {
- set r [random_data 450 0 0]
- set lsn [$env log_put $r]
- error_check_bad log_put [lindex $lsn 0] "ERROR:"
- }
-
- # Put the record we are interested in
- set save_lsn [$env log_put $rec]
- error_check_bad log_put [lindex $save_lsn 0] "ERROR:"
-
- # Put 10 more random records
- for { set i 0 } { $i < 10 } { incr i} {
- set r [random_data 450 0 0]
- set lsn [$env log_put $r]
- error_check_bad log_put [lindex $lsn 0] "ERROR:"
- }
-
- # Now check the flush
- set ret [$env log_flush $save_lsn]
- error_check_good log_flush $ret 0
-
- # Now, we want to crash the region and recheck. Closing the
- # log does not flush any records, so we'll use a close to
- # do the "crash"
-
- #
- # Now, close and remove the log region
- error_check_good env:close:$env [$env close] 0
- set ret [berkdb envremove -home $dir]
- error_check_good env:remove $ret 0
-
- # Re-open the log and try to read the record.
- set env [berkdb env \
- -home $dir -create -log -mode 0644 -log_max $max]
- error_check_bad log_env:$dir $env NULL
- error_check_good log:$dir [is_substr $env "env"] 1
-
- set gotrec [$env log_get -set $save_lsn]
- error_check_good lp_get [lindex $gotrec 1] $rec
-
- # Close and unlink the file
- error_check_good env:close:$env [$env close] 0
- error_check_good envremove:$dir [berkdb envremove -home $dir] 0
- log_cleanup $dir
- }
-
- puts "Log003 Complete"
-}
-
-# Make sure that if we do PREVs on a log, but the beginning of the
-# log has been truncated, we do the right thing.
-proc log004 { dir } {
- source ./include.tcl
-
- puts "Log004: Prev on log when beginning of log has been truncated."
- # Use archive test to populate log
- env_cleanup $dir
- puts "Log004.a: Call archive to populate log."
- archive
-
- # Delete all log files under 100
- puts "Log004.b: Delete all log files under 100."
- set ret [catch { glob $dir/log.00000000* } result]
- if { $ret == 0 } {
- eval fileremove -f $result
- }
-
- # Now open the log and get the first record and try a prev
- puts "Log004.c: Open truncated log, attempt to access missing portion."
- set myenv [berkdb env -create -log -home $dir]
- error_check_good log_open [is_substr $myenv "env"] 1
-
- set ret [$myenv log_get -first]
- error_check_bad log_get [llength $ret] 0
-
- # This should give DB_NOTFOUND which is a ret of length 0
- catch {$myenv log_get -prev} ret
- error_check_good log_get_prev [string length $ret] 0
-
- puts "Log004.d: Close log and environment."
- error_check_good log_close [$myenv close] 0
- puts "Log004 complete."
-}
diff --git a/bdb/test/log001.tcl b/bdb/test/log001.tcl
new file mode 100644
index 00000000000..87df780cb5a
--- /dev/null
+++ b/bdb/test/log001.tcl
@@ -0,0 +1,120 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: log001.tcl,v 11.29 2002/04/30 20:27:56 sue Exp $
+#
+
+# TEST log001
+# TEST Read/write log records.
+proc log001 { } {
+ global passwd
+ global rand_init
+
+ berkdb srand $rand_init
+ set iter 1000
+ set max [expr 1024 * 128]
+ log001_body $max $iter 1
+ log001_body $max $iter 0
+ log001_body $max $iter 1 "-encryptaes $passwd"
+ log001_body $max $iter 0 "-encryptaes $passwd"
+ log001_body $max [expr $iter * 15] 1
+ log001_body $max [expr $iter * 15] 0
+ log001_body $max [expr $iter * 15] 1 "-encryptaes $passwd"
+ log001_body $max [expr $iter * 15] 0 "-encryptaes $passwd"
+}
+
+proc log001_body { max nrecs fixedlength {encargs ""} } {
+ source ./include.tcl
+
+ puts -nonewline "Log001: Basic put/get log records "
+ if { $fixedlength == 1 } {
+ puts "(fixed-length $encargs)"
+ } else {
+ puts "(variable-length $encargs)"
+ }
+
+ env_cleanup $testdir
+
+ set env [eval {berkdb_env -log -create -home $testdir -mode 0644} \
+ $encargs -log_max $max]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ # We will write records to the log and make sure we can
+ # read them back correctly. We'll use a standard pattern
+ # repeated some number of times for each record.
+ set lsn_list {}
+ set rec_list {}
+ puts "\tLog001.a: Writing $nrecs log records"
+ for { set i 0 } { $i < $nrecs } { incr i } {
+ set rec ""
+ for { set j 0 } { $j < [expr $i % 10 + 1] } {incr j} {
+ set rec $rec$i:logrec:$i
+ }
+ if { $fixedlength != 1 } {
+ set rec $rec:[random_data 237 0 0]
+ }
+ set lsn [$env log_put $rec]
+ error_check_bad log_put [is_substr $lsn log_cmd] 1
+ lappend lsn_list $lsn
+ lappend rec_list $rec
+ }
+
+ # Open a log cursor.
+ set logc [$env log_cursor]
+ error_check_good logc [is_valid_logc $logc $env] TRUE
+
+ puts "\tLog001.b: Retrieving log records sequentially (forward)"
+ set i 0
+ for { set grec [$logc get -first] } { [llength $grec] != 0 } {
+ set grec [$logc get -next]} {
+ error_check_good log_get:seq [lindex $grec 1] \
+ [lindex $rec_list $i]
+ incr i
+ }
+
+ puts "\tLog001.c: Retrieving log records sequentially (backward)"
+ set i [llength $rec_list]
+ for { set grec [$logc get -last] } { [llength $grec] != 0 } {
+ set grec [$logc get -prev] } {
+ incr i -1
+ error_check_good \
+ log_get:seq [lindex $grec 1] [lindex $rec_list $i]
+ }
+
+ puts "\tLog001.d: Retrieving log records sequentially by LSN"
+ set i 0
+ foreach lsn $lsn_list {
+ set grec [$logc get -set $lsn]
+ error_check_good \
+ log_get:seq [lindex $grec 1] [lindex $rec_list $i]
+ incr i
+ }
+
+ puts "\tLog001.e: Retrieving log records randomly by LSN"
+ set m [expr [llength $lsn_list] - 1]
+ for { set i 0 } { $i < $nrecs } { incr i } {
+ set recno [berkdb random_int 0 $m ]
+ set lsn [lindex $lsn_list $recno]
+ set grec [$logc get -set $lsn]
+ error_check_good \
+ log_get:seq [lindex $grec 1] [lindex $rec_list $recno]
+ }
+
+ puts "\tLog001.f: Retrieving first/current, last/current log record"
+ set grec [$logc get -first]
+ error_check_good log_get:seq [lindex $grec 1] [lindex $rec_list 0]
+ set grec [$logc get -current]
+ error_check_good log_get:seq [lindex $grec 1] [lindex $rec_list 0]
+ set i [expr [llength $rec_list] - 1]
+ set grec [$logc get -last]
+ error_check_good log_get:seq [lindex $grec 1] [lindex $rec_list $i]
+ set grec [$logc get -current]
+ error_check_good log_get:seq [lindex $grec 1] [lindex $rec_list $i]
+
+ # Close and unlink the file
+ error_check_good log_cursor:close:$logc [$logc close] 0
+ error_check_good env:close [$env close] 0
+ error_check_good envremove [berkdb envremove -home $testdir] 0
+}
diff --git a/bdb/test/log002.tcl b/bdb/test/log002.tcl
new file mode 100644
index 00000000000..6e91f55398f
--- /dev/null
+++ b/bdb/test/log002.tcl
@@ -0,0 +1,85 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: log002.tcl,v 11.28 2002/04/29 20:07:54 sue Exp $
+#
+
+# TEST log002
+# TEST Tests multiple logs
+# TEST Log truncation
+# TEST LSN comparison and file functionality.
+proc log002 { } {
+ source ./include.tcl
+
+ puts "Log002: Multiple log test w/trunc, file, compare functionality"
+
+ env_cleanup $testdir
+
+ set max [expr 1024 * 128]
+ set env [berkdb_env -create -home $testdir -mode 0644 \
+ -log -log_max $max]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ # We'll record every hundred'th record for later use
+ set info_list {}
+
+ puts "\tLog002.a: Writing log records"
+ set i 0
+ for {set s 0} { $s < [expr 3 * $max] } { incr s $len } {
+ set rec [random_data 120 0 0]
+ set len [string length $rec]
+ set lsn [$env log_put $rec]
+
+ if { [expr $i % 100 ] == 0 } {
+ lappend info_list [list $lsn $rec]
+ }
+ incr i
+ }
+
+ puts "\tLog002.b: Checking log_compare"
+ set last {0 0}
+ foreach p $info_list {
+ set l [lindex $p 0]
+ if { [llength $last] != 0 } {
+ error_check_good \
+ log_compare [$env log_compare $l $last] 1
+ error_check_good \
+ log_compare [$env log_compare $last $l] -1
+ error_check_good \
+ log_compare [$env log_compare $l $l] 0
+ }
+ set last $l
+ }
+
+ puts "\tLog002.c: Checking log_file"
+ set flist [glob $testdir/log*]
+ foreach p $info_list {
+
+ set lsn [lindex $p 0]
+ set f [$env log_file $lsn]
+
+ # Change all backslash separators on Windows to forward slash
+ # separators, which is what the rest of the test suite expects.
+ regsub -all {\\} $f {/} f
+
+ error_check_bad log_file:$f [lsearch $flist $f] -1
+ }
+
+ puts "\tLog002.d: Verifying records"
+
+ set logc [$env log_cursor]
+ error_check_good log_cursor [is_valid_logc $logc $env] TRUE
+
+ for {set i [expr [llength $info_list] - 1] } { $i >= 0 } { incr i -1} {
+ set p [lindex $info_list $i]
+ set grec [$logc get -set [lindex $p 0]]
+ error_check_good log_get:$env [lindex $grec 1] [lindex $p 1]
+ }
+
+ # Close and unlink the file
+ error_check_good log_cursor:close:$logc [$logc close] 0
+ error_check_good env:close [$env close] 0
+ error_check_good envremove [berkdb envremove -home $testdir] 0
+}
diff --git a/bdb/test/log003.tcl b/bdb/test/log003.tcl
new file mode 100644
index 00000000000..11297b59d50
--- /dev/null
+++ b/bdb/test/log003.tcl
@@ -0,0 +1,118 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: log003.tcl,v 11.28 2002/04/29 20:07:54 sue Exp $
+#
+
+# TEST log003
+# TEST Verify that log_flush is flushing records correctly.
+proc log003 { } {
+ source ./include.tcl
+
+ puts "Log003: Verify log_flush behavior"
+
+ set max [expr 1024 * 128]
+ env_cleanup $testdir
+ set short_rec "abcdefghijklmnopqrstuvwxyz"
+ set long_rec [repeat $short_rec 200]
+ set very_long_rec [repeat $long_rec 4]
+
+ foreach rec "$short_rec $long_rec $very_long_rec" {
+ puts "\tLog003.a: Verify flush on [string length $rec] byte rec"
+
+ set env [berkdb_env -log -home $testdir \
+ -create -mode 0644 -log_max $max]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ set lsn [$env log_put $rec]
+ error_check_bad log_put [lindex $lsn 0] "ERROR:"
+ set ret [$env log_flush $lsn]
+ error_check_good log_flush $ret 0
+
+ # Now, we want to crash the region and recheck. Closing the
+ # log does not flush any records, so we'll use a close to
+ # do the "crash"
+ set ret [$env close]
+ error_check_good log_env:close $ret 0
+
+ # Now, remove the log region
+ #set ret [berkdb envremove -home $testdir]
+ #error_check_good env:remove $ret 0
+
+ # Re-open the log and try to read the record.
+ set env [berkdb_env -create -home $testdir \
+ -log -mode 0644 -log_max $max]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ set logc [$env log_cursor]
+ error_check_good log_cursor [is_valid_logc $logc $env] TRUE
+
+ set gotrec [$logc get -first]
+ error_check_good lp_get [lindex $gotrec 1] $rec
+
+ # Close and unlink the file
+ error_check_good log_cursor:close:$logc [$logc close] 0
+ error_check_good env:close:$env [$env close] 0
+ error_check_good envremove [berkdb envremove -home $testdir] 0
+ log_cleanup $testdir
+ }
+
+ foreach rec "$short_rec $long_rec $very_long_rec" {
+ puts "\tLog003.b: \
+ Verify flush on non-last record [string length $rec]"
+ set env [berkdb_env \
+ -create -log -home $testdir -mode 0644 -log_max $max]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ # Put 10 random records
+ for { set i 0 } { $i < 10 } { incr i} {
+ set r [random_data 450 0 0]
+ set lsn [$env log_put $r]
+ error_check_bad log_put [lindex $lsn 0] "ERROR:"
+ }
+
+ # Put the record we are interested in
+ set save_lsn [$env log_put $rec]
+ error_check_bad log_put [lindex $save_lsn 0] "ERROR:"
+
+ # Put 10 more random records
+ for { set i 0 } { $i < 10 } { incr i} {
+ set r [random_data 450 0 0]
+ set lsn [$env log_put $r]
+ error_check_bad log_put [lindex $lsn 0] "ERROR:"
+ }
+
+ # Now check the flush
+ set ret [$env log_flush $save_lsn]
+ error_check_good log_flush $ret 0
+
+ # Now, we want to crash the region and recheck. Closing the
+ # log does not flush any records, so we'll use a close to
+ # do the "crash"
+
+ #
+ # Now, close and remove the log region
+ error_check_good env:close:$env [$env close] 0
+ set ret [berkdb envremove -home $testdir]
+ error_check_good env:remove $ret 0
+
+ # Re-open the log and try to read the record.
+ set env [berkdb_env \
+ -home $testdir -create -log -mode 0644 -log_max $max]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ set logc [$env log_cursor]
+ error_check_good log_cursor [is_valid_logc $logc $env] TRUE
+
+ set gotrec [$logc get -set $save_lsn]
+ error_check_good lp_get [lindex $gotrec 1] $rec
+
+ # Close and unlink the file
+ error_check_good log_cursor:close:$logc [$logc close] 0
+ error_check_good env:close:$env [$env close] 0
+ error_check_good envremove [berkdb envremove -home $testdir] 0
+ log_cleanup $testdir
+ }
+}
diff --git a/bdb/test/log004.tcl b/bdb/test/log004.tcl
new file mode 100644
index 00000000000..66968a8c1b4
--- /dev/null
+++ b/bdb/test/log004.tcl
@@ -0,0 +1,46 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: log004.tcl,v 11.28 2002/04/29 20:07:54 sue Exp $
+#
+
+# TEST log004
+# TEST Make sure that if we do PREVs on a log, but the beginning of the
+# TEST log has been truncated, we do the right thing.
+proc log004 { } {
+ source ./include.tcl
+
+ puts "Log004: Prev on log when beginning of log has been truncated."
+ # Use archive test to populate log
+ env_cleanup $testdir
+ puts "\tLog004.a: Call archive to populate log."
+ archive
+
+ # Delete all log files under 100
+ puts "\tLog004.b: Delete all log files under 100."
+ set ret [catch { glob $testdir/log.00000000* } result]
+ if { $ret == 0 } {
+ eval fileremove -f $result
+ }
+
+ # Now open the log and get the first record and try a prev
+ puts "\tLog004.c: Open truncated log, attempt to access missing portion."
+ set env [berkdb_env -create -log -home $testdir]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ set logc [$env log_cursor]
+ error_check_good log_cursor [is_valid_logc $logc $env] TRUE
+
+ set ret [$logc get -first]
+ error_check_bad log_get [llength $ret] 0
+
+ # This should give DB_NOTFOUND which is a ret of length 0
+ catch {$logc get -prev} ret
+ error_check_good log_get_prev [string length $ret] 0
+
+ puts "\tLog004.d: Close log and environment."
+ error_check_good log_cursor_close [$logc close] 0
+ error_check_good log_close [$env close] 0
+}
diff --git a/bdb/test/log005.tcl b/bdb/test/log005.tcl
new file mode 100644
index 00000000000..ab2ad703c55
--- /dev/null
+++ b/bdb/test/log005.tcl
@@ -0,0 +1,89 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: log005.tcl,v 11.1 2002/05/30 22:16:49 bostic Exp $
+#
+# TEST log005
+# TEST Check that log file sizes can change on the fly.
+proc log005 { } {
+ source ./include.tcl
+
+ puts "Log005: Check that log file sizes can change."
+ env_cleanup $testdir
+
+ # Open the environment, set and check the log file size.
+ puts "\tLog005.a: open, set and check the log file size."
+ set env [berkdb_env \
+ -create -home $testdir -log_buffer 10000 -log_max 1000000 -txn]
+ error_check_good envopen [is_valid_env $env] TRUE
+ set db [berkdb_open \
+ -env $env -create -mode 0644 -btree -auto_commit a.db]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ # Get the current log file maximum.
+ set max [log005_stat $env "Current log file size"]
+ error_check_good max_set $max 1000000
+
+ # Reset the log file size using a second open, and make sure
+ # it changes.
+ puts "\tLog005.b: reset during open, check the log file size."
+ set envtmp [berkdb_env -home $testdir -log_max 900000 -txn]
+ error_check_good envtmp_open [is_valid_env $envtmp] TRUE
+ error_check_good envtmp_close [$envtmp close] 0
+
+ set tmp [log005_stat $env "Current log file size"]
+ error_check_good max_changed 900000 $tmp
+
+ puts "\tLog005.c: fill in the current log file size."
+ # Fill in the current log file.
+ set new_lsn 0
+ set data [repeat "a" 1024]
+ for { set i 1 } \
+ { [log005_stat $env "Current log file number"] != 2 } \
+ { incr i } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set ret [$db put -txn $t $i $data]
+ error_check_good put $ret 0
+ error_check_good txn [$t commit] 0
+
+ set last_lsn $new_lsn
+ set new_lsn [log005_stat $env "Current log file offset"]
+ }
+
+ # The last LSN in the first file should be more than our new
+ # file size.
+ error_check_good "lsn check < 900000" [expr 900000 < $last_lsn] 1
+
+ # Close down the environment.
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$env close] 0
+
+ puts "\tLog005.d: check the log file size is unchanged after recovery."
+ # Open again, running recovery. Verify the log file size is as we
+ # left it.
+ set env [berkdb_env -create -home $testdir -recover -txn]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ set tmp [log005_stat $env "Current log file size"]
+ error_check_good after_recovery 900000 $tmp
+
+ error_check_good env_close [$env close] 0
+}
+
+# log005_stat --
+# Return the current log statistics.
+proc log005_stat { env s } {
+ set stat [$env log_stat]
+ foreach statpair $stat {
+ set statmsg [lindex $statpair 0]
+ set statval [lindex $statpair 1]
+ if {[is_substr $statmsg $s] != 0} {
+ return $statval
+ }
+ }
+ puts "FAIL: log005: stat string $s not found"
+ return 0
+}
diff --git a/bdb/test/logtrack.tcl b/bdb/test/logtrack.tcl
index cea4912e627..ad6b480b4e3 100644
--- a/bdb/test/logtrack.tcl
+++ b/bdb/test/logtrack.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: logtrack.tcl,v 11.6 2000/10/27 15:30:39 krinsky Exp $
+# $Id: logtrack.tcl,v 11.11 2002/09/03 16:44:37 sue Exp $
#
# logtrack.tcl: A collection of routines, formerly implemented in Perl
# as log.pl, to track which log record types the test suite hits.
@@ -35,20 +35,26 @@ proc logtrack_init { } {
# records were seen.
proc logtrack_read { dirname } {
global ltsname tmpname util_path
+ global encrypt passwd
set seendb [berkdb_open $ltsname]
error_check_good seendb_open [is_valid_db $seendb] TRUE
file delete -force $tmpname
- set ret [catch {exec $util_path/db_printlog -N \
- -h "$dirname" > $tmpname} res]
+ set pargs " -N -h $dirname "
+ if { $encrypt > 0 } {
+ append pargs " -P $passwd "
+ }
+ set ret [catch {eval exec $util_path/db_printlog $pargs > $tmpname} res]
error_check_good printlog $ret 0
error_check_good tmpfile_exists [file exists $tmpname] 1
set f [open $tmpname r]
while { [gets $f record] >= 0 } {
- regexp {\[[^\]]*\]\[[^\]]*\]([^\:]*)\:} $record whl name
- error_check_good seendb_put [$seendb put $name ""] 0
+ set r [regexp {\[[^\]]*\]\[[^\]]*\]([^\:]*)\:} $record whl name]
+ if { $r == 1 } {
+ error_check_good seendb_put [$seendb put $name ""] 0
+ }
}
close $f
file delete -force $tmpname
@@ -73,7 +79,7 @@ proc logtrack_summary { } {
set pref ""
while { [gets $f line] >= 0 } {
# Get the keyword, the first thing on the line:
- # BEGIN/DEPRECATED/PREFIX
+ # BEGIN/DEPRECATED/IGNORED/PREFIX
set keyword [lindex $line 0]
if { [string compare $keyword PREFIX] == 0 } {
@@ -92,7 +98,8 @@ proc logtrack_summary { } {
error_check_good exist_put [$existdb put \
${pref}_[lindex $line 1] ""] 0
- } elseif { [string compare $keyword DEPRECATED] == 0 } {
+ } elseif { [string compare $keyword DEPRECATED] == 0 ||
+ [string compare $keyword IGNORED] == 0 } {
error_check_good deprec_put [$deprecdb put \
${pref}_[lindex $line 1] ""] 0
}
diff --git a/bdb/test/mdbscript.tcl b/bdb/test/mdbscript.tcl
index 368aad371b2..9f3c971ee3c 100644
--- a/bdb/test/mdbscript.tcl
+++ b/bdb/test/mdbscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: mdbscript.tcl,v 11.23 2000/10/09 02:26:11 krinsky Exp $
+# $Id: mdbscript.tcl,v 11.29 2002/03/22 21:43:06 krinsky Exp $
#
# Process script for the multi-process db tester.
@@ -78,12 +78,18 @@ puts "$procid process id"
puts "$procs processes"
set klock NOLOCK
+
+# Note: all I/O operations, and especially flush, are expensive
+# on Win2000 at least with Tcl version 8.3.2. So we'll avoid
+# flushes in the main part of the loop below.
flush stdout
-set dbenv [berkdb env -create -cdb -home $dir]
-#set dbenv [berkdb env -create -cdb -log -home $dir]
+set dbenv [berkdb_env -create -cdb -home $dir]
+#set dbenv [berkdb_env -create -cdb -log -home $dir]
error_check_good dbenv [is_valid_env $dbenv] TRUE
+set locker [ $dbenv lock_id ]
+
set db [berkdb_open -env $dbenv -create -mode 0644 $omethod $file]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -96,6 +102,7 @@ tclsleep 5
proc get_lock { k } {
global dbenv
global procid
+ global locker
global klock
global DB_LOCK_WRITE
global DB_LOCK_NOWAIT
@@ -103,7 +110,7 @@ proc get_lock { k } {
global exception_handled
# Make sure that the key isn't in the middle of
# a delete operation
- if {[catch {$dbenv lock_get -nowait write $procid $k} klock] != 0 } {
+ if {[catch {$dbenv lock_get -nowait write $locker $k} klock] != 0 } {
set exception_handled 1
error_check_good \
@@ -136,7 +143,7 @@ set dlen [string length $datastr]
for { set i 0 } { $i < $iter } { incr i } {
set op [berkdb random_int 0 5]
puts "iteration $i operation $op"
- flush stdout
+ set close_cursor 0
if {[catch {
switch $op {
0 {
@@ -337,7 +344,6 @@ for { set i 0 } { $i < $iter } { incr i } {
set fnl [string first "\n" $errorInfo]
set theError [string range $errorInfo 0 [expr $fnl - 1]]
- flush stdout
if { [string compare $klock NOLOCK] != 0 } {
catch {$klock put}
}
@@ -348,11 +354,11 @@ for { set i 0 } { $i < $iter } { incr i } {
if {[string first FAIL $theError] == 0 && \
$exception_handled != 1} {
+ flush stdout
error "FAIL:[timestamp] test042: key $k: $theError"
}
set exception_handled 0
} else {
- flush stdout
if { [string compare $klock NOLOCK] != 0 } {
error_check_good "$klock put" [$klock put] 0
set klock NOLOCK
@@ -360,14 +366,11 @@ for { set i 0 } { $i < $iter } { incr i } {
}
}
-if {[catch {$db close} ret] != 0 } {
- error_check_good close [is_substr $errorInfo "DB_INCOMPLETE"] 1
- puts "Warning: sync incomplete on close ([pid])"
-} else {
- error_check_good close $ret 0
-}
-$dbenv close
+error_check_good db_close_catch [catch {$db close} ret] 0
+error_check_good db_close $ret 0
+error_check_good dbenv_close [$dbenv close] 0
+flush stdout
exit
puts "[timestamp] [pid] Complete"
diff --git a/bdb/test/memp001.tcl b/bdb/test/memp001.tcl
new file mode 100644
index 00000000000..c4bbf99b9b2
--- /dev/null
+++ b/bdb/test/memp001.tcl
@@ -0,0 +1,199 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: memp001.tcl,v 11.50 2002/08/07 16:46:28 bostic Exp $
+#
+
+# TEST memp001
+# TEST Randomly updates pages.
+proc memp001 { } {
+
+ memp001_body 1 ""
+ memp001_body 3 ""
+ memp001_body 1 -private
+ memp001_body 3 -private
+ memp001_body 1 "-system_mem -shm_key 1"
+ memp001_body 3 "-system_mem -shm_key 1"
+
+}
+
+proc memp001_body { ncache flags } {
+ source ./include.tcl
+ global rand_init
+
+ set nfiles 5
+ set iter 500
+ set psize 512
+ set cachearg "-cachesize {0 400000 $ncache}"
+
+ puts \
+"Memp001: { $flags } random update $iter iterations on $nfiles files."
+ #
+ # Check if this platform supports this set of flags
+ #
+ if { [mem_chk $flags] == 1 } {
+ return
+ }
+
+ env_cleanup $testdir
+ puts "\tMemp001.a: Create env with $ncache caches"
+ set env [eval {berkdb_env -create -mode 0644} \
+ $cachearg {-home $testdir} $flags]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ #
+ # Do a simple mpool_stat call to verify the number of caches
+ # just to exercise the stat code.
+ set stat [$env mpool_stat]
+ set str "Number of caches"
+ set checked 0
+ foreach statpair $stat {
+ if { $checked == 1 } {
+ break
+ }
+ if { [is_substr [lindex $statpair 0] $str] != 0} {
+ set checked 1
+ error_check_good ncache [lindex $statpair 1] $ncache
+ }
+ }
+ error_check_good checked $checked 1
+
+ # Open N memp files
+ puts "\tMemp001.b: Create $nfiles mpool files"
+ for {set i 1} {$i <= $nfiles} {incr i} {
+ set fname "data_file.$i"
+ file_create $testdir/$fname 50 $psize
+
+ set mpools($i) \
+ [$env mpool -create -pagesize $psize -mode 0644 $fname]
+ error_check_good mp_open [is_substr $mpools($i) $env.mp] 1
+ }
+
+ # Now, loop, picking files at random
+ berkdb srand $rand_init
+ puts "\tMemp001.c: Random page replacement loop"
+ for {set i 0} {$i < $iter} {incr i} {
+ set mpool $mpools([berkdb random_int 1 $nfiles])
+ set p(1) [get_range $mpool 10]
+ set p(2) [get_range $mpool 10]
+ set p(3) [get_range $mpool 10]
+ set p(1) [replace $mpool $p(1)]
+ set p(3) [replace $mpool $p(3)]
+ set p(4) [get_range $mpool 20]
+ set p(4) [replace $mpool $p(4)]
+ set p(5) [get_range $mpool 10]
+ set p(6) [get_range $mpool 20]
+ set p(7) [get_range $mpool 10]
+ set p(8) [get_range $mpool 20]
+ set p(5) [replace $mpool $p(5)]
+ set p(6) [replace $mpool $p(6)]
+ set p(9) [get_range $mpool 40]
+ set p(9) [replace $mpool $p(9)]
+ set p(10) [get_range $mpool 40]
+ set p(7) [replace $mpool $p(7)]
+ set p(8) [replace $mpool $p(8)]
+ set p(9) [replace $mpool $p(9)]
+ set p(10) [replace $mpool $p(10)]
+ #
+ # We now need to put all the pages we have here or
+ # else they end up pinned.
+ #
+ for {set x 1} { $x <= 10} {incr x} {
+ error_check_good pgput [$p($x) put] 0
+ }
+ }
+
+ # Close N memp files, close the environment.
+ puts "\tMemp001.d: Close mpools"
+ for {set i 1} {$i <= $nfiles} {incr i} {
+ error_check_good memp_close:$mpools($i) [$mpools($i) close] 0
+ }
+ error_check_good envclose [$env close] 0
+
+ for {set i 1} {$i <= $nfiles} {incr i} {
+ fileremove -f $testdir/data_file.$i
+ }
+}
+
+proc file_create { fname nblocks blocksize } {
+ set fid [open $fname w]
+ for {set i 0} {$i < $nblocks} {incr i} {
+ seek $fid [expr $i * $blocksize] start
+ puts -nonewline $fid $i
+ }
+ seek $fid [expr $nblocks * $blocksize - 1]
+
+ # We don't end the file with a newline, because some platforms (like
+ # Windows) emit CR/NL. There does not appear to be a BINARY open flag
+ # that prevents this.
+ puts -nonewline $fid "Z"
+ close $fid
+
+ # Make sure it worked
+ if { [file size $fname] != $nblocks * $blocksize } {
+ error "FAIL: file_create could not create correct file size"
+ }
+}
+
+proc get_range { mpool max } {
+ set pno [berkdb random_int 0 $max]
+ set p [$mpool get $pno]
+ error_check_good page [is_valid_page $p $mpool] TRUE
+ set got [$p pgnum]
+ if { $got != $pno } {
+ puts "Get_range: Page mismatch page |$pno| val |$got|"
+ }
+ set ret [$p init "Page is pinned by [pid]"]
+ error_check_good page_init $ret 0
+
+ return $p
+}
+
+proc replace { mpool p } {
+ set pgno [$p pgnum]
+
+ set ret [$p init "Page is unpinned by [pid]"]
+ error_check_good page_init $ret 0
+
+ set ret [$p put -dirty]
+ error_check_good page_put $ret 0
+
+ set p2 [$mpool get $pgno]
+ error_check_good page [is_valid_page $p2 $mpool] TRUE
+
+ return $p2
+}
+
+proc mem_chk { flags } {
+ source ./include.tcl
+ global errorCode
+
+ # Open the memp with region init specified
+ env_cleanup $testdir
+
+ set cachearg " -cachesize {0 400000 3}"
+ set ret [catch {eval {berkdb_env -create -mode 0644}\
+ $cachearg {-region_init -home $testdir} $flags} env]
+ if { $ret != 0 } {
+ # If the env open failed, it may be because we're on a platform
+ # such as HP-UX 10 that won't support mutexes in shmget memory.
+ # Or QNX, which doesn't support system memory at all.
+ # Verify that the return value was EINVAL or EOPNOTSUPP
+ # and bail gracefully.
+ error_check_good is_shm_test [is_substr $flags -system_mem] 1
+ error_check_good returned_error [expr \
+ [is_substr $errorCode EINVAL] || \
+ [is_substr $errorCode EOPNOTSUPP]] 1
+ puts "Warning:\
+ platform does not support mutexes in shmget memory."
+ puts "Skipping shared memory mpool test."
+ return 1
+ }
+ error_check_good env_open [is_valid_env $env] TRUE
+ error_check_good env_close [$env close] 0
+ env_cleanup $testdir
+
+ return 0
+}
diff --git a/bdb/test/memp002.tcl b/bdb/test/memp002.tcl
new file mode 100644
index 00000000000..d55f2987f06
--- /dev/null
+++ b/bdb/test/memp002.tcl
@@ -0,0 +1,62 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: memp002.tcl,v 11.47 2002/09/05 17:23:06 sandstro Exp $
+#
+
+# TEST memp002
+# TEST Tests multiple processes accessing and modifying the same files.
+proc memp002 { } {
+ #
+ # Multiple processes not supported by private memory so don't
+ # run memp002_body with -private.
+ #
+ memp002_body ""
+ memp002_body "-system_mem -shm_key 1"
+}
+
+proc memp002_body { flags } {
+ source ./include.tcl
+
+ puts "Memp002: {$flags} Multiprocess mpool tester"
+
+ set procs 4
+ set psizes "512 1024 2048 4096 8192"
+ set iterations 500
+ set npages 100
+
+ # Check if this combination of flags is supported by this arch.
+ if { [mem_chk $flags] == 1 } {
+ return
+ }
+
+ set iter [expr $iterations / $procs]
+
+ # Clean up old stuff and create new.
+ env_cleanup $testdir
+
+ for { set i 0 } { $i < [llength $psizes] } { incr i } {
+ fileremove -f $testdir/file$i
+ }
+ set e [eval {berkdb_env -create -lock -home $testdir} $flags]
+ error_check_good dbenv [is_valid_env $e] TRUE
+
+ set pidlist {}
+ for { set i 0 } { $i < $procs } {incr i} {
+
+ puts "$tclsh_path\
+ $test_path/mpoolscript.tcl $testdir $i $procs \
+ $iter $psizes $npages 3 $flags > \
+ $testdir/memp002.$i.out &"
+ set p [exec $tclsh_path $test_path/wrap.tcl \
+ mpoolscript.tcl $testdir/memp002.$i.out $testdir $i $procs \
+ $iter $psizes $npages 3 $flags &]
+ lappend pidlist $p
+ }
+ puts "Memp002: $procs independent processes now running"
+ watch_procs $pidlist
+
+ reset_env $e
+}
diff --git a/bdb/test/memp003.tcl b/bdb/test/memp003.tcl
new file mode 100644
index 00000000000..31eb55b757c
--- /dev/null
+++ b/bdb/test/memp003.tcl
@@ -0,0 +1,153 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: memp003.tcl,v 11.46 2002/04/30 17:26:06 sue Exp $
+#
+
+# TEST memp003
+# TEST Test reader-only/writer process combinations; we use the access methods
+# TEST for testing.
+proc memp003 { } {
+ #
+ # Multiple processes not supported by private memory so don't
+ # run memp003_body with -private.
+ #
+ memp003_body ""
+ memp003_body "-system_mem -shm_key 1"
+}
+
+proc memp003_body { flags } {
+ global alphabet
+ source ./include.tcl
+
+ puts "Memp003: {$flags} Reader/Writer tests"
+
+ if { [mem_chk $flags] == 1 } {
+ return
+ }
+
+ env_cleanup $testdir
+ set psize 1024
+ set nentries 500
+ set testfile mpool.db
+ set t1 $testdir/t1
+
+ # Create an environment that the two processes can share, with
+ # 20 pages per cache.
+ set c [list 0 [expr $psize * 20 * 3] 3]
+ set dbenv [eval {berkdb_env \
+ -create -lock -home $testdir -cachesize $c} $flags]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ # First open and create the file.
+ set db [berkdb_open -env $dbenv -create -truncate \
+ -mode 0644 -pagesize $psize -btree $testfile]
+ error_check_good dbopen/RW [is_valid_db $db] TRUE
+
+ set did [open $dict]
+ set txn ""
+ set count 0
+
+ puts "\tMemp003.a: create database"
+ set keys ""
+ # Here is the loop where we put and get each key/data pair
+ while { [gets $did str] != -1 && $count < $nentries } {
+ lappend keys $str
+
+ set ret [eval {$db put} $txn {$str $str}]
+ error_check_good put $ret 0
+
+ set ret [eval {$db get} $txn {$str}]
+ error_check_good get $ret [list [list $str $str]]
+
+ incr count
+ }
+ close $did
+ error_check_good close [$db close] 0
+
+ # Now open the file for read-only
+ set db [berkdb_open -env $dbenv -rdonly $testfile]
+ error_check_good dbopen/RO [is_substr $db db] 1
+
+ puts "\tMemp003.b: verify a few keys"
+ # Read and verify a couple of keys; saving them to check later
+ set testset ""
+ for { set i 0 } { $i < 10 } { incr i } {
+ set ndx [berkdb random_int 0 [expr $nentries - 1]]
+ set key [lindex $keys $ndx]
+ if { [lsearch $testset $key] != -1 } {
+ incr i -1
+ continue;
+ }
+
+ # The remote process stuff is unhappy with
+ # zero-length keys; make sure we don't pick one.
+ if { [llength $key] == 0 } {
+ incr i -1
+ continue
+ }
+
+ lappend testset $key
+
+ set ret [eval {$db get} $txn {$key}]
+ error_check_good get/RO $ret [list [list $key $key]]
+ }
+
+ puts "\tMemp003.c: retrieve and modify keys in remote process"
+ # Now open remote process where we will open the file RW
+ set f1 [open |$tclsh_path r+]
+ puts $f1 "source $test_path/test.tcl"
+ puts $f1 "flush stdout"
+ flush $f1
+
+ set c [concat "{" [list 0 [expr $psize * 20 * 3] 3] "}" ]
+ set remote_env [send_cmd $f1 \
+ "berkdb_env -create -lock -home $testdir -cachesize $c $flags"]
+ error_check_good remote_dbenv [is_valid_env $remote_env] TRUE
+
+ set remote_db [send_cmd $f1 "berkdb_open -env $remote_env $testfile"]
+ error_check_good remote_dbopen [is_valid_db $remote_db] TRUE
+
+ foreach k $testset {
+ # Get the key
+ set ret [send_cmd $f1 "$remote_db get $k"]
+ error_check_good remote_get $ret [list [list $k $k]]
+
+ # Now replace the key
+ set ret [send_cmd $f1 "$remote_db put $k $k$k"]
+ error_check_good remote_put $ret 0
+ }
+
+ puts "\tMemp003.d: verify changes in local process"
+ foreach k $testset {
+ set ret [eval {$db get} $txn {$key}]
+ error_check_good get_verify/RO $ret [list [list $key $key$key]]
+ }
+
+ puts "\tMemp003.e: Fill up the cache with dirty buffers"
+ foreach k $testset {
+ # Now rewrite the keys with BIG data
+ set data [replicate $alphabet 32]
+ set ret [send_cmd $f1 "$remote_db put $k $data"]
+ error_check_good remote_put $ret 0
+ }
+
+ puts "\tMemp003.f: Get more pages for the read-only file"
+ dump_file $db $txn $t1 nop
+
+ puts "\tMemp003.g: Sync from the read-only file"
+ error_check_good db_sync [$db sync] 0
+ error_check_good db_close [$db close] 0
+
+ set ret [send_cmd $f1 "$remote_db close"]
+ error_check_good remote_get $ret 0
+
+ # Close the environment both remotely and locally.
+ set ret [send_cmd $f1 "$remote_env close"]
+ error_check_good remote:env_close $ret 0
+ close $f1
+
+ reset_env $dbenv
+}
diff --git a/bdb/test/mpool.tcl b/bdb/test/mpool.tcl
deleted file mode 100644
index b2eb2252037..00000000000
--- a/bdb/test/mpool.tcl
+++ /dev/null
@@ -1,420 +0,0 @@
-# See the file LICENSE for redistribution information.
-#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
-# Sleepycat Software. All rights reserved.
-#
-# $Id: mpool.tcl,v 11.34 2001/01/18 04:58:07 krinsky Exp $
-#
-# Options are:
-# -cachesize {gbytes bytes ncache}
-# -nfiles <files>
-# -iterations <iterations>
-# -pagesize <page size in bytes>
-# -dir <directory in which to store memp>
-# -stat
-proc memp_usage {} {
- puts "memp -cachesize {gbytes bytes ncache}"
- puts "\t-nfiles <files>"
- puts "\t-iterations <iterations>"
- puts "\t-pagesize <page size in bytes>"
- puts "\t-dir <memp directory>"
- puts "\t-mem {private system}"
- return
-}
-
-proc mpool { args } {
- source ./include.tcl
- global errorCode
-
- puts "mpool {$args} running"
- # Set defaults
- set cachearg " -cachesize {0 200000 3}"
- set nfiles 5
- set iterations 500
- set pagesize "512 1024 2048 4096 8192"
- set npages 100
- set procs 4
- set seeds ""
- set shm_key 1
- set dostat 0
- set flags ""
- for { set i 0 } { $i < [llength $args] } {incr i} {
- switch -regexp -- [lindex $args $i] {
- -c.* {
- incr i
- set cachesize [lindex $args $i]
- set cachearg " -cachesize $cachesize"
- }
- -d.* { incr i; set testdir [lindex $args $i] }
- -i.* { incr i; set iterations [lindex $args $i] }
- -me.* {
- incr i
- if { [string \
- compare [lindex $args $i] private] == 0 } {
- set flags -private
- } elseif { [string \
- compare [lindex $args $i] system] == 0 } {
- #
- # We need to use a shm id. Use one
- # that is the same each time so that
- # we do not grow segments infinitely.
- set flags "-system_mem -shm_key $shm_key"
- } else {
- puts -nonewline \
- "FAIL:[timestamp] Usage: "
- memp_usage
- return
- }
- }
- -nf.* { incr i; set nfiles [lindex $args $i] }
- -np.* { incr i; set npages [lindex $args $i] }
- -pa.* { incr i; set pagesize [lindex $args $i] }
- -pr.* { incr i; set procs [lindex $args $i] }
- -se.* { incr i; set seeds [lindex $args $i] }
- -st.* { set dostat 1 }
- default {
- puts -nonewline "FAIL:[timestamp] Usage: "
- memp_usage
- return
- }
- }
- }
-
- # Clean out old directory
- env_cleanup $testdir
-
- # Open the memp with region init specified
- set ret [catch {eval {berkdb env -create -mode 0644}\
- $cachearg {-region_init -home $testdir} $flags} res]
- if { $ret == 0 } {
- set env $res
- } else {
- # If the env open failed, it may be because we're on a platform
- # such as HP-UX 10 that won't support mutexes in shmget memory.
- # Or QNX, which doesn't support system memory at all.
- # Verify that the return value was EINVAL or EOPNOTSUPP
- # and bail gracefully.
- error_check_good is_shm_test [is_substr $flags -system_mem] 1
- error_check_good returned_error [expr \
- [is_substr $errorCode EINVAL] || \
- [is_substr $errorCode EOPNOTSUPP]] 1
- puts "Warning:\
- platform does not support mutexes in shmget memory."
- puts "Skipping shared memory mpool test."
- return
- }
- error_check_good env_open [is_substr $env env] 1
-
- reset_env $env
- env_cleanup $testdir
-
- # Now open without region init
- set env [eval {berkdb env -create -mode 0644}\
- $cachearg {-home $testdir} $flags]
- error_check_good evn_open [is_substr $env env] 1
-
- memp001 $env \
- $testdir $nfiles $iterations [lindex $pagesize 0] $dostat $flags
- reset_env $env
- set ret [berkdb envremove -home $testdir]
- error_check_good env_remove $ret 0
- env_cleanup $testdir
-
- memp002 $testdir \
- $procs $pagesize $iterations $npages $seeds $dostat $flags
- set ret [berkdb envremove -home $testdir]
- error_check_good env_remove $ret 0
- env_cleanup $testdir
-
- memp003 $testdir $iterations $flags
- set ret [berkdb envremove -home $testdir]
- error_check_good env_remove $ret 0
-
- env_cleanup $testdir
-}
-
-proc memp001 {env dir n iter psize dostat flags} {
- source ./include.tcl
- global rand_init
-
- puts "Memp001: {$flags} random update $iter iterations on $n files."
-
- # Open N memp files
- for {set i 1} {$i <= $n} {incr i} {
- set fname "data_file.$i"
- file_create $dir/$fname 50 $psize
-
- set mpools($i) \
- [$env mpool -create -pagesize $psize -mode 0644 $fname]
- error_check_good mp_open [is_substr $mpools($i) $env.mp] 1
- }
-
- # Now, loop, picking files at random
- berkdb srand $rand_init
- for {set i 0} {$i < $iter} {incr i} {
- set mpool $mpools([berkdb random_int 1 $n])
- set p1 [get_range $mpool 10]
- set p2 [get_range $mpool 10]
- set p3 [get_range $mpool 10]
- set p1 [replace $mpool $p1]
- set p3 [replace $mpool $p3]
- set p4 [get_range $mpool 20]
- set p4 [replace $mpool $p4]
- set p5 [get_range $mpool 10]
- set p6 [get_range $mpool 20]
- set p7 [get_range $mpool 10]
- set p8 [get_range $mpool 20]
- set p5 [replace $mpool $p5]
- set p6 [replace $mpool $p6]
- set p9 [get_range $mpool 40]
- set p9 [replace $mpool $p9]
- set p10 [get_range $mpool 40]
- set p7 [replace $mpool $p7]
- set p8 [replace $mpool $p8]
- set p9 [replace $mpool $p9]
- set p10 [replace $mpool $p10]
- }
-
- if { $dostat == 1 } {
- puts [$env mpool_stat]
- for {set i 1} {$i <= $n} {incr i} {
- error_check_good mp_sync [$mpools($i) fsync] 0
- }
- }
-
- # Close N memp files
- for {set i 1} {$i <= $n} {incr i} {
- error_check_good memp_close:$mpools($i) [$mpools($i) close] 0
- fileremove -f $dir/data_file.$i
- }
-}
-
-proc file_create { fname nblocks blocksize } {
- set fid [open $fname w]
- for {set i 0} {$i < $nblocks} {incr i} {
- seek $fid [expr $i * $blocksize] start
- puts -nonewline $fid $i
- }
- seek $fid [expr $nblocks * $blocksize - 1]
-
- # We don't end the file with a newline, because some platforms (like
- # Windows) emit CR/NL. There does not appear to be a BINARY open flag
- # that prevents this.
- puts -nonewline $fid "Z"
- close $fid
-
- # Make sure it worked
- if { [file size $fname] != $nblocks * $blocksize } {
- error "FAIL: file_create could not create correct file size"
- }
-}
-
-proc get_range { mpool max } {
- set pno [berkdb random_int 0 $max]
- set p [$mpool get $pno]
- error_check_good page [is_valid_page $p $mpool] TRUE
- set got [$p pgnum]
- if { $got != $pno } {
- puts "Get_range: Page mismatch page |$pno| val |$got|"
- }
- set ret [$p init "Page is pinned by [pid]"]
- error_check_good page_init $ret 0
-
- return $p
-}
-
-proc replace { mpool p } {
- set pgno [$p pgnum]
-
- set ret [$p init "Page is unpinned by [pid]"]
- error_check_good page_init $ret 0
-
- set ret [$p put -dirty]
- error_check_good page_put $ret 0
-
- set p2 [$mpool get $pgno]
- error_check_good page [is_valid_page $p2 $mpool] TRUE
-
- return $p2
-}
-
-proc memp002 { dir procs psizes iterations npages seeds dostat flags } {
- source ./include.tcl
-
- puts "Memp002: {$flags} Multiprocess mpool tester"
-
- if { [is_substr $flags -private] != 0 } {
- puts "Memp002 skipping\
- multiple processes not supported by private memory"
- return
- }
- set iter [expr $iterations / $procs]
-
- # Clean up old stuff and create new.
- env_cleanup $dir
-
- for { set i 0 } { $i < [llength $psizes] } { incr i } {
- fileremove -f $dir/file$i
- }
- set e [eval {berkdb env -create -lock -home $dir} $flags]
- error_check_good dbenv [is_valid_widget $e env] TRUE
-
- set pidlist {}
- for { set i 0 } { $i < $procs } {incr i} {
- if { [llength $seeds] == $procs } {
- set seed [lindex $seeds $i]
- } else {
- set seed -1
- }
-
- puts "$tclsh_path\
- $test_path/mpoolscript.tcl $dir $i $procs \
- $iter $psizes $npages 3 $flags > \
- $dir/memp002.$i.out &"
- set p [exec $tclsh_path $test_path/wrap.tcl \
- mpoolscript.tcl $dir/memp002.$i.out $dir $i $procs \
- $iter $psizes $npages 3 $flags &]
- lappend pidlist $p
- }
- puts "Memp002: $procs independent processes now running"
- watch_procs
-
- reset_env $e
-}
-
-# Test reader-only/writer process combinations; we use the access methods
-# for testing.
-proc memp003 { dir {nentries 10000} flags } {
- global alphabet
- source ./include.tcl
-
- puts "Memp003: {$flags} Reader/Writer tests"
-
- if { [is_substr $flags -private] != 0 } {
- puts "Memp003 skipping\
- multiple processes not supported by private memory"
- return
- }
-
- env_cleanup $dir
- set psize 1024
- set testfile mpool.db
- set t1 $dir/t1
-
- # Create an environment that the two processes can share
- set c [list 0 [expr $psize * 10] 3]
- set dbenv [eval {berkdb env \
- -create -lock -home $dir -cachesize $c} $flags]
- error_check_good dbenv [is_valid_env $dbenv] TRUE
-
- # First open and create the file.
-
- set db [berkdb_open -env $dbenv -create -truncate \
- -mode 0644 -pagesize $psize -btree $testfile]
- error_check_good dbopen/RW [is_valid_db $db] TRUE
-
- set did [open $dict]
- set txn ""
- set count 0
-
- puts "\tMemp003.a: create database"
- set keys ""
- # Here is the loop where we put and get each key/data pair
- while { [gets $did str] != -1 && $count < $nentries } {
- lappend keys $str
-
- set ret [eval {$db put} $txn {$str $str}]
- error_check_good put $ret 0
-
- set ret [eval {$db get} $txn {$str}]
- error_check_good get $ret [list [list $str $str]]
-
- incr count
- }
- close $did
- error_check_good close [$db close] 0
-
- # Now open the file for read-only
- set db [berkdb_open -env $dbenv -rdonly $testfile]
- error_check_good dbopen/RO [is_substr $db db] 1
-
- puts "\tMemp003.b: verify a few keys"
- # Read and verify a couple of keys; saving them to check later
- set testset ""
- for { set i 0 } { $i < 10 } { incr i } {
- set ndx [berkdb random_int 0 [expr $nentries - 1]]
- set key [lindex $keys $ndx]
- if { [lsearch $testset $key] != -1 } {
- incr i -1
- continue;
- }
-
- # The remote process stuff is unhappy with
- # zero-length keys; make sure we don't pick one.
- if { [llength $key] == 0 } {
- incr i -1
- continue
- }
-
- lappend testset $key
-
- set ret [eval {$db get} $txn {$key}]
- error_check_good get/RO $ret [list [list $key $key]]
- }
-
- puts "\tMemp003.c: retrieve and modify keys in remote process"
- # Now open remote process where we will open the file RW
- set f1 [open |$tclsh_path r+]
- puts $f1 "source $test_path/test.tcl"
- puts $f1 "flush stdout"
- flush $f1
-
- set c [concat "{" [list 0 [expr $psize * 10] 3] "}" ]
- set remote_env [send_cmd $f1 \
- "berkdb env -create -lock -home $dir -cachesize $c $flags"]
- error_check_good remote_dbenv [is_valid_env $remote_env] TRUE
-
- set remote_db [send_cmd $f1 "berkdb_open -env $remote_env $testfile"]
- error_check_good remote_dbopen [is_valid_db $remote_db] TRUE
-
- foreach k $testset {
- # Get the key
- set ret [send_cmd $f1 "$remote_db get $k"]
- error_check_good remote_get $ret [list [list $k $k]]
-
- # Now replace the key
- set ret [send_cmd $f1 "$remote_db put $k $k$k"]
- error_check_good remote_put $ret 0
- }
-
- puts "\tMemp003.d: verify changes in local process"
- foreach k $testset {
- set ret [eval {$db get} $txn {$key}]
- error_check_good get_verify/RO $ret [list [list $key $key$key]]
- }
-
- puts "\tMemp003.e: Fill up the cache with dirty buffers"
- foreach k $testset {
- # Now rewrite the keys with BIG data
- set data [replicate $alphabet 32]
- set ret [send_cmd $f1 "$remote_db put $k $data"]
- error_check_good remote_put $ret 0
- }
-
- puts "\tMemp003.f: Get more pages for the read-only file"
- dump_file $db $txn $t1 nop
-
- puts "\tMemp003.g: Sync from the read-only file"
- error_check_good db_sync [$db sync] 0
- error_check_good db_close [$db close] 0
-
- set ret [send_cmd $f1 "$remote_db close"]
- error_check_good remote_get $ret 0
-
- # Close the environment both remotely and locally.
- set ret [send_cmd $f1 "$remote_env close"]
- error_check_good remote:env_close $ret 0
- close $f1
-
- reset_env $dbenv
-}
diff --git a/bdb/test/mpoolscript.tcl b/bdb/test/mpoolscript.tcl
index 8695254c257..c13f70eb945 100644
--- a/bdb/test/mpoolscript.tcl
+++ b/bdb/test/mpoolscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: mpoolscript.tcl,v 11.12 2000/05/05 15:23:47 sue Exp $
+# $Id: mpoolscript.tcl,v 11.16 2002/04/29 14:47:16 sandstro Exp $
#
# Random multiple process mpool tester.
# Usage: mpoolscript dir id numiters numfiles numpages sleepint
@@ -61,7 +61,7 @@ foreach i $pgsizes {
}
set cache [list 0 [expr $maxprocs * ([lindex $pgsizes 0] + $max)] 1]
-set env_cmd {berkdb env -lock -cachesize $cache -home $dir}
+set env_cmd {berkdb_env -lock -cachesize $cache -home $dir}
set e [eval $env_cmd $flags]
error_check_good env_open [is_valid_env $e] TRUE
@@ -78,7 +78,8 @@ foreach psize $pgsizes {
puts "Establishing long-term pin on file 0 page $id for process $id"
# Set up the long-pin page
-set lock [$e lock_get write $id 0:$id]
+set locker [$e lock_id]
+set lock [$e lock_get write $locker 0:$id]
error_check_good lock_get [is_valid_lock $lock $e] TRUE
set mp [lindex $mpools 0]
@@ -109,7 +110,7 @@ for { set iter 0 } { $iter < $numiters } { incr iter } {
set mpf [lindex $mpools $fnum]
for { set p 0 } { $p < $numpages } { incr p } {
- set lock [$e lock_get write $id $fnum:$p]
+ set lock [$e lock_get write $locker $fnum:$p]
error_check_good lock_get:$fnum:$p \
[is_valid_lock $lock $e] TRUE
diff --git a/bdb/test/mutex.tcl b/bdb/test/mutex.tcl
deleted file mode 100644
index 5300fb0c4a3..00000000000
--- a/bdb/test/mutex.tcl
+++ /dev/null
@@ -1,225 +0,0 @@
-# See the file LICENSE for redistribution information.
-#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
-# Sleepycat Software. All rights reserved.
-#
-# $Id: mutex.tcl,v 11.18 2000/09/01 19:24:59 krinsky Exp $
-#
-# Exercise mutex functionality.
-# Options are:
-# -dir <directory in which to store mpool>
-# -iter <iterations>
-# -mdegree <number of mutexes per iteration>
-# -nmutex <number of mutexes>
-# -procs <number of processes to run>
-# -wait <wait interval after getting locks>
-proc mutex_usage {} {
- puts stderr "mutex\n\t-dir <dir>\n\t-iter <iterations>"
- puts stderr "\t-mdegree <locks per iteration>\n\t-nmutex <n>"
- puts stderr "\t-procs <nprocs>"
- puts stderr "\n\t-wait <max wait interval>"
- return
-}
-
-proc mutex { args } {
- source ./include.tcl
-
- set dir db
- set iter 500
- set mdegree 3
- set nmutex 20
- set procs 5
- set wait 2
-
- for { set i 0 } { $i < [llength $args] } {incr i} {
- switch -regexp -- [lindex $args $i] {
- -d.* { incr i; set testdir [lindex $args $i] }
- -i.* { incr i; set iter [lindex $args $i] }
- -m.* { incr i; set mdegree [lindex $args $i] }
- -n.* { incr i; set nmutex [lindex $args $i] }
- -p.* { incr i; set procs [lindex $args $i] }
- -w.* { incr i; set wait [lindex $args $i] }
- default {
- puts -nonewline "FAIL:[timestamp] Usage: "
- mutex_usage
- return
- }
- }
- }
-
- if { [file exists $testdir/$dir] != 1 } {
- file mkdir $testdir/$dir
- } elseif { [file isdirectory $testdir/$dir ] != 1 } {
- error "$testdir/$dir is not a directory"
- }
-
- # Basic sanity tests
- mutex001 $testdir $nmutex
-
- # Basic synchronization tests
- mutex002 $testdir $nmutex
-
- # Multiprocess tests
- mutex003 $testdir $iter $nmutex $procs $mdegree $wait
-}
-
-proc mutex001 { dir nlocks } {
- source ./include.tcl
-
- puts "Mutex001: Basic functionality"
- env_cleanup $dir
-
- # Test open w/out create; should fail
- error_check_bad \
- env_open [catch {berkdb env -lock -home $dir} env] 0
-
- # Now open for real
- set env [berkdb env -create -mode 0644 -lock -home $dir]
- error_check_good env_open [is_valid_env $env] TRUE
-
- set m [$env mutex 0644 $nlocks]
- error_check_good mutex_init [is_valid_mutex $m $env] TRUE
-
- # Get, set each mutex; sleep, then get Release
- for { set i 0 } { $i < $nlocks } { incr i } {
- set r [$m get $i ]
- error_check_good mutex_get $r 0
-
- set r [$m setval $i $i]
- error_check_good mutex_setval $r 0
- }
- tclsleep 5
- for { set i 0 } { $i < $nlocks } { incr i } {
- set r [$m getval $i]
- error_check_good mutex_getval $r $i
-
- set r [$m release $i ]
- error_check_good mutex_get $r 0
- }
-
- error_check_good mutex_close [$m close] 0
- error_check_good env_close [$env close] 0
- puts "Mutex001: completed successfully."
-}
-
-# Test basic synchronization
-proc mutex002 { dir nlocks } {
- source ./include.tcl
-
- puts "Mutex002: Basic synchronization"
- env_cleanup $dir
-
- # Fork off child before we open any files.
- set f1 [open |$tclsh_path r+]
- puts $f1 "source $test_path/test.tcl"
- flush $f1
-
- # Open the environment and the mutex locally
- set local_env [berkdb env -create -mode 0644 -lock -home $dir]
- error_check_good env_open [is_valid_env $local_env] TRUE
-
- set local_mutex [$local_env mutex 0644 $nlocks]
- error_check_good \
- mutex_init [is_valid_mutex $local_mutex $local_env] TRUE
-
- # Open the environment and the mutex remotely
- set remote_env [send_cmd $f1 "berkdb env -lock -home $dir"]
- error_check_good remote:env_open [is_valid_env $remote_env] TRUE
-
- set remote_mutex [send_cmd $f1 "$remote_env mutex 0644 $nlocks"]
- error_check_good \
- mutex_init [is_valid_mutex $remote_mutex $remote_env] TRUE
-
- # Do a get here, then set the value to be pid.
- # On the remote side fire off a get and getval.
- set r [$local_mutex get 1]
- error_check_good lock_get $r 0
-
- set r [$local_mutex setval 1 [pid]]
- error_check_good lock_get $r 0
-
- # Now have the remote side request the lock and check its
- # value. Then wait 5 seconds, release the mutex and see
- # what the remote side returned.
- send_timed_cmd $f1 1 "$remote_mutex get 1"
- send_timed_cmd $f1 1 "set ret \[$remote_mutex getval 1\]"
-
- # Now sleep before resetting and releasing lock
- tclsleep 5
- set newv [expr [pid] - 1]
- set r [$local_mutex setval 1 $newv]
- error_check_good mutex_setval $r 0
-
- set r [$local_mutex release 1]
- error_check_good mutex_release $r 0
-
- # Now get the result from the other script
- # Timestamp
- set result [rcv_result $f1]
- error_check_good lock_get:remote_time [expr $result > 4] 1
-
- # Timestamp
- set result [rcv_result $f1]
-
- # Mutex value
- set result [send_cmd $f1 "puts \$ret"]
- error_check_good lock_get:remote_getval $result $newv
-
- # Close down the remote
- set ret [send_cmd $f1 "$remote_mutex close" 5]
- # Not sure why we need this, but we do... an extra blank line
- # someone gets output somewhere
- gets $f1 ret
- error_check_good remote:mutex_close $ret 0
-
- set ret [send_cmd $f1 "$remote_env close"]
- error_check_good remote:env_close $ret 0
-
- catch { close $f1 } result
-
- set ret [$local_mutex close]
- error_check_good local:mutex_close $ret 0
-
- set ret [$local_env close]
- error_check_good local:env_close $ret 0
-
- puts "Mutex002: completed successfully."
-}
-
-# Generate a bunch of parallel
-# testers that try to randomly obtain locks.
-proc mutex003 { dir iter nmutex procs mdegree wait } {
- source ./include.tcl
-
- puts "Mutex003: Multi-process random mutex test ($procs processes)"
-
- env_cleanup $dir
-
- # Now open the region we'll use for multiprocess testing.
- set env [berkdb env -create -mode 0644 -lock -home $dir]
- error_check_good env_open [is_valid_env $env] TRUE
-
- set mutex [$env mutex 0644 $nmutex]
- error_check_good mutex_init [is_valid_mutex $mutex $env] TRUE
-
- error_check_good mutex_close [$mutex close] 0
-
- # Now spawn off processes
- set proclist {}
- for { set i 0 } {$i < $procs} {incr i} {
- puts "$tclsh_path\
- $test_path/mutexscript.tcl $dir\
- $iter $nmutex $wait $mdegree > $testdir/$i.mutexout &"
- set p [exec $tclsh_path $test_path/wrap.tcl \
- mutexscript.tcl $testdir/$i.mutexout $dir\
- $iter $nmutex $wait $mdegree &]
- lappend proclist $p
- }
- puts "Mutex003: $procs independent processes now running"
- watch_procs
- error_check_good env_close [$env close] 0
- # Remove output files
- for { set i 0 } {$i < $procs} {incr i} {
- fileremove -f $dir/$i.mutexout
- }
-}
diff --git a/bdb/test/mutex001.tcl b/bdb/test/mutex001.tcl
new file mode 100644
index 00000000000..93f858993a5
--- /dev/null
+++ b/bdb/test/mutex001.tcl
@@ -0,0 +1,51 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: mutex001.tcl,v 11.23 2002/04/30 19:37:36 sue Exp $
+#
+
+# TEST mutex001
+# TEST Test basic mutex functionality
+proc mutex001 { } {
+ source ./include.tcl
+
+ puts "Mutex001: Basic functionality"
+ env_cleanup $testdir
+ set nlocks 20
+
+ # Test open w/out create; should fail
+ error_check_bad \
+ env_open [catch {berkdb_env -lock -home $testdir} env] 0
+
+ puts "\tMutex001.a: Create lock env"
+ # Now open for real
+ set env [berkdb_env -create -mode 0644 -lock -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ puts "\tMutex001.b: Create $nlocks mutexes"
+ set m [$env mutex 0644 $nlocks]
+ error_check_good mutex_init [is_valid_mutex $m $env] TRUE
+
+ # Get, set each mutex; sleep, then get Release
+ puts "\tMutex001.c: Get/set loop"
+ for { set i 0 } { $i < $nlocks } { incr i } {
+ set r [$m get $i ]
+ error_check_good mutex_get $r 0
+
+ set r [$m setval $i $i]
+ error_check_good mutex_setval $r 0
+ }
+ tclsleep 5
+ for { set i 0 } { $i < $nlocks } { incr i } {
+ set r [$m getval $i]
+ error_check_good mutex_getval $r $i
+
+ set r [$m release $i ]
+ error_check_good mutex_get $r 0
+ }
+
+ error_check_good mutex_close [$m close] 0
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/mutex002.tcl b/bdb/test/mutex002.tcl
new file mode 100644
index 00000000000..193e600fe8b
--- /dev/null
+++ b/bdb/test/mutex002.tcl
@@ -0,0 +1,94 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: mutex002.tcl,v 11.23 2002/04/30 19:37:36 sue Exp $
+#
+
+# TEST mutex002
+# TEST Test basic mutex synchronization
+proc mutex002 { } {
+ source ./include.tcl
+
+ puts "Mutex002: Basic synchronization"
+ env_cleanup $testdir
+ set nlocks 20
+
+ # Fork off child before we open any files.
+ set f1 [open |$tclsh_path r+]
+ puts $f1 "source $test_path/test.tcl"
+ flush $f1
+
+ # Open the environment and the mutex locally
+ puts "\tMutex002.a: Open local and remote env"
+ set local_env [berkdb_env -create -mode 0644 -lock -home $testdir]
+ error_check_good env_open [is_valid_env $local_env] TRUE
+
+ set local_mutex [$local_env mutex 0644 $nlocks]
+ error_check_good \
+ mutex_init [is_valid_mutex $local_mutex $local_env] TRUE
+
+ # Open the environment and the mutex remotely
+ set remote_env [send_cmd $f1 "berkdb_env -lock -home $testdir"]
+ error_check_good remote:env_open [is_valid_env $remote_env] TRUE
+
+ set remote_mutex [send_cmd $f1 "$remote_env mutex 0644 $nlocks"]
+ error_check_good \
+ mutex_init [is_valid_mutex $remote_mutex $remote_env] TRUE
+
+ # Do a get here, then set the value to be pid.
+ # On the remote side fire off a get and getval.
+ puts "\tMutex002.b: Local and remote get/set"
+ set r [$local_mutex get 1]
+ error_check_good lock_get $r 0
+
+ set r [$local_mutex setval 1 [pid]]
+ error_check_good lock_get $r 0
+
+ # Now have the remote side request the lock and check its
+ # value. Then wait 5 seconds, release the mutex and see
+ # what the remote side returned.
+ send_timed_cmd $f1 1 "$remote_mutex get 1"
+ send_timed_cmd $f1 1 "set ret \[$remote_mutex getval 1\]"
+
+ # Now sleep before resetting and releasing lock
+ tclsleep 5
+ set newv [expr [pid] - 1]
+ set r [$local_mutex setval 1 $newv]
+ error_check_good mutex_setval $r 0
+
+ set r [$local_mutex release 1]
+ error_check_good mutex_release $r 0
+
+ # Now get the result from the other script
+ # Timestamp
+ set result [rcv_result $f1]
+ error_check_good lock_get:remote_time [expr $result > 4] 1
+
+ # Timestamp
+ set result [rcv_result $f1]
+
+ # Mutex value
+ set result [send_cmd $f1 "puts \$ret"]
+ error_check_good lock_get:remote_getval $result $newv
+
+ # Close down the remote
+ puts "\tMutex002.c: Close remote"
+ set ret [send_cmd $f1 "$remote_mutex close" 5]
+ # Not sure why we need this, but we do... an extra blank line
+ # someone gets output somewhere
+ gets $f1 ret
+ error_check_good remote:mutex_close $ret 0
+
+ set ret [send_cmd $f1 "$remote_env close"]
+ error_check_good remote:env_close $ret 0
+
+ catch { close $f1 } result
+
+ set ret [$local_mutex close]
+ error_check_good local:mutex_close $ret 0
+
+ set ret [$local_env close]
+ error_check_good local:env_close $ret 0
+}
diff --git a/bdb/test/mutex003.tcl b/bdb/test/mutex003.tcl
new file mode 100644
index 00000000000..da35ac0d115
--- /dev/null
+++ b/bdb/test/mutex003.tcl
@@ -0,0 +1,52 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: mutex003.tcl,v 11.24 2002/09/05 17:23:06 sandstro Exp $
+#
+
+# TEST mutex003
+# TEST Generate a bunch of parallel testers that try to randomly obtain locks.
+proc mutex003 { } {
+ source ./include.tcl
+
+ set nmutex 20
+ set iter 500
+ set procs 5
+ set mdegree 3
+ set wait 2
+ puts "Mutex003: Multi-process random mutex test"
+
+ env_cleanup $testdir
+
+ puts "\tMutex003.a: Create environment"
+ # Now open the region we'll use for multiprocess testing.
+ set env [berkdb_env -create -mode 0644 -lock -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ set mutex [$env mutex 0644 $nmutex]
+ error_check_good mutex_init [is_valid_mutex $mutex $env] TRUE
+
+ error_check_good mutex_close [$mutex close] 0
+
+ # Now spawn off processes
+ puts "\tMutex003.b: Create $procs processes"
+ set pidlist {}
+ for { set i 0 } {$i < $procs} {incr i} {
+ puts "$tclsh_path\
+ $test_path/mutexscript.tcl $testdir\
+ $iter $nmutex $wait $mdegree > $testdir/$i.mutexout &"
+ set p [exec $tclsh_path $test_path/wrap.tcl \
+ mutexscript.tcl $testdir/$i.mutexout $testdir\
+ $iter $nmutex $wait $mdegree &]
+ lappend pidlist $p
+ }
+ puts "\tMutex003.c: $procs independent processes now running"
+ watch_procs $pidlist
+ error_check_good env_close [$env close] 0
+ # Remove output files
+ for { set i 0 } {$i < $procs} {incr i} {
+ fileremove -f $testdir/$i.mutexout
+ }
+}
diff --git a/bdb/test/mutexscript.tcl b/bdb/test/mutexscript.tcl
index 9a49e471186..bc410f2716d 100644
--- a/bdb/test/mutexscript.tcl
+++ b/bdb/test/mutexscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: mutexscript.tcl,v 11.12 2000/11/21 22:14:56 dda Exp $
+# $Id: mutexscript.tcl,v 11.16 2002/04/29 14:58:16 sandstro Exp $
#
# Random mutex tester.
# Usage: mutexscript dir numiters mlocks sleepint degree
@@ -43,7 +43,7 @@ puts " $numiters $nmutex $sleepint $degree"
flush stdout
# Open the environment and the mutex
-set e [berkdb env -create -mode 0644 -lock -home $dir]
+set e [berkdb_env -create -mode 0644 -lock -home $dir]
error_check_good evn_open [is_valid_env $e] TRUE
set mutex [$e mutex 0644 $nmutex]
@@ -73,8 +73,8 @@ for { set iter 0 } { $iter < $numiters } { incr iter } {
}
}
- # Pick sleep interval
- tclsleep [ berkdb random_int 1 $sleepint ]
+ # Sleep for 10 to (100*$sleepint) ms.
+ after [berkdb random_int 10 [expr $sleepint * 100]]
# Now release locks
foreach i $mlist {
diff --git a/bdb/test/ndbm.tcl b/bdb/test/ndbm.tcl
index a6286de0266..0bf8e0cc87c 100644
--- a/bdb/test/ndbm.tcl
+++ b/bdb/test/ndbm.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: ndbm.tcl,v 11.13 2000/08/25 14:21:51 sue Exp $
+# $Id: ndbm.tcl,v 11.16 2002/07/08 13:11:30 mjc Exp $
#
# Historic NDBM interface test.
# Use the first 1000 entries from the dictionary.
@@ -80,11 +80,14 @@ proc ndbm { { nentries 1000 } } {
error_check_good NDBM:diff($t3,$t2) \
[filecmp $t3 $t2] 0
- puts "\tNDBM.c: pagf/dirf test"
- set fd [$db pagfno]
- error_check_bad pagf $fd -1
- set fd [$db dirfno]
- error_check_bad dirf $fd -1
+ # File descriptors tests won't work under Windows.
+ if { $is_windows_test != 1 } {
+ puts "\tNDBM.c: pagf/dirf test"
+ set fd [$db pagfno]
+ error_check_bad pagf $fd -1
+ set fd [$db dirfno]
+ error_check_bad dirf $fd -1
+ }
puts "\tNDBM.d: close, open, and dump file"
diff --git a/bdb/test/parallel.tcl b/bdb/test/parallel.tcl
new file mode 100644
index 00000000000..4e101c088cb
--- /dev/null
+++ b/bdb/test/parallel.tcl
@@ -0,0 +1,295 @@
+# Code to load up the tests in to the Queue database
+# $Id: parallel.tcl,v 11.28 2002/09/05 17:23:06 sandstro Exp $
+proc load_queue { file {dbdir RUNQUEUE} nitems } {
+
+ puts -nonewline "Loading run queue with $nitems items..."
+ flush stdout
+
+ set env [berkdb_env -create -lock -home $dbdir]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ set db [eval {berkdb_open -env $env -create -truncate \
+ -mode 0644 -len 120 -queue queue.db} ]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set fid [open $file]
+
+ set count 0
+
+ while { [gets $fid str] != -1 } {
+ set testarr($count) $str
+ incr count
+ }
+
+ # Randomize array of tests.
+ set rseed [pid]
+ berkdb srand $rseed
+ puts -nonewline "randomizing..."
+ flush stdout
+ for { set i 0 } { $i < $count } { incr i } {
+ set j [berkdb random_int $i [expr $count - 1]]
+
+ set tmp $testarr($i)
+ set testarr($i) $testarr($j)
+ set testarr($j) $tmp
+ }
+
+ if { [string compare ALL $nitems] != 0 } {
+ set maxload $nitems
+ } else {
+ set maxload $count
+ }
+
+ puts "loading..."
+ flush stdout
+ for { set i 0 } { $i < $maxload } { incr i } {
+ set str $testarr($i)
+ set ret [eval {$db put -append $str} ]
+ error_check_good put:$db $ret [expr $i + 1]
+ }
+
+ puts "Loaded $maxload records (out of $count)."
+ close $fid
+ $db close
+ $env close
+}
+
+proc init_runqueue { {dbdir RUNQUEUE} nitems list} {
+
+ if { [file exists $dbdir] != 1 } {
+ file mkdir $dbdir
+ }
+ puts "Creating test list..."
+ $list -n
+ load_queue ALL.OUT $dbdir $nitems
+ file delete TEST.LIST
+ file rename ALL.OUT TEST.LIST
+# file delete ALL.OUT
+}
+
+proc run_parallel { nprocs {list run_all} {nitems ALL} } {
+ set basename ./PARALLEL_TESTDIR
+ set queuedir ./RUNQUEUE
+ source ./include.tcl
+
+ mkparalleldirs $nprocs $basename $queuedir
+
+ init_runqueue $queuedir $nitems $list
+
+ set basedir [pwd]
+ set pidlist {}
+ set queuedir ../../[string range $basedir \
+ [string last "/" $basedir] end]/$queuedir
+
+ for { set i 1 } { $i <= $nprocs } { incr i } {
+ fileremove -f ALL.OUT.$i
+ set ret [catch {
+ set p [exec $tclsh_path << \
+ "source $test_path/test.tcl;\
+ run_queue $i $basename.$i $queuedir $nitems" &]
+ lappend pidlist $p
+ set f [open $testdir/begin.$p w]
+ close $f
+ } res]
+ }
+ watch_procs $pidlist 300 360000
+
+ set failed 0
+ for { set i 1 } { $i <= $nprocs } { incr i } {
+ if { [check_failed_run ALL.OUT.$i] != 0 } {
+ set failed 1
+ puts "Regression tests failed in process $i."
+ }
+ }
+ if { $failed == 0 } {
+ puts "Regression tests succeeded."
+ }
+}
+
+proc run_queue { i rundir queuedir nitems } {
+ set builddir [pwd]
+ file delete $builddir/ALL.OUT.$i
+ cd $rundir
+
+ puts "Parallel run_queue process $i (pid [pid]) starting."
+
+ source ./include.tcl
+ global env
+
+ set dbenv [berkdb_env -create -lock -home $queuedir]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ set db [eval {berkdb_open -env $dbenv \
+ -mode 0644 -len 120 -queue queue.db} ]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set dbc [eval $db cursor]
+ error_check_good cursor [is_valid_cursor $dbc $db] TRUE
+
+ set count 0
+ set waitcnt 0
+
+ while { $waitcnt < 5 } {
+ set line [$db get -consume]
+ if { [ llength $line ] > 0 } {
+ set cmd [lindex [lindex $line 0] 1]
+ set num [lindex [lindex $line 0] 0]
+ set o [open $builddir/ALL.OUT.$i a]
+ puts $o "\nExecuting record $num ([timestamp -w]):\n"
+ set tdir "TESTDIR.$i"
+ regsub {TESTDIR} $cmd $tdir cmd
+ puts $o $cmd
+ close $o
+ if { [expr {$num % 10} == 0] } {
+ puts "Starting test $num of $nitems"
+ }
+ #puts "Process $i, record $num:\n$cmd"
+ set env(PURIFYOPTIONS) \
+ "-log-file=./test$num.%p -follow-child-processes -messages=first"
+ set env(PURECOVOPTIONS) \
+ "-counts-file=./cov.pcv -log-file=./cov.log -follow-child-processes"
+ if [catch {exec $tclsh_path \
+ << "source $test_path/test.tcl; $cmd" \
+ >>& $builddir/ALL.OUT.$i } res] {
+ set o [open $builddir/ALL.OUT.$i a]
+ puts $o "FAIL: '$cmd': $res"
+ close $o
+ }
+ env_cleanup $testdir
+ set o [open $builddir/ALL.OUT.$i a]
+ puts $o "\nEnding record $num ([timestamp])\n"
+ close $o
+ incr count
+ } else {
+ incr waitcnt
+ tclsleep 1
+ }
+ }
+
+ puts "Process $i: $count commands executed"
+
+ $dbc close
+ $db close
+ $dbenv close
+
+ #
+ # We need to put the pid file in the builddir's idea
+ # of testdir, not this child process' local testdir.
+ # Therefore source builddir's include.tcl to get its
+ # testdir.
+ # !!! This resets testdir, so don't do anything else
+ # local to the child after this.
+ source $builddir/include.tcl
+
+ set f [open $builddir/$testdir/end.[pid] w]
+ close $f
+}
+
+proc mkparalleldirs { nprocs basename queuedir } {
+ source ./include.tcl
+ set dir [pwd]
+
+ if { $is_windows_test != 1 } {
+ set EXE ""
+ } else {
+ set EXE ".exe"
+ }
+ for { set i 1 } { $i <= $nprocs } { incr i } {
+ set destdir $basename.$i
+ catch {file mkdir $destdir}
+ puts "Created $destdir"
+ if { $is_windows_test == 1 } {
+ catch {file mkdir $destdir/Debug}
+ catch {eval file copy \
+ [eval glob {$dir/Debug/*.dll}] $destdir/Debug}
+ }
+ catch {eval file copy \
+ [eval glob {$dir/{.libs,include.tcl}}] $destdir}
+ # catch {eval file copy $dir/$queuedir $destdir}
+ catch {eval file copy \
+ [eval glob {$dir/db_{checkpoint,deadlock}$EXE} \
+ {$dir/db_{dump,load,printlog,recover,stat,upgrade}$EXE} \
+ {$dir/db_{archive,verify}$EXE}] \
+ $destdir}
+
+ # Create modified copies of include.tcl in parallel
+ # directories so paths still work.
+
+ set infile [open ./include.tcl r]
+ set d [read $infile]
+ close $infile
+
+ regsub {test_path } $d {test_path ../} d
+ regsub {src_root } $d {src_root ../} d
+ set tdir "TESTDIR.$i"
+ regsub -all {TESTDIR} $d $tdir d
+ regsub {KILL \.} $d {KILL ..} d
+ set outfile [open $destdir/include.tcl w]
+ puts $outfile $d
+ close $outfile
+
+ global svc_list
+ foreach svc_exe $svc_list {
+ if { [file exists $dir/$svc_exe] } {
+ catch {eval file copy $dir/$svc_exe $destdir}
+ }
+ }
+ }
+}
+
+proc run_ptest { nprocs test args } {
+ global parms
+ set basename ./PARALLEL_TESTDIR
+ set queuedir NULL
+ source ./include.tcl
+
+ mkparalleldirs $nprocs $basename $queuedir
+
+ if { [info exists parms($test)] } {
+ foreach method \
+ "hash queue queueext recno rbtree frecno rrecno btree" {
+ if { [eval exec_ptest $nprocs $basename \
+ $test $method $args] != 0 } {
+ break
+ }
+ }
+ } else {
+ eval exec_ptest $nprocs $basename $test $args
+ }
+}
+
+proc exec_ptest { nprocs basename test args } {
+ source ./include.tcl
+
+ set basedir [pwd]
+ set pidlist {}
+ puts "Running $nprocs parallel runs of $test"
+ for { set i 1 } { $i <= $nprocs } { incr i } {
+ set outf ALL.OUT.$i
+ fileremove -f $outf
+ set ret [catch {
+ set p [exec $tclsh_path << \
+ "cd $basename.$i;\
+ source ../$test_path/test.tcl;\
+ $test $args" >& $outf &]
+ lappend pidlist $p
+ set f [open $testdir/begin.$p w]
+ close $f
+ } res]
+ }
+ watch_procs $pidlist 30 36000
+ set failed 0
+ for { set i 1 } { $i <= $nprocs } { incr i } {
+ if { [check_failed_run ALL.OUT.$i] != 0 } {
+ set failed 1
+ puts "Test $test failed in process $i."
+ }
+ }
+ if { $failed == 0 } {
+ puts "Test $test succeeded all processes"
+ return 0
+ } else {
+ puts "Test failed: stopping"
+ return 1
+ }
+}
diff --git a/bdb/test/recd001.tcl b/bdb/test/recd001.tcl
index bbf5159011b..bc7ac6d896a 100644
--- a/bdb/test/recd001.tcl
+++ b/bdb/test/recd001.tcl
@@ -1,19 +1,27 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd001.tcl,v 11.28 2000/12/07 19:13:46 sue Exp $
+# $Id: recd001.tcl,v 11.40 2002/05/08 19:36:18 sandstro Exp $
#
-# Recovery Test 1.
-# These are the most basic recovery tests. We do individual recovery
-# tests for each operation in the access method interface. First we
-# create a file and capture the state of the database (i.e., we copy
-# it. Then we run a transaction containing a single operation. In
-# one test, we abort the transaction and compare the outcome to the
-# original copy of the file. In the second test, we restore the
-# original copy of the database and then run recovery and compare
-# this against the actual database.
+# TEST recd001
+# TEST Per-operation recovery tests for non-duplicate, non-split
+# TEST messages. Makes sure that we exercise redo, undo, and do-nothing
+# TEST condition. Any test that appears with the message (change state)
+# TEST indicates that we've already run the particular test, but we are
+# TEST running it again so that we can change the state of the data base
+# TEST to prepare for the next test (this applies to all other recovery
+# TEST tests as well).
+# TEST
+# TEST These are the most basic recovery tests. We do individual recovery
+# TEST tests for each operation in the access method interface. First we
+# TEST create a file and capture the state of the database (i.e., we copy
+# TEST it. Then we run a transaction containing a single operation. In
+# TEST one test, we abort the transaction and compare the outcome to the
+# TEST original copy of the file. In the second test, we restore the
+# TEST original copy of the database and then run recovery and compare
+# TEST this against the actual database.
proc recd001 { method {select 0} args} {
global fixed_len
source ./include.tcl
@@ -43,7 +51,7 @@ proc recd001 { method {select 0} args} {
set flags "-create -txn -home $testdir"
puts "\tRecd001.a.0: creating environment"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
@@ -124,6 +132,7 @@ proc recd001 { method {select 0} args} {
set newdata NEWrecd001_dataNEW
set off 3
set len 12
+
set partial_grow replacement_record_grow
set partial_shrink xxx
if { [is_fixed_length $method] == 1 } {
@@ -165,16 +174,69 @@ proc recd001 { method {select 0} args} {
# }
op_recover abort $testdir $env_cmd $testfile $cmd $msg
op_recover commit $testdir $env_cmd $testfile $cmd $msg
- op_recover prepare $testdir $env_cmd $testfile2 $cmd $msg
- op_recover prepare-abort $testdir $env_cmd $testfile2 $cmd $msg
- op_recover prepare-commit $testdir $env_cmd $testfile2 $cmd $msg
+ #
+ # Note that since prepare-discard ultimately aborts
+ # the txn, it must come before prepare-commit.
+ #
+ op_recover prepare-abort $testdir $env_cmd $testfile2 \
+ $cmd $msg
+ op_recover prepare-discard $testdir $env_cmd $testfile2 \
+ $cmd $msg
+ op_recover prepare-commit $testdir $env_cmd $testfile2 \
+ $cmd $msg
}
set fixed_len $orig_fixed_len
- puts "\tRecd001.o: Verify db_printlog can read logfile"
- set tmpfile $testdir/printlog.out
- set stat [catch {exec $util_path/db_printlog -h $testdir \
- > $tmpfile} ret]
- error_check_good db_printlog $stat 0
- fileremove $tmpfile
+ if { [is_fixed_length $method] == 1 } {
+ puts "Skipping remainder of test for fixed length methods"
+ return
+ }
+
+ #
+ # Check partial extensions. If we add a key/data to the database
+ # and then expand it using -partial, then recover, recovery was
+ # failing in #3944. Check that scenario here.
+ #
+ # !!!
+ # We loop here because on each iteration, we need to clean up
+ # the old env (i.e. this test does not depend on earlier runs).
+ # If we run it without cleaning up the env inbetween, we do not
+ # test the scenario of #3944.
+ #
+ set len [string length $data]
+ set len2 256
+ set part_data [replicate "abcdefgh" 32]
+ set p [list 0 $len]
+ set cmd [subst \
+ {DB put -txn TXNID -partial {$len $len2} $key $part_data}]
+ set msg "Recd001.o: partial put prepopulated/expanding"
+ foreach op {abort commit prepare-abort prepare-discard prepare-commit} {
+ env_cleanup $testdir
+
+ set dbenv [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+ set t [$dbenv txn]
+ error_check_good txn_begin [is_valid_txn $t $dbenv] TRUE
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv -txn $t $opts $testfile"
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv -txn $t $opts $testfile2"
+ set db2 [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db2] TRUE
+
+ set ret [$db put -txn $t -partial $p $key $data]
+ error_check_good dbput $ret 0
+
+ set ret [$db2 put -txn $t -partial $p $key $data]
+ error_check_good dbput $ret 0
+ error_check_good txncommit [$t commit] 0
+ error_check_good dbclose [$db close] 0
+ error_check_good dbclose [$db2 close] 0
+ error_check_good dbenvclose [$dbenv close] 0
+
+ op_recover $op $testdir $env_cmd $testfile $cmd $msg
+ }
+ return
}
diff --git a/bdb/test/recd002.tcl b/bdb/test/recd002.tcl
index ffcec6527e8..ed579291283 100644
--- a/bdb/test/recd002.tcl
+++ b/bdb/test/recd002.tcl
@@ -1,11 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd002.tcl,v 11.22 2000/12/11 17:24:54 sue Exp $
+# $Id: recd002.tcl,v 11.30 2002/02/25 16:44:24 sandstro Exp $
#
-# Recovery Test #2. Verify that splits can be recovered.
+# TEST recd002
+# TEST Split recovery tests. For every known split log message, makes sure
+# TEST that we exercise redo, undo, and do-nothing condition.
proc recd002 { method {select 0} args} {
source ./include.tcl
global rand_init
@@ -37,7 +39,7 @@ proc recd002 { method {select 0} args} {
"-create -txn -lock_max 2000 -home $testdir"
puts "\tRecd002.a: creating environment"
- set env_cmd "berkdb env $eflags"
+ set env_cmd "berkdb_env $eflags"
set dbenv [eval $env_cmd]
error_check_bad dbenv $dbenv NULL
@@ -80,9 +82,14 @@ proc recd002 { method {select 0} args} {
}
op_recover abort $testdir $env_cmd $testfile $cmd $msg
op_recover commit $testdir $env_cmd $testfile $cmd $msg
- op_recover prepare $testdir $env_cmd $testfile2 $cmd $msg
+ #
+ # Note that since prepare-discard ultimately aborts
+ # the txn, it must come before prepare-commit.
+ #
op_recover prepare-abort $testdir $env_cmd $testfile2 \
$cmd $msg
+ op_recover prepare-discard $testdir $env_cmd $testfile2 \
+ $cmd $msg
op_recover prepare-commit $testdir $env_cmd $testfile2 \
$cmd $msg
}
diff --git a/bdb/test/recd003.tcl b/bdb/test/recd003.tcl
index af7097c8909..0fd054832ce 100644
--- a/bdb/test/recd003.tcl
+++ b/bdb/test/recd003.tcl
@@ -1,14 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd003.tcl,v 11.22 2000/12/07 19:13:46 sue Exp $
+# $Id: recd003.tcl,v 11.30 2002/02/25 16:44:24 sandstro Exp $
#
-# Recovery Test 3.
-# Test all the duplicate log messages and recovery operations. We make
-# sure that we exercise all possible recovery actions: redo, undo, undo
-# but no fix necessary and redo but no fix necessary.
+# TEST recd003
+# TEST Duplicate recovery tests. For every known duplicate log message,
+# TEST makes sure that we exercise redo, undo, and do-nothing condition.
+# TEST
+# TEST Test all the duplicate log messages and recovery operations. We make
+# TEST sure that we exercise all possible recovery actions: redo, undo, undo
+# TEST but no fix necessary and redo but no fix necessary.
proc recd003 { method {select 0} args } {
source ./include.tcl
global rand_init
@@ -31,7 +34,7 @@ proc recd003 { method {select 0} args } {
set eflags "-create -txn -home $testdir"
puts "\tRecd003.a: creating environment"
- set env_cmd "berkdb env $eflags"
+ set env_cmd "berkdb_env $eflags"
set dbenv [eval $env_cmd]
error_check_bad dbenv $dbenv NULL
@@ -95,9 +98,14 @@ proc recd003 { method {select 0} args } {
}
op_recover abort $testdir $env_cmd $testfile $cmd $msg
op_recover commit $testdir $env_cmd $testfile $cmd $msg
- op_recover prepare $testdir $env_cmd $testfile2 $cmd $msg
+ #
+ # Note that since prepare-discard ultimately aborts
+ # the txn, it must come before prepare-commit.
+ #
op_recover prepare-abort $testdir $env_cmd $testfile2 \
$cmd $msg
+ op_recover prepare-discard $testdir $env_cmd $testfile2 \
+ $cmd $msg
op_recover prepare-commit $testdir $env_cmd $testfile2 \
$cmd $msg
}
diff --git a/bdb/test/recd004.tcl b/bdb/test/recd004.tcl
index 012dd80f6e5..74504ac3cd7 100644
--- a/bdb/test/recd004.tcl
+++ b/bdb/test/recd004.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd004.tcl,v 11.21 2000/12/11 17:24:55 sue Exp $
+# $Id: recd004.tcl,v 11.29 2002/02/25 16:44:25 sandstro Exp $
#
-# Recovery Test #4.
-# Verify that we work correctly when big keys get elevated.
+# TEST recd004
+# TEST Big key test where big key gets elevated to internal page.
proc recd004 { method {select 0} args} {
source ./include.tcl
global rand_init
@@ -32,7 +32,7 @@ proc recd004 { method {select 0} args} {
set testfile2 recd004-2.db
set eflags "-create -txn -home $testdir"
puts "\tRecd004.a: creating environment"
- set env_cmd "berkdb env $eflags"
+ set env_cmd "berkdb_env $eflags"
set dbenv [eval $env_cmd]
error_check_bad dbenv $dbenv NULL
@@ -74,9 +74,14 @@ proc recd004 { method {select 0} args} {
}
op_recover abort $testdir $env_cmd $testfile $cmd $msg
op_recover commit $testdir $env_cmd $testfile $cmd $msg
- op_recover prepare $testdir $env_cmd $testfile2 $cmd $msg
+ #
+ # Note that since prepare-discard ultimately aborts
+ # the txn, it must come before prepare-commit.
+ #
op_recover prepare-abort $testdir $env_cmd $testfile2 \
$cmd $msg
+ op_recover prepare-discard $testdir $env_cmd $testfile2 \
+ $cmd $msg
op_recover prepare-commit $testdir $env_cmd $testfile2 \
$cmd $msg
}
diff --git a/bdb/test/recd005.tcl b/bdb/test/recd005.tcl
index 06a346f4484..7668c9e3be3 100644
--- a/bdb/test/recd005.tcl
+++ b/bdb/test/recd005.tcl
@@ -1,13 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd005.tcl,v 11.27 2000/12/15 21:41:38 ubell Exp $
+# $Id: recd005.tcl,v 11.34 2002/05/22 15:42:39 sue Exp $
#
-# Recovery Test 5.
-# Make sure that we can do catastrophic recovery even if we open
-# files using the same log file id.
+# TEST recd005
+# TEST Verify reuse of file ids works on catastrophic recovery.
+# TEST
+# TEST Make sure that we can do catastrophic recovery even if we open
+# TEST files using the same log file id.
proc recd005 { method args} {
source ./include.tcl
global rand_init
@@ -15,7 +17,7 @@ proc recd005 { method args} {
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Recd005: $method catastropic recovery"
+ puts "Recd005: $method catastrophic recovery"
berkdb srand $rand_init
@@ -38,7 +40,7 @@ proc recd005 { method args} {
puts "\tRecd005.$tnum: $s1 $s2 $op1 $op2"
puts "\tRecd005.$tnum.a: creating environment"
- set env_cmd "berkdb env $eflags"
+ set env_cmd "berkdb_env $eflags"
set dbenv [eval $env_cmd]
error_check_bad dbenv $dbenv NULL
@@ -147,12 +149,11 @@ proc do_one_file { dir method env env_cmd filename num op } {
# Save the initial file and open the environment and the first file
file copy -force $dir/$filename $dir/$filename.init
copy_extent_file $dir $filename init
- set oflags "-unknown -env $env"
+ set oflags "-auto_commit -unknown -env $env"
set db [eval {berkdb_open} $oflags $filename]
# Dump out file contents for initial case
- set tflags ""
- open_and_dump_file $filename $env $tflags $init_file nop \
+ open_and_dump_file $filename $env $init_file nop \
dump_file_direction "-first" "-next"
set txn [$env txn]
@@ -167,7 +168,7 @@ proc do_one_file { dir method env env_cmd filename num op } {
error_check_good sync:$db [$db sync] 0
file copy -force $dir/$filename $dir/$filename.afterop
copy_extent_file $dir $filename afterop
- open_and_dump_file $testdir/$filename.afterop NULL $tflags \
+ open_and_dump_file $testdir/$filename.afterop NULL \
$afterop_file nop dump_file_direction "-first" "-next"
error_check_good txn_$op:$txn [$txn $op] 0
@@ -179,7 +180,7 @@ proc do_one_file { dir method env env_cmd filename num op } {
# Dump out file and save a copy.
error_check_good sync:$db [$db sync] 0
- open_and_dump_file $testdir/$filename NULL $tflags $final_file nop \
+ open_and_dump_file $testdir/$filename NULL $final_file nop \
dump_file_direction "-first" "-next"
file copy -force $dir/$filename $dir/$filename.final
copy_extent_file $dir $filename final
@@ -211,8 +212,7 @@ proc check_file { dir env_cmd filename op } {
set afterop_file $dir/$filename.t2
set final_file $dir/$filename.t3
- set tflags ""
- open_and_dump_file $testdir/$filename NULL $tflags $final_file nop \
+ open_and_dump_file $testdir/$filename NULL $final_file nop \
dump_file_direction "-first" "-next"
if { $op == "abort" } {
filesort $init_file $init_file.sort
@@ -227,5 +227,4 @@ proc check_file { dir env_cmd filename op } {
diff(pre-commit,post-$op):diff($afterop_file,$final_file) \
[filecmp $afterop_file.sort $final_file.sort] 0
}
-
}
diff --git a/bdb/test/recd006.tcl b/bdb/test/recd006.tcl
index 14f01cc0b8f..fc35e755b08 100644
--- a/bdb/test/recd006.tcl
+++ b/bdb/test/recd006.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd006.tcl,v 11.21 2000/12/07 19:13:46 sue Exp $
+# $Id: recd006.tcl,v 11.26 2002/03/15 16:30:53 sue Exp $
#
-# Recovery Test 6.
-# Test nested transactions.
+# TEST recd006
+# TEST Nested transactions.
proc recd006 { method {select 0} args} {
global kvals
source ./include.tcl
@@ -83,7 +83,7 @@ proc recd006 { method {select 0} args} {
set eflags "-create -txn -home $testdir"
puts "\tRecd006.b: creating environment"
- set env_cmd "berkdb env $eflags"
+ set env_cmd "berkdb_env $eflags"
set dbenv [eval $env_cmd]
error_check_bad dbenv $dbenv NULL
@@ -176,7 +176,7 @@ proc nesttest { db parent env do p1 p2 child1 child2} {
# OK, do child 1
set kid1 [$env txn -parent $parent]
- error_check_good kid1 [is_valid_widget $kid1 $env.txn] TRUE
+ error_check_good kid1 [is_valid_txn $kid1 $env] TRUE
# Reading write-locked parent object should be OK
#puts "\tRead write-locked parent object for kid1."
@@ -193,7 +193,7 @@ proc nesttest { db parent env do p1 p2 child1 child2} {
# Now start child2
#puts "\tBegin txn for kid2."
set kid2 [$env txn -parent $parent]
- error_check_good kid2 [is_valid_widget $kid2 $env.txn] TRUE
+ error_check_good kid2 [is_valid_txn $kid2 $env] TRUE
# Getting anything in the p1 set should deadlock, so let's
# work on the p2 set.
diff --git a/bdb/test/recd007.tcl b/bdb/test/recd007.tcl
index d077ae19f2c..aeac3bea2c1 100644
--- a/bdb/test/recd007.tcl
+++ b/bdb/test/recd007.tcl
@@ -1,16 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd007.tcl,v 11.38 2000/12/20 21:39:23 krinsky Exp $
+# $Id: recd007.tcl,v 11.60 2002/08/08 15:38:07 bostic Exp $
#
-# Recovery Test 7.
-# This is a recovery test for create/delete of databases. We have
-# hooks in the database so that we can abort the process at various
-# points and make sure that the transaction doesn't commit. We
-# then need to recover and make sure the file is correctly existing
-# or not, as the case may be.
+# TEST recd007
+# TEST File create/delete tests.
+# TEST
+# TEST This is a recovery test for create/delete of databases. We have
+# TEST hooks in the database so that we can abort the process at various
+# TEST points and make sure that the transaction doesn't commit. We
+# TEST then need to recover and make sure the file is correctly existing
+# TEST or not, as the case may be.
proc recd007 { method args} {
global fixed_len
source ./include.tcl
@@ -28,10 +30,10 @@ proc recd007 { method args} {
set flags "-create -txn -home $testdir"
puts "\tRecd007.a: creating environment"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
set env [eval $env_cmd]
- #
+
# We need to create a database to get the pagesize (either
# the default or whatever might have been specified).
# Then remove it so we can compute fixed_len and create the
@@ -54,7 +56,6 @@ proc recd007 { method args} {
# Convert the args again because fixed_len is now real.
set opts [convert_args $method ""]
- #
# List of recovery tests: {HOOKS MSG} pairs
# Where each HOOK is a list of {COPY ABORT}
#
@@ -89,25 +90,26 @@ proc recd007 { method args} {
}
set rlist {
- { {"none" "prerename"} "Recd007.l0: none/prerename"}
- { {"none" "postrename"} "Recd007.l1: none/postrename"}
- { {"prerename" "none"} "Recd007.m0: prerename/none"}
- { {"postrename" "none"} "Recd007.m1: postrename/none"}
- { {"prerename" "prerename"} "Recd007.n: prerename/prerename"}
- { {"prerename" "postrename"} "Recd007.o: prerename/postrename"}
- { {"postrename" "postrename"} "Recd007.p: postrename/postrename"}
- }
- foreach op { dbremove dbrename } {
+ { {"none" "predestroy"} "Recd007.l0: none/predestroy"}
+ { {"none" "postdestroy"} "Recd007.l1: none/postdestroy"}
+ { {"predestroy" "none"} "Recd007.m0: predestroy/none"}
+ { {"postdestroy" "none"} "Recd007.m1: postdestroy/none"}
+ { {"predestroy" "predestroy"} "Recd007.n: predestroy/predestroy"}
+ { {"predestroy" "postdestroy"} "Recd007.o: predestroy/postdestroy"}
+ { {"postdestroy" "postdestroy"} "Recd007.p: postdestroy/postdestroy"}
+ }
+ foreach op { dbremove dbrename dbtruncate } {
foreach pair $rlist {
set cmd [lindex $pair 0]
set msg [lindex $pair 1]
file_recover_delete $testdir $env_cmd $omethod \
- $opts $testfile $cmd $msg $op
+ $opts $testfile $cmd $msg $op
}
}
if { $is_windows_test != 1 } {
- do_file_recover_delmk $testdir $env_cmd $omethod $opts $testfile
+ set env_cmd "berkdb_env_noerr $flags"
+ do_file_recover_delmk $testdir $env_cmd $method $opts $testfile
}
puts "\tRecd007.r: Verify db_printlog can read logfile"
@@ -150,6 +152,7 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
}
env_cleanup $dir
+ set dflags "-dar"
# Open the environment and set the copy/abort locations
set env [eval $env_cmd]
set copy [lindex $cmd 0]
@@ -167,17 +170,16 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
return
}
- #
# Basically non-existence is our initial state. When we
# abort, it is also our final state.
#
switch $sub {
0 {
- set oflags "-create $method -mode 0644 \
+ set oflags "-create $method -auto_commit -mode 0644 \
-env $env $opts $dbfile"
}
1 {
- set oflags "-create $method -mode 0644 \
+ set oflags "-create $method -auto_commit -mode 0644 \
-env $env $opts $dbfile sub0"
}
2 {
@@ -185,14 +187,14 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
# If we are aborting here, then we need to
# create a first subdb, then create a second
#
- set oflags "-create $method -mode 0644 \
+ set oflags "-create $method -auto_commit -mode 0644 \
-env $env $opts $dbfile sub0"
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
error_check_good db_close [$db close] 0
set init_file $dir/$dbfile.init
catch { file copy -force $dir/$dbfile $init_file } res
- set oflags "-create $method -mode 0644 \
+ set oflags "-create $method -auto_commit -mode 0644 \
-env $env $opts $dbfile sub1"
}
default {
@@ -214,8 +216,7 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
# Sync the mpool so any changes to the file that are
# in mpool get written to the disk file before the
# diff.
- puts "\t\tSyncing"
- $env mpool_sync "0 0"
+ $env mpool_sync
#
# If we don't abort, then we expect success.
@@ -238,7 +239,7 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
} else {
error_check_good \
diff(init,postcreate):diff($init_file,$dir/$dbfile)\
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff $dflags $init_file $dir $dbfile] 0
}
} else {
#
@@ -289,7 +290,7 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
#
error_check_good \
diff(initial,post-recover1):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff $dflags $init_file $dir $dbfile] 0
#
# Need a new copy to get the right LSN into the file.
#
@@ -300,7 +301,6 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
}
}
- #
# If we didn't make a copy, then we are done.
#
if {[string first "none" $copy] != -1} {
@@ -310,11 +310,7 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
#
# Now move the .afterop file to $dbfile. Run recovery again.
#
- file copy -force $dir/$dbfile.afterop $dir/$dbfile
-
- if { [is_queue $method] == 1 } {
- move_file_extent $dir $dbfile afterop copy
- }
+ copy_afterop $dir
berkdb debug_check
puts -nonewline "\t\tAbout to run recovery ... "
@@ -339,7 +335,7 @@ proc do_file_recover_create { dir env_cmd method opts dbfile sub cmd msg } {
#
error_check_good \
diff(initial,post-recover2):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff $dflags $init_file $dir $dbfile] 0
}
}
@@ -384,43 +380,61 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
error_check_good abort_location [is_valid_delete_loc $abort] 1
if { [is_record_based $method] == 1 } {
- set key 1
+ set key1 1
+ set key2 2
} else {
- set key recd007_key
+ set key1 recd007_key1
+ set key2 recd007_key2
}
- set data1 recd007_data
- set data2 NEWrecd007_data2
+ set data1 recd007_data0
+ set data2 recd007_data1
+ set data3 NEWrecd007_data2
#
# Depending on what sort of subdb we want, if any, our
# args to the open call will be different (and if we
# want a 2nd subdb, we create the first here.
#
+ # XXX
+ # For dbtruncate, we want oflags to have "$env" in it,
+ # not have the value currently in 'env'. That is why
+ # the '$' is protected below. Later on we use oflags
+ # but with a new $env we just opened.
+ #
switch $sub {
0 {
- set oflags "-create $method -mode 0644 \
- -env $env $opts $dbfile"
+ set subdb ""
+ set new $dbfile.new
+ set dflags "-dar"
+ set oflags "-create $method -auto_commit -mode 0644 \
+ -env \$env $opts $dbfile"
}
1 {
- set oflags "-create $method -mode 0644 \
- -env $env $opts $dbfile sub0"
+ set subdb sub0
+ set new $subdb.new
+ set dflags ""
+ set oflags "-create $method -auto_commit -mode 0644 \
+ -env \$env $opts $dbfile $subdb"
}
2 {
#
# If we are aborting here, then we need to
# create a first subdb, then create a second
#
- set oflags "-create $method -mode 0644 \
- -env $env $opts $dbfile sub0"
+ set subdb sub1
+ set new $subdb.new
+ set dflags ""
+ set oflags "-create $method -auto_commit -mode 0644 \
+ -env \$env $opts $dbfile sub0"
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
set txn [$env txn]
- set ret [$db put -txn $txn $key $data2]
+ set ret [$db put -txn $txn $key1 $data1]
error_check_good db_put $ret 0
error_check_good commit [$txn commit] 0
error_check_good db_close [$db close] 0
- set oflags "-create $method -mode 0644 \
- -env $env $opts $dbfile sub1"
+ set oflags "-create $method -auto_commit -mode 0644 \
+ -env \$env $opts $dbfile $subdb"
}
default {
puts "\tBad value $sub for sub"
@@ -443,11 +457,15 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
set txn [$env txn]
- set ret [$db put -txn $txn $key $data1]
+ set ret [$db put -txn $txn $key1 $data1]
+ error_check_good db_put $ret 0
+ set ret [$db put -txn $txn $key2 $data2]
error_check_good db_put $ret 0
error_check_good commit [$txn commit] 0
error_check_good db_close [$db close] 0
+ $env mpool_sync
+
set init_file $dir/$dbfile.init
catch { file copy -force $dir/$dbfile $init_file } res
@@ -459,16 +477,51 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
# If we don't abort, then we expect success.
# If we abort, we expect no file removed.
#
- if { [string compare $op dbremove] == 0 } {
- set ret [catch { berkdb $op -env $env $dbfile } remret]
+ switch $op {
+ "dbrename" {
+ set ret [catch { eval {berkdb} $op -env $env -auto_commit \
+ $dbfile $subdb $new } remret]
+ }
+ "dbremove" {
+ set ret [catch { eval {berkdb} $op -env $env -auto_commit \
+ $dbfile $subdb } remret]
+ }
+ "dbtruncate" {
+ set txn [$env txn]
+ set db [eval {berkdb_open_noerr -env} \
+ $env -auto_commit $dbfile $subdb]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ error_check_good txnbegin [is_valid_txn $txn $env] TRUE
+ set ret [catch {$db truncate -txn $txn} remret]
+ }
+ }
+ $env mpool_sync
+ if { $abort == "none" } {
+ if { $op == "dbtruncate" } {
+ error_check_good txncommit [$txn commit] 0
+ error_check_good dbclose [$db close] 0
+ }
+ #
+ # Operation was committed, verify it.
+ #
+ puts "\t\tCommand executed and committed."
+ error_check_good $op $ret 0
+ #
+ # If a dbtruncate, check that truncate returned the number
+ # of items previously in the database.
+ #
+ if { [string compare $op "dbtruncate"] == 0 } {
+ error_check_good remret $remret 2
+ }
+ recd007_check $op $sub $dir $dbfile $subdb $new $env $oflags
} else {
- set ret [catch { berkdb $op -env $env $dbfile $dbfile.new } \
- remret]
- }
- if {[string first "none" $abort] == -1} {
#
# Operation was aborted, verify it did not change.
#
+ if { $op == "dbtruncate" } {
+ error_check_good txnabort [$txn abort] 0
+ error_check_good dbclose [$db close] 0
+ }
puts "\t\tCommand executed and aborted."
error_check_good $op $ret 1
@@ -479,30 +532,16 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
error_check_good post$op.1 [file exists $dir/$dbfile] 1
error_check_good \
diff(init,post$op.2):diff($init_file,$dir/$dbfile)\
- [dbdump_diff $init_file $dir/$dbfile] 0
- } else {
- #
- # Operation was committed, verify it does
- # not exist.
- #
- puts "\t\tCommand executed and committed."
- error_check_good $op $ret 0
- #
- # Check that the file does not exist or correct
- # file exists.
- #
- error_check_good $op [file exists $dir/$dbfile] 0
- if { [string compare $op dbrename] == 0 } {
- error_check_good $op [file exists $dir/$dbfile.new] 1
- }
+ [dbdump_diff $dflags $init_file $dir $dbfile] 0
}
+ $env mpool_sync
error_check_good env_close [$env close] 0
catch { file copy -force $dir/$dbfile $init_file } res
-
if { [is_queue $method] == 1} {
copy_extent_file $dir $dbfile init
}
+
#
# Run recovery here. Should be a no-op. Verify that
# the file still doesn't exist or change (depending on abort)
@@ -517,20 +556,24 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
error "FAIL: Recovery error: $result."
return
}
+
puts "complete"
- if { [string first "none" $abort] != -1} {
+
+ if { $abort == "none" } {
#
- # Operation was committed, verify it still does
- # not exist.
+ # Operate was committed.
#
- error_check_good after_recover1 [file exists $dir/$dbfile] 0
+ set env [eval $env_cmd]
+ recd007_check $op $sub $dir $dbfile $subdb $new $env $oflags
+ error_check_good env_close [$env close] 0
} else {
#
# Operation was aborted, verify it did not change.
#
+ berkdb debug_check
error_check_good \
diff(initial,post-recover1):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff $dflags $init_file $dir $dbfile] 0
}
#
@@ -541,15 +584,10 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
}
#
- # Now move the .afterop file to $dbfile. Run recovery again.
+ # Now restore the .afterop file(s) to their original name.
+ # Run recovery again.
#
- set filecopy [glob $dir/*.afterop]
- set afterop [lindex $filecopy 0]
- file rename -force $afterop $dir/$dbfile
- set afterop [string range $afterop \
- [expr [string last "/" $afterop] + 1] \
- [string last "." $afterop]]
- move_file_extent $dir $dbfile afterop rename
+ copy_afterop $dir
berkdb debug_check
puts -nonewline "\t\tAbout to run recovery ... "
@@ -563,18 +601,16 @@ proc do_file_recover_delete { dir env_cmd method opts dbfile sub cmd msg op } {
puts "complete"
if { [string first "none" $abort] != -1} {
- #
- # Operation was committed, verify it still does
- # not exist.
- #
- error_check_good after_recover2 [file exists $dir/$dbfile] 0
+ set env [eval $env_cmd]
+ recd007_check $op $sub $dir $dbfile $subdb $new $env $oflags
+ error_check_good env_close [$env close] 0
} else {
#
# Operation was aborted, verify it did not change.
#
error_check_good \
diff(initial,post-recover2):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff $dflags $init_file $dir $dbfile] 0
}
}
@@ -597,11 +633,13 @@ proc do_file_recover_delmk { dir env_cmd method opts dbfile } {
if { $log_log_record_types == 1} {
logtrack_read $dir
}
+ set omethod [convert_method $method]
puts "\tRecd007.q: Delete and recreate a database"
env_cleanup $dir
# Open the environment and set the copy/abort locations
set env [eval $env_cmd]
+ error_check_good env_open [is_valid_env $env] TRUE
if { [is_record_based $method] == 1 } {
set key 1
@@ -611,13 +649,14 @@ proc do_file_recover_delmk { dir env_cmd method opts dbfile } {
set data1 recd007_data
set data2 NEWrecd007_data2
- set oflags "-create $method -mode 0644 -env $env $opts $dbfile"
+ set oflags \
+ "-create $omethod -auto_commit -mode 0644 $opts $dbfile"
#
# Open our db, add some data, close and copy as our
# init file.
#
- set db [eval {berkdb_open} $oflags]
+ set db [eval {berkdb_open_noerr} -env $env $oflags]
error_check_good db_open [is_valid_db $db] TRUE
set txn [$env txn]
set ret [$db put -txn $txn $key $data1]
@@ -625,7 +664,9 @@ proc do_file_recover_delmk { dir env_cmd method opts dbfile } {
error_check_good commit [$txn commit] 0
error_check_good db_close [$db close] 0
- set ret [catch { berkdb dbremove -env $env $dbfile } remret]
+ set ret \
+ [catch { berkdb dbremove -env $env -auto_commit $dbfile } remret]
+
#
# Operation was committed, verify it does
# not exist.
@@ -637,10 +678,10 @@ proc do_file_recover_delmk { dir env_cmd method opts dbfile } {
#
# Now create a new db with the same name.
#
- set db [eval {berkdb_open} $oflags]
+ set db [eval {berkdb_open_noerr} -env $env $oflags]
error_check_good db_open [is_valid_db $db] TRUE
set txn [$env txn]
- set ret [$db put -txn $txn $key $data1]
+ set ret [$db put -txn $txn $key [chop_data $method $data2]]
error_check_good db_put $ret 0
error_check_good commit [$txn commit] 0
error_check_good db_sync [$db sync] 0
@@ -663,9 +704,29 @@ proc do_file_recover_delmk { dir env_cmd method opts dbfile } {
# up the Tcl widgets.
#
set stat [catch {$db close} ret]
+ error_check_bad dbclose_after_remove $stat 0
+ error_check_good dbclose_after_remove [is_substr $ret recovery] 1
set stat [catch {$env close} ret]
+ error_check_bad envclose_after_remove $stat 0
+ error_check_good envclose_after_remove [is_substr $ret recovery] 1
+ #
+ # Reopen env and db and verify 2nd database is there.
+ #
+ set env [eval $env_cmd]
+ error_check_good env_open [is_valid_env $env] TRUE
+ set db [eval {berkdb_open} -env $env $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ set ret [$db get $key]
+ error_check_good dbget [llength $ret] 1
+ set kd [lindex $ret 0]
+ error_check_good key [lindex $kd 0] $key
+ error_check_good data2 [lindex $kd 1] [pad_data $method $data2]
+
+ error_check_good dbclose [$db close] 0
+ error_check_good envclose [$env close] 0
}
+
proc is_valid_create_loc { loc } {
switch $loc {
none -
@@ -683,8 +744,8 @@ proc is_valid_create_loc { loc } {
proc is_valid_delete_loc { loc } {
switch $loc {
none -
- prerename -
- postrename -
+ predestroy -
+ postdestroy -
postremcall
{ return 1 }
default
@@ -697,23 +758,23 @@ proc is_valid_delete_loc { loc } {
# just a free/invalid page.
# Return 1 if they are different, 0 if logically the same (or identical).
#
-proc dbdump_diff { initfile dbfile } {
+proc dbdump_diff { flags initfile dir dbfile } {
source ./include.tcl
set initdump $initfile.dump
set dbdump $dbfile.dump
- set stat [catch {exec $util_path/db_dump -dar -f $initdump \
+ set stat [catch {eval {exec $util_path/db_dump} $flags -f $initdump \
$initfile} ret]
error_check_good dbdump.init $stat 0
# Do a dump without the freelist which should eliminate any
# recovery differences.
- set stat [catch {exec $util_path/db_dump -dar -f $dbdump $dbfile} \
- ret]
+ set stat [catch {eval {exec $util_path/db_dump} $flags -f $dir/$dbdump \
+ $dir/$dbfile} ret]
error_check_good dbdump.db $stat 0
- set stat [filecmp $dbdump $initdump]
+ set stat [filecmp $dir/$dbdump $initdump]
if {$stat == 0} {
return 0
@@ -721,3 +782,105 @@ proc dbdump_diff { initfile dbfile } {
puts "diff: $dbdump $initdump gives:\n$ret"
return 1
}
+
+proc recd007_check { op sub dir dbfile subdb new env oflags } {
+ #
+ # No matter how many subdbs we have, dbtruncate will always
+ # have a file, and if we open our particular db, it should
+ # have no entries.
+ #
+ if { $sub == 0 } {
+ if { $op == "dbremove" } {
+ error_check_good $op:not-exist \
+ [file exists $dir/$dbfile] 0
+ } elseif { $op == "dbrename"} {
+ error_check_good $op:exist \
+ [file exists $dir/$dbfile] 0
+ error_check_good $op:exist2 \
+ [file exists $dir/$dbfile.new] 1
+ } else {
+ error_check_good $op:exist \
+ [file exists $dir/$dbfile] 1
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ set dbc [$db cursor]
+ error_check_good dbc_open \
+ [is_valid_cursor $dbc $db] TRUE
+ set ret [$dbc get -first]
+ error_check_good dbget1 [llength $ret] 0
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good db_close [$db close] 0
+ }
+ return
+ } else {
+ set t1 $dir/t1
+ #
+ # If we have subdbs, check that all but the last one
+ # are there, and the last one is correctly operated on.
+ #
+ set db [berkdb_open -rdonly -env $env $dbfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set c [eval {$db cursor}]
+ error_check_good db_cursor [is_valid_cursor $c $db] TRUE
+ set d [$c get -last]
+ if { $op == "dbremove" } {
+ if { $sub == 1 } {
+ error_check_good subdb:rem [llength $d] 0
+ } else {
+ error_check_bad subdb:rem [llength $d] 0
+ set sdb [lindex [lindex $d 0] 0]
+ error_check_bad subdb:rem1 $sdb $subdb
+ }
+ } elseif { $op == "dbrename"} {
+ set sdb [lindex [lindex $d 0] 0]
+ error_check_good subdb:ren $sdb $new
+ if { $sub != 1 } {
+ set d [$c get -prev]
+ error_check_bad subdb:ren [llength $d] 0
+ set sdb [lindex [lindex $d 0] 0]
+ error_check_good subdb:ren1 \
+ [is_substr "new" $sdb] 0
+ }
+ } else {
+ set sdb [lindex [lindex $d 0] 0]
+ set dbt [berkdb_open -rdonly -env $env $dbfile $sdb]
+ error_check_good db_open [is_valid_db $dbt] TRUE
+ set dbc [$dbt cursor]
+ error_check_good dbc_open \
+ [is_valid_cursor $dbc $dbt] TRUE
+ set ret [$dbc get -first]
+ error_check_good dbget2 [llength $ret] 0
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good db_close [$dbt close] 0
+ if { $sub != 1 } {
+ set d [$c get -prev]
+ error_check_bad subdb:ren [llength $d] 0
+ set sdb [lindex [lindex $d 0] 0]
+ set dbt [berkdb_open -rdonly -env $env \
+ $dbfile $sdb]
+ error_check_good db_open [is_valid_db $dbt] TRUE
+ set dbc [$db cursor]
+ error_check_good dbc_open \
+ [is_valid_cursor $dbc $db] TRUE
+ set ret [$dbc get -first]
+ error_check_bad dbget3 [llength $ret] 0
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good db_close [$dbt close] 0
+ }
+ }
+ error_check_good dbcclose [$c close] 0
+ error_check_good db_close [$db close] 0
+ }
+}
+
+proc copy_afterop { dir } {
+ set r [catch { set filecopy [glob $dir/*.afterop] } res]
+ if { $r == 1 } {
+ return
+ }
+ foreach f $filecopy {
+ set orig [string range $f 0 \
+ [expr [string last "." $f] - 1]]
+ catch { file rename -force $f $orig} res
+ }
+}
diff --git a/bdb/test/recd008.tcl b/bdb/test/recd008.tcl
index b75605b0475..548813a403b 100644
--- a/bdb/test/recd008.tcl
+++ b/bdb/test/recd008.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd008.tcl,v 1.22 2000/12/07 19:13:46 sue Exp $
+# $Id: recd008.tcl,v 1.26 2002/02/25 16:44:26 sandstro Exp $
#
-# Recovery Test 8.
-# Test deeply nested transactions and many-child transactions.
+# TEST recd008
+# TEST Test deeply nested transactions and many-child transactions.
proc recd008 { method {breadth 4} {depth 4} args} {
global kvals
source ./include.tcl
@@ -59,7 +59,7 @@ proc recd008 { method {breadth 4} {depth 4} args} {
set eflags "-mode 0644 -create -txn_max $txn_max \
-txn -home $testdir"
- set env_cmd "berkdb env $eflags"
+ set env_cmd "berkdb_env $eflags"
set dbenv [eval $env_cmd]
error_check_good env_open [is_valid_env $dbenv] TRUE
diff --git a/bdb/test/recd009.tcl b/bdb/test/recd009.tcl
index 2b49437346c..5538d2d7652 100644
--- a/bdb/test/recd009.tcl
+++ b/bdb/test/recd009.tcl
@@ -1,13 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd009.tcl,v 1.13 2000/12/07 19:13:46 sue Exp $
+# $Id: recd009.tcl,v 1.18 2002/04/01 20:11:44 krinsky Exp $
#
-# Recovery Test 9.
-# Test stability of record numbers across splits
-# and reverse splits and across recovery.
+# TEST recd009
+# TEST Verify record numbering across split/reverse splits and recovery.
proc recd009 { method {select 0} args} {
global fixed_len
source ./include.tcl
@@ -31,11 +30,11 @@ proc recd009 { method {select 0} args} {
puts "\tRecd009.a: Create $method environment and database."
set flags "-create -txn -home $testdir"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
- set oflags "-env $dbenv -create -mode 0644 $opts $method"
+ set oflags "-env $dbenv -pagesize 8192 -create -mode 0644 $opts $method"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
diff --git a/bdb/test/recd010.tcl b/bdb/test/recd010.tcl
index 4fd1aefbb60..2549e03a2c0 100644
--- a/bdb/test/recd010.tcl
+++ b/bdb/test/recd010.tcl
@@ -1,20 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd010.tcl,v 1.14 2000/12/11 17:24:55 sue Exp $
+# $Id: recd010.tcl,v 1.19 2002/03/15 19:05:07 sue Exp $
#
-# Recovery Test 10.
-# Test stability of btree duplicates across btree off-page dup splits
-# and reverse splits and across recovery.
+# TEST recd010
+# TEST Test stability of btree duplicates across btree off-page dup splits
+# TEST and reverse splits and across recovery.
proc recd010 { method {select 0} args} {
- global fixed_len
- global kvals
- global kvals_dups
- source ./include.tcl
-
- if { [is_dbtree $method] != 1 && [is_ddbtree $method] != 1} {
+ if { [is_btree $method] != 1 } {
puts "Recd010 skipping for method $method."
return
}
@@ -24,11 +19,24 @@ proc recd010 { method {select 0} args} {
puts "Recd010: skipping for specific pagesizes"
return
}
+ set largs $args
+ append largs " -dup "
+ recd010_main $method $select $largs
+ append largs " -dupsort "
+ recd010_main $method $select $largs
+}
- set opts [convert_args $method $args]
+proc recd010_main { method select largs } {
+ global fixed_len
+ global kvals
+ global kvals_dups
+ source ./include.tcl
+
+
+ set opts [convert_args $method $largs]
set method [convert_method $method]
- puts "\tRecd010 ($opts): Test duplicates across splits and recovery"
+ puts "Recd010 ($opts): Test duplicates across splits and recovery"
set testfile recd010.db
env_cleanup $testdir
@@ -41,10 +49,10 @@ proc recd010 { method {select 0} args} {
set data "data"
set key "recd010_key"
- puts "\tRecd010.a: Create $method environment and database."
+ puts "\tRecd010.a: Create environment and database."
set flags "-create -txn -home $testdir"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
@@ -69,17 +77,17 @@ proc recd010 { method {select 0} args} {
return
}
set rlist {
- { {recd010_split DB TXNID 1 $method 2 $mkeys}
+ { {recd010_split DB TXNID 1 2 $mkeys}
"Recd010.c: btree split 2 large dups"}
- { {recd010_split DB TXNID 0 $method 2 $mkeys}
+ { {recd010_split DB TXNID 0 2 $mkeys}
"Recd010.d: btree reverse split 2 large dups"}
- { {recd010_split DB TXNID 1 $method 10 $mkeys}
+ { {recd010_split DB TXNID 1 10 $mkeys}
"Recd010.e: btree split 10 dups"}
- { {recd010_split DB TXNID 0 $method 10 $mkeys}
+ { {recd010_split DB TXNID 0 10 $mkeys}
"Recd010.f: btree reverse split 10 dups"}
- { {recd010_split DB TXNID 1 $method 100 $mkeys}
+ { {recd010_split DB TXNID 1 100 $mkeys}
"Recd010.g: btree split 100 dups"}
- { {recd010_split DB TXNID 0 $method 100 $mkeys}
+ { {recd010_split DB TXNID 0 100 $mkeys}
"Recd010.h: btree reverse split 100 dups"}
}
@@ -100,7 +108,7 @@ proc recd010 { method {select 0} args} {
op_recover commit $testdir $env_cmd $testfile $cmd $msg
recd010_check $testdir $testfile $opts commit $reverse $firstkeys
}
- puts "\tRecd010.e: Verify db_printlog can read logfile"
+ puts "\tRecd010.i: Verify db_printlog can read logfile"
set tmpfile $testdir/printlog.out
set stat [catch {exec $util_path/db_printlog -h $testdir \
> $tmpfile} ret]
@@ -178,7 +186,14 @@ proc recd010_check { tdir testfile opts op reverse origdups } {
for {set d [$dbc get -set $key$ki]} { [llength $d] != 0 } {
set d [$dbc get -nextdup]} {
set thisdata [lindex [lindex $d 0] 1]
- error_check_good dup_check $thisdata $data$datacnt
+ if { $datacnt < 10 } {
+ set pdata $data.$ki.00$datacnt
+ } elseif { $datacnt < 100 } {
+ set pdata $data.$ki.0$datacnt
+ } else {
+ set pdata $data.$ki.$datacnt
+ }
+ error_check_good dup_check $thisdata $pdata
incr datacnt
}
error_check_good dup_count $datacnt $numdups
@@ -202,7 +217,7 @@ proc recd010_check { tdir testfile opts op reverse origdups } {
error_check_good db_close [$db close] 0
}
-proc recd010_split { db txn split method nkeys mkeys } {
+proc recd010_split { db txn split nkeys mkeys } {
global errorCode
global kvals
global kvals_dups
@@ -220,7 +235,14 @@ proc recd010_split { db txn split method nkeys mkeys } {
"\tRecd010_split: Add $nkeys keys, with $numdups duplicates each to force split."
for {set k 0} { $k < $nkeys } { incr k } {
for {set i 0} { $i < $numdups } { incr i } {
- set ret [$db put -txn $txn $key$k $data$i]
+ if { $i < 10 } {
+ set pdata $data.$k.00$i
+ } elseif { $i < 100 } {
+ set pdata $data.$k.0$i
+ } else {
+ set pdata $data.$k.$i
+ }
+ set ret [$db put -txn $txn $key$k $pdata]
error_check_good dbput:more $ret 0
}
}
diff --git a/bdb/test/recd011.tcl b/bdb/test/recd011.tcl
index a6fc269741b..74108a30650 100644
--- a/bdb/test/recd011.tcl
+++ b/bdb/test/recd011.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd011.tcl,v 11.13 2000/12/06 17:09:54 sue Exp $
+# $Id: recd011.tcl,v 11.19 2002/02/25 16:44:26 sandstro Exp $
#
-# Recovery Test 11.
-# Test recovery to a specific timestamp.
+# TEST recd011
+# TEST Verify that recovery to a specific timestamp works.
proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
source ./include.tcl
@@ -29,11 +29,11 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
puts "\tRecd0$tnum.a: Create environment and database."
set flags "-create -txn -home $testdir"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
- set oflags "-env $dbenv -create -mode 0644 $args $omethod"
+ set oflags "-auto_commit -env $dbenv -create -mode 0644 $args $omethod"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -70,11 +70,11 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
# Now, loop through and recover to each timestamp, verifying the
# expected increment.
puts "\tRecd0$tnum.c: Recover to each timestamp and check."
- for { set i 0 } { $i <= $niter } { incr i } {
+ for { set i $niter } { $i >= 0 } { incr i -1 } {
# Run db_recover.
- berkdb debug_check
set t [clock format $timeof($i) -format "%y%m%d%H%M.%S"]
+ berkdb debug_check
set ret [catch {exec $util_path/db_recover -h $testdir -t $t} r]
error_check_good db_recover($i,$t) $ret 0
@@ -91,7 +91,8 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
# Finally, recover to a time well before the first timestamp
# and well after the last timestamp. The latter should
- # be just like the last timestamp; the former should fail.
+ # be just like the timestamp of the last test performed;
+ # the former should fail.
puts "\tRecd0$tnum.d: Recover to before the first timestamp."
set t [clock format [expr $timeof(0) - 1000] -format "%y%m%d%H%M.%S"]
set ret [catch {exec $util_path/db_recover -h $testdir -t $t} r]
@@ -108,8 +109,8 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
error_check_good db_open(after) [is_valid_db $db] TRUE
set dbt [$db get $key]
- set datum [lindex [lindex $dbt 0] 1]
+ set datum2 [lindex [lindex $dbt 0] 1]
- error_check_good timestamp_recover $datum [pad_data $method $niter]
+ error_check_good timestamp_recover $datum2 $datum
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/recd012.tcl b/bdb/test/recd012.tcl
index 19dd7b011d1..8231e648588 100644
--- a/bdb/test/recd012.tcl
+++ b/bdb/test/recd012.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd012.tcl,v 11.14 2000/12/11 17:24:55 sue Exp $
+# $Id: recd012.tcl,v 11.27 2002/05/10 00:48:07 margo Exp $
#
-# Recovery Test 12.
-# Test recovery handling of file opens and closes.
+# TEST recd012
+# TEST Test of log file ID management. [#2288]
+# TEST Test recovery handling of file opens and closes.
proc recd012 { method {start 0} \
{niter 49} {noutiter 25} {niniter 100} {ndbs 5} args } {
source ./include.tcl
@@ -24,9 +25,8 @@ proc recd012 { method {start 0} \
puts "Recd012: skipping for specific pagesizes"
return
}
-
+
for { set i $start } { $i <= $niter } { incr i } {
-
env_cleanup $testdir
# For repeatability, we pass in the iteration number
@@ -35,13 +35,13 @@ proc recd012 { method {start 0} \
# This lets us re-run a potentially failing iteration
# without having to start from the beginning and work
# our way to it.
- #
+ #
# The number of databases ranges from 4 to 8 and is
# a function of $niter
-# set ndbs [expr ($i % 5) + 4]
-
+ # set ndbs [expr ($i % 5) + 4]
+
recd012_body \
- $method $ndbs $i $noutiter $niniter $pagesize $tnum $args
+ $method $ndbs $i $noutiter $niniter $pagesize $tnum $args
}
}
@@ -55,8 +55,15 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
puts "\tRecd0$tnum $method ($largs): Iteration $iter"
puts "\t\tRecd0$tnum.a: Create environment and $ndbs databases."
+ # We run out of lockers during some of the recovery runs, so
+ # we need to make sure that we specify a DB_CONFIG that will
+ # give us enough lockers.
+ set f [open $testdir/DB_CONFIG w]
+ puts $f "set_lk_max_lockers 5000"
+ close $f
+
set flags "-create -txn -home $testdir"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
error_check_good env_remove [berkdb envremove -home $testdir] 0
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
@@ -67,9 +74,12 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
# Initialize database that keeps track of number of open files (so
# we don't run out of descriptors).
set ofname of.db
- set ofdb [berkdb_open -env $dbenv\
+ set txn [$dbenv txn]
+ error_check_good open_txn_begin [is_valid_txn $txn $dbenv] TRUE
+ set ofdb [berkdb_open -env $dbenv -txn $txn\
-create -dup -mode 0644 -btree -pagesize 512 $ofname]
error_check_good of_open [is_valid_db $ofdb] TRUE
+ error_check_good open_txn_commit [$txn commit] 0
set oftxn [$dbenv txn]
error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
error_check_good of_put [$ofdb put -txn $oftxn $recd012_ofkey 1] 0
@@ -80,9 +90,10 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
# Create ndbs databases to work in, and a file listing db names to
# pick from.
- set f [open TESTDIR/dblist w]
- set oflags \
- "-env $dbenv -create -mode 0644 -pagesize $psz $largs $omethod"
+ set f [open $testdir/dblist w]
+
+ set oflags "-auto_commit -env $dbenv \
+ -create -mode 0644 -pagesize $psz $largs $omethod"
for { set i 0 } { $i < $ndbs } { incr i } {
# 50-50 chance of being a subdb, unless we're a queue.
if { [berkdb random_int 0 1] || [is_queue $method] } {
@@ -96,18 +107,17 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
set db [eval berkdb_open $oflags $dbname]
error_check_good db($i) [is_valid_db $db] TRUE
error_check_good db($i)_close [$db close] 0
- }
+ }
close $f
-
error_check_good env_close [$dbenv close] 0
-
+
# Now we get to the meat of things. Our goal is to do some number
# of opens, closes, updates, and shutdowns (simulated here by a
# close of all open handles and a close/reopen of the environment,
# with or without an envremove), matching the regular expression
#
# ((O[OUC]+S)+R+V)
- #
+ #
# We'll repeat the inner + a random number up to $niniter times,
# and the outer + a random number up to $noutiter times.
#
@@ -116,23 +126,22 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
# all handles properly. The environment will be left lying around
# before we run recovery 50% of the time.
set out [berkdb random_int 1 $noutiter]
- puts "\t\tRecd0$tnum.b: Performing $out recoveries of up to $niniter\
- ops."
+ puts \
+ "\t\tRecd0$tnum.b: Performing $out recoveries of up to $niniter ops."
for { set i 0 } { $i < $out } { incr i } {
set child [open "|$tclsh_path" w]
-
- # For performance, don't source everything,
+
+ # For performance, don't source everything,
# just what we'll need.
puts $child "load $tcllib"
puts $child "set fixed_len $fixed_len"
- puts $child "source ../test/testutils.tcl"
- puts $child "source ../test/recd0$tnum.tcl"
+ puts $child "source $src_root/test/testutils.tcl"
+ puts $child "source $src_root/test/recd0$tnum.tcl"
set rnd [expr $iter * 10000 + $i * 100 + $rand_init]
# Go.
- # puts "recd012_dochild {$env_cmd} $rnd $i $niniter\
- # $ndbs $tnum $method $ofname $largs"
+ berkdb debug_check
puts $child "recd012_dochild {$env_cmd} $rnd $i $niniter\
$ndbs $tnum $method $ofname $largs"
close $child
@@ -140,35 +149,35 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
# Run recovery 0-3 times.
set nrecs [berkdb random_int 0 3]
for { set j 0 } { $j < $nrecs } { incr j } {
+ berkdb debug_check
set ret [catch {exec $util_path/db_recover \
-h $testdir} res]
- if { $ret != 0 } {
+ if { $ret != 0 } {
puts "FAIL: db_recover returned with nonzero\
exit status, output as follows:"
file mkdir /tmp/12out
set fd [open /tmp/12out/[pid] w]
- puts $fd $res
+ puts $fd $res
close $fd
}
error_check_good recover($j) $ret 0
}
-
}
- # Run recovery one final time; it doesn't make sense to
+ # Run recovery one final time; it doesn't make sense to
# check integrity if we do not.
set ret [catch {exec $util_path/db_recover -h $testdir} res]
- if { $ret != 0 } {
+ if { $ret != 0 } {
puts "FAIL: db_recover returned with nonzero\
exit status, output as follows:"
- puts $res
+ puts $res
}
# Make sure each datum is the correct filename.
puts "\t\tRecd0$tnum.c: Checking data integrity."
- set dbenv [berkdb env -create -private -home $testdir]
+ set dbenv [berkdb_env -create -private -home $testdir]
error_check_good env_open_integrity [is_valid_env $dbenv] TRUE
- set f [open TESTDIR/dblist r]
+ set f [open $testdir/dblist r]
set i 0
while { [gets $f dbinfo] > 0 } {
set db [eval berkdb_open -env $dbenv $dbinfo]
@@ -188,21 +197,21 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
close $f
error_check_good env_close_integrity [$dbenv close] 0
-
# Verify
- error_check_good verify [verify_dir $testdir "\t\tRecd0$tnum.d: "] 0
+ error_check_good verify \
+ [verify_dir $testdir "\t\tRecd0$tnum.d: " 0 0 1] 0
}
-
proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
ofname args } {
global recd012_ofkey
+ source ./include.tcl
if { [is_record_based $method] } {
set keybase ""
} else {
set keybase .[repeat abcdefghijklmnopqrstuvwxyz 4]
}
-
+
# Initialize our random number generator, repeatably based on an arg.
berkdb srand $rnd
@@ -212,7 +221,11 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
# Find out how many databases appear to be open in the log--we
# don't want recovery to run out of filehandles.
- set ofdb [berkdb_open -env $dbenv $ofname]
+ set txn [$dbenv txn]
+ error_check_good child_txn_begin [is_valid_txn $txn $dbenv] TRUE
+ set ofdb [berkdb_open -env $dbenv -txn $txn $ofname]
+ error_check_good child_txn_commit [$txn commit] 0
+
set oftxn [$dbenv txn]
error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
set dbt [$ofdb get -txn $oftxn $recd012_ofkey]
@@ -222,14 +235,14 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
error_check_good of_commit [$oftxn commit] 0
# Read our dbnames
- set f [open TESTDIR/dblist r]
+ set f [open $testdir/dblist r]
set i 0
while { [gets $f dbname($i)] > 0 } {
incr i
}
close $f
- # We now have $ndbs extant databases.
+ # We now have $ndbs extant databases.
# Open one of them, just to get us started.
set opendbs {}
set oflags "-env $dbenv $args"
@@ -254,14 +267,13 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
set num_open [llength $opendbs]
if { $num_open == 0 } {
# If none are open, do an open first.
-
recd012_open
}
set n [berkdb random_int 0 [expr $num_open - 1]]
set pair [lindex $opendbs $n]
set udb [lindex $pair 0]
set uname [lindex $pair 1]
-
+
set key [berkdb random_int 1000 1999]$keybase
set data [chop_data $method $uname]
error_check_good put($uname,$udb,$key,$data) \
@@ -273,12 +285,11 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
[$curtxn commit] 0
set curtxn [$dbenv txn]
error_check_good txn_reopen \
- [is_valid_txn $curtxn $dbenv] TRUE
+ [is_valid_txn $curtxn $dbenv] TRUE
}
}
2 {
# Close.
-
if { [llength $opendbs] == 0 } {
# If none are open, open instead of closing.
recd012_open
@@ -286,28 +297,26 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
}
# Commit curtxn first, lest we self-deadlock.
- error_check_good txn_recommit \
- [$curtxn commit] 0
+ error_check_good txn_recommit [$curtxn commit] 0
# Do it.
set which [berkdb random_int 0 \
[expr [llength $opendbs] - 1]]
-
+
set db [lindex [lindex $opendbs $which] 0]
error_check_good db_choice [is_valid_db $db] TRUE
global errorCode errorInfo
error_check_good db_close \
[[lindex [lindex $opendbs $which] 0] close] 0
+
set opendbs [lreplace $opendbs $which $which]
incr nopenfiles -1
-
-
+
# Reopen txn.
set curtxn [$dbenv txn]
error_check_good txn_reopen \
[is_valid_txn $curtxn $dbenv] TRUE
-
}
}
@@ -335,12 +344,12 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
[$ofdb put -txn $oftxn $recd012_ofkey $nopenfiles] 0
error_check_good of_commit [$oftxn commit] 0
error_check_good ofdb_close [$ofdb close] 0
-}
+}
proc recd012_open { } {
- # This is basically an inline and has to modify curtxn,
+ # This is basically an inline and has to modify curtxn,
# so use upvars.
- upvar curtxn curtxn
+ upvar curtxn curtxn
upvar ndbs ndbs
upvar dbname dbname
upvar dbenv dbenv
@@ -361,21 +370,21 @@ proc recd012_open { } {
# Do it.
set which [berkdb random_int 0 [expr $ndbs - 1]]
- set db [eval berkdb_open \
- $oflags $dbname($which)]
+
+ set db [eval berkdb_open -auto_commit $oflags $dbname($which)]
+
lappend opendbs [list $db $dbname($which)]
# Reopen txn.
set curtxn [$dbenv txn]
- error_check_good txn_reopen \
- [is_valid_txn $curtxn $dbenv] TRUE
+ error_check_good txn_reopen [is_valid_txn $curtxn $dbenv] TRUE
incr nopenfiles
}
# Update the database containing the number of files that db_recover has
# to contend with--we want to avoid letting it run out of file descriptors.
-# We do this by keeping track of the number of unclosed opens since the
+# We do this by keeping track of the number of unclosed opens since the
# checkpoint before last.
# $recd012_ofkey stores this current value; the two dups available
# at $recd012_ofckptkey store the number of opens since the last checkpoint
@@ -399,7 +408,7 @@ proc recd012_nopenfiles_ckpt { env db nopenfiles } {
error_check_good del [$dbc del] 0
set nopenfiles [expr $nopenfiles - $discard]
-
+
# Get the next ckpt value
set dbt [$dbc get -nextdup]
error_check_good set2 [llength $dbt] 1
@@ -410,10 +419,10 @@ proc recd012_nopenfiles_ckpt { env db nopenfiles } {
# Put this new number at the end of the dup set.
error_check_good put [$dbc put -keylast $recd012_ofckptkey $sincelast] 0
-
+
# We should never deadlock since we're the only one in this db.
error_check_good dbc_close [$dbc close] 0
- error_check_good txn_commit [$txn commit] 0
+ error_check_good txn_commit [$txn commit] 0
return $nopenfiles
}
diff --git a/bdb/test/recd013.tcl b/bdb/test/recd013.tcl
index d134d487f1e..e08654f34e0 100644
--- a/bdb/test/recd013.tcl
+++ b/bdb/test/recd013.tcl
@@ -1,22 +1,22 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd013.tcl,v 11.10 2000/12/11 17:24:55 sue Exp $
+# $Id: recd013.tcl,v 11.18 2002/02/25 16:44:27 sandstro Exp $
#
-# Recovery Test 13.
-# Smoke test of aborted cursor adjustments.
+# TEST recd013
+# TEST Test of cursor adjustment on child transaction aborts. [#2373]
#
# XXX
# Other tests that cover more specific variants of the same issue
# are in the access method tests for now. This is probably wrong; we
# put this one here because they're closely based on and intertwined
# with other, non-transactional cursor stability tests that are among
-# the access method tests, and because we need at least one test to
+# the access method tests, and because we need at least one test to
# fit under recd and keep logtrack from complaining. We'll sort out the mess
# later; the important thing, for now, is that everything that needs to gets
-# tested. (This really shouldn't be under recd at all, since it doesn't
+# tested. (This really shouldn't be under recd at all, since it doesn't
# run recovery!)
proc recd013 { method { nitems 100 } args } {
source ./include.tcl
@@ -48,11 +48,12 @@ proc recd013 { method { nitems 100 } args } {
Create environment, database, and parent transaction."
set flags "-create -txn -home $testdir"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
set env [eval $env_cmd]
error_check_good dbenv [is_valid_env $env] TRUE
- set oflags "-env $env -create -mode 0644 -pagesize $pgsz $args $omethod"
+ set oflags \
+ "-auto_commit -env $env -create -mode 0644 -pagesize $pgsz $args $omethod"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -63,19 +64,44 @@ proc recd013 { method { nitems 100 } args } {
for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
set key $keybase$i
set data [chop_data $method $i$alphabet]
+
+ # First, try to put the item in a child transaction,
+ # then abort and verify all the cursors we've done up until
+ # now.
+ set ctxn [$env txn -parent $txn]
+ error_check_good child_txn($i) [is_valid_txn $ctxn $env] TRUE
+ error_check_good fake_put($i) [$db put -txn $ctxn $key $data] 0
+ error_check_good ctxn_abort($i) [$ctxn abort] 0
+ for { set j 1 } { $j < $i } { incr j 2 } {
+ error_check_good dbc_get($j) [$dbc($j) get -current] \
+ [list [list $keybase$j \
+ [pad_data $method $j$alphabet]]]
+ }
+
+ # Then put for real.
error_check_good init_put($i) [$db put -txn $txn $key $data] 0
+
+ # Set a cursor of the parent txn to each item.
+ set dbc($i) [$db cursor -txn $txn]
+ error_check_good dbc_getset($i) \
+ [$dbc($i) get -set $key] \
+ [list [list $keybase$i [pad_data $method $i$alphabet]]]
+
+ # And verify all the cursors, including the one we just
+ # created.
+ for { set j 1 } { $j <= $i } { incr j 2 } {
+ error_check_good dbc_get($j) [$dbc($j) get -current] \
+ [list [list $keybase$j \
+ [pad_data $method $j$alphabet]]]
+ }
}
- error_check_good init_txn_commit [$txn commit] 0
- # Create an initial txn; set a cursor of that txn to each item.
- set txn [$env txn]
- error_check_good txn [is_valid_txn $txn $env] TRUE
+ puts "\t\tRecd0$tnum.a.1: Verify cursor stability after init."
for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
- set dbc($i) [$db cursor -txn $txn]
- error_check_good dbc_getset($i) [$dbc($i) get -set $keybase$i] \
+ error_check_good dbc_get($i) [$dbc($i) get -current] \
[list [list $keybase$i [pad_data $method $i$alphabet]]]
}
-
+
puts "\tRecd0$tnum.b: Put test."
puts "\t\tRecd0$tnum.b.1: Put items."
set ctxn [$env txn -parent $txn]
@@ -99,7 +125,7 @@ proc recd013 { method { nitems 100 } args } {
error_check_good curs_close [$curs close] 0
}
}
-
+
puts "\t\tRecd0$tnum.b.2: Verify cursor stability after abort."
error_check_good ctxn_abort [$ctxn abort] 0
@@ -122,7 +148,7 @@ proc recd013 { method { nitems 100 } args } {
error_check_good db_verify \
[verify_dir $testdir "\t\tRecd0$tnum.b.3: "] 0
- # Now put back all the even records, this time in the parent.
+ # Now put back all the even records, this time in the parent.
# Commit and re-begin the transaction so we can abort and
# get back to a nice full database.
for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
@@ -135,9 +161,9 @@ proc recd013 { method { nitems 100 } args } {
error_check_good txn [is_valid_txn $txn $env] TRUE
# Delete test. Set a cursor to each record. Delete the even ones
- # in the parent and check cursor stability. Then open a child
+ # in the parent and check cursor stability. Then open a child
# transaction, and delete the odd ones. Verify that the database
- # is empty
+ # is empty.
puts "\tRecd0$tnum.c: Delete test."
unset dbc
@@ -149,8 +175,9 @@ proc recd013 { method { nitems 100 } args } {
error_check_good dbc_getset($i) [$dbc($i) get -set $keybase$i] \
[list [list $keybase$i [pad_data $method $i$alphabet]]]
}
-
- puts "\t\tRecd0$tnum.c.1: Delete even items in parent txn."
+
+ puts "\t\tRecd0$tnum.c.1: Delete even items in child txn and abort."
+
if { [is_rrecno $method] != 1 } {
set init 2
set bound [expr 2 * $nitems]
@@ -162,9 +189,25 @@ proc recd013 { method { nitems 100 } args } {
set bound [expr $nitems + 1]
set step 1
}
+
+ set ctxn [$env txn -parent $txn]
for { set i $init } { $i <= $bound } { incr i $step } {
- error_check_good del($i) [$db del -txn $txn $keybase$i] 0
+ error_check_good del($i) [$db del -txn $ctxn $keybase$i] 0
}
+ error_check_good ctxn_abort [$ctxn abort] 0
+
+ # Verify that no items are deleted.
+ for { set i 1 } { $i <= 2 * $nitems } { incr i } {
+ error_check_good dbc_get($i) [$dbc($i) get -current] \
+ [list [list $keybase$i [pad_data $method $i$alphabet]]]
+ }
+
+ puts "\t\tRecd0$tnum.c.2: Delete even items in child txn and commit."
+ set ctxn [$env txn -parent $txn]
+ for { set i $init } { $i <= $bound } { incr i $step } {
+ error_check_good del($i) [$db del -txn $ctxn $keybase$i] 0
+ }
+ error_check_good ctxn_commit [$ctxn commit] 0
# Verify that even items are deleted and odd items are not.
for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
@@ -181,10 +224,10 @@ proc recd013 { method { nitems 100 } args } {
[list [list "" ""]]
}
- puts "\t\tRecd0$tnum.c.2: Delete odd items in child txn."
+ puts "\t\tRecd0$tnum.c.3: Delete odd items in child txn."
set ctxn [$env txn -parent $txn]
-
+
for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
if { [is_rrecno $method] != 1 } {
set j $i
@@ -196,14 +239,14 @@ proc recd013 { method { nitems 100 } args } {
}
error_check_good del($i) [$db del -txn $ctxn $keybase$j] 0
}
-
+
# Verify that everyone's deleted.
for { set i 1 } { $i <= 2 * $nitems } { incr i } {
error_check_good get_deleted($i) \
[llength [$db get -txn $ctxn $keybase$i]] 0
}
- puts "\t\tRecd0$tnum.c.3: Verify cursor stability after abort."
+ puts "\t\tRecd0$tnum.c.4: Verify cursor stability after abort."
error_check_good ctxn_abort [$ctxn abort] 0
# Verify that even items are deleted and odd items are not.
@@ -229,7 +272,7 @@ proc recd013 { method { nitems 100 } args } {
# Sync and verify.
error_check_good db_sync [$db sync] 0
error_check_good db_verify \
- [verify_dir $testdir "\t\tRecd0$tnum.c.4: "] 0
+ [verify_dir $testdir "\t\tRecd0$tnum.c.5: "] 0
puts "\tRecd0$tnum.d: Clean up."
error_check_good txn_commit [$txn commit] 0
@@ -238,7 +281,7 @@ proc recd013 { method { nitems 100 } args } {
error_check_good verify_dir \
[verify_dir $testdir "\t\tRecd0$tnum.d.1: "] 0
- if { $log_log_record_types == 1 } {
+ if { $log_log_record_types == 1 } {
logtrack_read $testdir
}
}
diff --git a/bdb/test/recd014.tcl b/bdb/test/recd014.tcl
index 83b3920de9b..6796341dca2 100644
--- a/bdb/test/recd014.tcl
+++ b/bdb/test/recd014.tcl
@@ -1,16 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: recd014.tcl,v 1.9 2001/01/11 17:16:04 sue Exp $
+# $Id: recd014.tcl,v 1.19 2002/08/15 19:21:24 sandstro Exp $
#
-# Recovery Test 14.
-# This is a recovery test for create/delete of queue extents. We have
-# hooks in the database so that we can abort the process at various
-# points and make sure that the extent file does or does not exist. We
-# then need to recover and make sure the file is correctly existing
-# or not, as the case may be.
+# TEST recd014
+# TEST This is a recovery test for create/delete of queue extents. We
+# TEST then need to recover and make sure the file is correctly existing
+# TEST or not, as the case may be.
proc recd014 { method args} {
global fixed_len
source ./include.tcl
@@ -51,7 +49,7 @@ proc recd014 { method args} {
set flags "-create -txn -home $testdir"
puts "\tRecd014.a: creating environment"
- set env_cmd "berkdb env $flags"
+ set env_cmd "berkdb_env $flags"
puts "\tRecd014.b: Create test commit"
ext_recover_create $testdir $env_cmd $omethod \
@@ -61,21 +59,14 @@ proc recd014 { method args} {
$opts $testfile abort
puts "\tRecd014.c: Consume test commit"
- ext_recover_delete $testdir $env_cmd $omethod \
- $opts $testfile consume commit
+ ext_recover_consume $testdir $env_cmd $omethod \
+ $opts $testfile commit
puts "\tRecd014.c: Consume test abort"
- ext_recover_delete $testdir $env_cmd $omethod \
- $opts $testfile consume abort
-
- puts "\tRecd014.d: Delete test commit"
- ext_recover_delete $testdir $env_cmd $omethod \
- $opts $testfile delete commit
- puts "\tRecd014.d: Delete test abort"
- ext_recover_delete $testdir $env_cmd $omethod \
- $opts $testfile delete abort
+ ext_recover_consume $testdir $env_cmd $omethod \
+ $opts $testfile abort
set fixed_len $orig_fixed_len
- puts "\tRecd014.e: Verify db_printlog can read logfile"
+ puts "\tRecd014.d: Verify db_printlog can read logfile"
set tmpfile $testdir/printlog.out
set stat [catch {exec $util_path/db_printlog -h $testdir \
> $tmpfile} ret]
@@ -105,7 +96,11 @@ proc ext_recover_create { dir env_cmd method opts dbfile txncmd } {
set t [$env txn]
error_check_good txn_begin [is_valid_txn $t $env] TRUE
- set ret [catch {eval {berkdb_open} $oflags} db]
+ set ret [catch {eval {berkdb_open} -txn $t $oflags} db]
+ error_check_good txn_commit [$t commit] 0
+
+ set t [$env txn]
+ error_check_good txn_begin [is_valid_txn $t $env] TRUE
#
# The command to execute to create an extent is a put.
@@ -123,7 +118,7 @@ proc ext_recover_create { dir env_cmd method opts dbfile txncmd } {
puts "\t\tSyncing"
error_check_good db_sync [$db sync] 0
- catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
+ catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
copy_extent_file $dir $dbfile afterop
error_check_good txn_$txncmd:$t [$t $txncmd] 0
@@ -149,7 +144,10 @@ proc ext_recover_create { dir env_cmd method opts dbfile txncmd } {
catch { file copy -force $dir/$dbfile $init_file } res
copy_extent_file $dir $dbfile init
}
+ set t [$env txn]
+ error_check_good txn_begin [is_valid_txn $t $env] TRUE
error_check_good db_close [$db close] 0
+ error_check_good txn_commit [$t commit] 0
error_check_good env_close [$env close] 0
#
@@ -241,7 +239,7 @@ proc ext_create_check { dir txncmd init_file dbfile oflags putrecno } {
#
error_check_good \
diff(initial,post-recover2):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff "-dar" $init_file $dir $dbfile] 0
} else {
#
# Operation aborted. The file is there, but make
@@ -255,8 +253,7 @@ proc ext_create_check { dir txncmd init_file dbfile oflags putrecno } {
}
}
-
-proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
+proc ext_recover_consume { dir env_cmd method opts dbfile txncmd} {
global log_log_record_types
global alphabet
source ./include.tcl
@@ -269,55 +266,52 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
env_cleanup $dir
# Open the environment and set the copy/abort locations
set env [eval $env_cmd]
-
- set oflags "-create $method -mode 0644 -pagesize 512 \
+
+ set oflags "-create -auto_commit $method -mode 0644 -pagesize 512 \
-env $env $opts $dbfile"
-
+
#
# Open our db, add some data, close and copy as our
# init file.
#
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
-
+
set extnum 0
set data [chop_data $method [replicate $alphabet 512]]
set txn [$env txn]
error_check_good txn_begin [is_valid_txn $txn $env] TRUE
- set putrecno [$db put -append $data]
+ set putrecno [$db put -txn $txn -append $data]
error_check_good db_put $putrecno 1
error_check_good commit [$txn commit] 0
error_check_good db_close [$db close] 0
-
+
puts "\t\tExecuting command"
-
+
set init_file $dir/$dbfile.init
catch { file copy -force $dir/$dbfile $init_file } res
copy_extent_file $dir $dbfile init
-
+
#
# If we don't abort, then we expect success.
# If we abort, we expect no file removed until recovery is run.
#
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
-
+
set t [$env txn]
error_check_good txn_begin [is_valid_txn $t $env] TRUE
- if { [string compare $op "delete"] == 0 } {
- set dbcmd "$db del -txn $t $putrecno"
- } else {
- set dbcmd "$db get -txn $t -consume"
- }
+ set dbcmd "$db get -txn $t -consume"
set ret [eval $dbcmd]
error_check_good db_sync [$db sync] 0
- catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
+ catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
copy_extent_file $dir $dbfile afterop
error_check_good txn_$txncmd:$t [$t $txncmd] 0
+ error_check_good db_sync [$db sync] 0
set dbq [make_ext_filename $dir $dbfile $extnum]
if {$txncmd == "abort"} {
#
@@ -330,20 +324,10 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
# Since we aborted the txn, we should be able
# to get to our original entry.
#
- error_check_good post$op.1 [file exists $dbq] 1
-
- set xdb [eval {berkdb_open} $oflags]
- error_check_good db_open [is_valid_db $xdb] TRUE
- set kd [$xdb get $putrecno]
- set key [lindex [lindex $kd 0] 0]
- error_check_good dbget_key $key $putrecno
- set retdata [lindex [lindex $kd 0] 1]
- error_check_good dbget_data $data $retdata
- error_check_good db_close [$xdb close] 0
-
+ error_check_good postconsume.1 [file exists $dbq] 1
error_check_good \
- diff(init,post$op.2):diff($init_file,$dir/$dbfile)\
- [dbdump_diff $init_file $dir/$dbfile] 0
+ diff(init,postconsume.2):diff($init_file,$dir/$dbfile)\
+ [dbdump_diff "-dar" $init_file $dir $dbfile] 0
} else {
#
# Operation was committed, verify it does
@@ -353,14 +337,8 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
#
# Check file existence. Consume operations remove
# the extent when we move off, which we should have
- # done. Delete operations won't remove the extent
- # until we run recovery.
- #
- if { [string compare $op "delete"] == 0 } {
- error_check_good ${op}_exists [file exists $dbq] 1
- } else {
- error_check_good ${op}_exists [file exists $dbq] 0
- }
+ # done.
+ error_check_good consume_exists [file exists $dbq] 0
}
error_check_good db_close [$db close] 0
error_check_good env_close [$env close] 0
@@ -384,7 +362,7 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
#
error_check_good \
diff(initial,post-recover1):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff "-dar" $init_file $dir $dbfile] 0
} else {
#
# Operation was committed, verify it does
@@ -396,7 +374,7 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
#
# Run recovery here. Re-do the operation.
- # Verify that the file doesn't exist
+ # Verify that the file doesn't exist
# (if we committed) or change (if we aborted)
# when we are done.
#
@@ -418,14 +396,14 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
#
error_check_good \
diff(initial,post-recover1):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff "-dar" $init_file $dir $dbfile] 0
} else {
#
# Operation was committed, verify it does
# not exist. Both operations should result
# in no file existing now that we've run recovery.
#
- error_check_good after_recover1 [file exists $dbq] 0
+ error_check_good after_recover2 [file exists $dbq] 0
}
#
@@ -456,12 +434,12 @@ proc ext_recover_delete { dir env_cmd method opts dbfile op txncmd} {
#
error_check_good \
diff(initial,post-recover2):diff($init_file,$dir/$dbfile) \
- [dbdump_diff $init_file $dir/$dbfile] 0
+ [dbdump_diff "-dar" $init_file $dir $dbfile] 0
} else {
#
# Operation was committed, verify it still does
# not exist.
#
- error_check_good after_recover2 [file exists $dbq] 0
+ error_check_good after_recover3 [file exists $dbq] 0
}
}
diff --git a/bdb/test/recd015.tcl b/bdb/test/recd015.tcl
new file mode 100644
index 00000000000..8c3ad612419
--- /dev/null
+++ b/bdb/test/recd015.tcl
@@ -0,0 +1,160 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd015.tcl,v 1.13 2002/09/05 17:23:06 sandstro Exp $
+#
+# TEST recd015
+# TEST This is a recovery test for testing lots of prepared txns.
+# TEST This test is to force the use of txn_recover to call with the
+# TEST DB_FIRST flag and then DB_NEXT.
+proc recd015 { method args } {
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ puts "Recd015: $method ($args) prepared txns test"
+
+ # Create the database and environment.
+
+ set numtxns 1
+ set testfile NULL
+
+ set env_cmd "berkdb_env -create -txn -home $testdir"
+ set msg "\tRecd015.a"
+ puts "$msg Simple test to prepare $numtxns txn "
+ foreach op { abort commit discard } {
+ env_cleanup $testdir
+ recd015_body $env_cmd $testfile $numtxns $msg $op
+ }
+
+ #
+ # Now test large numbers of prepared txns to test DB_NEXT
+ # on txn_recover.
+ #
+ set numtxns 250
+ set testfile recd015.db
+ set txnmax [expr $numtxns + 5]
+ #
+ # For this test we create our database ahead of time so that we
+ # don't need to send methods and args to the script.
+ #
+ env_cleanup $testdir
+ set env_cmd "berkdb_env -create -txn_max $txnmax -txn -home $testdir"
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $env] TRUE
+ set db [eval {berkdb_open -create} $omethod -env $env $args $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
+ error_check_good envclose [$env close] 0
+
+ set msg "\tRecd015.b"
+ puts "$msg Large test to prepare $numtxns txn "
+ foreach op { abort commit discard } {
+ recd015_body $env_cmd $testfile $numtxns $msg $op
+ }
+
+ set stat [catch {exec $util_path/db_printlog -h $testdir \
+ > $testdir/LOG } ret]
+ error_check_good db_printlog $stat 0
+ fileremove $testdir/LOG
+}
+
+proc recd015_body { env_cmd testfile numtxns msg op } {
+ source ./include.tcl
+
+ sentinel_init
+ set gidf $testdir/gidfile
+ fileremove -f $gidf
+ set pidlist {}
+ puts "$msg.0: Executing child script to prepare txns"
+ berkdb debug_check
+ set p [exec $tclsh_path $test_path/wrap.tcl recd15scr.tcl \
+ $testdir/recdout $env_cmd $testfile $gidf $numtxns &]
+
+ lappend pidlist $p
+ watch_procs $pidlist 5
+ set f1 [open $testdir/recdout r]
+ set r [read $f1]
+ puts $r
+ close $f1
+ fileremove -f $testdir/recdout
+
+ berkdb debug_check
+ puts -nonewline "$msg.1: Running recovery ... "
+ flush stdout
+ berkdb debug_check
+ set env [eval $env_cmd -recover]
+ error_check_good dbenv-recover [is_valid_env $env] TRUE
+ puts "complete"
+
+ puts "$msg.2: getting txns from txn_recover"
+ set txnlist [$env txn_recover]
+ error_check_good txnlist_len [llength $txnlist] $numtxns
+
+ set gfd [open $gidf r]
+ set i 0
+ while { [gets $gfd gid] != -1 } {
+ set gids($i) $gid
+ incr i
+ }
+ close $gfd
+ #
+ # Make sure we have as many as we expect
+ error_check_good num_gids $i $numtxns
+
+ set i 0
+ puts "$msg.3: comparing GIDs and $op txns"
+ foreach tpair $txnlist {
+ set txn [lindex $tpair 0]
+ set gid [lindex $tpair 1]
+ error_check_good gidcompare $gid $gids($i)
+ error_check_good txn:$op [$txn $op] 0
+ incr i
+ }
+ if { $op != "discard" } {
+ error_check_good envclose [$env close] 0
+ return
+ }
+ #
+ # If we discarded, now do it again and randomly resolve some
+ # until all txns are resolved.
+ #
+ puts "$msg.4: resolving/discarding txns"
+ set txnlist [$env txn_recover]
+ set len [llength $txnlist]
+ set opval(1) "abort"
+ set opcnt(1) 0
+ set opval(2) "commit"
+ set opcnt(2) 0
+ set opval(3) "discard"
+ set opcnt(3) 0
+ while { $len != 0 } {
+ set opicnt(1) 0
+ set opicnt(2) 0
+ set opicnt(3) 0
+ #
+ # Abort/commit or discard them randomly until
+ # all are resolved.
+ #
+ for { set i 0 } { $i < $len } { incr i } {
+ set t [lindex $txnlist $i]
+ set txn [lindex $t 0]
+ set newop [berkdb random_int 1 3]
+ set ret [$txn $opval($newop)]
+ error_check_good txn_$opval($newop):$i $ret 0
+ incr opcnt($newop)
+ incr opicnt($newop)
+ }
+# puts "$opval(1): $opicnt(1) Total: $opcnt(1)"
+# puts "$opval(2): $opicnt(2) Total: $opcnt(2)"
+# puts "$opval(3): $opicnt(3) Total: $opcnt(3)"
+
+ set txnlist [$env txn_recover]
+ set len [llength $txnlist]
+ }
+
+ error_check_good envclose [$env close] 0
+}
diff --git a/bdb/test/recd016.tcl b/bdb/test/recd016.tcl
new file mode 100644
index 00000000000..504aca09617
--- /dev/null
+++ b/bdb/test/recd016.tcl
@@ -0,0 +1,183 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd016.tcl,v 11.8 2002/09/05 17:23:07 sandstro Exp $
+#
+# TEST recd016
+# TEST This is a recovery test for testing running recovery while
+# TEST recovery is already running. While bad things may or may not
+# TEST happen, if recovery is then run properly, things should be correct.
+proc recd016 { method args } {
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ puts "Recd016: $method ($args) simultaneous recovery test"
+ puts "Recd016: Skipping; waiting on SR #6277"
+ return
+
+ # Create the database and environment.
+ set testfile recd016.db
+
+ #
+ # For this test we create our database ahead of time so that we
+ # don't need to send methods and args to the script.
+ #
+ cleanup $testdir NULL
+
+ #
+ # Use a smaller log to make more files and slow down recovery.
+ #
+ set gflags ""
+ set pflags ""
+ set log_max [expr 256 * 1024]
+ set nentries 10000
+ set nrec 6
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ set t4 $testdir/t4
+ set t5 $testdir/t5
+ # Since we are using txns, we need at least 1 lock per
+ # record (for queue). So set lock_max accordingly.
+ set lkmax [expr $nentries * 2]
+
+ puts "\tRecd016.a: Create environment and database"
+ set env_cmd "berkdb_env -create -log_max $log_max \
+ -lock_max $lkmax -txn -home $testdir"
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $env] TRUE
+ set db [eval {berkdb_open -create} \
+ $omethod -auto_commit -env $env $args $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set did [open $dict]
+ set abid [open $t4 w]
+
+ if { [is_record_based $method] == 1 } {
+ set checkfunc recd016_recno.check
+ append gflags " -recno"
+ } else {
+ set checkfunc recd016.check
+ }
+ puts "\tRecd016.b: put/get loop"
+ # Here is the loop where we put and get each key/data pair
+ set count 0
+ while { [gets $did str] != -1 && $count < $nentries } {
+ if { [is_record_based $method] == 1 } {
+ global kvals
+
+ set key [expr $count + 1]
+ if { 0xffffffff > 0 && $key > 0xffffffff } {
+ set key [expr $key - 0x100000000]
+ }
+ if { $key == 0 || $key - 0xffffffff == 1 } {
+ incr key
+ incr count
+ }
+ set kvals($key) [pad_data $method $str]
+ } else {
+ set key $str
+ set str [reverse $str]
+ }
+ #
+ # Start a transaction. Alternately abort and commit them.
+ # This will create a bigger log for recovery to collide.
+ #
+ set txn [$env txn]
+ set ret [eval \
+ {$db put} -txn $txn $pflags {$key [chop_data $method $str]}]
+ error_check_good put $ret 0
+
+ if {[expr $count % 2] == 0} {
+ set ret [$txn commit]
+ error_check_good txn_commit $ret 0
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_good commit_get \
+ $ret [list [list $key [pad_data $method $str]]]
+ } else {
+ set ret [$txn abort]
+ error_check_good txn_abort $ret 0
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_good abort_get [llength $ret] 0
+ puts $abid $key
+ }
+ incr count
+ }
+ close $did
+ close $abid
+ error_check_good dbclose [$db close] 0
+ error_check_good envclose [$env close] 0
+
+ set pidlist {}
+ puts "\tRecd016.c: Start up $nrec recovery processes at once"
+ for {set i 0} {$i < $nrec} {incr i} {
+ set p [exec $util_path/db_recover -h $testdir -c &]
+ lappend pidlist $p
+ }
+ watch_procs $pidlist 5
+ #
+ # Now that they are all done run recovery correctly
+ puts "\tRecd016.d: Run recovery process"
+ set stat [catch {exec $util_path/db_recover -h $testdir -c} result]
+ if { $stat == 1 } {
+ error "FAIL: Recovery error: $result."
+ }
+
+ puts "\tRecd016.e: Open, dump and check database"
+ # Now compare the keys to see if they match the dictionary (or ints)
+ if { [is_record_based $method] == 1 } {
+ set oid [open $t2 w]
+ for {set i 1} {$i <= $nentries} {incr i} {
+ set j $i
+ if { 0xffffffff > 0 && $j > 0xffffffff } {
+ set j [expr $j - 0x100000000]
+ }
+ if { $j == 0 } {
+ incr i
+ incr j
+ }
+ puts $oid $j
+ }
+ close $oid
+ } else {
+ set q q
+ filehead $nentries $dict $t2
+ }
+ filesort $t2 $t3
+ file rename -force $t3 $t2
+ filesort $t4 $t3
+ file rename -force $t3 $t4
+ fileextract $t2 $t4 $t3
+ file rename -force $t3 $t5
+
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ open_and_dump_file $testfile $env $t1 $checkfunc \
+ dump_file_direction "-first" "-next"
+ filesort $t1 $t3
+ error_check_good envclose [$env close] 0
+
+ error_check_good Recd016:diff($t5,$t3) \
+ [filecmp $t5 $t3] 0
+
+ set stat [catch {exec $util_path/db_printlog -h $testdir \
+ > $testdir/LOG } ret]
+ error_check_good db_printlog $stat 0
+ fileremove $testdir/LOG
+}
+
+# Check function for recd016; keys and data are identical
+proc recd016.check { key data } {
+ error_check_good "key/data mismatch" $data [reverse $key]
+}
+
+proc recd016_recno.check { key data } {
+ global kvals
+
+ error_check_good key"$key"_exists [info exists kvals($key)] 1
+ error_check_good "key/data mismatch, key $key" $data $kvals($key)
+}
diff --git a/bdb/test/recd017.tcl b/bdb/test/recd017.tcl
new file mode 100644
index 00000000000..9f8208c1b3e
--- /dev/null
+++ b/bdb/test/recd017.tcl
@@ -0,0 +1,151 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd017.tcl,v 11.4 2002/09/03 16:44:37 sue Exp $
+#
+# TEST recd017
+# TEST Test recovery and security. This is basically a watered
+# TEST down version of recd001 just to verify that encrypted environments
+# TEST can be recovered.
+proc recd017 { method {select 0} args} {
+ global fixed_len
+ global encrypt
+ global passwd
+ source ./include.tcl
+
+ set orig_fixed_len $fixed_len
+ set opts [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ puts "Recd017: $method operation/transaction tests"
+
+ # Create the database and environment.
+ env_cleanup $testdir
+
+ # The recovery tests were originally written to
+ # do a command, abort, do it again, commit, and then
+ # repeat the sequence with another command. Each command
+ # tends to require that the previous command succeeded and
+ # left the database a certain way. To avoid cluttering up the
+ # op_recover interface as well as the test code, we create two
+ # databases; one does abort and then commit for each op, the
+ # other does prepare, prepare-abort, and prepare-commit for each
+ # op. If all goes well, this allows each command to depend
+ # exactly one successful iteration of the previous command.
+ set testfile recd017.db
+ set testfile2 recd017-2.db
+
+ set flags "-create -encryptaes $passwd -txn -home $testdir"
+
+ puts "\tRecd017.a.0: creating environment"
+ set env_cmd "berkdb_env $flags"
+ convert_encrypt $env_cmd
+ set dbenv [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ #
+ # We need to create a database to get the pagesize (either
+ # the default or whatever might have been specified).
+ # Then remove it so we can compute fixed_len and create the
+ # real database.
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv -encrypt $opts $testfile"
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ set stat [$db stat]
+ #
+ # Compute the fixed_len based on the pagesize being used.
+ # We want the fixed_len to be 1/4 the pagesize.
+ #
+ set pg [get_pagesize $stat]
+ error_check_bad get_pagesize $pg -1
+ set fixed_len [expr $pg / 4]
+ error_check_good db_close [$db close] 0
+ error_check_good dbremove [berkdb dbremove -env $dbenv $testfile] 0
+
+ # Convert the args again because fixed_len is now real.
+ # Create the databases and close the environment.
+ # cannot specify db truncate in txn protected env!!!
+ set opts [convert_args $method ""]
+ convert_encrypt $env_cmd
+ set omethod [convert_method $method]
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv -encrypt $opts $testfile"
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ error_check_good db_close [$db close] 0
+
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv -encrypt $opts $testfile2"
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ error_check_good db_close [$db close] 0
+
+ error_check_good env_close [$dbenv close] 0
+
+ puts "\tRecd017.a.1: Verify db_printlog can read logfile"
+ set tmpfile $testdir/printlog.out
+ set stat [catch {exec $util_path/db_printlog -h $testdir -P $passwd \
+ > $tmpfile} ret]
+ error_check_good db_printlog $stat 0
+ fileremove $tmpfile
+
+ # List of recovery tests: {CMD MSG} pairs.
+ set rlist {
+ { {DB put -txn TXNID $key $data} "Recd017.b: put"}
+ { {DB del -txn TXNID $key} "Recd017.c: delete"}
+ }
+
+ # These are all the data values that we're going to need to read
+ # through the operation table and run the recovery tests.
+
+ if { [is_record_based $method] == 1 } {
+ set key 1
+ } else {
+ set key recd017_key
+ }
+ set data recd017_data
+ foreach pair $rlist {
+ set cmd [subst [lindex $pair 0]]
+ set msg [lindex $pair 1]
+ if { $select != 0 } {
+ set tag [lindex $msg 0]
+ set tail [expr [string length $tag] - 2]
+ set tag [string range $tag $tail $tail]
+ if { [lsearch $select $tag] == -1 } {
+ continue
+ }
+ }
+
+ if { [is_queue $method] != 1 } {
+ if { [string first append $cmd] != -1 } {
+ continue
+ }
+ if { [string first consume $cmd] != -1 } {
+ continue
+ }
+ }
+
+# if { [is_fixed_length $method] == 1 } {
+# if { [string first partial $cmd] != -1 } {
+# continue
+# }
+# }
+ op_recover abort $testdir $env_cmd $testfile $cmd $msg
+ op_recover commit $testdir $env_cmd $testfile $cmd $msg
+ #
+ # Note that since prepare-discard ultimately aborts
+ # the txn, it must come before prepare-commit.
+ #
+ op_recover prepare-abort $testdir $env_cmd $testfile2 \
+ $cmd $msg
+ op_recover prepare-discard $testdir $env_cmd $testfile2 \
+ $cmd $msg
+ op_recover prepare-commit $testdir $env_cmd $testfile2 \
+ $cmd $msg
+ }
+ set fixed_len $orig_fixed_len
+ return
+}
diff --git a/bdb/test/recd018.tcl b/bdb/test/recd018.tcl
new file mode 100644
index 00000000000..fb5a589d851
--- /dev/null
+++ b/bdb/test/recd018.tcl
@@ -0,0 +1,110 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2000-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd018.tcl,v 11.2 2002/03/13 21:04:20 sue Exp $
+#
+# TEST recd018
+# TEST Test recover of closely interspersed checkpoints and commits.
+#
+# This test is from the error case from #4230.
+#
+proc recd018 { method {ndbs 10} args } {
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+ set tnum 18
+
+ puts "Recd0$tnum ($args): $method recovery of checkpoints and commits."
+
+ set tname recd0$tnum.db
+ env_cleanup $testdir
+
+ set i 0
+ if { [is_record_based $method] == 1 } {
+ set key 1
+ set key2 2
+ } else {
+ set key KEY
+ set key2 KEY2
+ }
+
+ puts "\tRecd0$tnum.a: Create environment and database."
+ set flags "-create -txn -home $testdir"
+
+ set env_cmd "berkdb_env $flags"
+ set dbenv [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ set oflags "-auto_commit -env $dbenv -create -mode 0644 $args $omethod"
+ for { set i 0 } { $i < $ndbs } { incr i } {
+ set testfile $tname.$i
+ set db($i) [eval {berkdb_open} $oflags $testfile]
+ error_check_good dbopen [is_valid_db $db($i)] TRUE
+ set file $testdir/$testfile.init
+ catch { file copy -force $testdir/$testfile $file} res
+ copy_extent_file $testdir $testfile init
+ }
+
+ # Main loop: Write a record or two to each database.
+ # Do a commit immediately followed by a checkpoint after each one.
+ error_check_good "Initial Checkpoint" [$dbenv txn_checkpoint] 0
+
+ puts "\tRecd0$tnum.b Put/Commit/Checkpoint to $ndbs databases"
+ for { set i 0 } { $i < $ndbs } { incr i } {
+ set testfile $tname.$i
+ set data $i
+
+ # Put, in a txn.
+ set txn [$dbenv txn]
+ error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
+ error_check_good db_put \
+ [$db($i) put -txn $txn $key [chop_data $method $data]] 0
+ error_check_good txn_commit [$txn commit] 0
+ error_check_good txn_checkpt [$dbenv txn_checkpoint] 0
+ if { [expr $i % 2] == 0 } {
+ set txn [$dbenv txn]
+ error_check_good txn2 [is_valid_txn $txn $dbenv] TRUE
+ error_check_good db_put [$db($i) put \
+ -txn $txn $key2 [chop_data $method $data]] 0
+ error_check_good txn_commit [$txn commit] 0
+ error_check_good txn_checkpt [$dbenv txn_checkpoint] 0
+ }
+ error_check_good db_close [$db($i) close] 0
+ set file $testdir/$testfile.afterop
+ catch { file copy -force $testdir/$testfile $file} res
+ copy_extent_file $testdir $testfile afterop
+ }
+ error_check_good env_close [$dbenv close] 0
+
+ # Now, loop through and recover to each timestamp, verifying the
+ # expected increment.
+ puts "\tRecd0$tnum.c: Run recovery (no-op)"
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 0
+
+ puts "\tRecd0$tnum.d: Run recovery (initial file)"
+ for { set i 0 } {$i < $ndbs } { incr i } {
+ set testfile $tname.$i
+ set file $testdir/$testfile.init
+ catch { file copy -force $file $testdir/$testfile } res
+ move_file_extent $testdir $testfile init copy
+ }
+
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 0
+
+ puts "\tRecd0$tnum.e: Run recovery (after file)"
+ for { set i 0 } {$i < $ndbs } { incr i } {
+ set testfile $tname.$i
+ set file $testdir/$testfile.afterop
+ catch { file copy -force $file $testdir/$testfile } res
+ move_file_extent $testdir $testfile afterop copy
+ }
+
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 0
+
+}
diff --git a/bdb/test/recd019.tcl b/bdb/test/recd019.tcl
new file mode 100644
index 00000000000..dd67b7dcb2a
--- /dev/null
+++ b/bdb/test/recd019.tcl
@@ -0,0 +1,121 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd019.tcl,v 11.3 2002/08/08 15:38:07 bostic Exp $
+#
+# TEST recd019
+# TEST Test txn id wrap-around and recovery.
+proc recd019 { method {numid 50} args} {
+ global fixed_len
+ global txn_curid
+ global log_log_record_types
+ source ./include.tcl
+
+ set orig_fixed_len $fixed_len
+ set opts [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ puts "Recd019: $method txn id wrap-around test"
+
+ # Create the database and environment.
+ env_cleanup $testdir
+
+ set testfile recd019.db
+
+ set flags "-create -txn -home $testdir"
+
+ puts "\tRecd019.a: creating environment"
+ set env_cmd "berkdb_env $flags"
+ set dbenv [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ # Test txn wrapping. Force a txn_recycle msg.
+ #
+ set new_curid $txn_curid
+ set new_maxid [expr $new_curid + $numid]
+ error_check_good txn_id_set [$dbenv txn_id_set $new_curid $new_maxid] 0
+
+ #
+ # We need to create a database to get the pagesize (either
+ # the default or whatever might have been specified).
+ # Then remove it so we can compute fixed_len and create the
+ # real database.
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv $opts $testfile"
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ set stat [$db stat]
+ #
+ # Compute the fixed_len based on the pagesize being used.
+ # We want the fixed_len to be 1/4 the pagesize.
+ #
+ set pg [get_pagesize $stat]
+ error_check_bad get_pagesize $pg -1
+ set fixed_len [expr $pg / 4]
+ error_check_good db_close [$db close] 0
+ error_check_good dbremove [berkdb dbremove -env $dbenv $testfile] 0
+
+ # Convert the args again because fixed_len is now real.
+ # Create the databases and close the environment.
+ # cannot specify db truncate in txn protected env!!!
+ set opts [convert_args $method ""]
+ set omethod [convert_method $method]
+ set oflags "-create $omethod -mode 0644 \
+ -env $dbenv -auto_commit $opts $testfile"
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ #
+ # Force txn ids to wrap twice and then some.
+ #
+ set nument [expr $numid * 3 - 2]
+ puts "\tRecd019.b: Wrapping txn ids after $numid"
+ set file $testdir/$testfile.init
+ catch { file copy -force $testdir/$testfile $file} res
+ copy_extent_file $testdir $testfile init
+ for { set i 1 } { $i <= $nument } { incr i } {
+ # Use 'i' as key so method doesn't matter
+ set key $i
+ set data $i
+
+ # Put, in a txn.
+ set txn [$dbenv txn]
+ error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
+ error_check_good db_put \
+ [$db put -txn $txn $key [chop_data $method $data]] 0
+ error_check_good txn_commit [$txn commit] 0
+ }
+ error_check_good db_close [$db close] 0
+ set file $testdir/$testfile.afterop
+ catch { file copy -force $testdir/$testfile $file} res
+ copy_extent_file $testdir $testfile afterop
+ error_check_good env_close [$dbenv close] 0
+
+ # Keep track of the log types we've seen
+ if { $log_log_record_types == 1} {
+ logtrack_read $testdir
+ }
+
+ # Now, loop through and recover.
+ puts "\tRecd019.c: Run recovery (no-op)"
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 0
+
+ puts "\tRecd019.d: Run recovery (initial file)"
+ set file $testdir/$testfile.init
+ catch { file copy -force $file $testdir/$testfile } res
+ move_file_extent $testdir $testfile init copy
+
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 0
+
+ puts "\tRecd019.e: Run recovery (after file)"
+ set file $testdir/$testfile.afterop
+ catch { file copy -force $file $testdir/$testfile } res
+ move_file_extent $testdir $testfile afterop copy
+
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 0
+}
diff --git a/bdb/test/recd020.tcl b/bdb/test/recd020.tcl
new file mode 100644
index 00000000000..93a89f32578
--- /dev/null
+++ b/bdb/test/recd020.tcl
@@ -0,0 +1,180 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd020.tcl,v 11.8 2002/08/08 15:38:08 bostic Exp $
+#
+# TEST recd020
+# TEST Test recovery after checksum error.
+proc recd020 { method args} {
+ global fixed_len
+ global log_log_record_types
+ global datastr
+ source ./include.tcl
+
+ set pgindex [lsearch -exact $args "-pagesize"]
+ if { $pgindex != -1 } {
+ puts "Recd020: skipping for specific pagesizes"
+ return
+ }
+ if { [is_queueext $method] == 1 } {
+ puts "Recd020: skipping for method $method"
+ return
+ }
+
+ puts "Recd020: $method recovery after checksum error"
+
+ # Create the database and environment.
+ env_cleanup $testdir
+
+ set testfile recd020.db
+ set flags "-create -txn -home $testdir"
+
+ puts "\tRecd020.a: creating environment"
+ set env_cmd "berkdb_env $flags"
+ set dbenv [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ set pgsize 512
+ set orig_fixed_len $fixed_len
+ set fixed_len [expr $pgsize / 4]
+ set opts [convert_args $method $args]
+ set omethod [convert_method $method]
+ set oflags "-create $omethod -mode 0644 \
+ -auto_commit -chksum -pagesize $pgsize $opts $testfile"
+ set db [eval {berkdb_open} -env $dbenv $oflags]
+
+ #
+ # Put some data.
+ #
+ set nument 50
+ puts "\tRecd020.b: Put some data"
+ for { set i 1 } { $i <= $nument } { incr i } {
+ # Use 'i' as key so method doesn't matter
+ set key $i
+ set data $i$datastr
+
+ # Put, in a txn.
+ set txn [$dbenv txn]
+ error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
+ error_check_good db_put \
+ [$db put -txn $txn $key [chop_data $method $data]] 0
+ error_check_good txn_commit [$txn commit] 0
+ }
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$dbenv close] 0
+ #
+ # We need to remove the env so that we don't get cached
+ # pages.
+ #
+ error_check_good env_remove [berkdb envremove -home $testdir] 0
+
+ puts "\tRecd020.c: Overwrite part of database"
+ #
+ # First just touch some bits in the file. We want to go
+ # through the paging system, so touch some data pages,
+ # like the middle of page 2.
+ # We should get a checksum error for the checksummed file.
+ #
+ set pg 2
+ set fid [open $testdir/$testfile r+]
+ fconfigure $fid -translation binary
+ set seeklen [expr $pgsize * $pg + 200]
+ seek $fid $seeklen start
+ set byte [read $fid 1]
+ binary scan $byte c val
+ set newval [expr ~$val]
+ set newbyte [binary format c $newval]
+ seek $fid $seeklen start
+ puts -nonewline $fid $newbyte
+ close $fid
+
+ #
+ # Verify we get the checksum error. When we get it, it should
+ # log the error as well, so when we run recovery we'll need to
+ # do catastrophic recovery. We do this in a sub-process so that
+ # the files are closed after the panic.
+ #
+ set f1 [open |$tclsh_path r+]
+ puts $f1 "source $test_path/test.tcl"
+
+ set env_cmd "berkdb_env_noerr $flags"
+ set dbenv [send_cmd $f1 $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ set db [send_cmd $f1 "{berkdb_open_noerr} -env $dbenv $oflags"]
+ error_check_good db [is_valid_db $db] TRUE
+
+ # We need to set non-blocking mode so that after each command
+ # we can read all the remaining output from that command and
+ # we can know what the output from one command is.
+ fconfigure $f1 -blocking 0
+ set ret [read $f1]
+ set got_err 0
+ for { set i 1 } { $i <= $nument } { incr i } {
+ set stat [send_cmd $f1 "catch {$db get $i} r"]
+ set getret [send_cmd $f1 "puts \$r"]
+ set ret [read $f1]
+ if { $stat == 1 } {
+ error_check_good dbget:fail [is_substr $getret \
+ "checksum error: catastrophic recovery required"] 1
+ set got_err 1
+ # Now verify that it was an error on the page we set.
+ error_check_good dbget:pg$pg [is_substr $ret \
+ "failed for page $pg"] 1
+ break
+ } else {
+ set key [lindex [lindex $getret 0] 0]
+ set data [lindex [lindex $getret 0] 1]
+ error_check_good keychk $key $i
+ error_check_good datachk $data \
+ [pad_data $method $i$datastr]
+ }
+ }
+ error_check_good got_chksum $got_err 1
+ set ret [send_cmd $f1 "$db close"]
+ set extra [read $f1]
+ error_check_good db:fail [is_substr $ret "run recovery"] 1
+
+ set ret [send_cmd $f1 "$dbenv close"]
+ error_check_good env_close:fail [is_substr $ret "run recovery"] 1
+ close $f1
+
+ # Keep track of the log types we've seen
+ if { $log_log_record_types == 1} {
+ logtrack_read $testdir
+ }
+
+ puts "\tRecd020.d: Run normal recovery"
+ set ret [catch {exec $util_path/db_recover -h $testdir} r]
+ error_check_good db_recover $ret 1
+ error_check_good dbrec:fail \
+ [is_substr $r "checksum error: catastrophic recovery required"] 1
+
+ catch {fileremove $testdir/$testfile} ret
+ puts "\tRecd020.e: Run catastrophic recovery"
+ set ret [catch {exec $util_path/db_recover -c -h $testdir} r]
+ error_check_good db_recover $ret 0
+
+ #
+ # Now verify the data was reconstructed correctly.
+ #
+ set env_cmd "berkdb_env_noerr $flags"
+ set dbenv [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+ set db [eval {berkdb_open} -env $dbenv $oflags]
+ error_check_good db [is_valid_db $db] TRUE
+
+ for { set i 1 } { $i <= $nument } { incr i } {
+ set stat [catch {$db get $i} ret]
+ error_check_good stat $stat 0
+ set key [lindex [lindex $ret 0] 0]
+ set data [lindex [lindex $ret 0] 1]
+ error_check_good keychk $key $i
+ error_check_good datachk $data [pad_data $method $i$datastr]
+ }
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$dbenv close] 0
+}
diff --git a/bdb/test/recd15scr.tcl b/bdb/test/recd15scr.tcl
new file mode 100644
index 00000000000..e1238907a71
--- /dev/null
+++ b/bdb/test/recd15scr.tcl
@@ -0,0 +1,74 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recd15scr.tcl,v 1.5 2002/01/30 13:18:04 margo Exp $
+#
+# Recd15 - lots of txns - txn prepare script
+# Usage: recd15script envcmd dbcmd gidf numtxns
+# envcmd: command to open env
+# dbfile: name of database file
+# gidf: name of global id file
+# numtxns: number of txns to start
+
+source ./include.tcl
+source $test_path/test.tcl
+source $test_path/testutils.tcl
+
+set usage "recd15script envcmd dbfile gidfile numtxns"
+
+# Verify usage
+if { $argc != 4 } {
+ puts stderr "FAIL:[timestamp] Usage: $usage"
+ exit
+}
+
+# Initialize arguments
+set envcmd [ lindex $argv 0 ]
+set dbfile [ lindex $argv 1 ]
+set gidfile [ lindex $argv 2 ]
+set numtxns [ lindex $argv 3 ]
+
+set txnmax [expr $numtxns + 5]
+set dbenv [eval $envcmd]
+error_check_good envopen [is_valid_env $dbenv] TRUE
+
+set usedb 0
+if { $dbfile != "NULL" } {
+ set usedb 1
+ set db [berkdb_open -auto_commit -env $dbenv $dbfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+}
+
+puts "\tRecd015script.a: Begin $numtxns txns"
+for {set i 0} {$i < $numtxns} {incr i} {
+ set t [$dbenv txn]
+ error_check_good txnbegin($i) [is_valid_txn $t $dbenv] TRUE
+ set txns($i) $t
+ if { $usedb } {
+ set dbc [$db cursor -txn $t]
+ error_check_good cursor($i) [is_valid_cursor $dbc $db] TRUE
+ set curs($i) $dbc
+ }
+}
+
+puts "\tRecd015script.b: Prepare $numtxns txns"
+set gfd [open $gidfile w+]
+for {set i 0} {$i < $numtxns} {incr i} {
+ if { $usedb } {
+ set dbc $curs($i)
+ error_check_good dbc_close [$dbc close] 0
+ }
+ set t $txns($i)
+ set gid [make_gid recd015script:$t]
+ puts $gfd $gid
+ error_check_good txn_prepare:$t [$t prepare $gid] 0
+}
+close $gfd
+
+#
+# We do not close the db or env, but exit with the txns outstanding.
+#
+puts "\tRecd015script completed successfully"
+flush stdout
diff --git a/bdb/test/recdscript.tcl b/bdb/test/recdscript.tcl
new file mode 100644
index 00000000000..a2afde46e4d
--- /dev/null
+++ b/bdb/test/recdscript.tcl
@@ -0,0 +1,37 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: recdscript.tcl,v 11.4 2002/01/11 15:53:32 bostic Exp $
+#
+# Recovery txn prepare script
+# Usage: recdscript op dir envcmd dbfile cmd
+# op: primary txn operation
+# dir: test directory
+# envcmd: command to open env
+# dbfile: name of database file
+# gidf: name of global id file
+# cmd: db command to execute
+
+source ./include.tcl
+source $test_path/test.tcl
+
+set usage "recdscript op dir envcmd dbfile gidfile cmd"
+
+# Verify usage
+if { $argc != 6 } {
+ puts stderr "FAIL:[timestamp] Usage: $usage"
+ exit
+}
+
+# Initialize arguments
+set op [ lindex $argv 0 ]
+set dir [ lindex $argv 1 ]
+set envcmd [ lindex $argv 2 ]
+set dbfile [ lindex $argv 3 ]
+set gidfile [ lindex $argv 4 ]
+set cmd [ lindex $argv 5 ]
+
+op_recover_prep $op $dir $envcmd $dbfile $gidfile $cmd
+flush stdout
diff --git a/bdb/test/rep001.tcl b/bdb/test/rep001.tcl
new file mode 100644
index 00000000000..97a640029f5
--- /dev/null
+++ b/bdb/test/rep001.tcl
@@ -0,0 +1,249 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rep001.tcl,v 1.16 2002/08/26 17:52:19 margo Exp $
+#
+# TEST rep001
+# TEST Replication rename and forced-upgrade test.
+# TEST
+# TEST Run a modified version of test001 in a replicated master environment;
+# TEST verify that the database on the client is correct.
+# TEST Next, remove the database, close the master, upgrade the
+# TEST client, reopen the master, and make sure the new master can correctly
+# TEST run test001 and propagate it in the other direction.
+
+proc rep001 { method { niter 1000 } { tnum "01" } args } {
+ global passwd
+
+ puts "Rep0$tnum: Replication sanity test."
+
+ set envargs ""
+ rep001_sub $method $niter $tnum $envargs $args
+
+ puts "Rep0$tnum: Replication and security sanity test."
+ append envargs " -encryptaes $passwd "
+ append args " -encrypt "
+ rep001_sub $method $niter $tnum $envargs $args
+}
+
+proc rep001_sub { method niter tnum envargs largs } {
+ source ./include.tcl
+ global testdir
+ global encrypt
+
+ env_cleanup $testdir
+
+ replsetup $testdir/MSGQUEUEDIR
+
+ set masterdir $testdir/MASTERDIR
+ set clientdir $testdir/CLIENTDIR
+
+ file mkdir $masterdir
+ file mkdir $clientdir
+
+ if { [is_record_based $method] == 1 } {
+ set checkfunc test001_recno.check
+ } else {
+ set checkfunc test001.check
+ }
+
+ # Open a master.
+ repladd 1
+ set masterenv \
+ [eval {berkdb_env -create -lock_max 2500 -log_max 1000000} \
+ $envargs {-home $masterdir -txn -rep_master -rep_transport \
+ [list 1 replsend]}]
+ error_check_good master_env [is_valid_env $masterenv] TRUE
+
+ # Open a client
+ repladd 2
+ set clientenv [eval {berkdb_env -create} $envargs -txn -lock_max 2500 \
+ {-home $clientdir -rep_client -rep_transport [list 2 replsend]}]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+
+ # Bring the client online by processing the startup messages.
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Open a test database on the master (so we can test having handles
+ # open across an upgrade).
+ puts "\tRep0$tnum.a:\
+ Opening test database for post-upgrade client logging test."
+ set master_upg_db [berkdb_open \
+ -create -auto_commit -btree -env $masterenv rep0$tnum-upg.db]
+ set puttxn [$masterenv txn]
+ error_check_good master_upg_db_put \
+ [$master_upg_db put -txn $puttxn hello world] 0
+ error_check_good puttxn_commit [$puttxn commit] 0
+ error_check_good master_upg_db_close [$master_upg_db close] 0
+
+ # Run a modified test001 in the master (and update client).
+ puts "\tRep0$tnum.b: Running test001 in replicated env."
+ eval test001 $method $niter 0 $tnum 1 -env $masterenv $largs
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Open the cross-upgrade database on the client and check its contents.
+ set client_upg_db [berkdb_open \
+ -create -auto_commit -btree -env $clientenv rep0$tnum-upg.db]
+ error_check_good client_upg_db_get [$client_upg_db get hello] \
+ [list [list hello world]]
+ # !!! We use this handle later. Don't close it here.
+
+ # Verify the database in the client dir.
+ puts "\tRep0$tnum.c: Verifying client database contents."
+ set testdir [get_home $masterenv]
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ open_and_dump_file test0$tnum.db $clientenv $t1 \
+ $checkfunc dump_file_direction "-first" "-next"
+
+ # Remove the file (and update client).
+ puts "\tRep0$tnum.d: Remove the file on the master and close master."
+ error_check_good remove \
+ [$masterenv dbremove -auto_commit test0$tnum.db] 0
+ error_check_good masterenv_close [$masterenv close] 0
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Don't get confused in Tcl.
+ puts "\tRep0$tnum.e: Upgrade client."
+ set newmasterenv $clientenv
+ error_check_good upgrade_client [$newmasterenv rep_start -master] 0
+
+ # Run test001 in the new master
+ puts "\tRep0$tnum.f: Running test001 in new master."
+ eval test001 $method $niter 0 $tnum 1 -env $newmasterenv $largs
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $newmasterenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ puts "\tRep0$tnum.g: Reopen old master as client and catch up."
+ # Throttle master so it can't send everything at once
+ $newmasterenv rep_limit 0 [expr 64 * 1024]
+ set newclientenv [eval {berkdb_env -create -recover} $envargs \
+ -txn -lock_max 2500 \
+ {-home $masterdir -rep_client -rep_transport [list 1 replsend]}]
+ error_check_good newclient_env [is_valid_env $newclientenv] TRUE
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $newclientenv 1]
+ incr nproced [replprocessqueue $newmasterenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+ set stats [$newmasterenv rep_stat]
+ set nthrottles [getstats $stats {Transmission limited}]
+ error_check_bad nthrottles $nthrottles -1
+ error_check_bad nthrottles $nthrottles 0
+
+ # Run a modified test001 in the new master (and update client).
+ puts "\tRep0$tnum.h: Running test001 in new master."
+ eval test001 $method \
+ $niter $niter $tnum 1 -env $newmasterenv $largs
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $newclientenv 1]
+ incr nproced [replprocessqueue $newmasterenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Test put to the database handle we opened back when the new master
+ # was a client.
+ puts "\tRep0$tnum.i: Test put to handle opened before upgrade."
+ set puttxn [$newmasterenv txn]
+ error_check_good client_upg_db_put \
+ [$client_upg_db put -txn $puttxn hello there] 0
+ error_check_good puttxn_commit [$puttxn commit] 0
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $newclientenv 1]
+ incr nproced [replprocessqueue $newmasterenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Close the new master's handle for the upgrade-test database; we
+ # don't need it. Then check to make sure the client did in fact
+ # update the database.
+ error_check_good client_upg_db_close [$client_upg_db close] 0
+ set newclient_upg_db [berkdb_open -env $newclientenv rep0$tnum-upg.db]
+ error_check_good newclient_upg_db_get [$newclient_upg_db get hello] \
+ [list [list hello there]]
+ error_check_good newclient_upg_db_close [$newclient_upg_db close] 0
+
+ # Verify the database in the client dir.
+ puts "\tRep0$tnum.j: Verifying new client database contents."
+ set testdir [get_home $newmasterenv]
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ open_and_dump_file test0$tnum.db $newclientenv $t1 \
+ $checkfunc dump_file_direction "-first" "-next"
+
+ if { [string compare [convert_method $method] -recno] != 0 } {
+ filesort $t1 $t3
+ }
+ error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
+
+
+ error_check_good newmasterenv_close [$newmasterenv close] 0
+ error_check_good newclientenv_close [$newclientenv close] 0
+
+ if { [lsearch $envargs "-encrypta*"] !=-1 } {
+ set encrypt 1
+ }
+ error_check_good verify \
+ [verify_dir $clientdir "\tRep0$tnum.k: " 0 0 1] 0
+ replclose $testdir/MSGQUEUEDIR
+}
diff --git a/bdb/test/rep002.tcl b/bdb/test/rep002.tcl
new file mode 100644
index 00000000000..68666b0d0f0
--- /dev/null
+++ b/bdb/test/rep002.tcl
@@ -0,0 +1,278 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rep002.tcl,v 11.11 2002/08/08 18:13:12 sue Exp $
+#
+# TEST rep002
+# TEST Basic replication election test.
+# TEST
+# TEST Run a modified version of test001 in a replicated master environment;
+# TEST hold an election among a group of clients to make sure they select
+# TEST a proper master from amongst themselves, in various scenarios.
+
+proc rep002 { method { niter 10 } { nclients 3 } { tnum "02" } args } {
+ source ./include.tcl
+ global elect_timeout
+
+ set elect_timeout 1000000
+
+ if { [is_record_based $method] == 1 } {
+ puts "Rep002: Skipping for method $method."
+ return
+ }
+
+ env_cleanup $testdir
+
+ set qdir $testdir/MSGQUEUEDIR
+ replsetup $qdir
+
+ set masterdir $testdir/MASTERDIR
+ file mkdir $masterdir
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set clientdir($i) $testdir/CLIENTDIR.$i
+ file mkdir $clientdir($i)
+ }
+
+ puts "Rep0$tnum: Replication election test with $nclients clients."
+
+ # Open a master.
+ repladd 1
+ set env_cmd(M) "berkdb_env -create -log_max 1000000 -home \
+ $masterdir -txn -rep_master -rep_transport \[list 1 replsend\]"
+ set masterenv [eval $env_cmd(M)]
+ error_check_good master_env [is_valid_env $masterenv] TRUE
+
+ # Open the clients.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set envid [expr $i + 2]
+ repladd $envid
+ set env_cmd($i) "berkdb_env -create -home $clientdir($i) \
+ -txn -rep_client -rep_transport \[list $envid replsend\]"
+ set clientenv($i) [eval $env_cmd($i)]
+ error_check_good \
+ client_env($i) [is_valid_env $clientenv($i)] TRUE
+ }
+
+ # Run a modified test001 in the master.
+ puts "\tRep0$tnum.a: Running test001 in replicated env."
+ eval test001 $method $niter 0 $tnum 0 -env $masterenv $args
+
+ # Loop, processing first the master's messages, then the client's,
+ # until both queues are empty.
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set envid [expr $i + 2]
+ incr nproced [replprocessqueue $clientenv($i) $envid]
+ }
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Verify the database in the client dir.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ puts "\tRep0$tnum.b: Verifying contents of client database $i."
+ set testdir [get_home $masterenv]
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ open_and_dump_file test0$tnum.db $clientenv($i) $testdir/t1 \
+ test001.check dump_file_direction "-first" "-next"
+
+ if { [string compare [convert_method $method] -recno] != 0 } {
+ filesort $t1 $t3
+ }
+ error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
+
+ verify_dir $clientdir($i) "\tRep0$tnum.c: " 0 0 1
+ }
+
+ # Start an election in the first client.
+ puts "\tRep0$tnum.d: Starting election without dead master."
+
+ set elect_pipe(0) [start_election \
+ $qdir $env_cmd(0) [expr $nclients + 1] 20 $elect_timeout]
+
+ tclsleep 1
+
+ # We want to verify all the clients but the one that declared an
+ # election get the election message.
+ # We also want to verify that the master declares the election
+ # over by fiat, even if everyone uses a lower priority than 20.
+ # Loop and process all messages, keeping track of which
+ # sites got a HOLDELECTION and checking that the returned newmaster,
+ # if any, is 1 (the master's replication ID).
+ set got_hold_elect(M) 0
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set got_hold_elect($i) 0
+ }
+ while { 1 } {
+ set nproced 0
+ set he 0
+ set nm 0
+
+
+ incr nproced [replprocessqueue $masterenv 1 0 he nm]
+
+ if { $he == 1 } {
+ set elect_pipe(M) [start_election $qdir \
+ $env_cmd(M) [expr $nclients + 1] 0 $elect_timeout]
+ set got_hold_elect(M) 1
+ }
+ if { $nm != 0 } {
+ error_check_good newmaster_is_master $nm 1
+ }
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set he 0
+ set envid [expr $i + 2]
+ incr nproced \
+ [replprocessqueue $clientenv($i) $envid 0 he nm]
+ if { $he == 1 } {
+ # error_check_bad client(0)_in_elect $i 0
+ set elect_pipe(M) [start_election $qdir \
+ $env_cmd($i) [expr $nclients + 1] 0 \
+ $elect_timeout]
+ set got_hold_elect($i) 1
+ }
+ if { $nm != 0 } {
+ error_check_good newmaster_is_master $nm 1
+ }
+ }
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ error_check_good got_hold_elect(master) $got_hold_elect(M) 0
+ unset got_hold_elect(M)
+ # error_check_good got_hold_elect(0) $got_hold_elect(0) 0
+ unset got_hold_elect(0)
+ for { set i 1 } { $i < $nclients } { incr i } {
+ error_check_good got_hold_elect($i) $got_hold_elect($i) 1
+ unset got_hold_elect($i)
+ }
+
+ cleanup_elections
+
+ # We need multiple clients to proceed from here.
+ if { $nclients < 2 } {
+ puts "\tRep0$tnum: Skipping for less than two clients."
+ error_check_good masterenv_close [$masterenv close] 0
+ for { set i 0 } { $i < $nclients } { incr i } {
+ error_check_good clientenv_close($i) \
+ [$clientenv($i) close] 0
+ }
+ return
+ }
+
+ # Make sure all the clients are synced up and ready to be good
+ # voting citizens.
+ error_check_good master_flush [$masterenv rep_flush] 0
+ while { 1 } {
+ set nproced 0
+ incr nproced [replprocessqueue $masterenv 1 0]
+ for { set i 0 } { $i < $nclients } { incr i } {
+ incr nproced [replprocessqueue $clientenv($i) \
+ [expr $i + 2] 0]
+ }
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Now hold another election in the first client, this time with
+ # a dead master.
+ puts "\tRep0$tnum.e: Starting election with dead master."
+ error_check_good masterenv_close [$masterenv close] 0
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ replclear [expr $i + 2]
+ }
+
+ set elect_pipe(0) [start_election \
+ $qdir $env_cmd(0) [expr $nclients + 1] 20 $elect_timeout]
+
+ tclsleep 1
+
+ # Process messages, and verify that the client with the highest
+ # priority--client #1--wins.
+ set got_newmaster 0
+ set tries 10
+ while { 1 } {
+ set nproced 0
+ set he 0
+ set nm 0
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set he 0
+ set envid [expr $i + 2]
+ incr nproced \
+ [replprocessqueue $clientenv($i) $envid 0 he nm]
+ if { $he == 1 } {
+
+ # Client #1 has priority 100; everyone else
+ # has priority 10.
+ if { $i == 1 } {
+ set pri 100
+ } else {
+ set pri 10
+ }
+ # error_check_bad client(0)_in_elect $i 0
+ set elect_pipe(M) [start_election $qdir \
+ $env_cmd($i) [expr $nclients + 1] $pri \
+ $elect_timeout]
+ set got_hold_elect($i) 1
+ }
+ if { $nm != 0 } {
+ error_check_good newmaster_is_master $nm \
+ [expr 1 + 2]
+ set got_newmaster $nm
+
+ # If this env is the new master, it needs to
+ # configure itself as such--this is a different
+ # env handle from the one that performed the
+ # election.
+ if { $nm == $envid } {
+ error_check_good make_master($i) \
+ [$clientenv($i) rep_start -master] \
+ 0
+ }
+ }
+ }
+
+ # We need to wait around to make doubly sure that the
+ # election has finished...
+ if { $nproced == 0 } {
+ incr tries -1
+ if { $tries == 0 } {
+ break
+ } else {
+ tclsleep 1
+ }
+ }
+ }
+
+ # Verify that client #1 is actually the winner.
+ error_check_good "client 1 wins" $got_newmaster [expr 1 + 2]
+
+ cleanup_elections
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ error_check_good clientenv_close($i) [$clientenv($i) close] 0
+ }
+
+ replclose $testdir/MSGQUEUEDIR
+}
+
+proc reptwo { args } { eval rep002 $args }
diff --git a/bdb/test/rep003.tcl b/bdb/test/rep003.tcl
new file mode 100644
index 00000000000..7bb7e00ddbf
--- /dev/null
+++ b/bdb/test/rep003.tcl
@@ -0,0 +1,221 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rep003.tcl,v 11.9 2002/08/09 02:23:50 margo Exp $
+#
+# TEST rep003
+# TEST Repeated shutdown/restart replication test
+# TEST
+# TEST Run a quick put test in a replicated master environment; start up,
+# TEST shut down, and restart client processes, with and without recovery.
+# TEST To ensure that environment state is transient, use DB_PRIVATE.
+
+proc rep003 { method { tnum "03" } args } {
+ source ./include.tcl
+ global testdir rep003_dbname rep003_omethod rep003_oargs
+
+ env_cleanup $testdir
+ set niter 10
+ set rep003_dbname rep003.db
+
+ if { [is_record_based $method] } {
+ puts "Rep0$tnum: Skipping for method $method"
+ return
+ }
+
+ set rep003_omethod [convert_method $method]
+ set rep003_oargs [convert_args $method $args]
+
+ replsetup $testdir/MSGQUEUEDIR
+
+ set masterdir $testdir/MASTERDIR
+ file mkdir $masterdir
+
+ set clientdir $testdir/CLIENTDIR
+ file mkdir $clientdir
+
+ puts "Rep0$tnum: Replication repeated-startup test"
+
+ # Open a master.
+ repladd 1
+ set masterenv [berkdb_env_noerr -create -log_max 1000000 \
+ -home $masterdir -txn -rep_master -rep_transport [list 1 replsend]]
+ error_check_good master_env [is_valid_env $masterenv] TRUE
+
+ puts "\tRep0$tnum.a: Simple client startup test."
+
+ # Put item one.
+ rep003_put $masterenv A1 a-one
+
+ # Open a client.
+ repladd 2
+ set clientenv [berkdb_env_noerr -create -private -home $clientdir -txn \
+ -rep_client -rep_transport [list 2 replsend]]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+
+ # Put another quick item.
+ rep003_put $masterenv A2 a-two
+
+ # Loop, processing first the master's messages, then the client's,
+ # until both queues are empty.
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ rep003_check $clientenv A1 a-one
+ rep003_check $clientenv A2 a-two
+
+ error_check_good clientenv_close [$clientenv close] 0
+ replclear 2
+
+ # Now reopen the client after doing another put.
+ puts "\tRep0$tnum.b: Client restart."
+ rep003_put $masterenv B1 b-one
+
+ unset clientenv
+ set clientenv [berkdb_env_noerr -create -private -home $clientdir -txn \
+ -rep_client -rep_transport [list 2 replsend]]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+
+ rep003_put $masterenv B2 b-two
+
+ # Loop, processing first the master's messages, then the client's,
+ # until both queues are empty.
+ while { 1 } {
+ set nproced 0
+
+ # The items from part A should be present at all times--
+ # if we roll them back, we've screwed up. [#5709]
+ rep003_check $clientenv A1 a-one
+ rep003_check $clientenv A2 a-two
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ rep003_check $clientenv B1 b-one
+ rep003_check $clientenv B2 b-two
+
+ error_check_good clientenv_close [$clientenv close] 0
+
+ replclear 2
+
+ # Now reopen the client after a recovery.
+ puts "\tRep0$tnum.c: Client restart after recovery."
+ rep003_put $masterenv C1 c-one
+
+ unset clientenv
+ set clientenv [berkdb_env_noerr -create -private -home $clientdir -txn \
+ -recover -rep_client -rep_transport [list 2 replsend]]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+
+ rep003_put $masterenv C2 c-two
+
+ # Loop, processing first the master's messages, then the client's,
+ # until both queues are empty.
+ while { 1 } {
+ set nproced 0
+
+ # The items from part A should be present at all times--
+ # if we roll them back, we've screwed up. [#5709]
+ rep003_check $clientenv A1 a-one
+ rep003_check $clientenv A2 a-two
+ rep003_check $clientenv B1 b-one
+ rep003_check $clientenv B2 b-two
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ rep003_check $clientenv C1 c-one
+ rep003_check $clientenv C2 c-two
+
+ error_check_good clientenv_close [$clientenv close] 0
+
+ replclear 2
+
+ # Now reopen the client after a catastrophic recovery.
+ puts "\tRep0$tnum.d: Client restart after catastrophic recovery."
+ rep003_put $masterenv D1 d-one
+
+ unset clientenv
+ set clientenv [berkdb_env_noerr -create -private -home $clientdir -txn \
+ -recover_fatal -rep_client -rep_transport [list 2 replsend]]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+
+ rep003_put $masterenv D2 d-two
+
+ # Loop, processing first the master's messages, then the client's,
+ # until both queues are empty.
+ while { 1 } {
+ set nproced 0
+
+ # The items from part A should be present at all times--
+ # if we roll them back, we've screwed up. [#5709]
+ rep003_check $clientenv A1 a-one
+ rep003_check $clientenv A2 a-two
+ rep003_check $clientenv B1 b-one
+ rep003_check $clientenv B2 b-two
+ rep003_check $clientenv C1 c-one
+ rep003_check $clientenv C2 c-two
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $clientenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ rep003_check $clientenv D1 d-one
+ rep003_check $clientenv D2 d-two
+
+ error_check_good clientenv_close [$clientenv close] 0
+
+ error_check_good masterenv_close [$masterenv close] 0
+ replclose $testdir/MSGQUEUEDIR
+}
+
+proc rep003_put { masterenv key data } {
+ global rep003_dbname rep003_omethod rep003_oargs
+
+ set db [eval {berkdb_open_noerr -create -env $masterenv -auto_commit} \
+ $rep003_omethod $rep003_oargs $rep003_dbname]
+ error_check_good rep3_put_open($key,$data) [is_valid_db $db] TRUE
+
+ set txn [$masterenv txn]
+ error_check_good rep3_put($key,$data) [$db put -txn $txn $key $data] 0
+ error_check_good rep3_put_txn_commit($key,$data) [$txn commit] 0
+
+ error_check_good rep3_put_close($key,$data) [$db close] 0
+}
+
+proc rep003_check { env key data } {
+ global rep003_dbname
+
+ set db [berkdb_open_noerr -rdonly -env $env $rep003_dbname]
+ error_check_good rep3_check_open($key,$data) [is_valid_db $db] TRUE
+
+ set dbt [$db get $key]
+ error_check_good rep3_check($key,$data) \
+ [lindex [lindex $dbt 0] 1] $data
+
+ error_check_good rep3_put_close($key,$data) [$db close] 0
+}
diff --git a/bdb/test/rep004.tcl b/bdb/test/rep004.tcl
new file mode 100644
index 00000000000..e1d4d3b65c7
--- /dev/null
+++ b/bdb/test/rep004.tcl
@@ -0,0 +1,198 @@
+#
+# Copyright (c) 2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rep004.tcl,v 1.5 2002/08/08 18:13:12 sue Exp $
+#
+# TEST rep004
+# TEST Test of DB_REP_LOGSONLY.
+# TEST
+# TEST Run a quick put test in a master environment that has one logs-only
+# TEST client. Shut down, then run catastrophic recovery in the logs-only
+# TEST client and check that the database is present and populated.
+
+proc rep004 { method { nitems 10 } { tnum "04" } args } {
+ source ./include.tcl
+ global testdir
+
+ env_cleanup $testdir
+ set dbname rep0$tnum.db
+
+ set omethod [convert_method $method]
+ set oargs [convert_args $method $args]
+
+ puts "Rep0$tnum: Test of logs-only replication clients"
+
+ replsetup $testdir/MSGQUEUEDIR
+ set masterdir $testdir/MASTERDIR
+ file mkdir $masterdir
+ set clientdir $testdir/CLIENTDIR
+ file mkdir $clientdir
+ set logsonlydir $testdir/LOGSONLYDIR
+ file mkdir $logsonlydir
+
+ # Open a master, a logsonly replica, and a normal client.
+ repladd 1
+ set masterenv [berkdb_env -create -home $masterdir -txn -rep_master \
+ -rep_transport [list 1 replsend]]
+ error_check_good master_env [is_valid_env $masterenv] TRUE
+
+ repladd 2
+ set loenv [berkdb_env -create -home $logsonlydir -txn -rep_logsonly \
+ -rep_transport [list 2 replsend]]
+ error_check_good logsonly_env [is_valid_env $loenv] TRUE
+
+ repladd 3
+ set clientenv [berkdb_env -create -home $clientdir -txn -rep_client \
+ -rep_transport [list 3 replsend]]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+
+
+ puts "\tRep0$tnum.a: Populate database."
+
+ set db [eval {berkdb open -create -mode 0644 -auto_commit} \
+ -env $masterenv $oargs $omethod $dbname]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set did [open $dict]
+ set count 0
+ while { [gets $did str] != -1 && $count < $nitems } {
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ set data $str
+ } else {
+ set key $str
+ set data [reverse $str]
+ }
+ set kvals($count) $key
+ set dvals($count) [pad_data $method $data]
+
+ set txn [$masterenv txn]
+ error_check_good txn($count) [is_valid_txn $txn $masterenv] TRUE
+
+ set ret [eval \
+ {$db put} -txn $txn {$key [chop_data $method $data]}]
+ error_check_good put($count) $ret 0
+
+ error_check_good commit($count) [$txn commit] 0
+
+ incr count
+ }
+
+ puts "\tRep0$tnum.b: Sync up clients."
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $loenv 2]
+ incr nproced [replprocessqueue $clientenv 3]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+
+ puts "\tRep0$tnum.c: Get master and logs-only client ahead."
+ set newcount 0
+ while { [gets $did str] != -1 && $newcount < $nitems } {
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ set data $str
+ } else {
+ set key $str
+ set data [reverse $str]
+ }
+ set kvals($count) $key
+ set dvals($count) [pad_data $method $data]
+
+ set txn [$masterenv txn]
+ error_check_good txn($count) [is_valid_txn $txn $masterenv] TRUE
+
+ set ret [eval \
+ {$db put} -txn $txn {$key [chop_data $method $data]}]
+ error_check_good put($count) $ret 0
+
+ error_check_good commit($count) [$txn commit] 0
+
+ incr count
+ incr newcount
+ }
+
+ error_check_good db_close [$db close] 0
+
+ puts "\tRep0$tnum.d: Sync up logs-only client only, then fail over."
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+ incr nproced [replprocessqueue $loenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+
+ # "Crash" the master, and fail over to the upgradeable client.
+ error_check_good masterenv_close [$masterenv close] 0
+ replclear 3
+
+ error_check_good upgrade_client [$clientenv rep_start -master] 0
+ set donenow 0
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $clientenv 3]
+ incr nproced [replprocessqueue $loenv 2]
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ error_check_good loenv_close [$loenv close] 0
+
+ puts "\tRep0$tnum.e: Run catastrophic recovery on logs-only client."
+ set loenv [berkdb_env -create -home $logsonlydir -txn -recover_fatal]
+
+ puts "\tRep0$tnum.f: Verify logs-only client contents."
+ set lodb [eval {berkdb open} -env $loenv $oargs $omethod $dbname]
+ set loc [$lodb cursor]
+
+ set cdb [eval {berkdb open} -env $clientenv $oargs $omethod $dbname]
+ set cc [$cdb cursor]
+
+ # Make sure new master and recovered logs-only replica match.
+ for { set cdbt [$cc get -first] } \
+ { [llength $cdbt] > 0 } { set cdbt [$cc get -next] } {
+ set lodbt [$loc get -next]
+
+ error_check_good newmaster_replica_match $cdbt $lodbt
+ }
+
+ # Reset new master cursor.
+ error_check_good cc_close [$cc close] 0
+ set cc [$cdb cursor]
+
+ for { set lodbt [$loc get -first] } \
+ { [llength $lodbt] > 0 } { set lodbt [$loc get -next] } {
+ set cdbt [$cc get -next]
+
+ error_check_good replica_newmaster_match $lodbt $cdbt
+ }
+
+ error_check_good loc_close [$loc close] 0
+ error_check_good lodb_close [$lodb close] 0
+ error_check_good loenv_close [$loenv close] 0
+
+ error_check_good cc_close [$cc close] 0
+ error_check_good cdb_close [$cdb close] 0
+ error_check_good clientenv_close [$clientenv close] 0
+
+ close $did
+
+ replclose $testdir/MSGQUEUEDIR
+}
diff --git a/bdb/test/rep005.tcl b/bdb/test/rep005.tcl
new file mode 100644
index 00000000000..e0515f1cd62
--- /dev/null
+++ b/bdb/test/rep005.tcl
@@ -0,0 +1,225 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rep005.tcl,v 11.3 2002/08/08 18:13:13 sue Exp $
+#
+# TEST rep005
+# TEST Replication election test with error handling.
+# TEST
+# TEST Run a modified version of test001 in a replicated master environment;
+# TEST hold an election among a group of clients to make sure they select
+# TEST a proper master from amongst themselves, forcing errors at various
+# TEST locations in the election path.
+
+proc rep005 { method { niter 10 } { tnum "05" } args } {
+ source ./include.tcl
+
+ if { [is_record_based $method] == 1 } {
+ puts "Rep005: Skipping for method $method."
+ return
+ }
+
+ set nclients 3
+ env_cleanup $testdir
+
+ set qdir $testdir/MSGQUEUEDIR
+ replsetup $qdir
+
+ set masterdir $testdir/MASTERDIR
+ file mkdir $masterdir
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set clientdir($i) $testdir/CLIENTDIR.$i
+ file mkdir $clientdir($i)
+ }
+
+ puts "Rep0$tnum: Replication election test with $nclients clients."
+
+ # Open a master.
+ repladd 1
+ set env_cmd(M) "berkdb_env -create -log_max 1000000 -home \
+ $masterdir -txn -rep_master -rep_transport \[list 1 replsend\]"
+ set masterenv [eval $env_cmd(M)]
+ error_check_good master_env [is_valid_env $masterenv] TRUE
+
+ # Open the clients.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set envid [expr $i + 2]
+ repladd $envid
+ set env_cmd($i) "berkdb_env -create -home $clientdir($i) \
+ -txn -rep_client -rep_transport \[list $envid replsend\]"
+ set clientenv($i) [eval $env_cmd($i)]
+ error_check_good \
+ client_env($i) [is_valid_env $clientenv($i)] TRUE
+ }
+
+ # Run a modified test001 in the master.
+ puts "\tRep0$tnum.a: Running test001 in replicated env."
+ eval test001 $method $niter 0 $tnum 0 -env $masterenv $args
+
+ # Loop, processing first the master's messages, then the client's,
+ # until both queues are empty.
+ while { 1 } {
+ set nproced 0
+
+ incr nproced [replprocessqueue $masterenv 1]
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set envid [expr $i + 2]
+ incr nproced [replprocessqueue $clientenv($i) $envid]
+ }
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ # Verify the database in the client dir.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ puts "\tRep0$tnum.b: Verifying contents of client database $i."
+ set testdir [get_home $masterenv]
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ open_and_dump_file test0$tnum.db $clientenv($i) $testdir/t1 \
+ test001.check dump_file_direction "-first" "-next"
+
+ if { [string compare [convert_method $method] -recno] != 0 } {
+ filesort $t1 $t3
+ }
+ error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
+
+ verify_dir $clientdir($i) "\tRep0$tnum.c: " 0 0 1
+ }
+
+ # Make sure all the clients are synced up and ready to be good
+ # voting citizens.
+ error_check_good master_flush [$masterenv rep_flush] 0
+ while { 1 } {
+ set nproced 0
+ incr nproced [replprocessqueue $masterenv 1 0]
+ for { set i 0 } { $i < $nclients } { incr i } {
+ incr nproced [replprocessqueue $clientenv($i) \
+ [expr $i + 2] 0]
+ }
+
+ if { $nproced == 0 } {
+ break
+ }
+ }
+
+ error_check_good masterenv_close [$masterenv close] 0
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ replclear [expr $i + 2]
+ }
+ #
+ # We set up the error list for each client. We know that the
+ # first client is the one calling the election, therefore, add
+ # the error location on sending the message (electsend) for that one.
+ set m "Rep0$tnum"
+ set count 0
+ foreach c0 { electinit electsend electvote1 electwait1 electvote2 \
+ electwait2 } {
+ foreach c1 { electinit electvote1 electwait1 electvote2 \
+ electwait2 } {
+ foreach c2 { electinit electvote1 electwait1 \
+ electvote2 electwait2 } {
+ set elist [list $c0 $c1 $c2]
+ rep005_elect env_cmd clientenv $qdir $m \
+ $count $elist
+ incr count
+ }
+ }
+ }
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ error_check_good clientenv_close($i) [$clientenv($i) close] 0
+ }
+
+ replclose $testdir/MSGQUEUEDIR
+}
+
+proc rep005_elect { ecmd cenv qdir msg count elist } {
+ global elect_timeout
+ upvar $ecmd env_cmd
+ upvar $cenv clientenv
+
+ set elect_timeout 1000000
+ set nclients [llength $elist]
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set err_cmd($i) [lindex $elist $i]
+ }
+ puts "\t$msg.d.$count: Starting election with errors $elist"
+ set elect_pipe(0) [start_election $qdir $env_cmd(0) \
+ [expr $nclients + 1] 20 $elect_timeout $err_cmd(0)]
+
+ tclsleep 1
+
+ # Process messages, and verify that the client with the highest
+ # priority--client #1--wins.
+ set got_newmaster 0
+ set tries 10
+ while { 1 } {
+ set nproced 0
+ set he 0
+ set nm 0
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set he 0
+ set envid [expr $i + 2]
+# puts "Processing queue for client $i"
+ incr nproced \
+ [replprocessqueue $clientenv($i) $envid 0 he nm]
+ if { $he == 1 } {
+ # Client #1 has priority 100; everyone else
+ if { $i == 1 } {
+ set pri 100
+ } else {
+ set pri 10
+ }
+ # error_check_bad client(0)_in_elect $i 0
+# puts "Starting election on client $i"
+ set elect_pipe($i) [start_election $qdir \
+ $env_cmd($i) [expr $nclients + 1] $pri \
+ $elect_timeout $err_cmd($i)]
+ set got_hold_elect($i) 1
+ }
+ if { $nm != 0 } {
+ error_check_good newmaster_is_master $nm \
+ [expr 1 + 2]
+ set got_newmaster $nm
+
+ # If this env is the new master, it needs to
+ # configure itself as such--this is a different
+ # env handle from the one that performed the
+ # election.
+ if { $nm == $envid } {
+ error_check_good make_master($i) \
+ [$clientenv($i) rep_start -master] \
+ 0
+ }
+ }
+ }
+
+ # We need to wait around to make doubly sure that the
+ # election has finished...
+ if { $nproced == 0 } {
+ incr tries -1
+ if { $tries == 0 } {
+ break
+ } else {
+ tclsleep 1
+ }
+ }
+ }
+
+ # Verify that client #1 is actually the winner.
+ error_check_good "client 1 wins" $got_newmaster [expr 1 + 2]
+
+ cleanup_elections
+
+}
diff --git a/bdb/test/reputils.tcl b/bdb/test/reputils.tcl
new file mode 100644
index 00000000000..340e359f26d
--- /dev/null
+++ b/bdb/test/reputils.tcl
@@ -0,0 +1,659 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: reputils.tcl,v 11.34 2002/08/12 17:54:18 sandstro Exp $
+#
+# Replication testing utilities
+
+# Environment handle for the env containing the replication "communications
+# structure" (really a CDB environment).
+
+# The test environment consists of a queue and a # directory (environment)
+# per replication site. The queue is used to hold messages destined for a
+# particular site and the directory will contain the environment for the
+# site. So the environment looks like:
+# $testdir
+# ___________|______________________________
+# / | \ \
+# MSGQUEUEDIR MASTERDIR CLIENTDIR.0 ... CLIENTDIR.N-1
+# | | ... |
+# 1 2 .. N+1
+#
+# The master is site 1 in the MSGQUEUEDIR and clients 1-N map to message
+# queues 2 - N+1.
+#
+# The globals repenv(1-N) contain the environment handles for the sites
+# with a given id (i.e., repenv(1) is the master's environment.
+
+global queueenv
+
+# Array of DB handles, one per machine ID, for the databases that contain
+# messages.
+global queuedbs
+global machids
+
+global elect_timeout
+set elect_timeout 50000000
+set drop 0
+
+# Create the directory structure for replication testing.
+# Open the master and client environments; store these in the global repenv
+# Return the master's environment: "-env masterenv"
+#
+proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } {
+ source ./include.tcl
+ global clientdir
+ global drop drop_msg
+ global masterdir
+ global repenv
+ global testdir
+
+ env_cleanup $testdir
+
+ replsetup $testdir/MSGQUEUEDIR
+
+ set masterdir $testdir/MASTERDIR
+ file mkdir $masterdir
+ if { $droppct != 0 } {
+ set drop 1
+ set drop_msg [expr 100 / $droppct]
+ } else {
+ set drop 0
+ }
+
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set clientdir($i) $testdir/CLIENTDIR.$i
+ file mkdir $clientdir($i)
+ }
+
+ # Open a master.
+ repladd 1
+ #
+ # Set log smaller than default to force changing files,
+ # but big enough so that the tests that use binary files
+ # as keys/data can run.
+ #
+ set lmax [expr 3 * 1024 * 1024]
+ set masterenv [eval {berkdb_env -create -log_max $lmax} $envargs \
+ {-home $masterdir -txn -rep_master -rep_transport \
+ [list 1 replsend]}]
+ error_check_good master_env [is_valid_env $masterenv] TRUE
+ set repenv(master) $masterenv
+
+ # Open clients
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set envid [expr $i + 2]
+ repladd $envid
+ set clientenv [eval {berkdb_env -create} $envargs -txn \
+ {-cachesize { 0 10000000 0 }} -lock_max 10000 \
+ {-home $clientdir($i) -rep_client -rep_transport \
+ [list $envid replsend]}]
+ error_check_good client_env [is_valid_env $clientenv] TRUE
+ set repenv($i) $clientenv
+ }
+ set repenv($i) NULL
+ append largs " -env $masterenv "
+
+ # Process startup messages
+ repl_envprocq $tnum $nclients $oob
+
+ return $largs
+}
+
+# Process all incoming messages. Iterate until there are no messages left
+# in anyone's queue so that we capture all message exchanges. We verify that
+# the requested number of clients matches the number of client environments
+# we have. The oob parameter indicates if we should process the queue
+# with out-of-order delivery. The replprocess procedure actually does
+# the real work of processing the queue -- this routine simply iterates
+# over the various queues and does the initial setup.
+
+proc repl_envprocq { tnum { nclients 1 } { oob 0 }} {
+ global repenv
+ global drop
+
+ set masterenv $repenv(master)
+ for { set i 0 } { 1 } { incr i } {
+ if { $repenv($i) == "NULL"} {
+ break
+ }
+ }
+ error_check_good i_nclients $nclients $i
+
+ set name [format "Repl%03d" $tnum]
+ berkdb debug_check
+ puts -nonewline "\t$name: Processing master/$i client queues"
+ set rand_skip 0
+ if { $oob } {
+ puts " out-of-order"
+ } else {
+ puts " in order"
+ }
+ set do_check 1
+ set droprestore $drop
+ while { 1 } {
+ set nproced 0
+
+ if { $oob } {
+ set rand_skip [berkdb random_int 2 10]
+ }
+ incr nproced [replprocessqueue $masterenv 1 $rand_skip]
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set envid [expr $i + 2]
+ if { $oob } {
+ set rand_skip [berkdb random_int 2 10]
+ }
+ set n [replprocessqueue $repenv($i) \
+ $envid $rand_skip]
+ incr nproced $n
+ }
+
+ if { $nproced == 0 } {
+ # Now that we delay requesting records until
+ # we've had a few records go by, we should always
+ # see that the number of requests is lower than the
+ # number of messages that were enqueued.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set clientenv $repenv($i)
+ set stats [$clientenv rep_stat]
+ set queued [getstats $stats \
+ {Total log records queued}]
+ error_check_bad queued_stats \
+ $queued -1
+ set requested [getstats $stats \
+ {Log records requested}]
+ error_check_bad requested_stats \
+ $requested -1
+ if { $queued != 0 && $do_check != 0 } {
+ error_check_good num_requested \
+ [expr $requested < $queued] 1
+ }
+
+ $clientenv rep_request 1 1
+ }
+
+ # If we were dropping messages, we might need
+ # to flush the log so that we get everything
+ # and end up in the right state.
+ if { $drop != 0 } {
+ set drop 0
+ set do_check 0
+ $masterenv rep_flush
+ berkdb debug_check
+ puts "\t$name: Flushing Master"
+ } else {
+ break
+ }
+ }
+ }
+
+ # Reset the clients back to the default state in case we
+ # have more processing to do.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ set clientenv $repenv($i)
+ $clientenv rep_request 4 128
+ }
+ set drop $droprestore
+}
+
+# Verify that the directories in the master are exactly replicated in
+# each of the client environments.
+
+proc repl_envver0 { tnum method { nclients 1 } } {
+ global clientdir
+ global masterdir
+ global repenv
+
+ # Verify the database in the client dir.
+ # First dump the master.
+ set t1 $masterdir/t1
+ set t2 $masterdir/t2
+ set t3 $masterdir/t3
+ set omethod [convert_method $method]
+ set name [format "Repl%03d" $tnum]
+
+ #
+ # We are interested in the keys of whatever databases are present
+ # in the master environment, so we just call a no-op check function
+ # since we have no idea what the contents of this database really is.
+ # We just need to walk the master and the clients and make sure they
+ # have the same contents.
+ #
+ set cwd [pwd]
+ cd $masterdir
+ set stat [catch {glob test*.db} dbs]
+ cd $cwd
+ if { $stat == 1 } {
+ return
+ }
+ foreach testfile $dbs {
+ open_and_dump_file $testfile $repenv(master) $masterdir/t2 \
+ repl_noop dump_file_direction "-first" "-next"
+
+ if { [string compare [convert_method $method] -recno] != 0 } {
+ filesort $t2 $t3
+ file rename -force $t3 $t2
+ }
+ for { set i 0 } { $i < $nclients } { incr i } {
+ puts "\t$name: Verifying client $i database \
+ $testfile contents."
+ open_and_dump_file $testfile $repenv($i) \
+ $t1 repl_noop dump_file_direction "-first" "-next"
+
+ if { [string compare $omethod "-recno"] != 0 } {
+ filesort $t1 $t3
+ } else {
+ catch {file copy -force $t1 $t3} ret
+ }
+ error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
+ }
+ }
+}
+
+# Remove all the elements from the master and verify that these
+# deletions properly propagated to the clients.
+
+proc repl_verdel { tnum method { nclients 1 } } {
+ global clientdir
+ global masterdir
+ global repenv
+
+ # Delete all items in the master.
+ set name [format "Repl%03d" $tnum]
+ set cwd [pwd]
+ cd $masterdir
+ set stat [catch {glob test*.db} dbs]
+ cd $cwd
+ if { $stat == 1 } {
+ return
+ }
+ foreach testfile $dbs {
+ puts "\t$name: Deleting all items from the master."
+ set txn [$repenv(master) txn]
+ error_check_good txn_begin [is_valid_txn $txn \
+ $repenv(master)] TRUE
+ set db [berkdb_open -txn $txn -env $repenv(master) $testfile]
+ error_check_good reopen_master [is_valid_db $db] TRUE
+ set dbc [$db cursor -txn $txn]
+ error_check_good reopen_master_cursor \
+ [is_valid_cursor $dbc $db] TRUE
+ for { set dbt [$dbc get -first] } { [llength $dbt] > 0 } \
+ { set dbt [$dbc get -next] } {
+ error_check_good del_item [$dbc del] 0
+ }
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good txn_commit [$txn commit] 0
+ error_check_good db_close [$db close] 0
+
+ repl_envprocq $tnum $nclients
+
+ # Check clients.
+ for { set i 0 } { $i < $nclients } { incr i } {
+ puts "\t$name: Verifying emptiness of client database $i."
+
+ set db [berkdb_open -env $repenv($i) $testfile]
+ error_check_good reopen_client($i) \
+ [is_valid_db $db] TRUE
+ set dbc [$db cursor]
+ error_check_good reopen_client_cursor($i) \
+ [is_valid_cursor $dbc $db] TRUE
+
+ error_check_good client($i)_empty \
+ [llength [$dbc get -first]] 0
+
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good db_close [$db close] 0
+ }
+ }
+}
+
+# Replication "check" function for the dump procs that expect to
+# be able to verify the keys and data.
+proc repl_noop { k d } {
+ return
+}
+
+# Close all the master and client environments in a replication test directory.
+proc repl_envclose { tnum envargs } {
+ source ./include.tcl
+ global clientdir
+ global encrypt
+ global masterdir
+ global repenv
+ global testdir
+
+ if { [lsearch $envargs "-encrypta*"] !=-1 } {
+ set encrypt 1
+ }
+
+ # In order to make sure that we have fully-synced and ready-to-verify
+ # databases on all the clients, do a checkpoint on the master and
+ # process messages in order to flush all the clients.
+ set drop 0
+ set do_check 0
+ set name [format "Repl%03d" $tnum]
+ berkdb debug_check
+ puts "\t$name: Checkpointing master."
+ error_check_good masterenv_ckp [$repenv(master) txn_checkpoint] 0
+
+ # Count clients.
+ for { set ncli 0 } { 1 } { incr ncli } {
+ if { $repenv($ncli) == "NULL" } {
+ break
+ }
+ }
+ repl_envprocq $tnum $ncli
+
+ error_check_good masterenv_close [$repenv(master) close] 0
+ verify_dir $masterdir "\t$name: " 0 0 1
+ for { set i 0 } { $i < $ncli } { incr i } {
+ error_check_good client($i)_close [$repenv($i) close] 0
+ verify_dir $clientdir($i) "\t$name: " 0 0 1
+ }
+ replclose $testdir/MSGQUEUEDIR
+
+}
+
+# Close up a replication group
+proc replclose { queuedir } {
+ global queueenv queuedbs machids
+
+ foreach m $machids {
+ set db $queuedbs($m)
+ error_check_good dbr_close [$db close] 0
+ }
+ error_check_good qenv_close [$queueenv close] 0
+ set machids {}
+}
+
+# Create a replication group for testing.
+proc replsetup { queuedir } {
+ global queueenv queuedbs machids
+
+ file mkdir $queuedir
+ set queueenv \
+ [berkdb_env -create -txn -lock_max 20000 -home $queuedir]
+ error_check_good queueenv [is_valid_env $queueenv] TRUE
+
+ if { [info exists queuedbs] } {
+ unset queuedbs
+ }
+ set machids {}
+
+ return $queueenv
+}
+
+# Send function for replication.
+proc replsend { control rec fromid toid } {
+ global queuedbs queueenv machids
+ global drop drop_msg
+
+ #
+ # If we are testing with dropped messages, then we drop every
+ # $drop_msg time. If we do that just return 0 and don't do
+ # anything.
+ #
+ if { $drop != 0 } {
+ incr drop
+ if { $drop == $drop_msg } {
+ set drop 1
+ return 0
+ }
+ }
+ # XXX
+ # -1 is DB_BROADCAST_MID
+ if { $toid == -1 } {
+ set machlist $machids
+ } else {
+ if { [info exists queuedbs($toid)] != 1 } {
+ error "replsend: machid $toid not found"
+ }
+ set machlist [list $toid]
+ }
+
+ foreach m $machlist {
+ # XXX should a broadcast include to "self"?
+ if { $m == $fromid } {
+ continue
+ }
+
+ set db $queuedbs($m)
+ set txn [$queueenv txn]
+ $db put -txn $txn -append [list $control $rec $fromid]
+ error_check_good replsend_commit [$txn commit] 0
+ }
+
+ return 0
+}
+
+# Nuke all the pending messages for a particular site.
+proc replclear { machid } {
+ global queuedbs queueenv
+
+ if { [info exists queuedbs($machid)] != 1 } {
+ error "FAIL: replclear: machid $machid not found"
+ }
+
+ set db $queuedbs($machid)
+ set txn [$queueenv txn]
+ set dbc [$db cursor -txn $txn]
+ for { set dbt [$dbc get -rmw -first] } { [llength $dbt] > 0 } \
+ { set dbt [$dbc get -rmw -next] } {
+ error_check_good replclear($machid)_del [$dbc del] 0
+ }
+ error_check_good replclear($machid)_dbc_close [$dbc close] 0
+ error_check_good replclear($machid)_txn_commit [$txn commit] 0
+}
+
+# Add a machine to a replication environment.
+proc repladd { machid } {
+ global queueenv queuedbs machids
+
+ if { [info exists queuedbs($machid)] == 1 } {
+ error "FAIL: repladd: machid $machid already exists"
+ }
+
+ set queuedbs($machid) [berkdb open -auto_commit \
+ -env $queueenv -create -recno -renumber repqueue$machid.db]
+ error_check_good repqueue_create [is_valid_db $queuedbs($machid)] TRUE
+
+ lappend machids $machid
+}
+
+# Process a queue of messages, skipping every "skip_interval" entry.
+# We traverse the entire queue, but since we skip some messages, we
+# may end up leaving things in the queue, which should get picked up
+# on a later run.
+
+proc replprocessqueue { dbenv machid { skip_interval 0 } \
+ { hold_electp NONE } { newmasterp NONE } } {
+ global queuedbs queueenv errorCode
+
+ # hold_electp is a call-by-reference variable which lets our caller
+ # know we need to hold an election.
+ if { [string compare $hold_electp NONE] != 0 } {
+ upvar $hold_electp hold_elect
+ }
+ set hold_elect 0
+
+ # newmasterp is the same idea, only returning the ID of a master
+ # given in a DB_REP_NEWMASTER return.
+ if { [string compare $newmasterp NONE] != 0 } {
+ upvar $newmasterp newmaster
+ }
+ set newmaster 0
+
+ set nproced 0
+
+ set txn [$queueenv txn]
+ set dbc [$queuedbs($machid) cursor -txn $txn]
+
+ error_check_good process_dbc($machid) \
+ [is_valid_cursor $dbc $queuedbs($machid)] TRUE
+
+ for { set dbt [$dbc get -first] } \
+ { [llength $dbt] != 0 } \
+ { set dbt [$dbc get -next] } {
+ set data [lindex [lindex $dbt 0] 1]
+
+ # If skip_interval is nonzero, we want to process messages
+ # out of order. We do this in a simple but slimy way--
+ # continue walking with the cursor without processing the
+ # message or deleting it from the queue, but do increment
+ # "nproced". The way this proc is normally used, the
+ # precise value of nproced doesn't matter--we just don't
+ # assume the queues are empty if it's nonzero. Thus,
+ # if we contrive to make sure it's nonzero, we'll always
+ # come back to records we've skipped on a later call
+ # to replprocessqueue. (If there really are no records,
+ # we'll never get here.)
+ #
+ # Skip every skip_interval'th record (and use a remainder other
+ # than zero so that we're guaranteed to really process at least
+ # one record on every call).
+ if { $skip_interval != 0 } {
+ if { $nproced % $skip_interval == 1 } {
+ incr nproced
+ continue
+ }
+ }
+
+ # We have to play an ugly cursor game here: we currently
+ # hold a lock on the page of messages, but rep_process_message
+ # might need to lock the page with a different cursor in
+ # order to send a response. So save our recno, close
+ # the cursor, and then reopen and reset the cursor.
+ set recno [lindex [lindex $dbt 0] 0]
+ error_check_good dbc_process_close [$dbc close] 0
+ error_check_good txn_commit [$txn commit] 0
+ set ret [catch {$dbenv rep_process_message \
+ [lindex $data 2] [lindex $data 0] [lindex $data 1]} res]
+ set txn [$queueenv txn]
+ set dbc [$queuedbs($machid) cursor -txn $txn]
+ set dbt [$dbc get -set $recno]
+
+ if { $ret != 0 } {
+ if { [is_substr $res DB_REP_HOLDELECTION] } {
+ set hold_elect 1
+ } else {
+ error "FAIL:[timestamp]\
+ rep_process_message returned $res"
+ }
+ }
+
+ incr nproced
+
+ $dbc del
+
+ if { $ret == 0 && $res != 0 } {
+ if { [is_substr $res DB_REP_NEWSITE] } {
+ # NEWSITE; do nothing.
+ } else {
+ set newmaster $res
+ # Break as soon as we get a NEWMASTER message;
+ # our caller needs to handle it.
+ break
+ }
+ }
+
+ if { $hold_elect == 1 } {
+ # Break also on a HOLDELECTION, for the same reason.
+ break
+ }
+
+ }
+
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good txn_commit [$txn commit] 0
+
+ # Return the number of messages processed.
+ return $nproced
+}
+
+set run_repl_flag "-run_repl"
+
+proc extract_repl_args { args } {
+ global run_repl_flag
+
+ for { set arg [lindex $args [set i 0]] } \
+ { [string length $arg] > 0 } \
+ { set arg [lindex $args [incr i]] } {
+ if { [string compare $arg $run_repl_flag] == 0 } {
+ return [lindex $args [expr $i + 1]]
+ }
+ }
+ return ""
+}
+
+proc delete_repl_args { args } {
+ global run_repl_flag
+
+ set ret {}
+
+ for { set arg [lindex $args [set i 0]] } \
+ { [string length $arg] > 0 } \
+ { set arg [lindex $args [incr i]] } {
+ if { [string compare $arg $run_repl_flag] != 0 } {
+ lappend ret $arg
+ } else {
+ incr i
+ }
+ }
+ return $ret
+}
+
+global elect_serial
+global elections_in_progress
+set elect_serial 0
+
+# Start an election in a sub-process.
+proc start_election { qdir envstring nsites pri timeout {err "none"}} {
+ source ./include.tcl
+ global elect_serial elect_timeout elections_in_progress machids
+
+ incr elect_serial
+
+ set t [open "|$tclsh_path >& $testdir/ELECTION_OUTPUT.$elect_serial" w]
+
+ puts $t "source $test_path/test.tcl"
+ puts $t "replsetup $qdir"
+ foreach i $machids { puts $t "repladd $i" }
+ puts $t "set env_cmd \{$envstring\}"
+ puts $t "set dbenv \[eval \$env_cmd -errfile \
+ $testdir/ELECTION_ERRFILE.$elect_serial -errpfx FAIL: \]"
+# puts "Start election err $err, env $envstring"
+ puts $t "\$dbenv test abort $err"
+ puts $t "set res \[catch \{\$dbenv rep_elect $nsites $pri \
+ $elect_timeout\} ret\]"
+ if { $err != "none" } {
+ puts $t "\$dbenv test abort none"
+ puts $t "set res \[catch \{\$dbenv rep_elect $nsites $pri \
+ $elect_timeout\} ret\]"
+ }
+ flush $t
+
+ set elections_in_progress($elect_serial) $t
+ return $elect_serial
+}
+
+proc close_election { i } {
+ global elections_in_progress
+ set t $elections_in_progress($i)
+ puts $t "\$dbenv close"
+ close $t
+ unset elections_in_progress($i)
+}
+
+proc cleanup_elections { } {
+ global elect_serial elections_in_progress
+
+ for { set i 0 } { $i <= $elect_serial } { incr i } {
+ if { [info exists elections_in_progress($i)] != 0 } {
+ close_election $i
+ }
+ }
+
+ set elect_serial 0
+}
diff --git a/bdb/test/rpc001.tcl b/bdb/test/rpc001.tcl
index 331a18cfbf1..1b65639014f 100644
--- a/bdb/test/rpc001.tcl
+++ b/bdb/test/rpc001.tcl
@@ -1,17 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: rpc001.tcl,v 11.23 2001/01/02 20:04:56 sue Exp $
-#
-# Test RPC specifics, primarily that unsupported functions return
-# errors and such.
+# $Id: rpc001.tcl,v 11.33 2002/07/25 22:57:32 mjc Exp $
#
+# TEST rpc001
+# TEST Test RPC server timeouts for cursor, txn and env handles.
+# TEST Test RPC specifics, primarily that unsupported functions return
+# TEST errors and such.
proc rpc001 { } {
global __debug_on
global __debug_print
global errorInfo
+ global rpc_svc
source ./include.tcl
#
@@ -21,10 +23,10 @@ proc rpc001 { } {
set itime 10
puts "Rpc001: Server timeouts: resource $ttime sec, idle $itime sec"
if { [string compare $rpc_server "localhost"] == 0 } {
- set dpid [exec $util_path/berkeley_db_svc \
+ set dpid [exec $util_path/$rpc_svc \
-h $rpc_testdir -t $ttime -I $itime &]
} else {
- set dpid [exec rsh $rpc_server $rpc_path/berkeley_db_svc \
+ set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-h $rpc_testdir -t $ttime -I $itime&]
}
puts "\tRpc001.a: Started server, pid $dpid"
@@ -36,14 +38,14 @@ proc rpc001 { } {
set testfile "rpc001.db"
set home [file tail $rpc_testdir]
- set env [eval {berkdb env -create -mode 0644 -home $home \
+ set env [eval {berkdb_env -create -mode 0644 -home $home \
-server $rpc_server -client_timeout 10000 -txn}]
error_check_good lock_env:open [is_valid_env $env] TRUE
puts "\tRpc001.c: Opening a database"
#
# NOTE: the type of database doesn't matter, just use btree.
- set db [eval {berkdb_open -create -btree -mode 0644} \
+ set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-env $env $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -230,9 +232,10 @@ proc rpc001 { } {
#
# We need a 2nd env just to do an op to timeout the env.
+ # Make the flags different so we don't end up sharing a handle.
#
- set env1 [eval {berkdb env -create -mode 0644 -home $home \
- -server $rpc_server -client_timeout 10000 -txn}]
+ set env1 [eval {berkdb_env -create -mode 0644 -home $home \
+ -server $rpc_server -client_timeout 10000}]
error_check_good lock_env:open [is_valid_env $env1] TRUE
puts "\tRpc001.l: Timeout idle env handle"
@@ -247,7 +250,7 @@ proc rpc001 { } {
error_check_good env_timeout \
[is_substr $errorInfo "DB_NOSERVER_ID"] 1
- exec $KILL $dpid
+ tclkill $dpid
}
proc rpc_timeoutjoin {env msg sleeptime use_txn} {
@@ -257,8 +260,10 @@ proc rpc_timeoutjoin {env msg sleeptime use_txn} {
puts -nonewline "\t$msg: Test join cursors and timeouts"
if { $use_txn } {
puts " (using txns)"
+ set txnflag "-auto_commit"
} else {
puts " (without txns)"
+ set txnflag ""
}
#
# Set up a simple set of join databases
@@ -278,32 +283,32 @@ proc rpc_timeoutjoin {env msg sleeptime use_txn} {
{apple pie} {raspberry pie} {lemon pie}
}
set fdb [eval {berkdb_open -create -btree -mode 0644} \
- -env $env -dup fruit.db]
+ $txnflag -env $env -dup fruit.db]
error_check_good dbopen [is_valid_db $fdb] TRUE
set pdb [eval {berkdb_open -create -btree -mode 0644} \
- -env $env -dup price.db]
+ $txnflag -env $env -dup price.db]
error_check_good dbopen [is_valid_db $pdb] TRUE
set ddb [eval {berkdb_open -create -btree -mode 0644} \
- -env $env -dup dessert.db]
+ $txnflag -env $env -dup dessert.db]
error_check_good dbopen [is_valid_db $ddb] TRUE
foreach kd $fruit {
set k [lindex $kd 0]
set d [lindex $kd 1]
- set ret [$fdb put $k $d]
+ set ret [eval {$fdb put} $txnflag {$k $d}]
error_check_good fruit_put $ret 0
}
error_check_good sync [$fdb sync] 0
foreach kd $price {
set k [lindex $kd 0]
set d [lindex $kd 1]
- set ret [$pdb put $k $d]
+ set ret [eval {$pdb put} $txnflag {$k $d}]
error_check_good price_put $ret 0
}
error_check_good sync [$pdb sync] 0
foreach kd $dessert {
set k [lindex $kd 0]
set d [lindex $kd 1]
- set ret [$ddb put $k $d]
+ set ret [eval {$ddb put} $txnflag {$k $d}]
error_check_good dessert_put $ret 0
}
error_check_good sync [$ddb sync] 0
@@ -326,7 +331,7 @@ proc rpc_join {env msg sleep fdb pdb ddb use_txn op} {
#
set curs_list {}
set txn_list {}
- set msgnum [expr $op * 2 + 1]
+ set msgnum [expr $op * 2 + 1]
if { $use_txn } {
puts "\t$msg$msgnum: Set up txns and join cursor"
set txn [$env txn]
@@ -346,7 +351,7 @@ proc rpc_join {env msg sleep fdb pdb ddb use_txn op} {
#
# Start a cursor, (using txn child0 in the fruit and price dbs, if
- # needed). # Just pick something simple to join on.
+ # needed). # Just pick something simple to join on.
# Then call join on the dessert db.
#
set fkey yellow
@@ -372,7 +377,7 @@ proc rpc_join {env msg sleep fdb pdb ddb use_txn op} {
set ret [$jdbc get]
error_check_bad jget [llength $ret] 0
- set msgnum [expr $op * 2 + 2]
+ set msgnum [expr $op * 2 + 2]
if { $op == 1 } {
puts -nonewline "\t$msg$msgnum: Timeout all cursors"
if { $use_txn } {
diff --git a/bdb/test/rpc002.tcl b/bdb/test/rpc002.tcl
index 6b11914c2eb..4b69265bf3a 100644
--- a/bdb/test/rpc002.tcl
+++ b/bdb/test/rpc002.tcl
@@ -1,16 +1,17 @@
-# See the file LICENSE for redistribution information.
+# Sel the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: rpc002.tcl,v 1.7 2000/10/27 13:23:56 sue Exp $
+# $Id: rpc002.tcl,v 1.17 2002/07/16 20:53:03 bostic Exp $
#
-# RPC Test 2
-# Test invalid RPC functions and make sure we error them correctly
+# TEST rpc002
+# TEST Test invalid RPC functions and make sure we error them correctly
proc rpc002 { } {
global __debug_on
global __debug_print
global errorInfo
+ global rpc_svc
source ./include.tcl
set testfile "rpc002.db"
@@ -20,9 +21,9 @@ proc rpc002 { } {
#
puts "Rpc002: Unsupported interface test"
if { [string compare $rpc_server "localhost"] == 0 } {
- set dpid [exec $util_path/berkeley_db_svc -h $rpc_testdir &]
+ set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &]
} else {
- set dpid [exec rsh $rpc_server $rpc_path/berkeley_db_svc \
+ set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-h $rpc_testdir &]
}
puts "\tRpc002.a: Started server, pid $dpid"
@@ -32,7 +33,7 @@ proc rpc002 { } {
puts "\tRpc002.b: Unsupported env options"
#
# Test each "pre-open" option for env's. These need to be
- # tested on the 'berkdb env' line.
+ # tested on the 'berkdb_env' line.
#
set rlist {
{ "-data_dir $rpc_testdir" "Rpc002.b0"}
@@ -50,8 +51,8 @@ proc rpc002 { } {
{ "-verbose {recovery on}" "Rpc002.b13"}
}
- set e "berkdb env -create -mode 0644 -home $home -server $rpc_server \
- -client_timeout 10000 -txn"
+ set e "berkdb_env_noerr -create -mode 0644 -home $home \
+ -server $rpc_server -client_timeout 10000 -txn"
foreach pair $rlist {
set cmd [lindex $pair 0]
set msg [lindex $pair 1]
@@ -60,7 +61,7 @@ proc rpc002 { } {
set stat [catch {eval $e $cmd} ret]
error_check_good $cmd $stat 1
error_check_good $cmd.err \
- [is_substr $errorInfo "meaningless in RPC env"] 1
+ [is_substr $errorInfo "meaningless in an RPC env"] 1
}
#
@@ -68,7 +69,7 @@ proc rpc002 { } {
# the rest)
#
puts "\tRpc002.c: Unsupported env related interfaces"
- set env [eval {berkdb env -create -mode 0644 -home $home \
+ set env [eval {berkdb_env_noerr -create -mode 0644 -home $home \
-server $rpc_server -client_timeout 10000 -txn}]
error_check_good envopen [is_valid_env $env] TRUE
set dbcmd "berkdb_open_noerr -create -btree -mode 0644 -env $env \
@@ -89,16 +90,14 @@ proc rpc002 { } {
{ " log_archive" "Rpc002.c5"}
{ " log_file {0 0}" "Rpc002.c6"}
{ " log_flush" "Rpc002.c7"}
- { " log_get -current" "Rpc002.c8"}
- { " log_register $db $testfile" "Rpc002.c9"}
- { " log_stat" "Rpc002.c10"}
- { " log_unregister $db" "Rpc002.c11"}
- { " mpool -create -pagesize 512" "Rpc002.c12"}
- { " mpool_stat" "Rpc002.c13"}
- { " mpool_sync {0 0}" "Rpc002.c14"}
- { " mpool_trickle 50" "Rpc002.c15"}
- { " txn_checkpoint -min 1" "Rpc002.c16"}
- { " txn_stat" "Rpc002.c17"}
+ { " log_cursor" "Rpc002.c8"}
+ { " log_stat" "Rpc002.c9"}
+ { " mpool -create -pagesize 512" "Rpc002.c10"}
+ { " mpool_stat" "Rpc002.c11"}
+ { " mpool_sync {0 0}" "Rpc002.c12"}
+ { " mpool_trickle 50" "Rpc002.c13"}
+ { " txn_checkpoint -min 1" "Rpc002.c14"}
+ { " txn_stat" "Rpc002.c15"}
}
foreach pair $rlist {
@@ -109,7 +108,7 @@ proc rpc002 { } {
set stat [catch {eval $env $cmd} ret]
error_check_good $cmd $stat 1
error_check_good $cmd.err \
- [is_substr $errorInfo "meaningless in RPC env"] 1
+ [is_substr $errorInfo "meaningless in an RPC env"] 1
}
error_check_good dbclose [$db close] 0
@@ -128,7 +127,7 @@ proc rpc002 { } {
set stat [catch {eval $dbcmd} ret]
error_check_good dbopen_cache $stat 1
error_check_good dbopen_cache_err \
- [is_substr $errorInfo "meaningless in RPC env"] 1
+ [is_substr $errorInfo "meaningless in an RPC env"] 1
puts "\tRpc002.d1: Try to upgrade a database"
#
@@ -136,9 +135,9 @@ proc rpc002 { } {
set stat [catch {eval {berkdb upgrade -env} $env $testfile} ret]
error_check_good dbupgrade $stat 1
error_check_good dbupgrade_err \
- [is_substr $errorInfo "meaningless in RPC env"] 1
+ [is_substr $errorInfo "meaningless in an RPC env"] 1
error_check_good envclose [$env close] 0
- exec $KILL $dpid
+ tclkill $dpid
}
diff --git a/bdb/test/rpc003.tcl b/bdb/test/rpc003.tcl
new file mode 100644
index 00000000000..76f0dca6c07
--- /dev/null
+++ b/bdb/test/rpc003.tcl
@@ -0,0 +1,166 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rpc003.tcl,v 11.9 2002/07/16 20:53:03 bostic Exp $
+#
+# Test RPC and secondary indices.
+proc rpc003 { } {
+ source ./include.tcl
+ global dict nsecondaries
+ global rpc_svc
+
+ #
+ # First set up the files. Secondary indices only work readonly
+ # over RPC. So we need to create the databases first without
+ # RPC. Then run checking over RPC.
+ #
+ puts "Rpc003: Secondary indices over RPC"
+ if { [string compare $rpc_server "localhost"] != 0 } {
+ puts "Cannot run to non-local RPC server. Skipping."
+ return
+ }
+ cleanup $testdir NULL
+ puts "\tRpc003.a: Creating local secondary index databases"
+
+ # Primary method/args.
+ set pmethod btree
+ set pomethod [convert_method $pmethod]
+ set pargs ""
+ set methods {dbtree dbtree}
+ set argses [convert_argses $methods ""]
+ set omethods [convert_methods $methods]
+
+ set nentries 500
+
+ puts "\tRpc003.b: ($pmethod/$methods) $nentries equal key/data pairs"
+ set pname "primary003.db"
+ set snamebase "secondary003"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [berkdb_env -create -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the primary.
+ set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ # Open and associate the secondaries
+ set sdbs {}
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+
+ set did [open $dict]
+ for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+ if { [is_record_based $pmethod] == 1 } {
+ set key [expr $n + 1]
+ set datum $str
+ } else {
+ set key $str
+ gets $did datum
+ }
+ set keys($n) $key
+ set data($n) [pad_data $pmethod $datum]
+
+ set ret [eval {$pdb put} {$key [chop_data $pmethod $datum]}]
+ error_check_good put($n) $ret 0
+ }
+ close $did
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good primary_close [$pdb close] 0
+ error_check_good env_close [$env close] 0
+
+ #
+ # We have set up our databases, so now start the server and
+ # read them over RPC.
+ #
+ set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &]
+ puts "\tRpc003.c: Started server, pid $dpid"
+ tclsleep 2
+
+ set home [file tail $rpc_testdir]
+ set env [eval {berkdb_env_noerr -create -mode 0644 -home $home \
+ -server $rpc_server}]
+ error_check_good lock_env:open [is_valid_env $env] TRUE
+
+ #
+ # Attempt to send in a NULL callback to associate. It will fail
+ # if the primary and secondary are not both read-only.
+ #
+ set msg "\tRpc003.d"
+ puts "$msg: Using r/w primary and r/w secondary"
+ set popen "berkdb_open_noerr -env $env $pomethod $pargs $pname"
+ set sopen "berkdb_open_noerr -create -env $env \
+ [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
+ rpc003_assoc_err $popen $sopen $msg
+
+ set msg "\tRpc003.e"
+ puts "$msg: Using r/w primary and read-only secondary"
+ set popen "berkdb_open_noerr -env $env $pomethod $pargs $pname"
+ set sopen "berkdb_open_noerr -env $env -rdonly \
+ [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
+ rpc003_assoc_err $popen $sopen $msg
+
+ set msg "\tRpc003.f"
+ puts "$msg: Using read-only primary and r/w secondary"
+ set popen "berkdb_open_noerr -env $env $pomethod -rdonly $pargs $pname"
+ set sopen "berkdb_open_noerr -create -env $env \
+ [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
+ rpc003_assoc_err $popen $sopen $msg
+
+ # Open and associate the secondaries
+ puts "\tRpc003.g: Checking secondaries, both read-only"
+ set pdb [eval {berkdb_open_noerr -env} $env \
+ -rdonly $pomethod $pargs $pname]
+ error_check_good primary_open2 [is_valid_db $pdb] TRUE
+
+ set sdbs {}
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -env} $env -rdonly \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open2($i) [is_valid_db $sdb] TRUE
+ error_check_good db_associate2($i) \
+ [eval {$pdb associate} "" $sdb] 0
+ lappend sdbs $sdb
+ }
+ check_secondaries $pdb $sdbs $nentries keys data "Rpc003.h"
+
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good primary_close [$pdb close] 0
+ error_check_good env_close [$env close] 0
+
+ tclkill $dpid
+}
+
+proc rpc003_assoc_err { popen sopen msg } {
+ set pdb [eval $popen]
+ error_check_good assoc_err_popen [is_valid_db $pdb] TRUE
+
+ puts "$msg.0: NULL callback"
+ set sdb [eval $sopen]
+ error_check_good assoc_err_sopen [is_valid_db $sdb] TRUE
+ set stat [catch {eval {$pdb associate} "" $sdb} ret]
+ error_check_good db_associate:rdonly $stat 1
+ error_check_good db_associate:inval [is_substr $ret invalid] 1
+
+ puts "$msg.1: non-NULL callback"
+ set stat [catch {eval $pdb associate [callback_n 0] $sdb} ret]
+ error_check_good db_associate:callback $stat 1
+ error_check_good db_associate:rpc \
+ [is_substr $ret "not supported in RPC"] 1
+ error_check_good assoc_sclose [$sdb close] 0
+ error_check_good assoc_pclose [$pdb close] 0
+}
diff --git a/bdb/test/rpc004.tcl b/bdb/test/rpc004.tcl
new file mode 100644
index 00000000000..ca1462f3a89
--- /dev/null
+++ b/bdb/test/rpc004.tcl
@@ -0,0 +1,76 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rpc004.tcl,v 11.6 2002/07/16 20:53:03 bostic Exp $
+#
+# TEST rpc004
+# TEST Test RPC server and security
+proc rpc004 { } {
+ global __debug_on
+ global __debug_print
+ global errorInfo
+ global passwd
+ global rpc_svc
+ source ./include.tcl
+
+ puts "Rpc004: RPC server + security"
+ cleanup $testdir NULL
+ if { [string compare $rpc_server "localhost"] == 0 } {
+ set dpid [exec $util_path/$rpc_svc \
+ -h $rpc_testdir -P $passwd &]
+ } else {
+ set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
+ -h $rpc_testdir -P $passwd &]
+ }
+ puts "\tRpc004.a: Started server, pid $dpid"
+
+ tclsleep 2
+ remote_cleanup $rpc_server $rpc_testdir $testdir
+ puts "\tRpc004.b: Creating environment"
+
+ set testfile "rpc004.db"
+ set testfile1 "rpc004a.db"
+ set home [file tail $rpc_testdir]
+
+ set env [eval {berkdb_env -create -mode 0644 -home $home \
+ -server $rpc_server -encryptaes $passwd -txn}]
+ error_check_good lock_env:open [is_valid_env $env] TRUE
+
+ puts "\tRpc004.c: Opening a non-encrypted database"
+ #
+ # NOTE: the type of database doesn't matter, just use btree.
+ set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
+ -env $env $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ puts "\tRpc004.d: Opening an encrypted database"
+ set db1 [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
+ -env $env -encrypt $testfile1]
+ error_check_good dbopen [is_valid_db $db1] TRUE
+
+ set txn [$env txn]
+ error_check_good txn [is_valid_txn $txn $env] TRUE
+ puts "\tRpc004.e: Put/get on both databases"
+ set key "key"
+ set data "data"
+
+ set ret [$db put -txn $txn $key $data]
+ error_check_good db_put $ret 0
+ set ret [$db get -txn $txn $key]
+ error_check_good db_get $ret [list [list $key $data]]
+ set ret [$db1 put -txn $txn $key $data]
+ error_check_good db1_put $ret 0
+ set ret [$db1 get -txn $txn $key]
+ error_check_good db1_get $ret [list [list $key $data]]
+
+ error_check_good txn_commit [$txn commit] 0
+ error_check_good db_close [$db close] 0
+ error_check_good db1_close [$db1 close] 0
+ error_check_good env_close [$env close] 0
+
+ # Cleanup our environment because it's encrypted
+ remote_cleanup $rpc_server $rpc_testdir $testdir
+ tclkill $dpid
+}
diff --git a/bdb/test/rpc005.tcl b/bdb/test/rpc005.tcl
new file mode 100644
index 00000000000..f46e7355e5a
--- /dev/null
+++ b/bdb/test/rpc005.tcl
@@ -0,0 +1,137 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rpc005.tcl,v 11.4 2002/07/16 20:53:03 bostic Exp $
+#
+# TEST rpc005
+# TEST Test RPC server handle ID sharing
+proc rpc005 { } {
+ global __debug_on
+ global __debug_print
+ global errorInfo
+ global rpc_svc
+ source ./include.tcl
+
+ puts "Rpc005: RPC server handle sharing"
+ if { [string compare $rpc_server "localhost"] == 0 } {
+ set dpid [exec $util_path/$rpc_svc \
+ -h $rpc_testdir &]
+ } else {
+ set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
+ -h $rpc_testdir &]
+ }
+ puts "\tRpc005.a: Started server, pid $dpid"
+
+ tclsleep 2
+ remote_cleanup $rpc_server $rpc_testdir $testdir
+ puts "\tRpc005.b: Creating environment"
+
+ set testfile "rpc005.db"
+ set testfile1 "rpc005a.db"
+ set subdb1 "subdb1"
+ set subdb2 "subdb2"
+ set home [file tail $rpc_testdir]
+
+ set env [eval {berkdb_env -create -mode 0644 -home $home \
+ -server $rpc_server -txn}]
+ error_check_good lock_env:open [is_valid_env $env] TRUE
+
+ puts "\tRpc005.c: Compare identical and different configured envs"
+ set env_ident [eval {berkdb_env -home $home \
+ -server $rpc_server -txn}]
+ error_check_good lock_env:open [is_valid_env $env_ident] TRUE
+
+ set env_diff [eval {berkdb_env -home $home \
+ -server $rpc_server -txn nosync}]
+ error_check_good lock_env:open [is_valid_env $env_diff] TRUE
+
+ error_check_good ident:id [$env rpcid] [$env_ident rpcid]
+ error_check_bad diff:id [$env rpcid] [$env_diff rpcid]
+
+ error_check_good envclose [$env_diff close] 0
+ error_check_good envclose [$env_ident close] 0
+
+ puts "\tRpc005.d: Opening a database"
+ set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
+ -env $env $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ puts "\tRpc005.e: Compare identical and different configured dbs"
+ set db_ident [eval {berkdb_open -btree} -env $env $testfile]
+ error_check_good dbopen [is_valid_db $db_ident] TRUE
+
+ set db_diff [eval {berkdb_open -btree} -env $env -rdonly $testfile]
+ error_check_good dbopen [is_valid_db $db_diff] TRUE
+
+ set db_diff2 [eval {berkdb_open -btree} -env $env -rdonly $testfile]
+ error_check_good dbopen [is_valid_db $db_diff2] TRUE
+
+ error_check_good ident:id [$db rpcid] [$db_ident rpcid]
+ error_check_bad diff:id [$db rpcid] [$db_diff rpcid]
+ error_check_good ident2:id [$db_diff rpcid] [$db_diff2 rpcid]
+
+ error_check_good db_close [$db_ident close] 0
+ error_check_good db_close [$db_diff close] 0
+ error_check_good db_close [$db_diff2 close] 0
+ error_check_good db_close [$db close] 0
+
+ puts "\tRpc005.f: Compare with a database and subdatabases"
+ set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
+ -env $env $testfile1 $subdb1]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set dbid [$db rpcid]
+
+ set db2 [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
+ -env $env $testfile1 $subdb2]
+ error_check_good dbopen [is_valid_db $db2] TRUE
+ set db2id [$db2 rpcid]
+ error_check_bad 2subdb:id $dbid $db2id
+
+ set db_ident [eval {berkdb_open -btree} -env $env $testfile1 $subdb1]
+ error_check_good dbopen [is_valid_db $db_ident] TRUE
+ set identid [$db_ident rpcid]
+
+ set db_ident2 [eval {berkdb_open -btree} -env $env $testfile1 $subdb2]
+ error_check_good dbopen [is_valid_db $db_ident2] TRUE
+ set ident2id [$db_ident2 rpcid]
+
+ set db_diff1 [eval {berkdb_open -btree} -env $env -rdonly \
+ $testfile1 $subdb1]
+ error_check_good dbopen [is_valid_db $db_diff1] TRUE
+ set diff1id [$db_diff1 rpcid]
+
+ set db_diff2 [eval {berkdb_open -btree} -env $env -rdonly \
+ $testfile1 $subdb2]
+ error_check_good dbopen [is_valid_db $db_diff2] TRUE
+ set diff2id [$db_diff2 rpcid]
+
+ set db_diff [eval {berkdb_open -unknown} -env $env -rdonly $testfile1]
+ error_check_good dbopen [is_valid_db $db_diff] TRUE
+ set diffid [$db_diff rpcid]
+
+ set db_diff2a [eval {berkdb_open -btree} -env $env -rdonly \
+ $testfile1 $subdb2]
+ error_check_good dbopen [is_valid_db $db_diff2a] TRUE
+ set diff2aid [$db_diff2a rpcid]
+
+ error_check_good ident:id $dbid $identid
+ error_check_good ident2:id $db2id $ident2id
+ error_check_bad diff:id $dbid $diffid
+ error_check_bad diff2:id $db2id $diffid
+ error_check_bad diff3:id $diff2id $diffid
+ error_check_bad diff4:id $diff1id $diffid
+ error_check_good diff2a:id $diff2id $diff2aid
+
+ error_check_good db_close [$db_ident close] 0
+ error_check_good db_close [$db_ident2 close] 0
+ error_check_good db_close [$db_diff close] 0
+ error_check_good db_close [$db_diff1 close] 0
+ error_check_good db_close [$db_diff2 close] 0
+ error_check_good db_close [$db_diff2a close] 0
+ error_check_good db_close [$db2 close] 0
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$env close] 0
+ tclkill $dpid
+}
diff --git a/bdb/test/rsrc001.tcl b/bdb/test/rsrc001.tcl
index 6d76044f454..1d57769fda2 100644
--- a/bdb/test/rsrc001.tcl
+++ b/bdb/test/rsrc001.tcl
@@ -1,13 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: rsrc001.tcl,v 11.18 2001/01/18 06:41:03 krinsky Exp $
+# $Id: rsrc001.tcl,v 11.23 2002/01/11 15:53:33 bostic Exp $
#
-# Recno backing file test.
-# Try different patterns of adding records and making sure that the
-# corresponding file matches
+# TEST rsrc001
+# TEST Recno backing file test. Try different patterns of adding
+# TEST records and making sure that the corresponding file matches.
proc rsrc001 { } {
source ./include.tcl
@@ -47,7 +47,7 @@ proc rsrc001 { } {
# Now fill out the backing file and create the check file.
set oid1 [open $testdir/rsrc.txt a]
set oid2 [open $testdir/check.txt w]
-
+
# This one was already put into rsrc.txt.
puts $oid2 $rec1
@@ -154,15 +154,15 @@ proc rsrc001 { } {
set rec "Last record with reopen"
puts $oid $rec
- incr key
+ incr key
set ret [eval {$db put} $txn {$key $rec}]
error_check_good put_byno_with_reopen $ret 0
puts "\tRsrc001.g:\
- Put several beyond end of file, after reopen."
+ Put several beyond end of file, after reopen with snapshot."
error_check_good db_close [$db close] 0
set db [eval {berkdb_open -create -mode 0644\
- -recno -source $testdir/rsrc.txt} $testfile]
+ -snapshot -recno -source $testdir/rsrc.txt} $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
set rec "Really really last record with reopen"
@@ -171,7 +171,7 @@ proc rsrc001 { } {
puts $oid ""
puts $oid $rec
- incr key
+ incr key
incr key
incr key
incr key
@@ -179,8 +179,6 @@ proc rsrc001 { } {
set ret [eval {$db put} $txn {$key $rec}]
error_check_good put_byno_with_reopen $ret 0
-
-
error_check_good db_sync [$db sync] 0
error_check_good db_sync [$db sync] 0
diff --git a/bdb/test/rsrc002.tcl b/bdb/test/rsrc002.tcl
index d3b45c9a7f3..0cb3cf752e6 100644
--- a/bdb/test/rsrc002.tcl
+++ b/bdb/test/rsrc002.tcl
@@ -1,13 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: rsrc002.tcl,v 11.11 2000/11/29 15:01:06 sue Exp $
+# $Id: rsrc002.tcl,v 11.14 2002/01/11 15:53:33 bostic Exp $
#
-# Recno backing file test #2: test of set_re_delim.
-# Specify a backing file with colon-delimited records,
-# and make sure they are correctly interpreted.
+# TEST rsrc002
+# TEST Recno backing file test #2: test of set_re_delim. Specify a backing
+# TEST file with colon-delimited records, and make sure they are correctly
+# TEST interpreted.
proc rsrc002 { } {
source ./include.tcl
diff --git a/bdb/test/rsrc003.tcl b/bdb/test/rsrc003.tcl
index c93b3bbde12..f357a1e7f80 100644
--- a/bdb/test/rsrc003.tcl
+++ b/bdb/test/rsrc003.tcl
@@ -1,13 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: rsrc003.tcl,v 11.1 2000/11/29 18:28:49 sue Exp $
+# $Id: rsrc003.tcl,v 11.5 2002/01/11 15:53:33 bostic Exp $
#
-# Recno backing file test.
-# Try different patterns of adding records and making sure that the
-# corresponding file matches
+# TEST rsrc003
+# TEST Recno backing file test. Try different patterns of adding
+# TEST records and making sure that the corresponding file matches.
proc rsrc003 { } {
source ./include.tcl
global fixed_len
@@ -26,7 +26,7 @@ proc rsrc003 { } {
set bigrec3 [replicate "This is record 3 " 512]
set orig_fixed_len $fixed_len
- set rlist {
+ set rlist {
{{$rec1 $rec2 $rec3} "small records" }
{{$bigrec1 $bigrec2 $bigrec3} "large records" }}
@@ -65,26 +65,26 @@ proc rsrc003 { } {
puts \
"Rsrc003: Testing with disk-backed database with $msg."
}
-
+
puts -nonewline \
"\tRsrc003.a: Read file, rewrite last record;"
puts " write it out and diff"
set db [eval {berkdb_open -create -mode 0644 -recno \
-len $reclen -source $testdir/rsrc.txt} $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
-
+
# Read the last record; replace it (don't change it).
# Then close the file and diff the two files.
set txn ""
set dbc [eval {$db cursor} $txn]
error_check_good db_cursor \
[is_valid_cursor $dbc $db] TRUE
-
+
set rec [$dbc get -last]
error_check_good get_last [llength [lindex $rec 0]] 2
set key [lindex [lindex $rec 0] 0]
set data [lindex [lindex $rec 0] 1]
-
+
# Get the last record from the text file
set oid [open $testdir/rsrc.txt]
set laststr ""
@@ -95,17 +95,17 @@ proc rsrc003 { } {
close $oid
set data [sanitize_record $data]
error_check_good getlast $data $laststr
-
+
set ret [eval {$db put} $txn {$key $data}]
error_check_good replace_last $ret 0
-
+
error_check_good curs_close [$dbc close] 0
error_check_good db_sync [$db sync] 0
error_check_good db_sync [$db sync] 0
error_check_good \
diff1($testdir/rsrc.txt,$testdir/check.txt) \
[filecmp $testdir/rsrc.txt $testdir/check.txt] 0
-
+
puts -nonewline "\tRsrc003.b: "
puts "Append some records in tree and verify in file."
set oid [open $testdir/check.txt a]
@@ -124,7 +124,7 @@ proc rsrc003 { } {
set ret [filecmp $testdir/rsrc.txt $testdir/check.txt]
error_check_good \
diff2($testdir/{rsrc.txt,check.txt}) $ret 0
-
+
puts "\tRsrc003.c: Append by record number"
set oid [open $testdir/check.txt a]
for {set i 1} {$i < 10} {incr i} {
@@ -136,14 +136,14 @@ proc rsrc003 { } {
set ret [eval {$db put} $txn {$key $rec}]
error_check_good put_byno $ret 0
}
-
+
error_check_good db_sync [$db sync] 0
error_check_good db_sync [$db sync] 0
close $oid
set ret [filecmp $testdir/rsrc.txt $testdir/check.txt]
error_check_good \
diff3($testdir/{rsrc.txt,check.txt}) $ret 0
-
+
puts \
"\tRsrc003.d: Verify proper syncing of changes on close."
error_check_good Rsrc003:db_close [$db close] 0
@@ -171,4 +171,3 @@ proc rsrc003 { } {
set fixed_len $orig_fixed_len
return
}
-
diff --git a/bdb/test/rsrc004.tcl b/bdb/test/rsrc004.tcl
new file mode 100644
index 00000000000..f6c2f997eb8
--- /dev/null
+++ b/bdb/test/rsrc004.tcl
@@ -0,0 +1,52 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: rsrc004.tcl,v 11.3 2002/01/11 15:53:33 bostic Exp $
+#
+# TEST rsrc004
+# TEST Recno backing file test for EOF-terminated records.
+proc rsrc004 { } {
+ source ./include.tcl
+
+ foreach isfixed { 0 1 } {
+ cleanup $testdir NULL
+
+ # Create the backing text file.
+ set oid1 [open $testdir/rsrc.txt w]
+ if { $isfixed == 1 } {
+ puts -nonewline $oid1 "record 1xxx"
+ puts -nonewline $oid1 "record 2xxx"
+ } else {
+ puts $oid1 "record 1xxx"
+ puts $oid1 "record 2xxx"
+ }
+ puts -nonewline $oid1 "record 3"
+ close $oid1
+
+ set args "-create -mode 0644 -recno -source $testdir/rsrc.txt"
+ if { $isfixed == 1 } {
+ append args " -len [string length "record 1xxx"]"
+ set match "record 3 "
+ puts "Rsrc004: EOF-terminated recs: fixed length"
+ } else {
+ puts "Rsrc004: EOF-terminated recs: variable length"
+ set match "record 3"
+ }
+
+ puts "\tRsrc004.a: Read file, verify correctness."
+ set db [eval berkdb_open $args "$testdir/rsrc004.db"]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ # Read the last record
+ set dbc [eval {$db cursor} ""]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+
+ set rec [$dbc get -last]
+ error_check_good get_last $rec [list [list 3 $match]]
+
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good db_close [$db close] 0
+ }
+}
diff --git a/bdb/test/scr001/chk.code b/bdb/test/scr001/chk.code
new file mode 100644
index 00000000000..eb01d8614b3
--- /dev/null
+++ b/bdb/test/scr001/chk.code
@@ -0,0 +1,37 @@
+#!/bin/sh -
+#
+# $Id: chk.code,v 1.10 2002/02/04 16:03:26 bostic Exp $
+#
+# Check to make sure that the code samples in the documents build.
+
+d=../..
+
+[ -d $d/docs_src ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+[ -f ../libdb.a ] || (cd .. && make libdb.a) || {
+ echo 'FAIL: unable to find or build libdb.a'
+ exit 1
+}
+
+for i in `find $d/docs_src -name '*.cs'`; do
+ echo " compiling $i"
+ sed -e 's/m4_include(\(.*\))/#include <\1>/g' \
+ -e 's/m4_[a-z]*[(\[)]*//g' \
+ -e 's/(\[//g' \
+ -e '/argv/!s/])//g' \
+ -e 's/dnl//g' \
+ -e 's/__GT__/>/g' \
+ -e 's/__LB__/[/g' \
+ -e 's/__LT__/</g' \
+ -e 's/__RB__/]/g' < $i > t.c
+ if cc -Wall -Werror -I.. t.c ../libdb.a -o t; then
+ :
+ else
+ echo "FAIL: unable to compile $i"
+ exit 1
+ fi
+done
+
+exit 0
diff --git a/bdb/test/scr002/chk.def b/bdb/test/scr002/chk.def
new file mode 100644
index 00000000000..7d5e6670f63
--- /dev/null
+++ b/bdb/test/scr002/chk.def
@@ -0,0 +1,64 @@
+#!/bin/sh -
+#
+# $Id: chk.def,v 1.9 2002/03/27 04:32:57 bostic Exp $
+#
+# Check to make sure we haven't forgotten to add any interfaces
+# to the Win32 libdb.def file.
+
+d=../..
+
+# Test must be run from the top-level directory, not from a test directory.
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+f=$d/build_win32/libdb.def
+t1=__1
+t2=__2
+
+exitv=0
+
+sed '/; /d' $f |
+ egrep @ |
+ awk '{print $1}' |
+ sed -e '/db_xa_switch/d' \
+ -e '/^__/d' -e '/^;/d' |
+ sort > $t1
+
+egrep __P $d/dbinc_auto/ext_prot.in |
+ sed '/^[a-z]/!d' |
+ awk '{print $2}' |
+ sed 's/^\*//' |
+ sed '/^__/d' | sort > $t2
+
+if cmp -s $t1 $t2 ; then
+ :
+else
+ echo "<<< libdb.def >>> DB include files"
+ diff $t1 $t2
+ echo "FAIL: missing items in libdb.def file."
+ exitv=1
+fi
+
+# Check to make sure we don't have any extras in the libdb.def file.
+sed '/; /d' $f |
+ egrep @ |
+ awk '{print $1}' |
+ sed -e '/__db_global_values/d' > $t1
+
+for i in `cat $t1`; do
+ if egrep $i $d/*/*.c > /dev/null; then
+ :
+ else
+ echo "$f: $i not found in DB sources"
+ fi
+done > $t2
+
+test -s $t2 && {
+ cat $t2
+ echo "FAIL: found unnecessary items in libdb.def file."
+ exitv=1
+}
+
+exit $exitv
diff --git a/bdb/test/scr003/chk.define b/bdb/test/scr003/chk.define
new file mode 100644
index 00000000000..f73355eddf6
--- /dev/null
+++ b/bdb/test/scr003/chk.define
@@ -0,0 +1,77 @@
+#!/bin/sh -
+#
+# $Id: chk.define,v 1.21 2002/03/27 04:32:58 bostic Exp $
+#
+# Check to make sure that all #defines are actually used.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+exitv=0
+t1=__1
+t2=__2
+t3=__3
+
+egrep '^#define' $d/dbinc/*.h $d/dbinc/*.in |
+ sed -e '/db_185.in/d' -e '/xa.h/d' |
+ awk '{print $2}' |
+ sed -e '/^B_DELETE/d' \
+ -e '/^B_MAX/d' \
+ -e '/^CIRCLEQ_/d' \
+ -e '/^DB_BTREEOLDVER/d' \
+ -e '/^DB_HASHOLDVER/d' \
+ -e '/^DB_LOCKVERSION/d' \
+ -e '/^DB_MAX_PAGES/d' \
+ -e '/^DB_QAMOLDVER/d' \
+ -e '/^DB_TXNVERSION/d' \
+ -e '/^DB_UNUSED/d' \
+ -e '/^DEFINE_DB_CLASS/d' \
+ -e '/^HASH_UNUSED/d' \
+ -e '/^LIST_/d' \
+ -e '/^LOG_OP/d' \
+ -e '/^MINFILL/d' \
+ -e '/^MUTEX_FIELDS/d' \
+ -e '/^NCACHED2X/d' \
+ -e '/^NCACHED30/d' \
+ -e '/^PAIR_MASK/d' \
+ -e '/^P_16_COPY/d' \
+ -e '/^P_32_COPY/d' \
+ -e '/^P_32_SWAP/d' \
+ -e '/^P_TO_UINT16/d' \
+ -e '/^QPAGE_CHKSUM/d' \
+ -e '/^QPAGE_NORMAL/d' \
+ -e '/^QPAGE_SEC/d' \
+ -e '/^SH_CIRCLEQ_/d' \
+ -e '/^SH_LIST_/d' \
+ -e '/^SH_TAILQ_/d' \
+ -e '/^SIZEOF_PAGE/d' \
+ -e '/^TAILQ_/d' \
+ -e '/^WRAPPED_CLASS/d' \
+ -e '/^__BIT_TYPES_DEFINED__/d' \
+ -e '/^__DBC_INTERNAL/d' \
+ -e '/^i_/d' \
+ -e '/_H_/d' \
+ -e 's/(.*//' | sort > $t1
+
+find $d -name '*.c' -o -name '*.cpp' > $t2
+for i in `cat $t1`; do
+ if egrep -w $i `cat $t2` > /dev/null; then
+ :;
+ else
+ f=`egrep -l "#define.*$i" $d/dbinc/*.h $d/dbinc/*.in |
+ sed 's;\.\.\/\.\.\/dbinc/;;' | tr -s "[:space:]" " "`
+ echo "FAIL: $i: $f"
+ fi
+done | sort -k 2 > $t3
+
+test -s $t3 && {
+ cat $t3
+ echo "FAIL: found unused #defines"
+ exit 1
+}
+
+exit $exitv
diff --git a/bdb/test/scr004/chk.javafiles b/bdb/test/scr004/chk.javafiles
new file mode 100644
index 00000000000..d30c5e3e779
--- /dev/null
+++ b/bdb/test/scr004/chk.javafiles
@@ -0,0 +1,31 @@
+#!/bin/sh -
+#
+# $Id: chk.javafiles,v 1.5 2002/01/30 19:50:52 bostic Exp $
+#
+# Check to make sure we haven't forgotten to add any Java files to the list
+# of source files in the Makefile.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+f=$d/dist/Makefile.in
+j=$d/java/src/com/sleepycat
+
+t1=__1
+t2=__2
+
+find $j/db/ $j/examples $d/rpc_server/java -name \*.java -print |
+ sed -e 's/^.*\///' | sort > $t1
+tr ' \t' '\n' < $f | sed -e '/\.java$/!d' -e 's/^.*\///' | sort > $t2
+
+cmp $t1 $t2 > /dev/null || {
+ echo "<<< java source files >>> Makefile"
+ diff $t1 $t2
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/scr005/chk.nl b/bdb/test/scr005/chk.nl
new file mode 100644
index 00000000000..47c7ff74d4b
--- /dev/null
+++ b/bdb/test/scr005/chk.nl
@@ -0,0 +1,112 @@
+#!/bin/sh -
+#
+# $Id: chk.nl,v 1.6 2002/01/07 15:12:12 bostic Exp $
+#
+# Check to make sure that there are no trailing newlines in __db_err calls.
+
+d=../..
+
+[ -f $d/README ] || {
+ echo "FAIL: chk.nl can't find the source directory."
+ exit 1
+}
+
+cat << END_OF_CODE > t.c
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+int chk(FILE *, char *);
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ FILE *fp;
+ int exitv;
+
+ for (exitv = 0; *++argv != NULL;) {
+ if ((fp = fopen(*argv, "r")) == NULL) {
+ fprintf(stderr, "%s: %s\n", *argv, strerror(errno));
+ return (1);
+ }
+ if (chk(fp, *argv))
+ exitv = 1;
+ (void)fclose(fp);
+ }
+ return (exitv);
+}
+
+int
+chk(fp, name)
+ FILE *fp;
+ char *name;
+{
+ int ch, exitv, line, q;
+
+ exitv = 0;
+ for (ch = 'a', line = 1;;) {
+ if ((ch = getc(fp)) == EOF)
+ return (exitv);
+ if (ch == '\n') {
+ ++line;
+ continue;
+ }
+ if (ch != '_') continue;
+ if ((ch = getc(fp)) != '_') continue;
+ if ((ch = getc(fp)) != 'd') continue;
+ if ((ch = getc(fp)) != 'b') continue;
+ if ((ch = getc(fp)) != '_') continue;
+ if ((ch = getc(fp)) != 'e') continue;
+ if ((ch = getc(fp)) != 'r') continue;
+ if ((ch = getc(fp)) != 'r') continue;
+ while ((ch = getc(fp)) != '"') {
+ if (ch == EOF)
+ return (exitv);
+ if (ch == '\n')
+ ++line;
+ }
+ while ((ch = getc(fp)) != '"')
+ switch (ch) {
+ case EOF:
+ return (exitv);
+ case '\\n':
+ ++line;
+ break;
+ case '.':
+ if ((ch = getc(fp)) != '"')
+ ungetc(ch, fp);
+ else {
+ fprintf(stderr,
+ "%s: <period> at line %d\n", name, line);
+ exitv = 1;
+ }
+ break;
+ case '\\\\':
+ if ((ch = getc(fp)) != 'n')
+ ungetc(ch, fp);
+ else if ((ch = getc(fp)) != '"')
+ ungetc(ch, fp);
+ else {
+ fprintf(stderr,
+ "%s: <newline> at line %d\n", name, line);
+ exitv = 1;
+ }
+ break;
+ }
+ }
+ return (exitv);
+}
+END_OF_CODE
+
+cc t.c -o t
+if ./t $d/*/*.[ch] $d/*/*.cpp $d/*/*.in ; then
+ :
+else
+ echo "FAIL: found __db_err calls ending with periods/newlines."
+ exit 1
+fi
+
+exit 0
diff --git a/bdb/test/scr006/chk.offt b/bdb/test/scr006/chk.offt
new file mode 100644
index 00000000000..6800268d2a2
--- /dev/null
+++ b/bdb/test/scr006/chk.offt
@@ -0,0 +1,36 @@
+#!/bin/sh -
+#
+# $Id: chk.offt,v 1.9 2001/10/26 13:40:15 bostic Exp $
+#
+# Make sure that no off_t's have snuck into the release.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t=__1
+
+egrep -w off_t $d/*/*.[ch] $d/*/*.in |
+sed -e "/#undef off_t/d" \
+ -e "/mp_fopen.c:.*can't use off_t's here/d" \
+ -e "/mp_fopen.c:.*size or type off_t's or/d" \
+ -e "/mp_fopen.c:.*where an off_t is 32-bits/d" \
+ -e "/mutex\/tm.c:/d" \
+ -e "/os_map.c:.*(off_t)0))/d" \
+ -e "/os_rw.c:.*(off_t)db_iop->pgno/d" \
+ -e "/os_seek.c:.*off_t offset;/d" \
+ -e "/os_seek.c:.*offset = /d" \
+ -e "/test_perf\/perf_misc.c:/d" \
+ -e "/test_server\/dbs.c:/d" \
+ -e "/test_vxworks\/vx_mutex.c:/d" > $t
+
+test -s $t && {
+ cat $t
+ echo "FAIL: found questionable off_t usage"
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/scr007/chk.proto b/bdb/test/scr007/chk.proto
new file mode 100644
index 00000000000..ae406fa23fe
--- /dev/null
+++ b/bdb/test/scr007/chk.proto
@@ -0,0 +1,45 @@
+#!/bin/sh -
+#
+# $Id: chk.proto,v 1.8 2002/03/27 04:32:59 bostic Exp $
+#
+# Check to make sure that prototypes are actually needed.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t1=__1
+t2=__2
+t3=__3
+
+egrep '__P' $d/dbinc_auto/*.h |
+ sed -e 's/[ ][ ]*__P.*//' \
+ -e 's/^.*[ *]//' \
+ -e '/__db_cprint/d' \
+ -e '/__db_lprint/d' \
+ -e '/__db_noop_log/d' \
+ -e '/__db_prnpage/d' \
+ -e '/__db_txnlist_print/d' \
+ -e '/__db_util_arg/d' \
+ -e '/__ham_func2/d' \
+ -e '/__ham_func3/d' \
+ -e '/_getpgnos/d' \
+ -e '/_print$/d' \
+ -e '/_read$/d' > $t1
+
+find $d -name '*.in' -o -name '*.[ch]' -o -name '*.cpp' > $t2
+for i in `cat $t1`; do
+ c=$(egrep -low $i $(cat $t2) | wc -l)
+ echo "$i: $c"
+done | egrep ' 1$' > $t3
+
+test -s $t3 && {
+ cat $t3
+ echo "FAIL: found unnecessary prototypes."
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/scr008/chk.pubdef b/bdb/test/scr008/chk.pubdef
new file mode 100644
index 00000000000..4f59e831b25
--- /dev/null
+++ b/bdb/test/scr008/chk.pubdef
@@ -0,0 +1,179 @@
+#!/bin/sh -
+#
+# Reconcile the list of public defines with the man pages and the Java files.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+p=$d/dist/pubdef.in
+
+exitv=0
+
+# Check that pubdef.in has everything listed in m4.links.
+f=$d/docs_src/m4/m4.links
+sed -n \
+ -e 's/^\$1, \(DB_[^,]*\).*/\1/p' \
+ -e d < $f |
+while read name; do
+ if `egrep -w "$name" $p > /dev/null`; then
+ :
+ else
+ echo "$f: $name is missing from $p"
+ exitv=1
+ fi
+done
+
+# Check that m4.links has everything listed in pubdef.in.
+f=$d/docs_src/m4/m4.links
+sed '/^#/d' $p |
+while read name isdoc isinc isjava; do
+ if `egrep -w "^.1, $name" $f > /dev/null`; then
+ [ "X$isdoc" != "XD" ] && {
+ echo "$name should not appear in $f"
+ exitv=1
+ }
+ else
+ [ "X$isdoc" = "XD" ] && {
+ echo "$name does not appear in $f"
+ exitv=1;
+ }
+ fi
+done
+
+# Check that pubdef.in has everything listed in db.in.
+f=$d/dbinc/db.in
+sed -n \
+ -e 's/^#define[ ]*\(DB_[A-Z_0-9]*\).*/\1/p' \
+ -e 's/^[ ]*\(DB_[A-Z_]*\)=[0-9].*/\1/p' \
+ -e d < $f |
+while read name; do
+ if `egrep -w "$name" $p > /dev/null`; then
+ :
+ else
+ echo "$f: $name is missing from $p"
+ exitv=1
+ fi
+done
+
+# Check that db.in has everything listed in pubdef.in.
+f=$d/dbinc/db.in
+sed '/^#/d' $p |
+while read name isdoc isinc isjava; do
+ if `egrep -w "#define[ ]$name|[ ][ ]*$name=[0-9][0-9]*" \
+ $f > /dev/null`; then
+ [ "X$isinc" != "XI" ] && {
+ echo "$name should not appear in $f"
+ exitv=1
+ }
+ else
+ [ "X$isinc" = "XI" ] && {
+ echo "$name does not appear in $f"
+ exitv=1
+ }
+ fi
+done
+
+# Check that pubdef.in has everything listed in DbConstants.java.
+f=$d/java/src/com/sleepycat/db/DbConstants.java
+sed -n -e 's/.*static final int[ ]*\([^ ]*\).*/\1/p' < $f |
+while read name; do
+ if `egrep -w "$name" $p > /dev/null`; then
+ :
+ else
+ echo "$f: $name is missing from $p"
+ exitv=1
+ fi
+done
+
+# Check that DbConstants.java has everything listed in pubdef.in.
+f=$d/java/src/com/sleepycat/db/DbConstants.java
+sed '/^#/d' $p |
+while read name isdoc isinc isjava; do
+ if `egrep -w "static final int[ ]$name =" $f > /dev/null`; then
+ [ "X$isjava" != "XJ" ] && {
+ echo "$name should not appear in $f"
+ exitv=1
+ }
+ else
+ [ "X$isjava" = "XJ" ] && {
+ echo "$name does not appear in $f"
+ exitv=1
+ }
+ fi
+done
+
+# Check that pubdef.in has everything listed in Db.java.
+f=$d/java/src/com/sleepycat/db/Db.java
+sed -n -e 's/.*static final int[ ]*\([^ ;]*\).*/\1/p' < $f |
+while read name; do
+ if `egrep -w "$name" $p > /dev/null`; then
+ :
+ else
+ echo "$f: $name is missing from $p"
+ exitv=1;
+ fi
+done
+sed -n -e 's/^[ ]*\([^ ]*\) = DbConstants\..*/\1/p' < $f |
+while read name; do
+ if `egrep -w "$name" $p > /dev/null`; then
+ :
+ else
+ echo "$f: $name is missing from $p"
+ exitv=1
+ fi
+done
+
+# Check that Db.java has all of the Java case values listed in pubdef.in.
+# Any J entries should appear twice -- once as a static final int, with
+# no initialization value, and once assigned to the DbConstants value. Any
+# C entries should appear once as a static final int, with an initialization
+# value.
+f=$d/java/src/com/sleepycat/db/Db.java
+sed '/^#/d' $p |
+while read name isdoc isinc isjava; do
+ if `egrep -w "static final int[ ]$name;$" $f > /dev/null`; then
+ [ "X$isjava" != "XJ" ] && {
+ echo "$name should not appear in $f"
+ exitv=1
+ }
+ else
+ [ "X$isjava" = "XJ" ] && {
+ echo "$name does not appear in $f"
+ exitv=1
+ }
+ fi
+done
+sed '/^#/d' $p |
+while read name isdoc isinc isjava; do
+ if `egrep -w "= DbConstants.$name;" $f > /dev/null`; then
+ [ "X$isjava" != "XJ" ] && {
+ echo "$name should not appear in $f"
+ exitv=1
+ }
+ else
+ [ "X$isjava" = "XJ" ] && {
+ echo "$name does not appear in $f"
+ exitv=1
+ }
+ fi
+done
+sed '/^#/d' $p |
+while read name isdoc isinc isjava; do
+ if `egrep "static final int[ ]$name =.*;" $f > /dev/null`; then
+ [ "X$isjava" != "XC" ] && {
+ echo "$name should not appear in $f"
+ exitv=1
+ }
+ else
+ [ "X$isjava" = "XC" ] && {
+ echo "$name does not appear in $f"
+ exitv=1
+ }
+ fi
+done
+
+exit $exitv
diff --git a/bdb/test/scr009/chk.srcfiles b/bdb/test/scr009/chk.srcfiles
new file mode 100644
index 00000000000..4f09a2890f6
--- /dev/null
+++ b/bdb/test/scr009/chk.srcfiles
@@ -0,0 +1,39 @@
+#!/bin/sh -
+#
+# $Id: chk.srcfiles,v 1.10 2002/02/04 22:25:33 bostic Exp $
+#
+# Check to make sure we haven't forgotten to add any files to the list
+# of source files Win32 uses to build its dsp files.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+f=$d/dist/srcfiles.in
+t1=__1
+t2=__2
+
+sed -e '/^[ #]/d' \
+ -e '/^$/d' < $f |
+ awk '{print $1}' > $t1
+find $d -type f |
+ sed -e 's/^\.\.\/\.\.\///' \
+ -e '/^build[^_]/d' \
+ -e '/^test\//d' \
+ -e '/^test_server/d' \
+ -e '/^test_thread/d' \
+ -e '/^test_vxworks/d' |
+ egrep '\.c$|\.cpp$|\.def$|\.rc$' |
+ sed -e '/perl.DB_File\/version.c/d' |
+ sort > $t2
+
+cmp $t1 $t2 > /dev/null || {
+ echo "<<< srcfiles.in >>> existing files"
+ diff $t1 $t2
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/scr010/chk.str b/bdb/test/scr010/chk.str
new file mode 100644
index 00000000000..2b5698c0ff2
--- /dev/null
+++ b/bdb/test/scr010/chk.str
@@ -0,0 +1,31 @@
+#!/bin/sh -
+#
+# $Id: chk.str,v 1.5 2001/10/12 17:55:36 bostic Exp $
+#
+# Check spelling in quoted strings.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t1=__t1
+
+sed -e '/^#include/d' \
+ -e '/revid/d' \
+ -e '/"/!d' \
+ -e 's/^[^"]*//' \
+ -e 's/%s/ /g' \
+ -e 's/[^"]*$//' \
+ -e 's/\\[nt]/ /g' $d/*/*.c $d/*/*.cpp |
+spell | sort | comm -23 /dev/stdin spell.ok > $t1
+
+test -s $t1 && {
+ cat $t1
+ echo "FAIL: found questionable spelling in strings."
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/scr010/spell.ok b/bdb/test/scr010/spell.ok
new file mode 100644
index 00000000000..18af8d1306d
--- /dev/null
+++ b/bdb/test/scr010/spell.ok
@@ -0,0 +1,825 @@
+AES
+AJVX
+ALLDB
+API
+APP
+AccessExample
+Acflmo
+Aclmop
+Ahlm
+Ahm
+BCFILprRsvVxX
+BCc
+BDBXXXXXX
+BH
+BI
+BII
+BINTERNAL
+BTREE
+Bc
+BerkeleyDB
+BtRecExample
+Btree
+CD
+CDB
+CDS
+CDdFILTVvX
+CFILpRsv
+CFLprsvVxX
+CFh
+CHKSUM
+CLpsvxX
+CONFIG
+CdFILTvX
+ClassNotFoundException
+Config
+DBC
+DBENV
+DBP
+DBS
+DBSDIR
+DBT
+DBTYPE
+DBcursor
+DONOTINDEX
+DS
+DUP
+DUPMASTER
+DUPSORT
+Db
+DbAppendRecno
+DbAttachImpl
+DbBtreeCompare
+DbBtreePrefix
+DbBtreeStat
+DbDeadlockException
+DbDupCompare
+DbEnv
+DbEnvFeedback
+DbErrcall
+DbException
+DbFeedback
+DbHash
+DbHashStat
+DbKeyRange
+DbLock
+DbLockNotGrantedException
+DbLockRequest
+DbLockStat
+DbLogStat
+DbLogc
+DbLsn
+DbMemoryException
+DbMpoolFStat
+DbMpoolFile
+DbMpoolStat
+DbPreplist
+DbQueueStat
+DbRecoveryInit
+DbRepStat
+DbRepTransport
+DbRunRecoveryException
+DbSecondaryKeyCreate
+DbTxn
+DbTxnRecover
+DbTxnStat
+DbUtil
+DbXAResource
+DbXid
+Dbc
+Dbt
+Dde
+Deref'ing
+EIO
+EIRT
+EIi
+ENV
+EnvExample
+EnvInfoDelete
+Exp
+FIXEDLEN
+Fd
+Ff
+Fh
+FileNotFoundException
+GetFileInformationByHandle
+GetJavaVM
+GetJoin
+HOFFSET
+HOLDELECTION
+Hashtable
+ILo
+ILprR
+INDX
+INIT
+IREAD
+ISSET
+IWR
+IWRITE
+Ik
+KEYEMPTY
+KEYEXIST
+KeyRange
+LBTREE
+LOCKDOWN
+LOGC
+LRECNO
+LRU
+LSN
+Lcom
+Ljava
+Ll
+LockExample
+LogRegister
+LpRsS
+LprRsS
+MEM
+MMDDhhmm
+MPOOL
+MPOOLFILE
+MapViewOfFile
+Maxid
+Mb
+Mbytes
+Metadata
+Metapage
+Mpool
+MpoolExample
+Mutex
+NEWMASTER
+NEWSITE
+NG
+NODUP
+NODUPDATA
+NOLOCKING
+NOMMAP
+NOMORE
+NOORDERCHK
+NOPANIC
+NOSERVER
+NOSYNC
+NOTFOUND
+NOTGRANTED
+NOTYPE
+NOWAIT
+NP
+NoP
+NoqV
+NqV
+NrV
+NsV
+OLDVERSION
+ORDERCHKONLY
+Offpage
+OpenFileMapping
+OutputStream
+PGNO
+PID
+PREV
+Pgno
+RECNO
+RECNOSYNC
+RECNUM
+RINTERNAL
+RMW
+RPC
+RT
+RUNRECOVERY
+Recno
+RepElectResult
+RepProcessMessage
+SERVERPROG
+SERVERVERS
+SETFD
+SHA
+SS
+Shm
+Sleepycat
+Subdatabase
+TDS
+TESTDIR
+TID
+TMP
+TMPDIR
+TODO
+TPS
+TXN
+TXNID
+TXNs
+Tcl
+TempFolder
+TestKeyRange
+TestLogc
+TpcbExample
+Tt
+Txn
+Txnid
+Txns
+UID
+UNAVAIL
+USERMEM
+Unencrypted
+UnmapViewOfFile
+VM
+VX
+Vv
+VvW
+VvXxZ
+Vvw
+Vx
+VxWorks
+Waitsfor
+XA
+XAException
+Xid
+XxZ
+YIELDCPU
+YY
+abc
+abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
+abcdef
+abs
+addpage
+addr
+addrem
+adj
+afterop
+ahr
+alldb
+alloc
+alsVv
+amx
+anum
+appl
+appname
+archivedir
+arg
+args
+ata
+badkey
+berkdb
+berkeley
+bfname
+bfree
+bigpages
+bnum
+bostic
+bqual
+bsize
+bt
+btcompare
+btrec
+btree
+buf
+bylsn
+bypage
+byteswap
+byteswapped
+bytevalue
+cachesize
+cadjust
+callpgin
+cd
+cdb
+cdel
+ceVv
+ceh
+celmNrtVZ
+celmNtV
+celmNtVZ
+cget
+charkey
+charset
+chgpg
+chkpoint
+chkpt
+chksum
+ckp
+cksum
+clearerr
+clientrun
+cmdargs
+cnt
+compareproc
+compat
+conf
+config
+copypage
+cp
+crdel
+creat
+curadj
+curlsn
+datalen
+db
+dbc
+dbclient
+dbclose
+dbe
+dbenv
+dbkill
+dbm
+dbmclose
+dbminit
+dbobj
+dbopen
+dbp
+dbreg
+dbremove
+dbrename
+dbs
+dbt
+dbtruncate
+dbverify
+dd
+def
+del
+delext
+delim
+dev
+df
+dh
+dir
+dirfno
+dist
+dists
+dlen
+ds
+dsize
+dup
+dup'ed
+dupcompare
+dups
+dupset
+dupsort
+efh
+eid
+electinit
+electsend
+electvote
+electwait
+encryptaes
+encryptany
+endian
+env
+envid
+envremove
+eof
+errcall
+errfile
+errno
+errpfx
+excl
+extentsize
+faststat
+fclose
+fcntl
+fcreate
+fd
+ff
+ffactor
+fget
+fh
+fid
+fileid
+fileopen
+firstkey
+fiv
+flushcommit
+foo
+fopen
+formatID
+fput
+freelist
+fset
+fstat
+fsync
+ftype
+func
+fv
+gbytes
+gc'ed
+gen
+getBranchQualifier
+getFormatId
+getGlobalTransactionId
+gettime
+gettimeofday
+gettype
+getval
+gid
+groupalloc
+gtrid
+hashproc
+hcreate
+hdestroy
+hdr
+hostname
+hsearch
+icursor
+idletimeout
+ids
+idup
+iitem
+inc
+incfirst
+indx
+init
+inlen
+inp
+insdel
+int
+intValue
+io
+iread
+isdeleted
+itemorder
+iter
+iwr
+iwrite
+javax
+kb
+kbyte
+kbytes
+keyfirst
+keygroup
+keygroups
+keygrp
+keylast
+keyrange
+killinterval
+killiteration
+killtest
+klNpP
+klNprRV
+klNprRs
+krinsky
+lM
+lP
+lang
+lastid
+ld
+len
+lf
+lg
+libdb
+lk
+llsn
+localhost
+localtime
+lockid
+logc
+logclean
+logfile
+logflush
+logsonly
+lorder
+lpgno
+lsVv
+lsn
+lsynch
+lt
+lu
+luB
+luGB
+luKB
+luKb
+luM
+luMB
+luMb
+lx
+mNP
+mNs
+machid
+makedup
+malloc
+margo
+maxcommitperflush
+maxkey
+maxlockers
+maxlocks
+maxnactive
+maxnlockers
+maxnlocks
+maxnobjects
+maxobjects
+maxops
+maxtimeout
+maxtxns
+mbytes
+mem
+memp
+metadata
+metaflags
+metagroup
+metalsn
+metapage
+metasub
+methodID
+mincommitperflush
+minkey
+minlocks
+minwrite
+minwrites
+mis
+mjc
+mkdir
+mlock
+mmap
+mmapped
+mmapsize
+mmetalsn
+mmpgno
+mp
+mpf
+mpgno
+mpool
+msg
+munmap
+mutex
+mutexes
+mutexlocks
+mv
+mvptr
+mydrive
+mydrivexxx
+nO
+nP
+nTV
+nTt
+naborts
+nactive
+nbegins
+nbytes
+ncaches
+ncommits
+nconflicts
+ndata
+ndbm
+ndeadlocks
+ndx
+needswap
+nelem
+nevict
+newalloc
+newclient
+newfile
+newitem
+newmaster
+newname
+newpage
+newpgno
+newsite
+nextdup
+nextkey
+nextlsn
+nextnodup
+nextpgno
+ng
+nitems
+nkeys
+nlockers
+nlocks
+nlsn
+nmodes
+nnext
+nnextlsn
+nnowaits
+nobjects
+nodup
+nodupdata
+nogrant
+nolocking
+nommap
+noop
+nooverwrite
+nopanic
+nosort
+nosync
+notfound
+notgranted
+nowait
+nowaits
+npages
+npgno
+nrec
+nrecords
+nreleases
+nrequests
+nrestores
+nsites
+ntasks
+nthreads
+num
+numdup
+obj
+offpage
+ok
+olddata
+olditem
+oldname
+opd
+opflags
+opmods
+orig
+os
+osynch
+outlen
+ovfl
+ovflpoint
+ovflsize
+ovref
+pageimage
+pagelsn
+pageno
+pagesize
+pagesizes
+pagfno
+panic'ing
+paniccall
+panicstate
+parentid
+passwd
+perf
+perfdb
+pflag
+pg
+pgcookie
+pgdbt
+pget
+pgfree
+pgin
+pgno
+pgnum
+pgout
+pgsize
+pid
+pkey
+plist
+pn
+postdestroy
+postlog
+postlogmeta
+postopen
+postsync
+prR
+prec
+predestroy
+preopen
+prev
+prevlsn
+prevnodup
+prheader
+pri
+printlog
+proc
+procs
+pthread
+pthreads
+ptype
+pv
+qV
+qam
+qs
+qtest
+rRV
+rRs
+rV
+rand
+rcuradj
+rdonly
+readd
+readonly
+realloc
+rec
+reclength
+recno
+recnum
+recnums
+recs
+refcount
+regionmax
+regop
+regsize
+relink
+repl
+revsplitoff
+rf
+rkey
+rlsn
+rm
+rmid
+rmw
+ro
+rootent
+rootlsn
+rpc
+rpcid
+rs
+rsplit
+runlog
+rw
+rwrw
+rwrwrw
+sS
+sV
+sVv
+scount
+secon
+secs
+sendproc
+seq
+setto
+setval
+sh
+shalloc
+shm
+shmat
+shmctl
+shmdt
+shmem
+shmget
+shr
+sleepycat
+splitdata
+splitmeta
+srand
+stat
+str
+strcmp
+strdup
+strerror
+strlen
+subdatabase
+subdb
+sv
+svc
+tV
+tVZ
+tas
+tcl
+tcp
+thr
+threadID
+tid
+tiebreaker
+timestamp
+tlen
+tm
+tmp
+tmpdir
+tmutex
+tnum
+tp
+tpcb
+treeorder
+ttpcbddlk
+ttpcbi
+ttpcbr
+ttype
+tx
+txn
+txnarray
+txnid
+txns
+txt
+ubell
+ud
+uid
+ulen
+uncorrect
+undeleting
+unmap
+unpinned
+upd
+upi
+usec
+usecs
+usr
+util
+vVxXZ
+vZ
+val
+var
+vec
+ver
+vflag
+vrfy
+vw
+vx
+vxmutex
+vxtmp
+waitsfor
+walkdupint
+walkpages
+wb
+wc
+wcount
+wordlist
+writeable
+wrnosync
+wt
+xa
+xid
+xxx
+yieldcpu
diff --git a/bdb/test/scr011/chk.tags b/bdb/test/scr011/chk.tags
new file mode 100644
index 00000000000..14a3c4e011d
--- /dev/null
+++ b/bdb/test/scr011/chk.tags
@@ -0,0 +1,41 @@
+#!/bin/sh -
+#
+# $Id: chk.tags,v 1.10 2001/10/12 17:55:36 bostic Exp $
+#
+# Check to make sure we don't need any more symbolic links to tags files.
+
+d=../..
+
+# Test must be run from the top-level directory, not from a test directory.
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t1=__1
+t2=__2
+
+(cd $d && ls -F | egrep / | sort |
+ sed -e 's/\///' \
+ -e '/^CVS$/d' \
+ -e '/^build_vxworks$/d' \
+ -e '/^build_win32$/d' \
+ -e '/^docs$/d' \
+ -e '/^docs_book$/d' \
+ -e '/^docs_src$/d' \
+ -e '/^java$/d' \
+ -e '/^perl$/d' \
+ -e '/^test$/d' \
+ -e '/^test_cxx$/d' \
+ -e '/^test_purify$/d' \
+ -e '/^test_thread$/d' \
+ -e '/^test_vxworks$/d') > $t1
+
+(cd $d && ls */tags | sed 's/\/tags$//' | sort) > $t2
+if diff $t1 $t2 > /dev/null; then
+ exit 0
+else
+ echo "<<< source tree >>> tags files"
+ diff $t1 $t2
+ exit 1
+fi
diff --git a/bdb/test/scr012/chk.vx_code b/bdb/test/scr012/chk.vx_code
new file mode 100644
index 00000000000..8d7ca608f93
--- /dev/null
+++ b/bdb/test/scr012/chk.vx_code
@@ -0,0 +1,68 @@
+#!/bin/sh -
+#
+# $Id: chk.vx_code,v 1.6 2002/03/27 20:20:25 bostic Exp $
+#
+# Check to make sure the auto-generated utility code in the VxWorks build
+# directory compiles.
+
+d=../..
+
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+[ -f ../libdb.a ] || (cd .. && make libdb.a) || {
+ echo 'FAIL: unable to find or build libdb.a'
+ exit 1
+}
+
+rm -f t.c t1.c t2.c
+
+header()
+{
+ echo "int"
+ echo "main(int argc, char *argv[])"
+ echo "{return ($1(argv[1]));}"
+}
+
+(echo "int"
+ echo "main(int argc, char *argv[])"
+ echo "{"
+ echo "int i;") > t1.c
+
+for i in db_archive db_checkpoint db_deadlock db_dump db_load \
+ db_printlog db_recover db_stat db_upgrade db_verify dbdemo; do
+ echo " compiling build_vxworks/$i"
+ (cat $d/build_vxworks/$i/$i.c; header $i) > t.c
+ if cc -Wall -I.. -I$d t.c \
+ $d/clib/getopt.c \
+ $d/common/util_arg.c \
+ $d/common/util_cache.c \
+ $d/common/util_log.c \
+ $d/common/util_sig.c ../libdb.a -o t; then
+ :
+ else
+ echo "FAIL: unable to compile $i"
+ exit 1
+ fi
+
+ cat $d/build_vxworks/$i/$i.c >> t2.c
+ echo "i = $i(argv[1]);" >> t1.c
+done
+
+(cat t2.c t1.c; echo "return (0); }") > t.c
+
+echo " compiling build_vxworks utility composite"
+if cc -Dlint -Wall -I.. -I$d t.c \
+ $d/clib/getopt.c \
+ $d/common/util_arg.c \
+ $d/common/util_cache.c \
+ $d/common/util_log.c \
+ $d/common/util_sig.c ../libdb.a -o t; then
+ :
+else
+ echo "FAIL: unable to compile utility composite"
+ exit 1
+fi
+
+exit 0
diff --git a/bdb/test/scr013/chk.stats b/bdb/test/scr013/chk.stats
new file mode 100644
index 00000000000..3a404699668
--- /dev/null
+++ b/bdb/test/scr013/chk.stats
@@ -0,0 +1,114 @@
+#!/bin/sh -
+#
+# $Id: chk.stats,v 1.6 2002/08/19 18:35:18 bostic Exp $
+#
+# Check to make sure all of the stat structure members are included in
+# all of the possible formats.
+
+# Top-level directory.
+d=../..
+
+# Path names are from a top-level directory.
+[ -f $d/README ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+exitv=0
+t=__tmp
+
+# Extract the field names for a structure from the db.h file.
+inc_fields()
+{
+ sed -e "/struct $1 {/,/^};$/p" \
+ -e d < $d/dbinc/db.in |
+ sed -e 1d \
+ -e '$d' \
+ -e '/;/!d' \
+ -e 's/;.*//' \
+ -e 's/^[ ].*[ \*]//'
+}
+
+cat << END_OF_IGNORE > IGNORE
+bt_maxkey
+bt_metaflags
+hash_metaflags
+qs_metaflags
+qs_ndata
+END_OF_IGNORE
+
+# Check to make sure the elements of a structure from db.h appear in
+# the other files.
+inc()
+{
+ for i in `inc_fields $1`; do
+ if egrep -w $i IGNORE > /dev/null; then
+ echo " $1: ignoring $i"
+ continue
+ fi
+ for j in $2; do
+ if egrep -w $i $d/$j > /dev/null; then
+ :;
+ else
+ echo " $1: $i not found in $j."
+ exitv=1
+ fi
+ done
+ done
+}
+
+inc "__db_bt_stat" \
+ "tcl/tcl_db.c db_stat/db_stat.c docs_src/db/db_stat.so"
+inc "__db_h_stat" \
+ "tcl/tcl_db.c db_stat/db_stat.c docs_src/db/db_stat.so"
+inc "__db_qam_stat" \
+ "tcl/tcl_db.c db_stat/db_stat.c docs_src/db/db_stat.so"
+inc __db_lock_stat \
+ "tcl/tcl_lock.c db_stat/db_stat.c docs_src/lock/lock_stat.so"
+inc __db_log_stat \
+ "tcl/tcl_log.c db_stat/db_stat.c docs_src/log/log_stat.so"
+inc __db_mpool_stat \
+ "tcl/tcl_mp.c db_stat/db_stat.c docs_src/memp/memp_stat.so"
+inc __db_txn_stat \
+ "tcl/tcl_txn.c db_stat/db_stat.c docs_src/txn/txn_stat.so"
+
+# Check to make sure the elements from a man page appears in db.in.
+man()
+{
+ for i in `cat $t`; do
+ if egrep -w $i IGNORE > /dev/null; then
+ echo " $1: ignoring $i"
+ continue
+ fi
+ if egrep -w $i $d/dbinc/db.in > /dev/null; then
+ :;
+ else
+ echo " $1: $i not found in db.h."
+ exitv=1
+ fi
+ done
+}
+
+sed -e '/m4_stat(/!d' \
+ -e 's/.*m4_stat(\([^)]*\)).*/\1/' < $d/docs_src/db/db_stat.so > $t
+man "checking db_stat.so against db.h"
+
+sed -e '/m4_stat(/!d' \
+ -e 's/.*m4_stat(\([^)]*\)).*/\1/' \
+ -e 's/.* //' < $d/docs_src/lock/lock_stat.so > $t
+man "checking lock_stat.so against db.h"
+
+sed -e '/m4_stat[12](/!d' \
+ -e 's/.*m4_stat[12](\([^)]*\)).*/\1/' < $d/docs_src/log/log_stat.so > $t
+man "checking log_stat.so against db.h"
+
+sed -e '/m4_stat[123](/!d' \
+ -e 's/.*m4_stat[123](\([^)]*\)).*/\1/' < $d/docs_src/memp/memp_stat.so > $t
+man "checking memp_stat.so against db.h"
+
+sed -e '/m4_stat(/!d' \
+ -e 's/.*m4_stat(.*, \([^)]*\)).*/\1/' \
+ -e 's/__[LR]B__//g' < $d/docs_src/txn/txn_stat.so > $t
+man "checking txn_stat.so against db.h"
+
+exit $exitv
diff --git a/bdb/test/scr014/chk.err b/bdb/test/scr014/chk.err
new file mode 100644
index 00000000000..72b4a62719f
--- /dev/null
+++ b/bdb/test/scr014/chk.err
@@ -0,0 +1,34 @@
+#!/bin/sh -
+#
+# $Id: chk.err,v 1.3 2002/03/27 04:33:05 bostic Exp $
+#
+# Check to make sure all of the error values have corresponding error
+# message strings in db_strerror().
+
+# Top-level directory.
+d=../..
+
+# Path names are from a top-level directory.
+[ -f $d/README ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t1=__tmp1
+t2=__tmp2
+
+egrep -- "define.*DB_.*-309" $d/dbinc/db.in | awk '{print $2}' > $t1
+sed -e '/^db_strerror/,/^}/{' \
+ -e '/ case DB_/{' \
+ -e 's/:.*//' \
+ -e 's/.* //' \
+ -e p \
+ -e '}' \
+ -e '}' \
+ -e d \
+ < $d/common/db_err.c > $t2
+
+cmp $t1 $t2 > /dev/null ||
+(echo "<<< db.h >>> db_strerror" && diff $t1 $t2 && exit 1)
+
+exit 0
diff --git a/bdb/test/scr015/README b/bdb/test/scr015/README
new file mode 100644
index 00000000000..75a356eea06
--- /dev/null
+++ b/bdb/test/scr015/README
@@ -0,0 +1,36 @@
+# $Id: README,v 1.1 2001/05/31 23:09:11 dda Exp $
+
+Use the scripts testall or testone to run all, or just one of the C++
+tests. You must be in this directory to run them. For example,
+
+ $ export LIBS="-L/usr/include/BerkeleyDB/lib"
+ $ export CXXFLAGS="-I/usr/include/BerkeleyDB/include"
+ $ export LD_LIBRARY_PATH="/usr/include/BerkeleyDB/lib"
+ $ ./testone TestAppendRecno
+ $ ./testall
+
+The scripts will use c++ in your path. Set environment variables $CXX
+to override this. It will also honor any $CXXFLAGS and $LIBS
+variables that are set, except that -c are silently removed from
+$CXXFLAGS (since we do the compilation in one step).
+
+To run successfully, you will probably need to set $LD_LIBRARY_PATH
+to be the directory containing libdb_cxx-X.Y.so
+
+As an alternative, use the --prefix=<DIR> option, a la configure
+to set the top of the BerkeleyDB install directory. This forces
+the proper options to be added to $LIBS, $CXXFLAGS $LD_LIBRARY_PATH.
+For example,
+
+ $ ./testone --prefix=/usr/include/BerkeleyDB TestAppendRecno
+ $ ./testall --prefix=/usr/include/BerkeleyDB
+
+The test framework is pretty simple. Any <name>.cpp file in this
+directory that is not mentioned in the 'ignore' file represents a
+test. If the test is not compiled successfully, the compiler output
+is left in <name>.compileout . Otherwise, the java program is run in
+a clean subdirectory using as input <name>.testin, or if that doesn't
+exist, /dev/null. Output and error from the test run are put into
+<name>.out, <name>.err . If <name>.testout, <name>.testerr exist,
+they are used as reference files and any differences are reported.
+If either of the reference files does not exist, /dev/null is used.
diff --git a/bdb/test/scr015/TestConstruct01.cpp b/bdb/test/scr015/TestConstruct01.cpp
new file mode 100644
index 00000000000..7ae328d458c
--- /dev/null
+++ b/bdb/test/scr015/TestConstruct01.cpp
@@ -0,0 +1,330 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestConstruct01.cpp,v 1.5 2002/01/23 14:26:40 bostic Exp $
+ */
+
+/*
+ * Do some regression tests for constructors.
+ * Run normally (without arguments) it is a simple regression test.
+ * Run with a numeric argument, it repeats the regression a number
+ * of times, to try to determine if there are memory leaks.
+ */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <iostream.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#endif
+
+#include <iomanip.h>
+#include <db_cxx.h>
+
+#define ERR(a) \
+ do { \
+ cout << "FAIL: " << (a) << "\n"; sysexit(1); \
+ } while (0)
+
+#define ERR2(a1,a2) \
+ do { \
+ cout << "FAIL: " << (a1) << ": " << (a2) << "\n"; sysexit(1); \
+ } while (0)
+
+#define ERR3(a1,a2,a3) \
+ do { \
+ cout << "FAIL: " << (a1) << ": " << (a2) << ": " << (a3) << "\n"; sysexit(1); \
+ } while (0)
+
+#define CHK(a) \
+ do { \
+ int _ret; \
+ if ((_ret = (a)) != 0) { \
+ ERR3("DB function " #a " has bad return", _ret, DbEnv::strerror(_ret)); \
+ } \
+ } while (0)
+
+#ifdef VERBOSE
+#define DEBUGOUT(a) cout << a << "\n"
+#else
+#define DEBUGOUT(a)
+#endif
+
+#define CONSTRUCT01_DBNAME "construct01.db"
+#define CONSTRUCT01_DBDIR "."
+#define CONSTRUCT01_DBFULLPATH (CONSTRUCT01_DBDIR "/" CONSTRUCT01_DBNAME)
+
+int itemcount; // count the number of items in the database
+
+// A good place to put a breakpoint...
+//
+void sysexit(int status)
+{
+ exit(status);
+}
+
+void check_file_removed(const char *name, int fatal)
+{
+ unlink(name);
+#if 0
+ if (access(name, 0) == 0) {
+ if (fatal)
+ cout << "FAIL: ";
+ cout << "File \"" << name << "\" still exists after run\n";
+ if (fatal)
+ sysexit(1);
+ }
+#endif
+}
+
+// Check that key/data for 0 - count-1 are already present,
+// and write a key/data for count. The key and data are
+// both "0123...N" where N == count-1.
+//
+// For some reason on Windows, we need to open using the full pathname
+// of the file when there is no environment, thus the 'has_env'
+// variable.
+//
+void rundb(Db *db, int count, int has_env)
+{
+ const char *name;
+
+ if (has_env)
+ name = CONSTRUCT01_DBNAME;
+ else
+ name = CONSTRUCT01_DBFULLPATH;
+
+ db->set_error_stream(&cerr);
+
+ // We don't really care about the pagesize, but we do want
+ // to make sure adjusting Db specific variables works before
+ // opening the db.
+ //
+ CHK(db->set_pagesize(1024));
+ CHK(db->open(NULL, name, NULL, DB_BTREE, count ? 0 : DB_CREATE, 0664));
+
+ // The bit map of keys we've seen
+ long bitmap = 0;
+
+ // The bit map of keys we expect to see
+ long expected = (1 << (count+1)) - 1;
+
+ char outbuf[10];
+ int i;
+ for (i=0; i<count; i++) {
+ outbuf[i] = '0' + i;
+ }
+ outbuf[i++] = '\0';
+ Dbt key(outbuf, i);
+ Dbt data(outbuf, i);
+
+ DEBUGOUT("Put: " << outbuf);
+ CHK(db->put(0, &key, &data, DB_NOOVERWRITE));
+
+ // Acquire a cursor for the table.
+ Dbc *dbcp;
+ CHK(db->cursor(NULL, &dbcp, 0));
+
+ // Walk through the table, checking
+ Dbt readkey;
+ Dbt readdata;
+ while (dbcp->get(&readkey, &readdata, DB_NEXT) == 0) {
+ char *key_string = (char *)readkey.get_data();
+ char *data_string = (char *)readdata.get_data();
+ DEBUGOUT("Got: " << key_string << ": " << data_string);
+ int len = strlen(key_string);
+ long bit = (1 << len);
+ if (len > count) {
+ ERR("reread length is bad");
+ }
+ else if (strcmp(data_string, key_string) != 0) {
+ ERR("key/data don't match");
+ }
+ else if ((bitmap & bit) != 0) {
+ ERR("key already seen");
+ }
+ else if ((expected & bit) == 0) {
+ ERR("key was not expected");
+ }
+ else {
+ bitmap |= bit;
+ expected &= ~(bit);
+ for (i=0; i<len; i++) {
+ if (key_string[i] != ('0' + i)) {
+ cout << " got " << key_string
+ << " (" << (int)key_string[i] << ")"
+ << ", wanted " << i
+ << " (" << (int)('0' + i) << ")"
+ << " at position " << i << "\n";
+ ERR("key is corrupt");
+ }
+ }
+ }
+ }
+ if (expected != 0) {
+ cout << " expected more keys, bitmap is: " << expected << "\n";
+ ERR("missing keys in database");
+ }
+ CHK(dbcp->close());
+ CHK(db->close(0));
+}
+
+void t1(int except_flag)
+{
+ cout << " Running test 1:\n";
+ Db db(0, except_flag);
+ rundb(&db, itemcount++, 0);
+ cout << " finished.\n";
+}
+
+void t2(int except_flag)
+{
+ cout << " Running test 2:\n";
+ Db db(0, except_flag);
+ rundb(&db, itemcount++, 0);
+ cout << " finished.\n";
+}
+
+void t3(int except_flag)
+{
+ cout << " Running test 3:\n";
+ Db db(0, except_flag);
+ rundb(&db, itemcount++, 0);
+ cout << " finished.\n";
+}
+
+void t4(int except_flag)
+{
+ cout << " Running test 4:\n";
+ DbEnv env(except_flag);
+ CHK(env.open(CONSTRUCT01_DBDIR, DB_CREATE | DB_INIT_MPOOL, 0));
+ Db db(&env, 0);
+ CHK(db.close(0));
+ CHK(env.close(0));
+ cout << " finished.\n";
+}
+
+void t5(int except_flag)
+{
+ cout << " Running test 5:\n";
+ DbEnv env(except_flag);
+ CHK(env.open(CONSTRUCT01_DBDIR, DB_CREATE | DB_INIT_MPOOL, 0));
+ Db db(&env, 0);
+ rundb(&db, itemcount++, 1);
+ // Note we cannot reuse the old Db!
+ Db anotherdb(&env, 0);
+
+ anotherdb.set_errpfx("test5");
+ rundb(&anotherdb, itemcount++, 1);
+ CHK(env.close(0));
+ cout << " finished.\n";
+}
+
+void t6(int except_flag)
+{
+ cout << " Running test 6:\n";
+
+ /* From user [#2939] */
+ int err;
+
+ DbEnv* penv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
+ penv->set_cachesize(0, 32 * 1024, 0);
+ penv->open(CONSTRUCT01_DBDIR, DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL, 0);
+
+ //LEAK: remove this block and leak disappears
+ Db* pdb = new Db(penv,0);
+ if ((err = pdb->close(0)) != 0) {
+ fprintf(stderr, "Error closing Db: %s\n", db_strerror(err));
+ }
+ delete pdb;
+ //LEAK: remove this block and leak disappears
+
+ if ((err = penv->close(0)) != 0) {
+ fprintf(stderr, "Error closing DbEnv: %s\n", db_strerror(err));
+ }
+ delete penv;
+
+ // Make sure we get a message from C++ layer reminding us to close.
+ cerr << "expected error: ";
+ {
+ DbEnv foo(DB_CXX_NO_EXCEPTIONS);
+ foo.open(CONSTRUCT01_DBDIR, DB_CREATE, 0);
+ }
+ cerr << "should have received error.\n";
+ cout << " finished.\n";
+}
+
+// remove any existing environment or database
+void removeall()
+{
+ {
+ DbEnv tmpenv(DB_CXX_NO_EXCEPTIONS);
+ (void)tmpenv.remove(CONSTRUCT01_DBDIR, DB_FORCE);
+ }
+
+ check_file_removed(CONSTRUCT01_DBFULLPATH, 1);
+ for (int i=0; i<8; i++) {
+ char buf[20];
+ sprintf(buf, "__db.00%d", i);
+ check_file_removed(buf, 1);
+ }
+}
+
+int doall(int except_flag)
+{
+ itemcount = 0;
+ try {
+ // before and after the run, removing any
+ // old environment/database.
+ //
+ removeall();
+ t1(except_flag);
+ t2(except_flag);
+ t3(except_flag);
+ t4(except_flag);
+ t5(except_flag);
+ t6(except_flag);
+
+ removeall();
+ return 0;
+ }
+ catch (DbException &dbe) {
+ ERR2("EXCEPTION RECEIVED", dbe.what());
+ }
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ int iterations = 1;
+ if (argc > 1) {
+ iterations = atoi(argv[1]);
+ if (iterations < 0) {
+ ERR("Usage: construct01 count");
+ }
+ }
+ for (int i=0; i<iterations; i++) {
+ if (iterations != 0) {
+ cout << "(" << i << "/" << iterations << ") ";
+ }
+ cout << "construct01 running:\n";
+ if (doall(DB_CXX_NO_EXCEPTIONS) != 0) {
+ ERR("SOME TEST FAILED FOR NO-EXCEPTION TEST");
+ }
+ else if (doall(0) != 0) {
+ ERR("SOME TEST FAILED FOR EXCEPTION TEST");
+ }
+ else {
+ cout << "\nALL TESTS SUCCESSFUL\n";
+ }
+ }
+ return 0;
+}
diff --git a/bdb/test/scr015/TestConstruct01.testerr b/bdb/test/scr015/TestConstruct01.testerr
new file mode 100644
index 00000000000..1ba627d103b
--- /dev/null
+++ b/bdb/test/scr015/TestConstruct01.testerr
@@ -0,0 +1,4 @@
+expected error: DbEnv::_destroy_check: open DbEnv object destroyed
+should have received error.
+expected error: DbEnv::_destroy_check: open DbEnv object destroyed
+should have received error.
diff --git a/bdb/test/scr015/TestConstruct01.testout b/bdb/test/scr015/TestConstruct01.testout
new file mode 100644
index 00000000000..9b840f9fcf4
--- /dev/null
+++ b/bdb/test/scr015/TestConstruct01.testout
@@ -0,0 +1,27 @@
+(0/1) construct01 running:
+ Running test 1:
+ finished.
+ Running test 2:
+ finished.
+ Running test 3:
+ finished.
+ Running test 4:
+ finished.
+ Running test 5:
+ finished.
+ Running test 6:
+ finished.
+ Running test 1:
+ finished.
+ Running test 2:
+ finished.
+ Running test 3:
+ finished.
+ Running test 4:
+ finished.
+ Running test 5:
+ finished.
+ Running test 6:
+ finished.
+
+ALL TESTS SUCCESSFUL
diff --git a/bdb/test/scr015/TestExceptInclude.cpp b/bdb/test/scr015/TestExceptInclude.cpp
new file mode 100644
index 00000000000..28bc498222f
--- /dev/null
+++ b/bdb/test/scr015/TestExceptInclude.cpp
@@ -0,0 +1,27 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestExceptInclude.cpp,v 1.4 2002/07/05 22:17:59 dda Exp $
+ */
+
+/* We should be able to include cxx_except.h without db_cxx.h,
+ * and use the DbException class. We do need db.h to get a few
+ * typedefs defined that the DbException classes use.
+ *
+ * This program does nothing, it's just here to make sure
+ * the compilation works.
+ */
+#include <db.h>
+#include <cxx_except.h>
+
+int main(int argc, char *argv[])
+{
+ DbException *dbe = new DbException("something");
+ DbMemoryException *dbme = new DbMemoryException("anything");
+
+ dbe = dbme;
+}
+
diff --git a/bdb/test/scr015/TestGetSetMethods.cpp b/bdb/test/scr015/TestGetSetMethods.cpp
new file mode 100644
index 00000000000..81ef914eac3
--- /dev/null
+++ b/bdb/test/scr015/TestGetSetMethods.cpp
@@ -0,0 +1,91 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestGetSetMethods.cpp,v 1.4 2002/01/11 15:53:59 bostic Exp $
+ */
+
+/*
+ * Do some regression tests for simple get/set access methods
+ * on DbEnv, DbTxn, Db. We don't currently test that they have
+ * the desired effect, only that they operate and return correctly.
+ */
+
+#include <db_cxx.h>
+#include <iostream.h>
+
+int main(int argc, char *argv[])
+{
+ try {
+ DbEnv *dbenv = new DbEnv(0);
+ DbTxn *dbtxn;
+ u_int8_t conflicts[10];
+
+ dbenv->set_error_stream(&cerr);
+ dbenv->set_timeout(0x90000000,
+ DB_SET_LOCK_TIMEOUT);
+ dbenv->set_lg_bsize(0x1000);
+ dbenv->set_lg_dir(".");
+ dbenv->set_lg_max(0x10000000);
+ dbenv->set_lg_regionmax(0x100000);
+ dbenv->set_lk_conflicts(conflicts, sizeof(conflicts));
+ dbenv->set_lk_detect(DB_LOCK_DEFAULT);
+ // exists, but is deprecated:
+ // dbenv->set_lk_max(0);
+ dbenv->set_lk_max_lockers(100);
+ dbenv->set_lk_max_locks(10);
+ dbenv->set_lk_max_objects(1000);
+ dbenv->set_mp_mmapsize(0x10000);
+ dbenv->set_tas_spins(1000);
+
+ // Need to open the environment so we
+ // can get a transaction.
+ //
+ dbenv->open(".", DB_CREATE | DB_INIT_TXN |
+ DB_INIT_LOCK | DB_INIT_LOG |
+ DB_INIT_MPOOL,
+ 0644);
+
+ dbenv->txn_begin(NULL, &dbtxn, DB_TXN_NOWAIT);
+ dbtxn->set_timeout(0xA0000000, DB_SET_TXN_TIMEOUT);
+ dbtxn->abort();
+
+ dbenv->close(0);
+
+ // We get a db, one for each type.
+ // That's because once we call (for instance)
+ // set_bt_maxkey, DB 'knows' that this is a
+ // Btree Db, and it cannot be used to try Hash
+ // or Recno functions.
+ //
+ Db *db_bt = new Db(NULL, 0);
+ db_bt->set_bt_maxkey(10000);
+ db_bt->set_bt_minkey(100);
+ db_bt->set_cachesize(0, 0x100000, 0);
+ db_bt->close(0);
+
+ Db *db_h = new Db(NULL, 0);
+ db_h->set_h_ffactor(0x10);
+ db_h->set_h_nelem(100);
+ db_h->set_lorder(0);
+ db_h->set_pagesize(0x10000);
+ db_h->close(0);
+
+ Db *db_re = new Db(NULL, 0);
+ db_re->set_re_delim('@');
+ db_re->set_re_pad(10);
+ db_re->set_re_source("re.in");
+ db_re->close(0);
+
+ Db *db_q = new Db(NULL, 0);
+ db_q->set_q_extentsize(200);
+ db_q->close(0);
+
+ }
+ catch (DbException &dbe) {
+ cerr << "Db Exception: " << dbe.what() << "\n";
+ }
+ return 0;
+}
diff --git a/bdb/test/scr015/TestKeyRange.cpp b/bdb/test/scr015/TestKeyRange.cpp
new file mode 100644
index 00000000000..980d2f518e0
--- /dev/null
+++ b/bdb/test/scr015/TestKeyRange.cpp
@@ -0,0 +1,171 @@
+/*NOTE: AccessExample changed to test Db.key_range.
+ * We made a global change of /AccessExample/TestKeyRange/,
+ * the only other changes are marked with comments that
+ * are notated as 'ADDED'.
+ */
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestKeyRange.cpp,v 1.4 2002/01/23 14:26:41 bostic Exp $
+ */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <iostream.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#endif
+
+#include <iomanip.h>
+#include <db_cxx.h>
+
+class TestKeyRange
+{
+public:
+ TestKeyRange();
+ void run();
+
+private:
+ static const char FileName[];
+
+ // no need for copy and assignment
+ TestKeyRange(const TestKeyRange &);
+ void operator = (const TestKeyRange &);
+};
+
+static void usage(); // forward
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1) {
+ usage();
+ }
+
+ // Use a try block just to report any errors.
+ // An alternate approach to using exceptions is to
+ // use error models (see DbEnv::set_error_model()) so
+ // that error codes are returned for all Berkeley DB methods.
+ //
+ try {
+ TestKeyRange app;
+ app.run();
+ return 0;
+ }
+ catch (DbException &dbe) {
+ cerr << "TestKeyRange: " << dbe.what() << "\n";
+ return 1;
+ }
+}
+
+static void usage()
+{
+ cerr << "usage: TestKeyRange\n";
+ exit(1);
+}
+
+const char TestKeyRange::FileName[] = "access.db";
+
+TestKeyRange::TestKeyRange()
+{
+}
+
+void TestKeyRange::run()
+{
+ // Remove the previous database.
+ (void)unlink(FileName);
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ Db db(0, 0);
+
+ db.set_error_stream(&cerr);
+ db.set_errpfx("TestKeyRange");
+ db.set_pagesize(1024); /* Page size: 1K. */
+ db.set_cachesize(0, 32 * 1024, 0);
+ db.open(NULL, FileName, NULL, DB_BTREE, DB_CREATE, 0664);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ char buf[1024];
+ char rbuf[1024];
+ char *t;
+ char *p;
+ int ret;
+ int len;
+ Dbt *firstkey = NULL;
+ char firstbuf[1024];
+
+ for (;;) {
+ cout << "input>";
+ cout.flush();
+
+ cin.getline(buf, sizeof(buf));
+ if (cin.eof())
+ break;
+
+ if ((len = strlen(buf)) <= 0)
+ continue;
+ for (t = rbuf, p = buf + (len - 1); p >= buf;)
+ *t++ = *p--;
+ *t++ = '\0';
+
+ Dbt key(buf, len + 1);
+ Dbt data(rbuf, len + 1);
+ if (firstkey == NULL) {
+ strcpy(firstbuf, buf);
+ firstkey = new Dbt(firstbuf, len + 1);
+ }
+
+ ret = db.put(0, &key, &data, DB_NOOVERWRITE);
+ if (ret == DB_KEYEXIST) {
+ cout << "Key " << buf << " already exists.\n";
+ }
+ cout << "\n";
+ }
+
+ // We put a try block around this section of code
+ // to ensure that our database is properly closed
+ // in the event of an error.
+ //
+ try {
+ // Acquire a cursor for the table.
+ Dbc *dbcp;
+ db.cursor(NULL, &dbcp, 0);
+
+ /*ADDED...*/
+ DB_KEY_RANGE range;
+ memset(&range, 0, sizeof(range));
+
+ db.key_range(NULL, firstkey, &range, 0);
+ printf("less: %f\n", range.less);
+ printf("equal: %f\n", range.equal);
+ printf("greater: %f\n", range.greater);
+ /*end ADDED*/
+
+ Dbt key;
+ Dbt data;
+
+ // Walk through the table, printing the key/data pairs.
+ while (dbcp->get(&key, &data, DB_NEXT) == 0) {
+ char *key_string = (char *)key.get_data();
+ char *data_string = (char *)data.get_data();
+ cout << key_string << " : " << data_string << "\n";
+ }
+ dbcp->close();
+ }
+ catch (DbException &dbe) {
+ cerr << "TestKeyRange: " << dbe.what() << "\n";
+ }
+
+ db.close(0);
+}
diff --git a/bdb/test/scr015/TestKeyRange.testin b/bdb/test/scr015/TestKeyRange.testin
new file mode 100644
index 00000000000..a2b6bd74e7b
--- /dev/null
+++ b/bdb/test/scr015/TestKeyRange.testin
@@ -0,0 +1,8 @@
+first line is alphabetically somewhere in the middle.
+Blah blah
+let's have exactly eight lines of input.
+stuff
+more stuff
+and even more stuff
+lastly
+but not leastly.
diff --git a/bdb/test/scr015/TestKeyRange.testout b/bdb/test/scr015/TestKeyRange.testout
new file mode 100644
index 00000000000..25b2e1a835c
--- /dev/null
+++ b/bdb/test/scr015/TestKeyRange.testout
@@ -0,0 +1,19 @@
+input>
+input>
+input>
+input>
+input>
+input>
+input>
+input>
+input>less: 0.375000
+equal: 0.125000
+greater: 0.500000
+Blah blah : halb halB
+and even more stuff : ffuts erom neve dna
+but not leastly. : .yltsael ton tub
+first line is alphabetically somewhere in the middle. : .elddim eht ni erehwemos yllacitebahpla si enil tsrif
+lastly : yltsal
+let's have exactly eight lines of input. : .tupni fo senil thgie yltcaxe evah s'tel
+more stuff : ffuts erom
+stuff : ffuts
diff --git a/bdb/test/scr015/TestLogc.cpp b/bdb/test/scr015/TestLogc.cpp
new file mode 100644
index 00000000000..94fcfa0b3ec
--- /dev/null
+++ b/bdb/test/scr015/TestLogc.cpp
@@ -0,0 +1,101 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestLogc.cpp,v 1.6 2002/01/23 14:26:41 bostic Exp $
+ */
+
+/*
+ * A basic regression test for the Logc class.
+ */
+
+#include <db_cxx.h>
+#include <iostream.h>
+
+static void show_dbt(ostream &os, Dbt *dbt)
+{
+ int i;
+ int size = dbt->get_size();
+ unsigned char *data = (unsigned char *)dbt->get_data();
+
+ os << "size: " << size << " data: ";
+ for (i=0; i<size && i<10; i++) {
+ os << (int)data[i] << " ";
+ }
+ if (i<size)
+ os << "...";
+}
+
+int main(int argc, char *argv[])
+{
+ try {
+ DbEnv *env = new DbEnv(0);
+ env->open(".", DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL, 0);
+
+ // Do some database activity to get something into the log.
+ Db *db1 = new Db(env, 0);
+ db1->open(NULL, "first.db", NULL, DB_BTREE, DB_CREATE, 0);
+ Dbt *key = new Dbt((char *)"a", 1);
+ Dbt *data = new Dbt((char *)"b", 1);
+ db1->put(NULL, key, data, 0);
+ key->set_data((char *)"c");
+ data->set_data((char *)"d");
+ db1->put(NULL, key, data, 0);
+ db1->close(0);
+
+ Db *db2 = new Db(env, 0);
+ db2->open(NULL, "second.db", NULL, DB_BTREE, DB_CREATE, 0);
+ key->set_data((char *)"w");
+ data->set_data((char *)"x");
+ db2->put(NULL, key, data, 0);
+ key->set_data((char *)"y");
+ data->set_data((char *)"z");
+ db2->put(NULL, key, data, 0);
+ db2->close(0);
+
+ // Now get a log cursor and walk through.
+ DbLogc *logc;
+
+ env->log_cursor(&logc, 0);
+ int ret = 0;
+ DbLsn lsn;
+ Dbt *dbt = new Dbt();
+ u_int32_t flags = DB_FIRST;
+
+ int count = 0;
+ while ((ret = logc->get(&lsn, dbt, flags)) == 0) {
+
+ // We ignore the contents of the log record,
+ // it's not portable. Even the exact count
+ // is may change when the underlying implementation
+ // changes, we'll just make sure at the end we saw
+ // 'enough'.
+ //
+ // cout << "logc.get: " << count;
+ // show_dbt(cout, dbt);
+ // cout << "\n";
+ //
+ count++;
+ flags = DB_NEXT;
+ }
+ if (ret != DB_NOTFOUND) {
+ cerr << "*** FAIL: logc.get returned: "
+ << DbEnv::strerror(ret) << "\n";
+ }
+ logc->close(0);
+
+ // There has to be at *least* four log records,
+ // since we did four separate database operations.
+ //
+ if (count < 4)
+ cerr << "*** FAIL: not enough log records\n";
+
+ cout << "TestLogc done.\n";
+ }
+ catch (DbException &dbe) {
+ cerr << "*** FAIL: " << dbe.what() <<"\n";
+ }
+ return 0;
+}
diff --git a/bdb/test/scr015/TestLogc.testout b/bdb/test/scr015/TestLogc.testout
new file mode 100644
index 00000000000..afac3af7eda
--- /dev/null
+++ b/bdb/test/scr015/TestLogc.testout
@@ -0,0 +1 @@
+TestLogc done.
diff --git a/bdb/test/scr015/TestSimpleAccess.cpp b/bdb/test/scr015/TestSimpleAccess.cpp
new file mode 100644
index 00000000000..2450b9b3030
--- /dev/null
+++ b/bdb/test/scr015/TestSimpleAccess.cpp
@@ -0,0 +1,67 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestSimpleAccess.cpp,v 1.5 2002/01/23 14:26:41 bostic Exp $
+ */
+
+/*
+ * Do some regression tests for constructors.
+ * Run normally (without arguments) it is a simple regression test.
+ * Run with a numeric argument, it repeats the regression a number
+ * of times, to try to determine if there are memory leaks.
+ */
+
+#include <db_cxx.h>
+#include <iostream.h>
+
+int main(int argc, char *argv[])
+{
+ try {
+ Db *db = new Db(NULL, 0);
+ db->open(NULL, "my.db", NULL, DB_BTREE, DB_CREATE, 0644);
+
+ // populate our massive database.
+ // all our strings include null for convenience.
+ // Note we have to cast for idiomatic
+ // usage, since newer gcc requires it.
+ Dbt *keydbt = new Dbt((char *)"key", 4);
+ Dbt *datadbt = new Dbt((char *)"data", 5);
+ db->put(NULL, keydbt, datadbt, 0);
+
+ // Now, retrieve. We could use keydbt over again,
+ // but that wouldn't be typical in an application.
+ Dbt *goodkeydbt = new Dbt((char *)"key", 4);
+ Dbt *badkeydbt = new Dbt((char *)"badkey", 7);
+ Dbt *resultdbt = new Dbt();
+ resultdbt->set_flags(DB_DBT_MALLOC);
+
+ int ret;
+
+ if ((ret = db->get(NULL, goodkeydbt, resultdbt, 0)) != 0) {
+ cout << "get: " << DbEnv::strerror(ret) << "\n";
+ }
+ else {
+ char *result = (char *)resultdbt->get_data();
+ cout << "got data: " << result << "\n";
+ }
+
+ if ((ret = db->get(NULL, badkeydbt, resultdbt, 0)) != 0) {
+ // We expect this...
+ cout << "get using bad key: "
+ << DbEnv::strerror(ret) << "\n";
+ }
+ else {
+ char *result = (char *)resultdbt->get_data();
+ cout << "*** got data using bad key!!: "
+ << result << "\n";
+ }
+ cout << "finished test\n";
+ }
+ catch (DbException &dbe) {
+ cerr << "Db Exception: " << dbe.what();
+ }
+ return 0;
+}
diff --git a/bdb/test/scr015/TestSimpleAccess.testout b/bdb/test/scr015/TestSimpleAccess.testout
new file mode 100644
index 00000000000..dc88d4788e4
--- /dev/null
+++ b/bdb/test/scr015/TestSimpleAccess.testout
@@ -0,0 +1,3 @@
+got data: data
+get using bad key: DB_NOTFOUND: No matching key/data pair found
+finished test
diff --git a/bdb/test/scr015/TestTruncate.cpp b/bdb/test/scr015/TestTruncate.cpp
new file mode 100644
index 00000000000..d5c0dc6de29
--- /dev/null
+++ b/bdb/test/scr015/TestTruncate.cpp
@@ -0,0 +1,84 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestTruncate.cpp,v 1.5 2002/01/23 14:26:41 bostic Exp $
+ */
+
+/*
+ * Do some regression tests for constructors.
+ * Run normally (without arguments) it is a simple regression test.
+ * Run with a numeric argument, it repeats the regression a number
+ * of times, to try to determine if there are memory leaks.
+ */
+
+#include <db_cxx.h>
+#include <iostream.h>
+
+int main(int argc, char *argv[])
+{
+ try {
+ Db *db = new Db(NULL, 0);
+ db->open(NULL, "my.db", NULL, DB_BTREE, DB_CREATE, 0644);
+
+ // populate our massive database.
+ // all our strings include null for convenience.
+ // Note we have to cast for idiomatic
+ // usage, since newer gcc requires it.
+ Dbt *keydbt = new Dbt((char*)"key", 4);
+ Dbt *datadbt = new Dbt((char*)"data", 5);
+ db->put(NULL, keydbt, datadbt, 0);
+
+ // Now, retrieve. We could use keydbt over again,
+ // but that wouldn't be typical in an application.
+ Dbt *goodkeydbt = new Dbt((char*)"key", 4);
+ Dbt *badkeydbt = new Dbt((char*)"badkey", 7);
+ Dbt *resultdbt = new Dbt();
+ resultdbt->set_flags(DB_DBT_MALLOC);
+
+ int ret;
+
+ if ((ret = db->get(NULL, goodkeydbt, resultdbt, 0)) != 0) {
+ cout << "get: " << DbEnv::strerror(ret) << "\n";
+ }
+ else {
+ char *result = (char *)resultdbt->get_data();
+ cout << "got data: " << result << "\n";
+ }
+
+ if ((ret = db->get(NULL, badkeydbt, resultdbt, 0)) != 0) {
+ // We expect this...
+ cout << "get using bad key: "
+ << DbEnv::strerror(ret) << "\n";
+ }
+ else {
+ char *result = (char *)resultdbt->get_data();
+ cout << "*** got data using bad key!!: "
+ << result << "\n";
+ }
+
+ // Now, truncate and make sure that it's really gone.
+ cout << "truncating data...\n";
+ u_int32_t nrecords;
+ db->truncate(NULL, &nrecords, 0);
+ cout << "truncate returns " << nrecords << "\n";
+ if ((ret = db->get(NULL, goodkeydbt, resultdbt, 0)) != 0) {
+ // We expect this...
+ cout << "after truncate get: "
+ << DbEnv::strerror(ret) << "\n";
+ }
+ else {
+ char *result = (char *)resultdbt->get_data();
+ cout << "got data: " << result << "\n";
+ }
+
+ db->close(0);
+ cout << "finished test\n";
+ }
+ catch (DbException &dbe) {
+ cerr << "Db Exception: " << dbe.what();
+ }
+ return 0;
+}
diff --git a/bdb/test/scr015/TestTruncate.testout b/bdb/test/scr015/TestTruncate.testout
new file mode 100644
index 00000000000..0a4bc98165d
--- /dev/null
+++ b/bdb/test/scr015/TestTruncate.testout
@@ -0,0 +1,6 @@
+got data: data
+get using bad key: DB_NOTFOUND: No matching key/data pair found
+truncating data...
+truncate returns 1
+after truncate get: DB_NOTFOUND: No matching key/data pair found
+finished test
diff --git a/bdb/test/scr015/chk.cxxtests b/bdb/test/scr015/chk.cxxtests
new file mode 100644
index 00000000000..5c21e27208c
--- /dev/null
+++ b/bdb/test/scr015/chk.cxxtests
@@ -0,0 +1,71 @@
+#!/bin/sh -
+#
+# $Id: chk.cxxtests,v 1.5 2002/07/05 22:17:59 dda Exp $
+#
+# Check to make sure that regression tests for C++ run.
+
+TEST_CXX_SRCDIR=../test/scr015 # must be a relative directory
+
+# All paths must be relative to a subdirectory of the build directory
+LIBS="-L.. -ldb -ldb_cxx"
+CXXFLAGS="-I.. -I../../dbinc"
+
+# Test must be run from a local build directory, not from a test
+# directory.
+cd ..
+[ -f db_config.h ] || {
+ echo 'FAIL: chk.cxxtests must be run from a local build directory.'
+ exit 1
+}
+[ -d ../docs_src ] || {
+ echo 'FAIL: chk.cxxtests must be run from a local build directory.'
+ exit 1
+}
+[ -f libdb.a ] || make libdb.a || {
+ echo 'FAIL: unable to build libdb.a'
+ exit 1
+}
+[ -f libdb_cxx.a ] || make libdb_cxx.a || {
+ echo 'FAIL: unable to build libdb_cxx.a'
+ exit 1
+}
+CXX=`sed -e '/^CXX=/!d' -e 's/^CXX=//' -e 's/.*mode=compile *//' Makefile`
+echo " ====== cxx tests using $CXX"
+testnames=`cd $TEST_CXX_SRCDIR; ls *.cpp | sed -e 's/\.cpp$//'`
+
+for testname in $testnames; do
+ if grep -x $testname $TEST_CXX_SRCDIR/ignore > /dev/null; then
+ echo " **** cxx test $testname ignored"
+ continue
+ fi
+
+ echo " ==== cxx test $testname"
+ rm -rf TESTCXX; mkdir TESTCXX
+ cd ./TESTCXX
+ testprefix=../$TEST_CXX_SRCDIR/$testname
+
+ ${CXX} ${CXXFLAGS} -o $testname $testprefix.cpp ${LIBS} > ../$testname.compileout 2>&1 || {
+ echo "FAIL: compilation of $testname failed, see ../$testname.compileout"
+ exit 1
+ }
+ rm -f ../$testname.compileout
+ infile=$testprefix.testin
+ [ -f $infile ] || infile=/dev/null
+ goodoutfile=$testprefix.testout
+ [ -f $goodoutfile ] || goodoutfile=/dev/null
+ gooderrfile=$testprefix.testerr
+ [ -f $gooderrfile ] || gooderrfile=/dev/null
+ ./$testname <$infile >../$testname.out 2>../$testname.err
+ cmp ../$testname.out $goodoutfile > /dev/null || {
+ echo "FAIL: $testname output differs: see ../$testname.out, $goodoutfile"
+ exit 1
+ }
+ cmp ../$testname.err $gooderrfile > /dev/null || {
+ echo "FAIL: $testname error differs: see ../$testname.err, $gooderrfile"
+ exit 1
+ }
+ cd ..
+ rm -f $testname.err $testname.out
+done
+rm -rf TESTCXX
+exit 0
diff --git a/bdb/test/scr015/ignore b/bdb/test/scr015/ignore
new file mode 100644
index 00000000000..55ce82ae372
--- /dev/null
+++ b/bdb/test/scr015/ignore
@@ -0,0 +1,4 @@
+#
+# $Id: ignore,v 1.3 2001/10/12 13:02:32 dda Exp $
+#
+# A list of tests to ignore
diff --git a/bdb/test/scr015/testall b/bdb/test/scr015/testall
new file mode 100644
index 00000000000..a2d493a8b22
--- /dev/null
+++ b/bdb/test/scr015/testall
@@ -0,0 +1,32 @@
+#!/bin/sh -
+# $Id: testall,v 1.3 2001/09/13 14:49:36 dda Exp $
+#
+# Run all the C++ regression tests
+
+ecode=0
+prefixarg=""
+stdinarg=""
+while :
+do
+ case "$1" in
+ --prefix=* )
+ prefixarg="$1"; shift;;
+ --stdin )
+ stdinarg="$1"; shift;;
+ * )
+ break
+ esac
+done
+files="`find . -name \*.cpp -print`"
+for file in $files; do
+ name=`echo $file | sed -e 's:^\./::' -e 's/\.cpp$//'`
+ if grep $name ignore > /dev/null; then
+ echo " **** cxx test $name ignored"
+ else
+ echo " ==== cxx test $name"
+ if ! sh ./testone $prefixarg $stdinarg $name; then
+ ecode=1
+ fi
+ fi
+done
+exit $ecode
diff --git a/bdb/test/scr015/testone b/bdb/test/scr015/testone
new file mode 100644
index 00000000000..3bbba3f90f0
--- /dev/null
+++ b/bdb/test/scr015/testone
@@ -0,0 +1,122 @@
+#!/bin/sh -
+# $Id: testone,v 1.5 2002/07/05 22:17:59 dda Exp $
+#
+# Run just one C++ regression test, the single argument
+# is the basename of the test, e.g. TestRpcServer
+
+error()
+{
+ echo '' >&2
+ echo "C++ regression error: $@" >&2
+ echo '' >&2
+ ecode=1
+}
+
+# compares the result against the good version,
+# reports differences, and removes the result file
+# if there are no differences.
+#
+compare_result()
+{
+ good="$1"
+ latest="$2"
+ if [ ! -e "$good" ]; then
+ echo "Note: $good does not exist"
+ return
+ fi
+ tmpout=/tmp/blddb$$.tmp
+ diff "$good" "$latest" > $tmpout
+ if [ -s $tmpout ]; then
+ nbad=`grep '^[0-9]' $tmpout | wc -l`
+ error "$good and $latest differ in $nbad places."
+ else
+ rm $latest
+ fi
+ rm -f $tmpout
+}
+
+ecode=0
+stdinflag=n
+gdbflag=n
+CXX=${CXX:-c++}
+LIBS=${LIBS:-}
+
+# remove any -c option in the CXXFLAGS
+CXXFLAGS="`echo " ${CXXFLAGS} " | sed -e 's/ -c //g'`"
+
+# determine the prefix of the install tree
+prefix=""
+while :
+do
+ case "$1" in
+ --prefix=* )
+ prefix="`echo $1 | sed -e 's/--prefix=//'`"; shift
+ LIBS="-L$prefix/lib -ldb_cxx $LIBS"
+ CXXFLAGS="-I$prefix/include $CXXFLAGS"
+ export LD_LIBRARY_PATH="$prefix/lib:$LD_LIBRARY_PATH"
+ ;;
+ --stdin )
+ stdinflag=y; shift
+ ;;
+ --gdb )
+ CXXFLAGS="-g $CXXFLAGS"
+ gdbflag=y; shift
+ ;;
+ * )
+ break
+ ;;
+ esac
+done
+
+if [ "$#" = 0 ]; then
+ echo 'Usage: testone [ --prefix=<dir> | --stdin ] TestName'
+ exit 1
+fi
+name="$1"
+
+# compile
+rm -rf TESTDIR; mkdir TESTDIR
+cd ./TESTDIR
+
+${CXX} ${CXXFLAGS} -o $name ../$name.cpp ${LIBS} > ../$name.compileout 2>&1
+if [ $? != 0 -o -s ../$name.compileout ]; then
+ error "compilation of $name failed, see $name.compileout"
+ exit 1
+fi
+rm -f ../$name.compileout
+
+# find input and error file
+infile=../$name.testin
+if [ ! -f $infile ]; then
+ infile=/dev/null
+fi
+
+# run and diff results
+rm -rf TESTDIR
+if [ "$gdbflag" = y ]; then
+ if [ -s $infile ]; then
+ echo "Input file is $infile"
+ fi
+ gdb ./$name
+ exit 0
+elif [ "$stdinflag" = y ]; then
+ ./$name >../$name.out 2>../$name.err
+else
+ ./$name <$infile >../$name.out 2>../$name.err
+fi
+cd ..
+
+testerr=$name.testerr
+if [ ! -f $testerr ]; then
+ testerr=/dev/null
+fi
+
+testout=$name.testout
+if [ ! -f $testout ]; then
+ testout=/dev/null
+fi
+
+compare_result $testout $name.out
+compare_result $testerr $name.err
+rm -rf TESTDIR
+exit $ecode
diff --git a/bdb/test/scr016/CallbackTest.java b/bdb/test/scr016/CallbackTest.java
new file mode 100644
index 00000000000..eede964a027
--- /dev/null
+++ b/bdb/test/scr016/CallbackTest.java
@@ -0,0 +1,83 @@
+package com.sleepycat.test;
+import com.sleepycat.db.*;
+
+public class CallbackTest
+{
+ public static void main(String args[])
+ {
+ try {
+ Db db = new Db(null, 0);
+ db.set_bt_compare(new BtreeCompare());
+ db.open(null, "test.db", "", Db.DB_BTREE, Db.DB_CREATE, 0666);
+ StringDbt[] keys = new StringDbt[10];
+ StringDbt[] datas = new StringDbt[10];
+ for (int i = 0; i<10; i++) {
+ int val = (i * 3) % 10;
+ keys[i] = new StringDbt("key" + val);
+ datas[i] = new StringDbt("data" + val);
+ System.out.println("put " + val);
+ db.put(null, keys[i], datas[i], 0);
+ }
+ }
+ catch (DbException dbe) {
+ System.err.println("FAIL: " + dbe);
+ }
+ catch (java.io.FileNotFoundException fnfe) {
+ System.err.println("FAIL: " + fnfe);
+ }
+
+ }
+
+
+}
+
+class BtreeCompare
+ implements DbBtreeCompare
+{
+ /* A weird comparator, for example.
+ * In fact, it may not be legal, since it's not monotonically increasing.
+ */
+ public int bt_compare(Db db, Dbt dbt1, Dbt dbt2)
+ {
+ System.out.println("compare function called");
+ byte b1[] = dbt1.get_data();
+ byte b2[] = dbt2.get_data();
+ System.out.println(" " + (new String(b1)) + ", " + (new String(b2)));
+ int len1 = b1.length;
+ int len2 = b2.length;
+ if (len1 != len2)
+ return (len1 < len2) ? 1 : -1;
+ int value = 1;
+ for (int i=0; i<len1; i++) {
+ if (b1[i] != b2[i])
+ return (b1[i] < b2[i]) ? value : -value;
+ value *= -1;
+ }
+ return 0;
+ }
+}
+
+class StringDbt extends Dbt
+{
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ }
+
+ String getString()
+ {
+ return new String(get_data(), 0, get_size());
+ }
+}
diff --git a/bdb/test/scr016/CallbackTest.testout b/bdb/test/scr016/CallbackTest.testout
new file mode 100644
index 00000000000..68797d4a2de
--- /dev/null
+++ b/bdb/test/scr016/CallbackTest.testout
@@ -0,0 +1,60 @@
+put 0
+put 3
+compare function called
+ key3, key0
+put 6
+compare function called
+ key6, key3
+put 9
+compare function called
+ key9, key6
+put 2
+compare function called
+ key2, key9
+compare function called
+ key2, key0
+compare function called
+ key2, key6
+compare function called
+ key2, key3
+compare function called
+ key2, key0
+put 5
+compare function called
+ key5, key3
+compare function called
+ key5, key9
+compare function called
+ key5, key6
+put 8
+compare function called
+ key8, key5
+compare function called
+ key8, key9
+compare function called
+ key8, key6
+put 1
+compare function called
+ key1, key9
+compare function called
+ key1, key0
+compare function called
+ key1, key5
+compare function called
+ key1, key2
+compare function called
+ key1, key0
+put 4
+compare function called
+ key4, key5
+compare function called
+ key4, key2
+compare function called
+ key4, key3
+put 7
+compare function called
+ key7, key4
+compare function called
+ key7, key8
+compare function called
+ key7, key6
diff --git a/bdb/test/scr016/README b/bdb/test/scr016/README
new file mode 100644
index 00000000000..226a8aa3b77
--- /dev/null
+++ b/bdb/test/scr016/README
@@ -0,0 +1,37 @@
+# $Id: README,v 1.2 2001/05/31 23:09:10 dda Exp $
+
+Use the scripts testall or testone to run all, or just one of the Java
+tests. You must be in this directory to run them. For example,
+
+ $ export LD_LIBRARY_PATH=/usr/local/Berkeley3.3/lib
+ $ ./testone TestAppendRecno
+ $ ./testall
+
+The scripts will use javac and java in your path. Set environment
+variables $JAVAC and $JAVA to override this. It will also and honor
+any $CLASSPATH that is already set, prepending ../../../../classes to
+it, which is where the test .class files are put, and where the DB
+.class files can normally be found after a build on Unix and Windows.
+If none of these variables are set, everything will probably work
+with whatever java/javac is in your path.
+
+To run successfully, you will probably need to set $LD_LIBRARY_PATH
+to be the directory containing libdb_java-X.Y.so
+
+As an alternative, use the --prefix=<DIR> option, a la configure
+to set the top of the BerkeleyDB install directory. This forces
+the proper options to be added to $LD_LIBRARY_PATH.
+For example,
+
+ $ ./testone --prefix=/usr/include/BerkeleyDB TestAppendRecno
+ $ ./testall --prefix=/usr/include/BerkeleyDB
+
+The test framework is pretty simple. Any <name>.java file in this
+directory that is not mentioned in the 'ignore' file represents a
+test. If the test is not compiled successfully, the compiler output
+is left in <name>.compileout . Otherwise, the java program is run in
+a clean subdirectory using as input <name>.testin, or if that doesn't
+exist, /dev/null. Output and error from the test run are put into
+<name>.out, <name>.err . If <name>.testout, <name>.testerr exist,
+they are used as reference files and any differences are reported.
+If either of the reference files does not exist, /dev/null is used.
diff --git a/bdb/test/scr016/TestAppendRecno.java b/bdb/test/scr016/TestAppendRecno.java
new file mode 100644
index 00000000000..f4ea70ca084
--- /dev/null
+++ b/bdb/test/scr016/TestAppendRecno.java
@@ -0,0 +1,258 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestAppendRecno.java,v 1.4 2002/08/16 19:35:53 dda Exp $
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class TestAppendRecno
+ implements DbAppendRecno
+{
+ private static final String FileName = "access.db";
+ int callback_count = 0;
+ Db table = null;
+
+ public TestAppendRecno()
+ {
+ }
+
+ private static void usage()
+ {
+ System.err.println("usage: TestAppendRecno\n");
+ System.exit(1);
+ }
+
+ public static void main(String argv[])
+ {
+ try
+ {
+ TestAppendRecno app = new TestAppendRecno();
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("TestAppendRecno: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("TestAppendRecno: " + fnfe.toString());
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ table = new Db(null, 0);
+ table.set_error_stream(System.err);
+ table.set_errpfx("TestAppendRecno");
+ table.set_append_recno(this);
+
+ table.open(null, FileName, null, Db.DB_RECNO, Db.DB_CREATE, 0644);
+ for (int i=0; i<10; i++) {
+ System.out.println("\n*** Iteration " + i );
+ try {
+ RecnoDbt key = new RecnoDbt(77+i);
+ StringDbt data = new StringDbt("data" + i + "_xyz");
+ table.put(null, key, data, Db.DB_APPEND);
+ }
+ catch (DbException dbe) {
+ System.out.println("dbe: " + dbe);
+ }
+ }
+
+ // Acquire an iterator for the table.
+ Dbc iterator;
+ iterator = table.cursor(null, 0);
+
+ // Walk through the table, printing the key/data pairs.
+ // See class StringDbt defined below.
+ //
+ RecnoDbt key = new RecnoDbt();
+ StringDbt data = new StringDbt();
+ while (iterator.get(key, data, Db.DB_NEXT) == 0)
+ {
+ System.out.println(key.getRecno() + " : " + data.getString());
+ }
+ iterator.close();
+ table.close(0);
+ System.out.println("Test finished.");
+ }
+
+ public void db_append_recno(Db db, Dbt dbt, int recno)
+ throws DbException
+ {
+ int count = callback_count++;
+
+ System.out.println("====\ncallback #" + count);
+ System.out.println("db is table: " + (db == table));
+ System.out.println("recno = " + recno);
+
+ // This gives variable output.
+ //System.out.println("dbt = " + dbt);
+ if (dbt instanceof RecnoDbt) {
+ System.out.println("dbt = " +
+ ((RecnoDbt)dbt).getRecno());
+ }
+ else if (dbt instanceof StringDbt) {
+ System.out.println("dbt = " +
+ ((StringDbt)dbt).getString());
+ }
+ else {
+ // Note: the dbts are created out of whole
+ // cloth by Berkeley DB, not us!
+ System.out.println("internally created dbt: " +
+ new StringDbt(dbt) + ", size " +
+ dbt.get_size());
+ }
+
+ switch (count) {
+ case 0:
+ // nothing
+ break;
+
+ case 1:
+ dbt.set_size(dbt.get_size() - 1);
+ break;
+
+ case 2:
+ System.out.println("throwing...");
+ throw new DbException("append_recno thrown");
+ //not reached
+
+ case 3:
+ // Should result in an error (size unchanged).
+ dbt.set_offset(1);
+ break;
+
+ case 4:
+ dbt.set_offset(1);
+ dbt.set_size(dbt.get_size() - 1);
+ break;
+
+ case 5:
+ dbt.set_offset(1);
+ dbt.set_size(dbt.get_size() - 2);
+ break;
+
+ case 6:
+ dbt.set_data(new String("abc").getBytes());
+ dbt.set_size(3);
+ break;
+
+ case 7:
+ // Should result in an error.
+ dbt.set_data(null);
+ break;
+
+ case 8:
+ // Should result in an error.
+ dbt.set_data(new String("abc").getBytes());
+ dbt.set_size(4);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ // Here's an example of how you can extend a Dbt to store recno's.
+ //
+ static /*inner*/
+ class RecnoDbt extends Dbt
+ {
+ RecnoDbt()
+ {
+ this(0); // let other constructor do most of the work
+ }
+
+ RecnoDbt(int value)
+ {
+ set_flags(Db.DB_DBT_USERMEM); // do not allocate on retrieval
+ arr = new byte[4];
+ set_data(arr); // use our local array for data
+ set_ulen(4); // size of return storage
+ setRecno(value);
+ }
+
+ public String toString() /*override*/
+ {
+ return String.valueOf(getRecno());
+ }
+
+ void setRecno(int value)
+ {
+ set_recno_key_data(value);
+ set_size(arr.length);
+ }
+
+ int getRecno()
+ {
+ return get_recno_key_data();
+ }
+
+ byte arr[];
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ StringDbt(Dbt dbt)
+ {
+ set_data(dbt.get_data());
+ set_size(dbt.get_size());
+ }
+
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ }
+
+ String getString()
+ {
+ return new String(get_data(), 0, get_size());
+ }
+
+ public String toString() /*override*/
+ {
+ return getString();
+ }
+ }
+}
+
diff --git a/bdb/test/scr016/TestAppendRecno.testout b/bdb/test/scr016/TestAppendRecno.testout
new file mode 100644
index 00000000000..970174e7a96
--- /dev/null
+++ b/bdb/test/scr016/TestAppendRecno.testout
@@ -0,0 +1,82 @@
+
+*** Iteration 0
+====
+callback #0
+db is table: true
+recno = 1
+internally created dbt: data0_xyz, size 9
+
+*** Iteration 1
+====
+callback #1
+db is table: true
+recno = 2
+internally created dbt: data1_xyz, size 9
+
+*** Iteration 2
+====
+callback #2
+db is table: true
+recno = 3
+internally created dbt: data2_xyz, size 9
+throwing...
+dbe: com.sleepycat.db.DbException: append_recno thrown
+
+*** Iteration 3
+====
+callback #3
+db is table: true
+recno = 3
+internally created dbt: data3_xyz, size 9
+dbe: com.sleepycat.db.DbException: Dbt.size + Dbt.offset greater than array length
+
+*** Iteration 4
+====
+callback #4
+db is table: true
+recno = 3
+internally created dbt: data4_xyz, size 9
+
+*** Iteration 5
+====
+callback #5
+db is table: true
+recno = 4
+internally created dbt: data5_xyz, size 9
+
+*** Iteration 6
+====
+callback #6
+db is table: true
+recno = 5
+internally created dbt: data6_xyz, size 9
+
+*** Iteration 7
+====
+callback #7
+db is table: true
+recno = 6
+internally created dbt: data7_xyz, size 9
+dbe: com.sleepycat.db.DbException: Dbt.data is null
+
+*** Iteration 8
+====
+callback #8
+db is table: true
+recno = 6
+internally created dbt: data8_xyz, size 9
+dbe: com.sleepycat.db.DbException: Dbt.size + Dbt.offset greater than array length
+
+*** Iteration 9
+====
+callback #9
+db is table: true
+recno = 6
+internally created dbt: data9_xyz, size 9
+1 : data0_xyz
+2 : data1_xy
+3 : ata4_xyz
+4 : ata5_xy
+5 : abc
+6 : data9_xyz
+Test finished.
diff --git a/bdb/test/scr016/TestAssociate.java b/bdb/test/scr016/TestAssociate.java
new file mode 100644
index 00000000000..4105b9cb0a1
--- /dev/null
+++ b/bdb/test/scr016/TestAssociate.java
@@ -0,0 +1,333 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestAssociate.java,v 1.4 2002/08/16 19:35:54 dda Exp $
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Hashtable;
+
+public class TestAssociate
+ implements DbDupCompare
+{
+ private static final String FileName = "access.db";
+ public static Db saveddb1 = null;
+ public static Db saveddb2 = null;
+
+ public TestAssociate()
+ {
+ }
+
+ private static void usage()
+ {
+ System.err.println("usage: TestAssociate\n");
+ System.exit(1);
+ }
+
+ public static void main(String argv[])
+ {
+ try
+ {
+ TestAssociate app = new TestAssociate();
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("TestAssociate: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("TestAssociate: " + fnfe.toString());
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ public static int counter = 0;
+ public static String results[] = { "abc", "def", "ghi", "JKL", "MNO", null };
+
+ // Prompts for a line, and keeps prompting until a non blank
+ // line is returned. Returns null on error.
+ //
+ static public String askForLine(Reader reader,
+ PrintStream out, String prompt)
+ {
+ /*
+ String result = "";
+ while (result != null && result.length() == 0) {
+ out.print(prompt);
+ out.flush();
+ result = getLine(reader);
+ }
+ return result;
+ */
+ return results[counter++];
+ }
+
+ // Not terribly efficient, but does the job.
+ // Works for reading a line from stdin or a file.
+ // Returns null on EOF. If EOF appears in the middle
+ // of a line, returns that line, then null on next call.
+ //
+ static public String getLine(Reader reader)
+ {
+ StringBuffer b = new StringBuffer();
+ int c;
+ try {
+ while ((c = reader.read()) != -1 && c != '\n') {
+ if (c != '\r')
+ b.append((char)c);
+ }
+ }
+ catch (IOException ioe) {
+ c = -1;
+ }
+
+ if (c == -1 && b.length() == 0)
+ return null;
+ else
+ return b.toString();
+ }
+
+ static public String shownull(Object o)
+ {
+ if (o == null)
+ return "null";
+ else
+ return "not null";
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ DbEnv dbenv = new DbEnv(0);
+ dbenv.open("./", Db.DB_CREATE|Db.DB_INIT_MPOOL, 0644);
+ (new java.io.File(FileName)).delete();
+ Db table = new Db(dbenv, 0);
+ Db table2 = new Db(dbenv, 0);
+ table2.set_dup_compare(this);
+ table2.set_flags(Db.DB_DUPSORT);
+ table.set_error_stream(System.err);
+ table2.set_error_stream(System.err);
+ table.set_errpfx("TestAssociate");
+ table2.set_errpfx("TestAssociate(table2)");
+ System.out.println("Primary database is " + shownull(table));
+ System.out.println("Secondary database is " + shownull(table2));
+ saveddb1 = table;
+ saveddb2 = table2;
+ table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+ table2.open(null, FileName + "2", null,
+ Db.DB_BTREE, Db.DB_CREATE, 0644);
+ table.associate(null, table2, new Capitalize(), 0);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ Reader reader = new StringReader("abc\ndef\njhi");
+
+ for (;;) {
+ String line = askForLine(reader, System.out, "input> ");
+ if (line == null)
+ break;
+
+ String reversed = (new StringBuffer(line)).reverse().toString();
+
+ // See definition of StringDbt below
+ //
+ StringDbt key = new StringDbt(line);
+ StringDbt data = new StringDbt(reversed);
+
+ try
+ {
+ int err;
+ if ((err = table.put(null,
+ key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
+ System.out.println("Key " + line + " already exists.");
+ }
+ }
+ catch (DbException dbe)
+ {
+ System.out.println(dbe.toString());
+ }
+ System.out.println("");
+ }
+
+ // Acquire an iterator for the table.
+ Dbc iterator;
+ iterator = table2.cursor(null, 0);
+
+ // Walk through the table, printing the key/data pairs.
+ // See class StringDbt defined below.
+ //
+ StringDbt key = new StringDbt();
+ StringDbt data = new StringDbt();
+ StringDbt pkey = new StringDbt();
+
+ while (iterator.get(key, data, Db.DB_NEXT) == 0)
+ {
+ System.out.println(key.getString() + " : " + data.getString());
+ }
+
+ key.setString("BC");
+ System.out.println("get BC returns " + table2.get(null, key, data, 0));
+ System.out.println(" values: " + key.getString() + " : " + data.getString());
+ System.out.println("pget BC returns " + table2.pget(null, key, pkey, data, 0));
+ System.out.println(" values: " + key.getString() + " : " + pkey.getString() + " : " + data.getString());
+ key.setString("KL");
+ System.out.println("get KL returns " + table2.get(null, key, data, 0));
+ System.out.println(" values: " + key.getString() + " : " + data.getString());
+ System.out.println("pget KL returns " + table2.pget(null, key, pkey, data, 0));
+ System.out.println(" values: " + key.getString() + " : " + pkey.getString() + " : " + data.getString());
+
+ iterator.close();
+ table.close(0);
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ }
+
+ String getString()
+ {
+ return new String(get_data(), 0, get_size());
+ }
+
+ public String toString()
+ {
+ return "StringDbt=" + getString();
+ }
+ }
+
+ /* creates a stupid secondary index as follows:
+ For an N letter key, we use N-1 letters starting at
+ position 1. If the new letters are already capitalized,
+ we return the old array, but with offset set to 1.
+ If the letters are not capitalized, we create a new,
+ capitalized array. This is pretty stupid for
+ an application, but it tests all the paths in the runtime.
+ */
+ public static class Capitalize implements DbSecondaryKeyCreate
+ {
+ public int secondary_key_create(Db secondary, Dbt key, Dbt value,
+ Dbt result)
+ throws DbException
+ {
+ String which = "unknown db";
+ if (saveddb1.equals(secondary)) {
+ which = "primary";
+ }
+ else if (saveddb2.equals(secondary)) {
+ which = "secondary";
+ }
+ System.out.println("secondary_key_create, Db: " + shownull(secondary) + "(" + which + "), key: " + show_dbt(key) + ", data: " + show_dbt(value));
+ int len = key.get_size();
+ byte[] arr = key.get_data();
+ boolean capped = true;
+
+ if (len < 1)
+ throw new DbException("bad key");
+
+ if (len < 2)
+ return Db.DB_DONOTINDEX;
+
+ result.set_size(len - 1);
+ for (int i=1; capped && i<len; i++) {
+ if (!Character.isUpperCase((char)arr[i]))
+ capped = false;
+ }
+ if (capped) {
+ System.out.println(" creating key(1): " + new String(arr, 1, len-1));
+ result.set_data(arr);
+ result.set_offset(1);
+ }
+ else {
+ System.out.println(" creating key(2): " + (new String(arr)).substring(1).
+ toUpperCase());
+ result.set_data((new String(arr)).substring(1).
+ toUpperCase().getBytes());
+ }
+ return 0;
+ }
+ }
+
+ public int dup_compare(Db db, Dbt dbt1, Dbt dbt2)
+ {
+ System.out.println("compare");
+ int sz1 = dbt1.get_size();
+ int sz2 = dbt2.get_size();
+ if (sz1 < sz2)
+ return -1;
+ if (sz1 > sz2)
+ return 1;
+ byte[] data1 = dbt1.get_data();
+ byte[] data2 = dbt2.get_data();
+ for (int i=0; i<sz1; i++)
+ if (data1[i] != data2[i])
+ return (data1[i] < data2[i] ? -1 : 1);
+ return 0;
+ }
+
+ public static int nseen = 0;
+ public static Hashtable ht = new Hashtable();
+
+ public static String show_dbt(Dbt dbt)
+ {
+ String name;
+
+ if (dbt == null)
+ return "null dbt";
+
+ name = (String)ht.get(dbt);
+ if (name == null) {
+ name = "Dbt" + (nseen++);
+ ht.put(dbt, name);
+ }
+
+ byte[] value = dbt.get_data();
+ if (value == null)
+ return name + "(null)";
+ else
+ return name + "(\"" + new String(value) + "\")";
+ }
+}
+
+
diff --git a/bdb/test/scr016/TestAssociate.testout b/bdb/test/scr016/TestAssociate.testout
new file mode 100644
index 00000000000..34414b660d1
--- /dev/null
+++ b/bdb/test/scr016/TestAssociate.testout
@@ -0,0 +1,30 @@
+Primary database is not null
+Secondary database is not null
+secondary_key_create, Db: not null(secondary), key: Dbt0("abc"), data: Dbt1("cba")
+ creating key(2): BC
+
+secondary_key_create, Db: not null(secondary), key: Dbt2("def"), data: Dbt3("fed")
+ creating key(2): EF
+
+secondary_key_create, Db: not null(secondary), key: Dbt4("ghi"), data: Dbt5("ihg")
+ creating key(2): HI
+
+secondary_key_create, Db: not null(secondary), key: Dbt6("JKL"), data: Dbt7("LKJ")
+ creating key(1): KL
+
+secondary_key_create, Db: not null(secondary), key: Dbt8("MNO"), data: Dbt9("ONM")
+ creating key(1): NO
+
+BC : cba
+EF : fed
+HI : ihg
+KL : LKJ
+NO : ONM
+get BC returns 0
+ values: BC : cba
+pget BC returns 0
+ values: BC : abc : cba
+get KL returns 0
+ values: KL : LKJ
+pget KL returns 0
+ values: KL : JKL : LKJ
diff --git a/bdb/test/scr016/TestClosedDb.java b/bdb/test/scr016/TestClosedDb.java
new file mode 100644
index 00000000000..3bd6e5380f8
--- /dev/null
+++ b/bdb/test/scr016/TestClosedDb.java
@@ -0,0 +1,62 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestClosedDb.java,v 1.4 2002/01/23 14:29:51 bostic Exp $
+ */
+
+/*
+ * Close the Db, and make sure operations after that fail gracefully.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestClosedDb
+{
+ public static void main(String[] args)
+ {
+ try {
+ Db db = new Db(null, 0);
+ db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ // populate our massive database.
+ Dbt keydbt = new Dbt("key".getBytes());
+ Dbt datadbt = new Dbt("data".getBytes());
+ db.put(null, keydbt, datadbt, 0);
+
+ // Now, retrieve. We could use keydbt over again,
+ // but that wouldn't be typical in an application.
+ Dbt goodkeydbt = new Dbt("key".getBytes());
+ Dbt badkeydbt = new Dbt("badkey".getBytes());
+ Dbt resultdbt = new Dbt();
+ resultdbt.set_flags(Db.DB_DBT_MALLOC);
+
+ int ret;
+
+ // Close the db - subsequent operations should fail
+ // by throwing an exception.
+ db.close(0);
+ try {
+ db.get(null, goodkeydbt, resultdbt, 0);
+ System.out.println("Error - did not expect to get this far.");
+ }
+ catch (DbException dbe) {
+ System.out.println("Got expected Db Exception: " + dbe);
+ }
+ System.out.println("finished test");
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ }
+
+ }
+
+}
diff --git a/bdb/test/scr016/TestClosedDb.testout b/bdb/test/scr016/TestClosedDb.testout
new file mode 100644
index 00000000000..ce13883f63a
--- /dev/null
+++ b/bdb/test/scr016/TestClosedDb.testout
@@ -0,0 +1,2 @@
+Got expected Db Exception: com.sleepycat.db.DbException: null object: Invalid argument
+finished test
diff --git a/bdb/test/scr016/TestConstruct01.java b/bdb/test/scr016/TestConstruct01.java
new file mode 100644
index 00000000000..b60073ebc0d
--- /dev/null
+++ b/bdb/test/scr016/TestConstruct01.java
@@ -0,0 +1,474 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestConstruct01.java,v 1.6 2002/01/23 14:29:51 bostic Exp $
+ */
+
+/*
+ * Do some regression tests for constructors.
+ * Run normally (without arguments) it is a simple regression test.
+ * Run with a numeric argument, it repeats the regression a number
+ * of times, to try to determine if there are memory leaks.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+
+public class TestConstruct01
+{
+ public static final String CONSTRUCT01_DBNAME = "construct01.db";
+ public static final String CONSTRUCT01_DBDIR = "/tmp";
+ public static final String CONSTRUCT01_DBFULLPATH =
+ CONSTRUCT01_DBDIR + "/" + CONSTRUCT01_DBNAME;
+
+ private int itemcount; // count the number of items in the database
+ public static boolean verbose_flag = false;
+
+ public static void ERR(String a)
+ {
+ System.out.println("FAIL: " + a);
+ System.err.println("FAIL: " + a);
+ sysexit(1);
+ }
+
+ public static void DEBUGOUT(String s)
+ {
+ System.out.println(s);
+ }
+
+ public static void VERBOSEOUT(String s)
+ {
+ if (verbose_flag)
+ System.out.println(s);
+ }
+
+ public static void sysexit(int code)
+ {
+ System.exit(code);
+ }
+
+ private static void check_file_removed(String name, boolean fatal,
+ boolean force_remove_first)
+ {
+ File f = new File(name);
+ if (force_remove_first) {
+ f.delete();
+ }
+ if (f.exists()) {
+ if (fatal)
+ System.out.print("FAIL: ");
+ System.out.print("File \"" + name + "\" still exists after run\n");
+ if (fatal)
+ sysexit(1);
+ }
+ }
+
+
+ // Check that key/data for 0 - count-1 are already present,
+ // and write a key/data for count. The key and data are
+ // both "0123...N" where N == count-1.
+ //
+ // For some reason on Windows, we need to open using the full pathname
+ // of the file when there is no environment, thus the 'has_env'
+ // variable.
+ //
+ void rundb(Db db, int count, boolean has_env, TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ String name;
+
+ if (has_env)
+ name = CONSTRUCT01_DBNAME;
+ else
+ name = CONSTRUCT01_DBFULLPATH;
+
+ db.set_error_stream(System.err);
+
+ // We don't really care about the pagesize, but we do want
+ // to make sure adjusting Db specific variables works before
+ // opening the db.
+ //
+ db.set_pagesize(1024);
+ db.open(null, name, null, Db.DB_BTREE,
+ (count != 0) ? 0 : Db.DB_CREATE, 0664);
+
+
+ // The bit map of keys we've seen
+ long bitmap = 0;
+
+ // The bit map of keys we expect to see
+ long expected = (1 << (count+1)) - 1;
+
+ byte outbuf[] = new byte[count+1];
+ int i;
+ for (i=0; i<count; i++) {
+ outbuf[i] = (byte)('0' + i);
+ //outbuf[i] = System.out.println((byte)('0' + i);
+ }
+ outbuf[i++] = (byte)'x';
+
+ /*
+ System.out.println("byte: " + ('0' + 0) + ", after: " +
+ (int)'0' + "=" + (int)('0' + 0) +
+ "," + (byte)outbuf[0]);
+ */
+
+ Dbt key = new Dbt(outbuf, 0, i);
+ Dbt data = new Dbt(outbuf, 0, i);
+
+ //DEBUGOUT("Put: " + (char)outbuf[0] + ": " + new String(outbuf));
+ db.put(null, key, data, Db.DB_NOOVERWRITE);
+
+ // Acquire a cursor for the table.
+ Dbc dbcp = db.cursor(null, 0);
+
+ // Walk through the table, checking
+ Dbt readkey = new Dbt();
+ Dbt readdata = new Dbt();
+ Dbt whoknows = new Dbt();
+
+ readkey.set_flags(options.dbt_alloc_flags);
+ readdata.set_flags(options.dbt_alloc_flags);
+
+ //DEBUGOUT("Dbc.get");
+ while (dbcp.get(readkey, readdata, Db.DB_NEXT) == 0) {
+ String key_string = new String(readkey.get_data());
+ String data_string = new String(readdata.get_data());
+ //DEBUGOUT("Got: " + key_string + ": " + data_string);
+ int len = key_string.length();
+ if (len <= 0 || key_string.charAt(len-1) != 'x') {
+ ERR("reread terminator is bad");
+ }
+ len--;
+ long bit = (1 << len);
+ if (len > count) {
+ ERR("reread length is bad: expect " + count + " got "+ len + " (" + key_string + ")" );
+ }
+ else if (!data_string.equals(key_string)) {
+ ERR("key/data don't match");
+ }
+ else if ((bitmap & bit) != 0) {
+ ERR("key already seen");
+ }
+ else if ((expected & bit) == 0) {
+ ERR("key was not expected");
+ }
+ else {
+ bitmap |= bit;
+ expected &= ~(bit);
+ for (i=0; i<len; i++) {
+ if (key_string.charAt(i) != ('0' + i)) {
+ System.out.print(" got " + key_string
+ + " (" + (int)key_string.charAt(i)
+ + "), wanted " + i
+ + " (" + (int)('0' + i)
+ + ") at position " + i + "\n");
+ ERR("key is corrupt");
+ }
+ }
+ }
+ }
+ if (expected != 0) {
+ System.out.print(" expected more keys, bitmap is: " + expected + "\n");
+ ERR("missing keys in database");
+ }
+ dbcp.close();
+ db.close(0);
+ }
+
+ void t1(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ Db db = new Db(null, 0);
+ rundb(db, itemcount++, false, options);
+ }
+
+ void t2(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ Db db = new Db(null, 0);
+ rundb(db, itemcount++, false, options);
+ // rundb(db, itemcount++, false, options);
+ // rundb(db, itemcount++, false, options);
+ }
+
+ void t3(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ Db db = new Db(null, 0);
+ // rundb(db, itemcount++, false, options);
+ db.set_errpfx("test3");
+ for (int i=0; i<100; i++)
+ db.set_errpfx("str" + i);
+ rundb(db, itemcount++, false, options);
+ }
+
+ void t4(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ DbEnv env = new DbEnv(0);
+ env.open(CONSTRUCT01_DBDIR, Db.DB_CREATE | Db.DB_INIT_MPOOL, 0);
+ Db db = new Db(env, 0);
+ /**/
+ //rundb(db, itemcount++, true, options);
+ db.set_errpfx("test4");
+ rundb(db, itemcount++, true, options);
+ /**/
+ env.close(0);
+ }
+
+ void t5(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ DbEnv env = new DbEnv(0);
+ env.open(CONSTRUCT01_DBDIR, Db.DB_CREATE | Db.DB_INIT_MPOOL, 0);
+ Db db = new Db(env, 0);
+ // rundb(db, itemcount++, true, options);
+ db.set_errpfx("test5");
+ rundb(db, itemcount++, true, options);
+ /*
+ env.close(0);
+
+ // reopen the environment, don't recreate
+ env.open(CONSTRUCT01_DBDIR, Db.DB_INIT_MPOOL, 0);
+ // Note we cannot reuse the old Db!
+ */
+ Db anotherdb = new Db(env, 0);
+
+ // rundb(anotherdb, itemcount++, true, options);
+ anotherdb.set_errpfx("test5");
+ rundb(anotherdb, itemcount++, true, options);
+ env.close(0);
+ }
+
+ void t6(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ Db db = new Db(null, 0);
+ DbEnv dbenv = new DbEnv(0);
+ db.close(0);
+ dbenv.close(0);
+
+ System.gc();
+ System.runFinalization();
+ }
+
+ // By design, t7 leaves a db and dbenv open; it should be detected.
+ void t7(TestOptions options)
+ throws DbException, FileNotFoundException
+ {
+ Db db = new Db(null, 0);
+ DbEnv dbenv = new DbEnv(0);
+
+ System.gc();
+ System.runFinalization();
+ }
+
+ // remove any existing environment or database
+ void removeall(boolean use_db)
+ {
+ {
+ if (use_db) {
+ try {
+ /**/
+ //memory leak for this:
+ Db tmpdb = new Db(null, 0);
+ tmpdb.remove(CONSTRUCT01_DBFULLPATH, null, 0);
+ /**/
+ DbEnv tmpenv = new DbEnv(0);
+ tmpenv.remove(CONSTRUCT01_DBDIR, Db.DB_FORCE);
+ }
+ catch (DbException dbe) {
+ System.err.println("error during remove: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ //expected error:
+ // System.err.println("error during remove: " + fnfe);
+ }
+ }
+ }
+ check_file_removed(CONSTRUCT01_DBFULLPATH, true, !use_db);
+ for (int i=0; i<8; i++) {
+ String fname = "__db.00" + i;
+ check_file_removed(fname, true, !use_db);
+ }
+ }
+
+ boolean doall(TestOptions options)
+ {
+ itemcount = 0;
+ try {
+ removeall((options.testmask & 1) != 0);
+ for (int item=1; item<32; item++) {
+ if ((options.testmask & (1 << item)) != 0) {
+ VERBOSEOUT(" Running test " + item + ":");
+ switch (item) {
+ case 1:
+ t1(options);
+ break;
+ case 2:
+ t2(options);
+ break;
+ case 3:
+ t3(options);
+ break;
+ case 4:
+ t4(options);
+ break;
+ case 5:
+ t5(options);
+ break;
+ case 6:
+ t6(options);
+ break;
+ case 7:
+ t7(options);
+ break;
+ default:
+ ERR("unknown test case: " + item);
+ break;
+ }
+ VERBOSEOUT(" finished.\n");
+ }
+ }
+ removeall((options.testmask & 1) != 0);
+ options.successcounter++;
+ return true;
+ }
+ catch (DbException dbe) {
+ ERR("EXCEPTION RECEIVED: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ ERR("EXCEPTION RECEIVED: " + fnfe);
+ }
+ return false;
+ }
+
+ public static void main(String args[])
+ {
+ int iterations = 200;
+ int mask = 0x7f;
+
+ // Make sure the database file is removed before we start.
+ check_file_removed(CONSTRUCT01_DBFULLPATH, true, true);
+
+ for (int argcnt=0; argcnt<args.length; argcnt++) {
+ String arg = args[argcnt];
+ if (arg.charAt(0) == '-') {
+ // keep on lower bit, which means to remove db between tests.
+ mask = 1;
+ for (int pos=1; pos<arg.length(); pos++) {
+ char ch = arg.charAt(pos);
+ if (ch >= '0' && ch <= '9') {
+ mask |= (1 << (ch - '0'));
+ }
+ else if (ch == 'v') {
+ verbose_flag = true;
+ }
+ else {
+ ERR("Usage: construct01 [-testdigits] count");
+ }
+ }
+ VERBOSEOUT("mask = " + mask);
+
+ }
+ else {
+ try {
+ iterations = Integer.parseInt(arg);
+ if (iterations < 0) {
+ ERR("Usage: construct01 [-testdigits] count");
+ }
+ }
+ catch (NumberFormatException nfe) {
+ ERR("EXCEPTION RECEIVED: " + nfe);
+ }
+ }
+ }
+
+ // Run GC before and after the test to give
+ // a baseline for any Java memory used.
+ //
+ System.gc();
+ System.runFinalization();
+ VERBOSEOUT("gc complete");
+ long starttotal = Runtime.getRuntime().totalMemory();
+ long startfree = Runtime.getRuntime().freeMemory();
+
+ TestConstruct01 con = new TestConstruct01();
+ int[] dbt_flags = { 0, Db.DB_DBT_MALLOC, Db.DB_DBT_REALLOC };
+ String[] dbt_flags_name = { "default", "malloc", "realloc" };
+
+ TestOptions options = new TestOptions();
+ options.testmask = mask;
+
+ for (int flagiter = 0; flagiter < dbt_flags.length; flagiter++) {
+ options.dbt_alloc_flags = dbt_flags[flagiter];
+
+ VERBOSEOUT("Running with DBT alloc flags: " +
+ dbt_flags_name[flagiter]);
+ for (int i=0; i<iterations; i++) {
+ if (iterations != 0) {
+ VERBOSEOUT("(" + i + "/" + iterations + ") ");
+ }
+ VERBOSEOUT("construct01 running:");
+ if (!con.doall(options)) {
+ ERR("SOME TEST FAILED");
+ }
+ else {
+ VERBOSEOUT("\nTESTS SUCCESSFUL");
+ }
+
+ // We continually run GC during the test to keep
+ // the Java memory usage low. That way we can
+ // monitor the total memory usage externally
+ // (e.g. via ps) and verify that we aren't leaking
+ // memory in the JNI or DB layer.
+ //
+ System.gc();
+ System.runFinalization();
+ VERBOSEOUT("gc complete");
+ }
+ }
+
+ if (options.successcounter == 600) {
+ System.out.println("ALL TESTS SUCCESSFUL");
+ }
+ else {
+ System.out.println("***FAIL: " + (600 - options.successcounter) +
+ " tests did not complete");
+ }
+ long endtotal = Runtime.getRuntime().totalMemory();
+ long endfree = Runtime.getRuntime().freeMemory();
+
+ System.out.println("delta for total mem: " + magnitude(endtotal - starttotal));
+ System.out.println("delta for free mem: " + magnitude(endfree - startfree));
+
+ return;
+ }
+
+ static String magnitude(long value)
+ {
+ final long max = 10000000;
+ for (long scale = 10; scale <= max; scale *= 10) {
+ if (value < scale && value > -scale)
+ return "<" + scale;
+ }
+ return ">" + max;
+ }
+
+}
+
+class TestOptions
+{
+ int testmask = 0; // which tests to run
+ int dbt_alloc_flags = 0; // DB_DBT_* flags to use
+ int successcounter =0;
+}
+
diff --git a/mysql-test/t/README b/bdb/test/scr016/TestConstruct01.testerr
index e69de29bb2d..e69de29bb2d 100644
--- a/mysql-test/t/README
+++ b/bdb/test/scr016/TestConstruct01.testerr
diff --git a/bdb/test/scr016/TestConstruct01.testout b/bdb/test/scr016/TestConstruct01.testout
new file mode 100644
index 00000000000..5d2041cd197
--- /dev/null
+++ b/bdb/test/scr016/TestConstruct01.testout
@@ -0,0 +1,3 @@
+ALL TESTS SUCCESSFUL
+delta for total mem: <10
+delta for free mem: <10000
diff --git a/bdb/test/scr016/TestConstruct02.java b/bdb/test/scr016/TestConstruct02.java
new file mode 100644
index 00000000000..5bbb55ccd56
--- /dev/null
+++ b/bdb/test/scr016/TestConstruct02.java
@@ -0,0 +1,326 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestConstruct02.java,v 1.6 2002/08/16 19:35:54 dda Exp $
+ */
+
+/*
+ * Do some regression tests for constructors.
+ * Run normally (without arguments) it is a simple regression test.
+ * Run with a numeric argument, it repeats the regression a number
+ * of times, to try to determine if there are memory leaks.
+ */
+
+package com.sleepycat.test;
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+
+public class TestConstruct02
+{
+ public static final String CONSTRUCT02_DBNAME = "construct02.db";
+ public static final String CONSTRUCT02_DBDIR = "./";
+ public static final String CONSTRUCT02_DBFULLPATH =
+ CONSTRUCT02_DBDIR + "/" + CONSTRUCT02_DBNAME;
+
+ private int itemcount; // count the number of items in the database
+ public static boolean verbose_flag = false;
+
+ private DbEnv dbenv = new DbEnv(0);
+
+ public TestConstruct02()
+ throws DbException, FileNotFoundException
+ {
+ dbenv.open(CONSTRUCT02_DBDIR, Db.DB_CREATE | Db.DB_INIT_MPOOL, 0666);
+ }
+
+ public void close()
+ {
+ try {
+ dbenv.close(0);
+ removeall(true, true);
+ }
+ catch (DbException dbe) {
+ ERR("DbException: " + dbe);
+ }
+ }
+
+ public static void ERR(String a)
+ {
+ System.out.println("FAIL: " + a);
+ sysexit(1);
+ }
+
+ public static void DEBUGOUT(String s)
+ {
+ System.out.println(s);
+ }
+
+ public static void VERBOSEOUT(String s)
+ {
+ if (verbose_flag)
+ System.out.println(s);
+ }
+
+ public static void sysexit(int code)
+ {
+ System.exit(code);
+ }
+
+ private static void check_file_removed(String name, boolean fatal,
+ boolean force_remove_first)
+ {
+ File f = new File(name);
+ if (force_remove_first) {
+ f.delete();
+ }
+ if (f.exists()) {
+ if (fatal)
+ System.out.print("FAIL: ");
+ System.out.print("File \"" + name + "\" still exists after run\n");
+ if (fatal)
+ sysexit(1);
+ }
+ }
+
+
+ // Check that key/data for 0 - count-1 are already present,
+ // and write a key/data for count. The key and data are
+ // both "0123...N" where N == count-1.
+ //
+ void rundb(Db db, int count)
+ throws DbException, FileNotFoundException
+ {
+ if (count >= 64)
+ throw new IllegalArgumentException("rundb count arg >= 64");
+
+ // The bit map of keys we've seen
+ long bitmap = 0;
+
+ // The bit map of keys we expect to see
+ long expected = (1 << (count+1)) - 1;
+
+ byte outbuf[] = new byte[count+1];
+ int i;
+ for (i=0; i<count; i++) {
+ outbuf[i] = (byte)('0' + i);
+ }
+ outbuf[i++] = (byte)'x';
+
+ Dbt key = new Dbt(outbuf, 0, i);
+ Dbt data = new Dbt(outbuf, 0, i);
+
+ db.put(null, key, data, Db.DB_NOOVERWRITE);
+
+ // Acquire a cursor for the table.
+ Dbc dbcp = db.cursor(null, 0);
+
+ // Walk through the table, checking
+ Dbt readkey = new Dbt();
+ Dbt readdata = new Dbt();
+ Dbt whoknows = new Dbt();
+
+ readkey.set_flags(Db.DB_DBT_MALLOC);
+ readdata.set_flags(Db.DB_DBT_MALLOC);
+
+ while (dbcp.get(readkey, readdata, Db.DB_NEXT) == 0) {
+ byte[] key_bytes = readkey.get_data();
+ byte[] data_bytes = readdata.get_data();
+
+ int len = key_bytes.length;
+ if (len != data_bytes.length) {
+ ERR("key and data are different");
+ }
+ for (i=0; i<len-1; i++) {
+ byte want = (byte)('0' + i);
+ if (key_bytes[i] != want || data_bytes[i] != want) {
+ System.out.println(" got " + new String(key_bytes) +
+ "/" + new String(data_bytes));
+ ERR("key or data is corrupt");
+ }
+ }
+ if (len <= 0 ||
+ key_bytes[len-1] != (byte)'x' ||
+ data_bytes[len-1] != (byte)'x') {
+ ERR("reread terminator is bad");
+ }
+ len--;
+ long bit = (1 << len);
+ if (len > count) {
+ ERR("reread length is bad: expect " + count + " got "+ len);
+ }
+ else if ((bitmap & bit) != 0) {
+ ERR("key already seen");
+ }
+ else if ((expected & bit) == 0) {
+ ERR("key was not expected");
+ }
+ bitmap |= bit;
+ expected &= ~(bit);
+ }
+ if (expected != 0) {
+ System.out.print(" expected more keys, bitmap is: " +
+ expected + "\n");
+ ERR("missing keys in database");
+ }
+ dbcp.close();
+ }
+
+ void t1()
+ throws DbException, FileNotFoundException
+ {
+ Db db = new Db(dbenv, 0);
+ db.set_error_stream(System.err);
+ db.set_pagesize(1024);
+ db.open(null, CONSTRUCT02_DBNAME, null, Db.DB_BTREE,
+ Db.DB_CREATE, 0664);
+
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ db.close(0);
+
+ // Reopen no longer allowed, so we create a new db.
+ db = new Db(dbenv, 0);
+ db.set_error_stream(System.err);
+ db.set_pagesize(1024);
+ db.open(null, CONSTRUCT02_DBNAME, null, Db.DB_BTREE,
+ Db.DB_CREATE, 0664);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ rundb(db, itemcount++);
+ db.close(0);
+ }
+
+ // remove any existing environment or database
+ void removeall(boolean use_db, boolean remove_env)
+ {
+ {
+ try {
+ if (remove_env) {
+ DbEnv tmpenv = new DbEnv(0);
+ tmpenv.remove(CONSTRUCT02_DBDIR, Db.DB_FORCE);
+ }
+ else if (use_db) {
+ /**/
+ //memory leak for this:
+ Db tmpdb = new Db(null, 0);
+ tmpdb.remove(CONSTRUCT02_DBFULLPATH, null, 0);
+ /**/
+ }
+ }
+ catch (DbException dbe) {
+ System.err.println("error during remove: " + dbe);
+ }
+ catch (FileNotFoundException dbe) {
+ System.err.println("error during remove: " + dbe);
+ }
+ }
+ check_file_removed(CONSTRUCT02_DBFULLPATH, true, !use_db);
+ if (remove_env) {
+ for (int i=0; i<8; i++) {
+ String fname = "__db.00" + i;
+ check_file_removed(fname, true, !use_db);
+ }
+ }
+ }
+
+ boolean doall()
+ {
+ itemcount = 0;
+ try {
+ VERBOSEOUT(" Running test 1:\n");
+ t1();
+ VERBOSEOUT(" finished.\n");
+ removeall(true, false);
+ return true;
+ }
+ catch (DbException dbe) {
+ ERR("EXCEPTION RECEIVED: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ ERR("EXCEPTION RECEIVED: " + fnfe);
+ }
+ return false;
+ }
+
+ public static void main(String args[])
+ {
+ int iterations = 200;
+
+ for (int argcnt=0; argcnt<args.length; argcnt++) {
+ String arg = args[argcnt];
+ try {
+ iterations = Integer.parseInt(arg);
+ if (iterations < 0) {
+ ERR("Usage: construct02 [-testdigits] count");
+ }
+ }
+ catch (NumberFormatException nfe) {
+ ERR("EXCEPTION RECEIVED: " + nfe);
+ }
+ }
+
+ System.gc();
+ System.runFinalization();
+ VERBOSEOUT("gc complete");
+ long starttotal = Runtime.getRuntime().totalMemory();
+ long startfree = Runtime.getRuntime().freeMemory();
+ TestConstruct02 con = null;
+
+ try {
+ con = new TestConstruct02();
+ }
+ catch (DbException dbe) {
+ System.err.println("Exception: " + dbe);
+ System.exit(1);
+ }
+ catch (java.io.FileNotFoundException fnfe) {
+ System.err.println("Exception: " + fnfe);
+ System.exit(1);
+ }
+
+ for (int i=0; i<iterations; i++) {
+ if (iterations != 0) {
+ VERBOSEOUT("(" + i + "/" + iterations + ") ");
+ }
+ VERBOSEOUT("construct02 running:\n");
+ if (!con.doall()) {
+ ERR("SOME TEST FAILED");
+ }
+ System.gc();
+ System.runFinalization();
+ VERBOSEOUT("gc complete");
+
+ }
+ con.close();
+
+ System.out.print("ALL TESTS SUCCESSFUL\n");
+
+ long endtotal = Runtime.getRuntime().totalMemory();
+ long endfree = Runtime.getRuntime().freeMemory();
+
+ System.out.println("delta for total mem: " + magnitude(endtotal - starttotal));
+ System.out.println("delta for free mem: " + magnitude(endfree - startfree));
+
+ return;
+ }
+
+ static String magnitude(long value)
+ {
+ final long max = 10000000;
+ for (long scale = 10; scale <= max; scale *= 10) {
+ if (value < scale && value > -scale)
+ return "<" + scale;
+ }
+ return ">" + max;
+ }
+}
diff --git a/bdb/test/scr016/TestConstruct02.testout b/bdb/test/scr016/TestConstruct02.testout
new file mode 100644
index 00000000000..5d2041cd197
--- /dev/null
+++ b/bdb/test/scr016/TestConstruct02.testout
@@ -0,0 +1,3 @@
+ALL TESTS SUCCESSFUL
+delta for total mem: <10
+delta for free mem: <10000
diff --git a/bdb/test/scr016/TestDbtFlags.java b/bdb/test/scr016/TestDbtFlags.java
new file mode 100644
index 00000000000..98527e6b3e7
--- /dev/null
+++ b/bdb/test/scr016/TestDbtFlags.java
@@ -0,0 +1,241 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestDbtFlags.java,v 1.4 2002/08/16 19:35:54 dda Exp $
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class TestDbtFlags
+{
+ private static final String FileName = "access.db";
+ private int flag_value;
+ private int buf_size;
+ private int cur_input_line = 0;
+
+ /*zippy quotes for test input*/
+ static final String[] input_lines = {
+ "If we shadows have offended",
+ "Think but this, and all is mended",
+ "That you have but slumber'd here",
+ "While these visions did appear",
+ "And this weak and idle theme",
+ "No more yielding but a dream",
+ "Gentles, do not reprehend",
+ "if you pardon, we will mend",
+ "And, as I am an honest Puck, if we have unearned luck",
+ "Now to 'scape the serpent's tongue, we will make amends ere long;",
+ "Else the Puck a liar call; so, good night unto you all.",
+ "Give me your hands, if we be friends, and Robin shall restore amends."
+ };
+
+ public TestDbtFlags(int flag_value, int buf_size)
+ {
+ this.flag_value = flag_value;
+ this.buf_size = buf_size;
+ }
+
+ public static void runWithFlags(int flag_value, int size)
+ {
+ String msg = "=-=-=-= Test with DBT flags " + flag_value +
+ " bufsize " + size;
+ System.out.println(msg);
+ System.err.println(msg);
+
+ try
+ {
+ TestDbtFlags app = new TestDbtFlags(flag_value, size);
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("TestDbtFlags: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("TestDbtFlags: " + fnfe.toString());
+ System.exit(1);
+ }
+ }
+
+ public static void main(String argv[])
+ {
+ runWithFlags(Db.DB_DBT_MALLOC, -1);
+ runWithFlags(Db.DB_DBT_REALLOC, -1);
+ runWithFlags(Db.DB_DBT_USERMEM, 20);
+ runWithFlags(Db.DB_DBT_USERMEM, 50);
+ runWithFlags(Db.DB_DBT_USERMEM, 200);
+ runWithFlags(0, -1);
+
+ System.exit(0);
+ }
+
+ String get_input_line()
+ {
+ if (cur_input_line >= input_lines.length)
+ return null;
+ return input_lines[cur_input_line++];
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ Db table = new Db(null, 0);
+ table.set_error_stream(System.err);
+ table.set_errpfx("TestDbtFlags");
+ table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ for (;;) {
+ //System.err.println("input line " + cur_input_line);
+ String line = get_input_line();
+ if (line == null)
+ break;
+
+ String reversed = (new StringBuffer(line)).reverse().toString();
+
+ // See definition of StringDbt below
+ //
+ StringDbt key = new StringDbt(line, flag_value);
+ StringDbt data = new StringDbt(reversed, flag_value);
+
+ try
+ {
+ int err;
+ if ((err = table.put(null,
+ key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
+ System.out.println("Key " + line + " already exists.");
+ }
+ key.check_flags();
+ data.check_flags();
+ }
+ catch (DbException dbe)
+ {
+ System.out.println(dbe.toString());
+ }
+ }
+
+ // Acquire an iterator for the table.
+ Dbc iterator;
+ iterator = table.cursor(null, 0);
+
+ // Walk through the table, printing the key/data pairs.
+ // See class StringDbt defined below.
+ //
+ StringDbt key = new StringDbt(flag_value, buf_size);
+ StringDbt data = new StringDbt(flag_value, buf_size);
+
+ int iteration_count = 0;
+ int dbreturn = 0;
+
+ while (dbreturn == 0) {
+ //System.err.println("iteration " + iteration_count);
+ try {
+ if ((dbreturn = iterator.get(key, data, Db.DB_NEXT)) == 0) {
+ System.out.println(key.get_string() + " : " + data.get_string());
+ }
+ }
+ catch (DbMemoryException dme) {
+ /* In a real application, we'd normally increase
+ * the size of the buffer. Since we've created
+ * this error condition for testing, we'll just report it.
+ * We still need to skip over this record, and we don't
+ * want to mess with our original Dbt's, since we want
+ * to see more errors. So create some temporary
+ * mallocing Dbts to get this record.
+ */
+ System.err.println("exception, iteration " + iteration_count +
+ ": " + dme);
+ System.err.println(" key size: " + key.get_size() +
+ " ulen: " + key.get_ulen());
+ System.err.println(" data size: " + key.get_size() +
+ " ulen: " + key.get_ulen());
+
+ dme.get_dbt().set_size(buf_size);
+ StringDbt tempkey = new StringDbt(Db.DB_DBT_MALLOC, -1);
+ StringDbt tempdata = new StringDbt(Db.DB_DBT_MALLOC, -1);
+ if ((dbreturn = iterator.get(tempkey, tempdata, Db.DB_NEXT)) != 0) {
+ System.err.println("cannot get expected next record");
+ return;
+ }
+ System.out.println(tempkey.get_string() + " : " +
+ tempdata.get_string());
+ }
+ iteration_count++;
+ }
+ key.check_flags();
+ data.check_flags();
+
+ iterator.close();
+ table.close(0);
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ int saved_flags;
+
+ StringDbt(int flags, int buf_size)
+ {
+ this.saved_flags = flags;
+ set_flags(saved_flags);
+ if (buf_size != -1) {
+ set_data(new byte[buf_size]);
+ set_ulen(buf_size);
+ }
+ }
+
+ StringDbt(String value, int flags)
+ {
+ this.saved_flags = flags;
+ set_flags(saved_flags);
+ set_string(value);
+ }
+
+ void set_string(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ check_flags();
+ }
+
+ String get_string()
+ {
+ check_flags();
+ return new String(get_data(), 0, get_size());
+ }
+
+ void check_flags()
+ {
+ int actual_flags = get_flags();
+ if (actual_flags != saved_flags) {
+ System.err.println("flags botch: expected " + saved_flags +
+ ", got " + actual_flags);
+ }
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestDbtFlags.testerr b/bdb/test/scr016/TestDbtFlags.testerr
new file mode 100644
index 00000000000..7666868ebd4
--- /dev/null
+++ b/bdb/test/scr016/TestDbtFlags.testerr
@@ -0,0 +1,54 @@
+=-=-=-= Test with DBT flags 4 bufsize -1
+=-=-=-= Test with DBT flags 16 bufsize -1
+=-=-=-= Test with DBT flags 32 bufsize 20
+exception, iteration 0: Dbt not large enough for available data
+ key size: 28 ulen: 20
+ data size: 28 ulen: 20
+exception, iteration 1: Dbt not large enough for available data
+ key size: 53 ulen: 20
+ data size: 53 ulen: 20
+exception, iteration 2: Dbt not large enough for available data
+ key size: 55 ulen: 20
+ data size: 55 ulen: 20
+exception, iteration 3: Dbt not large enough for available data
+ key size: 25 ulen: 20
+ data size: 25 ulen: 20
+exception, iteration 4: Dbt not large enough for available data
+ key size: 69 ulen: 20
+ data size: 69 ulen: 20
+exception, iteration 5: Dbt not large enough for available data
+ key size: 27 ulen: 20
+ data size: 27 ulen: 20
+exception, iteration 6: Dbt not large enough for available data
+ key size: 28 ulen: 20
+ data size: 28 ulen: 20
+exception, iteration 7: Dbt not large enough for available data
+ key size: 65 ulen: 20
+ data size: 65 ulen: 20
+exception, iteration 8: Dbt not large enough for available data
+ key size: 32 ulen: 20
+ data size: 32 ulen: 20
+exception, iteration 9: Dbt not large enough for available data
+ key size: 33 ulen: 20
+ data size: 33 ulen: 20
+exception, iteration 10: Dbt not large enough for available data
+ key size: 30 ulen: 20
+ data size: 30 ulen: 20
+exception, iteration 11: Dbt not large enough for available data
+ key size: 27 ulen: 20
+ data size: 27 ulen: 20
+=-=-=-= Test with DBT flags 32 bufsize 50
+exception, iteration 1: Dbt not large enough for available data
+ key size: 53 ulen: 50
+ data size: 53 ulen: 50
+exception, iteration 2: Dbt not large enough for available data
+ key size: 55 ulen: 50
+ data size: 55 ulen: 50
+exception, iteration 4: Dbt not large enough for available data
+ key size: 69 ulen: 50
+ data size: 69 ulen: 50
+exception, iteration 7: Dbt not large enough for available data
+ key size: 65 ulen: 50
+ data size: 65 ulen: 50
+=-=-=-= Test with DBT flags 32 bufsize 200
+=-=-=-= Test with DBT flags 0 bufsize -1
diff --git a/bdb/test/scr016/TestDbtFlags.testout b/bdb/test/scr016/TestDbtFlags.testout
new file mode 100644
index 00000000000..b8deb1bcc16
--- /dev/null
+++ b/bdb/test/scr016/TestDbtFlags.testout
@@ -0,0 +1,78 @@
+=-=-=-= Test with DBT flags 4 bufsize -1
+And this weak and idle theme : emeht eldi dna kaew siht dnA
+And, as I am an honest Puck, if we have unearned luck : kcul denraenu evah ew fi ,kcuP tsenoh na ma I sa ,dnA
+Else the Puck a liar call; so, good night unto you all. : .lla uoy otnu thgin doog ,os ;llac rail a kcuP eht eslE
+Gentles, do not reprehend : dneherper ton od ,seltneG
+Give me your hands, if we be friends, and Robin shall restore amends. : .sdnema erotser llahs niboR dna ,sdneirf eb ew fi ,sdnah ruoy em eviG
+If we shadows have offended : dedneffo evah swodahs ew fI
+No more yielding but a dream : maerd a tub gnidleiy erom oN
+Now to 'scape the serpent's tongue, we will make amends ere long; : ;gnol ere sdnema ekam lliw ew ,eugnot s'tnepres eht epacs' ot woN
+That you have but slumber'd here : ereh d'rebmuls tub evah uoy tahT
+Think but this, and all is mended : dednem si lla dna ,siht tub knihT
+While these visions did appear : raeppa did snoisiv eseht elihW
+if you pardon, we will mend : dnem lliw ew ,nodrap uoy fi
+=-=-=-= Test with DBT flags 16 bufsize -1
+And this weak and idle theme : emeht eldi dna kaew siht dnA
+And, as I am an honest Puck, if we have unearned luck : kcul denraenu evah ew fi ,kcuP tsenoh na ma I sa ,dnA
+Else the Puck a liar call; so, good night unto you all. : .lla uoy otnu thgin doog ,os ;llac rail a kcuP eht eslE
+Gentles, do not reprehend : dneherper ton od ,seltneG
+Give me your hands, if we be friends, and Robin shall restore amends. : .sdnema erotser llahs niboR dna ,sdneirf eb ew fi ,sdnah ruoy em eviG
+If we shadows have offended : dedneffo evah swodahs ew fI
+No more yielding but a dream : maerd a tub gnidleiy erom oN
+Now to 'scape the serpent's tongue, we will make amends ere long; : ;gnol ere sdnema ekam lliw ew ,eugnot s'tnepres eht epacs' ot woN
+That you have but slumber'd here : ereh d'rebmuls tub evah uoy tahT
+Think but this, and all is mended : dednem si lla dna ,siht tub knihT
+While these visions did appear : raeppa did snoisiv eseht elihW
+if you pardon, we will mend : dnem lliw ew ,nodrap uoy fi
+=-=-=-= Test with DBT flags 32 bufsize 20
+And this weak and idle theme : emeht eldi dna kaew siht dnA
+And, as I am an honest Puck, if we have unearned luck : kcul denraenu evah ew fi ,kcuP tsenoh na ma I sa ,dnA
+Else the Puck a liar call; so, good night unto you all. : .lla uoy otnu thgin doog ,os ;llac rail a kcuP eht eslE
+Gentles, do not reprehend : dneherper ton od ,seltneG
+Give me your hands, if we be friends, and Robin shall restore amends. : .sdnema erotser llahs niboR dna ,sdneirf eb ew fi ,sdnah ruoy em eviG
+If we shadows have offended : dedneffo evah swodahs ew fI
+No more yielding but a dream : maerd a tub gnidleiy erom oN
+Now to 'scape the serpent's tongue, we will make amends ere long; : ;gnol ere sdnema ekam lliw ew ,eugnot s'tnepres eht epacs' ot woN
+That you have but slumber'd here : ereh d'rebmuls tub evah uoy tahT
+Think but this, and all is mended : dednem si lla dna ,siht tub knihT
+While these visions did appear : raeppa did snoisiv eseht elihW
+if you pardon, we will mend : dnem lliw ew ,nodrap uoy fi
+=-=-=-= Test with DBT flags 32 bufsize 50
+And this weak and idle theme : emeht eldi dna kaew siht dnA
+And, as I am an honest Puck, if we have unearned luck : kcul denraenu evah ew fi ,kcuP tsenoh na ma I sa ,dnA
+Else the Puck a liar call; so, good night unto you all. : .lla uoy otnu thgin doog ,os ;llac rail a kcuP eht eslE
+Gentles, do not reprehend : dneherper ton od ,seltneG
+Give me your hands, if we be friends, and Robin shall restore amends. : .sdnema erotser llahs niboR dna ,sdneirf eb ew fi ,sdnah ruoy em eviG
+If we shadows have offended : dedneffo evah swodahs ew fI
+No more yielding but a dream : maerd a tub gnidleiy erom oN
+Now to 'scape the serpent's tongue, we will make amends ere long; : ;gnol ere sdnema ekam lliw ew ,eugnot s'tnepres eht epacs' ot woN
+That you have but slumber'd here : ereh d'rebmuls tub evah uoy tahT
+Think but this, and all is mended : dednem si lla dna ,siht tub knihT
+While these visions did appear : raeppa did snoisiv eseht elihW
+if you pardon, we will mend : dnem lliw ew ,nodrap uoy fi
+=-=-=-= Test with DBT flags 32 bufsize 200
+And this weak and idle theme : emeht eldi dna kaew siht dnA
+And, as I am an honest Puck, if we have unearned luck : kcul denraenu evah ew fi ,kcuP tsenoh na ma I sa ,dnA
+Else the Puck a liar call; so, good night unto you all. : .lla uoy otnu thgin doog ,os ;llac rail a kcuP eht eslE
+Gentles, do not reprehend : dneherper ton od ,seltneG
+Give me your hands, if we be friends, and Robin shall restore amends. : .sdnema erotser llahs niboR dna ,sdneirf eb ew fi ,sdnah ruoy em eviG
+If we shadows have offended : dedneffo evah swodahs ew fI
+No more yielding but a dream : maerd a tub gnidleiy erom oN
+Now to 'scape the serpent's tongue, we will make amends ere long; : ;gnol ere sdnema ekam lliw ew ,eugnot s'tnepres eht epacs' ot woN
+That you have but slumber'd here : ereh d'rebmuls tub evah uoy tahT
+Think but this, and all is mended : dednem si lla dna ,siht tub knihT
+While these visions did appear : raeppa did snoisiv eseht elihW
+if you pardon, we will mend : dnem lliw ew ,nodrap uoy fi
+=-=-=-= Test with DBT flags 0 bufsize -1
+And this weak and idle theme : emeht eldi dna kaew siht dnA
+And, as I am an honest Puck, if we have unearned luck : kcul denraenu evah ew fi ,kcuP tsenoh na ma I sa ,dnA
+Else the Puck a liar call; so, good night unto you all. : .lla uoy otnu thgin doog ,os ;llac rail a kcuP eht eslE
+Gentles, do not reprehend : dneherper ton od ,seltneG
+Give me your hands, if we be friends, and Robin shall restore amends. : .sdnema erotser llahs niboR dna ,sdneirf eb ew fi ,sdnah ruoy em eviG
+If we shadows have offended : dedneffo evah swodahs ew fI
+No more yielding but a dream : maerd a tub gnidleiy erom oN
+Now to 'scape the serpent's tongue, we will make amends ere long; : ;gnol ere sdnema ekam lliw ew ,eugnot s'tnepres eht epacs' ot woN
+That you have but slumber'd here : ereh d'rebmuls tub evah uoy tahT
+Think but this, and all is mended : dednem si lla dna ,siht tub knihT
+While these visions did appear : raeppa did snoisiv eseht elihW
+if you pardon, we will mend : dnem lliw ew ,nodrap uoy fi
diff --git a/bdb/test/scr016/TestGetSetMethods.java b/bdb/test/scr016/TestGetSetMethods.java
new file mode 100644
index 00000000000..a1b2722d8fd
--- /dev/null
+++ b/bdb/test/scr016/TestGetSetMethods.java
@@ -0,0 +1,99 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestGetSetMethods.java,v 1.3 2002/01/11 15:54:02 bostic Exp $
+ */
+
+/*
+ * Do some regression tests for simple get/set access methods
+ * on DbEnv, DbTxn, Db. We don't currently test that they have
+ * the desired effect, only that they operate and return correctly.
+ */
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestGetSetMethods
+{
+ public void testMethods()
+ throws DbException, FileNotFoundException
+ {
+ DbEnv dbenv = new DbEnv(0);
+ DbTxn dbtxn;
+ byte[][] conflicts = new byte[10][10];
+
+ dbenv.set_timeout(0x90000000,
+ Db.DB_SET_LOCK_TIMEOUT);
+ dbenv.set_lg_bsize(0x1000);
+ dbenv.set_lg_dir(".");
+ dbenv.set_lg_max(0x10000000);
+ dbenv.set_lg_regionmax(0x100000);
+ dbenv.set_lk_conflicts(conflicts);
+ dbenv.set_lk_detect(Db.DB_LOCK_DEFAULT);
+ // exists, but is deprecated:
+ // dbenv.set_lk_max(0);
+ dbenv.set_lk_max_lockers(100);
+ dbenv.set_lk_max_locks(10);
+ dbenv.set_lk_max_objects(1000);
+ dbenv.set_mp_mmapsize(0x10000);
+ dbenv.set_tas_spins(1000);
+
+ // Need to open the environment so we
+ // can get a transaction.
+ //
+ dbenv.open(".", Db.DB_CREATE | Db.DB_INIT_TXN |
+ Db.DB_INIT_LOCK | Db.DB_INIT_LOG |
+ Db.DB_INIT_MPOOL,
+ 0644);
+
+ dbtxn = dbenv.txn_begin(null, Db.DB_TXN_NOWAIT);
+ dbtxn.set_timeout(0xA0000000, Db.DB_SET_TXN_TIMEOUT);
+ dbtxn.abort();
+
+ dbenv.close(0);
+
+ // We get a db, one for each type.
+ // That's because once we call (for instance)
+ // set_bt_maxkey, DB 'knows' that this is a
+ // Btree Db, and it cannot be used to try Hash
+ // or Recno functions.
+ //
+ Db db_bt = new Db(null, 0);
+ db_bt.set_bt_maxkey(10000);
+ db_bt.set_bt_minkey(100);
+ db_bt.set_cachesize(0, 0x100000, 0);
+ db_bt.close(0);
+
+ Db db_h = new Db(null, 0);
+ db_h.set_h_ffactor(0x10);
+ db_h.set_h_nelem(100);
+ db_h.set_lorder(0);
+ db_h.set_pagesize(0x10000);
+ db_h.close(0);
+
+ Db db_re = new Db(null, 0);
+ db_re.set_re_delim('@');
+ db_re.set_re_pad(10);
+ db_re.set_re_source("re.in");
+ db_re.close(0);
+
+ Db db_q = new Db(null, 0);
+ db_q.set_q_extentsize(200);
+ db_q.close(0);
+ }
+
+ public static void main(String[] args)
+ {
+ try {
+ TestGetSetMethods tester = new TestGetSetMethods();
+ tester.testMethods();
+ }
+ catch (Exception e) {
+ System.err.println("TestGetSetMethods: Exception: " + e);
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestKeyRange.java b/bdb/test/scr016/TestKeyRange.java
new file mode 100644
index 00000000000..8eda2de426f
--- /dev/null
+++ b/bdb/test/scr016/TestKeyRange.java
@@ -0,0 +1,203 @@
+/*NOTE: TestKeyRange is AccessExample changed to test Db.key_range.
+ * See comments with ADDED for specific areas of change.
+ */
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestKeyRange.java,v 1.4 2002/08/16 19:35:55 dda Exp $
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.StringReader;
+import java.io.Reader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class TestKeyRange
+{
+ private static final String FileName = "access.db";
+
+ public TestKeyRange()
+ {
+ }
+
+ private static void usage()
+ {
+ System.err.println("usage: TestKeyRange\n");
+ System.exit(1);
+ }
+
+ public static void main(String argv[])
+ {
+ try
+ {
+ TestKeyRange app = new TestKeyRange();
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("TestKeyRange: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("TestKeyRange: " + fnfe.toString());
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ // Prompts for a line, and keeps prompting until a non blank
+ // line is returned. Returns null on error.
+ //
+ static public String askForLine(Reader reader,
+ PrintStream out, String prompt)
+ {
+ String result = "";
+ while (result != null && result.length() == 0) {
+ out.print(prompt);
+ out.flush();
+ result = getLine(reader);
+ }
+ return result;
+ }
+
+ // Not terribly efficient, but does the job.
+ // Works for reading a line from stdin or a file.
+ // Returns null on EOF. If EOF appears in the middle
+ // of a line, returns that line, then null on next call.
+ //
+ static public String getLine(Reader reader)
+ {
+ StringBuffer b = new StringBuffer();
+ int c;
+ try {
+ while ((c = reader.read()) != -1 && c != '\n') {
+ if (c != '\r')
+ b.append((char)c);
+ }
+ }
+ catch (IOException ioe) {
+ c = -1;
+ }
+
+ if (c == -1 && b.length() == 0)
+ return null;
+ else
+ return b.toString();
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ Db table = new Db(null, 0);
+ table.set_error_stream(System.err);
+ table.set_errpfx("TestKeyRange");
+ table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ Reader reader = new StringReader("abc\nmiddle\nzend\nmoremiddle\nZED\nMAMAMIA");
+
+ int count= 0;/*ADDED*/
+ for (;;) {
+ String line = askForLine(reader, System.out, "input>");
+ if (line == null)
+ break;
+
+ String reversed = (new StringBuffer(line)).reverse().toString();
+
+ // See definition of StringDbt below
+ //
+ StringDbt key = new StringDbt(line);
+ StringDbt data = new StringDbt(reversed);
+
+ try
+ {
+ int err;
+ if ((err = table.put(null, key, data, 0)) == Db.DB_KEYEXIST) {
+ System.out.println("Key " + line + " already exists.");
+ }
+ }
+ catch (DbException dbe)
+ {
+ System.out.println(dbe.toString());
+ }
+ System.out.println("");
+
+ /*START ADDED*/
+ {
+ if (count++ > 0) {
+ DbKeyRange range = new DbKeyRange();
+ table.key_range(null, key, range, 0);
+ System.out.println("less: " + range.less);
+ System.out.println("equal: " + range.equal);
+ System.out.println("greater: " + range.greater);
+ }
+ }
+ /*END ADDED*/
+
+ }
+
+ // Acquire an iterator for the table.
+ Dbc iterator;
+ iterator = table.cursor(null, 0);
+
+ // Walk through the table, printing the key/data pairs.
+ // See class StringDbt defined below.
+ //
+ StringDbt key = new StringDbt();
+ StringDbt data = new StringDbt();
+ while (iterator.get(key, data, Db.DB_NEXT) == 0)
+ {
+ System.out.println(key.getString() + " : " + data.getString());
+ }
+ iterator.close();
+ table.close(0);
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ }
+
+ String getString()
+ {
+ return new String(get_data(), 0, get_size());
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestKeyRange.testout b/bdb/test/scr016/TestKeyRange.testout
new file mode 100644
index 00000000000..c265f3289fb
--- /dev/null
+++ b/bdb/test/scr016/TestKeyRange.testout
@@ -0,0 +1,27 @@
+input>
+input>
+less: 0.5
+equal: 0.5
+greater: 0.0
+input>
+less: 0.6666666666666666
+equal: 0.3333333333333333
+greater: 0.0
+input>
+less: 0.5
+equal: 0.25
+greater: 0.25
+input>
+less: 0.0
+equal: 0.2
+greater: 0.8
+input>
+less: 0.0
+equal: 0.16666666666666666
+greater: 0.8333333333333334
+input>MAMAMIA : AIMAMAM
+ZED : DEZ
+abc : cba
+middle : elddim
+moremiddle : elddimerom
+zend : dnez
diff --git a/bdb/test/scr016/TestLockVec.java b/bdb/test/scr016/TestLockVec.java
new file mode 100644
index 00000000000..ad48e9f2f9a
--- /dev/null
+++ b/bdb/test/scr016/TestLockVec.java
@@ -0,0 +1,249 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestLockVec.java,v 1.4 2002/08/16 19:35:55 dda Exp $
+ */
+
+/*
+ * test of DbEnv.lock_vec()
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestLockVec
+{
+ public static int locker1;
+ public static int locker2;
+
+ public static void gdb_pause()
+ {
+ try {
+ System.err.println("attach gdb and type return...");
+ System.in.read(new byte[10]);
+ }
+ catch (java.io.IOException ie) {
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ try {
+ DbEnv dbenv1 = new DbEnv(0);
+ DbEnv dbenv2 = new DbEnv(0);
+ dbenv1.open(".",
+ Db.DB_CREATE | Db.DB_INIT_LOCK | Db.DB_INIT_MPOOL, 0);
+ dbenv2.open(".",
+ Db.DB_CREATE | Db.DB_INIT_LOCK | Db.DB_INIT_MPOOL, 0);
+ locker1 = dbenv1.lock_id();
+ locker2 = dbenv1.lock_id();
+ Db db1 = new Db(dbenv1, 0);
+ db1.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0);
+ Db db2 = new Db(dbenv2, 0);
+ db2.open(null, "my.db", null, Db.DB_BTREE, 0, 0);
+
+ // populate our database, just two elements.
+ Dbt Akey = new Dbt("A".getBytes());
+ Dbt Adata = new Dbt("Adata".getBytes());
+ Dbt Bkey = new Dbt("B".getBytes());
+ Dbt Bdata = new Dbt("Bdata".getBytes());
+
+ // We don't allow Dbts to be reused within the
+ // same method call, so we need some duplicates.
+ Dbt Akeyagain = new Dbt("A".getBytes());
+ Dbt Bkeyagain = new Dbt("B".getBytes());
+
+ db1.put(null, Akey, Adata, 0);
+ db1.put(null, Bkey, Bdata, 0);
+
+ Dbt notInDatabase = new Dbt("C".getBytes());
+
+ /* make sure our check mechanisms work */
+ int expectedErrs = 0;
+
+ lock_check_free(dbenv2, Akey);
+ try {
+ lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
+ }
+ catch (DbException dbe1) {
+ expectedErrs += 1;
+ }
+ DbLock tmplock = dbenv1.lock_get(locker1, Db.DB_LOCK_NOWAIT,
+ Akey, Db.DB_LOCK_READ);
+ lock_check_held(dbenv2, Akey, Db.DB_LOCK_READ);
+ try {
+ lock_check_free(dbenv2, Akey);
+ }
+ catch (DbException dbe2) {
+ expectedErrs += 2;
+ }
+ if (expectedErrs != 1+2) {
+ System.err.println("lock check mechanism is broken");
+ System.exit(1);
+ }
+ dbenv1.lock_put(tmplock);
+
+ /* Now on with the test, a series of lock_vec requests,
+ * with checks between each call.
+ */
+
+ System.out.println("get a few");
+ /* Request: get A(W), B(R), B(R) */
+ DbLockRequest[] reqs = new DbLockRequest[3];
+
+ reqs[0] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_WRITE,
+ Akey, null);
+ reqs[1] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
+ Bkey, null);
+ reqs[2] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
+ Bkeyagain, null);
+
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 3);
+
+ /* Locks held: A(W), B(R), B(R) */
+ lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
+ lock_check_held(dbenv2, Akey, Db.DB_LOCK_WRITE);
+
+ System.out.println("put a couple");
+ /* Request: put A, B(first) */
+ reqs[0].set_op(Db.DB_LOCK_PUT);
+ reqs[1].set_op(Db.DB_LOCK_PUT);
+
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 2);
+
+ /* Locks held: B(R) */
+ lock_check_free(dbenv2, Akey);
+ lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
+
+ System.out.println("put one more, test index offset");
+ /* Request: put B(second) */
+ reqs[2].set_op(Db.DB_LOCK_PUT);
+
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 2, 1);
+
+ /* Locks held: <none> */
+ lock_check_free(dbenv2, Akey);
+ lock_check_free(dbenv2, Bkey);
+
+ System.out.println("get a few");
+ /* Request: get A(R), A(R), B(R) */
+ reqs[0] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
+ Akey, null);
+ reqs[1] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
+ Akeyagain, null);
+ reqs[2] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
+ Bkey, null);
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 3);
+
+ /* Locks held: A(R), B(R), B(R) */
+ lock_check_held(dbenv2, Akey, Db.DB_LOCK_READ);
+ lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
+
+ System.out.println("try putobj");
+ /* Request: get B(R), putobj A */
+ reqs[1] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
+ Bkey, null);
+ reqs[2] = new DbLockRequest(Db.DB_LOCK_PUT_OBJ, 0,
+ Akey, null);
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 1, 2);
+
+ /* Locks held: B(R), B(R) */
+ lock_check_free(dbenv2, Akey);
+ lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
+
+ System.out.println("get one more");
+ /* Request: get A(W) */
+ reqs[0] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_WRITE,
+ Akey, null);
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 1);
+
+ /* Locks held: A(W), B(R), B(R) */
+ lock_check_held(dbenv2, Akey, Db.DB_LOCK_WRITE);
+ lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
+
+ System.out.println("putall");
+ /* Request: putall */
+ reqs[0] = new DbLockRequest(Db.DB_LOCK_PUT_ALL, 0,
+ null, null);
+ dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 1);
+
+ lock_check_free(dbenv2, Akey);
+ lock_check_free(dbenv2, Bkey);
+ db1.close(0);
+ dbenv1.close(0);
+ db2.close(0);
+ dbenv2.close(0);
+ System.out.println("done");
+ }
+ catch (DbLockNotGrantedException nge) {
+ System.err.println("Db Exception: " + nge);
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ }
+
+ }
+
+ /* Verify that the lock is free, throw an exception if not.
+ * We do this by trying to grab a write lock (no wait).
+ */
+ static void lock_check_free(DbEnv dbenv, Dbt dbt)
+ throws DbException
+ {
+ DbLock tmplock = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
+ dbt, Db.DB_LOCK_WRITE);
+ dbenv.lock_put(tmplock);
+ }
+
+ /* Verify that the lock is held with the mode, throw an exception if not.
+ * If we have a write lock, we should not be able to get the lock
+ * for reading. If we have a read lock, we should be able to get
+ * it for reading, but not writing.
+ */
+ static void lock_check_held(DbEnv dbenv, Dbt dbt, int mode)
+ throws DbException
+ {
+ DbLock never = null;
+
+ try {
+ if (mode == Db.DB_LOCK_WRITE) {
+ never = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
+ dbt, Db.DB_LOCK_READ);
+ }
+ else if (mode == Db.DB_LOCK_READ) {
+ DbLock rlock = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
+ dbt, Db.DB_LOCK_READ);
+ dbenv.lock_put(rlock);
+ never = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
+ dbt, Db.DB_LOCK_WRITE);
+ }
+ else {
+ throw new DbException("lock_check_held bad mode");
+ }
+ }
+ catch (DbLockNotGrantedException nge) {
+ /* We expect this on our last lock_get call */
+ }
+
+ /* make sure we failed */
+ if (never != null) {
+ try {
+ dbenv.lock_put(never);
+ }
+ catch (DbException dbe2) {
+ System.err.println("Got some real troubles now");
+ System.exit(1);
+ }
+ throw new DbException("lock_check_held: lock was not held");
+ }
+ }
+
+}
diff --git a/bdb/test/scr016/TestLockVec.testout b/bdb/test/scr016/TestLockVec.testout
new file mode 100644
index 00000000000..1cf16c6ac4e
--- /dev/null
+++ b/bdb/test/scr016/TestLockVec.testout
@@ -0,0 +1,8 @@
+get a few
+put a couple
+put one more, test index offset
+get a few
+try putobj
+get one more
+putall
+done
diff --git a/bdb/test/scr016/TestLogc.java b/bdb/test/scr016/TestLogc.java
new file mode 100644
index 00000000000..ec9c373a93b
--- /dev/null
+++ b/bdb/test/scr016/TestLogc.java
@@ -0,0 +1,100 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestLogc.java,v 1.7 2002/08/16 19:35:55 dda Exp $
+ */
+
+/*
+ * A basic regression test for the Logc class.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestLogc
+{
+ public static void main(String[] args)
+ {
+ try {
+ DbEnv env = new DbEnv(0);
+ env.open(".", Db.DB_CREATE | Db.DB_INIT_LOG | Db.DB_INIT_MPOOL, 0);
+
+ // Do some database activity to get something into the log.
+ Db db1 = new Db(env, 0);
+ db1.open(null, "first.db", null, Db.DB_BTREE, Db.DB_CREATE, 0);
+ db1.put(null, new Dbt("a".getBytes()), new Dbt("b".getBytes()), 0);
+ db1.put(null, new Dbt("c".getBytes()), new Dbt("d".getBytes()), 0);
+ db1.close(0);
+
+ Db db2 = new Db(env, 0);
+ db2.open(null, "second.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+ db2.put(null, new Dbt("w".getBytes()), new Dbt("x".getBytes()), 0);
+ db2.put(null, new Dbt("y".getBytes()), new Dbt("z".getBytes()), 0);
+ db2.close(0);
+
+ // Now get a log cursor and walk through.
+ DbLogc logc = env.log_cursor(0);
+
+ int ret = 0;
+ DbLsn lsn = new DbLsn();
+ Dbt dbt = new Dbt();
+ int flags = Db.DB_FIRST;
+
+ int count = 0;
+ while ((ret = logc.get(lsn, dbt, flags)) == 0) {
+
+ // We ignore the contents of the log record,
+ // it's not portable. Even the exact count
+ // is may change when the underlying implementation
+ // changes, we'll just make sure at the end we saw
+ // 'enough'.
+ //
+ // System.out.println("logc.get: " + count);
+ // System.out.println(showDbt(dbt));
+ //
+ count++;
+ flags = Db.DB_NEXT;
+ }
+ if (ret != Db.DB_NOTFOUND) {
+ System.err.println("*** FAIL: logc.get returned: " +
+ DbEnv.strerror(ret));
+ }
+ logc.close(0);
+
+ // There has to be at *least* four log records,
+ // since we did four separate database operations.
+ //
+ if (count < 4)
+ System.out.println("*** FAIL: not enough log records");
+
+ System.out.println("TestLogc done.");
+ }
+ catch (DbException dbe) {
+ System.err.println("*** FAIL: Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("*** FAIL: FileNotFoundException: " + fnfe);
+ }
+
+ }
+
+ public static String showDbt(Dbt dbt)
+ {
+ StringBuffer sb = new StringBuffer();
+ int size = dbt.get_size();
+ byte[] data = dbt.get_data();
+ int i;
+ for (i=0; i<size && i<10; i++) {
+ sb.append(Byte.toString(data[i]));
+ sb.append(' ');
+ }
+ if (i<size)
+ sb.append("...");
+ return "size: " + size + " data: " + sb.toString();
+ }
+}
diff --git a/bdb/test/scr016/TestLogc.testout b/bdb/test/scr016/TestLogc.testout
new file mode 100644
index 00000000000..afac3af7eda
--- /dev/null
+++ b/bdb/test/scr016/TestLogc.testout
@@ -0,0 +1 @@
+TestLogc done.
diff --git a/bdb/test/scr016/TestOpenEmpty.java b/bdb/test/scr016/TestOpenEmpty.java
new file mode 100644
index 00000000000..ae92fd363d9
--- /dev/null
+++ b/bdb/test/scr016/TestOpenEmpty.java
@@ -0,0 +1,189 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestOpenEmpty.java,v 1.4 2002/08/16 19:35:55 dda Exp $
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class TestOpenEmpty
+{
+ private static final String FileName = "access.db";
+
+ public TestOpenEmpty()
+ {
+ }
+
+ private static void usage()
+ {
+ System.err.println("usage: TestOpenEmpty\n");
+ System.exit(1);
+ }
+
+ public static void main(String argv[])
+ {
+ try
+ {
+ TestOpenEmpty app = new TestOpenEmpty();
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("TestOpenEmpty: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("TestOpenEmpty: " + fnfe.toString());
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ // Prompts for a line, and keeps prompting until a non blank
+ // line is returned. Returns null on error.
+ //
+ static public String askForLine(InputStreamReader reader,
+ PrintStream out, String prompt)
+ {
+ String result = "";
+ while (result != null && result.length() == 0) {
+ out.print(prompt);
+ out.flush();
+ result = getLine(reader);
+ }
+ return result;
+ }
+
+ // Not terribly efficient, but does the job.
+ // Works for reading a line from stdin or a file.
+ // Returns null on EOF. If EOF appears in the middle
+ // of a line, returns that line, then null on next call.
+ //
+ static public String getLine(InputStreamReader reader)
+ {
+ StringBuffer b = new StringBuffer();
+ int c;
+ try {
+ while ((c = reader.read()) != -1 && c != '\n') {
+ if (c != '\r')
+ b.append((char)c);
+ }
+ }
+ catch (IOException ioe) {
+ c = -1;
+ }
+
+ if (c == -1 && b.length() == 0)
+ return null;
+ else
+ return b.toString();
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ try { (new java.io.FileOutputStream(FileName)).close(); }
+ catch (IOException ioe) { }
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ Db table = new Db(null, 0);
+ table.set_error_stream(System.err);
+ table.set_errpfx("TestOpenEmpty");
+ table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ InputStreamReader reader = new InputStreamReader(System.in);
+
+ for (;;) {
+ String line = askForLine(reader, System.out, "input> ");
+ if (line == null)
+ break;
+
+ String reversed = (new StringBuffer(line)).reverse().toString();
+
+ // See definition of StringDbt below
+ //
+ StringDbt key = new StringDbt(line);
+ StringDbt data = new StringDbt(reversed);
+
+ try
+ {
+ int err;
+ if ((err = table.put(null,
+ key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
+ System.out.println("Key " + line + " already exists.");
+ }
+ }
+ catch (DbException dbe)
+ {
+ System.out.println(dbe.toString());
+ }
+ System.out.println("");
+ }
+
+ // Acquire an iterator for the table.
+ Dbc iterator;
+ iterator = table.cursor(null, 0);
+
+ // Walk through the table, printing the key/data pairs.
+ // See class StringDbt defined below.
+ //
+ StringDbt key = new StringDbt();
+ StringDbt data = new StringDbt();
+ while (iterator.get(key, data, Db.DB_NEXT) == 0)
+ {
+ System.out.println(key.getString() + " : " + data.getString());
+ }
+ iterator.close();
+ table.close(0);
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ }
+
+ String getString()
+ {
+ return new String(get_data(), 0, get_size());
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestOpenEmpty.testerr b/bdb/test/scr016/TestOpenEmpty.testerr
new file mode 100644
index 00000000000..dd3e01c7ab7
--- /dev/null
+++ b/bdb/test/scr016/TestOpenEmpty.testerr
@@ -0,0 +1,2 @@
+TestOpenEmpty: access.db: unexpected file type or format
+TestOpenEmpty: com.sleepycat.db.DbException: Invalid argument: Invalid argument
diff --git a/bdb/test/scr016/TestReplication.java b/bdb/test/scr016/TestReplication.java
new file mode 100644
index 00000000000..87cb683d60f
--- /dev/null
+++ b/bdb/test/scr016/TestReplication.java
@@ -0,0 +1,289 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestReplication.java,v 1.3 2002/01/23 14:29:51 bostic Exp $
+ */
+
+/*
+ * Simple test of replication, merely to exercise the individual
+ * methods in the API. Rather than use TCP/IP, our transport
+ * mechanism is just an ArrayList of byte arrays.
+ * It's managed like a queue, and synchronization is via
+ * the ArrayList object itself and java's wait/notify.
+ * It's not terribly extensible, but it's fine for a small test.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Vector;
+
+public class TestReplication extends Thread
+ implements DbRepTransport
+{
+ public static final String MASTER_ENVDIR = "./master";
+ public static final String CLIENT_ENVDIR = "./client";
+
+ private Vector queue = new Vector();
+ private DbEnv master_env;
+ private DbEnv client_env;
+
+ private static void mkdir(String name)
+ throws IOException
+ {
+ (new File(name)).mkdir();
+ }
+
+
+ // The client thread runs this
+ public void run()
+ {
+ try {
+ System.err.println("c10");
+ client_env = new DbEnv(0);
+ System.err.println("c11");
+ client_env.set_rep_transport(1, this);
+ System.err.println("c12");
+ client_env.open(CLIENT_ENVDIR, Db.DB_CREATE | Db.DB_INIT_MPOOL, 0);
+ System.err.println("c13");
+ Dbt myid = new Dbt("master01".getBytes());
+ System.err.println("c14");
+ client_env.rep_start(myid, Db.DB_REP_CLIENT);
+ System.err.println("c15");
+ DbEnv.RepProcessMessage processMsg = new DbEnv.RepProcessMessage();
+ processMsg.envid = 2;
+ System.err.println("c20");
+ boolean running = true;
+
+ Dbt control = new Dbt();
+ Dbt rec = new Dbt();
+
+ while (running) {
+ int msgtype = 0;
+
+ System.err.println("c30");
+ synchronized (queue) {
+ if (queue.size() == 0) {
+ System.err.println("c40");
+ sleepShort();
+ }
+ else {
+ msgtype = ((Integer)queue.firstElement()).intValue();
+ queue.removeElementAt(0);
+ byte[] data;
+
+ System.err.println("c50 " + msgtype);
+
+ switch (msgtype) {
+ case -1:
+ running = false;
+ break;
+ case 1:
+ data = (byte[])queue.firstElement();
+ queue.removeElementAt(0);
+ control.set_data(data);
+ control.set_size(data.length);
+ break;
+ case 2:
+ control.set_data(null);
+ control.set_size(0);
+ break;
+ case 3:
+ data = (byte[])queue.firstElement();
+ queue.removeElementAt(0);
+ rec.set_data(data);
+ rec.set_size(data.length);
+ break;
+ case 4:
+ rec.set_data(null);
+ rec.set_size(0);
+ break;
+ }
+
+ }
+ }
+ System.err.println("c60");
+ if (msgtype == 3 || msgtype == 4) {
+ System.out.println("cLIENT: Got message");
+ client_env.rep_process_message(control, rec,
+ processMsg);
+ }
+ }
+ System.err.println("c70");
+ Db db = new Db(client_env, 0);
+ db.open(null, "x.db", null, Db.DB_BTREE, 0, 0);
+ Dbt data = new Dbt();
+ System.err.println("c80");
+ db.get(null, new Dbt("Hello".getBytes()), data, 0);
+ System.err.println("c90");
+ System.out.println("Hello " + new String(data.get_data(), data.get_offset(), data.get_size()));
+ System.err.println("c95");
+ client_env.close(0);
+ }
+ catch (Exception e) {
+ System.err.println("client exception: " + e);
+ }
+ }
+
+ // Implements DbTransport
+ public int send(DbEnv env, Dbt control, Dbt rec, int flags, int envid)
+ throws DbException
+ {
+ System.out.println("Send to " + envid);
+ if (envid == 1) {
+ System.err.println("Unexpected envid = " + envid);
+ return 0;
+ }
+
+ int nbytes = 0;
+
+ synchronized (queue) {
+ System.out.println("Sending message");
+ byte[] data = control.get_data();
+ if (data != null && data.length > 0) {
+ queue.addElement(new Integer(1));
+ nbytes += data.length;
+ byte[] newdata = new byte[data.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ queue.addElement(newdata);
+ }
+ else
+ {
+ queue.addElement(new Integer(2));
+ }
+
+ data = rec.get_data();
+ if (data != null && data.length > 0) {
+ queue.addElement(new Integer(3));
+ nbytes += data.length;
+ byte[] newdata = new byte[data.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ queue.addElement(newdata);
+ }
+ else
+ {
+ queue.addElement(new Integer(4));
+ }
+ System.out.println("MASTER: sent message");
+ }
+ return 0;
+ }
+
+ public void sleepShort()
+ {
+ try {
+ sleep(100);
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ }
+
+ public void send_terminator()
+ {
+ synchronized (queue) {
+ queue.addElement(new Integer(-1));
+ }
+ }
+
+ public void master()
+ {
+ try {
+ master_env = new DbEnv(0);
+ master_env.set_rep_transport(2, this);
+ master_env.open(MASTER_ENVDIR, Db.DB_CREATE | Db.DB_INIT_MPOOL, 0644);
+ System.err.println("10");
+ Dbt myid = new Dbt("client01".getBytes());
+ master_env.rep_start(myid, Db.DB_REP_MASTER);
+ System.err.println("10");
+ Db db = new Db(master_env, 0);
+ System.err.println("20");
+ db.open(null, "x.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+ System.err.println("30");
+ db.put(null, new Dbt("Hello".getBytes()),
+ new Dbt("world".getBytes()), 0);
+ System.err.println("40");
+ //DbEnv.RepElectResult electionResult = new DbEnv.RepElectResult();
+ //master_env.rep_elect(2, 2, 3, 4, electionResult);
+ db.close(0);
+ System.err.println("50");
+ master_env.close(0);
+ send_terminator();
+ }
+ catch (Exception e) {
+ System.err.println("client exception: " + e);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ // The test should only take a few milliseconds.
+ // give it 10 seconds before bailing out.
+ TimelimitThread t = new TimelimitThread(1000*10);
+ t.start();
+
+ try {
+ mkdir(CLIENT_ENVDIR);
+ mkdir(MASTER_ENVDIR);
+
+ TestReplication rep = new TestReplication();
+
+ // Run the client as a seperate thread.
+ rep.start();
+
+ // Run the master.
+ rep.master();
+
+ // Wait for the master to finish.
+ rep.join();
+ }
+ catch (Exception e)
+ {
+ System.err.println("Exception: " + e);
+ }
+ t.finished();
+ }
+
+}
+
+class TimelimitThread extends Thread
+{
+ long nmillis;
+ boolean finished = false;
+
+ TimelimitThread(long nmillis)
+ {
+ this.nmillis = nmillis;
+ }
+
+ public void finished()
+ {
+ finished = true;
+ }
+
+ public void run()
+ {
+ long targetTime = System.currentTimeMillis() + nmillis;
+ long curTime;
+
+ while (!finished &&
+ ((curTime = System.currentTimeMillis()) < targetTime)) {
+ long diff = targetTime - curTime;
+ if (diff > 100)
+ diff = 100;
+ try {
+ sleep(diff);
+ }
+ catch (InterruptedException ie) {
+ }
+ }
+ System.err.println("");
+ System.exit(1);
+ }
+}
diff --git a/bdb/test/scr016/TestRpcServer.java b/bdb/test/scr016/TestRpcServer.java
new file mode 100644
index 00000000000..ef325cef075
--- /dev/null
+++ b/bdb/test/scr016/TestRpcServer.java
@@ -0,0 +1,193 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestRpcServer.java,v 1.3 2002/01/11 15:54:03 bostic Exp $
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class TestRpcServer
+{
+ private static final String FileName = "access.db";
+
+ public TestRpcServer()
+ {
+ }
+
+ private static void usage()
+ {
+ System.err.println("usage: TestRpcServer\n");
+ System.exit(1);
+ }
+
+ public static void main(String argv[])
+ {
+ try
+ {
+ TestRpcServer app = new TestRpcServer();
+ app.run();
+ }
+ catch (DbException dbe)
+ {
+ System.err.println("TestRpcServer: " + dbe.toString());
+ System.exit(1);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println("TestRpcServer: " + fnfe.toString());
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ // Prompts for a line, and keeps prompting until a non blank
+ // line is returned. Returns null on error.
+ //
+ static public String askForLine(Reader reader,
+ PrintStream out, String prompt)
+ {
+ String result = "";
+ while (result != null && result.length() == 0) {
+ out.print(prompt);
+ out.flush();
+ result = getLine(reader);
+ }
+ return result;
+ }
+
+ // Not terribly efficient, but does the job.
+ // Works for reading a line from stdin or a file.
+ // Returns null on EOF. If EOF appears in the middle
+ // of a line, returns that line, then null on next call.
+ //
+ static public String getLine(Reader reader)
+ {
+ StringBuffer b = new StringBuffer();
+ int c;
+ try {
+ while ((c = reader.read()) != -1 && c != '\n') {
+ if (c != '\r')
+ b.append((char)c);
+ }
+ }
+ catch (IOException ioe) {
+ c = -1;
+ }
+
+ if (c == -1 && b.length() == 0)
+ return null;
+ else
+ return b.toString();
+ }
+
+ public void run()
+ throws DbException, FileNotFoundException
+ {
+ // Remove the previous database.
+ new File(FileName).delete();
+
+ DbEnv dbenv = new DbEnv(Db.DB_CLIENT);
+ dbenv.set_rpc_server(null, "localhost", 0, 0, 0);
+ dbenv.open(".", Db.DB_CREATE, 0644);
+ System.out.println("server connection set");
+
+ // Create the database object.
+ // There is no environment for this simple example.
+ Db table = new Db(dbenv, 0);
+ table.set_error_stream(System.err);
+ table.set_errpfx("TestRpcServer");
+ table.open(FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ //
+ // Insert records into the database, where the key is the user
+ // input and the data is the user input in reverse order.
+ //
+ Reader reader =
+ new StringReader("abc\nStuff\nmore Stuff\nlast line\n");
+
+ for (;;) {
+ String line = askForLine(reader, System.out, "input> ");
+ if (line == null)
+ break;
+
+ String reversed = (new StringBuffer(line)).reverse().toString();
+
+ // See definition of StringDbt below
+ //
+ StringDbt key = new StringDbt(line);
+ StringDbt data = new StringDbt(reversed);
+
+ try
+ {
+ int err;
+ if ((err = table.put(null,
+ key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
+ System.out.println("Key " + line + " already exists.");
+ }
+ }
+ catch (DbException dbe)
+ {
+ System.out.println(dbe.toString());
+ }
+ System.out.println("");
+ }
+
+ // Acquire an iterator for the table.
+ Dbc iterator;
+ iterator = table.cursor(null, 0);
+
+ // Walk through the table, printing the key/data pairs.
+ // See class StringDbt defined below.
+ //
+ StringDbt key = new StringDbt();
+ StringDbt data = new StringDbt();
+ while (iterator.get(key, data, Db.DB_NEXT) == 0)
+ {
+ System.out.println(key.getString() + " : " + data.getString());
+ }
+ iterator.close();
+ table.close(0);
+ }
+
+ // Here's an example of how you can extend a Dbt in a straightforward
+ // way to allow easy storage/retrieval of strings, or whatever
+ // kind of data you wish. We've declared it as a static inner
+ // class, but it need not be.
+ //
+ static /*inner*/
+ class StringDbt extends Dbt
+ {
+ StringDbt()
+ {
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ StringDbt(String value)
+ {
+ setString(value);
+ set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+ }
+
+ void setString(String value)
+ {
+ set_data(value.getBytes());
+ set_size(value.length());
+ }
+
+ String getString()
+ {
+ return new String(get_data(), 0, get_size());
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestSameDbt.java b/bdb/test/scr016/TestSameDbt.java
new file mode 100644
index 00000000000..9866ed49307
--- /dev/null
+++ b/bdb/test/scr016/TestSameDbt.java
@@ -0,0 +1,56 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestSameDbt.java,v 1.4 2002/01/23 14:29:51 bostic Exp $
+ */
+
+/*
+ * Simple test for get/put of specific values.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestSameDbt
+{
+ public static void main(String[] args)
+ {
+ try {
+ Db db = new Db(null, 0);
+ db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ // try reusing the dbt
+ Dbt keydatadbt = new Dbt("stuff".getBytes());
+ int gotexcept = 0;
+
+ try {
+ db.put(null, keydatadbt, keydatadbt, 0);
+ }
+ catch (DbException dbe) {
+ System.out.println("got expected Db Exception: " + dbe);
+ gotexcept++;
+ }
+
+ if (gotexcept != 1) {
+ System.err.println("Missed exception");
+ System.out.println("** FAIL **");
+ }
+ else {
+ System.out.println("Test succeeded.");
+ }
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ }
+
+ }
+
+}
diff --git a/bdb/test/scr016/TestSameDbt.testout b/bdb/test/scr016/TestSameDbt.testout
new file mode 100644
index 00000000000..be4bbbe59e9
--- /dev/null
+++ b/bdb/test/scr016/TestSameDbt.testout
@@ -0,0 +1,2 @@
+got expected Db Exception: com.sleepycat.db.DbException: Dbt is already in use
+Test succeeded.
diff --git a/bdb/test/scr016/TestSimpleAccess.java b/bdb/test/scr016/TestSimpleAccess.java
new file mode 100644
index 00000000000..ba7390cada1
--- /dev/null
+++ b/bdb/test/scr016/TestSimpleAccess.java
@@ -0,0 +1,37 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestSimpleAccess.java,v 1.5 2002/08/16 19:35:55 dda Exp $
+ */
+
+/*
+ * Simple test for get/put of specific values.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestSimpleAccess
+{
+ public static void main(String[] args)
+ {
+ try {
+ Db db = new Db(null, 0);
+ db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ TestUtil.populate(db);
+ System.out.println("finished test");
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestSimpleAccess.testout b/bdb/test/scr016/TestSimpleAccess.testout
new file mode 100644
index 00000000000..dc88d4788e4
--- /dev/null
+++ b/bdb/test/scr016/TestSimpleAccess.testout
@@ -0,0 +1,3 @@
+got data: data
+get using bad key: DB_NOTFOUND: No matching key/data pair found
+finished test
diff --git a/bdb/test/scr016/TestStat.java b/bdb/test/scr016/TestStat.java
new file mode 100644
index 00000000000..55ba9823115
--- /dev/null
+++ b/bdb/test/scr016/TestStat.java
@@ -0,0 +1,57 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestStat.java,v 1.1 2002/08/16 19:35:56 dda Exp $
+ */
+
+/*
+ * Simple test for get/put of specific values.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestStat
+{
+ public static void main(String[] args)
+ {
+ int envflags =
+ Db.DB_INIT_MPOOL | Db.DB_INIT_LOCK |
+ Db.DB_INIT_LOG | Db.DB_INIT_TXN | Db.DB_CREATE;
+ try {
+ DbEnv dbenv = new DbEnv(0);
+ dbenv.open(".", envflags, 0);
+ Db db = new Db(dbenv, 0);
+ db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0);
+
+ TestUtil.populate(db);
+ System.out.println("BtreeStat:");
+ DbBtreeStat stat = (DbBtreeStat)db.stat(0);
+ System.out.println(" bt_magic: " + stat.bt_magic);
+
+ System.out.println("LogStat:");
+ DbLogStat logstat = dbenv.log_stat(0);
+ System.out.println(" st_magic: " + logstat.st_magic);
+ System.out.println(" st_cur_file: " + logstat.st_cur_file);
+
+ System.out.println("RepStat:");
+ DbRepStat repstat = dbenv.rep_stat(0);
+ System.out.println(" st_status: " + repstat.st_status);
+ System.out.println(" st_log_duplication: " +
+ repstat.st_log_duplicated);
+
+ System.out.println("finished test");
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestStat.testout b/bdb/test/scr016/TestStat.testout
new file mode 100644
index 00000000000..caf9db1fb13
--- /dev/null
+++ b/bdb/test/scr016/TestStat.testout
@@ -0,0 +1,11 @@
+got data: data
+get using bad key: DB_NOTFOUND: No matching key/data pair found
+BtreeStat:
+ bt_magic: 340322
+LogStat:
+ st_magic: 264584
+ st_cur_file: 1
+RepStat:
+ st_status: 0
+ st_log_duplication: 0
+finished test
diff --git a/bdb/test/scr016/TestTruncate.java b/bdb/test/scr016/TestTruncate.java
new file mode 100644
index 00000000000..71377236246
--- /dev/null
+++ b/bdb/test/scr016/TestTruncate.java
@@ -0,0 +1,87 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestTruncate.java,v 1.4 2002/01/23 14:29:52 bostic Exp $
+ */
+
+/*
+ * Simple test for get/put of specific values.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestTruncate
+{
+ public static void main(String[] args)
+ {
+ try {
+ Db db = new Db(null, 0);
+ db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+
+ // populate our massive database.
+ Dbt keydbt = new Dbt("key".getBytes());
+ Dbt datadbt = new Dbt("data".getBytes());
+ db.put(null, keydbt, datadbt, 0);
+
+ // Now, retrieve. We could use keydbt over again,
+ // but that wouldn't be typical in an application.
+ Dbt goodkeydbt = new Dbt("key".getBytes());
+ Dbt badkeydbt = new Dbt("badkey".getBytes());
+ Dbt resultdbt = new Dbt();
+ resultdbt.set_flags(Db.DB_DBT_MALLOC);
+
+ int ret;
+
+ if ((ret = db.get(null, goodkeydbt, resultdbt, 0)) != 0) {
+ System.out.println("get: " + DbEnv.strerror(ret));
+ }
+ else {
+ String result =
+ new String(resultdbt.get_data(), 0, resultdbt.get_size());
+ System.out.println("got data: " + result);
+ }
+
+ if ((ret = db.get(null, badkeydbt, resultdbt, 0)) != 0) {
+ // We expect this...
+ System.out.println("get using bad key: " + DbEnv.strerror(ret));
+ }
+ else {
+ String result =
+ new String(resultdbt.get_data(), 0, resultdbt.get_size());
+ System.out.println("*** got data using bad key!!: " + result);
+ }
+
+ // Now, truncate and make sure that it's really gone.
+ System.out.println("truncating data...");
+ int nrecords = db.truncate(null, 0);
+ System.out.println("truncate returns " + nrecords);
+ if ((ret = db.get(null, goodkeydbt, resultdbt, 0)) != 0) {
+ // We expect this...
+ System.out.println("after trunctate get: " +
+ DbEnv.strerror(ret));
+ }
+ else {
+ String result =
+ new String(resultdbt.get_data(), 0, resultdbt.get_size());
+ System.out.println("got data: " + result);
+ }
+
+ db.close(0);
+ System.out.println("finished test");
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ }
+
+ }
+
+}
diff --git a/bdb/test/scr016/TestTruncate.testout b/bdb/test/scr016/TestTruncate.testout
new file mode 100644
index 00000000000..23f291df754
--- /dev/null
+++ b/bdb/test/scr016/TestTruncate.testout
@@ -0,0 +1,6 @@
+got data: data
+get using bad key: DB_NOTFOUND: No matching key/data pair found
+truncating data...
+truncate returns 1
+after trunctate get: DB_NOTFOUND: No matching key/data pair found
+finished test
diff --git a/bdb/test/scr016/TestUtil.java b/bdb/test/scr016/TestUtil.java
new file mode 100644
index 00000000000..1bddfb0b014
--- /dev/null
+++ b/bdb/test/scr016/TestUtil.java
@@ -0,0 +1,57 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2002
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestUtil.java,v 1.1 2002/08/16 19:35:56 dda Exp $
+ */
+
+/*
+ * Utilities used by many tests.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import java.io.FileNotFoundException;
+
+public class TestUtil
+{
+ public static void populate(Db db)
+ throws DbException
+ {
+ // populate our massive database.
+ Dbt keydbt = new Dbt("key".getBytes());
+ Dbt datadbt = new Dbt("data".getBytes());
+ db.put(null, keydbt, datadbt, 0);
+
+ // Now, retrieve. We could use keydbt over again,
+ // but that wouldn't be typical in an application.
+ Dbt goodkeydbt = new Dbt("key".getBytes());
+ Dbt badkeydbt = new Dbt("badkey".getBytes());
+ Dbt resultdbt = new Dbt();
+ resultdbt.set_flags(Db.DB_DBT_MALLOC);
+
+ int ret;
+
+ if ((ret = db.get(null, goodkeydbt, resultdbt, 0)) != 0) {
+ System.out.println("get: " + DbEnv.strerror(ret));
+ }
+ else {
+ String result =
+ new String(resultdbt.get_data(), 0, resultdbt.get_size());
+ System.out.println("got data: " + result);
+ }
+
+ if ((ret = db.get(null, badkeydbt, resultdbt, 0)) != 0) {
+ // We expect this...
+ System.out.println("get using bad key: " + DbEnv.strerror(ret));
+ }
+ else {
+ String result =
+ new String(resultdbt.get_data(), 0, resultdbt.get_size());
+ System.out.println("*** got data using bad key!!: " + result);
+ }
+ }
+}
diff --git a/bdb/test/scr016/TestXAServlet.java b/bdb/test/scr016/TestXAServlet.java
new file mode 100644
index 00000000000..8b9fe57e261
--- /dev/null
+++ b/bdb/test/scr016/TestXAServlet.java
@@ -0,0 +1,313 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997, 1998, 1999, 2000
+ * Sleepycat Software. All rights reserved.
+ *
+ * $Id: TestXAServlet.java,v 1.1 2002/04/24 03:26:33 dda Exp $
+ */
+
+/*
+ * Simple test of XA, using WebLogic.
+ */
+
+package com.sleepycat.test;
+
+import com.sleepycat.db.*;
+import com.sleepycat.db.xa.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import javax.transaction.*;
+import javax.transaction.xa.*;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import weblogic.transaction.TxHelper;
+import weblogic.transaction.TransactionManager;
+
+public class TestXAServlet extends HttpServlet
+{
+ public static final String ENV_HOME = "TESTXADIR";
+ public static final String DEFAULT_URL = "t3://localhost:7001";
+ public static String filesep = System.getProperty("file.separator");
+
+ private static TransactionManager tm;
+ private static DbXAResource xaresource;
+ private static boolean initialized = false;
+
+ /**
+ * Utility to remove files recursively.
+ */
+ public static void removeRecursive(File f)
+ {
+ if (f.isDirectory()) {
+ String[] sub = f.list();
+ for (int i=0; i<sub.length; i++)
+ removeRecursive(new File(f.getName() + filesep + sub[i]));
+ }
+ f.delete();
+ }
+
+ /**
+ * Typically done only once, unless shutdown is invoked. This
+ * sets up directories, and removes any work files from previous
+ * runs. Also establishes a transaction manager that we'll use
+ * for various transactions. Each call opens/creates a new DB
+ * environment in our work directory.
+ */
+ public static synchronized void startup()
+ {
+ if (initialized)
+ return;
+
+ try {
+ File dir = new File(ENV_HOME);
+ removeRecursive(dir);
+ dir.mkdirs();
+
+ System.out.println("Getting context");
+ InitialContext ic = getInitialContext(DEFAULT_URL);
+ System.out.println("Creating XAResource");
+ xaresource = new DbXAResource(ENV_HOME, 77, 0);
+ System.out.println("Registering with transaction manager");
+ tm = TxHelper.getTransactionManager();
+ tm.registerStaticResource("DbXA", xaresource);
+ initialized = true;
+ }
+ catch (Exception e) {
+ System.err.println("Exception: " + e);
+ e.printStackTrace();
+ }
+ initialized = true;
+ }
+
+ /**
+ * Closes the XA resource manager.
+ */
+ public static synchronized void shutdown(PrintWriter out)
+ throws XAException
+ {
+ if (!initialized)
+ return;
+
+ out.println("Closing the resource.");
+ xaresource.close(0);
+ out.println("Shutdown complete.");
+ initialized = false;
+ }
+
+
+ /**
+ * Should be called once per chunk of major activity.
+ */
+ public void initialize()
+ {
+ startup();
+ }
+
+ private static int count = 1;
+ private static boolean debugInited = false;
+ private Xid bogusXid;
+
+ public static synchronized int incrCount()
+ {
+ return count++;
+ }
+
+ public void debugSetup(PrintWriter out)
+ throws ServletException, IOException
+ {
+ try {
+ Db.load_db();
+ }
+ catch (Exception e) {
+ out.println("got exception during load: " + e);
+ System.out.println("got exception during load: " + e);
+ }
+ out.println("The servlet has been restarted, and Berkeley DB is loaded");
+ out.println("<p>If you're debugging, you should now start the debugger and set breakpoints.");
+ }
+
+ public void doXATransaction(PrintWriter out, String key, String value,
+ String operation)
+ throws ServletException, IOException
+ {
+ try {
+ int counter = incrCount();
+ if (key == null || key.equals(""))
+ key = "key" + counter;
+ if (value == null || value.equals(""))
+ value = "value" + counter;
+
+ out.println("Adding (\"" + key + "\", \"" + value + "\")");
+
+ System.out.println("XA transaction begin");
+ tm.begin();
+ System.out.println("getting XA transaction");
+ DbXAResource.DbAttach attach = DbXAResource.xa_attach(null, null);
+ DbTxn txn = attach.get_txn();
+ DbEnv env = attach.get_env();
+ Db db = new Db(env, 0);
+ db.open(txn, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+ System.out.println("DB put " + key);
+ db.put(txn,
+ new Dbt(key.getBytes()),
+ new Dbt(value.getBytes()),
+ 0);
+
+ if (operation.equals("rollback")) {
+ out.println("<p>ROLLBACK");
+ System.out.println("XA transaction rollback");
+ tm.rollback();
+ System.out.println("XA rollback returned");
+
+ // The old db is no good after the rollback
+ // since the open was part of the transaction.
+ // Get another db for the cursor dump
+ //
+ db = new Db(env, 0);
+ db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644);
+ }
+ else {
+ out.println("<p>COMMITTED");
+ System.out.println("XA transaction commit");
+ tm.commit();
+ }
+
+ // Show the current state of the database.
+ Dbc dbc = db.cursor(null, 0);
+ Dbt gotkey = new Dbt();
+ Dbt gotdata = new Dbt();
+
+ out.println("<p>Current database values:");
+ while (dbc.get(gotkey, gotdata, Db.DB_NEXT) == 0) {
+ out.println("<br> " + getDbtString(gotkey) + " : "
+ + getDbtString(gotdata));
+ }
+ dbc.close();
+ db.close(0);
+ }
+ catch (DbException dbe) {
+ System.err.println("Db Exception: " + dbe);
+ out.println(" *** Exception received: " + dbe);
+ dbe.printStackTrace();
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("FileNotFoundException: " + fnfe);
+ out.println(" *** Exception received: " + fnfe);
+ fnfe.printStackTrace();
+ }
+ // Includes SystemException, NotSupportedException, RollbackException
+ catch (Exception e) {
+ System.err.println("Exception: " + e);
+ out.println(" *** Exception received: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ private static Xid getBogusXid()
+ throws XAException
+ {
+ return new DbXid(1, "BOGUS_gtrid".getBytes(),
+ "BOGUS_bqual".getBytes());
+ }
+
+ private static String getDbtString(Dbt dbt)
+ {
+ return new String(dbt.get_data(), 0, dbt.get_size());
+ }
+
+ /**
+ * doGet is called as a result of invoking the servlet.
+ */
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException
+ {
+ try {
+ resp.setContentType("text/html");
+ PrintWriter out = resp.getWriter();
+
+ String key = req.getParameter("key");
+ String value = req.getParameter("value");
+ String operation = req.getParameter("operation");
+
+ out.println("<HTML>");
+ out.println("<HEAD>");
+ out.println("<TITLE>Berkeley DB with XA</TITLE>");
+ out.println("</HEAD><BODY>");
+ out.println("<a href=\"TestXAServlet" +
+ "\">Database put and commit</a><br>");
+ out.println("<a href=\"TestXAServlet?operation=rollback" +
+ "\">Database put and rollback</a><br>");
+ out.println("<a href=\"TestXAServlet?operation=close" +
+ "\">Close the XA resource manager</a><br>");
+ out.println("<a href=\"TestXAServlet?operation=forget" +
+ "\">Forget an operation (bypasses TM)</a><br>");
+ out.println("<a href=\"TestXAServlet?operation=prepare" +
+ "\">Prepare an operation (bypasses TM)</a><br>");
+ out.println("<br>");
+
+ if (!debugInited) {
+ // Don't initialize XA yet, give the user
+ // a chance to attach a debugger if necessary.
+ debugSetup(out);
+ debugInited = true;
+ }
+ else {
+ initialize();
+ if (operation == null)
+ operation = "commit";
+
+ if (operation.equals("close")) {
+ shutdown(out);
+ }
+ else if (operation.equals("forget")) {
+ // A bogus test, we just make sure the API is callable.
+ out.println("<p>FORGET");
+ System.out.println("XA forget bogus XID (bypass TM)");
+ xaresource.forget(getBogusXid());
+ }
+ else if (operation.equals("prepare")) {
+ // A bogus test, we just make sure the API is callable.
+ out.println("<p>PREPARE");
+ System.out.println("XA prepare bogus XID (bypass TM)");
+ xaresource.prepare(getBogusXid());
+ }
+ else {
+ // commit, rollback, prepare, forget
+ doXATransaction(out, key, value, operation);
+ }
+ }
+ out.println("</BODY></HTML>");
+
+ System.out.println("Finished.");
+ }
+ // Includes SystemException, NotSupportedException, RollbackException
+ catch (Exception e) {
+ System.err.println("Exception: " + e);
+ e.printStackTrace();
+ }
+
+ }
+
+
+ /**
+ * From weblogic's sample code:
+ * samples/examples/jta/jmsjdbc/Client.java
+ */
+ private static InitialContext getInitialContext(String url)
+ throws NamingException
+ {
+ Hashtable env = new Hashtable();
+ env.put(Context.INITIAL_CONTEXT_FACTORY,
+ "weblogic.jndi.WLInitialContextFactory");
+ env.put(Context.PROVIDER_URL, url);
+ return new InitialContext(env);
+ }
+
+}
diff --git a/bdb/test/scr016/chk.javatests b/bdb/test/scr016/chk.javatests
new file mode 100644
index 00000000000..34d7dfe78d7
--- /dev/null
+++ b/bdb/test/scr016/chk.javatests
@@ -0,0 +1,79 @@
+#!/bin/sh -
+#
+# $Id: chk.javatests,v 1.5 2002/08/16 19:35:56 dda Exp $
+#
+# Check to make sure that regression tests for Java run.
+
+TEST_JAVA_SRCDIR=../test/scr016 # must be a relative directory
+JAVA=${JAVA:-java}
+JAVAC=${JAVAC:-javac}
+
+# CLASSPATH is used by javac and java.
+# We use CLASSPATH rather than the -classpath command line option
+# because the latter behaves differently from JDK1.1 and JDK1.2
+export CLASSPATH="./classes:../db.jar"
+export LD_LIBRARY_PATH="../.libs"
+
+
+# All paths must be relative to a subdirectory of the build directory
+LIBS="-L.. -ldb -ldb_cxx"
+CXXFLAGS="-I.. -I../../dbinc"
+
+# Test must be run from a local build directory, not from a test
+# directory.
+cd ..
+[ -f db_config.h ] || {
+ echo 'FAIL: chk.javatests must be run from a local build directory.'
+ exit 1
+}
+[ -d ../docs_src ] || {
+ echo 'FAIL: chk.javatests must be run from a local build directory.'
+ exit 1
+}
+version=`sed -e 's/.* \([0-9]*\.[0-9]*\)\..*/\1/' -e q ../README `
+[ -f libdb_java-$version.la ] || make libdb_java-$version.la || {
+ echo "FAIL: unable to build libdb_java-$version.la"
+ exit 1
+}
+[ -f db.jar ] || make db.jar || {
+ echo 'FAIL: unable to build db.jar'
+ exit 1
+}
+testnames=`cd $TEST_JAVA_SRCDIR; ls *.java | sed -e 's/\.java$//'`
+
+for testname in $testnames; do
+ if grep -x $testname $TEST_JAVA_SRCDIR/ignore > /dev/null; then
+ echo " **** java test $testname ignored"
+ continue
+ fi
+
+ echo " ==== java test $testname"
+ rm -rf TESTJAVA; mkdir -p TESTJAVA/classes
+ cd ./TESTJAVA
+ testprefix=../$TEST_JAVA_SRCDIR/$testname
+ ${JAVAC} -d ./classes $testprefix.java ../$TEST_JAVA_SRCDIR/TestUtil.java > ../$testname.compileout 2>&1 || {
+pwd
+ echo "FAIL: compilation of $testname failed, see ../$testname.compileout"
+ exit 1
+ }
+ rm -f ../$testname.compileout
+ infile=$testprefix.testin
+ [ -f $infile ] || infile=/dev/null
+ goodoutfile=$testprefix.testout
+ [ -f $goodoutfile ] || goodoutfile=/dev/null
+ gooderrfile=$testprefix.testerr
+ [ -f $gooderrfile ] || gooderrfile=/dev/null
+ ${JAVA} com.sleepycat.test.$testname <$infile >../$testname.out 2>../$testname.err
+ cmp ../$testname.out $goodoutfile > /dev/null || {
+ echo "FAIL: $testname output differs: see ../$testname.out, $goodoutfile"
+ exit 1
+ }
+ cmp ../$testname.err $gooderrfile > /dev/null || {
+ echo "FAIL: $testname error differs: see ../$testname.err, $gooderrfile"
+ exit 1
+ }
+ cd ..
+ rm -f $testname.err $testname.out
+done
+rm -rf TESTJAVA
+exit 0
diff --git a/bdb/test/scr016/ignore b/bdb/test/scr016/ignore
new file mode 100644
index 00000000000..1dfaf6adea4
--- /dev/null
+++ b/bdb/test/scr016/ignore
@@ -0,0 +1,22 @@
+#
+# $Id: ignore,v 1.4 2002/08/16 19:35:56 dda Exp $
+#
+# A list of tests to ignore
+
+# TestRpcServer is not debugged
+TestRpcServer
+
+# TestReplication is not debugged
+TestReplication
+
+# These are currently not working
+TestAppendRecno
+TestAssociate
+TestLogc
+TestConstruct02
+
+# TestUtil is used by the other tests, it does not stand on its own
+TestUtil
+
+# XA needs a special installation, it is not part of testall
+TestXAServlet
diff --git a/bdb/test/scr016/testall b/bdb/test/scr016/testall
new file mode 100644
index 00000000000..a4e1b5a8c70
--- /dev/null
+++ b/bdb/test/scr016/testall
@@ -0,0 +1,32 @@
+#!/bin/sh -
+# $Id: testall,v 1.4 2001/09/13 14:49:37 dda Exp $
+#
+# Run all the Java regression tests
+
+ecode=0
+prefixarg=""
+stdinarg=""
+while :
+do
+ case "$1" in
+ --prefix=* )
+ prefixarg="$1"; shift;;
+ --stdin )
+ stdinarg="$1"; shift;;
+ * )
+ break
+ esac
+done
+files="`find . -name \*.java -print`"
+for file in $files; do
+ name=`echo $file | sed -e 's:^\./::' -e 's/\.java$//'`
+ if grep $name ignore > /dev/null; then
+ echo " **** java test $name ignored"
+ else
+ echo " ==== java test $name"
+ if ! sh ./testone $prefixarg $stdinarg $name; then
+ ecode=1
+ fi
+ fi
+done
+exit $ecode
diff --git a/bdb/test/scr016/testone b/bdb/test/scr016/testone
new file mode 100644
index 00000000000..5f5d2e0017d
--- /dev/null
+++ b/bdb/test/scr016/testone
@@ -0,0 +1,122 @@
+#!/bin/sh -
+# $Id: testone,v 1.5 2002/08/16 19:35:56 dda Exp $
+#
+# Run just one Java regression test, the single argument
+# is the classname within this package.
+
+error()
+{
+ echo '' >&2
+ echo "Java regression error: $@" >&2
+ echo '' >&2
+ ecode=1
+}
+
+# compares the result against the good version,
+# reports differences, and removes the result file
+# if there are no differences.
+#
+compare_result()
+{
+ good="$1"
+ latest="$2"
+ if [ ! -e "$good" ]; then
+ echo "Note: $good does not exist"
+ return
+ fi
+ tmpout=/tmp/blddb$$.tmp
+ diff "$good" "$latest" > $tmpout
+ if [ -s $tmpout ]; then
+ nbad=`grep '^[0-9]' $tmpout | wc -l`
+ error "$good and $latest differ in $nbad places."
+ else
+ rm $latest
+ fi
+ rm -f $tmpout
+}
+
+ecode=0
+stdinflag=n
+JAVA=${JAVA:-java}
+JAVAC=${JAVAC:-javac}
+
+# classdir is relative to TESTDIR subdirectory
+classdir=./classes
+
+# CLASSPATH is used by javac and java.
+# We use CLASSPATH rather than the -classpath command line option
+# because the latter behaves differently from JDK1.1 and JDK1.2
+export CLASSPATH="$classdir:$CLASSPATH"
+
+# determine the prefix of the install tree
+prefix=""
+while :
+do
+ case "$1" in
+ --prefix=* )
+ prefix="`echo $1 | sed -e 's/--prefix=//'`"; shift
+ export LD_LIBRARY_PATH="$prefix/lib:$LD_LIBRARY_PATH"
+ export CLASSPATH="$prefix/lib/db.jar:$CLASSPATH"
+ ;;
+ --stdin )
+ stdinflag=y; shift
+ ;;
+ * )
+ break
+ ;;
+ esac
+done
+
+if [ "$#" = 0 ]; then
+ echo 'Usage: testone [ --prefix=<dir> | --stdin ] TestName'
+ exit 1
+fi
+name="$1"
+
+# class must be public
+if ! grep "public.*class.*$name" $name.java > /dev/null; then
+ error "public class $name is not declared in file $name.java"
+ exit 1
+fi
+
+# compile
+rm -rf TESTDIR; mkdir TESTDIR
+cd ./TESTDIR
+mkdir -p $classdir
+${JAVAC} -d $classdir ../$name.java ../TestUtil.java > ../$name.compileout 2>&1
+if [ $? != 0 -o -s ../$name.compileout ]; then
+ error "compilation of $name failed, see $name.compileout"
+ exit 1
+fi
+rm -f ../$name.compileout
+
+# find input and error file
+infile=../$name.testin
+if [ ! -f $infile ]; then
+ infile=/dev/null
+fi
+
+# run and diff results
+rm -rf TESTDIR
+if [ "$stdinflag" = y ]
+then
+ ${JAVA} com.sleepycat.test.$name $TEST_ARGS >../$name.out 2>../$name.err
+else
+ ${JAVA} com.sleepycat.test.$name $TEST_ARGS <$infile >../$name.out 2>../$name.err
+fi
+cd ..
+
+testerr=$name.testerr
+if [ ! -f $testerr ]; then
+ testerr=/dev/null
+fi
+
+testout=$name.testout
+if [ ! -f $testout ]; then
+ testout=/dev/null
+fi
+
+compare_result $testout $name.out
+compare_result $testerr $name.err
+rm -rf TESTDIR
+exit $ecode
diff --git a/bdb/test/scr017/O.BH b/bdb/test/scr017/O.BH
new file mode 100644
index 00000000000..cd499d38779
--- /dev/null
+++ b/bdb/test/scr017/O.BH
@@ -0,0 +1,196 @@
+abc_10_efg
+abc_10_efg
+abc_11_efg
+abc_11_efg
+abc_12_efg
+abc_12_efg
+abc_13_efg
+abc_13_efg
+abc_14_efg
+abc_14_efg
+abc_15_efg
+abc_15_efg
+abc_16_efg
+abc_16_efg
+abc_17_efg
+abc_17_efg
+abc_18_efg
+abc_18_efg
+abc_19_efg
+abc_19_efg
+abc_1_efg
+abc_1_efg
+abc_20_efg
+abc_20_efg
+abc_21_efg
+abc_21_efg
+abc_22_efg
+abc_22_efg
+abc_23_efg
+abc_23_efg
+abc_24_efg
+abc_24_efg
+abc_25_efg
+abc_25_efg
+abc_26_efg
+abc_26_efg
+abc_27_efg
+abc_27_efg
+abc_28_efg
+abc_28_efg
+abc_29_efg
+abc_29_efg
+abc_2_efg
+abc_2_efg
+abc_30_efg
+abc_30_efg
+abc_31_efg
+abc_31_efg
+abc_32_efg
+abc_32_efg
+abc_33_efg
+abc_33_efg
+abc_34_efg
+abc_34_efg
+abc_36_efg
+abc_36_efg
+abc_37_efg
+abc_37_efg
+abc_38_efg
+abc_38_efg
+abc_39_efg
+abc_39_efg
+abc_3_efg
+abc_3_efg
+abc_40_efg
+abc_40_efg
+abc_41_efg
+abc_41_efg
+abc_42_efg
+abc_42_efg
+abc_43_efg
+abc_43_efg
+abc_44_efg
+abc_44_efg
+abc_45_efg
+abc_45_efg
+abc_46_efg
+abc_46_efg
+abc_47_efg
+abc_47_efg
+abc_48_efg
+abc_48_efg
+abc_49_efg
+abc_49_efg
+abc_4_efg
+abc_4_efg
+abc_50_efg
+abc_50_efg
+abc_51_efg
+abc_51_efg
+abc_52_efg
+abc_52_efg
+abc_53_efg
+abc_53_efg
+abc_54_efg
+abc_54_efg
+abc_55_efg
+abc_55_efg
+abc_56_efg
+abc_56_efg
+abc_57_efg
+abc_57_efg
+abc_58_efg
+abc_58_efg
+abc_59_efg
+abc_59_efg
+abc_5_efg
+abc_5_efg
+abc_60_efg
+abc_60_efg
+abc_61_efg
+abc_61_efg
+abc_62_efg
+abc_62_efg
+abc_63_efg
+abc_63_efg
+abc_64_efg
+abc_64_efg
+abc_65_efg
+abc_65_efg
+abc_66_efg
+abc_66_efg
+abc_67_efg
+abc_67_efg
+abc_68_efg
+abc_68_efg
+abc_69_efg
+abc_69_efg
+abc_6_efg
+abc_6_efg
+abc_70_efg
+abc_70_efg
+abc_71_efg
+abc_71_efg
+abc_72_efg
+abc_72_efg
+abc_73_efg
+abc_73_efg
+abc_74_efg
+abc_74_efg
+abc_75_efg
+abc_75_efg
+abc_76_efg
+abc_76_efg
+abc_77_efg
+abc_77_efg
+abc_78_efg
+abc_78_efg
+abc_79_efg
+abc_79_efg
+abc_7_efg
+abc_7_efg
+abc_80_efg
+abc_80_efg
+abc_81_efg
+abc_81_efg
+abc_82_efg
+abc_82_efg
+abc_83_efg
+abc_83_efg
+abc_84_efg
+abc_84_efg
+abc_85_efg
+abc_85_efg
+abc_86_efg
+abc_86_efg
+abc_87_efg
+abc_87_efg
+abc_88_efg
+abc_88_efg
+abc_89_efg
+abc_89_efg
+abc_8_efg
+abc_8_efg
+abc_90_efg
+abc_90_efg
+abc_91_efg
+abc_91_efg
+abc_92_efg
+abc_92_efg
+abc_93_efg
+abc_93_efg
+abc_94_efg
+abc_94_efg
+abc_95_efg
+abc_95_efg
+abc_96_efg
+abc_96_efg
+abc_97_efg
+abc_97_efg
+abc_98_efg
+abc_98_efg
+abc_99_efg
+abc_99_efg
+abc_9_efg
+abc_9_efg
diff --git a/bdb/test/scr017/O.R b/bdb/test/scr017/O.R
new file mode 100644
index 00000000000..d78a04727d8
--- /dev/null
+++ b/bdb/test/scr017/O.R
@@ -0,0 +1,196 @@
+1
+abc_1_efg
+2
+abc_2_efg
+3
+abc_3_efg
+4
+abc_4_efg
+5
+abc_5_efg
+6
+abc_6_efg
+7
+abc_7_efg
+8
+abc_8_efg
+9
+abc_9_efg
+10
+abc_10_efg
+11
+abc_11_efg
+12
+abc_12_efg
+13
+abc_13_efg
+14
+abc_14_efg
+15
+abc_15_efg
+16
+abc_16_efg
+17
+abc_17_efg
+18
+abc_18_efg
+19
+abc_19_efg
+20
+abc_20_efg
+21
+abc_21_efg
+22
+abc_22_efg
+23
+abc_23_efg
+24
+abc_24_efg
+25
+abc_25_efg
+26
+abc_26_efg
+27
+abc_27_efg
+28
+abc_28_efg
+29
+abc_29_efg
+30
+abc_30_efg
+31
+abc_31_efg
+32
+abc_32_efg
+33
+abc_33_efg
+34
+abc_34_efg
+35
+abc_36_efg
+36
+abc_37_efg
+37
+abc_38_efg
+38
+abc_39_efg
+39
+abc_40_efg
+40
+abc_41_efg
+41
+abc_42_efg
+42
+abc_43_efg
+43
+abc_44_efg
+44
+abc_45_efg
+45
+abc_46_efg
+46
+abc_47_efg
+47
+abc_48_efg
+48
+abc_49_efg
+49
+abc_50_efg
+50
+abc_51_efg
+51
+abc_52_efg
+52
+abc_53_efg
+53
+abc_54_efg
+54
+abc_55_efg
+55
+abc_56_efg
+56
+abc_57_efg
+57
+abc_58_efg
+58
+abc_59_efg
+59
+abc_60_efg
+60
+abc_61_efg
+61
+abc_62_efg
+62
+abc_63_efg
+63
+abc_64_efg
+64
+abc_65_efg
+65
+abc_66_efg
+66
+abc_67_efg
+67
+abc_68_efg
+68
+abc_69_efg
+69
+abc_70_efg
+70
+abc_71_efg
+71
+abc_72_efg
+72
+abc_73_efg
+73
+abc_74_efg
+74
+abc_75_efg
+75
+abc_76_efg
+76
+abc_77_efg
+77
+abc_78_efg
+78
+abc_79_efg
+79
+abc_80_efg
+80
+abc_81_efg
+81
+abc_82_efg
+82
+abc_83_efg
+83
+abc_84_efg
+84
+abc_85_efg
+85
+abc_86_efg
+86
+abc_87_efg
+87
+abc_88_efg
+88
+abc_89_efg
+89
+abc_90_efg
+90
+abc_91_efg
+91
+abc_92_efg
+92
+abc_93_efg
+93
+abc_94_efg
+94
+abc_95_efg
+95
+abc_96_efg
+96
+abc_97_efg
+97
+abc_98_efg
+98
+abc_99_efg
diff --git a/bdb/test/scr017/chk.db185 b/bdb/test/scr017/chk.db185
new file mode 100644
index 00000000000..c2a07c51d26
--- /dev/null
+++ b/bdb/test/scr017/chk.db185
@@ -0,0 +1,26 @@
+#!/bin/sh -
+#
+# $Id: chk.db185,v 1.2 2001/10/12 17:55:38 bostic Exp $
+#
+# Check to make sure we can run DB 1.85 code.
+
+[ -f ../libdb.a ] || (cd .. && make libdb.a) || {
+ echo 'FAIL: unable to find or build libdb.a'
+ exit 1
+}
+
+if cc -g -Wall -I.. t.c ../libdb.a -o t; then
+ :
+else
+ echo "FAIL: unable to compile test program t.c"
+ exit 1
+fi
+
+if ./t; then
+ :
+else
+ echo "FAIL: test program failed"
+ exit 1
+fi
+
+exit 0
diff --git a/bdb/test/scr017/t.c b/bdb/test/scr017/t.c
new file mode 100644
index 00000000000..f03b33880d6
--- /dev/null
+++ b/bdb/test/scr017/t.c
@@ -0,0 +1,188 @@
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db_185.h"
+
+void err(char *);
+int mycmp(const DBT *, const DBT *);
+void ops(DB *, int);
+
+int
+main()
+{
+ DB *dbp;
+ HASHINFO h_info;
+ BTREEINFO b_info;
+ RECNOINFO r_info;
+
+ printf("\tBtree...\n");
+ memset(&b_info, 0, sizeof(b_info));
+ b_info.flags = R_DUP;
+ b_info.cachesize = 100 * 1024;
+ b_info.psize = 512;
+ b_info.lorder = 4321;
+ b_info.compare = mycmp;
+ (void)remove("a.db");
+ if ((dbp =
+ dbopen("a.db", O_CREAT | O_RDWR, 0664, DB_BTREE, &b_info)) == NULL)
+ err("dbopen: btree");
+ ops(dbp, DB_BTREE);
+
+ printf("\tHash...\n");
+ memset(&h_info, 0, sizeof(h_info));
+ h_info.bsize = 512;
+ h_info.ffactor = 6;
+ h_info.nelem = 1000;
+ h_info.cachesize = 100 * 1024;
+ h_info.lorder = 1234;
+ (void)remove("a.db");
+ if ((dbp =
+ dbopen("a.db", O_CREAT | O_RDWR, 0664, DB_HASH, &h_info)) == NULL)
+ err("dbopen: hash");
+ ops(dbp, DB_HASH);
+
+ printf("\tRecno...\n");
+ memset(&r_info, 0, sizeof(r_info));
+ r_info.flags = R_FIXEDLEN;
+ r_info.cachesize = 100 * 1024;
+ r_info.psize = 1024;
+ r_info.reclen = 37;
+ (void)remove("a.db");
+ if ((dbp =
+ dbopen("a.db", O_CREAT | O_RDWR, 0664, DB_RECNO, &r_info)) == NULL)
+ err("dbopen: recno");
+ ops(dbp, DB_RECNO);
+
+ return (0);
+}
+
+int
+mycmp(a, b)
+ const DBT *a, *b;
+{
+ size_t len;
+ u_int8_t *p1, *p2;
+
+ len = a->size > b->size ? b->size : a->size;
+ for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
+ if (*p1 != *p2)
+ return ((long)*p1 - (long)*p2);
+ return ((long)a->size - (long)b->size);
+}
+
+void
+ops(dbp, type)
+ DB *dbp;
+ int type;
+{
+ FILE *outfp;
+ DBT key, data;
+ recno_t recno;
+ int i, ret;
+ char buf[64];
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ for (i = 1; i < 100; ++i) { /* Test DB->put. */
+ sprintf(buf, "abc_%d_efg", i);
+ if (type == DB_RECNO) {
+ recno = i;
+ key.data = &recno;
+ key.size = sizeof(recno);
+ } else {
+ key.data = data.data = buf;
+ key.size = data.size = strlen(buf);
+ }
+
+ data.data = buf;
+ data.size = strlen(buf);
+ if (dbp->put(dbp, &key, &data, 0))
+ err("DB->put");
+ }
+
+ if (type == DB_RECNO) { /* Test DB->get. */
+ recno = 97;
+ key.data = &recno;
+ key.size = sizeof(recno);
+ } else {
+ key.data = buf;
+ key.size = strlen(buf);
+ }
+ sprintf(buf, "abc_%d_efg", 97);
+ if (dbp->get(dbp, &key, &data, 0) != 0)
+ err("DB->get");
+ if (memcmp(data.data, buf, strlen(buf)))
+ err("DB->get: wrong data returned");
+
+ if (type == DB_RECNO) { /* Test DB->put no-overwrite. */
+ recno = 42;
+ key.data = &recno;
+ key.size = sizeof(recno);
+ } else {
+ key.data = buf;
+ key.size = strlen(buf);
+ }
+ sprintf(buf, "abc_%d_efg", 42);
+ if (dbp->put(dbp, &key, &data, R_NOOVERWRITE) == 0)
+ err("DB->put: no-overwrite succeeded");
+
+ if (type == DB_RECNO) { /* Test DB->del. */
+ recno = 35;
+ key.data = &recno;
+ key.size = sizeof(recno);
+ } else {
+ sprintf(buf, "abc_%d_efg", 35);
+ key.data = buf;
+ key.size = strlen(buf);
+ }
+ if (dbp->del(dbp, &key, 0))
+ err("DB->del");
+
+ /* Test DB->seq. */
+ if ((outfp = fopen("output", "w")) == NULL)
+ err("fopen: output");
+ while ((ret = dbp->seq(dbp, &key, &data, R_NEXT)) == 0) {
+ if (type == DB_RECNO)
+ fprintf(outfp, "%d\n", *(int *)key.data);
+ else
+ fprintf(outfp,
+ "%.*s\n", (int)key.size, (char *)key.data);
+ fprintf(outfp, "%.*s\n", (int)data.size, (char *)data.data);
+ }
+ if (ret != 1)
+ err("DB->seq");
+ fclose(outfp);
+ switch (type) {
+ case DB_BTREE:
+ ret = system("cmp output O.BH");
+ break;
+ case DB_HASH:
+ ret = system("sort output | cmp - O.BH");
+ break;
+ case DB_RECNO:
+ ret = system("cmp output O.R");
+ break;
+ }
+ if (ret != 0)
+ err("output comparison failed");
+
+ if (dbp->sync(dbp, 0)) /* Test DB->sync. */
+ err("DB->sync");
+
+ if (dbp->close(dbp)) /* Test DB->close. */
+ err("DB->close");
+}
+
+void
+err(s)
+ char *s;
+{
+ fprintf(stderr, "\t%s: %s\n", s, strerror(errno));
+ exit (1);
+}
diff --git a/bdb/test/scr018/chk.comma b/bdb/test/scr018/chk.comma
new file mode 100644
index 00000000000..42df48d1881
--- /dev/null
+++ b/bdb/test/scr018/chk.comma
@@ -0,0 +1,30 @@
+#!/bin/sh -
+#
+# $Id: chk.comma,v 1.1 2001/11/03 18:43:49 bostic Exp $
+#
+# Look for trailing commas in declarations. Some compilers can't handle:
+# enum {
+# foo,
+# bar,
+# };
+
+[ -f ../libdb.a ] || (cd .. && make libdb.a) || {
+ echo 'FAIL: unable to find or build libdb.a'
+ exit 1
+}
+
+if cc -g -Wall -I.. t.c ../libdb.a -o t; then
+ :
+else
+ echo "FAIL: unable to compile test program t.c"
+ exit 1
+fi
+
+if ./t ../../*/*.[ch] ../../*/*.in; then
+ :
+else
+ echo "FAIL: test program failed"
+ exit 1
+fi
+
+exit 0
diff --git a/bdb/test/scr018/t.c b/bdb/test/scr018/t.c
new file mode 100644
index 00000000000..4056a605928
--- /dev/null
+++ b/bdb/test/scr018/t.c
@@ -0,0 +1,46 @@
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <strings.h>
+
+int
+chk(f)
+ char *f;
+{
+ int ch, l, r;
+
+ if (freopen(f, "r", stdin) == NULL) {
+ fprintf(stderr, "%s: %s\n", f, strerror(errno));
+ exit (1);
+ }
+ for (l = 1, r = 0; (ch = getchar()) != EOF;) {
+ if (ch != ',')
+ goto next;
+ do { ch = getchar(); } while (isblank(ch));
+ if (ch != '\n')
+ goto next;
+ ++l;
+ do { ch = getchar(); } while (isblank(ch));
+ if (ch != '}')
+ goto next;
+ r = 1;
+ printf("%s: line %d\n", f, l);
+
+next: if (ch == '\n')
+ ++l;
+ }
+ return (r);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int r;
+
+ for (r = 0; *++argv != NULL;)
+ if (chk(*argv))
+ r = 1;
+ return (r);
+}
diff --git a/bdb/test/scr019/chk.include b/bdb/test/scr019/chk.include
new file mode 100644
index 00000000000..444217bedb4
--- /dev/null
+++ b/bdb/test/scr019/chk.include
@@ -0,0 +1,40 @@
+#!/bin/sh -
+#
+# $Id: chk.include,v 1.3 2002/03/27 04:33:09 bostic Exp $
+#
+# Check for inclusion of files already included in db_int.h.
+
+d=../..
+
+# Test must be run from the top-level directory, not from a test directory.
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t1=__1
+t2=__2
+
+egrep -- '#include[ ]' $d/dbinc/db_int.in |
+sed -e '/[ ]db\.h'/d \
+ -e 's/^#include.//' \
+ -e 's/[<>"]//g' \
+ -e 's/[ ].*//' > $t1
+
+for i in `cat $t1`; do
+ (cd $d && egrep "^#include[ ].*[<\"]$i[>\"]" */*.[ch])
+done |
+sed -e '/^build/d' \
+ -e '/^db_dump185/d' \
+ -e '/^examples_c/d' \
+ -e '/^libdb_java.*errno.h/d' \
+ -e '/^libdb_java.*java_util.h/d' \
+ -e '/^test_/d' \
+ -e '/^mutex\/tm.c/d' > $t2
+
+[ -s $t2 ] && {
+ echo 'FAIL: found extraneous includes in the source'
+ cat $t2
+ exit 1
+}
+exit 0
diff --git a/bdb/test/scr020/chk.inc b/bdb/test/scr020/chk.inc
new file mode 100644
index 00000000000..189126b10c3
--- /dev/null
+++ b/bdb/test/scr020/chk.inc
@@ -0,0 +1,43 @@
+#!/bin/sh -
+#
+# $Id: chk.inc,v 1.1 2002/02/10 17:14:33 bostic Exp $
+#
+# Check for inclusion of db_config.h after "const" or other includes.
+
+d=../..
+
+# Test must be run from the top-level directory, not from a test directory.
+[ -f $d/LICENSE ] || {
+ echo 'FAIL: cannot find source distribution directory.'
+ exit 1
+}
+
+t1=__1
+t2=__2
+
+(cd $d && find . -name '*.[chys]' -o -name '*.cpp' |
+ xargs egrep -l '#include.*db_config.h') > $t1
+
+:> $t2
+for i in `cat $t1`; do
+ egrep -w 'db_config.h|const' /dev/null $d/$i | head -1 >> $t2
+done
+
+if egrep const $t2 > /dev/null; then
+ echo 'FAIL: found const before include of db_config.h'
+ egrep const $t2
+ exit 1
+fi
+
+:> $t2
+for i in `cat $t1`; do
+ egrep -w '#include' /dev/null $d/$i | head -1 >> $t2
+done
+
+if egrep -v db_config.h $t2 > /dev/null; then
+ echo 'FAIL: found includes before include of db_config.h'
+ egrep -v db_config.h $t2
+ exit 1
+fi
+
+exit 0
diff --git a/bdb/test/scr021/chk.flags b/bdb/test/scr021/chk.flags
new file mode 100644
index 00000000000..1b2bb62cca7
--- /dev/null
+++ b/bdb/test/scr021/chk.flags
@@ -0,0 +1,97 @@
+#!/bin/sh -
+#
+# $Id: chk.flags,v 1.8 2002/08/14 02:19:55 bostic Exp $
+#
+# Check flag name-spaces.
+
+d=../..
+
+t1=__1
+
+# Check for DB_ENV flags.
+(grep 'F_ISSET([^ ]*dbenv,' $d/*/*.[chys];
+ grep 'F_SET([^ ]*dbenv,' $d/*/*.[chys];
+ grep 'F_CLR([^ ]*dbenv,' $d/*/*.[chys]) |
+ sed -e '/DB_ENV_/d' -e '/F_SET([^ ]*dbenv, db_env_reset)/d' > $t1
+[ -s $t1 ] && {
+ cat $t1
+ exit 1
+}
+
+grep 'DB_ENV_' $d/*/*.c |
+sed -e '/F_.*dbenv,/d' \
+ -e '/DB_ENV_TEST_RECOVERY(.*DB_TEST_/d' \
+ -e '/\/libdb_java\//d' > $t1
+[ -s $t1 ] && {
+ cat $t1
+ exit 1
+}
+
+# Check for DB flags.
+(grep 'F_ISSET([^ ]*dbp,' $d/*/*.[chys];
+ grep 'F_SET([^ ]*dbp,' $d/*/*.[chys];
+ grep 'F_CLR([^ ]*dbp,' $d/*/*.[chys]) |
+ sed -e '/DB_AM_/d' \
+ -e '/db.c:.*F_SET.*F_ISSET(subdbp,/d' > $t1
+[ -s $t1 ] && {
+ cat $t1
+ exit 1
+}
+
+grep 'DB_AM_' $d/*/*.c |
+sed -e '/F_.*dbp/d' \
+ -e '/"DB->open", dbp->flags, DB_AM_DUP,/d' \
+ -e '/"DB_NODUPDATA" behavior for databases with/d' \
+ -e '/If DB_AM_OPEN_CALLED is not set, then we/d' \
+ -e '/This was checked in set_flags when DB_AM_ENCRYPT/d' \
+ -e '/XA_ABORT, we can safely set DB_AM_RECOVER/d' \
+ -e '/ DB_AM_RECNUM\./d' \
+ -e '/ DB_AM_RECOVER set\./d' \
+ -e '/isdup = dbp->flags & DB_AM_DUP/d' \
+ -e '/otherwise we simply do/d' \
+ -e '/pginfo/d' \
+ -e '/setting DB_AM_RECOVER, we guarantee that we don/d' \
+ -e '/:[ {]*DB_AM_/d' > $t1
+[ -s $t1 ] && {
+ cat $t1
+ exit 1
+}
+
+# Check for DBC flags.
+(grep 'F_ISSET([^ ]*dbc,' $d/*/*.[chys];
+ grep 'F_SET([^ ]*dbc,' $d/*/*.[chys];
+ grep 'F_CLR([^ ]*dbc,' $d/*/*.[chys]) |
+ sed -e '/DBC_/d' > $t1
+[ -s $t1 ] && {
+ cat $t1
+ exit 1
+}
+
+grep 'DBC_' $d/*/*.c |
+sed -e '/F_.*dbc/d' \
+ -e '/DBC_INTERNAL/d' \
+ -e '/DBC_LOGGING/d' \
+ -e '/Do the actual get. Set DBC_TRANSIENT/d' \
+ -e '/If DBC_WRITEDUP is set, the cursor is an in/d' \
+ -e '/The DBC_TRANSIENT flag indicates that we/d' \
+ -e '/This function replaces the DBC_CONTINUE and DBC_KEYSET/d' \
+ -e '/db_cam.c:.*F_CLR(opd, DBC_ACTIVE);/d' \
+ -e '/{ DBC_/d' > $t1
+[ -s $t1 ] && {
+ cat $t1
+ exit 1
+}
+
+# Check for bad use of macros.
+egrep 'case .*F_SET\(|case .*F_CLR\(' $d/*/*.c > $t1
+egrep 'for .*F_SET\(|for .*F_CLR\(' $d/*/*.c >> $t1
+egrep 'if .*F_SET\(|if .*F_CLR\(' $d/*/*.c >> $t1
+egrep 'switch .*F_SET\(|switch .*F_CLR\(' $d/*/*.c >> $t1
+egrep 'while .*F_SET\(|while .*F_CLR\(' $d/*/*.c >> $t1
+[ -s $t1 ] && {
+ echo 'if statement followed by non-test macro'
+ cat $t1
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/scr022/chk.rr b/bdb/test/scr022/chk.rr
new file mode 100644
index 00000000000..df230315299
--- /dev/null
+++ b/bdb/test/scr022/chk.rr
@@ -0,0 +1,22 @@
+#!/bin/sh -
+#
+# $Id: chk.rr,v 1.1 2002/04/19 15:13:05 bostic Exp $
+
+d=../..
+
+t1=__1
+
+# Check for DB_RUNRECOVERY being specified instead of a call to db_panic.
+egrep DB_RUNRECOVERY $d/*/*.c |
+ sed -e '/common\/db_err.c:/d' \
+ -e '/libdb_java\/java_util.c:/d' \
+ -e '/db_dispatch.c:.*if (ret == DB_RUNRECOVERY/d' \
+ -e '/txn.c:.* \* DB_RUNRECOVERY and we need to/d' \
+ -e '/__db_panic(.*, DB_RUNRECOVERY)/d' > $t1
+[ -s $t1 ] && {
+ echo "DB_RUNRECOVERY used; should be a call to db_panic."
+ cat $t1
+ exit 1
+}
+
+exit 0
diff --git a/bdb/test/sdb001.tcl b/bdb/test/sdb001.tcl
index 938b6c10c6d..a03160e0ab7 100644
--- a/bdb/test/sdb001.tcl
+++ b/bdb/test/sdb001.tcl
@@ -1,24 +1,42 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb001.tcl,v 11.12 2000/08/25 14:21:52 sue Exp $
+# $Id: sdb001.tcl,v 11.18 2002/06/10 15:39:36 sue Exp $
#
-# Sub DB Test 1 {access method}
-# Test non-subdb and subdb operations
-# Test naming (filenames begin with -)
-# Test existence (cannot create subdb of same name with -excl)
+# TEST subdb001 Tests mixing db and subdb operations
+# TEST Tests mixing db and subdb operations
+# TEST Create a db, add data, try to create a subdb.
+# TEST Test naming db and subdb with a leading - for correct parsing
+# TEST Existence check -- test use of -excl with subdbs
+# TEST
+# TEST Test non-subdb and subdb operations
+# TEST Test naming (filenames begin with -)
+# TEST Test existence (cannot create subdb of same name with -excl)
proc subdb001 { method args } {
source ./include.tcl
+ global errorInfo
set args [convert_args $method $args]
set omethod [convert_method $method]
+ if { [is_queue $method] == 1 } {
+ puts "Subdb001: skipping for method $method"
+ return
+ }
puts "Subdb001: $method ($args) subdb and non-subdb tests"
- # Create the database and open the dictionary
set testfile $testdir/subdb001.db
+ set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ set env NULL
+ incr eindex
+ set env [lindex $args $eindex]
+ puts "Subdb001 skipping for env $env"
+ return
+ }
+ # Create the database and open the dictionary
set subdb subdb0
cleanup $testdir NULL
puts "\tSubdb001.a: Non-subdb database and subdb operations"
@@ -27,7 +45,7 @@ proc subdb001 { method args } {
# open/add with a subdb. Should fail.
#
puts "\tSubdb001.a.0: Create db, add data, close, try subdb"
- set db [eval {berkdb_open -create -truncate -mode 0644} \
+ set db [eval {berkdb_open -create -mode 0644} \
$args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -70,6 +88,12 @@ proc subdb001 { method args } {
#
set testfile $testdir/subdb001a.db
puts "\tSubdb001.a.1: Create db, close, try subdb"
+ #
+ # !!!
+ # Using -truncate is illegal when opening for subdbs, but we
+ # can use it here because we are not using subdbs for this
+ # create.
+ #
set db [eval {berkdb_open -create -truncate -mode 0644} $args \
{$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -108,9 +132,18 @@ proc subdb001 { method args } {
# Create 1 db with 1 subdb. Try to create another subdb of
# the same name. Should fail.
#
- puts "\tSubdb001.c: Existence check"
+ puts "\tSubdb001.c: Truncate check"
set testfile $testdir/subdb001c.db
set subdb subdb
+ set stat [catch {eval {berkdb_open_noerr -create -truncate -mode 0644} \
+ $args {$omethod $testfile $subdb}} ret]
+ error_check_bad dbopen $stat 0
+ error_check_good trunc [is_substr $ret \
+ "illegal with multiple databases"] 1
+
+ puts "\tSubdb001.d: Existence check"
+ set testfile $testdir/subdb001d.db
+ set subdb subdb
set ret [catch {eval {berkdb_open -create -excl -mode 0644} $args \
{$omethod $testfile $subdb}} db]
error_check_good dbopen [is_valid_db $db] TRUE
diff --git a/bdb/test/sdb002.tcl b/bdb/test/sdb002.tcl
index 11547195c02..4757e12afc7 100644
--- a/bdb/test/sdb002.tcl
+++ b/bdb/test/sdb002.tcl
@@ -1,20 +1,47 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb002.tcl,v 11.20 2000/09/20 13:22:04 sue Exp $
+# $Id: sdb002.tcl,v 11.35 2002/08/23 18:01:53 sandstro Exp $
#
-# Sub DB Test 2 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
-# Then repeat using an environment.
+# TEST subdb002
+# TEST Tests basic subdb functionality
+# TEST Small keys, small data
+# TEST Put/get per key
+# TEST Dump file
+# TEST Close, reopen
+# TEST Dump file
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Close file, reopen, do retrieve and re-verify.
+# TEST Then repeat using an environment.
proc subdb002 { method {nentries 10000} args } {
+ global passwd
+
+ set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ set env NULL
+ incr eindex
+ set env [lindex $args $eindex]
+ puts "Subdb002 skipping for env $env"
+ return
+ }
+ set largs $args
+ subdb002_main $method $nentries $largs
+ append largs " -chksum "
+ subdb002_main $method $nentries $largs
+ append largs "-encryptaes $passwd "
+ subdb002_main $method $nentries $largs
+}
+
+proc subdb002_main { method nentries largs } {
source ./include.tcl
+ global encrypt
- set largs [convert_args $method $args]
+ set largs [convert_args $method $largs]
set omethod [convert_method $method]
env_cleanup $testdir
@@ -23,8 +50,20 @@ proc subdb002 { method {nentries 10000} args } {
set testfile $testdir/subdb002.db
subdb002_body $method $omethod $nentries $largs $testfile NULL
+ # Run convert_encrypt so that old_encrypt will be reset to
+ # the proper value and cleanup will work.
+ convert_encrypt $largs
+ set encargs ""
+ set largs [split_encargs $largs encargs]
+
cleanup $testdir NULL
- set env [berkdb env -create -mode 0644 -txn -home $testdir]
+ if { [is_queue $omethod] == 1 } {
+ set sdb002_env berkdb_env_noerr
+ } else {
+ set sdb002_env berkdb_env
+ }
+ set env [eval {$sdb002_env -create -cachesize {0 10000000 0} \
+ -mode 0644 -txn} -home $testdir $encargs]
error_check_good env_open [is_valid_env $env] TRUE
puts "Subdb002: $method ($largs) basic subdb tests in an environment"
@@ -36,6 +75,8 @@ proc subdb002 { method {nentries 10000} args } {
}
proc subdb002_body { method omethod nentries largs testfile env } {
+ global encrypt
+ global passwd
source ./include.tcl
# Create the database and open the dictionary
@@ -130,7 +171,7 @@ proc subdb002_body { method omethod nentries largs testfile env } {
puts "\tSubdb002.c: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_subfile $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile $env $t1 $checkfunc \
dump_file_direction "-first" "-next" $subdb
if { [is_record_based $method] != 1 } {
filesort $t1 $t3
@@ -142,7 +183,7 @@ proc subdb002_body { method omethod nentries largs testfile env } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tSubdb002.d: close, open, and dump file in reverse direction"
- open_and_dump_subfile $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile $env $t1 $checkfunc \
dump_file_direction "-last" "-prev" $subdb
if { [is_record_based $method] != 1 } {
@@ -151,6 +192,19 @@ proc subdb002_body { method omethod nentries largs testfile env } {
error_check_good Subdb002:diff($t3,$t2) \
[filecmp $t3 $t2] 0
+
+ puts "\tSubdb002.e: db_dump with subdatabase"
+ set outfile $testdir/subdb002.dump
+ set dumpargs " -f $outfile -s $subdb "
+ if { $encrypt > 0 } {
+ append dumpargs " -P $passwd "
+ }
+ if { $env != "NULL" } {
+ append dumpargs " -h $testdir "
+ }
+ append dumpargs " $testfile"
+ set stat [catch {eval {exec $util_path/db_dump} $dumpargs} ret]
+ error_check_good dbdump.subdb $stat 0
}
# Check function for Subdb002; keys and data are identical
diff --git a/bdb/test/sdb003.tcl b/bdb/test/sdb003.tcl
index 32bb93d5236..5d1536d8c84 100644
--- a/bdb/test/sdb003.tcl
+++ b/bdb/test/sdb003.tcl
@@ -1,15 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb003.tcl,v 11.17 2000/08/25 14:21:52 sue Exp $
+# $Id: sdb003.tcl,v 11.24 2002/06/10 15:39:37 sue Exp $
#
-# Sub DB Test 3 {access method}
-# Use the first 10,000 entries from the dictionary as subdbnames.
-# Insert each with entry as name of subdatabase and a partial list as key/data.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
+# TEST subdb003
+# TEST Tests many subdbs
+# TEST Creates many subdbs and puts a small amount of
+# TEST data in each (many defaults to 2000)
+# TEST
+# TEST Use the first 10,000 entries from the dictionary as subdbnames.
+# TEST Insert each with entry as name of subdatabase and a partial list
+# TEST as key/data. After all are entered, retrieve all; compare output
+# TEST to original. Close file, reopen, do retrieve and re-verify.
proc subdb003 { method {nentries 1000} args } {
source ./include.tcl
@@ -23,12 +27,32 @@ proc subdb003 { method {nentries 1000} args } {
puts "Subdb003: $method ($args) many subdb tests"
+ set txnenv 0
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb003.db
+ set env NULL
+ } else {
+ set testfile subdb003.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ if { $nentries == 1000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
+ }
# Create the database and open the dictionary
- set testfile $testdir/subdb003.db
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
- cleanup $testdir NULL
+ cleanup $testdir $env
set pflags ""
set gflags ""
@@ -62,18 +86,35 @@ proc subdb003 { method {nentries 1000} args } {
} else {
set key $str
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $str]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set ret [eval {$db get} $gflags {$key}]
- error_check_good get $ret [list [list $key [pad_data $method $str]]]
+ error_check_good get $ret [list [list $key \
+ [pad_data $method $str]]]
incr count
}
close $did
incr fcount
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match
@@ -95,7 +136,7 @@ proc subdb003 { method {nentries 1000} args } {
[filecmp $t3 $t2] 0
# Now, reopen the file and run the last test again.
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile $env $t1 $checkfunc \
dump_file_direction "-first" "-next" $subdb
if { [is_record_based $method] != 1 } {
filesort $t1 $t3
@@ -106,7 +147,7 @@ proc subdb003 { method {nentries 1000} args } {
# Now, reopen the file and run the last test again in the
# reverse direction.
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile $env $t1 $checkfunc \
dump_file_direction "-last" "-prev" $subdb
if { [is_record_based $method] != 1 } {
@@ -120,6 +161,7 @@ proc subdb003 { method {nentries 1000} args } {
flush stdout
}
}
+ close $fdid
puts ""
}
diff --git a/bdb/test/sdb004.tcl b/bdb/test/sdb004.tcl
index fb63f9d6d1d..d3d95f1fde0 100644
--- a/bdb/test/sdb004.tcl
+++ b/bdb/test/sdb004.tcl
@@ -1,15 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb004.tcl,v 11.14 2000/08/25 14:21:53 sue Exp $
+# $Id: sdb004.tcl,v 11.22 2002/07/11 18:53:45 sandstro Exp $
#
-# SubDB Test 4 {access method}
-# Create 1 db with many large subdbs. Use the contents as subdb names.
-# Take the source files and dbtest executable and enter their names as the
-# key with their contents as data. After all are entered, retrieve all;
-# compare output to original. Close file, reopen, do retrieve and re-verify.
+# TEST subdb004
+# TEST Tests large subdb names
+# TEST subdb name = filecontents,
+# TEST key = filename, data = filecontents
+# TEST Put/get per key
+# TEST Dump file
+# TEST Dump subdbs, verify data and subdb name match
+# TEST
+# TEST Create 1 db with many large subdbs. Use the contents as subdb names.
+# TEST Take the source files and dbtest executable and enter their names as
+# TEST the key with their contents as data. After all are entered, retrieve
+# TEST all; compare output to original. Close file, reopen, do retrieve and
+# TEST re-verify.
proc subdb004 { method args} {
global names
source ./include.tcl
@@ -25,14 +33,34 @@ proc subdb004 { method args} {
puts "Subdb004: $method ($args) \
filecontents=subdbname filename=key filecontents=data pairs"
+ set txnenv 0
+ set envargs ""
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb004.db
+ set env NULL
+ } else {
+ set testfile subdb004.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append envargs " -auto_commit "
+ }
+ set testdir [get_home $env]
+ }
# Create the database and open the dictionary
- set testfile $testdir/subdb004.db
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
set t4 $testdir/t4
- cleanup $testdir NULL
+ cleanup $testdir $env
set pflags ""
set gflags ""
set txn ""
@@ -44,8 +72,14 @@ proc subdb004 { method args} {
}
# Here is the loop where we put and get each key/data pair
- set file_list [glob ../*/*.c ./libdb.so.3.0 ./libtool ./libtool.exe]
+ # Note that the subdatabase name is passed in as a char *, not
+ # in a DBT, so it may not contain nulls; use only source files.
+ set file_list [glob $src_root/*/*.c]
set fcount [llength $file_list]
+ if { $txnenv == 1 && $fcount > 100 } {
+ set file_list [lrange $file_list 0 99]
+ set fcount 100
+ }
set count 0
if { [is_record_based $method] == 1 } {
@@ -79,9 +113,17 @@ proc subdb004 { method args} {
set db [eval {berkdb_open -create -mode 0644} \
$args {$omethod $testfile $subdb}]
error_check_good dbopen [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval \
{$db put} $txn $pflags {$key [chop_data $method $data]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Should really catch errors
set fid [open $t4 w]
@@ -104,7 +146,15 @@ proc subdb004 { method args} {
# Now we will get each key from the DB and compare the results
# to the original.
# puts "\tSubdb004.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_bin_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
@@ -114,21 +164,30 @@ proc subdb004 { method args} {
# as the data in that subdb and that the filename is the key.
#
puts "\tSubdb004.b: Compare subdb names with key/data"
- set db [berkdb_open -rdonly $testfile]
+ set db [eval {berkdb_open -rdonly} $envargs {$testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set c [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $c $db] TRUE
for {set d [$c get -first] } { [llength $d] != 0 } \
{set d [$c get -next] } {
set subdbname [lindex [lindex $d 0] 0]
- set subdb [berkdb_open $testfile $subdbname]
+ set subdb [eval {berkdb_open} $args {$testfile $subdbname}]
error_check_good dbopen [is_valid_db $db] TRUE
# Output the subdb name
set ofid [open $t3 w]
fconfigure $ofid -translation binary
- set subdbname [string trimright $subdbname \0]
+ if { [string compare "\0" \
+ [string range $subdbname end end]] == 0 } {
+ set slen [expr [string length $subdbname] - 2]
+ set subdbname [string range $subdbname 1 $slen]
+ }
puts -nonewline $ofid $subdbname
close $ofid
@@ -154,6 +213,9 @@ proc subdb004 { method args} {
error_check_good db_close [$subdb close] 0
}
error_check_good curs_close [$c close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
if { [is_record_based $method] != 1 } {
diff --git a/bdb/test/sdb005.tcl b/bdb/test/sdb005.tcl
index 22e4083c46c..98cea5b348b 100644
--- a/bdb/test/sdb005.tcl
+++ b/bdb/test/sdb005.tcl
@@ -1,11 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb005.tcl,v 11.12 2000/08/25 14:21:53 sue Exp $
+# $Id: sdb005.tcl,v 11.18 2002/07/11 18:53:46 sandstro Exp $
#
-# Test cursor operations between subdbs.
+# TEST subdb005
+# TEST Tests cursor operations in subdbs
+# TEST Put/get per key
+# TEST Verify cursor operations work within subdb
+# TEST Verify cursor operations do not work across subdbs
+# TEST
#
# We should test this on all btrees, all hash, and a combination thereof
proc subdb005 {method {nentries 100} args } {
@@ -20,21 +25,50 @@ proc subdb005 {method {nentries 100} args } {
}
puts "Subdb005: $method ( $args ) subdb cursor operations test"
+ set txnenv 0
+ set envargs ""
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb005.db
+ set env NULL
+ } else {
+ set testfile subdb005.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append envargs " -auto_commit "
+ if { $nentries == 100 } {
+ set nentries 20
+ }
+ }
+ set testdir [get_home $env]
+ }
+
+ cleanup $testdir $env
set txn ""
- cleanup $testdir NULL
set psize 8192
- set testfile $testdir/subdb005.db
set duplist {-1 -1 -1 -1 -1}
build_all_subdb \
- $testfile [list $method] [list $psize] $duplist $nentries $args
+ $testfile [list $method] $psize $duplist $nentries $args
set numdb [llength $duplist]
#
# Get a cursor in each subdb and move past the end of each
# subdb. Make sure we don't end up in another subdb.
#
puts "\tSubdb005.a: Cursor ops - first/prev and last/next"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
for {set i 0} {$i < $numdb} {incr i} {
- set db [berkdb_open -unknown $testfile sub$i.db]
+ set db [eval {berkdb_open -unknown} $args {$testfile sub$i.db}]
error_check_good dbopen [is_valid_db $db] TRUE
set db_handle($i) $db
# Used in 005.c test
@@ -54,6 +88,7 @@ proc subdb005 {method {nentries 100} args } {
error_check_good dbc_get [expr [llength $d] != 0] 1
set d [$dbc get -next]
error_check_good dbc_get [expr [llength $d] == 0] 1
+ error_check_good dbc_close [$dbc close] 0
}
#
# Get a key from each subdb and try to get this key in a
@@ -67,15 +102,17 @@ proc subdb005 {method {nentries 100} args } {
}
set db $db_handle($i)
if { [is_record_based $method] == 1 } {
- set d [$db get -recno $db_key($n)]
+ set d [eval {$db get -recno} $txn {$db_key($n)}]
error_check_good \
db_get [expr [llength $d] == 0] 1
} else {
- set d [$db get $db_key($n)]
+ set d [eval {$db get} $txn {$db_key($n)}]
error_check_good db_get [expr [llength $d] == 0] 1
}
}
-
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
#
# Clean up
#
@@ -92,7 +129,7 @@ proc subdb005 {method {nentries 100} args } {
{berkdb_open_noerr -unknown $testfile} ret] 0
puts "\tSubdb005.d: Check contents of DB for subdb names only"
- set db [berkdb_open -unknown -rdonly $testfile]
+ set db [eval {berkdb_open -unknown -rdonly} $envargs {$testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set subdblist [$db get -glob *]
foreach kd $subdblist {
diff --git a/bdb/test/sdb006.tcl b/bdb/test/sdb006.tcl
index 70dee5c7343..fd6066b08d6 100644
--- a/bdb/test/sdb006.tcl
+++ b/bdb/test/sdb006.tcl
@@ -1,17 +1,20 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb006.tcl,v 11.12 2000/09/20 13:22:03 sue Exp $
+# $Id: sdb006.tcl,v 11.20 2002/06/20 19:01:02 sue Exp $
#
-# We'll test 2-way, 3-way, and 4-way joins and figure that if those work,
-# everything else does as well. We'll create test databases called
-# sub1.db, sub2.db, sub3.db, and sub4.db. The number on the database
-# describes the duplication -- duplicates are of the form 0, N, 2N, 3N, ...
-# where N is the number of the database. Primary.db is the primary database,
-# and sub0.db is the database that has no matching duplicates. All of
-# these are within a single database.
+# TEST subdb006
+# TEST Tests intra-subdb join
+# TEST
+# TEST We'll test 2-way, 3-way, and 4-way joins and figure that if those work,
+# TEST everything else does as well. We'll create test databases called
+# TEST sub1.db, sub2.db, sub3.db, and sub4.db. The number on the database
+# TEST describes the duplication -- duplicates are of the form 0, N, 2N, 3N,
+# TEST ... where N is the number of the database. Primary.db is the primary
+# TEST database, and sub0.db is the database that has no matching duplicates.
+# TEST All of these are within a single database.
#
# We should test this on all btrees, all hash, and a combination thereof
proc subdb006 {method {nentries 100} args } {
@@ -27,8 +30,34 @@ proc subdb006 {method {nentries 100} args } {
return
}
+ set txnenv 0
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb006.db
+ set env NULL
+ } else {
+ set testfile subdb006.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ if { $nentries == 100 } {
+ # !!!
+ # nentries must be greater than the number
+ # of do_join_subdb calls below.
+ #
+ set nentries 35
+ }
+ }
+ set testdir [get_home $env]
+ }
berkdb srand $rand_init
+ set oargs $args
foreach opt {" -dup" " -dupsort"} {
append args $opt
@@ -40,10 +69,12 @@ proc subdb006 {method {nentries 100} args } {
#
puts "\tSubdb006.a: Intra-subdb join"
- cleanup $testdir NULL
- set testfile $testdir/subdb006.db
+ if { $env != "NULL" } {
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
- set psize [list 8192]
+ set psize 8192
set duplist {0 50 25 16 12}
set numdb [llength $duplist]
build_all_subdb $testfile [list $method] $psize \
@@ -53,77 +84,85 @@ proc subdb006 {method {nentries 100} args } {
puts "Subdb006: Building the primary database $method"
set oflags "-create -mode 0644 [conv $omethod \
[berkdb random_int 1 2]]"
- set db [eval {berkdb_open} $oflags $testfile primary.db]
+ set db [eval {berkdb_open} $oflags $oargs $testfile primary.db]
error_check_good dbopen [is_valid_db $db] TRUE
for { set i 0 } { $i < 1000 } { incr i } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set key [format "%04d" $i]
- set ret [$db put $key stub]
+ set ret [eval {$db put} $txn {$key stub}]
error_check_good "primary put" $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
error_check_good "primary close" [$db close] 0
set did [open $dict]
gets $did str
- do_join_subdb $testfile primary.db "1 0" $str
+ do_join_subdb $testfile primary.db "1 0" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "2 0" $str
+ do_join_subdb $testfile primary.db "2 0" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 0" $str
+ do_join_subdb $testfile primary.db "3 0" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 0" $str
+ do_join_subdb $testfile primary.db "4 0" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "1" $str
+ do_join_subdb $testfile primary.db "1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "2" $str
+ do_join_subdb $testfile primary.db "2" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3" $str
+ do_join_subdb $testfile primary.db "3" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4" $str
+ do_join_subdb $testfile primary.db "4" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "1 2" $str
+ do_join_subdb $testfile primary.db "1 2" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "1 2 3" $str
+ do_join_subdb $testfile primary.db "1 2 3" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "1 2 3 4" $str
+ do_join_subdb $testfile primary.db "1 2 3 4" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "2 1" $str
+ do_join_subdb $testfile primary.db "2 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 2 1" $str
+ do_join_subdb $testfile primary.db "3 2 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 3 2 1" $str
+ do_join_subdb $testfile primary.db "4 3 2 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "1 3" $str
+ do_join_subdb $testfile primary.db "1 3" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 1" $str
+ do_join_subdb $testfile primary.db "3 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "1 4" $str
+ do_join_subdb $testfile primary.db "1 4" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 1" $str
+ do_join_subdb $testfile primary.db "4 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "2 3" $str
+ do_join_subdb $testfile primary.db "2 3" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 2" $str
+ do_join_subdb $testfile primary.db "3 2" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "2 4" $str
+ do_join_subdb $testfile primary.db "2 4" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 2" $str
+ do_join_subdb $testfile primary.db "4 2" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 4" $str
+ do_join_subdb $testfile primary.db "3 4" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 3" $str
+ do_join_subdb $testfile primary.db "4 3" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "2 3 4" $str
+ do_join_subdb $testfile primary.db "2 3 4" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 4 1" $str
+ do_join_subdb $testfile primary.db "3 4 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 2 1" $str
+ do_join_subdb $testfile primary.db "4 2 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "0 2 1" $str
+ do_join_subdb $testfile primary.db "0 2 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "3 2 0" $str
+ do_join_subdb $testfile primary.db "3 2 0" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 3 2 1" $str
+ do_join_subdb $testfile primary.db "4 3 2 1" $str $oargs
gets $did str
- do_join_subdb $testfile primary.db "4 3 0 1" $str
+ do_join_subdb $testfile primary.db "4 3 0 1" $str $oargs
close $did
}
diff --git a/bdb/test/sdb007.tcl b/bdb/test/sdb007.tcl
index 6b56fd411dd..0f9488a92a1 100644
--- a/bdb/test/sdb007.tcl
+++ b/bdb/test/sdb007.tcl
@@ -1,19 +1,24 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb007.tcl,v 11.13 2000/12/11 17:24:55 sue Exp $
+# $Id: sdb007.tcl,v 11.20 2002/07/11 18:53:46 sandstro Exp $
#
-# Sub DB Test 7 {access method}
-# Use the first 10,000 entries from the dictionary spread across each subdb.
-# Use a different page size for every subdb.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
-proc subdb007 { method {nentries 10000} args } {
+# TEST subdb007
+# TEST Tests page size difference errors between subdbs.
+# TEST Test 3 different scenarios for page sizes.
+# TEST 1. Create/open with a default page size, 2nd subdb create with
+# TEST specified different one, should error.
+# TEST 2. Create/open with specific page size, 2nd subdb create with
+# TEST different one, should error.
+# TEST 3. Create/open with specified page size, 2nd subdb create with
+# TEST same specified size, should succeed.
+# TEST (4th combo of using all defaults is a basic test, done elsewhere)
+proc subdb007 { method args } {
source ./include.tcl
+ set db2args [convert_args -btree $args]
set args [convert_args $method $args]
set omethod [convert_method $method]
@@ -23,101 +28,105 @@ proc subdb007 { method {nentries 10000} args } {
}
set pgindex [lsearch -exact $args "-pagesize"]
if { $pgindex != -1 } {
- puts "Subdb007: skipping for specific pagesizes"
+ puts "Subdb007: skipping for specific page sizes"
return
}
- puts "Subdb007: $method ($args) subdb tests with different pagesizes"
-
- # Create the database and open the dictionary
- set testfile $testdir/subdb007.db
- set t1 $testdir/t1
- set t2 $testdir/t2
- set t3 $testdir/t3
- set t4 $testdir/t4
- cleanup $testdir NULL
-
- set txn ""
- set count 0
-
- if { [is_record_based $method] == 1 } {
- set checkfunc subdb007_recno.check
+ puts "Subdb007: $method ($args) subdb tests with different page sizes"
+
+ set txnenv 0
+ set envargs ""
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb007.db
+ set env NULL
} else {
- set checkfunc subdb007.check
- }
- puts "\tSubdb007.a: create subdbs of different page sizes"
- set psize {8192 4096 2048 1024 512}
- set nsubdbs [llength $psize]
- for { set i 0 } { $i < $nsubdbs } { incr i } {
- lappend duplist -1
- }
- set newent [expr $nentries / $nsubdbs]
- build_all_subdb $testfile [list $method] $psize $duplist $newent $args
-
- # Now we will get each key from the DB and compare the results
- # to the original.
- for { set subdb 0 } { $subdb < $nsubdbs } { incr subdb } {
- puts "\tSubdb007.b: dump file sub$subdb.db"
- set db [berkdb_open -unknown $testfile sub$subdb.db]
- dump_file $db $txn $t1 $checkfunc
- error_check_good db_close [$db close] 0
-
- # Now compare the keys to see if they match the dictionary
- # (or ints)
- if { [is_record_based $method] == 1 } {
- set oid [open $t2 w]
- for {set i 1} {$i <= $newent} {incr i} {
- puts $oid [expr $subdb * $newent + $i]
- }
- close $oid
- file rename -force $t1 $t3
- } else {
- set beg [expr $subdb * $newent]
- incr beg
- set end [expr $beg + $newent - 1]
- filehead $end $dict $t3 $beg
- filesort $t3 $t2
- filesort $t1 $t3
+ set testfile subdb007.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append envargs " -auto_commit "
+ append db2args " -auto_commit "
}
+ set testdir [get_home $env]
+ }
+ set sub1 "sub1"
+ set sub2 "sub2"
+ cleanup $testdir $env
+ set txn ""
- error_check_good Subdb007:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
-
- puts "\tSubdb007.c: sub$subdb.db: close, open, and dump file"
- # Now, reopen the file and run the last test again.
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
- dump_file_direction "-first" "-next" sub$subdb.db
- if { [is_record_based $method] != 1 } {
- filesort $t1 $t3
+ puts "\tSubdb007.a.0: create subdb with default page size"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {$omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ #
+ # Figure out what the default page size is so that we can
+ # guarantee we create it with a different value.
+ set statret [$db stat]
+ set pgsz 0
+ foreach pair $statret {
+ set fld [lindex $pair 0]
+ if { [string compare $fld {Page size}] == 0 } {
+ set pgsz [lindex $pair 1]
}
+ }
+ error_check_good dbclose [$db close] 0
- error_check_good Subdb007:diff($t2,$t3) \
- [filecmp $t2 $t3] 0
-
- # Now, reopen the file and run the last test again in the
- # reverse direction.
- puts "\tSubdb007.d: sub$subdb.db:\
- close, open, and dump file in reverse direction"
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
- dump_file_direction "-last" "-prev" sub$subdb.db
+ if { $pgsz == 512 } {
+ set pgsz2 2048
+ } else {
+ set pgsz2 512
+ }
- if { [is_record_based $method] != 1 } {
- filesort $t1 $t3
+ puts "\tSubdb007.a.1: create 2nd subdb with specified page size"
+ set stat [catch {eval {berkdb_open_noerr -create -btree} \
+ $db2args {-pagesize $pgsz2 $testfile $sub2}} ret]
+ error_check_good subdb:pgsz $stat 1
+ error_check_good subdb:fail [is_substr $ret \
+ "Different pagesize specified"] 1
+
+ set ret [eval {berkdb dbremove} $envargs {$testfile}]
+
+ puts "\tSubdb007.b.0: create subdb with specified page size"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-pagesize $pgsz2 $omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ set statret [$db stat]
+ set newpgsz 0
+ foreach pair $statret {
+ set fld [lindex $pair 0]
+ if { [string compare $fld {Page size}] == 0 } {
+ set newpgsz [lindex $pair 1]
}
-
- error_check_good Subdb007:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
}
-}
-
-# Check function for Subdb007; keys and data are identical
-proc subdb007.check { key data } {
- error_check_good "key/data mismatch" $data $key
-}
+ error_check_good pgsize $pgsz2 $newpgsz
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSubdb007.b.1: create 2nd subdb with different page size"
+ set stat [catch {eval {berkdb_open_noerr -create -btree} \
+ $db2args {-pagesize $pgsz $testfile $sub2}} ret]
+ error_check_good subdb:pgsz $stat 1
+ error_check_good subdb:fail [is_substr $ret \
+ "Different pagesize specified"] 1
+
+ set ret [eval {berkdb dbremove} $envargs {$testfile}]
+
+ puts "\tSubdb007.c.0: create subdb with specified page size"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-pagesize $pgsz2 $omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSubdb007.c.1: create 2nd subdb with same specified page size"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-pagesize $pgsz2 $omethod $testfile $sub2}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
-proc subdb007_recno.check { key data } {
-global dict
-global kvals
- error_check_good key"$key"_exists [info exists kvals($key)] 1
- error_check_good "key/data mismatch, key $key" $data $kvals($key)
}
diff --git a/bdb/test/sdb008.tcl b/bdb/test/sdb008.tcl
index b005f00931a..1c46aed2087 100644
--- a/bdb/test/sdb008.tcl
+++ b/bdb/test/sdb008.tcl
@@ -1,20 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb008.tcl,v 11.14 2000/08/25 14:21:53 sue Exp $
-#
-# Sub DB Test 8 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Use a different or random lorder for each subdb.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
-proc subdb008 { method {nentries 10000} args } {
+# $Id: sdb008.tcl,v 11.25 2002/07/11 18:53:46 sandstro Exp $
+# TEST subdb008
+# TEST Tests lorder difference errors between subdbs.
+# TEST Test 3 different scenarios for lorder.
+# TEST 1. Create/open with specific lorder, 2nd subdb create with
+# TEST different one, should error.
+# TEST 2. Create/open with a default lorder 2nd subdb create with
+# TEST specified different one, should error.
+# TEST 3. Create/open with specified lorder, 2nd subdb create with
+# TEST same specified lorder, should succeed.
+# TEST (4th combo of using all defaults is a basic test, done elsewhere)
+proc subdb008 { method args } {
source ./include.tcl
- global rand_init
+ set db2args [convert_args -btree $args]
set args [convert_args $method $args]
set omethod [convert_method $method]
@@ -22,130 +25,97 @@ proc subdb008 { method {nentries 10000} args } {
puts "Subdb008: skipping for method $method"
return
}
-
- berkdb srand $rand_init
-
- puts "Subdb008: $method ($args) subdb lorder tests"
-
- # Create the database and open the dictionary
- set testfile $testdir/subdb008.db
- set t1 $testdir/t1
- set t2 $testdir/t2
- set t3 $testdir/t3
- set t4 $testdir/t4
- cleanup $testdir NULL
-
- set txn ""
- set pflags ""
- set gflags ""
-
- if { [is_record_based $method] == 1 } {
- set checkfunc subdb008_recno.check
+ set txnenv 0
+ set envargs ""
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb008.db
+ set env NULL
} else {
- set checkfunc subdb008.check
- }
- set nsubdbs 4
- set lo [list 4321 1234]
- puts "\tSubdb008.a: put/get loop"
- # Here is the loop where we put and get each key/data pair
- for { set i 0 } { $i < $nsubdbs } { incr i } {
- set subdb sub$i.db
- if { $i >= [llength $lo]} {
- set r [berkdb random_int 0 1]
- set order [lindex $lo $r]
- } else {
- set order [lindex $lo $i]
+ set testfile subdb008.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs "-env $env"
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append db2args " -auto_commit "
+ append envargs " -auto_commit "
}
- set db [eval {berkdb_open -create -mode 0644} \
- $args {-lorder $order $omethod $testfile $subdb}]
- set did [open $dict]
- set count 0
- while { [gets $did str] != -1 && $count < $nentries } {
- if { [is_record_based $method] == 1 } {
- global kvals
-
- set gflags "-recno"
- set key [expr $i * $nentries]
- set key [expr $key + $count + 1]
- set kvals($key) [pad_data $method $str]
- } else {
- set key $str
- }
- set ret [eval {$db put} \
- $txn $pflags {$key [chop_data $method $str]}]
- error_check_good put $ret 0
-
- set ret [eval {$db get} $gflags {$key}]
- error_check_good \
- get $ret [list [list $key [pad_data $method $str]]]
- incr count
- }
- close $did
- error_check_good db_close [$db close] 0
+ set testdir [get_home $env]
}
-
- # Now we will get each key from the DB and compare the results
- # to the original.
- for { set subdb 0 } { $subdb < $nsubdbs } { incr subdb } {
- puts "\tSubdb008.b: dump file sub$subdb.db"
- set db [berkdb_open -unknown $testfile sub$subdb.db]
- dump_file $db $txn $t1 $checkfunc
- error_check_good db_close [$db close] 0
-
- # Now compare the keys to see if they match the dictionary
- # (or ints)
- if { [is_record_based $method] == 1 } {
- set oid [open $t2 w]
- for {set i 1} {$i <= $nentries} {incr i} {
- puts $oid [expr $subdb * $nentries + $i]
- }
- close $oid
- file rename -force $t1 $t3
- } else {
- set q q
- filehead $nentries $dict $t3
- filesort $t3 $t2
- filesort $t1 $t3
- }
-
- error_check_good Subdb008:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
-
- puts "\tSubdb008.c: sub$subdb.db: close, open, and dump file"
- # Now, reopen the file and run the last test again.
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
- dump_file_direction "-first" "-next" sub$subdb.db
- if { [is_record_based $method] != 1 } {
- filesort $t1 $t3
- }
-
- error_check_good Subdb008:diff($t2,$t3) \
- [filecmp $t2 $t3] 0
-
- # Now, reopen the file and run the last test again in the
- # reverse direction.
- puts "\tSubdb008.d: sub$subdb.db:\
- close, open, and dump file in reverse direction"
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
- dump_file_direction "-last" "-prev" sub$subdb.db
-
- if { [is_record_based $method] != 1 } {
- filesort $t1 $t3
- }
-
- error_check_good Subdb008:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
+ puts "Subdb008: $method ($args) subdb tests with different lorders"
+
+ set sub1 "sub1"
+ set sub2 "sub2"
+ cleanup $testdir $env
+
+ puts "\tSubdb008.b.0: create subdb with specified lorder"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-lorder 4321 $omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ # Figure out what the default lorder is so that we can
+ # guarantee we create it with a different value later.
+ set is_swap [$db is_byteswapped]
+ if { $is_swap } {
+ set other 4321
+ } else {
+ set other 1234
}
-}
-
-# Check function for Subdb008; keys and data are identical
-proc subdb008.check { key data } {
- error_check_good "key/data mismatch" $data $key
-}
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSubdb008.b.1: create 2nd subdb with different lorder"
+ set stat [catch {eval {berkdb_open_noerr -create $omethod} \
+ $args {-lorder 1234 $testfile $sub2}} ret]
+ error_check_good subdb:lorder $stat 1
+ error_check_good subdb:fail [is_substr $ret \
+ "Different lorder specified"] 1
+
+ set ret [eval {berkdb dbremove} $envargs {$testfile}]
+
+ puts "\tSubdb008.c.0: create subdb with opposite specified lorder"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-lorder 1234 $omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSubdb008.c.1: create 2nd subdb with different lorder"
+ set stat [catch {eval {berkdb_open_noerr -create $omethod} \
+ $args {-lorder 4321 $testfile $sub2}} ret]
+ error_check_good subdb:lorder $stat 1
+ error_check_good subdb:fail [is_substr $ret \
+ "Different lorder specified"] 1
+
+ set ret [eval {berkdb dbremove} $envargs {$testfile}]
+
+ puts "\tSubdb008.d.0: create subdb with default lorder"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {$omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSubdb008.d.1: create 2nd subdb with different lorder"
+ set stat [catch {eval {berkdb_open_noerr -create -btree} \
+ $db2args {-lorder $other $testfile $sub2}} ret]
+ error_check_good subdb:lorder $stat 1
+ error_check_good subdb:fail [is_substr $ret \
+ "Different lorder specified"] 1
+
+ set ret [eval {berkdb dbremove} $envargs {$testfile}]
+
+ puts "\tSubdb008.e.0: create subdb with specified lorder"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-lorder $other $omethod $testfile $sub1}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSubdb008.e.1: create 2nd subdb with same specified lorder"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {-lorder $other $omethod $testfile $sub2}]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbclose [$db close] 0
-proc subdb008_recno.check { key data } {
-global dict
-global kvals
- error_check_good key"$key"_exists [info exists kvals($key)] 1
- error_check_good "key/data mismatch, key $key" $data $kvals($key)
}
diff --git a/bdb/test/sdb009.tcl b/bdb/test/sdb009.tcl
index 060bea643bb..4e4869643ef 100644
--- a/bdb/test/sdb009.tcl
+++ b/bdb/test/sdb009.tcl
@@ -1,15 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb009.tcl,v 11.4 2000/08/25 14:21:53 sue Exp $
+# $Id: sdb009.tcl,v 11.9 2002/07/11 18:53:46 sandstro Exp $
#
-# Subdatabase Test 9 (replacement)
-# Test the DB->rename method.
+# TEST subdb009
+# TEST Test DB->rename() method for subdbs
proc subdb009 { method args } {
global errorCode
source ./include.tcl
+
set omethod [convert_method $method]
set args [convert_args $method $args]
@@ -20,43 +21,72 @@ proc subdb009 { method args } {
return
}
- set file $testdir/subdb009.db
+ set txnenv 0
+ set envargs ""
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb009.db
+ set env NULL
+ } else {
+ set testfile subdb009.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append envargs " -auto_commit "
+ }
+ set testdir [get_home $env]
+ }
set oldsdb OLDDB
set newsdb NEWDB
# Make sure we're starting from a clean slate.
- cleanup $testdir NULL
- error_check_bad "$file exists" [file exists $file] 1
+ cleanup $testdir $env
+ error_check_bad "$testfile exists" [file exists $testfile] 1
puts "\tSubdb009.a: Create/rename file"
puts "\t\tSubdb009.a.1: create"
set db [eval {berkdb_open -create -mode 0644}\
- $omethod $args $file $oldsdb]
+ $omethod $args {$testfile $oldsdb}]
error_check_good dbopen [is_valid_db $db] TRUE
# The nature of the key and data are unimportant; use numeric key
# so record-based methods don't need special treatment.
+ set txn ""
set key 1
set data [pad_data $method data]
- error_check_good dbput [$db put $key $data] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ error_check_good dbput [eval {$db put} $txn {$key $data}] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good dbclose [$db close] 0
puts "\t\tSubdb009.a.2: rename"
- error_check_good rename_file [eval {berkdb dbrename} $file \
- $oldsdb $newsdb] 0
+ error_check_good rename_file [eval {berkdb dbrename} $envargs \
+ {$testfile $oldsdb $newsdb}] 0
puts "\t\tSubdb009.a.3: check"
# Open again with create to make sure we've really completely
# disassociated the subdb from the old name.
set odb [eval {berkdb_open -create -mode 0644}\
- $omethod $args $file $oldsdb]
+ $omethod $args $testfile $oldsdb]
error_check_good odb_open [is_valid_db $odb] TRUE
set odbt [$odb get $key]
error_check_good odb_close [$odb close] 0
set ndb [eval {berkdb_open -create -mode 0644}\
- $omethod $args $file $newsdb]
+ $omethod $args $testfile $newsdb]
error_check_good ndb_open [is_valid_db $ndb] TRUE
set ndbt [$ndb get $key]
error_check_good ndb_close [$ndb close] 0
@@ -69,7 +99,8 @@ proc subdb009 { method args } {
# Now there's both an old and a new. Rename the "new" to the "old"
# and make sure that fails.
puts "\tSubdb009.b: Make sure rename fails instead of overwriting"
- set ret [catch {eval {berkdb dbrename} $file $oldsdb $newsdb} res]
+ set ret [catch {eval {berkdb dbrename} $envargs $testfile \
+ $oldsdb $newsdb} res]
error_check_bad rename_overwrite $ret 0
error_check_good rename_overwrite_ret [is_substr $errorCode EEXIST] 1
diff --git a/bdb/test/sdb010.tcl b/bdb/test/sdb010.tcl
index 6bec78d372b..51f25976c56 100644
--- a/bdb/test/sdb010.tcl
+++ b/bdb/test/sdb010.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdb010.tcl,v 11.4 2000/08/25 14:21:53 sue Exp $
+# $Id: sdb010.tcl,v 11.14 2002/07/11 18:53:47 sandstro Exp $
#
-# Subdatabase Test 10 {access method}
-# Test of dbremove
+# TEST subdb010
+# TEST Test DB->remove() method and DB->truncate() for subdbs
proc subdb010 { method args } {
global errorCode
source ./include.tcl
@@ -14,33 +14,153 @@ proc subdb010 { method args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Subdb010: Test of DB->remove()"
+ puts "Subdb010: Test of DB->remove() and DB->truncate"
if { [is_queue $method] == 1 } {
puts "\tSubdb010: Skipping for method $method."
return
}
- cleanup $testdir NULL
+ set txnenv 0
+ set envargs ""
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb010.db
+ set tfpath $testfile
+ set env NULL
+ } else {
+ set testfile subdb010.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append envargs " -auto_commit "
+ }
+ set testdir [get_home $env]
+ set tfpath $testdir/$testfile
+ }
+ cleanup $testdir $env
- set testfile $testdir/subdb010.db
+ set txn ""
set testdb DATABASE
+ set testdb2 DATABASE2
- set db [eval {berkdb_open -create -truncate -mode 0644} $omethod \
+ set db [eval {berkdb_open -create -mode 0644} $omethod \
$args $testfile $testdb]
error_check_good db_open [is_valid_db $db] TRUE
error_check_good db_close [$db close] 0
- error_check_good file_exists_before [file exists $testfile] 1
- error_check_good db_remove [berkdb dbremove $testfile $testdb] 0
+ puts "\tSubdb010.a: Test of DB->remove()"
+ error_check_good file_exists_before [file exists $tfpath] 1
+ error_check_good db_remove [eval {berkdb dbremove} $envargs \
+ $testfile $testdb] 0
# File should still exist.
- error_check_good file_exists_after [file exists $testfile] 1
+ error_check_good file_exists_after [file exists $tfpath] 1
# But database should not.
set ret [catch {eval berkdb_open $omethod $args $testfile $testdb} res]
error_check_bad open_failed ret 0
error_check_good open_failed_ret [is_substr $errorCode ENOENT] 1
+ puts "\tSubdb010.b: Setup for DB->truncate()"
+ # The nature of the key and data are unimportant; use numeric key
+ # so record-based methods don't need special treatment.
+ set key1 1
+ set key2 2
+ set data1 [pad_data $method data1]
+ set data2 [pad_data $method data2]
+
+ set db [eval {berkdb_open -create -mode 0644} $omethod \
+ $args {$testfile $testdb}]
+ error_check_good db_open [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ error_check_good dbput [eval {$db put} $txn {$key1 $data1}] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ set db2 [eval {berkdb_open -create -mode 0644} $omethod \
+ $args $testfile $testdb2]
+ error_check_good db_open [is_valid_db $db2] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ error_check_good dbput [eval {$db2 put} $txn {$key2 $data2}] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ error_check_good db_close [$db close] 0
+ error_check_good db_close [$db2 close] 0
+
+ puts "\tSubdb010.c: truncate"
+ #
+ # Return value should be 1, the count of how many items were
+ # destroyed when we truncated.
+ set db [eval {berkdb_open -create -mode 0644} $omethod \
+ $args $testfile $testdb]
+ error_check_good db_open [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ error_check_good trunc_subdb [eval {$db truncate} $txn] 1
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ puts "\tSubdb010.d: check"
+ set db [eval {berkdb_open} $args {$testfile $testdb}]
+ error_check_good db_open [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+ set kd [$dbc get -first]
+ error_check_good trunc_dbcget [llength $kd] 0
+ error_check_good dbcclose [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ set db2 [eval {berkdb_open} $args {$testfile $testdb2}]
+ error_check_good db_open [is_valid_db $db2] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db2 cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db2] TRUE
+ set kd [$dbc get -first]
+ error_check_bad notrunc_dbcget1 [llength $kd] 0
+ set db2kd [list [list $key2 $data2]]
+ error_check_good key2 $kd $db2kd
+ set kd [$dbc get -next]
+ error_check_good notrunc_dbget2 [llength $kd] 0
+ error_check_good dbcclose [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ error_check_good db_close [$db close] 0
+ error_check_good db_close [$db2 close] 0
puts "\tSubdb010 succeeded."
}
diff --git a/bdb/test/sdb011.tcl b/bdb/test/sdb011.tcl
new file mode 100644
index 00000000000..862e32f73ed
--- /dev/null
+++ b/bdb/test/sdb011.tcl
@@ -0,0 +1,143 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: sdb011.tcl,v 11.9 2002/07/11 18:53:47 sandstro Exp $
+#
+# TEST subdb011
+# TEST Test deleting Subdbs with overflow pages
+# TEST Create 1 db with many large subdbs.
+# TEST Test subdatabases with overflow pages.
+proc subdb011 { method {ndups 13} {nsubdbs 10} args} {
+ global names
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ if { [is_queue $method] == 1 || [is_fixed_length $method] == 1 } {
+ puts "Subdb011: skipping for method $method"
+ return
+ }
+ set txnenv 0
+ set envargs ""
+ set max_files 0
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/subdb011.db
+ set env NULL
+ set tfpath $testfile
+ } else {
+ set testfile subdb011.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set envargs " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ append envargs " -auto_commit "
+ set max_files 50
+ if { $ndups == 13 } {
+ set ndups 7
+ }
+ }
+ set testdir [get_home $env]
+ set tfpath $testdir/$testfile
+ }
+
+ # Create the database and open the dictionary
+
+ cleanup $testdir $env
+ set txn ""
+
+ # Here is the loop where we put and get each key/data pair
+ set file_list [get_file_list]
+ if { $max_files != 0 && [llength $file_list] > $max_files } {
+ set fend [expr $max_files - 1]
+ set file_list [lrange $file_list 0 $fend]
+ }
+ set flen [llength $file_list]
+ puts "Subdb011: $method ($args) $ndups overflow dups with \
+ $flen filename=key filecontents=data pairs"
+
+ puts "\tSubdb011.a: Create each of $nsubdbs subdbs and dups"
+ set slist {}
+ set i 0
+ set count 0
+ foreach f $file_list {
+ set i [expr $i % $nsubdbs]
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ set names([expr $count + 1]) $f
+ } else {
+ set key $f
+ }
+ # Should really catch errors
+ set fid [open $f r]
+ fconfigure $fid -translation binary
+ set filecont [read $fid]
+ set subdb subdb$i
+ lappend slist $subdb
+ close $fid
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {$omethod $testfile $subdb}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ for {set dup 0} {$dup < $ndups} {incr dup} {
+ set data $dup:$filecont
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key \
+ [chop_data $method $data]}]
+ error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ }
+ error_check_good dbclose [$db close] 0
+ incr i
+ incr count
+ }
+
+ puts "\tSubdb011.b: Verify overflow pages"
+ foreach subdb $slist {
+ set db [eval {berkdb_open -create -mode 0644} \
+ $args {$omethod $testfile $subdb}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set stat [$db stat]
+
+ # What everyone else calls overflow pages, hash calls "big
+ # pages", so we need to special-case hash here. (Hash
+ # overflow pages are additional pages after the first in a
+ # bucket.)
+ if { [string compare [$db get_type] hash] == 0 } {
+ error_check_bad overflow \
+ [is_substr $stat "{{Number of big pages} 0}"] 1
+ } else {
+ error_check_bad overflow \
+ [is_substr $stat "{{Overflow pages} 0}"] 1
+ }
+ error_check_good dbclose [$db close] 0
+ }
+
+ puts "\tSubdb011.c: Delete subdatabases"
+ for {set i $nsubdbs} {$i > 0} {set i [expr $i - 1]} {
+ #
+ # Randomly delete a subdatabase
+ set sindex [berkdb random_int 0 [expr $i - 1]]
+ set subdb [lindex $slist $sindex]
+ #
+ # Delete the one we did from the list
+ set slist [lreplace $slist $sindex $sindex]
+ error_check_good file_exists_before [file exists $tfpath] 1
+ error_check_good db_remove [eval {berkdb dbremove} $envargs \
+ {$testfile $subdb}] 0
+ }
+}
+
diff --git a/bdb/test/sdb012.tcl b/bdb/test/sdb012.tcl
new file mode 100644
index 00000000000..9c05d977daf
--- /dev/null
+++ b/bdb/test/sdb012.tcl
@@ -0,0 +1,428 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: sdb012.tcl,v 1.3 2002/08/08 15:38:10 bostic Exp $
+#
+# TEST subdb012
+# TEST Test subdbs with locking and transactions
+# TEST Tests creating and removing subdbs while handles
+# TEST are open works correctly, and in the face of txns.
+#
+proc subdb012 { method args } {
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ if { [is_queue $method] == 1 } {
+ puts "Subdb012: skipping for method $method"
+ return
+ }
+
+ # If we are using an env, then skip this test. It needs its own.
+ set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $args $eindex]
+ puts "Subdb012 skipping for env $env"
+ return
+ }
+ set encargs ""
+ set largs [split_encargs $args encargs]
+
+ puts "Subdb012: $method ($largs $encargs) subdb txn/locking tests"
+
+ #
+ # sdb012_body takes a txn list containing 4 elements.
+ # {txn command for first subdb
+ # txn command for second subdb
+ # txn command for first subdb removal
+ # txn command for second subdb removal}
+ #
+ # The allowed commands are 'none' 'one', 'auto', 'abort', 'commit'.
+ # 'none' is a special case meaning run without a txn. In the
+ # case where all 4 items are 'none', we run in a lock-only env.
+ # 'one' is a special case meaning we create the subdbs together
+ # in one single transaction. It is indicated as the value for t1,
+ # and the value in t2 indicates if that single txn should be
+ # aborted or committed. It is not used and has no meaning
+ # in the removal case. 'auto' means use the -auto_commit flag
+ # to the operation, and 'abort' and 'commit' do the obvious.
+ #
+ # First test locking w/o txns. If any in tlist are 'none',
+ # all must be none.
+ #
+ # Now run through the txn-based operations
+ set count 0
+ set sdb "Subdb012."
+ set teststr "abcdefghijklmnopqrstuvwxyz"
+ set testlet [split $teststr {}]
+ foreach t1 { none one abort auto commit } {
+ foreach t2 { none abort auto commit } {
+ if { $t1 == "one" } {
+ if { $t2 == "none" || $t2 == "auto"} {
+ continue
+ }
+ }
+ set tlet [lindex $testlet $count]
+ foreach r1 { none abort auto commit } {
+ foreach r2 { none abort auto commit } {
+ set tlist [list $t1 $t2 $r1 $r2]
+ sdb012_body $testdir $omethod $largs \
+ $encargs $sdb$tlet $tlist
+ }
+ }
+ incr count
+ }
+ }
+
+}
+
+proc s012 { method args } {
+ source ./include.tcl
+
+ set omethod [convert_method $method]
+
+ set encargs ""
+ set largs ""
+
+ puts "Subdb012: $method ($largs $encargs) subdb txn/locking tests"
+
+ set sdb "Subdb012."
+ set tlet X
+ set tlist $args
+ error_check_good tlist [llength $tlist] 4
+ sdb012_body $testdir $omethod $largs $encargs $sdb$tlet $tlist
+}
+
+#
+# This proc checks the tlist values and returns the flags
+# that should be used when opening the env. If we are running
+# with no txns, then just -lock, otherwise -txn.
+#
+proc sdb012_subsys { tlist } {
+ set t1 [lindex $tlist 0]
+ #
+ # If we have no txns, all elements of the list should be none.
+ # In that case we only run with locking turned on.
+ # Otherwise, we use the full txn subsystems.
+ #
+ set allnone {none none none none}
+ if { $allnone == $tlist } {
+ set subsys "-lock"
+ } else {
+ set subsys "-txn"
+ }
+ return $subsys
+}
+
+#
+# This proc parses the tlist and returns a list of 4 items that
+# should be used in operations. I.e. it will begin the txns as
+# needed, or return a -auto_commit flag, etc.
+#
+proc sdb012_tflags { env tlist } {
+ set ret ""
+ set t1 ""
+ foreach t $tlist {
+ switch $t {
+ one {
+ set t1 [$env txn]
+ error_check_good txnbegin [is_valid_txn $t1 $env] TRUE
+ lappend ret "-txn $t1"
+ lappend ret "-txn $t1"
+ }
+ auto {
+ lappend ret "-auto_commit"
+ }
+ abort -
+ commit {
+ #
+ # If the previous command was a "one", skip over
+ # this commit/abort. Otherwise start a new txn
+ # for the removal case.
+ #
+ if { $t1 == "" } {
+ set txn [$env txn]
+ error_check_good txnbegin [is_valid_txn $txn \
+ $env] TRUE
+ lappend ret "-txn $txn"
+ } else {
+ set t1 ""
+ }
+ }
+ none {
+ lappend ret ""
+ }
+ default {
+ error "Txn command $t not implemented"
+ }
+ }
+ }
+ return $ret
+}
+
+#
+# This proc parses the tlist and returns a list of 4 items that
+# should be used in the txn conclusion operations. I.e. it will
+# give "" if using auto_commit (i.e. no final txn op), or a single
+# abort/commit if both subdb's are in one txn.
+#
+proc sdb012_top { tflags tlist } {
+ set ret ""
+ set t1 ""
+ #
+ # We know both lists have 4 items. Iterate over them
+ # using multiple value lists so we know which txn goes
+ # with each op.
+ #
+ # The tflags list is needed to extract the txn command
+ # out for the operation. The tlist list is needed to
+ # determine what operation we are doing.
+ #
+ foreach t $tlist tf $tflags {
+ switch $t {
+ one {
+ set t1 [lindex $tf 1]
+ }
+ auto {
+ lappend ret "sdb012_nop"
+ }
+ abort -
+ commit {
+ #
+ # If the previous command was a "one" (i.e. t1
+ # is set), append a correct command and then
+ # an empty one.
+ #
+ if { $t1 == "" } {
+ set txn [lindex $tf 1]
+ set top "$txn $t"
+ lappend ret $top
+ } else {
+ set top "$t1 $t"
+ lappend ret "sdb012_nop"
+ lappend ret $top
+ set t1 ""
+ }
+ }
+ none {
+ lappend ret "sdb012_nop"
+ }
+ }
+ }
+ return $ret
+}
+
+proc sdb012_nop { } {
+ return 0
+}
+
+proc sdb012_isabort { tlist item } {
+ set i [lindex $tlist $item]
+ if { $i == "one" } {
+ set i [lindex $tlist [expr $item + 1]]
+ }
+ if { $i == "abort" } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc sdb012_body { testdir omethod largs encargs msg tlist } {
+
+ puts "\t$msg: $tlist"
+ set testfile subdb012.db
+ set subdb1 sub1
+ set subdb2 sub2
+
+ set subsys [sdb012_subsys $tlist]
+ env_cleanup $testdir
+ set env [eval {berkdb_env -create -home} $testdir $subsys $encargs]
+ error_check_good dbenv [is_valid_env $env] TRUE
+ error_check_good test_lock [$env test abort subdb_lock] 0
+
+ #
+ # Convert from our tlist txn commands into real flags we
+ # will pass to commands. Use the multiple values feature
+ # of foreach to do this efficiently.
+ #
+ set tflags [sdb012_tflags $env $tlist]
+ foreach {txn1 txn2 rem1 rem2} $tflags {break}
+ foreach {top1 top2 rop1 rop2} [sdb012_top $tflags $tlist] {break}
+
+# puts "txn1 $txn1, txn2 $txn2, rem1 $rem1, rem2 $rem2"
+# puts "top1 $top1, top2 $top2, rop1 $rop1, rop2 $rop2"
+ puts "\t$msg.0: Create sub databases in env with $subsys"
+ set s1 [eval {berkdb_open -env $env -create -mode 0644} \
+ $largs $txn1 {$omethod $testfile $subdb1}]
+ error_check_good dbopen [is_valid_db $s1] TRUE
+
+ set ret [eval $top1]
+ error_check_good t1_end $ret 0
+
+ set s2 [eval {berkdb_open -env $env -create -mode 0644} \
+ $largs $txn2 {$omethod $testfile $subdb2}]
+ error_check_good dbopen [is_valid_db $s2] TRUE
+
+ puts "\t$msg.1: Subdbs are open; resolve txns if necessary"
+ set ret [eval $top2]
+ error_check_good t2_end $ret 0
+
+ set t1_isabort [sdb012_isabort $tlist 0]
+ set t2_isabort [sdb012_isabort $tlist 1]
+ set r1_isabort [sdb012_isabort $tlist 2]
+ set r2_isabort [sdb012_isabort $tlist 3]
+
+# puts "t1_isabort $t1_isabort, t2_isabort $t2_isabort, r1_isabort $r1_isabort, r2_isabort $r2_isabort"
+
+ puts "\t$msg.2: Subdbs are open; verify removal failures"
+ # Verify removes of subdbs with open subdb's fail
+ #
+ # We should fail no matter what. If we aborted, then the
+ # subdb should not exist. If we didn't abort, we should fail
+ # with DB_LOCK_NOTGRANTED.
+ #
+ # XXX - Do we need -auto_commit for all these failing ones?
+ set r [ catch {berkdb dbremove -env $env $testfile $subdb1} result ]
+ error_check_bad dbremove1_open $r 0
+ if { $t1_isabort } {
+ error_check_good dbremove1_open_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbremove1_open [is_substr \
+ $result DB_LOCK_NOTGRANTED] 1
+ }
+
+ set r [ catch {berkdb dbremove -env $env $testfile $subdb2} result ]
+ error_check_bad dbremove2_open $r 0
+ if { $t2_isabort } {
+ error_check_good dbremove2_open_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbremove2_open [is_substr \
+ $result DB_LOCK_NOTGRANTED] 1
+ }
+
+ # Verify file remove fails
+ set r [catch {berkdb dbremove -env $env $testfile} result]
+ error_check_bad dbremovef_open $r 0
+
+ #
+ # If both aborted, there should be no file??
+ #
+ if { $t1_isabort && $t2_isabort } {
+ error_check_good dbremovef_open_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbremovef_open [is_substr \
+ $result DB_LOCK_NOTGRANTED] 1
+ }
+
+ puts "\t$msg.3: Close subdb2; verify removals"
+ error_check_good close_s2 [$s2 close] 0
+ set r [ catch {eval {berkdb dbremove -env} \
+ $env $rem2 $testfile $subdb2} result ]
+ if { $t2_isabort } {
+ error_check_bad dbrem2_ab $r 0
+ error_check_good dbrem2_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbrem2 $result 0
+ }
+ # Resolve subdb2 removal txn
+ set r [eval $rop2]
+ error_check_good rop2 $r 0
+
+ set r [ catch {berkdb dbremove -env $env $testfile $subdb1} result ]
+ error_check_bad dbremove1.2_open $r 0
+ if { $t1_isabort } {
+ error_check_good dbremove1.2_open_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbremove1.2_open [is_substr \
+ $result DB_LOCK_NOTGRANTED] 1
+ }
+
+ # There are three cases here:
+ # 1. if both t1 and t2 aborted, the file shouldn't exist
+ # 2. if only t1 aborted, the file still exists and nothing is open
+ # 3. if neither aborted a remove should fail because the first
+ # subdb is still open
+ # In case 2, don't try the remove, because it should succeed
+ # and we won't be able to test anything else.
+ if { !$t1_isabort || $t2_isabort } {
+ set r [catch {berkdb dbremove -env $env $testfile} result]
+ if { $t1_isabort && $t2_isabort } {
+ error_check_bad dbremovef.2_open $r 0
+ error_check_good dbremove.2_open_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_bad dbremovef.2_open $r 0
+ error_check_good dbremove.2_open [is_substr \
+ $result DB_LOCK_NOTGRANTED] 1
+ }
+ }
+
+ puts "\t$msg.4: Close subdb1; verify removals"
+ error_check_good close_s1 [$s1 close] 0
+ set r [ catch {eval {berkdb dbremove -env} \
+ $env $rem1 $testfile $subdb1} result ]
+ if { $t1_isabort } {
+ error_check_bad dbremove1_ab $r 0
+ error_check_good dbremove1_ab [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbremove1 $result 0
+ }
+ # Resolve subdb1 removal txn
+ set r [eval $rop1]
+ error_check_good rop1 $r 0
+
+
+ # Verify removal of subdb2. All DB handles are closed now.
+ # So we have two scenarios:
+ # 1. The removal of subdb2 above was successful and subdb2
+ # doesn't exist and we should fail that way.
+ # 2. The removal of subdb2 above was aborted, and this
+ # removal should succeed.
+ #
+ set r [ catch {berkdb dbremove -env $env $testfile $subdb2} result ]
+ if { $r2_isabort && !$t2_isabort } {
+ error_check_good dbremove2.1_ab $result 0
+ } else {
+ error_check_bad dbremove2.1 $r 0
+ error_check_good dbremove2.1 [is_substr \
+ $result "no such file"] 1
+ }
+
+ # Verify removal of subdb1. All DB handles are closed now.
+ # So we have two scenarios:
+ # 1. The removal of subdb1 above was successful and subdb1
+ # doesn't exist and we should fail that way.
+ # 2. The removal of subdb1 above was aborted, and this
+ # removal should succeed.
+ #
+ set r [ catch {berkdb dbremove -env $env $testfile $subdb1} result ]
+ if { $r1_isabort && !$t1_isabort } {
+ error_check_good dbremove1.1 $result 0
+ } else {
+ error_check_bad dbremove_open $r 0
+ error_check_good dbremove.1 [is_substr \
+ $result "no such file"] 1
+ }
+
+ puts "\t$msg.5: All closed; remove file"
+ set r [catch {berkdb dbremove -env $env $testfile} result]
+ if { $t1_isabort && $t2_isabort } {
+ error_check_bad dbremove_final_ab $r 0
+ error_check_good dbremove_file_abstr [is_substr \
+ $result "no such file"] 1
+ } else {
+ error_check_good dbremove_final $r 0
+ }
+ error_check_good envclose [$env close] 0
+}
diff --git a/bdb/test/sdbscript.tcl b/bdb/test/sdbscript.tcl
index 1b099520e88..d1978ccb048 100644
--- a/bdb/test/sdbscript.tcl
+++ b/bdb/test/sdbscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdbscript.tcl,v 11.7 2000/04/21 18:36:23 krinsky Exp $
+# $Id: sdbscript.tcl,v 11.9 2002/01/11 15:53:36 bostic Exp $
#
# Usage: subdbscript testfile subdbnumber factor
# testfile: name of DB itself
diff --git a/bdb/test/sdbtest001.tcl b/bdb/test/sdbtest001.tcl
index e3ff2b032d3..b8b4508c2a4 100644
--- a/bdb/test/sdbtest001.tcl
+++ b/bdb/test/sdbtest001.tcl
@@ -1,18 +1,26 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdbtest001.tcl,v 11.13 2000/08/25 14:21:53 sue Exp $
+# $Id: sdbtest001.tcl,v 11.19 2002/05/22 15:42:42 sue Exp $
#
-# Sub DB All-Method Test 1
-# Make several subdb's of different access methods all in one DB.
-# Rotate methods and repeat [#762].
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
-proc subdbtest001 { {nentries 10000} } {
+# TEST sdbtest001
+# TEST Tests multiple access methods in one subdb
+# TEST Open several subdbs, each with a different access method
+# TEST Small keys, small data
+# TEST Put/get per key per subdb
+# TEST Dump file, verify per subdb
+# TEST Close, reopen per subdb
+# TEST Dump file, verify per subdb
+# TEST
+# TEST Make several subdb's of different access methods all in one DB.
+# TEST Rotate methods and repeat [#762].
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Close file, reopen, do retrieve and re-verify.
+proc sdbtest001 { {nentries 10000} } {
source ./include.tcl
puts "Subdbtest001: many different subdb access methods in one"
@@ -41,16 +49,25 @@ proc subdbtest001 { {nentries 10000} } {
lappend method_list [list "-btree" "-rbtree" "-ddbtree" "-dbtree"]
lappend method_list [list "-dbtree" "-ddbtree" "-btree" "-rbtree"]
lappend method_list [list "-ddbtree" "-dbtree" "-rbtree" "-btree"]
+ set plist [list 512 8192 1024 4096 2048 16384]
+ set mlen [llength $method_list]
+ set plen [llength $plist]
+ while { $plen < $mlen } {
+ set plist [concat $plist $plist]
+ set plen [llength $plist]
+ }
+ set pgsz 0
foreach methods $method_list {
cleanup $testdir NULL
puts "\tSubdbtest001.a: create subdbs of different access methods:"
puts "\tSubdbtest001.a: $methods"
- set psize {8192 4096}
set nsubdbs [llength $methods]
set duplist ""
for { set i 0 } { $i < $nsubdbs } { incr i } {
lappend duplist -1
}
+ set psize [lindex $plist $pgsz]
+ incr pgsz
set newent [expr $nentries / $nsubdbs]
build_all_subdb $testfile $methods $psize $duplist $newent
@@ -95,7 +112,7 @@ proc subdbtest001 { {nentries 10000} } {
puts "\tSubdbtest001.c: sub$subdb.db: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile NULL $t1 $checkfunc \
dump_file_direction "-first" "-next" sub$subdb.db
if { [string compare $method "-recno"] != 0 } {
filesort $t1 $t3
@@ -107,7 +124,7 @@ proc subdbtest001 { {nentries 10000} } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tSubdbtest001.d: sub$subdb.db: close, open, and dump file in reverse direction"
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile NULL $t1 $checkfunc \
dump_file_direction "-last" "-prev" sub$subdb.db
if { [string compare $method "-recno"] != 0 } {
diff --git a/bdb/test/sdbtest002.tcl b/bdb/test/sdbtest002.tcl
index b8bad4e70e1..95717413a7b 100644
--- a/bdb/test/sdbtest002.tcl
+++ b/bdb/test/sdbtest002.tcl
@@ -1,19 +1,30 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdbtest002.tcl,v 11.19 2000/08/25 14:21:53 sue Exp $
+# $Id: sdbtest002.tcl,v 11.26 2002/09/05 17:23:07 sandstro Exp $
#
-# Sub DB All-Method Test 2
-# Make several subdb's of different access methods all in one DB.
-# Fork of some child procs to each manipulate one subdb and when
-# they are finished, verify the contents of the databases.
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
-proc subdbtest002 { {nentries 10000} } {
+# TEST sdbtest002
+# TEST Tests multiple access methods in one subdb access by multiple
+# TEST processes.
+# TEST Open several subdbs, each with a different access method
+# TEST Small keys, small data
+# TEST Put/get per key per subdb
+# TEST Fork off several child procs to each delete selected
+# TEST data from their subdb and then exit
+# TEST Dump file, verify contents of each subdb is correct
+# TEST Close, reopen per subdb
+# TEST Dump file, verify per subdb
+# TEST
+# TEST Make several subdb's of different access methods all in one DB.
+# TEST Fork of some child procs to each manipulate one subdb and when
+# TEST they are finished, verify the contents of the databases.
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Close file, reopen, do retrieve and re-verify.
+proc sdbtest002 { {nentries 10000} } {
source ./include.tcl
puts "Subdbtest002: many different subdb access methods in one"
@@ -34,7 +45,7 @@ proc subdbtest002 { {nentries 10000} } {
cleanup $testdir NULL
puts "\tSubdbtest002.a: create subdbs of different access methods:"
puts "\t\t$methods"
- set psize {8192 4096}
+ set psize 4096
set nsubdbs [llength $methods]
set duplist ""
for { set i 0 } { $i < $nsubdbs } { incr i } {
@@ -65,7 +76,7 @@ proc subdbtest002 { {nentries 10000} } {
$testdir/subdb002.log.$subdb $testfile $subdb $nsubdbs &]
lappend pidlist $p
}
- watch_procs 5
+ watch_procs $pidlist 5
for { set subdb 0 } { $subdb < $nsubdbs } { incr subdb } {
set method [lindex $methods $subdb]
@@ -124,7 +135,7 @@ proc subdbtest002 { {nentries 10000} } {
puts "\tSubdbtest002.c: sub$subdb.db: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile NULL $t1 $checkfunc \
dump_file_direction "-first" "-next" sub$subdb.db
if { [string compare $method "-recno"] != 0 } {
filesort $t1 $t3
@@ -136,7 +147,7 @@ proc subdbtest002 { {nentries 10000} } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tSubdbtest002.d: sub$subdb.db: close, open, and dump file in reverse direction"
- open_and_dump_subfile $testfile NULL $txn $t1 $checkfunc \
+ open_and_dump_subfile $testfile NULL $t1 $checkfunc \
dump_file_direction "-last" "-prev" sub$subdb.db
if { [string compare $method "-recno"] != 0 } {
diff --git a/bdb/test/sdbutils.tcl b/bdb/test/sdbutils.tcl
index 0cb33b28649..3221a422e18 100644
--- a/bdb/test/sdbutils.tcl
+++ b/bdb/test/sdbutils.tcl
@@ -1,21 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sdbutils.tcl,v 11.9 2000/05/22 12:51:38 bostic Exp $
+# $Id: sdbutils.tcl,v 11.14 2002/06/10 15:39:39 sue Exp $
#
proc build_all_subdb { dbname methods psize dups {nentries 100} {dbargs ""}} {
set nsubdbs [llength $dups]
- set plen [llength $psize]
set mlen [llength $methods]
set savearg $dbargs
for {set i 0} {$i < $nsubdbs} { incr i } {
set m [lindex $methods [expr $i % $mlen]]
set dbargs $savearg
- set p [lindex $psize [expr $i % $plen]]
subdb_build $dbname $nentries [lindex $dups $i] \
- $i $m $p sub$i.db $dbargs
+ $i $m $psize sub$i.db $dbargs
}
}
@@ -27,6 +25,13 @@ proc subdb_build { name nkeys ndups dup_interval method psize subdb dbargs} {
puts "Method: $method"
+ set txnenv 0
+ set eindex [lsearch -exact $dbargs "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $dbargs $eindex]
+ set txnenv [is_txnenv $env]
+ }
# Create the database and open the dictionary
set oflags "-create -mode 0644 $omethod \
-pagesize $psize $dbargs $name $subdb"
@@ -54,16 +59,32 @@ proc subdb_build { name nkeys ndups dup_interval method psize subdb dbargs} {
}
}
}
+ set txn ""
for { set count 0 } { [gets $did str] != -1 && $count < $nkeys } {
incr count} {
for { set i 0 } { $i < $ndups } { incr i } {
set data [format "%04d" [expr $i * $dup_interval]]
- set ret [$db put $str [chop_data $method $data]]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$str \
+ [chop_data $method $data]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
if { $ndups == 0 } {
- set ret [$db put $str [chop_data $method NODUP]]
+ set ret [eval {$db put} $txn {$str \
+ [chop_data $method NODUP]}]
error_check_good put $ret 0
} elseif { $ndups < 0 } {
if { [is_record_based $method] == 1 } {
@@ -71,33 +92,38 @@ proc subdb_build { name nkeys ndups dup_interval method psize subdb dbargs} {
set num [expr $nkeys * $dup_interval]
set num [expr $num + $count + 1]
- set ret [$db put $num [chop_data $method $str]]
+ set ret [eval {$db put} $txn {$num \
+ [chop_data $method $str]}]
set kvals($num) [pad_data $method $str]
error_check_good put $ret 0
} else {
- set ret [$db put $str [chop_data $method $str]]
+ set ret [eval {$db put} $txn \
+ {$str [chop_data $method $str]}]
error_check_good put $ret 0
}
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
close $did
error_check_good close:$name [$db close] 0
}
-proc do_join_subdb { db primary subdbs key } {
+proc do_join_subdb { db primary subdbs key oargs } {
source ./include.tcl
puts "\tJoining: $subdbs on $key"
# Open all the databases
- set p [berkdb_open -unknown $db $primary]
+ set p [eval {berkdb_open -unknown} $oargs $db $primary]
error_check_good "primary open" [is_valid_db $p] TRUE
set dblist ""
set curslist ""
foreach i $subdbs {
- set jdb [berkdb_open -unknown $db sub$i.db]
+ set jdb [eval {berkdb_open -unknown} $oargs $db sub$i.db]
error_check_good "sub$i.db open" [is_valid_db $jdb] TRUE
lappend jlist [list $jdb $key]
diff --git a/bdb/test/sec001.tcl b/bdb/test/sec001.tcl
new file mode 100644
index 00000000000..eb4bcc24dd2
--- /dev/null
+++ b/bdb/test/sec001.tcl
@@ -0,0 +1,205 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2001
+# Sleepycat Software. All rights reserved.
+#
+# $Id: sec001.tcl,v 11.7 2002/05/31 16:19:30 sue Exp $
+#
+# TEST sec001
+# TEST Test of security interface
+proc sec001 { } {
+ global errorInfo
+ global errorCode
+
+ source ./include.tcl
+
+ set testfile1 env1.db
+ set testfile2 $testdir/env2.db
+ set subdb1 sub1
+ set subdb2 sub2
+
+ puts "Sec001: Test of basic encryption interface."
+ env_cleanup $testdir
+
+ set passwd1 "passwd1"
+ set passwd1_bad "passwd1_bad"
+ set passwd2 "passwd2"
+ set key "key"
+ set data "data"
+
+ #
+ # This first group tests bad create scenarios and also
+ # tests attempting to use encryption after creating a
+ # non-encrypted env/db to begin with.
+ #
+ set nopass ""
+ puts "\tSec001.a.1: Create db with encryption."
+ set db [berkdb_open -create -encryptaes $passwd1 -btree $testfile2]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSec001.a.2: Open db without encryption."
+ set stat [catch {berkdb_open_noerr $testfile2} ret]
+ error_check_good db:nocrypto $stat 1
+ error_check_good db:fail [is_substr $ret "no encryption key"] 1
+
+ set ret [berkdb dbremove -encryptaes $passwd1 $testfile2]
+
+ puts "\tSec001.b.1: Create db without encryption or checksum."
+ set db [berkdb_open -create -btree $testfile2]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSec001.b.2: Open db with encryption."
+ set stat [catch {berkdb_open_noerr -encryptaes $passwd1 $testfile2} ret]
+ error_check_good db:nocrypto $stat 1
+ error_check_good db:fail [is_substr $ret "supplied encryption key"] 1
+
+ set ret [berkdb dbremove $testfile2]
+
+ puts "\tSec001.c.1: Create db with checksum."
+ set db [berkdb_open -create -chksum -btree $testfile2]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSec001.c.2: Open db with encryption."
+ set stat [catch {berkdb_open_noerr -encryptaes $passwd1 $testfile2} ret]
+ error_check_good db:nocrypto $stat 1
+ error_check_good db:fail [is_substr $ret "supplied encryption key"] 1
+
+ set ret [berkdb dbremove $testfile2]
+
+ puts "\tSec001.d.1: Create subdb with encryption."
+ set db [berkdb_open -create -encryptaes $passwd1 -btree \
+ $testfile2 $subdb1]
+ error_check_good subdb [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSec001.d.2: Create 2nd subdb without encryption."
+ set stat [catch {berkdb_open_noerr -create -btree \
+ $testfile2 $subdb2} ret]
+ error_check_good subdb:nocrypto $stat 1
+ error_check_good subdb:fail [is_substr $ret "no encryption key"] 1
+
+ set ret [berkdb dbremove -encryptaes $passwd1 $testfile2]
+
+ puts "\tSec001.e.1: Create subdb without encryption or checksum."
+ set db [berkdb_open -create -btree $testfile2 $subdb1]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSec001.e.2: Create 2nd subdb with encryption."
+ set stat [catch {berkdb_open_noerr -create -btree -encryptaes $passwd1 \
+ $testfile2 $subdb2} ret]
+ error_check_good subdb:nocrypto $stat 1
+ error_check_good subdb:fail [is_substr $ret "supplied encryption key"] 1
+
+ env_cleanup $testdir
+
+ puts "\tSec001.f.1: Open env with encryption, empty passwd."
+ set stat [catch {berkdb_env_noerr -create -home $testdir \
+ -encryptaes $nopass} ret]
+ error_check_good env:nopass $stat 1
+ error_check_good env:fail [is_substr $ret "Empty password"] 1
+
+ puts "\tSec001.f.2: Create without encryption algorithm (DB_ENCRYPT_ANY)."
+ set stat [catch {berkdb_env_noerr -create -home $testdir \
+ -encryptany $passwd1} ret]
+ error_check_good env:any $stat 1
+ error_check_good env:fail [is_substr $ret "algorithm not supplied"] 1
+
+ puts "\tSec001.f.3: Create without encryption."
+ set env [berkdb_env -create -home $testdir]
+ error_check_good env [is_valid_env $env] TRUE
+
+ puts "\tSec001.f.4: Open again with encryption."
+ set stat [catch {berkdb_env_noerr -home $testdir \
+ -encryptaes $passwd1} ret]
+ error_check_good env:unencrypted $stat 1
+ error_check_good env:fail [is_substr $ret \
+ "Joining non-encrypted environment"] 1
+
+ error_check_good envclose [$env close] 0
+
+ env_cleanup $testdir
+
+ #
+ # This second group tests creating and opening a secure env.
+ # We test that others can join successfully, and that other's with
+ # bad/no passwords cannot. Also test that we cannot use the
+ # db->set_encrypt method when we've already got a secure dbenv.
+ #
+ puts "\tSec001.g.1: Open with encryption."
+ set env [berkdb_env_noerr -create -home $testdir -encryptaes $passwd1]
+ error_check_good env [is_valid_env $env] TRUE
+
+ puts "\tSec001.g.2: Open again with encryption - same passwd."
+ set env1 [berkdb_env -home $testdir -encryptaes $passwd1]
+ error_check_good env [is_valid_env $env1] TRUE
+ error_check_good envclose [$env1 close] 0
+
+ puts "\tSec001.g.3: Open again with any encryption (DB_ENCRYPT_ANY)."
+ set env1 [berkdb_env -home $testdir -encryptany $passwd1]
+ error_check_good env [is_valid_env $env1] TRUE
+ error_check_good envclose [$env1 close] 0
+
+ puts "\tSec001.g.4: Open with encryption - different length passwd."
+ set stat [catch {berkdb_env_noerr -home $testdir \
+ -encryptaes $passwd1_bad} ret]
+ error_check_good env:$passwd1_bad $stat 1
+ error_check_good env:fail [is_substr $ret "Invalid password"] 1
+
+ puts "\tSec001.g.5: Open with encryption - different passwd."
+ set stat [catch {berkdb_env_noerr -home $testdir \
+ -encryptaes $passwd2} ret]
+ error_check_good env:$passwd2 $stat 1
+ error_check_good env:fail [is_substr $ret "Invalid password"] 1
+
+ puts "\tSec001.g.6: Open env without encryption."
+ set stat [catch {berkdb_env_noerr -home $testdir} ret]
+ error_check_good env:$passwd2 $stat 1
+ error_check_good env:fail [is_substr $ret "Encrypted environment"] 1
+
+ puts "\tSec001.g.7: Open database with encryption in env"
+ set stat [catch {berkdb_open_noerr -env $env -btree -create \
+ -encryptaes $passwd2 $testfile1} ret]
+ error_check_good db:$passwd2 $stat 1
+ error_check_good env:fail [is_substr $ret "method not permitted"] 1
+
+ puts "\tSec001.g.8: Close creating env"
+ error_check_good envclose [$env close] 0
+
+ #
+ # This third group tests opening the env after the original env
+ # handle is closed. Just to make sure we can reopen it in
+ # the right fashion even if no handles are currently open.
+ #
+ puts "\tSec001.h.1: Reopen without encryption."
+ set stat [catch {berkdb_env_noerr -home $testdir} ret]
+ error_check_good env:noencrypt $stat 1
+ error_check_good env:fail [is_substr $ret "Encrypted environment"] 1
+
+ puts "\tSec001.h.2: Reopen with bad passwd."
+ set stat [catch {berkdb_env_noerr -home $testdir -encryptaes \
+ $passwd1_bad} ret]
+ error_check_good env:$passwd1_bad $stat 1
+ error_check_good env:fail [is_substr $ret "Invalid password"] 1
+
+ puts "\tSec001.h.3: Reopen with encryption."
+ set env [berkdb_env -create -home $testdir -encryptaes $passwd1]
+ error_check_good env [is_valid_env $env] TRUE
+
+ puts "\tSec001.h.4: 2nd Reopen with encryption."
+ set env1 [berkdb_env -home $testdir -encryptaes $passwd1]
+ error_check_good env [is_valid_env $env1] TRUE
+
+ error_check_good envclose [$env1 close] 0
+ error_check_good envclose [$env close] 0
+
+ puts "\tSec001 complete."
+}
diff --git a/bdb/test/sec002.tcl b/bdb/test/sec002.tcl
new file mode 100644
index 00000000000..d790162f1d7
--- /dev/null
+++ b/bdb/test/sec002.tcl
@@ -0,0 +1,143 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2001
+# Sleepycat Software. All rights reserved.
+#
+# $Id: sec002.tcl,v 11.3 2002/04/24 19:04:59 bostic Exp $
+#
+# TEST sec002
+# TEST Test of security interface and catching errors in the
+# TEST face of attackers overwriting parts of existing files.
+proc sec002 { } {
+ global errorInfo
+ global errorCode
+
+ source ./include.tcl
+
+ set testfile1 $testdir/sec002-1.db
+ set testfile2 $testdir/sec002-2.db
+ set testfile3 $testdir/sec002-3.db
+ set testfile4 $testdir/sec002-4.db
+
+ puts "Sec002: Test of basic encryption interface."
+ env_cleanup $testdir
+
+ set passwd1 "passwd1"
+ set passwd2 "passwd2"
+ set key "key"
+ set data "data"
+ set pagesize 1024
+
+ #
+ # Set up 4 databases, two encrypted, but with different passwords
+ # and one unencrypt, but with checksumming turned on and one
+ # unencrypted and no checksumming. Place the exact same data
+ # in each one.
+ #
+ puts "\tSec002.a: Setup databases"
+ set db_cmd "-create -pagesize $pagesize -btree "
+ set db [eval {berkdb_open} -encryptaes $passwd1 $db_cmd $testfile1]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ set db [eval {berkdb_open} -encryptaes $passwd2 $db_cmd $testfile2]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ set db [eval {berkdb_open} -chksum $db_cmd $testfile3]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ set db [eval {berkdb_open} $db_cmd $testfile4]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ #
+ # First just touch some bits in the file. We know that in btree
+ # meta pages, bytes 92-459 are unused. Scribble on them in both
+ # an encrypted, and both unencrypted files. We should get
+ # a checksum error for the encrypted, and checksummed files.
+ # We should get no error for the normal file.
+ #
+ set fidlist {}
+ set fid [open $testfile1 r+]
+ lappend fidlist $fid
+ set fid [open $testfile3 r+]
+ lappend fidlist $fid
+ set fid [open $testfile4 r+]
+ lappend fidlist $fid
+
+ puts "\tSec002.b: Overwrite unused space in meta-page"
+ foreach f $fidlist {
+ fconfigure $f -translation binary
+ seek $f 100 start
+ set byte [read $f 1]
+ binary scan $byte c val
+ set newval [expr ~$val]
+ set newbyte [binary format c $newval]
+ seek $f 100 start
+ puts -nonewline $f $newbyte
+ close $f
+ }
+ puts "\tSec002.c: Reopen modified databases"
+ set stat [catch {berkdb_open_noerr -encryptaes $passwd1 $testfile1} ret]
+ error_check_good db:$testfile1 $stat 1
+ error_check_good db:$testfile1:fail \
+ [is_substr $ret "metadata page checksum error"] 1
+
+ set stat [catch {berkdb_open_noerr -chksum $testfile3} ret]
+ error_check_good db:$testfile3 $stat 1
+ error_check_good db:$testfile3:fail \
+ [is_substr $ret "metadata page checksum error"] 1
+
+ set stat [catch {berkdb_open_noerr $testfile4} db]
+ error_check_good db:$testfile4 $stat 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\tSec002.d: Replace root page in encrypted w/ encrypted"
+ set fid1 [open $testfile1 r+]
+ set fid2 [open $testfile2 r+]
+ seek $fid1 $pagesize start
+ seek $fid2 $pagesize start
+ set root1 [read $fid1 $pagesize]
+ close $fid1
+ puts -nonewline $fid2 $root1
+ close $fid2
+
+ set db [berkdb_open_noerr -encryptaes $passwd2 $testfile2]
+ error_check_good db [is_valid_db $db] TRUE
+ set stat [catch {$db get $key} ret]
+ error_check_good dbget $stat 1
+ error_check_good db:$testfile2:fail \
+ [is_substr $ret "checksum error: catastrophic recovery required"] 1
+ set stat [catch {$db close} ret]
+ error_check_good dbclose $stat 1
+ error_check_good db:$testfile2:fail [is_substr $ret "DB_RUNRECOVERY"] 1
+
+ puts "\tSec002.e: Replace root page in encrypted w/ unencrypted"
+ set fid2 [open $testfile2 r+]
+ set fid4 [open $testfile4 r+]
+ seek $fid2 $pagesize start
+ seek $fid4 $pagesize start
+ set root4 [read $fid4 $pagesize]
+ close $fid4
+ puts -nonewline $fid2 $root4
+ close $fid2
+
+ set db [berkdb_open_noerr -encryptaes $passwd2 $testfile2]
+ error_check_good db [is_valid_db $db] TRUE
+ set stat [catch {$db get $key} ret]
+ error_check_good dbget $stat 1
+ error_check_good db:$testfile2:fail \
+ [is_substr $ret "checksum error: catastrophic recovery required"] 1
+ set stat [catch {$db close} ret]
+ error_check_good dbclose $stat 1
+ error_check_good db:$testfile2:fail [is_substr $ret "DB_RUNRECOVERY"] 1
+
+ cleanup $testdir NULL 1
+ puts "\tSec002 complete."
+}
diff --git a/bdb/test/shelltest.tcl b/bdb/test/shelltest.tcl
new file mode 100644
index 00000000000..6190bac1f8d
--- /dev/null
+++ b/bdb/test/shelltest.tcl
@@ -0,0 +1,88 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: shelltest.tcl,v 1.20 2002/04/19 15:42:20 bostic Exp $
+#
+# TEST scr###
+# TEST The scr### directories are shell scripts that test a variety of
+# TEST things, including things about the distribution itself. These
+# TEST tests won't run on most systems, so don't even try to run them.
+#
+# shelltest.tcl:
+# Code to run shell script tests, to incorporate Java, C++,
+# example compilation, etc. test scripts into the Tcl framework.
+proc shelltest { { run_one 0 }} {
+ source ./include.tcl
+ global shelltest_list
+
+ set SH /bin/sh
+ if { [file executable $SH] != 1 } {
+ puts "Shell tests require valid shell /bin/sh: not found."
+ puts "Skipping shell tests."
+ return 0
+ }
+
+ if { $run_one == 0 } {
+ puts "Running shell script tests..."
+
+ foreach testpair $shelltest_list {
+ set dir [lindex $testpair 0]
+ set test [lindex $testpair 1]
+
+ env_cleanup $testdir
+ shelltest_copy $test_path/$dir $testdir
+ shelltest_run $SH $dir $test $testdir
+ }
+ } else {
+ set run_one [expr $run_one - 1];
+ set dir [lindex [lindex $shelltest_list $run_one] 0]
+ set test [lindex [lindex $shelltest_list $run_one] 1]
+
+ env_cleanup $testdir
+ shelltest_copy $test_path/$dir $testdir
+ shelltest_run $SH $dir $test $testdir
+ }
+}
+
+proc shelltest_copy { fromdir todir } {
+ set globall [glob $fromdir/*]
+
+ foreach f $globall {
+ file copy $f $todir/
+ }
+}
+
+proc shelltest_run { sh srcdir test testdir } {
+ puts "Running shell script $srcdir ($test)..."
+
+ set ret [catch {exec $sh -c "cd $testdir && sh $test" >&@ stdout} res]
+
+ if { $ret != 0 } {
+ puts "FAIL: shell test $srcdir/$test exited abnormally"
+ }
+}
+
+proc scr001 {} { shelltest 1 }
+proc scr002 {} { shelltest 2 }
+proc scr003 {} { shelltest 3 }
+proc scr004 {} { shelltest 4 }
+proc scr005 {} { shelltest 5 }
+proc scr006 {} { shelltest 6 }
+proc scr007 {} { shelltest 7 }
+proc scr008 {} { shelltest 8 }
+proc scr009 {} { shelltest 9 }
+proc scr010 {} { shelltest 10 }
+proc scr011 {} { shelltest 11 }
+proc scr012 {} { shelltest 12 }
+proc scr013 {} { shelltest 13 }
+proc scr014 {} { shelltest 14 }
+proc scr015 {} { shelltest 15 }
+proc scr016 {} { shelltest 16 }
+proc scr017 {} { shelltest 17 }
+proc scr018 {} { shelltest 18 }
+proc scr019 {} { shelltest 19 }
+proc scr020 {} { shelltest 20 }
+proc scr021 {} { shelltest 21 }
+proc scr022 {} { shelltest 22 }
diff --git a/bdb/test/si001.tcl b/bdb/test/si001.tcl
new file mode 100644
index 00000000000..1a2247c5f8b
--- /dev/null
+++ b/bdb/test/si001.tcl
@@ -0,0 +1,116 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: si001.tcl,v 1.7 2002/04/29 17:12:02 sandstro Exp $
+#
+# TEST sindex001
+# TEST Basic secondary index put/delete test
+proc sindex001 { methods {nentries 200} {tnum 1} args } {
+ source ./include.tcl
+ global dict nsecondaries
+
+ # Primary method/args.
+ set pmethod [lindex $methods 0]
+ set pargs [convert_args $pmethod $args]
+ set pomethod [convert_method $pmethod]
+
+ # Method/args for all the secondaries. If only one method
+ # was specified, assume the same method and a standard N
+ # secondaries.
+ set methods [lrange $methods 1 end]
+ if { [llength $methods] == 0 } {
+ for { set i 0 } { $i < $nsecondaries } { incr i } {
+ lappend methods $pmethod
+ }
+ }
+
+ set argses [convert_argses $methods $args]
+ set omethods [convert_methods $methods]
+
+ puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+ env_cleanup $testdir
+
+ set pname "primary00$tnum.db"
+ set snamebase "secondary00$tnum"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [berkdb_env -create -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the primary.
+ set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ # Open and associate the secondaries
+ set sdbs {}
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+
+ puts "\tSindex00$tnum.a: Put loop"
+ set did [open $dict]
+ for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+ if { [is_record_based $pmethod] == 1 } {
+ set key [expr $n + 1]
+ set datum $str
+ } else {
+ set key $str
+ gets $did datum
+ }
+ set keys($n) $key
+ set data($n) [pad_data $pmethod $datum]
+
+ set ret [eval {$pdb put} {$key [chop_data $pmethod $datum]}]
+ error_check_good put($n) $ret 0
+ }
+ close $did
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+
+ puts "\tSindex00$tnum.b: Put/overwrite loop"
+ for { set n 0 } { $n < $nentries } { incr n } {
+ set newd $data($n).$keys($n)
+ set ret [eval {$pdb put} {$keys($n) [chop_data $pmethod $newd]}]
+ error_check_good put_overwrite($n) $ret 0
+ set data($n) [pad_data $pmethod $newd]
+ }
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+
+ # Delete the second half of the entries through the primary.
+ # We do the second half so we can just pass keys(0 ... n/2)
+ # to check_secondaries.
+ set half [expr $nentries / 2]
+ puts "\tSindex00$tnum.c: Primary delete loop: deleting $half entries"
+ for { set n $half } { $n < $nentries } { incr n } {
+ set ret [$pdb del $keys($n)]
+ error_check_good pdel($n) $ret 0
+ }
+ check_secondaries $pdb $sdbs $half keys data "Sindex00$tnum.c"
+
+ # Delete half of what's left, through the first secondary.
+ set quar [expr $half / 2]
+ puts "\tSindex00$tnum.d: Secondary delete loop: deleting $quar entries"
+ set sdb [lindex $sdbs 0]
+ set callback [callback_n 0]
+ for { set n $quar } { $n < $half } { incr n } {
+ set skey [$callback $keys($n) [pad_data $pmethod $data($n)]]
+ set ret [$sdb del $skey]
+ error_check_good sdel($n) $ret 0
+ }
+ check_secondaries $pdb $sdbs $quar keys data "Sindex00$tnum.d"
+
+ puts "\tSindex00$tnum.e: Closing/disassociating primary first"
+ error_check_good primary_close [$pdb close] 0
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/si002.tcl b/bdb/test/si002.tcl
new file mode 100644
index 00000000000..46ba86e7560
--- /dev/null
+++ b/bdb/test/si002.tcl
@@ -0,0 +1,167 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: si002.tcl,v 1.6 2002/04/29 17:12:02 sandstro Exp $
+#
+# TEST sindex002
+# TEST Basic cursor-based secondary index put/delete test
+proc sindex002 { methods {nentries 200} {tnum 2} args } {
+ source ./include.tcl
+ global dict nsecondaries
+
+ # Primary method/args.
+ set pmethod [lindex $methods 0]
+ set pargs [convert_args $pmethod $args]
+ set pomethod [convert_method $pmethod]
+
+ # Method/args for all the secondaries. If only one method
+ # was specified, assume the same method and a standard N
+ # secondaries.
+ set methods [lrange $methods 1 end]
+ if { [llength $methods] == 0 } {
+ for { set i 0 } { $i < $nsecondaries } { incr i } {
+ lappend methods $pmethod
+ }
+ }
+
+ set argses [convert_argses $methods $args]
+ set omethods [convert_methods $methods]
+
+ puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+ env_cleanup $testdir
+
+ set pname "primary00$tnum.db"
+ set snamebase "secondary00$tnum"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [berkdb_env -create -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the primary.
+ set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ # Open and associate the secondaries
+ set sdbs {}
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+
+ puts "\tSindex00$tnum.a: Cursor put (-keyfirst/-keylast) loop"
+ set did [open $dict]
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+ if { [is_record_based $pmethod] == 1 } {
+ set key [expr $n + 1]
+ set datum $str
+ } else {
+ set key $str
+ gets $did datum
+ }
+ set ns($key) $n
+ set keys($n) $key
+ set data($n) [pad_data $pmethod $datum]
+
+ if { $n % 2 == 0 } {
+ set pflag " -keyfirst "
+ } else {
+ set pflag " -keylast "
+ }
+
+ set ret [eval {$pdbc put} $pflag \
+ {$key [chop_data $pmethod $datum]}]
+ error_check_good put($n) $ret 0
+ }
+ close $did
+ error_check_good pdbc_close [$pdbc close] 0
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+
+ puts "\tSindex00$tnum.b: Cursor put overwrite (-current) loop"
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
+ { set dbt [$pdbc get -next] } {
+ set key [lindex [lindex $dbt 0] 0]
+ set datum [lindex [lindex $dbt 0] 1]
+ set newd $datum.$key
+ set ret [eval {$pdbc put -current} [chop_data $pmethod $newd]]
+ error_check_good put_overwrite($key) $ret 0
+ set data($ns($key)) [pad_data $pmethod $newd]
+ }
+ error_check_good pdbc_close [$pdbc close] 0
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+
+ puts "\tSindex00$tnum.c: Secondary c_pget/primary put overwrite loop"
+ # We walk the first secondary, then put-overwrite each primary key/data
+ # pair we find. This doubles as a DBC->c_pget test.
+ set sdb [lindex $sdbs 0]
+ set sdbc [$sdb cursor]
+ error_check_good sdb_cursor [is_valid_cursor $sdbc $sdb] TRUE
+ for { set dbt [$sdbc pget -first] } { [llength $dbt] > 0 } \
+ { set dbt [$sdbc pget -next] } {
+ set pkey [lindex [lindex $dbt 0] 1]
+ set pdatum [lindex [lindex $dbt 0] 2]
+
+ # Extended entries will be showing up underneath us, in
+ # unpredictable places. Keep track of which pkeys
+ # we've extended, and don't extend them repeatedly.
+ if { [info exists pkeys_done($pkey)] == 1 } {
+ continue
+ } else {
+ set pkeys_done($pkey) 1
+ }
+
+ set newd $pdatum.[string range $pdatum 0 2]
+ set ret [eval {$pdb put} $pkey [chop_data $pmethod $newd]]
+ error_check_good pdb_put($pkey) $ret 0
+ set data($ns($pkey)) [pad_data $pmethod $newd]
+ }
+ error_check_good sdbc_close [$sdbc close] 0
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.c"
+
+ # Delete the second half of the entries through the primary.
+ # We do the second half so we can just pass keys(0 ... n/2)
+ # to check_secondaries.
+ set half [expr $nentries / 2]
+ puts "\tSindex00$tnum.d:\
+ Primary cursor delete loop: deleting $half entries"
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ set dbt [$pdbc get -first]
+ for { set i 0 } { [llength $dbt] > 0 && $i < $half } { incr i } {
+ error_check_good pdbc_del [$pdbc del] 0
+ set dbt [$pdbc get -next]
+ }
+ error_check_good pdbc_close [$pdbc close] 0
+ cursor_check_secondaries $pdb $sdbs $half "Sindex00$tnum.d"
+
+ # Delete half of what's left, through the first secondary.
+ set quar [expr $half / 2]
+ puts "\tSindex00$tnum.e:\
+ Secondary cursor delete loop: deleting $quar entries"
+ set sdb [lindex $sdbs 0]
+ set sdbc [$sdb cursor]
+ set dbt [$sdbc get -first]
+ for { set i 0 } { [llength $dbt] > 0 && $i < $quar } { incr i } {
+ error_check_good sdbc_del [$sdbc del] 0
+ set dbt [$sdbc get -next]
+ }
+ error_check_good sdbc_close [$sdbc close] 0
+ cursor_check_secondaries $pdb $sdbs $quar "Sindex00$tnum.e"
+
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good primary_close [$pdb close] 0
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/si003.tcl b/bdb/test/si003.tcl
new file mode 100644
index 00000000000..1cc8c884e75
--- /dev/null
+++ b/bdb/test/si003.tcl
@@ -0,0 +1,142 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: si003.tcl,v 1.6 2002/04/29 17:12:03 sandstro Exp $
+#
+# TEST sindex003
+# TEST sindex001 with secondaries created and closed mid-test
+# TEST Basic secondary index put/delete test with secondaries
+# TEST created mid-test.
+proc sindex003 { methods {nentries 200} {tnum 3} args } {
+ source ./include.tcl
+ global dict nsecondaries
+
+ # Primary method/args.
+ set pmethod [lindex $methods 0]
+ set pargs [convert_args $pmethod $args]
+ set pomethod [convert_method $pmethod]
+
+ # Method/args for all the secondaries. If only one method
+ # was specified, assume the same method and a standard N
+ # secondaries.
+ set methods [lrange $methods 1 end]
+ if { [llength $methods] == 0 } {
+ for { set i 0 } { $i < $nsecondaries } { incr i } {
+ lappend methods $pmethod
+ }
+ }
+
+ set argses [convert_argses $methods $args]
+ set omethods [convert_methods $methods]
+
+ puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+ env_cleanup $testdir
+
+ set pname "primary00$tnum.db"
+ set snamebase "secondary00$tnum"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [eval {berkdb_env -create -home $testdir}]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the primary.
+ set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ puts -nonewline "\tSindex00$tnum.a: Put loop ... "
+ set did [open $dict]
+ for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+ if { [is_record_based $pmethod] == 1 } {
+ set key [expr $n + 1]
+ set datum $str
+ } else {
+ set key $str
+ gets $did datum
+ }
+ set keys($n) $key
+ set data($n) [pad_data $pmethod $datum]
+
+ set ret [eval {$pdb put} {$key [chop_data $pmethod $datum]}]
+ error_check_good put($n) $ret 0
+ }
+ close $did
+
+ # Open and associate the secondaries
+ set sdbs {}
+ puts "opening secondaries."
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate -create [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+
+ puts -nonewline "\tSindex00$tnum.b: Put/overwrite loop ... "
+ for { set n 0 } { $n < $nentries } { incr n } {
+ set newd $data($n).$keys($n)
+ set ret [eval {$pdb put} {$keys($n) [chop_data $pmethod $newd]}]
+ error_check_good put_overwrite($n) $ret 0
+ set data($n) [pad_data $pmethod $newd]
+ }
+
+ # Close the secondaries again.
+ puts "closing secondaries."
+ for { set sdb [lindex $sdbs end] } { [string length $sdb] > 0 } \
+ { set sdb [lindex $sdbs end] } {
+ error_check_good second_close($sdb) [$sdb close] 0
+ set sdbs [lrange $sdbs 0 end-1]
+ check_secondaries \
+ $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+ }
+
+ # Delete the second half of the entries through the primary.
+ # We do the second half so we can just pass keys(0 ... n/2)
+ # to check_secondaries.
+ set half [expr $nentries / 2]
+ puts -nonewline \
+ "\tSindex00$tnum.c: Primary delete loop: deleting $half entries ..."
+ for { set n $half } { $n < $nentries } { incr n } {
+ set ret [$pdb del $keys($n)]
+ error_check_good pdel($n) $ret 0
+ }
+
+ # Open and associate the secondaries
+ set sdbs {}
+ puts "\n\t\topening secondaries."
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] \
+ $snamebase.r2.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate -create [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+ check_secondaries $pdb $sdbs $half keys data "Sindex00$tnum.c"
+
+ # Delete half of what's left, through the first secondary.
+ set quar [expr $half / 2]
+ puts "\tSindex00$tnum.d: Secondary delete loop: deleting $quar entries"
+ set sdb [lindex $sdbs 0]
+ set callback [callback_n 0]
+ for { set n $quar } { $n < $half } { incr n } {
+ set skey [$callback $keys($n) [pad_data $pmethod $data($n)]]
+ set ret [$sdb del $skey]
+ error_check_good sdel($n) $ret 0
+ }
+ check_secondaries $pdb $sdbs $quar keys data "Sindex00$tnum.d"
+
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good primary_close [$pdb close] 0
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/si004.tcl b/bdb/test/si004.tcl
new file mode 100644
index 00000000000..291100da6b3
--- /dev/null
+++ b/bdb/test/si004.tcl
@@ -0,0 +1,194 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: si004.tcl,v 1.6 2002/04/29 17:12:03 sandstro Exp $
+#
+# TEST sindex004
+# TEST sindex002 with secondaries created and closed mid-test
+# TEST Basic cursor-based secondary index put/delete test, with
+# TEST secondaries created mid-test.
+proc sindex004 { methods {nentries 200} {tnum 4} args } {
+ source ./include.tcl
+ global dict nsecondaries
+
+ # Primary method/args.
+ set pmethod [lindex $methods 0]
+ set pargs [convert_args $pmethod $args]
+ set pomethod [convert_method $pmethod]
+
+ # Method/args for all the secondaries. If only one method
+ # was specified, assume the same method and a standard N
+ # secondaries.
+ set methods [lrange $methods 1 end]
+ if { [llength $methods] == 0 } {
+ for { set i 0 } { $i < $nsecondaries } { incr i } {
+ lappend methods $pmethod
+ }
+ }
+
+ set argses [convert_argses $methods $args]
+ set omethods [convert_methods $methods]
+
+ puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+ env_cleanup $testdir
+
+ set pname "primary00$tnum.db"
+ set snamebase "secondary00$tnum"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [berkdb_env -create -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the primary.
+ set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ puts -nonewline \
+ "\tSindex00$tnum.a: Cursor put (-keyfirst/-keylast) loop ... "
+ set did [open $dict]
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+ if { [is_record_based $pmethod] == 1 } {
+ set key [expr $n + 1]
+ set datum $str
+ } else {
+ set key $str
+ gets $did datum
+ }
+ set ns($key) $n
+ set keys($n) $key
+ set data($n) [pad_data $pmethod $datum]
+
+ if { $n % 2 == 0 } {
+ set pflag " -keyfirst "
+ } else {
+ set pflag " -keylast "
+ }
+
+ set ret [eval {$pdbc put} $pflag \
+ {$key [chop_data $pmethod $datum]}]
+ error_check_good put($n) $ret 0
+ }
+ close $did
+ error_check_good pdbc_close [$pdbc close] 0
+
+ # Open and associate the secondaries
+ set sdbs {}
+ puts "\n\t\topening secondaries."
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate -create [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+
+ puts "\tSindex00$tnum.b: Cursor put overwrite (-current) loop"
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
+ { set dbt [$pdbc get -next] } {
+ set key [lindex [lindex $dbt 0] 0]
+ set datum [lindex [lindex $dbt 0] 1]
+ set newd $datum.$key
+ set ret [eval {$pdbc put -current} [chop_data $pmethod $newd]]
+ error_check_good put_overwrite($key) $ret 0
+ set data($ns($key)) [pad_data $pmethod $newd]
+ }
+ error_check_good pdbc_close [$pdbc close] 0
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+
+ puts -nonewline "\tSindex00$tnum.c:\
+ Secondary c_pget/primary put overwrite loop ... "
+ # We walk the first secondary, then put-overwrite each primary key/data
+ # pair we find. This doubles as a DBC->c_pget test.
+ set sdb [lindex $sdbs 0]
+ set sdbc [$sdb cursor]
+ error_check_good sdb_cursor [is_valid_cursor $sdbc $sdb] TRUE
+ for { set dbt [$sdbc pget -first] } { [llength $dbt] > 0 } \
+ { set dbt [$sdbc pget -next] } {
+ set pkey [lindex [lindex $dbt 0] 1]
+ set pdatum [lindex [lindex $dbt 0] 2]
+
+ # Extended entries will be showing up underneath us, in
+ # unpredictable places. Keep track of which pkeys
+ # we've extended, and don't extend them repeatedly.
+ if { [info exists pkeys_done($pkey)] == 1 } {
+ continue
+ } else {
+ set pkeys_done($pkey) 1
+ }
+
+ set newd $pdatum.[string range $pdatum 0 2]
+ set ret [eval {$pdb put} $pkey [chop_data $pmethod $newd]]
+ error_check_good pdb_put($pkey) $ret 0
+ set data($ns($pkey)) [pad_data $pmethod $newd]
+ }
+ error_check_good sdbc_close [$sdbc close] 0
+
+ # Close the secondaries again.
+ puts "\n\t\tclosing secondaries."
+ for { set sdb [lindex $sdbs end] } { [string length $sdb] > 0 } \
+ { set sdb [lindex $sdbs end] } {
+ error_check_good second_close($sdb) [$sdb close] 0
+ set sdbs [lrange $sdbs 0 end-1]
+ check_secondaries \
+ $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+ }
+
+ # Delete the second half of the entries through the primary.
+ # We do the second half so we can just pass keys(0 ... n/2)
+ # to check_secondaries.
+ set half [expr $nentries / 2]
+ puts -nonewline "\tSindex00$tnum.d:\
+ Primary cursor delete loop: deleting $half entries ... "
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ set dbt [$pdbc get -first]
+ for { set i 0 } { [llength $dbt] > 0 && $i < $half } { incr i } {
+ error_check_good pdbc_del [$pdbc del] 0
+ set dbt [$pdbc get -next]
+ }
+ error_check_good pdbc_close [$pdbc close] 0
+
+ set sdbs {}
+ puts "\n\t\topening secondaries."
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] \
+ $snamebase.r2.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate -create [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+ cursor_check_secondaries $pdb $sdbs $half "Sindex00$tnum.d"
+
+ # Delete half of what's left, through the first secondary.
+ set quar [expr $half / 2]
+ puts "\tSindex00$tnum.e:\
+ Secondary cursor delete loop: deleting $quar entries"
+ set sdb [lindex $sdbs 0]
+ set sdbc [$sdb cursor]
+ set dbt [$sdbc get -first]
+ for { set i 0 } { [llength $dbt] > 0 && $i < $quar } { incr i } {
+ error_check_good sdbc_del [$sdbc del] 0
+ set dbt [$sdbc get -next]
+ }
+ error_check_good sdbc_close [$sdbc close] 0
+ cursor_check_secondaries $pdb $sdbs $quar "Sindex00$tnum.e"
+
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good primary_close [$pdb close] 0
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/si005.tcl b/bdb/test/si005.tcl
new file mode 100644
index 00000000000..e5ed49175c9
--- /dev/null
+++ b/bdb/test/si005.tcl
@@ -0,0 +1,179 @@
+
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: si005.tcl,v 11.4 2002/04/29 17:12:03 sandstro Exp $
+#
+# Sindex005: Secondary index and join test.
+proc sindex005 { methods {nitems 1000} {tnum 5} args } {
+ source ./include.tcl
+
+ # Primary method/args.
+ set pmethod [lindex $methods 0]
+ set pargs [convert_args $pmethod $args]
+ set pomethod [convert_method $pmethod]
+
+ # Sindex005 does a join within a simulated database schema
+ # in which the primary index maps a record ID to a ZIP code and
+ # name in the form "XXXXXname", and there are two secondaries:
+ # one mapping ZIP to ID, the other mapping name to ID.
+ # The primary may be of any database type; the two secondaries
+ # must be either btree or hash.
+
+ # Method/args for all the secondaries. If only one method
+ # was specified, assume the same method for the two secondaries.
+ set methods [lrange $methods 1 end]
+ if { [llength $methods] == 0 } {
+ for { set i 0 } { $i < 2 } { incr i } {
+ lappend methods $pmethod
+ }
+ } elseif { [llength $methods] != 2 } {
+ puts "FAIL: Sindex00$tnum requires exactly two secondaries."
+ return
+ }
+
+ set argses [convert_argses $methods $args]
+ set omethods [convert_methods $methods]
+
+ puts "Sindex00$tnum ($pmethod/$methods) Secondary index join test."
+ env_cleanup $testdir
+
+ set pname "sindex00$tnum-primary.db"
+ set zipname "sindex00$tnum-zip.db"
+ set namename "sindex00$tnum-name.db"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [berkdb_env -create -home $testdir]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the databases.
+ set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ set zipdb [eval {berkdb_open -create -dup -env} $env \
+ [lindex $omethods 0] [lindex $argses 0] $zipname]
+ error_check_good zip_open [is_valid_db $zipdb] TRUE
+ error_check_good zip_associate [$pdb associate s5_getzip $zipdb] 0
+
+ set namedb [eval {berkdb_open -create -dup -env} $env \
+ [lindex $omethods 1] [lindex $argses 1] $namename]
+ error_check_good name_open [is_valid_db $namedb] TRUE
+ error_check_good name_associate [$pdb associate s5_getname $namedb] 0
+
+ puts "\tSindex00$tnum.a: Populate database with $nitems \"names\""
+ s5_populate $pdb $nitems
+ puts "\tSindex00$tnum.b: Perform a join on each \"name\" and \"ZIP\""
+ s5_jointest $pdb $zipdb $namedb
+
+ error_check_good name_close [$namedb close] 0
+ error_check_good zip_close [$zipdb close] 0
+ error_check_good primary_close [$pdb close] 0
+ error_check_good env_close [$env close] 0
+}
+
+proc s5_jointest { pdb zipdb namedb } {
+ set pdbc [$pdb cursor]
+ error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
+ for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
+ { set dbt [$pdbc get -next] } {
+ set item [lindex [lindex $dbt 0] 1]
+ set retlist [s5_dojoin $item $pdb $zipdb $namedb]
+ }
+}
+
+proc s5_dojoin { item pdb zipdb namedb } {
+ set name [s5_getname "" $item]
+ set zip [s5_getzip "" $item]
+
+ set zipc [$zipdb cursor]
+ error_check_good zipc($item) [is_valid_cursor $zipc $zipdb] TRUE
+
+ set namec [$namedb cursor]
+ error_check_good namec($item) [is_valid_cursor $namec $namedb] TRUE
+
+ set pc [$pdb cursor]
+ error_check_good pc($item) [is_valid_cursor $pc $pdb] TRUE
+
+ set ret [$zipc get -set $zip]
+ set zd [lindex [lindex $ret 0] 1]
+ error_check_good zipset($zip) [s5_getzip "" $zd] $zip
+
+ set ret [$namec get -set $name]
+ set nd [lindex [lindex $ret 0] 1]
+ error_check_good nameset($name) [s5_getname "" $nd] $name
+
+ set joinc [$pdb join $zipc $namec]
+
+ set anyreturned 0
+ for { set dbt [$joinc get] } { [llength $dbt] > 0 } \
+ { set dbt [$joinc get] } {
+ set ritem [lindex [lindex $dbt 0] 1]
+ error_check_good returned_item($item) $ritem $item
+ incr anyreturned
+ }
+ error_check_bad anyreturned($item) $anyreturned 0
+
+ error_check_good joinc_close($item) [$joinc close] 0
+ error_check_good pc_close($item) [$pc close] 0
+ error_check_good namec_close($item) [$namec close] 0
+ error_check_good zipc_close($item) [$zipc close] 0
+}
+
+proc s5_populate { db nitems } {
+ global dict
+
+ set did [open $dict]
+ for { set i 1 } { $i <= $nitems } { incr i } {
+ gets $did word
+ if { [string length $word] < 3 } {
+ gets $did word
+ if { [string length $word] < 3 } {
+ puts "FAIL:\
+ unexpected pair of words < 3 chars long"
+ }
+ }
+ set datalist [s5_name2zips $word]
+ foreach data $datalist {
+ error_check_good db_put($data) [$db put $i $data$word] 0
+ }
+ }
+ close $did
+}
+
+proc s5_getzip { key data } { return [string range $data 0 4] }
+proc s5_getname { key data } { return [string range $data 5 end] }
+
+# The dirty secret of this test is that the ZIP code is a function of the
+# name, so we can generate a database and then verify join results easily
+# without having to consult actual data.
+#
+# Any word passed into this function will generate from 1 to 26 ZIP
+# entries, out of the set {00000, 01000 ... 99000}. The number of entries
+# is just the position in the alphabet of the word's first letter; the
+# entries are then hashed to the set {00, 01 ... 99} N different ways.
+proc s5_name2zips { name } {
+ global alphabet
+
+ set n [expr [string first [string index $name 0] $alphabet] + 1]
+ error_check_bad starts_with_abc($name) $n -1
+
+ set ret {}
+ for { set i 0 } { $i < $n } { incr i } {
+ set b 0
+ for { set j 1 } { $j < [string length $name] } \
+ { incr j } {
+ set b [s5_nhash $name $i $j $b]
+ }
+ lappend ret [format %05u [expr $b % 100]000]
+ }
+ return $ret
+}
+proc s5_nhash { name i j b } {
+ global alphabet
+
+ set c [string first [string index $name $j] $alphabet']
+ return [expr (($b * 991) + ($i * 997) + $c) % 10000000]
+}
diff --git a/bdb/test/si006.tcl b/bdb/test/si006.tcl
new file mode 100644
index 00000000000..3a1dbb3c4f8
--- /dev/null
+++ b/bdb/test/si006.tcl
@@ -0,0 +1,129 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: si006.tcl,v 1.2 2002/05/15 17:18:03 sandstro Exp $
+#
+# TEST sindex006
+# TEST Basic secondary index put/delete test with transactions
+proc sindex006 { methods {nentries 200} {tnum 6} args } {
+ source ./include.tcl
+ global dict nsecondaries
+
+ # Primary method/args.
+ set pmethod [lindex $methods 0]
+ set pargs [convert_args $pmethod $args]
+ set pomethod [convert_method $pmethod]
+
+ # Method/args for all the secondaries. If only one method
+ # was specified, assume the same method and a standard N
+ # secondaries.
+ set methods [lrange $methods 1 end]
+ if { [llength $methods] == 0 } {
+ for { set i 0 } { $i < $nsecondaries } { incr i } {
+ lappend methods $pmethod
+ }
+ }
+
+ set argses [convert_argses $methods $args]
+ set omethods [convert_methods $methods]
+
+ puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+ puts " with transactions"
+ env_cleanup $testdir
+
+ set pname "primary00$tnum.db"
+ set snamebase "secondary00$tnum"
+
+ # Open an environment
+ # XXX if one is not supplied!
+ set env [berkdb_env -create -home $testdir -txn]
+ error_check_good env_open [is_valid_env $env] TRUE
+
+ # Open the primary.
+ set pdb [eval {berkdb_open -create -auto_commit -env} $env $pomethod \
+ $pargs $pname]
+ error_check_good primary_open [is_valid_db $pdb] TRUE
+
+ # Open and associate the secondaries
+ set sdbs {}
+ for { set i 0 } { $i < [llength $omethods] } { incr i } {
+ set sdb [eval {berkdb_open -create -auto_commit -env} $env \
+ [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+ error_check_good second_open($i) [is_valid_db $sdb] TRUE
+
+ error_check_good db_associate($i) \
+ [$pdb associate -auto_commit [callback_n $i] $sdb] 0
+ lappend sdbs $sdb
+ }
+
+ puts "\tSindex00$tnum.a: Put loop"
+ set did [open $dict]
+ for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+ if { [is_record_based $pmethod] == 1 } {
+ set key [expr $n + 1]
+ set datum $str
+ } else {
+ set key $str
+ gets $did datum
+ }
+ set keys($n) $key
+ set data($n) [pad_data $pmethod $datum]
+
+ set txn [$env txn]
+ set ret [eval {$pdb put} -txn $txn \
+ {$key [chop_data $pmethod $datum]}]
+ error_check_good put($n) $ret 0
+ error_check_good txn_commit($n) [$txn commit] 0
+ }
+ close $did
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+
+ puts "\tSindex00$tnum.b: Put/overwrite loop"
+ for { set n 0 } { $n < $nentries } { incr n } {
+ set newd $data($n).$keys($n)
+
+ set txn [$env txn]
+ set ret [eval {$pdb put} -txn $txn \
+ {$keys($n) [chop_data $pmethod $newd]}]
+ error_check_good put_overwrite($n) $ret 0
+ set data($n) [pad_data $pmethod $newd]
+ error_check_good txn_commit($n) [$txn commit] 0
+ }
+ check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+
+ # Delete the second half of the entries through the primary.
+ # We do the second half so we can just pass keys(0 ... n/2)
+ # to check_secondaries.
+ set half [expr $nentries / 2]
+ puts "\tSindex00$tnum.c: Primary delete loop: deleting $half entries"
+ for { set n $half } { $n < $nentries } { incr n } {
+ set txn [$env txn]
+ set ret [$pdb del -txn $txn $keys($n)]
+ error_check_good pdel($n) $ret 0
+ error_check_good txn_commit($n) [$txn commit] 0
+ }
+ check_secondaries $pdb $sdbs $half keys data "Sindex00$tnum.c"
+
+ # Delete half of what's left, through the first secondary.
+ set quar [expr $half / 2]
+ puts "\tSindex00$tnum.d: Secondary delete loop: deleting $quar entries"
+ set sdb [lindex $sdbs 0]
+ set callback [callback_n 0]
+ for { set n $quar } { $n < $half } { incr n } {
+ set skey [$callback $keys($n) [pad_data $pmethod $data($n)]]
+ set txn [$env txn]
+ set ret [$sdb del -txn $txn $skey]
+ error_check_good sdel($n) $ret 0
+ error_check_good txn_commit($n) [$txn commit] 0
+ }
+ check_secondaries $pdb $sdbs $quar keys data "Sindex00$tnum.d"
+
+ puts "\tSindex00$tnum.e: Closing/disassociating primary first"
+ error_check_good primary_close [$pdb close] 0
+ foreach sdb $sdbs {
+ error_check_good secondary_close [$sdb close] 0
+ }
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/sindex.tcl b/bdb/test/sindex.tcl
new file mode 100644
index 00000000000..fc2a0fc2f31
--- /dev/null
+++ b/bdb/test/sindex.tcl
@@ -0,0 +1,259 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2001-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: sindex.tcl,v 1.8 2002/05/07 17:15:46 krinsky Exp $
+#
+# Secondary index test driver and maintenance routines.
+#
+# Breaking from the usual convention, we put the driver function
+# for the secondary index tests here, in its own file. The reason
+# for this is that it's something which compartmentalizes nicely,
+# has little in common with other driver functions, and
+# is likely to be run on its own from time to time.
+#
+# The secondary index tests themselves live in si0*.tcl.
+
+# Standard number of secondary indices to create if a single-element
+# list of methods is passed into the secondary index tests.
+global nsecondaries
+set nsecondaries 2
+
+# Run the secondary index tests.
+proc sindex { {verbose 0} args } {
+ global verbose_check_secondaries
+ set verbose_check_secondaries $verbose
+
+ # Run basic tests with a single secondary index and a small number
+ # of keys, then again with a larger number of keys. (Note that
+ # we can't go above 5000, since we use two items from our
+ # 10K-word list for each key/data pair.)
+ foreach n { 200 5000 } {
+ foreach pm { btree hash recno frecno queue queueext } {
+ foreach sm { dbtree dhash ddbtree ddhash btree hash } {
+ sindex001 [list $pm $sm $sm] $n
+ sindex002 [list $pm $sm $sm] $n
+ # Skip tests 3 & 4 for large lists;
+ # they're not that interesting.
+ if { $n < 1000 } {
+ sindex003 [list $pm $sm $sm] $n
+ sindex004 [list $pm $sm $sm] $n
+ }
+
+ sindex006 [list $pm $sm $sm] $n
+ }
+ }
+ }
+
+ # Run secondary index join test. (There's no point in running
+ # this with both lengths, the primary is unhappy for now with fixed-
+ # length records (XXX), and we need unsorted dups in the secondaries.)
+ foreach pm { btree hash recno } {
+ foreach sm { btree hash } {
+ sindex005 [list $pm $sm $sm] 1000
+ }
+ sindex005 [list $pm btree hash] 1000
+ sindex005 [list $pm hash btree] 1000
+ }
+
+
+ # Run test with 50 secondaries.
+ foreach pm { btree hash } {
+ set methlist [list $pm]
+ for { set i 0 } { $i < 50 } { incr i } {
+ # XXX this should incorporate hash after #3726
+ if { $i % 2 == 0 } {
+ lappend methlist "dbtree"
+ } else {
+ lappend methlist "ddbtree"
+ }
+ }
+ sindex001 $methlist 500
+ sindex002 $methlist 500
+ sindex003 $methlist 500
+ sindex004 $methlist 500
+ }
+}
+
+# The callback function we use for each given secondary in most tests
+# is a simple function of its place in the list of secondaries (0-based)
+# and the access method (since recnos may need different callbacks).
+#
+# !!!
+# Note that callbacks 0-3 return unique secondary keys if the input data
+# are unique; callbacks 4 and higher may not, so don't use them with
+# the normal wordlist and secondaries that don't support dups.
+# The callbacks that incorporate a key don't work properly with recno
+# access methods, at least not in the current test framework (the
+# error_check_good lines test for e.g. 1foo, when the database has
+# e.g. 0x010x000x000x00foo).
+proc callback_n { n } {
+ switch $n {
+ 0 { return _s_reversedata }
+ 1 { return _s_noop }
+ 2 { return _s_concatkeydata }
+ 3 { return _s_concatdatakey }
+ 4 { return _s_reverseconcat }
+ 5 { return _s_truncdata }
+ 6 { return _s_alwayscocacola }
+ }
+ return _s_noop
+}
+
+proc _s_reversedata { a b } { return [reverse $b] }
+proc _s_truncdata { a b } { return [string range $b 1 end] }
+proc _s_concatkeydata { a b } { return $a$b }
+proc _s_concatdatakey { a b } { return $b$a }
+proc _s_reverseconcat { a b } { return [reverse $a$b] }
+proc _s_alwayscocacola { a b } { return "Coca-Cola" }
+proc _s_noop { a b } { return $b }
+
+# Should the check_secondary routines print lots of output?
+set verbose_check_secondaries 0
+
+# Given a primary database handle, a list of secondary handles, a
+# number of entries, and arrays of keys and data, verify that all
+# databases have what they ought to.
+proc check_secondaries { pdb sdbs nentries keyarr dataarr {pref "Check"} } {
+ upvar $keyarr keys
+ upvar $dataarr data
+ global verbose_check_secondaries
+
+ # Make sure each key/data pair is in the primary.
+ if { $verbose_check_secondaries } {
+ puts "\t\t$pref.1: Each key/data pair is in the primary"
+ }
+ for { set i 0 } { $i < $nentries } { incr i } {
+ error_check_good pdb_get($i) [$pdb get $keys($i)] \
+ [list [list $keys($i) $data($i)]]
+ }
+
+ for { set j 0 } { $j < [llength $sdbs] } { incr j } {
+ # Make sure each key/data pair is in this secondary.
+ if { $verbose_check_secondaries } {
+ puts "\t\t$pref.2:\
+ Each skey/key/data tuple is in secondary #$j"
+ }
+ for { set i 0 } { $i < $nentries } { incr i } {
+ set sdb [lindex $sdbs $j]
+ set skey [[callback_n $j] $keys($i) $data($i)]
+ error_check_good sdb($j)_pget($i) \
+ [$sdb pget -get_both $skey $keys($i)] \
+ [list [list $skey $keys($i) $data($i)]]
+ }
+
+ # Make sure this secondary contains only $nentries
+ # items.
+ if { $verbose_check_secondaries } {
+ puts "\t\t$pref.3: Secondary #$j has $nentries items"
+ }
+ set dbc [$sdb cursor]
+ error_check_good dbc($i) \
+ [is_valid_cursor $dbc $sdb] TRUE
+ for { set k 0 } { [llength [$dbc get -next]] > 0 } \
+ { incr k } { }
+ error_check_good numitems($i) $k $nentries
+ error_check_good dbc($i)_close [$dbc close] 0
+ }
+
+ if { $verbose_check_secondaries } {
+ puts "\t\t$pref.4: Primary has $nentries items"
+ }
+ set dbc [$pdb cursor]
+ error_check_good pdbc [is_valid_cursor $dbc $pdb] TRUE
+ for { set k 0 } { [llength [$dbc get -next]] > 0 } { incr k } { }
+ error_check_good numitems $k $nentries
+ error_check_good pdbc_close [$dbc close] 0
+}
+
+# Given a primary database handle and a list of secondary handles, walk
+# through the primary and make sure all the secondaries are correct,
+# then walk through the secondaries and make sure the primary is correct.
+#
+# This is slightly less rigorous than the normal check_secondaries--we
+# use it whenever we don't have up-to-date "keys" and "data" arrays.
+proc cursor_check_secondaries { pdb sdbs nentries { pref "Check" } } {
+ global verbose_check_secondaries
+
+ # Make sure each key/data pair in the primary is in each secondary.
+ set pdbc [$pdb cursor]
+ error_check_good ccs_pdbc [is_valid_cursor $pdbc $pdb] TRUE
+ set i 0
+ if { $verbose_check_secondaries } {
+ puts "\t\t$pref.1:\
+ Key/data in primary => key/data in secondaries"
+ }
+
+ for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
+ { set dbt [$pdbc get -next] } {
+ incr i
+ set pkey [lindex [lindex $dbt 0] 0]
+ set pdata [lindex [lindex $dbt 0] 1]
+ for { set j 0 } { $j < [llength $sdbs] } { incr j } {
+ set sdb [lindex $sdbs $j]
+ set sdbt [$sdb pget -get_both \
+ [[callback_n $j] $pkey $pdata] $pkey]
+ error_check_good pkey($pkey,$j) \
+ [lindex [lindex $sdbt 0] 1] $pkey
+ error_check_good pdata($pdata,$j) \
+ [lindex [lindex $sdbt 0] 2] $pdata
+ }
+ }
+ error_check_good ccs_pdbc_close [$pdbc close] 0
+ error_check_good primary_has_nentries $i $nentries
+
+ for { set j 0 } { $j < [llength $sdbs] } { incr j } {
+ if { $verbose_check_secondaries } {
+ puts "\t\t$pref.2:\
+ Key/data in secondary #$j => key/data in primary"
+ }
+ set sdb [lindex $sdbs $j]
+ set sdbc [$sdb cursor]
+ error_check_good ccs_sdbc($j) [is_valid_cursor $sdbc $sdb] TRUE
+ set i 0
+ for { set dbt [$sdbc pget -first] } { [llength $dbt] > 0 } \
+ { set dbt [$sdbc pget -next] } {
+ incr i
+ set pkey [lindex [lindex $dbt 0] 1]
+ set pdata [lindex [lindex $dbt 0] 2]
+ error_check_good pdb_get($pkey/$pdata,$j) \
+ [$pdb get -get_both $pkey $pdata] \
+ [list [list $pkey $pdata]]
+ }
+ error_check_good secondary($j)_has_nentries $i $nentries
+
+ # To exercise pget -last/pget -prev, we do it backwards too.
+ set i 0
+ for { set dbt [$sdbc pget -last] } { [llength $dbt] > 0 } \
+ { set dbt [$sdbc pget -prev] } {
+ incr i
+ set pkey [lindex [lindex $dbt 0] 1]
+ set pdata [lindex [lindex $dbt 0] 2]
+ error_check_good pdb_get_bkwds($pkey/$pdata,$j) \
+ [$pdb get -get_both $pkey $pdata] \
+ [list [list $pkey $pdata]]
+ }
+ error_check_good secondary($j)_has_nentries_bkwds $i $nentries
+
+ error_check_good ccs_sdbc_close($j) [$sdbc close] 0
+ }
+}
+
+# The secondary index tests take a list of the access methods that
+# each array ought to use. Convert at one blow into a list of converted
+# argses and omethods for each method in the list.
+proc convert_argses { methods largs } {
+ set ret {}
+ foreach m $methods {
+ lappend ret [convert_args $m $largs]
+ }
+ return $ret
+}
+proc convert_methods { methods } {
+ set ret {}
+ foreach m $methods {
+ lappend ret [convert_method $m]
+ }
+ return $ret
+}
diff --git a/bdb/test/sysscript.tcl b/bdb/test/sysscript.tcl
index 1b7545e4c6b..810b0df6cef 100644
--- a/bdb/test/sysscript.tcl
+++ b/bdb/test/sysscript.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: sysscript.tcl,v 11.12 2000/05/22 12:51:38 bostic Exp $
+# $Id: sysscript.tcl,v 11.17 2002/07/29 17:05:24 sue Exp $
#
# System integration test script.
# This script runs a single process that tests the full functionality of
@@ -31,7 +31,6 @@ source ./include.tcl
source $test_path/test.tcl
source $test_path/testutils.tcl
-set alphabet "abcdefghijklmnopqrstuvwxyz"
set mypid [pid]
set usage "sysscript dir nfiles key_avg data_avg method"
@@ -64,7 +63,7 @@ puts "$data_avg average data length"
flush stdout
# Create local environment
-set dbenv [berkdb env -txn -home $dir]
+set dbenv [berkdb_env -txn -home $dir]
set err [catch {error_check_good $mypid:dbenv [is_substr $dbenv env] 1} ret]
if {$err != 0} {
puts $ret
@@ -74,7 +73,7 @@ if {$err != 0} {
# Now open the files
for { set i 0 } { $i < $nfiles } { incr i } {
set file test044.$i.db
- set db($i) [berkdb open -env $dbenv $method $file]
+ set db($i) [berkdb open -auto_commit -env $dbenv $method $file]
set err [catch {error_check_bad $mypid:dbopen $db($i) NULL} ret]
if {$err != 0} {
puts $ret
diff --git a/bdb/test/test.tcl b/bdb/test/test.tcl
index 7678f2fcbfb..10ee9425b7a 100644
--- a/bdb/test/test.tcl
+++ b/bdb/test/test.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test.tcl,v 11.114 2001/01/09 21:28:52 sue Exp $
+# $Id: test.tcl,v 11.225 2002/09/10 18:51:38 sue Exp $
source ./include.tcl
@@ -16,6 +16,7 @@ if { [file exists $testdir] != 1 } {
global __debug_print
global __debug_on
+global __debug_test
global util_path
#
@@ -30,69 +31,52 @@ if { [string first "exec format error" $ret] != -1 } {
set util_path .
}
set __debug_print 0
-set __debug_on 0
+set encrypt 0
+set old_encrypt 0
+set passwd test_passwd
# This is where the test numbering and parameters now live.
source $test_path/testparams.tcl
-for { set i 1 } { $i <= $deadtests } {incr i} {
- set name [format "dead%03d.tcl" $i]
- source $test_path/$name
-}
-for { set i 1 } { $i <= $envtests } {incr i} {
- set name [format "env%03d.tcl" $i]
- source $test_path/$name
-}
-for { set i 1 } { $i <= $recdtests } {incr i} {
- set name [format "recd%03d.tcl" $i]
- source $test_path/$name
-}
-for { set i 1 } { $i <= $rpctests } {incr i} {
- set name [format "rpc%03d.tcl" $i]
- source $test_path/$name
-}
-for { set i 1 } { $i <= $rsrctests } {incr i} {
- set name [format "rsrc%03d.tcl" $i]
- source $test_path/$name
-}
-for { set i 1 } { $i <= $runtests } {incr i} {
- set name [format "test%03d.tcl" $i]
- # Test numbering may be sparse.
- if { [file exists $test_path/$name] == 1 } {
+# Error stream that (should!) always go to the console, even if we're
+# redirecting to ALL.OUT.
+set consoleerr stderr
+
+foreach sub $subs {
+ if { [info exists num_test($sub)] != 1 } {
+ puts stderr "Subsystem $sub has no number of tests specified in\
+ testparams.tcl; skipping."
+ continue
+ }
+ set end $num_test($sub)
+ for { set i 1 } { $i <= $end } {incr i} {
+ set name [format "%s%03d.tcl" $sub $i]
source $test_path/$name
}
}
-for { set i 1 } { $i <= $subdbtests } {incr i} {
- set name [format "sdb%03d.tcl" $i]
- source $test_path/$name
-}
source $test_path/archive.tcl
source $test_path/byteorder.tcl
source $test_path/dbm.tcl
source $test_path/hsearch.tcl
source $test_path/join.tcl
-source $test_path/lock001.tcl
-source $test_path/lock002.tcl
-source $test_path/lock003.tcl
-source $test_path/log.tcl
source $test_path/logtrack.tcl
-source $test_path/mpool.tcl
-source $test_path/mutex.tcl
source $test_path/ndbm.tcl
-source $test_path/sdbtest001.tcl
-source $test_path/sdbtest002.tcl
+source $test_path/parallel.tcl
+source $test_path/reputils.tcl
source $test_path/sdbutils.tcl
+source $test_path/shelltest.tcl
+source $test_path/sindex.tcl
source $test_path/testutils.tcl
-source $test_path/txn.tcl
source $test_path/upgrade.tcl
set dict $test_path/wordlist
set alphabet "abcdefghijklmnopqrstuvwxyz"
+set datastr "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
# Random number seed.
global rand_init
-set rand_init 1013
+set rand_init 101301
# Default record length and padding character for
# fixed record length access method(s)
@@ -103,6 +87,21 @@ set recd_debug 0
set log_log_record_types 0
set ohandles {}
+# Normally, we're not running an all-tests-in-one-env run. This matters
+# for error stream/error prefix settings in berkdb_open.
+global is_envmethod
+set is_envmethod 0
+
+# For testing locker id wrap around.
+global lock_curid
+global lock_maxid
+set lock_curid 0
+set lock_maxid 2147483647
+global txn_curid
+global txn_maxid
+set txn_curid 2147483648
+set txn_maxid 4294967295
+
# Set up any OS-specific values
global tcl_platform
set is_windows_test [is_substr $tcl_platform(os) "Win"]
@@ -112,41 +111,8 @@ set is_qnx_test [is_substr $tcl_platform(os) "QNX"]
# From here on out, test.tcl contains the procs that are used to
# run all or part of the test suite.
-proc run_am { } {
- global runtests
- source ./include.tcl
-
- fileremove -f ALL.OUT
-
- # Access method tests.
- #
- # XXX
- # Broken up into separate tclsh instantiations so we don't require
- # so much memory.
- foreach i "btree rbtree hash queue queueext recno frecno rrecno" {
- puts "Running $i tests"
- for { set j 1 } { $j <= $runtests } {incr j} {
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- run_method -$i $j $j" >>& ALL.OUT } res] {
- set o [open ALL.OUT a]
- puts $o "FAIL: [format "test%03d" $j] $i"
- close $o
- }
- }
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- subdb -$i 0 1" >>& ALL.OUT } res] {
- set o [open ALL.OUT a]
- puts $o "FAIL: subdb -$i test"
- close $o
- }
- }
-}
-
proc run_std { args } {
- global runtests
- global subdbtests
+ global num_test
source ./include.tcl
set exflgs [eval extractflags $args]
@@ -156,6 +122,7 @@ proc run_std { args } {
set display 1
set run 1
set am_only 0
+ set no_am 0
set std_only 1
set rflags {--}
foreach f $flags {
@@ -163,6 +130,10 @@ proc run_std { args } {
A {
set std_only 0
}
+ M {
+ set no_am 1
+ puts "run_std: all but access method tests."
+ }
m {
set am_only 1
puts "run_std: access method tests only."
@@ -183,7 +154,7 @@ proc run_std { args } {
puts -nonewline "Test suite run started at: "
puts [clock format [clock seconds] -format "%H:%M %D"]
puts [berkdb version -string]
-
+
puts -nonewline $o "Test suite run started at: "
puts $o [clock format [clock seconds] -format "%H:%M %D"]
puts $o [berkdb version -string]
@@ -196,16 +167,17 @@ proc run_std { args } {
{"archive" "archive"}
{"locking" "lock"}
{"logging" "log"}
- {"memory pool" "mpool"}
+ {"memory pool" "memp"}
{"mutex" "mutex"}
{"transaction" "txn"}
{"deadlock detection" "dead"}
- {"subdatabase" "subdb_gen"}
+ {"subdatabase" "sdb"}
{"byte-order" "byte"}
{"recno backing file" "rsrc"}
{"DBM interface" "dbm"}
{"NDBM interface" "ndbm"}
{"Hsearch interface" "hsearch"}
+ {"secondary index" "sindex"}
}
if { $am_only == 0 } {
@@ -229,12 +201,22 @@ proc run_std { args } {
# so we don't require so much memory, but I think it's cleaner
# and more useful to do it down inside proc r than here,
# since "r recd" gets done a lot and needs to work.
+ #
+ # Note that we still wrap the test in an exec so that
+ # its output goes to ALL.OUT. run_recd will wrap each test
+ # so that both error streams go to stdout (which here goes
+ # to ALL.OUT); information that run_recd wishes to print
+ # to the "real" stderr, but outside the wrapping for each test,
+ # such as which tests are being skipped, it can still send to
+ # stderr.
puts "Running recovery tests"
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- r $rflags recd" >>& ALL.OUT } res] {
+ if [catch {
+ exec $tclsh_path \
+ << "source $test_path/test.tcl; r $rflags recd" \
+ 2>@ stderr >> ALL.OUT
+ } res] {
set o [open ALL.OUT a]
- puts $o "FAIL: recd test"
+ puts $o "FAIL: recd tests"
close $o
}
@@ -255,38 +237,34 @@ proc run_std { args } {
}
}
- # Access method tests.
- #
- # XXX
- # Broken up into separate tclsh instantiations so we don't require
- # so much memory.
- foreach i "btree rbtree hash queue queueext recno frecno rrecno" {
- puts "Running $i tests"
- for { set j 1 } { $j <= $runtests } {incr j} {
- if { $run == 0 } {
- set o [open ALL.OUT a]
- run_method -$i $j $j $display $run $o
- close $o
- }
- if { $run } {
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- run_method -$i $j $j $display $run" \
- >>& ALL.OUT } res] {
+ if { $no_am == 0 } {
+ # Access method tests.
+ #
+ # XXX
+ # Broken up into separate tclsh instantiations so we don't
+ # require so much memory.
+ foreach i \
+ "btree hash queue queueext recno rbtree frecno rrecno" {
+ puts "Running $i tests"
+ for { set j 1 } { $j <= $num_test(test) } {incr j} {
+ if { $run == 0 } {
set o [open ALL.OUT a]
- puts $o \
- "FAIL: [format "test%03d" $j] $i"
+ run_method -$i $j $j $display $run $o
close $o
}
+ if { $run } {
+ if [catch {exec $tclsh_path \
+ << "source $test_path/test.tcl; \
+ run_method -$i $j $j $display $run"\
+ >>& ALL.OUT } res] {
+ set o [open ALL.OUT a]
+ puts $o "FAIL:\
+ [format "test%03d" $j] $i"
+ close $o
+ }
+ }
}
}
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- subdb -$i $display $run" >>& ALL.OUT } res] {
- set o [open ALL.OUT a]
- puts $o "FAIL: subdb -$i test"
- close $o
- }
}
# If not actually running, no need to check for failure.
@@ -296,14 +274,8 @@ proc run_std { args } {
return
}
- set failed 0
- set o [open ALL.OUT r]
- while { [gets $o line] >= 0 } {
- if { [regexp {^FAIL} $line] != 0 } {
- set failed 1
- }
- }
- close $o
+ set failed [check_failed_run ALL.OUT]
+
set o [open ALL.OUT a]
if { $failed == 0 } {
puts "Regression Tests Succeeded"
@@ -320,11 +292,22 @@ proc run_std { args } {
close $o
}
+proc check_failed_run { file {text "^FAIL"}} {
+ set failed 0
+ set o [open $file r]
+ while { [gets $o line] >= 0 } {
+ set ret [regexp $text $line]
+ if { $ret != 0 } {
+ set failed 1
+ }
+ }
+ close $o
+
+ return $failed
+}
+
proc r { args } {
- global envtests
- global recdtests
- global subdbtests
- global deadtests
+ global num_test
source ./include.tcl
set exflgs [eval extractflags $args]
@@ -345,68 +328,42 @@ proc r { args } {
}
if {[catch {
- set l [ lindex $args 0 ]
- switch $l {
- archive {
+ set sub [ lindex $args 0 ]
+ switch $sub {
+ byte {
if { $display } {
- puts "eval archive [lrange $args 1 end]"
+ puts "run_test byteorder"
}
if { $run } {
check_handles
- eval archive [lrange $args 1 end]
+ run_test byteorder
}
}
- byte {
- foreach method \
- "-hash -btree -recno -queue -queueext -frecno" {
- if { $display } {
- puts "byteorder $method"
- }
- if { $run } {
- check_handles
- byteorder $method
- }
- }
- }
- dbm {
- if { $display } {
- puts "dbm"
- }
+ archive -
+ dbm -
+ hsearch -
+ ndbm -
+ shelltest -
+ sindex {
+ if { $display } { puts "r $sub" }
if { $run } {
check_handles
- dbm
+ $sub
}
}
- dead {
- for { set i 1 } { $i <= $deadtests } \
- { incr i } {
- if { $display } {
- puts "eval dead00$i\
- [lrange $args 1 end]"
- }
- if { $run } {
- check_handles
- eval dead00$i\
- [lrange $args 1 end]
- }
- }
- }
- env {
- for { set i 1 } { $i <= $envtests } {incr i} {
- if { $display } {
- puts "eval env00$i"
- }
- if { $run } {
- check_handles
- eval env00$i
- }
- }
- }
- hsearch {
- if { $display } { puts "hsearch" }
+ bigfile -
+ dead -
+ env -
+ lock -
+ log -
+ memp -
+ mutex -
+ rsrc -
+ sdbtest -
+ txn {
+ if { $display } { run_subsystem $sub 1 0 }
if { $run } {
- check_handles
- hsearch
+ run_subsystem $sub
}
}
join {
@@ -419,7 +376,7 @@ proc r { args } {
}
join1 {
if { $display } { puts jointest }
- if { $run } {
+ if { $run } {
check_handles
jointest
}
@@ -467,147 +424,99 @@ proc r { args } {
jointest 512 3
}
}
- lock {
- if { $display } {
- puts \
- "eval locktest [lrange $args 1 end]"
- }
- if { $run } {
- check_handles
- eval locktest [lrange $args 1 end]
- }
- }
- log {
- if { $display } {
- puts "eval logtest [lrange $args 1 end]"
- }
- if { $run } {
- check_handles
- eval logtest [lrange $args 1 end]
- }
- }
- mpool {
- eval r $saveflags mpool1
- eval r $saveflags mpool2
- eval r $saveflags mpool3
- }
- mpool1 {
- if { $display } {
- puts "eval mpool [lrange $args 1 end]"
- }
- if { $run } {
- check_handles
- eval mpool [lrange $args 1 end]
- }
- }
- mpool2 {
- if { $display } {
- puts "eval mpool\
- -mem system [lrange $args 1 end]"
- }
- if { $run } {
- check_handles
- eval mpool\
- -mem system [lrange $args 1 end]
- }
- }
- mpool3 {
- if { $display } {
- puts "eval mpool\
- -mem private [lrange $args 1 end]"
- }
- if { $run } {
- eval mpool\
- -mem private [lrange $args 1 end]
- }
- }
- mutex {
- if { $display } {
- puts "eval mutex [lrange $args 1 end]"
- }
- if { $run } {
- check_handles
- eval mutex [lrange $args 1 end]
- }
- }
- ndbm {
- if { $display } { puts ndbm }
- if { $run } {
- check_handles
- ndbm
- }
- }
recd {
- if { $display } { puts run_recds }
- if { $run } {
- check_handles
- run_recds
- }
+ check_handles
+ run_recds $run $display [lrange $args 1 end]
}
- rpc {
- # RPC must be run as one unit due to server,
- # so just print "r rpc" in the display case.
- if { $display } { puts "r rpc" }
- if { $run } {
- check_handles
- eval rpc001
- check_handles
- eval rpc002
- if { [catch {run_rpcmethod -txn} ret]\
- != 0 } {
- puts $ret
+ rep {
+ for { set j 1 } { $j <= $num_test(test) } \
+ { incr j } {
+ if { $display } {
+ puts "eval run_test \
+ run_repmethod 0 $j $j"
}
- foreach method \
- "hash queue queueext recno frecno rrecno rbtree btree" {
- if { [catch {run_rpcmethod \
- -$method} ret] != 0 } {
- puts $ret
- }
+ if { $run } {
+ eval run_test \
+ run_repmethod 0 $j $j
}
}
- }
- rsrc {
- if { $display } { puts "rsrc001\nrsrc002" }
- if { $run } {
- check_handles
- rsrc001
- check_handles
- rsrc002
+ for { set i 1 } \
+ { $i <= $num_test(rep) } {incr i} {
+ set test [format "%s%03d" $sub $i]
+ if { $i == 2 } {
+ if { $run } {
+ puts "Skipping rep002 \
+ (waiting on SR #6195)"
+ }
+ continue
+ }
+ if { $display } {
+ puts "run_test $test"
+ }
+ if { $run } {
+ run_test $test
+ }
}
}
- subdb {
- eval r $saveflags subdb_gen
-
- foreach method \
- "btree rbtree hash queue queueext recno frecno rrecno" {
- check_handles
- eval subdb -$method $display $run
+ rpc {
+ if { $display } { puts "r $sub" }
+ global rpc_svc svc_list
+ set old_rpc_src $rpc_svc
+ foreach rpc_svc $svc_list {
+ if { !$run || \
+ ![file exist $util_path/$rpc_svc] } {
+ continue
+ }
+ run_subsystem rpc
+ if { [catch {run_rpcmethod -txn} ret] != 0 } {
+ puts $ret
+ }
+ run_test run_rpcmethod
}
+ set rpc_svc $old_rpc_src
}
- subdb_gen {
+ sec {
if { $display } {
- puts "subdbtest001 ; verify_dir"
- puts "subdbtest002 ; verify_dir"
+ run_subsystem $sub 1 0
}
if { $run } {
- check_handles
- eval subdbtest001
- verify_dir
- check_handles
- eval subdbtest002
- verify_dir
+ run_subsystem $sub 0 1
+ }
+ for { set j 1 } { $j <= $num_test(test) } \
+ { incr j } {
+ if { $display } {
+ puts "eval run_test \
+ run_secmethod $j $j"
+ puts "eval run_test \
+ run_secenv $j $j"
+ }
+ if { $run } {
+ eval run_test \
+ run_secmethod $j $j
+ eval run_test \
+ run_secenv $j $j
+ }
}
}
- txn {
+ sdb {
if { $display } {
- puts "txntest [lrange $args 1 end]"
+ puts "eval r $saveflags sdbtest"
+ for { set j 1 } \
+ { $j <= $num_test(sdb) } \
+ { incr j } {
+ puts "eval run_test \
+ subdb $j $j"
+ }
}
if { $run } {
- check_handles
- eval txntest [lrange $args 1 end]
+ eval r $saveflags sdbtest
+ for { set j 1 } \
+ { $j <= $num_test(sdb) } \
+ { incr j } {
+ eval run_test subdb $j $j
+ }
}
}
-
btree -
rbtree -
hash -
@@ -640,16 +549,44 @@ proc r { args } {
}
}
+proc run_subsystem { prefix { display 0 } { run 1} } {
+ global num_test
+ if { [info exists num_test($prefix)] != 1 } {
+ puts stderr "Subsystem $sub has no number of tests specified in\
+ testparams.tcl; skipping."
+ return
+ }
+ for { set i 1 } { $i <= $num_test($prefix) } {incr i} {
+ set name [format "%s%03d" $prefix $i]
+ if { $display } {
+ puts "eval $name"
+ }
+ if { $run } {
+ check_handles
+ catch {eval $name}
+ }
+ }
+}
+
+proc run_test { testname args } {
+ source ./include.tcl
+ foreach method "hash queue queueext recno rbtree frecno rrecno btree" {
+ check_handles
+ eval $testname -$method $args
+ verify_dir $testdir "" 1
+ }
+}
+
proc run_method { method {start 1} {stop 0} {display 0} {run 1} \
{ outfile stdout } args } {
global __debug_on
global __debug_print
+ global num_test
global parms
- global runtests
source ./include.tcl
if { $stop == 0 } {
- set stop $runtests
+ set stop $num_test(test)
}
if { $run == 1 } {
puts $outfile "run_method: $method $start $stop $args"
@@ -659,7 +596,7 @@ proc run_method { method {start 1} {stop 0} {display 0} {run 1} \
for { set i $start } { $i <= $stop } {incr i} {
set name [format "test%03d" $i]
if { [info exists parms($name)] != 1 } {
- puts "[format Test%03d $i] disabled in\
+ puts stderr "[format Test%03d $i] disabled in\
testparams.tcl; skipping."
continue
}
@@ -698,34 +635,36 @@ proc run_method { method {start 1} {stop 0} {display 0} {run 1} \
}
}
-proc run_rpcmethod { type {start 1} {stop 0} {largs ""} } {
+proc run_rpcmethod { method {start 1} {stop 0} {largs ""} } {
global __debug_on
global __debug_print
+ global num_test
global parms
- global runtests
+ global is_envmethod
+ global rpc_svc
source ./include.tcl
if { $stop == 0 } {
- set stop $runtests
+ set stop $num_test(test)
}
- puts "run_rpcmethod: $type $start $stop $largs"
+ puts "run_rpcmethod: $method $start $stop $largs"
set save_largs $largs
if { [string compare $rpc_server "localhost"] == 0 } {
- set dpid [exec $util_path/berkeley_db_svc -h $rpc_testdir &]
+ set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &]
} else {
- set dpid [exec rsh $rpc_server $rpc_path/berkeley_db_svc \
+ set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-h $rpc_testdir &]
}
puts "\tRun_rpcmethod.a: starting server, pid $dpid"
- tclsleep 2
+ tclsleep 10
remote_cleanup $rpc_server $rpc_testdir $testdir
set home [file tail $rpc_testdir]
- set txn ""
+ set is_envmethod 1
set use_txn 0
- if { [string first "txn" $type] != -1 } {
+ if { [string first "txn" $method] != -1 } {
set use_txn 1
}
if { $use_txn == 1 } {
@@ -737,7 +676,7 @@ proc run_rpcmethod { type {start 1} {stop 0} {largs ""} } {
set i 1
check_handles
remote_cleanup $rpc_server $rpc_testdir $testdir
- set env [eval {berkdb env -create -mode 0644 -home $home \
+ set env [eval {berkdb_env -create -mode 0644 -home $home \
-server $rpc_server -client_timeout 10000} -txn]
error_check_good env_open [is_valid_env $env] TRUE
@@ -746,14 +685,16 @@ proc run_rpcmethod { type {start 1} {stop 0} {largs ""} } {
set stat [catch {eval txn001_subb $ntxns $env} res]
}
error_check_good envclose [$env close] 0
+ set stat [catch {eval txn003} res]
} else {
set stat [catch {
for { set i $start } { $i <= $stop } {incr i} {
check_handles
set name [format "test%03d" $i]
if { [info exists parms($name)] != 1 } {
- puts "[format Test%03d $i] disabled in\
- testparams.tcl; skipping."
+ puts stderr "[format Test%03d $i]\
+ disabled in testparams.tcl;\
+ skipping."
continue
}
remote_cleanup $rpc_server $rpc_testdir $testdir
@@ -761,16 +702,16 @@ proc run_rpcmethod { type {start 1} {stop 0} {largs ""} } {
# Set server cachesize to 1Mb. Otherwise some
# tests won't fit (like test084 -btree).
#
- set env [eval {berkdb env -create -mode 0644 \
+ set env [eval {berkdb_env -create -mode 0644 \
-home $home -server $rpc_server \
-client_timeout 10000 \
- -cachesize {0 1048576 1} }]
+ -cachesize {0 1048576 1}}]
error_check_good env_open \
[is_valid_env $env] TRUE
append largs " -env $env "
puts "[timestamp]"
- eval $name $type $parms($name) $largs
+ eval $name $method $parms($name) $largs
if { $__debug_print != 0 } {
puts ""
}
@@ -789,37 +730,38 @@ proc run_rpcmethod { type {start 1} {stop 0} {largs ""} } {
set fnl [string first "\n" $errorInfo]
set theError [string range $errorInfo 0 [expr $fnl - 1]]
- exec $KILL $dpid
+ tclkill $dpid
if {[string first FAIL $errorInfo] == -1} {
error "FAIL:[timestamp]\
- run_rpcmethod: $type $i: $theError"
+ run_rpcmethod: $method $i: $theError"
} else {
error $theError;
}
}
- exec $KILL $dpid
-
+ set is_envmethod 0
+ tclkill $dpid
}
-proc run_rpcnoserver { type {start 1} {stop 0} {largs ""} } {
+proc run_rpcnoserver { method {start 1} {stop 0} {largs ""} } {
global __debug_on
global __debug_print
+ global num_test
global parms
- global runtests
+ global is_envmethod
source ./include.tcl
if { $stop == 0 } {
- set stop $runtests
+ set stop $num_test(test)
}
- puts "run_rpcnoserver: $type $start $stop $largs"
+ puts "run_rpcnoserver: $method $start $stop $largs"
set save_largs $largs
remote_cleanup $rpc_server $rpc_testdir $testdir
set home [file tail $rpc_testdir]
- set txn ""
+ set is_envmethod 1
set use_txn 0
- if { [string first "txn" $type] != -1 } {
+ if { [string first "txn" $method] != -1 } {
set use_txn 1
}
if { $use_txn == 1 } {
@@ -831,7 +773,7 @@ proc run_rpcnoserver { type {start 1} {stop 0} {largs ""} } {
set i 1
check_handles
remote_cleanup $rpc_server $rpc_testdir $testdir
- set env [eval {berkdb env -create -mode 0644 -home $home \
+ set env [eval {berkdb_env -create -mode 0644 -home $home \
-server $rpc_server -client_timeout 10000} -txn]
error_check_good env_open [is_valid_env $env] TRUE
@@ -846,8 +788,9 @@ proc run_rpcnoserver { type {start 1} {stop 0} {largs ""} } {
check_handles
set name [format "test%03d" $i]
if { [info exists parms($name)] != 1 } {
- puts "[format Test%03d $i] disabled in\
- testparams.tcl; skipping."
+ puts stderr "[format Test%03d $i]\
+ disabled in testparams.tcl;\
+ skipping."
continue
}
remote_cleanup $rpc_server $rpc_testdir $testdir
@@ -855,7 +798,7 @@ proc run_rpcnoserver { type {start 1} {stop 0} {largs ""} } {
# Set server cachesize to 1Mb. Otherwise some
# tests won't fit (like test084 -btree).
#
- set env [eval {berkdb env -create -mode 0644 \
+ set env [eval {berkdb_env -create -mode 0644 \
-home $home -server $rpc_server \
-client_timeout 10000 \
-cachesize {0 1048576 1} }]
@@ -864,7 +807,7 @@ proc run_rpcnoserver { type {start 1} {stop 0} {largs ""} } {
append largs " -env $env "
puts "[timestamp]"
- eval $name $type $parms($name) $largs
+ eval $name $method $parms($name) $largs
if { $__debug_print != 0 } {
puts ""
}
@@ -885,49 +828,72 @@ proc run_rpcnoserver { type {start 1} {stop 0} {largs ""} } {
set theError [string range $errorInfo 0 [expr $fnl - 1]]
if {[string first FAIL $errorInfo] == -1} {
error "FAIL:[timestamp]\
- run_rpcnoserver: $type $i: $theError"
+ run_rpcnoserver: $method $i: $theError"
} else {
error $theError;
}
+ set is_envmethod 0
}
}
#
-# Run method tests in one environment. (As opposed to run_envmethod1
-# which runs each test in its own, new environment.)
+# Run method tests in secure mode.
#
-proc run_envmethod { type {start 1} {stop 0} {largs ""} } {
+proc run_secmethod { method {start 1} {stop 0} {display 0} {run 1} \
+ { outfile stdout } args } {
+ global passwd
+
+ append largs " -encryptaes $passwd "
+ eval run_method $method $start $stop $display $run $outfile $largs
+}
+
+#
+# Run method tests in its own, new secure environment.
+#
+proc run_secenv { method {start 1} {stop 0} {largs ""} } {
global __debug_on
global __debug_print
+ global is_envmethod
+ global num_test
global parms
- global runtests
+ global passwd
source ./include.tcl
if { $stop == 0 } {
- set stop $runtests
+ set stop $num_test(test)
}
- puts "run_envmethod: $type $start $stop $largs"
+ puts "run_secenv: $method $start $stop $largs"
set save_largs $largs
env_cleanup $testdir
- set txn ""
+ set is_envmethod 1
set stat [catch {
for { set i $start } { $i <= $stop } {incr i} {
check_handles
- set env [eval {berkdb env -create -mode 0644 \
- -home $testdir}]
+ set env [eval {berkdb_env -create -mode 0644 \
+ -home $testdir -encryptaes $passwd \
+ -cachesize {0 1048576 1}}]
error_check_good env_open [is_valid_env $env] TRUE
append largs " -env $env "
puts "[timestamp]"
set name [format "test%03d" $i]
if { [info exists parms($name)] != 1 } {
- puts "[format Test%03d $i] disabled in\
+ puts stderr "[format Test%03d $i] disabled in\
testparams.tcl; skipping."
continue
}
- eval $name $type $parms($name) $largs
+
+ #
+ # Run each test multiple times in the secure env.
+ # Once with a secure env + clear database
+ # Once with a secure env + secure database
+ #
+ eval $name $method $parms($name) $largs
+ append largs " -encrypt "
+ eval $name $method $parms($name) $largs
+
if { $__debug_print != 0 } {
puts ""
}
@@ -939,7 +905,7 @@ proc run_envmethod { type {start 1} {stop 0} {largs ""} } {
set largs $save_largs
error_check_good envclose [$env close] 0
error_check_good envremove [berkdb envremove \
- -home $testdir] 0
+ -home $testdir -encryptaes $passwd] 0
}
} res]
if { $stat != 0} {
@@ -949,22 +915,476 @@ proc run_envmethod { type {start 1} {stop 0} {largs ""} } {
set theError [string range $errorInfo 0 [expr $fnl - 1]]
if {[string first FAIL $errorInfo] == -1} {
error "FAIL:[timestamp]\
- run_envmethod: $type $i: $theError"
+ run_secenv: $method $i: $theError"
} else {
error $theError;
}
+ set is_envmethod 0
}
}
-proc subdb { method display run {outfile stdout} args} {
- global subdbtests testdir
+#
+# Run replication method tests in master and client env.
+#
+proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
+ {do_sec 0} {do_oob 0} {largs "" } } {
+ source ./include.tcl
+ global __debug_on
+ global __debug_print
+ global __debug_test
+ global is_envmethod
+ global num_test
global parms
+ global passwd
+ global rand_init
- for { set i 1 } {$i <= $subdbtests} {incr i} {
+ berkdb srand $rand_init
+ set c [string index $test 0]
+ if { $c == "s" } {
+ set i [string range $test 1 end]
set name [format "subdb%03d" $i]
+ } else {
+ set i $test
+ set name [format "test%03d" $i]
+ }
+ puts "run_reptest: $method $name"
+
+ env_cleanup $testdir
+ set is_envmethod 1
+ set stat [catch {
+ if { $do_sec } {
+ set envargs "-encryptaes $passwd"
+ append largs " -encrypt "
+ } else {
+ set envargs ""
+ }
+ check_handles
+ #
+ # This will set up the master and client envs
+ # and will return us the args to pass to the
+ # test.
+ set largs [repl_envsetup \
+ $envargs $largs $test $nclients $droppct $do_oob]
+
+ puts "[timestamp]"
if { [info exists parms($name)] != 1 } {
- puts "[format Subdb%03d $i] disabled in\
+ puts stderr "[format Test%03d $i] \
+ disabled in\
+ testparams.tcl; skipping."
+ continue
+ }
+ puts -nonewline \
+ "Repl: $name: dropping $droppct%, $nclients clients "
+ if { $do_del } {
+ puts -nonewline " with delete verification;"
+ } else {
+ puts -nonewline " no delete verification;"
+ }
+ if { $do_sec } {
+ puts -nonewline " with security;"
+ } else {
+ puts -nonewline " no security;"
+ }
+ if { $do_oob } {
+ puts -nonewline " with out-of-order msgs;"
+ } else {
+ puts -nonewline " no out-of-order msgs;"
+ }
+ puts ""
+
+ eval $name $method $parms($name) $largs
+
+ if { $__debug_print != 0 } {
+ puts ""
+ }
+ if { $__debug_on != 0 } {
+ debug $__debug_test
+ }
+ flush stdout
+ flush stderr
+ repl_envprocq $i $nclients $do_oob
+ repl_envver0 $i $method $nclients
+ if { $do_del } {
+ repl_verdel $i $method $nclients
+ }
+ repl_envclose $i $envargs
+ } res]
+ if { $stat != 0} {
+ global errorInfo;
+
+ set fnl [string first "\n" $errorInfo]
+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
+ if {[string first FAIL $errorInfo] == -1} {
+ error "FAIL:[timestamp]\
+ run_reptest: $method $i: $theError"
+ } else {
+ error $theError;
+ }
+ }
+ set is_envmethod 0
+}
+
+#
+# Run replication method tests in master and client env.
+#
+proc run_repmethod { method {numcl 0} {start 1} {stop 0} {display 0}
+ {run 1} {outfile stdout} {largs ""} } {
+ source ./include.tcl
+ global __debug_on
+ global __debug_print
+ global __debug_test
+ global is_envmethod
+ global num_test
+ global parms
+ global passwd
+ global rand_init
+
+ set stopsdb $num_test(sdb)
+ if { $stop == 0 } {
+ set stop $num_test(test)
+ } else {
+ if { $stopsdb > $stop } {
+ set stopsdb $stop
+ }
+ }
+ berkdb srand $rand_init
+
+ #
+ # We want to run replication both normally and with crypto.
+ # So run it once and then run again with crypto.
+ #
+ set save_largs $largs
+ env_cleanup $testdir
+
+ if { $display == 1 } {
+ for { set i $start } { $i <= $stop } { incr i } {
+ puts $outfile "eval run_repmethod $method \
+ 0 $i $i 0 1 stdout $largs"
+ }
+ }
+ if { $run == 1 } {
+ set is_envmethod 1
+ #
+ # Use an array for number of clients because we really don't
+ # want to evenly-weight all numbers of clients. Favor smaller
+ # numbers but test more clients occasionally.
+ set drop_list { 0 0 0 0 0 1 1 5 5 10 20 }
+ set drop_len [expr [llength $drop_list] - 1]
+ set client_list { 1 1 2 1 1 1 2 2 3 1 }
+ set cl_len [expr [llength $client_list] - 1]
+ set stat [catch {
+ for { set i $start } { $i <= $stopsdb } {incr i} {
+ if { $numcl == 0 } {
+ set clindex [berkdb random_int 0 $cl_len]
+ set nclients [lindex $client_list $clindex]
+ } else {
+ set nclients $numcl
+ }
+ set drindex [berkdb random_int 0 $drop_len]
+ set droppct [lindex $drop_list $drindex]
+ set do_sec [berkdb random_int 0 1]
+ set do_oob [berkdb random_int 0 1]
+ set do_del [berkdb random_int 0 1]
+
+ if { $do_sec } {
+ set envargs "-encryptaes $passwd"
+ append largs " -encrypt "
+ } else {
+ set envargs ""
+ }
+ check_handles
+ #
+ # This will set up the master and client envs
+ # and will return us the args to pass to the
+ # test.
+ set largs [repl_envsetup $envargs $largs \
+ $i $nclients $droppct $do_oob]
+
+ puts "[timestamp]"
+ set name [format "subdb%03d" $i]
+ if { [info exists parms($name)] != 1 } {
+ puts stderr "[format Subdb%03d $i] \
+ disabled in\
+ testparams.tcl; skipping."
+ continue
+ }
+ puts -nonewline "Repl: $name: dropping $droppct%, \
+ $nclients clients "
+ if { $do_del } {
+ puts -nonewline " with delete verification;"
+ } else {
+ puts -nonewline " no delete verification;"
+ }
+ if { $do_sec } {
+ puts -nonewline " with security;"
+ } else {
+ puts -nonewline " no security;"
+ }
+ if { $do_oob } {
+ puts -nonewline " with out-of-order msgs;"
+ } else {
+ puts -nonewline " no out-of-order msgs;"
+ }
+ puts ""
+
+ eval $name $method $parms($name) $largs
+
+ if { $__debug_print != 0 } {
+ puts ""
+ }
+ if { $__debug_on != 0 } {
+ debug $__debug_test
+ }
+ flush stdout
+ flush stderr
+ repl_envprocq $i $nclients $do_oob
+ repl_envver0 $i $method $nclients
+ if { $do_del } {
+ repl_verdel $i $method $nclients
+ }
+ repl_envclose $i $envargs
+ set largs $save_largs
+ }
+ } res]
+ if { $stat != 0} {
+ global errorInfo;
+
+ set fnl [string first "\n" $errorInfo]
+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
+ if {[string first FAIL $errorInfo] == -1} {
+ error "FAIL:[timestamp]\
+ run_repmethod: $method $i: $theError"
+ } else {
+ error $theError;
+ }
+ }
+ set stat [catch {
+ for { set i $start } { $i <= $stop } {incr i} {
+ if { $numcl == 0 } {
+ set clindex [berkdb random_int 0 $cl_len]
+ set nclients [lindex $client_list $clindex]
+ } else {
+ set nclients $numcl
+ }
+ set drindex [berkdb random_int 0 $drop_len]
+ set droppct [lindex $drop_list $drindex]
+ set do_sec [berkdb random_int 0 1]
+ set do_oob [berkdb random_int 0 1]
+ set do_del [berkdb random_int 0 1]
+
+ if { $do_sec } {
+ set envargs "-encryptaes $passwd"
+ append largs " -encrypt "
+ } else {
+ set envargs ""
+ }
+ check_handles
+ #
+ # This will set up the master and client envs
+ # and will return us the args to pass to the
+ # test.
+ set largs [repl_envsetup $envargs $largs \
+ $i $nclients $droppct $do_oob]
+
+ puts "[timestamp]"
+ set name [format "test%03d" $i]
+ if { [info exists parms($name)] != 1 } {
+ puts stderr "[format Test%03d $i] \
+ disabled in\
+ testparams.tcl; skipping."
+ continue
+ }
+ puts -nonewline "Repl: $name: dropping $droppct%, \
+ $nclients clients "
+ if { $do_del } {
+ puts -nonewline " with delete verification;"
+ } else {
+ puts -nonewline " no delete verification;"
+ }
+ if { $do_sec } {
+ puts -nonewline " with security;"
+ } else {
+ puts -nonewline " no security;"
+ }
+ if { $do_oob } {
+ puts -nonewline " with out-of-order msgs;"
+ } else {
+ puts -nonewline " no out-of-order msgs;"
+ }
+ puts ""
+
+ eval $name $method $parms($name) $largs
+
+ if { $__debug_print != 0 } {
+ puts ""
+ }
+ if { $__debug_on != 0 } {
+ debug $__debug_test
+ }
+ flush stdout
+ flush stderr
+ repl_envprocq $i $nclients $do_oob
+ repl_envver0 $i $method $nclients
+ if { $do_del } {
+ repl_verdel $i $method $nclients
+ }
+ repl_envclose $i $envargs
+ set largs $save_largs
+ }
+ } res]
+ if { $stat != 0} {
+ global errorInfo;
+
+ set fnl [string first "\n" $errorInfo]
+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
+ if {[string first FAIL $errorInfo] == -1} {
+ error "FAIL:[timestamp]\
+ run_repmethod: $method $i: $theError"
+ } else {
+ error $theError;
+ }
+ }
+ set is_envmethod 0
+ }
+}
+
+#
+# Run method tests, each in its own, new environment. (As opposed to
+# run_envmethod1 which runs all the tests in a single environment.)
+#
+proc run_envmethod { method {start 1} {stop 0} {display 0} {run 1} \
+ {outfile stdout } { largs "" } } {
+ global __debug_on
+ global __debug_print
+ global __debug_test
+ global is_envmethod
+ global num_test
+ global parms
+ source ./include.tcl
+
+ set stopsdb $num_test(sdb)
+ if { $stop == 0 } {
+ set stop $num_test(test)
+ } else {
+ if { $stopsdb > $stop } {
+ set stopsdb $stop
+ }
+ }
+
+ set save_largs $largs
+ env_cleanup $testdir
+
+ if { $display == 1 } {
+ for { set i $start } { $i <= $stop } { incr i } {
+ puts $outfile "eval run_envmethod $method \
+ $i $i 0 1 stdout $largs"
+ }
+ }
+
+ if { $run == 1 } {
+ set is_envmethod 1
+ #
+ # Run both subdb and normal tests for as long as there are
+ # some of each type. Start with the subdbs:
+ set stat [catch {
+ for { set i $start } { $i <= $stopsdb } {incr i} {
+ check_handles
+ set env [eval {berkdb_env -create -txn \
+ -mode 0644 -home $testdir}]
+ error_check_good env_open \
+ [is_valid_env $env] TRUE
+ append largs " -env $env "
+
+ puts "[timestamp]"
+ set name [format "subdb%03d" $i]
+ if { [info exists parms($name)] != 1 } {
+ puts stderr \
+ "[format Subdb%03d $i] disabled in\
+ testparams.tcl; skipping."
+ continue
+ }
+ eval $name $method $parms($name) $largs
+
+ error_check_good envclose [$env close] 0
+ error_check_good envremove [berkdb envremove \
+ -home $testdir] 0
+ flush stdout
+ flush stderr
+ set largs $save_largs
+ }
+ } res]
+ if { $stat != 0} {
+ global errorInfo;
+
+ set fnl [string first "\n" $errorInfo]
+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
+ if {[string first FAIL $errorInfo] == -1} {
+ error "FAIL:[timestamp]\
+ run_envmethod: $method $i: $theError"
+ } else {
+ error $theError;
+ }
+ }
+ # Subdb tests are done, now run through the regular tests:
+ set stat [catch {
+ for { set i $start } { $i <= $stop } {incr i} {
+ check_handles
+ set env [eval {berkdb_env -create -txn \
+ -mode 0644 -home $testdir}]
+ error_check_good env_open \
+ [is_valid_env $env] TRUE
+ append largs " -env $env "
+
+ puts "[timestamp]"
+ set name [format "test%03d" $i]
+ if { [info exists parms($name)] != 1 } {
+ puts stderr \
+ "[format Test%03d $i] disabled in\
+ testparams.tcl; skipping."
+ continue
+ }
+ eval $name $method $parms($name) $largs
+
+ if { $__debug_print != 0 } {
+ puts ""
+ }
+ if { $__debug_on != 0 } {
+ debug $__debug_test
+ }
+ flush stdout
+ flush stderr
+ set largs $save_largs
+ error_check_good envclose [$env close] 0
+ error_check_good envremove [berkdb envremove \
+ -home $testdir] 0
+ }
+ } res]
+ if { $stat != 0} {
+ global errorInfo;
+
+ set fnl [string first "\n" $errorInfo]
+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
+ if {[string first FAIL $errorInfo] == -1} {
+ error "FAIL:[timestamp]\
+ run_envmethod: $method $i: $theError"
+ } else {
+ error $theError;
+ }
+ }
+ set is_envmethod 0
+ }
+}
+
+proc subdb { method {start 1} {stop 0} {display 0} {run 1} \
+ {outfile stdout} args} {
+ global num_test testdir
+ global parms
+
+ for { set i $start } { $i <= $stop } {incr i} {
+ set name [format "subdb%03d" $i]
+ if { [info exists parms($name)] != 1 } {
+ puts stderr "[format Subdb%03d $i] disabled in\
testparams.tcl; skipping."
continue
}
@@ -983,37 +1403,63 @@ proc subdb { method display run {outfile stdout} args} {
}
}
-proc run_recd { method {start 1} {stop 0} args } {
+proc run_recd { method {start 1} {stop 0} {run 1} {display 0} args } {
global __debug_on
global __debug_print
+ global __debug_test
global parms
- global recdtests
+ global num_test
global log_log_record_types
source ./include.tcl
if { $stop == 0 } {
- set stop $recdtests
+ set stop $num_test(recd)
+ }
+ if { $run == 1 } {
+ puts "run_recd: $method $start $stop $args"
}
- puts "run_recd: $method $start $stop $args"
if {[catch {
for { set i $start } { $i <= $stop } {incr i} {
- check_handles
- puts "[timestamp]"
set name [format "recd%03d" $i]
- # By redirecting stdout to stdout, we make exec
- # print output rather than simply returning it.
- exec $tclsh_path << "source $test_path/test.tcl; \
- set log_log_record_types $log_log_record_types; \
- eval $name $method" >@ stdout
- if { $__debug_print != 0 } {
- puts ""
+ if { [info exists parms($name)] != 1 } {
+ puts stderr "[format Recd%03d $i] disabled in\
+ testparams.tcl; skipping."
+ continue
}
- if { $__debug_on != 0 } {
- debug
+ if { $display } {
+ puts "eval $name $method $parms($name) $args"
+ }
+ if { $run } {
+ check_handles
+ puts "[timestamp]"
+ # By redirecting stdout to stdout, we make exec
+ # print output rather than simply returning it.
+ # By redirecting stderr to stdout too, we make
+ # sure everything winds up in the ALL.OUT file.
+ set ret [catch { exec $tclsh_path << \
+ "source $test_path/test.tcl; \
+ set log_log_record_types \
+ $log_log_record_types; eval $name \
+ $method $parms($name) $args" \
+ >&@ stdout
+ } res]
+
+ # Don't die if the test failed; we want
+ # to just proceed.
+ if { $ret != 0 } {
+ puts "FAIL:[timestamp] $res"
+ }
+
+ if { $__debug_print != 0 } {
+ puts ""
+ }
+ if { $__debug_on != 0 } {
+ debug $__debug_test
+ }
+ flush stdout
+ flush stderr
}
- flush stdout
- flush stderr
}
} res] != 0} {
global errorInfo;
@@ -1029,7 +1475,7 @@ proc run_recd { method {start 1} {stop 0} args } {
}
}
-proc run_recds { } {
+proc run_recds { {run 1} {display 0} args } {
global log_log_record_types
set log_log_record_types 1
@@ -1037,18 +1483,19 @@ proc run_recds { } {
foreach method \
"btree rbtree hash queue queueext recno frecno rrecno" {
check_handles
- if { [catch \
- {run_recd -$method} ret ] != 0 } {
+ if { [catch {eval \
+ run_recd -$method 1 0 $run $display $args} ret ] != 0 } {
puts $ret
}
}
- logtrack_summary
+ if { $run } {
+ logtrack_summary
+ }
set log_log_record_types 0
}
proc run_all { args } {
- global runtests
- global subdbtests
+ global num_test
source ./include.tcl
fileremove -f ALL.OUT
@@ -1058,6 +1505,8 @@ proc run_all { args } {
set display 1
set run 1
set am_only 0
+ set parallel 0
+ set nparalleltests 0
set rflags {--}
foreach f $flags {
switch $f {
@@ -1091,51 +1540,60 @@ proc run_all { args } {
lappend args -A
eval {run_std} $args
- set test_pagesizes { 512 8192 65536 }
+ set test_pagesizes [get_test_pagesizes]
set args [lindex $exflgs 0]
set save_args $args
foreach pgsz $test_pagesizes {
set args $save_args
- append args " -pagesize $pgsz"
+ append args " -pagesize $pgsz -chksum"
if { $am_only == 0 } {
# Run recovery tests.
#
+ # XXX These don't actually work at multiple pagesizes;
+ # disable them for now.
+ #
# XXX These too are broken into separate tclsh
- # instantiations so we don't require so much
+ # instantiations so we don't require so much
# memory, but I think it's cleaner
# and more useful to do it down inside proc r than here,
# since "r recd" gets done a lot and needs to work.
- puts "Running recovery tests with pagesize $pgsz"
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- r $rflags recd $args" >>& ALL.OUT } res] {
- set o [open ALL.OUT a]
- puts $o "FAIL: recd test"
- close $o
- }
+ #
+ # XXX See comment in run_std for why this only directs
+ # stdout and not stderr. Don't worry--the right stuff
+ # happens.
+ #puts "Running recovery tests with pagesize $pgsz"
+ #if [catch {exec $tclsh_path \
+ # << "source $test_path/test.tcl; \
+ # r $rflags recd $args" \
+ # 2>@ stderr >> ALL.OUT } res] {
+ # set o [open ALL.OUT a]
+ # puts $o "FAIL: recd test:"
+ # puts $o $res
+ # close $o
+ #}
}
-
+
# Access method tests.
#
# XXX
- # Broken up into separate tclsh instantiations so
+ # Broken up into separate tclsh instantiations so
# we don't require so much memory.
foreach i \
"btree rbtree hash queue queueext recno frecno rrecno" {
puts "Running $i tests with pagesize $pgsz"
- for { set j 1 } { $j <= $runtests } {incr j} {
+ for { set j 1 } { $j <= $num_test(test) } {incr j} {
if { $run == 0 } {
set o [open ALL.OUT a]
- run_method -$i $j $j $display \
- $run $o $args
+ eval {run_method -$i $j $j $display \
+ $run $o} $args
close $o
}
if { $run } {
if [catch {exec $tclsh_path \
<< "source $test_path/test.tcl; \
- run_method -$i $j $j $display \
- $run stdout $args" \
+ eval {run_method -$i $j $j \
+ $display $run stdout} $args" \
>>& ALL.OUT } res] {
set o [open ALL.OUT a]
puts $o \
@@ -1149,47 +1607,82 @@ proc run_all { args } {
#
# Run subdb tests with varying pagesizes too.
#
+ for { set j 1 } { $j <= $num_test(sdb) } {incr j} {
+ if { $run == 0 } {
+ set o [open ALL.OUT a]
+ eval {subdb -$i $j $j $display \
+ $run $o} $args
+ close $o
+ }
+ if { $run == 1 } {
+ if [catch {exec $tclsh_path \
+ << "source $test_path/test.tcl; \
+ eval {subdb -$i $j $j $display \
+ $run stdout} $args" \
+ >>& ALL.OUT } res] {
+ set o [open ALL.OUT a]
+ puts $o "FAIL: subdb -$i $j $j"
+ close $o
+ }
+ }
+ }
+ }
+ }
+ set args $save_args
+ #
+ # Run access method tests at default page size in one env.
+ #
+ foreach i "btree rbtree hash queue queueext recno frecno rrecno" {
+ puts "Running $i tests in a txn env"
+ for { set j 1 } { $j <= $num_test(test) } { incr j } {
if { $run == 0 } {
set o [open ALL.OUT a]
- subdb -$i $display $run $o $args
+ run_envmethod -$i $j $j $display \
+ $run $o $args
close $o
}
- if { $run == 1 } {
+ if { $run } {
if [catch {exec $tclsh_path \
<< "source $test_path/test.tcl; \
- subdb -$i $display $run stdout $args" \
+ run_envmethod -$i $j $j \
+ $display $run stdout $args" \
>>& ALL.OUT } res] {
set o [open ALL.OUT a]
- puts $o "FAIL: subdb -$i test"
+ puts $o \
+ "FAIL: run_envmethod $i $j $j"
close $o
}
}
}
}
- set args $save_args
#
- # Run access method tests at default page size in one env.
+ # Run tests using proc r. The replication tests have been
+ # moved from run_std to run_all.
#
- foreach i "btree rbtree hash queue queueext recno frecno rrecno" {
- puts "Running $i tests in an env"
- if { $run == 0 } {
+ set test_list {
+ {"replication" "rep"}
+ {"security" "sec"}
+ }
+ #
+ # If configured for RPC, then run rpc tests too.
+ #
+ if { [file exists ./berkeley_db_svc] ||
+ [file exists ./berkeley_db_cxxsvc] ||
+ [file exists ./berkeley_db_javasvc] } {
+ append test_list {{"RPC" "rpc"}}
+ }
+
+ foreach pair $test_list {
+ set msg [lindex $pair 0]
+ set cmd [lindex $pair 1]
+ puts "Running $msg tests"
+ if [catch {exec $tclsh_path \
+ << "source $test_path/test.tcl; \
+ r $rflags $cmd $args" >>& ALL.OUT } res] {
set o [open ALL.OUT a]
- run_envmethod1 -$i 1 $runtests $display \
- $run $o $args
+ puts $o "FAIL: $cmd test"
close $o
}
- if { $run } {
- if [catch {exec $tclsh_path \
- << "source $test_path/test.tcl; \
- run_envmethod1 -$i 1 $runtests $display \
- $run stdout $args" \
- >>& ALL.OUT } res] {
- set o [open ALL.OUT a]
- puts $o \
- "FAIL: run_envmethod1 $i"
- close $o
- }
- }
}
# If not actually running, no need to check for failure.
@@ -1229,58 +1722,97 @@ proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
{ outfile stdout } args } {
global __debug_on
global __debug_print
+ global __debug_test
+ global is_envmethod
+ global num_test
global parms
- global runtests
source ./include.tcl
+ set stopsdb $num_test(sdb)
if { $stop == 0 } {
- set stop $runtests
+ set stop $num_test(test)
+ } else {
+ if { $stopsdb > $stop } {
+ set stopsdb $stop
+ }
}
if { $run == 1 } {
puts "run_envmethod1: $method $start $stop $args"
}
- set txn ""
+ set is_envmethod 1
if { $run == 1 } {
check_handles
env_cleanup $testdir
error_check_good envremove [berkdb envremove -home $testdir] 0
- set env [eval {berkdb env -create -mode 0644 -home $testdir}]
+ set env [eval {berkdb_env -create -cachesize {0 10000000 0}} \
+ {-mode 0644 -home $testdir}]
error_check_good env_open [is_valid_env $env] TRUE
append largs " -env $env "
}
+ if { $display } {
+ # The envmethod1 tests can't be split up, since they share
+ # an env.
+ puts $outfile "eval run_envmethod1 $method $args"
+ }
+
+ set stat [catch {
+ for { set i $start } { $i <= $stopsdb } {incr i} {
+ set name [format "subdb%03d" $i]
+ if { [info exists parms($name)] != 1 } {
+ puts stderr "[format Subdb%03d $i] disabled in\
+ testparams.tcl; skipping."
+ continue
+ }
+ if { $run } {
+ puts $outfile "[timestamp]"
+ eval $name $method $parms($name) $largs
+ if { $__debug_print != 0 } {
+ puts $outfile ""
+ }
+ if { $__debug_on != 0 } {
+ debug $__debug_test
+ }
+ }
+ flush stdout
+ flush stderr
+ }
+ } res]
+ if { $stat != 0} {
+ global errorInfo;
+
+ set fnl [string first "\n" $errorInfo]
+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
+ if {[string first FAIL $errorInfo] == -1} {
+ error "FAIL:[timestamp]\
+ run_envmethod: $method $i: $theError"
+ } else {
+ error $theError;
+ }
+ }
set stat [catch {
for { set i $start } { $i <= $stop } {incr i} {
set name [format "test%03d" $i]
if { [info exists parms($name)] != 1 } {
- puts "[format Test%03d $i] disabled in\
- testparams.tcl; skipping."
+ puts stderr "[format Test%03d $i] disabled in\
+ testparams.tcl; skipping."
continue
}
- if { $display } {
- puts -nonewline $outfile "eval $name $method"
- puts -nonewline $outfile " $parms($name) $args"
- puts $outfile " ; verify_dir $testdir \"\" 1"
- }
if { $run } {
- check_handles $outfile
puts $outfile "[timestamp]"
eval $name $method $parms($name) $largs
if { $__debug_print != 0 } {
puts $outfile ""
}
if { $__debug_on != 0 } {
- debug
+ debug $__debug_test
}
}
flush stdout
flush stderr
}
} res]
- if { $run == 1 } {
- error_check_good envclose [$env close] 0
- }
if { $stat != 0} {
global errorInfo;
@@ -1293,5 +1825,39 @@ proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
error $theError;
}
}
+ if { $run == 1 } {
+ error_check_good envclose [$env close] 0
+ check_handles $outfile
+ }
+ set is_envmethod 0
+
+}
+
+# We want to test all of 512b, 8Kb, and 64Kb pages, but chances are one
+# of these is the default pagesize. We don't want to run all the AM tests
+# twice, so figure out what the default page size is, then return the
+# other two.
+proc get_test_pagesizes { } {
+ # Create an in-memory database.
+ set db [berkdb_open -create -btree]
+ error_check_good gtp_create [is_valid_db $db] TRUE
+ set statret [$db stat]
+ set pgsz 0
+ foreach pair $statret {
+ set fld [lindex $pair 0]
+ if { [string compare $fld {Page size}] == 0 } {
+ set pgsz [lindex $pair 1]
+ }
+ }
+ error_check_good gtp_close [$db close] 0
+
+ error_check_bad gtp_pgsz $pgsz 0
+ switch $pgsz {
+ 512 { return {8192 32768} }
+ 8192 { return {512 32768} }
+ 32768 { return {512 8192} }
+ default { return {512 8192 32768} }
+ }
+ error_check_good NOTREACHED 0 1
}
diff --git a/bdb/test/test001.tcl b/bdb/test/test001.tcl
index fa8e112d100..f0b562bbf24 100644
--- a/bdb/test/test001.tcl
+++ b/bdb/test/test001.tcl
@@ -1,45 +1,85 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test001.tcl,v 11.17 2000/12/06 16:08:05 bostic Exp $
+# $Id: test001.tcl,v 11.28 2002/08/08 15:38:11 bostic Exp $
#
-# DB Test 1 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; retrieve each.
-# After all are entered, retrieve all; compare output to original.
-# Close file, reopen, do retrieve and re-verify.
-proc test001 { method {nentries 10000} {start 0} {tnum "01"} args } {
+# TEST test001
+# TEST Small keys/data
+# TEST Put/get per key
+# TEST Dump file
+# TEST Close, reopen
+# TEST Dump file
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Close file, reopen, do retrieve and re-verify.
+proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args } {
source ./include.tcl
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Test0$tnum: $method ($args) $nentries equal key/data pairs"
- if { $start != 0 } {
- puts "\tStarting at $start"
- }
-
# Create the database and open the dictionary
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
+ # If we are not using an external env, then test setting
+ # the database cache size and using multiple caches.
+ set txnenv 0
if { $eindex == -1 } {
set testfile $testdir/test0$tnum.db
+ append args " -cachesize {0 1048576 3} "
set env NULL
} else {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
+ }
+ puts "Test0$tnum: $method ($args) $nentries equal key/data pairs"
+ if { $start != 0 } {
+ # Sadly enough, we are using start in two different ways.
+ # In test090, it is used to test really big records numbers
+ # in queue. In replication, it is used to be able to run
+ # different iterations of this test using different key/data
+ # pairs. We try to hide all that magic here.
+ puts "\tStarting at $start"
+
+ if { $tnum != 90 } {
+ set did [open $dict]
+ for { set nlines 0 } { [gets $did str] != -1 } \
+ { incr nlines} {
+ }
+ close $did
+ if { $start + $nentries > $nlines } {
+ set start [expr $nlines - $nentries]
+ }
+ }
}
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
- cleanup $testdir $env
+ if { $noclean == 0 } {
+ cleanup $testdir $env
+ }
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args $omethod $testfile]
+ -create -mode 0644} $args $omethod $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -47,8 +87,6 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} args } {
set gflags ""
set txn ""
- set nentries [expr $nentries + $start]
-
if { [is_record_based $method] == 1 } {
set checkfunc test001_recno.check
append gflags " -recno"
@@ -57,20 +95,46 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} args } {
}
puts "\tTest0$tnum.a: put/get loop"
# Here is the loop where we put and get each key/data pair
- set count $start
+ set count 0
+ if { $start != 0 && $tnum != 90 } {
+ # Skip over "start" entries
+ for { set count 0 } { $count < $start } { incr count } {
+ gets $did str
+ }
+ set count 0
+ }
while { [gets $did str] != -1 && $count < $nentries } {
if { [is_record_based $method] == 1 } {
global kvals
- set key [expr $count + 1]
+ set key [expr $count + 1 + $start]
+ if { 0xffffffff > 0 && $key > 0xffffffff } {
+ set key [expr $key - 0x100000000]
+ }
+ if { $key == 0 || $key - 0xffffffff == 1 } {
+ incr key
+ incr count
+ }
set kvals($key) [pad_data $method $str]
} else {
set key $str
set str [reverse $str]
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval \
{$db put} $txn $pflags {$key [chop_data $method $str]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ if { $count % 50 == 0 } {
+ error_check_good txn_checkpoint($count) \
+ [$env txn_checkpoint] 0
+ }
+ }
set ret [eval {$db get} $gflags {$key}]
error_check_good \
@@ -86,30 +150,56 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} args } {
error_check_good getbothBAD [llength $ret] 0
incr count
- if { [expr $count + 1] == 0 } {
- incr count
- }
}
close $did
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest0$tnum.b: dump file"
dump_file $db $txn $t1 $checkfunc
+ #
+ # dump_file should just have been "get" calls, so
+ # aborting a get should really be a no-op. Abort
+ # just for the fun of it.
+ if { $txnenv == 1 } {
+ error_check_good txn [$t abort] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary (or ints)
if { [is_record_based $method] == 1 } {
set oid [open $t2 w]
- for {set i [expr $start + 1]} {$i <= $nentries} {set i [incr i]} {
- if { $i == 0 } {
- incr i
+ # If this is test 90, we're checking wrap and we really
+ # only added nentries number of items starting at start.
+ # However, if this isn't 90, then we started at start and
+ # added an addition nentries number of items.
+ if { $tnum == 90 } {
+ for {set i 1} {$i <= $nentries} {incr i} {
+ set j [expr $i + $start]
+ if { 0xffffffff > 0 && $j > 0xffffffff } {
+ set j [expr $j - 0x100000000]
+ }
+ if { $j == 0 } {
+ incr i
+ incr j
+ }
+ puts $oid $j
+ }
+ } else {
+ for { set i 1 } { $i <= $nentries + $start } {incr i} {
+ puts $oid $i
}
- puts $oid $i
}
close $oid
} else {
set q q
- filehead $nentries $dict $t2
+ # We assume that when this is used with start != 0, the
+ # test database accumulates data
+ filehead [expr $nentries + $start] $dict $t2
}
filesort $t2 $t3
file rename -force $t3 $t2
@@ -120,7 +210,7 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} args } {
puts "\tTest0$tnum.c: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_file_direction "-first" "-next"
if { [string compare $omethod "-recno"] != 0 } {
filesort $t1 $t3
@@ -132,7 +222,7 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} args } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_file_direction "-last" "-prev"
if { [string compare $omethod "-recno"] != 0 } {
diff --git a/bdb/test/test002.tcl b/bdb/test/test002.tcl
index 882240b77bb..bc28994d6a7 100644
--- a/bdb/test/test002.tcl
+++ b/bdb/test/test002.tcl
@@ -1,17 +1,21 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test002.tcl,v 11.13 2000/08/25 14:21:53 sue Exp $
+# $Id: test002.tcl,v 11.19 2002/05/22 15:42:43 sue Exp $
#
-# DB Test 2 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and a fixed, medium length data string;
-# retrieve each. After all are entered, retrieve all; compare output
-# to original. Close file, reopen, do retrieve and re-verify.
-
-set datastr abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+# TEST test002
+# TEST Small keys/medium data
+# TEST Put/get per key
+# TEST Dump file
+# TEST Close, reopen
+# TEST Dump file
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and a fixed, medium length data string;
+# TEST retrieve each. After all are entered, retrieve all; compare output
+# TEST to original. Close file, reopen, do retrieve and re-verify.
proc test002 { method {nentries 10000} args } {
global datastr
@@ -21,8 +25,7 @@ proc test002 { method {nentries 10000} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Test002: $method ($args) $nentries key <fixed data> pairs"
-
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -34,14 +37,28 @@ proc test002 { method {nentries 10000} args } {
set testfile test002.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
# Create the database and open the dictionary
+ puts "Test002: $method ($args) $nentries key <fixed data> pairs"
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -63,8 +80,16 @@ proc test002 { method {nentries 10000} args } {
} else {
set key $str
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn $pflags {$key [chop_data $method $datastr]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set ret [eval {$db get} $gflags {$key}]
@@ -76,7 +101,15 @@ proc test002 { method {nentries 10000} args } {
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest002.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 test002.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary
@@ -100,7 +133,7 @@ proc test002 { method {nentries 10000} args } {
# Now, reopen the file and run the last test again.
puts "\tTest002.c: close, open, and dump file"
- open_and_dump_file $testfile $env $txn $t1 test002.check \
+ open_and_dump_file $testfile $env $t1 test002.check \
dump_file_direction "-first" "-next"
if { [string compare $omethod "-recno"] != 0 } {
@@ -111,7 +144,7 @@ proc test002 { method {nentries 10000} args } {
# Now, reopen the file and run the last test again in reverse direction.
puts "\tTest002.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 test002.check \
+ open_and_dump_file $testfile $env $t1 test002.check \
dump_file_direction "-last" "-prev"
if { [string compare $omethod "-recno"] != 0 } {
diff --git a/bdb/test/test003.tcl b/bdb/test/test003.tcl
index 013af2d419c..c7bfe6c15ad 100644
--- a/bdb/test/test003.tcl
+++ b/bdb/test/test003.tcl
@@ -1,14 +1,21 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test003.tcl,v 11.18 2000/08/25 14:21:54 sue Exp $
+# $Id: test003.tcl,v 11.25 2002/05/22 18:32:18 sue Exp $
#
-# DB Test 3 {access method}
-# Take the source files and dbtest executable and enter their names as the
-# key with their contents as data. After all are entered, retrieve all;
-# compare output to original. Close file, reopen, do retrieve and re-verify.
+# TEST test003
+# TEST Small keys/large data
+# TEST Put/get per key
+# TEST Dump file
+# TEST Close, reopen
+# TEST Dump file
+# TEST
+# TEST Take the source files and dbtest executable and enter their names
+# TEST as the key with their contents as data. After all are entered,
+# TEST retrieve all; compare output to original. Close file, reopen, do
+# TEST retrieve and re-verify.
proc test003 { method args} {
global names
source ./include.tcl
@@ -23,6 +30,8 @@ proc test003 { method args} {
puts "Test003: $method ($args) filename=key filecontents=data pairs"
# Create the database and open the dictionary
+ set limit 0
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -34,6 +43,12 @@ proc test003 { method args} {
set testfile test003.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ set limit 100
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -42,7 +57,7 @@ proc test003 { method args} {
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args $omethod $testfile]
+ -create -mode 0644} $args $omethod $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
set pflags ""
set gflags ""
@@ -55,11 +70,14 @@ proc test003 { method args} {
}
# Here is the loop where we put and get each key/data pair
- set file_list [ glob \
- { $test_path/../*/*.[ch] } $test_path/*.tcl *.{a,o,lo,exe} \
- $test_path/file.1 ]
-
- puts "\tTest003.a: put/get loop"
+ set file_list [get_file_list]
+ if { $limit } {
+ if { [llength $file_list] > $limit } {
+ set file_list [lrange $file_list 1 $limit]
+ }
+ }
+ set len [llength $file_list]
+ puts "\tTest003.a: put/get loop $len entries"
set count 0
foreach f $file_list {
if { [string compare [file type $f] "file"] != 0 } {
@@ -78,9 +96,17 @@ proc test003 { method args} {
fconfigure $fid -translation binary
set data [read $fid]
close $fid
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $data]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Should really catch errors
set fid [open $t4 w]
@@ -104,7 +130,15 @@ proc test003 { method args} {
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest003.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_bin_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the entries in the
@@ -135,7 +169,7 @@ proc test003 { method args} {
# Now, reopen the file and run the last test again.
puts "\tTest003.c: close, open, and dump file"
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_bin_file_direction "-first" "-next"
if { [is_record_based $method] == 1 } {
@@ -147,8 +181,7 @@ proc test003 { method args} {
# Now, reopen the file and run the last test again in reverse direction.
puts "\tTest003.d: close, open, and dump file in reverse direction"
-
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_bin_file_direction "-last" "-prev"
if { [is_record_based $method] == 1 } {
diff --git a/bdb/test/test004.tcl b/bdb/test/test004.tcl
index 0b076d6cfb7..7bea6f88eca 100644
--- a/bdb/test/test004.tcl
+++ b/bdb/test/test004.tcl
@@ -1,14 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test004.tcl,v 11.15 2000/08/25 14:21:54 sue Exp $
+# $Id: test004.tcl,v 11.21 2002/05/22 18:32:35 sue Exp $
#
-# DB Test 4 {access method}
-# Check that cursor operations work. Create a database.
-# Read through the database sequentially using cursors and
-# delete each element.
+# TEST test004
+# TEST Small keys/medium data
+# TEST Put/get per key
+# TEST Sequential (cursor) get/delete
+# TEST
+# TEST Check that cursor operations work. Create a database.
+# TEST Read through the database sequentially using cursors and
+# TEST delete each element.
proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
source ./include.tcl
@@ -18,33 +22,47 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
set tnum test00$reopen
- puts -nonewline "$tnum:\
- $method ($args) $nentries delete small key; medium data pairs"
- if {$reopen == 5} {
- puts "(with close)"
- } else {
- puts ""
- }
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
if { $eindex == -1 } {
- set testfile $testdir/test004.db
+ set testfile $testdir/$tnum.db
set env NULL
} else {
- set testfile test004.db
+ set testfile $tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
+ }
+
+ puts -nonewline "$tnum:\
+ $method ($args) $nentries delete small key; medium data pairs"
+ if {$reopen == 5} {
+ puts "(with close)"
+ } else {
+ puts ""
}
+
# Create the database and open the dictionary
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644} $args {$omethod $testfile}]
+ set db [eval {berkdb_open -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -71,8 +89,17 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
set datastr [ make_data_str $str ]
- set ret [eval {$db put} $txn $pflags {$key [chop_data $method $datastr]}]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn $pflags \
+ {$key [chop_data $method $datastr]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set ret [eval {$db get} $gflags {$key}]
error_check_good "$tnum:put" $ret \
@@ -93,6 +120,11 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
# Now we will get each key from the DB and compare the results
# to the original, then delete it.
set outf [open $t1 w]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set c [eval {$db cursor} $txn]
set count 0
@@ -117,6 +149,9 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
}
close $outf
error_check_good curs_close [$c close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now compare the keys to see if they match the dictionary
if { [is_record_based $method] == 1 } {
diff --git a/bdb/test/test005.tcl b/bdb/test/test005.tcl
index 4cb5d88dfe2..f3e37f2149d 100644
--- a/bdb/test/test005.tcl
+++ b/bdb/test/test005.tcl
@@ -1,14 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test005.tcl,v 11.4 2000/05/22 12:51:38 bostic Exp $
+# $Id: test005.tcl,v 11.7 2002/01/11 15:53:40 bostic Exp $
#
-# DB Test 5 {access method}
-# Check that cursor operations work. Create a database; close database and
-# reopen it. Then read through the database sequentially using cursors and
-# delete each element.
+# TEST test005
+# TEST Small keys/medium data
+# TEST Put/get per key
+# TEST Close, reopen
+# TEST Sequential (cursor) get/delete
+# TEST
+# TEST Check that cursor operations work. Create a database; close
+# TEST it and reopen it. Then read through the database sequentially
+# TEST using cursors and delete each element.
proc test005 { method {nentries 10000} args } {
eval {test004 $method $nentries 5 0} $args
}
diff --git a/bdb/test/test006.tcl b/bdb/test/test006.tcl
index 9364d2a4f60..fbaebfe8ac8 100644
--- a/bdb/test/test006.tcl
+++ b/bdb/test/test006.tcl
@@ -1,14 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test006.tcl,v 11.13 2000/08/25 14:21:54 sue Exp $
+# $Id: test006.tcl,v 11.19 2002/05/22 15:42:44 sue Exp $
#
-# DB Test 6 {access method}
-# Keyed delete test.
-# Create database.
-# Go through database, deleting all entries by key.
+# TEST test006
+# TEST Small keys/medium data
+# TEST Put/get per key
+# TEST Keyed delete and verify
+# TEST
+# TEST Keyed delete test.
+# TEST Create database.
+# TEST Go through database, deleting all entries by key.
proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
source ./include.tcl
@@ -23,15 +27,8 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
set tname Test0$tnum
set dbname test0$tnum
}
- puts -nonewline "$tname: $method ($args) "
- puts -nonewline "$nentries equal small key; medium data pairs"
- if {$reopen == 1} {
- puts " (with close)"
- } else {
- puts ""
- }
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -43,6 +40,25 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
set testfile $dbname.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
+ }
+ puts -nonewline "$tname: $method ($args) "
+ puts -nonewline "$nentries equal small key; medium data pairs"
+ if {$reopen == 1} {
+ puts " (with close)"
+ } else {
+ puts ""
}
set pflags ""
@@ -50,14 +66,14 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
set txn ""
set count 0
if { [is_record_based $method] == 1 } {
- append gflags " -recno"
+ append gflags " -recno"
}
# Here is the loop where we put and get each key/data pair
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -70,9 +86,17 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
set datastr [make_data_str $str]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $datastr]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set ret [eval {$db get} $gflags {$key}]
error_check_good "$tname: put $datastr got $ret" \
@@ -108,8 +132,16 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
error_check_good "$tname: get $datastr got $ret" \
$ret [list [list $key [pad_data $method $datastr]]]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db del} $txn {$key}]
error_check_good db_del:$key $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
diff --git a/bdb/test/test007.tcl b/bdb/test/test007.tcl
index 305740f0369..1e99d107a2d 100644
--- a/bdb/test/test007.tcl
+++ b/bdb/test/test007.tcl
@@ -1,13 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test007.tcl,v 11.5 2000/05/22 12:51:38 bostic Exp $
+# $Id: test007.tcl,v 11.8 2002/01/11 15:53:40 bostic Exp $
#
-# DB Test 7 {access method}
-# Check that delete operations work. Create a database; close database and
-# reopen it. Then issues delete by key for each entry.
+# TEST test007
+# TEST Small keys/medium data
+# TEST Put/get per key
+# TEST Close, reopen
+# TEST Keyed delete
+# TEST
+# TEST Check that delete operations work. Create a database; close
+# TEST database and reopen it. Then issues delete by key for each
+# TEST entry.
proc test007 { method {nentries 10000} {tnum 7} args} {
eval {test006 $method $nentries 1 $tnum} $args
}
diff --git a/bdb/test/test008.tcl b/bdb/test/test008.tcl
index 34144391ccc..0af97a40110 100644
--- a/bdb/test/test008.tcl
+++ b/bdb/test/test008.tcl
@@ -1,15 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test008.tcl,v 11.17 2000/10/19 17:35:39 sue Exp $
+# $Id: test008.tcl,v 11.23 2002/05/22 15:42:45 sue Exp $
#
-# DB Test 8 {access method}
-# Take the source files and dbtest executable and enter their names as the
-# key with their contents as data. After all are entered, begin looping
-# through the entries; deleting some pairs and then readding them.
-proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
+# TEST test008
+# TEST Small keys/large data
+# TEST Put/get per key
+# TEST Loop through keys by steps (which change)
+# TEST ... delete each key at step
+# TEST ... add each key back
+# TEST ... change step
+# TEST Confirm that overflow pages are getting reused
+# TEST
+# TEST Take the source files and dbtest executable and enter their names as
+# TEST the key with their contents as data. After all are entered, begin
+# TEST looping through the entries; deleting some pairs and then readding them.
+proc test008 { method {reopen 8} {debug 0} args} {
source ./include.tcl
set tnum test00$reopen
@@ -29,6 +37,7 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -40,6 +49,11 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
set testfile $tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -48,7 +62,7 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644} \
+ set db [eval {berkdb_open -create -mode 0644} \
$args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -57,7 +71,7 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
set txn ""
# Here is the loop where we put and get each key/data pair
- set file_list [glob ../*/*.c ./*.o ./*.lo ./*.exe]
+ set file_list [get_file_list]
set count 0
puts "\tTest00$reopen.a: Initial put/get loop"
@@ -65,9 +79,25 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
set names($count) $f
set key $f
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
put_file $db $txn $pflags $f
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
get_file $db $txn $gflags $f $t4
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good Test00$reopen:diff($f,$t4) \
[filecmp $f $t4] 0
@@ -88,11 +118,27 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
puts "\tTest00$reopen.b: Delete re-add loop"
foreach i "1 2 4 8 16" {
for {set ndx 0} {$ndx < $count} { incr ndx $i} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db del} $txn {$names($ndx)}]
error_check_good db_del:$names($ndx) $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
for {set ndx 0} {$ndx < $count} { incr ndx $i} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
put_file $db $txn $pflags $names($ndx)
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
}
@@ -104,7 +150,15 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
# Now, reopen the file and make sure the key/data pairs look right.
puts "\tTest00$reopen.c: Dump contents forward"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_bin_file $db $txn $t1 test008.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set oid [open $t2.tmp w]
foreach f $file_list {
@@ -120,7 +174,15 @@ proc test008 { method {nentries 10000} {reopen 8} {debug 0} args} {
# Now, reopen the file and run the last test again in reverse direction.
puts "\tTest00$reopen.d: Dump contents backward"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_bin_file_direction $db $txn $t1 test008.check "-last" "-prev"
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
filesort $t1 $t3
diff --git a/bdb/test/test009.tcl b/bdb/test/test009.tcl
index e9c01875f77..7ef46d8c818 100644
--- a/bdb/test/test009.tcl
+++ b/bdb/test/test009.tcl
@@ -1,15 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test009.tcl,v 11.4 2000/05/22 12:51:38 bostic Exp $
+# $Id: test009.tcl,v 11.8 2002/05/22 15:42:45 sue Exp $
#
-# DB Test 9 {access method}
-# Check that we reuse overflow pages. Create database with lots of
-# big key/data pairs. Go through and delete and add keys back
-# randomly. Then close the DB and make sure that we have everything
-# we think we should.
-proc test009 { method {nentries 10000} args} {
- eval {test008 $method $nentries 9 0} $args
+# TEST test009
+# TEST Small keys/large data
+# TEST Same as test008; close and reopen database
+# TEST
+# TEST Check that we reuse overflow pages. Create database with lots of
+# TEST big key/data pairs. Go through and delete and add keys back
+# TEST randomly. Then close the DB and make sure that we have everything
+# TEST we think we should.
+proc test009 { method args} {
+ eval {test008 $method 9 0} $args
}
diff --git a/bdb/test/test010.tcl b/bdb/test/test010.tcl
index b3aedb2bee9..0b5f5531795 100644
--- a/bdb/test/test010.tcl
+++ b/bdb/test/test010.tcl
@@ -1,17 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test010.tcl,v 11.14 2000/08/25 14:21:54 sue Exp $
+# $Id: test010.tcl,v 11.20 2002/06/11 14:09:56 sue Exp $
#
-# DB Test 10 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; add duplicate
-# records for each.
-# After all are entered, retrieve all; verify output.
-# Close file, reopen, do retrieve and re-verify.
-# This does not work for recno
+# TEST test010
+# TEST Duplicate test
+# TEST Small key/data pairs.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; add duplicate records for each.
+# TEST After all are entered, retrieve all; verify output.
+# TEST Close file, reopen, do retrieve and re-verify.
+# TEST This does not work for recno
proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
source ./include.tcl
@@ -25,9 +27,8 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
return
}
- puts "Test0$tnum: $method ($args) $nentries small dup key/data pairs"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -39,7 +40,23 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
+ puts "Test0$tnum: $method ($args) $nentries \
+ small $ndups dup key/data pairs"
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
@@ -47,7 +64,7 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644 -dup} $args {$omethod $testfile}]
+ -create -mode 0644 -dup} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -58,17 +75,30 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
set count 0
# Here is the loop where we put and get each key/data pair
- set dbc [eval {$db cursor} $txn]
while { [gets $did str] != -1 && $count < $nentries } {
for { set i 1 } { $i <= $ndups } { incr i } {
set datastr $i:$str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$str [chop_data $method $datastr]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Now retrieve all the keys matching this key
set x 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
for {set ret [$dbc get "-set" $str]} \
{[llength $ret] != 0} \
{set ret [$dbc get "-next"] } {
@@ -87,9 +117,13 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
incr x
}
error_check_good "Test0$tnum:ndups:$str" [expr $x - 1] $ndups
+ error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
incr count
}
- error_check_good cursor_close [$dbc close] 0
close $did
# Now we will get each key from the DB and compare the results
@@ -99,7 +133,15 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
for { set i 1 } { $i <= $ndups } {incr i} {
lappend dlist $i
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now compare the keys to see if they match the dictionary entries
set q q
@@ -115,7 +157,15 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
error_check_good dbopen [is_valid_db $db] TRUE
puts "\tTest0$tnum.b: Checking file for correct duplicates after close"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now compare the keys to see if they match the dictionary entries
filesort $t1 $t3
diff --git a/bdb/test/test011.tcl b/bdb/test/test011.tcl
index 444f6240e92..63e2203efe4 100644
--- a/bdb/test/test011.tcl
+++ b/bdb/test/test011.tcl
@@ -1,18 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test011.tcl,v 11.20 2000/08/25 14:21:54 sue Exp $
+# $Id: test011.tcl,v 11.27 2002/06/11 14:09:56 sue Exp $
#
-# DB Test 11 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; add duplicate
-# records for each.
-# Then do some key_first/key_last add_before, add_after operations.
-# This does not work for recno
-# To test if dups work when they fall off the main page, run this with
-# a very tiny page size.
+# TEST test011
+# TEST Duplicate test
+# TEST Small key/data pairs.
+# TEST Test DB_KEYFIRST, DB_KEYLAST, DB_BEFORE and DB_AFTER.
+# TEST To test off-page duplicates, run with small pagesize.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; add duplicate records for each.
+# TEST Then do some key_first/key_last add_before, add_after operations.
+# TEST This does not work for recno
+# TEST
+# TEST To test if dups work when they fall off the main page, run this with
+# TEST a very tiny page size.
proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
global dlist
global rand_init
@@ -27,9 +32,6 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
if { [is_record_based $method] == 1 } {
test011_recno $method $nentries $tnum $args
return
- } else {
- puts -nonewline "Test0$tnum: $method $nentries small dup "
- puts "key/data pairs, cursor ops"
}
if {$ndups < 5} {
set ndups 5
@@ -41,6 +43,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
berkdb srand $rand_init
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -52,13 +55,30 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
+
+ puts -nonewline "Test0$tnum: $method $nentries small $ndups dup "
+ puts "key/data pairs, cursor ops"
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644} [concat $args "-dup"] {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -74,7 +94,6 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
# 0 and $ndups+1 using keyfirst/keylast. We'll add 2 and 4 using
# add before and add after.
puts "\tTest0$tnum.a: put and get duplicate keys."
- set dbc [eval {$db cursor} $txn]
set i ""
for { set i 1 } { $i <= $ndups } { incr i 2 } {
lappend dlist $i
@@ -83,12 +102,26 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
while { [gets $did str] != -1 && $count < $nentries } {
for { set i 1 } { $i <= $ndups } { incr i 2 } {
set datastr $i:$str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn $pflags {$str $datastr}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Now retrieve all the keys matching this key
set x 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
for {set ret [$dbc get "-set" $str ]} \
{[llength $ret] != 0} \
{set ret [$dbc get "-next"] } {
@@ -108,16 +141,27 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
incr x 2
}
error_check_good Test0$tnum:numdups $x $maxodd
+ error_check_good curs_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
- error_check_good curs_close [$dbc close] 0
close $did
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest0$tnum.b: \
traverse entire file checking duplicates before close."
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now compare the keys to see if they match the dictionary entries
set q q
@@ -135,7 +179,15 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
puts "\tTest0$tnum.c: \
traverse entire file checking duplicates after close."
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now compare the keys to see if they match the dictionary entries
filesort $t1 $t3
@@ -143,24 +195,56 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
[filecmp $t3 $t2] 0
puts "\tTest0$tnum.d: Testing key_first functionality"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
add_dup $db $txn $nentries "-keyfirst" 0 0
set dlist [linsert $dlist 0 0]
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
puts "\tTest0$tnum.e: Testing key_last functionality"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
add_dup $db $txn $nentries "-keylast" [expr $maxodd - 1] 0
lappend dlist [expr $maxodd - 1]
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
puts "\tTest0$tnum.f: Testing add_before functionality"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
add_dup $db $txn $nentries "-before" 2 3
set dlist [linsert $dlist 2 2]
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
puts "\tTest0$tnum.g: Testing add_after functionality"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
add_dup $db $txn $nentries "-after" 4 4
set dlist [linsert $dlist 4 4]
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
@@ -209,6 +293,7 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
+ set txnenv 0
if { $eindex == -1 } {
set testfile $testdir/test0$tnum.db
set env NULL
@@ -216,6 +301,18 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
set testfile test0$tnum.db
incr eindex
set env [lindex $largs $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append largs " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -226,7 +323,7 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
append largs " -renumber"
}
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $largs {$omethod $testfile}]
+ -create -mode 0644} $largs {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -247,13 +344,26 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
# Seed the database with an initial record
gets $did str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn {1 [chop_data $method $str]}]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good put $ret 0
set count 1
set dlist "NULL $str"
# Open a cursor
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
puts "\tTest0$tnum.a: put and get entries"
while { [gets $did str] != -1 && $count < $nentries } {
@@ -312,6 +422,9 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
}
close $did
error_check_good cclose [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Create check key file.
set oid [open $t2 w]
@@ -321,20 +434,28 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
close $oid
puts "\tTest0$tnum.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 test011_check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good Test0$tnum:diff($t2,$t1) \
[filecmp $t2 $t1] 0
error_check_good db_close [$db close] 0
puts "\tTest0$tnum.c: close, open, and dump file"
- open_and_dump_file $testfile $env $txn $t1 test011_check \
+ open_and_dump_file $testfile $env $t1 test011_check \
dump_file_direction "-first" "-next"
error_check_good Test0$tnum:diff($t2,$t1) \
[filecmp $t2 $t1] 0
puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 test011_check \
+ open_and_dump_file $testfile $env $t1 test011_check \
dump_file_direction "-last" "-prev"
filesort $t1 $t3 -n
diff --git a/bdb/test/test012.tcl b/bdb/test/test012.tcl
index 87127901e19..e7237d27267 100644
--- a/bdb/test/test012.tcl
+++ b/bdb/test/test012.tcl
@@ -1,14 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test012.tcl,v 11.14 2000/08/25 14:21:54 sue Exp $
+# $Id: test012.tcl,v 11.20 2002/05/22 15:42:46 sue Exp $
#
-# DB Test 12 {access method}
-# Take the source files and dbtest executable and enter their contents as
-# the key with their names as data. After all are entered, retrieve all;
-# compare output to original. Close file, reopen, do retrieve and re-verify.
+# TEST test012
+# TEST Large keys/small data
+# TEST Same as test003 except use big keys (source files and
+# TEST executables) and small data (the file/executable names).
+# TEST
+# TEST Take the source files and dbtest executable and enter their contents
+# TEST as the key with their names as data. After all are entered, retrieve
+# TEST all; compare output to original. Close file, reopen, do retrieve and
+# TEST re-verify.
proc test012 { method args} {
global names
source ./include.tcl
@@ -24,6 +29,7 @@ proc test012 { method args} {
puts "Test012: $method ($args) filename=data filecontents=key pairs"
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -35,6 +41,11 @@ proc test012 { method args} {
set testfile test012.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -44,7 +55,7 @@ proc test012 { method args} {
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set pflags ""
@@ -52,22 +63,37 @@ proc test012 { method args} {
set txn ""
# Here is the loop where we put and get each key/data pair
- set file_list [glob $test_path/../\[a-z\]*/*.c \
- $test_path/./*.lo ./*.exe]
+ set file_list [get_file_list]
puts "\tTest012.a: put/get loop"
set count 0
foreach f $file_list {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
put_file_as_key $db $txn $pflags $f
set kd [get_file_as_key $db $txn $gflags $f]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest012.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_binkey_file $db $txn $t1 test012.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the data to see if they match the .o and dbtest files
@@ -85,7 +111,7 @@ proc test012 { method args} {
# Now, reopen the file and run the last test again.
puts "\tTest012.c: close, open, and dump file"
- open_and_dump_file $testfile $env $txn $t1 test012.check \
+ open_and_dump_file $testfile $env $t1 test012.check \
dump_binkey_file_direction "-first" "-next"
filesort $t1 $t3
@@ -95,7 +121,7 @@ proc test012 { method args} {
# Now, reopen the file and run the last test again in reverse direction.
puts "\tTest012.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 test012.check\
+ open_and_dump_file $testfile $env $t1 test012.check\
dump_binkey_file_direction "-last" "-prev"
filesort $t1 $t3
diff --git a/bdb/test/test013.tcl b/bdb/test/test013.tcl
index 5812cf8f64d..96d7757b0d8 100644
--- a/bdb/test/test013.tcl
+++ b/bdb/test/test013.tcl
@@ -1,17 +1,20 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test013.tcl,v 11.18 2000/08/25 14:21:54 sue Exp $
+# $Id: test013.tcl,v 11.23 2002/05/22 15:42:46 sue Exp $
#
-# DB Test 13 {access method}
-#
-# 1. Insert 10000 keys and retrieve them (equal key/data pairs).
-# 2. Attempt to overwrite keys with NO_OVERWRITE set (expect error).
-# 3. Actually overwrite each one with its datum reversed.
-#
-# No partial testing here.
+# TEST test013
+# TEST Partial put test
+# TEST Overwrite entire records using partial puts.
+# TEST Make surethat NOOVERWRITE flag works.
+# TEST
+# TEST 1. Insert 10000 keys and retrieve them (equal key/data pairs).
+# TEST 2. Attempt to overwrite keys with NO_OVERWRITE set (expect error).
+# TEST 3. Actually overwrite each one with its datum reversed.
+# TEST
+# TEST No partial testing here.
proc test013 { method {nentries 10000} args } {
global errorCode
global errorInfo
@@ -23,9 +26,8 @@ proc test013 { method {nentries 10000} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Test013: $method ($args) $nentries equal key/data pairs, put test"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -37,14 +39,28 @@ proc test013 { method {nentries 10000} args } {
set testfile test013.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+ puts "Test013: $method ($args) $nentries equal key/data pairs, put test"
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -70,6 +86,11 @@ proc test013 { method {nentries 10000} args } {
} else {
set key $str
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $str]}]
error_check_good put $ret 0
@@ -77,6 +98,9 @@ proc test013 { method {nentries 10000} args } {
set ret [eval {$db get} $gflags $txn {$key}]
error_check_good \
get $ret [list [list $key [pad_data $method $str]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
@@ -93,6 +117,11 @@ proc test013 { method {nentries 10000} args } {
set key $str
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn $pflags \
{-nooverwrite $key [chop_data $method $str]}]
error_check_good put [is_substr $ret "DB_KEYEXIST"] 1
@@ -101,6 +130,9 @@ proc test013 { method {nentries 10000} args } {
set ret [eval {$db get} $txn $gflags {$key}]
error_check_good \
get $ret [list [list $key [pad_data $method $str]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
@@ -116,6 +148,11 @@ proc test013 { method {nentries 10000} args } {
set key $str
}
set rstr [string toupper $str]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} \
$txn $pflags {$key [chop_data $method $rstr]}]
error_check_good put $r 0
@@ -124,13 +161,24 @@ proc test013 { method {nentries 10000} args } {
set ret [eval {$db get} $txn $gflags {$key}]
error_check_good \
get $ret [list [list $key [pad_data $method $rstr]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
# Now make sure that everything looks OK
puts "\tTest013.d: check entire file contents"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary (or ints)
@@ -153,7 +201,7 @@ proc test013 { method {nentries 10000} args } {
puts "\tTest013.e: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_file_direction "-first" "-next"
if { [is_record_based $method] == 0 } {
@@ -166,7 +214,7 @@ proc test013 { method {nentries 10000} args } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tTest013.f: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_file_direction "-last" "-prev"
if { [is_record_based $method] == 0 } {
diff --git a/bdb/test/test014.tcl b/bdb/test/test014.tcl
index 3ad5335dd0a..00d69d3352e 100644
--- a/bdb/test/test014.tcl
+++ b/bdb/test/test014.tcl
@@ -1,17 +1,20 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test014.tcl,v 11.19 2000/08/25 14:21:54 sue Exp $
+# $Id: test014.tcl,v 11.24 2002/05/22 15:42:46 sue Exp $
#
-# DB Test 14 {access method}
-#
-# Partial put test, small data, replacing with same size. The data set
-# consists of the first nentries of the dictionary. We will insert them
-# (and retrieve them) as we do in test 1 (equal key/data pairs). Then
-# we'll try to perform partial puts of some characters at the beginning,
-# some at the end, and some at the middle.
+# TEST test014
+# TEST Exercise partial puts on short data
+# TEST Run 5 combinations of numbers of characters to replace,
+# TEST and number of times to increase the size by.
+# TEST
+# TEST Partial put test, small data, replacing with same size. The data set
+# TEST consists of the first nentries of the dictionary. We will insert them
+# TEST (and retrieve them) as we do in test 1 (equal key/data pairs). Then
+# TEST we'll try to perform partial puts of some characters at the beginning,
+# TEST some at the end, and some at the middle.
proc test014 { method {nentries 10000} args } {
set fixed 0
set args [convert_args $method $args]
@@ -71,6 +74,7 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -82,6 +86,18 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
set testfile test014.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -89,7 +105,7 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set gflags ""
@@ -117,7 +133,15 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
global dvals
# initial put
- set ret [$db put $key $str]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key $str}]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good dbput $ret 0
set offset [string length $str]
@@ -133,11 +157,28 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
a[set offset]x[set chars]a[set increase] \
$str $data]
set offset [expr $offset + $chars]
- set ret [$db put -partial [list $offset 0] $key $data]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put -partial [list $offset 0]} \
+ $txn {$key $data}]
error_check_good dbput:post $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
} else {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
partial_put $method $db $txn \
$gflags $key $str $chars $increase
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
incr count
}
@@ -145,7 +186,15 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
# Now make sure that everything looks OK
puts "\tTest014.b: check entire file contents"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 test014.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary (or ints)
@@ -168,7 +217,7 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
puts "\tTest014.c: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_file $testfile $env $txn \
+ open_and_dump_file $testfile $env \
$t1 test014.check dump_file_direction "-first" "-next"
if { [string compare $omethod "-recno"] != 0 } {
@@ -182,7 +231,7 @@ proc test014_body { method flagp chars increase {nentries 10000} args } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tTest014.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 \
+ open_and_dump_file $testfile $env $t1 \
test014.check dump_file_direction "-last" "-prev"
if { [string compare $omethod "-recno"] != 0 } {
diff --git a/bdb/test/test015.tcl b/bdb/test/test015.tcl
index 61abddd3799..f129605a405 100644
--- a/bdb/test/test015.tcl
+++ b/bdb/test/test015.tcl
@@ -1,14 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test015.tcl,v 11.20 2000/08/25 14:21:54 sue Exp $
+# $Id: test015.tcl,v 11.27 2002/05/31 16:57:25 sue Exp $
#
-# DB Test 15 {access method}
-# Partial put test when item does not exist.
+# TEST test015
+# TEST Partial put test
+# TEST Partial put test where the key does not initially exist.
proc test015 { method {nentries 7500} { start 0 } args } {
- global fixed_len
+ global fixed_len testdir
set low_range 50
set mid_range 100
@@ -43,6 +44,15 @@ proc test015 { method {nentries 7500} { start 0 } args } {
puts -nonewline "$this: "
eval [concat test015_body $method [lindex $entry 1] \
$nentries $args]
+ set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $args $eindex]
+ set testdir [get_home $env]
+ }
+puts "Verifying testdir $testdir"
+
+ error_check_good verify [verify_dir $testdir "\tTest015.e: "] 0
}
}
@@ -55,6 +65,7 @@ proc test015_init { } {
proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
global dvals
global fixed_len
+ global testdir
source ./include.tcl
set args [convert_args $method $args]
@@ -71,6 +82,7 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
puts "Put $rcount strings random offsets between $off_low and $off_hi"
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -82,14 +94,27 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
set testfile test015.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries > 5000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+ set retdir $testdir
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set pflags ""
@@ -97,7 +122,7 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
set txn ""
set count 0
- puts "\tTest015.a: put/get loop"
+ puts "\tTest015.a: put/get loop for $nentries entries"
# Here is the loop where we put and get each key/data pair
# Each put is a partial put of a record that does not exist.
@@ -148,9 +173,17 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
set slen [expr $fixed_len - $off]
set data [eval "binary format a$slen" {$data}]
}
- set ret [eval {$db put} \
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn \
{-partial [list $off [string length $data]] $key $data}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
@@ -158,7 +191,15 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
# Now make sure that everything looks OK
puts "\tTest015.b: check entire file contents"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary (or ints)
@@ -183,7 +224,7 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
puts "\tTest015.c: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_file $testfile $env $txn $t1 \
+ open_and_dump_file $testfile $env $t1 \
$checkfunc dump_file_direction "-first" "-next"
if { [string compare $omethod "-recno"] != 0 } {
@@ -196,7 +237,7 @@ proc test015_body { method off_low off_hi rcount {nentries 10000} args } {
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tTest015.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 \
+ open_and_dump_file $testfile $env $t1 \
$checkfunc dump_file_direction "-last" "-prev"
if { [string compare $omethod "-recno"] != 0 } {
diff --git a/bdb/test/test016.tcl b/bdb/test/test016.tcl
index def3c114693..af289f866f4 100644
--- a/bdb/test/test016.tcl
+++ b/bdb/test/test016.tcl
@@ -1,19 +1,20 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test016.tcl,v 11.17 2000/08/25 14:21:54 sue Exp $
+# $Id: test016.tcl,v 11.23 2002/05/22 15:42:46 sue Exp $
#
-# DB Test 16 {access method}
-# Partial put test where partial puts make the record smaller.
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and a fixed, medium length data string;
-# retrieve each. After all are entered, go back and do partial puts,
-# replacing a random-length string with the key value.
-# Then verify.
-
-set datastr abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+# TEST test016
+# TEST Partial put test
+# TEST Partial put where the datum gets shorter as a result of the put.
+# TEST
+# TEST Partial put test where partial puts make the record smaller.
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and a fixed, medium length data string;
+# TEST retrieve each. After all are entered, go back and do partial puts,
+# TEST replacing a random-length string with the key value.
+# TEST Then verify.
proc test016 { method {nentries 10000} args } {
global datastr
@@ -31,9 +32,8 @@ proc test016 { method {nentries 10000} args } {
return
}
- puts "Test016: $method ($args) $nentries partial put shorten"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -45,13 +45,27 @@ proc test016 { method {nentries 10000} args } {
set testfile test016.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+ puts "Test016: $method ($args) $nentries partial put shorten"
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set pflags ""
@@ -64,7 +78,6 @@ proc test016 { method {nentries 10000} args } {
}
# Here is the loop where we put and get each key/data pair
-
puts "\tTest016.a: put/get loop"
set did [open $dict]
while { [gets $did str] != -1 && $count < $nentries } {
@@ -73,6 +86,11 @@ proc test016 { method {nentries 10000} args } {
} else {
set key $str
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $datastr]}]
error_check_good put $ret 0
@@ -80,6 +98,9 @@ proc test016 { method {nentries 10000} args } {
set ret [eval {$db get} $txn $gflags {$key}]
error_check_good \
get $ret [list [list $key [pad_data $method $datastr]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
@@ -103,12 +124,20 @@ proc test016 { method {nentries 10000} args } {
set s2 [string toupper $key]
set s3 [string range $datastr [expr $repl_off + $repl_len] end ]
set dvals($key) [pad_data $method $s1$s2$s3]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn {-partial \
[list $repl_off $repl_len] $key [chop_data $method $s2]}]
error_check_good put $ret 0
set ret [eval {$db get} $txn $gflags {$key}]
error_check_good \
put $ret [list [list $key [pad_data $method $s1$s2$s3]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
@@ -116,7 +145,15 @@ proc test016 { method {nentries 10000} args } {
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest016.c: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 test016.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary
@@ -139,7 +176,7 @@ proc test016 { method {nentries 10000} args } {
# Now, reopen the file and run the last test again.
puts "\tTest016.d: close, open, and dump file"
- open_and_dump_file $testfile $env $txn $t1 test016.check \
+ open_and_dump_file $testfile $env $t1 test016.check \
dump_file_direction "-first" "-next"
if { [ is_record_based $method ] == 0 } {
@@ -150,7 +187,7 @@ proc test016 { method {nentries 10000} args } {
# Now, reopen the file and run the last test again in reverse direction.
puts "\tTest016.e: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 test016.check \
+ open_and_dump_file $testfile $env $t1 test016.check \
dump_file_direction "-last" "-prev"
if { [ is_record_based $method ] == 0 } {
diff --git a/bdb/test/test017.tcl b/bdb/test/test017.tcl
index 95fe82e081c..1f99aa328fb 100644
--- a/bdb/test/test017.tcl
+++ b/bdb/test/test017.tcl
@@ -1,22 +1,22 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test017.tcl,v 11.13 2000/12/11 17:42:18 sue Exp $
-#
-# DB Test 17 {access method}
-# Run duplicates with small page size so that we test off page duplicates.
-# Then after we have an off-page database, test with overflow pages too.
+# $Id: test017.tcl,v 11.23 2002/06/20 19:01:02 sue Exp $
#
+# TEST test017
+# TEST Basic offpage duplicate test.
+# TEST
+# TEST Run duplicates with small page size so that we test off page duplicates.
+# TEST Then after we have an off-page database, test with overflow pages too.
proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
source ./include.tcl
set args [convert_args $method $args]
set omethod [convert_method $method]
- if { [is_record_based $method] == 1 || \
- [is_rbtree $method] == 1 } {
+ if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
puts "Test0$tnum skipping for method $method"
return
}
@@ -29,9 +29,8 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
}
}
- puts "Test0$tnum: $method ($args) Off page duplicate tests with $ndups duplicates"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -43,6 +42,11 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -52,7 +56,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644 -dup} $args {$omethod $testfile}]
+ -create -mode 0644 -dup} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set pflags ""
@@ -60,17 +64,22 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
set txn ""
set count 0
+ set file_list [get_file_list 1]
+ if { $txnenv == 1 } {
+ set flen [llength $file_list]
+ reduce_dups flen ndups
+ set file_list [lrange $file_list 0 $flen]
+ }
+ puts "Test0$tnum: $method ($args) Off page duplicate tests with $ndups duplicates"
+
set ovfl ""
# Here is the loop where we put and get each key/data pair
- set dbc [eval {$db cursor} $txn]
- puts -nonewline \
- "\tTest0$tnum.a: Creating duplicates with "
+ puts -nonewline "\tTest0$tnum.a: Creating duplicates with "
if { $contents != 0 } {
puts "file contents as key/data"
} else {
puts "file name as key/data"
}
- set file_list [glob ../*/*.c ./*.lo]
foreach f $file_list {
if { $contents != 0 } {
set fid [open $f r]
@@ -85,9 +94,17 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
}
for { set i 1 } { $i <= $ndups } { incr i } {
set datastr $i:$str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$str [chop_data $method $datastr]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
#
@@ -101,6 +118,12 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
error_check_bad $f:dbget_dups [llength $ret] 0
error_check_good $f:dbget_dups1 [llength $ret] $ndups
set x 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
for {set ret [$dbc get "-set" $str]} \
{[llength $ret] != 0} \
{set ret [$dbc get "-next"] } {
@@ -119,9 +142,12 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
incr x
}
error_check_good "Test0$tnum:ndups:$str" [expr $x - 1] $ndups
+ error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
- error_check_good cursor_close [$dbc close] 0
# Now we will get each key from the DB and compare the results
# to the original.
@@ -145,19 +171,33 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
fileremove $t2.tmp
fileremove $t4.tmp
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
if {$contents == 0} {
filesort $t1 $t3
- error_check_good Test0$tnum:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
+ error_check_good Test0$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
# Now compare the keys to see if they match the file names
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 test017.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
filesort $t1 $t3
- error_check_good Test0$tnum:diff($t3,$t4) \
- [filecmp $t3 $t4] 0
+ error_check_good Test0$tnum:diff($t3,$t4) [filecmp $t3 $t4] 0
}
error_check_good db_close [$db close] 0
@@ -165,13 +205,20 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
error_check_good dbopen [is_valid_db $db] TRUE
puts "\tTest0$tnum.c: Checking file for correct duplicates after close"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
if {$contents == 0} {
# Now compare the keys to see if they match the filenames
filesort $t1 $t3
- error_check_good Test0$tnum:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
+ error_check_good Test0$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
}
error_check_good db_close [$db close] 0
@@ -204,6 +251,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
error_check_good db_close [$db close] 0
return
}
+
puts "\tTest0$tnum.e: Add overflow duplicate entries"
set ovfldup [expr $ndups + 1]
foreach f $ovfl {
@@ -214,20 +262,41 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
fconfigure $fid -translation binary
set fdata [read $fid]
close $fid
- set data $ovfldup:$fdata
+ set data $ovfldup:$fdata:$fdata:$fdata:$fdata
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn $pflags {$f $data}]
error_check_good ovfl_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+
puts "\tTest0$tnum.f: Verify overflow duplicate entries"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dup_check $db $txn $t1 $dlist $ovfldup
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
filesort $t1 $t3
- error_check_good Test0$tnum:diff($t3,$t2) \
- [filecmp $t3 $t2] 0
+ error_check_good Test0$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
set stat [$db stat]
- error_check_bad overflow1 \
- [is_substr $stat "{{Overflow pages} 0}"] 1
+ if { [is_hash [$db get_type]] } {
+ error_check_bad overflow1_hash [is_substr $stat \
+ "{{Number of big pages} 0}"] 1
+ } else {
+ error_check_bad \
+ overflow1 [is_substr $stat "{{Overflow pages} 0}"] 1
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test018.tcl b/bdb/test/test018.tcl
index 95493da2d03..8fc8a14e95e 100644
--- a/bdb/test/test018.tcl
+++ b/bdb/test/test018.tcl
@@ -1,12 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test018.tcl,v 11.3 2000/02/14 03:00:18 bostic Exp $
+# $Id: test018.tcl,v 11.6 2002/01/11 15:53:43 bostic Exp $
#
-# DB Test 18 {access method}
-# Run duplicates with small page size so that we test off page duplicates.
+# TEST test018
+# TEST Offpage duplicate test
+# TEST Key_{first,last,before,after} offpage duplicates.
+# TEST Run duplicates with small page size so that we test off page
+# TEST duplicates.
proc test018 { method {nentries 10000} args} {
puts "Test018: Off page duplicate tests"
eval {test011 $method $nentries 19 18 -pagesize 512} $args
diff --git a/bdb/test/test019.tcl b/bdb/test/test019.tcl
index 4031ae2dc16..aa3a58a0bcd 100644
--- a/bdb/test/test019.tcl
+++ b/bdb/test/test019.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test019.tcl,v 11.14 2000/08/25 14:21:54 sue Exp $
+# $Id: test019.tcl,v 11.21 2002/05/22 15:42:47 sue Exp $
#
-# Test019 { access_method nentries }
-# Test the partial get functionality.
+# TEST test019
+# TEST Partial get test.
proc test019 { method {nentries 10000} args } {
global fixed_len
global rand_init
@@ -14,9 +14,8 @@ proc test019 { method {nentries 10000} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Test019: $method ($args) $nentries partial get test"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -28,11 +27,25 @@ proc test019 { method {nentries 10000} args } {
set testfile test019.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+ puts "Test019: $method ($args) $nentries partial get test"
+
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
berkdb srand $rand_init
@@ -57,6 +70,11 @@ proc test019 { method {nentries 10000} args } {
}
set repl [berkdb random_int $fixed_len 100]
set data [chop_data $method [replicate $str $repl]]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn {-nooverwrite $key $data}]
error_check_good dbput:$key $ret 0
@@ -64,6 +82,9 @@ proc test019 { method {nentries 10000} args } {
error_check_good \
dbget:$key $ret [list [list $key [pad_data $method $data]]]
set kvals($key) $repl
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
close $did
@@ -76,18 +97,23 @@ proc test019 { method {nentries 10000} args } {
} else {
set key $str
}
- set data [replicate $str $kvals($key)]
+ set data [pad_data $method [replicate $str $kvals($key)]]
+
+ set maxndx [expr [string length $data] - 1]
- if { [is_fixed_length $method] == 1 } {
- set maxndx $fixed_len
- } else {
- set maxndx [expr [string length $data] - 1]
- }
set beg [berkdb random_int 0 [expr $maxndx - 1]]
- set len [berkdb random_int 1 [expr $maxndx - $beg]]
+ set len [berkdb random_int 0 [expr $maxndx * 2]]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db get} \
$txn {-partial [list $beg $len]} $gflags {$key}]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# In order for tcl to handle this, we have to overwrite the
# last character with a NULL. That makes the length one less
@@ -95,12 +121,10 @@ proc test019 { method {nentries 10000} args } {
set k [lindex [lindex $ret 0] 0]
set d [lindex [lindex $ret 0] 1]
error_check_good dbget_key $k $key
- # If $d contains some of the padding, we want to get rid of it.
- set firstnull [string first "\0" $d]
- if { $firstnull == -1 } { set firstnull [string length $d] }
- error_check_good dbget_data \
- [string range $d 0 [expr $firstnull - 1]] \
+
+ error_check_good dbget_data $d \
[string range $data $beg [expr $beg + $len - 1]]
+
}
error_check_good db_close [$db close] 0
close $did
diff --git a/bdb/test/test020.tcl b/bdb/test/test020.tcl
index 1961d0e02dd..9b6d939acad 100644
--- a/bdb/test/test020.tcl
+++ b/bdb/test/test020.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test020.tcl,v 11.12 2000/10/19 23:15:22 ubell Exp $
+# $Id: test020.tcl,v 11.17 2002/05/22 15:42:47 sue Exp $
#
-# DB Test 20 {access method}
-# Test in-memory databases.
+# TEST test020
+# TEST In-Memory database tests.
proc test020 { method {nentries 10000} args } {
source ./include.tcl
@@ -17,12 +17,11 @@ proc test020 { method {nentries 10000} args } {
puts "Test020 skipping for method $method"
return
}
- puts "Test020: $method ($args) $nentries equal key/data pairs"
-
# Create the database and open the dictionary
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# Check if we are using an env.
@@ -31,10 +30,24 @@ proc test020 { method {nentries 10000} args } {
} else {
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+ puts "Test020: $method ($args) $nentries equal key/data pairs"
+
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod}]
+ -create -mode 0644} $args {$omethod}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -60,19 +73,35 @@ proc test020 { method {nentries 10000} args } {
} else {
set key $str
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $str]}]
error_check_good put $ret 0
set ret [eval {$db get} $txn $gflags {$key}]
error_check_good \
get $ret [list [list $key [pad_data $method $str]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest020.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary (or ints)
diff --git a/bdb/test/test021.tcl b/bdb/test/test021.tcl
index f9a1fe32f7e..56936da389a 100644
--- a/bdb/test/test021.tcl
+++ b/bdb/test/test021.tcl
@@ -1,25 +1,26 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test021.tcl,v 11.10 2000/08/25 14:21:55 sue Exp $
+# $Id: test021.tcl,v 11.15 2002/05/22 15:42:47 sue Exp $
#
-# DB Test 21 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self, reversed as key and self as data.
-# After all are entered, retrieve each using a cursor SET_RANGE, and getting
-# about 20 keys sequentially after it (in some cases we'll run out towards
-# the end of the file).
+# TEST test021
+# TEST Btree range tests.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self, reversed as key and self as data.
+# TEST After all are entered, retrieve each using a cursor SET_RANGE, and
+# TEST getting about 20 keys sequentially after it (in some cases we'll
+# TEST run out towards the end of the file).
proc test021 { method {nentries 10000} args } {
source ./include.tcl
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "Test021: $method ($args) $nentries equal key/data pairs"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -31,13 +32,27 @@ proc test021 { method {nentries 10000} args } {
set testfile test021.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+ puts "Test021: $method ($args) $nentries equal key/data pairs"
+
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -65,9 +80,17 @@ proc test021 { method {nentries 10000} args } {
set key [reverse $str]
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} \
$txn $pflags {$key [chop_data $method $str]}]
error_check_good db_put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
close $did
@@ -81,6 +104,11 @@ proc test021 { method {nentries 10000} args } {
error_check_good dbopen [is_valid_db $db] TRUE
# Open a cursor
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_substr $dbc $db] 1
@@ -112,6 +140,10 @@ proc test021 { method {nentries 10000} args } {
}
incr i
}
+ error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
close $did
}
diff --git a/bdb/test/test022.tcl b/bdb/test/test022.tcl
index f9a4c96637e..d25d7ecdffe 100644
--- a/bdb/test/test022.tcl
+++ b/bdb/test/test022.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test022.tcl,v 11.10 2000/08/25 14:21:55 sue Exp $
+# $Id: test022.tcl,v 11.14 2002/05/22 15:42:48 sue Exp $
#
-# Test022: Test of DB->get_byteswapped
+# TEST test022
+# TEST Test of DB->getbyteswapped().
proc test022 { method args } {
source ./include.tcl
@@ -14,6 +15,7 @@ proc test022 { method args } {
puts "Test022 ($args) $omethod: DB->getbyteswapped()"
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -27,6 +29,11 @@ proc test022 { method args } {
set testfile2 "test022b.db"
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
diff --git a/bdb/test/test023.tcl b/bdb/test/test023.tcl
index c222bdd83c5..c37539a0f55 100644
--- a/bdb/test/test023.tcl
+++ b/bdb/test/test023.tcl
@@ -1,14 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test023.tcl,v 11.13 2000/08/25 14:21:55 sue Exp $
+# $Id: test023.tcl,v 11.18 2002/05/22 15:42:48 sue Exp $
#
-# Duplicate delete test.
-# Add a key with duplicates (first time on-page, second time off-page)
-# Number the dups.
-# Delete dups and make sure that CURRENT/NEXT/PREV work correctly.
+# TEST test023
+# TEST Duplicate test
+# TEST Exercise deletes and cursor operations within a duplicate set.
+# TEST Add a key with duplicates (first time on-page, second time off-page)
+# TEST Number the dups.
+# TEST Delete dups and make sure that CURRENT/NEXT/PREV work correctly.
proc test023 { method args } {
global alphabet
global dupnum
@@ -26,6 +28,7 @@ proc test023 { method args } {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -37,19 +40,29 @@ proc test023 { method args } {
set testfile test023.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644 -dup} $args {$omethod $testfile}]
+ -create -mode 0644 -dup} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set pflags ""
set gflags ""
set txn ""
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good db_cursor [is_substr $dbc $db] 1
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
foreach i { onpage offpage } {
if { $i == "onpage" } {
@@ -159,7 +172,7 @@ proc test023 { method args } {
puts "\tTest023.f: Count keys, overwrite current, count again"
# At this point we should have 17 keys the (initial 20 minus
# 3 deletes)
- set dbc2 [$db cursor]
+ set dbc2 [eval {$db cursor} $txn]
error_check_good db_cursor:2 [is_substr $dbc2 $db] 1
set count_check 0
@@ -178,6 +191,7 @@ proc test023 { method args } {
incr count_check
}
error_check_good numdups $count_check 17
+ error_check_good dbc2_close [$dbc2 close] 0
# Done, delete all the keys for next iteration
set ret [eval {$db del} $txn {$key}]
@@ -190,6 +204,9 @@ proc test023 { method args } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test024.tcl b/bdb/test/test024.tcl
index f0b6762cd2f..bbdc8fb2253 100644
--- a/bdb/test/test024.tcl
+++ b/bdb/test/test024.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test024.tcl,v 11.14 2000/08/25 14:21:55 sue Exp $
+# $Id: test024.tcl,v 11.19 2002/05/22 15:42:48 sue Exp $
#
-# DB Test 24 {method nentries}
-# Test the Btree and Record number get-by-number functionality.
+# TEST test024
+# TEST Record number retrieval test.
+# TEST Test the Btree and Record number get-by-number functionality.
proc test024 { method {nentries 10000} args} {
source ./include.tcl
global rand_init
@@ -25,6 +26,7 @@ proc test024 { method {nentries 10000} args} {
berkdb srand $rand_init
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -36,6 +38,18 @@ proc test024 { method {nentries 10000} args} {
set testfile test024.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -59,11 +73,11 @@ proc test024 { method {nentries 10000} args} {
set sorted_keys [lsort $keys]
# Create the database
if { [string compare $omethod "-btree"] == 0 } {
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644 -recnum} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
} else {
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
}
@@ -84,12 +98,20 @@ proc test024 { method {nentries 10000} args} {
} else {
set key $k
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $k]}]
error_check_good put $ret 0
set ret [eval {$db get} $txn $gflags {$key}]
error_check_good \
get $ret [list [list $key [pad_data $method $k]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Now we will get each key from the DB and compare the results
@@ -111,13 +133,21 @@ proc test024 { method {nentries 10000} args} {
set gflags " -recno"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
for { set k 1 } { $k <= $count } { incr k } {
- set ret [eval {$db get} $txn $gflags {$k}]
+ set ret [eval {$db get} $txn $gflags {$k}]
puts $oid [lindex [lindex $ret 0] 1]
error_check_good recnum_get [lindex [lindex $ret 0] 1] \
[pad_data $method [lindex $sorted_keys [expr $k - 1]]]
}
close $oid
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
error_check_good Test024.c:diff($t1,$t2) \
@@ -128,12 +158,20 @@ proc test024 { method {nentries 10000} args} {
set db [eval {berkdb_open -rdonly} $args $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
set oid [open $t2 w]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
for { set k 1 } { $k <= $count } { incr k } {
- set ret [eval {$db get} $txn $gflags {$k}]
+ set ret [eval {$db get} $txn $gflags {$k}]
puts $oid [lindex [lindex $ret 0] 1]
error_check_good recnum_get [lindex [lindex $ret 0] 1] \
[pad_data $method [lindex $sorted_keys [expr $k - 1]]]
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $oid
error_check_good db_close [$db close] 0
error_check_good Test024.d:diff($t1,$t2) \
@@ -155,12 +193,20 @@ proc test024 { method {nentries 10000} args} {
close $oid
set oid [open $t2 w]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
for { set k $count } { $k > 0 } { incr k -1 } {
- set ret [eval {$db get} $txn $gflags {$k}]
+ set ret [eval {$db get} $txn $gflags {$k}]
puts $oid [lindex [lindex $ret 0] 1]
error_check_good recnum_get [lindex [lindex $ret 0] 1] \
[pad_data $method [lindex $sorted_keys [expr $k - 1]]]
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $oid
error_check_good db_close [$db close] 0
error_check_good Test024.e:diff($t1,$t2) \
@@ -175,12 +221,20 @@ proc test024 { method {nentries 10000} args} {
set kval [lindex $keys [expr $kndx - 1]]
set recno [expr [lsearch $sorted_keys $kval] + 1]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
if { [is_record_based $method] == 1 } {
set ret [eval {$db del} $txn {$recno}]
} else {
set ret [eval {$db del} $txn {$kval}]
}
error_check_good delete $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Remove the key from the key list
set ndx [expr $kndx - 1]
@@ -192,12 +246,20 @@ proc test024 { method {nentries 10000} args} {
}
# Check that the keys after it have been renumbered
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
if { $do_renumber == 1 && $recno != $count } {
set r [expr $recno - 1]
set ret [eval {$db get} $txn $gflags {$recno}]
error_check_good get_after_del \
[lindex [lindex $ret 0] 1] [lindex $sorted_keys $r]
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Decrement count
incr count -1
diff --git a/bdb/test/test025.tcl b/bdb/test/test025.tcl
index 9f8deecb488..180a1aa2939 100644
--- a/bdb/test/test025.tcl
+++ b/bdb/test/test025.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test025.tcl,v 11.11 2000/11/16 23:56:18 ubell Exp $
+# $Id: test025.tcl,v 11.19 2002/05/24 15:24:54 sue Exp $
#
-# DB Test 25 {method nentries}
-# Test the DB_APPEND flag.
+# TEST test025
+# TEST DB_APPEND flag test.
proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
global kvals
source ./include.tcl
@@ -25,6 +25,7 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -36,12 +37,24 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -58,22 +71,42 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
gets $did str
set k [expr $count + 1]
set kvals($k) [pad_data $method $str]
- set ret [eval {$db put} $txn $k {[chop_data $method $str]}]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$k [chop_data $method $str]}]
error_check_good db_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
-
+
while { [gets $did str] != -1 && $count < $nentries } {
set k [expr $count + 1]
set kvals($k) [pad_data $method $str]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} $txn $pflags {[chop_data $method $str]}]
error_check_good db_put $ret $k
set ret [eval {$db get} $txn $gflags {$k}]
error_check_good \
get $ret [list [list $k [pad_data $method $str]]]
- incr count
- if { [expr $count + 1] == 0 } {
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ # The recno key will be count + 1, so when we hit
+ # UINT32_MAX - 1, reset to 0.
+ if { $count == [expr 0xfffffffe] } {
+ set count 0
+ } else {
incr count
}
}
@@ -82,18 +115,26 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest0$tnum.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest0$tnum.c: close, open, and dump file"
# Now, reopen the file and run the last test again.
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_file_direction -first -next
# Now, reopen the file and run the last test again in the
# reverse direction.
puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
- open_and_dump_file $testfile $env $txn $t1 $checkfunc \
+ open_and_dump_file $testfile $env $t1 $checkfunc \
dump_file_direction -last -prev
}
diff --git a/bdb/test/test026.tcl b/bdb/test/test026.tcl
index 6c19c60a2e5..ce65e925d35 100644
--- a/bdb/test/test026.tcl
+++ b/bdb/test/test026.tcl
@@ -1,14 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test026.tcl,v 11.13 2000/11/17 19:07:51 sue Exp $
+# $Id: test026.tcl,v 11.20 2002/06/11 14:09:56 sue Exp $
#
-# DB Test 26 {access method}
-# Keyed delete test through cursor.
-# If ndups is small; this will test on-page dups; if it's large, it
-# will test off-page dups.
+# TEST test026
+# TEST Small keys/medium data w/duplicates
+# TEST Put/get per key.
+# TEST Loop through keys -- delete each key
+# TEST ... test that cursors delete duplicates correctly
+# TEST
+# TEST Keyed delete test through cursor. If ndups is small; this will
+# TEST test on-page dups; if it's large, it will test off-page dups.
proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
source ./include.tcl
@@ -20,10 +24,8 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
puts "Test0$tnum skipping for method $method"
return
}
- puts "Test0$tnum: $method ($args) $nentries keys\
- with $ndups dups; cursor delete test"
-
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -35,8 +37,25 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the defaults down a bit.
+ # If we are wanting a lot of dups, set that
+ # down a bit or repl testing takes very long.
+ #
+ if { $nentries == 2000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
+ puts "Test0$tnum: $method ($args) $nentries keys\
+ with $ndups dups; cursor delete test"
set pflags ""
set gflags ""
@@ -46,16 +65,24 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
# Here is the loop where we put and get each key/data pair
puts "\tTest0$tnum.a: Put loop"
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644} $args {$omethod -dup $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
while { [gets $did str] != -1 && $count < [expr $nentries * $ndups] } {
set datastr [ make_data_str $str ]
for { set j 1 } { $j <= $ndups} {incr j} {
- set ret [eval {$db put} \
- $txn $pflags {$str [chop_data $method $j$datastr]}]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} \
+ $txn $pflags {$str [chop_data $method $j$datastr]}]
error_check_good db_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
incr count
}
}
@@ -68,6 +95,11 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
# Now we will sequentially traverse the database getting each
# item and deleting it.
set count 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_substr $dbc $db] 1
@@ -97,16 +129,27 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
error_check_good db_del:$key $ret 0
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest0$tnum.c: Verify empty file"
# Double check that file is now empty
set db [eval {berkdb_open} $args $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_substr $dbc $db] 1
set ret [$dbc get -first]
error_check_good get_on_empty [string length $ret] 0
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test027.tcl b/bdb/test/test027.tcl
index ae4bf64fb3e..a0f6dfa4dcb 100644
--- a/bdb/test/test027.tcl
+++ b/bdb/test/test027.tcl
@@ -1,13 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test027.tcl,v 11.4 2000/05/22 12:51:39 bostic Exp $
+# $Id: test027.tcl,v 11.7 2002/01/11 15:53:45 bostic Exp $
#
-# DB Test 27 {access method}
-# Check that delete operations work. Create a database; close database and
-# reopen it. Then issues delete by key for each entry.
+# TEST test027
+# TEST Off-page duplicate test
+# TEST Test026 with parameters to force off-page duplicates.
+# TEST
+# TEST Check that delete operations work. Create a database; close
+# TEST database and reopen it. Then issues delete by key for each
+# TEST entry.
proc test027 { method {nentries 100} args} {
eval {test026 $method $nentries 100 27} $args
}
diff --git a/bdb/test/test028.tcl b/bdb/test/test028.tcl
index b460dd53a98..a546744fdac 100644
--- a/bdb/test/test028.tcl
+++ b/bdb/test/test028.tcl
@@ -1,16 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test028.tcl,v 11.12 2000/08/25 14:21:55 sue Exp $
+# $Id: test028.tcl,v 11.20 2002/07/01 15:03:45 krinsky Exp $
#
-# Put after cursor delete test.
+# TEST test028
+# TEST Cursor delete test
+# TEST Test put operations after deleting through a cursor.
proc test028 { method args } {
global dupnum
global dupstr
global alphabet
- global errorInfo
source ./include.tcl
set args [convert_args $method $args]
@@ -30,6 +31,7 @@ proc test028 { method args } {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -41,11 +43,16 @@ proc test028 { method args } {
set testfile test028.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set ndups 20
@@ -57,6 +64,11 @@ proc test028 { method args } {
set gflags " -recno"
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_substr $dbc $db] 1
@@ -129,8 +141,8 @@ proc test028 { method args } {
puts "\tTest028.g: Insert key with duplicates"
for { set count 0 } { $count < $ndups } { incr count } {
- set ret [eval {$db put} \
- $txn {$key [chop_data $method $count$dupstr]}]
+ set ret [eval {$db put} $txn \
+ {$key [chop_data $method $count$dupstr]}]
error_check_good db_put $ret 0
}
@@ -161,7 +173,6 @@ proc test028 { method args } {
if { $count == [expr $ndups - 1] } {
puts "\tTest028.k:\
Duplicate No_Overwrite test"
- set $errorInfo ""
set ret [eval {$db put} $txn \
{-nooverwrite $key $dupstr}]
error_check_good db_put [is_substr \
@@ -179,7 +190,8 @@ proc test028 { method args } {
$txn {-nooverwrite $key 0$dupstr}]
error_check_good db_put $ret 0
for { set count 1 } { $count < $ndups } { incr count } {
- set ret [eval {$db put} $txn {$key $count$dupstr}]
+ set ret [eval {$db put} $txn \
+ {$key $count$dupstr}]
error_check_good db_put $ret 0
}
@@ -192,8 +204,10 @@ proc test028 { method args } {
error_check_good db_del $ret 0
}
}
-
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test029.tcl b/bdb/test/test029.tcl
index c10815b0bf3..8e4b8aa6e41 100644
--- a/bdb/test/test029.tcl
+++ b/bdb/test/test029.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test029.tcl,v 11.13 2000/08/25 14:21:55 sue Exp $
+# $Id: test029.tcl,v 11.20 2002/06/29 13:44:44 bostic Exp $
#
-# DB Test 29 {method nentries}
-# Test the Btree and Record number renumbering.
+# TEST test029
+# TEST Test the Btree and Record number renumbering.
proc test029 { method {nentries 10000} args} {
source ./include.tcl
@@ -26,6 +26,7 @@ proc test029 { method {nentries 10000} args} {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -37,6 +38,20 @@ proc test029 { method {nentries 10000} args} {
set testfile test029.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ # Do not set nentries down to 100 until we
+ # fix SR #5958.
+ set nentries 1000
+ }
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -64,11 +79,11 @@ proc test029 { method {nentries 10000} args} {
# Create the database
if { [string compare $omethod "-btree"] == 0 } {
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644 -recnum} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
} else {
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
}
@@ -89,14 +104,19 @@ proc test029 { method {nentries 10000} args} {
} else {
set key $k
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$key [chop_data $method $k]}]
error_check_good dbput $ret 0
set ret [eval {$db get} $txn $gflags {$key}]
- if { [string compare [lindex [lindex $ret 0] 1] $k] != 0 } {
- puts "Test029: put key-data $key $k got $ret"
- return
+ error_check_good dbget [lindex [lindex $ret 0] 1] $k
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
}
}
@@ -110,8 +130,16 @@ proc test029 { method {nentries 10000} args} {
set key $first_key
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db del} $txn {$key}]
error_check_good db_del $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now we are ready to retrieve records based on
# record number
@@ -120,28 +148,50 @@ proc test029 { method {nentries 10000} args} {
}
# First try to get the old last key (shouldn't exist)
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db get} $txn $gflags {$last_keynum}]
error_check_good get_after_del $ret [list]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Now try to get what we think should be the last key
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db get} $txn $gflags {[expr $last_keynum - 1]}]
error_check_good \
getn_last_after_del [lindex [lindex $ret 0] 1] $last_key
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Create a cursor; we need it for the next test and we
# need it for recno here.
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good db_cursor [is_substr $dbc $db] 1
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
# OK, now re-put the first key and make sure that we
# renumber the last key appropriately.
if { [string compare $omethod "-btree"] == 0 } {
- set ret [eval {$db put} $txn {$key [chop_data $method $first_key]}]
+ set ret [eval {$db put} $txn \
+ {$key [chop_data $method $first_key]}]
error_check_good db_put $ret 0
} else {
# Recno
- set ret [eval {$dbc get} $txn {-first}]
- set ret [eval {$dbc put} $txn $pflags {-before $first_key}]
+ set ret [$dbc get -first]
+ set ret [eval {$dbc put} $pflags {-before $first_key}]
error_check_bad dbc_put:DB_BEFORE $ret 0
}
@@ -153,7 +203,7 @@ proc test029 { method {nentries 10000} args} {
# Now delete the first key in the database using a cursor
puts "\tTest029.d: delete with cursor and verify renumber"
- set ret [eval {$dbc get} $txn {-first}]
+ set ret [$dbc get -first]
error_check_good dbc_first $ret [list [list $key $first_key]]
# Now delete at the cursor
@@ -175,10 +225,10 @@ proc test029 { method {nentries 10000} args} {
puts "\tTest029.e: put with cursor and verify renumber"
if { [string compare $omethod "-btree"] == 0 } {
set ret [eval {$dbc put} \
- $txn $pflags {-current $first_key}]
+ $pflags {-current $first_key}]
error_check_good dbc_put:DB_CURRENT $ret 0
} else {
- set ret [eval {$dbc put} $txn $pflags {-before $first_key}]
+ set ret [eval {$dbc put} $pflags {-before $first_key}]
error_check_bad dbc_put:DB_BEFORE $ret 0
}
@@ -188,5 +238,8 @@ proc test029 { method {nentries 10000} args} {
get_after_cursor_reput [lindex [lindex $ret 0] 1] $last_key
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test030.tcl b/bdb/test/test030.tcl
index 7395adf82bd..d91359f07a0 100644
--- a/bdb/test/test030.tcl
+++ b/bdb/test/test030.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test030.tcl,v 11.13 2000/08/25 14:21:55 sue Exp $
+# $Id: test030.tcl,v 11.18 2002/05/22 15:42:50 sue Exp $
#
-# DB Test 30: Test DB_NEXT_DUP Functionality.
+# TEST test030
+# TEST Test DB_NEXT_DUP Functionality.
proc test030 { method {nentries 10000} args } {
global rand_init
source ./include.tcl
@@ -18,11 +19,10 @@ proc test030 { method {nentries 10000} args } {
puts "Test030 skipping for method $method"
return
}
-
- puts "Test030: $method ($args) $nentries DB_NEXT_DUP testing"
berkdb srand $rand_init
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -36,20 +36,34 @@ proc test030 { method {nentries 10000} args } {
set cntfile cntfile.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+
+ puts "Test030: $method ($args) $nentries DB_NEXT_DUP testing"
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644 -dup} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
# Use a second DB to keep track of how many duplicates
# we enter per key
- set cntdb [eval {berkdb_open -create -truncate \
+ set cntdb [eval {berkdb_open -create \
-mode 0644} $args {-btree $cntfile}]
error_check_good dbopen:cntfile [is_valid_db $db] TRUE
@@ -64,15 +78,30 @@ proc test030 { method {nentries 10000} args } {
set did [open $dict]
puts "\tTest030.a: put and get duplicate keys."
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
while { [gets $did str] != -1 && $count < $nentries } {
set ndup [berkdb random_int 1 10]
for { set i 1 } { $i <= $ndup } { incr i 1 } {
+ set ctxn ""
+ if { $txnenv == 1 } {
+ set ct [$env txn]
+ error_check_good txn \
+ [is_valid_txn $ct $env] TRUE
+ set ctxn "-txn $ct"
+ }
set ret [eval {$cntdb put} \
- $txn $pflags {$str [chop_data $method $ndup]}]
+ $ctxn $pflags {$str [chop_data $method $ndup]}]
error_check_good put_cnt $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$ct commit] 0
+ }
set datastr $i:$str
set ret [eval {$db put} \
$txn $pflags {$str [chop_data $method $datastr]}]
@@ -132,8 +161,16 @@ proc test030 { method {nentries 10000} args } {
set lastkey $k
# Figure out how may dups we should have
- set ret [eval {$cntdb get} $txn $pflags {$k}]
+ if { $txnenv == 1 } {
+ set ct [$env txn]
+ error_check_good txn [is_valid_txn $ct $env] TRUE
+ set ctxn "-txn $ct"
+ }
+ set ret [eval {$cntdb get} $ctxn $pflags {$k}]
set ndup [lindex [lindex $ret 0] 1]
+ if { $txnenv == 1 } {
+ error_check_good txn [$ct commit] 0
+ }
set howmany 1
for { set ret [$dbc get -nextdup] } \
@@ -186,6 +223,9 @@ proc test030 { method {nentries 10000} args } {
}
error_check_good cnt_curs_close [$cnt_dbc close] 0
error_check_good db_curs_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good cnt_file_close [$cntdb close] 0
error_check_good db_file_close [$db close] 0
}
diff --git a/bdb/test/test031.tcl b/bdb/test/test031.tcl
index 35041541fa7..0006deb2d99 100644
--- a/bdb/test/test031.tcl
+++ b/bdb/test/test031.tcl
@@ -1,21 +1,25 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test031.tcl,v 11.17 2000/11/06 19:31:55 sue Exp $
+# $Id: test031.tcl,v 11.24 2002/06/26 06:22:44 krinsky Exp $
#
-# DB Test 31 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and "ndups" duplicates
-# For the data field, prepend random five-char strings (see test032)
-# that we force the duplicate sorting code to do something.
-# Along the way, test that we cannot insert duplicate duplicates
-# using DB_NODUPDATA.
-# By setting ndups large, we can make this an off-page test
-# After all are entered, retrieve all; verify output.
-# Close file, reopen, do retrieve and re-verify.
-# This does not work for recno
+# TEST test031
+# TEST Duplicate sorting functionality
+# TEST Make sure DB_NODUPDATA works.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and "ndups" duplicates
+# TEST For the data field, prepend random five-char strings (see test032)
+# TEST that we force the duplicate sorting code to do something.
+# TEST Along the way, test that we cannot insert duplicate duplicates
+# TEST using DB_NODUPDATA.
+# TEST
+# TEST By setting ndups large, we can make this an off-page test
+# TEST After all are entered, retrieve all; verify output.
+# TEST Close file, reopen, do retrieve and re-verify.
+# TEST This does not work for recno
proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
global alphabet
global rand_init
@@ -27,6 +31,7 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
set omethod [convert_method $method]
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -40,6 +45,19 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
set checkdb checkdb.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -47,19 +65,19 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
cleanup $testdir $env
puts "Test0$tnum: \
- $method ($args) $nentries small sorted dup key/data pairs"
+ $method ($args) $nentries small $ndups sorted dup key/data pairs"
if { [is_record_based $method] == 1 || \
[is_rbtree $method] == 1 } {
puts "Test0$tnum skipping for method $omethod"
return
}
- set db [eval {berkdb_open -create -truncate \
+ set db [eval {berkdb_open -create \
-mode 0644} $args {$omethod -dup -dupsort $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
set check_db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {-hash $checkdb}]
+ -create -mode 0644} $args {-hash $checkdb}]
error_check_good dbopen:check_db [is_valid_db $check_db] TRUE
set pflags ""
@@ -69,8 +87,13 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
# Here is the loop where we put and get each key/data pair
puts "\tTest0$tnum.a: Put/get loop, check nodupdata"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
while { [gets $did str] != -1 && $count < $nentries } {
# Re-initialize random string generator
randstring_init $ndups
@@ -132,13 +155,21 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
incr count
}
error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $did
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest0$tnum.b: Checking file for correct duplicates"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open(2) [is_substr $dbc $db] 1
+ error_check_good cursor_open(2) [is_valid_cursor $dbc $db] TRUE
set lastkey "THIS WILL NEVER BE A KEY VALUE"
# no need to delete $lastkey
@@ -189,8 +220,11 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
set ret [$check_c get -first]
error_check_good check_c:get:$ret [llength $ret] 0
error_check_good check_c:close [$check_c close] 0
- error_check_good check_db:close [$check_db close] 0
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good check_db:close [$check_db close] 0
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test032.tcl b/bdb/test/test032.tcl
index 1504ec5cc2d..2076b744851 100644
--- a/bdb/test/test032.tcl
+++ b/bdb/test/test032.tcl
@@ -1,20 +1,22 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test032.tcl,v 11.15 2000/08/25 14:21:55 sue Exp $
+# $Id: test032.tcl,v 11.23 2002/06/11 14:09:57 sue Exp $
#
-# DB Test 32 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and "ndups" duplicates
-# For the data field, prepend the letters of the alphabet
-# in a random order so that we force the duplicate sorting
-# code to do something.
-# By setting ndups large, we can make this an off-page test
-# After all are entered; test the DB_GET_BOTH functionality
-# first by retrieving each dup in the file explicitly. Then
-# test the failure case.
+# TEST test032
+# TEST DB_GET_BOTH, DB_GET_BOTH_RANGE
+# TEST
+# TEST Use the first 10,000 entries from the dictionary. Insert each with
+# TEST self as key and "ndups" duplicates. For the data field, prepend the
+# TEST letters of the alphabet in a random order so we force the duplicate
+# TEST sorting code to do something. By setting ndups large, we can make
+# TEST this an off-page test.
+# TEST
+# TEST Test the DB_GET_BOTH functionality by retrieving each dup in the file
+# TEST explicitly. Test the DB_GET_BOTH_RANGE functionality by retrieving
+# TEST the unique key prefix (cursor only). Finally test the failure case.
proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
global alphabet rand_init
source ./include.tcl
@@ -25,6 +27,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
berkdb srand $rand_init
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -38,6 +41,19 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
set checkdb checkdb.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -45,19 +61,19 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
cleanup $testdir $env
puts "Test0$tnum:\
- $method ($args) $nentries small sorted dup key/data pairs"
+ $method ($args) $nentries small sorted $ndups dup key/data pairs"
if { [is_record_based $method] == 1 || \
[is_rbtree $method] == 1 } {
puts "Test0$tnum skipping for method $omethod"
return
}
- set db [eval {berkdb_open -create -truncate -mode 0644 \
+ set db [eval {berkdb_open -create -mode 0644 \
$omethod -dup -dupsort} $args {$testfile} ]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
set check_db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {-hash $checkdb}]
+ -create -mode 0644} $args {-hash $checkdb}]
error_check_good dbopen:check_db [is_valid_db $check_db] TRUE
set pflags ""
@@ -67,8 +83,13 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
# Here is the loop where we put and get each key/data pair
puts "\tTest0$tnum.a: Put/get loop"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
while { [gets $did str] != -1 && $count < $nentries } {
# Re-initialize random string generator
randstring_init $ndups
@@ -101,8 +122,8 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
break
}
if {[string compare $lastdup $datastr] > 0} {
- error_check_good sorted_dups($lastdup,$datastr)\
- 0 1
+ error_check_good \
+ sorted_dups($lastdup,$datastr) 0 1
}
incr x
set lastdup $datastr
@@ -112,14 +133,22 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
incr count
}
error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $did
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest0$tnum.b: Checking file for correct duplicates (no cursor)"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set check_c [eval {$check_db cursor} $txn]
error_check_good check_c_open(2) \
- [is_substr $check_c $check_db] 1
+ [is_valid_cursor $check_c $check_db] TRUE
for {set ndx 0} {$ndx < [expr 4 * $ndups]} {incr ndx 4} {
for {set ret [$check_c get -first]} \
@@ -138,10 +167,11 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
}
$db sync
+
# Now repeat the above test using cursor ops
puts "\tTest0$tnum.c: Checking file for correct duplicates (cursor)"
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
for {set ndx 0} {$ndx < [expr 4 * $ndups]} {incr ndx 4} {
for {set ret [$check_c get -first]} \
@@ -155,7 +185,11 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
set data $pref:$k
set ret [eval {$dbc get} {-get_both $k $data}]
error_check_good \
- get_both_key:$k $ret [list [list $k $data]]
+ curs_get_both_data:$k $ret [list [list $k $data]]
+
+ set ret [eval {$dbc get} {-get_both_range $k $pref}]
+ error_check_good \
+ curs_get_both_range:$k $ret [list [list $k $data]]
}
}
@@ -188,8 +222,10 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
}
error_check_good check_c:close [$check_c close] 0
- error_check_good check_db:close [$check_db close] 0
-
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good check_db:close [$check_db close] 0
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test033.tcl b/bdb/test/test033.tcl
index ed46e6bda04..a7796ce99d6 100644
--- a/bdb/test/test033.tcl
+++ b/bdb/test/test033.tcl
@@ -1,31 +1,32 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test033.tcl,v 11.11 2000/10/25 15:45:20 sue Exp $
+# $Id: test033.tcl,v 11.24 2002/08/08 15:38:11 bostic Exp $
#
-# DB Test 33 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and data; add duplicate
-# records for each.
-# After all are entered, retrieve all; verify output by doing
-# DB_GET_BOTH on existing and non-existing keys.
-# This does not work for recno
+# TEST test033
+# TEST DB_GET_BOTH without comparison function
+# TEST
+# TEST Use the first 10,000 entries from the dictionary. Insert each with
+# TEST self as key and data; add duplicate records for each. After all are
+# TEST entered, retrieve all and verify output using DB_GET_BOTH (on DB and
+# TEST DBC handles) and DB_GET_BOTH_RANGE (on a DBC handle) on existent and
+# TEST nonexistent keys.
+# TEST
+# TEST XXX
+# TEST This does not work for rbtree.
proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
source ./include.tcl
set args [convert_args $method $args]
set omethod [convert_method $method]
-
- puts "Test0$tnum: $method ($args) $nentries small dup key/data pairs"
- if { [is_record_based $method] == 1 || \
- [is_rbtree $method] == 1 } {
- puts "Test0$tnum skipping for method $omethod"
+ if { [is_rbtree $method] == 1 } {
+ puts "Test0$tnum skipping for method $method"
return
}
- # Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -37,67 +38,139 @@ proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
+
+ puts "Test0$tnum: $method ($args) $nentries small $ndups dup key/data pairs"
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644 \
- $omethod -dup} $args {$testfile}]
+ # Duplicate data entries are not allowed in record based methods.
+ if { [is_record_based $method] == 1 } {
+ set db [eval {berkdb_open -create -mode 0644 \
+ $omethod} $args {$testfile}]
+ } else {
+ set db [eval {berkdb_open -create -mode 0644 \
+ $omethod -dup} $args {$testfile}]
+ }
error_check_good dbopen [is_valid_db $db] TRUE
- set did [open $dict]
set pflags ""
set gflags ""
set txn ""
- set count 0
+
+ # Allocate a cursor for DB_GET_BOTH_RANGE.
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
puts "\tTest0$tnum.a: Put/get loop."
# Here is the loop where we put and get each key/data pair
+ set count 0
+ set did [open $dict]
while { [gets $did str] != -1 && $count < $nentries } {
- for { set i 1 } { $i <= $ndups } { incr i } {
- set datastr $i:$str
- set ret [eval {$db put} \
- $txn $pflags {$str [chop_data $method $datastr]}]
- error_check_good db_put $ret 0
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ set ret [eval {$db put} $txn $pflags \
+ {$key [chop_data $method $str]}]
+ error_check_good put $ret 0
+ } else {
+ for { set i 1 } { $i <= $ndups } { incr i } {
+ set datastr $i:$str
+ set ret [eval {$db put} \
+ $txn $pflags {$str [chop_data $method $datastr]}]
+ error_check_good db_put $ret 0
+ }
}
# Now retrieve all the keys matching this key and dup
- for {set i 1} {$i <= $ndups } { incr i } {
- set datastr $i:$str
- set ret [eval {$db get} $txn {-get_both $str $datastr}]
- error_check_good "Test0$tnum:dup#" [lindex \
- [lindex $ret 0] 1] [pad_data $method $datastr]
+ # for non-record based AMs.
+ if { [is_record_based $method] == 1 } {
+ test033_recno.check $db $dbc $method $str $txn $key
+ } else {
+ test033_check $db $dbc $method $str $txn $ndups
}
-
- # Now retrieve non-existent dup (i is ndups + 1)
- set datastr $i:$str
- set ret [eval {$db get} $txn {-get_both $str $datastr}]
- error_check_good Test0$tnum:dupfailure [llength $ret] 0
incr count
}
+
close $did
- set did [open $dict]
- set count 0
puts "\tTest0$tnum.b: Verifying DB_GET_BOTH after creation."
+ set count 0
+ set did [open $dict]
while { [gets $did str] != -1 && $count < $nentries } {
- # Now retrieve all the keys matching this key and dup
- for {set i 1} {$i <= $ndups } { incr i } {
- set datastr $i:$str
- set ret [eval {$db get} $txn {-get_both $str $datastr}]
- error_check_good "Test0$tnum:dup#" \
- [lindex [lindex $ret 0] 1] $datastr
+ # Now retrieve all the keys matching this key
+ # for non-record based AMs.
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ test033_recno.check $db $dbc $method $str $txn $key
+ } else {
+ test033_check $db $dbc $method $str $txn $ndups
}
-
- # Now retrieve non-existent dup (i is ndups + 1)
- set datastr $i:$str
- set ret [eval {$db get} $txn {-get_both $str $datastr}]
- error_check_good Test0$tnum:dupfailure [llength $ret] 0
incr count
}
close $did
+ error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
+
+# No testing of dups is done on record-based methods.
+proc test033_recno.check {db dbc method str txn key} {
+ set ret [eval {$db get} $txn {-recno $key}]
+ error_check_good "db_get:$method" \
+ [lindex [lindex $ret 0] 1] [pad_data $method $str]
+ set ret [$dbc get -get_both $key [pad_data $method $str]]
+ error_check_good "db_get_both:$method" \
+ [lindex [lindex $ret 0] 1] [pad_data $method $str]
+}
+
+# Testing of non-record-based methods includes duplicates
+# and get_both_range.
+proc test033_check {db dbc method str txn ndups} {
+ for {set i 1} {$i <= $ndups } { incr i } {
+ set datastr $i:$str
+
+ set ret [eval {$db get} $txn {-get_both $str $datastr}]
+ error_check_good "db_get_both:dup#" \
+ [lindex [lindex $ret 0] 1] $datastr
+
+ set ret [$dbc get -get_both $str $datastr]
+ error_check_good "dbc_get_both:dup#" \
+ [lindex [lindex $ret 0] 1] $datastr
+
+ set ret [$dbc get -get_both_range $str $datastr]
+ error_check_good "dbc_get_both_range:dup#" \
+ [lindex [lindex $ret 0] 1] $datastr
+ }
+
+ # Now retrieve non-existent dup (i is ndups + 1)
+ set datastr $i:$str
+ set ret [eval {$db get} $txn {-get_both $str $datastr}]
+ error_check_good db_get_both:dupfailure [llength $ret] 0
+ set ret [$dbc get -get_both $str $datastr]
+ error_check_good dbc_get_both:dupfailure [llength $ret] 0
+ set ret [$dbc get -get_both_range $str $datastr]
+ error_check_good dbc_get_both_range [llength $ret] 0
+}
diff --git a/bdb/test/test034.tcl b/bdb/test/test034.tcl
index b82f369f791..647ad940815 100644
--- a/bdb/test/test034.tcl
+++ b/bdb/test/test034.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1998, 1999, 2000
+# Copyright (c) 1998-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test034.tcl,v 11.4 2000/02/14 03:00:19 bostic Exp $
+# $Id: test034.tcl,v 11.8 2002/01/11 15:53:46 bostic Exp $
#
-# DB Test 34 {access method}
-# DB_GET_BOTH functionality with off-page duplicates.
+# TEST test034
+# TEST test032 with off-page duplicates
+# TEST DB_GET_BOTH, DB_GET_BOTH_RANGE functionality with off-page duplicates.
proc test034 { method {nentries 10000} args} {
# Test with off-page duplicates
eval {test032 $method $nentries 20 34 -pagesize 512} $args
diff --git a/bdb/test/test035.tcl b/bdb/test/test035.tcl
index e2afef4afb3..06796b1e9aa 100644
--- a/bdb/test/test035.tcl
+++ b/bdb/test/test035.tcl
@@ -1,16 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test035.tcl,v 11.3 2000/02/14 03:00:19 bostic Exp $
+# $Id: test035.tcl,v 11.8 2002/07/22 17:00:39 sue Exp $
#
-# DB Test 35 {access method}
-# DB_GET_BOTH functionality with off-page duplicates.
+# TEST test035
+# TEST Test033 with off-page duplicates
+# TEST DB_GET_BOTH functionality with off-page duplicates.
proc test035 { method {nentries 10000} args} {
# Test with off-page duplicates
eval {test033 $method $nentries 20 35 -pagesize 512} $args
-
# Test with multiple pages of off-page duplicates
eval {test033 $method [expr $nentries / 10] 100 35 -pagesize 512} $args
}
diff --git a/bdb/test/test036.tcl b/bdb/test/test036.tcl
index 4d859c0652a..4e54f363ff8 100644
--- a/bdb/test/test036.tcl
+++ b/bdb/test/test036.tcl
@@ -1,27 +1,27 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test036.tcl,v 11.13 2000/08/25 14:21:55 sue Exp $
+# $Id: test036.tcl,v 11.18 2002/05/22 15:42:51 sue Exp $
#
-# DB Test 36 {access method}
-# Put nentries key/data pairs (from the dictionary) using a cursor
-# and KEYFIRST and KEYLAST (this tests the case where use use cursor
-# put for non-existent keys).
+# TEST test036
+# TEST Test KEYFIRST and KEYLAST when the key doesn't exist
+# TEST Put nentries key/data pairs (from the dictionary) using a cursor
+# TEST and KEYFIRST and KEYLAST (this tests the case where use use cursor
+# TEST put for non-existent keys).
proc test036 { method {nentries 10000} args } {
source ./include.tcl
set args [convert_args $method $args]
set omethod [convert_method $method]
-
- puts "Test036: $method ($args) $nentries equal key/data pairs"
if { [is_record_based $method] == 1 } {
puts "Test036 skipping for method recno"
return
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -33,13 +33,27 @@ proc test036 { method {nentries 10000} args } {
set testfile test036.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
+
+ puts "Test036: $method ($args) $nentries equal key/data pairs"
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $args {$omethod $testfile}]
+ -create -mode 0644} $args {$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -56,8 +70,13 @@ proc test036 { method {nentries 10000} args } {
}
puts "\tTest036.a: put/get loop KEYFIRST"
# Here is the loop where we put and get each key/data pair
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor [is_substr $dbc $db] 1
+ error_check_good cursor [is_valid_cursor $dbc $db] TRUE
while { [gets $did str] != -1 && $count < $nentries } {
if { [is_record_based $method] == 1 } {
global kvals
@@ -67,7 +86,7 @@ proc test036 { method {nentries 10000} args } {
} else {
set key $str
}
- set ret [eval {$dbc put} $txn $pflags {-keyfirst $key $str}]
+ set ret [eval {$dbc put} $pflags {-keyfirst $key $str}]
error_check_good put $ret 0
set ret [eval {$db get} $txn $gflags {$key}]
@@ -75,10 +94,18 @@ proc test036 { method {nentries 10000} args } {
incr count
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
puts "\tTest036.a: put/get loop KEYLAST"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor [is_substr $dbc $db] 1
+ error_check_good cursor [is_valid_cursor $dbc $db] TRUE
while { [gets $did str] != -1 && $count < $nentries } {
if { [is_record_based $method] == 1 } {
global kvals
@@ -96,12 +123,23 @@ proc test036 { method {nentries 10000} args } {
incr count
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $did
# Now we will get each key from the DB and compare the results
# to the original.
puts "\tTest036.c: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now compare the keys to see if they match the dictionary (or ints)
diff --git a/bdb/test/test037.tcl b/bdb/test/test037.tcl
index 31528c6ee54..0b2e2989949 100644
--- a/bdb/test/test037.tcl
+++ b/bdb/test/test037.tcl
@@ -1,12 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test037.tcl,v 11.11 2000/08/25 14:21:55 sue Exp $
+# $Id: test037.tcl,v 11.18 2002/03/15 16:30:54 sue Exp $
#
-# Test037: RMW functionality.
+# TEST test037
+# TEST Test DB_RMW
proc test037 { method {nentries 100} args } {
+ global encrypt
+
source ./include.tcl
set eindex [lsearch -exact $args "-env"]
#
@@ -21,6 +24,8 @@ proc test037 { method {nentries 100} args } {
puts "Test037: RMW $method"
set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
set omethod [convert_method $method]
# Create the database
@@ -28,7 +33,7 @@ proc test037 { method {nentries 100} args } {
set testfile test037.db
set local_env \
- [berkdb env -create -mode 0644 -txn -home $testdir]
+ [eval {berkdb_env -create -mode 0644 -txn} $encargs -home $testdir]
error_check_good dbenv [is_valid_env $local_env] TRUE
set db [eval {berkdb_open \
@@ -73,9 +78,9 @@ proc test037 { method {nentries 100} args } {
puts "\tTest037.b: Setting up environments"
# Open local environment
- set env_cmd [concat berkdb env -create -txn -home $testdir]
+ set env_cmd [concat berkdb_env -create -txn $encargs -home $testdir]
set local_env [eval $env_cmd]
- error_check_good dbenv [is_valid_widget $local_env env] TRUE
+ error_check_good dbenv [is_valid_env $local_env] TRUE
# Open local transaction
set local_txn [$local_env txn]
@@ -101,11 +106,11 @@ proc test037 { method {nentries 100} args } {
set did [open $dict]
set rkey 0
- set db [berkdb_open -env $local_env $testfile]
+ set db [berkdb_open -auto_commit -env $local_env $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
set rdb [send_cmd $f1 \
- "berkdb_open -env $remote_env -mode 0644 $testfile"]
- error_check_good remote:dbopen [is_valid_widget $rdb db] TRUE
+ "berkdb_open -auto_commit -env $remote_env -mode 0644 $testfile"]
+ error_check_good remote:dbopen [is_valid_db $rdb] TRUE
puts "\tTest037.d: Testing without RMW"
@@ -142,12 +147,12 @@ proc test037 { method {nentries 100} args } {
# Open local transaction
set local_txn [$local_env txn]
error_check_good \
- txn_open [is_valid_widget $local_txn $local_env.txn] TRUE
+ txn_open [is_valid_txn $local_txn $local_env] TRUE
# Open remote transaction
set remote_txn [send_cmd $f1 "$remote_env txn"]
error_check_good remote:txn_open \
- [is_valid_widget $remote_txn $remote_env.txn] TRUE
+ [is_valid_txn $remote_txn $remote_env] TRUE
# Now, get a key and try to "get" it from both DBs.
error_check_bad "gets on new open" [gets $did str] -1
diff --git a/bdb/test/test038.tcl b/bdb/test/test038.tcl
index 2a726f1bcd9..3babde8fe0b 100644
--- a/bdb/test/test038.tcl
+++ b/bdb/test/test038.tcl
@@ -1,20 +1,22 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test038.tcl,v 11.12 2000/08/25 14:21:56 sue Exp $
+# $Id: test038.tcl,v 11.23 2002/06/11 14:09:57 sue Exp $
#
-# DB Test 38 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and "ndups" duplicates
-# For the data field, prepend the letters of the alphabet
-# in a random order so that we force the duplicate sorting
-# code to do something.
-# By setting ndups large, we can make this an off-page test
-# After all are entered; test the DB_GET_BOTH functionality
-# first by retrieving each dup in the file explicitly. Then
-# remove each duplicate and try DB_GET_BOTH again.
+# TEST test038
+# TEST DB_GET_BOTH, DB_GET_BOTH_RANGE on deleted items
+# TEST
+# TEST Use the first 10,000 entries from the dictionary. Insert each with
+# TEST self as key and "ndups" duplicates. For the data field, prepend the
+# TEST letters of the alphabet in a random order so we force the duplicate
+# TEST sorting code to do something. By setting ndups large, we can make
+# TEST this an off-page test
+# TEST
+# TEST Test the DB_GET_BOTH and DB_GET_BOTH_RANGE functionality by retrieving
+# TEST each dup in the file explicitly. Then remove each duplicate and try
+# TEST the retrieval again.
proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
global alphabet
global rand_init
@@ -25,7 +27,13 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
+ if { [is_record_based $method] == 1 || \
+ [is_rbtree $method] == 1 } {
+ puts "Test0$tnum skipping for method $method"
+ return
+ }
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -39,6 +47,19 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
set checkdb checkdb.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
@@ -47,18 +68,13 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
puts "Test0$tnum: \
$method ($args) $nentries small sorted dup key/data pairs"
- if { [is_record_based $method] == 1 || \
- [is_rbtree $method] == 1 } {
- puts "Test0$tnum skipping for method $method"
- return
- }
- set db [eval {berkdb_open -create -truncate -mode 0644 \
+ set db [eval {berkdb_open -create -mode 0644 \
$omethod -dup -dupsort} $args {$testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
- set check_db [berkdb_open \
- -create -truncate -mode 0644 -hash $checkdb]
+ set check_db [eval {berkdb_open \
+ -create -mode 0644 -hash} $args {$checkdb}]
error_check_good dbopen:check_db [is_valid_db $check_db] TRUE
set pflags ""
@@ -68,8 +84,13 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
# Here is the loop where we put and get each key/data pair
puts "\tTest0$tnum.a: Put/get loop"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
while { [gets $did str] != -1 && $count < $nentries } {
set dups ""
for { set i 1 } { $i <= $ndups } { incr i } {
@@ -125,14 +146,22 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
incr count
}
error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $did
# Now check the duplicates, then delete then recheck
puts "\tTest0$tnum.b: Checking and Deleting duplicates"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
set check_c [eval {$check_db cursor} $txn]
- error_check_good cursor_open [is_substr $check_c $check_db] 1
+ error_check_good cursor_open [is_valid_cursor $check_c $check_db] TRUE
for {set ndx 0} {$ndx < $ndups} {incr ndx} {
for {set ret [$check_c get -first]} \
@@ -145,16 +174,37 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
set nn [expr $ndx * 3]
set pref [string range $d $nn [expr $nn + 1]]
set data $pref:$k
- set ret [eval {$dbc get} $txn {-get_both $k $data}]
+ set ret [$dbc get -get_both $k $data]
error_check_good \
get_both_key:$k [lindex [lindex $ret 0] 0] $k
error_check_good \
get_both_data:$k [lindex [lindex $ret 0] 1] $data
+
+ set ret [$dbc get -get_both_range $k $pref]
+ error_check_good \
+ get_both_key:$k [lindex [lindex $ret 0] 0] $k
+ error_check_good \
+ get_both_data:$k [lindex [lindex $ret 0] 1] $data
+
set ret [$dbc del]
error_check_good del $ret 0
+
set ret [eval {$db get} $txn {-get_both $k $data}]
error_check_good error_case:$k [llength $ret] 0
+ # We should either not find anything (if deleting the
+ # largest duplicate in the set) or a duplicate that
+ # sorts larger than the one we deleted.
+ set ret [$dbc get -get_both_range $k $pref]
+ if { [llength $ret] != 0 } {
+ set datastr [lindex [lindex $ret 0] 1]]
+ if {[string compare \
+ $pref [lindex [lindex $ret 0] 1]] >= 0} {
+ error_check_good \
+ error_case_range:sorted_dups($pref,$datastr) 0 1
+ }
+ }
+
if {$ndx != 0} {
set n [expr ($ndx - 1) * 3]
set pref [string range $d $n [expr $n + 1]]
@@ -167,8 +217,11 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
}
error_check_good check_c:close [$check_c close] 0
- error_check_good check_db:close [$check_db close] 0
-
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ error_check_good check_db:close [$check_db close] 0
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test039.tcl b/bdb/test/test039.tcl
index 957468ce542..2bbc83ebe05 100644
--- a/bdb/test/test039.tcl
+++ b/bdb/test/test039.tcl
@@ -1,20 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test039.tcl,v 11.11 2000/08/25 14:21:56 sue Exp $
+# $Id: test039.tcl,v 11.20 2002/06/11 14:09:57 sue Exp $
#
-# DB Test 39 {access method}
-# Use the first 10,000 entries from the dictionary.
-# Insert each with self as key and "ndups" duplicates
-# For the data field, prepend the letters of the alphabet
-# in a random order so that we force the duplicate sorting
-# code to do something.
-# By setting ndups large, we can make this an off-page test
-# After all are entered; test the DB_GET_BOTH functionality
-# first by retrieving each dup in the file explicitly. Then
-# remove each duplicate and try DB_GET_BOTH again.
+# TEST test039
+# TEST DB_GET_BOTH/DB_GET_BOTH_RANGE on deleted items without comparison
+# TEST function.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary. Insert each with
+# TEST self as key and "ndups" duplicates. For the data field, prepend the
+# TEST letters of the alphabet in a random order so we force the duplicate
+# TEST sorting code to do something. By setting ndups large, we can make
+# TEST this an off-page test.
+# TEST
+# TEST Test the DB_GET_BOTH and DB_GET_BOTH_RANGE functionality by retrieving
+# TEST each dup in the file explicitly. Then remove each duplicate and try
+# TEST the retrieval again.
proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
global alphabet
global rand_init
@@ -25,7 +28,13 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
+ if { [is_record_based $method] == 1 || \
+ [is_rbtree $method] == 1 } {
+ puts "Test0$tnum skipping for method $method"
+ return
+ }
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -39,26 +48,35 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
set checkdb checkdb.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
set t2 $testdir/t2
set t3 $testdir/t3
cleanup $testdir $env
- puts "Test0$tnum: $method $nentries small unsorted dup key/data pairs"
- if { [is_record_based $method] == 1 || \
- [is_rbtree $method] == 1 } {
- puts "Test0$tnum skipping for method $method"
- return
- }
+ puts "Test0$tnum: $method $nentries \
+ small $ndups unsorted dup key/data pairs"
- set db [eval {berkdb_open -create -truncate -mode 0644 \
+ set db [eval {berkdb_open -create -mode 0644 \
$omethod -dup} $args {$testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
- set check_db \
- [berkdb_open -create -truncate -mode 0644 -hash $checkdb]
+ set check_db [eval \
+ {berkdb_open -create -mode 0644 -hash} $args {$checkdb}]
error_check_good dbopen:check_db [is_valid_db $check_db] TRUE
set pflags ""
@@ -68,8 +86,13 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
# Here is the loop where we put and get each key/data pair
puts "\tTest0$tnum.a: Put/get loop"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
while { [gets $did str] != -1 && $count < $nentries } {
set dups ""
for { set i 1 } { $i <= $ndups } { incr i } {
@@ -124,14 +147,22 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
incr count
}
error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
close $did
# Now check the duplicates, then delete then recheck
puts "\tTest0$tnum.b: Checking and Deleting duplicates"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
+ error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
set check_c [eval {$check_db cursor} $txn]
- error_check_good cursor_open [is_substr $check_c $check_db] 1
+ error_check_good cursor_open [is_valid_cursor $check_c $check_db] TRUE
for {set ndx 0} {$ndx < $ndups} {incr ndx} {
for {set ret [$check_c get -first]} \
@@ -144,8 +175,7 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
set nn [expr $ndx * 3]
set pref [string range $d $nn [expr $nn + 1]]
set data $pref:$k
- set ret \
- [eval {$dbc get} $txn $gflags {-get_both $k $data}]
+ set ret [$dbc get -get_both $k $data]
error_check_good \
get_both_key:$k [lindex [lindex $ret 0] 0] $k
error_check_good \
@@ -154,24 +184,28 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
set ret [$dbc del]
error_check_good del $ret 0
- set ret \
- [eval {$dbc get} $txn $gflags {-get_both $k $data}]
- error_check_good error_case:$k [llength $ret] 0
+ set ret [$dbc get -get_both $k $data]
+ error_check_good get_both:$k [llength $ret] 0
+
+ set ret [$dbc get -get_both_range $k $data]
+ error_check_good get_both_range:$k [llength $ret] 0
if {$ndx != 0} {
set n [expr ($ndx - 1) * 3]
set pref [string range $d $n [expr $n + 1]]
set data $pref:$k
- set ret [eval {$dbc get} \
- $txn $gflags {-get_both $k $data}]
+ set ret [$dbc get -get_both $k $data]
error_check_good error_case:$k [llength $ret] 0
}
}
}
error_check_good check_c:close [$check_c close] 0
- error_check_good check_db:close [$check_db close] 0
-
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ error_check_good check_db:close [$check_db close] 0
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test040.tcl b/bdb/test/test040.tcl
index 912e1735d8e..1856f78fc2e 100644
--- a/bdb/test/test040.tcl
+++ b/bdb/test/test040.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1998, 1999, 2000
+# Copyright (c) 1998-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test040.tcl,v 11.3 2000/02/14 03:00:20 bostic Exp $
+# $Id: test040.tcl,v 11.6 2002/01/11 15:53:47 bostic Exp $
#
-# DB Test 40 {access method}
-# DB_GET_BOTH functionality with off-page duplicates.
+# TEST test040
+# TEST Test038 with off-page duplicates
+# TEST DB_GET_BOTH functionality with off-page duplicates.
proc test040 { method {nentries 10000} args} {
# Test with off-page duplicates
eval {test038 $method $nentries 20 40 -pagesize 512} $args
diff --git a/bdb/test/test041.tcl b/bdb/test/test041.tcl
index bba89f49b5a..fdcbdbef3d7 100644
--- a/bdb/test/test041.tcl
+++ b/bdb/test/test041.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test041.tcl,v 11.3 2000/02/14 03:00:20 bostic Exp $
+# $Id: test041.tcl,v 11.6 2002/01/11 15:53:47 bostic Exp $
#
-# DB Test 41 {access method}
-# DB_GET_BOTH functionality with off-page duplicates.
+# TEST test041
+# TEST Test039 with off-page duplicates
+# TEST DB_GET_BOTH functionality with off-page duplicates.
proc test041 { method {nentries 10000} args} {
# Test with off-page duplicates
eval {test039 $method $nentries 20 41 -pagesize 512} $args
diff --git a/bdb/test/test042.tcl b/bdb/test/test042.tcl
index 232cb3a6b0e..9f444b8349c 100644
--- a/bdb/test/test042.tcl
+++ b/bdb/test/test042.tcl
@@ -1,27 +1,26 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test042.tcl,v 11.24 2000/08/25 14:21:56 sue Exp $
+# $Id: test042.tcl,v 11.37 2002/09/05 17:23:07 sandstro Exp $
#
-# DB Test 42 {access method}
-#
-# Multiprocess DB test; verify that locking is working for the concurrent
-# access method product.
-#
-# Use the first "nentries" words from the dictionary. Insert each with self
-# as key and a fixed, medium length data string. Then fire off multiple
-# processes that bang on the database. Each one should try to read and write
-# random keys. When they rewrite, they'll append their pid to the data string
-# (sometimes doing a rewrite sometimes doing a partial put). Some will use
-# cursors to traverse through a few keys before finding one to write.
-
-set datastr abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+# TEST test042
+# TEST Concurrent Data Store test (CDB)
+# TEST
+# TEST Multiprocess DB test; verify that locking is working for the
+# TEST concurrent access method product.
+# TEST
+# TEST Use the first "nentries" words from the dictionary. Insert each with
+# TEST self as key and a fixed, medium length data string. Then fire off
+# TEST multiple processes that bang on the database. Each one should try to
+# TEST read and write random keys. When they rewrite, they'll append their
+# TEST pid to the data string (sometimes doing a rewrite sometimes doing a
+# TEST partial put). Some will use cursors to traverse through a few keys
+# TEST before finding one to write.
proc test042 { method {nentries 1000} args } {
- global datastr
- source ./include.tcl
+ global encrypt
#
# If we are using an env, then skip this test. It needs its own.
@@ -32,10 +31,25 @@ proc test042 { method {nentries 1000} args } {
puts "Test042 skipping for env $env"
return
}
+
set args [convert_args $method $args]
- set omethod [convert_method $method]
+ if { $encrypt != 0 } {
+ puts "Test042 skipping for security"
+ return
+ }
+ test042_body $method $nentries 0 $args
+ test042_body $method $nentries 1 $args
+}
+
+proc test042_body { method nentries alldb args } {
+ source ./include.tcl
- puts "Test042: CDB Test $method $nentries"
+ if { $alldb } {
+ set eflag "-cdb -cdb_alldb"
+ } else {
+ set eflag "-cdb"
+ }
+ puts "Test042: CDB Test ($eflag) $method $nentries"
# Set initial parameters
set do_exit 0
@@ -62,44 +76,24 @@ proc test042 { method {nentries 1000} args } {
env_cleanup $testdir
- set env [berkdb env -create -cdb -home $testdir]
- error_check_good dbenv [is_valid_widget $env env] TRUE
-
- set db [eval {berkdb_open -env $env -create -truncate \
- -mode 0644 $omethod} $oargs {$testfile}]
- error_check_good dbopen [is_valid_widget $db db] TRUE
+ set env [eval {berkdb_env -create} $eflag -home $testdir]
+ error_check_good dbenv [is_valid_env $env] TRUE
- set did [open $dict]
-
- set pflags ""
- set gflags ""
- set txn ""
- set count 0
-
- # Here is the loop where we put each key/data pair
- puts "\tTest042.a: put/get loop"
- while { [gets $did str] != -1 && $count < $nentries } {
- if { [is_record_based $method] == 1 } {
- set key [expr $count + 1]
- } else {
- set key $str
+ # Env is created, now set up database
+ test042_dbinit $env $nentries $method $oargs $testfile 0
+ if { $alldb } {
+ for { set i 1 } {$i < $procs} {incr i} {
+ test042_dbinit $env $nentries $method $oargs \
+ $testfile $i
}
- set ret [eval {$db put} \
- $txn $pflags {$key [chop_data $method $datastr]}]
- error_check_good put:$db $ret 0
- incr count
}
- close $did
- error_check_good close:$db [$db close] 0
-
- # Database is created, now set up environment
# Remove old mpools and Open/create the lock and mpool regions
error_check_good env:close:$env [$env close] 0
set ret [berkdb envremove -home $testdir]
error_check_good env_remove $ret 0
- set env [berkdb env -create -cdb -home $testdir]
+ set env [eval {berkdb_env -create} $eflag -home $testdir]
error_check_good dbenv [is_valid_widget $env env] TRUE
if { $do_exit == 1 } {
@@ -112,16 +106,21 @@ proc test042 { method {nentries 1000} args } {
set pidlist {}
for { set i 0 } {$i < $procs} {incr i} {
+ if { $alldb } {
+ set tf $testfile$i
+ } else {
+ set tf ${testfile}0
+ }
puts "exec $tclsh_path $test_path/wrap.tcl \
mdbscript.tcl $testdir/test042.$i.log \
- $method $testdir $testfile $nentries $iter $i $procs &"
+ $method $testdir $tf $nentries $iter $i $procs &"
set p [exec $tclsh_path $test_path/wrap.tcl \
mdbscript.tcl $testdir/test042.$i.log $method \
- $testdir $testfile $nentries $iter $i $procs &]
+ $testdir $tf $nentries $iter $i $procs &]
lappend pidlist $p
}
puts "Test042: $procs independent processes now running"
- watch_procs
+ watch_procs $pidlist
# Check for test failure
set e [eval findfail [glob $testdir/test042.*.log]]
@@ -147,3 +146,36 @@ proc rand_key { method nkeys renum procs} {
return [berkdb random_int 0 [expr $nkeys - 1]]
}
}
+
+proc test042_dbinit { env nentries method oargs tf ext } {
+ global datastr
+ source ./include.tcl
+
+ set omethod [convert_method $method]
+ set db [eval {berkdb_open -env $env -create \
+ -mode 0644 $omethod} $oargs {$tf$ext}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set did [open $dict]
+
+ set pflags ""
+ set gflags ""
+ set txn ""
+ set count 0
+
+ # Here is the loop where we put each key/data pair
+ puts "\tTest042.a: put loop $tf$ext"
+ while { [gets $did str] != -1 && $count < $nentries } {
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ } else {
+ set key $str
+ }
+ set ret [eval {$db put} \
+ $txn $pflags {$key [chop_data $method $datastr]}]
+ error_check_good put:$db $ret 0
+ incr count
+ }
+ close $did
+ error_check_good close:$db [$db close] 0
+}
diff --git a/bdb/test/test043.tcl b/bdb/test/test043.tcl
index 274ec1b7184..eea7ec86d54 100644
--- a/bdb/test/test043.tcl
+++ b/bdb/test/test043.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test043.tcl,v 11.12 2000/08/25 14:21:56 sue Exp $
+# $Id: test043.tcl,v 11.17 2002/05/22 15:42:52 sue Exp $
#
-# DB Test 43 {method nentries}
-# Test the Record number implicit creation and renumbering options.
+# TEST test043
+# TEST Recno renumbering and implicit creation test
+# TEST Test the Record number implicit creation and renumbering options.
proc test043 { method {nentries 10000} args} {
source ./include.tcl
@@ -22,6 +23,7 @@ proc test043 { method {nentries 10000} args} {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -33,11 +35,23 @@ proc test043 { method {nentries 10000} args} {
set testfile test043.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
# Create the database
- set db [eval {berkdb_open -create -truncate -mode 0644} $args \
+ set db [eval {berkdb_open -create -mode 0644} $args \
{$omethod $testfile}]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -53,16 +67,29 @@ proc test043 { method {nentries 10000} args} {
}
puts "\tTest043.a: insert keys at $interval record intervals"
while { $count <= $nentries } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$count [chop_data $method $count]}]
error_check_good "$db put $count" $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set last $count
incr count $interval
}
puts "\tTest043.b: get keys using DB_FIRST/DB_NEXT"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
- error_check_good "$db cursor" [is_substr $dbc $db] 1
+ error_check_good "$db cursor" [is_valid_cursor $dbc $db] TRUE
set check 1
for { set rec [$dbc get -first] } { [llength $rec] != 0 } {
@@ -158,5 +185,8 @@ proc test043 { method {nentries 10000} args} {
}
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test044.tcl b/bdb/test/test044.tcl
index 0be7a704961..67cf3ea24b8 100644
--- a/bdb/test/test044.tcl
+++ b/bdb/test/test044.tcl
@@ -1,25 +1,31 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test044.tcl,v 11.26 2000/10/27 13:23:56 sue Exp $
+# $Id: test044.tcl,v 11.32 2002/07/16 20:53:04 bostic Exp $
#
-# DB Test 44 {access method}
-# System integration DB test: verify that locking, recovery, checkpoint,
-# and all the other utilities basically work.
+# TEST test044
+# TEST Small system integration tests
+# TEST Test proper functioning of the checkpoint daemon,
+# TEST recovery, transactions, etc.
+# TEST
+# TEST System integration DB test: verify that locking, recovery, checkpoint,
+# TEST and all the other utilities basically work.
+# TEST
+# TEST The test consists of $nprocs processes operating on $nfiles files. A
+# TEST transaction consists of adding the same key/data pair to some random
+# TEST number of these files. We generate a bimodal distribution in key size
+# TEST with 70% of the keys being small (1-10 characters) and the remaining
+# TEST 30% of the keys being large (uniform distribution about mean $key_avg).
+# TEST If we generate a key, we first check to make sure that the key is not
+# TEST already in the dataset. If it is, we do a lookup.
#
-# The test consists of $nprocs processes operating on $nfiles files. A
-# transaction consists of adding the same key/data pair to some random
-# number of these files. We generate a bimodal distribution in key
-# size with 70% of the keys being small (1-10 characters) and the
-# remaining 30% of the keys being large (uniform distribution about
-# mean $key_avg). If we generate a key, we first check to make sure
-# that the key is not already in the dataset. If it is, we do a lookup.
-#
-# XXX This test uses grow-only files currently!
+# XXX
+# This test uses grow-only files currently!
proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
source ./include.tcl
+ global encrypt
global rand_init
set args [convert_args $method $args]
@@ -35,6 +41,10 @@ proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
puts "Test044 skipping for env $env"
return
}
+ if { $encrypt != 0 } {
+ puts "Test044 skipping for security"
+ return
+ }
puts "Test044: system integration test db $method $nprocs processes \
on $nfiles files"
@@ -62,7 +72,7 @@ proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
# Create an environment
puts "\tTest044.a: creating environment and $nfiles files"
- set dbenv [berkdb env -create -txn -home $testdir]
+ set dbenv [berkdb_env -create -txn -home $testdir]
error_check_good env_open [is_valid_env $dbenv] TRUE
# Create a bunch of files
@@ -97,7 +107,7 @@ proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
set cycle 1
set ncycles 3
while { $cycle <= $ncycles } {
- set dbenv [berkdb env -create -txn -home $testdir]
+ set dbenv [berkdb_env -create -txn -home $testdir]
error_check_good env_open [is_valid_env $dbenv] TRUE
# Fire off deadlock detector and checkpointer
@@ -128,16 +138,13 @@ proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
#
error_check_good env_close [$dbenv close] 0
- exec $KILL -9 $ddpid
- exec $KILL -9 $cppid
- #
- # Use catch so that if any of the children died, we don't
- # stop the script
- #
+ tclkill $ddpid
+ tclkill $cppid
+
foreach p $pidlist {
- set e [catch {eval exec \
- [concat $KILL -9 $p]} res]
+ tclkill $p
}
+
# Check for test failure
set e [eval findfail [glob $testdir/test044.*.log]]
error_check_good "FAIL: error message(s) in log files" $e 0
diff --git a/bdb/test/test045.tcl b/bdb/test/test045.tcl
index 65f031d0290..3825135facd 100644
--- a/bdb/test/test045.tcl
+++ b/bdb/test/test045.tcl
@@ -1,11 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test045.tcl,v 11.17 2000/10/19 23:15:22 ubell Exp $
+# $Id: test045.tcl,v 11.24 2002/02/07 17:50:10 sue Exp $
+#
+# TEST test045
+# TEST Small random tester
+# TEST Runs a number of random add/delete/retrieve operations.
+# TEST Tests both successful conditions and error conditions.
+# TEST
+# TEST Run the random db tester on the specified access method.
#
-# DB Test 45 Run the random db tester on the specified access method.
# Options are:
# -adds <maximum number of keys before you disable adds>
# -cursors <number of cursors>
@@ -17,11 +23,7 @@
# -keyavg <average key size>
proc test045 { method {nops 10000} args } {
source ./include.tcl
-
- if { [is_frecno $method] == 1 } {
- puts "\tSkipping Test045 for method $method."
- return
- }
+ global encrypt
#
# If we are using an env, then skip this test. It needs its own.
@@ -33,6 +35,10 @@ proc test045 { method {nops 10000} args } {
return
}
set args [convert_args $method $args]
+ if { $encrypt != 0 } {
+ puts "Test045 skipping for security"
+ return
+ }
set omethod [convert_method $method]
puts "Test045: Random tester on $method for $nops operations"
@@ -63,7 +69,7 @@ proc test045 { method {nops 10000} args } {
-errpct { incr i; set errpct [lindex $args $i] }
-init { incr i; set init [lindex $args $i] }
-keyavg { incr i; set keyavg [lindex $args $i] }
- -extent { incr i;
+ -extent { incr i;
lappend oargs "-extent" "100" }
default { lappend oargs [lindex $args $i] }
}
@@ -77,7 +83,7 @@ proc test045 { method {nops 10000} args } {
# Run the script with 3 times the number of initial elements to
# set it up.
set db [eval {berkdb_open \
- -create -truncate -mode 0644 $omethod} $oargs {$f}]
+ -create -mode 0644 $omethod} $oargs {$f}]
error_check_good dbopen:$f [is_valid_db $db] TRUE
set r [$db close]
@@ -90,7 +96,7 @@ proc test045 { method {nops 10000} args } {
if { $init != 0 } {
set n [expr 3 * $init]
exec $tclsh_path \
- $test_path/dbscript.tcl $f $n \
+ $test_path/dbscript.tcl $method $f $n \
1 $init $n $keyavg $dataavg $dups 0 -1 \
> $testdir/test045.init
}
@@ -101,11 +107,11 @@ proc test045 { method {nops 10000} args } {
puts "\tTest045.b: Now firing off berkdb rand dbscript, running: "
# Now the database is initialized, run a test
puts "$tclsh_path\
- $test_path/dbscript.tcl $f $nops $cursors $delete $adds \
+ $test_path/dbscript.tcl $method $f $nops $cursors $delete $adds \
$keyavg $dataavg $dups $errpct > $testdir/test045.log"
exec $tclsh_path \
- $test_path/dbscript.tcl $f \
+ $test_path/dbscript.tcl $method $f \
$nops $cursors $delete $adds $keyavg \
$dataavg $dups $errpct \
> $testdir/test045.log
diff --git a/bdb/test/test046.tcl b/bdb/test/test046.tcl
index 3bfed3ef5d8..4136f30aaa7 100644
--- a/bdb/test/test046.tcl
+++ b/bdb/test/test046.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test046.tcl,v 11.26 2000/08/25 14:21:56 sue Exp $
+# $Id: test046.tcl,v 11.33 2002/05/24 15:24:55 sue Exp $
#
-# DB Test 46: Overwrite test of small/big key/data with cursor checks.
+# TEST test046
+# TEST Overwrite test of small/big key/data with cursor checks.
proc test046 { method args } {
global alphabet
global errorInfo
@@ -33,6 +34,7 @@ proc test046 { method args } {
}
puts "\tTest046: Create $method database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -44,6 +46,11 @@ proc test046 { method args } {
set testfile test046.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
@@ -52,28 +59,43 @@ proc test046 { method args } {
set db [eval {berkdb_open} $oflags $testfile.a]
error_check_good dbopen [is_valid_db $db] TRUE
- # open curs to db
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
-
# keep nkeys even
set nkeys 20
# Fill page w/ small key/data pairs
puts "\tTest046: Fill page with $nkeys small key/data pairs."
for { set i 1 } { $i <= $nkeys } { incr i } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
if { [is_record_based $method] == 1} {
- set ret [$db put $i $data$i]
+ set ret [eval {$db put} $txn {$i $data$i}]
} elseif { $i < 10 } {
- set ret [$db put [set key]00$i [set data]00$i]
+ set ret [eval {$db put} $txn [set key]00$i \
+ [set data]00$i]
} elseif { $i < 100 } {
- set ret [$db put [set key]0$i [set data]0$i]
+ set ret [eval {$db put} $txn [set key]0$i \
+ [set data]0$i]
} else {
- set ret [$db put $key$i $data$i]
+ set ret [eval {$db put} $txn {$key$i $data$i}]
}
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+ # open curs to db
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_substr $dbc $db] 1
+
# get db order of keys
for {set i 1; set ret [$dbc get -first]} { [llength $ret] != 0} { \
set ret [$dbc get -next]} {
@@ -92,7 +114,7 @@ proc test046 { method args } {
# delete before cursor(n-1), make sure it is gone
set i [expr $i - 1]
- error_check_good db_del [$db del $key_set($i)] 0
+ error_check_good db_del [eval {$db del} $txn {$key_set($i)}] 0
# use set_range to get first key starting at n-1, should
# give us nth--but only works for btree
@@ -120,7 +142,7 @@ proc test046 { method args } {
puts "\t\tTest046.a.2: Delete cursor item by key."
# nth key, which cursor should be on now
set i [incr i]
- set ret [$db del $key_set($i)]
+ set ret [eval {$db del} $txn {$key_set($i)}]
error_check_good db_del $ret 0
# this should return n+1 key/data, curr has nth key/data
@@ -155,7 +177,7 @@ proc test046 { method args } {
set ret [$dbc get -prev]
error_check_bad dbc_get:prev [llength $curr] 0
# delete *after* cursor pos.
- error_check_good db:del [$db del $key_set([incr i])] 0
+ error_check_good db:del [eval {$db del} $txn {$key_set([incr i])}] 0
# make sure item is gone, try to get it
if { [string compare $omethod "-btree"] == 0} {
@@ -211,12 +233,12 @@ proc test046 { method args } {
puts "\t\tTest046.c.1: Insert by key before the cursor."
# i is at curs pos, i=n+1, we want to go BEFORE
set i [incr i -1]
- set ret [$db put $key_set($i) $data_set($i)]
+ set ret [eval {$db put} $txn {$key_set($i) $data_set($i)}]
error_check_good db_put:before $ret 0
puts "\t\tTest046.c.2: Insert by key after the cursor."
set i [incr i +2]
- set ret [$db put $key_set($i) $data_set($i)]
+ set ret [eval {$db put} $txn {$key_set($i) $data_set($i)}]
error_check_good db_put:after $ret 0
puts "\t\tTest046.c.3: Insert by curs with deleted curs (should fail)."
@@ -224,6 +246,9 @@ proc test046 { method args } {
set i [incr i -1]
error_check_good dbc:close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db:close [$db close] 0
if { [is_record_based $method] == 1} {
puts "\t\tSkipping the rest of test for method $method."
@@ -233,7 +258,12 @@ proc test046 { method args } {
# Reopen without printing __db_errs.
set db [eval {berkdb_open_noerr} $oflags $testfile.a]
error_check_good dbopen [is_valid_db $db] TRUE
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good cursor [is_valid_cursor $dbc $db] TRUE
# should fail with EINVAL (deleted cursor)
@@ -254,7 +284,7 @@ proc test046 { method args } {
Insert by cursor before/after existent cursor."
# can't use before after w/o dup except renumber in recno
# first, restore an item so they don't fail
- #set ret [$db put $key_set($i) $data_set($i)]
+ #set ret [eval {$db put} $txn {$key_set($i) $data_set($i)}]
#error_check_good db_put $ret 0
#set ret [$dbc get -set $key_set($i)]
@@ -275,21 +305,37 @@ proc test046 { method args } {
# overwrites
puts "\tTest046.d.0: Cleanup, close db, open new db with no dups."
error_check_good dbc:close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db:close [$db close] 0
set db [eval {berkdb_open} $oflags $testfile.d]
error_check_good dbopen [is_valid_db $db] TRUE
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
- set nkeys 20
-
# Fill page w/ small key/data pairs
puts "\tTest046.d.0: Fill page with $nkeys small key/data pairs."
for { set i 1 } { $i < $nkeys } { incr i } {
- set ret [$db put $key$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i $data$i}]
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+ set nkeys 20
+
# Prepare cursor on item
set ret [$dbc get -first]
error_check_bad dbc_get:first [llength $ret] 0
@@ -347,14 +393,14 @@ proc test046 { method args } {
if { [string compare $type key_over] == 0 } {
puts "\t\tTest046.d.$i: Key\
Overwrite:($i_pair) by ($w_pair)."
- set ret [$db put \
+ set ret [eval {$db put} $txn \
$"key_init[lindex $i_pair 0]" \
$"data_over[lindex $w_pair 1]"]
error_check_good \
dbput:over:i($i_pair):o($w_pair) $ret 0
# check value
- set ret [$db \
- get $"key_init[lindex $i_pair 0]"]
+ set ret [eval {$db get} $txn \
+ $"key_init[lindex $i_pair 0]"]
error_check_bad \
db:get:check [llength $ret] 0
error_check_good db:get:compare_data \
@@ -382,6 +428,9 @@ proc test046 { method args } {
puts "\tTest046.d.3: Cleanup for next part of test."
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
if { [is_rbtree $method] == 1} {
@@ -394,10 +443,6 @@ proc test046 { method args } {
set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e]
error_check_good dbopen [is_valid_db $db] TRUE
- # open curs to db
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
-
# keep nkeys even
set nkeys 20
set ndups 20
@@ -406,14 +451,31 @@ proc test046 { method args } {
puts "\tTest046.e.2:\
Put $nkeys small key/data pairs and $ndups sorted dups."
for { set i 0 } { $i < $nkeys } { incr i } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
if { $i < 10 } {
- set ret [$db put [set key]0$i [set data]0$i]
+ set ret [eval {$db put} $txn [set key]0$i [set data]0$i]
} else {
- set ret [$db put $key$i $data$i]
+ set ret [eval {$db put} $txn {$key$i $data$i}]
}
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ # open curs to db
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_substr $dbc $db] 1
+
# get db order of keys
for {set i 0; set ret [$dbc get -first]} { [llength $ret] != 0} { \
set ret [$dbc get -next]} {
@@ -431,15 +493,15 @@ proc test046 { method args } {
for { set i 0 } { $i < $ndups } { incr i } {
if { $i < 10 } {
- set ret [$db put $keym DUPLICATE_0$i]
+ set ret [eval {$db put} $txn {$keym DUPLICATE_0$i}]
} else {
- set ret [$db put $keym DUPLICATE_$i]
+ set ret [eval {$db put} $txn {$keym DUPLICATE_$i}]
}
error_check_good db_put:DUP($i) $ret 0
}
puts "\tTest046.e.3: Check duplicate duplicates"
- set ret [$db put $keym DUPLICATE_00]
+ set ret [eval {$db put} $txn {$keym DUPLICATE_00}]
error_check_good dbput:dupdup [is_substr $ret "DB_KEYEXIST"] 1
# get dup ordering
@@ -479,11 +541,24 @@ proc test046 { method args } {
#error_check_good \
# dbc_get:current:deleted [is_substr $ret "DB_KEYEMPTY"] 1
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
# restore deleted keys
- error_check_good db_put:1 [$db put $keym $dup_set($i)] 0
- error_check_good db_put:2 [$db put $keym $dup_set([incr i])] 0
- error_check_good db_put:3 [$db put $keym $dup_set([incr i])] 0
+ error_check_good db_put:1 [eval {$db put} $txn {$keym $dup_set($i)}] 0
+ error_check_good db_put:2 [eval {$db put} $txn \
+ {$keym $dup_set([incr i])}] 0
+ error_check_good db_put:3 [eval {$db put} $txn \
+ {$keym $dup_set([incr i])}] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# tested above
@@ -491,7 +566,13 @@ proc test046 { method args } {
error_check_good dbclose [$db close] 0
set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e]
error_check_good dbopen [is_valid_db $db] TRUE
- error_check_good db_cursor [is_substr [set dbc [$db cursor]] $db] 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
set ret [$dbc get -set $keym]
error_check_bad dbc_get:set [llength $ret] 0
@@ -519,7 +600,7 @@ proc test046 { method args } {
set i 0
# use "spam" to prevent a duplicate duplicate.
- set ret [$db put $keym $dup_set($i)spam]
+ set ret [eval {$db put} $txn {$keym $dup_set($i)spam}]
error_check_good db_put:before $ret 0
# make sure cursor was maintained
set ret [$dbc get -current]
@@ -530,7 +611,7 @@ proc test046 { method args } {
puts "\t\tTest046.g.2: Insert by key after cursor."
set i [expr $i + 2]
# use "eggs" to prevent a duplicate duplicate
- set ret [$db put $keym $dup_set($i)eggs]
+ set ret [eval {$db put} $txn {$keym $dup_set($i)eggs}]
error_check_good db_put:after $ret 0
# make sure cursor was maintained
set ret [$dbc get -current]
@@ -559,19 +640,29 @@ proc test046 { method args } {
puts "\t\tTest046.h.2: New db (no dupsort)."
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
- set db [berkdb_open \
- -create -dup $omethod -mode 0644 -truncate $testfile.h]
+ set db [eval {berkdb_open} \
+ $oflags -dup $testfile.h]
error_check_good db_open [is_valid_db $db] TRUE
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
for {set i 0} {$i < $nkeys} {incr i} {
if { $i < 10 } {
- error_check_good db_put [$db put key0$i datum0$i] 0
+ set ret [eval {$db put} $txn {key0$i datum0$i}]
+ error_check_good db_put $ret 0
} else {
- error_check_good db_put [$db put key$i datum$i] 0
+ set ret [eval {$db put} $txn {key$i datum$i}]
+ error_check_good db_put $ret 0
}
if { $i == 0 } {
for {set j 0} {$j < $ndups} {incr j} {
@@ -581,9 +672,11 @@ proc test046 { method args } {
set keyput key$i
}
if { $j < 10 } {
- set ret [$db put $keyput DUP_datum0$j]
+ set ret [eval {$db put} $txn \
+ {$keyput DUP_datum0$j}]
} else {
- set ret [$db put $keyput DUP_datum$j]
+ set ret [eval {$db put} $txn \
+ {$keyput DUP_datum$j}]
}
error_check_good dbput:dup $ret 0
}
@@ -711,6 +804,9 @@ proc test046 { method args } {
puts "\tTest046.i: Cleaning up from test."
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest046 complete."
diff --git a/bdb/test/test047.tcl b/bdb/test/test047.tcl
index 9d11cd3db83..61c1d0864c5 100644
--- a/bdb/test/test047.tcl
+++ b/bdb/test/test047.tcl
@@ -1,15 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test047.tcl,v 11.10 2000/08/25 14:21:56 sue Exp $
+# $Id: test047.tcl,v 11.19 2002/08/05 19:23:51 sandstro Exp $
#
-# DB Test 47: test of the SET_RANGE interface to DB->c_get.
+# TEST test047
+# TEST DBcursor->c_get get test with SET_RANGE option.
proc test047 { method args } {
source ./include.tcl
set tstn 047
+ set args [convert_args $method $args]
if { [is_btree $method] != 1 } {
puts "Test$tstn skipping for method $method"
@@ -27,6 +29,7 @@ proc test047 { method args } {
puts "\tTest$tstn.a: Create $method database."
set eindex [lsearch -exact $args "-env"]
+ set txnenv 0
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
@@ -41,27 +44,45 @@ proc test047 { method args } {
set testfile2 test0$tstn.b.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
- set oflags "-create -truncate -mode 0644 -dup $args $method"
+ set oflags "-create -mode 0644 -dup $args $method"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
- # open curs to db
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
-
set nkeys 20
# Fill page w/ small key/data pairs
#
puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
for { set i 0 } { $i < $nkeys } { incr i } {
- set ret [$db put $key$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i $data$i}]
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ # open curs to db
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+
puts "\tTest$tstn.c: Get data with SET_RANGE, then delete by cursor."
set i 0
set ret [$dbc get -set_range $key$i]
@@ -77,13 +98,14 @@ proc test047 { method args } {
puts "\tTest$tstn.d: \
Use another cursor to fix item on page, delete by db."
- set dbcurs2 [$db cursor]
- error_check_good db:cursor2 [is_substr $dbcurs2 $db] 1
+ set dbcurs2 [eval {$db cursor} $txn]
+ error_check_good db:cursor2 [is_valid_cursor $dbcurs2 $db] TRUE
set ret [$dbcurs2 get -set [lindex [lindex $ret 0] 0]]
error_check_bad dbc_get(2):set [llength $ret] 0
set curr $ret
- error_check_good db:del [$db del [lindex [lindex $ret 0] 0]] 0
+ error_check_good db:del [eval {$db del} $txn \
+ {[lindex [lindex $ret 0] 0]}] 0
# make sure item is gone
set ret [$dbcurs2 get -set_range [lindex [lindex $curr 0] 0]]
@@ -93,6 +115,9 @@ proc test047 { method args } {
puts "\tTest$tstn.e: Close for second part of test, close db/cursors."
error_check_good dbc:close [$dbc close] 0
error_check_good dbc2:close [$dbcurs2 close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good dbclose [$db close] 0
# open db
@@ -103,27 +128,48 @@ proc test047 { method args } {
puts "\tTest$tstn.f: Fill page with $nkeys pairs, one set of dups."
for {set i 0} { $i < $nkeys } {incr i} {
# a pair
- set ret [$db put $key$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i $data$i}]
error_check_good dbput($i) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
set j 0
for {set i 0} { $i < $nkeys } {incr i} {
# a dup set for same 1 key
- set ret [$db put $key$i DUP_$data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i DUP_$data$i}]
error_check_good dbput($i):dup $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
puts "\tTest$tstn.g: \
Get dups key w/ SET_RANGE, pin onpage with another cursor."
set i 0
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
set ret [$dbc get -set_range $key$i]
error_check_bad dbc_get:set_range [llength $ret] 0
- set dbc2 [$db cursor]
- error_check_good db_cursor2 [is_substr $dbc2 $db] 1
+ set dbc2 [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc2 $db] TRUE
set ret2 [$dbc2 get -set_range $key$i]
error_check_bad dbc2_get:set_range [llength $ret] 0
@@ -138,14 +184,13 @@ proc test047 { method args } {
error_check_good dbc_close [$dbc close] 0
error_check_good dbc2_close [$dbc2 close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
set db [eval {berkdb_open} $oflags $testfile2]
error_check_good dbopen [is_valid_db $db] TRUE
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
- set dbc2 [$db cursor]
- error_check_good db_cursor2 [is_substr $dbc2 $db] 1
set nkeys 10
set ndups 1000
@@ -153,18 +198,36 @@ proc test047 { method args } {
puts "\tTest$tstn.i: Fill page with $nkeys pairs and $ndups dups."
for {set i 0} { $i < $nkeys } { incr i} {
# a pair
- set ret [$db put $key$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i $data$i}]
error_check_good dbput $ret 0
# dups for single pair
if { $i == 0} {
for {set j 0} { $j < $ndups } { incr j } {
- set ret [$db put $key$i DUP_$data$i:$j]
+ set ret [eval {$db put} $txn \
+ {$key$i DUP_$data$i:$j}]
error_check_good dbput:dup $ret 0
}
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
set i 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+ set dbc2 [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc2 $db] TRUE
puts "\tTest$tstn.j: \
Get key of first dup with SET_RANGE, fix with 2 curs."
set ret [$dbc get -set_range $key$i]
@@ -186,6 +249,9 @@ proc test047 { method args } {
puts "\tTest$tstn.l: Cleanup."
error_check_good dbc_close [$dbc close] 0
error_check_good dbc2_close [$dbc2 close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest$tstn complete."
diff --git a/bdb/test/test048.tcl b/bdb/test/test048.tcl
index 84c7c47b721..2131f6f553c 100644
--- a/bdb/test/test048.tcl
+++ b/bdb/test/test048.tcl
@@ -1,16 +1,18 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test048.tcl,v 11.11 2000/12/11 17:42:18 sue Exp $
+# $Id: test048.tcl,v 11.18 2002/07/29 20:27:49 sandstro Exp $
#
-# Test048: Cursor stability across btree splits.
+# TEST test048
+# TEST Cursor stability across Btree splits.
proc test048 { method args } {
global errorCode
source ./include.tcl
set tstn 048
+ set args [convert_args $method $args]
if { [is_btree $method] != 1 } {
puts "Test$tstn skipping for method $method."
@@ -35,6 +37,7 @@ proc test048 { method args } {
set flags ""
puts "\tTest$tstn.a: Create $method database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -46,11 +49,16 @@ proc test048 { method args } {
set testfile test0$tstn.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
- set oflags "-create -truncate -mode 0644 $args $method"
+ set oflags "-create -mode 0644 $args $method"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -59,20 +67,34 @@ proc test048 { method args } {
#
puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
for { set i 0 } { $i < $nkeys } { incr i } {
- set ret [$db put key000$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {key000$i $data$i}]
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# get db ordering, set cursors
puts "\tTest$tstn.c: Set cursors on each of $nkeys pairs."
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
for {set i 0; set ret [$db get key000$i]} {\
$i < $nkeys && [llength $ret] != 0} {\
incr i; set ret [$db get key000$i]} {
set key_set($i) [lindex [lindex $ret 0] 0]
set data_set($i) [lindex [lindex $ret 0] 1]
- set dbc [$db cursor]
+ set dbc [eval {$db cursor} $txn]
set dbc_set($i) $dbc
- error_check_good db_cursor:$i [is_substr $dbc_set($i) $db] 1
+ error_check_good db_cursor:$i \
+ [is_valid_cursor $dbc_set($i) $db] TRUE
set ret [$dbc_set($i) get -set $key_set($i)]
error_check_bad dbc_set($i)_get:set [llength $ret] 0
}
@@ -82,18 +104,21 @@ proc test048 { method args } {
puts "\tTest$tstn.d: Add $mkeys pairs to force split."
for {set i $nkeys} { $i < $mkeys } { incr i } {
if { $i >= 100 } {
- set ret [$db put key0$i $data$i]
+ set ret [eval {$db put} $txn {key0$i $data$i}]
} elseif { $i >= 10 } {
- set ret [$db put key00$i $data$i]
+ set ret [eval {$db put} $txn {key00$i $data$i}]
} else {
- set ret [$db put key000$i $data$i]
+ set ret [eval {$db put} $txn {key000$i $data$i}]
}
error_check_good dbput:more $ret 0
}
puts "\tTest$tstn.e: Make sure split happened."
- error_check_bad stat:check-split [is_substr [$db stat] \
+ # XXX We cannot call stat with active txns or we deadlock.
+ if { $txnenv != 1 } {
+ error_check_bad stat:check-split [is_substr [$db stat] \
"{{Internal pages} 0}"] 1
+ }
puts "\tTest$tstn.f: Check to see that cursors maintained reference."
for {set i 0} { $i < $nkeys } {incr i} {
@@ -107,19 +132,18 @@ proc test048 { method args } {
puts "\tTest$tstn.g: Delete added keys to force reverse split."
for {set i $nkeys} { $i < $mkeys } { incr i } {
if { $i >= 100 } {
- error_check_good db_del:$i [$db del key0$i] 0
+ error_check_good db_del:$i \
+ [eval {$db del} $txn {key0$i}] 0
} elseif { $i >= 10 } {
- error_check_good db_del:$i [$db del key00$i] 0
+ error_check_good db_del:$i \
+ [eval {$db del} $txn {key00$i}] 0
} else {
- error_check_good db_del:$i [$db del key000$i] 0
+ error_check_good db_del:$i \
+ [eval {$db del} $txn {key000$i}] 0
}
}
- puts "\tTest$tstn.h: Verify reverse split."
- error_check_good stat:check-reverse_split [is_substr [$db stat] \
- "{{Internal pages} 0}"] 1
-
- puts "\tTest$tstn.i: Verify cursor reference."
+ puts "\tTest$tstn.h: Verify cursor reference."
for {set i 0} { $i < $nkeys } {incr i} {
set ret [$dbc_set($i) get -current]
error_check_bad dbc$i:get:current [llength $ret] 0
@@ -128,11 +152,18 @@ proc test048 { method args } {
error_check_good dbc$i:get(match) $ret $ret2
}
- puts "\tTest$tstn.j: Cleanup."
+ puts "\tTest$tstn.i: Cleanup."
# close cursors
for {set i 0} { $i < $nkeys } {incr i} {
error_check_good dbc_close:$i [$dbc_set($i) close] 0
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ puts "\tTest$tstn.j: Verify reverse split."
+ error_check_good stat:check-reverse_split [is_substr [$db stat] \
+ "{{Internal pages} 0}"] 1
+
error_check_good dbclose [$db close] 0
puts "\tTest$tstn complete."
diff --git a/bdb/test/test049.tcl b/bdb/test/test049.tcl
index aaea3b200bf..3040727c469 100644
--- a/bdb/test/test049.tcl
+++ b/bdb/test/test049.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test049.tcl,v 11.15 2000/08/25 14:21:56 sue Exp $
+# $Id: test049.tcl,v 11.21 2002/05/22 15:42:53 sue Exp $
#
-# Test 049: Test of each cursor routine with unitialized cursors
+# TEST test049
+# TEST Cursor operations on uninitialized cursors.
proc test049 { method args } {
global errorInfo
global errorCode
@@ -17,7 +18,7 @@ proc test049 { method args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- puts "\tTest$tstn: Test of cursor routines with unitialized cursors."
+ puts "\tTest$tstn: Test of cursor routines with uninitialized cursors."
set key "key"
set data "data"
@@ -30,6 +31,7 @@ proc test049 { method args } {
}
puts "\tTest$tstn.a: Create $method database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -41,34 +43,53 @@ proc test049 { method args } {
set testfile test0$tstn.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
- set oflags "-create -truncate -mode 0644 $rflags $omethod $args"
+ set oflags "-create -mode 0644 $rflags $omethod $args"
if { [is_record_based $method] == 0 && [is_rbtree $method] != 1 } {
append oflags " -dup"
}
set db [eval {berkdb_open_noerr} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
- set dbc_u [$db cursor]
- error_check_good db:cursor [is_substr $dbc_u $db] 1
-
set nkeys 10
puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
for { set i 1 } { $i <= $nkeys } { incr i } {
- set ret [$db put $key$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i $data$i}]
error_check_good dbput:$i $ret 0
if { $i == 1 } {
for {set j 0} { $j < [expr $nkeys / 2]} {incr j} {
- set ret [$db put $key$i DUPLICATE$j]
+ set ret [eval {$db put} $txn \
+ {$key$i DUPLICATE$j}]
error_check_good dbput:dup:$j $ret 0
}
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# DBC GET
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc_u [eval {$db cursor} $txn]
+ error_check_good db:cursor [is_valid_cursor $dbc_u $db] TRUE
+
puts "\tTest$tstn.c: Test dbc->get interfaces..."
set i 0
foreach flag { current first last next prev nextdup} {
@@ -112,7 +133,7 @@ proc test049 { method args } {
# now uninitialize cursor
error_check_good dbc_close [$dbc_u close] 0
- set dbc_u [$db cursor]
+ set dbc_u [eval {$db cursor} $txn]
error_check_good \
db_cursor [is_substr $dbc_u $db] 1
}
@@ -154,6 +175,9 @@ proc test049 { method args } {
error_check_good dbc_del [is_substr $errorCode EINVAL] 1
error_check_good dbc_close [$dbc_u close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest$tstn complete."
diff --git a/bdb/test/test050.tcl b/bdb/test/test050.tcl
index 4a2d8c8fdc0..dfaeddd035c 100644
--- a/bdb/test/test050.tcl
+++ b/bdb/test/test050.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test050.tcl,v 11.15 2000/08/25 14:21:57 sue Exp $
+# $Id: test050.tcl,v 11.21 2002/05/24 14:15:13 bostic Exp $
#
-# Test050: Overwrite test of small/big key/data with cursor checks for RECNO
+# TEST test050
+# TEST Overwrite test of small/big key/data with cursor checks for Recno.
proc test050 { method args } {
global alphabet
global errorInfo
@@ -30,6 +31,7 @@ proc test050 { method args } {
set flags ""
puts "\tTest$tstn: Create $method database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -41,18 +43,19 @@ proc test050 { method args } {
set testfile test0$tstn.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
- set oflags "-create -truncate -mode 0644 $args $omethod"
+ set oflags "-create -mode 0644 $args $omethod"
set db [eval {berkdb_open_noerr} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
- # open curs to db
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
-
# keep nkeys even
set nkeys 20
@@ -60,9 +63,26 @@ proc test050 { method args } {
#
puts "\tTest$tstn: Fill page with $nkeys small key/data pairs."
for { set i 1 } { $i <= $nkeys } { incr i } {
- set ret [$db put $i [chop_data $method $data$i]]
- error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$i [chop_data $method $data$i]}]
+ error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ }
+
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
}
+ # open curs to db
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
# get db order of keys
for {set i 0; set ret [$dbc get -first]} { [llength $ret] != 0} { \
@@ -83,8 +103,16 @@ proc test050 { method args } {
puts "\t\tTest$tstn.a.1:\
Insert with uninitialized cursor (should fail)."
error_check_good dbc_close [$dbc close] 0
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
catch {$dbc put -before DATA1} ret
error_check_good dbc_put:before:uninit [is_substr $errorCode EINVAL] 1
@@ -169,8 +197,8 @@ proc test050 { method args } {
if { [string compare $type by_key] == 0 } {
puts "\t\tTest$tstn.b.$i:\
Overwrite:($pair):$type"
- set ret [$db put \
- 1 OVER$pair$data[lindex $pair 1]]
+ set ret [eval {$db put} $txn \
+ 1 {OVER$pair$data[lindex $pair 1]}]
error_check_good dbput:over:($pair) $ret 0
} else {
# This is a cursor overwrite
@@ -185,7 +213,9 @@ proc test050 { method args } {
puts "\tTest$tstn.c: Cleanup and close cursor."
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
- puts "\tTest$tstn complete."
}
diff --git a/bdb/test/test051.tcl b/bdb/test/test051.tcl
index 6994526e214..830b7630788 100644
--- a/bdb/test/test051.tcl
+++ b/bdb/test/test051.tcl
@@ -1,17 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test051.tcl,v 11.14 2000/08/25 14:21:57 sue Exp $
-#
-# Test51:
-# Test of the fixed recno method.
-# 0. Test various flags (legal and illegal) to open
-# 1. Test partial puts where dlen != size (should fail)
-# 2. Partial puts for existent record -- replaces at beg, mid, and
-# end of record, as well as full replace
+# $Id: test051.tcl,v 11.21 2002/05/24 13:43:24 sue Exp $
#
+# TEST test051
+# TEST Fixed-length record Recno test.
+# TEST 0. Test various flags (legal and illegal) to open
+# TEST 1. Test partial puts where dlen != size (should fail)
+# TEST 2. Partial puts for existent record -- replaces at beg, mid, and
+# TEST end of record, as well as full replace
proc test051 { method { args "" } } {
global fixed_len
global errorInfo
@@ -28,6 +27,7 @@ proc test051 { method { args "" } } {
}
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -41,19 +41,23 @@ proc test051 { method { args "" } } {
set testfile1 test051a.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
- set oflags "-create -truncate -mode 0644 $args"
+ set oflags "-create -mode 0644 $args"
# Test various flags (legal and illegal) to open
puts "\tTest051.a: Test correct flag behavior on open."
set errorCode NONE
foreach f { "-dup" "-dup -dupsort" "-recnum" } {
puts "\t\tTest051.a: Test flag $f"
- error_check_good dbopen:flagtest:catch \
- [catch {set db \
- [eval {berkdb_open_noerr} $oflags $f $omethod \
- $testfile]} ret] 1
+ set stat [catch {eval {berkdb_open_noerr} $oflags $f $omethod \
+ $testfile} ret]
+ error_check_good dbopen:flagtest:catch $stat 1
error_check_good \
dbopen:flagtest:$f [is_substr $errorCode EINVAL] 1
set errorCode NONE
@@ -66,24 +70,28 @@ proc test051 { method { args "" } } {
$db close
} else {
error_check_good \
- dbopen:flagtest:catch [catch {set db [eval \
- {berkdb_open_noerr} $oflags $f \
- $omethod $testfile]} ret] 1
+ dbopen:flagtest:catch [catch {eval {berkdb_open_noerr}\
+ $oflags $f $omethod $testfile} ret] 1
error_check_good \
dbopen:flagtest:$f [is_substr $errorCode EINVAL] 1
}
-
# Test partial puts where dlen != size (should fail)
# it is an error to specify a partial put w/ different
# dlen and size in fixed length recno/queue
set key 1
set data ""
+ set txn ""
set test_char "a"
set db [eval {berkdb_open_noerr} $oflags $omethod $testfile1]
error_check_good dbopen [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
puts "\tTest051.b: Partial puts with dlen != size."
foreach dlen { 1 16 20 32 } {
foreach doff { 0 10 20 32 } {
@@ -91,8 +99,8 @@ proc test051 { method { args "" } } {
puts "\t\tTest051.e: dlen: $dlen, doff: $doff, \
size: [expr $dlen+1]"
set data [repeat $test_char [expr $dlen + 1]]
- error_check_good catch:put 1 [catch {$db \
- put -partial [list $doff $dlen] $key $data} ret]
+ error_check_good catch:put 1 [catch {eval {$db put -partial \
+ [list $doff $dlen]} $txn {$key $data}} ret]
#
# We don't get back the server error string just
# the result.
@@ -109,8 +117,8 @@ proc test051 { method { args "" } } {
puts "\t\tTest051.e: dlen: $dlen, doff: $doff, \
size: [expr $dlen-1]"
set data [repeat $test_char [expr $dlen - 1]]
- error_check_good catch:put 1 [catch {$db \
- put -partial [list $doff $dlen] $key $data} ret]
+ error_check_good catch:put 1 [catch {eval {$db put -partial \
+ [list $doff $dlen]} $txn {$key $data}} ret]
if { $eindex == -1 } {
error_check_good "dbput:partial: dlen > size" \
[is_substr $errorInfo "Length improper"] 1
@@ -121,6 +129,9 @@ proc test051 { method { args "" } } {
}
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
$db close
# Partial puts for existent record -- replaces at beg, mid, and
@@ -132,14 +143,24 @@ proc test051 { method { args "" } } {
puts "\t\tTest051.f: First try a put and then a full replace."
set data [repeat "a" $fixed_len]
- set ret [$db put 1 $data]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {1 $data}]
error_check_good dbput $ret 0
- error_check_good dbget $data [lindex [lindex [$db get -recno 1] 0] 1]
+ set ret [eval {$db get} $txn {-recno 1}]
+ error_check_good dbget $data [lindex [lindex $ret 0] 1]
set data [repeat "b" $fixed_len]
- set ret [$db put -partial [list 0 $fixed_len] 1 $data]
+ set ret [eval {$db put -partial [list 0 $fixed_len]} $txn {1 $data}]
error_check_good dbput $ret 0
- error_check_good dbget $data [lindex [lindex [$db get -recno 1] 0] 1]
+ set ret [eval {$db get} $txn {-recno 1}]
+ error_check_good dbget $data [lindex [lindex $ret 0] 1]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set data "InitialData"
set pdata "PUT"
@@ -154,12 +175,21 @@ proc test051 { method { args "" } } {
puts "\t\tTest051.g: Now replace at different offsets ($offlist)."
foreach doff $offlist {
incr key
- set ret [$db put $key $data]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key $data}]
error_check_good dbput:init $ret 0
puts "\t\t Test051.g: Replace at offset $doff."
- set ret [$db put -partial [list $doff $dlen] $key $pdata]
+ set ret [eval {$db put -partial [list $doff $dlen]} $txn \
+ {$key $pdata}]
error_check_good dbput:partial $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
if { $doff == 0} {
set beg ""
@@ -186,6 +216,4 @@ proc test051 { method { args "" } } {
}
$db close
-
- puts "\tTest051 complete."
}
diff --git a/bdb/test/test052.tcl b/bdb/test/test052.tcl
index 820c99a2bd5..1f386449630 100644
--- a/bdb/test/test052.tcl
+++ b/bdb/test/test052.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test052.tcl,v 11.10 2000/10/06 19:29:52 krinsky Exp $
+# $Id: test052.tcl,v 11.16 2002/07/08 20:48:58 sandstro Exp $
#
-# Test52
-# Renumbering recno test.
+# TEST test052
+# TEST Renumbering record Recno test.
proc test052 { method args } {
global alphabet
global errorInfo
@@ -27,6 +27,7 @@ proc test052 { method args } {
set flags ""
puts "\tTest052: Create $method database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -38,27 +39,45 @@ proc test052 { method args } {
set testfile test052.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
- set oflags "-create -truncate -mode 0644 $args $omethod"
+ set oflags "-create -mode 0644 $args $omethod"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
- # open curs to db
- set dbc [$db cursor]
- error_check_good db_cursor [is_substr $dbc $db] 1
-
# keep nkeys even
set nkeys 20
# Fill page w/ small key/data pairs
puts "\tTest052: Fill page with $nkeys small key/data pairs."
for { set i 1 } { $i <= $nkeys } { incr i } {
- set ret [$db put $i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$i $data$i}]
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ }
+
+ # open curs to db
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
}
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
# get db order of keys
for {set i 1; set ret [$dbc get -first]} { [llength $ret] != 0} { \
@@ -79,7 +98,7 @@ proc test052 { method args } {
# delete by key before current
set i [incr i -1]
- error_check_good db_del:before [$db del $keys($i)] 0
+ error_check_good db_del:before [eval {$db del} $txn {$keys($i)}] 0
# with renumber, current's data should be constant, but key==--key
set i [incr i +1]
error_check_good dbc:data \
@@ -94,7 +113,7 @@ proc test052 { method args } {
error_check_bad dbc:get [llength $ret] 0
error_check_good dbc:get:curs [lindex [lindex $ret 0] 1] \
$darray([expr $i + 1])
- error_check_good db_del:curr [$db del $keys($i)] 0
+ error_check_good db_del:curr [eval {$db del} $txn {$keys($i)}] 0
set ret [$dbc get -current]
# After a delete, cursor should return DB_NOTFOUND.
@@ -114,7 +133,7 @@ proc test052 { method args } {
# should be { keys($nkeys/2), darray($nkeys/2 + 2) }
set i [expr $nkeys/2]
# deleting data for key after current (key $nkeys/2 + 1)
- error_check_good db_del [$db del $keys([expr $i + 1])] 0
+ error_check_good db_del [eval {$db del} $txn {$keys([expr $i + 1])}] 0
# current should be constant
set ret [$dbc get -current]
@@ -248,6 +267,9 @@ proc test052 { method args } {
$ret [list [list $keys($i) $darray($i)]]
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest052 complete."
diff --git a/bdb/test/test053.tcl b/bdb/test/test053.tcl
index e3a908c90d8..3e217a2b55f 100644
--- a/bdb/test/test053.tcl
+++ b/bdb/test/test053.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test053.tcl,v 11.12 2000/12/11 17:24:55 sue Exp $
+# $Id: test053.tcl,v 11.18 2002/05/24 15:24:55 sue Exp $
#
-# Test53: test of the DB_REVSPLITOFF flag in the btree and
-# Btree-w-recnum methods
+# TEST test053
+# TEST Test of the DB_REVSPLITOFF flag in the Btree and Btree-w-recnum
+# TEST methods.
proc test053 { method args } {
global alphabet
global errorCode
@@ -31,6 +32,7 @@ proc test053 { method args } {
set flags ""
puts "\tTest053.a: Create $omethod $args database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -42,12 +44,17 @@ proc test053 { method args } {
set testfile test053.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
set oflags \
- "-create -truncate -revsplitoff -pagesize 1024 $args $omethod"
+ "-create -revsplitoff -pagesize 1024 $args $omethod"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -77,8 +84,16 @@ proc test053 { method args } {
} else {
set key $keyroot$j
}
- set ret [$db put $key $data]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key $data}]
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
}
@@ -89,16 +104,29 @@ proc test053 { method args } {
puts "\tTest053.d: Delete all but one key per page."
for {set i 0} { $i < $npages } {incr i } {
for {set j 1} { $j < $nkeys } {incr j } {
- set ret [$db del $key_set($i)0$j]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db del} $txn {$key_set($i)0$j}]
error_check_good dbdel $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
}
puts "\tTest053.e: Check to make sure all pages are still there."
error_check_good page_count:check \
[is_substr [$db stat] "{Leaf pages} $npages"] 1
- set dbc [$db cursor]
- error_check_good db:cursor [is_substr $dbc $db] 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db:cursor [is_valid_cursor $dbc $db] TRUE
# walk cursor through tree forward, backward.
# delete one key, repeat
@@ -125,7 +153,7 @@ proc test053 { method args } {
puts "\t\tTest053.f.$i:\
Walk through tree with record numbers."
for {set j 1} {$j <= [expr $npages - $i]} {incr j} {
- set curr [$db get -recno $j]
+ set curr [eval {$db get} $txn {-recno $j}]
error_check_bad \
db_get:recno:$j [llength $curr] 0
error_check_good db_get:recno:keys:$j \
@@ -135,10 +163,10 @@ proc test053 { method args } {
}
puts "\tTest053.g.$i:\
Delete single key ([expr $npages - $i] keys left)."
- set ret [$db del $key_set($i)00]
+ set ret [eval {$db del} $txn {$key_set($i)00}]
error_check_good dbdel $ret 0
error_check_good del:check \
- [llength [$db get $key_set($i)00]] 0
+ [llength [eval {$db get} $txn {$key_set($i)00}]] 0
}
# end for loop, verify db_notfound
@@ -149,7 +177,7 @@ proc test053 { method args } {
for {set i 0} { $i < $npages} {incr i} {
puts "\tTest053.i.$i:\
Restore single key ([expr $i + 1] keys in tree)."
- set ret [$db put $key_set($i)00 $data]
+ set ret [eval {$db put} $txn {$key_set($i)00 $data}]
error_check_good dbput $ret 0
puts -nonewline \
@@ -177,7 +205,7 @@ proc test053 { method args } {
puts "\t\tTest053.k.$i:\
Walk through tree with record numbers."
for {set j 1} {$j <= [expr $i + 1]} {incr j} {
- set curr [$db get -recno $j]
+ set curr [eval {$db get} $txn {-recno $j}]
error_check_bad \
db_get:recno:$j [llength $curr] 0
error_check_good db_get:recno:keys:$j \
@@ -188,6 +216,9 @@ proc test053 { method args } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "Test053 complete."
diff --git a/bdb/test/test054.tcl b/bdb/test/test054.tcl
index 7308f995645..f53f5a658bf 100644
--- a/bdb/test/test054.tcl
+++ b/bdb/test/test054.tcl
@@ -1,32 +1,32 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test054.tcl,v 11.15 2000/08/25 14:21:57 sue Exp $
+# $Id: test054.tcl,v 11.23 2002/06/17 18:41:29 sue Exp $
#
-# Test054:
-#
-# This test checks for cursor maintenance in the presence of deletes.
-# There are N different scenarios to tests:
-# 1. No duplicates. Cursor A deletes a key, do a GET for the key.
-# 2. No duplicates. Cursor is positioned right before key K, Delete K,
-# do a next on the cursor.
-# 3. No duplicates. Cursor is positioned on key K, do a regular delete of K.
-# do a current get on K.
-# 4. Repeat 3 but do a next instead of current.
-#
-# 5. Duplicates. Cursor A is on the first item of a duplicate set, A
-# does a delete. Then we do a non-cursor get.
-# 6. Duplicates. Cursor A is in a duplicate set and deletes the item.
-# do a delete of the entire Key. Test cursor current.
-# 7. Continue last test and try cursor next.
-# 8. Duplicates. Cursor A is in a duplicate set and deletes the item.
-# Cursor B is in the same duplicate set and deletes a different item.
-# Verify that the cursor is in the right place.
-# 9. Cursors A and B are in the place in the same duplicate set. A deletes
-# its item. Do current on B.
-# 10. Continue 8 and do a next on B.
+# TEST test054
+# TEST Cursor maintenance during key/data deletion.
+# TEST
+# TEST This test checks for cursor maintenance in the presence of deletes.
+# TEST There are N different scenarios to tests:
+# TEST 1. No duplicates. Cursor A deletes a key, do a GET for the key.
+# TEST 2. No duplicates. Cursor is positioned right before key K, Delete K,
+# TEST do a next on the cursor.
+# TEST 3. No duplicates. Cursor is positioned on key K, do a regular delete
+# TEST of K, do a current get on K.
+# TEST 4. Repeat 3 but do a next instead of current.
+# TEST 5. Duplicates. Cursor A is on the first item of a duplicate set, A
+# TEST does a delete. Then we do a non-cursor get.
+# TEST 6. Duplicates. Cursor A is in a duplicate set and deletes the item.
+# TEST do a delete of the entire Key. Test cursor current.
+# TEST 7. Continue last test and try cursor next.
+# TEST 8. Duplicates. Cursor A is in a duplicate set and deletes the item.
+# TEST Cursor B is in the same duplicate set and deletes a different item.
+# TEST Verify that the cursor is in the right place.
+# TEST 9. Cursors A and B are in the place in the same duplicate set. A
+# TEST deletes its item. Do current on B.
+# TEST 10. Continue 8 and do a next on B.
proc test054 { method args } {
global errorInfo
source ./include.tcl
@@ -34,7 +34,7 @@ proc test054 { method args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- append args " -create -truncate -mode 0644"
+ append args " -create -mode 0644"
puts "Test054 ($method $args):\
interspersed cursor and normal operations"
if { [is_record_based $method] == 1 } {
@@ -42,18 +42,29 @@ proc test054 { method args } {
return
}
- # Create the database and open the dictionary
+ # Find the environment in the argument list, we'll need it
+ # later.
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ }
+
+ # Create the database and open the dictionary
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
if { $eindex == -1 } {
- set testfile $testdir/test054.db
+ set testfile $testdir/test054-nodup.db
set env NULL
} else {
- set testfile test054.db
- incr eindex
+ set testfile test054-nodup.db
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -64,15 +75,28 @@ proc test054 { method args } {
set db [eval {berkdb_open} $args {$omethod $testfile}]
error_check_good db_open:nodup [is_valid_db $db] TRUE
- set curs [eval {$db cursor} $txn]
- error_check_good curs_open:nodup [is_substr $curs $db] 1
-
# Put three keys in the database
for { set key 1 } { $key <= 3 } {incr key} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn $flags {$key datum$key}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set curs [eval {$db cursor} $txn]
+ error_check_good curs_open:nodup [is_valid_cursor $curs $db] TRUE
+
# Retrieve keys sequentially so we can figure out their order
set i 1
for {set d [$curs get -first] } \
@@ -82,7 +106,7 @@ proc test054 { method args } {
incr i
}
- # TEST CASE 1
+ # Test case #1.
puts "\tTest054.a1: Delete w/cursor, regular get"
# Now set the cursor on the middle on.
@@ -94,7 +118,7 @@ proc test054 { method args } {
error_check_good curs_get:DB_SET:data $d datum$key_set(2)
# Now do the delete
- set r [eval {$curs del} $txn]
+ set r [$curs del]
error_check_good curs_del $r 0
# Now do the get
@@ -103,17 +127,33 @@ proc test054 { method args } {
# Free up the cursor.
error_check_good cursor_close [eval {$curs close}] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
- # TEST CASE 2
+ # Test case #2.
puts "\tTest054.a2: Cursor before K, delete K, cursor next"
# Replace key 2
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn {$key_set(2) datum$key_set(2)}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# Open and position cursor on first item.
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set curs [eval {$db cursor} $txn]
- error_check_good curs_open:nodup [is_substr $curs $db] 1
+ error_check_good curs_open:nodup [is_valid_cursor $curs $db] TRUE
# Retrieve keys sequentially so we can figure out their order
set i 1
@@ -143,7 +183,7 @@ proc test054 { method args } {
error_check_good curs_get:DB_NEXT:key $k $key_set(3)
error_check_good curs_get:DB_NEXT:data $d datum$key_set(3)
- # TEST CASE 3
+ # Test case #3.
puts "\tTest054.a3: Cursor on K, delete K, cursor current"
# delete item 3
@@ -153,18 +193,34 @@ proc test054 { method args } {
set ret [$curs get -current]
error_check_good current_after_del $ret [list [list [] []]]
error_check_good cursor_close [$curs close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
puts "\tTest054.a4: Cursor on K, delete K, cursor next"
# Restore keys 2 and 3
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn {$key_set(2) datum$key_set(2)}]
error_check_good put $r 0
set r [eval {$db put} $txn {$key_set(3) datum$key_set(3)}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
# Create the new cursor and put it on 1
set curs [eval {$db cursor} $txn]
- error_check_good curs_open:nodup [is_substr $curs $db] 1
+ error_check_good curs_open:nodup [is_valid_cursor $curs $db] TRUE
set r [$curs get -set $key_set(1)]
error_check_bad cursor_get:DB_SET [llength $r] 0
set k [lindex [lindex $r 0] 0]
@@ -186,6 +242,9 @@ proc test054 { method args } {
# Close cursor
error_check_good curs_close [$curs close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
# Now get ready for duplicate tests
@@ -197,19 +256,49 @@ proc test054 { method args } {
puts "\tTest054.b: Duplicate Tests"
append args " -dup"
+
+ # Open a new database for the dup tests so -truncate is not needed.
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/test054-dup.db
+ set env NULL
+ } else {
+ set testfile test054-dup.db
+ set env [lindex $args $eindex]
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+
+ set flags ""
+ set txn ""
+
set db [eval {berkdb_open} $args {$omethod $testfile}]
error_check_good db_open:dup [is_valid_db $db] TRUE
- set curs [eval {$db cursor} $txn]
- error_check_good curs_open:dup [is_substr $curs $db] 1
-
# Put three keys in the database
for { set key 1 } { $key <= 3 } {incr key} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn $flags {$key datum$key}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Retrieve keys sequentially so we can figure out their order
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set curs [eval {$db cursor} $txn]
+ error_check_good curs_open:dup [is_valid_cursor $curs $db] TRUE
+
set i 1
for {set d [$curs get -first] } \
{[llength $d] != 0 } \
@@ -224,7 +313,7 @@ proc test054 { method args } {
error_check_good dup:put $r 0
}
- # TEST CASE 5
+ # Test case #5.
puts "\tTest054.b1: Delete dup w/cursor on first item. Get on key."
# Now set the cursor on the first of the duplicate set.
@@ -243,7 +332,7 @@ proc test054 { method args } {
set r [eval {$db get} $txn {$key_set(2)}]
error_check_good get_after_del [lindex [lindex $r 0] 1] dup_1
- # TEST CASE 6
+ # Test case #6.
puts "\tTest054.b2: Now get the next duplicate from the cursor."
# Now do next on cursor
@@ -254,12 +343,12 @@ proc test054 { method args } {
error_check_good curs_get:DB_NEXT:key $k $key_set(2)
error_check_good curs_get:DB_NEXT:data $d dup_1
- # TEST CASE 3
+ # Test case #3.
puts "\tTest054.b3: Two cursors in set; each delete different items"
# Open a new cursor.
set curs2 [eval {$db cursor} $txn]
- error_check_good curs_open [is_substr $curs2 $db] 1
+ error_check_good curs_open [is_valid_cursor $curs2 $db] TRUE
# Set on last of duplicate set.
set r [$curs2 get -set $key_set(3)]
@@ -365,5 +454,8 @@ proc test054 { method args } {
# Close cursor
error_check_good curs_close [$curs close] 0
error_check_good curs2_close [$curs2 close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test055.tcl b/bdb/test/test055.tcl
index fc5ce4e98bd..25134dca4be 100644
--- a/bdb/test/test055.tcl
+++ b/bdb/test/test055.tcl
@@ -1,16 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test055.tcl,v 11.11 2000/08/25 14:21:57 sue Exp $
+# $Id: test055.tcl,v 11.16 2002/05/22 15:42:55 sue Exp $
#
-# Test055:
-# This test checks basic cursor operations.
-# There are N different scenarios to tests:
-# 1. (no dups) Set cursor, retrieve current.
-# 2. (no dups) Set cursor, retrieve next.
-# 3. (no dups) Set cursor, retrieve prev.
+# TEST test055
+# TEST Basic cursor operations.
+# TEST This test checks basic cursor operations.
+# TEST There are N different scenarios to tests:
+# TEST 1. (no dups) Set cursor, retrieve current.
+# TEST 2. (no dups) Set cursor, retrieve next.
+# TEST 3. (no dups) Set cursor, retrieve prev.
proc test055 { method args } {
global errorInfo
source ./include.tcl
@@ -21,6 +22,7 @@ proc test055 { method args } {
puts "Test055: $method interspersed cursor and normal operations"
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -32,6 +34,11 @@ proc test055 { method args } {
set testfile test055.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -39,28 +46,41 @@ proc test055 { method args } {
set txn ""
puts "\tTest055.a: No duplicates"
- set db [eval {berkdb_open -create -truncate -mode 0644 $omethod } \
+ set db [eval {berkdb_open -create -mode 0644 $omethod } \
$args {$testfile}]
error_check_good db_open:nodup [is_valid_db $db] TRUE
- set curs [eval {$db cursor} $txn]
- error_check_good curs_open:nodup [is_substr $curs $db] 1
-
# Put three keys in the database
for { set key 1 } { $key <= 3 } {incr key} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn $flags {$key datum$key}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Retrieve keys sequentially so we can figure out their order
set i 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set curs [eval {$db cursor} $txn]
+ error_check_good curs_open:nodup [is_valid_cursor $curs $db] TRUE
+
for {set d [$curs get -first] } { [llength $d] != 0 } {\
set d [$curs get -next] } {
set key_set($i) [lindex [lindex $d 0] 0]
incr i
}
- # TEST CASE 1
+ # Test case #1.
puts "\tTest055.a1: Set cursor, retrieve current"
# Now set the cursor on the middle on.
@@ -81,7 +101,7 @@ proc test055 { method args } {
error_check_good \
curs_get:DB_CURRENT:data $d [pad_data $method datum$key_set(2)]
- # TEST CASE 2
+ # Test case #2.
puts "\tTest055.a2: Set cursor, retrieve previous"
set r [$curs get -prev]
error_check_bad cursor_get:DB_PREV [llength $r] 0
@@ -91,10 +111,10 @@ proc test055 { method args } {
error_check_good \
curs_get:DB_PREV:data $d [pad_data $method datum$key_set(1)]
- #TEST CASE 3
+ # Test case #3.
puts "\tTest055.a2: Set cursor, retrieve next"
- # Now set the cursor on the middle on.
+ # Now set the cursor on the middle one.
set r [$curs get -set $key_set(2)]
error_check_bad cursor_get:DB_SET [llength $r] 0
set k [lindex [lindex $r 0] 0]
@@ -114,5 +134,8 @@ proc test055 { method args } {
# Close cursor and database.
error_check_good curs_close [$curs close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test056.tcl b/bdb/test/test056.tcl
index ade3890c3f9..ef310332ed1 100644
--- a/bdb/test/test056.tcl
+++ b/bdb/test/test056.tcl
@@ -1,12 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test056.tcl,v 11.13 2000/08/25 14:21:57 sue Exp $
+# $Id: test056.tcl,v 11.18 2002/05/22 15:42:55 sue Exp $
#
-# Test056
-# Check if deleting a key when a cursor is on a duplicate of that key works.
+# TEST test056
+# TEST Cursor maintenance during deletes.
+# TEST Check if deleting a key when a cursor is on a duplicate of that
+# TEST key works.
proc test056 { method args } {
global errorInfo
source ./include.tcl
@@ -14,7 +16,7 @@ proc test056 { method args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- append args " -create -truncate -mode 0644 -dup "
+ append args " -create -mode 0644 -dup "
if { [is_record_based $method] == 1 || [is_rbtree $method] } {
puts "Test056: skipping for method $method"
return
@@ -22,6 +24,7 @@ proc test056 { method args } {
puts "Test056: $method delete of key in presence of cursor"
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -33,6 +36,11 @@ proc test056 { method args } {
set testfile test056.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -42,18 +50,31 @@ proc test056 { method args } {
set db [eval {berkdb_open} $args {$omethod $testfile}]
error_check_good db_open:dup [is_valid_db $db] TRUE
- set curs [eval {$db cursor} $txn]
- error_check_good curs_open:dup [is_substr $curs $db] 1
-
puts "\tTest056.a: Key delete with cursor on duplicate."
# Put three keys in the database
for { set key 1 } { $key <= 3 } {incr key} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn $flags {$key datum$key}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Retrieve keys sequentially so we can figure out their order
set i 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set curs [eval {$db cursor} $txn]
+ error_check_good curs_open:dup [is_valid_cursor $curs $db] TRUE
+
for {set d [$curs get -first] } { [llength $d] != 0 } {
set d [$curs get -next] } {
set key_set($i) [lindex [lindex $d 0] 0]
@@ -141,5 +162,8 @@ proc test056 { method args } {
error_check_good curs_get:DB_FIRST:data $d datum$key_set(3)
error_check_good curs_close [$curs close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test057.tcl b/bdb/test/test057.tcl
index 1dc350e32a5..04fb09ef260 100644
--- a/bdb/test/test057.tcl
+++ b/bdb/test/test057.tcl
@@ -1,16 +1,17 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test057.tcl,v 11.17 2000/08/25 14:21:57 sue Exp $
+# $Id: test057.tcl,v 11.22 2002/05/22 15:42:56 sue Exp $
#
-# Test057:
-# Check if we handle the case where we delete a key with the cursor on it
-# and then add the same key. The cursor should not get the new item
-# returned, but the item shouldn't disappear.
-# Run test tests, one where the overwriting put is done with a put and
-# one where it's done with a cursor put.
+# TEST test057
+# TEST Cursor maintenance during key deletes.
+# TEST Check if we handle the case where we delete a key with the cursor on
+# TEST it and then add the same key. The cursor should not get the new item
+# TEST returned, but the item shouldn't disappear.
+# TEST Run test tests, one where the overwriting put is done with a put and
+# TEST one where it's done with a cursor put.
proc test057 { method args } {
global errorInfo
source ./include.tcl
@@ -18,7 +19,7 @@ proc test057 { method args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
- append args " -create -truncate -mode 0644 -dup "
+ append args " -create -mode 0644 -dup "
if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
puts "Test057: skipping for method $method"
return
@@ -26,6 +27,7 @@ proc test057 { method args } {
puts "Test057: $method delete and replace in presence of cursor."
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -37,6 +39,11 @@ proc test057 { method args } {
set testfile test057.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -46,20 +53,33 @@ proc test057 { method args } {
set db [eval {berkdb_open} $args {$omethod $testfile}]
error_check_good dbopen:dup [is_valid_db $db] TRUE
- set curs [eval {$db cursor} $txn]
- error_check_good curs_open:dup [is_substr $curs $db] 1
-
puts "\tTest057.a: Set cursor, delete cursor, put with key."
# Put three keys in the database
for { set key 1 } { $key <= 3 } {incr key} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn $flags {$key datum$key}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Retrieve keys sequentially so we can figure out their order
set i 1
- for {set d [$curs get -first] } {[llength $d] != 0 } {\
- set d [$curs get -next] } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set curs [eval {$db cursor} $txn]
+ error_check_good curs_open:dup [is_valid_cursor $curs $db] TRUE
+
+ for {set d [$curs get -first] } {[llength $d] != 0 } \
+ {set d [$curs get -next] } {
set key_set($i) [lindex [lindex $d 0] 0]
incr i
}
@@ -108,7 +128,7 @@ proc test057 { method args } {
puts "\tTest057.b: Set two cursor on a key, delete one, overwrite other"
set curs2 [eval {$db cursor} $txn]
- error_check_good curs2_open [is_substr $curs2 $db] 1
+ error_check_good curs2_open [is_valid_cursor $curs2 $db] TRUE
# Set both cursors on the 4rd key
set r [$curs get -set $key_set(3)]
@@ -221,5 +241,8 @@ proc test057 { method args } {
error_check_good curs2_close [$curs2 close] 0
error_check_good curs_close [$curs close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test058.tcl b/bdb/test/test058.tcl
index 00870a6b5f8..daf164fd6e2 100644
--- a/bdb/test/test058.tcl
+++ b/bdb/test/test058.tcl
@@ -1,10 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test058.tcl,v 11.14 2000/08/25 14:21:57 sue Exp $
+# $Id: test058.tcl,v 11.20 2002/02/22 15:26:27 sandstro Exp $
#
+# TEST test058
+# TEST Verify that deleting and reading duplicates results in correct ordering.
proc test058 { method args } {
source ./include.tcl
@@ -18,6 +20,8 @@ proc test058 { method args } {
return
}
set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
set omethod [convert_method $method]
if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
@@ -28,12 +32,12 @@ proc test058 { method args } {
# environment
env_cleanup $testdir
- set eflags "-create -txn -home $testdir"
- set env [eval {berkdb env} $eflags]
+ set eflags "-create -txn $encargs -home $testdir"
+ set env [eval {berkdb_env} $eflags]
error_check_good env [is_valid_env $env] TRUE
# db open
- set flags "-create -mode 0644 -dup -env $env $args"
+ set flags "-auto_commit -create -mode 0644 -dup -env $env $args"
set db [eval {berkdb_open} $flags $omethod "test058.db"]
error_check_good dbopen [is_valid_db $db] TRUE
diff --git a/bdb/test/test059.tcl b/bdb/test/test059.tcl
index f9988c4e20b..596ea7a3c94 100644
--- a/bdb/test/test059.tcl
+++ b/bdb/test/test059.tcl
@@ -1,16 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test059.tcl,v 11.12 2000/08/25 14:21:57 sue Exp $
-#
-# Test059:
-# Make sure that we handle retrieves of zero-length data items correctly.
-# The following ops, should allow a partial data retrieve of 0-length.
-# db_get
-# db_cget FIRST, NEXT, LAST, PREV, CURRENT, SET, SET_RANGE
+# $Id: test059.tcl,v 11.18 2002/06/11 15:10:16 sue Exp $
#
+# TEST test059
+# TEST Cursor ops work with a partial length of 0.
+# TEST Make sure that we handle retrieves of zero-length data items correctly.
+# TEST The following ops, should allow a partial data retrieve of 0-length.
+# TEST db_get
+# TEST db_cget FIRST, NEXT, LAST, PREV, CURRENT, SET, SET_RANGE
proc test059 { method args } {
source ./include.tcl
@@ -20,6 +20,7 @@ proc test059 { method args } {
puts "Test059: $method 0-length partial data retrieval"
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -31,6 +32,11 @@ proc test059 { method args } {
set testfile test059.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -44,20 +50,33 @@ proc test059 { method args } {
}
puts "\tTest059.a: Populate a database"
- set oflags "-create -truncate -mode 0644 $omethod $args $testfile"
+ set oflags "-create -mode 0644 $omethod $args $testfile"
set db [eval {berkdb_open} $oflags]
error_check_good db_create [is_substr $db db] 1
# Put ten keys in the database
for { set key 1 } { $key <= 10 } {incr key} {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set r [eval {$db put} $txn $pflags {$key datum$key}]
error_check_good put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Retrieve keys sequentially so we can figure out their order
set i 1
- set curs [$db cursor]
- error_check_good db_curs [is_substr $curs $db] 1
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set curs [eval {$db cursor} $txn]
+ error_check_good db_curs [is_valid_cursor $curs $db] TRUE
for {set d [$curs get -first] } { [llength $d] != 0 } {
set d [$curs get -next] } {
@@ -68,7 +87,7 @@ proc test059 { method args } {
puts "\tTest059.a: db get with 0 partial length retrieve"
# Now set the cursor on the middle one.
- set ret [eval {$db get -partial {0 0}} $gflags {$key_set(5)}]
+ set ret [eval {$db get -partial {0 0}} $txn $gflags {$key_set(5)}]
error_check_bad db_get_0 [llength $ret] 0
puts "\tTest059.a: db cget FIRST with 0 partial length retrieve"
@@ -124,5 +143,8 @@ proc test059 { method args } {
}
error_check_good curs_close [$curs close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test060.tcl b/bdb/test/test060.tcl
index 7f7cc71f00b..4a18c97f42f 100644
--- a/bdb/test/test060.tcl
+++ b/bdb/test/test060.tcl
@@ -1,13 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test060.tcl,v 11.6 2000/08/25 14:21:57 sue Exp $
+# $Id: test060.tcl,v 11.10 2002/05/22 15:42:56 sue Exp $
#
-# Test060: Test of the DB_EXCL flag to DB->open.
-# 1) Attempt to open and create a nonexistent database; verify success.
-# 2) Attempt to reopen it; verify failure.
+# TEST test060
+# TEST Test of the DB_EXCL flag to DB->open().
+# TEST 1) Attempt to open and create a nonexistent database; verify success.
+# TEST 2) Attempt to reopen it; verify failure.
proc test060 { method args } {
global errorCode
source ./include.tcl
@@ -18,6 +19,7 @@ proc test060 { method args } {
puts "Test060: $method ($args) Test of the DB_EXCL flag to DB->open"
# Set the database location and make sure the db doesn't exist yet
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -29,6 +31,11 @@ proc test060 { method args } {
set testfile test060.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
diff --git a/bdb/test/test061.tcl b/bdb/test/test061.tcl
index c3187268e39..65544e88deb 100644
--- a/bdb/test/test061.tcl
+++ b/bdb/test/test061.tcl
@@ -1,20 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test061.tcl,v 11.12 2000/10/27 13:23:56 sue Exp $
+# $Id: test061.tcl,v 11.18 2002/02/22 15:26:27 sandstro Exp $
#
-# Test061: Test of transaction abort and commit for in-memory databases.
-# a) Put + abort: verify absence of data
-# b) Put + commit: verify presence of data
-# c) Overwrite + abort: verify that data is unchanged
-# d) Overwrite + commit: verify that data has changed
-# e) Delete + abort: verify that data is still present
-# f) Delete + commit: verify that data has been deleted
+# TEST test061
+# TEST Test of txn abort and commit for in-memory databases.
+# TEST a) Put + abort: verify absence of data
+# TEST b) Put + commit: verify presence of data
+# TEST c) Overwrite + abort: verify that data is unchanged
+# TEST d) Overwrite + commit: verify that data has changed
+# TEST e) Delete + abort: verify that data is still present
+# TEST f) Delete + commit: verify that data has been deleted
proc test061 { method args } {
global alphabet
+ global encrypt
global errorCode
+ global passwd
source ./include.tcl
#
@@ -32,6 +35,8 @@ proc test061 { method args } {
puts "Test061 skipping for method $method"
return
}
+ set encargs ""
+ set args [split_encargs $args encargs]
puts "Test061: Transaction abort and commit test for in-memory data."
puts "Test061: $method $args"
@@ -52,12 +57,12 @@ proc test061 { method args } {
env_cleanup $testdir
# create environment
- set eflags "-create -txn -home $testdir"
- set dbenv [eval {berkdb env} $eflags]
+ set eflags "-create -txn $encargs -home $testdir"
+ set dbenv [eval {berkdb_env} $eflags]
error_check_good dbenv [is_valid_env $dbenv] TRUE
# db open -- no file specified, in-memory database
- set flags "-create $args $omethod"
+ set flags "-auto_commit -create $args $omethod"
set db [eval {berkdb_open -env} $dbenv $flags]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -202,14 +207,20 @@ proc test061 { method args } {
error_check_good env_close [eval {$dbenv close}] 0
# Now run db_recover and ensure that it runs cleanly.
+ set utilflag ""
+ if { $encrypt != 0 } {
+ set utilflag "-P $passwd"
+ }
puts "\tTest061.g: Running db_recover -h"
- set ret [catch {exec $util_path/db_recover -h $testdir} res]
+ set ret [catch {eval {exec} $util_path/db_recover -h $testdir \
+ $utilflag} res]
if { $ret != 0 } {
puts "FAIL: db_recover outputted $res"
}
error_check_good db_recover $ret 0
puts "\tTest061.h: Running db_recover -c -h"
- set ret [catch {exec $util_path/db_recover -c -h $testdir} res]
+ set ret [catch {eval {exec} $util_path/db_recover -c -h $testdir \
+ $utilflag} res]
error_check_good db_recover-c $ret 0
}
diff --git a/bdb/test/test062.tcl b/bdb/test/test062.tcl
index 43a5e1d3939..5cacd98a2c0 100644
--- a/bdb/test/test062.tcl
+++ b/bdb/test/test062.tcl
@@ -1,14 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test062.tcl,v 11.13 2000/12/20 19:02:36 sue Exp $
+# $Id: test062.tcl,v 11.20 2002/06/11 14:09:57 sue Exp $
#
-# DB Test 62: Test of partial puts onto duplicate pages.
-# Insert the first 200 words into the dictionary 200 times each with
-# self as key and <random letter>:self as data. Use partial puts to
-# append self again to data; verify correctness.
+# TEST test062
+# TEST Test of partial puts (using DB_CURRENT) onto duplicate pages.
+# TEST Insert the first 200 words into the dictionary 200 times each with
+# TEST self as key and <random letter>:self as data. Use partial puts to
+# TEST append self again to data; verify correctness.
proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
global alphabet
global rand_init
@@ -19,7 +20,12 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
+ if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
+ puts "Test0$tnum skipping for method $omethod"
+ return
+ }
# Create the database and open the dictionary
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -31,16 +37,25 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 200 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
puts "Test0$tnum:\
- $method ($args) Partial puts and duplicates."
- if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
- puts "Test0$tnum skipping for method $omethod"
- return
- }
- set db [eval {berkdb_open -create -truncate -mode 0644 \
+ $method ($args) $nentries Partial puts and $ndups duplicates."
+ set db [eval {berkdb_open -create -mode 0644 \
$omethod -dup} $args {$testfile} ]
error_check_good dbopen [is_valid_db $db] TRUE
set did [open $dict]
@@ -52,25 +67,35 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
# Here is the loop where we put each key/data pair
puts "\tTest0$tnum.a: Put loop (initialize database)"
- set dbc [eval {$db cursor} $txn]
- error_check_good cursor_open [is_substr $dbc $db] 1
while { [gets $did str] != -1 && $count < $nentries } {
for { set i 1 } { $i <= $ndups } { incr i } {
set pref \
[string index $alphabet [berkdb random_int 0 25]]
set datastr $pref:$str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set ret [eval {$db put} \
$txn $pflags {$str [chop_data $method $datastr]}]
error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
set keys($count) $str
incr count
}
- error_check_good cursor_close [$dbc close] 0
close $did
puts "\tTest0$tnum.b: Partial puts."
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
set dbc [eval {$db cursor} $txn]
error_check_good cursor_open [is_substr $dbc $db] 1
@@ -91,21 +116,21 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
set doff [expr [string length $d] + 2]
set dlen 0
error_check_good data_and_key_sanity $d $k
-
+
set ret [$dbc get -current]
error_check_good before_sanity \
[lindex [lindex $ret 0] 0] \
[string range [lindex [lindex $ret 0] 1] 2 end]
-
+
error_check_good partial_put [eval {$dbc put -current \
-partial [list $doff $dlen] $d}] 0
-
+
set ret [$dbc get -current]
error_check_good partial_put_correct \
[lindex [lindex $ret 0] 1] $orig_d$d
}
}
-
+
puts "\tTest0$tnum.c: Double-checking get loop."
# Double-check that each datum in the regular db has
# been appropriately modified.
@@ -121,5 +146,8 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test063.tcl b/bdb/test/test063.tcl
index 2b9c4c4c763..2e8726c8f96 100644
--- a/bdb/test/test063.tcl
+++ b/bdb/test/test063.tcl
@@ -1,13 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test063.tcl,v 11.11 2000/08/25 14:21:58 sue Exp $
+# $Id: test063.tcl,v 11.17 2002/05/24 15:24:55 sue Exp $
#
-# DB Test 63: Test that the DB_RDONLY flag is respected.
-# Attempt to both DB->put and DBC->c_put into a database
-# that has been opened DB_RDONLY, and check for failure.
+# TEST test063
+# TEST Test of the DB_RDONLY flag to DB->open
+# TEST Attempt to both DB->put and DBC->c_put into a database
+# TEST that has been opened DB_RDONLY, and check for failure.
proc test063 { method args } {
global errorCode
source ./include.tcl
@@ -16,6 +17,7 @@ proc test063 { method args } {
set omethod [convert_method $method]
set tnum 63
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -27,6 +29,11 @@ proc test063 { method args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -36,6 +43,7 @@ proc test063 { method args } {
set data2 "more_data"
set gflags ""
+ set txn ""
if { [is_record_based $method] == 1 } {
set key "1"
@@ -47,18 +55,26 @@ proc test063 { method args } {
# Create a test database.
puts "\tTest0$tnum.a: Creating test database."
- set db [eval {berkdb_open_noerr -create -truncate -mode 0644} \
+ set db [eval {berkdb_open_noerr -create -mode 0644} \
$omethod $args $testfile]
error_check_good db_create [is_valid_db $db] TRUE
# Put and get an item so it's nonempty.
- set ret [eval {$db put} $key [chop_data $method $data]]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key [chop_data $method $data]}]
error_check_good initial_put $ret 0
- set dbt [eval {$db get} $gflags $key]
+ set dbt [eval {$db get} $txn $gflags {$key}]
error_check_good initial_get $dbt \
[list [list $key [pad_data $method $data]]]
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
if { $eindex == -1 } {
@@ -74,19 +90,33 @@ proc test063 { method args } {
set db [eval {berkdb_open_noerr -rdonly} $args {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
- set dbt [eval {$db get} $gflags $key]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbt [eval {$db get} $txn $gflags {$key}]
error_check_good db_get $dbt \
[list [list $key [pad_data $method $data]]]
- set ret [catch {eval {$db put} $key2 [chop_data $method $data]} res]
+ set ret [catch {eval {$db put} $txn \
+ {$key2 [chop_data $method $data]}} res]
error_check_good put_failed $ret 1
error_check_good db_put_rdonly [is_substr $errorCode "EACCES"] 1
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set errorCode "NONE"
puts "\tTest0$tnum.c: Attempting cursor put."
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good cursor_create [is_valid_cursor $dbc $db] TRUE
error_check_good cursor_set [$dbc get -first] $dbt
@@ -94,17 +124,17 @@ proc test063 { method args } {
error_check_good c_put_failed $ret 1
error_check_good dbc_put_rdonly [is_substr $errorCode "EACCES"] 1
- set dbt [eval {$db get} $gflags $key2]
+ set dbt [eval {$db get} $gflags {$key2}]
error_check_good db_get_key2 $dbt ""
puts "\tTest0$tnum.d: Attempting ordinary delete."
set errorCode "NONE"
- set ret [catch {eval {$db del} $key} 1]
+ set ret [catch {eval {$db del} $txn {$key}} 1]
error_check_good del_failed $ret 1
error_check_good db_del_rdonly [is_substr $errorCode "EACCES"] 1
- set dbt [eval {$db get} $gflags $key]
+ set dbt [eval {$db get} $txn $gflags {$key}]
error_check_good db_get_key $dbt \
[list [list $key [pad_data $method $data]]]
@@ -124,6 +154,9 @@ proc test063 { method args } {
puts "\tTest0$tnum.f: Close, reopen db; verify unchanged."
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
set db [eval {berkdb_open} $omethod $args $testfile]
diff --git a/bdb/test/test064.tcl b/bdb/test/test064.tcl
index ad39f4b2256..c306b0d9d46 100644
--- a/bdb/test/test064.tcl
+++ b/bdb/test/test064.tcl
@@ -1,14 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test064.tcl,v 11.8 2000/08/25 14:21:58 sue Exp $
+# $Id: test064.tcl,v 11.13 2002/05/22 15:42:57 sue Exp $
#
-# DB Test 64: Test of DB->get_type
-# Create a database of type specified by method.
-# Make sure DB->get_type returns the right thing with both a
-# normal and DB_UNKNOWN open.
+# TEST test064
+# TEST Test of DB->get_type
+# TEST Create a database of type specified by method.
+# TEST Make sure DB->get_type returns the right thing with both a normal
+# TEST and DB_UNKNOWN open.
proc test064 { method args } {
source ./include.tcl
@@ -16,6 +17,7 @@ proc test064 { method args } {
set omethod [convert_method $method]
set tnum 64
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -27,6 +29,11 @@ proc test064 { method args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -34,7 +41,7 @@ proc test064 { method args } {
# Create a test database.
puts "\tTest0$tnum.a: Creating test database of type $method."
- set db [eval {berkdb_open -create -truncate -mode 0644} \
+ set db [eval {berkdb_open -create -mode 0644} \
$omethod $args $testfile]
error_check_good db_create [is_valid_db $db] TRUE
diff --git a/bdb/test/test065.tcl b/bdb/test/test065.tcl
index 5f236ebbd04..ea29b4d2db7 100644
--- a/bdb/test/test065.tcl
+++ b/bdb/test/test065.tcl
@@ -1,20 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test065.tcl,v 11.8 2000/08/25 14:21:58 sue Exp $
+# $Id: test065.tcl,v 11.16 2002/08/22 18:18:50 sandstro Exp $
#
-# DB Test 65: Test of DB->stat(DB_RECORDCOUNT)
+# TEST test065
+# TEST Test of DB->stat(DB_FASTSTAT)
proc test065 { method args } {
source ./include.tcl
global errorCode
global alphabet
+ set nentries 10000
set args [convert_args $method $args]
set omethod [convert_method $method]
set tnum 65
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -26,37 +29,48 @@ proc test065 { method args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
- puts "Test0$tnum: $method ($args) DB->stat(DB_RECORDCOUNT) test."
+ puts "Test0$tnum: $method ($args) DB->stat(DB_FAST_STAT) test."
puts "\tTest0$tnum.a: Create database and check it while empty."
- set db [eval {berkdb_open_noerr -create -truncate -mode 0644} \
+ set db [eval {berkdb_open_noerr -create -mode 0644} \
$omethod $args $testfile]
error_check_good db_open [is_valid_db $db] TRUE
- set ret [catch {eval $db stat -recordcount} res]
+ set ret [catch {eval $db stat -faststat} res]
error_check_good db_close [$db close] 0
if { ([is_record_based $method] && ![is_queue $method]) \
|| [is_rbtree $method] } {
- error_check_good recordcount_ok [lindex [lindex $res 0] 1] 0
+ error_check_good recordcount_ok [is_substr $res \
+ "{{Number of keys} 0}"] 1
} else {
- error_check_good \
- recordcount_notok [is_substr $errorCode "EINVAL"] 1
puts "\tTest0$tnum: Test complete for method $method."
return
}
# If we've got this far, we're on an access method for
- # which DB_RECORDCOUNT makes sense. Thus, we no longer
+ # which record counts makes sense. Thus, we no longer
# catch EINVALs, and no longer care about __db_errs.
set db [eval {berkdb_open -create -mode 0644} $omethod $args $testfile]
- puts "\tTest0$tnum.b: put 10000 keys."
+ puts "\tTest0$tnum.b: put $nentries keys."
if { [is_record_based $method] } {
set gflags " -recno "
@@ -66,80 +80,119 @@ proc test065 { method args } {
set keypfx "key"
}
+ set txn ""
set data [pad_data $method $alphabet]
- for { set ndx 1 } { $ndx <= 10000 } { incr ndx } {
- set ret [eval {$db put} $keypfx$ndx $data]
+ for { set ndx 1 } { $ndx <= $nentries } { incr ndx } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$keypfx$ndx $data}]
error_check_good db_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
- set ret [$db stat -recordcount]
- error_check_good \
- recordcount_after_puts [lindex [lindex $ret 0] 1] 10000
-
- puts "\tTest0$tnum.c: delete 9000 keys."
- for { set ndx 1 } { $ndx <= 9000 } { incr ndx } {
+ set ret [$db stat -faststat]
+ error_check_good recordcount_after_puts \
+ [is_substr $ret "{{Number of keys} $nentries}"] 1
+
+ puts "\tTest0$tnum.c: delete 90% of keys."
+ set end [expr {$nentries / 10 * 9}]
+ for { set ndx 1 } { $ndx <= $end } { incr ndx } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
if { [is_rrecno $method] == 1 } {
# if we're renumbering, when we hit key 5001 we'll
# have deleted 5000 and we'll croak! So delete key
# 1, repeatedly.
- set ret [eval {$db del} [concat $keypfx 1]]
+ set ret [eval {$db del} $txn {[concat $keypfx 1]}]
} else {
- set ret [eval {$db del} $keypfx$ndx]
+ set ret [eval {$db del} $txn {$keypfx$ndx}]
}
error_check_good db_del $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
- set ret [$db stat -recordcount]
+ set ret [$db stat -faststat]
if { [is_rrecno $method] == 1 || [is_rbtree $method] == 1 } {
- # We allow renumbering--thus the stat should return 1000
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 1000
+ # We allow renumbering--thus the stat should return 10%
+ # of nentries.
+ error_check_good recordcount_after_dels [is_substr $ret \
+ "{{Number of keys} [expr {$nentries / 10}]}"] 1
} else {
# No renumbering--no change in RECORDCOUNT!
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 10000
+ error_check_good recordcount_after_dels \
+ [is_substr $ret "{{Number of keys} $nentries}"] 1
}
- puts "\tTest0$tnum.d: put 8000 new keys at the beginning."
- for { set ndx 1 } { $ndx <= 8000 } {incr ndx } {
- set ret [eval {$db put} $keypfx$ndx $data]
+ puts "\tTest0$tnum.d: put new keys at the beginning."
+ set end [expr {$nentries / 10 * 8}]
+ for { set ndx 1 } { $ndx <= $end } {incr ndx } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$keypfx$ndx $data}]
error_check_good db_put_beginning $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
- set ret [$db stat -recordcount]
+ set ret [$db stat -faststat]
if { [is_rrecno $method] == 1 } {
- # With renumbering we're back up to 8000
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 8000
+ # With renumbering we're back up to 80% of $nentries
+ error_check_good recordcount_after_dels [is_substr $ret \
+ "{{Number of keys} [expr {$nentries / 10 * 8}]}"] 1
} elseif { [is_rbtree $method] == 1 } {
- # Total records in a btree is now 9000
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 9000
+ # Total records in a btree is now 90% of $nentries
+ error_check_good recordcount_after_dels [is_substr $ret \
+ "{{Number of keys} [expr {$nentries / 10 * 9}]}"] 1
} else {
# No renumbering--still no change in RECORDCOUNT.
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 10000
+ error_check_good recordcount_after_dels [is_substr $ret \
+ "{{Number of keys} $nentries}"] 1
}
- puts "\tTest0$tnum.e: put 8000 new keys off the end."
- for { set ndx 9001 } { $ndx <= 17000 } {incr ndx } {
- set ret [eval {$db put} $keypfx$ndx $data]
+ puts "\tTest0$tnum.e: put new keys at the end."
+ set start [expr {1 + $nentries / 10 * 9}]
+ set end [expr {($nentries / 10 * 9) + ($nentries / 10 * 8)}]
+ for { set ndx $start } { $ndx <= $end } { incr ndx } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$keypfx$ndx $data}]
error_check_good db_put_end $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
- set ret [$db stat -recordcount]
+ set ret [$db stat -faststat]
if { [is_rbtree $method] != 1 } {
- # If this is a recno database, the record count should
- # be up to 17000, the largest number we've seen, with
+ # If this is a recno database, the record count should be up
+ # to (1.7 x nentries), the largest number we've seen, with
# or without renumbering.
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 17000
+ error_check_good recordcount_after_puts2 [is_substr $ret \
+ "{{Number of keys} [expr {$start - 1 + $nentries / 10 * 8}]}"] 1
} else {
- # In an rbtree, 1000 of those keys were overwrites,
- # so there are 7000 new keys + 9000 old keys == 16000
- error_check_good \
- recordcount_after_dels [lindex [lindex $ret 0] 1] 16000
+ # In an rbtree, 1000 of those keys were overwrites, so there
+ # are (.7 x nentries) new keys and (.9 x nentries) old keys
+ # for a total of (1.6 x nentries).
+ error_check_good recordcount_after_puts2 [is_substr $ret \
+ "{{Number of keys} [expr {$start -1 + $nentries / 10 * 7}]}"] 1
}
error_check_good db_close [$db close] 0
diff --git a/bdb/test/test066.tcl b/bdb/test/test066.tcl
index 591c51a4c87..13d0894dcae 100644
--- a/bdb/test/test066.tcl
+++ b/bdb/test/test066.tcl
@@ -1,12 +1,15 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test066.tcl,v 11.7 2000/08/25 14:21:58 sue Exp $
+# $Id: test066.tcl,v 11.12 2002/05/24 15:24:56 sue Exp $
#
-# DB Test 66: Make sure a cursor put to DB_CURRENT acts as an overwrite in
-# a database with duplicates
+# TEST test066
+# TEST Test of cursor overwrites of DB_CURRENT w/ duplicates.
+# TEST
+# TEST Make sure a cursor put to DB_CURRENT acts as an overwrite in a
+# TEST database with duplicates.
proc test066 { method args } {
set omethod [convert_method $method]
set args [convert_args $method $args]
@@ -22,6 +25,7 @@ proc test066 { method args } {
source ./include.tcl
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -33,9 +37,15 @@ proc test066 { method args } {
set testfile test066.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
+ set txn ""
set key "test"
set data "olddata"
@@ -43,10 +53,23 @@ proc test066 { method args } {
$testfile]
error_check_good db_open [is_valid_db $db] TRUE
- set ret [eval {$db put} $key [chop_data $method $data]]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key [chop_data $method $data]}]
error_check_good db_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
set ret [$dbc get -first]
@@ -67,6 +90,9 @@ proc test066 { method args } {
error_check_good db_get_next $ret ""
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
puts "\tTest0$tnum: Test completed successfully."
diff --git a/bdb/test/test067.tcl b/bdb/test/test067.tcl
index c287d7b1ec5..5f5a88c4be1 100644
--- a/bdb/test/test067.tcl
+++ b/bdb/test/test067.tcl
@@ -1,26 +1,32 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test067.tcl,v 11.12 2000/08/25 14:21:58 sue Exp $
+# $Id: test067.tcl,v 11.19 2002/06/11 15:19:16 sue Exp $
#
-# DB Test 67: Test of DB_CURRENT partial puts on almost-empty duplicate pages.
-# This test was written to address the following issue, #2 in the list of
-# issues relating to bug #0820:
-# 2. DBcursor->put, DB_CURRENT flag, off-page duplicates, hash and btree:
-# In Btree, the DB_CURRENT overwrite of off-page duplicate records
-# first deletes the record and then puts the new one -- this could
-# be a problem if the removal of the record causes a reverse split.
-# Suggested solution is to acquire a cursor to lock down the current
-# record, put a new record after that record, and then delete using
-# the held cursor.
-# It also tests the following, #5 in the same list of issues:
-# 5. DBcursor->put, DB_AFTER/DB_BEFORE/DB_CURRENT flags, DB_DBT_PARTIAL set,
-# duplicate comparison routine specified.
-# The partial change does not change how data items sort, but the
-# record to be put isn't built yet, and that record supplied is the
-# one that's checked for ordering compatibility.
+# TEST test067
+# TEST Test of DB_CURRENT partial puts onto almost empty duplicate
+# TEST pages, with and without DB_DUP_SORT.
+# TEST
+# TEST Test of DB_CURRENT partial puts on almost-empty duplicate pages.
+# TEST This test was written to address the following issue, #2 in the
+# TEST list of issues relating to bug #0820:
+# TEST
+# TEST 2. DBcursor->put, DB_CURRENT flag, off-page duplicates, hash and btree:
+# TEST In Btree, the DB_CURRENT overwrite of off-page duplicate records
+# TEST first deletes the record and then puts the new one -- this could
+# TEST be a problem if the removal of the record causes a reverse split.
+# TEST Suggested solution is to acquire a cursor to lock down the current
+# TEST record, put a new record after that record, and then delete using
+# TEST the held cursor.
+# TEST
+# TEST It also tests the following, #5 in the same list of issues:
+# TEST 5. DBcursor->put, DB_AFTER/DB_BEFORE/DB_CURRENT flags, DB_DBT_PARTIAL
+# TEST set, duplicate comparison routine specified.
+# TEST The partial change does not change how data items sort, but the
+# TEST record to be put isn't built yet, and that record supplied is the
+# TEST one that's checked for ordering compatibility.
proc test067 { method {ndups 1000} {tnum 67} args } {
source ./include.tcl
global alphabet
@@ -29,6 +35,12 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
set args [convert_args $method $args]
set omethod [convert_method $method]
+ if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
+ puts "\tTest0$tnum: skipping for method $method."
+ return
+ }
+ set txn ""
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
# If we are using an env, then testfile should just be the db name.
@@ -40,18 +52,31 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ if { $ndups == 1000 } {
+ set ndups 100
+ }
+ }
+ set testdir [get_home $env]
}
puts "Test0$tnum:\
$method ($args) Partial puts on near-empty duplicate pages."
- if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
- puts "\tTest0$tnum: skipping for method $method."
- return
- }
foreach dupopt { "-dup" "-dup -dupsort" } {
+ #
+ # Testdir might get reset from the env's home dir back
+ # to the default if this calls something that sources
+ # include.tcl, since testdir is a global. Set it correctly
+ # here each time through the loop.
+ #
+ if { $env != "NULL" } {
+ set testdir [get_home $env]
+ }
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644 \
+ set db [eval {berkdb_open -create -mode 0644 \
$omethod} $args $dupopt {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
@@ -62,9 +87,17 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
for { set ndx 0 } { $ndx < $ndups } { incr ndx } {
set data $alphabet$ndx
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
# No need for pad_data since we're skipping recno.
- set ret [eval {$db put} $key $data]
+ set ret [eval {$db put} $txn {$key $data}]
error_check_good put($key,$data) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# Sync so we can inspect database if the next section bombs.
@@ -72,7 +105,12 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
puts "\tTest0$tnum.b ($dupopt):\
Deleting dups (last first), overwriting each."
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good cursor_create [is_valid_cursor $dbc $db] TRUE
set count 0
@@ -109,6 +147,9 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
}
diff --git a/bdb/test/test068.tcl b/bdb/test/test068.tcl
index 587cd207890..31f4272ba55 100644
--- a/bdb/test/test068.tcl
+++ b/bdb/test/test068.tcl
@@ -1,28 +1,30 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test068.tcl,v 11.11 2000/08/25 14:21:58 sue Exp $
+# $Id: test068.tcl,v 11.17 2002/06/11 15:34:47 sue Exp $
#
-# DB Test 68: Test of DB_BEFORE and DB_AFTER and partial puts.
-# Make sure DB_BEFORE and DB_AFTER work properly with partial puts,
-# and check that they return EINVAL if DB_DUPSORT is set or if DB_DUP is not.
+# TEST test068
+# TEST Test of DB_BEFORE and DB_AFTER with partial puts.
+# TEST Make sure DB_BEFORE and DB_AFTER work properly with partial puts, and
+# TEST check that they return EINVAL if DB_DUPSORT is set or if DB_DUP is not.
proc test068 { method args } {
source ./include.tcl
global alphabet
global errorCode
set tnum 68
- set nkeys 1000
set args [convert_args $method $args]
set omethod [convert_method $method]
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
+ set nkeys 1000
if { $eindex == -1 } {
set testfile $testdir/test0$tnum.db
set env NULL
@@ -30,6 +32,12 @@ proc test068 { method args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ set nkeys 100
+ }
+ set testdir [get_home $env]
}
puts "Test0$tnum:\
@@ -41,6 +49,7 @@ proc test068 { method args } {
# Create a list of $nkeys words to insert into db.
puts "\tTest0$tnum.a: Initialize word list."
+ set txn ""
set wordlist {}
set count 0
set did [open $dict]
@@ -62,14 +71,30 @@ proc test068 { method args } {
}
foreach dupopt $dupoptlist {
+ #
+ # Testdir might be reset in the loop by some proc sourcing
+ # include.tcl. Reset it to the env's home here, before
+ # cleanup.
+ if { $env != "NULL" } {
+ set testdir [get_home $env]
+ }
cleanup $testdir $env
- set db [eval {berkdb_open_noerr -create -truncate -mode 0644 \
+ set db [eval {berkdb_open_noerr -create -mode 0644 \
$omethod} $args $dupopt {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
puts "\tTest0$tnum.b ($dupopt): DB initialization: put loop."
foreach word $wordlist {
- error_check_good db_put [$db put $word $word] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$word $word}]
+ error_check_good db_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
puts "\tTest0$tnum.c ($dupopt): get loop."
@@ -82,7 +107,12 @@ proc test068 { method args } {
error_check_good get_key [list [list $word $word]] $dbt
}
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
puts "\tTest0$tnum.d ($dupopt): DBC->put w/ DB_AFTER."
@@ -116,6 +146,10 @@ proc test068 { method args } {
puts "\tTest0$tnum ($dupopt): Correct error returns,\
skipping further test."
# continue with broad foreach
+ error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
continue
}
@@ -143,11 +177,19 @@ proc test068 { method args } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
eval $db sync
puts "\tTest0$tnum.g ($dupopt): Verify correctness."
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
# loop through the whole db beginning to end,
@@ -176,6 +218,9 @@ proc test068 { method args } {
incr count
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
}
diff --git a/bdb/test/test069.tcl b/bdb/test/test069.tcl
index f3b839de7f9..d986c861358 100644
--- a/bdb/test/test069.tcl
+++ b/bdb/test/test069.tcl
@@ -1,14 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test069.tcl,v 11.4 2000/02/14 03:00:21 bostic Exp $
+# $Id: test069.tcl,v 11.7 2002/01/11 15:53:52 bostic Exp $
#
-# DB Test 69: Run DB Test 67 with a small number of dups,
-# to ensure that partial puts to DB_CURRENT work correctly in
-# the absence of duplicate pages.
-
+# TEST test069
+# TEST Test of DB_CURRENT partial puts without duplicates-- test067 w/
+# TEST small ndups to ensure that partial puts to DB_CURRENT work
+# TEST correctly in the absence of duplicate pages.
proc test069 { method {ndups 50} {tnum 69} args } {
eval test067 $method $ndups $tnum $args
}
diff --git a/bdb/test/test070.tcl b/bdb/test/test070.tcl
index befec9ce1e9..986fd079589 100644
--- a/bdb/test/test070.tcl
+++ b/bdb/test/test070.tcl
@@ -1,19 +1,22 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test070.tcl,v 11.18 2000/12/18 20:04:47 sue Exp $
+# $Id: test070.tcl,v 11.27 2002/09/05 17:23:07 sandstro Exp $
#
-# DB Test 70: Test of DB_CONSUME.
-# Fork off six processes, four consumers and two producers.
-# The producers will each put 20000 records into a queue;
-# the consumers will each get 10000.
-# Then, verify that no record was lost or retrieved twice.
+# TEST test070
+# TEST Test of DB_CONSUME (Four consumers, 1000 items.)
+# TEST
+# TEST Fork off six processes, four consumers and two producers.
+# TEST The producers will each put 20000 records into a queue;
+# TEST the consumers will each get 10000.
+# TEST Then, verify that no record was lost or retrieved twice.
proc test070 { method {nconsumers 4} {nproducers 2} \
{nitems 1000} {mode CONSUME } {start 0} {txn -txn} {tnum 70} args } {
source ./include.tcl
global alphabet
+ global encrypt
#
# If we are using an env, then skip this test. It needs its own.
@@ -26,6 +29,10 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
}
set omethod [convert_method $method]
set args [convert_args $method $args]
+ if { $encrypt != 0 } {
+ puts "Test0$tnum skipping for security"
+ return
+ }
puts "Test0$tnum: $method ($args) Test of DB_$mode flag to DB->get."
puts "\tUsing $txn environment."
@@ -42,7 +49,7 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
set testfile test0$tnum.db
# Create environment
- set dbenv [eval {berkdb env -create $txn -home } $testdir]
+ set dbenv [eval {berkdb_env -create $txn -home } $testdir]
error_check_good dbenv_create [is_valid_env $dbenv] TRUE
# Create database
@@ -86,7 +93,7 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
}
# Wait for all children.
- watch_procs 10
+ watch_procs $pidlist 10
# Verify: slurp all record numbers into list, sort, and make
# sure each appears exactly once.
@@ -96,6 +103,12 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
set input $consumerlog$ndx
set iid [open $input r]
while { [gets $iid str] != -1 } {
+ # Convert high ints to negative ints, to
+ # simulate Tcl's behavior on a 32-bit machine
+ # even if we're on a 64-bit one.
+ if { $str > 0x7fffffff } {
+ set str [expr $str - 1 - 0xffffffff]
+ }
lappend reclist $str
}
close $iid
@@ -104,16 +117,25 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
set nitems [expr $start + $nitems]
for { set ndx $start } { $ndx < $nitems } { incr ndx } {
+ # Convert high ints to negative ints, to simulate
+ # 32-bit behavior on 64-bit platforms.
+ if { $ndx > 0x7fffffff } {
+ set cmp [expr $ndx - 1 - 0xffffffff]
+ } else {
+ set cmp [expr $ndx + 0]
+ }
# Skip 0 if we are wrapping around
- if { $ndx == 0 } {
+ if { $cmp == 0 } {
incr ndx
incr nitems
+ incr cmp
}
# Be sure to convert ndx to a number before comparing.
- error_check_good pop_num [lindex $sortreclist 0] [expr $ndx + 0]
+ error_check_good pop_num [lindex $sortreclist 0] $cmp
set sortreclist [lreplace $sortreclist 0 0]
}
error_check_good list_ends_empty $sortreclist {}
+ error_check_good db_close [$db close] 0
error_check_good dbenv_close [$dbenv close] 0
puts "\tTest0$tnum completed successfully."
diff --git a/bdb/test/test071.tcl b/bdb/test/test071.tcl
index 376c902ec4d..3f2604022f1 100644
--- a/bdb/test/test071.tcl
+++ b/bdb/test/test071.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test071.tcl,v 11.6 2000/12/01 04:28:36 ubell Exp $
+# $Id: test071.tcl,v 11.9 2002/01/11 15:53:53 bostic Exp $
#
-# DB Test 71: Test of DB_CONSUME.
-# This is DB Test 70, with one consumer, one producers, and 10000 items.
+# TEST test071
+# TEST Test of DB_CONSUME (One consumer, 10000 items.)
+# TEST This is DB Test 70, with one consumer, one producers, and 10000 items.
proc test071 { method {nconsumers 1} {nproducers 1}\
{nitems 10000} {mode CONSUME} {start 0 } {txn -txn} {tnum 71} args } {
diff --git a/bdb/test/test072.tcl b/bdb/test/test072.tcl
index 3ca7415a2cb..3c08f93975d 100644
--- a/bdb/test/test072.tcl
+++ b/bdb/test/test072.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test072.tcl,v 11.13 2000/12/11 17:24:55 sue Exp $
+# $Id: test072.tcl,v 11.27 2002/07/01 15:40:48 krinsky Exp $
#
-# DB Test 72: Test of cursor stability when duplicates are moved off-page.
+# TEST test072
+# TEST Test of cursor stability when duplicates are moved off-page.
proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
source ./include.tcl
global alphabet
@@ -13,6 +14,7 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
set omethod [convert_method $method]
set args [convert_args $method $args]
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -24,6 +26,11 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -37,8 +44,6 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
set predatum "1234567890"
set postdatum "0987654321"
- append args " -pagesize $pagesize "
-
puts -nonewline "Test0$tnum $omethod ($args): "
if { [is_record_based $method] || [is_rbtree $method] } {
puts "Skipping for method $method."
@@ -53,57 +58,73 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
return
}
- foreach dupopt { "-dup" "-dup -dupsort" } {
- set db [eval {berkdb_open -create -truncate -mode 0644} \
- $omethod $args $dupopt $testfile]
+ append args " -pagesize $pagesize "
+ set txn ""
+
+ set dlist [list "-dup" "-dup -dupsort"]
+ set testid 0
+ foreach dupopt $dlist {
+ incr testid
+ set duptestfile $testfile$testid
+ set db [eval {berkdb_open -create -mode 0644} \
+ $omethod $args $dupopt {$duptestfile}]
error_check_good "db open" [is_valid_db $db] TRUE
puts \
"\tTest0$tnum.a: ($dupopt) Set up surrounding keys and cursors."
- error_check_good pre_put [$db put $prekey $predatum] 0
- error_check_good post_put [$db put $postkey $postdatum] 0
- set precursor [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$prekey $predatum}]
+ error_check_good pre_put $ret 0
+ set ret [eval {$db put} $txn {$postkey $postdatum}]
+ error_check_good post_put $ret 0
+
+ set precursor [eval {$db cursor} $txn]
error_check_good precursor [is_valid_cursor $precursor \
$db] TRUE
- set postcursor [$db cursor]
+ set postcursor [eval {$db cursor} $txn]
error_check_good postcursor [is_valid_cursor $postcursor \
$db] TRUE
error_check_good preset [$precursor get -set $prekey] \
[list [list $prekey $predatum]]
error_check_good postset [$postcursor get -set $postkey] \
[list [list $postkey $postdatum]]
-
+
puts "\tTest0$tnum.b: Put/create cursor/verify all cursor loop."
-
+
for { set i 0 } { $i < $ndups } { incr i } {
set datum [format "%4d$alphabet" [expr $i + 1000]]
set data($i) $datum
-
+
# Uncomment these lines to see intermediate steps.
- error_check_good db_sync($i) [$db sync] 0
- error_check_good db_dump($i) \
- [catch {exec $util_path/db_dump \
- -da $testfile > TESTDIR/out.$i}] 0
-
- error_check_good "db put ($i)" [$db put $key $datum] 0
-
- set dbc($i) [$db cursor]
+ # error_check_good db_sync($i) [$db sync] 0
+ # error_check_good db_dump($i) \
+ # [catch {exec $util_path/db_dump \
+ # -da $duptestfile > $testdir/out.$i}] 0
+
+ set ret [eval {$db put} $txn {$key $datum}]
+ error_check_good "db put ($i)" $ret 0
+
+ set dbc($i) [eval {$db cursor} $txn]
error_check_good "db cursor ($i)"\
[is_valid_cursor $dbc($i) $db] TRUE
-
+
error_check_good "dbc get -get_both ($i)"\
[$dbc($i) get -get_both $key $datum]\
[list [list $key $datum]]
-
+
for { set j 0 } { $j < $i } { incr j } {
set dbt [$dbc($j) get -current]
set k [lindex [lindex $dbt 0] 0]
set d [lindex [lindex $dbt 0] 1]
-
+
#puts "cursor $j after $i: $d"
-
+
eval {$db sync}
-
+
error_check_good\
"cursor $j key correctness after $i puts" \
$k $key
@@ -111,8 +132,8 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
"cursor $j data correctness after $i puts" \
$d $data($j)
}
-
- # Check correctness of pre- and post- cursors. Do an
+
+ # Check correctness of pre- and post- cursors. Do an
# error_check_good on the lengths first so that we don't
# spew garbage as the "got" field and screw up our
# terminal. (It's happened here.)
@@ -121,7 +142,7 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
error_check_good \
"key earlier cursor correctness after $i puts" \
[string length [lindex [lindex $pre_dbt 0] 0]] \
- [string length $prekey]
+ [string length $prekey]
error_check_good \
"data earlier cursor correctness after $i puts" \
[string length [lindex [lindex $pre_dbt 0] 1]] \
@@ -129,12 +150,11 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
error_check_good \
"key later cursor correctness after $i puts" \
[string length [lindex [lindex $post_dbt 0] 0]] \
- [string length $postkey]
+ [string length $postkey]
error_check_good \
"data later cursor correctness after $i puts" \
[string length [lindex [lindex $post_dbt 0] 1]]\
[string length $postdatum]
-
error_check_good \
"earlier cursor correctness after $i puts" \
@@ -143,38 +163,40 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
"later cursor correctness after $i puts" \
$post_dbt [list [list $postkey $postdatum]]
}
-
+
puts "\tTest0$tnum.c: Reverse Put/create cursor/verify all cursor loop."
set end [expr $ndups * 2 - 1]
- for { set i $end } { $i > $ndups } { set i [expr $i - 1] } {
+ for { set i $end } { $i >= $ndups } { set i [expr $i - 1] } {
set datum [format "%4d$alphabet" [expr $i + 1000]]
set data($i) $datum
-
+
# Uncomment these lines to see intermediate steps.
- error_check_good db_sync($i) [$db sync] 0
- error_check_good db_dump($i) \
- [catch {exec $util_path/db_dump \
- -da $testfile > TESTDIR/out.$i}] 0
-
- error_check_good "db put ($i)" [$db put $key $datum] 0
-
- set dbc($i) [$db cursor]
+ # error_check_good db_sync($i) [$db sync] 0
+ # error_check_good db_dump($i) \
+ # [catch {exec $util_path/db_dump \
+ # -da $duptestfile > $testdir/out.$i}] 0
+
+ set ret [eval {$db put} $txn {$key $datum}]
+ error_check_good "db put ($i)" $ret 0
+
+ error_check_bad dbc($i)_stomped [info exists dbc($i)] 1
+ set dbc($i) [eval {$db cursor} $txn]
error_check_good "db cursor ($i)"\
[is_valid_cursor $dbc($i) $db] TRUE
-
+
error_check_good "dbc get -get_both ($i)"\
[$dbc($i) get -get_both $key $datum]\
[list [list $key $datum]]
-
+
for { set j $i } { $j < $end } { incr j } {
set dbt [$dbc($j) get -current]
set k [lindex [lindex $dbt 0] 0]
set d [lindex [lindex $dbt 0] 1]
-
+
#puts "cursor $j after $i: $d"
-
+
eval {$db sync}
-
+
error_check_good\
"cursor $j key correctness after $i puts" \
$k $key
@@ -182,8 +204,8 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
"cursor $j data correctness after $i puts" \
$d $data($j)
}
-
- # Check correctness of pre- and post- cursors. Do an
+
+ # Check correctness of pre- and post- cursors. Do an
# error_check_good on the lengths first so that we don't
# spew garbage as the "got" field and screw up our
# terminal. (It's happened here.)
@@ -192,7 +214,7 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
error_check_good \
"key earlier cursor correctness after $i puts" \
[string length [lindex [lindex $pre_dbt 0] 0]] \
- [string length $prekey]
+ [string length $prekey]
error_check_good \
"data earlier cursor correctness after $i puts" \
[string length [lindex [lindex $pre_dbt 0] 1]] \
@@ -200,12 +222,11 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
error_check_good \
"key later cursor correctness after $i puts" \
[string length [lindex [lindex $post_dbt 0] 0]] \
- [string length $postkey]
+ [string length $postkey]
error_check_good \
"data later cursor correctness after $i puts" \
[string length [lindex [lindex $post_dbt 0] 1]]\
[string length $postdatum]
-
error_check_good \
"earlier cursor correctness after $i puts" \
@@ -217,9 +238,15 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
# Close cursors.
puts "\tTest0$tnum.d: Closing cursors."
- for { set i 0 } { $i < $ndups } { incr i } {
+ for { set i 0 } { $i <= $end } { incr i } {
error_check_good "dbc close ($i)" [$dbc($i) close] 0
}
+ unset dbc
+ error_check_good precursor_close [$precursor close] 0
+ error_check_good postcursor_close [$postcursor close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good "db close" [$db close] 0
}
}
diff --git a/bdb/test/test073.tcl b/bdb/test/test073.tcl
index 12a48b0e412..02a0f3b0d19 100644
--- a/bdb/test/test073.tcl
+++ b/bdb/test/test073.tcl
@@ -1,25 +1,27 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test073.tcl,v 11.17 2000/12/11 17:24:55 sue Exp $
+# $Id: test073.tcl,v 11.23 2002/05/22 15:42:59 sue Exp $
#
-# DB Test 73: Test of cursor stability on duplicate pages.
-# Does the following:
-# a. Initialize things by DB->putting ndups dups and
-# setting a reference cursor to point to each.
-# b. c_put ndups dups (and correspondingly expanding
-# the set of reference cursors) after the last one, making sure
-# after each step that all the reference cursors still point to
-# the right item.
-# c. Ditto, but before the first one.
-# d. Ditto, but after each one in sequence first to last.
-# e. Ditto, but after each one in sequence from last to first.
-# occur relative to the new datum)
-# f. Ditto for the two sequence tests, only doing a
-# DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
-# new one.
+# TEST test073
+# TEST Test of cursor stability on duplicate pages.
+# TEST
+# TEST Does the following:
+# TEST a. Initialize things by DB->putting ndups dups and
+# TEST setting a reference cursor to point to each.
+# TEST b. c_put ndups dups (and correspondingly expanding
+# TEST the set of reference cursors) after the last one, making sure
+# TEST after each step that all the reference cursors still point to
+# TEST the right item.
+# TEST c. Ditto, but before the first one.
+# TEST d. Ditto, but after each one in sequence first to last.
+# TEST e. Ditto, but after each one in sequence from last to first.
+# TEST occur relative to the new datum)
+# TEST f. Ditto for the two sequence tests, only doing a
+# TEST DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
+# TEST new one.
proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
source ./include.tcl
global alphabet
@@ -27,6 +29,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
set omethod [convert_method $method]
set args [convert_args $method $args]
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -38,11 +41,16 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
set key "the key"
-
+ set txn ""
puts -nonewline "Test0$tnum $omethod ($args): "
if { [is_record_based $method] || [is_rbtree $method] } {
@@ -60,7 +68,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
append args " -pagesize $pagesize -dup"
set db [eval {berkdb_open \
- -create -truncate -mode 0644} $omethod $args $testfile]
+ -create -mode 0644} $omethod $args $testfile]
error_check_good "db open" [is_valid_db $db] TRUE
# Number of outstanding keys.
@@ -71,17 +79,31 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
for { set i 0 } { $i < $ndups } { incr i } {
set datum [makedatum_t73 $i 0]
- error_check_good "db put ($i)" [$db put $key $datum] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key $datum}]
+ error_check_good "db put ($i)" $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
set is_long($i) 0
incr keys
}
puts "\tTest0$tnum.a.2: Initializing cursor get loop; $keys dups."
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
for { set i 0 } { $i < $keys } { incr i } {
set datum [makedatum_t73 $i 0]
- set dbc($i) [$db cursor]
+ set dbc($i) [eval {$db cursor} $txn]
error_check_good "db cursor ($i)"\
[is_valid_cursor $dbc($i) $db] TRUE
error_check_good "dbc get -get_both ($i)"\
@@ -97,7 +119,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
# to be added (since they start from zero)
set datum [makedatum_t73 $keys 0]
- set curs [$db cursor]
+ set curs [eval {$db cursor} $txn]
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
TRUE
error_check_good "c_put(DB_KEYLAST, $keys)"\
@@ -118,7 +140,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
# to be added (since they start from zero)
set datum [makedatum_t73 $keys 0]
- set curs [$db cursor]
+ set curs [eval {$db cursor} $txn]
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
TRUE
error_check_good "c_put(DB_KEYFIRST, $keys)"\
@@ -138,7 +160,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
set keysnow $keys
for { set i 0 } { $i < $keysnow } { incr i } {
set datum [makedatum_t73 $keys 0]
- set curs [$db cursor]
+ set curs [eval {$db cursor} $txn]
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
TRUE
@@ -162,7 +184,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
for { set i [expr $keys - 1] } { $i >= 0 } { incr i -1 } {
set datum [makedatum_t73 $keys 0]
- set curs [$db cursor]
+ set curs [eval {$db cursor} $txn]
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
TRUE
@@ -190,7 +212,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
for { set i 0 } { $i < $keysnow } { incr i } {
set olddatum [makedatum_t73 $i 0]
set newdatum [makedatum_t73 $i 1]
- set curs [$db cursor]
+ set curs [eval {$db cursor} $txn]
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
TRUE
@@ -215,6 +237,9 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
for { set i 0 } { $i < $keys } { incr i } {
error_check_good "dbc close ($i)" [$dbc($i) close] 0
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good "db close" [$db close] 0
}
diff --git a/bdb/test/test074.tcl b/bdb/test/test074.tcl
index ddc5f16429d..7f620db2d97 100644
--- a/bdb/test/test074.tcl
+++ b/bdb/test/test074.tcl
@@ -1,12 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test074.tcl,v 11.10 2000/08/25 14:21:58 sue Exp $
+# $Id: test074.tcl,v 11.17 2002/05/24 15:24:56 sue Exp $
#
-# DB Test 74: Test of DB_NEXT_NODUP.
-proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} args } {
+# TEST test074
+# TEST Test of DB_NEXT_NODUP.
+proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
source ./include.tcl
global alphabet
global rand_init
@@ -31,6 +32,7 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
puts "\tTest0$tnum.a: No duplicates."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -42,11 +44,17 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
set testfile test0$tnum-nodup.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644} $omethod\
+ set db [eval {berkdb_open -create -mode 0644} $omethod\
$args {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
+ set txn ""
# Insert nitems items.
puts "\t\tTest0$tnum.a.1: Put loop."
@@ -61,14 +69,28 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
set key "key$i"
}
set data "$globaldata$i"
- error_check_good put($i) [$db put $key\
- [chop_data $method $data]] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key \
+ [chop_data $method $data]}]
+ error_check_good put($i) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
puts "\t\tTest0$tnum.a.2: Get($dir)"
# foundarray($i) is set when key number i is found in the database
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
# Initialize foundarray($i) to zero for all $i
@@ -105,17 +127,28 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
}
error_check_good dbc_close(nodup) [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
# If we are a method that doesn't allow dups, verify that
# we get an empty list if we try to use DB_NEXT_DUP
if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
puts "\t\tTest0$tnum.a.5: Check DB_NEXT_DUP for $method."
- set dbc [$db cursor]
+ set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
set dbt [$dbc get $dir]
error_check_good $method:nextdup [$dbc get -nextdup] [list]
error_check_good dbc_close(nextdup) [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
error_check_good db_close(nodup) [$db close] 0
@@ -143,7 +176,7 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
puts "\tTest0$tnum.b: Duplicates ($opt)."
puts "\t\tTest0$tnum.b.1 ($opt): Put loop."
- set db [eval {berkdb_open -create -truncate -mode 0644}\
+ set db [eval {berkdb_open -create -mode 0644}\
$opt $omethod $args {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
@@ -160,8 +193,17 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
set data "$globaldata$j"
}
- error_check_good put($i,$j) \
- [$db put $key $data] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn \
+ [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key $data}]
+ error_check_good put($i,$j) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
}
@@ -175,7 +217,12 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
# within the duplicate set.
puts "\t\tTest0$tnum.b.2 ($opt): Get loop."
set one "001"
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good dbc($opt) [is_valid_cursor $dbc $db] TRUE
for { set i 1 } { $i <= $nitems } { incr i } {
set dbt [$dbc get $dir]
@@ -216,6 +263,9 @@ proc test074 { method {dir -nextnodup} {pagesize 512} {nitems 100} {tnum 74} arg
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
}
diff --git a/bdb/test/test075.tcl b/bdb/test/test075.tcl
index 2aa0e1e2501..540d8f0ed73 100644
--- a/bdb/test/test075.tcl
+++ b/bdb/test/test075.tcl
@@ -1,195 +1,205 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test075.tcl,v 11.9 2000/08/25 14:21:58 sue Exp $
+# $Id: test075.tcl,v 11.21 2002/08/08 15:38:11 bostic Exp $
#
-# DB Test 75 (replacement)
-# Test the DB->rename method.
+# TEST test075
+# TEST Test of DB->rename().
+# TEST (formerly test of DB_TRUNCATE cached page invalidation [#1487])
proc test075 { method { tnum 75 } args } {
+ global encrypt
global errorCode
+ global errorInfo
+
source ./include.tcl
set omethod [convert_method $method]
set args [convert_args $method $args]
puts "Test0$tnum: $method ($args): Test of DB->rename()"
-
- # If we are using an env, then testfile should just be the db name.
- # Otherwise it is the test directory and the name.
+ # If we are using an env, then testfile should just be the
+ # db name. Otherwise it is the test directory and the name.
set eindex [lsearch -exact $args "-env"]
- if { $eindex == -1 } {
- set oldfile $testdir/test0$tnum-old.db
- set newfile $testdir/test0$tnum.db
- set env NULL
- set renargs ""
- } else {
- set oldfile test0$tnum-old.db
- set newfile test0$tnum.db
- # File existence checks won't work in an env, since $oldfile
- # and $newfile won't be in the current working directory.
- # We use this to skip them, and turn our secondary check
- # (opening the dbs and seeing that all is well) into the main
- # one.
+ if { $eindex != -1 } {
+ # If we are using an env, then skip this test.
+ # It needs its own.
incr eindex
set env [lindex $args $eindex]
- set renargs " -env $env"
- }
-
- # Make sure we're starting from a clean slate.
- cleanup $testdir $env
- if { $env == "NULL" } {
- error_check_bad "$oldfile exists" [file exists $oldfile] 1
- error_check_bad "$newfile exists" [file exists $newfile] 1
- }
-
- puts "\tTest0$tnum.a: Create/rename file"
- puts "\t\tTest0$tnum.a.1: create"
- set db [eval {berkdb_open -create -mode 0644} $omethod $args $oldfile]
- error_check_good dbopen [is_valid_db $db] TRUE
-
- if { $env == "NULL" } {
- error_check_bad "$oldfile exists" [file exists $oldfile] 0
- error_check_bad "$newfile exists" [file exists $newfile] 1
- }
-
- # The nature of the key and data are unimportant; use numeric key
- # so record-based methods don't need special treatment.
- set key 1
- set data [pad_data $method data]
-
- error_check_good dbput [$db put $key $data] 0
- error_check_good dbclose [$db close] 0
-
- puts "\t\tTest0$tnum.a.2: rename"
- if { $env == "NULL" } {
- error_check_bad "$oldfile exists" [file exists $oldfile] 0
- error_check_bad "$newfile exists" [file exists $newfile] 1
- }
- error_check_good rename_file [eval {berkdb dbrename}\
- $renargs $oldfile $newfile] 0
- if { $env == "NULL" } {
- error_check_bad "$oldfile exists" [file exists $oldfile] 1
- error_check_bad "$newfile exists" [file exists $newfile] 0
+ puts "Skipping test075 for env $env"
+ return
}
-
- puts "\t\tTest0$tnum.a.3: check"
- # Open again with create to make sure we're not caching or anything
- # silly. In the normal case (no env), we already know the file doesn't
- # exist.
- set odb [eval {berkdb_open -create -mode 0644} $omethod $args $oldfile]
- set ndb [eval {berkdb_open -create -mode 0644} $omethod $args $newfile]
- error_check_good odb_open [is_valid_db $odb] TRUE
- error_check_good ndb_open [is_valid_db $ndb] TRUE
-
- set odbt [$odb get $key]
- set ndbt [$ndb get $key]
-
- # The DBT from the "old" database should be empty, not the "new" one.
- error_check_good odbt_empty [llength $odbt] 0
- error_check_bad ndbt_empty [llength $ndbt] 0
-
- error_check_good ndbt [lindex [lindex $ndbt 0] 1] $data
-
- error_check_good odb_close [$odb close] 0
- error_check_good ndb_close [$ndb close] 0
-
- if { $env != "NULL" } {
- puts "\tTest0$tnum: External environment present; \
- skipping remainder"
+ if { $encrypt != 0 } {
+ puts "Skipping test075 for security"
return
}
- # Now there's both an old and a new. Rename the "new" to the "old"
- # and make sure that fails.
- #
- # XXX Ideally we'd do this test even when there's an external
- # environment, but that env has errpfx/errfile set now. :-(
- puts "\tTest0$tnum.b: Make sure rename fails instead of overwriting"
- set ret [catch {eval {berkdb dbrename} $renargs $newfile $oldfile} res]
- error_check_bad rename_overwrite $ret 0
- error_check_good rename_overwrite_ret [is_substr $errorCode EEXIST] 1
-
- # Verify and then start over from a clean slate.
- verify_dir $testdir "\tTest0$tnum.c: "
- cleanup $testdir $env
- error_check_bad "$oldfile exists" [file exists $oldfile] 1
- error_check_bad "$newfile exists" [file exists $newfile] 1
-
- set oldfile test0$tnum-old.db
- set newfile test0$tnum.db
-
- puts "\tTest0$tnum.d: Create/rename file in environment"
-
- set env [berkdb env -create -home $testdir]
- error_check_good env_open [is_valid_env $env] TRUE
- error_check_bad "$oldfile exists" [file exists $oldfile] 1
- error_check_bad "$newfile exists" [file exists $newfile] 1
-
- puts "\t\tTest0$tnum.d.1: create"
- set db [eval {berkdb_open -create -mode 0644} -env $env\
- $omethod $args $oldfile]
- error_check_good dbopen [is_valid_db $db] TRUE
-
- # We need to make sure that it didn't create/rename into the
- # current directory.
- error_check_bad "$oldfile exists" [file exists $oldfile] 1
- error_check_bad "$newfile exists" [file exists $newfile] 1
- error_check_bad "$testdir/$oldfile exists"\
- [file exists $testdir/$oldfile] 0
- error_check_bad "$testdir/$newfile exists"\
- [file exists $testdir/$newfile] 1
-
- error_check_good dbput [$db put $key $data] 0
- error_check_good dbclose [$db close] 0
-
- puts "\t\tTest0$tnum.d.2: rename"
-
- error_check_good rename_file [berkdb dbrename -env $env\
- $oldfile $newfile] 0
- error_check_bad "$oldfile exists" [file exists $oldfile] 1
- error_check_bad "$newfile exists" [file exists $newfile] 1
- error_check_bad "$testdir/$oldfile exists"\
- [file exists $testdir/$oldfile] 1
- error_check_bad "$testdir/$newfile exists"\
- [file exists $testdir/$newfile] 0
-
- puts "\t\tTest0$tnum.d.3: check"
- # Open again with create to make sure we're not caching or anything
- # silly.
- set odb [eval {berkdb_open -create -mode 0644} -env $env\
- $omethod $args $oldfile]
- set ndb [eval {berkdb_open -create -mode 0644} -env $env\
- $omethod $args $newfile]
- error_check_good odb_open [is_valid_db $odb] TRUE
- error_check_good ndb_open [is_valid_db $ndb] TRUE
-
- set odbt [$odb get $key]
- set ndbt [$ndb get $key]
-
- # The DBT from the "old" database should be empty, not the "new" one.
- error_check_good odbt_empty [llength $odbt] 0
- error_check_bad ndbt_empty [llength $ndbt] 0
-
- error_check_good ndbt [lindex [lindex $ndbt 0] 1] $data
-
- error_check_good odb_close [$odb close] 0
- error_check_good ndb_close [$ndb close] 0
-
- # XXX
- # We need to close and reopen the env since berkdb_open has
- # set its errfile/errpfx, and we can't unset that.
- error_check_good env_close [$env close] 0
- set env [berkdb env -home $testdir]
- error_check_good env_open2 [is_valid_env $env] TRUE
-
- puts "\tTest0$tnum.e:\
- Make sure rename fails instead of overwriting in env"
- set ret [catch {eval {berkdb dbrename} -env $env $newfile $oldfile} res]
- error_check_bad rename_overwrite $ret 0
- error_check_good rename_overwrite_ret [is_substr $errorCode EEXIST] 1
-
- error_check_good env_close [$env close] 0
-
- puts "\tTest0$tnum succeeded."
+ # Define absolute pathnames
+ set curdir [pwd]
+ cd $testdir
+ set fulldir [pwd]
+ cd $curdir
+ set reldir $testdir
+
+ # Set up absolute and relative pathnames for test
+ set paths [list $fulldir $reldir]
+ foreach path $paths {
+ puts "\tTest0$tnum: starting test of $path path"
+ set oldfile $path/test0$tnum-old.db
+ set newfile $path/test0$tnum.db
+ set env NULL
+ set envargs ""
+
+ # Loop through test using the following rename options
+ # 1. no environment, not in transaction
+ # 2. with environment, not in transaction
+ # 3. rename with auto-commit
+ # 4. rename in committed transaction
+ # 5. rename in aborted transaction
+
+ foreach op "noenv env auto commit abort" {
+
+ puts "\tTest0$tnum.a: Create/rename file with $op"
+
+ # Make sure we're starting with a clean slate.
+
+ if { $op == "noenv" } {
+ cleanup $path $env
+ if { $env == "NULL" } {
+ error_check_bad "$oldfile exists" \
+ [file exists $oldfile] 1
+ error_check_bad "$newfile exists" \
+ [file exists $newfile] 1
+ }
+ }
+
+ if { $op == "env" } {
+ env_cleanup $path
+ set env [berkdb_env -create -home $path]
+ set envargs "-env $env"
+ error_check_good env_open [is_valid_env $env] TRUE
+ }
+
+ if { $op == "auto" || $op == "commit" || $op == "abort" } {
+ env_cleanup $path
+ set env [berkdb_env -create -home $path -txn]
+ set envargs "-env $env"
+ error_check_good env_open [is_valid_env $env] TRUE
+ }
+
+ puts "\t\tTest0$tnum.a.1: create"
+ set db [eval {berkdb_open -create -mode 0644} \
+ $omethod $envargs $args $oldfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ if { $env == "NULL" } {
+ error_check_bad \
+ "$oldfile exists" [file exists $oldfile] 0
+ error_check_bad \
+ "$newfile exists" [file exists $newfile] 1
+ }
+
+ # The nature of the key and data are unimportant;
+ # use numeric key to record-based methods don't need
+ # special treatment.
+ set key 1
+ set data [pad_data $method data]
+
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+
+ puts "\t\tTest0$tnum.a.2: rename"
+ if { $env == "NULL" } {
+ error_check_bad \
+ "$oldfile exists" [file exists $oldfile] 0
+ error_check_bad \
+ "$newfile exists" [file exists $newfile] 1
+ }
+
+ # Regular renames use berkdb dbrename but transaction
+ # protected renames must use $env dbrename.
+ if { $op == "noenv" || $op == "env" } {
+ error_check_good rename_file [eval {berkdb dbrename} \
+ $envargs $oldfile $newfile] 0
+ } elseif { $op == "auto" } {
+ error_check_good rename_file [eval {$env dbrename} \
+ -auto_commit $oldfile $newfile] 0
+ } else {
+ # $op is "abort" or "commit"
+ set txn [$env txn]
+ error_check_good rename_file [eval {$env dbrename} \
+ -txn $txn $oldfile $newfile] 0
+ error_check_good txn_$op [$txn $op] 0
+ }
+
+ if { $env == "NULL" } {
+ error_check_bad \
+ "$oldfile exists" [file exists $oldfile] 1
+ error_check_bad \
+ "$newfile exists" [file exists $newfile] 0
+ }
+
+ puts "\t\tTest0$tnum.a.3: check"
+ # Open again with create to make sure we're not caching or
+ # anything silly. In the normal case (no env), we already
+ # know the file doesn't exist.
+ set odb [eval {berkdb_open -create -mode 0644} \
+ $envargs $omethod $args $oldfile]
+ set ndb [eval {berkdb_open -create -mode 0644} \
+ $envargs $omethod $args $newfile]
+ error_check_good odb_open [is_valid_db $odb] TRUE
+ error_check_good ndb_open [is_valid_db $ndb] TRUE
+
+ # The DBT from the "old" database should be empty,
+ # not the "new" one, except in the case of an abort.
+ set odbt [$odb get $key]
+ if { $op == "abort" } {
+ error_check_good odbt_has_data [llength $odbt] 1
+ } else {
+ set ndbt [$ndb get $key]
+ error_check_good odbt_empty [llength $odbt] 0
+ error_check_bad ndbt_empty [llength $ndbt] 0
+ error_check_good ndbt [lindex \
+ [lindex $ndbt 0] 1] $data
+ }
+ error_check_good odb_close [$odb close] 0
+ error_check_good ndb_close [$ndb close] 0
+
+ # Now there's both an old and a new. Rename the
+ # "new" to the "old" and make sure that fails.
+ #
+ # XXX Ideally we'd do this test even when there's
+ # an external environment, but that env has
+ # errpfx/errfile set now. :-(
+ puts "\tTest0$tnum.b: Make sure rename fails\
+ instead of overwriting"
+ if { $env != "NULL" } {
+ error_check_good env_close [$env close] 0
+ set env [berkdb_env_noerr -home $path]
+ error_check_good env_open2 \
+ [is_valid_env $env] TRUE
+ set ret [catch {eval {berkdb dbrename} \
+ -env $env $newfile $oldfile} res]
+ error_check_bad rename_overwrite $ret 0
+ error_check_good rename_overwrite_ret \
+ [is_substr $errorCode EEXIST] 1
+ }
+
+ # Verify and then start over from a clean slate.
+ verify_dir $path "\tTest0$tnum.c: "
+ cleanup $path $env
+ if { $env != "NULL" } {
+ error_check_good env_close [$env close] 0
+ }
+ if { $env == "NULL" } {
+ error_check_bad "$oldfile exists" \
+ [file exists $oldfile] 1
+ error_check_bad "$newfile exists" \
+ [file exists $newfile] 1
+
+ set oldfile test0$tnum-old.db
+ set newfile test0$tnum.db
+ }
+ }
+ }
}
diff --git a/bdb/test/test076.tcl b/bdb/test/test076.tcl
index 13a919011e4..9f7b1ed2972 100644
--- a/bdb/test/test076.tcl
+++ b/bdb/test/test076.tcl
@@ -1,17 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test076.tcl,v 1.7 2000/08/25 14:21:58 sue Exp $
+# $Id: test076.tcl,v 1.18 2002/07/08 20:16:31 sue Exp $
#
-# DB Test 76: Test creation of many small databases in an env
+# TEST test076
+# TEST Test creation of many small databases in a single environment. [#1528].
proc test076 { method { ndbs 1000 } { tnum 76 } args } {
source ./include.tcl
- set omethod [convert_method $method]
set args [convert_args $method $args]
-
+ set encargs ""
+ set args [split_encargs $args encargs]
+ set omethod [convert_method $method]
if { [is_record_based $method] == 1 } {
set key ""
@@ -20,34 +22,53 @@ proc test076 { method { ndbs 1000 } { tnum 76 } args } {
}
set data "datamoredatamoredata"
- puts -nonewline "Test0$tnum $method ($args): "
- puts -nonewline "Create $ndbs"
- puts " small databases in one env."
-
# Create an env if we weren't passed one.
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
if { $eindex == -1 } {
set deleteenv 1
- set env [eval {berkdb env -create -home} $testdir \
- {-cachesize {0 102400 1}}]
+ env_cleanup $testdir
+ set env [eval {berkdb_env -create -home} $testdir $encargs]
error_check_good env [is_valid_env $env] TRUE
set args "$args -env $env"
} else {
set deleteenv 0
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ if { $ndbs == 1000 } {
+ set ndbs 100
+ }
+ }
+ set testdir [get_home $env]
}
+ puts -nonewline "Test0$tnum $method ($args): "
+ puts -nonewline "Create $ndbs"
+ puts " small databases in one env."
+
cleanup $testdir $env
+ set txn ""
for { set i 1 } { $i <= $ndbs } { incr i } {
set testfile test0$tnum.$i.db
- set db [eval {berkdb_open -create -truncate -mode 0644}\
+ set db [eval {berkdb_open -create -mode 0644}\
$args $omethod $testfile]
error_check_good db_open($i) [is_valid_db $db] TRUE
- error_check_good db_put($i) [$db put $key$i \
- [chop_data $method $data$i]] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key$i \
+ [chop_data $method $data$i]}]
+ error_check_good db_put($i) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close($i) [$db close] 0
}
diff --git a/bdb/test/test077.tcl b/bdb/test/test077.tcl
index 47248a309b8..99cf432af20 100644
--- a/bdb/test/test077.tcl
+++ b/bdb/test/test077.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test077.tcl,v 1.4 2000/08/25 14:21:58 sue Exp $
+# $Id: test077.tcl,v 1.10 2002/05/24 15:24:57 sue Exp $
#
-# DB Test 77: Test of DB_GET_RECNO [#1206].
+# TEST test077
+# TEST Test of DB_GET_RECNO [#1206].
proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
source ./include.tcl
global alphabet
@@ -22,6 +23,7 @@ proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
set data $alphabet
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
if { $eindex == -1 } {
set testfile $testdir/test0$tnum.db
@@ -30,23 +32,43 @@ proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644\
+ set db [eval {berkdb_open -create -mode 0644\
-pagesize $pagesize} $omethod $args {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
puts "\tTest0$tnum.a: Populating database."
+ set txn ""
for { set i 1 } { $i <= $nkeys } { incr i } {
set key [format %5d $i]
- error_check_good db_put($key) [$db put $key $data] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$key $data}]
+ error_check_good db_put($key) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
puts "\tTest0$tnum.b: Verifying record numbers."
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good dbc_open [is_valid_cursor $dbc $db] TRUE
set i 1
@@ -64,5 +86,8 @@ proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
diff --git a/bdb/test/test078.tcl b/bdb/test/test078.tcl
index 9642096faf9..45a1d46466e 100644
--- a/bdb/test/test078.tcl
+++ b/bdb/test/test078.tcl
@@ -1,11 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test078.tcl,v 1.9 2000/12/11 17:24:55 sue Exp $
+# $Id: test078.tcl,v 1.18 2002/06/20 19:01:02 sue Exp $
#
-# DB Test 78: Test of DBC->c_count(). [#303]
+# TEST test078
+# TEST Test of DBC->c_count(). [#303]
proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
source ./include.tcl
global alphabet rand_init
@@ -17,14 +18,23 @@ proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
berkdb srand $rand_init
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ }
+
if { $eindex == -1 } {
- set testfile $testdir/test0$tnum.db
+ set testfile $testdir/test0$tnum-a.db
set env NULL
} else {
- set testfile test0$tnum.db
- incr eindex
+ set testfile test0$tnum-a.db
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
cleanup $testdir $env
@@ -35,13 +45,23 @@ proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
return
}
- set db [eval {berkdb_open -create -truncate -mode 0644\
+ set db [eval {berkdb_open -create -mode 0644\
-pagesize $pagesize} $omethod $args {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
+ set txn ""
for { set i 1 } { $i <= $nkeys } { incr i } {
- error_check_good put.a($i) [$db put $i\
- [pad_data $method $alphabet$i]] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$i\
+ [pad_data $method $alphabet$i]}]
+ error_check_good put.a($i) $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good count.a [$db count $i] 1
}
error_check_good db_close.a [$db close] 0
@@ -56,18 +76,38 @@ proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
set letter [lindex $tuple 0]
set dupopt [lindex $tuple 2]
+ if { $eindex == -1 } {
+ set testfile $testdir/test0$tnum-b.db
+ set env NULL
+ } else {
+ set testfile test0$tnum-b.db
+ set env [lindex $args $eindex]
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+
puts "\tTest0$tnum.$letter: Duplicates ([lindex $tuple 1])."
puts "\t\tTest0$tnum.$letter.1: Populating database."
- set db [eval {berkdb_open -create -truncate -mode 0644\
+ set db [eval {berkdb_open -create -mode 0644\
-pagesize $pagesize} $dupopt $omethod $args {$testfile}]
error_check_good db_open [is_valid_db $db] TRUE
for { set i 1 } { $i <= $nkeys } { incr i } {
for { set j 0 } { $j < $i } { incr j } {
- error_check_good put.$letter,$i [$db put $i\
- [pad_data $method $j$alphabet]] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn \
+ [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {$i\
+ [pad_data $method $j$alphabet]}]
+ error_check_good put.$letter,$i $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
}
diff --git a/bdb/test/test079.tcl b/bdb/test/test079.tcl
index fe7b978a3dd..70fd4e05090 100644
--- a/bdb/test/test079.tcl
+++ b/bdb/test/test079.tcl
@@ -1,14 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test079.tcl,v 11.5 2000/11/16 23:56:18 ubell Exp $
+# $Id: test079.tcl,v 11.8 2002/01/11 15:53:54 bostic Exp $
#
-# DB Test 79 {access method}
-# Check that delete operations work in large btrees. 10000 entries and
-# a pagesize of 512 push this out to a four-level btree, with a small fraction
-# of the entries going on overflow pages.
+# TEST test079
+# TEST Test of deletes in large trees. (test006 w/ sm. pagesize).
+# TEST
+# TEST Check that delete operations work in large btrees. 10000 entries
+# TEST and a pagesize of 512 push this out to a four-level btree, with a
+# TEST small fraction of the entries going on overflow pages.
proc test079 { method {nentries 10000} {pagesize 512} {tnum 79} args} {
if { [ is_queueext $method ] == 1 } {
set method "queue";
diff --git a/bdb/test/test080.tcl b/bdb/test/test080.tcl
index 02a6a7242cd..9f649496f68 100644
--- a/bdb/test/test080.tcl
+++ b/bdb/test/test080.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test080.tcl,v 11.7 2000/10/19 23:15:22 ubell Exp $
+# $Id: test080.tcl,v 11.16 2002/08/08 15:38:12 bostic Exp $
#
-# DB Test 80 {access method}
-# Test of dbremove
+# TEST test080
+# TEST Test of DB->remove()
proc test080 { method {tnum 80} args } {
source ./include.tcl
@@ -15,27 +15,112 @@ proc test080 { method {tnum 80} args } {
puts "Test0$tnum: Test of DB->remove()"
+ # Determine full path
+ set curdir [pwd]
+ cd $testdir
+ set fulldir [pwd]
+ cd $curdir
+ # Test both relative and absolute path
+ set paths [list $fulldir $testdir]
+
+ # If we are using an env, then skip this test.
+ # It needs its own.
set eindex [lsearch -exact $args "-env"]
- if { $eindex != -1 } {
- puts "\tTest0$tnum: Skipping in the presence of an environment"
+ set encargs ""
+ set args [split_encargs $args encargs]
+ if { $encargs != ""} {
+ puts "Skipping test080 for security"
return
}
- cleanup $testdir NULL
-
- set testfile $testdir/test0$tnum.db
- set db [eval {berkdb_open -create -truncate -mode 0644} $omethod \
- $args {$testfile}]
- error_check_good db_open [is_valid_db $db] TRUE
- for {set i 1} { $i < 1000 } {incr i} {
- $db put $i $i
+ if { $eindex != -1 } {
+ incr eindex
+ set e [lindex $args $eindex]
+ puts "Skipping test080 for env $e"
+ return
}
- error_check_good db_close [$db close] 0
- error_check_good file_exists_before [file exists $testfile] 1
+ foreach path $paths {
+
+ set dbfile test0$tnum.db
+ set testfile $path/$dbfile
+
+ # Loop through test using the following remove options
+ # 1. no environment, not in transaction
+ # 2. with environment, not in transaction
+ # 3. rename with auto-commit
+ # 4. rename in committed transaction
+ # 5. rename in aborted transaction
+
+ foreach op "noenv env auto commit abort" {
- error_check_good db_remove [berkdb dbremove $testfile] 0
- error_check_good file_exists_after [file exists $testfile] 0
+ # Make sure we're starting with a clean slate.
+ env_cleanup $testdir
+ if { $op == "noenv" } {
+ set dbfile $testfile
+ set e NULL
+ set envargs ""
+ } else {
+ if { $op == "env" } {
+ set largs ""
+ } else {
+ set largs " -txn"
+ }
+ set e [eval {berkdb_env -create -home $path} $largs]
+ set envargs "-env $e"
+ error_check_good env_open [is_valid_env $e] TRUE
+ }
- puts "\tTest0$tnum succeeded."
+ puts "\tTest0$tnum: dbremove with $op in $path"
+ puts "\tTest0$tnum.a.1: Create file"
+ set db [eval {berkdb_open -create -mode 0644} $omethod \
+ $envargs $args {$dbfile}]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ # The nature of the key and data are unimportant;
+ # use numeric key to record-based methods don't need
+ # special treatment.
+ set key 1
+ set data [pad_data $method data]
+
+ error_check_good dbput [$db put $key $data] 0
+ error_check_good dbclose [$db close] 0
+ error_check_good file_exists_before \
+ [file exists $testfile] 1
+
+ # Use berkdb dbremove for non-transactional tests
+ # and $env dbremove for transactional tests
+ puts "\tTest0$tnum.a.2: Remove file"
+ if { $op == "noenv" || $op == "env" } {
+ error_check_good remove_$op \
+ [eval {berkdb dbremove} $envargs $dbfile] 0
+ } elseif { $op == "auto" } {
+ error_check_good remove_$op \
+ [eval {$e dbremove} -auto_commit $dbfile] 0
+ } else {
+ # $op is "abort" or "commit"
+ set txn [$e txn]
+ error_check_good remove_$op \
+ [eval {$e dbremove} -txn $txn $dbfile] 0
+ error_check_good txn_$op [$txn $op] 0
+ }
+
+ puts "\tTest0$tnum.a.3: Check that file is gone"
+ # File should now be gone, except in the case of an abort.
+ if { $op != "abort" } {
+ error_check_good exists_after \
+ [file exists $testfile] 0
+ } else {
+ error_check_good exists_after \
+ [file exists $testfile] 1
+ }
+
+ if { $e != "NULL" } {
+ error_check_good env_close [$e close] 0
+ }
+
+ set dbfile test0$tnum-old.db
+ set testfile $path/$dbfile
+ }
+ }
}
diff --git a/bdb/test/test081.tcl b/bdb/test/test081.tcl
index 44e708c5d49..37c2b44ac33 100644
--- a/bdb/test/test081.tcl
+++ b/bdb/test/test081.tcl
@@ -1,14 +1,13 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test081.tcl,v 11.3 2000/03/01 15:13:59 krinsky Exp $
-#
-# Test 81.
-# Test off-page duplicates and overflow pages together with
-# very large keys (key/data as file contents).
+# $Id: test081.tcl,v 11.6 2002/01/11 15:53:55 bostic Exp $
#
+# TEST test081
+# TEST Test off-page duplicates and overflow pages together with
+# TEST very large keys (key/data as file contents).
proc test081 { method {ndups 13} {tnum 81} args} {
source ./include.tcl
diff --git a/bdb/test/test082.tcl b/bdb/test/test082.tcl
index e8bd4f975dd..e8c1fa45a92 100644
--- a/bdb/test/test082.tcl
+++ b/bdb/test/test082.tcl
@@ -1,15 +1,14 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test082.tcl,v 11.1 2000/04/30 05:05:26 krinsky Exp $
+# $Id: test082.tcl,v 11.5 2002/01/11 15:53:55 bostic Exp $
#
-# Test 82.
-# Test of DB_PREV_NODUP
-proc test082 { method {dir -prevnodup} {pagesize 512} {nitems 100}\
- {tnum 82} args} {
+# TEST test082
+# TEST Test of DB_PREV_NODUP (uses test074).
+proc test082 { method {dir -prevnodup} {nitems 100} {tnum 82} args} {
source ./include.tcl
- eval {test074 $method $dir $pagesize $nitems $tnum} $args
+ eval {test074 $method $dir $nitems $tnum} $args
}
diff --git a/bdb/test/test083.tcl b/bdb/test/test083.tcl
index 7565a5a74f5..e4168ee1c43 100644
--- a/bdb/test/test083.tcl
+++ b/bdb/test/test083.tcl
@@ -1,12 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test083.tcl,v 11.6 2000/12/11 17:24:55 sue Exp $
+# $Id: test083.tcl,v 11.13 2002/06/24 14:06:38 sue Exp $
#
-# Test 83.
-# Test of DB->key_range
+# TEST test083
+# TEST Test of DB->key_range.
proc test083 { method {pgsz 512} {maxitems 5000} {step 2} args} {
source ./include.tcl
set omethod [convert_method $method]
@@ -25,6 +25,7 @@ proc test083 { method {pgsz 512} {maxitems 5000} {step 2} args} {
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
if { $eindex == -1 } {
set testfile $testdir/test083.db
@@ -33,6 +34,11 @@ proc test083 { method {pgsz 512} {maxitems 5000} {step 2} args} {
set testfile test083.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
# We assume that numbers will be at most six digits wide
@@ -45,19 +51,22 @@ proc test083 { method {pgsz 512} {maxitems 5000} {step 2} args} {
{ set nitems [expr $nitems * $step] } {
puts "\tTest083.a: Opening new database"
+ if { $env != "NULL"} {
+ set testdir [get_home $env]
+ }
cleanup $testdir $env
- set db [eval {berkdb_open -create -truncate -mode 0644} \
+ set db [eval {berkdb_open -create -mode 0644} \
-pagesize $pgsz $omethod $args $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
- t83_build $db $nitems
- t83_test $db $nitems
+ t83_build $db $nitems $env $txnenv
+ t83_test $db $nitems $env $txnenv
error_check_good db_close [$db close] 0
}
}
-proc t83_build { db nitems } {
+proc t83_build { db nitems env txnenv } {
source ./include.tcl
puts "\tTest083.b: Populating database with $nitems keys"
@@ -73,24 +82,38 @@ proc t83_build { db nitems } {
# just skip the randomization step.
#puts "\t\tTest083.b.2: Randomizing key list"
#set keylist [randomize_list $keylist]
-
#puts "\t\tTest083.b.3: Populating database with randomized keys"
puts "\t\tTest083.b.2: Populating database"
set data [repeat . 50]
-
+ set txn ""
foreach keynum $keylist {
- error_check_good db_put [$db put key[format %6d $keynum] \
- $data] 0
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {key[format %6d $keynum] $data}]
+ error_check_good db_put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
}
-proc t83_test { db nitems } {
+proc t83_test { db nitems env txnenv } {
# Look at the first key, then at keys about 1/4, 1/2, 3/4, and
# all the way through the database. Make sure the key_ranges
# aren't off by more than 10%.
- set dbc [$db cursor]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ } else {
+ set txn ""
+ }
+ set dbc [eval {$db cursor} $txn]
error_check_good dbc [is_valid_cursor $dbc $db] TRUE
puts "\tTest083.c: Verifying ranges..."
@@ -129,6 +152,9 @@ proc t83_test { db nitems } {
}
error_check_good dbc_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
proc roughly_equal { a b tol } {
diff --git a/bdb/test/test084.tcl b/bdb/test/test084.tcl
index 0efd0d17c00..89bc13978b0 100644
--- a/bdb/test/test084.tcl
+++ b/bdb/test/test084.tcl
@@ -1,16 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test084.tcl,v 11.6 2000/12/11 17:24:55 sue Exp $
-#
-# Test 84.
-# Basic sanity test (test001) with large (64K) pages.
+# $Id: test084.tcl,v 11.11 2002/07/13 18:09:14 margo Exp $
#
+# TEST test084
+# TEST Basic sanity test (test001) with large (64K) pages.
proc test084 { method {nentries 10000} {tnum 84} {pagesize 65536} args} {
source ./include.tcl
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -22,6 +22,11 @@ proc test084 { method {nentries 10000} {tnum 84} {pagesize 65536} args} {
set testfile test0$tnum-empty.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set pgindex [lsearch -exact $args "-pagesize"]
@@ -34,7 +39,7 @@ proc test084 { method {nentries 10000} {tnum 84} {pagesize 65536} args} {
set args "-pagesize $pagesize $args"
- eval {test001 $method $nentries 0 $tnum} $args
+ eval {test001 $method $nentries 0 $tnum 0} $args
set omethod [convert_method $method]
set args [convert_args $method $args]
diff --git a/bdb/test/test085.tcl b/bdb/test/test085.tcl
index 09134a00f65..b0412d6fe68 100644
--- a/bdb/test/test085.tcl
+++ b/bdb/test/test085.tcl
@@ -1,20 +1,23 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test085.tcl,v 1.4 2000/12/11 17:24:55 sue Exp $
+# $Id: test085.tcl,v 1.13 2002/08/08 17:23:46 sandstro Exp $
#
-# DB Test 85: Test of cursor behavior when a cursor is pointing to a deleted
-# btree key which then has duplicates added.
+# TEST test085
+# TEST Test of cursor behavior when a cursor is pointing to a deleted
+# TEST btree key which then has duplicates added. [#2473]
proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
source ./include.tcl
global alphabet
set omethod [convert_method $method]
set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
-
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -26,6 +29,11 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
set testfile test0$tnum.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set pgindex [lsearch -exact $args "-pagesize"]
@@ -45,6 +53,7 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
set predatum "1234567890"
set datum $alphabet
set postdatum "0987654321"
+ set txn ""
append args " -pagesize $pagesize -dup"
@@ -61,8 +70,8 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
# Repeat the test with both on-page and off-page numbers of dups.
foreach ndups "$onp $offp" {
- # Put operations we want to test on a cursor set to the
- # deleted item, the key to use with them, and what should
+ # Put operations we want to test on a cursor set to the
+ # deleted item, the key to use with them, and what should
# come before and after them given a placement of
# the deleted item at the beginning or end of the dupset.
set final [expr $ndups - 1]
@@ -100,15 +109,22 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
{{-prevnodup} "" $prekey $predatum end}
}
+ set txn ""
foreach pair $getops {
set op [lindex $pair 0]
puts "\tTest0$tnum: Get ($op) with $ndups duplicates,\
cursor at the [lindex $pair 4]."
set db [eval {berkdb_open -create \
- -truncate -mode 0644} $omethod $args $testfile]
+ -mode 0644} $omethod $encargs $args $testfile]
error_check_good "db open" [is_valid_db $db] TRUE
- set dbc [test085_setup $db]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn \
+ [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [test085_setup $db $txn]
set beginning [expr [string compare \
[lindex $pair 4] "beginning"] == 0]
@@ -116,9 +132,10 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
for { set i 0 } { $i < $ndups } { incr i } {
if { $beginning } {
error_check_good db_put($i) \
- [$db put $key [test085_ddatum $i]] 0
+ [eval {$db put} $txn \
+ {$key [test085_ddatum $i]}] 0
} else {
- set c [$db cursor]
+ set c [eval {$db cursor} $txn]
set j [expr $ndups - $i - 1]
error_check_good db_cursor($j) \
[is_valid_cursor $c $db] TRUE
@@ -128,14 +145,14 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
error_check_good c_close [$c close] 0
}
}
-
+
set gargs [lindex $pair 1]
set ekey ""
set edata ""
eval set ekey [lindex $pair 2]
eval set edata [lindex $pair 3]
- set dbt [eval $dbc get $op $gargs]
+ set dbt [eval $dbc get $op $gargs]
if { [string compare $ekey EMPTYLIST] == 0 } {
error_check_good dbt($op,$ndups) \
[llength $dbt] 0
@@ -144,8 +161,27 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
[list [list $ekey $edata]]
}
error_check_good "dbc close" [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good "db close" [$db close] 0
verify_dir $testdir "\t\t"
+
+ # Remove testfile so we can do without truncate flag.
+ # This is okay because we've already done verify and
+ # dump/load.
+ if { $env == "NULL" } {
+ set ret [eval {berkdb dbremove} \
+ $encargs $testfile]
+ } elseif { $txnenv == 1 } {
+ set ret [eval "$env dbremove" \
+ -auto_commit $encargs $testfile]
+ } else {
+ set ret [eval {berkdb dbremove} \
+ -env $env $encargs $testfile]
+ }
+ error_check_good dbremove $ret 0
+
}
foreach pair $putops {
@@ -154,21 +190,27 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
puts "\tTest0$tnum: Put ($op) with $ndups duplicates,\
cursor at the [lindex $pair 4]."
set db [eval {berkdb_open -create \
- -truncate -mode 0644} $omethod $args $testfile]
+ -mode 0644} $omethod $args $encargs $testfile]
error_check_good "db open" [is_valid_db $db] TRUE
set beginning [expr [string compare \
[lindex $pair 4] "beginning"] == 0]
-
- set dbc [test085_setup $db]
+
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [test085_setup $db $txn]
# Put duplicates.
for { set i 0 } { $i < $ndups } { incr i } {
if { $beginning } {
error_check_good db_put($i) \
- [$db put $key [test085_ddatum $i]] 0
+ [eval {$db put} $txn \
+ {$key [test085_ddatum $i]}] 0
} else {
- set c [$db cursor]
+ set c [eval {$db cursor} $txn]
set j [expr $ndups - $i - 1]
error_check_good db_cursor($j) \
[is_valid_cursor $c $db] TRUE
@@ -180,17 +222,17 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
}
# Set up cursors for stability test.
- set pre_dbc [$db cursor]
+ set pre_dbc [eval {$db cursor} $txn]
error_check_good pre_set [$pre_dbc get -set $prekey] \
[list [list $prekey $predatum]]
- set post_dbc [$db cursor]
+ set post_dbc [eval {$db cursor} $txn]
error_check_good post_set [$post_dbc get -set $postkey]\
[list [list $postkey $postdatum]]
- set first_dbc [$db cursor]
+ set first_dbc [eval {$db cursor} $txn]
error_check_good first_set \
[$first_dbc get -get_both $key [test085_ddatum 0]] \
[list [list $key [test085_ddatum 0]]]
- set last_dbc [$db cursor]
+ set last_dbc [eval {$db cursor} $txn]
error_check_good last_set \
[$last_dbc get -get_both $key [test085_ddatum \
[expr $ndups - 1]]] \
@@ -227,23 +269,39 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
[$last_dbc get -current] \
[list [list $key [test085_ddatum [expr $ndups -1]]]]
-
foreach c "$pre_dbc $post_dbc $first_dbc $last_dbc" {
error_check_good ${c}_close [$c close] 0
}
error_check_good "dbc close" [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good "db close" [$db close] 0
- verify_dir $testdir "\t\t"
+ verify_dir $testdir "\t\t"
+
+ # Remove testfile so we can do without truncate flag.
+ # This is okay because we've already done verify and
+ # dump/load.
+ if { $env == "NULL" } {
+ set ret [eval {berkdb dbremove} \
+ $encargs $testfile]
+ } elseif { $txnenv == 1 } {
+ set ret [eval "$env dbremove" \
+ -auto_commit $encargs $testfile]
+ } else {
+ set ret [eval {berkdb dbremove} \
+ -env $env $encargs $testfile]
+ }
+ error_check_good dbremove $ret 0
}
}
}
-
-# Set up the test database; put $prekey, $key, and $postkey with their
+# Set up the test database; put $prekey, $key, and $postkey with their
# respective data, and then delete $key with a new cursor. Return that
# cursor, still pointing to the deleted item.
-proc test085_setup { db } {
+proc test085_setup { db txn } {
upvar key key
upvar prekey prekey
upvar postkey postkey
@@ -251,13 +309,13 @@ proc test085_setup { db } {
upvar postdatum postdatum
# no one else should ever see this one!
- set datum "bbbbbbbb"
+ set datum "bbbbbbbb"
- error_check_good pre_put [$db put $prekey $predatum] 0
- error_check_good main_put [$db put $key $datum] 0
- error_check_good post_put [$db put $postkey $postdatum] 0
+ error_check_good pre_put [eval {$db put} $txn {$prekey $predatum}] 0
+ error_check_good main_put [eval {$db put} $txn {$key $datum}] 0
+ error_check_good post_put [eval {$db put} $txn {$postkey $postdatum}] 0
- set dbc [$db cursor]
+ set dbc [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
error_check_good dbc_getset [$dbc get -get_both $key $datum] \
diff --git a/bdb/test/test086.tcl b/bdb/test/test086.tcl
index dc30de8ec37..e15aa1d8bb9 100644
--- a/bdb/test/test086.tcl
+++ b/bdb/test/test086.tcl
@@ -1,16 +1,21 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test086.tcl,v 11.2 2000/08/25 14:21:58 sue Exp $
-
-# Test086: Cursor stability across btree splits w/ subtransaction abort [#2373].
+# $Id: test086.tcl,v 11.9 2002/08/06 17:58:00 sandstro Exp $
+#
+# TEST test086
+# TEST Test of cursor stability across btree splits/rsplits with
+# TEST subtransaction aborts (a variant of test048). [#2373]
proc test086 { method args } {
global errorCode
source ./include.tcl
set tstn 086
+ set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
if { [is_btree $method] != 1 } {
puts "Test$tstn skipping for method $method."
@@ -40,11 +45,11 @@ proc test086 { method args } {
set t1 $testdir/t1
env_cleanup $testdir
- set env [berkdb env -create -home $testdir -txn]
+ set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
error_check_good berkdb_env [is_valid_env $env] TRUE
puts "\tTest$tstn.a: Create $method database."
- set oflags "-create -env $env -mode 0644 $args $method"
+ set oflags "-auto_commit -create -env $env -mode 0644 $args $method"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -97,7 +102,6 @@ proc test086 { method args } {
puts "\tTest$tstn.e: Abort."
error_check_good ctxn_abort [$ctxn abort] 0
-
puts "\tTest$tstn.f: Check and see that cursors maintained reference."
for {set i 0} { $i < $nkeys } {incr i} {
set ret [$dbc_set($i) get -current]
@@ -107,7 +111,7 @@ proc test086 { method args } {
error_check_good dbc$i:get(match) $ret $ret2
}
- # Put (and this time keep) the keys that caused the split.
+ # Put (and this time keep) the keys that caused the split.
# We'll delete them to test reverse splits.
puts "\tTest$tstn.g: Put back added keys."
for {set i $nkeys} { $i < $mkeys } { incr i } {
diff --git a/bdb/test/test087.tcl b/bdb/test/test087.tcl
index 7096e6c1cb9..089664a0002 100644
--- a/bdb/test/test087.tcl
+++ b/bdb/test/test087.tcl
@@ -1,31 +1,38 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test087.tcl,v 11.6 2000/12/11 17:24:55 sue Exp $
+# $Id: test087.tcl,v 11.14 2002/07/08 20:16:31 sue Exp $
#
-# DB Test 87: Test of cursor stability on duplicate pages w/aborts.
-# Does the following:
-# a. Initialize things by DB->putting ndups dups and
-# setting a reference cursor to point to each.
-# b. c_put ndups dups (and correspondingly expanding
-# the set of reference cursors) after the last one, making sure
-# after each step that all the reference cursors still point to
-# the right item.
-# c. Ditto, but before the first one.
-# d. Ditto, but after each one in sequence first to last.
-# e. Ditto, but after each one in sequence from last to first.
-# occur relative to the new datum)
-# f. Ditto for the two sequence tests, only doing a
-# DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
-# new one.
+# TEST test087
+# TEST Test of cursor stability when converting to and modifying
+# TEST off-page duplicate pages with subtransaction aborts. [#2373]
+# TEST
+# TEST Does the following:
+# TEST a. Initialize things by DB->putting ndups dups and
+# TEST setting a reference cursor to point to each. Do each put twice,
+# TEST first aborting, then committing, so we're sure to abort the move
+# TEST to off-page dups at some point.
+# TEST b. c_put ndups dups (and correspondingly expanding
+# TEST the set of reference cursors) after the last one, making sure
+# TEST after each step that all the reference cursors still point to
+# TEST the right item.
+# TEST c. Ditto, but before the first one.
+# TEST d. Ditto, but after each one in sequence first to last.
+# TEST e. Ditto, but after each one in sequence from last to first.
+# TEST occur relative to the new datum)
+# TEST f. Ditto for the two sequence tests, only doing a
+# TEST DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
+# TEST new one.
proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
source ./include.tcl
global alphabet
- set omethod [convert_method $method]
set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
+ set omethod [convert_method $method]
puts "Test0$tnum $omethod ($args): "
set eindex [lsearch -exact $args "-env"]
@@ -52,34 +59,38 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
puts "Cursor stability on dup. pages w/ aborts."
}
- set env [berkdb env -create -home $testdir -txn]
+ set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
error_check_good env_create [is_valid_env $env] TRUE
- set db [eval {berkdb_open -env $env \
- -create -mode 0644} $omethod $args $testfile]
+ set db [eval {berkdb_open -auto_commit \
+ -create -env $env -mode 0644} $omethod $args $testfile]
error_check_good "db open" [is_valid_db $db] TRUE
# Number of outstanding keys.
- set keys 0
+ set keys $ndups
- puts "\tTest0$tnum.a.1: Initializing put loop; $ndups dups, short data."
+ puts "\tTest0$tnum.a: put/abort/put/commit loop;\
+ $ndups dups, short data."
set txn [$env txn]
error_check_good txn [is_valid_txn $txn $env] TRUE
for { set i 0 } { $i < $ndups } { incr i } {
set datum [makedatum_t73 $i 0]
- error_check_good "db put ($i)" [$db put -txn $txn $key $datum] 0
+ set ctxn [$env txn -parent $txn]
+ error_check_good ctxn(abort,$i) [is_valid_txn $ctxn $env] TRUE
+ error_check_good "db put/abort ($i)" \
+ [$db put -txn $ctxn $key $datum] 0
+ error_check_good ctxn_abort($i) [$ctxn abort] 0
- set is_long($i) 0
- incr keys
- }
- error_check_good txn_commit [$txn commit] 0
+ verify_t73 is_long dbc [expr $i - 1] $key
- puts "\tTest0$tnum.a.2: Initializing cursor get loop; $keys dups."
- set txn [$env txn]
- error_check_good txn [is_valid_txn $txn $env] TRUE
- for { set i 0 } { $i < $keys } { incr i } {
- set datum [makedatum_t73 $i 0]
+ set ctxn [$env txn -parent $txn]
+ error_check_good ctxn(commit,$i) [is_valid_txn $ctxn $env] TRUE
+ error_check_good "db put/commit ($i)" \
+ [$db put -txn $ctxn $key $datum] 0
+ error_check_good ctxn_commit($i) [$ctxn commit] 0
+
+ set is_long($i) 0
set dbc($i) [$db cursor -txn $txn]
error_check_good "db cursor ($i)"\
@@ -87,6 +98,8 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
error_check_good "dbc get -get_both ($i)"\
[$dbc($i) get -get_both $key $datum]\
[list [list $key $datum]]
+
+ verify_t73 is_long dbc $i $key
}
puts "\tTest0$tnum.b: Cursor put (DB_KEYLAST); $ndups new dups,\
@@ -97,7 +110,6 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
for { set i 0 } { $i < $ndups } { incr i } {
# !!! keys contains the number of the next dup
# to be added (since they start from zero)
-
set datum [makedatum_t73 $keys 0]
set curs [$db cursor -txn $ctxn]
error_check_good "db cursor create" [is_valid_cursor $curs $db]\
@@ -272,7 +284,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
for { set i 0 } { $i < $keys } { incr i } {
error_check_good "dbc close ($i)" [$dbc($i) close] 0
}
- error_check_good txn_commit [$txn commit] 0
error_check_good "db close" [$db close] 0
+ error_check_good txn_commit [$txn commit] 0
error_check_good "env close" [$env close] 0
}
diff --git a/bdb/test/test088.tcl b/bdb/test/test088.tcl
index d7b0f815a00..7065b4cd642 100644
--- a/bdb/test/test088.tcl
+++ b/bdb/test/test088.tcl
@@ -1,17 +1,19 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test088.tcl,v 11.4 2000/12/11 17:24:55 sue Exp $
+# $Id: test088.tcl,v 11.12 2002/08/05 19:23:51 sandstro Exp $
#
-# Test088: Cursor stability across btree splits with very deep trees.
-# (Variant of test048, SR #2514.)
+# TEST test088
+# TEST Test of cursor stability across btree splits with very
+# TEST deep trees (a variant of test048). [#2514]
proc test088 { method args } {
global errorCode alphabet
source ./include.tcl
set tstn 088
+ set args [convert_args $method $args]
if { [is_btree $method] != 1 } {
puts "Test$tstn skipping for method $method."
@@ -33,6 +35,7 @@ proc test088 { method args } {
set flags ""
puts "\tTest$tstn.a: Create $method database."
+ set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
@@ -44,12 +47,18 @@ proc test088 { method args } {
set testfile test$tstn.db
incr eindex
set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ }
+ set testdir [get_home $env]
}
set t1 $testdir/t1
cleanup $testdir $env
- set ps 512
- set oflags "-create -pagesize $ps -truncate -mode 0644 $args $method"
+ set ps 512
+ set txn ""
+ set oflags "-create -pagesize $ps -mode 0644 $args $method"
set db [eval {berkdb_open} $oflags $testfile]
error_check_good dbopen [is_valid_db $db] TRUE
@@ -58,45 +67,62 @@ proc test088 { method args } {
#
puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
for { set i 0 } { $i < $nkeys } { incr i } {
- set ret [$db put ${key}00000$i $data$i]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn {${key}00000$i $data$i}]
error_check_good dbput $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
}
# get db ordering, set cursors
puts "\tTest$tstn.c: Set cursors on each of $nkeys pairs."
+ # if mkeys is above 1000, need to adjust below for lexical order
+ set mkeys 30000
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ set mkeys 300
+ }
for {set i 0; set ret [$db get ${key}00000$i]} {\
$i < $nkeys && [llength $ret] != 0} {\
incr i; set ret [$db get ${key}00000$i]} {
set key_set($i) [lindex [lindex $ret 0] 0]
set data_set($i) [lindex [lindex $ret 0] 1]
- set dbc [$db cursor]
+ set dbc [eval {$db cursor} $txn]
set dbc_set($i) $dbc
error_check_good db_cursor:$i [is_substr $dbc_set($i) $db] 1
set ret [$dbc_set($i) get -set $key_set($i)]
error_check_bad dbc_set($i)_get:set [llength $ret] 0
}
- # if mkeys is above 1000, need to adjust below for lexical order
- set mkeys 30000
puts "\tTest$tstn.d: Add $mkeys pairs to force splits."
for {set i $nkeys} { $i < $mkeys } { incr i } {
if { $i >= 10000 } {
- set ret [$db put ${key}0$i $data$i]
+ set ret [eval {$db put} $txn {${key}0$i $data$i}]
} elseif { $i >= 1000 } {
- set ret [$db put ${key}00$i $data$i]
+ set ret [eval {$db put} $txn {${key}00$i $data$i}]
} elseif { $i >= 100 } {
- set ret [$db put ${key}000$i $data$i]
+ set ret [eval {$db put} $txn {${key}000$i $data$i}]
} elseif { $i >= 10 } {
- set ret [$db put ${key}0000$i $data$i]
+ set ret [eval {$db put} $txn {${key}0000$i $data$i}]
} else {
- set ret [$db put ${key}00000$i $data$i]
+ set ret [eval {$db put} $txn {${key}00000$i $data$i}]
}
error_check_good dbput:more $ret 0
}
puts "\tTest$tstn.e: Make sure splits happened."
- error_check_bad stat:check-split [is_substr [$db stat] \
- "{{Internal pages} 0}"] 1
+ # XXX cannot execute stat in presence of txns and cursors.
+ if { $txnenv == 0 } {
+ error_check_bad stat:check-split [is_substr [$db stat] \
+ "{{Internal pages} 0}"] 1
+ }
puts "\tTest$tstn.f: Check to see that cursors maintained reference."
for {set i 0} { $i < $nkeys } {incr i} {
@@ -110,16 +136,17 @@ proc test088 { method args } {
puts "\tTest$tstn.g: Delete added keys to force reverse splits."
for {set i $nkeys} { $i < $mkeys } { incr i } {
if { $i >= 10000 } {
- error_check_good db_del:$i [$db del ${key}0$i] 0
+ set ret [eval {$db del} $txn {${key}0$i}]
} elseif { $i >= 1000 } {
- error_check_good db_del:$i [$db del ${key}00$i] 0
+ set ret [eval {$db del} $txn {${key}00$i}]
} elseif { $i >= 100 } {
- error_check_good db_del:$i [$db del ${key}000$i] 0
+ set ret [eval {$db del} $txn {${key}000$i}]
} elseif { $i >= 10 } {
- error_check_good db_del:$i [$db del ${key}0000$i] 0
+ set ret [eval {$db del} $txn {${key}0000$i}]
} else {
- error_check_good db_del:$i [$db del ${key}00000$i] 0
+ set ret [eval {$db del} $txn {${key}00000$i}]
}
+ error_check_good dbput:more $ret 0
}
puts "\tTest$tstn.h: Verify cursor reference."
@@ -136,6 +163,9 @@ proc test088 { method args } {
for {set i 0} { $i < $nkeys } {incr i} {
error_check_good dbc_close:$i [$dbc_set($i) close] 0
}
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good dbclose [$db close] 0
puts "\tTest$tstn complete."
diff --git a/bdb/test/test089.tcl b/bdb/test/test089.tcl
new file mode 100644
index 00000000000..d378152f203
--- /dev/null
+++ b/bdb/test/test089.tcl
@@ -0,0 +1,180 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test089.tcl,v 11.2 2002/08/08 15:38:12 bostic Exp $
+#
+# TEST test089
+# TEST Concurrent Data Store test (CDB)
+# TEST
+# TEST Enhanced CDB testing to test off-page dups, cursor dups and
+# TEST cursor operations like c_del then c_get.
+proc test089 { method {nentries 1000} args } {
+ global datastr
+ global encrypt
+ source ./include.tcl
+
+ #
+ # If we are using an env, then skip this test. It needs its own.
+ set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $args $eindex]
+ puts "Test089 skipping for env $env"
+ return
+ }
+ set encargs ""
+ set args [convert_args $method $args]
+ set oargs [split_encargs $args encargs]
+ set omethod [convert_method $method]
+
+ puts "Test089: ($oargs) $method CDB Test cursor/dup operations"
+
+ # Process arguments
+ # Create the database and open the dictionary
+ set testfile test089.db
+ set testfile1 test089a.db
+
+ env_cleanup $testdir
+
+ set env [eval {berkdb_env -create -cdb} $encargs -home $testdir]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ set db [eval {berkdb_open -env $env -create \
+ -mode 0644 $omethod} $oargs {$testfile}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set db1 [eval {berkdb_open -env $env -create \
+ -mode 0644 $omethod} $oargs {$testfile1}]
+ error_check_good dbopen [is_valid_db $db1] TRUE
+
+ set pflags ""
+ set gflags ""
+ set txn ""
+ set count 0
+
+ # Here is the loop where we put each key/data pair
+ puts "\tTest089.a: put loop"
+ set did [open $dict]
+ while { [gets $did str] != -1 && $count < $nentries } {
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ } else {
+ set key $str
+ }
+ set ret [eval {$db put} \
+ $txn $pflags {$key [chop_data $method $datastr]}]
+ error_check_good put:$db $ret 0
+ set ret [eval {$db1 put} \
+ $txn $pflags {$key [chop_data $method $datastr]}]
+ error_check_good put:$db1 $ret 0
+ incr count
+ }
+ close $did
+ error_check_good close:$db [$db close] 0
+ error_check_good close:$db1 [$db1 close] 0
+
+ # Database is created, now set up environment
+
+ # Remove old mpools and Open/create the lock and mpool regions
+ error_check_good env:close:$env [$env close] 0
+ set ret [eval {berkdb envremove} $encargs -home $testdir]
+ error_check_good env_remove $ret 0
+
+ set env [eval {berkdb_env_noerr -create -cdb} $encargs -home $testdir]
+ error_check_good dbenv [is_valid_widget $env env] TRUE
+
+ # This tests the failure found in #1923
+ puts "\tTest089.b: test delete then get"
+
+ set db1 [eval {berkdb_open_noerr -env $env -create \
+ -mode 0644 $omethod} $oargs {$testfile1}]
+ error_check_good dbopen [is_valid_db $db1] TRUE
+
+ set dbc [$db1 cursor -update]
+ error_check_good dbcursor [is_valid_cursor $dbc $db1] TRUE
+
+ for {set kd [$dbc get -first] } { [llength $kd] != 0 } \
+ {set kd [$dbc get -next] } {
+ error_check_good dbcdel [$dbc del] 0
+ }
+ error_check_good dbc_close [$dbc close] 0
+
+ puts "\tTest089.c: CDB cursor dups"
+ set dbc [$db1 cursor -update]
+ error_check_good dbcursor [is_valid_cursor $dbc $db1] TRUE
+ set stat [catch {$dbc dup} ret]
+ error_check_bad wr_cdup_stat $stat 0
+ error_check_good wr_cdup [is_substr $ret \
+ "Cannot duplicate writeable cursor"] 1
+
+ set dbc_ro [$db1 cursor]
+ error_check_good dbcursor [is_valid_cursor $dbc_ro $db1] TRUE
+ set dup_dbc [$dbc_ro dup]
+ error_check_good rd_cdup [is_valid_cursor $dup_dbc $db1] TRUE
+
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good dbc_close [$dbc_ro close] 0
+ error_check_good dbc_close [$dup_dbc close] 0
+ error_check_good db_close [$db1 close] 0
+ error_check_good env_close [$env close] 0
+
+ if { [is_btree $method] != 1 } {
+ puts "Skipping rest of test089 for $method method."
+ return
+ }
+ set pgindex [lsearch -exact $args "-pagesize"]
+ if { $pgindex != -1 } {
+ puts "Skipping rest of test089 for specific pagesizes"
+ return
+ }
+ append oargs " -dup "
+ test089_dup $testdir $encargs $oargs $omethod $nentries
+ append oargs " -dupsort "
+ test089_dup $testdir $encargs $oargs $omethod $nentries
+}
+
+proc test089_dup { testdir encargs oargs method nentries } {
+
+ env_cleanup $testdir
+ set env [eval {berkdb_env -create -cdb} $encargs -home $testdir]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ #
+ # Set pagesize small to generate lots of off-page dups
+ #
+ set page 512
+ set nkeys 5
+ set data "data"
+ set key "test089_key"
+ set testfile test089.db
+ puts "\tTest089.d: CDB ($oargs) off-page dups"
+ set oflags "-env $env -create -mode 0644 $oargs $method"
+ set db [eval {berkdb_open} -pagesize $page $oflags $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ puts "\tTest089.e: Fill page with $nkeys keys, with $nentries dups"
+ for { set k 0 } { $k < $nkeys } { incr k } {
+ for { set i 0 } { $i < $nentries } { incr i } {
+ set ret [$db put $key $i$data$k]
+ error_check_good dbput $ret 0
+ }
+ }
+
+ # Verify we have off-page duplicates
+ set stat [$db stat]
+ error_check_bad stat:offpage [is_substr $stat "{{Internal pages} 0}"] 1
+
+ set dbc [$db cursor -update]
+ error_check_good dbcursor [is_valid_cursor $dbc $db] TRUE
+
+ puts "\tTest089.f: test delete then get of off-page dups"
+ for {set kd [$dbc get -first] } { [llength $kd] != 0 } \
+ {set kd [$dbc get -next] } {
+ error_check_good dbcdel [$dbc del] 0
+ }
+ error_check_good dbc_close [$dbc close] 0
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$env close] 0
+}
diff --git a/bdb/test/test090.tcl b/bdb/test/test090.tcl
index ed6ec9632f5..da90688ffc5 100644
--- a/bdb/test/test090.tcl
+++ b/bdb/test/test090.tcl
@@ -1,20 +1,16 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test090.tcl,v 11.4 2000/12/11 17:24:56 sue Exp $
+# $Id: test090.tcl,v 11.10 2002/08/15 20:55:21 sandstro Exp $
#
-# DB Test 90 {access method}
-# Check for functionality near the end of the queue.
-#
-#
-proc test090 { method {nentries 1000} {txn -txn} {tnum "90"} args} {
+# TEST test090
+# TEST Test for functionality near the end of the queue using test001.
+proc test090 { method {nentries 10000} {txn -txn} {tnum "90"} args} {
if { [is_queueext $method ] == 0 } {
puts "Skipping test0$tnum for $method."
return;
}
- eval {test001 $method $nentries 4294967000 $tnum} $args
- eval {test025 $method $nentries 4294967000 $tnum} $args
- eval {test070 $method 4 2 $nentries WAIT 4294967000 $txn $tnum} $args
+ eval {test001 $method $nentries 4294967000 $tnum 0} $args
}
diff --git a/bdb/test/test091.tcl b/bdb/test/test091.tcl
index 9420b571ce3..cfd2a60ebb5 100644
--- a/bdb/test/test091.tcl
+++ b/bdb/test/test091.tcl
@@ -1,13 +1,12 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: test091.tcl,v 11.4 2000/12/01 04:28:36 ubell Exp $
-#
-# DB Test 91 {access method}
-# Check for CONSUME_WAIT functionality
+# $Id: test091.tcl,v 11.7 2002/01/11 15:53:56 bostic Exp $
#
+# TEST test091
+# TEST Test of DB_CONSUME_WAIT.
proc test091 { method {nconsumers 4} \
{nproducers 2} {nitems 1000} {start 0 } {tnum "91"} args} {
if { [is_queue $method ] == 0 } {
diff --git a/bdb/test/test092.tcl b/bdb/test/test092.tcl
new file mode 100644
index 00000000000..29c1c55a9a9
--- /dev/null
+++ b/bdb/test/test092.tcl
@@ -0,0 +1,241 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test092.tcl,v 11.13 2002/02/22 15:26:28 sandstro Exp $
+#
+# TEST test092
+# TEST Test of DB_DIRTY_READ [#3395]
+# TEST
+# TEST We set up a database with nentries in it. We then open the
+# TEST database read-only twice. One with dirty read and one without.
+# TEST We open the database for writing and update some entries in it.
+# TEST Then read those new entries via db->get (clean and dirty), and
+# TEST via cursors (clean and dirty).
+proc test092 { method {nentries 1000} args } {
+ source ./include.tcl
+ #
+ # If we are using an env, then skip this test. It needs its own.
+ set eindex [lsearch -exact $args "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $args $eindex]
+ puts "Test092 skipping for env $env"
+ return
+ }
+ set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
+ set omethod [convert_method $method]
+
+ puts "Test092: Dirty Read Test $method $nentries"
+
+ # Create the database and open the dictionary
+ set testfile test092.db
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+
+ env_cleanup $testdir
+
+ set lmax [expr $nentries * 2]
+ set lomax [expr $nentries * 2]
+ set env [eval {berkdb_env -create -txn} $encargs -home $testdir \
+ -lock_max_locks $lmax -lock_max_objects $lomax]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ set db [eval {berkdb_open -env $env -create \
+ -mode 0644 $omethod} $args {$testfile}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ # Here is the loop where we put each key/data pair.
+ # Key is entry, data is entry also.
+ puts "\tTest092.a: put loop"
+ set count 0
+ set did [open $dict]
+ while { [gets $did str] != -1 && $count < $nentries } {
+ if { [is_record_based $method] == 1 } {
+ global kvals
+
+ set key [expr $count + 1]
+ set kvals($key) [pad_data $method $str]
+ } else {
+ set key $str
+ }
+ set ret [eval {$db put} {$key [chop_data $method $str]}]
+ error_check_good put:$db $ret 0
+ incr count
+ }
+ close $did
+ error_check_good close:$db [$db close] 0
+
+ puts "\tTest092.b: Opening all the handles"
+ #
+ # Open all of our handles.
+ # We need:
+ # 1. Our main txn (t).
+ # 2. A txn that can read dirty data (tdr).
+ # 3. A db handle for writing via txn (dbtxn).
+ # 4. A db handle for clean data (dbcl).
+ # 5. A db handle for dirty data (dbdr).
+ # 6. A cursor handle for dirty txn data (clean db handle using
+ # the dirty txn handle on the cursor call) (dbccl1).
+ # 7. A cursor handle for dirty data (dirty on get call) (dbcdr0).
+ # 8. A cursor handle for dirty data (dirty on cursor call) (dbcdr1).
+ set t [$env txn]
+ error_check_good txnbegin [is_valid_txn $t $env] TRUE
+
+ set tdr [$env txn -dirty]
+ error_check_good txnbegin:dr [is_valid_txn $tdr $env] TRUE
+ set dbtxn [eval {berkdb_open -auto_commit -env $env -dirty \
+ -mode 0644 $omethod} {$testfile}]
+ error_check_good dbopen:dbtxn [is_valid_db $dbtxn] TRUE
+
+ set dbcl [eval {berkdb_open -auto_commit -env $env \
+ -rdonly -mode 0644 $omethod} {$testfile}]
+ error_check_good dbopen:dbcl [is_valid_db $dbcl] TRUE
+
+ set dbdr [eval {berkdb_open -auto_commit -env $env -dirty \
+ -rdonly -mode 0644 $omethod} {$testfile}]
+ error_check_good dbopen:dbdr [is_valid_db $dbdr] TRUE
+
+ set dbccl [$dbcl cursor -txn $tdr]
+ error_check_good dbcurs:dbcl [is_valid_cursor $dbccl $dbcl] TRUE
+
+ set dbcdr0 [$dbdr cursor]
+ error_check_good dbcurs:dbdr0 [is_valid_cursor $dbcdr0 $dbdr] TRUE
+
+ set dbcdr1 [$dbdr cursor -dirty]
+ error_check_good dbcurs:dbdr1 [is_valid_cursor $dbcdr1 $dbdr] TRUE
+
+ #
+ # Now that we have all of our handles, change all the data in there
+ # to be the key and data the same, but data is capitalized.
+ puts "\tTest092.c: put/get data within a txn"
+ set gflags ""
+ if { [is_record_based $method] == 1 } {
+ set checkfunc test092dr_recno.check
+ append gflags " -recno"
+ } else {
+ set checkfunc test092dr.check
+ }
+ set count 0
+ set did [open $dict]
+ while { [gets $did str] != -1 && $count < $nentries } {
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ } else {
+ set key $str
+ }
+ set ustr [string toupper $str]
+ set clret [list [list $key [pad_data $method $str]]]
+ set drret [list [list $key [pad_data $method $ustr]]]
+ #
+ # Put the data in the txn.
+ #
+ set ret [eval {$dbtxn put} -txn $t \
+ {$key [chop_data $method $ustr]}]
+ error_check_good put:$dbtxn $ret 0
+
+ #
+ # Now get the data using the different db handles and
+ # make sure it is dirty or clean data.
+ #
+ # Using the dirty txn should show us dirty data
+ set ret [eval {$dbcl get -txn $tdr} $gflags {$key}]
+ error_check_good dbdr2:get $ret $drret
+
+ set ret [eval {$dbdr get -dirty} $gflags {$key}]
+ error_check_good dbdr1:get $ret $drret
+
+ set ret [eval {$dbdr get -txn $tdr} $gflags {$key}]
+ error_check_good dbdr2:get $ret $drret
+
+ incr count
+ }
+ close $did
+
+ puts "\tTest092.d: Check dirty data using dirty txn and clean db/cursor"
+ dump_file_walk $dbccl $t1 $checkfunc "-first" "-next"
+
+ puts "\tTest092.e: Check dirty data using -dirty cget flag"
+ dump_file_walk $dbcdr0 $t2 $checkfunc "-first" "-next" "-dirty"
+
+ puts "\tTest092.f: Check dirty data using -dirty cursor"
+ dump_file_walk $dbcdr1 $t3 $checkfunc "-first" "-next"
+
+ #
+ # We must close these before aborting the real txn
+ # because they all hold read locks on the pages.
+ #
+ error_check_good dbccl:close [$dbccl close] 0
+ error_check_good dbcdr0:close [$dbcdr0 close] 0
+ error_check_good dbcdr1:close [$dbcdr1 close] 0
+
+ #
+ # Now abort the modifying transaction and rerun the data checks.
+ #
+ puts "\tTest092.g: Aborting the write-txn"
+ error_check_good txnabort [$t abort] 0
+
+ set dbccl [$dbcl cursor -txn $tdr]
+ error_check_good dbcurs:dbcl [is_valid_cursor $dbccl $dbcl] TRUE
+
+ set dbcdr0 [$dbdr cursor]
+ error_check_good dbcurs:dbdr0 [is_valid_cursor $dbcdr0 $dbdr] TRUE
+
+ set dbcdr1 [$dbdr cursor -dirty]
+ error_check_good dbcurs:dbdr1 [is_valid_cursor $dbcdr1 $dbdr] TRUE
+
+ if { [is_record_based $method] == 1 } {
+ set checkfunc test092cl_recno.check
+ } else {
+ set checkfunc test092cl.check
+ }
+ puts "\tTest092.h: Check clean data using -dirty cget flag"
+ dump_file_walk $dbccl $t1 $checkfunc "-first" "-next"
+
+ puts "\tTest092.i: Check clean data using -dirty cget flag"
+ dump_file_walk $dbcdr0 $t2 $checkfunc "-first" "-next" "-dirty"
+
+ puts "\tTest092.j: Check clean data using -dirty cursor"
+ dump_file_walk $dbcdr1 $t3 $checkfunc "-first" "-next"
+
+ # Clean up our handles
+ error_check_good dbccl:close [$dbccl close] 0
+ error_check_good tdrcommit [$tdr commit] 0
+ error_check_good dbcdr0:close [$dbcdr0 close] 0
+ error_check_good dbcdr1:close [$dbcdr1 close] 0
+ error_check_good dbclose [$dbcl close] 0
+ error_check_good dbclose [$dbdr close] 0
+ error_check_good dbclose [$dbtxn close] 0
+ error_check_good envclose [$env close] 0
+}
+
+# Check functions for test092; keys and data are identical
+# Clean checks mean keys and data are identical.
+# Dirty checks mean data are uppercase versions of keys.
+proc test092cl.check { key data } {
+ error_check_good "key/data mismatch" $key $data
+}
+
+proc test092cl_recno.check { key data } {
+ global kvals
+
+ error_check_good key"$key"_exists [info exists kvals($key)] 1
+ error_check_good "key/data mismatch, key $key" $data $kvals($key)
+}
+
+proc test092dr.check { key data } {
+ error_check_good "key/data mismatch" $key [string tolower $data]
+}
+
+proc test092dr_recno.check { key data } {
+ global kvals
+
+ error_check_good key"$key"_exists [info exists kvals($key)] 1
+ error_check_good "key/data mismatch, key $key" $data \
+ [string toupper $kvals($key)]
+}
+
diff --git a/bdb/test/test093.tcl b/bdb/test/test093.tcl
new file mode 100644
index 00000000000..e3f8f0103c6
--- /dev/null
+++ b/bdb/test/test093.tcl
@@ -0,0 +1,393 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test093.tcl,v 11.20 2002/06/20 19:01:02 sue Exp $
+#
+# TEST test093
+# TEST Test using set_bt_compare.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Close file, reopen, do retrieve and re-verify.
+proc test093 { method {nentries 10000} {tnum "93"} args} {
+ source ./include.tcl
+ global btvals
+ global btvalsck
+ global errorInfo
+
+ set dbargs [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ if { [is_btree $method] != 1 } {
+ puts "Test0$tnum: skipping for method $method."
+ return
+ }
+ set txnenv 0
+ set eindex [lsearch -exact $dbargs "-env"]
+ if { $eindex != -1 } {
+ set testfile test0$tnum.db
+ incr eindex
+ set env [lindex $dbargs $eindex]
+ set rpcenv [is_rpcenv $env]
+ if { $rpcenv == 1 } {
+ puts "Test0$tnum: skipping for RPC"
+ return
+ }
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append dbargs " -auto_commit "
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
+ cleanup $testdir $env
+ }
+ puts "Test0$tnum: $method ($args) $nentries using btcompare"
+
+
+ test093_run $omethod $dbargs $nentries $tnum test093_cmp1 test093_sort1
+ test093_runbig $omethod $dbargs $nentries $tnum \
+ test093_cmp1 test093_sort1
+ test093_run $omethod $dbargs $nentries $tnum test093_cmp2 test093_sort2
+ #
+ # Don't bother running the second, really slow, comparison
+ # function on test093_runbig (file contents).
+
+ # Clean up so verification doesn't fail. (There's currently
+ # no way to specify a comparison function to berkdb dbverify.)
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ set eindex [lsearch -exact $dbargs "-env"]
+ if { $eindex == -1 } {
+ set env NULL
+ } else {
+ incr eindex
+ set env [lindex $dbargs $eindex]
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+}
+
+proc test093_run { method dbargs nentries tnum cmpfunc sortfunc } {
+ source ./include.tcl
+ global btvals
+ global btvalsck
+
+ # Create the database and open the dictionary
+ set eindex [lsearch -exact $dbargs "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ set txnenv 0
+ if { $eindex == -1 } {
+ set testfile $testdir/test0$tnum.db
+ set env NULL
+ } else {
+ set testfile test0$tnum.db
+ incr eindex
+ set env [lindex $dbargs $eindex]
+ set txnenv [is_txnenv $env]
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+
+ set db [eval {berkdb_open -btcompare $cmpfunc \
+ -create -mode 0644} $method $dbargs $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set did [open $dict]
+
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ set pflags ""
+ set gflags ""
+ set txn ""
+ set btvals {}
+ set btvalsck {}
+ set checkfunc test093_check
+ puts "\tTest0$tnum.a: put/get loop"
+ # Here is the loop where we put and get each key/data pair
+ set count 0
+ while { [gets $did str] != -1 && $count < $nentries } {
+ set key $str
+ set str [reverse $str]
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval \
+ {$db put} $txn $pflags {$key [chop_data $method $str]}]
+ error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ lappend btvals $key
+
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_good \
+ get $ret [list [list $key [pad_data $method $str]]]
+
+ incr count
+ }
+ close $did
+ # Now we will get each key from the DB and compare the results
+ # to the original.
+ puts "\tTest0$tnum.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ # Now compare the keys to see if they match the dictionary (or ints)
+ set q q
+ filehead $nentries $dict $t2
+ filesort $t2 $t3
+ file rename -force $t3 $t2
+ filesort $t1 $t3
+
+ error_check_good Test0$tnum:diff($t3,$t2) \
+ [filecmp $t3 $t2] 0
+
+ puts "\tTest0$tnum.c: dump file in order"
+ # Now, reopen the file and run the last test again.
+ # We open it here, ourselves, because all uses of the db
+ # need to have the correct comparison func set. Then
+ # call dump_file_direction directly.
+ set btvalsck {}
+ set db [eval {berkdb_open -btcompare $cmpfunc -rdonly} \
+ $dbargs $method $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dump_file_direction $db $txn $t1 $checkfunc "-first" "-next"
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ #
+ # We need to sort btvals according to the comparison function.
+ # Once that is done, btvalsck and btvals should be the same.
+ puts "\tTest0$tnum.d: check file order"
+
+ $sortfunc
+
+ error_check_good btvals:len [llength $btvals] [llength $btvalsck]
+ for {set i 0} {$i < $nentries} {incr i} {
+ error_check_good vals:$i [lindex $btvals $i] \
+ [lindex $btvalsck $i]
+ }
+}
+
+proc test093_runbig { method dbargs nentries tnum cmpfunc sortfunc } {
+ source ./include.tcl
+ global btvals
+ global btvalsck
+
+ # Create the database and open the dictionary
+ set eindex [lsearch -exact $dbargs "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ set txnenv 0
+ if { $eindex == -1 } {
+ set testfile $testdir/test0$tnum.db
+ set env NULL
+ } else {
+ set testfile test0$tnum.db
+ incr eindex
+ set env [lindex $dbargs $eindex]
+ set txnenv [is_txnenv $env]
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+
+ set db [eval {berkdb_open -btcompare $cmpfunc \
+ -create -mode 0644} $method $dbargs $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ set t4 $testdir/t4
+ set t5 $testdir/t5
+ set pflags ""
+ set gflags ""
+ set txn ""
+ set btvals {}
+ set btvalsck {}
+ set checkfunc test093_checkbig
+ puts "\tTest0$tnum.e:\
+ big key put/get loop key=filecontents data=filename"
+
+ # Here is the loop where we put and get each key/data pair
+ set file_list [get_file_list 1]
+
+ set count 0
+ foreach f $file_list {
+ set fid [open $f r]
+ fconfigure $fid -translation binary
+ set key [read $fid]
+ close $fid
+
+ set key $f$key
+
+ set fcopy [open $t5 w]
+ fconfigure $fcopy -translation binary
+ puts -nonewline $fcopy $key
+ close $fcopy
+
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} $txn $pflags {$key \
+ [chop_data $method $f]}]
+ error_check_good put_file $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ lappend btvals $key
+
+ # Should really catch errors
+ set fid [open $t4 w]
+ fconfigure $fid -translation binary
+ if [catch {eval {$db get} $gflags {$key}} data] {
+ puts -nonewline $fid $data
+ } else {
+ # Data looks like {{key data}}
+ set key [lindex [lindex $data 0] 0]
+ puts -nonewline $fid $key
+ }
+ close $fid
+ error_check_good \
+ Test093:diff($t5,$t4) [filecmp $t5 $t4] 0
+
+ incr count
+ }
+
+ # Now we will get each key from the DB and compare the results
+ # to the original.
+ puts "\tTest0$tnum.f: big dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dump_file $db $txn $t1 $checkfunc
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ puts "\tTest0$tnum.g: dump file in order"
+ # Now, reopen the file and run the last test again.
+ # We open it here, ourselves, because all uses of the db
+ # need to have the correct comparison func set. Then
+ # call dump_file_direction directly.
+
+ set btvalsck {}
+ set db [eval {berkdb_open -btcompare $cmpfunc -rdonly} \
+ $dbargs $method $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dump_file_direction $db $txn $t1 $checkfunc "-first" "-next"
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ #
+ # We need to sort btvals according to the comparison function.
+ # Once that is done, btvalsck and btvals should be the same.
+ puts "\tTest0$tnum.h: check file order"
+
+ $sortfunc
+ error_check_good btvals:len [llength $btvals] [llength $btvalsck]
+
+ set end [llength $btvals]
+ for {set i 0} {$i < $end} {incr i} {
+ error_check_good vals:$i [lindex $btvals $i] \
+ [lindex $btvalsck $i]
+ }
+}
+
+# Simple bt comparison.
+proc test093_cmp1 { a b } {
+ return [string compare $b $a]
+}
+
+# Simple bt sorting.
+proc test093_sort1 {} {
+ global btvals
+ #
+ # This one is easy, just sort in reverse.
+ #
+ set btvals [lsort -decreasing $btvals]
+}
+
+proc test093_cmp2 { a b } {
+ set arev [reverse $a]
+ set brev [reverse $b]
+ return [string compare $arev $brev]
+}
+
+proc test093_sort2 {} {
+ global btvals
+
+ # We have to reverse them, then sorts them.
+ # Then reverse them back to real words.
+ set rbtvals {}
+ foreach i $btvals {
+ lappend rbtvals [reverse $i]
+ }
+ set rbtvals [lsort -increasing $rbtvals]
+ set newbtvals {}
+ foreach i $rbtvals {
+ lappend newbtvals [reverse $i]
+ }
+ set btvals $newbtvals
+}
+
+# Check function for test093; keys and data are identical
+proc test093_check { key data } {
+ global btvalsck
+
+ error_check_good "key/data mismatch" $data [reverse $key]
+ lappend btvalsck $key
+}
+
+# Check function for test093 big keys;
+proc test093_checkbig { key data } {
+ source ./include.tcl
+ global btvalsck
+
+ set fid [open $data r]
+ fconfigure $fid -translation binary
+ set cont [read $fid]
+ close $fid
+ error_check_good "key/data mismatch" $key $data$cont
+ lappend btvalsck $key
+}
+
diff --git a/bdb/test/test094.tcl b/bdb/test/test094.tcl
new file mode 100644
index 00000000000..781052913f4
--- /dev/null
+++ b/bdb/test/test094.tcl
@@ -0,0 +1,251 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test094.tcl,v 11.16 2002/06/20 19:01:02 sue Exp $
+#
+# TEST test094
+# TEST Test using set_dup_compare.
+# TEST
+# TEST Use the first 10,000 entries from the dictionary.
+# TEST Insert each with self as key and data; retrieve each.
+# TEST After all are entered, retrieve all; compare output to original.
+# TEST Close file, reopen, do retrieve and re-verify.
+proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
+ source ./include.tcl
+ global errorInfo
+
+ set dbargs [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ if { [is_btree $method] != 1 && [is_hash $method] != 1 } {
+ puts "Test0$tnum: skipping for method $method."
+ return
+ }
+
+ set txnenv 0
+ set eindex [lsearch -exact $dbargs "-env"]
+ # Create the database and open the dictionary
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/test0$tnum-a.db
+ set env NULL
+ } else {
+ set testfile test0$tnum-a.db
+ incr eindex
+ set env [lindex $dbargs $eindex]
+ set rpcenv [is_rpcenv $env]
+ if { $rpcenv == 1 } {
+ puts "Test0$tnum: skipping for RPC"
+ return
+ }
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append dbargs " -auto_commit "
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ }
+ set testdir [get_home $env]
+ }
+ puts "Test0$tnum: $method ($args) $nentries \
+ with $ndups dups using dupcompare"
+
+ cleanup $testdir $env
+
+ set db [eval {berkdb_open_noerr -dupcompare test094_cmp \
+ -dup -dupsort -create -mode 0644} $omethod $dbargs {$testfile}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set did [open $dict]
+ set t1 $testdir/t1
+ set pflags ""
+ set gflags ""
+ set txn ""
+ puts "\tTest0$tnum.a: $nentries put/get duplicates loop"
+ # Here is the loop where we put and get each key/data pair
+ set count 0
+ set dlist {}
+ for {set i 0} {$i < $ndups} {incr i} {
+ set dlist [linsert $dlist 0 $i]
+ }
+ while { [gets $did str] != -1 && $count < $nentries } {
+ set key $str
+ for {set i 0} {$i < $ndups} {incr i} {
+ set data $i:$str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} \
+ $txn $pflags {$key [chop_data $omethod $data]}]
+ error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ }
+
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_good get [llength $ret] $ndups
+ incr count
+ }
+ close $did
+ # Now we will get each key from the DB and compare the results
+ # to the original.
+ puts "\tTest0$tnum.b: traverse checking duplicates before close"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dup_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ # Set up second testfile so truncate flag is not needed.
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/test0$tnum-b.db
+ set env NULL
+ } else {
+ set testfile test0$tnum-b.db
+ set env [lindex $dbargs $eindex]
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+
+ #
+ # Test dupcompare with data items big enough to force offpage dups.
+ #
+ puts "\tTest0$tnum.c: big key put/get dup loop key=filename data=filecontents"
+ set db [eval {berkdb_open -dupcompare test094_cmp -dup -dupsort \
+ -create -mode 0644} $omethod $dbargs $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ # Here is the loop where we put and get each key/data pair
+ set file_list [get_file_list 1]
+ if { [llength $file_list] > $nentries } {
+ set file_list [lrange $file_list 1 $nentries]
+ }
+
+ set count 0
+ foreach f $file_list {
+ set fid [open $f r]
+ fconfigure $fid -translation binary
+ set cont [read $fid]
+ close $fid
+
+ set key $f
+ for {set i 0} {$i < $ndups} {incr i} {
+ set data $i:$cont
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$db put} \
+ $txn $pflags {$key [chop_data $omethod $data]}]
+ error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ }
+
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_good get [llength $ret] $ndups
+ incr count
+ }
+
+ puts "\tTest0$tnum.d: traverse checking duplicates before close"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dup_file_check $db $txn $t1 $dlist
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ set testdir [get_home $env]
+ }
+ error_check_good db_close [$db close] 0
+
+ # Clean up the test directory, since there's currently
+ # no way to specify a dup_compare function to berkdb dbverify
+ # and without one it will fail.
+ cleanup $testdir $env
+}
+
+# Simple dup comparison.
+proc test094_cmp { a b } {
+ return [string compare $b $a]
+}
+
+# Check if each key appears exactly [llength dlist] times in the file with
+# the duplicate tags matching those that appear in dlist.
+proc test094_dup_big { db txn tmpfile dlist {extra 0}} {
+ source ./include.tcl
+
+ set outf [open $tmpfile w]
+ # Now we will get each key from the DB and dump to outfile
+ set c [eval {$db cursor} $txn]
+ set lastkey ""
+ set done 0
+ while { $done != 1} {
+ foreach did $dlist {
+ set rec [$c get "-next"]
+ if { [string length $rec] == 0 } {
+ set done 1
+ break
+ }
+ set key [lindex [lindex $rec 0] 0]
+ set fulldata [lindex [lindex $rec 0] 1]
+ set id [id_of $fulldata]
+ set d [data_of $fulldata]
+ if { [string compare $key $lastkey] != 0 && \
+ $id != [lindex $dlist 0] } {
+ set e [lindex $dlist 0]
+ error "FAIL: \tKey \
+ $key, expected dup id $e, got $id"
+ }
+ error_check_good dupget.data $d $key
+ error_check_good dupget.id $id $did
+ set lastkey $key
+ }
+ #
+ # Some tests add an extra dup (like overflow entries)
+ # Check id if it exists.
+ if { $extra != 0} {
+ set okey $key
+ set rec [$c get "-next"]
+ if { [string length $rec] != 0 } {
+ set key [lindex [lindex $rec 0] 0]
+ #
+ # If this key has no extras, go back for
+ # next iteration.
+ if { [string compare $key $lastkey] != 0 } {
+ set key $okey
+ set rec [$c get "-prev"]
+ } else {
+ set fulldata [lindex [lindex $rec 0] 1]
+ set id [id_of $fulldata]
+ set d [data_of $fulldata]
+ error_check_bad dupget.data1 $d $key
+ error_check_good dupget.id1 $id $extra
+ }
+ }
+ }
+ if { $done != 1 } {
+ puts $outf $key
+ }
+ }
+ close $outf
+ error_check_good curs_close [$c close] 0
+}
diff --git a/bdb/test/test095.tcl b/bdb/test/test095.tcl
new file mode 100644
index 00000000000..5543f346b7e
--- /dev/null
+++ b/bdb/test/test095.tcl
@@ -0,0 +1,296 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2000-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test095.tcl,v 11.16 2002/08/08 15:38:12 bostic Exp $
+#
+# TEST test095
+# TEST Bulk get test. [#2934]
+proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
+ source ./include.tcl
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ set txnenv 0
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set basename $testdir/test0$tnum
+ set env NULL
+ # If we've our own env, no reason to swap--this isn't
+ # an mpool test.
+ set carg { -cachesize {0 25000000 0} }
+ } else {
+ set basename test0$tnum
+ incr eindex
+ set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ puts "Skipping for environment with txns"
+ return
+ }
+ set testdir [get_home $env]
+ set carg {}
+ }
+ cleanup $testdir $env
+
+ puts "Test0$tnum: $method ($args) Bulk get test"
+
+ if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
+ puts "Test0$tnum skipping for method $method"
+ return
+ }
+
+ # We run the meat of the test twice: once with unsorted dups,
+ # once with sorted dups.
+ for { set dflag "-dup"; set sort "unsorted"; set diter 0 } \
+ { $diter < 2 } \
+ { set dflag "-dup -dupsort"; set sort "sorted"; incr diter } {
+ set testfile $basename-$sort.db
+ set did [open $dict]
+
+ # Open and populate the database with $nsets sets of dups.
+ # Each set contains as many dups as its number
+ puts "\tTest0$tnum.a:\
+ Creating database with $nsets sets of $sort dups."
+ set dargs "$dflag $carg $args"
+ set db [eval {berkdb_open -create} $omethod $dargs $testfile]
+ error_check_good db_open [is_valid_db $db] TRUE
+ t95_populate $db $did $nsets 0
+
+ # Run basic get tests.
+ t95_gettest $db $tnum b [expr 8192] 1
+ t95_gettest $db $tnum c [expr 10 * 8192] 0
+
+ # Run cursor get tests.
+ t95_cgettest $db $tnum d [expr 100] 1
+ t95_cgettest $db $tnum e [expr 10 * 8192] 0
+
+ # Run invalid flag combination tests
+ # Sync and reopen test file so errors won't be sent to stderr
+ error_check_good db_sync [$db sync] 0
+ set noerrdb [eval berkdb_open_noerr $dargs $testfile]
+ t95_flagtest $noerrdb $tnum f [expr 8192]
+ t95_cflagtest $noerrdb $tnum g [expr 100]
+ error_check_good noerrdb_close [$noerrdb close] 0
+
+ # Set up for overflow tests
+ set max [expr 4000 * $noverflows]
+ puts "\tTest0$tnum.h: Growing\
+ database with $noverflows overflow sets (max item size $max)"
+ t95_populate $db $did $noverflows 4000
+
+ # Run overflow get tests.
+ t95_gettest $db $tnum i [expr 10 * 8192] 1
+ t95_gettest $db $tnum j [expr $max * 2] 1
+ t95_gettest $db $tnum k [expr $max * $noverflows * 2] 0
+
+ # Run overflow cursor get tests.
+ t95_cgettest $db $tnum l [expr 10 * 8192] 1
+ t95_cgettest $db $tnum m [expr $max * 2] 0
+
+ error_check_good db_close [$db close] 0
+ close $did
+ }
+}
+
+proc t95_gettest { db tnum letter bufsize expectfail } {
+ t95_gettest_body $db $tnum $letter $bufsize $expectfail 0
+}
+proc t95_cgettest { db tnum letter bufsize expectfail } {
+ t95_gettest_body $db $tnum $letter $bufsize $expectfail 1
+}
+proc t95_flagtest { db tnum letter bufsize } {
+ t95_flagtest_body $db $tnum $letter $bufsize 0
+}
+proc t95_cflagtest { db tnum letter bufsize } {
+ t95_flagtest_body $db $tnum $letter $bufsize 1
+}
+
+# Basic get test
+proc t95_gettest_body { db tnum letter bufsize expectfail usecursor } {
+ global errorCode
+
+ if { $usecursor == 0 } {
+ set action "db get -multi"
+ } else {
+ set action "dbc get -multi -set/-next"
+ }
+ puts "\tTest0$tnum.$letter: $action with bufsize $bufsize"
+
+ set allpassed TRUE
+ set saved_err ""
+
+ # Cursor for $usecursor.
+ if { $usecursor != 0 } {
+ set getcurs [$db cursor]
+ error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
+ }
+
+ # Traverse DB with cursor; do get/c_get(DB_MULTIPLE) on each item.
+ set dbc [$db cursor]
+ error_check_good is_valid_dbc [is_valid_cursor $dbc $db] TRUE
+ for { set dbt [$dbc get -first] } { [llength $dbt] != 0 } \
+ { set dbt [$dbc get -nextnodup] } {
+ set key [lindex [lindex $dbt 0] 0]
+ set datum [lindex [lindex $dbt 0] 1]
+
+ if { $usecursor == 0 } {
+ set ret [catch {eval $db get -multi $bufsize $key} res]
+ } else {
+ set res {}
+ for { set ret [catch {eval $getcurs get -multi $bufsize\
+ -set $key} tres] } \
+ { $ret == 0 && [llength $tres] != 0 } \
+ { set ret [catch {eval $getcurs get -multi $bufsize\
+ -nextdup} tres]} {
+ eval lappend res $tres
+ }
+ }
+
+ # If we expect a failure, be more tolerant if the above fails;
+ # just make sure it's an ENOMEM, mark it, and move along.
+ if { $expectfail != 0 && $ret != 0 } {
+ error_check_good multi_failure_errcode \
+ [is_substr $errorCode ENOMEM] 1
+ set allpassed FALSE
+ continue
+ }
+ error_check_good get_multi($key) $ret 0
+ t95_verify $res FALSE
+ }
+
+ set ret [catch {eval $db get -multi $bufsize} res]
+
+ if { $expectfail == 1 } {
+ error_check_good allpassed $allpassed FALSE
+ puts "\t\tTest0$tnum.$letter:\
+ returned at least one ENOMEM (as expected)"
+ } else {
+ error_check_good allpassed $allpassed TRUE
+ puts "\t\tTest0$tnum.$letter: succeeded (as expected)"
+ }
+
+ error_check_good dbc_close [$dbc close] 0
+ if { $usecursor != 0 } {
+ error_check_good getcurs_close [$getcurs close] 0
+ }
+}
+
+# Test of invalid flag combinations for -multi
+proc t95_flagtest_body { db tnum letter bufsize usecursor } {
+ global errorCode
+
+ if { $usecursor == 0 } {
+ set action "db get -multi "
+ } else {
+ set action "dbc get -multi "
+ }
+ puts "\tTest0$tnum.$letter: $action with invalid flag combinations"
+
+ # Cursor for $usecursor.
+ if { $usecursor != 0 } {
+ set getcurs [$db cursor]
+ error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
+ }
+
+ if { $usecursor == 0 } {
+ # Disallowed flags for basic -multi get
+ set badflags [list consume consume_wait {rmw some_key}]
+
+ foreach flag $badflags {
+ catch {eval $db get -multi $bufsize -$flag} ret
+ error_check_good \
+ db:get:multi:$flag [is_substr $errorCode EINVAL] 1
+ }
+ } else {
+ # Disallowed flags for cursor -multi get
+ set cbadflags [list last get_recno join_item \
+ {multi_key 1000} prev prevnodup]
+
+ set dbc [$db cursor]
+ $dbc get -first
+ foreach flag $cbadflags {
+ catch {eval $dbc get -multi $bufsize -$flag} ret
+ error_check_good dbc:get:multi:$flag \
+ [is_substr $errorCode EINVAL] 1
+ }
+ error_check_good dbc_close [$dbc close] 0
+ }
+ if { $usecursor != 0 } {
+ error_check_good getcurs_close [$getcurs close] 0
+ }
+ puts "\t\tTest0$tnum.$letter completed"
+}
+
+# Verify that a passed-in list of key/data pairs all match the predicted
+# structure (e.g. {{thing1 thing1.0}}, {{key2 key2.0} {key2 key2.1}}).
+proc t95_verify { res multiple_keys } {
+ global alphabet
+
+ set i 0
+
+ set orig_key [lindex [lindex $res 0] 0]
+ set nkeys [string trim $orig_key $alphabet']
+ set base_key [string trim $orig_key 0123456789]
+ set datum_count 0
+
+ while { 1 } {
+ set key [lindex [lindex $res $i] 0]
+ set datum [lindex [lindex $res $i] 1]
+
+ if { $datum_count >= $nkeys } {
+ if { [llength $key] != 0 } {
+ # If there are keys beyond $nkeys, we'd
+ # better have multiple_keys set.
+ error_check_bad "keys beyond number $i allowed"\
+ $multiple_keys FALSE
+
+ # If multiple_keys is set, accept the new key.
+ set orig_key $key
+ set nkeys [eval string trim \
+ $orig_key {$alphabet'}]
+ set base_key [eval string trim \
+ $orig_key 0123456789]
+ set datum_count 0
+ } else {
+ # datum_count has hit nkeys. We're done.
+ return
+ }
+ }
+
+ error_check_good returned_key($i) $key $orig_key
+ error_check_good returned_datum($i) \
+ $datum $base_key.[format %4u $datum_count]
+ incr datum_count
+ incr i
+ }
+}
+
+# Add nsets dup sets, each consisting of {word$ndups word$n} pairs,
+# with "word" having (i * pad_bytes) bytes extra padding.
+proc t95_populate { db did nsets pad_bytes } {
+ set txn ""
+ for { set i 1 } { $i <= $nsets } { incr i } {
+ # basekey is a padded dictionary word
+ gets $did basekey
+
+ append basekey [repeat "a" [expr $pad_bytes * $i]]
+
+ # key is basekey with the number of dups stuck on.
+ set key $basekey$i
+
+ for { set j 0 } { $j < $i } { incr j } {
+ set data $basekey.[format %4u $j]
+ error_check_good db_put($key,$data) \
+ [eval {$db put} $txn {$key $data}] 0
+ }
+ }
+
+ # This will make debugging easier, and since the database is
+ # read-only from here out, it's cheap.
+ error_check_good db_sync [$db sync] 0
+}
diff --git a/bdb/test/test096.tcl b/bdb/test/test096.tcl
new file mode 100644
index 00000000000..042df19eac7
--- /dev/null
+++ b/bdb/test/test096.tcl
@@ -0,0 +1,202 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1999-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test096.tcl,v 11.19 2002/08/19 20:09:29 margo Exp $
+#
+# TEST test096
+# TEST Db->truncate test.
+proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} {
+ global fixed_len
+ source ./include.tcl
+
+ set orig_fixed_len $fixed_len
+ set args [convert_args $method $args]
+ set encargs ""
+ set args [split_encargs $args encargs]
+ set omethod [convert_method $method]
+
+ puts "Test096: $method db truncate method test"
+ if { [is_record_based $method] == 1 || \
+ [is_rbtree $method] == 1 } {
+ puts "Test096 skipping for method $method"
+ return
+ }
+ set pgindex [lsearch -exact $args "-pagesize"]
+ if { $pgindex != -1 } {
+ puts "Test096: Skipping for specific pagesizes"
+ return
+ }
+
+ # Create the database and open the dictionary
+ set eindex [lsearch -exact $args "-env"]
+ set testfile test096.db
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 0 } {
+ puts "Environment w/o txns specified; skipping."
+ return
+ }
+ if { $nentries == 1000 } {
+ set nentries 100
+ }
+ reduce_dups nentries ndups
+ set testdir [get_home $env]
+ set closeenv 0
+ } else {
+ env_cleanup $testdir
+
+ #
+ # We need an env for exclusive-use testing.
+ set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
+ error_check_good env_create [is_valid_env $env] TRUE
+ set closeenv 1
+ }
+
+ set t1 $testdir/t1
+
+ puts "\tTest096.a: Create $nentries entries"
+ set db [eval {berkdb_open -create -auto_commit \
+ -env $env $omethod -mode 0644} $args $testfile]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ set did [open $dict]
+ set count 0
+ set txn ""
+ set pflags ""
+ set gflags ""
+ while { [gets $did str] != -1 && $count < $nentries } {
+ set key $str
+ set datastr [reverse $str]
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ set ret [eval {$db put} \
+ $txn $pflags {$key [chop_data $method $datastr]}]
+ error_check_good put $ret 0
+ error_check_good txn [$t commit] 0
+
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_good $key:dbget [llength $ret] 1
+
+ incr count
+ }
+ close $did
+
+ puts "\tTest096.b: Truncate database"
+ error_check_good dbclose [$db close] 0
+ set dbtr [eval {berkdb_open -create -auto_commit \
+ -env $env $omethod -mode 0644} $args $testfile]
+ error_check_good db_open [is_valid_db $dbtr] TRUE
+
+ set ret [$dbtr truncate -auto_commit]
+ error_check_good dbtrunc $ret $nentries
+ error_check_good db_close [$dbtr close] 0
+
+ set db [eval {berkdb_open -env $env} $args $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set ret [$db get -glob *]
+ error_check_good dbget [llength $ret] 0
+ error_check_good dbclose [$db close] 0
+ error_check_good dbverify [verify_dir $testdir "\tTest096.c: "] 0
+
+ #
+ # Remove database, and create a new one with dups.
+ #
+ puts "\tTest096.d: Create $nentries entries with $ndups duplicates"
+ set ret [berkdb dbremove -env $env -auto_commit $testfile]
+ set db [eval {berkdb_open -pagesize $pagesize -dup -auto_commit \
+ -create -env $env $omethod -mode 0644} $args $testfile]
+ error_check_good db_open [is_valid_db $db] TRUE
+ set did [open $dict]
+ set count 0
+ set txn ""
+ set pflags ""
+ set gflags ""
+ while { [gets $did str] != -1 && $count < $nentries } {
+ set key $str
+ for { set i 1 } { $i <= $ndups } { incr i } {
+ set datastr $i:$str
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ set ret [eval {$db put} \
+ $txn $pflags {$key [chop_data $method $datastr]}]
+ error_check_good put $ret 0
+ error_check_good txn [$t commit] 0
+ }
+
+ set ret [eval {$db get} $gflags {$key}]
+ error_check_bad $key:dbget_dups [llength $ret] 0
+ error_check_good $key:dbget_dups1 [llength $ret] $ndups
+
+ incr count
+ }
+ close $did
+ set dlist ""
+ for { set i 1 } {$i <= $ndups} {incr i} {
+ lappend dlist $i
+ }
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ dup_check $db $txn $t1 $dlist
+ error_check_good txn [$t commit] 0
+ puts "\tTest096.e: Verify off page duplicates status"
+ set stat [$db stat]
+ error_check_bad stat:offpage [is_substr $stat \
+ "{{Duplicate pages} 0}"] 1
+
+ set recs [expr $ndups * $count]
+ error_check_good dbclose [$db close] 0
+
+ puts "\tTest096.f: Truncate database in a txn then abort"
+ set txn [$env txn]
+
+ set dbtr [eval {berkdb_open -auto_commit -create \
+ -env $env $omethod -mode 0644} $args $testfile]
+ error_check_good db_open [is_valid_db $dbtr] TRUE
+ error_check_good txnbegin [is_valid_txn $txn $env] TRUE
+
+ set ret [$dbtr truncate -txn $txn]
+ error_check_good dbtrunc $ret $recs
+
+ error_check_good txnabort [$txn abort] 0
+ error_check_good db_close [$dbtr close] 0
+
+ set db [eval {berkdb_open -auto_commit -env $env} $args $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set ret [$db get -glob *]
+ error_check_good dbget [llength $ret] $recs
+ error_check_good dbclose [$db close] 0
+
+ puts "\tTest096.g: Truncate database in a txn then commit"
+ set txn [$env txn]
+ error_check_good txnbegin [is_valid_txn $txn $env] TRUE
+
+ set dbtr [eval {berkdb_open -auto_commit -create \
+ -env $env $omethod -mode 0644} $args $testfile]
+ error_check_good db_open [is_valid_db $dbtr] TRUE
+
+ set ret [$dbtr truncate -txn $txn]
+ error_check_good dbtrunc $ret $recs
+
+ error_check_good txncommit [$txn commit] 0
+ error_check_good db_close [$dbtr close] 0
+
+ set db [berkdb_open -auto_commit -env $env $testfile]
+ error_check_good dbopen [is_valid_db $db] TRUE
+ set ret [$db get -glob *]
+ error_check_good dbget [llength $ret] 0
+ error_check_good dbclose [$db close] 0
+
+ set testdir [get_home $env]
+ error_check_good dbverify [verify_dir $testdir "\tTest096.h: "] 0
+
+ if { $closeenv == 1 } {
+ error_check_good envclose [$env close] 0
+ }
+}
diff --git a/bdb/test/test097.tcl b/bdb/test/test097.tcl
new file mode 100644
index 00000000000..6e43b820b2f
--- /dev/null
+++ b/bdb/test/test097.tcl
@@ -0,0 +1,188 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test097.tcl,v 11.8 2002/09/04 18:47:42 sue Exp $
+#
+# TEST test097
+# TEST Open up a large set of database files simultaneously.
+# TEST Adjust for local file descriptor resource limits.
+# TEST Then use the first 1000 entries from the dictionary.
+# TEST Insert each with self as key and a fixed, medium length data string;
+# TEST retrieve each. After all are entered, retrieve all; compare output
+# TEST to original.
+
+proc test097 { method {ndbs 500} {nentries 400} args } {
+ global pad_datastr
+ source ./include.tcl
+
+ set largs [convert_args $method $args]
+ set encargs ""
+ set largs [split_encargs $largs encargs]
+
+ # Open an environment, with a 1MB cache.
+ set eindex [lsearch -exact $largs "-env"]
+ if { $eindex != -1 } {
+ incr eindex
+ set env [lindex $largs $eindex]
+ puts "Test097: $method: skipping for env $env"
+ return
+ }
+ env_cleanup $testdir
+ set env [eval {berkdb_env -create \
+ -cachesize { 0 1048576 1 } -txn} -home $testdir $encargs]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ # Create the database and open the dictionary
+ set testfile test097.db
+ set t1 $testdir/t1
+ set t2 $testdir/t2
+ set t3 $testdir/t3
+ #
+ # When running with HAVE_MUTEX_SYSTEM_RESOURCES,
+ # we can run out of mutex lock slots due to the nature of this test.
+ # So, for this test, increase the number of pages per extent
+ # to consume fewer resources.
+ #
+ if { [is_queueext $method] } {
+ set numdb [expr $ndbs / 4]
+ set eindex [lsearch -exact $largs "-extent"]
+ error_check_bad extent $eindex -1
+ incr eindex
+ set extval [lindex $largs $eindex]
+ set extval [expr $extval * 4]
+ set largs [lreplace $largs $eindex $eindex $extval]
+ }
+ puts -nonewline "Test097: $method ($largs) "
+ puts "$nentries entries in at most $ndbs simultaneous databases"
+
+ puts "\tTest097.a: Simultaneous open"
+ set numdb [test097_open tdb $ndbs $method $env $testfile $largs]
+ if { $numdb == 0 } {
+ puts "\tTest097: Insufficient resources available -- skipping."
+ error_check_good envclose [$env close] 0
+ return
+ }
+
+ set did [open $dict]
+
+ set pflags ""
+ set gflags ""
+ set txn ""
+ set count 0
+
+ # Here is the loop where we put and get each key/data pair
+ if { [is_record_based $method] == 1 } {
+ append gflags "-recno"
+ }
+ puts "\tTest097.b: put/get on $numdb databases"
+ set datastr "abcdefghij"
+ set pad_datastr [pad_data $method $datastr]
+ while { [gets $did str] != -1 && $count < $nentries } {
+ if { [is_record_based $method] == 1 } {
+ set key [expr $count + 1]
+ } else {
+ set key $str
+ }
+ for { set i 1 } { $i <= $numdb } { incr i } {
+ set ret [eval {$tdb($i) put} $txn $pflags \
+ {$key [chop_data $method $datastr]}]
+ error_check_good put $ret 0
+ set ret [eval {$tdb($i) get} $gflags {$key}]
+ error_check_good get $ret [list [list $key \
+ [pad_data $method $datastr]]]
+ }
+ incr count
+ }
+ close $did
+
+ # Now we will get each key from the DB and compare the results
+ # to the original.
+ puts "\tTest097.c: dump and check files"
+ for { set j 1 } { $j <= $numdb } { incr j } {
+ dump_file $tdb($j) $txn $t1 test097.check
+ error_check_good db_close [$tdb($j) close] 0
+
+ # Now compare the keys to see if they match the dictionary
+ if { [is_record_based $method] == 1 } {
+ set oid [open $t2 w]
+ for {set i 1} {$i <= $nentries} {set i [incr i]} {
+ puts $oid $i
+ }
+ close $oid
+ filesort $t2 $t3
+ file rename -force $t3 $t2
+ } else {
+ set q q
+ filehead $nentries $dict $t3
+ filesort $t3 $t2
+ }
+ filesort $t1 $t3
+
+ error_check_good Test097:diff($t3,$t2) [filecmp $t3 $t2] 0
+ }
+ error_check_good envclose [$env close] 0
+}
+
+# Check function for test097; data should be fixed are identical
+proc test097.check { key data } {
+ global pad_datastr
+ error_check_good "data mismatch for key $key" $data $pad_datastr
+}
+
+proc test097_open { tdb ndbs method env testfile largs } {
+ global errorCode
+ upvar $tdb db
+
+ set j 0
+ set numdb $ndbs
+ if { [is_queueext $method] } {
+ set numdb [expr $ndbs / 4]
+ }
+ set omethod [convert_method $method]
+ for { set i 1 } {$i <= $numdb } { incr i } {
+ set stat [catch {eval {berkdb_open -env $env \
+ -pagesize 512 -create -mode 0644} \
+ $largs {$omethod $testfile.$i}} db($i)]
+ #
+ # Check if we've reached our limit
+ #
+ if { $stat == 1 } {
+ set min 20
+ set em [is_substr $errorCode EMFILE]
+ set en [is_substr $errorCode ENFILE]
+ error_check_good open_ret [expr $em || $en] 1
+ puts \
+ "\tTest097.a.1 Encountered resource limits opening $i files, adjusting"
+ if { [is_queueext $method] } {
+ set end [expr $j / 4]
+ set min 10
+ } else {
+ set end [expr $j - 10]
+ }
+ #
+ # If we cannot open even $min files, then this test is
+ # not very useful. Close up shop and go back.
+ #
+ if { $end < $min } {
+ test097_close db 1 $j
+ return 0
+ }
+ test097_close db [expr $end + 1] $j
+ return $end
+ } else {
+ error_check_good dbopen [is_valid_db $db($i)] TRUE
+ set j $i
+ }
+ }
+ return $j
+}
+
+proc test097_close { tdb start end } {
+ upvar $tdb db
+
+ for { set i $start } { $i <= $end } { incr i } {
+ error_check_good db($i)close [$db($i) close] 0
+ }
+}
diff --git a/bdb/test/test098.tcl b/bdb/test/test098.tcl
new file mode 100644
index 00000000000..320e0258a84
--- /dev/null
+++ b/bdb/test/test098.tcl
@@ -0,0 +1,91 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test098.tcl,v 1.5 2002/07/11 20:38:36 sandstro Exp $
+#
+# TEST test098
+# TEST Test of DB_GET_RECNO and secondary indices. Open a primary and
+# TEST a secondary, and do a normal cursor get followed by a get_recno.
+# TEST (This is a smoke test for "Bug #1" in [#5811].)
+
+proc test098 { method args } {
+ source ./include.tcl
+
+ set omethod [convert_method $method]
+ set args [convert_args $method $args]
+
+ puts "Test098: $omethod ($args): DB_GET_RECNO and secondary indices."
+
+ if { [is_rbtree $method] != 1 } {
+ puts "\tTest098: Skipping for method $method."
+ return
+ }
+
+ set txnenv 0
+ set eindex [lsearch -exact $args "-env"]
+ set txn ""
+ set auto ""
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set base $testdir/test098
+ set env NULL
+ } else {
+ set base test098
+ incr eindex
+ set env [lindex $args $eindex]
+ set rpcenv [is_rpcenv $env]
+ if { $rpcenv == 1 } {
+ puts "Test098: Skipping for RPC"
+ return
+ }
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ set auto " -auto_commit "
+ }
+ set testdir [get_home $env]
+ }
+ cleanup $testdir $env
+
+ puts "\tTest098.a: Set up databases."
+
+ set adb [eval {berkdb_open} $omethod $args $auto \
+ {-create} $base-primary.db]
+ error_check_good adb_create [is_valid_db $adb] TRUE
+
+ set bdb [eval {berkdb_open} $omethod $args $auto \
+ {-create} $base-secondary.db]
+ error_check_good bdb_create [is_valid_db $bdb] TRUE
+
+ set ret [eval $adb associate $auto [callback_n 0] $bdb]
+ error_check_good associate $ret 0
+
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set ret [eval {$adb put} $txn aaa data1]
+ error_check_good put $ret 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+
+ set bc [$bdb cursor]
+ error_check_good cursor [is_valid_cursor $bc $bdb] TRUE
+
+ puts "\tTest098.b: c_get(DB_FIRST) on the secondary."
+ error_check_good get_first [$bc get -first] \
+ [list [list [[callback_n 0] aaa data1] data1]]
+
+ puts "\tTest098.c: c_get(DB_GET_RECNO) on the secondary."
+ error_check_good get_recno [$bc get -get_recno] 1
+
+ error_check_good c_close [$bc close] 0
+
+ error_check_good bdb_close [$bdb close] 0
+ error_check_good adb_close [$adb close] 0
+}
diff --git a/bdb/test/test099.tcl b/bdb/test/test099.tcl
new file mode 100644
index 00000000000..db177ce5fff
--- /dev/null
+++ b/bdb/test/test099.tcl
@@ -0,0 +1,177 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test099.tcl,v 1.2 2002/08/08 15:38:13 bostic Exp $
+#
+# TEST test099
+# TEST
+# TEST Test of DB->get and DBC->c_get with set_recno and get_recno.
+# TEST
+# TEST Populate a small btree -recnum database.
+# TEST After all are entered, retrieve each using -recno with DB->get.
+# TEST Open a cursor and do the same for DBC->c_get with set_recno.
+# TEST Verify that set_recno sets the record number position properly.
+# TEST Verify that get_recno returns the correct record numbers.
+proc test099 { method {nentries 10000} args } {
+ source ./include.tcl
+
+ set args [convert_args $method $args]
+ set omethod [convert_method $method]
+
+ puts "Test099: Test of set_recno and get_recno in DBC->c_get."
+ if { [is_rbtree $method] != 1 } {
+ puts "Test099: skipping for method $method."
+ return
+ }
+
+ set txnenv 0
+ set eindex [lsearch -exact $args "-env"]
+ #
+ # If we are using an env, then testfile should just be the db name.
+ # Otherwise it is the test directory and the name.
+ if { $eindex == -1 } {
+ set testfile $testdir/test099.db
+ set env NULL
+ } else {
+ set testfile test099.db
+ incr eindex
+ set env [lindex $args $eindex]
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append args " -auto_commit "
+ #
+ # If we are using txns and running with the
+ # default, set the default down a bit.
+ #
+ if { $nentries == 10000 } {
+ set nentries 100
+ }
+ }
+ set testdir [get_home $env]
+ }
+ set t1 $testdir/t1
+ cleanup $testdir $env
+
+ # Create the database and open the dictionary
+ set db [eval {berkdb_open \
+ -create -mode 0644} $args {$omethod $testfile}]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ set did [open $dict]
+
+ set pflags ""
+ set gflags ""
+ set txn ""
+ set count 1
+
+ append gflags " -recno"
+
+ puts "\tTest099.a: put loop"
+ # Here is the loop where we put each key/data pair
+ while { [gets $did str] != -1 && $count < $nentries } {
+# global kvals
+# set key [expr $count]
+# set kvals($key) [pad_data $method $str]
+ set key $str
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set r [eval {$db put} \
+ $txn $pflags {$key [chop_data $method $str]}]
+ error_check_good db_put $r 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ incr count
+ }
+ close $did
+
+ puts "\tTest099.b: dump file"
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ dump_file $db $txn $t1 test099.check
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+
+ puts "\tTest099.c: Test set_recno then get_recno"
+ set db [eval {berkdb_open -rdonly} $args $omethod $testfile ]
+ error_check_good dbopen [is_valid_db $db] TRUE
+
+ # Open a cursor
+ if { $txnenv == 1 } {
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
+ set dbc [eval {$db cursor} $txn]
+ error_check_good db_cursor [is_substr $dbc $db] 1
+
+ set did [open $t1]
+ set recno 1
+
+ # Create key(recno) array to use for later comparison
+ while { [gets $did str] != -1 } {
+ set kvals($recno) $str
+ incr recno
+ }
+
+ set recno 1
+ set ret [$dbc get -first]
+ error_check_bad dbc_get_first [llength $ret] 0
+
+ # First walk forward through the database ....
+ while { $recno < $count } {
+ # Test set_recno: verify it sets the record number properly.
+ set current [$dbc get -current]
+ set r [$dbc get -set_recno $recno]
+ error_check_good set_recno $current $r
+ # Test set_recno: verify that we find the expected key
+ # at the current record number position.
+ set k [lindex [lindex $r 0] 0]
+ error_check_good set_recno $kvals($recno) $k
+
+ # Test get_recno: verify that the return from
+ # get_recno matches the record number just set.
+ set g [$dbc get -get_recno]
+ error_check_good get_recno $recno $g
+ set ret [$dbc get -next]
+ incr recno
+ }
+
+ # ... and then backward.
+ set recno [expr $count - 1]
+ while { $recno > 0 } {
+ # Test set_recno: verify that we find the expected key
+ # at the current record number position.
+ set r [$dbc get -set_recno $recno]
+ set k [lindex [lindex $r 0] 0]
+ error_check_good set_recno $kvals($recno) $k
+
+ # Test get_recno: verify that the return from
+ # get_recno matches the record number just set.
+ set g [$dbc get -get_recno]
+ error_check_good get_recno $recno $g
+ set recno [expr $recno - 1]
+ }
+
+ error_check_good cursor_close [$dbc close] 0
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
+ error_check_good db_close [$db close] 0
+ close $did
+}
+
+# Check function for dumped file; data should be fixed are identical
+proc test099.check { key data } {
+ error_check_good "data mismatch for key $key" $key $data
+}
diff --git a/bdb/test/test100.tcl b/bdb/test/test100.tcl
new file mode 100644
index 00000000000..f80b2e526dd
--- /dev/null
+++ b/bdb/test/test100.tcl
@@ -0,0 +1,17 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2000-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test100.tcl,v 11.1 2002/08/15 20:55:20 sandstro Exp $
+#
+# TEST test100
+# TEST Test for functionality near the end of the queue
+# TEST using test025 (DB_APPEND).
+proc test100 { method {nentries 10000} {txn -txn} {tnum "100"} args} {
+ if { [is_queueext $method ] == 0 } {
+ puts "Skipping test0$tnum for $method."
+ return;
+ }
+ eval {test025 $method $nentries 4294967000 $tnum} $args
+}
diff --git a/bdb/test/test101.tcl b/bdb/test/test101.tcl
new file mode 100644
index 00000000000..7e5c8fc30fc
--- /dev/null
+++ b/bdb/test/test101.tcl
@@ -0,0 +1,17 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2000-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: test101.tcl,v 11.1 2002/08/15 20:55:20 sandstro Exp $
+#
+# TEST test101
+# TEST Test for functionality near the end of the queue
+# TEST using test070 (DB_CONSUME).
+proc test101 { method {nentries 10000} {txn -txn} {tnum "101"} args} {
+ if { [is_queueext $method ] == 0 } {
+ puts "Skipping test0$tnum for $method."
+ return;
+ }
+ eval {test070 $method 4 2 1000 WAIT 4294967000 $txn $tnum} $args
+}
diff --git a/bdb/test/testparams.tcl b/bdb/test/testparams.tcl
index 2def6a9d0d8..6628db532d7 100644
--- a/bdb/test/testparams.tcl
+++ b/bdb/test/testparams.tcl
@@ -1,37 +1,72 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 2000
+# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: testparams.tcl,v 11.39 2001/01/11 17:29:42 sue Exp $
+# $Id: testparams.tcl,v 11.117 2002/09/05 02:30:00 margo Exp $
-set deadtests 3
-set envtests 8
-set recdtests 13
-set rsrctests 3
-set runtests 93
-set subdbtests 10
-set rpctests 2
+set subs {bigfile dead env lock log memp mutex recd rep rpc rsrc \
+ sdb sdbtest sec si test txn}
+set num_test(bigfile) 2
+set num_test(dead) 7
+set num_test(env) 11
+set num_test(lock) 5
+set num_test(log) 5
+set num_test(memp) 3
+set num_test(mutex) 3
+set num_test(recd) 20
+set num_test(rep) 5
+set num_test(rpc) 5
+set num_test(rsrc) 4
+set num_test(sdb) 12
+set num_test(sdbtest) 2
+set num_test(sec) 2
+set num_test(si) 6
+set num_test(test) 101
+set num_test(txn) 9
+
+set parms(recd001) 0
+set parms(recd002) 0
+set parms(recd003) 0
+set parms(recd004) 0
+set parms(recd005) ""
+set parms(recd006) 0
+set parms(recd007) ""
+set parms(recd008) {4 4}
+set parms(recd009) 0
+set parms(recd010) 0
+set parms(recd011) {200 15 1}
+set parms(recd012) {0 49 25 100 5}
+set parms(recd013) 100
+set parms(recd014) ""
+set parms(recd015) ""
+set parms(recd016) ""
+set parms(recd017) 0
+set parms(recd018) 10
+set parms(recd019) 50
+set parms(recd020) ""
set parms(subdb001) ""
set parms(subdb002) 10000
set parms(subdb003) 1000
set parms(subdb004) ""
set parms(subdb005) 100
set parms(subdb006) 100
-set parms(subdb007) 10000
-set parms(subdb008) 10000
+set parms(subdb007) ""
+set parms(subdb008) ""
set parms(subdb009) ""
set parms(subdb010) ""
-set parms(test001) {10000 0 "01"}
+set parms(subdb011) {13 10}
+set parms(subdb012) ""
+set parms(test001) {10000 0 "01" 0}
set parms(test002) 10000
set parms(test003) ""
set parms(test004) {10000 4 0}
set parms(test005) 10000
set parms(test006) {10000 0 6}
set parms(test007) {10000 7}
-set parms(test008) {10000 8 0}
-set parms(test009) 10000
+set parms(test008) {8 0}
+set parms(test009) ""
set parms(test010) {10000 5 10}
set parms(test011) {10000 5 11}
set parms(test012) ""
@@ -96,7 +131,7 @@ set parms(test070) {4 2 1000 CONSUME 0 -txn 70}
set parms(test071) {1 1 10000 CONSUME 0 -txn 71}
set parms(test072) {512 20 72}
set parms(test073) {512 50 73}
-set parms(test074) {-nextnodup 512 100 74}
+set parms(test074) {-nextnodup 100 74}
set parms(test075) {75}
set parms(test076) {1000 76}
set parms(test077) {1000 512 77}
@@ -104,12 +139,56 @@ set parms(test078) {100 512 78}
set parms(test079) {10000 512 79}
set parms(test080) {80}
set parms(test081) {13 81}
-set parms(test082) {-prevnodup 512 100 82}
+set parms(test082) {-prevnodup 100 82}
set parms(test083) {512 5000 2}
set parms(test084) {10000 84 65536}
set parms(test085) {512 3 10 85}
set parms(test086) ""
set parms(test087) {512 50 87}
set parms(test088) ""
-set parms(test090) {1000 -txn 90}
+set parms(test089) 1000
+set parms(test090) {10000 -txn 90}
set parms(test091) {4 2 1000 0 91}
+set parms(test092) {1000}
+set parms(test093) {10000 93}
+set parms(test094) {10000 10 94}
+set parms(test095) {1000 25 95}
+set parms(test096) {512 1000 19}
+set parms(test097) {500 400}
+set parms(test098) ""
+set parms(test099) 10000
+set parms(test100) {10000 -txn 100}
+set parms(test101) {10000 -txn 101}
+
+# RPC server executables. Each of these is tested (if it exists)
+# when running the RPC tests.
+set svc_list { berkeley_db_svc berkeley_db_cxxsvc \
+ berkeley_db_javasvc }
+set rpc_svc berkeley_db_svc
+
+# Shell script tests. Each list entry is a {directory filename} pair,
+# invoked with "/bin/sh filename".
+set shelltest_list {
+ { scr001 chk.code }
+ { scr002 chk.def }
+ { scr003 chk.define }
+ { scr004 chk.javafiles }
+ { scr005 chk.nl }
+ { scr006 chk.offt }
+ { scr007 chk.proto }
+ { scr008 chk.pubdef }
+ { scr009 chk.srcfiles }
+ { scr010 chk.str }
+ { scr011 chk.tags }
+ { scr012 chk.vx_code }
+ { scr013 chk.stats }
+ { scr014 chk.err }
+ { scr015 chk.cxxtests }
+ { scr016 chk.javatests }
+ { scr017 chk.db185 }
+ { scr018 chk.comma }
+ { scr019 chk.include }
+ { scr020 chk.inc }
+ { scr021 chk.flags }
+ { scr022 chk.rr }
+}
diff --git a/bdb/test/testutils.tcl b/bdb/test/testutils.tcl
index c5edaef7f6a..d1f89dd1e15 100644
--- a/bdb/test/testutils.tcl
+++ b/bdb/test/testutils.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
+# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: testutils.tcl,v 11.86 2001/01/18 23:21:14 krinsky Exp $
+# $Id: testutils.tcl,v 11.165 2002/09/05 17:54:04 sandstro Exp $
#
# Test system utilities
#
@@ -12,14 +12,25 @@
proc timestamp {{opt ""}} {
global __timestamp_start
+ set now [clock seconds]
+
+ # -c accurate to the click, instead of the second.
+ # -r seconds since the Epoch
+ # -t current time in the format expected by db_recover -t.
+ # -w wallclock time
+ # else wallclock plus elapsed time.
if {[string compare $opt "-r"] == 0} {
- clock seconds
+ return $now
} elseif {[string compare $opt "-t"] == 0} {
- # -t gives us the current time in the format expected by
- # db_recover -t.
- return [clock format [clock seconds] -format "%y%m%d%H%M.%S"]
+ return [clock format $now -format "%y%m%d%H%M.%S"]
+ } elseif {[string compare $opt "-w"] == 0} {
+ return [clock format $now -format "%c"]
} else {
- set now [clock seconds]
+ if {[string compare $opt "-c"] == 0} {
+ set printclicks 1
+ } else {
+ set printclicks 0
+ }
if {[catch {set start $__timestamp_start}] != 0} {
set __timestamp_start $now
@@ -30,7 +41,13 @@ proc timestamp {{opt ""}} {
set the_time [clock format $now -format ""]
set __timestamp_start $now
- format "%02d:%02d:%02d (%02d:%02d:%02d)" \
+ if { $printclicks == 1 } {
+ set pc_print [format ".%08u" [__fix_num [clock clicks]]]
+ } else {
+ set pc_print ""
+ }
+
+ format "%02d:%02d:%02d$pc_print (%02d:%02d:%02d)" \
[__fix_num [clock format $now -format "%H"]] \
[__fix_num [clock format $now -format "%M"]] \
[__fix_num [clock format $now -format "%S"]] \
@@ -115,32 +132,68 @@ proc get_file_as_key { db txn flags file} {
# open file and call dump_file to dumpkeys to tempfile
proc open_and_dump_file {
- dbname dbenv txn outfile checkfunc dump_func beg cont} {
+ dbname env outfile checkfunc dump_func beg cont } {
+ global encrypt
+ global passwd
source ./include.tcl
- if { $dbenv == "NULL" } {
- set db [berkdb open -rdonly -unknown $dbname]
- error_check_good dbopen [is_valid_db $db] TRUE
- } else {
- set db [berkdb open -env $dbenv -rdonly -unknown $dbname]
- error_check_good dbopen [is_valid_db $db] TRUE
+
+ set encarg ""
+ if { $encrypt > 0 && $env == "NULL" } {
+ set encarg "-encryptany $passwd"
+ }
+ set envarg ""
+ set txn ""
+ set txnenv 0
+ if { $env != "NULL" } {
+ append envarg " -env $env "
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append envarg " -auto_commit "
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
}
+ set db [eval {berkdb open} $envarg -rdonly -unknown $encarg $dbname]
+ error_check_good dbopen [is_valid_db $db] TRUE
$dump_func $db $txn $outfile $checkfunc $beg $cont
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
# open file and call dump_file to dumpkeys to tempfile
proc open_and_dump_subfile {
- dbname dbenv txn outfile checkfunc dump_func beg cont subdb} {
+ dbname env outfile checkfunc dump_func beg cont subdb} {
+ global encrypt
+ global passwd
source ./include.tcl
- if { $dbenv == "NULL" } {
- set db [berkdb open -rdonly -unknown $dbname $subdb]
- error_check_good dbopen [is_valid_db $db] TRUE
- } else {
- set db [berkdb open -env $dbenv -rdonly -unknown $dbname $subdb]
- error_check_good dbopen [is_valid_db $db] TRUE
+ set encarg ""
+ if { $encrypt > 0 && $env == "NULL" } {
+ set encarg "-encryptany $passwd"
+ }
+ set envarg ""
+ set txn ""
+ set txnenv 0
+ if { $env != "NULL" } {
+ append envarg "-env $env"
+ set txnenv [is_txnenv $env]
+ if { $txnenv == 1 } {
+ append envarg " -auto_commit "
+ set t [$env txn]
+ error_check_good txn [is_valid_txn $t $env] TRUE
+ set txn "-txn $t"
+ }
}
+ set db [eval {berkdb open -rdonly -unknown} \
+ $envarg $encarg {$dbname $subdb}]
+ error_check_good dbopen [is_valid_db $db] TRUE
$dump_func $db $txn $outfile $checkfunc $beg $cont
+ if { $txnenv == 1 } {
+ error_check_good txn [$t commit] 0
+ }
error_check_good db_close [$db close] 0
}
@@ -155,12 +208,18 @@ proc dump_file { db txn outfile checkfunc } {
proc dump_file_direction { db txn outfile checkfunc start continue } {
source ./include.tcl
- set outf [open $outfile w]
# Now we will get each key from the DB and dump to outfile
set c [eval {$db cursor} $txn]
error_check_good db_cursor [is_valid_cursor $c $db] TRUE
- for {set d [$c get $start] } { [llength $d] != 0 } {
- set d [$c get $continue] } {
+ dump_file_walk $c $outfile $checkfunc $start $continue
+ error_check_good curs_close [$c close] 0
+}
+
+proc dump_file_walk { c outfile checkfunc start continue {flag ""} } {
+ set outf [open $outfile w]
+ for {set d [eval {$c get} $flag $start] } \
+ { [llength $d] != 0 } \
+ {set d [eval {$c get} $flag $continue] } {
set kd [lindex $d 0]
set k [lindex $kd 0]
set d2 [lindex $kd 1]
@@ -170,7 +229,6 @@ proc dump_file_direction { db txn outfile checkfunc start continue } {
# puts $outf "$k $d2"
}
close $outf
- error_check_good curs_close [$c close] 0
}
proc dump_binkey_file { db txn outfile checkfunc } {
@@ -285,8 +343,8 @@ proc error_check_good { func result desired {txn 0} } {
}
# Locks have the prefix of their manager.
-proc is_substr { l mgr } {
- if { [string first $mgr $l] == -1 } {
+proc is_substr { str sub } {
+ if { [string first $sub $str] == -1 } {
return 0
} else {
return 1
@@ -297,7 +355,7 @@ proc release_list { l } {
# Now release all the locks
foreach el $l {
- set ret [$el put]
+ catch { $el put } ret
error_check_good lock_put $ret 0
}
}
@@ -374,6 +432,54 @@ proc dup_check { db txn tmpfile dlist {extra 0}} {
error_check_good curs_close [$c close] 0
}
+# Check if each key appears exactly [llength dlist] times in the file with
+# the duplicate tags matching those that appear in dlist.
+proc dup_file_check { db txn tmpfile dlist } {
+ source ./include.tcl
+
+ set outf [open $tmpfile w]
+ # Now we will get each key from the DB and dump to outfile
+ set c [eval {$db cursor} $txn]
+ set lastkey ""
+ set done 0
+ while { $done != 1} {
+ foreach did $dlist {
+ set rec [$c get "-next"]
+ if { [string length $rec] == 0 } {
+ set done 1
+ break
+ }
+ set key [lindex [lindex $rec 0] 0]
+ if { [string compare $key $lastkey] != 0 } {
+ #
+ # If we changed files read in new contents.
+ #
+ set fid [open $key r]
+ fconfigure $fid -translation binary
+ set filecont [read $fid]
+ close $fid
+ }
+ set fulldata [lindex [lindex $rec 0] 1]
+ set id [id_of $fulldata]
+ set d [data_of $fulldata]
+ if { [string compare $key $lastkey] != 0 && \
+ $id != [lindex $dlist 0] } {
+ set e [lindex $dlist 0]
+ error "FAIL: \tKey \
+ $key, expected dup id $e, got $id"
+ }
+ error_check_good dupget.data $d $filecont
+ error_check_good dupget.id $id $did
+ set lastkey $key
+ }
+ if { $done != 1 } {
+ puts $outf $key
+ }
+ }
+ close $outf
+ error_check_good curs_close [$c close] 0
+}
+
# Parse duplicate data entries of the form N:data. Data_of returns
# the data part; id_of returns the numerical part
proc data_of {str} {
@@ -513,7 +619,7 @@ proc sentinel_init { } {
set filelist {}
set ret [catch {glob $testdir/begin.*} result]
- if { $ret == 0 } {
+ if { $ret == 0 } {
set filelist $result
}
@@ -527,16 +633,33 @@ proc sentinel_init { } {
}
}
-proc watch_procs { {delay 30} {max 3600} } {
+proc watch_procs { pidlist {delay 30} {max 3600} {quiet 0} } {
source ./include.tcl
set elapsed 0
+
+ # Don't start watching the processes until a sentinel
+ # file has been created for each one.
+ foreach pid $pidlist {
+ while { [file exists $testdir/begin.$pid] == 0 } {
+ tclsleep $delay
+ incr elapsed $delay
+ # If pids haven't been created in one-tenth
+ # of the time allowed for the whole test,
+ # there's a problem. Report an error and fail.
+ if { $elapsed > [expr {$max / 10}] } {
+ puts "FAIL: begin.pid not created"
+ break
+ }
+ }
+ }
+
while { 1 } {
tclsleep $delay
incr elapsed $delay
- # Find the list of processes withoutstanding sentinel
+ # Find the list of processes with outstanding sentinel
# files (i.e. a begin.pid and no end.pid).
set beginlist {}
set endlist {}
@@ -586,18 +709,14 @@ proc watch_procs { {delay 30} {max 3600} } {
if { $elapsed > $max } {
# We have exceeded the limit; kill processes
# and report an error
- set rlist {}
foreach i $l {
- set r [catch { exec $KILL $i } result]
- if { $r == 0 } {
- lappend rlist $i
- }
+ tclkill $i
}
- error_check_good "Processes still running" \
- [llength $rlist] 0
}
}
- puts "All processes have exited."
+ if { $quiet == 0 } {
+ puts "All processes have exited."
+ }
}
# These routines are all used from within the dbscript.tcl tester.
@@ -935,7 +1054,7 @@ proc filecheck { file txn } {
unset check_array
}
- open_and_dump_file $file NULL $txn $file.dump dbcheck dump_full_file \
+ open_and_dump_file $file NULL $file.dump dbcheck dump_full_file \
"-first" "-next"
# Check that everything we checked had all its data
@@ -964,20 +1083,11 @@ proc filecheck { file txn } {
}
}
-proc esetup { dir } {
- source ./include.tcl
-
- set ret [berkdb envremove -home $dir]
-
- fileremove -f $dir/file0 $dir/file1 $dir/file2 $dir/file3
- set mp [memp $dir 0644 -create -cachesize { 0 10240 }]
- set lp [lock_open "" -create 0644]
- error_check_good memp_close [$mp close] 0
- error_check_good lock_close [$lp close] 0
-}
-
-proc cleanup { dir env } {
+proc cleanup { dir env { quiet 0 } } {
global gen_upgrade
+ global is_qnx_test
+ global old_encrypt
+ global passwd
global upgrade_dir
global upgrade_be
global upgrade_method
@@ -989,46 +1099,109 @@ proc cleanup { dir env } {
set maj [lindex $vers 0]
set min [lindex $vers 1]
- if { $upgrade_be == 1 } {
- set version_dir "$maj.${min}be"
+ # Is this machine big or little endian? We want to mark
+ # the test directories appropriately, since testing
+ # little-endian databases generated by a big-endian machine,
+ # and/or vice versa, is interesting.
+ if { [big_endian] } {
+ set myendianness be
} else {
- set version_dir "$maj.${min}le"
+ set myendianness le
}
- set dest $upgrade_dir/$version_dir/$upgrade_method/$upgrade_name
+ if { $upgrade_be == 1 } {
+ set version_dir "$myendianness-$maj.${min}be"
+ set en be
+ } else {
+ set version_dir "$myendianness-$maj.${min}le"
+ set en le
+ }
- catch {exec mkdir -p $dest}
- catch {exec sh -c "mv $dir/*.db $dest"}
- catch {exec sh -c "mv $dir/__dbq.* $dest"}
+ set dest $upgrade_dir/$version_dir/$upgrade_method
+ exec mkdir -p $dest
+
+ set dbfiles [glob -nocomplain $dir/*.db]
+ foreach dbfile $dbfiles {
+ set basename [string range $dbfile \
+ [expr [string length $dir] + 1] end-3]
+
+ set newbasename $upgrade_name-$basename
+
+ # db_dump file
+ error_check_good db_dump($dbfile) \
+ [catch {exec $util_path/db_dump -k $dbfile > \
+ $dir/$newbasename.dump}] 0
+
+ # tcl_dump file
+ upgrade_dump $dbfile \
+ $dir/$newbasename.tcldump
+
+ # Rename dbfile and any dbq files.
+ file rename $dbfile $dir/$newbasename-$en.db
+ foreach dbq \
+ [glob -nocomplain $dir/__dbq.$basename.db.*] {
+ set s [string length $dir/__dbq.]
+ set newname [string replace $dbq $s \
+ [expr [string length $basename] + $s - 1] \
+ $newbasename-$en]
+ file rename $dbq $newname
+ }
+ set cwd [pwd]
+ cd $dir
+ catch {eval exec tar -cvf $dest/$newbasename.tar \
+ [glob $newbasename* __dbq.$newbasename-$en.db.*]}
+ catch {exec gzip -9v $dest/$newbasename.tar}
+ cd $cwd
+ }
}
# check_handles
set remfiles {}
set ret [catch { glob $dir/* } result]
if { $ret == 0 } {
- foreach file $result {
+ foreach fileorig $result {
#
# We:
# - Ignore any env-related files, which are
# those that have __db.* or log.* if we are
- # running in an env.
+ # running in an env. Also ignore files whose
+ # names start with REPDIR_; these are replication
+ # subdirectories.
# - Call 'dbremove' on any databases.
# Remove any remaining temp files.
#
- switch -glob -- $file {
+ switch -glob -- $fileorig {
+ */DIR_* -
*/__db.* -
*/log.* {
if { $env != "NULL" } {
continue
} else {
- lappend remfiles $file
+ if { $is_qnx_test } {
+ catch {berkdb envremove -force \
+ -home $dir} r
+ }
+ lappend remfiles $fileorig
}
}
*.db {
set envargs ""
+ set encarg ""
+ #
+ # If in an env, it should be open crypto
+ # or not already.
+ #
if { $env != "NULL"} {
- set file [file tail $file]
+ set file [file tail $fileorig]
set envargs " -env $env "
+ if { [is_txnenv $env] } {
+ append envargs " -auto_commit "
+ }
+ } else {
+ if { $old_encrypt != 0 } {
+ set encarg "-encryptany $passwd"
+ }
+ set file $fileorig
}
# If a database is left in a corrupt
@@ -1038,15 +1211,33 @@ proc cleanup { dir env } {
# just forcibly remove the file with a warning
# message.
set ret [catch \
- {eval {berkdb dbremove} $envargs $file} res]
+ {eval {berkdb dbremove} $envargs $encarg \
+ $file} res]
if { $ret != 0 } {
- puts \
+ # If it failed, there is a chance
+ # that the previous run was using
+ # encryption and we cannot know about
+ # it (different tclsh instantiation).
+ # Try to remove it with crypto.
+ if { $env == "NULL" && \
+ $old_encrypt == 0} {
+ set ret [catch \
+ {eval {berkdb dbremove} \
+ -encryptany $passwd \
+ $envargs $file} res]
+ }
+ if { $ret != 0 } {
+ if { $quiet == 0 } {
+ puts \
"FAIL: dbremove in cleanup failed: $res"
- lappend remfiles $file
+ }
+ set file $fileorig
+ lappend remfiles $file
+ }
}
}
default {
- lappend remfiles $file
+ lappend remfiles $fileorig
}
}
}
@@ -1068,9 +1259,15 @@ proc log_cleanup { dir } {
}
proc env_cleanup { dir } {
+ global old_encrypt
+ global passwd
source ./include.tcl
- set stat [catch {berkdb envremove -home $dir} ret]
+ set encarg ""
+ if { $old_encrypt != 0 } {
+ set encarg "-encryptany $passwd"
+ }
+ set stat [catch {eval {berkdb envremove -home} $dir $encarg} ret]
#
# If something failed and we are left with a region entry
# in /dev/shmem that is zero-length, the envremove will
@@ -1136,33 +1333,90 @@ proc help { cmd } {
# Notice that we catch the return from CP and do not do anything with it.
# This is because Solaris CP seems to exit non-zero on occasion, but
# everything else seems to run just fine.
+#
+# We split it into two functions so that the preparation and command
+# could be executed in a different process than the recovery.
+#
+proc op_codeparse { encodedop op } {
+ set op1 ""
+ set op2 ""
+ switch $encodedop {
+ "abort" {
+ set op1 $encodedop
+ set op2 ""
+ }
+ "commit" {
+ set op1 $encodedop
+ set op2 ""
+ }
+ "prepare-abort" {
+ set op1 "prepare"
+ set op2 "abort"
+ }
+ "prepare-commit" {
+ set op1 "prepare"
+ set op2 "commit"
+ }
+ "prepare-discard" {
+ set op1 "prepare"
+ set op2 "discard"
+ }
+ }
+
+ if { $op == "op" } {
+ return $op1
+ } else {
+ return $op2
+ }
+}
+
proc op_recover { encodedop dir env_cmd dbfile cmd msg } {
+ source ./include.tcl
+
+ set op [op_codeparse $encodedop "op"]
+ set op2 [op_codeparse $encodedop "sub"]
+ puts "\t$msg $encodedop"
+ set gidf ""
+ if { $op == "prepare" } {
+ sentinel_init
+
+ # Fork off a child to run the cmd
+ # We append the gid, so start here making sure
+ # we don't have old gid's around.
+ set outfile $testdir/childlog
+ fileremove -f $testdir/gidfile
+ set gidf $testdir/gidfile
+ set pidlist {}
+ # puts "$tclsh_path $test_path/recdscript.tcl $testdir/recdout \
+ # $op $dir $env_cmd $dbfile $gidf $cmd"
+ set p [exec $tclsh_path $test_path/wrap.tcl recdscript.tcl \
+ $testdir/recdout $op $dir $env_cmd $dbfile $gidf $cmd &]
+ lappend pidlist $p
+ watch_procs $pidlist 5
+ set f1 [open $testdir/recdout r]
+ set r [read $f1]
+ puts -nonewline $r
+ close $f1
+ fileremove -f $testdir/recdout
+ } else {
+ op_recover_prep $op $dir $env_cmd $dbfile $gidf $cmd
+ }
+ op_recover_rec $op $op2 $dir $env_cmd $dbfile $gidf
+}
+
+proc op_recover_prep { op dir env_cmd dbfile gidf cmd } {
global log_log_record_types
global recd_debug
global recd_id
global recd_op
source ./include.tcl
- #puts "op_recover: $encodedop $dir $env_cmd $dbfile $cmd $msg"
+ #puts "op_recover: $op $dir $env $dbfile $cmd"
set init_file $dir/t1
set afterop_file $dir/t2
set final_file $dir/t3
- set op ""
- set op2 ""
- if { $encodedop == "prepare-abort" } {
- set op "prepare"
- set op2 "abort"
- } elseif { $encodedop == "prepare-commit" } {
- set op "prepare"
- set op2 "commit"
- } else {
- set op $encodedop
- }
-
- puts "\t$msg $encodedop"
-
# Keep track of the log types we've seen
if { $log_log_record_types == 1} {
logtrack_read $dir
@@ -1172,13 +1426,15 @@ proc op_recover { encodedop dir env_cmd dbfile cmd msg } {
catch { file copy -force $dir/$dbfile $dir/$dbfile.init } res
copy_extent_file $dir $dbfile init
+ convert_encrypt $env_cmd
set env [eval $env_cmd]
- set db [berkdb open -env $env $dbfile]
+ error_check_good envopen [is_valid_env $env] TRUE
+
+ set db [berkdb open -auto_commit -env $env $dbfile]
error_check_good dbopen [is_valid_db $db] TRUE
# Dump out file contents for initial case
- set tflags ""
- open_and_dump_file $dbfile $env $tflags $init_file nop \
+ open_and_dump_file $dbfile $env $init_file nop \
dump_file_direction "-first" "-next"
set t [$env txn]
@@ -1233,43 +1489,38 @@ proc op_recover { encodedop dir env_cmd dbfile cmd msg } {
set record_exec_cmd_ret 0
set lenient_exec_cmd_ret 0
- # Sync the file so that we can capture a snapshot to test
- # recovery.
+ # Sync the file so that we can capture a snapshot to test recovery.
error_check_good sync:$db [$db sync] 0
catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
copy_extent_file $dir $dbfile afterop
+ open_and_dump_file $dir/$dbfile.afterop NULL \
+ $afterop_file nop dump_file_direction "-first" "-next"
- #set tflags "-txn $t"
- open_and_dump_file $dir/$dbfile.afterop NULL $tflags \
- $afterop_file nop dump_file_direction \
- "-first" "-next"
#puts "\t\t\tExecuting txn_$op:$t"
- error_check_good txn_$op:$t [$t $op] 0
- if { $op2 != "" } {
- #puts "\t\t\tExecuting txn_$op2:$t"
- error_check_good txn_$op2:$t [$t $op2] 0
+ if { $op == "prepare" } {
+ set gid [make_gid global:$t]
+ set gfd [open $gidf w+]
+ puts $gfd $gid
+ close $gfd
+ error_check_good txn_$op:$t [$t $op $gid] 0
+ } else {
+ error_check_good txn_$op:$t [$t $op] 0
}
- switch $encodedop {
+ switch $op {
"commit" { puts "\t\tCommand executed and committed." }
"abort" { puts "\t\tCommand executed and aborted." }
"prepare" { puts "\t\tCommand executed and prepared." }
- "prepare-commit" {
- puts "\t\tCommand executed, prepared, and committed."
- }
- "prepare-abort" {
- puts "\t\tCommand executed, prepared, and aborted."
- }
}
- # Dump out file and save a copy.
+ # Sync the file so that we can capture a snapshot to test recovery.
error_check_good sync:$db [$db sync] 0
- open_and_dump_file $dir/$dbfile NULL $tflags $final_file nop \
- dump_file_direction "-first" "-next"
catch { file copy -force $dir/$dbfile $dir/$dbfile.final } res
copy_extent_file $dir $dbfile final
+ open_and_dump_file $dir/$dbfile.final NULL \
+ $final_file nop dump_file_direction "-first" "-next"
# If this is an abort or prepare-abort, it should match the
# original file.
@@ -1281,56 +1532,121 @@ proc op_recover { encodedop dir env_cmd dbfile cmd msg } {
# Thus we just skip this in the prepare-only case; what
# we care about are the results of a prepare followed by a
# recovery, which we test later.
- if { $op == "commit" || $op2 == "commit" } {
+ if { $op == "commit" } {
filesort $afterop_file $afterop_file.sort
filesort $final_file $final_file.sort
error_check_good \
diff(post-$op,pre-commit):diff($afterop_file,$final_file) \
[filecmp $afterop_file.sort $final_file.sort] 0
- } elseif { $op == "abort" || $op2 == "abort" } {
+ } elseif { $op == "abort" } {
filesort $init_file $init_file.sort
filesort $final_file $final_file.sort
error_check_good \
diff(initial,post-$op):diff($init_file,$final_file) \
[filecmp $init_file.sort $final_file.sort] 0
} else {
- # Make sure this really is a prepare-only
- error_check_good assert:prepare-only $encodedop "prepare"
+ # Make sure this really is one of the prepare tests
+ error_check_good assert:prepare-test $op "prepare"
}
# Running recovery on this database should not do anything.
# Flush all data to disk, close the environment and save the
# file.
- error_check_good close:$db [$db close] 0
-
- # If all we've done is a prepare, then there's still a
- # transaction active, and an env close will return DB_RUNRECOVERY
- if { $encodedop == "prepare" } {
- catch {$env close} ret
- error_check_good env_close \
- [is_substr $ret DB_RUNRECOVERY] 1
- } else {
- reset_env $env
+ # XXX DO NOT CLOSE FILE ON PREPARE -- if you are prepared,
+ # you really have an active transaction and you're not allowed
+ # to close files that are being acted upon by in-process
+ # transactions.
+ if { $op != "prepare" } {
+ error_check_good close:$db [$db close] 0
+ }
+
+ #
+ # If we are running 'prepare' don't close the env with an
+ # active transaction. Leave it alone so the close won't
+ # quietly abort it on us.
+ if { [is_substr $op "prepare"] != 1 } {
+ error_check_good envclose [$env close] 0
+ }
+ return
+}
+
+proc op_recover_rec { op op2 dir env_cmd dbfile gidf} {
+ global log_log_record_types
+ global recd_debug
+ global recd_id
+ global recd_op
+ global encrypt
+ global passwd
+ source ./include.tcl
+
+ #puts "op_recover_rec: $op $op2 $dir $env_cmd $dbfile $gidf"
+
+ set init_file $dir/t1
+ set afterop_file $dir/t2
+ set final_file $dir/t3
+
+ # Keep track of the log types we've seen
+ if { $log_log_record_types == 1} {
+ logtrack_read $dir
}
berkdb debug_check
- puts -nonewline "\t\tRunning recovery ... "
+ puts -nonewline "\t\top_recover_rec: Running recovery ... "
flush stdout
- set stat [catch {exec $util_path/db_recover -h $dir -c} result]
+ set recargs "-h $dir -c "
+ if { $encrypt > 0 } {
+ append recargs " -P $passwd "
+ }
+ set stat [catch {eval exec $util_path/db_recover -e $recargs} result]
if { $stat == 1 } {
error "FAIL: Recovery error: $result."
}
puts -nonewline "complete ... "
- error_check_good db_verify [verify_dir $testdir "\t\t" 0 1] 0
+ #
+ # We cannot run db_recover here because that will open an env, run
+ # recovery, then close it, which will abort the outstanding txns.
+ # We want to do it ourselves.
+ #
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_widget $env env] TRUE
+ error_check_good db_verify [verify_dir $testdir "\t\t" 0 1] 0
puts "verified"
- berkdb debug_check
- set env [eval $env_cmd]
- error_check_good dbenv [is_valid_widget $env env] TRUE
- open_and_dump_file $dir/$dbfile NULL $tflags $final_file nop \
+ # If we left a txn as prepared, but not aborted or committed,
+ # we need to do a txn_recover. Make sure we have the same
+ # number of txns we want.
+ if { $op == "prepare"} {
+ set txns [$env txn_recover]
+ error_check_bad txnrecover [llength $txns] 0
+ set gfd [open $gidf r]
+ set origgid [read -nonewline $gfd]
+ close $gfd
+ set txnlist [lindex $txns 0]
+ set t [lindex $txnlist 0]
+ set gid [lindex $txnlist 1]
+ error_check_good gidcompare $gid $origgid
+ puts "\t\t\tExecuting txn_$op2:$t"
+ error_check_good txn_$op2:$t [$t $op2] 0
+ #
+ # If we are testing discard, we do need to resolve
+ # the txn, so get the list again and now abort it.
+ #
+ if { $op2 == "discard" } {
+ set txns [$env txn_recover]
+ error_check_bad txnrecover [llength $txns] 0
+ set txnlist [lindex $txns 0]
+ set t [lindex $txnlist 0]
+ set gid [lindex $txnlist 1]
+ error_check_good gidcompare $gid $origgid
+ puts "\t\t\tExecuting txn_abort:$t"
+ error_check_good disc_txn_abort:$t [$t abort] 0
+ }
+ }
+
+ open_and_dump_file $dir/$dbfile NULL $final_file nop \
dump_file_direction "-first" "-next"
if { $op == "commit" || $op2 == "commit" } {
filesort $afterop_file $afterop_file.sort
@@ -1358,11 +1674,10 @@ proc op_recover { encodedop dir env_cmd dbfile cmd msg } {
}
berkdb debug_check
- puts -nonewline \
- "\t\tRunning recovery on pre-op database ... "
+ puts -nonewline "\t\tRunning recovery on pre-op database ... "
flush stdout
- set stat [catch {exec $util_path/db_recover -h $dir -c} result]
+ set stat [catch {eval exec $util_path/db_recover $recargs} result]
if { $stat == 1 } {
error "FAIL: Recovery error: $result."
}
@@ -1374,7 +1689,7 @@ proc op_recover { encodedop dir env_cmd dbfile cmd msg } {
set env [eval $env_cmd]
- open_and_dump_file $dir/$dbfile NULL $tflags $final_file nop \
+ open_and_dump_file $dir/$dbfile NULL $final_file nop \
dump_file_direction "-first" "-next"
if { $op == "commit" || $op2 == "commit" } {
filesort $final_file $final_file.sort
@@ -1458,6 +1773,54 @@ proc reset_env { env } {
error_check_good env_close [$env close] 0
}
+proc minlocks { myenv locker_id obj_id num } {
+ return [countlocks $myenv $locker_id $obj_id $num ]
+}
+
+proc maxlocks { myenv locker_id obj_id num } {
+ return [countlocks $myenv $locker_id $obj_id $num ]
+}
+
+proc minwrites { myenv locker_id obj_id num } {
+ return [countlocks $myenv $locker_id $obj_id $num ]
+}
+
+proc countlocks { myenv locker_id obj_id num } {
+ set locklist ""
+ for { set i 0} {$i < [expr $obj_id * 4]} { incr i } {
+ set r [catch {$myenv lock_get read $locker_id \
+ [expr $obj_id * 1000 + $i]} l ]
+ if { $r != 0 } {
+ puts $l
+ return ERROR
+ } else {
+ error_check_good lockget:$obj_id [is_substr $l $myenv] 1
+ lappend locklist $l
+ }
+ }
+
+ # Now acquire a write lock
+ if { $obj_id != 1 } {
+ set r [catch {$myenv lock_get write $locker_id \
+ [expr $obj_id * 1000 + 10]} l ]
+ if { $r != 0 } {
+ puts $l
+ return ERROR
+ } else {
+ error_check_good lockget:$obj_id [is_substr $l $myenv] 1
+ lappend locklist $l
+ }
+ }
+
+ set ret [ring $myenv $locker_id $obj_id $num]
+
+ foreach l $locklist {
+ error_check_good lockput:$l [$l put] 0
+ }
+
+ return $ret
+}
+
# This routine will let us obtain a ring of deadlocks.
# Each locker will get a lock on obj_id, then sleep, and
# then try to lock (obj_id + 1) % num.
@@ -1469,7 +1832,7 @@ proc ring { myenv locker_id obj_id num } {
source ./include.tcl
if {[catch {$myenv lock_get write $locker_id $obj_id} lock1] != 0} {
- puts $errorInfo
+ puts $lock1
return ERROR
} else {
error_check_good lockget:$obj_id [is_substr $lock1 $myenv] 1
@@ -1482,6 +1845,7 @@ proc ring { myenv locker_id obj_id num } {
if {[string match "*DEADLOCK*" $lock2] == 1} {
set ret DEADLOCK
} else {
+ puts $lock2
set ret ERROR
}
} else {
@@ -1511,7 +1875,7 @@ proc clump { myenv locker_id obj_id num } {
set obj_id 10
if {[catch {$myenv lock_get read $locker_id $obj_id} lock1] != 0} {
- puts $errorInfo
+ puts $lock1
return ERROR
} else {
error_check_good lockget:$obj_id \
@@ -1542,10 +1906,15 @@ proc clump { myenv locker_id obj_id num } {
return $ret
}
-proc dead_check { t procs dead clean other } {
+proc dead_check { t procs timeout dead clean other } {
error_check_good $t:$procs:other $other 0
switch $t {
ring {
+ # with timeouts the number of deadlocks is unpredictable
+ if { $timeout != 0 && $dead > 1 } {
+ set clean [ expr $clean + $dead - 1]
+ set dead 1
+ }
error_check_good $t:$procs:deadlocks $dead 1
error_check_good $t:$procs:success $clean \
[expr $procs - 1]
@@ -1555,6 +1924,26 @@ proc dead_check { t procs dead clean other } {
[expr $procs - 1]
error_check_good $t:$procs:success $clean 1
}
+ oldyoung {
+ error_check_good $t:$procs:deadlocks $dead 1
+ error_check_good $t:$procs:success $clean \
+ [expr $procs - 1]
+ }
+ minlocks {
+ error_check_good $t:$procs:deadlocks $dead 1
+ error_check_good $t:$procs:success $clean \
+ [expr $procs - 1]
+ }
+ maxlocks {
+ error_check_good $t:$procs:deadlocks $dead 1
+ error_check_good $t:$procs:success $clean \
+ [expr $procs - 1]
+ }
+ minwrites {
+ error_check_good $t:$procs:deadlocks $dead 1
+ error_check_good $t:$procs:success $clean \
+ [expr $procs - 1]
+ }
default {
error "Test $t not implemented"
}
@@ -1604,6 +1993,9 @@ proc reverse { s } {
return $res
}
+#
+# This is a internal only proc. All tests should use 'is_valid_db' etc.
+#
proc is_valid_widget { w expected } {
# First N characters must match "expected"
set l [string length $expected]
@@ -1640,6 +2032,10 @@ proc is_valid_lock { lock env } {
return [is_valid_widget $lock $env.lock]
}
+proc is_valid_logc { logc env } {
+ return [is_valid_widget $logc $env.logc]
+}
+
proc is_valid_mpool { mpool env } {
return [is_valid_widget $mpool $env.mp]
}
@@ -1656,11 +2052,20 @@ proc is_valid_mutex { m env } {
return [is_valid_widget $m $env.mutex]
}
+proc is_valid_lock {l env} {
+ return [is_valid_widget $l $env.lock]
+}
+
+proc is_valid_locker {l } {
+ return [is_valid_widget $l ""]
+}
+
proc send_cmd { fd cmd {sleep 2}} {
source ./include.tcl
- puts $fd "set v \[$cmd\]"
- puts $fd "puts \$v"
+ puts $fd "if \[catch {set v \[$cmd\] ; puts \$v} ret\] { \
+ puts \"FAIL: \$ret\" \
+ }"
puts $fd "flush stdout"
flush $fd
berkdb debug_check
@@ -1747,6 +2152,20 @@ proc make_fixed_length {method data {pad 0}} {
return $data
}
+proc make_gid {data} {
+ while { [string length $data] < 127 } {
+ set data [format ${data}0]
+ }
+ return $data
+}
+
+proc make_gid {data} {
+ while { [string length $data] < 128 } {
+ set data [format ${data}0]
+ }
+ return $data
+}
+
# shift data for partial
# pad with fixed pad (which is NULL)
proc partial_shift { data offset direction} {
@@ -1785,7 +2204,9 @@ proc convert_method { method } {
switch -- $method {
-btree -
-dbtree -
+ dbtree -
-ddbtree -
+ ddbtree -
-rbtree -
BTREE -
DB_BTREE -
@@ -1799,9 +2220,12 @@ proc convert_method { method } {
rbtree { return "-btree" }
-dhash -
+ -ddhash -
-hash -
DB_HASH -
HASH -
+ dhash -
+ ddhash -
db_hash -
h -
hash { return "-hash" }
@@ -1819,7 +2243,7 @@ proc convert_method { method } {
qe -
qamext -
-queueext -
- queueextent -
+ queueextent -
queueext { return "-queue" }
-frecno -
@@ -1845,6 +2269,32 @@ proc convert_method { method } {
}
}
+proc split_encargs { largs encargsp } {
+ global encrypt
+ upvar $encargsp e
+ set eindex [lsearch $largs "-encrypta*"]
+ if { $eindex == -1 } {
+ set e ""
+ set newl $largs
+ } else {
+ set eend [expr $eindex + 1]
+ set e [lrange $largs $eindex $eend]
+ set newl [lreplace $largs $eindex $eend "-encrypt"]
+ }
+ return $newl
+}
+
+proc convert_encrypt { largs } {
+ global encrypt
+ global old_encrypt
+
+ set old_encrypt $encrypt
+ set encrypt 0
+ if { [lsearch $largs "-encrypt*"] != -1 } {
+ set encrypt 1
+ }
+}
+
# If recno-with-renumbering or btree-with-renumbering is specified, then
# fix the arguments to specify the DB_RENUMBER/DB_RECNUM option for the
# -flags argument.
@@ -1856,13 +2306,15 @@ proc convert_args { method {largs ""} } {
source ./include.tcl
if { [string first - $largs] == -1 &&\
- [string compare $largs ""] != 0 } {
+ [string compare $largs ""] != 0 &&\
+ [string compare $largs {{}}] != 0 } {
set errstring "args must contain a hyphen; does this test\
have no numeric args?"
- puts "FAIL:[timestamp] $errstring"
+ puts "FAIL:[timestamp] $errstring (largs was $largs)"
return -code return
}
+ convert_encrypt $largs
if { $gen_upgrade == 1 && $upgrade_be == 1 } {
append largs " -lorder 4321 "
} elseif { $gen_upgrade == 1 && $upgrade_be != 1 } {
@@ -1880,6 +2332,9 @@ proc convert_args { method {largs ""} } {
append largs " -dupsort "
} elseif { [is_dhash $method] == 1 } {
append largs " -dup "
+ } elseif { [is_ddhash $method] == 1 } {
+ append largs " -dup "
+ append largs " -dupsort "
} elseif { [is_queueext $method] == 1 } {
append largs " -extent 2 "
}
@@ -1900,7 +2355,7 @@ proc is_btree { method } {
}
proc is_dbtree { method } {
- set names { -dbtree }
+ set names { -dbtree dbtree }
if { [lsearch $names $method] >= 0 } {
return 1
} else {
@@ -1909,7 +2364,7 @@ proc is_dbtree { method } {
}
proc is_ddbtree { method } {
- set names { -ddbtree }
+ set names { -ddbtree ddbtree }
if { [lsearch $names $method] >= 0 } {
return 1
} else {
@@ -1963,7 +2418,16 @@ proc is_hash { method } {
}
proc is_dhash { method } {
- set names { -dhash }
+ set names { -dhash dhash }
+ if { [lsearch $names $method] >= 0 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_ddhash { method } {
+ set names { -ddhash ddhash }
if { [lsearch $names $method] >= 0 } {
return 1
} else {
@@ -2107,6 +2571,16 @@ proc tclsleep { s } {
after [expr $s * 1000 + 56]
}
+# Kill a process.
+proc tclkill { id } {
+ source ./include.tcl
+
+ while { [ catch {exec $KILL -0 $id} ] == 0 } {
+ catch {exec $KILL -9 $id}
+ tclsleep 5
+ }
+}
+
# Compare two files, a la diff. Returns 1 if non-identical, 0 if identical.
proc filecmp { file_a file_b } {
set fda [open $file_a r]
@@ -2133,17 +2607,47 @@ proc filecmp { file_a file_b } {
return 0
}
+# Give two SORTED files, one of which is a complete superset of the other,
+# extract out the unique portions of the superset and put them in
+# the given outfile.
+proc fileextract { superset subset outfile } {
+ set sup [open $superset r]
+ set sub [open $subset r]
+ set outf [open $outfile w]
+
+ # The gets can't be in the while condition because we'll
+ # get short-circuit evaluated.
+ set nrp [gets $sup pline]
+ set nrb [gets $sub bline]
+ while { $nrp >= 0 } {
+ if { $nrp != $nrb || [string compare $pline $bline] != 0} {
+ puts $outf $pline
+ } else {
+ set nrb [gets $sub bline]
+ }
+ set nrp [gets $sup pline]
+ }
+
+ close $sup
+ close $sub
+ close $outf
+ return 0
+}
+
# Verify all .db files in the specified directory.
-proc verify_dir { \
- {directory "./TESTDIR"} { pref "" } { noredo 0 } { quiet 0 } } {
+proc verify_dir { {directory $testdir} \
+ { pref "" } { noredo 0 } { quiet 0 } { nodump 0 } { cachesize 0 } } {
+ global encrypt
+ global passwd
+
# If we're doing database verification between tests, we don't
# want to do verification twice without an intervening cleanup--some
# test was skipped. Always verify by default (noredo == 0) so
# that explicit calls to verify_dir during tests don't require
# cleanup commands.
- if { $noredo == 1 } {
+ if { $noredo == 1 } {
if { [file exists $directory/NOREVERIFY] == 1 } {
- if { $quiet == 0 } {
+ if { $quiet == 0 } {
puts "Skipping verification."
}
return
@@ -2164,21 +2668,177 @@ proc verify_dir { \
set errpfxarg {-errpfx "FAIL: verify" }
set errarg $errfilearg$errpfxarg
set ret 0
+
+ # Open an env, so that we have a large enough cache. Pick
+ # a fairly generous default if we haven't specified something else.
+
+ if { $cachesize == 0 } {
+ set cachesize [expr 1024 * 1024]
+ }
+ set encarg ""
+ if { $encrypt != 0 } {
+ set encarg "-encryptaes $passwd"
+ }
+
+ set env [eval {berkdb_env -create -private} $encarg \
+ {-cachesize [list 0 $cachesize 0]}]
+ set earg " -env $env $errarg "
+
foreach db $dbs {
- if { [catch {eval {berkdb dbverify} $errarg $db} res] != 0 } {
+ if { [catch {eval {berkdb dbverify} $earg $db} res] != 0 } {
puts $res
puts "FAIL:[timestamp] Verification of $db failed."
set ret 1
+ continue
} else {
error_check_good verify:$db $res 0
- if { $quiet == 0 } {
+ if { $quiet == 0 } {
puts "${pref}Verification of $db succeeded."
}
}
+
+ # Skip the dump if it's dangerous to do it.
+ if { $nodump == 0 } {
+ if { [catch {eval dumploadtest $db} res] != 0 } {
+ puts $res
+ puts "FAIL:[timestamp] Dump/load of $db failed."
+ set ret 1
+ continue
+ } else {
+ error_check_good dumpload:$db $res 0
+ if { $quiet == 0 } {
+ puts \
+ "${pref}Dump/load of $db succeeded."
+ }
+ }
+ }
}
+
+ error_check_good vrfyenv_close [$env close] 0
+
return $ret
}
+# Is the database handle in $db a master database containing subdbs?
+proc check_for_subdbs { db } {
+ set stat [$db stat]
+ for { set i 0 } { [string length [lindex $stat $i]] > 0 } { incr i } {
+ set elem [lindex $stat $i]
+ if { [string compare [lindex $elem 0] Flags] == 0 } {
+ # This is the list of flags; look for
+ # "subdatabases".
+ if { [is_substr [lindex $elem 1] subdatabases] } {
+ return 1
+ }
+ }
+ }
+ return 0
+}
+
+proc dumploadtest { db {subdb ""} } {
+ global util_path
+ global encrypt
+ global passwd
+
+ set newdbname $db-dumpload.db
+
+ # Open original database, or subdb if we have one.
+ set dbarg ""
+ set utilflag ""
+ if { $encrypt != 0 } {
+ set dbarg "-encryptany $passwd"
+ set utilflag "-P $passwd"
+ }
+ set max_size [expr 15 * 1024]
+ if { [string length $subdb] == 0 } {
+ set olddb [eval {berkdb_open -rdonly} $dbarg $db]
+ error_check_good olddb($db) [is_valid_db $olddb] TRUE
+
+ if { [check_for_subdbs $olddb] } {
+ # If $db has subdatabases, dumploadtest each one
+ # separately.
+ set oc [$olddb cursor]
+ error_check_good orig_cursor($db) \
+ [is_valid_cursor $oc $olddb] TRUE
+
+ for { set dbt [$oc get -first] } \
+ { [llength $dbt] > 0 } \
+ { set dbt [$oc get -next] } {
+ set subdb [lindex [lindex $dbt 0] 0]
+
+ # Skip any files over this size. The problem is
+ # that when when we dump/load it, files that are
+ # too big result in E2BIG errors because the
+ # arguments to db_dump are too long. 64K seems
+ # to be the limit (on FreeBSD), cut it to 32K
+ # just to be safe.
+ if {[string length $subdb] < $max_size && \
+ [string length $subdb] != 0} {
+ dumploadtest $db $subdb
+ }
+ }
+ error_check_good oldcclose [$oc close] 0
+ error_check_good olddbclose [$olddb close] 0
+ return 0
+ }
+ # No subdatabase
+ set have_subdb 0
+ } else {
+ set olddb [eval {berkdb_open -rdonly} $dbarg {$db $subdb}]
+ error_check_good olddb($db) [is_valid_db $olddb] TRUE
+
+ set have_subdb 1
+ }
+
+ # Do a db_dump test. Dump/load each file.
+ if { $have_subdb } {
+ set rval [catch {eval {exec $util_path/db_dump} $utilflag -k \
+ -s {$subdb} $db | \
+ $util_path/db_load $utilflag $newdbname} res]
+ } else {
+ set rval [catch {eval {exec $util_path/db_dump} $utilflag -k \
+ $db | $util_path/db_load $utilflag $newdbname} res]
+ }
+ error_check_good db_dump/db_load($db:$res) $rval 0
+
+ # Now open new database.
+ set newdb [eval {berkdb_open -rdonly} $dbarg $newdbname]
+ error_check_good newdb($db) [is_valid_db $newdb] TRUE
+
+ # Walk through olddb and newdb and make sure their contents
+ # are identical.
+ set oc [$olddb cursor]
+ set nc [$newdb cursor]
+ error_check_good orig_cursor($db) \
+ [is_valid_cursor $oc $olddb] TRUE
+ error_check_good new_cursor($db) \
+ [is_valid_cursor $nc $newdb] TRUE
+
+ for { set odbt [$oc get -first] } { [llength $odbt] > 0 } \
+ { set odbt [$oc get -next] } {
+ set ndbt [$nc get -get_both \
+ [lindex [lindex $odbt 0] 0] [lindex [lindex $odbt 0] 1]]
+ error_check_good db_compare($db/$newdbname) $ndbt $odbt
+ }
+
+ for { set ndbt [$nc get -first] } { [llength $ndbt] > 0 } \
+ { set ndbt [$nc get -next] } {
+ set odbt [$oc get -get_both \
+ [lindex [lindex $ndbt 0] 0] [lindex [lindex $ndbt 0] 1]]
+ error_check_good db_compare_back($db) $odbt $ndbt
+ }
+
+ error_check_good orig_cursor_close($db) [$oc close] 0
+ error_check_good new_cursor_close($db) [$nc close] 0
+
+ error_check_good orig_db_close($db) [$olddb close] 0
+ error_check_good new_db_close($db) [$newdb close] 0
+
+ eval berkdb dbremove $dbarg $newdbname
+
+ return 0
+}
+
# Generate randomly ordered, guaranteed-unique four-character strings that can
# be used to differentiate duplicates without creating duplicate duplicates.
# (test031 & test032) randstring_init is required before the first call to
@@ -2285,10 +2945,16 @@ proc extractflags { args } {
# Wrapper for berkdb open, used throughout the test suite so that we can
# set an errfile/errpfx as appropriate.
proc berkdb_open { args } {
+ global is_envmethod
+
+ if { [info exists is_envmethod] == 0 } {
+ set is_envmethod 0
+ }
+
set errargs {}
- if { [file exists /dev/stderr] == 1 } {
+ if { $is_envmethod == 0 && [file exists /dev/stderr] == 1 } {
append errargs " -errfile /dev/stderr "
- append errargs " -errpfx \\F\\A\\I\\L "
+ append errargs " -errpfx \\F\\A\\I\\L"
}
eval {berkdb open} $errargs $args
@@ -2299,6 +2965,29 @@ proc berkdb_open_noerr { args } {
eval {berkdb open} $args
}
+# Wrapper for berkdb env, used throughout the test suite so that we can
+# set an errfile/errpfx as appropriate.
+proc berkdb_env { args } {
+ global is_envmethod
+
+ if { [info exists is_envmethod] == 0 } {
+ set is_envmethod 0
+ }
+
+ set errargs {}
+ if { $is_envmethod == 0 && [file exists /dev/stderr] == 1 } {
+ append errargs " -errfile /dev/stderr "
+ append errargs " -errpfx \\F\\A\\I\\L"
+ }
+
+ eval {berkdb env} $errargs $args
+}
+
+# Version without errpfx/errfile, used when we're expecting a failure.
+proc berkdb_env_noerr { args } {
+ eval {berkdb env} $args
+}
+
proc check_handles { {outf stdout} } {
global ohandles
@@ -2314,8 +3003,16 @@ proc open_handles { } {
}
proc move_file_extent { dir dbfile tag op } {
- set files [get_extfiles $dir $dbfile $tag]
- foreach extfile $files {
+ set curfiles [get_extfiles $dir $dbfile ""]
+ set tagfiles [get_extfiles $dir $dbfile $tag]
+ #
+ # We want to copy or rename only those that have been saved,
+ # so delete all the current extent files so that we don't
+ # end up with extra ones we didn't restore from our saved ones.
+ foreach extfile $curfiles {
+ file delete -force $extfile
+ }
+ foreach extfile $tagfiles {
set i [string last "." $extfile]
incr i
set extnum [string range $extfile $i end]
@@ -2378,3 +3075,135 @@ proc get_pagesize { stat } {
}
return -1
}
+
+# Get a globbed list of source files and executables to use as large
+# data items in overflow page tests.
+proc get_file_list { {small 0} } {
+ global is_windows_test
+ global is_qnx_test
+ global src_root
+
+ if { $is_qnx_test } {
+ set small 1
+ }
+ if { $small && $is_windows_test } {
+ return [glob $src_root/*/*.c */env*.obj]
+ } elseif { $small } {
+ return [glob $src_root/*/*.c ./env*.o]
+ } elseif { $is_windows_test } {
+ return \
+ [glob $src_root/*/*.c */*.obj */libdb??.dll */libdb??d.dll]
+ } else {
+ return [glob $src_root/*/*.c ./*.o ./.libs/libdb-?.?.s?]
+ }
+}
+
+proc is_cdbenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -cdb] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_lockenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -lock] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_logenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -log] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_mpoolenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -mpool] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_rpcenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -rpc] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_secenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -crypto] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc is_txnenv { env } {
+ set sys [$env attributes]
+ if { [lsearch $sys -txn] != -1 } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+proc get_home { env } {
+ set sys [$env attributes]
+ set h [lsearch $sys -home]
+ if { $h == -1 } {
+ return NULL
+ }
+ incr h
+ return [lindex $sys $h]
+}
+
+proc reduce_dups { nent ndp } {
+ upvar $nent nentries
+ upvar $ndp ndups
+
+ # If we are using a txnenv, assume it is using
+ # the default maximum number of locks, cut back
+ # so that we don't run out of locks. Reduce
+ # by 25% until we fit.
+ #
+ while { [expr $nentries * $ndups] > 5000 } {
+ set nentries [expr ($nentries / 4) * 3]
+ set ndups [expr ($ndups / 4) * 3]
+ }
+}
+
+proc getstats { statlist field } {
+ foreach pair $statlist {
+ set txt [lindex $pair 0]
+ if { [string equal $txt $field] == 1 } {
+ return [lindex $pair 1]
+ }
+ }
+ return -1
+}
+
+proc big_endian { } {
+ global tcl_platform
+ set e $tcl_platform(byteOrder)
+ if { [string compare $e littleEndian] == 0 } {
+ return 0
+ } elseif { [string compare $e bigEndian] == 0 } {
+ return 1
+ } else {
+ error "FAIL: Unknown endianness $e"
+ }
+}
diff --git a/bdb/test/txn.tcl b/bdb/test/txn.tcl
deleted file mode 100644
index 904ef5fdca0..00000000000
--- a/bdb/test/txn.tcl
+++ /dev/null
@@ -1,181 +0,0 @@
-# See the file LICENSE for redistribution information.
-#
-# Copyright (c) 1996, 1997, 1998, 1999, 2000
-# Sleepycat Software. All rights reserved.
-#
-# $Id: txn.tcl,v 11.12 2000/12/31 19:26:23 bostic Exp $
-#
-# Options are:
-# -dir <directory in which to store memp>
-# -max <max number of concurrent transactions>
-# -iterations <iterations>
-# -stat
-proc txn_usage {} {
- puts "txn -dir <directory> -iterations <number of ops> \
- -max <max number of transactions> -stat"
-}
-
-proc txntest { args } {
- source ./include.tcl
-
- # Set defaults
- set iterations 50
- set max 1024
- set dostat 0
- set flags ""
- for { set i 0 } { $i < [llength $args] } {incr i} {
- switch -regexp -- [lindex $args $i] {
- -d.* { incr i; set testdir [lindex $args $i] }
- -f.* { incr i; set flags [lindex $args $i] }
- -i.* { incr i; set iterations [lindex $args $i] }
- -m.* { incr i; set max [lindex $args $i] }
- -s.* { set dostat 1 }
- default {
- puts -nonewline "FAIL:[timestamp] Usage: "
- txn_usage
- return
- }
- }
- }
- if { $max < $iterations } {
- set max $iterations
- }
-
- # Now run the various functionality tests
- txn001 $testdir $max $iterations $flags
- txn002 $testdir $max $iterations
-}
-
-proc txn001 { dir max ntxns flags} {
- source ./include.tcl
-
- puts "Txn001: Basic begin, commit, abort"
-
- # Open environment
- env_cleanup $dir
-
- set env [eval {berkdb \
- env -create -mode 0644 -txn -txn_max $max -home $dir} $flags]
- error_check_good evn_open [is_valid_env $env] TRUE
- txn001_suba $ntxns $env
- txn001_subb $ntxns $env
- txn001_subc $ntxns $env
- # Close and unlink the file
- error_check_good env_close:$env [$env close] 0
-}
-
-proc txn001_suba { ntxns env } {
- source ./include.tcl
-
- # We will create a bunch of transactions and commit them.
- set txn_list {}
- set tid_list {}
- puts "Txn001.a: Beginning/Committing $ntxns Transactions in $env"
- for { set i 0 } { $i < $ntxns } { incr i } {
- set txn [$env txn]
- error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-
- lappend txn_list $txn
-
- set tid [$txn id]
- error_check_good tid_check [lsearch $tid_list $tid] -1
-
- lappend tid_list $tid
- }
-
- # Now commit them all
- foreach t $txn_list {
- error_check_good txn_commit:$t [$t commit] 0
- }
-}
-
-proc txn001_subb { ntxns env } {
- # We will create a bunch of transactions and abort them.
- set txn_list {}
- set tid_list {}
- puts "Txn001.b: Beginning/Aborting Transactions"
- for { set i 0 } { $i < $ntxns } { incr i } {
- set txn [$env txn]
- error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-
- lappend txn_list $txn
-
- set tid [$txn id]
- error_check_good tid_check [lsearch $tid_list $tid] -1
-
- lappend tid_list $tid
- }
-
- # Now abort them all
- foreach t $txn_list {
- error_check_good txn_abort:$t [$t abort] 0
- }
-}
-
-proc txn001_subc { ntxns env } {
- # We will create a bunch of transactions and commit them.
- set txn_list {}
- set tid_list {}
- puts "Txn001.c: Beginning/Prepare/Committing Transactions"
- for { set i 0 } { $i < $ntxns } { incr i } {
- set txn [$env txn]
- error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-
- lappend txn_list $txn
-
- set tid [$txn id]
- error_check_good tid_check [lsearch $tid_list $tid] -1
-
- lappend tid_list $tid
- }
-
- # Now prepare them all
- foreach t $txn_list {
- error_check_good txn_prepare:$t [$t prepare] 0
- }
-
- # Now commit them all
- foreach t $txn_list {
- error_check_good txn_commit:$t [$t commit] 0
- }
-
-}
-
-# Verify that read-only transactions do not create any log records
-proc txn002 { dir max ntxns } {
- source ./include.tcl
-
- puts "Txn002: Read-only transaction test"
-
- env_cleanup $dir
- set env [berkdb \
- env -create -mode 0644 -txn -txn_max $max -home $dir]
- error_check_good dbenv [is_valid_env $env] TRUE
-
- # We will create a bunch of transactions and commit them.
- set txn_list {}
- set tid_list {}
- puts "Txn002.a: Beginning/Committing Transactions"
- for { set i 0 } { $i < $ntxns } { incr i } {
- set txn [$env txn]
- error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-
- lappend txn_list $txn
-
- set tid [$txn id]
- error_check_good tid_check [lsearch $tid_list $tid] -1
-
- lappend tid_list $tid
- }
-
- # Now commit them all
- foreach t $txn_list {
- error_check_good txn_commit:$t [$t commit] 0
- }
-
- # Now verify that there aren't any log records.
- set r [$env log_get -first]
- error_check_good log_get:$r [llength $r] 0
-
- error_check_good env_close:$r [$env close] 0
-}
diff --git a/bdb/test/txn001.tcl b/bdb/test/txn001.tcl
new file mode 100644
index 00000000000..406ef35751c
--- /dev/null
+++ b/bdb/test/txn001.tcl
@@ -0,0 +1,116 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn001.tcl,v 11.35 2002/05/10 17:44:28 sue Exp $
+#
+
+# TEST txn001
+# TEST Begin, commit, abort testing.
+proc txn001 { {tnum "01"} { max 1024 } { ntxns 50 } } {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ puts -nonewline "Txn0$tnum: Basic begin, commit, abort"
+
+ if { $tnum != "01"} {
+ puts " (with ID wrap)"
+ } else {
+ puts ""
+ }
+
+ # Open environment
+ env_cleanup $testdir
+
+ set env [eval {berkdb_env -create -mode 0644 -txn \
+ -txn_max $max -home $testdir}]
+ error_check_good evn_open [is_valid_env $env] TRUE
+ error_check_good txn_id_set \
+ [ $env txn_id_set $txn_curid $txn_maxid ] 0
+ txn001_suba $ntxns $env $tnum
+ txn001_subb $ntxns $env $tnum
+ txn001_subc $ntxns $env $tnum
+ # Close and unlink the file
+ error_check_good env_close:$env [$env close] 0
+}
+
+proc txn001_suba { ntxns env tnum } {
+ source ./include.tcl
+
+ # We will create a bunch of transactions and commit them.
+ set txn_list {}
+ set tid_list {}
+ puts "\tTxn0$tnum.a: Beginning/Committing $ntxns Transactions in $env"
+ for { set i 0 } { $i < $ntxns } { incr i } {
+ set txn [$env txn]
+ error_check_good txn_begin [is_valid_txn $txn $env] TRUE
+
+ lappend txn_list $txn
+
+ set tid [$txn id]
+ error_check_good tid_check [lsearch $tid_list $tid] -1
+
+ lappend tid_list $tid
+ }
+
+ # Now commit them all
+ foreach t $txn_list {
+ error_check_good txn_commit:$t [$t commit] 0
+ }
+}
+
+proc txn001_subb { ntxns env tnum } {
+ # We will create a bunch of transactions and abort them.
+ set txn_list {}
+ set tid_list {}
+ puts "\tTxn0$tnum.b: Beginning/Aborting Transactions"
+ for { set i 0 } { $i < $ntxns } { incr i } {
+ set txn [$env txn]
+ error_check_good txn_begin [is_valid_txn $txn $env] TRUE
+
+ lappend txn_list $txn
+
+ set tid [$txn id]
+ error_check_good tid_check [lsearch $tid_list $tid] -1
+
+ lappend tid_list $tid
+ }
+
+ # Now abort them all
+ foreach t $txn_list {
+ error_check_good txn_abort:$t [$t abort] 0
+ }
+}
+
+proc txn001_subc { ntxns env tnum } {
+ # We will create a bunch of transactions and commit them.
+ set txn_list {}
+ set tid_list {}
+ puts "\tTxn0$tnum.c: Beginning/Prepare/Committing Transactions"
+ for { set i 0 } { $i < $ntxns } { incr i } {
+ set txn [$env txn]
+ error_check_good txn_begin [is_valid_txn $txn $env] TRUE
+
+ lappend txn_list $txn
+
+ set tid [$txn id]
+ error_check_good tid_check [lsearch $tid_list $tid] -1
+
+ lappend tid_list $tid
+ }
+
+ # Now prepare them all
+ foreach t $txn_list {
+ error_check_good txn_prepare:$t \
+ [$t prepare [make_gid global:$t]] 0
+ }
+
+ # Now commit them all
+ foreach t $txn_list {
+ error_check_good txn_commit:$t [$t commit] 0
+ }
+
+}
+
diff --git a/bdb/test/txn002.tcl b/bdb/test/txn002.tcl
new file mode 100644
index 00000000000..5107472644d
--- /dev/null
+++ b/bdb/test/txn002.tcl
@@ -0,0 +1,91 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn002.tcl,v 11.38 2002/05/10 17:44:29 sue Exp $
+#
+
+# TEST txn002
+# TEST Verify that read-only transactions do not write log records.
+proc txn002 { {tnum "02" } { max 1024 } { ntxns 50 } } {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ puts -nonewline "Txn0$tnum: Read-only transaction test ($max) ($ntxns)"
+
+ if { $tnum != "02" } {
+ puts " (with ID wrap)"
+ } else {
+ puts ""
+ }
+
+ env_cleanup $testdir
+ set env [berkdb \
+ env -create -mode 0644 -txn -txn_max $max -home $testdir]
+ error_check_good dbenv [is_valid_env $env] TRUE
+ error_check_good txn_id_set \
+ [$env txn_id_set $txn_curid $txn_maxid ] 0
+
+ # Save the current bytes in the log.
+ set off_start [txn002_logoff $env]
+
+ # We will create a bunch of transactions and commit them.
+ set txn_list {}
+ set tid_list {}
+ puts "\tTxn0$tnum.a: Beginning/Committing Transactions"
+ for { set i 0 } { $i < $ntxns } { incr i } {
+ set txn [$env txn]
+ error_check_good txn_begin [is_valid_txn $txn $env] TRUE
+
+ lappend txn_list $txn
+
+ set tid [$txn id]
+ error_check_good tid_check [lsearch $tid_list $tid] -1
+
+ lappend tid_list $tid
+ }
+ foreach t $txn_list {
+ error_check_good txn_commit:$t [$t commit] 0
+ }
+
+ # Make sure we haven't written any new log records except
+ # potentially some recycle records if we were wrapping txnids.
+ set off_stop [txn002_logoff $env]
+ if { $off_stop != $off_start } {
+ txn002_recycle_only $testdir
+ }
+
+ error_check_good env_close [$env close] 0
+}
+
+proc txn002_logoff { env } {
+ set stat [$env log_stat]
+ foreach i $stat {
+ foreach {txt val} $i {break}
+ if { [string compare \
+ $txt {Current log file offset}] == 0 } {
+ return $val
+ }
+ }
+}
+
+# Make sure that the only log records found are txn_recycle records
+proc txn002_recycle_only { dir } {
+ global util_path
+
+ set tmpfile $dir/printlog.out
+ set stat [catch {exec $util_path/db_printlog -h $dir > $tmpfile} ret]
+ error_check_good db_printlog $stat 0
+
+ set f [open $tmpfile r]
+ while { [gets $f record] >= 0 } {
+ set r [regexp {\[[^\]]*\]\[[^\]]*\]([^\:]*)\:} $record whl name]
+ if { $r == 1 } {
+ error_check_good record_type __txn_recycle $name
+ }
+ }
+ close $f
+ fileremove $tmpfile
+}
diff --git a/bdb/test/txn003.tcl b/bdb/test/txn003.tcl
new file mode 100644
index 00000000000..71e450cf9ce
--- /dev/null
+++ b/bdb/test/txn003.tcl
@@ -0,0 +1,238 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn003.tcl,v 11.40 2002/09/05 17:23:08 sandstro Exp $
+#
+
+# TEST txn003
+# TEST Test abort/commit/prepare of txns with outstanding child txns.
+proc txn003 { {tnum "03"} } {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ puts -nonewline "Txn0$tnum: Outstanding child transaction test"
+
+ if { $tnum != "03" } {
+ puts " (with ID wrap)"
+ } else {
+ puts ""
+ }
+ env_cleanup $testdir
+ set testfile txn003.db
+
+ set env_cmd "berkdb_env_noerr -create -txn -home $testdir"
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $env] TRUE
+ error_check_good txn_id_set \
+ [$env txn_id_set $txn_curid $txn_maxid] 0
+
+ set oflags {-auto_commit -create -btree -mode 0644 -env $env $testfile}
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ #
+ # Put some data so that we can check commit or abort of child
+ #
+ set key 1
+ set origdata some_data
+ set newdata this_is_new_data
+ set newdata2 some_other_new_data
+
+ error_check_good db_put [$db put -auto_commit $key $origdata] 0
+ error_check_good dbclose [$db close] 0
+
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ txn003_check $db $key "Origdata" $origdata
+
+ puts "\tTxn0$tnum.a: Parent abort"
+ set parent [$env txn]
+ error_check_good txn_begin [is_valid_txn $parent $env] TRUE
+ set child [$env txn -parent $parent]
+ error_check_good txn_begin [is_valid_txn $child $env] TRUE
+ error_check_good db_put [$db put -txn $child $key $newdata] 0
+ error_check_good parent_abort [$parent abort] 0
+ txn003_check $db $key "parent_abort" $origdata
+ # Check child handle is invalid
+ set stat [catch {$child abort} ret]
+ error_check_good child_handle $stat 1
+ error_check_good child_h2 [is_substr $ret "invalid command name"] 1
+
+ puts "\tTxn0$tnum.b: Parent commit"
+ set parent [$env txn]
+ error_check_good txn_begin [is_valid_txn $parent $env] TRUE
+ set child [$env txn -parent $parent]
+ error_check_good txn_begin [is_valid_txn $child $env] TRUE
+ error_check_good db_put [$db put -txn $child $key $newdata] 0
+ error_check_good parent_commit [$parent commit] 0
+ txn003_check $db $key "parent_commit" $newdata
+ # Check child handle is invalid
+ set stat [catch {$child abort} ret]
+ error_check_good child_handle $stat 1
+ error_check_good child_h2 [is_substr $ret "invalid command name"] 1
+ error_check_good dbclose [$db close] 0
+ error_check_good env_close [$env close] 0
+
+ #
+ # Since the data check assumes what has come before, the 'commit'
+ # operation must be last.
+ #
+ set hdr "\tTxn0$tnum"
+ set rlist {
+ {begin ".c"}
+ {prepare ".d"}
+ {abort ".e"}
+ {commit ".f"}
+ }
+ set count 0
+ foreach pair $rlist {
+ incr count
+ set op [lindex $pair 0]
+ set msg [lindex $pair 1]
+ set msg $hdr$msg
+ txn003_body $env_cmd $testfile $testdir $key $newdata2 $msg $op
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $env] TRUE
+
+ berkdb debug_check
+ set db [eval {berkdb_open} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+ #
+ # For prepare we'll then just
+ # end up aborting after we test what we need to.
+ # So set gooddata to the same as abort.
+ switch $op {
+ abort {
+ set gooddata $newdata
+ }
+ begin {
+ set gooddata $newdata
+ }
+ commit {
+ set gooddata $newdata2
+ }
+ prepare {
+ set gooddata $newdata
+ }
+ }
+ txn003_check $db $key "parent_$op" $gooddata
+ error_check_good dbclose [$db close] 0
+ error_check_good env_close [$env close] 0
+ }
+
+ # We can't do the attempted child discard on Windows
+ # because it will leave open files that can't be removed.
+ # Skip the remainder of the test for Windows.
+ if { $is_windows_test == 1 } {
+ puts "Skipping remainder of test for Windows"
+ return
+ }
+ puts "\tTxn0$tnum.g: Attempt child prepare"
+ set env [eval $env_cmd]
+ error_check_good dbenv [is_valid_env $env] TRUE
+ berkdb debug_check
+ set db [eval {berkdb_open_noerr} $oflags]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ set parent [$env txn]
+ error_check_good txn_begin [is_valid_txn $parent $env] TRUE
+ set child [$env txn -parent $parent]
+ error_check_good txn_begin [is_valid_txn $child $env] TRUE
+ error_check_good db_put [$db put -txn $child $key $newdata] 0
+ set gid [make_gid child_prepare:$child]
+ set stat [catch {$child prepare $gid} ret]
+ error_check_good child_prepare $stat 1
+ error_check_good child_prep_err [is_substr $ret "txn prepare"] 1
+
+ puts "\tTxn0$tnum.h: Attempt child discard"
+ set stat [catch {$child discard} ret]
+ error_check_good child_discard $stat 1
+
+ # We just panic'd the region, so the next operations will fail.
+ # No matter, we still have to clean up all the handles.
+
+ set stat [catch {$parent commit} ret]
+ error_check_good parent_commit $stat 1
+ error_check_good parent_commit:fail [is_substr $ret "DB_RUNRECOVERY"] 1
+
+ set stat [catch {$db close} ret]
+ error_check_good db_close $stat 1
+ error_check_good db_close:fail [is_substr $ret "DB_RUNRECOVERY"] 1
+
+ set stat [catch {$env close} ret]
+ error_check_good env_close $stat 1
+ error_check_good env_close:fail [is_substr $ret "DB_RUNRECOVERY"] 1
+}
+
+proc txn003_body { env_cmd testfile dir key newdata2 msg op } {
+ source ./include.tcl
+
+ berkdb debug_check
+ sentinel_init
+ set gidf $dir/gidfile
+ fileremove -f $gidf
+ set pidlist {}
+ puts "$msg.0: Executing child script to prepare txns"
+ berkdb debug_check
+ set p [exec $tclsh_path $test_path/wrap.tcl txnscript.tcl \
+ $testdir/txnout $env_cmd $testfile $gidf $key $newdata2 &]
+ lappend pidlist $p
+ watch_procs $pidlist 5
+ set f1 [open $testdir/txnout r]
+ set r [read $f1]
+ puts $r
+ close $f1
+ fileremove -f $testdir/txnout
+
+ berkdb debug_check
+ puts -nonewline "$msg.1: Running recovery ... "
+ flush stdout
+ berkdb debug_check
+ set env [eval $env_cmd "-recover"]
+ error_check_good dbenv-recover [is_valid_env $env] TRUE
+ puts "complete"
+
+ puts "$msg.2: getting txns from txn_recover"
+ set txnlist [$env txn_recover]
+ error_check_good txnlist_len [llength $txnlist] 1
+ set tpair [lindex $txnlist 0]
+
+ set gfd [open $gidf r]
+ set ret [gets $gfd parentgid]
+ close $gfd
+ set txn [lindex $tpair 0]
+ set gid [lindex $tpair 1]
+ if { $op == "begin" } {
+ puts "$msg.2: $op new txn"
+ } else {
+ puts "$msg.2: $op parent"
+ }
+ error_check_good gidcompare $gid $parentgid
+ if { $op == "prepare" } {
+ set gid [make_gid prepare_recover:$txn]
+ set stat [catch {$txn $op $gid} ret]
+ error_check_good prep_error $stat 1
+ error_check_good prep_err \
+ [is_substr $ret "transaction already prepared"] 1
+ error_check_good txn:prep_abort [$txn abort] 0
+ } elseif { $op == "begin" } {
+ set stat [catch {$env txn} ret]
+ error_check_good begin_error $stat 1
+ error_check_good begin_err \
+ [is_substr $ret "not yet committed transactions is incomplete"] 1
+ error_check_good txn:prep_abort [$txn abort] 0
+ } else {
+ error_check_good txn:$op [$txn $op] 0
+ }
+ error_check_good envclose [$env close] 0
+}
+
+proc txn003_check { db key msg gooddata } {
+ set kd [$db get $key]
+ set data [lindex [lindex $kd 0] 1]
+ error_check_good $msg $data $gooddata
+}
diff --git a/bdb/test/txn004.tcl b/bdb/test/txn004.tcl
new file mode 100644
index 00000000000..75e1b40043f
--- /dev/null
+++ b/bdb/test/txn004.tcl
@@ -0,0 +1,62 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn004.tcl,v 11.39 2002/05/15 17:14:06 sandstro Exp $
+#
+
+# TEST txn004
+# TEST Test of wraparound txnids (txn001)
+proc txn004 { } {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ set orig_curid $txn_curid
+ set orig_maxid $txn_maxid
+ puts "\tTxn004.1: wraparound txnids"
+ set txn_curid [expr $txn_maxid - 2]
+ txn001 "04.1"
+ puts "\tTxn004.2: closer wraparound txnids"
+ set txn_curid [expr $txn_maxid - 3]
+ set txn_maxid [expr $txn_maxid - 2]
+ txn001 "04.2"
+
+ puts "\tTxn004.3: test wraparound txnids"
+ txn_idwrap_check $testdir
+ set txn_curid $orig_curid
+ set txn_maxid $orig_maxid
+ return
+}
+
+proc txn_idwrap_check { testdir } {
+ global txn_curid
+ global txn_maxid
+
+ env_cleanup $testdir
+
+ # Open/create the txn region
+ set e [berkdb_env -create -txn -home $testdir]
+ error_check_good env_open [is_substr $e env] 1
+
+ set txn1 [$e txn]
+ error_check_good txn1 [is_valid_txn $txn1 $e] TRUE
+ error_check_good txn_id_set \
+ [$e txn_id_set [expr $txn_maxid - 1] $txn_maxid] 0
+
+ set txn2 [$e txn]
+ error_check_good txn2 [is_valid_txn $txn2 $e] TRUE
+
+ # txn3 will require a wraparound txnid
+ # XXX How can we test it has a wrapped id?
+ set txn3 [$e txn]
+ error_check_good wrap_txn3 [is_valid_txn $txn3 $e] TRUE
+
+ error_check_good free_txn1 [$txn1 commit] 0
+ error_check_good free_txn2 [$txn2 commit] 0
+ error_check_good free_txn3 [$txn3 commit] 0
+
+ error_check_good close [$e close] 0
+}
+
diff --git a/bdb/test/txn005.tcl b/bdb/test/txn005.tcl
new file mode 100644
index 00000000000..604f3ad7de4
--- /dev/null
+++ b/bdb/test/txn005.tcl
@@ -0,0 +1,75 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn005.tcl,v 11.35 2002/08/08 15:38:14 bostic Exp $
+#
+
+# TEST txn005
+# TEST Test transaction ID wraparound and recovery.
+proc txn005 {} {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ env_cleanup $testdir
+ puts "Txn005: Test transaction wraparound recovery"
+
+ # Open/create the txn region
+ puts "\tTxn005.a: Create environment"
+ set e [berkdb_env -create -txn -home $testdir]
+ error_check_good env_open [is_valid_env $e] TRUE
+
+ set txn1 [$e txn]
+ error_check_good txn1 [is_valid_txn $txn1 $e] TRUE
+
+ set db [berkdb_open -env $e -txn $txn1 -create -btree txn005.db]
+ error_check_good db [is_valid_db $db] TRUE
+ error_check_good txn1_commit [$txn1 commit] 0
+
+ puts "\tTxn005.b: Set txn ids"
+ error_check_good txn_id_set \
+ [$e txn_id_set [expr $txn_maxid - 1] $txn_maxid] 0
+
+ # txn2 and txn3 will require a wraparound txnid
+ set txn2 [$e txn]
+ error_check_good txn2 [is_valid_txn $txn2 $e] TRUE
+
+ error_check_good put [$db put -txn $txn2 "a" ""] 0
+ error_check_good txn2_commit [$txn2 commit] 0
+
+ error_check_good get_a [$db get "a"] "{a {}}"
+
+ error_check_good close [$db close] 0
+
+ set txn3 [$e txn]
+ error_check_good txn3 [is_valid_txn $txn3 $e] TRUE
+
+ set db [berkdb_open -env $e -txn $txn3 -btree txn005.db]
+ error_check_good db [is_valid_db $db] TRUE
+
+ error_check_good put2 [$db put -txn $txn3 "b" ""] 0
+ error_check_good sync [$db sync] 0
+ error_check_good txn3_abort [$txn3 abort] 0
+ error_check_good dbclose [$db close] 0
+ error_check_good eclose [$e close] 0
+
+ puts "\tTxn005.c: Run recovery"
+ set stat [catch {exec $util_path/db_recover -h $testdir -e -c} result]
+ if { $stat == 1 } {
+ error "FAIL: Recovery error: $result."
+ }
+
+ puts "\tTxn005.d: Check data"
+ set e [berkdb_env -txn -home $testdir]
+ error_check_good env_open [is_valid_env $e] TRUE
+
+ set db [berkdb_open -env $e -auto_commit -btree txn005.db]
+ error_check_good db [is_valid_db $db] TRUE
+
+ error_check_good get_a [$db get "a"] "{a {}}"
+ error_check_bad get_b [$db get "b"] "{b {}}"
+ error_check_good dbclose [$db close] 0
+ error_check_good eclose [$e close] 0
+}
diff --git a/bdb/test/txn006.tcl b/bdb/test/txn006.tcl
new file mode 100644
index 00000000000..7bf37d34dfc
--- /dev/null
+++ b/bdb/test/txn006.tcl
@@ -0,0 +1,47 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn006.tcl,v 1.5 2002/08/01 19:59:19 sue Exp $
+#
+#
+#TEST txn006
+#TEST Test dump/load in transactional environment.
+proc txn006 { { iter 50 } } {
+ source ./include.tcl
+ set testfile txn006.db
+
+ puts "Txn006: Test dump/load in transaction environment"
+ env_cleanup $testdir
+
+ puts "\tTxn006.a: Create environment and database"
+ # Open/create the txn region
+ set e [berkdb_env -create -home $testdir -txn]
+ error_check_good env_open [is_valid_env $e] TRUE
+
+ # Open/create database
+ set db [berkdb_open -auto_commit -env $e \
+ -create -btree -dup $testfile]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ # Start a transaction
+ set txn [$e txn]
+ error_check_good txn [is_valid_txn $txn $e] TRUE
+
+ puts "\tTxn006.b: Put data"
+ # Put some data
+ for { set i 1 } { $i < $iter } { incr i } {
+ error_check_good put [$db put -txn $txn key$i data$i] 0
+ }
+
+ # End transaction, close db
+ error_check_good txn_commit [$txn commit] 0
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$e close] 0
+
+ puts "\tTxn006.c: dump/load"
+ # Dump and load
+ exec $util_path/db_dump -p -h $testdir $testfile | \
+ $util_path/db_load -h $testdir $testfile
+}
diff --git a/bdb/test/txn007.tcl b/bdb/test/txn007.tcl
new file mode 100644
index 00000000000..f67dc209f92
--- /dev/null
+++ b/bdb/test/txn007.tcl
@@ -0,0 +1,57 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn007.tcl,v 11.3 2002/08/08 15:38:14 bostic Exp $
+#
+#TEST txn007
+#TEST Test of DB_TXN_WRITE_NOSYNC
+proc txn007 { { iter 50 } } {
+ source ./include.tcl
+ set testfile txn007.db
+
+ puts "Txn007: DB_TXN_WRITE_NOSYNC"
+ env_cleanup $testdir
+
+ # Open/create the txn region
+ puts "\tTxn007.a: Create env and database with -wrnosync"
+ set e [berkdb_env -create -home $testdir -txn -wrnosync]
+ error_check_good env_open [is_valid_env $e] TRUE
+
+ # Open/create database
+ set db [berkdb open -auto_commit -env $e \
+ -create -btree -dup $testfile]
+ error_check_good db_open [is_valid_db $db] TRUE
+
+ # Put some data
+ puts "\tTxn007.b: Put $iter data items in individual transactions"
+ for { set i 1 } { $i < $iter } { incr i } {
+ # Start a transaction
+ set txn [$e txn]
+ error_check_good txn [is_valid_txn $txn $e] TRUE
+ $db put -txn $txn key$i data$i
+ error_check_good txn_commit [$txn commit] 0
+ }
+ set stat [$e log_stat]
+ puts "\tTxn007.c: Check log stats"
+ foreach i $stat {
+ set txt [lindex $i 0]
+ if { [string equal $txt {Times log written}] == 1 } {
+ set wrval [lindex $i 1]
+ }
+ if { [string equal $txt {Times log flushed}] == 1 } {
+ set syncval [lindex $i 1]
+ }
+ }
+ error_check_good wrval [expr $wrval >= $iter] 1
+ #
+ # We should have written at least 'iter' number of times,
+ # but not synced on any of those.
+ #
+ set val [expr $wrval - $iter]
+ error_check_good syncval [expr $syncval <= $val] 1
+
+ error_check_good db_close [$db close] 0
+ error_check_good env_close [$e close] 0
+}
diff --git a/bdb/test/txn008.tcl b/bdb/test/txn008.tcl
new file mode 100644
index 00000000000..ad57ea0eeaa
--- /dev/null
+++ b/bdb/test/txn008.tcl
@@ -0,0 +1,32 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn008.tcl,v 11.3 2002/05/10 17:55:54 sue Exp $
+#
+
+# TEST txn008
+# TEST Test of wraparound txnids (txn002)
+proc txn008 { } {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ set orig_curid $txn_curid
+ set orig_maxid $txn_maxid
+ puts "\tTxn008.1: wraparound txnids"
+ set txn_curid [expr $txn_maxid - 2]
+ txn002 "08.1"
+ puts "\tTxn008.2: closer wraparound txnids"
+ set txn_curid [expr $txn_maxid - 3]
+ set txn_maxid [expr $txn_maxid - 2]
+ txn002 "08.2"
+
+ puts "\tTxn008.3: test wraparound txnids"
+ txn_idwrap_check $testdir
+ set txn_curid $orig_curid
+ set txn_maxid $orig_maxid
+ return
+}
+
diff --git a/bdb/test/txn009.tcl b/bdb/test/txn009.tcl
new file mode 100644
index 00000000000..784c0068a41
--- /dev/null
+++ b/bdb/test/txn009.tcl
@@ -0,0 +1,32 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txn009.tcl,v 11.3 2002/05/10 17:55:55 sue Exp $
+#
+
+# TEST txn009
+# TEST Test of wraparound txnids (txn003)
+proc txn009 { } {
+ source ./include.tcl
+ global txn_curid
+ global txn_maxid
+
+ set orig_curid $txn_curid
+ set orig_maxid $txn_maxid
+ puts "\tTxn009.1: wraparound txnids"
+ set txn_curid [expr $txn_maxid - 2]
+ txn003 "09.1"
+ puts "\tTxn009.2: closer wraparound txnids"
+ set txn_curid [expr $txn_maxid - 3]
+ set txn_maxid [expr $txn_maxid - 2]
+ txn003 "09.2"
+
+ puts "\tTxn009.3: test wraparound txnids"
+ txn_idwrap_check $testdir
+ set txn_curid $orig_curid
+ set txn_maxid $orig_maxid
+ return
+}
+
diff --git a/bdb/test/txnscript.tcl b/bdb/test/txnscript.tcl
new file mode 100644
index 00000000000..1a4a1b6f2ec
--- /dev/null
+++ b/bdb/test/txnscript.tcl
@@ -0,0 +1,67 @@
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 1996-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: txnscript.tcl,v 11.3 2002/01/23 15:33:40 bostic Exp $
+#
+# Txn003 script - outstanding child prepare script
+# Usage: txnscript envcmd dbcmd gidf key data
+# envcmd: command to open env
+# dbfile: name of database file
+# gidf: name of global id file
+# key: key to use
+# data: new data to use
+
+source ./include.tcl
+source $test_path/test.tcl
+source $test_path/testutils.tcl
+
+set usage "txnscript envcmd dbfile gidfile key data"
+
+# Verify usage
+if { $argc != 5 } {
+ puts stderr "FAIL:[timestamp] Usage: $usage"
+ exit
+}
+
+# Initialize arguments
+set envcmd [ lindex $argv 0 ]
+set dbfile [ lindex $argv 1 ]
+set gidfile [ lindex $argv 2 ]
+set key [ lindex $argv 3 ]
+set data [ lindex $argv 4 ]
+
+set dbenv [eval $envcmd]
+error_check_good envopen [is_valid_env $dbenv] TRUE
+
+set usedb 1
+set db [berkdb_open -auto_commit -env $dbenv $dbfile]
+error_check_good dbopen [is_valid_db $db] TRUE
+
+puts "\tTxnscript.a: begin parent and child txn"
+set parent [$dbenv txn]
+error_check_good parent [is_valid_txn $parent $dbenv] TRUE
+set child [$dbenv txn -parent $parent]
+error_check_good parent [is_valid_txn $child $dbenv] TRUE
+
+puts "\tTxnscript.b: Modify data"
+error_check_good db_put [$db put -txn $child $key $data] 0
+
+set gfd [open $gidfile w+]
+set gid [make_gid txnscript:$parent]
+puts $gfd $gid
+puts "\tTxnscript.c: Prepare parent only"
+error_check_good txn_prepare:$parent [$parent prepare $gid] 0
+close $gfd
+
+puts "\tTxnscript.d: Check child handle"
+set stat [catch {$child abort} ret]
+error_check_good child_handle $stat 1
+error_check_good child_h2 [is_substr $ret "invalid command name"] 1
+
+#
+# We do not close the db or env, but exit with the txns outstanding.
+#
+puts "\tTxnscript completed successfully"
+flush stdout
diff --git a/bdb/test/update.tcl b/bdb/test/update.tcl
index 81fc9ba9e2c..2bedfacc793 100644
--- a/bdb/test/update.tcl
+++ b/bdb/test/update.tcl
@@ -1,9 +1,10 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: update.tcl,v 11.9 2000/10/27 13:23:56 sue Exp $
+# $Id: update.tcl,v 11.11 2002/01/11 15:53:58 bostic Exp $
+
source ./include.tcl
global update_dir
set update_dir "$test_path/update_test"
diff --git a/bdb/test/upgrade.tcl b/bdb/test/upgrade.tcl
index 0d2f656bcf9..1c0ffc5461a 100644
--- a/bdb/test/upgrade.tcl
+++ b/bdb/test/upgrade.tcl
@@ -1,9 +1,9 @@
# See the file LICENSE for redistribution information.
#
-# Copyright (c) 1999, 2000
+# Copyright (c) 1999-2002
# Sleepycat Software. All rights reserved.
#
-# $Id: upgrade.tcl,v 11.16 2000/10/27 13:23:56 sue Exp $
+# $Id: upgrade.tcl,v 11.22 2002/07/28 03:22:41 krinsky Exp $
source ./include.tcl
@@ -17,6 +17,7 @@ set gen_upgrade 0
global upgrade_dir
global upgrade_be
global upgrade_method
+global upgrade_name
proc upgrade { { archived_test_loc "DEFAULT" } } {
source ./include.tcl
@@ -40,7 +41,7 @@ proc upgrade { { archived_test_loc "DEFAULT" } } {
foreach file [glob $upgrade_dir/$version/$method/*] {
regexp (\[^\/\]*)\.tar\.gz$ $file dummy name
- cleanup $testdir NULL
+ cleanup $testdir NULL 1
#puts "$upgrade_dir/$version/$method/$name.tar.gz"
set curdir [pwd]
cd $testdir
@@ -109,6 +110,8 @@ proc _upgrade_test { temp_dir version method file endianness } {
set ret [berkdb upgrade "$temp_dir/$file-$endianness.db"]
error_check_good dbupgrade $ret 0
+ error_check_good dbupgrade_verify [verify_dir $temp_dir "" 0 0 1] 0
+
upgrade_dump "$temp_dir/$file-$endianness.db" "$temp_dir/temp.dump"
error_check_good "Upgrade diff.$endianness: $version $method $file" \
@@ -138,31 +141,41 @@ proc gen_upgrade { dir } {
global upgrade_dir
global upgrade_be
global upgrade_method
- global runtests
+ global upgrade_name
+ global num_test
+ global parms
source ./include.tcl
set gen_upgrade 1
set upgrade_dir $dir
- foreach upgrade_be { 0 1 } {
- foreach i "btree rbtree hash recno rrecno queue frecno" {
- puts "Running $i tests"
- set upgrade_method $i
- set start 1
- for { set j $start } { $j <= $runtests } {incr j} {
+ foreach i "btree rbtree hash recno rrecno frecno queue queueext" {
+ puts "Running $i tests"
+ set upgrade_method $i
+ set start 1
+ for { set j $start } { $j <= $num_test(test) } { incr j } {
+ set upgrade_name [format "test%03d" $j]
+ if { [info exists parms($upgrade_name)] != 1 } {
+ continue
+ }
+
+ foreach upgrade_be { 0 1 } {
if [catch {exec $tclsh_path \
<< "source $test_path/test.tcl;\
- global upgrade_be;\
+ global gen_upgrade upgrade_be;\
+ global upgrade_method upgrade_name;\
+ set gen_upgrade 1;\
set upgrade_be $upgrade_be;\
+ set upgrade_method $upgrade_method;\
+ set upgrade_name $upgrade_name;\
run_method -$i $j $j"} res] {
- puts "FAIL: [format "test%03d" $j] $i"
+ puts "FAIL: $upgrade_name $i"
}
puts $res
- cleanup $testdir NULL
+ cleanup $testdir NULL 1
}
}
}
-
set gen_upgrade 0
}
@@ -241,6 +254,8 @@ proc upgrade_dump { database file {stripnulls 0} } {
}
close $f
+ error_check_good upgrade_dump_c_close [$dbc close] 0
+ error_check_good upgrade_dump_db_close [$db close] 0
}
proc _comp { a b } {
diff --git a/bdb/test/upgrade/README b/bdb/test/upgrade/README
deleted file mode 100644
index 1afada2ecf4..00000000000
--- a/bdb/test/upgrade/README
+++ /dev/null
@@ -1,85 +0,0 @@
- The Berkeley DB Upgrade Tests
-
-Quick ref:
-
- Running the tests:
- (in tclsh)
- % source ../test/test.tcl
- % upgrade
-
- Generating the test databases:
- (in tclsh)
- % source ../test/test.tcl
- % gen_upgrade /where/you/want/them
-
- (in your shell)
- $ cd /where/you/want/them
- $ perl $db_dir/upgrade/scripts/pack-3.0.pl
- $ mv 3.0 $db_dir/upgrade/databases
-
-What they are:
-
-The DB upgrade tests are a framework for testing two main features of
-Berkeley DB: the db_dump utility, and the "DB_UPGRADE" flag to DB->open.
-They work by taking a tarred, gzipped set of test databases and dumps, and
-verifying that the set of items is the same in the original database (as
-dumped by the version of DB that created it) as in the upgraded one,
-and is the same in the original database and in a new database generated by
-db_loading a db_dump.
-
-In db 3.X and higher, the upgrade test is repeated on a database with
-the opposite endianness to the system the database was generated on.
-
-How to generate test databases:
-
-Ordinarily, this is something that only very rarely has to occur;
-an archive of upgrade test databases can and should be kept, so ideally
-the generation step only needs to be done once for each major DB release.
-
-To generate the test databases, execute the command "gen_upgrade <dir>"
-inside a tclsh. The method tests will run twice, once for each endianness,
-and all the databases will be saved in a hierarchy named by <dir>.
-
-Once the databases have been built, the archives expected by the upgrade tests
-must be built using the "pack" script, in upgrade/scripts/pack-<version>.pl.
-This script must be edited slightly to specify the location on a given system
-of the DB source tree and utilities; it then converts the set of databases
-under the current working directory into a set of .tar.gz files containing
-the databases as well as flat files with their contents in item-by-item and
-db_dump formats.
-
-How to run the upgrade tests:
-
-Run "upgrade" from tclsh in the DB build directory. By default, this
-looks in upgrade/databases, in the DB source tree. An optional first argument
-can be used to specify an alternate directory.
-
-A note on 2.X tests:
-
-The 2.X packing script, as well as a patch against a 2.6.6 test directory
-to allow it to generate test databases, is in upgrade/generate-2.X.
-
-Note that the upgrade tests can be *run* on an the 2.X test archives
-without anything in this directory. It is provided only for
-archival reasons, in case there is ever reason to generate a new
-set of test databases.
-
-XXX: Note also that it quite likely has paths hard-coded for a specific
-system that is not yours.
-
-Known Issues:
-
-1. The following 2.X databases trigger a bug in the db 2.X hash code.
-This bug affects only empty and near-empty databases, and has been
-corrected in db 3.X, but it will prevent the following from passing
-the db_dump test. (They have been removed from the canonical database
-collection.)
-
- 2.X hash -- test026
- 2.X hash -- test038
- 2.X hash -- test039
- 2.X hash -- test040
-
-2. The 2.X recno versions of test043 cannot be made to pass the db_dump
-test because the 2.X version of db_dump has no -k flag and cannot preserve
-sparsely populated databases.
diff --git a/bdb/test/upgrade/generate-2.X/pack-2.6.6.pl b/bdb/test/upgrade/generate-2.X/pack-2.6.6.pl
deleted file mode 100644
index f031d46ca62..00000000000
--- a/bdb/test/upgrade/generate-2.X/pack-2.6.6.pl
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use Archive::Tar;
-
-my $subdir;
-my $file;
-my $archive_name;
-
-my $version = "2.6.6";
-my $build_dir = "/work/db/upgrade/db-2.6.6/build_unix";
-my $db_dump_path = "$build_dir/db_dump";
-my $pwd = `pwd`;
-
-$| = 1;
-
-chomp( $pwd );
-
-opendir( DIR, $version . "le" ) || die;
-while( $subdir = readdir( DIR ) )
-{
- if( $subdir !~ m{^\.\.?$} )
- {
- opendir( SUBDIR, $version . "le/$subdir" ) || die;
- while( $file = readdir( SUBDIR ) )
- {
- if( $file !~ m{^\.\.?$} )
- {
- print "[" . localtime() . "] " . "$subdir $file", "\n";
-
- eval
- {
- my $data;
- my $archive;
-
- system( "mkdir", "-p", "$version/$subdir" );
- $file =~ m{(.*)\.};
- $archive_name = "$1";
- $archive_name =~ s{Test}{test};
- $archive = Archive::Tar->new();
- $archive->add_data( "$archive_name-le.db",
- read_file( $version . "le/$subdir/$file" ) );
-# $archive->add_data( "$archive_name-be.db",
-# read_file( $version . "be/$subdir/$file" ) );
- $archive->add_data( "$archive_name.dump",
- db_dump( "$pwd/$version" . "le/$subdir/$file" ) );
- $data = tcl_dump( "$pwd/$version" . "le/$subdir/$file" );
- $archive->add_data( "$archive_name.tcldump", $data );
- $archive->write( "$version/$subdir/$archive_name.tar.gz", 9 );
- };
- if( $@ )
- {
- print( "Could not process $file: $@\n" );
- }
- }
- }
- }
-}
-
-sub read_file
-{
- my ($file) = @_;
- my $data;
-
- open( FILE, "<$file" ) || die;
- read( FILE, $data, -s $file );
- close( file );
-
- return $data;
-}
-
-sub db_dump
-{
- my ($file) = @_;
-
- #print $file, "\n";
- unlink( "temp.dump" );
- system( "sh", "-c", "$db_dump_path $file >temp.dump" ) && die;
- if( -e "temp.dump" )
- {
- return read_file( "temp.dump" );
- }
- else
- {
- die "db_dump failure: $file\n";
- }
-}
-
-sub tcl_dump
-{
- my ($file) = @_;
- my $up_dump_args = "";
-
- if ($file =~ /test012/) {
- $up_dump_args .= "1";
- }
-
- unlink( "temp.dump" );
- open( TCL, "|$build_dir/dbtest" );
-print TCL <<END;
-cd $build_dir
-source ../test/test.tcl
-upgrade_dump $file $pwd/temp.dump $up_dump_args
-END
- close( TCL );
- if( -e "temp.dump" )
- {
- return read_file( "temp.dump" );
- }
- else
- {
- die "TCL dump failure: $file\n";
- }
-}
diff --git a/bdb/test/upgrade/generate-2.X/test-2.6.patch b/bdb/test/upgrade/generate-2.X/test-2.6.patch
deleted file mode 100644
index 557e8061eae..00000000000
--- a/bdb/test/upgrade/generate-2.X/test-2.6.patch
+++ /dev/null
@@ -1,379 +0,0 @@
-diff -crN test.orig/test.tcl test/test.tcl
-*** test.orig/test.tcl Fri Dec 11 14:56:26 1998
---- test/test.tcl Mon Oct 4 15:26:16 1999
-***************
-*** 8,13 ****
---- 8,14 ----
- source ./include.tcl
- source ../test/testutils.tcl
- source ../test/byteorder.tcl
-+ source ../test/upgrade.tcl
-
- set testdir ./TESTDIR
- if { [file exists $testdir] != 1 } {
-***************
-*** 114,119 ****
---- 115,124 ----
- global debug_print
- global debug_on
- global runtests
-+
-+ global __method
-+ set __method $method
-+
- if { $stop == 0 } {
- set stop $runtests
- }
-diff -crN test.orig/testutils.tcl test/testutils.tcl
-*** test.orig/testutils.tcl Tue Dec 15 07:58:51 1998
---- test/testutils.tcl Wed Oct 6 17:40:45 1999
-***************
-*** 680,690 ****
---- 680,698 ----
-
- proc cleanup { dir } {
- source ./include.tcl
-+ global __method
-+ global errorInfo
- # Remove the database and environment.
- txn_unlink $dir 1
- memp_unlink $dir 1
- log_unlink $dir 1
- lock_unlink $dir 1
-+
-+ catch { exec mkdir -p /work/upgrade/2.6/$__method } res
-+ puts $res
-+ catch { exec sh -c "mv $dir/*.db /work/upgrade/2.6/$__method" } res
-+ puts $res
-+
- set ret [catch { glob $dir/* } result]
- if { $ret == 0 } {
- eval exec $RM -rf $result
-diff -crN test.orig/upgrade.tcl test/upgrade.tcl
-*** test.orig/upgrade.tcl Wed Dec 31 19:00:00 1969
---- test/upgrade.tcl Mon Oct 18 21:22:39 1999
-***************
-*** 0 ****
---- 1,322 ----
-+ # See the file LICENSE for redistribution information.
-+ #
-+ # Copyright (c) 1999
-+ # Sleepycat Software. All rights reserved.
-+ #
-+ # @(#)upgrade.tcl 11.1 (Sleepycat) 8/23/99
-+ #
-+ source ./include.tcl
-+ global gen_upgrade
-+ set gen_upgrade 0
-+ global upgrade_dir
-+ set upgrade_dir "/work/upgrade/DOTEST"
-+ global upgrade_be
-+ global upgrade_method
-+
-+ proc upgrade { } {
-+ source ./include.tcl
-+ global upgrade_dir
-+
-+ foreach version [glob $upgrade_dir/*] {
-+ regexp \[^\/\]*$ $version version
-+ foreach method [glob $upgrade_dir/$version/*] {
-+ regexp \[^\/\]*$ $method method
-+ foreach file [glob $upgrade_dir/$version/$method/*] {
-+ puts $file
-+ regexp (\[^\/\]*)\.tar\.gz$ $file dummy name
-+ foreach endianness {"le" "be"} {
-+ puts "Update: $version $method $name $endianness"
-+ set ret [catch {_upgrade $upgrade_dir $testdir $version $method $name $endianness 1 1} message]
-+ if { $ret != 0 } {
-+ puts $message
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ proc _upgrade { source_dir temp_dir version method file endianness do_db_load_test do_upgrade_test } {
-+ source include.tcl
-+ global errorInfo
-+
-+ cleanup $temp_dir
-+
-+ exec tar zxf "$source_dir/$version/$method/$file.tar.gz" -C $temp_dir
-+
-+ if { $do_db_load_test } {
-+ set ret [catch \
-+ {exec ./db_load -f "$temp_dir/$file.dump" \
-+ "$temp_dir/upgrade.db"} message]
-+ error_check_good \
-+ "Update load: $version $method $file $message" $ret 0
-+
-+ set ret [catch \
-+ {exec ./db_dump -f "$temp_dir/upgrade.dump" \
-+ "$temp_dir/upgrade.db"} message]
-+ error_check_good \
-+ "Update dump: $version $method $file $message" $ret 0
-+
-+ error_check_good "Update diff.1.1: $version $method $file" \
-+ [catch { exec $CMP "$temp_dir/$file.dump" "$temp_dir/upgrade.dump" } ret] 0
-+ error_check_good "Update diff.1.2: $version $method $file" $ret ""
-+ }
-+
-+ if { $do_upgrade_test } {
-+ set ret [catch {berkdb open -upgrade "$temp_dir/$file-$endianness.db"} db]
-+ if { $ret == 1 } {
-+ if { ![is_substr $errorInfo "version upgrade"] } {
-+ set fnl [string first "\n" $errorInfo]
-+ set theError [string range $errorInfo 0 [expr $fnl - 1]]
-+ error $theError
-+ }
-+ } else {
-+ error_check_good dbopen [is_valid_db $db] TRUE
-+ error_check_good dbclose [$db close] 0
-+
-+ set ret [catch \
-+ {exec ./db_dump -f "$temp_dir/upgrade.dump" \
-+ "$temp_dir/$file-$endianness.db"} message]
-+ error_check_good \
-+ "Update dump: $version $method $file $message" $ret 0
-+
-+ error_check_good "Update diff.2: $version $method $file" \
-+ [catch { exec $CMP "$temp_dir/$file.dump" "$temp_dir/upgrade.dump" } ret] 0
-+ error_check_good "Update diff.2: $version $method $file" $ret ""
-+ }
-+ }
-+ }
-+
-+ proc gen_upgrade { dir } {
-+ global gen_upgrade
-+ global upgrade_dir
-+ global upgrade_be
-+ global upgrade_method
-+ global __method
-+ global runtests
-+ source ./include.tcl
-+ set tclsh_path "/work/db/upgrade/db-2.6.6/build_unix/dbtest"
-+
-+ set gen_upgrade 1
-+ set upgrade_dir $dir
-+
-+ foreach upgrade_be { 0 1 } {
-+ foreach i "rrecno" {
-+ # "hash btree rbtree hash recno rrecno"
-+ puts "Running $i tests"
-+ set upgrade_method $i
-+ for { set j 1 } { $j <= $runtests } {incr j} {
-+ if [catch {exec $tclsh_path \
-+ << "source ../test/test.tcl; \
-+ run_method $i $j $j"} res] {
-+ puts "FAIL: [format "test%03d" $j] $i"
-+ }
-+ puts $res
-+ set __method $i
-+ cleanup $testdir
-+ }
-+ }
-+ }
-+
-+ set gen_upgrade 0
-+ }
-+
-+ proc upgrade_dump { database file {with_binkey 0} } {
-+ source ./include.tcl
-+ global errorInfo
-+
-+ set is_recno 0
-+
-+ set db [dbopen $database 0 0600 DB_UNKNOWN]
-+ set dbc [$db cursor 0]
-+
-+ set f [open $file w+]
-+ fconfigure $f -encoding binary -translation binary
-+
-+ #
-+ # Get a sorted list of keys
-+ #
-+ set key_list ""
-+ if { [catch {set pair [$dbc get "" $DB_FIRST]}] != 0 } {
-+ set pair [$dbc get 0 $DB_FIRST]
-+ set is_recno 1
-+ }
-+
-+ while { 1 } {
-+ if { [llength $pair] == 0 } {
-+ break
-+ }
-+ lappend key_list [list [lindex $pair 0]]
-+ set pair [$dbc get 0 $DB_NEXT]
-+ }
-+
-+
-+ # Discard duplicated keys; we now have a key for each
-+ # duplicate, not each unique key, and we don't want to get each
-+ # duplicate multiple times when we iterate over key_list.
-+ set uniq_keys {}
-+ foreach key $key_list {
-+ if { [info exists existence_list($key)] == 0 } {
-+ lappend uniq_keys [list $key]
-+ }
-+ set existence_list($key) 1
-+ }
-+ set key_list $uniq_keys
-+
-+ set key_list [lsort -command _comp $key_list]
-+
-+ #foreach llave $key_list {
-+ # puts $llave
-+ #}
-+
-+ #
-+ # Get the data for each key
-+ #
-+
-+ for { set i 0 } { $i < [llength $key_list] } { incr i } {
-+ set key [concat [lindex $key_list $i]]
-+ # XXX Gross awful hack. We want to DB_SET in the vast
-+ # majority of cases, but DB_SET can't handle binary keys
-+ # in the 2.X Tcl interface. So we look manually and linearly
-+ # for the key we want if with_binkey == 1.
-+ if { $with_binkey != 1 } {
-+ set pair [$dbc get $key $DB_SET]
-+ } else {
-+ set pair [_search_binkey $key $dbc]
-+ }
-+ if { $is_recno != 1 } {
-+ set key [upgrade_convkey $key $dbc]
-+ }
-+ #puts "pair:$pair:[lindex $pair 1]"
-+ set data [lindex $pair 1]
-+ set data [upgrade_convdata $data $dbc]
-+ set data_list [list $data]
-+ catch { while { $is_recno == 0 } {
-+ set pair [$dbc get 0 $DB_NEXT_DUP]
-+ if { [llength $pair] == 0 } {
-+ break
-+ }
-+
-+ set data [lindex $pair 1]
-+ set data [upgrade_convdata $data $dbc]
-+ lappend data_list [list $data]
-+ } }
-+ set data_list [lsort -command _comp $data_list]
-+ puts -nonewline $f [binary format i [string length $key]]
-+ puts -nonewline $f $key
-+ puts -nonewline $f [binary format i [llength $data_list]]
-+ for { set j 0 } { $j < [llength $data_list] } { incr j } {
-+ puts -nonewline $f [binary format i [string length [concat [lindex $data_list $j]]]]
-+ puts -nonewline $f [concat [lindex $data_list $j]]
-+ }
-+ }
-+
-+ close $f
-+ }
-+
-+ proc _comp { a b } {
-+ # return expr [[concat $a] < [concat $b]]
-+ return [string compare [concat $a] [concat $b]]
-+ }
-+
-+ # Converts a key to the format of keys in the 3.X Tcl interface
-+ proc upgrade_convkey { key dbc } {
-+ source ./include.tcl
-+
-+ # Stick a null on the end.
-+ set k "$key\0"
-+
-+ set tmp $testdir/gb0
-+
-+ # Attempt a dbc getbinkey to get any additional parts of the key.
-+ set dbt [$dbc getbinkey $tmp 0 $DB_CURRENT]
-+
-+ set tmpid [open $tmp r]
-+ fconfigure $tmpid -encoding binary -translation binary
-+ set cont [read $tmpid]
-+
-+ set k $k$cont
-+
-+ close $tmpid
-+
-+ exec $RM -f $tmp
-+
-+ return $k
-+ }
-+
-+ # Converts a datum to the format of data in the 3.X Tcl interface
-+ proc upgrade_convdata { data dbc } {
-+ source ./include.tcl
-+ set is_partial 0
-+
-+ # Get the datum out of "data"
-+ if { [llength $data] == 1 } {
-+ set d [lindex $data 0]
-+ } elseif { [llength $data] == 2 } {
-+ # It was a partial return; the first arg is the number of nuls
-+ set d [lindex $data 1]
-+ set numnul [lindex $data 0]
-+ while { $numnul > 0 } {
-+ set d "\0$d"
-+ incr numnul -1
-+ }
-+
-+ # The old Tcl getbin and the old Tcl partial put
-+ # interface are incompatible; we'll wind up returning
-+ # the datum twice if we try a getbin now. So
-+ # set a flag to avoid it.
-+ set is_partial 1
-+
-+ } else {
-+ set d $data
-+ }
-+
-+
-+ if { $is_partial != 1 } {
-+
-+ # Stick a null on the end.
-+ set d "$d\0"
-+
-+ set tmp $testdir/gb1
-+
-+ # Attempt a dbc getbin to get any additional parts of the datum
-+ # the Tcl interface has neglected.
-+ set dbt [$dbc getbin $tmp 0 $DB_CURRENT]
-+
-+ set tmpid [open $tmp r]
-+ fconfigure $tmpid -encoding binary -translation binary
-+ set cont [read $tmpid]
-+
-+ set d $d$cont
-+
-+ #puts "$data->$d"
-+
-+ close $tmpid
-+ }
-+
-+ return [list $d]
-+ }
-+
-+ # Implement the DB_SET functionality, stupidly, in terms of DB_NEXT and
-+ # manual comparisons. We have to use this instead of DB_SET with
-+ # binary keys, as the old Tcl interface can't handle binary keys but DB_SET
-+ # requires them. So instead, we page through using DB_NEXT, which returns
-+ # the binary keys only up to the first null, and compare to our specified
-+ # key, which is similarly truncated.
-+ #
-+ # This is really slow, but is seldom used.
-+ proc _search_binkey { key dbc } {
-+ #puts "doing _search_binkey $key $dbc"
-+ source ./include.tcl
-+ set dbt [$dbc get 0 $DB_FIRST]
-+ while { [llength $dbt] != 0 } {
-+ set curkey [lindex $dbt 0]
-+ if { [string compare $key $curkey] == 0 } {
-+ return $dbt
-+ }
-+ set dbt [$dbc get 0 $DB_NEXT]
-+ }
-+
-+ # We didn't find it. Return an empty list.
-+ return {}
-+ }
diff --git a/bdb/test/wrap.tcl b/bdb/test/wrap.tcl
index 4a5c825d8f0..aaceb4f74e6 100644
--- a/bdb/test/wrap.tcl
+++ b/bdb/test/wrap.tcl
@@ -1,12 +1,19 @@
-# Sentinel file wrapper for multi-process tests.
-# This is designed to avoid a set of nasty bugs, primarily on Windows,
-# where pid reuse causes watch_procs to sit around waiting for some
-# random process that's not DB's and is not exiting.
+# See the file LICENSE for redistribution information.
+#
+# Copyright (c) 2000-2002
+# Sleepycat Software. All rights reserved.
+#
+# $Id: wrap.tcl,v 11.6 2002/04/25 13:35:02 bostic Exp $
+#
+# Sentinel file wrapper for multi-process tests. This is designed to avoid a
+# set of nasty bugs, primarily on Windows, where pid reuse causes watch_procs
+# to sit around waiting for some random process that's not DB's and is not
+# exiting.
source ./include.tcl
+source $test_path/testutils.tcl
# Arguments:
-#
if { $argc < 3 } {
puts "FAIL: wrap.tcl: Usage: wrap.tcl script log scriptargs"
exit
@@ -33,13 +40,17 @@ set childsentinel $testdir/begin.$childpid
set f [open $childsentinel w]
close $f
+puts $t "source $test_path/test.tcl"
+puts $t "set script $script"
+
# Set up argv for the subprocess, since the args aren't passed in as true
# arguments thanks to the pipe structure.
puts $t "set argc [llength $args]"
puts $t "set argv [list $args]"
-# Command the test to run.
-puts $t "source $test_path/$script"
+puts $t {set ret [catch { source $test_path/$script } result]}
+puts $t {if { [string length $result] > 0 } { puts $result }}
+puts $t {error_check_good "$test_path/$script run: pid [pid]" $ret 0}
# Close the pipe. This will flush the above commands and actually run the
# test, and will also return an error a la exec if anything bad happens
@@ -55,4 +66,6 @@ close $f
set f [open $testdir/end.$parentpid w]
close $f
+error_check_good "Pipe close ($childpid: $script $argv: logfile $logfile)"\
+ $ret 0
exit $ret
diff --git a/bdb/txn/txn.c b/bdb/txn/txn.c
index 0f6d894c19b..78c54791d06 100644
--- a/bdb/txn/txn.c
+++ b/bdb/txn/txn.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -39,11 +39,12 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: txn.c,v 11.61 2001/01/10 18:18:52 bostic Exp $";
+static const char revid[] = "$Id: txn.c,v 11.179 2002/08/29 17:41:17 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <stdlib.h>
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
@@ -59,58 +60,129 @@ static const char revid[] = "$Id: txn.c,v 11.61 2001/01/10 18:18:52 bostic Exp $
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_shash.h"
-#include "txn.h"
-#include "lock.h"
-#include "log.h"
-#include "db_dispatch.h"
-#include "db_page.h"
-#include "db_ext.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+#define SET_LOG_FLAGS(dbenv, txnp, lflags) \
+ do { \
+ lflags = DB_COMMIT | DB_PERMANENT; \
+ if (F_ISSET(txnp, TXN_SYNC)) \
+ lflags |= DB_FLUSH; \
+ else if (!F_ISSET(txnp, TXN_NOSYNC) && \
+ !F_ISSET(dbenv, DB_ENV_TXN_NOSYNC)) { \
+ if (F_ISSET(dbenv, DB_ENV_TXN_WRITE_NOSYNC)) \
+ lflags |= DB_WRNOSYNC; \
+ else \
+ lflags |= DB_FLUSH; \
+ } \
+ } while (0)
-static int __txn_begin __P((DB_TXN *));
-static int __txn_isvalid __P((const DB_TXN *, TXN_DETAIL **, u_int32_t));
+/*
+ * __txn_isvalid enumerated types. We cannot simply use the transaction
+ * statuses, because different statuses need to be handled differently
+ * depending on the caller.
+ */
+typedef enum {
+ TXN_OP_ABORT,
+ TXN_OP_COMMIT,
+ TXN_OP_DISCARD,
+ TXN_OP_PREPARE
+} txnop_t;
+
+static int __txn_begin_int __P((DB_TXN *, int));
+static int __txn_end __P((DB_TXN *, int));
+static int __txn_isvalid __P((const DB_TXN *, TXN_DETAIL **, txnop_t));
+static int __txn_set_timeout __P(( DB_TXN *, db_timeout_t, u_int32_t));
static int __txn_undo __P((DB_TXN *));
+#ifndef db_create
/*
+ * txn_abort --
* txn_begin --
- * This is a wrapper to the actual begin process. Normal txn_begin()
- * allocates a DB_TXN structure for the caller, while txn_xa_begin() does
- * not. Other than that, both call into the common __txn_begin code().
+ * txn_commit --
+ *
+ * When we switched to methods in 4.0, we guessed txn_{abort,begin,commit}
+ * were the interfaces applications would likely use and not be willing to
+ * change, due to the sheer volume of the calls. Provide wrappers -- we
+ * could do txn_abort and txn_commit using macros, but not txn_begin, as
+ * the name of the field is txn_begin, we didn't want to modify it.
+ *
+ * The issue with txn_begin hits us in another way. If configured with the
+ * --with-uniquename option, we use #defines to re-define DB's interfaces
+ * to unique names. We can't do that for these functions because txn_begin
+ * is also a field name in the DB_ENV structure, and the #defines we use go
+ * at the end of the db.h file -- we get control too late to #define a field
+ * name. So, modify the script that generates the unique names #defines to
+ * not generate them for these three functions, and don't include the three
+ * functions in libraries built with that configuration option.
+ *
+ * EXTERN: int txn_abort __P((DB_TXN *));
+ * EXTERN: int txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
+ * EXTERN: int txn_commit __P((DB_TXN *, u_int32_t));
+ */
+int
+txn_abort(txnp)
+ DB_TXN *txnp;
+{
+ return (txnp->abort(txnp));
+}
+
+int
+txn_begin(dbenv, parent, txnpp, flags)
+ DB_ENV *dbenv;
+ DB_TXN *parent, **txnpp;
+ u_int32_t flags;
+{
+ return (dbenv->txn_begin(dbenv, parent, txnpp, flags));
+}
+
+int
+txn_commit(txnp, flags)
+ DB_TXN *txnp;
+ u_int32_t flags;
+{
+ return (txnp->commit(txnp, flags));
+}
+#endif /* !db_create */
+
+/*
+ * __txn_begin --
+ * This is a wrapper to the actual begin process. Normal transaction
+ * begin allocates a DB_TXN structure for the caller, while XA transaction
+ * begin does not. Other than that, both call into common __txn_begin_int
+ * code.
*
* Internally, we use TXN_DETAIL structures, but the DB_TXN structure
* provides access to the transaction ID and the offset in the transaction
* region of the TXN_DETAIL structure.
+ *
+ * PUBLIC: int __txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
*/
int
-txn_begin(dbenv, parent, txnpp, flags)
+__txn_begin(dbenv, parent, txnpp, flags)
DB_ENV *dbenv;
DB_TXN *parent, **txnpp;
u_int32_t flags;
{
+ DB_LOCKREGION *region;
DB_TXN *txn;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_txn_begin(dbenv, parent, txnpp, flags));
-#endif
-
+ *txnpp = NULL;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, DB_INIT_TXN);
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_begin", DB_INIT_TXN);
if ((ret = __db_fchk(dbenv,
"txn_begin", flags,
- DB_TXN_NOWAIT | DB_TXN_NOSYNC | DB_TXN_SYNC)) != 0)
+ DB_DIRTY_READ | DB_TXN_NOWAIT |
+ DB_TXN_NOSYNC | DB_TXN_SYNC)) != 0)
return (ret);
if ((ret = __db_fcchk(dbenv,
"txn_begin", flags, DB_TXN_NOSYNC, DB_TXN_SYNC)) != 0)
@@ -122,7 +194,10 @@ txn_begin(dbenv, parent, txnpp, flags)
txn->mgrp = dbenv->tx_handle;
txn->parent = parent;
TAILQ_INIT(&txn->kids);
+ TAILQ_INIT(&txn->events);
txn->flags = TXN_MALLOC;
+ if (LF_ISSET(DB_DIRTY_READ))
+ F_SET(txn, TXN_DIRTY_READ);
if (LF_ISSET(DB_TXN_NOSYNC))
F_SET(txn, TXN_NOSYNC);
if (LF_ISSET(DB_TXN_SYNC))
@@ -130,15 +205,41 @@ txn_begin(dbenv, parent, txnpp, flags)
if (LF_ISSET(DB_TXN_NOWAIT))
F_SET(txn, TXN_NOWAIT);
- if ((ret = __txn_begin(txn)) != 0) {
- __os_free(txn, sizeof(DB_TXN));
- txn = NULL;
- }
+ if ((ret = __txn_begin_int(txn, 0)) != 0)
+ goto err;
- if (txn != NULL && parent != NULL)
+ if (parent != NULL)
TAILQ_INSERT_HEAD(&parent->kids, txn, klinks);
+ if (LOCKING_ON(dbenv)) {
+ region = ((DB_LOCKTAB *)dbenv->lk_handle)->reginfo.primary;
+ if (parent != NULL) {
+ ret = __lock_inherit_timeout(dbenv,
+ parent->txnid, txn->txnid);
+ /* No parent locker set yet. */
+ if (ret == EINVAL) {
+ parent = NULL;
+ ret = 0;
+ }
+ if (ret != 0)
+ goto err;
+ }
+
+ /*
+ * Parent is NULL if we have no parent
+ * or it has no timeouts set.
+ */
+ if (parent == NULL && region->tx_timeout != 0)
+ if ((ret = __lock_set_timeout(dbenv, txn->txnid,
+ region->tx_timeout, DB_SET_TXN_TIMEOUT)) != 0)
+ goto err;
+ }
+
*txnpp = txn;
+ return (0);
+
+err:
+ __os_free(dbenv, txn);
return (ret);
}
@@ -158,26 +259,60 @@ __txn_xa_begin(dbenv, txn)
memset(txn, 0, sizeof(DB_TXN));
txn->mgrp = dbenv->tx_handle;
+ TAILQ_INIT(&txn->kids);
+ TAILQ_INIT(&txn->events);
- return (__txn_begin(txn));
+ return (__txn_begin_int(txn, 0));
}
/*
- * __txn_begin --
+ * __txn_compensate_begin
+ * Begin an compensation transaction. This is a special interface
+ * that is used only for transactions that must be started to compensate
+ * for actions during an abort. Currently only used for allocations.
+ *
+ * PUBLIC: int __txn_compensate_begin __P((DB_ENV *, DB_TXN **txnp));
+ */
+int
+__txn_compensate_begin(dbenv, txnpp)
+ DB_ENV *dbenv;
+ DB_TXN **txnpp;
+{
+ DB_TXN *txn;
+ int ret;
+
+ PANIC_CHECK(dbenv);
+
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), &txn)) != 0)
+ return (ret);
+
+ txn->mgrp = dbenv->tx_handle;
+ TAILQ_INIT(&txn->kids);
+ TAILQ_INIT(&txn->events);
+ txn->flags = TXN_MALLOC;
+ F_SET(txn, TXN_COMPENSATE);
+
+ *txnpp = txn;
+ return (__txn_begin_int(txn, 1));
+}
+
+/*
+ * __txn_begin_int --
* Normal DB version of txn_begin.
*/
static int
-__txn_begin(txn)
+__txn_begin_int(txn, internal)
DB_TXN *txn;
+ int internal;
{
DB_ENV *dbenv;
- DB_LSN begin_lsn;
+ DB_LSN begin_lsn, null_lsn;
DB_TXNMGR *mgr;
DB_TXNREGION *region;
TXN_DETAIL *td;
size_t off;
- u_int32_t id;
- int ret;
+ u_int32_t id, *ids;
+ int nids, ret;
mgr = txn->mgrp;
dbenv = mgr->dbenv;
@@ -188,36 +323,73 @@ __txn_begin(txn)
* need never write records for read-only transactions). However,
* we do need to find the current LSN so that we can store it in the
* transaction structure, so we can know where to take checkpoints.
+ *
+ * XXX
+ * We should set this value when we write the first log record, not
+ * here.
*/
- if (LOGGING_ON(dbenv) &&
- (ret = log_put(dbenv, &begin_lsn, NULL, DB_CURLSN)) != 0)
- goto err2;
+ if (DBENV_LOGGING(dbenv))
+ __log_txn_lsn(dbenv, &begin_lsn, NULL, NULL);
R_LOCK(dbenv, &mgr->reginfo);
+ if (!F_ISSET(txn, TXN_COMPENSATE) && F_ISSET(region, TXN_IN_RECOVERY)) {
+ __db_err(dbenv, "operation not permitted during recovery");
+ ret = EINVAL;
+ goto err;
+ }
- /* Make sure that last_txnid is not going to wrap around. */
- if (region->last_txnid == TXN_INVALID) {
+ /* Make sure that we aren't still recovering prepared transactions. */
+ if (!internal && region->stat.st_nrestores != 0) {
__db_err(dbenv,
-"txn_begin: transaction ID wrapped. Exit the database environment\nand restart the application as if application failure had occurred");
+ "recovery of prepared but not yet committed transactions is incomplete");
ret = EINVAL;
- goto err1;
+ goto err;
+ }
+
+ /*
+ * Allocate a new transaction id. Our current valid range can span
+ * the maximum valid value, so check for it and wrap manually.
+ */
+ if (region->last_txnid == TXN_MAXIMUM &&
+ region->cur_maxid != TXN_MAXIMUM)
+ region->last_txnid = TXN_MINIMUM - 1;
+
+ if (region->last_txnid == region->cur_maxid) {
+ if ((ret = __os_malloc(dbenv,
+ sizeof(u_int32_t) * region->maxtxns, &ids)) != 0)
+ goto err;
+ nids = 0;
+ for (td = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
+ td != NULL;
+ td = SH_TAILQ_NEXT(td, links, __txn_detail))
+ ids[nids++] = td->txnid;
+ region->last_txnid = TXN_MINIMUM - 1;
+ region->cur_maxid = TXN_MAXIMUM;
+ if (nids != 0)
+ __db_idspace(ids, nids,
+ &region->last_txnid, &region->cur_maxid);
+ __os_free(dbenv, ids);
+ if (DBENV_LOGGING(dbenv) &&
+ (ret = __txn_recycle_log(dbenv, NULL,
+ &null_lsn, 0, region->last_txnid, region->cur_maxid)) != 0)
+ goto err;
}
/* Allocate a new transaction detail structure. */
if ((ret =
__db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {
__db_err(dbenv,
- "Unable to allocate memory for transaction detail");
- goto err1;
+ "Unable to allocate memory for transaction detail");
+ goto err;
}
/* Place transaction on active transaction list. */
SH_TAILQ_INSERT_HEAD(&region->active_txn, td, links, __txn_detail);
id = ++region->last_txnid;
- ++region->nbegins;
- if (++region->nactive > region->maxnactive)
- region->maxnactive = region->nactive;
+ ++region->stat.st_nbegins;
+ if (++region->stat.st_nactive > region->stat.st_maxnactive)
+ region->stat.st_maxnactive = region->stat.st_nactive;
td->txnid = id;
td->begin_lsn = begin_lsn;
@@ -228,12 +400,20 @@ __txn_begin(txn)
else
td->parent = INVALID_ROFF;
+ td->flags = 0;
off = R_OFFSET(&mgr->reginfo, td);
R_UNLOCK(dbenv, &mgr->reginfo);
ZERO_LSN(txn->last_lsn);
txn->txnid = id;
- txn->off = off;
+ txn->off = (u_int32_t)off;
+
+ txn->abort = __txn_abort;
+ txn->commit = __txn_commit;
+ txn->discard = __txn_discard;
+ txn->id = __txn_id;
+ txn->prepare = __txn_prepare;
+ txn->set_timeout = __txn_set_timeout;
/*
* If this is a transaction family, we must link the child to the
@@ -242,7 +422,7 @@ __txn_begin(txn)
if (txn->parent != NULL && LOCKING_ON(dbenv))
if ((ret = __lock_addfamilylocker(dbenv,
txn->parent->txnid, txn->txnid)) != 0)
- goto err2;
+ return (ret);
if (F_ISSET(txn, TXN_MALLOC)) {
MUTEX_THREAD_LOCK(dbenv, mgr->mutexp);
@@ -252,34 +432,33 @@ __txn_begin(txn)
return (0);
-err1: R_UNLOCK(dbenv, &mgr->reginfo);
-
-err2: return (ret);
+err: R_UNLOCK(dbenv, &mgr->reginfo);
+ return (ret);
}
/*
- * txn_commit --
+ * __txn_commit --
* Commit a transaction.
+ *
+ * PUBLIC: int __txn_commit __P((DB_TXN *, u_int32_t));
*/
int
-txn_commit(txnp, flags)
+__txn_commit(txnp, flags)
DB_TXN *txnp;
u_int32_t flags;
{
DB_ENV *dbenv;
+ DB_LOCKREQ request;
DB_TXN *kid;
- int is_commit, ret, t_ret;
+ TXN_DETAIL *td;
+ u_int32_t lflags;
+ int ret, t_ret;
dbenv = txnp->mgrp->dbenv;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_txn_commit(txnp, flags));
-#endif
-
PANIC_CHECK(dbenv);
- if ((ret = __txn_isvalid(txnp, NULL, TXN_COMMITTED)) != 0)
+ if ((ret = __txn_isvalid(txnp, &td, TXN_OP_COMMIT)) != 0)
return (ret);
/*
@@ -290,10 +469,10 @@ txn_commit(txnp, flags)
* specifying the wrong flag for some reason.
*/
if (__db_fchk(dbenv,
- "txn_commit", flags, DB_TXN_NOSYNC | DB_TXN_SYNC) != 0)
+ "DB_TXN->commit", flags, DB_TXN_NOSYNC | DB_TXN_SYNC) != 0)
flags = DB_TXN_SYNC;
if (__db_fcchk(dbenv,
- "txn_commit", flags, DB_TXN_NOSYNC, DB_TXN_SYNC) != 0)
+ "DB_TXN->commit", flags, DB_TXN_NOSYNC, DB_TXN_SYNC) != 0)
flags = DB_TXN_SYNC;
if (LF_ISSET(DB_TXN_NOSYNC)) {
F_CLR(txnp, TXN_SYNC);
@@ -305,16 +484,33 @@ txn_commit(txnp, flags)
}
/*
- * Commit any unresolved children. If there's an error, abort any
- * unresolved children and the parent.
+ * Commit any unresolved children. If anyone fails to commit,
+ * then try to abort the rest of the kids and then abort the parent.
+ * Abort should never fail; if it does, we bail out immediately.
*/
while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
- if ((ret = txn_commit(kid, flags)) != 0) {
+ if ((ret = kid->commit(kid, flags)) != 0)
while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
- (void)txn_abort(kid);
- (void)txn_abort(txnp);
- goto err;
- }
+ if ((t_ret = kid->abort(kid)) != 0)
+ return (__db_panic(dbenv, t_ret));
+
+ /*
+ * Process any aborted pages from our children.
+ * We delay putting pages on the free list that are newly
+ * allocated and then aborted so that we can undo other
+ * allocations, if necessary, without worrying about
+ * these pages which were not on the free list before.
+ */
+ if (txnp->txn_list != NULL) {
+ t_ret = __db_do_the_limbo(dbenv, NULL, txnp, txnp->txn_list);
+ __db_txnlist_end(dbenv, txnp->txn_list);
+ txnp->txn_list = NULL;
+ if (t_ret != 0 && ret == 0)
+ ret = t_ret;
+ }
+
+ if (ret != 0)
+ goto err;
/*
* If there are any log records, write a log record and sync the log,
@@ -322,27 +518,35 @@ txn_commit(txnp, flags)
* we do not need to commit the child synchronously since it may still
* abort (if its parent aborts), and otherwise its parent or ultimate
* ancestor will write synchronously.
- *
- * I'd rather return a logging error than a flag-wrong error, so if
- * the log routines fail, set "ret" without regard to previous value.
*/
- if (LOGGING_ON(dbenv) && !IS_ZERO_LSN(txnp->last_lsn)) {
+ if (DBENV_LOGGING(dbenv) && !IS_ZERO_LSN(txnp->last_lsn)) {
if (txnp->parent == NULL) {
- if ((t_ret = __txn_regop_log(dbenv,
- txnp, &txnp->last_lsn,
- (F_ISSET(dbenv, DB_ENV_TXN_NOSYNC) &&
- !F_ISSET(txnp, TXN_SYNC)) ||
- F_ISSET(txnp, TXN_NOSYNC) ? 0 : DB_FLUSH,
- TXN_COMMIT, (int32_t)time(NULL))) != 0) {
- ret = t_ret;
+ /*
+ * We are about to free all the read locks
+ * for this transaction below. Some of those
+ * locks might be handle locks which should
+ * not be freed, because they will be freed
+ * when the handle is closed. Check the
+ * events and preprocess any trades now so
+ * that we don't release the locks below.
+ */
+ if ((ret = __txn_doevents(dbenv, txnp, 0, 1)) != 0)
+ goto err;
+ request.op = DB_LOCK_PUT_READ;
+ if (LOCKING_ON(dbenv) && (ret = dbenv->lock_vec(
+ dbenv, txnp->txnid, 0, &request, 1, NULL)) != 0)
+ goto err;
+
+ SET_LOG_FLAGS(dbenv, txnp, lflags);
+ if ((ret = __txn_regop_log(dbenv,
+ txnp, &txnp->last_lsn, lflags,
+ TXN_COMMIT, (int32_t)time(NULL))) != 0)
goto err;
- }
} else {
/* Log the commit in the parent! */
- if ((t_ret = __txn_child_log(dbenv,
+ if ((ret = __txn_child_log(dbenv,
txnp->parent, &txnp->parent->last_lsn,
0, txnp->txnid, &txnp->last_lsn)) != 0) {
- ret = t_ret;
goto err;
}
@@ -350,108 +554,206 @@ txn_commit(txnp, flags)
}
}
- is_commit = 1;
- if (0) {
-err: is_commit = 0;
- }
- if ((t_ret = __txn_end(txnp, is_commit)) != 0 && ret == 0)
+ /* This is OK because __txn_end can only fail with a panic. */
+ return (__txn_end(txnp, 1));
+
+err: /*
+ * If we are prepared, then we "must" be able to commit. We
+ * panic here because even though the coordinator might be
+ * able to retry it is not clear it would know to do that.
+ * Otherwise we'll try to abort. If that is successful,
+ * then we return whatever was in ret (i.e., the reason we failed).
+ * If the abort was unsuccessful, then abort probably returned
+ * DB_RUNRECOVERY and we need to propagate that up.
+ */
+ if (td->status == TXN_PREPARED)
+ return (__db_panic(dbenv, ret));
+
+ if ((t_ret = txnp->abort(txnp)) != 0)
ret = t_ret;
return (ret);
}
/*
- * txn_abort --
+ * __txn_abort --
* Abort a transaction.
+ *
+ * PUBLIC: int __txn_abort __P((DB_TXN *));
*/
int
-txn_abort(txnp)
+__txn_abort(txnp)
DB_TXN *txnp;
{
DB_ENV *dbenv;
+ DB_LOCKREQ request;
DB_TXN *kid;
- int ret, t_ret;
+ TXN_DETAIL *td;
+ u_int32_t lflags;
+ int ret;
dbenv = txnp->mgrp->dbenv;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_txn_abort(txnp));
-#endif
+ PANIC_CHECK(dbenv);
+
+ /* Ensure that abort always fails fatally. */
+ if ((ret = __txn_isvalid(txnp, &td, TXN_OP_ABORT)) != 0)
+ return (__db_panic(dbenv, ret));
+
+ /*
+ * Try to abort any unresolved children.
+ *
+ * Abort either succeeds or panics the region. As soon as we
+ * see any failure, we just get out of here and return the panic
+ * up.
+ */
+ while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
+ if ((ret = kid->abort(kid)) != 0)
+ return (ret);
+
+ if (LOCKING_ON(dbenv)) {
+ /*
+ * We are about to free all the read locks for this transaction
+ * below. Some of those locks might be handle locks which
+ * should not be freed, because they will be freed when the
+ * handle is closed. Check the events and preprocess any
+ * trades now so that we don't release the locks below.
+ */
+ if ((ret = __txn_doevents(dbenv, txnp, 0, 1)) != 0)
+ return (__db_panic(dbenv, ret));
+
+ /* Turn off timeouts. */
+ if ((ret = __lock_set_timeout(dbenv,
+ txnp->txnid, 0, DB_SET_TXN_TIMEOUT)) != 0)
+ return (__db_panic(dbenv, ret));
+
+ if ((ret = __lock_set_timeout(dbenv,
+ txnp->txnid, 0, DB_SET_LOCK_TIMEOUT)) != 0)
+ return (__db_panic(dbenv, ret));
+
+ request.op = DB_LOCK_UPGRADE_WRITE;
+ if ((ret = dbenv->lock_vec(
+ dbenv, txnp->txnid, 0, &request, 1, NULL)) != 0)
+ return (__db_panic(dbenv, ret));
+ }
+ if ((ret = __txn_undo(txnp)) != 0)
+ return (__db_panic(dbenv, ret));
+
+ /*
+ * Normally, we do not need to log aborts. However, if we
+ * are a distributed transaction (i.e., we have a prepare),
+ * then we log the abort so we know that this transaction
+ * was actually completed.
+ */
+ SET_LOG_FLAGS(dbenv, txnp, lflags);
+ if (DBENV_LOGGING(dbenv) && td->status == TXN_PREPARED &&
+ (ret = __txn_regop_log(dbenv, txnp, &txnp->last_lsn,
+ lflags, TXN_ABORT, (int32_t)time(NULL))) != 0)
+ return (__db_panic(dbenv, ret));
+
+ /* __txn_end always panics if it errors, so pass the return along. */
+ return (__txn_end(txnp, 0));
+}
+
+/*
+ * __txn_discard --
+ * Free the per-process resources associated with this txn handle.
+ *
+ * PUBLIC: int __txn_discard __P((DB_TXN *, u_int32_t flags));
+ */
+int
+__txn_discard(txnp, flags)
+ DB_TXN *txnp;
+ u_int32_t flags;
+{
+ DB_ENV *dbenv;
+ DB_TXN *freep;
+ TXN_DETAIL *td;
+ int ret;
+
+ COMPQUIET(flags, 0);
+
+ dbenv = txnp->mgrp->dbenv;
+ freep = NULL;
PANIC_CHECK(dbenv);
- if ((ret = __txn_isvalid(txnp, NULL, TXN_ABORTED)) != 0)
+ if ((ret = __txn_isvalid(txnp, &td, TXN_OP_DISCARD)) != 0)
return (ret);
- /* Abort any unresolved children. */
- while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
- if ((t_ret = txn_abort(kid)) != 0 && ret == 0)
- ret = t_ret;
+ /* Should be no children. */
+ DB_ASSERT(TAILQ_FIRST(&txnp->kids) == NULL);
+ DB_ASSERT(F_ISSET(td, TXN_RESTORED));
- if ((t_ret = __txn_undo(txnp)) != 0 && ret == 0)
- ret = t_ret;
+ /* Free the space. */
+ MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
+ txnp->mgrp->n_discards++;
+ if (F_ISSET(txnp, TXN_MALLOC)) {
+ TAILQ_REMOVE(&txnp->mgrp->txn_chain, txnp, links);
+ freep = txnp;
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, txnp->mgrp->mutexp);
+ if (freep != NULL)
+ __os_free(dbenv, freep);
- if ((t_ret = __txn_end(txnp, 0)) != 0 && ret == 0)
- ret = t_ret;
- return (ret);
+ return (0);
}
/*
- * txn_prepare --
+ * __txn_prepare --
* Flush the log so a future commit is guaranteed to succeed.
+ *
+ * PUBLIC: int __txn_prepare __P((DB_TXN *, u_int8_t *));
*/
int
-txn_prepare(txnp)
+__txn_prepare(txnp, gid)
DB_TXN *txnp;
+ u_int8_t *gid;
{
DBT xid;
DB_ENV *dbenv;
DB_TXN *kid;
TXN_DETAIL *td;
+ u_int32_t lflags;
int ret;
dbenv = txnp->mgrp->dbenv;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_txn_prepare(txnp));
-#endif
-
PANIC_CHECK(dbenv);
- if ((ret = __txn_isvalid(txnp, &td, TXN_PREPARED)) != 0)
+ if ((ret = __txn_isvalid(txnp, &td, TXN_OP_PREPARE)) != 0)
return (ret);
- /* Prepare any unresolved children. */
+ /* Commit any unresolved children. */
while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
- if ((ret = txn_prepare(kid)) != 0)
+ if ((ret = kid->commit(kid, DB_TXN_NOSYNC)) != 0)
return (ret);
/*
- * We indicate that a transaction is an XA transaction by putting
- * a valid size in the xid.size fiels. XA requires that the transaction
- * be either ENDED or SUSPENDED when prepare is called, so we know
- * that if the xa_status isn't in one of those states, but we are
- * calling prepare that we are not an XA transaction.
+ * In XA, the global transaction ID in the txn_detail structure is
+ * already set; in a non-XA environment, we must set it here. XA
+ * requires that the transaction be either ENDED or SUSPENDED when
+ * prepare is called, so we know that if the xa_status isn't in one
+ * of those states, then we are calling prepare directly and we need
+ * to fill in the td->xid.
*/
-
- if (LOGGING_ON(dbenv)) {
+ if (DBENV_LOGGING(dbenv)) {
memset(&xid, 0, sizeof(xid));
+ if (td->xa_status != TXN_XA_ENDED &&
+ td->xa_status != TXN_XA_SUSPENDED)
+ /* Regular prepare; fill in the gid. */
+ memcpy(td->xid, gid, sizeof(td->xid));
+
+ xid.size = sizeof(td->xid);
xid.data = td->xid;
- xid.size = td->xa_status != TXN_XA_ENDED &&
- td->xa_status != TXN_XA_SUSPENDED ? 0 : sizeof(td->xid);
+
+ SET_LOG_FLAGS(dbenv, txnp, lflags);
if ((ret = __txn_xa_regop_log(dbenv, txnp, &txnp->last_lsn,
- (F_ISSET(dbenv, DB_ENV_TXN_NOSYNC) &&
- !F_ISSET(txnp, TXN_SYNC)) ||
- F_ISSET(txnp, TXN_NOSYNC) ? 0 : DB_FLUSH, TXN_PREPARE,
- &xid, td->format, td->gtrid, td->bqual,
+ lflags, TXN_PREPARE, &xid, td->format, td->gtrid, td->bqual,
&td->begin_lsn)) != 0) {
- __db_err(dbenv, "txn_prepare: log_write failed %s",
+ __db_err(dbenv, "DB_TXN->prepare: log_write failed %s",
db_strerror(ret));
return (ret);
}
- if (txnp->parent != NULL)
- F_SET(txnp->parent, TXN_CHILDCOMMIT);
}
MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
@@ -461,17 +763,36 @@ txn_prepare(txnp)
}
/*
- * txn_id --
+ * __txn_id --
* Return the transaction ID.
+ *
+ * PUBLIC: u_int32_t __txn_id __P((DB_TXN *));
*/
u_int32_t
-txn_id(txnp)
+__txn_id(txnp)
DB_TXN *txnp;
{
return (txnp->txnid);
}
/*
+ * __txn_set_timeout --
+ * Set timeout values in the txn structure.
+ */
+static int
+__txn_set_timeout(txnp, timeout, op)
+ DB_TXN *txnp;
+ db_timeout_t timeout;
+ u_int32_t op;
+{
+ if (op != DB_SET_TXN_TIMEOUT && op != DB_SET_LOCK_TIMEOUT)
+ return (__db_ferr(txnp->mgrp->dbenv, "DB_TXN->set_timeout", 0));
+
+ return (__lock_set_timeout(
+ txnp->mgrp->dbenv, txnp->txnid, timeout, op));
+}
+
+/*
* __txn_isvalid --
* Return 0 if the txnp is reasonable, otherwise panic.
*/
@@ -479,12 +800,22 @@ static int
__txn_isvalid(txnp, tdp, op)
const DB_TXN *txnp;
TXN_DETAIL **tdp;
- u_int32_t op;
+ txnop_t op;
{
DB_TXNMGR *mgrp;
+ DB_TXNREGION *region;
TXN_DETAIL *tp;
mgrp = txnp->mgrp;
+ region = mgrp->reginfo.primary;
+
+ /* Check for recovery. */
+ if (!F_ISSET(txnp, TXN_COMPENSATE) &&
+ F_ISSET(region, TXN_IN_RECOVERY)) {
+ __db_err(mgrp->dbenv,
+ "operation not permitted during recovery");
+ goto err;
+ }
/* Check for live cursors. */
if (txnp->cursors != 0) {
@@ -492,25 +823,70 @@ __txn_isvalid(txnp, tdp, op)
goto err;
}
- /* Check transaction's status. */
+ /* Check transaction's state. */
tp = (TXN_DETAIL *)R_ADDR(&mgrp->reginfo, txnp->off);
if (tdp != NULL)
*tdp = tp;
+ /* Handle any operation specific checks. */
+ switch (op) {
+ case TXN_OP_DISCARD:
+ /*
+ * Since we're just tossing the per-process space; there are
+ * a lot of problems with the transaction that we can tolerate.
+ */
+
+ /* Transaction is already been reused. */
+ if (txnp->txnid != tp->txnid)
+ return (0);
+
+ /* What we've got had better be a restored transaction. */
+ if (!F_ISSET(tp, TXN_RESTORED)) {
+ __db_err(mgrp->dbenv, "not a restored transaction");
+ return (__db_panic(mgrp->dbenv, EINVAL));
+ }
+
+ return (0);
+ case TXN_OP_PREPARE:
+ if (txnp->parent != NULL) {
+ /*
+ * This is not fatal, because you could imagine an
+ * application that simply prepares everybody because
+ * it doesn't distinguish between children and parents.
+ * I'm not arguing this is good, but I could imagine
+ * someone doing it.
+ */
+ __db_err(mgrp->dbenv,
+ "Prepare disallowed on child transactions");
+ return (EINVAL);
+ }
+ break;
+ case TXN_OP_ABORT:
+ case TXN_OP_COMMIT:
+ default:
+ break;
+ }
+
switch (tp->status) {
+ case TXN_PREPARED:
+ if (op == TXN_OP_PREPARE) {
+ __db_err(mgrp->dbenv, "transaction already prepared");
+ /*
+ * Txn_prepare doesn't blow away the user handle, so
+ * in this case, give the user the opportunity to
+ * abort or commit.
+ */
+ return (EINVAL);
+ }
+ break;
+ case TXN_RUNNING:
+ break;
case TXN_ABORTED:
case TXN_COMMITTED:
default:
__db_err(mgrp->dbenv, "transaction already %s",
tp->status == TXN_COMMITTED ? "committed" : "aborted");
goto err;
- case TXN_PREPARED:
- if (op == TXN_PREPARED) {
- __db_err(mgrp->dbenv, "transaction already prepared");
- goto err;
- }
- case TXN_RUNNING:
- break;
}
return (0);
@@ -526,10 +902,8 @@ err: /*
/*
* __txn_end --
* Internal transaction end routine.
- *
- * PUBLIC: int __txn_end __P((DB_TXN *, int));
*/
-int
+static int
__txn_end(txnp, is_commit)
DB_TXN *txnp;
int is_commit;
@@ -539,46 +913,59 @@ __txn_end(txnp, is_commit)
DB_TXNMGR *mgr;
DB_TXNREGION *region;
TXN_DETAIL *tp;
- int ret;
+ int do_closefiles, ret;
mgr = txnp->mgrp;
dbenv = mgr->dbenv;
region = mgr->reginfo.primary;
+ do_closefiles = 0;
+
+ /* Process commit events. */
+ if ((ret = __txn_doevents(dbenv, txnp, is_commit, 0)) != 0)
+ return (__db_panic(dbenv, ret));
/* Release the locks. */
request.op = txnp->parent == NULL ||
is_commit == 0 ? DB_LOCK_PUT_ALL : DB_LOCK_INHERIT;
- if (LOCKING_ON(dbenv)) {
- ret = lock_vec(dbenv, txnp->txnid, 0, &request, 1, NULL);
- if (ret != 0 && (ret != DB_LOCK_DEADLOCK || is_commit)) {
- __db_err(dbenv, "%s: release locks failed %s",
- is_commit ? "txn_commit" : "txn_abort",
- db_strerror(ret));
- __db_panic(dbenv, ret);
- }
- }
+ /*
+ * __txn_end cannot return an simple error, we MUST return
+ * success/failure from commit or abort, ignoring any internal
+ * errors. So, we panic if something goes wrong. We can't
+ * deadlock here because we're not acquiring any new locks,
+ * so DB_LOCK_DEADLOCK is just as fatal as any other error.
+ */
+ if (LOCKING_ON(dbenv) && (ret = dbenv->lock_vec(
+ dbenv, txnp->txnid, DB_LOCK_FREE_LOCKER, &request, 1, NULL)) != 0)
+ return (__db_panic(dbenv, ret));
/* End the transaction. */
R_LOCK(dbenv, &mgr->reginfo);
tp = (TXN_DETAIL *)R_ADDR(&mgr->reginfo, txnp->off);
SH_TAILQ_REMOVE(&region->active_txn, tp, links, __txn_detail);
+ if (F_ISSET(tp, TXN_RESTORED)) {
+ region->stat.st_nrestores--;
+ do_closefiles = region->stat.st_nrestores == 0;
+ }
+
__db_shalloc_free(mgr->reginfo.addr, tp);
if (is_commit)
- region->ncommits++;
+ region->stat.st_ncommits++;
else
- region->naborts++;
- --region->nactive;
+ region->stat.st_naborts++;
+ --region->stat.st_nactive;
R_UNLOCK(dbenv, &mgr->reginfo);
/*
- * The transaction cannot get more locks, remove its locker info.
+ * The transaction cannot get more locks, remove its locker info,
+ * if any.
*/
- if (LOCKING_ON(dbenv))
- __lock_freefamilylocker(dbenv->lk_handle, txnp->txnid);
+ if (LOCKING_ON(dbenv) && (ret =
+ __lock_freefamilylocker(dbenv->lk_handle, txnp->txnid)) != 0)
+ return (__db_panic(dbenv, ret));
if (txnp->parent != NULL)
TAILQ_REMOVE(&txnp->parent->kids, txnp, klinks);
@@ -588,9 +975,16 @@ __txn_end(txnp, is_commit)
TAILQ_REMOVE(&mgr->txn_chain, txnp, links);
MUTEX_THREAD_UNLOCK(dbenv, mgr->mutexp);
- __os_free(txnp, sizeof(*txnp));
+ __os_free(dbenv, txnp);
}
+ if (do_closefiles) {
+ F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ (void)__dbreg_close_files(dbenv);
+ F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ mgr->n_discards = 0;
+ (void)dbenv->txn_checkpoint(dbenv, 0, 0, DB_FORCE);
+ }
return (0);
}
@@ -605,16 +999,19 @@ __txn_undo(txnp)
{
DBT rdbt;
DB_ENV *dbenv;
+ DB_LOGC *logc;
DB_LSN key_lsn;
+ DB_TXN *ptxn;
DB_TXNMGR *mgr;
+ int ret, t_ret;
void *txnlist;
- int ret, threaded;
mgr = txnp->mgrp;
dbenv = mgr->dbenv;
+ logc = NULL;
txnlist = NULL;
- if (!LOGGING_ON(dbenv))
+ if (!DBENV_LOGGING(dbenv))
return (0);
/*
@@ -623,53 +1020,66 @@ __txn_undo(txnp)
* allocation here and use DB_DBT_USERMEM.
*/
memset(&rdbt, 0, sizeof(rdbt));
- threaded = F_ISSET(dbenv, DB_ENV_THREAD) ? 1 : 0;
- if (threaded)
- F_SET(&rdbt, DB_DBT_MALLOC);
key_lsn = txnp->last_lsn;
- /* Allocate a transaction list for children or aborted page creates. */
- if ((ret = __db_txnlist_init(dbenv, &txnlist)) != 0)
+ /*
+ * Allocate a txnlist for children and aborted page allocs.
+ * We need to associate the list with the maximal parent
+ * so that aborted pages are recovered when that transaction
+ * is commited or aborted.
+ */
+ for (ptxn = txnp->parent; ptxn != NULL && ptxn->parent != NULL;)
+ ptxn = ptxn->parent;
+
+ if (ptxn != NULL && ptxn->txn_list != NULL)
+ txnlist = ptxn->txn_list;
+ else if (txnp->txn_list != NULL)
+ txnlist = txnp->txn_list;
+ else if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txnlist)) != 0)
return (ret);
+ else if (ptxn != NULL)
+ ptxn->txn_list = txnlist;
if (F_ISSET(txnp, TXN_CHILDCOMMIT) &&
- (ret = __db_txnlist_lsninit(dbenv,
- txnlist, &txnp->last_lsn)) != 0)
+ (ret = __db_txnlist_lsninit(dbenv, txnlist, &txnp->last_lsn)) != 0)
return (ret);
- for (ret = 0; ret == 0 && !IS_ZERO_LSN(key_lsn);) {
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ goto err;
+ while (ret == 0 && !IS_ZERO_LSN(key_lsn)) {
/*
* The dispatch routine returns the lsn of the record
* before the current one in the key_lsn argument.
*/
- if ((ret = log_get(dbenv, &key_lsn, &rdbt, DB_SET)) == 0) {
- ret = __db_dispatch(dbenv,
- &rdbt, &key_lsn, DB_TXN_ABORT, txnlist);
- if (threaded && rdbt.data != NULL) {
- __os_free(rdbt.data, rdbt.size);
- rdbt.data = NULL;
- }
+ if ((ret = logc->get(logc, &key_lsn, &rdbt, DB_SET)) == 0) {
+ ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+ dbenv->recover_dtab_size, &rdbt, &key_lsn,
+ DB_TXN_ABORT, txnlist);
if (F_ISSET(txnp, TXN_CHILDCOMMIT))
(void)__db_txnlist_lsnadd(dbenv,
txnlist, &key_lsn, 0);
}
- if (ret != 0) {
+ if (ret == DB_SURPRISE_KID) {
+ if ((ret = __db_txnlist_lsninit(
+ dbenv, txnlist, &key_lsn)) == 0)
+ F_SET(txnp, TXN_CHILDCOMMIT);
+ } else if (ret != 0) {
__db_err(txnp->mgrp->dbenv,
- "txn_abort: Log undo failed for LSN: %lu %lu: %s",
+ "DB_TXN->abort: Log undo failed for LSN: %lu %lu: %s",
(u_long)key_lsn.file, (u_long)key_lsn.offset,
db_strerror(ret));
- if (txnlist != NULL)
- __db_txnlist_end(dbenv, txnlist);
- return (ret);
+ goto err;
}
}
- if (txnlist != NULL) {
- __db_do_the_limbo(dbenv, txnlist);
- __db_txnlist_end(dbenv, txnlist);
- }
+ ret = __db_do_the_limbo(dbenv, ptxn, txnp, txnlist);
+err: if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (ptxn == NULL && txnlist != NULL)
+ __db_txnlist_end(dbenv, txnlist);
return (ret);
}
@@ -682,150 +1092,115 @@ __txn_undo(txnp)
* its first LSN. This is the lowest LSN we can checkpoint, since any record
* written after since that point may be involved in a transaction and may
* therefore need to be undone in the case of an abort.
+ *
+ * PUBLIC: int __txn_checkpoint
+ * PUBLIC: __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t));
*/
int
-txn_checkpoint(dbenv, kbytes, minutes, flags)
+__txn_checkpoint(dbenv, kbytes, minutes, flags)
DB_ENV *dbenv;
u_int32_t kbytes, minutes, flags;
{
- DB_LOG *dblp;
- DB_LSN ckp_lsn, sync_lsn, last_ckp;
+ DB_LSN ckp_lsn, last_ckp;
DB_TXNMGR *mgr;
DB_TXNREGION *region;
- LOG *lp;
TXN_DETAIL *txnp;
time_t last_ckp_time, now;
u_int32_t bytes, mbytes;
- int interval, ret;
+ int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_txn_checkpoint(dbenv, kbytes, minutes));
-#endif
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, DB_INIT_TXN);
-
- mgr = dbenv->tx_handle;
- region = mgr->reginfo.primary;
- dblp = dbenv->lg_handle;
- lp = dblp->reginfo.primary;
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->tx_handle, "txn_checkpoint", DB_INIT_TXN);
/*
- * Check if we need to checkpoint.
+ * On a replication client, all transactions are read-only; therefore,
+ * a checkpoint is a null-op.
+ *
+ * We permit txn_checkpoint, instead of just rendering it illegal,
+ * so that an application can just let a checkpoint thread continue
+ * to operate as it gets promoted or demoted between being a
+ * master and a client.
*/
- ZERO_LSN(ckp_lsn);
+ if (F_ISSET(dbenv, DB_ENV_REP_CLIENT))
+ return (0);
- if (LF_ISSET(DB_FORCE))
- goto do_ckp;
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
- R_LOCK(dbenv, &dblp->reginfo);
- mbytes = lp->stat.st_wc_mbytes;
/*
- * We add the current buffer offset so as to count bytes that
- * have not yet been written, but are sitting in the log buffer.
+ * The checkpoint LSN is an LSN such that all transactions begun before
+ * it are complete. Our first guess (corrected below based on the list
+ * of active transactions) is the last-written LSN.
*/
- bytes = lp->stat.st_wc_bytes + lp->b_off;
- ckp_lsn = lp->lsn;
- R_UNLOCK(dbenv, &dblp->reginfo);
-
- /* Don't checkpoint a quiescent database. */
- if (bytes == 0 && mbytes == 0)
- return (0);
+ __log_txn_lsn(dbenv, &ckp_lsn, &mbytes, &bytes);
- if (kbytes != 0 && mbytes * 1024 + bytes / 1024 >= (u_int32_t)kbytes)
- goto do_ckp;
+ if (!LF_ISSET(DB_FORCE)) {
+ /* Don't checkpoint a quiescent database. */
+ if (bytes == 0 && mbytes == 0)
+ return (0);
- if (minutes != 0) {
- (void)time(&now);
+ if (kbytes != 0 &&
+ mbytes * 1024 + bytes / 1024 >= (u_int32_t)kbytes)
+ goto do_ckp;
- R_LOCK(dbenv, &mgr->reginfo);
- last_ckp_time = region->time_ckp;
- R_UNLOCK(dbenv, &mgr->reginfo);
+ if (minutes != 0) {
+ (void)time(&now);
- if (now - last_ckp_time >= (time_t)(minutes * 60))
- goto do_ckp;
- }
+ R_LOCK(dbenv, &mgr->reginfo);
+ last_ckp_time = region->time_ckp;
+ R_UNLOCK(dbenv, &mgr->reginfo);
- /*
- * If we checked time and data and didn't go to checkpoint,
- * we're done.
- */
- if (minutes != 0 || kbytes != 0)
- return (0);
+ if (now - last_ckp_time >= (time_t)(minutes * 60))
+ goto do_ckp;
+ }
-do_ckp:
- if (IS_ZERO_LSN(ckp_lsn)) {
- R_LOCK(dbenv, &dblp->reginfo);
- ckp_lsn = lp->lsn;
- R_UNLOCK(dbenv, &dblp->reginfo);
+ /*
+ * If we checked time and data and didn't go to checkpoint,
+ * we're done.
+ */
+ if (minutes != 0 || kbytes != 0)
+ return (0);
}
- /*
- * We have to find an LSN such that all transactions begun
- * before that LSN are complete.
- */
+do_ckp: /* Look through the active transactions for the lowest begin LSN. */
R_LOCK(dbenv, &mgr->reginfo);
-
- if (IS_ZERO_LSN(region->pending_ckp)) {
- for (txnp =
- SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
- txnp != NULL;
- txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
-
- /*
- * Look through the active transactions for the
- * lowest begin lsn.
- */
- if (!IS_ZERO_LSN(txnp->begin_lsn) &&
- log_compare(&txnp->begin_lsn, &ckp_lsn) < 0)
- ckp_lsn = txnp->begin_lsn;
- }
- region->pending_ckp = ckp_lsn;
- } else
- ckp_lsn = region->pending_ckp;
-
+ for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
+ txnp != NULL;
+ txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail))
+ if (!IS_ZERO_LSN(txnp->begin_lsn) &&
+ log_compare(&txnp->begin_lsn, &ckp_lsn) < 0)
+ ckp_lsn = txnp->begin_lsn;
R_UNLOCK(dbenv, &mgr->reginfo);
+ if (MPOOL_ON(dbenv) && (ret = dbenv->memp_sync(dbenv, NULL)) != 0) {
+ __db_err(dbenv,
+ "txn_checkpoint: failed to flush the buffer cache %s",
+ db_strerror(ret));
+ return (ret);
+ }
+
/*
- * Try three times to sync the mpool buffers up to the specified LSN,
- * sleeping 1, 2 and 4 seconds between attempts.
+ * Because we can't be a replication client here, and because
+ * recovery (somewhat unusually) calls txn_checkpoint and expects
+ * it to write a log message, LOGGING_ON is the correct macro here.
*/
- if (MPOOL_ON(dbenv))
- for (interval = 1;;) {
- /*
- * memp_sync may change the lsn you pass it, so don't
- * pass it the actual ckp_lsn, pass it a local instead.
- */
- sync_lsn = ckp_lsn;
- if ((ret = memp_sync(dbenv, &sync_lsn)) == 0)
- break;
-
- /*
- * ret == DB_INCOMPLETE means there are still buffers
- * to flush, the checkpoint is not complete.
- */
- if (ret == DB_INCOMPLETE) {
- if (interval > 4)
- return (ret);
-
- (void)__os_sleep(dbenv, interval, 0);
- interval *= 2;
- } else {
- __db_err(dbenv,
- "txn_checkpoint: failure in memp_sync %s",
- db_strerror(ret));
- return (ret);
- }
- }
-
if (LOGGING_ON(dbenv)) {
R_LOCK(dbenv, &mgr->reginfo);
last_ckp = region->last_ckp;
- ZERO_LSN(region->pending_ckp);
R_UNLOCK(dbenv, &mgr->reginfo);
- if ((ret = __txn_ckp_log(dbenv,
- NULL, &ckp_lsn, DB_CHECKPOINT, &ckp_lsn,
+ /*
+ * Put out records for the open files before we log
+ * the checkpoint. The records are certain to be at
+ * or after ckp_lsn, but before the checkpoint record
+ * itself, so they're sure to be included if we start
+ * recovery from the ckp_lsn contained in this
+ * checkpoint.
+ */
+ if ((ret = __dbreg_open_files(dbenv)) != 0 ||
+ (ret = __txn_ckp_log(dbenv,
+ NULL, &ckp_lsn, DB_PERMANENT | DB_FLUSH, &ckp_lsn,
&last_ckp, (int32_t)time(NULL))) != 0) {
__db_err(dbenv,
"txn_checkpoint: log failed at LSN [%ld %ld] %s",
@@ -834,15 +1209,41 @@ do_ckp:
return (ret);
}
- R_LOCK(dbenv, &mgr->reginfo);
- region->last_ckp = ckp_lsn;
- (void)time(&region->time_ckp);
- R_UNLOCK(dbenv, &mgr->reginfo);
+ __txn_updateckp(dbenv, &ckp_lsn);
}
return (0);
}
/*
+ * __txn_getckp --
+ * Get the LSN of the last transaction checkpoint.
+ *
+ * PUBLIC: int __txn_getckp __P((DB_ENV *, DB_LSN *));
+ */
+int
+__txn_getckp(dbenv, lsnp)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+{
+ DB_LSN lsn;
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+
+ R_LOCK(dbenv, &mgr->reginfo);
+ lsn = region->last_ckp;
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ if (IS_ZERO_LSN(lsn))
+ return (DB_NOTFOUND);
+
+ *lsnp = lsn;
+ return (0);
+}
+
+/*
* __txn_activekids --
* Return if this transaction has any active children.
*
@@ -858,7 +1259,7 @@ __txn_activekids(dbenv, rectype, txnp)
* On a child commit, we know that there are children (i.e., the
* commiting child at the least. In that case, skip this check.
*/
- if (rectype == DB_txn_child)
+ if (F_ISSET(txnp, TXN_COMPENSATE) || rectype == DB___txn_child)
return (0);
if (TAILQ_FIRST(&txnp->kids) != NULL) {
@@ -867,3 +1268,161 @@ __txn_activekids(dbenv, rectype, txnp)
}
return (0);
}
+
+/*
+ * __txn_force_abort --
+ * Force an abort record into the log if the commit record
+ * failed to get to disk.
+ *
+ * PUBLIC: int __txn_force_abort __P((DB_ENV *, u_int8_t *));
+ */
+int
+__txn_force_abort(dbenv, buffer)
+ DB_ENV *dbenv;
+ u_int8_t *buffer;
+{
+ DB_CIPHER *db_cipher;
+ HDR *hdr;
+ u_int32_t offset, opcode, rec_len, rec_type, sum_len;
+ u_int8_t *bp, *key, chksum[DB_MAC_KEY];
+ size_t hdrsize;
+ int ret;
+
+ db_cipher = dbenv->crypto_handle;
+
+ /*
+ * This routine depends on the layout of HDR and the __txn_regop
+ * record in txn.src. We are passed the beginning of the commit
+ * record in the log buffer and overwrite the commit with an abort
+ * and recalculate the checksum. We may be passed a txn_xa_regop
+ * that is, an XA prepare), there's no need to overwrite that one.
+ */
+ hdr = (HDR *)buffer;
+ memcpy(&rec_type, hdr, sizeof(rec_type));
+ if (rec_type == DB___txn_xa_regop)
+ return (0);
+
+ offset = sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN);
+ rec_len = offset + sizeof(u_int32_t) + sizeof(int32_t);
+ if (CRYPTO_ON(dbenv)) {
+ key = db_cipher->mac_key;
+ hdrsize = HDR_CRYPTO_SZ;
+ sum_len = DB_MAC_KEY;
+ if ((ret = db_cipher->decrypt(dbenv, db_cipher->data,
+ &hdr->iv[0], buffer + hdrsize, rec_len)) != 0)
+ return (__db_panic(dbenv, ret));
+ } else {
+ key = NULL;
+ hdrsize = HDR_NORMAL_SZ;
+ sum_len = sizeof(u_int32_t);
+ }
+ bp = buffer + hdrsize + offset;
+ opcode = TXN_ABORT;
+ memcpy(bp, &opcode, sizeof(opcode));
+
+ if (CRYPTO_ON(dbenv) &&
+ (ret = db_cipher->encrypt(dbenv,
+ db_cipher->data, &hdr->iv[0], buffer + hdrsize, rec_len)) != 0)
+ return (__db_panic(dbenv, ret));
+
+ __db_chksum(buffer + hdrsize, rec_len, key, chksum);
+ memcpy(buffer + SSZ(HDR, chksum), &chksum, sum_len);
+
+ return (0);
+}
+
+/*
+ * __txn_preclose
+ * Before we can close an environment, we need to check if we
+ * were in the midst of taking care of restored transactions. If
+ * so, then we need to close the files that we opened.
+ *
+ * PUBLIC: int __txn_preclose __P((DB_ENV *));
+ */
+int
+__txn_preclose(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+ int do_closefiles, ret;
+
+ mgr = (DB_TXNMGR *)dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+ do_closefiles = 0;
+
+ R_LOCK(dbenv, &mgr->reginfo);
+ if (region != NULL &&
+ region->stat.st_nrestores
+ <= mgr->n_discards && mgr->n_discards != 0)
+ do_closefiles = 1;
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ if (do_closefiles) {
+ /*
+ * Set the DBLOG_RECOVER flag while closing these
+ * files so they do not create additional log records
+ * that will confuse future recoveries.
+ */
+ F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ ret = __dbreg_close_files(dbenv);
+ F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ } else
+ ret = 0;
+
+ return (ret);
+}
+
+/*
+ * __txn_reset --
+ * Reset the last txnid to its minimum value, and log the reset.
+ *
+ * PUBLIC: int __txn_reset __P((DB_ENV *));
+ */
+int
+__txn_reset(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_LSN scrap;
+ DB_TXNREGION *region;
+
+ region = ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary;
+ region->last_txnid = TXN_MINIMUM;
+
+ DB_ASSERT(LOGGING_ON(dbenv));
+ return (__txn_recycle_log(dbenv,
+ NULL, &scrap, 0, TXN_MINIMUM, TXN_MAXIMUM));
+}
+
+/*
+ * __txn_updateckp --
+ * Update the last_ckp field in the transaction region. This happens
+ * at the end of a normal checkpoint and also when a replication client
+ * receives a checkpoint record.
+ *
+ * PUBLIC: void __txn_updateckp __P((DB_ENV *, DB_LSN *));
+ */
+void
+__txn_updateckp(dbenv, lsnp)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+{
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+
+ /*
+ * We want to make sure last_ckp only moves forward; since
+ * we drop locks above and in log_put, it's possible
+ * for two calls to __txn_ckp_log to finish in a different
+ * order from how they were called.
+ */
+ R_LOCK(dbenv, &mgr->reginfo);
+ if (log_compare(&region->last_ckp, lsnp) < 0) {
+ region->last_ckp = *lsnp;
+ (void)time(&region->time_ckp);
+ }
+ R_UNLOCK(dbenv, &mgr->reginfo);
+}
diff --git a/bdb/txn/txn.src b/bdb/txn/txn.src
index b1e131c2bd7..3f69b29e3ff 100644
--- a/bdb/txn/txn.src
+++ b/bdb/txn/txn.src
@@ -1,13 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
- * $Id: txn.src,v 11.10 2001/01/02 00:58:33 margo Exp $
+ * $Id: txn.src,v 11.19 2002/03/27 04:33:15 bostic Exp $
*/
-PREFIX txn
+PREFIX __txn
+DBPRIVATE
INCLUDE #include "db_config.h"
INCLUDE
@@ -15,25 +16,20 @@ INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
-INCLUDE #include <errno.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
-INCLUDE #include "db_page.h"
-INCLUDE #include "db_dispatch.h"
-INCLUDE #include "db_am.h"
-INCLUDE #include "txn.h"
+INCLUDE #include "dbinc/crypto.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_dispatch.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/rep.h"
+INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
- * DEPRECATED in 3.1 to add timestamps.
- */
-DEPRECATED old_regop 6
-ARG opcode u_int32_t lu
-END
-
-/*
* This is the standard log operation for commit.
* Note that we are using an int32_t for the timestamp. This means that
* in 2039 we will need to deprecate this log record and create one that
@@ -44,11 +40,6 @@ ARG opcode u_int32_t lu
ARG timestamp int32_t ld
END
-DEPRECATED old_ckp 7
-POINTER ckp_lsn DB_LSN * lu
-POINTER last_ckp DB_LSN * lu
-END
-
/*
* This is the checkpoint record. It contains the lsn that the checkpoint
* guarantees and a pointer to the last checkpoint so we can walk backwards
@@ -70,20 +61,19 @@ ARG timestamp int32_t ld
END
/*
- * This is the standard log operation for prepare (since right now
- * we only use prepare in an XA environment).
+ * This is the (new) log operation for a child commit. It is
+ * logged as a record in the PARENT. The child field contains
+ * the transaction ID of the child committing and the c_lsn is
+ * the last LSN of the child's log trail.
*/
-DEPRECATED xa_regop_old 8
-ARG opcode u_int32_t lu
-DBT xid DBT s
-ARG formatID int32_t ld
-ARG gtrid u_int32_t u
-ARG bqual u_int32_t u
+BEGIN child 12
+ARG child u_int32_t lx
+POINTER c_lsn DB_LSN * lu
END
+
/*
- * This is the standard log operation for prepare (since right now
- * we only use prepare in an XA environment).
+ * This is the standard log operation for prepare.
*/
BEGIN xa_regop 13
ARG opcode u_int32_t lu
@@ -95,20 +85,9 @@ POINTER begin_lsn DB_LSN * lu
END
/*
- * This is the log operation for a child commit.
- */
-DEPRECATED child_old 9
-ARG opcode u_int32_t lu
-ARG parent u_int32_t lx
-END
-
-/*
- * This is the (new) log operation for a child commit. It is
- * logged as a record in the PARENT. The child field contains
- * the transaction ID of the child committing and the c_lsn is
- * the last LSN of the child's log trail.
+ * Log the fact that we are recycling txnids.
*/
-BEGIN child 12
-ARG child u_int32_t lx
-POINTER c_lsn DB_LSN * lu
+BEGIN recycle 14
+ARG min u_int32_t u
+ARG max u_int32_t u
END
diff --git a/bdb/txn/txn_method.c b/bdb/txn/txn_method.c
new file mode 100644
index 00000000000..60fdf30583e
--- /dev/null
+++ b/bdb/txn/txn_method.c
@@ -0,0 +1,105 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: txn_method.c,v 11.62 2002/05/09 20:09:35 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/txn.h"
+
+#ifdef HAVE_RPC
+#include "dbinc_auto/db_server.h"
+#include "dbinc_auto/rpc_client_ext.h"
+#endif
+
+static int __txn_set_tx_max __P((DB_ENV *, u_int32_t));
+static int __txn_set_tx_timestamp __P((DB_ENV *, time_t *));
+
+/*
+ * __txn_dbenv_create --
+ * Transaction specific initialization of the DB_ENV structure.
+ *
+ * PUBLIC: void __txn_dbenv_create __P((DB_ENV *));
+ */
+void
+__txn_dbenv_create(dbenv)
+ DB_ENV *dbenv;
+{
+ /*
+ * !!!
+ * Our caller has not yet had the opportunity to reset the panic
+ * state or turn off mutex locking, and so we can neither check
+ * the panic state or acquire a mutex in the DB_ENV create path.
+ */
+
+ dbenv->tx_max = DEF_MAX_TXNS;
+
+#ifdef HAVE_RPC
+ if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+ dbenv->set_tx_max = __dbcl_set_tx_max;
+ dbenv->set_tx_timestamp = __dbcl_set_tx_timestamp;
+ dbenv->txn_checkpoint = __dbcl_txn_checkpoint;
+ dbenv->txn_recover = __dbcl_txn_recover;
+ dbenv->txn_stat = __dbcl_txn_stat;
+ dbenv->txn_begin = __dbcl_txn_begin;
+ } else
+#endif
+ {
+ dbenv->set_tx_max = __txn_set_tx_max;
+ dbenv->set_tx_timestamp = __txn_set_tx_timestamp;
+ dbenv->txn_checkpoint = __txn_checkpoint;
+#ifdef CONFIG_TEST
+ dbenv->txn_id_set = __txn_id_set;
+#endif
+ dbenv->txn_recover = __txn_recover;
+ dbenv->txn_stat = __txn_stat;
+ dbenv->txn_begin = __txn_begin;
+ }
+}
+
+/*
+ * __txn_set_tx_max --
+ * Set the size of the transaction table.
+ */
+static int
+__txn_set_tx_max(dbenv, tx_max)
+ DB_ENV *dbenv;
+ u_int32_t tx_max;
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_max");
+
+ dbenv->tx_max = tx_max;
+ return (0);
+}
+
+/*
+ * __txn_set_tx_timestamp --
+ * Set the transaction recovery timestamp.
+ */
+static int
+__txn_set_tx_timestamp(dbenv, timestamp)
+ DB_ENV *dbenv;
+ time_t *timestamp;
+{
+ ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_timestamp");
+
+ dbenv->tx_timestamp = *timestamp;
+ return (0);
+}
diff --git a/bdb/txn/txn_rec.c b/bdb/txn/txn_rec.c
index bed20d98e1e..69af6a1f907 100644
--- a/bdb/txn/txn_rec.c
+++ b/bdb/txn/txn_rec.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
/*
@@ -36,23 +36,20 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: txn_rec.c,v 11.15 2001/01/11 18:19:55 bostic Exp $";
+static const char revid[] = "$Id: txn_rec.c,v 11.41 2002/08/06 04:42:37 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "txn.h"
-#include "db_am.h"
-#include "db_dispatch.h"
-#include "log.h"
-#include "common_ext.h"
-
-static int __txn_restore_txn __P((DB_ENV *, DB_LSN *, __txn_xa_regop_args *));
+#include "dbinc/db_page.h"
+#include "dbinc/txn.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_dispatch.h"
#define IS_XA_TXN(R) (R->xid.size != 0)
@@ -72,6 +69,7 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
db_recops op;
void *info;
{
+ DB_TXNHEAD *headp;
__txn_regop_args *argp;
int ret;
@@ -82,31 +80,62 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
if ((ret = __txn_regop_read(dbenv, dbtp->data, &argp)) != 0)
return (ret);
- if (argp->opcode != TXN_COMMIT) {
- ret = EINVAL;
- goto err;
- }
+ headp = info;
+ /*
+ * We are only ever called during FORWARD_ROLL or BACKWARD_ROLL.
+ * We check for the former explicitly and the last two clauses
+ * apply to the BACKWARD_ROLL case.
+ */
if (op == DB_TXN_FORWARD_ROLL)
- ret = __db_txnlist_remove(info, argp->txnid->txnid);
- else if (dbenv->tx_timestamp == 0 ||
- argp->timestamp <= (int32_t)dbenv->tx_timestamp)
/*
- * We know this is the backward roll case because we
- * are never called during ABORT or OPENFILES.
+ * If this was a 2-phase-commit transaction, then it
+ * might already have been removed from the list, and
+ * that's OK. Ignore the return code from remove.
*/
- ret = __db_txnlist_add(dbenv, info, argp->txnid->txnid, 0);
- else
+ (void)__db_txnlist_remove(dbenv, info, argp->txnid->txnid);
+ else if ((dbenv->tx_timestamp != 0 &&
+ argp->timestamp > (int32_t)dbenv->tx_timestamp) ||
+ (!IS_ZERO_LSN(headp->trunc_lsn) &&
+ log_compare(&headp->trunc_lsn, lsnp) < 0)) {
/*
- * This is commit record, but we failed the timestamp check
- * so we should treat it as an abort and add it to the list
- * as an aborted record.
+ * We failed either the timestamp check or the trunc_lsn check,
+ * so we treat this as an abort even if it was a commit record.
*/
- ret = __db_txnlist_add(dbenv, info, argp->txnid->txnid, 1);
+ ret = __db_txnlist_update(dbenv,
+ info, argp->txnid->txnid, TXN_ABORT, NULL);
+
+ if (ret == TXN_NOTFOUND)
+ ret = __db_txnlist_add(dbenv,
+ info, argp->txnid->txnid, TXN_IGNORE, NULL);
+ else if (ret != TXN_OK)
+ goto err;
+ /* else ret = 0; Not necessary because TXN_OK == 0 */
+ } else {
+ /* This is a normal commit; mark it appropriately. */
+ ret = __db_txnlist_update(dbenv,
+ info, argp->txnid->txnid, argp->opcode, lsnp);
+
+ if (ret == TXN_NOTFOUND)
+ ret = __db_txnlist_add(dbenv,
+ info, argp->txnid->txnid,
+ argp->opcode == TXN_ABORT ?
+ TXN_IGNORE : argp->opcode, lsnp);
+ else if (ret != TXN_OK)
+ goto err;
+ /* else ret = 0; Not necessary because TXN_OK == 0 */
+ }
if (ret == 0)
*lsnp = argp->prev_lsn;
-err: __os_free(argp, 0);
+
+ if (0) {
+err: __db_err(dbenv,
+ "txnid %lx commit record found, already on commit list",
+ argp->txnid->txnid);
+ ret = EINVAL;
+ }
+ __os_free(dbenv, argp);
return (ret);
}
@@ -140,58 +169,50 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
goto err;
}
- ret = __db_txnlist_find(info, argp->txnid->txnid);
+ ret = __db_txnlist_find(dbenv, info, argp->txnid->txnid);
/*
* If we are rolling forward, then an aborted prepare
- * indicates that this is the last record we'll see for
- * this transaction ID and we should remove it from the
+ * indicates that this may the last record we'll see for
+ * this transaction ID, so we should remove it from the
* list.
*/
- if (op == DB_TXN_FORWARD_ROLL && ret == 1)
- ret = __db_txnlist_remove(info, argp->txnid->txnid);
- else if (op == DB_TXN_BACKWARD_ROLL && ret != 0) {
+ if (op == DB_TXN_FORWARD_ROLL) {
+ if ((ret = __db_txnlist_remove(dbenv,
+ info, argp->txnid->txnid)) != TXN_OK)
+ goto txn_err;
+ } else if (op == DB_TXN_BACKWARD_ROLL && ret == TXN_PREPARE) {
/*
* On the backward pass, we have three possibilities:
* 1. The transaction is already committed, no-op.
- * 2. The transaction is not committed and we are XA, treat
- * like commited and roll forward so that can be committed
- * or aborted late.
- * 3. The transaction is not committed and we are not XA
- * mark the transaction as aborted.
- *
- * Cases 2 and 3 are handled here.
+ * 2. The transaction is already aborted, no-op.
+ * 3. The transaction is neither committed nor aborted.
+ * Treat this like a commit and roll forward so that
+ * the transaction can be resurrected in the region.
+ * We handle case 3 here; cases 1 and 2 are the final clause
+ * below.
+ * This is prepared, but not yet committed transaction. We
+ * need to add it to the transaction list, so that it gets
+ * rolled forward. We also have to add it to the region's
+ * internal state so it can be properly aborted or committed
+ * after recovery (see txn_recover).
*/
-
- /*
- * Should never have seen this transaction unless it was
- * commited.
- */
- DB_ASSERT(ret == DB_NOTFOUND);
-
- if (IS_XA_TXN(argp)) {
- /*
- * This is an XA prepared, but not yet committed
- * transaction. We need to add it to the
- * transaction list, so that it gets rolled
- * forward. We also have to add it to the region's
- * internal state so it can be properly aborted
- * or recovered.
- */
- if ((ret = __db_txnlist_add(dbenv,
- info, argp->txnid->txnid, 0)) == 0)
- ret = __txn_restore_txn(dbenv, lsnp, argp);
- } else
- ret = __db_txnlist_add(dbenv,
- info, argp->txnid->txnid, 1);
+ if ((ret = __db_txnlist_remove(dbenv,
+ info, argp->txnid->txnid)) != TXN_OK) {
+txn_err: __db_err(dbenv,
+ "Transaction not in list %x", argp->txnid->txnid);
+ ret = DB_NOTFOUND;
+ } else if ((ret = __db_txnlist_add(dbenv,
+ info, argp->txnid->txnid, TXN_COMMIT, lsnp)) == 0)
+ ret = __txn_restore_txn(dbenv, lsnp, argp);
} else
ret = 0;
if (ret == 0)
*lsnp = argp->prev_lsn;
-err: __os_free(argp, 0);
+err: __os_free(dbenv, argp);
return (ret);
}
@@ -219,18 +240,11 @@ __txn_ckp_recover(dbenv, dbtp, lsnp, op, info)
if ((ret = __txn_ckp_read(dbenv, dbtp->data, &argp)) != 0)
return (ret);
- /*
- * Check for 'restart' checkpoint record. This occurs when the
- * checkpoint lsn is equal to the lsn of the checkpoint record
- * and means that we could set the transaction ID back to 1, so
- * that we don't exhaust the transaction ID name space.
- */
- if (argp->ckp_lsn.file == lsnp->file &&
- argp->ckp_lsn.offset == lsnp->offset)
- __db_txnlist_gen(info, DB_REDO(op) ? -1 : 1);
+ if (op == DB_TXN_BACKWARD_ROLL)
+ __db_txnlist_ckp(dbenv, info, lsnp);
*lsnp = argp->last_ckp;
- __os_free(argp, 0);
+ __os_free(dbenv, argp);
return (DB_TXN_CKP);
}
@@ -250,7 +264,7 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
void *info;
{
__txn_child_args *argp;
- int ret;
+ int c_stat, p_stat, ret;
#ifdef DEBUG_RECOVER
(void)__txn_child_print(dbenv, dbtp, lsnp, op, info);
@@ -272,17 +286,54 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
ret = __db_txnlist_lsnadd(dbenv,
info, &argp->c_lsn, TXNLIST_NEW);
} else if (op == DB_TXN_BACKWARD_ROLL) {
- if (__db_txnlist_find(info, argp->txnid->txnid) == 0)
- ret = __db_txnlist_add(dbenv, info, argp->child, 0);
- else
- ret = __db_txnlist_add(dbenv, info, argp->child, 1);
- } else
- ret = __db_txnlist_remove(info, argp->child);
+ /* Child might exist -- look for it. */
+ c_stat = __db_txnlist_find(dbenv, info, argp->child);
+ p_stat = __db_txnlist_find(dbenv, info, argp->txnid->txnid);
+
+ if (c_stat == TXN_EXPECTED) {
+ /*
+ * The open after this create succeeded. If the
+ * parent succeeded, we don't want to redo; if the
+ * parent aborted, we do want to undo.
+ */
+ ret = __db_txnlist_update(dbenv,
+ info, argp->child,
+ p_stat == TXN_COMMIT ? TXN_IGNORE : TXN_ABORT,
+ NULL);
+ if (ret > 0)
+ ret = 0;
+ } else if (c_stat == TXN_UNEXPECTED) {
+ /*
+ * The open after this create failed. If the parent
+ * is rolling forward, we need to roll forward. If
+ * the parent failed, then we do not want to abort
+ * (because the file may not be the one in which we
+ * are interested).
+ */
+ ret = __db_txnlist_update(dbenv, info, argp->child,
+ p_stat == TXN_COMMIT ? TXN_COMMIT : TXN_IGNORE,
+ NULL);
+ if (ret > 0)
+ ret = 0;
+ } else if (c_stat != TXN_IGNORE) {
+ ret = __db_txnlist_add(dbenv, info, argp->child,
+ p_stat == TXN_COMMIT ? TXN_COMMIT : TXN_ABORT,
+ NULL);
+ }
+ } else {
+ /* Forward Roll */
+ if ((ret =
+ __db_txnlist_remove(dbenv, info, argp->child)) != TXN_OK) {
+ __db_err(dbenv,
+ "Transaction not in list %x", argp->txnid->txnid);
+ ret = DB_NOTFOUND;
+ }
+ }
if (ret == 0)
*lsnp = argp->prev_lsn;
- __os_free(argp, 0);
+ __os_free(dbenv, argp);
return (ret);
}
@@ -291,13 +342,16 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
* __txn_restore_txn --
* Using only during XA recovery. If we find any transactions that are
* prepared, but not yet committed, then we need to restore the transaction's
- * state into the shared region, because the TM is going to issue a txn_abort
- * or txn_commit and we need to respond correctly.
+ * state into the shared region, because the TM is going to issue an abort
+ * or commit and we need to respond correctly.
*
* lsnp is the LSN of the returned LSN
* argp is the perpare record (in an appropriate structure)
+ *
+ * PUBLIC: int __txn_restore_txn __P((DB_ENV *,
+ * PUBLIC: DB_LSN *, __txn_xa_regop_args *));
*/
-static int
+int
__txn_restore_txn(dbenv, lsnp, argp)
DB_ENV *dbenv;
DB_LSN *lsnp;
@@ -317,8 +371,10 @@ __txn_restore_txn(dbenv, lsnp, argp)
/* Allocate a new transaction detail structure. */
if ((ret =
- __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0)
+ __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {
+ R_UNLOCK(dbenv, &mgr->reginfo);
return (ret);
+ }
/* Place transaction on active transaction list. */
SH_TAILQ_INSERT_HEAD(&region->active_txn, td, links, __txn_detail);
@@ -333,7 +389,48 @@ __txn_restore_txn(dbenv, lsnp, argp)
td->bqual = argp->bqual;
td->gtrid = argp->gtrid;
td->format = argp->formatID;
+ td->flags = 0;
+ F_SET(td, TXN_RESTORED);
+ region->stat.st_nrestores++;
+ region->stat.st_nactive++;
+ if (region->stat.st_nactive > region->stat.st_maxnactive)
+ region->stat.st_maxnactive = region->stat.st_nactive;
R_UNLOCK(dbenv, &mgr->reginfo);
return (0);
}
+
+/*
+ * __txn_recycle_recover --
+ * Recovery function for recycle.
+ *
+ * PUBLIC: int __txn_recycle_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__txn_recycle_recover(dbenv, dbtp, lsnp, op, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __txn_recycle_args *argp;
+ int ret;
+
+#ifdef DEBUG_RECOVER
+ (void)__txn_child_print(dbenv, dbtp, lsnp, op, info);
+#endif
+ if ((ret = __txn_recycle_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+
+ COMPQUIET(lsnp, NULL);
+
+ if ((ret = __db_txnlist_gen(dbenv, info,
+ DB_UNDO(op) ? -1 : 1, argp->min, argp->max)) != 0)
+ return (ret);
+
+ __os_free(dbenv, argp);
+
+ return (0);
+}
diff --git a/bdb/txn/txn_recover.c b/bdb/txn/txn_recover.c
new file mode 100644
index 00000000000..732a82e5030
--- /dev/null
+++ b/bdb/txn/txn_recover.c
@@ -0,0 +1,306 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: txn_recover.c,v 1.36 2002/08/19 16:59:15 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/log.h"
+#include "dbinc_auto/db_auto.h"
+#include "dbinc_auto/crdel_auto.h"
+#include "dbinc_auto/db_ext.h"
+
+/*
+ * __txn_continue
+ * Fill in the fields of the local transaction structure given
+ * the detail transaction structure.
+ *
+ * XXX
+ * I'm not sure that we work correctly with nested txns.
+ *
+ * PUBLIC: void __txn_continue __P((DB_ENV *, DB_TXN *, TXN_DETAIL *, size_t));
+ */
+void
+__txn_continue(env, txnp, td, off)
+ DB_ENV *env;
+ DB_TXN *txnp;
+ TXN_DETAIL *td;
+ size_t off;
+{
+ txnp->mgrp = env->tx_handle;
+ txnp->parent = NULL;
+ txnp->last_lsn = td->last_lsn;
+ txnp->txnid = td->txnid;
+ txnp->off = (roff_t)off;
+
+ txnp->abort = __txn_abort;
+ txnp->commit = __txn_commit;
+ txnp->discard = __txn_discard;
+ txnp->id = __txn_id;
+ txnp->prepare = __txn_prepare;
+
+ txnp->flags = 0;
+}
+
+/*
+ * __txn_map_gid
+ * Return the txn that corresponds to this global ID.
+ *
+ * PUBLIC: int __txn_map_gid __P((DB_ENV *,
+ * PUBLIC: u_int8_t *, TXN_DETAIL **, size_t *));
+ */
+int
+__txn_map_gid(dbenv, gid, tdp, offp)
+ DB_ENV *dbenv;
+ u_int8_t *gid;
+ TXN_DETAIL **tdp;
+ size_t *offp;
+{
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *tmr;
+
+ mgr = dbenv->tx_handle;
+ tmr = mgr->reginfo.primary;
+
+ /*
+ * Search the internal active transaction table to find the
+ * matching xid. If this is a performance hit, then we
+ * can create a hash table, but I doubt it's worth it.
+ */
+ R_LOCK(dbenv, &mgr->reginfo);
+ for (*tdp = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail);
+ *tdp != NULL;
+ *tdp = SH_TAILQ_NEXT(*tdp, links, __txn_detail))
+ if (memcmp(gid, (*tdp)->xid, sizeof((*tdp)->xid)) == 0)
+ break;
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ if (*tdp == NULL)
+ return (EINVAL);
+
+ *offp = R_OFFSET(&mgr->reginfo, *tdp);
+ return (0);
+}
+
+/*
+ * __txn_recover --
+ * Public interface to retrieve the list of prepared, but not yet
+ * commited transactions. See __txn_get_prepared for details. This
+ * function and __db_xa_recover both wrap that one.
+ *
+ * PUBLIC: int __txn_recover
+ * PUBLIC: __P((DB_ENV *, DB_PREPLIST *, long, long *, u_int32_t));
+ */
+int
+__txn_recover(dbenv, preplist, count, retp, flags)
+ DB_ENV *dbenv;
+ DB_PREPLIST *preplist;
+ long count, *retp;
+ u_int32_t flags;
+{
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(
+ dbenv, dbenv->tx_handle, "txn_recover", DB_INIT_TXN);
+
+ if (F_ISSET((DB_TXNREGION *)
+ ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary,
+ TXN_IN_RECOVERY)) {
+ __db_err(dbenv, "operation not permitted while in recovery");
+ return (EINVAL);
+ }
+ return (__txn_get_prepared(dbenv, NULL, preplist, count, retp, flags));
+}
+
+/*
+ * __txn_get_prepared --
+ * Returns a list of prepared (and for XA, heuristically completed)
+ * transactions (less than or equal to the count parameter). One of
+ * xids or txns must be set to point to an array of the appropriate type.
+ * The count parameter indicates the number of entries in the xids and/or
+ * txns array. The retp parameter will be set to indicate the number of
+ * entries returned in the xids/txns array. Flags indicates the operation,
+ * one of DB_FIRST or DB_NEXT.
+ *
+ * PUBLIC: int __txn_get_prepared __P((DB_ENV *,
+ * PUBLIC: XID *, DB_PREPLIST *, long, long *, u_int32_t));
+ */
+int
+__txn_get_prepared(dbenv, xids, txns, count, retp, flags)
+ DB_ENV *dbenv;
+ XID *xids;
+ DB_PREPLIST *txns;
+ long count; /* This is long for XA compatibility. */
+ long *retp;
+ u_int32_t flags;
+{
+ DBT data;
+ DB_LOGC *logc;
+ DB_LSN min, open_lsn;
+ DB_PREPLIST *prepp;
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *tmr;
+ TXN_DETAIL *td;
+ XID *xidp;
+ __txn_ckp_args *ckp_args;
+ long i;
+ int nrestores, open_files, ret, t_ret;
+ void *txninfo;
+
+ *retp = 0;
+
+ logc = NULL;
+ MAX_LSN(min);
+ prepp = txns;
+ xidp = xids;
+ nrestores = ret = 0;
+ open_files = 1;
+
+ /*
+ * If we are starting a scan, then we traverse the active transaction
+ * list once making sure that all transactions are marked as not having
+ * been collected. Then on each pass, we mark the ones we collected
+ * so that if we cannot collect them all at once, we can finish up
+ * next time with a continue.
+ */
+
+ mgr = dbenv->tx_handle;
+ tmr = mgr->reginfo.primary;
+
+ /*
+ * During this pass we need to figure out if we are going to need
+ * to open files. We need to open files if we've never collected
+ * before (in which case, none of the COLLECTED bits will be set)
+ * and the ones that we are collecting are restored (if they aren't
+ * restored, then we never crashed; just the main server did).
+ */
+ R_LOCK(dbenv, &mgr->reginfo);
+ if (flags == DB_FIRST) {
+ for (td = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail);
+ td != NULL;
+ td = SH_TAILQ_NEXT(td, links, __txn_detail)) {
+ if (F_ISSET(td, TXN_RESTORED))
+ nrestores++;
+ if (F_ISSET(td, TXN_COLLECTED))
+ open_files = 0;
+ F_CLR(td, TXN_COLLECTED);
+ }
+ mgr->n_discards = 0;
+ } else
+ open_files = 0;
+
+ /* Now begin collecting active transactions. */
+ for (td = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail);
+ td != NULL && *retp < count;
+ td = SH_TAILQ_NEXT(td, links, __txn_detail)) {
+ if (td->status != TXN_PREPARED || F_ISSET(td, TXN_COLLECTED))
+ continue;
+
+ if (xids != NULL) {
+ xidp->formatID = td->format;
+ xidp->gtrid_length = td->gtrid;
+ xidp->bqual_length = td->bqual;
+ memcpy(xidp->data, td->xid, sizeof(td->xid));
+ xidp++;
+ }
+
+ if (txns != NULL) {
+ if ((ret = __os_calloc(dbenv,
+ 1, sizeof(DB_TXN), &prepp->txn)) != 0)
+ goto err;
+ __txn_continue(dbenv,
+ prepp->txn, td, R_OFFSET(&mgr->reginfo, td));
+ F_SET(prepp->txn, TXN_MALLOC);
+ memcpy(prepp->gid, td->xid, sizeof(td->xid));
+ prepp++;
+ }
+
+ if (log_compare(&td->begin_lsn, &min) < 0)
+ min = td->begin_lsn;
+
+ (*retp)++;
+ F_SET(td, TXN_COLLECTED);
+ }
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ /*
+ * Now link all the transactions into the transaction manager's list.
+ */
+ if (txns != NULL) {
+ MUTEX_THREAD_LOCK(dbenv, mgr->mutexp);
+ for (i = 0; i < *retp; i++)
+ TAILQ_INSERT_TAIL(&mgr->txn_chain, txns[i].txn, links);
+ MUTEX_THREAD_UNLOCK(dbenv, mgr->mutexp);
+ }
+
+ if (open_files && nrestores && *retp != 0 && !IS_MAX_LSN(min)) {
+ /*
+ * Figure out the last checkpoint before the smallest
+ * start_lsn in the region.
+ */
+ F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ goto err;
+
+ memset(&data, 0, sizeof(data));
+ if ((ret = __txn_getckp(dbenv, &open_lsn)) == 0)
+ while (!IS_ZERO_LSN(open_lsn) && (ret =
+ logc->get(logc, &open_lsn, &data, DB_SET)) == 0 &&
+ log_compare(&min, &open_lsn) < 0) {
+ /* Format the log record. */
+ if ((ret = __txn_ckp_read(dbenv,
+ data.data, &ckp_args)) != 0) {
+ __db_err(dbenv,
+ "Invalid checkpoint record at [%lu][%lu]",
+ (u_long)open_lsn.file,
+ (u_long)open_lsn.offset);
+ goto err;
+ }
+ open_lsn = ckp_args->last_ckp;
+ __os_free(dbenv, ckp_args);
+ }
+
+ /*
+ * There are three ways by which we may have gotten here.
+ * - We got a DB_NOTFOUND -- we need to read the first
+ * log record.
+ * - We found a checkpoint before min. We're done.
+ * - We found a checkpoint after min who's last_ckp is 0. We
+ * need to start at the beginning of the log.
+ */
+ if ((ret == DB_NOTFOUND || IS_ZERO_LSN(open_lsn)) &&
+ (ret = logc->get(logc, &open_lsn, &data, DB_FIRST)) != 0) {
+ __db_err(dbenv, "No log records");
+ goto err;
+ }
+
+ if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
+ goto err;
+ ret = __env_openfiles(dbenv, logc,
+ txninfo, &data, &open_lsn, NULL, 0, 0);
+ if (txninfo != NULL)
+ __db_txnlist_end(dbenv, txninfo);
+ }
+
+err: F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+
+ if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ return (ret);
+}
diff --git a/bdb/txn/txn_region.c b/bdb/txn/txn_region.c
index 77ce3d08f89..bf72d4f1d2c 100644
--- a/bdb/txn/txn_region.c
+++ b/bdb/txn/txn_region.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: txn_region.c,v 11.36 2001/01/11 18:19:55 bostic Exp $";
+static const char revid[] = "$Id: txn_region.c,v 11.73 2002/08/06 04:42:37 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -28,98 +28,13 @@ static const char revid[] = "$Id: txn_region.c,v 11.36 2001/01/11 18:19:55 bosti
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
-#include "db_page.h"
-#include "log.h" /* for __log_lastckp */
-#include "txn.h"
-#include "db_am.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+static int __txn_findlastckp __P((DB_ENV *, DB_LSN *));
static int __txn_init __P((DB_ENV *, DB_TXNMGR *));
-static int __txn_set_tx_max __P((DB_ENV *, u_int32_t));
-static int __txn_set_tx_recover __P((DB_ENV *,
- int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
-static int __txn_set_tx_timestamp __P((DB_ENV *, time_t *));
-
-/*
- * __txn_dbenv_create --
- * Transaction specific initialization of the DB_ENV structure.
- *
- * PUBLIC: void __txn_dbenv_create __P((DB_ENV *));
- */
-void
-__txn_dbenv_create(dbenv)
- DB_ENV *dbenv;
-{
- dbenv->tx_max = DEF_MAX_TXNS;
-
- dbenv->set_tx_max = __txn_set_tx_max;
- dbenv->set_tx_recover = __txn_set_tx_recover;
- dbenv->set_tx_timestamp = __txn_set_tx_timestamp;
-
-#ifdef HAVE_RPC
- /*
- * If we have a client, overwrite what we just setup to point to
- * client functions.
- */
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
- dbenv->set_tx_max = __dbcl_set_tx_max;
- dbenv->set_tx_recover = __dbcl_set_tx_recover;
- dbenv->set_tx_timestamp = __dbcl_set_tx_timestamp;
- }
-#endif
-}
-
-/*
- * __txn_set_tx_max --
- * Set the size of the transaction table.
- */
-static int
-__txn_set_tx_max(dbenv, tx_max)
- DB_ENV *dbenv;
- u_int32_t tx_max;
-{
- ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_max");
-
- dbenv->tx_max = tx_max;
- return (0);
-}
-
-/*
- * __txn_set_tx_recover --
- * Set the transaction abort recover function.
- */
-static int
-__txn_set_tx_recover(dbenv, tx_recover)
- DB_ENV *dbenv;
- int (*tx_recover) __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
-{
- dbenv->tx_recover = tx_recover;
- return (0);
-}
-
-/*
- * __txn_set_tx_timestamp --
- * Set the transaction recovery timestamp.
- */
-static int
-__txn_set_tx_timestamp(dbenv, timestamp)
- DB_ENV *dbenv;
- time_t *timestamp;
-{
- ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_timestamp");
-
- dbenv->tx_timestamp = *timestamp;
- return (0);
-}
+static size_t __txn_region_size __P((DB_ENV *));
/*
* __txn_open --
@@ -148,7 +63,7 @@ __txn_open(dbenv)
if (F_ISSET(dbenv, DB_ENV_CREATE))
F_SET(&tmgrp->reginfo, REGION_CREATE_OK);
if ((ret = __db_r_attach(dbenv,
- &tmgrp->reginfo, TXN_REGION_SIZE(dbenv->tx_max))) != 0)
+ &tmgrp->reginfo, __txn_region_size(dbenv))) != 0)
goto err;
/* If we created the region, initialize it. */
@@ -161,14 +76,10 @@ __txn_open(dbenv)
R_ADDR(&tmgrp->reginfo, tmgrp->reginfo.rp->primary);
/* Acquire a mutex to protect the active TXN list. */
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if ((ret = __db_mutex_alloc(
- dbenv, &tmgrp->reginfo, &tmgrp->mutexp)) != 0)
- goto err;
- if ((ret = __db_mutex_init(
- dbenv, tmgrp->mutexp, 0, MUTEX_THREAD)) != 0)
- goto err;
- }
+ if (F_ISSET(dbenv, DB_ENV_THREAD) &&
+ (ret = __db_mutex_setup(dbenv, &tmgrp->reginfo, &tmgrp->mutexp,
+ MUTEX_ALLOC | MUTEX_NO_RLOCK | MUTEX_THREAD)) != 0)
+ goto err;
R_UNLOCK(dbenv, &tmgrp->reginfo);
@@ -184,7 +95,7 @@ err: if (tmgrp->reginfo.addr != NULL) {
}
if (tmgrp->mutexp != NULL)
__db_mutex_free(dbenv, &tmgrp->reginfo, tmgrp->mutexp);
- __os_free(tmgrp, sizeof(*tmgrp));
+ __os_free(dbenv, tmgrp);
return (ret);
}
@@ -200,15 +111,29 @@ __txn_init(dbenv, tmgrp)
DB_LSN last_ckp;
DB_TXNREGION *region;
int ret;
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ u_int8_t *addr;
+#endif
- ZERO_LSN(last_ckp);
/*
- * If possible, fetch the last checkpoint LSN from the log system
- * so that the backwards chain of checkpoints is unbroken when
- * the environment is removed and recreated. [#2865]
+ * Find the last checkpoint in the log.
*/
- if (LOGGING_ON(dbenv) && (ret = __log_lastckp(dbenv, &last_ckp)) != 0)
- return (ret);
+ ZERO_LSN(last_ckp);
+ if (LOGGING_ON(dbenv)) {
+ /*
+ * The log system has already walked through the last
+ * file. Get the LSN of a checkpoint it may have found.
+ */
+ __log_get_cached_ckp_lsn(dbenv, &last_ckp);
+
+ /*
+ * If that didn't work, look backwards from the beginning of
+ * the last log file until we find the last checkpoint.
+ */
+ if (IS_ZERO_LSN(last_ckp) &&
+ (ret = __txn_findlastckp(dbenv, &last_ckp)) != 0)
+ return (ret);
+ }
if ((ret = __db_shalloc(tmgrp->reginfo.addr,
sizeof(DB_TXNREGION), 0, &tmgrp->reginfo.primary)) != 0) {
@@ -223,7 +148,7 @@ __txn_init(dbenv, tmgrp)
region->maxtxns = dbenv->tx_max;
region->last_txnid = TXN_MINIMUM;
- ZERO_LSN(region->pending_ckp);
+ region->cur_maxid = TXN_MAXIMUM;
region->last_ckp = last_ckp;
region->time_ckp = time(NULL);
@@ -233,25 +158,86 @@ __txn_init(dbenv, tmgrp)
*/
region->logtype = 0;
region->locktype = 0;
- region->naborts = 0;
- region->ncommits = 0;
- region->nbegins = 0;
- region->nactive = 0;
- region->maxnactive = 0;
- SH_TAILQ_INIT(&region->active_txn);
+ memset(&region->stat, 0, sizeof(region->stat));
+ region->stat.st_maxtxns = region->maxtxns;
+ SH_TAILQ_INIT(&region->active_txn);
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ /* Allocate room for the txn maintenance info and initialize it. */
+ if ((ret = __db_shalloc(tmgrp->reginfo.addr,
+ sizeof(REGMAINT) + TXN_MAINT_SIZE, 0, &addr)) != 0) {
+ __db_err(dbenv,
+ "Unable to allocate memory for mutex maintenance");
+ return (ret);
+ }
+ __db_maintinit(&tmgrp->reginfo, addr, TXN_MAINT_SIZE);
+ region->maint_off = R_OFFSET(&tmgrp->reginfo, addr);
+#endif
return (0);
}
/*
- * __txn_close --
- * Close a transaction region.
+ * __txn_findlastckp --
+ * Find the last checkpoint in the log, walking backwards from the
+ * beginning of the last log file. (The log system looked through
+ * the last log file when it started up.)
+ */
+static int
+__txn_findlastckp(dbenv, lsnp)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+{
+ DB_LOGC *logc;
+ DB_LSN lsn;
+ DBT dbt;
+ int ret, t_ret;
+ u_int32_t rectype;
+
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+
+ /* Get the last LSN. */
+ memset(&dbt, 0, sizeof(dbt));
+ if ((ret = logc->get(logc, &lsn, &dbt, DB_LAST)) != 0)
+ goto err;
+
+ /*
+ * Twiddle the last LSN so it points to the beginning of the last
+ * file; we know there's no checkpoint after that, since the log
+ * system already looked there.
+ */
+ lsn.offset = 0;
+
+ /* Read backwards, looking for checkpoints. */
+ while ((ret = logc->get(logc, &lsn, &dbt, DB_PREV)) == 0) {
+ if (dbt.size < sizeof(u_int32_t))
+ continue;
+ memcpy(&rectype, dbt.data, sizeof(u_int32_t));
+ if (rectype == DB___txn_ckp) {
+ *lsnp = lsn;
+ break;
+ }
+ }
+
+err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ /*
+ * Not finding a checkpoint is not an error; there may not exist
+ * one in the log.
+ */
+ return ((ret == 0 || ret == DB_NOTFOUND) ? 0 : ret);
+}
+
+/*
+ * __txn_dbenv_refresh --
+ * Clean up after the transaction system on a close or failed open.
+ * Called only from __dbenv_refresh. (Formerly called __txn_close.)
*
- * PUBLIC: int __txn_close __P((DB_ENV *));
+ * PUBLIC: int __txn_dbenv_refresh __P((DB_ENV *));
*/
int
-__txn_close(dbenv)
+__txn_dbenv_refresh(dbenv)
DB_ENV *dbenv;
{
DB_TXN *txnp;
@@ -274,22 +260,23 @@ __txn_close(dbenv)
*/
if (TAILQ_FIRST(&tmgrp->txn_chain) != NULL) {
__db_err(dbenv,
- "Error: closing the transaction region with active transactions\n");
+ "Error: closing the transaction region with active transactions");
ret = EINVAL;
while ((txnp = TAILQ_FIRST(&tmgrp->txn_chain)) != NULL) {
txnid = txnp->txnid;
- if ((t_ret = txn_abort(txnp)) != 0) {
+ if ((t_ret = txnp->abort(txnp)) != 0) {
__db_err(dbenv,
- "Unable to abort transaction 0x%x: %s\n",
+ "Unable to abort transaction 0x%x: %s",
txnid, db_strerror(t_ret));
ret = __db_panic(dbenv, t_ret);
+ break;
}
}
}
/* Flush the log. */
if (LOGGING_ON(dbenv) &&
- (t_ret = log_flush(dbenv, NULL)) != 0 && ret == 0)
+ (t_ret = dbenv->log_flush(dbenv, NULL)) != 0 && ret == 0)
ret = t_ret;
/* Discard the per-thread lock. */
@@ -300,94 +287,88 @@ __txn_close(dbenv)
if ((t_ret = __db_r_detach(dbenv, &tmgrp->reginfo, 0)) != 0 && ret == 0)
ret = t_ret;
- __os_free(tmgrp, sizeof(*tmgrp));
+ __os_free(dbenv, tmgrp);
dbenv->tx_handle = NULL;
return (ret);
}
+/*
+ * __txn_region_size --
+ * Return the amount of space needed for the txn region. Make the
+ * region large enough to hold txn_max transaction detail structures
+ * plus some space to hold thread handles and the beginning of the
+ * shalloc region and anything we need for mutex system resource
+ * recording.
+ */
+static size_t
+__txn_region_size(dbenv)
+ DB_ENV *dbenv;
+{
+ size_t s;
+
+ s = sizeof(DB_TXNREGION) +
+ dbenv->tx_max * sizeof(TXN_DETAIL) + 10 * 1024;
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ if (F_ISSET(dbenv, DB_ENV_THREAD))
+ s += sizeof(REGMAINT) + TXN_MAINT_SIZE;
+#endif
+ return (s);
+}
+
+/*
+ * __txn_region_destroy
+ * Destroy any region maintenance info.
+ *
+ * PUBLIC: void __txn_region_destroy __P((DB_ENV *, REGINFO *));
+ */
+void
+__txn_region_destroy(dbenv, infop)
+ DB_ENV *dbenv;
+ REGINFO *infop;
+{
+ __db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
+ ((DB_TXNREGION *)R_ADDR(infop, infop->rp->primary))->maint_off));
+
+ COMPQUIET(dbenv, NULL);
+ COMPQUIET(infop, NULL);
+}
+
+#ifdef CONFIG_TEST
+/*
+ * __txn_id_set --
+ * Set the current transaction ID and current maximum unused ID (for
+ * testing purposes only).
+ *
+ * PUBLIC: int __txn_id_set __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
int
-txn_stat(dbenv, statp, db_malloc)
+__txn_id_set(dbenv, cur_txnid, max_txnid)
DB_ENV *dbenv;
- DB_TXN_STAT **statp;
- void *(*db_malloc) __P((size_t));
+ u_int32_t cur_txnid, max_txnid;
{
DB_TXNMGR *mgr;
DB_TXNREGION *region;
- DB_TXN_STAT *stats;
- TXN_DETAIL *txnp;
- size_t nbytes;
- u_int32_t nactive, ndx;
- int ret, slop;
-
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_txn_stat(dbenv, statp, db_malloc));
-#endif
-
- PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, DB_INIT_TXN);
+ int ret;
- *statp = NULL;
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_id_set", DB_INIT_TXN);
- slop = 200;
mgr = dbenv->tx_handle;
region = mgr->reginfo.primary;
+ region->last_txnid = cur_txnid;
+ region->cur_maxid = max_txnid;
-retry: R_LOCK(dbenv, &mgr->reginfo);
- nactive = region->nactive;
- R_UNLOCK(dbenv, &mgr->reginfo);
-
- /*
- * Allocate extra active structures to handle any transactions that
- * are created while we have the region unlocked.
- */
- nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * (nactive + slop);
- if ((ret = __os_malloc(dbenv, nbytes, db_malloc, &stats)) != 0)
- return (ret);
-
- R_LOCK(dbenv, &mgr->reginfo);
- stats->st_last_txnid = region->last_txnid;
- stats->st_last_ckp = region->last_ckp;
- stats->st_maxtxns = region->maxtxns;
- stats->st_naborts = region->naborts;
- stats->st_nbegins = region->nbegins;
- stats->st_ncommits = region->ncommits;
- stats->st_pending_ckp = region->pending_ckp;
- stats->st_time_ckp = region->time_ckp;
- stats->st_nactive = region->nactive;
- if (stats->st_nactive > nactive + 200) {
- R_UNLOCK(dbenv, &mgr->reginfo);
- slop *= 2;
- goto retry;
+ ret = 0;
+ if (cur_txnid < TXN_MINIMUM) {
+ __db_err(dbenv, "Current ID value %lu below minimum",
+ cur_txnid);
+ ret = EINVAL;
}
- stats->st_maxnactive = region->maxnactive;
- stats->st_txnarray = (DB_TXN_ACTIVE *)&stats[1];
-
- ndx = 0;
- for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
- txnp != NULL;
- txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
- stats->st_txnarray[ndx].txnid = txnp->txnid;
- if (txnp->parent == INVALID_ROFF)
- stats->st_txnarray[ndx].parentid = TXN_INVALID_ID;
- else
- stats->st_txnarray[ndx].parentid =
- ((TXN_DETAIL *)R_ADDR(&mgr->reginfo,
- txnp->parent))->txnid;
- stats->st_txnarray[ndx].lsn = txnp->begin_lsn;
- ndx++;
-
- if (ndx >= stats->st_nactive)
- break;
+ if (max_txnid < TXN_MINIMUM) {
+ __db_err(dbenv, "Maximum ID value %lu below minimum",
+ max_txnid);
+ ret = EINVAL;
}
-
- stats->st_region_wait = mgr->reginfo.rp->mutex.mutex_set_wait;
- stats->st_region_nowait = mgr->reginfo.rp->mutex.mutex_set_nowait;
- stats->st_regsize = mgr->reginfo.rp->size;
-
- R_UNLOCK(dbenv, &mgr->reginfo);
-
- *statp = stats;
- return (0);
+ return (ret);
}
+#endif
diff --git a/bdb/txn/txn_stat.c b/bdb/txn/txn_stat.c
new file mode 100644
index 00000000000..f7d84e8f4c6
--- /dev/null
+++ b/bdb/txn/txn_stat.c
@@ -0,0 +1,102 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: txn_stat.c,v 11.15 2002/04/26 23:00:36 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/txn.h"
+
+/*
+ * __txn_stat --
+ *
+ * PUBLIC: int __txn_stat __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+ */
+int
+__txn_stat(dbenv, statp, flags)
+ DB_ENV *dbenv;
+ DB_TXN_STAT **statp;
+ u_int32_t flags;
+{
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+ DB_TXN_STAT *stats;
+ TXN_DETAIL *txnp;
+ size_t nbytes;
+ u_int32_t ndx;
+ int ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_stat", DB_INIT_TXN);
+
+ *statp = NULL;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->txn_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
+
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+
+ /*
+ * Allocate for the maximum active transactions -- the DB_TXN_ACTIVE
+ * struct is small and the maximum number of active transactions is
+ * not going to be that large. Don't have to lock anything to look
+ * at the region's maximum active transactions value, it's read-only
+ * and never changes after the region is created.
+ */
+ nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * region->maxtxns;
+ if ((ret = __os_umalloc(dbenv, nbytes, &stats)) != 0)
+ return (ret);
+
+ R_LOCK(dbenv, &mgr->reginfo);
+ memcpy(stats, &region->stat, sizeof(*stats));
+ stats->st_last_txnid = region->last_txnid;
+ stats->st_last_ckp = region->last_ckp;
+ stats->st_time_ckp = region->time_ckp;
+ stats->st_txnarray = (DB_TXN_ACTIVE *)&stats[1];
+
+ ndx = 0;
+ for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
+ txnp != NULL;
+ txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
+ stats->st_txnarray[ndx].txnid = txnp->txnid;
+ if (txnp->parent == INVALID_ROFF)
+ stats->st_txnarray[ndx].parentid = TXN_INVALID;
+ else
+ stats->st_txnarray[ndx].parentid =
+ ((TXN_DETAIL *)R_ADDR(&mgr->reginfo,
+ txnp->parent))->txnid;
+ stats->st_txnarray[ndx].lsn = txnp->begin_lsn;
+ ndx++;
+ }
+
+ stats->st_region_wait = mgr->reginfo.rp->mutex.mutex_set_wait;
+ stats->st_region_nowait = mgr->reginfo.rp->mutex.mutex_set_nowait;
+ stats->st_regsize = mgr->reginfo.rp->size;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ mgr->reginfo.rp->mutex.mutex_set_wait = 0;
+ mgr->reginfo.rp->mutex.mutex_set_nowait = 0;
+ memset(&region->stat, 0, sizeof(region->stat));
+ region->stat.st_maxtxns = region->maxtxns;
+ region->stat.st_maxnactive =
+ region->stat.st_nactive = stats->st_nactive;
+ }
+
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ *statp = stats;
+ return (0);
+}
diff --git a/bdb/txn/txn_util.c b/bdb/txn/txn_util.c
new file mode 100644
index 00000000000..cbfbc419615
--- /dev/null
+++ b/bdb/txn/txn_util.c
@@ -0,0 +1,234 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2002
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char revid[] = "$Id: txn_util.c,v 11.18 2002/08/06 06:25:12 bostic Exp $";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/txn.h"
+
+typedef struct __txn_event TXN_EVENT;
+struct __txn_event {
+ TXN_EVENT_T op;
+ TAILQ_ENTRY(__txn_event) links;
+ union {
+ struct {
+ /* Delayed remove. */
+ char *name;
+ u_int8_t *fileid;
+ } r;
+ struct {
+ /* Lock event. */
+ DB_LOCK lock;
+ u_int32_t locker;
+ DB *dbp;
+ } t;
+ } u;
+};
+
+/*
+ * __txn_remevent --
+ *
+ * Creates a remove event that can be added to the commit list.
+ *
+ * PUBLIC: int __txn_remevent __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, const char *, u_int8_t*));
+ */
+int
+__txn_remevent(dbenv, txn, name, fileid)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ const char *name;
+ u_int8_t *fileid;
+{
+ int ret;
+ TXN_EVENT *e;
+
+ e = NULL;
+ if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
+ return (ret);
+
+ if ((ret = __os_strdup(dbenv, name, &e->u.r.name)) != 0)
+ goto err;
+
+ if (fileid != NULL) {
+ if ((ret = __os_calloc(dbenv,
+ 1, DB_FILE_ID_LEN, &e->u.r.fileid)) != 0)
+ return (ret);
+ memcpy(e->u.r.fileid, fileid, DB_FILE_ID_LEN);
+ }
+
+ e->op = TXN_REMOVE;
+ TAILQ_INSERT_TAIL(&txn->events, e, links);
+
+ return (0);
+
+err: if (e != NULL)
+ __os_free(dbenv, e);
+
+ return (ret);
+}
+
+/*
+ * __txn_lockevent --
+ *
+ * Add a lockevent to the commit-queue. The lock event indicates a locker
+ * trade.
+ *
+ * PUBLIC: int __txn_lockevent __P((DB_ENV *,
+ * PUBLIC: DB_TXN *, DB *, DB_LOCK *, u_int32_t));
+ */
+int
+__txn_lockevent(dbenv, txn, dbp, lock, locker)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB *dbp;
+ DB_LOCK *lock;
+ u_int32_t locker;
+{
+ int ret;
+ TXN_EVENT *e;
+
+ if (!LOCKING_ON(dbenv))
+ return (0);
+
+ e = NULL;
+ if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
+ return (ret);
+
+ e->u.t.locker = locker;
+ e->u.t.lock = *lock;
+ e->u.t.dbp = dbp;
+ e->op = TXN_TRADE;
+ TAILQ_INSERT_TAIL(&txn->events, e, links);
+
+ return (0);
+}
+
+/*
+ * __txn_remlock --
+ * Remove a lock event because the locker is going away. We can remove
+ * by lock (using offset) or by locker_id (or by both).
+ *
+ * PUBLIC: void __txn_remlock __P((DB_ENV *, DB_TXN *, DB_LOCK *, u_int32_t));
+ */
+void
+__txn_remlock(dbenv, txn, lock, locker)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ DB_LOCK *lock;
+ u_int32_t locker;
+{
+ TXN_EVENT *e, *next_e;
+
+ for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {
+ next_e = TAILQ_NEXT(e, links);
+ if ((e->op != TXN_TRADE && e->op != TXN_TRADED) ||
+ (e->u.t.lock.off != lock->off && e->u.t.locker != locker))
+ continue;
+ TAILQ_REMOVE(&txn->events, e, links);
+ __os_free(dbenv, e);
+ }
+
+ return;
+}
+
+/*
+ * __txn_doevents --
+ * Process the list of events associated with a transaction. On commit,
+ * apply the events; on abort, just toss the entries.
+ *
+ * PUBLIC: int __txn_doevents __P((DB_ENV *, DB_TXN *, int, int));
+ */
+#define DO_TRADE do { \
+ memset(&req, 0, sizeof(req)); \
+ req.lock = e->u.t.lock; \
+ req.op = DB_LOCK_TRADE; \
+ t_ret = __lock_vec(dbenv, e->u.t.locker, 0, &req, 1, NULL); \
+ if (t_ret == 0) \
+ e->u.t.dbp->cur_lid = e->u.t.locker; \
+ else if (t_ret == DB_NOTFOUND) \
+ t_ret = 0; \
+ if (t_ret != 0 && ret == 0) \
+ ret = t_ret; \
+ e->op = TXN_TRADED; \
+} while (0)
+
+int
+__txn_doevents(dbenv, txn, is_commit, preprocess)
+ DB_ENV *dbenv;
+ DB_TXN *txn;
+ int is_commit, preprocess;
+{
+ DB_LOCKREQ req;
+ TXN_EVENT *e;
+ int ret, t_ret;
+
+ ret = 0;
+
+ /*
+ * This phase only gets called if we have a phase where we
+ * release read locks. Since not all paths will call this
+ * phase, we have to check for it below as well. So, when
+ * we do the trade, we update the opcode of the entry so that
+ * we don't try the trade again.
+ */
+ if (preprocess) {
+ for (e = TAILQ_FIRST(&txn->events);
+ e != NULL; e = TAILQ_NEXT(e, links)) {
+ if (e->op != TXN_TRADE)
+ continue;
+ DO_TRADE;
+ }
+ return (ret);
+ }
+
+ while ((e = TAILQ_FIRST(&txn->events)) != NULL) {
+ TAILQ_REMOVE(&txn->events, e, links);
+ if (!is_commit)
+ goto dofree;
+ switch (e->op) {
+ case TXN_REMOVE:
+ if (e->u.r.fileid != NULL) {
+ if ((t_ret = dbenv->memp_nameop(dbenv,
+ e->u.r.fileid,
+ NULL, e->u.r.name, NULL)) != 0 && ret == 0)
+ ret = t_ret;
+ __os_free(dbenv, e->u.r.fileid);
+ } else if ((t_ret =
+ __os_unlink(dbenv, e->u.r.name)) != 0 && ret == 0)
+ ret = t_ret;
+ __os_free(dbenv, e->u.r.name);
+ break;
+ case TXN_TRADE:
+ DO_TRADE;
+ /* Fall through */
+ case TXN_TRADED:
+ /* Downgrade the lock. */
+ if ((t_ret = __lock_downgrade(dbenv,
+ &e->u.t.lock, DB_LOCK_READ, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ break;
+ default:
+ /* This had better never happen. */
+ DB_ASSERT(0);
+ }
+dofree: __os_free(dbenv, e);
+ }
+
+ return (ret);
+}
diff --git a/bdb/xa/xa.c b/bdb/xa/xa.c
index b13a6d503b3..6667d14c2bf 100644
--- a/bdb/xa/xa.c
+++ b/bdb/xa/xa.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: xa.c,v 11.10 2000/12/14 07:39:14 ubell Exp $";
+static const char revid[] = "$Id: xa.c,v 11.23 2002/08/29 14:22:25 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -19,11 +19,7 @@ static const char revid[] = "$Id: xa.c,v 11.10 2000/12/14 07:39:14 ubell Exp $";
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "log.h"
-#include "txn.h"
-#include "db_am.h"
-#include "db_dispatch.h"
+#include "dbinc/txn.h"
static int __db_xa_close __P((char *, int, long));
static int __db_xa_commit __P((XID *, int, long));
@@ -35,8 +31,7 @@ static int __db_xa_prepare __P((XID *, int, long));
static int __db_xa_recover __P((XID *, long, int, long));
static int __db_xa_rollback __P((XID *, int, long));
static int __db_xa_start __P((XID *, int, long));
-static void __xa_txn_end __P((DB_ENV *));
-static void __xa_txn_init __P((DB_ENV *, TXN_DETAIL *, size_t));
+static void __xa_txn_end __P((DB_TXN *));
/*
* Possible flag values:
@@ -158,7 +153,7 @@ __db_xa_close(xa_info, rmid, flags)
/* Discard space held for the current transaction. */
if (env->xa_txn != NULL)
- __os_free(env->xa_txn, sizeof(DB_TXN));
+ __os_free(env, env->xa_txn);
/* Close the environment. */
if ((t_ret = env->close(env, 0)) != 0 && ret == 0)
@@ -220,7 +215,7 @@ __db_xa_start(xid, rmid, flags)
return (XA_RBOTHER);
/* Now, fill in the global transaction structure. */
- __xa_txn_init(env, td, off);
+ __txn_continue(env, env->xa_txn, td, off);
td->xa_status = TXN_XA_STARTED;
} else {
if (__txn_xa_begin(env, env->xa_txn) != 0)
@@ -327,15 +322,15 @@ __db_xa_prepare(xid, rmid, flags)
return (XAER_PROTO);
/* Now, fill in the global transaction structure. */
- __xa_txn_init(env, td, off);
+ __txn_continue(env, env->xa_txn, td, off);
- if (txn_prepare(env->xa_txn) != 0)
+ if (env->xa_txn->prepare(env->xa_txn, (u_int8_t *)xid->data) != 0)
return (XAER_RMERR);
td->xa_status = TXN_XA_PREPARED;
/* No fatal value that would require an XAER_RMFAIL. */
- __xa_txn_end(env);
+ __xa_txn_end(env->xa_txn);
return (XA_OK);
}
@@ -385,13 +380,13 @@ __db_xa_commit(xid, rmid, flags)
return (XAER_PROTO);
/* Now, fill in the global transaction structure. */
- __xa_txn_init(env, td, off);
+ __txn_continue(env, env->xa_txn, td, off);
- if (txn_commit(env->xa_txn, 0) != 0)
+ if (env->xa_txn->commit(env->xa_txn, 0) != 0)
return (XAER_RMERR);
/* No fatal value that would require an XAER_RMFAIL. */
- __xa_txn_end(env);
+ __xa_txn_end(env->xa_txn);
return (XA_OK);
}
@@ -409,118 +404,26 @@ __db_xa_recover(xids, count, rmid, flags)
long count, flags;
int rmid;
{
- __txn_xa_regop_args *argp;
- DBT data;
DB_ENV *env;
- DB_LOG *log;
- XID *xidp;
- int err, ret;
- u_int32_t rectype, txnid;
-
- ret = 0;
- xidp = xids;
+ u_int32_t newflags;
+ long rval;
/* If the environment is closed, then we're done. */
if (__db_rmid_to_env(rmid, &env) != 0)
return (XAER_PROTO);
- /*
- * If we are starting a scan, then we need to figure out where
- * to begin. If we are not starting a scan, we'll start from
- * wherever the log cursor is. Since XA apps cannot be threaded,
- * we don't have to worry about someone else having moved it.
- */
- log = env->lg_handle;
- if (LF_ISSET(TMSTARTRSCAN)) {
- if ((err = __log_findckp(env, &log->xa_first)) == DB_NOTFOUND) {
- /*
- * If there were no log files, then we have no
- * transactions to return, so we simply return 0.
- */
- return (0);
- }
- if ((err = __db_txnlist_init(env, &log->xa_info)) != 0)
- return (XAER_RMERR);
- } else {
- /*
- * If we are not starting a scan, the log cursor had
- * better be set.
- */
- if (IS_ZERO_LSN(log->xa_lsn))
- return (XAER_PROTO);
- }
-
- /*
- * At this point log->xa_first contains the point in the log
- * to which we need to roll back. If we are starting a scan,
- * we'll start at the last record; if we're continuing a scan,
- * we'll have to start at log->xa_lsn.
- */
-
- memset(&data, 0, sizeof(data));
- for (err = log_get(env, &log->xa_lsn, &data,
- LF_ISSET(TMSTARTRSCAN) ? DB_LAST : DB_SET);
- err == 0 && log_compare(&log->xa_lsn, &log->xa_first) > 0;
- err = log_get(env, &log->xa_lsn, &data, DB_PREV)) {
- memcpy(&rectype, data.data, sizeof(rectype));
-
- /*
- * The only record type we care about is an DB_txn_xa_regop.
- * If it's a commit, we have to add it to a txnlist. If it's
- * a prepare, and we don't have a commit, then we return it.
- * We are redoing some of what's in the xa_regop_recovery
- * code, but we have to do it here so we can get at the xid
- * in the record.
- */
- if (rectype != DB_txn_xa_regop && rectype != DB_txn_regop)
- continue;
-
- memcpy(&txnid, (u_int8_t *)data.data + sizeof(rectype),
- sizeof(txnid));
- err = __db_txnlist_find(log->xa_info, txnid);
- switch (rectype) {
- case DB_txn_regop:
- if (err == DB_NOTFOUND)
- __db_txnlist_add(env, log->xa_info, txnid, 0);
- err = 0;
- break;
- case DB_txn_xa_regop:
- /*
- * This transaction is committed, so we needn't read
- * the record and do anything.
- */
- if (err == 0)
- break;
- if ((err =
- __txn_xa_regop_read(env, data.data, &argp)) != 0) {
- ret = XAER_RMERR;
- goto out;
- }
-
- xidp->formatID = argp->formatID;
- xidp->gtrid_length = argp->gtrid;
- xidp->bqual_length = argp->bqual;
- memcpy(xidp->data, argp->xid.data, argp->xid.size);
- ret++;
- xidp++;
- __os_free(argp, sizeof(*argp));
- if (ret == count)
- goto done;
- break;
- }
- }
-
- if (err != 0 && err != DB_NOTFOUND)
- goto out;
-
-done: if (LF_ISSET(TMENDRSCAN)) {
- ZERO_LSN(log->xa_lsn);
- ZERO_LSN(log->xa_first);
+ if (LF_ISSET(TMSTARTRSCAN))
+ newflags = DB_FIRST;
+ else if (LF_ISSET(TMENDRSCAN))
+ newflags = DB_LAST;
+ else
+ newflags = DB_NEXT;
-out: __db_txnlist_end(env, log->xa_info);
- log->xa_info = NULL;
- }
- return (ret);
+ rval = 0;
+ if (__txn_get_prepared(env, xids, NULL, count, &rval, newflags) != 0)
+ return (XAER_RMERR);
+ else
+ return (rval);
}
/*
@@ -560,12 +463,12 @@ __db_xa_rollback(xid, rmid, flags)
return (XAER_PROTO);
/* Now, fill in the global transaction structure. */
- __xa_txn_init(env, td, off);
- if (txn_abort(env->xa_txn) != 0)
+ __txn_continue(env, env->xa_txn, td, off);
+ if (env->xa_txn->abort(env->xa_txn) != 0)
return (XAER_RMERR);
/* No fatal value that would require an XAER_RMFAIL. */
- __xa_txn_end(env);
+ __xa_txn_end(env->xa_txn);
return (XA_OK);
}
@@ -624,38 +527,13 @@ __db_xa_complete(handle, retval, rmid, flags)
}
/*
- * __xa_txn_init --
- * Fill in the fields of the local transaction structure given
- * the detail transaction structure.
- */
-static void
-__xa_txn_init(env, td, off)
- DB_ENV *env;
- TXN_DETAIL *td;
- size_t off;
-{
- DB_TXN *txn;
-
- txn = env->xa_txn;
- txn->mgrp = env->tx_handle;
- txn->parent = NULL;
- txn->last_lsn = td->last_lsn;
- txn->txnid = td->txnid;
- txn->off = off;
- txn->flags = 0;
-}
-
-/*
* __xa_txn_end --
- * Invalidate a transaction structure that was generated by xa_txn_init.
+ * Invalidate a transaction structure that was generated by __txn_continue.
*/
static void
-__xa_txn_end(env)
- DB_ENV *env;
-{
+__xa_txn_end(txn)
DB_TXN *txn;
-
- txn = env->xa_txn;
+{
if (txn != NULL)
txn->txnid = TXN_INVALID;
}
diff --git a/bdb/xa/xa_db.c b/bdb/xa/xa_db.c
index ba3dbfeddbb..b84bb1c9fa9 100644
--- a/bdb/xa/xa_db.c
+++ b/bdb/xa/xa_db.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1998, 1999, 2000
+ * Copyright (c) 1998-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: xa_db.c,v 11.9 2000/09/06 18:57:59 ubell Exp $";
+static const char revid[] = "$Id: xa_db.c,v 11.21 2002/08/29 14:22:25 margo Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -16,15 +16,14 @@ static const char revid[] = "$Id: xa_db.c,v 11.9 2000/09/06 18:57:59 ubell Exp $
#endif
#include "db_int.h"
-#include "xa.h"
-#include "xa_ext.h"
-#include "txn.h"
+#include "dbinc/xa.h"
+#include "dbinc/txn.h"
static int __xa_close __P((DB *, u_int32_t));
static int __xa_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
static int __xa_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
static int __xa_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
-static int __xa_open __P((DB *,
+static int __xa_open __P((DB *, DB_TXN *,
const char *, const char *, DBTYPE, u_int32_t, int));
static int __xa_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
@@ -33,7 +32,7 @@ typedef struct __xa_methods {
int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t));
int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
- int (*open) __P((DB *,
+ int (*open) __P((DB *, DB_TXN *,
const char *, const char *, DBTYPE, u_int32_t, int));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
} XA_METHODS;
@@ -73,8 +72,9 @@ __db_xa_create(dbp)
*/
static int
-__xa_open(dbp, name, subdb, type, flags, mode)
+__xa_open(dbp, txn, name, subdb, type, flags, mode)
DB *dbp;
+ DB_TXN *txn;
const char *name, *subdb;
DBTYPE type;
u_int32_t flags;
@@ -85,7 +85,7 @@ __xa_open(dbp, name, subdb, type, flags, mode)
xam = (XA_METHODS *)dbp->xa_internal;
- if ((ret = xam->open(dbp, name, subdb, type, flags, mode)) != 0)
+ if ((ret = xam->open(dbp, txn, name, subdb, type, flags, mode)) != 0)
return (ret);
xam->cursor = dbp->cursor;
@@ -109,7 +109,7 @@ __xa_cursor(dbp, txn, dbcp, flags)
{
DB_TXN *t;
- t = txn != NULL && txn == dbp->open_txn ? txn : dbp->dbenv->xa_txn;
+ t = txn != NULL ? txn : dbp->dbenv->xa_txn;
if (t->txnid == TXN_INVALID)
t = NULL;
@@ -125,7 +125,7 @@ __xa_del(dbp, txn, key, flags)
{
DB_TXN *t;
- t = txn != NULL && txn == dbp->open_txn ? txn : dbp->dbenv->xa_txn;
+ t = txn != NULL ? txn : dbp->dbenv->xa_txn;
if (t->txnid == TXN_INVALID)
t = NULL;
@@ -141,7 +141,7 @@ __xa_close(dbp, flags)
real_close = ((XA_METHODS *)dbp->xa_internal)->close;
- __os_free(dbp->xa_internal, sizeof(XA_METHODS));
+ __os_free(dbp->dbenv, dbp->xa_internal);
dbp->xa_internal = NULL;
return (real_close(dbp, flags));
@@ -156,7 +156,7 @@ __xa_get(dbp, txn, key, data, flags)
{
DB_TXN *t;
- t = txn != NULL && txn == dbp->open_txn ? txn : dbp->dbenv->xa_txn;
+ t = txn != NULL ? txn : dbp->dbenv->xa_txn;
if (t->txnid == TXN_INVALID)
t = NULL;
@@ -173,7 +173,7 @@ __xa_put(dbp, txn, key, data, flags)
{
DB_TXN *t;
- t = txn != NULL && txn == dbp->open_txn ? txn : dbp->dbenv->xa_txn;
+ t = txn != NULL ? txn : dbp->dbenv->xa_txn;
if (t->txnid == TXN_INVALID)
t = NULL;
diff --git a/bdb/xa/xa_map.c b/bdb/xa/xa_map.c
index 1af268477db..42fa4b20ed2 100644
--- a/bdb/xa/xa_map.c
+++ b/bdb/xa/xa_map.c
@@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: xa_map.c,v 11.5 2000/11/30 00:58:46 ubell Exp $";
+static const char revid[] = "$Id: xa_map.c,v 11.19 2002/09/03 14:58:27 sue Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -18,7 +18,7 @@ static const char revid[] = "$Id: xa_map.c,v 11.5 2000/11/30 00:58:46 ubell Exp
#endif
#include "db_int.h"
-#include "txn.h"
+#include "dbinc/txn.h"
/*
* This file contains all the mapping information that we need to support
@@ -72,31 +72,9 @@ __db_xid_to_txn(dbenv, xid, offp)
XID *xid;
size_t *offp;
{
- DB_TXNMGR *mgr;
- DB_TXNREGION *tmr;
struct __txn_detail *td;
- mgr = dbenv->tx_handle;
- tmr = mgr->reginfo.primary;
-
- /*
- * Search the internal active transaction table to find the
- * matching xid. If this is a performance hit, then we
- * can create a hash table, but I doubt it's worth it.
- */
- R_LOCK(dbenv, &mgr->reginfo);
- for (td = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail);
- td != NULL;
- td = SH_TAILQ_NEXT(td, links, __txn_detail))
- if (memcmp(xid->data, td->xid, XIDDATASIZE) == 0)
- break;
- R_UNLOCK(dbenv, &mgr->reginfo);
-
- if (td == NULL)
- return (EINVAL);
-
- *offp = R_OFFSET(&mgr->reginfo, td);
- return (0);
+ return (__txn_map_gid(dbenv, (u_int8_t *)xid->data, &td, offp));
}
/*
diff --git a/client/Makefile.am b/client/Makefile.am
index 9c994814714..92c46519275 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -16,9 +16,8 @@
# This file is public domain and comes with NO WARRANTY of any kind
-INCLUDES = -I$(srcdir)/../include \
- -I../include -I$(srcdir)/.. -I$(top_srcdir) \
- -I.. $(openssl_includes)
+#AUTOMAKE_OPTIONS = nostdinc
+INCLUDES = -I$(top_srcdir)/include $(openssl_includes)
LIBS = @CLIENT_LIBS@
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la
bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \
diff --git a/client/client_priv.h b/client/client_priv.h
index b8181245be2..b6bfc253854 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -37,4 +37,6 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
OPT_SELECT_LIMIT, OPT_MAX_JOIN_SIZE, OPT_SSL_SSL,
OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE,
- OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION, OPT_FRM };
+ OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
+ OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
+ OPT_COMPATIBLE };
diff --git a/client/completion_hash.cc b/client/completion_hash.cc
index ff5d0b28e41..536e7f9373a 100644
--- a/client/completion_hash.cc
+++ b/client/completion_hash.cc
@@ -27,7 +27,7 @@
#include <my_sys.h>
#include "completion_hash.h"
-uint hashpjw(char *arKey, uint nKeyLength)
+uint hashpjw(const char *arKey, uint nKeyLength)
{
uint h = 0, g, i;
@@ -111,7 +111,7 @@ int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength,
return SUCCESS;
}
-static Bucket *completion_hash_find(HashTable *ht, char *arKey,
+static Bucket *completion_hash_find(HashTable *ht, const char *arKey,
uint nKeyLength)
{
uint h, nIndex;
@@ -156,7 +156,7 @@ int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength)
return 0;
}
-Bucket *find_all_matches(HashTable *ht, char *str, uint length,
+Bucket *find_all_matches(HashTable *ht, const char *str, uint length,
uint *res_length)
{
Bucket *b;
diff --git a/client/completion_hash.h b/client/completion_hash.h
index c0853fddfe7..2595a445c9d 100644
--- a/client/completion_hash.h
+++ b/client/completion_hash.h
@@ -43,14 +43,14 @@ typedef struct hashtable {
uint nTableSize;
uint initialized;
MEM_ROOT mem_root;
- uint(*pHashFunction) (char *arKey, uint nKeyLength);
+ uint(*pHashFunction) (const char *arKey, uint nKeyLength);
Bucket **arBuckets;
} HashTable;
extern int completion_hash_init(HashTable *ht, uint nSize);
extern int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength, char *str);
extern int hash_exists(HashTable *ht, char *arKey);
-extern Bucket *find_all_matches(HashTable *ht, char *str, uint length, uint *res_length);
+extern Bucket *find_all_matches(HashTable *ht, const char *str, uint length, uint *res_length);
extern Bucket *find_longest_match(HashTable *ht, char *str, uint length, uint *res_length);
extern void add_word(HashTable *ht,char *str);
extern void completion_hash_clean(HashTable *ht);
diff --git a/client/connect_test.c b/client/connect_test.c
index fd81ad635ad..e19f83dac92 100644
--- a/client/connect_test.c
+++ b/client/connect_test.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "my_global.h"
#include "mysql.h"
static void change_user(MYSQL *sock,const char *user, const char *password,
diff --git a/client/insert_test.c b/client/insert_test.c
index 42691df6875..e4eb852af52 100644
--- a/client/insert_test.c
+++ b/client/insert_test.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "my_global.h"
#include "mysql.h"
#define INSERT_QUERY "insert into test (name,num) values ('item %d', %d)"
@@ -33,6 +34,7 @@ int main(int argc, char **argv)
exit(1);
}
+ mysql_init(&mysql);
if (!(sock = mysql_real_connect(&mysql,NULL,NULL,NULL,argv[1],0,NULL,0)))
{
fprintf(stderr,"Couldn't connect to engine!\n%s\n",mysql_error(&mysql));
diff --git a/client/mysql.cc b/client/mysql.cc
index 5f84261bd82..41da0113670 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -40,7 +40,7 @@
#include <signal.h>
#include <violite.h>
-const char *VER= "12.18";
+const char *VER= "13.4";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -92,7 +92,7 @@ extern "C" {
#endif
#ifdef FN_NO_CASE_SENCE
-#define cmp_database(A,B) my_strcasecmp((A),(B))
+#define cmp_database(A,B) my_strcasecmp(system_charset_info, (A), (B))
#else
#define cmp_database(A,B) strcmp((A),(B))
#endif
@@ -156,6 +156,11 @@ static FILE *PAGER, *OUTFILE;
static MEM_ROOT hash_mem_root;
static uint prompt_counter;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=0;
+#endif
+static uint opt_protocol=0;
+
#include "sslopt-vars.h"
#ifndef DBUG_OFF
@@ -194,6 +199,7 @@ static void end_pager();
static void init_tee(const char *);
static void end_tee();
static const char* construct_prompt();
+static char *get_arg(char *line, my_bool get_next_arg);
static void init_username();
static void add_int_to_prompt(int toadd);
@@ -209,8 +215,8 @@ typedef struct {
} COMMANDS;
static COMMANDS commands[] = {
- { "help", 'h', com_help, 0, "Display this help." },
- { "?", '?', com_help, 0, "Synonym for `help'." },
+ { "help", 'h', com_help, 1, "Display this help." },
+ { "?", '?', com_help, 1, "Synonym for `help'." },
{ "clear", 'c', com_clear, 0, "Clear command."},
{ "connect",'r', com_connect,1,
"Reconnect to the server. Optional arguments are db and host." },
@@ -271,14 +277,15 @@ static const char *server_default_groups[]=
{ "server", "embedded", "mysql_SERVER", 0 };
#ifdef HAVE_READLINE
-extern "C" void add_history(char *command); /* From readline directory */
-extern "C" int read_history(char *command);
-extern "C" int write_history(char *command);
+extern "C" int add_history(const char *command); /* From readline directory */
+extern "C" int read_history(const char *command);
+extern "C" int write_history(const char *command);
static void initialize_readline (char *name);
#endif
static COMMANDS *find_command (char *name,char cmd_name);
-static bool add_line(String &buffer,char *line,char *in_string);
+static bool add_line(String &buffer,char *line,char *in_string,
+ bool *ml_comment);
static void remove_cntrl(String &buffer);
static void print_table_data(MYSQL_RES *result);
static void print_table_data_html(MYSQL_RES *result);
@@ -350,6 +357,7 @@ int main(int argc,char *argv[])
if (!status.batch)
ignore_errors=1; // Don't abort monitor
signal(SIGINT, mysql_end); // Catch SIGINT to clean up
+ signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
/*
Run in interactive mode like the ingres/postgres monitor
@@ -385,8 +393,11 @@ int main(int argc,char *argv[])
}
}
#endif
- sprintf(buff,
+ sprintf(buff, "%s",
"Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n");
+#ifdef NOT_YET
+ "Type 'help [[%]function name[%]]' to get help on usage of function.\n");
+#endif
put_info(buff,INFO_INFO);
status.exit_status=read_lines(1); // read lines and execute them
if (opt_outfile)
@@ -427,6 +438,9 @@ sig_handler mysql_end(int sig)
my_free(full_username,MYF(MY_ALLOW_ZERO_PTR));
my_free(part_username,MYF(MY_ALLOW_ZERO_PTR));
my_free(default_prompt,MYF(MY_ALLOW_ZERO_PTR));
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
mysql_server_end();
free_defaults(defaults_argv);
@@ -534,6 +548,8 @@ static struct my_option my_long_options[] =
{"prompt", OPT_PROMPT, "Set the mysql prompt to this value.",
(gptr*) &current_prompt, (gptr*) &current_prompt, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"quick", 'q',
"Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file. ",
(gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -542,6 +558,11 @@ static struct my_option my_long_options[] =
0, 0, 0},
{"silent", 's', "Be more silent.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -646,6 +667,16 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_NOPAGER:
printf("WARNING: option deprecated; use --disable-pager instead.\n");
opt_nopager= 1;
+ case OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) ==
+ ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
break;
case 'A':
rehash= 0;
@@ -708,7 +739,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'W':
#ifdef __WIN__
- opt_mysql_unix_port= my_strdup(MYSQL_NAMEDPIPE, MYF(0));
+ opt_protocol = MYSQL_PROTOCOL_PIPE;
#endif
break;
#include <sslopt-case.h>
@@ -782,9 +813,10 @@ static int read_lines(bool execute_commands)
char *line;
char in_string=0;
ulong line_number=0;
+ bool ml_comment= 0;
COMMANDS *com;
status.exit_status=1;
-
+
for (;;)
{
if (status.batch || !execute_commands)
@@ -853,7 +885,7 @@ static int read_lines(bool execute_commands)
#endif
continue;
}
- if (add_line(glob_buffer,line,&in_string))
+ if (add_line(glob_buffer,line,&in_string,&ml_comment))
break;
}
/* if in batch mode, send last query even if it doesn't end with \g or go */
@@ -884,14 +916,14 @@ static COMMANDS *find_command (char *name,char cmd_char)
}
else
{
- while (isspace(*name))
+ while (my_isspace(system_charset_info,*name))
name++;
if (strchr(name,';') || strstr(name,"\\g"))
return ((COMMANDS *) 0);
if ((end=strcont(name," \t")))
{
len=(uint) (end - name);
- while (isspace(*end))
+ while (my_isspace(system_charset_info,*end))
end++;
if (!*end)
end=0; // no arguments to function
@@ -903,7 +935,8 @@ static COMMANDS *find_command (char *name,char cmd_char)
for (uint i= 0; commands[i].name; i++)
{
if (commands[i].func &&
- ((name && !my_casecmp(name,commands[i].name,len) &&
+ ((name &&
+ !my_strncasecmp(system_charset_info,name,commands[i].name,len) &&
!commands[i].name[len] &&
(!end || (end && commands[i].takes_params))) ||
!name && commands[i].cmd_char == cmd_char))
@@ -913,7 +946,8 @@ static COMMANDS *find_command (char *name,char cmd_char)
}
-static bool add_line(String &buffer,char *line,char *in_string)
+static bool add_line(String &buffer,char *line,char *in_string,
+ bool *ml_comment)
{
uchar inchar;
char buff[80],*pos,*out;
@@ -931,19 +965,20 @@ static bool add_line(String &buffer,char *line,char *in_string)
for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
{
- if (isspace(inchar) && out == line && buffer.is_empty())
+ if (my_isspace(system_charset_info,inchar) && out == line &&
+ buffer.is_empty())
continue;
#ifdef USE_MB
int l;
- if (use_mb(default_charset_info) &&
- (l = my_ismbchar(default_charset_info, pos, strend))) {
+ if (use_mb(system_charset_info) &&
+ (l = my_ismbchar(system_charset_info, pos, strend))) {
while (l--)
*out++ = *pos++;
pos--;
continue;
}
#endif
- if (inchar == '\\')
+ if (!*ml_comment && inchar == '\\')
{ // mSQL or postgreSQL style command ?
if (!(inchar = (uchar) *++pos))
break; // readline adds one '\'
@@ -955,7 +990,7 @@ static bool add_line(String &buffer,char *line,char *in_string)
}
if ((com=find_command(NullS,(char) inchar)))
{
- const String tmp(line,(uint) (out-line));
+ const String tmp(line,(uint) (out-line), system_charset_info);
buffer.append(tmp);
if ((*com->func)(&buffer,pos-1) > 0)
return 1; // Quit
@@ -977,7 +1012,7 @@ static bool add_line(String &buffer,char *line,char *in_string)
continue;
}
}
- else if (inchar == ';' && !*in_string)
+ else if (!*ml_comment && inchar == ';' && !*in_string)
{ // ';' is end of command
if (out != line)
buffer.append(line,(uint) (out-line)); // Add this line
@@ -997,17 +1032,33 @@ static bool add_line(String &buffer,char *line,char *in_string)
buffer.length(0);
out=line;
}
- else if (!*in_string && (inchar == '#' ||
- inchar == '-' && pos[1] == '-' &&
- isspace(pos[2])))
+ else if (!*ml_comment && (!*in_string && (inchar == '#' ||
+ inchar == '-' && pos[1] == '-' &&
+ my_isspace(system_charset_info,pos[2]))))
break; // comment to end of line
+ else if (!*in_string && inchar == '/' && *(pos+1) == '*')
+ {
+ pos++;
+ *ml_comment= 1;
+ if (out != line)
+ {
+ buffer.append(line,(uint) (out-line));
+ out=line;
+ }
+ }
+ else if (*ml_comment && !*in_string && inchar == '*' && *(pos+1) == '/')
+ {
+ pos++;
+ *ml_comment= 0;
+ }
else
{ // Add found char to buffer
if (inchar == *in_string)
*in_string=0;
else if (!*in_string && (inchar == '\'' || inchar == '"'))
*in_string=(char) inchar;
- *out++ = (char) inchar;
+ if (!(*ml_comment))
+ *out++ = (char) inchar;
}
}
if (out != line || !buffer.is_empty())
@@ -1016,7 +1067,7 @@ static bool add_line(String &buffer,char *line,char *in_string)
uint length=(uint) (out-line);
if (buffer.length() + length >= buffer.alloced_length())
buffer.realloc(buffer.length()+length+IO_SIZE);
- if (buffer.append(line,length))
+ if (!(*ml_comment) && buffer.append(line,length))
return 1;
}
return 0;
@@ -1028,8 +1079,8 @@ static bool add_line(String &buffer,char *line,char *in_string)
#ifdef HAVE_READLINE
-static char *new_command_generator(char *text, int);
-static char **new_mysql_completion (char *text, int start, int end);
+static char *new_command_generator(const char *text, int);
+static char **new_mysql_completion (const char *text, int start, int end);
/*
Tell the GNU Readline library how to complete. We want to try to complete
@@ -1037,8 +1088,11 @@ static char **new_mysql_completion (char *text, int start, int end);
if not.
*/
-char **no_completion (char *text __attribute__ ((unused)),
- char *word __attribute__ ((unused)))
+#if defined(USE_NEW_READLINE_INTERFACE) || defined(USE_LIBEDIT_INTERFACE)
+char *no_completion(const char*,int)
+#else
+int no_completion()
+#endif
{
return 0; /* No filename completion */
}
@@ -1049,9 +1103,16 @@ static void initialize_readline (char *name)
rl_readline_name = name;
/* Tell the completer that we want a crack first. */
- /* rl_attempted_completion_function = (CPPFunction *)mysql_completion;*/
- rl_attempted_completion_function = (CPPFunction *) new_mysql_completion;
- rl_completion_entry_function=(Function *) no_completion;
+#if defined(USE_NEW_READLINE_INTERFACE)
+ rl_attempted_completion_function= (rl_completion_func_t*)&new_mysql_completion;
+ rl_completion_entry_function= (rl_compentry_func_t*)&no_completion;
+#elif defined(USE_LIBEDIT_INTERFACE)
+ rl_attempted_completion_function= (CPPFunction*)&new_mysql_completion;
+ rl_completion_entry_function= (CPFunction*)&no_completion;
+#else
+ rl_attempted_completion_function= (CPPFunction*)&new_mysql_completion;
+ rl_completion_entry_function= (Function*)&no_completion;
+#endif
}
/*
@@ -1061,17 +1122,21 @@ static void initialize_readline (char *name)
array of matches, or NULL if there aren't any.
*/
-static char **new_mysql_completion (char *text,
+static char **new_mysql_completion (const char *text,
int start __attribute__((unused)),
int end __attribute__((unused)))
{
if (!status.batch && !quick)
- return completion_matches(text, (CPFunction*) new_command_generator);
+#if defined(USE_NEW_READLINE_INTERFACE)
+ return rl_completion_matches(text, new_command_generator);
+#else
+ return completion_matches((char *)text, (CPFunction *)new_command_generator);
+#endif
else
return (char**) 0;
}
-static char *new_command_generator(char *text,int state)
+static char *new_command_generator(const char *text,int state)
{
static int textlen;
char *ptr;
@@ -1250,7 +1315,7 @@ You can turn off this feature to get a quicker startup with -A\n\n");
sizeof(char *) *
(num_fields*2+1))))
break;
- field_names[i][num_fields*2]='\0';
+ field_names[i][num_fields*2]= '\0';
j=0;
while ((sql_field=mysql_fetch_field(fields)))
{
@@ -1270,7 +1335,7 @@ You can turn off this feature to get a quicker startup with -A\n\n");
{
tee_fprintf(stdout,
"Didn't find any fields in table '%s'\n",table_row[0]);
- field_names[i]=0;
+ field_names[i]= 0;
}
i++;
}
@@ -1326,31 +1391,150 @@ static int reconnect(void)
The different commands
***************************************************************************/
+int mysql_real_query_for_lazy(const char *buf, int length)
+{
+ for (uint retry=0;; retry++)
+ {
+ if (!mysql_real_query(&mysql,buf,length))
+ return 0;
+ uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql));
+ if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
+ status.batch)
+ return error;
+ if (reconnect())
+ return error;
+ }
+}
+
+int mysql_store_result_for_lazy(MYSQL_RES **result)
+{
+ if ((*result=mysql_store_result(&mysql)))
+ return 0;
+
+ if (mysql_error(&mysql)[0])
+ return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
+
+ return 0;
+}
+
+
+static int com_server_help(String *buffer __attribute__((unused)),
+ char *line __attribute__((unused)), char *help_arg)
+{
+ MYSQL_ROW cur;
+ const char *server_cmd= buffer->ptr();
+ char cmd_buf[100];
+ MYSQL_RES *result;
+ int error;
+
+ if (help_arg[0] != '\'')
+ {
+ (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
+ server_cmd= cmd_buf;
+ }
+
+ if (!status.batch)
+ {
+ old_buffer= *buffer;
+ old_buffer.copy();
+ }
+
+ if (!connected && reconnect())
+ return 1;
+
+ if ((error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd))))
+ return error;
+ if ((error= mysql_store_result_for_lazy(&result)))
+ return error;
+
+ if (result)
+ {
+ ulonglong num_rows= mysql_num_rows(result);
+ if (num_rows == 1)
+ {
+ if (!(cur= mysql_fetch_row(result)))
+ {
+ error= -1;
+ goto err;
+ }
+
+ init_pager();
+ if (cur[1][0] == 'Y')
+ {
+ tee_fprintf(PAGER, "Help topic \'%s\'\n", cur[0]);
+ tee_fprintf(PAGER, "%s\n", cur[2]);
+ tee_fprintf(PAGER, "For help on specific function please type 'help <function>'\nwhere function is one of next:\n%s\n", cur[3]);
+ }
+ else
+ {
+ tee_fprintf(PAGER, "Name: \'%s\'\n\n", cur[0]);
+ tee_fprintf(PAGER, "Description:\n%s\n\n", cur[2]);
+ if (cur[3])
+ tee_fprintf(PAGER, "Examples:\n%s\n", cur[3]);
+ }
+ end_pager();
+ }
+ else if (num_rows > 1)
+ {
+ put_info("Many help items for your request exist", INFO_INFO);
+ put_info("For more specific request please type 'help <item>' where item is one of next:", INFO_INFO);
+
+ init_pager();
+ char last_char= '_';
+ while ((cur= mysql_fetch_row(result)))
+ {
+ if (cur[1][0]!=last_char)
+ {
+ put_info("-------------------------------------------", INFO_INFO);
+ put_info(cur[1][0] == 'Y' ?
+ "categories:" : "functions:", INFO_INFO);
+ put_info("-------------------------------------------", INFO_INFO);
+ }
+ last_char= cur[1][0];
+ tee_fprintf(PAGER, "%s\n", cur[0]);
+ }
+ tee_fprintf(PAGER, "\n");
+ end_pager();
+ }
+ else
+ {
+ put_info("\nNothing found\n", INFO_INFO);
+ }
+ }
+
+err:
+ mysql_free_result(result);
+ return error;
+}
+
static int
-com_help (String *buffer __attribute__((unused)),
- char *line __attribute__((unused)))
+com_help(String *buffer __attribute__((unused)),
+ char *line __attribute__((unused)))
{
reg1 int i;
+ char * help_arg= strchr(line,' ');
- put_info("\nFor the complete MySQL Manual online visit:\n http://www.mysql.com/documentation\n", INFO_INFO);
- put_info("For info on technical support from MySQL developers visit:\n http://www.mysql.com/support\n", INFO_INFO);
- put_info("For info on MySQL books, utilities, consultants, etc. visit:\n http://www.mysql.com/portal\n", INFO_INFO);
- put_info("List of all MySQL commands:", INFO_INFO);
- if (!named_cmds)
- put_info(" (Commands must appear first on line and end with ';')\n",
- INFO_INFO);
- for (i = 0; commands[i].name; i++)
+ if (help_arg)
{
- if (commands[i].func)
- tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
- commands[i].cmd_char, commands[i].doc);
+ return com_server_help(buffer,line,help_arg+1);
}
- if (connected)
- tee_fprintf(stdout,
- "\nConnection id: %ld (Can be used with mysqladmin kill)\n\n",
- mysql_thread_id(&mysql));
else
- tee_fprintf(stdout, "Not connected! Reconnect with 'connect'!\n\n");
+ {
+ put_info("\nFor the complete MySQL Manual online visit:\n http://www.mysql.com/documentation\n", INFO_INFO);
+ put_info("For info on technical support from MySQL developers visit:\n http://www.mysql.com/support\n", INFO_INFO);
+ put_info("For info on MySQL books, utilities, consultants, etc. visit:\n http://www.mysql.com/portal\n", INFO_INFO);
+ put_info("List of all MySQL commands:", INFO_INFO);
+ if (!named_cmds)
+ put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
+ for (i = 0; commands[i].name; i++)
+ {
+ if (commands[i].func)
+ tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
+ commands[i].cmd_char, commands[i].doc);
+ }
+ }
+ if (connected && mysql_get_server_version(&mysql) >= 40100)
+ put_info("\nFor server side help, type 'help all'\n", INFO_INFO);
return 0;
}
@@ -1375,9 +1559,9 @@ com_clear(String *buffer,char *line __attribute__((unused)))
static int
com_go(String *buffer,char *line __attribute__((unused)))
{
- char buff[160],time_buff[32];
+ char buff[200], time_buff[32], *pos;
MYSQL_RES *result;
- ulong timer;
+ ulong timer, warnings;
uint error=0;
if (!status.batch)
@@ -1406,30 +1590,23 @@ com_go(String *buffer,char *line __attribute__((unused)))
(void) com_print(buffer,0);
if (skip_updates &&
- (buffer->length() < 4 || my_sortcmp(buffer->ptr(),"SET ",4)))
+ (buffer->length() < 4 || my_strnncoll(system_charset_info,
+ (const uchar*)buffer->ptr(),4,
+ (const uchar*)"SET ",4)))
{
(void) put_info("Ignoring query to other database",INFO_INFO);
return 0;
}
timer=start_timer();
- for (uint retry=0;; retry++)
+
+ error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
+ if (error)
{
- if (!mysql_real_query(&mysql,buffer->ptr(),buffer->length()))
- break;
- error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql));
- if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1
- || status.batch)
- {
- buffer->length(0); // Remove query on error
- return error;
- }
- if (reconnect())
- {
- buffer->length(0); // Remove query on error
- return error;
- }
+ buffer->length(0); // Remove query on error
+ return error;
}
+
error=0;
buffer->length(0);
@@ -1442,13 +1619,9 @@ com_go(String *buffer,char *line __attribute__((unused)))
}
else
{
- if (!(result=mysql_store_result(&mysql)))
- {
- if (mysql_error(&mysql)[0])
- {
- return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
- }
- }
+ error= mysql_store_result_for_lazy(&result);
+ if (error)
+ return error;
}
if (verbose >= 3 || !opt_silent)
@@ -1459,7 +1632,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
{
if (!mysql_num_rows(result) && ! quick)
{
- sprintf(buff,"Empty set%s",time_buff);
+ strmov(buff, "Empty set");
}
else
{
@@ -1474,20 +1647,30 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_tab_data(result);
else
print_table_data(result);
- sprintf(buff,"%ld %s in set%s",
+ sprintf(buff,"%ld %s in set",
(long) mysql_num_rows(result),
- (long) mysql_num_rows(result) == 1 ? "row" : "rows",
- time_buff);
+ (long) mysql_num_rows(result) == 1 ? "row" : "rows");
end_pager();
}
}
else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0)
- sprintf(buff,"Query OK%s",time_buff);
+ strmov(buff,"Query OK");
else
- sprintf(buff,"Query OK, %ld %s affected%s",
+ sprintf(buff,"Query OK, %ld %s affected",
(long) mysql_affected_rows(&mysql),
- (long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows",
- time_buff);
+ (long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows");
+
+ pos=strend(buff);
+ if ((warnings= mysql_warning_count(&mysql)))
+ {
+ *pos++= ',';
+ *pos++= ' ';
+ pos=int2str(warnings, pos, 10);
+ pos=strmov(pos, " warning");
+ if (warnings != 1)
+ *pos++= 's';
+ }
+ strmov(pos, time_buff);
put_info(buff,INFO_RESULT);
if (mysql_info(&mysql))
put_info(mysql_info(&mysql),INFO_RESULT);
@@ -1598,10 +1781,10 @@ print_table_data(MYSQL_RES *result)
print_field_types(result);
mysql_field_seek(result,0);
}
- separator.copy("+",1);
+ separator.copy("+",1,system_charset_info);
while ((field = mysql_fetch_field(result)))
{
- uint length= column_names ? (uint) strlen(field->name) : 0;
+ uint length= column_names ? field->name_length : 0;
if (quick)
length=max(length,field->length);
else
@@ -1743,7 +1926,7 @@ print_table_data_vertically(MYSQL_RES *result)
while ((field = mysql_fetch_field(result)))
{
- uint length=(uint) strlen(field->name);
+ uint length= field->name_length;
if (length > max_length)
max_length= length;
field->max_length=length;
@@ -1812,8 +1995,9 @@ safe_put_field(const char *pos,ulong length)
{
#ifdef USE_MB
int l;
- if (use_mb(default_charset_info) &&
- (l = my_ismbchar(default_charset_info, pos, end))) {
+ if (use_mb(system_charset_info) &&
+ (l = my_ismbchar(system_charset_info, pos, end)))
+ {
while (l--)
tee_putc(*pos++, PAGER);
pos--;
@@ -1873,7 +2057,7 @@ com_tee(String *buffer, char *line __attribute__((unused)))
if (status.batch)
return 0;
- while (isspace(*line))
+ while (my_isspace(system_charset_info,*line))
line++;
if (!(param = strchr(line, ' '))) // if outfile wasn't given, use the default
{
@@ -1892,11 +2076,12 @@ com_tee(String *buffer, char *line __attribute__((unused)))
}
/* eliminate the spaces before the parameters */
- while (isspace(*param))
+ while (my_isspace(system_charset_info,*param))
param++;
end= strmake(file_name, param, sizeof(file_name) - 1);
/* remove end space from command line */
- while (end > file_name && (isspace(end[-1]) || iscntrl(end[-1])))
+ while (end > file_name && (my_isspace(system_charset_info,end[-1]) ||
+ my_iscntrl(system_charset_info,end[-1])))
end--;
end[0]= 0;
if (end == file_name)
@@ -1932,7 +2117,7 @@ com_pager(String *buffer, char *line __attribute__((unused)))
if (status.batch)
return 0;
/* Skip space from file name */
- while (isspace(*line))
+ while (my_isspace(system_charset_info,*line))
line++;
if (!(param= strchr(line, ' '))) // if pager was not given, use the default
{
@@ -1948,10 +2133,11 @@ com_pager(String *buffer, char *line __attribute__((unused)))
}
else
{
- while (isspace(*param))
+ while (my_isspace(system_charset_info,*param))
param++;
end=strmake(pager_name, param, sizeof(pager_name)-1);
- while (end > pager_name && (isspace(end[-1]) || iscntrl(end[-1])))
+ while (end > pager_name && (my_isspace(system_charset_info,end[-1]) ||
+ my_iscntrl(system_charset_info,end[-1])))
end--;
end[0]=0;
strmov(pager, pager_name);
@@ -2085,23 +2271,21 @@ com_print(String *buffer,char *line __attribute__((unused)))
static int
com_connect(String *buffer, char *line)
{
- char *tmp,buff[256];
+ char *tmp, buff[256];
bool save_rehash= rehash;
int error;
+ bzero(buff, sizeof(buff));
if (buffer)
{
- while (isspace(*line))
- line++;
- strnmov(buff,line,sizeof(buff)-1); // Don't destroy history
- if (buff[0] == '\\') // Short command
- buff[1]=' ';
- tmp=(char *) strtok(buff," \t"); // Skip connect command
- if (tmp && (tmp=(char *) strtok(NullS," \t;")))
+ strmov(buff, line);
+ tmp= get_arg(buff, 0);
+ if (tmp && *tmp)
{
- my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
- current_db=my_strdup(tmp,MYF(MY_WME));
- if ((tmp=(char *) strtok(NullS," \t;")))
+ my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
+ current_db= my_strdup(tmp, MYF(MY_WME));
+ tmp= get_arg(buff, 1);
+ if (tmp)
{
my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
current_host=my_strdup(tmp,MYF(MY_WME));
@@ -2137,15 +2321,16 @@ static int com_source(String *buffer, char *line)
FILE *sql_file;
/* Skip space from file name */
- while (isspace(*line))
+ while (my_isspace(system_charset_info,*line))
line++;
if (!(param = strchr(line, ' '))) // Skip command name
return put_info("Usage: \\. <filename> | source <filename>",
INFO_ERROR, 0);
- while (isspace(*param))
+ while (my_isspace(system_charset_info,*param))
param++;
end=strmake(source_name,param,sizeof(source_name)-1);
- while (end > source_name && (isspace(end[-1]) || iscntrl(end[-1])))
+ while (end > source_name && (my_isspace(system_charset_info,end[-1]) ||
+ my_iscntrl(system_charset_info,end[-1])))
end--;
end[0]=0;
unpack_filename(source_name,source_name);
@@ -2186,18 +2371,15 @@ com_use(String *buffer __attribute__((unused)), char *line)
char *tmp;
char buff[256];
- while (isspace(*line))
- line++;
- strnmov(buff,line,sizeof(buff)-1); // Don't destroy history
- if (buff[0] == '\\') // Short command
- buff[1]=' ';
- tmp=(char *) strtok(buff," \t;"); // Skip connect command
- if (!tmp || !(tmp=(char *) strtok(NullS," \t;")))
+ bzero(buff, sizeof(buff));
+ strmov(buff, line);
+ tmp= get_arg(buff, 0);
+ if (!tmp || !*tmp)
{
- put_info("USE must be followed by a database name",INFO_ERROR);
+ put_info("USE must be followed by a database name", INFO_ERROR);
return 0;
}
- if (!current_db || cmp_database(current_db,tmp))
+ if (!current_db || cmp_database(current_db, tmp))
{
if (one_database)
skip_updates= 1;
@@ -2233,6 +2415,74 @@ com_use(String *buffer __attribute__((unused)), char *line)
}
+/*
+ Gets argument from a command on the command line. If get_next_arg is
+ not defined, skips the command and returns the first argument. The
+ line is modified by adding zero to the end of the argument. If
+ get_next_arg is defined, then the function searches for end of string
+ first, after found, returns the next argument and adds zero to the
+ end. If you ever wish to use this feature, remember to initialize all
+ items in the array to zero first.
+*/
+
+char *get_arg(char *line, my_bool get_next_arg)
+{
+ char *ptr;
+ my_bool quoted= 0, valid_arg= 0;
+ uint count= 0;
+ char qtype= 0;
+
+ ptr= line;
+ if (get_next_arg)
+ {
+ for (; ptr && *ptr; ptr++);
+ if ((ptr + 1) && *(ptr + 1))
+ ptr++;
+ }
+ else
+ {
+ /* skip leading white spaces */
+ while (my_isspace(system_charset_info, *ptr))
+ ptr++;
+ if (*ptr == '\\') // short command was used
+ ptr+= 2;
+ while (!my_isspace(system_charset_info, *ptr)) // skip command
+ ptr++;
+ }
+ while (my_isspace(system_charset_info, *ptr))
+ ptr++;
+ if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
+ {
+ qtype= *ptr;
+ quoted= 1;
+ ptr++;
+ }
+ for (; ptr && *ptr; ptr++, count++)
+ {
+ if (*ptr == '\\') // escaped character
+ {
+ // jump over the backslash
+ char *tmp_ptr, tmp_buff[256];
+ tmp_ptr= strmov(tmp_buff, (ptr - count));
+ tmp_ptr-= (strlen(tmp_buff) - count);
+ strmov(tmp_ptr, (ptr + 1));
+ strmov(line, tmp_buff);
+ ptr= line;
+ ptr+= count;
+ }
+ else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
+ {
+ *ptr= 0;
+ break;
+ }
+ }
+ for (ptr-= count; ptr && *ptr; ptr++)
+ if (!my_isspace(system_charset_info, *ptr))
+ valid_arg= 1;
+ return valid_arg ? ptr - count : '\0';
+}
+
+
static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
@@ -2255,6 +2505,12 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#endif
+ if (opt_protocol)
+ mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
if (safe_updates)
{
char init_command[100];
@@ -2278,7 +2534,9 @@ sql_real_connect(char *host,char *database,char *user,char *password,
return -1; // Retryable
}
connected=1;
+#ifndef EMBEDDED_LIBRARY
mysql.reconnect=info_flag ? 1 : 0; // We want to know if this happens
+#endif
#ifdef HAVE_READLINE
build_completion_hash(rehash, 1);
#endif
@@ -2370,14 +2628,16 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
tee_fprintf(stdout, "Client characterset:\t%s\n",
- default_charset_info->name);
+ system_charset_info->name);
tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name);
+#ifndef EMBEDDED_LIBRARY
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || ! mysql.unix_socket)
tee_fprintf(stdout, "TCP port:\t\t%d\n", mysql.port);
else
tee_fprintf(stdout, "UNIX socket:\t\t%s\n", mysql.unix_socket);
if (mysql.net.compress)
tee_fprintf(stdout, "Protocol:\t\tCompressed\n");
+#endif
if ((status=mysql_stat(&mysql)) && !mysql_error(&mysql)[0])
{
@@ -2479,7 +2739,7 @@ static void remove_cntrl(String &buffer)
{
char *start,*end;
end=(start=(char*) buffer.ptr())+buffer.length();
- while (start < end && !isgraph(end[-1]))
+ while (start < end && !my_isgraph(system_charset_info,end[-1]))
end--;
buffer.length((uint) (end-start));
}
@@ -2643,14 +2903,16 @@ static const char* construct_prompt()
break;
}
case 'p':
+#ifndef EMBEDDED_LIBRARY
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") ||
! mysql.unix_socket)
add_int_to_prompt(mysql.port);
else
{
char *pos=strrchr(mysql.unix_socket,'/');
- processed_prompt.append(pos ? pos+1 : mysql.unix_socket);
+ processed_prompt.append(pos ? pos+1 : mysql.unix_socket);
}
+#endif
break;
case 'U':
if (!full_username)
@@ -2791,3 +3053,4 @@ void sql_element_free(void *ptr)
my_free((gptr) ptr,MYF(0));
}
#endif /* EMBEDDED_LIBRARY */
+
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index 95bc17e880b..cba137d54c6 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -23,6 +23,7 @@
#include <my_pthread.h> /* because of signal() */
#endif
#include <sys/stat.h>
+#include <mysql.h>
#define ADMIN_VERSION "8.40"
#define MAX_MYSQL_VAR 256
@@ -42,6 +43,11 @@ static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations,
static ulong opt_connect_timeout, opt_shutdown_timeout;
static my_string unix_port=0;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=0;
+#endif
+static uint opt_protocol=0;
+
/*
When using extended-status relatively, ex_val_max_len is the estimated
maximum length for any relative value printed by extended-status. The
@@ -78,16 +84,16 @@ static void store_values(MYSQL_RES *result);
The order of commands must be the same as command_names,
except ADMIN_ERROR
*/
-enum commands {
- ADMIN_ERROR,
+enum commands {
+ ADMIN_ERROR,
ADMIN_CREATE, ADMIN_DROP, ADMIN_SHUTDOWN,
- ADMIN_RELOAD, ADMIN_REFRESH, ADMIN_VER,
- ADMIN_PROCESSLIST, ADMIN_STATUS, ADMIN_KILL,
- ADMIN_DEBUG, ADMIN_VARIABLES, ADMIN_FLUSH_LOGS,
- ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
- ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
- ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
- ADMIN_FLUSH_THREADS
+ ADMIN_RELOAD, ADMIN_REFRESH, ADMIN_VER,
+ ADMIN_PROCESSLIST, ADMIN_STATUS, ADMIN_KILL,
+ ADMIN_DEBUG, ADMIN_VARIABLES, ADMIN_FLUSH_LOGS,
+ ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
+ ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
+ ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
+ ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
};
static const char *command_names[]= {
"create", "drop", "shutdown",
@@ -96,8 +102,8 @@ static const char *command_names[]= {
"debug", "variables", "flush-logs",
"flush-hosts", "flush-tables", "password",
"ping", "extended-status", "flush-status",
- "flush-privileges", "start-slave", "stop-slave",
- "flush-threads",
+ "flush-privileges", "start-slave", "stop-slave",
+ "flush-threads","old-password",
NullS
};
@@ -135,6 +141,8 @@ static struct my_option my_long_options[] =
#endif
{"port", 'P', "Port number to use for connection.", (gptr*) &tcp_port,
(gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"relative", 'r',
"Show difference between current and previous values when used with -i. Currently works only with extended-status.",
(gptr*) &opt_relative, (gptr*) &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0,
@@ -142,6 +150,11 @@ static struct my_option my_long_options[] =
{"set-variable", 'O',
"Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"silent", 's', "Silently exit if one can't connect to server",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
@@ -159,7 +172,7 @@ static struct my_option my_long_options[] =
(gptr*) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"vertical", 'E',
+ {"vertical", 'E',
"Print output vertically. Is similar to --relative, but prints output vertically.",
(gptr*) &opt_vertical, (gptr*) &opt_vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -205,7 +218,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'W':
#ifdef __WIN__
- unix_port=MYSQL_NAMEDPIPE;
+ opt_protocol = MYSQL_PROTOCOL_PIPE;
#endif
break;
case '#':
@@ -234,6 +247,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
charsets_dir = argument;
#endif
break;
+ case OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
}
if (error)
{
@@ -284,6 +306,12 @@ int main(int argc,char *argv[])
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#endif
+ if (opt_protocol)
+ mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
if (sql_connect(&mysql, option_wait))
error = 1;
else
@@ -326,6 +354,9 @@ int main(int argc,char *argv[])
}
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
my_free(user,MYF(MY_ALLOW_ZERO_PTR));
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
free_defaults(save_argv);
my_end(0);
exit(error ? 1 : 0);
@@ -386,7 +417,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
wait--; /* One less retry */
if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) &&
(mysql_errno(mysql) != CR_CONNECTION_ERROR))
- {
+ {
fprintf(stderr,"Got error: %s\n", mysql_error(mysql));
if (!option_force)
return 1;
@@ -401,7 +432,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
}
else
{
- putc('.',stderr);
+ putc('.',stderr);
(void) fflush(stderr);
}
}
@@ -419,6 +450,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
const char *status;
+ struct rand_struct rand_st;
for (; argc > 0 ; argv++,argc--)
{
@@ -630,7 +662,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
MYSQL_RES *res;
MYSQL_ROW row;
uint rownr = 0;
- void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
+ void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
new_line = 1;
if (mysql_query(mysql, "show status") ||
@@ -722,9 +754,14 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
break;
}
+ case ADMIN_OLD_PASSWORD:
case ADMIN_PASSWORD:
{
- char buff[128],crypted_pw[33];
+ char buff[128],crypted_pw[64];
+ time_t start_time;
+ /* Do initialization the same way as we do in mysqld */
+ start_time=time((time_t*) 0);
+ randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
if (argc < 2)
{
@@ -732,7 +769,9 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 1;
}
if (argv[1][0])
- make_scrambled_password(crypted_pw,argv[1]);
+ make_scrambled_password(crypted_pw,argv[1],
+ (find_type(argv[0], &command_typelib, 2) ==
+ ADMIN_OLD_PASSWORD), &rand_st);
else
crypted_pw[0]=0; /* No password */
sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw);
@@ -837,7 +876,8 @@ static void usage(void)
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
- password new-password Change old password to new-password");
+ password new-password Change old password to new-password, MySQL 4.1 hashing.\n\
+ old-password new-password Change old password to new-password in old format.\n");
#endif
puts("\
ping Check if mysqld is alive\n\
@@ -995,7 +1035,7 @@ static void print_relative_row_vert(MYSQL_RES *result __attribute__((unused)),
putchar('|');
tmp = cur[1] ? strtoull(cur[1], NULL, 10) : (ulonglong) 0;
- printf(" %-*s|", ex_val_max_len[row] + 1,
+ printf(" %-*s|", ex_val_max_len[row] + 1,
llstr((tmp - last_values[row]), buff));
/* Find the minimum row length needed to output the relative value */
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 4cf86eb31c7..83c93ee3fca 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -18,6 +18,7 @@
#undef MYSQL_SERVER
#include "client_priv.h"
#include <time.h>
+#include <assert.h>
#include "log_event.h"
#define BIN_LOG_HEADER_SIZE 4
@@ -56,6 +57,9 @@ static short binlog_flags = 0;
static MYSQL* mysql = NULL;
static const char* table = 0;
+static bool use_local_load= 0;
+static const char* dirname_for_local_load= 0;
+
static void dump_local_log_entries(const char* logname);
static void dump_remote_log_entries(const char* logname);
static void dump_log_entries(const char* logname);
@@ -64,6 +68,128 @@ static void dump_remote_table(NET* net, const char* db, const char* table);
static void die(const char* fmt, ...);
static MYSQL* safe_connect();
+class Load_log_processor
+{
+ char target_dir_name[MY_NFILE];
+ int target_dir_name_len;
+ DYNAMIC_ARRAY file_names;
+
+ const char* create_file(Create_file_log_event *ce)
+ {
+ const char *bname= ce->fname + ce->fname_len -1;
+ while (bname>ce->fname && bname[-1]!=FN_LIBCHAR)
+ bname--;
+
+ uint blen= ce->fname_len - (bname-ce->fname);
+ uint full_len= target_dir_name_len + blen;
+ char *tmp;
+ if (!(tmp= my_malloc(full_len + 9 + 1,MYF(MY_WME))) ||
+ set_dynamic(&file_names,(gptr)&ce,ce->file_id))
+ {
+ die("Could not construct local filename %s%s",target_dir_name,bname);
+ return 0;
+ }
+
+ char *ptr= tmp;
+ memcpy(ptr,target_dir_name,target_dir_name_len);
+ ptr+= target_dir_name_len;
+ memcpy(ptr,bname,blen);
+ ptr+= blen;
+ sprintf(ptr,"-%08x",ce->file_id);
+
+ ce->set_fname_outside_temp_buf(tmp,full_len);
+
+ return tmp;
+ }
+
+ void append_to_file(const char* fname, int flags,
+ gptr data, uint size)
+ {
+ File file;
+ if ((file= my_open(fname,flags,MYF(MY_WME)) < 0) ||
+ my_write(file,(byte*) data,size,MYF(MY_WME|MY_NABP)) ||
+ my_close(file,MYF(MY_WME)))
+ exit(1);
+ }
+
+public:
+
+ Load_log_processor()
+ {
+ init_dynamic_array(&file_names,sizeof(Create_file_log_event*),
+ 100,100 CALLER_INFO);
+ }
+
+ ~Load_log_processor()
+ {
+ destroy();
+ delete_dynamic(&file_names);
+ }
+
+ void init_by_dir_name(const char *atarget_dir_name)
+ {
+ char *end= strmov(target_dir_name,atarget_dir_name);
+ if (end[-1]!=FN_LIBCHAR)
+ *end++= FN_LIBCHAR;
+ target_dir_name_len= end-target_dir_name;
+ }
+ void init_by_file_name(const char *file_name)
+ {
+ int len= strlen(file_name);
+ const char *end= file_name + len - 1;
+ while (end>file_name && *end!=FN_LIBCHAR)
+ end--;
+ if (*end!=FN_LIBCHAR)
+ target_dir_name_len= 0;
+ else
+ {
+ target_dir_name_len= end - file_name + 1;
+ memmove(target_dir_name,file_name,target_dir_name_len);
+ }
+ }
+ void init_by_cur_dir()
+ {
+ target_dir_name_len= 0;
+ }
+ void destroy()
+ {
+ Create_file_log_event **ptr= (Create_file_log_event**)file_names.buffer;
+ Create_file_log_event **end= ptr + file_names.elements;
+ for (; ptr<end; ptr++)
+ {
+ if (*ptr)
+ {
+ my_free((char*)(*ptr)->fname,MYF(MY_WME));
+ delete *ptr;
+ *ptr= 0;
+ }
+ }
+ }
+ Create_file_log_event *grab_event(uint file_id)
+ {
+ Create_file_log_event **ptr=
+ (Create_file_log_event**)file_names.buffer + file_id;
+ Create_file_log_event *res= *ptr;
+ *ptr= 0;
+ return res;
+ }
+ void process(Create_file_log_event *ce)
+ {
+ const char *fname= create_file(ce);
+ append_to_file(fname,O_CREAT|O_BINARY,ce->block,ce->block_len);
+ }
+ void process(Append_block_log_event *ae)
+ {
+ if (ae->file_id >= file_names.elements)
+ die("Skiped CreateFile event for file_id: %u",ae->file_id);
+ Create_file_log_event* ce=
+ *((Create_file_log_event**)file_names.buffer + ae->file_id);
+ append_to_file(ce->fname,O_APPEND|O_BINARY,ae->block,ae->block_len);
+ }
+};
+
+Load_log_processor load_processor;
+
static struct my_option my_long_options[] =
{
#ifndef DBUG_OFF
@@ -97,6 +223,9 @@ static struct my_option my_long_options[] =
{"user", 'u', "Connect to the remote server as username",
(gptr*) &user, (gptr*) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
0, 0},
+ {"local-load", 'l', "Prepare files for local load in directory",
+ (gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0,
+ GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
@@ -209,6 +338,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'V':
print_version();
exit(0);
+ case 'l':
+ use_local_load= 1;
+ break;
case '?':
usage();
exit(0);
@@ -420,6 +552,8 @@ static void dump_local_log_entries(const char* logname)
MYF(MY_WME | MY_NABP)))
exit(1);
old_format = check_header(file);
+ if (use_local_load && !dirname_for_local_load)
+ load_processor.init_by_file_name(logname);
}
else
{
@@ -441,6 +575,8 @@ static void dump_local_log_entries(const char* logname)
}
file->pos_in_file=position;
file->seek_not_done=0;
+ if (use_local_load && !dirname_for_local_load)
+ load_processor.init_by_cur_dir();
}
if (!position)
@@ -495,11 +631,43 @@ Could not read entry at offset %s : Error in log format or read error",
}
if (!short_form)
fprintf(result_file, "# at %s\n",llstr(old_off,llbuff));
-
- ev->print(result_file, short_form, last_db);
+
+ if (!use_local_load)
+ ev->print(result_file, short_form, last_db);
+ else
+ {
+ switch(ev->get_type_code())
+ {
+ case CREATE_FILE_EVENT:
+ {
+ Create_file_log_event* ce= (Create_file_log_event*)ev;
+ ce->print(result_file, short_form, last_db,true);
+ load_processor.process(ce);
+ ev= 0;
+ break;
+ }
+ case APPEND_BLOCK_EVENT:
+ ev->print(result_file, short_form, last_db);
+ load_processor.process((Append_block_log_event*)ev);
+ break;
+ case EXEC_LOAD_EVENT:
+ {
+ ev->print(result_file, short_form, last_db);
+ Execute_load_log_event *exv= (Execute_load_log_event*)ev;
+ Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
+ ce->print(result_file, short_form, last_db,true);
+ my_free((char*)ce->fname,MYF(MY_WME));
+ delete ce;
+ break;
+ }
+ default:
+ ev->print(result_file, short_form, last_db);
+ }
+ }
}
rec_count++;
- delete ev;
+ if (ev)
+ delete ev;
}
if (fd >= 0)
my_close(fd, MYF(MY_WME));
@@ -520,6 +688,8 @@ int main(int argc, char** argv)
if (use_remote)
mysql = safe_connect();
+ if (dirname_for_local_load)
+ load_processor.init_by_dir_name(dirname_for_local_load);
if (table)
{
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 3261ec1577d..cd67a2c7522 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -41,6 +41,10 @@ static char *opt_password = 0, *current_user = 0, *default_charset = 0,
*current_host = 0;
static int first_error = 0;
DYNAMIC_ARRAY tables4repair;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=0;
+#endif
+static uint opt_protocol=0;
enum operations {DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE};
@@ -109,6 +113,8 @@ static struct my_option my_long_options[] =
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"quick", 'q',
"If you are using this option with CHECK TABLE, it prevents the check from scanning the rows to check for wrong links. This is the fastest check. If you are using this option with REPAIR TABLE, it will try to repair only the index tree. This is the fastest repair method for a table.",
(gptr*) &opt_quick, (gptr*) &opt_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
@@ -116,6 +122,11 @@ static struct my_option my_long_options[] =
{"repair", 'r',
"Can fix almost anything except unique keys that aren't unique.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"silent", 's', "Print only error messages.", (gptr*) &opt_silent,
(gptr*) &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
@@ -238,7 +249,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'W':
#ifdef __WIN__
- opt_mysql_unix_port = MYSQL_NAMEDPIPE;
+ opt_protocol = MYSQL_PROTOCOL_PIPE;
#endif
break;
case '#':
@@ -252,6 +263,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
verbose++;
break;
case 'V': print_version(); exit(0);
+ case OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
}
return 0;
}
@@ -582,6 +602,12 @@ static int dbConnect(char *host, char *user, char *passwd)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#endif
+ if (opt_protocol)
+ mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
{
@@ -669,6 +695,9 @@ int main(int argc, char **argv)
if (opt_auto_repair)
delete_dynamic(&tables4repair);
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
my_end(0);
return(first_error!=0);
} /* main */
diff --git a/client/mysqldump.c b/client/mysqldump.c
index da02c49dd69..908bdc5b51e 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -36,7 +36,7 @@
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
*/
-#define DUMP_VERSION "9.07"
+#define DUMP_VERSION "10.0"
#include <my_global.h>
#include <my_sys.h>
@@ -69,27 +69,45 @@
static char *add_load_option(char *ptr, const char *object,
const char *statement);
+static ulong find_set(TYPELIB *lib, const char *x, uint length,
+ char **err_pos, uint *err_len);
static char *field_escape(char *to,const char *from,uint length);
-static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick=0, extended_insert = 0,
- lock_tables=0,ignore_errors=0,flush_logs=0,replace=0,
- ignore=0,opt_drop=0,opt_keywords=0,opt_lock=0,opt_compress=0,
- opt_delayed=0,create_options=0,opt_quoted=0,opt_databases=0,
+static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
+ lock_tables=1,ignore_errors=0,flush_logs=0,replace=0,
+ ignore=0,opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
+ opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
opt_alldbs=0,opt_create_db=0,opt_first_slave=0,
- opt_autocommit=0,opt_master_data,opt_disable_keys=0,opt_xml=0,
+ opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
tty_password=0,opt_single_transaction=0;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
*lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
- *where=0, *default_charset;
-static uint opt_mysql_port=0;
+ *where=0, *default_charset, *opt_compatible_mode_str= 0,
+ *err_ptr= 0;
+static ulong opt_compatible_mode= 0;
+static uint opt_mysql_port= 0, err_len= 0;
static my_string opt_mysql_unix_port=0;
static int first_error=0;
extern ulong net_buffer_length;
static DYNAMIC_STRING extended_row;
#include <sslopt-vars.h>
FILE *md_result_file;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=0;
+#endif
+static uint opt_protocol= 0;
+
+const char *compatible_mode_names[]=
+{
+ "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
+ "SAPDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
+ NullS
+};
+TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
+ "", compatible_mode_names};
+
static struct my_option my_long_options[] =
{
@@ -98,13 +116,13 @@ static struct my_option my_long_options[] =
(gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"all", 'a', "Include all MySQL specific create options.",
- (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 0,
+ (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
- (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
+ (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
0},
{"add-locks", OPT_LOCKS, "Add locks around insert statements.",
- (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
+ (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
0},
{"allow-keywords", OPT_KEYWORDS,
"Allow creation of column names that are keywords.", (gptr*) &opt_keywords,
@@ -112,6 +130,10 @@ static struct my_option my_long_options[] =
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory where character sets are", (gptr*) &charsets_dir,
(gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"compatible", OPT_COMPATIBLE,
+ "Change the dump to be compatible with a given mode. By default tables are dumped without any restrictions. Legal modes are: mysql323, mysql40, postgresql, oracle, mssql, db2, sapdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option does a no operation on earlier server versions.",
+ (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"complete-insert", 'c', "Use complete insert statements.", (gptr*) &cFlag,
(gptr*) &cFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
@@ -131,11 +153,11 @@ static struct my_option my_long_options[] =
0, 0},
{"disable-keys", 'K',
"'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (gptr*) &opt_disable_keys,
- (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"extended-insert", 'e',
"Allows utilization of the new, much faster INSERT syntax.",
(gptr*) &extended_insert, (gptr*) &extended_insert, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
+ 1, 0, 0, 0, 0, 0},
{"fields-terminated-by", OPT_FTB,
"Fields in the textfile are terminated by ...", (gptr*) &fields_terminated,
(gptr*) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -164,7 +186,7 @@ static struct my_option my_long_options[] =
(gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
- (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"master-data", OPT_MASTER_DATA,
"This will cause the master position and filename to be appended to your output. This will automagically enable --first-slave.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -174,8 +196,8 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"single-transaction", OPT_TRANSACTION,
"Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.",
- (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
+ (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-create-db", 'n',
"'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given.}",
(gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
@@ -188,7 +210,7 @@ static struct my_option my_long_options[] =
"Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"opt", OPT_OPTIMIZE,
- "Same as --add-drop-table --add-locks --all --quick --extended-insert --lock-tables --disable-keys",
+ "Same as --add-drop-table --add-locks --all --quick --extended-insert --lock-tables --disable-keys. Enabled by default, disable with --skip-opt.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
@@ -200,14 +222,24 @@ static struct my_option my_long_options[] =
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
- (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"quote-names",'Q', "Quote table and column names with a `",
(gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"result-file", 'r',
"Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+ {"skip-opt", OPT_SKIP_OPTIMIZATION,
+ "Disable --opt. Disables --add-locks, --all, --quick, --extended-insert, --lock-tables and --disable-keys.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -311,6 +343,7 @@ static void write_header(FILE *sql_file, char *db_name)
return;
} /* write_header */
+
static void write_footer(FILE *sql_file)
{
if (opt_xml)
@@ -318,6 +351,7 @@ static void write_footer(FILE *sql_file)
fputs("\n", sql_file);
} /* write_footer */
+
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -347,7 +381,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'W':
#ifdef __WIN__
- opt_mysql_unix_port=MYSQL_NAMEDPIPE;
+ opt_protocol = MYSQL_PROTOCOL_PIPE;
#endif
break;
case 'T':
@@ -367,18 +401,48 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
usage();
exit(0);
case (int) OPT_OPTIMIZE:
- extended_insert=opt_drop=opt_lock=quick=create_options=opt_disable_keys=
- lock_tables=1;
+ extended_insert= opt_drop= opt_lock= quick= create_options=
+ opt_disable_keys= lock_tables= 1;
if (opt_single_transaction) lock_tables=0;
break;
+ case (int) OPT_SKIP_OPTIMIZATION:
+ extended_insert= opt_drop= opt_lock= quick= create_options=
+ opt_disable_keys= lock_tables= 0;
+ break;
case (int) OPT_TABLES:
opt_databases=0;
break;
+ case (int) OPT_COMPATIBLE:
+ {
+ char buff[255];
+
+ opt_quoted= 1;
+ opt_compatible_mode_str= argument;
+ opt_compatible_mode= find_set(&compatible_mode_typelib,
+ argument, strlen(argument),
+ &err_ptr, &err_len);
+ if (err_len)
+ {
+ strmake(buff, err_ptr, min(sizeof(buff), err_len));
+ fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
+ exit(1);
+ }
+ break;
+ }
+ case (int) OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol= find_type(argument, &sql_protocol_typelib, 0))
+ == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
}
return 0;
}
-
static int get_options(int *argc, char ***argv)
{
int ho_error;
@@ -398,13 +462,8 @@ static int get_options(int *argc, char ***argv)
"%s: You must use option --tab with --fields-...\n", my_progname);
return(1);
}
-
- if (opt_single_transaction && lock_tables)
- {
- fprintf(stderr, "%s: You can't use --lock-tables and --single-transaction at the same time.\n", my_progname);
- return(1);
- }
-
+ if (opt_single_transaction)
+ lock_tables= 0;
if (enclosed && opt_enclosed)
{
fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
@@ -483,6 +542,12 @@ static int dbConnect(char *host, char *user,char *passwd)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#endif
+ if (opt_protocol)
+ mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
NULL,opt_mysql_port,opt_mysql_unix_port,
0)))
@@ -527,7 +592,7 @@ static my_bool test_if_special_chars(const char *str)
{
#if MYSQL_VERSION_ID >= 32300
for ( ; *str ; str++)
- if (!isvar(*str) && *str != '$')
+ if (!my_isvar(system_charset_info,*str) && *str != '$')
return 1;
#endif
return 0;
@@ -578,6 +643,31 @@ static uint getTableStructure(char *table, char* db)
/* Make an sql-file, if path was given iow. option -T was given */
char buff[20+FN_REFLEN];
+ if (opt_compatible_mode)
+ {
+ char *end;
+ uint i;
+
+ sprintf(buff, "/*!41000 SET @@sql_mode=\"");
+ end= strend(buff);
+ for (i= 0; opt_compatible_mode; opt_compatible_mode>>= 1, i++)
+ {
+ if (opt_compatible_mode & 1)
+ {
+ end= strmov(end, compatible_mode_names[i]);
+ end= strmov(end, ",");
+ }
+ }
+ end= strmov(--end, "\" */");
+ if (mysql_query(sock, buff))
+ {
+ fprintf(stderr, "%s: Can't set the compatible mode '%s' (%s)\n",
+ my_progname, table, mysql_error(sock));
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+ }
+
sprintf(buff,"show create table `%s`",table);
if (mysql_query(sock, buff))
{
@@ -1045,7 +1135,8 @@ static void dumpTable(uint numFields, char *table)
/* change any strings ("inf","nan",..) into NULL */
char *ptr = row[i];
dynstr_append(&extended_row,
- (!isalpha(*ptr)) ? ptr : "NULL");
+ (!my_isalpha(system_charset_info,*ptr)) ?
+ ptr : "NULL");
}
}
else
@@ -1077,9 +1168,11 @@ static void dumpTable(uint numFields, char *table)
char *ptr = row[i];
if (opt_xml)
fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n",
- field->name,!isalpha(*ptr) ?ptr: "NULL");
+ field->name,
+ !my_isalpha(system_charset_info, *ptr) ? ptr: "NULL");
else
- fputs((!isalpha(*ptr)) ? ptr : "NULL", md_result_file);
+ fputs((!my_isalpha(system_charset_info,*ptr)) ?
+ ptr : "NULL", md_result_file);
}
}
else
@@ -1248,8 +1341,28 @@ static int init_dumping(char *database)
{
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", database);
if (!opt_create_db)
- fprintf(md_result_file,"\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
+ {
+ char qbuf[128];
+ MYSQL_ROW row;
+ MYSQL_RES *dbinfo;
+
+ sprintf(qbuf,"SHOW CREATE DATABASE WITH IF NOT EXISTS %s",database);
+
+ if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
+ {
+ /* Old server version, dump generic CREATE DATABASE */
+ fprintf(md_result_file,"\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
database);
+ }
+ else
+ {
+ row = mysql_fetch_row(dbinfo);
+ if (row[1])
+ {
+ fprintf(md_result_file,"\n%s;\n",row[1]);
+ }
+ }
+ }
fprintf(md_result_file,"\nUSE %s;\n", database);
}
}
@@ -1350,6 +1463,48 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
} /* dump_selected_tables */
+
+static ulong find_set(TYPELIB *lib, const char *x, uint length,
+ char **err_pos, uint *err_len)
+{
+ const char *end= x + length;
+ ulong found= 0;
+ uint find;
+ char buff[255];
+
+ *err_pos= 0; // No error yet
+ while (end > x && my_isspace(system_charset_info, end[-1]))
+ end--;
+
+ *err_len= 0;
+ if (x != end)
+ {
+ const char *start= x;
+ for (;;)
+ {
+ const char *pos= start;
+ uint var_len;
+
+ for (; pos != end && *pos != ','; pos++) ;
+ var_len= (uint) (pos - start);
+ strmake(buff, start, min(sizeof(buff), var_len));
+ find= find_type(buff, lib, var_len);
+ if (!find)
+ {
+ *err_pos= (char*) start;
+ *err_len= var_len;
+ }
+ else
+ found|= ((longlong) 1 << (find - 1));
+ if (pos == end)
+ break;
+ start= pos + 1;
+ }
+ }
+ return found;
+}
+
+
/* Print a value with a prefix on file */
static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
const char *prefix, const char *name,
@@ -1460,6 +1615,9 @@ int main(int argc, char **argv)
MYF(0), mysql_error(sock));
}
else if (opt_single_transaction) /* Just to make it beautiful enough */
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
{
/*
In case we were locking all tables, we did not start transaction
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index a11b7383517..408a5873589 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -49,6 +49,11 @@ static my_string opt_mysql_unix_port=0;
static my_string opt_ignore_lines=0;
#include <sslopt-vars.h>
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=0;
+#endif
+static uint opt_protocol=0;
+
static struct my_option my_long_options[] =
{
{"character-sets-dir", OPT_CHARSETS_DIR,
@@ -112,8 +117,15 @@ static struct my_option my_long_options[] =
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"replace", 'r', "If duplicate unique key was found, replace old row.",
(gptr*) &replace, (gptr*) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"silent", 's', "Be more silent.", (gptr*) &silent, (gptr*) &silent, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
@@ -181,10 +193,19 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
#ifdef __WIN__
case 'W':
- opt_mysql_unix_port=MYSQL_NAMEDPIPE;
+ opt_protocol = MYSQL_PROTOCOL_PIPE;
opt_local_file=1;
break;
#endif
+ case OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
case '#':
DBUG_PUSH(argument ? argument : "d:t:o");
break;
@@ -352,6 +373,12 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#endif
+ if (opt_protocol)
+ mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
database,opt_mysql_port,opt_mysql_unix_port,
0)))
@@ -486,6 +513,9 @@ int main(int argc, char **argv)
exitcode = error;
db_disconnect(current_host, sock);
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
free_defaults(argv_to_free);
my_end(0);
return(exitcode);
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 0b47e06534f..e6e21f177ef 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -31,6 +31,11 @@ static my_string host=0,opt_password=0,user=0;
static my_bool opt_show_keys=0,opt_compress=0,opt_status=0, tty_password=0;
static uint opt_verbose=0;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=0;
+#endif
+static uint opt_protocol=0;
+
static void get_options(int *argc,char ***argv);
static uint opt_mysql_port=0;
static int list_dbs(MYSQL *mysql,const char *wild);
@@ -104,6 +109,12 @@ int main(int argc, char **argv)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#endif
+ if (opt_protocol)
+ mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
if (!(mysql_real_connect(&mysql,host,user,opt_password,
(first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port,
0)))
@@ -131,6 +142,9 @@ int main(int argc, char **argv)
mysql_close(&mysql); /* Close & free connection */
if (opt_password)
my_free(opt_password,MYF(0));
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
my_end(0);
exit(error ? 1 : 0);
return 0; /* No compiler warnings */
@@ -165,6 +179,13 @@ static struct my_option my_long_options[] =
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -230,9 +251,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'W':
#ifdef __WIN__
- opt_mysql_unix_port=MYSQL_NAMEDPIPE;
+ opt_protocol = MYSQL_PROTOCOL_PIPE;
#endif
break;
+ case OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
case '#':
DBUG_PUSH(argument ? argument : "d:t:o");
break;
diff --git a/client/mysqltest.c b/client/mysqltest.c
index cad13fe1349..f417018dbb7 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -166,7 +166,8 @@ typedef struct
VAR var_reg[10];
/*Perl/shell-like variable registers */
HASH var_hash;
-int disable_query_log=0, disable_result_log=0;
+my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0;
+my_bool disable_info= 1; /* By default off */
struct connection cons[MAX_CONS];
struct connection* cur_con, *next_con, *cons_end;
@@ -195,6 +196,8 @@ Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_WAIT_FOR_SLAVE_TO_STOP,
Q_REQUIRE_VERSION,
+Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
+Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND
@@ -253,6 +256,10 @@ const char *command_names[]=
"require_manager",
"wait_for_slave_to_stop",
"require_version",
+ "enable_warnings",
+ "disable_warnings",
+ "enable_info",
+ "diable_info",
0
};
@@ -311,7 +318,7 @@ static int eval_result = 0;
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
-int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
+my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
#define MAX_SERVER_ARGS 20
@@ -482,9 +489,9 @@ void init_parser()
int hex_val(int c)
{
- if (isdigit(c))
+ if (my_isdigit(system_charset_info,c))
return c - '0';
- else if ((c = tolower(c)) >= 'a' && c <= 'f')
+ else if ((c = my_tolower(system_charset_info,c)) >= 'a' && c <= 'f')
return c - 'a' + 10;
else
return -1;
@@ -594,7 +601,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
{
const char* save_var_name = var_name, *end;
end = (var_name_end) ? *var_name_end : 0;
- while (isvar(*var_name) && var_name != end)
+ while (my_isvar(system_charset_info,*var_name) && var_name != end)
++var_name;
if (var_name == save_var_name)
{
@@ -745,7 +752,7 @@ int do_server_op(struct st_query* q,const char* op)
com_p=strmov(com_p,"_exec ");
if (!*p)
die("Missing server name in server_%s\n",op);
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(system_charset_info,*p))
{
*com_p++=*p++;
}
@@ -778,7 +785,7 @@ int do_require_version(struct st_query* q)
if (!*p)
die("Missing version argument in require_version\n");
ver_arg = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
ver_arg_len = p - ver_arg;
@@ -808,7 +815,7 @@ int do_source(struct st_query* q)
if (!*p)
die("Missing file name in source\n");
name = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
@@ -1045,11 +1052,11 @@ int do_let(struct st_query* q)
if (!*p)
die("Missing variable name in let\n");
var_name = p;
- while (*p && (*p != '=' || isspace(*p)))
+ while (*p && (*p != '=' || my_isspace(system_charset_info,*p)))
p++;
var_name_end = p;
if (*p == '=') p++;
- while (*p && isspace(*p))
+ while (*p && my_isspace(system_charset_info,*p))
p++;
var_val_start = p;
return var_set(var_name, var_name_end, var_val_start, q->end);
@@ -1078,8 +1085,8 @@ int do_disable_rpl_parse(struct st_query* q __attribute__((unused)))
int do_sleep(struct st_query* q, my_bool real_sleep)
{
- char* p=q->first_argument;
- while (*p && isspace(*p))
+ char *p=q->first_argument;
+ while (*p && my_isspace(system_charset_info,*p))
p++;
if (!*p)
die("Missing argument in sleep\n");
@@ -1095,7 +1102,7 @@ static void get_file_name(char *filename, struct st_query* q)
char* p=q->first_argument;
strnmov(filename, p, FN_REFLEN);
/* Remove end space */
- while (p > filename && isspace(p[-1]))
+ while (p > filename && my_isspace(system_charset_info,p[-1]))
p--;
p[0]=0;
}
@@ -1181,7 +1188,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
if (*from != ' ' && *from)
die("Wrong string argument in %s\n", q->query);
- while (isspace(*from)) /* Point to next string */
+ while (my_isspace(system_charset_info,*from)) /* Point to next string */
from++;
*to =0; /* End of string marker */
@@ -1238,8 +1245,8 @@ static void get_replace(struct st_query *q)
insert_pointer_name(&to_array,to);
}
for (i=1,pos=word_end_chars ; i < 256 ; i++)
- if (isspace(i))
- *pos++=i;
+ if (my_isspace(system_charset_info,i))
+ *pos++= i;
*pos=0; /* End pointer */
if (!(glob_replace=init_replace((char**) from_array.typelib.type_names,
(char**) to_array.typelib.type_names,
@@ -1275,7 +1282,7 @@ int select_connection(char *p)
if (!*p)
die("Missing connection name in connect\n");
name = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
@@ -1301,7 +1308,7 @@ int close_connection(struct st_query* q)
if (!*p)
die("Missing connection name in connect\n");
name = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
@@ -1309,6 +1316,7 @@ int close_connection(struct st_query* q)
{
if (!strcmp(con->name, name))
{
+#ifndef EMBEDDED_LIBRARY
if (q->type == Q_DIRTY_CLOSE)
{
if (con->mysql.net.vio)
@@ -1317,7 +1325,7 @@ int close_connection(struct st_query* q)
con->mysql.net.vio = 0;
}
}
-
+#endif
mysql_close(&con->mysql);
DBUG_RETURN(0);
}
@@ -1337,11 +1345,13 @@ int close_connection(struct st_query* q)
char* safe_get_param(char* str, char** arg, const char* msg)
{
DBUG_ENTER("safe_get_param");
- while (*str && isspace(*str)) str++;
+ while (*str && my_isspace(system_charset_info,*str))
+ str++;
*arg = str;
for (; *str && *str != ',' && *str != ')' ; str++)
{
- if (isspace(*str)) *str = 0;
+ if (my_isspace(system_charset_info,*str))
+ *str = 0;
}
if (!*str)
die(msg);
@@ -1623,7 +1633,7 @@ int read_line(char* buf, int size)
{
state = R_COMMENT;
}
- else if (isspace(c))
+ else if (my_isspace(system_charset_info,c))
{
if (c == '\n')
start_lineno= ++*lineno; /* Query hasn't started yet */
@@ -1749,7 +1759,7 @@ int read_query(struct st_query** q_ptr)
{
expected_errno = 0;
p++;
- for (;isdigit(*p);p++)
+ for (;my_isdigit(system_charset_info,*p);p++)
expected_errno = expected_errno * 10 + *p - '0';
q->expected_errno[0] = expected_errno;
q->expected_errno[1] = 0;
@@ -1757,25 +1767,28 @@ int read_query(struct st_query** q_ptr)
}
}
- while (*p && isspace(*p)) p++ ;
+ while (*p && my_isspace(system_charset_info,*p))
+ p++ ;
if (*p == '@')
{
p++;
p1 = q->record_file;
- while (!isspace(*p) &&
+ while (!my_isspace(system_charset_info,*p) &&
p1 < q->record_file + sizeof(q->record_file) - 1)
*p1++ = *p++;
*p1 = 0;
}
}
- while (*p && isspace(*p)) p++;
+ while (*p && my_isspace(system_charset_info,*p))
+ p++;
if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME))))
die(NullS);
/* Calculate first word and first argument */
- for (p=q->query; *p && !isspace(*p) ; p++) ;
+ for (p=q->query; *p && !my_isspace(system_charset_info,*p) ; p++) ;
q->first_word_len = (uint) (p - q->query);
- while (*p && isspace(*p)) p++;
+ while (*p && my_isspace(system_charset_info,*p))
+ p++;
q->first_argument=p;
q->end = strend(q->query);
parser.read_lines++;
@@ -2024,6 +2037,36 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
dynstr_append_mem(ds, val, len);
}
+/*
+ Append all results to the dynamic string separated with '\t'
+*/
+
+static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
+{
+ MYSQL_ROW row;
+ int num_fields= mysql_num_fields(res);
+ unsigned long *lengths;
+ while ((row = mysql_fetch_row(res)))
+ {
+ int i;
+ lengths = mysql_fetch_lengths(res);
+ for (i = 0; i < num_fields; i++)
+ {
+ const char *val= row[i];
+ ulonglong len= lengths[i];
+ if (!val)
+ {
+ val = "NULL";
+ len = 4;
+ }
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
+ }
+ dynstr_append_mem(ds, "\n", 1);
+ }
+}
+
/*
* flags control the phased/stages of query execution to be performed
@@ -2034,12 +2077,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
MYSQL_RES* res = 0;
- MYSQL_FIELD* fields;
- MYSQL_ROW row;
- int num_fields,i, error = 0;
- unsigned long* lengths;
- char* val;
- int len;
+ int i, error = 0;
DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_tmp;
DYNAMIC_STRING eval_query;
@@ -2127,17 +2165,17 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
mysql_error(mysql));
/*
- if we do not abort on error, failure to run the query does
- not fail the whole test case
+ if we do not abort on error, failure to run the query does
+ not fail the whole test case
*/
goto end;
}
/*{
verbose_msg("failed in mysql_store_result for query '%s' (%d)", query,
- mysql_errno(mysql));
+ mysql_errno(mysql));
error = 1;
goto end;
- }*/
+ }*/
}
if (q->expected_errno[0])
@@ -2148,45 +2186,52 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end;
}
- if (!res)
- goto end;
-
if (!disable_result_log)
{
- fields = mysql_fetch_fields(res);
- num_fields = mysql_num_fields(res);
- for (i = 0; i < num_fields; i++)
+ if (res)
{
- if (i)
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append(ds, fields[i].name);
- }
-
- dynstr_append_mem(ds, "\n", 1);
-
- while ((row = mysql_fetch_row(res)))
- {
- lengths = mysql_fetch_lengths(res);
+ int num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
for (i = 0; i < num_fields; i++)
{
- val = (char*)row[i];
- len = lengths[i];
-
- if (!val)
- {
- val = (char*)"NULL";
- len = 4;
- }
-
if (i)
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ dynstr_append(ds, fields[i].name);
+ }
+ dynstr_append_mem(ds, "\n", 1);
+ append_result(ds, res);
+ }
+
+ /* Add all warnings to the result */
+ if (!disable_warnings && mysql_warning_count(mysql))
+ {
+ MYSQL_RES *warn_res=0;
+ uint count= mysql_warning_count(mysql);
+ if (!mysql_real_query(mysql, "SHOW WARNINGS", 13))
+ {
+ warn_res=mysql_store_result(mysql);
}
+ if (!warn_res)
+ verbose_msg("Warning count is %u but didn't get any warnings\n",
+ count);
+ else
+ {
+ dynstr_append_mem(ds, "Warnings:\n", 10);
+ append_result(ds, warn_res);
+ mysql_free_result(warn_res);
+ }
+ }
+ if (!disable_info && mysql_info(mysql))
+ {
+ dynstr_append(ds, "info: ");
+ dynstr_append(ds, mysql_info(mysql));
dynstr_append_mem(ds, "\n", 1);
}
- if (glob_replace)
- free_replace();
}
+
+ if (glob_replace)
+ free_replace();
+
if (record)
{
if (!q->record_file[0] && !result_file)
@@ -2298,7 +2343,8 @@ static void init_var_hash()
{
VAR* v;
DBUG_ENTER("init_var_hash");
- if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
+ if (hash_init(&var_hash, system_charset_info,
+ 1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
var_from_env("MASTER_MYPORT", "9306");
var_from_env("SLAVE_MYPORT", "9307");
@@ -2391,6 +2437,10 @@ int main(int argc, char** argv)
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_RESULT_LOG: disable_result_log=0; break;
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
+ case Q_ENABLE_WARNINGS: disable_warnings=0; break;
+ case Q_DISABLE_WARNINGS: disable_warnings=1; break;
+ case Q_ENABLE_INFO: disable_info=0; break;
+ case Q_DISABLE_INFO: disable_info=1; break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q, 0); break;
case Q_REAL_SLEEP: do_sleep(q, 1); break;
diff --git a/client/select_test.c b/client/select_test.c
index ee2a9192865..d7f18c0f1f0 100644
--- a/client/select_test.c
+++ b/client/select_test.c
@@ -19,6 +19,7 @@
#endif
#include <stdio.h>
#include <stdlib.h>
+#include "my_global.h"
#include "mysql.h"
#define SELECT_QUERY "select name from test where num = %d"
diff --git a/client/sql_string.cc b/client/sql_string.cc
index 3c5e481eaad..8ab205d9fb1 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -40,19 +40,16 @@ extern void sql_element_free(void *ptr);
bool String::real_alloc(uint32 arg_length)
{
arg_length=ALIGN_SIZE(arg_length+1);
+ str_length=0;
if (Alloced_length < arg_length)
{
free();
if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
- {
- str_length=0;
return TRUE;
- }
Alloced_length=arg_length;
alloced=1;
}
Ptr[0]=0;
- str_length=0;
return FALSE;
}
@@ -94,36 +91,58 @@ bool String::realloc(uint32 alloc_length)
return FALSE;
}
-bool String::set(longlong num)
+bool String::set(longlong num, CHARSET_INFO *cs)
{
- if (alloc(21))
+ uint l=20*cs->mbmaxlen+1;
+
+ if (alloc(l))
return TRUE;
- str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
+ if (cs->snprintf == my_snprintf_8bit)
+ {
+ str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
+ }
+ else
+ {
+ str_length=cs->snprintf(cs,Ptr,l,"%d",num);
+ }
+ str_charset=cs;
return FALSE;
}
-bool String::set(ulonglong num)
+bool String::set(ulonglong num, CHARSET_INFO *cs)
{
- if (alloc(21))
+ uint l=20*cs->mbmaxlen+1;
+
+ if (alloc(l))
return TRUE;
- str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
+ if (cs->snprintf == my_snprintf_8bit)
+ {
+ str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
+ }
+ else
+ {
+ str_length=cs->snprintf(cs,Ptr,l,"%d",num);
+ }
+ str_charset=cs;
return FALSE;
}
-bool String::set(double num,uint decimals)
+bool String::set(double num,uint decimals, CHARSET_INFO *cs)
{
char buff[331];
+
+ str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
sprintf(buff,"%.14g",num); // Enough for a DATETIME
- return copy(buff, (uint32) strlen(buff));
+ return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
char *pos,*to;
VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
- if (!isdigit(buff[1]))
+ if (!my_isdigit(&my_charset_latin1, buff[1]))
{ // Nan or Inf
pos=buff+1;
if (sign)
@@ -131,7 +150,7 @@ bool String::set(double num,uint decimals)
buff[0]='-';
pos=buff;
}
- return copy(pos,(uint32) strlen(pos));
+ return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs);
}
if (alloc((uint32) ((uint32) decpt+3+decimals)))
return TRUE;
@@ -181,7 +200,7 @@ end:
#else
sprintf(buff,"%.*f",(int) decimals,num);
#endif
- return copy(buff,(uint32) strlen(buff));
+ return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs);
#endif
}
@@ -203,16 +222,67 @@ bool String::copy(const String &str)
str_length=str.str_length;
bmove(Ptr,str.Ptr,str_length); // May be overlapping
Ptr[str_length]=0;
+ str_charset=str.str_charset;
return FALSE;
}
-bool String::copy(const char *str,uint32 arg_length)
+bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
{
if (alloc(arg_length))
return TRUE;
if ((str_length=arg_length))
memcpy(Ptr,str,arg_length);
Ptr[arg_length]=0;
+ str_charset=cs;
+ return FALSE;
+}
+
+/* Copy with charset convertion */
+bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to)
+{
+ uint32 new_length=to->mbmaxlen*arg_length;
+ int cnvres;
+ my_wc_t wc;
+ const uchar *s=(const uchar *)str;
+ const uchar *se=s+arg_length;
+ uchar *d, *de;
+
+ if (alloc(new_length))
+ return TRUE;
+
+ d=(uchar *)Ptr;
+ de=d+new_length;
+
+ for (str_length=new_length ; s < se && d < de ; )
+ {
+ if ((cnvres=from->mb_wc(from,&wc,s,se)) > 0 )
+ {
+ s+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILSEQ)
+ {
+ s++;
+ wc='?';
+ }
+ else
+ break;
+
+outp:
+ if((cnvres=to->wc_mb(to,wc,d,de)) >0 )
+ {
+ d+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILUNI && wc!='?')
+ {
+ wc='?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ Ptr[new_length]=0;
+ length((uint32) (d-(uchar *)Ptr));
+ str_charset=to;
return FALSE;
}
@@ -234,7 +304,7 @@ bool String::fill(uint32 max_length,char fill_char)
void String::strip_sp()
{
- while (str_length && isspace(Ptr[str_length-1]))
+ while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
str_length--;
}
@@ -296,10 +366,10 @@ uint32 String::numchars()
register uint32 n=0,mblen;
register const char *mbstr=Ptr;
register const char *end=mbstr+str_length;
- if (use_mb(default_charset_info))
+ if (use_mb(str_charset))
{
while (mbstr < end) {
- if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
+ if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
else ++mbstr;
++n;
}
@@ -316,11 +386,11 @@ int String::charpos(int i,uint32 offset)
register uint32 mblen;
register const char *mbstr=Ptr+offset;
register const char *end=Ptr+str_length;
- if (use_mb(default_charset_info))
+ if (use_mb(str_charset))
{
if (i<=0) return i;
while (i && mbstr < end) {
- if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
+ if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
else ++mbstr;
--i;
}
@@ -361,6 +431,39 @@ skipp:
return -1;
}
+/*
+ Search after a string without regarding to case
+ This needs to be replaced when we have character sets per string
+*/
+
+int String::strstr_case(const String &s,uint32 offset)
+{
+ if (s.length()+offset <= str_length)
+ {
+ if (!s.length())
+ return ((int) offset); // Empty string is always found
+
+ register const char *str = Ptr+offset;
+ register const char *search=s.ptr();
+ const char *end=Ptr+str_length-s.length()+1;
+ const char *search_end=s.ptr()+s.length();
+skipp:
+ while (str != end)
+ {
+ if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
+ {
+ register char *i,*j;
+ i=(char*) str; j=(char*) search+1;
+ while (j != search_end)
+ if (str_charset->sort_order[*i++] !=
+ str_charset->sort_order[*j++])
+ goto skipp;
+ return (int) (str-Ptr) -1;
+ }
+ }
+ }
+ return -1;
+}
/*
** Search string from end. Offset is offset to the end of string
@@ -428,6 +531,44 @@ bool String::replace(uint32 offset,uint32 arg_length,const String &to)
return FALSE;
}
+// added by Holyfoot for "geometry" needs
+int String::reserve(uint32 space_needed, uint32 grow_by)
+{
+ if (Alloced_length < str_length + space_needed)
+ {
+ if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void String::qs_append(const char *str)
+{
+ int len = strlen(str);
+ memcpy(Ptr + str_length, str, len + 1);
+ str_length += len;
+}
+
+void String::qs_append(double d)
+{
+ char *buff = Ptr + str_length;
+ sprintf(buff,"%.14g", d);
+ str_length += strlen(buff);
+}
+
+void String::qs_append(double *d)
+{
+ double ld;
+ float8get(ld, (char*) d);
+ qs_append(ld);
+}
+
+void String::qs_append(const char &c)
+{
+ Ptr[str_length] = c;
+ str_length += sizeof(c);
+}
+
int sortcmp(const String *x,const String *y)
{
@@ -435,28 +576,38 @@ int sortcmp(const String *x,const String *y)
const char *t= y->ptr();
uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
+ if (use_strnxfrm(x->str_charset))
{
#ifndef CMP_ENDSPACE
- while (x_len && isspace(s[x_len-1]))
+ while (x_len && my_isspace(x->str_charset,s[x_len-1]))
x_len--;
- while (y_len && isspace(t[y_len-1]))
+ while (y_len && my_isspace(x->str_charset,t[y_len-1]))
y_len--;
#endif
- return my_strnncoll(default_charset_info,
+ return my_strnncoll(x->str_charset,
(unsigned char *)s,x_len,(unsigned char *)t,y_len);
}
else
{
-#endif /* USE_STRCOLL */
x_len-=len; // For easy end space test
y_len-=len;
- while (len--)
+ if (x->str_charset->sort_order)
{
- if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++])
- return ((int) my_sort_order[(uchar) s[-1]] -
- (int) my_sort_order[(uchar) t[-1]]);
+ while (len--)
+ {
+ if (x->str_charset->sort_order[(uchar) *s++] !=
+ x->str_charset->sort_order[(uchar) *t++])
+ return ((int) x->str_charset->sort_order[(uchar) s[-1]] -
+ (int) x->str_charset->sort_order[(uchar) t[-1]]);
+ }
+ }
+ else
+ {
+ while (len--)
+ {
+ if (*s++ != *t++)
+ return ((int) s[-1] - (int) t[-1]);
+ }
}
#ifndef CMP_ENDSPACE
/* Don't compare end space in strings */
@@ -465,14 +616,14 @@ int sortcmp(const String *x,const String *y)
{
const char *end=t+y_len;
for (; t != end ; t++)
- if (!isspace(*t))
+ if (!my_isspace(x->str_charset,*t))
return -1;
}
else
{
const char *end=s+x_len;
for (; s != end ; s++)
- if (!isspace(*s))
+ if (!my_isspace(x->str_charset,*s))
return 1;
}
return 0;
@@ -480,9 +631,7 @@ int sortcmp(const String *x,const String *y)
#else
return (int) (x_len-y_len);
#endif /* CMP_ENDSPACE */
-#ifdef USE_STRCOLL
}
-#endif
}
@@ -514,240 +663,9 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
return from; // Actually an error
if ((to->str_length=min(from->str_length,from_length)))
memcpy(to->Ptr,from->Ptr,to->str_length);
+ to->str_charset=from->str_charset;
return to;
}
-/* Make it easier to handle different charactersets */
-
-#ifdef USE_MB
-#define INC_PTR(A,B) A+=((use_mb_flag && \
- my_ismbchar(default_charset_info,A,B)) ? \
- my_ismbchar(default_charset_info,A,B) : 1)
-#else
-#define INC_PTR(A,B) A++
-#endif
-
-/*
-** Compare string against string with wildcard
-** 0 if matched
-** -1 if not matched with wildcard
-** 1 if matched with wildcard
-*/
-
-#ifdef LIKE_CMP_TOUPPER
-#define likeconv(A) (uchar) toupper(A)
-#else
-#define likeconv(A) (uchar) my_sort_order[(uchar) (A)]
-#endif
-
-static int wild_case_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,
- char escape)
-{
- int result= -1; // Not found, using wildcards
-#ifdef USE_MB
- bool use_mb_flag=use_mb(default_charset_info);
-#endif
- while (wildstr != wildend)
- {
- while (*wildstr != wild_many && *wildstr != wild_one)
- {
- if (*wildstr == escape && wildstr+1 != wildend)
- wildstr++;
-#ifdef USE_MB
- int l;
- if (use_mb_flag &&
- (l = my_ismbchar(default_charset_info, wildstr, wildend)))
- {
- if (str+l > str_end || memcmp(str, wildstr, l) != 0)
- return 1;
- str += l;
- wildstr += l;
- }
- else
-#endif
- if (str == str_end || likeconv(*wildstr++) != likeconv(*str++))
- return(1); // No match
- if (wildstr == wildend)
- return (str != str_end); // Match if both are at end
- result=1; // Found an anchor char
- }
- if (*wildstr == wild_one)
- {
- do
- {
- if (str == str_end) // Skipp one char if possible
- return (result);
- INC_PTR(str,str_end);
- } while (++wildstr < wildend && *wildstr == wild_one);
- if (wildstr == wildend)
- break;
- }
- if (*wildstr == wild_many)
- { // Found wild_many
- wildstr++;
- /* Remove any '%' and '_' from the wild search string */
- for ( ; wildstr != wildend ; wildstr++)
- {
- if (*wildstr == wild_many)
- continue;
- if (*wildstr == wild_one)
- {
- if (str == str_end)
- return (-1);
- INC_PTR(str,str_end);
- continue;
- }
- break; // Not a wild character
- }
- if (wildstr == wildend)
- return(0); // Ok if wild_many is last
- if (str == str_end)
- return -1;
-
- uchar cmp;
- if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
- cmp= *++wildstr;
-#ifdef USE_MB
- const char* mb = wildstr;
- int mblen;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(default_charset_info, wildstr, wildend);
-#endif
- INC_PTR(wildstr,wildend); // This is compared trough cmp
- cmp=likeconv(cmp);
- do
- {
-#ifdef USE_MB
- if (use_mb_flag)
- {
- for (;;)
- {
- if (str >= str_end)
- return -1;
- if (mblen)
- {
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(default_charset_info, str, str_end) &&
- likeconv(*str) == cmp)
- {
- str++;
- break;
- }
- INC_PTR(str, str_end);
- }
- }
- else
- {
-#endif /* USE_MB */
- while (str != str_end && likeconv(*str) != cmp)
- str++;
- if (str++ == str_end) return (-1);
-#ifdef USE_MB
- }
-#endif
- {
- int tmp=wild_case_compare(str,str_end,wildstr,wildend,escape);
- if (tmp <= 0)
- return (tmp);
- }
- } while (str != str_end && wildstr[0] != wild_many);
- return(-1);
- }
- }
- return (str != str_end ? 1 : 0);
-}
-
-int wild_case_compare(String &match,String &wild, char escape)
-{
- return wild_case_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape);
-}
-/*
-** The following is used when using LIKE on binary strings
-*/
-
-static int wild_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape)
-{
- int result= -1; // Not found, using wildcards
- while (wildstr != wildend)
- {
- while (*wildstr != wild_many && *wildstr != wild_one)
- {
- if (*wildstr == escape && wildstr+1 != wildend)
- wildstr++;
- if (str == str_end || *wildstr++ != *str++)
- return(1);
- if (wildstr == wildend)
- return (str != str_end); // Match if both are at end
- result=1; // Found an anchor char
- }
- if (*wildstr == wild_one)
- {
- do
- {
- if (str == str_end) // Skipp one char if possible
- return (result);
- str++;
- } while (*++wildstr == wild_one && wildstr != wildend);
- if (wildstr == wildend)
- break;
- }
- if (*wildstr == wild_many)
- { // Found wild_many
- wildstr++;
- /* Remove any '%' and '_' from the wild search string */
- for ( ; wildstr != wildend ; wildstr++)
- {
- if (*wildstr == wild_many)
- continue;
- if (*wildstr == wild_one)
- {
- if (str == str_end)
- return (-1);
- str++;
- continue;
- }
- break; // Not a wild character
- }
- if (wildstr == wildend)
- return(0); // Ok if wild_many is last
- if (str == str_end)
- return -1;
-
- char cmp;
- if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
- cmp= *++wildstr;
- wildstr++; // This is compared trough cmp
- do
- {
- while (str != str_end && *str != cmp)
- str++;
- if (str++ == str_end) return (-1);
- {
- int tmp=wild_compare(str,str_end,wildstr,wildend,escape);
- if (tmp <= 0)
- return (tmp);
- }
- } while (str != str_end && wildstr[0] != wild_many);
- return(-1);
- }
- }
- return (str != str_end ? 1 : 0);
-}
-
-
-int wild_compare(String &match,String &wild, char escape)
-{
- return wild_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape);
-}
diff --git a/client/sql_string.h b/client/sql_string.h
index cffe78936a0..42f9e446981 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -24,31 +24,56 @@
#define NOT_FIXED_DEC 31
#endif
+class String;
+int sortcmp(const String *a,const String *b);
+int stringcmp(const String *a,const String *b);
+String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
+
class String
{
char *Ptr;
uint32 str_length,Alloced_length;
bool alloced;
+ CHARSET_INFO *str_charset;
public:
String()
- { Ptr=0; str_length=Alloced_length=0; alloced=0; }
+ {
+ Ptr=0; str_length=Alloced_length=0; alloced=0;
+ str_charset=default_charset_info;
+ }
String(uint32 length_arg)
- { alloced=0; Alloced_length=0; (void) real_alloc(length_arg); }
- String(const char *str)
- { Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;}
- String(const char *str,uint32 len)
- { Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;}
- String(char *str,uint32 len)
- { Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;}
+ {
+ alloced=0; Alloced_length=0; (void) real_alloc(length_arg);
+ str_charset=default_charset_info;
+ }
+ String(const char *str, CHARSET_INFO *cs)
+ {
+ Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;
+ str_charset=cs;
+ }
+ String(const char *str,uint32 len, CHARSET_INFO *cs)
+ {
+ Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;
+ str_charset=cs;
+ }
+ String(char *str,uint32 len, CHARSET_INFO *cs)
+ {
+ Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;
+ str_charset=cs;
+ }
String(const String &str)
- { Ptr=str.Ptr ; str_length=str.str_length ;
- Alloced_length=str.Alloced_length; alloced=0; }
-
+ {
+ Ptr=str.Ptr ; str_length=str.str_length ;
+ Alloced_length=str.Alloced_length; alloced=0;
+ str_charset=str.str_charset;
+ }
static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
{ sql_element_free(ptr_arg); }
~String() { free(); }
+ inline void set_charset(CHARSET_INFO *charset) { str_charset=charset; }
+ inline CHARSET_INFO *charset() const { return str_charset; }
inline uint32 length() const { return str_length;}
inline uint32 alloced_length() const { return Alloced_length;}
inline char& operator [] (uint32 i) const { return Ptr[i]; }
@@ -76,28 +101,31 @@ public:
Alloced_length=str.Alloced_length-offset;
else
Alloced_length=0;
+ str_charset=str.str_charset;
}
- inline void set(char *str,uint32 arg_length)
+ inline void set(char *str,uint32 arg_length, CHARSET_INFO *cs)
{
free();
Ptr=(char*) str; str_length=Alloced_length=arg_length ; alloced=0;
+ str_charset=cs;
}
- inline void set(const char *str,uint32 arg_length)
+ inline void set(const char *str,uint32 arg_length, CHARSET_INFO *cs)
{
free();
Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0;
+ str_charset=cs;
}
- inline void set_quick(char *str,uint32 arg_length)
+ inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs)
{
if (!alloced)
{
Ptr=(char*) str; str_length=Alloced_length=arg_length;
}
+ str_charset=cs;
}
- bool set(longlong num);
- /* bool set(long num); */
- bool set(ulonglong num);
- bool set(double num,uint decimals=2);
+ bool set(longlong num, CHARSET_INFO *cs);
+ bool set(ulonglong num, CHARSET_INFO *cs);
+ bool set(double num,uint decimals, CHARSET_INFO *cs);
inline void free()
{
if (alloced)
@@ -124,7 +152,7 @@ public:
char *new_ptr;
if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0))))
{
- (void) my_free(Ptr,MYF(0));
+ Alloced_length = 0;
real_alloc(arg_length);
}
else
@@ -148,11 +176,13 @@ public:
bool copy(); // Alloc string if not alloced
bool copy(const String &s); // Allocate new string
- bool copy(const char *s,uint32 arg_length); // Allocate new string
+ bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string
+ bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto);
bool append(const String &s);
bool append(const char *s,uint32 arg_length=0);
bool append(IO_CACHE* file, uint32 arg_length);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
+ int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
bool replace(uint32 offset,uint32 arg_length,const String &to);
inline bool append(char chr)
@@ -171,13 +201,57 @@ public:
}
bool fill(uint32 max_length,char fill);
void strip_sp();
- inline void caseup() { ::caseup(Ptr,str_length); }
- inline void casedn() { ::casedn(Ptr,str_length); }
+ inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
+ inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
friend int sortcmp(const String *a,const String *b);
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
- friend int wild_case_compare(String &match,String &wild,char escape);
- friend int wild_compare(String &match,String &wild,char escape);
uint32 numchars();
int charpos(int i,uint32 offset=0);
+
+ int reserve(uint32 space_needed)
+ {
+ return realloc(str_length + space_needed);
+ }
+ int reserve(uint32 space_needed, uint32 grow_by);
+
+ /*
+ The following append operations do NOT check alloced memory
+ q_*** methods writes values of parameters itself
+ qs_*** methods writes string representation of value
+ */
+ void q_append(const char &c)
+ {
+ Ptr[str_length++] = c;
+ }
+ void q_append(const uint32 &n)
+ {
+ int4store(Ptr + str_length, n);
+ str_length += 4;
+ }
+ void q_append(double d)
+ {
+ float8store(Ptr + str_length, d);
+ str_length += 8;
+ }
+ void q_append(double *d)
+ {
+ float8store(Ptr + str_length, *d);
+ str_length += 8;
+ }
+ void q_append(const char *data, uint32 data_len)
+ {
+ memcpy(Ptr + str_length, data, data_len);
+ str_length += data_len;
+ }
+
+ void WriteAtPosition(int position, uint32 value)
+ {
+ int4store(Ptr + position,value);
+ }
+
+ void qs_append(const char *str);
+ void qs_append(double d);
+ void qs_append(double *d);
+ void qs_append(const char &c);
};
diff --git a/cmd-line-utils/Makefile.am b/cmd-line-utils/Makefile.am
new file mode 100644
index 00000000000..340dcdccf18
--- /dev/null
+++ b/cmd-line-utils/Makefile.am
@@ -0,0 +1,6 @@
+## Process this file with automake to create Makefile.in
+
+SUBDIRS= @readline_basedir@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am
new file mode 100644
index 00000000000..631c61ff350
--- /dev/null
+++ b/cmd-line-utils/libedit/Makefile.am
@@ -0,0 +1,88 @@
+## Process this file with automake to create Makefile.in
+# Makefile for the GNU readline library.
+# Copyright (C) 1994,1996,1997 Free Software Foundation, Inc.
+
+ASRC=vi.c emacs.c common.c
+AHDR=vi.h emacs.h common.h
+
+INCLUDES = -I$(top_srcdir)/include -I$(srcdir)/../.. -I..
+
+noinst_LIBRARIES = liblibedit.a
+
+liblibedit_a_SOURCES = chared.c el.c fgetln.c history.c map.c \
+ prompt.c readline.c search.c \
+ strlcpy.c tokenizer.c vi.c common.c \
+ emacs.c hist.c key.c parse.c read.c \
+ refresh.c sig.c term.c tty.c help.c \
+ fcns.c
+
+pkginclude_HEADERS = readline/readline.h
+
+noinst_HEADERS = chared.h el.h histedit.h key.h \
+ parse.h refresh.h sig.h sys.h \
+ tokenizer.h compat.h compat_conf.h fgetln.h \
+ hist.h map.h prompt.h search.h \
+ strlcpy.h term.h tty.h
+
+EXTRA_DIST = makelist
+
+DEFS = -DUNDEF_THREADS_HACK -DHAVE_CONFIG_H -DNO_KILL_INTR
+
+vi.h: vi.c makelist
+ sh ./makelist -h ./vi.c > $@.tmp && \
+ mv $@.tmp $@
+
+emacs.h: emacs.c makelist
+ sh ./makelist -h ./emacs.c > $@.tmp && \
+ mv $@.tmp $@
+
+common.h: common.c makelist
+ sh ./makelist -h ./common.c > $@.tmp && \
+ mv $@.tmp $@
+
+help.c: ${ASRC} makelist
+ sh ./makelist -bc ${ASRC} > $@.tmp && \
+ mv $@.tmp $@
+
+help.h: ${ASRC} makelist
+ sh ./makelist -bh ${ASRC} > $@.tmp && \
+ mv $@.tmp $@
+
+fcns.h: ${AHDR} makelist
+ sh ./makelist -fh ${AHDR} > $@.tmp && \
+ mv $@.tmp $@
+
+fcns.c: ${AHDR} fcns.h makelist
+ sh ./makelist -fc ${AHDR} > $@.tmp && \
+ mv $@.tmp $@
+
+#%.o: vi.h emacs.h common.h help.h fcns.h
+#objects := $(patsubst %.c,%.o,$(wildcard *.c))
+#$(objects): vi.h emacs.h
+
+chared.o: vi.h emacs.h common.h help.h fcns.h
+el.o: vi.h emacs.h common.h help.h fcns.h
+fgetln.o: vi.h emacs.h common.h help.h fcns.h
+history.o: vi.h emacs.h common.h help.h fcns.h
+map.o: vi.h emacs.h common.h help.h fcns.h
+prompt.o: vi.h emacs.h common.h help.h fcns.h
+readline.o: vi.h emacs.h common.h help.h fcns.h
+search.o: vi.h emacs.h common.h help.h fcns.h
+strlcpy.o: vi.h emacs.h common.h help.h fcns.h
+tokenizer.o: vi.h emacs.h common.h help.h fcns.h
+vi.o: vi.h emacs.h common.h help.h fcns.h
+common.o: vi.h emacs.h common.h help.h fcns.h
+emacs.o: vi.h emacs.h common.h help.h fcns.h
+hist.o: vi.h emacs.h common.h help.h fcns.h
+key.o: vi.h emacs.h common.h help.h fcns.h
+parse.o: vi.h emacs.h common.h help.h fcns.h
+read.o: vi.h emacs.h common.h help.h fcns.h
+refresh.o: vi.h emacs.h common.h help.h fcns.h
+sig.o: vi.h emacs.h common.h help.h fcns.h
+term.o: vi.h emacs.h common.h help.h fcns.h
+tty.o: vi.h emacs.h common.h help.h fcns.h
+help.o: vi.h emacs.h common.h help.h fcns.h
+fcns.o: vi.h emacs.h common.h help.h fcns.h
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/cmd-line-utils/libedit/TEST/test.c b/cmd-line-utils/libedit/TEST/test.c
new file mode 100644
index 00000000000..605341eac62
--- /dev/null
+++ b/cmd-line-utils/libedit/TEST/test.c
@@ -0,0 +1,269 @@
+/* $NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include "compat.h"
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
+ The Regents of the University of California. All rights reserved.\n");
+#endif /* not lint */
+
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * test.c: A little test program
+ */
+#include "sys.h"
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "histedit.h"
+#include "tokenizer.h"
+
+static int continuation = 0;
+static EditLine *el = NULL;
+
+static u_char complete(EditLine *, int);
+ int main(int, char **);
+static char *prompt(EditLine *);
+static void sig(int);
+
+static char *
+prompt(EditLine *el)
+{
+ static char a[] = "Edit$";
+ static char b[] = "Edit>";
+
+ return (continuation ? b : a);
+}
+
+static void
+sig(int i)
+{
+
+ (void) fprintf(stderr, "Got signal %d.\n", i);
+ el_reset(el);
+}
+
+static unsigned char
+complete(EditLine *el, int ch)
+{
+ DIR *dd = opendir(".");
+ struct dirent *dp;
+ const char* ptr;
+ const LineInfo *lf = el_line(el);
+ int len;
+
+ /*
+ * Find the last word
+ */
+ for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--)
+ continue;
+ len = lf->cursor - ++ptr;
+
+ for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
+ if (len > strlen(dp->d_name))
+ continue;
+ if (strncmp(dp->d_name, ptr, len) == 0) {
+ closedir(dd);
+ if (el_insertstr(el, &dp->d_name[len]) == -1)
+ return (CC_ERROR);
+ else
+ return (CC_REFRESH);
+ }
+ }
+
+ closedir(dd);
+ return (CC_ERROR);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int num;
+ const char *buf;
+ Tokenizer *tok;
+ int lastevent = 0, ncontinuation;
+ History *hist;
+ HistEvent ev;
+
+ (void) signal(SIGINT, sig);
+ (void) signal(SIGQUIT, sig);
+ (void) signal(SIGHUP, sig);
+ (void) signal(SIGTERM, sig);
+
+ hist = history_init(); /* Init the builtin history */
+ /* Remember 100 events */
+ history(hist, &ev, H_SETSIZE, 100);
+
+ tok = tok_init(NULL); /* Initialize the tokenizer */
+
+ /* Initialize editline */
+ el = el_init(*argv, stdin, stdout, stderr);
+
+ el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */
+ el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */
+ el_set(el, EL_PROMPT, prompt); /* Set the prompt function */
+
+ /* Tell editline to use this history interface */
+ el_set(el, EL_HIST, history, hist);
+
+ /* Add a user-defined function */
+ el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
+
+ /* Bind tab to it */
+ el_set(el, EL_BIND, "^I", "ed-complete", NULL);
+
+ /*
+ * Bind j, k in vi command mode to previous and next line, instead
+ * of previous and next history.
+ */
+ el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
+ el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
+
+ /*
+ * Source the user's defaults file.
+ */
+ el_source(el, NULL);
+
+ while ((buf = el_gets(el, &num)) != NULL && num != 0) {
+ int ac;
+ char **av;
+#ifdef DEBUG
+ (void) fprintf(stderr, "got %d %s", num, buf);
+#endif
+ if (!continuation && num == 1)
+ continue;
+
+ if (tok_line(tok, buf, &ac, &av) > 0)
+ ncontinuation = 1;
+
+#if 0
+ if (continuation) {
+ /*
+ * Append to the right event in case the user
+ * moved around in history.
+ */
+ if (history(hist, &ev, H_SET, lastevent) == -1)
+ err(1, "%d: %s\n", lastevent, ev.str);
+ history(hist, &ev, H_ADD , buf);
+ } else {
+ history(hist, &ev, H_ENTER, buf);
+ lastevent = ev.num;
+ }
+#else
+ /* Simpler */
+ history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf);
+#endif
+
+ continuation = ncontinuation;
+ ncontinuation = 0;
+
+ if (strcmp(av[0], "history") == 0) {
+ int rv;
+
+ switch (ac) {
+ case 1:
+ for (rv = history(hist, &ev, H_LAST); rv != -1;
+ rv = history(hist, &ev, H_PREV))
+ (void) fprintf(stdout, "%4d %s",
+ ev.num, ev.str);
+ break;
+
+ case 2:
+ if (strcmp(av[1], "clear") == 0)
+ history(hist, &ev, H_CLEAR);
+ else
+ goto badhist;
+ break;
+
+ case 3:
+ if (strcmp(av[1], "load") == 0)
+ history(hist, &ev, H_LOAD, av[2]);
+ else if (strcmp(av[1], "save") == 0)
+ history(hist, &ev, H_SAVE, av[2]);
+ break;
+
+ badhist:
+ default:
+ (void) fprintf(stderr,
+ "Bad history arguments\n");
+ break;
+ }
+ } else if (el_parse(el, ac, av) == -1) {
+ switch (fork()) {
+ case 0:
+ execvp(av[0], av);
+ perror(av[0]);
+ _exit(1);
+ /*NOTREACHED*/
+ break;
+
+ case -1:
+ perror("fork");
+ break;
+
+ default:
+ if (wait(&num) == -1)
+ perror("wait");
+ (void) fprintf(stderr, "Exit %x\n", num);
+ break;
+ }
+ }
+
+ tok_reset(tok);
+ }
+
+ el_end(el);
+ tok_end(tok);
+ history_end(hist);
+
+ return (0);
+}
diff --git a/cmd-line-utils/libedit/chared.c b/cmd-line-utils/libedit/chared.c
new file mode 100644
index 00000000000..6ac051c3bb0
--- /dev/null
+++ b/cmd-line-utils/libedit/chared.c
@@ -0,0 +1,690 @@
+/* $NetBSD: chared.c,v 1.14 2001/05/17 01:02:17 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * chared.c: Character editor utilities
+ */
+#include "sys.h"
+
+#include <stdlib.h>
+#include "el.h"
+
+/* value to leave unused in line buffer */
+#define EL_LEAVE 2
+
+/* cv_undo():
+ * Handle state for the vi undo command
+ */
+protected void
+cv_undo(EditLine *el,int action, size_t size, char *ptr)
+{
+ c_undo_t *vu = &el->el_chared.c_undo;
+ vu->action = action;
+ vu->ptr = ptr;
+ vu->isize = size;
+ (void) memcpy(vu->buf, vu->ptr, size);
+#ifdef DEBUG_UNDO
+ (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
+ vu->ptr, vu->isize, vu->dsize);
+#endif
+}
+
+
+/* c_insert():
+ * Insert num characters
+ */
+protected void
+c_insert(EditLine *el, int num)
+{
+ char *cp;
+
+ if (el->el_line.lastchar + num >= el->el_line.limit)
+ return; /* can't go past end of buffer */
+
+ if (el->el_line.cursor < el->el_line.lastchar) {
+ /* if I must move chars */
+ for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
+ cp[num] = *cp;
+ }
+ el->el_line.lastchar += num;
+}
+
+
+/* c_delafter():
+ * Delete num characters after the cursor
+ */
+protected void
+c_delafter(EditLine *el, int num)
+{
+
+ if (el->el_line.cursor + num > el->el_line.lastchar)
+ num = el->el_line.lastchar - el->el_line.cursor;
+
+ if (num > 0) {
+ char *cp;
+
+ if (el->el_map.current != el->el_map.emacs)
+ cv_undo(el, INSERT, (size_t)num, el->el_line.cursor);
+
+ for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[num];
+
+ el->el_line.lastchar -= num;
+ }
+}
+
+
+/* c_delbefore():
+ * Delete num characters before the cursor
+ */
+protected void
+c_delbefore(EditLine *el, int num)
+{
+
+ if (el->el_line.cursor - num < el->el_line.buffer)
+ num = el->el_line.cursor - el->el_line.buffer;
+
+ if (num > 0) {
+ char *cp;
+
+ if (el->el_map.current != el->el_map.emacs)
+ cv_undo(el, INSERT, (size_t)num,
+ el->el_line.cursor - num);
+
+ for (cp = el->el_line.cursor - num;
+ cp <= el->el_line.lastchar;
+ cp++)
+ *cp = cp[num];
+
+ el->el_line.lastchar -= num;
+ }
+}
+
+
+/* ce__isword():
+ * Return if p is part of a word according to emacs
+ */
+protected int
+ce__isword(int p)
+{
+ return (isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL);
+}
+
+
+/* cv__isword():
+ * Return if p is part of a word according to vi
+ */
+protected int
+cv__isword(int p)
+{
+ return (!isspace(p));
+}
+
+
+/* c__prev_word():
+ * Find the previous word
+ */
+protected char *
+c__prev_word(char *p, char *low, int n, int (*wtest)(int))
+{
+ p--;
+
+ while (n--) {
+ while ((p >= low) && !(*wtest)((unsigned char) *p))
+ p--;
+ while ((p >= low) && (*wtest)((unsigned char) *p))
+ p--;
+ }
+
+ /* cp now points to one character before the word */
+ p++;
+ if (p < low)
+ p = low;
+ /* cp now points where we want it */
+ return (p);
+}
+
+
+/* c__next_word():
+ * Find the next word
+ */
+protected char *
+c__next_word(char *p, char *high, int n, int (*wtest)(int))
+{
+ while (n--) {
+ while ((p < high) && !(*wtest)((unsigned char) *p))
+ p++;
+ while ((p < high) && (*wtest)((unsigned char) *p))
+ p++;
+ }
+ if (p > high)
+ p = high;
+ /* p now points where we want it */
+ return (p);
+}
+
+/* cv_next_word():
+ * Find the next word vi style
+ */
+protected char *
+cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
+{
+ int test;
+
+ while (n--) {
+ test = (*wtest)((unsigned char) *p);
+ while ((p < high) && (*wtest)((unsigned char) *p) == test)
+ p++;
+ /*
+ * vi historically deletes with cw only the word preserving the
+ * trailing whitespace! This is not what 'w' does..
+ */
+ if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+ while ((p < high) && isspace((unsigned char) *p))
+ p++;
+ }
+
+ /* p now points where we want it */
+ if (p > high)
+ return (high);
+ else
+ return (p);
+}
+
+
+/* cv_prev_word():
+ * Find the previous word vi style
+ */
+protected char *
+cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int))
+{
+ int test;
+
+ while (n--) {
+ p--;
+ /*
+ * vi historically deletes with cb only the word preserving the
+ * leading whitespace! This is not what 'b' does..
+ */
+ if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+ while ((p > low) && isspace((unsigned char) *p))
+ p--;
+ test = (*wtest)((unsigned char) *p);
+ while ((p >= low) && (*wtest)((unsigned char) *p) == test)
+ p--;
+ p++;
+ while (isspace((unsigned char) *p))
+ p++;
+ }
+
+ /* p now points where we want it */
+ if (p < low)
+ return (low);
+ else
+ return (p);
+}
+
+
+#ifdef notdef
+/* c__number():
+ * Ignore character p points to, return number appearing after that.
+ * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
+ * Return p pointing to last char used.
+ */
+protected char *
+c__number(
+ char *p, /* character position */
+ int *num, /* Return value */
+ int dval) /* dval is the number to subtract from like $-3 */
+{
+ int i;
+ int sign = 1;
+
+ if (*++p == '^') {
+ *num = 1;
+ return (p);
+ }
+ if (*p == '$') {
+ if (*++p != '-') {
+ *num = 0x7fffffff; /* Handle $ */
+ return (--p);
+ }
+ sign = -1; /* Handle $- */
+ ++p;
+ }
+ for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
+ continue;
+ *num = (sign < 0 ? dval - i : i);
+ return (--p);
+}
+#endif
+
+/* cv_delfini():
+ * Finish vi delete action
+ */
+protected void
+cv_delfini(EditLine *el)
+{
+ int size;
+ int oaction;
+
+ if (el->el_chared.c_vcmd.action & INSERT)
+ el->el_map.current = el->el_map.key;
+
+ oaction = el->el_chared.c_vcmd.action;
+ el->el_chared.c_vcmd.action = NOP;
+
+ if (el->el_chared.c_vcmd.pos == 0)
+ return;
+
+
+ if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
+ size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
+ c_delbefore(el, size);
+ el->el_line.cursor = el->el_chared.c_vcmd.pos;
+ re_refresh_cursor(el);
+ } else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
+ size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
+ c_delafter(el, size);
+ } else {
+ size = 1;
+ c_delafter(el, size);
+ }
+ switch (oaction) {
+ case DELETE|INSERT:
+ el->el_chared.c_undo.action = DELETE|INSERT;
+ break;
+ case DELETE:
+ el->el_chared.c_undo.action = INSERT;
+ break;
+ case NOP:
+ case INSERT:
+ default:
+ EL_ABORT((el->el_errfile, "Bad oaction %d\n", oaction));
+ break;
+ }
+
+
+ el->el_chared.c_undo.ptr = el->el_line.cursor;
+ el->el_chared.c_undo.dsize = size;
+}
+
+
+#ifdef notdef
+/* ce__endword():
+ * Go to the end of this word according to emacs
+ */
+protected char *
+ce__endword(char *p, char *high, int n)
+{
+ p++;
+
+ while (n--) {
+ while ((p < high) && isspace((unsigned char) *p))
+ p++;
+ while ((p < high) && !isspace((unsigned char) *p))
+ p++;
+ }
+
+ p--;
+ return (p);
+}
+#endif
+
+
+/* cv__endword():
+ * Go to the end of this word according to vi
+ */
+protected char *
+cv__endword(char *p, char *high, int n)
+{
+ p++;
+
+ while (n--) {
+ while ((p < high) && isspace((unsigned char) *p))
+ p++;
+
+ if (isalnum((unsigned char) *p))
+ while ((p < high) && isalnum((unsigned char) *p))
+ p++;
+ else
+ while ((p < high) && !(isspace((unsigned char) *p) ||
+ isalnum((unsigned char) *p)))
+ p++;
+ }
+ p--;
+ return (p);
+}
+
+/* ch_init():
+ * Initialize the character editor
+ */
+protected int
+ch_init(EditLine *el)
+{
+ el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ);
+ if (el->el_line.buffer == NULL)
+ return (-1);
+
+ (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
+ el->el_line.cursor = el->el_line.buffer;
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - 2];
+
+ el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
+ if (el->el_chared.c_undo.buf == NULL)
+ return (-1);
+ (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
+ el->el_chared.c_undo.action = NOP;
+ el->el_chared.c_undo.isize = 0;
+ el->el_chared.c_undo.dsize = 0;
+ el->el_chared.c_undo.ptr = el->el_line.buffer;
+
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_vcmd.pos = el->el_line.buffer;
+ el->el_chared.c_vcmd.ins = el->el_line.buffer;
+
+ el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
+ if (el->el_chared.c_kill.buf == NULL)
+ return (-1);
+ (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
+ el->el_chared.c_kill.mark = el->el_line.buffer;
+ el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
+
+ el->el_map.current = el->el_map.key;
+
+ el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
+ el->el_state.doingarg = 0;
+ el->el_state.metanext = 0;
+ el->el_state.argument = 1;
+ el->el_state.lastcmd = ED_UNASSIGNED;
+
+ el->el_chared.c_macro.nline = NULL;
+ el->el_chared.c_macro.level = -1;
+ el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
+ sizeof(char *));
+ if (el->el_chared.c_macro.macro == NULL)
+ return (-1);
+ return (0);
+}
+
+/* ch_reset():
+ * Reset the character editor
+ */
+protected void
+ch_reset(EditLine *el)
+{
+ el->el_line.cursor = el->el_line.buffer;
+ el->el_line.lastchar = el->el_line.buffer;
+
+ el->el_chared.c_undo.action = NOP;
+ el->el_chared.c_undo.isize = 0;
+ el->el_chared.c_undo.dsize = 0;
+ el->el_chared.c_undo.ptr = el->el_line.buffer;
+
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_vcmd.pos = el->el_line.buffer;
+ el->el_chared.c_vcmd.ins = el->el_line.buffer;
+
+ el->el_chared.c_kill.mark = el->el_line.buffer;
+
+ el->el_map.current = el->el_map.key;
+
+ el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
+ el->el_state.doingarg = 0;
+ el->el_state.metanext = 0;
+ el->el_state.argument = 1;
+ el->el_state.lastcmd = ED_UNASSIGNED;
+
+ el->el_chared.c_macro.level = -1;
+
+ el->el_history.eventno = 0;
+}
+
+/* ch_enlargebufs():
+ * Enlarge line buffer to be able to hold twice as much characters.
+ * Returns 1 if successful, 0 if not.
+ */
+protected int
+ch_enlargebufs(el, addlen)
+ EditLine *el;
+ size_t addlen;
+{
+ size_t sz, newsz;
+ char *newbuffer, *oldbuf, *oldkbuf;
+
+ sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
+ newsz = sz * 2;
+ /*
+ * If newly required length is longer than current buffer, we need
+ * to make the buffer big enough to hold both old and new stuff.
+ */
+ if (addlen > sz) {
+ while(newsz - sz < addlen)
+ newsz *= 2;
+ }
+
+ /*
+ * Reallocate line buffer.
+ */
+ newbuffer = el_realloc(el->el_line.buffer, newsz);
+ if (!newbuffer)
+ return 0;
+
+ /* zero the newly added memory, leave old data in */
+ (void) memset(&newbuffer[sz], 0, newsz - sz);
+
+ oldbuf = el->el_line.buffer;
+
+ el->el_line.buffer = newbuffer;
+ el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
+ el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
+ el->el_line.limit = &newbuffer[newsz - EL_LEAVE];
+
+ /*
+ * Reallocate kill buffer.
+ */
+ newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz);
+ if (!newbuffer)
+ return 0;
+
+ /* zero the newly added memory, leave old data in */
+ (void) memset(&newbuffer[sz], 0, newsz - sz);
+
+ oldkbuf = el->el_chared.c_kill.buf;
+
+ el->el_chared.c_kill.buf = newbuffer;
+ el->el_chared.c_kill.last = newbuffer +
+ (el->el_chared.c_kill.last - oldkbuf);
+ el->el_chared.c_kill.mark = el->el_line.buffer +
+ (el->el_chared.c_kill.mark - oldbuf);
+
+ /*
+ * Reallocate undo buffer.
+ */
+ newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz);
+ if (!newbuffer)
+ return 0;
+
+ /* zero the newly added memory, leave old data in */
+ (void) memset(&newbuffer[sz], 0, newsz - sz);
+
+ el->el_chared.c_undo.ptr = el->el_line.buffer +
+ (el->el_chared.c_undo.ptr - oldbuf);
+ el->el_chared.c_undo.buf = newbuffer;
+
+ if (!hist_enlargebuf(el, sz, newsz))
+ return 0;
+
+ return 1;
+}
+
+/* ch_end():
+ * Free the data structures used by the editor
+ */
+protected void
+ch_end(EditLine *el)
+{
+ el_free((ptr_t) el->el_line.buffer);
+ el->el_line.buffer = NULL;
+ el->el_line.limit = NULL;
+ el_free((ptr_t) el->el_chared.c_undo.buf);
+ el->el_chared.c_undo.buf = NULL;
+ el_free((ptr_t) el->el_chared.c_kill.buf);
+ el->el_chared.c_kill.buf = NULL;
+ el_free((ptr_t) el->el_chared.c_macro.macro);
+ el->el_chared.c_macro.macro = NULL;
+ ch_reset(el);
+}
+
+
+/* el_insertstr():
+ * Insert string at cursorI
+ */
+public int
+el_insertstr(EditLine *el, const char *s)
+{
+ size_t len;
+
+ if ((len = strlen(s)) == 0)
+ return (-1);
+ if (el->el_line.lastchar + len >= el->el_line.limit) {
+ if (!ch_enlargebufs(el, len))
+ return (-1);
+ }
+
+ c_insert(el, (int)len);
+ while (*s)
+ *el->el_line.cursor++ = *s++;
+ return (0);
+}
+
+
+/* el_deletestr():
+ * Delete num characters before the cursor
+ */
+public void
+el_deletestr(EditLine *el, int n)
+{
+ if (n <= 0)
+ return;
+
+ if (el->el_line.cursor < &el->el_line.buffer[n])
+ return;
+
+ c_delbefore(el, n); /* delete before dot */
+ el->el_line.cursor -= n;
+ if (el->el_line.cursor < el->el_line.buffer)
+ el->el_line.cursor = el->el_line.buffer;
+}
+
+/* c_gets():
+ * Get a string
+ */
+protected int
+c_gets(EditLine *el, char *buf)
+{
+ char ch;
+ int len = 0;
+
+ for (ch = 0; ch == 0;) {
+ if (el_getc(el, &ch) != 1)
+ return (ed_end_of_file(el, 0));
+ switch (ch) {
+ case 0010: /* Delete and backspace */
+ case 0177:
+ if (len > 1) {
+ *el->el_line.cursor-- = '\0';
+ el->el_line.lastchar = el->el_line.cursor;
+ buf[len--] = '\0';
+ } else {
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+ return (CC_REFRESH);
+ }
+ re_refresh(el);
+ ch = 0;
+ break;
+
+ case 0033: /* ESC */
+ case '\r': /* Newline */
+ case '\n':
+ break;
+
+ default:
+ if (len >= EL_BUFSIZ)
+ term_beep(el);
+ else {
+ buf[len++] = ch;
+ *el->el_line.cursor++ = ch;
+ el->el_line.lastchar = el->el_line.cursor;
+ }
+ re_refresh(el);
+ ch = 0;
+ break;
+ }
+ }
+ buf[len] = ch;
+ return (len);
+}
+
+
+/* c_hpos():
+ * Return the current horizontal position of the cursor
+ */
+protected int
+c_hpos(EditLine *el)
+{
+ char *ptr;
+
+ /*
+ * Find how many characters till the beginning of this line.
+ */
+ if (el->el_line.cursor == el->el_line.buffer)
+ return (0);
+ else {
+ for (ptr = el->el_line.cursor - 1;
+ ptr >= el->el_line.buffer && *ptr != '\n';
+ ptr--)
+ continue;
+ return (el->el_line.cursor - ptr - 1);
+ }
+}
diff --git a/cmd-line-utils/libedit/chared.h b/cmd-line-utils/libedit/chared.h
new file mode 100644
index 00000000000..2eb9ad32886
--- /dev/null
+++ b/cmd-line-utils/libedit/chared.h
@@ -0,0 +1,159 @@
+/* $NetBSD: chared.h,v 1.6 2001/01/10 07:45:41 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)chared.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.chared.h: Character editor interface
+ */
+#ifndef _h_el_chared
+#define _h_el_chared
+
+#include <ctype.h>
+#include <string.h>
+
+#include "histedit.h"
+
+#define EL_MAXMACRO 10
+
+/*
+ * This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works
+ * like real vi: i.e. the transition from command<->insert modes moves
+ * the cursor.
+ *
+ * On the other hand we really don't want to move the cursor, because
+ * all the editing commands don't include the character under the cursor.
+ * Probably the best fix is to make all the editing commands aware of
+ * this fact.
+ */
+#define VI_MOVE
+
+
+typedef struct c_macro_t {
+ int level;
+ char **macro;
+ char *nline;
+} c_macro_t;
+
+/*
+ * Undo information for both vi and emacs
+ */
+typedef struct c_undo_t {
+ int action;
+ size_t isize;
+ size_t dsize;
+ char *ptr;
+ char *buf;
+} c_undo_t;
+
+/*
+ * Current action information for vi
+ */
+typedef struct c_vcmd_t {
+ int action;
+ char *pos;
+ char *ins;
+} c_vcmd_t;
+
+/*
+ * Kill buffer for emacs
+ */
+typedef struct c_kill_t {
+ char *buf;
+ char *last;
+ char *mark;
+} c_kill_t;
+
+/*
+ * Note that we use both data structures because the user can bind
+ * commands from both editors!
+ */
+typedef struct el_chared_t {
+ c_undo_t c_undo;
+ c_kill_t c_kill;
+ c_vcmd_t c_vcmd;
+ c_macro_t c_macro;
+} el_chared_t;
+
+
+#define STReof "^D\b\b"
+#define STRQQ "\"\""
+
+#define isglob(a) (strchr("*[]?", (a)) != NULL)
+#define isword(a) (isprint(a))
+
+#define NOP 0x00
+#define DELETE 0x01
+#define INSERT 0x02
+#define CHANGE 0x04
+
+#define CHAR_FWD 0
+#define CHAR_BACK 1
+
+#define MODE_INSERT 0
+#define MODE_REPLACE 1
+#define MODE_REPLACE_1 2
+
+#include "common.h"
+#include "vi.h"
+#include "emacs.h"
+#include "search.h"
+#include "fcns.h"
+
+
+protected int cv__isword(int);
+protected void cv_delfini(EditLine *);
+protected char *cv__endword(char *, char *, int);
+protected int ce__isword(int);
+protected void cv_undo(EditLine *, int, size_t, char *);
+protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int));
+protected char *cv_prev_word(EditLine*, char *, char *, int, int (*)(int));
+protected char *c__next_word(char *, char *, int, int (*)(int));
+protected char *c__prev_word(char *, char *, int, int (*)(int));
+protected void c_insert(EditLine *, int);
+protected void c_delbefore(EditLine *, int);
+protected void c_delafter(EditLine *, int);
+protected int c_gets(EditLine *, char *);
+protected int c_hpos(EditLine *);
+
+protected int ch_init(EditLine *);
+protected void ch_reset(EditLine *);
+protected int ch_enlargebufs __P((EditLine *, size_t));
+protected void ch_end(EditLine *);
+
+#endif /* _h_el_chared */
diff --git a/cmd-line-utils/libedit/common.c b/cmd-line-utils/libedit/common.c
new file mode 100644
index 00000000000..9ac6af9ac1b
--- /dev/null
+++ b/cmd-line-utils/libedit/common.c
@@ -0,0 +1,954 @@
+/* $NetBSD: common.c,v 1.10 2001/01/10 07:45:41 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * common.c: Common Editor functions
+ */
+#include "sys.h"
+#include "el.h"
+
+/* ed_end_of_file():
+ * Indicate end of file
+ * [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_end_of_file(EditLine *el, int c __attribute__((unused)))
+{
+
+ re_goto_bottom(el);
+ *el->el_line.lastchar = '\0';
+ return (CC_EOF);
+}
+
+
+/* ed_insert():
+ * Add character to the line
+ * Insert a character [bound to all insert keys]
+ */
+protected el_action_t
+ed_insert(EditLine *el, int c)
+{
+ int i;
+
+ if (c == '\0')
+ return (CC_ERROR);
+
+ if (el->el_line.lastchar + el->el_state.argument >=
+ el->el_line.limit) {
+ /* end of buffer space, try to allocate more */
+ if (!ch_enlargebufs(el, (size_t) el->el_state.argument))
+ return CC_ERROR; /* error allocating more */
+ }
+
+ if (el->el_state.argument == 1) {
+ if (el->el_state.inputmode != MODE_INSERT) {
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ *el->el_line.cursor;
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
+ '\0';
+ c_delafter(el, 1);
+ }
+ c_insert(el, 1);
+
+ *el->el_line.cursor++ = c;
+ el->el_state.doingarg = 0; /* just in case */
+ re_fastaddc(el); /* fast refresh for one char. */
+ } else {
+ if (el->el_state.inputmode != MODE_INSERT) {
+ for (i = 0; i < el->el_state.argument; i++)
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ el->el_line.cursor[i];
+
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
+ '\0';
+ c_delafter(el, el->el_state.argument);
+ }
+ c_insert(el, el->el_state.argument);
+
+ while (el->el_state.argument--)
+ *el->el_line.cursor++ = c;
+ re_refresh(el);
+ }
+
+ if (el->el_state.inputmode == MODE_REPLACE_1)
+ (void) vi_command_mode(el, 0);
+
+ return (CC_NORM);
+}
+
+
+/* ed_delete_prev_word():
+ * Delete from beginning of current word to cursor
+ * [M-^?] [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_prev_word(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *p, *kp;
+
+ if (el->el_line.cursor == el->el_line.buffer)
+ return (CC_ERROR);
+
+ cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+ el->el_state.argument, ce__isword);
+
+ for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
+ *kp++ = *p;
+ el->el_chared.c_kill.last = kp;
+
+ c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
+ el->el_line.cursor = cp;
+ if (el->el_line.cursor < el->el_line.buffer)
+ el->el_line.cursor = el->el_line.buffer; /* bounds check */
+ return (CC_REFRESH);
+}
+
+
+/* ed_delete_next_char():
+ * Delete character under cursor
+ * [^D] [x]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_next_char(EditLine *el, int c __attribute__((unused)))
+{
+#ifdef notdef /* XXX */
+#define EL el->el_line
+ (void) fprintf(el->el_errlfile,
+ "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
+ EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
+ EL.lastchar, EL.limit, EL.limit);
+#endif
+ if (el->el_line.cursor == el->el_line.lastchar) {
+ /* if I'm at the end */
+ if (el->el_map.type == MAP_VI) {
+ if (el->el_line.cursor == el->el_line.buffer) {
+ /* if I'm also at the beginning */
+#ifdef KSHVI
+ return (CC_ERROR);
+#else
+ term_overwrite(el, STReof, 4);
+ /* then do a EOF */
+ term__flush();
+ return (CC_EOF);
+#endif
+ } else {
+#ifdef KSHVI
+ el->el_line.cursor--;
+#else
+ return (CC_ERROR);
+#endif
+ }
+ } else {
+ if (el->el_line.cursor != el->el_line.buffer)
+ el->el_line.cursor--;
+ else
+ return (CC_ERROR);
+ }
+ }
+ c_delafter(el, el->el_state.argument); /* delete after dot */
+ if (el->el_line.cursor >= el->el_line.lastchar &&
+ el->el_line.cursor > el->el_line.buffer)
+ /* bounds check */
+ el->el_line.cursor = el->el_line.lastchar - 1;
+ return (CC_REFRESH);
+}
+
+
+/* ed_kill_line():
+ * Cut to the end of line
+ * [^K] [^K]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_kill_line(EditLine *el, int c __attribute__((unused)))
+{
+ char *kp, *cp;
+
+ cp = el->el_line.cursor;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_line.lastchar)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ /* zap! -- delete to end */
+ el->el_line.lastchar = el->el_line.cursor;
+ return (CC_REFRESH);
+}
+
+
+/* ed_move_to_end():
+ * Move cursor to the end of line
+ * [^E] [^E]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_move_to_end(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_line.cursor = el->el_line.lastchar;
+ if (el->el_map.type == MAP_VI) {
+#ifdef VI_MOVE
+ el->el_line.cursor--;
+#endif
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ }
+ return (CC_CURSOR);
+}
+
+
+/* ed_move_to_beg():
+ * Move cursor to the beginning of line
+ * [^A] [^A]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_move_to_beg(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_line.cursor = el->el_line.buffer;
+
+ if (el->el_map.type == MAP_VI) {
+ /* We want FIRST non space character */
+ while (isspace((unsigned char) *el->el_line.cursor))
+ el->el_line.cursor++;
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ }
+ return (CC_CURSOR);
+}
+
+
+/* ed_transpose_chars():
+ * Exchange the character to the left of the cursor with the one under it
+ * [^T] [^T]
+ */
+protected el_action_t
+ed_transpose_chars(EditLine *el, int c)
+{
+
+ if (el->el_line.cursor < el->el_line.lastchar) {
+ if (el->el_line.lastchar <= &el->el_line.buffer[1])
+ return (CC_ERROR);
+ else
+ el->el_line.cursor++;
+ }
+ if (el->el_line.cursor > &el->el_line.buffer[1]) {
+ /* must have at least two chars entered */
+ c = el->el_line.cursor[-2];
+ el->el_line.cursor[-2] = el->el_line.cursor[-1];
+ el->el_line.cursor[-1] = c;
+ return (CC_REFRESH);
+ } else
+ return (CC_ERROR);
+}
+
+
+/* ed_next_char():
+ * Move to the right one character
+ * [^F] [^F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor >= el->el_line.lastchar)
+ return (CC_ERROR);
+
+ el->el_line.cursor += el->el_state.argument;
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* ed_prev_word():
+ * Move to the beginning of the current word
+ * [M-b] [b]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.buffer)
+ return (CC_ERROR);
+
+ el->el_line.cursor = c__prev_word(el->el_line.cursor,
+ el->el_line.buffer,
+ el->el_state.argument,
+ ce__isword);
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* ed_prev_char():
+ * Move to the left one character
+ * [^B] [^B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor > el->el_line.buffer) {
+ el->el_line.cursor -= el->el_state.argument;
+ if (el->el_line.cursor < el->el_line.buffer)
+ el->el_line.cursor = el->el_line.buffer;
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+ } else
+ return (CC_ERROR);
+}
+
+
+/* ed_quoted_insert():
+ * Add the next character typed verbatim
+ * [^V] [^V]
+ */
+protected el_action_t
+ed_quoted_insert(EditLine *el, int c)
+{
+ int num;
+ char tc;
+
+ tty_quotemode(el);
+ num = el_getc(el, &tc);
+ c = (unsigned char) tc;
+ tty_noquotemode(el);
+ if (num == 1)
+ return (ed_insert(el, c));
+ else
+ return (ed_end_of_file(el, 0));
+}
+
+
+/* ed_digit():
+ * Adds to argument or enters a digit
+ */
+protected el_action_t
+ed_digit(EditLine *el, int c)
+{
+
+ if (!isdigit(c))
+ return (CC_ERROR);
+
+ if (el->el_state.doingarg) {
+ /* if doing an arg, add this in... */
+ if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
+ el->el_state.argument = c - '0';
+ else {
+ if (el->el_state.argument > 1000000)
+ return (CC_ERROR);
+ el->el_state.argument =
+ (el->el_state.argument * 10) + (c - '0');
+ }
+ return (CC_ARGHACK);
+ } else {
+ if (el->el_line.lastchar + 1 >= el->el_line.limit) {
+ if (!ch_enlargebufs(el, 1))
+ return (CC_ERROR);
+ }
+
+ if (el->el_state.inputmode != MODE_INSERT) {
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
+ *el->el_line.cursor;
+ el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
+ '\0';
+ c_delafter(el, 1);
+ }
+ c_insert(el, 1);
+ *el->el_line.cursor++ = c;
+ el->el_state.doingarg = 0;
+ re_fastaddc(el);
+ }
+ return (CC_NORM);
+}
+
+
+/* ed_argument_digit():
+ * Digit that starts argument
+ * For ESC-n
+ */
+protected el_action_t
+ed_argument_digit(EditLine *el, int c)
+{
+
+ if (!isdigit(c))
+ return (CC_ERROR);
+
+ if (el->el_state.doingarg) {
+ if (el->el_state.argument > 1000000)
+ return (CC_ERROR);
+ el->el_state.argument = (el->el_state.argument * 10) +
+ (c - '0');
+ } else { /* else starting an argument */
+ el->el_state.argument = c - '0';
+ el->el_state.doingarg = 1;
+ }
+ return (CC_ARGHACK);
+}
+
+
+/* ed_unassigned():
+ * Indicates unbound character
+ * Bound to keys that are not assigned
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_unassigned(EditLine *el, int c __attribute__((unused)))
+{
+
+ term_beep(el);
+ term__flush();
+ return (CC_NORM);
+}
+
+
+/**
+ ** TTY key handling.
+ **/
+
+/* ed_tty_sigint():
+ * Tty interrupt character
+ * [^C]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigint(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_tty_dsusp():
+ * Tty delayed suspend character
+ * [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_dsusp(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_tty_flush_output():
+ * Tty flush output characters
+ * [^O]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_flush_output(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_tty_sigquit():
+ * Tty quit character
+ * [^\]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigquit(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_tty_sigtstp():
+ * Tty suspend character
+ * [^Z]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigtstp(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_tty_stop_output():
+ * Tty disallow output characters
+ * [^S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_stop_output(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_tty_start_output():
+ * Tty allow output characters
+ * [^Q]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_start_output(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_newline():
+ * Execute command
+ * [^J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_newline(EditLine *el, int c __attribute__((unused)))
+{
+
+ re_goto_bottom(el);
+ *el->el_line.lastchar++ = '\n';
+ *el->el_line.lastchar = '\0';
+ if (el->el_map.type == MAP_VI)
+ el->el_chared.c_vcmd.ins = el->el_line.buffer;
+ return (CC_NEWLINE);
+}
+
+
+/* ed_delete_prev_char():
+ * Delete the character to the left of the cursor
+ * [^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_prev_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor <= el->el_line.buffer)
+ return (CC_ERROR);
+
+ c_delbefore(el, el->el_state.argument);
+ el->el_line.cursor -= el->el_state.argument;
+ if (el->el_line.cursor < el->el_line.buffer)
+ el->el_line.cursor = el->el_line.buffer;
+ return (CC_REFRESH);
+}
+
+
+/* ed_clear_screen():
+ * Clear screen leaving current line at the top
+ * [^L]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_clear_screen(EditLine *el, int c __attribute__((unused)))
+{
+
+ term_clear_screen(el); /* clear the whole real screen */
+ re_clear_display(el); /* reset everything */
+ return (CC_REFRESH);
+}
+
+
+/* ed_redisplay():
+ * Redisplay everything
+ * ^R
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_redisplay(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_REDISPLAY);
+}
+
+
+/* ed_start_over():
+ * Erase current line and start from scratch
+ * [^G]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_start_over(EditLine *el, int c __attribute__((unused)))
+{
+
+ ch_reset(el);
+ return (CC_REFRESH);
+}
+
+
+/* ed_sequence_lead_in():
+ * First character in a bound sequence
+ * Placeholder for external keys
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_sequence_lead_in(EditLine *el __attribute__((unused)),
+ int c __attribute__((unused)))
+{
+
+ return (CC_NORM);
+}
+
+
+/* ed_prev_history():
+ * Move to the previous history line
+ * [^P] [k]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_history(EditLine *el, int c __attribute__((unused)))
+{
+ char beep = 0;
+
+ el->el_chared.c_undo.action = NOP;
+ *el->el_line.lastchar = '\0'; /* just in case */
+
+ if (el->el_history.eventno == 0) { /* save the current buffer
+ * away */
+ (void) strncpy(el->el_history.buf, el->el_line.buffer,
+ EL_BUFSIZ);
+ el->el_history.last = el->el_history.buf +
+ (el->el_line.lastchar - el->el_line.buffer);
+ }
+ el->el_history.eventno += el->el_state.argument;
+
+ if (hist_get(el) == CC_ERROR) {
+ beep = 1;
+ /* el->el_history.eventno was fixed by first call */
+ (void) hist_get(el);
+ }
+ re_refresh(el);
+ if (beep)
+ return (CC_ERROR);
+ else
+ return (CC_NORM); /* was CC_UP_HIST */
+}
+
+
+/* ed_next_history():
+ * Move to the next history line
+ * [^N] [j]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_history(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_chared.c_undo.action = NOP;
+ *el->el_line.lastchar = '\0'; /* just in case */
+
+ el->el_history.eventno -= el->el_state.argument;
+
+ if (el->el_history.eventno < 0) {
+ el->el_history.eventno = 0;
+ return (CC_ERROR);/* make it beep */
+ }
+ return (hist_get(el));
+}
+
+
+/* ed_search_prev_history():
+ * Search previous in history for a line matching the current
+ * next search history [M-P] [K]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_search_prev_history(EditLine *el, int c __attribute__((unused)))
+{
+ const char *hp;
+ int h;
+ bool_t found = 0;
+
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_undo.action = NOP;
+ *el->el_line.lastchar = '\0'; /* just in case */
+ if (el->el_history.eventno < 0) {
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile,
+ "e_prev_search_hist(): eventno < 0;\n");
+#endif
+ el->el_history.eventno = 0;
+ return (CC_ERROR);
+ }
+ if (el->el_history.eventno == 0) {
+ (void) strncpy(el->el_history.buf, el->el_line.buffer,
+ EL_BUFSIZ);
+ el->el_history.last = el->el_history.buf +
+ (el->el_line.lastchar - el->el_line.buffer);
+ }
+ if (el->el_history.ref == NULL)
+ return (CC_ERROR);
+
+ hp = HIST_FIRST(el);
+ if (hp == NULL)
+ return (CC_ERROR);
+
+ c_setpat(el); /* Set search pattern !! */
+
+ for (h = 1; h <= el->el_history.eventno; h++)
+ hp = HIST_NEXT(el);
+
+ while (hp != NULL) {
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+#endif
+ if ((strncmp(hp, el->el_line.buffer, (size_t)
+ (el->el_line.lastchar - el->el_line.buffer)) ||
+ hp[el->el_line.lastchar - el->el_line.buffer]) &&
+ c_hmatch(el, hp)) {
+ found++;
+ break;
+ }
+ h++;
+ hp = HIST_NEXT(el);
+ }
+
+ if (!found) {
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "not found\n");
+#endif
+ return (CC_ERROR);
+ }
+ el->el_history.eventno = h;
+
+ return (hist_get(el));
+}
+
+
+/* ed_search_next_history():
+ * Search next in history for a line matching the current
+ * [M-N] [J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_search_next_history(EditLine *el, int c __attribute__((unused)))
+{
+ const char *hp;
+ int h;
+ bool_t found = 0;
+
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_undo.action = NOP;
+ *el->el_line.lastchar = '\0'; /* just in case */
+
+ if (el->el_history.eventno == 0)
+ return (CC_ERROR);
+
+ if (el->el_history.ref == NULL)
+ return (CC_ERROR);
+
+ hp = HIST_FIRST(el);
+ if (hp == NULL)
+ return (CC_ERROR);
+
+ c_setpat(el); /* Set search pattern !! */
+
+ for (h = 1; h < el->el_history.eventno && hp; h++) {
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+#endif
+ if ((strncmp(hp, el->el_line.buffer, (size_t)
+ (el->el_line.lastchar - el->el_line.buffer)) ||
+ hp[el->el_line.lastchar - el->el_line.buffer]) &&
+ c_hmatch(el, hp))
+ found = h;
+ hp = HIST_NEXT(el);
+ }
+
+ if (!found) { /* is it the current history number? */
+ if (!c_hmatch(el, el->el_history.buf)) {
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "not found\n");
+#endif
+ return (CC_ERROR);
+ }
+ }
+ el->el_history.eventno = found;
+
+ return (hist_get(el));
+}
+
+
+/* ed_prev_line():
+ * Move up one line
+ * Could be [k] [^p]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_line(EditLine *el, int c __attribute__((unused)))
+{
+ char *ptr;
+ int nchars = c_hpos(el);
+
+ /*
+ * Move to the line requested
+ */
+ if (*(ptr = el->el_line.cursor) == '\n')
+ ptr--;
+
+ for (; ptr >= el->el_line.buffer; ptr--)
+ if (*ptr == '\n' && --el->el_state.argument <= 0)
+ break;
+
+ if (el->el_state.argument > 0)
+ return (CC_ERROR);
+
+ /*
+ * Move to the beginning of the line
+ */
+ for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
+ continue;
+
+ /*
+ * Move to the character requested
+ */
+ for (ptr++;
+ nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+ ptr++)
+ continue;
+
+ el->el_line.cursor = ptr;
+ return (CC_CURSOR);
+}
+
+
+/* ed_next_line():
+ * Move down one line
+ * Could be [j] [^n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_line(EditLine *el, int c __attribute__((unused)))
+{
+ char *ptr;
+ int nchars = c_hpos(el);
+
+ /*
+ * Move to the line requested
+ */
+ for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
+ if (*ptr == '\n' && --el->el_state.argument <= 0)
+ break;
+
+ if (el->el_state.argument > 0)
+ return (CC_ERROR);
+
+ /*
+ * Move to the character requested
+ */
+ for (ptr++;
+ nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+ ptr++)
+ continue;
+
+ el->el_line.cursor = ptr;
+ return (CC_CURSOR);
+}
+
+
+/* ed_command():
+ * Editline extended command
+ * [M-X] [:]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_command(EditLine *el, int c __attribute__((unused)))
+{
+ char tmpbuf[EL_BUFSIZ];
+ int tmplen;
+
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+
+ c_insert(el, 3); /* prompt + ": " */
+ *el->el_line.cursor++ = '\n';
+ *el->el_line.cursor++ = ':';
+ *el->el_line.cursor++ = ' ';
+ re_refresh(el);
+
+ tmplen = c_gets(el, tmpbuf);
+ tmpbuf[tmplen] = '\0';
+
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+
+ if (parse_line(el, tmpbuf) == -1)
+ return (CC_ERROR);
+ else
+ return (CC_REFRESH);
+}
diff --git a/cmd-line-utils/libedit/compat.h b/cmd-line-utils/libedit/compat.h
new file mode 100644
index 00000000000..3693a2db809
--- /dev/null
+++ b/cmd-line-utils/libedit/compat.h
@@ -0,0 +1,43 @@
+#ifndef __LIBEDIT_COMPATH_H
+#define __LIBEDIT_COMPATH_H
+
+#define __RCSID(x)
+#define __COPYRIGHT(x)
+
+#include "compat_conf.h"
+
+#ifndef HAVE_VIS_H
+/* string visual representation - may want to reimplement */
+#define strvis(d,s,m) strcpy(d,s)
+#define strunvis(d,s) strcpy(d,s)
+#endif
+
+#ifndef HAVE_FGETLN
+#include "fgetln.h"
+#endif
+
+#ifndef HAVE_ISSETUGID
+#define issetugid() (getuid()!=geteuid() || getegid()!=getgid())
+#endif
+
+#ifndef HAVE_STRLCPY
+#include "strlcpy.h"
+#endif
+
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
+#define __attribute__(A)
+#endif
+
+#endif
diff --git a/cmd-line-utils/libedit/compat_conf.h b/cmd-line-utils/libedit/compat_conf.h
new file mode 100644
index 00000000000..e2b9557f5b1
--- /dev/null
+++ b/cmd-line-utils/libedit/compat_conf.h
@@ -0,0 +1,2 @@
+
+#include "my_config.h"
diff --git a/cmd-line-utils/libedit/editline.3 b/cmd-line-utils/libedit/editline.3
new file mode 100644
index 00000000000..1b812ebcc79
--- /dev/null
+++ b/cmd-line-utils/libedit/editline.3
@@ -0,0 +1,619 @@
+.\" $NetBSD: editline.3,v 1.21 2001/04/02 18:29:49 wiz Exp $
+.\"
+.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the NetBSD
+.\" Foundation, Inc. and its contributors.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd November 12, 1999
+.Os
+.Dt EDITLINE 3
+.Sh NAME
+.Nm editline ,
+.Nm el_init ,
+.Nm el_end ,
+.Nm el_reset ,
+.Nm el_gets ,
+.Nm el_getc ,
+.Nm el_push ,
+.Nm el_parse ,
+.Nm el_set ,
+.Nm el_source ,
+.Nm el_resize ,
+.Nm el_line ,
+.Nm el_insertstr ,
+.Nm el_deletestr ,
+.Nm history_init ,
+.Nm history_end ,
+.Nm history
+.Nd line editor and history functions
+.Sh LIBRARY
+.Lb libedit
+.Sh SYNOPSIS
+.Fd #include <histedit.h>
+.Ft EditLine *
+.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr"
+.Ft void
+.Fn el_end "EditLine *e"
+.Ft void
+.Fn el_reset "EditLine *e"
+.Ft const char *
+.Fn el_gets "EditLine *e" "int *count"
+.Ft int
+.Fn el_getc "EditLine *e" "char *ch"
+.Ft void
+.Fn el_push "EditLine *e" "const char *str"
+.Ft int
+.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
+.Ft int
+.Fn el_set "EditLine *e" "int op" "..."
+.Ft int
+.Fn el_get "EditLine *e" "int op" "void *result"
+.Ft int
+.Fn el_source "EditLine *e" "const char *file"
+.Ft void
+.Fn el_resize "EditLine *e"
+.Ft const LineInfo *
+.Fn el_line "EditLine *e"
+.Ft int
+.Fn el_insertstr "EditLine *e" "const char *str"
+.Ft void
+.Fn el_deletestr "EditLine *e" "int count"
+.Ft History *
+.Fn history_init
+.Ft void
+.Fn history_end "History *h"
+.Ft int
+.Fn history "History *h" "HistEvent *ev" "int op" "..."
+.Sh DESCRIPTION
+The
+.Nm
+library provides generic line editing and history functions,
+similar to those found in
+.Xr sh 1 .
+.Pp
+These functions are available in the
+.Nm libedit
+library (which needs the
+.Nm libtermcap
+library).
+Programs should be linked with
+.Fl ledit ltermcap .
+.Sh LINE EDITING FUNCTIONS
+The line editing functions use a common data structure,
+.Fa EditLine ,
+which is created by
+.Fn el_init
+and freed by
+.Fn el_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn el_init
+Initialise the line editor, and return a data structure
+to be used by all other line editing functions.
+.Fa prog
+is the name of the invoking program, used when reading the
+.Xr editrc 5
+file to determine which settings to use.
+.Fa fin ,
+.Fa fout
+and
+.Fa ferr
+are the input, output, and error streams (respectively) to use.
+In this documentation, references to
+.Dq the tty
+are actually to this input/output stream combination.
+.It Fn el_end
+Clean up and finish with
+.Fa e ,
+assumed to have been created with
+.Fn el_init .
+.It Fn el_reset
+Reset the tty and the parser.
+This should be called after an error which may have upset the tty's
+state.
+.It Fn el_gets
+Read a line from the tty.
+.Fa count
+is modified to contain the number of characters read.
+Returns the line read if successful, or
+.Dv NULL
+if no characters were read or if an error occurred.
+.It Fn el_getc
+Read a character from the tty.
+.Fa ch
+is modified to contain the character read.
+Returns the number of characters read if successful, -1 otherwise.
+.It Fn el_push
+Pushes
+.Fa str
+back onto the input stream.
+This is used by the macro expansion mechanism.
+Refer to the description of
+.Ic bind
+.Fl s
+in
+.Xr editrc 5
+for more information.
+.It Fn el_parse
+Parses the
+.Fa argv
+array (which is
+.Fa argc
+elements in size)
+to execute builtin
+.Nm
+commands.
+If the command is prefixed with
+.Dq prog:
+then
+.Fn el_parse
+will only execute the command if
+.Dq prog
+matches the
+.Fa prog
+argument supplied to
+.Fn el_init .
+The return value is
+-1 if the command is unknown,
+0 if there was no error or
+.Dq prog
+didn't match, or
+1 if the command returned an error.
+Refer to
+.Xr editrc 5
+for more information.
+.It Fn el_set
+Set
+.Nm
+parameters.
+.Fa op
+determines which parameter to set, and each operation has its
+own parameter list.
+.Pp
+The following values for
+.Fa op
+are supported, along with the required argument list:
+.Bl -tag -width 4n
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
+Define prompt printing function as
+.Fa f ,
+which is to return a string that contains the prompt.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
+Define right side prompt printing function as
+.Fa f ,
+which is to return a string that contains the prompt.
+.It Dv EL_TERMINAL , Fa "const char *type"
+Define terminal type of the tty to be
+.Fa type ,
+or to
+.Ev TERM
+if
+.Fa type
+is
+.Dv NULL .
+.It Dv EL_EDITOR , Fa "const char *mode"
+Set editing mode to
+.Fa mode ,
+which must be one of
+.Dq emacs
+or
+.Dq vi .
+.It Dv EL_SIGNAL , Fa "int flag"
+If
+.Fa flag
+is non-zero,
+.Nm
+will install its own signal handler for the following signals when
+reading command input:
+.Dv SIGCONT ,
+.Dv SIGHUP ,
+.Dv SIGINT ,
+.Dv SIGQUIT ,
+.Dv SIGSTOP ,
+.Dv SIGTERM ,
+.Dv SIGTSTP ,
+and
+.Dv SIGWINCH .
+Otherwise, the current signal handlers will be used.
+.It Dv EL_BIND , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic bind
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_ECHOTC , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic echotc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_SETTC , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic settc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_SETTY , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic setty
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_TELLTC , Xo
+.Fa "const char *" ,
+.Fa "..." ,
+.Dv NULL
+.Xc
+Perform the
+.Ic telltc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_ADDFN , Xo
+.Fa "const char *name" ,
+.Fa "const char *help" ,
+.Fa "unsigned char (*func)(EditLine *e, int ch)
+.Xc
+Add a user defined function,
+.Fn func ,
+referred to as
+.Fa name
+which is invoked when a key which is bound to
+.Fa name
+is entered.
+.Fa help
+is a description of
+.Fa name .
+At invocation time,
+.Fa ch
+is the key which caused the invocation.
+The return value of
+.Fn func
+should be one of:
+.Bl -tag -width "CC_REDISPLAY"
+.It Dv CC_NORM
+Add a normal character.
+.It Dv CC_NEWLINE
+End of line was entered.
+.It Dv CC_EOF
+EOF was entered.
+.It Dv CC_ARGHACK
+Expecting further command input as arguments, do nothing visually.
+.It Dv CC_REFRESH
+Refresh display.
+.It Dv CC_REFRESH_BEEP
+Refresh display, and beep.
+.It Dv CC_CURSOR
+Cursor moved, so update and perform
+.Dv CC_REFRESH.
+.It Dv CC_REDISPLAY
+Redisplay entire input line.
+This is useful if a key binding outputs extra information.
+.It Dv CC_ERROR
+An error occurred.
+Beep, and flush tty.
+.It Dv CC_FATAL
+Fatal error, reset tty to known state.
+.El
+.It Dv EL_HIST , Xo
+.Fa "History *(*func)(History *, int op, ...)" ,
+.Fa "const char *ptr"
+.Xc
+Defines which history function to use, which is usually
+.Fn history .
+.Fa ptr
+should be the value returned by
+.Fn history_init .
+.It Dv EL_EDITMODE , Fa "int flag"
+If
+.Fa flag
+is non-zero,
+editing is enabled (the default).
+Note that this is only an indication, and does not
+affect the operation of
+.Nm "" .
+At this time, it is the caller's responsibility to
+check this
+(using
+.Fn el_get )
+to determine if editing should be enabled or not.
+.El
+.It Fn el_get
+Get
+.Nm
+parameters.
+.Fa op
+determines which parameter to retrieve into
+.Fa result .
+.Pp
+The following values for
+.Fa op
+are supported, along with actual type of
+.Fa result :
+.Bl -tag -width 4n
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
+Return a pointer to the function that displays the prompt.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
+Return a pointer to the function that displays the rightside prompt.
+.It Dv EL_EDITOR , Fa "const char *"
+Return the name of the editor, which will be one of
+.Dq emacs
+or
+.Dq vi .
+.It Dv EL_SIGNAL , Fa "int *"
+Return non-zero if
+.Nm
+has installed private signal handlers (see
+.Fn el_get
+above).
+.It Dv EL_EDITMODE, Fa "int *"
+Return non-zero if editing is enabled.
+.El
+.It Fn el_source
+Initialise
+.Nm
+by reading the contents of
+.Fa file .
+.Fn el_parse
+is called for each line in
+.Fa file .
+If
+.Fa file
+is
+.Dv NULL ,
+try
+.Pa $PWD/.editrc
+then
+.Pa $HOME/.editrc .
+Refer to
+.Xr editrc 5
+for details on the format of
+.Fa file .
+.It Fn el_resize
+Must be called if the terminal size changes.
+If
+.Dv EL_SIGNAL
+has been set with
+.Fn el_set ,
+then this is done automatically.
+Otherwise, it's the responsibility of the application to call
+.Fn el_resize
+on the appropriate occasions.
+.It Fn el_line
+Return the editing information for the current line in a
+.Fa LineInfo
+structure, which is defined as follows:
+.Bd -literal
+typedef struct lineinfo {
+ const char *buffer; /* address of buffer */
+ const char *cursor; /* address of cursor */
+ const char *lastchar; /* address of last character */
+} LineInfo;
+.Ed
+.It Fn el_insertstr
+Insert
+.Fa str
+into the line at the cursor.
+Returns -1 if
+.Fa str
+is empty or won't fit, and 0 otherwise.
+.It Fn el_deletestr
+Delete
+.Fa num
+characters before the cursor.
+.El
+.Sh HISTORY LIST FUNCTIONS
+The history functions use a common data structure,
+.Fa History ,
+which is created by
+.Fn history_init
+and freed by
+.Fn history_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn history_init
+Initialise the history list, and return a data structure
+to be used by all other history list functions.
+.It Fn history_end
+Clean up and finish with
+.Fa h ,
+assumed to have been created with
+.Fn history_init .
+.It Fn history
+Perform operation
+.Fa op
+on the history list, with optional arguments as needed by the
+operation.
+.Fa ev
+is changed accordingly to operation.
+The following values for
+.Fa op
+are supported, along with the required argument list:
+.Bl -tag -width 4n
+.It Dv H_SETSIZE , Fa "int size"
+Set size of history to
+.Fa size
+elements.
+.It Dv H_GETSIZE
+Get number of events currently in history.
+.It Dv H_END
+Cleans up and finishes with
+.Fa h ,
+assumed to be created with
+.Fn history_init .
+.It Dv H_CLEAR
+Clear the history.
+.It Dv H_FUNC , Xo
+.Fa "void *ptr" ,
+.Fa "history_gfun_t first" ,
+.Fa "history_gfun_t next" ,
+.Fa "history_gfun_t last" ,
+.Fa "history_gfun_t prev" ,
+.Fa "history_gfun_t curr" ,
+.Fa "history_sfun_t set" ,
+.Fa "history_vfun_t clear" ,
+.Fa "history_efun_t enter" ,
+.Fa "history_efun_t add"
+.Xc
+Define functions to perform various history operations.
+.Fa ptr
+is the argument given to a function when it's invoked.
+.It Dv H_FIRST
+Return the first element in the history.
+.It Dv H_LAST
+Return the last element in the history.
+.It Dv H_PREV
+Return the previous element in the history.
+.It Dv H_NEXT
+Return the next element in the history.
+.It Dv H_CURR
+Return the current element in the history.
+.It Dv H_SET
+Set the cursor to point to the requested element.
+.It Dv H_ADD , Fa "const char *str"
+Append
+.Fa str
+to the current element of the history, or create an element with
+.It Dv H_APPEND , Fa "const char *str"
+Append
+.Fa str
+to the last new element of the history.
+.It Dv H_ENTER , Fa "const char *str"
+Add
+.Fa str
+as a new element to the history, and, if necessary,
+removing the oldest entry to keep the list to the created size.
+.It Dv H_PREV_STR , Fa "const char *str"
+Return the closest previous event that starts with
+.Fa str .
+.It Dv H_NEXT_STR , Fa "const char *str"
+Return the closest next event that starts with
+.Fa str .
+.It Dv H_PREV_EVENT , Fa "int e"
+Return the previous event numbered
+.Fa e .
+.It Dv H_NEXT_EVENT , Fa "int e"
+Return the next event numbered
+.Fa e .
+.It Dv H_LOAD , Fa "const char *file"
+Load the history list stored in
+.Fa file .
+.It Dv H_SAVE , Fa "const char *file"
+Save the history list to
+.Fa file .
+.El
+.Pp
+.Fn history
+returns 0 if the operation
+.Fa op
+succeeds. Otherwise, -1 is returned and
+.Fa ev
+is updated to contain more details about the error.
+.El
+.\"XXX.Sh EXAMPLES
+.\"XXX: provide some examples
+.Sh SEE ALSO
+.Xr editrc 5 ,
+.Xr sh 1 ,
+.Xr signal 3 ,
+.Xr termcap 3
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Bx 4.4 .
+.Dv CC_REDISPLAY
+appeared in
+.Nx 1.3 .
+.Dv CC_REFRESH_BEEP ,
+.Dv EL_EDITMODE
+and the readline emulation appeared in
+.Nx 1.4 .
+.Dv EL_RPROMPT
+appeared in
+.Nx 1.5 .
+.Sh AUTHORS
+The
+.Nm
+library was written by Christos Zoulas.
+Luke Mewburn wrote this manual and implemented
+.Dv CC_REDISPLAY ,
+.Dv CC_REFRESH_BEEP ,
+.Dv EL_EDITMODE ,
+and
+.Dv EL_RPROMPT .
+Jaromir Dolecek implemented the readline emulation.
+.Sh BUGS
+The tokenization functions are not publically defined in
+.Fd <histedit.h>.
+.Pp
+At this time, it is the responsibility of the caller to
+check the result of the
+.Dv EL_EDITMODE
+operation of
+.Fn el_get
+(after an
+.Fn el_source
+or
+.Fn el_parse )
+to determine if
+.Nm
+should be used for further input.
+I.e.,
+.Dv EL_EDITMODE
+is purely an indication of the result of the most recent
+.Xr editrc 5
+.Ic edit
+command.
diff --git a/cmd-line-utils/libedit/editrc.5 b/cmd-line-utils/libedit/editrc.5
new file mode 100644
index 00000000000..b1122618939
--- /dev/null
+++ b/cmd-line-utils/libedit/editrc.5
@@ -0,0 +1,491 @@
+.\" $NetBSD: editrc.5,v 1.11 2001/06/19 13:42:09 wiz Exp $
+.\"
+.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the NetBSD
+.\" Foundation, Inc. and its contributors.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd November 8, 2000
+.Os
+.Dt EDITRC 5
+.Sh NAME
+.Nm editrc
+.Nd configuration file for editline library
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+file defines various settings to be used by the
+.Xr editline 3
+library.
+.Pp
+The format of each line is:
+.Dl [prog:]command [arg [...]]
+.Pp
+.Ar command
+is one of the
+.Xr editline 3
+builtin commands.
+Refer to
+.Sx BUILTIN COMMANDS
+for more information.
+.Pp
+.Ar prog
+is the program name string that a program defines when it calls
+.Xr el_init 3
+to setup
+.Xr editline 3 ,
+which is usually
+.Va argv[0] .
+.Ar command
+will be executed for any program which matches
+.Ar prog .
+.Pp
+.Ar prog
+may also be a
+.Xr regex 3
+style
+regular expression, in which case
+.Ar command
+will be executed for any program that matches the regular expression.
+.Pp
+If
+.Ar prog
+is absent,
+.Ar command
+is executed for all programs.
+.Sh BUILTIN COMMANDS
+The
+.Nm editline
+library has some builtin commands, which affect the way
+that the line editing and history functions operate.
+These are based on similar named builtins present in the
+.Xr tcsh 1
+shell.
+.Pp
+The following builtin commands are available:
+.Bl -tag -width 4n
+.It Ic bind Xo
+.Op Fl a
+.Op Fl e
+.Op Fl k
+.Op Fl l
+.Op Fl r
+.Op Fl s
+.Op Fl v
+.Op Ar key Op Ar command
+.Xc
+Without options, list all bound keys, and the editor command to which
+each is bound.
+If
+.Ar key
+is supplied, show the bindings for
+.Ar key .
+If
+.Ar key command
+is supplied, bind
+.Ar command
+to
+.Ar key .
+Options include:
+.Bl -tag -width 4n
+.It Fl e
+Bind all keys to the standard GNU Emacs-like bindings.
+.It Fl v
+Bind all keys to the standard
+.Xr vi 1 -like
+bindings.
+.It Fl a
+List or change key bindings in the
+.Xr vi 1
+mode alternate (command mode) key map.
+.It Fl k
+.Ar key
+is interpreted as a symbolic arrow key name, which may be one of
+.Sq up ,
+.Sq down ,
+.Sq left
+or
+.Sq right .
+.It Fl l
+List all editor commands and a short description of each.
+.It Fl r
+Remove a key's binding.
+.It Fl s
+.Ar command
+is taken as a literal string and treated as terminal input when
+.Ar key
+is typed.
+Bound keys in
+.Ar command
+are themselves reinterpreted, and this continues for ten levels of
+interpretation.
+.El
+.Pp
+.Ar command
+may be one of the commands documented in
+.Sx "EDITOR COMMANDS"
+below, or another key.
+.Pp
+.Ar key
+and
+.Ar command
+can contain control characters of the form
+.Sm off
+.Sq No ^ Ar character
+.Sm on
+.Po
+e.g.
+.Sq ^A
+.Pc ,
+and the following backslashed escape sequences:
+.Pp
+.Bl -tag -compact -offset indent -width 4n
+.It Ic \ea
+Bell
+.It Ic \eb
+Backspace
+.It Ic \ee
+Escape
+.It Ic \ef
+Formfeed
+.It Ic \en
+Newline
+.It Ic \er
+Carriage return
+.It Ic \et
+Horizontal tab
+.It Ic \ev
+Vertical tab
+.Sm off
+.It Sy \e Ar nnn
+.Sm on
+The ASCII character corresponding to the octal number
+.Ar nnn .
+.El
+.Pp
+.Sq \e
+nullifies the special meaning of the following character,
+if it has any, notably
+.Sq \e
+and
+.Sq ^ .
+.It Ic echotc Xo
+.Op Fl sv
+.Ar arg
+.Ar ...
+.Xc
+Exercise terminal capabilities given in
+.Ar arg Ar ... .
+If
+.Ar arg
+is
+.Sq baud ,
+.Sq cols ,
+.Sq lines ,
+.Sq rows ,
+.Sq meta or
+.Sq tabs ,
+the value of that capability is printed, with
+.Dq yes
+or
+.Dq no
+indicating that the terminal does or does not have that capability.
+.Pp
+.Fl s
+returns an emptry string for non-existent capabilities, rather than
+causing an error.
+.Fl v
+causes messages to be verbose.
+.It Ic edit Op Li on | Li off
+Enable or disable the
+.Nm editline
+functionality in a program.
+.It Ic history
+List the history.
+.It Ic telltc
+List the values of all the terminal capabilities (see
+.Xr termcap 5 ).
+.It Ic settc Ar cap Ar val
+Set the terminal capability
+.Ar cap
+to
+.Ar val ,
+as defined in
+.Xr termcap 5 .
+No sanity checking is done.
+.It Ic setty Xo
+.Op Fl a
+.Op Fl d
+.Op Fl q
+.Op Fl x
+.Op Ar +mode
+.Op Ar -mode
+.Op Ar mode
+.Xc
+Control which tty modes that
+.Nm
+won't allow the user to change.
+.Fl d ,
+.Fl q
+or
+.Fl x
+tells
+.Ic setty
+to act on the
+.Sq edit ,
+.Sq quote
+or
+.Sq execute
+set of tty modes respectively; defaulting to
+.Fl x .
+.Pp
+Without other arguments,
+.Ic setty
+lists the modes in the chosen set which are fixed on
+.Po
+.Sq +mode
+.Pc
+or off
+.Po
+.Sq -mode
+.Pc .
+.Fl a
+lists all tty modes in the chosen set regardless of the setting.
+With
+.Ar +mode ,
+.Ar -mode
+or
+.Ar mode ,
+fixes
+.Ar mode
+on or off or removes control of
+.Ar mode
+in the chosen set.
+.El
+.Sh EDITOR COMMANDS
+The following editor commands are available for use in key bindings:
+.\" Section automatically generated with makelist
+.Bl -tag -width 4n
+.It Ic vi-paste-next
+Vi paste previous deletion to the right of the cursor.
+.It Ic vi-paste-prev
+Vi paste previous deletion to the left of the cursor.
+.It Ic vi-prev-space-word
+Vi move to the previous space delimited word.
+.It Ic vi-prev-word
+Vi move to the previous word.
+.It Ic vi-next-space-word
+Vi move to the next space delimited word.
+.It Ic vi-next-word
+Vi move to the next word.
+.It Ic vi-change-case
+Vi change case of character under the cursor and advance one character.
+.It Ic vi-change-meta
+Vi change prefix command.
+.It Ic vi-insert-at-bol
+Vi enter insert mode at the beginning of line.
+.It Ic vi-replace-char
+Vi replace character under the cursor with the next character typed.
+.It Ic vi-replace-mode
+Vi enter replace mode.
+.It Ic vi-substitute-char
+Vi replace character under the cursor and enter insert mode.
+.It Ic vi-substitute-line
+Vi substitute entire line.
+.It Ic vi-change-to-eol
+Vi change to end of line.
+.It Ic vi-insert
+Vi enter insert mode.
+.It Ic vi-add
+Vi enter insert mode after the cursor.
+.It Ic vi-add-at-eol
+Vi enter insert mode at end of line.
+.It Ic vi-delete-meta
+Vi delete prefix command.
+.It Ic vi-end-word
+Vi move to the end of the current space delimited word.
+.It Ic vi-to-end-word
+Vi move to the end of the current word.
+.It Ic vi-undo
+Vi undo last change.
+.It Ic vi-command-mode
+Vi enter command mode (use alternative key bindings).
+.It Ic vi-zero
+Vi move to the beginning of line.
+.It Ic vi-delete-prev-char
+Vi move to previous character (backspace).
+.It Ic vi-list-or-eof
+Vi list choices for completion or indicate end of file if empty line.
+.It Ic vi-kill-line-prev
+Vi cut from beginning of line to cursor.
+.It Ic vi-search-prev
+Vi search history previous.
+.It Ic vi-search-next
+Vi search history next.
+.It Ic vi-repeat-search-next
+Vi repeat current search in the same search direction.
+.It Ic vi-repeat-search-prev
+Vi repeat current search in the opposite search direction.
+.It Ic vi-next-char
+Vi move to the character specified next.
+.It Ic vi-prev-char
+Vi move to the character specified previous.
+.It Ic vi-to-next-char
+Vi move up to the character specified next.
+.It Ic vi-to-prev-char
+Vi move up to the character specified previous.
+.It Ic vi-repeat-next-char
+Vi repeat current character search in the same search direction.
+.It Ic vi-repeat-prev-char
+Vi repeat current character search in the opposite search direction.
+.It Ic em-delete-or-list
+Delete character under cursor or list completions if at end of line.
+.It Ic em-delete-next-word
+Cut from cursor to end of current word.
+.It Ic em-yank
+Paste cut buffer at cursor position.
+.It Ic em-kill-line
+Cut the entire line and save in cut buffer.
+.It Ic em-kill-region
+Cut area between mark and cursor and save in cut buffer.
+.It Ic em-copy-region
+Copy area between mark and cursor to cut buffer.
+.It Ic em-gosmacs-traspose
+Exchange the two characters before the cursor.
+.It Ic em-next-word
+Move next to end of current word.
+.It Ic em-upper-case
+Uppercase the characters from cursor to end of current word.
+.It Ic em-capitol-case
+Capitalize the characters from cursor to end of current word.
+.It Ic em-lower-case
+Lowercase the characters from cursor to end of current word.
+.It Ic em-set-mark
+Set the mark at cursor.
+.It Ic em-exchange-mark
+Exchange the cursor and mark.
+.It Ic em-universal-argument
+Universal argument (argument times 4).
+.It Ic em-meta-next
+Add 8th bit to next character typed.
+.It Ic em-toggle-overwrite
+Switch from insert to overwrite mode or vice versa.
+.It Ic em-copy-prev-word
+Copy current word to cursor.
+.It Ic em-inc-search-next
+Emacs incremental next search.
+.It Ic em-inc-search-prev
+Emacs incremental reverse search.
+.It Ic ed-end-of-file
+Indicate end of file.
+.It Ic ed-insert
+Add character to the line.
+.It Ic ed-delete-prev-word
+Delete from beginning of current word to cursor.
+.It Ic ed-delete-next-char
+Delete character under cursor.
+.It Ic ed-kill-line
+Cut to the end of line.
+.It Ic ed-move-to-end
+Move cursor to the end of line.
+.It Ic ed-move-to-beg
+Move cursor to the beginning of line.
+.It Ic ed-transpose-chars
+Exchange the character to the left of the cursor with the one under it.
+.It Ic ed-next-char
+Move to the right one character.
+.It Ic ed-prev-word
+Move to the beginning of the current word.
+.It Ic ed-prev-char
+Move to the left one character.
+.It Ic ed-quoted-insert
+Add the next character typed verbatim.
+.It Ic ed-digit
+Adds to argument or enters a digit.
+.It Ic ed-argument-digit
+Digit that starts argument.
+.It Ic ed-unassigned
+Indicates unbound character.
+.It Ic ed-tty-sigint
+Tty interrupt character.
+.It Ic ed-tty-dsusp
+Tty delayed suspend character.
+.It Ic ed-tty-flush-output
+Tty flush output characters.
+.It Ic ed-tty-sigquit
+Tty quit character.
+.It Ic ed-tty-sigtstp
+Tty suspend character.
+.It Ic ed-tty-stop-output
+Tty disallow output characters.
+.It Ic ed-tty-start-output
+Tty allow output characters.
+.It Ic ed-newline
+Execute command.
+.It Ic ed-delete-prev-char
+Delete the character to the left of the cursor.
+.It Ic ed-clear-screen
+Clear screen leaving current line at the top.
+.It Ic ed-redisplay
+Redisplay everything.
+.It Ic ed-start-over
+Erase current line and start from scratch.
+.It Ic ed-sequence-lead-in
+First character in a bound sequence.
+.It Ic ed-prev-history
+Move to the previous history line.
+.It Ic ed-next-history
+Move to the next history line.
+.It Ic ed-search-prev-history
+Search previous in history for a line matching the current.
+.It Ic ed-search-next-history
+Search next in history for a line matching the current.
+.It Ic ed-prev-line
+Move up one line.
+.It Ic ed-next-line
+Move down one line.
+.It Ic ed-command
+Editline extended command.
+.El
+.\" End of section automatically generated with makelist
+.Sh SEE ALSO
+.Xr editline 3 ,
+.Xr regex 3 ,
+.Xr termcap 5
+.Sh AUTHORS
+The
+.Nm editline
+library was written by Christos Zoulas,
+and this manual was written by Luke Mewburn,
+with some sections inspired by
+.Xr tcsh 1 .
diff --git a/cmd-line-utils/libedit/el.c b/cmd-line-utils/libedit/el.c
new file mode 100644
index 00000000000..d436d113419
--- /dev/null
+++ b/cmd-line-utils/libedit/el.c
@@ -0,0 +1,468 @@
+/* $NetBSD: el.c,v 1.21 2001/01/05 22:45:30 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * el.c: EditLine interface functions
+ */
+#include "sys.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "el.h"
+
+/* el_init():
+ * Initialize editline and set default parameters.
+ */
+public EditLine *
+el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
+{
+
+ EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
+#ifdef DEBUG
+ char *tty;
+#endif
+
+ if (el == NULL)
+ return (NULL);
+
+ memset(el, 0, sizeof(EditLine));
+
+ el->el_infd = fileno(fin);
+ el->el_outfile = fout;
+ el->el_errfile = ferr;
+ el->el_prog = strdup(prog);
+
+ /*
+ * Initialize all the modules. Order is important!!!
+ */
+ el->el_flags = 0;
+
+ (void) term_init(el);
+ (void) key_init(el);
+ (void) map_init(el);
+ if (tty_init(el) == -1)
+ el->el_flags |= NO_TTY;
+ (void) ch_init(el);
+ (void) search_init(el);
+ (void) hist_init(el);
+ (void) prompt_init(el);
+ (void) sig_init(el);
+
+ return (el);
+}
+
+
+/* el_end():
+ * Clean up.
+ */
+public void
+el_end(EditLine *el)
+{
+
+ if (el == NULL)
+ return;
+
+ el_reset(el);
+
+ term_end(el);
+ key_end(el);
+ map_end(el);
+ tty_end(el);
+ ch_end(el);
+ search_end(el);
+ hist_end(el);
+ prompt_end(el);
+ sig_end(el);
+
+ el_free((ptr_t) el->el_prog);
+ el_free((ptr_t) el);
+}
+
+
+/* el_reset():
+ * Reset the tty and the parser
+ */
+public void
+el_reset(EditLine *el)
+{
+
+ tty_cookedmode(el);
+ ch_reset(el); /* XXX: Do we want that? */
+}
+
+
+/* el_set():
+ * set the editline parameters
+ */
+public int
+el_set(EditLine *el, int op, ...)
+{
+ va_list va;
+ int rv;
+ va_start(va, op);
+
+ if (el == NULL)
+ return (-1);
+ switch (op) {
+ case EL_PROMPT:
+ case EL_RPROMPT:
+ rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
+ break;
+
+ case EL_TERMINAL:
+ rv = term_set(el, va_arg(va, char *));
+ break;
+
+ case EL_EDITOR:
+ rv = map_set_editor(el, va_arg(va, char *));
+ break;
+
+ case EL_SIGNAL:
+ if (va_arg(va, int))
+ el->el_flags |= HANDLE_SIGNALS;
+ else
+ el->el_flags &= ~HANDLE_SIGNALS;
+ rv = 0;
+ break;
+
+ case EL_BIND:
+ case EL_TELLTC:
+ case EL_SETTC:
+ case EL_ECHOTC:
+ case EL_SETTY:
+ {
+ const char *argv[20];
+ int i;
+
+ for (i = 1; i < 20; i++)
+ if ((argv[i] = va_arg(va, char *)) == NULL)
+ break;
+
+ switch (op) {
+ case EL_BIND:
+ argv[0] = "bind";
+ rv = map_bind(el, i, argv);
+ break;
+
+ case EL_TELLTC:
+ argv[0] = "telltc";
+ rv = term_telltc(el, i, argv);
+ break;
+
+ case EL_SETTC:
+ argv[0] = "settc";
+ rv = term_settc(el, i, argv);
+ break;
+
+ case EL_ECHOTC:
+ argv[0] = "echotc";
+ rv = term_echotc(el, i, argv);
+ break;
+
+ case EL_SETTY:
+ argv[0] = "setty";
+ rv = tty_stty(el, i, argv);
+ break;
+
+ default:
+ rv = -1;
+ EL_ABORT((el->el_errfile, "Bad op %d\n", op));
+ break;
+ }
+ break;
+ }
+
+ case EL_ADDFN:
+ {
+ char *name = va_arg(va, char *);
+ char *help = va_arg(va, char *);
+ el_func_t func = va_arg(va, el_func_t);
+
+ rv = map_addfunc(el, name, help, func);
+ break;
+ }
+
+ case EL_HIST:
+ {
+ hist_fun_t func = va_arg(va, hist_fun_t);
+ ptr_t ptr = va_arg(va, char *);
+
+ rv = hist_set(el, func, ptr);
+ break;
+ }
+
+ case EL_EDITMODE:
+ if (va_arg(va, int))
+ el->el_flags &= ~EDIT_DISABLED;
+ else
+ el->el_flags |= EDIT_DISABLED;
+ rv = 0;
+ break;
+
+ default:
+ rv = -1;
+ }
+
+ va_end(va);
+ return (rv);
+}
+
+
+/* el_get():
+ * retrieve the editline parameters
+ */
+public int
+el_get(EditLine *el, int op, void *ret)
+{
+ int rv;
+
+ if (el == NULL || ret == NULL)
+ return (-1);
+ switch (op) {
+ case EL_PROMPT:
+ case EL_RPROMPT:
+ rv = prompt_get(el, (el_pfunc_t *) & ret, op);
+ break;
+
+ case EL_EDITOR:
+ rv = map_get_editor(el, (const char **) &ret);
+ break;
+
+ case EL_SIGNAL:
+ *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
+ rv = 0;
+ break;
+
+ case EL_EDITMODE:
+ *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
+ rv = 0;
+ break;
+
+#if 0 /* XXX */
+ case EL_TERMINAL:
+ rv = term_get(el, (const char *) &ret);
+ break;
+
+ case EL_BIND:
+ case EL_TELLTC:
+ case EL_SETTC:
+ case EL_ECHOTC:
+ case EL_SETTY:
+ {
+ char *argv[20];
+ int i;
+
+ for (i = 1; i < 20; i++)
+ if ((argv[i] = va_arg(va, char *)) == NULL)
+ break;
+
+ switch (op) {
+ case EL_BIND:
+ argv[0] = "bind";
+ rv = map_bind(el, i, argv);
+ break;
+
+ case EL_TELLTC:
+ argv[0] = "telltc";
+ rv = term_telltc(el, i, argv);
+ break;
+
+ case EL_SETTC:
+ argv[0] = "settc";
+ rv = term_settc(el, i, argv);
+ break;
+
+ case EL_ECHOTC:
+ argv[0] = "echotc";
+ rv = term_echotc(el, i, argv);
+ break;
+
+ case EL_SETTY:
+ argv[0] = "setty";
+ rv = tty_stty(el, i, argv);
+ break;
+
+ default:
+ rv = -1;
+ EL_ABORT((el->errfile, "Bad op %d\n", op));
+ break;
+ }
+ break;
+ }
+
+ case EL_ADDFN:
+ {
+ char *name = va_arg(va, char *);
+ char *help = va_arg(va, char *);
+ el_func_t func = va_arg(va, el_func_t);
+
+ rv = map_addfunc(el, name, help, func);
+ break;
+ }
+
+ case EL_HIST:
+ {
+ hist_fun_t func = va_arg(va, hist_fun_t);
+ ptr_t ptr = va_arg(va, char *);
+ rv = hist_set(el, func, ptr);
+ }
+ break;
+#endif /* XXX */
+
+ default:
+ rv = -1;
+ }
+
+ return (rv);
+}
+
+
+/* el_line():
+ * Return editing info
+ */
+public const LineInfo *
+el_line(EditLine *el)
+{
+
+ return (const LineInfo *) (void *) &el->el_line;
+}
+
+static const char elpath[] = "/.editrc";
+
+/* el_source():
+ * Source a file
+ */
+public int
+el_source(EditLine *el, const char *fname)
+{
+ FILE *fp;
+ size_t len;
+ char *ptr, path[MAXPATHLEN];
+
+ fp = NULL;
+ if (fname == NULL) {
+ if (issetugid())
+ return (-1);
+ if ((ptr = getenv("HOME")) == NULL)
+ return (-1);
+ if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
+ return (-1);
+ if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
+ return (-1);
+ fname = path;
+ }
+ if (fp == NULL)
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ return (-1);
+
+ while ((ptr = fgetln(fp, &len)) != NULL) {
+ if (len > 0 && ptr[len - 1] == '\n')
+ --len;
+ ptr[len] = '\0';
+ if (parse_line(el, ptr) == -1) {
+ (void) fclose(fp);
+ return (-1);
+ }
+ }
+
+ (void) fclose(fp);
+ return (0);
+}
+
+
+/* el_resize():
+ * Called from program when terminal is resized
+ */
+public void
+el_resize(EditLine *el)
+{
+ int lins, cols;
+ sigset_t oset, nset;
+
+ (void) sigemptyset(&nset);
+ (void) sigaddset(&nset, SIGWINCH);
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ /* get the correct window size */
+ if (term_get_size(el, &lins, &cols))
+ term_change_size(el, lins, cols);
+
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+
+/* el_beep():
+ * Called from the program to beep
+ */
+public void
+el_beep(EditLine *el)
+{
+
+ term_beep(el);
+}
+
+
+/* el_editmode()
+ * Set the state of EDIT_DISABLED from the `edit' command.
+ */
+protected int
+/*ARGSUSED*/
+el_editmode(EditLine *el, int argc, const char **argv)
+{
+ const char *how;
+
+ if (argv == NULL || argc != 2 || argv[1] == NULL)
+ return (-1);
+
+ how = argv[1];
+ if (strcmp(how, "on") == 0)
+ el->el_flags &= ~EDIT_DISABLED;
+ else if (strcmp(how, "off") == 0)
+ el->el_flags |= EDIT_DISABLED;
+ else {
+ (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
+ return (-1);
+ }
+ return (0);
+}
diff --git a/cmd-line-utils/libedit/el.h b/cmd-line-utils/libedit/el.h
new file mode 100644
index 00000000000..484cbab6122
--- /dev/null
+++ b/cmd-line-utils/libedit/el.h
@@ -0,0 +1,142 @@
+/* $NetBSD: el.h,v 1.8 2001/01/06 14:44:50 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)el.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.h: Internal structures.
+ */
+#ifndef _h_el
+#define _h_el
+/*
+ * Local defaults
+ */
+#define KSHVI
+#define VIDEFAULT
+#define ANCHOR
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#define EL_BUFSIZ 1024 /* Maximum line size */
+
+#define HANDLE_SIGNALS 1<<0
+#define NO_TTY 1<<1
+#define EDIT_DISABLED 1<<2
+
+typedef int bool_t; /* True or not */
+
+typedef unsigned char el_action_t; /* Index to command array */
+
+typedef struct coord_t { /* Position on the screen */
+ int h;
+ int v;
+} coord_t;
+
+typedef struct el_line_t {
+ char *buffer; /* Input line */
+ char *cursor; /* Cursor position */
+ char *lastchar; /* Last character */
+ const char *limit; /* Max position */
+} el_line_t;
+
+/*
+ * Editor state
+ */
+typedef struct el_state_t {
+ int inputmode; /* What mode are we in? */
+ int doingarg; /* Are we getting an argument? */
+ int argument; /* Numeric argument */
+ int metanext; /* Is the next char a meta char */
+ el_action_t lastcmd; /* Previous command */
+} el_state_t;
+
+/*
+ * Until we come up with something better...
+ */
+#define el_malloc(a) malloc(a)
+#define el_realloc(a,b) realloc(a, b)
+#define el_free(a) free(a)
+
+#include "tty.h"
+#include "prompt.h"
+#include "key.h"
+#include "term.h"
+#include "refresh.h"
+#include "chared.h"
+#include "common.h"
+#include "search.h"
+#include "hist.h"
+#include "map.h"
+#include "parse.h"
+#include "sig.h"
+#include "help.h"
+
+struct editline {
+ char *el_prog; /* the program name */
+ FILE *el_outfile; /* Stdio stuff */
+ FILE *el_errfile; /* Stdio stuff */
+ int el_infd; /* Input file descriptor */
+ int el_flags; /* Various flags. */
+ coord_t el_cursor; /* Cursor location */
+ char **el_display; /* Real screen image = what is there */
+ char **el_vdisplay; /* Virtual screen image = what we see */
+ el_line_t el_line; /* The current line information */
+ el_state_t el_state; /* Current editor state */
+ el_term_t el_term; /* Terminal dependent stuff */
+ el_tty_t el_tty; /* Tty dependent stuff */
+ el_refresh_t el_refresh; /* Refresh stuff */
+ el_prompt_t el_prompt; /* Prompt stuff */
+ el_prompt_t el_rprompt; /* Prompt stuff */
+ el_chared_t el_chared; /* Characted editor stuff */
+ el_map_t el_map; /* Key mapping stuff */
+ el_key_t el_key; /* Key binding stuff */
+ el_history_t el_history; /* History stuff */
+ el_search_t el_search; /* Search stuff */
+ el_signal_t el_signal; /* Signal handling stuff */
+};
+
+protected int el_editmode(EditLine *, int, const char **);
+
+#ifdef DEBUG
+#define EL_ABORT(a) (void) (fprintf(el->el_errfile, "%s, %d: ", \
+ __FILE__, __LINE__), fprintf a, abort())
+#else
+#define EL_ABORT(a) abort()
+#endif
+#endif /* _h_el */
diff --git a/cmd-line-utils/libedit/emacs.c b/cmd-line-utils/libedit/emacs.c
new file mode 100644
index 00000000000..bb5ffb2a9f6
--- /dev/null
+++ b/cmd-line-utils/libedit/emacs.c
@@ -0,0 +1,482 @@
+/* $NetBSD: emacs.c,v 1.9 2001/01/10 07:45:41 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * emacs.c: Emacs functions
+ */
+#include "sys.h"
+#include "el.h"
+
+/* em_delete_or_list():
+ * Delete character under cursor or list completions if at end of line
+ * [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_or_list(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.lastchar) {
+ /* if I'm at the end */
+ if (el->el_line.cursor == el->el_line.buffer) {
+ /* and the beginning */
+ term_overwrite(el, STReof, 4); /* then do a EOF */
+ term__flush();
+ return (CC_EOF);
+ } else {
+ /*
+ * Here we could list completions, but it is an
+ * error right now
+ */
+ term_beep(el);
+ return (CC_ERROR);
+ }
+ } else {
+ c_delafter(el, el->el_state.argument); /* delete after dot */
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+ /* bounds check */
+ return (CC_REFRESH);
+ }
+}
+
+
+/* em_delete_next_word():
+ * Cut from cursor to end of current word
+ * [M-d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_next_word(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *p, *kp;
+
+ if (el->el_line.cursor == el->el_line.lastchar)
+ return (CC_ERROR);
+
+ cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ el->el_state.argument, ce__isword);
+
+ for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
+ /* save the text */
+ *kp++ = *p;
+ el->el_chared.c_kill.last = kp;
+
+ c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+ /* bounds check */
+ return (CC_REFRESH);
+}
+
+
+/* em_yank():
+ * Paste cut buffer at cursor position
+ * [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_yank(EditLine *el, int c __attribute__((unused)))
+{
+ char *kp, *cp;
+
+ if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) {
+ if (!ch_enlargebufs(el, 1))
+ return (CC_ERROR);
+ }
+
+ if (el->el_line.lastchar +
+ (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
+ el->el_line.limit)
+ return (CC_ERROR);
+
+ el->el_chared.c_kill.mark = el->el_line.cursor;
+ cp = el->el_line.cursor;
+
+ /* open the space, */
+ c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
+ /* copy the chars */
+ for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
+ *cp++ = *kp;
+
+ /* if an arg, cursor at beginning else cursor at end */
+ if (el->el_state.argument == 1)
+ el->el_line.cursor = cp;
+
+ return (CC_REFRESH);
+}
+
+
+/* em_kill_line():
+ * Cut the entire line and save in cut buffer
+ * [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_line(EditLine *el, int c __attribute__((unused)))
+{
+ char *kp, *cp;
+
+ cp = el->el_line.buffer;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_line.lastchar)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ /* zap! -- delete all of it */
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+ return (CC_REFRESH);
+}
+
+
+/* em_kill_region():
+ * Cut area between mark and cursor and save in cut buffer
+ * [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_region(EditLine *el, int c __attribute__((unused)))
+{
+ char *kp, *cp;
+
+ if (!el->el_chared.c_kill.mark)
+ return (CC_ERROR);
+
+ if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+ cp = el->el_line.cursor;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_chared.c_kill.mark)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ c_delafter(el, cp - el->el_line.cursor);
+ } else { /* mark is before cursor */
+ cp = el->el_chared.c_kill.mark;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_line.cursor)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ c_delbefore(el, cp - el->el_chared.c_kill.mark);
+ el->el_line.cursor = el->el_chared.c_kill.mark;
+ }
+ return (CC_REFRESH);
+}
+
+
+/* em_copy_region():
+ * Copy area between mark and cursor to cut buffer
+ * [M-W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_region(EditLine *el, int c __attribute__((unused)))
+{
+ char *kp, *cp;
+
+ if (el->el_chared.c_kill.mark)
+ return (CC_ERROR);
+
+ if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+ cp = el->el_line.cursor;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_chared.c_kill.mark)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ } else {
+ cp = el->el_chared.c_kill.mark;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_line.cursor)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ }
+ return (CC_NORM);
+}
+
+
+/* em_gosmacs_traspose():
+ * Exchange the two characters before the cursor
+ * Gosling emacs transpose chars [^T]
+ */
+protected el_action_t
+em_gosmacs_traspose(EditLine *el, int c)
+{
+
+ if (el->el_line.cursor > &el->el_line.buffer[1]) {
+ /* must have at least two chars entered */
+ c = el->el_line.cursor[-2];
+ el->el_line.cursor[-2] = el->el_line.cursor[-1];
+ el->el_line.cursor[-1] = c;
+ return (CC_REFRESH);
+ } else
+ return (CC_ERROR);
+}
+
+
+/* em_next_word():
+ * Move next to end of current word
+ * [M-f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_next_word(EditLine *el, int c __attribute__((unused)))
+{
+ if (el->el_line.cursor == el->el_line.lastchar)
+ return (CC_ERROR);
+
+ el->el_line.cursor = c__next_word(el->el_line.cursor,
+ el->el_line.lastchar,
+ el->el_state.argument,
+ ce__isword);
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* em_upper_case():
+ * Uppercase the characters from cursor to end of current word
+ * [M-u]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_upper_case(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *ep;
+
+ ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ el->el_state.argument, ce__isword);
+
+ for (cp = el->el_line.cursor; cp < ep; cp++)
+ if (islower((unsigned char) *cp))
+ *cp = toupper(*cp);
+
+ el->el_line.cursor = ep;
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+ return (CC_REFRESH);
+}
+
+
+/* em_capitol_case():
+ * Capitalize the characters from cursor to end of current word
+ * [M-c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_capitol_case(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *ep;
+
+ ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ el->el_state.argument, ce__isword);
+
+ for (cp = el->el_line.cursor; cp < ep; cp++) {
+ if (isalpha((unsigned char) *cp)) {
+ if (islower((unsigned char) *cp))
+ *cp = toupper(*cp);
+ cp++;
+ break;
+ }
+ }
+ for (; cp < ep; cp++)
+ if (isupper((unsigned char) *cp))
+ *cp = tolower(*cp);
+
+ el->el_line.cursor = ep;
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+ return (CC_REFRESH);
+}
+
+
+/* em_lower_case():
+ * Lowercase the characters from cursor to end of current word
+ * [M-l]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_lower_case(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *ep;
+
+ ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+ el->el_state.argument, ce__isword);
+
+ for (cp = el->el_line.cursor; cp < ep; cp++)
+ if (isupper((unsigned char) *cp))
+ *cp = tolower(*cp);
+
+ el->el_line.cursor = ep;
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+ return (CC_REFRESH);
+}
+
+
+/* em_set_mark():
+ * Set the mark at cursor
+ * [^@]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_set_mark(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_chared.c_kill.mark = el->el_line.cursor;
+ return (CC_NORM);
+}
+
+
+/* em_exchange_mark():
+ * Exchange the cursor and mark
+ * [^X^X]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_exchange_mark(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp;
+
+ cp = el->el_line.cursor;
+ el->el_line.cursor = el->el_chared.c_kill.mark;
+ el->el_chared.c_kill.mark = cp;
+ return (CC_CURSOR);
+}
+
+
+/* em_universal_argument():
+ * Universal argument (argument times 4)
+ * [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_universal_argument(EditLine *el, int c __attribute__((unused)))
+{ /* multiply current argument by 4 */
+
+ if (el->el_state.argument > 1000000)
+ return (CC_ERROR);
+ el->el_state.doingarg = 1;
+ el->el_state.argument *= 4;
+ return (CC_ARGHACK);
+}
+
+
+/* em_meta_next():
+ * Add 8th bit to next character typed
+ * [<ESC>]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_meta_next(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_state.metanext = 1;
+ return (CC_ARGHACK);
+}
+
+
+/* em_toggle_overwrite():
+ * Switch from insert to overwrite mode or vice versa
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_toggle_overwrite(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
+ MODE_REPLACE : MODE_INSERT;
+ return (CC_NORM);
+}
+
+
+/* em_copy_prev_word():
+ * Copy current word to cursor
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_prev_word(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *oldc, *dp;
+
+ if (el->el_line.cursor == el->el_line.buffer)
+ return (CC_ERROR);
+
+ oldc = el->el_line.cursor;
+ /* does a bounds check */
+ cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+ el->el_state.argument, ce__isword);
+
+ c_insert(el, oldc - cp);
+ for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
+ *dp++ = *cp;
+
+ el->el_line.cursor = dp;/* put cursor at end */
+
+ return (CC_REFRESH);
+}
+
+
+/* em_inc_search_next():
+ * Emacs incremental next search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_next(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_search.patlen = 0;
+ return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
+}
+
+
+/* em_inc_search_prev():
+ * Emacs incremental reverse search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_prev(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_search.patlen = 0;
+ return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
+}
diff --git a/cmd-line-utils/libedit/fgetln.c b/cmd-line-utils/libedit/fgetln.c
new file mode 100644
index 00000000000..4f7416a4c8d
--- /dev/null
+++ b/cmd-line-utils/libedit/fgetln.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include "compat.h"
+
+#ifndef HAVE_FGETLN
+
+#ifdef HAVE_GETLINE
+
+extern int getline (char **lineptr, size_t *n, FILE *stream);
+
+#else
+
+/* The interface here is that of GNU libc's getline */
+static int
+getline (char **lineptr, size_t *n, FILE *stream)
+{
+#define EXPAND_CHUNK 16
+
+ int n_read = 0;
+ char *line = *lineptr;
+
+ if (lineptr == NULL) return -1;
+ if (n == NULL) return -1;
+ if (stream == NULL) return -1;
+ if (*lineptr == NULL || *n == 0) return -1;
+
+#ifdef HAVE_FLOCKFILE
+ flockfile (stream);
+#endif
+
+ while (1)
+ {
+ int c;
+
+#ifdef HAVE_FLOCKFILE
+ c = getc_unlocked (stream);
+#else
+ c = getc (stream);
+#endif
+
+ if (c == EOF)
+ {
+ if (n_read > 0)
+ line[n_read] = '\0';
+ break;
+ }
+
+ if (n_read + 2 >= *n)
+ {
+ size_t new_size;
+
+ if (*n == 0)
+ new_size = 16;
+ else
+ new_size = *n * 2;
+
+ if (*n >= new_size) /* Overflowed size_t */
+ line = NULL;
+ else
+ line = (char *) (*lineptr ? (char*) realloc(*lineptr, new_size) :
+ (char*) malloc(new_size));
+
+ if (line)
+ {
+ *lineptr = line;
+ *n = new_size;
+ }
+ else
+ {
+ if (*n > 0)
+ {
+ (*lineptr)[*n - 1] = '\0';
+ n_read = *n - 2;
+ }
+ break;
+ }
+ }
+
+ line[n_read] = c;
+ n_read++;
+
+ if (c == '\n')
+ {
+ line[n_read] = '\0';
+ break;
+ }
+ }
+
+#ifdef HAVE_FLOCKFILE
+ funlockfile (stream);
+#endif
+
+ return n_read - 1;
+}
+#endif /* ! HAVE_GETLINE */
+
+char *fgetln(FILE *stream, size_t *len)
+{
+ char *ptr = NULL;
+ int sz;
+ size_t length= 0;
+
+ sz = getline(&ptr, &length, stream);
+ if(len) {
+ *len = sz;
+ }
+
+ return sz >= 0 ? ptr : NULL;
+}
+#endif
diff --git a/cmd-line-utils/libedit/fgetln.h b/cmd-line-utils/libedit/fgetln.h
new file mode 100644
index 00000000000..b2ddce01da9
--- /dev/null
+++ b/cmd-line-utils/libedit/fgetln.h
@@ -0,0 +1,3 @@
+#include <stdio.h>
+
+char *fgetln(FILE *stream, size_t *len);
diff --git a/cmd-line-utils/libedit/hist.c b/cmd-line-utils/libedit/hist.c
new file mode 100644
index 00000000000..2b20c7d14dc
--- /dev/null
+++ b/cmd-line-utils/libedit/hist.c
@@ -0,0 +1,192 @@
+/* $NetBSD: hist.c,v 1.9 2001/05/17 01:02:17 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * hist.c: History access functions
+ */
+#include "sys.h"
+#include <stdlib.h>
+#include "el.h"
+
+/* hist_init():
+ * Initialization function.
+ */
+protected int
+hist_init(EditLine *el)
+{
+
+ el->el_history.fun = NULL;
+ el->el_history.ref = NULL;
+ el->el_history.buf = (char *) el_malloc(EL_BUFSIZ);
+ el->el_history.sz = EL_BUFSIZ;
+ if (el->el_history.buf == NULL)
+ return (-1);
+ el->el_history.last = el->el_history.buf;
+ return (0);
+}
+
+
+/* hist_end():
+ * clean up history;
+ */
+protected void
+hist_end(EditLine *el)
+{
+
+ el_free((ptr_t) el->el_history.buf);
+ el->el_history.buf = NULL;
+}
+
+
+/* hist_set():
+ * Set new history interface
+ */
+protected int
+hist_set(EditLine *el, hist_fun_t fun, ptr_t ptr)
+{
+
+ el->el_history.ref = ptr;
+ el->el_history.fun = fun;
+ return (0);
+}
+
+
+/* hist_get():
+ * Get a history line and update it in the buffer.
+ * eventno tells us the event to get.
+ */
+protected el_action_t
+hist_get(EditLine *el)
+{
+ const char *hp;
+ int h;
+
+ if (el->el_history.eventno == 0) { /* if really the current line */
+ (void) strncpy(el->el_line.buffer, el->el_history.buf,
+ el->el_history.sz);
+ el->el_line.lastchar = el->el_line.buffer +
+ (el->el_history.last - el->el_history.buf);
+
+#ifdef KSHVI
+ if (el->el_map.type == MAP_VI)
+ el->el_line.cursor = el->el_line.buffer;
+ else
+#endif /* KSHVI */
+ el->el_line.cursor = el->el_line.lastchar;
+
+ return (CC_REFRESH);
+ }
+ if (el->el_history.ref == NULL)
+ return (CC_ERROR);
+
+ hp = HIST_FIRST(el);
+
+ if (hp == NULL)
+ return (CC_ERROR);
+
+ for (h = 1; h < el->el_history.eventno; h++)
+ if ((hp = HIST_NEXT(el)) == NULL) {
+ el->el_history.eventno = h;
+ return (CC_ERROR);
+ }
+ (void) strncpy(el->el_line.buffer, hp,
+ (size_t)(el->el_line.limit - el->el_line.buffer));
+ el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
+
+ if (el->el_line.lastchar > el->el_line.buffer) {
+ if (el->el_line.lastchar[-1] == '\n')
+ el->el_line.lastchar--;
+ if (el->el_line.lastchar[-1] == ' ')
+ el->el_line.lastchar--;
+ if (el->el_line.lastchar < el->el_line.buffer)
+ el->el_line.lastchar = el->el_line.buffer;
+ }
+#ifdef KSHVI
+ if (el->el_map.type == MAP_VI)
+ el->el_line.cursor = el->el_line.buffer;
+ else
+#endif /* KSHVI */
+ el->el_line.cursor = el->el_line.lastchar;
+
+ return (CC_REFRESH);
+}
+
+
+/* hist_list()
+ * List history entries
+ */
+protected int
+/*ARGSUSED*/
+hist_list(EditLine *el, int argc __attribute__((unused)),
+ const char **argv __attribute__((unused)))
+{
+ const char *str;
+
+ if (el->el_history.ref == NULL)
+ return (-1);
+ for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
+ (void) fprintf(el->el_outfile, "%d %s",
+ el->el_history.ev.num, str);
+ return (0);
+}
+
+/* hist_enlargebuf()
+ * Enlarge history buffer to specified value. Called from el_enlargebufs().
+ * Return 0 for failure, 1 for success.
+ */
+protected int
+/*ARGSUSED*/
+hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
+{
+ char *newbuf;
+
+ newbuf = realloc(el->el_history.buf, newsz);
+ if (!newbuf)
+ return 0;
+
+ (void) memset(&newbuf[oldsz], '\0', newsz - oldsz);
+
+ el->el_history.last = newbuf +
+ (el->el_history.last - el->el_history.buf);
+ el->el_history.buf = newbuf;
+ el->el_history.sz = newsz;
+
+ return 1;
+}
diff --git a/cmd-line-utils/libedit/hist.h b/cmd-line-utils/libedit/hist.h
new file mode 100644
index 00000000000..e650b6a55a9
--- /dev/null
+++ b/cmd-line-utils/libedit/hist.h
@@ -0,0 +1,80 @@
+/* $NetBSD: hist.h,v 1.6 2001/01/10 07:45:41 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)hist.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.hist.c: History functions
+ */
+#ifndef _h_el_hist
+#define _h_el_hist
+
+#include "histedit.h"
+
+typedef int (*hist_fun_t)(ptr_t, HistEvent *, int, ...);
+
+typedef struct el_history_t {
+ char *buf; /* The history buffer */
+ size_t sz; /* Size of history buffer */
+ char *last; /* The last character */
+ int eventno; /* Event we are looking for */
+ ptr_t ref; /* Argument for history fcns */
+ hist_fun_t fun; /* Event access */
+ HistEvent ev; /* Event cookie */
+} el_history_t;
+
+#define HIST_FUN(el, fn, arg) \
+ ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
+ fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
+
+#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL)
+#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL)
+#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL)
+#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL)
+#define HIST_EVENT(el, num) HIST_FUN(el, H_EVENT, num)
+#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
+#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
+
+protected int hist_init(EditLine *);
+protected void hist_end(EditLine *);
+protected el_action_t hist_get(EditLine *);
+protected int hist_set(EditLine *, hist_fun_t, ptr_t);
+protected int hist_list(EditLine *, int, const char **);
+protected int hist_enlargebuf(EditLine *, size_t, size_t);
+
+#endif /* _h_el_hist */
diff --git a/cmd-line-utils/libedit/histedit.h b/cmd-line-utils/libedit/histedit.h
new file mode 100644
index 00000000000..0b8d175cef1
--- /dev/null
+++ b/cmd-line-utils/libedit/histedit.h
@@ -0,0 +1,190 @@
+/* $NetBSD: histedit.h,v 1.16 2000/09/04 22:06:30 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)histedit.h 8.2 (Berkeley) 1/3/94
+ */
+
+/*
+ * histedit.h: Line editor and history interface.
+ */
+#ifndef _HISTEDIT_H_
+#define _HISTEDIT_H_
+
+#include <sys/types.h>
+#include <stdio.h>
+
+/*
+ * ==== Editing ====
+ */
+typedef struct editline EditLine;
+
+/*
+ * For user-defined function interface
+ */
+typedef struct lineinfo {
+ const char *buffer;
+ const char *cursor;
+ const char *lastchar;
+} LineInfo;
+
+
+/*
+ * EditLine editor function return codes.
+ * For user-defined function interface
+ */
+#define CC_NORM 0
+#define CC_NEWLINE 1
+#define CC_EOF 2
+#define CC_ARGHACK 3
+#define CC_REFRESH 4
+#define CC_CURSOR 5
+#define CC_ERROR 6
+#define CC_FATAL 7
+#define CC_REDISPLAY 8
+#define CC_REFRESH_BEEP 9
+
+/*
+ * Initialization, cleanup, and resetting
+ */
+EditLine *el_init(const char *, FILE *, FILE *, FILE *);
+void el_reset(EditLine *);
+void el_end(EditLine *);
+
+
+/*
+ * Get a line, a character or push a string back in the input queue
+ */
+const char *el_gets(EditLine *, int *);
+int el_getc(EditLine *, char *);
+void el_push(EditLine *, const char *);
+
+/*
+ * Beep!
+ */
+void el_beep(EditLine *);
+
+/*
+ * High level function internals control
+ * Parses argc, argv array and executes builtin editline commands
+ */
+int el_parse(EditLine *, int, const char **);
+
+/*
+ * Low level editline access functions
+ */
+int el_set(EditLine *, int, ...);
+int el_get(EditLine *, int, void *);
+
+/*
+ * el_set/el_get parameters
+ */
+#define EL_PROMPT 0 /* , el_pfunc_t); */
+#define EL_TERMINAL 1 /* , const char *); */
+#define EL_EDITOR 2 /* , const char *); */
+#define EL_SIGNAL 3 /* , int); */
+#define EL_BIND 4 /* , const char *, ..., NULL); */
+#define EL_TELLTC 5 /* , const char *, ..., NULL); */
+#define EL_SETTC 6 /* , const char *, ..., NULL); */
+#define EL_ECHOTC 7 /* , const char *, ..., NULL); */
+#define EL_SETTY 8 /* , const char *, ..., NULL); */
+#define EL_ADDFN 9 /* , const char *, const char * */
+ /* , el_func_t); */
+#define EL_HIST 10 /* , hist_fun_t, const char *); */
+#define EL_EDITMODE 11 /* , int); */
+#define EL_RPROMPT 12 /* , el_pfunc_t); */
+
+/*
+ * Source named file or $PWD/.editrc or $HOME/.editrc
+ */
+int el_source(EditLine *, const char *);
+
+/*
+ * Must be called when the terminal changes size; If EL_SIGNAL
+ * is set this is done automatically otherwise it is the responsibility
+ * of the application
+ */
+void el_resize(EditLine *);
+
+
+/*
+ * User-defined function interface.
+ */
+const LineInfo *el_line(EditLine *);
+int el_insertstr(EditLine *, const char *);
+void el_deletestr(EditLine *, int);
+
+/*
+ * ==== History ====
+ */
+
+typedef struct history History;
+
+typedef struct HistEvent {
+ int num;
+ const char *str;
+} HistEvent;
+
+/*
+ * History access functions.
+ */
+History * history_init(void);
+void history_end(History *);
+
+int history(History *, HistEvent *, int, ...);
+
+#define H_FUNC 0 /* , UTSL */
+#define H_SETSIZE 1 /* , const int); */
+#define H_GETSIZE 2 /* , void); */
+#define H_FIRST 3 /* , void); */
+#define H_LAST 4 /* , void); */
+#define H_PREV 5 /* , void); */
+#define H_NEXT 6 /* , void); */
+#define H_CURR 8 /* , const int); */
+#define H_SET 7 /* , void); */
+#define H_ADD 9 /* , const char *); */
+#define H_ENTER 10 /* , const char *); */
+#define H_APPEND 11 /* , const char *); */
+#define H_END 12 /* , void); */
+#define H_NEXT_STR 13 /* , const char *); */
+#define H_PREV_STR 14 /* , const char *); */
+#define H_NEXT_EVENT 15 /* , const int); */
+#define H_PREV_EVENT 16 /* , const int); */
+#define H_LOAD 17 /* , const char *); */
+#define H_SAVE 18 /* , const char *); */
+#define H_CLEAR 19 /* , void); */
+
+#endif /* _HISTEDIT_H_ */
diff --git a/cmd-line-utils/libedit/history.c b/cmd-line-utils/libedit/history.c
new file mode 100644
index 00000000000..90d94e7fc18
--- /dev/null
+++ b/cmd-line-utils/libedit/history.c
@@ -0,0 +1,864 @@
+/* $NetBSD: history.c,v 1.17 2001/03/20 00:08:31 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * hist.c: History access functions
+ */
+#include "sys.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#ifdef HAVE_VIS_H
+#include <vis.h>
+#endif
+#include <sys/stat.h>
+
+static const char hist_cookie[] = "_HiStOrY_V2_\n";
+
+#include "histedit.h"
+
+typedef int (*history_gfun_t)(ptr_t, HistEvent *);
+typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
+typedef void (*history_vfun_t)(ptr_t, HistEvent *);
+typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
+
+struct history {
+ ptr_t h_ref; /* Argument for history fcns */
+ int h_ent; /* Last entry point for history */
+ history_gfun_t h_first; /* Get the first element */
+ history_gfun_t h_next; /* Get the next element */
+ history_gfun_t h_last; /* Get the last element */
+ history_gfun_t h_prev; /* Get the previous element */
+ history_gfun_t h_curr; /* Get the current element */
+ history_sfun_t h_set; /* Set the current element */
+ history_vfun_t h_clear; /* Clear the history list */
+ history_efun_t h_enter; /* Add an element */
+ history_efun_t h_add; /* Append to an element */
+};
+#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
+#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
+#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
+#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
+#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
+#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
+#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
+#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
+#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
+
+#define h_malloc(a) malloc(a)
+#define h_realloc(a, b) realloc((a), (b))
+#define h_free(a) free(a)
+
+
+private int history_setsize(History *, HistEvent *, int);
+private int history_getsize(History *, HistEvent *);
+private int history_set_fun(History *, History *);
+private int history_load(History *, const char *);
+private int history_save(History *, const char *);
+private int history_prev_event(History *, HistEvent *, int);
+private int history_next_event(History *, HistEvent *, int);
+private int history_next_string(History *, HistEvent *, const char *);
+private int history_prev_string(History *, HistEvent *, const char *);
+
+
+/***********************************************************************/
+
+/*
+ * Builtin- history implementation
+ */
+typedef struct hentry_t {
+ HistEvent ev; /* What we return */
+ struct hentry_t *next; /* Next entry */
+ struct hentry_t *prev; /* Previous entry */
+} hentry_t;
+
+typedef struct history_t {
+ hentry_t list; /* Fake list header element */
+ hentry_t *cursor; /* Current element in the list */
+ int max; /* Maximum number of events */
+ int cur; /* Current number of events */
+ int eventid; /* For generation of unique event id */
+} history_t;
+
+private int history_def_first(ptr_t, HistEvent *);
+private int history_def_last(ptr_t, HistEvent *);
+private int history_def_next(ptr_t, HistEvent *);
+private int history_def_prev(ptr_t, HistEvent *);
+private int history_def_curr(ptr_t, HistEvent *);
+private int history_def_set(ptr_t, HistEvent *, const int n);
+private int history_def_enter(ptr_t, HistEvent *, const char *);
+private int history_def_add(ptr_t, HistEvent *, const char *);
+private void history_def_init(ptr_t *, HistEvent *, int);
+private void history_def_clear(ptr_t, HistEvent *);
+private int history_def_insert(history_t *, HistEvent *, const char *);
+private void history_def_delete(history_t *, HistEvent *, hentry_t *);
+
+#define history_def_setsize(p, num)(void) (((history_t *) p)->max = (num))
+#define history_def_getsize(p) (((history_t *) p)->cur)
+
+#define he_strerror(code) he_errlist[code]
+#define he_seterrev(evp, code) {\
+ evp->num = code;\
+ evp->str = he_strerror(code);\
+ }
+
+/* error messages */
+static const char *const he_errlist[] = {
+ "OK",
+ "unknown error",
+ "malloc() failed",
+ "first event not found",
+ "last event not found",
+ "empty list",
+ "no next event",
+ "no previous event",
+ "current event is invalid",
+ "event not found",
+ "can't read history from file",
+ "can't write history",
+ "required parameter(s) not supplied",
+ "history size negative",
+ "function not allowed with other history-functions-set the default",
+ "bad parameters"
+};
+/* error codes */
+#define _HE_OK 0
+#define _HE_UNKNOWN 1
+#define _HE_MALLOC_FAILED 2
+#define _HE_FIRST_NOTFOUND 3
+#define _HE_LAST_NOTFOUND 4
+#define _HE_EMPTY_LIST 5
+#define _HE_END_REACHED 6
+#define _HE_START_REACHED 7
+#define _HE_CURR_INVALID 8
+#define _HE_NOT_FOUND 9
+#define _HE_HIST_READ 10
+#define _HE_HIST_WRITE 11
+#define _HE_PARAM_MISSING 12
+#define _HE_SIZE_NEGATIVE 13
+#define _HE_NOT_ALLOWED 14
+#define _HE_BAD_PARAM 15
+
+/* history_def_first():
+ * Default function to return the first event in the history.
+ */
+private int
+history_def_first(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ h->cursor = h->list.next;
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_FIRST_NOTFOUND);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/* history_def_last():
+ * Default function to return the last event in the history.
+ */
+private int
+history_def_last(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ h->cursor = h->list.prev;
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_LAST_NOTFOUND);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/* history_def_next():
+ * Default function to return the next event in the history.
+ */
+private int
+history_def_next(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ h->cursor = h->cursor->next;
+ else {
+ he_seterrev(ev, _HE_EMPTY_LIST);
+ return (-1);
+ }
+
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_END_REACHED);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/* history_def_prev():
+ * Default function to return the previous event in the history.
+ */
+private int
+history_def_prev(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ h->cursor = h->cursor->prev;
+ else {
+ he_seterrev(ev,
+ (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
+ return (-1);
+ }
+
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_START_REACHED);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/* history_def_curr():
+ * Default function to return the current event in the history.
+ */
+private int
+history_def_curr(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev,
+ (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/* history_def_set():
+ * Default function to set the current event in the history to the
+ * given one.
+ */
+private int
+history_def_set(ptr_t p, HistEvent *ev, const int n)
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cur == 0) {
+ he_seterrev(ev, _HE_EMPTY_LIST);
+ return (-1);
+ }
+ if (h->cursor == &h->list || h->cursor->ev.num != n) {
+ for (h->cursor = h->list.next; h->cursor != &h->list;
+ h->cursor = h->cursor->next)
+ if (h->cursor->ev.num == n)
+ break;
+ }
+ if (h->cursor == &h->list) {
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+ }
+ return (0);
+}
+
+
+/* history_def_add():
+ * Append string to element
+ */
+private int
+history_def_add(ptr_t p, HistEvent *ev, const char *str)
+{
+ history_t *h = (history_t *) p;
+ size_t len;
+ char *s;
+
+ if (h->cursor == &h->list)
+ return (history_def_enter(p, ev, str));
+ len = strlen(h->cursor->ev.str) + strlen(str) + 1;
+ s = (char *) h_malloc(len);
+ if (!s) {
+ he_seterrev(ev, _HE_MALLOC_FAILED);
+ return (-1);
+ }
+ (void) strlcpy(s, h->cursor->ev.str, len);
+ (void) strlcat(s, str, len);
+ /* LINTED const cast */
+ h_free((ptr_t) h->cursor->ev.str);
+ h->cursor->ev.str = s;
+ *ev = h->cursor->ev;
+ return (0);
+}
+
+
+/* history_def_delete():
+ * Delete element hp of the h list
+ */
+/* ARGSUSED */
+private void
+history_def_delete(history_t *h,
+ HistEvent *ev __attribute__((unused)), hentry_t *hp)
+{
+
+ if (hp == &h->list)
+ abort();
+ hp->prev->next = hp->next;
+ hp->next->prev = hp->prev;
+ /* LINTED const cast */
+ h_free((ptr_t) hp->ev.str);
+ h_free(hp);
+ h->cur--;
+}
+
+
+/* history_def_insert():
+ * Insert element with string str in the h list
+ */
+private int
+history_def_insert(history_t *h, HistEvent *ev, const char *str)
+{
+
+ h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
+ if (h->cursor)
+ h->cursor->ev.str = strdup(str);
+ if (!h->cursor || !h->cursor->ev.str) {
+ he_seterrev(ev, _HE_MALLOC_FAILED);
+ return (-1);
+ }
+ h->cursor->ev.num = ++h->eventid;
+ h->cursor->next = h->list.next;
+ h->cursor->prev = &h->list;
+ h->list.next->prev = h->cursor;
+ h->list.next = h->cursor;
+ h->cur++;
+
+ *ev = h->cursor->ev;
+ return (0);
+}
+
+
+/* history_def_enter():
+ * Default function to enter an item in the history
+ */
+private int
+history_def_enter(ptr_t p, HistEvent *ev, const char *str)
+{
+ history_t *h = (history_t *) p;
+
+ if (history_def_insert(h, ev, str) == -1)
+ return (-1); /* error, keep error message */
+
+ /*
+ * Always keep at least one entry.
+ * This way we don't have to check for the empty list.
+ */
+ while (h->cur - 1 > h->max)
+ history_def_delete(h, ev, h->list.prev);
+
+ return (0);
+}
+
+
+/* history_def_init():
+ * Default history initialization function
+ */
+/* ARGSUSED */
+private void
+history_def_init(ptr_t *p, HistEvent *ev __attribute__((unused)), int n)
+{
+ history_t *h = (history_t *) h_malloc(sizeof(history_t));
+
+ if (n <= 0)
+ n = 0;
+ h->eventid = 0;
+ h->cur = 0;
+ h->max = n;
+ h->list.next = h->list.prev = &h->list;
+ h->list.ev.str = NULL;
+ h->list.ev.num = 0;
+ h->cursor = &h->list;
+ *p = (ptr_t) h;
+}
+
+
+/* history_def_clear():
+ * Default history cleanup function
+ */
+private void
+history_def_clear(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ while (h->list.prev != &h->list)
+ history_def_delete(h, ev, h->list.prev);
+ h->eventid = 0;
+ h->cur = 0;
+}
+
+
+
+
+/************************************************************************/
+
+/* history_init():
+ * Initialization function.
+ */
+public History *
+history_init(void)
+{
+ History *h = (History *) h_malloc(sizeof(History));
+ HistEvent ev;
+
+ history_def_init(&h->h_ref, &ev, 0);
+ h->h_ent = -1;
+ h->h_next = history_def_next;
+ h->h_first = history_def_first;
+ h->h_last = history_def_last;
+ h->h_prev = history_def_prev;
+ h->h_curr = history_def_curr;
+ h->h_set = history_def_set;
+ h->h_clear = history_def_clear;
+ h->h_enter = history_def_enter;
+ h->h_add = history_def_add;
+
+ return (h);
+}
+
+
+/* history_end():
+ * clean up history;
+ */
+public void
+history_end(History *h)
+{
+ HistEvent ev;
+
+ if (h->h_next == history_def_next)
+ history_def_clear(h->h_ref, &ev);
+}
+
+
+
+/* history_setsize():
+ * Set history number of events
+ */
+private int
+history_setsize(History *h, HistEvent *ev, int num)
+{
+
+ if (h->h_next != history_def_next) {
+ he_seterrev(ev, _HE_NOT_ALLOWED);
+ return (-1);
+ }
+ if (num < 0) {
+ he_seterrev(ev, _HE_BAD_PARAM);
+ return (-1);
+ }
+ history_def_setsize(h->h_ref, num);
+ return (0);
+}
+
+
+/* history_getsize():
+ * Get number of events currently in history
+ */
+private int
+history_getsize(History *h, HistEvent *ev)
+{
+ int retval = 0;
+
+ if (h->h_next != history_def_next) {
+ he_seterrev(ev, _HE_NOT_ALLOWED);
+ return (-1);
+ }
+ retval = history_def_getsize(h->h_ref);
+ if (retval < -1) {
+ he_seterrev(ev, _HE_SIZE_NEGATIVE);
+ return (-1);
+ }
+ ev->num = retval;
+ return (0);
+}
+
+
+/* history_set_fun():
+ * Set history functions
+ */
+private int
+history_set_fun(History *h, History *nh)
+{
+ HistEvent ev;
+
+ if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
+ nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
+ nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
+ nh->h_ref == NULL) {
+ if (h->h_next != history_def_next) {
+ history_def_init(&h->h_ref, &ev, 0);
+ h->h_first = history_def_first;
+ h->h_next = history_def_next;
+ h->h_last = history_def_last;
+ h->h_prev = history_def_prev;
+ h->h_curr = history_def_curr;
+ h->h_set = history_def_set;
+ h->h_clear = history_def_clear;
+ h->h_enter = history_def_enter;
+ h->h_add = history_def_add;
+ }
+ return (-1);
+ }
+ if (h->h_next == history_def_next)
+ history_def_clear(h->h_ref, &ev);
+
+ h->h_ent = -1;
+ h->h_first = nh->h_first;
+ h->h_next = nh->h_next;
+ h->h_last = nh->h_last;
+ h->h_prev = nh->h_prev;
+ h->h_curr = nh->h_curr;
+ h->h_set = nh->h_set;
+ h->h_clear = nh->h_clear;
+ h->h_enter = nh->h_enter;
+ h->h_add = nh->h_add;
+
+ return (0);
+}
+
+
+/* history_load():
+ * History load function
+ */
+private int
+history_load(History *h, const char *fname)
+{
+ FILE *fp;
+ char *line;
+ size_t sz, max_size;
+ char *ptr;
+ int i = -1;
+ HistEvent ev;
+
+ if ((fp = fopen(fname, "r")) == NULL)
+ return (i);
+
+ if ((line = fgetln(fp, &sz)) == NULL)
+ goto done;
+
+ if (strncmp(line, hist_cookie, sz) != 0)
+ goto done;
+
+ ptr = h_malloc(max_size = 1024);
+ for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
+ char c = line[sz];
+
+ if (sz != 0 && line[sz - 1] == '\n')
+ line[--sz] = '\0';
+ else
+ line[sz] = '\0';
+
+ if (max_size < sz) {
+ max_size = (sz + 1023) & ~1023;
+ ptr = h_realloc(ptr, max_size);
+ }
+ (void) strunvis(ptr, line);
+ line[sz] = c;
+ HENTER(h, &ev, ptr);
+ }
+ h_free(ptr);
+
+done:
+ (void) fclose(fp);
+ return (i);
+}
+
+
+/* history_save():
+ * History save function
+ */
+private int
+history_save(History *h, const char *fname)
+{
+ FILE *fp;
+ HistEvent ev;
+ int i = 0, retval;
+ size_t len, max_size;
+ char *ptr;
+
+ if ((fp = fopen(fname, "w")) == NULL)
+ return (-1);
+
+ (void) fchmod(fileno(fp), S_IRUSR|S_IWUSR);
+ (void) fputs(hist_cookie, fp);
+ ptr = h_malloc(max_size = 1024);
+ for (retval = HLAST(h, &ev);
+ retval != -1;
+ retval = HPREV(h, &ev), i++) {
+ len = strlen(ev.str) * 4;
+ if (len >= max_size) {
+ max_size = (len + 1023) & 1023;
+ ptr = h_realloc(ptr, max_size);
+ }
+ (void) strvis(ptr, ev.str, VIS_WHITE);
+ (void) fprintf(fp, "%s\n", ev.str);
+ }
+ h_free(ptr);
+ (void) fclose(fp);
+ return (i);
+}
+
+
+/* history_prev_event():
+ * Find the previous event, with number given
+ */
+private int
+history_prev_event(History *h, HistEvent *ev, int num)
+{
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+ if (ev->num == num)
+ return (0);
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+}
+
+
+/* history_next_event():
+ * Find the next event, with number given
+ */
+private int
+history_next_event(History *h, HistEvent *ev, int num)
+{
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+ if (ev->num == num)
+ return (0);
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+}
+
+
+/* history_prev_string():
+ * Find the previous event beginning with string
+ */
+private int
+history_prev_string(History *h, HistEvent *ev, const char *str)
+{
+ size_t len = strlen(str);
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+ if (strncmp(str, ev->str, len) == 0)
+ return (0);
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+}
+
+
+/* history_next_string():
+ * Find the next event beginning with string
+ */
+private int
+history_next_string(History *h, HistEvent *ev, const char *str)
+{
+ size_t len = strlen(str);
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+ if (strncmp(str, ev->str, len) == 0)
+ return (0);
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+}
+
+
+/* history():
+ * User interface to history functions.
+ */
+int
+history(History *h, HistEvent *ev, int fun, ...)
+{
+ va_list va;
+ const char *str;
+ int retval;
+
+ va_start(va, fun);
+
+ he_seterrev(ev, _HE_OK);
+
+ switch (fun) {
+ case H_GETSIZE:
+ retval = history_getsize(h, ev);
+ break;
+
+ case H_SETSIZE:
+ retval = history_setsize(h, ev, va_arg(va, int));
+ break;
+
+ case H_ADD:
+ str = va_arg(va, const char *);
+ retval = HADD(h, ev, str);
+ break;
+
+ case H_ENTER:
+ str = va_arg(va, const char *);
+ if ((retval = HENTER(h, ev, str)) != -1)
+ h->h_ent = ev->num;
+ break;
+
+ case H_APPEND:
+ str = va_arg(va, const char *);
+ if ((retval = HSET(h, ev, h->h_ent)) != -1)
+ retval = HADD(h, ev, str);
+ break;
+
+ case H_FIRST:
+ retval = HFIRST(h, ev);
+ break;
+
+ case H_NEXT:
+ retval = HNEXT(h, ev);
+ break;
+
+ case H_LAST:
+ retval = HLAST(h, ev);
+ break;
+
+ case H_PREV:
+ retval = HPREV(h, ev);
+ break;
+
+ case H_CURR:
+ retval = HCURR(h, ev);
+ break;
+
+ case H_SET:
+ retval = HSET(h, ev, va_arg(va, const int));
+ break;
+
+ case H_CLEAR:
+ HCLEAR(h, ev);
+ retval = 0;
+ break;
+
+ case H_LOAD:
+ retval = history_load(h, va_arg(va, const char *));
+ if (retval == -1)
+ he_seterrev(ev, _HE_HIST_READ);
+ break;
+
+ case H_SAVE:
+ retval = history_save(h, va_arg(va, const char *));
+ if (retval == -1)
+ he_seterrev(ev, _HE_HIST_WRITE);
+ break;
+
+ case H_PREV_EVENT:
+ retval = history_prev_event(h, ev, va_arg(va, int));
+ break;
+
+ case H_NEXT_EVENT:
+ retval = history_next_event(h, ev, va_arg(va, int));
+ break;
+
+ case H_PREV_STR:
+ retval = history_prev_string(h, ev, va_arg(va, const char *));
+ break;
+
+ case H_NEXT_STR:
+ retval = history_next_string(h, ev, va_arg(va, const char *));
+ break;
+
+ case H_FUNC:
+ {
+ History hf;
+
+ hf.h_ref = va_arg(va, ptr_t);
+ h->h_ent = -1;
+ hf.h_first = va_arg(va, history_gfun_t);
+ hf.h_next = va_arg(va, history_gfun_t);
+ hf.h_last = va_arg(va, history_gfun_t);
+ hf.h_prev = va_arg(va, history_gfun_t);
+ hf.h_curr = va_arg(va, history_gfun_t);
+ hf.h_set = va_arg(va, history_sfun_t);
+ hf.h_clear = va_arg(va, history_vfun_t);
+ hf.h_enter = va_arg(va, history_efun_t);
+ hf.h_add = va_arg(va, history_efun_t);
+
+ if ((retval = history_set_fun(h, &hf)) == -1)
+ he_seterrev(ev, _HE_PARAM_MISSING);
+ break;
+ }
+
+ case H_END:
+ history_end(h);
+ retval = 0;
+ break;
+
+ default:
+ retval = -1;
+ he_seterrev(ev, _HE_UNKNOWN);
+ break;
+ }
+ va_end(va);
+ return (retval);
+}
diff --git a/cmd-line-utils/libedit/key.c b/cmd-line-utils/libedit/key.c
new file mode 100644
index 00000000000..629c6aeeb9c
--- /dev/null
+++ b/cmd-line-utils/libedit/key.c
@@ -0,0 +1,681 @@
+/* $NetBSD: key.c,v 1.12 2001/05/17 01:02:17 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * key.c: This module contains the procedures for maintaining
+ * the extended-key map.
+ *
+ * An extended-key (key) is a sequence of keystrokes introduced
+ * with an sequence introducer and consisting of an arbitrary
+ * number of characters. This module maintains a map (the el->el_key.map)
+ * to convert these extended-key sequences into input strs
+ * (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
+ *
+ * Warning:
+ * If key is a substr of some other keys, then the longer
+ * keys are lost!! That is, if the keys "abcd" and "abcef"
+ * are in el->el_key.map, adding the key "abc" will cause the first two
+ * definitions to be lost.
+ *
+ * Restrictions:
+ * -------------
+ * 1) It is not possible to have one key that is a
+ * substr of another.
+ */
+#include "sys.h"
+#include <string.h>
+#include <stdlib.h>
+
+#include "el.h"
+
+/*
+ * The Nodes of the el->el_key.map. The el->el_key.map is a linked list
+ * of these node elements
+ */
+struct key_node_t {
+ char ch; /* single character of key */
+ int type; /* node type */
+ key_value_t val; /* command code or pointer to str, */
+ /* if this is a leaf */
+ struct key_node_t *next; /* ptr to next char of this key */
+ struct key_node_t *sibling; /* ptr to another key with same prefix*/
+};
+
+private int node_trav(EditLine *, key_node_t *, char *,
+ key_value_t *);
+private int node__try(EditLine *, key_node_t *, const char *,
+ key_value_t *, int);
+private key_node_t *node__get(int);
+private void node__put(EditLine *, key_node_t *);
+private int node__delete(EditLine *, key_node_t **, const char *);
+private int node_lookup(EditLine *, const char *,
+ key_node_t *, int);
+private int node_enum(EditLine *, key_node_t *, int);
+private int key__decode_char(char *, int, int);
+
+#define KEY_BUFSIZ EL_BUFSIZ
+
+
+/* key_init():
+ * Initialize the key maps
+ */
+protected int
+key_init(EditLine *el)
+{
+
+ el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
+ if (el->el_key.buf == NULL)
+ return (-1);
+ el->el_key.map = NULL;
+ key_reset(el);
+ return (0);
+}
+
+
+/* key_end():
+ * Free the key maps
+ */
+protected void
+key_end(EditLine *el)
+{
+
+ el_free((ptr_t) el->el_key.buf);
+ el->el_key.buf = NULL;
+ /* XXX: provide a function to clear the keys */
+ el->el_key.map = NULL;
+}
+
+
+/* key_map_cmd():
+ * Associate cmd with a key value
+ */
+protected key_value_t *
+key_map_cmd(EditLine *el, int cmd)
+{
+
+ el->el_key.val.cmd = (el_action_t) cmd;
+ return (&el->el_key.val);
+}
+
+
+/* key_map_str():
+ * Associate str with a key value
+ */
+protected key_value_t *
+key_map_str(EditLine *el, char *str)
+{
+
+ el->el_key.val.str = str;
+ return (&el->el_key.val);
+}
+
+
+/* key_reset():
+ * Takes all nodes on el->el_key.map and puts them on free list. Then
+ * initializes el->el_key.map with arrow keys
+ * [Always bind the ansi arrow keys?]
+ */
+protected void
+key_reset(EditLine *el)
+{
+
+ node__put(el, el->el_key.map);
+ el->el_key.map = NULL;
+ return;
+}
+
+
+/* key_get():
+ * Calls the recursive function with entry point el->el_key.map
+ * Looks up *ch in map and then reads characters until a
+ * complete match is found or a mismatch occurs. Returns the
+ * type of the match found (XK_STR, XK_CMD, or XK_EXE).
+ * Returns NULL in val.str and XK_STR for no match.
+ * The last character read is returned in *ch.
+ */
+protected int
+key_get(EditLine *el, char *ch, key_value_t *val)
+{
+
+ return (node_trav(el, el->el_key.map, ch, val));
+}
+
+
+/* key_add():
+ * Adds key to the el->el_key.map and associates the value in val with it.
+ * If key is already is in el->el_key.map, the new code is applied to the
+ * existing key. Ntype specifies if code is a command, an
+ * out str or a unix command.
+ */
+protected void
+key_add(EditLine *el, const char *key, key_value_t *val, int ntype)
+{
+
+ if (key[0] == '\0') {
+ (void) fprintf(el->el_errfile,
+ "key_add: Null extended-key not allowed.\n");
+ return;
+ }
+ if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) {
+ (void) fprintf(el->el_errfile,
+ "key_add: sequence-lead-in command not allowed\n");
+ return;
+ }
+ if (el->el_key.map == NULL)
+ /* tree is initially empty. Set up new node to match key[0] */
+ el->el_key.map = node__get(key[0]);
+ /* it is properly initialized */
+
+ /* Now recurse through el->el_key.map */
+ (void) node__try(el, el->el_key.map, key, val, ntype);
+ return;
+}
+
+
+/* key_clear():
+ *
+ */
+protected void
+key_clear(EditLine *el, el_action_t *map, const char *in)
+{
+
+ if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) &&
+ ((map == el->el_map.key &&
+ el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) ||
+ (map == el->el_map.alt &&
+ el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN)))
+ (void) key_delete(el, in);
+}
+
+
+/* key_delete():
+ * Delete the key and all longer keys staring with key, if
+ * they exists.
+ */
+protected int
+key_delete(EditLine *el, const char *key)
+{
+
+ if (key[0] == '\0') {
+ (void) fprintf(el->el_errfile,
+ "key_delete: Null extended-key not allowed.\n");
+ return (-1);
+ }
+ if (el->el_key.map == NULL)
+ return (0);
+
+ (void) node__delete(el, &el->el_key.map, key);
+ return (0);
+}
+
+
+/* key_print():
+ * Print the binding associated with key key.
+ * Print entire el->el_key.map if null
+ */
+protected void
+key_print(EditLine *el, const char *key)
+{
+
+ /* do nothing if el->el_key.map is empty and null key specified */
+ if (el->el_key.map == NULL && *key == 0)
+ return;
+
+ el->el_key.buf[0] = '"';
+ if (node_lookup(el, key, el->el_key.map, 1) <= -1)
+ /* key is not bound */
+ (void) fprintf(el->el_errfile, "Unbound extended key \"%s\"\n",
+ key);
+ return;
+}
+
+
+/* node_trav():
+ * recursively traverses node in tree until match or mismatch is
+ * found. May read in more characters.
+ */
+private int
+node_trav(EditLine *el, key_node_t *ptr, char *ch, key_value_t *val)
+{
+
+ if (ptr->ch == *ch) {
+ /* match found */
+ if (ptr->next) {
+ /* key not complete so get next char */
+ if (el_getc(el, ch) != 1) { /* if EOF or error */
+ val->cmd = ED_END_OF_FILE;
+ return (XK_CMD);
+ /* PWP: Pretend we just read an end-of-file */
+ }
+ return (node_trav(el, ptr->next, ch, val));
+ } else {
+ *val = ptr->val;
+ if (ptr->type != XK_CMD)
+ *ch = '\0';
+ return (ptr->type);
+ }
+ } else {
+ /* no match found here */
+ if (ptr->sibling) {
+ /* try next sibling */
+ return (node_trav(el, ptr->sibling, ch, val));
+ } else {
+ /* no next sibling -- mismatch */
+ val->str = NULL;
+ return (XK_STR);
+ }
+ }
+}
+
+
+/* node__try():
+ * Find a node that matches *str or allocate a new one
+ */
+private int
+node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ntype)
+{
+
+ if (ptr->ch != *str) {
+ key_node_t *xm;
+
+ for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+ if (xm->sibling->ch == *str)
+ break;
+ if (xm->sibling == NULL)
+ xm->sibling = node__get(*str); /* setup new node */
+ ptr = xm->sibling;
+ }
+ if (*++str == '\0') {
+ /* we're there */
+ if (ptr->next != NULL) {
+ node__put(el, ptr->next);
+ /* lose longer keys with this prefix */
+ ptr->next = NULL;
+ }
+ switch (ptr->type) {
+ case XK_CMD:
+ case XK_NOD:
+ break;
+ case XK_STR:
+ case XK_EXE:
+ if (ptr->val.str)
+ el_free((ptr_t) ptr->val.str);
+ break;
+ default:
+ EL_ABORT((el->el_errfile, "Bad XK_ type %d\n",
+ ptr->type));
+ break;
+ }
+
+ switch (ptr->type = ntype) {
+ case XK_CMD:
+ ptr->val = *val;
+ break;
+ case XK_STR:
+ case XK_EXE:
+ ptr->val.str = strdup(val->str);
+ break;
+ default:
+ EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+ break;
+ }
+ } else {
+ /* still more chars to go */
+ if (ptr->next == NULL)
+ ptr->next = node__get(*str); /* setup new node */
+ (void) node__try(el, ptr->next, str, val, ntype);
+ }
+ return (0);
+}
+
+
+/* node__delete():
+ * Delete node that matches str
+ */
+private int
+node__delete(EditLine *el, key_node_t **inptr, const char *str)
+{
+ key_node_t *ptr;
+ key_node_t *prev_ptr = NULL;
+
+ ptr = *inptr;
+
+ if (ptr->ch != *str) {
+ key_node_t *xm;
+
+ for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+ if (xm->sibling->ch == *str)
+ break;
+ if (xm->sibling == NULL)
+ return (0);
+ prev_ptr = xm;
+ ptr = xm->sibling;
+ }
+ if (*++str == '\0') {
+ /* we're there */
+ if (prev_ptr == NULL)
+ *inptr = ptr->sibling;
+ else
+ prev_ptr->sibling = ptr->sibling;
+ ptr->sibling = NULL;
+ node__put(el, ptr);
+ return (1);
+ } else if (ptr->next != NULL &&
+ node__delete(el, &ptr->next, str) == 1) {
+ if (ptr->next != NULL)
+ return (0);
+ if (prev_ptr == NULL)
+ *inptr = ptr->sibling;
+ else
+ prev_ptr->sibling = ptr->sibling;
+ ptr->sibling = NULL;
+ node__put(el, ptr);
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+
+/* node__put():
+ * Puts a tree of nodes onto free list using free(3).
+ */
+private void
+node__put(EditLine *el, key_node_t *ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ if (ptr->next != NULL) {
+ node__put(el, ptr->next);
+ ptr->next = NULL;
+ }
+ node__put(el, ptr->sibling);
+
+ switch (ptr->type) {
+ case XK_CMD:
+ case XK_NOD:
+ break;
+ case XK_EXE:
+ case XK_STR:
+ if (ptr->val.str != NULL)
+ el_free((ptr_t) ptr->val.str);
+ break;
+ default:
+ EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type));
+ break;
+ }
+ el_free((ptr_t) ptr);
+}
+
+
+/* node__get():
+ * Returns pointer to an key_node_t for ch.
+ */
+private key_node_t *
+node__get(int ch)
+{
+ key_node_t *ptr;
+
+ ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t));
+ if (ptr == NULL)
+ return NULL;
+ ptr->ch = ch;
+ ptr->type = XK_NOD;
+ ptr->val.str = NULL;
+ ptr->next = NULL;
+ ptr->sibling = NULL;
+ return (ptr);
+}
+
+
+
+/* node_lookup():
+ * look for the str starting at node ptr.
+ * Print if last node
+ */
+private int
+node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)
+{
+ int ncnt;
+
+ if (ptr == NULL)
+ return (-1); /* cannot have null ptr */
+
+ if (*str == 0) {
+ /* no more chars in str. node_enum from here. */
+ (void) node_enum(el, ptr, cnt);
+ return (0);
+ } else {
+ /* If match put this char into el->el_key.buf. Recurse */
+ if (ptr->ch == *str) {
+ /* match found */
+ ncnt = key__decode_char(el->el_key.buf, cnt,
+ (unsigned char) ptr->ch);
+ if (ptr->next != NULL)
+ /* not yet at leaf */
+ return (node_lookup(el, str + 1, ptr->next,
+ ncnt + 1));
+ else {
+ /* next node is null so key should be complete */
+ if (str[1] == 0) {
+ el->el_key.buf[ncnt + 1] = '"';
+ el->el_key.buf[ncnt + 2] = '\0';
+ key_kprint(el, el->el_key.buf,
+ &ptr->val, ptr->type);
+ return (0);
+ } else
+ return (-1);
+ /* mismatch -- str still has chars */
+ }
+ } else {
+ /* no match found try sibling */
+ if (ptr->sibling)
+ return (node_lookup(el, str, ptr->sibling,
+ cnt));
+ else
+ return (-1);
+ }
+ }
+}
+
+
+/* node_enum():
+ * Traverse the node printing the characters it is bound in buffer
+ */
+private int
+node_enum(EditLine *el, key_node_t *ptr, int cnt)
+{
+ int ncnt;
+
+ if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */
+ el->el_key.buf[++cnt] = '"';
+ el->el_key.buf[++cnt] = '\0';
+ (void) fprintf(el->el_errfile,
+ "Some extended keys too long for internal print buffer");
+ (void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf);
+ return (0);
+ }
+ if (ptr == NULL) {
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile,
+ "node_enum: BUG!! Null ptr passed\n!");
+#endif
+ return (-1);
+ }
+ /* put this char at end of str */
+ ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch);
+ if (ptr->next == NULL) {
+ /* print this key and function */
+ el->el_key.buf[ncnt + 1] = '"';
+ el->el_key.buf[ncnt + 2] = '\0';
+ key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
+ } else
+ (void) node_enum(el, ptr->next, ncnt + 1);
+
+ /* go to sibling if there is one */
+ if (ptr->sibling)
+ (void) node_enum(el, ptr->sibling, cnt);
+ return (0);
+}
+
+
+/* key_kprint():
+ * Print the specified key and its associated
+ * function specified by val
+ */
+protected void
+key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)
+{
+ el_bindings_t *fp;
+ char unparsbuf[EL_BUFSIZ];
+ static const char fmt[] = "%-15s-> %s\n";
+
+ if (val != NULL)
+ switch (ntype) {
+ case XK_STR:
+ case XK_EXE:
+ (void) fprintf(el->el_outfile, fmt, key,
+ key__decode_str(val->str, unparsbuf,
+ ntype == XK_STR ? "\"\"" : "[]"));
+ break;
+ case XK_CMD:
+ for (fp = el->el_map.help; fp->name; fp++)
+ if (val->cmd == fp->func) {
+ (void) fprintf(el->el_outfile, fmt,
+ key, fp->name);
+ break;
+ }
+#ifdef DEBUG_KEY
+ if (fp->name == NULL)
+ (void) fprintf(el->el_outfile,
+ "BUG! Command not found.\n");
+#endif
+
+ break;
+ default:
+ EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+ break;
+ }
+ else
+ (void) fprintf(el->el_outfile, fmt, key, "no input");
+}
+
+
+/* key__decode_char():
+ * Put a printable form of char in buf.
+ */
+private int
+key__decode_char(char *buf, int cnt, int ch)
+{
+ if (ch == 0) {
+ buf[cnt++] = '^';
+ buf[cnt] = '@';
+ return (cnt);
+ }
+ if (iscntrl(ch)) {
+ buf[cnt++] = '^';
+ if (ch == '\177')
+ buf[cnt] = '?';
+ else
+ buf[cnt] = ch | 0100;
+ } else if (ch == '^') {
+ buf[cnt++] = '\\';
+ buf[cnt] = '^';
+ } else if (ch == '\\') {
+ buf[cnt++] = '\\';
+ buf[cnt] = '\\';
+ } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) {
+ buf[cnt] = ch;
+ } else {
+ buf[cnt++] = '\\';
+ buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0';
+ buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0';
+ buf[cnt] = (ch & 7) + '0';
+ }
+ return (cnt);
+}
+
+
+/* key__decode_str():
+ * Make a printable version of the ey
+ */
+protected char *
+key__decode_str(const char *str, char *buf, const char *sep)
+{
+ char *b;
+ const char *p;
+
+ b = buf;
+ if (sep[0] != '\0')
+ *b++ = sep[0];
+ if (*str == 0) {
+ *b++ = '^';
+ *b++ = '@';
+ if (sep[0] != '\0' && sep[1] != '\0')
+ *b++ = sep[1];
+ *b++ = 0;
+ return (buf);
+ }
+ for (p = str; *p != 0; p++) {
+ if (iscntrl((unsigned char) *p)) {
+ *b++ = '^';
+ if (*p == '\177')
+ *b++ = '?';
+ else
+ *b++ = *p | 0100;
+ } else if (*p == '^' || *p == '\\') {
+ *b++ = '\\';
+ *b++ = *p;
+ } else if (*p == ' ' || (isprint((unsigned char) *p) &&
+ !isspace((unsigned char) *p))) {
+ *b++ = *p;
+ } else {
+ *b++ = '\\';
+ *b++ = (((unsigned int) *p >> 6) & 7) + '0';
+ *b++ = (((unsigned int) *p >> 3) & 7) + '0';
+ *b++ = (*p & 7) + '0';
+ }
+ }
+ if (sep[0] != '\0' && sep[1] != '\0')
+ *b++ = sep[1];
+ *b++ = 0;
+ return (buf); /* should check for overflow */
+}
diff --git a/cmd-line-utils/libedit/key.h b/cmd-line-utils/libedit/key.h
new file mode 100644
index 00000000000..c3a0889f901
--- /dev/null
+++ b/cmd-line-utils/libedit/key.h
@@ -0,0 +1,79 @@
+/* $NetBSD: key.h,v 1.5 2001/01/23 15:55:30 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)key.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.key.h: Key macro header
+ */
+#ifndef _h_el_key
+#define _h_el_key
+
+typedef union key_value_t {
+ el_action_t cmd; /* If it is a command the # */
+ char *str; /* If it is a string... */
+} key_value_t;
+
+typedef struct key_node_t key_node_t;
+
+typedef struct el_key_t {
+ char *buf; /* Key print buffer */
+ key_node_t *map; /* Key map */
+ key_value_t val; /* Local conversion buffer */
+} el_key_t;
+
+#define XK_CMD 0
+#define XK_STR 1
+#define XK_NOD 2
+#define XK_EXE 3
+
+protected int key_init(EditLine *);
+protected void key_end(EditLine *);
+protected key_value_t *key_map_cmd(EditLine *, int);
+protected key_value_t *key_map_str(EditLine *, char *);
+protected void key_reset(EditLine *);
+protected int key_get(EditLine *, char *, key_value_t *);
+protected void key_add(EditLine *, const char *, key_value_t *, int);
+protected void key_clear(EditLine *, el_action_t *, const char *);
+protected int key_delete(EditLine *, const char *);
+protected void key_print(EditLine *, const char *);
+protected void key_kprint(EditLine *, const char *,
+ key_value_t *, int);
+protected char *key__decode_str(const char *, char *, const char *);
+
+#endif /* _h_el_key */
diff --git a/cmd-line-utils/libedit/makelist b/cmd-line-utils/libedit/makelist
new file mode 100644
index 00000000000..8e9835309d6
--- /dev/null
+++ b/cmd-line-utils/libedit/makelist
@@ -0,0 +1,254 @@
+#!/bin/sh -
+# $NetBSD: makelist,v 1.7 2001/01/09 19:22:31 jdolecek Exp $
+#
+# Copyright (c) 1992, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Christos Zoulas of Cornell University.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)makelist 5.3 (Berkeley) 6/4/93
+
+# makelist.sh: Automatically generate header files...
+
+AWK=/usr/bin/awk
+USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
+
+if [ "x$1" = "x" ]
+then
+ echo $USAGE 1>&2
+ exit 1
+fi
+
+FLAG="$1"
+shift
+
+FILES="$@"
+
+case $FLAG in
+
+# generate foo.h file from foo.c
+#
+-h)
+ set - `echo $FILES | sed -e 's/\\./_/g'`
+ hdr="_h_`basename $1`"
+ cat $FILES | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
+ }
+ /\(\):/ {
+ pr = substr($2, 1, 2);
+ if (pr == "vi" || pr == "em" || pr == "ed") {
+ name = substr($2, 1, length($2) - 3);
+#
+# XXX: need a space between name and prototype so that -fc and -fh
+# parsing is much easier
+#
+ printf("protected el_action_t\t%s (EditLine *, int);\n", name);
+ }
+ }
+ END {
+ printf("#endif /* %s */\n", "'$hdr'");
+ }'
+ ;;
+
+# generate help.c from various .c files
+#
+-bc)
+ cat $FILES | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#include \"sys.h\"\n#include \"el.h\"\n");
+ printf("private const struct el_bindings_t el_func_help[] = {\n");
+ low = "abcdefghijklmnopqrstuvwxyz_";
+ high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
+ for (i = 1; i <= length(low); i++)
+ tr[substr(low, i, 1)] = substr(high, i, 1);
+ }
+ /\(\):/ {
+ pr = substr($2, 1, 2);
+ if (pr == "vi" || pr == "em" || pr == "ed") {
+ name = substr($2, 1, length($2) - 3);
+ uname = "";
+ fname = "";
+ for (i = 1; i <= length(name); i++) {
+ s = substr(name, i, 1);
+ uname = uname tr[s];
+ if (s == "_")
+ s = "-";
+ fname = fname s;
+ }
+
+ printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ",");
+ ok = 1;
+ }
+ }
+ /^ \*/ {
+ if (ok) {
+ printf(" \"");
+ for (i = 2; i < NF; i++)
+ printf("%s ", $i);
+ printf("%s\" },\n", $i);
+ ok = 0;
+ }
+ }
+ END {
+ printf(" { NULL, 0, NULL }\n");
+ printf("};\n");
+ printf("\nprotected const el_bindings_t* help__get()");
+ printf("{ return el_func_help; }\n");
+ }'
+ ;;
+
+# generate help.h from various .c files
+#
+-bh)
+ $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#ifndef _h_help_c\n#define _h_help_c\n");
+ printf("protected const el_bindings_t *help__get(void);\n");
+ printf("#endif /* _h_help_c */\n");
+ }' /dev/null
+ ;;
+
+# generate fcns.h from various .h files
+#
+-fh)
+ cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
+ sort | tr '[a-z]' '[A-Z]' | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
+ count = 0;
+ }
+ {
+ printf("#define\t%-30.30s\t%3d\n", $1, count++);
+ }
+ END {
+ printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
+
+ printf("typedef el_action_t (*el_func_t)(EditLine *, int);");
+ printf("\nprotected const el_func_t* func__get(void);\n");
+ printf("#endif /* _h_fcns_c */\n");
+ }'
+ ;;
+
+# generate fcns.c from various .h files
+#
+-fc)
+ cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#include \"sys.h\"\n#include \"el.h\"\n");
+ printf("private const el_func_t el_func[] = {");
+ maxlen = 80;
+ needn = 1;
+ len = 0;
+ }
+ {
+ clen = 25 + 2;
+ len += clen;
+ if (len >= maxlen)
+ needn = 1;
+ if (needn) {
+ printf("\n ");
+ needn = 0;
+ len = 4 + clen;
+ }
+ s = $1 ",";
+ printf("%-26.26s ", s);
+ }
+ END {
+ printf("\n};\n");
+ printf("\nprotected const el_func_t* func__get() { return el_func; }\n");
+ }'
+ ;;
+
+# generate editline.c from various .c files
+#
+-e)
+ echo "$FILES" | tr ' ' '\012' | $AWK '
+ BEGIN {
+ printf("/* Automatically generated file, do not edit */\n");
+ printf("#define protected static\n");
+ printf("#define SCCSID\n");
+ }
+ {
+ printf("#include \"%s\"\n", $1);
+ }'
+ ;;
+
+# generate man page fragment from various .c files
+#
+-m)
+ cat $FILES | $AWK '
+ BEGIN {
+ printf(".\\\" Section automatically generated with makelist\n");
+ printf(".Bl -tag -width 4n\n");
+ }
+ /\(\):/ {
+ pr = substr($2, 1, 2);
+ if (pr == "vi" || pr == "em" || pr == "ed") {
+ name = substr($2, 1, length($2) - 3);
+ fname = "";
+ for (i = 1; i <= length(name); i++) {
+ s = substr(name, i, 1);
+ if (s == "_")
+ s = "-";
+ fname = fname s;
+ }
+
+ printf(".It Ic %s\n", fname);
+ ok = 1;
+ }
+ }
+ /^ \*/ {
+ if (ok) {
+ for (i = 2; i < NF; i++)
+ printf("%s ", $i);
+ printf("%s.\n", $i);
+ ok = 0;
+ }
+ }
+ END {
+ printf(".El\n");
+ printf(".\\\" End of section automatically generated with makelist\n");
+ }'
+ ;;
+
+*)
+ echo $USAGE 1>&2
+ exit 1
+ ;;
+
+esac
diff --git a/cmd-line-utils/libedit/map.c b/cmd-line-utils/libedit/map.c
new file mode 100644
index 00000000000..144ccf1ebe0
--- /dev/null
+++ b/cmd-line-utils/libedit/map.c
@@ -0,0 +1,1412 @@
+/* $NetBSD: map.c,v 1.14 2001/01/09 17:22:09 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * map.c: Editor function definitions
+ */
+#include "sys.h"
+#include <stdlib.h>
+#include "el.h"
+
+#define N_KEYS 256
+
+private void map_print_key(EditLine *, el_action_t *, const char *);
+private void map_print_some_keys(EditLine *, el_action_t *, int, int);
+private void map_print_all_keys(EditLine *);
+private void map_init_nls(EditLine *);
+private void map_init_meta(EditLine *);
+
+/* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */
+
+
+private const el_action_t el_map_emacs[] = {
+ /* 0 */ EM_SET_MARK, /* ^@ */
+ /* 1 */ ED_MOVE_TO_BEG, /* ^A */
+ /* 2 */ ED_PREV_CHAR, /* ^B */
+ /* 3 */ ED_TTY_SIGINT, /* ^C */
+ /* 4 */ EM_DELETE_OR_LIST, /* ^D */
+ /* 5 */ ED_MOVE_TO_END, /* ^E */
+ /* 6 */ ED_NEXT_CHAR, /* ^F */
+ /* 7 */ ED_UNASSIGNED, /* ^G */
+ /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */
+ /* 9 */ ED_UNASSIGNED, /* ^I */
+ /* 10 */ ED_NEWLINE, /* ^J */
+ /* 11 */ ED_KILL_LINE, /* ^K */
+ /* 12 */ ED_CLEAR_SCREEN, /* ^L */
+ /* 13 */ ED_NEWLINE, /* ^M */
+ /* 14 */ ED_NEXT_HISTORY, /* ^N */
+ /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
+ /* 16 */ ED_PREV_HISTORY, /* ^P */
+ /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
+ /* 18 */ ED_REDISPLAY, /* ^R */
+ /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
+ /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */
+ /* 21 */ EM_KILL_LINE, /* ^U */
+ /* 22 */ ED_QUOTED_INSERT, /* ^V */
+ /* 23 */ EM_KILL_REGION, /* ^W */
+ /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */
+ /* 25 */ EM_YANK, /* ^Y */
+ /* 26 */ ED_TTY_SIGTSTP, /* ^Z */
+ /* 27 */ EM_META_NEXT, /* ^[ */
+ /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
+ /* 29 */ ED_TTY_DSUSP, /* ^] */
+ /* 30 */ ED_UNASSIGNED, /* ^^ */
+ /* 31 */ ED_UNASSIGNED, /* ^_ */
+ /* 32 */ ED_INSERT, /* SPACE */
+ /* 33 */ ED_INSERT, /* ! */
+ /* 34 */ ED_INSERT, /* " */
+ /* 35 */ ED_INSERT, /* # */
+ /* 36 */ ED_INSERT, /* $ */
+ /* 37 */ ED_INSERT, /* % */
+ /* 38 */ ED_INSERT, /* & */
+ /* 39 */ ED_INSERT, /* ' */
+ /* 40 */ ED_INSERT, /* ( */
+ /* 41 */ ED_INSERT, /* ) */
+ /* 42 */ ED_INSERT, /* * */
+ /* 43 */ ED_INSERT, /* + */
+ /* 44 */ ED_INSERT, /* , */
+ /* 45 */ ED_INSERT, /* - */
+ /* 46 */ ED_INSERT, /* . */
+ /* 47 */ ED_INSERT, /* / */
+ /* 48 */ ED_DIGIT, /* 0 */
+ /* 49 */ ED_DIGIT, /* 1 */
+ /* 50 */ ED_DIGIT, /* 2 */
+ /* 51 */ ED_DIGIT, /* 3 */
+ /* 52 */ ED_DIGIT, /* 4 */
+ /* 53 */ ED_DIGIT, /* 5 */
+ /* 54 */ ED_DIGIT, /* 6 */
+ /* 55 */ ED_DIGIT, /* 7 */
+ /* 56 */ ED_DIGIT, /* 8 */
+ /* 57 */ ED_DIGIT, /* 9 */
+ /* 58 */ ED_INSERT, /* : */
+ /* 59 */ ED_INSERT, /* ; */
+ /* 60 */ ED_INSERT, /* < */
+ /* 61 */ ED_INSERT, /* = */
+ /* 62 */ ED_INSERT, /* > */
+ /* 63 */ ED_INSERT, /* ? */
+ /* 64 */ ED_INSERT, /* @ */
+ /* 65 */ ED_INSERT, /* A */
+ /* 66 */ ED_INSERT, /* B */
+ /* 67 */ ED_INSERT, /* C */
+ /* 68 */ ED_INSERT, /* D */
+ /* 69 */ ED_INSERT, /* E */
+ /* 70 */ ED_INSERT, /* F */
+ /* 71 */ ED_INSERT, /* G */
+ /* 72 */ ED_INSERT, /* H */
+ /* 73 */ ED_INSERT, /* I */
+ /* 74 */ ED_INSERT, /* J */
+ /* 75 */ ED_INSERT, /* K */
+ /* 76 */ ED_INSERT, /* L */
+ /* 77 */ ED_INSERT, /* M */
+ /* 78 */ ED_INSERT, /* N */
+ /* 79 */ ED_INSERT, /* O */
+ /* 80 */ ED_INSERT, /* P */
+ /* 81 */ ED_INSERT, /* Q */
+ /* 82 */ ED_INSERT, /* R */
+ /* 83 */ ED_INSERT, /* S */
+ /* 84 */ ED_INSERT, /* T */
+ /* 85 */ ED_INSERT, /* U */
+ /* 86 */ ED_INSERT, /* V */
+ /* 87 */ ED_INSERT, /* W */
+ /* 88 */ ED_INSERT, /* X */
+ /* 89 */ ED_INSERT, /* Y */
+ /* 90 */ ED_INSERT, /* Z */
+ /* 91 */ ED_INSERT, /* [ */
+ /* 92 */ ED_INSERT, /* \ */
+ /* 93 */ ED_INSERT, /* ] */
+ /* 94 */ ED_INSERT, /* ^ */
+ /* 95 */ ED_INSERT, /* _ */
+ /* 96 */ ED_INSERT, /* ` */
+ /* 97 */ ED_INSERT, /* a */
+ /* 98 */ ED_INSERT, /* b */
+ /* 99 */ ED_INSERT, /* c */
+ /* 100 */ ED_INSERT, /* d */
+ /* 101 */ ED_INSERT, /* e */
+ /* 102 */ ED_INSERT, /* f */
+ /* 103 */ ED_INSERT, /* g */
+ /* 104 */ ED_INSERT, /* h */
+ /* 105 */ ED_INSERT, /* i */
+ /* 106 */ ED_INSERT, /* j */
+ /* 107 */ ED_INSERT, /* k */
+ /* 108 */ ED_INSERT, /* l */
+ /* 109 */ ED_INSERT, /* m */
+ /* 110 */ ED_INSERT, /* n */
+ /* 111 */ ED_INSERT, /* o */
+ /* 112 */ ED_INSERT, /* p */
+ /* 113 */ ED_INSERT, /* q */
+ /* 114 */ ED_INSERT, /* r */
+ /* 115 */ ED_INSERT, /* s */
+ /* 116 */ ED_INSERT, /* t */
+ /* 117 */ ED_INSERT, /* u */
+ /* 118 */ ED_INSERT, /* v */
+ /* 119 */ ED_INSERT, /* w */
+ /* 120 */ ED_INSERT, /* x */
+ /* 121 */ ED_INSERT, /* y */
+ /* 122 */ ED_INSERT, /* z */
+ /* 123 */ ED_INSERT, /* { */
+ /* 124 */ ED_INSERT, /* | */
+ /* 125 */ ED_INSERT, /* } */
+ /* 126 */ ED_INSERT, /* ~ */
+ /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
+ /* 128 */ ED_UNASSIGNED, /* M-^@ */
+ /* 129 */ ED_UNASSIGNED, /* M-^A */
+ /* 130 */ ED_UNASSIGNED, /* M-^B */
+ /* 131 */ ED_UNASSIGNED, /* M-^C */
+ /* 132 */ ED_UNASSIGNED, /* M-^D */
+ /* 133 */ ED_UNASSIGNED, /* M-^E */
+ /* 134 */ ED_UNASSIGNED, /* M-^F */
+ /* 135 */ ED_UNASSIGNED, /* M-^G */
+ /* 136 */ ED_DELETE_PREV_WORD, /* M-^H */
+ /* 137 */ ED_UNASSIGNED, /* M-^I */
+ /* 138 */ ED_UNASSIGNED, /* M-^J */
+ /* 139 */ ED_UNASSIGNED, /* M-^K */
+ /* 140 */ ED_CLEAR_SCREEN, /* M-^L */
+ /* 141 */ ED_UNASSIGNED, /* M-^M */
+ /* 142 */ ED_UNASSIGNED, /* M-^N */
+ /* 143 */ ED_UNASSIGNED, /* M-^O */
+ /* 144 */ ED_UNASSIGNED, /* M-^P */
+ /* 145 */ ED_UNASSIGNED, /* M-^Q */
+ /* 146 */ ED_UNASSIGNED, /* M-^R */
+ /* 147 */ ED_UNASSIGNED, /* M-^S */
+ /* 148 */ ED_UNASSIGNED, /* M-^T */
+ /* 149 */ ED_UNASSIGNED, /* M-^U */
+ /* 150 */ ED_UNASSIGNED, /* M-^V */
+ /* 151 */ ED_UNASSIGNED, /* M-^W */
+ /* 152 */ ED_UNASSIGNED, /* M-^X */
+ /* 153 */ ED_UNASSIGNED, /* M-^Y */
+ /* 154 */ ED_UNASSIGNED, /* M-^Z */
+ /* 155 */ ED_UNASSIGNED, /* M-^[ */
+ /* 156 */ ED_UNASSIGNED, /* M-^\ */
+ /* 157 */ ED_UNASSIGNED, /* M-^] */
+ /* 158 */ ED_UNASSIGNED, /* M-^^ */
+ /* 159 */ EM_COPY_PREV_WORD, /* M-^_ */
+ /* 160 */ ED_UNASSIGNED, /* M-SPACE */
+ /* 161 */ ED_UNASSIGNED, /* M-! */
+ /* 162 */ ED_UNASSIGNED, /* M-" */
+ /* 163 */ ED_UNASSIGNED, /* M-# */
+ /* 164 */ ED_UNASSIGNED, /* M-$ */
+ /* 165 */ ED_UNASSIGNED, /* M-% */
+ /* 166 */ ED_UNASSIGNED, /* M-& */
+ /* 167 */ ED_UNASSIGNED, /* M-' */
+ /* 168 */ ED_UNASSIGNED, /* M-( */
+ /* 169 */ ED_UNASSIGNED, /* M-) */
+ /* 170 */ ED_UNASSIGNED, /* M-* */
+ /* 171 */ ED_UNASSIGNED, /* M-+ */
+ /* 172 */ ED_UNASSIGNED, /* M-, */
+ /* 173 */ ED_UNASSIGNED, /* M-- */
+ /* 174 */ ED_UNASSIGNED, /* M-. */
+ /* 175 */ ED_UNASSIGNED, /* M-/ */
+ /* 176 */ ED_ARGUMENT_DIGIT, /* M-0 */
+ /* 177 */ ED_ARGUMENT_DIGIT, /* M-1 */
+ /* 178 */ ED_ARGUMENT_DIGIT, /* M-2 */
+ /* 179 */ ED_ARGUMENT_DIGIT, /* M-3 */
+ /* 180 */ ED_ARGUMENT_DIGIT, /* M-4 */
+ /* 181 */ ED_ARGUMENT_DIGIT, /* M-5 */
+ /* 182 */ ED_ARGUMENT_DIGIT, /* M-6 */
+ /* 183 */ ED_ARGUMENT_DIGIT, /* M-7 */
+ /* 184 */ ED_ARGUMENT_DIGIT, /* M-8 */
+ /* 185 */ ED_ARGUMENT_DIGIT, /* M-9 */
+ /* 186 */ ED_UNASSIGNED, /* M-: */
+ /* 187 */ ED_UNASSIGNED, /* M-; */
+ /* 188 */ ED_UNASSIGNED, /* M-< */
+ /* 189 */ ED_UNASSIGNED, /* M-= */
+ /* 190 */ ED_UNASSIGNED, /* M-> */
+ /* 191 */ ED_UNASSIGNED, /* M-? */
+ /* 192 */ ED_UNASSIGNED, /* M-@ */
+ /* 193 */ ED_UNASSIGNED, /* M-A */
+ /* 194 */ ED_PREV_WORD, /* M-B */
+ /* 195 */ EM_CAPITOL_CASE, /* M-C */
+ /* 196 */ EM_DELETE_NEXT_WORD, /* M-D */
+ /* 197 */ ED_UNASSIGNED, /* M-E */
+ /* 198 */ EM_NEXT_WORD, /* M-F */
+ /* 199 */ ED_UNASSIGNED, /* M-G */
+ /* 200 */ ED_UNASSIGNED, /* M-H */
+ /* 201 */ ED_UNASSIGNED, /* M-I */
+ /* 202 */ ED_UNASSIGNED, /* M-J */
+ /* 203 */ ED_UNASSIGNED, /* M-K */
+ /* 204 */ EM_LOWER_CASE, /* M-L */
+ /* 205 */ ED_UNASSIGNED, /* M-M */
+ /* 206 */ ED_SEARCH_NEXT_HISTORY, /* M-N */
+ /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */
+ /* 208 */ ED_SEARCH_PREV_HISTORY, /* M-P */
+ /* 209 */ ED_UNASSIGNED, /* M-Q */
+ /* 210 */ ED_UNASSIGNED, /* M-R */
+ /* 211 */ ED_UNASSIGNED, /* M-S */
+ /* 212 */ ED_UNASSIGNED, /* M-T */
+ /* 213 */ EM_UPPER_CASE, /* M-U */
+ /* 214 */ ED_UNASSIGNED, /* M-V */
+ /* 215 */ EM_COPY_REGION, /* M-W */
+ /* 216 */ ED_COMMAND, /* M-X */
+ /* 217 */ ED_UNASSIGNED, /* M-Y */
+ /* 218 */ ED_UNASSIGNED, /* M-Z */
+ /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */
+ /* 220 */ ED_UNASSIGNED, /* M-\ */
+ /* 221 */ ED_UNASSIGNED, /* M-] */
+ /* 222 */ ED_UNASSIGNED, /* M-^ */
+ /* 223 */ ED_UNASSIGNED, /* M-_ */
+ /* 223 */ ED_UNASSIGNED, /* M-` */
+ /* 224 */ ED_UNASSIGNED, /* M-a */
+ /* 225 */ ED_PREV_WORD, /* M-b */
+ /* 226 */ EM_CAPITOL_CASE, /* M-c */
+ /* 227 */ EM_DELETE_NEXT_WORD, /* M-d */
+ /* 228 */ ED_UNASSIGNED, /* M-e */
+ /* 229 */ EM_NEXT_WORD, /* M-f */
+ /* 230 */ ED_UNASSIGNED, /* M-g */
+ /* 231 */ ED_UNASSIGNED, /* M-h */
+ /* 232 */ ED_UNASSIGNED, /* M-i */
+ /* 233 */ ED_UNASSIGNED, /* M-j */
+ /* 234 */ ED_UNASSIGNED, /* M-k */
+ /* 235 */ EM_LOWER_CASE, /* M-l */
+ /* 236 */ ED_UNASSIGNED, /* M-m */
+ /* 237 */ ED_SEARCH_NEXT_HISTORY, /* M-n */
+ /* 238 */ ED_UNASSIGNED, /* M-o */
+ /* 239 */ ED_SEARCH_PREV_HISTORY, /* M-p */
+ /* 240 */ ED_UNASSIGNED, /* M-q */
+ /* 241 */ ED_UNASSIGNED, /* M-r */
+ /* 242 */ ED_UNASSIGNED, /* M-s */
+ /* 243 */ ED_UNASSIGNED, /* M-t */
+ /* 244 */ EM_UPPER_CASE, /* M-u */
+ /* 245 */ ED_UNASSIGNED, /* M-v */
+ /* 246 */ EM_COPY_REGION, /* M-w */
+ /* 247 */ ED_COMMAND, /* M-x */
+ /* 248 */ ED_UNASSIGNED, /* M-y */
+ /* 249 */ ED_UNASSIGNED, /* M-z */
+ /* 250 */ ED_UNASSIGNED, /* M-{ */
+ /* 251 */ ED_UNASSIGNED, /* M-| */
+ /* 252 */ ED_UNASSIGNED, /* M-} */
+ /* 253 */ ED_UNASSIGNED, /* M-~ */
+ /* 254 */ ED_DELETE_PREV_WORD /* M-^? */
+ /* 255 */
+};
+
+
+/*
+ * keymap table for vi. Each index into above tbl; should be
+ * N_KEYS entries long. Vi mode uses a sticky-extend to do command mode:
+ * insert mode characters are in the normal keymap, and command mode
+ * in the extended keymap.
+ */
+private const el_action_t el_map_vi_insert[] = {
+#ifdef KSHVI
+ /* 0 */ ED_UNASSIGNED, /* ^@ */
+ /* 1 */ ED_INSERT, /* ^A */
+ /* 2 */ ED_INSERT, /* ^B */
+ /* 3 */ ED_INSERT, /* ^C */
+ /* 4 */ VI_LIST_OR_EOF, /* ^D */
+ /* 5 */ ED_INSERT, /* ^E */
+ /* 6 */ ED_INSERT, /* ^F */
+ /* 7 */ ED_INSERT, /* ^G */
+ /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */
+ /* 9 */ ED_INSERT, /* ^I */ /* Tab Key */
+ /* 10 */ ED_NEWLINE, /* ^J */
+ /* 11 */ ED_INSERT, /* ^K */
+ /* 12 */ ED_INSERT, /* ^L */
+ /* 13 */ ED_NEWLINE, /* ^M */
+ /* 14 */ ED_INSERT, /* ^N */
+ /* 15 */ ED_INSERT, /* ^O */
+ /* 16 */ ED_INSERT, /* ^P */
+ /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
+ /* 18 */ ED_INSERT, /* ^R */
+ /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
+ /* 20 */ ED_INSERT, /* ^T */
+ /* 21 */ VI_KILL_LINE_PREV, /* ^U */
+ /* 22 */ ED_QUOTED_INSERT, /* ^V */
+ /* 23 */ ED_DELETE_PREV_WORD, /* ^W */
+ /* ED_DELETE_PREV_WORD: Only until strt edit pos */
+ /* 24 */ ED_INSERT, /* ^X */
+ /* 25 */ ED_INSERT, /* ^Y */
+ /* 26 */ ED_INSERT, /* ^Z */
+ /* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */
+ /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
+ /* 29 */ ED_INSERT, /* ^] */
+ /* 30 */ ED_INSERT, /* ^^ */
+ /* 31 */ ED_INSERT, /* ^_ */
+#else /* !KSHVI */
+ /*
+ * NOTE: These mappings do NOT Correspond well
+ * to the KSH VI editing assignments.
+ * On the other and they are convenient and
+ * many people have have gotten used to them.
+ */
+ /* 0 */ ED_UNASSIGNED, /* ^@ */
+ /* 1 */ ED_MOVE_TO_BEG, /* ^A */
+ /* 2 */ ED_PREV_CHAR, /* ^B */
+ /* 3 */ ED_TTY_SIGINT, /* ^C */
+ /* 4 */ VI_LIST_OR_EOF, /* ^D */
+ /* 5 */ ED_MOVE_TO_END, /* ^E */
+ /* 6 */ ED_NEXT_CHAR, /* ^F */
+ /* 7 */ ED_UNASSIGNED, /* ^G */
+ /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */
+ /* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */
+ /* 10 */ ED_NEWLINE, /* ^J */
+ /* 11 */ ED_KILL_LINE, /* ^K */
+ /* 12 */ ED_CLEAR_SCREEN, /* ^L */
+ /* 13 */ ED_NEWLINE, /* ^M */
+ /* 14 */ ED_NEXT_HISTORY, /* ^N */
+ /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
+ /* 16 */ ED_PREV_HISTORY, /* ^P */
+ /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
+ /* 18 */ ED_REDISPLAY, /* ^R */
+ /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
+ /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */
+ /* 21 */ VI_KILL_LINE_PREV, /* ^U */
+ /* 22 */ ED_QUOTED_INSERT, /* ^V */
+ /* 23 */ ED_DELETE_PREV_WORD, /* ^W */
+ /* 24 */ ED_UNASSIGNED, /* ^X */
+ /* 25 */ ED_TTY_DSUSP, /* ^Y */
+ /* 26 */ ED_TTY_SIGTSTP, /* ^Z */
+ /* 27 */ VI_COMMAND_MODE, /* ^[ */
+ /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
+ /* 29 */ ED_UNASSIGNED, /* ^] */
+ /* 30 */ ED_UNASSIGNED, /* ^^ */
+ /* 31 */ ED_UNASSIGNED, /* ^_ */
+#endif /* KSHVI */
+ /* 32 */ ED_INSERT, /* SPACE */
+ /* 33 */ ED_INSERT, /* ! */
+ /* 34 */ ED_INSERT, /* " */
+ /* 35 */ ED_INSERT, /* # */
+ /* 36 */ ED_INSERT, /* $ */
+ /* 37 */ ED_INSERT, /* % */
+ /* 38 */ ED_INSERT, /* & */
+ /* 39 */ ED_INSERT, /* ' */
+ /* 40 */ ED_INSERT, /* ( */
+ /* 41 */ ED_INSERT, /* ) */
+ /* 42 */ ED_INSERT, /* * */
+ /* 43 */ ED_INSERT, /* + */
+ /* 44 */ ED_INSERT, /* , */
+ /* 45 */ ED_INSERT, /* - */
+ /* 46 */ ED_INSERT, /* . */
+ /* 47 */ ED_INSERT, /* / */
+ /* 48 */ ED_INSERT, /* 0 */
+ /* 49 */ ED_INSERT, /* 1 */
+ /* 50 */ ED_INSERT, /* 2 */
+ /* 51 */ ED_INSERT, /* 3 */
+ /* 52 */ ED_INSERT, /* 4 */
+ /* 53 */ ED_INSERT, /* 5 */
+ /* 54 */ ED_INSERT, /* 6 */
+ /* 55 */ ED_INSERT, /* 7 */
+ /* 56 */ ED_INSERT, /* 8 */
+ /* 57 */ ED_INSERT, /* 9 */
+ /* 58 */ ED_INSERT, /* : */
+ /* 59 */ ED_INSERT, /* ; */
+ /* 60 */ ED_INSERT, /* < */
+ /* 61 */ ED_INSERT, /* = */
+ /* 62 */ ED_INSERT, /* > */
+ /* 63 */ ED_INSERT, /* ? */
+ /* 64 */ ED_INSERT, /* @ */
+ /* 65 */ ED_INSERT, /* A */
+ /* 66 */ ED_INSERT, /* B */
+ /* 67 */ ED_INSERT, /* C */
+ /* 68 */ ED_INSERT, /* D */
+ /* 69 */ ED_INSERT, /* E */
+ /* 70 */ ED_INSERT, /* F */
+ /* 71 */ ED_INSERT, /* G */
+ /* 72 */ ED_INSERT, /* H */
+ /* 73 */ ED_INSERT, /* I */
+ /* 74 */ ED_INSERT, /* J */
+ /* 75 */ ED_INSERT, /* K */
+ /* 76 */ ED_INSERT, /* L */
+ /* 77 */ ED_INSERT, /* M */
+ /* 78 */ ED_INSERT, /* N */
+ /* 79 */ ED_INSERT, /* O */
+ /* 80 */ ED_INSERT, /* P */
+ /* 81 */ ED_INSERT, /* Q */
+ /* 82 */ ED_INSERT, /* R */
+ /* 83 */ ED_INSERT, /* S */
+ /* 84 */ ED_INSERT, /* T */
+ /* 85 */ ED_INSERT, /* U */
+ /* 86 */ ED_INSERT, /* V */
+ /* 87 */ ED_INSERT, /* W */
+ /* 88 */ ED_INSERT, /* X */
+ /* 89 */ ED_INSERT, /* Y */
+ /* 90 */ ED_INSERT, /* Z */
+ /* 91 */ ED_INSERT, /* [ */
+ /* 92 */ ED_INSERT, /* \ */
+ /* 93 */ ED_INSERT, /* ] */
+ /* 94 */ ED_INSERT, /* ^ */
+ /* 95 */ ED_INSERT, /* _ */
+ /* 96 */ ED_INSERT, /* ` */
+ /* 97 */ ED_INSERT, /* a */
+ /* 98 */ ED_INSERT, /* b */
+ /* 99 */ ED_INSERT, /* c */
+ /* 100 */ ED_INSERT, /* d */
+ /* 101 */ ED_INSERT, /* e */
+ /* 102 */ ED_INSERT, /* f */
+ /* 103 */ ED_INSERT, /* g */
+ /* 104 */ ED_INSERT, /* h */
+ /* 105 */ ED_INSERT, /* i */
+ /* 106 */ ED_INSERT, /* j */
+ /* 107 */ ED_INSERT, /* k */
+ /* 108 */ ED_INSERT, /* l */
+ /* 109 */ ED_INSERT, /* m */
+ /* 110 */ ED_INSERT, /* n */
+ /* 111 */ ED_INSERT, /* o */
+ /* 112 */ ED_INSERT, /* p */
+ /* 113 */ ED_INSERT, /* q */
+ /* 114 */ ED_INSERT, /* r */
+ /* 115 */ ED_INSERT, /* s */
+ /* 116 */ ED_INSERT, /* t */
+ /* 117 */ ED_INSERT, /* u */
+ /* 118 */ ED_INSERT, /* v */
+ /* 119 */ ED_INSERT, /* w */
+ /* 120 */ ED_INSERT, /* x */
+ /* 121 */ ED_INSERT, /* y */
+ /* 122 */ ED_INSERT, /* z */
+ /* 123 */ ED_INSERT, /* { */
+ /* 124 */ ED_INSERT, /* | */
+ /* 125 */ ED_INSERT, /* } */
+ /* 126 */ ED_INSERT, /* ~ */
+ /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
+ /* 128 */ ED_UNASSIGNED, /* M-^@ */
+ /* 129 */ ED_UNASSIGNED, /* M-^A */
+ /* 130 */ ED_UNASSIGNED, /* M-^B */
+ /* 131 */ ED_UNASSIGNED, /* M-^C */
+ /* 132 */ ED_UNASSIGNED, /* M-^D */
+ /* 133 */ ED_UNASSIGNED, /* M-^E */
+ /* 134 */ ED_UNASSIGNED, /* M-^F */
+ /* 135 */ ED_UNASSIGNED, /* M-^G */
+ /* 136 */ ED_UNASSIGNED, /* M-^H */
+ /* 137 */ ED_UNASSIGNED, /* M-^I */
+ /* 138 */ ED_UNASSIGNED, /* M-^J */
+ /* 139 */ ED_UNASSIGNED, /* M-^K */
+ /* 140 */ ED_UNASSIGNED, /* M-^L */
+ /* 141 */ ED_UNASSIGNED, /* M-^M */
+ /* 142 */ ED_UNASSIGNED, /* M-^N */
+ /* 143 */ ED_UNASSIGNED, /* M-^O */
+ /* 144 */ ED_UNASSIGNED, /* M-^P */
+ /* 145 */ ED_UNASSIGNED, /* M-^Q */
+ /* 146 */ ED_UNASSIGNED, /* M-^R */
+ /* 147 */ ED_UNASSIGNED, /* M-^S */
+ /* 148 */ ED_UNASSIGNED, /* M-^T */
+ /* 149 */ ED_UNASSIGNED, /* M-^U */
+ /* 150 */ ED_UNASSIGNED, /* M-^V */
+ /* 151 */ ED_UNASSIGNED, /* M-^W */
+ /* 152 */ ED_UNASSIGNED, /* M-^X */
+ /* 153 */ ED_UNASSIGNED, /* M-^Y */
+ /* 154 */ ED_UNASSIGNED, /* M-^Z */
+ /* 155 */ ED_UNASSIGNED, /* M-^[ */
+ /* 156 */ ED_UNASSIGNED, /* M-^\ */
+ /* 157 */ ED_UNASSIGNED, /* M-^] */
+ /* 158 */ ED_UNASSIGNED, /* M-^^ */
+ /* 159 */ ED_UNASSIGNED, /* M-^_ */
+ /* 160 */ ED_UNASSIGNED, /* M-SPACE */
+ /* 161 */ ED_UNASSIGNED, /* M-! */
+ /* 162 */ ED_UNASSIGNED, /* M-" */
+ /* 163 */ ED_UNASSIGNED, /* M-# */
+ /* 164 */ ED_UNASSIGNED, /* M-$ */
+ /* 165 */ ED_UNASSIGNED, /* M-% */
+ /* 166 */ ED_UNASSIGNED, /* M-& */
+ /* 167 */ ED_UNASSIGNED, /* M-' */
+ /* 168 */ ED_UNASSIGNED, /* M-( */
+ /* 169 */ ED_UNASSIGNED, /* M-) */
+ /* 170 */ ED_UNASSIGNED, /* M-* */
+ /* 171 */ ED_UNASSIGNED, /* M-+ */
+ /* 172 */ ED_UNASSIGNED, /* M-, */
+ /* 173 */ ED_UNASSIGNED, /* M-- */
+ /* 174 */ ED_UNASSIGNED, /* M-. */
+ /* 175 */ ED_UNASSIGNED, /* M-/ */
+ /* 176 */ ED_UNASSIGNED, /* M-0 */
+ /* 177 */ ED_UNASSIGNED, /* M-1 */
+ /* 178 */ ED_UNASSIGNED, /* M-2 */
+ /* 179 */ ED_UNASSIGNED, /* M-3 */
+ /* 180 */ ED_UNASSIGNED, /* M-4 */
+ /* 181 */ ED_UNASSIGNED, /* M-5 */
+ /* 182 */ ED_UNASSIGNED, /* M-6 */
+ /* 183 */ ED_UNASSIGNED, /* M-7 */
+ /* 184 */ ED_UNASSIGNED, /* M-8 */
+ /* 185 */ ED_UNASSIGNED, /* M-9 */
+ /* 186 */ ED_UNASSIGNED, /* M-: */
+ /* 187 */ ED_UNASSIGNED, /* M-; */
+ /* 188 */ ED_UNASSIGNED, /* M-< */
+ /* 189 */ ED_UNASSIGNED, /* M-= */
+ /* 190 */ ED_UNASSIGNED, /* M-> */
+ /* 191 */ ED_UNASSIGNED, /* M-? */
+ /* 192 */ ED_UNASSIGNED, /* M-@ */
+ /* 193 */ ED_UNASSIGNED, /* M-A */
+ /* 194 */ ED_UNASSIGNED, /* M-B */
+ /* 195 */ ED_UNASSIGNED, /* M-C */
+ /* 196 */ ED_UNASSIGNED, /* M-D */
+ /* 197 */ ED_UNASSIGNED, /* M-E */
+ /* 198 */ ED_UNASSIGNED, /* M-F */
+ /* 199 */ ED_UNASSIGNED, /* M-G */
+ /* 200 */ ED_UNASSIGNED, /* M-H */
+ /* 201 */ ED_UNASSIGNED, /* M-I */
+ /* 202 */ ED_UNASSIGNED, /* M-J */
+ /* 203 */ ED_UNASSIGNED, /* M-K */
+ /* 204 */ ED_UNASSIGNED, /* M-L */
+ /* 205 */ ED_UNASSIGNED, /* M-M */
+ /* 206 */ ED_UNASSIGNED, /* M-N */
+ /* 207 */ ED_UNASSIGNED, /* M-O */
+ /* 208 */ ED_UNASSIGNED, /* M-P */
+ /* 209 */ ED_UNASSIGNED, /* M-Q */
+ /* 210 */ ED_UNASSIGNED, /* M-R */
+ /* 211 */ ED_UNASSIGNED, /* M-S */
+ /* 212 */ ED_UNASSIGNED, /* M-T */
+ /* 213 */ ED_UNASSIGNED, /* M-U */
+ /* 214 */ ED_UNASSIGNED, /* M-V */
+ /* 215 */ ED_UNASSIGNED, /* M-W */
+ /* 216 */ ED_UNASSIGNED, /* M-X */
+ /* 217 */ ED_UNASSIGNED, /* M-Y */
+ /* 218 */ ED_UNASSIGNED, /* M-Z */
+ /* 219 */ ED_UNASSIGNED, /* M-[ */
+ /* 220 */ ED_UNASSIGNED, /* M-\ */
+ /* 221 */ ED_UNASSIGNED, /* M-] */
+ /* 222 */ ED_UNASSIGNED, /* M-^ */
+ /* 223 */ ED_UNASSIGNED, /* M-_ */
+ /* 224 */ ED_UNASSIGNED, /* M-` */
+ /* 225 */ ED_UNASSIGNED, /* M-a */
+ /* 226 */ ED_UNASSIGNED, /* M-b */
+ /* 227 */ ED_UNASSIGNED, /* M-c */
+ /* 228 */ ED_UNASSIGNED, /* M-d */
+ /* 229 */ ED_UNASSIGNED, /* M-e */
+ /* 230 */ ED_UNASSIGNED, /* M-f */
+ /* 231 */ ED_UNASSIGNED, /* M-g */
+ /* 232 */ ED_UNASSIGNED, /* M-h */
+ /* 233 */ ED_UNASSIGNED, /* M-i */
+ /* 234 */ ED_UNASSIGNED, /* M-j */
+ /* 235 */ ED_UNASSIGNED, /* M-k */
+ /* 236 */ ED_UNASSIGNED, /* M-l */
+ /* 237 */ ED_UNASSIGNED, /* M-m */
+ /* 238 */ ED_UNASSIGNED, /* M-n */
+ /* 239 */ ED_UNASSIGNED, /* M-o */
+ /* 240 */ ED_UNASSIGNED, /* M-p */
+ /* 241 */ ED_UNASSIGNED, /* M-q */
+ /* 242 */ ED_UNASSIGNED, /* M-r */
+ /* 243 */ ED_UNASSIGNED, /* M-s */
+ /* 244 */ ED_UNASSIGNED, /* M-t */
+ /* 245 */ ED_UNASSIGNED, /* M-u */
+ /* 246 */ ED_UNASSIGNED, /* M-v */
+ /* 247 */ ED_UNASSIGNED, /* M-w */
+ /* 248 */ ED_UNASSIGNED, /* M-x */
+ /* 249 */ ED_UNASSIGNED, /* M-y */
+ /* 250 */ ED_UNASSIGNED, /* M-z */
+ /* 251 */ ED_UNASSIGNED, /* M-{ */
+ /* 252 */ ED_UNASSIGNED, /* M-| */
+ /* 253 */ ED_UNASSIGNED, /* M-} */
+ /* 254 */ ED_UNASSIGNED, /* M-~ */
+ /* 255 */ ED_UNASSIGNED /* M-^? */
+};
+
+private const el_action_t el_map_vi_command[] = {
+ /* 0 */ ED_UNASSIGNED, /* ^@ */
+ /* 1 */ ED_MOVE_TO_BEG, /* ^A */
+ /* 2 */ ED_UNASSIGNED, /* ^B */
+ /* 3 */ ED_TTY_SIGINT, /* ^C */
+ /* 4 */ ED_UNASSIGNED, /* ^D */
+ /* 5 */ ED_MOVE_TO_END, /* ^E */
+ /* 6 */ ED_UNASSIGNED, /* ^F */
+ /* 7 */ ED_UNASSIGNED, /* ^G */
+ /* 8 */ ED_PREV_CHAR, /* ^H */
+ /* 9 */ ED_UNASSIGNED, /* ^I */
+ /* 10 */ ED_NEWLINE, /* ^J */
+ /* 11 */ ED_KILL_LINE, /* ^K */
+ /* 12 */ ED_CLEAR_SCREEN, /* ^L */
+ /* 13 */ ED_NEWLINE, /* ^M */
+ /* 14 */ ED_NEXT_HISTORY, /* ^N */
+ /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
+ /* 16 */ ED_PREV_HISTORY, /* ^P */
+ /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
+ /* 18 */ ED_REDISPLAY, /* ^R */
+ /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
+ /* 20 */ ED_UNASSIGNED, /* ^T */
+ /* 21 */ VI_KILL_LINE_PREV, /* ^U */
+ /* 22 */ ED_UNASSIGNED, /* ^V */
+ /* 23 */ ED_DELETE_PREV_WORD, /* ^W */
+ /* 24 */ ED_UNASSIGNED, /* ^X */
+ /* 25 */ ED_UNASSIGNED, /* ^Y */
+ /* 26 */ ED_UNASSIGNED, /* ^Z */
+ /* 27 */ EM_META_NEXT, /* ^[ */
+ /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
+ /* 29 */ ED_UNASSIGNED, /* ^] */
+ /* 30 */ ED_UNASSIGNED, /* ^^ */
+ /* 31 */ ED_UNASSIGNED, /* ^_ */
+ /* 32 */ ED_NEXT_CHAR, /* SPACE */
+ /* 33 */ ED_UNASSIGNED, /* ! */
+ /* 34 */ ED_UNASSIGNED, /* " */
+ /* 35 */ ED_UNASSIGNED, /* # */
+ /* 36 */ ED_MOVE_TO_END, /* $ */
+ /* 37 */ ED_UNASSIGNED, /* % */
+ /* 38 */ ED_UNASSIGNED, /* & */
+ /* 39 */ ED_UNASSIGNED, /* ' */
+ /* 40 */ ED_UNASSIGNED, /* ( */
+ /* 41 */ ED_UNASSIGNED, /* ) */
+ /* 42 */ ED_UNASSIGNED, /* * */
+ /* 43 */ ED_NEXT_HISTORY, /* + */
+ /* 44 */ VI_REPEAT_PREV_CHAR, /* , */
+ /* 45 */ ED_PREV_HISTORY, /* - */
+ /* 46 */ ED_UNASSIGNED, /* . */
+ /* 47 */ VI_SEARCH_PREV, /* / */
+ /* 48 */ VI_ZERO, /* 0 */
+ /* 49 */ ED_ARGUMENT_DIGIT, /* 1 */
+ /* 50 */ ED_ARGUMENT_DIGIT, /* 2 */
+ /* 51 */ ED_ARGUMENT_DIGIT, /* 3 */
+ /* 52 */ ED_ARGUMENT_DIGIT, /* 4 */
+ /* 53 */ ED_ARGUMENT_DIGIT, /* 5 */
+ /* 54 */ ED_ARGUMENT_DIGIT, /* 6 */
+ /* 55 */ ED_ARGUMENT_DIGIT, /* 7 */
+ /* 56 */ ED_ARGUMENT_DIGIT, /* 8 */
+ /* 57 */ ED_ARGUMENT_DIGIT, /* 9 */
+ /* 58 */ ED_COMMAND, /* : */
+ /* 59 */ VI_REPEAT_NEXT_CHAR, /* ; */
+ /* 60 */ ED_UNASSIGNED, /* < */
+ /* 61 */ ED_UNASSIGNED, /* = */
+ /* 62 */ ED_UNASSIGNED, /* > */
+ /* 63 */ VI_SEARCH_NEXT, /* ? */
+ /* 64 */ ED_UNASSIGNED, /* @ */
+ /* 65 */ VI_ADD_AT_EOL, /* A */
+ /* 66 */ VI_PREV_SPACE_WORD, /* B */
+ /* 67 */ VI_CHANGE_TO_EOL, /* C */
+ /* 68 */ ED_KILL_LINE, /* D */
+ /* 69 */ VI_TO_END_WORD, /* E */
+ /* 70 */ VI_PREV_CHAR, /* F */
+ /* 71 */ ED_UNASSIGNED, /* G */
+ /* 72 */ ED_UNASSIGNED, /* H */
+ /* 73 */ VI_INSERT_AT_BOL, /* I */
+ /* 74 */ ED_SEARCH_NEXT_HISTORY, /* J */
+ /* 75 */ ED_SEARCH_PREV_HISTORY, /* K */
+ /* 76 */ ED_UNASSIGNED, /* L */
+ /* 77 */ ED_UNASSIGNED, /* M */
+ /* 78 */ VI_REPEAT_SEARCH_PREV, /* N */
+ /* 79 */ ED_SEQUENCE_LEAD_IN, /* O */
+ /* 80 */ VI_PASTE_PREV, /* P */
+ /* 81 */ ED_UNASSIGNED, /* Q */
+ /* 82 */ VI_REPLACE_MODE, /* R */
+ /* 83 */ VI_SUBSTITUTE_LINE, /* S */
+ /* 84 */ VI_TO_PREV_CHAR, /* T */
+ /* 85 */ ED_UNASSIGNED, /* U */
+ /* 86 */ ED_UNASSIGNED, /* V */
+ /* 87 */ VI_NEXT_SPACE_WORD, /* W */
+ /* 88 */ ED_DELETE_PREV_CHAR, /* X */
+ /* 89 */ ED_UNASSIGNED, /* Y */
+ /* 90 */ ED_UNASSIGNED, /* Z */
+ /* 91 */ ED_SEQUENCE_LEAD_IN, /* [ */
+ /* 92 */ ED_UNASSIGNED, /* \ */
+ /* 93 */ ED_UNASSIGNED, /* ] */
+ /* 94 */ ED_MOVE_TO_BEG, /* ^ */
+ /* 95 */ ED_UNASSIGNED, /* _ */
+ /* 96 */ ED_UNASSIGNED, /* ` */
+ /* 97 */ VI_ADD, /* a */
+ /* 98 */ VI_PREV_WORD, /* b */
+ /* 99 */ VI_CHANGE_META, /* c */
+ /* 100 */ VI_DELETE_META, /* d */
+ /* 101 */ VI_END_WORD, /* e */
+ /* 102 */ VI_NEXT_CHAR, /* f */
+ /* 103 */ ED_UNASSIGNED, /* g */
+ /* 104 */ ED_PREV_CHAR, /* h */
+ /* 105 */ VI_INSERT, /* i */
+ /* 106 */ ED_NEXT_HISTORY, /* j */
+ /* 107 */ ED_PREV_HISTORY, /* k */
+ /* 108 */ ED_NEXT_CHAR, /* l */
+ /* 109 */ ED_UNASSIGNED, /* m */
+ /* 110 */ VI_REPEAT_SEARCH_NEXT, /* n */
+ /* 111 */ ED_UNASSIGNED, /* o */
+ /* 112 */ VI_PASTE_NEXT, /* p */
+ /* 113 */ ED_UNASSIGNED, /* q */
+ /* 114 */ VI_REPLACE_CHAR, /* r */
+ /* 115 */ VI_SUBSTITUTE_CHAR, /* s */
+ /* 116 */ VI_TO_NEXT_CHAR, /* t */
+ /* 117 */ VI_UNDO, /* u */
+ /* 118 */ ED_UNASSIGNED, /* v */
+ /* 119 */ VI_NEXT_WORD, /* w */
+ /* 120 */ ED_DELETE_NEXT_CHAR, /* x */
+ /* 121 */ ED_UNASSIGNED, /* y */
+ /* 122 */ ED_UNASSIGNED, /* z */
+ /* 123 */ ED_UNASSIGNED, /* { */
+ /* 124 */ ED_UNASSIGNED, /* | */
+ /* 125 */ ED_UNASSIGNED, /* } */
+ /* 126 */ VI_CHANGE_CASE, /* ~ */
+ /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
+ /* 128 */ ED_UNASSIGNED, /* M-^@ */
+ /* 129 */ ED_UNASSIGNED, /* M-^A */
+ /* 130 */ ED_UNASSIGNED, /* M-^B */
+ /* 131 */ ED_UNASSIGNED, /* M-^C */
+ /* 132 */ ED_UNASSIGNED, /* M-^D */
+ /* 133 */ ED_UNASSIGNED, /* M-^E */
+ /* 134 */ ED_UNASSIGNED, /* M-^F */
+ /* 135 */ ED_UNASSIGNED, /* M-^G */
+ /* 136 */ ED_UNASSIGNED, /* M-^H */
+ /* 137 */ ED_UNASSIGNED, /* M-^I */
+ /* 138 */ ED_UNASSIGNED, /* M-^J */
+ /* 139 */ ED_UNASSIGNED, /* M-^K */
+ /* 140 */ ED_UNASSIGNED, /* M-^L */
+ /* 141 */ ED_UNASSIGNED, /* M-^M */
+ /* 142 */ ED_UNASSIGNED, /* M-^N */
+ /* 143 */ ED_UNASSIGNED, /* M-^O */
+ /* 144 */ ED_UNASSIGNED, /* M-^P */
+ /* 145 */ ED_UNASSIGNED, /* M-^Q */
+ /* 146 */ ED_UNASSIGNED, /* M-^R */
+ /* 147 */ ED_UNASSIGNED, /* M-^S */
+ /* 148 */ ED_UNASSIGNED, /* M-^T */
+ /* 149 */ ED_UNASSIGNED, /* M-^U */
+ /* 150 */ ED_UNASSIGNED, /* M-^V */
+ /* 151 */ ED_UNASSIGNED, /* M-^W */
+ /* 152 */ ED_UNASSIGNED, /* M-^X */
+ /* 153 */ ED_UNASSIGNED, /* M-^Y */
+ /* 154 */ ED_UNASSIGNED, /* M-^Z */
+ /* 155 */ ED_UNASSIGNED, /* M-^[ */
+ /* 156 */ ED_UNASSIGNED, /* M-^\ */
+ /* 157 */ ED_UNASSIGNED, /* M-^] */
+ /* 158 */ ED_UNASSIGNED, /* M-^^ */
+ /* 159 */ ED_UNASSIGNED, /* M-^_ */
+ /* 160 */ ED_UNASSIGNED, /* M-SPACE */
+ /* 161 */ ED_UNASSIGNED, /* M-! */
+ /* 162 */ ED_UNASSIGNED, /* M-" */
+ /* 163 */ ED_UNASSIGNED, /* M-# */
+ /* 164 */ ED_UNASSIGNED, /* M-$ */
+ /* 165 */ ED_UNASSIGNED, /* M-% */
+ /* 166 */ ED_UNASSIGNED, /* M-& */
+ /* 167 */ ED_UNASSIGNED, /* M-' */
+ /* 168 */ ED_UNASSIGNED, /* M-( */
+ /* 169 */ ED_UNASSIGNED, /* M-) */
+ /* 170 */ ED_UNASSIGNED, /* M-* */
+ /* 171 */ ED_UNASSIGNED, /* M-+ */
+ /* 172 */ ED_UNASSIGNED, /* M-, */
+ /* 173 */ ED_UNASSIGNED, /* M-- */
+ /* 174 */ ED_UNASSIGNED, /* M-. */
+ /* 175 */ ED_UNASSIGNED, /* M-/ */
+ /* 176 */ ED_UNASSIGNED, /* M-0 */
+ /* 177 */ ED_UNASSIGNED, /* M-1 */
+ /* 178 */ ED_UNASSIGNED, /* M-2 */
+ /* 179 */ ED_UNASSIGNED, /* M-3 */
+ /* 180 */ ED_UNASSIGNED, /* M-4 */
+ /* 181 */ ED_UNASSIGNED, /* M-5 */
+ /* 182 */ ED_UNASSIGNED, /* M-6 */
+ /* 183 */ ED_UNASSIGNED, /* M-7 */
+ /* 184 */ ED_UNASSIGNED, /* M-8 */
+ /* 185 */ ED_UNASSIGNED, /* M-9 */
+ /* 186 */ ED_UNASSIGNED, /* M-: */
+ /* 187 */ ED_UNASSIGNED, /* M-; */
+ /* 188 */ ED_UNASSIGNED, /* M-< */
+ /* 189 */ ED_UNASSIGNED, /* M-= */
+ /* 190 */ ED_UNASSIGNED, /* M-> */
+ /* 191 */ ED_UNASSIGNED, /* M-? */
+ /* 192 */ ED_UNASSIGNED, /* M-@ */
+ /* 193 */ ED_UNASSIGNED, /* M-A */
+ /* 194 */ ED_UNASSIGNED, /* M-B */
+ /* 195 */ ED_UNASSIGNED, /* M-C */
+ /* 196 */ ED_UNASSIGNED, /* M-D */
+ /* 197 */ ED_UNASSIGNED, /* M-E */
+ /* 198 */ ED_UNASSIGNED, /* M-F */
+ /* 199 */ ED_UNASSIGNED, /* M-G */
+ /* 200 */ ED_UNASSIGNED, /* M-H */
+ /* 201 */ ED_UNASSIGNED, /* M-I */
+ /* 202 */ ED_UNASSIGNED, /* M-J */
+ /* 203 */ ED_UNASSIGNED, /* M-K */
+ /* 204 */ ED_UNASSIGNED, /* M-L */
+ /* 205 */ ED_UNASSIGNED, /* M-M */
+ /* 206 */ ED_UNASSIGNED, /* M-N */
+ /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */
+ /* 208 */ ED_UNASSIGNED, /* M-P */
+ /* 209 */ ED_UNASSIGNED, /* M-Q */
+ /* 210 */ ED_UNASSIGNED, /* M-R */
+ /* 211 */ ED_UNASSIGNED, /* M-S */
+ /* 212 */ ED_UNASSIGNED, /* M-T */
+ /* 213 */ ED_UNASSIGNED, /* M-U */
+ /* 214 */ ED_UNASSIGNED, /* M-V */
+ /* 215 */ ED_UNASSIGNED, /* M-W */
+ /* 216 */ ED_UNASSIGNED, /* M-X */
+ /* 217 */ ED_UNASSIGNED, /* M-Y */
+ /* 218 */ ED_UNASSIGNED, /* M-Z */
+ /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */
+ /* 220 */ ED_UNASSIGNED, /* M-\ */
+ /* 221 */ ED_UNASSIGNED, /* M-] */
+ /* 222 */ ED_UNASSIGNED, /* M-^ */
+ /* 223 */ ED_UNASSIGNED, /* M-_ */
+ /* 224 */ ED_UNASSIGNED, /* M-` */
+ /* 225 */ ED_UNASSIGNED, /* M-a */
+ /* 226 */ ED_UNASSIGNED, /* M-b */
+ /* 227 */ ED_UNASSIGNED, /* M-c */
+ /* 228 */ ED_UNASSIGNED, /* M-d */
+ /* 229 */ ED_UNASSIGNED, /* M-e */
+ /* 230 */ ED_UNASSIGNED, /* M-f */
+ /* 231 */ ED_UNASSIGNED, /* M-g */
+ /* 232 */ ED_UNASSIGNED, /* M-h */
+ /* 233 */ ED_UNASSIGNED, /* M-i */
+ /* 234 */ ED_UNASSIGNED, /* M-j */
+ /* 235 */ ED_UNASSIGNED, /* M-k */
+ /* 236 */ ED_UNASSIGNED, /* M-l */
+ /* 237 */ ED_UNASSIGNED, /* M-m */
+ /* 238 */ ED_UNASSIGNED, /* M-n */
+ /* 239 */ ED_UNASSIGNED, /* M-o */
+ /* 240 */ ED_UNASSIGNED, /* M-p */
+ /* 241 */ ED_UNASSIGNED, /* M-q */
+ /* 242 */ ED_UNASSIGNED, /* M-r */
+ /* 243 */ ED_UNASSIGNED, /* M-s */
+ /* 244 */ ED_UNASSIGNED, /* M-t */
+ /* 245 */ ED_UNASSIGNED, /* M-u */
+ /* 246 */ ED_UNASSIGNED, /* M-v */
+ /* 247 */ ED_UNASSIGNED, /* M-w */
+ /* 248 */ ED_UNASSIGNED, /* M-x */
+ /* 249 */ ED_UNASSIGNED, /* M-y */
+ /* 250 */ ED_UNASSIGNED, /* M-z */
+ /* 251 */ ED_UNASSIGNED, /* M-{ */
+ /* 252 */ ED_UNASSIGNED, /* M-| */
+ /* 253 */ ED_UNASSIGNED, /* M-} */
+ /* 254 */ ED_UNASSIGNED, /* M-~ */
+ /* 255 */ ED_UNASSIGNED /* M-^? */
+};
+
+
+/* map_init():
+ * Initialize and allocate the maps
+ */
+protected int
+map_init(EditLine *el)
+{
+
+ /*
+ * Make sure those are correct before starting.
+ */
+#ifdef MAP_DEBUG
+ if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t))
+ EL_ABORT((el->errfile, "Emacs map incorrect\n"));
+ if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t))
+ EL_ABORT((el->errfile, "Vi command map incorrect\n"));
+ if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t))
+ EL_ABORT((el->errfile, "Vi insert map incorrect\n"));
+#endif
+
+ el->el_map.alt = (el_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS);
+ if (el->el_map.alt == NULL)
+ return (-1);
+ el->el_map.key = (el_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS);
+ if (el->el_map.key == NULL)
+ return (-1);
+ el->el_map.emacs = el_map_emacs;
+ el->el_map.vic = el_map_vi_command;
+ el->el_map.vii = el_map_vi_insert;
+ el->el_map.help = (el_bindings_t *) el_malloc(sizeof(el_bindings_t) *
+ EL_NUM_FCNS);
+ if (el->el_map.help == NULL)
+ return (-1);
+ (void) memcpy(el->el_map.help, help__get(),
+ sizeof(el_bindings_t) * EL_NUM_FCNS);
+ el->el_map.func = (el_func_t *)el_malloc(sizeof(el_func_t) *
+ EL_NUM_FCNS);
+ if (el->el_map.func == NULL)
+ return (-1);
+ memcpy(el->el_map.func, func__get(), sizeof(el_func_t) * EL_NUM_FCNS);
+ el->el_map.nfunc = EL_NUM_FCNS;
+
+#ifdef VIDEFAULT
+ map_init_vi(el);
+#else
+ map_init_emacs(el);
+#endif /* VIDEFAULT */
+ return (0);
+}
+
+
+/* map_end():
+ * Free the space taken by the editor maps
+ */
+protected void
+map_end(EditLine *el)
+{
+
+ el_free((ptr_t) el->el_map.alt);
+ el->el_map.alt = NULL;
+ el_free((ptr_t) el->el_map.key);
+ el->el_map.key = NULL;
+ el->el_map.emacs = NULL;
+ el->el_map.vic = NULL;
+ el->el_map.vii = NULL;
+ el_free((ptr_t) el->el_map.help);
+ el->el_map.help = NULL;
+ el_free((ptr_t) el->el_map.func);
+ el->el_map.func = NULL;
+}
+
+
+/* map_init_nls():
+ * Find all the printable keys and bind them to self insert
+ */
+private void
+map_init_nls(EditLine *el)
+{
+ int i;
+
+ el_action_t *map = el->el_map.key;
+
+ for (i = 0200; i <= 0377; i++)
+ if (isprint(i))
+ map[i] = ED_INSERT;
+}
+
+
+/* map_init_meta():
+ * Bind all the meta keys to the appropriate ESC-<key> sequence
+ */
+private void
+map_init_meta(EditLine *el)
+{
+ char buf[3];
+ int i;
+ el_action_t *map = el->el_map.key;
+ el_action_t *alt = el->el_map.alt;
+
+ for (i = 0; i <= 0377 && map[i] != EM_META_NEXT; i++)
+ continue;
+
+ if (i > 0377) {
+ for (i = 0; i <= 0377 && alt[i] != EM_META_NEXT; i++)
+ continue;
+ if (i > 0377) {
+ i = 033;
+ if (el->el_map.type == MAP_VI)
+ map = alt;
+ } else
+ map = alt;
+ }
+ buf[0] = (char) i;
+ buf[2] = 0;
+ for (i = 0200; i <= 0377; i++)
+ switch (map[i]) {
+ case ED_INSERT:
+ case ED_UNASSIGNED:
+ case ED_SEQUENCE_LEAD_IN:
+ break;
+ default:
+ buf[1] = i & 0177;
+ key_add(el, buf, key_map_cmd(el, (int) map[i]), XK_CMD);
+ break;
+ }
+ map[(int) buf[0]] = ED_SEQUENCE_LEAD_IN;
+}
+
+
+/* map_init_vi():
+ * Initialize the vi bindings
+ */
+protected void
+map_init_vi(EditLine *el)
+{
+ int i;
+ el_action_t *key = el->el_map.key;
+ el_action_t *alt = el->el_map.alt;
+ const el_action_t *vii = el->el_map.vii;
+ const el_action_t *vic = el->el_map.vic;
+
+ el->el_map.type = MAP_VI;
+ el->el_map.current = el->el_map.key;
+
+ key_reset(el);
+
+ for (i = 0; i < N_KEYS; i++) {
+ key[i] = vii[i];
+ alt[i] = vic[i];
+ }
+
+ map_init_meta(el);
+ map_init_nls(el);
+
+ tty_bind_char(el, 1);
+ term_bind_arrow(el);
+}
+
+
+/* map_init_emacs():
+ * Initialize the emacs bindings
+ */
+protected void
+map_init_emacs(EditLine *el)
+{
+ int i;
+ char buf[3];
+ el_action_t *key = el->el_map.key;
+ el_action_t *alt = el->el_map.alt;
+ const el_action_t *emacs = el->el_map.emacs;
+
+ el->el_map.type = MAP_EMACS;
+ el->el_map.current = el->el_map.key;
+ key_reset(el);
+
+ for (i = 0; i < N_KEYS; i++) {
+ key[i] = emacs[i];
+ alt[i] = ED_UNASSIGNED;
+ }
+
+ map_init_meta(el);
+ map_init_nls(el);
+
+ buf[0] = CONTROL('X');
+ buf[1] = CONTROL('X');
+ buf[2] = 0;
+ key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD);
+
+ tty_bind_char(el, 1);
+ term_bind_arrow(el);
+}
+
+
+/* map_set_editor():
+ * Set the editor
+ */
+protected int
+map_set_editor(EditLine *el, char *editor)
+{
+
+ if (strcmp(editor, "emacs") == 0) {
+ map_init_emacs(el);
+ return (0);
+ }
+ if (strcmp(editor, "vi") == 0) {
+ map_init_vi(el);
+ return (0);
+ }
+ return (-1);
+}
+
+
+/* map_get_editor():
+ * Retrieve the editor
+ */
+protected int
+map_get_editor(EditLine *el, const char **editor)
+{
+
+ if (editor == NULL)
+ return (-1);
+ switch (el->el_map.type) {
+ case MAP_EMACS:
+ *editor = "emacs";
+ return (0);
+ case MAP_VI:
+ *editor = "vi";
+ return (0);
+ }
+ return (-1);
+}
+
+
+/* map_print_key():
+ * Print the function description for 1 key
+ */
+private void
+map_print_key(EditLine *el, el_action_t *map, const char *in)
+{
+ char outbuf[EL_BUFSIZ];
+ el_bindings_t *bp;
+
+ if (in[0] == '\0' || in[1] == '\0') {
+ (void) key__decode_str(in, outbuf, "");
+ for (bp = el->el_map.help; bp->name != NULL; bp++)
+ if (bp->func == map[(unsigned char) *in]) {
+ (void) fprintf(el->el_outfile,
+ "%s\t->\t%s\n", outbuf, bp->name);
+ return;
+ }
+ } else
+ key_print(el, in);
+}
+
+
+/* map_print_some_keys():
+ * Print keys from first to last
+ */
+private void
+map_print_some_keys(EditLine *el, el_action_t *map, int first, int last)
+{
+ el_bindings_t *bp;
+ char firstbuf[2], lastbuf[2];
+ char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ];
+
+ firstbuf[0] = first;
+ firstbuf[1] = 0;
+ lastbuf[0] = last;
+ lastbuf[1] = 0;
+ if (map[first] == ED_UNASSIGNED) {
+ if (first == last)
+ (void) fprintf(el->el_outfile,
+ "%-15s-> is undefined\n",
+ key__decode_str(firstbuf, unparsbuf, STRQQ));
+ return;
+ }
+ for (bp = el->el_map.help; bp->name != NULL; bp++) {
+ if (bp->func == map[first]) {
+ if (first == last) {
+ (void) fprintf(el->el_outfile, "%-15s-> %s\n",
+ key__decode_str(firstbuf, unparsbuf, STRQQ),
+ bp->name);
+ } else {
+ (void) fprintf(el->el_outfile,
+ "%-4s to %-7s-> %s\n",
+ key__decode_str(firstbuf, unparsbuf, STRQQ),
+ key__decode_str(lastbuf, extrabuf, STRQQ),
+ bp->name);
+ }
+ return;
+ }
+ }
+#ifdef MAP_DEBUG
+ if (map == el->el_map.key) {
+ (void) fprintf(el->el_outfile,
+ "BUG!!! %s isn't bound to anything.\n",
+ key__decode_str(firstbuf, unparsbuf, STRQQ));
+ (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n",
+ first, el->el_map.key[first]);
+ } else {
+ (void) fprintf(el->el_outfile,
+ "BUG!!! %s isn't bound to anything.\n",
+ key__decode_str(firstbuf, unparsbuf, STRQQ));
+ (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n",
+ first, el->el_map.alt[first]);
+ }
+#endif
+ EL_ABORT((el->el_errfile, "Error printing keys\n"));
+}
+
+
+/* map_print_all_keys():
+ * Print the function description for all keys.
+ */
+private void
+map_print_all_keys(EditLine *el)
+{
+ int prev, i;
+
+ (void) fprintf(el->el_outfile, "Standard key bindings\n");
+ prev = 0;
+ for (i = 0; i < N_KEYS; i++) {
+ if (el->el_map.key[prev] == el->el_map.key[i])
+ continue;
+ map_print_some_keys(el, el->el_map.key, prev, i - 1);
+ prev = i;
+ }
+ map_print_some_keys(el, el->el_map.key, prev, i - 1);
+
+ (void) fprintf(el->el_outfile, "Alternative key bindings\n");
+ prev = 0;
+ for (i = 0; i < N_KEYS; i++) {
+ if (el->el_map.alt[prev] == el->el_map.alt[i])
+ continue;
+ map_print_some_keys(el, el->el_map.alt, prev, i - 1);
+ prev = i;
+ }
+ map_print_some_keys(el, el->el_map.alt, prev, i - 1);
+
+ (void) fprintf(el->el_outfile, "Multi-character bindings\n");
+ key_print(el, "");
+ (void) fprintf(el->el_outfile, "Arrow key bindings\n");
+ term_print_arrow(el, "");
+}
+
+
+/* map_bind():
+ * Add/remove/change bindings
+ */
+protected int
+map_bind(EditLine *el, int argc, const char **argv)
+{
+ el_action_t *map;
+ int ntype, rem;
+ const char *p;
+ char inbuf[EL_BUFSIZ];
+ char outbuf[EL_BUFSIZ];
+ const char *in = NULL;
+ char *out = NULL;
+ el_bindings_t *bp;
+ int cmd;
+ int key;
+
+ if (argv == NULL)
+ return (-1);
+
+ map = el->el_map.key;
+ ntype = XK_CMD;
+ key = rem = 0;
+ for (argc = 1; (p = argv[argc]) != NULL; argc++)
+ if (p[0] == '-')
+ switch (p[1]) {
+ case 'a':
+ map = el->el_map.alt;
+ break;
+
+ case 's':
+ ntype = XK_STR;
+ break;
+#ifdef notyet
+ case 'c':
+ ntype = XK_EXE;
+ break;
+#endif
+ case 'k':
+ key = 1;
+ break;
+
+ case 'r':
+ rem = 1;
+ break;
+
+ case 'v':
+ map_init_vi(el);
+ return (0);
+
+ case 'e':
+ map_init_emacs(el);
+ return (0);
+
+ case 'l':
+ for (bp = el->el_map.help; bp->name != NULL;
+ bp++)
+ (void) fprintf(el->el_outfile,
+ "%s\n\t%s\n",
+ bp->name, bp->description);
+ return (0);
+ default:
+ (void) fprintf(el->el_errfile,
+ "%s: Invalid switch `%c'.\n",
+ argv[0], p[1]);
+ }
+ else
+ break;
+
+ if (argv[argc] == NULL) {
+ map_print_all_keys(el);
+ return (0);
+ }
+ if (key)
+ in = argv[argc++];
+ else if ((in = parse__string(inbuf, argv[argc++])) == NULL) {
+ (void) fprintf(el->el_errfile,
+ "%s: Invalid \\ or ^ in instring.\n",
+ argv[0]);
+ return (-1);
+ }
+ if (rem) {
+ if (key) {
+ (void) term_clear_arrow(el, in);
+ return (-1);
+ }
+ if (in[1])
+ (void) key_delete(el, in);
+ else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN)
+ (void) key_delete(el, in);
+ else
+ map[(unsigned char) *in] = ED_UNASSIGNED;
+ return (0);
+ }
+ if (argv[argc] == NULL) {
+ if (key)
+ term_print_arrow(el, in);
+ else
+ map_print_key(el, map, in);
+ return (0);
+ }
+#ifdef notyet
+ if (argv[argc + 1] != NULL) {
+ bindkey_usage();
+ return (-1);
+ }
+#endif
+
+ switch (ntype) {
+ case XK_STR:
+ case XK_EXE:
+ if ((out = parse__string(outbuf, argv[argc])) == NULL) {
+ (void) fprintf(el->el_errfile,
+ "%s: Invalid \\ or ^ in outstring.\n", argv[0]);
+ return (-1);
+ }
+ if (key)
+ term_set_arrow(el, in, key_map_str(el, out), ntype);
+ else
+ key_add(el, in, key_map_str(el, out), ntype);
+ map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
+ break;
+
+ case XK_CMD:
+ if ((cmd = parse_cmd(el, argv[argc])) == -1) {
+ (void) fprintf(el->el_errfile,
+ "%s: Invalid command `%s'.\n", argv[0], argv[argc]);
+ return (-1);
+ }
+ if (key)
+ term_set_arrow(el, in, key_map_str(el, out), ntype);
+ else {
+ if (in[1]) {
+ key_add(el, in, key_map_cmd(el, cmd), ntype);
+ map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
+ } else {
+ key_clear(el, map, in);
+ map[(unsigned char) *in] = cmd;
+ }
+ }
+ break;
+
+ default:
+ EL_ABORT((el->el_errfile, "Bad XK_ type\n", ntype));
+ break;
+ }
+ return (0);
+}
+
+
+/* map_addfunc():
+ * add a user defined function
+ */
+protected int
+map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func)
+{
+ void *p;
+ int nf = el->el_map.nfunc + 2;
+
+ if (name == NULL || help == NULL || func == NULL)
+ return (-1);
+
+ if ((p = el_realloc(el->el_map.func, nf * sizeof(el_func_t))) == NULL)
+ return (-1);
+ el->el_map.func = (el_func_t *) p;
+ if ((p = el_realloc(el->el_map.help, nf * sizeof(el_bindings_t)))
+ == NULL)
+ return (-1);
+ el->el_map.help = (el_bindings_t *) p;
+
+ nf = el->el_map.nfunc;
+ el->el_map.func[nf] = func;
+
+ el->el_map.help[nf].name = name;
+ el->el_map.help[nf].func = nf;
+ el->el_map.help[nf].description = help;
+ el->el_map.help[++nf].name = NULL;
+ el->el_map.nfunc++;
+
+ return (0);
+}
diff --git a/cmd-line-utils/libedit/map.h b/cmd-line-utils/libedit/map.h
new file mode 100644
index 00000000000..6033eaf1a87
--- /dev/null
+++ b/cmd-line-utils/libedit/map.h
@@ -0,0 +1,79 @@
+/* $NetBSD: map.h,v 1.6 2001/01/09 17:22:09 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)map.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.map.h: Editor maps
+ */
+#ifndef _h_el_map
+#define _h_el_map
+
+typedef struct el_bindings_t { /* for the "bind" shell command */
+ const char *name; /* function name for bind command */
+ int func; /* function numeric value */
+ const char *description; /* description of function */
+} el_bindings_t;
+
+
+typedef struct el_map_t {
+ el_action_t *alt; /* The current alternate key map */
+ el_action_t *key; /* The current normal key map */
+ el_action_t *current; /* The keymap we are using */
+ const el_action_t *emacs; /* The default emacs key map */
+ const el_action_t *vic; /* The vi command mode key map */
+ const el_action_t *vii; /* The vi insert mode key map */
+ int type; /* Emacs or vi */
+ el_bindings_t *help; /* The help for the editor functions */
+ el_func_t *func; /* List of available functions */
+ int nfunc; /* The number of functions/help items */
+} el_map_t;
+
+#define MAP_EMACS 0
+#define MAP_VI 1
+
+protected int map_bind(EditLine *, int, const char **);
+protected int map_init(EditLine *);
+protected void map_end(EditLine *);
+protected void map_init_vi(EditLine *);
+protected void map_init_emacs(EditLine *);
+protected int map_set_editor(EditLine *, char *);
+protected int map_get_editor(EditLine *, const char **);
+protected int map_addfunc(EditLine *, const char *, const char *, el_func_t);
+
+#endif /* _h_el_map */
diff --git a/cmd-line-utils/libedit/parse.c b/cmd-line-utils/libedit/parse.c
new file mode 100644
index 00000000000..b6d077793af
--- /dev/null
+++ b/cmd-line-utils/libedit/parse.c
@@ -0,0 +1,253 @@
+/* $NetBSD: parse.c,v 1.14 2001/01/23 15:55:30 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * parse.c: parse an editline extended command
+ *
+ * commands are:
+ *
+ * bind
+ * echotc
+ * edit
+ * gettc
+ * history
+ * settc
+ * setty
+ */
+#include "sys.h"
+#include "el.h"
+#include "tokenizer.h"
+#include <stdlib.h>
+
+private const struct {
+ const char *name;
+ int (*func)(EditLine *, int, const char **);
+} cmds[] = {
+ { "bind", map_bind },
+ { "echotc", term_echotc },
+ { "edit", el_editmode },
+ { "history", hist_list },
+ { "telltc", term_telltc },
+ { "settc", term_settc },
+ { "setty", tty_stty },
+ { NULL, NULL }
+};
+
+
+/* parse_line():
+ * Parse a line and dispatch it
+ */
+protected int
+parse_line(EditLine *el, const char *line)
+{
+ const char **argv;
+ int argc;
+ Tokenizer *tok;
+
+ tok = tok_init(NULL);
+ tok_line(tok, line, &argc, &argv);
+ argc = el_parse(el, argc, argv);
+ tok_end(tok);
+ return (argc);
+}
+
+
+/* el_parse():
+ * Command dispatcher
+ */
+public int
+el_parse(EditLine *el, int argc, const char *argv[])
+{
+ const char *ptr;
+ int i;
+
+ if (argc < 1)
+ return (-1);
+ ptr = strchr(argv[0], ':');
+ if (ptr != NULL) {
+ char *tprog;
+ size_t l;
+
+ if (ptr == argv[0])
+ return (0);
+ l = ptr - argv[0] - 1;
+ tprog = (char *) el_malloc(l + 1);
+ if (tprog == NULL)
+ return (0);
+ (void) strncpy(tprog, argv[0], l);
+ tprog[l] = '\0';
+ ptr++;
+ l = el_match(el->el_prog, tprog);
+ el_free(tprog);
+ if (!l)
+ return (0);
+ } else
+ ptr = argv[0];
+
+ for (i = 0; cmds[i].name != NULL; i++)
+ if (strcmp(cmds[i].name, ptr) == 0) {
+ i = (*cmds[i].func) (el, argc, argv);
+ return (-i);
+ }
+ return (-1);
+}
+
+
+/* parse__escape():
+ * Parse a string of the form ^<char> \<odigit> \<char> and return
+ * the appropriate character or -1 if the escape is not valid
+ */
+protected int
+parse__escape(const char **const ptr)
+{
+ const char *p;
+ int c;
+
+ p = *ptr;
+
+ if (p[1] == 0)
+ return (-1);
+
+ if (*p == '\\') {
+ p++;
+ switch (*p) {
+ case 'a':
+ c = '\007'; /* Bell */
+ break;
+ case 'b':
+ c = '\010'; /* Backspace */
+ break;
+ case 't':
+ c = '\011'; /* Horizontal Tab */
+ break;
+ case 'n':
+ c = '\012'; /* New Line */
+ break;
+ case 'v':
+ c = '\013'; /* Vertical Tab */
+ break;
+ case 'f':
+ c = '\014'; /* Form Feed */
+ break;
+ case 'r':
+ c = '\015'; /* Carriage Return */
+ break;
+ case 'e':
+ c = '\033'; /* Escape */
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ int cnt, ch;
+
+ for (cnt = 0, c = 0; cnt < 3; cnt++) {
+ ch = *p++;
+ if (ch < '0' || ch > '7') {
+ p--;
+ break;
+ }
+ c = (c << 3) | (ch - '0');
+ }
+ if ((c & 0xffffff00) != 0)
+ return (-1);
+ --p;
+ break;
+ }
+ default:
+ c = *p;
+ break;
+ }
+ } else if (*p == '^' && isalpha((unsigned char) p[1])) {
+ p++;
+ c = (*p == '?') ? '\177' : (*p & 0237);
+ } else
+ c = *p;
+ *ptr = ++p;
+ return (c);
+}
+/* parse__string():
+ * Parse the escapes from in and put the raw string out
+ */
+protected char *
+parse__string(char *out, const char *in)
+{
+ char *rv = out;
+ int n;
+
+ for (;;)
+ switch (*in) {
+ case '\0':
+ *out = '\0';
+ return (rv);
+
+ case '\\':
+ case '^':
+ if ((n = parse__escape(&in)) == -1)
+ return (NULL);
+ *out++ = n;
+ break;
+
+ default:
+ *out++ = *in++;
+ break;
+ }
+}
+
+
+/* parse_cmd():
+ * Return the command number for the command string given
+ * or -1 if one is not found
+ */
+protected int
+parse_cmd(EditLine *el, const char *cmd)
+{
+ el_bindings_t *b;
+
+ for (b = el->el_map.help; b->name != NULL; b++)
+ if (strcmp(b->name, cmd) == 0)
+ return (b->func);
+ return (-1);
+}
diff --git a/cmd-line-utils/libedit/parse.h b/cmd-line-utils/libedit/parse.h
new file mode 100644
index 00000000000..4aaef2f834a
--- /dev/null
+++ b/cmd-line-utils/libedit/parse.h
@@ -0,0 +1,52 @@
+/* $NetBSD: parse.h,v 1.4 2000/09/04 22:06:31 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)parse.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.parse.h: Parser functions
+ */
+#ifndef _h_el_parse
+#define _h_el_parse
+
+protected int parse_line(EditLine *, const char *);
+protected int parse__escape(const char ** const);
+protected char *parse__string(char *, const char *);
+protected int parse_cmd(EditLine *, const char *);
+
+#endif /* _h_el_parse */
diff --git a/cmd-line-utils/libedit/prompt.c b/cmd-line-utils/libedit/prompt.c
new file mode 100644
index 00000000000..fb7d9d35936
--- /dev/null
+++ b/cmd-line-utils/libedit/prompt.c
@@ -0,0 +1,168 @@
+/* $NetBSD: prompt.c,v 1.8 2001/01/10 07:45:41 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * prompt.c: Prompt printing functions
+ */
+#include "sys.h"
+#include <stdio.h>
+#include "el.h"
+
+private char *prompt_default(EditLine *);
+private char *prompt_default_r(EditLine *);
+
+/* prompt_default():
+ * Just a default prompt, in case the user did not provide one
+ */
+private char *
+/*ARGSUSED*/
+prompt_default(EditLine *el __attribute__((unused)))
+{
+ static char a[3] = {'?', ' ', '\0'};
+
+ return (a);
+}
+
+
+/* prompt_default_r():
+ * Just a default rprompt, in case the user did not provide one
+ */
+private char *
+/*ARGSUSED*/
+prompt_default_r(EditLine *el __attribute__((unused)))
+{
+ static char a[1] = {'\0'};
+
+ return (a);
+}
+
+
+/* prompt_print():
+ * Print the prompt and update the prompt position.
+ * We use an array of integers in case we want to pass
+ * literal escape sequences in the prompt and we want a
+ * bit to flag them
+ */
+protected void
+prompt_print(EditLine *el, int op)
+{
+ el_prompt_t *elp;
+ char *p;
+
+ if (op == EL_PROMPT)
+ elp = &el->el_prompt;
+ else
+ elp = &el->el_rprompt;
+ p = (elp->p_func) (el);
+ while (*p)
+ re_putc(el, *p++, 1);
+
+ elp->p_pos.v = el->el_refresh.r_cursor.v;
+ elp->p_pos.h = el->el_refresh.r_cursor.h;
+}
+
+
+/* prompt_init():
+ * Initialize the prompt stuff
+ */
+protected int
+prompt_init(EditLine *el)
+{
+
+ el->el_prompt.p_func = prompt_default;
+ el->el_prompt.p_pos.v = 0;
+ el->el_prompt.p_pos.h = 0;
+ el->el_rprompt.p_func = prompt_default_r;
+ el->el_rprompt.p_pos.v = 0;
+ el->el_rprompt.p_pos.h = 0;
+ return (0);
+}
+
+
+/* prompt_end():
+ * Clean up the prompt stuff
+ */
+protected void
+/*ARGSUSED*/
+prompt_end(EditLine *el __attribute__((unused)))
+{
+}
+
+
+/* prompt_set():
+ * Install a prompt printing function
+ */
+protected int
+prompt_set(EditLine *el, el_pfunc_t prf, int op)
+{
+ el_prompt_t *p;
+
+ if (op == EL_PROMPT)
+ p = &el->el_prompt;
+ else
+ p = &el->el_rprompt;
+ if (prf == NULL) {
+ if (op == EL_PROMPT)
+ p->p_func = prompt_default;
+ else
+ p->p_func = prompt_default_r;
+ } else
+ p->p_func = prf;
+ p->p_pos.v = 0;
+ p->p_pos.h = 0;
+ return (0);
+}
+
+
+/* prompt_get():
+ * Retrieve the prompt printing function
+ */
+protected int
+prompt_get(EditLine *el, el_pfunc_t *prf, int op)
+{
+
+ if (prf == NULL)
+ return (-1);
+ if (op == EL_PROMPT)
+ *prf = el->el_prompt.p_func;
+ else
+ *prf = el->el_rprompt.p_func;
+ return (0);
+}
diff --git a/cmd-line-utils/libedit/prompt.h b/cmd-line-utils/libedit/prompt.h
new file mode 100644
index 00000000000..08810e22a0c
--- /dev/null
+++ b/cmd-line-utils/libedit/prompt.h
@@ -0,0 +1,62 @@
+/* $NetBSD: prompt.h,v 1.5 2000/09/04 22:06:31 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)prompt.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.prompt.h: Prompt printing stuff
+ */
+#ifndef _h_el_prompt
+#define _h_el_prompt
+
+#include "histedit.h"
+
+typedef char * (*el_pfunc_t)(EditLine*);
+
+typedef struct el_prompt_t {
+ el_pfunc_t p_func; /* Function to return the prompt */
+ coord_t p_pos; /* position in the line after prompt */
+} el_prompt_t;
+
+protected void prompt_print(EditLine *, int);
+protected int prompt_set(EditLine *, el_pfunc_t, int);
+protected int prompt_get(EditLine *, el_pfunc_t *, int);
+protected int prompt_init(EditLine *);
+protected void prompt_end(EditLine *);
+
+#endif /* _h_el_prompt */
diff --git a/cmd-line-utils/libedit/read.c b/cmd-line-utils/libedit/read.c
new file mode 100644
index 00000000000..05f9e3da454
--- /dev/null
+++ b/cmd-line-utils/libedit/read.c
@@ -0,0 +1,514 @@
+/* $NetBSD: read.c,v 1.19 2001/01/10 07:45:41 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * read.c: Clean this junk up! This is horrible code.
+ * Terminal read functions
+ */
+#include "sys.h"
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "el.h"
+
+#define OKCMD -1
+
+private int read__fixio(int, int);
+private int read_preread(EditLine *);
+private int read_getcmd(EditLine *, el_action_t *, char *);
+private int read_char(EditLine *, char *);
+
+#ifdef DEBUG_EDIT
+private void
+read_debug(EditLine *el)
+{
+
+ if (el->el_line.cursor > el->el_line.lastchar)
+ (void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
+ if (el->el_line.cursor < el->el_line.buffer)
+ (void) fprintf(el->el_errfile, "cursor < buffer\r\n");
+ if (el->el_line.cursor > el->el_line.limit)
+ (void) fprintf(el->el_errfile, "cursor > limit\r\n");
+ if (el->el_line.lastchar > el->el_line.limit)
+ (void) fprintf(el->el_errfile, "lastchar > limit\r\n");
+ if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
+ (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
+}
+#endif /* DEBUG_EDIT */
+
+
+/* read__fixio():
+ * Try to recover from a read error
+ */
+/* ARGSUSED */
+private int
+read__fixio(int fd __attribute__((unused)), int e)
+{
+
+ switch (e) {
+ case -1: /* Make sure that the code is reachable */
+
+#ifdef EWOULDBLOCK
+ case EWOULDBLOCK:
+#ifndef TRY_AGAIN
+#define TRY_AGAIN
+#endif
+#endif /* EWOULDBLOCK */
+
+#if defined(POSIX) && defined(EAGAIN)
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EAGAIN:
+#ifndef TRY_AGAIN
+#define TRY_AGAIN
+#endif
+#endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
+#endif /* POSIX && EAGAIN */
+
+ e = 0;
+#ifdef TRY_AGAIN
+#if defined(F_SETFL) && defined(O_NDELAY)
+ if ((e = fcntl(fd, F_GETFL, 0)) == -1)
+ return (-1);
+
+ if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
+ return (-1);
+ else
+ e = 1;
+#endif /* F_SETFL && O_NDELAY */
+
+#ifdef FIONBIO
+ {
+ int zero = 0;
+
+ if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1)
+ return (-1);
+ else
+ e = 1;
+ }
+#endif /* FIONBIO */
+
+#endif /* TRY_AGAIN */
+ return (e ? 0 : -1);
+
+ case EINTR:
+ return (0);
+
+ default:
+ return (-1);
+ }
+}
+
+
+/* read_preread():
+ * Try to read the stuff in the input queue;
+ */
+private int
+read_preread(EditLine *el)
+{
+ int chrs = 0;
+
+ if (el->el_chared.c_macro.nline) {
+ el_free((ptr_t) el->el_chared.c_macro.nline);
+ el->el_chared.c_macro.nline = NULL;
+ }
+ if (el->el_tty.t_mode == ED_IO)
+ return (0);
+
+#ifdef FIONREAD
+ (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
+ if (chrs > 0) {
+ char buf[EL_BUFSIZ];
+
+ chrs = read(el->el_infd, buf,
+ (size_t) MIN(chrs, EL_BUFSIZ - 1));
+ if (chrs > 0) {
+ buf[chrs] = '\0';
+ el->el_chared.c_macro.nline = strdup(buf);
+ el_push(el, el->el_chared.c_macro.nline);
+ }
+ }
+#endif /* FIONREAD */
+
+ return (chrs > 0);
+}
+
+
+/* el_push():
+ * Push a macro
+ */
+public void
+el_push(EditLine *el, const char *str)
+{
+ c_macro_t *ma = &el->el_chared.c_macro;
+
+ if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
+ ma->level++;
+ /* LINTED const cast */
+ ma->macro[ma->level] = (char *) str;
+ } else {
+ term_beep(el);
+ term__flush();
+ }
+}
+
+
+/* read_getcmd():
+ * Return next command from the input stream.
+ */
+private int
+read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
+{
+ el_action_t cmd = ED_UNASSIGNED;
+ int num;
+
+ while (cmd == ED_UNASSIGNED || cmd == ED_SEQUENCE_LEAD_IN) {
+ if ((num = el_getc(el, ch)) != 1) /* if EOF or error */
+ return (num);
+
+#ifdef KANJI
+ if ((*ch & 0200)) {
+ el->el_state.metanext = 0;
+ cmd = CcViMap[' '];
+ break;
+ } else
+#endif /* KANJI */
+
+ if (el->el_state.metanext) {
+ el->el_state.metanext = 0;
+ *ch |= 0200;
+ }
+ cmd = el->el_map.current[(unsigned char) *ch];
+ if (cmd == ED_SEQUENCE_LEAD_IN) {
+ key_value_t val;
+ switch (key_get(el, ch, &val)) {
+ case XK_CMD:
+ cmd = val.cmd;
+ break;
+ case XK_STR:
+ el_push(el, val.str);
+ break;
+#ifdef notyet
+ case XK_EXE:
+ /* XXX: In the future to run a user function */
+ RunCommand(val.str);
+ break;
+#endif
+ default:
+ EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
+ break;
+ }
+ }
+ if (el->el_map.alt == NULL)
+ el->el_map.current = el->el_map.key;
+ }
+ *cmdnum = cmd;
+ return (OKCMD);
+}
+
+
+/* read_char():
+ * Read a character from the tty.
+ */
+private int
+read_char(EditLine *el, char *cp)
+{
+ int num_read;
+ int tried = 0;
+
+ while ((num_read = read(el->el_infd, cp, 1)) == -1)
+ if (!tried && read__fixio(el->el_infd, errno) == 0)
+ tried = 1;
+ else {
+ *cp = '\0';
+ return (-1);
+ }
+
+ return (num_read);
+}
+
+
+/* el_getc():
+ * Read a character
+ */
+public int
+el_getc(EditLine *el, char *cp)
+{
+ int num_read;
+ c_macro_t *ma = &el->el_chared.c_macro;
+
+ term__flush();
+ for (;;) {
+ if (ma->level < 0) {
+ if (!read_preread(el))
+ break;
+ }
+ if (ma->level < 0)
+ break;
+
+ if (*ma->macro[ma->level] == 0) {
+ ma->level--;
+ continue;
+ }
+ *cp = *ma->macro[ma->level]++ & 0377;
+ if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode
+ * On */
+ ma->level--;
+ }
+ return (1);
+ }
+
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile, "Turning raw mode on\n");
+#endif /* DEBUG_READ */
+ if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
+ return (0);
+
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile, "Reading a character\n");
+#endif /* DEBUG_READ */
+ num_read = read_char(el, cp);
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile, "Got it %c\n", *cp);
+#endif /* DEBUG_READ */
+ return (num_read);
+}
+
+
+public const char *
+el_gets(EditLine *el, int *nread)
+{
+ int retval;
+ el_action_t cmdnum = 0;
+ int num; /* how many chars we have read at NL */
+ char ch;
+#ifdef FIONREAD
+ c_macro_t *ma = &el->el_chared.c_macro;
+#endif /* FIONREAD */
+
+ if (el->el_flags & HANDLE_SIGNALS)
+ sig_set(el);
+
+ if (el->el_flags & NO_TTY) {
+ char *cp = el->el_line.buffer;
+ size_t idx;
+
+ while (read_char(el, cp) == 1) {
+ /* make sure there is space for next character */
+ if (cp + 1 >= el->el_line.limit) {
+ idx = (cp - el->el_line.buffer);
+ if (!ch_enlargebufs(el, 2))
+ break;
+ cp = &el->el_line.buffer[idx];
+ }
+ cp++;
+ if (cp[-1] == '\r' || cp[-1] == '\n')
+ break;
+ }
+
+ el->el_line.cursor = el->el_line.lastchar = cp;
+ *cp = '\0';
+ if (nread)
+ *nread = el->el_line.cursor - el->el_line.buffer;
+ return (el->el_line.buffer);
+ }
+ re_clear_display(el); /* reset the display stuff */
+ ch_reset(el);
+
+#ifdef FIONREAD
+ if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
+ long chrs = 0;
+
+ (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
+ if (chrs == 0) {
+ if (tty_rawmode(el) < 0) {
+ if (nread)
+ *nread = 0;
+ return (NULL);
+ }
+ }
+ }
+#endif /* FIONREAD */
+
+ re_refresh(el); /* print the prompt */
+
+ if (el->el_flags & EDIT_DISABLED) {
+ char *cp = el->el_line.buffer;
+ size_t idx;
+
+ term__flush();
+
+ while (read_char(el, cp) == 1) {
+ /* make sure there is space next character */
+ if (cp + 1 >= el->el_line.limit) {
+ idx = (cp - el->el_line.buffer);
+ if (!ch_enlargebufs(el, 2))
+ break;
+ cp = &el->el_line.buffer[idx];
+ }
+ cp++;
+ if (cp[-1] == '\r' || cp[-1] == '\n')
+ break;
+ }
+
+ el->el_line.cursor = el->el_line.lastchar = cp;
+ *cp = '\0';
+ if (nread)
+ *nread = el->el_line.cursor - el->el_line.buffer;
+ return (el->el_line.buffer);
+ }
+ for (num = OKCMD; num == OKCMD;) { /* while still editing this
+ * line */
+#ifdef DEBUG_EDIT
+ read_debug(el);
+#endif /* DEBUG_EDIT */
+ /* if EOF or error */
+ if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile,
+ "Returning from el_gets %d\n", num);
+#endif /* DEBUG_READ */
+ break;
+ }
+ if ((int) cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile,
+ "ERROR: illegal command from key 0%o\r\n", ch);
+#endif /* DEBUG_EDIT */
+ continue; /* try again */
+ }
+ /* now do the real command */
+#ifdef DEBUG_READ
+ {
+ el_bindings_t *b;
+ for (b = el->el_map.help; b->name; b++)
+ if (b->func == cmdnum)
+ break;
+ if (b->name)
+ (void) fprintf(el->el_errfile,
+ "Executing %s\n", b->name);
+ else
+ (void) fprintf(el->el_errfile,
+ "Error command = %d\n", cmdnum);
+ }
+#endif /* DEBUG_READ */
+ retval = (*el->el_map.func[cmdnum]) (el, ch);
+
+ /* save the last command here */
+ el->el_state.lastcmd = cmdnum;
+
+ /* use any return value */
+ switch (retval) {
+ case CC_CURSOR:
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ re_refresh_cursor(el);
+ break;
+
+ case CC_REDISPLAY:
+ re_clear_lines(el);
+ re_clear_display(el);
+ /* FALLTHROUGH */
+
+ case CC_REFRESH:
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ re_refresh(el);
+ break;
+
+ case CC_REFRESH_BEEP:
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ re_refresh(el);
+ term_beep(el);
+ break;
+
+ case CC_NORM: /* normal char */
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ break;
+
+ case CC_ARGHACK: /* Suggested by Rich Salz */
+ /* <rsalz@pineapple.bbn.com> */
+ break; /* keep going... */
+
+ case CC_EOF: /* end of file typed */
+ num = 0;
+ break;
+
+ case CC_NEWLINE: /* normal end of line */
+ num = el->el_line.lastchar - el->el_line.buffer;
+ break;
+
+ case CC_FATAL: /* fatal error, reset to known state */
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile,
+ "*** editor fatal ERROR ***\r\n\n");
+#endif /* DEBUG_READ */
+ /* put (real) cursor in a known place */
+ re_clear_display(el); /* reset the display stuff */
+ ch_reset(el); /* reset the input pointers */
+ re_refresh(el); /* print the prompt again */
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ break;
+
+ case CC_ERROR:
+ default: /* functions we don't know about */
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile,
+ "*** editor ERROR ***\r\n\n");
+#endif /* DEBUG_READ */
+ el->el_state.argument = 1;
+ el->el_state.doingarg = 0;
+ term_beep(el);
+ term__flush();
+ break;
+ }
+ }
+
+ /* make sure the tty is set up correctly */
+ (void) tty_cookedmode(el);
+ term__flush(); /* flush any buffered output */
+ if (el->el_flags & HANDLE_SIGNALS)
+ sig_clr(el);
+ if (nread)
+ *nread = num;
+ return (num ? el->el_line.buffer : NULL);
+}
diff --git a/cmd-line-utils/libedit/readline.c b/cmd-line-utils/libedit/readline.c
new file mode 100644
index 00000000000..e9c8409102c
--- /dev/null
+++ b/cmd-line-utils/libedit/readline.c
@@ -0,0 +1,1661 @@
+/* $NetBSD: readline.c,v 1.19 2001/01/10 08:10:45 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "compat.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include "histedit.h"
+#include "readline/readline.h"
+#include "sys.h"
+#include "el.h"
+#include "fcns.h" /* for EL_NUM_FCNS */
+
+/* for rl_complete() */
+#define TAB '\r'
+
+/* see comment at the #ifdef for sense of this */
+#define GDB_411_HACK
+
+/* readline compatibility stuff - look at readline sources/documentation */
+/* to see what these variables mean */
+const char *rl_library_version = "EditLine wrapper";
+const char *rl_readline_name = "";
+FILE *rl_instream = NULL;
+FILE *rl_outstream = NULL;
+int rl_point = 0;
+int rl_end = 0;
+char *rl_line_buffer = NULL;
+
+int history_base = 1; /* probably never subject to change */
+int history_length = 0;
+int max_input_history = 0;
+char history_expansion_char = '!';
+char history_subst_char = '^';
+const char *history_no_expand_chars = " \t\n=(";
+Function *history_inhibit_expansion_function = NULL;
+
+int rl_inhibit_completion = 0;
+int rl_attempted_completion_over = 0;
+const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
+char *rl_completer_word_break_characters = NULL;
+char *rl_completer_quote_characters = NULL;
+CPFunction *rl_completion_entry_function = NULL;
+CPPFunction *rl_attempted_completion_function = NULL;
+
+/*
+ * This is set to character indicating type of completion being done by
+ * rl_complete_internal(); this is available for application completion
+ * functions.
+ */
+int rl_completion_type = 0;
+
+/*
+ * If more than this number of items results from query for possible
+ * completions, we ask user if they are sure to really display the list.
+ */
+int rl_completion_query_items = 100;
+
+/*
+ * List of characters which are word break characters, but should be left
+ * in the parsed text when it is passed to the completion function.
+ * Shell uses this to help determine what kind of completing to do.
+ */
+char *rl_special_prefixes = (char *)NULL;
+
+/*
+ * This is the character appended to the completed words if at the end of
+ * the line. Default is ' ' (a space).
+ */
+int rl_completion_append_character = ' ';
+
+/* stuff below is used internally by libedit for readline emulation */
+
+/* if not zero, non-unique completions always show list of possible matches */
+static int _rl_complete_show_all = 0;
+
+static History *h = NULL;
+static EditLine *e = NULL;
+static int el_rl_complete_cmdnum = 0;
+
+/* internal functions */
+static unsigned char _el_rl_complete(EditLine *, int);
+static char *_get_prompt(EditLine *);
+static HIST_ENTRY *_move_history(int);
+static int _history_search_gen(const char *, int, int);
+static int _history_expand_command(const char *, size_t, char **);
+static char *_rl_compat_sub(const char *, const char *,
+ const char *, int);
+static int rl_complete_internal(int);
+static int _rl_qsort_string_compare(const void *, const void *);
+
+/*
+ * needed for prompt switching in readline()
+ */
+static char *el_rl_prompt = NULL;
+
+
+/* ARGSUSED */
+static char *
+_get_prompt(EditLine *el __attribute__((unused)))
+{
+ return (el_rl_prompt);
+}
+
+
+/*
+ * generic function for moving around history
+ */
+static HIST_ENTRY *
+_move_history(int op)
+{
+ HistEvent ev;
+ static HIST_ENTRY rl_he;
+
+ if (history(h, &ev, op) != 0)
+ return (HIST_ENTRY *) NULL;
+
+ rl_he.line = ev.str;
+ rl_he.data = "";
+
+ return (&rl_he);
+}
+
+
+/*
+ * READLINE compatibility stuff
+ */
+
+/*
+ * initialize rl compat stuff
+ */
+int
+rl_initialize(void)
+{
+ HistEvent ev;
+ const LineInfo *li;
+ int i;
+ int editmode = 1;
+ struct termios t;
+
+ if (e != NULL)
+ el_end(e);
+ if (h != NULL)
+ history_end(h);
+
+ if (!rl_instream)
+ rl_instream = stdin;
+ if (!rl_outstream)
+ rl_outstream = stdout;
+
+ /*
+ * See if we don't really want to run the editor
+ */
+ if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
+ editmode = 0;
+
+ e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
+
+ if (!editmode)
+ el_set(e, EL_EDITMODE, 0);
+
+ h = history_init();
+ if (!e || !h)
+ return (-1);
+
+ history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
+ history_length = 0;
+ max_input_history = INT_MAX;
+ el_set(e, EL_HIST, history, h);
+
+ /* for proper prompt printing in readline() */
+ el_rl_prompt = strdup("");
+ el_set(e, EL_PROMPT, _get_prompt);
+ el_set(e, EL_SIGNAL, 1);
+
+ /* set default mode to "emacs"-style and read setting afterwards */
+ /* so this can be overriden */
+ el_set(e, EL_EDITOR, "emacs");
+
+ /*
+ * Word completition - this has to go AFTER rebinding keys
+ * to emacs-style.
+ */
+ el_set(e, EL_ADDFN, "rl_complete",
+ "ReadLine compatible completition function",
+ _el_rl_complete);
+ el_set(e, EL_BIND, "^I", "rl_complete", NULL);
+
+ /*
+ * Find out where the rl_complete function was added; this is
+ * used later to detect that lastcmd was also rl_complete.
+ */
+ for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {
+ if (e->el_map.func[i] == _el_rl_complete) {
+ el_rl_complete_cmdnum = i;
+ break;
+ }
+ }
+
+ /* read settings from configuration file */
+ el_source(e, NULL);
+
+ /*
+ * Unfortunately, some applications really do use rl_point
+ * and rl_line_buffer directly.
+ */
+ li = el_line(e);
+ /* LINTED const cast */
+ rl_line_buffer = (char *) li->buffer;
+ rl_point = rl_end = 0;
+
+ return (0);
+}
+
+
+/*
+ * read one line from input stream and return it, chomping
+ * trailing newline (if there is any)
+ */
+char *
+readline(const char *prompt)
+{
+ HistEvent ev;
+ int count;
+ const char *ret;
+
+ if (e == NULL || h == NULL)
+ rl_initialize();
+
+ /* update prompt accordingly to what has been passed */
+ if (!prompt)
+ prompt = "";
+ if (strcmp(el_rl_prompt, prompt) != 0) {
+ free(el_rl_prompt);
+ el_rl_prompt = strdup(prompt);
+ }
+ /* get one line from input stream */
+ ret = el_gets(e, &count);
+
+ if (ret && count > 0) {
+ char *foo;
+ int lastidx;
+
+ foo = strdup(ret);
+ lastidx = count - 1;
+ if (foo[lastidx] == '\n')
+ foo[lastidx] = '\0';
+
+ ret = foo;
+ } else
+ ret = NULL;
+
+ history(h, &ev, H_GETSIZE);
+ history_length = ev.num;
+
+ /* LINTED const cast */
+ return (char *) ret;
+}
+
+/*
+ * history functions
+ */
+
+/*
+ * is normally called before application starts to use
+ * history expansion functions
+ */
+void
+using_history(void)
+{
+ if (h == NULL || e == NULL)
+ rl_initialize();
+}
+
+
+/*
+ * substitute ``what'' with ``with'', returning resulting string; if
+ * globally == 1, substitutes all occurences of what, otherwise only the
+ * first one
+ */
+static char *
+_rl_compat_sub(const char *str, const char *what, const char *with,
+ int globally)
+{
+ char *result;
+ const char *temp, *new;
+ unsigned int len, with_len, what_len, add;
+ size_t size, i;
+
+ result = malloc((size = 16));
+ temp = str;
+ with_len = strlen(with);
+ what_len = strlen(what);
+ len = 0;
+ do {
+ new = strstr(temp, what);
+ if (new) {
+ i = new - temp;
+ add = i + with_len;
+ if (i + add + 1 >= size) {
+ size += add + 1;
+ result = realloc(result, size);
+ }
+ (void) strncpy(&result[len], temp, i);
+ len += i;
+ (void) strcpy(&result[len], with); /* safe */
+ len += with_len;
+ temp = new + what_len;
+ } else {
+ add = strlen(temp);
+ if (len + add + 1 >= size) {
+ size += add + 1;
+ result = realloc(result, size);
+ }
+ (void) strcpy(&result[len], temp); /* safe */
+ len += add;
+ temp = NULL;
+ }
+ } while (temp && globally);
+ result[len] = '\0';
+
+ return (result);
+}
+
+
+/*
+ * the real function doing history expansion - takes as argument command
+ * to do and data upon which the command should be executed
+ * does expansion the way I've understood readline documentation
+ * word designator ``%'' isn't supported (yet ?)
+ *
+ * returns 0 if data was not modified, 1 if it was and 2 if the string
+ * should be only printed and not executed; in case of error,
+ * returns -1 and *result points to NULL
+ * it's callers responsibility to free() string returned in *result
+ */
+static int
+_history_expand_command(const char *command, size_t cmdlen, char **result)
+{
+ char **arr, *tempcmd, *line, *search = NULL, *cmd;
+ const char *event_data = NULL;
+ static char *from = NULL, *to = NULL;
+ int start = -1, end = -1, max, i, idx;
+ int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0;
+ int event_num = 0, retval;
+ size_t cmdsize;
+
+ *result = NULL;
+
+ cmd = alloca(cmdlen + 1);
+ (void) strncpy(cmd, command, cmdlen);
+ cmd[cmdlen] = 0;
+
+ idx = 1;
+ /* find out which event to take */
+ if (cmd[idx] == history_expansion_char) {
+ event_num = history_length;
+ idx++;
+ } else {
+ int off, num;
+ size_t len;
+ off = idx;
+ while (cmd[off] && !strchr(":^$*-%", cmd[off]))
+ off++;
+ num = atoi(&cmd[idx]);
+ if (num != 0) {
+ event_num = num;
+ if (num < 0)
+ event_num += history_length + 1;
+ } else {
+ int prefix = 1, curr_num;
+ HistEvent ev;
+
+ len = off - idx;
+ if (cmd[idx] == '?') {
+ idx++, len--;
+ if (cmd[off - 1] == '?')
+ len--;
+ else if (cmd[off] != '\n' && cmd[off] != '\0')
+ return (-1);
+ prefix = 0;
+ }
+ search = alloca(len + 1);
+ (void) strncpy(search, &cmd[idx], len);
+ search[len] = '\0';
+
+ if (history(h, &ev, H_CURR) != 0)
+ return (-1);
+ curr_num = ev.num;
+
+ if (prefix)
+ retval = history_search_prefix(search, -1);
+ else
+ retval = history_search(search, -1);
+
+ if (retval == -1) {
+ fprintf(rl_outstream, "%s: Event not found\n",
+ search);
+ return (-1);
+ }
+ if (history(h, &ev, H_CURR) != 0)
+ return (-1);
+ event_data = ev.str;
+
+ /* roll back to original position */
+ history(h, &ev, H_NEXT_EVENT, curr_num);
+ }
+ idx = off;
+ }
+
+ if (!event_data && event_num >= 0) {
+ HIST_ENTRY *rl_he;
+ rl_he = history_get(event_num);
+ if (!rl_he)
+ return (0);
+ event_data = rl_he->line;
+ } else
+ return (-1);
+
+ if (cmd[idx] != ':')
+ return (-1);
+ cmd += idx + 1;
+
+ /* recognize cmd */
+ if (*cmd == '^')
+ start = end = 1, cmd++;
+ else if (*cmd == '$')
+ start = end = -1, cmd++;
+ else if (*cmd == '*')
+ start = 1, end = -1, cmd++;
+ else if (isdigit((unsigned char) *cmd)) {
+ const char *temp;
+ int shifted = 0;
+
+ start = atoi(cmd);
+ temp = cmd;
+ for (; isdigit((unsigned char) *cmd); cmd++);
+ if (temp != cmd)
+ shifted = 1;
+ if (shifted && *cmd == '-') {
+ if (!isdigit((unsigned char) *(cmd + 1)))
+ end = -2;
+ else {
+ end = atoi(cmd + 1);
+ for (; isdigit((unsigned char) *cmd); cmd++);
+ }
+ } else if (shifted && *cmd == '*')
+ end = -1, cmd++;
+ else if (shifted)
+ end = start;
+ }
+ if (*cmd == ':')
+ cmd++;
+
+ line = strdup(event_data);
+ for (; *cmd; cmd++) {
+ if (*cmd == ':')
+ continue;
+ else if (*cmd == 'h')
+ h_on = 1 | g_on, g_on = 0;
+ else if (*cmd == 't')
+ t_on = 1 | g_on, g_on = 0;
+ else if (*cmd == 'r')
+ r_on = 1 | g_on, g_on = 0;
+ else if (*cmd == 'e')
+ e_on = 1 | g_on, g_on = 0;
+ else if (*cmd == 'p')
+ p_on = 1 | g_on, g_on = 0;
+ else if (*cmd == 'g')
+ g_on = 2;
+ else if (*cmd == 's' || *cmd == '&') {
+ char *what, *with, delim;
+ size_t len, from_len;
+ size_t size;
+
+ if (*cmd == '&' && (from == NULL || to == NULL))
+ continue;
+ else if (*cmd == 's') {
+ delim = *(++cmd), cmd++;
+ size = 16;
+ what = realloc(from, size);
+ len = 0;
+ for (; *cmd && *cmd != delim; cmd++) {
+ if (*cmd == '\\'
+ && *(cmd + 1) == delim)
+ cmd++;
+ if (len >= size)
+ what = realloc(what,
+ (size <<= 1));
+ what[len++] = *cmd;
+ }
+ what[len] = '\0';
+ from = what;
+ if (*what == '\0') {
+ free(what);
+ if (search)
+ from = strdup(search);
+ else {
+ from = NULL;
+ return (-1);
+ }
+ }
+ cmd++; /* shift after delim */
+ if (!*cmd)
+ continue;
+
+ size = 16;
+ with = realloc(to, size);
+ len = 0;
+ from_len = strlen(from);
+ for (; *cmd && *cmd != delim; cmd++) {
+ if (len + from_len + 1 >= size) {
+ size += from_len + 1;
+ with = realloc(with, size);
+ }
+ if (*cmd == '&') {
+ /* safe */
+ (void) strcpy(&with[len], from);
+ len += from_len;
+ continue;
+ }
+ if (*cmd == '\\'
+ && (*(cmd + 1) == delim
+ || *(cmd + 1) == '&'))
+ cmd++;
+ with[len++] = *cmd;
+ }
+ with[len] = '\0';
+ to = with;
+
+ tempcmd = _rl_compat_sub(line, from, to,
+ (g_on) ? 1 : 0);
+ free(line);
+ line = tempcmd;
+ g_on = 0;
+ }
+ }
+ }
+
+ arr = history_tokenize(line);
+ free(line); /* no more needed */
+ if (arr && *arr == NULL)
+ free(arr), arr = NULL;
+ if (!arr)
+ return (-1);
+
+ /* find out max valid idx to array of array */
+ max = 0;
+ for (i = 0; arr[i]; i++)
+ max++;
+ max--;
+
+ /* set boundaries to something relevant */
+ if (start < 0)
+ start = 1;
+ if (end < 0)
+ end = max - ((end < -1) ? 1 : 0);
+
+ /* check boundaries ... */
+ if (start > max || end > max || start > end)
+ return (-1);
+
+ for (i = 0; i <= max; i++) {
+ char *temp;
+ if (h_on && (i == 1 || h_on > 1) &&
+ (temp = strrchr(arr[i], '/')))
+ *(temp + 1) = '\0';
+ if (t_on && (i == 1 || t_on > 1) &&
+ (temp = strrchr(arr[i], '/')))
+ (void) strcpy(arr[i], temp + 1);
+ if (r_on && (i == 1 || r_on > 1) &&
+ (temp = strrchr(arr[i], '.')))
+ *temp = '\0';
+ if (e_on && (i == 1 || e_on > 1) &&
+ (temp = strrchr(arr[i], '.')))
+ (void) strcpy(arr[i], temp);
+ }
+
+ cmdsize = 1, cmdlen = 0;
+ tempcmd = malloc(cmdsize);
+ for (i = start; start <= i && i <= end; i++) {
+ int arr_len;
+
+ arr_len = strlen(arr[i]);
+ if (cmdlen + arr_len + 1 >= cmdsize) {
+ cmdsize += arr_len + 1;
+ tempcmd = realloc(tempcmd, cmdsize);
+ }
+ (void) strcpy(&tempcmd[cmdlen], arr[i]); /* safe */
+ cmdlen += arr_len;
+ tempcmd[cmdlen++] = ' '; /* add a space */
+ }
+ while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1]))
+ cmdlen--;
+ tempcmd[cmdlen] = '\0';
+
+ *result = tempcmd;
+
+ for (i = 0; i <= max; i++)
+ free(arr[i]);
+ free(arr), arr = (char **) NULL;
+ return (p_on) ? 2 : 1;
+}
+
+
+/*
+ * csh-style history expansion
+ */
+int
+history_expand(char *str, char **output)
+{
+ int i, retval = 0, idx;
+ size_t size;
+ char *temp, *result;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ *output = strdup(str); /* do it early */
+
+ if (str[0] == history_subst_char) {
+ /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
+ temp = alloca(4 + strlen(str) + 1);
+ temp[0] = temp[1] = history_expansion_char;
+ temp[2] = ':';
+ temp[3] = 's';
+ (void) strcpy(temp + 4, str);
+ str = temp;
+ }
+#define ADD_STRING(what, len) \
+ { \
+ if (idx + len + 1 > size) \
+ result = realloc(result, (size += len + 1)); \
+ (void)strncpy(&result[idx], what, len); \
+ idx += len; \
+ result[idx] = '\0'; \
+ }
+
+ result = NULL;
+ size = idx = 0;
+ for (i = 0; str[i];) {
+ int start, j, loop_again;
+ size_t len;
+
+ loop_again = 1;
+ start = j = i;
+loop:
+ for (; str[j]; j++) {
+ if (str[j] == '\\' &&
+ str[j + 1] == history_expansion_char) {
+ (void) strcpy(&str[j], &str[j + 1]);
+ continue;
+ }
+ if (!loop_again) {
+ if (str[j] == '?') {
+ while (str[j] && str[++j] != '?');
+ if (str[j] == '?')
+ j++;
+ } else if (isspace((unsigned char) str[j]))
+ break;
+ }
+ if (str[j] == history_expansion_char
+ && !strchr(history_no_expand_chars, str[j + 1])
+ && (!history_inhibit_expansion_function ||
+ (*history_inhibit_expansion_function)(str, j) == 0))
+ break;
+ }
+
+ if (str[j] && str[j + 1] != '#' && loop_again) {
+ i = j;
+ j++;
+ if (str[j] == history_expansion_char)
+ j++;
+ loop_again = 0;
+ goto loop;
+ }
+ len = i - start;
+ temp = &str[start];
+ ADD_STRING(temp, len);
+
+ if (str[i] == '\0' || str[i] != history_expansion_char
+ || str[i + 1] == '#') {
+ len = j - i;
+ temp = &str[i];
+ ADD_STRING(temp, len);
+ if (start == 0)
+ retval = 0;
+ else
+ retval = 1;
+ break;
+ }
+ retval = _history_expand_command(&str[i], (size_t) (j - i),
+ &temp);
+ if (retval != -1) {
+ len = strlen(temp);
+ ADD_STRING(temp, len);
+ }
+ i = j;
+ } /* for(i ...) */
+
+ if (retval == 2) {
+ add_history(temp);
+#ifdef GDB_411_HACK
+ /* gdb 4.11 has been shipped with readline, where */
+ /* history_expand() returned -1 when the line */
+ /* should not be executed; in readline 2.1+ */
+ /* it should return 2 in such a case */
+ retval = -1;
+#endif
+ }
+ free(*output);
+ *output = result;
+
+ return (retval);
+}
+
+
+/*
+ * Parse the string into individual tokens, similarily to how shell would do it.
+ */
+char **
+history_tokenize(const char *str)
+{
+ int size = 1, result_idx = 0, i, start;
+ size_t len;
+ char **result = NULL, *temp, delim = '\0';
+
+ for (i = 0; str[i]; i++) {
+ while (isspace((unsigned char) str[i]))
+ i++;
+ start = i;
+ for (; str[i]; i++) {
+ if (str[i] == '\\') {
+ if (str[i+1] != '\0')
+ i++;
+ } else if (str[i] == delim)
+ delim = '\0';
+ else if (!delim &&
+ (isspace((unsigned char) str[i]) ||
+ strchr("()<>;&|$", str[i])))
+ break;
+ else if (!delim && strchr("'`\"", str[i]))
+ delim = str[i];
+ }
+
+ if (result_idx + 2 >= size) {
+ size <<= 1;
+ result = realloc(result, size * sizeof(char *));
+ }
+ len = i - start;
+ temp = malloc(len + 1);
+ (void) strncpy(temp, &str[start], len);
+ temp[len] = '\0';
+ result[result_idx++] = temp;
+ result[result_idx] = NULL;
+ }
+
+ return (result);
+}
+
+
+/*
+ * limit size of history record to ``max'' events
+ */
+void
+stifle_history(int max)
+{
+ HistEvent ev;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ if (history(h, &ev, H_SETSIZE, max) == 0)
+ max_input_history = max;
+}
+
+
+/*
+ * "unlimit" size of history - set the limit to maximum allowed int value
+ */
+int
+unstifle_history(void)
+{
+ HistEvent ev;
+ int omax;
+
+ history(h, &ev, H_SETSIZE, INT_MAX);
+ omax = max_input_history;
+ max_input_history = INT_MAX;
+ return (omax); /* some value _must_ be returned */
+}
+
+
+int
+history_is_stifled(void)
+{
+
+ /* cannot return true answer */
+ return (max_input_history != INT_MAX);
+}
+
+
+/*
+ * read history from a file given
+ */
+int
+read_history(const char *filename)
+{
+ HistEvent ev;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+ return (history(h, &ev, H_LOAD, filename));
+}
+
+
+/*
+ * write history to a file given
+ */
+int
+write_history(const char *filename)
+{
+ HistEvent ev;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+ return (history(h, &ev, H_SAVE, filename));
+}
+
+
+/*
+ * returns history ``num''th event
+ *
+ * returned pointer points to static variable
+ */
+HIST_ENTRY *
+history_get(int num)
+{
+ static HIST_ENTRY she;
+ HistEvent ev;
+ int i = 1, curr_num;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ /* rewind to beginning */
+ if (history(h, &ev, H_CURR) != 0)
+ return (NULL);
+ curr_num = ev.num;
+ if (history(h, &ev, H_LAST) != 0)
+ return (NULL); /* error */
+ while (i < num && history(h, &ev, H_PREV) == 0)
+ i++;
+ if (i != num)
+ return (NULL); /* not so many entries */
+
+ she.line = ev.str;
+ she.data = NULL;
+
+ /* rewind history to the same event it was before */
+ (void) history(h, &ev, H_FIRST);
+ (void) history(h, &ev, H_NEXT_EVENT, curr_num);
+
+ return (&she);
+}
+
+
+/*
+ * add the line to history table
+ */
+int
+add_history(const char *line)
+{
+ HistEvent ev;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ (void) history(h, &ev, H_ENTER, line);
+ if (history(h, &ev, H_GETSIZE) == 0)
+ history_length = ev.num;
+
+ return (!(history_length > 0)); /* return 0 if all is okay */
+}
+
+
+/*
+ * clear the history list - delete all entries
+ */
+void
+clear_history(void)
+{
+ HistEvent ev;
+
+ history(h, &ev, H_CLEAR);
+}
+
+
+/*
+ * returns offset of the current history event
+ */
+int
+where_history(void)
+{
+ HistEvent ev;
+ int curr_num, off;
+
+ if (history(h, &ev, H_CURR) != 0)
+ return (0);
+ curr_num = ev.num;
+
+ history(h, &ev, H_FIRST);
+ off = 1;
+ while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
+ off++;
+
+ return (off);
+}
+
+
+/*
+ * returns current history event or NULL if there is no such event
+ */
+HIST_ENTRY *
+current_history(void)
+{
+
+ return (_move_history(H_CURR));
+}
+
+
+/*
+ * returns total number of bytes history events' data are using
+ */
+int
+history_total_bytes(void)
+{
+ HistEvent ev;
+ int curr_num, size;
+
+ if (history(h, &ev, H_CURR) != 0)
+ return (-1);
+ curr_num = ev.num;
+
+ history(h, &ev, H_FIRST);
+ size = 0;
+ do
+ size += strlen(ev.str);
+ while (history(h, &ev, H_NEXT) == 0);
+
+ /* get to the same position as before */
+ history(h, &ev, H_PREV_EVENT, curr_num);
+
+ return (size);
+}
+
+
+/*
+ * sets the position in the history list to ``pos''
+ */
+int
+history_set_pos(int pos)
+{
+ HistEvent ev;
+ int off, curr_num;
+
+ if (pos > history_length || pos < 0)
+ return (-1);
+
+ history(h, &ev, H_CURR);
+ curr_num = ev.num;
+ history(h, &ev, H_FIRST);
+ off = 0;
+ while (off < pos && history(h, &ev, H_NEXT) == 0)
+ off++;
+
+ if (off != pos) { /* do a rollback in case of error */
+ history(h, &ev, H_FIRST);
+ history(h, &ev, H_NEXT_EVENT, curr_num);
+ return (-1);
+ }
+ return (0);
+}
+
+
+/*
+ * returns previous event in history and shifts pointer accordingly
+ */
+HIST_ENTRY *
+previous_history(void)
+{
+
+ return (_move_history(H_PREV));
+}
+
+
+/*
+ * returns next event in history and shifts pointer accordingly
+ */
+HIST_ENTRY *
+next_history(void)
+{
+
+ return (_move_history(H_NEXT));
+}
+
+
+/*
+ * generic history search function
+ */
+static int
+_history_search_gen(const char *str, int direction, int pos)
+{
+ HistEvent ev;
+ const char *strp;
+ int curr_num;
+
+ if (history(h, &ev, H_CURR) != 0)
+ return (-1);
+ curr_num = ev.num;
+
+ for (;;) {
+ strp = strstr(ev.str, str);
+ if (strp && (pos < 0 || &ev.str[pos] == strp))
+ return (int) (strp - ev.str);
+ if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0)
+ break;
+ }
+
+ history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
+
+ return (-1);
+}
+
+
+/*
+ * searches for first history event containing the str
+ */
+int
+history_search(const char *str, int direction)
+{
+
+ return (_history_search_gen(str, direction, -1));
+}
+
+
+/*
+ * searches for first history event beginning with str
+ */
+int
+history_search_prefix(const char *str, int direction)
+{
+
+ return (_history_search_gen(str, direction, 0));
+}
+
+
+/*
+ * search for event in history containing str, starting at offset
+ * abs(pos); continue backward, if pos<0, forward otherwise
+ */
+/* ARGSUSED */
+int
+history_search_pos(const char *str,
+ int direction __attribute__((unused)), int pos)
+{
+ HistEvent ev;
+ int curr_num, off;
+
+ off = (pos > 0) ? pos : -pos;
+ pos = (pos > 0) ? 1 : -1;
+
+ if (history(h, &ev, H_CURR) != 0)
+ return (-1);
+ curr_num = ev.num;
+
+ if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
+ return (-1);
+
+
+ for (;;) {
+ if (strstr(ev.str, str))
+ return (off);
+ if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
+ break;
+ }
+
+ /* set "current" pointer back to previous state */
+ history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
+
+ return (-1);
+}
+
+
+/********************************/
+/* completition functions */
+
+/*
+ * does tilde expansion of strings of type ``~user/foo''
+ * if ``user'' isn't valid user name or ``txt'' doesn't start
+ * w/ '~', returns pointer to strdup()ed copy of ``txt''
+ *
+ * it's callers's responsibility to free() returned string
+ */
+char *
+tilde_expand(char *txt)
+{
+ struct passwd *pass;
+ char *temp;
+ size_t len = 0;
+
+ if (txt[0] != '~')
+ return (strdup(txt));
+
+ temp = strchr(txt + 1, '/');
+ if (temp == NULL)
+ temp = strdup(txt + 1);
+ else {
+ len = temp - txt + 1; /* text until string after slash */
+ temp = malloc(len);
+ (void) strncpy(temp, txt + 1, len - 2);
+ temp[len - 2] = '\0';
+ }
+ pass = getpwnam(temp);
+ free(temp); /* value no more needed */
+ if (pass == NULL)
+ return (strdup(txt));
+
+ /* update pointer txt to point at string immedially following */
+ /* first slash */
+ txt += len;
+
+ temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
+ (void) sprintf(temp, "%s/%s", pass->pw_dir, txt);
+
+ return (temp);
+}
+
+
+/*
+ * return first found file name starting by the ``text'' or NULL if no
+ * such file can be found
+ * value of ``state'' is ignored
+ *
+ * it's caller's responsibility to free returned string
+ */
+char *
+filename_completion_function(const char *text, int state)
+{
+ static DIR *dir = NULL;
+ static char *filename = NULL, *dirname = NULL;
+ static size_t filename_len = 0;
+ struct dirent *entry;
+ char *temp;
+ size_t len;
+
+ if (state == 0 || dir == NULL) {
+ if (dir != NULL) {
+ closedir(dir);
+ dir = NULL;
+ }
+ temp = strrchr(text, '/');
+ if (temp) {
+ temp++;
+ filename = realloc(filename, strlen(temp) + 1);
+ (void) strcpy(filename, temp);
+ len = temp - text; /* including last slash */
+ dirname = realloc(dirname, len + 1);
+ (void) strncpy(dirname, text, len);
+ dirname[len] = '\0';
+ } else {
+ filename = strdup(text);
+ dirname = NULL;
+ }
+
+ /* support for ``~user'' syntax */
+ if (dirname && *dirname == '~') {
+ temp = tilde_expand(dirname);
+ dirname = realloc(dirname, strlen(temp) + 1);
+ (void) strcpy(dirname, temp); /* safe */
+ free(temp); /* no longer needed */
+ }
+ /* will be used in cycle */
+ filename_len = strlen(filename);
+ if (filename_len == 0)
+ return (NULL); /* no expansion possible */
+
+ dir = opendir(dirname ? dirname : ".");
+ if (!dir)
+ return (NULL); /* cannot open the directory */
+ }
+ /* find the match */
+ while ((entry = readdir(dir)) != NULL) {
+ /* otherwise, get first entry where first */
+ /* filename_len characters are equal */
+ if (entry->d_name[0] == filename[0]
+#if defined(__SVR4) || defined(__linux__)
+ && strlen(entry->d_name) >= filename_len
+#else
+ && entry->d_namlen >= filename_len
+#endif
+ && strncmp(entry->d_name, filename,
+ filename_len) == 0)
+ break;
+ }
+
+ if (entry) { /* match found */
+
+ struct stat stbuf;
+#if defined(__SVR4) || defined(__linux__)
+ len = strlen(entry->d_name) +
+#else
+ len = entry->d_namlen +
+#endif
+ ((dirname) ? strlen(dirname) : 0) + 1 + 1;
+ temp = malloc(len);
+ (void) sprintf(temp, "%s%s",
+ dirname ? dirname : "", entry->d_name); /* safe */
+
+ /* test, if it's directory */
+ if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
+ strcat(temp, "/"); /* safe */
+ } else
+ temp = NULL;
+
+ return (temp);
+}
+
+
+/*
+ * a completion generator for usernames; returns _first_ username
+ * which starts with supplied text
+ * text contains a partial username preceded by random character
+ * (usually '~'); state is ignored
+ * it's callers responsibility to free returned value
+ */
+char *
+username_completion_function(const char *text, int state)
+{
+ struct passwd *pwd;
+
+ if (text[0] == '\0')
+ return (NULL);
+
+ if (*text == '~')
+ text++;
+
+ if (state == 0)
+ setpwent();
+
+ while ((pwd = getpwent()) && text[0] == pwd->pw_name[0]
+ && strcmp(text, pwd->pw_name) == 0);
+
+ if (pwd == NULL) {
+ endpwent();
+ return (NULL);
+ }
+ return (strdup(pwd->pw_name));
+}
+
+
+/*
+ * el-compatible wrapper around rl_complete; needed for key binding
+ */
+/* ARGSUSED */
+static unsigned char
+_el_rl_complete(EditLine *el __attribute__((unused)), int ch)
+{
+ return (unsigned char) rl_complete(0, ch);
+}
+
+
+/*
+ * returns list of completitions for text given
+ */
+char **
+completion_matches(const char *text, CPFunction *genfunc)
+{
+ char **match_list = NULL, *retstr, *prevstr;
+ size_t match_list_len, max_equal, which, i;
+ unsigned int matches;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ matches = 0;
+ match_list_len = 1;
+ while ((retstr = (*genfunc) (text, matches)) != NULL) {
+ if (matches + 1 >= match_list_len) {
+ match_list_len <<= 1;
+ match_list = realloc(match_list,
+ match_list_len * sizeof(char *));
+ }
+ match_list[++matches] = retstr;
+ }
+
+ if (!match_list)
+ return (char **) NULL; /* nothing found */
+
+ /* find least denominator and insert it to match_list[0] */
+ which = 2;
+ prevstr = match_list[1];
+ max_equal = strlen(prevstr);
+ for (; which <= matches; which++) {
+ for (i = 0; i < max_equal &&
+ prevstr[i] == match_list[which][i]; i++)
+ continue;
+ max_equal = i;
+ }
+
+ retstr = malloc(max_equal + 1);
+ (void) strncpy(retstr, match_list[1], max_equal);
+ retstr[max_equal] = '\0';
+ match_list[0] = retstr;
+
+ /* add NULL as last pointer to the array */
+ if (matches + 1 >= match_list_len)
+ match_list = realloc(match_list,
+ (match_list_len + 1) * sizeof(char *));
+ match_list[matches + 1] = (char *) NULL;
+
+ return (match_list);
+}
+
+/*
+ * Sort function for qsort(). Just wrapper around strcasecmp().
+ */
+static int
+_rl_qsort_string_compare(i1, i2)
+ const void *i1, *i2;
+{
+ /*LINTED const castaway*/
+ const char *s1 = ((const char **)i1)[0];
+ /*LINTED const castaway*/
+ const char *s2 = ((const char **)i2)[0];
+
+ return strcasecmp(s1, s2);
+}
+
+/*
+ * Display list of strings in columnar format on readline's output stream.
+ * 'matches' is list of strings, 'len' is number of strings in 'matches',
+ * 'max' is maximum length of string in 'matches'.
+ */
+void
+rl_display_match_list (matches, len, max)
+ char **matches;
+ int len, max;
+{
+ int i, idx, limit, count;
+ int screenwidth = e->el_term.t_size.h;
+
+ /*
+ * Find out how many entries can be put on one line, count
+ * with two spaces between strings.
+ */
+ limit = screenwidth / (max + 2);
+ if (limit == 0)
+ limit = 1;
+
+ /* how many lines of output */
+ count = len / limit;
+ if (count * limit < len)
+ count++;
+
+ /* Sort the items if they are not already sorted. */
+ qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
+ _rl_qsort_string_compare);
+
+ idx = 1;
+ for(; count > 0; count--) {
+ for(i=0; i < limit && matches[idx]; i++, idx++)
+ fprintf(e->el_outfile, "%-*s ", max, matches[idx]);
+ fprintf(e->el_outfile, "\n");
+ }
+}
+
+/*
+ * Complete the word at or before point, called by rl_complete()
+ * 'what_to_do' says what to do with the completion.
+ * `?' means list the possible completions.
+ * TAB means do standard completion.
+ * `*' means insert all of the possible completions.
+ * `!' means to do standard completion, and list all possible completions if
+ * there is more than one.
+ *
+ * Note: '*' support is not implemented
+ */
+static int
+rl_complete_internal(int what_to_do)
+{
+ CPFunction *complet_func;
+ const LineInfo *li;
+ char *temp, **matches;
+ const char *ctemp;
+ size_t len;
+
+ rl_completion_type = what_to_do;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ complet_func = rl_completion_entry_function;
+ if (!complet_func)
+ complet_func = filename_completion_function;
+
+ /* We now look backwards for the start of a filename/variable word */
+ li = el_line(e);
+ ctemp = (const char *) li->cursor;
+ while (ctemp > li->buffer
+ && !strchr(rl_basic_word_break_characters, ctemp[-1])
+ && (!rl_special_prefixes
+ || !strchr(rl_special_prefixes, ctemp[-1]) ) )
+ ctemp--;
+
+ len = li->cursor - ctemp;
+ temp = alloca(len + 1);
+ (void) strncpy(temp, ctemp, len);
+ temp[len] = '\0';
+
+ /* these can be used by function called in completion_matches() */
+ /* or (*rl_attempted_completion_function)() */
+ rl_point = li->cursor - li->buffer;
+ rl_end = li->lastchar - li->buffer;
+
+ if (!rl_attempted_completion_function)
+ matches = completion_matches(temp, complet_func);
+ else {
+ int end = li->cursor - li->buffer;
+ matches = (*rl_attempted_completion_function) (temp, (int)
+ (end - len), end);
+ }
+
+ if (matches) {
+ int i, retval = CC_REFRESH;
+ int matches_num, maxlen, match_len, match_display=1;
+
+ /*
+ * Only replace the completed string with common part of
+ * possible matches if there is possible completion.
+ */
+ if (matches[0][0] != '\0') {
+ el_deletestr(e, (int) len);
+ el_insertstr(e, matches[0]);
+ }
+
+ if (what_to_do == '?')
+ goto display_matches;
+
+ if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+ /*
+ * We found exact match. Add a space after
+ * it, unless we do filename completition and the
+ * object is a directory.
+ */
+ size_t alen = strlen(matches[0]);
+ if ((complet_func != filename_completion_function
+ || (alen > 0 && (matches[0])[alen - 1] != '/'))
+ && rl_completion_append_character) {
+ char buf[2];
+ buf[0] = rl_completion_append_character;
+ buf[1] = '\0';
+ el_insertstr(e, buf);
+ }
+ } else if (what_to_do == '!') {
+ display_matches:
+ /*
+ * More than one match and requested to list possible
+ * matches.
+ */
+
+ for(i=1, maxlen=0; matches[i]; i++) {
+ match_len = strlen(matches[i]);
+ if (match_len > maxlen)
+ maxlen = match_len;
+ }
+ matches_num = i - 1;
+
+ /* newline to get on next line from command line */
+ fprintf(e->el_outfile, "\n");
+
+ /*
+ * If there are too many items, ask user for display
+ * confirmation.
+ */
+ if (matches_num > rl_completion_query_items) {
+ fprintf(e->el_outfile,
+ "Display all %d possibilities? (y or n) ",
+ matches_num);
+ fflush(e->el_outfile);
+ if (getc(stdin) != 'y')
+ match_display = 0;
+ fprintf(e->el_outfile, "\n");
+ }
+
+ if (match_display)
+ rl_display_match_list(matches, matches_num,
+ maxlen);
+ retval = CC_REDISPLAY;
+ } else if (matches[0][0]) {
+ /*
+ * There was some common match, but the name was
+ * not complete enough. Next tab will print possible
+ * completions.
+ */
+ el_beep(e);
+ } else {
+ /* lcd is not a valid object - further specification */
+ /* is needed */
+ el_beep(e);
+ retval = CC_NORM;
+ }
+
+ /* free elements of array and the array itself */
+ for (i = 0; matches[i]; i++)
+ free(matches[i]);
+ free(matches), matches = NULL;
+
+ return (retval);
+ }
+ return (CC_NORM);
+}
+
+
+/*
+ * complete word at current point
+ */
+int
+rl_complete(int ignore, int invoking_key)
+{
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ if (rl_inhibit_completion) {
+ rl_insert(ignore, invoking_key);
+ return (CC_REFRESH);
+ } else if (e->el_state.lastcmd == el_rl_complete_cmdnum)
+ return rl_complete_internal('?');
+ else if (_rl_complete_show_all)
+ return rl_complete_internal('!');
+ else
+ return (rl_complete_internal(TAB));
+}
+
+
+/*
+ * misc other functions
+ */
+
+/*
+ * bind key c to readline-type function func
+ */
+int
+rl_bind_key(int c, int func(int, int))
+{
+ int retval = -1;
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ if (func == rl_insert) {
+ /* XXX notice there is no range checking of ``c'' */
+ e->el_map.key[c] = ED_INSERT;
+ retval = 0;
+ }
+ return (retval);
+}
+
+
+/*
+ * read one key from input - handles chars pushed back
+ * to input stream also
+ */
+int
+rl_read_key(void)
+{
+ char fooarr[2 * sizeof(int)];
+
+ if (e == NULL || h == NULL)
+ rl_initialize();
+
+ return (el_getc(e, fooarr));
+}
+
+
+/*
+ * reset the terminal
+ */
+/* ARGSUSED */
+void
+rl_reset_terminal(const char *p __attribute__((unused)))
+{
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+ el_reset(e);
+}
+
+
+/*
+ * insert character ``c'' back into input stream, ``count'' times
+ */
+int
+rl_insert(int count, int c)
+{
+ char arr[2];
+
+ if (h == NULL || e == NULL)
+ rl_initialize();
+
+ /* XXX - int -> char conversion can lose on multichars */
+ arr[0] = c;
+ arr[1] = '\0';
+
+ for (; count > 0; count--)
+ el_push(e, arr);
+
+ return (0);
+}
diff --git a/cmd-line-utils/libedit/readline/readline.h b/cmd-line-utils/libedit/readline/readline.h
new file mode 100644
index 00000000000..851ade02b53
--- /dev/null
+++ b/cmd-line-utils/libedit/readline/readline.h
@@ -0,0 +1,127 @@
+/* $NetBSD: readline.h,v 1.1 2001/01/05 21:15:50 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _READLINE_H_
+#define _READLINE_H_
+
+#include <sys/types.h>
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#else
+#ifndef __BEGIN_DECLS
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+#endif
+
+/* list of readline stuff supported by editline library's readline wrapper */
+
+/* typedefs */
+typedef int Function(const char *, int);
+typedef void VFunction(void);
+typedef char *CPFunction(const char *, int);
+typedef char **CPPFunction(const char *, int, int);
+
+typedef struct _hist_entry {
+ const char *line;
+ const char *data;
+} HIST_ENTRY;
+
+/* global variables used by readline enabled applications */
+__BEGIN_DECLS
+extern const char *rl_library_version;
+extern const char *rl_readline_name;
+extern FILE *rl_instream;
+extern FILE *rl_outstream;
+extern char *rl_line_buffer;
+extern int rl_point, rl_end;
+extern int history_base, history_length;
+extern int max_input_history;
+extern const char *rl_basic_word_break_characters;
+extern char *rl_completer_word_break_characters;
+extern char *rl_completer_quote_characters;
+extern CPFunction *rl_completion_entry_function;
+extern CPPFunction *rl_attempted_completion_function;
+extern int rl_completion_type;
+extern int rl_completion_query_items;
+extern char *rl_special_prefixes;
+extern int rl_completion_append_character;
+
+/* supported functions */
+char *readline(const char *);
+int rl_initialize(void);
+
+void using_history(void);
+int add_history(const char *);
+void clear_history(void);
+void stifle_history(int);
+int unstifle_history(void);
+int history_is_stifled(void);
+int where_history(void);
+HIST_ENTRY *current_history(void);
+HIST_ENTRY *history_get(int);
+int history_total_bytes(void);
+int history_set_pos(int);
+HIST_ENTRY *previous_history(void);
+HIST_ENTRY *next_history(void);
+int history_search(const char *, int);
+int history_search_prefix(const char *, int);
+int history_search_pos(const char *, int, int);
+int read_history(const char *);
+int write_history(const char *);
+int history_expand(char *, char **);
+char **history_tokenize(const char *);
+
+char *tilde_expand(char *);
+char *filename_completion_function(const char *, int);
+char *username_completion_function(const char *, int);
+int rl_complete(int, int);
+int rl_read_key(void);
+char **completion_matches(const char *, CPFunction *);
+void rl_display_match_list(char **, int, int);
+
+int rl_insert(int, int);
+void rl_reset_terminal(const char *);
+int rl_bind_key(int, int (*)(int, int));
+__END_DECLS
+
+#endif /* _READLINE_H_ */
diff --git a/cmd-line-utils/libedit/refresh.c b/cmd-line-utils/libedit/refresh.c
new file mode 100644
index 00000000000..534e7e12304
--- /dev/null
+++ b/cmd-line-utils/libedit/refresh.c
@@ -0,0 +1,1100 @@
+/* $NetBSD: refresh.c,v 1.17 2001/04/13 00:53:11 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * refresh.c: Lower level screen refreshing functions
+ */
+#include "sys.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "el.h"
+
+private void re_addc(EditLine *, int);
+private void re_update_line(EditLine *, char *, char *, int);
+private void re_insert (EditLine *, char *, int, int, char *, int);
+private void re_delete(EditLine *, char *, int, int, int);
+private void re_fastputc(EditLine *, int);
+private void re__strncopy(char *, char *, size_t);
+private void re__copy_and_pad(char *, const char *, size_t);
+
+#ifdef DEBUG_REFRESH
+private void re_printstr(EditLine *, char *, char *, char *);
+#define __F el->el_errfile
+#define ELRE_ASSERT(a, b, c) do \
+ if (a) { \
+ (void) fprintf b; \
+ c; \
+ } \
+ while (0)
+#define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;)
+
+/* re_printstr():
+ * Print a string on the debugging pty
+ */
+private void
+re_printstr(EditLine *el, char *str, char *f, char *t)
+{
+
+ ELRE_DEBUG(1, (__F, "%s:\"", str));
+ while (f < t)
+ ELRE_DEBUG(1, (__F, "%c", *f++ & 0177));
+ ELRE_DEBUG(1, (__F, "\"\r\n"));
+}
+#else
+#define ELRE_ASSERT(a, b, c)
+#define ELRE_DEBUG(a, b)
+#endif
+
+
+/* re_addc():
+ * Draw c, expanding tabs, control chars etc.
+ */
+private void
+re_addc(EditLine *el, int c)
+{
+
+ if (isprint(c)) {
+ re_putc(el, c, 1);
+ return;
+ }
+ if (c == '\n') { /* expand the newline */
+ int oldv = el->el_refresh.r_cursor.v;
+ re_putc(el, '\0', 0); /* assure end of line */
+ if (oldv == el->el_refresh.r_cursor.v) { /* XXX */
+ el->el_refresh.r_cursor.h = 0; /* reset cursor pos */
+ el->el_refresh.r_cursor.v++;
+ }
+ return;
+ }
+ if (c == '\t') { /* expand the tab */
+ for (;;) {
+ re_putc(el, ' ', 1);
+ if ((el->el_refresh.r_cursor.h & 07) == 0)
+ break; /* go until tab stop */
+ }
+ } else if (iscntrl(c)) {
+ re_putc(el, '^', 1);
+ if (c == '\177')
+ re_putc(el, '?', 1);
+ else
+ /* uncontrolify it; works only for iso8859-1 like sets */
+ re_putc(el, (c | 0100), 1);
+ } else {
+ re_putc(el, '\\', 1);
+ re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1);
+ re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1);
+ re_putc(el, (c & 07) + '0', 1);
+ }
+}
+
+
+/* re_putc():
+ * Draw the character given
+ */
+protected void
+re_putc(EditLine *el, int c, int shift)
+{
+
+ ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c));
+
+ el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c;
+ if (!shift)
+ return;
+
+ el->el_refresh.r_cursor.h++; /* advance to next place */
+ if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) {
+ el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0';
+ /* assure end of line */
+ el->el_refresh.r_cursor.h = 0; /* reset it. */
+
+ /*
+ * If we would overflow (input is longer than terminal size),
+ * emulate scroll by dropping first line and shuffling the rest.
+ * We do this via pointer shuffling - it's safe in this case
+ * and we avoid memcpy().
+ */
+ if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) {
+ int i, lins = el->el_term.t_size.v;
+ char *firstline = el->el_vdisplay[0];
+
+ for(i=1; i < lins; i++)
+ el->el_vdisplay[i-1] = el->el_vdisplay[i];
+
+ firstline[0] = '\0'; /* empty the string */
+ el->el_vdisplay[i-1] = firstline;
+ } else
+ el->el_refresh.r_cursor.v++;
+
+ ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
+ (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
+ el->el_refresh.r_cursor.v, el->el_term.t_size.v),
+ abort());
+ }
+}
+
+
+/* re_refresh():
+ * draws the new virtual screen image from the current input
+ * line, then goes line-by-line changing the real image to the new
+ * virtual image. The routine to re-draw a line can be replaced
+ * easily in hopes of a smarter one being placed there.
+ */
+protected void
+re_refresh(EditLine *el)
+{
+ int i, rhdiff;
+ char *cp, *st;
+ coord_t cur;
+#ifdef notyet
+ size_t termsz;
+#endif
+
+ ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%s:\r\n",
+ el->el_line.buffer));
+
+ /* reset the Drawing cursor */
+ el->el_refresh.r_cursor.h = 0;
+ el->el_refresh.r_cursor.v = 0;
+
+ /* temporarily draw rprompt to calculate its size */
+ prompt_print(el, EL_RPROMPT);
+
+ /* reset the Drawing cursor */
+ el->el_refresh.r_cursor.h = 0;
+ el->el_refresh.r_cursor.v = 0;
+
+ cur.h = -1; /* set flag in case I'm not set */
+ cur.v = 0;
+
+ prompt_print(el, EL_PROMPT);
+
+ /* draw the current input buffer */
+#if notyet
+ termsz = el->el_term.t_size.h * el->el_term.t_size.v;
+ if (el->el_line.lastchar - el->el_line.buffer > termsz) {
+ /*
+ * If line is longer than terminal, process only part
+ * of line which would influence display.
+ */
+ size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz;
+
+ st = el->el_line.lastchar - rem
+ - (termsz - (((rem / el->el_term.t_size.v) - 1)
+ * el->el_term.t_size.v));
+ } else
+#endif
+ st = el->el_line.buffer;
+
+ for (cp = st; cp < el->el_line.lastchar; cp++) {
+ if (cp == el->el_line.cursor) {
+ /* save for later */
+ cur.h = el->el_refresh.r_cursor.h;
+ cur.v = el->el_refresh.r_cursor.v;
+ }
+ re_addc(el, (unsigned char) *cp);
+ }
+
+ if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */
+ cur.h = el->el_refresh.r_cursor.h;
+ cur.v = el->el_refresh.r_cursor.v;
+ }
+ rhdiff = el->el_term.t_size.h - el->el_refresh.r_cursor.h -
+ el->el_rprompt.p_pos.h;
+ if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v &&
+ !el->el_refresh.r_cursor.v && rhdiff > 1) {
+ /*
+ * have a right-hand side prompt that will fit
+ * on the end of the first line with at least
+ * one character gap to the input buffer.
+ */
+ while (--rhdiff > 0) /* pad out with spaces */
+ re_putc(el, ' ', 1);
+ prompt_print(el, EL_RPROMPT);
+ } else {
+ el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */
+ el->el_rprompt.p_pos.v = 0;
+ }
+
+ re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */
+
+ el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
+
+ ELRE_DEBUG(1, (__F,
+ "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
+ el->el_term.t_size.h, el->el_refresh.r_cursor.h,
+ el->el_refresh.r_cursor.v, el->el_vdisplay[0]));
+
+ ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv));
+ for (i = 0; i <= el->el_refresh.r_newcv; i++) {
+ /* NOTE THAT re_update_line MAY CHANGE el_display[i] */
+ re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
+
+ /*
+ * Copy the new line to be the current one, and pad out with
+ * spaces to the full width of the terminal so that if we try
+ * moving the cursor by writing the character that is at the
+ * end of the screen line, it won't be a NUL or some old
+ * leftover stuff.
+ */
+ re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
+ (size_t) el->el_term.t_size.h);
+ }
+ ELRE_DEBUG(1, (__F,
+ "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
+ el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i));
+
+ if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
+ for (; i <= el->el_refresh.r_oldcv; i++) {
+ term_move_to_line(el, i);
+ term_move_to_char(el, 0);
+ term_clear_EOL(el, (int) strlen(el->el_display[i]));
+#ifdef DEBUG_REFRESH
+ term_overwrite(el, "C\b", 2);
+#endif /* DEBUG_REFRESH */
+ el->el_display[i][0] = '\0';
+ }
+
+ el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */
+ ELRE_DEBUG(1, (__F,
+ "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
+ el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
+ cur.h, cur.v));
+ term_move_to_line(el, cur.v); /* go to where the cursor is */
+ term_move_to_char(el, cur.h);
+}
+
+
+/* re_goto_bottom():
+ * used to go to last used screen line
+ */
+protected void
+re_goto_bottom(EditLine *el)
+{
+
+ term_move_to_line(el, el->el_refresh.r_oldcv);
+ term__putc('\r');
+ term__putc('\n');
+ re_clear_display(el);
+ term__flush();
+}
+
+
+/* re_insert():
+ * insert num characters of s into d (in front of the character)
+ * at dat, maximum length of d is dlen
+ */
+private void
+/*ARGSUSED*/
+re_insert(EditLine *el __attribute__((unused)),
+ char *d, int dat, int dlen, char *s, int num)
+{
+ char *a, *b;
+
+ if (num <= 0)
+ return;
+ if (num > dlen - dat)
+ num = dlen - dat;
+
+ ELRE_DEBUG(1,
+ (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, d));
+ ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
+
+ /* open up the space for num chars */
+ if (num > 0) {
+ b = d + dlen - 1;
+ a = b - num;
+ while (a >= &d[dat])
+ *b-- = *a--;
+ d[dlen] = '\0'; /* just in case */
+ }
+ ELRE_DEBUG(1, (__F,
+ "re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, d));
+ ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
+
+ /* copy the characters */
+ for (a = d + dat; (a < d + dlen) && (num > 0); num--)
+ *a++ = *s++;
+
+ ELRE_DEBUG(1,
+ (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
+ num, dat, dlen, d, s));
+ ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
+}
+
+
+/* re_delete():
+ * delete num characters d at dat, maximum length of d is dlen
+ */
+private void
+/*ARGSUSED*/
+re_delete(EditLine *el __attribute__((unused)),
+ char *d, int dat, int dlen, int num)
+{
+ char *a, *b;
+
+ if (num <= 0)
+ return;
+ if (dat + num >= dlen) {
+ d[dat] = '\0';
+ return;
+ }
+ ELRE_DEBUG(1,
+ (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, d));
+
+ /* open up the space for num chars */
+ if (num > 0) {
+ b = d + dat;
+ a = b + num;
+ while (a < &d[dlen])
+ *b++ = *a++;
+ d[dlen] = '\0'; /* just in case */
+ }
+ ELRE_DEBUG(1,
+ (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, d));
+}
+
+
+/* re__strncopy():
+ * Like strncpy without padding.
+ */
+private void
+re__strncopy(char *a, char *b, size_t n)
+{
+
+ while (n-- && *b)
+ *a++ = *b++;
+}
+
+
+/*****************************************************************
+ re_update_line() is based on finding the middle difference of each line
+ on the screen; vis:
+
+ /old first difference
+ /beginning of line | /old last same /old EOL
+ v v v v
+old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new: eddie> Oh, my little buggy says to me, as lurgid as
+ ^ ^ ^ ^
+ \beginning of line | \new last same \new end of line
+ \new first difference
+
+ all are character pointers for the sake of speed. Special cases for
+ no differences, as well as for end of line additions must be handled.
+**************************************************************** */
+
+/* Minimum at which doing an insert it "worth it". This should be about
+ * half the "cost" of going into insert mode, inserting a character, and
+ * going back out. This should really be calculated from the termcap
+ * data... For the moment, a good number for ANSI terminals.
+ */
+#define MIN_END_KEEP 4
+
+private void
+re_update_line(EditLine *el, char *old, char *new, int i)
+{
+ char *o, *n, *p, c;
+ char *ofd, *ols, *oe, *nfd, *nls, *ne;
+ char *osb, *ose, *nsb, *nse;
+ int fx, sx;
+
+ /*
+ * find first diff
+ */
+ for (o = old, n = new; *o && (*o == *n); o++, n++)
+ continue;
+ ofd = o;
+ nfd = n;
+
+ /*
+ * Find the end of both old and new
+ */
+ while (*o)
+ o++;
+ /*
+ * Remove any trailing blanks off of the end, being careful not to
+ * back up past the beginning.
+ */
+ while (ofd < o) {
+ if (o[-1] != ' ')
+ break;
+ o--;
+ }
+ oe = o;
+ *oe = '\0';
+
+ while (*n)
+ n++;
+
+ /* remove blanks from end of new */
+ while (nfd < n) {
+ if (n[-1] != ' ')
+ break;
+ n--;
+ }
+ ne = n;
+ *ne = '\0';
+
+ /*
+ * if no diff, continue to next line of redraw
+ */
+ if (*ofd == '\0' && *nfd == '\0') {
+ ELRE_DEBUG(1, (__F, "no difference.\r\n"));
+ return;
+ }
+ /*
+ * find last same pointer
+ */
+ while ((o > ofd) && (n > nfd) && (*--o == *--n))
+ continue;
+ ols = ++o;
+ nls = ++n;
+
+ /*
+ * find same begining and same end
+ */
+ osb = ols;
+ nsb = nls;
+ ose = ols;
+ nse = nls;
+
+ /*
+ * case 1: insert: scan from nfd to nls looking for *ofd
+ */
+ if (*ofd) {
+ for (c = *ofd, n = nfd; n < nls; n++) {
+ if (c == *n) {
+ for (o = ofd, p = n;
+ p < nls && o < ols && *o == *p;
+ o++, p++)
+ continue;
+ /*
+ * if the new match is longer and it's worth
+ * keeping, then we take it
+ */
+ if (((nse - nsb) < (p - n)) &&
+ (2 * (p - n) > n - nfd)) {
+ nsb = n;
+ nse = p;
+ osb = ofd;
+ ose = o;
+ }
+ }
+ }
+ }
+ /*
+ * case 2: delete: scan from ofd to ols looking for *nfd
+ */
+ if (*nfd) {
+ for (c = *nfd, o = ofd; o < ols; o++) {
+ if (c == *o) {
+ for (n = nfd, p = o;
+ p < ols && n < nls && *p == *n;
+ p++, n++)
+ continue;
+ /*
+ * if the new match is longer and it's worth
+ * keeping, then we take it
+ */
+ if (((ose - osb) < (p - o)) &&
+ (2 * (p - o) > o - ofd)) {
+ nsb = nfd;
+ nse = n;
+ osb = o;
+ ose = p;
+ }
+ }
+ }
+ }
+ /*
+ * Pragmatics I: If old trailing whitespace or not enough characters to
+ * save to be worth it, then don't save the last same info.
+ */
+ if ((oe - ols) < MIN_END_KEEP) {
+ ols = oe;
+ nls = ne;
+ }
+ /*
+ * Pragmatics II: if the terminal isn't smart enough, make the data
+ * dumber so the smart update doesn't try anything fancy
+ */
+
+ /*
+ * fx is the number of characters we need to insert/delete: in the
+ * beginning to bring the two same begins together
+ */
+ fx = (nsb - nfd) - (osb - ofd);
+ /*
+ * sx is the number of characters we need to insert/delete: in the
+ * end to bring the two same last parts together
+ */
+ sx = (nls - nse) - (ols - ose);
+
+ if (!EL_CAN_INSERT) {
+ if (fx > 0) {
+ osb = ols;
+ ose = ols;
+ nsb = nls;
+ nse = nls;
+ }
+ if (sx > 0) {
+ ols = oe;
+ nls = ne;
+ }
+ if ((ols - ofd) < (nls - nfd)) {
+ ols = oe;
+ nls = ne;
+ }
+ }
+ if (!EL_CAN_DELETE) {
+ if (fx < 0) {
+ osb = ols;
+ ose = ols;
+ nsb = nls;
+ nse = nls;
+ }
+ if (sx < 0) {
+ ols = oe;
+ nls = ne;
+ }
+ if ((ols - ofd) > (nls - nfd)) {
+ ols = oe;
+ nls = ne;
+ }
+ }
+ /*
+ * Pragmatics III: make sure the middle shifted pointers are correct if
+ * they don't point to anything (we may have moved ols or nls).
+ */
+ /* if the change isn't worth it, don't bother */
+ /* was: if (osb == ose) */
+ if ((ose - osb) < MIN_END_KEEP) {
+ osb = ols;
+ ose = ols;
+ nsb = nls;
+ nse = nls;
+ }
+ /*
+ * Now that we are done with pragmatics we recompute fx, sx
+ */
+ fx = (nsb - nfd) - (osb - ofd);
+ sx = (nls - nse) - (ols - ose);
+
+ ELRE_DEBUG(1, (__F, "\n"));
+ ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n",
+ ofd - old, osb - old, ose - old, ols - old, oe - old));
+ ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
+ nfd - new, nsb - new, nse - new, nls - new, ne - new));
+ ELRE_DEBUG(1, (__F,
+ "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"));
+ ELRE_DEBUG(1, (__F,
+ "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));
+#ifdef DEBUG_REFRESH
+ re_printstr(el, "old- oe", old, oe);
+ re_printstr(el, "new- ne", new, ne);
+ re_printstr(el, "old-ofd", old, ofd);
+ re_printstr(el, "new-nfd", new, nfd);
+ re_printstr(el, "ofd-osb", ofd, osb);
+ re_printstr(el, "nfd-nsb", nfd, nsb);
+ re_printstr(el, "osb-ose", osb, ose);
+ re_printstr(el, "nsb-nse", nsb, nse);
+ re_printstr(el, "ose-ols", ose, ols);
+ re_printstr(el, "nse-nls", nse, nls);
+ re_printstr(el, "ols- oe", ols, oe);
+ re_printstr(el, "nls- ne", nls, ne);
+#endif /* DEBUG_REFRESH */
+
+ /*
+ * el_cursor.v to this line i MUST be in this routine so that if we
+ * don't have to change the line, we don't move to it. el_cursor.h to
+ * first diff char
+ */
+ term_move_to_line(el, i);
+
+ /*
+ * at this point we have something like this:
+ *
+ * /old /ofd /osb /ose /ols /oe
+ * v.....................v v..................v v........v
+ * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
+ * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
+ * ^.....................^ ^..................^ ^........^
+ * \new \nfd \nsb \nse \nls \ne
+ *
+ * fx is the difference in length between the chars between nfd and
+ * nsb, and the chars between ofd and osb, and is thus the number of
+ * characters to delete if < 0 (new is shorter than old, as above),
+ * or insert (new is longer than short).
+ *
+ * sx is the same for the second differences.
+ */
+
+ /*
+ * if we have a net insert on the first difference, AND inserting the
+ * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful
+ * character (which is ne if nls != ne, otherwise is nse) off the edge
+ * of the screen (el->el_term.t_size.h) else we do the deletes first
+ * so that we keep everything we need to.
+ */
+
+ /*
+ * if the last same is the same like the end, there is no last same
+ * part, otherwise we want to keep the last same part set p to the
+ * last useful old character
+ */
+ p = (ols != oe) ? oe : ose;
+
+ /*
+ * if (There is a diffence in the beginning) && (we need to insert
+ * characters) && (the number of characters to insert is less than
+ * the term width)
+ * We need to do an insert!
+ * else if (we need to delete characters)
+ * We need to delete characters!
+ * else
+ * No insert or delete
+ */
+ if ((nsb != nfd) && fx > 0 &&
+ ((p - old) + fx <= el->el_term.t_size.h)) {
+ ELRE_DEBUG(1,
+ (__F, "first diff insert at %d...\r\n", nfd - new));
+ /*
+ * Move to the first char to insert, where the first diff is.
+ */
+ term_move_to_char(el, nfd - new);
+ /*
+ * Check if we have stuff to keep at end
+ */
+ if (nsb != ne) {
+ ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
+ /*
+ * insert fx chars of new starting at nfd
+ */
+ if (fx > 0) {
+ ELRE_DEBUG(!EL_CAN_INSERT, (__F,
+ "ERROR: cannot insert in early first diff\n"));
+ term_insertwrite(el, nfd, fx);
+ re_insert(el, old, ofd - old,
+ el->el_term.t_size.h, nfd, fx);
+ }
+ /*
+ * write (nsb-nfd) - fx chars of new starting at
+ * (nfd + fx)
+ */
+ term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
+ re__strncopy(ofd + fx, nfd + fx,
+ (size_t) ((nsb - nfd) - fx));
+ } else {
+ ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
+ term_overwrite(el, nfd, (nsb - nfd));
+ re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
+ /*
+ * Done
+ */
+ return;
+ }
+ } else if (fx < 0) {
+ ELRE_DEBUG(1,
+ (__F, "first diff delete at %d...\r\n", ofd - old));
+ /*
+ * move to the first char to delete where the first diff is
+ */
+ term_move_to_char(el, ofd - old);
+ /*
+ * Check if we have stuff to save
+ */
+ if (osb != oe) {
+ ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
+ /*
+ * fx is less than zero *always* here but we check
+ * for code symmetry
+ */
+ if (fx < 0) {
+ ELRE_DEBUG(!EL_CAN_DELETE, (__F,
+ "ERROR: cannot delete in first diff\n"));
+ term_deletechars(el, -fx);
+ re_delete(el, old, ofd - old,
+ el->el_term.t_size.h, -fx);
+ }
+ /*
+ * write (nsb-nfd) chars of new starting at nfd
+ */
+ term_overwrite(el, nfd, (nsb - nfd));
+ re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
+
+ } else {
+ ELRE_DEBUG(1, (__F,
+ "but with nothing left to save\r\n"));
+ /*
+ * write (nsb-nfd) chars of new starting at nfd
+ */
+ term_overwrite(el, nfd, (nsb - nfd));
+ ELRE_DEBUG(1, (__F,
+ "cleareol %d\n", (oe - old) - (ne - new)));
+ term_clear_EOL(el, (oe - old) - (ne - new));
+ /*
+ * Done
+ */
+ return;
+ }
+ } else
+ fx = 0;
+
+ if (sx < 0 && (ose - old) + fx < el->el_term.t_size.h) {
+ ELRE_DEBUG(1, (__F,
+ "second diff delete at %d...\r\n", (ose - old) + fx));
+ /*
+ * Check if we have stuff to delete
+ */
+ /*
+ * fx is the number of characters inserted (+) or deleted (-)
+ */
+
+ term_move_to_char(el, (ose - old) + fx);
+ /*
+ * Check if we have stuff to save
+ */
+ if (ols != oe) {
+ ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
+ /*
+ * Again a duplicate test.
+ */
+ if (sx < 0) {
+ ELRE_DEBUG(!EL_CAN_DELETE, (__F,
+ "ERROR: cannot delete in second diff\n"));
+ term_deletechars(el, -sx);
+ }
+ /*
+ * write (nls-nse) chars of new starting at nse
+ */
+ term_overwrite(el, nse, (nls - nse));
+ } else {
+ ELRE_DEBUG(1, (__F,
+ "but with nothing left to save\r\n"));
+ term_overwrite(el, nse, (nls - nse));
+ ELRE_DEBUG(1, (__F,
+ "cleareol %d\n", (oe - old) - (ne - new)));
+ if ((oe - old) - (ne - new) != 0)
+ term_clear_EOL(el, (oe - old) - (ne - new));
+ }
+ }
+ /*
+ * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
+ */
+ if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
+ ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n",
+ nfd - new));
+
+ term_move_to_char(el, nfd - new);
+ /*
+ * Check if we have stuff to keep at the end
+ */
+ if (nsb != ne) {
+ ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
+ /*
+ * We have to recalculate fx here because we set it
+ * to zero above as a flag saying that we hadn't done
+ * an early first insert.
+ */
+ fx = (nsb - nfd) - (osb - ofd);
+ if (fx > 0) {
+ /*
+ * insert fx chars of new starting at nfd
+ */
+ ELRE_DEBUG(!EL_CAN_INSERT, (__F,
+ "ERROR: cannot insert in late first diff\n"));
+ term_insertwrite(el, nfd, fx);
+ re_insert(el, old, ofd - old,
+ el->el_term.t_size.h, nfd, fx);
+ }
+ /*
+ * write (nsb-nfd) - fx chars of new starting at
+ * (nfd + fx)
+ */
+ term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
+ re__strncopy(ofd + fx, nfd + fx,
+ (size_t) ((nsb - nfd) - fx));
+ } else {
+ ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
+ term_overwrite(el, nfd, (nsb - nfd));
+ re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
+ }
+ }
+ /*
+ * line is now NEW up to nse
+ */
+ if (sx >= 0) {
+ ELRE_DEBUG(1, (__F,
+ "second diff insert at %d...\r\n", nse - new));
+ term_move_to_char(el, nse - new);
+ if (ols != oe) {
+ ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
+ if (sx > 0) {
+ /* insert sx chars of new starting at nse */
+ ELRE_DEBUG(!EL_CAN_INSERT, (__F,
+ "ERROR: cannot insert in second diff\n"));
+ term_insertwrite(el, nse, sx);
+ }
+ /*
+ * write (nls-nse) - sx chars of new starting at
+ * (nse + sx)
+ */
+ term_overwrite(el, nse + sx, (nls - nse) - sx);
+ } else {
+ ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
+ term_overwrite(el, nse, (nls - nse));
+
+ /*
+ * No need to do a clear-to-end here because we were
+ * doing a second insert, so we will have over
+ * written all of the old string.
+ */
+ }
+ }
+ ELRE_DEBUG(1, (__F, "done.\r\n"));
+}
+
+
+/* re__copy_and_pad():
+ * Copy string and pad with spaces
+ */
+private void
+re__copy_and_pad(char *dst, const char *src, size_t width)
+{
+ unsigned int i;
+
+ for (i = 0; i < width; i++) {
+ if (*src == '\0')
+ break;
+ *dst++ = *src++;
+ }
+
+ for (; i < width; i++)
+ *dst++ = ' ';
+
+ *dst = '\0';
+}
+
+
+/* re_refresh_cursor():
+ * Move to the new cursor position
+ */
+protected void
+re_refresh_cursor(EditLine *el)
+{
+ char *cp, c;
+ int h, v, th;
+
+ /* first we must find where the cursor is... */
+ h = el->el_prompt.p_pos.h;
+ v = el->el_prompt.p_pos.v;
+ th = el->el_term.t_size.h; /* optimize for speed */
+
+ /* do input buffer to el->el_line.cursor */
+ for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
+ c = *cp;
+ h++; /* all chars at least this long */
+
+ if (c == '\n') {/* handle newline in data part too */
+ h = 0;
+ v++;
+ } else {
+ if (c == '\t') { /* if a tab, to next tab stop */
+ while (h & 07) {
+ h++;
+ }
+ } else if (iscntrl((unsigned char) c)) {
+ /* if control char */
+ h++;
+ if (h > th) { /* if overflow, compensate */
+ h = 1;
+ v++;
+ }
+ } else if (!isprint((unsigned char) c)) {
+ h += 3;
+ if (h > th) { /* if overflow, compensate */
+ h = h - th;
+ v++;
+ }
+ }
+ }
+
+ if (h >= th) { /* check, extra long tabs picked up here also */
+ h = 0;
+ v++;
+ }
+ }
+
+ /* now go there */
+ term_move_to_line(el, v);
+ term_move_to_char(el, h);
+ term__flush();
+}
+
+
+/* re_fastputc():
+ * Add a character fast.
+ */
+private void
+re_fastputc(EditLine *el, int c)
+{
+
+ term__putc(c);
+ el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
+ if (el->el_cursor.h >= el->el_term.t_size.h) {
+ /* if we must overflow */
+ el->el_cursor.h = 0;
+
+ /*
+ * If we would overflow (input is longer than terminal size),
+ * emulate scroll by dropping first line and shuffling the rest.
+ * We do this via pointer shuffling - it's safe in this case
+ * and we avoid memcpy().
+ */
+ if (el->el_cursor.v + 1 >= el->el_term.t_size.v) {
+ int i, lins = el->el_term.t_size.v;
+ char *firstline = el->el_display[0];
+
+ for(i=1; i < lins; i++)
+ el->el_display[i-1] = el->el_display[i];
+
+ re__copy_and_pad(firstline, "", 0);
+ el->el_display[i-1] = firstline;
+ } else {
+ el->el_cursor.v++;
+ el->el_refresh.r_oldcv++;
+ }
+ if (EL_HAS_AUTO_MARGINS) {
+ if (EL_HAS_MAGIC_MARGINS) {
+ term__putc(' ');
+ term__putc('\b');
+ }
+ } else {
+ term__putc('\r');
+ term__putc('\n');
+ }
+ }
+}
+
+
+/* re_fastaddc():
+ * we added just one char, handle it fast.
+ * Assumes that screen cursor == real cursor
+ */
+protected void
+re_fastaddc(EditLine *el)
+{
+ char c;
+ int rhdiff;
+
+ c = el->el_line.cursor[-1];
+
+ if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
+ re_refresh(el); /* too hard to handle */
+ return;
+ }
+ rhdiff = el->el_term.t_size.h - el->el_cursor.h -
+ el->el_rprompt.p_pos.h;
+ if (el->el_rprompt.p_pos.h && rhdiff < 3) {
+ re_refresh(el); /* clear out rprompt if less than 1 char gap */
+ return;
+ } /* else (only do at end of line, no TAB) */
+ if (iscntrl((unsigned char) c)) { /* if control char, do caret */
+ char mc = (c == '\177') ? '?' : (c | 0100);
+ re_fastputc(el, '^');
+ re_fastputc(el, mc);
+ } else if (isprint((unsigned char) c)) { /* normal char */
+ re_fastputc(el, c);
+ } else {
+ re_fastputc(el, '\\');
+ re_fastputc(el, (int) ((((unsigned int) c >> 6) & 7) + '0'));
+ re_fastputc(el, (int) ((((unsigned int) c >> 3) & 7) + '0'));
+ re_fastputc(el, (c & 7) + '0');
+ }
+ term__flush();
+}
+
+
+/* re_clear_display():
+ * clear the screen buffers so that new new prompt starts fresh.
+ */
+protected void
+re_clear_display(EditLine *el)
+{
+ int i;
+
+ el->el_cursor.v = 0;
+ el->el_cursor.h = 0;
+ for (i = 0; i < el->el_term.t_size.v; i++)
+ el->el_display[i][0] = '\0';
+ el->el_refresh.r_oldcv = 0;
+}
+
+
+/* re_clear_lines():
+ * Make sure all lines are *really* blank
+ */
+protected void
+re_clear_lines(EditLine *el)
+{
+
+ if (EL_CAN_CEOL) {
+ int i;
+ term_move_to_char(el, 0);
+ for (i = 0; i <= el->el_refresh.r_oldcv; i++) {
+ /* for each line on the screen */
+ term_move_to_line(el, i);
+ term_clear_EOL(el, el->el_term.t_size.h);
+ }
+ term_move_to_line(el, 0);
+ } else {
+ term_move_to_line(el, el->el_refresh.r_oldcv);
+ /* go to last line */
+ term__putc('\r'); /* go to BOL */
+ term__putc('\n'); /* go to new line */
+ }
+}
diff --git a/cmd-line-utils/libedit/refresh.h b/cmd-line-utils/libedit/refresh.h
new file mode 100644
index 00000000000..33c0887c1b3
--- /dev/null
+++ b/cmd-line-utils/libedit/refresh.h
@@ -0,0 +1,63 @@
+/* $NetBSD: refresh.h,v 1.4 2001/01/10 07:45:42 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)refresh.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.refresh.h: Screen refresh functions
+ */
+#ifndef _h_el_refresh
+#define _h_el_refresh
+
+#include "histedit.h"
+
+typedef struct {
+ coord_t r_cursor; /* Refresh cursor position */
+ int r_oldcv; /* Vertical locations */
+ int r_newcv;
+} el_refresh_t;
+
+protected void re_putc(EditLine *, int, int);
+protected void re_clear_lines(EditLine *);
+protected void re_clear_display(EditLine *);
+protected void re_refresh(EditLine *);
+protected void re_refresh_cursor(EditLine *);
+protected void re_fastaddc(EditLine *);
+protected void re_goto_bottom(EditLine *);
+
+#endif /* _h_el_refresh */
diff --git a/cmd-line-utils/libedit/search.c b/cmd-line-utils/libedit/search.c
new file mode 100644
index 00000000000..bdc3a1e8bb9
--- /dev/null
+++ b/cmd-line-utils/libedit/search.c
@@ -0,0 +1,646 @@
+/* $NetBSD: search.c,v 1.11 2001/01/23 15:55:31 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * search.c: History and character search functions
+ */
+#include "sys.h"
+#include <stdlib.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if defined(REGEX)
+#include <regex.h>
+#elif defined(REGEXP)
+#include <regexp.h>
+#endif
+#include "el.h"
+
+/*
+ * Adjust cursor in vi mode to include the character under it
+ */
+#define EL_CURSOR(el) \
+ ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
+ ((el)->el_map.current == (el)->el_map.alt)))
+
+/* search_init():
+ * Initialize the search stuff
+ */
+protected int
+search_init(EditLine *el)
+{
+
+ el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ);
+ if (el->el_search.patbuf == NULL)
+ return (-1);
+ el->el_search.patlen = 0;
+ el->el_search.patdir = -1;
+ el->el_search.chacha = '\0';
+ el->el_search.chadir = -1;
+ return (0);
+}
+
+
+/* search_end():
+ * Initialize the search stuff
+ */
+protected void
+search_end(EditLine *el)
+{
+
+ el_free((ptr_t) el->el_search.patbuf);
+ el->el_search.patbuf = NULL;
+}
+
+
+#ifdef REGEXP
+/* regerror():
+ * Handle regular expression errors
+ */
+public void
+/*ARGSUSED*/
+regerror(const char *msg)
+{
+}
+#endif
+
+
+/* el_match():
+ * Return if string matches pattern
+ */
+protected int
+el_match(const char *str, const char *pat)
+{
+#if defined (REGEX)
+ regex_t re;
+ int rv;
+#elif defined (REGEXP)
+ regexp *rp;
+ int rv;
+#else
+ extern char *re_comp(const char *);
+ extern int re_exec(const char *);
+#endif
+
+ if (strstr(str, pat) != NULL)
+ return (1);
+
+#if defined(REGEX)
+ if (regcomp(&re, pat, 0) == 0) {
+ rv = regexec(&re, str, 0, NULL, 0) == 0;
+ regfree(&re);
+ } else {
+ rv = 0;
+ }
+ return (rv);
+#elif defined(REGEXP)
+ if ((re = regcomp(pat)) != NULL) {
+ rv = regexec(re, str);
+ free((ptr_t) re);
+ } else {
+ rv = 0;
+ }
+ return (rv);
+#else
+ if (re_comp(pat) != NULL)
+ return (0);
+ else
+ return (re_exec(str) == 1);
+#endif
+}
+
+
+/* c_hmatch():
+ * return True if the pattern matches the prefix
+ */
+protected int
+c_hmatch(EditLine *el, const char *str)
+{
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
+ el->el_search.patbuf, str);
+#endif /* SDEBUG */
+
+ return (el_match(str, el->el_search.patbuf));
+}
+
+
+/* c_setpat():
+ * Set the history seatch pattern
+ */
+protected void
+c_setpat(EditLine *el)
+{
+ if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
+ el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
+ el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer;
+ if (el->el_search.patlen >= EL_BUFSIZ)
+ el->el_search.patlen = EL_BUFSIZ - 1;
+ if (el->el_search.patlen != 0) {
+ (void) strncpy(el->el_search.patbuf, el->el_line.buffer,
+ el->el_search.patlen);
+ el->el_search.patbuf[el->el_search.patlen] = '\0';
+ } else
+ el->el_search.patlen = strlen(el->el_search.patbuf);
+ }
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "\neventno = %d\n",
+ el->el_history.eventno);
+ (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
+ (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n",
+ el->el_search.patbuf);
+ (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
+ EL_CURSOR(el) - el->el_line.buffer,
+ el->el_line.lastchar - el->el_line.buffer);
+#endif
+}
+
+
+/* ce_inc_search():
+ * Emacs incremental search
+ */
+protected el_action_t
+ce_inc_search(EditLine *el, int dir)
+{
+ static const char STRfwd[] = {'f', 'w', 'd', '\0'},
+ STRbck[] = {'b', 'c', 'k', '\0'};
+ static char pchar = ':';/* ':' = normal, '?' = failed */
+ static char endcmd[2] = {'\0', '\0'};
+ char ch, *ocursor = el->el_line.cursor, oldpchar = pchar;
+ const char *cp;
+
+ el_action_t ret = CC_NORM;
+
+ int ohisteventno = el->el_history.eventno;
+ int oldpatlen = el->el_search.patlen;
+ int newdir = dir;
+ int done, redo;
+
+ if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
+ el->el_search.patlen >= el->el_line.limit)
+ return (CC_ERROR);
+
+ for (;;) {
+
+ if (el->el_search.patlen == 0) { /* first round */
+ pchar = ':';
+#ifdef ANCHOR
+ el->el_search.patbuf[el->el_search.patlen++] = '.';
+ el->el_search.patbuf[el->el_search.patlen++] = '*';
+#endif
+ }
+ done = redo = 0;
+ *el->el_line.lastchar++ = '\n';
+ for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd;
+ *cp; *el->el_line.lastchar++ = *cp++)
+ continue;
+ *el->el_line.lastchar++ = pchar;
+ for (cp = &el->el_search.patbuf[1];
+ cp < &el->el_search.patbuf[el->el_search.patlen];
+ *el->el_line.lastchar++ = *cp++)
+ continue;
+ *el->el_line.lastchar = '\0';
+ re_refresh(el);
+
+ if (el_getc(el, &ch) != 1)
+ return (ed_end_of_file(el, 0));
+
+ switch (el->el_map.current[(unsigned char) ch]) {
+ case ED_INSERT:
+ case ED_DIGIT:
+ if (el->el_search.patlen > EL_BUFSIZ - 3)
+ term_beep(el);
+ else {
+ el->el_search.patbuf[el->el_search.patlen++] =
+ ch;
+ *el->el_line.lastchar++ = ch;
+ *el->el_line.lastchar = '\0';
+ re_refresh(el);
+ }
+ break;
+
+ case EM_INC_SEARCH_NEXT:
+ newdir = ED_SEARCH_NEXT_HISTORY;
+ redo++;
+ break;
+
+ case EM_INC_SEARCH_PREV:
+ newdir = ED_SEARCH_PREV_HISTORY;
+ redo++;
+ break;
+
+ case ED_DELETE_PREV_CHAR:
+ if (el->el_search.patlen > 1)
+ done++;
+ else
+ term_beep(el);
+ break;
+
+ default:
+ switch (ch) {
+ case 0007: /* ^G: Abort */
+ ret = CC_ERROR;
+ done++;
+ break;
+
+ case 0027: /* ^W: Append word */
+ /* No can do if globbing characters in pattern */
+ for (cp = &el->el_search.patbuf[1];; cp++)
+ if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
+ el->el_line.cursor +=
+ el->el_search.patlen - 1;
+ cp = c__next_word(el->el_line.cursor,
+ el->el_line.lastchar, 1,
+ ce__isword);
+ while (el->el_line.cursor < cp &&
+ *el->el_line.cursor != '\n') {
+ if (el->el_search.patlen >
+ EL_BUFSIZ - 3) {
+ term_beep(el);
+ break;
+ }
+ el->el_search.patbuf[el->el_search.patlen++] =
+ *el->el_line.cursor;
+ *el->el_line.lastchar++ =
+ *el->el_line.cursor++;
+ }
+ el->el_line.cursor = ocursor;
+ *el->el_line.lastchar = '\0';
+ re_refresh(el);
+ break;
+ } else if (isglob(*cp)) {
+ term_beep(el);
+ break;
+ }
+ break;
+
+ default: /* Terminate and execute cmd */
+ endcmd[0] = ch;
+ el_push(el, endcmd);
+ /* FALLTHROUGH */
+
+ case 0033: /* ESC: Terminate */
+ ret = CC_REFRESH;
+ done++;
+ break;
+ }
+ break;
+ }
+
+ while (el->el_line.lastchar > el->el_line.buffer &&
+ *el->el_line.lastchar != '\n')
+ *el->el_line.lastchar-- = '\0';
+ *el->el_line.lastchar = '\0';
+
+ if (!done) {
+
+ /* Can't search if unmatched '[' */
+ for (cp = &el->el_search.patbuf[el->el_search.patlen-1],
+ ch = ']';
+ cp > el->el_search.patbuf;
+ cp--)
+ if (*cp == '[' || *cp == ']') {
+ ch = *cp;
+ break;
+ }
+ if (el->el_search.patlen > 1 && ch != '[') {
+ if (redo && newdir == dir) {
+ if (pchar == '?') { /* wrap around */
+ el->el_history.eventno =
+ newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
+ if (hist_get(el) == CC_ERROR)
+ /* el->el_history.event
+ * no was fixed by
+ * first call */
+ (void) hist_get(el);
+ el->el_line.cursor = newdir ==
+ ED_SEARCH_PREV_HISTORY ?
+ el->el_line.lastchar :
+ el->el_line.buffer;
+ } else
+ el->el_line.cursor +=
+ newdir ==
+ ED_SEARCH_PREV_HISTORY ?
+ -1 : 1;
+ }
+#ifdef ANCHOR
+ el->el_search.patbuf[el->el_search.patlen++] =
+ '.';
+ el->el_search.patbuf[el->el_search.patlen++] =
+ '*';
+#endif
+ el->el_search.patbuf[el->el_search.patlen] =
+ '\0';
+ if (el->el_line.cursor < el->el_line.buffer ||
+ el->el_line.cursor > el->el_line.lastchar ||
+ (ret = ce_search_line(el,
+ &el->el_search.patbuf[1],
+ newdir)) == CC_ERROR) {
+ /* avoid c_setpat */
+ el->el_state.lastcmd =
+ (el_action_t) newdir;
+ ret = newdir == ED_SEARCH_PREV_HISTORY ?
+ ed_search_prev_history(el, 0) :
+ ed_search_next_history(el, 0);
+ if (ret != CC_ERROR) {
+ el->el_line.cursor = newdir ==
+ ED_SEARCH_PREV_HISTORY ?
+ el->el_line.lastchar :
+ el->el_line.buffer;
+ (void) ce_search_line(el,
+ &el->el_search.patbuf[1],
+ newdir);
+ }
+ }
+ el->el_search.patbuf[--el->el_search.patlen] =
+ '\0';
+ if (ret == CC_ERROR) {
+ term_beep(el);
+ if (el->el_history.eventno !=
+ ohisteventno) {
+ el->el_history.eventno =
+ ohisteventno;
+ if (hist_get(el) == CC_ERROR)
+ return (CC_ERROR);
+ }
+ el->el_line.cursor = ocursor;
+ pchar = '?';
+ } else {
+ pchar = ':';
+ }
+ }
+ ret = ce_inc_search(el, newdir);
+
+ if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
+ /*
+ * break abort of failed search at last
+ * non-failed
+ */
+ ret = CC_NORM;
+
+ }
+ if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
+ /* restore on normal return or error exit */
+ pchar = oldpchar;
+ el->el_search.patlen = oldpatlen;
+ if (el->el_history.eventno != ohisteventno) {
+ el->el_history.eventno = ohisteventno;
+ if (hist_get(el) == CC_ERROR)
+ return (CC_ERROR);
+ }
+ el->el_line.cursor = ocursor;
+ if (ret == CC_ERROR)
+ re_refresh(el);
+ }
+ if (done || ret != CC_NORM)
+ return (ret);
+ }
+}
+
+
+/* cv_search():
+ * Vi search.
+ */
+protected el_action_t
+cv_search(EditLine *el, int dir)
+{
+ char ch;
+ char tmpbuf[EL_BUFSIZ];
+ int tmplen;
+
+ tmplen = 0;
+#ifdef ANCHOR
+ tmpbuf[tmplen++] = '.';
+ tmpbuf[tmplen++] = '*';
+#endif
+
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+ el->el_search.patdir = dir;
+
+ c_insert(el, 2); /* prompt + '\n' */
+ *el->el_line.cursor++ = '\n';
+ *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
+ re_refresh(el);
+
+#ifdef ANCHOR
+#define LEN 2
+#else
+#define LEN 0
+#endif
+
+ tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
+ ch = tmpbuf[tmplen];
+ tmpbuf[tmplen] = '\0';
+
+ if (tmplen == LEN) {
+ /*
+ * Use the old pattern, but wild-card it.
+ */
+ if (el->el_search.patlen == 0) {
+ el->el_line.buffer[0] = '\0';
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+ re_refresh(el);
+ return (CC_ERROR);
+ }
+#ifdef ANCHOR
+ if (el->el_search.patbuf[0] != '.' &&
+ el->el_search.patbuf[0] != '*') {
+ (void) strncpy(tmpbuf, el->el_search.patbuf,
+ sizeof(tmpbuf) - 1);
+ el->el_search.patbuf[0] = '.';
+ el->el_search.patbuf[1] = '*';
+ (void) strncpy(&el->el_search.patbuf[2], tmpbuf,
+ EL_BUFSIZ - 3);
+ el->el_search.patlen++;
+ el->el_search.patbuf[el->el_search.patlen++] = '.';
+ el->el_search.patbuf[el->el_search.patlen++] = '*';
+ el->el_search.patbuf[el->el_search.patlen] = '\0';
+ }
+#endif
+ } else {
+#ifdef ANCHOR
+ tmpbuf[tmplen++] = '.';
+ tmpbuf[tmplen++] = '*';
+#endif
+ tmpbuf[tmplen] = '\0';
+ (void) strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
+ el->el_search.patlen = tmplen;
+ }
+ el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
+ el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
+ if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
+ ed_search_next_history(el, 0)) == CC_ERROR) {
+ re_refresh(el);
+ return (CC_ERROR);
+ } else {
+ if (ch == 0033) {
+ re_refresh(el);
+ *el->el_line.lastchar++ = '\n';
+ *el->el_line.lastchar = '\0';
+ re_goto_bottom(el);
+ return (CC_NEWLINE);
+ } else
+ return (CC_REFRESH);
+ }
+}
+
+
+/* ce_search_line():
+ * Look for a pattern inside a line
+ */
+protected el_action_t
+ce_search_line(EditLine *el, char *pattern, int dir)
+{
+ char *cp;
+
+ if (dir == ED_SEARCH_PREV_HISTORY) {
+ for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--)
+ if (el_match(cp, pattern)) {
+ el->el_line.cursor = cp;
+ return (CC_NORM);
+ }
+ return (CC_ERROR);
+ } else {
+ for (cp = el->el_line.cursor; *cp != '\0' &&
+ cp < el->el_line.limit; cp++)
+ if (el_match(cp, pattern)) {
+ el->el_line.cursor = cp;
+ return (CC_NORM);
+ }
+ return (CC_ERROR);
+ }
+}
+
+
+/* cv_repeat_srch():
+ * Vi repeat search
+ */
+protected el_action_t
+cv_repeat_srch(EditLine *el, int c)
+{
+
+#ifdef SDEBUG
+ (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
+ c, el->el_search.patlen, el->el_search.patbuf);
+#endif
+
+ el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
+ el->el_line.lastchar = el->el_line.buffer;
+
+ switch (c) {
+ case ED_SEARCH_NEXT_HISTORY:
+ return (ed_search_next_history(el, 0));
+ case ED_SEARCH_PREV_HISTORY:
+ return (ed_search_prev_history(el, 0));
+ default:
+ return (CC_ERROR);
+ }
+}
+
+
+/* cv_csearch_back():
+ * Vi character search reverse
+ */
+protected el_action_t
+cv_csearch_back(EditLine *el, int ch, int count, int tflag)
+{
+ char *cp;
+
+ cp = el->el_line.cursor;
+ while (count--) {
+ if (*cp == ch)
+ cp--;
+ while (cp > el->el_line.buffer && *cp != ch)
+ cp--;
+ }
+
+ if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
+ return (CC_ERROR);
+
+ if (*cp == ch && tflag)
+ cp++;
+
+ el->el_line.cursor = cp;
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ re_refresh_cursor(el);
+ return (CC_NORM);
+}
+
+
+/* cv_csearch_fwd():
+ * Vi character search forward
+ */
+protected el_action_t
+cv_csearch_fwd(EditLine *el, int ch, int count, int tflag)
+{
+ char *cp;
+
+ cp = el->el_line.cursor;
+ while (count--) {
+ if (*cp == ch)
+ cp++;
+ while (cp < el->el_line.lastchar && *cp != ch)
+ cp++;
+ }
+
+ if (cp >= el->el_line.lastchar)
+ return (CC_ERROR);
+
+ if (*cp == ch && tflag)
+ cp--;
+
+ el->el_line.cursor = cp;
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ re_refresh_cursor(el);
+ return (CC_NORM);
+}
diff --git a/cmd-line-utils/libedit/search.h b/cmd-line-utils/libedit/search.h
new file mode 100644
index 00000000000..676bbe2e35b
--- /dev/null
+++ b/cmd-line-utils/libedit/search.h
@@ -0,0 +1,70 @@
+/* $NetBSD: search.h,v 1.5 2000/09/04 22:06:32 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)search.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.search.h: Line and history searching utilities
+ */
+#ifndef _h_el_search
+#define _h_el_search
+
+#include "histedit.h"
+
+typedef struct el_search_t {
+ char *patbuf; /* The pattern buffer */
+ size_t patlen; /* Length of the pattern buffer */
+ int patdir; /* Direction of the last search */
+ int chadir; /* Character search direction */
+ char chacha; /* Character we are looking for */
+} el_search_t;
+
+
+protected int el_match(const char *, const char *);
+protected int search_init(EditLine *);
+protected void search_end(EditLine *);
+protected int c_hmatch(EditLine *, const char *);
+protected void c_setpat(EditLine *);
+protected el_action_t ce_inc_search(EditLine *, int);
+protected el_action_t cv_search(EditLine *, int);
+protected el_action_t ce_search_line(EditLine *, char *, int);
+protected el_action_t cv_repeat_srch(EditLine *, int);
+protected el_action_t cv_csearch_back(EditLine *, int, int, int);
+protected el_action_t cv_csearch_fwd(EditLine *, int, int, int);
+
+#endif /* _h_el_search */
diff --git a/cmd-line-utils/libedit/sig.c b/cmd-line-utils/libedit/sig.c
new file mode 100644
index 00000000000..19408a0a8f2
--- /dev/null
+++ b/cmd-line-utils/libedit/sig.c
@@ -0,0 +1,192 @@
+/* $NetBSD: sig.c,v 1.8 2001/01/09 17:31:04 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * sig.c: Signal handling stuff.
+ * our policy is to trap all signals, set a good state
+ * and pass the ball to our caller.
+ */
+#include "sys.h"
+#include "el.h"
+#include <stdlib.h>
+
+private EditLine *sel = NULL;
+
+private const int sighdl[] = {
+#define _DO(a) (a),
+ ALLSIGS
+#undef _DO
+ - 1
+};
+
+private void sig_handler(int);
+
+/* sig_handler():
+ * This is the handler called for all signals
+ * XXX: we cannot pass any data so we just store the old editline
+ * state in a private variable
+ */
+private void
+sig_handler(int signo)
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+ (void) sigaddset(&nset, signo);
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ switch (signo) {
+ case SIGCONT:
+ tty_rawmode(sel);
+ if (ed_redisplay(sel, 0) == CC_REFRESH)
+ re_refresh(sel);
+ term__flush();
+ break;
+
+ case SIGWINCH:
+ el_resize(sel);
+ break;
+
+ default:
+ tty_cookedmode(sel);
+ break;
+ }
+
+ for (i = 0; sighdl[i] != -1; i++)
+ if (signo == sighdl[i])
+ break;
+
+ (void) signal(signo, sel->el_signal[i]);
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+ (void) kill(0, signo);
+}
+
+
+/* sig_init():
+ * Initialize all signal stuff
+ */
+protected int
+sig_init(EditLine *el)
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+#define _DO(a) (void) sigaddset(&nset, a);
+ ALLSIGS
+#undef _DO
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
+
+ el->el_signal = (sig_t *) el_malloc(SIGSIZE);
+ if (el->el_signal == NULL)
+ return (-1);
+ for (i = 0; sighdl[i] != -1; i++)
+ el->el_signal[i] = SIG_ERR;
+
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ return (0);
+}
+
+
+/* sig_end():
+ * Clear all signal stuff
+ */
+protected void
+sig_end(EditLine *el)
+{
+
+ el_free((ptr_t) el->el_signal);
+ el->el_signal = NULL;
+}
+
+
+/* sig_set():
+ * set all the signal handlers
+ */
+protected void
+sig_set(EditLine *el)
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+#define _DO(a) (void) sigaddset(&nset, a);
+ ALLSIGS
+#undef _DO
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ for (i = 0; sighdl[i] != -1; i++) {
+ sig_t s;
+ /* This could happen if we get interrupted */
+ if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
+ el->el_signal[i] = s;
+ }
+ sel = el;
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+
+/* sig_clr():
+ * clear all the signal handlers
+ */
+protected void
+sig_clr(EditLine *el)
+{
+ int i;
+ sigset_t nset, oset;
+
+ (void) sigemptyset(&nset);
+#define _DO(a) (void) sigaddset(&nset, a);
+ ALLSIGS
+#undef _DO
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ for (i = 0; sighdl[i] != -1; i++)
+ if (el->el_signal[i] != SIG_ERR)
+ (void) signal(sighdl[i], el->el_signal[i]);
+
+ sel = NULL; /* we are going to die if the handler is
+ * called */
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+}
diff --git a/cmd-line-utils/libedit/sig.h b/cmd-line-utils/libedit/sig.h
new file mode 100644
index 00000000000..e7231b65cf4
--- /dev/null
+++ b/cmd-line-utils/libedit/sig.h
@@ -0,0 +1,72 @@
+/* $NetBSD: sig.h,v 1.3 2000/09/04 22:06:32 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sig.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.sig.h: Signal handling functions
+ */
+#ifndef _h_el_sig
+#define _h_el_sig
+
+#include <signal.h>
+
+#include "histedit.h"
+
+/*
+ * Define here all the signals we are going to handle
+ * The _DO macro is used to iterate in the source code
+ */
+#define ALLSIGS \
+ _DO(SIGINT) \
+ _DO(SIGTSTP) \
+ _DO(SIGSTOP) \
+ _DO(SIGQUIT) \
+ _DO(SIGHUP) \
+ _DO(SIGTERM) \
+ _DO(SIGCONT) \
+ _DO(SIGWINCH)
+
+typedef sig_t *el_signal_t;
+
+protected void sig_end(EditLine*);
+protected int sig_init(EditLine*);
+protected void sig_set(EditLine*);
+protected void sig_clr(EditLine*);
+
+#endif /* _h_el_sig */
diff --git a/cmd-line-utils/libedit/strlcpy.c b/cmd-line-utils/libedit/strlcpy.c
new file mode 100644
index 00000000000..74317d99cd2
--- /dev/null
+++ b/cmd-line-utils/libedit/strlcpy.c
@@ -0,0 +1,28 @@
+#include <string.h>
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t size)
+{
+ if(size) {
+ strncpy(dst, src, size-1);
+ dst[size-1] = '\0';
+ } else {
+ dst[0] = '\0';
+ }
+ return strlen(src);
+}
+
+size_t strlcat(char *dst, const char *src, size_t size)
+{
+ int dl = strlen(dst);
+ int sz = size-dl-1;
+
+ if(sz >= 0) {
+ strncat(dst, src, sz);
+ dst[sz] = '\0';
+ }
+
+ return dl+strlen(src);
+}
+
+#endif
diff --git a/cmd-line-utils/libedit/strlcpy.h b/cmd-line-utils/libedit/strlcpy.h
new file mode 100644
index 00000000000..e4d3a7ffa3f
--- /dev/null
+++ b/cmd-line-utils/libedit/strlcpy.h
@@ -0,0 +1,2 @@
+size_t strlcpy(char *dst, const char *src, size_t size);
+size_t strlcat(char *dst, const char *src, size_t size);
diff --git a/cmd-line-utils/libedit/sys.h b/cmd-line-utils/libedit/sys.h
new file mode 100644
index 00000000000..d9007243456
--- /dev/null
+++ b/cmd-line-utils/libedit/sys.h
@@ -0,0 +1,94 @@
+/* $NetBSD: sys.h,v 1.4 2000/09/04 22:06:32 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sys.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * sys.h: Put all the stupid compiler and system dependencies here...
+ */
+#ifndef _h_sys
+#define _h_sys
+
+#ifndef public
+# define public /* Externally visible functions/variables */
+#endif
+
+#ifndef private
+# define private static /* Always hidden internals */
+#endif
+
+#ifndef protected
+# define protected /* Redefined from elsewhere to "static" */
+ /* When we want to hide everything */
+#endif
+
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+#ifndef _PTR_T
+# define _PTR_T
+typedef void *ptr_t;
+#endif
+
+#ifndef _IOCTL_T
+# define _IOCTL_T
+typedef void *ioctl_t;
+#endif
+
+#include <stdio.h>
+
+#define REGEX /* Use POSIX.2 regular expression functions */
+#undef REGEXP /* Use UNIX V8 regular expression functions */
+
+#if defined(__sun__) && defined(__SVR4)
+# undef REGEX
+# undef REGEXP
+# include <malloc.h>
+typedef void (*sig_t)(int);
+#endif
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+#endif /* _h_sys */
diff --git a/cmd-line-utils/libedit/term.c b/cmd-line-utils/libedit/term.c
new file mode 100644
index 00000000000..df8d1ea67cc
--- /dev/null
+++ b/cmd-line-utils/libedit/term.c
@@ -0,0 +1,1564 @@
+/* $NetBSD: term.c,v 1.32 2001/01/23 15:55:31 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * term.c: Editor/termcap-curses interface
+ * We have to declare a static variable here, since the
+ * termcap putchar routine does not take an argument!
+ */
+#include "sys.h"
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termcap.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include "el.h"
+
+/*
+ * IMPORTANT NOTE: these routines are allowed to look at the current screen
+ * and the current possition assuming that it is correct. If this is not
+ * true, then the update will be WRONG! This is (should be) a valid
+ * assumption...
+ */
+
+#define TC_BUFSIZE 2048
+
+#define GoodStr(a) (el->el_term.t_str[a] != NULL && \
+ el->el_term.t_str[a][0] != '\0')
+#define Str(a) el->el_term.t_str[a]
+#define Val(a) el->el_term.t_val[a]
+
+#ifdef notdef
+private const struct {
+ const char *b_name;
+ int b_rate;
+} baud_rate[] = {
+#ifdef B0
+ { "0", B0 },
+#endif
+#ifdef B50
+ { "50", B50 },
+#endif
+#ifdef B75
+ { "75", B75 },
+#endif
+#ifdef B110
+ { "110", B110 },
+#endif
+#ifdef B134
+ { "134", B134 },
+#endif
+#ifdef B150
+ { "150", B150 },
+#endif
+#ifdef B200
+ { "200", B200 },
+#endif
+#ifdef B300
+ { "300", B300 },
+#endif
+#ifdef B600
+ { "600", B600 },
+#endif
+#ifdef B900
+ { "900", B900 },
+#endif
+#ifdef B1200
+ { "1200", B1200 },
+#endif
+#ifdef B1800
+ { "1800", B1800 },
+#endif
+#ifdef B2400
+ { "2400", B2400 },
+#endif
+#ifdef B3600
+ { "3600", B3600 },
+#endif
+#ifdef B4800
+ { "4800", B4800 },
+#endif
+#ifdef B7200
+ { "7200", B7200 },
+#endif
+#ifdef B9600
+ { "9600", B9600 },
+#endif
+#ifdef EXTA
+ { "19200", EXTA },
+#endif
+#ifdef B19200
+ { "19200", B19200 },
+#endif
+#ifdef EXTB
+ { "38400", EXTB },
+#endif
+#ifdef B38400
+ { "38400", B38400 },
+#endif
+ { NULL, 0 }
+};
+#endif
+
+private const struct termcapstr {
+ const char *name;
+ const char *long_name;
+} tstr[] = {
+#define T_al 0
+ { "al", "add new blank line" },
+#define T_bl 1
+ { "bl", "audible bell" },
+#define T_cd 2
+ { "cd", "clear to bottom" },
+#define T_ce 3
+ { "ce", "clear to end of line" },
+#define T_ch 4
+ { "ch", "cursor to horiz pos" },
+#define T_cl 5
+ { "cl", "clear screen" },
+#define T_dc 6
+ { "dc", "delete a character" },
+#define T_dl 7
+ { "dl", "delete a line" },
+#define T_dm 8
+ { "dm", "start delete mode" },
+#define T_ed 9
+ { "ed", "end delete mode" },
+#define T_ei 10
+ { "ei", "end insert mode" },
+#define T_fs 11
+ { "fs", "cursor from status line" },
+#define T_ho 12
+ { "ho", "home cursor" },
+#define T_ic 13
+ { "ic", "insert character" },
+#define T_im 14
+ { "im", "start insert mode" },
+#define T_ip 15
+ { "ip", "insert padding" },
+#define T_kd 16
+ { "kd", "sends cursor down" },
+#define T_kl 17
+ { "kl", "sends cursor left" },
+#define T_kr 18
+ { "kr", "sends cursor right" },
+#define T_ku 19
+ { "ku", "sends cursor up" },
+#define T_md 20
+ { "md", "begin bold" },
+#define T_me 21
+ { "me", "end attributes" },
+#define T_nd 22
+ { "nd", "non destructive space" },
+#define T_se 23
+ { "se", "end standout" },
+#define T_so 24
+ { "so", "begin standout" },
+#define T_ts 25
+ { "ts", "cursor to status line" },
+#define T_up 26
+ { "up", "cursor up one" },
+#define T_us 27
+ { "us", "begin underline" },
+#define T_ue 28
+ { "ue", "end underline" },
+#define T_vb 29
+ { "vb", "visible bell" },
+#define T_DC 30
+ { "DC", "delete multiple chars" },
+#define T_DO 31
+ { "DO", "cursor down multiple" },
+#define T_IC 32
+ { "IC", "insert multiple chars" },
+#define T_LE 33
+ { "LE", "cursor left multiple" },
+#define T_RI 34
+ { "RI", "cursor right multiple" },
+#define T_UP 35
+ { "UP", "cursor up multiple" },
+#define T_kh 36
+ { "kh", "send cursor home" },
+#define T_at7 37
+ { "@7", "send cursor end" },
+#define T_str 38
+ { NULL, NULL }
+};
+
+private const struct termcapval {
+ const char *name;
+ const char *long_name;
+} tval[] = {
+#define T_am 0
+ { "am", "has automatic margins" },
+#define T_pt 1
+ { "pt", "has physical tabs" },
+#define T_li 2
+ { "li", "Number of lines" },
+#define T_co 3
+ { "co", "Number of columns" },
+#define T_km 4
+ { "km", "Has meta key" },
+#define T_xt 5
+ { "xt", "Tab chars destructive" },
+#define T_xn 6
+ { "xn", "newline ignored at right margin" },
+#define T_MT 7
+ { "MT", "Has meta key" }, /* XXX? */
+#define T_val 8
+ { NULL, NULL, }
+};
+/* do two or more of the attributes use me */
+
+private void term_setflags(EditLine *);
+private int term_rebuffer_display(EditLine *);
+private void term_free_display(EditLine *);
+private int term_alloc_display(EditLine *);
+private void term_alloc(EditLine *, const struct termcapstr *, const char *);
+private void term_init_arrow(EditLine *);
+private void term_reset_arrow(EditLine *);
+
+
+private FILE *term_outfile = NULL; /* XXX: How do we fix that? */
+
+
+/* term_setflags():
+ * Set the terminal capability flags
+ */
+private void
+term_setflags(EditLine *el)
+{
+ EL_FLAGS = 0;
+ if (el->el_tty.t_tabs)
+ EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0;
+
+ EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0;
+ EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0;
+ EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0;
+ EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ?
+ TERM_CAN_INSERT : 0;
+ EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0;
+ EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0;
+ EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0;
+
+ if (GoodStr(T_me) && GoodStr(T_ue))
+ EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ?
+ TERM_CAN_ME : 0;
+ else
+ EL_FLAGS &= ~TERM_CAN_ME;
+ if (GoodStr(T_me) && GoodStr(T_se))
+ EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ?
+ TERM_CAN_ME : 0;
+
+
+#ifdef DEBUG_SCREEN
+ if (!EL_CAN_UP) {
+ (void) fprintf(el->el_errfile,
+ "WARNING: Your terminal cannot move up.\n");
+ (void) fprintf(el->el_errfile,
+ "Editing may be odd for long lines.\n");
+ }
+ if (!EL_CAN_CEOL)
+ (void) fprintf(el->el_errfile, "no clear EOL capability.\n");
+ if (!EL_CAN_DELETE)
+ (void) fprintf(el->el_errfile, "no delete char capability.\n");
+ if (!EL_CAN_INSERT)
+ (void) fprintf(el->el_errfile, "no insert char capability.\n");
+#endif /* DEBUG_SCREEN */
+}
+
+
+/* term_init():
+ * Initialize the terminal stuff
+ */
+protected int
+term_init(EditLine *el)
+{
+
+ el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE);
+ if (el->el_term.t_buf == NULL)
+ return (-1);
+ el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE);
+ if (el->el_term.t_cap == NULL)
+ return (-1);
+ el->el_term.t_fkey = (fkey_t *) el_malloc(A_K_NKEYS * sizeof(fkey_t));
+ if (el->el_term.t_fkey == NULL)
+ return (-1);
+ el->el_term.t_loc = 0;
+ el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char *));
+ if (el->el_term.t_str == NULL)
+ return (-1);
+ (void) memset(el->el_term.t_str, 0, T_str * sizeof(char *));
+ el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int));
+ if (el->el_term.t_val == NULL)
+ return (-1);
+ (void) memset(el->el_term.t_val, 0, T_val * sizeof(int));
+ term_outfile = el->el_outfile;
+ if (term_set(el, NULL) == -1)
+ return (-1);
+ term_init_arrow(el);
+ return (0);
+}
+/* term_end():
+ * Clean up the terminal stuff
+ */
+protected void
+term_end(EditLine *el)
+{
+
+ el_free((ptr_t) el->el_term.t_buf);
+ el->el_term.t_buf = NULL;
+ el_free((ptr_t) el->el_term.t_cap);
+ el->el_term.t_cap = NULL;
+ el->el_term.t_loc = 0;
+ el_free((ptr_t) el->el_term.t_str);
+ el->el_term.t_str = NULL;
+ el_free((ptr_t) el->el_term.t_val);
+ el->el_term.t_val = NULL;
+ term_free_display(el);
+}
+
+
+/* term_alloc():
+ * Maintain a string pool for termcap strings
+ */
+private void
+term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
+{
+ char termbuf[TC_BUFSIZE];
+ int tlen, clen;
+ char **tlist = el->el_term.t_str;
+ char **tmp, **str = &tlist[t - tstr];
+
+ if (cap == NULL || *cap == '\0') {
+ *str = NULL;
+ return;
+ } else
+ clen = strlen(cap);
+
+ tlen = *str == NULL ? 0 : strlen(*str);
+
+ /*
+ * New string is shorter; no need to allocate space
+ */
+ if (clen <= tlen) {
+ (void) strcpy(*str, cap); /* XXX strcpy is safe */
+ return;
+ }
+ /*
+ * New string is longer; see if we have enough space to append
+ */
+ if (el->el_term.t_loc + 3 < TC_BUFSIZE) {
+ /* XXX strcpy is safe */
+ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc],
+ cap);
+ el->el_term.t_loc += clen + 1; /* one for \0 */
+ return;
+ }
+ /*
+ * Compact our buffer; no need to check compaction, cause we know it
+ * fits...
+ */
+ tlen = 0;
+ for (tmp = tlist; tmp < &tlist[T_str]; tmp++)
+ if (*tmp != NULL && *tmp != '\0' && *tmp != *str) {
+ char *ptr;
+
+ for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++)
+ continue;
+ termbuf[tlen++] = '\0';
+ }
+ memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE);
+ el->el_term.t_loc = tlen;
+ if (el->el_term.t_loc + 3 >= TC_BUFSIZE) {
+ (void) fprintf(el->el_errfile,
+ "Out of termcap string space.\n");
+ return;
+ }
+ /* XXX strcpy is safe */
+ (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
+ el->el_term.t_loc += clen + 1; /* one for \0 */
+ return;
+}
+
+
+/* term_rebuffer_display():
+ * Rebuffer the display after the screen changed size
+ */
+private int
+term_rebuffer_display(EditLine *el)
+{
+ coord_t *c = &el->el_term.t_size;
+
+ term_free_display(el);
+
+ c->h = Val(T_co);
+ c->v = Val(T_li);
+
+ if (term_alloc_display(el) == -1)
+ return (-1);
+ return (0);
+}
+
+
+/* term_alloc_display():
+ * Allocate a new display.
+ */
+private int
+term_alloc_display(EditLine *el)
+{
+ int i;
+ char **b;
+ coord_t *c = &el->el_term.t_size;
+
+ b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
+ if (b == NULL)
+ return (-1);
+ for (i = 0; i < c->v; i++) {
+ b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
+ if (b[i] == NULL)
+ return (-1);
+ }
+ b[c->v] = NULL;
+ el->el_display = b;
+
+ b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
+ if (b == NULL)
+ return (-1);
+ for (i = 0; i < c->v; i++) {
+ b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
+ if (b[i] == NULL)
+ return (-1);
+ }
+ b[c->v] = NULL;
+ el->el_vdisplay = b;
+ return (0);
+}
+
+
+/* term_free_display():
+ * Free the display buffers
+ */
+private void
+term_free_display(EditLine *el)
+{
+ char **b;
+ char **bufp;
+
+ b = el->el_display;
+ el->el_display = NULL;
+ if (b != NULL) {
+ for (bufp = b; *bufp != NULL; bufp++)
+ el_free((ptr_t) * bufp);
+ el_free((ptr_t) b);
+ }
+ b = el->el_vdisplay;
+ el->el_vdisplay = NULL;
+ if (b != NULL) {
+ for (bufp = b; *bufp != NULL; bufp++)
+ el_free((ptr_t) * bufp);
+ el_free((ptr_t) b);
+ }
+}
+
+
+/* term_move_to_line():
+ * move to line <where> (first line == 0)
+ * as efficiently as possible
+ */
+protected void
+term_move_to_line(EditLine *el, int where)
+{
+ int del;
+
+ if (where == el->el_cursor.v)
+ return;
+
+ if (where > el->el_term.t_size.v) {
+#ifdef DEBUG_SCREEN
+ (void) fprintf(el->el_errfile,
+ "term_move_to_line: where is ridiculous: %d\r\n", where);
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+ if ((del = where - el->el_cursor.v) > 0) {
+ while (del > 0) {
+ if (EL_HAS_AUTO_MARGINS &&
+ el->el_display[el->el_cursor.v][0] != '\0') {
+ /* move without newline */
+ term_move_to_char(el, el->el_term.t_size.h - 1);
+ term_overwrite(el,
+ &el->el_display[el->el_cursor.v][el->el_cursor.h],
+ 1);
+ /* updates Cursor */
+ del--;
+ } else {
+ if ((del > 1) && GoodStr(T_DO)) {
+ (void) tputs(tgoto(Str(T_DO), del, del),
+ del, term__putc);
+ del = 0;
+ } else {
+ for (; del > 0; del--)
+ term__putc('\n');
+ /* because the \n will become \r\n */
+ el->el_cursor.h = 0;
+ }
+ }
+ }
+ } else { /* del < 0 */
+ if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
+ (void) tputs(tgoto(Str(T_UP), -del, -del), -del,
+ term__putc);
+ else {
+ if (GoodStr(T_up))
+ for (; del < 0; del++)
+ (void) tputs(Str(T_up), 1, term__putc);
+ }
+ }
+ el->el_cursor.v = where;/* now where is here */
+}
+
+
+/* term_move_to_char():
+ * Move to the character position specified
+ */
+protected void
+term_move_to_char(EditLine *el, int where)
+{
+ int del, i;
+
+mc_again:
+ if (where == el->el_cursor.h)
+ return;
+
+ if (where > el->el_term.t_size.h) {
+#ifdef DEBUG_SCREEN
+ (void) fprintf(el->el_errfile,
+ "term_move_to_char: where is riduculous: %d\r\n", where);
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+ if (!where) { /* if where is first column */
+ term__putc('\r'); /* do a CR */
+ el->el_cursor.h = 0;
+ return;
+ }
+ del = where - el->el_cursor.h;
+
+ if ((del < -4 || del > 4) && GoodStr(T_ch))
+ /* go there directly */
+ (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc);
+ else {
+ if (del > 0) { /* moving forward */
+ if ((del > 4) && GoodStr(T_RI))
+ (void) tputs(tgoto(Str(T_RI), del, del),
+ del, term__putc);
+ else {
+ /* if I can do tabs, use them */
+ if (EL_CAN_TAB) {
+ if ((el->el_cursor.h & 0370) !=
+ (where & 0370)) {
+ /* if not within tab stop */
+ for (i =
+ (el->el_cursor.h & 0370);
+ i < (where & 0370);
+ i += 8)
+ term__putc('\t');
+ /* then tab over */
+ el->el_cursor.h = where & 0370;
+ }
+ }
+ /*
+ * it's usually cheaper to just write the
+ * chars, so we do.
+ */
+ /*
+ * NOTE THAT term_overwrite() WILL CHANGE
+ * el->el_cursor.h!!!
+ */
+ term_overwrite(el,
+ &el->el_display[el->el_cursor.v][el->el_cursor.h],
+ where - el->el_cursor.h);
+
+ }
+ } else { /* del < 0 := moving backward */
+ if ((-del > 4) && GoodStr(T_LE))
+ (void) tputs(tgoto(Str(T_LE), -del, -del),
+ -del, term__putc);
+ else { /* can't go directly there */
+ /*
+ * if the "cost" is greater than the "cost"
+ * from col 0
+ */
+ if (EL_CAN_TAB ?
+ ((unsigned int)-del > (((unsigned int) where >> 3) +
+ (where & 07)))
+ : (-del > where)) {
+ term__putc('\r'); /* do a CR */
+ el->el_cursor.h = 0;
+ goto mc_again; /* and try again */
+ }
+ for (i = 0; i < -del; i++)
+ term__putc('\b');
+ }
+ }
+ }
+ el->el_cursor.h = where; /* now where is here */
+}
+
+
+/* term_overwrite():
+ * Overstrike num characters
+ */
+protected void
+term_overwrite(EditLine *el, const char *cp, int n)
+{
+ if (n <= 0)
+ return; /* catch bugs */
+
+ if (n > el->el_term.t_size.h) {
+#ifdef DEBUG_SCREEN
+ (void) fprintf(el->el_errfile,
+ "term_overwrite: n is riduculous: %d\r\n", n);
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+ do {
+ term__putc(*cp++);
+ el->el_cursor.h++;
+ } while (--n);
+
+ if (el->el_cursor.h >= el->el_term.t_size.h) { /* wrap? */
+ if (EL_HAS_AUTO_MARGINS) { /* yes */
+ el->el_cursor.h = 0;
+ el->el_cursor.v++;
+ if (EL_HAS_MAGIC_MARGINS) {
+ /* force the wrap to avoid the "magic"
+ * situation */
+ char c;
+ if ((c = el->el_display[el->el_cursor.v][el->el_cursor.h])
+ != '\0')
+ term_overwrite(el, &c, 1);
+ else
+ term__putc(' ');
+ el->el_cursor.h = 1;
+ }
+ } else /* no wrap, but cursor stays on screen */
+ el->el_cursor.h = el->el_term.t_size.h;
+ }
+}
+
+
+/* term_deletechars():
+ * Delete num characters
+ */
+protected void
+term_deletechars(EditLine *el, int num)
+{
+ if (num <= 0)
+ return;
+
+ if (!EL_CAN_DELETE) {
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile, " ERROR: cannot delete \n");
+#endif /* DEBUG_EDIT */
+ return;
+ }
+ if (num > el->el_term.t_size.h) {
+#ifdef DEBUG_SCREEN
+ (void) fprintf(el->el_errfile,
+ "term_deletechars: num is riduculous: %d\r\n", num);
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+ if (GoodStr(T_DC)) /* if I have multiple delete */
+ if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more
+ * expen. */
+ (void) tputs(tgoto(Str(T_DC), num, num),
+ num, term__putc);
+ return;
+ }
+ if (GoodStr(T_dm)) /* if I have delete mode */
+ (void) tputs(Str(T_dm), 1, term__putc);
+
+ if (GoodStr(T_dc)) /* else do one at a time */
+ while (num--)
+ (void) tputs(Str(T_dc), 1, term__putc);
+
+ if (GoodStr(T_ed)) /* if I have delete mode */
+ (void) tputs(Str(T_ed), 1, term__putc);
+}
+
+
+/* term_insertwrite():
+ * Puts terminal in insert character mode or inserts num
+ * characters in the line
+ */
+protected void
+term_insertwrite(EditLine *el, char *cp, int num)
+{
+ if (num <= 0)
+ return;
+ if (!EL_CAN_INSERT) {
+#ifdef DEBUG_EDIT
+ (void) fprintf(el->el_errfile, " ERROR: cannot insert \n");
+#endif /* DEBUG_EDIT */
+ return;
+ }
+ if (num > el->el_term.t_size.h) {
+#ifdef DEBUG_SCREEN
+ (void) fprintf(el->el_errfile,
+ "StartInsert: num is riduculous: %d\r\n", num);
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+ if (GoodStr(T_IC)) /* if I have multiple insert */
+ if ((num > 1) || !GoodStr(T_ic)) {
+ /* if ic would be more expensive */
+ (void) tputs(tgoto(Str(T_IC), num, num),
+ num, term__putc);
+ term_overwrite(el, cp, num);
+ /* this updates el_cursor.h */
+ return;
+ }
+ if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */
+ (void) tputs(Str(T_im), 1, term__putc);
+
+ el->el_cursor.h += num;
+ do
+ term__putc(*cp++);
+ while (--num);
+
+ if (GoodStr(T_ip)) /* have to make num chars insert */
+ (void) tputs(Str(T_ip), 1, term__putc);
+
+ (void) tputs(Str(T_ei), 1, term__putc);
+ return;
+ }
+ do {
+ if (GoodStr(T_ic)) /* have to make num chars insert */
+ (void) tputs(Str(T_ic), 1, term__putc);
+ /* insert a char */
+
+ term__putc(*cp++);
+
+ el->el_cursor.h++;
+
+ if (GoodStr(T_ip)) /* have to make num chars insert */
+ (void) tputs(Str(T_ip), 1, term__putc);
+ /* pad the inserted char */
+
+ } while (--num);
+}
+
+
+/* term_clear_EOL():
+ * clear to end of line. There are num characters to clear
+ */
+protected void
+term_clear_EOL(EditLine *el, int num)
+{
+ int i;
+
+ if (EL_CAN_CEOL && GoodStr(T_ce))
+ (void) tputs(Str(T_ce), 1, term__putc);
+ else {
+ for (i = 0; i < num; i++)
+ term__putc(' ');
+ el->el_cursor.h += num; /* have written num spaces */
+ }
+}
+
+
+/* term_clear_screen():
+ * Clear the screen
+ */
+protected void
+term_clear_screen(EditLine *el)
+{ /* clear the whole screen and home */
+
+ if (GoodStr(T_cl))
+ /* send the clear screen code */
+ (void) tputs(Str(T_cl), Val(T_li), term__putc);
+ else if (GoodStr(T_ho) && GoodStr(T_cd)) {
+ (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */
+ /* clear to bottom of screen */
+ (void) tputs(Str(T_cd), Val(T_li), term__putc);
+ } else {
+ term__putc('\r');
+ term__putc('\n');
+ }
+}
+
+
+/* term_beep():
+ * Beep the way the terminal wants us
+ */
+protected void
+term_beep(EditLine *el)
+{
+ if (GoodStr(T_bl))
+ /* what termcap says we should use */
+ (void) tputs(Str(T_bl), 1, term__putc);
+ else
+ term__putc('\007'); /* an ASCII bell; ^G */
+}
+
+
+#ifdef notdef
+/* term_clear_to_bottom():
+ * Clear to the bottom of the screen
+ */
+protected void
+term_clear_to_bottom(EditLine *el)
+{
+ if (GoodStr(T_cd))
+ (void) tputs(Str(T_cd), Val(T_li), term__putc);
+ else if (GoodStr(T_ce))
+ (void) tputs(Str(T_ce), Val(T_li), term__putc);
+}
+#endif
+
+
+/* term_set():
+ * Read in the terminal capabilities from the requested terminal
+ */
+protected int
+term_set(EditLine *el, const char *term)
+{
+ int i;
+ char buf[TC_BUFSIZE];
+ char *area;
+ const struct termcapstr *t;
+ sigset_t oset, nset;
+ int lins, cols;
+
+ (void) sigemptyset(&nset);
+ (void) sigaddset(&nset, SIGWINCH);
+ (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ area = buf;
+
+
+ if (term == NULL)
+ term = getenv("TERM");
+
+ if (!term || !term[0])
+ term = "dumb";
+
+ if (strcmp(term, "emacs") == 0)
+ el->el_flags |= EDIT_DISABLED;
+
+ memset(el->el_term.t_cap, 0, TC_BUFSIZE);
+
+ i = tgetent(el->el_term.t_cap, term);
+
+ if (i <= 0) {
+ if (i == -1)
+ (void) fprintf(el->el_errfile,
+ "Cannot read termcap database;\n");
+ else if (i == 0)
+ (void) fprintf(el->el_errfile,
+ "No entry for terminal type \"%s\";\n", term);
+ (void) fprintf(el->el_errfile,
+ "using dumb terminal settings.\n");
+ Val(T_co) = 80; /* do a dumb terminal */
+ Val(T_pt) = Val(T_km) = Val(T_li) = 0;
+ Val(T_xt) = Val(T_MT);
+ for (t = tstr; t->name != NULL; t++)
+ term_alloc(el, t, NULL);
+ } else {
+ /* auto/magic margins */
+ Val(T_am) = tgetflag("am");
+ Val(T_xn) = tgetflag("xn");
+ /* Can we tab */
+ Val(T_pt) = tgetflag("pt");
+ Val(T_xt) = tgetflag("xt");
+ /* do we have a meta? */
+ Val(T_km) = tgetflag("km");
+ Val(T_MT) = tgetflag("MT");
+ /* Get the size */
+ Val(T_co) = tgetnum("co");
+ Val(T_li) = tgetnum("li");
+ for (t = tstr; t->name != NULL; t++)
+ term_alloc(el, t, tgetstr(t->name, &area));
+ }
+
+ if (Val(T_co) < 2)
+ Val(T_co) = 80; /* just in case */
+ if (Val(T_li) < 1)
+ Val(T_li) = 24;
+
+ el->el_term.t_size.v = Val(T_co);
+ el->el_term.t_size.h = Val(T_li);
+
+ term_setflags(el);
+
+ /* get the correct window size */
+ (void) term_get_size(el, &lins, &cols);
+ if (term_change_size(el, lins, cols) == -1)
+ return (-1);
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+ term_bind_arrow(el);
+ return (i <= 0 ? -1 : 0);
+}
+
+
+/* term_get_size():
+ * Return the new window size in lines and cols, and
+ * true if the size was changed.
+ */
+protected int
+term_get_size(EditLine *el, int *lins, int *cols)
+{
+
+ *cols = Val(T_co);
+ *lins = Val(T_li);
+
+#ifdef TIOCGWINSZ
+ {
+ struct winsize ws;
+ if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) & ws) != -1) {
+ if (ws.ws_col)
+ *cols = ws.ws_col;
+ if (ws.ws_row)
+ *lins = ws.ws_row;
+ }
+ }
+#endif
+#ifdef TIOCGSIZE
+ {
+ struct ttysize ts;
+ if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) & ts) != -1) {
+ if (ts.ts_cols)
+ *cols = ts.ts_cols;
+ if (ts.ts_lines)
+ *lins = ts.ts_lines;
+ }
+ }
+#endif
+ return (Val(T_co) != *cols || Val(T_li) != *lins);
+}
+
+
+/* term_change_size():
+ * Change the size of the terminal
+ */
+protected int
+term_change_size(EditLine *el, int lins, int cols)
+{
+ /*
+ * Just in case
+ */
+ Val(T_co) = (cols < 2) ? 80 : cols;
+ Val(T_li) = (lins < 1) ? 24 : lins;
+
+ /* re-make display buffers */
+ if (term_rebuffer_display(el) == -1)
+ return (-1);
+ re_clear_display(el);
+ return (0);
+}
+
+
+/* term_init_arrow():
+ * Initialize the arrow key bindings from termcap
+ */
+private void
+term_init_arrow(EditLine *el)
+{
+ fkey_t *arrow = el->el_term.t_fkey;
+
+ arrow[A_K_DN].name = "down";
+ arrow[A_K_DN].key = T_kd;
+ arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY;
+ arrow[A_K_DN].type = XK_CMD;
+
+ arrow[A_K_UP].name = "up";
+ arrow[A_K_UP].key = T_ku;
+ arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY;
+ arrow[A_K_UP].type = XK_CMD;
+
+ arrow[A_K_LT].name = "left";
+ arrow[A_K_LT].key = T_kl;
+ arrow[A_K_LT].fun.cmd = ED_PREV_CHAR;
+ arrow[A_K_LT].type = XK_CMD;
+
+ arrow[A_K_RT].name = "right";
+ arrow[A_K_RT].key = T_kr;
+ arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR;
+ arrow[A_K_RT].type = XK_CMD;
+
+ arrow[A_K_HO].name = "home";
+ arrow[A_K_HO].key = T_kh;
+ arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG;
+ arrow[A_K_HO].type = XK_CMD;
+
+ arrow[A_K_EN].name = "end";
+ arrow[A_K_EN].key = T_at7;
+ arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END;
+ arrow[A_K_EN].type = XK_CMD;
+}
+
+
+/* term_reset_arrow():
+ * Reset arrow key bindings
+ */
+private void
+term_reset_arrow(EditLine *el)
+{
+ fkey_t *arrow = el->el_term.t_fkey;
+ static const char strA[] = {033, '[', 'A', '\0'};
+ static const char strB[] = {033, '[', 'B', '\0'};
+ static const char strC[] = {033, '[', 'C', '\0'};
+ static const char strD[] = {033, '[', 'D', '\0'};
+ static const char strH[] = {033, '[', 'H', '\0'};
+ static const char strF[] = {033, '[', 'F', '\0'};
+ static const char stOA[] = {033, 'O', 'A', '\0'};
+ static const char stOB[] = {033, 'O', 'B', '\0'};
+ static const char stOC[] = {033, 'O', 'C', '\0'};
+ static const char stOD[] = {033, 'O', 'D', '\0'};
+ static const char stOH[] = {033, 'O', 'H', '\0'};
+ static const char stOF[] = {033, 'O', 'F', '\0'};
+
+ key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ key_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+ key_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+ key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ key_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+ key_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+
+ if (el->el_map.type == MAP_VI) {
+ key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ key_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+ key_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+ key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ key_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+ key_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+ }
+}
+
+
+/* term_set_arrow():
+ * Set an arrow key binding
+ */
+protected int
+term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type)
+{
+ fkey_t *arrow = el->el_term.t_fkey;
+ int i;
+
+ for (i = 0; i < A_K_NKEYS; i++)
+ if (strcmp(name, arrow[i].name) == 0) {
+ arrow[i].fun = *fun;
+ arrow[i].type = type;
+ return (0);
+ }
+ return (-1);
+}
+
+
+/* term_clear_arrow():
+ * Clear an arrow key binding
+ */
+protected int
+term_clear_arrow(EditLine *el, const char *name)
+{
+ fkey_t *arrow = el->el_term.t_fkey;
+ int i;
+
+ for (i = 0; i < A_K_NKEYS; i++)
+ if (strcmp(name, arrow[i].name) == 0) {
+ arrow[i].type = XK_NOD;
+ return (0);
+ }
+ return (-1);
+}
+
+
+/* term_print_arrow():
+ * Print the arrow key bindings
+ */
+protected void
+term_print_arrow(EditLine *el, const char *name)
+{
+ int i;
+ fkey_t *arrow = el->el_term.t_fkey;
+
+ for (i = 0; i < A_K_NKEYS; i++)
+ if (*name == '\0' || strcmp(name, arrow[i].name) == 0)
+ if (arrow[i].type != XK_NOD)
+ key_kprint(el, arrow[i].name, &arrow[i].fun,
+ arrow[i].type);
+}
+
+
+/* term_bind_arrow():
+ * Bind the arrow keys
+ */
+protected void
+term_bind_arrow(EditLine *el)
+{
+ el_action_t *map;
+ const el_action_t *dmap;
+ int i, j;
+ char *p;
+ fkey_t *arrow = el->el_term.t_fkey;
+
+ /* Check if the components needed are initialized */
+ if (el->el_term.t_buf == NULL || el->el_map.key == NULL)
+ return;
+
+ map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key;
+ dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs;
+
+ term_reset_arrow(el);
+
+ for (i = 0; i < A_K_NKEYS; i++) {
+ p = el->el_term.t_str[arrow[i].key];
+ if (p && *p) {
+ j = (unsigned char) *p;
+ /*
+ * Assign the arrow keys only if:
+ *
+ * 1. They are multi-character arrow keys and the user
+ * has not re-assigned the leading character, or
+ * has re-assigned the leading character to be
+ * ED_SEQUENCE_LEAD_IN
+ * 2. They are single arrow keys pointing to an
+ * unassigned key.
+ */
+ if (arrow[i].type == XK_NOD)
+ key_clear(el, map, p);
+ else {
+ if (p[1] && (dmap[j] == map[j] ||
+ map[j] == ED_SEQUENCE_LEAD_IN)) {
+ key_add(el, p, &arrow[i].fun,
+ arrow[i].type);
+ map[j] = ED_SEQUENCE_LEAD_IN;
+ } else if (map[j] == ED_UNASSIGNED) {
+ key_clear(el, map, p);
+ if (arrow[i].type == XK_CMD)
+ map[j] = arrow[i].fun.cmd;
+ else
+ key_add(el, p, &arrow[i].fun,
+ arrow[i].type);
+ }
+ }
+ }
+ }
+}
+
+
+/* term__putc():
+ * Add a character
+ */
+protected int
+term__putc(int c)
+{
+
+ return (fputc(c, term_outfile));
+}
+
+
+/* term__flush():
+ * Flush output
+ */
+protected void
+term__flush(void)
+{
+
+ (void) fflush(term_outfile);
+}
+
+
+/* term_telltc():
+ * Print the current termcap characteristics
+ */
+protected int
+/*ARGSUSED*/
+term_telltc(EditLine *el, int
+ argc __attribute__((unused)),
+ const char **argv __attribute__((unused)))
+{
+ const struct termcapstr *t;
+ char **ts;
+ char upbuf[EL_BUFSIZ];
+
+ (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n");
+ (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n");
+ (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n",
+ Val(T_co), Val(T_li));
+ (void) fprintf(el->el_outfile,
+ "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no");
+ (void) fprintf(el->el_outfile,
+ "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not ");
+ (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n",
+ EL_HAS_AUTO_MARGINS ? "has" : "does not have");
+ if (EL_HAS_AUTO_MARGINS)
+ (void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
+ EL_HAS_MAGIC_MARGINS ? "has" : "does not have");
+
+ for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++)
+ (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n",
+ t->long_name,
+ t->name, *ts && **ts ?
+ key__decode_str(*ts, upbuf, "") : "(empty)");
+ (void) fputc('\n', el->el_outfile);
+ return (0);
+}
+
+
+/* term_settc():
+ * Change the current terminal characteristics
+ */
+protected int
+/*ARGSUSED*/
+term_settc(EditLine *el, int argc __attribute__((unused)), const char **argv)
+{
+ const struct termcapstr *ts;
+ const struct termcapval *tv;
+ const char *what, *how;
+
+ if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
+ return (-1);
+
+ what = argv[1];
+ how = argv[2];
+
+ /*
+ * Do the strings first
+ */
+ for (ts = tstr; ts->name != NULL; ts++)
+ if (strcmp(ts->name, what) == 0)
+ break;
+
+ if (ts->name != NULL) {
+ term_alloc(el, ts, how);
+ term_setflags(el);
+ return (0);
+ }
+ /*
+ * Do the numeric ones second
+ */
+ for (tv = tval; tv->name != NULL; tv++)
+ if (strcmp(tv->name, what) == 0)
+ break;
+
+ if (tv->name != NULL) {
+ if (tv == &tval[T_pt] || tv == &tval[T_km] ||
+ tv == &tval[T_am] || tv == &tval[T_xn]) {
+ if (strcmp(how, "yes") == 0)
+ el->el_term.t_val[tv - tval] = 1;
+ else if (strcmp(how, "no") == 0)
+ el->el_term.t_val[tv - tval] = 0;
+ else {
+ (void) fprintf(el->el_errfile,
+ "settc: Bad value `%s'.\n", how);
+ return (-1);
+ }
+ term_setflags(el);
+ if (term_change_size(el, Val(T_li), Val(T_co)) == -1)
+ return (-1);
+ return (0);
+ } else {
+ long i;
+ char *ep;
+
+ i = strtol(how, &ep, 10);
+ if (*ep != '\0') {
+ (void) fprintf(el->el_errfile,
+ "settc: Bad value `%s'.\n", how);
+ return (-1);
+ }
+ el->el_term.t_val[tv - tval] = (int) i;
+ el->el_term.t_size.v = Val(T_co);
+ el->el_term.t_size.h = Val(T_li);
+ if (tv == &tval[T_co] || tv == &tval[T_li])
+ if (term_change_size(el, Val(T_li), Val(T_co))
+ == -1)
+ return (-1);
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+
+/* term_echotc():
+ * Print the termcap string out with variable substitution
+ */
+protected int
+/*ARGSUSED*/
+term_echotc(EditLine *el, int argc __attribute__((unused)), const char **argv)
+{
+ char *cap, *scap, *ep;
+ int arg_need, arg_cols, arg_rows;
+ int verbose = 0, silent = 0;
+ char *area;
+ static const char fmts[] = "%s\n", fmtd[] = "%d\n";
+ const struct termcapstr *t;
+ char buf[TC_BUFSIZE];
+ long i;
+
+ area = buf;
+
+ if (argv == NULL || argv[1] == NULL)
+ return (-1);
+ argv++;
+
+ if (argv[0][0] == '-') {
+ switch (argv[0][1]) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ silent = 1;
+ break;
+ default:
+ /* stderror(ERR_NAME | ERR_TCUSAGE); */
+ break;
+ }
+ argv++;
+ }
+ if (!*argv || *argv[0] == '\0')
+ return (0);
+ if (strcmp(*argv, "tabs") == 0) {
+ (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no");
+ return (0);
+ } else if (strcmp(*argv, "meta") == 0) {
+ (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no");
+ return (0);
+ } else if (strcmp(*argv, "xn") == 0) {
+ (void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ?
+ "yes" : "no");
+ return (0);
+ } else if (strcmp(*argv, "am") == 0) {
+ (void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ?
+ "yes" : "no");
+ return (0);
+ } else if (strcmp(*argv, "baud") == 0) {
+#ifdef notdef
+ int i;
+
+ for (i = 0; baud_rate[i].b_name != NULL; i++)
+ if (el->el_tty.t_speed == baud_rate[i].b_rate) {
+ (void) fprintf(el->el_outfile, fmts,
+ baud_rate[i].b_name);
+ return (0);
+ }
+ (void) fprintf(el->el_outfile, fmtd, 0);
+#else
+ (void) fprintf(el->el_outfile, fmtd, el->el_tty.t_speed);
+#endif
+ return (0);
+ } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
+ (void) fprintf(el->el_outfile, fmtd, Val(T_li));
+ return (0);
+ } else if (strcmp(*argv, "cols") == 0) {
+ (void) fprintf(el->el_outfile, fmtd, Val(T_co));
+ return (0);
+ }
+ /*
+ * Try to use our local definition first
+ */
+ scap = NULL;
+ for (t = tstr; t->name != NULL; t++)
+ if (strcmp(t->name, *argv) == 0) {
+ scap = el->el_term.t_str[t - tstr];
+ break;
+ }
+ if (t->name == NULL)
+ scap = tgetstr(*argv, &area);
+ if (!scap || scap[0] == '\0') {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Termcap parameter `%s' not found.\n",
+ *argv);
+ return (-1);
+ }
+ /*
+ * Count home many values we need for this capability.
+ */
+ for (cap = scap, arg_need = 0; *cap; cap++)
+ if (*cap == '%')
+ switch (*++cap) {
+ case 'd':
+ case '2':
+ case '3':
+ case '.':
+ case '+':
+ arg_need++;
+ break;
+ case '%':
+ case '>':
+ case 'i':
+ case 'r':
+ case 'n':
+ case 'B':
+ case 'D':
+ break;
+ default:
+ /*
+ * hpux has lot's of them...
+ */
+ if (verbose)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: unknown termcap %% `%c'.\n",
+ *cap);
+ /* This is bad, but I won't complain */
+ break;
+ }
+
+ switch (arg_need) {
+ case 0:
+ argv++;
+ if (*argv && *argv[0]) {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Extra argument `%s'.\n",
+ *argv);
+ return (-1);
+ }
+ (void) tputs(scap, 1, term__putc);
+ break;
+ case 1:
+ argv++;
+ if (!*argv || *argv[0] == '\0') {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Missing argument.\n");
+ return (-1);
+ }
+ arg_cols = 0;
+ i = strtol(*argv, &ep, 10);
+ if (*ep != '\0' || i < 0) {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Bad value `%s' for rows.\n",
+ *argv);
+ return (-1);
+ }
+ arg_rows = (int) i;
+ argv++;
+ if (*argv && *argv[0]) {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Extra argument `%s'.\n",
+ *argv);
+ return (-1);
+ }
+ (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc);
+ break;
+ default:
+ /* This is wrong, but I will ignore it... */
+ if (verbose)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Too many required arguments (%d).\n",
+ arg_need);
+ /* FALLTHROUGH */
+ case 2:
+ argv++;
+ if (!*argv || *argv[0] == '\0') {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Missing argument.\n");
+ return (-1);
+ }
+ i = strtol(*argv, &ep, 10);
+ if (*ep != '\0' || i < 0) {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Bad value `%s' for cols.\n",
+ *argv);
+ return (-1);
+ }
+ arg_cols = (int) i;
+ argv++;
+ if (!*argv || *argv[0] == '\0') {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Missing argument.\n");
+ return (-1);
+ }
+ i = strtol(*argv, &ep, 10);
+ if (*ep != '\0' || i < 0) {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Bad value `%s' for rows.\n",
+ *argv);
+ return (-1);
+ }
+ arg_rows = (int) i;
+ if (*ep != '\0') {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Bad value `%s'.\n", *argv);
+ return (-1);
+ }
+ argv++;
+ if (*argv && *argv[0]) {
+ if (!silent)
+ (void) fprintf(el->el_errfile,
+ "echotc: Warning: Extra argument `%s'.\n",
+ *argv);
+ return (-1);
+ }
+ (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows,
+ term__putc);
+ break;
+ }
+ return (0);
+}
diff --git a/cmd-line-utils/libedit/term.h b/cmd-line-utils/libedit/term.h
new file mode 100644
index 00000000000..9f03c549515
--- /dev/null
+++ b/cmd-line-utils/libedit/term.h
@@ -0,0 +1,124 @@
+/* $NetBSD: term.h,v 1.12 2001/01/04 15:56:32 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)term.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.term.h: Termcap header
+ */
+#ifndef _h_el_term
+#define _h_el_term
+
+#include "histedit.h"
+
+typedef struct { /* Symbolic function key bindings */
+ const char *name; /* name of the key */
+ int key; /* Index in termcap table */
+ key_value_t fun; /* Function bound to it */
+ int type; /* Type of function */
+} fkey_t;
+
+typedef struct {
+ coord_t t_size; /* # lines and cols */
+ int t_flags;
+#define TERM_CAN_INSERT 0x001 /* Has insert cap */
+#define TERM_CAN_DELETE 0x002 /* Has delete cap */
+#define TERM_CAN_CEOL 0x004 /* Has CEOL cap */
+#define TERM_CAN_TAB 0x008 /* Can use tabs */
+#define TERM_CAN_ME 0x010 /* Can turn all attrs. */
+#define TERM_CAN_UP 0x020 /* Can move up */
+#define TERM_HAS_META 0x040 /* Has a meta key */
+#define TERM_HAS_AUTO_MARGINS 0x080 /* Has auto margins */
+#define TERM_HAS_MAGIC_MARGINS 0x100 /* Has magic margins */
+ char *t_buf; /* Termcap buffer */
+ int t_loc; /* location used */
+ char **t_str; /* termcap strings */
+ int *t_val; /* termcap values */
+ char *t_cap; /* Termcap buffer */
+ fkey_t *t_fkey; /* Array of keys */
+} el_term_t;
+
+/*
+ * fKey indexes
+ */
+#define A_K_DN 0
+#define A_K_UP 1
+#define A_K_LT 2
+#define A_K_RT 3
+#define A_K_HO 4
+#define A_K_EN 5
+#define A_K_NKEYS 6
+
+protected void term_move_to_line(EditLine *, int);
+protected void term_move_to_char(EditLine *, int);
+protected void term_clear_EOL(EditLine *, int);
+protected void term_overwrite(EditLine *, const char *, int);
+protected void term_insertwrite(EditLine *, char *, int);
+protected void term_deletechars(EditLine *, int);
+protected void term_clear_screen(EditLine *);
+protected void term_beep(EditLine *);
+protected int term_change_size(EditLine *, int, int);
+protected int term_get_size(EditLine *, int *, int *);
+protected int term_init(EditLine *);
+protected void term_bind_arrow(EditLine *);
+protected void term_print_arrow(EditLine *, const char *);
+protected int term_clear_arrow(EditLine *, const char *);
+protected int term_set_arrow(EditLine *, const char *, key_value_t *, int);
+protected void term_end(EditLine *);
+protected int term_set(EditLine *, const char *);
+protected int term_settc(EditLine *, int, const char **);
+protected int term_telltc(EditLine *, int, const char **);
+protected int term_echotc(EditLine *, int, const char **);
+protected int term__putc(int);
+protected void term__flush(void);
+
+/*
+ * Easy access macros
+ */
+#define EL_FLAGS (el)->el_term.t_flags
+
+#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT)
+#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE)
+#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL)
+#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB)
+#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME)
+#define EL_HAS_META (EL_FLAGS & TERM_HAS_META)
+#define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS)
+#define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS)
+
+#endif /* _h_el_term */
diff --git a/cmd-line-utils/libedit/tokenizer.c b/cmd-line-utils/libedit/tokenizer.c
new file mode 100644
index 00000000000..7a7e5b5ed75
--- /dev/null
+++ b/cmd-line-utils/libedit/tokenizer.c
@@ -0,0 +1,391 @@
+/* $NetBSD: tokenizer.c,v 1.7 2001/01/04 15:56:32 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * tokenize.c: Bourne shell like tokenizer
+ */
+#include "sys.h"
+#include <string.h>
+#include <stdlib.h>
+#include "tokenizer.h"
+
+typedef enum {
+ Q_none, Q_single, Q_double, Q_one, Q_doubleone
+} quote_t;
+
+#define IFS "\t \n"
+
+#define TOK_KEEP 1
+#define TOK_EAT 2
+
+#define WINCR 20
+#define AINCR 10
+
+#define tok_malloc(a) malloc(a)
+#define tok_free(a) free(a)
+#define tok_realloc(a, b) realloc(a, b)
+
+
+struct tokenizer {
+ char *ifs; /* In field separator */
+ int argc, amax; /* Current and maximum number of args */
+ const char **argv; /* Argument list */
+ char *wptr, *wmax; /* Space and limit on the word buffer */
+ char *wstart; /* Beginning of next word */
+ char *wspace; /* Space of word buffer */
+ quote_t quote; /* Quoting state */
+ int flags; /* flags; */
+};
+
+
+private void tok_finish(Tokenizer *);
+
+
+/* tok_finish():
+ * Finish a word in the tokenizer.
+ */
+private void
+tok_finish(Tokenizer *tok)
+{
+
+ *tok->wptr = '\0';
+ if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) {
+ tok->argv[tok->argc++] = tok->wstart;
+ tok->argv[tok->argc] = NULL;
+ tok->wstart = ++tok->wptr;
+ }
+ tok->flags &= ~TOK_KEEP;
+}
+
+
+/* tok_init():
+ * Initialize the tokenizer
+ */
+public Tokenizer *
+tok_init(const char *ifs)
+{
+ Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer));
+
+ tok->ifs = strdup(ifs ? ifs : IFS);
+ tok->argc = 0;
+ tok->amax = AINCR;
+ tok->argv = (const char **) tok_malloc(sizeof(char *) * tok->amax);
+ if (tok->argv == NULL)
+ return (NULL);
+ tok->argv[0] = NULL;
+ tok->wspace = (char *) tok_malloc(WINCR);
+ if (tok->wspace == NULL)
+ return (NULL);
+ tok->wmax = tok->wspace + WINCR;
+ tok->wstart = tok->wspace;
+ tok->wptr = tok->wspace;
+ tok->flags = 0;
+ tok->quote = Q_none;
+
+ return (tok);
+}
+
+
+/* tok_reset():
+ * Reset the tokenizer
+ */
+public void
+tok_reset(Tokenizer *tok)
+{
+
+ tok->argc = 0;
+ tok->wstart = tok->wspace;
+ tok->wptr = tok->wspace;
+ tok->flags = 0;
+ tok->quote = Q_none;
+}
+
+
+/* tok_end():
+ * Clean up
+ */
+public void
+tok_end(Tokenizer *tok)
+{
+
+ tok_free((ptr_t) tok->ifs);
+ tok_free((ptr_t) tok->wspace);
+ tok_free((ptr_t) tok->argv);
+ tok_free((ptr_t) tok);
+}
+
+
+
+/* tok_line():
+ * Bourne shell like tokenizing
+ * Return:
+ * -1: Internal error
+ * 3: Quoted return
+ * 2: Unmatched double quote
+ * 1: Unmatched single quote
+ * 0: Ok
+ */
+public int
+tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
+{
+ const char *ptr;
+
+ for (;;) {
+ switch (*(ptr = line++)) {
+ case '\'':
+ tok->flags |= TOK_KEEP;
+ tok->flags &= ~TOK_EAT;
+ switch (tok->quote) {
+ case Q_none:
+ tok->quote = Q_single; /* Enter single quote
+ * mode */
+ break;
+
+ case Q_single: /* Exit single quote mode */
+ tok->quote = Q_none;
+ break;
+
+ case Q_one: /* Quote this ' */
+ tok->quote = Q_none;
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_double: /* Stay in double quote mode */
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_doubleone: /* Quote this ' */
+ tok->quote = Q_double;
+ *tok->wptr++ = *ptr;
+ break;
+
+ default:
+ return (-1);
+ }
+ break;
+
+ case '"':
+ tok->flags &= ~TOK_EAT;
+ tok->flags |= TOK_KEEP;
+ switch (tok->quote) {
+ case Q_none: /* Enter double quote mode */
+ tok->quote = Q_double;
+ break;
+
+ case Q_double: /* Exit double quote mode */
+ tok->quote = Q_none;
+ break;
+
+ case Q_one: /* Quote this " */
+ tok->quote = Q_none;
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_single: /* Stay in single quote mode */
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_doubleone: /* Quote this " */
+ tok->quote = Q_double;
+ *tok->wptr++ = *ptr;
+ break;
+
+ default:
+ return (-1);
+ }
+ break;
+
+ case '\\':
+ tok->flags |= TOK_KEEP;
+ tok->flags &= ~TOK_EAT;
+ switch (tok->quote) {
+ case Q_none: /* Quote next character */
+ tok->quote = Q_one;
+ break;
+
+ case Q_double: /* Quote next character */
+ tok->quote = Q_doubleone;
+ break;
+
+ case Q_one: /* Quote this, restore state */
+ *tok->wptr++ = *ptr;
+ tok->quote = Q_none;
+ break;
+
+ case Q_single: /* Stay in single quote mode */
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_doubleone: /* Quote this \ */
+ tok->quote = Q_double;
+ *tok->wptr++ = *ptr;
+ break;
+
+ default:
+ return (-1);
+ }
+ break;
+
+ case '\n':
+ tok->flags &= ~TOK_EAT;
+ switch (tok->quote) {
+ case Q_none:
+ tok_finish(tok);
+ *argv = tok->argv;
+ *argc = tok->argc;
+ return (0);
+
+ case Q_single:
+ case Q_double:
+ *tok->wptr++ = *ptr; /* Add the return */
+ break;
+
+ case Q_doubleone: /* Back to double, eat the '\n' */
+ tok->flags |= TOK_EAT;
+ tok->quote = Q_double;
+ break;
+
+ case Q_one: /* No quote, more eat the '\n' */
+ tok->flags |= TOK_EAT;
+ tok->quote = Q_none;
+ break;
+
+ default:
+ return (0);
+ }
+ break;
+
+ case '\0':
+ switch (tok->quote) {
+ case Q_none:
+ /* Finish word and return */
+ if (tok->flags & TOK_EAT) {
+ tok->flags &= ~TOK_EAT;
+ return (3);
+ }
+ tok_finish(tok);
+ *argv = tok->argv;
+ *argc = tok->argc;
+ return (0);
+
+ case Q_single:
+ return (1);
+
+ case Q_double:
+ return (2);
+
+ case Q_doubleone:
+ tok->quote = Q_double;
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_one:
+ tok->quote = Q_none;
+ *tok->wptr++ = *ptr;
+ break;
+
+ default:
+ return (-1);
+ }
+ break;
+
+ default:
+ tok->flags &= ~TOK_EAT;
+ switch (tok->quote) {
+ case Q_none:
+ if (strchr(tok->ifs, *ptr) != NULL)
+ tok_finish(tok);
+ else
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_single:
+ case Q_double:
+ *tok->wptr++ = *ptr;
+ break;
+
+
+ case Q_doubleone:
+ *tok->wptr++ = '\\';
+ tok->quote = Q_double;
+ *tok->wptr++ = *ptr;
+ break;
+
+ case Q_one:
+ tok->quote = Q_none;
+ *tok->wptr++ = *ptr;
+ break;
+
+ default:
+ return (-1);
+
+ }
+ break;
+ }
+
+ if (tok->wptr >= tok->wmax - 4) {
+ size_t size = tok->wmax - tok->wspace + WINCR;
+ char *s = (char *) tok_realloc(tok->wspace, size);
+ /* SUPPRESS 22 */
+ int offs = s - tok->wspace;
+ if (s == NULL)
+ return (-1);
+
+ if (offs != 0) {
+ int i;
+ for (i = 0; i < tok->argc; i++)
+ tok->argv[i] = tok->argv[i] + offs;
+ tok->wptr = tok->wptr + offs;
+ tok->wstart = tok->wstart + offs;
+ tok->wmax = s + size;
+ tok->wspace = s;
+ }
+ }
+ if (tok->argc >= tok->amax - 4) {
+ const char **p;
+ tok->amax += AINCR;
+ p = (const char **) tok_realloc(tok->argv,
+ tok->amax * sizeof(char *));
+ if (p == NULL)
+ return (-1);
+ tok->argv = p;
+ }
+ }
+}
diff --git a/cmd-line-utils/libedit/tokenizer.h b/cmd-line-utils/libedit/tokenizer.h
new file mode 100644
index 00000000000..14919fd3f84
--- /dev/null
+++ b/cmd-line-utils/libedit/tokenizer.h
@@ -0,0 +1,54 @@
+/* $NetBSD: tokenizer.h,v 1.4 2000/09/04 22:06:33 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)tokenizer.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * tokenizer.h: Header file for tokenizer routines
+ */
+#ifndef _h_tokenizer
+#define _h_tokenizer
+
+typedef struct tokenizer Tokenizer;
+
+Tokenizer *tok_init(const char *);
+void tok_reset(Tokenizer *);
+void tok_end(Tokenizer *);
+int tok_line(Tokenizer *, const char *, int *, const char ***);
+
+#endif /* _h_tokenizer */
diff --git a/cmd-line-utils/libedit/tty.c b/cmd-line-utils/libedit/tty.c
new file mode 100644
index 00000000000..2c7b502136d
--- /dev/null
+++ b/cmd-line-utils/libedit/tty.c
@@ -0,0 +1,1177 @@
+/* $NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * tty.c: tty interface stuff
+ */
+#include "sys.h"
+#include "tty.h"
+#include "el.h"
+
+typedef struct ttymodes_t {
+ const char *m_name;
+ u_int m_value;
+ int m_type;
+} ttymodes_t;
+
+typedef struct ttymap_t {
+ int nch, och; /* Internal and termio rep of chars */
+ el_action_t bind[3]; /* emacs, vi, and vi-cmd */
+} ttymap_t;
+
+
+private const ttyperm_t ttyperm = {
+ {
+ {"iflag:", ICRNL, (INLCR | IGNCR)},
+ {"oflag:", (OPOST | ONLCR), ONLRET},
+ {"cflag:", 0, 0},
+ {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
+ (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
+ {"chars:", 0, 0},
+ },
+ {
+ {"iflag:", (INLCR | ICRNL), IGNCR},
+ {"oflag:", (OPOST | ONLCR), ONLRET},
+ {"cflag:", 0, 0},
+ {"lflag:", ISIG,
+ (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
+ {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
+ C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
+ C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
+ },
+ {
+ {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
+ {"oflag:", 0, 0},
+ {"cflag:", 0, 0},
+ {"lflag:", 0, ISIG | IEXTEN},
+ {"chars:", 0, 0},
+ }
+};
+
+private const ttychar_t ttychar = {
+ {
+ CINTR, CQUIT, CERASE, CKILL,
+ CEOF, CEOL, CEOL2, CSWTCH,
+ CDSWTCH, CERASE2, CSTART, CSTOP,
+ CWERASE, CSUSP, CDSUSP, CREPRINT,
+ CDISCARD, CLNEXT, CSTATUS, CPAGE,
+ CPGOFF, CKILL2, CBRK, CMIN,
+ CTIME
+ },
+ {
+ CINTR, CQUIT, CERASE, CKILL,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
+ _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
+ 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0
+ }
+};
+
+private const ttymap_t tty_map[] = {
+#ifdef VERASE
+ {C_ERASE, VERASE,
+ {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+#endif /* VERASE */
+#ifdef VERASE2
+ {C_ERASE2, VERASE2,
+ {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+#endif /* VERASE2 */
+#ifdef VKILL
+ {C_KILL, VKILL,
+ {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
+#endif /* VKILL */
+#ifdef VKILL2
+ {C_KILL2, VKILL2,
+ {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
+#endif /* VKILL2 */
+#ifdef VEOF
+ {C_EOF, VEOF,
+ {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
+#endif /* VEOF */
+#ifdef VWERASE
+ {C_WERASE, VWERASE,
+ {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
+#endif /* VWERASE */
+#ifdef VREPRINT
+ {C_REPRINT, VREPRINT,
+ {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
+#endif /* VREPRINT */
+#ifdef VLNEXT
+ {C_LNEXT, VLNEXT,
+ {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
+#endif /* VLNEXT */
+ {-1, -1,
+ {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
+};
+
+private const ttymodes_t ttymodes[] = {
+#ifdef IGNBRK
+ {"ignbrk", IGNBRK, MD_INP},
+#endif /* IGNBRK */
+#ifdef BRKINT
+ {"brkint", BRKINT, MD_INP},
+#endif /* BRKINT */
+#ifdef IGNPAR
+ {"ignpar", IGNPAR, MD_INP},
+#endif /* IGNPAR */
+#ifdef PARMRK
+ {"parmrk", PARMRK, MD_INP},
+#endif /* PARMRK */
+#ifdef INPCK
+ {"inpck", INPCK, MD_INP},
+#endif /* INPCK */
+#ifdef ISTRIP
+ {"istrip", ISTRIP, MD_INP},
+#endif /* ISTRIP */
+#ifdef INLCR
+ {"inlcr", INLCR, MD_INP},
+#endif /* INLCR */
+#ifdef IGNCR
+ {"igncr", IGNCR, MD_INP},
+#endif /* IGNCR */
+#ifdef ICRNL
+ {"icrnl", ICRNL, MD_INP},
+#endif /* ICRNL */
+#ifdef IUCLC
+ {"iuclc", IUCLC, MD_INP},
+#endif /* IUCLC */
+#ifdef IXON
+ {"ixon", IXON, MD_INP},
+#endif /* IXON */
+#ifdef IXANY
+ {"ixany", IXANY, MD_INP},
+#endif /* IXANY */
+#ifdef IXOFF
+ {"ixoff", IXOFF, MD_INP},
+#endif /* IXOFF */
+#ifdef IMAXBEL
+ {"imaxbel", IMAXBEL, MD_INP},
+#endif /* IMAXBEL */
+
+#ifdef OPOST
+ {"opost", OPOST, MD_OUT},
+#endif /* OPOST */
+#ifdef OLCUC
+ {"olcuc", OLCUC, MD_OUT},
+#endif /* OLCUC */
+#ifdef ONLCR
+ {"onlcr", ONLCR, MD_OUT},
+#endif /* ONLCR */
+#ifdef OCRNL
+ {"ocrnl", OCRNL, MD_OUT},
+#endif /* OCRNL */
+#ifdef ONOCR
+ {"onocr", ONOCR, MD_OUT},
+#endif /* ONOCR */
+#ifdef ONOEOT
+ {"onoeot", ONOEOT, MD_OUT},
+#endif /* ONOEOT */
+#ifdef ONLRET
+ {"onlret", ONLRET, MD_OUT},
+#endif /* ONLRET */
+#ifdef OFILL
+ {"ofill", OFILL, MD_OUT},
+#endif /* OFILL */
+#ifdef OFDEL
+ {"ofdel", OFDEL, MD_OUT},
+#endif /* OFDEL */
+#ifdef NLDLY
+ {"nldly", NLDLY, MD_OUT},
+#endif /* NLDLY */
+#ifdef CRDLY
+ {"crdly", CRDLY, MD_OUT},
+#endif /* CRDLY */
+#ifdef TABDLY
+ {"tabdly", TABDLY, MD_OUT},
+#endif /* TABDLY */
+#ifdef XTABS
+ {"xtabs", XTABS, MD_OUT},
+#endif /* XTABS */
+#ifdef BSDLY
+ {"bsdly", BSDLY, MD_OUT},
+#endif /* BSDLY */
+#ifdef VTDLY
+ {"vtdly", VTDLY, MD_OUT},
+#endif /* VTDLY */
+#ifdef FFDLY
+ {"ffdly", FFDLY, MD_OUT},
+#endif /* FFDLY */
+#ifdef PAGEOUT
+ {"pageout", PAGEOUT, MD_OUT},
+#endif /* PAGEOUT */
+#ifdef WRAP
+ {"wrap", WRAP, MD_OUT},
+#endif /* WRAP */
+
+#ifdef CIGNORE
+ {"cignore", CIGNORE, MD_CTL},
+#endif /* CBAUD */
+#ifdef CBAUD
+ {"cbaud", CBAUD, MD_CTL},
+#endif /* CBAUD */
+#ifdef CSTOPB
+ {"cstopb", CSTOPB, MD_CTL},
+#endif /* CSTOPB */
+#ifdef CREAD
+ {"cread", CREAD, MD_CTL},
+#endif /* CREAD */
+#ifdef PARENB
+ {"parenb", PARENB, MD_CTL},
+#endif /* PARENB */
+#ifdef PARODD
+ {"parodd", PARODD, MD_CTL},
+#endif /* PARODD */
+#ifdef HUPCL
+ {"hupcl", HUPCL, MD_CTL},
+#endif /* HUPCL */
+#ifdef CLOCAL
+ {"clocal", CLOCAL, MD_CTL},
+#endif /* CLOCAL */
+#ifdef LOBLK
+ {"loblk", LOBLK, MD_CTL},
+#endif /* LOBLK */
+#ifdef CIBAUD
+ {"cibaud", CIBAUD, MD_CTL},
+#endif /* CIBAUD */
+#ifdef CRTSCTS
+#ifdef CCTS_OFLOW
+ {"ccts_oflow", CCTS_OFLOW, MD_CTL},
+#else
+ {"crtscts", CRTSCTS, MD_CTL},
+#endif /* CCTS_OFLOW */
+#endif /* CRTSCTS */
+#ifdef CRTS_IFLOW
+ {"crts_iflow", CRTS_IFLOW, MD_CTL},
+#endif /* CRTS_IFLOW */
+#ifdef CDTRCTS
+ {"cdtrcts", CDTRCTS, MD_CTL},
+#endif /* CDTRCTS */
+#ifdef MDMBUF
+ {"mdmbuf", MDMBUF, MD_CTL},
+#endif /* MDMBUF */
+#ifdef RCV1EN
+ {"rcv1en", RCV1EN, MD_CTL},
+#endif /* RCV1EN */
+#ifdef XMT1EN
+ {"xmt1en", XMT1EN, MD_CTL},
+#endif /* XMT1EN */
+
+#ifdef ISIG
+ {"isig", ISIG, MD_LIN},
+#endif /* ISIG */
+#ifdef ICANON
+ {"icanon", ICANON, MD_LIN},
+#endif /* ICANON */
+#ifdef XCASE
+ {"xcase", XCASE, MD_LIN},
+#endif /* XCASE */
+#ifdef ECHO
+ {"echo", ECHO, MD_LIN},
+#endif /* ECHO */
+#ifdef ECHOE
+ {"echoe", ECHOE, MD_LIN},
+#endif /* ECHOE */
+#ifdef ECHOK
+ {"echok", ECHOK, MD_LIN},
+#endif /* ECHOK */
+#ifdef ECHONL
+ {"echonl", ECHONL, MD_LIN},
+#endif /* ECHONL */
+#ifdef NOFLSH
+ {"noflsh", NOFLSH, MD_LIN},
+#endif /* NOFLSH */
+#ifdef TOSTOP
+ {"tostop", TOSTOP, MD_LIN},
+#endif /* TOSTOP */
+#ifdef ECHOCTL
+ {"echoctl", ECHOCTL, MD_LIN},
+#endif /* ECHOCTL */
+#ifdef ECHOPRT
+ {"echoprt", ECHOPRT, MD_LIN},
+#endif /* ECHOPRT */
+#ifdef ECHOKE
+ {"echoke", ECHOKE, MD_LIN},
+#endif /* ECHOKE */
+#ifdef DEFECHO
+ {"defecho", DEFECHO, MD_LIN},
+#endif /* DEFECHO */
+#ifdef FLUSHO
+ {"flusho", FLUSHO, MD_LIN},
+#endif /* FLUSHO */
+#ifdef PENDIN
+ {"pendin", PENDIN, MD_LIN},
+#endif /* PENDIN */
+#ifdef IEXTEN
+ {"iexten", IEXTEN, MD_LIN},
+#endif /* IEXTEN */
+#ifdef NOKERNINFO
+ {"nokerninfo", NOKERNINFO, MD_LIN},
+#endif /* NOKERNINFO */
+#ifdef ALTWERASE
+ {"altwerase", ALTWERASE, MD_LIN},
+#endif /* ALTWERASE */
+#ifdef EXTPROC
+ {"extproc", EXTPROC, MD_LIN},
+#endif /* EXTPROC */
+
+#if defined(VINTR)
+ {"intr", C_SH(C_INTR), MD_CHAR},
+#endif /* VINTR */
+#if defined(VQUIT)
+ {"quit", C_SH(C_QUIT), MD_CHAR},
+#endif /* VQUIT */
+#if defined(VERASE)
+ {"erase", C_SH(C_ERASE), MD_CHAR},
+#endif /* VERASE */
+#if defined(VKILL)
+ {"kill", C_SH(C_KILL), MD_CHAR},
+#endif /* VKILL */
+#if defined(VEOF)
+ {"eof", C_SH(C_EOF), MD_CHAR},
+#endif /* VEOF */
+#if defined(VEOL)
+ {"eol", C_SH(C_EOL), MD_CHAR},
+#endif /* VEOL */
+#if defined(VEOL2)
+ {"eol2", C_SH(C_EOL2), MD_CHAR},
+#endif /* VEOL2 */
+#if defined(VSWTCH)
+ {"swtch", C_SH(C_SWTCH), MD_CHAR},
+#endif /* VSWTCH */
+#if defined(VDSWTCH)
+ {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
+#endif /* VDSWTCH */
+#if defined(VERASE2)
+ {"erase2", C_SH(C_ERASE2), MD_CHAR},
+#endif /* VERASE2 */
+#if defined(VSTART)
+ {"start", C_SH(C_START), MD_CHAR},
+#endif /* VSTART */
+#if defined(VSTOP)
+ {"stop", C_SH(C_STOP), MD_CHAR},
+#endif /* VSTOP */
+#if defined(VWERASE)
+ {"werase", C_SH(C_WERASE), MD_CHAR},
+#endif /* VWERASE */
+#if defined(VSUSP)
+ {"susp", C_SH(C_SUSP), MD_CHAR},
+#endif /* VSUSP */
+#if defined(VDSUSP)
+ {"dsusp", C_SH(C_DSUSP), MD_CHAR},
+#endif /* VDSUSP */
+#if defined(VREPRINT)
+ {"reprint", C_SH(C_REPRINT), MD_CHAR},
+#endif /* VREPRINT */
+#if defined(VDISCARD)
+ {"discard", C_SH(C_DISCARD), MD_CHAR},
+#endif /* VDISCARD */
+#if defined(VLNEXT)
+ {"lnext", C_SH(C_LNEXT), MD_CHAR},
+#endif /* VLNEXT */
+#if defined(VSTATUS)
+ {"status", C_SH(C_STATUS), MD_CHAR},
+#endif /* VSTATUS */
+#if defined(VPAGE)
+ {"page", C_SH(C_PAGE), MD_CHAR},
+#endif /* VPAGE */
+#if defined(VPGOFF)
+ {"pgoff", C_SH(C_PGOFF), MD_CHAR},
+#endif /* VPGOFF */
+#if defined(VKILL2)
+ {"kill2", C_SH(C_KILL2), MD_CHAR},
+#endif /* VKILL2 */
+#if defined(VBRK)
+ {"brk", C_SH(C_BRK), MD_CHAR},
+#endif /* VBRK */
+#if defined(VMIN)
+ {"min", C_SH(C_MIN), MD_CHAR},
+#endif /* VMIN */
+#if defined(VTIME)
+ {"time", C_SH(C_TIME), MD_CHAR},
+#endif /* VTIME */
+ {NULL, 0, -1},
+};
+
+
+
+#define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
+#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
+
+#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
+#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
+#define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
+
+private void tty__getchar(struct termios *, unsigned char *);
+private void tty__setchar(struct termios *, unsigned char *);
+private speed_t tty__getspeed(struct termios *);
+private int tty_setup(EditLine *);
+
+#define t_qu t_ts
+
+
+/* tty_setup():
+ * Get the tty parameters and initialize the editing state
+ */
+private int
+tty_setup(EditLine *el)
+{
+ int rst = 1;
+
+ if (el->el_flags & EDIT_DISABLED)
+ return (0);
+
+ if (tty_getty(el, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile,
+ "tty_setup: tty_getty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
+
+ el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
+ el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
+ el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
+
+ el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
+ el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
+
+ el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
+ el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
+
+ el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
+ el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
+
+ el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
+ el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
+
+ /*
+ * Reset the tty chars to reasonable defaults
+ * If they are disabled, then enable them.
+ */
+ if (rst) {
+ if (tty__cooked_mode(&el->el_tty.t_ts)) {
+ tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+ /*
+ * Don't affect CMIN and CTIME for the editor mode
+ */
+ for (rst = 0; rst < C_NCC - 2; rst++)
+ if (el->el_tty.t_c[TS_IO][rst] !=
+ el->el_tty.t_vdisable
+ && el->el_tty.t_c[ED_IO][rst] !=
+ el->el_tty.t_vdisable)
+ el->el_tty.t_c[ED_IO][rst] =
+ el->el_tty.t_c[TS_IO][rst];
+ for (rst = 0; rst < C_NCC; rst++)
+ if (el->el_tty.t_c[TS_IO][rst] !=
+ el->el_tty.t_vdisable)
+ el->el_tty.t_c[EX_IO][rst] =
+ el->el_tty.t_c[TS_IO][rst];
+ }
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+ if (tty_setty(el, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile,
+ "tty_setup: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ } else
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+
+ el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
+ el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
+
+ el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
+ el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
+
+ el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
+ el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
+
+ el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
+ el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
+
+ tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+ tty_bind_char(el, 1);
+ return (0);
+}
+
+protected int
+tty_init(EditLine *el)
+{
+
+ el->el_tty.t_mode = EX_IO;
+ el->el_tty.t_vdisable = _POSIX_VDISABLE;
+ (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
+ (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
+ return (tty_setup(el));
+}
+
+
+/* tty_end():
+ * Restore the tty to its original settings
+ */
+protected void
+/*ARGSUSED*/
+tty_end(EditLine *el __attribute__((unused)))
+{
+
+ /* XXX: Maybe reset to an initial state? */
+}
+
+
+/* tty__getspeed():
+ * Get the tty speed
+ */
+private speed_t
+tty__getspeed(struct termios *td)
+{
+ speed_t spd;
+
+ if ((spd = cfgetispeed(td)) == 0)
+ spd = cfgetospeed(td);
+ return (spd);
+}
+
+
+/* tty__getchar():
+ * Get the tty characters
+ */
+private void
+tty__getchar(struct termios *td, unsigned char *s)
+{
+
+#ifdef VINTR
+ s[C_INTR] = td->c_cc[VINTR];
+#endif /* VINTR */
+#ifdef VQUIT
+ s[C_QUIT] = td->c_cc[VQUIT];
+#endif /* VQUIT */
+#ifdef VERASE
+ s[C_ERASE] = td->c_cc[VERASE];
+#endif /* VERASE */
+#ifdef VKILL
+ s[C_KILL] = td->c_cc[VKILL];
+#endif /* VKILL */
+#ifdef VEOF
+ s[C_EOF] = td->c_cc[VEOF];
+#endif /* VEOF */
+#ifdef VEOL
+ s[C_EOL] = td->c_cc[VEOL];
+#endif /* VEOL */
+#ifdef VEOL2
+ s[C_EOL2] = td->c_cc[VEOL2];
+#endif /* VEOL2 */
+#ifdef VSWTCH
+ s[C_SWTCH] = td->c_cc[VSWTCH];
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+ s[C_DSWTCH] = td->c_cc[VDSWTCH];
+#endif /* VDSWTCH */
+#ifdef VERASE2
+ s[C_ERASE2] = td->c_cc[VERASE2];
+#endif /* VERASE2 */
+#ifdef VSTART
+ s[C_START] = td->c_cc[VSTART];
+#endif /* VSTART */
+#ifdef VSTOP
+ s[C_STOP] = td->c_cc[VSTOP];
+#endif /* VSTOP */
+#ifdef VWERASE
+ s[C_WERASE] = td->c_cc[VWERASE];
+#endif /* VWERASE */
+#ifdef VSUSP
+ s[C_SUSP] = td->c_cc[VSUSP];
+#endif /* VSUSP */
+#ifdef VDSUSP
+ s[C_DSUSP] = td->c_cc[VDSUSP];
+#endif /* VDSUSP */
+#ifdef VREPRINT
+ s[C_REPRINT] = td->c_cc[VREPRINT];
+#endif /* VREPRINT */
+#ifdef VDISCARD
+ s[C_DISCARD] = td->c_cc[VDISCARD];
+#endif /* VDISCARD */
+#ifdef VLNEXT
+ s[C_LNEXT] = td->c_cc[VLNEXT];
+#endif /* VLNEXT */
+#ifdef VSTATUS
+ s[C_STATUS] = td->c_cc[VSTATUS];
+#endif /* VSTATUS */
+#ifdef VPAGE
+ s[C_PAGE] = td->c_cc[VPAGE];
+#endif /* VPAGE */
+#ifdef VPGOFF
+ s[C_PGOFF] = td->c_cc[VPGOFF];
+#endif /* VPGOFF */
+#ifdef VKILL2
+ s[C_KILL2] = td->c_cc[VKILL2];
+#endif /* KILL2 */
+#ifdef VMIN
+ s[C_MIN] = td->c_cc[VMIN];
+#endif /* VMIN */
+#ifdef VTIME
+ s[C_TIME] = td->c_cc[VTIME];
+#endif /* VTIME */
+} /* tty__getchar */
+
+
+/* tty__setchar():
+ * Set the tty characters
+ */
+private void
+tty__setchar(struct termios *td, unsigned char *s)
+{
+
+#ifdef VINTR
+ td->c_cc[VINTR] = s[C_INTR];
+#endif /* VINTR */
+#ifdef VQUIT
+ td->c_cc[VQUIT] = s[C_QUIT];
+#endif /* VQUIT */
+#ifdef VERASE
+ td->c_cc[VERASE] = s[C_ERASE];
+#endif /* VERASE */
+#ifdef VKILL
+ td->c_cc[VKILL] = s[C_KILL];
+#endif /* VKILL */
+#ifdef VEOF
+ td->c_cc[VEOF] = s[C_EOF];
+#endif /* VEOF */
+#ifdef VEOL
+ td->c_cc[VEOL] = s[C_EOL];
+#endif /* VEOL */
+#ifdef VEOL2
+ td->c_cc[VEOL2] = s[C_EOL2];
+#endif /* VEOL2 */
+#ifdef VSWTCH
+ td->c_cc[VSWTCH] = s[C_SWTCH];
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+ td->c_cc[VDSWTCH] = s[C_DSWTCH];
+#endif /* VDSWTCH */
+#ifdef VERASE2
+ td->c_cc[VERASE2] = s[C_ERASE2];
+#endif /* VERASE2 */
+#ifdef VSTART
+ td->c_cc[VSTART] = s[C_START];
+#endif /* VSTART */
+#ifdef VSTOP
+ td->c_cc[VSTOP] = s[C_STOP];
+#endif /* VSTOP */
+#ifdef VWERASE
+ td->c_cc[VWERASE] = s[C_WERASE];
+#endif /* VWERASE */
+#ifdef VSUSP
+ td->c_cc[VSUSP] = s[C_SUSP];
+#endif /* VSUSP */
+#ifdef VDSUSP
+ td->c_cc[VDSUSP] = s[C_DSUSP];
+#endif /* VDSUSP */
+#ifdef VREPRINT
+ td->c_cc[VREPRINT] = s[C_REPRINT];
+#endif /* VREPRINT */
+#ifdef VDISCARD
+ td->c_cc[VDISCARD] = s[C_DISCARD];
+#endif /* VDISCARD */
+#ifdef VLNEXT
+ td->c_cc[VLNEXT] = s[C_LNEXT];
+#endif /* VLNEXT */
+#ifdef VSTATUS
+ td->c_cc[VSTATUS] = s[C_STATUS];
+#endif /* VSTATUS */
+#ifdef VPAGE
+ td->c_cc[VPAGE] = s[C_PAGE];
+#endif /* VPAGE */
+#ifdef VPGOFF
+ td->c_cc[VPGOFF] = s[C_PGOFF];
+#endif /* VPGOFF */
+#ifdef VKILL2
+ td->c_cc[VKILL2] = s[C_KILL2];
+#endif /* VKILL2 */
+#ifdef VMIN
+ td->c_cc[VMIN] = s[C_MIN];
+#endif /* VMIN */
+#ifdef VTIME
+ td->c_cc[VTIME] = s[C_TIME];
+#endif /* VTIME */
+} /* tty__setchar */
+
+
+/* tty_bind_char():
+ * Rebind the editline functions
+ */
+protected void
+tty_bind_char(EditLine *el, int force)
+{
+
+ unsigned char *t_n = el->el_tty.t_c[ED_IO];
+ unsigned char *t_o = el->el_tty.t_ed.c_cc;
+ unsigned char new[2], old[2];
+ const ttymap_t *tp;
+ el_action_t *map, *alt;
+ const el_action_t *dmap, *dalt;
+ new[1] = old[1] = '\0';
+
+ map = el->el_map.key;
+ alt = el->el_map.alt;
+ if (el->el_map.type == MAP_VI) {
+ dmap = el->el_map.vii;
+ dalt = el->el_map.vic;
+ } else {
+ dmap = el->el_map.emacs;
+ dalt = NULL;
+ }
+
+ for (tp = tty_map; tp->nch != -1; tp++) {
+ new[0] = t_n[tp->nch];
+ old[0] = t_o[tp->och];
+ if (new[0] == old[0] && !force)
+ continue;
+ /* Put the old default binding back, and set the new binding */
+ key_clear(el, map, (char *)old);
+ map[old[0]] = dmap[old[0]];
+ key_clear(el, map, (char *)new);
+ /* MAP_VI == 1, MAP_EMACS == 0... */
+ map[new[0]] = tp->bind[el->el_map.type];
+ if (dalt) {
+ key_clear(el, alt, (char *)old);
+ alt[old[0]] = dalt[old[0]];
+ key_clear(el, alt, (char *)new);
+ alt[new[0]] = tp->bind[el->el_map.type + 1];
+ }
+ }
+}
+
+
+/* tty_rawmode():
+ * Set terminal into 1 character at a time mode.
+ */
+protected int
+tty_rawmode(EditLine *el)
+{
+
+ if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
+ return (0);
+
+ if (el->el_flags & EDIT_DISABLED)
+ return (0);
+
+ if (tty_getty(el, &el->el_tty.t_ts) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ /*
+ * We always keep up with the eight bit setting and the speed of the
+ * tty. But only we only believe changes that are made to cooked mode!
+ */
+ el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
+ el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
+
+ if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
+ tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
+ (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+ (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+ (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+ (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+ }
+ if (tty__cooked_mode(&el->el_tty.t_ts)) {
+ if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
+ el->el_tty.t_ex.c_cflag =
+ el->el_tty.t_ts.c_cflag;
+ el->el_tty.t_ex.c_cflag &=
+ ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
+ el->el_tty.t_ex.c_cflag |=
+ el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
+
+ el->el_tty.t_ed.c_cflag =
+ el->el_tty.t_ts.c_cflag;
+ el->el_tty.t_ed.c_cflag &=
+ ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
+ el->el_tty.t_ed.c_cflag |=
+ el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
+ }
+ if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
+ (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
+ el->el_tty.t_ex.c_lflag =
+ el->el_tty.t_ts.c_lflag;
+ el->el_tty.t_ex.c_lflag &=
+ ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
+ el->el_tty.t_ex.c_lflag |=
+ el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
+
+ el->el_tty.t_ed.c_lflag =
+ el->el_tty.t_ts.c_lflag;
+ el->el_tty.t_ed.c_lflag &=
+ ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
+ el->el_tty.t_ed.c_lflag |=
+ el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
+ }
+ if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
+ (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
+ el->el_tty.t_ex.c_iflag =
+ el->el_tty.t_ts.c_iflag;
+ el->el_tty.t_ex.c_iflag &=
+ ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
+ el->el_tty.t_ex.c_iflag |=
+ el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
+
+ el->el_tty.t_ed.c_iflag =
+ el->el_tty.t_ts.c_iflag;
+ el->el_tty.t_ed.c_iflag &=
+ ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
+ el->el_tty.t_ed.c_iflag |=
+ el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
+ }
+ if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
+ (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
+ el->el_tty.t_ex.c_oflag =
+ el->el_tty.t_ts.c_oflag;
+ el->el_tty.t_ex.c_oflag &=
+ ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
+ el->el_tty.t_ex.c_oflag |=
+ el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
+
+ el->el_tty.t_ed.c_oflag =
+ el->el_tty.t_ts.c_oflag;
+ el->el_tty.t_ed.c_oflag &=
+ ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
+ el->el_tty.t_ed.c_oflag |=
+ el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
+ }
+ if (tty__gettabs(&el->el_tty.t_ex) == 0)
+ el->el_tty.t_tabs = 0;
+ else
+ el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
+
+ {
+ int i;
+
+ tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+ /*
+ * Check if the user made any changes.
+ * If he did, then propagate the changes to the
+ * edit and execute data structures.
+ */
+ for (i = 0; i < C_NCC; i++)
+ if (el->el_tty.t_c[TS_IO][i] !=
+ el->el_tty.t_c[EX_IO][i])
+ break;
+
+ if (i != C_NCC) {
+ /*
+ * Propagate changes only to the unprotected
+ * chars that have been modified just now.
+ */
+ for (i = 0; i < C_NCC; i++) {
+ if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
+ && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
+ el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
+ if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
+ el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
+ }
+ tty_bind_char(el, 0);
+ tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+
+ for (i = 0; i < C_NCC; i++) {
+ if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
+ && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
+ el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
+ if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
+ el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
+ }
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+ }
+ }
+ }
+ if (tty_setty(el, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ el->el_tty.t_mode = ED_IO;
+ return (0);
+}
+
+
+/* tty_cookedmode():
+ * Set the tty back to normal mode
+ */
+protected int
+tty_cookedmode(EditLine *el)
+{ /* set tty in normal setup */
+
+ if (el->el_tty.t_mode == EX_IO)
+ return (0);
+
+ if (el->el_flags & EDIT_DISABLED)
+ return (0);
+
+ if (tty_setty(el, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile,
+ "tty_cookedmode: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ el->el_tty.t_mode = EX_IO;
+ return (0);
+}
+
+
+/* tty_quotemode():
+ * Turn on quote mode
+ */
+protected int
+tty_quotemode(EditLine *el)
+{
+ if (el->el_tty.t_mode == QU_IO)
+ return (0);
+
+ el->el_tty.t_qu = el->el_tty.t_ed;
+
+ el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
+ el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
+
+ el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
+ el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
+
+ el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
+ el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
+
+ el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
+ el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
+
+ if (tty_setty(el, &el->el_tty.t_qu) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ el->el_tty.t_mode = QU_IO;
+ return (0);
+}
+
+
+/* tty_noquotemode():
+ * Turn off quote mode
+ */
+protected int
+tty_noquotemode(EditLine *el)
+{
+
+ if (el->el_tty.t_mode != QU_IO)
+ return (0);
+ if (tty_setty(el, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return (-1);
+ }
+ el->el_tty.t_mode = ED_IO;
+ return (0);
+}
+
+
+/* tty_stty():
+ * Stty builtin
+ */
+protected int
+/*ARGSUSED*/
+tty_stty(EditLine *el, int argc __attribute__((unused)), const char **argv)
+{
+ const ttymodes_t *m;
+ char x;
+ const char *d;
+ int aflag = 0;
+ const char *s;
+ const char *name;
+ int z = EX_IO;
+
+ if (argv == NULL)
+ return (-1);
+ name = *argv++;
+
+ while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
+ switch (argv[0][1]) {
+ case 'a':
+ aflag++;
+ argv++;
+ break;
+ case 'd':
+ argv++;
+ z = ED_IO;
+ break;
+ case 'x':
+ argv++;
+ z = EX_IO;
+ break;
+ case 'q':
+ argv++;
+ z = QU_IO;
+ break;
+ default:
+ (void) fprintf(el->el_errfile,
+ "%s: Unknown switch `%c'.\n",
+ name, argv[0][1]);
+ return (-1);
+ }
+
+ if (!argv || !*argv) {
+ int i = -1;
+ int len = 0, st = 0, cu;
+ for (m = ttymodes; m->m_name; m++) {
+ if (m->m_type != i) {
+ (void) fprintf(el->el_outfile, "%s%s",
+ i != -1 ? "\n" : "",
+ el->el_tty.t_t[z][m->m_type].t_name);
+ i = m->m_type;
+ st = len =
+ strlen(el->el_tty.t_t[z][m->m_type].t_name);
+ }
+ x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
+ ? '+' : '\0';
+ x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
+ ? '-' : x;
+
+ if (x != '\0' || aflag) {
+
+ cu = strlen(m->m_name) + (x != '\0') + 1;
+
+ if (len + cu >= el->el_term.t_size.h) {
+ (void) fprintf(el->el_outfile, "\n%*s",
+ st, "");
+ len = st + cu;
+ } else
+ len += cu;
+
+ if (x != '\0')
+ (void) fprintf(el->el_outfile, "%c%s ",
+ x, m->m_name);
+ else
+ (void) fprintf(el->el_outfile, "%s ",
+ m->m_name);
+ }
+ }
+ (void) fprintf(el->el_outfile, "\n");
+ return (0);
+ }
+ while (argv && (s = *argv++)) {
+ switch (*s) {
+ case '+':
+ case '-':
+ x = *s++;
+ break;
+ default:
+ x = '\0';
+ break;
+ }
+ d = s;
+ for (m = ttymodes; m->m_name; m++)
+ if (strcmp(m->m_name, d) == 0)
+ break;
+
+ if (!m->m_name) {
+ (void) fprintf(el->el_errfile,
+ "%s: Invalid argument `%s'.\n", name, d);
+ return (-1);
+ }
+ switch (x) {
+ case '+':
+ el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
+ el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+ break;
+ case '-':
+ el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+ el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
+ break;
+ default:
+ el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+ el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+ break;
+ }
+ }
+ return (0);
+}
+
+
+#ifdef notyet
+/* tty_printchar():
+ * DEbugging routine to print the tty characters
+ */
+private void
+tty_printchar(EditLine *el, unsigned char *s)
+{
+ ttyperm_t *m;
+ int i;
+
+ for (i = 0; i < C_NCC; i++) {
+ for (m = el->el_tty.t_t; m->m_name; m++)
+ if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
+ break;
+ if (m->m_name)
+ (void) fprintf(el->el_errfile, "%s ^%c ",
+ m->m_name, s[i] + 'A' - 1);
+ if (i % 5 == 0)
+ (void) fprintf(el->el_errfile, "\n");
+ }
+ (void) fprintf(el->el_errfile, "\n");
+}
+#endif /* notyet */
diff --git a/cmd-line-utils/libedit/tty.h b/cmd-line-utils/libedit/tty.h
new file mode 100644
index 00000000000..5fdcfadf0dc
--- /dev/null
+++ b/cmd-line-utils/libedit/tty.h
@@ -0,0 +1,484 @@
+/* $NetBSD: tty.h,v 1.8 2000/09/04 22:06:33 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)tty.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.tty.h: Local terminal header
+ */
+#ifndef _h_el_tty
+#define _h_el_tty
+
+#include "histedit.h"
+#include <termios.h>
+#include <unistd.h>
+
+/* Define our own since everyone gets it wrong! */
+#define CONTROL(A) ((A) & 037)
+
+/*
+ * Aix compatible names
+ */
+# if defined(VWERSE) && !defined(VWERASE)
+# define VWERASE VWERSE
+# endif /* VWERSE && !VWERASE */
+
+# if defined(VDISCRD) && !defined(VDISCARD)
+# define VDISCARD VDISCRD
+# endif /* VDISCRD && !VDISCARD */
+
+# if defined(VFLUSHO) && !defined(VDISCARD)
+# define VDISCARD VFLUSHO
+# endif /* VFLUSHO && VDISCARD */
+
+# if defined(VSTRT) && !defined(VSTART)
+# define VSTART VSTRT
+# endif /* VSTRT && ! VSTART */
+
+# if defined(VSTAT) && !defined(VSTATUS)
+# define VSTATUS VSTAT
+# endif /* VSTAT && ! VSTATUS */
+
+# ifndef ONLRET
+# define ONLRET 0
+# endif /* ONLRET */
+
+# ifndef TAB3
+# ifdef OXTABS
+# define TAB3 OXTABS
+# else
+# define TAB3 0
+# endif /* OXTABS */
+# endif /* !TAB3 */
+
+# if defined(OXTABS) && !defined(XTABS)
+# define XTABS OXTABS
+# endif /* OXTABS && !XTABS */
+
+# ifndef ONLCR
+# define ONLCR 0
+# endif /* ONLCR */
+
+# ifndef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN */
+
+# ifndef ECHOCTL
+# define ECHOCTL 0
+# endif /* ECHOCTL */
+
+# ifndef PARENB
+# define PARENB 0
+# endif /* PARENB */
+
+# ifndef EXTPROC
+# define EXTPROC 0
+# endif /* EXTPROC */
+
+# ifndef FLUSHO
+# define FLUSHO 0
+# endif /* FLUSHO */
+
+
+# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
+# define _POSIX_VDISABLE VDISABLE
+# endif /* VDISABLE && ! _POSIX_VDISABLE */
+
+/*
+ * Work around ISC's definition of IEXTEN which is
+ * XCASE!
+ */
+# ifdef ISC
+# if defined(IEXTEN) && defined(XCASE)
+# if IEXTEN == XCASE
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN == XCASE */
+# endif /* IEXTEN && XCASE */
+# if defined(IEXTEN) && !defined(XCASE)
+# define XCASE IEXTEN
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN && !XCASE */
+# endif /* ISC */
+
+/*
+ * Work around convex weirdness where turning off IEXTEN makes us
+ * lose all postprocessing!
+ */
+#if defined(convex) || defined(__convex__)
+# if defined(IEXTEN) && IEXTEN != 0
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN != 0 */
+#endif /* convex || __convex__ */
+
+/*
+ * So that we don't lose job control.
+ */
+#ifdef __SVR4
+# undef CSWTCH
+#endif
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE ((unsigned char) -1)
+#endif /* _POSIX_VDISABLE */
+
+#if !defined(CREPRINT) && defined(CRPRNT)
+# define CREPRINT CRPRNT
+#endif /* !CREPRINT && CRPRNT */
+#if !defined(CDISCARD) && defined(CFLUSH)
+# define CDISCARD CFLUSH
+#endif /* !CDISCARD && CFLUSH */
+
+#ifndef CINTR
+# define CINTR CONTROL('c')
+#endif /* CINTR */
+#ifndef CQUIT
+# define CQUIT 034 /* ^\ */
+#endif /* CQUIT */
+#ifndef CERASE
+# define CERASE 0177 /* ^? */
+#endif /* CERASE */
+#ifndef CKILL
+# define CKILL CONTROL('u')
+#endif /* CKILL */
+#ifndef CEOF
+# define CEOF CONTROL('d')
+#endif /* CEOF */
+#ifndef CEOL
+# define CEOL _POSIX_VDISABLE
+#endif /* CEOL */
+#ifndef CEOL2
+# define CEOL2 _POSIX_VDISABLE
+#endif /* CEOL2 */
+#ifndef CSWTCH
+# define CSWTCH _POSIX_VDISABLE
+#endif /* CSWTCH */
+#ifndef CDSWTCH
+# define CDSWTCH _POSIX_VDISABLE
+#endif /* CDSWTCH */
+#ifndef CERASE2
+# define CERASE2 _POSIX_VDISABLE
+#endif /* CERASE2 */
+#ifndef CSTART
+# define CSTART CONTROL('q')
+#endif /* CSTART */
+#ifndef CSTOP
+# define CSTOP CONTROL('s')
+#endif /* CSTOP */
+#ifndef CSUSP
+# define CSUSP CONTROL('z')
+#endif /* CSUSP */
+#ifndef CDSUSP
+# define CDSUSP CONTROL('y')
+#endif /* CDSUSP */
+
+#ifdef hpux
+
+# ifndef CREPRINT
+# define CREPRINT _POSIX_VDISABLE
+# endif /* CREPRINT */
+# ifndef CDISCARD
+# define CDISCARD _POSIX_VDISABLE
+# endif /* CDISCARD */
+# ifndef CLNEXT
+# define CLNEXT _POSIX_VDISABLE
+# endif /* CLNEXT */
+# ifndef CWERASE
+# define CWERASE _POSIX_VDISABLE
+# endif /* CWERASE */
+
+#else /* !hpux */
+
+# ifndef CREPRINT
+# define CREPRINT CONTROL('r')
+# endif /* CREPRINT */
+# ifndef CDISCARD
+# define CDISCARD CONTROL('o')
+# endif /* CDISCARD */
+# ifndef CLNEXT
+# define CLNEXT CONTROL('v')
+# endif /* CLNEXT */
+# ifndef CWERASE
+# define CWERASE CONTROL('w')
+# endif /* CWERASE */
+
+#endif /* hpux */
+
+#ifndef CSTATUS
+# define CSTATUS CONTROL('t')
+#endif /* CSTATUS */
+#ifndef CPAGE
+# define CPAGE ' '
+#endif /* CPAGE */
+#ifndef CPGOFF
+# define CPGOFF CONTROL('m')
+#endif /* CPGOFF */
+#ifndef CKILL2
+# define CKILL2 _POSIX_VDISABLE
+#endif /* CKILL2 */
+#ifndef CBRK
+# ifndef masscomp
+# define CBRK 0377
+# else
+# define CBRK '\0'
+# endif /* masscomp */
+#endif /* CBRK */
+#ifndef CMIN
+# define CMIN CEOF
+#endif /* CMIN */
+#ifndef CTIME
+# define CTIME CEOL
+#endif /* CTIME */
+
+/*
+ * Fix for sun inconsistency. On termio VSUSP and the rest of the
+ * ttychars > NCC are defined. So we undefine them.
+ */
+#if defined(TERMIO) || defined(POSIX)
+# if defined(POSIX) && defined(NCCS)
+# define NUMCC NCCS
+# else
+# ifdef NCC
+# define NUMCC NCC
+# endif /* NCC */
+# endif /* POSIX && NCCS */
+# ifdef NUMCC
+# ifdef VINTR
+# if NUMCC <= VINTR
+# undef VINTR
+# endif /* NUMCC <= VINTR */
+# endif /* VINTR */
+# ifdef VQUIT
+# if NUMCC <= VQUIT
+# undef VQUIT
+# endif /* NUMCC <= VQUIT */
+# endif /* VQUIT */
+# ifdef VERASE
+# if NUMCC <= VERASE
+# undef VERASE
+# endif /* NUMCC <= VERASE */
+# endif /* VERASE */
+# ifdef VKILL
+# if NUMCC <= VKILL
+# undef VKILL
+# endif /* NUMCC <= VKILL */
+# endif /* VKILL */
+# ifdef VEOF
+# if NUMCC <= VEOF
+# undef VEOF
+# endif /* NUMCC <= VEOF */
+# endif /* VEOF */
+# ifdef VEOL
+# if NUMCC <= VEOL
+# undef VEOL
+# endif /* NUMCC <= VEOL */
+# endif /* VEOL */
+# ifdef VEOL2
+# if NUMCC <= VEOL2
+# undef VEOL2
+# endif /* NUMCC <= VEOL2 */
+# endif /* VEOL2 */
+# ifdef VSWTCH
+# if NUMCC <= VSWTCH
+# undef VSWTCH
+# endif /* NUMCC <= VSWTCH */
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+# if NUMCC <= VDSWTCH
+# undef VDSWTCH
+# endif /* NUMCC <= VDSWTCH */
+# endif /* VDSWTCH */
+# ifdef VERASE2
+# if NUMCC <= VERASE2
+# undef VERASE2
+# endif /* NUMCC <= VERASE2 */
+# endif /* VERASE2 */
+# ifdef VSTART
+# if NUMCC <= VSTART
+# undef VSTART
+# endif /* NUMCC <= VSTART */
+# endif /* VSTART */
+# ifdef VSTOP
+# if NUMCC <= VSTOP
+# undef VSTOP
+# endif /* NUMCC <= VSTOP */
+# endif /* VSTOP */
+# ifdef VWERASE
+# if NUMCC <= VWERASE
+# undef VWERASE
+# endif /* NUMCC <= VWERASE */
+# endif /* VWERASE */
+# ifdef VSUSP
+# if NUMCC <= VSUSP
+# undef VSUSP
+# endif /* NUMCC <= VSUSP */
+# endif /* VSUSP */
+# ifdef VDSUSP
+# if NUMCC <= VDSUSP
+# undef VDSUSP
+# endif /* NUMCC <= VDSUSP */
+# endif /* VDSUSP */
+# ifdef VREPRINT
+# if NUMCC <= VREPRINT
+# undef VREPRINT
+# endif /* NUMCC <= VREPRINT */
+# endif /* VREPRINT */
+# ifdef VDISCARD
+# if NUMCC <= VDISCARD
+# undef VDISCARD
+# endif /* NUMCC <= VDISCARD */
+# endif /* VDISCARD */
+# ifdef VLNEXT
+# if NUMCC <= VLNEXT
+# undef VLNEXT
+# endif /* NUMCC <= VLNEXT */
+# endif /* VLNEXT */
+# ifdef VSTATUS
+# if NUMCC <= VSTATUS
+# undef VSTATUS
+# endif /* NUMCC <= VSTATUS */
+# endif /* VSTATUS */
+# ifdef VPAGE
+# if NUMCC <= VPAGE
+# undef VPAGE
+# endif /* NUMCC <= VPAGE */
+# endif /* VPAGE */
+# ifdef VPGOFF
+# if NUMCC <= VPGOFF
+# undef VPGOFF
+# endif /* NUMCC <= VPGOFF */
+# endif /* VPGOFF */
+# ifdef VKILL2
+# if NUMCC <= VKILL2
+# undef VKILL2
+# endif /* NUMCC <= VKILL2 */
+# endif /* VKILL2 */
+# ifdef VBRK
+# if NUMCC <= VBRK
+# undef VBRK
+# endif /* NUMCC <= VBRK */
+# endif /* VBRK */
+# ifdef VMIN
+# if NUMCC <= VMIN
+# undef VMIN
+# endif /* NUMCC <= VMIN */
+# endif /* VMIN */
+# ifdef VTIME
+# if NUMCC <= VTIME
+# undef VTIME
+# endif /* NUMCC <= VTIME */
+# endif /* VTIME */
+# endif /* NUMCC */
+#endif /* !POSIX */
+
+#define C_INTR 0
+#define C_QUIT 1
+#define C_ERASE 2
+#define C_KILL 3
+#define C_EOF 4
+#define C_EOL 5
+#define C_EOL2 6
+#define C_SWTCH 7
+#define C_DSWTCH 8
+#define C_ERASE2 9
+#define C_START 10
+#define C_STOP 11
+#define C_WERASE 12
+#define C_SUSP 13
+#define C_DSUSP 14
+#define C_REPRINT 15
+#define C_DISCARD 16
+#define C_LNEXT 17
+#define C_STATUS 18
+#define C_PAGE 19
+#define C_PGOFF 20
+#define C_KILL2 21
+#define C_BRK 22
+#define C_MIN 23
+#define C_TIME 24
+#define C_NCC 25
+#define C_SH(A) (1 << (A))
+
+/*
+ * Terminal dependend data structures
+ */
+#define EX_IO 0 /* while we are executing */
+#define ED_IO 1 /* while we are editing */
+#define TS_IO 2 /* new mode from terminal */
+#define QU_IO 2 /* used only for quoted chars */
+#define NN_IO 3 /* The number of entries */
+
+#define MD_INP 0
+#define MD_OUT 1
+#define MD_CTL 2
+#define MD_LIN 3
+#define MD_CHAR 4
+#define MD_NN 5
+
+typedef struct {
+ const char *t_name;
+ u_int t_setmask;
+ u_int t_clrmask;
+} ttyperm_t[NN_IO][MD_NN];
+
+typedef unsigned char ttychar_t[NN_IO][C_NCC];
+
+protected int tty_init(EditLine *);
+protected void tty_end(EditLine *);
+protected int tty_stty(EditLine *, int, const char**);
+protected int tty_rawmode(EditLine *);
+protected int tty_cookedmode(EditLine *);
+protected int tty_quotemode(EditLine *);
+protected int tty_noquotemode(EditLine *);
+protected void tty_bind_char(EditLine *, int);
+
+typedef struct {
+ ttyperm_t t_t;
+ ttychar_t t_c;
+ struct termios t_ex, t_ed, t_ts;
+ int t_tabs;
+ int t_eight;
+ speed_t t_speed;
+ int t_mode;
+ unsigned char t_vdisable;
+} el_tty_t;
+
+
+#endif /* _h_el_tty */
diff --git a/cmd-line-utils/libedit/vi.c b/cmd-line-utils/libedit/vi.c
new file mode 100644
index 00000000000..296e11eb4d9
--- /dev/null
+++ b/cmd-line-utils/libedit/vi.c
@@ -0,0 +1,935 @@
+/* $NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "compat.h"
+
+/*
+ * vi.c: Vi mode commands.
+ */
+#include "sys.h"
+#include "el.h"
+
+private el_action_t cv_action(EditLine *, int);
+private el_action_t cv_paste(EditLine *, int);
+
+/* cv_action():
+ * Handle vi actions.
+ */
+private el_action_t
+cv_action(EditLine *el, int c)
+{
+ char *cp, *kp;
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_vcmd.pos = 0;
+
+ el->el_chared.c_undo.isize = 0;
+ el->el_chared.c_undo.dsize = 0;
+ kp = el->el_chared.c_undo.buf;
+ for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
+ *kp++ = *cp;
+ el->el_chared.c_undo.dsize++;
+ }
+
+ el->el_chared.c_undo.action = INSERT;
+ el->el_chared.c_undo.ptr = el->el_line.buffer;
+ el->el_line.lastchar = el->el_line.buffer;
+ el->el_line.cursor = el->el_line.buffer;
+ if (c & INSERT)
+ el->el_map.current = el->el_map.key;
+
+ return (CC_REFRESH);
+ }
+ el->el_chared.c_vcmd.pos = el->el_line.cursor;
+ el->el_chared.c_vcmd.action = c;
+ return (CC_ARGHACK);
+
+#ifdef notdef
+ /*
+ * I don't think that this is needed. But we keep it for now
+ */
+ else
+ if (el_chared.c_vcmd.action == NOP) {
+ el->el_chared.c_vcmd.pos = el->el_line.cursor;
+ el->el_chared.c_vcmd.action = c;
+ return (CC_ARGHACK);
+ } else {
+ el->el_chared.c_vcmd.action = 0;
+ el->el_chared.c_vcmd.pos = 0;
+ return (CC_ERROR);
+ }
+#endif
+}
+
+
+/* cv_paste():
+ * Paste previous deletion before or after the cursor
+ */
+private el_action_t
+cv_paste(EditLine *el, int c)
+{
+ char *ptr;
+ c_undo_t *un = &el->el_chared.c_undo;
+
+#ifdef DEBUG_PASTE
+ (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
+ un->action, un->buf, un->isize, un->dsize);
+#endif
+ if (un->isize == 0)
+ return (CC_ERROR);
+
+ if (!c && el->el_line.cursor < el->el_line.lastchar)
+ el->el_line.cursor++;
+ ptr = el->el_line.cursor;
+
+ c_insert(el, (int) un->isize);
+ if (el->el_line.cursor + un->isize > el->el_line.lastchar)
+ return (CC_ERROR);
+ (void) memcpy(ptr, un->buf, un->isize);
+ return (CC_REFRESH);
+}
+
+
+/* vi_paste_next():
+ * Vi paste previous deletion to the right of the cursor
+ * [p]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_paste_next(EditLine *el, int c __attribute__((unused)))
+{
+
+ return (cv_paste(el, 0));
+}
+
+
+/* vi_paste_prev():
+ * Vi paste previous deletion to the left of the cursor
+ * [P]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_paste_prev(EditLine *el, int c __attribute__((unused)))
+{
+
+ return (cv_paste(el, 1));
+}
+
+
+/* vi_prev_space_word():
+ * Vi move to the previous space delimited word
+ * [B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_space_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.buffer)
+ return (CC_ERROR);
+
+ el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+ el->el_line.buffer,
+ el->el_state.argument,
+ cv__isword);
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* vi_prev_word():
+ * Vi move to the previous word
+ * [B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.buffer)
+ return (CC_ERROR);
+
+ el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+ el->el_line.buffer,
+ el->el_state.argument,
+ ce__isword);
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* vi_next_space_word():
+ * Vi move to the next space delimited word
+ * [W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_space_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.lastchar)
+ return (CC_ERROR);
+
+ el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
+ el->el_line.lastchar,
+ el->el_state.argument,
+ cv__isword);
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* vi_next_word():
+ * Vi move to the next word
+ * [w]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.lastchar)
+ return (CC_ERROR);
+
+ el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
+ el->el_line.lastchar,
+ el->el_state.argument,
+ ce__isword);
+
+ if (el->el_map.type == MAP_VI)
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* vi_change_case():
+ * Vi change case of character under the cursor and advance one character
+ * [~]
+ */
+protected el_action_t
+vi_change_case(EditLine *el, int c)
+{
+
+ if (el->el_line.cursor < el->el_line.lastchar) {
+ c = *el->el_line.cursor;
+ if (isupper(c))
+ *el->el_line.cursor++ = tolower(c);
+ else if (islower(c))
+ *el->el_line.cursor++ = toupper(c);
+ else
+ el->el_line.cursor++;
+ re_fastaddc(el);
+ return (CC_NORM);
+ }
+ return (CC_ERROR);
+}
+
+
+/* vi_change_meta():
+ * Vi change prefix command
+ * [c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_change_meta(EditLine *el, int c __attribute__((unused)))
+{
+
+ /*
+ * Delete with insert == change: first we delete and then we leave in
+ * insert mode.
+ */
+ return (cv_action(el, DELETE | INSERT));
+}
+
+
+/* vi_insert_at_bol():
+ * Vi enter insert mode at the beginning of line
+ * [I]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_insert_at_bol(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_line.cursor = el->el_line.buffer;
+ el->el_chared.c_vcmd.ins = el->el_line.cursor;
+
+ el->el_chared.c_undo.ptr = el->el_line.cursor;
+ el->el_chared.c_undo.action = DELETE;
+
+ el->el_map.current = el->el_map.key;
+ return (CC_CURSOR);
+}
+
+
+/* vi_replace_char():
+ * Vi replace character under the cursor with the next character typed
+ * [r]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_replace_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_map.current = el->el_map.key;
+ el->el_state.inputmode = MODE_REPLACE_1;
+ el->el_chared.c_undo.action = CHANGE;
+ el->el_chared.c_undo.ptr = el->el_line.cursor;
+ el->el_chared.c_undo.isize = 0;
+ el->el_chared.c_undo.dsize = 0;
+ return (CC_NORM);
+}
+
+
+/* vi_replace_mode():
+ * Vi enter replace mode
+ * [R]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_replace_mode(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_map.current = el->el_map.key;
+ el->el_state.inputmode = MODE_REPLACE;
+ el->el_chared.c_undo.action = CHANGE;
+ el->el_chared.c_undo.ptr = el->el_line.cursor;
+ el->el_chared.c_undo.isize = 0;
+ el->el_chared.c_undo.dsize = 0;
+ return (CC_NORM);
+}
+
+
+/* vi_substitute_char():
+ * Vi replace character under the cursor and enter insert mode
+ * [r]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_substitute_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ c_delafter(el, el->el_state.argument);
+ el->el_map.current = el->el_map.key;
+ return (CC_REFRESH);
+}
+
+
+/* vi_substitute_line():
+ * Vi substitute entire line
+ * [S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_substitute_line(EditLine *el, int c __attribute__((unused)))
+{
+
+ (void) em_kill_line(el, 0);
+ el->el_map.current = el->el_map.key;
+ return (CC_REFRESH);
+}
+
+
+/* vi_change_to_eol():
+ * Vi change to end of line
+ * [C]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_change_to_eol(EditLine *el, int c __attribute__((unused)))
+{
+
+ (void) ed_kill_line(el, 0);
+ el->el_map.current = el->el_map.key;
+ return (CC_REFRESH);
+}
+
+
+/* vi_insert():
+ * Vi enter insert mode
+ * [i]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_insert(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_map.current = el->el_map.key;
+
+ el->el_chared.c_vcmd.ins = el->el_line.cursor;
+ el->el_chared.c_undo.ptr = el->el_line.cursor;
+ el->el_chared.c_undo.action = DELETE;
+
+ return (CC_NORM);
+}
+
+
+/* vi_add():
+ * Vi enter insert mode after the cursor
+ * [a]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_add(EditLine *el, int c __attribute__((unused)))
+{
+ int ret;
+
+ el->el_map.current = el->el_map.key;
+ if (el->el_line.cursor < el->el_line.lastchar) {
+ el->el_line.cursor++;
+ if (el->el_line.cursor > el->el_line.lastchar)
+ el->el_line.cursor = el->el_line.lastchar;
+ ret = CC_CURSOR;
+ } else
+ ret = CC_NORM;
+
+ el->el_chared.c_vcmd.ins = el->el_line.cursor;
+ el->el_chared.c_undo.ptr = el->el_line.cursor;
+ el->el_chared.c_undo.action = DELETE;
+
+ return (ret);
+}
+
+
+/* vi_add_at_eol():
+ * Vi enter insert mode at end of line
+ * [A]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_add_at_eol(EditLine *el, int c __attribute__((unused)))
+{
+
+ el->el_map.current = el->el_map.key;
+ el->el_line.cursor = el->el_line.lastchar;
+
+ /* Mark where insertion begins */
+ el->el_chared.c_vcmd.ins = el->el_line.lastchar;
+ el->el_chared.c_undo.ptr = el->el_line.lastchar;
+ el->el_chared.c_undo.action = DELETE;
+ return (CC_CURSOR);
+}
+
+
+/* vi_delete_meta():
+ * Vi delete prefix command
+ * [d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_delete_meta(EditLine *el, int c __attribute__((unused)))
+{
+
+ return (cv_action(el, DELETE));
+}
+
+
+/* vi_end_word():
+ * Vi move to the end of the current space delimited word
+ * [E]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_end_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.lastchar)
+ return (CC_ERROR);
+
+ el->el_line.cursor = cv__endword(el->el_line.cursor,
+ el->el_line.lastchar, el->el_state.argument);
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* vi_to_end_word():
+ * Vi move to the end of the current word
+ * [e]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_end_word(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_line.cursor == el->el_line.lastchar)
+ return (CC_ERROR);
+
+ el->el_line.cursor = cv__endword(el->el_line.cursor,
+ el->el_line.lastchar, el->el_state.argument);
+
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ el->el_line.cursor++;
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+}
+
+
+/* vi_undo():
+ * Vi undo last change
+ * [u]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_undo(EditLine *el, int c __attribute__((unused)))
+{
+ char *cp, *kp;
+ char temp;
+ int i, size;
+ c_undo_t *un = &el->el_chared.c_undo;
+
+#ifdef DEBUG_UNDO
+ (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
+ un->action, un->buf, un->isize, un->dsize);
+#endif
+ switch (un->action) {
+ case DELETE:
+ if (un->dsize == 0)
+ return (CC_NORM);
+
+ (void) memcpy(un->buf, un->ptr, un->dsize);
+ for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
+ *cp = cp[un->dsize];
+
+ el->el_line.lastchar -= un->dsize;
+ el->el_line.cursor = un->ptr;
+
+ un->action = INSERT;
+ un->isize = un->dsize;
+ un->dsize = 0;
+ break;
+
+ case DELETE | INSERT:
+ size = un->isize - un->dsize;
+ if (size > 0)
+ i = un->dsize;
+ else
+ i = un->isize;
+ cp = un->ptr;
+ kp = un->buf;
+ while (i-- > 0) {
+ temp = *kp;
+ *kp++ = *cp;
+ *cp++ = temp;
+ }
+ if (size > 0) {
+ el->el_line.cursor = cp;
+ c_insert(el, size);
+ while (size-- > 0 && cp < el->el_line.lastchar) {
+ temp = *kp;
+ *kp++ = *cp;
+ *cp++ = temp;
+ }
+ } else if (size < 0) {
+ size = -size;
+ for (; cp <= el->el_line.lastchar; cp++) {
+ *kp++ = *cp;
+ *cp = cp[size];
+ }
+ el->el_line.lastchar -= size;
+ }
+ el->el_line.cursor = un->ptr;
+ i = un->dsize;
+ un->dsize = un->isize;
+ un->isize = i;
+ break;
+
+ case INSERT:
+ if (un->isize == 0)
+ return (CC_NORM);
+
+ el->el_line.cursor = un->ptr;
+ c_insert(el, (int) un->isize);
+ (void) memcpy(un->ptr, un->buf, un->isize);
+ un->action = DELETE;
+ un->dsize = un->isize;
+ un->isize = 0;
+ break;
+
+ case CHANGE:
+ if (un->isize == 0)
+ return (CC_NORM);
+
+ el->el_line.cursor = un->ptr;
+ size = (int) (el->el_line.cursor - el->el_line.lastchar);
+ if (size < (int)un->isize)
+ size = un->isize;
+ cp = un->ptr;
+ kp = un->buf;
+ for (i = 0; i < size; i++) {
+ temp = *kp;
+ *kp++ = *cp;
+ *cp++ = temp;
+ }
+ un->dsize = 0;
+ break;
+
+ default:
+ return (CC_ERROR);
+ }
+
+ return (CC_REFRESH);
+}
+
+
+/* vi_command_mode():
+ * Vi enter command mode (use alternative key bindings)
+ * [<ESC>]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_command_mode(EditLine *el, int c __attribute__((unused)))
+{
+ int size;
+
+ /* [Esc] cancels pending action */
+ el->el_chared.c_vcmd.ins = 0;
+ el->el_chared.c_vcmd.action = NOP;
+ el->el_chared.c_vcmd.pos = 0;
+
+ el->el_state.doingarg = 0;
+ size = el->el_chared.c_undo.ptr - el->el_line.cursor;
+ if (size < 0)
+ size = -size;
+ if (el->el_chared.c_undo.action == (INSERT | DELETE) ||
+ el->el_chared.c_undo.action == DELETE)
+ el->el_chared.c_undo.dsize = size;
+ else
+ el->el_chared.c_undo.isize = size;
+
+ el->el_state.inputmode = MODE_INSERT;
+ el->el_map.current = el->el_map.alt;
+#ifdef VI_MOVE
+ if (el->el_line.cursor > el->el_line.buffer)
+ el->el_line.cursor--;
+#endif
+ return (CC_CURSOR);
+}
+
+
+/* vi_zero():
+ * Vi move to the beginning of line
+ * [0]
+ */
+protected el_action_t
+vi_zero(EditLine *el, int c)
+{
+
+ if (el->el_state.doingarg) {
+ if (el->el_state.argument > 1000000)
+ return (CC_ERROR);
+ el->el_state.argument =
+ (el->el_state.argument * 10) + (c - '0');
+ return (CC_ARGHACK);
+ } else {
+ el->el_line.cursor = el->el_line.buffer;
+ if (el->el_chared.c_vcmd.action & DELETE) {
+ cv_delfini(el);
+ return (CC_REFRESH);
+ }
+ return (CC_CURSOR);
+ }
+}
+
+
+/* vi_delete_prev_char():
+ * Vi move to previous character (backspace)
+ * [^H]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_delete_prev_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_chared.c_vcmd.ins == 0)
+ return (CC_ERROR);
+
+ if (el->el_chared.c_vcmd.ins >
+ el->el_line.cursor - el->el_state.argument)
+ return (CC_ERROR);
+
+ c_delbefore(el, el->el_state.argument);
+ el->el_line.cursor -= el->el_state.argument;
+
+ return (CC_REFRESH);
+}
+
+
+/* vi_list_or_eof():
+ * Vi list choices for completion or indicate end of file if empty line
+ * [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_list_or_eof(EditLine *el, int c __attribute__((unused)))
+{
+
+#ifdef notyet
+ if (el->el_line.cursor == el->el_line.lastchar &&
+ el->el_line.cursor == el->el_line.buffer) {
+#endif
+ term_overwrite(el, STReof, 4); /* then do a EOF */
+ term__flush();
+ return (CC_EOF);
+#ifdef notyet
+ } else {
+ re_goto_bottom(el);
+ *el->el_line.lastchar = '\0'; /* just in case */
+ return (CC_LIST_CHOICES);
+ }
+#endif
+}
+
+
+/* vi_kill_line_prev():
+ * Vi cut from beginning of line to cursor
+ * [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_kill_line_prev(EditLine *el, int c __attribute__((unused)))
+{
+ char *kp, *cp;
+
+ cp = el->el_line.buffer;
+ kp = el->el_chared.c_kill.buf;
+ while (cp < el->el_line.cursor)
+ *kp++ = *cp++; /* copy it */
+ el->el_chared.c_kill.last = kp;
+ c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
+ el->el_line.cursor = el->el_line.buffer; /* zap! */
+ return (CC_REFRESH);
+}
+
+
+/* vi_search_prev():
+ * Vi search history previous
+ * [?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_search_prev(EditLine *el, int c __attribute__((unused)))
+{
+
+ return (cv_search(el, ED_SEARCH_PREV_HISTORY));
+}
+
+
+/* vi_search_next():
+ * Vi search history next
+ * [/]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_search_next(EditLine *el, int c __attribute__((unused)))
+{
+
+ return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
+}
+
+
+/* vi_repeat_search_next():
+ * Vi repeat current search in the same search direction
+ * [n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_search_next(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_search.patlen == 0)
+ return (CC_ERROR);
+ else
+ return (cv_repeat_srch(el, el->el_search.patdir));
+}
+
+
+/* vi_repeat_search_prev():
+ * Vi repeat current search in the opposite search direction
+ * [N]
+ */
+/*ARGSUSED*/
+protected el_action_t
+vi_repeat_search_prev(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_search.patlen == 0)
+ return (CC_ERROR);
+ else
+ return (cv_repeat_srch(el,
+ el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
+ ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
+}
+
+
+/* vi_next_char():
+ * Vi move to the character specified next
+ * [f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_char(EditLine *el, int c __attribute__((unused)))
+{
+ char ch;
+
+ if (el_getc(el, &ch) != 1)
+ return (ed_end_of_file(el, 0));
+
+ el->el_search.chadir = CHAR_FWD;
+ el->el_search.chacha = ch;
+
+ return (cv_csearch_fwd(el, ch, el->el_state.argument, 0));
+
+}
+
+
+/* vi_prev_char():
+ * Vi move to the character specified previous
+ * [F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_char(EditLine *el, int c __attribute__((unused)))
+{
+ char ch;
+
+ if (el_getc(el, &ch) != 1)
+ return (ed_end_of_file(el, 0));
+
+ el->el_search.chadir = CHAR_BACK;
+ el->el_search.chacha = ch;
+
+ return (cv_csearch_back(el, ch, el->el_state.argument, 0));
+}
+
+
+/* vi_to_next_char():
+ * Vi move up to the character specified next
+ * [t]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_next_char(EditLine *el, int c __attribute__((unused)))
+{
+ char ch;
+
+ if (el_getc(el, &ch) != 1)
+ return (ed_end_of_file(el, 0));
+
+ return (cv_csearch_fwd(el, ch, el->el_state.argument, 1));
+
+}
+
+
+/* vi_to_prev_char():
+ * Vi move up to the character specified previous
+ * [T]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_prev_char(EditLine *el, int c __attribute__((unused)))
+{
+ char ch;
+
+ if (el_getc(el, &ch) != 1)
+ return (ed_end_of_file(el, 0));
+
+ return (cv_csearch_back(el, ch, el->el_state.argument, 1));
+}
+
+
+/* vi_repeat_next_char():
+ * Vi repeat current character search in the same search direction
+ * [;]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_next_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_search.chacha == 0)
+ return (CC_ERROR);
+
+ return (el->el_search.chadir == CHAR_FWD
+ ? cv_csearch_fwd(el, el->el_search.chacha,
+ el->el_state.argument, 0)
+ : cv_csearch_back(el, el->el_search.chacha,
+ el->el_state.argument, 0));
+}
+
+
+/* vi_repeat_prev_char():
+ * Vi repeat current character search in the opposite search direction
+ * [,]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_prev_char(EditLine *el, int c __attribute__((unused)))
+{
+
+ if (el->el_search.chacha == 0)
+ return (CC_ERROR);
+
+ return el->el_search.chadir == CHAR_BACK ?
+ cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
+ cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
+}
diff --git a/readline/.cvsignore b/cmd-line-utils/readline/.cvsignore
index e9955884756..e9955884756 100644
--- a/readline/.cvsignore
+++ b/cmd-line-utils/readline/.cvsignore
diff --git a/cmd-line-utils/readline/COPYING b/cmd-line-utils/readline/COPYING
new file mode 100644
index 00000000000..1bf15263878
--- /dev/null
+++ b/cmd-line-utils/readline/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/cmd-line-utils/readline/INSTALL b/cmd-line-utils/readline/INSTALL
new file mode 100644
index 00000000000..adb27a9f222
--- /dev/null
+++ b/cmd-line-utils/readline/INSTALL
@@ -0,0 +1,273 @@
+Basic Installation
+==================
+
+These are installation instructions for Readline-4.3.
+
+The simplest way to compile readline is:
+
+ 1. `cd' to the directory containing the readline source code and type
+ `./configure' to configure readline for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes some time. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile readline and build the static readline
+ and history libraries. If supported, the shared readline and history
+ libraries will be built also. See below for instructions on compiling
+ the other parts of the distribution. Typing `make everything' will
+ cause the static and shared libraries (if supported) and the example
+ programs to be built.
+
+ 3. Type `make install' to install the static readline and history
+ libraries, the readline include files, the documentation, and, if
+ supported, the shared readline and history libraries.
+
+ 4. You can remove the created libraries and object files from the
+ build directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile readline for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the readline developers, and should be used with care.
+
+The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It
+uses those values to create a `Makefile' in the build directory,
+and Makefiles in the `doc', `shlib', and `examples'
+subdirectories. It also creates a `config.h' file containing
+system-dependent definitions. Finally, it creates a shell script
+`config.status' that you can run in the future to recreate the
+current configuration, a file `config.cache' that saves the
+results of its tests to speed up reconfiguring, and a file
+`config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+If you need to do unusual things to compile readline, please try
+to figure out how `configure' could check whether to do them, and
+mail diffs or instructions to <bug-readline@gnu.org> so they can
+be considered for the next release. If at some point
+`config.cache' contains results you don't want to keep, you may
+remove or edit it.
+
+The file `configure.in' is used to create `configure' by a
+program called `autoconf'. You only need `configure.in' if you
+want to change it or regenerate `configure' using a newer version
+of `autoconf'. The readline `configure.in' requires autoconf
+version 2.50 or newer.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile readline for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile readline for one architecture at a
+time in the source code directory. After you have installed
+readline for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the readline libraries in
+`/usr/local/lib', the include files in
+`/usr/local/include/readline', the man pages in `/usr/local/man',
+and the info files in `/usr/local/info'. You can specify an
+installation prefix other than `/usr/local' by giving `configure'
+the option `--prefix=PATH' or by supplying a value for the
+DESTDIR variable when running `make install'.
+
+You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.
+If you give `configure' the option `--exec-prefix=PATH', the
+readline Makefiles will use PATH as the prefix for installing the
+libraries. Documentation and other data files will still use the
+regular prefix.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' can not figure out
+automatically, but need to determine by the type of host readline
+will run on. Usually `configure' can figure that out, but if it
+prints a message saying it can not guess the host type, give it
+the `--host=TYPE' option. TYPE can either be a short name for
+the system type, such as `sun4', or a canonical name with three
+fields: CPU-COMPANY-SYSTEM (e.g., i386-unknown-freebsd4.2).
+
+See the file `config.sub' for the possible values of each field.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: the readline `configure' looks for a site script, but not
+all `configure' scripts do.
+
+Operation Controls
+==================
+
+`configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
+Optional Features
+=================
+
+The readline `configure' recognizes a single `--with-PACKAGE' option:
+
+`--with-curses'
+ This tells readline that it can find the termcap library functions
+ (tgetent, et al.) in the curses library, rather than a separate
+ termcap library. Readline uses the termcap functions, but does not
+ link with the termcap or curses library itself, allowing applications
+ which link with readline the to choose an appropriate library.
+ This option tells readline to link the example programs with the
+ curses library rather than libtermcap.
+
+`configure' also recognizes two `--enable-FEATURE' options:
+
+`--enable-shared'
+ Build the shared libraries by default on supported platforms. The
+ default is `yes'.
+
+`--enable-static'
+ Build the static libraries by default. The default is `yes'.
+
+Shared Libraries
+================
+
+There is support for building shared versions of the readline and
+history libraries. The configure script creates a Makefile in
+the `shlib' subdirectory, and typing `make shared' will cause
+shared versions of the readline and history libraries to be built
+on supported platforms.
+
+If `configure' is given the `--enable-shared' option, it will attempt
+to build the shared libraries by default on supported platforms.
+
+Configure calls the script support/shobj-conf to test whether or
+not shared library creation is supported and to generate the values
+of variables that are substituted into shlib/Makefile. If you
+try to build shared libraries on an unsupported platform, `make'
+will display a message asking you to update support/shobj-conf for
+your platform.
+
+If you need to update support/shobj-conf, you will need to create
+a `stanza' for your operating system and compiler. The script uses
+the value of host_os and ${CC} as determined by configure. For
+instance, FreeBSD 4.2 with any version of gcc is identified as
+`freebsd4.2-gcc*'.
+
+In the stanza for your operating system-compiler pair, you will need to
+define several variables. They are:
+
+SHOBJ_CC The C compiler used to compile source files into shareable
+ object files. This is normally set to the value of ${CC}
+ by configure, and should not need to be changed.
+
+SHOBJ_CFLAGS Flags to pass to the C compiler ($SHOBJ_CC) to create
+ position-independent code. If you are using gcc, this
+ should probably be set to `-fpic'.
+
+SHOBJ_LD The link editor to be used to create the shared library from
+ the object files created by $SHOBJ_CC. If you are using
+ gcc, a value of `gcc' will probably work.
+
+SHOBJ_LDFLAGS Flags to pass to SHOBJ_LD to enable shared object creation.
+ If you are using gcc, `-shared' may be all that is necessary.
+ These should be the flags needed for generic shared object
+ creation.
+
+SHLIB_XLDFLAGS Additional flags to pass to SHOBJ_LD for shared library
+ creation. Many systems use the -R option to the link
+ editor to embed a path within the library for run-time
+ library searches. A reasonable value for such systems would
+ be `-R$(libdir)'.
+
+SHLIB_LIBS Any additional libraries that shared libraries should be
+ linked against when they are created.
+
+SHLIB_LIBSUFF The suffix to add to `libreadline' and `libhistory' when
+ generating the filename of the shared library. Many systems
+ use `so'; HP-UX uses `sl'.
+
+SHLIB_LIBVERSION The string to append to the filename to indicate the version
+ of the shared library. It should begin with $(SHLIB_LIBSUFF),
+ and possibly include version information that allows the
+ run-time loader to load the version of the shared library
+ appropriate for a particular program. Systems using shared
+ libraries similar to SunOS 4.x use major and minor library
+ version numbers; for those systems a value of
+ `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' is appropriate.
+ Systems based on System V Release 4 don't use minor version
+ numbers; use `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' on those systems.
+ Other Unix versions use different schemes.
+
+SHLIB_STATUS Set this to `supported' when you have defined the other
+ necessary variables. Make uses this to determine whether
+ or not shared library creation should be attempted. If
+ shared libraries are not supported, this will be set to
+ `unsupported'.
+
+You should look at the existing stanzas in support/shobj-conf for ideas.
+
+Once you have updated support/shobj-conf, re-run configure and type
+`make shared' or `make'. The shared libraries will be created in the
+shlib subdirectory.
+
+If shared libraries are created, `make install' will install them.
+You may install only the shared libraries by running `make
+install-shared' from the top-level build directory. Running `make
+install' in the shlib subdirectory will also work. If you don't want
+to install any created shared libraries, run `make install-static'.
diff --git a/cmd-line-utils/readline/Makefile.am b/cmd-line-utils/readline/Makefile.am
new file mode 100644
index 00000000000..7c4fe8eeb91
--- /dev/null
+++ b/cmd-line-utils/readline/Makefile.am
@@ -0,0 +1,35 @@
+## Process this file with automake to create Makefile.in
+# Makefile for the GNU readline library.
+# Copyright (C) 1994,1996,1997 Free Software Foundation, Inc.
+
+# Last -I$(top_srcdir) needed for RedHat!
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)
+
+noinst_LIBRARIES = libreadline.a
+
+libreadline_a_SOURCES = readline.c funmap.c keymaps.c \
+ vi_mode.c parens.c rltty.c \
+ complete.c bind.c isearch.c \
+ display.c signals.c \
+ util.c kill.c \
+ undo.c macro.c input.c \
+ callback.c terminal.c xmalloc.c \
+ history.c histsearch.c histexpand.c \
+ histfile.c nls.c search.c \
+ shell.c tilde.c misc.c text.c mbutil.c
+
+pkginclude_HEADERS = readline.h chardefs.h keymaps.h \
+ history.h tilde.h rlmbutil.h rltypedefs.h rlprivate.h \
+ rlshell.h xmalloc.h
+
+noinst_HEADERS = rldefs.h histlib.h rlwinsize.h \
+ posixstat.h posixdir.h posixjmp.h \
+ tilde.h rlconf.h rltty.h ansi_stdlib.h \
+ tcap.h rlstdc.h
+
+EXTRA_DIST= emacs_keymap.c vi_keymap.c
+
+DEFS = -DUNDEF_THREADS_HACK -DHAVE_CONFIG_H -DNO_KILL_INTR
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/cmd-line-utils/readline/README b/cmd-line-utils/readline/README
new file mode 100644
index 00000000000..7aa939452fb
--- /dev/null
+++ b/cmd-line-utils/readline/README
@@ -0,0 +1,172 @@
+Introduction
+============
+
+This is the Gnu Readline library, version 4.3.
+
+The Readline library provides a set of functions for use by applications
+that allow users to edit command lines as they are typed in. Both
+Emacs and vi editing modes are available. The Readline library includes
+additional functions to maintain a list of previously-entered command
+lines, to recall and perhaps reedit those lines, and perform csh-like
+history expansion on previous commands.
+
+The history facilites are also placed into a separate library, the
+History library, as part of the build process. The History library
+may be used without Readline in applications which desire its
+capabilities.
+
+The Readline library is free software, distributed under the terms of
+the [GNU] General Public License, version 2. For more information, see
+the file COPYING.
+
+To build the library, try typing `./configure', then `make'. The
+configuration process is automated, so no further intervention should
+be necessary. Readline builds with `gcc' by default if it is
+available. If you want to use `cc' instead, type
+
+ CC=cc ./configure
+
+if you are using a Bourne-style shell. If you are not, the following
+may work:
+
+ env CC=cc ./configure
+
+Read the file INSTALL in this directory for more information about how
+to customize and control the build process.
+
+The file rlconf.h contains C preprocessor defines that enable and disable
+certain Readline features.
+
+The special make target `everything' will build the static and shared
+libraries (if the target platform supports them) and the examples.
+
+Examples
+========
+
+There are several example programs that use Readline features in the
+examples directory. The `rl' program is of particular interest. It
+is a command-line interface to Readline, suitable for use in shell
+scripts in place of `read'.
+
+Shared Libraries
+================
+
+There is skeletal support for building shared versions of the
+Readline and History libraries. The configure script creates
+a Makefile in the `shlib' subdirectory, and typing `make shared'
+will cause shared versions of the Readline and History libraries
+to be built on supported platforms.
+
+If `configure' is given the `--enable-shared' option, it will attempt
+to build the shared libraries by default on supported platforms.
+
+Configure calls the script support/shobj-conf to test whether or
+not shared library creation is supported and to generate the values
+of variables that are substituted into shlib/Makefile. If you
+try to build shared libraries on an unsupported platform, `make'
+will display a message asking you to update support/shobj-conf for
+your platform.
+
+If you need to update support/shobj-conf, you will need to create
+a `stanza' for your operating system and compiler. The script uses
+the value of host_os and ${CC} as determined by configure. For
+instance, FreeBSD 4.2 with any version of gcc is identified as
+`freebsd4.2-gcc*'.
+
+In the stanza for your operating system-compiler pair, you will need to
+define several variables. They are:
+
+SHOBJ_CC The C compiler used to compile source files into shareable
+ object files. This is normally set to the value of ${CC}
+ by configure, and should not need to be changed.
+
+SHOBJ_CFLAGS Flags to pass to the C compiler ($SHOBJ_CC) to create
+ position-independent code. If you are using gcc, this
+ should probably be set to `-fpic'.
+
+SHOBJ_LD The link editor to be used to create the shared library from
+ the object files created by $SHOBJ_CC. If you are using
+ gcc, a value of `gcc' will probably work.
+
+SHOBJ_LDFLAGS Flags to pass to SHOBJ_LD to enable shared object creation.
+ If you are using gcc, `-shared' may be all that is necessary.
+ These should be the flags needed for generic shared object
+ creation.
+
+SHLIB_XLDFLAGS Additional flags to pass to SHOBJ_LD for shared library
+ creation. Many systems use the -R option to the link
+ editor to embed a path within the library for run-time
+ library searches. A reasonable value for such systems would
+ be `-R$(libdir)'.
+
+SHLIB_LIBS Any additional libraries that shared libraries should be
+ linked against when they are created.
+
+SHLIB_LIBSUFF The suffix to add to `libreadline' and `libhistory' when
+ generating the filename of the shared library. Many systems
+ use `so'; HP-UX uses `sl'.
+
+SHLIB_LIBVERSION The string to append to the filename to indicate the version
+ of the shared library. It should begin with $(SHLIB_LIBSUFF),
+ and possibly include version information that allows the
+ run-time loader to load the version of the shared library
+ appropriate for a particular program. Systems using shared
+ libraries similar to SunOS 4.x use major and minor library
+ version numbers; for those systems a value of
+ `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' is appropriate.
+ Systems based on System V Release 4 don't use minor version
+ numbers; use `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' on those systems.
+ Other Unix versions use different schemes.
+
+SHLIB_STATUS Set this to `supported' when you have defined the other
+ necessary variables. Make uses this to determine whether
+ or not shared library creation should be attempted.
+
+You should look at the existing stanzas in support/shobj-conf for ideas.
+
+Once you have updated support/shobj-conf, re-run configure and type
+`make shared'. The shared libraries will be created in the shlib
+subdirectory.
+
+If shared libraries are created, `make install' will install them.
+You may install only the shared libraries by running `make
+install-shared' from the top-level build directory. Running `make
+install' in the shlib subdirectory will also work. If you don't want
+to install any created shared libraries, run `make install-static'.
+
+Documentation
+=============
+
+The documentation for the Readline and History libraries appears in
+the `doc' subdirectory. There are three texinfo files and a
+Unix-style manual page describing the facilities available in the
+Readline library. The texinfo files include both user and
+programmer's manuals. HTML versions of the manuals appear in the
+`doc' subdirectory as well.
+
+Reporting Bugs
+==============
+
+Bug reports for Readline should be sent to:
+
+ bug-readline@gnu.org
+
+When reporting a bug, please include the following information:
+
+ * the version number and release status of Readline (e.g., 4.2-release)
+ * the machine and OS that it is running on
+ * a list of the compilation flags or the contents of `config.h', if
+ appropriate
+ * a description of the bug
+ * a recipe for recreating the bug reliably
+ * a fix for the bug if you have one!
+
+If you would like to contact the Readline maintainer directly, send mail
+to bash-maintainers@gnu.org.
+
+Since Readline is developed along with bash, the bug-bash@gnu.org mailing
+list (mirrored to the Usenet newsgroup gnu.bash.bug) often contains
+Readline bug reports and fixes.
+
+Chet Ramey
+chet@po.cwru.edu
diff --git a/cmd-line-utils/readline/ansi_stdlib.h b/cmd-line-utils/readline/ansi_stdlib.h
new file mode 100644
index 00000000000..db13cd234bd
--- /dev/null
+++ b/cmd-line-utils/readline/ansi_stdlib.h
@@ -0,0 +1,54 @@
+/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
+/* A minimal stdlib.h containing extern declarations for those functions
+ that bash uses. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Bash; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_STDLIB_H_)
+#define _STDLIB_H_ 1
+
+/* String conversion functions. */
+extern int atoi ();
+
+extern double atof ();
+extern double strtod ();
+
+/* Memory allocation functions. */
+/* Generic pointer type. */
+#ifndef PTR_T
+
+#if defined (__STDC__)
+# define PTR_T void *
+#else
+# define PTR_T char *
+#endif
+
+#endif /* PTR_T */
+
+extern PTR_T malloc ();
+extern PTR_T realloc ();
+extern void free ();
+
+/* Other miscellaneous functions. */
+extern void abort ();
+extern void exit ();
+extern char *getenv ();
+extern void qsort ();
+
+#endif /* _STDLIB_H */
diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c
new file mode 100644
index 00000000000..7e8ca04e0d6
--- /dev/null
+++ b/cmd-line-utils/readline/bind.c
@@ -0,0 +1,2151 @@
+/* bind.c -- key binding and startup file support for the readline library. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+/* Variables exported by this file. */
+Keymap rl_binding_keymap;
+
+static char *_rl_read_file PARAMS((char *, size_t *));
+static void _rl_init_file_error PARAMS((const char *));
+static int _rl_read_init_file PARAMS((const char *, int));
+static int glean_key_from_name PARAMS((char *));
+static int substring_member_of_array PARAMS((char *, const char **));
+
+static int currently_reading_init_file;
+
+/* used only in this file */
+static int _rl_prefer_visible_bell = 1;
+
+/* **************************************************************** */
+/* */
+/* Binding keys */
+/* */
+/* **************************************************************** */
+
+/* rl_add_defun (char *name, rl_command_func_t *function, int key)
+ Add NAME to the list of named functions. Make FUNCTION be the function
+ that gets called. If KEY is not -1, then bind it. */
+int
+rl_add_defun (name, function, key)
+ const char *name;
+ rl_command_func_t *function;
+ int key;
+{
+ if (key != -1)
+ rl_bind_key (key, function);
+ rl_add_funmap_entry (name, function);
+ return 0;
+}
+
+/* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */
+int
+rl_bind_key (key, function)
+ int key;
+ rl_command_func_t *function;
+{
+ if (key < 0)
+ return (key);
+
+ if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+ {
+ if (_rl_keymap[ESC].type == ISKMAP)
+ {
+ Keymap escmap;
+
+ escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
+ key = UNMETA (key);
+ escmap[key].type = ISFUNC;
+ escmap[key].function = function;
+ return (0);
+ }
+ return (key);
+ }
+
+ _rl_keymap[key].type = ISFUNC;
+ _rl_keymap[key].function = function;
+ rl_binding_keymap = _rl_keymap;
+ return (0);
+}
+
+/* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid
+ KEY. */
+int
+rl_bind_key_in_map (key, function, map)
+ int key;
+ rl_command_func_t *function;
+ Keymap map;
+{
+ int result;
+ Keymap oldmap;
+
+ oldmap = _rl_keymap;
+ _rl_keymap = map;
+ result = rl_bind_key (key, function);
+ _rl_keymap = oldmap;
+ return (result);
+}
+
+/* Make KEY do nothing in the currently selected keymap.
+ Returns non-zero in case of error. */
+int
+rl_unbind_key (key)
+ int key;
+{
+ return (rl_bind_key (key, (rl_command_func_t *)NULL));
+}
+
+/* Make KEY do nothing in MAP.
+ Returns non-zero in case of error. */
+int
+rl_unbind_key_in_map (key, map)
+ int key;
+ Keymap map;
+{
+ return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
+}
+
+/* Unbind all keys bound to FUNCTION in MAP. */
+int
+rl_unbind_function_in_map (func, map)
+ rl_command_func_t *func;
+ Keymap map;
+{
+ register int i, rval;
+
+ for (i = rval = 0; i < KEYMAP_SIZE; i++)
+ {
+ if (map[i].type == ISFUNC && map[i].function == func)
+ {
+ map[i].function = (rl_command_func_t *)NULL;
+ rval = 1;
+ }
+ }
+ return rval;
+}
+
+int
+rl_unbind_command_in_map (command, map)
+ const char *command;
+ Keymap map;
+{
+ rl_command_func_t *func;
+
+ func = rl_named_function (command);
+ if (func == 0)
+ return 0;
+ return (rl_unbind_function_in_map (func, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ FUNCTION. This makes new keymaps as necessary. The initial
+ place to do bindings is in MAP. */
+int
+rl_set_key (keyseq, function, map)
+ const char *keyseq;
+ rl_command_func_t *function;
+ Keymap map;
+{
+ return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ the string of characters MACRO. This makes new keymaps as
+ necessary. The initial place to do bindings is in MAP. */
+int
+rl_macro_bind (keyseq, macro, map)
+ const char *keyseq, *macro;
+ Keymap map;
+{
+ char *macro_keys;
+ int macro_keys_len;
+
+ macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
+
+ if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+ {
+ free (macro_keys);
+ return -1;
+ }
+ rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+ return 0;
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ the arbitrary pointer DATA. TYPE says what kind of data is
+ pointed to by DATA, right now this can be a function (ISFUNC),
+ a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps
+ as necessary. The initial place to do bindings is in MAP. */
+int
+rl_generic_bind (type, keyseq, data, map)
+ int type;
+ const char *keyseq;
+ char *data;
+ Keymap map;
+{
+ char *keys;
+ int keys_len;
+ register int i;
+ KEYMAP_ENTRY k;
+
+ k.function = 0;
+
+ /* If no keys to bind to, exit right away. */
+ if (!keyseq || !*keyseq)
+ {
+ if (type == ISMACR)
+ free (data);
+ return -1;
+ }
+
+ keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
+
+ /* Translate the ASCII representation of KEYSEQ into an array of
+ characters. Stuff the characters into KEYS, and the length of
+ KEYS into KEYS_LEN. */
+ if (rl_translate_keyseq (keyseq, keys, &keys_len))
+ {
+ free (keys);
+ return -1;
+ }
+
+ /* Bind keys, making new keymaps as necessary. */
+ for (i = 0; i < keys_len; i++)
+ {
+ unsigned char uc = keys[i];
+ int ic;
+
+ ic = uc;
+ if (ic < 0 || ic >= KEYMAP_SIZE)
+ return -1;
+
+ if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
+ {
+ ic = UNMETA (ic);
+ if (map[ESC].type == ISKMAP)
+ map = FUNCTION_TO_KEYMAP (map, ESC);
+ }
+
+ if ((i + 1) < keys_len)
+ {
+ if (map[ic].type != ISKMAP)
+ {
+ /* We allow subsequences of keys. If a keymap is being
+ created that will `shadow' an existing function or macro
+ key binding, we save that keybinding into the ANYOTHERKEY
+ index in the new map. The dispatch code will look there
+ to find the function to execute if the subsequence is not
+ matched. ANYOTHERKEY was chosen to be greater than
+ UCHAR_MAX. */
+ k = map[ic];
+
+ map[ic].type = ISKMAP;
+ map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
+ }
+ map = FUNCTION_TO_KEYMAP (map, ic);
+ /* The dispatch code will return this function if no matching
+ key sequence is found in the keymap. This (with a little
+ help from the dispatch code in readline.c) allows `a' to be
+ mapped to something, `abc' to be mapped to something else,
+ and the function bound to `a' to be executed when the user
+ types `abx', leaving `bx' in the input queue. */
+ if (k.function /* && k.type == ISFUNC */)
+ {
+ map[ANYOTHERKEY] = k;
+ k.function = 0;
+ }
+ }
+ else
+ {
+ if (map[ic].type == ISMACR)
+ free ((char *)map[ic].function);
+ else if (map[ic].type == ISKMAP)
+ {
+ map = FUNCTION_TO_KEYMAP (map, ic);
+ ic = ANYOTHERKEY;
+ }
+
+ map[ic].function = KEYMAP_TO_FUNCTION (data);
+ map[ic].type = type;
+ }
+
+ rl_binding_keymap = map;
+ }
+ free (keys);
+ return 0;
+}
+
+/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
+ an array of characters. LEN gets the final length of ARRAY. Return
+ non-zero if there was an error parsing SEQ. */
+int
+rl_translate_keyseq (seq, array, len)
+ const char *seq;
+ char *array;
+ int *len;
+{
+ register int i, c, l, temp;
+
+ for (i = l = 0; (c = seq[i]); i++)
+ {
+ if (c == '\\')
+ {
+ c = seq[++i];
+
+ if (c == 0)
+ break;
+
+ /* Handle \C- and \M- prefixes. */
+ if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
+ {
+ /* Handle special case of backwards define. */
+ if (strncmp (&seq[i], "C-\\M-", 5) == 0)
+ {
+ array[l++] = ESC; /* ESC is meta-prefix */
+ i += 5;
+ array[l++] = CTRL (_rl_to_upper (seq[i]));
+ if (seq[i] == '\0')
+ i--;
+ }
+ else if (c == 'M')
+ {
+ i++;
+ array[l++] = ESC; /* ESC is meta-prefix */
+ }
+ else if (c == 'C')
+ {
+ i += 2;
+ /* Special hack for C-?... */
+ array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
+ }
+ continue;
+ }
+
+ /* Translate other backslash-escaped characters. These are the
+ same escape sequences that bash's `echo' and `printf' builtins
+ handle, with the addition of \d -> RUBOUT. A backslash
+ preceding a character that is not special is stripped. */
+ switch (c)
+ {
+ case 'a':
+ array[l++] = '\007';
+ break;
+ case 'b':
+ array[l++] = '\b';
+ break;
+ case 'd':
+ array[l++] = RUBOUT; /* readline-specific */
+ break;
+ case 'e':
+ array[l++] = ESC;
+ break;
+ case 'f':
+ array[l++] = '\f';
+ break;
+ case 'n':
+ array[l++] = NEWLINE;
+ break;
+ case 'r':
+ array[l++] = RETURN;
+ break;
+ case 't':
+ array[l++] = TAB;
+ break;
+ case 'v':
+ array[l++] = 0x0B;
+ break;
+ case '\\':
+ array[l++] = '\\';
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ i++;
+ for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++)
+ c = (c * 8) + OCTVALUE (seq[i]);
+ i--; /* auto-increment in for loop */
+ array[l++] = c & largest_char;
+ break;
+ case 'x':
+ i++;
+ for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++)
+ c = (c * 16) + HEXVALUE (seq[i]);
+ if (temp == 2)
+ c = 'x';
+ i--; /* auto-increment in for loop */
+ array[l++] = c & largest_char;
+ break;
+ default: /* backslashes before non-special chars just add the char */
+ array[l++] = c;
+ break; /* the backslash is stripped */
+ }
+ continue;
+ }
+
+ array[l++] = c;
+ }
+
+ *len = l;
+ array[l] = '\0';
+ return (0);
+}
+
+char *
+rl_untranslate_keyseq (seq)
+ int seq;
+{
+ static char kseq[16];
+ int i, c;
+
+ i = 0;
+ c = seq;
+ if (META_CHAR (c))
+ {
+ kseq[i++] = '\\';
+ kseq[i++] = 'M';
+ kseq[i++] = '-';
+ c = UNMETA (c);
+ }
+ else if (CTRL_CHAR (c))
+ {
+ kseq[i++] = '\\';
+ kseq[i++] = 'C';
+ kseq[i++] = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
+ else if (c == RUBOUT)
+ {
+ kseq[i++] = '\\';
+ kseq[i++] = 'C';
+ kseq[i++] = '-';
+ c = '?';
+ }
+
+ if (c == ESC)
+ {
+ kseq[i++] = '\\';
+ c = 'e';
+ }
+ else if (c == '\\' || c == '"')
+ {
+ kseq[i++] = '\\';
+ }
+
+ kseq[i++] = (unsigned char) c;
+ kseq[i] = '\0';
+ return kseq;
+}
+
+static char *
+_rl_untranslate_macro_value (seq)
+ char *seq;
+{
+ char *ret, *r, *s;
+ int c;
+
+ r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
+ for (s = seq; *s; s++)
+ {
+ c = *s;
+ if (META_CHAR (c))
+ {
+ *r++ = '\\';
+ *r++ = 'M';
+ *r++ = '-';
+ c = UNMETA (c);
+ }
+ else if (CTRL_CHAR (c) && c != ESC)
+ {
+ *r++ = '\\';
+ *r++ = 'C';
+ *r++ = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
+ else if (c == RUBOUT)
+ {
+ *r++ = '\\';
+ *r++ = 'C';
+ *r++ = '-';
+ c = '?';
+ }
+
+ if (c == ESC)
+ {
+ *r++ = '\\';
+ c = 'e';
+ }
+ else if (c == '\\' || c == '"')
+ *r++ = '\\';
+
+ *r++ = (unsigned char)c;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Return a pointer to the function that STRING represents.
+ If STRING doesn't have a matching function, then a NULL pointer
+ is returned. */
+rl_command_func_t *
+rl_named_function (string)
+ const char *string;
+{
+ register int i;
+
+ rl_initialize_funmap ();
+
+ for (i = 0; funmap[i]; i++)
+ if (_rl_stricmp (funmap[i]->name, string) == 0)
+ return (funmap[i]->function);
+ return ((rl_command_func_t *)NULL);
+}
+
+/* Return the function (or macro) definition which would be invoked via
+ KEYSEQ if executed in MAP. If MAP is NULL, then the current keymap is
+ used. TYPE, if non-NULL, is a pointer to an int which will receive the
+ type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap),
+ or ISMACR (macro). */
+rl_command_func_t *
+rl_function_of_keyseq (keyseq, map, type)
+ const char *keyseq;
+ Keymap map;
+ int *type;
+{
+ register int i;
+
+ if (!map)
+ map = _rl_keymap;
+
+ for (i = 0; keyseq && keyseq[i]; i++)
+ {
+ unsigned char ic = keyseq[i];
+
+ if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+ {
+ if (map[ESC].type != ISKMAP)
+ {
+ if (type)
+ *type = map[ESC].type;
+
+ return (map[ESC].function);
+ }
+ else
+ {
+ map = FUNCTION_TO_KEYMAP (map, ESC);
+ ic = UNMETA (ic);
+ }
+ }
+
+ if (map[ic].type == ISKMAP)
+ {
+ /* If this is the last key in the key sequence, return the
+ map. */
+ if (!keyseq[i + 1])
+ {
+ if (type)
+ *type = ISKMAP;
+
+ return (map[ic].function);
+ }
+ else
+ map = FUNCTION_TO_KEYMAP (map, ic);
+ }
+ else
+ {
+ if (type)
+ *type = map[ic].type;
+
+ return (map[ic].function);
+ }
+ }
+ return ((rl_command_func_t *) NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = (char *)NULL;
+
+/* The file we're currently reading key bindings from. */
+static const char *current_readline_init_file;
+static int current_readline_init_include_level;
+static int current_readline_init_lineno;
+
+/* Read FILENAME into a locally-allocated buffer and return the buffer.
+ The size of the buffer is returned in *SIZEP. Returns NULL if any
+ errors were encountered. */
+static char *
+_rl_read_file (filename, sizep)
+ char *filename;
+ size_t *sizep;
+{
+ struct stat finfo;
+ size_t file_size;
+ char *buffer;
+ int i, file;
+
+ if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
+ return ((char *)NULL);
+
+ file_size = (size_t)finfo.st_size;
+
+ /* check for overflow on very large files */
+ if (file_size != finfo.st_size || file_size + 1 < file_size)
+ {
+ if (file >= 0)
+ close (file);
+#if defined (EFBIG)
+ errno = EFBIG;
+#endif
+ return ((char *)NULL);
+ }
+
+ /* Read the file into BUFFER. */
+ buffer = (char *)xmalloc (file_size + 1);
+ i = read (file, buffer, file_size);
+ close (file);
+
+ if (i < 0)
+ {
+ free (buffer);
+ return ((char *)NULL);
+ }
+
+ buffer[i] = '\0';
+ if (sizep)
+ *sizep = i;
+
+ return (buffer);
+}
+
+/* Re-read the current keybindings file. */
+int
+rl_re_read_init_file (count, ignore)
+ int count __attribute__((unused)), ignore __attribute__((unused));
+{
+ int r;
+ r = rl_read_init_file ((const char *)NULL);
+ rl_set_keymap_from_edit_mode ();
+ return r;
+}
+
+/* Do key bindings from a file. If FILENAME is NULL it defaults
+ to the first non-null filename from this list:
+ 1. the filename used for the previous call
+ 2. the value of the shell variable `INPUTRC'
+ 3. ~/.inputrc
+ If the file existed and could be opened and read, 0 is returned,
+ otherwise errno is returned. */
+int
+rl_read_init_file (filename)
+ const char *filename;
+{
+ /* Default the filename. */
+ if (filename == 0)
+ {
+ filename = last_readline_init_file;
+ if (filename == 0)
+ filename = sh_get_env_value ("INPUTRC");
+ if (filename == 0)
+ filename = DEFAULT_INPUTRC;
+ }
+
+ if (*filename == 0)
+ filename = DEFAULT_INPUTRC;
+
+#if defined (__MSDOS__)
+ if (_rl_read_init_file (filename, 0) == 0)
+ return 0;
+ filename = "~/_inputrc";
+#endif
+ return (_rl_read_init_file (filename, 0));
+}
+
+static int
+_rl_read_init_file (filename, include_level)
+ const char *filename;
+ int include_level;
+{
+ register int i;
+ char *buffer, *openname, *line, *end;
+ size_t file_size;
+
+ current_readline_init_file = filename;
+ current_readline_init_include_level = include_level;
+
+ openname = tilde_expand (filename);
+ buffer = _rl_read_file (openname, &file_size);
+ free (openname);
+
+ if (buffer == 0)
+ return (errno);
+
+ if (include_level == 0 && filename != last_readline_init_file)
+ {
+ FREE (last_readline_init_file);
+ last_readline_init_file = savestring (filename);
+ }
+
+ currently_reading_init_file = 1;
+
+ /* Loop over the lines in the file. Lines that start with `#' are
+ comments; all other lines are commands for readline initialization. */
+ current_readline_init_lineno = 1;
+ line = buffer;
+ end = buffer + file_size;
+ while (line < end)
+ {
+ /* Find the end of this line. */
+ for (i = 0; line + i != end && line[i] != '\n'; i++);
+
+#if defined (__CYGWIN__)
+ /* ``Be liberal in what you accept.'' */
+ if (line[i] == '\n' && line[i-1] == '\r')
+ line[i - 1] = '\0';
+#endif
+
+ /* Mark end of line. */
+ line[i] = '\0';
+
+ /* Skip leading whitespace. */
+ while (*line && whitespace (*line))
+ {
+ line++;
+ i--;
+ }
+
+ /* If the line is not a comment, then parse it. */
+ if (*line && *line != '#')
+ rl_parse_and_bind (line);
+
+ /* Move to the next line. */
+ line += i + 1;
+ current_readline_init_lineno++;
+ }
+
+ free (buffer);
+ currently_reading_init_file = 0;
+ return (0);
+}
+
+static void
+_rl_init_file_error (msg)
+ const char *msg;
+{
+ if (currently_reading_init_file)
+ fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
+ current_readline_init_lineno, msg);
+ else
+ fprintf (stderr, "readline: %s\n", msg);
+}
+
+/* **************************************************************** */
+/* */
+/* Parser Directives */
+/* */
+/* **************************************************************** */
+
+typedef int _rl_parser_func_t PARAMS((char *));
+
+/* Things that mean `Control'. */
+const char *_rl_possible_control_prefixes[] = {
+ "Control-", "C-", "CTRL-", (const char *)NULL
+};
+
+const char *_rl_possible_meta_prefixes[] = {
+ "Meta", "M-", (const char *)NULL
+};
+
+/* Conditionals. */
+
+/* Calling programs set this to have their argv[0]. */
+const char *rl_readline_name = "other";
+
+/* Stack of previous values of parsing_conditionalized_out. */
+static unsigned char *if_stack = (unsigned char *)NULL;
+static int if_stack_depth;
+static int if_stack_size;
+
+/* Push _rl_parsing_conditionalized_out, and set parser state based
+ on ARGS. */
+static int
+parser_if (args)
+ char *args;
+{
+ register int i;
+
+ /* Push parser state. */
+ if (if_stack_depth + 1 >= if_stack_size)
+ {
+ if (!if_stack)
+ if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
+ else
+ if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
+ }
+ if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
+
+ /* If parsing is turned off, then nothing can turn it back on except
+ for finding the matching endif. In that case, return right now. */
+ if (_rl_parsing_conditionalized_out)
+ return 0;
+
+ /* Isolate first argument. */
+ for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+ if (args[i])
+ args[i++] = '\0';
+
+ /* Handle "$if term=foo" and "$if mode=emacs" constructs. If this
+ isn't term=foo, or mode=emacs, then check to see if the first
+ word in ARGS is the same as the value stored in rl_readline_name. */
+ if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
+ {
+ char *tem, *tname;
+
+ /* Terminals like "aaa-60" are equivalent to "aaa". */
+ tname = savestring (rl_terminal_name);
+ tem = strchr (tname, '-');
+ if (tem)
+ *tem = '\0';
+
+ /* Test the `long' and `short' forms of the terminal name so that
+ if someone has a `sun-cmd' and does not want to have bindings
+ that will be executed if the terminal is a `sun', they can put
+ `$if term=sun-cmd' into their .inputrc. */
+ _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
+ _rl_stricmp (args + 5, rl_terminal_name);
+ free (tname);
+ }
+#if defined (VI_MODE)
+ else if (_rl_strnicmp (args, "mode=", 5) == 0)
+ {
+ int mode;
+
+ if (_rl_stricmp (args + 5, "emacs") == 0)
+ mode = emacs_mode;
+ else if (_rl_stricmp (args + 5, "vi") == 0)
+ mode = vi_mode;
+ else
+ mode = no_mode;
+
+ _rl_parsing_conditionalized_out = mode != rl_editing_mode;
+ }
+#endif /* VI_MODE */
+ /* Check to see if the first word in ARGS is the same as the
+ value stored in rl_readline_name. */
+ else if (_rl_stricmp (args, rl_readline_name) == 0)
+ _rl_parsing_conditionalized_out = 0;
+ else
+ _rl_parsing_conditionalized_out = 1;
+ return 0;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+static int
+parser_else (args)
+ char *args __attribute__((unused));
+{
+ register int i;
+
+ if (if_stack_depth == 0)
+ {
+ _rl_init_file_error ("$else found without matching $if");
+ return 0;
+ }
+
+ /* Check the previous (n - 1) levels of the stack to make sure that
+ we haven't previously turned off parsing. */
+ for (i = 0; i < if_stack_depth - 1; i++)
+ if (if_stack[i] == 1)
+ return 0;
+
+ /* Invert the state of parsing if at top level. */
+ _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
+ return 0;
+}
+
+/* Terminate a conditional, popping the value of
+ _rl_parsing_conditionalized_out from the stack. */
+static int
+parser_endif (args)
+ char *args __attribute__((unused));
+{
+ if (if_stack_depth)
+ _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
+ else
+ _rl_init_file_error ("$endif without matching $if");
+ return 0;
+}
+
+static int
+parser_include (args)
+ char *args;
+{
+ const char *old_init_file;
+ char *e;
+ int old_line_number, old_include_level, r;
+
+ if (_rl_parsing_conditionalized_out)
+ return (0);
+
+ old_init_file = current_readline_init_file;
+ old_line_number = current_readline_init_lineno;
+ old_include_level = current_readline_init_include_level;
+
+ e = strchr (args, '\n');
+ if (e)
+ *e = '\0';
+ r = _rl_read_init_file ((const char *)args, old_include_level + 1);
+
+ current_readline_init_file = old_init_file;
+ current_readline_init_lineno = old_line_number;
+ current_readline_init_include_level = old_include_level;
+
+ return r;
+}
+
+/* Associate textual names with actual functions. */
+static struct {
+ const char *name;
+ _rl_parser_func_t *function;
+} parser_directives [] = {
+ { "if", parser_if },
+ { "endif", parser_endif },
+ { "else", parser_else },
+ { "include", parser_include },
+ { (char *)0x0, (_rl_parser_func_t *)0x0 }
+};
+
+/* Handle a parser directive. STATEMENT is the line of the directive
+ without any leading `$'. */
+static int
+handle_parser_directive (statement)
+ char *statement;
+{
+ register int i;
+ char *directive, *args;
+
+ /* Isolate the actual directive. */
+
+ /* Skip whitespace. */
+ for (i = 0; whitespace (statement[i]); i++);
+
+ directive = &statement[i];
+
+ for (; statement[i] && !whitespace (statement[i]); i++);
+
+ if (statement[i])
+ statement[i++] = '\0';
+
+ for (; statement[i] && whitespace (statement[i]); i++);
+
+ args = &statement[i];
+
+ /* Lookup the command, and act on it. */
+ for (i = 0; parser_directives[i].name; i++)
+ if (_rl_stricmp (directive, parser_directives[i].name) == 0)
+ {
+ (*parser_directives[i].function) (args);
+ return (0);
+ }
+
+ /* display an error message about the unknown parser directive */
+ _rl_init_file_error ("unknown parser directive");
+ return (1);
+}
+
+/* Read the binding command from STRING and perform it.
+ A key binding command looks like: Keyname: function-name\0,
+ a variable binding command looks like: set variable value.
+ A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+int
+rl_parse_and_bind (string)
+ char *string;
+{
+ char *funname, *kname;
+ register int c, i;
+ int key, equivalency;
+
+ while (string && whitespace (*string))
+ string++;
+
+ if (!string || !*string || *string == '#')
+ return 0;
+
+ /* If this is a parser directive, act on it. */
+ if (*string == '$')
+ {
+ handle_parser_directive (&string[1]);
+ return 0;
+ }
+
+ /* If we aren't supposed to be parsing right now, then we're done. */
+ if (_rl_parsing_conditionalized_out)
+ return 0;
+
+ i = 0;
+ /* If this keyname is a complex key expression surrounded by quotes,
+ advance to after the matching close quote. This code allows the
+ backslash to quote characters in the key expression. */
+ if (*string == '"')
+ {
+ int passc = 0;
+
+ for (i = 1; (c = string[i]); i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ continue;
+ }
+
+ if (c == '\\')
+ {
+ passc++;
+ continue;
+ }
+
+ if (c == '"')
+ break;
+ }
+ /* If we didn't find a closing quote, abort the line. */
+ if (string[i] == '\0')
+ {
+ _rl_init_file_error ("no closing `\"' in key binding");
+ return 1;
+ }
+ }
+
+ /* Advance to the colon (:) or whitespace which separates the two objects. */
+ for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+ equivalency = (c == ':' && string[i + 1] == '=');
+
+ /* Mark the end of the command (or keyname). */
+ if (string[i])
+ string[i++] = '\0';
+
+ /* If doing assignment, skip the '=' sign as well. */
+ if (equivalency)
+ string[i++] = '\0';
+
+ /* If this is a command to set a variable, then do that. */
+ if (_rl_stricmp (string, "set") == 0)
+ {
+ char *var = string + i;
+ char *value;
+
+ /* Make VAR point to start of variable name. */
+ while (*var && whitespace (*var)) var++;
+
+ /* Make VALUE point to start of value string. */
+ value = var;
+ while (*value && !whitespace (*value)) value++;
+ if (*value)
+ *value++ = '\0';
+ while (*value && whitespace (*value)) value++;
+
+ rl_variable_bind (var, value);
+ return 0;
+ }
+
+ /* Skip any whitespace between keyname and funname. */
+ for (; string[i] && whitespace (string[i]); i++);
+ funname = &string[i];
+
+ /* Now isolate funname.
+ For straight function names just look for whitespace, since
+ that will signify the end of the string. But this could be a
+ macro definition. In that case, the string is quoted, so skip
+ to the matching delimiter. We allow the backslash to quote the
+ delimiter characters in the macro body. */
+ /* This code exists to allow whitespace in macro expansions, which
+ would otherwise be gobbled up by the next `for' loop.*/
+ /* XXX - it may be desirable to allow backslash quoting only if " is
+ the quoted string delimiter, like the shell. */
+ if (*funname == '\'' || *funname == '"')
+ {
+ int delimiter = string[i++], passc;
+
+ for (passc = 0; (c = string[i]); i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ continue;
+ }
+
+ if (c == '\\')
+ {
+ passc = 1;
+ continue;
+ }
+
+ if (c == delimiter)
+ break;
+ }
+ if (c)
+ i++;
+ }
+
+ /* Advance to the end of the string. */
+ for (; string[i] && !whitespace (string[i]); i++);
+
+ /* No extra whitespace at the end of the string. */
+ string[i] = '\0';
+
+ /* Handle equivalency bindings here. Make the left-hand side be exactly
+ whatever the right-hand evaluates to, including keymaps. */
+ if (equivalency)
+ {
+ return 0;
+ }
+
+ /* If this is a new-style key-binding, then do the binding with
+ rl_set_key (). Otherwise, let the older code deal with it. */
+ if (*string == '"')
+ {
+ char *seq;
+ register int j, k, passc;
+
+ seq = (char *)xmalloc (1 + strlen (string));
+ for (j = 1, k = passc = 0; string[j]; j++)
+ {
+ /* Allow backslash to quote characters, but leave them in place.
+ This allows a string to end with a backslash quoting another
+ backslash, or with a backslash quoting a double quote. The
+ backslashes are left in place for rl_translate_keyseq (). */
+ if (passc || (string[j] == '\\'))
+ {
+ seq[k++] = string[j];
+ passc = !passc;
+ continue;
+ }
+
+ if (string[j] == '"')
+ break;
+
+ seq[k++] = string[j];
+ }
+ seq[k] = '\0';
+
+ /* Binding macro? */
+ if (*funname == '\'' || *funname == '"')
+ {
+ j = strlen (funname);
+
+ /* Remove the delimiting quotes from each end of FUNNAME. */
+ if (j && funname[j - 1] == *funname)
+ funname[j - 1] = '\0';
+
+ rl_macro_bind (seq, &funname[1], _rl_keymap);
+ }
+ else
+ rl_set_key (seq, rl_named_function (funname), _rl_keymap);
+
+ free (seq);
+ return 0;
+ }
+
+ /* Get the actual character we want to deal with. */
+ kname = strrchr (string, '-');
+ if (!kname)
+ kname = string;
+ else
+ kname++;
+
+ key = glean_key_from_name (kname);
+
+ /* Add in control and meta bits. */
+ if (substring_member_of_array (string, _rl_possible_control_prefixes))
+ key = CTRL (_rl_to_upper (key));
+
+ if (substring_member_of_array (string, _rl_possible_meta_prefixes))
+ key = META (key);
+
+ /* Temporary. Handle old-style keyname with macro-binding. */
+ if (*funname == '\'' || *funname == '"')
+ {
+ char useq[2];
+ int fl = strlen (funname);
+
+ useq[0] = key; useq[1] = '\0';
+ if (fl && funname[fl - 1] == *funname)
+ funname[fl - 1] = '\0';
+
+ rl_macro_bind (useq, &funname[1], _rl_keymap);
+ }
+#if defined (PREFIX_META_HACK)
+ /* Ugly, but working hack to keep prefix-meta around. */
+ else if (_rl_stricmp (funname, "prefix-meta") == 0)
+ {
+ char seq[2];
+
+ seq[0] = key;
+ seq[1] = '\0';
+ rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
+ }
+#endif /* PREFIX_META_HACK */
+ else
+ rl_bind_key (key, rl_named_function (funname));
+ return 0;
+}
+
+/* Simple structure for boolean readline variables (i.e., those that can
+ have one of two values; either "On" or 1 for truth, or "Off" or 0 for
+ false. */
+
+#define V_SPECIAL 0x1
+
+static struct {
+ const char *name;
+ int *value;
+ int flags;
+} boolean_varlist [] = {
+ { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
+ { "byte-oriented", &rl_byte_oriented, 0 },
+ { "completion-ignore-case", &_rl_completion_case_fold, 0 },
+ { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
+ { "disable-completion", &rl_inhibit_completion, 0 },
+ { "enable-keypad", &_rl_enable_keypad, 0 },
+ { "expand-tilde", &rl_complete_with_tilde_expansion, 0 },
+ { "history-preserve-point", &_rl_history_preserve_point, 0 },
+ { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode, 0 },
+ { "input-meta", &_rl_meta_flag, 0 },
+ { "mark-directories", &_rl_complete_mark_directories, 0 },
+ { "mark-modified-lines", &_rl_mark_modified_lines, 0 },
+ { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
+ { "match-hidden-files", &_rl_match_hidden_files, 0 },
+ { "meta-flag", &_rl_meta_flag, 0 },
+ { "output-meta", &_rl_output_meta_chars, 0 },
+ { "page-completions", &_rl_page_completions, 0 },
+ { "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL },
+ { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
+ { "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
+#if defined (VISIBLE_STATS)
+ { "visible-stats", &rl_visible_stats, 0 },
+#endif /* VISIBLE_STATS */
+ { (char *)NULL, (int *)NULL, 0 }
+};
+
+static int
+find_boolean_var (name)
+ const char *name;
+{
+ register int i;
+
+ for (i = 0; boolean_varlist[i].name; i++)
+ if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
+ return i;
+ return -1;
+}
+
+/* Hooks for handling special boolean variables, where a
+ function needs to be called or another variable needs
+ to be changed when they're changed. */
+static void
+hack_special_boolean_var (i)
+ int i;
+{
+ const char *name;
+
+ name = boolean_varlist[i].name;
+
+ if (_rl_stricmp (name, "blink-matching-paren") == 0)
+ _rl_enable_paren_matching (rl_blink_matching_paren);
+ else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
+ {
+ if (_rl_prefer_visible_bell)
+ _rl_bell_preference = VISIBLE_BELL;
+ else
+ _rl_bell_preference = AUDIBLE_BELL;
+ }
+}
+
+typedef int _rl_sv_func_t PARAMS((const char *));
+
+/* These *must* correspond to the array indices for the appropriate
+ string variable. (Though they're not used right now.) */
+#define V_BELLSTYLE 0
+#define V_COMBEGIN 1
+#define V_EDITMODE 2
+#define V_ISRCHTERM 3
+#define V_KEYMAP 4
+
+#define V_STRING 1
+#define V_INT 2
+
+/* Forward declarations */
+static int sv_bell_style PARAMS((const char *));
+static int sv_combegin PARAMS((const char *));
+static int sv_compquery PARAMS((const char *));
+static int sv_editmode PARAMS((const char *));
+static int sv_isrchterm PARAMS((const char *));
+static int sv_keymap PARAMS((const char *));
+
+static struct {
+ const char *name;
+ int flags;
+ _rl_sv_func_t *set_func;
+} string_varlist[] = {
+ { "bell-style", V_STRING, sv_bell_style },
+ { "comment-begin", V_STRING, sv_combegin },
+ { "completion-query-items", V_INT, sv_compquery },
+ { "editing-mode", V_STRING, sv_editmode },
+ { "isearch-terminators", V_STRING, sv_isrchterm },
+ { "keymap", V_STRING, sv_keymap },
+ { (char *)NULL, 0, 0 }
+};
+
+static int
+find_string_var (name)
+ const char *name;
+{
+ register int i;
+
+ for (i = 0; string_varlist[i].name; i++)
+ if (_rl_stricmp (name, string_varlist[i].name) == 0)
+ return i;
+ return -1;
+}
+
+/* A boolean value that can appear in a `set variable' command is true if
+ the value is null or empty, `on' (case-insenstive), or "1". Any other
+ values result in 0 (false). */
+static int
+bool_to_int (value)
+ char *value;
+{
+ return (value == 0 || *value == '\0' ||
+ (_rl_stricmp (value, "on") == 0) ||
+ (value[0] == '1' && value[1] == '\0'));
+}
+
+int
+rl_variable_bind (name, value)
+ const char *name, *value;
+{
+ register int i;
+ int v;
+
+ /* Check for simple variables first. */
+ i = find_boolean_var (name);
+ if (i >= 0)
+ {
+ *boolean_varlist[i].value = bool_to_int (value);
+ if (boolean_varlist[i].flags & V_SPECIAL)
+ hack_special_boolean_var (i);
+ return 0;
+ }
+
+ i = find_string_var (name);
+
+ /* For the time being, unknown variable names or string names without a
+ handler function are simply ignored. */
+ if (i < 0 || string_varlist[i].set_func == 0)
+ return 0;
+
+ v = (*string_varlist[i].set_func) (value);
+ return v;
+}
+
+static int
+sv_editmode (value)
+ const char *value;
+{
+ if (_rl_strnicmp (value, "vi", 2) == 0)
+ {
+#if defined (VI_MODE)
+ _rl_keymap = vi_insertion_keymap;
+ rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+ return 0;
+ }
+ else if (_rl_strnicmp (value, "emacs", 5) == 0)
+ {
+ _rl_keymap = emacs_standard_keymap;
+ rl_editing_mode = emacs_mode;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sv_combegin (value)
+ const char *value;
+{
+ if (value && *value)
+ {
+ FREE (_rl_comment_begin);
+ _rl_comment_begin = savestring (value);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sv_compquery (value)
+ const char *value;
+{
+ int nval = 100;
+
+ if (value && *value)
+ {
+ nval = atoi (value);
+ if (nval < 0)
+ nval = 0;
+ }
+ rl_completion_query_items = nval;
+ return 0;
+}
+
+static int
+sv_keymap (value)
+ const char *value;
+{
+ Keymap kmap;
+
+ kmap = rl_get_keymap_by_name (value);
+ if (kmap)
+ {
+ rl_set_keymap (kmap);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sv_bell_style (value)
+ const char *value;
+{
+ if (value == 0 || *value == '\0')
+ _rl_bell_preference = AUDIBLE_BELL;
+ else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
+ _rl_bell_preference = NO_BELL;
+ else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
+ _rl_bell_preference = AUDIBLE_BELL;
+ else if (_rl_stricmp (value, "visible") == 0)
+ _rl_bell_preference = VISIBLE_BELL;
+ else
+ return 1;
+ return 0;
+}
+
+static int
+sv_isrchterm (value)
+ const char *value;
+{
+ int beg, end, delim;
+ char *v;
+
+ if (value == 0)
+ return 1;
+
+ /* Isolate the value and translate it into a character string. */
+ v = savestring (value);
+ FREE (_rl_isearch_terminators);
+ if (v[0] == '"' || v[0] == '\'')
+ {
+ delim = v[0];
+ for (beg = end = 1; v[end] && v[end] != delim; end++)
+ ;
+ }
+ else
+ {
+ for (beg = end = 0; whitespace (v[end]) == 0; end++)
+ ;
+ }
+
+ v[end] = '\0';
+
+ /* The value starts at v + beg. Translate it into a character string. */
+ _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1);
+ rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
+ _rl_isearch_terminators[end] = '\0';
+
+ free (v);
+ return 0;
+}
+
+/* Return the character which matches NAME.
+ For example, `Space' returns ' '. */
+
+typedef struct {
+ const char *name;
+ int value;
+} assoc_list;
+
+static assoc_list name_key_alist[] = {
+ { "DEL", 0x7f },
+ { "ESC", '\033' },
+ { "Escape", '\033' },
+ { "LFD", '\n' },
+ { "Newline", '\n' },
+ { "RET", '\r' },
+ { "Return", '\r' },
+ { "Rubout", 0x7f },
+ { "SPC", ' ' },
+ { "Space", ' ' },
+ { "Tab", 0x09 },
+ { (char *)0x0, 0 }
+};
+
+static int
+glean_key_from_name (name)
+ char *name;
+{
+ register int i;
+
+ for (i = 0; name_key_alist[i].name; i++)
+ if (_rl_stricmp (name, name_key_alist[i].name) == 0)
+ return (name_key_alist[i].value);
+
+ return (*(unsigned char *)name); /* XXX was return (*name) */
+}
+
+/* Auxiliary functions to manage keymaps. */
+static struct {
+ const char *name;
+ Keymap map;
+} keymap_names[] = {
+ { "emacs", emacs_standard_keymap },
+ { "emacs-standard", emacs_standard_keymap },
+ { "emacs-meta", emacs_meta_keymap },
+ { "emacs-ctlx", emacs_ctlx_keymap },
+#if defined (VI_MODE)
+ { "vi", vi_movement_keymap },
+ { "vi-move", vi_movement_keymap },
+ { "vi-command", vi_movement_keymap },
+ { "vi-insert", vi_insertion_keymap },
+#endif /* VI_MODE */
+ { (char *)0x0, (Keymap)0x0 }
+};
+
+Keymap
+rl_get_keymap_by_name (name)
+ const char *name;
+{
+ register int i;
+
+ for (i = 0; keymap_names[i].name; i++)
+ if (_rl_stricmp (name, keymap_names[i].name) == 0)
+ return (keymap_names[i].map);
+ return ((Keymap) NULL);
+}
+
+char *
+rl_get_keymap_name (map)
+ Keymap map;
+{
+ register int i;
+ for (i = 0; keymap_names[i].name; i++)
+ if (map == keymap_names[i].map)
+ return ((char *)keymap_names[i].name);
+ return ((char *)NULL);
+}
+
+void
+rl_set_keymap (map)
+ Keymap map;
+{
+ if (map)
+ _rl_keymap = map;
+}
+
+Keymap
+rl_get_keymap ()
+{
+ return (_rl_keymap);
+}
+
+void
+rl_set_keymap_from_edit_mode ()
+{
+ if (rl_editing_mode == emacs_mode)
+ _rl_keymap = emacs_standard_keymap;
+#if defined (VI_MODE)
+ else if (rl_editing_mode == vi_mode)
+ _rl_keymap = vi_insertion_keymap;
+#endif /* VI_MODE */
+}
+
+
+const char *
+rl_get_keymap_name_from_edit_mode ()
+{
+ if (rl_editing_mode == emacs_mode)
+ return "emacs";
+#if defined (VI_MODE)
+ else if (rl_editing_mode == vi_mode)
+ return "vi";
+#endif /* VI_MODE */
+ else
+ return "nope";
+}
+
+/* **************************************************************** */
+/* */
+/* Key Binding and Function Information */
+/* */
+/* **************************************************************** */
+
+/* Each of the following functions produces information about the
+ state of keybindings and functions known to Readline. The info
+ is always printed to rl_outstream, and in such a way that it can
+ be read back in (i.e., passed to rl_parse_and_bind (). */
+
+/* Print the names of functions known to Readline. */
+void
+rl_list_funmap_names ()
+{
+ register int i;
+ const char **funmap_names;
+
+ funmap_names = rl_funmap_names ();
+
+ if (!funmap_names)
+ return;
+
+ for (i = 0; funmap_names[i]; i++)
+ fprintf (rl_outstream, "%s\n", funmap_names[i]);
+
+ free (funmap_names);
+}
+
+static char *
+_rl_get_keyname (key)
+ int key;
+{
+ char *keyname;
+ int i, c;
+
+ keyname = (char *)xmalloc (8);
+
+ c = key;
+ /* Since this is going to be used to write out keysequence-function
+ pairs for possible inclusion in an inputrc file, we don't want to
+ do any special meta processing on KEY. */
+
+#if 1
+ /* XXX - Experimental */
+ /* We might want to do this, but the old version of the code did not. */
+
+ /* If this is an escape character, we don't want to do any more processing.
+ Just add the special ESC key sequence and return. */
+ if (c == ESC)
+ {
+ keyname[0] = '\\';
+ keyname[1] = 'e';
+ keyname[2] = '\0';
+ return keyname;
+ }
+#endif
+
+ /* RUBOUT is translated directly into \C-? */
+ if (key == RUBOUT)
+ {
+ keyname[0] = '\\';
+ keyname[1] = 'C';
+ keyname[2] = '-';
+ keyname[3] = '?';
+ keyname[4] = '\0';
+ return keyname;
+ }
+
+ i = 0;
+ /* Now add special prefixes needed for control characters. This can
+ potentially change C. */
+ if (CTRL_CHAR (c))
+ {
+ keyname[i++] = '\\';
+ keyname[i++] = 'C';
+ keyname[i++] = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
+
+ /* XXX experimental code. Turn the characters that are not ASCII or
+ ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
+ This changes C. */
+ if (c >= 128 && c <= 159)
+ {
+ keyname[i++] = '\\';
+ keyname[i++] = '2';
+ c -= 128;
+ keyname[i++] = (c / 8) + '0';
+ c = (c % 8) + '0';
+ }
+
+ /* Now, if the character needs to be quoted with a backslash, do that. */
+ if (c == '\\' || c == '"')
+ keyname[i++] = '\\';
+
+ /* Now add the key, terminate the string, and return it. */
+ keyname[i++] = (char) c;
+ keyname[i] = '\0';
+
+ return keyname;
+}
+
+/* Return a NULL terminated array of strings which represent the key
+ sequences that are used to invoke FUNCTION in MAP. */
+char **
+rl_invoking_keyseqs_in_map (function, map)
+ rl_command_func_t *function;
+ Keymap map;
+{
+ register int key;
+ char **result;
+ int result_index, result_size;
+
+ result = (char **)NULL;
+ result_index = result_size = 0;
+
+ for (key = 0; key < KEYMAP_SIZE; key++)
+ {
+ switch (map[key].type)
+ {
+ case ISMACR:
+ /* Macros match, if, and only if, the pointers are identical.
+ Thus, they are treated exactly like functions in here. */
+ case ISFUNC:
+ /* If the function in the keymap is the one we are looking for,
+ then add the current KEY to the list of invoking keys. */
+ if (map[key].function == function)
+ {
+ char *keyname;
+
+ keyname = _rl_get_keyname (key);
+
+ if (result_index + 2 > result_size)
+ {
+ result_size += 10;
+ result = (char **)xrealloc (result, result_size * sizeof (char *));
+ }
+
+ result[result_index++] = keyname;
+ result[result_index] = (char *)NULL;
+ }
+ break;
+
+ case ISKMAP:
+ {
+ char **seqs;
+ register int i;
+
+ /* Find the list of keyseqs in this map which have FUNCTION as
+ their target. Add the key sequences found to RESULT. */
+ if (map[key].function)
+ seqs =
+ rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
+ else
+ break;
+
+ if (seqs == 0)
+ break;
+
+ for (i = 0; seqs[i]; i++)
+ {
+ char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
+
+ if (key == ESC)
+#if 0
+ sprintf (keyname, "\\e");
+#else
+ /* XXX - experimental */
+ sprintf (keyname, "\\M-");
+#endif
+ else if (CTRL_CHAR (key))
+ sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
+ else if (key == RUBOUT)
+ sprintf (keyname, "\\C-?");
+ else if (key == '\\' || key == '"')
+ {
+ keyname[0] = '\\';
+ keyname[1] = (char) key;
+ keyname[2] = '\0';
+ }
+ else
+ {
+ keyname[0] = (char) key;
+ keyname[1] = '\0';
+ }
+
+ strcat (keyname, seqs[i]);
+ free (seqs[i]);
+
+ if (result_index + 2 > result_size)
+ {
+ result_size += 10;
+ result = (char **)xrealloc (result, result_size * sizeof (char *));
+ }
+
+ result[result_index++] = keyname;
+ result[result_index] = (char *)NULL;
+ }
+
+ free (seqs);
+ }
+ break;
+ }
+ }
+ return (result);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+ sequences that can be used to invoke FUNCTION using the current keymap. */
+char **
+rl_invoking_keyseqs (function)
+ rl_command_func_t *function;
+{
+ return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
+}
+
+/* Print all of the functions and their bindings to rl_outstream. If
+ PRINT_READABLY is non-zero, then print the output in such a way
+ that it can be read back in. */
+void
+rl_function_dumper (print_readably)
+ int print_readably;
+{
+ register int i;
+ const char **names;
+ const char *name;
+
+ names = rl_funmap_names ();
+
+ fprintf (rl_outstream, "\n");
+
+ for (i = 0; (name = names[i]); i++)
+ {
+ rl_command_func_t *function;
+ char **invokers;
+
+ function = rl_named_function (name);
+ invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
+
+ if (print_readably)
+ {
+ if (!invokers)
+ fprintf (rl_outstream, "# %s (not bound)\n", name);
+ else
+ {
+ register int j;
+
+ for (j = 0; invokers[j]; j++)
+ {
+ fprintf (rl_outstream, "\"%s\": %s\n",
+ invokers[j], name);
+ free (invokers[j]);
+ }
+
+ free (invokers);
+ }
+ }
+ else
+ {
+ if (!invokers)
+ fprintf (rl_outstream, "%s is not bound to any keys\n",
+ name);
+ else
+ {
+ register int j;
+
+ fprintf (rl_outstream, "%s can be found on ", name);
+
+ for (j = 0; invokers[j] && j < 5; j++)
+ {
+ fprintf (rl_outstream, "\"%s\"%s", invokers[j],
+ invokers[j + 1] ? ", " : ".\n");
+ }
+
+ if (j == 5 && invokers[j])
+ fprintf (rl_outstream, "...\n");
+
+ for (j = 0; invokers[j]; j++)
+ free (invokers[j]);
+
+ free (invokers);
+ }
+ }
+ }
+}
+
+/* Print all of the current functions and their bindings to
+ rl_outstream. If an explicit argument is given, then print
+ the output in such a way that it can be read back in. */
+int
+rl_dump_functions (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (rl_dispatching)
+ fprintf (rl_outstream, "\r\n");
+ rl_function_dumper (rl_explicit_arg);
+ rl_on_new_line ();
+ return (0);
+}
+
+static void
+_rl_macro_dumper_internal (print_readably, map, prefix)
+ int print_readably;
+ Keymap map;
+ char *prefix;
+{
+ register int key;
+ char *keyname, *out;
+ int prefix_len;
+
+ for (key = 0; key < KEYMAP_SIZE; key++)
+ {
+ switch (map[key].type)
+ {
+ case ISMACR:
+ keyname = _rl_get_keyname (key);
+ out = _rl_untranslate_macro_value ((char *)map[key].function);
+
+ if (print_readably)
+ fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
+ keyname,
+ out ? out : "");
+ else
+ fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
+ keyname,
+ out ? out : "");
+ free (keyname);
+ free (out);
+ break;
+ case ISFUNC:
+ break;
+ case ISKMAP:
+ prefix_len = prefix ? strlen (prefix) : 0;
+ if (key == ESC)
+ {
+ keyname = (char *)xmalloc (3 + prefix_len);
+ if (prefix)
+ strcpy (keyname, prefix);
+ keyname[prefix_len] = '\\';
+ keyname[prefix_len + 1] = 'e';
+ keyname[prefix_len + 2] = '\0';
+ }
+ else
+ {
+ keyname = _rl_get_keyname (key);
+ if (prefix)
+ {
+ out = (char *)xmalloc (strlen (keyname) + prefix_len + 1);
+ strcpy (out, prefix);
+ strcpy (out + prefix_len, keyname);
+ free (keyname);
+ keyname = out;
+ }
+ }
+
+ _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
+ free (keyname);
+ break;
+ }
+ }
+}
+
+void
+rl_macro_dumper (print_readably)
+ int print_readably;
+{
+ _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
+}
+
+int
+rl_dump_macros (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (rl_dispatching)
+ fprintf (rl_outstream, "\r\n");
+ rl_macro_dumper (rl_explicit_arg);
+ rl_on_new_line ();
+ return (0);
+}
+
+void
+rl_variable_dumper (print_readably)
+ int print_readably;
+{
+ int i;
+ const char *kname;
+
+ for (i = 0; boolean_varlist[i].name; i++)
+ {
+ if (print_readably)
+ fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
+ *boolean_varlist[i].value ? "on" : "off");
+ else
+ fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
+ *boolean_varlist[i].value ? "on" : "off");
+ }
+
+ /* bell-style */
+ switch (_rl_bell_preference)
+ {
+ case NO_BELL:
+ kname = "none"; break;
+ case VISIBLE_BELL:
+ kname = "visible"; break;
+ case AUDIBLE_BELL:
+ default:
+ kname = "audible"; break;
+ }
+ if (print_readably)
+ fprintf (rl_outstream, "set bell-style %s\n", kname);
+ else
+ fprintf (rl_outstream, "bell-style is set to `%s'\n", kname);
+
+ /* comment-begin */
+ if (print_readably)
+ fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
+ else
+ fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
+
+ /* completion-query-items */
+ if (print_readably)
+ fprintf (rl_outstream, "set completion-query-items %d\n", rl_completion_query_items);
+ else
+ fprintf (rl_outstream, "completion-query-items is set to `%d'\n", rl_completion_query_items);
+
+ /* editing-mode */
+ if (print_readably)
+ fprintf (rl_outstream, "set editing-mode %s\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
+ else
+ fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
+
+ /* isearch-terminators */
+ if (_rl_isearch_terminators)
+ {
+ char *disp;
+
+ disp = _rl_untranslate_macro_value (_rl_isearch_terminators);
+
+ if (print_readably)
+ fprintf (rl_outstream, "set isearch-terminators \"%s\"\n", disp);
+ else
+ fprintf (rl_outstream, "isearch-terminators is set to \"%s\"\n", disp);
+
+ free (disp);
+ }
+
+ /* keymap */
+ kname = rl_get_keymap_name (_rl_keymap);
+ if (kname == 0)
+ kname = rl_get_keymap_name_from_edit_mode ();
+ if (print_readably)
+ fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none");
+ else
+ fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none");
+}
+
+/* Print all of the current variables and their values to
+ rl_outstream. If an explicit argument is given, then print
+ the output in such a way that it can be read back in. */
+int
+rl_dump_variables (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (rl_dispatching)
+ fprintf (rl_outstream, "\r\n");
+ rl_variable_dumper (rl_explicit_arg);
+ rl_on_new_line ();
+ return (0);
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
+ now, this is always used to attempt to bind the arrow keys, hence the
+ check for rl_vi_movement_mode. */
+void
+_rl_bind_if_unbound (keyseq, default_func)
+ const char *keyseq;
+ rl_command_func_t *default_func;
+{
+ rl_command_func_t *func;
+
+ if (keyseq)
+ {
+ func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
+#if defined (VI_MODE)
+ if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
+#else
+ if (!func || func == rl_do_lowercase_version)
+#endif
+ rl_set_key (keyseq, default_func, _rl_keymap);
+ }
+}
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+ char *string;
+ const char **array;
+{
+ while (*array)
+ {
+ if (_rl_strindex (string, *array))
+ return (1);
+ array++;
+ }
+ return (0);
+}
diff --git a/cmd-line-utils/readline/callback.c b/cmd-line-utils/readline/callback.c
new file mode 100644
index 00000000000..a8f4323c929
--- /dev/null
+++ b/cmd-line-utils/readline/callback.c
@@ -0,0 +1,156 @@
+/* callback.c -- functions to use readline as an X `callback' mechanism. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include "rlconf.h"
+
+#if defined (READLINE_CALLBACKS)
+
+#include <sys/types.h>
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "readline.h"
+#include "rlprivate.h"
+
+/* **************************************************************** */
+/* */
+/* Callback Readline Functions */
+/* */
+/* **************************************************************** */
+
+/* Allow using readline in situations where a program may have multiple
+ things to handle at once, and dispatches them via select(). Call
+ rl_callback_handler_install() with the prompt and a function to call
+ whenever a complete line of input is ready. The user must then
+ call rl_callback_read_char() every time some input is available, and
+ rl_callback_read_char() will call the user's function with the complete
+ text read in at each end of line. The terminal is kept prepped and
+ signals handled all the time, except during calls to the user's function. */
+
+rl_vcpfunc_t *rl_linefunc; /* user callback function */
+static int in_handler; /* terminal_prepped and signals set? */
+
+/* Make sure the terminal is set up, initialize readline, and prompt. */
+static void
+_rl_callback_newline ()
+{
+ rl_initialize ();
+
+ if (in_handler == 0)
+ {
+ in_handler = 1;
+
+ (*rl_prep_term_function) (_rl_meta_flag);
+
+#if defined (HANDLE_SIGNALS)
+ rl_set_signals ();
+#endif
+ }
+
+ readline_internal_setup ();
+}
+
+/* Install a readline handler, set up the terminal, and issue the prompt. */
+void
+rl_callback_handler_install (prompt, linefunc)
+ const char *prompt;
+ rl_vcpfunc_t *linefunc;
+{
+ rl_set_prompt (prompt);
+ rl_linefunc = linefunc;
+ _rl_callback_newline ();
+}
+
+/* Read one character, and dispatch to the handler if it ends the line. */
+void
+rl_callback_read_char ()
+{
+ char *line;
+ int eof;
+
+ if (rl_linefunc == NULL)
+ {
+ fprintf (stderr, "readline: readline_callback_read_char() called with no handler!\r\n");
+ abort ();
+ }
+
+ eof = readline_internal_char ();
+
+ /* We loop in case some function has pushed input back with rl_execute_next. */
+ for (;;)
+ {
+ if (rl_done)
+ {
+ line = readline_internal_teardown (eof);
+
+ (*rl_deprep_term_function) ();
+#if defined (HANDLE_SIGNALS)
+ rl_clear_signals ();
+#endif
+ in_handler = 0;
+ (*rl_linefunc) (line);
+
+ /* If the user did not clear out the line, do it for him. */
+ if (rl_line_buffer[0])
+ _rl_init_line_state ();
+
+ /* Redisplay the prompt if readline_handler_{install,remove}
+ not called. */
+ if (in_handler == 0 && rl_linefunc)
+ _rl_callback_newline ();
+ }
+ if (rl_pending_input)
+ eof = readline_internal_char ();
+ else
+ break;
+ }
+}
+
+/* Remove the handler, and make sure the terminal is in its normal state. */
+void
+rl_callback_handler_remove ()
+{
+ rl_linefunc = NULL;
+ if (in_handler)
+ {
+ in_handler = 0;
+ (*rl_deprep_term_function) ();
+#if defined (HANDLE_SIGNALS)
+ rl_clear_signals ();
+#endif
+ }
+}
+
+#endif
diff --git a/cmd-line-utils/readline/chardefs.h b/cmd-line-utils/readline/chardefs.h
new file mode 100644
index 00000000000..a537be220b0
--- /dev/null
+++ b/cmd-line-utils/readline/chardefs.h
@@ -0,0 +1,159 @@
+/* chardefs.h -- Character definitions for readline. */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#ifndef _CHARDEFS_H_
+#define _CHARDEFS_H_
+
+#include <ctype.h>
+
+#if defined (HAVE_CONFIG_H)
+# if defined (HAVE_STRING_H)
+# if ! defined (STDC_HEADERS) && defined (HAVE_MEMORY_H)
+# include <memory.h>
+# endif
+# include <string.h>
+# endif /* HAVE_STRING_H */
+# if defined (HAVE_STRINGS_H)
+# include <strings.h>
+# endif /* HAVE_STRINGS_H */
+#else
+# include <string.h>
+#endif /* !HAVE_CONFIG_H */
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifdef CTRL
+# undef CTRL
+#endif
+#ifdef UNCTRL
+# undef UNCTRL
+#endif
+
+/* Some character stuff. */
+#define control_character_threshold 0x020 /* Smaller than this is control. */
+#define control_character_mask 0x1f /* 0x20 - 1 */
+#define meta_character_threshold 0x07f /* Larger than this is Meta. */
+#define control_character_bit 0x40 /* 0x000000, must be off. */
+#define meta_character_bit 0x080 /* x0000000, must be on. */
+#define largest_char 255 /* Largest character value. */
+
+#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
+#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
+
+#define CTRL(c) ((c) & control_character_mask)
+#define META(c) ((c) | meta_character_bit)
+
+#define UNMETA(c) ((c) & (~meta_character_bit))
+#define UNCTRL(c) _rl_to_upper(((c)|control_character_bit))
+
+#if defined STDC_HEADERS || (!defined (isascii) && !defined (HAVE_ISASCII))
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+#endif
+
+#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT)
+# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
+#endif
+
+#define NON_NEGATIVE(c) ((unsigned char)(c) == (c))
+
+/* Some systems define these; we want our definitions. */
+#undef ISPRINT
+
+#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c))
+#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
+#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
+#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
+#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
+#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
+
+#define _rl_lowercase_p(c) (NON_NEGATIVE(c) && ISLOWER(c))
+#define _rl_uppercase_p(c) (NON_NEGATIVE(c) && ISUPPER(c))
+#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9')
+
+#define _rl_pure_alphabetic(c) (NON_NEGATIVE(c) && ISALPHA(c))
+#define ALPHABETIC(c) (NON_NEGATIVE(c) && ISALNUM(c))
+
+#ifndef _rl_to_upper
+# define _rl_to_upper(c) (_rl_lowercase_p(c) ? toupper((unsigned char)c) : (c))
+# define _rl_to_lower(c) (_rl_uppercase_p(c) ? tolower((unsigned char)c) : (c))
+#endif
+
+#ifndef _rl_digit_value
+# define _rl_digit_value(x) ((x) - '0')
+#endif
+
+#ifndef _rl_isident
+# define _rl_isident(c) (ISALNUM(c) || (c) == '_')
+#endif
+
+#ifndef ISOCTAL
+# define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
+#endif
+#define OCTVALUE(c) ((c) - '0')
+
+#define HEXVALUE(c) \
+ (((c) >= 'a' && (c) <= 'f') \
+ ? (c)-'a'+10 \
+ : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
+
+#ifndef NEWLINE
+#define NEWLINE '\n'
+#endif
+
+#ifndef RETURN
+#define RETURN CTRL('M')
+#endif
+
+#ifndef RUBOUT
+#define RUBOUT 0x7f
+#endif
+
+#ifndef TAB
+#define TAB '\t'
+#endif
+
+#ifdef ABORT_CHAR
+#undef ABORT_CHAR
+#endif
+#define ABORT_CHAR CTRL('G')
+
+#ifdef PAGE
+#undef PAGE
+#endif
+#define PAGE CTRL('L')
+
+#ifdef SPACE
+#undef SPACE
+#endif
+#define SPACE ' ' /* XXX - was 0x20 */
+
+#ifdef ESC
+#undef ESC
+#endif
+#define ESC CTRL('[')
+
+#endif /* _CHARDEFS_H_ */
diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c
new file mode 100644
index 00000000000..693550c9945
--- /dev/null
+++ b/cmd-line-utils/readline/complete.c
@@ -0,0 +1,2004 @@
+/* complete.c -- filename completion for readline. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <pwd.h>
+
+#include "posixdir.h"
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "xmalloc.h"
+#include "rlprivate.h"
+
+#ifdef __STDC__
+typedef int QSFUNC (const void *, const void *);
+#else
+typedef int QSFUNC ();
+#endif
+
+#ifdef HAVE_LSTAT
+# define LSTAT lstat
+#else
+# define LSTAT stat
+#endif
+
+/* Unix version of a hidden file. Could be different on other systems. */
+#define HIDDEN_FILE(fname) ((fname)[0] == '.')
+
+/* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is
+ defined. */
+#if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE)
+extern struct passwd *getpwent PARAMS((void));
+#endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */
+
+/* If non-zero, then this is the address of a function to call when
+ completing a word would normally display the list of possible matches.
+ This function is called instead of actually doing the display.
+ It takes three arguments: (char **matches, int num_matches, int max_length)
+ where MATCHES is the array of strings that matched, NUM_MATCHES is the
+ number of strings in that array, and MAX_LENGTH is the length of the
+ longest string in that array. */
+rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
+
+#if defined (VISIBLE_STATS)
+# if !defined (X_OK)
+# define X_OK 1
+# endif
+static int stat_char PARAMS((char *));
+#endif
+
+static char *rl_quote_filename PARAMS((char *, int, char *));
+
+static void set_completion_defaults PARAMS((int));
+static int get_y_or_n PARAMS((int));
+static int _rl_internal_pager PARAMS((int));
+static char *printable_part PARAMS((char *));
+static int print_filename PARAMS((char *, char *));
+
+static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
+
+static char **remove_duplicate_matches PARAMS((char **));
+static void insert_match PARAMS((char *, int, int, char *));
+static int append_to_match PARAMS((char *, int, int, int));
+static void insert_all_matches PARAMS((char **, int, char *));
+static void display_matches PARAMS((char **));
+static int compute_lcd_of_matches PARAMS((char **, int, const char *));
+static int postprocess_matches PARAMS((char ***, int));
+
+static char *make_quoted_replacement PARAMS((char *, int, char *));
+
+/* **************************************************************** */
+/* */
+/* Completion matching, from readline's point of view. */
+/* */
+/* **************************************************************** */
+
+/* Variables known only to the readline library. */
+
+/* If non-zero, non-unique completions always show the list of matches. */
+int _rl_complete_show_all = 0;
+
+/* If non-zero, completed directory names have a slash appended. */
+int _rl_complete_mark_directories = 1;
+
+/* If non-zero, the symlinked directory completion behavior introduced in
+ readline-4.2a is disabled, and symlinks that point to directories have
+ a slash appended (subject to the value of _rl_complete_mark_directories).
+ This is user-settable via the mark-symlinked-directories variable. */
+int _rl_complete_mark_symlink_dirs = 0;
+
+/* If non-zero, completions are printed horizontally in alphabetical order,
+ like `ls -x'. */
+int _rl_print_completions_horizontally;
+
+/* Non-zero means that case is not significant in filename completion. */
+#if defined (__MSDOS__) && !defined (__DJGPP__)
+int _rl_completion_case_fold = 1;
+#else
+int _rl_completion_case_fold;
+#endif
+
+/* If non-zero, don't match hidden files (filenames beginning with a `.' on
+ Unix) when doing filename completion. */
+int _rl_match_hidden_files = 1;
+
+/* Global variables available to applications using readline. */
+
+#if defined (VISIBLE_STATS)
+/* Non-zero means add an additional character to each filename displayed
+ during listing completion iff rl_filename_completion_desired which helps
+ to indicate the type of file being listed. */
+int rl_visible_stats = 0;
+#endif /* VISIBLE_STATS */
+
+/* If non-zero, then this is the address of a function to call when
+ completing on a directory name. The function is called with
+ the address of a string (the current directory name) as an arg. */
+rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
+
+rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
+
+/* Non-zero means readline completion functions perform tilde expansion. */
+int rl_complete_with_tilde_expansion = 0;
+
+/* Pointer to the generator function for completion_matches ().
+ NULL means to use rl_filename_completion_function (), the default filename
+ completer. */
+rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
+
+/* Pointer to alternative function to create matches.
+ Function is called with TEXT, START, and END.
+ START and END are indices in RL_LINE_BUFFER saying what the boundaries
+ of TEXT are.
+ If this function exists and returns NULL then call the value of
+ rl_completion_entry_function to try to match, otherwise use the
+ array of strings returned. */
+rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+
+/* Non-zero means to suppress normal filename completion after the
+ user-specified completion function has been called. */
+int rl_attempted_completion_over = 0;
+
+/* Set to a character indicating the type of completion being performed
+ by rl_complete_internal, available for use by application completion
+ functions. */
+int rl_completion_type = 0;
+
+/* Up to this many items will be displayed in response to a
+ possible-completions call. After that, we ask the user if
+ she is sure she wants to see them all. */
+int rl_completion_query_items = 100;
+
+int _rl_page_completions = 1;
+
+/* The basic list of characters that signal a break between words for the
+ completer routine. The contents of this variable is what breaks words
+ in the shell, i.e. " \t\n\"\\'`@$><=" */
+const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */
+
+/* List of basic quoting characters. */
+const char *rl_basic_quote_characters = "\"'";
+
+/* The list of characters that signal a break between words for
+ rl_complete_internal. The default list is the contents of
+ rl_basic_word_break_characters. */
+const char *rl_completer_word_break_characters = (const char *)NULL;
+
+/* List of characters which can be used to quote a substring of the line.
+ Completion occurs on the entire substring, and within the substring
+ rl_completer_word_break_characters are treated as any other character,
+ unless they also appear within this list. */
+const char *rl_completer_quote_characters = (const char *)NULL;
+
+/* List of characters that should be quoted in filenames by the completer. */
+const char *rl_filename_quote_characters = (const char *)NULL;
+
+/* List of characters that are word break characters, but should be left
+ in TEXT when it is passed to the completion function. The shell uses
+ this to help determine what kind of completing to do. */
+const char *rl_special_prefixes = (const char *)NULL;
+
+/* If non-zero, then disallow duplicates in the matches. */
+int rl_ignore_completion_duplicates = 1;
+
+/* Non-zero means that the results of the matches are to be treated
+ as filenames. This is ALWAYS zero on entry, and can only be changed
+ within a completion entry finder function. */
+int rl_filename_completion_desired = 0;
+
+/* Non-zero means that the results of the matches are to be quoted using
+ double quotes (or an application-specific quoting mechanism) if the
+ filename contains any characters in rl_filename_quote_chars. This is
+ ALWAYS non-zero on entry, and can only be changed within a completion
+ entry finder function. */
+int rl_filename_quoting_desired = 1;
+
+/* This function, if defined, is called by the completer when real
+ filename completion is done, after all the matching names have been
+ generated. It is passed a (char**) known as matches in the code below.
+ It consists of a NULL-terminated array of pointers to potential
+ matching strings. The 1st element (matches[0]) is the maximal
+ substring that is common to all matches. This function can re-arrange
+ the list of matches as required, but all elements of the array must be
+ free()'d if they are deleted. The main intent of this function is
+ to implement FIGNORE a la SunOS csh. */
+rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL;
+
+/* Set to a function to quote a filename in an application-specific fashion.
+ Called with the text to quote, the type of match found (single or multiple)
+ and a pointer to the quoting character to be used, which the function can
+ reset if desired. */
+rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename;
+
+/* Function to call to remove quoting characters from a filename. Called
+ before completion is attempted, so the embedded quotes do not interfere
+ with matching names in the file system. Readline doesn't do anything
+ with this; it's set only by applications. */
+rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL;
+
+/* Function to call to decide whether or not a word break character is
+ quoted. If a character is quoted, it does not break words for the
+ completer. */
+rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL;
+
+/* If non-zero, the completion functions don't append anything except a
+ possible closing quote. This is set to 0 by rl_complete_internal and
+ may be changed by an application-specific completion function. */
+int rl_completion_suppress_append = 0;
+
+/* Character appended to completed words when at the end of the line. The
+ default is a space. */
+int rl_completion_append_character = ' ';
+
+/* If non-zero, a slash will be appended to completed filenames that are
+ symbolic links to directory names, subject to the value of the
+ mark-directories variable (which is user-settable). This exists so
+ that application completion functions can override the user's preference
+ (set via the mark-symlinked-directories variable) if appropriate.
+ It's set to the value of _rl_complete_mark_symlink_dirs in
+ rl_complete_internal before any application-specific completion
+ function is called, so without that function doing anything, the user's
+ preferences are honored. */
+int rl_completion_mark_symlink_dirs;
+
+/* If non-zero, inhibit completion (temporarily). */
+int rl_inhibit_completion;
+
+/* Variables local to this file. */
+
+/* Local variable states what happened during the last completion attempt. */
+static int completion_changed_buffer;
+
+/*************************************/
+/* */
+/* Bindable completion functions */
+/* */
+/*************************************/
+
+/* Complete the word at or before point. You have supplied the function
+ that does the initial simple matching selection algorithm (see
+ rl_completion_matches ()). The default is to do filename completion. */
+int
+rl_complete (ignore, invoking_key)
+ int ignore, invoking_key;
+{
+ if (rl_inhibit_completion)
+ return (_rl_insert_char (ignore, invoking_key));
+ else if (rl_last_func == rl_complete && !completion_changed_buffer)
+ return (rl_complete_internal ('?'));
+ else if (_rl_complete_show_all)
+ return (rl_complete_internal ('!'));
+ else
+ return (rl_complete_internal (TAB));
+}
+
+/* List the possible completions. See description of rl_complete (). */
+int
+rl_possible_completions (ignore, invoking_key)
+ int ignore __attribute__((unused)), invoking_key __attribute__((unused));
+{
+ return (rl_complete_internal ('?'));
+}
+
+int
+rl_insert_completions (ignore, invoking_key)
+ int ignore __attribute__((unused)), invoking_key __attribute__((unused));
+{
+ return (rl_complete_internal ('*'));
+}
+
+/* Return the correct value to pass to rl_complete_internal performing
+ the same tests as rl_complete. This allows consecutive calls to an
+ application's completion function to list possible completions and for
+ an application-specific completion function to honor the
+ show-all-if-ambiguous readline variable. */
+int
+rl_completion_mode (cfunc)
+ rl_command_func_t *cfunc;
+{
+ if (rl_last_func == cfunc && !completion_changed_buffer)
+ return '?';
+ else if (_rl_complete_show_all)
+ return '!';
+ else
+ return TAB;
+}
+
+/************************************/
+/* */
+/* Completion utility functions */
+/* */
+/************************************/
+
+/* Set default values for readline word completion. These are the variables
+ that application completion functions can change or inspect. */
+static void
+set_completion_defaults (what_to_do)
+ int what_to_do;
+{
+ /* Only the completion entry function can change these. */
+ rl_filename_completion_desired = 0;
+ rl_filename_quoting_desired = 1;
+ rl_completion_type = what_to_do;
+ rl_completion_suppress_append = 0;
+
+ /* The completion entry function may optionally change this. */
+ rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
+}
+
+/* The user must press "y" or "n". Non-zero return means "y" pressed. */
+static int
+get_y_or_n (for_pager)
+ int for_pager;
+{
+ int c;
+
+ for (;;)
+ {
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (c == 'y' || c == 'Y' || c == ' ')
+ return (1);
+ if (c == 'n' || c == 'N' || c == RUBOUT)
+ return (0);
+ if (c == ABORT_CHAR)
+ _rl_abort_internal ();
+ if (for_pager && (c == NEWLINE || c == RETURN))
+ return (2);
+ if (for_pager && (c == 'q' || c == 'Q'))
+ return (0);
+ rl_ding ();
+ }
+}
+
+static int
+_rl_internal_pager (lines)
+ int lines;
+{
+ int i;
+
+ fprintf (rl_outstream, "--More--");
+ fflush (rl_outstream);
+ i = get_y_or_n (1);
+ _rl_erase_entire_line ();
+ if (i == 0)
+ return -1;
+ else if (i == 2)
+ return (lines - 1);
+ else
+ return 0;
+}
+
+#if defined (VISIBLE_STATS)
+/* Return the character which best describes FILENAME.
+ `@' for symbolic links
+ `/' for directories
+ `*' for executables
+ `=' for sockets
+ `|' for FIFOs
+ `%' for character special devices
+ `#' for block special devices */
+static int
+stat_char (filename)
+ char *filename;
+{
+ struct stat finfo;
+ int character, r;
+
+#if defined (HAVE_LSTAT) && defined (S_ISLNK)
+ r = lstat (filename, &finfo);
+#else
+ r = stat (filename, &finfo);
+#endif
+
+ if (r == -1)
+ return (0);
+
+ character = 0;
+ if (S_ISDIR (finfo.st_mode))
+ character = '/';
+#if defined (S_ISCHR)
+ else if (S_ISCHR (finfo.st_mode))
+ character = '%';
+#endif /* S_ISCHR */
+#if defined (S_ISBLK)
+ else if (S_ISBLK (finfo.st_mode))
+ character = '#';
+#endif /* S_ISBLK */
+#if defined (S_ISLNK)
+ else if (S_ISLNK (finfo.st_mode))
+ character = '@';
+#endif /* S_ISLNK */
+#if defined (S_ISSOCK)
+ else if (S_ISSOCK (finfo.st_mode))
+ character = '=';
+#endif /* S_ISSOCK */
+#if defined (S_ISFIFO)
+ else if (S_ISFIFO (finfo.st_mode))
+ character = '|';
+#endif
+ else if (S_ISREG (finfo.st_mode))
+ {
+ if (access (filename, X_OK) == 0)
+ character = '*';
+ }
+ return (character);
+}
+#endif /* VISIBLE_STATS */
+
+/* Return the portion of PATHNAME that should be output when listing
+ possible completions. If we are hacking filename completion, we
+ are only interested in the basename, the portion following the
+ final slash. Otherwise, we return what we were passed. Since
+ printing empty strings is not very informative, if we're doing
+ filename completion, and the basename is the empty string, we look
+ for the previous slash and return the portion following that. If
+ there's no previous slash, we just return what we were passed. */
+static char *
+printable_part (pathname)
+ char *pathname;
+{
+ char *temp, *x;
+
+ if (rl_filename_completion_desired == 0) /* don't need to do anything */
+ return (pathname);
+
+ temp = strrchr (pathname, '/');
+#if defined (__MSDOS__)
+ if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
+ temp = pathname + 1;
+#endif
+
+ if (temp == 0 || *temp == '\0')
+ return (pathname);
+ /* If the basename is NULL, we might have a pathname like '/usr/src/'.
+ Look for a previous slash and, if one is found, return the portion
+ following that slash. If there's no previous slash, just return the
+ pathname we were passed. */
+ else if (temp[1] == '\0')
+ {
+ for (x = temp - 1; x > pathname; x--)
+ if (*x == '/')
+ break;
+ return ((*x == '/') ? x + 1 : pathname);
+ }
+ else
+ return ++temp;
+}
+
+/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
+ are using it, check for and output a single character for `special'
+ filenames. Return the number of characters we output. */
+
+#define PUTX(c) \
+ do { \
+ if (CTRL_CHAR (c)) \
+ { \
+ putc ('^', rl_outstream); \
+ putc (UNCTRL (c), rl_outstream); \
+ printed_len += 2; \
+ } \
+ else if (c == RUBOUT) \
+ { \
+ putc ('^', rl_outstream); \
+ putc ('?', rl_outstream); \
+ printed_len += 2; \
+ } \
+ else \
+ { \
+ putc (c, rl_outstream); \
+ printed_len++; \
+ } \
+ } while (0)
+
+static int
+print_filename (to_print, full_pathname)
+ char *to_print, *full_pathname;
+{
+ int printed_len = 0;
+#if !defined (VISIBLE_STATS)
+ char *s;
+
+ for (s = to_print; *s; s++)
+ {
+ PUTX (*s);
+ }
+#else
+ char *s, c, *new_full_pathname;
+ int extension_char, slen, tlen;
+
+ for (s = to_print; *s; s++)
+ {
+ PUTX (*s);
+ }
+
+ if (rl_filename_completion_desired && rl_visible_stats)
+ {
+ /* If to_print != full_pathname, to_print is the basename of the
+ path passed. In this case, we try to expand the directory
+ name before checking for the stat character. */
+ if (to_print != full_pathname)
+ {
+ /* Terminate the directory name. */
+ c = to_print[-1];
+ to_print[-1] = '\0';
+
+ /* If setting the last slash in full_pathname to a NUL results in
+ full_pathname being the empty string, we are trying to complete
+ files in the root directory. If we pass a null string to the
+ bash directory completion hook, for example, it will expand it
+ to the current directory. We just want the `/'. */
+ s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/");
+ if (rl_directory_completion_hook)
+ (*rl_directory_completion_hook) (&s);
+
+ slen = strlen (s);
+ tlen = strlen (to_print);
+ new_full_pathname = (char *)xmalloc (slen + tlen + 2);
+ strcpy (new_full_pathname, s);
+ new_full_pathname[slen] = '/';
+ strcpy (new_full_pathname + slen + 1, to_print);
+
+ extension_char = stat_char (new_full_pathname);
+
+ free (new_full_pathname);
+ to_print[-1] = c;
+ }
+ else
+ {
+ s = tilde_expand (full_pathname);
+ extension_char = stat_char (s);
+ }
+
+ free (s);
+ if (extension_char)
+ {
+ putc (extension_char, rl_outstream);
+ printed_len++;
+ }
+ }
+#endif /* VISIBLE_STATS */
+ return printed_len;
+}
+
+static char *
+rl_quote_filename (s, rtype, qcp)
+ char *s;
+ int rtype __attribute__((unused));
+ char *qcp;
+{
+ char *r;
+
+ r = (char *)xmalloc (strlen (s) + 2);
+ *r = *rl_completer_quote_characters;
+ strcpy (r + 1, s);
+ if (qcp)
+ *qcp = *rl_completer_quote_characters;
+ return r;
+}
+
+/* Find the bounds of the current word for completion purposes, and leave
+ rl_point set to the end of the word. This function skips quoted
+ substrings (characters between matched pairs of characters in
+ rl_completer_quote_characters). First we try to find an unclosed
+ quoted substring on which to do matching. If one is not found, we use
+ the word break characters to find the boundaries of the current word.
+ We call an application-specific function to decide whether or not a
+ particular word break character is quoted; if that function returns a
+ non-zero result, the character does not break a word. This function
+ returns the opening quote character if we found an unclosed quoted
+ substring, '\0' otherwise. FP, if non-null, is set to a value saying
+ which (shell-like) quote characters we found (single quote, double
+ quote, or backslash) anywhere in the string. DP, if non-null, is set to
+ the value of the delimiter character that caused a word break. */
+
+char
+_rl_find_completion_word (fp, dp)
+ int *fp, *dp;
+{
+ int scan, end, found_quote, delimiter, pass_next, isbrk;
+ char quote_char;
+
+ end = rl_point;
+ found_quote = delimiter = 0;
+ quote_char = '\0';
+
+ if (rl_completer_quote_characters)
+ {
+ /* We have a list of characters which can be used in pairs to
+ quote substrings for the completer. Try to find the start
+ of an unclosed quoted substring. */
+ /* FOUND_QUOTE is set so we know what kind of quotes we found. */
+ for (scan = pass_next = 0; scan < end; scan++)
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ continue;
+ }
+
+ /* Shell-like semantics for single quotes -- don't allow backslash
+ to quote anything in single quotes, especially not the closing
+ quote. If you don't like this, take out the check on the value
+ of quote_char. */
+ if (quote_char != '\'' && rl_line_buffer[scan] == '\\')
+ {
+ pass_next = 1;
+ found_quote |= RL_QF_BACKSLASH;
+ continue;
+ }
+
+ if (quote_char != '\0')
+ {
+ /* Ignore everything until the matching close quote char. */
+ if (rl_line_buffer[scan] == quote_char)
+ {
+ /* Found matching close. Abandon this substring. */
+ quote_char = '\0';
+ rl_point = end;
+ }
+ }
+ else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
+ {
+ /* Found start of a quoted substring. */
+ quote_char = rl_line_buffer[scan];
+ rl_point = scan + 1;
+ /* Shell-like quoting conventions. */
+ if (quote_char == '\'')
+ found_quote |= RL_QF_SINGLE_QUOTE;
+ else if (quote_char == '"')
+ found_quote |= RL_QF_DOUBLE_QUOTE;
+ else
+ found_quote |= RL_QF_OTHER_QUOTE;
+ }
+ }
+ }
+
+ if (rl_point == end && quote_char == '\0')
+ {
+ /* We didn't find an unclosed quoted substring upon which to do
+ completion, so use the word break characters to find the
+ substring on which to complete. */
+#if defined (HANDLE_MULTIBYTE)
+ while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))
+#else
+ while (--rl_point)
+#endif
+ {
+ scan = rl_line_buffer[rl_point];
+
+ if (strchr (rl_completer_word_break_characters, scan) == 0)
+ continue;
+
+ /* Call the application-specific function to tell us whether
+ this word break character is quoted and should be skipped. */
+ if (rl_char_is_quoted_p && found_quote &&
+ (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
+ continue;
+
+ /* Convoluted code, but it avoids an n^2 algorithm with calls
+ to char_is_quoted. */
+ break;
+ }
+ }
+
+ /* If we are at an unquoted word break, then advance past it. */
+ scan = rl_line_buffer[rl_point];
+
+ /* If there is an application-specific function to say whether or not
+ a character is quoted and we found a quote character, let that
+ function decide whether or not a character is a word break, even
+ if it is found in rl_completer_word_break_characters. Don't bother
+ if we're at the end of the line, though. */
+ if (scan)
+ {
+ if (rl_char_is_quoted_p)
+ isbrk = (found_quote == 0 ||
+ (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
+ strchr (rl_completer_word_break_characters, scan) != 0;
+ else
+ isbrk = strchr (rl_completer_word_break_characters, scan) != 0;
+
+ if (isbrk)
+ {
+ /* If the character that caused the word break was a quoting
+ character, then remember it as the delimiter. */
+ if (rl_basic_quote_characters &&
+ strchr (rl_basic_quote_characters, scan) &&
+ (end - rl_point) > 1)
+ delimiter = scan;
+
+ /* If the character isn't needed to determine something special
+ about what kind of completion to perform, then advance past it. */
+ if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0)
+ rl_point++;
+ }
+ }
+
+ if (fp)
+ *fp = found_quote;
+ if (dp)
+ *dp = delimiter;
+
+ return (quote_char);
+}
+
+static char **
+gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
+ char *text;
+ int start, end;
+ rl_compentry_func_t *our_func;
+ int found_quote, quote_char;
+{
+ char **matches, *temp;
+
+ /* If the user wants to TRY to complete, but then wants to give
+ up and use the default completion function, they set the
+ variable rl_attempted_completion_function. */
+ if (rl_attempted_completion_function)
+ {
+ matches = (*rl_attempted_completion_function) (text, start, end);
+
+ if (matches || rl_attempted_completion_over)
+ {
+ rl_attempted_completion_over = 0;
+ return (matches);
+ }
+ }
+
+ /* Beware -- we're stripping the quotes here. Do this only if we know
+ we are doing filename completion and the application has defined a
+ filename dequoting function. */
+ temp = (char *)NULL;
+
+ if (found_quote && our_func == rl_filename_completion_function &&
+ rl_filename_dequoting_function)
+ {
+ /* delete single and double quotes */
+ temp = (*rl_filename_dequoting_function) (text, quote_char);
+ text = temp; /* not freeing text is not a memory leak */
+ }
+
+ matches = rl_completion_matches (text, our_func);
+ FREE (temp);
+ return matches;
+}
+
+/* Filter out duplicates in MATCHES. This frees up the strings in
+ MATCHES. */
+static char **
+remove_duplicate_matches (matches)
+ char **matches;
+{
+ char *lowest_common;
+ int i, j, newlen;
+ char dead_slot;
+ char **temp_array;
+
+ /* Sort the items. */
+ for (i = 0; matches[i]; i++)
+ ;
+
+ /* Sort the array without matches[0], since we need it to
+ stay in place no matter what. */
+ if (i)
+ qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
+
+ /* Remember the lowest common denominator for it may be unique. */
+ lowest_common = savestring (matches[0]);
+
+ for (i = newlen = 0; matches[i + 1]; i++)
+ {
+ if (strcmp (matches[i], matches[i + 1]) == 0)
+ {
+ free (matches[i]);
+ matches[i] = (char *)&dead_slot;
+ }
+ else
+ newlen++;
+ }
+
+ /* We have marked all the dead slots with (char *)&dead_slot.
+ Copy all the non-dead entries into a new array. */
+ temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
+ for (i = j = 1; matches[i]; i++)
+ {
+ if (matches[i] != (char *)&dead_slot)
+ temp_array[j++] = matches[i];
+ }
+ temp_array[j] = (char *)NULL;
+
+ if (matches[0] != (char *)&dead_slot)
+ free (matches[0]);
+
+ /* Place the lowest common denominator back in [0]. */
+ temp_array[0] = lowest_common;
+
+ /* If there is one string left, and it is identical to the
+ lowest common denominator, then the LCD is the string to
+ insert. */
+ if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
+ {
+ free (temp_array[1]);
+ temp_array[1] = (char *)NULL;
+ }
+ return (temp_array);
+}
+
+/* Find the common prefix of the list of matches, and put it into
+ matches[0]. */
+static int
+compute_lcd_of_matches (match_list, matches, text)
+ char **match_list;
+ int matches;
+ const char *text;
+{
+ register int i, c1, c2, si;
+ int low; /* Count of max-matched characters. */
+#if defined (HANDLE_MULTIBYTE)
+ int v;
+ mbstate_t ps1, ps2;
+ wchar_t wc1, wc2;
+#endif
+
+ /* If only one match, just use that. Otherwise, compare each
+ member of the list with the next, finding out where they
+ stop matching. */
+ if (matches == 1)
+ {
+ match_list[0] = match_list[1];
+ match_list[1] = (char *)NULL;
+ return 1;
+ }
+
+ for (i = 1, low = 100000; i < matches; i++)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ memset (&ps1, 0, sizeof (mbstate_t));
+ memset (&ps2, 0, sizeof (mbstate_t));
+ }
+#endif
+ if (_rl_completion_case_fold)
+ {
+ for (si = 0;
+ (c1 = _rl_to_lower(match_list[i][si])) &&
+ (c2 = _rl_to_lower(match_list[i + 1][si]));
+ si++)
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
+ mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
+ wc1 = towlower (wc1);
+ wc2 = towlower (wc2);
+ if (wc1 != wc2)
+ break;
+ else if (v > 1)
+ si += v - 1;
+ }
+ else
+#endif
+ if (c1 != c2)
+ break;
+ }
+ else
+ {
+ for (si = 0;
+ (c1 = match_list[i][si]) &&
+ (c2 = match_list[i + 1][si]);
+ si++)
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ mbstate_t ps_back = ps1;
+ if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
+ break;
+ else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
+ si += v - 1;
+ }
+ else
+#endif
+ if (c1 != c2)
+ break;
+ }
+
+ if (low > si)
+ low = si;
+ }
+
+ /* If there were multiple matches, but none matched up to even the
+ first character, and the user typed something, use that as the
+ value of matches[0]. */
+ if (low == 0 && text && *text)
+ {
+ match_list[0] = (char *)xmalloc (strlen (text) + 1);
+ strcpy (match_list[0], text);
+ }
+ else
+ {
+ match_list[0] = (char *)xmalloc (low + 1);
+
+ /* XXX - this might need changes in the presence of multibyte chars */
+
+ /* If we are ignoring case, try to preserve the case of the string
+ the user typed in the face of multiple matches differing in case. */
+ if (_rl_completion_case_fold)
+ {
+ /* sort the list to get consistent answers. */
+ qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
+
+ si = strlen (text);
+ if (si <= low)
+ {
+ for (i = 1; i <= matches; i++)
+ if (strncmp (match_list[i], text, si) == 0)
+ {
+ strncpy (match_list[0], match_list[i], low);
+ break;
+ }
+ /* no casematch, use first entry */
+ if (i > matches)
+ strncpy (match_list[0], match_list[1], low);
+ }
+ else
+ /* otherwise, just use the text the user typed. */
+ strncpy (match_list[0], text, low);
+ }
+ else
+ strncpy (match_list[0], match_list[1], low);
+
+ match_list[0][low] = '\0';
+ }
+
+ return matches;
+}
+
+static int
+postprocess_matches (matchesp, matching_filenames)
+ char ***matchesp;
+ int matching_filenames;
+{
+ char *t, **matches, **temp_matches;
+ int nmatch, i;
+
+ matches = *matchesp;
+
+ if (matches == 0)
+ return 0;
+
+ /* It seems to me that in all the cases we handle we would like
+ to ignore duplicate possiblilities. Scan for the text to
+ insert being identical to the other completions. */
+ if (rl_ignore_completion_duplicates)
+ {
+ temp_matches = remove_duplicate_matches (matches);
+ free (matches);
+ matches = temp_matches;
+ }
+
+ /* If we are matching filenames, then here is our chance to
+ do clever processing by re-examining the list. Call the
+ ignore function with the array as a parameter. It can
+ munge the array, deleting matches as it desires. */
+ if (rl_ignore_some_completions_function && matching_filenames)
+ {
+ for (nmatch = 1; matches[nmatch]; nmatch++)
+ ;
+ (void)(*rl_ignore_some_completions_function) (matches);
+ if (matches == 0 || matches[0] == 0)
+ {
+ FREE (matches);
+ *matchesp = (char **)0;
+ return 0;
+ }
+ else
+ {
+ /* If we removed some matches, recompute the common prefix. */
+ for (i = 1; matches[i]; i++)
+ ;
+ if (i > 1 && i < nmatch)
+ {
+ t = matches[0];
+ compute_lcd_of_matches (matches, i - 1, t);
+ FREE (t);
+ }
+ }
+ }
+
+ *matchesp = matches;
+ return (1);
+}
+
+/* A convenience function for displaying a list of strings in
+ columnar format on readline's output stream. MATCHES is the list
+ of strings, in argv format, LEN is the number of strings in MATCHES,
+ and MAX is the length of the longest string in MATCHES. */
+void
+rl_display_match_list (matches, len, max)
+ char **matches;
+ int len, max;
+{
+ int count, limit, printed_len, lines;
+ int i, j, k, l;
+ char *temp;
+
+ /* How many items of MAX length can we fit in the screen window? */
+ max += 2;
+ limit = _rl_screenwidth / max;
+ if (limit != 1 && (limit * max == _rl_screenwidth))
+ limit--;
+
+ /* Avoid a possible floating exception. If max > _rl_screenwidth,
+ limit will be 0 and a divide-by-zero fault will result. */
+ if (limit == 0)
+ limit = 1;
+
+ /* How many iterations of the printing loop? */
+ count = (len + (limit - 1)) / limit;
+
+ /* Watch out for special case. If LEN is less than LIMIT, then
+ just do the inner printing loop.
+ 0 < len <= limit implies count = 1. */
+
+ /* Sort the items if they are not already sorted. */
+ if (rl_ignore_completion_duplicates == 0)
+ qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
+
+ rl_crlf ();
+
+ lines = 0;
+ if (_rl_print_completions_horizontally == 0)
+ {
+ /* Print the sorted items, up-and-down alphabetically, like ls. */
+ for (i = 1; i <= count; i++)
+ {
+ for (j = 0, l = i; j < limit; j++)
+ {
+ if (l > len || matches[l] == 0)
+ break;
+ else
+ {
+ temp = printable_part (matches[l]);
+ printed_len = print_filename (temp, matches[l]);
+
+ if (j + 1 < limit)
+ for (k = 0; k < max - printed_len; k++)
+ putc (' ', rl_outstream);
+ }
+ l += count;
+ }
+ rl_crlf ();
+ lines++;
+ if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
+ {
+ lines = _rl_internal_pager (lines);
+ if (lines < 0)
+ return;
+ }
+ }
+ }
+ else
+ {
+ /* Print the sorted items, across alphabetically, like ls -x. */
+ for (i = 1; matches[i]; i++)
+ {
+ temp = printable_part (matches[i]);
+ printed_len = print_filename (temp, matches[i]);
+ /* Have we reached the end of this line? */
+ if (matches[i+1])
+ {
+ if (i && (limit > 1) && (i % limit) == 0)
+ {
+ rl_crlf ();
+ lines++;
+ if (_rl_page_completions && lines >= _rl_screenheight - 1)
+ {
+ lines = _rl_internal_pager (lines);
+ if (lines < 0)
+ return;
+ }
+ }
+ else
+ for (k = 0; k < max - printed_len; k++)
+ putc (' ', rl_outstream);
+ }
+ }
+ rl_crlf ();
+ }
+}
+
+/* Display MATCHES, a list of matching filenames in argv format. This
+ handles the simple case -- a single match -- first. If there is more
+ than one match, we compute the number of strings in the list and the
+ length of the longest string, which will be needed by the display
+ function. If the application wants to handle displaying the list of
+ matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
+ address of a function, and we just call it. If we're handling the
+ display ourselves, we just call rl_display_match_list. We also check
+ that the list of matches doesn't exceed the user-settable threshold,
+ and ask the user if he wants to see the list if there are more matches
+ than RL_COMPLETION_QUERY_ITEMS. */
+static void
+display_matches (matches)
+ char **matches;
+{
+ int len, max, i;
+ char *temp;
+
+ /* Move to the last visible line of a possibly-multiple-line command. */
+ _rl_move_vert (_rl_vis_botlin);
+
+ /* Handle simple case first. What if there is only one answer? */
+ if (matches[1] == 0)
+ {
+ temp = printable_part (matches[0]);
+ rl_crlf ();
+ print_filename (temp, matches[0]);
+ rl_crlf ();
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return;
+ }
+
+ /* There is more than one answer. Find out how many there are,
+ and find the maximum printed length of a single entry. */
+ for (max = 0, i = 1; matches[i]; i++)
+ {
+ temp = printable_part (matches[i]);
+ len = strlen (temp);
+
+ if (len > max)
+ max = len;
+ }
+
+ len = i - 1;
+
+ /* If the caller has defined a display hook, then call that now. */
+ if (rl_completion_display_matches_hook)
+ {
+ (*rl_completion_display_matches_hook) (matches, len, max);
+ return;
+ }
+
+ /* If there are many items, then ask the user if she really wants to
+ see them all. */
+ if (len >= rl_completion_query_items)
+ {
+ rl_crlf ();
+ fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
+ fflush (rl_outstream);
+ if (get_y_or_n (0) == 0)
+ {
+ rl_crlf ();
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return;
+ }
+ }
+
+ rl_display_match_list (matches, len, max);
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+}
+
+static char *
+make_quoted_replacement (match, mtype, qc)
+ char *match;
+ int mtype;
+ char *qc; /* Pointer to quoting character, if any */
+{
+ int should_quote, do_replace;
+ char *replacement;
+
+ /* If we are doing completion on quoted substrings, and any matches
+ contain any of the completer_word_break_characters, then auto-
+ matically prepend the substring with a quote character (just pick
+ the first one from the list of such) if it does not already begin
+ with a quote string. FIXME: Need to remove any such automatically
+ inserted quote character when it no longer is necessary, such as
+ if we change the string we are completing on and the new set of
+ matches don't require a quoted substring. */
+ replacement = match;
+
+ should_quote = match && rl_completer_quote_characters &&
+ rl_filename_completion_desired &&
+ rl_filename_quoting_desired;
+
+ if (should_quote)
+ should_quote = should_quote && (!qc || !*qc ||
+ (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc)));
+
+ if (should_quote)
+ {
+ /* If there is a single match, see if we need to quote it.
+ This also checks whether the common prefix of several
+ matches needs to be quoted. */
+ should_quote = rl_filename_quote_characters
+ ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
+ : 0;
+
+ do_replace = should_quote ? mtype : NO_MATCH;
+ /* Quote the replacement, since we found an embedded
+ word break character in a potential match. */
+ if (do_replace != NO_MATCH && rl_filename_quoting_function)
+ replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
+ }
+ return (replacement);
+}
+
+static void
+insert_match (match, start, mtype, qc)
+ char *match;
+ int start, mtype;
+ char *qc;
+{
+ char *replacement;
+ char oqc;
+
+ oqc = qc ? *qc : '\0';
+ replacement = make_quoted_replacement (match, mtype, qc);
+
+ /* Now insert the match. */
+ if (replacement)
+ {
+ /* Don't double an opening quote character. */
+ if (qc && *qc && start && rl_line_buffer[start - 1] == *qc &&
+ replacement[0] == *qc)
+ start--;
+ /* If make_quoted_replacement changed the quoting character, remove
+ the opening quote and insert the (fully-quoted) replacement. */
+ else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc &&
+ replacement[0] != oqc)
+ start--;
+ _rl_replace_text (replacement, start, rl_point - 1);
+ if (replacement != match)
+ free (replacement);
+ }
+}
+
+/* Append any necessary closing quote and a separator character to the
+ just-inserted match. If the user has specified that directories
+ should be marked by a trailing `/', append one of those instead. The
+ default trailing character is a space. Returns the number of characters
+ appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
+ has them) and don't add a suffix for a symlink to a directory. A
+ nontrivial match is one that actually adds to the word being completed.
+ The variable rl_completion_mark_symlink_dirs controls this behavior
+ (it's initially set to the what the user has chosen, indicated by the
+ value of _rl_complete_mark_symlink_dirs, but may be modified by an
+ application's completion function). */
+static int
+append_to_match (text, delimiter, quote_char, nontrivial_match)
+ char *text;
+ int delimiter, quote_char, nontrivial_match;
+{
+ char temp_string[4], *filename;
+ int temp_string_index, s;
+ struct stat finfo;
+
+ temp_string_index = 0;
+ if (quote_char && rl_point && rl_line_buffer[rl_point - 1] != quote_char)
+ temp_string[temp_string_index++] = quote_char;
+
+ if (delimiter)
+ temp_string[temp_string_index++] = delimiter;
+ else if (rl_completion_suppress_append == 0 && rl_completion_append_character)
+ temp_string[temp_string_index++] = rl_completion_append_character;
+
+ temp_string[temp_string_index++] = '\0';
+
+ if (rl_filename_completion_desired)
+ {
+ filename = tilde_expand (text);
+ s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
+ ? LSTAT (filename, &finfo)
+ : stat (filename, &finfo);
+ if (s == 0 && S_ISDIR (finfo.st_mode))
+ {
+ if (_rl_complete_mark_directories)
+ {
+ /* This is clumsy. Avoid putting in a double slash if point
+ is at the end of the line and the previous character is a
+ slash. */
+ if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/')
+ ;
+ else if (rl_line_buffer[rl_point] != '/')
+ rl_insert_text ("/");
+ }
+ }
+#ifdef S_ISLNK
+ /* Don't add anything if the filename is a symlink and resolves to a
+ directory. */
+ else if (s == 0 && S_ISLNK (finfo.st_mode) &&
+ stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
+ ;
+#endif
+ else
+ {
+ if (rl_point == rl_end && temp_string_index)
+ rl_insert_text (temp_string);
+ }
+ free (filename);
+ }
+ else
+ {
+ if (rl_point == rl_end && temp_string_index)
+ rl_insert_text (temp_string);
+ }
+
+ return (temp_string_index);
+}
+
+static void
+insert_all_matches (matches, point, qc)
+ char **matches;
+ int point;
+ char *qc;
+{
+ int i;
+ char *rp;
+
+ rl_begin_undo_group ();
+ /* remove any opening quote character; make_quoted_replacement will add
+ it back. */
+ if (qc && *qc && point && rl_line_buffer[point - 1] == *qc)
+ point--;
+ rl_delete_text (point, rl_point);
+ rl_point = point;
+
+ if (matches[1])
+ {
+ for (i = 1; matches[i]; i++)
+ {
+ rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc);
+ rl_insert_text (rp);
+ rl_insert_text (" ");
+ if (rp != matches[i])
+ free (rp);
+ }
+ }
+ else
+ {
+ rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
+ rl_insert_text (rp);
+ rl_insert_text (" ");
+ if (rp != matches[0])
+ free (rp);
+ }
+ rl_end_undo_group ();
+}
+
+void
+_rl_free_match_list (matches)
+ char **matches;
+{
+ register int i;
+
+ if (matches == 0)
+ return;
+
+ for (i = 0; matches[i]; i++)
+ free (matches[i]);
+ free (matches);
+}
+
+/* Complete the word at or before point.
+ WHAT_TO_DO says what to do with the completion.
+ `?' means list the possible completions.
+ TAB means do standard completion.
+ `*' means insert all of the possible completions.
+ `!' means to do standard completion, and list all possible completions if
+ there is more than one. */
+int
+rl_complete_internal (what_to_do)
+ int what_to_do;
+{
+ char **matches;
+ rl_compentry_func_t *our_func;
+ int start, end, delimiter, found_quote, i, nontrivial_lcd;
+ char *text, *saved_line_buffer;
+ char quote_char;
+
+ RL_SETSTATE(RL_STATE_COMPLETING);
+
+ set_completion_defaults (what_to_do);
+
+ saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
+ our_func = rl_completion_entry_function
+ ? rl_completion_entry_function
+ : rl_filename_completion_function;
+
+ /* We now look backwards for the start of a filename/variable word. */
+ end = rl_point;
+ found_quote = delimiter = 0;
+ quote_char = '\0';
+
+ if (rl_point)
+ /* This (possibly) changes rl_point. If it returns a non-zero char,
+ we know we have an open quote. */
+ quote_char = _rl_find_completion_word (&found_quote, &delimiter);
+
+ start = rl_point;
+ rl_point = end;
+
+ text = rl_copy_text (start, end);
+ matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
+ /* nontrivial_lcd is set if the common prefix adds something to the word
+ being completed. */
+ nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
+ free (text);
+
+ if (matches == 0)
+ {
+ rl_ding ();
+ FREE (saved_line_buffer);
+ completion_changed_buffer = 0;
+ RL_UNSETSTATE(RL_STATE_COMPLETING);
+ return (0);
+ }
+
+ /* If we are matching filenames, the attempted completion function will
+ have set rl_filename_completion_desired to a non-zero value. The basic
+ rl_filename_completion_function does this. */
+ i = rl_filename_completion_desired;
+
+ if (postprocess_matches (&matches, i) == 0)
+ {
+ rl_ding ();
+ FREE (saved_line_buffer);
+ completion_changed_buffer = 0;
+ RL_UNSETSTATE(RL_STATE_COMPLETING);
+ return (0);
+ }
+
+ switch (what_to_do)
+ {
+ case TAB:
+ case '!':
+ /* Insert the first match with proper quoting. */
+ if (*matches[0])
+ insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
+
+ /* If there are more matches, ring the bell to indicate.
+ If we are in vi mode, Posix.2 says to not ring the bell.
+ If the `show-all-if-ambiguous' variable is set, display
+ all the matches immediately. Otherwise, if this was the
+ only match, and we are hacking files, check the file to
+ see if it was a directory. If so, and the `mark-directories'
+ variable is set, add a '/' to the name. If not, and we
+ are at the end of the line, then add a space. */
+ if (matches[1])
+ {
+ if (what_to_do == '!')
+ {
+ display_matches (matches);
+ break;
+ }
+ else if (rl_editing_mode != vi_mode)
+ rl_ding (); /* There are other matches remaining. */
+ }
+ else
+ append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
+
+ break;
+
+ case '*':
+ insert_all_matches (matches, start, &quote_char);
+ break;
+
+ case '?':
+ display_matches (matches);
+ break;
+
+ default:
+ fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do);
+ rl_ding ();
+ FREE (saved_line_buffer);
+ RL_UNSETSTATE(RL_STATE_COMPLETING);
+ return 1;
+ }
+
+ _rl_free_match_list (matches);
+
+ /* Check to see if the line has changed through all of this manipulation. */
+ if (saved_line_buffer)
+ {
+ completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
+ free (saved_line_buffer);
+ }
+
+ RL_UNSETSTATE(RL_STATE_COMPLETING);
+ return 0;
+}
+
+/***************************************************************/
+/* */
+/* Application-callable completion match generator functions */
+/* */
+/***************************************************************/
+
+/* Return an array of (char *) which is a list of completions for TEXT.
+ If there are no completions, return a NULL pointer.
+ The first entry in the returned array is the substitution for TEXT.
+ The remaining entries are the possible completions.
+ The array is terminated with a NULL pointer.
+
+ ENTRY_FUNCTION is a function of two args, and returns a (char *).
+ The first argument is TEXT.
+ The second is a state argument; it should be zero on the first call, and
+ non-zero on subsequent calls. It returns a NULL pointer to the caller
+ when there are no more matches.
+ */
+char **
+rl_completion_matches (text, entry_function)
+ const char *text;
+ rl_compentry_func_t *entry_function;
+{
+ /* Number of slots in match_list. */
+ int match_list_size;
+
+ /* The list of matches. */
+ char **match_list;
+
+ /* Number of matches actually found. */
+ int matches;
+
+ /* Temporary string binder. */
+ char *string;
+
+ matches = 0;
+ match_list_size = 10;
+ match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
+ match_list[1] = (char *)NULL;
+
+ while ((string = (*entry_function) (text, matches)))
+ {
+ if (matches + 1 == match_list_size)
+ match_list = (char **)xrealloc
+ (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
+
+ match_list[++matches] = string;
+ match_list[matches + 1] = (char *)NULL;
+ }
+
+ /* If there were any matches, then look through them finding out the
+ lowest common denominator. That then becomes match_list[0]. */
+ if (matches)
+ compute_lcd_of_matches (match_list, matches, text);
+ else /* There were no matches. */
+ {
+ free (match_list);
+ match_list = (char **)NULL;
+ }
+ return (match_list);
+}
+
+/* A completion function for usernames.
+ TEXT contains a partial username preceded by a random
+ character (usually `~'). */
+char *
+rl_username_completion_function (text, state)
+ const char *text;
+ int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT)
+ return (char *)NULL;
+#else /* !__WIN32__ && !__OPENNT) */
+ static char *username = (char *)NULL;
+ static struct passwd *entry;
+ static int namelen, first_char, first_char_loc;
+ char *value;
+
+ if (state == 0)
+ {
+ FREE (username);
+
+ first_char = *text;
+ first_char_loc = first_char == '~';
+
+ username = savestring (&text[first_char_loc]);
+ namelen = strlen (username);
+ setpwent ();
+ }
+
+ while ((entry = getpwent ()))
+ {
+ /* Null usernames should result in all users as possible completions. */
+ if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
+ break;
+ }
+
+ if (entry == 0)
+ {
+ endpwent ();
+ return ((char *)NULL);
+ }
+ else
+ {
+ value = (char *)xmalloc (2 + strlen (entry->pw_name));
+
+ *value = *text;
+
+ strcpy (value + first_char_loc, entry->pw_name);
+
+ if (first_char == '~')
+ rl_filename_completion_desired = 1;
+
+ return (value);
+ }
+#endif /* !__WIN32__ && !__OPENNT */
+}
+
+/* Okay, now we write the entry_function for filename completion. In the
+ general case. Note that completion in the shell is a little different
+ because of all the pathnames that must be followed when looking up the
+ completion for a command. */
+char *
+rl_filename_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static DIR *directory = (DIR *)NULL;
+ static char *filename = (char *)NULL;
+ static char *dirname = (char *)NULL;
+ static char *users_dirname = (char *)NULL;
+ static int filename_len;
+ char *temp;
+ int dirlen;
+ struct dirent *entry;
+
+ /* If we don't have any state, then do some initialization. */
+ if (state == 0)
+ {
+ /* If we were interrupted before closing the directory or reading
+ all of its contents, close it. */
+ if (directory)
+ {
+ closedir (directory);
+ directory = (DIR *)NULL;
+ }
+ FREE (dirname);
+ FREE (filename);
+ FREE (users_dirname);
+
+ filename = savestring (text);
+ if (*text == 0)
+ text = ".";
+ dirname = savestring (text);
+
+ temp = strrchr (dirname, '/');
+
+#if defined (__MSDOS__)
+ /* special hack for //X/... */
+ if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
+ temp = strrchr (dirname + 3, '/');
+#endif
+
+ if (temp)
+ {
+ strcpy (filename, ++temp);
+ *temp = '\0';
+ }
+#if defined (__MSDOS__)
+ /* searches from current directory on the drive */
+ else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':')
+ {
+ strcpy (filename, dirname + 2);
+ dirname[2] = '\0';
+ }
+#endif
+ else
+ {
+ dirname[0] = '.';
+ dirname[1] = '\0';
+ }
+
+ /* We aren't done yet. We also support the "~user" syntax. */
+
+ /* Save the version of the directory that the user typed. */
+ users_dirname = savestring (dirname);
+
+ if (*dirname == '~')
+ {
+ temp = tilde_expand (dirname);
+ free (dirname);
+ dirname = temp;
+ }
+
+ if (rl_directory_rewrite_hook)
+ (*rl_directory_rewrite_hook) (&dirname);
+
+ if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
+ {
+ free (users_dirname);
+ users_dirname = savestring (dirname);
+ }
+
+ directory = opendir (dirname);
+ filename_len = strlen (filename);
+
+ rl_filename_completion_desired = 1;
+ }
+
+ /* At this point we should entertain the possibility of hacking wildcarded
+ filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name
+ contains globbing characters, then build an array of directories, and
+ then map over that list while completing. */
+ /* *** UNIMPLEMENTED *** */
+
+ /* Now that we have some state, we can read the directory. */
+
+ entry = (struct dirent *)NULL;
+ while (directory && (entry = readdir (directory)))
+ {
+ /* Special case for no filename. If the user has disabled the
+ `match-hidden-files' variable, skip filenames beginning with `.'.
+ All other entries except "." and ".." match. */
+ if (filename_len == 0)
+ {
+ if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name))
+ continue;
+
+ if (entry->d_name[0] != '.' ||
+ (entry->d_name[1] &&
+ (entry->d_name[1] != '.' || entry->d_name[2])))
+ break;
+ }
+ else
+ {
+ /* Otherwise, if these match up to the length of filename, then
+ it is a match. */
+ if (_rl_completion_case_fold)
+ {
+ if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) &&
+ (((int)D_NAMLEN (entry)) >= filename_len) &&
+ (_rl_strnicmp (filename, entry->d_name, filename_len) == 0))
+ break;
+ }
+ else
+ {
+ if ((entry->d_name[0] == filename[0]) &&
+ (((int)D_NAMLEN (entry)) >= filename_len) &&
+ (strncmp (filename, entry->d_name, filename_len) == 0))
+ break;
+ }
+ }
+ }
+
+ if (entry == 0)
+ {
+ if (directory)
+ {
+ closedir (directory);
+ directory = (DIR *)NULL;
+ }
+ if (dirname)
+ {
+ free (dirname);
+ dirname = (char *)NULL;
+ }
+ if (filename)
+ {
+ free (filename);
+ filename = (char *)NULL;
+ }
+ if (users_dirname)
+ {
+ free (users_dirname);
+ users_dirname = (char *)NULL;
+ }
+
+ return (char *)NULL;
+ }
+ else
+ {
+ /* dirname && (strcmp (dirname, ".") != 0) */
+ if (dirname && (dirname[0] != '.' || dirname[1]))
+ {
+ if (rl_complete_with_tilde_expansion && *users_dirname == '~')
+ {
+ dirlen = strlen (dirname);
+ temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
+ strcpy (temp, dirname);
+ /* Canonicalization cuts off any final slash present. We
+ may need to add it back. */
+ if (dirname[dirlen - 1] != '/')
+ {
+ temp[dirlen++] = '/';
+ temp[dirlen] = '\0';
+ }
+ }
+ else
+ {
+ dirlen = strlen (users_dirname);
+ temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
+ strcpy (temp, users_dirname);
+ /* Make sure that temp has a trailing slash here. */
+ if (users_dirname[dirlen - 1] != '/')
+ temp[dirlen++] = '/';
+ }
+
+ strcpy (temp + dirlen, entry->d_name);
+ }
+ else
+ temp = savestring (entry->d_name);
+
+ return (temp);
+ }
+}
+
+/* An initial implementation of a menu completion function a la tcsh. The
+ first time (if the last readline command was not rl_menu_complete), we
+ generate the list of matches. This code is very similar to the code in
+ rl_complete_internal -- there should be a way to combine the two. Then,
+ for each item in the list of matches, we insert the match in an undoable
+ fashion, with the appropriate character appended (this happens on the
+ second and subsequent consecutive calls to rl_menu_complete). When we
+ hit the end of the match list, we restore the original unmatched text,
+ ring the bell, and reset the counter to zero. */
+int
+rl_menu_complete (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ rl_compentry_func_t *our_func;
+ int matching_filenames, found_quote;
+
+ static char *orig_text;
+ static char **matches = (char **)0;
+ static int match_list_index = 0;
+ static int match_list_size = 0;
+ static int orig_start, orig_end;
+ static char quote_char;
+ static int delimiter;
+
+ /* The first time through, we generate the list of matches and set things
+ up to insert them. */
+ if (rl_last_func != rl_menu_complete)
+ {
+ /* Clean up from previous call, if any. */
+ FREE (orig_text);
+ if (matches)
+ _rl_free_match_list (matches);
+
+ match_list_index = match_list_size = 0;
+ matches = (char **)NULL;
+
+ /* Only the completion entry function can change these. */
+ set_completion_defaults ('%');
+
+ our_func = rl_completion_entry_function
+ ? rl_completion_entry_function
+ : rl_filename_completion_function;
+
+ /* We now look backwards for the start of a filename/variable word. */
+ orig_end = rl_point;
+ found_quote = delimiter = 0;
+ quote_char = '\0';
+
+ if (rl_point)
+ /* This (possibly) changes rl_point. If it returns a non-zero char,
+ we know we have an open quote. */
+ quote_char = _rl_find_completion_word (&found_quote, &delimiter);
+
+ orig_start = rl_point;
+ rl_point = orig_end;
+
+ orig_text = rl_copy_text (orig_start, orig_end);
+ matches = gen_completion_matches (orig_text, orig_start, orig_end,
+ our_func, found_quote, quote_char);
+
+ /* If we are matching filenames, the attempted completion function will
+ have set rl_filename_completion_desired to a non-zero value. The basic
+ rl_filename_completion_function does this. */
+ matching_filenames = rl_filename_completion_desired;
+
+ if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
+ {
+ rl_ding ();
+ FREE (matches);
+ matches = (char **)0;
+ FREE (orig_text);
+ orig_text = (char *)0;
+ completion_changed_buffer = 0;
+ return (0);
+ }
+
+ for (match_list_size = 0; matches[match_list_size]; match_list_size++)
+ ;
+ /* matches[0] is lcd if match_list_size > 1, but the circular buffer
+ code below should take care of it. */
+ }
+
+ /* Now we have the list of matches. Replace the text between
+ rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
+ matches[match_list_index], and add any necessary closing char. */
+
+ if (matches == 0 || match_list_size == 0)
+ {
+ rl_ding ();
+ FREE (matches);
+ matches = (char **)0;
+ completion_changed_buffer = 0;
+ return (0);
+ }
+
+ match_list_index = (match_list_index + count) % match_list_size;
+ if (match_list_index < 0)
+ match_list_index += match_list_size;
+
+ if (match_list_index == 0 && match_list_size > 1)
+ {
+ rl_ding ();
+ insert_match (orig_text, orig_start, MULT_MATCH, &quote_char);
+ }
+ else
+ {
+ insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
+ append_to_match (matches[match_list_index], delimiter, quote_char,
+ strcmp (orig_text, matches[match_list_index]));
+ }
+
+ completion_changed_buffer = 1;
+ return (0);
+}
diff --git a/cmd-line-utils/readline/configure.in b/cmd-line-utils/readline/configure.in
new file mode 100644
index 00000000000..bc78f8a0f60
--- /dev/null
+++ b/cmd-line-utils/readline/configure.in
@@ -0,0 +1,206 @@
+dnl
+dnl Configure script for readline library
+dnl
+dnl report bugs to chet@po.cwru.edu
+dnl
+dnl Process this file with autoconf to produce a configure script.
+AC_REVISION([for Readline 4.3, version 2.45, from autoconf version] AC_ACVERSION)
+
+AC_INIT(readline, 4.3, bug-readline@gnu.org)
+
+dnl make sure we are using a recent autoconf version
+AC_PREREQ(2.50)
+
+AC_CONFIG_SRCDIR(readline.h)
+AC_CONFIG_AUX_DIR(./support)
+AC_CONFIG_HEADERS(config.h)
+
+dnl update the value of RL_READLINE_VERSION in readline.h when this changes
+LIBVERSION=4.3
+
+AC_CANONICAL_HOST
+
+dnl configure defaults
+opt_curses=no
+
+dnl arguments to configure
+AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval)
+
+if test "$opt_curses" = "yes"; then
+ prefer_curses=yes
+fi
+
+dnl option parsing for optional features
+opt_static_libs=yes
+opt_shared_libs=yes
+
+AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared], [build shared libraries [[default=YES]]]), opt_shared_libs=$enableval)
+AC_ARG_ENABLE(static, AC_HELP_STRING([--enable-static], [build static libraries [[default=YES]]]), opt_static_libs=$enableval)
+
+echo ""
+echo "Beginning configuration for readline-$LIBVERSION for ${host_cpu}-${host_vendor}-${host_os}"
+echo ""
+
+# We want these before the checks, so the checks can modify their values.
+test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1
+
+AC_PROG_MAKE_SET
+AC_PROG_CC
+dnl AC_AIX
+AC_MINIX
+
+# If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS.
+test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O"
+
+AC_PROG_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_CHECK_PROG(AR, ar, , ar)
+dnl Set default for ARFLAGS, since autoconf does not have a macro for it.
+dnl This allows people to set it when running configure or make
+test -n "$ARFLAGS" || ARFLAGS="cr"
+AC_PROG_RANLIB
+
+MAKE_SHELL=/bin/sh
+AC_SUBST(MAKE_SHELL)
+
+AC_C_CONST
+AC_C_PROTOTYPES
+AC_C_CHAR_UNSIGNED
+
+AC_TYPE_SIGNAL
+
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(ssize_t, int)
+
+AC_HEADER_STAT
+AC_HEADER_DIRENT
+
+AC_CHECK_FUNCS(lstat memmove putenv select setenv setlocale \
+ strcasecmp strpbrk tcgetattr vsnprintf isascii isxdigit)
+
+AC_FUNC_STRCOLL
+
+AC_CHECK_HEADERS(unistd.h stdlib.h varargs.h stdarg.h string.h strings.h \
+ limits.h sys/ptem.h sys/pte.h sys/stream.h sys/select.h \
+ termcap.h termios.h termio.h sys/file.h locale.h memory.h )
+
+BASH_SYS_SIGNAL_VINTAGE
+BASH_SYS_REINSTALL_SIGHANDLERS
+
+BASH_FUNC_POSIX_SETJMP
+BASH_FUNC_LSTAT
+BASH_FUNC_STRCOLL
+
+BASH_CHECK_GETPW_FUNCS
+
+AC_HEADER_TIOCGWINSZ
+
+BASH_TYPE_SIGHANDLER
+BASH_HAVE_TIOCSTAT
+BASH_HAVE_FIONREAD
+BASH_CHECK_SPEED_T
+BASH_STRUCT_WINSIZE
+BASH_STRUCT_DIRENT_D_INO
+BASH_STRUCT_DIRENT_D_FILENO
+
+dnl yuck
+case "$host_os" in
+aix*) prefer_curses=yes ;;
+esac
+BASH_CHECK_LIB_TERMCAP
+if test "$TERMCAP_LIB" = "./lib/termcap/libtermcap.a"; then
+ if test "$prefer_curses" = yes; then
+ TERMCAP_LIB=-lcurses
+ else
+ TERMCAP_LIB=-ltermcap #default
+ fi
+fi
+
+BASH_CHECK_MULTIBYTE
+
+case "$host_cpu" in
+*cray*) LOCAL_CFLAGS=-DCRAY ;;
+*s390*) LOCAL_CFLAGS=-fsigned-char ;;
+esac
+
+case "$host_os" in
+isc*) LOCAL_CFLAGS=-Disc386 ;;
+esac
+
+# shared library configuration section
+#
+# Shared object configuration section. These values are generated by
+# ${srcdir}/support/shobj-conf
+#
+if test -f ${srcdir}/support/shobj-conf; then
+ AC_MSG_CHECKING(configuration for building shared libraries)
+ eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c ${host_cpu} -o ${host_os} -v ${host_vendor}`
+ AC_SUBST(SHOBJ_CC)
+ AC_SUBST(SHOBJ_CFLAGS)
+ AC_SUBST(SHOBJ_LD)
+ AC_SUBST(SHOBJ_LDFLAGS)
+ AC_SUBST(SHOBJ_XLDFLAGS)
+ AC_SUBST(SHOBJ_LIBS)
+ AC_SUBST(SHOBJ_STATUS)
+ AC_SUBST(SHLIB_STATUS)
+ AC_SUBST(SHLIB_XLDFLAGS)
+ AC_SUBST(SHLIB_LIBSUFF)
+ AC_SUBST(SHLIB_LIBVERSION)
+ AC_SUBST(SHLIB_LIBS)
+ AC_MSG_RESULT($SHLIB_STATUS)
+
+ # SHLIB_STATUS is either `supported' or `unsupported'. If it's
+ # `unsupported', turn off any default shared library building
+ if test "$SHLIB_STATUS" = 'unsupported'; then
+ opt_shared_libs=no
+ fi
+
+ # shared library versioning
+ # quoted for m4 so I can use character classes
+ SHLIB_MAJOR=[`expr "$LIBVERSION" : '\([0-9]\)\..*'`]
+ SHLIB_MINOR=[`expr "$LIBVERSION" : '[0-9]\.\([0-9]\).*'`]
+ AC_SUBST(SHLIB_MAJOR)
+ AC_SUBST(SHLIB_MINOR)
+fi
+
+if test "$opt_static_libs" = "yes"; then
+ STATIC_TARGET=static
+ STATIC_INSTALL_TARGET=install-static
+fi
+if test "$opt_shared_libs" = "yes"; then
+ SHARED_TARGET=shared
+ SHARED_INSTALL_TARGET=install-shared
+fi
+
+AC_SUBST(STATIC_TARGET)
+AC_SUBST(SHARED_TARGET)
+AC_SUBST(STATIC_INSTALL_TARGET)
+AC_SUBST(SHARED_INSTALL_TARGET)
+
+case "$host_os" in
+msdosdjgpp*) BUILD_DIR=`pwd.exe` ;; # to prevent //d/path/file
+*) BUILD_DIR=`pwd` ;;
+esac
+
+AC_SUBST(BUILD_DIR)
+
+AC_SUBST(CFLAGS)
+AC_SUBST(LOCAL_CFLAGS)
+AC_SUBST(LOCAL_LDFLAGS)
+AC_SUBST(LOCAL_DEFS)
+
+AC_SUBST(AR)
+AC_SUBST(ARFLAGS)
+
+AC_SUBST(host_cpu)
+AC_SUBST(host_os)
+
+AC_SUBST(LIBVERSION)
+
+AC_SUBST(TERMCAP_LIB)
+
+AC_OUTPUT([Makefile doc/Makefile examples/Makefile shlib/Makefile],
+[
+# Makefile uses this timestamp file to record whether config.h is up to date.
+echo > stamp-h
+])
diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c
new file mode 100644
index 00000000000..f393e7e8516
--- /dev/null
+++ b/cmd-line-utils/readline/display.c
@@ -0,0 +1,2198 @@
+/* display.c -- readline redisplay facility. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "posixstat.h"
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+/* Termcap library stuff. */
+#include "tcap.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+#if defined (HACK_TERMCAP_MOTION)
+extern char *_rl_term_forward_char;
+#endif
+
+static void update_line PARAMS((char *, char *, int, int, int, int));
+static void space_to_eol PARAMS((int));
+static void delete_chars PARAMS((int));
+static void insert_some_chars PARAMS((char *, int, int));
+static void cr PARAMS((void));
+
+#if defined (HANDLE_MULTIBYTE)
+static int _rl_col_width PARAMS((const char *, int, int));
+static int *_rl_wrapped_line;
+#else
+# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s))
+#endif
+
+static int *inv_lbreaks, *vis_lbreaks;
+static int inv_lbsize, vis_lbsize;
+
+/* Heuristic used to decide whether it is faster to move from CUR to NEW
+ by backing up or outputting a carriage return and moving forward. */
+#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
+
+/* **************************************************************** */
+/* */
+/* Display stuff */
+/* */
+/* **************************************************************** */
+
+/* This is the stuff that is hard for me. I never seem to write good
+ display routines in C. Let's see how I do this time. */
+
+/* (PWP) Well... Good for a simple line updater, but totally ignores
+ the problems of input lines longer than the screen width.
+
+ update_line and the code that calls it makes a multiple line,
+ automatically wrapping line update. Careful attention needs
+ to be paid to the vertical position variables. */
+
+/* Keep two buffers; one which reflects the current contents of the
+ screen, and the other to draw what we think the new contents should
+ be. Then compare the buffers, and make whatever changes to the
+ screen itself that we should. Finally, make the buffer that we
+ just drew into be the one which reflects the current contents of the
+ screen, and place the cursor where it belongs.
+
+ Commands that want to can fix the display themselves, and then let
+ this function know that the display has been fixed by setting the
+ RL_DISPLAY_FIXED variable. This is good for efficiency. */
+
+/* Application-specific redisplay function. */
+rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
+
+/* Global variables declared here. */
+/* What YOU turn on when you have handled all redisplay yourself. */
+int rl_display_fixed = 0;
+
+int _rl_suppress_redisplay = 0;
+
+/* The stuff that gets printed out before the actual text of the line.
+ This is usually pointing to rl_prompt. */
+const char *rl_display_prompt = (char *)NULL;
+
+/* Pseudo-global variables declared here. */
+/* The visible cursor position. If you print some text, adjust this. */
+int _rl_last_c_pos = 0;
+int _rl_last_v_pos = 0;
+
+/* Number of lines currently on screen minus 1. */
+int _rl_vis_botlin = 0;
+
+/* Variables used only in this file. */
+/* The last left edge of text that was displayed. This is used when
+ doing horizontal scrolling. It shifts in thirds of a screenwidth. */
+static int last_lmargin;
+
+/* The line display buffers. One is the line currently displayed on
+ the screen. The other is the line about to be displayed. */
+static char *visible_line = (char *)NULL;
+static char *invisible_line = (char *)NULL;
+
+/* A buffer for `modeline' messages. */
+static char msg_buf[128];
+
+/* Non-zero forces the redisplay even if we thought it was unnecessary. */
+static int forced_display;
+
+/* Default and initial buffer size. Can grow. */
+static int line_size = 1024;
+
+/* Variables to keep track of the expanded prompt string, which may
+ include invisible characters. */
+
+static char *local_prompt, *local_prompt_prefix;
+static int prompt_visible_length, prompt_prefix_length;
+
+/* The number of invisible characters in the line currently being
+ displayed on the screen. */
+static int visible_wrap_offset;
+
+/* The number of invisible characters in the prompt string. Static so it
+ can be shared between rl_redisplay and update_line */
+static int wrap_offset;
+
+/* The index of the last invisible character in the prompt string. */
+static int prompt_last_invisible;
+
+/* The length (buffer offset) of the first line of the last (possibly
+ multi-line) buffer displayed on the screen. */
+static int visible_first_line_len;
+
+/* Number of invisible characters on the first physical line of the prompt.
+ Only valid when the number of physical characters in the prompt exceeds
+ (or is equal to) _rl_screenwidth. */
+static int prompt_invis_chars_first_line;
+
+static int prompt_last_screen_line;
+
+/* Expand the prompt string S and return the number of visible
+ characters in *LP, if LP is not null. This is currently more-or-less
+ a placeholder for expansion. LIP, if non-null is a place to store the
+ index of the last invisible character in the returned string. NIFLP,
+ if non-zero, is a place to store the number of invisible characters in
+ the first prompt line. */
+
+/* Current implementation:
+ \001 (^A) start non-visible characters
+ \002 (^B) end non-visible characters
+ all characters except \001 and \002 (following a \001) are copied to
+ the returned string; all characters except those between \001 and
+ \002 are assumed to be `visible'. */
+
+static char *
+expand_prompt (pmt, lp, lip, niflp)
+ char *pmt;
+ int *lp, *lip, *niflp;
+{
+ char *r, *ret, *p;
+ int l, rl, last, ignoring, ninvis, invfl;
+
+ /* Short-circuit if we can. */
+ if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
+ {
+ r = savestring (pmt);
+ if (lp)
+ *lp = strlen (r);
+ return r;
+ }
+
+ l = strlen (pmt);
+ r = ret = (char *)xmalloc (l + 1);
+
+ invfl = 0; /* invisible chars in first line of prompt */
+
+ for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
+ {
+ /* This code strips the invisible character string markers
+ RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
+ if (*p == RL_PROMPT_START_IGNORE)
+ {
+ ignoring++;
+ continue;
+ }
+ else if (ignoring && *p == RL_PROMPT_END_IGNORE)
+ {
+ ignoring = 0;
+ last = r - ret - 1;
+ continue;
+ }
+ else
+ {
+ *r++ = *p;
+ if (!ignoring)
+ rl++;
+ else
+ ninvis++;
+ if (rl == _rl_screenwidth)
+ invfl = ninvis;
+ }
+ }
+
+ if (rl < _rl_screenwidth)
+ invfl = ninvis;
+
+ *r = '\0';
+ if (lp)
+ *lp = rl;
+ if (lip)
+ *lip = last;
+ if (niflp)
+ *niflp = invfl;
+ return ret;
+}
+
+/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
+ PMT and return the rest of PMT. */
+char *
+_rl_strip_prompt (pmt)
+ char *pmt;
+{
+ char *ret;
+
+ ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL);
+ return ret;
+}
+
+/*
+ * Expand the prompt string into the various display components, if
+ * necessary.
+ *
+ * local_prompt = expanded last line of string in rl_display_prompt
+ * (portion after the final newline)
+ * local_prompt_prefix = portion before last newline of rl_display_prompt,
+ * expanded via expand_prompt
+ * prompt_visible_length = number of visible characters in local_prompt
+ * prompt_prefix_length = number of visible characters in local_prompt_prefix
+ *
+ * This function is called once per call to readline(). It may also be
+ * called arbitrarily to expand the primary prompt.
+ *
+ * The return value is the number of visible characters on the last line
+ * of the (possibly multi-line) prompt.
+ */
+int
+rl_expand_prompt (prompt)
+ char *prompt;
+{
+ char *p, *t;
+ int c;
+
+ /* Clear out any saved values. */
+ FREE (local_prompt);
+ FREE (local_prompt_prefix);
+
+ local_prompt = local_prompt_prefix = (char *)0;
+ prompt_last_invisible = prompt_visible_length = 0;
+
+ if (prompt == 0 || *prompt == 0)
+ return (0);
+
+ p = strrchr (prompt, '\n');
+ if (!p)
+ {
+ /* The prompt is only one logical line, though it might wrap. */
+ local_prompt = expand_prompt (prompt, &prompt_visible_length,
+ &prompt_last_invisible,
+ &prompt_invis_chars_first_line);
+ local_prompt_prefix = (char *)0;
+ return (prompt_visible_length);
+ }
+ else
+ {
+ /* The prompt spans multiple lines. */
+ t = ++p;
+ local_prompt = expand_prompt (p, &prompt_visible_length,
+ &prompt_last_invisible,
+ &prompt_invis_chars_first_line);
+ c = *t; *t = '\0';
+ /* The portion of the prompt string up to and including the
+ final newline is now null-terminated. */
+ local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
+ (int *)NULL,
+ &prompt_invis_chars_first_line);
+ *t = c;
+ return (prompt_prefix_length);
+ }
+}
+
+/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
+ arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
+ and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
+ increased. If the lines have already been allocated, this ensures that
+ they can hold at least MINSIZE characters. */
+static void
+init_line_structures (minsize)
+ int minsize;
+{
+ register int n;
+
+ if (invisible_line == 0) /* initialize it */
+ {
+ if (line_size < minsize)
+ line_size = minsize;
+ visible_line = (char *)xmalloc (line_size);
+ invisible_line = (char *)xmalloc (line_size);
+ }
+ else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
+ {
+ line_size *= 2;
+ if (line_size < minsize)
+ line_size = minsize;
+ visible_line = (char *)xrealloc (visible_line, line_size);
+ invisible_line = (char *)xrealloc (invisible_line, line_size);
+ }
+
+ for (n = minsize; n < line_size; n++)
+ {
+ visible_line[n] = 0;
+ invisible_line[n] = 1;
+ }
+
+ if (vis_lbreaks == 0)
+ {
+ /* should be enough. */
+ inv_lbsize = vis_lbsize = 256;
+ inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
+ vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
+#if defined (HANDLE_MULTIBYTE)
+ _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
+#endif
+ inv_lbreaks[0] = vis_lbreaks[0] = 0;
+ }
+}
+
+/* Basic redisplay algorithm. */
+void
+rl_redisplay ()
+{
+ register int in, out, c, linenum, cursor_linenum;
+ register char *line;
+ int c_pos, inv_botlin, lb_botlin, lb_linenum;
+ int newlines, lpos, temp;
+ const char *prompt_this_line;
+#if defined (HANDLE_MULTIBYTE)
+ wchar_t wc;
+ size_t wc_bytes;
+ int wc_width;
+ mbstate_t ps;
+ int _rl_wrapped_multicolumn = 0;
+#endif
+
+ if (!readline_echoing_p)
+ return;
+
+ if (!rl_display_prompt)
+ rl_display_prompt = "";
+
+ if (invisible_line == 0)
+ {
+ init_line_structures (0);
+ rl_on_new_line ();
+ }
+
+ /* Draw the line into the buffer. */
+ c_pos = -1;
+
+ line = invisible_line;
+ out = inv_botlin = 0;
+
+ /* Mark the line as modified or not. We only do this for history
+ lines. */
+ if (_rl_mark_modified_lines && current_history () && rl_undo_list)
+ {
+ line[out++] = '*';
+ line[out] = '\0';
+ }
+
+ /* If someone thought that the redisplay was handled, but the currently
+ visible line has a different modification state than the one about
+ to become visible, then correct the caller's misconception. */
+ if (visible_line[0] != invisible_line[0])
+ rl_display_fixed = 0;
+
+ /* If the prompt to be displayed is the `primary' readline prompt (the
+ one passed to readline()), use the values we have already expanded.
+ If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
+ number of non-visible characters in the prompt string. */
+ if (rl_display_prompt == rl_prompt || local_prompt)
+ {
+ int local_len = local_prompt ? strlen (local_prompt) : 0;
+ if (local_prompt_prefix && forced_display)
+ _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
+
+ if (local_len > 0)
+ {
+ temp = local_len + out + 2;
+ if (temp >= line_size)
+ {
+ line_size = (temp + 1024) - (temp % 1024);
+ visible_line = (char *)xrealloc (visible_line, line_size);
+ line = invisible_line = (char *)xrealloc (invisible_line, line_size);
+ }
+ strncpy (line + out, local_prompt, local_len);
+ out += local_len;
+ }
+ line[out] = '\0';
+ wrap_offset = local_len - prompt_visible_length;
+ }
+ else
+ {
+ int pmtlen;
+ prompt_this_line = strrchr (rl_display_prompt, '\n');
+ if (!prompt_this_line)
+ prompt_this_line = rl_display_prompt;
+ else
+ {
+ prompt_this_line++;
+ pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
+ if (forced_display)
+ {
+ _rl_output_some_chars (rl_display_prompt, pmtlen);
+ /* Make sure we are at column zero even after a newline,
+ regardless of the state of terminal output processing. */
+ if (pmtlen < 2 || prompt_this_line[-2] != '\r')
+ cr ();
+ }
+ }
+
+ pmtlen = strlen (prompt_this_line);
+ temp = pmtlen + out + 2;
+ if (temp >= line_size)
+ {
+ line_size = (temp + 1024) - (temp % 1024);
+ visible_line = (char *)xrealloc (visible_line, line_size);
+ line = invisible_line = (char *)xrealloc (invisible_line, line_size);
+ }
+ strncpy (line + out, prompt_this_line, pmtlen);
+ out += pmtlen;
+ line[out] = '\0';
+ wrap_offset = prompt_invis_chars_first_line = 0;
+ }
+
+#define CHECK_INV_LBREAKS() \
+ do { \
+ if (newlines >= (inv_lbsize - 2)) \
+ { \
+ inv_lbsize *= 2; \
+ inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+ } \
+ } while (0)
+
+#if defined (HANDLE_MULTIBYTE)
+#define CHECK_LPOS() \
+ do { \
+ lpos++; \
+ if (lpos >= _rl_screenwidth) \
+ { \
+ if (newlines >= (inv_lbsize - 2)) \
+ { \
+ inv_lbsize *= 2; \
+ inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+ _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
+ } \
+ inv_lbreaks[++newlines] = out; \
+ _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
+ lpos = 0; \
+ } \
+ } while (0)
+#else
+#define CHECK_LPOS() \
+ do { \
+ lpos++; \
+ if (lpos >= _rl_screenwidth) \
+ { \
+ if (newlines >= (inv_lbsize - 2)) \
+ { \
+ inv_lbsize *= 2; \
+ inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+ } \
+ inv_lbreaks[++newlines] = out; \
+ lpos = 0; \
+ } \
+ } while (0)
+#endif
+
+ /* inv_lbreaks[i] is where line i starts in the buffer. */
+ inv_lbreaks[newlines = 0] = 0;
+ lpos = out - wrap_offset;
+#if defined (HANDLE_MULTIBYTE)
+ memset (_rl_wrapped_line, 0, vis_lbsize);
+#endif
+
+ /* prompt_invis_chars_first_line is the number of invisible characters in
+ the first physical line of the prompt.
+ wrap_offset - prompt_invis_chars_first_line is the number of invis
+ chars on the second line. */
+
+ /* what if lpos is already >= _rl_screenwidth before we start drawing the
+ contents of the command line? */
+ while (lpos >= _rl_screenwidth)
+ {
+ /* fix from Darin Johnson <darin@acuson.com> for prompt string with
+ invisible characters that is longer than the screen width. The
+ prompt_invis_chars_first_line variable could be made into an array
+ saying how many invisible characters there are per line, but that's
+ probably too much work for the benefit gained. How many people have
+ prompts that exceed two physical lines? */
+ temp = ((newlines + 1) * _rl_screenwidth) +
+#if 0
+ ((newlines == 0) ? prompt_invis_chars_first_line : 0) +
+#else
+ ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) +
+#endif
+ ((newlines == 1) ? wrap_offset : 0);
+
+ inv_lbreaks[++newlines] = temp;
+ lpos -= _rl_screenwidth;
+ }
+
+ prompt_last_screen_line = newlines;
+
+ /* Draw the rest of the line (after the prompt) into invisible_line, keeping
+ track of where the cursor is (c_pos), the number of the line containing
+ the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
+ It maintains an array of line breaks for display (inv_lbreaks).
+ This handles expanding tabs for display and displaying meta characters. */
+ lb_linenum = 0;
+#if defined (HANDLE_MULTIBYTE)
+ in = 0;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ memset (&ps, 0, sizeof (mbstate_t));
+ wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
+ }
+ else
+ wc_bytes = 1;
+ while (in < rl_end)
+#else
+ for (in = 0; in < rl_end; in++)
+#endif
+ {
+ c = (unsigned char)rl_line_buffer[in];
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
+ {
+ /* Byte sequence is invalid or shortened. Assume that the
+ first byte represents a character. */
+ wc_bytes = 1;
+ /* Assume that a character occupies a single column. */
+ wc_width = 1;
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (wc_bytes == (size_t)0)
+ break; /* Found '\0' */
+ else
+ {
+ temp = wcwidth (wc);
+ wc_width = (temp < 0) ? 1 : temp;
+ }
+ }
+#endif
+
+ if (out + 8 >= line_size) /* XXX - 8 for \t */
+ {
+ line_size *= 2;
+ visible_line = (char *)xrealloc (visible_line, line_size);
+ invisible_line = (char *)xrealloc (invisible_line, line_size);
+ line = invisible_line;
+ }
+
+ if (in == rl_point)
+ {
+ c_pos = out;
+ lb_linenum = newlines;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
+#else
+ if (META_CHAR (c))
+#endif
+ {
+ if (_rl_output_meta_chars == 0)
+ {
+ sprintf (line + out, "\\%o", c);
+
+ if (lpos + 4 >= _rl_screenwidth)
+ {
+ temp = _rl_screenwidth - lpos;
+ CHECK_INV_LBREAKS ();
+ inv_lbreaks[++newlines] = out + temp;
+ lpos = 4 - temp;
+ }
+ else
+ lpos += 4;
+
+ out += 4;
+ }
+ else
+ {
+ line[out++] = c;
+ CHECK_LPOS();
+ }
+ }
+#if defined (DISPLAY_TABS)
+ else if (c == '\t')
+ {
+ register int newout;
+
+#if 0
+ newout = (out | (int)7) + 1;
+#else
+ newout = out + 8 - lpos % 8;
+#endif
+ temp = newout - out;
+ if (lpos + temp >= _rl_screenwidth)
+ {
+ register int temp2;
+ temp2 = _rl_screenwidth - lpos;
+ CHECK_INV_LBREAKS ();
+ inv_lbreaks[++newlines] = out + temp2;
+ lpos = temp - temp2;
+ while (out < newout)
+ line[out++] = ' ';
+ }
+ else
+ {
+ while (out < newout)
+ line[out++] = ' ';
+ lpos += temp;
+ }
+ }
+#endif
+ else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
+ {
+ line[out++] = '\0'; /* XXX - sentinel */
+ CHECK_INV_LBREAKS ();
+ inv_lbreaks[++newlines] = out;
+ lpos = 0;
+ }
+ else if (CTRL_CHAR (c) || c == RUBOUT)
+ {
+ line[out++] = '^';
+ CHECK_LPOS();
+ line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
+ CHECK_LPOS();
+ }
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ register int i;
+
+ _rl_wrapped_multicolumn = 0;
+
+ if (_rl_screenwidth < lpos + wc_width)
+ for (i = lpos; i < _rl_screenwidth; i++)
+ {
+ /* The space will be removed in update_line() */
+ line[out++] = ' ';
+ _rl_wrapped_multicolumn++;
+ CHECK_LPOS();
+ }
+ if (in == rl_point)
+ {
+ c_pos = out;
+ lb_linenum = newlines;
+ }
+ for (i = in; i < in+wc_bytes; i++)
+ line[out++] = rl_line_buffer[i];
+ for (i = 0; i < wc_width; i++)
+ CHECK_LPOS();
+ }
+ else
+ {
+ line[out++] = c;
+ CHECK_LPOS();
+ }
+#else
+ line[out++] = c;
+ CHECK_LPOS();
+#endif
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ in += wc_bytes;
+ wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
+ }
+ else
+ in++;
+#endif
+
+ }
+ line[out] = '\0';
+ if (c_pos < 0)
+ {
+ c_pos = out;
+ lb_linenum = newlines;
+ }
+
+ inv_botlin = lb_botlin = newlines;
+ CHECK_INV_LBREAKS ();
+ inv_lbreaks[newlines+1] = out;
+ cursor_linenum = lb_linenum;
+
+ /* C_POS == position in buffer where cursor should be placed.
+ CURSOR_LINENUM == line number where the cursor should be placed. */
+
+ /* PWP: now is when things get a bit hairy. The visible and invisible
+ line buffers are really multiple lines, which would wrap every
+ (screenwidth - 1) characters. Go through each in turn, finding
+ the changed region and updating it. The line order is top to bottom. */
+
+ /* If we can move the cursor up and down, then use multiple lines,
+ otherwise, let long lines display in a single terminal line, and
+ horizontally scroll it. */
+
+ if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
+ {
+ int nleft, pos, changed_screen_line;
+
+ if (!rl_display_fixed || forced_display)
+ {
+ forced_display = 0;
+
+ /* If we have more than a screenful of material to display, then
+ only display a screenful. We should display the last screen,
+ not the first. */
+ if (out >= _rl_screenchars)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
+ else
+ out = _rl_screenchars - 1;
+ }
+
+ /* The first line is at character position 0 in the buffer. The
+ second and subsequent lines start at inv_lbreaks[N], offset by
+ OFFSET (which has already been calculated above). */
+
+#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
+#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
+#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
+#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
+#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? (char*)"" : VIS_CHARS(line)
+#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
+
+ /* For each line in the buffer, do the updating display. */
+ for (linenum = 0; linenum <= inv_botlin; linenum++)
+ {
+ update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
+ VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
+
+ /* If this is the line with the prompt, we might need to
+ compensate for invisible characters in the new line. Do
+ this only if there is not more than one new line (which
+ implies that we completely overwrite the old visible line)
+ and the new line is shorter than the old. Make sure we are
+ at the end of the new line before clearing. */
+ if (linenum == 0 &&
+ inv_botlin == 0 && _rl_last_c_pos == out &&
+ (wrap_offset > visible_wrap_offset) &&
+ (_rl_last_c_pos < visible_first_line_len))
+ {
+ nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
+ if (nleft)
+ _rl_clear_to_eol (nleft);
+ }
+
+ /* Since the new first line is now visible, save its length. */
+ if (linenum == 0)
+ visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
+ }
+
+ /* We may have deleted some lines. If so, clear the left over
+ blank ones at the bottom out. */
+ if (_rl_vis_botlin > inv_botlin)
+ {
+ char *tt;
+ for (; linenum <= _rl_vis_botlin; linenum++)
+ {
+ tt = VIS_CHARS (linenum);
+ _rl_move_vert (linenum);
+ _rl_move_cursor_relative (0, tt);
+ _rl_clear_to_eol
+ ((linenum == _rl_vis_botlin) ? (int)strlen (tt) : _rl_screenwidth);
+ }
+ }
+ _rl_vis_botlin = inv_botlin;
+
+ /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
+ different screen line during this redisplay. */
+ changed_screen_line = _rl_last_v_pos != cursor_linenum;
+ if (changed_screen_line)
+ {
+ _rl_move_vert (cursor_linenum);
+ /* If we moved up to the line with the prompt using _rl_term_up,
+ the physical cursor position on the screen stays the same,
+ but the buffer position needs to be adjusted to account
+ for invisible characters. */
+ if (cursor_linenum == 0 && wrap_offset)
+ _rl_last_c_pos += wrap_offset;
+ }
+
+ /* We have to reprint the prompt if it contains invisible
+ characters, since it's not generally OK to just reprint
+ the characters from the current cursor position. But we
+ only need to reprint it if the cursor is before the last
+ invisible character in the prompt string. */
+ nleft = prompt_visible_length + wrap_offset;
+ if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
+ _rl_last_c_pos <= prompt_last_invisible && local_prompt)
+ {
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ if (_rl_term_cr)
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif
+ _rl_output_some_chars (local_prompt, nleft);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft);
+ else
+ _rl_last_c_pos = nleft;
+ }
+
+ /* Where on that line? And where does that line start
+ in the buffer? */
+ pos = inv_lbreaks[cursor_linenum];
+ /* nleft == number of characters in the line buffer between the
+ start of the line and the cursor position. */
+ nleft = c_pos - pos;
+
+ /* Since _rl_backspace() doesn't know about invisible characters in the
+ prompt, and there's no good way to tell it, we compensate for
+ those characters here and call _rl_backspace() directly. */
+ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
+ {
+ _rl_backspace (_rl_last_c_pos - nleft);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft);
+ else
+ _rl_last_c_pos = nleft;
+ }
+
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+ else if (nleft != _rl_last_c_pos)
+ _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+ }
+ }
+ else /* Do horizontal scrolling. */
+ {
+#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
+ int lmargin, ndisp, nleft, phys_c_pos, t;
+
+ /* Always at top line. */
+ _rl_last_v_pos = 0;
+
+ /* Compute where in the buffer the displayed line should start. This
+ will be LMARGIN. */
+
+ /* The number of characters that will be displayed before the cursor. */
+ ndisp = c_pos - wrap_offset;
+ nleft = prompt_visible_length + wrap_offset;
+ /* Where the new cursor position will be on the screen. This can be
+ longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
+ phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
+ t = _rl_screenwidth / 3;
+
+ /* If the number of characters had already exceeded the screenwidth,
+ last_lmargin will be > 0. */
+
+ /* If the number of characters to be displayed is more than the screen
+ width, compute the starting offset so that the cursor is about
+ two-thirds of the way across the screen. */
+ if (phys_c_pos > _rl_screenwidth - 2)
+ {
+ lmargin = c_pos - (2 * t);
+ if (lmargin < 0)
+ lmargin = 0;
+ /* If the left margin would be in the middle of a prompt with
+ invisible characters, don't display the prompt at all. */
+ if (wrap_offset && lmargin > 0 && lmargin < nleft)
+ lmargin = nleft;
+ }
+ else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
+ lmargin = 0;
+ else if (phys_c_pos < 1)
+ {
+ /* If we are moving back towards the beginning of the line and
+ the last margin is no longer correct, compute a new one. */
+ lmargin = ((c_pos - 1) / t) * t; /* XXX */
+ if (wrap_offset && lmargin > 0 && lmargin < nleft)
+ lmargin = nleft;
+ }
+ else
+ lmargin = last_lmargin;
+
+ /* If the first character on the screen isn't the first character
+ in the display line, indicate this with a special character. */
+ if (lmargin > 0)
+ line[lmargin] = '<';
+
+ /* If SCREENWIDTH characters starting at LMARGIN do not encompass
+ the whole line, indicate that with a special character at the
+ right edge of the screen. If LMARGIN is 0, we need to take the
+ wrap offset into account. */
+ t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
+ if (t < out)
+ line[t - 1] = '>';
+
+ if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
+ {
+ forced_display = 0;
+ update_line (&visible_line[last_lmargin],
+ &invisible_line[lmargin],
+ 0,
+ _rl_screenwidth + visible_wrap_offset,
+ _rl_screenwidth + (lmargin ? 0 : wrap_offset),
+ 0);
+
+ /* If the visible new line is shorter than the old, but the number
+ of invisible characters is greater, and we are at the end of
+ the new line, we need to clear to eol. */
+ t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
+ if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
+ (_rl_last_c_pos == out) &&
+ t < visible_first_line_len)
+ {
+ nleft = _rl_screenwidth - t;
+ _rl_clear_to_eol (nleft);
+ }
+ visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
+ if (visible_first_line_len > _rl_screenwidth)
+ visible_first_line_len = _rl_screenwidth;
+
+ _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
+ last_lmargin = lmargin;
+ }
+ }
+ fflush (rl_outstream);
+
+ /* Swap visible and non-visible lines. */
+ {
+ char *vtemp = visible_line;
+ int *itemp = vis_lbreaks, ntemp = vis_lbsize;
+
+ visible_line = invisible_line;
+ invisible_line = vtemp;
+
+ vis_lbreaks = inv_lbreaks;
+ inv_lbreaks = itemp;
+
+ vis_lbsize = inv_lbsize;
+ inv_lbsize = ntemp;
+
+ rl_display_fixed = 0;
+ /* If we are displaying on a single line, and last_lmargin is > 0, we
+ are not displaying any invisible characters, so set visible_wrap_offset
+ to 0. */
+ if (_rl_horizontal_scroll_mode && last_lmargin)
+ visible_wrap_offset = 0;
+ else
+ visible_wrap_offset = wrap_offset;
+ }
+}
+
+/* PWP: update_line() is based on finding the middle difference of each
+ line on the screen; vis:
+
+ /old first difference
+ /beginning of line | /old last same /old EOL
+ v v v v
+old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new: eddie> Oh, my little buggy says to me, as lurgid as
+ ^ ^ ^ ^
+ \beginning of line | \new last same \new end of line
+ \new first difference
+
+ All are character pointers for the sake of speed. Special cases for
+ no differences, as well as for end of line additions must be handled.
+
+ Could be made even smarter, but this works well enough */
+static void
+update_line (old, new, current_line, omax, nmax, inv_botlin)
+ register char *old, *new;
+ int current_line, omax, nmax, inv_botlin;
+{
+ register char *ofd, *ols, *oe, *nfd, *nls, *ne;
+ int temp, lendiff, wsatend, od, nd;
+ int current_invis_chars;
+ int col_lendiff, col_temp;
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t ps_new, ps_old;
+ int new_offset, old_offset, tmp;
+#endif
+
+ /* If we're at the right edge of a terminal that supports xn, we're
+ ready to wrap around, so do so. This fixes problems with knowing
+ the exact cursor position and cut-and-paste with certain terminal
+ emulators. In this calculation, TEMP is the physical screen
+ position of the cursor. */
+ temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+ if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
+ && _rl_last_v_pos == current_line - 1)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ wchar_t wc;
+ mbstate_t ps;
+ int tempwidth, bytes;
+ size_t ret;
+
+ /* This fixes only double-column characters, but if the wrapped
+ character comsumes more than three columns, spaces will be
+ inserted in the string buffer. */
+ if (_rl_wrapped_line[current_line] > 0)
+ _rl_clear_to_eol (_rl_wrapped_line[current_line]);
+
+ memset (&ps, 0, sizeof (mbstate_t));
+ ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
+ if (ret == (size_t)-1 || ret == (size_t)-2)
+ {
+ tempwidth = 1;
+ ret = 1;
+ }
+ else if (ret == 0)
+ tempwidth = 0;
+ else
+ tempwidth = wcwidth (wc);
+
+ if (tempwidth > 0)
+ {
+ int count;
+ bytes = ret;
+ for (count = 0; count < bytes; count++)
+ putc (new[count], rl_outstream);
+ _rl_last_c_pos = tempwidth;
+ _rl_last_v_pos++;
+ memset (&ps, 0, sizeof (mbstate_t));
+ ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
+ if (ret != 0 && bytes != 0)
+ {
+ if (ret == (size_t)-1 || ret == (size_t)-2)
+ memmove (old+bytes, old+1, strlen (old+1));
+ else
+ memmove (old+bytes, old+ret, strlen (old+ret));
+ memcpy (old, new, bytes);
+ }
+ }
+ else
+ {
+ putc (' ', rl_outstream);
+ _rl_last_c_pos = 1;
+ _rl_last_v_pos++;
+ if (old[0] && new[0])
+ old[0] = new[0];
+ }
+ }
+ else
+#endif
+ {
+ if (new[0])
+ putc (new[0], rl_outstream);
+ else
+ putc (' ', rl_outstream);
+ _rl_last_c_pos = 1; /* XXX */
+ _rl_last_v_pos++;
+ if (old[0] && new[0])
+ old[0] = new[0];
+ }
+ }
+
+
+ /* Find first difference. */
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ memset (&ps_new, 0, sizeof(mbstate_t));
+ memset (&ps_old, 0, sizeof(mbstate_t));
+
+ new_offset = old_offset = 0;
+ for (ofd = old, nfd = new;
+ (ofd - old < omax) && *ofd &&
+ _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
+ {
+ old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
+ new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
+ ofd = old + old_offset;
+ nfd = new + new_offset;
+ }
+ }
+ else
+#endif
+ for (ofd = old, nfd = new;
+ (ofd - old < omax) && *ofd && (*ofd == *nfd);
+ ofd++, nfd++)
+ ;
+
+ /* Move to the end of the screen line. ND and OD are used to keep track
+ of the distance between ne and new and oe and old, respectively, to
+ move a subtraction out of each loop. */
+ for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
+ for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
+
+ /* If no difference, continue to next line. */
+ if (ofd == oe && nfd == ne)
+ return;
+
+ wsatend = 1; /* flag for trailing whitespace */
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
+ nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
+ while ((ols > ofd) && (nls > nfd))
+ {
+ memset (&ps_old, 0, sizeof (mbstate_t));
+ memset (&ps_new, 0, sizeof (mbstate_t));
+
+ _rl_adjust_point (old, ols - old, &ps_old);
+ _rl_adjust_point (new, nls - new, &ps_new);
+
+ if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
+ break;
+
+ if (*ols == ' ')
+ wsatend = 0;
+
+ ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
+ nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
+ }
+ }
+ else
+ {
+#endif /* HANDLE_MULTIBYTE */
+ ols = oe - 1; /* find last same */
+ nls = ne - 1;
+ while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
+ {
+ if (*ols != ' ')
+ wsatend = 0;
+ ols--;
+ nls--;
+ }
+#if defined (HANDLE_MULTIBYTE)
+ }
+#endif
+
+ if (wsatend)
+ {
+ ols = oe;
+ nls = ne;
+ }
+#if defined (HANDLE_MULTIBYTE)
+ /* This may not work for stateful encoding, but who cares? To handle
+ stateful encoding properly, we have to scan each string from the
+ beginning and compare. */
+ else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
+#else
+ else if (*ols != *nls)
+#endif
+ {
+ if (*ols) /* don't step past the NUL */
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
+ else
+ ols++;
+ }
+ if (*nls)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
+ else
+ nls++;
+ }
+ }
+
+ /* count of invisible characters in the current invisible line. */
+ current_invis_chars = W_OFFSET (current_line, wrap_offset);
+ if (_rl_last_v_pos != current_line)
+ {
+ _rl_move_vert (current_line);
+ if (current_line == 0 && visible_wrap_offset)
+ _rl_last_c_pos += visible_wrap_offset;
+ }
+
+ /* If this is the first line and there are invisible characters in the
+ prompt string, and the prompt string has not changed, and the current
+ cursor position is before the last invisible character in the prompt,
+ and the index of the character to move to is past the end of the prompt
+ string, then redraw the entire prompt string. We can only do this
+ reliably if the terminal supports a `cr' capability.
+
+ This is not an efficiency hack -- there is a problem with redrawing
+ portions of the prompt string if they contain terminal escape
+ sequences (like drawing the `unbold' sequence without a corresponding
+ `bold') that manifests itself on certain terminals. */
+
+ lendiff = local_prompt ? strlen (local_prompt) : 0;
+ od = ofd - old; /* index of first difference in visible line */
+ if (current_line == 0 && !_rl_horizontal_scroll_mode &&
+ _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
+ od >= lendiff && _rl_last_c_pos <= prompt_last_invisible)
+ {
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif
+ _rl_output_some_chars (local_prompt, lendiff);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff);
+ else
+ _rl_last_c_pos = lendiff;
+ }
+
+ _rl_move_cursor_relative (od, old);
+
+ /* if (len (new) > len (old))
+ lendiff == difference in buffer
+ col_lendiff == difference on screen
+ When not using multibyte characters, these are equal */
+ lendiff = (nls - nfd) - (ols - ofd);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
+ else
+ col_lendiff = lendiff;
+
+ /* If we are changing the number of invisible characters in a line, and
+ the spot of first difference is before the end of the invisible chars,
+ lendiff needs to be adjusted. */
+ if (current_line == 0 && !_rl_horizontal_scroll_mode &&
+ current_invis_chars != visible_wrap_offset)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ lendiff += visible_wrap_offset - current_invis_chars;
+ col_lendiff += visible_wrap_offset - current_invis_chars;
+ }
+ else
+ {
+ lendiff += visible_wrap_offset - current_invis_chars;
+ col_lendiff = lendiff;
+ }
+ }
+
+ /* Insert (diff (len (old), len (new)) ch. */
+ temp = ne - nfd;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ col_temp = _rl_col_width (new, nfd - new, ne - new);
+ else
+ col_temp = temp;
+
+ if (col_lendiff > 0) /* XXX - was lendiff */
+ {
+ /* Non-zero if we're increasing the number of lines. */
+ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+ /* Sometimes it is cheaper to print the characters rather than
+ use the terminal's capabilities. If we're growing the number
+ of lines, make sure we actually cause the new line to wrap
+ around on auto-wrapping terminals. */
+ if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+ {
+ /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
+ _rl_horizontal_scroll_mode == 1, inserting the characters with
+ _rl_term_IC or _rl_term_ic will screw up the screen because of the
+ invisible characters. We need to just draw them. */
+ if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
+ lendiff <= prompt_visible_length || !current_invis_chars))
+ {
+ insert_some_chars (nfd, lendiff, col_lendiff);
+ _rl_last_c_pos += col_lendiff;
+ }
+ else if (*ols == 0)
+ {
+ /* At the end of a line the characters do not have to
+ be "inserted". They can just be placed on the screen. */
+ /* However, this screws up the rest of this block, which
+ assumes you've done the insert because you can. */
+ _rl_output_some_chars (nfd, lendiff);
+ _rl_last_c_pos += col_lendiff;
+ }
+ else
+ {
+ /* We have horizontal scrolling and we are not inserting at
+ the end. We have invisible characters in this line. This
+ is a dumb update. */
+ _rl_output_some_chars (nfd, temp);
+ _rl_last_c_pos += col_temp;
+ return;
+ }
+ /* Copy (new) chars to screen from first diff to last match. */
+ temp = nls - nfd;
+ if ((temp - lendiff) > 0)
+ {
+ _rl_output_some_chars (nfd + lendiff, temp - lendiff);
+#if 0
+ _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff) - col_lendiff;
+#else
+ _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
+#endif
+ }
+ }
+ else
+ {
+ /* cannot insert chars, write to EOL */
+ _rl_output_some_chars (nfd, temp);
+ _rl_last_c_pos += col_temp;
+ }
+ }
+ else /* Delete characters from line. */
+ {
+ /* If possible and inexpensive to use terminal deletion, then do so. */
+ if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
+ {
+ /* If all we're doing is erasing the invisible characters in the
+ prompt string, don't bother. It screws up the assumptions
+ about what's on the screen. */
+ if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
+ -lendiff == visible_wrap_offset)
+ col_lendiff = 0;
+
+ if (col_lendiff)
+ delete_chars (-col_lendiff); /* delete (diff) characters */
+
+ /* Copy (new) chars to screen from first diff to last match */
+ temp = nls - nfd;
+ if (temp > 0)
+ {
+ _rl_output_some_chars (nfd, temp);
+ _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
+ }
+ }
+ /* Otherwise, print over the existing material. */
+ else
+ {
+ if (temp > 0)
+ {
+ _rl_output_some_chars (nfd, temp);
+ _rl_last_c_pos += col_temp;
+ }
+ lendiff = (oe - old) - (ne - new);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
+ else
+ col_lendiff = lendiff;
+
+ if (col_lendiff)
+ {
+ if (_rl_term_autowrap && current_line < inv_botlin)
+ space_to_eol (col_lendiff);
+ else
+ _rl_clear_to_eol (col_lendiff);
+ }
+ }
+ }
+}
+
+/* Tell the update routines that we have moved onto a new (empty) line. */
+int
+rl_on_new_line ()
+{
+ if (visible_line)
+ visible_line[0] = '\0';
+
+ _rl_last_c_pos = _rl_last_v_pos = 0;
+ _rl_vis_botlin = last_lmargin = 0;
+ if (vis_lbreaks)
+ vis_lbreaks[0] = vis_lbreaks[1] = 0;
+ visible_wrap_offset = 0;
+ return 0;
+}
+
+/* Tell the update routines that we have moved onto a new line with the
+ prompt already displayed. Code originally from the version of readline
+ distributed with CLISP. */
+int
+rl_on_new_line_with_prompt ()
+{
+ int prompt_size, i, l, real_screenwidth, newlines;
+ char *prompt_last_line;
+
+ /* Initialize visible_line and invisible_line to ensure that they can hold
+ the already-displayed prompt. */
+ prompt_size = strlen (rl_prompt) + 1;
+ init_line_structures (prompt_size);
+
+ /* Make sure the line structures hold the already-displayed prompt for
+ redisplay. */
+ strcpy (visible_line, rl_prompt);
+ strcpy (invisible_line, rl_prompt);
+
+ /* If the prompt contains newlines, take the last tail. */
+ prompt_last_line = strrchr (rl_prompt, '\n');
+ if (!prompt_last_line)
+ prompt_last_line = rl_prompt;
+
+ l = strlen (prompt_last_line);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);
+ else
+ _rl_last_c_pos = l;
+
+ /* Dissect prompt_last_line into screen lines. Note that here we have
+ to use the real screenwidth. Readline's notion of screenwidth might be
+ one less, see terminal.c. */
+ real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
+ _rl_last_v_pos = l / real_screenwidth;
+ /* If the prompt length is a multiple of real_screenwidth, we don't know
+ whether the cursor is at the end of the last line, or already at the
+ beginning of the next line. Output a newline just to be safe. */
+ if (l > 0 && (l % real_screenwidth) == 0)
+ _rl_output_some_chars ("\n", 1);
+ last_lmargin = 0;
+
+ newlines = 0; i = 0;
+ while (i <= l)
+ {
+ _rl_vis_botlin = newlines;
+ vis_lbreaks[newlines++] = i;
+ i += real_screenwidth;
+ }
+ vis_lbreaks[newlines] = l;
+ visible_wrap_offset = 0;
+
+ return 0;
+}
+
+/* Actually update the display, period. */
+int
+rl_forced_update_display ()
+{
+ if (visible_line)
+ {
+ register char *temp = visible_line;
+
+ while (*temp)
+ *temp++ = '\0';
+ }
+ rl_on_new_line ();
+ forced_display++;
+ (*rl_redisplay_function) ();
+ return 0;
+}
+
+/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
+ DATA is the contents of the screen line of interest; i.e., where
+ the movement is being done. */
+void
+_rl_move_cursor_relative (new, data)
+ int new;
+ const char *data;
+{
+ register int i;
+
+ /* If we don't have to do anything, then return. */
+#if defined (HANDLE_MULTIBYTE)
+ /* If we have multibyte characters, NEW is indexed by the buffer point in
+ a multibyte string, but _rl_last_c_pos is the display position. In
+ this case, NEW's display position is not obvious. */
+ if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return;
+#else
+ if (_rl_last_c_pos == new) return;
+#endif
+
+ /* It may be faster to output a CR, and then move forwards instead
+ of moving backwards. */
+ /* i == current physical cursor position. */
+ i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+ if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
+ (_rl_term_autowrap && i == _rl_screenwidth))
+ {
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif /* !__MSDOS__ */
+ _rl_last_c_pos = 0;
+ }
+
+ if (_rl_last_c_pos < new)
+ {
+ /* Move the cursor forward. We do it by printing the command
+ to move the cursor forward if there is one, else print that
+ portion of the output buffer again. Which is cheaper? */
+
+ /* The above comment is left here for posterity. It is faster
+ to print one character (non-control) than to print a control
+ sequence telling the terminal to move forward one character.
+ That kind of control is for people who don't know what the
+ data is underneath the cursor. */
+#if defined (HACK_TERMCAP_MOTION)
+ if (_rl_term_forward_char)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int width;
+ width = _rl_col_width (data, _rl_last_c_pos, new);
+ for (i = 0; i < width; i++)
+ tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+ }
+ else
+ {
+ for (i = _rl_last_c_pos; i < new; i++)
+ tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+ }
+ }
+ else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+ for (i = 0; i < new; i++)
+ putc (data[i], rl_outstream);
+ }
+ else
+ for (i = _rl_last_c_pos; i < new; i++)
+ putc (data[i], rl_outstream);
+
+#else /* !HACK_TERMCAP_MOTION */
+
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+ for (i = 0; i < new; i++)
+ putc (data[i], rl_outstream);
+ }
+ else
+ for (i = _rl_last_c_pos; i < new; i++)
+ putc (data[i], rl_outstream);
+
+#endif /* !HACK_TERMCAP_MOTION */
+
+ }
+#if defined (HANDLE_MULTIBYTE)
+ /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
+ The byte length of the string is probably bigger than the column width
+ of the string, which means that if NEW == _rl_last_c_pos, then NEW's
+ display point is less than _rl_last_c_pos. */
+ else if (_rl_last_c_pos >= new)
+#else
+ else if (_rl_last_c_pos > new)
+#endif
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+ for (i = 0; i < new; i++)
+ putc (data[i], rl_outstream);
+ }
+ else
+ _rl_backspace (_rl_last_c_pos - new);
+ }
+
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos = _rl_col_width (data, 0, new);
+ else
+ _rl_last_c_pos = new;
+}
+
+/* PWP: move the cursor up or down. */
+void
+_rl_move_vert (to)
+ int to;
+{
+ register int delta, i;
+
+ if (_rl_last_v_pos == to || to > _rl_screenheight)
+ return;
+
+ if ((delta = to - _rl_last_v_pos) > 0)
+ {
+ for (i = 0; i < delta; i++)
+ putc ('\n', rl_outstream);
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif
+ _rl_last_c_pos = 0;
+ }
+ else
+ { /* delta < 0 */
+ if (_rl_term_up && *_rl_term_up)
+ for (i = 0; i < -delta; i++)
+ tputs (_rl_term_up, 1, _rl_output_character_function);
+ }
+
+ _rl_last_v_pos = to; /* Now TO is here */
+}
+
+/* Physically print C on rl_outstream. This is for functions which know
+ how to optimize the display. Return the number of characters output. */
+int
+rl_show_char (c)
+ int c;
+{
+ int n = 1;
+ if (META_CHAR (c) && (_rl_output_meta_chars == 0))
+ {
+ fprintf (rl_outstream, "M-");
+ n += 2;
+ c = UNMETA (c);
+ }
+
+#if defined (DISPLAY_TABS)
+ if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
+#else
+ if (CTRL_CHAR (c) || c == RUBOUT)
+#endif /* !DISPLAY_TABS */
+ {
+ fprintf (rl_outstream, "C-");
+ n += 2;
+ c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
+ }
+
+ putc (c, rl_outstream);
+ fflush (rl_outstream);
+ return n;
+}
+
+int
+rl_character_len (c, pos)
+ register int c, pos;
+{
+ unsigned char uc;
+
+ uc = (unsigned char)c;
+
+ if (META_CHAR (uc))
+ return ((_rl_output_meta_chars == 0) ? 4 : 1);
+
+ if (uc == '\t')
+ {
+#if defined (DISPLAY_TABS)
+ return (((pos | 7) + 1) - pos);
+#else
+ return (2);
+#endif /* !DISPLAY_TABS */
+ }
+
+ if (CTRL_CHAR (c) || c == RUBOUT)
+ return (2);
+
+ return ((ISPRINT (uc)) ? 1 : 2);
+}
+
+/* How to print things in the "echo-area". The prompt is treated as a
+ mini-modeline. */
+
+#if defined (USE_VARARGS)
+int
+#if defined (PREFER_STDARG)
+rl_message (const char *format, ...)
+#else
+rl_message (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#if defined (PREFER_VARARGS)
+ char *format;
+#endif
+
+#if defined (PREFER_STDARG)
+ va_start (args, format);
+#else
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+
+#if defined (HAVE_VSNPRINTF)
+ vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
+#else
+ vsprintf (msg_buf, format, args);
+ msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
+#endif
+ va_end (args);
+
+ rl_display_prompt = msg_buf;
+ (*rl_redisplay_function) ();
+ return 0;
+}
+#else /* !USE_VARARGS */
+int
+rl_message (format, arg1, arg2)
+ char *format;
+ int arg1, arg2;
+{
+ sprintf (msg_buf, format, arg1, arg2);
+ msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
+ rl_display_prompt = msg_buf;
+ (*rl_redisplay_function) ();
+ return 0;
+}
+#endif /* !USE_VARARGS */
+
+/* How to clear things from the "echo-area". */
+int
+rl_clear_message ()
+{
+ rl_display_prompt = rl_prompt;
+ (*rl_redisplay_function) ();
+ return 0;
+}
+
+int
+rl_reset_line_state ()
+{
+ rl_on_new_line ();
+
+ rl_display_prompt = rl_prompt ? rl_prompt : "";
+ forced_display = 1;
+ return 0;
+}
+
+static char *saved_local_prompt;
+static char *saved_local_prefix;
+static int saved_last_invisible;
+static int saved_visible_length;
+
+void
+rl_save_prompt ()
+{
+ saved_local_prompt = local_prompt;
+ saved_local_prefix = local_prompt_prefix;
+ saved_last_invisible = prompt_last_invisible;
+ saved_visible_length = prompt_visible_length;
+
+ local_prompt = local_prompt_prefix = (char *)0;
+ prompt_last_invisible = prompt_visible_length = 0;
+}
+
+void
+rl_restore_prompt ()
+{
+ FREE (local_prompt);
+ FREE (local_prompt_prefix);
+
+ local_prompt = saved_local_prompt;
+ local_prompt_prefix = saved_local_prefix;
+ prompt_last_invisible = saved_last_invisible;
+ prompt_visible_length = saved_visible_length;
+}
+
+char *
+_rl_make_prompt_for_search (pchar)
+ int pchar;
+{
+ int len;
+ char *pmt;
+
+ rl_save_prompt ();
+
+ if (saved_local_prompt == 0)
+ {
+ len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
+ pmt = (char *)xmalloc (len + 2);
+ if (len)
+ strcpy (pmt, rl_prompt);
+ pmt[len] = pchar;
+ pmt[len+1] = '\0';
+ }
+ else
+ {
+ len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
+ pmt = (char *)xmalloc (len + 2);
+ if (len)
+ strcpy (pmt, saved_local_prompt);
+ pmt[len] = pchar;
+ pmt[len+1] = '\0';
+ local_prompt = savestring (pmt);
+ prompt_last_invisible = saved_last_invisible;
+ prompt_visible_length = saved_visible_length + 1;
+ }
+ return pmt;
+}
+
+/* Quick redisplay hack when erasing characters at the end of the line. */
+void
+_rl_erase_at_end_of_line (l)
+ int l;
+{
+ register int i;
+
+ _rl_backspace (l);
+ for (i = 0; i < l; i++)
+ putc (' ', rl_outstream);
+ _rl_backspace (l);
+ for (i = 0; i < l; i++)
+ visible_line[--_rl_last_c_pos] = '\0';
+ rl_display_fixed++;
+}
+
+/* Clear to the end of the line. COUNT is the minimum
+ number of character spaces to clear, */
+void
+_rl_clear_to_eol (count)
+ int count;
+{
+ if (_rl_term_clreol)
+ tputs (_rl_term_clreol, 1, _rl_output_character_function);
+ else if (count)
+ space_to_eol (count);
+}
+
+/* Clear to the end of the line using spaces. COUNT is the minimum
+ number of character spaces to clear, */
+static void
+space_to_eol (count)
+ int count;
+{
+ register int i;
+
+ for (i = 0; i < count; i++)
+ putc (' ', rl_outstream);
+
+ _rl_last_c_pos += count;
+}
+
+void
+_rl_clear_screen ()
+{
+ if (_rl_term_clrpag)
+ tputs (_rl_term_clrpag, 1, _rl_output_character_function);
+ else
+ rl_crlf ();
+}
+
+/* Insert COUNT characters from STRING to the output stream at column COL. */
+static void
+insert_some_chars (string, count, col)
+ char *string;
+ int count, col;
+{
+ /* DEBUGGING */
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ if (count != col)
+ fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
+
+ /* If IC is defined, then we do not have to "enter" insert mode. */
+ if (_rl_term_IC)
+ {
+ char *buffer;
+
+ buffer = tgoto (_rl_term_IC, 0, col);
+ tputs (buffer, 1, _rl_output_character_function);
+ _rl_output_some_chars (string, count);
+ }
+ else
+ {
+ register int i;
+
+ /* If we have to turn on insert-mode, then do so. */
+ if (_rl_term_im && *_rl_term_im)
+ tputs (_rl_term_im, 1, _rl_output_character_function);
+
+ /* If there is a special command for inserting characters, then
+ use that first to open up the space. */
+ if (_rl_term_ic && *_rl_term_ic)
+ {
+ for (i = col; i--; )
+ tputs (_rl_term_ic, 1, _rl_output_character_function);
+ }
+
+ /* Print the text. */
+ _rl_output_some_chars (string, count);
+
+ /* If there is a string to turn off insert mode, we had best use
+ it now. */
+ if (_rl_term_ei && *_rl_term_ei)
+ tputs (_rl_term_ei, 1, _rl_output_character_function);
+ }
+}
+
+/* Delete COUNT characters from the display line. */
+static void
+delete_chars (count)
+ int count;
+{
+ if (count > _rl_screenwidth) /* XXX */
+ return;
+
+ if (_rl_term_DC && *_rl_term_DC)
+ {
+ char *buffer;
+ buffer = tgoto (_rl_term_DC, count, count);
+ tputs (buffer, count, _rl_output_character_function);
+ }
+ else
+ {
+ if (_rl_term_dc && *_rl_term_dc)
+ while (count--)
+ tputs (_rl_term_dc, 1, _rl_output_character_function);
+ }
+}
+
+void
+_rl_update_final ()
+{
+ int full_lines;
+
+ full_lines = 0;
+ /* If the cursor is the only thing on an otherwise-blank last line,
+ compensate so we don't print an extra CRLF. */
+ if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
+ visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
+ {
+ _rl_vis_botlin--;
+ full_lines = 1;
+ }
+ _rl_move_vert (_rl_vis_botlin);
+ /* If we've wrapped lines, remove the final xterm line-wrap flag. */
+ if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
+ {
+ char *last_line;
+
+ last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
+ _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
+ _rl_clear_to_eol (0);
+ putc (last_line[_rl_screenwidth - 1], rl_outstream);
+ }
+ _rl_vis_botlin = 0;
+ rl_crlf ();
+ fflush (rl_outstream);
+ rl_display_fixed++;
+}
+
+/* Move to the start of the current line. */
+static void
+cr ()
+{
+ if (_rl_term_cr)
+ {
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif
+ _rl_last_c_pos = 0;
+ }
+}
+
+/* Redraw the last line of a multi-line prompt that may possibly contain
+ terminal escape sequences. Called with the cursor at column 0 of the
+ line to draw the prompt on. */
+static void
+redraw_prompt (t)
+ char *t;
+{
+ const char *oldp;
+ char *oldl, *oldlprefix;
+ int oldlen, oldlast, oldplen, oldninvis;
+
+ /* Geez, I should make this a struct. */
+ oldp = rl_display_prompt;
+ oldl = local_prompt;
+ oldlprefix = local_prompt_prefix;
+ oldlen = prompt_visible_length;
+ oldplen = prompt_prefix_length;
+ oldlast = prompt_last_invisible;
+ oldninvis = prompt_invis_chars_first_line;
+
+ rl_display_prompt = t;
+ local_prompt = expand_prompt (t, &prompt_visible_length,
+ &prompt_last_invisible,
+ &prompt_invis_chars_first_line);
+ local_prompt_prefix = (char *)NULL;
+ rl_forced_update_display ();
+
+ rl_display_prompt = oldp;
+ local_prompt = oldl;
+ local_prompt_prefix = oldlprefix;
+ prompt_visible_length = oldlen;
+ prompt_prefix_length = oldplen;
+ prompt_last_invisible = oldlast;
+ prompt_invis_chars_first_line = oldninvis;
+}
+
+/* Redisplay the current line after a SIGWINCH is received. */
+void
+_rl_redisplay_after_sigwinch ()
+{
+ char *t;
+
+ /* Clear the current line and put the cursor at column 0. Make sure
+ the right thing happens if we have wrapped to a new screen line. */
+ if (_rl_term_cr)
+ {
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif
+ _rl_last_c_pos = 0;
+#if defined (__MSDOS__)
+ space_to_eol (_rl_screenwidth);
+ putc ('\r', rl_outstream);
+#else
+ if (_rl_term_clreol)
+ tputs (_rl_term_clreol, 1, _rl_output_character_function);
+ else
+ {
+ space_to_eol (_rl_screenwidth);
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+ }
+#endif
+ if (_rl_last_v_pos > 0)
+ _rl_move_vert (0);
+ }
+ else
+ rl_crlf ();
+
+ /* Redraw only the last line of a multi-line prompt. */
+ t = strrchr (rl_display_prompt, '\n');
+ if (t)
+ redraw_prompt (++t);
+ else
+ rl_forced_update_display ();
+}
+
+void
+_rl_clean_up_for_exit ()
+{
+ if (readline_echoing_p)
+ {
+ _rl_move_vert (_rl_vis_botlin);
+ _rl_vis_botlin = 0;
+ fflush (rl_outstream);
+ rl_restart_output (1, 0);
+ }
+}
+
+void
+_rl_erase_entire_line ()
+{
+ cr ();
+ _rl_clear_to_eol (0);
+ cr ();
+ fflush (rl_outstream);
+}
+
+/* return the `current display line' of the cursor -- the number of lines to
+ move up to get to the first screen line of the current readline line. */
+int
+_rl_current_display_line ()
+{
+ int ret, nleft;
+
+ /* Find out whether or not there might be invisible characters in the
+ editing buffer. */
+ if (rl_display_prompt == rl_prompt)
+ nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
+ else
+ nleft = _rl_last_c_pos - _rl_screenwidth;
+
+ if (nleft > 0)
+ ret = 1 + nleft / _rl_screenwidth;
+ else
+ ret = 0;
+
+ return ret;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Calculate the number of screen columns occupied by STR from START to END.
+ In the case of multibyte characters with stateful encoding, we have to
+ scan from the beginning of the string to take the state into account. */
+static int
+_rl_col_width (str, start, end)
+ const char *str;
+ int start, end;
+{
+ wchar_t wc;
+ mbstate_t ps = {0};
+ int tmp, point, width, max;
+
+ if (end <= start)
+ return 0;
+
+ point = 0;
+ max = end;
+
+ while (point < start)
+ {
+ tmp = mbrlen (str + point, max, &ps);
+ if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+ {
+ /* In this case, the bytes are invalid or too short to compose a
+ multibyte character, so we assume that the first byte represents
+ a single character. */
+ point++;
+ max--;
+
+ /* Clear the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (tmp == 0)
+ break; /* Found '\0' */
+ else
+ {
+ point += tmp;
+ max -= tmp;
+ }
+ }
+
+ /* If START is not a byte that starts a character, then POINT will be
+ greater than START. In this case, assume that (POINT - START) gives
+ a byte count that is the number of columns of difference. */
+ width = point - start;
+
+ while (point < end)
+ {
+ tmp = mbrtowc (&wc, str + point, max, &ps);
+ if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+ {
+ /* In this case, the bytes are invalid or too short to compose a
+ multibyte character, so we assume that the first byte represents
+ a single character. */
+ point++;
+ max--;
+
+ /* and assume that the byte occupies a single column. */
+ width++;
+
+ /* Clear the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (tmp == 0)
+ break; /* Found '\0' */
+ else
+ {
+ point += tmp;
+ max -= tmp;
+ tmp = wcwidth(wc);
+ width += (tmp >= 0) ? tmp : 1;
+ }
+ }
+
+ width += point - end;
+
+ return width;
+}
+#endif /* HANDLE_MULTIBYTE */
+
diff --git a/cmd-line-utils/readline/emacs_keymap.c b/cmd-line-utils/readline/emacs_keymap.c
new file mode 100644
index 00000000000..ca9d1343b65
--- /dev/null
+++ b/cmd-line-utils/readline/emacs_keymap.c
@@ -0,0 +1,873 @@
+/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* !BUFSIZ */
+
+#include "readline.h"
+
+/* An array of function pointers, one for each possible key.
+ If the type byte is ISKMAP, then the pointer is the address of
+ a keymap. */
+
+KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
+
+ /* Control keys. */
+ { ISFUNC, rl_set_mark }, /* Control-@ */
+ { ISFUNC, rl_beg_of_line }, /* Control-a */
+ { ISFUNC, rl_backward_char }, /* Control-b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */
+ { ISFUNC, rl_delete }, /* Control-d */
+ { ISFUNC, rl_end_of_line }, /* Control-e */
+ { ISFUNC, rl_forward_char }, /* Control-f */
+ { ISFUNC, rl_abort }, /* Control-g */
+ { ISFUNC, rl_rubout }, /* Control-h */
+ { ISFUNC, rl_complete }, /* Control-i */
+ { ISFUNC, rl_newline }, /* Control-j */
+ { ISFUNC, rl_kill_line }, /* Control-k */
+ { ISFUNC, rl_clear_screen }, /* Control-l */
+ { ISFUNC, rl_newline }, /* Control-m */
+ { ISFUNC, rl_get_next_history }, /* Control-n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */
+ { ISFUNC, rl_get_previous_history }, /* Control-p */
+ { ISFUNC, rl_quoted_insert }, /* Control-q */
+ { ISFUNC, rl_reverse_search_history }, /* Control-r */
+ { ISFUNC, rl_forward_search_history }, /* Control-s */
+ { ISFUNC, rl_transpose_chars }, /* Control-t */
+ { ISFUNC, rl_unix_line_discard }, /* Control-u */
+ { ISFUNC, rl_quoted_insert }, /* Control-v */
+ { ISFUNC, rl_unix_word_rubout }, /* Control-w */
+ { ISKMAP, (rl_command_func_t *)emacs_ctlx_keymap }, /* Control-x */
+ { ISFUNC, rl_yank }, /* Control-y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */
+ { ISKMAP, (rl_command_func_t *)emacs_meta_keymap }, /* Control-[ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */
+ { ISFUNC, rl_char_search }, /* Control-] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */
+ { ISFUNC, rl_undo_command }, /* Control-_ */
+
+ /* The start of printing characters. */
+ { ISFUNC, rl_insert }, /* SPACE */
+ { ISFUNC, rl_insert }, /* ! */
+ { ISFUNC, rl_insert }, /* " */
+ { ISFUNC, rl_insert }, /* # */
+ { ISFUNC, rl_insert }, /* $ */
+ { ISFUNC, rl_insert }, /* % */
+ { ISFUNC, rl_insert }, /* & */
+ { ISFUNC, rl_insert }, /* ' */
+ { ISFUNC, rl_insert }, /* ( */
+ { ISFUNC, rl_insert }, /* ) */
+ { ISFUNC, rl_insert }, /* * */
+ { ISFUNC, rl_insert }, /* + */
+ { ISFUNC, rl_insert }, /* , */
+ { ISFUNC, rl_insert }, /* - */
+ { ISFUNC, rl_insert }, /* . */
+ { ISFUNC, rl_insert }, /* / */
+
+ /* Regular digits. */
+ { ISFUNC, rl_insert }, /* 0 */
+ { ISFUNC, rl_insert }, /* 1 */
+ { ISFUNC, rl_insert }, /* 2 */
+ { ISFUNC, rl_insert }, /* 3 */
+ { ISFUNC, rl_insert }, /* 4 */
+ { ISFUNC, rl_insert }, /* 5 */
+ { ISFUNC, rl_insert }, /* 6 */
+ { ISFUNC, rl_insert }, /* 7 */
+ { ISFUNC, rl_insert }, /* 8 */
+ { ISFUNC, rl_insert }, /* 9 */
+
+ /* A little more punctuation. */
+ { ISFUNC, rl_insert }, /* : */
+ { ISFUNC, rl_insert }, /* ; */
+ { ISFUNC, rl_insert }, /* < */
+ { ISFUNC, rl_insert }, /* = */
+ { ISFUNC, rl_insert }, /* > */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* @ */
+
+ /* Uppercase alphabet. */
+ { ISFUNC, rl_insert }, /* A */
+ { ISFUNC, rl_insert }, /* B */
+ { ISFUNC, rl_insert }, /* C */
+ { ISFUNC, rl_insert }, /* D */
+ { ISFUNC, rl_insert }, /* E */
+ { ISFUNC, rl_insert }, /* F */
+ { ISFUNC, rl_insert }, /* G */
+ { ISFUNC, rl_insert }, /* H */
+ { ISFUNC, rl_insert }, /* I */
+ { ISFUNC, rl_insert }, /* J */
+ { ISFUNC, rl_insert }, /* K */
+ { ISFUNC, rl_insert }, /* L */
+ { ISFUNC, rl_insert }, /* M */
+ { ISFUNC, rl_insert }, /* N */
+ { ISFUNC, rl_insert }, /* O */
+ { ISFUNC, rl_insert }, /* P */
+ { ISFUNC, rl_insert }, /* Q */
+ { ISFUNC, rl_insert }, /* R */
+ { ISFUNC, rl_insert }, /* S */
+ { ISFUNC, rl_insert }, /* T */
+ { ISFUNC, rl_insert }, /* U */
+ { ISFUNC, rl_insert }, /* V */
+ { ISFUNC, rl_insert }, /* W */
+ { ISFUNC, rl_insert }, /* X */
+ { ISFUNC, rl_insert }, /* Y */
+ { ISFUNC, rl_insert }, /* Z */
+
+ /* Some more punctuation. */
+ { ISFUNC, rl_insert }, /* [ */
+ { ISFUNC, rl_insert }, /* \ */
+ { ISFUNC, rl_insert }, /* ] */
+ { ISFUNC, rl_insert }, /* ^ */
+ { ISFUNC, rl_insert }, /* _ */
+ { ISFUNC, rl_insert }, /* ` */
+
+ /* Lowercase alphabet. */
+ { ISFUNC, rl_insert }, /* a */
+ { ISFUNC, rl_insert }, /* b */
+ { ISFUNC, rl_insert }, /* c */
+ { ISFUNC, rl_insert }, /* d */
+ { ISFUNC, rl_insert }, /* e */
+ { ISFUNC, rl_insert }, /* f */
+ { ISFUNC, rl_insert }, /* g */
+ { ISFUNC, rl_insert }, /* h */
+ { ISFUNC, rl_insert }, /* i */
+ { ISFUNC, rl_insert }, /* j */
+ { ISFUNC, rl_insert }, /* k */
+ { ISFUNC, rl_insert }, /* l */
+ { ISFUNC, rl_insert }, /* m */
+ { ISFUNC, rl_insert }, /* n */
+ { ISFUNC, rl_insert }, /* o */
+ { ISFUNC, rl_insert }, /* p */
+ { ISFUNC, rl_insert }, /* q */
+ { ISFUNC, rl_insert }, /* r */
+ { ISFUNC, rl_insert }, /* s */
+ { ISFUNC, rl_insert }, /* t */
+ { ISFUNC, rl_insert }, /* u */
+ { ISFUNC, rl_insert }, /* v */
+ { ISFUNC, rl_insert }, /* w */
+ { ISFUNC, rl_insert }, /* x */
+ { ISFUNC, rl_insert }, /* y */
+ { ISFUNC, rl_insert }, /* z */
+
+ /* Final punctuation. */
+ { ISFUNC, rl_insert }, /* { */
+ { ISFUNC, rl_insert }, /* | */
+ { ISFUNC, rl_insert }, /* } */
+ { ISFUNC, rl_insert }, /* ~ */
+ { ISFUNC, rl_rubout }, /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+ /* Pure 8-bit characters (128 - 159).
+ These might be used in some
+ character sets. */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+
+ /* ISO Latin-1 characters (160 - 255) */
+ { ISFUNC, rl_insert }, /* No-break space */
+ { ISFUNC, rl_insert }, /* Inverted exclamation mark */
+ { ISFUNC, rl_insert }, /* Cent sign */
+ { ISFUNC, rl_insert }, /* Pound sign */
+ { ISFUNC, rl_insert }, /* Currency sign */
+ { ISFUNC, rl_insert }, /* Yen sign */
+ { ISFUNC, rl_insert }, /* Broken bar */
+ { ISFUNC, rl_insert }, /* Section sign */
+ { ISFUNC, rl_insert }, /* Diaeresis */
+ { ISFUNC, rl_insert }, /* Copyright sign */
+ { ISFUNC, rl_insert }, /* Feminine ordinal indicator */
+ { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */
+ { ISFUNC, rl_insert }, /* Not sign */
+ { ISFUNC, rl_insert }, /* Soft hyphen */
+ { ISFUNC, rl_insert }, /* Registered sign */
+ { ISFUNC, rl_insert }, /* Macron */
+ { ISFUNC, rl_insert }, /* Degree sign */
+ { ISFUNC, rl_insert }, /* Plus-minus sign */
+ { ISFUNC, rl_insert }, /* Superscript two */
+ { ISFUNC, rl_insert }, /* Superscript three */
+ { ISFUNC, rl_insert }, /* Acute accent */
+ { ISFUNC, rl_insert }, /* Micro sign */
+ { ISFUNC, rl_insert }, /* Pilcrow sign */
+ { ISFUNC, rl_insert }, /* Middle dot */
+ { ISFUNC, rl_insert }, /* Cedilla */
+ { ISFUNC, rl_insert }, /* Superscript one */
+ { ISFUNC, rl_insert }, /* Masculine ordinal indicator */
+ { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */
+ { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */
+ { ISFUNC, rl_insert }, /* Vulgar fraction one half */
+ { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */
+ { ISFUNC, rl_insert }, /* Inverted questionk mark */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */
+ { ISFUNC, rl_insert }, /* Latin capital letter ae */
+ { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */
+ { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */
+ { ISFUNC, rl_insert }, /* Multiplication sign */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */
+ { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */
+ { ISFUNC, rl_insert }, /* Latin small letter a with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter a with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter a with tilde */
+ { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter a with ring above */
+ { ISFUNC, rl_insert }, /* Latin small letter ae */
+ { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */
+ { ISFUNC, rl_insert }, /* Latin small letter e with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter e with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter i with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter i with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */
+ { ISFUNC, rl_insert }, /* Latin small letter n with tilde */
+ { ISFUNC, rl_insert }, /* Latin small letter o with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter o with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter o with tilde */
+ { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */
+ { ISFUNC, rl_insert }, /* Division sign */
+ { ISFUNC, rl_insert }, /* Latin small letter o with stroke */
+ { ISFUNC, rl_insert }, /* Latin small letter u with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter u with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter y with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */
+ { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
+
+ /* Meta keys. Just like above, but the high bit is set. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-@ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-a */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-c */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-d */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-e */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-f */
+ { ISFUNC, rl_abort }, /* Meta-Control-g */
+ { ISFUNC, rl_backward_kill_word }, /* Meta-Control-h */
+ { ISFUNC, rl_tab_insert }, /* Meta-Control-i */
+ { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-k */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-l */
+ { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-o */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-q */
+ { ISFUNC, rl_revert_line }, /* Meta-Control-r */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-s */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-t */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-v */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-w */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-x */
+ { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-z */
+
+ { ISFUNC, rl_complete }, /* Meta-Control-[ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-\ */
+ { ISFUNC, rl_backward_char_search }, /* Meta-Control-] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-^ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-_ */
+
+ /* The start of printing characters. */
+ { ISFUNC, rl_set_mark }, /* Meta-SPACE */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-! */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-" */
+ { ISFUNC, rl_insert_comment }, /* Meta-# */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-$ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-% */
+ { ISFUNC, rl_tilde_expand }, /* Meta-& */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-' */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-( */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-) */
+ { ISFUNC, rl_insert_completions }, /* Meta-* */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-+ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-, */
+ { ISFUNC, rl_digit_argument }, /* Meta-- */
+ { ISFUNC, rl_yank_last_arg}, /* Meta-. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-/ */
+
+ /* Regular digits. */
+ { ISFUNC, rl_digit_argument }, /* Meta-0 */
+ { ISFUNC, rl_digit_argument }, /* Meta-1 */
+ { ISFUNC, rl_digit_argument }, /* Meta-2 */
+ { ISFUNC, rl_digit_argument }, /* Meta-3 */
+ { ISFUNC, rl_digit_argument }, /* Meta-4 */
+ { ISFUNC, rl_digit_argument }, /* Meta-5 */
+ { ISFUNC, rl_digit_argument }, /* Meta-6 */
+ { ISFUNC, rl_digit_argument }, /* Meta-7 */
+ { ISFUNC, rl_digit_argument }, /* Meta-8 */
+ { ISFUNC, rl_digit_argument }, /* Meta-9 */
+
+ /* A little more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-: */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-; */
+ { ISFUNC, rl_beginning_of_history }, /* Meta-< */
+ { ISFUNC, rl_possible_completions }, /* Meta-= */
+ { ISFUNC, rl_end_of_history }, /* Meta-> */
+ { ISFUNC, rl_possible_completions }, /* Meta-? */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-@ */
+
+ /* Uppercase alphabet. */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-A */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-B */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-C */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-D */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-E */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-F */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-G */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-H */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-I */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-J */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-K */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-L */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-M */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-N */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-O */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-P */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-R */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-S */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-T */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-U */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-V */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-W */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-X */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */
+ { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
+
+ /* Some more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */
+ { ISFUNC, rl_delete_horizontal_space }, /* Meta-\ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-^ */
+ { ISFUNC, rl_yank_last_arg }, /* Meta-_ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-` */
+
+ /* Lowercase alphabet. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-a */
+ { ISFUNC, rl_backward_word }, /* Meta-b */
+ { ISFUNC, rl_capitalize_word }, /* Meta-c */
+ { ISFUNC, rl_kill_word }, /* Meta-d */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-e */
+ { ISFUNC, rl_forward_word }, /* Meta-f */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-g */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-h */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-i */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-j */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-k */
+ { ISFUNC, rl_downcase_word }, /* Meta-l */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-m */
+ { ISFUNC, rl_noninc_forward_search }, /* Meta-n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */
+ { ISFUNC, rl_noninc_reverse_search }, /* Meta-p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-q */
+ { ISFUNC, rl_revert_line }, /* Meta-r */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-s */
+ { ISFUNC, rl_transpose_words }, /* Meta-t */
+ { ISFUNC, rl_upcase_word }, /* Meta-u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-v */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-w */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-x */
+ { ISFUNC, rl_yank_pop }, /* Meta-y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-z */
+
+ /* Final punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-{ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-| */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-} */
+ { ISFUNC, rl_tilde_expand }, /* Meta-~ */
+ { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */
+
+#if KEYMAP_SIZE > 128
+ /* Undefined keys. */
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
+
+ /* Control keys. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */
+ { ISFUNC, rl_abort }, /* Control-g */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-j */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-k */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-m */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */
+ { ISFUNC, rl_re_read_init_file }, /* Control-r */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */
+ { ISFUNC, rl_undo_command }, /* Control-u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */
+ { ISFUNC, rl_exchange_point_and_mark }, /* Control-x */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-_ */
+
+ /* The start of printing characters. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* " */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* # */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* % */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* & */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */
+ { ISFUNC, rl_start_kbd_macro }, /* ( */
+ { ISFUNC, rl_end_kbd_macro }, /* ) */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* * */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* + */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* , */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* - */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* . */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* / */
+
+ /* Regular digits. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 0 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 1 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 2 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 3 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 4 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 5 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 6 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 7 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 8 */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* 9 */
+
+ /* A little more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* : */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* < */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* = */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* > */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */
+
+ /* Uppercase alphabet. */
+ { ISFUNC, rl_do_lowercase_version }, /* A */
+ { ISFUNC, rl_do_lowercase_version }, /* B */
+ { ISFUNC, rl_do_lowercase_version }, /* C */
+ { ISFUNC, rl_do_lowercase_version }, /* D */
+ { ISFUNC, rl_do_lowercase_version }, /* E */
+ { ISFUNC, rl_do_lowercase_version }, /* F */
+ { ISFUNC, rl_do_lowercase_version }, /* G */
+ { ISFUNC, rl_do_lowercase_version }, /* H */
+ { ISFUNC, rl_do_lowercase_version }, /* I */
+ { ISFUNC, rl_do_lowercase_version }, /* J */
+ { ISFUNC, rl_do_lowercase_version }, /* K */
+ { ISFUNC, rl_do_lowercase_version }, /* L */
+ { ISFUNC, rl_do_lowercase_version }, /* M */
+ { ISFUNC, rl_do_lowercase_version }, /* N */
+ { ISFUNC, rl_do_lowercase_version }, /* O */
+ { ISFUNC, rl_do_lowercase_version }, /* P */
+ { ISFUNC, rl_do_lowercase_version }, /* Q */
+ { ISFUNC, rl_do_lowercase_version }, /* R */
+ { ISFUNC, rl_do_lowercase_version }, /* S */
+ { ISFUNC, rl_do_lowercase_version }, /* T */
+ { ISFUNC, rl_do_lowercase_version }, /* U */
+ { ISFUNC, rl_do_lowercase_version }, /* V */
+ { ISFUNC, rl_do_lowercase_version }, /* W */
+ { ISFUNC, rl_do_lowercase_version }, /* X */
+ { ISFUNC, rl_do_lowercase_version }, /* Y */
+ { ISFUNC, rl_do_lowercase_version }, /* Z */
+
+ /* Some more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */
+
+ /* Lowercase alphabet. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* a */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* c */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* d */
+ { ISFUNC, rl_call_last_kbd_macro }, /* e */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* f */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* g */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* h */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* i */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* j */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* k */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* l */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* m */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* o */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* q */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* r */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* s */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* t */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* v */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* w */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* x */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* z */
+
+ /* Final punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* { */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* | */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* } */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */
+ { ISFUNC, rl_backward_kill_line }, /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+ /* Undefined keys. */
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
diff --git a/cmd-line-utils/readline/funmap.c b/cmd-line-utils/readline/funmap.c
new file mode 100644
index 00000000000..fe9a1da43d7
--- /dev/null
+++ b/cmd-line-utils/readline/funmap.c
@@ -0,0 +1,253 @@
+/* funmap.c -- attach names to functions. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* BUFSIZ */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "rlconf.h"
+#include "readline.h"
+
+#include "xmalloc.h"
+
+#ifdef __STDC__
+typedef int QSFUNC (const void *, const void *);
+#else
+typedef int QSFUNC ();
+#endif
+
+extern int _rl_qsort_string_compare PARAMS((char **, char **));
+
+FUNMAP **funmap;
+static int funmap_size;
+static int funmap_entry;
+
+/* After initializing the function map, this is the index of the first
+ program specific function. */
+int funmap_program_specific_entry_start;
+
+static FUNMAP default_funmap[] = {
+ { "abort", rl_abort },
+ { "accept-line", rl_newline },
+ { "arrow-key-prefix", rl_arrow_keys },
+ { "backward-byte", rl_backward_byte },
+ { "backward-char", rl_backward_char },
+ { "backward-delete-char", rl_rubout },
+ { "backward-kill-line", rl_backward_kill_line },
+ { "backward-kill-word", rl_backward_kill_word },
+ { "backward-word", rl_backward_word },
+ { "beginning-of-history", rl_beginning_of_history },
+ { "beginning-of-line", rl_beg_of_line },
+ { "call-last-kbd-macro", rl_call_last_kbd_macro },
+ { "capitalize-word", rl_capitalize_word },
+ { "character-search", rl_char_search },
+ { "character-search-backward", rl_backward_char_search },
+ { "clear-screen", rl_clear_screen },
+ { "complete", rl_complete },
+ { "copy-backward-word", rl_copy_backward_word },
+ { "copy-forward-word", rl_copy_forward_word },
+ { "copy-region-as-kill", rl_copy_region_to_kill },
+ { "delete-char", rl_delete },
+ { "delete-char-or-list", rl_delete_or_show_completions },
+ { "delete-horizontal-space", rl_delete_horizontal_space },
+ { "digit-argument", rl_digit_argument },
+ { "do-lowercase-version", rl_do_lowercase_version },
+ { "downcase-word", rl_downcase_word },
+ { "dump-functions", rl_dump_functions },
+ { "dump-macros", rl_dump_macros },
+ { "dump-variables", rl_dump_variables },
+ { "emacs-editing-mode", rl_emacs_editing_mode },
+ { "end-kbd-macro", rl_end_kbd_macro },
+ { "end-of-history", rl_end_of_history },
+ { "end-of-line", rl_end_of_line },
+ { "exchange-point-and-mark", rl_exchange_point_and_mark },
+ { "forward-backward-delete-char", rl_rubout_or_delete },
+ { "forward-byte", rl_forward_byte },
+ { "forward-char", rl_forward_char },
+ { "forward-search-history", rl_forward_search_history },
+ { "forward-word", rl_forward_word },
+ { "history-search-backward", rl_history_search_backward },
+ { "history-search-forward", rl_history_search_forward },
+ { "insert-comment", rl_insert_comment },
+ { "insert-completions", rl_insert_completions },
+ { "kill-whole-line", rl_kill_full_line },
+ { "kill-line", rl_kill_line },
+ { "kill-region", rl_kill_region },
+ { "kill-word", rl_kill_word },
+ { "menu-complete", rl_menu_complete },
+ { "next-history", rl_get_next_history },
+ { "non-incremental-forward-search-history", rl_noninc_forward_search },
+ { "non-incremental-reverse-search-history", rl_noninc_reverse_search },
+ { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
+ { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
+ { "overwrite-mode", rl_overwrite_mode },
+#ifdef __CYGWIN__
+ { "paste-from-clipboard", rl_paste_from_clipboard },
+#endif
+ { "possible-completions", rl_possible_completions },
+ { "previous-history", rl_get_previous_history },
+ { "quoted-insert", rl_quoted_insert },
+ { "re-read-init-file", rl_re_read_init_file },
+ { "redraw-current-line", rl_refresh_line},
+ { "reverse-search-history", rl_reverse_search_history },
+ { "revert-line", rl_revert_line },
+ { "self-insert", rl_insert },
+ { "set-mark", rl_set_mark },
+ { "start-kbd-macro", rl_start_kbd_macro },
+ { "tab-insert", rl_tab_insert },
+ { "tilde-expand", rl_tilde_expand },
+ { "transpose-chars", rl_transpose_chars },
+ { "transpose-words", rl_transpose_words },
+ { "tty-status", rl_tty_status },
+ { "undo", rl_undo_command },
+ { "universal-argument", rl_universal_argument },
+ { "unix-line-discard", rl_unix_line_discard },
+ { "unix-word-rubout", rl_unix_word_rubout },
+ { "upcase-word", rl_upcase_word },
+ { "yank", rl_yank },
+ { "yank-last-arg", rl_yank_last_arg },
+ { "yank-nth-arg", rl_yank_nth_arg },
+ { "yank-pop", rl_yank_pop },
+
+#if defined (VI_MODE)
+ { "vi-append-eol", rl_vi_append_eol },
+ { "vi-append-mode", rl_vi_append_mode },
+ { "vi-arg-digit", rl_vi_arg_digit },
+ { "vi-back-to-indent", rl_vi_back_to_indent },
+ { "vi-bWord", rl_vi_bWord },
+ { "vi-bword", rl_vi_bword },
+ { "vi-change-case", rl_vi_change_case },
+ { "vi-change-char", rl_vi_change_char },
+ { "vi-change-to", rl_vi_change_to },
+ { "vi-char-search", rl_vi_char_search },
+ { "vi-column", rl_vi_column },
+ { "vi-complete", rl_vi_complete },
+ { "vi-delete", rl_vi_delete },
+ { "vi-delete-to", rl_vi_delete_to },
+ { "vi-eWord", rl_vi_eWord },
+ { "vi-editing-mode", rl_vi_editing_mode },
+ { "vi-end-word", rl_vi_end_word },
+ { "vi-eof-maybe", rl_vi_eof_maybe },
+ { "vi-eword", rl_vi_eword },
+ { "vi-fWord", rl_vi_fWord },
+ { "vi-fetch-history", rl_vi_fetch_history },
+ { "vi-first-print", rl_vi_first_print },
+ { "vi-fword", rl_vi_fword },
+ { "vi-goto-mark", rl_vi_goto_mark },
+ { "vi-insert-beg", rl_vi_insert_beg },
+ { "vi-insertion-mode", rl_vi_insertion_mode },
+ { "vi-match", rl_vi_match },
+ { "vi-movement-mode", rl_vi_movement_mode },
+ { "vi-next-word", rl_vi_next_word },
+ { "vi-overstrike", rl_vi_overstrike },
+ { "vi-overstrike-delete", rl_vi_overstrike_delete },
+ { "vi-prev-word", rl_vi_prev_word },
+ { "vi-put", rl_vi_put },
+ { "vi-redo", rl_vi_redo },
+ { "vi-replace", rl_vi_replace },
+ { "vi-search", rl_vi_search },
+ { "vi-search-again", rl_vi_search_again },
+ { "vi-set-mark", rl_vi_set_mark },
+ { "vi-subst", rl_vi_subst },
+ { "vi-tilde-expand", rl_vi_tilde_expand },
+ { "vi-yank-arg", rl_vi_yank_arg },
+ { "vi-yank-to", rl_vi_yank_to },
+#endif /* VI_MODE */
+
+ {(char *)NULL, (rl_command_func_t *)NULL }
+};
+
+int
+rl_add_funmap_entry (name, function)
+ const char *name;
+ rl_command_func_t *function;
+{
+ if (funmap_entry + 2 >= funmap_size)
+ {
+ funmap_size += 64;
+ funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *));
+ }
+
+ funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
+ funmap[funmap_entry]->name = name;
+ funmap[funmap_entry]->function = function;
+
+ funmap[++funmap_entry] = (FUNMAP *)NULL;
+ return funmap_entry;
+}
+
+static int funmap_initialized;
+
+/* Make the funmap contain all of the default entries. */
+void
+rl_initialize_funmap ()
+{
+ register int i;
+
+ if (funmap_initialized)
+ return;
+
+ for (i = 0; default_funmap[i].name; i++)
+ rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
+
+ funmap_initialized = 1;
+ funmap_program_specific_entry_start = i;
+}
+
+/* Produce a NULL terminated array of known function names. The array
+ is sorted. The array itself is allocated, but not the strings inside.
+ You should free () the array when you done, but not the pointrs. */
+const char **
+rl_funmap_names ()
+{
+ const char **result;
+ int result_size, result_index;
+
+ /* Make sure that the function map has been initialized. */
+ rl_initialize_funmap ();
+
+ for (result_index = result_size = 0, result = (const char **)NULL; funmap[result_index]; result_index++)
+ {
+ if (result_index + 2 > result_size)
+ {
+ result_size += 20;
+ result = (const char **)xrealloc (result, result_size * sizeof (char *));
+ }
+
+ result[result_index] = funmap[result_index]->name;
+ result[result_index + 1] = (char *)NULL;
+ }
+
+ qsort (result, result_index, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
+ return (result);
+}
diff --git a/cmd-line-utils/readline/histexpand.c b/cmd-line-utils/readline/histexpand.c
new file mode 100644
index 00000000000..f01d54c5b1d
--- /dev/null
+++ b/cmd-line-utils/readline/histexpand.c
@@ -0,0 +1,1491 @@
+/* histexpand.c -- history expansion. */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file contains the GNU History Library (the Library), a set of
+ routines for managing the text of previously typed lines.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+# ifndef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include "rlmbutil.h"
+
+#include "history.h"
+#include "histlib.h"
+
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
+#define HISTORY_QUOTE_CHARACTERS "\"'`"
+
+typedef int _hist_search_func_t PARAMS((const char *, int));
+
+extern int rl_byte_oriented; /* declared in mbutil.c */
+
+static char error_pointer;
+
+static char *subst_lhs;
+static char *subst_rhs;
+static int subst_lhs_len;
+static int subst_rhs_len;
+
+static char *get_history_word_specifier PARAMS((char *, char *, int *));
+static char *history_find_word PARAMS((char *, int));
+
+static char *quote_breaks PARAMS((char *));
+
+/* Variables exported by this file. */
+/* The character that represents the start of a history expansion
+ request. This is usually `!'. */
+char history_expansion_char = '!';
+
+/* The character that invokes word substitution if found at the start of
+ a line. This is usually `^'. */
+char history_subst_char = '^';
+
+/* During tokenization, if this character is seen as the first character
+ of a word, then it, and all subsequent characters upto a newline are
+ ignored. For a Bourne shell, this should be '#'. Bash special cases
+ the interactive comment character to not be a comment delimiter. */
+char history_comment_char = '\0';
+
+/* The list of characters which inhibit the expansion of text if found
+ immediately following history_expansion_char. */
+const char *history_no_expand_chars = " \t\n\r=";
+
+/* If set to a non-zero value, single quotes inhibit history expansion.
+ The default is 0. */
+int history_quotes_inhibit_expansion = 0;
+
+/* Used to split words by history_tokenize_internal. */
+const char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
+
+/* If set, this points to a function that is called to verify that a
+ particular history expansion should be performed. */
+rl_linebuf_func_t *history_inhibit_expansion_function;
+
+/* **************************************************************** */
+/* */
+/* History Expansion */
+/* */
+/* **************************************************************** */
+
+/* Hairy history expansion on text, not tokens. This is of general
+ use, and thus belongs in this library. */
+
+/* The last string searched for by a !?string? search. */
+static char *search_string;
+
+/* The last string matched by a !?string? search. */
+static char *search_match;
+
+/* Return the event specified at TEXT + OFFSET modifying OFFSET to
+ point to after the event specifier. Just a pointer to the history
+ line is returned; NULL is returned in the event of a bad specifier.
+ You pass STRING with *INDEX equal to the history_expansion_char that
+ begins this specification.
+ DELIMITING_QUOTE is a character that is allowed to end the string
+ specification for what to search for in addition to the normal
+ characters `:', ` ', `\t', `\n', and sometimes `?'.
+ So you might call this function like:
+ line = get_history_event ("!echo:p", &index, 0); */
+char *
+get_history_event (string, caller_index, delimiting_quote)
+ const char *string;
+ int *caller_index;
+ int delimiting_quote;
+{
+ register int i;
+ register char c;
+ HIST_ENTRY *entry;
+ int which, sign, local_index, substring_okay;
+ _hist_search_func_t *search_func;
+ char *temp;
+
+ /* The event can be specified in a number of ways.
+
+ !! the previous command
+ !n command line N
+ !-n current command-line minus N
+ !str the most recent command starting with STR
+ !?str[?]
+ the most recent command containing STR
+
+ All values N are determined via HISTORY_BASE. */
+
+ i = *caller_index;
+
+ if (string[i] != history_expansion_char)
+ return ((char *)NULL);
+
+ /* Move on to the specification. */
+ i++;
+
+ sign = 1;
+ substring_okay = 0;
+
+#define RETURN_ENTRY(e, w) \
+ return ((e = history_get (w)) ? e->line : (char *)NULL)
+
+ /* Handle !! case. */
+ if (string[i] == history_expansion_char)
+ {
+ i++;
+ which = history_base + (history_length - 1);
+ *caller_index = i;
+ RETURN_ENTRY (entry, which);
+ }
+
+ /* Hack case of numeric line specification. */
+ if (string[i] == '-')
+ {
+ sign = -1;
+ i++;
+ }
+
+ if (_rl_digit_p (string[i]))
+ {
+ /* Get the extent of the digits and compute the value. */
+ for (which = 0; _rl_digit_p (string[i]); i++)
+ which = (which * 10) + _rl_digit_value (string[i]);
+
+ *caller_index = i;
+
+ if (sign < 0)
+ which = (history_length + history_base) - which;
+
+ RETURN_ENTRY (entry, which);
+ }
+
+ /* This must be something to search for. If the spec begins with
+ a '?', then the string may be anywhere on the line. Otherwise,
+ the string must be found at the start of a line. */
+ if (string[i] == '?')
+ {
+ substring_okay++;
+ i++;
+ }
+
+ /* Only a closing `?' or a newline delimit a substring search string. */
+ for (local_index = i; (c = string[i]); i++)
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int v;
+ mbstate_t ps;
+
+ memset (&ps, 0, sizeof (mbstate_t));
+ /* These produce warnings because we're passing a const string to a
+ function that takes a non-const string. */
+ _rl_adjust_point (string, i, &ps);
+ if ((v = _rl_get_char_len (string + i, &ps)) > 1)
+ {
+ i += v - 1;
+ continue;
+ }
+ }
+ else
+#endif /* HANDLE_MULTIBYTE */
+ if ((!substring_okay && (whitespace (c) || c == ':' ||
+ (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
+ string[i] == delimiting_quote)) ||
+ string[i] == '\n' ||
+ (substring_okay && string[i] == '?'))
+ break;
+
+ which = i - local_index;
+ temp = (char *)xmalloc (1 + which);
+ if (which)
+ strncpy (temp, string + local_index, which);
+ temp[which] = '\0';
+
+ if (substring_okay && string[i] == '?')
+ i++;
+
+ *caller_index = i;
+
+#define FAIL_SEARCH() \
+ do { \
+ history_offset = history_length; free (temp) ; return (char *)NULL; \
+ } while (0)
+
+ /* If there is no search string, try to use the previous search string,
+ if one exists. If not, fail immediately. */
+ if (*temp == '\0' && substring_okay)
+ {
+ if (search_string)
+ {
+ free (temp);
+ temp = savestring (search_string);
+ }
+ else
+ FAIL_SEARCH ();
+ }
+
+ search_func = substring_okay ? history_search : history_search_prefix;
+ while (1)
+ {
+ local_index = (*search_func) (temp, -1);
+
+ if (local_index < 0)
+ FAIL_SEARCH ();
+
+ if (local_index == 0 || substring_okay)
+ {
+ entry = current_history ();
+ history_offset = history_length;
+
+ /* If this was a substring search, then remember the
+ string that we matched for word substitution. */
+ if (substring_okay)
+ {
+ FREE (search_string);
+ search_string = temp;
+
+ FREE (search_match);
+ search_match = history_find_word (entry->line, local_index);
+ }
+ else
+ free (temp);
+
+ return (entry->line);
+ }
+
+ if (history_offset)
+ history_offset--;
+ else
+ FAIL_SEARCH ();
+ }
+#undef FAIL_SEARCH
+#undef RETURN_ENTRY
+}
+
+/* Function for extracting single-quoted strings. Used for inhibiting
+ history expansion within single quotes. */
+
+/* Extract the contents of STRING as if it is enclosed in single quotes.
+ SINDEX, when passed in, is the offset of the character immediately
+ following the opening single quote; on exit, SINDEX is left pointing
+ to the closing single quote. */
+static void
+hist_string_extract_single_quoted (string, sindex)
+ char *string;
+ int *sindex;
+{
+ register int i;
+
+ for (i = *sindex; string[i] && string[i] != '\''; i++)
+ ;
+
+ *sindex = i;
+}
+
+static char *
+quote_breaks (s)
+ char *s;
+{
+ register char *p, *r;
+ char *ret;
+ int len = 3;
+
+ for (p = s; p && *p; p++, len++)
+ {
+ if (*p == '\'')
+ len += 3;
+ else if (whitespace (*p) || *p == '\n')
+ len += 2;
+ }
+
+ r = ret = (char *)xmalloc (len);
+ *r++ = '\'';
+ for (p = s; p && *p; )
+ {
+ if (*p == '\'')
+ {
+ *r++ = '\'';
+ *r++ = '\\';
+ *r++ = '\'';
+ *r++ = '\'';
+ p++;
+ }
+ else if (whitespace (*p) || *p == '\n')
+ {
+ *r++ = '\'';
+ *r++ = *p++;
+ *r++ = '\'';
+ }
+ else
+ *r++ = *p++;
+ }
+ *r++ = '\'';
+ *r = '\0';
+ return ret;
+}
+
+static char *
+hist_error(s, start, current, errtype)
+ char *s;
+ int start, current, errtype;
+{
+ char *temp;
+ const char *emsg;
+ int ll, elen;
+
+ ll = current - start;
+
+ switch (errtype)
+ {
+ case EVENT_NOT_FOUND:
+ emsg = "event not found";
+ elen = 15;
+ break;
+ case BAD_WORD_SPEC:
+ emsg = "bad word specifier";
+ elen = 18;
+ break;
+ case SUBST_FAILED:
+ emsg = "substitution failed";
+ elen = 19;
+ break;
+ case BAD_MODIFIER:
+ emsg = "unrecognized history modifier";
+ elen = 29;
+ break;
+ case NO_PREV_SUBST:
+ emsg = "no previous substitution";
+ elen = 24;
+ break;
+ default:
+ emsg = "unknown expansion error";
+ elen = 23;
+ break;
+ }
+
+ temp = (char *)xmalloc (ll + elen + 3);
+ strncpy (temp, s + start, ll);
+ temp[ll] = ':';
+ temp[ll + 1] = ' ';
+ strcpy (temp + ll + 2, emsg);
+ return (temp);
+}
+
+/* Get a history substitution string from STR starting at *IPTR
+ and return it. The length is returned in LENPTR.
+
+ A backslash can quote the delimiter. If the string is the
+ empty string, the previous pattern is used. If there is
+ no previous pattern for the lhs, the last history search
+ string is used.
+
+ If IS_RHS is 1, we ignore empty strings and set the pattern
+ to "" anyway. subst_lhs is not changed if the lhs is empty;
+ subst_rhs is allowed to be set to the empty string. */
+
+static char *
+get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
+ char *str;
+ int *iptr, delimiter, is_rhs, *lenptr;
+{
+ register int si, i, j, k;
+ char *s;
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t ps;
+#endif
+
+ s = (char *)NULL;
+ i = *iptr;
+
+#if defined (HANDLE_MULTIBYTE)
+ memset (&ps, 0, sizeof (mbstate_t));
+ _rl_adjust_point (str, i, &ps);
+#endif
+
+ for (si = i; str[si] && str[si] != delimiter; si++)
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int v;
+ if ((v = _rl_get_char_len (str + si, &ps)) > 1)
+ si += v - 1;
+ else if (str[si] == '\\' && str[si + 1] == delimiter)
+ si++;
+ }
+ else
+#endif /* HANDLE_MULTIBYTE */
+ if (str[si] == '\\' && str[si + 1] == delimiter)
+ si++;
+
+ if (si > i || is_rhs)
+ {
+ s = (char *)xmalloc (si - i + 1);
+ for (j = 0, k = i; k < si; j++, k++)
+ {
+ /* Remove a backslash quoting the search string delimiter. */
+ if (str[k] == '\\' && str[k + 1] == delimiter)
+ k++;
+ s[j] = str[k];
+ }
+ s[j] = '\0';
+ if (lenptr)
+ *lenptr = j;
+ }
+
+ i = si;
+ if (str[i])
+ i++;
+ *iptr = i;
+
+ return s;
+}
+
+static void
+postproc_subst_rhs ()
+{
+ char *new;
+ int i, j, new_size;
+
+ new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
+ for (i = j = 0; i < subst_rhs_len; i++)
+ {
+ if (subst_rhs[i] == '&')
+ {
+ if (j + subst_lhs_len >= new_size)
+ new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
+ strcpy (new + j, subst_lhs);
+ j += subst_lhs_len;
+ }
+ else
+ {
+ /* a single backslash protects the `&' from lhs interpolation */
+ if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
+ i++;
+ if (j >= new_size)
+ new = (char *)xrealloc (new, new_size *= 2);
+ new[j++] = subst_rhs[i];
+ }
+ }
+ new[j] = '\0';
+ free (subst_rhs);
+ subst_rhs = new;
+ subst_rhs_len = j;
+}
+
+/* Expand the bulk of a history specifier starting at STRING[START].
+ Returns 0 if everything is OK, -1 if an error occurred, and 1
+ if the `p' modifier was supplied and the caller should just print
+ the returned string. Returns the new index into string in
+ *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
+static int
+history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
+ char *string;
+ int start, *end_index_ptr;
+ char **ret_string;
+ char *current_line; /* for !# */
+{
+ int i, n, starting_index;
+ int substitute_globally, want_quotes, print_only;
+ char *event, *temp, *result, *tstr, *t, c, *word_spec;
+ int result_len;
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t ps;
+
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+ result = (char *)xmalloc (result_len = 128);
+
+ i = start;
+
+ /* If it is followed by something that starts a word specifier,
+ then !! is implied as the event specifier. */
+
+ if (member (string[i + 1], ":$*%^"))
+ {
+ char fake_s[3];
+ int fake_i = 0;
+ i++;
+ fake_s[0] = fake_s[1] = history_expansion_char;
+ fake_s[2] = '\0';
+ event = get_history_event (fake_s, &fake_i, 0);
+ }
+ else if (string[i + 1] == '#')
+ {
+ i += 2;
+ event = current_line;
+ }
+ else
+ {
+ int quoted_search_delimiter = 0;
+
+ /* If the character before this `!' is a double or single
+ quote, then this expansion takes place inside of the
+ quoted string. If we have to search for some text ("!foo"),
+ allow the delimiter to end the search string. */
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int c, l;
+ l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
+ c = string[l];
+ /* XXX - original patch had i - 1 ??? If i == 0 it would fail. */
+ if (i && (c == '\'' || c == '"'))
+ quoted_search_delimiter = c;
+ }
+ else
+#endif /* HANDLE_MULTIBYTE */
+ if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
+ quoted_search_delimiter = string[i - 1];
+
+ event = get_history_event (string, &i, quoted_search_delimiter);
+ }
+
+ if (event == 0)
+ {
+ *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
+ free (result);
+ return (-1);
+ }
+
+ /* If a word specifier is found, then do what that requires. */
+ starting_index = i;
+ word_spec = get_history_word_specifier (string, event, &i);
+
+ /* There is no such thing as a `malformed word specifier'. However,
+ it is possible for a specifier that has no match. In that case,
+ we complain. */
+ if (word_spec == (char *)&error_pointer)
+ {
+ *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
+ free (result);
+ return (-1);
+ }
+
+ /* If no word specifier, than the thing of interest was the event. */
+ temp = word_spec ? savestring (word_spec) : savestring (event);
+ FREE (word_spec);
+
+ /* Perhaps there are other modifiers involved. Do what they say. */
+ want_quotes = substitute_globally = print_only = 0;
+ starting_index = i;
+
+ while (string[i] == ':')
+ {
+ c = string[i + 1];
+
+ if (c == 'g')
+ {
+ substitute_globally = 1;
+ i++;
+ c = string[i + 1];
+ }
+
+ switch (c)
+ {
+ default:
+ *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
+ free (result);
+ free (temp);
+ return -1;
+
+ case 'q':
+ want_quotes = 'q';
+ break;
+
+ case 'x':
+ want_quotes = 'x';
+ break;
+
+ /* :p means make this the last executed line. So we
+ return an error state after adding this line to the
+ history. */
+ case 'p':
+ print_only++;
+ break;
+
+ /* :t discards all but the last part of the pathname. */
+ case 't':
+ tstr = strrchr (temp, '/');
+ if (tstr)
+ {
+ tstr++;
+ t = savestring (tstr);
+ free (temp);
+ temp = t;
+ }
+ break;
+
+ /* :h discards the last part of a pathname. */
+ case 'h':
+ tstr = strrchr (temp, '/');
+ if (tstr)
+ *tstr = '\0';
+ break;
+
+ /* :r discards the suffix. */
+ case 'r':
+ tstr = strrchr (temp, '.');
+ if (tstr)
+ *tstr = '\0';
+ break;
+
+ /* :e discards everything but the suffix. */
+ case 'e':
+ tstr = strrchr (temp, '.');
+ if (tstr)
+ {
+ t = savestring (tstr);
+ free (temp);
+ temp = t;
+ }
+ break;
+
+ /* :s/this/that substitutes `that' for the first
+ occurrence of `this'. :gs/this/that substitutes `that'
+ for each occurrence of `this'. :& repeats the last
+ substitution. :g& repeats the last substitution
+ globally. */
+
+ case '&':
+ case 's':
+ {
+ char *new_event;
+ int delimiter, failed, si, l_temp;
+
+ if (c == 's')
+ {
+ if (i + 2 < (int)strlen (string))
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ _rl_adjust_point (string, i + 2, &ps);
+ if (_rl_get_char_len (string + i + 2, &ps) > 1)
+ delimiter = 0;
+ else
+ delimiter = string[i + 2];
+ }
+ else
+#endif /* HANDLE_MULTIBYTE */
+ delimiter = string[i + 2];
+ }
+ else
+ break; /* no search delimiter */
+
+ i += 3;
+
+ t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
+ /* An empty substitution lhs with no previous substitution
+ uses the last search string as the lhs. */
+ if (t)
+ {
+ FREE (subst_lhs);
+ subst_lhs = t;
+ }
+ else if (!subst_lhs)
+ {
+ if (search_string && *search_string)
+ {
+ subst_lhs = savestring (search_string);
+ subst_lhs_len = strlen (subst_lhs);
+ }
+ else
+ {
+ subst_lhs = (char *) NULL;
+ subst_lhs_len = 0;
+ }
+ }
+
+ FREE (subst_rhs);
+ subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
+
+ /* If `&' appears in the rhs, it's supposed to be replaced
+ with the lhs. */
+ if (member ('&', subst_rhs))
+ postproc_subst_rhs ();
+ }
+ else
+ i += 2;
+
+ /* If there is no lhs, the substitution can't succeed. */
+ if (subst_lhs_len == 0)
+ {
+ *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
+ free (result);
+ free (temp);
+ return -1;
+ }
+
+ l_temp = strlen (temp);
+ /* Ignore impossible cases. */
+ if (subst_lhs_len > l_temp)
+ {
+ *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+ free (result);
+ free (temp);
+ return (-1);
+ }
+
+ /* Find the first occurrence of THIS in TEMP. */
+ si = 0;
+ for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
+ if (STREQN (temp+si, subst_lhs, subst_lhs_len))
+ {
+ int len = subst_rhs_len - subst_lhs_len + l_temp;
+ new_event = (char *)xmalloc (1 + len);
+ strncpy (new_event, temp, si);
+ strncpy (new_event + si, subst_rhs, subst_rhs_len);
+ strncpy (new_event + si + subst_rhs_len,
+ temp + si + subst_lhs_len,
+ l_temp - (si + subst_lhs_len));
+ new_event[len] = '\0';
+ free (temp);
+ temp = new_event;
+
+ failed = 0;
+
+ if (substitute_globally)
+ {
+ si += subst_rhs_len;
+ l_temp = strlen (temp);
+ substitute_globally++;
+ continue;
+ }
+ else
+ break;
+ }
+
+ if (substitute_globally > 1)
+ {
+ substitute_globally = 0;
+ continue; /* don't want to increment i */
+ }
+
+ if (failed == 0)
+ continue; /* don't want to increment i */
+
+ *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+ free (result);
+ free (temp);
+ return (-1);
+ }
+ }
+ i += 2;
+ }
+ /* Done with modfiers. */
+ /* Believe it or not, we have to back the pointer up by one. */
+ --i;
+
+ if (want_quotes)
+ {
+ char *x;
+
+ if (want_quotes == 'q')
+ x = sh_single_quote (temp);
+ else if (want_quotes == 'x')
+ x = quote_breaks (temp);
+ else
+ x = savestring (temp);
+
+ free (temp);
+ temp = x;
+ }
+
+ n = strlen (temp);
+ if (n >= result_len)
+ result = (char *)xrealloc (result, n + 2);
+ strcpy (result, temp);
+ free (temp);
+
+ *end_index_ptr = i;
+ *ret_string = result;
+ return (print_only);
+}
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+ to a string. Returns:
+
+ -1) If there was an error in expansion.
+ 0) If no expansions took place (or, if the only change in
+ the text was the de-slashifying of the history expansion
+ character)
+ 1) If expansions did take place
+ 2) If the `p' modifier was given and the caller should print the result
+
+ If an error ocurred in expansion, then OUTPUT contains a descriptive
+ error message. */
+
+#define ADD_STRING(s) \
+ do \
+ { \
+ int sl = strlen (s); \
+ j += sl; \
+ if (j >= result_len) \
+ { \
+ while (j >= result_len) \
+ result_len += 128; \
+ result = (char *)xrealloc (result, result_len); \
+ } \
+ strcpy (result + j - sl, s); \
+ } \
+ while (0)
+
+#define ADD_CHAR(c) \
+ do \
+ { \
+ if (j >= result_len - 1) \
+ result = (char *)xrealloc (result, result_len += 64); \
+ result[j++] = c; \
+ result[j] = '\0'; \
+ } \
+ while (0)
+
+int
+history_expand (hstring, output)
+ char *hstring;
+ char **output;
+{
+ register int j;
+ int i, r, l, passc, cc, modified, eindex, only_printing;
+ char *string;
+
+ /* The output string, and its length. */
+ int result_len;
+ char *result;
+
+#if defined (HANDLE_MULTIBYTE)
+ char mb[MB_LEN_MAX];
+ mbstate_t ps;
+#endif
+
+ /* Used when adding the string. */
+ char *temp;
+
+ if (output == 0)
+ return 0;
+
+ /* Setting the history expansion character to 0 inhibits all
+ history expansion. */
+ if (history_expansion_char == 0)
+ {
+ *output = savestring (hstring);
+ return (0);
+ }
+
+ /* Prepare the buffer for printing error messages. */
+ result = (char *)xmalloc (result_len = 256);
+ result[0] = '\0';
+
+ only_printing = modified = 0;
+ l = strlen (hstring);
+
+ /* Grovel the string. Only backslash and single quotes can quote the
+ history escape character. We also handle arg specifiers. */
+
+ /* Before we grovel forever, see if the history_expansion_char appears
+ anywhere within the text. */
+
+ /* The quick substitution character is a history expansion all right. That
+ is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
+ that is the substitution that we do. */
+ if (hstring[0] == history_subst_char)
+ {
+ string = (char *)xmalloc (l + 5);
+
+ string[0] = string[1] = history_expansion_char;
+ string[2] = ':';
+ string[3] = 's';
+ strcpy (string + 4, hstring);
+ l += 4;
+ }
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+ string = hstring;
+ /* If not quick substitution, still maybe have to do expansion. */
+
+ /* `!' followed by one of the characters in history_no_expand_chars
+ is NOT an expansion. */
+ for (i = 0; string[i]; i++)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int v;
+ v = _rl_get_char_len (string + i, &ps);
+ if (v > 1)
+ {
+ i += v - 1;
+ continue;
+ }
+ }
+#endif /* HANDLE_MULTIBYTE */
+
+ cc = string[i + 1];
+ /* The history_comment_char, if set, appearing at the beginning
+ of a word signifies that the rest of the line should not have
+ history expansion performed on it.
+ Skip the rest of the line and break out of the loop. */
+ if (history_comment_char && string[i] == history_comment_char &&
+ (i == 0 || member (string[i - 1], history_word_delimiters)))
+ {
+ while (string[i])
+ i++;
+ break;
+ }
+ else if (string[i] == history_expansion_char)
+ {
+ if (!cc || member (cc, history_no_expand_chars))
+ continue;
+ /* If the calling application has set
+ history_inhibit_expansion_function to a function that checks
+ for special cases that should not be history expanded,
+ call the function and skip the expansion if it returns a
+ non-zero value. */
+ else if (history_inhibit_expansion_function &&
+ (*history_inhibit_expansion_function) (string, i))
+ continue;
+ else
+ break;
+ }
+ /* XXX - at some point, might want to extend this to handle
+ double quotes as well. */
+ else if (history_quotes_inhibit_expansion && string[i] == '\'')
+ {
+ /* If this is bash, single quotes inhibit history expansion. */
+ i++;
+ hist_string_extract_single_quoted (string, &i);
+ }
+ else if (history_quotes_inhibit_expansion && string[i] == '\\')
+ {
+ /* If this is bash, allow backslashes to quote single
+ quotes and the history expansion character. */
+ if (cc == '\'' || cc == history_expansion_char)
+ i++;
+ }
+ }
+
+ if (string[i] != history_expansion_char)
+ {
+ free (result);
+ *output = savestring (string);
+ return (0);
+ }
+ }
+
+ /* Extract and perform the substitution. */
+ for (passc = i = j = 0; i < l; i++)
+ {
+ int tchar = string[i];
+
+ if (passc)
+ {
+ passc = 0;
+ ADD_CHAR (tchar);
+ continue;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int k, c;
+
+ c = tchar;
+ memset (mb, 0, sizeof (mb));
+ for (k = 0; k < MB_LEN_MAX; k++)
+ {
+ mb[k] = (char)c;
+ memset (&ps, 0, sizeof (mbstate_t));
+ if (_rl_get_char_len (mb, &ps) == -2)
+ c = string[++i];
+ else
+ break;
+ }
+ if (strlen (mb) > 1)
+ {
+ ADD_STRING (mb);
+ break;
+ }
+ }
+#endif /* HANDLE_MULTIBYTE */
+
+ if (tchar == history_expansion_char)
+ tchar = -3;
+ else if (tchar == history_comment_char)
+ tchar = -2;
+
+ switch (tchar)
+ {
+ default:
+ ADD_CHAR (string[i]);
+ break;
+
+ case '\\':
+ passc++;
+ ADD_CHAR (tchar);
+ break;
+
+ case '\'':
+ {
+ /* If history_quotes_inhibit_expansion is set, single quotes
+ inhibit history expansion. */
+ if (history_quotes_inhibit_expansion)
+ {
+ int quote, slen;
+
+ quote = i++;
+ hist_string_extract_single_quoted (string, &i);
+
+ slen = i - quote + 2;
+ temp = (char *)xmalloc (slen);
+ strncpy (temp, string + quote, slen);
+ temp[slen - 1] = '\0';
+ ADD_STRING (temp);
+ free (temp);
+ }
+ else
+ ADD_CHAR (string[i]);
+ break;
+ }
+
+ case -2: /* history_comment_char */
+ if (i == 0 || member (string[i - 1], history_word_delimiters))
+ {
+ temp = (char *)xmalloc (l - i + 1);
+ strcpy (temp, string + i);
+ ADD_STRING (temp);
+ free (temp);
+ i = l;
+ }
+ else
+ ADD_CHAR (string[i]);
+ break;
+
+ case -3: /* history_expansion_char */
+ cc = string[i + 1];
+
+ /* If the history_expansion_char is followed by one of the
+ characters in history_no_expand_chars, then it is not a
+ candidate for expansion of any kind. */
+ if (member (cc, history_no_expand_chars))
+ {
+ ADD_CHAR (string[i]);
+ break;
+ }
+
+#if defined (NO_BANG_HASH_MODIFIERS)
+ /* There is something that is listed as a `word specifier' in csh
+ documentation which means `the expanded text to this point'.
+ That is not a word specifier, it is an event specifier. If we
+ don't want to allow modifiers with `!#', just stick the current
+ output line in again. */
+ if (cc == '#')
+ {
+ if (result)
+ {
+ temp = (char *)xmalloc (1 + strlen (result));
+ strcpy (temp, result);
+ ADD_STRING (temp);
+ free (temp);
+ }
+ i++;
+ break;
+ }
+#endif
+
+ r = history_expand_internal (string, i, &eindex, &temp, result);
+ if (r < 0)
+ {
+ *output = temp;
+ free (result);
+ if (string != hstring)
+ free (string);
+ return -1;
+ }
+ else
+ {
+ if (temp)
+ {
+ modified++;
+ if (*temp)
+ ADD_STRING (temp);
+ free (temp);
+ }
+ only_printing = r == 1;
+ i = eindex;
+ }
+ break;
+ }
+ }
+
+ *output = result;
+ if (string != hstring)
+ free (string);
+
+ if (only_printing)
+ {
+ add_history (result);
+ return (2);
+ }
+
+ return (modified != 0);
+}
+
+/* Return a consed string which is the word specified in SPEC, and found
+ in FROM. NULL is returned if there is no spec. The address of
+ ERROR_POINTER is returned if the word specified cannot be found.
+ CALLER_INDEX is the offset in SPEC to start looking; it is updated
+ to point to just after the last character parsed. */
+static char *
+get_history_word_specifier (spec, from, caller_index)
+ char *spec, *from;
+ int *caller_index;
+{
+ register int i = *caller_index;
+ int first, last;
+ int expecting_word_spec = 0;
+ char *result;
+
+ /* The range of words to return doesn't exist yet. */
+ first = last = 0;
+ result = (char *)NULL;
+
+ /* If we found a colon, then this *must* be a word specification. If
+ it isn't, then it is an error. */
+ if (spec[i] == ':')
+ {
+ i++;
+ expecting_word_spec++;
+ }
+
+ /* Handle special cases first. */
+
+ /* `%' is the word last searched for. */
+ if (spec[i] == '%')
+ {
+ *caller_index = i + 1;
+ return (search_match ? savestring (search_match) : savestring (""));
+ }
+
+ /* `*' matches all of the arguments, but not the command. */
+ if (spec[i] == '*')
+ {
+ *caller_index = i + 1;
+ result = history_arg_extract (1, '$', from);
+ return (result ? result : savestring (""));
+ }
+
+ /* `$' is last arg. */
+ if (spec[i] == '$')
+ {
+ *caller_index = i + 1;
+ return (history_arg_extract ('$', '$', from));
+ }
+
+ /* Try to get FIRST and LAST figured out. */
+
+ if (spec[i] == '-')
+ first = 0;
+ else if (spec[i] == '^')
+ first = 1;
+ else if (_rl_digit_p (spec[i]) && expecting_word_spec)
+ {
+ for (first = 0; _rl_digit_p (spec[i]); i++)
+ first = (first * 10) + _rl_digit_value (spec[i]);
+ }
+ else
+ return ((char *)NULL); /* no valid `first' for word specifier */
+
+ if (spec[i] == '^' || spec[i] == '*')
+ {
+ last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
+ i++;
+ }
+ else if (spec[i] != '-')
+ last = first;
+ else
+ {
+ i++;
+
+ if (_rl_digit_p (spec[i]))
+ {
+ for (last = 0; _rl_digit_p (spec[i]); i++)
+ last = (last * 10) + _rl_digit_value (spec[i]);
+ }
+ else if (spec[i] == '$')
+ {
+ i++;
+ last = '$';
+ }
+#if 0
+ else if (!spec[i] || spec[i] == ':')
+ /* check against `:' because there could be a modifier separator */
+#else
+ else
+ /* csh seems to allow anything to terminate the word spec here,
+ leaving it as an abbreviation. */
+#endif
+ last = -1; /* x- abbreviates x-$ omitting word `$' */
+ }
+
+ *caller_index = i;
+
+ if (last >= first || last == '$' || last < 0)
+ result = history_arg_extract (first, last, from);
+
+ return (result ? result : (char *)&error_pointer);
+}
+
+/* Extract the args specified, starting at FIRST, and ending at LAST.
+ The args are taken from STRING. If either FIRST or LAST is < 0,
+ then make that arg count from the right (subtract from the number of
+ tokens, so that FIRST = -1 means the next to last token on the line).
+ If LAST is `$' the last arg from STRING is used. */
+char *
+history_arg_extract (first, last, string)
+ int first, last;
+ const char *string;
+{
+ register int i, len;
+ char *result;
+ int size, offset;
+ char **list;
+
+ /* XXX - think about making history_tokenize return a struct array,
+ each struct in array being a string and a length to avoid the
+ calls to strlen below. */
+ if ((list = history_tokenize (string)) == NULL)
+ return ((char *)NULL);
+
+ for (len = 0; list[len]; len++)
+ ;
+
+ if (last < 0)
+ last = len + last - 1;
+
+ if (first < 0)
+ first = len + first - 1;
+
+ if (last == '$')
+ last = len - 1;
+
+ if (first == '$')
+ first = len - 1;
+
+ last++;
+
+ if (first >= len || last > len || first < 0 || last < 0 || first > last)
+ result = ((char *)NULL);
+ else
+ {
+ for (size = 0, i = first; i < last; i++)
+ size += strlen (list[i]) + 1;
+ result = (char *)xmalloc (size + 1);
+ result[0] = '\0';
+
+ for (i = first, offset = 0; i < last; i++)
+ {
+ strcpy (result + offset, list[i]);
+ offset += strlen (list[i]);
+ if (i + 1 < last)
+ {
+ result[offset++] = ' ';
+ result[offset] = 0;
+ }
+ }
+ }
+
+ for (i = 0; i < len; i++)
+ free (list[i]);
+ free (list);
+
+ return (result);
+}
+
+#define slashify_in_quotes "\\`\"$"
+
+/* Parse STRING into tokens and return an array of strings. If WIND is
+ not -1 and INDP is not null, we also want the word surrounding index
+ WIND. The position in the returned array of strings is returned in
+ *INDP. */
+static char **
+history_tokenize_internal (string, wind, indp)
+ const char *string;
+ int wind, *indp;
+{
+ char **result;
+ register int i, start, result_index, size;
+ int len, delimiter;
+
+ /* If we're searching for a string that's not part of a word (e.g., " "),
+ make sure we set *INDP to a reasonable value. */
+ if (indp && wind != -1)
+ *indp = -1;
+
+ /* Get a token, and stuff it into RESULT. The tokens are split
+ exactly where the shell would split them. */
+ for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
+ {
+ delimiter = 0;
+
+ /* Skip leading whitespace. */
+ for (; string[i] && whitespace (string[i]); i++)
+ ;
+ if (string[i] == 0 || string[i] == history_comment_char)
+ return (result);
+
+ start = i;
+
+ if (member (string[i], "()\n"))
+ {
+ i++;
+ goto got_token;
+ }
+
+ if (member (string[i], "<>;&|$"))
+ {
+ int peek = string[i + 1];
+
+ if (peek == string[i] && peek != '$')
+ {
+ if (peek == '<' && string[i + 2] == '-')
+ i++;
+ i += 2;
+ goto got_token;
+ }
+ else
+ {
+ if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
+ ((peek == '>') && (string[i] == '&')) ||
+ ((peek == '(') && (string[i] == '$')))
+ {
+ i += 2;
+ goto got_token;
+ }
+ }
+ if (string[i] != '$')
+ {
+ i++;
+ goto got_token;
+ }
+ }
+
+ /* Get word from string + i; */
+
+ if (member (string[i], HISTORY_QUOTE_CHARACTERS))
+ delimiter = string[i++];
+
+ for (; string[i]; i++)
+ {
+ if (string[i] == '\\' && string[i + 1] == '\n')
+ {
+ i++;
+ continue;
+ }
+
+ if (string[i] == '\\' && delimiter != '\'' &&
+ (delimiter != '"' || member (string[i], slashify_in_quotes)))
+ {
+ i++;
+ continue;
+ }
+
+ if (delimiter && string[i] == delimiter)
+ {
+ delimiter = 0;
+ continue;
+ }
+
+ if (!delimiter && (member (string[i], history_word_delimiters)))
+ break;
+
+ if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
+ delimiter = string[i];
+ }
+
+ got_token:
+
+ /* If we are looking for the word in which the character at a
+ particular index falls, remember it. */
+ if (indp && wind != -1 && wind >= start && wind < i)
+ *indp = result_index;
+
+ len = i - start;
+ if (result_index + 2 >= size)
+ result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
+ result[result_index] = (char *)xmalloc (1 + len);
+ strncpy (result[result_index], string + start, len);
+ result[result_index][len] = '\0';
+ result[++result_index] = (char *)NULL;
+ }
+
+ return (result);
+}
+
+/* Return an array of tokens, much as the shell might. The tokens are
+ parsed out of STRING. */
+char **
+history_tokenize (string)
+ const char *string;
+{
+ return (history_tokenize_internal (string, -1, (int *)NULL));
+}
+
+/* Find and return the word which contains the character at index IND
+ in the history line LINE. Used to save the word matched by the
+ last history !?string? search. */
+static char *
+history_find_word (line, ind)
+ char *line;
+ int ind;
+{
+ char **words, *s;
+ int i, wind;
+
+ words = history_tokenize_internal (line, ind, &wind);
+ if (wind == -1 || words == 0)
+ return ((char *)NULL);
+ s = words[wind];
+ for (i = 0; i < wind; i++)
+ free (words[i]);
+ for (i = wind + 1; words[i]; i++)
+ free (words[i]);
+ free (words);
+ return s;
+}
diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c
new file mode 100644
index 00000000000..60a91251b7a
--- /dev/null
+++ b/cmd-line-utils/readline/histfile.c
@@ -0,0 +1,479 @@
+/* histfile.c - functions to manipulate the history file. */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file contains the GNU History Library (the Library), a set of
+ routines for managing the text of previously typed lines.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/* The goal is to make the implementation transparent, so that you
+ don't have to know what data types are used, just what functions
+ you can call. I think I have done that. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <sys/types.h>
+#ifndef _MINIX
+# include <sys/file.h>
+#endif
+#include "posixstat.h"
+#include <fcntl.h>
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (__EMX__) || defined (__CYGWIN__)
+# undef HAVE_MMAP
+#endif
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+
+# ifdef MAP_FILE
+# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
+# define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
+# else
+# define MAP_RFLAGS MAP_PRIVATE
+# define MAP_WFLAGS MAP_SHARED
+# endif
+
+# ifndef MAP_FAILED
+# define MAP_FAILED ((void *)-1)
+# endif
+
+#endif /* HAVE_MMAP */
+
+/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
+ on win 95/98/nt), we want to open files with O_BINARY mode so that there
+ is no \n -> \r\n conversion performed. On other systems, we don't want to
+ mess around with O_BINARY at all, so we ensure that it's defined to 0. */
+#if defined (__EMX__) || defined (__CYGWIN__)
+# ifndef O_BINARY
+# define O_BINARY 0
+# endif
+#else /* !__EMX__ && !__CYGWIN__ */
+# undef O_BINARY
+# define O_BINARY 0
+#endif /* !__EMX__ && !__CYGWIN__ */
+
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "history.h"
+#include "histlib.h"
+
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Return the string that should be used in the place of this
+ filename. This only matters when you don't specify the
+ filename to read_history (), or write_history (). */
+static char *
+history_filename (filename)
+ const char *filename;
+{
+ char *return_val;
+ const char *home;
+ int home_len;
+
+ return_val = filename ? savestring (filename) : (char *)NULL;
+
+ if (return_val)
+ return (return_val);
+
+ home = sh_get_env_value ("HOME");
+
+ if (home == 0)
+ {
+ home = ".";
+ home_len = 1;
+ }
+ else
+ home_len = strlen (home);
+
+ return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
+ strcpy (return_val, home);
+ return_val[home_len] = '/';
+#if defined (__MSDOS__)
+ strcpy (return_val + home_len + 1, "_history");
+#else
+ strcpy (return_val + home_len + 1, ".history");
+#endif
+
+ return (return_val);
+}
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+ If FILENAME is NULL, then read from ~/.history. Returns 0 if
+ successful, or errno if not. */
+int
+read_history (filename)
+ const char *filename;
+{
+ return (read_history_range (filename, 0, -1));
+}
+
+/* Read a range of lines from FILENAME, adding them to the history list.
+ Start reading at the FROM'th line and end at the TO'th. If FROM
+ is zero, start at the beginning. If TO is less than FROM, read
+ until the end of the file. If FILENAME is NULL, then read from
+ ~/.history. Returns 0 if successful, or errno if not. */
+int
+read_history_range (filename, from, to)
+ const char *filename;
+ int from, to;
+{
+ register char *line_start, *line_end;
+ char *input, *buffer, *bufend;
+ int file, current_line, chars_read;
+ struct stat finfo;
+ size_t file_size;
+
+ buffer = (char *)NULL;
+ input = history_filename (filename);
+ file = open (input, O_RDONLY|O_BINARY, 0666);
+
+ if ((file < 0) || (fstat (file, &finfo) == -1))
+ goto error_and_exit;
+
+ file_size = (size_t)finfo.st_size;
+
+ /* check for overflow on very large files */
+ if (file_size != finfo.st_size || file_size + 1 < file_size)
+ {
+#if defined (EFBIG)
+ errno = EFBIG;
+#elif defined (EOVERFLOW)
+ errno = EOVERFLOW;
+#endif
+ goto error_and_exit;
+ }
+
+#ifdef HAVE_MMAP
+ /* We map read/write and private so we can change newlines to NULs without
+ affecting the underlying object. */
+ buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
+ if ((void *)buffer == MAP_FAILED)
+ goto error_and_exit;
+ chars_read = file_size;
+#else
+ buffer = (char *)malloc (file_size + 1);
+ if (buffer == 0)
+ goto error_and_exit;
+
+ chars_read = read (file, buffer, file_size);
+#endif
+ if (chars_read < 0)
+ {
+ error_and_exit:
+ chars_read = errno;
+ if (file >= 0)
+ close (file);
+
+ FREE (input);
+#ifndef HAVE_MMAP
+ FREE (buffer);
+#endif
+
+ return (chars_read);
+ }
+
+ close (file);
+
+ /* Set TO to larger than end of file if negative. */
+ if (to < 0)
+ to = chars_read;
+
+ /* Start at beginning of file, work to end. */
+ bufend = buffer + chars_read;
+ current_line = 0;
+
+ /* Skip lines until we are at FROM. */
+ for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
+ if (*line_end == '\n')
+ {
+ current_line++;
+ line_start = line_end + 1;
+ }
+
+ /* If there are lines left to gobble, then gobble them now. */
+ for (line_end = line_start; line_end < bufend; line_end++)
+ if (*line_end == '\n')
+ {
+ *line_end = '\0';
+
+ if (*line_start)
+ add_history (line_start);
+
+ current_line++;
+
+ if (current_line >= to)
+ break;
+
+ line_start = line_end + 1;
+ }
+
+ FREE (input);
+#ifndef HAVE_MMAP
+ FREE (buffer);
+#else
+ munmap (buffer, file_size);
+#endif
+
+ return (0);
+}
+
+/* Truncate the history file FNAME, leaving only LINES trailing lines.
+ If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
+ on failure. */
+int
+history_truncate_file (fname, lines)
+ const char *fname;
+ int lines;
+{
+ char *buffer, *filename, *bp;
+ int file, chars_read, rv;
+ struct stat finfo;
+ size_t file_size;
+
+ buffer = (char *)NULL;
+ filename = history_filename (fname);
+ file = open (filename, O_RDONLY|O_BINARY, 0666);
+ rv = 0;
+
+ /* Don't try to truncate non-regular files. */
+ if (file == -1 || fstat (file, &finfo) == -1)
+ {
+ rv = errno;
+ if (file != -1)
+ close (file);
+ goto truncate_exit;
+ }
+
+ if (S_ISREG (finfo.st_mode) == 0)
+ {
+ close (file);
+#ifdef EFTYPE
+ rv = EFTYPE;
+#else
+ rv = EINVAL;
+#endif
+ goto truncate_exit;
+ }
+
+ file_size = (size_t)finfo.st_size;
+
+ /* check for overflow on very large files */
+ if (file_size != finfo.st_size || file_size + 1 < file_size)
+ {
+ close (file);
+#if defined (EFBIG)
+ rv = errno = EFBIG;
+#elif defined (EOVERFLOW)
+ rv = errno = EOVERFLOW;
+#else
+ rv = errno = EINVAL;
+#endif
+ goto truncate_exit;
+ }
+
+ buffer = (char *)malloc (file_size + 1);
+ if (buffer == 0)
+ {
+ close (file);
+ goto truncate_exit;
+ }
+
+ chars_read = read (file, buffer, file_size);
+ close (file);
+
+ if (chars_read <= 0)
+ {
+ rv = (chars_read < 0) ? errno : 0;
+ goto truncate_exit;
+ }
+
+ /* Count backwards from the end of buffer until we have passed
+ LINES lines. */
+ for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
+ {
+ if (*bp == '\n')
+ lines--;
+ }
+
+ /* If this is the first line, then the file contains exactly the
+ number of lines we want to truncate to, so we don't need to do
+ anything. It's the first line if we don't find a newline between
+ the current value of i and 0. Otherwise, write from the start of
+ this line until the end of the buffer. */
+ for ( ; bp > buffer; bp--)
+ if (*bp == '\n')
+ {
+ bp++;
+ break;
+ }
+
+ /* Write only if there are more lines in the file than we want to
+ truncate to. */
+ if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
+ {
+ write (file, bp, chars_read - (bp - buffer));
+
+#if defined (__BEOS__)
+ /* BeOS ignores O_TRUNC. */
+ ftruncate (file, chars_read - (bp - buffer));
+#endif
+
+ close (file);
+ }
+
+ truncate_exit:
+
+ FREE (buffer);
+
+ free (filename);
+ return rv;
+}
+
+/* Workhorse function for writing history. Writes NELEMENT entries
+ from the history list to FILENAME. OVERWRITE is non-zero if you
+ wish to replace FILENAME with the entries. */
+static int
+history_do_write (filename, nelements, overwrite)
+ const char *filename;
+ int nelements, overwrite;
+{
+ register int i;
+ char *output;
+ int file, mode, rv;
+ size_t cursize;
+
+#ifdef HAVE_MMAP
+ mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
+#else
+ mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
+#endif
+ output = history_filename (filename);
+ rv = 0;
+
+ if ((file = open (output, mode, 0600)) == -1)
+ {
+ FREE (output);
+ return (errno);
+ }
+
+#ifdef HAVE_MMAP
+ cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
+#endif
+
+ if (nelements > history_length)
+ nelements = history_length;
+
+ /* Build a buffer of all the lines to write, and write them in one syscall.
+ Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
+ {
+ HIST_ENTRY **the_history; /* local */
+ register int j;
+ int buffer_size;
+ char *buffer;
+
+ the_history = history_list ();
+ /* Calculate the total number of bytes to write. */
+ for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
+ buffer_size += 1 + strlen (the_history[i]->line);
+
+ /* Allocate the buffer, and fill it. */
+#ifdef HAVE_MMAP
+ if (ftruncate (file, buffer_size+cursize) == -1)
+ goto mmap_error;
+ buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
+ if ((void *)buffer == MAP_FAILED)
+ {
+mmap_error:
+ rv = errno;
+ FREE (output);
+ close (file);
+ return rv;
+ }
+#else
+ buffer = (char *)malloc (buffer_size);
+ if (buffer == 0)
+ {
+ rv = errno;
+ FREE (output);
+ close (file);
+ return rv;
+ }
+#endif
+
+ for (j = 0, i = history_length - nelements; i < history_length; i++)
+ {
+ strcpy (buffer + j, the_history[i]->line);
+ j += strlen (the_history[i]->line);
+ buffer[j++] = '\n';
+ }
+
+#ifdef HAVE_MMAP
+ if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
+ rv = errno;
+#else
+ if (write (file, buffer, buffer_size) < 0)
+ rv = errno;
+ free (buffer);
+#endif
+ }
+
+ close (file);
+
+ FREE (output);
+
+ return (rv);
+}
+
+/* Append NELEMENT entries to FILENAME. The entries appended are from
+ the end of the list minus NELEMENTs up to the end of the list. */
+int
+append_history (nelements, filename)
+ int nelements;
+ const char *filename;
+{
+ return (history_do_write (filename, nelements, HISTORY_APPEND));
+}
+
+/* Overwrite FILENAME with the current history. If FILENAME is NULL,
+ then write the history list to ~/.history. Values returned
+ are as in read_history ().*/
+int
+write_history (filename)
+ const char *filename;
+{
+ return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
+}
diff --git a/cmd-line-utils/readline/histlib.h b/cmd-line-utils/readline/histlib.h
new file mode 100644
index 00000000000..c39af71814c
--- /dev/null
+++ b/cmd-line-utils/readline/histlib.h
@@ -0,0 +1,82 @@
+/* histlib.h -- internal definitions for the history library. */
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file contains the GNU History Library (the Library), a set of
+ routines for managing the text of previously typed lines.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_HISTLIB_H_)
+#define _HISTLIB_H_
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if !defined (STREQ)
+#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
+#define STREQN(a, b, n) (((n) == 0) ? (1) \
+ : ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
+#endif
+
+#ifndef savestring
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifndef _rl_digit_p
+#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef _rl_digit_value
+#define _rl_digit_value(c) ((c) - '0')
+#endif
+
+#ifndef member
+# ifndef strchr
+extern char *strchr ();
+# endif
+#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
+#endif
+
+#ifndef FREE
+# define FREE(x) if (x) free (x)
+#endif
+
+/* Possible history errors passed to hist_error. */
+#define EVENT_NOT_FOUND 0
+#define BAD_WORD_SPEC 1
+#define SUBST_FAILED 2
+#define BAD_MODIFIER 3
+#define NO_PREV_SUBST 4
+
+/* Possible definitions for history starting point specification. */
+#define ANCHORED_SEARCH 1
+#define NON_ANCHORED_SEARCH 0
+
+/* Possible definitions for what style of writing the history file we want. */
+#define HISTORY_APPEND 0
+#define HISTORY_OVERWRITE 1
+
+/* Some variable definitions shared across history source files. */
+extern int history_offset;
+
+#endif /* !_HISTLIB_H_ */
diff --git a/cmd-line-utils/readline/history.c b/cmd-line-utils/readline/history.c
new file mode 100644
index 00000000000..4242f33efe1
--- /dev/null
+++ b/cmd-line-utils/readline/history.c
@@ -0,0 +1,381 @@
+/* History.c -- standalone history library */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file contains the GNU History Library (the Library), a set of
+ routines for managing the text of previously typed lines.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/* The goal is to make the implementation transparent, so that you
+ don't have to know what data types are used, just what functions
+ you can call. I think I have done that. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include "history.h"
+#include "histlib.h"
+
+#include "xmalloc.h"
+
+/* The number of slots to increase the_history by. */
+#define DEFAULT_HISTORY_GROW_SIZE 50
+
+/* **************************************************************** */
+/* */
+/* History Functions */
+/* */
+/* **************************************************************** */
+
+/* An array of HIST_ENTRY. This is where we store the history. */
+static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
+
+/* Non-zero means that we have enforced a limit on the amount of
+ history that we save. */
+static int history_stifled;
+
+/* The current number of slots allocated to the input_history. */
+static int history_size;
+
+/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
+ entries to remember. */
+int history_max_entries;
+int max_input_history; /* backwards compatibility */
+
+/* The current location of the interactive history pointer. Just makes
+ life easier for outside callers. */
+int history_offset;
+
+/* The number of strings currently stored in the history list. */
+int history_length;
+
+/* The logical `base' of the history array. It defaults to 1. */
+int history_base = 1;
+
+/* Return the current HISTORY_STATE of the history. */
+HISTORY_STATE *
+history_get_history_state ()
+{
+ HISTORY_STATE *state;
+
+ state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
+ state->entries = the_history;
+ state->offset = history_offset;
+ state->length = history_length;
+ state->size = history_size;
+ state->flags = 0;
+ if (history_stifled)
+ state->flags |= HS_STIFLED;
+
+ return (state);
+}
+
+/* Set the state of the current history array to STATE. */
+void
+history_set_history_state (state)
+ HISTORY_STATE *state;
+{
+ the_history = state->entries;
+ history_offset = state->offset;
+ history_length = state->length;
+ history_size = state->size;
+ if (state->flags & HS_STIFLED)
+ history_stifled = 1;
+}
+
+/* Begin a session in which the history functions might be used. This
+ initializes interactive variables. */
+void
+using_history ()
+{
+ history_offset = history_length;
+}
+
+/* Return the number of bytes that the primary history entries are using.
+ This just adds up the lengths of the_history->lines. */
+int
+history_total_bytes ()
+{
+ register int i, result;
+
+ for (i = result = 0; the_history && the_history[i]; i++)
+ result += strlen (the_history[i]->line);
+
+ return (result);
+}
+
+/* Returns the magic number which says what history element we are
+ looking at now. In this implementation, it returns history_offset. */
+int
+where_history ()
+{
+ return (history_offset);
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+ Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+ int pos;
+{
+ if (pos > history_length || pos < 0 || !the_history)
+ return (0);
+ history_offset = pos;
+ return (1);
+}
+
+/* Return the current history array. The caller has to be carefull, since this
+ is the actual array of data, and could be bashed or made corrupt easily.
+ The array is terminated with a NULL pointer. */
+HIST_ENTRY **
+history_list ()
+{
+ return (the_history);
+}
+
+/* Return the history entry at the current position, as determined by
+ history_offset. If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *
+current_history ()
+{
+ return ((history_offset == history_length) || the_history == 0)
+ ? (HIST_ENTRY *)NULL
+ : the_history[history_offset];
+}
+
+/* Back up history_offset to the previous history entry, and return
+ a pointer to that entry. If there is no previous entry then return
+ a NULL pointer. */
+HIST_ENTRY *
+previous_history ()
+{
+ return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
+}
+
+/* Move history_offset forward to the next history entry, and return
+ a pointer to that entry. If there is no next entry then return a
+ NULL pointer. */
+HIST_ENTRY *
+next_history ()
+{
+ return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
+}
+
+/* Return the history entry which is logically at OFFSET in the history array.
+ OFFSET is relative to history_base. */
+HIST_ENTRY *
+history_get (offset)
+ int offset;
+{
+ int local_index;
+
+ local_index = offset - history_base;
+ return (local_index >= history_length || local_index < 0 || !the_history)
+ ? (HIST_ENTRY *)NULL
+ : the_history[local_index];
+}
+
+/* Place STRING at the end of the history list. The data field
+ is set to NULL. */
+void
+add_history (string)
+ const char *string;
+{
+ HIST_ENTRY *temp;
+
+ if (history_stifled && (history_length == history_max_entries))
+ {
+ register int i;
+
+ /* If the history is stifled, and history_length is zero,
+ and it equals history_max_entries, we don't save items. */
+ if (history_length == 0)
+ return;
+
+ /* If there is something in the slot, then remove it. */
+ if (the_history[0])
+ {
+ free (the_history[0]->line);
+ free (the_history[0]);
+ }
+
+ /* Copy the rest of the entries, moving down one slot. */
+ for (i = 0; i < history_length; i++)
+ the_history[i] = the_history[i + 1];
+
+ history_base++;
+ }
+ else
+ {
+ if (history_size == 0)
+ {
+ history_size = DEFAULT_HISTORY_GROW_SIZE;
+ the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
+ history_length = 1;
+ }
+ else
+ {
+ if (history_length == (history_size - 1))
+ {
+ history_size += DEFAULT_HISTORY_GROW_SIZE;
+ the_history = (HIST_ENTRY **)
+ xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
+ }
+ history_length++;
+ }
+ }
+
+ temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+ temp->line = savestring (string);
+ temp->data = (char *)NULL;
+
+ the_history[history_length] = (HIST_ENTRY *)NULL;
+ the_history[history_length - 1] = temp;
+}
+
+/* Make the history entry at WHICH have LINE and DATA. This returns
+ the old entry so you can dispose of the data. In the case of an
+ invalid WHICH, a NULL pointer is returned. */
+HIST_ENTRY *
+replace_history_entry (which, line, data)
+ int which;
+ const char *line;
+ histdata_t data;
+{
+ HIST_ENTRY *temp, *old_value;
+
+ if (which >= history_length)
+ return ((HIST_ENTRY *)NULL);
+
+ temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+ old_value = the_history[which];
+
+ temp->line = savestring (line);
+ temp->data = data;
+ the_history[which] = temp;
+
+ return (old_value);
+}
+
+/* Remove history element WHICH from the history. The removed
+ element is returned to you so you can free the line, data,
+ and containing structure. */
+HIST_ENTRY *
+remove_history (which)
+ int which;
+{
+ HIST_ENTRY *return_value;
+ register int i;
+
+ if (which >= history_length || !history_length)
+ return_value = (HIST_ENTRY *)NULL;
+ else
+ {
+ return_value = the_history[which];
+
+ for (i = which; i < history_length; i++)
+ the_history[i] = the_history[i + 1];
+
+ history_length--;
+ }
+
+ return (return_value);
+}
+
+/* Stifle the history list, remembering only MAX number of lines. */
+void
+stifle_history (max)
+ int max;
+{
+ register int i, j;
+
+ if (max < 0)
+ max = 0;
+
+ if (history_length > max)
+ {
+ /* This loses because we cannot free the data. */
+ for (i = 0, j = history_length - max; i < j; i++)
+ {
+ free (the_history[i]->line);
+ free (the_history[i]);
+ }
+
+ history_base = i;
+ for (j = 0, i = history_length - max; j < max; i++, j++)
+ the_history[j] = the_history[i];
+ the_history[j] = (HIST_ENTRY *)NULL;
+ history_length = j;
+ }
+
+ history_stifled = 1;
+ max_input_history = history_max_entries = max;
+}
+
+/* Stop stifling the history. This returns the previous maximum
+ number of history entries. The value is positive if the history
+ was stifled, negative if it wasn't. */
+int
+unstifle_history ()
+{
+ if (history_stifled)
+ {
+ history_stifled = 0;
+ return (history_max_entries);
+ }
+ else
+ return (-history_max_entries);
+}
+
+int
+history_is_stifled ()
+{
+ return (history_stifled);
+}
+
+void
+clear_history ()
+{
+ register int i;
+
+ /* This loses because we cannot free the data. */
+ for (i = 0; i < history_length; i++)
+ {
+ free (the_history[i]->line);
+ free (the_history[i]);
+ the_history[i] = (HIST_ENTRY *)NULL;
+ }
+
+ history_offset = history_length = 0;
+}
diff --git a/cmd-line-utils/readline/history.h b/cmd-line-utils/readline/history.h
new file mode 100644
index 00000000000..afd85104554
--- /dev/null
+++ b/cmd-line-utils/readline/history.h
@@ -0,0 +1,246 @@
+/* History.h -- the names of functions that you can call in history. */
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file contains the GNU History Library (the Library), a set of
+ routines for managing the text of previously typed lines.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#ifndef _HISTORY_H_
+#define _HISTORY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined READLINE_LIBRARY
+# include "rlstdc.h"
+# include "rltypedefs.h"
+#else
+# include <readline/rlstdc.h>
+# include <readline/rltypedefs.h>
+#endif
+
+#ifdef __STDC__
+typedef void *histdata_t;
+#else
+typedef char *histdata_t;
+#endif
+
+/* The structure used to store a history entry. */
+typedef struct _hist_entry {
+ char *line;
+ histdata_t data;
+} HIST_ENTRY;
+
+/* A structure used to pass the current state of the history stuff around. */
+typedef struct _hist_state {
+ HIST_ENTRY **entries; /* Pointer to the entries themselves. */
+ int offset; /* The location pointer within this array. */
+ int length; /* Number of elements within this array. */
+ int size; /* Number of slots allocated to this array. */
+ int flags;
+} HISTORY_STATE;
+
+/* Flag values for the `flags' member of HISTORY_STATE. */
+#define HS_STIFLED 0x01
+
+/* Initialization and state management. */
+
+/* Begin a session in which the history functions might be used. This
+ just initializes the interactive variables. */
+extern void using_history PARAMS((void));
+
+/* Return the current HISTORY_STATE of the history. */
+extern HISTORY_STATE *history_get_history_state PARAMS((void));
+
+/* Set the state of the current history array to STATE. */
+extern void history_set_history_state PARAMS((HISTORY_STATE *));
+
+/* Manage the history list. */
+
+/* Place STRING at the end of the history list.
+ The associated data field (if any) is set to NULL. */
+extern void add_history PARAMS((const char *));
+
+/* A reasonably useless function, only here for completeness. WHICH
+ is the magic number that tells us which element to delete. The
+ elements are numbered from 0. */
+extern HIST_ENTRY *remove_history PARAMS((int));
+
+/* Make the history entry at WHICH have LINE and DATA. This returns
+ the old entry so you can dispose of the data. In the case of an
+ invalid WHICH, a NULL pointer is returned. */
+extern HIST_ENTRY *replace_history_entry PARAMS((int, const char *, histdata_t));
+
+/* Clear the history list and start over. */
+extern void clear_history PARAMS((void));
+
+/* Stifle the history list, remembering only MAX number of entries. */
+extern void stifle_history PARAMS((int));
+
+/* Stop stifling the history. This returns the previous amount the
+ history was stifled by. The value is positive if the history was
+ stifled, negative if it wasn't. */
+extern int unstifle_history PARAMS((void));
+
+/* Return 1 if the history is stifled, 0 if it is not. */
+extern int history_is_stifled PARAMS((void));
+
+/* Information about the history list. */
+
+/* Return a NULL terminated array of HIST_ENTRY which is the current input
+ history. Element 0 of this list is the beginning of time. If there
+ is no history, return NULL. */
+extern HIST_ENTRY **history_list PARAMS((void));
+
+/* Returns the number which says what history element we are now
+ looking at. */
+extern int where_history PARAMS((void));
+
+/* Return the history entry at the current position, as determined by
+ history_offset. If there is no entry there, return a NULL pointer. */
+extern HIST_ENTRY *current_history PARAMS((void));
+
+/* Return the history entry which is logically at OFFSET in the history
+ array. OFFSET is relative to history_base. */
+extern HIST_ENTRY *history_get PARAMS((int));
+
+/* Return the number of bytes that the primary history entries are using.
+ This just adds up the lengths of the_history->lines. */
+extern int history_total_bytes PARAMS((void));
+
+/* Moving around the history list. */
+
+/* Set the position in the history list to POS. */
+extern int history_set_pos PARAMS((int));
+
+/* Back up history_offset to the previous history entry, and return
+ a pointer to that entry. If there is no previous entry, return
+ a NULL pointer. */
+extern HIST_ENTRY *previous_history PARAMS((void));
+
+/* Move history_offset forward to the next item in the input_history,
+ and return the a pointer to that entry. If there is no next entry,
+ return a NULL pointer. */
+extern HIST_ENTRY *next_history PARAMS((void));
+
+/* Searching the history list. */
+
+/* Search the history for STRING, starting at history_offset.
+ If DIRECTION < 0, then the search is through previous entries,
+ else through subsequent. If the string is found, then
+ current_history () is the history entry, and the value of this function
+ is the offset in the line of that history entry that the string was
+ found in. Otherwise, nothing is changed, and a -1 is returned. */
+extern int history_search PARAMS((const char *, int));
+
+/* Search the history for STRING, starting at history_offset.
+ The search is anchored: matching lines must begin with string.
+ DIRECTION is as in history_search(). */
+extern int history_search_prefix PARAMS((const char *, int));
+
+/* Search for STRING in the history list, starting at POS, an
+ absolute index into the list. DIR, if negative, says to search
+ backwards from POS, else forwards.
+ Returns the absolute index of the history element where STRING
+ was found, or -1 otherwise. */
+extern int history_search_pos PARAMS((const char *, int, int));
+
+/* Managing the history file. */
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+ If FILENAME is NULL, then read from ~/.history. Returns 0 if
+ successful, or errno if not. */
+extern int read_history PARAMS((const char *));
+
+/* Read a range of lines from FILENAME, adding them to the history list.
+ Start reading at the FROM'th line and end at the TO'th. If FROM
+ is zero, start at the beginning. If TO is less than FROM, read
+ until the end of the file. If FILENAME is NULL, then read from
+ ~/.history. Returns 0 if successful, or errno if not. */
+extern int read_history_range PARAMS((const char *, int, int));
+
+/* Write the current history to FILENAME. If FILENAME is NULL,
+ then write the history list to ~/.history. Values returned
+ are as in read_history (). */
+extern int write_history PARAMS((const char *));
+
+/* Append NELEMENT entries to FILENAME. The entries appended are from
+ the end of the list minus NELEMENTs up to the end of the list. */
+extern int append_history PARAMS((int, const char *));
+
+/* Truncate the history file, leaving only the last NLINES lines. */
+extern int history_truncate_file PARAMS((const char *, int));
+
+/* History expansion. */
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+ to a string. Returns:
+
+ 0) If no expansions took place (or, if the only change in
+ the text was the de-slashifying of the history expansion
+ character)
+ 1) If expansions did take place
+ -1) If there was an error in expansion.
+ 2) If the returned line should just be printed.
+
+ If an error ocurred in expansion, then OUTPUT contains a descriptive
+ error message. */
+extern int history_expand PARAMS((char *, char **));
+
+/* Extract a string segment consisting of the FIRST through LAST
+ arguments present in STRING. Arguments are broken up as in
+ the shell. */
+extern char *history_arg_extract PARAMS((int, int, const char *));
+
+/* Return the text of the history event beginning at the current
+ offset into STRING. Pass STRING with *INDEX equal to the
+ history_expansion_char that begins this specification.
+ DELIMITING_QUOTE is a character that is allowed to end the string
+ specification for what to search for in addition to the normal
+ characters `:', ` ', `\t', `\n', and sometimes `?'. */
+extern char *get_history_event PARAMS((const char *, int *, int));
+
+/* Return an array of tokens, much as the shell might. The tokens are
+ parsed out of STRING. */
+extern char **history_tokenize PARAMS((const char *));
+
+/* Exported history variables. */
+extern int history_base;
+extern int history_length;
+extern int history_max_entries;
+extern char history_expansion_char;
+extern char history_subst_char;
+extern const char *history_word_delimiters;
+extern char history_comment_char;
+extern const char *history_no_expand_chars;
+extern char *history_search_delimiter_chars;
+extern int history_quotes_inhibit_expansion;
+
+/* Backwards compatibility */
+extern int max_input_history;
+
+/* If set, this function is called to decide whether or not a particular
+ history expansion should be treated as a special case for the calling
+ application and not expanded. */
+extern rl_linebuf_func_t *history_inhibit_expansion_function;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_HISTORY_H_ */
diff --git a/cmd-line-utils/readline/histsearch.c b/cmd-line-utils/readline/histsearch.c
new file mode 100644
index 00000000000..d94fd6cd9c6
--- /dev/null
+++ b/cmd-line-utils/readline/histsearch.c
@@ -0,0 +1,195 @@
+/* histsearch.c -- searching the history list. */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file contains the GNU History Library (the Library), a set of
+ routines for managing the text of previously typed lines.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include "history.h"
+#include "histlib.h"
+
+/* The list of alternate characters that can delimit a history search
+ string. */
+char *history_search_delimiter_chars = (char *)NULL;
+
+static int history_search_internal PARAMS((const char *, int, int));
+
+/* Search the history for STRING, starting at history_offset.
+ If DIRECTION < 0, then the search is through previous entries, else
+ through subsequent. If ANCHORED is non-zero, the string must
+ appear at the beginning of a history line, otherwise, the string
+ may appear anywhere in the line. If the string is found, then
+ current_history () is the history entry, and the value of this
+ function is the offset in the line of that history entry that the
+ string was found in. Otherwise, nothing is changed, and a -1 is
+ returned. */
+
+static int
+history_search_internal (string, direction, anchored)
+ const char *string;
+ int direction, anchored;
+{
+ register int i, reverse;
+ register char *line;
+ register int line_index;
+ int string_len;
+ HIST_ENTRY **the_history; /* local */
+
+ i = history_offset;
+ reverse = (direction < 0);
+
+ /* Take care of trivial cases first. */
+ if (string == 0 || *string == '\0')
+ return (-1);
+
+ if (!history_length || ((i == history_length) && !reverse))
+ return (-1);
+
+ if (reverse && (i == history_length))
+ i--;
+
+#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
+
+ the_history = history_list ();
+ string_len = strlen (string);
+ while (1)
+ {
+ /* Search each line in the history list for STRING. */
+
+ /* At limit for direction? */
+ if ((reverse && i < 0) || (!reverse && i == history_length))
+ return (-1);
+
+ line = the_history[i]->line;
+ line_index = strlen (line);
+
+ /* If STRING is longer than line, no match. */
+ if (string_len > line_index)
+ {
+ NEXT_LINE ();
+ continue;
+ }
+
+ /* Handle anchored searches first. */
+ if (anchored == ANCHORED_SEARCH)
+ {
+ if (STREQN (string, line, string_len))
+ {
+ history_offset = i;
+ return (0);
+ }
+
+ NEXT_LINE ();
+ continue;
+ }
+
+ /* Do substring search. */
+ if (reverse)
+ {
+ line_index -= string_len;
+
+ while (line_index >= 0)
+ {
+ if (STREQN (string, line + line_index, string_len))
+ {
+ history_offset = i;
+ return (line_index);
+ }
+ line_index--;
+ }
+ }
+ else
+ {
+ register int limit;
+
+ limit = line_index - string_len + 1;
+ line_index = 0;
+
+ while (line_index < limit)
+ {
+ if (STREQN (string, line + line_index, string_len))
+ {
+ history_offset = i;
+ return (line_index);
+ }
+ line_index++;
+ }
+ }
+ NEXT_LINE ();
+ }
+}
+
+/* Do a non-anchored search for STRING through the history in DIRECTION. */
+int
+history_search (string, direction)
+ const char *string;
+ int direction;
+{
+ return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
+}
+
+/* Do an anchored search for string through the history in DIRECTION. */
+int
+history_search_prefix (string, direction)
+ const char *string;
+ int direction;
+{
+ return (history_search_internal (string, direction, ANCHORED_SEARCH));
+}
+
+/* Search for STRING in the history list. DIR is < 0 for searching
+ backwards. POS is an absolute index into the history list at
+ which point to begin searching. */
+int
+history_search_pos (string, dir, pos)
+ const char *string;
+ int dir, pos;
+{
+ int ret, old;
+
+ old = where_history ();
+ history_set_pos (pos);
+ if (history_search (string, dir) == -1)
+ {
+ history_set_pos (old);
+ return (-1);
+ }
+ ret = where_history ();
+ history_set_pos (old);
+ return ret;
+}
diff --git a/cmd-line-utils/readline/input.c b/cmd-line-utils/readline/input.c
new file mode 100644
index 00000000000..1442c5ef155
--- /dev/null
+++ b/cmd-line-utils/readline/input.c
@@ -0,0 +1,540 @@
+/* input.c -- character input functions for readline. */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_SELECT)
+# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
+# include <sys/time.h>
+# endif
+#endif /* HAVE_SELECT */
+#if defined (HAVE_SYS_SELECT_H)
+# include <sys/select.h>
+#endif
+
+#if defined (FIONREAD_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* What kind of non-blocking I/O do we have? */
+#if !defined (O_NDELAY) && defined (O_NONBLOCK)
+# define O_NDELAY O_NONBLOCK /* Posix style */
+#endif
+
+/* Non-null means it is a pointer to a function to run while waiting for
+ character input. */
+rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
+
+rl_getc_func_t *rl_getc_function = rl_getc;
+
+static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
+
+static int ibuffer_space PARAMS((void));
+static int rl_get_char PARAMS((int *));
+static int rl_gather_tyi PARAMS((void));
+
+/* **************************************************************** */
+/* */
+/* Character Input Buffering */
+/* */
+/* **************************************************************** */
+
+static int pop_index, push_index;
+static unsigned char ibuffer[512];
+static int ibuffer_len = sizeof (ibuffer) - 1;
+
+#define any_typein (push_index != pop_index)
+
+int
+_rl_any_typein ()
+{
+ return any_typein;
+}
+
+/* Return the amount of space available in the buffer for stuffing
+ characters. */
+static int
+ibuffer_space ()
+{
+ if (pop_index > push_index)
+ return (pop_index - push_index - 1);
+ else
+ return (ibuffer_len - (push_index - pop_index));
+}
+
+/* Get a key from the buffer of characters to be read.
+ Return the key in KEY.
+ Result is KEY if there was a key, or 0 if there wasn't. */
+static int
+rl_get_char (key)
+ int *key;
+{
+ if (push_index == pop_index)
+ return (0);
+
+ *key = ibuffer[pop_index++];
+
+ if (pop_index >= ibuffer_len)
+ pop_index = 0;
+
+ return (1);
+}
+
+/* Stuff KEY into the *front* of the input buffer.
+ Returns non-zero if successful, zero if there is
+ no space left in the buffer. */
+int
+_rl_unget_char (key)
+ int key;
+{
+ if (ibuffer_space ())
+ {
+ pop_index--;
+ if (pop_index < 0)
+ pop_index = ibuffer_len - 1;
+ ibuffer[pop_index] = key;
+ return (1);
+ }
+ return (0);
+}
+
+/* If a character is available to be read, then read it and stuff it into
+ IBUFFER. Otherwise, just return. Returns number of characters read
+ (0 if none available) and -1 on error (EIO). */
+static int
+rl_gather_tyi ()
+{
+ int tty;
+ register int tem, result;
+ int chars_avail;
+ char input;
+#if defined(HAVE_SELECT)
+ fd_set readfds, exceptfds;
+ struct timeval timeout;
+#endif
+
+ tty = fileno (rl_instream);
+
+#if defined (HAVE_SELECT)
+ FD_ZERO (&readfds);
+ FD_ZERO (&exceptfds);
+ FD_SET (tty, &readfds);
+ FD_SET (tty, &exceptfds);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = _keyboard_input_timeout;
+ result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
+ if (result <= 0)
+ return 0; /* Nothing to read. */
+#endif
+
+ result = -1;
+#if defined (FIONREAD)
+ errno = 0;
+ result = ioctl (tty, FIONREAD, &chars_avail);
+ if (result == -1 && errno == EIO)
+ return -1;
+#endif
+
+#if defined (O_NDELAY)
+ if (result == -1)
+ {
+ tem = fcntl (tty, F_GETFL, 0);
+
+ fcntl (tty, F_SETFL, (tem | O_NDELAY));
+ chars_avail = read (tty, &input, 1);
+
+ fcntl (tty, F_SETFL, tem);
+ if (chars_avail == -1 && errno == EAGAIN)
+ return 0;
+ }
+#endif /* O_NDELAY */
+
+ /* If there's nothing available, don't waste time trying to read
+ something. */
+ if (chars_avail <= 0)
+ return 0;
+
+ tem = ibuffer_space ();
+
+ if (chars_avail > tem)
+ chars_avail = tem;
+
+ /* One cannot read all of the available input. I can only read a single
+ character at a time, or else programs which require input can be
+ thwarted. If the buffer is larger than one character, I lose.
+ Damn! */
+ if (tem < ibuffer_len)
+ chars_avail = 0;
+
+ if (result != -1)
+ {
+ while (chars_avail--)
+ rl_stuff_char ((*rl_getc_function) (rl_instream));
+ }
+ else
+ {
+ if (chars_avail)
+ rl_stuff_char (input);
+ }
+
+ return 1;
+}
+
+int
+rl_set_keyboard_input_timeout (u)
+ int u;
+{
+ int o;
+
+ o = _keyboard_input_timeout;
+ if (u > 0)
+ _keyboard_input_timeout = u;
+ return (o);
+}
+
+/* Is there input available to be read on the readline input file
+ descriptor? Only works if the system has select(2) or FIONREAD.
+ Uses the value of _keyboard_input_timeout as the timeout; if another
+ readline function wants to specify a timeout and not leave it up to
+ the user, it should use _rl_input_queued(timeout_value_in_microseconds)
+ instead. */
+int
+_rl_input_available ()
+{
+#if defined(HAVE_SELECT)
+ fd_set readfds, exceptfds;
+ struct timeval timeout;
+#endif
+#if !defined (HAVE_SELECT) && defined(FIONREAD)
+ int chars_avail;
+#endif
+ int tty;
+
+ tty = fileno (rl_instream);
+
+#if defined (HAVE_SELECT)
+ FD_ZERO (&readfds);
+ FD_ZERO (&exceptfds);
+ FD_SET (tty, &readfds);
+ FD_SET (tty, &exceptfds);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = _keyboard_input_timeout;
+ return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
+#else
+
+#if defined (FIONREAD)
+ if (ioctl (tty, FIONREAD, &chars_avail) == 0)
+ return (chars_avail);
+#endif
+
+#endif
+
+ return 0;
+}
+
+int
+_rl_input_queued (t)
+ int t;
+{
+ int old_timeout, r;
+
+ old_timeout = rl_set_keyboard_input_timeout (t);
+ r = _rl_input_available ();
+ rl_set_keyboard_input_timeout (old_timeout);
+ return r;
+}
+
+void
+_rl_insert_typein (c)
+ int c;
+{
+ int key, t, i;
+ char *string;
+
+ i = key = 0;
+ string = (char *)xmalloc (ibuffer_len + 1);
+ string[i++] = (char) c;
+
+ while ((t = rl_get_char (&key)) &&
+ _rl_keymap[key].type == ISFUNC &&
+ _rl_keymap[key].function == rl_insert)
+ string[i++] = key;
+
+ if (t)
+ _rl_unget_char (key);
+
+ string[i] = '\0';
+ rl_insert_text (string);
+ free (string);
+}
+
+/* Add KEY to the buffer of characters to be read. Returns 1 if the
+ character was stuffed correctly; 0 otherwise. */
+int
+rl_stuff_char (key)
+ int key;
+{
+ if (ibuffer_space () == 0)
+ return 0;
+
+ if (key == EOF)
+ {
+ key = NEWLINE;
+ rl_pending_input = EOF;
+ RL_SETSTATE (RL_STATE_INPUTPENDING);
+ }
+ ibuffer[push_index++] = key;
+ if (push_index >= ibuffer_len)
+ push_index = 0;
+
+ return 1;
+}
+
+/* Make C be the next command to be executed. */
+int
+rl_execute_next (c)
+ int c;
+{
+ rl_pending_input = c;
+ RL_SETSTATE (RL_STATE_INPUTPENDING);
+ return 0;
+}
+
+/* Clear any pending input pushed with rl_execute_next() */
+int
+rl_clear_pending_input ()
+{
+ rl_pending_input = 0;
+ RL_UNSETSTATE (RL_STATE_INPUTPENDING);
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Character Input */
+/* */
+/* **************************************************************** */
+
+/* Read a key, including pending input. */
+int
+rl_read_key ()
+{
+ int c;
+
+ rl_key_sequence_length++;
+
+ if (rl_pending_input)
+ {
+ c = rl_pending_input;
+ rl_clear_pending_input ();
+ }
+ else
+ {
+ /* If input is coming from a macro, then use that. */
+ if ((c = _rl_next_macro_key ()))
+ return (c);
+
+ /* If the user has an event function, then call it periodically. */
+ if (rl_event_hook)
+ {
+ while (rl_event_hook && rl_get_char (&c) == 0)
+ {
+ (*rl_event_hook) ();
+ if (rl_done) /* XXX - experimental */
+ return ('\n');
+ if (rl_gather_tyi () < 0) /* XXX - EIO */
+ {
+ rl_done = 1;
+ return ('\n');
+ }
+ }
+ }
+ else
+ {
+ if (rl_get_char (&c) == 0)
+ c = (*rl_getc_function) (rl_instream);
+ }
+ }
+
+ return (c);
+}
+
+int
+rl_getc (stream)
+ FILE *stream;
+{
+ int result;
+ unsigned char c;
+
+ while (1)
+ {
+ result = read (fileno (stream), &c, sizeof (unsigned char));
+
+ if (result == sizeof (unsigned char))
+ return (c);
+
+ /* If zero characters are returned, then the file that we are
+ reading from is empty! Return EOF in that case. */
+ if (result == 0)
+ return (EOF);
+
+#if defined (__BEOS__)
+ if (errno == EINTR)
+ continue;
+#endif
+
+#if defined (EWOULDBLOCK)
+# define X_EWOULDBLOCK EWOULDBLOCK
+#else
+# define X_EWOULDBLOCK -99
+#endif
+
+#if defined (EAGAIN)
+# define X_EAGAIN EAGAIN
+#else
+# define X_EAGAIN -99
+#endif
+
+ if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
+ {
+ if (sh_unset_nodelay_mode (fileno (stream)) < 0)
+ return (EOF);
+ continue;
+ }
+
+#undef X_EWOULDBLOCK
+#undef X_EAGAIN
+
+ /* If the error that we received was SIGINT, then try again,
+ this is simply an interrupted system call to read ().
+ Otherwise, some error ocurred, also signifying EOF. */
+ if (errno != EINTR)
+ return (EOF);
+ }
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* read multibyte char */
+int
+_rl_read_mbchar (mbchar, size)
+ char *mbchar;
+ int size;
+{
+ int mb_len = 0;
+ size_t mbchar_bytes_length;
+ wchar_t wc;
+ mbstate_t ps, ps_back;
+
+ memset(&ps, 0, sizeof (mbstate_t));
+ memset(&ps_back, 0, sizeof (mbstate_t));
+
+ while (mb_len < size)
+ {
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ mbchar[mb_len++] = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
+ if (mbchar_bytes_length == (size_t)(-1))
+ break; /* invalid byte sequence for the current locale */
+ else if (mbchar_bytes_length == (size_t)(-2))
+ {
+ /* shorted bytes */
+ ps = ps_back;
+ continue;
+ }
+ else if (mbchar_bytes_length > (size_t)(0))
+ break;
+ }
+
+ return mb_len;
+}
+
+/* Read a multibyte-character string whose first character is FIRST into
+ the buffer MB of length MBLEN. Returns the last character read, which
+ may be FIRST. Used by the search functions, among others. Very similar
+ to _rl_read_mbchar. */
+int
+_rl_read_mbstring (first, mb, mblen)
+ int first;
+ char *mb;
+ int mblen;
+{
+ int i, c;
+ mbstate_t ps;
+
+ c = first;
+ memset (mb, 0, mblen);
+ for (i = 0; i < mblen; i++)
+ {
+ mb[i] = (char)c;
+ memset (&ps, 0, sizeof (mbstate_t));
+ if (_rl_get_char_len (mb, &ps) == -2)
+ {
+ /* Read more for multibyte character */
+ RL_SETSTATE (RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE (RL_STATE_MOREINPUT);
+ }
+ else
+ break;
+ }
+ return c;
+}
+#endif /* HANDLE_MULTIBYTE */
diff --git a/cmd-line-utils/readline/isearch.c b/cmd-line-utils/readline/isearch.c
new file mode 100644
index 00000000000..137842a841f
--- /dev/null
+++ b/cmd-line-utils/readline/isearch.c
@@ -0,0 +1,560 @@
+/* **************************************************************** */
+/* */
+/* I-Search and Searching */
+/* */
+/* **************************************************************** */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif
+
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* Variables exported to other files in the readline library. */
+char *_rl_isearch_terminators = (char *)NULL;
+
+/* Variables imported from other files in the readline library. */
+extern HIST_ENTRY *_rl_saved_line_for_history;
+
+/* Forward declarations */
+static int rl_search_history PARAMS((int, int));
+
+/* Last line found by the current incremental search, so we don't `find'
+ identical lines many times in a row. */
+static char *prev_line_found;
+
+/* Last search string and its length. */
+static char *last_isearch_string;
+static int last_isearch_string_len;
+
+static const char *default_isearch_terminators = "\033\012";
+
+/* Search backwards through the history looking for a string which is typed
+ interactively. Start with the current line. */
+int
+rl_reverse_search_history (sign, key)
+ int sign, key;
+{
+ return (rl_search_history (-sign, key));
+}
+
+/* Search forwards through the history looking for a string which is typed
+ interactively. Start with the current line. */
+int
+rl_forward_search_history (sign, key)
+ int sign, key;
+{
+ return (rl_search_history (sign, key));
+}
+
+/* Display the current state of the search in the echo-area.
+ SEARCH_STRING contains the string that is being searched for,
+ DIRECTION is zero for forward, or 1 for reverse,
+ WHERE is the history list number of the current line. If it is
+ -1, then this line is the starting one. */
+static void
+rl_display_search (search_string, reverse_p, where)
+ char *search_string;
+ int reverse_p, where __attribute__((unused));
+{
+ char *message;
+ int msglen, searchlen;
+
+ searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
+
+ message = (char *)xmalloc (searchlen + 33);
+ msglen = 0;
+
+#if defined (NOTDEF)
+ if (where != -1)
+ {
+ sprintf (message, "[%d]", where + history_base);
+ msglen = strlen (message);
+ }
+#endif /* NOTDEF */
+
+ message[msglen++] = '(';
+
+ if (reverse_p)
+ {
+ strcpy (message + msglen, "reverse-");
+ msglen += 8;
+ }
+
+ strcpy (message + msglen, "i-search)`");
+ msglen += 10;
+
+ if (search_string)
+ {
+ strcpy (message + msglen, search_string);
+ msglen += searchlen;
+ }
+
+ strcpy (message + msglen, "': ");
+
+ rl_message ("%s", message);
+ free (message);
+ (*rl_redisplay_function) ();
+}
+
+/* Search through the history looking for an interactively typed string.
+ This is analogous to i-search. We start the search in the current line.
+ DIRECTION is which direction to search; >= 0 means forward, < 0 means
+ backwards. */
+static int
+rl_search_history (direction, invoking_key)
+ int direction, invoking_key __attribute__((unused));
+{
+ /* The string that the user types in to search for. */
+ char *search_string;
+
+ /* The current length of SEARCH_STRING. */
+ int search_string_index;
+
+ /* The amount of space that SEARCH_STRING has allocated to it. */
+ int search_string_size;
+
+ /* The list of lines to search through. */
+ char **lines, *allocated_line;
+
+ /* The length of LINES. */
+ int hlen;
+
+ /* Where we get LINES from. */
+ HIST_ENTRY **hlist;
+
+ register int i;
+ int orig_point, orig_mark, orig_line, last_found_line;
+ int c, found, failed, sline_len;
+ int n, wstart, wlen;
+#if defined (HANDLE_MULTIBYTE)
+ char mb[MB_LEN_MAX];
+#endif
+
+ /* The line currently being searched. */
+ char *sline;
+
+ /* Offset in that line. */
+ int line_index;
+
+ /* Non-zero if we are doing a reverse search. */
+ int reverse;
+
+ /* The list of characters which terminate the search, but are not
+ subsequently executed. If the variable isearch-terminators has
+ been set, we use that value, otherwise we use ESC and C-J. */
+ const char *isearch_terminators;
+
+ RL_SETSTATE(RL_STATE_ISEARCH);
+ orig_point = rl_point;
+ orig_mark = rl_mark;
+ last_found_line = orig_line = where_history ();
+ reverse = direction < 0;
+ hlist = history_list ();
+ allocated_line = (char *)NULL;
+
+ isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
+ : default_isearch_terminators;
+
+ /* Create an arrary of pointers to the lines that we want to search. */
+ rl_maybe_replace_line ();
+ i = 0;
+ if (hlist)
+ for (i = 0; hlist[i]; i++);
+
+ /* Allocate space for this many lines, +1 for the current input line,
+ and remember those lines. */
+ lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
+ for (i = 0; i < hlen; i++)
+ lines[i] = hlist[i]->line;
+
+ if (_rl_saved_line_for_history)
+ lines[i] = _rl_saved_line_for_history->line;
+ else
+ {
+ /* Keep track of this so we can free it. */
+ allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
+ strcpy (allocated_line, &rl_line_buffer[0]);
+ lines[i] = allocated_line;
+ }
+
+ hlen++;
+
+ /* The line where we start the search. */
+ i = orig_line;
+
+ rl_save_prompt ();
+
+ /* Initialize search parameters. */
+ search_string = (char *)xmalloc (search_string_size = 128);
+ *search_string = '\0';
+ search_string_index = 0;
+ prev_line_found = (char *)0; /* XXX */
+
+ /* Normalize DIRECTION into 1 or -1. */
+ direction = (direction >= 0) ? 1 : -1;
+
+ rl_display_search (search_string, reverse, -1);
+
+ sline = rl_line_buffer;
+ sline_len = strlen (sline);
+ line_index = rl_point;
+
+ found = failed = 0;
+ for (;;)
+ {
+ rl_command_func_t *f = (rl_command_func_t *)NULL;
+
+ /* Read a key and decide how to proceed. */
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ c = _rl_read_mbstring (c, mb, MB_LEN_MAX);
+#endif
+
+ /* Translate the keys we do something with to opcodes. */
+ if (c >= 0 && _rl_keymap[c].type == ISFUNC)
+ {
+ f = _rl_keymap[c].function;
+
+ if (f == rl_reverse_search_history)
+ c = reverse ? -1 : -2;
+ else if (f == rl_forward_search_history)
+ c = !reverse ? -1 : -2;
+ else if (f == rl_rubout)
+ c = -3;
+ else if (c == CTRL ('G'))
+ c = -4;
+ else if (c == CTRL ('W')) /* XXX */
+ c = -5;
+ else if (c == CTRL ('Y')) /* XXX */
+ c = -6;
+ }
+
+ /* The characters in isearch_terminators (set from the user-settable
+ variable isearch-terminators) are used to terminate the search but
+ not subsequently execute the character as a command. The default
+ value is "\033\012" (ESC and C-J). */
+ if (strchr (isearch_terminators, c))
+ {
+ /* ESC still terminates the search, but if there is pending
+ input or if input arrives within 0.1 seconds (on systems
+ with select(2)) it is used as a prefix character
+ with rl_execute_next. WATCH OUT FOR THIS! This is intended
+ to allow the arrow keys to be used like ^F and ^B are used
+ to terminate the search and execute the movement command.
+ XXX - since _rl_input_available depends on the application-
+ settable keyboard timeout value, this could alternatively
+ use _rl_input_queued(100000) */
+ if (c == ESC && _rl_input_available ())
+ rl_execute_next (ESC);
+ break;
+ }
+
+#define ENDSRCH_CHAR(c) \
+ ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c))
+ {
+ /* This sets rl_pending_input to c; it will be picked up the next
+ time rl_read_key is called. */
+ rl_execute_next (c);
+ break;
+ }
+ }
+ else
+#endif
+ if (c >= 0 && ENDSRCH_CHAR (c))
+ {
+ /* This sets rl_pending_input to c; it will be picked up the next
+ time rl_read_key is called. */
+ rl_execute_next (c);
+ break;
+ }
+
+ switch (c)
+ {
+ case -1:
+ if (search_string_index == 0)
+ {
+ if (last_isearch_string)
+ {
+ search_string_size = 64 + last_isearch_string_len;
+ search_string = (char *)xrealloc (search_string, search_string_size);
+ strcpy (search_string, last_isearch_string);
+ search_string_index = last_isearch_string_len;
+ rl_display_search (search_string, reverse, -1);
+ break;
+ }
+ continue;
+ }
+ else if (reverse)
+ --line_index;
+ else if (line_index != sline_len)
+ ++line_index;
+ else
+ rl_ding ();
+ break;
+
+ /* switch directions */
+ case -2:
+ direction = -direction;
+ reverse = direction < 0;
+ break;
+
+ /* delete character from search string. */
+ case -3: /* C-H, DEL */
+ /* This is tricky. To do this right, we need to keep a
+ stack of search positions for the current search, with
+ sentinels marking the beginning and end. But this will
+ do until we have a real isearch-undo. */
+ if (search_string_index == 0)
+ rl_ding ();
+ else
+ search_string[--search_string_index] = '\0';
+
+ break;
+
+ case -4: /* C-G */
+ rl_replace_line (lines[orig_line], 0);
+ rl_point = orig_point;
+ rl_mark = orig_mark;
+ rl_restore_prompt();
+ rl_clear_message ();
+ if (allocated_line)
+ free (allocated_line);
+ free (lines);
+ RL_UNSETSTATE(RL_STATE_ISEARCH);
+ return 0;
+
+ case -5: /* C-W */
+ /* skip over portion of line we already matched */
+ wstart = rl_point + search_string_index;
+ if (wstart >= rl_end)
+ {
+ rl_ding ();
+ break;
+ }
+
+ /* if not in a word, move to one. */
+ if (rl_alphabetic(rl_line_buffer[wstart]) == 0)
+ {
+ rl_ding ();
+ break;
+ }
+ n = wstart;
+ while (n < rl_end && rl_alphabetic(rl_line_buffer[n]))
+ n++;
+ wlen = n - wstart + 1;
+ if (search_string_index + wlen + 1 >= search_string_size)
+ {
+ search_string_size += wlen + 1;
+ search_string = (char *)xrealloc (search_string, search_string_size);
+ }
+ for (; wstart < n; wstart++)
+ search_string[search_string_index++] = rl_line_buffer[wstart];
+ search_string[search_string_index] = '\0';
+ break;
+
+ case -6: /* C-Y */
+ /* skip over portion of line we already matched */
+ wstart = rl_point + search_string_index;
+ if (wstart >= rl_end)
+ {
+ rl_ding ();
+ break;
+ }
+ n = rl_end - wstart + 1;
+ if (search_string_index + n + 1 >= search_string_size)
+ {
+ search_string_size += n + 1;
+ search_string = (char *)xrealloc (search_string, search_string_size);
+ }
+ for (n = wstart; n < rl_end; n++)
+ search_string[search_string_index++] = rl_line_buffer[n];
+ search_string[search_string_index] = '\0';
+ break;
+
+ default:
+ /* Add character to search string and continue search. */
+ if (search_string_index + 2 >= search_string_size)
+ {
+ search_string_size += 128;
+ search_string = (char *)xrealloc (search_string, search_string_size);
+ }
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ int j, l;
+ for (j = 0, l = strlen (mb); j < l; )
+ search_string[search_string_index++] = mb[j++];
+ }
+ else
+#endif
+ search_string[search_string_index++] = c;
+ search_string[search_string_index] = '\0';
+ break;
+ }
+
+ for (found = failed = 0;;)
+ {
+ int limit = sline_len - search_string_index + 1;
+
+ /* Search the current line. */
+ while (reverse ? (line_index >= 0) : (line_index < limit))
+ {
+ if (STREQN (search_string, sline + line_index, search_string_index))
+ {
+ found++;
+ break;
+ }
+ else
+ line_index += direction;
+ }
+ if (found)
+ break;
+
+ /* Move to the next line, but skip new copies of the line
+ we just found and lines shorter than the string we're
+ searching for. */
+ do
+ {
+ /* Move to the next line. */
+ i += direction;
+
+ /* At limit for direction? */
+ if (reverse ? (i < 0) : (i == hlen))
+ {
+ failed++;
+ break;
+ }
+
+ /* We will need these later. */
+ sline = lines[i];
+ sline_len = strlen (sline);
+ }
+ while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
+ (search_string_index > sline_len));
+
+ if (failed)
+ break;
+
+ /* Now set up the line for searching... */
+ line_index = reverse ? sline_len - search_string_index : 0;
+ }
+
+ if (failed)
+ {
+ /* We cannot find the search string. Ding the bell. */
+ rl_ding ();
+ i = last_found_line;
+ continue; /* XXX - was break */
+ }
+
+ /* We have found the search string. Just display it. But don't
+ actually move there in the history list until the user accepts
+ the location. */
+ if (found)
+ {
+ prev_line_found = lines[i];
+ rl_replace_line (lines[i], 0);
+ rl_point = line_index;
+ last_found_line = i;
+ rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
+ }
+ }
+
+ /* The searching is over. The user may have found the string that she
+ was looking for, or else she may have exited a failing search. If
+ LINE_INDEX is -1, then that shows that the string searched for was
+ not found. We use this to determine where to place rl_point. */
+
+ /* First put back the original state. */
+ strcpy (rl_line_buffer, lines[orig_line]);
+
+ rl_restore_prompt ();
+
+ /* Save the search string for possible later use. */
+ FREE (last_isearch_string);
+ last_isearch_string = search_string;
+ last_isearch_string_len = search_string_index;
+
+ if (last_found_line < orig_line)
+ rl_get_previous_history (orig_line - last_found_line, 0);
+ else
+ rl_get_next_history (last_found_line - orig_line, 0);
+
+ /* If the string was not found, put point at the end of the last matching
+ line. If last_found_line == orig_line, we didn't find any matching
+ history lines at all, so put point back in its original position. */
+ if (line_index < 0)
+ {
+ if (last_found_line == orig_line)
+ line_index = orig_point;
+ else
+ line_index = strlen (rl_line_buffer);
+ rl_mark = orig_mark;
+ }
+
+ rl_point = line_index;
+ /* Don't worry about where to put the mark here; rl_get_previous_history
+ and rl_get_next_history take care of it. */
+
+ rl_clear_message ();
+
+ FREE (allocated_line);
+ free (lines);
+
+ RL_UNSETSTATE(RL_STATE_ISEARCH);
+
+ return 0;
+}
diff --git a/cmd-line-utils/readline/keymaps.c b/cmd-line-utils/readline/keymaps.c
new file mode 100644
index 00000000000..12506d3aab2
--- /dev/null
+++ b/cmd-line-utils/readline/keymaps.c
@@ -0,0 +1,150 @@
+/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+ This file is part of GNU Readline, a library for reading lines
+ of text with interactive input and history editing.
+
+ Readline is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ Readline is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Readline; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h> /* for FILE * definition for readline.h */
+
+#include "readline.h"
+#include "rlconf.h"
+
+#include "emacs_keymap.c"
+
+#if defined (VI_MODE)
+#include "vi_keymap.c"
+#endif
+
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/* */
+/* Functions for manipulating Keymaps. */
+/* */
+/* **************************************************************** */
+
+
+/* Return a new, empty keymap.
+ Free it with free() when you are done. */
+Keymap
+rl_make_bare_keymap ()
+{
+ register int i;
+ Keymap keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY));
+
+ for (i = 0; i < KEYMAP_SIZE; i++)
+ {
+ keymap[i].type = ISFUNC;
+ keymap[i].function = (rl_command_func_t *)NULL;
+ }
+
+ for (i = 'A'; i < ('Z' + 1); i++)
+ {
+ keymap[i].type = ISFUNC;
+ keymap[i].function = rl_do_lowercase_version;
+ }
+
+ return (keymap);
+}
+
+/* Return a new keymap which is a copy of MAP. */
+Keymap
+rl_copy_keymap (map)
+ Keymap map;
+{
+ register int i;
+ Keymap temp = rl_make_bare_keymap ();
+
+ for (i = 0; i < KEYMAP_SIZE; i++)
+ {
+ temp[i].type = map[i].type;
+ temp[i].function = map[i].function;
+ }
+ return (temp);
+}
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+ the uppercase Meta characters bound to run their lowercase equivalents,
+ and the Meta digits bound to produce numeric arguments. */
+Keymap
+rl_make_keymap ()
+{
+ register int i;
+ Keymap newmap;
+
+ newmap = rl_make_bare_keymap ();
+
+ /* All ASCII printing characters are self-inserting. */
+ for (i = ' '; i < 127; i++)
+ newmap[i].function = rl_insert;
+
+ newmap[TAB].function = rl_insert;
+ newmap[RUBOUT].function = rl_rubout; /* RUBOUT == 127 */
+ newmap[CTRL('H')].function = rl_rubout;
+
+#if KEYMAP_SIZE > 128
+ /* Printing characters in some 8-bit character sets. */
+ for (i = 128; i < 160; i++)
+ newmap[i].function = rl_insert;
+
+ /* ISO Latin-1 printing characters should self-insert. */
+ for (i = 160; i < 256; i++)
+ newmap[i].function = rl_insert;
+#endif /* KEYMAP_SIZE > 128 */
+
+ return (newmap);
+}
+
+/* Free the storage associated with MAP. */
+void
+rl_discard_keymap (map)
+ Keymap map;
+{
+ int i;
+
+ if (!map)
+ return;
+
+ for (i = 0; i < KEYMAP_SIZE; i++)
+ {
+ switch (map[i].type)
+ {
+ case ISFUNC:
+ break;
+
+ case ISKMAP:
+ rl_discard_keymap ((Keymap)map[i].function);
+ break;
+
+ case ISMACR:
+ free ((char *)map[i].function);
+ break;
+ }
+ }
+}
diff --git a/cmd-line-utils/readline/keymaps.h b/cmd-line-utils/readline/keymaps.h
new file mode 100644
index 00000000000..66fa2a5ec14
--- /dev/null
+++ b/cmd-line-utils/readline/keymaps.h
@@ -0,0 +1,103 @@
+/* keymaps.h -- Manipulation of readline keymaps. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#ifndef _KEYMAPS_H_
+#define _KEYMAPS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (READLINE_LIBRARY)
+# include "rlstdc.h"
+# include "chardefs.h"
+# include "rltypedefs.h"
+#else
+# include <readline/rlstdc.h>
+# include <readline/chardefs.h>
+# include <readline/rltypedefs.h>
+#endif
+
+/* A keymap contains one entry for each key in the ASCII set.
+ Each entry consists of a type and a pointer.
+ FUNCTION is the address of a function to run, or the
+ address of a keymap to indirect through.
+ TYPE says which kind of thing FUNCTION is. */
+typedef struct _keymap_entry {
+ char type;
+ rl_command_func_t *function;
+} KEYMAP_ENTRY;
+
+/* This must be large enough to hold bindings for all of the characters
+ in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x,
+ and so on) plus one for subsequence matching. */
+#define KEYMAP_SIZE 257
+#define ANYOTHERKEY KEYMAP_SIZE-1
+
+/* I wanted to make the above structure contain a union of:
+ union { rl_command_func_t *function; struct _keymap_entry *keymap; } value;
+ but this made it impossible for me to create a static array.
+ Maybe I need C lessons. */
+
+typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
+typedef KEYMAP_ENTRY *Keymap;
+
+/* The values that TYPE can have in a keymap entry. */
+#define ISFUNC 0
+#define ISKMAP 1
+#define ISMACR 2
+
+extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
+extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
+
+/* Return a new, empty keymap.
+ Free it with free() when you are done. */
+extern Keymap rl_make_bare_keymap PARAMS((void));
+
+/* Return a new keymap which is a copy of MAP. */
+extern Keymap rl_copy_keymap PARAMS((Keymap));
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+ the lowercase Meta characters bound to run their equivalents, and
+ the Meta digits bound to produce numeric arguments. */
+extern Keymap rl_make_keymap PARAMS((void));
+
+/* Free the storage associated with a keymap. */
+extern void rl_discard_keymap PARAMS((Keymap));
+
+/* These functions actually appear in bind.c */
+
+/* Return the keymap corresponding to a given name. Names look like
+ `emacs' or `emacs-meta' or `vi-insert'. */
+extern Keymap rl_get_keymap_by_name PARAMS((const char *));
+
+/* Return the current keymap. */
+extern Keymap rl_get_keymap PARAMS((void));
+
+/* Set the current keymap to MAP. */
+extern void rl_set_keymap PARAMS((Keymap));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _KEYMAPS_H_ */
diff --git a/cmd-line-utils/readline/kill.c b/cmd-line-utils/readline/kill.c
new file mode 100644
index 00000000000..f8c6961bbd3
--- /dev/null
+++ b/cmd-line-utils/readline/kill.c
@@ -0,0 +1,652 @@
+/* kill.c -- kill ring management. */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h> /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/* */
+/* Killing Mechanism */
+/* */
+/* **************************************************************** */
+
+/* What we assume for a max number of kills. */
+#define DEFAULT_MAX_KILLS 10
+
+/* The real variable to look at to find out when to flush kills. */
+static int rl_max_kills = DEFAULT_MAX_KILLS;
+
+/* Where to store killed text. */
+static char **rl_kill_ring = (char **)NULL;
+
+/* Where we are in the kill ring. */
+static int rl_kill_index;
+
+/* How many slots we have in the kill ring. */
+static int rl_kill_ring_length;
+
+static int _rl_copy_to_kill_ring PARAMS((char *, int));
+static int region_kill_internal PARAMS((int));
+static int _rl_copy_word_as_kill PARAMS((int, int));
+static int rl_yank_nth_arg_internal PARAMS((int, int, int));
+
+/* How to say that you only want to save a certain amount
+ of kill material. */
+int
+rl_set_retained_kills (num)
+ int num __attribute__((unused));
+{
+ return 0;
+}
+
+/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary.
+ This uses TEXT directly, so the caller must not free it. If APPEND is
+ non-zero, and the last command was a kill, the text is appended to the
+ current kill ring slot, otherwise prepended. */
+static int
+_rl_copy_to_kill_ring (text, append)
+ char *text;
+ int append;
+{
+ char *old, *new;
+ int slot;
+
+ /* First, find the slot to work with. */
+ if (_rl_last_command_was_kill == 0)
+ {
+ /* Get a new slot. */
+ if (rl_kill_ring == 0)
+ {
+ /* If we don't have any defined, then make one. */
+ rl_kill_ring = (char **)
+ xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
+ rl_kill_ring[slot = 0] = (char *)NULL;
+ }
+ else
+ {
+ /* We have to add a new slot on the end, unless we have
+ exceeded the max limit for remembering kills. */
+ slot = rl_kill_ring_length;
+ if (slot == rl_max_kills)
+ {
+ register int i;
+ free (rl_kill_ring[0]);
+ for (i = 0; i < slot; i++)
+ rl_kill_ring[i] = rl_kill_ring[i + 1];
+ }
+ else
+ {
+ slot = rl_kill_ring_length += 1;
+ rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
+ }
+ rl_kill_ring[--slot] = (char *)NULL;
+ }
+ }
+ else
+ slot = rl_kill_ring_length - 1;
+
+ /* If the last command was a kill, prepend or append. */
+ if (_rl_last_command_was_kill && rl_editing_mode != vi_mode)
+ {
+ old = rl_kill_ring[slot];
+ new = (char *)xmalloc (1 + strlen (old) + strlen (text));
+
+ if (append)
+ {
+ strcpy (new, old);
+ strcat (new, text);
+ }
+ else
+ {
+ strcpy (new, text);
+ strcat (new, old);
+ }
+ free (old);
+ free (text);
+ rl_kill_ring[slot] = new;
+ }
+ else
+ rl_kill_ring[slot] = text;
+
+ rl_kill_index = slot;
+ return 0;
+}
+
+/* The way to kill something. This appends or prepends to the last
+ kill, if the last command was a kill command. if FROM is less
+ than TO, then the text is appended, otherwise prepended. If the
+ last command was not a kill command, then a new slot is made for
+ this kill. */
+int
+rl_kill_text (from, to)
+ int from, to;
+{
+ char *text;
+
+ /* Is there anything to kill? */
+ if (from == to)
+ {
+ _rl_last_command_was_kill++;
+ return 0;
+ }
+
+ text = rl_copy_text (from, to);
+
+ /* Delete the copied text from the line. */
+ rl_delete_text (from, to);
+
+ _rl_copy_to_kill_ring (text, from < to);
+
+ _rl_last_command_was_kill++;
+ return 0;
+}
+
+/* Now REMEMBER! In order to do prepending or appending correctly, kill
+ commands always make rl_point's original position be the FROM argument,
+ and rl_point's extent be the TO argument. */
+
+/* **************************************************************** */
+/* */
+/* Killing Commands */
+/* */
+/* **************************************************************** */
+
+/* Delete the word at point, saving the text in the kill ring. */
+int
+rl_kill_word (count, key)
+ int count, key;
+{
+ int orig_point;
+
+ if (count < 0)
+ return (rl_backward_kill_word (-count, key));
+ else
+ {
+ orig_point = rl_point;
+ rl_forward_word (count, key);
+
+ if (rl_point != orig_point)
+ rl_kill_text (orig_point, rl_point);
+
+ rl_point = orig_point;
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+ return 0;
+}
+
+/* Rubout the word before point, placing it on the kill ring. */
+int
+rl_backward_kill_word (count, ignore)
+ int count, ignore;
+{
+ int orig_point;
+
+ if (count < 0)
+ return (rl_kill_word (-count, ignore));
+ else
+ {
+ orig_point = rl_point;
+ rl_backward_word (count, ignore);
+
+ if (rl_point != orig_point)
+ rl_kill_text (orig_point, rl_point);
+
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+ return 0;
+}
+
+/* Kill from here to the end of the line. If DIRECTION is negative, kill
+ back to the line start instead. */
+int
+rl_kill_line (direction, ignore)
+ int direction, ignore;
+{
+ int orig_point;
+
+ if (direction < 0)
+ return (rl_backward_kill_line (1, ignore));
+ else
+ {
+ orig_point = rl_point;
+ rl_end_of_line (1, ignore);
+ if (orig_point != rl_point)
+ rl_kill_text (orig_point, rl_point);
+ rl_point = orig_point;
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+ return 0;
+}
+
+/* Kill backwards to the start of the line. If DIRECTION is negative, kill
+ forwards to the line end instead. */
+int
+rl_backward_kill_line (direction, ignore)
+ int direction, ignore;
+{
+ int orig_point;
+
+ if (direction < 0)
+ return (rl_kill_line (1, ignore));
+ else
+ {
+ if (!rl_point)
+ rl_ding ();
+ else
+ {
+ orig_point = rl_point;
+ rl_beg_of_line (1, ignore);
+ if (rl_point != orig_point)
+ rl_kill_text (orig_point, rl_point);
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+ }
+ return 0;
+}
+
+/* Kill the whole line, no matter where point is. */
+int
+rl_kill_full_line (count, ignore)
+ int count __attribute__((unused)), ignore __attribute__((unused));
+{
+ rl_begin_undo_group ();
+ rl_point = 0;
+ rl_kill_text (rl_point, rl_end);
+ rl_mark = 0;
+ rl_end_undo_group ();
+ return 0;
+}
+
+/* The next two functions mimic unix line editing behaviour, except they
+ save the deleted text on the kill ring. This is safer than not saving
+ it, and since we have a ring, nobody should get screwed. */
+
+/* This does what C-w does in Unix. We can't prevent people from
+ using behaviour that they expect. */
+int
+rl_unix_word_rubout (count, key)
+ int count, key __attribute__((unused));
+{
+ int orig_point;
+
+ if (rl_point == 0)
+ rl_ding ();
+ else
+ {
+ orig_point = rl_point;
+ if (count <= 0)
+ count = 1;
+
+ while (count--)
+ {
+ while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0))
+ rl_point--;
+ }
+
+ rl_kill_text (orig_point, rl_point);
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+ return 0;
+}
+
+/* Here is C-u doing what Unix does. You don't *have* to use these
+ key-bindings. We have a choice of killing the entire line, or
+ killing from where we are to the start of the line. We choose the
+ latter, because if you are a Unix weenie, then you haven't backspaced
+ into the line at all, and if you aren't, then you know what you are
+ doing. */
+int
+rl_unix_line_discard (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (rl_point == 0)
+ rl_ding ();
+ else
+ {
+ rl_kill_text (rl_point, 0);
+ rl_point = 0;
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+ return 0;
+}
+
+/* Copy the text in the `region' to the kill ring. If DELETE is non-zero,
+ delete the text from the line as well. */
+static int
+region_kill_internal (delete)
+ int delete;
+{
+ char *text;
+
+ if (rl_mark != rl_point)
+ {
+ text = rl_copy_text (rl_point, rl_mark);
+ if (delete)
+ rl_delete_text (rl_point, rl_mark);
+ _rl_copy_to_kill_ring (text, rl_point < rl_mark);
+ }
+
+ _rl_last_command_was_kill++;
+ return 0;
+}
+
+/* Copy the text in the region to the kill ring. */
+int
+rl_copy_region_to_kill (count, ignore)
+ int count __attribute__((unused)), ignore __attribute__((unused));
+{
+ return (region_kill_internal (0));
+}
+
+/* Kill the text between the point and mark. */
+int
+rl_kill_region (count, ignore)
+ int count __attribute__((unused)), ignore __attribute__((unused));
+{
+ int r, npoint;
+
+ npoint = (rl_point < rl_mark) ? rl_point : rl_mark;
+ r = region_kill_internal (1);
+ _rl_fix_point (1);
+ rl_point = npoint;
+ return r;
+}
+
+/* Copy COUNT words to the kill ring. DIR says which direction we look
+ to find the words. */
+static int
+_rl_copy_word_as_kill (count, dir)
+ int count, dir;
+{
+ int om, op, r;
+
+ om = rl_mark;
+ op = rl_point;
+
+ if (dir > 0)
+ rl_forward_word (count, 0);
+ else
+ rl_backward_word (count, 0);
+
+ rl_mark = rl_point;
+
+ if (dir > 0)
+ rl_backward_word (count, 0);
+ else
+ rl_forward_word (count, 0);
+
+ r = region_kill_internal (0);
+
+ rl_mark = om;
+ rl_point = op;
+
+ return r;
+}
+
+int
+rl_copy_forward_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_copy_backward_word (-count, key));
+
+ return (_rl_copy_word_as_kill (count, 1));
+}
+
+int
+rl_copy_backward_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_copy_forward_word (-count, key));
+
+ return (_rl_copy_word_as_kill (count, -1));
+}
+
+/* Yank back the last killed text. This ignores arguments. */
+int
+rl_yank (count, ignore)
+ int count __attribute__((unused)), ignore __attribute__((unused));
+{
+ if (rl_kill_ring == 0)
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+
+ _rl_set_mark_at_pos (rl_point);
+ rl_insert_text (rl_kill_ring[rl_kill_index]);
+ return 0;
+}
+
+/* If the last command was yank, or yank_pop, and the text just
+ before point is identical to the current kill item, then
+ delete that text from the line, rotate the index down, and
+ yank back some other text. */
+int
+rl_yank_pop (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ int l, n;
+
+ if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
+ !rl_kill_ring)
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+
+ l = strlen (rl_kill_ring[rl_kill_index]);
+ n = rl_point - l;
+ if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
+ {
+ rl_delete_text (n, rl_point);
+ rl_point = n;
+ rl_kill_index--;
+ if (rl_kill_index < 0)
+ rl_kill_index = rl_kill_ring_length - 1;
+ rl_yank (1, 0);
+ return 0;
+ }
+ else
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+}
+
+/* Yank the COUNTh argument from the previous history line, skipping
+ HISTORY_SKIP lines before looking for the `previous line'. */
+static int
+rl_yank_nth_arg_internal (count, ignore, history_skip)
+ int count, ignore, history_skip;
+{
+ register HIST_ENTRY *entry;
+ char *arg;
+ int i, pos;
+
+ pos = where_history ();
+
+ if (history_skip)
+ {
+ for (i = 0; i < history_skip; i++)
+ entry = previous_history ();
+ }
+
+ entry = previous_history ();
+
+ history_set_pos (pos);
+
+ if (entry == 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ arg = history_arg_extract (count, count, entry->line);
+ if (!arg || !*arg)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ rl_begin_undo_group ();
+
+ _rl_set_mark_at_pos (rl_point);
+
+#if defined (VI_MODE)
+ /* Vi mode always inserts a space before yanking the argument, and it
+ inserts it right *after* rl_point. */
+ if (rl_editing_mode == vi_mode)
+ {
+ rl_vi_append_mode (1, ignore);
+ rl_insert_text (" ");
+ }
+#endif /* VI_MODE */
+
+ rl_insert_text (arg);
+ free (arg);
+
+ rl_end_undo_group ();
+ return 0;
+}
+
+/* Yank the COUNTth argument from the previous history line. */
+int
+rl_yank_nth_arg (count, ignore)
+ int count, ignore;
+{
+ return (rl_yank_nth_arg_internal (count, ignore, 0));
+}
+
+/* Yank the last argument from the previous history line. This `knows'
+ how rl_yank_nth_arg treats a count of `$'. With an argument, this
+ behaves the same as rl_yank_nth_arg. */
+int
+rl_yank_last_arg (count, key)
+ int count, key;
+{
+ static int history_skip = 0;
+ static int explicit_arg_p = 0;
+ static int count_passed = 1;
+ static int direction = 1;
+ static int undo_needed = 0;
+ int retval;
+
+ if (rl_last_func != rl_yank_last_arg)
+ {
+ history_skip = 0;
+ explicit_arg_p = rl_explicit_arg;
+ count_passed = count;
+ direction = 1;
+ }
+ else
+ {
+ if (undo_needed)
+ rl_do_undo ();
+ if (count < 1)
+ direction = -direction;
+ history_skip += direction;
+ if (history_skip < 0)
+ history_skip = 0;
+ }
+
+ if (explicit_arg_p)
+ retval = rl_yank_nth_arg_internal (count_passed, key, history_skip);
+ else
+ retval = rl_yank_nth_arg_internal ('$', key, history_skip);
+
+ undo_needed = retval == 0;
+ return retval;
+}
+
+/* A special paste command for users of Cygnus's cygwin32. */
+#if defined (__CYGWIN__)
+#include <windows.h>
+
+int
+rl_paste_from_clipboard (count, key)
+ int count, key;
+{
+ char *data, *ptr;
+ int len;
+
+ if (OpenClipboard (NULL) == 0)
+ return (0);
+
+ data = (char *)GetClipboardData (CF_TEXT);
+ if (data)
+ {
+ ptr = strchr (data, '\r');
+ if (ptr)
+ {
+ len = ptr - data;
+ ptr = (char *)xmalloc (len + 1);
+ ptr[len] = '\0';
+ strncpy (ptr, data, len);
+ }
+ else
+ ptr = data;
+ _rl_set_mark_at_pos (rl_point);
+ rl_insert_text (ptr);
+ if (ptr != data)
+ free (ptr);
+ CloseClipboard ();
+ }
+ return (0);
+}
+#endif /* __CYGWIN__ */
diff --git a/cmd-line-utils/readline/macro.c b/cmd-line-utils/readline/macro.c
new file mode 100644
index 00000000000..7ab4b6ca657
--- /dev/null
+++ b/cmd-line-utils/readline/macro.c
@@ -0,0 +1,262 @@
+/* macro.c -- keyboard macros for readline. */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h> /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/* */
+/* Hacking Keyboard Macros */
+/* */
+/* **************************************************************** */
+
+/* The currently executing macro string. If this is non-zero,
+ then it is a malloc ()'ed string where input is coming from. */
+char *rl_executing_macro = (char *)NULL;
+
+/* The offset in the above string to the next character to be read. */
+static int executing_macro_index;
+
+/* The current macro string being built. Characters get stuffed
+ in here by add_macro_char (). */
+static char *current_macro = (char *)NULL;
+
+/* The size of the buffer allocated to current_macro. */
+static int current_macro_size;
+
+/* The index at which characters are being added to current_macro. */
+static int current_macro_index;
+
+/* A structure used to save nested macro strings.
+ It is a linked list of string/index for each saved macro. */
+struct saved_macro {
+ struct saved_macro *next;
+ char *string;
+ int sindex;
+};
+
+/* The list of saved macros. */
+static struct saved_macro *macro_list = (struct saved_macro *)NULL;
+
+/* Set up to read subsequent input from STRING.
+ STRING is free ()'ed when we are done with it. */
+void
+_rl_with_macro_input (string)
+ char *string;
+{
+ _rl_push_executing_macro ();
+ rl_executing_macro = string;
+ executing_macro_index = 0;
+ RL_SETSTATE(RL_STATE_MACROINPUT);
+}
+
+/* Return the next character available from a macro, or 0 if
+ there are no macro characters. */
+int
+_rl_next_macro_key ()
+{
+ if (rl_executing_macro == 0)
+ return (0);
+
+ if (rl_executing_macro[executing_macro_index] == 0)
+ {
+ _rl_pop_executing_macro ();
+ return (_rl_next_macro_key ());
+ }
+
+ return (rl_executing_macro[executing_macro_index++]);
+}
+
+/* Save the currently executing macro on a stack of saved macros. */
+void
+_rl_push_executing_macro ()
+{
+ struct saved_macro *saver;
+
+ saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
+ saver->next = macro_list;
+ saver->sindex = executing_macro_index;
+ saver->string = rl_executing_macro;
+
+ macro_list = saver;
+}
+
+/* Discard the current macro, replacing it with the one
+ on the top of the stack of saved macros. */
+void
+_rl_pop_executing_macro ()
+{
+ struct saved_macro *macro;
+
+ FREE (rl_executing_macro);
+ rl_executing_macro = (char *)NULL;
+ executing_macro_index = 0;
+
+ if (macro_list)
+ {
+ macro = macro_list;
+ rl_executing_macro = macro_list->string;
+ executing_macro_index = macro_list->sindex;
+ macro_list = macro_list->next;
+ free (macro);
+ }
+
+ if (rl_executing_macro == 0)
+ RL_UNSETSTATE(RL_STATE_MACROINPUT);
+}
+
+/* Add a character to the macro being built. */
+void
+_rl_add_macro_char (c)
+ int c;
+{
+ if (current_macro_index + 1 >= current_macro_size)
+ {
+ if (current_macro == 0)
+ current_macro = (char *)xmalloc (current_macro_size = 25);
+ else
+ current_macro = (char *)xrealloc (current_macro, current_macro_size += 25);
+ }
+
+ current_macro[current_macro_index++] = c;
+ current_macro[current_macro_index] = '\0';
+}
+
+void
+_rl_kill_kbd_macro ()
+{
+ if (current_macro)
+ {
+ free (current_macro);
+ current_macro = (char *) NULL;
+ }
+ current_macro_size = current_macro_index = 0;
+
+ FREE (rl_executing_macro);
+ rl_executing_macro = (char *) NULL;
+ executing_macro_index = 0;
+
+ RL_UNSETSTATE(RL_STATE_MACRODEF);
+}
+
+/* Begin defining a keyboard macro.
+ Keystrokes are recorded as they are executed.
+ End the definition with rl_end_kbd_macro ().
+ If a numeric argument was explicitly typed, then append this
+ definition to the end of the existing macro, and start by
+ re-executing the existing macro. */
+int
+rl_start_kbd_macro (ignore1, ignore2)
+ int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
+{
+ if (RL_ISSTATE (RL_STATE_MACRODEF))
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+
+ if (rl_explicit_arg)
+ {
+ if (current_macro)
+ _rl_with_macro_input (savestring (current_macro));
+ }
+ else
+ current_macro_index = 0;
+
+ RL_SETSTATE(RL_STATE_MACRODEF);
+ return 0;
+}
+
+/* Stop defining a keyboard macro.
+ A numeric argument says to execute the macro right now,
+ that many times, counting the definition as the first time. */
+int
+rl_end_kbd_macro (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ if (RL_ISSTATE (RL_STATE_MACRODEF) == 0)
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+
+ current_macro_index -= rl_key_sequence_length - 1;
+ current_macro[current_macro_index] = '\0';
+
+ RL_UNSETSTATE(RL_STATE_MACRODEF);
+
+ return (rl_call_last_kbd_macro (--count, 0));
+}
+
+/* Execute the most recently defined keyboard macro.
+ COUNT says how many times to execute it. */
+int
+rl_call_last_kbd_macro (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ if (current_macro == 0)
+ _rl_abort_internal ();
+
+ if (RL_ISSTATE (RL_STATE_MACRODEF))
+ {
+ rl_ding (); /* no recursive macros */
+ current_macro[--current_macro_index] = '\0'; /* erase this char */
+ return 0;
+ }
+
+ while (count--)
+ _rl_with_macro_input (savestring (current_macro));
+ return 0;
+}
+
+void
+rl_push_macro_input (macro)
+ char *macro;
+{
+ _rl_with_macro_input (macro);
+}
diff --git a/cmd-line-utils/readline/mbutil.c b/cmd-line-utils/readline/mbutil.c
new file mode 100644
index 00000000000..debad6320ce
--- /dev/null
+++ b/cmd-line-utils/readline/mbutil.c
@@ -0,0 +1,337 @@
+/* mbutil.c -- readline multibyte character utility functions */
+
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "posixjmp.h"
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h> /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (TIOCSTAT_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif /* TIOCSTAT_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* Declared here so it can be shared between the readline and history
+ libraries. */
+#if defined (HANDLE_MULTIBYTE)
+int rl_byte_oriented = 0;
+#else
+int rl_byte_oriented = 1;
+#endif
+
+/* **************************************************************** */
+/* */
+/* Multibyte Character Utility Functions */
+/* */
+/* **************************************************************** */
+
+#if defined(HANDLE_MULTIBYTE)
+
+static int
+_rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
+ char *string;
+ int seed, count, find_non_zero;
+{
+ size_t tmp = 0;
+ mbstate_t ps;
+ int point = 0;
+ wchar_t wc;
+
+ memset(&ps, 0, sizeof (mbstate_t));
+ if (seed < 0)
+ seed = 0;
+ if (count <= 0)
+ return seed;
+
+ point = seed + _rl_adjust_point(string, seed, &ps);
+ /* if this is true, means that seed was not pointed character
+ started byte. So correct the point and consume count */
+ if (seed < point)
+ count --;
+
+ while (count > 0)
+ {
+ tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
+ if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+ {
+ /* invalid bytes. asume a byte represents a character */
+ point++;
+ count--;
+ /* reset states. */
+ memset(&ps, 0, sizeof(mbstate_t));
+ }
+ else if (tmp == (size_t)0)
+ /* found '\0' char */
+ break;
+ else
+ {
+ /* valid bytes */
+ point += tmp;
+ if (find_non_zero)
+ {
+ if (wcwidth (wc) == 0)
+ continue;
+ else
+ count--;
+ }
+ else
+ count--;
+ }
+ }
+
+ if (find_non_zero)
+ {
+ tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
+ while (wcwidth (wc) == 0)
+ {
+ point += tmp;
+ tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
+ if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2))
+ break;
+ }
+ }
+ return point;
+}
+
+static int
+_rl_find_prev_mbchar_internal (string, seed, find_non_zero)
+ char *string;
+ int seed, find_non_zero;
+{
+ mbstate_t ps;
+ int prev, non_zero_prev, point, length;
+ size_t tmp;
+ wchar_t wc;
+
+ memset(&ps, 0, sizeof(mbstate_t));
+ length = strlen(string);
+
+ if (seed < 0)
+ return 0;
+ else if (length < seed)
+ return length;
+
+ prev = non_zero_prev = point = 0;
+ while (point < seed)
+ {
+ tmp = mbrtowc (&wc, string + point, length - point, &ps);
+ if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+ {
+ /* in this case, bytes are invalid or shorted to compose
+ multibyte char, so assume that the first byte represents
+ a single character anyway. */
+ tmp = 1;
+ /* clear the state of the byte sequence, because
+ in this case effect of mbstate is undefined */
+ memset(&ps, 0, sizeof (mbstate_t));
+ }
+ else if (tmp == 0)
+ break; /* Found '\0' char. Can this happen? */
+ else
+ {
+ if (find_non_zero)
+ {
+ if (wcwidth (wc) != 0)
+ prev = point;
+ }
+ else
+ prev = point;
+ }
+
+ point += tmp;
+ }
+
+ return prev;
+}
+
+/* return the number of bytes parsed from the multibyte sequence starting
+ at src, if a non-L'\0' wide character was recognized. It returns 0,
+ if a L'\0' wide character was recognized. It returns (size_t)(-1),
+ if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
+ if it couldn't parse a complete multibyte character. */
+int
+_rl_get_char_len (src, ps)
+ const char *src;
+ mbstate_t *ps;
+{
+ size_t tmp;
+
+ tmp = mbrlen((const char *)src, (size_t)strlen (src), ps);
+ if (tmp == (size_t)(-2))
+ {
+ /* shorted to compose multibyte char */
+ memset (ps, 0, sizeof(mbstate_t));
+ return -2;
+ }
+ else if (tmp == (size_t)(-1))
+ {
+ /* invalid to compose multibyte char */
+ /* initialize the conversion state */
+ memset (ps, 0, sizeof(mbstate_t));
+ return -1;
+ }
+ else if (tmp == (size_t)0)
+ return 0;
+ else
+ return (int)tmp;
+}
+
+/* compare the specified two characters. If the characters matched,
+ return 1. Otherwise return 0. */
+int
+_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
+ char *buf1, *buf2;
+ mbstate_t *ps1, *ps2;
+ int pos1, pos2;
+{
+ int i, w1, w2;
+
+ if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 ||
+ (w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 ||
+ (w1 != w2) ||
+ (buf1[pos1] != buf2[pos2]))
+ return 0;
+
+ for (i = 1; i < w1; i++)
+ if (buf1[pos1+i] != buf2[pos2+i])
+ return 0;
+
+ return 1;
+}
+
+/* adjust pointed byte and find mbstate of the point of string.
+ adjusted point will be point <= adjusted_point, and returns
+ differences of the byte(adjusted_point - point).
+ if point is invalied (point < 0 || more than string length),
+ it returns -1 */
+int
+_rl_adjust_point(string, point, ps)
+ const char *string;
+ int point;
+ mbstate_t *ps;
+{
+ size_t tmp = 0;
+ int length;
+ int pos = 0;
+
+ length = strlen(string);
+ if (point < 0)
+ return -1;
+ if (length < point)
+ return -1;
+
+ while (pos < point)
+ {
+ tmp = mbrlen (string + pos, length - pos, ps);
+ if((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+ {
+ /* in this case, bytes are invalid or shorted to compose
+ multibyte char, so assume that the first byte represents
+ a single character anyway. */
+ pos++;
+ /* clear the state of the byte sequence, because
+ in this case effect of mbstate is undefined */
+ memset (ps, 0, sizeof (mbstate_t));
+ }
+ else
+ pos += tmp;
+ }
+
+ return (pos - point);
+}
+
+int
+_rl_is_mbchar_matched (string, seed, end, mbchar, length)
+ char *string;
+ int seed, end;
+ char *mbchar;
+ int length;
+{
+ int i;
+
+ if ((end - seed) < length)
+ return 0;
+
+ for (i = 0; i < length; i++)
+ if (string[seed + i] != mbchar[i])
+ return 0;
+ return 1;
+}
+#endif /* HANDLE_MULTIBYTE */
+
+/* Find next `count' characters started byte point of the specified seed.
+ If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte
+ characters. */
+#undef _rl_find_next_mbchar
+int
+_rl_find_next_mbchar (string, seed, count, flags)
+ char *string __attribute__((unused));
+ int seed, count, flags __attribute__((unused));
+{
+#if defined (HANDLE_MULTIBYTE)
+ return _rl_find_next_mbchar_internal (string, seed, count, flags);
+#else
+ return (seed + count);
+#endif
+}
+
+/* Find previous character started byte point of the specified seed.
+ Returned point will be point <= seed. If flags is MB_FIND_NONZERO,
+ we look for non-zero-width multibyte characters. */
+#undef _rl_find_prev_mbchar
+int
+_rl_find_prev_mbchar (string, seed, flags)
+ char *string __attribute__((unused));
+ int seed, flags __attribute__((unused));
+{
+#if defined (HANDLE_MULTIBYTE)
+ return _rl_find_prev_mbchar_internal (string, seed, flags);
+#else
+ return ((seed == 0) ? seed : seed - 1);
+#endif
+}
diff --git a/cmd-line-utils/readline/misc.c b/cmd-line-utils/readline/misc.c
new file mode 100644
index 00000000000..94ad433473b
--- /dev/null
+++ b/cmd-line-utils/readline/misc.c
@@ -0,0 +1,496 @@
+/* misc.c -- miscellaneous bindable readline functions. */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+# include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+static int rl_digit_loop PARAMS((void));
+static void _rl_history_set_point PARAMS((void));
+
+/* Forward declarations used in this file */
+void _rl_free_history_entry PARAMS((HIST_ENTRY *));
+
+/* If non-zero, rl_get_previous_history and rl_get_next_history attempt
+ to preserve the value of rl_point from line to line. */
+int _rl_history_preserve_point = 0;
+
+/* Saved target point for when _rl_history_preserve_point is set. Special
+ value of -1 means that point is at the end of the line. */
+int _rl_history_saved_point = -1;
+
+/* **************************************************************** */
+/* */
+/* Numeric Arguments */
+/* */
+/* **************************************************************** */
+
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+static int
+rl_digit_loop ()
+{
+ int key, c, sawminus, sawdigits;
+
+ rl_save_prompt ();
+
+ RL_SETSTATE(RL_STATE_NUMERICARG);
+ sawminus = sawdigits = 0;
+ while (1)
+ {
+ if (rl_numeric_arg > 1000000)
+ {
+ sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
+ rl_ding ();
+ rl_restore_prompt ();
+ rl_clear_message ();
+ RL_UNSETSTATE(RL_STATE_NUMERICARG);
+ return 1;
+ }
+ rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ key = c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (c < 0)
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+
+ /* If we see a key bound to `universal-argument' after seeing digits,
+ it ends the argument but is otherwise ignored. */
+ if (_rl_keymap[c].type == ISFUNC &&
+ _rl_keymap[c].function == rl_universal_argument)
+ {
+ if (sawdigits == 0)
+ {
+ rl_numeric_arg *= 4;
+ continue;
+ }
+ else
+ {
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ key = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ rl_restore_prompt ();
+ rl_clear_message ();
+ RL_UNSETSTATE(RL_STATE_NUMERICARG);
+ return (_rl_dispatch (key, _rl_keymap));
+ }
+ }
+
+ c = UNMETA (c);
+
+ if (_rl_digit_p (c))
+ {
+ rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
+ sawdigits = rl_explicit_arg = 1;
+ }
+ else if (c == '-' && rl_explicit_arg == 0)
+ {
+ rl_numeric_arg = sawminus = 1;
+ rl_arg_sign = -1;
+ }
+ else
+ {
+ /* Make M-- command equivalent to M--1 command. */
+ if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
+ rl_explicit_arg = 1;
+ rl_restore_prompt ();
+ rl_clear_message ();
+ RL_UNSETSTATE(RL_STATE_NUMERICARG);
+ return (_rl_dispatch (key, _rl_keymap));
+ }
+ }
+
+ /*NOTREACHED*/
+}
+
+/* Add the current digit to the argument in progress. */
+int
+rl_digit_argument (ignore, key)
+ int ignore __attribute__((unused)), key;
+{
+ rl_execute_next (key);
+ return (rl_digit_loop ());
+}
+
+/* What to do when you abort reading an argument. */
+int
+rl_discard_argument ()
+{
+ rl_ding ();
+ rl_clear_message ();
+ _rl_init_argument ();
+ return 0;
+}
+
+/* Create a default argument. */
+int
+_rl_init_argument ()
+{
+ rl_numeric_arg = rl_arg_sign = 1;
+ rl_explicit_arg = 0;
+ return 0;
+}
+
+/* C-u, universal argument. Multiply the current argument by 4.
+ Read a key. If the key has nothing to do with arguments, then
+ dispatch on it. If the key is the abort character then abort. */
+int
+rl_universal_argument (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ rl_numeric_arg *= 4;
+ return (rl_digit_loop ());
+}
+
+/* **************************************************************** */
+/* */
+/* History Utilities */
+/* */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+ the history features of readline. This is our local interface to
+ the history mechanism. */
+
+/* While we are editing the history, this is the saved
+ version of the original line. */
+HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+void
+_rl_start_using_history ()
+{
+ using_history ();
+ if (_rl_saved_line_for_history)
+ _rl_free_history_entry (_rl_saved_line_for_history);
+
+ _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+void
+_rl_free_history_entry (entry)
+ HIST_ENTRY *entry;
+{
+ if (entry == 0)
+ return;
+ if (entry->line)
+ free (entry->line);
+ free (entry);
+}
+
+/* Perhaps put back the current line if it has changed. */
+int
+rl_maybe_replace_line ()
+{
+ HIST_ENTRY *temp;
+
+ temp = current_history ();
+ /* If the current line has changed, save the changes. */
+ if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
+ {
+ temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
+ free (temp->line);
+ free (temp);
+ }
+ return 0;
+}
+
+/* Restore the _rl_saved_line_for_history if there is one. */
+int
+rl_maybe_unsave_line ()
+{
+ if (_rl_saved_line_for_history)
+ {
+ rl_replace_line (_rl_saved_line_for_history->line, 0);
+ rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
+ _rl_free_history_entry (_rl_saved_line_for_history);
+ _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+ rl_point = rl_end; /* rl_replace_line sets rl_end */
+ }
+ else
+ rl_ding ();
+ return 0;
+}
+
+/* Save the current line in _rl_saved_line_for_history. */
+int
+rl_maybe_save_line ()
+{
+ if (_rl_saved_line_for_history == 0)
+ {
+ _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+ _rl_saved_line_for_history->line = savestring (rl_line_buffer);
+ _rl_saved_line_for_history->data = (char *)rl_undo_list;
+ }
+ return 0;
+}
+
+int
+_rl_free_saved_history_line ()
+{
+ if (_rl_saved_line_for_history)
+ {
+ _rl_free_history_entry (_rl_saved_line_for_history);
+ _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+ }
+ return 0;
+}
+
+static void
+_rl_history_set_point ()
+{
+ rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
+ ? _rl_history_saved_point
+ : rl_end;
+ if (rl_point > rl_end)
+ rl_point = rl_end;
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ rl_point = 0;
+#endif /* VI_MODE */
+
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = (rl_point == rl_end ? 0 : rl_end);
+}
+
+void
+rl_replace_from_history (entry, flags)
+ HIST_ENTRY *entry;
+ int flags __attribute__((unused)); /* currently unused */
+{
+ rl_replace_line (entry->line, 0);
+ rl_undo_list = (UNDO_LIST *)entry->data;
+ rl_point = rl_end;
+ rl_mark = 0;
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ {
+ rl_point = 0;
+ rl_mark = rl_end;
+ }
+#endif
+}
+
+/* **************************************************************** */
+/* */
+/* History Commands */
+/* */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+int
+rl_beginning_of_history (count, key)
+ int count __attribute__((unused)), key;
+{
+ return (rl_get_previous_history (1 + where_history (), key));
+}
+
+/* Meta-> goes to the end of the history. (The current line). */
+int
+rl_end_of_history (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ rl_maybe_replace_line ();
+ using_history ();
+ rl_maybe_unsave_line ();
+ return 0;
+}
+
+/* Move down to the next history line. */
+int
+rl_get_next_history (count, key)
+ int count, key;
+{
+ HIST_ENTRY *temp;
+
+ if (count < 0)
+ return (rl_get_previous_history (-count, key));
+
+ if (count == 0)
+ return 0;
+
+ rl_maybe_replace_line ();
+
+ /* either not saved by rl_newline or at end of line, so set appropriately. */
+ if (_rl_history_saved_point == -1 && (rl_point || rl_end))
+ _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+ temp = (HIST_ENTRY *)NULL;
+ while (count)
+ {
+ temp = next_history ();
+ if (!temp)
+ break;
+ --count;
+ }
+
+ if (temp == 0)
+ rl_maybe_unsave_line ();
+ else
+ {
+ rl_replace_from_history (temp, 0);
+ _rl_history_set_point ();
+ }
+ return 0;
+}
+
+/* Get the previous item out of our interactive history, making it the current
+ line. If there is no previous history, just ding. */
+int
+rl_get_previous_history (count, key)
+ int count, key;
+{
+ HIST_ENTRY *old_temp, *temp;
+
+ if (count < 0)
+ return (rl_get_next_history (-count, key));
+
+ if (count == 0)
+ return 0;
+
+ /* either not saved by rl_newline or at end of line, so set appropriately. */
+ if (_rl_history_saved_point == -1 && (rl_point || rl_end))
+ _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+ /* If we don't have a line saved, then save this one. */
+ rl_maybe_save_line ();
+
+ /* If the current line has changed, save the changes. */
+ rl_maybe_replace_line ();
+
+ temp = old_temp = (HIST_ENTRY *)NULL;
+ while (count)
+ {
+ temp = previous_history ();
+ if (temp == 0)
+ break;
+
+ old_temp = temp;
+ --count;
+ }
+
+ /* If there was a large argument, and we moved back to the start of the
+ history, that is not an error. So use the last value found. */
+ if (!temp && old_temp)
+ temp = old_temp;
+
+ if (temp == 0)
+ rl_ding ();
+ else
+ {
+ rl_replace_from_history (temp, 0);
+ _rl_history_set_point ();
+ }
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Editing Modes */
+/* */
+/* **************************************************************** */
+/* How to toggle back and forth between editing modes. */
+int
+rl_vi_editing_mode (count, key)
+ int count __attribute__((unused)), key;
+{
+#if defined (VI_MODE)
+ _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
+ rl_editing_mode = vi_mode;
+ rl_vi_insertion_mode (1, key);
+#endif /* VI_MODE */
+
+ return 0;
+}
+
+int
+rl_emacs_editing_mode (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ rl_editing_mode = emacs_mode;
+ _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
+ _rl_keymap = emacs_standard_keymap;
+ return 0;
+}
+
+/* Function for the rest of the library to use to set insert/overwrite mode. */
+void
+_rl_set_insert_mode (im, force)
+ int im, force __attribute__((unused));
+{
+#ifdef CURSOR_MODE
+ _rl_set_cursor (im, force);
+#endif
+
+ rl_insert_mode = im;
+}
+
+/* Toggle overwrite mode. A positive explicit argument selects overwrite
+ mode. A negative or zero explicit argument selects insert mode. */
+int
+rl_overwrite_mode (count, key)
+ int count, key __attribute__((unused));
+{
+ if (rl_explicit_arg == 0)
+ _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
+ else if (count > 0)
+ _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
+ else
+ _rl_set_insert_mode (RL_IM_INSERT, 0);
+
+ return 0;
+}
diff --git a/cmd-line-utils/readline/nls.c b/cmd-line-utils/readline/nls.c
new file mode 100644
index 00000000000..706c8195c10
--- /dev/null
+++ b/cmd-line-utils/readline/nls.c
@@ -0,0 +1,225 @@
+/* nls.c -- skeletal internationalization code. */
+
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+# include <locale.h>
+#endif
+
+#include <ctype.h>
+
+#include "rldefs.h"
+#include "readline.h"
+#include "rlshell.h"
+#include "rlprivate.h"
+
+#if !defined (HAVE_SETLOCALE)
+/* A list of legal values for the LANG or LC_CTYPE environment variables.
+ If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
+ or LANG environment variable (using the first of those with a value),
+ readline eight-bit mode is enabled. */
+static char *legal_lang_values[] =
+{
+ "iso88591",
+ "iso88592",
+ "iso88593",
+ "iso88594",
+ "iso88595",
+ "iso88596",
+ "iso88597",
+ "iso88598",
+ "iso88599",
+ "iso885910",
+ "koi8r",
+ 0
+};
+
+static char *normalize_codeset PARAMS((char *));
+static char *find_codeset PARAMS((char *, size_t *));
+#endif /* !HAVE_SETLOCALE */
+
+/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
+ to decide the defaults for 8-bit character input and output. Returns
+ 1 if we set eight-bit mode. */
+int
+_rl_init_eightbit ()
+{
+/* If we have setlocale(3), just check the current LC_CTYPE category
+ value, and go into eight-bit mode if it's not C or POSIX. */
+#if defined (HAVE_SETLOCALE)
+ char *t;
+
+ /* Set the LC_CTYPE locale category from environment variables. */
+ t = setlocale (LC_CTYPE, "");
+ if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
+ {
+ _rl_meta_flag = 1;
+ _rl_convert_meta_chars_to_ascii = 0;
+ _rl_output_meta_chars = 1;
+ return (1);
+ }
+ else
+ return (0);
+
+#else /* !HAVE_SETLOCALE */
+ char *lspec, *t;
+ int i;
+
+ /* We don't have setlocale. Finesse it. Check the environment for the
+ appropriate variables and set eight-bit mode if they have the right
+ values. */
+ lspec = sh_get_env_value ("LC_ALL");
+ if (lspec == 0) lspec = sh_get_env_value ("LC_CTYPE");
+ if (lspec == 0) lspec = sh_get_env_value ("LANG");
+ if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
+ return (0);
+ for (i = 0; t && legal_lang_values[i]; i++)
+ if (STREQ (t, legal_lang_values[i]))
+ {
+ _rl_meta_flag = 1;
+ _rl_convert_meta_chars_to_ascii = 0;
+ _rl_output_meta_chars = 1;
+ break;
+ }
+ free (t);
+ return (legal_lang_values[i] ? 1 : 0);
+
+#endif /* !HAVE_SETLOCALE */
+}
+
+#if !defined (HAVE_SETLOCALE)
+static char *
+normalize_codeset (codeset)
+ char *codeset;
+{
+ size_t namelen, i;
+ int len, all_digits;
+ char *wp, *retval;
+
+ codeset = find_codeset (codeset, &namelen);
+
+ if (codeset == 0)
+ return (codeset);
+
+ all_digits = 1;
+ for (len = 0, i = 0; i < namelen; i++)
+ {
+ if (ISALNUM ((unsigned char)codeset[i]))
+ {
+ len++;
+ all_digits &= _rl_digit_p (codeset[i]);
+ }
+ }
+
+ retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
+ if (retval == 0)
+ return ((char *)0);
+
+ wp = retval;
+ /* Add `iso' to beginning of an all-digit codeset */
+ if (all_digits)
+ {
+ *wp++ = 'i';
+ *wp++ = 's';
+ *wp++ = 'o';
+ }
+
+ for (i = 0; i < namelen; i++)
+ if (ISALPHA ((unsigned char)codeset[i]))
+ *wp++ = _rl_to_lower (codeset[i]);
+ else if (_rl_digit_p (codeset[i]))
+ *wp++ = codeset[i];
+ *wp = '\0';
+
+ return retval;
+}
+
+/* Isolate codeset portion of locale specification. */
+static char *
+find_codeset (name, lenp)
+ char *name;
+ size_t *lenp;
+{
+ char *cp, *language, *result;
+
+ cp = language = name;
+ result = (char *)0;
+
+ while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
+ cp++;
+
+ /* This does not make sense: language has to be specified. As
+ an exception we allow the variable to contain only the codeset
+ name. Perhaps there are funny codeset names. */
+ if (language == cp)
+ {
+ *lenp = strlen (language);
+ result = language;
+ }
+ else
+ {
+ /* Next is the territory. */
+ if (*cp == '_')
+ do
+ ++cp;
+ while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
+
+ /* Now, finally, is the codeset. */
+ result = cp;
+ if (*cp == '.')
+ do
+ ++cp;
+ while (*cp && *cp != '@');
+
+ if (cp - result > 2)
+ {
+ result++;
+ *lenp = cp - result;
+ }
+ else
+ {
+ *lenp = strlen (language);
+ result = language;
+ }
+ }
+
+ return result;
+}
+#endif /* !HAVE_SETLOCALE */
diff --git a/cmd-line-utils/readline/parens.c b/cmd-line-utils/readline/parens.c
new file mode 100644
index 00000000000..54ef1f3695f
--- /dev/null
+++ b/cmd-line-utils/readline/parens.c
@@ -0,0 +1,179 @@
+/* parens.c -- Implementation of matching parentheses feature. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#include "rlconf.h"
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (FD_SET) && !defined (HAVE_SELECT)
+# define HAVE_SELECT
+#endif
+
+#if defined (HAVE_SELECT)
+# include <sys/time.h>
+#endif /* HAVE_SELECT */
+#if defined (HAVE_SYS_SELECT_H)
+# include <sys/select.h>
+#endif
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else /* !HAVE_STRING_H */
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+#include "readline.h"
+#include "rlprivate.h"
+
+static int find_matching_open PARAMS((char *, int, int));
+
+/* Non-zero means try to blink the matching open parenthesis when the
+ close parenthesis is inserted. */
+#if defined (HAVE_SELECT)
+int rl_blink_matching_paren = 1;
+#else /* !HAVE_SELECT */
+int rl_blink_matching_paren = 0;
+#endif /* !HAVE_SELECT */
+
+static int _paren_blink_usec = 500000;
+
+/* Change emacs_standard_keymap to have bindings for paren matching when
+ ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */
+void
+_rl_enable_paren_matching (on_or_off)
+ int on_or_off;
+{
+ if (on_or_off)
+ { /* ([{ */
+ rl_bind_key_in_map (')', rl_insert_close, emacs_standard_keymap);
+ rl_bind_key_in_map (']', rl_insert_close, emacs_standard_keymap);
+ rl_bind_key_in_map ('}', rl_insert_close, emacs_standard_keymap);
+ }
+ else
+ { /* ([{ */
+ rl_bind_key_in_map (')', rl_insert, emacs_standard_keymap);
+ rl_bind_key_in_map (']', rl_insert, emacs_standard_keymap);
+ rl_bind_key_in_map ('}', rl_insert, emacs_standard_keymap);
+ }
+}
+
+int
+rl_set_paren_blink_timeout (u)
+ int u;
+{
+ int o;
+
+ o = _paren_blink_usec;
+ if (u > 0)
+ _paren_blink_usec = u;
+ return (o);
+}
+
+int
+rl_insert_close (count, invoking_key)
+ int count, invoking_key;
+{
+ if (rl_explicit_arg || !rl_blink_matching_paren)
+ _rl_insert_char (count, invoking_key);
+ else
+ {
+#if defined (HAVE_SELECT)
+ int orig_point, match_point, ready;
+ struct timeval timer;
+ fd_set readfds;
+
+ _rl_insert_char (1, invoking_key);
+ (*rl_redisplay_function) ();
+ match_point =
+ find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
+
+ /* Emacs might message or ring the bell here, but I don't. */
+ if (match_point < 0)
+ return -1;
+
+ FD_ZERO (&readfds);
+ FD_SET (fileno (rl_instream), &readfds);
+ timer.tv_sec = 0;
+ timer.tv_usec = _paren_blink_usec;
+
+ orig_point = rl_point;
+ rl_point = match_point;
+ (*rl_redisplay_function) ();
+ ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
+ rl_point = orig_point;
+#else /* !HAVE_SELECT */
+ _rl_insert_char (count, invoking_key);
+#endif /* !HAVE_SELECT */
+ }
+ return 0;
+}
+
+static int
+find_matching_open (string, from, closer)
+ char *string;
+ int from, closer;
+{
+ register int i;
+ int opener, level, delimiter;
+
+ switch (closer)
+ {
+ case ']': opener = '['; break;
+ case '}': opener = '{'; break;
+ case ')': opener = '('; break;
+ default:
+ return (-1);
+ }
+
+ level = 1; /* The closer passed in counts as 1. */
+ delimiter = 0; /* Delimited state unknown. */
+
+ for (i = from; i > -1; i--)
+ {
+ if (delimiter && (string[i] == delimiter))
+ delimiter = 0;
+ else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i]))
+ delimiter = string[i];
+ else if (!delimiter && (string[i] == closer))
+ level++;
+ else if (!delimiter && (string[i] == opener))
+ level--;
+
+ if (!level)
+ break;
+ }
+ return (i);
+}
diff --git a/cmd-line-utils/readline/posixdir.h b/cmd-line-utils/readline/posixdir.h
new file mode 100644
index 00000000000..505e27954f1
--- /dev/null
+++ b/cmd-line-utils/readline/posixdir.h
@@ -0,0 +1,57 @@
+/* posixdir.h -- Posix directory reading includes and defines. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/* This file should be included instead of <dirent.h> or <sys/dir.h>. */
+
+#if !defined (_POSIXDIR_H_)
+#define _POSIXDIR_H_
+
+#if defined (HAVE_DIRENT_H)
+# include <dirent.h>
+# define D_NAMLEN(d) (strlen ((d)->d_name))
+#else
+# if defined (HAVE_SYS_NDIR_H)
+# include <sys/ndir.h>
+# endif
+# if defined (HAVE_SYS_DIR_H)
+# include <sys/dir.h>
+# endif
+# if defined (HAVE_NDIR_H)
+# include <ndir.h>
+# endif
+# if !defined (dirent)
+# define dirent direct
+# endif /* !dirent */
+# define D_NAMLEN(d) ((d)->d_namlen)
+#endif /* !HAVE_DIRENT_H */
+
+#if defined (STRUCT_DIRENT_HAS_D_INO) && !defined (STRUCT_DIRENT_HAS_D_FILENO)
+# define d_fileno d_ino
+#endif
+
+#if defined (_POSIX_SOURCE) && (!defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO))
+/* Posix does not require that the d_ino field be present, and some
+ systems do not provide it. */
+# define REAL_DIR_ENTRY(dp) 1
+#else
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* _POSIX_SOURCE */
+
+#endif /* !_POSIXDIR_H_ */
diff --git a/cmd-line-utils/readline/posixjmp.h b/cmd-line-utils/readline/posixjmp.h
new file mode 100644
index 00000000000..b52aa00332b
--- /dev/null
+++ b/cmd-line-utils/readline/posixjmp.h
@@ -0,0 +1,40 @@
+/* posixjmp.h -- wrapper for setjmp.h with changes for POSIX systems. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#ifndef _POSIXJMP_H_
+#define _POSIXJMP_H_
+
+#include <setjmp.h>
+
+/* This *must* be included *after* config.h */
+
+#if defined (HAVE_POSIX_SIGSETJMP)
+# define procenv_t sigjmp_buf
+# if !defined (__OPENNT)
+# undef setjmp
+# define setjmp(x) sigsetjmp((x), 1)
+# undef longjmp
+# define longjmp(x, n) siglongjmp((x), (n))
+# endif /* !__OPENNT */
+#else
+# define procenv_t jmp_buf
+#endif
+
+#endif /* _POSIXJMP_H_ */
diff --git a/cmd-line-utils/readline/posixstat.h b/cmd-line-utils/readline/posixstat.h
new file mode 100644
index 00000000000..c93b52887e9
--- /dev/null
+++ b/cmd-line-utils/readline/posixstat.h
@@ -0,0 +1,142 @@
+/* posixstat.h -- Posix stat(2) definitions for systems that
+ don't have them. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/* This file should be included instead of <sys/stat.h>.
+ It relies on the local sys/stat.h to work though. */
+#if !defined (_POSIXSTAT_H_)
+#define _POSIXSTAT_H_
+
+#include <sys/stat.h>
+
+#if defined (STAT_MACROS_BROKEN)
+# undef S_ISBLK
+# undef S_ISCHR
+# undef S_ISDIR
+# undef S_ISFIFO
+# undef S_ISREG
+# undef S_ISLNK
+#endif /* STAT_MACROS_BROKEN */
+
+/* These are guaranteed to work only on isc386 */
+#if !defined (S_IFDIR) && !defined (S_ISDIR)
+# define S_IFDIR 0040000
+#endif /* !S_IFDIR && !S_ISDIR */
+#if !defined (S_IFMT)
+# define S_IFMT 0170000
+#endif /* !S_IFMT */
+
+/* Posix 1003.1 5.6.1.1 <sys/stat.h> file types */
+
+/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but
+ do not provide the S_IS* macros that Posix requires. */
+
+#if defined (_S_IFMT) && !defined (S_IFMT)
+#define S_IFMT _S_IFMT
+#endif
+#if defined (_S_IFIFO) && !defined (S_IFIFO)
+#define S_IFIFO _S_IFIFO
+#endif
+#if defined (_S_IFCHR) && !defined (S_IFCHR)
+#define S_IFCHR _S_IFCHR
+#endif
+#if defined (_S_IFDIR) && !defined (S_IFDIR)
+#define S_IFDIR _S_IFDIR
+#endif
+#if defined (_S_IFBLK) && !defined (S_IFBLK)
+#define S_IFBLK _S_IFBLK
+#endif
+#if defined (_S_IFREG) && !defined (S_IFREG)
+#define S_IFREG _S_IFREG
+#endif
+#if defined (_S_IFLNK) && !defined (S_IFLNK)
+#define S_IFLNK _S_IFLNK
+#endif
+#if defined (_S_IFSOCK) && !defined (S_IFSOCK)
+#define S_IFSOCK _S_IFSOCK
+#endif
+
+/* Test for each symbol individually and define the ones necessary (some
+ systems claiming Posix compatibility define some but not all). */
+
+#if defined (S_IFBLK) && !defined (S_ISBLK)
+#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */
+#endif
+
+#if defined (S_IFCHR) && !defined (S_ISCHR)
+#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */
+#endif
+
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */
+#endif
+
+#if defined (S_IFREG) && !defined (S_ISREG)
+#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */
+#endif
+
+#if defined (S_IFIFO) && !defined (S_ISFIFO)
+#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */
+#endif
+
+#if defined (S_IFLNK) && !defined (S_ISLNK)
+#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */
+#endif
+
+#if defined (S_IFSOCK) && !defined (S_ISSOCK)
+#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */
+#endif
+
+/*
+ * POSIX 1003.1 5.6.1.2 <sys/stat.h> File Modes
+ */
+
+#if !defined (S_IRWXU)
+# if !defined (S_IREAD)
+# define S_IREAD 00400
+# define S_IWRITE 00200
+# define S_IEXEC 00100
+# endif /* S_IREAD */
+
+# if !defined (S_IRUSR)
+# define S_IRUSR S_IREAD /* read, owner */
+# define S_IWUSR S_IWRITE /* write, owner */
+# define S_IXUSR S_IEXEC /* execute, owner */
+
+# define S_IRGRP (S_IREAD >> 3) /* read, group */
+# define S_IWGRP (S_IWRITE >> 3) /* write, group */
+# define S_IXGRP (S_IEXEC >> 3) /* execute, group */
+
+# define S_IROTH (S_IREAD >> 6) /* read, other */
+# define S_IWOTH (S_IWRITE >> 6) /* write, other */
+# define S_IXOTH (S_IEXEC >> 6) /* execute, other */
+# endif /* !S_IRUSR */
+
+# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#endif /* !S_IRWXU */
+
+/* These are non-standard, but are used in builtins.c$symbolic_umask() */
+#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
+#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
+#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+
+#endif /* _POSIXSTAT_H_ */
diff --git a/cmd-line-utils/readline/readline.c b/cmd-line-utils/readline/readline.c
new file mode 100644
index 00000000000..28801f19dfc
--- /dev/null
+++ b/cmd-line-utils/readline/readline.c
@@ -0,0 +1,973 @@
+/* readline.c -- a general facility for reading lines of input
+ with emacs style editing and completion. */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include "posixstat.h"
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+# include <locale.h>
+#endif
+
+#include <stdio.h>
+#include "posixjmp.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+# define INCL_DOSPROCESS
+# include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#ifndef RL_LIBRARY_VERSION
+# define RL_LIBRARY_VERSION "4.3"
+#endif
+
+#ifndef RL_READLINE_VERSION
+# define RL_READLINE_VERSION 0x0403
+#endif
+
+extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
+
+/* Forward declarations used in this file. */
+static char *readline_internal PARAMS((void));
+static void readline_initialize_everything PARAMS((void));
+
+static void bind_arrow_keys_internal PARAMS((Keymap));
+static void bind_arrow_keys PARAMS((void));
+
+static void readline_default_bindings PARAMS((void));
+
+/* **************************************************************** */
+/* */
+/* Line editing input utility */
+/* */
+/* **************************************************************** */
+
+const char *rl_library_version = RL_LIBRARY_VERSION;
+
+int rl_readline_version = RL_READLINE_VERSION;
+
+/* True if this is `real' readline as opposed to some stub substitute. */
+int rl_gnu_readline_p = 1;
+
+/* A pointer to the keymap that is currently in use.
+ By default, it is the standard emacs keymap. */
+Keymap _rl_keymap = emacs_standard_keymap;
+
+/* The current style of editing. */
+int rl_editing_mode = emacs_mode;
+
+/* The current insert mode: input (the default) or overwrite */
+int rl_insert_mode = RL_IM_DEFAULT;
+
+/* Non-zero if we called this function from _rl_dispatch(). It's present
+ so functions can find out whether they were called from a key binding
+ or directly from an application. */
+int rl_dispatching;
+
+/* Non-zero if the previous command was a kill command. */
+int _rl_last_command_was_kill = 0;
+
+/* The current value of the numeric argument specified by the user. */
+int rl_numeric_arg = 1;
+
+/* Non-zero if an argument was typed. */
+int rl_explicit_arg = 0;
+
+/* Temporary value used while generating the argument. */
+int rl_arg_sign = 1;
+
+/* Non-zero means we have been called at least once before. */
+static int rl_initialized;
+
+#if 0
+/* If non-zero, this program is running in an EMACS buffer. */
+static int running_in_emacs;
+#endif
+
+/* Flags word encapsulating the current readline state. */
+int rl_readline_state = RL_STATE_NONE;
+
+/* The current offset in the current input line. */
+int rl_point;
+
+/* Mark in the current input line. */
+int rl_mark;
+
+/* Length of the current input line. */
+int rl_end;
+
+/* Make this non-zero to return the current input_line. */
+int rl_done;
+
+/* The last function executed by readline. */
+rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL;
+
+/* Top level environment for readline_internal (). */
+procenv_t readline_top_level;
+
+/* The streams we interact with. */
+FILE *_rl_in_stream, *_rl_out_stream;
+
+/* The names of the streams that we do input and output to. */
+FILE *rl_instream = (FILE *)NULL;
+FILE *rl_outstream = (FILE *)NULL;
+
+/* Non-zero means echo characters as they are read. Defaults to no echo;
+ set to 1 if there is a controlling terminal, we can get its attributes,
+ and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings
+ for the code that sets it. */
+int readline_echoing_p = 0;
+
+/* Current prompt. */
+char *rl_prompt = (char *)NULL;
+int rl_visible_prompt_length = 0;
+
+/* Set to non-zero by calling application if it has already printed rl_prompt
+ and does not want readline to do it the first time. */
+int rl_already_prompted = 0;
+
+/* The number of characters read in order to type this complete command. */
+int rl_key_sequence_length = 0;
+
+/* If non-zero, then this is the address of a function to call just
+ before readline_internal_setup () prints the first prompt. */
+rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL;
+
+/* If non-zero, this is the address of a function to call just before
+ readline_internal_setup () returns and readline_internal starts
+ reading input characters. */
+rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL;
+
+/* What we use internally. You should always refer to RL_LINE_BUFFER. */
+static char *the_line;
+
+/* The character that can generate an EOF. Really read from
+ the terminal driver... just defaulted here. */
+int _rl_eof_char = CTRL ('D');
+
+/* Non-zero makes this the next keystroke to read. */
+int rl_pending_input = 0;
+
+/* Pointer to a useful terminal name. */
+const char *rl_terminal_name = (const char *)NULL;
+
+/* Non-zero means to always use horizontal scrolling in line display. */
+int _rl_horizontal_scroll_mode = 0;
+
+/* Non-zero means to display an asterisk at the starts of history lines
+ which have been modified. */
+int _rl_mark_modified_lines = 0;
+
+/* The style of `bell' notification preferred. This can be set to NO_BELL,
+ AUDIBLE_BELL, or VISIBLE_BELL. */
+int _rl_bell_preference = AUDIBLE_BELL;
+
+/* String inserted into the line by rl_insert_comment (). */
+char *_rl_comment_begin;
+
+/* Keymap holding the function currently being executed. */
+Keymap rl_executing_keymap;
+
+/* Non-zero means to erase entire line, including prompt, on empty input lines. */
+int rl_erase_empty_line = 0;
+
+/* Non-zero means to read only this many characters rather than up to a
+ character bound to accept-line. */
+int rl_num_chars_to_read;
+
+/* Line buffer and maintenence. */
+char *rl_line_buffer = (char *)NULL;
+int rl_line_buffer_len = 0;
+
+/* Forward declarations used by the display, termcap, and history code. */
+
+/* **************************************************************** */
+/* */
+/* `Forward' declarations */
+/* */
+/* **************************************************************** */
+
+/* Non-zero means do not parse any lines other than comments and
+ parser directives. */
+unsigned char _rl_parsing_conditionalized_out = 0;
+
+/* Non-zero means to convert characters with the meta bit set to
+ escape-prefixed characters so we can indirect through
+ emacs_meta_keymap or vi_escape_keymap. */
+int _rl_convert_meta_chars_to_ascii = 1;
+
+/* Non-zero means to output characters with the meta bit set directly
+ rather than as a meta-prefixed escape sequence. */
+int _rl_output_meta_chars = 0;
+
+/* **************************************************************** */
+/* */
+/* Top Level Functions */
+/* */
+/* **************************************************************** */
+
+/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
+int _rl_meta_flag = 0; /* Forward declaration */
+
+/* Set up the prompt and expand it. Called from readline() and
+ rl_callback_handler_install (). */
+int
+rl_set_prompt (prompt)
+ const char *prompt;
+{
+ FREE (rl_prompt);
+ rl_prompt = prompt ? savestring (prompt) : (char *)NULL;
+
+ rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+ return 0;
+}
+
+/* Read a line of input. Prompt with PROMPT. An empty PROMPT means
+ none. A return value of NULL means that EOF was encountered. */
+char *
+readline (prompt)
+ const char *prompt;
+{
+ char *value;
+
+ /* If we are at EOF return a NULL string. */
+ if (rl_pending_input == EOF)
+ {
+ rl_clear_pending_input ();
+ return ((char *)NULL);
+ }
+
+ rl_set_prompt (prompt);
+
+ rl_initialize ();
+ (*rl_prep_term_function) (_rl_meta_flag);
+
+#if defined (HANDLE_SIGNALS)
+ rl_set_signals ();
+#endif
+
+ value = readline_internal ();
+ (*rl_deprep_term_function) ();
+
+#if defined (HANDLE_SIGNALS)
+ rl_clear_signals ();
+#endif
+
+ return (value);
+}
+
+#if defined (READLINE_CALLBACKS)
+# define STATIC_CALLBACK
+#else
+# define STATIC_CALLBACK static
+#endif
+
+STATIC_CALLBACK void
+readline_internal_setup ()
+{
+ char *nprompt;
+
+ _rl_in_stream = rl_instream;
+ _rl_out_stream = rl_outstream;
+
+ if (rl_startup_hook)
+ (*rl_startup_hook) ();
+
+ /* If we're not echoing, we still want to at least print a prompt, because
+ rl_redisplay will not do it for us. If the calling application has a
+ custom redisplay function, though, let that function handle it. */
+ if (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
+ {
+ if (rl_prompt && rl_already_prompted == 0)
+ {
+ nprompt = _rl_strip_prompt (rl_prompt);
+ fprintf (_rl_out_stream, "%s", nprompt);
+ fflush (_rl_out_stream);
+ free (nprompt);
+ }
+ }
+ else
+ {
+ if (rl_prompt && rl_already_prompted)
+ rl_on_new_line_with_prompt ();
+ else
+ rl_on_new_line ();
+ (*rl_redisplay_function) ();
+ }
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ rl_vi_insertion_mode (1, 0);
+#endif /* VI_MODE */
+
+ if (rl_pre_input_hook)
+ (*rl_pre_input_hook) ();
+}
+
+STATIC_CALLBACK char *
+readline_internal_teardown (eof)
+ int eof;
+{
+ char *temp;
+ HIST_ENTRY *entry;
+
+ /* Restore the original of this history line, iff the line that we
+ are editing was originally in the history, AND the line has changed. */
+ entry = current_history ();
+
+ if (entry && rl_undo_list)
+ {
+ temp = savestring (the_line);
+ rl_revert_line (1, 0);
+ entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
+ _rl_free_history_entry (entry);
+
+ strcpy (the_line, temp);
+ free (temp);
+ }
+
+ /* At any rate, it is highly likely that this line has an undo list. Get
+ rid of it now. */
+ if (rl_undo_list)
+ rl_free_undo_list ();
+
+ /* Restore normal cursor, if available. */
+ _rl_set_insert_mode (RL_IM_INSERT, 0);
+
+ return (eof ? (char *)NULL : savestring (the_line));
+}
+
+STATIC_CALLBACK int
+#if defined (READLINE_CALLBACKS)
+readline_internal_char ()
+#else
+readline_internal_charloop ()
+#endif
+{
+ static int lastc, eof_found;
+ int c, code, lk;
+
+ lastc = -1;
+ eof_found = 0;
+
+#if !defined (READLINE_CALLBACKS)
+ while (rl_done == 0)
+ {
+#endif
+ lk = _rl_last_command_was_kill;
+
+ code = setjmp (readline_top_level);
+
+ if (code)
+ (*rl_redisplay_function) ();
+
+ if (rl_pending_input == 0)
+ {
+ /* Then initialize the argument and number of keys read. */
+ _rl_init_argument ();
+ rl_key_sequence_length = 0;
+ }
+
+ RL_SETSTATE(RL_STATE_READCMD);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_READCMD);
+
+ /* EOF typed to a non-blank line is a <NL>. */
+ if (c == EOF && rl_end)
+ c = NEWLINE;
+
+ /* The character _rl_eof_char typed to blank line, and not as the
+ previous character is interpreted as EOF. */
+ if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
+ {
+#if defined (READLINE_CALLBACKS)
+ RL_SETSTATE(RL_STATE_DONE);
+ return (rl_done = 1);
+#else
+ eof_found = 1;
+ break;
+#endif
+ }
+
+ lastc = c;
+ _rl_dispatch ((unsigned char)c, _rl_keymap);
+
+ /* If there was no change in _rl_last_command_was_kill, then no kill
+ has taken place. Note that if input is pending we are reading
+ a prefix command, so nothing has changed yet. */
+ if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
+ _rl_last_command_was_kill = 0;
+
+#if defined (VI_MODE)
+ /* In vi mode, when you exit insert mode, the cursor moves back
+ over the previous character. We explicitly check for that here. */
+ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
+ rl_vi_check ();
+#endif /* VI_MODE */
+
+ if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read)
+ {
+ (*rl_redisplay_function) ();
+ rl_newline (1, '\n');
+ }
+
+ if (rl_done == 0)
+ (*rl_redisplay_function) ();
+
+ /* If the application writer has told us to erase the entire line if
+ the only character typed was something bound to rl_newline, do so. */
+ if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline &&
+ rl_point == 0 && rl_end == 0)
+ _rl_erase_entire_line ();
+
+#if defined (READLINE_CALLBACKS)
+ return 0;
+#else
+ }
+
+ return (eof_found);
+#endif
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+readline_internal_charloop ()
+{
+ int eof = 1;
+
+ while (rl_done == 0)
+ eof = readline_internal_char ();
+ return (eof);
+}
+#endif /* READLINE_CALLBACKS */
+
+/* Read a line of input from the global rl_instream, doing output on
+ the global rl_outstream.
+ If rl_prompt is non-null, then that is our prompt. */
+static char *
+readline_internal ()
+{
+ int eof;
+
+ readline_internal_setup ();
+ eof = readline_internal_charloop ();
+ return (readline_internal_teardown (eof));
+}
+
+void
+_rl_init_line_state ()
+{
+ rl_point = rl_end = rl_mark = 0;
+ the_line = rl_line_buffer;
+ the_line[0] = 0;
+}
+
+void
+_rl_set_the_line ()
+{
+ the_line = rl_line_buffer;
+}
+
+/* Do the command associated with KEY in MAP.
+ If the associated command is really a keymap, then read
+ another key, and dispatch into that map. */
+int
+_rl_dispatch (key, map)
+ register int key;
+ Keymap map;
+{
+ return _rl_dispatch_subseq (key, map, 0);
+}
+
+int
+_rl_dispatch_subseq (key, map, got_subseq)
+ register int key;
+ Keymap map;
+ int got_subseq;
+{
+ int r, newkey;
+ char *macro;
+ rl_command_func_t *func;
+
+ if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+ {
+ if (map[ESC].type == ISKMAP)
+ {
+ if (RL_ISSTATE (RL_STATE_MACRODEF))
+ _rl_add_macro_char (ESC);
+ map = FUNCTION_TO_KEYMAP (map, ESC);
+ key = UNMETA (key);
+ rl_key_sequence_length += 2;
+ return (_rl_dispatch (key, map));
+ }
+ else
+ rl_ding ();
+ return 0;
+ }
+
+ if (RL_ISSTATE (RL_STATE_MACRODEF))
+ _rl_add_macro_char (key);
+
+ r = 0;
+ switch (map[key].type)
+ {
+ case ISFUNC:
+ func = map[key].function;
+ if (func)
+ {
+ /* Special case rl_do_lowercase_version (). */
+ if (func == rl_do_lowercase_version)
+ return (_rl_dispatch (_rl_to_lower (key), map));
+
+ rl_executing_keymap = map;
+
+#if 0
+ _rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available ();
+#endif
+
+ rl_dispatching = 1;
+ RL_SETSTATE(RL_STATE_DISPATCHING);
+ r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
+ RL_UNSETSTATE(RL_STATE_DISPATCHING);
+ rl_dispatching = 0;
+
+ /* If we have input pending, then the last command was a prefix
+ command. Don't change the state of rl_last_func. Otherwise,
+ remember the last command executed in this variable. */
+ if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
+ rl_last_func = map[key].function;
+ }
+ else if (map[ANYOTHERKEY].function)
+ {
+ /* OK, there's no function bound in this map, but there is a
+ shadow function that was overridden when the current keymap
+ was created. Return -2 to note that. */
+ _rl_unget_char (key);
+ return -2;
+ }
+ else if (got_subseq)
+ {
+ /* Return -1 to note that we're in a subsequence, but we don't
+ have a matching key, nor was one overridden. This means
+ we need to back up the recursion chain and find the last
+ subsequence that is bound to a function. */
+ _rl_unget_char (key);
+ return -1;
+ }
+ else
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+ break;
+
+ case ISKMAP:
+ if (map[key].function != 0)
+ {
+#if defined (VI_MODE)
+ /* The only way this test will be true is if a subsequence has been
+ bound starting with ESC, generally the arrow keys. What we do is
+ check whether there's input in the queue, which there generally
+ will be if an arrow key has been pressed, and, if there's not,
+ just dispatch to (what we assume is) rl_vi_movement_mode right
+ away. This is essentially an input test with a zero timeout. */
+ if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
+ && _rl_input_queued (0) == 0)
+ return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
+#endif
+
+ rl_key_sequence_length++;
+
+ if (key == ESC)
+ RL_SETSTATE(RL_STATE_METANEXT);
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ newkey = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ if (key == ESC)
+ RL_UNSETSTATE(RL_STATE_METANEXT);
+
+ if (newkey < 0)
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+
+ r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function);
+
+ if (r == -2)
+ /* We didn't match anything, and the keymap we're indexed into
+ shadowed a function previously bound to that prefix. Call
+ the function. The recursive call to _rl_dispatch_subseq has
+ already taken care of pushing any necessary input back onto
+ the input queue with _rl_unget_char. */
+ r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
+ else if (r && map[ANYOTHERKEY].function)
+ {
+ /* We didn't match (r is probably -1), so return something to
+ tell the caller that it should try ANYOTHERKEY for an
+ overridden function. */
+ _rl_unget_char (key);
+ return -2;
+ }
+ else if (r && got_subseq)
+ {
+ /* OK, back up the chain. */
+ _rl_unget_char (key);
+ return -1;
+ }
+ }
+ else
+ {
+ _rl_abort_internal ();
+ return -1;
+ }
+ break;
+
+ case ISMACR:
+ if (map[key].function != 0)
+ {
+ macro = savestring ((char *)map[key].function);
+ _rl_with_macro_input (macro);
+ return 0;
+ }
+ break;
+ }
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
+ _rl_vi_textmod_command (key))
+ _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
+#endif
+ return (r);
+}
+
+/* **************************************************************** */
+/* */
+/* Initializations */
+/* */
+/* **************************************************************** */
+
+/* Initialize readline (and terminal if not already). */
+int
+rl_initialize ()
+{
+ /* If we have never been called before, initialize the
+ terminal and data structures. */
+ if (!rl_initialized)
+ {
+ RL_SETSTATE(RL_STATE_INITIALIZING);
+ readline_initialize_everything ();
+ RL_UNSETSTATE(RL_STATE_INITIALIZING);
+ rl_initialized++;
+ RL_SETSTATE(RL_STATE_INITIALIZED);
+ }
+
+ /* Initalize the current line information. */
+ _rl_init_line_state ();
+
+ /* We aren't done yet. We haven't even gotten started yet! */
+ rl_done = 0;
+ RL_UNSETSTATE(RL_STATE_DONE);
+
+ /* Tell the history routines what is going on. */
+ _rl_start_using_history ();
+
+ /* Make the display buffer match the state of the line. */
+ rl_reset_line_state ();
+
+ /* No such function typed yet. */
+ rl_last_func = (rl_command_func_t *)NULL;
+
+ /* Parsing of key-bindings begins in an enabled state. */
+ _rl_parsing_conditionalized_out = 0;
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ _rl_vi_initialize_line ();
+#endif
+
+ /* Each line starts in insert mode (the default). */
+ _rl_set_insert_mode (RL_IM_DEFAULT, 1);
+
+ return 0;
+}
+
+#if 0
+#if defined (__EMX__)
+static void
+_emx_build_environ ()
+{
+ TIB *tibp;
+ PIB *pibp;
+ char *t, **tp;
+ int c;
+
+ DosGetInfoBlocks (&tibp, &pibp);
+ t = pibp->pib_pchenv;
+ for (c = 1; *t; c++)
+ t += strlen (t) + 1;
+ tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *));
+ t = pibp->pib_pchenv;
+ while (*t)
+ {
+ *tp++ = t;
+ t += strlen (t) + 1;
+ }
+ *tp = 0;
+}
+#endif /* __EMX__ */
+#endif
+
+/* Initialize the entire state of the world. */
+static void
+readline_initialize_everything ()
+{
+#if 0
+#if defined (__EMX__)
+ if (environ == 0)
+ _emx_build_environ ();
+#endif
+#endif
+
+#if 0
+ /* Find out if we are running in Emacs -- UNUSED. */
+ running_in_emacs = sh_get_env_value ("EMACS") != (char *)0;
+#endif
+
+ /* Set up input and output if they are not already set up. */
+ if (!rl_instream)
+ rl_instream = stdin;
+
+ if (!rl_outstream)
+ rl_outstream = stdout;
+
+ /* Bind _rl_in_stream and _rl_out_stream immediately. These values
+ may change, but they may also be used before readline_internal ()
+ is called. */
+ _rl_in_stream = rl_instream;
+ _rl_out_stream = rl_outstream;
+
+ /* Allocate data structures. */
+ if (rl_line_buffer == 0)
+ rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+
+ /* Initialize the terminal interface. */
+ if (rl_terminal_name == 0)
+ rl_terminal_name = sh_get_env_value ("TERM");
+ _rl_init_terminal_io (rl_terminal_name);
+
+ /* Bind tty characters to readline functions. */
+ readline_default_bindings ();
+
+ /* Initialize the function names. */
+ rl_initialize_funmap ();
+
+ /* Decide whether we should automatically go into eight-bit mode. */
+ _rl_init_eightbit ();
+
+ /* Read in the init file. */
+ rl_read_init_file ((char *)NULL);
+
+ /* XXX */
+ if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
+ {
+ _rl_screenwidth--;
+ _rl_screenchars -= _rl_screenheight;
+ }
+
+ /* Override the effect of any `set keymap' assignments in the
+ inputrc file. */
+ rl_set_keymap_from_edit_mode ();
+
+ /* Try to bind a common arrow key prefix, if not already bound. */
+ bind_arrow_keys ();
+
+ /* Enable the meta key, if this terminal has one. */
+ if (_rl_enable_meta)
+ _rl_enable_meta_key ();
+
+ /* If the completion parser's default word break characters haven't
+ been set yet, then do so now. */
+ if (rl_completer_word_break_characters == (char *)NULL)
+ rl_completer_word_break_characters = rl_basic_word_break_characters;
+}
+
+/* If this system allows us to look at the values of the regular
+ input editing characters, then bind them to their readline
+ equivalents, iff the characters are not bound to keymaps. */
+static void
+readline_default_bindings ()
+{
+ rl_tty_set_default_bindings (_rl_keymap);
+}
+
+/* Bind some common arrow key sequences in MAP. */
+static void
+bind_arrow_keys_internal (map)
+ Keymap map;
+{
+ Keymap xkeymap;
+
+ xkeymap = _rl_keymap;
+ _rl_keymap = map;
+
+#if defined (__MSDOS__)
+ _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
+ _rl_bind_if_unbound ("\033[0B", rl_backward_char);
+ _rl_bind_if_unbound ("\033[0C", rl_forward_char);
+ _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
+#endif
+
+ _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
+ _rl_bind_if_unbound ("\033[B", rl_get_next_history);
+ _rl_bind_if_unbound ("\033[C", rl_forward_char);
+ _rl_bind_if_unbound ("\033[D", rl_backward_char);
+ _rl_bind_if_unbound ("\033[H", rl_beg_of_line);
+ _rl_bind_if_unbound ("\033[F", rl_end_of_line);
+
+ _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
+ _rl_bind_if_unbound ("\033OB", rl_get_next_history);
+ _rl_bind_if_unbound ("\033OC", rl_forward_char);
+ _rl_bind_if_unbound ("\033OD", rl_backward_char);
+ _rl_bind_if_unbound ("\033OH", rl_beg_of_line);
+ _rl_bind_if_unbound ("\033OF", rl_end_of_line);
+
+ _rl_keymap = xkeymap;
+}
+
+/* Try and bind the common arrow key prefixes after giving termcap and
+ the inputrc file a chance to bind them and create `real' keymaps
+ for the arrow key prefix. */
+static void
+bind_arrow_keys ()
+{
+ bind_arrow_keys_internal (emacs_standard_keymap);
+
+#if defined (VI_MODE)
+ bind_arrow_keys_internal (vi_movement_keymap);
+ bind_arrow_keys_internal (vi_insertion_keymap);
+#endif
+}
+
+/* **************************************************************** */
+/* */
+/* Saving and Restoring Readline's state */
+/* */
+/* **************************************************************** */
+
+int
+rl_save_state (sp)
+ struct readline_state *sp;
+{
+ if (sp == 0)
+ return -1;
+
+ sp->point = rl_point;
+ sp->end = rl_end;
+ sp->mark = rl_mark;
+ sp->buffer = rl_line_buffer;
+ sp->buflen = rl_line_buffer_len;
+ sp->ul = rl_undo_list;
+ sp->prompt = rl_prompt;
+
+ sp->rlstate = rl_readline_state;
+ sp->done = rl_done;
+ sp->kmap = _rl_keymap;
+
+ sp->lastfunc = rl_last_func;
+ sp->insmode = rl_insert_mode;
+ sp->edmode = rl_editing_mode;
+ sp->kseqlen = rl_key_sequence_length;
+ sp->inf = rl_instream;
+ sp->outf = rl_outstream;
+ sp->pendingin = rl_pending_input;
+ sp->macro = rl_executing_macro;
+
+ sp->catchsigs = rl_catch_signals;
+ sp->catchsigwinch = rl_catch_sigwinch;
+
+ return (0);
+}
+
+int
+rl_restore_state (sp)
+ struct readline_state *sp;
+{
+ if (sp == 0)
+ return -1;
+
+ rl_point = sp->point;
+ rl_end = sp->end;
+ rl_mark = sp->mark;
+ the_line = rl_line_buffer = sp->buffer;
+ rl_line_buffer_len = sp->buflen;
+ rl_undo_list = sp->ul;
+ rl_prompt = sp->prompt;
+
+ rl_readline_state = sp->rlstate;
+ rl_done = sp->done;
+ _rl_keymap = sp->kmap;
+
+ rl_last_func = sp->lastfunc;
+ rl_insert_mode = sp->insmode;
+ rl_editing_mode = sp->edmode;
+ rl_key_sequence_length = sp->kseqlen;
+ rl_instream = sp->inf;
+ rl_outstream = sp->outf;
+ rl_pending_input = sp->pendingin;
+ rl_executing_macro = sp->macro;
+
+ rl_catch_signals = sp->catchsigs;
+ rl_catch_sigwinch = sp->catchsigwinch;
+
+ return (0);
+}
diff --git a/cmd-line-utils/readline/readline.h b/cmd-line-utils/readline/readline.h
new file mode 100644
index 00000000000..9425de50aef
--- /dev/null
+++ b/cmd-line-utils/readline/readline.h
@@ -0,0 +1,799 @@
+/* Readline.h -- the names of functions callable from within readline. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_READLINE_H_)
+#define _READLINE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (READLINE_LIBRARY)
+# include "rlstdc.h"
+# include "rltypedefs.h"
+# include "keymaps.h"
+# include "tilde.h"
+#else
+# include <readline/rlstdc.h>
+# include <readline/rltypedefs.h>
+# include <readline/keymaps.h>
+# include <readline/tilde.h>
+#endif
+
+/* Hex-encoded Readline version number. */
+#define RL_READLINE_VERSION 0x0403 /* Readline 4.3 */
+#define RL_VERSION_MAJOR 4
+#define RL_VERSION_MINOR 3
+
+/* Readline data structures. */
+
+/* Maintaining the state of undo. We remember individual deletes and inserts
+ on a chain of things to do. */
+
+/* The actions that undo knows how to undo. Notice that UNDO_DELETE means
+ to insert some text, and UNDO_INSERT means to delete some text. I.e.,
+ the code tells undo what to undo, not how to undo it. */
+enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
+
+/* What an element of THE_UNDO_LIST looks like. */
+typedef struct undo_list {
+ struct undo_list *next;
+ int start, end; /* Where the change took place. */
+ char *text; /* The text to insert, if undoing a delete. */
+ enum undo_code what; /* Delete, Insert, Begin, End. */
+} UNDO_LIST;
+
+/* The current undo list for RL_LINE_BUFFER. */
+extern UNDO_LIST *rl_undo_list;
+
+/* The data structure for mapping textual names to code addresses. */
+typedef struct _funmap {
+ const char *name;
+ rl_command_func_t *function;
+} FUNMAP;
+
+extern FUNMAP **funmap;
+
+/* **************************************************************** */
+/* */
+/* Functions available to bind to key sequences */
+/* */
+/* **************************************************************** */
+
+/* Bindable commands for numeric arguments. */
+extern int rl_digit_argument PARAMS((int, int));
+extern int rl_universal_argument PARAMS((int, int));
+
+/* Bindable commands for moving the cursor. */
+extern int rl_forward_byte PARAMS((int, int));
+extern int rl_forward_char PARAMS((int, int));
+extern int rl_forward PARAMS((int, int));
+extern int rl_backward_byte PARAMS((int, int));
+extern int rl_backward_char PARAMS((int, int));
+extern int rl_backward PARAMS((int, int));
+extern int rl_beg_of_line PARAMS((int, int));
+extern int rl_end_of_line PARAMS((int, int));
+extern int rl_forward_word PARAMS((int, int));
+extern int rl_backward_word PARAMS((int, int));
+extern int rl_refresh_line PARAMS((int, int));
+extern int rl_clear_screen PARAMS((int, int));
+extern int rl_arrow_keys PARAMS((int, int));
+
+/* Bindable commands for inserting and deleting text. */
+extern int rl_insert PARAMS((int, int));
+extern int rl_quoted_insert PARAMS((int, int));
+extern int rl_tab_insert PARAMS((int, int));
+extern int rl_newline PARAMS((int, int));
+extern int rl_do_lowercase_version PARAMS((int, int));
+extern int rl_rubout PARAMS((int, int));
+extern int rl_delete PARAMS((int, int));
+extern int rl_rubout_or_delete PARAMS((int, int));
+extern int rl_delete_horizontal_space PARAMS((int, int));
+extern int rl_delete_or_show_completions PARAMS((int, int));
+extern int rl_insert_comment PARAMS((int, int));
+
+/* Bindable commands for changing case. */
+extern int rl_upcase_word PARAMS((int, int));
+extern int rl_downcase_word PARAMS((int, int));
+extern int rl_capitalize_word PARAMS((int, int));
+
+/* Bindable commands for transposing characters and words. */
+extern int rl_transpose_words PARAMS((int, int));
+extern int rl_transpose_chars PARAMS((int, int));
+
+/* Bindable commands for searching within a line. */
+extern int rl_char_search PARAMS((int, int));
+extern int rl_backward_char_search PARAMS((int, int));
+
+/* Bindable commands for readline's interface to the command history. */
+extern int rl_beginning_of_history PARAMS((int, int));
+extern int rl_end_of_history PARAMS((int, int));
+extern int rl_get_next_history PARAMS((int, int));
+extern int rl_get_previous_history PARAMS((int, int));
+
+/* Bindable commands for managing the mark and region. */
+extern int rl_set_mark PARAMS((int, int));
+extern int rl_exchange_point_and_mark PARAMS((int, int));
+
+/* Bindable commands to set the editing mode (emacs or vi). */
+extern int rl_vi_editing_mode PARAMS((int, int));
+extern int rl_emacs_editing_mode PARAMS((int, int));
+
+/* Bindable commands to change the insert mode (insert or overwrite) */
+extern int rl_overwrite_mode PARAMS((int, int));
+
+/* Bindable commands for managing key bindings. */
+extern int rl_re_read_init_file PARAMS((int, int));
+extern int rl_dump_functions PARAMS((int, int));
+extern int rl_dump_macros PARAMS((int, int));
+extern int rl_dump_variables PARAMS((int, int));
+
+/* Bindable commands for word completion. */
+extern int rl_complete PARAMS((int, int));
+extern int rl_possible_completions PARAMS((int, int));
+extern int rl_insert_completions PARAMS((int, int));
+extern int rl_menu_complete PARAMS((int, int));
+
+/* Bindable commands for killing and yanking text, and managing the kill ring. */
+extern int rl_kill_word PARAMS((int, int));
+extern int rl_backward_kill_word PARAMS((int, int));
+extern int rl_kill_line PARAMS((int, int));
+extern int rl_backward_kill_line PARAMS((int, int));
+extern int rl_kill_full_line PARAMS((int, int));
+extern int rl_unix_word_rubout PARAMS((int, int));
+extern int rl_unix_line_discard PARAMS((int, int));
+extern int rl_copy_region_to_kill PARAMS((int, int));
+extern int rl_kill_region PARAMS((int, int));
+extern int rl_copy_forward_word PARAMS((int, int));
+extern int rl_copy_backward_word PARAMS((int, int));
+extern int rl_yank PARAMS((int, int));
+extern int rl_yank_pop PARAMS((int, int));
+extern int rl_yank_nth_arg PARAMS((int, int));
+extern int rl_yank_last_arg PARAMS((int, int));
+/* Not available unless __CYGWIN__ is defined. */
+#ifdef __CYGWIN__
+extern int rl_paste_from_clipboard PARAMS((int, int));
+#endif
+
+/* Bindable commands for incremental searching. */
+extern int rl_reverse_search_history PARAMS((int, int));
+extern int rl_forward_search_history PARAMS((int, int));
+
+/* Bindable keyboard macro commands. */
+extern int rl_start_kbd_macro PARAMS((int, int));
+extern int rl_end_kbd_macro PARAMS((int, int));
+extern int rl_call_last_kbd_macro PARAMS((int, int));
+
+/* Bindable undo commands. */
+extern int rl_revert_line PARAMS((int, int));
+extern int rl_undo_command PARAMS((int, int));
+
+/* Bindable tilde expansion commands. */
+extern int rl_tilde_expand PARAMS((int, int));
+
+/* Bindable terminal control commands. */
+extern int rl_restart_output PARAMS((int, int));
+extern int rl_stop_output PARAMS((int, int));
+
+/* Miscellaneous bindable commands. */
+extern int rl_abort PARAMS((int, int));
+extern int rl_tty_status PARAMS((int, int));
+
+/* Bindable commands for incremental and non-incremental history searching. */
+extern int rl_history_search_forward PARAMS((int, int));
+extern int rl_history_search_backward PARAMS((int, int));
+extern int rl_noninc_forward_search PARAMS((int, int));
+extern int rl_noninc_reverse_search PARAMS((int, int));
+extern int rl_noninc_forward_search_again PARAMS((int, int));
+extern int rl_noninc_reverse_search_again PARAMS((int, int));
+
+/* Bindable command used when inserting a matching close character. */
+extern int rl_insert_close PARAMS((int, int));
+
+/* Not available unless READLINE_CALLBACKS is defined. */
+extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *));
+extern void rl_callback_read_char PARAMS((void));
+extern void rl_callback_handler_remove PARAMS((void));
+
+/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
+/* VI-mode bindable commands. */
+extern int rl_vi_redo PARAMS((int, int));
+extern int rl_vi_undo PARAMS((int, int));
+extern int rl_vi_yank_arg PARAMS((int, int));
+extern int rl_vi_fetch_history PARAMS((int, int));
+extern int rl_vi_search_again PARAMS((int, int));
+extern int rl_vi_search PARAMS((int, int));
+extern int rl_vi_complete PARAMS((int, int));
+extern int rl_vi_tilde_expand PARAMS((int, int));
+extern int rl_vi_prev_word PARAMS((int, int));
+extern int rl_vi_next_word PARAMS((int, int));
+extern int rl_vi_end_word PARAMS((int, int));
+extern int rl_vi_insert_beg PARAMS((int, int));
+extern int rl_vi_append_mode PARAMS((int, int));
+extern int rl_vi_append_eol PARAMS((int, int));
+extern int rl_vi_eof_maybe PARAMS((int, int));
+extern int rl_vi_insertion_mode PARAMS((int, int));
+extern int rl_vi_movement_mode PARAMS((int, int));
+extern int rl_vi_arg_digit PARAMS((int, int));
+extern int rl_vi_change_case PARAMS((int, int));
+extern int rl_vi_put PARAMS((int, int));
+extern int rl_vi_column PARAMS((int, int));
+extern int rl_vi_delete_to PARAMS((int, int));
+extern int rl_vi_change_to PARAMS((int, int));
+extern int rl_vi_yank_to PARAMS((int, int));
+extern int rl_vi_delete PARAMS((int, int));
+extern int rl_vi_back_to_indent PARAMS((int, int));
+extern int rl_vi_first_print PARAMS((int, int));
+extern int rl_vi_char_search PARAMS((int, int));
+extern int rl_vi_match PARAMS((int, int));
+extern int rl_vi_change_char PARAMS((int, int));
+extern int rl_vi_subst PARAMS((int, int));
+extern int rl_vi_overstrike PARAMS((int, int));
+extern int rl_vi_overstrike_delete PARAMS((int, int));
+extern int rl_vi_replace PARAMS((int, int));
+extern int rl_vi_set_mark PARAMS((int, int));
+extern int rl_vi_goto_mark PARAMS((int, int));
+
+/* VI-mode utility functions. */
+extern int rl_vi_check PARAMS((void));
+extern int rl_vi_domove PARAMS((int, int *));
+extern int rl_vi_bracktype PARAMS((int));
+
+/* VI-mode pseudo-bindable commands, used as utility functions. */
+extern int rl_vi_fWord PARAMS((int, int));
+extern int rl_vi_bWord PARAMS((int, int));
+extern int rl_vi_eWord PARAMS((int, int));
+extern int rl_vi_fword PARAMS((int, int));
+extern int rl_vi_bword PARAMS((int, int));
+extern int rl_vi_eword PARAMS((int, int));
+
+/* **************************************************************** */
+/* */
+/* Well Published Functions */
+/* */
+/* **************************************************************** */
+
+/* Readline functions. */
+/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */
+extern char *readline PARAMS((const char *));
+
+extern int rl_set_prompt PARAMS((const char *));
+extern int rl_expand_prompt PARAMS((char *));
+
+extern int rl_initialize PARAMS((void));
+
+/* Undocumented; unused by readline */
+extern int rl_discard_argument PARAMS((void));
+
+/* Utility functions to bind keys to readline commands. */
+extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int));
+extern int rl_bind_key PARAMS((int, rl_command_func_t *));
+extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
+extern int rl_unbind_key PARAMS((int));
+extern int rl_unbind_key_in_map PARAMS((int, Keymap));
+extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap));
+extern int rl_unbind_command_in_map PARAMS((const char *, Keymap));
+extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
+extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap));
+extern int rl_variable_bind PARAMS((const char *, const char *));
+
+/* Backwards compatibility, use rl_generic_bind instead. */
+extern int rl_macro_bind PARAMS((const char *, const char *, Keymap));
+
+/* Undocumented in the texinfo manual; not really useful to programs. */
+extern int rl_translate_keyseq PARAMS((const char *, char *, int *));
+extern char *rl_untranslate_keyseq PARAMS((int));
+
+extern rl_command_func_t *rl_named_function PARAMS((const char *));
+extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *));
+
+extern void rl_list_funmap_names PARAMS((void));
+extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap));
+extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *));
+
+extern void rl_function_dumper PARAMS((int));
+extern void rl_macro_dumper PARAMS((int));
+extern void rl_variable_dumper PARAMS((int));
+
+extern int rl_read_init_file PARAMS((const char *));
+extern int rl_parse_and_bind PARAMS((char *));
+
+/* Functions for manipulating keymaps. */
+extern Keymap rl_make_bare_keymap PARAMS((void));
+extern Keymap rl_copy_keymap PARAMS((Keymap));
+extern Keymap rl_make_keymap PARAMS((void));
+extern void rl_discard_keymap PARAMS((Keymap));
+
+extern Keymap rl_get_keymap_by_name PARAMS((const char *));
+extern char *rl_get_keymap_name PARAMS((Keymap));
+extern void rl_set_keymap PARAMS((Keymap));
+extern Keymap rl_get_keymap PARAMS((void));
+/* Undocumented; used internally only. */
+extern void rl_set_keymap_from_edit_mode PARAMS((void));
+extern const char *rl_get_keymap_name_from_edit_mode PARAMS((void));
+
+/* Functions for manipulating the funmap, which maps command names to functions. */
+extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *));
+extern const char **rl_funmap_names PARAMS((void));
+/* Undocumented, only used internally -- there is only one funmap, and this
+ function may be called only once. */
+extern void rl_initialize_funmap PARAMS((void));
+
+/* Utility functions for managing keyboard macros. */
+extern void rl_push_macro_input PARAMS((char *));
+
+/* Functions for undoing, from undo.c */
+extern void rl_add_undo PARAMS((enum undo_code, int, int, char *));
+extern void rl_free_undo_list PARAMS((void));
+extern int rl_do_undo PARAMS((void));
+extern int rl_begin_undo_group PARAMS((void));
+extern int rl_end_undo_group PARAMS((void));
+extern int rl_modifying PARAMS((int, int));
+
+/* Functions for redisplay. */
+extern void rl_redisplay PARAMS((void));
+extern int rl_on_new_line PARAMS((void));
+extern int rl_on_new_line_with_prompt PARAMS((void));
+extern int rl_forced_update_display PARAMS((void));
+extern int rl_clear_message PARAMS((void));
+extern int rl_reset_line_state PARAMS((void));
+extern int rl_crlf PARAMS((void));
+
+#if (defined (__STDC__) || defined (__cplusplus)) && defined (USE_VARARGS) && defined (PREFER_STDARG)
+extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
+#else
+extern int rl_message ();
+#endif
+
+extern int rl_show_char PARAMS((int));
+
+/* Undocumented in texinfo manual. */
+extern int rl_character_len PARAMS((int, int));
+
+/* Save and restore internal prompt redisplay information. */
+extern void rl_save_prompt PARAMS((void));
+extern void rl_restore_prompt PARAMS((void));
+
+/* Modifying text. */
+extern void rl_replace_line PARAMS((const char *, int));
+extern int rl_insert_text PARAMS((const char *));
+extern int rl_delete_text PARAMS((int, int));
+extern int rl_kill_text PARAMS((int, int));
+extern char *rl_copy_text PARAMS((int, int));
+
+/* Terminal and tty mode management. */
+extern void rl_prep_terminal PARAMS((int));
+extern void rl_deprep_terminal PARAMS((void));
+extern void rl_tty_set_default_bindings PARAMS((Keymap));
+
+extern int rl_reset_terminal PARAMS((const char *));
+extern void rl_resize_terminal PARAMS((void));
+extern void rl_set_screen_size PARAMS((int, int));
+extern void rl_get_screen_size PARAMS((int *, int *));
+
+extern const char *rl_get_termcap PARAMS((const char *));
+
+/* Functions for character input. */
+extern int rl_stuff_char PARAMS((int));
+extern int rl_execute_next PARAMS((int));
+extern int rl_clear_pending_input PARAMS((void));
+extern int rl_read_key PARAMS((void));
+extern int rl_getc PARAMS((FILE *));
+extern int rl_set_keyboard_input_timeout PARAMS((int));
+
+/* `Public' utility functions . */
+extern void rl_extend_line_buffer PARAMS((int));
+extern int rl_ding PARAMS((void));
+extern int rl_alphabetic PARAMS((int));
+
+/* Readline signal handling, from signals.c */
+extern int rl_set_signals PARAMS((void));
+extern int rl_clear_signals PARAMS((void));
+extern void rl_cleanup_after_signal PARAMS((void));
+extern void rl_reset_after_signal PARAMS((void));
+extern void rl_free_line_state PARAMS((void));
+
+extern int rl_set_paren_blink_timeout PARAMS((int));
+
+/* Undocumented. */
+extern int rl_maybe_save_line PARAMS((void));
+extern int rl_maybe_unsave_line PARAMS((void));
+extern int rl_maybe_replace_line PARAMS((void));
+
+/* Completion functions. */
+extern int rl_complete_internal PARAMS((int));
+extern void rl_display_match_list PARAMS((char **, int, int));
+
+extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *));
+extern char *rl_username_completion_function PARAMS((const char *, int));
+extern char *rl_filename_completion_function PARAMS((const char *, int));
+
+extern int rl_completion_mode PARAMS((rl_command_func_t *));
+
+#if 0
+/* Backwards compatibility (compat.c). These will go away sometime. */
+extern void free_undo_list PARAMS((void));
+extern int maybe_save_line PARAMS((void));
+extern int maybe_unsave_line PARAMS((void));
+extern int maybe_replace_line PARAMS((void));
+
+extern int ding PARAMS((void));
+extern int alphabetic PARAMS((int));
+extern int crlf PARAMS((void));
+
+extern char **completion_matches PARAMS((char *, rl_compentry_func_t *));
+extern char *username_completion_function PARAMS((const char *, int));
+extern char *filename_completion_function PARAMS((const char *, int));
+#endif
+
+/* **************************************************************** */
+/* */
+/* Well Published Variables */
+/* */
+/* **************************************************************** */
+
+/* The version of this incarnation of the readline library. */
+extern const char *rl_library_version; /* e.g., "4.2" */
+extern int rl_readline_version; /* e.g., 0x0402 */
+
+/* True if this is real GNU readline. */
+extern int rl_gnu_readline_p;
+
+/* Flags word encapsulating the current readline state. */
+extern int rl_readline_state;
+
+/* Says which editing mode readline is currently using. 1 means emacs mode;
+ 0 means vi mode. */
+extern int rl_editing_mode;
+
+/* Insert or overwrite mode for emacs mode. 1 means insert mode; 0 means
+ overwrite mode. Reset to insert mode on each input line. */
+extern int rl_insert_mode;
+
+/* The name of the calling program. You should initialize this to
+ whatever was in argv[0]. It is used when parsing conditionals. */
+extern const char *rl_readline_name;
+
+/* The prompt readline uses. This is set from the argument to
+ readline (), and should not be assigned to directly. */
+extern char *rl_prompt;
+
+/* The line buffer that is in use. */
+extern char *rl_line_buffer;
+
+/* The location of point, and end. */
+extern int rl_point;
+extern int rl_end;
+
+/* The mark, or saved cursor position. */
+extern int rl_mark;
+
+/* Flag to indicate that readline has finished with the current input
+ line and should return it. */
+extern int rl_done;
+
+/* If set to a character value, that will be the next keystroke read. */
+extern int rl_pending_input;
+
+/* Non-zero if we called this function from _rl_dispatch(). It's present
+ so functions can find out whether they were called from a key binding
+ or directly from an application. */
+extern int rl_dispatching;
+
+/* Non-zero if the user typed a numeric argument before executing the
+ current function. */
+extern int rl_explicit_arg;
+
+/* The current value of the numeric argument specified by the user. */
+extern int rl_numeric_arg;
+
+/* The address of the last command function Readline executed. */
+extern rl_command_func_t *rl_last_func;
+
+/* The name of the terminal to use. */
+extern const char *rl_terminal_name;
+
+/* The input and output streams. */
+extern FILE *rl_instream;
+extern FILE *rl_outstream;
+
+/* If non-zero, then this is the address of a function to call just
+ before readline_internal () prints the first prompt. */
+extern rl_hook_func_t *rl_startup_hook;
+
+/* If non-zero, this is the address of a function to call just before
+ readline_internal_setup () returns and readline_internal starts
+ reading input characters. */
+extern rl_hook_func_t *rl_pre_input_hook;
+
+/* The address of a function to call periodically while Readline is
+ awaiting character input, or NULL, for no event handling. */
+extern rl_hook_func_t *rl_event_hook;
+
+/* The address of the function to call to fetch a character from the current
+ Readline input stream */
+extern rl_getc_func_t *rl_getc_function;
+
+extern rl_voidfunc_t *rl_redisplay_function;
+
+extern rl_vintfunc_t *rl_prep_term_function;
+extern rl_voidfunc_t *rl_deprep_term_function;
+
+/* Dispatch variables. */
+extern Keymap rl_executing_keymap;
+extern Keymap rl_binding_keymap;
+
+/* Display variables. */
+/* If non-zero, readline will erase the entire line, including any prompt,
+ if the only thing typed on an otherwise-blank line is something bound to
+ rl_newline. */
+extern int rl_erase_empty_line;
+
+/* If non-zero, the application has already printed the prompt (rl_prompt)
+ before calling readline, so readline should not output it the first time
+ redisplay is done. */
+extern int rl_already_prompted;
+
+/* A non-zero value means to read only this many characters rather than
+ up to a character bound to accept-line. */
+extern int rl_num_chars_to_read;
+
+/* The text of a currently-executing keyboard macro. */
+extern char *rl_executing_macro;
+
+/* Variables to control readline signal handling. */
+/* If non-zero, readline will install its own signal handlers for
+ SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
+extern int rl_catch_signals;
+
+/* If non-zero, readline will install a signal handler for SIGWINCH
+ that also attempts to call any calling application's SIGWINCH signal
+ handler. Note that the terminal is not cleaned up before the
+ application's signal handler is called; use rl_cleanup_after_signal()
+ to do that. */
+extern int rl_catch_sigwinch;
+
+/* Completion variables. */
+/* Pointer to the generator function for completion_matches ().
+ NULL means to use rl_filename_completion_function (), the default
+ filename completer. */
+extern rl_compentry_func_t *rl_completion_entry_function;
+
+/* If rl_ignore_some_completions_function is non-NULL it is the address
+ of a function to call after all of the possible matches have been
+ generated, but before the actual completion is done to the input line.
+ The function is called with one argument; a NULL terminated array
+ of (char *). If your function removes any of the elements, they
+ must be free()'ed. */
+extern rl_compignore_func_t *rl_ignore_some_completions_function;
+
+/* Pointer to alternative function to create matches.
+ Function is called with TEXT, START, and END.
+ START and END are indices in RL_LINE_BUFFER saying what the boundaries
+ of TEXT are.
+ If this function exists and returns NULL then call the value of
+ rl_completion_entry_function to try to match, otherwise use the
+ array of strings returned. */
+extern rl_completion_func_t *rl_attempted_completion_function;
+
+/* The basic list of characters that signal a break between words for the
+ completer routine. The initial contents of this variable is what
+ breaks words in the shell, i.e. "n\"\\'`@$>". */
+extern const char *rl_basic_word_break_characters;
+
+/* The list of characters that signal a break between words for
+ rl_complete_internal. The default list is the contents of
+ rl_basic_word_break_characters. */
+extern const char *rl_completer_word_break_characters;
+
+/* List of characters which can be used to quote a substring of the line.
+ Completion occurs on the entire substring, and within the substring
+ rl_completer_word_break_characters are treated as any other character,
+ unless they also appear within this list. */
+extern const char *rl_completer_quote_characters;
+
+/* List of quote characters which cause a word break. */
+extern const char *rl_basic_quote_characters;
+
+/* List of characters that need to be quoted in filenames by the completer. */
+extern const char *rl_filename_quote_characters;
+
+/* List of characters that are word break characters, but should be left
+ in TEXT when it is passed to the completion function. The shell uses
+ this to help determine what kind of completing to do. */
+extern const char *rl_special_prefixes;
+
+/* If non-zero, then this is the address of a function to call when
+ completing on a directory name. The function is called with
+ the address of a string (the current directory name) as an arg. It
+ changes what is displayed when the possible completions are printed
+ or inserted. */
+extern rl_icppfunc_t *rl_directory_completion_hook;
+
+/* If non-zero, this is the address of a function to call when completing
+ a directory name. This function takes the address of the directory name
+ to be modified as an argument. Unlike rl_directory_completion_hook, it
+ only modifies the directory name used in opendir(2), not what is displayed
+ when the possible completions are printed or inserted. It is called
+ before rl_directory_completion_hook. I'm not happy with how this works
+ yet, so it's undocumented. */
+extern rl_icppfunc_t *rl_directory_rewrite_hook;
+
+/* Backwards compatibility with previous versions of readline. */
+#define rl_symbolic_link_hook rl_directory_completion_hook
+
+/* If non-zero, then this is the address of a function to call when
+ completing a word would normally display the list of possible matches.
+ This function is called instead of actually doing the display.
+ It takes three arguments: (char **matches, int num_matches, int max_length)
+ where MATCHES is the array of strings that matched, NUM_MATCHES is the
+ number of strings in that array, and MAX_LENGTH is the length of the
+ longest string in that array. */
+extern rl_compdisp_func_t *rl_completion_display_matches_hook;
+
+/* Non-zero means that the results of the matches are to be treated
+ as filenames. This is ALWAYS zero on entry, and can only be changed
+ within a completion entry finder function. */
+extern int rl_filename_completion_desired;
+
+/* Non-zero means that the results of the matches are to be quoted using
+ double quotes (or an application-specific quoting mechanism) if the
+ filename contains any characters in rl_word_break_chars. This is
+ ALWAYS non-zero on entry, and can only be changed within a completion
+ entry finder function. */
+extern int rl_filename_quoting_desired;
+
+/* Set to a function to quote a filename in an application-specific fashion.
+ Called with the text to quote, the type of match found (single or multiple)
+ and a pointer to the quoting character to be used, which the function can
+ reset if desired. */
+extern rl_quote_func_t *rl_filename_quoting_function;
+
+/* Function to call to remove quoting characters from a filename. Called
+ before completion is attempted, so the embedded quotes do not interfere
+ with matching names in the file system. */
+extern rl_dequote_func_t *rl_filename_dequoting_function;
+
+/* Function to call to decide whether or not a word break character is
+ quoted. If a character is quoted, it does not break words for the
+ completer. */
+extern rl_linebuf_func_t *rl_char_is_quoted_p;
+
+/* Non-zero means to suppress normal filename completion after the
+ user-specified completion function has been called. */
+extern int rl_attempted_completion_over;
+
+/* Set to a character describing the type of completion being attempted by
+ rl_complete_internal; available for use by application completion
+ functions. */
+extern int rl_completion_type;
+
+/* Character appended to completed words when at the end of the line. The
+ default is a space. Nothing is added if this is '\0'. */
+extern int rl_completion_append_character;
+
+/* If set to non-zero by an application completion function,
+ rl_completion_append_character will not be appended. */
+extern int rl_completion_suppress_append;
+
+/* Up to this many items will be displayed in response to a
+ possible-completions call. After that, we ask the user if she
+ is sure she wants to see them all. The default value is 100. */
+extern int rl_completion_query_items;
+
+/* If non-zero, a slash will be appended to completed filenames that are
+ symbolic links to directory names, subject to the value of the
+ mark-directories variable (which is user-settable). This exists so
+ that application completion functions can override the user's preference
+ (set via the mark-symlinked-directories variable) if appropriate.
+ It's set to the value of _rl_complete_mark_symlink_dirs in
+ rl_complete_internal before any application-specific completion
+ function is called, so without that function doing anything, the user's
+ preferences are honored. */
+extern int rl_completion_mark_symlink_dirs;
+
+/* If non-zero, then disallow duplicates in the matches. */
+extern int rl_ignore_completion_duplicates;
+
+/* If this is non-zero, completion is (temporarily) inhibited, and the
+ completion character will be inserted as any other. */
+extern int rl_inhibit_completion;
+
+/* Definitions available for use by readline clients. */
+#define RL_PROMPT_START_IGNORE '\001'
+#define RL_PROMPT_END_IGNORE '\002'
+
+/* Possible values for do_replace argument to rl_filename_quoting_function,
+ called by rl_complete_internal. */
+#define NO_MATCH 0
+#define SINGLE_MATCH 1
+#define MULT_MATCH 2
+
+/* Possible state values for rl_readline_state */
+#define RL_STATE_NONE 0x00000 /* no state; before first call */
+
+#define RL_STATE_INITIALIZING 0x00001 /* initializing */
+#define RL_STATE_INITIALIZED 0x00002 /* initialization done */
+#define RL_STATE_TERMPREPPED 0x00004 /* terminal is prepped */
+#define RL_STATE_READCMD 0x00008 /* reading a command key */
+#define RL_STATE_METANEXT 0x00010 /* reading input after ESC */
+#define RL_STATE_DISPATCHING 0x00020 /* dispatching to a command */
+#define RL_STATE_MOREINPUT 0x00040 /* reading more input in a command function */
+#define RL_STATE_ISEARCH 0x00080 /* doing incremental search */
+#define RL_STATE_NSEARCH 0x00100 /* doing non-inc search */
+#define RL_STATE_SEARCH 0x00200 /* doing a history search */
+#define RL_STATE_NUMERICARG 0x00400 /* reading numeric argument */
+#define RL_STATE_MACROINPUT 0x00800 /* getting input from a macro */
+#define RL_STATE_MACRODEF 0x01000 /* defining keyboard macro */
+#define RL_STATE_OVERWRITE 0x02000 /* overwrite mode */
+#define RL_STATE_COMPLETING 0x04000 /* doing completion */
+#define RL_STATE_SIGHANDLER 0x08000 /* in readline sighandler */
+#define RL_STATE_UNDOING 0x10000 /* doing an undo */
+#define RL_STATE_INPUTPENDING 0x20000 /* rl_execute_next called */
+
+#define RL_STATE_DONE 0x80000 /* done; accepted line */
+
+#define RL_SETSTATE(x) (rl_readline_state |= (x))
+#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
+#define RL_ISSTATE(x) (rl_readline_state & (x))
+
+struct readline_state {
+ /* line state */
+ int point;
+ int end;
+ int mark;
+ char *buffer;
+ int buflen;
+ UNDO_LIST *ul;
+ char *prompt;
+
+ /* global state */
+ int rlstate;
+ int done;
+ Keymap kmap;
+
+ /* input state */
+ rl_command_func_t *lastfunc;
+ int insmode;
+ int edmode;
+ int kseqlen;
+ FILE *inf;
+ FILE *outf;
+ int pendingin;
+ char *macro;
+
+ /* signal state */
+ int catchsigs;
+ int catchsigwinch;
+
+ /* reserved for future expansion, so the struct size doesn't change */
+ char reserved[64];
+};
+
+extern int rl_save_state PARAMS((struct readline_state *));
+extern int rl_restore_state PARAMS((struct readline_state *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _READLINE_H_ */
diff --git a/cmd-line-utils/readline/rlconf.h b/cmd-line-utils/readline/rlconf.h
new file mode 100644
index 00000000000..c651fd8b41f
--- /dev/null
+++ b/cmd-line-utils/readline/rlconf.h
@@ -0,0 +1,60 @@
+/* rlconf.h -- readline configuration definitions */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RLCONF_H_)
+#define _RLCONF_H_
+
+/* Define this if you want the vi-mode editing available. */
+#define VI_MODE
+
+/* Define this to get an indication of file type when listing completions. */
+#define VISIBLE_STATS
+
+/* This definition is needed by readline.c, rltty.c, and signals.c. */
+/* If on, then readline handles signals in a way that doesn't screw. */
+#define HANDLE_SIGNALS
+
+/* Ugly but working hack for binding prefix meta. */
+#define PREFIX_META_HACK
+
+/* The final, last-ditch effort file name for an init file. */
+#define DEFAULT_INPUTRC "~/.inputrc"
+
+/* If defined, expand tabs to spaces. */
+#define DISPLAY_TABS
+
+/* If defined, use the terminal escape sequence to move the cursor forward
+ over a character when updating the line rather than rewriting it. */
+/* #define HACK_TERMCAP_MOTION */
+
+/* The string inserted by the `insert comment' command. */
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+
+/* Define this if you want code that allows readline to be used in an
+ X `callback' style. */
+#define READLINE_CALLBACKS
+
+/* Define this if you want the cursor to indicate insert or overwrite mode. */
+/* #define CURSOR_MODE */
+
+#endif /* _RLCONF_H_ */
diff --git a/cmd-line-utils/readline/rldefs.h b/cmd-line-utils/readline/rldefs.h
new file mode 100644
index 00000000000..5cba9a5ac32
--- /dev/null
+++ b/cmd-line-utils/readline/rldefs.h
@@ -0,0 +1,160 @@
+/* rldefs.h -- an attempt to isolate some of the system-specific defines
+ for readline. This should be included after any files that define
+ system-specific constants like _POSIX_VERSION or USG. */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RLDEFS_H_)
+#define _RLDEFS_H_
+
+#if defined (HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include "rlstdc.h"
+
+#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ <8)
+#define __attribute__(A)
+#endif
+
+#if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING)
+# define TERMIOS_TTY_DRIVER
+#else
+# if defined (HAVE_TERMIO_H)
+# define TERMIO_TTY_DRIVER
+# else
+# define NEW_TTY_DRIVER
+# endif
+#endif
+
+/* Posix macro to check file in statbuf for directory-ness.
+ This requires that <sys/stat.h> be included before this test. */
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+# define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#endif
+
+/* Decide which flavor of the header file describing the C library
+ string functions to include and include it. */
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else /* !HAVE_STRING_H */
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+#if defined (PREFER_STDARG)
+# include <stdarg.h>
+#else
+# if defined (PREFER_VARARGS)
+# include <varargs.h>
+# endif
+#endif
+
+#if defined (HAVE_STRCASECMP)
+#define _rl_stricmp strcasecmp
+#define _rl_strnicmp strncasecmp
+#else
+extern int _rl_stricmp PARAMS((char *, char *));
+extern int _rl_strnicmp PARAMS((char *, char *, int));
+#endif
+
+#if defined (HAVE_STRPBRK)
+# define _rl_strpbrk(a,b) strpbrk((a),(b))
+#else
+extern char *_rl_strpbrk PARAMS((const char *, const char *));
+#endif
+
+#if !defined (emacs_mode)
+# define no_mode -1
+# define vi_mode 0
+# define emacs_mode 1
+#endif
+
+#if !defined (RL_IM_INSERT)
+# define RL_IM_INSERT 1
+# define RL_IM_OVERWRITE 0
+#
+# define RL_IM_DEFAULT RL_IM_INSERT
+#endif
+
+/* If you cast map[key].function to type (Keymap) on a Cray,
+ the compiler takes the value of map[key].function and
+ divides it by 4 to convert between pointer types (pointers
+ to functions and pointers to structs are different sizes).
+ This is not what is wanted. */
+#if defined (CRAY)
+# define FUNCTION_TO_KEYMAP(map, key) (Keymap)((int)map[key].function)
+# define KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)((int)(data))
+#else
+# define FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function)
+# define KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)(data)
+#endif
+
+#ifndef savestring
+#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
+#endif
+
+/* Possible values for _rl_bell_preference. */
+#define NO_BELL 0
+#define AUDIBLE_BELL 1
+#define VISIBLE_BELL 2
+
+/* Definitions used when searching the line for characters. */
+/* NOTE: it is necessary that opposite directions are inverses */
+#define FTO 1 /* forward to */
+#define BTO -1 /* backward to */
+#define FFIND 2 /* forward find */
+#define BFIND -2 /* backward find */
+
+/* Possible values for the found_quote flags word used by the completion
+ functions. It says what kind of (shell-like) quoting we found anywhere
+ in the line. */
+#define RL_QF_SINGLE_QUOTE 0x01
+#define RL_QF_DOUBLE_QUOTE 0x02
+#define RL_QF_BACKSLASH 0x04
+#define RL_QF_OTHER_QUOTE 0x08
+
+/* Default readline line buffer length. */
+#define DEFAULT_BUFFER_SIZE 256
+
+#if !defined (STREQ)
+#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
+#define STREQN(a, b, n) (((n) == 0) ? (1) \
+ : ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
+#endif
+
+#if !defined (FREE)
+# define FREE(x) if (x) free (x)
+#endif
+
+#if !defined (SWAP)
+# define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
+#endif
+
+/* CONFIGURATION SECTION */
+#include "rlconf.h"
+
+#endif /* !_RLDEFS_H_ */
diff --git a/cmd-line-utils/readline/rlmbutil.h b/cmd-line-utils/readline/rlmbutil.h
new file mode 100644
index 00000000000..4660a72fce5
--- /dev/null
+++ b/cmd-line-utils/readline/rlmbutil.h
@@ -0,0 +1,108 @@
+/* rlmbutil.h -- utility functions for multibyte characters. */
+
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_MBUTIL_H_)
+#define _RL_MBUTIL_H_
+
+#include "rlstdc.h"
+
+/************************************************/
+/* check multibyte capability for I18N code */
+/************************************************/
+
+/* For platforms which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+ /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
+#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
+# include <wchar.h>
+# include <wctype.h>
+# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
+# define HANDLE_MULTIBYTE 1
+# endif
+#endif
+
+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
+#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
+# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
+# define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
+# define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+# define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
+# define mbstate_t int
+#endif
+
+/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
+ handle multibyte chars (some systems define MB_LEN_MAX as 1) */
+#ifdef HANDLE_MULTIBYTE
+# include <limits.h>
+# if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
+# undef MB_LEN_MAX
+# endif
+# if !defined (MB_LEN_MAX)
+# define MB_LEN_MAX 16
+# endif
+#endif
+
+/************************************************/
+/* end of multibyte capability checks for I18N */
+/************************************************/
+
+/*
+ * Flags for _rl_find_prev_mbchar and _rl_find_next_mbchar:
+ *
+ * MB_FIND_ANY find any multibyte character
+ * MB_FIND_NONZERO find a non-zero-width multibyte character
+ */
+
+#define MB_FIND_ANY 0x00
+#define MB_FIND_NONZERO 0x01
+
+extern int _rl_find_prev_mbchar PARAMS((char *, int, int));
+extern int _rl_find_next_mbchar PARAMS((char *, int, int, int));
+
+#ifdef HANDLE_MULTIBYTE
+
+extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *));
+extern int _rl_get_char_len PARAMS((const char *, mbstate_t *));
+extern int _rl_adjust_point PARAMS((const char *, int, mbstate_t *));
+
+extern int _rl_read_mbchar PARAMS((char *, int));
+extern int _rl_read_mbstring PARAMS((int, char *, int));
+
+extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
+
+#else /* !HANDLE_MULTIBYTE */
+
+#undef MB_LEN_MAX
+#undef MB_CUR_MAX
+
+#define MB_LEN_MAX 1
+#define MB_CUR_MAX 1
+
+#define _rl_find_prev_mbchar(b, i, f) (((i) == 0) ? (i) : ((i) - 1))
+#define _rl_find_next_mbchar(b, i1, i2, f) ((i1) + (i2))
+
+#endif /* !HANDLE_MULTIBYTE */
+
+extern int rl_byte_oriented;
+
+#endif /* _RL_MBUTIL_H_ */
diff --git a/cmd-line-utils/readline/rlprivate.h b/cmd-line-utils/readline/rlprivate.h
new file mode 100644
index 00000000000..36645fb4a65
--- /dev/null
+++ b/cmd-line-utils/readline/rlprivate.h
@@ -0,0 +1,284 @@
+/* rlprivate.h -- functions and variables global to the readline library,
+ but not intended for use by applications. */
+
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_PRIVATE_H_)
+#define _RL_PRIVATE_H_
+
+#include "rlconf.h" /* for VISIBLE_STATS */
+#include "rlstdc.h"
+#include "posixjmp.h" /* defines procenv_t */
+
+/*************************************************************************
+ * *
+ * Global functions undocumented in texinfo manual and not in readline.h *
+ * *
+ *************************************************************************/
+
+/*************************************************************************
+ * *
+ * Global variables undocumented in texinfo manual and not in readline.h *
+ * *
+ *************************************************************************/
+
+/* complete.c */
+extern int rl_complete_with_tilde_expansion;
+#if defined (VISIBLE_STATS)
+extern int rl_visible_stats;
+#endif /* VISIBLE_STATS */
+
+/* readline.c */
+extern int rl_line_buffer_len;
+extern int rl_arg_sign;
+extern int rl_visible_prompt_length;
+extern int readline_echoing_p;
+extern int rl_key_sequence_length;
+extern int rl_byte_oriented;
+
+/* display.c */
+extern int rl_display_fixed;
+
+/* parens.c */
+extern int rl_blink_matching_paren;
+
+/*************************************************************************
+ * *
+ * Global functions and variables unsed and undocumented *
+ * *
+ *************************************************************************/
+
+/* kill.c */
+extern int rl_set_retained_kills PARAMS((int));
+
+/* terminal.c */
+extern void _rl_set_screen_size PARAMS((int, int));
+
+/* undo.c */
+extern int _rl_fix_last_undo_of_type PARAMS((unsigned int, int, int));
+
+/* util.c */
+extern char *_rl_savestring PARAMS((const char *));
+
+/*************************************************************************
+ * *
+ * Functions and variables private to the readline library *
+ * *
+ *************************************************************************/
+
+/* NOTE: Functions and variables prefixed with `_rl_' are
+ pseudo-global: they are global so they can be shared
+ between files in the readline library, but are not intended
+ to be visible to readline callers. */
+
+/*************************************************************************
+ * Undocumented private functions *
+ *************************************************************************/
+
+#if defined(READLINE_CALLBACKS)
+
+/* readline.c */
+extern void readline_internal_setup PARAMS((void));
+extern char *readline_internal_teardown PARAMS((int));
+extern int readline_internal_char PARAMS((void));
+
+#endif /* READLINE_CALLBACKS */
+
+/* bind.c */
+extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *));
+
+/* complete.c */
+extern char _rl_find_completion_word PARAMS((int *, int *));
+extern void _rl_free_match_list PARAMS((char **));
+
+/* display.c */
+extern char *_rl_strip_prompt PARAMS((char *));
+extern void _rl_move_cursor_relative PARAMS((int, const char *));
+extern void _rl_move_vert PARAMS((int));
+extern void _rl_save_prompt PARAMS((void));
+extern void _rl_restore_prompt PARAMS((void));
+extern char *_rl_make_prompt_for_search PARAMS((int));
+extern void _rl_erase_at_end_of_line PARAMS((int));
+extern void _rl_clear_to_eol PARAMS((int));
+extern void _rl_clear_screen PARAMS((void));
+extern void _rl_update_final PARAMS((void));
+extern void _rl_redisplay_after_sigwinch PARAMS((void));
+extern void _rl_clean_up_for_exit PARAMS((void));
+extern void _rl_erase_entire_line PARAMS((void));
+extern int _rl_current_display_line PARAMS((void));
+
+/* input.c */
+extern int _rl_any_typein PARAMS((void));
+extern int _rl_input_available PARAMS((void));
+extern int _rl_input_queued PARAMS((int));
+extern void _rl_insert_typein PARAMS((int));
+extern int _rl_unget_char PARAMS((int));
+
+/* macro.c */
+extern void _rl_with_macro_input PARAMS((char *));
+extern int _rl_next_macro_key PARAMS((void));
+extern void _rl_push_executing_macro PARAMS((void));
+extern void _rl_pop_executing_macro PARAMS((void));
+extern void _rl_add_macro_char PARAMS((int));
+extern void _rl_kill_kbd_macro PARAMS((void));
+
+/* misc.c */
+extern int _rl_init_argument PARAMS((void));
+extern void _rl_start_using_history PARAMS((void));
+extern int _rl_free_saved_history_line PARAMS((void));
+extern void _rl_set_insert_mode PARAMS((int, int));
+
+/* nls.c */
+extern int _rl_init_eightbit PARAMS((void));
+
+/* parens.c */
+extern void _rl_enable_paren_matching PARAMS((int));
+
+/* readline.c */
+extern void _rl_init_line_state PARAMS((void));
+extern void _rl_set_the_line PARAMS((void));
+extern int _rl_dispatch PARAMS((int, Keymap));
+extern int _rl_dispatch_subseq PARAMS((int, Keymap, int));
+
+/* rltty.c */
+extern int _rl_disable_tty_signals PARAMS((void));
+extern int _rl_restore_tty_signals PARAMS((void));
+
+/* terminal.c */
+extern void _rl_get_screen_size PARAMS((int, int));
+extern int _rl_init_terminal_io PARAMS((const char *));
+#ifdef _MINIX
+extern void _rl_output_character_function PARAMS((int));
+#else
+extern int _rl_output_character_function PARAMS((int));
+#endif
+extern void _rl_output_some_chars PARAMS((const char *, int));
+extern int _rl_backspace PARAMS((int));
+extern void _rl_enable_meta_key PARAMS((void));
+extern void _rl_control_keypad PARAMS((int));
+extern void _rl_set_cursor PARAMS((int, int));
+
+/* text.c */
+extern void _rl_fix_point PARAMS((int));
+extern int _rl_replace_text PARAMS((const char *, int, int));
+extern int _rl_insert_char PARAMS((int, int));
+extern int _rl_overwrite_char PARAMS((int, int));
+extern int _rl_overwrite_rubout PARAMS((int, int));
+extern int _rl_rubout_char PARAMS((int, int));
+#if defined (HANDLE_MULTIBYTE)
+extern int _rl_char_search_internal PARAMS((int, int, char *, int));
+#else
+extern int _rl_char_search_internal PARAMS((int, int, int));
+#endif
+extern int _rl_set_mark_at_pos PARAMS((int));
+
+/* util.c */
+extern int _rl_abort_internal PARAMS((void));
+extern char *_rl_strindex PARAMS((const char *, const char *));
+extern int _rl_qsort_string_compare PARAMS((char **, char **));
+extern int (_rl_uppercase_p) PARAMS((int));
+extern int (_rl_lowercase_p) PARAMS((int));
+extern int (_rl_pure_alphabetic) PARAMS((int));
+extern int (_rl_digit_p) PARAMS((int));
+extern int (_rl_to_lower) PARAMS((int));
+extern int (_rl_to_upper) PARAMS((int));
+extern int (_rl_digit_value) PARAMS((int));
+
+/* vi_mode.c */
+extern void _rl_vi_initialize_line PARAMS((void));
+extern void _rl_vi_reset_last PARAMS((void));
+extern void _rl_vi_set_last PARAMS((int, int, int));
+extern int _rl_vi_textmod_command PARAMS((int));
+extern void _rl_vi_done_inserting PARAMS((void));
+
+/*************************************************************************
+ * Undocumented private variables *
+ *************************************************************************/
+
+/* bind.c */
+extern const char *_rl_possible_control_prefixes[];
+extern const char *_rl_possible_meta_prefixes[];
+
+/* complete.c */
+extern int _rl_complete_show_all;
+extern int _rl_complete_mark_directories;
+extern int _rl_complete_mark_symlink_dirs;
+extern int _rl_print_completions_horizontally;
+extern int _rl_completion_case_fold;
+extern int _rl_match_hidden_files;
+extern int _rl_page_completions;
+
+/* display.c */
+extern int _rl_vis_botlin;
+extern int _rl_last_c_pos;
+extern int _rl_suppress_redisplay;
+extern const char *rl_display_prompt;
+
+/* isearch.c */
+extern char *_rl_isearch_terminators;
+
+/* macro.c */
+extern char *_rl_executing_macro;
+
+/* misc.c */
+extern int _rl_history_preserve_point;
+extern int _rl_history_saved_point;
+
+/* readline.c */
+extern int _rl_horizontal_scroll_mode;
+extern int _rl_mark_modified_lines;
+extern int _rl_bell_preference;
+extern int _rl_meta_flag;
+extern int _rl_convert_meta_chars_to_ascii;
+extern int _rl_output_meta_chars;
+extern char *_rl_comment_begin;
+extern unsigned char _rl_parsing_conditionalized_out;
+extern Keymap _rl_keymap;
+extern FILE *_rl_in_stream;
+extern FILE *_rl_out_stream;
+extern int _rl_last_command_was_kill;
+extern int _rl_eof_char;
+extern procenv_t readline_top_level;
+
+/* terminal.c */
+extern int _rl_enable_keypad;
+extern int _rl_enable_meta;
+extern const char *_rl_term_clreol;
+extern const char *_rl_term_clrpag;
+extern const char *_rl_term_im;
+extern const char *_rl_term_ic;
+extern const char *_rl_term_ei;
+extern const char *_rl_term_DC;
+extern const char *_rl_term_up;
+extern const char *_rl_term_dc;
+extern const char *_rl_term_cr;
+extern const char *_rl_term_IC;
+extern int _rl_screenheight;
+extern int _rl_screenwidth;
+extern int _rl_screenchars;
+extern int _rl_terminal_can_insert;
+extern int _rl_term_autowrap;
+
+/* undo.c */
+extern int _rl_doing_an_undo;
+extern int _rl_undo_group_level;
+
+#endif /* _RL_PRIVATE_H_ */
diff --git a/cmd-line-utils/readline/rlshell.h b/cmd-line-utils/readline/rlshell.h
new file mode 100644
index 00000000000..3c03fbad576
--- /dev/null
+++ b/cmd-line-utils/readline/rlshell.h
@@ -0,0 +1,34 @@
+/* rlshell.h -- utility functions normally provided by bash. */
+
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_SHELL_H_)
+#define _RL_SHELL_H_
+
+#include "rlstdc.h"
+
+extern char *sh_single_quote PARAMS((char *));
+extern void sh_set_lines_and_columns PARAMS((int, int));
+extern char *sh_get_env_value PARAMS((const char *));
+extern char *sh_get_home_dir PARAMS((void));
+extern int sh_unset_nodelay_mode PARAMS((int));
+
+#endif /* _RL_SHELL_H_ */
diff --git a/cmd-line-utils/readline/rlstdc.h b/cmd-line-utils/readline/rlstdc.h
new file mode 100644
index 00000000000..d6a22b3742c
--- /dev/null
+++ b/cmd-line-utils/readline/rlstdc.h
@@ -0,0 +1,45 @@
+/* stdc.h -- macros to make source compile on both ANSI C and K&R C
+ compilers. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_STDC_H_)
+#define _RL_STDC_H_
+
+/* Adapted from BSD /usr/include/sys/cdefs.h. */
+
+/* A function can be defined using prototypes and compile on both ANSI C
+ and traditional C compilers with something like this:
+ extern char *func PARAMS((char *, char *, int)); */
+
+#if !defined (PARAMS)
+# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus)
+# define PARAMS(protos) protos
+# else
+# define PARAMS(protos) ()
+# endif
+#endif
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+#endif /* !_RL_STDC_H_ */
diff --git a/cmd-line-utils/readline/rltty.c b/cmd-line-utils/readline/rltty.c
new file mode 100644
index 00000000000..09702e9e755
--- /dev/null
+++ b/cmd-line-utils/readline/rltty.c
@@ -0,0 +1,911 @@
+/* rltty.c -- functions to prepare and restore the terminal for readline's
+ use. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+#include "rltty.h"
+#include "readline.h"
+#include "rlprivate.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
+rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
+
+static void block_sigint PARAMS((void));
+static void release_sigint PARAMS((void));
+
+static void set_winsize PARAMS((int));
+
+/* **************************************************************** */
+/* */
+/* Signal Management */
+/* */
+/* **************************************************************** */
+
+#if defined (HAVE_POSIX_SIGNALS)
+static sigset_t sigint_set, sigint_oset;
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+static int sigint_oldmask;
+# endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+static int sigint_blocked;
+
+/* Cause SIGINT to not be delivered until the corresponding call to
+ release_sigint(). */
+static void
+block_sigint ()
+{
+ if (sigint_blocked)
+ return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+ sigemptyset (&sigint_set);
+ sigemptyset (&sigint_oset);
+ sigaddset (&sigint_set, SIGINT);
+ sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+ sigint_oldmask = sigblock (sigmask (SIGINT));
+# else /* !HAVE_BSD_SIGNALS */
+# if defined (HAVE_USG_SIGHOLD)
+ sighold (SIGINT);
+# endif /* HAVE_USG_SIGHOLD */
+# endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ sigint_blocked = 1;
+}
+
+/* Allow SIGINT to be delivered. */
+static void
+release_sigint ()
+{
+ if (sigint_blocked == 0)
+ return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+ sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
+#else
+# if defined (HAVE_BSD_SIGNALS)
+ sigsetmask (sigint_oldmask);
+# else /* !HAVE_BSD_SIGNALS */
+# if defined (HAVE_USG_SIGHOLD)
+ sigrelse (SIGINT);
+# endif /* HAVE_USG_SIGHOLD */
+# endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ sigint_blocked = 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Saving and Restoring the TTY */
+/* */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped;
+
+static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars;
+
+/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
+ and output is suspended. */
+#if defined (__ksr1__)
+static int ksrflow;
+#endif
+
+/* Dummy call to force a backgrounded readline to stop before it tries
+ to get the tty settings. */
+static void
+set_winsize (tty)
+ int tty;
+{
+#if defined (TIOCGWINSZ)
+ struct winsize w;
+
+ if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+ (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif /* TIOCGWINSZ */
+}
+
+#if defined (NEW_TTY_DRIVER)
+
+/* Values for the `flags' field of a struct bsdtty. This tells which
+ elements of the struct bsdtty have been fetched from the system and
+ are valid. */
+#define SGTTY_SET 0x01
+#define LFLAG_SET 0x02
+#define TCHARS_SET 0x04
+#define LTCHARS_SET 0x08
+
+struct bsdtty {
+ struct sgttyb sgttyb; /* Basic BSD tty driver information. */
+ int lflag; /* Local mode flags, like LPASS8. */
+#if defined (TIOCGETC)
+ struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
+#endif
+#if defined (TIOCGLTC)
+ struct ltchars ltchars; /* 4.2 BSD editing characters */
+#endif
+ int flags; /* Bitmap saying which parts of the struct are valid. */
+};
+
+#define TIOTYPE struct bsdtty
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void
+save_tty_chars (tiop)
+ TIOTYPE *tiop;
+{
+ _rl_last_tty_chars = _rl_tty_chars;
+
+ if (tiop->flags & SGTTY_SET)
+ {
+ _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
+ _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
+ }
+
+ if (tiop->flags & TCHARS_SET)
+ {
+ _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
+ _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
+ _rl_tty_chars.t_start = tiop->tchars.t_startc;
+ _rl_tty_chars.t_stop = tiop->tchars.t_stopc;
+ _rl_tty_chars.t_eof = tiop->tchars.t_eofc;
+ _rl_tty_chars.t_eol = '\n';
+ _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
+ }
+
+ if (tiop->flags & LTCHARS_SET)
+ {
+ _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
+ _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
+ _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
+ _rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
+ _rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
+ _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
+ }
+
+ _rl_tty_chars.t_status = -1;
+}
+
+static int
+get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ set_winsize (tty);
+
+ tiop->flags = tiop->lflag = 0;
+
+ if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
+ return -1;
+ tiop->flags |= SGTTY_SET;
+
+#if defined (TIOCLGET)
+ if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
+ tiop->flags |= LFLAG_SET;
+#endif
+
+#if defined (TIOCGETC)
+ if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
+ tiop->flags |= TCHARS_SET;
+#endif
+
+#if defined (TIOCGLTC)
+ if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
+ tiop->flags |= LTCHARS_SET;
+#endif
+
+ return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ if (tiop->flags & SGTTY_SET)
+ {
+ ioctl (tty, TIOCSETN, &(tiop->sgttyb));
+ tiop->flags &= ~SGTTY_SET;
+ }
+ readline_echoing_p = 1;
+
+#if defined (TIOCLSET)
+ if (tiop->flags & LFLAG_SET)
+ {
+ ioctl (tty, TIOCLSET, &(tiop->lflag));
+ tiop->flags &= ~LFLAG_SET;
+ }
+#endif
+
+#if defined (TIOCSETC)
+ if (tiop->flags & TCHARS_SET)
+ {
+ ioctl (tty, TIOCSETC, &(tiop->tchars));
+ tiop->flags &= ~TCHARS_SET;
+ }
+#endif
+
+#if defined (TIOCSLTC)
+ if (tiop->flags & LTCHARS_SET)
+ {
+ ioctl (tty, TIOCSLTC, &(tiop->ltchars));
+ tiop->flags &= ~LTCHARS_SET;
+ }
+#endif
+
+ return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+ int meta_flag;
+ TIOTYPE oldtio, *tiop;
+{
+ readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
+
+ /* Copy the original settings to the structure we're going to use for
+ our settings. */
+ tiop->sgttyb = oldtio.sgttyb;
+ tiop->lflag = oldtio.lflag;
+#if defined (TIOCGETC)
+ tiop->tchars = oldtio.tchars;
+#endif
+#if defined (TIOCGLTC)
+ tiop->ltchars = oldtio.ltchars;
+#endif
+ tiop->flags = oldtio.flags;
+
+ /* First, the basic settings to put us into character-at-a-time, no-echo
+ input mode. */
+ tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
+ tiop->sgttyb.sg_flags |= CBREAK;
+
+ /* If this terminal doesn't care how the 8th bit is used, then we can
+ use it for the meta-key. If only one of even or odd parity is
+ specified, then the terminal is using parity, and we cannot. */
+#if !defined (ANYP)
+# define ANYP (EVENP | ODDP)
+#endif
+ if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
+ ((oldtio.sgttyb.sg_flags & ANYP) == 0))
+ {
+ tiop->sgttyb.sg_flags |= ANYP;
+
+ /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET)
+# if defined (LPASS8)
+ tiop->lflag |= LPASS8;
+# endif /* LPASS8 */
+#endif /* TIOCLGET */
+ }
+
+#if defined (TIOCGETC)
+# if defined (USE_XON_XOFF)
+ /* Get rid of terminal output start and stop characters. */
+ tiop->tchars.t_stopc = -1; /* C-s */
+ tiop->tchars.t_startc = -1; /* C-q */
+
+ /* If there is an XON character, bind it to restart the output. */
+ if (oldtio.tchars.t_startc != -1)
+ rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
+# endif /* USE_XON_XOFF */
+
+ /* If there is an EOF char, bind _rl_eof_char to it. */
+ if (oldtio.tchars.t_eofc != -1)
+ _rl_eof_char = oldtio.tchars.t_eofc;
+
+# if defined (NO_KILL_INTR)
+ /* Get rid of terminal-generated SIGQUIT and SIGINT. */
+ tiop->tchars.t_quitc = -1; /* C-\ */
+ tiop->tchars.t_intrc = -1; /* C-c */
+# endif /* NO_KILL_INTR */
+#endif /* TIOCGETC */
+
+#if defined (TIOCGLTC)
+ /* Make the interrupt keys go away. Just enough to make people happy. */
+ tiop->ltchars.t_dsuspc = -1; /* C-y */
+ tiop->ltchars.t_lnextc = -1; /* C-v */
+#endif /* TIOCGLTC */
+}
+
+#else /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+# define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+# define VTIME VEOL
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+# define TIOTYPE struct termios
+# define DRAIN_OUTPUT(fd) tcdrain (fd)
+# define GETATTR(tty, tiop) (tcgetattr (tty, tiop))
+# ifdef M_UNIX
+# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
+# else
+# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
+# endif /* !M_UNIX */
+#else
+# define TIOTYPE struct termio
+# define DRAIN_OUTPUT(fd)
+# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop))
+# define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop))
+#endif /* !TERMIOS_TTY_DRIVER */
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+#if defined (FLUSHO)
+# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
+#else
+# define OUTPUT_BEING_FLUSHED(tp) 0
+#endif
+
+static void
+save_tty_chars (tiop)
+ TIOTYPE *tiop;
+{
+ _rl_last_tty_chars = _rl_tty_chars;
+
+ _rl_tty_chars.t_eof = tiop->c_cc[VEOF];
+ _rl_tty_chars.t_eol = tiop->c_cc[VEOL];
+#ifdef VEOL2
+ _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
+#endif
+ _rl_tty_chars.t_erase = tiop->c_cc[VERASE];
+#ifdef VWERASE
+ _rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
+#endif
+ _rl_tty_chars.t_kill = tiop->c_cc[VKILL];
+#ifdef VREPRINT
+ _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
+#endif
+ _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
+ _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
+#ifdef VSUSP
+ _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
+#endif
+#ifdef VDSUSP
+ _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
+#endif
+#ifdef VSTART
+ _rl_tty_chars.t_start = tiop->c_cc[VSTART];
+#endif
+#ifdef VSTOP
+ _rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
+#endif
+#ifdef VLNEXT
+ _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
+#endif
+#ifdef VDISCARD
+ _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
+#endif
+#ifdef VSTATUS
+ _rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
+#endif
+}
+
+#if defined (_AIX) || defined (_AIX41)
+/* Currently this is only used on AIX */
+static void
+rltty_warning (msg)
+ char *msg;
+{
+ fprintf (stderr, "readline: warning: %s\n", msg);
+}
+#endif
+
+#if defined (_AIX)
+void
+setopost(tp)
+TIOTYPE *tp;
+{
+ if ((tp->c_oflag & OPOST) == 0)
+ {
+ rltty_warning ("turning on OPOST for terminal\r");
+ tp->c_oflag |= OPOST|ONLCR;
+ }
+}
+#endif
+
+static int
+_get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ int ioctl_ret;
+
+ while (1)
+ {
+ ioctl_ret = GETATTR (tty, tiop);
+ if (ioctl_ret < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ else
+ continue;
+ }
+ if (OUTPUT_BEING_FLUSHED (tiop))
+ {
+#if defined (FLUSHO) && defined (_AIX41)
+ rltty_warning ("turning off output flushing");
+ tiop->c_lflag &= ~FLUSHO;
+ break;
+#else
+ continue;
+#endif
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int
+get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ set_winsize (tty);
+
+ if (_get_tty_settings (tty, tiop) < 0)
+ return -1;
+
+#if defined (_AIX)
+ setopost(tiop);
+#endif
+
+ return 0;
+}
+
+static int
+_set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ while (SETATTR (tty, tiop) < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ errno = 0;
+ }
+ return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ if (_set_tty_settings (tty, tiop) < 0)
+ return -1;
+
+#if 0
+
+#if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ if (ksrflow)
+ {
+ ksrflow = 0;
+ tcflow (tty, TCOON);
+ }
+# else /* !ksr1 */
+ tcflow (tty, TCOON); /* Simulate a ^Q. */
+# endif /* !ksr1 */
+#else
+ ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
+#endif /* !TERMIOS_TTY_DRIVER */
+
+#endif /* 0 */
+
+ return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+ int meta_flag;
+ TIOTYPE oldtio, *tiop;
+{
+ readline_echoing_p = (oldtio.c_lflag & ECHO);
+
+ tiop->c_lflag &= ~(ICANON | ECHO);
+
+ if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
+ _rl_eof_char = oldtio.c_cc[VEOF];
+
+#if defined (USE_XON_XOFF)
+#if defined (IXANY)
+ tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
+#else
+ /* `strict' Posix systems do not define IXANY. */
+ tiop->c_iflag &= ~(IXON | IXOFF);
+#endif /* IXANY */
+#endif /* USE_XON_XOFF */
+
+ /* Only turn this off if we are using all 8 bits. */
+ if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
+ tiop->c_iflag &= ~(ISTRIP | INPCK);
+
+ /* Make sure we differentiate between CR and NL on input. */
+ tiop->c_iflag &= ~(ICRNL | INLCR);
+
+#if !defined (HANDLE_SIGNALS)
+ tiop->c_lflag &= ~ISIG;
+#else
+ tiop->c_lflag |= ISIG;
+#endif
+
+ tiop->c_cc[VMIN] = 1;
+ tiop->c_cc[VTIME] = 0;
+
+#if defined (FLUSHO)
+ if (OUTPUT_BEING_FLUSHED (tiop))
+ {
+ tiop->c_lflag &= ~FLUSHO;
+ oldtio.c_lflag &= ~FLUSHO;
+ }
+#endif
+
+ /* Turn off characters that we need on Posix systems with job control,
+ just to be sure. This includes ^Y and ^V. This should not really
+ be necessary. */
+#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
+
+#if defined (VLNEXT)
+ tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+ tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
+}
+#endif /* NEW_TTY_DRIVER */
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+void
+rl_prep_terminal (meta_flag)
+ int meta_flag;
+{
+ int tty;
+ TIOTYPE tio;
+
+ if (terminal_prepped)
+ return;
+
+ /* Try to keep this function from being INTerrupted. */
+ block_sigint ();
+
+ tty = fileno (rl_instream);
+
+ if (get_tty_settings (tty, &tio) < 0)
+ {
+ release_sigint ();
+ return;
+ }
+
+ otio = tio;
+
+ save_tty_chars (&otio);
+
+ prepare_terminal_settings (meta_flag, otio, &tio);
+
+ if (set_tty_settings (tty, &tio) < 0)
+ {
+ release_sigint ();
+ return;
+ }
+
+ if (_rl_enable_keypad)
+ _rl_control_keypad (1);
+
+ fflush (rl_outstream);
+ terminal_prepped = 1;
+ RL_SETSTATE(RL_STATE_TERMPREPPED);
+
+ release_sigint ();
+}
+
+/* Restore the terminal's normal settings and modes. */
+void
+rl_deprep_terminal ()
+{
+ int tty;
+
+ if (!terminal_prepped)
+ return;
+
+ /* Try to keep this function from being interrupted. */
+ block_sigint ();
+
+ tty = fileno (rl_instream);
+
+ if (_rl_enable_keypad)
+ _rl_control_keypad (0);
+
+ fflush (rl_outstream);
+
+ if (set_tty_settings (tty, &otio) < 0)
+ {
+ release_sigint ();
+ return;
+ }
+
+ terminal_prepped = 0;
+ RL_UNSETSTATE(RL_STATE_TERMPREPPED);
+
+ release_sigint ();
+}
+
+/* **************************************************************** */
+/* */
+/* Bogus Flow Control */
+/* */
+/* **************************************************************** */
+
+int
+rl_restart_output (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ int fildes = fileno (rl_outstream);
+#if defined (TIOCSTART)
+#if defined (apollo)
+ ioctl (&fildes, TIOCSTART, 0);
+#else
+ ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else /* !TIOCSTART */
+# if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ if (ksrflow)
+ {
+ ksrflow = 0;
+ tcflow (fildes, TCOON);
+ }
+# else /* !ksr1 */
+ tcflow (fildes, TCOON); /* Simulate a ^Q. */
+# endif /* !ksr1 */
+# else /* !TERMIOS_TTY_DRIVER */
+# if defined (TCXONC)
+ ioctl (fildes, TCXONC, TCOON);
+# endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTART */
+
+ return 0;
+}
+
+int
+rl_stop_output (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ int fildes = fileno (rl_instream);
+
+#if defined (TIOCSTOP)
+# if defined (apollo)
+ ioctl (&fildes, TIOCSTOP, 0);
+# else
+ ioctl (fildes, TIOCSTOP, 0);
+# endif /* apollo */
+#else /* !TIOCSTOP */
+# if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ ksrflow = 1;
+# endif /* ksr1 */
+ tcflow (fildes, TCOOFF);
+# else
+# if defined (TCXONC)
+ ioctl (fildes, TCXONC, TCOON);
+# endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTOP */
+
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Default Key Bindings */
+/* */
+/* **************************************************************** */
+
+/* Set the system's default editing characters to their readline equivalents
+ in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
+void
+rltty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+ TIOTYPE ttybuff;
+ int tty = fileno (rl_instream);
+
+#if defined (NEW_TTY_DRIVER)
+
+#define SET_SPECIAL(sc, func) \
+ do \
+ { \
+ int ic; \
+ ic = sc; \
+ if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \
+ kmap[(unsigned char)ic].function = func; \
+ } \
+ while (0)
+
+ if (get_tty_settings (tty, &ttybuff) == 0)
+ {
+ if (ttybuff.flags & SGTTY_SET)
+ {
+ SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+ SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+ }
+
+# if defined (TIOCGLTC)
+ if (ttybuff.flags & LTCHARS_SET)
+ {
+ SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+ SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
+ }
+# endif /* TIOCGLTC */
+ }
+
+#else /* !NEW_TTY_DRIVER */
+
+#define SET_SPECIAL(sc, func) \
+ do \
+ { \
+ unsigned char uc; \
+ uc = ttybuff.c_cc[sc]; \
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+ kmap[uc].function = func; \
+ } \
+ while (0)
+
+ if (get_tty_settings (tty, &ttybuff) == 0)
+ {
+ SET_SPECIAL (VERASE, rl_rubout);
+ SET_SPECIAL (VKILL, rl_unix_line_discard);
+
+# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+ SET_SPECIAL (VLNEXT, rl_quoted_insert);
+# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+ SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+# endif /* VWERASE && TERMIOS_TTY_DRIVER */
+ }
+#endif /* !NEW_TTY_DRIVER */
+}
+
+/* New public way to set the system default editing chars to their readline
+ equivalents. */
+void
+rl_tty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+ rltty_set_default_bindings (kmap);
+}
+
+#if defined (HANDLE_SIGNALS)
+
+#if defined (NEW_TTY_DRIVER)
+int
+_rl_disable_tty_signals ()
+{
+ return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+ return 0;
+}
+#else
+
+static TIOTYPE sigstty, nosigstty;
+static int tty_sigs_disabled = 0;
+
+int
+_rl_disable_tty_signals ()
+{
+ if (tty_sigs_disabled)
+ return 0;
+
+ if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
+ return -1;
+
+ nosigstty = sigstty;
+
+ nosigstty.c_lflag &= ~ISIG;
+ nosigstty.c_iflag &= ~IXON;
+
+ if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
+ return (_set_tty_settings (fileno (rl_instream), &sigstty));
+
+ tty_sigs_disabled = 1;
+ return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+ int r;
+
+ if (tty_sigs_disabled == 0)
+ return 0;
+
+ r = _set_tty_settings (fileno (rl_instream), &sigstty);
+
+ if (r == 0)
+ tty_sigs_disabled = 0;
+
+ return r;
+}
+#endif /* !NEW_TTY_DRIVER */
+
+#endif /* HANDLE_SIGNALS */
diff --git a/cmd-line-utils/readline/rltty.h b/cmd-line-utils/readline/rltty.h
new file mode 100644
index 00000000000..029a3fbc0e1
--- /dev/null
+++ b/cmd-line-utils/readline/rltty.h
@@ -0,0 +1,82 @@
+/* rltty.h - tty driver-related definitions used by some library files. */
+
+/* Copyright (C) 1995 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RLTTY_H_)
+#define _RLTTY_H_
+
+/* Posix systems use termios and the Posix signal functions. */
+#if defined (TERMIOS_TTY_DRIVER)
+# include <termios.h>
+#endif /* TERMIOS_TTY_DRIVER */
+
+/* System V machines use termio. */
+#if defined (TERMIO_TTY_DRIVER)
+# include <termio.h>
+# if !defined (TCOON)
+# define TCOON 1
+# endif
+#endif /* TERMIO_TTY_DRIVER */
+
+/* Other (BSD) machines use sgtty. */
+#if defined (NEW_TTY_DRIVER)
+# include <sgtty.h>
+#endif
+
+#include "rlwinsize.h"
+
+/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
+ it is not already defined. It is used both to determine if a
+ special character is disabled and to disable certain special
+ characters. Posix systems should set to 0, USG systems to -1. */
+#if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
+# if defined (_SVR4_VDISABLE)
+# define _POSIX_VDISABLE _SVR4_VDISABLE
+# else
+# if defined (_POSIX_VERSION)
+# define _POSIX_VDISABLE 0
+# else /* !_POSIX_VERSION */
+# define _POSIX_VDISABLE -1
+# endif /* !_POSIX_VERSION */
+# endif /* !_SVR4_DISABLE */
+#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
+
+typedef struct _rl_tty_chars {
+ char t_eof;
+ char t_eol;
+ char t_eol2;
+ char t_erase;
+ char t_werase;
+ char t_kill;
+ char t_reprint;
+ char t_intr;
+ char t_quit;
+ char t_susp;
+ char t_dsusp;
+ char t_start;
+ char t_stop;
+ char t_lnext;
+ char t_flush;
+ char t_status;
+} _RL_TTY_CHARS;
+
+#endif /* _RLTTY_H_ */
diff --git a/cmd-line-utils/readline/rltypedefs.h b/cmd-line-utils/readline/rltypedefs.h
new file mode 100644
index 00000000000..f3280e9fce0
--- /dev/null
+++ b/cmd-line-utils/readline/rltypedefs.h
@@ -0,0 +1,88 @@
+/* rltypedefs.h -- Type declarations for readline functions. */
+
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#ifndef _RL_TYPEDEFS_H_
+#define _RL_TYPEDEFS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Old-style */
+
+#if !defined (_FUNCTION_DEF)
+# define _FUNCTION_DEF
+
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+
+#endif /* _FUNCTION_DEF */
+
+/* New style. */
+
+#if !defined (_RL_FUNCTION_TYPEDEF)
+# define _RL_FUNCTION_TYPEDEF
+
+/* Bindable functions */
+typedef int rl_command_func_t PARAMS((int, int));
+
+/* Typedefs for the completion system */
+typedef char *rl_compentry_func_t PARAMS((const char *, int));
+typedef char **rl_completion_func_t PARAMS((const char *, int, int));
+
+typedef char *rl_quote_func_t PARAMS((char *, int, char *));
+typedef char *rl_dequote_func_t PARAMS((char *, int));
+
+typedef int rl_compignore_func_t PARAMS((char **));
+
+typedef void rl_compdisp_func_t PARAMS((char **, int, int));
+
+/* Type for input and pre-read hook functions like rl_event_hook */
+typedef int rl_hook_func_t PARAMS((void));
+
+/* Input function type */
+typedef int rl_getc_func_t PARAMS((FILE *));
+
+/* Generic function that takes a character buffer (which could be the readline
+ line buffer) and an index into it (which could be rl_point) and returns
+ an int. */
+typedef int rl_linebuf_func_t PARAMS((char *, int));
+
+/* `Generic' function pointer typedefs */
+typedef int rl_intfunc_t PARAMS((int));
+#define rl_ivoidfunc_t rl_hook_func_t
+typedef int rl_icpfunc_t PARAMS((char *));
+typedef int rl_icppfunc_t PARAMS((char **));
+
+typedef void rl_voidfunc_t PARAMS((void));
+typedef void rl_vintfunc_t PARAMS((int));
+typedef void rl_vcpfunc_t PARAMS((char *));
+typedef void rl_vcppfunc_t PARAMS((char **));
+#endif /* _RL_FUNCTION_TYPEDEF */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RL_TYPEDEFS_H_ */
diff --git a/cmd-line-utils/readline/rlwinsize.h b/cmd-line-utils/readline/rlwinsize.h
new file mode 100644
index 00000000000..7838154d023
--- /dev/null
+++ b/cmd-line-utils/readline/rlwinsize.h
@@ -0,0 +1,57 @@
+/* rlwinsize.h -- an attempt to isolate some of the system-specific defines
+ for `struct winsize' and TIOCGWINSZ. */
+
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RLWINSIZE_H_)
+#define _RLWINSIZE_H_
+
+#if defined (HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
+
+#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
+# include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
+
+#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
+# include <termios.h>
+#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
+
+/* Not in either of the standard places, look around. */
+#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
+# if defined (HAVE_SYS_STREAM_H)
+# include <sys/stream.h>
+# endif /* HAVE_SYS_STREAM_H */
+# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
+# include <sys/ptem.h>
+# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
+# endif /* HAVE_SYS_PTEM_H */
+# if defined (HAVE_SYS_PTE_H) /* ??? */
+# include <sys/pte.h>
+# endif /* HAVE_SYS_PTE_H */
+#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
+
+#endif /* _RL_WINSIZE_H */
+
diff --git a/cmd-line-utils/readline/search.c b/cmd-line-utils/readline/search.c
new file mode 100644
index 00000000000..ac47596a3f8
--- /dev/null
+++ b/cmd-line-utils/readline/search.c
@@ -0,0 +1,465 @@
+/* search.c - code for non-incremental searching in emacs and vi modes. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+ This file is part of the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif
+
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#ifdef abs
+# undef abs
+#endif
+#define abs(x) (((x) >= 0) ? (x) : -(x))
+
+extern HIST_ENTRY *_rl_saved_line_for_history;
+
+/* Functions imported from the rest of the library. */
+extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
+
+static char *noninc_search_string = (char *) NULL;
+static int noninc_history_pos;
+
+static char *prev_line_found = (char *) NULL;
+
+static int rl_history_search_len;
+static int rl_history_search_pos;
+static char *history_search_string;
+static int history_string_size;
+
+static void make_history_line_current PARAMS((HIST_ENTRY *));
+static int noninc_search_from_pos PARAMS((char *, int, int));
+static void noninc_dosearch PARAMS((char *, int));
+static void noninc_search PARAMS((int, int));
+static int rl_history_search_internal PARAMS((int, int));
+static void rl_history_search_reinit PARAMS((void));
+
+/* Make the data from the history entry ENTRY be the contents of the
+ current line. This doesn't do anything with rl_point; the caller
+ must set it. */
+static void
+make_history_line_current (entry)
+ HIST_ENTRY *entry;
+{
+ rl_replace_line (entry->line, 0);
+ rl_undo_list = (UNDO_LIST *)entry->data;
+
+ if (_rl_saved_line_for_history)
+ _rl_free_history_entry (_rl_saved_line_for_history);
+ _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Search the history list for STRING starting at absolute history position
+ POS. If STRING begins with `^', the search must match STRING at the
+ beginning of a history line, otherwise a full substring match is performed
+ for STRING. DIR < 0 means to search backwards through the history list,
+ DIR >= 0 means to search forward. */
+static int
+noninc_search_from_pos (string, pos, dir)
+ char *string;
+ int pos, dir;
+{
+ int ret, old;
+
+ if (pos < 0)
+ return -1;
+
+ old = where_history ();
+ if (history_set_pos (pos) == 0)
+ return -1;
+
+ RL_SETSTATE(RL_STATE_SEARCH);
+ if (*string == '^')
+ ret = history_search_prefix (string + 1, dir);
+ else
+ ret = history_search (string, dir);
+ RL_UNSETSTATE(RL_STATE_SEARCH);
+
+ if (ret != -1)
+ ret = where_history ();
+
+ history_set_pos (old);
+ return (ret);
+}
+
+/* Search for a line in the history containing STRING. If DIR is < 0, the
+ search is backwards through previous entries, else through subsequent
+ entries. */
+static void
+noninc_dosearch (string, dir)
+ char *string;
+ int dir;
+{
+ int oldpos, pos;
+ HIST_ENTRY *entry;
+
+ if (string == 0 || *string == '\0' || noninc_history_pos < 0)
+ {
+ rl_ding ();
+ return;
+ }
+
+ pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
+ if (pos == -1)
+ {
+ /* Search failed, current history position unchanged. */
+ rl_maybe_unsave_line ();
+ rl_clear_message ();
+ rl_point = 0;
+ rl_ding ();
+ return;
+ }
+
+ noninc_history_pos = pos;
+
+ oldpos = where_history ();
+ history_set_pos (noninc_history_pos);
+ entry = current_history ();
+#if defined (VI_MODE)
+ if (rl_editing_mode != vi_mode)
+#endif
+ history_set_pos (oldpos);
+
+ make_history_line_current (entry);
+
+ rl_point = 0;
+ rl_mark = rl_end;
+
+ rl_clear_message ();
+}
+
+/* Search non-interactively through the history list. DIR < 0 means to
+ search backwards through the history of previous commands; otherwise
+ the search is for commands subsequent to the current position in the
+ history list. PCHAR is the character to use for prompting when reading
+ the search string; if not specified (0), it defaults to `:'. */
+static void
+noninc_search (dir, pchar)
+ int dir;
+ int pchar;
+{
+ int saved_point, saved_mark, c;
+ char *p;
+#if defined (HANDLE_MULTIBYTE)
+ char mb[MB_LEN_MAX];
+#endif
+
+ rl_maybe_save_line ();
+ saved_point = rl_point;
+ saved_mark = rl_mark;
+
+ /* Use the line buffer to read the search string. */
+ rl_line_buffer[0] = 0;
+ rl_end = rl_point = 0;
+
+ p = _rl_make_prompt_for_search (pchar ? pchar : ':');
+ rl_message (p, 0, 0);
+ free (p);
+
+#define SEARCH_RETURN rl_restore_prompt (); RL_UNSETSTATE(RL_STATE_NSEARCH); return
+
+ RL_SETSTATE(RL_STATE_NSEARCH);
+ /* Read the search string. */
+ while (1)
+ {
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ c = _rl_read_mbstring (c, mb, MB_LEN_MAX);
+#endif
+
+ if (c == 0)
+ break;
+
+ switch (c)
+ {
+ case CTRL('H'):
+ case RUBOUT:
+ if (rl_point == 0)
+ {
+ rl_maybe_unsave_line ();
+ rl_clear_message ();
+ rl_point = saved_point;
+ rl_mark = saved_mark;
+ SEARCH_RETURN;
+ }
+ _rl_rubout_char (1, c);
+ break;
+
+ case CTRL('W'):
+ rl_unix_word_rubout (1, c);
+ break;
+
+ case CTRL('U'):
+ rl_unix_line_discard (1, c);
+ break;
+
+ case RETURN:
+ case NEWLINE:
+ goto dosearch;
+ /* NOTREACHED */
+ break;
+
+ case CTRL('C'):
+ case CTRL('G'):
+ rl_maybe_unsave_line ();
+ rl_clear_message ();
+ rl_point = saved_point;
+ rl_mark = saved_mark;
+ rl_ding ();
+ SEARCH_RETURN;
+
+ default:
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_insert_text (mb);
+ else
+#endif
+ _rl_insert_char (1, c);
+ break;
+ }
+ (*rl_redisplay_function) ();
+ }
+
+ dosearch:
+ rl_mark = saved_mark;
+
+ /* If rl_point == 0, we want to re-use the previous search string and
+ start from the saved history position. If there's no previous search
+ string, punt. */
+ if (rl_point == 0)
+ {
+ if (!noninc_search_string)
+ {
+ rl_ding ();
+ SEARCH_RETURN;
+ }
+ }
+ else
+ {
+ /* We want to start the search from the current history position. */
+ noninc_history_pos = where_history ();
+ FREE (noninc_search_string);
+ noninc_search_string = savestring (rl_line_buffer);
+ }
+
+ rl_restore_prompt ();
+ noninc_dosearch (noninc_search_string, dir);
+ RL_UNSETSTATE(RL_STATE_NSEARCH);
+}
+
+/* Search forward through the history list for a string. If the vi-mode
+ code calls this, KEY will be `?'. */
+int
+rl_noninc_forward_search (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ noninc_search (1, (key == '?') ? '?' : 0);
+ return 0;
+}
+
+/* Reverse search the history list for a string. If the vi-mode code
+ calls this, KEY will be `/'. */
+int
+rl_noninc_reverse_search (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ noninc_search (-1, (key == '/') ? '/' : 0);
+ return 0;
+}
+
+/* Search forward through the history list for the last string searched
+ for. If there is no saved search string, abort. */
+int
+rl_noninc_forward_search_again (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (!noninc_search_string)
+ {
+ rl_ding ();
+ return (-1);
+ }
+ noninc_dosearch (noninc_search_string, 1);
+ return 0;
+}
+
+/* Reverse search in the history list for the last string searched
+ for. If there is no saved search string, abort. */
+int
+rl_noninc_reverse_search_again (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (!noninc_search_string)
+ {
+ rl_ding ();
+ return (-1);
+ }
+ noninc_dosearch (noninc_search_string, -1);
+ return 0;
+}
+
+static int
+rl_history_search_internal (count, dir)
+ int count, dir;
+{
+ HIST_ENTRY *temp;
+ int ret, oldpos;
+
+ rl_maybe_save_line ();
+ temp = (HIST_ENTRY *)NULL;
+
+ /* Search COUNT times through the history for a line whose prefix
+ matches history_search_string. When this loop finishes, TEMP,
+ if non-null, is the history line to copy into the line buffer. */
+ while (count)
+ {
+ ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
+ if (ret == -1)
+ break;
+
+ /* Get the history entry we found. */
+ rl_history_search_pos = ret;
+ oldpos = where_history ();
+ history_set_pos (rl_history_search_pos);
+ temp = current_history ();
+ history_set_pos (oldpos);
+
+ /* Don't find multiple instances of the same line. */
+ if (prev_line_found && STREQ (prev_line_found, temp->line))
+ continue;
+ prev_line_found = temp->line;
+ count--;
+ }
+
+ /* If we didn't find anything at all, return. */
+ if (temp == 0)
+ {
+ rl_maybe_unsave_line ();
+ rl_ding ();
+ /* If you don't want the saved history line (last match) to show up
+ in the line buffer after the search fails, change the #if 0 to
+ #if 1 */
+#if 0
+ if (rl_point > rl_history_search_len)
+ {
+ rl_point = rl_end = rl_history_search_len;
+ rl_line_buffer[rl_end] = '\0';
+ rl_mark = 0;
+ }
+#else
+ rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
+ rl_mark = rl_end;
+#endif
+ return 1;
+ }
+
+ /* Copy the line we found into the current line buffer. */
+ make_history_line_current (temp);
+
+ rl_point = rl_history_search_len;
+ rl_mark = rl_end;
+
+ return 0;
+}
+
+static void
+rl_history_search_reinit ()
+{
+ rl_history_search_pos = where_history ();
+ rl_history_search_len = rl_point;
+ prev_line_found = (char *)NULL;
+ if (rl_point)
+ {
+ if (rl_history_search_len >= history_string_size - 2)
+ {
+ history_string_size = rl_history_search_len + 2;
+ history_search_string = (char *)xrealloc (history_search_string, history_string_size);
+ }
+ history_search_string[0] = '^';
+ strncpy (history_search_string + 1, rl_line_buffer, rl_point);
+ history_search_string[rl_point + 1] = '\0';
+ }
+ _rl_free_saved_history_line ();
+}
+
+/* Search forward in the history for the string of characters
+ from the start of the line to rl_point. This is a non-incremental
+ search. */
+int
+rl_history_search_forward (count, ignore)
+ int count, ignore;
+{
+ if (count == 0)
+ return (0);
+
+ if (rl_last_func != rl_history_search_forward &&
+ rl_last_func != rl_history_search_backward)
+ rl_history_search_reinit ();
+
+ if (rl_history_search_len == 0)
+ return (rl_get_next_history (count, ignore));
+ return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
+}
+
+/* Search backward through the history for the string of characters
+ from the start of the line to rl_point. This is a non-incremental
+ search. */
+int
+rl_history_search_backward (count, ignore)
+ int count, ignore;
+{
+ if (count == 0)
+ return (0);
+
+ if (rl_last_func != rl_history_search_forward &&
+ rl_last_func != rl_history_search_backward)
+ rl_history_search_reinit ();
+
+ if (rl_history_search_len == 0)
+ return (rl_get_previous_history (count, ignore));
+ return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
+}
diff --git a/cmd-line-utils/readline/shell.c b/cmd-line-utils/readline/shell.c
new file mode 100644
index 00000000000..ad27cc14884
--- /dev/null
+++ b/cmd-line-utils/readline/shell.c
@@ -0,0 +1,196 @@
+/* shell.c -- readline utility functions that are normally provided by
+ bash when readline is linked as part of the shell. */
+
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (HAVE_LIMITS_H)
+# include <limits.h>
+#endif
+
+#include <fcntl.h>
+#include <pwd.h>
+
+#include <stdio.h>
+
+#include "rlstdc.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#if !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid PARAMS((uid_t));
+#endif /* !HAVE_GETPW_DECLS */
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+/* Nonzero if the integer type T is signed. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* Bound on length of the string representing an integer value of type T.
+ Subtract one for the sign bit if T is signed;
+ 302 / 1000 is log10 (2) rounded up;
+ add one for integer division truncation;
+ add one more for a minus sign if t is signed. */
+#define INT_STRLEN_BOUND(t) \
+ ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
+ + 1 + TYPE_SIGNED (t))
+
+/* All of these functions are resolved from bash if we are linking readline
+ as part of bash. */
+
+/* Does shell-like quoting using single quotes. */
+char *
+sh_single_quote (string)
+ char *string;
+{
+ register int c;
+ char *result, *r, *s;
+
+ result = (char *)xmalloc (3 + (4 * strlen (string)));
+ r = result;
+ *r++ = '\'';
+
+ for (s = string; s && (c = *s); s++)
+ {
+ *r++ = c;
+
+ if (c == '\'')
+ {
+ *r++ = '\\'; /* insert escaped single quote */
+ *r++ = '\'';
+ *r++ = '\''; /* start new quoted string */
+ }
+ }
+
+ *r++ = '\'';
+ *r = '\0';
+
+ return (result);
+}
+
+/* Set the environment variables LINES and COLUMNS to lines and cols,
+ respectively. */
+void
+sh_set_lines_and_columns (lines, cols)
+ int lines, cols;
+{
+ char *b;
+
+#if defined (HAVE_PUTENV)
+ b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);
+ sprintf (b, "LINES=%d", lines);
+ putenv (b);
+ b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1);
+ sprintf (b, "COLUMNS=%d", cols);
+ putenv (b);
+#else /* !HAVE_PUTENV */
+# if defined (HAVE_SETENV)
+ b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
+ sprintf (b, "%d", lines);
+ setenv ("LINES", b, 1);
+ b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
+ sprintf (b, "%d", cols);
+ setenv ("COLUMNS", b, 1);
+# endif /* HAVE_SETENV */
+#endif /* !HAVE_PUTENV */
+}
+
+char *
+sh_get_env_value (varname)
+ const char *varname;
+{
+ return ((char *)getenv (varname));
+}
+
+char *
+sh_get_home_dir ()
+{
+ char *home_dir;
+ struct passwd *entry;
+
+ home_dir = (char *)NULL;
+ entry = getpwuid (getuid ());
+ if (entry)
+ home_dir = entry->pw_dir;
+ return (home_dir);
+}
+
+#if !defined (O_NDELAY)
+# if defined (FNDELAY)
+# define O_NDELAY FNDELAY
+# endif
+#endif
+
+int
+sh_unset_nodelay_mode (fd)
+ int fd;
+{
+ int flags, bflags;
+
+ if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
+ return -1;
+
+ bflags = 0;
+
+#ifdef O_NONBLOCK
+ bflags |= O_NONBLOCK;
+#endif
+
+#ifdef O_NDELAY
+ bflags |= O_NDELAY;
+#endif
+
+ if (flags & bflags)
+ {
+ flags &= ~bflags;
+ return (fcntl (fd, F_SETFL, flags));
+ }
+
+ return 0;
+}
diff --git a/cmd-line-utils/readline/signals.c b/cmd-line-utils/readline/signals.c
new file mode 100644
index 00000000000..0a1468b6b2a
--- /dev/null
+++ b/cmd-line-utils/readline/signals.c
@@ -0,0 +1,398 @@
+/* signals.c -- signal handling support for readline. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h> /* Just for NULL. Yuck. */
+#include <sys/types.h>
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+#if defined (HANDLE_SIGNALS)
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+
+#if !defined (RETSIGTYPE)
+# if defined (VOID_SIGHANDLER)
+# define RETSIGTYPE void
+# else
+# define RETSIGTYPE int
+# endif /* !VOID_SIGHANDLER */
+#endif /* !RETSIGTYPE */
+
+#if defined (VOID_SIGHANDLER)
+# define SIGHANDLER_RETURN return
+#else
+# define SIGHANDLER_RETURN return (0)
+#endif
+
+/* This typedef is equivalent to the one for Function; it allows us
+ to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
+typedef RETSIGTYPE SigHandler ();
+
+#if defined (HAVE_POSIX_SIGNALS)
+typedef struct sigaction sighandler_cxt;
+# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
+#else
+typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
+# define sigemptyset(m)
+#endif /* !HAVE_POSIX_SIGNALS */
+
+static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
+static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
+
+/* Exported variables for use by applications. */
+
+/* If non-zero, readline will install its own signal handlers for
+ SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
+int rl_catch_signals = 1;
+
+/* If non-zero, readline will install a signal handler for SIGWINCH. */
+#ifdef SIGWINCH
+int rl_catch_sigwinch = 1;
+#endif
+
+static int signals_set_flag;
+static int sigwinch_set_flag;
+
+/* **************************************************************** */
+/* */
+/* Signal Handling */
+/* */
+/* **************************************************************** */
+
+static sighandler_cxt old_int, old_term, old_alrm, old_quit;
+#if defined (SIGTSTP)
+static sighandler_cxt old_tstp, old_ttou, old_ttin;
+#endif
+#if defined (SIGWINCH)
+static sighandler_cxt old_winch;
+#endif
+
+/* Readline signal handler functions. */
+
+static RETSIGTYPE
+rl_signal_handler (sig)
+ int sig;
+{
+#if defined (HAVE_POSIX_SIGNALS)
+ sigset_t set;
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+ long omask;
+# else /* !HAVE_BSD_SIGNALS */
+ sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
+# endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ RL_SETSTATE(RL_STATE_SIGHANDLER);
+
+#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
+ /* Since the signal will not be blocked while we are in the signal
+ handler, ignore it until rl_clear_signals resets the catcher. */
+ if (sig == SIGINT || sig == SIGALRM)
+ rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
+#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
+
+ switch (sig)
+ {
+ case SIGINT:
+ rl_free_line_state ();
+ /* FALLTHROUGH */
+
+#if defined (SIGTSTP)
+ case SIGTSTP:
+ case SIGTTOU:
+ case SIGTTIN:
+#endif /* SIGTSTP */
+ case SIGALRM:
+ case SIGTERM:
+ case SIGQUIT:
+ rl_cleanup_after_signal ();
+
+#if defined (HAVE_POSIX_SIGNALS)
+ sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
+ sigdelset (&set, sig);
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+ omask = sigblock (0);
+# endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+#if defined (__EMX__)
+ signal (sig, SIG_ACK);
+#endif
+
+ kill (getpid (), sig);
+
+ /* Let the signal that we just sent through. */
+#if defined (HAVE_POSIX_SIGNALS)
+ sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+ sigsetmask (omask & ~(sigmask (sig)));
+# endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ rl_reset_after_signal ();
+ }
+
+ RL_UNSETSTATE(RL_STATE_SIGHANDLER);
+ SIGHANDLER_RETURN;
+}
+
+#if defined (SIGWINCH)
+static RETSIGTYPE
+rl_sigwinch_handler (sig)
+ int sig;
+{
+ SigHandler *oh;
+
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+ sighandler_cxt dummy_winch;
+
+ /* We don't want to change old_winch -- it holds the state of SIGWINCH
+ disposition set by the calling application. We need this state
+ because we call the application's SIGWINCH handler after updating
+ our own idea of the screen size. */
+ rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
+#endif
+
+ RL_SETSTATE(RL_STATE_SIGHANDLER);
+ rl_resize_terminal ();
+
+ /* If another sigwinch handler has been installed, call it. */
+ oh = (SigHandler *)old_winch.sa_handler;
+ if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
+ (*oh) (sig);
+
+ RL_UNSETSTATE(RL_STATE_SIGHANDLER);
+ SIGHANDLER_RETURN;
+}
+#endif /* SIGWINCH */
+
+/* Functions to manage signal handling. */
+
+#if !defined (HAVE_POSIX_SIGNALS)
+static int
+rl_sigaction (sig, nh, oh)
+ int sig;
+ sighandler_cxt *nh, *oh;
+{
+ oh->sa_handler = signal (sig, nh->sa_handler);
+ return 0;
+}
+#endif /* !HAVE_POSIX_SIGNALS */
+
+/* Set up a readline-specific signal handler, saving the old signal
+ information in OHANDLER. Return the old signal handler, like
+ signal(). */
+static SigHandler *
+rl_set_sighandler (sig, handler, ohandler)
+ int sig;
+ SigHandler *handler;
+ sighandler_cxt *ohandler;
+{
+ sighandler_cxt old_handler;
+#if defined (HAVE_POSIX_SIGNALS)
+ struct sigaction act;
+
+ act.sa_handler = handler;
+ act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */
+ sigemptyset (&act.sa_mask);
+ sigemptyset (&ohandler->sa_mask);
+ sigaction (sig, &act, &old_handler);
+#else
+ old_handler.sa_handler = (SigHandler *)signal (sig, handler);
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ /* XXX -- assume we have memcpy */
+ /* If rl_set_signals is called twice in a row, don't set the old handler to
+ rl_signal_handler, because that would cause infinite recursion. */
+ if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
+ memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
+
+ return (ohandler->sa_handler);
+}
+
+static void
+rl_maybe_set_sighandler (sig, handler, ohandler)
+ int sig;
+ SigHandler *handler;
+ sighandler_cxt *ohandler;
+{
+ sighandler_cxt dummy;
+ SigHandler *oh;
+
+ sigemptyset (&dummy.sa_mask);
+ oh = rl_set_sighandler (sig, handler, ohandler);
+ if (oh == (SigHandler *)SIG_IGN)
+ rl_sigaction (sig, ohandler, &dummy);
+}
+
+int
+rl_set_signals ()
+{
+ sighandler_cxt dummy;
+ SigHandler *oh;
+
+ if (rl_catch_signals && signals_set_flag == 0)
+ {
+ rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
+ rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
+ rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
+
+ oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
+ if (oh == (SigHandler *)SIG_IGN)
+ rl_sigaction (SIGALRM, &old_alrm, &dummy);
+#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
+ /* If the application using readline has already installed a signal
+ handler with SA_RESTART, SIGALRM will cause reads to be restarted
+ automatically, so readline should just get out of the way. Since
+ we tested for SIG_IGN above, we can just test for SIG_DFL here. */
+ if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
+ rl_sigaction (SIGALRM, &old_alrm, &dummy);
+#endif /* HAVE_POSIX_SIGNALS */
+
+#if defined (SIGTSTP)
+ rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
+#endif /* SIGTSTP */
+
+#if defined (SIGTTOU)
+ rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
+#endif /* SIGTTOU */
+
+#if defined (SIGTTIN)
+ rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
+#endif /* SIGTTIN */
+
+ signals_set_flag = 1;
+ }
+
+#if defined (SIGWINCH)
+ if (rl_catch_sigwinch && sigwinch_set_flag == 0)
+ {
+ rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
+ sigwinch_set_flag = 1;
+ }
+#endif /* SIGWINCH */
+
+ return 0;
+}
+
+int
+rl_clear_signals ()
+{
+ sighandler_cxt dummy;
+
+ if (rl_catch_signals && signals_set_flag == 1)
+ {
+ sigemptyset (&dummy.sa_mask);
+
+ rl_sigaction (SIGINT, &old_int, &dummy);
+ rl_sigaction (SIGTERM, &old_term, &dummy);
+ rl_sigaction (SIGQUIT, &old_quit, &dummy);
+ rl_sigaction (SIGALRM, &old_alrm, &dummy);
+
+#if defined (SIGTSTP)
+ rl_sigaction (SIGTSTP, &old_tstp, &dummy);
+#endif /* SIGTSTP */
+
+#if defined (SIGTTOU)
+ rl_sigaction (SIGTTOU, &old_ttou, &dummy);
+#endif /* SIGTTOU */
+
+#if defined (SIGTTIN)
+ rl_sigaction (SIGTTIN, &old_ttin, &dummy);
+#endif /* SIGTTIN */
+
+ signals_set_flag = 0;
+ }
+
+#if defined (SIGWINCH)
+ if (rl_catch_sigwinch && sigwinch_set_flag == 1)
+ {
+ sigemptyset (&dummy.sa_mask);
+ rl_sigaction (SIGWINCH, &old_winch, &dummy);
+ sigwinch_set_flag = 0;
+ }
+#endif
+
+ return 0;
+}
+
+/* Clean up the terminal and readline state after catching a signal, before
+ resending it to the calling application. */
+void
+rl_cleanup_after_signal ()
+{
+ _rl_clean_up_for_exit ();
+ (*rl_deprep_term_function) ();
+ rl_clear_signals ();
+ rl_clear_pending_input ();
+}
+
+/* Reset the terminal and readline state after a signal handler returns. */
+void
+rl_reset_after_signal ()
+{
+ (*rl_prep_term_function) (_rl_meta_flag);
+ rl_set_signals ();
+}
+
+/* Free up the readline variable line state for the current line (undo list,
+ any partial history entry, any keyboard macros in progress, and any
+ numeric arguments in process) after catching a signal, before calling
+ rl_cleanup_after_signal(). */
+void
+rl_free_line_state ()
+{
+ register HIST_ENTRY *entry;
+
+ rl_free_undo_list ();
+
+ entry = current_history ();
+ if (entry)
+ entry->data = (char *)NULL;
+
+ _rl_kill_kbd_macro ();
+ rl_clear_message ();
+ _rl_init_argument ();
+}
+
+#endif /* HANDLE_SIGNALS */
diff --git a/cmd-line-utils/readline/tcap.h b/cmd-line-utils/readline/tcap.h
new file mode 100644
index 00000000000..58ab894d93e
--- /dev/null
+++ b/cmd-line-utils/readline/tcap.h
@@ -0,0 +1,60 @@
+/* tcap.h -- termcap library functions and variables. */
+
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RLTCAP_H_)
+#define _RLTCAP_H_
+
+#if defined (HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#if defined (HAVE_TERMCAP_H)
+# if defined (__linux__) && !defined (SPEED_T_IN_SYS_TYPES)
+# include "rltty.h"
+# endif
+# include <termcap.h>
+#else
+
+/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
+ Unfortunately, PC is a global variable used by the termcap library. */
+#ifdef PC
+# undef PC
+#endif
+
+extern char PC;
+extern char *UP, *BC;
+
+extern short ospeed;
+
+extern int tgetent ();
+extern int tgetflag ();
+extern int tgetnum ();
+extern char *tgetstr ();
+
+extern int tputs ();
+
+extern char *tgoto ();
+
+#endif /* HAVE_TERMCAP_H */
+
+#endif /* !_RLTCAP_H_ */
diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c
new file mode 100644
index 00000000000..397b10a1d46
--- /dev/null
+++ b/cmd-line-utils/readline/terminal.c
@@ -0,0 +1,663 @@
+/* terminal.c -- controlling the terminal with termcap. */
+
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include "posixstat.h"
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+# include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
+# include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
+
+#include "rltty.h"
+#include "tcap.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
+#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
+
+/* **************************************************************** */
+/* */
+/* Terminal and Termcap */
+/* */
+/* **************************************************************** */
+
+static char *term_buffer = (char *)NULL;
+static char *term_string_buffer = (char *)NULL;
+
+static int tcap_initialized;
+
+#if !defined (__linux__)
+# if defined (__EMX__) || defined (NEED_EXTERN_PC)
+extern
+# endif /* __EMX__ || NEED_EXTERN_PC */
+char PC;
+char *BC, *UP;
+#endif /* __linux__ */
+
+/* Some strings to control terminal actions. These are output by tputs (). */
+const char *_rl_term_clreol;
+const char *_rl_term_clrpag;
+const char *_rl_term_cr;
+const char *_rl_term_backspace;
+const char *_rl_term_goto;
+const char *_rl_term_pc;
+
+/* Non-zero if we determine that the terminal can do character insertion. */
+int _rl_terminal_can_insert = 0;
+
+/* How to insert characters. */
+const char *_rl_term_im;
+const char *_rl_term_ei;
+const char *_rl_term_ic;
+const char *_rl_term_ip;
+const char *_rl_term_IC;
+
+/* How to delete characters. */
+const char *_rl_term_dc;
+const char *_rl_term_DC;
+
+#if defined (HACK_TERMCAP_MOTION)
+char *_rl_term_forward_char;
+#endif /* HACK_TERMCAP_MOTION */
+
+/* How to go up a line. */
+const char *_rl_term_up;
+
+/* A visible bell; char if the terminal can be made to flash the screen. */
+static const char *_rl_visible_bell;
+
+/* Non-zero means the terminal can auto-wrap lines. */
+int _rl_term_autowrap;
+
+/* Non-zero means that this terminal has a meta key. */
+static int term_has_meta;
+
+/* The sequences to write to turn on and off the meta key, if this
+ terminal has one. */
+static const char *_rl_term_mm;
+static const char *_rl_term_mo;
+
+/* The key sequences output by the arrow keys, if this terminal has any. */
+static const char *_rl_term_ku;
+static const char *_rl_term_kd;
+static const char *_rl_term_kr;
+static const char *_rl_term_kl;
+
+/* How to initialize and reset the arrow keys, if this terminal has any. */
+static const char *_rl_term_ks;
+static const char *_rl_term_ke;
+
+/* The key sequences sent by the Home and End keys, if any. */
+static const char *_rl_term_kh;
+static const char *_rl_term_kH;
+static const char *_rl_term_at7; /* @7 */
+
+/* Insert key */
+static const char *_rl_term_kI;
+
+/* Cursor control */
+static const char *_rl_term_vs; /* very visible */
+static const char *_rl_term_ve; /* normal */
+
+static void bind_termcap_arrow_keys PARAMS((Keymap));
+
+/* Variables that hold the screen dimensions, used by the display code. */
+int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
+
+/* Non-zero means the user wants to enable the keypad. */
+int _rl_enable_keypad;
+
+/* Non-zero means the user wants to enable a meta key. */
+int _rl_enable_meta = 1;
+
+#if defined (__EMX__)
+static void
+_emx_get_screensize (swp, shp)
+ int *swp, *shp;
+{
+ int sz[2];
+
+ _scrsize (sz);
+
+ if (swp)
+ *swp = sz[0];
+ if (shp)
+ *shp = sz[1];
+}
+#endif
+
+/* Get readline's idea of the screen size. TTY is a file descriptor open
+ to the terminal. If IGNORE_ENV is true, we do not pay attention to the
+ values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
+ non-null serve to check whether or not we have initialized termcap. */
+void
+_rl_get_screen_size (tty, ignore_env)
+ int tty, ignore_env;
+{
+ char *ss;
+#if defined (TIOCGWINSZ)
+ struct winsize window_size;
+#endif /* TIOCGWINSZ */
+
+#if defined (TIOCGWINSZ)
+ if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
+ {
+ _rl_screenwidth = (int) window_size.ws_col;
+ _rl_screenheight = (int) window_size.ws_row;
+ }
+#endif /* TIOCGWINSZ */
+
+#if defined (__EMX__)
+ _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
+#endif
+
+ /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
+ is unset. */
+ if (_rl_screenwidth <= 0)
+ {
+ if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
+ _rl_screenwidth = atoi (ss);
+
+#if !defined (__DJGPP__)
+ if (_rl_screenwidth <= 0 && term_string_buffer)
+ _rl_screenwidth = tgetnum ("co");
+#endif
+ }
+
+ /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
+ is unset. */
+ if (_rl_screenheight <= 0)
+ {
+ if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
+ _rl_screenheight = atoi (ss);
+
+#if !defined (__DJGPP__)
+ if (_rl_screenheight <= 0 && term_string_buffer)
+ _rl_screenheight = tgetnum ("li");
+#endif
+ }
+
+ /* If all else fails, default to 80x24 terminal. */
+ if (_rl_screenwidth <= 1)
+ _rl_screenwidth = 80;
+
+ if (_rl_screenheight <= 0)
+ _rl_screenheight = 24;
+
+ /* If we're being compiled as part of bash, set the environment
+ variables $LINES and $COLUMNS to new values. Otherwise, just
+ do a pair of putenv () or setenv () calls. */
+ sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
+
+ if (_rl_term_autowrap == 0)
+ _rl_screenwidth--;
+
+ _rl_screenchars = _rl_screenwidth * _rl_screenheight;
+}
+
+void
+_rl_set_screen_size (rows, cols)
+ int rows, cols;
+{
+ if (rows == 0 || cols == 0)
+ return;
+
+ _rl_screenheight = rows;
+ _rl_screenwidth = cols;
+
+ if (_rl_term_autowrap == 0)
+ _rl_screenwidth--;
+
+ _rl_screenchars = _rl_screenwidth * _rl_screenheight;
+}
+
+void
+rl_set_screen_size (rows, cols)
+ int rows, cols;
+{
+ _rl_set_screen_size (rows, cols);
+}
+
+void
+rl_get_screen_size (rows, cols)
+ int *rows, *cols;
+{
+ if (rows)
+ *rows = _rl_screenheight;
+ if (cols)
+ *cols = _rl_screenwidth;
+}
+
+void
+rl_resize_terminal ()
+{
+ if (readline_echoing_p)
+ {
+ _rl_get_screen_size (fileno (rl_instream), 1);
+ if (CUSTOM_REDISPLAY_FUNC ())
+ rl_forced_update_display ();
+ else
+ _rl_redisplay_after_sigwinch ();
+ }
+}
+
+struct _tc_string {
+ const char *tc_var;
+ const char **tc_value;
+};
+
+/* This should be kept sorted, just in case we decide to change the
+ search algorithm to something smarter. */
+static struct _tc_string tc_strings[] =
+{
+ { "@7", &_rl_term_at7 },
+ { "DC", &_rl_term_DC },
+ { "IC", &_rl_term_IC },
+ { "ce", &_rl_term_clreol },
+ { "cl", &_rl_term_clrpag },
+ { "cr", &_rl_term_cr },
+ { "dc", &_rl_term_dc },
+ { "ei", &_rl_term_ei },
+ { "ic", &_rl_term_ic },
+ { "im", &_rl_term_im },
+ { "kH", &_rl_term_kH }, /* home down ?? */
+ { "kI", &_rl_term_kI }, /* insert */
+ { "kd", &_rl_term_kd },
+ { "ke", &_rl_term_ke }, /* end keypad mode */
+ { "kh", &_rl_term_kh }, /* home */
+ { "kl", &_rl_term_kl },
+ { "kr", &_rl_term_kr },
+ { "ks", &_rl_term_ks }, /* start keypad mode */
+ { "ku", &_rl_term_ku },
+ { "le", &_rl_term_backspace },
+ { "mm", &_rl_term_mm },
+ { "mo", &_rl_term_mo },
+#if defined (HACK_TERMCAP_MOTION)
+ { "nd", &_rl_term_forward_char },
+#endif
+ { "pc", &_rl_term_pc },
+ { "up", &_rl_term_up },
+ { "vb", &_rl_visible_bell },
+ { "vs", &_rl_term_vs },
+ { "ve", &_rl_term_ve },
+};
+
+#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
+
+/* Read the desired terminal capability strings into BP. The capabilities
+ are described in the TC_STRINGS table. */
+static void
+get_term_capabilities (bp)
+ char **bp;
+{
+#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
+ register unsigned int i;
+
+ for (i = 0; i < NUM_TC_STRINGS; i++)
+# ifdef __LCC__
+ *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
+# else
+ *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
+# endif
+#endif
+ tcap_initialized = 1;
+}
+
+int
+_rl_init_terminal_io (terminal_name)
+ const char *terminal_name;
+{
+ const char *term;
+ char *buffer;
+ int tty, tgetent_ret;
+
+ term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
+ _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
+ tty = rl_instream ? fileno (rl_instream) : 0;
+ _rl_screenwidth = _rl_screenheight = 0;
+
+ if (term == 0)
+ term = "dumb";
+
+ /* I've separated this out for later work on not calling tgetent at all
+ if the calling application has supplied a custom redisplay function,
+ (and possibly if the application has supplied a custom input function). */
+ if (CUSTOM_REDISPLAY_FUNC())
+ {
+ tgetent_ret = -1;
+ }
+ else
+ {
+ if (term_string_buffer == 0)
+ term_string_buffer = (char *)xmalloc(2032);
+
+ if (term_buffer == 0)
+ term_buffer = (char *)xmalloc(4080);
+
+ buffer = term_string_buffer;
+
+ tgetent_ret = tgetent (term_buffer, term);
+ }
+
+ if (tgetent_ret <= 0)
+ {
+ FREE (term_string_buffer);
+ FREE (term_buffer);
+ buffer = term_buffer = term_string_buffer = (char *)NULL;
+
+ _rl_term_autowrap = 0; /* used by _rl_get_screen_size */
+
+#if defined (__EMX__)
+ _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
+ _rl_screenwidth--;
+#else /* !__EMX__ */
+ _rl_get_screen_size (tty, 0);
+#endif /* !__EMX__ */
+
+ /* Defaults. */
+ if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
+ {
+ _rl_screenwidth = 79;
+ _rl_screenheight = 24;
+ }
+
+ /* Everything below here is used by the redisplay code (tputs). */
+ _rl_screenchars = _rl_screenwidth * _rl_screenheight;
+ _rl_term_cr = "\r";
+ _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
+ _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
+ _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
+ _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
+ _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
+ _rl_term_mm = _rl_term_mo = (char *)NULL;
+ _rl_term_ve = _rl_term_vs = (char *)NULL;
+#if defined (HACK_TERMCAP_MOTION)
+ term_forward_char = (char *)NULL;
+#endif
+ _rl_terminal_can_insert = term_has_meta = 0;
+
+ /* Reasonable defaults for tgoto(). Readline currently only uses
+ tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
+ change that later... */
+ PC = '\0';
+ BC = (char*)(_rl_term_backspace = "\b");
+ UP = (char*)_rl_term_up;
+
+ return 0;
+ }
+
+ get_term_capabilities (&buffer);
+
+ /* Set up the variables that the termcap library expects the application
+ to provide. */
+ PC = _rl_term_pc ? *_rl_term_pc : 0;
+ BC = (char*)_rl_term_backspace;
+ UP = (char*)_rl_term_up;
+
+ if (!_rl_term_cr)
+ _rl_term_cr = "\r";
+
+ _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
+
+ _rl_get_screen_size (tty, 0);
+
+ /* "An application program can assume that the terminal can do
+ character insertion if *any one of* the capabilities `IC',
+ `im', `ic' or `ip' is provided." But we can't do anything if
+ only `ip' is provided, so... */
+ _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
+
+ /* Check to see if this terminal has a meta key and clear the capability
+ variables if there is none. */
+ term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
+ if (!term_has_meta)
+ _rl_term_mm = _rl_term_mo = (char *)NULL;
+
+ /* Attempt to find and bind the arrow keys. Do not override already
+ bound keys in an overzealous attempt, however. */
+
+ bind_termcap_arrow_keys (emacs_standard_keymap);
+
+#if defined (VI_MODE)
+ bind_termcap_arrow_keys (vi_movement_keymap);
+ bind_termcap_arrow_keys (vi_insertion_keymap);
+#endif /* VI_MODE */
+
+ return 0;
+}
+
+/* Bind the arrow key sequences from the termcap description in MAP. */
+static void
+bind_termcap_arrow_keys (map)
+ Keymap map;
+{
+ Keymap xkeymap;
+
+ xkeymap = _rl_keymap;
+ _rl_keymap = map;
+
+ _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
+ _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
+ _rl_bind_if_unbound (_rl_term_kr, rl_forward);
+ _rl_bind_if_unbound (_rl_term_kl, rl_backward);
+
+ _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
+ _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
+
+ _rl_keymap = xkeymap;
+}
+
+const char *
+rl_get_termcap (cap)
+ const char *cap;
+{
+ register unsigned int i;
+
+ if (tcap_initialized == 0)
+ return ((char *)NULL);
+ for (i = 0; i < NUM_TC_STRINGS; i++)
+ {
+ if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
+ return *(tc_strings[i].tc_value);
+ }
+ return ((char *)NULL);
+}
+
+/* Re-initialize the terminal considering that the TERM/TERMCAP variable
+ has changed. */
+int
+rl_reset_terminal (terminal_name)
+ const char *terminal_name;
+{
+ _rl_init_terminal_io (terminal_name);
+ return 0;
+}
+
+/* A function for the use of tputs () */
+#ifdef _MINIX
+void
+_rl_output_character_function (c)
+ int c;
+{
+ putc (c, _rl_out_stream);
+}
+#else /* !_MINIX */
+int
+_rl_output_character_function (c)
+ int c;
+{
+ return putc (c, _rl_out_stream);
+}
+#endif /* !_MINIX */
+
+/* Write COUNT characters from STRING to the output stream. */
+void
+_rl_output_some_chars (string, count)
+ const char *string;
+ int count;
+{
+ fwrite (string, 1, count, _rl_out_stream);
+}
+
+/* Move the cursor back. */
+int
+_rl_backspace (count)
+ int count;
+{
+ register int i;
+
+ if (_rl_term_backspace)
+ for (i = 0; i < count; i++)
+ tputs (_rl_term_backspace, 1, _rl_output_character_function);
+ else
+ for (i = 0; i < count; i++)
+ putc ('\b', _rl_out_stream);
+ return 0;
+}
+
+/* Move to the start of the next line. */
+int
+rl_crlf ()
+{
+#if defined (NEW_TTY_DRIVER)
+ if (_rl_term_cr)
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif /* NEW_TTY_DRIVER */
+ putc ('\n', _rl_out_stream);
+ return 0;
+}
+
+/* Ring the terminal bell. */
+int
+rl_ding ()
+{
+ if (readline_echoing_p)
+ {
+ switch (_rl_bell_preference)
+ {
+ case NO_BELL:
+ default:
+ break;
+ case VISIBLE_BELL:
+ if (_rl_visible_bell)
+ {
+ tputs (_rl_visible_bell, 1, _rl_output_character_function);
+ break;
+ }
+ /* FALLTHROUGH */
+ case AUDIBLE_BELL:
+ fprintf (stderr, "\007");
+ fflush (stderr);
+ break;
+ }
+ return (0);
+ }
+ return (-1);
+}
+
+/* **************************************************************** */
+/* */
+/* Controlling the Meta Key and Keypad */
+/* */
+/* **************************************************************** */
+
+void
+_rl_enable_meta_key ()
+{
+#if !defined (__DJGPP__)
+ if (term_has_meta && _rl_term_mm)
+ tputs (_rl_term_mm, 1, _rl_output_character_function);
+#endif
+}
+
+void
+_rl_control_keypad (on)
+ int on;
+{
+#if !defined (__DJGPP__)
+ if (on && _rl_term_ks)
+ tputs (_rl_term_ks, 1, _rl_output_character_function);
+ else if (!on && _rl_term_ke)
+ tputs (_rl_term_ke, 1, _rl_output_character_function);
+#endif
+}
+
+/* **************************************************************** */
+/* */
+/* Controlling the Cursor */
+/* */
+/* **************************************************************** */
+
+/* Set the cursor appropriately depending on IM, which is one of the
+ insert modes (insert or overwrite). Insert mode gets the normal
+ cursor. Overwrite mode gets a very visible cursor. Only does
+ anything if we have both capabilities. */
+void
+_rl_set_cursor (im, force)
+ int im, force;
+{
+ if (_rl_term_ve && _rl_term_vs)
+ {
+ if (force || im != rl_insert_mode)
+ {
+ if (im == RL_IM_OVERWRITE)
+ tputs (_rl_term_vs, 1, _rl_output_character_function);
+ else
+ tputs (_rl_term_ve, 1, _rl_output_character_function);
+ }
+ }
+}
diff --git a/cmd-line-utils/readline/text.c b/cmd-line-utils/readline/text.c
new file mode 100644
index 00000000000..81a468fdbda
--- /dev/null
+++ b/cmd-line-utils/readline/text.c
@@ -0,0 +1,1540 @@
+/* text.c -- text handling commands for readline. */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+# include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+# define INCL_DOSPROCESS
+# include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+/* **************************************************************** */
+/* */
+/* Insert and Delete */
+/* */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point. This is the only
+ way that you should do insertion. _rl_insert_char () calls this
+ function. Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+ const char *string;
+{
+ register int i, l;
+
+ l = (string && *string) ? strlen (string) : 0;
+ if (l == 0)
+ return 0;
+
+ if (rl_end + l >= rl_line_buffer_len)
+ rl_extend_line_buffer (rl_end + l);
+
+ for (i = rl_end; i >= rl_point; i--)
+ rl_line_buffer[i + l] = rl_line_buffer[i];
+ strncpy (rl_line_buffer + rl_point, string, l);
+
+ /* Remember how to undo this if we aren't undoing something. */
+ if (_rl_doing_an_undo == 0)
+ {
+ /* If possible and desirable, concatenate the undos. */
+ if ((l == 1) &&
+ rl_undo_list &&
+ (rl_undo_list->what == UNDO_INSERT) &&
+ (rl_undo_list->end == rl_point) &&
+ (rl_undo_list->end - rl_undo_list->start < 20))
+ rl_undo_list->end++;
+ else
+ rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+ }
+ rl_point += l;
+ rl_end += l;
+ rl_line_buffer[rl_end] = '\0';
+ return l;
+}
+
+/* Delete the string between FROM and TO. FROM is inclusive, TO is not.
+ Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+ int from, to;
+{
+ register char *text;
+ register int diff, i;
+
+ /* Fix it if the caller is confused. */
+ if (from > to)
+ SWAP (from, to);
+
+ /* fix boundaries */
+ if (to > rl_end)
+ {
+ to = rl_end;
+ if (from > to)
+ from = to;
+ }
+ if (from < 0)
+ from = 0;
+
+ text = rl_copy_text (from, to);
+
+ /* Some versions of strncpy() can't handle overlapping arguments. */
+ diff = to - from;
+ for (i = from; i < rl_end - diff; i++)
+ rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+ /* Remember how to undo this delete. */
+ if (_rl_doing_an_undo == 0)
+ rl_add_undo (UNDO_DELETE, from, to, text);
+ else
+ free (text);
+
+ rl_end -= diff;
+ rl_line_buffer[rl_end] = '\0';
+ return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+ text. If FIX_MARK_TOO is non-zero, the mark is forced within line
+ boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+ do { \
+ if (x > rl_end) \
+ x = rl_end; \
+ else if (x < 0) \
+ x = 0; \
+ } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+ int fix_mark_too;
+{
+ _RL_FIX_POINT (rl_point);
+ if (fix_mark_too)
+ _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+int
+_rl_replace_text (text, start, end)
+ const char *text;
+ int start, end;
+{
+ int n;
+
+ rl_begin_undo_group ();
+ rl_delete_text (start, end + 1);
+ rl_point = start;
+ n = rl_insert_text (text);
+ rl_end_undo_group ();
+
+ return n;
+}
+
+/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
+ non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+ const char *text;
+ int clear_undo;
+{
+ int len;
+
+ len = strlen (text);
+ if (len >= rl_line_buffer_len)
+ rl_extend_line_buffer (len);
+ strcpy (rl_line_buffer, text);
+ rl_end = len;
+
+ if (clear_undo)
+ rl_free_undo_list ();
+
+ _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/* */
+/* Readline character functions */
+/* */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine. No hair
+ is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+ rl_end is the place in the string that we would place '\0';
+ i.e., it is always safe to place '\0' there.
+
+ rl_point is the place in the string where the cursor is. Sometimes
+ this is the same as rl_end.
+
+ Any command that is called interactively receives two arguments.
+ The first is a count: the numeric arg pased to this command.
+ The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/* */
+/* Movement Commands */
+/* */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+ use said functions in other functions which do not do optimizing display.
+ I.e., you will have to update the data base for rl_redisplay, and you
+ might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_backward_byte (-count, key));
+
+ if (count > 0)
+ {
+ int end = rl_point + count;
+#if defined (VI_MODE)
+ int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
+#else
+ int lend = rl_end;
+#endif
+
+ if (end > lend)
+ {
+ rl_point = lend;
+ rl_ding ();
+ }
+ else
+ rl_point = end;
+ }
+
+ if (rl_end < 0)
+ rl_end = 0;
+
+ return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+ int count, key;
+{
+ int point;
+
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ return (rl_forward_byte (count, key));
+
+ if (count < 0)
+ return (rl_backward_char (-count, key));
+
+ if (count > 0)
+ {
+ point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+ if (rl_end <= point && rl_editing_mode == vi_mode)
+ point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+ if (rl_point == point)
+ rl_ding ();
+
+ rl_point = point;
+
+ if (rl_end < 0)
+ rl_end = 0;
+ }
+
+ return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+ int count, key;
+{
+ return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+ int count, key;
+{
+ return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_forward_byte (-count, key));
+
+ if (count > 0)
+ {
+ if (rl_point < count)
+ {
+ rl_point = 0;
+ rl_ding ();
+ }
+ else
+ rl_point -= count;
+ }
+
+ if (rl_point < 0)
+ rl_point = 0;
+
+ return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+ int count, key;
+{
+ int point;
+
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ return (rl_backward_byte (count, key));
+
+ if (count < 0)
+ return (rl_forward_char (-count, key));
+
+ if (count > 0)
+ {
+ point = rl_point;
+
+ while (count > 0 && point > 0)
+ {
+ point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+ count--;
+ }
+ if (count > 0)
+ {
+ rl_point = 0;
+ rl_ding ();
+ }
+ else
+ rl_point = point;
+ }
+
+ return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+ int count, key;
+{
+ return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+ int count, key;
+{
+ return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ rl_point = 0;
+ return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ rl_point = rl_end;
+ return 0;
+}
+
+/* XXX - these might need changes for multibyte characters */
+/* Move forward a word. We do what Emacs does. */
+int
+rl_forward_word (count, key)
+ int count, key;
+{
+ int c;
+
+ if (count < 0)
+ return (rl_backward_word (-count, key));
+
+ while (count)
+ {
+ if (rl_point == rl_end)
+ return 0;
+
+ /* If we are not in a word, move forward until we are in one.
+ Then, move forward until we hit a non-alphabetic character. */
+ c = rl_line_buffer[rl_point];
+ if (rl_alphabetic (c) == 0)
+ {
+ while (++rl_point < rl_end)
+ {
+ c = rl_line_buffer[rl_point];
+ if (rl_alphabetic (c))
+ break;
+ }
+ }
+
+ if (rl_point == rl_end)
+ return 0;
+
+ while (++rl_point < rl_end)
+ {
+ c = rl_line_buffer[rl_point];
+ if (rl_alphabetic (c) == 0)
+ break;
+ }
+ --count;
+ }
+
+ return 0;
+}
+
+/* Move backward a word. We do what Emacs does. */
+int
+rl_backward_word (count, key)
+ int count, key;
+{
+ int c;
+
+ if (count < 0)
+ return (rl_forward_word (-count, key));
+
+ while (count)
+ {
+ if (!rl_point)
+ return 0;
+
+ /* Like rl_forward_word (), except that we look at the characters
+ just before point. */
+
+ c = rl_line_buffer[rl_point - 1];
+ if (rl_alphabetic (c) == 0)
+ {
+ while (--rl_point)
+ {
+ c = rl_line_buffer[rl_point - 1];
+ if (rl_alphabetic (c))
+ break;
+ }
+ }
+
+ while (rl_point)
+ {
+ c = rl_line_buffer[rl_point - 1];
+ if (rl_alphabetic (c) == 0)
+ break;
+ else
+ --rl_point;
+ }
+
+ --count;
+ }
+
+ return 0;
+}
+
+/* Clear the current line. Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+ int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
+{
+ int curr_line;
+
+ curr_line = _rl_current_display_line ();
+
+ _rl_move_vert (curr_line);
+ _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */
+
+ _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+ the prompt and the current input line. Given a numeric arg, redraw only
+ the current line. */
+int
+rl_clear_screen (count, key)
+ int count, key;
+{
+ if (rl_explicit_arg)
+ {
+ rl_refresh_line (count, key);
+ return 0;
+ }
+
+ _rl_clear_screen (); /* calls termcap function to clear screen */
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+ int count, c __attribute__((unused));
+{
+ int ch;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ ch = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ switch (_rl_to_upper (ch))
+ {
+ case 'A':
+ rl_get_previous_history (count, ch);
+ break;
+
+ case 'B':
+ rl_get_next_history (count, ch);
+ break;
+
+ case 'C':
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_forward_char (count, ch);
+ else
+ rl_forward_byte (count, ch);
+ break;
+
+ case 'D':
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_backward_char (count, ch);
+ else
+ rl_backward_byte (count, ch);
+ break;
+
+ default:
+ rl_ding ();
+ }
+
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Text commands */
+/* */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+ If C introduces a multibyte sequence, we read the whole sequence and
+ then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+ int count, c;
+{
+ register int i;
+ char *string;
+#ifdef HANDLE_MULTIBYTE
+ int string_size;
+ char incoming[MB_LEN_MAX + 1];
+ int incoming_length = 0;
+ mbstate_t ps_back;
+ static int stored_count = 0;
+#endif
+
+ if (count <= 0)
+ return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+ incoming[0] = c;
+ incoming[1] = '\0';
+ incoming_length = 1;
+ }
+ else
+ {
+ wchar_t wc;
+ size_t ret;
+
+ if (stored_count <= 0)
+ stored_count = count;
+ else
+ count = stored_count;
+
+ ps_back = ps;
+ pending_bytes[pending_bytes_length++] = c;
+ ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+ if (ret == (size_t)-2)
+ {
+ /* Bytes too short to compose character, try to wait for next byte.
+ Restore the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ ps = ps_back;
+ return 1;
+ }
+ else if (ret == (size_t)-1)
+ {
+ /* Invalid byte sequence for the current locale. Treat first byte
+ as a single character. */
+ incoming[0] = pending_bytes[0];
+ incoming[1] = '\0';
+ incoming_length = 1;
+ pending_bytes_length--;
+ memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+ /* Clear the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (ret == (size_t)0)
+ {
+ incoming[0] = '\0';
+ incoming_length = 0;
+ pending_bytes_length--;
+ /* Clear the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else
+ {
+ /* We successfully read a single multibyte character. */
+ memcpy (incoming, pending_bytes, pending_bytes_length);
+ incoming[pending_bytes_length] = '\0';
+ incoming_length = pending_bytes_length;
+ pending_bytes_length = 0;
+ }
+ }
+#endif /* HANDLE_MULTIBYTE */
+
+ /* If we can optimize, then do it. But don't let people crash
+ readline because of extra large arguments. */
+ if (count > 1 && count <= 1024)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ string_size = count * incoming_length;
+ string = (char *)xmalloc (1 + string_size);
+
+ i = 0;
+ while (i < string_size)
+ {
+ strncpy (string + i, incoming, incoming_length);
+ i += incoming_length;
+ }
+ incoming_length = 0;
+ stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+ string = (char *)xmalloc (1 + count);
+
+ for (i = 0; i < count; i++)
+ string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+ string[i] = '\0';
+ rl_insert_text (string);
+ free (string);
+
+ return 0;
+ }
+
+ if (count > 1024)
+ {
+ int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+ string_size = incoming_length * 1024;
+ string = (char *)xmalloc (1 + string_size);
+
+ i = 0;
+ while (i < string_size)
+ {
+ strncpy (string + i, incoming, incoming_length);
+ i += incoming_length;
+ }
+
+ while (count)
+ {
+ decreaser = (count > 1024) ? 1024 : count;
+ string[decreaser*incoming_length] = '\0';
+ rl_insert_text (string);
+ count -= decreaser;
+ }
+
+ free (string);
+ incoming_length = 0;
+ stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+ char str[1024+1];
+
+ for (i = 0; i < 1024; i++)
+ str[i] = c;
+
+ while (count)
+ {
+ decreaser = (count > 1024 ? 1024 : count);
+ str[decreaser] = '\0';
+ rl_insert_text (str);
+ count -= decreaser;
+ }
+#endif /* !HANDLE_MULTIBYTE */
+
+ return 0;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+#endif
+ /* We are inserting a single character.
+ If there is pending input, then make a string of all of the
+ pending characters that are bound to rl_insert, and insert
+ them all. */
+ if (_rl_any_typein ())
+ _rl_insert_typein (c);
+ else
+ {
+ /* Inserting a single character. */
+ char str[2];
+
+ str[1] = '\0';
+ str[0] = c;
+ rl_insert_text (str);
+ }
+#if defined (HANDLE_MULTIBYTE)
+ }
+ else
+ {
+ rl_insert_text (incoming);
+ stored_count = 0;
+ }
+#endif
+
+ return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+ If C introduces a multibyte character sequence, read the entire sequence
+ before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+ int count, c;
+{
+ int i;
+#if defined (HANDLE_MULTIBYTE)
+ char mbkey[MB_LEN_MAX];
+ int k;
+
+ /* Read an entire multibyte character sequence to insert COUNT times. */
+ if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+ for (i = 0; i < count; i++)
+ {
+ rl_begin_undo_group ();
+
+ if (rl_point < rl_end)
+ rl_delete (1, c);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_insert_text (mbkey);
+ else
+#endif
+ _rl_insert_char (1, c);
+
+ rl_end_undo_group ();
+ }
+
+ return 0;
+}
+
+int
+rl_insert (count, c)
+ int count, c;
+{
+ return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+ : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+int
+rl_quoted_insert (count, key)
+ int count, key __attribute__((unused));
+{
+ int c;
+
+#if defined (HANDLE_SIGNALS)
+ _rl_disable_tty_signals ();
+#endif
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_SIGNALS)
+ _rl_restore_tty_signals ();
+#endif
+
+ return (_rl_insert_char (count, c));
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+ int count, key __attribute__((unused));
+{
+ return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed. We accept the whole line.
+ KEY is the key that invoked this command. I guess it could have
+ meaning in the future. */
+int
+rl_newline (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ rl_done = 1;
+
+ if (_rl_history_preserve_point)
+ _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+ RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ {
+ _rl_vi_done_inserting ();
+ _rl_vi_reset_last ();
+ }
+#endif /* VI_MODE */
+
+ /* If we've been asked to erase empty lines, suppress the final update,
+ since _rl_update_final calls rl_crlf(). */
+ if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+ return 0;
+
+ if (readline_echoing_p)
+ _rl_update_final ();
+ return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+ and some characters appearing in emacs_ctlx_keymap. This function
+ is just a stub, you bind keys to it and the code in _rl_dispatch ()
+ is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+ int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
+{
+ return 0;
+}
+
+/* This is different from what vi does, so the code's not shared. Emacs
+ rubout in overwrite mode has one oddity: it replaces a control
+ character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+ int count, key;
+{
+ int opoint;
+ int i, l;
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return 1;
+ }
+
+ opoint = rl_point;
+
+ /* L == number of spaces to insert */
+ for (i = l = 0; i < count; i++)
+ {
+ rl_backward_char (1, key);
+ l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */
+ }
+
+ rl_begin_undo_group ();
+
+ if (count > 1 || rl_explicit_arg)
+ rl_kill_text (opoint, rl_point);
+ else
+ rl_delete_text (opoint, rl_point);
+
+ /* Emacs puts point at the beginning of the sequence of spaces. */
+ opoint = rl_point;
+ _rl_insert_char (l, ' ');
+ rl_point = opoint;
+
+ rl_end_undo_group ();
+
+ return 0;
+}
+
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_delete (-count, key));
+
+ if (!rl_point)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (rl_insert_mode == RL_IM_OVERWRITE)
+ return (_rl_overwrite_rubout (count, key));
+
+ return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+ int count, key;
+{
+ int orig_point;
+ unsigned char c;
+
+ /* Duplicated code because this is called from other parts of the library. */
+ if (count < 0)
+ return (rl_delete (-count, key));
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (count > 1 || rl_explicit_arg)
+ {
+ orig_point = rl_point;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_backward_char (count, key);
+ else
+#endif
+ rl_backward_byte (count, key);
+ rl_kill_text (orig_point, rl_point);
+ }
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+#endif
+ c = rl_line_buffer[--rl_point];
+ rl_delete_text (rl_point, rl_point + 1);
+#if defined (HANDLE_MULTIBYTE)
+ }
+ else
+ {
+ int orig_point;
+
+ orig_point = rl_point;
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ c = rl_line_buffer[rl_point];
+ rl_delete_text (rl_point, orig_point);
+ }
+#endif /* HANDLE_MULTIBYTE */
+
+ /* I don't think that the hack for end of line is needed for
+ multibyte chars. */
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+#endif
+ if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+ {
+ int l;
+ l = rl_character_len (c, rl_point);
+ _rl_erase_at_end_of_line (l);
+ }
+ }
+
+ return 0;
+}
+
+/* Delete the character under the cursor. Given a numeric argument,
+ kill that many characters instead. */
+int
+rl_delete (count, key)
+ int count, key;
+{
+ int r;
+
+ if (count < 0)
+ return (_rl_rubout_char (-count, key));
+
+ if (rl_point == rl_end)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (count > 1 || rl_explicit_arg)
+ {
+ int orig_point = rl_point;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_forward_char (count, key);
+ else
+#endif
+ rl_forward_byte (count, key);
+
+ r = rl_kill_text (orig_point, rl_point);
+ rl_point = orig_point;
+ return r;
+ }
+ else
+ {
+ int new_point;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+ else
+ new_point = rl_point + 1;
+
+ return (rl_delete_text (rl_point, new_point));
+ }
+}
+
+/* Delete the character under the cursor, unless the insertion
+ point is at the end of the line, in which case the character
+ behind the cursor is deleted. COUNT is obeyed and may be used
+ to delete forward or backward that many characters. */
+int
+rl_rubout_or_delete (count, key)
+ int count, key;
+{
+ if (rl_end != 0 && rl_point == rl_end)
+ return (_rl_rubout_char (count, key));
+ else
+ return (rl_delete (count, key));
+}
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+ int count __attribute__((unused)), ignore __attribute__((unused));
+{
+ int start = rl_point;
+
+ while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ start = rl_point;
+
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ if (start != rl_point)
+ {
+ rl_delete_text (start, rl_point);
+ rl_point = start;
+ }
+ return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list. The eof character
+ is caught before this is invoked, so this really does the same thing as
+ delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+ int count, key;
+{
+ if (rl_end != 0 && rl_point == rl_end)
+ return (rl_possible_completions (count, key));
+ else
+ return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+ A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+ int count __attribute__((unused)), key;
+{
+ const char *rl_comment_text;
+ int rl_comment_len;
+
+ rl_beg_of_line (1, key);
+ rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+ if (rl_explicit_arg == 0)
+ rl_insert_text (rl_comment_text);
+ else
+ {
+ rl_comment_len = strlen (rl_comment_text);
+ if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+ rl_delete_text (rl_point, rl_point + rl_comment_len);
+ else
+ rl_insert_text (rl_comment_text);
+ }
+
+ (*rl_redisplay_function) ();
+ rl_newline (1, '\n');
+
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Changing Case */
+/* */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+ int count, key __attribute__((unused));
+{
+ return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+ int count, key __attribute__((unused));
+{
+ return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+ int count, key __attribute__((unused));
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+ Change the case of COUNT words, performing OP on them.
+ OP is one of UpCase, DownCase, or CapCase.
+ If a negative argument is given, leave point where it started,
+ otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+ int count, op;
+{
+ register int start, end;
+ int inword, c;
+
+ start = rl_point;
+ rl_forward_word (count, 0);
+ end = rl_point;
+
+ if (count < 0)
+ SWAP (start, end);
+
+ /* We are going to modify some text, so let's prepare to undo it. */
+ rl_modifying (start, end);
+
+ for (inword = 0; start < end; start++)
+ {
+ c = rl_line_buffer[start];
+ switch (op)
+ {
+ case UpCase:
+ rl_line_buffer[start] = _rl_to_upper (c);
+ break;
+
+ case DownCase:
+ rl_line_buffer[start] = _rl_to_lower (c);
+ break;
+
+ case CapCase:
+ rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
+ inword = rl_alphabetic (rl_line_buffer[start]);
+ break;
+
+ default:
+ rl_ding ();
+ return -1;
+ }
+ }
+ rl_point = end;
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Transposition */
+/* */
+/* **************************************************************** */
+
+/* Transpose the words at point. If point is at the end of the line,
+ transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+ int count, key;
+{
+ char *word1, *word2;
+ int w1_beg, w1_end, w2_beg, w2_end;
+ int orig_point = rl_point;
+
+ if (!count)
+ return 0;
+
+ /* Find the two words. */
+ rl_forward_word (count, key);
+ w2_end = rl_point;
+ rl_backward_word (1, key);
+ w2_beg = rl_point;
+ rl_backward_word (count, key);
+ w1_beg = rl_point;
+ rl_forward_word (1, key);
+ w1_end = rl_point;
+
+ /* Do some check to make sure that there really are two words. */
+ if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+ {
+ rl_ding ();
+ rl_point = orig_point;
+ return -1;
+ }
+
+ /* Get the text of the words. */
+ word1 = rl_copy_text (w1_beg, w1_end);
+ word2 = rl_copy_text (w2_beg, w2_end);
+
+ /* We are about to do many insertions and deletions. Remember them
+ as one operation. */
+ rl_begin_undo_group ();
+
+ /* Do the stuff at word2 first, so that we don't have to worry
+ about word1 moving. */
+ rl_point = w2_beg;
+ rl_delete_text (w2_beg, w2_end);
+ rl_insert_text (word1);
+
+ rl_point = w1_beg;
+ rl_delete_text (w1_beg, w1_end);
+ rl_insert_text (word2);
+
+ /* This is exactly correct since the text before this point has not
+ changed in length. */
+ rl_point = w2_end;
+
+ /* I think that does it. */
+ rl_end_undo_group ();
+ free (word1);
+ free (word2);
+
+ return 0;
+}
+
+/* Transpose the characters at point. If point is at the end of the line,
+ then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+ int count, key __attribute__((unused));
+{
+#if defined (HANDLE_MULTIBYTE)
+ char *dummy;
+ int i, prev_point;
+#else
+ char dummy[2];
+#endif
+ int char_length;
+
+ if (count == 0)
+ return 0;
+
+ if (!rl_point || rl_end < 2)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ rl_begin_undo_group ();
+
+ if (rl_point == rl_end)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ else
+ --rl_point;
+ count = 1;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ prev_point = rl_point;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ else
+#endif
+ rl_point--;
+
+#if defined (HANDLE_MULTIBYTE)
+ char_length = prev_point - rl_point;
+ dummy = (char *)xmalloc (char_length + 1);
+ for (i = 0; i < char_length; i++)
+ dummy[i] = rl_line_buffer[rl_point + i];
+ dummy[i] = '\0';
+#else
+ dummy[0] = rl_line_buffer[rl_point];
+ dummy[char_length = 1] = '\0';
+#endif
+
+ rl_delete_text (rl_point, rl_point + char_length);
+
+ rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+ _rl_fix_point (0);
+ rl_insert_text (dummy);
+ rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+ free (dummy);
+#endif
+
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Character Searching */
+/* */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+ int count, dir;
+ char *smbchar;
+ int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+ int count, dir, schar;
+#endif
+{
+ int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+ int prepos;
+#endif
+
+ pos = rl_point;
+ inc = (dir < 0) ? -1 : 1;
+ while (count)
+ {
+ if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+ : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+ pos += inc;
+#endif
+ do
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+ if (rl_line_buffer[pos] == schar)
+#endif
+ {
+ count--;
+ if (dir < 0)
+ rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+ : pos;
+ else
+ rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+ : pos;
+ break;
+ }
+#if defined (HANDLE_MULTIBYTE)
+ prepos = pos;
+#endif
+ }
+#if defined (HANDLE_MULTIBYTE)
+ while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+ : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+ while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+ }
+ return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+ FDIR is the direction to search if COUNT is non-negative; otherwise
+ the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE
+ that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+ int count, fdir, bdir;
+{
+ char mbchar[MB_LEN_MAX];
+ int mb_len;
+
+ mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+ if (count < 0)
+ return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+ else
+ return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+ int count, fdir, bdir;
+{
+ int c;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (count < 0)
+ return (_rl_char_search_internal (-count, bdir, c));
+ else
+ return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+int
+rl_char_search (count, key)
+ int count, key __attribute__((unused));
+{
+ return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+ int count, key __attribute__((unused));
+{
+ return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/* */
+/* The Mark and the Region. */
+/* */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+ int position;
+{
+ if (position > rl_end)
+ return -1;
+
+ rl_mark = position;
+ return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+ int count, key __attribute__((unused));
+{
+ return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (rl_mark > rl_end)
+ rl_mark = -1;
+
+ if (rl_mark == -1)
+ {
+ rl_ding ();
+ return -1;
+ }
+ else
+ SWAP (rl_point, rl_mark);
+
+ return 0;
+}
diff --git a/cmd-line-utils/readline/tilde.c b/cmd-line-utils/readline/tilde.c
new file mode 100644
index 00000000000..fab4aab65ad
--- /dev/null
+++ b/cmd-line-utils/readline/tilde.c
@@ -0,0 +1,458 @@
+/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+ This file is part of GNU Readline, a library for reading lines
+ of text with interactive input and history editing.
+
+ Readline is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ Readline is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Readline; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else /* !HAVE_STRING_H */
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#include "tilde.h"
+
+#if defined (TEST) || defined (STATIC_MALLOC)
+static void *xmalloc (), *xrealloc ();
+#else
+# include "xmalloc.h"
+#endif /* TEST || STATIC_MALLOC */
+
+#if !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid PARAMS((uid_t));
+extern struct passwd *getpwnam PARAMS((const char *));
+#endif /* !HAVE_GETPW_DECLS */
+
+#if !defined (savestring)
+#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
+#endif /* !savestring */
+
+#if !defined (NULL)
+# if defined (__STDC__)
+# define NULL ((void *) 0)
+# else
+# define NULL 0x0
+# endif /* !__STDC__ */
+#endif /* !NULL */
+
+/* If being compiled as part of bash, these will be satisfied from
+ variables.o. If being compiled as part of readline, they will
+ be satisfied from shell.o. */
+extern char *sh_get_home_dir PARAMS((void));
+extern char *sh_get_env_value PARAMS((const char *));
+
+/* The default value of tilde_additional_prefixes. This is set to
+ whitespace preceding a tilde so that simple programs which do not
+ perform any word separation get desired behaviour. */
+static const char *default_prefixes[] =
+ { " ~", "\t~", (const char *)NULL };
+
+/* The default value of tilde_additional_suffixes. This is set to
+ whitespace or newline so that simple programs which do not
+ perform any word separation get desired behaviour. */
+static const char *default_suffixes[] =
+ { " ", "\n", (const char *)NULL };
+
+/* If non-null, this contains the address of a function that the application
+ wants called before trying the standard tilde expansions. The function
+ is called with the text sans tilde, and returns a malloc()'ed string
+ which is the expansion, or a NULL pointer if the expansion fails. */
+tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL;
+
+/* If non-null, this contains the address of a function to call if the
+ standard meaning for expanding a tilde fails. The function is called
+ with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+ which is the expansion, or a NULL pointer if there is no expansion. */
+tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL;
+
+/* When non-null, this is a NULL terminated array of strings which
+ are duplicates for a tilde prefix. Bash uses this to expand
+ `=~' and `:~'. */
+char **tilde_additional_prefixes = (char **)default_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+ the end of a username, instead of just "/". Bash sets this to
+ `:' and `=~'. */
+char **tilde_additional_suffixes = (char **)default_suffixes;
+
+static int tilde_find_prefix PARAMS((const char *, int *));
+static int tilde_find_suffix PARAMS((const char *));
+static char *isolate_tilde_prefix PARAMS((const char *, int *));
+static char *glue_prefix_and_suffix PARAMS((char *, const char *, int));
+
+/* Find the start of a tilde expansion in STRING, and return the index of
+ the tilde which starts the expansion. Place the length of the text
+ which identified this tilde starter in LEN, excluding the tilde itself. */
+static int
+tilde_find_prefix (string, len)
+ const char *string;
+ int *len;
+{
+ register int i, j, string_len;
+ register char **prefixes;
+
+ prefixes = tilde_additional_prefixes;
+
+ string_len = strlen (string);
+ *len = 0;
+
+ if (*string == '\0' || *string == '~')
+ return (0);
+
+ if (prefixes)
+ {
+ for (i = 0; i < string_len; i++)
+ {
+ for (j = 0; prefixes[j]; j++)
+ {
+ if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
+ {
+ *len = strlen (prefixes[j]) - 1;
+ return (i + *len);
+ }
+ }
+ }
+ }
+ return (string_len);
+}
+
+/* Find the end of a tilde expansion in STRING, and return the index of
+ the character which ends the tilde definition. */
+static int
+tilde_find_suffix (string)
+ const char *string;
+{
+ register int i, j, string_len;
+ register char **suffixes;
+
+ suffixes = tilde_additional_suffixes;
+ string_len = strlen (string);
+
+ for (i = 0; i < string_len; i++)
+ {
+#if defined (__MSDOS__)
+ if (string[i] == '/' || string[i] == '\\' /* || !string[i] */)
+#else
+ if (string[i] == '/' /* || !string[i] */)
+#endif
+ break;
+
+ for (j = 0; suffixes && suffixes[j]; j++)
+ {
+ if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
+ return (i);
+ }
+ }
+ return (i);
+}
+
+/* Return a new string which is the result of tilde expanding STRING. */
+char *
+tilde_expand (string)
+ const char *string;
+{
+ char *result;
+ int result_size, result_index;
+
+ result_index = result_size = 0;
+ if ((result = strchr(string, '~')))
+ result = (char *)xmalloc (result_size = (strlen (string) + 16));
+ else
+ result = (char *)xmalloc (result_size = (strlen (string) + 1));
+
+ /* Scan through STRING expanding tildes as we come to them. */
+ while (1)
+ {
+ register int start, end;
+ char *tilde_word, *expansion;
+ int len;
+
+ /* Make START point to the tilde which starts the expansion. */
+ start = tilde_find_prefix (string, &len);
+
+ /* Copy the skipped text into the result. */
+ if ((result_index + start + 1) > result_size)
+ result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
+
+ strncpy (result + result_index, string, start);
+ result_index += start;
+
+ /* Advance STRING to the starting tilde. */
+ string += start;
+
+ /* Make END be the index of one after the last character of the
+ username. */
+ end = tilde_find_suffix (string);
+
+ /* If both START and END are zero, we are all done. */
+ if (!start && !end)
+ break;
+
+ /* Expand the entire tilde word, and copy it into RESULT. */
+ tilde_word = (char *)xmalloc (1 + end);
+ strncpy (tilde_word, string, end);
+ tilde_word[end] = '\0';
+ string += end;
+
+ expansion = tilde_expand_word (tilde_word);
+ free (tilde_word);
+
+ len = strlen (expansion);
+#ifdef __CYGWIN__
+ /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
+ $HOME for `user' is /. On cygwin, // denotes a network drive. */
+ if (len > 1 || *expansion != '/' || *string != '/')
+#endif
+ {
+ if ((result_index + len + 1) > result_size)
+ result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
+
+ strcpy (result + result_index, expansion);
+ result_index += len;
+ }
+ free (expansion);
+ }
+
+ result[result_index] = '\0';
+
+ return (result);
+}
+
+/* Take FNAME and return the tilde prefix we want expanded. If LENP is
+ non-null, the index of the end of the prefix into FNAME is returned in
+ the location it points to. */
+static char *
+isolate_tilde_prefix (fname, lenp)
+ const char *fname;
+ int *lenp;
+{
+ char *ret;
+ int i;
+
+ ret = (char *)xmalloc (strlen (fname));
+#if defined (__MSDOS__)
+ for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
+#else
+ for (i = 1; fname[i] && fname[i] != '/'; i++)
+#endif
+ ret[i - 1] = fname[i];
+ ret[i - 1] = '\0';
+ if (lenp)
+ *lenp = i;
+ return ret;
+}
+
+/* Return a string that is PREFIX concatenated with SUFFIX starting at
+ SUFFIND. */
+static char *
+glue_prefix_and_suffix (prefix, suffix, suffind)
+ char *prefix;
+ const char *suffix;
+ int suffind;
+{
+ char *ret;
+ int plen, slen;
+
+ plen = (prefix && *prefix) ? strlen (prefix) : 0;
+ slen = strlen (suffix + suffind);
+ ret = (char *)xmalloc (plen + slen + 1);
+ if (plen)
+ strcpy (ret, prefix);
+ strcpy (ret + plen, suffix + suffind);
+ return ret;
+}
+
+/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
+ tilde. If there is no expansion, call tilde_expansion_failure_hook.
+ This always returns a newly-allocated string, never static storage. */
+char *
+tilde_expand_word (filename)
+ const char *filename;
+{
+ char *dirname, *expansion, *username;
+ int user_len;
+ struct passwd *user_entry;
+
+ if (filename == 0)
+ return ((char *)NULL);
+
+ if (*filename != '~')
+ return (savestring (filename));
+
+ /* A leading `~/' or a bare `~' is *always* translated to the value of
+ $HOME or the home directory of the current user, regardless of any
+ preexpansion hook. */
+ if (filename[1] == '\0' || filename[1] == '/')
+ {
+ /* Prefix $HOME to the rest of the string. */
+ expansion = sh_get_env_value ("HOME");
+
+ /* If there is no HOME variable, look up the directory in
+ the password database. */
+ if (expansion == 0)
+ expansion = sh_get_home_dir ();
+
+ return (glue_prefix_and_suffix (expansion, filename, 1));
+ }
+
+ username = isolate_tilde_prefix (filename, &user_len);
+
+ if (tilde_expansion_preexpansion_hook)
+ {
+ expansion = (*tilde_expansion_preexpansion_hook) (username);
+ if (expansion)
+ {
+ dirname = glue_prefix_and_suffix (expansion, filename, user_len);
+ free (username);
+ free (expansion);
+ return (dirname);
+ }
+ }
+
+ /* No preexpansion hook, or the preexpansion hook failed. Look in the
+ password database. */
+ dirname = (char *)NULL;
+ user_entry = getpwnam (username);
+ if (user_entry == 0)
+ {
+ /* If the calling program has a special syntax for expanding tildes,
+ and we couldn't find a standard expansion, then let them try. */
+ if (tilde_expansion_failure_hook)
+ {
+ expansion = (*tilde_expansion_failure_hook) (username);
+ if (expansion)
+ {
+ dirname = glue_prefix_and_suffix (expansion, filename, user_len);
+ free (expansion);
+ }
+ }
+ free (username);
+ /* If we don't have a failure hook, or if the failure hook did not
+ expand the tilde, return a copy of what we were passed. */
+ if (dirname == 0)
+ dirname = savestring (filename);
+ }
+ else
+ {
+ free (username);
+ dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
+ }
+
+ endpwent ();
+ return (dirname);
+}
+
+
+#if defined (TEST)
+#undef NULL
+#include <stdio.h>
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *result, line[512];
+ int done = 0;
+
+ while (!done)
+ {
+ printf ("~expand: ");
+ fflush (stdout);
+
+ if (!gets (line))
+ strcpy (line, "done");
+
+ if ((strcmp (line, "done") == 0) ||
+ (strcmp (line, "quit") == 0) ||
+ (strcmp (line, "exit") == 0))
+ {
+ done = 1;
+ break;
+ }
+
+ result = tilde_expand (line);
+ printf (" --> %s\n", result);
+ free (result);
+ }
+ exit (0);
+}
+
+static void memory_error_and_abort ();
+
+static void *
+xmalloc (bytes)
+ size_t bytes;
+{
+ void *temp = (char *)malloc (bytes);
+
+ if (!temp)
+ memory_error_and_abort ();
+ return (temp);
+}
+
+static void *
+xrealloc (pointer, bytes)
+ void *pointer;
+ int bytes;
+{
+ void *temp;
+
+ if (!pointer)
+ temp = malloc (bytes);
+ else
+ temp = realloc (pointer, bytes);
+
+ if (!temp)
+ memory_error_and_abort ();
+
+ return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+ fprintf (stderr, "readline: out of virtual memory\n");
+ abort ();
+}
+
+/*
+ * Local variables:
+ * compile-command: "gcc -g -DTEST -o tilde tilde.c"
+ * end:
+ */
+#endif /* TEST */
diff --git a/cmd-line-utils/readline/tilde.h b/cmd-line-utils/readline/tilde.h
new file mode 100644
index 00000000000..f8182c999d9
--- /dev/null
+++ b/cmd-line-utils/readline/tilde.h
@@ -0,0 +1,78 @@
+/* tilde.h: Externally available variables and function in libtilde.a. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+ This file contains the Readline Library (the Library), a set of
+ routines for providing Emacs style line input to programs that ask
+ for it.
+
+ The 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 2, or (at your option)
+ any later version.
+
+ The 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_TILDE_H_)
+# define _TILDE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A function can be defined using prototypes and compile on both ANSI C
+ and traditional C compilers with something like this:
+ extern char *func PARAMS((char *, char *, int)); */
+
+#if !defined (PARAMS)
+# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus)
+# define PARAMS(protos) protos
+# else
+# define PARAMS(protos) ()
+# endif
+#endif
+
+typedef char *tilde_hook_func_t PARAMS((char *));
+
+/* If non-null, this contains the address of a function that the application
+ wants called before trying the standard tilde expansions. The function
+ is called with the text sans tilde, and returns a malloc()'ed string
+ which is the expansion, or a NULL pointer if the expansion fails. */
+extern tilde_hook_func_t *tilde_expansion_preexpansion_hook;
+
+/* If non-null, this contains the address of a function to call if the
+ standard meaning for expanding a tilde fails. The function is called
+ with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+ which is the expansion, or a NULL pointer if there is no expansion. */
+extern tilde_hook_func_t *tilde_expansion_failure_hook;
+
+/* When non-null, this is a NULL terminated array of strings which
+ are duplicates for a tilde prefix. Bash uses this to expand
+ `=~' and `:~'. */
+extern char **tilde_additional_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+ the end of a username, instead of just "/". Bash sets this to
+ `:' and `=~'. */
+extern char **tilde_additional_suffixes;
+
+/* Return a new string which is the result of tilde expanding STRING. */
+extern char *tilde_expand PARAMS((const char *));
+
+/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
+ tilde. If there is no expansion, call tilde_expansion_failure_hook. */
+extern char *tilde_expand_word PARAMS((const char *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TILDE_H_ */
diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c
new file mode 100644
index 00000000000..df913195fad
--- /dev/null
+++ b/cmd-line-utils/readline/undo.c
@@ -0,0 +1,264 @@
+/* readline.c -- a general facility for reading lines of input
+ with emacs style editing and completion. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h> /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* Non-zero tells rl_delete_text and rl_insert_text to not add to
+ the undo list. */
+int _rl_doing_an_undo = 0;
+
+/* How many unclosed undo groups we currently have. */
+int _rl_undo_group_level = 0;
+
+/* The current undo list for THE_LINE. */
+UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
+
+/* **************************************************************** */
+/* */
+/* Undo, and Undoing */
+/* */
+/* **************************************************************** */
+
+/* Remember how to undo something. Concatenate some undos if that
+ seems right. */
+void
+rl_add_undo (what, start, end, text)
+ enum undo_code what;
+ int start, end;
+ char *text;
+{
+ UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
+ temp->what = what;
+ temp->start = start;
+ temp->end = end;
+ temp->text = text;
+ temp->next = rl_undo_list;
+ rl_undo_list = temp;
+}
+
+/* Free the existing undo list. */
+void
+rl_free_undo_list ()
+{
+ while (rl_undo_list)
+ {
+ UNDO_LIST *release = rl_undo_list;
+ rl_undo_list = rl_undo_list->next;
+
+ if (release->what == UNDO_DELETE)
+ free (release->text);
+
+ free (release);
+ }
+ rl_undo_list = (UNDO_LIST *)NULL;
+}
+
+/* Undo the next thing in the list. Return 0 if there
+ is nothing to undo, or non-zero if there was. */
+int
+rl_do_undo ()
+{
+ UNDO_LIST *release;
+ int waiting_for_begin, start, end;
+
+#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
+
+ start = end = waiting_for_begin = 0;
+ do
+ {
+ if (!rl_undo_list)
+ return (0);
+
+ _rl_doing_an_undo = 1;
+ RL_SETSTATE(RL_STATE_UNDOING);
+
+ /* To better support vi-mode, a start or end value of -1 means
+ rl_point, and a value of -2 means rl_end. */
+ if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
+ {
+ start = TRANS (rl_undo_list->start);
+ end = TRANS (rl_undo_list->end);
+ }
+
+ switch (rl_undo_list->what)
+ {
+ /* Undoing deletes means inserting some text. */
+ case UNDO_DELETE:
+ rl_point = start;
+ rl_insert_text (rl_undo_list->text);
+ free (rl_undo_list->text);
+ break;
+
+ /* Undoing inserts means deleting some text. */
+ case UNDO_INSERT:
+ rl_delete_text (start, end);
+ rl_point = start;
+ break;
+
+ /* Undoing an END means undoing everything 'til we get to a BEGIN. */
+ case UNDO_END:
+ waiting_for_begin++;
+ break;
+
+ /* Undoing a BEGIN means that we are done with this group. */
+ case UNDO_BEGIN:
+ if (waiting_for_begin)
+ waiting_for_begin--;
+ else
+ rl_ding ();
+ break;
+ }
+
+ _rl_doing_an_undo = 0;
+ RL_UNSETSTATE(RL_STATE_UNDOING);
+
+ release = rl_undo_list;
+ rl_undo_list = rl_undo_list->next;
+ free (release);
+ }
+ while (waiting_for_begin);
+
+ return (1);
+}
+#undef TRANS
+
+int
+_rl_fix_last_undo_of_type (type, start, end)
+ unsigned int type;
+ int start, end;
+{
+ UNDO_LIST *rl;
+
+ for (rl = rl_undo_list; rl; rl = rl->next)
+ {
+ if (rl->what == type)
+ {
+ rl->start = start;
+ rl->end = end;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Begin a group. Subsequent undos are undone as an atomic operation. */
+int
+rl_begin_undo_group ()
+{
+ rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+ _rl_undo_group_level++;
+ return 0;
+}
+
+/* End an undo group started with rl_begin_undo_group (). */
+int
+rl_end_undo_group ()
+{
+ rl_add_undo (UNDO_END, 0, 0, 0);
+ _rl_undo_group_level--;
+ return 0;
+}
+
+/* Save an undo entry for the text from START to END. */
+int
+rl_modifying (start, end)
+ int start, end;
+{
+ if (start > end)
+ {
+ SWAP (start, end);
+ }
+
+ if (start != end)
+ {
+ char *temp = rl_copy_text (start, end);
+ rl_begin_undo_group ();
+ rl_add_undo (UNDO_DELETE, start, end, temp);
+ rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
+ rl_end_undo_group ();
+ }
+ return 0;
+}
+
+/* Revert the current line to its previous state. */
+int
+rl_revert_line (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ if (!rl_undo_list)
+ rl_ding ();
+ else
+ {
+ while (rl_undo_list)
+ rl_do_undo ();
+ }
+ return 0;
+}
+
+/* Do some undoing of things that were done. */
+int
+rl_undo_command (count, key)
+ int count, key __attribute__((unused));
+{
+ if (count < 0)
+ return 0; /* Nothing to do. */
+
+ while (count)
+ {
+ if (rl_do_undo ())
+ count--;
+ else
+ {
+ rl_ding ();
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c
new file mode 100644
index 00000000000..2a6e4e3398a
--- /dev/null
+++ b/cmd-line-utils/readline/util.c
@@ -0,0 +1,338 @@
+/* util.c -- readline utility functions */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "posixjmp.h"
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h> /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (TIOCSTAT_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif /* TIOCSTAT_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/* */
+/* Utility Functions */
+/* */
+/* **************************************************************** */
+
+/* Return 0 if C is not a member of the class of characters that belong
+ in words, or 1 if it is. */
+
+int _rl_allow_pathname_alphabetic_chars = 0;
+static const char *pathname_alphabetic_chars = "/-_=~.#$";
+
+int
+rl_alphabetic (c)
+ int c;
+{
+ if (ALPHABETIC (c))
+ return (1);
+
+ return (_rl_allow_pathname_alphabetic_chars &&
+ strchr (pathname_alphabetic_chars, c) != NULL);
+}
+
+/* How to abort things. */
+int
+_rl_abort_internal ()
+{
+ rl_ding ();
+ rl_clear_message ();
+ _rl_init_argument ();
+ rl_clear_pending_input ();
+
+ RL_UNSETSTATE (RL_STATE_MACRODEF);
+ while (rl_executing_macro)
+ _rl_pop_executing_macro ();
+
+ rl_last_func = (rl_command_func_t *)NULL;
+ longjmp (readline_top_level, 1);
+ return (0);
+}
+
+int
+rl_abort (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ return (_rl_abort_internal ());
+}
+
+int
+rl_tty_status (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+#if defined (TIOCSTAT)
+ ioctl (1, TIOCSTAT, (char *)0);
+ rl_refresh_line (count, key);
+#else
+ rl_ding ();
+#endif
+ return 0;
+}
+
+/* Return a copy of the string between FROM and TO.
+ FROM is inclusive, TO is not. */
+char *
+rl_copy_text (from, to)
+ int from, to;
+{
+ register int length;
+ char *copy;
+
+ /* Fix it if the caller is confused. */
+ if (from > to)
+ SWAP (from, to);
+
+ length = to - from;
+ copy = (char *)xmalloc (1 + length);
+ strncpy (copy, rl_line_buffer + from, length);
+ copy[length] = '\0';
+ return (copy);
+}
+
+/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
+ LEN characters. */
+void
+rl_extend_line_buffer (len)
+ int len;
+{
+ while (len >= rl_line_buffer_len)
+ {
+ rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
+ rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
+ }
+
+ _rl_set_the_line ();
+}
+
+
+/* A function for simple tilde expansion. */
+int
+rl_tilde_expand (ignore, key)
+ int ignore __attribute__((unused)), key __attribute__((unused));
+{
+ register int start, end;
+ char *homedir, *temp;
+ int len;
+
+ end = rl_point;
+ start = end - 1;
+
+ if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
+ {
+ homedir = tilde_expand ("~");
+ _rl_replace_text (homedir, start, end);
+ return (0);
+ }
+ else if (rl_line_buffer[start] != '~')
+ {
+ for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
+ ;
+ start++;
+ }
+
+ end = start;
+ do
+ end++;
+ while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
+
+ if (whitespace (rl_line_buffer[end]) || end >= rl_end)
+ end--;
+
+ /* If the first character of the current word is a tilde, perform
+ tilde expansion and insert the result. If not a tilde, do
+ nothing. */
+ if (rl_line_buffer[start] == '~')
+ {
+ len = end - start + 1;
+ temp = (char *)xmalloc (len + 1);
+ strncpy (temp, rl_line_buffer + start, len);
+ temp[len] = '\0';
+ homedir = tilde_expand (temp);
+ free (temp);
+
+ _rl_replace_text (homedir, start, end);
+ }
+
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* String Utility Functions */
+/* */
+/* **************************************************************** */
+
+/* Determine if s2 occurs in s1. If so, return a pointer to the
+ match in s1. The compare is case insensitive. */
+char *
+_rl_strindex (s1, s2)
+ register const char *s1, *s2;
+{
+ register int i, l, len;
+
+ for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
+ if (_rl_strnicmp (s1 + i, s2, l) == 0)
+ return ((char *) (s1 + i));
+ return ((char *)NULL);
+}
+
+#ifndef HAVE_STRPBRK
+/* Find the first occurrence in STRING1 of any character from STRING2.
+ Return a pointer to the character in STRING1. */
+char *
+_rl_strpbrk (string1, string2)
+ const char *string1, *string2;
+{
+ register const char *scan;
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t ps;
+ register int i, v;
+
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+ for (; *string1; string1++)
+ {
+ for (scan = string2; *scan; scan++)
+ {
+ if (*string1 == *scan)
+ return ((char *)string1);
+ }
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ v = _rl_get_char_len (string1, &ps);
+ if (v > 1)
+ string += v - 1; /* -1 to account for auto-increment in loop */
+ }
+#endif
+ }
+ return ((char *)NULL);
+}
+#endif
+
+#if !defined (HAVE_STRCASECMP)
+/* Compare at most COUNT characters from string1 to string2. Case
+ doesn't matter. */
+int
+_rl_strnicmp (string1, string2, count)
+ char *string1, *string2;
+ int count;
+{
+ register char ch1, ch2;
+
+ while (count)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+ if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
+ count--;
+ else
+ break;
+ }
+ return (count);
+}
+
+/* strcmp (), but caseless. */
+int
+_rl_stricmp (string1, string2)
+ char *string1, *string2;
+{
+ register char ch1, ch2;
+
+ while (*string1 && *string2)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+ if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
+ return (1);
+ }
+ return (*string1 - *string2);
+}
+#endif /* !HAVE_STRCASECMP */
+
+/* Stupid comparison routine for qsort () ing strings. */
+int
+_rl_qsort_string_compare (s1, s2)
+ char **s1, **s2;
+{
+#if defined (HAVE_STRCOLL)
+ return (strcoll (*s1, *s2));
+#else
+ int result;
+
+ result = **s1 - **s2;
+ if (result == 0)
+ result = strcmp (*s1, *s2);
+
+ return result;
+#endif
+}
+
+/* Function equivalents for the macros defined in chardefs.h. */
+#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); }
+
+FUNCTION_FOR_MACRO (_rl_digit_p)
+FUNCTION_FOR_MACRO (_rl_digit_value)
+FUNCTION_FOR_MACRO (_rl_lowercase_p)
+FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
+FUNCTION_FOR_MACRO (_rl_to_lower)
+FUNCTION_FOR_MACRO (_rl_to_upper)
+FUNCTION_FOR_MACRO (_rl_uppercase_p)
+
+/* Backwards compatibility, now that savestring has been removed from
+ all `public' readline header files. */
+#undef _rl_savestring
+char *
+_rl_savestring (s)
+ const char *s;
+{
+ return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
+}
diff --git a/cmd-line-utils/readline/vi_keymap.c b/cmd-line-utils/readline/vi_keymap.c
new file mode 100644
index 00000000000..53a67c674ce
--- /dev/null
+++ b/cmd-line-utils/readline/vi_keymap.c
@@ -0,0 +1,877 @@
+/* vi_keymap.c -- the keymap for vi_mode in readline (). */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* !BUFSIZ */
+
+#include "readline.h"
+
+#if 0
+extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
+#endif
+
+/* The keymap arrays for handling vi mode. */
+KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
+ /* The regular control keys come first. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */
+ { ISFUNC, rl_vi_eof_maybe }, /* Control-d */
+ { ISFUNC, rl_emacs_editing_mode }, /* Control-e */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */
+ { ISFUNC, rl_abort }, /* Control-g */
+ { ISFUNC, rl_backward_char }, /* Control-h */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */
+ { ISFUNC, rl_newline }, /* Control-j */
+ { ISFUNC, rl_kill_line }, /* Control-k */
+ { ISFUNC, rl_clear_screen }, /* Control-l */
+ { ISFUNC, rl_newline }, /* Control-m */
+ { ISFUNC, rl_get_next_history }, /* Control-n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */
+ { ISFUNC, rl_get_previous_history }, /* Control-p */
+ { ISFUNC, rl_quoted_insert }, /* Control-q */
+ { ISFUNC, rl_reverse_search_history }, /* Control-r */
+ { ISFUNC, rl_forward_search_history }, /* Control-s */
+ { ISFUNC, rl_transpose_chars }, /* Control-t */
+ { ISFUNC, rl_unix_line_discard }, /* Control-u */
+ { ISFUNC, rl_quoted_insert }, /* Control-v */
+ { ISFUNC, rl_unix_word_rubout }, /* Control-w */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */
+ { ISFUNC, rl_yank }, /* Control-y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */
+
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */ /* vi_escape_keymap */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */
+ { ISFUNC, rl_vi_undo }, /* Control-_ */
+
+ /* The start of printing characters. */
+ { ISFUNC, rl_forward_char }, /* SPACE */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* " */
+ { ISFUNC, rl_insert_comment }, /* # */
+ { ISFUNC, rl_end_of_line }, /* $ */
+ { ISFUNC, rl_vi_match }, /* % */
+ { ISFUNC, rl_vi_tilde_expand }, /* & */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */
+ { ISFUNC, rl_vi_complete }, /* * */
+ { ISFUNC, rl_get_next_history}, /* + */
+ { ISFUNC, rl_vi_char_search }, /* , */
+ { ISFUNC, rl_get_previous_history }, /* - */
+ { ISFUNC, rl_vi_redo }, /* . */
+ { ISFUNC, rl_vi_search }, /* / */
+
+ /* Regular digits. */
+ { ISFUNC, rl_beg_of_line }, /* 0 */
+ { ISFUNC, rl_vi_arg_digit }, /* 1 */
+ { ISFUNC, rl_vi_arg_digit }, /* 2 */
+ { ISFUNC, rl_vi_arg_digit }, /* 3 */
+ { ISFUNC, rl_vi_arg_digit }, /* 4 */
+ { ISFUNC, rl_vi_arg_digit }, /* 5 */
+ { ISFUNC, rl_vi_arg_digit }, /* 6 */
+ { ISFUNC, rl_vi_arg_digit }, /* 7 */
+ { ISFUNC, rl_vi_arg_digit }, /* 8 */
+ { ISFUNC, rl_vi_arg_digit }, /* 9 */
+
+ /* A little more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* : */
+ { ISFUNC, rl_vi_char_search }, /* ; */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* < */
+ { ISFUNC, rl_vi_complete }, /* = */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* > */
+ { ISFUNC, rl_vi_search }, /* ? */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */
+
+ /* Uppercase alphabet. */
+ { ISFUNC, rl_vi_append_eol }, /* A */
+ { ISFUNC, rl_vi_prev_word}, /* B */
+ { ISFUNC, rl_vi_change_to }, /* C */
+ { ISFUNC, rl_vi_delete_to }, /* D */
+ { ISFUNC, rl_vi_end_word }, /* E */
+ { ISFUNC, rl_vi_char_search }, /* F */
+ { ISFUNC, rl_vi_fetch_history }, /* G */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* H */
+ { ISFUNC, rl_vi_insert_beg }, /* I */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* J */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* K */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* L */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* M */
+ { ISFUNC, rl_vi_search_again }, /* N */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* O */
+ { ISFUNC, rl_vi_put }, /* P */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Q */
+ { ISFUNC, rl_vi_replace }, /* R */
+ { ISFUNC, rl_vi_subst }, /* S */
+ { ISFUNC, rl_vi_char_search }, /* T */
+ { ISFUNC, rl_revert_line }, /* U */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* V */
+ { ISFUNC, rl_vi_next_word }, /* W */
+ { ISFUNC, rl_rubout }, /* X */
+ { ISFUNC, rl_vi_yank_to }, /* Y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Z */
+
+ /* Some more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */
+ { ISFUNC, rl_vi_complete }, /* \ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */
+ { ISFUNC, rl_vi_first_print }, /* ^ */
+ { ISFUNC, rl_vi_yank_arg }, /* _ */
+ { ISFUNC, rl_vi_goto_mark }, /* ` */
+
+ /* Lowercase alphabet. */
+ { ISFUNC, rl_vi_append_mode }, /* a */
+ { ISFUNC, rl_vi_prev_word }, /* b */
+ { ISFUNC, rl_vi_change_to }, /* c */
+ { ISFUNC, rl_vi_delete_to }, /* d */
+ { ISFUNC, rl_vi_end_word }, /* e */
+ { ISFUNC, rl_vi_char_search }, /* f */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* g */
+ { ISFUNC, rl_backward_char }, /* h */
+ { ISFUNC, rl_vi_insertion_mode }, /* i */
+ { ISFUNC, rl_get_next_history }, /* j */
+ { ISFUNC, rl_get_previous_history }, /* k */
+ { ISFUNC, rl_forward_char }, /* l */
+ { ISFUNC, rl_vi_set_mark }, /* m */
+ { ISFUNC, rl_vi_search_again }, /* n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* o */
+ { ISFUNC, rl_vi_put }, /* p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* q */
+ { ISFUNC, rl_vi_change_char }, /* r */
+ { ISFUNC, rl_vi_subst }, /* s */
+ { ISFUNC, rl_vi_char_search }, /* t */
+ { ISFUNC, rl_vi_undo }, /* u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* v */
+ { ISFUNC, rl_vi_next_word }, /* w */
+ { ISFUNC, rl_vi_delete }, /* x */
+ { ISFUNC, rl_vi_yank_to }, /* y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* z */
+
+ /* Final punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* { */
+ { ISFUNC, rl_vi_column }, /* | */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* } */
+ { ISFUNC, rl_vi_change_case }, /* ~ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+ /* Undefined keys. */
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+
+KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
+ /* The regular control keys come first. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */
+ { ISFUNC, rl_insert }, /* Control-a */
+ { ISFUNC, rl_insert }, /* Control-b */
+ { ISFUNC, rl_insert }, /* Control-c */
+ { ISFUNC, rl_vi_eof_maybe }, /* Control-d */
+ { ISFUNC, rl_insert }, /* Control-e */
+ { ISFUNC, rl_insert }, /* Control-f */
+ { ISFUNC, rl_insert }, /* Control-g */
+ { ISFUNC, rl_rubout }, /* Control-h */
+ { ISFUNC, rl_complete }, /* Control-i */
+ { ISFUNC, rl_newline }, /* Control-j */
+ { ISFUNC, rl_insert }, /* Control-k */
+ { ISFUNC, rl_insert }, /* Control-l */
+ { ISFUNC, rl_newline }, /* Control-m */
+ { ISFUNC, rl_insert }, /* Control-n */
+ { ISFUNC, rl_insert }, /* Control-o */
+ { ISFUNC, rl_insert }, /* Control-p */
+ { ISFUNC, rl_insert }, /* Control-q */
+ { ISFUNC, rl_reverse_search_history }, /* Control-r */
+ { ISFUNC, rl_forward_search_history }, /* Control-s */
+ { ISFUNC, rl_transpose_chars }, /* Control-t */
+ { ISFUNC, rl_unix_line_discard }, /* Control-u */
+ { ISFUNC, rl_quoted_insert }, /* Control-v */
+ { ISFUNC, rl_unix_word_rubout }, /* Control-w */
+ { ISFUNC, rl_insert }, /* Control-x */
+ { ISFUNC, rl_yank }, /* Control-y */
+ { ISFUNC, rl_insert }, /* Control-z */
+
+ { ISFUNC, rl_vi_movement_mode }, /* Control-[ */
+ { ISFUNC, rl_insert }, /* Control-\ */
+ { ISFUNC, rl_insert }, /* Control-] */
+ { ISFUNC, rl_insert }, /* Control-^ */
+ { ISFUNC, rl_vi_undo }, /* Control-_ */
+
+ /* The start of printing characters. */
+ { ISFUNC, rl_insert }, /* SPACE */
+ { ISFUNC, rl_insert }, /* ! */
+ { ISFUNC, rl_insert }, /* " */
+ { ISFUNC, rl_insert }, /* # */
+ { ISFUNC, rl_insert }, /* $ */
+ { ISFUNC, rl_insert }, /* % */
+ { ISFUNC, rl_insert }, /* & */
+ { ISFUNC, rl_insert }, /* ' */
+ { ISFUNC, rl_insert }, /* ( */
+ { ISFUNC, rl_insert }, /* ) */
+ { ISFUNC, rl_insert }, /* * */
+ { ISFUNC, rl_insert }, /* + */
+ { ISFUNC, rl_insert }, /* , */
+ { ISFUNC, rl_insert }, /* - */
+ { ISFUNC, rl_insert }, /* . */
+ { ISFUNC, rl_insert }, /* / */
+
+ /* Regular digits. */
+ { ISFUNC, rl_insert }, /* 0 */
+ { ISFUNC, rl_insert }, /* 1 */
+ { ISFUNC, rl_insert }, /* 2 */
+ { ISFUNC, rl_insert }, /* 3 */
+ { ISFUNC, rl_insert }, /* 4 */
+ { ISFUNC, rl_insert }, /* 5 */
+ { ISFUNC, rl_insert }, /* 6 */
+ { ISFUNC, rl_insert }, /* 7 */
+ { ISFUNC, rl_insert }, /* 8 */
+ { ISFUNC, rl_insert }, /* 9 */
+
+ /* A little more punctuation. */
+ { ISFUNC, rl_insert }, /* : */
+ { ISFUNC, rl_insert }, /* ; */
+ { ISFUNC, rl_insert }, /* < */
+ { ISFUNC, rl_insert }, /* = */
+ { ISFUNC, rl_insert }, /* > */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* @ */
+
+ /* Uppercase alphabet. */
+ { ISFUNC, rl_insert }, /* A */
+ { ISFUNC, rl_insert }, /* B */
+ { ISFUNC, rl_insert }, /* C */
+ { ISFUNC, rl_insert }, /* D */
+ { ISFUNC, rl_insert }, /* E */
+ { ISFUNC, rl_insert }, /* F */
+ { ISFUNC, rl_insert }, /* G */
+ { ISFUNC, rl_insert }, /* H */
+ { ISFUNC, rl_insert }, /* I */
+ { ISFUNC, rl_insert }, /* J */
+ { ISFUNC, rl_insert }, /* K */
+ { ISFUNC, rl_insert }, /* L */
+ { ISFUNC, rl_insert }, /* M */
+ { ISFUNC, rl_insert }, /* N */
+ { ISFUNC, rl_insert }, /* O */
+ { ISFUNC, rl_insert }, /* P */
+ { ISFUNC, rl_insert }, /* Q */
+ { ISFUNC, rl_insert }, /* R */
+ { ISFUNC, rl_insert }, /* S */
+ { ISFUNC, rl_insert }, /* T */
+ { ISFUNC, rl_insert }, /* U */
+ { ISFUNC, rl_insert }, /* V */
+ { ISFUNC, rl_insert }, /* W */
+ { ISFUNC, rl_insert }, /* X */
+ { ISFUNC, rl_insert }, /* Y */
+ { ISFUNC, rl_insert }, /* Z */
+
+ /* Some more punctuation. */
+ { ISFUNC, rl_insert }, /* [ */
+ { ISFUNC, rl_insert }, /* \ */
+ { ISFUNC, rl_insert }, /* ] */
+ { ISFUNC, rl_insert }, /* ^ */
+ { ISFUNC, rl_insert }, /* _ */
+ { ISFUNC, rl_insert }, /* ` */
+
+ /* Lowercase alphabet. */
+ { ISFUNC, rl_insert }, /* a */
+ { ISFUNC, rl_insert }, /* b */
+ { ISFUNC, rl_insert }, /* c */
+ { ISFUNC, rl_insert }, /* d */
+ { ISFUNC, rl_insert }, /* e */
+ { ISFUNC, rl_insert }, /* f */
+ { ISFUNC, rl_insert }, /* g */
+ { ISFUNC, rl_insert }, /* h */
+ { ISFUNC, rl_insert }, /* i */
+ { ISFUNC, rl_insert }, /* j */
+ { ISFUNC, rl_insert }, /* k */
+ { ISFUNC, rl_insert }, /* l */
+ { ISFUNC, rl_insert }, /* m */
+ { ISFUNC, rl_insert }, /* n */
+ { ISFUNC, rl_insert }, /* o */
+ { ISFUNC, rl_insert }, /* p */
+ { ISFUNC, rl_insert }, /* q */
+ { ISFUNC, rl_insert }, /* r */
+ { ISFUNC, rl_insert }, /* s */
+ { ISFUNC, rl_insert }, /* t */
+ { ISFUNC, rl_insert }, /* u */
+ { ISFUNC, rl_insert }, /* v */
+ { ISFUNC, rl_insert }, /* w */
+ { ISFUNC, rl_insert }, /* x */
+ { ISFUNC, rl_insert }, /* y */
+ { ISFUNC, rl_insert }, /* z */
+
+ /* Final punctuation. */
+ { ISFUNC, rl_insert }, /* { */
+ { ISFUNC, rl_insert }, /* | */
+ { ISFUNC, rl_insert }, /* } */
+ { ISFUNC, rl_insert }, /* ~ */
+ { ISFUNC, rl_rubout }, /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+ /* Pure 8-bit characters (128 - 159).
+ These might be used in some
+ character sets. */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+ { ISFUNC, rl_insert }, /* ? */
+
+ /* ISO Latin-1 characters (160 - 255) */
+ { ISFUNC, rl_insert }, /* No-break space */
+ { ISFUNC, rl_insert }, /* Inverted exclamation mark */
+ { ISFUNC, rl_insert }, /* Cent sign */
+ { ISFUNC, rl_insert }, /* Pound sign */
+ { ISFUNC, rl_insert }, /* Currency sign */
+ { ISFUNC, rl_insert }, /* Yen sign */
+ { ISFUNC, rl_insert }, /* Broken bar */
+ { ISFUNC, rl_insert }, /* Section sign */
+ { ISFUNC, rl_insert }, /* Diaeresis */
+ { ISFUNC, rl_insert }, /* Copyright sign */
+ { ISFUNC, rl_insert }, /* Feminine ordinal indicator */
+ { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */
+ { ISFUNC, rl_insert }, /* Not sign */
+ { ISFUNC, rl_insert }, /* Soft hyphen */
+ { ISFUNC, rl_insert }, /* Registered sign */
+ { ISFUNC, rl_insert }, /* Macron */
+ { ISFUNC, rl_insert }, /* Degree sign */
+ { ISFUNC, rl_insert }, /* Plus-minus sign */
+ { ISFUNC, rl_insert }, /* Superscript two */
+ { ISFUNC, rl_insert }, /* Superscript three */
+ { ISFUNC, rl_insert }, /* Acute accent */
+ { ISFUNC, rl_insert }, /* Micro sign */
+ { ISFUNC, rl_insert }, /* Pilcrow sign */
+ { ISFUNC, rl_insert }, /* Middle dot */
+ { ISFUNC, rl_insert }, /* Cedilla */
+ { ISFUNC, rl_insert }, /* Superscript one */
+ { ISFUNC, rl_insert }, /* Masculine ordinal indicator */
+ { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */
+ { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */
+ { ISFUNC, rl_insert }, /* Vulgar fraction one half */
+ { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */
+ { ISFUNC, rl_insert }, /* Inverted questionk mark */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */
+ { ISFUNC, rl_insert }, /* Latin capital letter ae */
+ { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */
+ { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */
+ { ISFUNC, rl_insert }, /* Multiplication sign */
+ { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with grave */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */
+ { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */
+ { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */
+ { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */
+ { ISFUNC, rl_insert }, /* Latin small letter a with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter a with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter a with tilde */
+ { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter a with ring above */
+ { ISFUNC, rl_insert }, /* Latin small letter ae */
+ { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */
+ { ISFUNC, rl_insert }, /* Latin small letter e with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter e with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter i with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter i with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */
+ { ISFUNC, rl_insert }, /* Latin small letter n with tilde */
+ { ISFUNC, rl_insert }, /* Latin small letter o with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter o with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter o with tilde */
+ { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */
+ { ISFUNC, rl_insert }, /* Division sign */
+ { ISFUNC, rl_insert }, /* Latin small letter o with stroke */
+ { ISFUNC, rl_insert }, /* Latin small letter u with grave */
+ { ISFUNC, rl_insert }, /* Latin small letter u with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */
+ { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */
+ { ISFUNC, rl_insert }, /* Latin small letter y with acute */
+ { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */
+ { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+/* Unused for the time being. */
+#if 0
+KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
+ /* The regular control keys come first. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-g */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */
+ { ISFUNC, rl_tab_insert}, /* Control-i */
+ { ISFUNC, rl_emacs_editing_mode}, /* Control-j */
+ { ISFUNC, rl_kill_line }, /* Control-k */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */
+ { ISFUNC, rl_emacs_editing_mode}, /* Control-m */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-r */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */
+
+ { ISFUNC, rl_vi_movement_mode }, /* Control-[ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */
+ { ISFUNC, rl_vi_undo }, /* Control-_ */
+
+ /* The start of printing characters. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* " */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* # */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* % */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* & */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* * */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* + */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* , */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* - */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* . */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* / */
+
+ /* Regular digits. */
+ { ISFUNC, rl_vi_arg_digit }, /* 0 */
+ { ISFUNC, rl_vi_arg_digit }, /* 1 */
+ { ISFUNC, rl_vi_arg_digit }, /* 2 */
+ { ISFUNC, rl_vi_arg_digit }, /* 3 */
+ { ISFUNC, rl_vi_arg_digit }, /* 4 */
+ { ISFUNC, rl_vi_arg_digit }, /* 5 */
+ { ISFUNC, rl_vi_arg_digit }, /* 6 */
+ { ISFUNC, rl_vi_arg_digit }, /* 7 */
+ { ISFUNC, rl_vi_arg_digit }, /* 8 */
+ { ISFUNC, rl_vi_arg_digit }, /* 9 */
+
+ /* A little more punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* : */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* < */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* = */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* > */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */
+
+ /* Uppercase alphabet. */
+ { ISFUNC, rl_do_lowercase_version }, /* A */
+ { ISFUNC, rl_do_lowercase_version }, /* B */
+ { ISFUNC, rl_do_lowercase_version }, /* C */
+ { ISFUNC, rl_do_lowercase_version }, /* D */
+ { ISFUNC, rl_do_lowercase_version }, /* E */
+ { ISFUNC, rl_do_lowercase_version }, /* F */
+ { ISFUNC, rl_do_lowercase_version }, /* G */
+ { ISFUNC, rl_do_lowercase_version }, /* H */
+ { ISFUNC, rl_do_lowercase_version }, /* I */
+ { ISFUNC, rl_do_lowercase_version }, /* J */
+ { ISFUNC, rl_do_lowercase_version }, /* K */
+ { ISFUNC, rl_do_lowercase_version }, /* L */
+ { ISFUNC, rl_do_lowercase_version }, /* M */
+ { ISFUNC, rl_do_lowercase_version }, /* N */
+ { ISFUNC, rl_do_lowercase_version }, /* O */
+ { ISFUNC, rl_do_lowercase_version }, /* P */
+ { ISFUNC, rl_do_lowercase_version }, /* Q */
+ { ISFUNC, rl_do_lowercase_version }, /* R */
+ { ISFUNC, rl_do_lowercase_version }, /* S */
+ { ISFUNC, rl_do_lowercase_version }, /* T */
+ { ISFUNC, rl_do_lowercase_version }, /* U */
+ { ISFUNC, rl_do_lowercase_version }, /* V */
+ { ISFUNC, rl_do_lowercase_version }, /* W */
+ { ISFUNC, rl_do_lowercase_version }, /* X */
+ { ISFUNC, rl_do_lowercase_version }, /* Y */
+ { ISFUNC, rl_do_lowercase_version }, /* Z */
+
+ /* Some more punctuation. */
+ { ISFUNC, rl_arrow_keys }, /* [ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */
+
+ /* Lowercase alphabet. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* a */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* b */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* c */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* d */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* e */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* f */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* g */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* h */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* i */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* j */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* k */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* l */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* m */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* n */
+ { ISFUNC, rl_arrow_keys }, /* o */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* p */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* q */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* r */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* s */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* t */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* u */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* v */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* w */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* x */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* y */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* z */
+
+ /* Final punctuation. */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* { */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* | */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* } */
+ { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */
+ { ISFUNC, rl_backward_kill_word }, /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+ /* Undefined keys. */
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 },
+ { ISFUNC, (rl_command_func_t *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+#endif
diff --git a/cmd-line-utils/readline/vi_mode.c b/cmd-line-utils/readline/vi_mode.c
new file mode 100644
index 00000000000..01df589f625
--- /dev/null
+++ b/cmd-line-utils/readline/vi_mode.c
@@ -0,0 +1,1485 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+ Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+/* **************************************************************** */
+/* */
+/* VI Emulation Mode */
+/* */
+/* **************************************************************** */
+#include "rlconf.h"
+
+#if defined (VI_MODE)
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+/* Some standard library routines. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#ifndef member
+#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
+#endif
+
+/* Non-zero means enter insertion mode. */
+static int _rl_vi_doing_insert;
+
+/* Command keys which do movement for xxx_to commands. */
+static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|";
+
+/* Keymap used for vi replace characters. Created dynamically since
+ rarely used. */
+static Keymap vi_replace_map;
+
+/* The number of characters inserted in the last replace operation. */
+static int vi_replace_count;
+
+/* If non-zero, we have text inserted after a c[motion] command that put
+ us implicitly into insert mode. Some people want this text to be
+ attached to the command so that it is `redoable' with `.'. */
+static int vi_continued_command;
+static char *vi_insert_buffer;
+static int vi_insert_buffer_size;
+
+static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
+static int _rl_vi_last_repeat = 1;
+static int _rl_vi_last_arg_sign = 1;
+static int _rl_vi_last_motion;
+#if defined (HANDLE_MULTIBYTE)
+static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
+#else
+static int _rl_vi_last_search_char;
+#endif
+static int _rl_vi_last_replacement;
+
+static int _rl_vi_last_key_before_insert;
+
+static int vi_redoing;
+
+/* Text modification commands. These are the `redoable' commands. */
+static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
+
+/* Arrays for the saved marks. */
+static int vi_mark_chars['z' - 'a' + 1];
+
+static void _rl_vi_stuff_insert PARAMS((int));
+static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
+static int rl_digit_loop1 PARAMS((void));
+
+void
+_rl_vi_initialize_line ()
+{
+ register unsigned int i;
+
+ for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
+ vi_mark_chars[i] = -1;
+}
+
+void
+_rl_vi_reset_last ()
+{
+ _rl_vi_last_command = 'i';
+ _rl_vi_last_repeat = 1;
+ _rl_vi_last_arg_sign = 1;
+ _rl_vi_last_motion = 0;
+}
+
+void
+_rl_vi_set_last (key, repeat, sign)
+ int key, repeat, sign;
+{
+ _rl_vi_last_command = key;
+ _rl_vi_last_repeat = repeat;
+ _rl_vi_last_arg_sign = sign;
+}
+
+/* Is the command C a VI mode text modification command? */
+int
+_rl_vi_textmod_command (c)
+ int c;
+{
+ return (member (c, vi_textmod));
+}
+
+static void
+_rl_vi_stuff_insert (count)
+ int count;
+{
+ rl_begin_undo_group ();
+ while (count--)
+ rl_insert_text (vi_insert_buffer);
+ rl_end_undo_group ();
+}
+
+/* Bound to `.'. Called from command mode, so we know that we have to
+ redo a text modification command. The default for _rl_vi_last_command
+ puts you back into insert mode. */
+int
+rl_vi_redo (count, c)
+ int count, c __attribute__((unused));
+{
+ int r;
+
+ if (!rl_explicit_arg)
+ {
+ rl_numeric_arg = _rl_vi_last_repeat;
+ rl_arg_sign = _rl_vi_last_arg_sign;
+ }
+
+ r = 0;
+ vi_redoing = 1;
+ /* If we're redoing an insert with `i', stuff in the inserted text
+ and do not go into insertion mode. */
+ if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
+ {
+ _rl_vi_stuff_insert (count);
+ /* And back up point over the last character inserted. */
+ if (rl_point > 0)
+ rl_point--;
+ }
+ else
+ r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
+ vi_redoing = 0;
+
+ return (r);
+}
+
+/* A placeholder for further expansion. */
+int
+rl_vi_undo (count, key)
+ int count, key;
+{
+ return (rl_undo_command (count, key));
+}
+
+/* Yank the nth arg from the previous line into this line at point. */
+int
+rl_vi_yank_arg (count, key)
+ int count, key __attribute__((unused));
+{
+ /* Readline thinks that the first word on a line is the 0th, while vi
+ thinks the first word on a line is the 1st. Compensate. */
+ if (rl_explicit_arg)
+ rl_yank_nth_arg (count - 1, 0);
+ else
+ rl_yank_nth_arg ('$', 0);
+
+ return (0);
+}
+
+/* With an argument, move back that many history lines, else move to the
+ beginning of history. */
+int
+rl_vi_fetch_history (count, c)
+ int count, c;
+{
+ int wanted;
+
+ /* Giving an argument of n means we want the nth command in the history
+ file. The command number is interpreted the same way that the bash
+ `history' command does it -- that is, giving an argument count of 450
+ to this command would get the command listed as number 450 in the
+ output of `history'. */
+ if (rl_explicit_arg)
+ {
+ wanted = history_base + where_history () - count;
+ if (wanted <= 0)
+ rl_beginning_of_history (0, 0);
+ else
+ rl_get_previous_history (wanted, c);
+ }
+ else
+ rl_beginning_of_history (count, 0);
+ return (0);
+}
+
+/* Search again for the last thing searched for. */
+int
+rl_vi_search_again (count, key)
+ int count, key;
+{
+ switch (key)
+ {
+ case 'n':
+ rl_noninc_reverse_search_again (count, key);
+ break;
+
+ case 'N':
+ rl_noninc_forward_search_again (count, key);
+ break;
+ }
+ return (0);
+}
+
+/* Do a vi style search. */
+int
+rl_vi_search (count, key)
+ int count, key;
+{
+ switch (key)
+ {
+ case '?':
+ rl_noninc_forward_search (count, key);
+ break;
+
+ case '/':
+ rl_noninc_reverse_search (count, key);
+ break;
+
+ default:
+ rl_ding ();
+ break;
+ }
+ return (0);
+}
+
+/* Completion, from vi's point of view. */
+int
+rl_vi_complete (ignore, key)
+ int ignore __attribute__((unused)), key;
+{
+ if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+ {
+ if (!whitespace (rl_line_buffer[rl_point + 1]))
+ rl_vi_end_word (1, 'E');
+ rl_point++;
+ }
+
+ if (key == '*')
+ rl_complete_internal ('*'); /* Expansion and replacement. */
+ else if (key == '=')
+ rl_complete_internal ('?'); /* List possible completions. */
+ else if (key == '\\')
+ rl_complete_internal (TAB); /* Standard Readline completion. */
+ else
+ rl_complete (0, key);
+
+ if (key == '*' || key == '\\')
+ {
+ _rl_vi_set_last (key, 1, rl_arg_sign);
+ rl_vi_insertion_mode (1, key);
+ }
+ return (0);
+}
+
+/* Tilde expansion for vi mode. */
+int
+rl_vi_tilde_expand (ignore, key)
+ int ignore __attribute__((unused)), key;
+{
+ rl_tilde_expand (0, key);
+ _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
+ rl_vi_insertion_mode (1, key);
+ return (0);
+}
+
+/* Previous word in vi mode. */
+int
+rl_vi_prev_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_vi_next_word (-count, key));
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return (0);
+ }
+
+ if (_rl_uppercase_p (key))
+ rl_vi_bWord (count, key);
+ else
+ rl_vi_bword (count, key);
+
+ return (0);
+}
+
+/* Next word in vi mode. */
+int
+rl_vi_next_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_vi_prev_word (-count, key));
+
+ if (rl_point >= (rl_end - 1))
+ {
+ rl_ding ();
+ return (0);
+ }
+
+ if (_rl_uppercase_p (key))
+ rl_vi_fWord (count, key);
+ else
+ rl_vi_fword (count, key);
+ return (0);
+}
+
+/* Move to the end of the ?next? word. */
+int
+rl_vi_end_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (_rl_uppercase_p (key))
+ rl_vi_eWord (count, key);
+ else
+ rl_vi_eword (count, key);
+ return (0);
+}
+
+/* Move forward a word the way that 'W' does. */
+int
+rl_vi_fWord (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ while (count-- && rl_point < (rl_end - 1))
+ {
+ /* Skip until whitespace. */
+ while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+
+ /* Now skip whitespace. */
+ while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+ return (0);
+}
+
+int
+rl_vi_bWord (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ while (count-- && rl_point > 0)
+ {
+ /* If we are at the start of a word, move back to whitespace so
+ we will go back to the start of the previous word. */
+ if (!whitespace (rl_line_buffer[rl_point]) &&
+ whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ if (rl_point > 0)
+ {
+ while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
+ rl_point++;
+ }
+ }
+ return (0);
+}
+
+int
+rl_vi_eWord (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ while (count-- && rl_point < (rl_end - 1))
+ {
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ /* Move to the next non-whitespace character (to the start of the
+ next word). */
+ while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
+
+ if (rl_point && rl_point < rl_end)
+ {
+ /* Skip whitespace. */
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ /* Skip until whitespace. */
+ while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ /* Move back to the last character of the word. */
+ rl_point--;
+ }
+ }
+ return (0);
+}
+
+int
+rl_vi_fword (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ while (count-- && rl_point < (rl_end - 1))
+ {
+ /* Move to white space (really non-identifer). */
+ if (_rl_isident (rl_line_buffer[rl_point]))
+ {
+ while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+ else /* if (!whitespace (rl_line_buffer[rl_point])) */
+ {
+ while (!_rl_isident (rl_line_buffer[rl_point]) &&
+ !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+
+ /* Move past whitespace. */
+ while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+ return (0);
+}
+
+int
+rl_vi_bword (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ while (count-- && rl_point > 0)
+ {
+ int last_is_ident;
+
+ /* If we are at the start of a word, move back to whitespace
+ so we will go back to the start of the previous word. */
+ if (!whitespace (rl_line_buffer[rl_point]) &&
+ whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ /* If this character and the previous character are `opposite', move
+ back so we don't get messed up by the rl_point++ down there in
+ the while loop. Without this code, words like `l;' screw up the
+ function. */
+ last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
+ if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
+ (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
+ rl_point--;
+
+ while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ if (rl_point > 0)
+ {
+ if (_rl_isident (rl_line_buffer[rl_point]))
+ while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
+ else
+ while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
+ !whitespace (rl_line_buffer[rl_point]));
+ rl_point++;
+ }
+ }
+ return (0);
+}
+
+int
+rl_vi_eword (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ while (count-- && rl_point < rl_end - 1)
+ {
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ if (rl_point < rl_end)
+ {
+ if (_rl_isident (rl_line_buffer[rl_point]))
+ while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
+ else
+ while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
+ && !whitespace (rl_line_buffer[rl_point]));
+ }
+ rl_point--;
+ }
+ return (0);
+}
+
+int
+rl_vi_insert_beg (count, key)
+ int count __attribute__((unused)), key;
+{
+ rl_beg_of_line (1, key);
+ rl_vi_insertion_mode (1, key);
+ return (0);
+}
+
+int
+rl_vi_append_mode (count, key)
+ int count __attribute__((unused)), key;
+{
+ if (rl_point < rl_end)
+ {
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ rl_point++;
+ else
+ {
+ int point = rl_point;
+ rl_forward_char (1, key);
+ if (point == rl_point)
+ rl_point = rl_end;
+ }
+ }
+ rl_vi_insertion_mode (1, key);
+ return (0);
+}
+
+int
+rl_vi_append_eol (count, key)
+ int count __attribute__((unused)), key;
+{
+ rl_end_of_line (1, key);
+ rl_vi_append_mode (1, key);
+ return (0);
+}
+
+/* What to do in the case of C-d. */
+int
+rl_vi_eof_maybe (count, c)
+ int count __attribute__((unused)), c __attribute__((unused));
+{
+ return (rl_newline (1, '\n'));
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+ switching keymaps. */
+int
+rl_vi_insertion_mode (count, key)
+ int count __attribute__((unused)), key;
+{
+ _rl_keymap = vi_insertion_keymap;
+ _rl_vi_last_key_before_insert = key;
+ return (0);
+}
+
+static void
+_rl_vi_save_insert (up)
+ UNDO_LIST *up;
+{
+ int len, start, end;
+
+ if (up == 0)
+ {
+ if (vi_insert_buffer_size >= 1)
+ vi_insert_buffer[0] = '\0';
+ return;
+ }
+
+ start = up->start;
+ end = up->end;
+ len = end - start + 1;
+ if (len >= vi_insert_buffer_size)
+ {
+ vi_insert_buffer_size += (len + 32) - (len % 32);
+ vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
+ }
+ strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
+ vi_insert_buffer[len-1] = '\0';
+}
+
+void
+_rl_vi_done_inserting ()
+{
+ if (_rl_vi_doing_insert)
+ {
+ /* The `C', `s', and `S' commands set this. */
+ rl_end_undo_group ();
+ /* Now, the text between rl_undo_list->next->start and
+ rl_undo_list->next->end is what was inserted while in insert
+ mode. It gets copied to VI_INSERT_BUFFER because it depends
+ on absolute indices into the line which may change (though they
+ probably will not). */
+ _rl_vi_doing_insert = 0;
+ _rl_vi_save_insert (rl_undo_list->next);
+ vi_continued_command = 1;
+ }
+ else
+ {
+ if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
+ _rl_vi_save_insert (rl_undo_list);
+ /* XXX - Other keys probably need to be checked. */
+ else if (_rl_vi_last_key_before_insert == 'C')
+ rl_end_undo_group ();
+ while (_rl_undo_group_level > 0)
+ rl_end_undo_group ();
+ vi_continued_command = 0;
+ }
+}
+
+int
+rl_vi_movement_mode (count, key)
+ int count __attribute__((unused)), key;
+{
+ if (rl_point > 0)
+ rl_backward_char (1, key);
+
+ _rl_keymap = vi_movement_keymap;
+ _rl_vi_done_inserting ();
+ return (0);
+}
+
+int
+rl_vi_arg_digit (count, c)
+ int count, c;
+{
+ if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+ return (rl_beg_of_line (1, c));
+ else
+ return (rl_digit_argument (count, c));
+}
+
+/* Change the case of the next COUNT characters. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_vi_change_mbchar_case (count)
+ int count;
+{
+ wchar_t wc;
+ char mb[MB_LEN_MAX];
+ mbstate_t ps;
+
+ memset (&ps, 0, sizeof (mbstate_t));
+ if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
+ count--;
+ while (count-- && rl_point < rl_end)
+ {
+ mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
+ if (iswupper (wc))
+ wc = towlower (wc);
+ else if (iswlower (wc))
+ wc = towupper (wc);
+ else
+ {
+ /* Just skip over chars neither upper nor lower case */
+ rl_forward_char (1, 0);
+ continue;
+ }
+
+ /* Vi is kind of strange here. */
+ if (wc)
+ {
+ wctomb (mb, wc);
+ rl_begin_undo_group ();
+ rl_delete (1, 0);
+ rl_insert_text (mb);
+ rl_end_undo_group ();
+ rl_vi_check ();
+ }
+ else
+ rl_forward_char (1, 0);
+ }
+
+ return 0;
+}
+#endif
+
+int
+rl_vi_change_case (count, ignore)
+ int count, ignore __attribute__((unused));
+{
+ char c = 0;
+
+ /* Don't try this on an empty line. */
+ if (rl_point >= rl_end)
+ return (0);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ return (_rl_vi_change_mbchar_case (count));
+#endif
+
+ while (count-- && rl_point < rl_end)
+ {
+ if (_rl_uppercase_p (rl_line_buffer[rl_point]))
+ c = _rl_to_lower (rl_line_buffer[rl_point]);
+ else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
+ c = _rl_to_upper (rl_line_buffer[rl_point]);
+ else
+ {
+ /* Just skip over characters neither upper nor lower case. */
+ rl_forward_char (1, c);
+ continue;
+ }
+
+ /* Vi is kind of strange here. */
+ if (c)
+ {
+ rl_begin_undo_group ();
+ rl_delete (1, c);
+ _rl_insert_char (1, c);
+ rl_end_undo_group ();
+ rl_vi_check ();
+ }
+ else
+ rl_forward_char (1, c);
+ }
+ return (0);
+}
+
+int
+rl_vi_put (count, key)
+ int count __attribute__((unused)), key;
+{
+ if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
+ rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+
+ rl_yank (1, key);
+ rl_backward_char (1, key);
+ return (0);
+}
+
+int
+rl_vi_check ()
+{
+ if (rl_point && rl_point == rl_end)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ else
+ rl_point--;
+ }
+ return (0);
+}
+
+int
+rl_vi_column (count, key)
+ int count, key;
+{
+ if (count > rl_end)
+ rl_end_of_line (1, key);
+ else
+ rl_point = count - 1;
+ return (0);
+}
+
+int
+rl_vi_domove (key, nextkey)
+ int key, *nextkey;
+{
+ int c, save;
+ int old_end;
+
+ rl_mark = rl_point;
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ *nextkey = c;
+
+ if (!member (c, vi_motion))
+ {
+ if (_rl_digit_p (c))
+ {
+ save = rl_numeric_arg;
+ rl_numeric_arg = _rl_digit_value (c);
+ rl_digit_loop1 ();
+ rl_numeric_arg *= save;
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key (); /* real command */
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ *nextkey = c;
+ }
+ else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
+ {
+ rl_mark = rl_end;
+ rl_beg_of_line (1, c);
+ _rl_vi_last_motion = c;
+ return (0);
+ }
+ else
+ return (-1);
+ }
+
+ _rl_vi_last_motion = c;
+
+ /* Append a blank character temporarily so that the motion routines
+ work right at the end of the line. */
+ old_end = rl_end;
+ rl_line_buffer[rl_end++] = ' ';
+ rl_line_buffer[rl_end] = '\0';
+
+ _rl_dispatch (c, _rl_keymap);
+
+ /* Remove the blank that we added. */
+ rl_end = old_end;
+ rl_line_buffer[rl_end] = '\0';
+ if (rl_point > rl_end)
+ rl_point = rl_end;
+
+ /* No change in position means the command failed. */
+ if (rl_mark == rl_point)
+ return (-1);
+
+ /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
+ word. If we are not at the end of the line, and we are on a
+ non-whitespace character, move back one (presumably to whitespace). */
+ if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
+ !whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ /* If cw or cW, back up to the end of a word, so the behaviour of ce
+ or cE is the actual result. Brute-force, no subtlety. */
+ if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
+ {
+ /* Don't move farther back than where we started. */
+ while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ /* Posix.2 says that if cw or cW moves the cursor towards the end of
+ the line, the character under the cursor should be deleted. */
+ if (rl_point == rl_mark)
+ rl_point++;
+ else
+ {
+ /* Move past the end of the word so that the kill doesn't
+ remove the last letter of the previous word. Only do this
+ if we are not at the end of the line. */
+ if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+ }
+ }
+
+ if (rl_mark < rl_point)
+ SWAP (rl_point, rl_mark);
+
+ return (0);
+}
+
+/* A simplified loop for vi. Don't dispatch key at end.
+ Don't recognize minus sign?
+ Should this do rl_save_prompt/rl_restore_prompt? */
+static int
+rl_digit_loop1 ()
+{
+ int key, c;
+
+ RL_SETSTATE(RL_STATE_NUMERICARG);
+ while (1)
+ {
+ if (rl_numeric_arg > 1000000)
+ {
+ rl_explicit_arg = rl_numeric_arg = 0;
+ rl_ding ();
+ rl_clear_message ();
+ RL_UNSETSTATE(RL_STATE_NUMERICARG);
+ return 1;
+ }
+ rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ key = c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (c >= 0 && _rl_keymap[c].type == ISFUNC &&
+ _rl_keymap[c].function == rl_universal_argument)
+ {
+ rl_numeric_arg *= 4;
+ continue;
+ }
+
+ c = UNMETA (c);
+ if (_rl_digit_p (c))
+ {
+ if (rl_explicit_arg)
+ rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
+ else
+ rl_numeric_arg = _rl_digit_value (c);
+ rl_explicit_arg = 1;
+ }
+ else
+ {
+ rl_clear_message ();
+ rl_stuff_char (key);
+ break;
+ }
+ }
+
+ RL_UNSETSTATE(RL_STATE_NUMERICARG);
+ return (0);
+}
+
+int
+rl_vi_delete_to (count, key)
+ int count __attribute__((unused)), key;
+{
+ int c;
+
+ if (_rl_uppercase_p (key))
+ rl_stuff_char ('$');
+ else if (vi_redoing)
+ rl_stuff_char (_rl_vi_last_motion);
+
+ if (rl_vi_domove (key, &c))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ /* These are the motion commands that do not require adjusting the
+ mark. */
+ if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
+ rl_mark++;
+
+ rl_kill_text (rl_point, rl_mark);
+ return (0);
+}
+
+int
+rl_vi_change_to (count, key)
+ int count, key;
+{
+ int c, start_pos;
+
+ if (_rl_uppercase_p (key))
+ rl_stuff_char ('$');
+ else if (vi_redoing)
+ rl_stuff_char (_rl_vi_last_motion);
+
+ start_pos = rl_point;
+
+ if (rl_vi_domove (key, &c))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ /* These are the motion commands that do not require adjusting the
+ mark. c[wW] are handled by special-case code in rl_vi_domove(),
+ and already leave the mark at the correct location. */
+ if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
+ rl_mark++;
+
+ /* The cursor never moves with c[wW]. */
+ if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
+ rl_point = start_pos;
+
+ if (vi_redoing)
+ {
+ if (vi_insert_buffer && *vi_insert_buffer)
+ rl_begin_undo_group ();
+ rl_delete_text (rl_point, rl_mark);
+ if (vi_insert_buffer && *vi_insert_buffer)
+ {
+ rl_insert_text (vi_insert_buffer);
+ rl_end_undo_group ();
+ }
+ }
+ else
+ {
+ rl_begin_undo_group (); /* to make the `u' command work */
+ rl_kill_text (rl_point, rl_mark);
+ /* `C' does not save the text inserted for undoing or redoing. */
+ if (_rl_uppercase_p (key) == 0)
+ _rl_vi_doing_insert = 1;
+ _rl_vi_set_last (key, count, rl_arg_sign);
+ rl_vi_insertion_mode (1, key);
+ }
+
+ return (0);
+}
+
+int
+rl_vi_yank_to (count, key)
+ int count __attribute__((unused)), key;
+{
+ int c, save = rl_point;
+
+ if (_rl_uppercase_p (key))
+ rl_stuff_char ('$');
+
+ if (rl_vi_domove (key, &c))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ /* These are the motion commands that do not require adjusting the
+ mark. */
+ if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
+ rl_mark++;
+
+ rl_begin_undo_group ();
+ rl_kill_text (rl_point, rl_mark);
+ rl_end_undo_group ();
+ rl_do_undo ();
+ rl_point = save;
+
+ return (0);
+}
+
+int
+rl_vi_delete (count, key)
+ int count, key;
+{
+ int end;
+
+ if (rl_end == 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+ else
+ end = rl_point + count;
+
+ if (end >= rl_end)
+ end = rl_end;
+
+ rl_kill_text (rl_point, end);
+
+ if (rl_point > 0 && rl_point == rl_end)
+ rl_backward_char (1, key);
+ return (0);
+}
+
+int
+rl_vi_back_to_indent (count, key)
+ int count __attribute__((unused)), key;
+{
+ rl_beg_of_line (1, key);
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+ return (0);
+}
+
+int
+rl_vi_first_print (count, key)
+ int count __attribute__((unused)), key;
+{
+ return (rl_vi_back_to_indent (1, key));
+}
+
+int
+rl_vi_char_search (count, key)
+ int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+ static char *target;
+ static int mb_len;
+#else
+ static char target;
+#endif
+ static int orig_dir, dir;
+
+ if (key == ';' || key == ',')
+ dir = key == ';' ? orig_dir : -orig_dir;
+ else
+ {
+ if (vi_redoing)
+#if defined (HANDLE_MULTIBYTE)
+ target = _rl_vi_last_search_mbchar;
+#else
+ target = _rl_vi_last_search_char;
+#endif
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+ target = _rl_vi_last_search_mbchar;
+#else
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ _rl_vi_last_search_char = target = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+#endif
+ }
+
+ switch (key)
+ {
+ case 't':
+ orig_dir = dir = FTO;
+ break;
+
+ case 'T':
+ orig_dir = dir = BTO;
+ break;
+
+ case 'f':
+ orig_dir = dir = FFIND;
+ break;
+
+ case 'F':
+ orig_dir = dir = BFIND;
+ break;
+ }
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ return (_rl_char_search_internal (count, dir, target, mb_len));
+#else
+ return (_rl_char_search_internal (count, dir, target));
+#endif
+}
+
+/* Match brackets */
+int
+rl_vi_match (ignore, key)
+ int ignore __attribute__((unused)), key;
+{
+ int count = 1, brack, pos, tmp, pre;
+
+ pos = rl_point;
+ if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+ {
+ pre = rl_point;
+ rl_forward_char (1, key);
+ if (pre == rl_point)
+ break;
+ }
+ }
+ else
+ while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
+ rl_point < rl_end - 1)
+ rl_forward_char (1, key);
+
+ if (brack <= 0)
+ {
+ rl_point = pos;
+ rl_ding ();
+ return -1;
+ }
+ }
+
+ pos = rl_point;
+
+ if (brack < 0)
+ {
+ while (count)
+ {
+ tmp = pos;
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ pos--;
+ else
+ {
+ pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+ if (tmp == pos)
+ pos--;
+ }
+ if (pos >= 0)
+ {
+ int b = rl_vi_bracktype (rl_line_buffer[pos]);
+ if (b == -brack)
+ count--;
+ else if (b == brack)
+ count++;
+ }
+ else
+ {
+ rl_ding ();
+ return -1;
+ }
+ }
+ }
+ else
+ { /* brack > 0 */
+ while (count)
+ {
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ pos++;
+ else
+ pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
+
+ if (pos < rl_end)
+ {
+ int b = rl_vi_bracktype (rl_line_buffer[pos]);
+ if (b == -brack)
+ count--;
+ else if (b == brack)
+ count++;
+ }
+ else
+ {
+ rl_ding ();
+ return -1;
+ }
+ }
+ }
+ rl_point = pos;
+ return (0);
+}
+
+int
+rl_vi_bracktype (c)
+ int c;
+{
+ switch (c)
+ {
+ case '(': return 1;
+ case ')': return -1;
+ case '[': return 2;
+ case ']': return -2;
+ case '{': return 3;
+ case '}': return -3;
+ default: return 0;
+ }
+}
+
+/* XXX - think about reading an entire mbchar with _rl_read_mbchar and
+ inserting it in one bunch instead of the loop below (like in
+ rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0]
+ for test against 033 or ^C. Make sure that _rl_read_mbchar does
+ this right. */
+int
+rl_vi_change_char (count, key)
+ int count, key __attribute__((unused));
+{
+ int c;
+
+ if (vi_redoing)
+ c = _rl_vi_last_replacement;
+ else
+ {
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ _rl_vi_last_replacement = c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ }
+
+ if (c == '\033' || c == CTRL ('C'))
+ return -1;
+
+ while (count-- && rl_point < rl_end)
+ {
+ rl_begin_undo_group ();
+
+ rl_delete (1, c);
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ while (_rl_insert_char (1, c))
+ {
+ RL_SETSTATE (RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE (RL_STATE_MOREINPUT);
+ }
+ else
+#endif
+ _rl_insert_char (1, c);
+ if (count == 0)
+ rl_backward_char (1, c);
+
+ rl_end_undo_group ();
+ }
+ return (0);
+}
+
+int
+rl_vi_subst (count, key)
+ int count, key;
+{
+ /* If we are redoing, rl_vi_change_to will stuff the last motion char */
+ if (vi_redoing == 0)
+ rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */
+
+ return (rl_vi_change_to (count, 'c'));
+}
+
+int
+rl_vi_overstrike (count, key)
+ int count, key;
+{
+ if (_rl_vi_doing_insert == 0)
+ {
+ _rl_vi_doing_insert = 1;
+ rl_begin_undo_group ();
+ }
+
+ if (count > 0)
+ {
+ _rl_overwrite_char (count, key);
+ vi_replace_count += count;
+ }
+
+ return (0);
+}
+
+int
+rl_vi_overstrike_delete (count, key)
+ int count, key;
+{
+ int i, s;
+
+ for (i = 0; i < count; i++)
+ {
+ if (vi_replace_count == 0)
+ {
+ rl_ding ();
+ break;
+ }
+ s = rl_point;
+
+ if (rl_do_undo ())
+ vi_replace_count--;
+
+ if (rl_point == s)
+ rl_backward_char (1, key);
+ }
+
+ if (vi_replace_count == 0 && _rl_vi_doing_insert)
+ {
+ rl_end_undo_group ();
+ rl_do_undo ();
+ _rl_vi_doing_insert = 0;
+ }
+ return (0);
+}
+
+int
+rl_vi_replace (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ int i;
+
+ vi_replace_count = 0;
+
+ if (!vi_replace_map)
+ {
+ vi_replace_map = rl_make_bare_keymap ();
+
+ for (i = ' '; i < KEYMAP_SIZE; i++)
+ vi_replace_map[i].function = rl_vi_overstrike;
+
+ vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+ vi_replace_map[ESC].function = rl_vi_movement_mode;
+ vi_replace_map[RETURN].function = rl_newline;
+ vi_replace_map[NEWLINE].function = rl_newline;
+
+ /* If the normal vi insertion keymap has ^H bound to erase, do the
+ same here. Probably should remove the assignment to RUBOUT up
+ there, but I don't think it will make a difference in real life. */
+ if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
+ vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
+ vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
+
+ }
+ _rl_keymap = vi_replace_map;
+ return (0);
+}
+
+#if 0
+/* Try to complete the word we are standing on or the word that ends with
+ the previous character. A space matches everything. Word delimiters are
+ space and ;. */
+int
+rl_vi_possible_completions()
+{
+ int save_pos = rl_point;
+
+ if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
+ {
+ while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
+ rl_line_buffer[rl_point] != ';')
+ rl_point++;
+ }
+ else if (rl_line_buffer[rl_point - 1] == ';')
+ {
+ rl_ding ();
+ return (0);
+ }
+
+ rl_possible_completions ();
+ rl_point = save_pos;
+
+ return (0);
+}
+#endif
+
+/* Functions to save and restore marks. */
+int
+rl_vi_set_mark (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ int ch;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ ch = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (ch < 'a' || ch > 'z')
+ {
+ rl_ding ();
+ return -1;
+ }
+ ch -= 'a';
+ vi_mark_chars[ch] = rl_point;
+ return 0;
+}
+
+int
+rl_vi_goto_mark (count, key)
+ int count __attribute__((unused)), key __attribute__((unused));
+{
+ int ch;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ ch = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (ch == '`')
+ {
+ rl_point = rl_mark;
+ return 0;
+ }
+ else if (ch < 'a' || ch > 'z')
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ ch -= 'a';
+ if (vi_mark_chars[ch] == -1)
+ {
+ rl_ding ();
+ return -1;
+ }
+ rl_point = vi_mark_chars[ch];
+ return 0;
+}
+
+#endif /* VI_MODE */
diff --git a/cmd-line-utils/readline/xmalloc.c b/cmd-line-utils/readline/xmalloc.c
new file mode 100644
index 00000000000..8985d340d39
--- /dev/null
+++ b/cmd-line-utils/readline/xmalloc.c
@@ -0,0 +1,88 @@
+/* xmalloc.c -- safe versions of malloc and realloc */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GNU Readline, a library for reading lines
+ of text with interactive input and history editing.
+
+ Readline is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ Readline is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Readline; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/* */
+/* Memory Allocation and Deallocation. */
+/* */
+/* **************************************************************** */
+
+static void
+memory_error_and_abort (fname)
+ char *fname;
+{
+ fprintf (stderr, "%s: out of virtual memory\n", fname);
+ exit (2);
+}
+
+/* Return a pointer to free()able block of memory large enough
+ to hold BYTES number of bytes. If the memory cannot be allocated,
+ print an error message and abort. */
+PTR_T
+xmalloc (bytes)
+ size_t bytes;
+{
+ PTR_T temp;
+
+ temp = malloc (bytes);
+ if (temp == 0)
+ memory_error_and_abort ("xmalloc");
+ return (temp);
+}
+
+PTR_T
+xrealloc (pointer, bytes)
+ PTR_T pointer;
+ size_t bytes;
+{
+ PTR_T temp;
+
+ temp = pointer ? realloc (pointer, bytes) : malloc (bytes);
+
+ if (temp == 0)
+ memory_error_and_abort ("xrealloc");
+ return (temp);
+}
+
+/* Use this as the function to call when adding unwind protects so we
+ don't need to know what free() returns. */
+void
+xfree (string)
+ PTR_T string;
+{
+ if (string)
+ free (string);
+}
diff --git a/cmd-line-utils/readline/xmalloc.h b/cmd-line-utils/readline/xmalloc.h
new file mode 100644
index 00000000000..9cb08ba21f1
--- /dev/null
+++ b/cmd-line-utils/readline/xmalloc.h
@@ -0,0 +1,46 @@
+/* xmalloc.h -- memory allocation that aborts on errors. */
+
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline 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 2, or
+ (at your option) any later version.
+
+ The GNU Readline 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_XMALLOC_H_)
+#define _XMALLOC_H_
+
+#if defined (READLINE_LIBRARY)
+# include "rlstdc.h"
+#else
+# include <readline/rlstdc.h>
+#endif
+
+#ifndef PTR_T
+
+#ifdef __STDC__
+# define PTR_T void *
+#else
+# define PTR_T char *
+#endif
+
+#endif /* !PTR_T */
+
+extern PTR_T xmalloc PARAMS((size_t));
+extern PTR_T xrealloc PARAMS((void *, size_t));
+extern void xfree PARAMS((void *));
+
+#endif /* _XMALLOC_H_ */
diff --git a/configure.in b/configure.in
index d4f749d5de7..917ba9254a4 100644
--- a/configure.in
+++ b/configure.in
@@ -4,22 +4,19 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
-AM_INIT_AUTOMAKE(mysql, 4.0.11-gamma)
+AM_INIT_AUTOMAKE(mysql, 4.1.0-alpha)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
DOT_FRM_VERSION=6
# See the libtool docs for information on how to do shared lib versions.
-SHARED_LIB_VERSION=12:0:0
+SHARED_LIB_VERSION=14:0:0
# Set all version vars based on $VERSION. How do we do this more elegant ?
# Remember that regexps needs to quote [ and ] since this is run through m4
-MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|-.*$||"`
MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"`
MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"`
-F_PART=`echo $MYSQL_BASE_VERSION | sed -e "s|\.||g"| sed -e "s|[a-zA-Z]\+||"|sed -e "s|^\(..\)$|\\10|"`
-L_PART=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|^[[0-9]]\.[[0-9]]*\.||" | sed -e "s|^\(.\)$|0\\1|" | sed -e "s|[[a-z]]||"`
-MYSQL_VERSION_ID=${F_PART}${L_PART}
+MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION. | sed -e 's/\./ /g; s/ \([[0-9]]\) / 0\\1 /g; s/ //g'`
# The port should be constant for a LONG time
MYSQL_TCP_PORT_DEFAULT=3306
@@ -704,8 +701,11 @@ AC_SUBST(MYSQLD_USER)
# If we should allow LOAD DATA LOCAL
AC_MSG_CHECKING(If we should should enable LOAD DATA LOCAL by default)
AC_ARG_ENABLE(local-infile,
- [ --enable-local-infile Enable LOAD DATA LOCAL INFILE (default: disabled)],
- [ ENABLED_LOCAL_INFILE=$enableval ],
+ Enable LOAD DATA LOCAL INFILE (default: disabled)],
+ [
+ ENABLED_LOCAL_INFILE=$enableval
+ AC_DEFINE(ENABLED_LOCAL_INFILE)
+ ],
[ ENABLED_LOCAL_INFILE=no ]
)
if test "$ENABLED_LOCAL_INFILE" = "yes"
@@ -1729,8 +1729,37 @@ fi
MYSQL_PTHREAD_YIELD
######################################################################
-# For readline-4.0 (We simply move the mimimum amount of stuff from
-# the readline configure.in here)
+# For readline/libedit (We simply move the mimimum amount of stuff from
+# the readline/libedit configure.in here)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_AWK
+AC_PROG_INSTALL
+
+dnl Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(limits.h malloc.h sys/ioctl.h unistd.h sys/cdefs.h sys/types.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+dnl Checks for library functions.
+AC_FUNC_ALLOCA
+AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS(re_comp regcomp strdup strerror strstr strtol)
+
+AC_CHECK_HEADERS(vis.h)
+AC_CHECK_FUNCS(strlcat strlcpy)
+AC_CHECK_FUNCS(issetugid)
+AC_CHECK_FUNCS(fgetln)
+AC_CHECK_FUNCS(getline flockfile)
+
+# from old readline settting:
MAKE_SHELL=/bin/sh
AC_SUBST(MAKE_SHELL)
@@ -1760,7 +1789,7 @@ else
fi
AC_SUBST(TERMCAP_LIB)
-# End of readline stuff
+# End of readline/libedit stuff
#########################################################################
dnl Checks for library functions.
@@ -2144,26 +2173,71 @@ AC_SUBST(bench_dirs)
AC_ARG_WITH(readline,
[ --without-readline Use system readline instead of bundled copy.],
[ with_readline=$withval ],
- [ with_readline=yes ]
+ [ with_readline=undefined ]
)
+
+AC_ARG_WITH(libedit,
+ [ --without-libedit Use system libedit instead of bundled copy.],
+ [ with_libedit=$withval ],
+ [ with_libedit=undefined ]
+ )
+
+compile_readline= no
+compile_libedit= no
+
+if [test "$with_libedit" = "yes"] && [test "$with_readline" = "yes"]
+then
+ AC_MSG_ERROR([You can not use --with-readline and --with-libedit at the same time, please choose one of it])
+fi
+
+readline_topdir=""
+readline_basedir=""
+readline_dir=""
+readline_h_ln_cmd=""
+readline_link=""
+
if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
# For NetWare, do not need readline
- readline_dir=""
- readline_link=""
+ echo "Skipping readline"
else
-if test "$with_readline" = "yes"
-then
- readline_dir="readline"
- readline_link="\$(top_builddir)/readline/libreadline.a"
+mkdir include/readline
+
+if [test "$with_libedit" = "yes"] || [test "$with_libedit" = "undefined"] && [test "$with_readline" = "undefined"]
+then
+ readline_topdir="cmd-line-utils"
+ readline_basedir="libedit"
+ readline_dir="$readline_topdir/$readline_basedir"
+ readline_link="\$(top_builddir)/cmd-line-utils/libedit/liblibedit.a"
+ readline_h_ln_cmd="\$(LN) \$(top_builddir)/cmd-line-utils/libedit/readline/*.h readline/"
+ compile_libedit=yes
+ AC_DEFINE_UNQUOTED(USE_LIBEDIT_INTERFACE)
+elif test "$with_readline" = "yes"
+then
+ readline_topdir="cmd-line-utils"
+ readline_basedir="readline"
+ readline_dir="$readline_topdir/$readline_basedir"
+ readline_link="\$(top_builddir)/cmd-line-utils/readline/libreadline.a"
+ readline_h_ln_cmd="\$(LN) \$(top_builddir)/cmd-line-utils/readline/*.h readline/"
+ compile_readline=yes
+ AC_DEFINE_UNQUOTED(USE_NEW_READLINE_INTERFACE)
else
- # This requires readline to be in a standard place. Mosty for linux
- # there readline may be a shared library.
- readline_dir=""
- readline_link="-lreadline"
+ MYSQL_CHECK_LIBEDIT_INTERFACE
+ MYSQL_CHECK_NEW_RL_INTERFACE
+ if ["$mysql_cv_new_rl_interface"="yes"] || [test "$mysql_cv_libedit_interface"="no"]
+ then
+ readline_link="-lreadline"
+ else
+ readline_link="-ledit"
+ fi
fi
fi
+
AC_SUBST(readline_dir)
+AC_SUBST(readline_topdir)
+AC_SUBST(readline_basedir)
AC_SUBST(readline_link)
+AC_SUBST(readline_h_ln_cmd)
+
dnl In order to add new charset, you must add charset name to
dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.
@@ -2171,12 +2245,13 @@ dnl If the character set uses strcoll or other special handling,
dnl you must also create strings/ctype-$charset_name.c
AC_DIVERT_PUSH(0)
-CHARSETS_AVAILABLE="big5 cp1251 cp1257
- croat czech danish dec8 dos estonia euc_kr gb2312 gbk
- german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr
- latin1 latin1_de latin2 latin5 sjis swe7 tis620 ujis
- usa7 win1250 win1251ukr"
+CHARSETS_AVAILABLE="armscii8 big5 cp1251 cp1257
+ croat czech danish dec8 dos estonia euc_kr gb2312 gbk
+ german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr
+ latin1 latin1_de latin2 latin5 sjis swe7 tis620 ucs2 ujis
+ usa7 utf8 win1250 win1250ch win1251ukr"
CHARSETS_DEPRECATED="win1251"
+CHARSETS_COMPLEX="big5 czech euc_kr gb2312 gbk latin1_de sjis tis620 ucs2 ujis utf8 win1250ch"
DEFAULT_CHARSET=latin1
AC_DIVERT_POP
@@ -2207,208 +2282,151 @@ AC_MSG_CHECKING("character sets")
if test "$extra_charsets" = none; then
CHARSETS=""
elif test "$extra_charsets" = complex; then
- CHARSETS=`/bin/ls -1 $srcdir/strings/ctype-*.c | \
- sed -e 's;^.*/ctype-;;' -e 's;.c$;;'`
- CHARSETS=`echo $CHARSETS` # get rid of line breaks
+ CHARSETS="$CHARSETS_COMPLEX"
+elif test "$extra_charsets" = all; then
+ CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED"
else
- if test "$extra_charsets" = all; then
- CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED"
- else
- CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
- fi
+ CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
fi
-# Ensure that the default_charset is first in CHARSETS
-TMP_CHARSETS="$default_charset "
-for i in $CHARSETS
-do
- if test $i != $default_charset
- then
- TMP_CHARSETS="$TMP_CHARSETS $i"
- fi
-done
-CHARSETS=$TMP_CHARSETS
+CHARSETS="$DEFAULT_CHARSET $CHARSETS"
-# Check if charsets are all good
-for cs in $CHARSETS
-do
- charset_okay=0
- for charset in $CHARSETS_AVAILABLE $CHARSETS_DEPRECATED
- do
- if test $cs = $charset; then charset_okay=1; fi
- done
- if test $charset_okay = 0;
- then
- AC_MSG_ERROR([Charset $cs not available. (Available $CHARSETS_AVAILABLE).
- See the Installation chapter in the Reference Manual.]);
- fi
-done
-
-CHARSET_SRCS=""
-CHARSETS_NEED_SOURCE=""
-CHARSET_DECLARATIONS=""
-CHARSET_COMP_CS_INIT="CHARSET_INFO compiled_charsets[[]] = {"
+use_mb="no"
-want_use_strcoll=0
-want_use_mb=0
-
-index_file="$srcdir/sql/share/charsets/Index"
-
-for c in $CHARSETS
+for cs in $CHARSETS
do
- # get the charset number from $index_file
-changequote(,)dnl
- subpat='^'"${c}"'[ ][ ]*\([0-9][0-9]*\)[^0-9]*$'
- number=`sed -e "/$subpat/!d" -e 's//\1/' $index_file`
-changequote([,])dnl
- # some sanity checking....
- if test X"$number" = X
- then
- AC_MSG_ERROR([No number was found in $index_file for the $c character set. This is a bug in the MySQL distribution. Please report this message to bugs@lists.mysql.com.])
- fi
-
- cs_file="$srcdir/strings/ctype-$c.c"
- if test -f $cs_file
- then
- CHARSET_SRCS="${CHARSET_SRCS}ctype-$c.c "
- # get the strxfrm multiplier and max mb len from files
- subpat='^.*\\.configure\\. strxfrm_multiply_'"${c}"'='
- strx=`$AWK 'sub("'"$subpat"'", "") { print }' $cs_file`
- subpat='^.*\\.configure\\. mbmaxlen_'"${c}"'='
- maxl=`$AWK 'sub("'"$subpat"'", "") { print }' $cs_file`
-
- CHARSET_DECLARATIONS="$CHARSET_DECLARATIONS
-
-/* declarations for the ${c} character set, filled in by configure */
-extern uchar ctype_${c}[[]], to_lower_${c}[[]], to_upper_${c}[[]], sort_order_${c}[[]];"
- else
- CHARSETS_NEED_SOURCE="$CHARSETS_NEED_SOURCE $c"
- strx=''
- maxl=''
- fi
-
- CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
-
- /* this information is filled in by configure */
- {
- $number, /* number */
- \"$c\", /* name */
- ctype_${c},
- to_lower_${c},
- to_upper_${c},
- sort_order_${c},"
-
- if test -n "$strx"
- then
- want_use_strcoll=1
-
- CHARSET_DECLARATIONS="$CHARSET_DECLARATIONS
-extern int my_strcoll_${c}(const uchar *, const uchar *);
-extern int my_strxfrm_${c}(uchar *, const uchar *, int);
-extern int my_strnncoll_${c}(const uchar *, int, const uchar *, int);
-extern int my_strnxfrm_${c}(uchar *, const uchar *, int, int);
-extern my_bool my_like_range_${c}(const char *, uint, pchar, uint,
- char *, char *, uint *, uint *);"
-
- CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
- $strx, /* strxfrm_multiply */
- my_strcoll_${c},
- my_strxfrm_${c},
- my_strnncoll_${c},
- my_strnxfrm_${c},
- my_like_range_${c},"
- else
- CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
- 0, /* strxfrm_multiply */
- NULL, /* strcoll */
- NULL, /* strxfrm */
- NULL, /* strnncoll */
- NULL, /* strnxfrm */
- NULL, /* like_range */"
- fi
-
- if test -n "$maxl"
- then
- want_use_mb=1
-
- CHARSET_DECLARATIONS="$CHARSET_DECLARATIONS
-extern int ismbchar_${c}(const char *, const char *);
-extern my_bool ismbhead_${c}(uint);
-extern int mbcharlen_${c}(uint);"
-
-
- CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
- $maxl, /* mbmaxlen */
- ismbchar_${c},
- ismbhead_${c},
- mbcharlen_${c}"
- else
- CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
- 0, /* mbmaxlen */
- NULL, /* ismbchar */
- NULL, /* ismbhead */
- NULL /* mbcharlen */"
- fi
- CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
- },"
+ case $cs in
+ armscii8)
+ AC_DEFINE(HAVE_CHARSET_armscii8)
+ use_mb="yes"
+ ;;
+ big5)
+ AC_DEFINE(HAVE_CHARSET_big5)
+ use_mb="yes"
+ ;;
+ cp1251)
+ AC_DEFINE(HAVE_CHARSET_cp1251)
+ ;;
+ cp1257)
+ AC_DEFINE(HAVE_CHARSET_cp1257)
+ ;;
+ croat)
+ AC_DEFINE(HAVE_CHARSET_croat)
+ ;;
+ czech)
+ AC_DEFINE(HAVE_CHARSET_czech)
+ ;;
+ danish)
+ AC_DEFINE(HAVE_CHARSET_danish)
+ ;;
+ dec8)
+ AC_DEFINE(HAVE_CHARSET_dec8)
+ ;;
+ dos)
+ AC_DEFINE(HAVE_CHARSET_dos)
+ ;;
+ estonia)
+ AC_DEFINE(HAVE_CHARSET_estonia)
+ ;;
+ euc_kr)
+ AC_DEFINE(HAVE_CHARSET_euc_kr)
+ use_mb="yes"
+ ;;
+ gb2312)
+ AC_DEFINE(HAVE_CHARSET_gb2312)
+ use_mb="yes"
+ ;;
+ gbk)
+ AC_DEFINE(HAVE_CHARSET_gbk)
+ use_mb="yes"
+ ;;
+ german1)
+ AC_DEFINE(HAVE_CHARSET_german1)
+ ;;
+ greek)
+ AC_DEFINE(HAVE_CHARSET_greek)
+ ;;
+ hebrew)
+ AC_DEFINE(HAVE_CHARSET_hebrew)
+ ;;
+ hp8)
+ AC_DEFINE(HAVE_CHARSET_hp8)
+ ;;
+ hungarian)
+ AC_DEFINE(HAVE_CHARSET_hungarian)
+ ;;
+ koi8_ru)
+ AC_DEFINE(HAVE_CHARSET_koi8_ru)
+ ;;
+ koi8_ukr)
+ AC_DEFINE(HAVE_CHARSET_koi8_ukr)
+ ;;
+ latin1)
+ AC_DEFINE(HAVE_CHARSET_latin1)
+ ;;
+ latin1_de)
+ AC_DEFINE(HAVE_CHARSET_latin1_de)
+ ;;
+ latin2)
+ AC_DEFINE(HAVE_CHARSET_latin2)
+ ;;
+ latin5)
+ AC_DEFINE(HAVE_CHARSET_latin5)
+ ;;
+ sjis)
+ AC_DEFINE(HAVE_CHARSET_sjis)
+ use_mb="yes"
+ ;;
+ swe7)
+ AC_DEFINE(HAVE_CHARSET_swe7)
+ ;;
+ tis620)
+ AC_DEFINE(HAVE_CHARSET_tis620)
+ ;;
+ ucs2)
+ AC_DEFINE(HAVE_CHARSET_ucs2)
+ use_mb="yes"
+ ;;
+ ujis)
+ AC_DEFINE(HAVE_CHARSET_ujis)
+ use_mb="yes"
+ ;;
+ usa7)
+ AC_DEFINE(HAVE_CHARSET_usa7)
+ ;;
+ utf8)
+ AC_DEFINE(HAVE_CHARSET_utf8)
+ use_mb="yes"
+ ;;
+ win1250)
+ AC_DEFINE(HAVE_CHARSET_win1250)
+ ;;
+ win1250ch)
+ AC_DEFINE(HAVE_CHARSET_win1250ch)
+ ;;
+ win1251)
+ AC_DEFINE(HAVE_CHARSET_win1251)
+ ;;
+ win1251ukr)
+ AC_DEFINE(HAVE_CHARSET_win1251ukr)
+ ;;
+ *)
+ AC_MSG_ERROR([Charset $cs not available. (Available $CHARSETS_AVAILABLE).
+ See the Installation chapter in the Reference Manual.]);
+ esac
done
-CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
-
- /* this information is filled in by configure */
- {
- 0, /* end-of-list marker */
- NullS,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- NULL,
- NULL,
- NULL
- }
-};"
-
-
-if test $want_use_strcoll = 1
-then
- AC_DEFINE(USE_STRCOLL)
-fi
-
-if test $want_use_mb = 1
+dnl Always compile latin1
+AC_DEFINE(HAVE_CHARSET_latin1)
+
+if test "$use_mb" = "yes"
then
AC_DEFINE(USE_MB)
AC_DEFINE(USE_MB_IDENT)
fi
AC_SUBST(default_charset)
-AC_SUBST(CHARSET_SRCS)
-CHARSET_OBJS="`echo "$CHARSET_SRCS" | sed -e 's/\.c /.o /g'`"
-AC_SUBST(CHARSET_OBJS)
-AC_SUBST(CHARSETS_NEED_SOURCE)
-
-dnl We can't use AC_SUBST because these substitutions are too long.
-dnl I don't want to use sed, either, because there's a reason why
-dnl autoconf breaks up the substitution commands. So we'll just
-dnl write to a file and #include it.
-dnl AC_SUBST(CHARSET_DECLARATIONS)
-dnl AC_SUBST(CHARSET_COMP_CS_INIT)
-dnl sed -e "s%@CHARSET_DECLARATIONS@%$CHARSET_DECLARATIONS%g" \
-dnl -e "s%@CHARSET_COMP_CS_INIT@%$CHARSET_COMP_CS_INIT%g" \
-dnl $srcdir/strings/ctype.c.in > $srcdir/strings/ctype.c
-
-cat <<EOF > $srcdir/strings/ctype_autoconf.c
-/* This file is generated automatically by configure. */$CHARSET_DECLARATIONS
-
-$CHARSET_COMP_CS_INIT
-EOF
+AC_DEFINE_UNQUOTED(DEFAULT_CHARSET_NAME,"$default_charset")
AC_MSG_RESULT([default: $default_charset; compiled in: $CHARSETS])
@@ -2613,12 +2631,28 @@ AC_SUBST(GXX)
#AC_SUBST(TOOLS_LIBS)
# Output results
+
+if test "$compile_readline" = "yes"
+then
+ AC_OUTPUT(cmd-line-utils/readline/Makefile)
+fi
+
+if test "$compile_libedit" = "yes"
+then
+ AC_OUTPUT(cmd-line-utils/libedit/Makefile)
+fi
+
+if [test "$compile_libedit" = "yes"] || [test "$compile_readline" = "yes"]
+then
+ AC_OUTPUT(cmd-line-utils/Makefile)
+fi
+
AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl
strings/Makefile regex/Makefile heap/Makefile dnl
bdb/Makefile dnl
myisam/Makefile myisammrg/Makefile dnl
os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl
- man/Makefile BUILD/Makefile readline/Makefile vio/Makefile dnl
+ man/Makefile BUILD/Makefile vio/Makefile dnl
libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile dnl
libmysql/Makefile client/Makefile dnl
pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl
diff --git a/dbug/Makefile.am b/dbug/Makefile.am
index 08f0164c02c..bd512ee1d1d 100644
--- a/dbug/Makefile.am
+++ b/dbug/Makefile.am
@@ -15,7 +15,7 @@
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = libdbug.a ../strings/libmystrings.a
pkglib_LIBRARIES = libdbug.a
noinst_HEADERS = dbug_long.h
diff --git a/extra/Makefile.am b/extra/Makefile.am
index 8e4491969b5..8107beb2657 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -14,7 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I..
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
diff --git a/extra/mysql_install.c b/extra/mysql_install.c
index e2783f906b9..3f3da8cfb51 100644
--- a/extra/mysql_install.c
+++ b/extra/mysql_install.c
@@ -157,7 +157,7 @@ static int get_answer(QUESTION_WIDGET* w)
char c;
if (!fgets(buf,sizeof(buf),w->in))
die("Failed fgets on input stream");
- switch ((c=tolower(*buf)))
+ switch ((c=my_tolower(system_charset_info,*buf)))
{
case '\n':
return w->default_ind;
diff --git a/extra/replace.c b/extra/replace.c
index 41312f5e3d4..5826586988a 100644
--- a/extra/replace.c
+++ b/extra/replace.c
@@ -113,7 +113,7 @@ char *argv[];
exit(1);
for (i=1,pos=word_end_chars ; i < 256 ; i++)
- if (isspace(i))
+ if (my_isspace(system_charset_info,i))
*pos++=i;
*pos=0;
if (!(replace=init_replace((char**) from.typelib.type_names,
diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c
index c54f17a186e..f19ef467b5c 100644
--- a/extra/resolve_stack_dump.c
+++ b/extra/resolve_stack_dump.c
@@ -175,9 +175,9 @@ trace dump and specify the path to it with -s or --symbols-file");
static uchar hex_val(char c)
{
uchar l;
- if (isdigit(c))
+ if (my_isdigit(system_charset_info,c))
return c - '0';
- l = tolower(c);
+ l = my_tolower(system_charset_info,c);
if (l < 'a' || l > 'f')
return HEX_INVALID;
return (uchar)10 + ((uchar)c - (uchar)'a');
@@ -203,9 +203,11 @@ static int init_sym_entry(SYM_ENTRY* se, char* buf)
if (!se->addr)
return -1;
- while (isspace(*buf++)) ;
+ while (my_isspace(system_charset_info,*buf++))
+ /* empty */;
- while (isspace(*buf++)) ; /* skip more space */
+ while (my_isspace(system_charset_info,*buf++))
+ /* empty - skip more space */;
--buf;
/* now we are on the symbol */
for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
@@ -285,7 +287,8 @@ static void do_resolve()
while (fgets(buf, sizeof(buf), fp_dump))
{
p = buf;
- while(isspace(*p))
+ /* skip space */
+ while (my_isspace(system_charset_info,*p))
++p;
if (*p++ == '0' && *p++ == 'x')
diff --git a/extra/resolveip.c b/extra/resolveip.c
index 52d71d40a64..c9446b0fdf2 100644
--- a/extra/resolveip.c
+++ b/extra/resolveip.c
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
{
ip = *argv++;
- if (isdigit(ip[0]))
+ if (my_isdigit(system_charset_info,ip[0]))
{
taddr = inet_addr(ip);
if (taddr == htonl(INADDR_BROADCAST))
diff --git a/fs/Makefile.am b/fs/Makefile.am
index 33d1acd913d..6fea3d455a3 100644
--- a/fs/Makefile.am
+++ b/fs/Makefile.am
@@ -27,11 +27,8 @@ DISTCLEANFILES = CorbaFS-common.* CorbaFS-stubs.* CorbaFS-skels.* CorbaFS.h
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include \
- -I$(srcdir)/../regex \
- -I$(srcdir) -I../include -I.. -I. \
- -I$(srcdir) -I../include -I.. -I. \
- $(orbit_includes)
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/regex $(orbit_includes)
WRAPLIBS= @WRAPLIBS@
libexec_PROGRAMS = mysqlcorbafsd
noinst_PROGRAMS =mysqlfs_test
diff --git a/heap/Makefile.am b/heap/Makefile.am
index 41d98b79ae9..ec631148dce 100644
--- a/heap/Makefile.am
+++ b/heap/Makefile.am
@@ -14,7 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = libheap.a ../mysys/libmysys.a ../dbug/libdbug.a \
../strings/libmystrings.a
pkglib_LIBRARIES = libheap.a
diff --git a/heap/_check.c b/heap/_check.c
index 6cc19aba137..d4c4c26b346 100644
--- a/heap/_check.c
+++ b/heap/_check.c
@@ -20,6 +20,9 @@
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
ulong blength, my_bool print_status);
+static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
+ my_bool print_status);
+
/*
Check if keys and rows are ok in a heap table
@@ -37,7 +40,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
1 error
*/
-int heap_check_heap(HP_INFO *info,my_bool print_status)
+int heap_check_heap(HP_INFO *info, my_bool print_status)
{
int error;
uint key;
@@ -47,9 +50,13 @@ int heap_check_heap(HP_INFO *info,my_bool print_status)
DBUG_ENTER("heap_check_heap");
for (error=key= 0 ; key < share->keys ; key++)
- error|=check_one_key(share->keydef+key,key, share->records,share->blength,
- print_status);
-
+ {
+ if (share->keydef[key].algorithm == HA_KEY_ALG_BTREE)
+ error|= check_one_rb_key(info, key, share->records, print_status);
+ else
+ error|= check_one_key(share->keydef + key, key, share->records,
+ share->blength, print_status);
+ }
/*
This is basicly the same code as in hp_scan, but we repeat it here to
get shorter DBUG log file.
@@ -70,7 +77,7 @@ int heap_check_heap(HP_INFO *info,my_bool print_status)
break; /* End of file */
}
}
- _hp_find_record(info,pos);
+ hp_find_record(info,pos);
if (!info->current_ptr[share->reclength])
deleted++;
@@ -101,8 +108,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
for (i=found=max_links=seek=0 ; i < records ; i++)
{
hash_info=hp_find_hash(&keydef->block,i);
- if (_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
- blength,records) == i)
+ if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
+ blength,records) == i)
{
found++;
seek++;
@@ -110,8 +117,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
while ((hash_info=hash_info->next_key) && found < records + 1)
{
seek+= ++links;
- if ((rec_link=_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
- blength,records))
+ if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
+ blength, records))
!= i)
{
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
@@ -138,3 +145,44 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
(float) seek / (float) (records ? records : 1));
return error;
}
+
+static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
+ my_bool print_status)
+{
+ HP_KEYDEF *keydef= info->s->keydef + keynr;
+ int error= 0;
+ ulong found= 0;
+ byte *key, *recpos;
+ uint key_length;
+ uint not_used;
+
+ if ((key= tree_search_edge(&keydef->rb_tree, info->parents,
+ &info->last_pos, offsetof(TREE_ELEMENT, left))))
+ {
+ do
+ {
+ memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(byte*));
+ key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0);
+ if (ha_key_cmp(keydef->seg, info->recbuf, key, key_length,
+ SEARCH_FIND | SEARCH_SAME, &not_used))
+ {
+ error= 1;
+ DBUG_PRINT("error",("Record in wrong link: key: %d Record: %lx\n",
+ keynr, recpos));
+ }
+ else
+ found++;
+ key= tree_search_next(&keydef->rb_tree, &info->last_pos,
+ offsetof(TREE_ELEMENT, left),
+ offsetof(TREE_ELEMENT, right));
+ } while (key);
+ }
+ if (found != records)
+ {
+ DBUG_PRINT("error",("Found %lu of %lu records", found, records));
+ error= 1;
+ }
+ if (print_status)
+ printf("Key: %d records: %ld\n", keynr, records);
+ return error;
+}
diff --git a/heap/_rectest.c b/heap/_rectest.c
index 522940286fd..eb350263cec 100644
--- a/heap/_rectest.c
+++ b/heap/_rectest.c
@@ -19,9 +19,9 @@
#include "heapdef.h"
-int _hp_rectest(register HP_INFO *info, register const byte *old)
+int hp_rectest(register HP_INFO *info, register const byte *old)
{
- DBUG_ENTER("_hp_rectest");
+ DBUG_ENTER("hp_rectest");
if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
{
diff --git a/heap/heapdef.h b/heap/heapdef.h
index ef55cf5efd2..63109badb05 100644
--- a/heap/heapdef.h
+++ b/heap/heapdef.h
@@ -21,6 +21,7 @@
#include <my_pthread.h>
#endif
#include "heap.h" /* Structs & some defines */
+#include "my_tree.h"
/*
When allocating keys /rows in the internal block structure, do it
@@ -40,10 +41,10 @@ extern LIST *heap_open_list,*heap_share_list;
#define test_active(info) \
if (!(info->update & HA_STATE_AKTIV))\
{ my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
-#define hp_find_hash(A,B) ((HASH_INFO*) _hp_find_block((A),(B)))
+#define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B)))
/* Find pos for record and update it in info->current_ptr */
-#define _hp_find_record(info,pos) (info)->current_ptr= _hp_find_block(&(info)->s->block,pos)
+#define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos)
typedef struct st_hp_hash_info
{
@@ -51,40 +52,53 @@ typedef struct st_hp_hash_info
byte *ptr_to_rec;
} HASH_INFO;
+typedef struct {
+ HA_KEYSEG *keyseg;
+ uint key_length;
+ uint search_flag;
+} heap_rb_param;
+
/* Prototypes for intern functions */
-extern HP_SHARE *_hp_find_named_heap(const char *name);
-extern int _hp_rectest(HP_INFO *info,const byte *old);
-extern void _hp_delete_file_from_open_list(HP_INFO *info);
-extern byte *_hp_find_block(HP_BLOCK *info,ulong pos);
-extern int _hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
-extern void _hp_free(HP_SHARE *info);
-extern byte *_hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
- byte *last_pos);
-extern int _hp_write_key(HP_SHARE *info,HP_KEYDEF *keyinfo,
- const byte *record,byte *recpos);
-extern int _hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
- const byte *record,byte *recpos,int flag);
+extern HP_SHARE *hp_find_named_heap(const char *name);
+extern int hp_rectest(HP_INFO *info,const byte *old);
+extern byte *hp_find_block(HP_BLOCK *info,ulong pos);
+extern int hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
+extern void hp_free(HP_SHARE *info);
+extern byte *hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
+ byte *last_pos);
+extern int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
+ const byte *record, byte *recpos);
+extern int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
+ const byte *record, byte *recpos);
+extern int hp_rb_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
+ const byte *record,byte *recpos,int flag);
+extern int hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
+ const byte *record,byte *recpos,int flag);
extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
-extern byte *_hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
- uint nextflag);
-extern byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
- const byte *key,
- HASH_INFO *pos);
-extern ulong _hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
-extern ulong _hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
-extern ulong _hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
-extern void _hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
+extern byte *hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
+ uint nextflag);
+extern byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
+ const byte *key, HASH_INFO *pos);
+extern ulong hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
+extern ulong hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
+extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
+extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
HASH_INFO *newlink);
-extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
- const byte *rec2);
-extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
- const byte *key);
-extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
+extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
+ const byte *rec2);
+extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
+ const byte *key);
+extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
+extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
+ const byte *rec, byte *recpos);
+extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
+extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
-extern int _hp_close(register HP_INFO *info);
-extern void _hp_clear(HP_SHARE *info);
-
+extern int hp_close(register HP_INFO *info);
+extern void hp_clear(HP_SHARE *info);
+extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
+ uint k_len);
#ifdef THREAD
extern pthread_mutex_t THR_LOCK_heap;
#else
diff --git a/heap/hp_block.c b/heap/hp_block.c
index 5c052218e58..6a022fb3084 100644
--- a/heap/hp_block.c
+++ b/heap/hp_block.c
@@ -20,7 +20,7 @@
/* Find record according to record-position */
-byte *_hp_find_block(HP_BLOCK *block, ulong pos)
+byte *hp_find_block(HP_BLOCK *block, ulong pos)
{
reg1 int i;
reg3 HP_PTRS *ptr;
@@ -37,7 +37,7 @@ byte *_hp_find_block(HP_BLOCK *block, ulong pos)
/* get one new block-of-records. Alloc ptr to block if neaded */
/* Interrupts are stopped to allow ha_panic in interrupts */
-int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
+int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
{
reg1 uint i,j;
HP_PTRS *root;
@@ -84,7 +84,7 @@ int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
/* free all blocks under level */
-byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
+byte *hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
{
int i,max_pos;
byte *next_ptr;
@@ -99,7 +99,7 @@ byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
next_ptr=(byte*) (pos+1);
for (i=0 ; i < max_pos ; i++)
- next_ptr=_hp_free_level(block,level-1,
+ next_ptr=hp_free_level(block,level-1,
(HP_PTRS*) pos->blocks[i],next_ptr);
}
if ((byte*) pos != last_pos)
diff --git a/heap/hp_clear.c b/heap/hp_clear.c
index 2dcf91c03d7..e65d3a172c3 100644
--- a/heap/hp_clear.c
+++ b/heap/hp_clear.c
@@ -24,25 +24,33 @@
void heap_clear(HP_INFO *info)
{
- _hp_clear(info->s);
+ hp_clear(info->s);
}
-void _hp_clear(HP_SHARE *info)
+void hp_clear(HP_SHARE *info)
{
uint key;
- DBUG_ENTER("_hp_clear");
+ DBUG_ENTER("hp_clear");
if (info->block.levels)
- VOID(_hp_free_level(&info->block,info->block.levels,info->block.root,
+ VOID(hp_free_level(&info->block,info->block.levels,info->block.root,
(byte*) 0));
info->block.levels=0;
for (key=0 ; key < info->keys ; key++)
{
- HP_BLOCK *block= &info->keydef[key].block;
- if (block->levels)
- VOID(_hp_free_level(block,block->levels,block->root,(byte*) 0));
- block->levels=0;
- block->last_allocated=0;
+ HP_KEYDEF *keyinfo = info->keydef + key;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
+ {
+ delete_tree(&keyinfo->rb_tree);
+ }
+ else
+ {
+ HP_BLOCK *block= &keyinfo->block;
+ if (block->levels)
+ VOID(hp_free_level(block,block->levels,block->root,(byte*) 0));
+ block->levels=0;
+ block->last_allocated=0;
+ }
}
info->records=info->deleted=info->data_length=info->index_length=0;
info->blength=1;
diff --git a/heap/hp_close.c b/heap/hp_close.c
index 9e7d9ab31d1..3e0c9003ac8 100644
--- a/heap/hp_close.c
+++ b/heap/hp_close.c
@@ -26,16 +26,16 @@ int heap_close(HP_INFO *info)
int tmp;
DBUG_ENTER("heap_close");
pthread_mutex_lock(&THR_LOCK_heap);
- tmp= _hp_close(info);
+ tmp= hp_close(info);
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(tmp);
}
-int _hp_close(register HP_INFO *info)
+int hp_close(register HP_INFO *info)
{
int error=0;
- DBUG_ENTER("_hp_close");
+ DBUG_ENTER("hp_close");
#ifndef DBUG_OFF
if (info->s->changed && heap_check_heap(info,0))
{
@@ -45,7 +45,7 @@ int _hp_close(register HP_INFO *info)
info->s->changed=0;
heap_open_list=list_delete(heap_open_list,&info->open_list);
if (!--info->s->open_count && info->s->delete_on_close)
- _hp_free(info->s); /* Table was deleted */
+ hp_free(info->s); /* Table was deleted */
my_free((gptr) info,MYF(0));
DBUG_RETURN(error);
}
diff --git a/heap/hp_create.c b/heap/hp_create.c
index 1307fab1d12..5265607ce53 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -14,30 +14,181 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*
- Create is done by simply remove the database from memory if it exists.
- Open creates the database when neaded
-*/
-
#include "heapdef.h"
+static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
+static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
+ ulong max_records);
-int heap_create(const char *name)
+int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
+ uint reclength, ulong max_records, ulong min_records,
+ HP_CREATE_INFO *create_info)
{
- reg1 HP_SHARE *share;
+ uint i, j, key_segs, max_length, length;
+ HP_SHARE *share;
+ HA_KEYSEG *keyseg;
+
DBUG_ENTER("heap_create");
pthread_mutex_lock(&THR_LOCK_heap);
- if ((share=_hp_find_named_heap(name)))
+
+ if ((share= hp_find_named_heap(name)) && share->open_count == 0)
{
- if (share->open_count == 0)
- _hp_free(share);
+ hp_free(share);
+ share= NULL;
}
- else
+
+ if (!share)
{
- my_errno=ENOENT;
+ HP_KEYDEF *keyinfo;
+ DBUG_PRINT("info",("Initializing new table"));
+ for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
+ {
+ bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
+ bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree));
+ for (j= length= 0; j < keyinfo->keysegs; j++)
+ {
+ length+= keyinfo->seg[j].length;
+ if (keyinfo->seg[j].null_bit)
+ {
+ if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
+ keyinfo->flag|= HA_NULL_PART_KEY;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
+ keyinfo->rb_tree.size_of_element++;
+ }
+ switch (keyinfo->seg[j].type) {
+ case HA_KEYTYPE_SHORT_INT:
+ case HA_KEYTYPE_LONG_INT:
+ case HA_KEYTYPE_FLOAT:
+ case HA_KEYTYPE_DOUBLE:
+ case HA_KEYTYPE_USHORT_INT:
+ case HA_KEYTYPE_ULONG_INT:
+ case HA_KEYTYPE_LONGLONG:
+ case HA_KEYTYPE_ULONGLONG:
+ case HA_KEYTYPE_INT24:
+ case HA_KEYTYPE_UINT24:
+ case HA_KEYTYPE_INT8:
+ keyinfo->seg[j].flag|= HA_SWAP_KEY;
+ default:
+ break;
+ }
+ }
+ keyinfo->length= length;
+ length+= keyinfo->rb_tree.size_of_element +
+ ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(byte*) : 0);
+ if (length > max_length)
+ max_length= length;
+ key_segs+= keyinfo->keysegs;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
+ {
+ key_segs++; /* additional HA_KEYTYPE_END segment */
+ if (keyinfo->flag & HA_NULL_PART_KEY)
+ keyinfo->get_key_length= hp_rb_null_key_length;
+ else
+ keyinfo->get_key_length= hp_rb_key_length;
+ }
+ }
+ if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
+ keys*sizeof(HP_KEYDEF)+
+ key_segs*sizeof(HA_KEYSEG),
+ MYF(MY_ZEROFILL))))
+ {
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(1);
+ }
+ share->keydef= (HP_KEYDEF*) (share + 1);
+ keyseg= (HA_KEYSEG*) (share->keydef + keys);
+ init_block(&share->block, reclength + 1, min_records, max_records);
+ /* Fix keys */
+ memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
+ for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
+ {
+ keyinfo->seg= keyseg;
+ memcpy(keyseg, keydef[i].seg,
+ (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
+ keyseg+= keydef[i].keysegs;
+
+ if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
+ {
+ /* additional HA_KEYTYPE_END keyseg */
+ keyseg->type= HA_KEYTYPE_END;
+ keyseg->length= sizeof(byte*);
+ keyseg->flag= 0;
+ keyseg->null_bit= 0;
+ keyseg++;
+
+ init_tree(&keyinfo->rb_tree, 0, 0, sizeof(byte*),
+ (qsort_cmp2)keys_compare, 1, NULL, NULL);
+ keyinfo->delete_key= hp_rb_delete_key;
+ keyinfo->write_key= hp_rb_write_key;
+ }
+ else
+ {
+ init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
+ max_records);
+ keyinfo->delete_key= hp_delete_key;
+ keyinfo->write_key= hp_write_key;
+ }
+ }
+ share->min_records= min_records;
+ share->max_records= max_records;
+ share->data_length= share->index_length= 0;
+ share->reclength= reclength;
+ share->blength= 1;
+ share->keys= keys;
+ share->max_key_length= max_length;
+ share->changed= 0;
+ share->auto_key= create_info->auto_key;
+ share->auto_key_type= create_info->auto_key_type;
+ share->auto_increment= create_info->auto_increment;
+ /* Must be allocated separately for rename to work */
+ if (!(share->name= my_strdup(name,MYF(0))))
+ {
+ my_free((gptr) share,MYF(0));
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(1);
+ }
+#ifdef THREAD
+ thr_lock_init(&share->lock);
+ VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
+#endif
+ share->open_list.data= (void*) share;
+ heap_share_list= list_add(heap_share_list,&share->open_list);
}
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
+} /* heap_create */
+
+static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
+{
+ uint not_used;
+ return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
+ param->search_flag, &not_used);
+}
+
+static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
+ ulong max_records)
+{
+ uint i,recbuffer,records_in_block;
+
+ max_records= max(min_records,max_records);
+ if (!max_records)
+ max_records= 1000; /* As good as quess as anything */
+ recbuffer= (uint) (reclength + sizeof(byte**) - 1) & ~(sizeof(byte**) - 1);
+ records_in_block= max_records / 10;
+ if (records_in_block < 10 && max_records)
+ records_in_block= 10;
+ if (!records_in_block || records_in_block*recbuffer >
+ (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
+ records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
+ HP_MAX_LEVELS) / recbuffer + 1;
+ block->records_in_block= records_in_block;
+ block->recbuffer= recbuffer;
+ block->last_allocated= 0L;
+
+ for (i= 0; i <= HP_MAX_LEVELS; i++)
+ block->level_info[i].records_under_level=
+ (!i ? 1 : i == 1 ? records_in_block :
+ HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
}
int heap_delete_table(const char *name)
@@ -47,32 +198,31 @@ int heap_delete_table(const char *name)
DBUG_ENTER("heap_delete_table");
pthread_mutex_lock(&THR_LOCK_heap);
- if ((share=_hp_find_named_heap(name)))
+ if ((share= hp_find_named_heap(name)))
{
if (share->open_count == 0)
- _hp_free(share);
+ hp_free(share);
else
- share->delete_on_close=1;
- result=0;
+ share->delete_on_close= 1;
+ result= 0;
}
else
{
- result=my_errno=ENOENT;
+ result= my_errno=ENOENT;
}
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(result);
}
-
-void _hp_free(HP_SHARE *share)
+void hp_free(HP_SHARE *share)
{
- heap_share_list=list_delete(heap_share_list,&share->open_list);
- _hp_clear(share); /* Remove blocks from memory */
+ heap_share_list= list_delete(heap_share_list, &share->open_list);
+ hp_clear(share); /* Remove blocks from memory */
#ifdef THREAD
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->intern_lock));
#endif
- my_free((gptr) share->name,MYF(0));
- my_free((gptr) share,MYF(0));
+ my_free((gptr) share->name, MYF(0));
+ my_free((gptr) share, MYF(0));
return;
}
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index 6ed6a045543..73e431e6e66 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -20,25 +20,26 @@
int heap_delete(HP_INFO *info, const byte *record)
{
- uint key;
byte *pos;
HP_SHARE *share=info->s;
+ HP_KEYDEF *keydef, *end, *p_lastinx;
DBUG_ENTER("heap_delete");
DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
test_active(info);
- if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,record))
+ if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,record))
DBUG_RETURN(my_errno); /* Record changed */
share->changed=1;
if ( --(share->records) < share->blength >> 1) share->blength>>=1;
pos=info->current_ptr;
- for (key=0 ; key < share->keys ; key++)
+ p_lastinx = share->keydef + info->lastinx;
+ for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
+ keydef++)
{
- if (_hp_delete_key(info,share->keydef+key,record,pos,
- key == (uint) info->lastinx))
+ if ((*keydef->delete_key)(info, keydef, record, pos, keydef == p_lastinx))
goto err;
}
@@ -53,22 +54,39 @@ int heap_delete(HP_INFO *info, const byte *record)
#endif
DBUG_RETURN(0);
- err:
+err:
if (++(share->records) == share->blength)
share->blength+= share->blength;
DBUG_RETURN(my_errno);
}
+/*
+Remove one key from rb-tree
+*/
+int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
+ const byte *record, byte *recpos, int flag)
+{
+ heap_rb_param custom_arg;
+
+ if (flag)
+ info->last_pos= NULL; /* For heap_rnext/heap_rprev */
+
+ custom_arg.keyseg= keyinfo->seg;
+ custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
+ custom_arg.search_flag= SEARCH_SAME;
+ return tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg);
+}
+
/* Remove one key from hash-table */
/* Flag is set if we want's to correct info->current_ptr */
-int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
+int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
const byte *record, byte *recpos, int flag)
{
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
HP_SHARE *share=info->s;
- DBUG_ENTER("_hp_delete_key");
+ DBUG_ENTER("hp_delete_key");
blength=share->blength;
if (share->records+1 == blength)
@@ -78,13 +96,13 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
/* Search after record with key */
pos= hp_find_hash(&keyinfo->block,
- _hp_mask(_hp_rec_hashnr(keyinfo,record),blength,
- share->records+1));
+ hp_mask(hp_rec_hashnr(keyinfo, record), blength,
+ share->records + 1));
gpos = pos3 = 0;
while (pos->ptr_to_rec != recpos)
{
- if (flag && !_hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
+ if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
last_ptr=pos; /* Previous same key */
gpos=pos;
if (!(pos=pos->next_key))
@@ -117,33 +135,33 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
DBUG_RETURN (0);
/* Move the last key (lastpos) */
- lastpos_hashnr=_hp_rec_hashnr(keyinfo,lastpos->ptr_to_rec);
+ lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
/* pos is where lastpos should be */
- pos=hp_find_hash(&keyinfo->block,_hp_mask(lastpos_hashnr,share->blength,
+ pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
share->records));
if (pos == empty) /* Move to empty position. */
{
empty[0]=lastpos[0];
DBUG_RETURN(0);
}
- pos_hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
+ pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
/* pos3 is where the pos should be */
pos3= hp_find_hash(&keyinfo->block,
- _hp_mask(pos_hashnr,share->blength,share->records));
+ hp_mask(pos_hashnr, share->blength, share->records));
if (pos != pos3)
{ /* pos is on wrong posit */
empty[0]=pos[0]; /* Save it here */
pos[0]=lastpos[0]; /* This shold be here */
- _hp_movelink(pos,pos3,empty); /* Fix link to pos */
+ hp_movelink(pos, pos3, empty); /* Fix link to pos */
DBUG_RETURN(0);
}
- pos2= _hp_mask(lastpos_hashnr,blength,share->records+1);
- if (pos2 == _hp_mask(pos_hashnr,blength,share->records+1))
+ pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
+ if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
{ /* Identical key-positions */
if (pos2 != share->records)
{
empty[0]=lastpos[0];
- _hp_movelink(lastpos,pos,empty);
+ hp_movelink(lastpos, pos, empty);
DBUG_RETURN(0);
}
pos3= pos; /* Link pos->next after lastpos */
@@ -151,7 +169,7 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
else pos3= 0; /* Different positions merge */
empty[0]=lastpos[0];
- _hp_movelink(pos3,empty,pos->next_key);
+ hp_movelink(pos3, empty, pos->next_key);
pos->next_key=empty;
DBUG_RETURN(0);
}
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index e29e51d2b75..cd70d2ab532 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -19,30 +19,73 @@
#include "heapdef.h"
#include <m_ctype.h>
+ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
+ uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key, uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ ha_rows start_pos, end_pos;
+ HP_KEYDEF *keyinfo= info->s->keydef + inx;
+ TREE *rb_tree = &keyinfo->rb_tree;
+ heap_rb_param custom_arg;
+
+ info->lastinx= inx;
+ custom_arg.keyseg= keyinfo->seg;
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+ if (start_key)
+ {
+ custom_arg.key_length= hp_rb_pack_key(keyinfo, info->recbuf, start_key,
+ start_key_len);
+ start_pos= tree_record_pos(rb_tree, info->recbuf, start_search_flag,
+ &custom_arg);
+ }
+ else
+ {
+ start_pos= 0;
+ }
+
+ if (end_key)
+ {
+ custom_arg.key_length= hp_rb_pack_key(keyinfo, info->recbuf, end_key,
+ end_key_len);
+ end_pos= tree_record_pos(rb_tree, info->recbuf, end_search_flag,
+ &custom_arg);
+ }
+ else
+ {
+ end_pos= rb_tree->elements_in_tree + (ha_rows)1;
+ }
+
+ if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
+ return HA_POS_ERROR;
+ return end_pos < start_pos ? (ha_rows) 0 :
+ (end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos);
+}
+
/* Search after a record based on a key */
/* Sets info->current_ptr to found record */
/* next_flag: Search=0, next=1, prev =2, same =3 */
-byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
+byte *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
uint nextflag)
{
reg1 HASH_INFO *pos,*prev_ptr;
int flag;
uint old_nextflag;
HP_SHARE *share=info->s;
- DBUG_ENTER("_hp_search");
-
+ DBUG_ENTER("hp_search");
old_nextflag=nextflag;
flag=1;
prev_ptr=0;
if (share->records)
{
- pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_hashnr(keyinfo,key),
- share->blength,share->records));
+ pos=hp_find_hash(&keyinfo->block, hp_mask(hp_hashnr(keyinfo, key),
+ share->blength, share->records));
do
{
- if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
+ if (!hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
{
switch (nextflag) {
case 0: /* Search after key */
@@ -74,8 +117,8 @@ byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
{
flag=0; /* Reset flag */
if (hp_find_hash(&keyinfo->block,
- _hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
- share->blength,share->records)) != pos)
+ hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
+ share->blength, share->records)) != pos)
break; /* Wrong link */
}
}
@@ -102,14 +145,14 @@ byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
since last read !
*/
-byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
+byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
HASH_INFO *pos)
{
- DBUG_ENTER("_hp_search_next");
+ DBUG_ENTER("hp_search_next");
while ((pos= pos->next_key))
{
- if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
+ if (! hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
{
info->current_hash_ptr=pos;
DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
@@ -124,7 +167,7 @@ byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
/* Calculate pos according to keys */
-ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
+ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
{
if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
return (hashnr & ((buffmax >> 1) -1));
@@ -133,7 +176,7 @@ ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
/* Change link from pos to new_link */
-void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
+void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
{
HASH_INFO *old_link;
do
@@ -149,10 +192,11 @@ void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
/* Calc hashvalue for a key */
-ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
+ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
- register ulong nr=1, nr2=4;
- HP_KEYSEG *seg,*endseg;
+ /*register*/
+ ulong nr=1, nr2=4;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
@@ -170,12 +214,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- for (; pos < (uchar*) key ; pos++)
- {
- nr^=(ulong) ((((uint) nr & 63)+nr2) *
- ((uint) my_sort_order[(uint) *pos])) + (nr << 8);
- nr2+=3;
- }
+ seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,&nr2);
}
else
{
@@ -191,10 +230,11 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
/* Calc hashvalue for a key in a record */
-ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
+ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
- register ulong nr=1, nr2=4;
- HP_KEYSEG *seg,*endseg;
+ /*register*/
+ ulong nr=1, nr2=4;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
@@ -209,12 +249,7 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- for (; pos < end ; pos++)
- {
- nr^=(ulong) ((((uint) nr & 63)+nr2)*
- ((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
- nr2+=3;
- }
+ seg->charset->hash_sort(seg->charset,pos,end-pos,&nr,&nr2);
}
else
{
@@ -245,10 +280,10 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
* far, and works well on both numbers and strings.
*/
-ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
+ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
register ulong nr=0;
- HP_KEYSEG *seg,*endseg;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
@@ -266,11 +301,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- for (; pos < (uchar*) key ; pos++)
- {
- nr *=16777619;
- nr ^=((uint) my_sort_order[(uint) *pos]);
- }
+ seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
else
{
@@ -286,10 +317,10 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
/* Calc hashvalue for a key in a record */
-ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
+ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
register ulong nr=0;
- HP_KEYSEG *seg,*endseg;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
@@ -304,11 +335,7 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- for ( ; pos < end ; pos++)
- {
- nr *=16777619;
- nr ^=(uint) my_sort_order[(uint) *pos];
- }
+ seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
else
{
@@ -327,9 +354,9 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
/* Compare keys for two records. Returns 0 if they are identical */
-int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
+int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
{
- HP_KEYSEG *seg,*endseg;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
@@ -343,7 +370,7 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- if (my_sortcmp(rec1+seg->start,rec2+seg->start,seg->length))
+ if (my_strnncoll(seg->charset,rec1+seg->start,seg->length,rec2+seg->start,seg->length))
return 1;
}
else
@@ -357,9 +384,9 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
/* Compare a key in a record to a whole key */
-int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
+int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
{
- HP_KEYSEG *seg,*endseg;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
seg < endseg ;
@@ -375,7 +402,7 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- if (my_sortcmp(rec+seg->start,key,seg->length))
+ if (my_strnncoll(seg->charset,rec+seg->start,seg->length,key,seg->length))
return 1;
}
else
@@ -390,9 +417,9 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
/* Copy a key from a record to a keybuffer */
-void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
+void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
{
- HP_KEYSEG *seg,*endseg;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
@@ -403,7 +430,119 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
}
}
+uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
+ const byte *rec, byte *recpos)
+{
+ byte *start_key= key;
+ HA_KEYSEG *seg, *endseg;
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
+ {
+ if (seg->null_bit)
+ {
+ if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
+ continue;
+ }
+ if (seg->flag & HA_SWAP_KEY)
+ {
+ uint length= seg->length;
+ byte *pos= (byte*) rec + seg->start;
+
+#ifdef HAVE_ISNAN
+ if (seg->type == HA_KEYTYPE_FLOAT)
+ {
+ float nr;
+ float4get(nr, pos);
+ if (isnan(nr))
+ {
+ /* Replace NAN with zero */
+ bzero(key, length);
+ key+= length;
+ continue;
+ }
+ }
+ else if (seg->type == HA_KEYTYPE_DOUBLE)
+ {
+ double nr;
+ float8get(nr, pos);
+ if (isnan(nr))
+ {
+ bzero(key, length);
+ key+= length;
+ continue;
+ }
+ }
+#endif
+ pos+= length;
+ while (length--)
+ {
+ *key++= *--pos;
+ }
+ continue;
+ }
+ memcpy(key, rec + seg->start, (size_t) seg->length);
+ key+= seg->length;
+ }
+ memcpy(key, &recpos, sizeof(byte*));
+ return key - start_key;
+}
+
+uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
+{
+ HA_KEYSEG *seg, *endseg;
+ uchar *start_key= key;
+
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs;
+ seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
+ {
+ if (seg->null_bit)
+ {
+ k_len--;
+ if (!(*key++= (char) 1 - *old++))
+ {
+ k_len-= seg->length;
+ continue;
+ }
+ }
+ if (seg->flag & HA_SWAP_KEY)
+ {
+ uint length= seg->length;
+ byte *pos= (byte*) old + length;
+
+ k_len-= length;
+ while (length--)
+ {
+ *key++= *--pos;
+ }
+ continue;
+ }
+ memcpy((byte*) key, old, seg->length);
+ key+= seg->length;
+ k_len-= seg->length;
+ }
+ return key - start_key;
+}
+
+uint hp_rb_key_length(HP_KEYDEF *keydef,
+ const byte *key __attribute__((unused)))
+{
+ return keydef->length;
+}
+
+uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
+{
+ const byte *start_key= key;
+ HA_KEYSEG *seg, *endseg;
+
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
+ {
+ if (seg->null_bit && !*key++)
+ continue;
+ key+= seg->length;
+ }
+ return key - start_key;
+}
+
/*
Test if any of the key parts are NULL.
Return:
@@ -413,7 +552,7 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
{
- HP_KEYSEG *seg,*endseg;
+ HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
@@ -421,3 +560,51 @@ my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
}
return 0;
}
+
+void heap_update_auto_increment(HP_INFO *info, const byte *record)
+{
+ ulonglong value;
+ HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
+ const uchar *key= (uchar*) record + keyseg->start;
+
+ switch (info->s->auto_key_type) {
+ case HA_KEYTYPE_INT8:
+ case HA_KEYTYPE_BINARY:
+ value= (ulonglong) *(uchar*) key;
+ break;
+ case HA_KEYTYPE_SHORT_INT:
+ case HA_KEYTYPE_USHORT_INT:
+ value= (ulonglong) uint2korr(key);
+ break;
+ case HA_KEYTYPE_LONG_INT:
+ case HA_KEYTYPE_ULONG_INT:
+ value= (ulonglong) uint4korr(key);
+ break;
+ case HA_KEYTYPE_INT24:
+ case HA_KEYTYPE_UINT24:
+ value= (ulonglong) uint3korr(key);
+ break;
+ case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
+ {
+ float f_1;
+ float4get(f_1, key);
+ value= (ulonglong) f_1;
+ break;
+ }
+ case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
+ {
+ double f_1;
+ float8get(f_1, key);
+ value= (ulonglong) f_1;
+ break;
+ }
+ case HA_KEYTYPE_LONGLONG:
+ case HA_KEYTYPE_ULONGLONG:
+ value= uint8korr(key);
+ break;
+ default:
+ value= 0; /* Error */
+ break;
+ }
+ set_if_bigger(info->s->auto_increment, value);
+}
diff --git a/heap/hp_info.c b/heap/hp_info.c
index 3e9d6b6a90b..3122a665fac 100644
--- a/heap/hp_info.c
+++ b/heap/hp_info.c
@@ -55,5 +55,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x,
x->index_length= info->s->index_length;
x->max_records = info->s->max_records;
x->errkey = info->errkey;
+ if (flag & HA_STATUS_AUTO)
+ x->auto_increment= info->s->auto_increment + 1;
DBUG_RETURN(0);
} /* heap_info */
diff --git a/heap/hp_open.c b/heap/hp_open.c
index 1bb28e5ffdf..1fa832208fb 100644
--- a/heap/hp_open.c
+++ b/heap/hp_open.c
@@ -21,165 +21,72 @@
#include "hp_static.c" /* Stupid vms-linker */
#endif
-static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
- ulong max_records);
+#include "my_sys.h"
- /* open a heap database. */
-
-HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
- uint reclength, ulong max_records, ulong min_records)
+HP_INFO *heap_open(const char *name, int mode)
{
- uint i,j,key_segs,max_length,length;
HP_INFO *info;
HP_SHARE *share;
- HP_KEYSEG *keyseg;
- DBUG_ENTER("heap_open");
+ DBUG_ENTER("heap_open");
pthread_mutex_lock(&THR_LOCK_heap);
- if (!(share=_hp_find_named_heap(name)))
+ if (!(share= hp_find_named_heap(name)))
{
- DBUG_PRINT("info",("Initializing new table"));
- for (i=key_segs=max_length=0 ; i < keys ; i++)
- {
- key_segs+= keydef[i].keysegs;
- bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
- for (j=length=0 ; j < keydef[i].keysegs; j++)
- {
- length+=keydef[i].seg[j].length;
- if (keydef[i].seg[j].null_bit &&
- !(keydef[i].flag & HA_NULL_ARE_EQUAL))
- keydef[i].flag |= HA_NULL_PART_KEY;
- }
- keydef[i].length=length;
- if (length > max_length)
- max_length=length;
- }
- if (!(share = (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
- keys*sizeof(HP_KEYDEF)+
- key_segs*sizeof(HP_KEYSEG),
- MYF(MY_ZEROFILL))))
- {
- pthread_mutex_unlock(&THR_LOCK_heap);
- DBUG_RETURN(0);
- }
- share->keydef=(HP_KEYDEF*) (share+1);
- keyseg=(HP_KEYSEG*) (share->keydef+keys);
- init_block(&share->block,reclength+1,min_records,max_records);
- /* Fix keys */
- memcpy(share->keydef,keydef,(size_t) (sizeof(keydef[0])*keys));
- for (i=0 ; i < keys ; i++)
- {
- share->keydef[i].seg=keyseg;
- memcpy(keyseg,keydef[i].seg,
- (size_t) (sizeof(keyseg[0])*keydef[i].keysegs));
- keyseg+=keydef[i].keysegs;
- init_block(&share->keydef[i].block,sizeof(HASH_INFO),min_records,
- max_records);
- }
-
- share->min_records=min_records;
- share->max_records=max_records;
- share->data_length=share->index_length=0;
- share->reclength=reclength;
- share->blength=1;
- share->keys=keys;
- share->max_key_length=max_length;
- share->changed=0;
- if (!(share->name=my_strdup(name,MYF(0))))
- {
- my_free((gptr) share,MYF(0));
- pthread_mutex_unlock(&THR_LOCK_heap);
- DBUG_RETURN(0);
- }
-#ifdef THREAD
- thr_lock_init(&share->lock);
- VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
-#endif
- share->open_list.data=(void*) share;
- heap_share_list=list_add(heap_share_list,&share->open_list);
+ my_errno= ENOENT;
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(0);
}
- if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO)+
- share->max_key_length,
+ if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO) +
+ 2 * share->max_key_length,
MYF(MY_ZEROFILL))))
{
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
}
- share->open_count++;
+ share->open_count++;
#ifdef THREAD
thr_lock_data_init(&share->lock,&info->lock,NULL);
#endif
- info->open_list.data=(void*) info;
- heap_open_list=list_add(heap_open_list,&info->open_list);
+ info->open_list.data= (void*) info;
+ heap_open_list= list_add(heap_open_list,&info->open_list);
pthread_mutex_unlock(&THR_LOCK_heap);
- info->s=share;
- info->lastkey=(byte*) (info+1);
- info->mode=mode;
+ info->s= share;
+ info->lastkey= (byte*) (info + 1);
+ info->recbuf= (byte*) (info->lastkey + share->max_key_length);
+ info->mode= mode;
info->current_record= (ulong) ~0L; /* No current record */
- info->current_ptr=0;
- info->current_hash_ptr=0;
- info->lastinx= info->errkey= -1;
- info->update=0;
+ info->current_ptr= 0;
+ info->current_hash_ptr= 0;
+ info->lastinx= info->errkey= -1;
+ info->update= 0;
#ifndef DBUG_OFF
- info->opt_flag=READ_CHECK_USED; /* Check when changing */
+ info->opt_flag= READ_CHECK_USED; /* Check when changing */
#endif
DBUG_PRINT("exit",("heap: %lx reclength: %d records_in_block: %d",
info,share->reclength,share->block.records_in_block));
DBUG_RETURN(info);
-} /* heap_open */
-
+}
/* map name to a heap-nr. If name isn't found return 0 */
-HP_SHARE *_hp_find_named_heap(const char *name)
+HP_SHARE *hp_find_named_heap(const char *name)
{
LIST *pos;
HP_SHARE *info;
DBUG_ENTER("heap_find");
DBUG_PRINT("enter",("name: %s",name));
- for (pos=heap_share_list ; pos ; pos=pos->next)
+ for (pos= heap_share_list; pos; pos= pos->next)
{
- info=(HP_SHARE*) pos->data;
- if (!strcmp(name,info->name))
+ info= (HP_SHARE*) pos->data;
+ if (!strcmp(name, info->name))
{
- DBUG_PRINT("exit",("Old heap_database: %lx",info));
+ DBUG_PRINT("exit", ("Old heap_database: %lx",info));
DBUG_RETURN(info);
}
}
- DBUG_RETURN((HP_SHARE *)0);
+ DBUG_RETURN((HP_SHARE *) 0);
}
-static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
- ulong max_records)
-{
- uint i,recbuffer,records_in_block;
-
- max_records=max(min_records,max_records);
- if (!max_records)
- max_records=1000; /* As good as quess as anything */
- recbuffer=(uint) (reclength+sizeof(byte**)-1) & ~(sizeof(byte**)-1);
- records_in_block=max_records/10;
- if (records_in_block < HP_MIN_RECORDS_IN_BLOCK && max_records)
- records_in_block= HP_MIN_RECORDS_IN_BLOCK;
- /*
- Don't allocate too many rows at one time too keep memory consumption
- done when we don't need it.
- */
- if (records_in_block > HP_MAX_RECORDS_IN_BLOCK)
- records_in_block= HP_MAX_RECORDS_IN_BLOCK;
- if (!records_in_block || records_in_block*recbuffer >
- (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
- records_in_block=(my_default_record_cache_size-sizeof(HP_PTRS)*
- HP_MAX_LEVELS)/recbuffer+1;
- block->records_in_block=records_in_block;
- block->recbuffer=recbuffer;
- block->last_allocated= 0L;
-
- for (i=0 ; i <= HP_MAX_LEVELS ; i++)
- block->level_info[i].records_under_level=
- (!i ? 1 : i == 1 ? records_in_block :
- HP_PTRS_IN_NOD * block->level_info[i-1].records_under_level);
-}
diff --git a/heap/hp_panic.c b/heap/hp_panic.c
index 4b93190b7e1..2b659cbfbb3 100644
--- a/heap/hp_panic.c
+++ b/heap/hp_panic.c
@@ -31,7 +31,7 @@ int heap_panic(enum ha_panic_function flag)
next_open=element->next; /* Save if close */
switch (flag) {
case HA_PANIC_CLOSE:
- _hp_close(info);
+ hp_close(info);
break;
default:
break;
@@ -45,7 +45,7 @@ int heap_panic(enum ha_panic_function flag)
case HA_PANIC_CLOSE:
{
if (!share->open_count)
- _hp_free(share);
+ hp_free(share);
break;
}
default:
diff --git a/heap/hp_rename.c b/heap/hp_rename.c
index 118c5931f43..93906a66c37 100644
--- a/heap/hp_rename.c
+++ b/heap/hp_rename.c
@@ -27,7 +27,7 @@ int heap_rename(const char *old_name, const char *new_name)
DBUG_ENTER("heap_rename");
pthread_mutex_lock(&THR_LOCK_heap);
- if ((info=_hp_find_named_heap(old_name)))
+ if ((info = hp_find_named_heap(old_name)))
{
if (!(name_buff=(char*) my_strdup(new_name,MYF(MY_WME))))
{
diff --git a/heap/hp_rfirst.c b/heap/hp_rfirst.c
index 9a1f09244a0..1668376ed1c 100644
--- a/heap/hp_rfirst.c
+++ b/heap/hp_rfirst.c
@@ -18,11 +18,43 @@
/* Read first record with the current key */
-int heap_rfirst(HP_INFO *info, byte *record)
+int heap_rfirst(HP_INFO *info, byte *record, int inx)
{
+ HP_SHARE *share = info->s;
+ HP_KEYDEF *keyinfo = share->keydef + inx;
+
DBUG_ENTER("heap_rfirst");
- info->current_record=0;
- info->current_hash_ptr=0;
- info->update=HA_STATE_PREV_FOUND;
- DBUG_RETURN(heap_rnext(info,record));
+ info->lastinx= inx;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
+ {
+ byte *pos;
+
+ if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
+ &info->last_pos, offsetof(TREE_ELEMENT, left))))
+ {
+ memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
+ sizeof(byte*));
+ info->current_ptr = pos;
+ memcpy(record, pos, (size_t)share->reclength);
+ info->update = HA_STATE_AKTIV;
+ }
+ else
+ {
+ my_errno = HA_ERR_END_OF_FILE;
+ DBUG_RETURN(my_errno);
+ }
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ if (!(info->s->records))
+ {
+ my_errno=HA_ERR_END_OF_FILE;
+ DBUG_RETURN(my_errno);
+ }
+ info->current_record=0;
+ info->current_hash_ptr=0;
+ info->update=HA_STATE_PREV_FOUND;
+ DBUG_RETURN(heap_rnext(info,record));
+ }
}
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
index e7a1d81fba6..92d2982a457 100644
--- a/heap/hp_rkey.c
+++ b/heap/hp_rkey.c
@@ -16,29 +16,58 @@
#include "heapdef.h"
-int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
+int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
+ uint key_len, enum ha_rkey_function find_flag)
{
byte *pos;
- HP_SHARE *share=info->s;
+ HP_SHARE *share= info->s;
+ HP_KEYDEF *keyinfo= share->keydef + inx;
DBUG_ENTER("heap_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
if ((uint) inx >= share->keys)
{
- DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
+ DBUG_RETURN(my_errno= HA_ERR_WRONG_INDEX);
}
- info->lastinx=inx;
- info->current_record = (ulong) ~0L; /* For heap_rrnd() */
+ info->lastinx= inx;
+ info->current_record= (ulong) ~0L; /* For heap_rrnd() */
- if (!(pos=_hp_search(info,share->keydef+inx,key,0)))
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
- info->update=0;
- DBUG_RETURN(my_errno);
+ heap_rb_param custom_arg;
+
+ custom_arg.keyseg= info->s->keydef[inx].seg;
+ custom_arg.key_length= info->lastkey_len=
+ hp_rb_pack_key(keyinfo, info->recbuf, key, key_len);
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+ /* for next rkey() after deletion */
+ if (find_flag == HA_READ_AFTER_KEY)
+ info->last_find_flag= HA_READ_KEY_OR_NEXT;
+ else if (find_flag == HA_READ_BEFORE_KEY)
+ info->last_find_flag= HA_READ_KEY_OR_PREV;
+ else
+ info->last_find_flag= find_flag;
+ if (!(pos= tree_search_key(&keyinfo->rb_tree, info->recbuf, info->parents,
+ &info->last_pos, find_flag, &custom_arg)))
+ {
+ info->update= 0;
+ DBUG_RETURN(my_errno= HA_ERR_KEY_NOT_FOUND);
+ }
+ memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), sizeof(byte*));
+ info->current_ptr= pos;
+ }
+ else
+ {
+ if (!(pos= hp_search(info, share->keydef + inx, key, 0)))
+ {
+ info->update= 0;
+ DBUG_RETURN(my_errno);
+ }
+ if (!(keyinfo->flag & HA_NOSAME))
+ memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
- memcpy(record,pos,(size_t) share->reclength);
- info->update=HA_STATE_AKTIV;
- if (!(share->keydef[inx].flag & HA_NOSAME))
- memcpy(info->lastkey,key,(size_t) share->keydef[inx].length);
+ memcpy(record, pos, (size_t) share->reclength);
+ info->update= HA_STATE_AKTIV;
DBUG_RETURN(0);
}
@@ -47,5 +76,5 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
gptr heap_find(HP_INFO *info, int inx, const byte *key)
{
- return _hp_search(info,info->s->keydef+inx,key,0);
+ return hp_search(info, info->s->keydef + inx, key, 0);
}
diff --git a/heap/hp_rlast.c b/heap/hp_rlast.c
index 463b6dc9aac..b1a49739108 100644
--- a/heap/hp_rlast.c
+++ b/heap/hp_rlast.c
@@ -19,11 +19,38 @@
/* Read first record with the current key */
-int heap_rlast(HP_INFO *info, byte *record)
+int heap_rlast(HP_INFO *info, byte *record, int inx)
{
+ HP_SHARE *share= info->s;
+ HP_KEYDEF *keyinfo= share->keydef + inx;
+
DBUG_ENTER("heap_rlast");
- info->current_ptr=0;
- info->current_hash_ptr=0;
- info->update=HA_STATE_NEXT_FOUND;
- DBUG_RETURN(heap_rprev(info,record));
+ info->lastinx= inx;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
+ {
+ byte *pos;
+
+ if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
+ &info->last_pos, offsetof(TREE_ELEMENT, right))))
+ {
+ memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
+ sizeof(byte*));
+ info->current_ptr = pos;
+ memcpy(record, pos, (size_t)share->reclength);
+ info->update = HA_STATE_AKTIV;
+ }
+ else
+ {
+ my_errno = HA_ERR_END_OF_FILE;
+ DBUG_RETURN(my_errno);
+ }
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ info->current_ptr=0;
+ info->current_hash_ptr=0;
+ info->update=HA_STATE_NEXT_FOUND;
+ DBUG_RETURN(heap_rprev(info,record));
+ }
}
diff --git a/heap/hp_rnext.c b/heap/hp_rnext.c
index af08a0e68a2..a1bc480333e 100644
--- a/heap/hp_rnext.c
+++ b/heap/hp_rnext.c
@@ -22,27 +22,58 @@ int heap_rnext(HP_INFO *info, byte *record)
{
byte *pos;
HP_SHARE *share=info->s;
+ HP_KEYDEF *keyinfo;
DBUG_ENTER("heap_rnext");
if (info->lastinx < 0)
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
- if (info->current_hash_ptr)
- pos= _hp_search_next(info,share->keydef+info->lastinx, info->lastkey,
- info->current_hash_ptr);
- else
+ keyinfo = share->keydef + info->lastinx;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
- if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
+ heap_rb_param custom_arg;
+
+ if (info->last_pos)
+ pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
+ offsetof(TREE_ELEMENT, left),
+ offsetof(TREE_ELEMENT, right));
+ else
+ {
+ custom_arg.keyseg = keyinfo->seg;
+ custom_arg.key_length = info->lastkey_len;
+ custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
+ pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
+ &info->last_pos, info->last_find_flag, &custom_arg);
+ }
+ if (pos)
+ {
+ memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
+ sizeof(byte*));
+ info->current_ptr = pos;
+ }
+ else
{
- pos=0; /* Read next after last */
- my_errno=HA_ERR_KEY_NOT_FOUND;
+ my_errno = HA_ERR_KEY_NOT_FOUND;
}
- else if (!info->current_ptr) /* Deleted or first call */
- pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 0);
+ }
+ else
+ {
+ if (info->current_hash_ptr)
+ pos= hp_search_next(info, keyinfo, info->lastkey,
+ info->current_hash_ptr);
else
- pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 1);
+ {
+ if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
+ {
+ pos=0; /* Read next after last */
+ my_errno=HA_ERR_KEY_NOT_FOUND;
+ }
+ else if (!info->current_ptr) /* Deleted or first call */
+ pos= hp_search(info, keyinfo, info->lastkey, 0);
+ else
+ pos= hp_search(info, keyinfo, info->lastkey, 1);
+ }
}
-
if (!pos)
{
info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */
diff --git a/heap/hp_rprev.c b/heap/hp_rprev.c
index c7c649e6b9f..d8f5c01dcea 100644
--- a/heap/hp_rprev.c
+++ b/heap/hp_rprev.c
@@ -23,22 +23,53 @@ int heap_rprev(HP_INFO *info, byte *record)
{
byte *pos;
HP_SHARE *share=info->s;
+ HP_KEYDEF *keyinfo;
DBUG_ENTER("heap_rprev");
if (info->lastinx < 0)
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
-
- if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
+ keyinfo = share->keydef + info->lastinx;
+ if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
- if ((info->update & HA_STATE_DELETED))
- pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 3);
+ heap_rb_param custom_arg;
+
+ if (info->last_pos)
+ pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
+ offsetof(TREE_ELEMENT, right),
+ offsetof(TREE_ELEMENT, left));
else
- pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 2);
+ {
+ custom_arg.keyseg = keyinfo->seg;
+ custom_arg.key_length = keyinfo->length;
+ custom_arg.search_flag = SEARCH_SAME;
+ pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
+ &info->last_pos, info->last_find_flag, &custom_arg);
+ }
+ if (pos)
+ {
+ memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
+ sizeof(byte*));
+ info->current_ptr = pos;
+ }
+ else
+ {
+ my_errno = HA_ERR_KEY_NOT_FOUND;
+ }
}
else
{
- pos=0; /* Read next after last */
- my_errno=HA_ERR_KEY_NOT_FOUND;
+ if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
+ {
+ if ((info->update & HA_STATE_DELETED))
+ pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 3);
+ else
+ pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 2);
+ }
+ else
+ {
+ pos=0; /* Read next after last */
+ my_errno=HA_ERR_KEY_NOT_FOUND;
+ }
}
if (!pos)
{
diff --git a/heap/hp_rrnd.c b/heap/hp_rrnd.c
index 78abebcaf47..cce3ce24e51 100644
--- a/heap/hp_rrnd.c
+++ b/heap/hp_rrnd.c
@@ -88,7 +88,7 @@ int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
}
/* Find record number pos */
- _hp_find_record(info,pos);
+ hp_find_record(info, pos);
end:
if (!info->current_ptr[share->reclength])
diff --git a/heap/hp_rsame.c b/heap/hp_rsame.c
index a346707641b..6a375753b1a 100644
--- a/heap/hp_rsame.c
+++ b/heap/hp_rsame.c
@@ -41,8 +41,8 @@ int heap_rsame(register HP_INFO *info, byte *record, int inx)
else if (inx != -1)
{
info->lastinx=inx;
- _hp_make_key(share->keydef+inx,info->lastkey,record);
- if (!_hp_search(info,share->keydef+inx,info->lastkey,3))
+ hp_make_key(share->keydef + inx, info->lastkey, record);
+ if (!hp_search(info, share->keydef + inx, info->lastkey, 3))
{
info->update=0;
DBUG_RETURN(my_errno);
diff --git a/heap/hp_scan.c b/heap/hp_scan.c
index 0bbe40ba773..59e544ca590 100644
--- a/heap/hp_scan.c
+++ b/heap/hp_scan.c
@@ -58,7 +58,7 @@ int heap_scan(register HP_INFO *info, byte *record)
DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
}
}
- _hp_find_record(info,pos);
+ hp_find_record(info, pos);
}
if (!info->current_ptr[share->reclength])
{
diff --git a/heap/hp_test1.c b/heap/hp_test1.c
index e07af2761f0..2e0a57a12d3 100644
--- a/heap/hp_test1.c
+++ b/heap/hp_test1.c
@@ -36,25 +36,31 @@ int main(int argc, char **argv)
char record[128],key[32];
const char *filename;
HP_KEYDEF keyinfo[10];
- HP_KEYSEG keyseg[4];
+ HA_KEYSEG keyseg[4];
+ HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]);
filename= "test1";
get_options(argc,argv);
+ bzero(&hp_create_info, sizeof(hp_create_info));
+
keyinfo[0].keysegs=1;
keyinfo[0].seg=keyseg;
+ keyinfo[0].algorithm= HA_KEY_ALG_HASH;
keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[0].seg[0].start=1;
keyinfo[0].seg[0].length=6;
+ keyinfo[0].seg[0].charset=default_charset_info;
keyinfo[0].flag = HA_NOSAME;
-
+
deleted=0;
bzero((gptr) flags,sizeof(flags));
printf("- Creating heap-file\n");
- heap_create(filename);
- if (!(file=heap_open(filename,2,1,keyinfo,30,(ulong) flag*100000l,10l)))
+ if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l,
+ &hp_create_info) ||
+ !(file= heap_open(filename, 2)))
goto err;
printf("- Writing records:s\n");
strmov(record," ..... key ");
@@ -77,7 +83,7 @@ int main(int argc, char **argv)
if (heap_close(file))
goto err;
printf("- Reopening file\n");
- if (!(file=heap_open(filename,2,1,keyinfo,30,(ulong) flag*100000l,10l)))
+ if (!(file=heap_open(filename, 2)))
goto err;
printf("- Removing records\n");
@@ -85,7 +91,7 @@ int main(int argc, char **argv)
{
if (i == remove_ant) { VOID(heap_close(file)) ; return (0) ; }
sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
- if ((error = heap_rkey(file,record,0,key)))
+ if ((error = heap_rkey(file,record,0,key,0,6)))
{
if (verbose || (flags[j] == 1 ||
(error && my_errno != HA_ERR_KEY_NOT_FOUND)))
@@ -113,7 +119,7 @@ int main(int argc, char **argv)
sprintf(key,"%6d",i);
bmove(record+1,key,6);
my_errno=0;
- error=heap_rkey(file,record,0,key);
+ error=heap_rkey(file,record,0,key,0,6);
if (verbose ||
(error == 0 && flags[i] != 1) ||
(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
diff --git a/heap/hp_test2.c b/heap/hp_test2.c
index e2570893519..73e8039d125 100644
--- a/heap/hp_test2.c
+++ b/heap/hp_test2.c
@@ -26,7 +26,7 @@
#define SAFEMALLOC
#endif
-#include "heapdef.h" /* Because of _hp_find_block */
+#include "heapdef.h" /* Because of hp_find_block */
#include <signal.h>
#define MAX_RECORDS 100000
@@ -61,8 +61,9 @@ int main(int argc, char *argv[])
const char *filename,*filename2;
HP_INFO *file,*file2;
HP_KEYDEF keyinfo[MAX_KEYS];
- HP_KEYSEG keyseg[MAX_KEYS*5];
+ HA_KEYSEG keyseg[MAX_KEYS*5];
HEAP_PTR position;
+ HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]); /* init my_sys library & pthreads */
LINT_INIT(position);
@@ -70,6 +71,8 @@ int main(int argc, char *argv[])
filename2= "test2_2";
file=file2=0;
get_options(argc,argv);
+
+ bzero(&hp_create_info, sizeof(hp_create_info));
write_count=update=opt_delete=0;
key_check=0;
@@ -77,45 +80,53 @@ int main(int argc, char *argv[])
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
keyinfo[0].flag= 0;
+ keyinfo[0].algorithm= HA_KEY_ALG_HASH;
keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[0].seg[0].start=0;
keyinfo[0].seg[0].length=6;
keyinfo[0].seg[0].null_bit=0;
+ keyinfo[0].seg[0].charset=default_charset_info;
keyinfo[1].seg=keyseg+1;
keyinfo[1].keysegs=2;
keyinfo[1].flag=0;
+ keyinfo[1].algorithm= HA_KEY_ALG_HASH;
keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[1].seg[0].start=7;
keyinfo[1].seg[0].length=6;
keyinfo[1].seg[0].null_bit=0;
+ keyinfo[1].seg[0].charset=default_charset_info;
keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
keyinfo[1].seg[1].start=0; /* key in two parts */
keyinfo[1].seg[1].length=6;
keyinfo[1].seg[1].null_bit=0;
+ keyinfo[1].seg[1].charset=default_charset_info;
keyinfo[2].seg=keyseg+3;
keyinfo[2].keysegs=1;
keyinfo[2].flag=HA_NOSAME;
+ keyinfo[2].algorithm= HA_KEY_ALG_HASH;
keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[2].seg[0].start=12;
keyinfo[2].seg[0].length=8;
keyinfo[2].seg[0].null_bit=0;
+ keyinfo[2].seg[0].charset=default_charset_info;
+ keyinfo[3].seg=keyseg+4;
keyinfo[3].keysegs=1;
keyinfo[3].flag=HA_NOSAME;
- keyinfo[3].seg=keyseg+4;
+ keyinfo[3].algorithm= HA_KEY_ALG_HASH;
keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[3].seg[0].start=37;
keyinfo[3].seg[0].length=1;
keyinfo[3].seg[0].null_bit=1;
keyinfo[3].seg[0].null_pos=38;
+ keyinfo[3].seg[0].charset=default_charset_info;
bzero((char*) key1,sizeof(key1));
bzero((char*) key3,sizeof(key3));
printf("- Creating heap-file\n");
- if (heap_create(filename))
- goto err;
- if (!(file=heap_open(filename,2,keys,keyinfo,reclength,(ulong) flag*100000L,
- (ulong) recant/2)))
+ if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L,
+ (ulong) recant/2, &hp_create_info) ||
+ !(file= heap_open(filename, 2)))
goto err;
signal(SIGINT,endprog);
@@ -167,14 +178,14 @@ int main(int argc, char *argv[])
if (j != 0)
{
sprintf(key,"%6d",j);
- if (heap_rkey(file,record,0,key))
+ if (heap_rkey(file,record,0,key,6,0))
{
printf("can't find key1: \"%s\"\n",key);
goto err;
}
#ifdef NOT_USED
- if (file->current_ptr == _hp_find_block(&file->s->block,0) ||
- file->current_ptr == _hp_find_block(&file->s->block,1))
+ if (file->current_ptr == hp_find_block(&file->s->block,0) ||
+ file->current_ptr == hp_find_block(&file->s->block,1))
continue; /* Don't remove 2 first records */
#endif
if (heap_delete(file,record))
@@ -227,7 +238,7 @@ int main(int argc, char *argv[])
if (!key1[j])
continue;
sprintf(key,"%6d",j);
- if (heap_rkey(file,record,0,key))
+ if (heap_rkey(file,record,0,key,6,0))
{
printf("can't find key1: \"%s\"\n",key);
goto err;
@@ -277,7 +288,7 @@ int main(int argc, char *argv[])
printf("- Read first key - next - delete - next -> last\n");
DBUG_PRINT("progpos",("first - next - delete - next -> last"));
- if (heap_rkey(file,record,0,key))
+ if (heap_rkey(file,record,0,key,6,0))
goto err;
if (heap_rnext(file,record3)) goto err;
if (heap_delete(file,record3)) goto err;
@@ -306,7 +317,7 @@ int main(int argc, char *argv[])
if (!silent)
printf("- Read last key - delete - prev - prev - opt_delete - prev -> first\n");
- if (heap_rlast(file,record3)) goto err;
+ if (heap_rlast(file,record3,0)) goto err;
if (heap_delete(file,record3)) goto err;
key_check-=atoi(record3);
key1[atoi(record+keyinfo[0].seg[0].start)]--;
@@ -501,7 +512,7 @@ int main(int argc, char *argv[])
}
printf("- Read through all keys with first-next-last-prev\n");
ant=0;
- for (error=heap_rkey(file,record,0,key) ;
+ for (error=heap_rkey(file,record,0,key,6,0);
! error ;
error=heap_rnext(file,record))
ant++;
@@ -513,7 +524,7 @@ int main(int argc, char *argv[])
}
ant=0;
- for (error=heap_rlast(file,record) ;
+ for (error=heap_rlast(file,record,0) ;
! error ;
error=heap_rprev(file,record))
{
@@ -530,7 +541,7 @@ int main(int argc, char *argv[])
if (testflag == 4) goto end;
printf("- Reading through all rows through keys\n");
- if (!(file2=heap_open(filename,2,0,0,0,0,0)))
+ if (!(file2=heap_open(filename, 2)))
goto err;
if (heap_scan_init(file))
goto err;
@@ -538,7 +549,7 @@ int main(int argc, char *argv[])
{
if (error == 0)
{
- if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start))
+ if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start,8,0))
{
printf("can't find key3: \"%.8s\"\n",
record+keyinfo[2].seg[0].start);
@@ -549,7 +560,8 @@ int main(int argc, char *argv[])
heap_close(file2);
printf("- Creating output heap-file 2\n");
- if (!(file2=heap_open(filename2,2,1,keyinfo,reclength,0L,0L)))
+ if (heap_create(filename2,1,keyinfo,reclength,0L,0L,&hp_create_info) ||
+ !(file2= heap_open(filename2, 2)))
goto err;
printf("- Copying and removing records\n");
diff --git a/heap/hp_update.c b/heap/hp_update.c
index b0a1926e14a..2ed0edf08de 100644
--- a/heap/hp_update.c
+++ b/heap/hp_update.c
@@ -20,27 +20,30 @@
int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
{
- uint key;
+ HP_KEYDEF *keydef, *end, *p_lastinx;
byte *pos;
- HP_SHARE *share=info->s;
+ bool auto_key_changed= 0;
+ HP_SHARE *share= info->s;
DBUG_ENTER("heap_update");
test_active(info);
pos=info->current_ptr;
- if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,old))
+ if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,old))
DBUG_RETURN(my_errno); /* Record changed */
if (--(share->records) < share->blength >> 1) share->blength>>= 1;
share->changed=1;
- for (key=0 ; key < share->keys ; key++)
+ p_lastinx= share->keydef + info->lastinx;
+ for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
{
- if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new))
{
- if (_hp_delete_key(info,share->keydef+key,old,pos,key ==
- (uint) info->lastinx) ||
- _hp_write_key(share,share->keydef+key,heap_new,pos))
- goto err;
+ if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
+ (*keydef->write_key)(info, keydef, heap_new, pos))
+ goto err;
+ if (share->auto_key == (uint) (keydef - share->keydef + 1))
+ auto_key_changed= 1;
}
}
@@ -50,22 +53,37 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
#endif
+ if (auto_key_changed)
+ heap_update_auto_increment(info, heap_new);
DBUG_RETURN(0);
err:
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
{
- info->errkey=key;
- do
+ info->errkey = keydef - share->keydef;
+ if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
- if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
+ /* we don't need to delete non-inserted key from rb-tree */
+ if ((*keydef->write_key)(info, keydef, old, pos))
{
- if (_hp_delete_key(info,share->keydef+key,heap_new,pos,0) ||
- _hp_write_key(share,share->keydef+key,old,pos))
+ if (++(share->records) == share->blength)
+ share->blength+= share->blength;
+ DBUG_RETURN(my_errno);
+ }
+ keydef--;
+ }
+ while (keydef >= share->keydef)
+ {
+ if (hp_rec_key_cmp(keydef, old, heap_new))
+ {
+ if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
+ (*keydef->write_key)(info, keydef, old, pos))
break;
}
- } while (key-- > 0);
+ keydef--;
+ }
}
- if (++(share->records) == share->blength) share->blength+= share->blength;
+ if (++(share->records) == share->blength)
+ share->blength+= share->blength;
DBUG_RETURN(my_errno);
} /* heap_update */
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 18fa95e7760..f92d8caa633 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -27,12 +27,12 @@
#define HIGHUSED 8
static byte *next_free_record_pos(HP_SHARE *info);
-static HASH_INFO *_hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
+static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
ulong records);
int heap_write(HP_INFO *info, const byte *record)
{
- uint key;
+ HP_KEYDEF *keydef, *end;
byte *pos;
HP_SHARE *share=info->s;
DBUG_ENTER("heap_write");
@@ -47,9 +47,10 @@ int heap_write(HP_INFO *info, const byte *record)
DBUG_RETURN(my_errno);
share->changed=1;
- for (key=0 ; key < share->keys ; key++)
+ for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
+ keydef++)
{
- if (_hp_write_key(share,share->keydef+key,record,pos))
+ if ((*keydef->write_key)(info, keydef, record, pos))
goto err;
}
@@ -63,16 +64,24 @@ int heap_write(HP_INFO *info, const byte *record)
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
#endif
+ if (share->auto_key)
+ heap_update_auto_increment(info, record);
DBUG_RETURN(0);
err:
- DBUG_PRINT("info",("Duplicate key: %d",key));
- info->errkey= key;
- do
+ DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
+ info->errkey= keydef - share->keydef;
+ if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
- if (_hp_delete_key(info,share->keydef+key,record,pos,0))
+ /* we don't need to delete non-inserted key from rb-tree */
+ keydef--;
+ }
+ while (keydef >= share->keydef)
+ {
+ if ((*keydef->delete_key)(info, keydef, record, pos, 0))
break;
- } while (key-- > 0);
+ keydef--;
+ }
share->deleted++;
*((byte**) pos)=share->del_link;
@@ -82,6 +91,36 @@ err:
DBUG_RETURN(my_errno);
} /* heap_write */
+/*
+ Write a key to rb_tree-index
+*/
+
+int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
+ byte *recpos)
+{
+ heap_rb_param custom_arg;
+
+ info->last_pos= NULL; /* For heap_rnext/heap_rprev */
+ custom_arg.keyseg= keyinfo->seg;
+ custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
+ if (keyinfo->flag & HA_NOSAME)
+ {
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+ keyinfo->rb_tree.flag= TREE_NO_DUPS;
+ }
+ else
+ {
+ custom_arg.search_flag= SEARCH_SAME;
+ keyinfo->rb_tree.flag= 0;
+ }
+ if (!tree_insert(&keyinfo->rb_tree, (void*)info->recbuf,
+ custom_arg.key_length, &custom_arg))
+ {
+ my_errno= HA_ERR_FOUND_DUPP_KEY;
+ return 1;
+ }
+ return 0;
+}
/* Find where to place new record */
@@ -107,7 +146,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
my_errno=HA_ERR_RECORD_FILE_FULL;
DBUG_RETURN(NULL);
}
- if (_hp_get_new_block(&info->block,&length))
+ if (hp_get_new_block(&info->block,&length))
DBUG_RETURN(NULL);
info->data_length+=length;
}
@@ -118,12 +157,12 @@ static byte *next_free_record_pos(HP_SHARE *info)
block_pos*info->block.recbuffer);
}
-
/* Write a hash-key to the hash-index */
-int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
- const byte *record, byte *recpos)
+int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
+ const byte *record, byte *recpos)
{
+ HP_SHARE *share = info->s;
int flag;
ulong halfbuff,hashnr,first_index;
byte *ptr_to_rec,*ptr_to_rec2;
@@ -134,18 +173,18 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
flag=0;
- if (!(empty= _hp_find_free_hash(info,&keyinfo->block,info->records)))
+ if (!(empty= hp_find_free_hash(share,&keyinfo->block,share->records)))
DBUG_RETURN(-1); /* No more memory */
- halfbuff= (long) info->blength >> 1;
- pos= hp_find_hash(&keyinfo->block,(first_index=info->records-halfbuff));
+ halfbuff= (long) share->blength >> 1;
+ pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
if (pos != empty) /* If some records */
{
do
{
- hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
+ hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
if (flag == 0) /* First loop; Check if ok */
- if (_hp_mask(hashnr,info->blength,info->records) != first_index)
+ if (hp_mask(hashnr, share->blength, share->records) != first_index)
break;
if (!(hashnr & halfbuff))
{ /* Key will not move */
@@ -217,8 +256,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
}
/* Check if we are at the empty position */
- pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_rec_hashnr(keyinfo,record),
- info->blength,info->records+1));
+ pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record),
+ share->blength, share->records + 1));
if (pos == empty)
{
pos->ptr_to_rec=recpos;
@@ -229,8 +268,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
/* Check if more records in same hash-nr family */
empty[0]=pos[0];
gpos=hp_find_hash(&keyinfo->block,
- _hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
- info->blength,info->records+1));
+ hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
+ share->blength, share->records + 1));
if (pos == gpos)
{
pos->ptr_to_rec=recpos;
@@ -240,7 +279,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
{
pos->ptr_to_rec=recpos;
pos->next_key=0;
- _hp_movelink(pos,gpos,empty);
+ hp_movelink(pos, gpos, empty);
}
/* Check if duplicated keys */
@@ -251,7 +290,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
pos=empty;
do
{
- if (! _hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
+ if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}
@@ -263,7 +302,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
/* Returns ptr to block, and allocates block if neaded */
-static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
+static HASH_INFO *hp_find_free_hash(HP_SHARE *info,
HP_BLOCK *block, ulong records)
{
uint block_pos;
@@ -273,7 +312,7 @@ static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
return hp_find_hash(block,records);
if (!(block_pos=(records % block->records_in_block)))
{
- if (_hp_get_new_block(block,&length))
+ if (hp_get_new_block(block,&length))
return(NULL);
info->index_length+=length;
}
diff --git a/include/Makefile.am b/include/Makefile.am
index 7a02b38020d..8220424354d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -16,11 +16,11 @@
# MA 02111-1307, USA
BUILT_SOURCES = mysql_version.h m_ctype.h my_config.h
-pkginclude_HEADERS = dbug.h m_string.h my_sys.h my_list.h \
+pkginclude_HEADERS = dbug.h m_string.h my_sys.h my_list.h my_xml.h \
mysql.h mysql_com.h mysqld_error.h mysql_embed.h \
my_semaphore.h my_pthread.h my_no_pthread.h raid.h \
errmsg.h my_global.h my_net.h my_alloc.h \
- my_getopt.h sslopt-longopts.h \
+ my_getopt.h sslopt-longopts.h typelib.h \
sslopt-vars.h sslopt-case.h $(BUILT_SOURCES)
noinst_HEADERS = config-win.h config-os2.h config-netware.h \
nisam.h heap.h merge.h my_bitmap.h\
@@ -28,7 +28,8 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \
my_dir.h mysys_err.h my_base.h \
my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \
my_aes.h my_tree.h hash.h thr_alarm.h \
- thr_lock.h t_ctype.h violite.h md5.h mysql_version.h.in
+ thr_lock.h t_ctype.h violite.h md5.h \
+ mysql_version.h.in my_handler.h
# mysql_version.h are generated
SUPERCLEANFILES = mysql_version.h my_config.h
@@ -36,16 +37,25 @@ SUPERCLEANFILES = mysql_version.h my_config.h
# Some include files that may be moved and patched by configure
DISTCLEANFILES = sched.h
+clean:
+ $(RM) -f readline/*
+distclean:
+ $(RM) -f readline/*
+
all-local: my_config.h
# Since we include my_config.h it better exist from the beginning
link_sources:
$(CP) ../config.h my_config.h
+ $(RM) -f readline/*
+ @readline_h_ln_cmd@
# Keep automake happy
my_config.h: ../config.h
$(CP) ../config.h my_config.h
+ $(RM) -f readline/*
+ @readline_h_ln_cmd@
# These files should not be included in distributions since they are
# generated by configure from the .h.in files
diff --git a/include/config-win.h b/include/config-win.h
index b4b9a59a067..c1939e9116f 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -16,6 +16,12 @@
/* Defines for Win32 to make it compatible for MySQL */
+#ifdef __WIN2000__
+/* We have to do this define before including windows.h to get the AWE API
+functions */
+#define _WIN32_WINNT 0x0500
+#endif
+
#include <sys/locking.h>
#include <windows.h>
#include <math.h> /* Because of rint() */
@@ -23,6 +29,8 @@
#include <io.h>
#include <malloc.h>
+#define HAVE_SMEM 1
+
#if defined(__NT__)
#define SYSTEM_TYPE "NT"
#elif defined(__WIN2000__)
@@ -150,7 +158,9 @@ typedef uint rf_SetTimer;
#define access(A,B) _access(A,B)
#endif
-#if defined(__cplusplus)
+#if !defined(__cplusplus)
+#define inline __inline
+#endif /* __cplusplus */
inline double rint(double nr)
{
@@ -173,9 +183,6 @@ inline double ulonglong2double(ulonglong value)
}
#define my_off_t2double(A) ulonglong2double(A)
#endif /* _WIN64 */
-#else
-#define inline __inline
-#endif /* __cplusplus */
#if SIZEOF_OFF_T > 4
#define lseek(A,B,C) _lseeki64((A),(longlong) (B),(C))
@@ -263,6 +270,7 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_ISAM /* We want to have support for ISAM in 4.0 */
#define HAVE_QUERY_CACHE
#define SPRINTF_RETURNS_INT
+#define HAVE_VIO
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
@@ -314,3 +322,6 @@ inline double ulonglong2double(ulonglong value)
#define statistic_add(V,C,L) (V)+=(C)
#endif
#define statistic_increment(V,L) thread_safe_increment((V),(L))
+
+#define shared_memory_buffer_length 16000
+#define default_shared_memory_base_name "MYSQL";
diff --git a/include/errmsg.h b/include/errmsg.h
index 5136af5b87a..1f4e6e12f00 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -30,7 +30,7 @@ extern const char *client_errors[]; /* Error messages */
#define CR_MAX_ERROR 2999
#if defined(OS2) && defined(MYSQL_SERVER)
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
-#else
+#elif !defined(ER)
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
#endif
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
@@ -64,3 +64,25 @@ extern const char *client_errors[]; /* Error messages */
#define CR_SSL_CONNECTION_ERROR 2026
#define CR_MALFORMED_PACKET 2027
+/* new 4.1 error codes */
+#define CR_NULL_POINTER 2028
+#define CR_NO_PREPARE_STMT 2029
+#define CR_NOT_ALL_PARAMS_BOUND 2030
+#define CR_DATA_TRUNCATED 2031
+#define CR_NO_PARAMETERS_EXISTS 2032
+#define CR_INVALID_PARAMETER_NO 2033
+#define CR_INVALID_BUFFER_USE 2034
+#define CR_UNSUPPORTED_PARAM_TYPE 2035
+
+#define CR_SHARED_MEMORY_CONNECTION 2036
+#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2037
+#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2038
+#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2039
+#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2040
+#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2041
+#define CR_SHARED_MEMORY_MAP_ERROR 2042
+#define CR_SHARED_MEMORY_EVENT_ERROR 2043
+#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2044
+#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045
+#define CR_CONN_UNKNOW_PROTOCOL 2046
+#define CR_INVALID_CONN_HANDLE 2047
diff --git a/include/ft_global.h b/include/ft_global.h
index 9acdf6aaaf3..4aa916e91cf 100644
--- a/include/ft_global.h
+++ b/include/ft_global.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/include/hash.h b/include/hash.h
index e9c8c73c05b..0635d2fd7fc 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -40,13 +40,15 @@ typedef struct st_hash {
DYNAMIC_ARRAY array; /* Place for hash_keys */
hash_get_key get_key;
void (*free)(void *);
- uint (*calc_hashnr)(const byte *key,uint length);
+ uint (*calc_hashnr)(CHARSET_INFO *cs, const byte *key,uint length);
+ CHARSET_INFO *charset;
} HASH;
-#define hash_init(A,B,C,D,E,F,G) _hash_init(A,B,C,D,E,F,G CALLER_INFO)
-my_bool _hash_init(HASH *hash,uint default_array_elements, uint key_offset,
- uint key_length, hash_get_key get_key,
- void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
+#define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO)
+my_bool _hash_init(HASH *hash, CHARSET_INFO *charset,
+ uint default_array_elements, uint key_offset,
+ uint key_length, hash_get_key get_key,
+ void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
void hash_free(HASH *tree);
byte *hash_element(HASH *hash,uint idx);
gptr hash_search(HASH *info,const byte *key,uint length);
diff --git a/include/heap.h b/include/heap.h
index 02b04e2b3ec..3702d88ac70 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* This file should be included when using heap_database_funktions */
+/* This file should be included when using heap_database_functions */
/* Author: Michael Widenius */
#ifndef _heap_h
@@ -31,6 +31,9 @@ extern "C" {
#include <thr_lock.h>
#endif
+#include "my_handler.h"
+#include "my_tree.h"
+
/* defines used by heap-funktions */
#define HP_MAX_LEVELS 4 /* 128^5 records is enough */
@@ -47,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */
ulong index_length;
uint reclength; /* Length of one record */
int errkey;
+ ulonglong auto_increment;
} HEAPINFO;
@@ -73,22 +77,22 @@ typedef struct st_heap_block /* The data is saved in blocks */
ulong last_allocated; /* Blocks allocated, used by keys */
} HP_BLOCK;
-typedef struct st_hp_keyseg /* Key-portion */
-{
- uint start; /* Start of key in record (from 0) */
- uint length; /* Keylength */
- uint type;
- uint null_bit; /* bit set in row+null_pos */
- uint null_pos;
-} HP_KEYSEG;
+struct st_heap_info; /* For referense */
typedef struct st_hp_keydef /* Key definition with open */
{
uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */
uint keysegs; /* Number of key-segment */
uint length; /* Length of key (automatic) */
- HP_KEYSEG *seg;
+ uint8 algorithm; /* HASH / BTREE */
+ HA_KEYSEG *seg;
HP_BLOCK block; /* Where keys are saved */
+ TREE rb_tree;
+ int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
+ const byte *record, byte *recpos);
+ int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
+ const byte *record, byte *recpos, int flag);
+ uint (*get_key_length)(struct st_hp_keydef *keydef, const byte *key);
} HP_KEYDEF;
typedef struct st_heap_share
@@ -112,6 +116,9 @@ typedef struct st_heap_share
#endif
my_bool delete_on_close;
LIST open_list;
+ uint auto_key;
+ uint auto_key_type; /* real type of the auto key segment */
+ ulonglong auto_increment;
} HP_SHARE;
struct st_hp_hash_info;
@@ -126,17 +133,27 @@ typedef struct st_heap_info
int mode; /* Mode of file (READONLY..) */
uint opt_flag,update;
byte *lastkey; /* Last used key with rkey */
+ byte *recbuf; /* Record buffer for rb-tree keys */
+ enum ha_rkey_function last_find_flag;
+ TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1];
+ TREE_ELEMENT **last_pos;
+ uint lastkey_len;
#ifdef THREAD
THR_LOCK_DATA lock;
#endif
LIST open_list;
} HP_INFO;
+typedef struct st_heap_create_info
+{
+ uint auto_key;
+ uint auto_key_type;
+ ulonglong auto_increment;
+} HP_CREATE_INFO;
+
/* Prototypes for heap-functions */
-extern HP_INFO* heap_open(const char *name,int mode,uint keys,
- HP_KEYDEF *keydef,uint reclength,
- ulong max_records,ulong min_reloc);
+extern HP_INFO *heap_open(const char *name, int mode);
extern int heap_close(HP_INFO *info);
extern int heap_write(HP_INFO *info,const byte *buff);
extern int heap_update(HP_INFO *info,const byte *old,const byte *newdata);
@@ -145,7 +162,9 @@ extern int heap_scan_init(HP_INFO *info);
extern int heap_scan(register HP_INFO *info, byte *record);
extern int heap_delete(HP_INFO *info,const byte *buff);
extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
-extern int heap_create(const char *name);
+extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
+ uint reclength, ulong max_records, ulong min_records,
+ HP_CREATE_INFO *create_info);
extern int heap_delete_table(const char *name);
extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
extern int heap_rename(const char *old_name,const char *new_name);
@@ -153,10 +172,17 @@ extern int heap_panic(enum ha_panic_function flag);
extern int heap_rsame(HP_INFO *info,byte *record,int inx);
extern int heap_rnext(HP_INFO *info,byte *record);
extern int heap_rprev(HP_INFO *info,byte *record);
-extern int heap_rfirst(HP_INFO *info,byte *record);
-extern int heap_rlast(HP_INFO *info,byte *record);
+extern int heap_rfirst(HP_INFO *info,byte *record,int inx);
+extern int heap_rlast(HP_INFO *info,byte *record,int inx);
extern void heap_clear(HP_INFO *info);
-extern int heap_rkey(HP_INFO *info,byte *record,int inx,const byte *key);
+extern void heap_update_auto_increment(HP_INFO *info, const byte *record);
+ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
+ uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key, uint end_key_len,
+ enum ha_rkey_function end_search_flag);
+int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
+ uint key_len, enum ha_rkey_function find_flag);
extern gptr heap_find(HP_INFO *info,int inx,const byte *key);
extern int heap_check_heap(HP_INFO *info, my_bool print_status);
extern byte *heap_position(HP_INFO *info);
diff --git a/include/m_ctype.h b/include/m_ctype.h
index fc983d1d580..4ed5c6eec6a 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -26,68 +26,255 @@
extern "C" {
#endif
+#define MY_CS_NAME_SIZE 32
+#define MY_CS_CTYPE_TABLE_SIZE 257
+#define MY_CS_TO_LOWER_TABLE_SIZE 256
+#define MY_CS_TO_UPPER_TABLE_SIZE 256
+#define MY_CS_SORT_ORDER_TABLE_SIZE 256
+#define MY_CS_TO_UNI_TABLE_SIZE 256
+
#define CHARSET_DIR "charsets/"
-typedef struct charset_info_st
+#define my_wc_t ulong
+
+typedef struct unicase_info_st
{
- uint number;
- const char *name;
- uchar *ctype;
- uchar *to_lower;
- uchar *to_upper;
- uchar *sort_order;
-
- uint strxfrm_multiply;
- int (*strcoll)(const uchar *, const uchar *);
- int (*strxfrm)(uchar *, const uchar *, int);
- int (*strnncoll)(const uchar *, int, const uchar *, int);
- int (*strnxfrm)(uchar *, const uchar *, int, int);
- my_bool (*like_range)(const char *, uint, pchar, uint,
- char *, char *, uint *, uint *);
-
- uint mbmaxlen;
- int (*ismbchar)(const char *, const char *);
- my_bool (*ismbhead)(uint);
- int (*mbcharlen)(uint);
-} CHARSET_INFO;
+ uint16 toupper;
+ uint16 tolower;
+ uint16 sort;
+} MY_UNICASE_INFO;
+
+#define MY_CS_ILSEQ 0
+#define MY_CS_ILUNI 0
+#define MY_CS_TOOSMALL -1
+#define MY_CS_TOOFEW(n) (-1-(n))
+
+#define MY_SEQ_INTTAIL 1
+#define MY_SEQ_SPACES 2
-/* strings/ctype.c */
-extern CHARSET_INFO *default_charset_info;
-extern CHARSET_INFO *find_compiled_charset(uint cs_number);
-extern CHARSET_INFO *find_compiled_charset_by_name(const char *name);
-extern CHARSET_INFO compiled_charsets[];
-extern uint compiled_charset_number(const char *name);
-extern const char *compiled_charset_name(uint charset_number);
+ /* My charsets_list flags */
+#define MY_NO_SETS 0
+#define MY_CS_COMPILED 1 /* compiled-in sets */
+#define MY_CS_CONFIG 2 /* sets that have a *.conf file */
+#define MY_CS_INDEX 4 /* sets listed in the Index file */
+#define MY_CS_LOADED 8 /* sets that are currently loaded */
+#define MY_CS_BINSORT 16 /* if binary sort order */
+#define MY_CS_PRIMARY 32 /* if primary collation */
+#define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */
#define MY_CHARSET_UNDEFINED 0
#define MY_CHARSET_CURRENT (default_charset_info->number)
-/* Don't include std ctype.h when this is included */
-#define _CTYPE_H
-#define _CTYPE_H_
-#define _CTYPE_INCLUDED
-#define __CTYPE_INCLUDED
-#define _CTYPE_USING /* Don't put names in global namespace. */
-
-/* Fix things, if ctype.h would have been included before */
-#undef toupper
-#undef _toupper
-#undef _tolower
-#undef toupper
-#undef tolower
-#undef isalpha
-#undef isupper
-#undef islower
-#undef isdigit
-#undef isxdigit
-#undef isalnum
-#undef isspace
-#undef ispunct
-#undef isprint
-#undef isgraph
-#undef iscntrl
-#undef isascii
-#undef toascii
+
+typedef struct my_uni_idx_st
+{
+ uint16 from;
+ uint16 to;
+ uchar *tab;
+} MY_UNI_IDX;
+
+
+typedef struct charset_info_st
+{
+ uint number;
+ uint state;
+ const char *csname;
+ const char *name;
+ const char *comment;
+ uchar *ctype;
+ uchar *to_lower;
+ uchar *to_upper;
+ uchar *sort_order;
+ uint16 *tab_to_uni;
+ MY_UNI_IDX *tab_from_uni;
+
+ /* Collation routines */
+ uint strxfrm_multiply;
+ int (*strnncoll)(struct charset_info_st *,
+ const uchar *, uint, const uchar *, uint);
+ int (*strnncollsp)(struct charset_info_st *,
+ const uchar *, uint, const uchar *, uint);
+ int (*strnxfrm)(struct charset_info_st *,
+ uchar *, uint, const uchar *, uint);
+ my_bool (*like_range)(struct charset_info_st *,
+ const char *s, uint s_length,
+ int w_prefix, int w_one, int w_many,
+ uint res_length,
+ char *min_str, char *max_str,
+ uint *min_len, uint *max_len);
+ int (*wildcmp)(struct charset_info_st *,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape,int w_one, int w_many);
+
+ /* Multibyte routines */
+ uint mbmaxlen;
+ int (*ismbchar)(struct charset_info_st *, const char *, const char *);
+ my_bool (*ismbhead)(struct charset_info_st *, uint);
+ int (*mbcharlen)(struct charset_info_st *, uint);
+ uint (*numchars)(struct charset_info_st *, const char *b, const char *e);
+ uint (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos);
+
+ /* Unicode convertion */
+ int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
+ const unsigned char *s,const unsigned char *e);
+ int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
+ unsigned char *s,unsigned char *e);
+
+ /* Functions for case and sort convertion */
+ void (*caseup_str)(struct charset_info_st *, char *);
+ void (*casedn_str)(struct charset_info_st *, char *);
+ void (*caseup)(struct charset_info_st *, char *, uint);
+ void (*casedn)(struct charset_info_st *, char *, uint);
+ void (*tosort)(struct charset_info_st *, char *, uint);
+
+ /* Functions for case comparison */
+ int (*strcasecmp)(struct charset_info_st *, const char *, const char *);
+ int (*strncasecmp)(struct charset_info_st *, const char *, const char *,
+ uint);
+
+ /* Hash calculation */
+ uint (*hash_caseup)(struct charset_info_st *cs, const byte *key, uint len);
+ void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len,
+ ulong *nr1, ulong *nr2);
+
+ char max_sort_char; /* For LIKE optimization */
+
+ /* Charset dependant snprintf() */
+ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt,
+ ...);
+ int (*long10_to_str)(struct charset_info_st *, char *to, uint n, int radix,
+ long int val);
+ int (*longlong10_to_str)(struct charset_info_st *, char *to, uint n,
+ int radix, longlong val);
+
+ void (*fill)(struct charset_info_st *, char *to, uint len, int fill);
+
+ /* String-to-number convertion routines */
+ long (*strntol)(struct charset_info_st *, const char *s, uint l,
+ int base, char **e, int *err);
+ ulong (*strntoul)(struct charset_info_st *, const char *s, uint l,
+ int base, char **e, int *err);
+ longlong (*strntoll)(struct charset_info_st *, const char *s, uint l,
+ int base, char **e, int *err);
+ ulonglong (*strntoull)(struct charset_info_st *, const char *s, uint l,
+ int base, char **e, int *err);
+ double (*strntod)(struct charset_info_st *, char *s, uint l, char **e,
+ int *err);
+
+ ulong (*scan)(struct charset_info_st *, const char *b, const char *e,
+ int sq);
+
+} CHARSET_INFO;
+
+
+extern CHARSET_INFO my_charset_bin;
+extern CHARSET_INFO my_charset_latin1;
+extern CHARSET_INFO my_charset_big5;
+extern CHARSET_INFO my_charset_czech;
+extern CHARSET_INFO my_charset_euc_kr;
+extern CHARSET_INFO my_charset_gb2312;
+extern CHARSET_INFO my_charset_gbk;
+extern CHARSET_INFO my_charset_latin1_de;
+extern CHARSET_INFO my_charset_sjis;
+extern CHARSET_INFO my_charset_tis620;
+extern CHARSET_INFO my_charset_ucs2;
+extern CHARSET_INFO my_charset_ujis;
+extern CHARSET_INFO my_charset_utf8;
+extern CHARSET_INFO my_charset_win1250ch;
+
+
+extern my_bool my_parse_charset_xml(const char *bug, uint len,
+ int (*add)(CHARSET_INFO *cs));
+
+/* declarations for simple charsets */
+extern int my_strnxfrm_simple(CHARSET_INFO *, uchar *, uint, const uchar *,
+ uint);
+extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
+ const uchar *, uint);
+
+extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
+ const uchar *, uint);
+
+extern uint my_hash_caseup_simple(CHARSET_INFO *cs,
+ const byte *key, uint len);
+
+extern void my_hash_sort_simple(CHARSET_INFO *cs,
+ const uchar *key, uint len,
+ ulong *nr1, ulong *nr2);
+
+
+/* Functions for 8bit */
+extern void my_caseup_str_8bit(CHARSET_INFO *, char *);
+extern void my_casedn_str_8bit(CHARSET_INFO *, char *);
+extern void my_caseup_8bit(CHARSET_INFO *, char *, uint);
+extern void my_casedn_8bit(CHARSET_INFO *, char *, uint);
+extern void my_tosort_8bit(CHARSET_INFO *, char *, uint);
+
+extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *);
+extern int my_strncasecmp_8bit(CHARSET_INFO * cs, const char *, const char *,
+ uint);
+
+int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
+int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
+
+ulong my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq);
+
+int my_snprintf_8bit(struct charset_info_st *, char *to, uint n,
+ const char *fmt, ...);
+
+long my_strntol_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+ char **e, int *err);
+ulong my_strntoul_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+ char **e, int *err);
+longlong my_strntoll_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+ char **e, int *err);
+ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, uint l, int base,
+ char **e, int *err);
+double my_strntod_8bit(CHARSET_INFO *, char *s, uint l,char **e,
+ int *err);
+
+int my_long10_to_str_8bit(CHARSET_INFO *, char *to, uint l, int radix,
+ long int val);
+int my_longlong10_to_str_8bit(CHARSET_INFO *, char *to, uint l, int radix,
+ longlong val);
+
+void my_fill_8bit(CHARSET_INFO *cs, char* to, uint l, int fill);
+
+my_bool my_like_range_simple(CHARSET_INFO *cs,
+ const char *ptr, uint ptr_length,
+ int escape, int w_one, int w_many,
+ uint res_length,
+ char *min_str, char *max_str,
+ uint *min_length, uint *max_length);
+
+
+int my_wildcmp_8bit(CHARSET_INFO *,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many);
+
+uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e);
+uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos);
+
+
+#ifdef USE_MB
+/* Functions for multibyte charsets */
+extern void my_caseup_str_mb(CHARSET_INFO *, char *);
+extern void my_casedn_str_mb(CHARSET_INFO *, char *);
+extern void my_caseup_mb(CHARSET_INFO *, char *, uint);
+extern void my_casedn_mb(CHARSET_INFO *, char *, uint);
+extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *);
+extern int my_strncasecmp_mb(CHARSET_INFO * cs,const char *, const char *t,
+ uint);
+int my_wildcmp_mb(CHARSET_INFO *,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many);
+uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e);
+uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos);
+
+#endif
#define _U 01 /* Upper case */
#define _L 02 /* Lower case */
@@ -98,34 +285,13 @@ extern const char *compiled_charset_name(uint charset_number);
#define _B 0100 /* Blank */
#define _X 0200 /* heXadecimal digit */
-#define my_ctype (default_charset_info->ctype)
-#define my_to_upper (default_charset_info->to_upper)
-#define my_to_lower (default_charset_info->to_lower)
-#define my_sort_order (default_charset_info->sort_order)
-
-#define _toupper(c) (char) my_to_upper[(uchar) (c)]
-#define _tolower(c) (char) my_to_lower[(uchar) (c)]
-#define toupper(c) (char) my_to_upper[(uchar) (c)]
-#define tolower(c) (char) my_to_lower[(uchar) (c)]
-
-#define isalpha(c) ((my_ctype+1)[(uchar) (c)] & (_U | _L))
-#define isupper(c) ((my_ctype+1)[(uchar) (c)] & _U)
-#define islower(c) ((my_ctype+1)[(uchar) (c)] & _L)
-#define isdigit(c) ((my_ctype+1)[(uchar) (c)] & _NMR)
-#define isxdigit(c) ((my_ctype+1)[(uchar) (c)] & _X)
-#define isalnum(c) ((my_ctype+1)[(uchar) (c)] & (_U | _L | _NMR))
-#define isspace(c) ((my_ctype+1)[(uchar) (c)] & _SPC)
-#define ispunct(c) ((my_ctype+1)[(uchar) (c)] & _PNT)
-#define isprint(c) ((my_ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR | _B))
-#define isgraph(c) ((my_ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR))
-#define iscntrl(c) ((my_ctype+1)[(uchar) (c)] & _CTR)
-#define isascii(c) (!((c) & ~0177))
-#define toascii(c) ((c) & 0177)
-
-#ifdef ctype
-#undef ctype
-#endif /* ctype */
+#define my_isascii(c) (!((c) & ~0177))
+#define my_toascii(c) ((c) & 0177)
+#define my_tocntrl(c) ((c) & 31)
+#define my_toprint(c) ((c) | 64)
+#define my_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)])
+#define my_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)])
#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)
@@ -138,26 +304,36 @@ extern const char *compiled_charset_name(uint charset_number);
#define my_isgraph(s, c) (((s)->ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR))
#define my_iscntrl(s, c) (((s)->ctype+1)[(uchar) (c)] & _CTR)
-#define use_strcoll(s) ((s)->strcoll != NULL)
-#define MY_STRXFRM_MULTIPLY (default_charset_info->strxfrm_multiply)
-#define my_strnxfrm(s, a, b, c, d) ((s)->strnxfrm((a), (b), (c), (d)))
-#define my_strnncoll(s, a, b, c, d) ((s)->strnncoll((a), (b), (c), (d)))
-#define my_strxfrm(s, a, b, c, d) ((s)->strnxfrm((a), (b), (c)))
-#define my_strcoll(s, a, b) ((s)->strcoll((a), (b)))
-#define my_like_range(s, a, b, c, d, e, f, g, h) \
- ((s)->like_range((a), (b), (c), (d), (e), (f), (g), (h)))
+/* Some macros that should be cleaned up a little */
+#define my_isvar(s,c) (my_isalnum(s,c) || (c) == '_')
+#define my_isvar_start(s,c) (my_isalpha(s,c) || (c) == '_')
+
+#define use_strnxfrm(s) ((s)->state & MY_CS_STRNXFRM)
+#define my_strnxfrm(s, a, b, c, d) ((s)->strnxfrm((s), (a), (b), (c), (d)))
+#define my_strnncoll(s, a, b, c, d) ((s)->strnncoll((s), (a), (b), (c), (d)))
+#define my_like_range(s, a, b, c, d, e, f, g, h, i, j) \
+ ((s)->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j)))
+#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m)))
#define use_mb(s) ((s)->ismbchar != NULL)
-#define MBMAXLEN (default_charset_info->mbmaxlen)
-#define my_ismbchar(s, a, b) ((s)->ismbchar((a), (b)))
-#define my_ismbhead(s, a) ((s)->ismbhead((a)))
-#define my_mbcharlen(s, a) ((s)->mbcharlen((a)))
+#define my_ismbchar(s, a, b) ((s)->ismbchar((s), (a), (b)))
+#define my_ismbhead(s, a) ((s)->ismbhead((s), (a)))
+#define my_mbcharlen(s, a) ((s)->mbcharlen((s),(a)))
+
+#define my_caseup(s, a, l) ((s)->caseup((s), (a), (l)))
+#define my_casedn(s, a, l) ((s)->casedn((s), (a), (l)))
+#define my_tosort(s, a, l) ((s)->tosort((s), (a), (l)))
+#define my_caseup_str(s, a) ((s)->caseup_str((s), (a)))
+#define my_casedn_str(s, a) ((s)->casedn_str((s), (a)))
+#define my_strcasecmp(s, a, b) ((s)->strcasecmp((s), (a), (b)))
+#define my_strncasecmp(s, a, b, l) ((s)->strncasecmp((s), (a), (b), (l)))
+
+#define my_strntol(s, a, b, c, d, e) ((s)->strntol((s),(a),(b),(c),(d),(e)))
+#define my_strntoul(s, a, b, c, d, e) ((s)->strntoul((s),(a),(b),(c),(d),(e)))
+#define my_strntoll(s, a, b, c, d, e) ((s)->strntoll((s),(a),(b),(c),(d),(e)))
+#define my_strntoull(s, a, b, c,d, e) ((s)->strntoull((s),(a),(b),(c),(d),(e)))
+#define my_strntod(s, a, b, c, d) ((s)->strntod((s),(a),(b),(c),(d)))
-/* Some macros that should be cleaned up a little */
-#define isvar(c) (isalnum(c) || (c) == '_')
-#define isvar_start(c) (isalpha(c) || (c) == '_')
-#define tocntrl(c) ((c) & 31)
-#define toprint(c) ((c) | 64)
/* XXX: still need to take care of this one */
#ifdef MY_CHARSET_TIS620
diff --git a/include/m_string.h b/include/m_string.h
index c6943613b1a..15a488fe72a 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -31,6 +31,9 @@
#include <string.h>
#endif
+/* need by my_vsnprintf */
+#include <stdarg.h>
+
/* Correct some things for UNIXWARE7 */
#ifdef HAVE_UNIXWARE7_THREADS
#undef HAVE_STRINGS_H
@@ -238,6 +241,12 @@ extern ulonglong strtoull(const char *str, char **ptr, int base);
#endif
#endif
+/* my_vsnprintf.c */
+
+extern int my_vsnprintf( char *str, size_t n,
+ const char *format, va_list ap );
+extern int my_snprintf(char* to, size_t n, const char* fmt, ...);
+
#if defined(__cplusplus) && !defined(OS2)
}
#endif
diff --git a/include/my_base.h b/include/my_base.h
index e1761eac8f9..f167ae3d30e 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -50,13 +50,14 @@
/* The following is parameter to ha_rkey() how to use key */
enum ha_rkey_function {
- HA_READ_KEY_EXACT, /* Find first record else error */
- HA_READ_KEY_OR_NEXT, /* Record or next record */
- HA_READ_KEY_OR_PREV, /* Record or previous */
- HA_READ_AFTER_KEY, /* Find next rec. after key-record */
- HA_READ_BEFORE_KEY, /* Find next rec. before key-record */
- HA_READ_PREFIX, /* Key which as same prefix */
- HA_READ_PREFIX_LAST, /* Last key with the same prefix */
+ HA_READ_KEY_EXACT, /* Find first record else error */
+ HA_READ_KEY_OR_NEXT, /* Record or next record */
+ HA_READ_KEY_OR_PREV, /* Record or previous */
+ HA_READ_AFTER_KEY, /* Find next rec. after key-record */
+ HA_READ_BEFORE_KEY, /* Find next rec. before key-record */
+ HA_READ_PREFIX, /* Key which as same prefix */
+ HA_READ_PREFIX_LAST, /* Last key with the same prefix */
+ HA_READ_PREFIX_LAST_OR_PREV, /* Last or prev key with the same prefix */
HA_READ_MBR_CONTAIN,
HA_READ_MBR_INTERSECT,
HA_READ_MBR_WITHIN,
@@ -66,7 +67,7 @@ enum ha_rkey_function {
/* Key algorithm types */
-enum ha_key_alg {
+enum ha_key_alg {
HA_KEY_ALG_UNDEF= 0, /* Not specified (old file) */
HA_KEY_ALG_BTREE= 1, /* B-tree, default one */
HA_KEY_ALG_RTREE= 2, /* R-tree, for spatial searches */
@@ -148,9 +149,9 @@ enum ha_base_keytype {
#define HA_PACK_KEY 2 /* Pack string key to previous key */
#define HA_AUTO_KEY 16
#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */
-#define HA_FULLTEXT 128 /* SerG: for full-text search */
+#define HA_FULLTEXT 128 /* For full-text search */
#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */
-#define HA_SPATIAL 1024 /* Alex Barkov: for spatial search */
+#define HA_SPATIAL 1024 /* For spatial search */
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
@@ -200,7 +201,7 @@ enum ha_base_keytype {
/* Bits in flag to _status */
#define HA_STATUS_POS 1 /* Return position */
-#define HA_STATUS_NO_LOCK 2 /* Don't use external lock */
+#define HA_STATUS_NO_LOCK 2 /* Don't use external lock */
#define HA_STATUS_TIME 4 /* Return update time */
#define HA_STATUS_CONST 8 /* Return constants values */
#define HA_STATUS_VARIABLE 16
@@ -272,7 +273,7 @@ enum ha_base_keytype {
#define READ_CHECK_USED 4
#define KEY_READ_USED 8
#define WRITE_CACHE_USED 16
-#define OPT_NO_ROWS 32
+#define OPT_NO_ROWS 32
/* bits in update */
#define HA_STATE_CHANGED 1 /* Database has changed */
@@ -304,7 +305,7 @@ enum data_file_type {
typedef my_off_t ha_rows;
#else
#define rows2double(A) (double) (A)
-typedef ulong ha_rows;
+typedef ulong ha_rows;
#endif
#define HA_POS_ERROR (~ (ha_rows) 0)
diff --git a/include/my_global.h b/include/my_global.h
index f98cc48ba20..f7b97d96545 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -19,6 +19,11 @@
#ifndef _global_h
#define _global_h
+#ifndef EMBEDDED_LIBRARY
+#define HAVE_REPLICATION
+#define HAVE_EXTERNAL_CLIENT
+#endif
+
#if defined( __EMX__) && !defined( MYSQL_SERVER)
/* moved here to use below VOID macro redefinition */
#define INCL_BASE
diff --git a/include/my_handler.h b/include/my_handler.h
new file mode 100644
index 00000000000..618d1df1a6e
--- /dev/null
+++ b/include/my_handler.h
@@ -0,0 +1,66 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library 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 */
+
+#ifndef _my_handler_h
+#define _my_handler_h
+
+#include "my_global.h"
+#include "my_base.h"
+#include "m_ctype.h"
+#include "myisampack.h"
+
+typedef struct st_HA_KEYSEG /* Key-portion */
+{
+ uint8 type; /* Type of key (for sort) */
+ uint8 language;
+ uint8 null_bit; /* bitmask to test for NULL */
+ uint8 bit_start,bit_end; /* if bit field */
+ uint16 flag;
+ uint16 length; /* Keylength */
+ uint32 start; /* Start of key in record */
+ uint32 null_pos; /* position to NULL indicator */
+ CHARSET_INFO *charset;
+} HA_KEYSEG;
+
+#define get_key_length(length,key) \
+{ if ((uchar) *(key) != 255) \
+ length= (uint) (uchar) *((key)++); \
+ else \
+ { length=mi_uint2korr((key)+1); (key)+=3; } \
+}
+
+#define get_key_length_rdonly(length,key) \
+{ if ((uchar) *(key) != 255) \
+ length= ((uint) (uchar) *((key))); \
+ else \
+ { length=mi_uint2korr((key)+1); } \
+}
+
+#define get_key_pack_length(length,length_pack,key) \
+{ if ((uchar) *(key) != 255) \
+ { length= (uint) (uchar) *((key)++); length_pack=1; }\
+ else \
+ { length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
+}
+
+extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
+ my_bool);
+extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
+ register uchar *b, uint key_length, uint nextflag,
+ uint *diff_pos);
+
+#endif /* _my_handler_h */
diff --git a/include/my_list.h b/include/my_list.h
index 0f56d4c532b..789bbb50f97 100644
--- a/include/my_list.h
+++ b/include/my_list.h
@@ -32,8 +32,8 @@ extern LIST *list_add(LIST *root,LIST *element);
extern LIST *list_delete(LIST *root,LIST *element);
extern LIST *list_cons(void *data,LIST *root);
extern LIST *list_reverse(LIST *root);
-extern void list_free(LIST *root,pbool free_data);
-extern uint list_length(LIST *list);
+extern void list_free(LIST *root,unsigned int free_data);
+extern unsigned int list_length(LIST *list);
extern int list_walk(LIST *list,list_walk_action action,gptr argument);
#define rest(a) ((a)->next)
diff --git a/include/my_pthread.h b/include/my_pthread.h
index bea6b8bef5a..e4d8069096b 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -1,3 +1,4 @@
+
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -621,7 +622,7 @@ extern int pthread_dummy(int);
*/
#define DEFAULT_THREAD_STACK (192*1024L)
#else
-#define DEFAULT_THREAD_STACK (192*1024L)
+#define DEFAULT_THREAD_STACK (192*1024)
#endif
struct st_my_thread_var
@@ -635,6 +636,8 @@ struct st_my_thread_var
long id;
int cmp_length;
int volatile abort;
+ struct st_my_thread_var *next,**prev;
+ void *opt_info;
#ifndef DBUG_OFF
gptr dbug;
char name[THREAD_NAME_SIZE+1];
diff --git a/include/my_sys.h b/include/my_sys.h
index 9610033e2a9..c4fc157e6f2 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -37,6 +37,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#endif
#include <stdarg.h>
+#include <typelib.h>
#define MYSYS_PROGRAM_USES_CURSES() { error_handler_hook = my_message_curses; mysys_uses_curses=1; }
#define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;}
@@ -105,13 +106,6 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_SEEK_CUR 1
#define MY_SEEK_END 2
- /* My charsets_list flags */
-#define MY_NO_SETS 0
-#define MY_COMPILED_SETS 1 /* show compiled-in sets */
-#define MY_CONFIG_SETS 2 /* sets that have a *.conf file */
-#define MY_INDEX_SETS 4 /* all sets listed in the Index file */
-#define MY_LOADED_SETS 8 /* the sets that are currently loaded */
-
/* Some constants */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
@@ -207,11 +201,17 @@ extern int (*fatal_error_handler_hook)(uint my_err, const char *str,
myf MyFlags);
/* charsets */
+extern CHARSET_INFO *default_charset_info;
+extern CHARSET_INFO *system_charset_info;
+extern CHARSET_INFO *all_charsets[256];
+extern CHARSET_INFO compiled_charsets[];
+
extern uint get_charset_number(const char *cs_name);
extern const char *get_charset_name(uint cs_number);
extern CHARSET_INFO *get_charset(uint cs_number, myf flags);
extern my_bool set_default_charset(uint cs, myf flags);
extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
+extern CHARSET_INFO *get_charset_by_csname(const char *cs_name, myf flags);
extern my_bool set_default_charset_by_name(const char *cs_name, myf flags);
extern void free_charsets(void);
extern char *list_charsets(myf want_flags); /* my_free() this string... */
@@ -254,12 +254,6 @@ typedef struct wild_file_pack /* Struct to hold info when selecting files */
my_string *wild; /* Pointer to wildcards */
} WF_PACK;
-typedef struct st_typelib { /* Different types saved here */
- uint count; /* How many types */
- const char *name; /* Name of typelib */
- const char **type_names;
-} TYPELIB;
-
enum cache_type
{
READ_CACHE,WRITE_CACHE,
@@ -300,6 +294,14 @@ extern struct my_file_info
#endif
} my_file_info[MY_NFILE];
+typedef struct st_my_tmpdir
+{
+ char **list;
+ uint cur, max;
+#ifdef THREAD
+ pthread_mutex_t mutex;
+#endif
+} MY_TMPDIR;
typedef struct st_dynamic_array
{
@@ -509,6 +511,8 @@ extern int my_setwd(const char *dir,myf MyFlags);
extern int my_lock(File fd,int op,my_off_t start, my_off_t length,myf MyFlags);
extern gptr my_once_alloc(uint Size,myf MyFlags);
extern void my_once_free(void);
+extern char *my_once_strdup(const char *src,myf myflags);
+extern char *my_once_memdup(const char *src, uint len, myf myflags);
extern my_string my_tempnam(const char *dir,const char *pfx,myf MyFlags);
extern File my_open(const char *FileName,int Flags,myf MyFlags);
extern File my_register_filename(File fd, const char *FileName,
@@ -557,6 +561,7 @@ extern char *_my_strdup_with_length(const byte *from, uint length,
const char *sFile, uint uLine,
myf MyFlag);
+
#ifndef TERMINATE
extern void TERMINATE(FILE *file);
#endif
@@ -569,9 +574,6 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...));
extern int my_printf_error _VARARGS((uint my_err, const char *format,
myf MyFlags, ...)
__attribute__ ((format (printf, 2, 4))));
-extern int my_vsnprintf( char *str, size_t n,
- const char *format, va_list ap );
-extern int my_snprintf(char* to, size_t n, const char* fmt, ...);
extern int my_message(uint my_err, const char *str,myf MyFlags);
extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
@@ -589,12 +591,11 @@ extern void allow_break(void);
#define allow_break()
#endif
+extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist);
+extern char *my_tmpdir(MY_TMPDIR *tmpdir);
+extern void free_tmpdir(MY_TMPDIR *tmpdir);
+
extern void my_remember_signal(int signal_number,sig_handler (*func)(int));
-extern void caseup(my_string str,uint length);
-extern void casedn(my_string str,uint length);
-extern void caseup_str(my_string str);
-extern void casedn_str(my_string str);
-extern void case_sort(my_string str,uint length);
extern uint dirname_part(my_string to,const char *name);
extern uint dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A))
@@ -619,18 +620,12 @@ extern my_string my_path(my_string to,const char *progname,
extern my_string my_load_path(my_string to, const char *path,
const char *own_path_prefix);
extern int wild_compare(const char *str,const char *wildstr);
-extern my_string my_strcasestr(const char *src,const char *suffix);
-extern int my_strcasecmp(const char *s,const char *t);
-extern int my_strsortcmp(const char *s,const char *t);
-extern int my_casecmp(const char *s,const char *t,uint length);
-extern int my_sortcmp(const char *s,const char *t,uint length);
-extern int my_sortncmp(const char *s,uint s_len, const char *t,uint t_len);
extern WF_PACK *wf_comp(my_string str);
extern int wf_test(struct wild_file_pack *wf_pack,const char *name);
extern void wf_end(struct wild_file_pack *buffer);
extern size_s strip_sp(my_string str);
extern void get_date(my_string to,int timeflag,time_t use_time);
-extern void soundex(my_string out_pntr, my_string in_pntr,pbool remove_garbage);
+extern void soundex(CHARSET_INFO *, my_string out_pntr, my_string in_pntr,pbool remove_garbage);
extern int init_record_cache(RECORD_CACHE *info,uint cachesize,File file,
uint reclength,enum cache_type type,
pbool use_async_io);
@@ -711,10 +706,8 @@ extern void freeze_size(DYNAMIC_ARRAY *array);
#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
#define push_dynamic(A,B) insert_dynamic(A,B)
+#define reset_dynamic(array) ((array)->elements= 0)
-extern int find_type(my_string x,TYPELIB *typelib,uint full_name);
-extern void make_type(my_string to,uint nr,TYPELIB *typelib);
-extern const char *get_type(TYPELIB *typelib,uint nr);
extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
uint init_alloc,uint alloc_increment);
extern my_bool dynstr_append(DYNAMIC_STRING *str, const char *append);
diff --git a/include/my_tree.h b/include/my_tree.h
index 7cc7c615ba6..0e705e19bba 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -20,13 +20,17 @@
extern "C" {
#endif
-#define MAX_TREE_HIGHT 40 /* = max 1048576 leafs in tree */
+#include "my_base.h" /* get 'enum ha_rkey_function' */
+
+#define MAX_TREE_HEIGHT 40 /* = max 1048576 leafs in tree */
#define ELEMENT_KEY(tree,element)\
(tree->offset_to_key ? (void*)((byte*) element+tree->offset_to_key) :\
*((void**) (element+1)))
#define tree_set_pointer(element,ptr) *((byte **) (element+1))=((byte*) (ptr))
+#define TREE_NO_DUPS 1
+
typedef enum { left_root_right, right_root_left } TREE_WALK;
typedef uint32 element_count;
typedef int (*tree_walk_action)(void *,element_count,void *);
@@ -48,15 +52,18 @@ typedef struct st_tree_element {
} TREE_ELEMENT;
#endif /* MSDOS */
+#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs))
+
typedef struct st_tree {
TREE_ELEMENT *root,null_element;
- TREE_ELEMENT **parents[MAX_TREE_HIGHT];
+ TREE_ELEMENT **parents[MAX_TREE_HEIGHT];
uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated;
qsort_cmp2 compare;
- void* custom_arg;
+ void *custom_arg;
MEM_ROOT mem_root;
my_bool with_delete;
tree_element_free free;
+ uint flag;
} TREE;
/* Functions on whole tree */
@@ -70,11 +77,21 @@ void reset_tree(TREE*);
#define is_tree_inited(tree) ((tree)->root != 0)
/* Functions on leafs */
-TREE_ELEMENT *tree_insert(TREE *tree,void *key,uint key_size);
-void *tree_search(TREE *tree,void *key);
+TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
+ void *custom_arg);
+void *tree_search(TREE *tree, void *key, void *custom_arg);
int tree_walk(TREE *tree,tree_walk_action action,
void *argument, TREE_WALK visit);
-int tree_delete(TREE *tree,void *key);
+int tree_delete(TREE *tree, void *key, void *custom_arg);
+void *tree_search_key(TREE *tree, const void *key,
+ TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
+ enum ha_rkey_function flag, void *custom_arg);
+void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents,
+ TREE_ELEMENT ***last_pos, int child_offs);
+void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
+ int r_offs);
+ha_rows tree_record_pos(TREE *tree, const void *key,
+ enum ha_rkey_function search_flag, void *custom_arg);
#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*))
diff --git a/include/my_xml.h b/include/my_xml.h
new file mode 100644
index 00000000000..0d968ab38c7
--- /dev/null
+++ b/include/my_xml.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 _my_xml_h
+#define _my_xml_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define MY_XML_OK 0
+#define MY_XML_ERROR 1
+
+typedef struct xml_stack_st
+{
+ char errstr[128];
+ char attr[128];
+ char *attrend;
+ const char *beg;
+ const char *cur;
+ const char *end;
+ void *user_data;
+ int (*enter)(struct xml_stack_st *st,const char *val, uint len);
+ int (*value)(struct xml_stack_st *st,const char *val, uint len);
+ int (*leave)(struct xml_stack_st *st,const char *val, uint len);
+} MY_XML_PARSER;
+
+void my_xml_parser_create(MY_XML_PARSER *st);
+void my_xml_parser_free(MY_XML_PARSER *st);
+int my_xml_parse(MY_XML_PARSER *st,const char *str, uint len);
+
+void my_xml_set_value_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, const char *, uint len));
+void my_xml_set_enter_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, const char *, uint len));
+void my_xml_set_leave_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, const char *, uint len));
+void my_xml_set_user_data(MY_XML_PARSER *st, void *);
+
+uint my_xml_error_pos(MY_XML_PARSER *st);
+uint my_xml_error_lineno(MY_XML_PARSER *st);
+
+const char *my_xml_error_string(MY_XML_PARSER *st);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _my_xml_h */
diff --git a/include/myisam.h b/include/myisam.h
index 94b5d23bba6..e06f9fc37ca 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -28,6 +28,7 @@ extern "C" {
#ifndef _m_ctype_h
#include <m_ctype.h>
#endif
+#include "my_handler.h"
/* defines used by myisam-funktions */
@@ -105,20 +106,6 @@ typedef struct st_mi_create_info
struct st_myisam_info; /* For referense */
typedef struct st_myisam_info MI_INFO;
-typedef struct st_mi_keyseg /* Key-portion */
-{
- uint8 type; /* Type of key (for sort) */
- uint8 language;
- uint8 null_bit; /* bitmask to test for NULL */
- uint8 bit_start,bit_end; /* if bit field */
- uint16 flag;
- uint16 length; /* Keylength */
- uint32 start; /* Start of key in record */
- uint32 null_pos; /* position to NULL indicator */
- CHARSET_INFO *charset;
-} MI_KEYSEG;
-
-
struct st_mi_s_param;
typedef struct st_mi_keydef /* Key definition with open & info */
@@ -135,7 +122,7 @@ typedef struct st_mi_keydef /* Key definition with open & info */
uint16 block_size; /* block_size (auto) */
uint32 version; /* For concurrent read/write */
- MI_KEYSEG *seg,*end;
+ HA_KEYSEG *seg,*end;
int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo,
uchar *page,uchar *key,
uint key_len,uint comp_flag,uchar * *ret_pos,
@@ -147,6 +134,8 @@ typedef struct st_mi_keydef /* Key definition with open & info */
struct st_mi_s_param *s_temp);
void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos,
struct st_mi_s_param *s_temp);
+ int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
+ int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
} MI_KEYDEF;
@@ -157,7 +146,7 @@ typedef struct st_unique_def /* Segment definition of unique */
uint16 keysegs; /* Number of key-segment */
uchar key; /* Mapped to which key */
uint8 null_are_equal;
- MI_KEYSEG *seg,*end;
+ HA_KEYSEG *seg,*end;
} MI_UNIQUEDEF;
typedef struct st_mi_decode_tree /* Decode huff-table */
@@ -321,6 +310,7 @@ typedef struct st_sort_key_blocks /* Used when sorting */
int inited;
} SORT_KEY_BLOCKS;
+
typedef struct st_mi_check_param
{
ulonglong auto_increment_value;
@@ -339,7 +329,8 @@ typedef struct st_mi_check_param
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair, force_sort, calc_checksum;
- char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
+ char temp_filename[FN_REFLEN],*isam_file_name;
+ MY_TMPDIR *tmpdir;
int tmpfile_createflag;
myf myf_rw;
IO_CACHE read_cache;
@@ -351,6 +342,12 @@ typedef struct st_mi_check_param
char *op_name;
} MI_CHECK;
+typedef struct st_sort_ft_buf
+{
+ uchar *buf, *end;
+ int count;
+ uchar lastkey[MI_MAX_KEY_BUFF];
+} SORT_FT_BUF;
typedef struct st_sort_info
{
@@ -363,37 +360,13 @@ typedef struct st_sort_info
MI_CHECK *param;
char *buff;
SORT_KEY_BLOCKS *key_block,*key_block_end;
- /* sync things*/
+ SORT_FT_BUF *ft_buf;
+ /* sync things */
uint got_error, threads_running;
pthread_mutex_t mutex;
pthread_cond_t cond;
} SORT_INFO;
-
-typedef struct st_mi_sort_param
-{
- pthread_t thr;
- IO_CACHE read_cache, tempfile, tempfile_for_exceptions;
- DYNAMIC_ARRAY buffpek;
- ulonglong unique[MI_MAX_KEY_SEG+1];
- my_off_t pos,max_pos,filepos,start_recpos;
- uint key, key_length,real_key_length,sortbuff_size;
- uint maxbuffers, keys, find_length, sort_keys_length;
- my_bool fix_datafile, master;
- MI_KEYDEF *keyinfo;
- SORT_INFO *sort_info;
- uchar **sort_keys;
- byte *rec_buff;
- void *wordlist, *wordptr;
- char *record;
- char *tmpdir;
- int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *);
- int (*key_read)(struct st_mi_sort_param *,void *);
- int (*key_write)(struct st_mi_sort_param *, const void *);
- void (*lock_in_memory)(MI_CHECK *);
-} MI_SORT_PARAM;
-
-
/* functions in mi_check */
void myisamchk_init(MI_CHECK *param);
int chk_status(MI_CHECK *param, MI_INFO *info);
@@ -424,9 +397,7 @@ int filecopy(MI_CHECK *param, File to,File from,my_off_t start,
my_off_t length, const char *type);
int movepoint(MI_INFO *info,byte *record,my_off_t oldpos,
my_off_t newpos, uint prot_key);
-int sort_write_record(MI_SORT_PARAM *sort_param);
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile);
-int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong);
int test_if_almost_full(MI_INFO *info);
int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename);
void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
diff --git a/include/myisammrg.h b/include/myisammrg.h
index ea882450eef..8b09e1a9231 100644
--- a/include/myisammrg.h
+++ b/include/myisammrg.h
@@ -86,6 +86,7 @@ extern int myrg_rfirst(MYRG_INFO *file,byte *buf,int inx);
extern int myrg_rlast(MYRG_INFO *file,byte *buf,int inx);
extern int myrg_rnext(MYRG_INFO *file,byte *buf,int inx);
extern int myrg_rprev(MYRG_INFO *file,byte *buf,int inx);
+extern int myrg_rnext_same(MYRG_INFO *file,byte *buf);
extern int myrg_rkey(MYRG_INFO *file,byte *buf,int inx,const byte *key,
uint key_len, enum ha_rkey_function search_flag);
extern int myrg_rrnd(MYRG_INFO *file,byte *buf,ulonglong pos);
diff --git a/include/myisampack.h b/include/myisampack.h
index 6004177cfb0..95793e2aaeb 100644
--- a/include/myisampack.h
+++ b/include/myisampack.h
@@ -214,7 +214,7 @@
#ifdef BIG_TABLES
#define mi_rowstore(T,A) mi_int8store(T,A)
-#define mi_rowkorr(T) mi_uint8korr(T)
+#define mi_rowkorr(T) mi_uint8korr(T)
#else
#define mi_rowstore(T,A) { mi_int4store(T,0); mi_int4store(((T)+4),A); }
#define mi_rowkorr(T) mi_uint4korr((T)+4)
diff --git a/include/mysql.h b/include/mysql.h
index 486caa5baa5..51bffa60294 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -56,6 +56,12 @@ typedef int my_socket;
#include "mysql_com.h"
#include "mysql_version.h"
+#include "typelib.h"
+#ifndef DBUG_OFF
+#define CHECK_EXTRA_ARGUMENTS
+#endif
+
+#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */
extern unsigned int mysql_port;
extern char *mysql_unix_port;
@@ -72,16 +78,24 @@ extern char *mysql_unix_port;
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
typedef struct st_mysql_field {
- char *name; /* Name of column */
- char *table; /* Table of column if column was a field */
- char *org_table; /* Org table name if table was an alias */
- char *db; /* Database for table */
- char *def; /* Default value (set by mysql_list_fields) */
- unsigned long length; /* Width of column */
- unsigned long max_length; /* Max width of selected set */
- unsigned int flags; /* Div flags */
- unsigned int decimals; /* Number of decimals in field */
- enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
+ char *name; /* Name of column */
+ char *org_name; /* Original column name, if an alias */
+ char *table; /* Table of column if column was a field */
+ char *org_table; /* Org table name, if table was an alias */
+ char *db; /* Database for table */
+ char *def; /* Default value (set by mysql_list_fields) */
+ unsigned long length; /* Width of column */
+ unsigned long max_length; /* Max width of selected set */
+ unsigned int name_length;
+ unsigned int org_name_length;
+ unsigned int table_length;
+ unsigned int org_table_length;
+ unsigned int db_length;
+ unsigned int def_length;
+ unsigned int flags; /* Div flags */
+ unsigned int decimals; /* Number of decimals in field */
+ unsigned int charsetnr; /* Character set */
+ enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
} MYSQL_FIELD;
typedef char **MYSQL_ROW; /* return data as array of strings */
@@ -111,12 +125,17 @@ typedef struct st_mysql_data {
unsigned int fields;
MYSQL_ROWS *data;
MEM_ROOT alloc;
+#ifdef EMBEDDED_LIBRARY
+ MYSQL_ROWS **prev_ptr;
+#endif
} MYSQL_DATA;
struct st_mysql_options {
- unsigned int connect_timeout,client_flag;
+ unsigned int connect_timeout;
+ unsigned long client_flag;
unsigned int port;
- char *host,*init_command,*user,*password,*unix_socket,*db;
+ char *host,*user,*password,*unix_socket,*db;
+ struct st_dynamic_array *init_commands;
char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
char *ssl_key; /* PEM key file */
char *ssl_cert; /* PEM cert file */
@@ -141,31 +160,52 @@ struct st_mysql_options {
a read that is replication-aware
*/
my_bool no_master_reads;
+#ifdef EMBEDDED_LIBRARY
+ my_bool separate_thread;
+#endif
+ char *shared_memory_base_name;
+ unsigned int protocol;
};
-enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
- MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND,
- MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
- MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME,
- MYSQL_OPT_LOCAL_INFILE};
+enum mysql_option
+{
+ MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND,
+ MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME,
+ MYSQL_OPT_LOCAL_INFILE, MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME
+#ifdef EMBEDDED_LIBRARY
+ , MYSQL_OPT_USE_RESULT
+#endif
+};
-enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
- MYSQL_STATUS_USE_RESULT};
+enum mysql_status
+{
+ MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,MYSQL_STATUS_USE_RESULT
+};
+enum mysql_protocol_type
+{
+ MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, MYSQL_PROTOCOL_PIPE,
+ MYSQL_PROTOCOL_MEMORY
+};
/*
There are three types of queries - the ones that have to go to
the master, the ones that go to a slave, and the adminstrative
type which must happen on the pivot connectioin
*/
-enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
- MYSQL_RPL_ADMIN };
+enum mysql_rpl_type
+{
+ MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
+};
+
+#ifndef EMBEDDED_LIBRARY
-typedef struct st_mysql {
+typedef struct st_mysql
+{
NET net; /* Communication parameters */
gptr connector_fd; /* ConnectorFd for SSL */
- char *host,*user,*passwd,*unix_socket,*server_version,*host_info,
- *info,*db;
+ char *host,*user,*passwd,*unix_socket,*server_version,*host_info,*info;
+ char *db;
struct charset_info_st *charset;
MYSQL_FIELD *fields;
MEM_ROOT field_alloc;
@@ -174,16 +214,18 @@ typedef struct st_mysql {
my_ulonglong extra_info; /* Used by mysqlshow */
unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
- unsigned int port,client_flag,server_capabilities;
+ unsigned int port;
+ unsigned long client_flag,server_capabilities;
unsigned int protocol_version;
unsigned int field_count;
unsigned int server_status;
unsigned int server_language;
+ unsigned int warning_count;
struct st_mysql_options options;
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
- char scramble_buff[9];
+ char scramble_buff[21]; /* New protocol requires longer scramble*/
/*
Set if this is the original connection, not a master or a slave we have
@@ -199,8 +241,33 @@ typedef struct st_mysql {
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
/* needed for send/read/store/use result to work correctly with replication */
struct st_mysql* last_used_con;
+
+ LIST *stmts; /* list of all statements */
} MYSQL;
+#else
+
+struct st_mysql_res;
+
+typedef struct st_mysql
+{
+ struct st_mysql_res *result;
+ void *thd;
+ struct charset_info_st *charset;
+ unsigned int server_language;
+ MYSQL_FIELD *fields;
+ MEM_ROOT field_alloc;
+ my_ulonglong affected_rows;
+ unsigned int field_count;
+ struct st_mysql_options options;
+ enum mysql_status status;
+ my_bool free_me; /* If free in mysql_close */
+ my_ulonglong insert_id; /* id if insert on table with NEXTNR */
+ unsigned int last_errno;
+ char *last_error;
+} MYSQL;
+
+#endif
typedef struct st_mysql_res {
my_ulonglong row_count;
@@ -277,12 +344,13 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
unsigned int STDCALL mysql_errno(MYSQL *mysql);
const char * STDCALL mysql_error(MYSQL *mysql);
+unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
const char * STDCALL mysql_info(MYSQL *mysql);
unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
MYSQL * STDCALL mysql_init(MYSQL *mysql);
-int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
+my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca,
const char *capath, const char *cipher);
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
@@ -293,25 +361,25 @@ MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
const char *db,
unsigned int port,
const char *unix_socket,
- unsigned int clientflag);
+ unsigned long clientflag);
void STDCALL mysql_close(MYSQL *sock);
int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
int STDCALL mysql_query(MYSQL *mysql, const char *q);
int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
unsigned long length);
-int STDCALL mysql_read_query_result(MYSQL *mysql);
+my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
unsigned long length);
/* perform query on master */
-int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
- unsigned long length);
-int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
+my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
/* perform query on slave */
-int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length);
-int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
+my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
/*
enable/disable parsing of all queries to decide if they go on master or
@@ -326,12 +394,12 @@ int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
/* get the value of the master read flag */
-int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
+my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
/* discover the master and its slaves */
-int STDCALL mysql_rpl_probe(MYSQL* mysql);
+my_bool STDCALL mysql_rpl_probe(MYSQL* mysql);
/* set the master, close/free the old one, if it is not a pivot */
int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
@@ -351,6 +419,7 @@ int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
int STDCALL mysql_ping(MYSQL *mysql);
const char * STDCALL mysql_stat(MYSQL *mysql);
const char * STDCALL mysql_get_server_info(MYSQL *mysql);
+unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
const char * STDCALL mysql_get_client_info(void);
const char * STDCALL mysql_get_host_info(MYSQL *mysql);
unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
@@ -403,6 +472,109 @@ int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
char* res_buf,
int res_buf_size);
+
+
+/*
+ The following definitions are added for the enhanced
+ client-server protocol
+*/
+
+/* statement state */
+enum PREP_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
+
+/*
+ client TIME structure to handle TIME, DATE and TIMESTAMP directly in
+ binary protocol
+*/
+enum mysql_st_timestamp_type { MYSQL_TIMESTAMP_NONE, MYSQL_TIMESTAMP_DATE,
+ MYSQL_TIMESTAMP_FULL, MYSQL_TIMESTAMP_TIME };
+
+typedef struct mysql_st_time
+{
+ unsigned int year,month,day,hour,minute,second;
+ unsigned long second_part;
+ my_bool neg;
+
+ enum mysql_st_timestamp_type time_type;
+
+} MYSQL_TIME;
+
+
+/* bind structure */
+typedef struct st_mysql_bind
+{
+ unsigned long *length; /* output length pointer */
+ my_bool *is_null; /* Pointer to null indicators */
+ char *buffer; /* buffer to get/put data */
+ enum enum_field_types buffer_type; /* buffer type */
+ /* Must be set for string/blob data */
+ unsigned long buffer_length; /* buffer length */
+
+ /* The following are for internal use. Set by mysql_bind_param */
+ unsigned int param_number; /* For null count and error messages */
+ my_bool long_data_used; /* If used with mysql_send_long_data */
+ void (*store_param_func)(NET *net, struct st_mysql_bind *param);
+ void (*fetch_result)(struct st_mysql_bind *, unsigned char **row);
+} MYSQL_BIND;
+
+
+/* statement handler */
+typedef struct st_mysql_stmt
+{
+ MYSQL *mysql; /* connection handle */
+ MYSQL_BIND *params; /* input parameters */
+ MYSQL_RES *result; /* resultset */
+ MYSQL_BIND *bind; /* row binding */
+ MYSQL_FIELD *fields; /* prepare meta info */
+ LIST list; /* list to keep track of all stmts */
+ char *query; /* query buffer */
+ MEM_ROOT mem_root; /* root allocations */
+ unsigned long param_count; /* parameters count */
+ unsigned long field_count; /* fields count */
+ unsigned long stmt_id; /* Id for prepared statement */
+ unsigned int last_errno; /* error code */
+ enum PREP_STMT_STATE state; /* statement state */
+ char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
+ my_bool long_alloced; /* flag to indicate long alloced */
+ my_bool send_types_to_server; /* Types sent to server */
+ my_bool param_buffers; /* param bound buffers */
+ my_bool res_buffers; /* output bound buffers */
+ my_bool result_buffered; /* Results buffered */
+} MYSQL_STMT;
+
+
+MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query,
+ unsigned long length);
+int STDCALL mysql_execute(MYSQL_STMT * stmt);
+unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
+unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
+const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_commit(MYSQL * mysql);
+my_bool STDCALL mysql_rollback(MYSQL * mysql);
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
+int STDCALL mysql_fetch(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_send_long_data(MYSQL_STMT *stmt,
+ unsigned int param_number,
+ const char *data,
+ unsigned long length);
+MYSQL_RES *STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
+MYSQL_RES *STDCALL mysql_param_result(MYSQL_STMT *stmt);
+my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_more_results(MYSQL *mysql);
+my_bool STDCALL mysql_next_result(MYSQL *mysql);
+
+
+
+/* new status messages */
+#define MYSQL_SUCCESS 0
+#define MYSQL_STATUS_ERROR 1
+#define MYSQL_NO_DATA 100
+#define MYSQL_NEED_DATA 99
+
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
#ifdef USE_OLD_FUNCTIONS
@@ -419,8 +591,9 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
They are not for general usage
*/
-int simple_command(MYSQL *mysql,enum enum_server_command command,
- const char *arg, unsigned long length, my_bool skipp_check);
+my_bool
+simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ unsigned long length, my_bool skip_check);
unsigned long net_safe_read(MYSQL* mysql);
void STDCALL mysql_once_init(void);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 963c1212794..7eac3b113d2 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -29,20 +29,28 @@
#define LOCAL_HOST "localhost"
#define LOCAL_HOST_NAMEDPIPE "."
+
#if defined(__WIN__) && !defined( _CUSTOMCONFIG_)
#define MYSQL_NAMEDPIPE "MySQL"
#define MYSQL_SERVICENAME "MySql"
#endif /* __WIN__ */
-enum enum_server_command {
+enum enum_server_command
+{
COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
- COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS,
+ COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS,
COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
- COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
- COM_END /* Must be last! */
+ COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
+ COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
+ COM_END /* Must be last */
};
+
+#define SCRAMBLE_LENGTH 8
+#define SCRAMBLE41_LENGTH 20
+
+
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */
@@ -50,7 +58,8 @@ enum enum_server_command {
#define BLOB_FLAG 16 /* Field is a blob */
#define UNSIGNED_FLAG 32 /* Field is unsigned */
#define ZEROFILL_FLAG 64 /* Field is zerofill */
-#define BINARY_FLAG 128
+#define BINARY_FLAG 128 /* Field is binary */
+
/* The following are only sent to new clients */
#define ENUM_FLAG 256 /* field is an enum */
#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */
@@ -95,9 +104,14 @@ enum enum_server_command {
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
+#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */
+#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
+#define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multi query support */
-#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
-#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
+#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
+#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
+#define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */
+#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
#define MYSQL_ERRMSG_SIZE 200
#define NET_READ_TIMEOUT 30 /* Timeout on read */
@@ -111,16 +125,15 @@ typedef struct st_vio Vio;
#define MAX_BLOB_WIDTH 8192 /* Default width for blob */
typedef struct st_net {
+#ifndef EMBEDDED_LIBRARY
Vio* vio;
unsigned char *buff,*buff_end,*write_pos,*read_pos;
my_socket fd; /* For Perl DBI/dbd */
unsigned long max_packet,max_packet_size;
- unsigned int last_errno,pkt_nr,compress_pkt_nr;
+ unsigned int pkt_nr,compress_pkt_nr;
unsigned int write_timeout, read_timeout, retry_count;
int fcntl;
- char last_error[MYSQL_ERRMSG_SIZE];
- unsigned char error;
- my_bool return_errno,compress;
+ my_bool compress;
/*
The following variable is set if we are doing several queries in one
command ( as in LOAD TABLE ... FROM MASTER ),
@@ -131,32 +144,79 @@ typedef struct st_net {
unsigned char reading_or_writing;
char save_char;
my_bool no_send_ok;
+ /*
+ Pointer to query object in query cache, do not equal NULL (0) for
+ queries in cache that have not stored its results yet
+ */
+#endif
+ char last_error[MYSQL_ERRMSG_SIZE];
+ unsigned int last_errno;
+ unsigned char error;
gptr query_cache_query;
+ my_bool report_error; /* We should report error (we have unreported error) */
+ my_bool return_errno;
} NET;
#define packet_error (~(unsigned long) 0)
-enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
- FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
- FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
- FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP,
- FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24,
- FIELD_TYPE_DATE, FIELD_TYPE_TIME,
- FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR,
- FIELD_TYPE_NEWDATE,
- FIELD_TYPE_ENUM=247,
- FIELD_TYPE_SET=248,
- FIELD_TYPE_TINY_BLOB=249,
- FIELD_TYPE_MEDIUM_BLOB=250,
- FIELD_TYPE_LONG_BLOB=251,
- FIELD_TYPE_BLOB=252,
- FIELD_TYPE_VAR_STRING=253,
- FIELD_TYPE_STRING=254,
- FIELD_TYPE_GEOMETRY=255
+enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
+ MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
+ MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
+ MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
+ MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
+ MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
+ MYSQL_TYPE_NEWDATE,
+ MYSQL_TYPE_ENUM=247,
+ MYSQL_TYPE_SET=248,
+ MYSQL_TYPE_TINY_BLOB=249,
+ MYSQL_TYPE_MEDIUM_BLOB=250,
+ MYSQL_TYPE_LONG_BLOB=251,
+ MYSQL_TYPE_BLOB=252,
+ MYSQL_TYPE_VAR_STRING=253,
+ MYSQL_TYPE_STRING=254,
+ MYSQL_TYPE_GEOMETRY=255
+
};
-#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */
-#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */
+/* For backward compatibility */
+#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
+#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
+#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
+#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
+#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT
+#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE
+#define FIELD_TYPE_NULL MYSQL_TYPE_NULL
+#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP
+#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG
+#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24
+#define FIELD_TYPE_DATE MYSQL_TYPE_DATE
+#define FIELD_TYPE_TIME MYSQL_TYPE_TIME
+#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME
+#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR
+#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
+#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
+#define FIELD_TYPE_SET MYSQL_TYPE_SET
+#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
+#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB
+#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB
+#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB
+#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING
+#define FIELD_TYPE_STRING MYSQL_TYPE_STRING
+#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
+#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
+#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
+
+#if TO_BE_INCLUDED_LATER
+/* For bind applications, to indicate unsigned buffers */
+#define MYSQL_TYPE_UTINY -10
+#define MYSQL_TYPE_USHORT -9
+#define MYSQL_TYPE_ULONG -8
+#define MYSQL_TYPE_UFLOAT -7
+#define MYSQL_TYPE_UDOUBLE -6
+#define MYSQL_TYPE_ULONGLONG -5
+#define MYSQL_TYPE_UINT24 -4
+#endif
#define net_new_transaction(net) ((net)->pkt_nr=0)
@@ -164,21 +224,31 @@ enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
extern "C" {
#endif
-int my_net_init(NET *net, Vio* vio);
+my_bool my_net_init(NET *net, Vio* vio);
void my_net_local_init(NET *net);
void net_end(NET *net);
void net_clear(NET *net);
-int net_flush(NET *net);
-int my_net_write(NET *net,const char *packet,unsigned long len);
-int net_write_command(NET *net,unsigned char command,const char *packet,
- unsigned long len);
+my_bool net_realloc(NET *net, unsigned long length);
+#ifndef EMBEDDED_LIBRARY
+my_bool net_flush(NET *net);
+#else
+#define net_flush(A)
+#endif
+
+my_bool my_net_write(NET *net,const char *packet,unsigned long len);
+my_bool net_write_command(NET *net,unsigned char command,
+ const char *header, unsigned long head_len,
+ const char *packet, unsigned long len);
int net_real_write(NET *net,const char *packet,unsigned long len);
unsigned long my_net_read(NET *net);
-/* The following function is not meant for normal usage */
+/*
+ The following function is not meant for normal usage
+ Currently it's used internally by manager.c
+*/
struct sockaddr;
-int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
- unsigned int timeout);
+my_bool my_connect(my_socket s, const struct sockaddr *name,
+ unsigned int namelen, unsigned int timeout);
struct rand_struct {
unsigned long seed1,seed2,max_value;
@@ -191,7 +261,7 @@ struct rand_struct {
/* The following is for user defined functions */
-enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT};
+enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
typedef struct st_udf_args
{
@@ -229,9 +299,22 @@ extern unsigned long net_buffer_length;
void randominit(struct rand_struct *,unsigned long seed1,
unsigned long seed2);
double rnd(struct rand_struct *);
-void make_scrambled_password(char *to,const char *password);
+void make_scrambled_password(char *to,const char *password,
+ my_bool force_old_scramble,struct rand_struct *rand_st);
+int get_password_length(my_bool force_old_scramble);
+char get_password_version(const char* password);
+void create_random_string(int length,struct rand_struct *rand_st,char* target);
+my_bool validate_password(const char* password, const char* message,
+ unsigned long* salt);
+void password_hash_stage1(char *to, const char *password);
+void password_hash_stage2(char *to,const char *salt);
+void password_crypt(const char* from,char* to, const char* password,int length);
+void get_hash_and_password(unsigned long* salt, unsigned char pversion,char* hash,
+ unsigned char* bin_password);
void get_salt_from_password(unsigned long *res,const char *password);
-void make_password_from_salt(char *to, unsigned long *hash_res);
+void create_key_from_old_password(const char* password,char* key);
+void make_password_from_salt(char *to, unsigned long *hash_res,
+ unsigned char password_version);
char *scramble(char *to,const char *message,const char *password,
my_bool old_ver);
my_bool check_scramble(const char *, const char *message,
@@ -252,5 +335,7 @@ void my_thread_end(void);
#endif
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
+#define MYSQL_STMT_HEADER 4
+#define MYSQL_LONG_DATA_HEADER 6
#endif
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 0898b3d576f..377f714bfff 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -109,7 +109,7 @@
#define ER_CANT_REMOVE_ALL_FIELDS 1090
#define ER_CANT_DROP_FIELD_OR_KEY 1091
#define ER_INSERT_INFO 1092
-#define ER_INSERT_TABLE_USED 1093
+#define ER_UPDATE_TABLE_USED 1093
#define ER_NO_SUCH_THREAD 1094
#define ER_KILL_DENIED_ERROR 1095
#define ER_NO_TABLES_USED 1096
@@ -253,4 +253,17 @@
#define ER_CANT_USE_OPTION_HERE 1234
#define ER_NOT_SUPPORTED_YET 1235
#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
-#define ER_ERROR_MESSAGES 237
+#define ER_WRONG_FK_DEF 1237
+#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1238
+#define ER_CARDINALITY_COL 1239
+#define ER_SUBSELECT_NO_1_ROW 1240
+#define ER_UNKNOWN_STMT_HANDLER 1241
+#define ER_CORRUPT_HELP_DB 1242
+#define ER_CYCLIC_REFERENCE 1243
+#define ER_AUTO_CONVERT 1244
+#define ER_ILLEGAL_REFERENCE 1245
+#define ER_DERIVED_MUST_HAVE_ALIAS 1246
+#define ER_SELECT_REDUCED 1247
+#define ER_TABLENAME_NOT_ALLOWED_HERE 1248
+#define ER_NOT_SUPPORTED_AUTH_MODE 1249
+#define ER_ERROR_MESSAGES 250
diff --git a/include/thr_lock.h b/include/thr_lock.h
index 7459849cb04..cf5b0cce4bc 100644
--- a/include/thr_lock.h
+++ b/include/thr_lock.h
@@ -74,6 +74,7 @@ typedef struct st_thr_lock_data {
enum thr_lock_type type;
ulong thread_id;
void *status_param; /* Param to status functions */
+ void *debug_print_param;
} THR_LOCK_DATA;
struct st_lock_list {
@@ -97,6 +98,9 @@ typedef struct st_thr_lock {
} THR_LOCK;
+extern LIST *thr_lock_thread_list;
+extern pthread_mutex_t THR_LOCK_lock;
+
my_bool init_thr_lock(void); /* Must be called once/thread */
void thr_lock_init(THR_LOCK *lock);
void thr_lock_delete(THR_LOCK *lock);
diff --git a/include/typelib.h b/include/typelib.h
new file mode 100644
index 00000000000..1b049d19a11
--- /dev/null
+++ b/include/typelib.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 _typelib_h
+#define _typelib_h
+
+typedef struct st_typelib { /* Different types saved here */
+ unsigned int count; /* How many types */
+ const char *name; /* Name of typelib */
+ const char **type_names;
+} TYPELIB;
+
+extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name);
+extern void make_type(char *to,unsigned int nr,TYPELIB *typelib);
+extern const char *get_type(TYPELIB *typelib,unsigned int nr);
+
+extern TYPELIB sql_protocol_typelib;
+
+#endif /* _typelib_h */
diff --git a/include/violite.h b/include/violite.h
index 6c8ad1f4b69..4963fbb21e4 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -31,8 +31,11 @@
extern "C" {
#endif /* __cplusplus */
-enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
- VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
+enum enum_vio_type
+{
+ VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE,
+ VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY
+};
#ifndef __WIN__
#define HANDLE void *
@@ -41,6 +44,9 @@ enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
Vio* vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost);
#ifdef __WIN__
Vio* vio_new_win32pipe(HANDLE hPipe);
+Vio* vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map,
+ HANDLE event_server_wrote, HANDLE event_server_read,
+ HANDLE event_client_wrote, HANDLE event_client_read);
#endif
void vio_delete(Vio* vio);
@@ -107,6 +113,17 @@ my_bool vio_poll_read(Vio *vio,uint timeout);
}
#endif
+#ifdef HAVE_SMEM
+int vio_read_shared_memory(Vio *vio, gptr buf, int size);
+int vio_write_shared_memory(Vio *vio, const gptr buf, int size);
+int vio_close_shared_memory(Vio * vio);
+#endif
+#ifdef __WIN__
+int vio_read_pipe(Vio *vio, gptr buf, int size);
+int vio_write_pipe(Vio *vio, const gptr buf, int size);
+int vio_close_pipe(Vio * vio);
+#endif
+
#if defined(HAVE_VIO) && !defined(DONT_MAP_VIO)
#define vio_delete(vio) (vio)->viodelete(vio)
#define vio_errno(vio) (vio)->vioerrno(vio)
@@ -202,6 +219,7 @@ enum SSL_type
SSL_TYPE_SPECIFIED
};
+
#ifndef EMBEDDED_LIBRARY
/* This structure is for every connection on both sides */
struct st_vio
@@ -219,7 +237,7 @@ struct st_vio
void (*viodelete)(Vio*);
int (*vioerrno)(Vio*);
int (*read)(Vio*, gptr, int);
- int (*write)(Vio*, gptr, int);
+ int (*write)(Vio*, const gptr, int);
int (*vioblocking)(Vio*, my_bool, my_bool *);
my_bool (*is_blocking)(Vio*);
int (*viokeepalive)(Vio*, my_bool);
@@ -232,6 +250,17 @@ struct st_vio
#ifdef HAVE_OPENSSL
SSL* ssl_;
#endif /* HAVE_OPENSSL */
+#ifdef HAVE_SMEM
+ HANDLE handle_file_map;
+ char *handle_map;
+ HANDLE event_server_wrote;
+ HANDLE event_server_read;
+ HANDLE event_client_wrote;
+ HANDLE event_client_read;
+ long shared_memory_remain;
+ char *shared_memory_pos;
+ NET *net;
+#endif /* HAVE_SMEM */
#endif /* HAVE_VIO */
};
#endif /* EMBEDDED_LIBRARY */
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index e61dcf4ecee..69952c842ce 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -291,6 +291,7 @@ btr_cur_search_to_nth_level(
&& latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
&& !estimate
&& mode != PAGE_CUR_LE_OR_EXTENDS
+ && srv_use_adaptive_hash_indexes
&& btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor,
has_search_latch, mtr)) {
@@ -495,9 +496,11 @@ retry_page_get:
cursor->up_bytes = up_bytes;
#ifdef BTR_CUR_ADAPT
- btr_search_info_update(index, cursor);
-#endif
+ if (srv_use_adaptive_hash_indexes) {
+ btr_search_info_update(index, cursor);
+ }
+#endif
ut_ad(cursor->up_match != ULINT_UNDEFINED
|| mode != PAGE_CUR_GE);
ut_ad(cursor->up_match != ULINT_UNDEFINED
diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c
index 7b817d8263d..13efacb9da3 100644
--- a/innobase/btr/btr0pcur.c
+++ b/innobase/btr/btr0pcur.c
@@ -95,7 +95,9 @@ btr_pcur_store_position(
ut_a(cursor->latch_mode != BTR_NO_LATCHES);
if (page_get_n_recs(page) == 0) {
- /* It must be an empty index tree */
+ /* It must be an empty index tree; NOTE that in this case
+ we do not store the modify_clock, but always do a search
+ if we restore the cursor position */
ut_a(btr_page_get_next(page, mtr) == FIL_NULL
&& btr_page_get_prev(page, mtr) == FIL_NULL);
@@ -128,12 +130,13 @@ btr_pcur_store_position(
} else {
cursor->rel_pos = BTR_PCUR_ON;
}
-
+
cursor->old_stored = BTR_PCUR_OLD_STORED;
cursor->old_rec = dict_tree_copy_rec_order_prefix(tree, rec,
&(cursor->old_rec_buf),
&(cursor->buf_size));
+ cursor->block_when_stored = buf_block_align(page);
cursor->modify_clock = buf_frame_get_modify_clock(page);
}
@@ -205,6 +208,9 @@ btr_pcur_restore_position(
if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
+ /* In these cases we do not try an optimistic restoration,
+ but always do a search */
+
if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
from_left = TRUE;
} else {
@@ -214,6 +220,10 @@ btr_pcur_restore_position(
btr_cur_open_at_index_side(from_left,
btr_pcur_get_btr_cur(cursor)->index, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
+
+ cursor->block_when_stored =
+ buf_block_align(btr_pcur_get_page(cursor));
+
return(FALSE);
}
@@ -224,8 +234,9 @@ btr_pcur_restore_position(
if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) {
/* Try optimistic restoration */
- if (buf_page_optimistic_get(latch_mode, page,
- cursor->modify_clock, mtr)) {
+ if (buf_page_optimistic_get(latch_mode,
+ cursor->block_when_stored, page,
+ cursor->modify_clock, mtr)) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
@@ -270,8 +281,6 @@ btr_pcur_restore_position(
btr_pcur_open_with_no_init(btr_pcur_get_btr_cur(cursor)->index, tuple,
mode, latch_mode, cursor, 0, mtr);
-
- cursor->old_stored = BTR_PCUR_OLD_STORED;
/* Restore the old search mode */
cursor->search_mode = old_mode;
@@ -280,11 +289,18 @@ btr_pcur_restore_position(
&& btr_pcur_is_on_user_rec(cursor, mtr)
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) {
- /* We have to store the NEW value for the modify clock, since
- the cursor can now be on a different page! */
+ /* We have to store the NEW value for the modify clock, since
+ the cursor can now be on a different page! But we can retain
+ the value of old_rec */
+
+ cursor->modify_clock =
+ buf_frame_get_modify_clock(btr_pcur_get_page(cursor));
+
+ cursor->block_when_stored =
+ buf_block_align(btr_pcur_get_page(cursor));
+
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
- cursor->modify_clock = buf_frame_get_modify_clock(
- buf_frame_align(btr_pcur_get_rec(cursor)));
mem_heap_free(heap);
return(TRUE);
@@ -292,9 +308,10 @@ btr_pcur_restore_position(
mem_heap_free(heap);
- /* We have to store position information, modify clock value, etc.
- because the cursor may now be on a different page */
-
+ /* We have to store new position information, modify_clock etc.,
+ to the cursor because it can now be on a different page, the record
+ under it may have been removed, etc. */
+
btr_pcur_store_position(cursor, mtr);
return(FALSE);
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index c9a5ec5307f..3c6ec424434 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -196,7 +196,29 @@ If a new page is referenced in the buf_pool, and several pages
of its random access area (for instance, 32 consecutive pages
in a tablespace) have recently been referenced, we may predict
that the whole area may be needed in the near future, and issue
-the read requests for the whole area. */
+the read requests for the whole area.
+
+ AWE implementation
+ ------------------
+
+By a 'block' we mean the buffer header of type buf_block_t. By a 'page'
+we mean the physical 16 kB memory area allocated from RAM for that block.
+By a 'frame' we mean a 16 kB area in the virtual address space of the
+process, in the frame_mem of buf_pool.
+
+We can map pages to the frames of the buffer pool.
+
+1) A buffer block allocated to use as a non-data page, e.g., to the lock
+table, is always mapped to a frame.
+2) A bufferfixed or io-fixed data page is always mapped to a frame.
+3) When we need to map a block to frame, we look from the list
+awe_LRU_free_mapped and try to unmap its last block, but note that
+bufferfixed or io-fixed pages cannot be unmapped.
+4) For every frame in the buffer pool there is always a block whose page is
+mapped to it. When we create the buffer pool, we map the first elements
+in the free list to the frames.
+5) When we have AWE enabled, we disable adaptive hash indexes.
+*/
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
@@ -346,12 +368,15 @@ void
buf_block_init(
/*===========*/
buf_block_t* block, /* in: pointer to control block */
- byte* frame) /* in: pointer to buffer frame */
+ byte* frame) /* in: pointer to buffer frame, or NULL if in
+ the case of AWE there is no frame */
{
block->state = BUF_BLOCK_NOT_USED;
block->frame = frame;
+ block->awe_info = NULL;
+
block->modify_clock = ut_dulint_zero;
block->file_page_was_freed = FALSE;
@@ -360,34 +385,48 @@ buf_block_init(
rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock)));
-
- rw_lock_create(&(block->read_lock));
- rw_lock_set_level(&(block->read_lock), SYNC_NO_ORDER_CHECK);
+#ifdef UNIV_SYNC_DEBUG
rw_lock_create(&(block->debug_latch));
rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
+#endif
}
/************************************************************************
-Creates a buffer buf_pool object. */
-static
+Creates the buffer pool. */
+
buf_pool_t*
-buf_pool_create(
-/*============*/
+buf_pool_init(
+/*==========*/
/* out, own: buf_pool object, NULL if not
- enough memory */
+ enough memory or error */
ulint max_size, /* in: maximum size of the buf_pool in
blocks */
- ulint curr_size) /* in: current size to use, must be <=
+ ulint curr_size, /* in: current size to use, must be <=
max_size, currently must be equal to
max_size */
+ ulint n_frames) /* in: number of frames; if AWE is used,
+ this is the size of the address space window
+ where physical memory pages are mapped; if
+ AWE is not used then this must be the same
+ as max_size */
{
byte* frame;
ulint i;
buf_block_t* block;
ut_a(max_size == curr_size);
+ ut_a(srv_use_awe || n_frames == max_size);
+ if (n_frames > curr_size) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: you must specify in my.cnf .._awe_mem_mb larger\n"
+"InnoDB: than .._buffer_pool_size. Now the former is %lu pages,\n"
+"InnoDB: the latter %lu pages.\n", curr_size, n_frames);
+
+ return(NULL);
+ }
+
buf_pool = mem_alloc(sizeof(buf_pool_t));
/* 1. Initialize general fields
@@ -396,8 +435,38 @@ buf_pool_create(
mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex));
-
- buf_pool->frame_mem = ut_malloc(UNIV_PAGE_SIZE * (max_size + 1));
+
+ if (srv_use_awe) {
+ /*----------------------------------------*/
+ /* Allocate the virtual address space window, i.e., the
+ buffer pool frames */
+
+ buf_pool->frame_mem = os_awe_allocate_virtual_mem_window(
+ UNIV_PAGE_SIZE * (n_frames + 1));
+
+ /* Allocate the physical memory for AWE and the AWE info array
+ for buf_pool */
+
+ if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) {
+
+ fprintf(stderr,
+"InnoDB: AWE: Error: physical memory must be allocated in full megabytes.\n"
+"InnoDB: Trying to allocate %lu database pages.\n",
+ curr_size);
+
+ return(NULL);
+ }
+
+ if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info),
+ curr_size / ((1024 * 1024) / UNIV_PAGE_SIZE))) {
+
+ return(NULL);
+ }
+ /*----------------------------------------*/
+ } else {
+ buf_pool->frame_mem = ut_malloc(
+ UNIV_PAGE_SIZE * (n_frames + 1));
+ }
if (buf_pool->frame_mem == NULL) {
@@ -414,21 +483,60 @@ buf_pool_create(
buf_pool->max_size = max_size;
buf_pool->curr_size = curr_size;
+ buf_pool->n_frames = n_frames;
+
/* Align pointer to the first frame */
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);
+
buf_pool->frame_zero = frame;
+ buf_pool->high_end = frame + UNIV_PAGE_SIZE * n_frames;
+
+ if (srv_use_awe) {
+ /*----------------------------------------*/
+ /* Map an initial part of the allocated physical memory to
+ the window */
+
+ os_awe_map_physical_mem_to_window(buf_pool->frame_zero,
+ n_frames *
+ (UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE),
+ buf_pool->awe_info);
+ /*----------------------------------------*/
+ }
+
+ buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames);
+
+ if (buf_pool->blocks_of_frames == NULL) {
+
+ return(NULL);
+ }
- buf_pool->high_end = frame + UNIV_PAGE_SIZE * curr_size;
+ /* Init block structs and assign frames for them; in the case of
+ AWE there are less frames than blocks. Then we assign the frames
+ to the first blocks (we already mapped the memory above). We also
+ init the awe_info for every block. */
- /* Init block structs and assign frames for them */
for (i = 0; i < max_size; i++) {
block = buf_pool_get_nth_block(buf_pool, i);
+
+ if (i < n_frames) {
+ frame = buf_pool->frame_zero + i * UNIV_PAGE_SIZE;
+ *(buf_pool->blocks_of_frames + i) = block;
+ } else {
+ frame = NULL;
+ }
+
buf_block_init(block, frame);
- frame = frame + UNIV_PAGE_SIZE;
+
+ if (srv_use_awe) {
+ /*----------------------------------------*/
+ block->awe_info = buf_pool->awe_info
+ + i * (UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE);
+ /*----------------------------------------*/
+ }
}
-
+
buf_pool->page_hash = hash_create(2 * max_size);
buf_pool->n_pend_reads = 0;
@@ -438,12 +546,14 @@ buf_pool_create(
buf_pool->n_pages_read = 0;
buf_pool->n_pages_written = 0;
buf_pool->n_pages_created = 0;
-
+ buf_pool->n_pages_awe_remapped = 0;
+
buf_pool->n_page_gets = 0;
buf_pool->n_page_gets_old = 0;
buf_pool->n_pages_read_old = 0;
buf_pool->n_pages_written_old = 0;
buf_pool->n_pages_created_old = 0;
+ buf_pool->n_pages_awe_remapped_old = 0;
/* 2. Initialize flushing fields
---------------------------- */
@@ -466,40 +576,120 @@ buf_pool_create(
buf_pool->LRU_old = NULL;
+ UT_LIST_INIT(buf_pool->awe_LRU_free_mapped);
+
/* Add control blocks to the free list */
UT_LIST_INIT(buf_pool->free);
+
for (i = 0; i < curr_size; i++) {
block = buf_pool_get_nth_block(buf_pool, i);
- /* Wipe contents of page to eliminate a Purify warning */
- memset(block->frame, '\0', UNIV_PAGE_SIZE);
+ if (block->frame) {
+ /* Wipe contents of frame to eliminate a Purify
+ warning */
+
+ memset(block->frame, '\0', UNIV_PAGE_SIZE);
- UT_LIST_ADD_FIRST(free, buf_pool->free, block);
+ if (srv_use_awe) {
+ /* Add to the list of blocks mapped to
+ frames */
+
+ UT_LIST_ADD_LAST(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped, block);
+ }
+ }
+
+ UT_LIST_ADD_LAST(free, buf_pool->free, block);
}
mutex_exit(&(buf_pool->mutex));
- btr_search_sys_create(curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);
+ if (srv_use_adaptive_hash_indexes) {
+ btr_search_sys_create(
+ curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);
+ } else {
+ /* Create only a small dummy system */
+ btr_search_sys_create(1000);
+ }
return(buf_pool);
}
/************************************************************************
-Initializes the buffer buf_pool of the database. */
+Maps the page of block to a frame, if not mapped yet. Unmaps some page
+from the end of the awe_LRU_free_mapped. */
void
-buf_pool_init(
-/*==========*/
- ulint max_size, /* in: maximum size of the buf_pool in blocks */
- ulint curr_size) /* in: current size to use, must be <=
- max_size */
+buf_awe_map_page_to_frame(
+/*======================*/
+ buf_block_t* block, /* in: block whose page should be
+ mapped to a frame */
+ ibool add_to_mapped_list) /* in: TRUE if we in the case
+ we need to map the page should also
+ add the block to the
+ awe_LRU_free_mapped list */
{
- ut_a(buf_pool == NULL);
+ buf_block_t* bck;
- buf_pool_create(max_size, curr_size);
+ ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(block);
+
+ if (block->frame) {
+
+ return;
+ }
+
+ /* Scan awe_LRU_free_mapped from the end and try to find a block
+ which is not bufferfixed or io-fixed */
+
+ bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);
+
+ while (bck) {
+ if (bck->state == BUF_BLOCK_FILE_PAGE
+ && (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
+
+ /* We have to skip this */
+ bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck);
+ } else {
+ /* We can map block to the frame of bck */
+
+ os_awe_map_physical_mem_to_window(
+ bck->frame,
+ UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE,
+ block->awe_info);
+
+ block->frame = bck->frame;
+
+ *(buf_pool->blocks_of_frames
+ + (((ulint)(block->frame
+ - buf_pool->frame_zero))
+ >> UNIV_PAGE_SIZE_SHIFT))
+ = block;
+
+ bck->frame = NULL;
+ UT_LIST_REMOVE(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped,
+ bck);
+
+ if (add_to_mapped_list) {
+ UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped,
+ block);
+ }
+
+ buf_pool->n_pages_awe_remapped++;
+
+ return;
+ }
+ }
+
+ fprintf(stderr,
+"InnoDB: AWE: Fatal error: cannot find a page to unmap\n"
+"InnoDB: awe_LRU_free_mapped list length %lu\n",
+ UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
- ut_ad(buf_validate());
+ ut_a(0);
}
/************************************************************************
@@ -508,7 +698,9 @@ UNIV_INLINE
buf_block_t*
buf_block_alloc(void)
/*=================*/
- /* out, own: the allocated block */
+ /* out, own: the allocated block; also if AWE
+ is used it is guaranteed that the page is
+ mapped to a frame */
{
buf_block_t* block;
@@ -846,6 +1038,19 @@ loop:
}
}
+ /* If AWE is enabled and the page is not mapped to a frame, then
+ map it */
+
+ if (block->frame == NULL) {
+ ut_a(srv_use_awe);
+
+ /* We set second parameter TRUE because the block is in the
+ LRU list and we must put it to awe_LRU_free_mapped list once
+ mapped to a frame */
+
+ buf_awe_map_page_to_frame(block, TRUE);
+ }
+
#ifdef UNIV_SYNC_DEBUG
buf_block_buf_fix_inc_debug(block, file, line);
#else
@@ -900,8 +1105,26 @@ loop:
} else if (rw_latch == RW_NO_LATCH) {
if (must_read) {
- rw_lock_x_lock(&(block->read_lock));
- rw_lock_x_unlock(&(block->read_lock));
+ /* Let us wait until the read operation
+ completes */
+
+ for (;;) {
+ mutex_enter(&(buf_pool->mutex));
+
+ if (block->io_fix == BUF_IO_READ) {
+
+ mutex_exit(&(buf_pool->mutex));
+
+ /* Sleep 20 milliseconds */
+
+ os_thread_sleep(20000);
+ } else {
+
+ mutex_exit(&(buf_pool->mutex));
+
+ break;
+ }
+ }
}
fix_type = MTR_MEMO_BUF_FIX;
@@ -940,28 +1163,27 @@ buf_page_optimistic_get_func(
/*=========================*/
/* out: TRUE if success */
ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */
- buf_frame_t* guess, /* in: guessed frame */
+ buf_block_t* block, /* in: guessed buffer block */
+ buf_frame_t* guess, /* in: guessed frame; note that AWE may move
+ frames */
dulint modify_clock,/* in: modify clock value if mode is
..._GUESS_ON_CLOCK */
char* file, /* in: file name */
ulint line, /* in: line where called */
mtr_t* mtr) /* in: mini-transaction */
{
- buf_block_t* block;
ibool accessed;
ibool success;
ulint fix_type;
- ut_ad(mtr && guess);
+ ut_ad(mtr && block);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
- buf_pool->n_page_gets++;
-
- block = buf_block_align(guess);
mutex_enter(&(buf_pool->mutex));
- if (block->state != BUF_BLOCK_FILE_PAGE) {
+ /* If AWE is used, block may have a different frame now, e.g., NULL */
+
+ if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) {
mutex_exit(&(buf_pool->mutex));
@@ -1054,12 +1276,15 @@ buf_page_optimistic_get_func(
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
+ buf_pool->n_page_gets++;
+
return(TRUE);
}
/************************************************************************
This is used to get access to a known database page, when no waiting can be
-done. */
+done. For example, if a search in an adaptive hash index leads us to this
+frame. */
ibool
buf_page_get_known_nowait(
@@ -1078,13 +1303,11 @@ buf_page_get_known_nowait(
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
- buf_pool->n_page_gets++;
-
- block = buf_block_align(guess);
mutex_enter(&(buf_pool->mutex));
+ block = buf_block_align(guess);
+
if (block->state == BUF_BLOCK_REMOVE_HASH) {
/* Another thread is just freeing the block from the LRU list
of the buffer pool: do not try to access this page; this
@@ -1152,6 +1375,8 @@ buf_page_get_known_nowait(
ut_a((mode == BUF_KEEP_OLD)
|| (ibuf_count_get(block->space, block->offset) == 0));
#endif
+ buf_pool->n_page_gets++;
+
return(TRUE);
}
@@ -1322,8 +1547,6 @@ buf_page_init_for_read(
is completed. The x-lock is cleared by the io-handler thread. */
rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
-
- rw_lock_x_lock_gen(&(block->read_lock), BUF_IO_READ);
mutex_exit(&(buf_pool->mutex));
@@ -1546,9 +1769,7 @@ buf_page_io_complete(
buf_pool->n_pend_reads--;
buf_pool->n_pages_read++;
-
rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
- rw_lock_x_unlock_gen(&(block->read_lock), BUF_IO_READ);
if (buf_debug_prints) {
printf("Has read ");
@@ -1732,7 +1953,7 @@ buf_print(void)
ut_ad(buf_pool);
- size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE;
+ size = buf_pool->curr_size;
index_ids = mem_alloc(sizeof(dulint) * size);
counts = mem_alloc(sizeof(ulint) * size);
@@ -1847,7 +2068,7 @@ buf_print_io(
return;
}
- size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE;
+ size = buf_pool->curr_size;
mutex_enter(&(buf_pool->mutex));
@@ -1866,6 +2087,15 @@ buf_print_io(
buf += sprintf(buf,
"Modified db pages %lu\n",
UT_LIST_GET_LEN(buf_pool->flush_list));
+ if (srv_use_awe) {
+ buf += sprintf(buf,
+ "AWE: Buffer pool memory frames %lu\n",
+ buf_pool->n_frames);
+
+ buf += sprintf(buf,
+ "AWE: Database pages and free buffers mapped in frames %lu\n",
+ UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
+ }
buf += sprintf(buf, "Pending reads %lu \n", buf_pool->n_pend_reads);
@@ -1891,6 +2121,13 @@ buf_print_io(
(buf_pool->n_pages_written - buf_pool->n_pages_written_old)
/ time_elapsed);
+ if (srv_use_awe) {
+ buf += sprintf(buf, "AWE: %.2f page remaps/s\n",
+ (buf_pool->n_pages_awe_remapped
+ - buf_pool->n_pages_awe_remapped_old)
+ / time_elapsed);
+ }
+
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
buf += sprintf(buf, "Buffer pool hit rate %lu / 1000\n",
1000
@@ -1906,6 +2143,7 @@ buf_print_io(
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
+ buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
mutex_exit(&(buf_pool->mutex));
}
@@ -1922,6 +2160,7 @@ buf_refresh_io_stats(void)
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
+ buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
}
/*************************************************************************
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 78bde60c9b2..02587487a92 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -24,6 +24,7 @@ Created 11/11/1995 Heikki Tuuri
#include "log0log.h"
#include "os0file.h"
#include "trx0sys.h"
+#include "srv0srv.h"
/* When flushed, dirty blocks are searched in neigborhoods of this size, and
flushed along with the original page. */
@@ -103,7 +104,7 @@ buf_flush_ready_for_replace(
/*========================*/
/* out: TRUE if can replace immediately */
buf_block_t* block) /* in: buffer control block, must be in state
- BUF_BLOCK_FILE_PAGE and in the LRU list*/
+ BUF_BLOCK_FILE_PAGE and in the LRU list */
{
ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
@@ -134,7 +135,6 @@ buf_flush_ready_for_flush(
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
&& (block->io_fix == 0)) {
-
if (flush_type != BUF_FLUSH_LRU) {
return(TRUE);
@@ -436,6 +436,20 @@ buf_flush_try_page(
&& block && buf_flush_ready_for_flush(block, flush_type)) {
block->io_fix = BUF_IO_WRITE;
+
+ /* If AWE is enabled and the page is not mapped to a frame,
+ then map it */
+
+ if (block->frame == NULL) {
+ ut_a(srv_use_awe);
+
+ /* We set second parameter TRUE because the block is
+ in the LRU list and we must put it to
+ awe_LRU_free_mapped list once mapped to a frame */
+
+ buf_awe_map_page_to_frame(block, TRUE);
+ }
+
block->flush_type = flush_type;
if (buf_pool->n_flush[flush_type] == 0) {
@@ -486,6 +500,20 @@ buf_flush_try_page(
..._ready_for_flush). */
block->io_fix = BUF_IO_WRITE;
+
+ /* If AWE is enabled and the page is not mapped to a frame,
+ then map it */
+
+ if (block->frame == NULL) {
+ ut_a(srv_use_awe);
+
+ /* We set second parameter TRUE because the block is
+ in the LRU list and we must put it to
+ awe_LRU_free_mapped list once mapped to a frame */
+
+ buf_awe_map_page_to_frame(block, TRUE);
+ }
+
block->flush_type = flush_type;
if (buf_pool->n_flush[flush_type] == 0) {
@@ -511,6 +539,20 @@ buf_flush_try_page(
&& buf_flush_ready_for_flush(block, flush_type)) {
block->io_fix = BUF_IO_WRITE;
+
+ /* If AWE is enabled and the page is not mapped to a frame,
+ then map it */
+
+ if (block->frame == NULL) {
+ ut_a(srv_use_awe);
+
+ /* We set second parameter TRUE because the block is
+ in the LRU list and we must put it to
+ awe_LRU_free_mapped list once mapped to a frame */
+
+ buf_awe_map_page_to_frame(block, TRUE);
+ }
+
block->flush_type = flush_type;
if (buf_pool->n_flush[block->flush_type] == 0) {
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 2ec1506c522..051aa0191f6 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -132,7 +132,13 @@ buf_LRU_search_and_free_block(
mutex_exit(&(buf_pool->mutex));
- btr_search_drop_page_hash_index(block->frame);
+ /* Remove possible adaptive hash index built on the
+ page; in the case of AWE the block may not have a
+ frame at all */
+
+ if (block->frame) {
+ btr_search_drop_page_hash_index(block->frame);
+ }
mutex_enter(&(buf_pool->mutex));
@@ -196,7 +202,9 @@ list. */
buf_block_t*
buf_LRU_get_free_block(void)
/*========================*/
- /* out: the free control block */
+ /* out: the free control block; also if AWE is
+ used, it is guaranteed that the block has its
+ page mapped to a frame when we return */
{
buf_block_t* block = NULL;
ibool freed;
@@ -257,6 +265,22 @@ loop:
block = UT_LIST_GET_FIRST(buf_pool->free);
UT_LIST_REMOVE(free, buf_pool->free, block);
+
+ if (srv_use_awe) {
+ if (block->frame) {
+ /* Remove from the list of mapped pages */
+
+ UT_LIST_REMOVE(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped, block);
+ } else {
+ /* We map the page to a frame; second param
+ FALSE below because we do not want it to be
+ added to the awe_LRU_free_mapped list */
+
+ buf_awe_map_page_to_frame(block, FALSE);
+ }
+ }
+
block->state = BUF_BLOCK_READY_FOR_USE;
mutex_exit(&(buf_pool->mutex));
@@ -429,6 +453,13 @@ buf_LRU_remove_block(
/* Remove the block from the LRU list */
UT_LIST_REMOVE(LRU, buf_pool->LRU, block);
+ if (srv_use_awe && block->frame) {
+ /* Remove from the list of mapped pages */
+
+ UT_LIST_REMOVE(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped, block);
+ }
+
/* If the LRU list is so short that LRU_old not defined, return */
if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
@@ -475,6 +506,13 @@ buf_LRU_add_block_to_end_low(
UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
+ if (srv_use_awe && block->frame) {
+ /* Add to the list of mapped pages */
+
+ UT_LIST_ADD_LAST(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped, block);
+ }
+
if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
buf_pool->LRU_old_len++;
@@ -518,6 +556,15 @@ buf_LRU_add_block_low(
block->old = old;
cl = buf_pool_clock_tic();
+ if (srv_use_awe && block->frame) {
+ /* Add to the list of mapped pages; for simplicity we always
+ add to the start, even if the user would have set 'old'
+ TRUE */
+
+ UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped, block);
+ }
+
if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) {
UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, block);
@@ -613,6 +660,13 @@ buf_LRU_block_free_non_file_page(
memset(block->frame, '\0', UNIV_PAGE_SIZE);
#endif
UT_LIST_ADD_FIRST(free, buf_pool->free, block);
+
+ if (srv_use_awe && block->frame) {
+ /* Add to the list of mapped pages */
+
+ UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
+ buf_pool->awe_LRU_free_mapped, block);
+ }
}
/**********************************************************************
@@ -639,7 +693,9 @@ buf_LRU_block_remove_hashed_page(
buf_pool->freed_page_clock += 1;
- buf_frame_modify_clock_inc(block->frame);
+ /* Note that if AWE is enabled the block may not have a frame at all */
+
+ buf_block_modify_clock_inc(block);
HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
buf_page_address_fold(block->space, block->offset),
diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c
index 475a5bd9cbd..bb6670296b9 100644
--- a/innobase/buf/buf0rea.c
+++ b/innobase/buf/buf0rea.c
@@ -576,7 +576,7 @@ buf_read_recv_pages(
os_aio_print_debug = FALSE;
- while (buf_pool->n_pend_reads >= RECV_POOL_N_FREE_BLOCKS / 2) {
+ while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) {
os_aio_simulated_wake_handler_threads();
os_thread_sleep(500000);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index c70e848c5c8..9be10fe70d8 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -2181,6 +2181,7 @@ dict_skip_word(
/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
+#ifdef NOT_USED
static
int
dict_bracket_count(
@@ -2204,7 +2205,7 @@ dict_bracket_count(
return(count);
}
-
+#endif
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index d8d426d2036..1070a8f5426 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -456,7 +456,7 @@ dict_load_indexes(
ut_ad(len == 8);
id = mach_read_from_8(field);
- ut_a(0 == ut_strcmp("NAME",
+ ut_a(0 == ut_strcmp((void*) "NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 4))->name));
@@ -515,7 +515,7 @@ dict_load_indexes(
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == ut_strlen("ID_IND"))
- && (0 == ut_memcmp(name_buf, "ID_IND",
+ && (0 == ut_memcmp(name_buf, (void*) "ID_IND",
name_len))))) {
/* The index was created in memory already in
diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h
index 9d07dd0de18..81f19af4d40 100644
--- a/innobase/include/btr0pcur.h
+++ b/innobase/include/btr0pcur.h
@@ -466,6 +466,9 @@ struct btr_pcur_struct{
BTR_PCUR_AFTER, depending on whether
cursor was on, before, or after the
old_rec record */
+ buf_block_t* block_when_stored;/* buffer block when the position was
+ stored; note that if AWE is on, frames
+ may move */
dulint modify_clock; /* the modify clock value of the
buffer block when the cursor position
was stored */
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 395f88a2c7c..81eeb7fced8 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -30,6 +30,7 @@ Created 11/5/1995 Heikki Tuuri
#include "sync0rw.h"
#include "hash0hash.h"
#include "ut0byte.h"
+#include "os0proc.h"
/* Flags for flush types */
#define BUF_FLUSH_LRU 1
@@ -58,23 +59,34 @@ extern ibool buf_debug_prints;/* If this is set TRUE, the program
occurs */
/************************************************************************
-Initializes the buffer pool of the database. */
+Creates the buffer pool. */
-void
+buf_pool_t*
buf_pool_init(
/*==========*/
- ulint max_size, /* in: maximum size of the pool in blocks */
- ulint curr_size); /* in: current size to use, must be <=
+ /* out, own: buf_pool object, NULL if not
+ enough memory or error */
+ ulint max_size, /* in: maximum size of the buf_pool in
+ blocks */
+ ulint curr_size, /* in: current size to use, must be <=
+ max_size, currently must be equal to
max_size */
+ ulint n_frames); /* in: number of frames; if AWE is used,
+ this is the size of the address space window
+ where physical memory pages are mapped; if
+ AWE is not used then this must be the same
+ as max_size */
/*************************************************************************
-Gets the current size of buffer pool in bytes. */
+Gets the current size of buffer buf_pool in bytes. In the case of AWE, the
+size of AWE window (= the frames). */
UNIV_INLINE
ulint
buf_pool_get_curr_size(void);
/*========================*/
/* out: size in bytes */
/*************************************************************************
-Gets the maximum size of buffer pool in bytes. */
+Gets the maximum size of buffer pool in bytes. In the case of AWE, the
+size of AWE window (= the frames). */
UNIV_INLINE
ulint
buf_pool_get_max_size(void);
@@ -138,8 +150,8 @@ improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed as LA! */
NOTE! The following macros should be used instead of
buf_page_optimistic_get_func, to improve debugging. Only values RW_S_LATCH and
RW_X_LATCH are allowed as LA! */
-#define buf_page_optimistic_get(LA, G, MC, MTR) buf_page_optimistic_get_func(\
- LA, G, MC, IB__FILE__, __LINE__, MTR)
+#define buf_page_optimistic_get(LA, BL, G, MC, MTR) buf_page_optimistic_get_func(\
+ LA, BL, G, MC, IB__FILE__, __LINE__, MTR)
/************************************************************************
This is the general function used to get optimistic access to a database
page. */
@@ -149,7 +161,9 @@ buf_page_optimistic_get_func(
/*=========================*/
/* out: TRUE if success */
ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */
- buf_frame_t* guess, /* in: guessed frame */
+ buf_block_t* block, /* in: guessed block */
+ buf_frame_t* guess, /* in: guessed frame; note that AWE may move
+ frames */
dulint modify_clock,/* in: modify clock value if mode is
..._GUESS_ON_CLOCK */
char* file, /* in: file name */
@@ -350,6 +364,16 @@ buf_frame_modify_clock_inc(
/* out: new value */
buf_frame_t* frame); /* in: pointer to a frame */
/************************************************************************
+Increments the modify clock of a frame by 1. The caller must (1) own the
+buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
+on the block. */
+UNIV_INLINE
+dulint
+buf_block_modify_clock_inc(
+/*=======================*/
+ /* out: new value */
+ buf_block_t* block); /* in: block */
+/************************************************************************
Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
@@ -428,7 +452,7 @@ UNIV_INLINE
buf_frame_t*
buf_frame_align(
/*============*/
- /* out: pointer to block */
+ /* out: pointer to frame */
byte* ptr); /* in: pointer to a frame */
/***********************************************************************
Checks if a pointer points to the block array of the buffer pool (blocks, not
@@ -505,6 +529,19 @@ buf_pool_invalidate(void);
--------------------------- LOWER LEVEL ROUTINES -------------------------
=========================================================================*/
+/************************************************************************
+Maps the page of block to a frame, if not mapped yet. Unmaps some page
+from the end of the awe_LRU_free_mapped. */
+
+void
+buf_awe_map_page_to_frame(
+/*======================*/
+ buf_block_t* block, /* in: block whose page should be
+ mapped to a frame */
+ ibool add_to_mapped_list);/* in: TRUE if we in the case
+ we need to map the page should also
+ add the block to the
+ awe_LRU_free_mapped list */
/*************************************************************************
Adds latch level info for the rw-lock protecting the buffer frame. This
should be called in the debug version after a successful latching of a
@@ -638,7 +675,16 @@ struct buf_block_struct{
byte* frame; /* pointer to buffer frame which
is of size UNIV_PAGE_SIZE, and
aligned to an address divisible by
- UNIV_PAGE_SIZE */
+ UNIV_PAGE_SIZE; if AWE is used, this
+ will be NULL for the pages which are
+ currently not mapped into the virtual
+ address space window of the buffer
+ pool */
+ os_awe_t* awe_info; /* if AWE is used, then an array of
+ awe page infos for
+ UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE
+ (normally = 4) physical memory
+ pages; otherwise NULL */
ulint space; /* space id of the page */
ulint offset; /* page number within the space */
ulint lock_hash_val; /* hashed value of the page address
@@ -647,14 +693,6 @@ struct buf_block_struct{
record lock hash table */
rw_lock_t lock; /* read-write lock of the buffer
frame */
- rw_lock_t read_lock; /* rw-lock reserved when a page read
- to the frame is requested; a thread
- can wait for this rw-lock if it wants
- to wait for the read to complete;
- the usual way is to wait for lock,
- but if the thread just wants a
- bufferfix and no latch on the page,
- then it can wait for this rw-lock */
buf_block_t* hash; /* node used in chaining to the page
hash table */
ibool check_index_page_at_flush;
@@ -691,6 +729,10 @@ struct buf_block_struct{
/* node of the free block list */
UT_LIST_NODE_T(buf_block_t) LRU;
/* node of the LRU list */
+ UT_LIST_NODE_T(buf_block_t) awe_LRU_free_mapped;
+ /* in the AWE version node in the
+ list of free and LRU blocks which are
+ mapped to a frame */
ulint LRU_position; /* value which monotonically
decreases (or may stay constant if
the block is in the old blocks) toward
@@ -758,11 +800,12 @@ struct buf_block_struct{
BTR_SEARCH_RIGHT_SIDE in hash
indexing */
/* 6. Debug fields */
-
+#ifdef UNIV_SYNC_DEBUG
rw_lock_t debug_latch; /* in the debug version, each thread
which bufferfixes the block acquires
an s-latch here; so we can use the
debug utilities in sync0rw */
+#endif
ibool file_page_was_freed;
/* this is set to TRUE when fsp
frees a page in buffer pool */
@@ -781,16 +824,36 @@ struct buf_pool_struct{
struct and control blocks, except the
read-write lock in them */
byte* frame_mem; /* pointer to the memory area which
- was allocated for the frames */
+ was allocated for the frames; in AWE
+ this is the virtual address space
+ window where we map pages stored
+ in physical memory */
byte* frame_zero; /* pointer to the first buffer frame:
this may differ from frame_mem, because
this is aligned by the frame size */
- byte* high_end; /* pointer to the end of the
- buffer pool */
+ byte* high_end; /* pointer to the end of the buffer
+ frames */
+ ulint n_frames; /* number of frames */
buf_block_t* blocks; /* array of buffer control blocks */
+ buf_block_t** blocks_of_frames;/* inverse mapping which can be used
+ to retrieve the buffer control block
+ of a frame; this is an array which
+ lists the blocks of frames in the
+ order frame_zero,
+ frame_zero + UNIV_PAGE_SIZE, ...
+ a control block is always assigned
+ for each frame, even if the frame does
+ not contain any data; note that in AWE
+ there are more control blocks than
+ buffer frames */
+ os_awe_t* awe_info; /* if AWE is used, AWE info for the
+ physical 4 kB memory pages associated
+ with buffer frames */
ulint max_size; /* number of control blocks ==
maximum pool size in pages */
- ulint curr_size; /* current pool size in pages */
+ ulint curr_size; /* current pool size in pages;
+ currently always the same as
+ max_size */
hash_table_t* page_hash; /* hash table of the file pages */
ulint n_pend_reads; /* number of pending read operations */
@@ -802,11 +865,14 @@ struct buf_pool_struct{
ulint n_pages_created;/* number of pages created in the pool
with no read */
ulint n_page_gets; /* number of page gets performed;
- also successful seraches through
+ also successful searches through
the adaptive hash index are
counted as page gets; this field
is NOT protected by the buffer
pool mutex */
+ ulint n_pages_awe_remapped; /* if AWE is enabled, the
+ number of remaps of blocks to
+ buffer frames */
ulint n_page_gets_old;/* n_page_gets when buf_print was
last time called: used to calculate
hit rate */
@@ -815,6 +881,7 @@ struct buf_pool_struct{
ulint n_pages_written_old;/* number write operations */
ulint n_pages_created_old;/* number of pages created in
the pool with no read */
+ ulint n_pages_awe_remapped_old;
/* 2. Page flushing algorithm fields */
UT_LIST_BASE_NODE_T(buf_block_t) flush_list;
@@ -847,7 +914,10 @@ struct buf_pool_struct{
/* 3. LRU replacement algorithm fields */
UT_LIST_BASE_NODE_T(buf_block_t) free;
- /* base node of the free block list */
+ /* base node of the free block list;
+ in the case of AWE, at the start are
+ always free blocks for which the
+ physical memory is mapped to a frame */
UT_LIST_BASE_NODE_T(buf_block_t) LRU;
/* base node of the LRU list */
buf_block_t* LRU_old; /* pointer to the about 3/8 oldest
@@ -859,6 +929,12 @@ struct buf_pool_struct{
see buf0lru.c for the restrictions
on this value; not defined if
LRU_old == NULL */
+ UT_LIST_BASE_NODE_T(buf_block_t) awe_LRU_free_mapped;
+ /* list of those blocks which are
+ in the LRU list or the free list, and
+ where the page is mapped to a frame;
+ thus, frames allocated, e.g., to the
+ locki table, are not in this list */
};
/* States of a control block */
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 7227c79dc6a..d4e7122f3f9 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -36,25 +36,27 @@ buf_block_peek_if_too_old(
}
/*************************************************************************
-Gets the current size of buffer buf_pool in bytes. */
+Gets the current size of buffer buf_pool in bytes. In the case of AWE, the
+size of AWE window (= the frames). */
UNIV_INLINE
ulint
buf_pool_get_curr_size(void)
/*========================*/
/* out: size in bytes */
{
- return((buf_pool->curr_size) * UNIV_PAGE_SIZE);
+ return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
}
/*************************************************************************
-Gets the maximum size of buffer buf_pool in bytes. */
+Gets the maximum size of buffer buf_pool in bytes. In the case of AWE, the
+size of AWE window (= the frames). */
UNIV_INLINE
ulint
buf_pool_get_max_size(void)
/*=======================*/
/* out: size in bytes */
{
- return((buf_pool->max_size) * UNIV_PAGE_SIZE);
+ return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
}
/***********************************************************************
@@ -207,54 +209,24 @@ buf_block_align(
frame_zero = buf_pool->frame_zero;
- ut_ad((ulint)ptr >= (ulint)frame_zero);
-
- block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
- >> UNIV_PAGE_SIZE_SHIFT);
- if (block < buf_pool->blocks
- || block >= buf_pool->blocks + buf_pool->max_size) {
+ if ((ulint)ptr < (ulint)frame_zero
+ || (ulint)ptr > (ulint)(buf_pool->high_end)) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Error: trying to access a stray pointer %lx\n"
-"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
- (ulint)frame_zero, buf_pool->max_size);
+" InnoDB: Error: trying to access a stray pointer %lx\n"
+"InnoDB: buf pool start is at %lx, end at %lx\n"
+"InnoDB: Probable reason is database corruption or memory\n"
+"InnoDB: corruption. If this happens in an InnoDB database recovery,\n"
+"InnoDB: you can look from section 6.1 at http://www.innodb.com/ibman.html\n"
+"InnoDB: how to force recovery.\n",
+ (ulint)ptr, (ulint)frame_zero,
+ (ulint)(buf_pool->high_end));
ut_a(0);
}
-
- return(block);
-}
-
-/***********************************************************************
-Gets the block to whose frame the pointer is pointing to. Does not
-require a file page to be bufferfixed. */
-UNIV_INLINE
-buf_block_t*
-buf_block_align_low(
-/*================*/
- /* out: pointer to block */
- byte* ptr) /* in: pointer to a frame */
-{
- buf_block_t* block;
- buf_frame_t* frame_zero;
-
- ut_ad(ptr);
-
- frame_zero = buf_pool->frame_zero;
-
- ut_ad((ulint)ptr >= (ulint)frame_zero);
-
- block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
- >> UNIV_PAGE_SIZE_SHIFT);
- if (block < buf_pool->blocks
- || block >= buf_pool->blocks + buf_pool->max_size) {
-
- fprintf(stderr,
-"InnoDB: Error: trying to access a stray pointer %lx\n"
-"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
- (ulint)frame_zero, buf_pool->max_size);
- ut_a(0);
- }
-
+
+ block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
+ >> UNIV_PAGE_SIZE_SHIFT));
return(block);
}
@@ -264,7 +236,7 @@ UNIV_INLINE
buf_frame_t*
buf_frame_align(
/*============*/
- /* out: pointer to block */
+ /* out: pointer to frame */
byte* ptr) /* in: pointer to a frame */
{
buf_frame_t* frame;
@@ -273,14 +245,19 @@ buf_frame_align(
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
- if (((ulint)frame
- < (ulint)(buf_pool->frame_zero))
- || ((ulint)frame > (ulint)(buf_pool_get_nth_block(buf_pool,
- buf_pool->max_size - 1)->frame))) {
+ if (((ulint)frame < (ulint)(buf_pool->frame_zero))
+ || (ulint)frame >= (ulint)(buf_pool->high_end)) {
+
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Error: trying to access a stray pointer %lx\n"
-"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
- (ulint)(buf_pool->frame_zero), buf_pool->max_size);
+" InnoDB: Error: trying to access a stray pointer %lx\n"
+"InnoDB: buf pool start is at %lx, end at %lx\n"
+"InnoDB: Probable reason is database corruption or memory\n"
+"InnoDB: corruption. If this happens in an InnoDB database recovery,\n"
+"InnoDB: you can look from section 6.1 at http://www.innodb.com/ibman.html\n"
+"InnoDB: how to force recovery.\n",
+ (ulint)ptr, (ulint)(buf_pool->frame_zero),
+ (ulint)(buf_pool->high_end));
ut_a(0);
}
@@ -469,7 +446,7 @@ buf_frame_modify_clock_inc(
ut_ad(frame);
- block = buf_block_align_low(frame);
+ block = buf_block_align(frame);
ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
@@ -480,6 +457,25 @@ buf_frame_modify_clock_inc(
}
/************************************************************************
+Increments the modify clock of a frame by 1. The caller must (1) own the
+buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
+on the block. */
+UNIV_INLINE
+dulint
+buf_block_modify_clock_inc(
+/*=======================*/
+ /* out: new value */
+ buf_block_t* block) /* in: block */
+{
+ ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
+ || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
+
+ UT_DULINT_INC(block->modify_clock);
+
+ return(block->modify_clock);
+}
+
+/************************************************************************
Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
@@ -508,15 +504,16 @@ void
buf_block_buf_fix_inc_debug(
/*========================*/
buf_block_t* block, /* in: block to bufferfix */
- char* file, /* in: file name */
- ulint line) /* in: line */
+ char* file __attribute__ ((unused)), /* in: file name */
+ ulint line __attribute__ ((unused))) /* in: line */
{
+#ifdef UNIV_SYNC_DEBUG
ibool ret;
-
+
ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
ut_ad(ret == TRUE);
-
+#endif
block->buf_fix_count++;
}
diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h
index 946b6c4e31d..6a3c948507d 100644
--- a/innobase/include/buf0lru.h
+++ b/innobase/include/buf0lru.h
@@ -53,7 +53,9 @@ LRU list to the free list. */
buf_block_t*
buf_LRU_get_free_block(void);
/*=========================*/
- /* out: the free control block */
+ /* out: the free control block; also if AWE is
+ used, it is guaranteed that the block has its
+ page mapped to a frame when we return */
/**********************************************************************
Puts a block back to the free list. */
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index 7418e4abf1b..bef42cfec1c 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -355,12 +355,7 @@ in the debug version: spaces with an odd number as the id are replicate
spaces */
#define RECV_REPLICA_SPACE_ADD 1
-/* This many blocks must be left free in the buffer pool when we scan
-the log and store the scanned log records in the buffer pool: we will
-use these free blocks to read in pages when we start applying the
-log records to the database. */
-
-#define RECV_POOL_N_FREE_BLOCKS (ut_min(256, buf_pool_get_curr_size() / 8))
+extern ulint recv_n_pool_free_frames;
#ifndef UNIV_NONINL
#include "log0recv.ic"
diff --git a/innobase/include/mem0pool.h b/innobase/include/mem0pool.h
index 43707bd5f61..51c53afe788 100644
--- a/innobase/include/mem0pool.h
+++ b/innobase/include/mem0pool.h
@@ -19,6 +19,8 @@ typedef struct mem_pool_struct mem_pool_t;
/* The common memory pool */
extern mem_pool_t* mem_comm_pool;
+extern ulint mem_out_of_mem_err_msg_count;
+
/* Memory area header */
struct mem_area_struct{
diff --git a/innobase/include/os0proc.h b/innobase/include/os0proc.h
index 79750e5c1f7..664952bd166 100644
--- a/innobase/include/os0proc.h
+++ b/innobase/include/os0proc.h
@@ -15,6 +15,76 @@ Created 9/30/1995 Heikki Tuuri
typedef void* os_process_t;
typedef unsigned long int os_process_id_t;
+/* The cell type in os_awe_allocate_mem page info */
+#if defined(__WIN2000__) && defined(ULONG_PTR)
+typedef ULONG_PTR os_awe_t;
+#else
+typedef ulint os_awe_t;
+#endif
+
+/* Physical page size when Windows AWE is used. This is the normal
+page size of an Intel x86 processor. We cannot use AWE with 2 MB or 4 MB
+pages. */
+#define OS_AWE_X86_PAGE_SIZE 4096
+
+/********************************************************************
+Windows AWE support. Tries to enable the "lock pages in memory" privilege for
+the current process so that the current process can allocate memory-locked
+virtual address space to act as the window where AWE maps physical memory. */
+
+ibool
+os_awe_enable_lock_pages_in_mem(void);
+/*=================================*/
+ /* out: TRUE if success, FALSE if error;
+ prints error info to stderr if no success */
+/********************************************************************
+Allocates physical RAM memory up to 64 GB in an Intel 32-bit x86
+processor. */
+
+ibool
+os_awe_allocate_physical_mem(
+/*=========================*/
+ /* out: TRUE if success */
+ os_awe_t** page_info, /* out, own: array of opaque data containing
+ the info for allocated physical memory pages;
+ each allocated 4 kB physical memory page has
+ one slot of type os_awe_t in the array */
+ ulint n_megabytes); /* in: number of megabytes to allocate */
+/********************************************************************
+Allocates a window in the virtual address space where we can map then
+pages of physical memory. */
+
+byte*
+os_awe_allocate_virtual_mem_window(
+/*===============================*/
+ /* out, own: allocated memory, or NULL if did not
+ succeed */
+ ulint size); /* in: virtual memory allocation size in bytes, must
+ be < 2 GB */
+/********************************************************************
+With this function you can map parts of physical memory allocated with
+the ..._allocate_physical_mem to the virtual address space allocated with
+the previous function. Intel implements this so that the process page
+tables are updated accordingly. A test on a 1.5 GHz AMD processor and XP
+showed that this takes < 1 microsecond, much better than the estimated 80 us
+for copying a 16 kB page memory to memory. But, the operation will at least
+partially invalidate the translation lookaside buffer (TLB) of all
+processors. Under a real-world load the performance hit may be bigger. */
+
+ibool
+os_awe_map_physical_mem_to_window(
+/*==============================*/
+ /* out: TRUE if success; the function
+ calls exit(1) in case of an error */
+ byte* ptr, /* in: a page-aligned pointer to
+ somewhere in the virtual address
+ space window; we map the physical mem
+ pages here */
+ ulint n_mem_pages, /* in: number of 4 kB mem pages to
+ map */
+ os_awe_t* page_info); /* in: array of page infos for those
+ pages; each page has one slot in the
+ array */
/********************************************************************
Converts the current process id to a number. It is not guaranteed that the
number is unique. In Linux returns the 'process number' of the current
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 25d2ab77007..972fabc74cf 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -52,6 +52,14 @@ row_mysql_read_var_ref_noninline(
ulint* len, /* out: variable-length field length */
byte* field); /* in: field */
/***********************************************************************
+Frees the blob heap in prebuilt when no longer needed. */
+
+void
+row_mysql_prebuilt_free_blob_heap(
+/*==============================*/
+ row_prebuilt_t* prebuilt); /* in: prebuilt struct of a
+ ha_innobase:: table handle */
+/***********************************************************************
Stores a reference to a BLOB in the MySQL format. */
void
diff --git a/innobase/include/row0sel.h b/innobase/include/row0sel.h
index aa2da6fe5f6..cfc30852b87 100644
--- a/innobase/include/row0sel.h
+++ b/innobase/include/row0sel.h
@@ -115,7 +115,8 @@ row_search_for_mysql(
/*=================*/
/* out: DB_SUCCESS,
DB_RECORD_NOT_FOUND,
- DB_END_OF_INDEX, or DB_DEADLOCK */
+ DB_END_OF_INDEX, DB_DEADLOCK,
+ or DB_TOO_BIG_RECORD */
byte* buf, /* in/out: buffer for the fetched
row in the MySQL format */
ulint mode, /* in: search mode PAGE_CUR_L, ... */
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index ad6f71f7a3a..bc0960ae023 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -61,6 +61,7 @@ extern ulint srv_flush_log_at_trx_commit;
extern byte srv_latin1_ordering[256];/* The sort order table of the latin1
character set */
extern ulint srv_pool_size;
+extern ulint srv_awe_window_size;
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
@@ -86,6 +87,8 @@ extern ibool srv_use_doublewrite_buf;
extern ibool srv_set_thread_priorities;
extern int srv_query_thread_priority;
+extern ibool srv_use_awe;
+extern ibool srv_use_adaptive_hash_indexes;
/*-------------------------------------------*/
extern ulint srv_n_rows_inserted;
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index 09e0d800685..d3d04d58596 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -50,6 +50,16 @@ ut_malloc(
/* out, own: allocated memory */
ulint n); /* in: number of bytes to allocate */
/**************************************************************************
+Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
+out. It cannot be used if we want to return an error message. Prints to
+stderr a message if fails. */
+
+ibool
+ut_test_malloc(
+/*===========*/
+ /* out: TRUE if succeeded */
+ ulint n); /* in: try to allocate this many bytes */
+/**************************************************************************
Frees a memory bloock allocated with ut_malloc. */
void
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 7b08d6b89b8..d4329c4873c 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -3602,7 +3602,8 @@ lock_release_off_kernel(
ut_ad(lock_get_type(lock) == LOCK_TABLE);
if (lock_get_mode(lock) != LOCK_IS
- && (trx->insert_undo || trx->update_undo)) {
+ && 0 != ut_dulint_cmp(trx->undo_no,
+ ut_dulint_zero)) {
/* The trx may have modified the table.
We block the use of the MySQL query cache
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 539cde337bd..bdfce783a43 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -3064,8 +3064,8 @@ log_check_log_recs(
ut_memcpy(scan_buf, start, end - start);
recv_scan_log_recs(TRUE,
- buf_pool_get_curr_size() -
- RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
+ (buf_pool->n_frames -
+ recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
FALSE, scan_buf, end - start,
ut_dulint_align_down(buf_start_lsn,
OS_FILE_LOG_BLOCK_SIZE),
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index dfe67c444b4..3945b47933d 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -71,6 +71,14 @@ ulint recv_previous_parsed_rec_is_multi = 0;
ulint recv_max_parsed_page_no = 0;
+/* This many frames must be left free in the buffer pool when we scan
+the log and store the scanned log records in the buffer pool: we will
+use these free frames to read in pages when we start applying the
+log records to the database. */
+
+ulint recv_n_pool_free_frames = 256;
+
+
/************************************************************
Creates the recovery system. */
@@ -1018,10 +1026,10 @@ recv_recover_page(
block = buf_block_align(page);
if (just_read_in) {
- /* Move the ownership of the x-latch on the page to this OS
- thread, so that we can acquire a second x-latch on it. This
- is needed for the operations to the page to pass the debug
- checks. */
+ /* Move the ownership of the x-latch on the page to
+ this OS thread, so that we can acquire a second
+ x-latch on it. This is needed for the operations to
+ the page to pass the debug checks. */
rw_lock_x_lock_move_ownership(&(block->lock));
}
@@ -2362,8 +2370,8 @@ recv_group_scan_log_recs(
group, start_lsn, end_lsn);
finished = recv_scan_log_recs(TRUE,
- buf_pool_get_curr_size()
- - RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
+ (buf_pool->n_frames
+ - recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
TRUE, log_sys->buf,
RECV_SCAN_SIZE, start_lsn,
contiguous_lsn, group_scanned_lsn);
@@ -3001,8 +3009,8 @@ ask_again:
read_offset % UNIV_PAGE_SIZE, len, buf, NULL);
ret = recv_scan_log_recs(TRUE,
- buf_pool_get_curr_size() -
- RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
+ (buf_pool->n_frames -
+ recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
TRUE, buf, len, start_lsn,
&dummy_lsn, &scanned_lsn);
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 293ced92c42..82ed957b5fb 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -2142,7 +2142,7 @@ os_aio_simulated_handle(
ulint offs;
ulint lowest_offset;
byte* combined_buf;
- byte* combined_buf2= 0; /* Remove warning */
+ byte* combined_buf2;
ibool ret;
ulint n;
ulint i;
diff --git a/innobase/os/os0proc.c b/innobase/os/os0proc.c
index 1ee448a4a44..614cea63200 100644
--- a/innobase/os/os0proc.c
+++ b/innobase/os/os0proc.c
@@ -12,11 +12,469 @@ Created 9/30/1995 Heikki Tuuri
#include "os0proc.ic"
#endif
+#include "ut0mem.h"
+#include "ut0byte.h"
+
+
+/*
+How to get AWE to compile on Windows?
+-------------------------------------
+
+In the project settings of the innobase project the Visual C++ source,
+__WIN2000__ has to be defined.
+
+The Visual C++ has to be relatively recent and _WIN32_WINNT has to be
+defined to a value >= 0x0500 when windows.h is included.
+
+#define _WIN32_WINNT 0x0500
+
+Where does AWE work?
+-------------------
+
+See the error message in os_awe_allocate_physical_mem().
+
+How to assign privileges for mysqld to use AWE?
+-----------------------------------------------
+
+See the error message in os_awe_enable_lock_pages_in_mem().
+
+Use Windows AWE functions in this order
+---------------------------------------
+
+(1) os_awe_enable_lock_pages_in_mem();
+(2) os_awe_allocate_physical_mem();
+(3) os_awe_allocate_virtual_mem_window();
+(4) os_awe_map_physical_mem_to_window().
+
+To test 'AWE' in a computer which does not have the AWE API,
+you can compile with UNIV_SIMULATE_AWE defined in this file.
+*/
+
+#ifdef UNIV_SIMULATE_AWE
+/* If we simulate AWE, we allocate the 'physical memory' here */
+byte* os_awe_simulate_mem;
+ulint os_awe_simulate_mem_size;
+os_awe_t* os_awe_simulate_page_info;
+byte* os_awe_simulate_window;
+ulint os_awe_simulate_window_size;
+/* In simulated AWE the following contains a NULL pointer or a pointer
+to a mapped 'physical page' for each 4 kB page in the AWE window */
+byte** os_awe_simulate_map;
+#endif
+
+#ifdef __WIN2000__
+os_awe_t* os_awe_page_info;
+ulint os_awe_n_pages;
+byte* os_awe_window;
+ulint os_awe_window_size;
+#endif
+
+/********************************************************************
+Windows AWE support. Tries to enable the "lock pages in memory" privilege for
+the current process so that the current process can allocate memory-locked
+virtual address space to act as the window where AWE maps physical memory. */
+
+ibool
+os_awe_enable_lock_pages_in_mem(void)
+/*=================================*/
+ /* out: TRUE if success, FALSE if error;
+ prints error info to stderr if no success */
+{
+#ifdef UNIV_SIMULATE_AWE
+
+ return(TRUE);
+
+#elif defined(__WIN2000__)
+ struct {
+ DWORD Count;
+ LUID_AND_ATTRIBUTES Privilege[1];
+ } Info;
+ HANDLE hProcess;
+ HANDLE Token;
+ BOOL Result;
+
+ hProcess = GetCurrentProcess();
+
+ /* Open the token of the current process */
+
+ Result = OpenProcessToken(hProcess,
+ TOKEN_ADJUST_PRIVILEGES,
+ &Token);
+ if (Result != TRUE) {
+ fprintf(stderr,
+ "InnoDB: AWE: Cannot open process token, error %lu\n",
+ (ulint)GetLastError());
+ return(FALSE);
+ }
+
+ Info.Count = 1;
+
+ Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ /* Get the local unique identifier (LUID) of the SE_LOCK_MEMORY
+ privilege */
+
+ Result = LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME,
+ &(Info.Privilege[0].Luid));
+ if (Result != TRUE) {
+ fprintf(stderr,
+ "InnoDB: AWE: Cannot get local privilege value for %s, error %lu.\n",
+ SE_LOCK_MEMORY_NAME, (ulint)GetLastError());
+
+ return(FALSE);
+ }
+
+ /* Try to adjust the privilege */
+
+ Result = AdjustTokenPrivileges(Token, FALSE,
+ (PTOKEN_PRIVILEGES)&Info,
+ 0, NULL, NULL);
+ /* Check the result */
+
+ if (Result != TRUE) {
+ fprintf(stderr,
+ "InnoDB: AWE: Cannot adjust process token privileges, error %u.\n",
+ GetLastError());
+ return(FALSE);
+ } else if (GetLastError() != ERROR_SUCCESS) {
+ fprintf(stderr,
+"InnoDB: AWE: Cannot enable SE_LOCK_MEMORY privilege, error %lu.\n"
+"InnoDB: In Windows XP Home you cannot use AWE. In Windows 2000 and XP\n"
+"InnoDB: Professional you must go to the Control Panel, to\n"
+"InnoDB: Security Settings, to Local Policies, and enable\n"
+"InnoDB: the 'lock pages in memory' privilege for the user who runs\n"
+"InnoDB: the MySQL server.\n", GetLastError());
+
+ return(FALSE);
+ }
+
+ CloseHandle(Token);
+
+ return(TRUE);
+#else
#ifdef __WIN__
-#include <windows.h>
+ fprintf(stderr,
+"InnoDB: AWE: Error: to use AWE you must use a ...-nt MySQL executable.\n");
+#endif
+ return(FALSE);
#endif
+}
-#include "ut0mem.h"
+/********************************************************************
+Allocates physical RAM memory up to 64 GB in an Intel 32-bit x86
+processor. */
+
+ibool
+os_awe_allocate_physical_mem(
+/*=========================*/
+ /* out: TRUE if success */
+ os_awe_t** page_info, /* out, own: array of opaque data containing
+ the info for allocated physical memory pages;
+ each allocated 4 kB physical memory page has
+ one slot of type os_awe_t in the array */
+ ulint n_megabytes) /* in: number of megabytes to allocate */
+{
+#ifdef UNIV_SIMULATE_AWE
+ os_awe_simulate_page_info = ut_malloc(sizeof(os_awe_t) *
+ n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE));
+
+ os_awe_simulate_mem = ut_align(ut_malloc(
+ 4096 + 1024 * 1024 * n_megabytes),
+ 4096);
+ os_awe_simulate_mem_size = n_megabytes * 1024 * 1024;
+
+ *page_info = os_awe_simulate_page_info;
+
+ return(TRUE);
+
+#elif defined(__WIN2000__)
+ BOOL bResult;
+ os_awe_t NumberOfPages; /* Question: why does Windows
+ use the name ULONG_PTR for
+ a scalar integer type? Maybe
+ because we may also refer to
+ &NumberOfPages? */
+ os_awe_t NumberOfPagesInitial;
+ SYSTEM_INFO sSysInfo;
+ int PFNArraySize;
+
+ if (n_megabytes > 64 * 1024) {
+
+ fprintf(stderr,
+"InnoDB: AWE: Error: tried to allocate %lu MB.\n"
+"InnoDB: AWE cannot allocate more than 64 GB in any computer.\n", n_megabytes);
+
+ return(FALSE);
+ }
+
+ GetSystemInfo(&sSysInfo); /* fill the system information structure */
+
+ if ((ulint)OS_AWE_X86_PAGE_SIZE != (ulint)sSysInfo.dwPageSize) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: this computer has a page size of %lu.\n"
+"InnoDB: Should be 4096 bytes for InnoDB AWE support to work.\n",
+ (ulint)sSysInfo.dwPageSize);
+
+ return(FALSE);
+ }
+
+ /* Calculate the number of pages of memory to request */
+
+ NumberOfPages = n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE);
+
+ /* Calculate the size of page_info for allocated physical pages */
+
+ PFNArraySize = NumberOfPages * sizeof(os_awe_t);
+
+ *page_info = (os_awe_t*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);
+
+ if (*page_info == NULL) {
+ fprintf(stderr,
+"InnoDB: AWE: Failed to allocate page info array from process heap, error %lu\n",
+ (ulint)GetLastError());
+
+ return(FALSE);
+ }
+
+ ut_total_allocated_memory += PFNArraySize;
+
+ /* Enable this process' privilege to lock pages to physical memory */
+
+ if (!os_awe_enable_lock_pages_in_mem()) {
+
+ return(FALSE);
+ }
+
+ /* Allocate the physical memory */
+
+ NumberOfPagesInitial = NumberOfPages;
+
+ os_awe_page_info = *page_info;
+ os_awe_n_pages = (ulint)NumberOfPages;
+
+ /* Compilation note: if the compiler complains the function is not
+ defined, see the note at the start of this file */
+
+ bResult = AllocateUserPhysicalPages(GetCurrentProcess(),
+ &NumberOfPages,
+ *page_info);
+ if (bResult != TRUE) {
+ fprintf(stderr,
+"InnoDB: AWE: Cannot allocate physical pages, error %lu.\n",
+ (ulint)GetLastError());
+
+ return(FALSE);
+ }
+
+ if (NumberOfPagesInitial != NumberOfPages) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: allocated only %lu pages of %lu requested.\n"
+"InnoDB: Check that you have enough free RAM.\n"
+"InnoDB: In Windows XP Professional and 2000 Professional\n"
+"InnoDB: Windows PAE size is max 4 GB. In 2000 and .NET\n"
+"InnoDB: Advanced Servers and 2000 Datacenter Server it is 32 GB,\n"
+"InnoDB: and in .NET Datacenter Server it is 64 GB.\n"
+"InnoDB: A Microsoft web page said that the processor must be an Intel\n"
+"InnoDB: processor.\n",
+ (ulint)NumberOfPages,
+ (ulint)NumberOfPagesInitial);
+
+ return(FALSE);
+ }
+
+ fprintf(stderr,
+"InnoDB: Using Address Windowing Extensions (AWE); allocated %lu MB\n",
+ n_megabytes);
+
+ return(TRUE);
+#else
+ return(FALSE);
+#endif
+}
+
+/********************************************************************
+Allocates a window in the virtual address space where we can map then
+pages of physical memory. */
+
+byte*
+os_awe_allocate_virtual_mem_window(
+/*===============================*/
+ /* out, own: allocated memory, or NULL if did not
+ succeed */
+ ulint size) /* in: virtual memory allocation size in bytes, must
+ be < 2 GB */
+{
+#ifdef UNIV_SIMULATE_AWE
+ ulint i;
+
+ os_awe_simulate_window = ut_align(ut_malloc(4096 + size), 4096);
+ os_awe_simulate_window_size = size;
+
+ os_awe_simulate_map = ut_malloc(sizeof(byte*) * (size / 4096));
+
+ for (i = 0; i < (size / 4096); i++) {
+ *(os_awe_simulate_map + i) = NULL;
+ }
+
+ return(os_awe_simulate_window);
+
+#elif defined(__WIN2000__)
+ byte* ptr;
+
+ if (size > 0x7FFFFFFFFF) {
+ fprintf(stderr,
+"InnoDB: AWE: Cannot allocate %lu bytes of virtual memory\n", size);
+
+ return(NULL);
+ }
+
+ ptr = VirtualAlloc(NULL, (SIZE_T)size, MEM_RESERVE | MEM_PHYSICAL,
+ PAGE_READWRITE);
+ if (ptr == NULL) {
+ fprintf(stderr,
+"InnoDB: AWE: Cannot allocate %lu bytes of virtual memory, error %lu\n",
+ size, (ulint)GetLastError());
+
+ return(NULL);
+ }
+
+ os_awe_window = ptr;
+ os_awe_window_size = size;
+
+ ut_total_allocated_memory += size;
+
+ return(ptr);
+#else
+ return(NULL);
+#endif
+}
+
+/********************************************************************
+With this function you can map parts of physical memory allocated with
+the ..._allocate_physical_mem to the virtual address space allocated with
+the previous function. Intel implements this so that the process page
+tables are updated accordingly. A test on a 1.5 GHz AMD processor and XP
+showed that this takes < 1 microsecond, much better than the estimated 80 us
+for copying a 16 kB page memory to memory. But, the operation will at least
+partially invalidate the translation lookaside buffer (TLB) of all
+processors. Under a real-world load the performance hit may be bigger. */
+
+ibool
+os_awe_map_physical_mem_to_window(
+/*==============================*/
+ /* out: TRUE if success; the function
+ calls exit(1) in case of an error */
+ byte* ptr, /* in: a page-aligned pointer to
+ somewhere in the virtual address
+ space window; we map the physical mem
+ pages here */
+ ulint n_mem_pages, /* in: number of 4 kB mem pages to
+ map */
+ os_awe_t* page_info) /* in: array of page infos for those
+ pages; each page has one slot in the
+ array */
+{
+#ifdef UNIV_SIMULATE_AWE
+ ulint i;
+ byte** map;
+ byte* page;
+ byte* phys_page;
+
+ ut_a(ptr >= os_awe_simulate_window);
+ ut_a(ptr < os_awe_simulate_window + os_awe_simulate_window_size);
+ ut_a(page_info >= os_awe_simulate_page_info);
+ ut_a(page_info < os_awe_simulate_page_info +
+ (os_awe_simulate_mem_size / 4096));
+
+ /* First look if some other 'physical pages' are mapped at ptr,
+ and copy them back to where they were if yes */
+
+ map = os_awe_simulate_map
+ + ((ulint)(ptr - os_awe_simulate_window)) / 4096;
+ page = ptr;
+
+ for (i = 0; i < n_mem_pages; i++) {
+ if (*map != NULL) {
+ ut_memcpy(*map, page, 4096);
+ }
+ map++;
+ page += 4096;
+ }
+
+ /* Then copy to ptr the 'physical pages' determined by page_info; we
+ assume page_info is a segment of the array we created at the start */
+
+ phys_page = os_awe_simulate_mem
+ + (ulint)(page_info - os_awe_simulate_page_info)
+ * 4096;
+
+ ut_memcpy(ptr, phys_page, n_mem_pages * 4096);
+
+ /* Update the map */
+
+ map = os_awe_simulate_map
+ + ((ulint)(ptr - os_awe_simulate_window)) / 4096;
+
+ for (i = 0; i < n_mem_pages; i++) {
+ *map = phys_page;
+
+ map++;
+ phys_page += 4096;
+ }
+
+ return(TRUE);
+
+#elif defined(__WIN2000__)
+ BOOL bResult;
+ os_awe_t n_pages;
+
+ n_pages = (os_awe_t)n_mem_pages;
+
+ if (!(ptr >= os_awe_window)) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map to address %lx but AWE window start %lx\n",
+ (ulint)ptr, (ulint)os_awe_window);
+ ut_a(0);
+ }
+
+ if (!(ptr <= os_awe_window + os_awe_window_size - UNIV_PAGE_SIZE)) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map to address %lx but AWE window end %lx\n",
+ (ulint)ptr, (ulint)os_awe_window + os_awe_window_size);
+ ut_a(0);
+ }
+
+ if (!(page_info >= os_awe_page_info)) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map page info at %lx but array start %lx\n",
+ (ulint)page_info, (ulint)os_awe_page_info);
+ ut_a(0);
+ }
+
+ if (!(page_info <= os_awe_page_info + (os_awe_n_pages - 4))) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map page info at %lx but array end %lx\n",
+ (ulint)page_info, (ulint)(os_awe_page_info + os_awe_n_pages));
+ ut_a(0);
+ }
+
+ bResult = MapUserPhysicalPages((PVOID)ptr, n_pages, page_info);
+
+ if (bResult != TRUE) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: AWE: Mapping of %lu physical pages to address %lx failed,\n"
+"InnoDB: error %lu.\n"
+"InnoDB: Cannot continue operation.\n",
+ n_mem_pages, (ulint)ptr, (ulint)GetLastError());
+ exit(1);
+ }
+
+ return(TRUE);
+#else
+ return(FALSE);
+#endif
+}
/********************************************************************
Converts the current process id to a number. It is not guaranteed that the
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index ba56b3071cd..7cef63d1337 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -59,6 +59,19 @@ row_mysql_read_var_ref_noninline(
}
/***********************************************************************
+Frees the blob heap in prebuilt when no longer needed. */
+
+void
+row_mysql_prebuilt_free_blob_heap(
+/*==============================*/
+ row_prebuilt_t* prebuilt) /* in: prebuilt struct of a
+ ha_innobase:: table handle */
+{
+ mem_heap_free(prebuilt->blob_heap);
+ prebuilt->blob_heap = NULL;
+}
+
+/***********************************************************************
Stores a reference to a BLOB in the MySQL format. */
void
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index ea5b3020c08..34f951b0c8a 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2039,9 +2039,12 @@ Note that the template in prebuilt may advise us to copy only a few
columns to mysql_rec, other columns are left blank. All columns may not
be needed in the query. */
static
-void
+ibool
row_sel_store_mysql_rec(
/*====================*/
+ /* out: TRUE if success, FALSE
+ if could not allocate memory for a
+ BLOB */
byte* mysql_rec, /* out: row in the MySQL format */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec) /* in: Innobase record in the index
@@ -2092,7 +2095,19 @@ row_sel_store_mysql_rec(
if (templ->type == DATA_BLOB) {
ut_a(prebuilt->templ_contains_blob);
-
+
+ /* A heuristic test that we can allocate
+ the memory for a big BLOB. We have a safety
+ margin of 1000000 bytes. Since the test
+ takes some CPU time, we do not use for small
+ BLOBs. */
+
+ if (len > 2000000
+ && !ut_test_malloc(len + 1000000)) {
+
+ return(FALSE);
+ }
+
/* Copy the BLOB data to the BLOB
heap of prebuilt */
@@ -2142,6 +2157,8 @@ row_sel_store_mysql_rec(
}
}
}
+
+ return(TRUE);
}
/*************************************************************************
@@ -2526,7 +2543,8 @@ row_search_for_mysql(
/*=================*/
/* out: DB_SUCCESS,
DB_RECORD_NOT_FOUND,
- DB_END_OF_INDEX, or DB_DEADLOCK */
+ DB_END_OF_INDEX, DB_DEADLOCK,
+ or DB_TOO_BIG_RECORD */
byte* buf, /* in/out: buffer for the fetched
row in the MySQL format */
ulint mode, /* in: search mode PAGE_CUR_L, ... */
@@ -2758,7 +2776,12 @@ row_search_for_mysql(
#ifdef UNIV_SEARCH_DEBUG
ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
#endif
- row_sel_store_mysql_rec(buf, prebuilt, rec);
+ if (!row_sel_store_mysql_rec(buf, prebuilt,
+ rec)) {
+ err = DB_TOO_BIG_RECORD;
+
+ goto lock_wait_or_error;
+ }
mtr_commit(&mtr);
@@ -3200,7 +3223,11 @@ rec_loop:
rec_get_size(rec));
mach_write_to_4(buf, rec_get_extra_size(rec) + 4);
} else {
- row_sel_store_mysql_rec(buf, prebuilt, rec);
+ if (!row_sel_store_mysql_rec(buf, prebuilt, rec)) {
+ err = DB_TOO_BIG_RECORD;
+
+ goto lock_wait_or_error;
+ }
}
if (prebuilt->clust_index_was_generated) {
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index c6f3bd40dfe..af11516e9f0 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -140,9 +140,14 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
};
-ulint srv_pool_size = ULINT_MAX; /* size in database pages;
- MySQL originally sets this
- value in megabytes */
+ulint srv_pool_size = ULINT_MAX; /* size in pages; MySQL inits
+ this to size in kilobytes but
+ we normalize this to pages in
+ srv_boot() */
+ulint srv_awe_window_size = 0; /* size in pages; MySQL inits
+ this to bytes, but we
+ normalize it to pages in
+ srv_boot() */
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
ulint srv_lock_table_size = ULINT_MAX;
@@ -218,6 +223,13 @@ ibool srv_use_doublewrite_buf = TRUE;
ibool srv_set_thread_priorities = TRUE;
int srv_query_thread_priority = 0;
+
+/* TRUE if the Address Windowing Extensions of Windows are used; then we must
+disable adaptive hash indexes */
+ibool srv_use_awe = FALSE;
+ibool srv_use_adaptive_hash_indexes = TRUE;
+
+
/*-------------------------------------------*/
ulint srv_n_spin_wait_rounds = 20;
ulint srv_spin_wait_delay = 5;
@@ -2026,9 +2038,19 @@ srv_normalize_init_values(void)
srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
- srv_pool_size = srv_pool_size / UNIV_PAGE_SIZE;
+ srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024);
+
+ srv_awe_window_size = srv_awe_window_size / UNIV_PAGE_SIZE;
- srv_lock_table_size = 20 * srv_pool_size;
+ if (srv_use_awe) {
+ /* If we are using AWE we must save memory in the 32-bit
+ address space of the process, and cannot bind the lock
+ table size to the real buffer pool size. */
+
+ srv_lock_table_size = 20 * srv_awe_window_size;
+ } else {
+ srv_lock_table_size = 5 * srv_pool_size;
+ }
return(DB_SUCCESS);
}
@@ -2393,6 +2415,18 @@ srv_sprintf_innodb_monitor(
"Total memory allocated %lu; in additional pool allocated %lu\n",
ut_total_allocated_memory,
mem_pool_get_reserved(mem_comm_pool));
+
+ if (mem_out_of_mem_err_msg_count > 0) {
+ buf += sprintf(buf,
+ "Mem allocation has spilled out of additional mem pool %lu times\n");
+ }
+
+ if (srv_use_awe) {
+ buf += sprintf(buf,
+ "In addition to that %lu MB of AWE memory allocated\n",
+ srv_pool_size / ((1024 * 1024) / UNIV_PAGE_SIZE));
+ }
+
buf_print_io(buf, buf_end);
buf = buf + strlen(buf);
ut_a(buf < buf_end + 1500);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 65284d51b04..671ef4e5b22 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -935,6 +935,7 @@ innobase_start_or_create_for_mysql(void)
/*====================================*/
/* out: DB_SUCCESS or error code */
{
+ buf_pool_t* ret;
ibool create_new_db;
ibool log_file_created;
ibool log_created = FALSE;
@@ -972,6 +973,11 @@ innobase_start_or_create_for_mysql(void)
"InnoDB: !!!!!!!!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!!!!!!!\n");
#endif
+#ifdef UNIV_SIMULATE_AWE
+ fprintf(stderr,
+"InnoDB: !!!!!!!!!!!!!! UNIV_SIMULATE_AWE switched on !!!!!!!!!!!!!!!!!\n");
+#endif
+
if (srv_sizeof_trx_t_in_ha_innodb_cc != (ulint)sizeof(trx_t)) {
fprintf(stderr,
"InnoDB: Error: trx_t size is %lu in ha_innodb.cc but %lu in srv0start.c\n"
@@ -1002,6 +1008,17 @@ innobase_start_or_create_for_mysql(void)
srv_startup_is_before_trx_rollback_phase = TRUE;
os_aio_use_native_aio = FALSE;
+#if !defined(__WIN2000__) && !defined(UNIV_SIMULATE_AWE)
+ if (srv_use_awe) {
+
+ fprintf(stderr,
+"InnoDB: Error: You have specified innodb_buffer_pool_awe_mem_mb\n"
+"InnoDB: in my.cnf, but AWE can only be used in Windows 2000 and later.\n");
+
+ return(DB_ERROR);
+ }
+#endif
+
#ifdef __WIN__
if (os_get_os_version() == OS_WIN95
|| os_get_os_version() == OS_WIN31
@@ -1057,6 +1074,9 @@ innobase_start_or_create_for_mysql(void)
return(DB_ERROR);
}
+ /* Note that the call srv_boot() also changes the values of
+ srv_pool_size etc. to the units used by InnoDB internally */
+
err = srv_boot();
if (err != DB_SUCCESS) {
@@ -1088,7 +1108,26 @@ innobase_start_or_create_for_mysql(void)
fil_init(SRV_MAX_N_OPEN_FILES);
- buf_pool_init(srv_pool_size, srv_pool_size);
+ if (srv_use_awe) {
+ fprintf(stderr,
+"InnoDB: Using AWE: Memory window is %lu MB and AWE memory is %lu MB\n",
+ srv_awe_window_size / ((1024 * 1024) / UNIV_PAGE_SIZE),
+ srv_pool_size / ((1024 * 1024) / UNIV_PAGE_SIZE));
+
+ /* We must disable adaptive hash indexes because they do not
+ tolerate remapping of pages in AWE */
+
+ srv_use_adaptive_hash_indexes = FALSE;
+ ret = buf_pool_init(srv_pool_size, srv_pool_size,
+ srv_awe_window_size);
+ } else {
+ ret = buf_pool_init(srv_pool_size, srv_pool_size,
+ srv_pool_size);
+ }
+
+ if (ret == NULL) {
+ return(DB_ERROR);
+ }
fsp_init();
log_init();
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 0c10040847e..33c962772e8 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -472,9 +472,9 @@ trx_sys_update_mysql_binlog_offset(
if (0 != ut_memcmp(sys_header + field + TRX_SYS_MYSQL_LOG_NAME,
file_name, 1 + ut_strlen(file_name))) {
- mlog_write_string((byte*) (sys_header + field
- + TRX_SYS_MYSQL_LOG_NAME),
- (byte*) file_name, 1 + ut_strlen(file_name), mtr);
+ mlog_write_string(sys_header + field
+ + TRX_SYS_MYSQL_LOG_NAME,
+ file_name, 1 + ut_strlen(file_name), mtr);
}
if (mach_read_from_4(sys_header + field
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 38d15866769..5ac49397c90 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -99,7 +99,7 @@ trx_create(
trx->mysql_log_file_name = NULL;
trx->mysql_log_offset = 0;
- trx->mysql_master_log_file_name = (char*) "";
+ trx->mysql_master_log_file_name = "";
trx->mysql_master_log_pos = 0;
trx->ignore_duplicates_in_insert = FALSE;
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 03f15031fdf..a5991d5683d 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -77,8 +77,9 @@ ut_malloc_low(
ret = malloc(n + sizeof(ut_mem_block_t));
if (ret == NULL) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Fatal error: cannot allocate %lu bytes of\n"
+ " InnoDB: Fatal error: cannot allocate %lu bytes of\n"
"InnoDB: memory with malloc! Total allocated memory\n"
"InnoDB: by InnoDB %lu bytes. Operating system errno: %d\n"
"InnoDB: Cannot continue operation!\n"
@@ -135,6 +136,40 @@ ut_malloc(
}
/**************************************************************************
+Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
+out. It cannot be used if we want to return an error message. Prints to
+stderr a message if fails. */
+
+ibool
+ut_test_malloc(
+/*===========*/
+ /* out: TRUE if succeeded */
+ ulint n) /* in: try to allocate this many bytes */
+{
+ void* ret;
+
+ ret = malloc(n);
+
+ if (ret == NULL) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: cannot allocate %lu bytes of memory for\n"
+ "InnoDB: a BLOB with malloc! Total allocated memory\n"
+ "InnoDB: by InnoDB %lu bytes. Operating system errno: %d\n"
+ "InnoDB: Check if you should increase the swap file or\n"
+ "InnoDB: ulimits of your operating system.\n"
+ "InnoDB: On FreeBSD check you have compiled the OS with\n"
+ "InnoDB: a big enough maximum process size.\n",
+ n, ut_total_allocated_memory, errno);
+ return(FALSE);
+ }
+
+ free(ret);
+
+ return(TRUE);
+}
+
+/**************************************************************************
Frees a memory block allocated with ut_malloc. */
void
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index bb5eb662cd7..31a137b5fac 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -13,6 +13,7 @@ Created 5/11/1994 Heikki Tuuri
#endif
#include <stdarg.h>
+#include <string.h>
#include "ut0sort.h"
@@ -197,6 +198,7 @@ ut_get_year_month_day(
*month = (ulint)cal_tm.wMonth;
*day = (ulint)cal_tm.wDay;
#else
+ struct tm cal_tm;
struct tm* cal_tm_ptr;
time_t tm;
diff --git a/isam/Makefile.am b/isam/Makefile.am
index 8f23138f29f..6d9e4176d43 100644
--- a/isam/Makefile.am
+++ b/isam/Makefile.am
@@ -14,7 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
pkglib_LIBRARIES = libnisam.a
diff --git a/isam/_key.c b/isam/_key.c
index c0d667cb32d..871ec82eba7 100644
--- a/isam/_key.c
+++ b/isam/_key.c
@@ -53,12 +53,10 @@ uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *
}
*key++= (uchar) (length=(uint) (end-pos));
memcpy((byte*) key,(byte*) pos,(size_t) length);
-#ifdef USE_STRCOLL
- if (!use_strcoll(default_charset_info))
-#endif
+ if (!use_strnxfrm(default_charset_info))
{
if (type == HA_KEYTYPE_TEXT)
- case_sort((byte*) key,length);
+ my_tosort(default_charset_info,(byte*) key,length);
}
key+=length;
}
@@ -66,12 +64,10 @@ uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *
{
memcpy((byte*) key,(byte*) record+keyseg->base.start,
(size_t) keyseg->base.length);
-#ifdef USE_STRCOLL
- if (!use_strcoll(default_charset_info))
-#endif
+ if (!use_strnxfrm(default_charset_info))
{
if (type == HA_KEYTYPE_TEXT)
- case_sort((byte*) key,(uint) keyseg->base.length);
+ my_tosort(default_charset_info,(byte*) key,(uint) keyseg->base.length);
}
#ifdef NAN_TEST
else if (type == HA_KEYTYPE_FLOAT)
@@ -149,12 +145,10 @@ uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old,
}
else
memcpy((byte*) key,old,(size_t) length);
-#ifdef USE_STRCOLL
- if (!use_strcoll(default_charset_info))
-#endif
+ if (!use_strnxfrm(default_charset_info))
{
if (type == HA_KEYTYPE_TEXT)
- case_sort((byte*) key,length);
+ my_tosort(default_charset_info,(byte*) key,length);
}
key+= length;
}
diff --git a/isam/_search.c b/isam/_search.c
index 57787d61818..1ceeab1e824 100644
--- a/isam/_search.c
+++ b/isam/_search.c
@@ -118,7 +118,7 @@ int _nisam_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key,
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
{
keypos=_nisam_get_last_key(info,keyinfo,buff,lastkey,keypos);
- if ((nextflag & SEARCH_LAST) &&
+ if (!(nextflag & SEARCH_SMALLER) &&
_nisam_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND))
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
@@ -331,8 +331,7 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
(int) *as : b_length;
end= a+ min(key_length,(uint) length);
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info)) {
+ if (use_strnxfrm(default_charset_info)) {
if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
{
while (a < end)
@@ -349,7 +348,6 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
}
}
else
-#endif
{
while (a < end)
if ((flag= (int) *a++ - (int) *b++))
@@ -382,8 +380,7 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
}
else
{
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info)) {
+ if (use_strnxfrm(default_charset_info)) {
if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
{
while (a < end)
@@ -400,7 +397,6 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
}
}
else
-#endif
{
while (a < end)
if ((flag= (int) *a++ - (int) *b++))
@@ -515,11 +511,13 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
if (*a++ != *b++)
{
a--; b--;
- if (isdigit((char) *a) && isdigit((char) *b))
+ if (my_isdigit(default_charset_info, (char) *a) &&
+ my_isdigit(default_charset_info, (char) *b))
return ((int) *a - (int) *b);
- if (*a == '-' || isdigit((char) *b))
+ if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
return (-1);
- if (*b == '-' || *b++ == ' ' || isdigit((char) *a))
+ if (*b == '-' || *b++ == ' ' ||
+ my_isdigit(default_charset_info,(char) *a))
return (1);
if (*a++ == ' ')
return (-1);
@@ -539,11 +537,13 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
if (*a++ != *b++)
{
a--; b--;
- if (isdigit((char) *a) && isdigit((char) *b))
+ if (my_isdigit(default_charset_info,(char) *a) &&
+ my_isdigit(default_charset_info,(char) *b))
return ((int) *a - (int) *b);
- if (*a == '-' || isdigit((char) *b))
+ if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
return (-1);
- if (*b == '-' || *b++ == ' ' || isdigit((char) *a))
+ if (*b == '-' || *b++ == ' ' ||
+ my_isdigit(default_charset_info,(char) *a))
return (1);
if (*a++ == ' ')
return -1;
diff --git a/isam/isamlog.c b/isam/isamlog.c
index 0367c03e08a..ff3bca39e40 100644
--- a/isam/isamlog.c
+++ b/isam/isamlog.c
@@ -342,7 +342,7 @@ static int examine_log(my_string file_name, char **table_names)
file_info.process=0;
result=uint2korr(head+7);
if ((curr_file_info=(struct isamlog_file_info*)
- tree_search(&tree,&file_info)))
+ tree_search(&tree, &file_info, tree.custom_arg)))
{
curr_file_info->accessed=access_time;
if (update && curr_file_info->used && curr_file_info->closed)
@@ -444,7 +444,7 @@ static int examine_log(my_string file_name, char **table_names)
files_open++;
file_info.closed=0;
}
- VOID(tree_insert(&tree,(gptr) &file_info,0));
+ VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
if (file_info.used)
{
if (verbose && !record_pos_file)
@@ -463,7 +463,7 @@ static int examine_log(my_string file_name, char **table_names)
{
if (!curr_file_info->closed)
files_open--;
- VOID(tree_delete(&tree,(gptr) curr_file_info));
+ VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
}
break;
case LOG_EXTRA:
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
index b2e21afc743..fd12aac1e09 100644
--- a/isam/pack_isam.c
+++ b/isam/pack_isam.c
@@ -46,22 +46,6 @@
#define OLD_EXT ".OLD"
#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
-#ifdef __WIN__
-static double ulonglong2double(ulonglong value)
-{
- longlong nr=(longlong) value;
- if (nr >= 0)
- return (double) nr;
- return (18446744073709551616.0 + (double) nr);
-}
-
-#if SIZEOF_OFF_T > 4
-#define my_off_t2double(A) ulonglong2double(A)
-#else
-#define my_off_t2double(A) ((double) (A))
-#endif /* SIZEOF_OFF_T > 4 */
-#endif
-
struct st_file_buffer {
File file;
char *buffer,*pos,*end;
@@ -687,7 +671,8 @@ static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,
+ NULL, NULL);
if (records)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
@@ -765,7 +750,8 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->tree_buff)
{
global_count=count;
- if (!(element=tree_insert(&count->int_tree,pos,0)) ||
+ if (!(element=tree_insert(&count->int_tree, pos, 0,
+ count->int_tree.custom_arg)) ||
((element->count == 1 &&
count->tree_buff + tree_buff_length <
count->tree_pos + count->field_length) ||
@@ -1736,7 +1722,8 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
break;
case FIELD_INTERVALL:
global_count=count;
- pos=(byte*) tree_search(&count->int_tree,start_pos);
+ pos=(byte*) tree_search(&count->int_tree, start_pos,
+ count->int_tree.custom_arg);
intervall=(uint) (pos - count->tree_buff)/field_length;
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
start_pos=end_pos;
diff --git a/isam/static.c b/isam/static.c
index 9c68a0cfdba..0a8dc809ad7 100644
--- a/isam/static.c
+++ b/isam/static.c
@@ -41,5 +41,5 @@ uint NEAR nisam_read_vec[]=
{
SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
- SEARCH_FIND, SEARCH_LAST
+ SEARCH_FIND, SEARCH_LAST,SEARCH_LAST | SEARCH_SMALLER
};
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index fac544ba44d..1d5a5b19180 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -20,8 +20,7 @@
target = libmysqlclient.la
target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -DMYSQL_CLIENT
LIBS = @CLIENT_LIBS@
-INCLUDES = -I$(srcdir)/../include -I../include \
- -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes)
+INCLUDES = -I$(top_srcdir)/include $(openssl_includes)
include $(srcdir)/Makefile.shared
@@ -49,10 +48,6 @@ link_sources:
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
done; \
- for f in $(mystringsgen); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ ../strings/$$f $(srcdir)/$$f; \
- done; \
for f in $$qs; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index 9f4b3e9ccdd..9440d920719 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -27,9 +27,6 @@ pkglib_LTLIBRARIES = $(target)
noinst_PROGRAMS = conf_to_src
-# We need .lo, not .o files for everything.
-CHARSET_OBJS=@CHARSET_OBJS@
-LTCHARSET_OBJS= ${CHARSET_OBJS:.o=.lo}
target_sources = libmysql.c password.c manager.c \
get_password.c errmsg.c
@@ -38,17 +35,21 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
strmake.lo strend.lo \
strnlen.lo strfill.lo is_prefix.lo \
int2str.lo str2int.lo strinstr.lo strcont.lo \
- strcend.lo bcmp.lo \
+ strcend.lo bcmp.lo ctype-latin1.lo \
bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \
- strtoull.lo strtoll.lo llstr.lo \
- ctype.lo $(LTCHARSET_OBJS)
+ strtoull.lo strtoll.lo llstr.lo my_vsnprintf.lo \
+ ctype.lo ctype-simple.lo ctype-bin.lo ctype-mb.lo \
+ ctype-big5.lo ctype-czech.lo ctype-euc_kr.lo \
+ ctype-win1250ch.lo ctype-utf8.lo ctype-extra.lo \
+ ctype-gb2312.lo ctype-gbk.lo ctype-latin1_de.lo \
+ ctype-sjis.lo ctype-tis620.lo ctype-ujis.lo xml.lo
+
mystringsextra= strto.c
-mystringsgen= ctype_autoconf.c
dbugobjects = dbug.lo # IT IS IN SAFEMALLOC.C sanity.lo
mysysheaders = mysys_priv.h my_static.h
mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
my_create.lo my_delete.lo mf_tempfile.lo my_open.lo \
- mf_casecnv.lo my_read.lo my_write.lo errors.lo \
+ my_read.lo my_write.lo errors.lo \
my_error.lo my_getwd.lo my_div.lo \
mf_pack.lo my_messnc.lo mf_dirname.lo mf_fn_ext.lo\
mf_wcomp.lo typelib.lo safemalloc.lo my_alloc.lo \
@@ -59,7 +60,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
my_compress.lo array.lo my_once.lo list.lo my_net.lo \
charset.lo hash.lo mf_iocache.lo \
mf_iocache2.lo my_seek.lo my_sleep.lo \
- my_pread.lo mf_cache.lo my_vsnprintf.lo md5.lo \
+ my_pread.lo mf_cache.lo md5.lo sha1.lo\
my_getopt.lo my_gethostbyname.lo my_port.lo
sqlobjects = net.lo
@@ -77,8 +78,7 @@ DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
# The automatic dependencies miss this
-bmove_upp.lo: $(LTCHARSET_OBJS)
-ctype.lo: ctype_extra_sources.c
+#bmove_upp.lo: $(LTCHARSET_OBJS)
clean-local:
rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \
@@ -86,12 +86,9 @@ clean-local:
`echo $(mysysobjects) | sed "s;\.lo;.c;g"` \
`echo $(vio_objects) | sed "s;\.lo;.c;g"` \
$(CHARSET_SRCS) $(CHARSET_OBJS) \
- $(mystringsextra) $(mystringsgen) $(mysysheaders) \
- ctype_extra_sources.c net.c ../linked_client_sources
+ $(mystringsextra) $(mysysheaders) \
+ ../linked_client_sources net.c
-ctype_extra_sources.c: conf_to_src
- ./conf_to_src $(top_srcdir) @CHARSETS_NEED_SOURCE@ > \
- $(srcdir)/ctype_extra_sources.c
conf_to_src_SOURCES = conf_to_src.c
conf_to_src_LDADD=
#force static linking of conf_to_src - essential when linking against
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 375ca7329c0..bbb85885886 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -51,7 +51,27 @@ const char *client_errors[]=
"Error connecting to slave:",
"Error connecting to master:",
"SSL connection error",
- "Malformed packet"
+ "Malformed packet",
+ "Invalid use of null pointer",
+ "Statement not prepared",
+ "Not all parameters data supplied",
+ "Data truncated",
+ "No parameters exists in the statement",
+ "Invalid parameter number",
+ "Can't send long data for non string or binary data types (parameter: %d)",
+ "Using unsupported buffer type: %d (parameter: %d)",
+ "Shared memory (%lu)",
+ "Can't open shared memory. Request event don't create (%lu)",
+ "Can't open shared memory. Answer event don't create (%lu)",
+ "Can't open shared memory. File mapping don't create (%lu)",
+ "Can't open shared memory. Map of memory don't create (%lu)",
+ "Can't open shared memory. File mapping don't create for client (%lu)",
+ "Can't open shared memory. Map of memory don't create for client (%lu)",
+ "Can't open shared memory. %s event don't create for client (%lu)",
+ "Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
+ "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Wrong or unknown protocol",
+ "Invalid connection handle"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -86,7 +106,27 @@ const char *client_errors[]=
"Error connecting to slave:",
"Error connecting to master:",
"SSL connection error",
- "Malformed packet"
+ "Malformed packet",
+ "Invalid use of null pointer",
+ "Statement not prepared",
+ "Not all parameters data supplied",
+ "Data truncated",
+ "No parameters exists in the statement",
+ "Invalid parameter number",
+ "Can't send long data for non string or binary data types (parameter: %d)",
+ "Using unsupported buffer type: %d (parameter: %d)",
+ "Shared memory (%lu)",
+ "Can't open shared memory. Request event don't create (%lu)",
+ "Can't open shared memory. Answer event don't create (%lu)",
+ "Can't open shared memory. File mapping don't create (%lu)",
+ "Can't open shared memory. Map of memory don't create (%lu)",
+ "Can't open shared memory. File mapping don't create for client (%lu)",
+ "Can't open shared memory. Map of memory don't create for client (%lu)",
+ "Can't open shared memory. %s event don't create for client (%lu)",
+ "Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
+ "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Wrong or unknown protocol",
+ "Invalid connection handle"
};
#else /* ENGLISH */
@@ -119,7 +159,27 @@ const char *client_errors[]=
"Error connecting to slave:",
"Error connecting to master:",
"SSL connection error",
- "Malformed packet"
+ "Malformed packet",
+ "Invalid use of null pointer",
+ "Statement not prepared",
+ "Not all parameters data supplied",
+ "Data truncated",
+ "No parameters exists in the statement",
+ "Invalid parameter number",
+ "Can't send long data for non string or binary data types (parameter: %d)",
+ "Using unsupported buffer type: %d (parameter: %d)",
+ "Shared memory (%lu)",
+ "Can't open shared memory. Request event don't create (%lu)",
+ "Can't open shared memory. Answer event don't create (%lu)",
+ "Can't open shared memory. File mapping don't create (%lu)",
+ "Can't open shared memory. Map of memory don't create (%lu)",
+ "Can't open shared memory. File mapping don't create for client (%lu)",
+ "Can't open shared memory. Map of memory don't create for client (%lu)",
+ "Can't open shared memory. %s event don't create for client (%lu)",
+ "Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
+ "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Wrong or unknown protocol",
+ "Invalid connection handle"
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 10cfb5ec88c..fe435616532 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
+#include <assert.h> /* for DBUG_ASSERT() */
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -40,7 +41,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#ifdef HAVE_SELECT_H
-# include <select.h>
+#include <select.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
@@ -64,7 +65,10 @@ ulong max_allowed_packet= 1024L*1024L*1024L;
ulong net_read_timeout= NET_READ_TIMEOUT;
ulong net_write_timeout= NET_WRITE_TIMEOUT;
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS)
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \
+ | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \
+ | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+
#ifdef __WIN__
#define CONNECT_TIMEOUT 20
@@ -80,6 +84,23 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT;
#define SOCKET_ERROR -1
#endif /* __WIN__ */
+#ifdef HAVE_SMEM
+char *shared_memory_base_name=0;
+const char *def_shared_memory_base_name=default_shared_memory_base_name;
+#endif
+
+const char *sql_protocol_names_lib[] =
+{ "TCP", "SOCKET", "PIPE", "MEMORY",NullS };
+TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
+ sql_protocol_names_lib};
+/*
+ If allowed through some configuration, then this needs to
+ be changed
+*/
+#define MAX_LONG_DATA_LENGTH 8192
+#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)
+#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
+
static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields,
uint field_count);
static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
@@ -88,11 +109,12 @@ static void end_server(MYSQL *mysql);
static void read_user_name(char *name);
static void append_wild(char *to,char *end,const char *wild);
static my_bool mysql_reconnect(MYSQL *mysql);
-static int send_file_to_server(MYSQL *mysql,const char *filename);
+static my_bool send_file_to_server(MYSQL *mysql,const char *filename);
static sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length);
-
+static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list);
+static void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count);
static my_bool org_my_init_done=0;
int STDCALL mysql_server_init(int argc __attribute__((unused)),
@@ -150,7 +172,7 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
/****************************************************************************
- A modified version of connect(). connect2() allows you to specify
+ A modified version of connect(). my_connect() allows you to specify
a timeout value, in seconds, that we should wait until we
derermine we can't connect to a particular host. If timeout is 0,
my_connect() will behave exactly like connect().
@@ -158,11 +180,11 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
-int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
- uint timeout)
+my_bool my_connect(my_socket s, const struct sockaddr *name,
+ uint namelen, uint timeout)
{
#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
#else
int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
@@ -175,7 +197,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/
if (timeout == 0)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK
@@ -188,7 +210,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
if ((res != 0) && (s_err != EINPROGRESS))
{
errno = s_err; /* Restore it */
- return(-1);
+ return(1);
}
if (res == 0) /* Connected quickly! */
return(0);
@@ -212,9 +234,9 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
FD_ZERO(&sfds);
FD_SET(s, &sfds);
/*
- * select could be interrupted by a signal, and if it is,
+ * select could be interrupted by a signal, and if it is,
* the timeout should be adjusted and the select restarted
- * to work around OSes that don't restart select and
+ * to work around OSes that don't restart select and
* implementations of select that don't adjust tv upon
* failure to reflect the time remaining
*/
@@ -233,7 +255,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
now_time=time(NULL);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
- return -1;
+ return 1;
}
/* select() returned something more interesting than zero, let's
@@ -243,12 +265,12 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
- return(-1);
+ return(1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
- return(-1); /* but return an error... */
+ return(1); /* but return an error... */
}
return(0); /* It's all good! */
#endif
@@ -326,6 +348,192 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
}
#endif
+/*
+ Create new shared memory connection, return handler of connection
+
+ SYNOPSIS
+ create_shared_memory()
+ mysql Pointer of mysql structure
+ net Pointer of net structure
+ connect_timeout Timeout of connection
+*/
+#ifdef HAVE_SMEM
+HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
+{
+ ulong smem_buffer_length = shared_memory_buffer_length + 4;
+/*
+ event_connect_request is event object for start connection actions
+ event_connect_answer is event object for confirm, that server put data
+ handle_connect_file_map is file-mapping object, use for create shared memory
+ handle_connect_map is pointer on shared memory
+ handle_map is pointer on shared memory for client
+ event_server_wrote,
+ event_server_read,
+ event_client_wrote,
+ event_client_read are events for transfer data between server and client
+ handle_file_map is file-mapping object, use for create shared memory
+*/
+ HANDLE event_connect_request = NULL;
+ HANDLE event_connect_answer = NULL;
+ HANDLE handle_connect_file_map = NULL;
+ char *handle_connect_map = NULL;
+
+ char *handle_map = NULL;
+ HANDLE event_server_wrote = NULL;
+ HANDLE event_server_read = NULL;
+ HANDLE event_client_wrote = NULL;
+ HANDLE event_client_read = NULL;
+ HANDLE handle_file_map = NULL;
+ ulong connect_number;
+ char connect_number_char[22], *p;
+ char tmp[64];
+ char *suffix_pos;
+ DWORD error_allow = 0;
+ DWORD error_code = 0;
+ char *shared_memory_base_name = mysql->options.shared_memory_base_name;
+
+/*
+ The name of event and file-mapping events create agree next rule:
+ shared_memory_base_name+unique_part
+ Where:
+ shared_memory_base_name is unique value for each server
+ unique_part is uniquel value for each object (events and file-mapping)
+*/
+ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS);
+ strmov(suffix_pos, "CONNECT_REQUEST");
+ if ((event_connect_request = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR;
+ goto err;
+ }
+ strmov(suffix_pos, "CONNECT_ANSWER");
+ if ((event_connect_answer = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR;
+ goto err;
+ }
+ strmov(suffix_pos, "CONNECT_DATA");
+ if ((handle_connect_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR;
+ goto err;
+ }
+ if ((handle_connect_map = MapViewOfFile(handle_connect_file_map,FILE_MAP_WRITE,0,0,sizeof(DWORD))) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR;
+ goto err;
+ }
+/*
+ Send to server request of connection
+*/
+ if (!SetEvent(event_connect_request))
+ {
+ error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR;
+ goto err;
+ }
+/*
+ Wait of answer from server
+*/
+ if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != WAIT_OBJECT_0)
+ {
+ error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR;
+ goto err;
+ }
+/*
+ Get number of connection
+*/
+ connect_number = uint4korr(handle_connect_map);/*WAX2*/
+ p = int2str(connect_number, connect_number_char, 10);
+
+/*
+ The name of event and file-mapping events create agree next rule:
+ shared_memory_base_name+unique_part+number_of_connection
+ Where:
+ shared_memory_base_name is uniquel value for each server
+ unique_part is uniquel value for each object (events and file-mapping)
+ number_of_connection is number of connection between server and client
+*/
+ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
+ "_",NullS);
+ strmov(suffix_pos, "DATA");
+ if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR;
+ goto err2;
+ }
+ if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0,
+ smem_buffer_length)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_MAP_ERROR;
+ goto err2;
+ }
+
+ strmov(suffix_pos, "SERVER_WROTE");
+ if ((event_server_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
+ goto err2;
+ }
+
+ strmov(suffix_pos, "SERVER_READ");
+ if ((event_server_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
+ goto err2;
+ }
+
+ strmov(suffix_pos, "CLIENT_WROTE");
+ if ((event_client_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
+ goto err2;
+ }
+
+ strmov(suffix_pos, "CLIENT_READ");
+ if ((event_client_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
+ {
+ error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
+ goto err2;
+ }
+/*
+ Set event that server should send data
+*/
+ SetEvent(event_server_read);
+
+err2:
+ if (error_allow == 0)
+ {
+ net->vio = vio_new_win32shared_memory(net,handle_file_map,handle_map,event_server_wrote,
+ event_server_read,event_client_wrote,event_client_read);
+ }
+ else
+ {
+ error_code = GetLastError();
+ if (event_server_read) CloseHandle(event_server_read);
+ if (event_server_wrote) CloseHandle(event_server_wrote);
+ if (event_client_read) CloseHandle(event_client_read);
+ if (event_client_wrote) CloseHandle(event_client_wrote);
+ if (handle_map) UnmapViewOfFile(handle_map);
+ if (handle_file_map) CloseHandle(handle_file_map);
+ }
+err:
+ if (error_allow) error_code = GetLastError();
+ if (event_connect_request) CloseHandle(event_connect_request);
+ if (event_connect_answer) CloseHandle(event_connect_answer);
+ if (handle_connect_map) UnmapViewOfFile(handle_connect_map);
+ if (handle_connect_file_map) CloseHandle(handle_connect_file_map);
+ if (error_allow)
+ {
+ net->last_errno=error_allow;
+ if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR)
+ sprintf(net->last_error,ER(net->last_errno),suffix_pos,error_code);
+ else
+ sprintf(net->last_error,ER(net->last_errno),error_code);
+ return(INVALID_HANDLE_VALUE);
+ }
+ return(handle_map);
+};
+#endif
/*****************************************************************************
read a packet from server. Give error message if socket was down
@@ -454,37 +662,37 @@ static void free_rows(MYSQL_DATA *cur)
}
-int
-simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
- ulong length, my_bool skipp_check)
+static my_bool
+advanced_command(MYSQL *mysql, enum enum_server_command command,
+ const char *header, ulong header_length,
+ const char *arg, ulong arg_length, my_bool skip_check)
{
NET *net= &mysql->net;
- int result= -1;
+ my_bool result= 1;
init_sigpipe_variables
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
+
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql))
- goto end;
+ return 1;
}
if (mysql->status != MYSQL_STATUS_READY)
{
strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
- goto end;
+ return 1;
}
mysql->net.last_error[0]=0;
mysql->net.last_errno=0;
mysql->info=0;
mysql->affected_rows= ~(my_ulonglong) 0;
- net_clear(net); /* Clear receive buffer */
- if (!arg)
- arg="";
+ net_clear(&mysql->net); /* Clear receive buffer */
- if (net_write_command(net,(uchar) command,arg,
- length ? length : (ulong) strlen(arg)))
+ if (net_write_command(net,(uchar) command, header, header_length,
+ arg, arg_length))
{
DBUG_PRINT("error",("Can't send command to server. Error: %d",
socket_errno));
@@ -497,8 +705,8 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
end_server(mysql);
if (mysql_reconnect(mysql))
goto end;
- if (net_write_command(net,(uchar) command,arg,
- length ? length : (ulong) strlen(arg)))
+ if (net_write_command(net,(uchar) command, header, header_length,
+ arg, arg_length))
{
net->last_errno=CR_SERVER_GONE_ERROR;
strmov(net->last_error,ER(net->last_errno));
@@ -506,15 +714,23 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
}
}
result=0;
- if (!skipp_check)
+ if (!skip_check)
result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
- -1 : 0);
+ 1 : 0);
end:
reset_sigpipe(mysql);
return result;
}
+my_bool
+simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ ulong length, my_bool skip_check)
+{
+ return advanced_command(mysql, command, NullS, 0, arg, length, skip_check);
+}
+
+
static void free_old_query(MYSQL *mysql)
{
DBUG_ENTER("free_old_query");
@@ -526,6 +742,7 @@ static void free_old_query(MYSQL *mysql)
DBUG_VOID_RETURN;
}
+
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
struct passwd *getpwuid(uid_t);
char* getlogin(void);
@@ -612,7 +829,6 @@ append_wild(char *to, char *end, const char *wild)
}
-
/**************************************************************************
Init debugging if MYSQL_DEBUG environment variable is found
**************************************************************************/
@@ -697,13 +913,13 @@ mysql_free_result(MYSQL_RES *result)
{
if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
{
- DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
+ DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows"));
for (;;)
{
ulong pkt_len;
if ((pkt_len=net_safe_read(result->handle)) == packet_error)
break;
- if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
+ if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
break; /* End of data */
}
result->handle->status=MYSQL_STATUS_READY;
@@ -732,12 +948,34 @@ static const char *default_options[]=
"connect-timeout", "local-infile", "disable-local-infile",
"replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-cipher", "max-allowed-packet",
+ "protocol", "shared-memory-base-name",
NullS
};
static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options};
+static int add_init_command(struct st_mysql_options *options, const char *cmd)
+{
+ char *tmp;
+
+ if (!options->init_commands)
+ {
+ options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
+ MYF(MY_WME));
+ init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
+ }
+
+ if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
+ insert_dynamic(options->init_commands, (gptr)&tmp))
+ {
+ my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
+ return 1;
+ }
+
+ return 0;
+}
+
static void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
{
@@ -783,6 +1021,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
break;
case 3: /* compress */
options->compress=1;
+ options->client_flag|= CLIENT_COMPRESS;
break;
case 4: /* password */
if (opt_arg)
@@ -791,9 +1030,8 @@ static void mysql_read_default_options(struct st_mysql_options *options,
options->password=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 5: /* pipe */
- options->named_pipe=1; /* Force named pipe */
- break;
+ case 5:
+ options->protocol = MYSQL_PROTOCOL_PIPE;
case 20: /* connect_timeout */
case 6: /* timeout */
if (opt_arg)
@@ -807,11 +1045,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
}
break;
case 8: /* init-command */
- if (opt_arg)
- {
- my_free(options->init_command,MYF(MY_ALLOW_ZERO_PTR));
- options->init_command=my_strdup(opt_arg,MYF(MY_WME));
- }
+ add_init_command(options,opt_arg);
break;
case 9: /* host */
if (opt_arg)
@@ -889,6 +1123,20 @@ static void mysql_read_default_options(struct st_mysql_options *options,
case 27:
options->max_allowed_packet= atoi(opt_arg);
break;
+ case 28: /* protocol */
+ if ((options->protocol = find_type(opt_arg, &sql_protocol_typelib,0)) == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
+ exit(1);
+ }
+ break;
+ case 29: /* shared_memory_base_name */
+#ifdef HAVE_SMEM
+ if (options->shared_memory_base_name != def_shared_memory_base_name)
+ my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
+#endif
+ break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -906,41 +1154,95 @@ static void mysql_read_default_options(struct st_mysql_options *options,
static MYSQL_FIELD *
unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
- my_bool default_value, my_bool long_flag_protocol)
+ my_bool default_value, uint server_capabilities)
{
MYSQL_ROWS *row;
MYSQL_FIELD *field,*result;
+ ulong lengths[8]; /* Max of fields */
DBUG_ENTER("unpack_fields");
field=result=(MYSQL_FIELD*) alloc_root(alloc,
(uint) sizeof(MYSQL_FIELD)*fields);
if (!result)
+ {
+ free_rows(data); /* Free old data */
DBUG_RETURN(0);
-
- for (row=data->data; row ; row = row->next,field++)
+ }
+ bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields);
+ if (server_capabilities & CLIENT_PROTOCOL_41)
{
- field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
- field->name= strdup_root(alloc,(char*) row->data[1]);
- field->length= (uint) uint3korr(row->data[2]);
- field->type= (enum enum_field_types) (uchar) row->data[3][0];
- if (long_flag_protocol)
+ /* server is 4.1, and returns the new field result format */
+ for (row=data->data; row ; row = row->next,field++)
{
- field->flags= uint2korr(row->data[4]);
- field->decimals=(uint) (uchar) row->data[4][2];
+ uchar *pos;
+ fetch_lengths(&lengths[0], row->data, default_value ? 7 : 6);
+ field->db = strdup_root(alloc,(char*) row->data[0]);
+ field->table = strdup_root(alloc,(char*) row->data[1]);
+ field->org_table= strdup_root(alloc,(char*) row->data[2]);
+ field->name = strdup_root(alloc,(char*) row->data[3]);
+ field->org_name = strdup_root(alloc,(char*) row->data[4]);
+
+ field->db_length= lengths[0];
+ field->table_length= lengths[1];
+ field->org_table_length= lengths[2];
+ field->name_length= lengths[3];
+ field->org_name_length= lengths[4];
+
+ /* Unpack fixed length parts */
+ pos= (uchar*) row->data[5];
+ field->charsetnr= uint2korr(pos);
+ field->length= (uint) uint3korr(pos+2);
+ field->type= (enum enum_field_types) pos[5];
+ field->flags= uint2korr(pos+6);
+ field->decimals= (uint) pos[8];
+
+ if (INTERNAL_NUM_FIELD(field))
+ field->flags|= NUM_FLAG;
+ if (default_value && row->data[6])
+ {
+ field->def=strdup_root(alloc,(char*) row->data[8]);
+ field->def_length= lengths[6];
+ }
}
- else
+ }
+#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
+ else
+ {
+ /* old protocol, for backward compatibility */
+ for (row=data->data; row ; row = row->next,field++)
{
- field->flags= (uint) (uchar) row->data[4][0];
- field->decimals=(uint) (uchar) row->data[4][1];
+ fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
+ field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
+ field->name= strdup_root(alloc,(char*) row->data[1]);
+ field->length= (uint) uint3korr(row->data[2]);
+ field->type= (enum enum_field_types) (uchar) row->data[3][0];
+
+ field->org_table_length= field->table_length= lengths[0];
+ field->name_length= lengths[1];
+
+ if (server_capabilities & CLIENT_LONG_FLAG)
+ {
+ field->flags= uint2korr(row->data[4]);
+ field->decimals=(uint) (uchar) row->data[4][2];
+ }
+ else
+ {
+ field->flags= (uint) (uchar) row->data[4][0];
+ field->decimals=(uint) (uchar) row->data[4][1];
+ }
+ if (INTERNAL_NUM_FIELD(field))
+ field->flags|= NUM_FLAG;
+ if (default_value && row->data[5])
+ {
+ field->def=strdup_root(alloc,(char*) row->data[5]);
+ field->def_length= lengths[5];
+ }
+ else
+ field->def=0;
+ field->max_length= 0;
}
- if (INTERNAL_NUM_FIELD(field))
- field->flags|= NUM_FLAG;
- if (default_value && row->data[5])
- field->def=strdup_root(alloc,(char*) row->data[5]);
- else
- field->def=0;
- field->max_length= 0;
}
+#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
free_rows(data); /* Free old data */
DBUG_RETURN(result);
}
@@ -976,14 +1278,22 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
result->rows=0;
result->fields=fields;
- while (*(cp=net->read_pos) != 254 || pkt_len != 1)
+ /*
+ The last EOF packet is either a single 254 character or (in MySQL 4.1)
+ 254 followed by 1-7 status bytes.
+
+ This doesn't conflict with normal usage of 254 which stands for a
+ string where the length of the string is 8 bytes. (see net_field_length())
+ */
+
+ while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
{
result->rows++;
if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
- sizeof(MYSQL_ROWS))) ||
+ sizeof(MYSQL_ROWS))) ||
!(cur->data= ((MYSQL_ROW)
alloc_root(&result->alloc,
- (fields+1)*sizeof(char *)+pkt_len))))
+ (fields+1)*sizeof(char *)+pkt_len))))
{
free_rows(result);
net->last_errno=CR_OUT_OF_MEMORY;
@@ -1028,6 +1338,11 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
}
}
*prev_ptr=0; /* last pointer is null */
+ if (pkt_len > 1) /* MySQL 4.1 protocol */
+ {
+ mysql->warning_count= uint2korr(cp+1);
+ DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
+ }
DBUG_PRINT("exit",("Got %d rows",result->rows));
DBUG_RETURN(result);
}
@@ -1048,8 +1363,12 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
if ((pkt_len=net_safe_read(mysql)) == packet_error)
return -1;
- if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
+ if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ {
+ if (pkt_len > 1) /* MySQL 4.1 protocol */
+ mysql->warning_count= uint2korr(mysql->net.read_pos+1);
return 1; /* End of data */
+ }
prev_pos= 0; /* allowed to write at packet[-1] */
pos=mysql->net.read_pos;
end_pos=pos+pkt_len;
@@ -1082,7 +1401,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
}
/* perform query on master */
-int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
unsigned long length)
{
DBUG_ENTER("mysql_master_query");
@@ -1091,8 +1410,8 @@ int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
DBUG_RETURN(mysql_read_query_result(mysql));
}
-int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length)
+my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+ unsigned long length)
{
MYSQL *master = mysql->master;
DBUG_ENTER("mysql_master_send_query");
@@ -1103,9 +1422,9 @@ int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
}
-/* perform query on slave */
-int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length)
+/* perform query on slave */
+my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+ unsigned long length)
{
DBUG_ENTER("mysql_slave_query");
if (mysql_slave_send_query(mysql, q, length))
@@ -1113,7 +1432,8 @@ int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
DBUG_RETURN(mysql_read_query_result(mysql));
}
-int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+
+my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned long length)
{
MYSQL* last_used_slave, *slave_to_use = 0;
@@ -1147,7 +1467,7 @@ void STDCALL mysql_disable_rpl_parse(MYSQL* mysql)
mysql->options.rpl_parse = 0;
}
-/* get the value of the parse flag */
+/* get the value of the parse flag */
int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql)
{
return mysql->options.rpl_parse;
@@ -1164,8 +1484,8 @@ void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
mysql->options.no_master_reads = 1;
}
-/* get the value of the master read flag */
-int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
+/* get the value of the master read flag */
+my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
{
return !(mysql->options.no_master_reads);
}
@@ -1194,7 +1514,7 @@ static void expand_error(MYSQL* mysql, int error)
read the given result and row
*/
-static int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
+static my_bool get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
{
MYSQL* master;
DBUG_ENTER("get_master");
@@ -1214,11 +1534,11 @@ static int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
retrieve all the slaves
*/
-static int get_slaves_from_master(MYSQL* mysql)
+static my_bool get_slaves_from_master(MYSQL* mysql)
{
MYSQL_RES* res = 0;
MYSQL_ROW row;
- int error = 1;
+ my_bool error = 1;
int has_auth_info;
int port_ind;
DBUG_ENTER("get_slaves_from_master");
@@ -1281,11 +1601,11 @@ err:
}
-int STDCALL mysql_rpl_probe(MYSQL* mysql)
+my_bool STDCALL mysql_rpl_probe(MYSQL* mysql)
{
MYSQL_RES *res= 0;
MYSQL_ROW row;
- int error = 1;
+ my_bool error= 1;
DBUG_ENTER("mysql_rpl_probe");
/*
@@ -1293,7 +1613,7 @@ int STDCALL mysql_rpl_probe(MYSQL* mysql)
the most reliable way to do this is to run SHOW SLAVE STATUS and see
if we have a non-empty master host. This is still not fool-proof -
it is not a sin to have a master that has a dormant slave thread with
- a non-empty master host. However, it is more reliable to check
+ a non-empty master host. However, it is more reliable to check
for empty master than whether the slave thread is actually running
*/
if (mysql_query(mysql, "SHOW SLAVE STATUS") ||
@@ -1348,9 +1668,9 @@ STDCALL mysql_rpl_query_type(const char* q, int len)
for (; q < q_end; ++q)
{
char c;
- if (isalpha(c=*q))
+ if (my_isalpha(system_charset_info, (c= *q)))
{
- switch(tolower(c)) {
+ switch (my_tolower(system_charset_info,c)) {
case 'i': /* insert */
case 'u': /* update or unlock tables */
case 'l': /* lock tables or load data infile */
@@ -1358,9 +1678,11 @@ STDCALL mysql_rpl_query_type(const char* q, int len)
case 'a': /* alter */
return MYSQL_RPL_MASTER;
case 'c': /* create or check */
- return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_MASTER ;
+ return my_tolower(system_charset_info,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
+ MYSQL_RPL_MASTER;
case 's': /* select or show */
- return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_SLAVE;
+ return my_tolower(system_charset_info,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
+ MYSQL_RPL_SLAVE;
case 'f': /* flush */
case 'r': /* repair */
case 'g': /* grant */
@@ -1397,7 +1719,7 @@ mysql_init(MYSQL *mysql)
By default, we are a replication pivot. The caller must reset it
after we return if this is not the case.
*/
- mysql->rpl_pivot = 1;
+ mysql->rpl_pivot = 1;
#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__)
if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE))
(void) signal(SIGPIPE,pipe_sig_handler);
@@ -1410,6 +1732,9 @@ mysql_init(MYSQL *mysql)
#ifdef ENABLED_LOCAL_INFILE
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
#endif
+#ifdef HAVE_SMEM
+ mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name;
+#endif
return mysql;
}
@@ -1478,11 +1803,11 @@ void STDCALL mysql_once_init(void)
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
-int STDCALL
+my_bool STDCALL
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
- const char *key __attribute__((unused)),
+ const char *key __attribute__((unused)),
const char *cert __attribute__((unused)),
- const char *ca __attribute__((unused)),
+ const char *ca __attribute__((unused)),
const char *capath __attribute__((unused)),
const char *cipher __attribute__((unused)))
{
@@ -1492,7 +1817,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
mysql->options.ssl_ca= strdup_if_not_null(ca);
mysql->options.ssl_capath= strdup_if_not_null(capath);
mysql->options.ssl_cipher= strdup_if_not_null(cipher);
-#endif
+#endif /* HAVE_OPENSSL */
return 0;
}
@@ -1502,10 +1827,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************/
-static int
+#ifdef HAVE_OPENSSL
+static void
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
{
-#ifdef HAVE_OPENSSL
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
@@ -1519,9 +1844,8 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
mysql->options.ssl_cipher= 0;
mysql->options.use_ssl = FALSE;
mysql->connector_fd = 0;
-#endif /* HAVE_OPENSSL */
- return 0;
}
+#endif /* HAVE_OPENSSL */
/**************************************************************************
Connect to sql server
@@ -1556,10 +1880,11 @@ mysql_connect(MYSQL *mysql,const char *host,
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
- uint port, const char *unix_socket,uint client_flag)
+ uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16];
char *end,*host_info,*charset_name;
+ char password_hash[SCRAMBLE41_LENGTH]; /* tmp storage stage1 hash */
my_socket sock;
uint32 ip_addr;
struct sockaddr_in sock_addr;
@@ -1621,9 +1946,38 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
/*
** Grab a socket and connect it to the server
*/
-
+#if defined(HAVE_SMEM)
+ if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)&&
+ (!host || !strcmp(host,LOCAL_HOST)))
+ {
+ if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
+ INVALID_HANDLE_VALUE)
+ {
+ DBUG_PRINT("error",
+ ("host: '%s' socket: '%s' shared memory: %s have_tcpip: %d",
+ host ? host : "<null>",
+ unix_socket ? unix_socket : "<null>",
+ (int) mysql->options.shared_memory_base_name,
+ (int) have_tcpip));
+ if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
+ goto error;
+/*
+Try also with PIPE or TCP/IP
+*/
+ }
+ else
+ {
+ mysql->options.protocol=MYSQL_PROTOCOL_MEMORY;
+ sock=0;
+ unix_socket = 0;
+ host=mysql->options.shared_memory_base_name;
+ host_info=(char*) ER(CR_SHARED_MEMORY_CONNECTION);
+ }
+ } else
+#endif //HAVE_SMEM
#if defined(HAVE_SYS_UN_H)
- if ((!host || !strcmp(host,LOCAL_HOST)) && (unix_socket || mysql_unix_port))
+ if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&&
+ (!host || !strcmp(host,LOCAL_HOST)) && (unix_socket || mysql_unix_port))
{
host=LOCAL_HOST;
if (!unix_socket)
@@ -1641,53 +1995,49 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, unix_socket);
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
- mysql->options.connect_timeout) <0)
+ mysql->options.connect_timeout))
{
DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno));
net->last_errno=CR_CONNECTION_ERROR;
sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno);
goto error;
}
+ else
+ mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
}
else
#elif defined(__WIN__)
+ if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&&
+ ((unix_socket || !host && is_NT() ||
+ host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||!have_tcpip))&&(!net->vio))
{
- if ((unix_socket ||
- !host && is_NT() ||
- host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||
- mysql->options.named_pipe || !have_tcpip))
+ sock=0;
+ if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout,
+ (char**) &host, (char**) &unix_socket)) ==
+ INVALID_HANDLE_VALUE)
{
- sock=0;
- if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout,
- (char**) &host, (char**) &unix_socket)) ==
- INVALID_HANDLE_VALUE)
- {
- DBUG_PRINT("error",
- ("host: '%s' socket: '%s' named_pipe: %d have_tcpip: %d",
- host ? host : "<null>",
- unix_socket ? unix_socket : "<null>",
- (int) mysql->options.named_pipe,
- (int) have_tcpip));
- if (mysql->options.named_pipe ||
- (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
- (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
- {
- net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
- goto error; /* User only requested named pipes */
- }
- /* Try also with TCP/IP */
- }
- else
- {
- net->vio=vio_new_win32pipe(hPipe);
- sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host,
- unix_socket);
- }
+ DBUG_PRINT("error",
+ ("host: '%s' socket: '%s' have_tcpip: %d",
+ host ? host : "<null>",
+ unix_socket ? unix_socket : "<null>",
+ (int) have_tcpip));
+ if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
+ (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
+ (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
+ goto error;
+ /*
+ Try also with TCP/IP
+ */
+ }
+ else
+ {
+ net->vio=vio_new_win32pipe(hPipe);
+ sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host,
+ unix_socket);
}
}
- if (hPipe == INVALID_HANDLE_VALUE)
#endif
+ if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio))
{
unix_socket=0; /* This is not used */
if (!port)
@@ -1734,7 +2084,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
}
sock_addr.sin_port = (ushort) htons((ushort) port);
if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
- mysql->options.connect_timeout) <0)
+ mysql->options.connect_timeout))
{
DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host));
net->last_errno= CR_CONN_HOST_ERROR;
@@ -1742,6 +2092,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
goto error;
}
}
+ else
+ if (!net->vio)
+ {
+ DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
+ net->last_errno= CR_CONN_UNKNOW_PROTOCOL;
+ sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL));
+ goto error;
+ };
if (!net->vio || my_net_init(net, net->vio))
{
@@ -1759,13 +2117,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
vio_poll_read(net->vio, mysql->options.connect_timeout))
{
net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
- /* Check if version of protocoll matches current one */
+ /* Check if version of protocol matches current one */
mysql->protocol_version= net->read_pos[0];
DBUG_DUMP("packet",(char*) net->read_pos,10);
@@ -1872,32 +2230,28 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
#endif /* HAVE_OPENSSL */
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
-#ifdef HAVE_COMPRESS
- if ((mysql->server_capabilities & CLIENT_COMPRESS) &&
- (mysql->options.compress || (client_flag & CLIENT_COMPRESS)))
- client_flag|=CLIENT_COMPRESS; /* We will use compression */
- else
+ /* Remove options that server doesn't support */
+ client_flag= ((client_flag &
+ ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
+ (client_flag & mysql->server_capabilities));
+
+#ifndef HAVE_COMPRESS
+ client_flag&= ~CLIENT_COMPRESS;
#endif
- client_flag&= ~CLIENT_COMPRESS;
-#ifdef HAVE_OPENSSL
- if ((mysql->server_capabilities & CLIENT_SSL) &&
- (mysql->options.use_ssl || (client_flag & CLIENT_SSL)))
+ if (client_flag & CLIENT_PROTOCOL_41)
{
- DBUG_PRINT("info", ("Changing IO layer to SSL"));
- client_flag |= CLIENT_SSL;
+ /* 4.1 server and 4.1 client has a 4 byte option flag */
+ int4store(buff,client_flag);
+ int4store(buff+4,max_allowed_packet);
+ end= buff+8;
}
else
{
- if (client_flag & CLIENT_SSL)
- {
- DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL"));
- }
- client_flag &= ~CLIENT_SSL;
+ int2store(buff,client_flag);
+ int3store(buff+2,max_allowed_packet);
+ end= buff+5;
}
-#endif /* HAVE_OPENSSL */
-
- int2store(buff,client_flag);
mysql->client_flag=client_flag;
#ifdef HAVE_OPENSSL
@@ -1908,10 +2262,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (client_flag & CLIENT_SSL)
{
struct st_mysql_options *options= &mysql->options;
- if (my_net_write(net,buff,(uint) (2)) || net_flush(net))
+ if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Do the SSL layering. */
@@ -1923,64 +2277,160 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
options->ssl_cipher)))
{
net->last_errno= CR_SSL_CONNECTION_ERROR;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
DBUG_PRINT("info", ("IO layer change in progress..."));
- if(sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),
- mysql->net.vio, (long) (mysql->options.connect_timeout)))
+ if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),
+ mysql->net.vio, (long) (mysql->options.connect_timeout)))
{
net->last_errno= CR_SSL_CONNECTION_ERROR;
strmov(net->last_error,ER(net->last_errno));
- goto error;
+ goto error;
}
DBUG_PRINT("info", ("IO layer change done!"));
}
#endif /* HAVE_OPENSSL */
- DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d client_flag: %d",
+ DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
mysql->server_version,mysql->server_capabilities,
mysql->server_status, client_flag));
-
/* This needs to be changed as it's not useful with big packets */
- int3store(buff+2,max_allowed_packet);
if (user && user[0])
- strmake(buff+5,user,32); /* Max user name */
+ strmake(end,user,32); /* Max user name */
else
- read_user_name((char*) buff+5);
+ read_user_name((char*) end);
+ /* We have to handle different version of handshake here */
#ifdef _CUSTOMCONFIG_
#include "_cust_libmysql.h";
#endif
- DBUG_PRINT("info",("user: %s",buff+5));
- end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
+ DBUG_PRINT("info",("user: %s",end));
+ /*
+ We always start with old type handshake the only difference is message sent
+ If server handles secure connection type we'll not send the real scramble
+ */
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ if (passwd[0])
+ {
+ /* Prepare false scramble */
+ end=strend(end)+1;
+ bfill(end, SCRAMBLE_LENGTH, 'x');
+ end+=SCRAMBLE_LENGTH;
+ *end=0;
+ }
+ else /* For empty password*/
+ {
+ end=strend(end)+1;
+ *end=0; /* Store zero length scramble */
+ }
+ }
+ else
+ {
+ /*
+ Real scramble is only sent to old servers. This can be blocked
+ by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
+ */
+ end=scramble(strend(end)+1, mysql->scramble_buff, passwd,
+ (my_bool) (mysql->protocol_version == 9));
+ }
+ /* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end=strmake(end+1,db,NAME_LEN);
mysql->db=my_strdup(db,MYF(MY_WME));
db=0;
}
+ /* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
- if (net_safe_read(mysql) == packet_error)
+
+ /* We shall only query sever if it expect us to do so */
+
+ if ( (pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
+
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ /* This should always happen with new server unless empty password */
+ if (pkt_length==24 && net->read_pos[0])
+ /* OK/Error packets have zero as the first char */
+ {
+ /* Old passwords will have '*' at the first byte of hash */
+ if (net->read_pos[0] != '*')
+ {
+ /* Build full password hash as it is required to decode scramble */
+ password_hash_stage1(buff, passwd);
+ /* Store copy as we'll need it later */
+ memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
+ /* Finally hash complete password using hash we got from server */
+ password_hash_stage2(password_hash,(const char*) net->read_pos);
+ /* Decypt and store scramble 4 = hash for stage2 */
+ password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
+ password_hash, SCRAMBLE41_LENGTH);
+ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
+ /* Encode scramble with password. Recycle buffer */
+ password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
+ }
+ else
+ {
+ /* Create password to decode scramble */
+ create_key_from_old_password(passwd,password_hash);
+ /* Decypt and store scramble 4 = hash for stage2 */
+ password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
+ password_hash, SCRAMBLE41_LENGTH);
+ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
+ /* Finally scramble decoded scramble with password */
+ scramble(buff, mysql->scramble_buff, passwd,0);
+ }
+ /* Write second package of authentication */
+ if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+ /* Read What server thinks about out new auth message report */
+ if (net_safe_read(mysql) == packet_error)
+ goto error;
+ }
+ }
+
+ /* End of authentication part of handshake */
+
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
if (mysql->options.max_allowed_packet)
net->max_packet_size= mysql->options.max_allowed_packet;
if (db && mysql_select_db(mysql,db))
goto error;
- if (mysql->options.init_command)
+
+ if (mysql->options.init_commands)
{
+ DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
+ char **ptr= (char**)init_commands->buffer;
+ char **end= ptr + init_commands->elements;
+
my_bool reconnect=mysql->reconnect;
mysql->reconnect=0;
- if (mysql_query(mysql,mysql->options.init_command))
- goto error;
- mysql_free_result(mysql_use_result(mysql));
+
+ for (; ptr<end; ptr++)
+ {
+ MYSQL_RES *res;
+ if (mysql_query(mysql,*ptr))
+ goto error;
+ if (mysql->fields)
+ {
+ if (!(res= mysql_use_result(mysql)))
+ goto error;
+ mysql_free_result(res);
+ }
+ }
+
mysql->reconnect=reconnect;
}
@@ -2056,7 +2506,7 @@ static my_bool mysql_reconnect(MYSQL *mysql)
mysql->free_me=0;
mysql_close(mysql);
*mysql=tmp_mysql;
- mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */
+ mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */
net_clear(&mysql->net);
mysql->affected_rows= ~(my_ulonglong) 0;
DBUG_RETURN(0);
@@ -2064,13 +2514,17 @@ static my_bool mysql_reconnect(MYSQL *mysql)
/**************************************************************************
- Change user and database
+ Change user and database
**************************************************************************/
-my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
+my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db)
{
- char buff[512],*pos=buff;
+ char buff[512],*end=buff;
+ ulong pkt_length;
+ char password_hash[SCRAMBLE41_LENGTH]; /* Used for tmp storage of stage1 hash */
+ NET *net= &mysql->net;
+
DBUG_ENTER("mysql_change_user");
if (!user)
@@ -2078,12 +2532,91 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
if (!passwd)
passwd="";
- pos=strmov(pos,user)+1;
- pos=scramble(pos, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
- pos=strmov(pos+1,db ? db : "");
- if (simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (pos-buff),0))
- DBUG_RETURN(1);
+ /* Store user into the buffer */
+ end=strmov(end,user)+1;
+
+ /*
+ We always start with old type handshake the only difference is message sent
+ If server handles secure connection type we'll not send the real scramble
+ */
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ if (passwd[0])
+ {
+ /* Prepare false scramble */
+ bfill(end, SCRAMBLE_LENGTH, 'x');
+ end+=SCRAMBLE_LENGTH;
+ *end=0;
+
+ }
+ else /* For empty password*/
+ *end=0; /* Store zero length scramble */
+ }
+ else
+ /*
+ Real scramble is only sent to old servers. This can be blocked
+ by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
+ */
+ end=scramble(end, mysql->scramble_buff, passwd,
+ (my_bool) (mysql->protocol_version == 9));
+
+ /* Add database if needed */
+ end=strmov(end+1,db ? db : "");
+
+ /* Write authentication package */
+
+ simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
+
+ /* We shall only query sever if it expect us to do so */
+ if ( (pkt_length=net_safe_read(mysql)) == packet_error)
+ goto error;
+
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ /* This should always happen with new server unless empty password */
+ if (pkt_length==24 && net->read_pos[0])
+ /* Err/OK messages has first character=0 */
+ {
+ /* Old passwords will have zero at the first byte of hash */
+ if (net->read_pos[0] != '*')
+ {
+ /* Build full password hash as it is required to decode scramble */
+ password_hash_stage1(buff, passwd);
+ /* Store copy as we'll need it later */
+ memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
+ /* Finally hash complete password using hash we got from server */
+ password_hash_stage2(password_hash, (const char*) net->read_pos);
+ /* Decypt and store scramble 4 = hash for stage2 */
+ password_crypt((const char*) net->read_pos+4, mysql->scramble_buff,
+ password_hash, SCRAMBLE41_LENGTH);
+ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
+ /* Encode scramble with password. Recycle buffer */
+ password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
+ }
+ else
+ {
+ /* Create password to decode scramble */
+ create_key_from_old_password(passwd,password_hash);
+ /* Decypt and store scramble 4 = hash for stage2 */
+ password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
+ password_hash, SCRAMBLE41_LENGTH);
+ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
+ /* Finally scramble decoded scramble with password */
+ scramble(buff, mysql->scramble_buff, passwd,
+ (my_bool) (mysql->protocol_version == 9));
+ }
+ /* Write second package of authentication */
+ if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+ /* Read What server thinks about out new auth message report */
+ if (net_safe_read(mysql) == packet_error)
+ goto error;
+ }
+ }
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
@@ -2093,6 +2626,10 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
mysql->passwd=my_strdup(passwd,MYF(MY_WME));
mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
DBUG_RETURN(0);
+
+ error:
+ DBUG_RETURN(1);
+
}
@@ -2138,7 +2675,6 @@ mysql_close(MYSQL *mysql)
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
@@ -2148,9 +2684,23 @@ mysql_close(MYSQL *mysql)
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ if (mysql->options.init_commands)
+ {
+ DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
+ char **ptr= (char**)init_commands->buffer;
+ char **end= ptr + init_commands->elements;
+ for (; ptr<end; ptr++)
+ my_free(*ptr,MYF(MY_WME));
+ delete_dynamic(init_commands);
+ my_free((char*)init_commands,MYF(MY_WME));
+ }
#ifdef HAVE_OPENSSL
mysql_ssl_free(mysql);
#endif /* HAVE_OPENSSL */
+#ifdef HAVE_SMEM
+ if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
+ my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif /* HAVE_SMEM */
/* Clear pointers for better safety */
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
bzero((char*) &mysql->options,sizeof(mysql->options));
@@ -2168,6 +2718,16 @@ mysql_close(MYSQL *mysql)
}
mysql->rpl_pivot=0;
}
+ if (mysql->stmts)
+ {
+ /* Free any open prepared statements */
+ LIST *element, *next_element;
+ for (element= mysql->stmts; element; element= next_element)
+ {
+ next_element= element->next;
+ stmt_close((MYSQL_STMT *)element->data, 0);
+ }
+ }
if (mysql != mysql->master)
mysql_close(mysql->master);
if (mysql->free_me)
@@ -2254,7 +2814,7 @@ STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
Send the query and return so we can do something else.
Needs to be followed by mysql_read_query_result() when we want to
finish processing it.
-*/
+*/
int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
@@ -2280,7 +2840,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length)
}
-int STDCALL mysql_read_query_result(MYSQL *mysql)
+my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
{
uchar *pos;
ulong field_count;
@@ -2288,13 +2848,14 @@ int STDCALL mysql_read_query_result(MYSQL *mysql)
ulong length;
DBUG_ENTER("mysql_read_query_result");
- /* read from the connection which we actually used, which
- could differ from the original connection if we have slaves
- */
+ /*
+ Read from the connection which we actually used, which
+ could differ from the original connection if we have slaves
+ */
mysql = mysql->last_used_con;
if ((length = net_safe_read(mysql)) == packet_error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
get_info:
pos=(uchar*) mysql->net.read_pos;
@@ -2302,10 +2863,18 @@ get_info:
{
mysql->affected_rows= net_field_length_ll(&pos);
mysql->insert_id= net_field_length_ll(&pos);
- if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
+ if (protocol_41(mysql))
{
mysql->server_status=uint2korr(pos); pos+=2;
+ mysql->warning_count=uint2korr(pos); pos+=2;
}
+ else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
+ {
+ mysql->server_status=uint2korr(pos); pos+=2;
+ mysql->warning_count= 0;
+ }
+ DBUG_PRINT("info",("status: %ld warning_count: %ld",
+ mysql->server_status, mysql->warning_count));
if (pos < mysql->net.read_pos+length && net_field_length(&pos))
mysql->info=(char*) pos;
DBUG_RETURN(0);
@@ -2314,22 +2883,23 @@ get_info:
{
int error=send_file_to_server(mysql,(char*) pos);
if ((length=net_safe_read(mysql)) == packet_error || error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
goto get_info; /* Get info packet */
}
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS;
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
- if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
- DBUG_RETURN(-1);
+
+ if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 6 : 5)))
+ DBUG_RETURN(1);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
(uint) field_count,0,
- (my_bool) test(mysql->server_capabilities &
- CLIENT_LONG_FLAG))))
- DBUG_RETURN(-1);
- mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->server_capabilities)))
+ DBUG_RETURN(1);
+ mysql->status= MYSQL_STATUS_GET_RESULT;
mysql->field_count= (uint) field_count;
+ mysql->warning_count= 0;
DBUG_RETURN(0);
}
@@ -2342,15 +2912,16 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length)
DBUG_PRINT("query",("Query = '%-.4096s'",query));
if (mysql_send_query(mysql,query,length))
- DBUG_RETURN(-1);
- DBUG_RETURN(mysql_read_query_result(mysql));
+ DBUG_RETURN(1);
+ DBUG_RETURN((int) mysql_read_query_result(mysql));
}
-static int
+static my_bool
send_file_to_server(MYSQL *mysql, const char *filename)
{
- int fd, readcount, result= -1;
+ int fd, readcount;
+ my_bool result= 1;
uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
char *buf, tmp_name[FN_REFLEN];
DBUG_ENTER("send_file_to_server");
@@ -2358,7 +2929,7 @@ send_file_to_server(MYSQL *mysql, const char *filename)
if (!(buf=my_malloc(packet_length,MYF(0))))
{
strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
fn_format(tmp_name,filename,"","",4); /* Convert to client format */
@@ -2567,33 +3138,37 @@ mysql_fetch_row(MYSQL_RES *res)
else the lengths are calculated from the offset between pointers.
**************************************************************************/
+static void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count)
+{
+ ulong *prev_length;
+ byte *start=0;
+ MYSQL_ROW end;
+
+ prev_length=0; /* Keep gcc happy */
+ for (end=column + field_count + 1 ; column != end ; column++, to++)
+ {
+ if (!*column)
+ {
+ *to= 0; /* Null */
+ continue;
+ }
+ if (start) /* Found end of prev string */
+ *prev_length= (ulong) (*column-start-1);
+ start= *column;
+ prev_length= to;
+ }
+}
+
+
ulong * STDCALL
mysql_fetch_lengths(MYSQL_RES *res)
{
- ulong *lengths,*prev_length;
- byte *start;
- MYSQL_ROW column,end;
+ MYSQL_ROW column;
if (!(column=res->current_row))
return 0; /* Something is wrong */
if (res->data)
- {
- start=0;
- prev_length=0; /* Keep gcc happy */
- lengths=res->lengths;
- for (end=column+res->field_count+1 ; column != end ; column++,lengths++)
- {
- if (!*column)
- {
- *lengths=0; /* Null */
- continue;
- }
- if (start) /* Found end of prev string */
- *prev_length= (ulong) (*column-start-1);
- start= *column;
- prev_length=lengths;
- }
- }
+ fetch_lengths(res->lengths, column, res->field_count);
return res->lengths;
}
@@ -2691,7 +3266,8 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) ||
- !(query = read_rows(mysql,(MYSQL_FIELD*) 0,6)))
+ !(query = read_rows(mysql,(MYSQL_FIELD*) 0,
+ protocol_41(mysql) ? 7 : 6)))
DBUG_RETURN(NULL);
free_old_query(mysql);
@@ -2705,13 +3281,13 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
mysql->fields=0;
result->field_count = (uint) query->rows;
result->fields= unpack_fields(query,&result->field_alloc,
- result->field_count,1,
- (my_bool) test(mysql->server_capabilities &
- CLIENT_LONG_FLAG));
+ result->field_count, 1,
+ mysql->server_capabilities);
result->eof=1;
DBUG_RETURN(result);
}
+
/* List all running processes (threads) in server */
MYSQL_RES * STDCALL
@@ -2728,11 +3304,11 @@ mysql_list_processes(MYSQL *mysql)
free_old_query(mysql);
pos=(uchar*) mysql->net.read_pos;
field_count=(uint) net_field_length(&pos);
- if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0,5)))
+ if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0,
+ protocol_41(mysql) ? 6 : 5)))
DBUG_RETURN(NULL);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
- (my_bool) test(mysql->server_capabilities &
- CLIENT_LONG_FLAG))))
+ mysql->server_capabilities)))
DBUG_RETURN(0);
mysql->status=MYSQL_STATUS_GET_RESULT;
mysql->field_count=field_count;
@@ -2826,6 +3402,35 @@ mysql_get_server_info(MYSQL *mysql)
}
+/*
+ Get version number for server in a form easy to test on
+
+ SYNOPSIS
+ mysql_get_server_version()
+ mysql Connection
+
+ EXAMPLE
+ 4.1.0-alfa -> 40100
+
+ NOTES
+ We will ensure that a newer server always has a bigger number.
+
+ RETURN
+ Signed number > 323000
+*/
+
+ulong STDCALL
+mysql_get_server_version(MYSQL *mysql)
+{
+ uint major, minor, version;
+ char *pos= mysql->server_version, *end_pos;
+ major= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
+ minor= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
+ version= (uint) strtoul(pos, &end_pos, 10);
+ return (ulong) major*10000L+(ulong) (minor*100+version);
+}
+
+
const char * STDCALL
mysql_get_host_info(MYSQL *mysql)
{
@@ -2857,9 +3462,10 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
break;
case MYSQL_OPT_COMPRESS:
mysql->options.compress= 1; /* Remember for connect */
+ mysql->options.client_flag|= CLIENT_COMPRESS;
break;
case MYSQL_OPT_NAMED_PIPE:
- mysql->options.named_pipe=1; /* Force named pipe */
+ mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
break;
case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
if (!arg || test(*(uint*) arg))
@@ -2868,8 +3474,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
break;
case MYSQL_INIT_COMMAND:
- my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
- mysql->options.init_command=my_strdup(arg,MYF(MY_WME));
+ add_init_command(&mysql->options,arg);
break;
case MYSQL_READ_DEFAULT_FILE:
my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
@@ -2887,8 +3492,18 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
break;
+ case MYSQL_OPT_PROTOCOL:
+ mysql->options.protocol= *(uint*) arg;
+ break;
+ case MYSQL_SHARED_MEMORY_BASE_NAME:
+#ifdef HAVE_SMEM
+ if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
+ my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME));
+#endif
+ break;
default:
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
@@ -2961,6 +3576,11 @@ const char * STDCALL mysql_error(MYSQL *mysql)
return mysql->net.last_error;
}
+uint STDCALL mysql_warning_count(MYSQL *mysql)
+{
+ return mysql->warning_count;
+}
+
const char *STDCALL mysql_info(MYSQL *mysql)
{
return mysql->info;
@@ -3183,3 +3803,1766 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
}
*to=0;
}
+
+/********************************************************************
+
+ Implementation of new client-server prototypes for 4.1 version
+ starts from here ..
+
+ mysql_* are real prototypes used by applications
+
+*********************************************************************/
+
+/********************************************************************
+ Misc Utility functions
+********************************************************************/
+
+/*
+ Set the internal stmt error messages
+*/
+
+static void set_stmt_error(MYSQL_STMT * stmt, int errcode)
+{
+ DBUG_ENTER("set_stmt_error");
+ DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
+ DBUG_ASSERT(stmt != 0);
+
+ stmt->last_errno= errcode;
+ strmov(stmt->last_error, ER(errcode));
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Copy error message to statement handler
+*/
+
+static void set_stmt_errmsg(MYSQL_STMT * stmt, char *err, int errcode)
+{
+ DBUG_ENTER("set_stmt_error_msg");
+ DBUG_PRINT("enter", ("error: %d '%s'", errcode, err));
+ DBUG_ASSERT(stmt != 0);
+
+ stmt->last_errno= errcode;
+ if (err && err[0])
+ strmov(stmt->last_error, err);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Set the internal error message to mysql handler
+*/
+
+static void set_mysql_error(MYSQL * mysql, int errcode)
+{
+ DBUG_ENTER("set_mysql_error");
+ DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
+ DBUG_ASSERT(mysql != 0);
+
+ mysql->net.last_errno= errcode;
+ strmov(mysql->net.last_error, ER(errcode));
+}
+
+
+/*
+ Reallocate the NET package to be at least of 'length' bytes
+
+ SYNPOSIS
+ my_realloc_str()
+ net The NET structure to modify
+ int length Ensure that net->buff is at least this big
+
+ RETURN VALUES
+ 0 ok
+ 1 Error
+
+*/
+
+static my_bool my_realloc_str(NET *net, ulong length)
+{
+ ulong buf_length= (ulong) (net->write_pos - net->buff);
+ my_bool res=0;
+ DBUG_ENTER("my_realloc_str");
+ if (buf_length + length > net->max_packet)
+ {
+ res= net_realloc(net, buf_length + length);
+ net->write_pos= net->buff+ buf_length;
+ }
+ DBUG_RETURN(res);
+}
+
+/********************************************************************
+ Prepare related implementations
+********************************************************************/
+
+/*
+ Read the prepare statement results ..
+
+ NOTE
+ This is only called for connection to servers that supports
+ prepared statements (and thus the 4.1 protocol)
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+static my_bool read_prepare_result(MYSQL_STMT *stmt)
+{
+ uchar *pos;
+ uint field_count;
+ ulong length, param_count;
+ MYSQL_DATA *fields_data;
+ MYSQL *mysql= stmt->mysql;
+ DBUG_ENTER("read_prepare_result");
+
+ mysql= mysql->last_used_con;
+ if ((length= net_safe_read(mysql)) == packet_error)
+ DBUG_RETURN(1);
+
+ pos= (uchar*) mysql->net.read_pos;
+ stmt->stmt_id= uint4korr(pos); pos+=4;
+ field_count= uint2korr(pos); pos+=2;
+ param_count= uint2korr(pos); pos+=2;
+
+ if (field_count != 0)
+ {
+ if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
+ mysql->server_status|= SERVER_STATUS_IN_TRANS;
+
+ mysql->extra_info= net_field_length_ll(&pos);
+ if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 8)))
+ DBUG_RETURN(1);
+ if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root,
+ field_count,0,
+ mysql->server_capabilities)))
+ DBUG_RETURN(1);
+ }
+ if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
+ sizeof(MYSQL_BIND)*
+ (param_count +
+ field_count))))
+ {
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY);
+ DBUG_RETURN(0);
+ }
+ stmt->bind= (stmt->params + param_count);
+ stmt->field_count= (uint) field_count;
+ stmt->param_count= (ulong) param_count;
+ mysql->status= MYSQL_STATUS_READY;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Prepare the query and return the new statement handle to
+ caller.
+
+ Also update the total parameter count along with resultset
+ metadata information by reading from server
+*/
+
+
+MYSQL_STMT *STDCALL
+mysql_prepare(MYSQL *mysql, const char *query, ulong length)
+{
+ MYSQL_STMT *stmt;
+ DBUG_ENTER("mysql_prepare");
+ DBUG_ASSERT(mysql != 0);
+
+#ifdef CHECK_EXTRA_ARGUMENTS
+ if (!query)
+ {
+ set_mysql_error(mysql, CR_NULL_POINTER);
+ DBUG_RETURN(0);
+ }
+#endif
+
+ if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT),
+ MYF(MY_WME | MY_ZEROFILL))) ||
+ !(stmt->query= my_strdup_with_length((byte *) query, length, MYF(0))))
+ {
+ my_free((gptr) stmt, MYF(MY_ALLOW_ZERO_PTR));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY);
+ DBUG_RETURN(0);
+ }
+ if (simple_command(mysql, COM_PREPARE, query, length, 1))
+ {
+ stmt_close(stmt, 1);
+ DBUG_RETURN(0);
+ }
+
+ init_alloc_root(&stmt->mem_root,8192,0);
+ stmt->mysql= mysql;
+ if (read_prepare_result(stmt))
+ {
+ stmt_close(stmt, 1);
+ DBUG_RETURN(0);
+ }
+ stmt->state= MY_ST_PREPARE;
+ mysql->stmts= list_add(mysql->stmts, &stmt->list);
+ stmt->list.data= stmt;
+ DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
+ DBUG_RETURN(stmt);
+}
+
+/*
+ Get the execute query meta information for non-select
+ statements (on demand).
+*/
+
+unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
+{
+ MYSQL_FIELD *fields, *field, *end;
+ MEM_ROOT *alloc= &stmt->mem_root;
+
+ if (!stmt->mysql->field_count)
+ return 0;
+
+ stmt->field_count= stmt->mysql->field_count;
+
+ /*
+ Get the field information for non-select statements
+ like SHOW and DESCRIBE commands
+ */
+ if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
+ sizeof(MYSQL_FIELD) * stmt->field_count)) ||
+ !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
+ sizeof(MYSQL_BIND ) * stmt->field_count)))
+ return 0;
+
+ for (fields= stmt->mysql->fields, end= fields+stmt->field_count,
+ field= stmt->fields;
+ field && fields < end; fields++, field++)
+ {
+ field->db = strdup_root(alloc,fields->db);
+ field->table = strdup_root(alloc,fields->table);
+ field->org_table= strdup_root(alloc,fields->org_table);
+ field->name = strdup_root(alloc,fields->name);
+ field->org_name = strdup_root(alloc,fields->org_name);
+ field->charsetnr= fields->charsetnr;
+ field->length = fields->length;
+ field->type = fields->type;
+ field->flags = fields->flags;
+ field->decimals = fields->decimals;
+ field->def = fields->def ? strdup_root(alloc,fields->def): 0;
+ field->max_length= 0;
+ }
+ return stmt->field_count;
+}
+
+/*
+ Returns prepared meta information in the form of resultset
+ to client.
+*/
+
+MYSQL_RES * STDCALL
+mysql_prepare_result(MYSQL_STMT *stmt)
+{
+ MYSQL_RES *result;
+ DBUG_ENTER("mysql_prepare_result");
+
+ if (!stmt->field_count || !stmt->fields)
+ {
+ if (!alloc_stmt_fields(stmt))
+ DBUG_RETURN(0);
+ }
+ if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
+ sizeof(ulong)*stmt->field_count,
+ MYF(MY_WME | MY_ZEROFILL))))
+ return 0;
+
+ result->eof=1; /* Marker for buffered */
+ result->fields= stmt->fields;
+ result->field_count= stmt->field_count;
+ DBUG_RETURN(result);
+}
+
+/*
+ Returns parameter columns meta information in the form of
+ resultset.
+*/
+
+MYSQL_RES * STDCALL
+mysql_param_result(MYSQL_STMT *stmt)
+{
+ DBUG_ENTER("mysql_param_result");
+
+ if (!stmt->param_count)
+ DBUG_RETURN(0);
+
+ /*
+ TODO: Fix this when server sends the information.
+ Till then keep a dummy prototype
+ */
+ DBUG_RETURN(0);
+}
+
+
+
+/********************************************************************
+ Prepare-execute, and param handling
+*********************************************************************/
+
+/*
+ Store the buffer type
+*/
+
+static void store_param_type(NET *net, uint type)
+{
+ int2store(net->write_pos, type);
+ net->write_pos+=2;
+}
+
+/*
+ Store the length of parameter data
+ (Same function as in sql/net_pkg.cc)
+*/
+
+char *
+net_store_length(char *pkg, ulong length)
+{
+ uchar *packet=(uchar*) pkg;
+ if (length < 251)
+ {
+ *packet=(uchar) length;
+ return (char*) packet+1;
+ }
+ /* 251 is reserved for NULL */
+ if (length < 65536L)
+ {
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+ }
+ if (length < 16777216L)
+ {
+ *packet++=253;
+ int3store(packet,(ulong) length);
+ return (char*) packet+3;
+ }
+ *packet++=254;
+ int8store(packet, (ulonglong) length);
+ return (char*) packet+9;
+}
+
+
+/****************************************************************************
+ Functions to store parameter data from a prepared statement.
+
+ All functions has the following characteristics:
+
+ SYNOPSIS
+ store_param_xxx()
+ net MySQL NET connection
+ param MySQL bind param
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Can't alloc net->buffer)
+****************************************************************************/
+
+
+static void store_param_tinyint(NET *net, MYSQL_BIND *param)
+{
+ *(net->write_pos++)= (uchar) *param->buffer;
+}
+
+static void store_param_short(NET *net, MYSQL_BIND *param)
+{
+ short value= *(short*) param->buffer;
+ int2store(net->write_pos,value);
+ net->write_pos+=2;
+}
+
+static void store_param_int32(NET *net, MYSQL_BIND *param)
+{
+ int32 value= *(int32*) param->buffer;
+ int4store(net->write_pos,value);
+ net->write_pos+=4;
+}
+
+static void store_param_int64(NET *net, MYSQL_BIND *param)
+{
+ longlong value= *(longlong*) param->buffer;
+ int8store(net->write_pos,value);
+ net->write_pos+= 8;
+}
+
+static void store_param_float(NET *net, MYSQL_BIND *param)
+{
+ float value= *(float*) param->buffer;
+ float4store(net->write_pos, value);
+ net->write_pos+= 4;
+}
+
+static void store_param_double(NET *net, MYSQL_BIND *param)
+{
+ double value= *(double*) param->buffer;
+ float8store(net->write_pos, value);
+ net->write_pos+= 8;
+}
+
+static void store_param_time(NET *net, MYSQL_BIND *param)
+{
+ MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
+ char buff[15], *pos;
+ uint length;
+
+ pos= buff+1;
+ pos[0]= tm->neg ? 1: 0;
+ int4store(pos+1, tm->day);
+ pos[5]= (uchar) tm->hour;
+ pos[6]= (uchar) tm->minute;
+ pos[7]= (uchar) tm->second;
+ int4store(pos+8, tm->second_part);
+ if (tm->second_part)
+ length= 11;
+ else if (tm->hour || tm->minute || tm->second || tm->day)
+ length= 8;
+ else
+ length= 0;
+ buff[0]= (char) length++;
+ memcpy((char *)net->write_pos, buff, length);
+ net->write_pos+= length;
+}
+
+static void net_store_datetime(NET *net, MYSQL_TIME *tm)
+{
+ char buff[12], *pos;
+ uint length;
+
+ pos= buff+1;
+
+ int2store(pos, tm->year);
+ pos[2]= (uchar) tm->month;
+ pos[3]= (uchar) tm->day;
+ pos[4]= (uchar) tm->hour;
+ pos[5]= (uchar) tm->minute;
+ pos[6]= (uchar) tm->second;
+ int4store(pos+7, tm->second_part);
+ if (tm->second_part)
+ length= 11;
+ else if (tm->hour || tm->minute || tm->second)
+ length= 7;
+ else if (tm->year || tm->month || tm->day)
+ length= 4;
+ else
+ length= 0;
+ buff[0]= (char) length++;
+ memcpy((char *)net->write_pos, buff, length);
+ net->write_pos+= length;
+}
+
+static void store_param_date(NET *net, MYSQL_BIND *param)
+{
+ MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
+ tm->hour= tm->minute= tm->second= 0;
+ tm->second_part= 0;
+ net_store_datetime(net, tm);
+}
+
+static void store_param_datetime(NET *net, MYSQL_BIND *param)
+{
+ MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
+ net_store_datetime(net, tm);
+}
+
+static void store_param_str(NET *net, MYSQL_BIND *param)
+{
+ ulong length= min(*param->length, param->buffer_length);
+ char *to= (char *) net_store_length((char *) net->write_pos, length);
+ memcpy(to, param->buffer, length);
+ net->write_pos= (uchar*) to+length;
+}
+
+
+/*
+ Mark if the parameter is NULL.
+
+ SYNOPSIS
+ store_param_null()
+ net MySQL NET connection
+ param MySQL bind param
+
+ DESCRIPTION
+ A data package starts with a string of bits where we set a bit
+ if a parameter is NULL
+*/
+
+static void store_param_null(NET *net, MYSQL_BIND *param)
+{
+ uint pos= param->param_number;
+ (uchar) net->buff[pos/8]|= (1 << pos & 7);
+}
+
+
+/*
+ Set parameter data by reading from input buffers from the
+ client application
+*/
+
+
+static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
+{
+ MYSQL *mysql= stmt->mysql;
+ NET *net = &mysql->net;
+ DBUG_ENTER("store_param");
+ DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %lu is_null: %d",
+ param->buffer_type,
+ param->buffer ? param->buffer : "0", *param->length,
+ *param->is_null));
+
+ if (*param->is_null)
+ store_param_null(net, param);
+ else
+ {
+ /*
+ Param->length should ALWAYS point to the correct length for the type
+ Either to the length pointer given by the user or param->buffer_length
+ */
+ if ((my_realloc_str(net, 9 + *param->length)))
+ {
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY);
+ DBUG_RETURN(1);
+ }
+ (*param->store_param_func)(net, param);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Send the prepare query to server for execution
+*/
+
+static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
+{
+ MYSQL *mysql= stmt->mysql;
+ NET *net= &mysql->net;
+ char buff[MYSQL_STMT_HEADER];
+ DBUG_ENTER("execute");
+ DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
+
+ mysql->last_used_con= mysql;
+ int4store(buff, stmt->stmt_id); /* Send stmt id to server */
+ if (advanced_command(mysql, COM_EXECUTE, buff, MYSQL_STMT_HEADER, packet,
+ length, 1) ||
+ mysql_read_query_result(mysql))
+ {
+ set_stmt_errmsg(stmt, net->last_error, net->last_errno);
+ DBUG_RETURN(1);
+ }
+ stmt->state= MY_ST_EXECUTE;
+ mysql_free_result(stmt->result);
+ stmt->result= (MYSQL_RES *)0;
+ stmt->result_buffered= 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Execute the prepare query
+*/
+
+int STDCALL mysql_execute(MYSQL_STMT *stmt)
+{
+ DBUG_ENTER("mysql_execute");
+
+ if (stmt->state == MY_ST_UNKNOWN)
+ {
+ set_stmt_error(stmt, CR_NO_PREPARE_STMT);
+ DBUG_RETURN(1);
+ }
+ stmt->mysql->fields= stmt->fields;
+ if (stmt->param_count)
+ {
+ NET *net= &stmt->mysql->net;
+ MYSQL_BIND *param, *param_end;
+ char *param_data;
+ ulong length;
+ uint null_count;
+ my_bool result;
+
+#ifdef CHECK_EXTRA_ARGUMENTS
+ if (!stmt->param_buffers)
+ {
+ /* Parameters exists, but no bound buffers */
+ set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND);
+ DBUG_RETURN(1);
+ }
+#endif
+ net_clear(net); /* Sets net->write_pos */
+ /* Reserve place for null-marker bytes */
+ null_count= (stmt->param_count+7) /8;
+ bzero((char*) net->write_pos, null_count);
+ net->write_pos+= null_count;
+ param_end= stmt->params + stmt->param_count;
+
+ /* In case if buffers (type) altered, indicate to server */
+ *(net->write_pos)++= (uchar) stmt->send_types_to_server;
+ if (stmt->send_types_to_server)
+ {
+ /*
+ Store types of parameters in first in first package
+ that is sent to the server.
+ */
+ for (param= stmt->params; param < param_end ; param++)
+ store_param_type(net, (uint) param->buffer_type);
+ }
+
+ for (param= stmt->params; param < param_end; param++)
+ {
+ /* check if mysql_long_data() was used */
+ if (param->long_data_used)
+ param->long_data_used= 0; /* Clear for next execute call */
+ else if (store_param(stmt, param))
+ DBUG_RETURN(1);
+ }
+ length= (ulong) (net->write_pos - net->buff);
+ /* TODO: Look into avoding the following memdup */
+ if (!(param_data= my_memdup((const char*) net->buff, length, MYF(0))))
+ {
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY);
+ DBUG_RETURN(1);
+ }
+ net->write_pos= net->buff; /* Reset for net_write() */
+ result= execute(stmt, param_data, length);
+ stmt->send_types_to_server=0;
+ my_free(param_data, MYF(MY_WME));
+ DBUG_RETURN(result);
+ }
+ DBUG_RETURN((int) execute(stmt,0,0));
+}
+
+
+/*
+ Return total parameters count in the statement
+*/
+
+ulong STDCALL mysql_param_count(MYSQL_STMT * stmt)
+{
+ DBUG_ENTER("mysql_param_count");
+ DBUG_RETURN(stmt->param_count);
+}
+
+/*
+ Return total affected rows from the last statement
+*/
+
+my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
+{
+ return stmt->mysql->last_used_con->affected_rows;
+}
+
+
+static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
+static my_bool int_is_null_false= 0;
+static my_bool int_is_null_dummy;
+static unsigned long param_length_is_dummy;
+
+/*
+ Setup the parameter data buffers from application
+*/
+
+my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
+{
+ uint count=0;
+ MYSQL_BIND *param, *end;
+ DBUG_ENTER("mysql_bind_param");
+
+#ifdef CHECK_EXTRA_ARGUMENTS
+ if (stmt->state == MY_ST_UNKNOWN)
+ {
+ set_stmt_error(stmt, CR_NO_PREPARE_STMT);
+ DBUG_RETURN(1);
+ }
+ if (!stmt->param_count)
+ {
+ set_stmt_error(stmt, CR_NO_PARAMETERS_EXISTS);
+ DBUG_RETURN(1);
+ }
+#endif
+
+ /* Allocated on prepare */
+ memcpy((char*) stmt->params, (char*) bind,
+ sizeof(MYSQL_BIND) * stmt->param_count);
+
+ for (param= stmt->params, end= param+stmt->param_count;
+ param < end ;
+ param++)
+ {
+ param->param_number= count++;
+ param->long_data_used= 0;
+
+ /*
+ If param->length is not given, change it to point to buffer_length.
+ This way we can always use *param->length to get the length of data
+ */
+ if (!param->length)
+ param->length= &param->buffer_length;
+
+ /* If param->is_null is not set, then the value can never be NULL */
+ if (!param->is_null)
+ param->is_null= &int_is_null_false;
+
+ /* Setup data copy functions for the different supported types */
+ switch (param->buffer_type) {
+ case MYSQL_TYPE_NULL:
+ param->is_null= &int_is_null_true;
+ break;
+ case MYSQL_TYPE_TINY:
+ /* Force param->length as this is fixed for this type */
+ param->length= &param->buffer_length;
+ param->buffer_length= 1;
+ param->store_param_func= store_param_tinyint;
+ break;
+ case MYSQL_TYPE_SHORT:
+ param->length= &param->buffer_length;
+ param->buffer_length= 2;
+ param->store_param_func= store_param_short;
+ break;
+ case MYSQL_TYPE_LONG:
+ param->length= &param->buffer_length;
+ param->buffer_length= 4;
+ param->store_param_func= store_param_int32;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ param->length= &param->buffer_length;
+ param->buffer_length= 8;
+ param->store_param_func= store_param_int64;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ param->length= &param->buffer_length;
+ param->buffer_length= 4;
+ param->store_param_func= store_param_float;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ param->length= &param->buffer_length;
+ param->buffer_length= 8;
+ param->store_param_func= store_param_double;
+ break;
+ case MYSQL_TYPE_TIME:
+ /* Buffer length ignored for DATE, TIME and DATETIME */
+ param->store_param_func= store_param_time;
+ break;
+ case MYSQL_TYPE_DATE:
+ param->store_param_func= store_param_date;
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ param->store_param_func= store_param_datetime;
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ param->store_param_func= store_param_str;
+ break;
+ default:
+ sprintf(stmt->last_error,
+ ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ param->buffer_type, count);
+ DBUG_RETURN(1);
+ }
+ }
+ /* We have to send/resendtype information to MySQL */
+ stmt->send_types_to_server= 1;
+ stmt->param_buffers= 1;
+ DBUG_RETURN(0);
+}
+
+
+/********************************************************************
+ Long data implementation
+*********************************************************************/
+
+/*
+ Send long data in pieces to the server
+
+ SYNOPSIS
+ mysql_send_long_data()
+ stmt Statement handler
+ param_number Parameter number (0 - N-1)
+ data Data to send to server
+ length Length of data to send (may be 0)
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+
+my_bool STDCALL
+mysql_send_long_data(MYSQL_STMT *stmt, uint param_number,
+ const char *data, ulong length)
+{
+ MYSQL_BIND *param;
+ DBUG_ENTER("mysql_send_long_data");
+ DBUG_ASSERT(stmt != 0);
+ DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
+ param_number, data, length));
+
+ if (param_number >= stmt->param_count)
+ {
+ set_stmt_error(stmt, CR_INVALID_PARAMETER_NO);
+ DBUG_RETURN(1);
+ }
+ param= stmt->params+param_number;
+ if (param->buffer_type < MYSQL_TYPE_TINY_BLOB ||
+ param->buffer_type > MYSQL_TYPE_STRING)
+ {
+ /*
+ Long data handling should be used only for string/binary
+ types only
+ */
+ sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE),
+ param->param_number);
+ DBUG_RETURN(1);
+ }
+ /* Mark for execute that the result is already sent */
+ param->long_data_used= 1;
+ if (length)
+ {
+ MYSQL *mysql= stmt->mysql;
+ char *packet, extra_data[MYSQL_LONG_DATA_HEADER];
+
+ packet= extra_data;
+ int4store(packet, stmt->stmt_id); packet+=4;
+ int2store(packet, param_number); packet+=2;
+
+ /*
+ Note that we don't get any ok packet from the server in this case
+ This is intentional to save bandwidth.
+ */
+ if (advanced_command(mysql, COM_LONG_DATA, extra_data,
+ MYSQL_LONG_DATA_HEADER, data, length, 1))
+ {
+ set_stmt_errmsg(stmt,(char *) mysql->net.last_error,
+ mysql->net.last_errno);
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+/********************************************************************
+ Fetch-bind related implementations
+*********************************************************************/
+
+/****************************************************************************
+ Functions to fetch data to application buffers
+
+ All functions has the following characteristics:
+
+ SYNOPSIS
+ fetch_result_xxx()
+ param MySQL bind param
+ row Row value
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Can't alloc net->buffer)
+****************************************************************************/
+
+static void set_zero_time(MYSQL_TIME *tm)
+{
+ tm->year= tm->month= tm->day= 0;
+ tm->hour= tm->minute= tm->second= 0;
+ tm->second_part= 0;
+ tm->neg= (bool)0;
+}
+
+/* Read TIME from binary packet and return it to MYSQL_TIME */
+static uint read_binary_time(MYSQL_TIME *tm, uchar **pos)
+{
+ uchar *to;
+ uint length;
+
+ if (!(length= net_field_length(pos)))
+ {
+ set_zero_time(tm);
+ return 0;
+ }
+
+ to= *pos;
+ tm->second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
+
+ tm->day= (ulong) sint4korr(to+1);
+ tm->hour= (uint) to[5];
+ tm->minute= (uint) to[6];
+ tm->second= (uint) to[7];
+
+ tm->year= tm->month= 0;
+ tm->neg= (bool)to[0];
+ return length;
+}
+
+/* Read DATETIME from binary packet and return it to MYSQL_TIME */
+static uint read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
+{
+ uchar *to;
+ uint length;
+
+ if (!(length= net_field_length(pos)))
+ {
+ set_zero_time(tm);
+ return 0;
+ }
+
+ to= *pos;
+ tm->second_part= (length > 7 ) ? (ulong) sint4korr(to+7): 0;
+
+ if (length > 4)
+ {
+ tm->hour= (uint) to[4];
+ tm->minute= (uint) to[5];
+ tm->second= (uint) to[6];
+ }
+ else
+ tm->hour= tm->minute= tm->second= 0;
+
+ tm->year= (uint) sint2korr(to);
+ tm->month= (uint) to[2];
+ tm->day= (uint) to[3];
+ tm->neg= 0;
+ return length;
+}
+
+/* Read DATE from binary packet and return it to MYSQL_TIME */
+static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
+{
+ uchar *to;
+ uint length;
+
+ if (!(length= net_field_length(pos)))
+ {
+ set_zero_time(tm);
+ return 0;
+ }
+
+ to= *pos;
+ tm->year = (uint) sint2korr(to);
+ tm->month= (uint) to[2];
+ tm->day= (uint) to[3];
+
+ tm->hour= tm->minute= tm->second= 0;
+ tm->second_part= 0;
+ tm->neg= 0;
+ return length;
+}
+
+/* Convert Numeric to buffer types */
+static void send_data_long(MYSQL_BIND *param, longlong value)
+{
+ char *buffer= param->buffer;
+
+ switch(param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ *param->buffer= (uchar) value;
+ break;
+ case MYSQL_TYPE_SHORT:
+ int2store(buffer, value);
+ break;
+ case MYSQL_TYPE_LONG:
+ int4store(buffer, value);
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ int8store(buffer, value);
+ break;
+ case MYSQL_TYPE_FLOAT:
+ {
+ float data= (float)value;
+ float4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double data= (double)value;
+ float8store(buffer, data);
+ break;
+ }
+ default:
+ {
+ uint length= (uint)(longlong10_to_str(value,buffer,10)-buffer);
+ *param->length= length;
+ buffer[length]='\0';
+ }
+ }
+}
+
+
+/* Convert Double to buffer types */
+static void send_data_double(MYSQL_BIND *param, double value)
+{
+ char *buffer= param->buffer;
+
+ switch(param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ *buffer= (uchar)value;
+ break;
+ case MYSQL_TYPE_SHORT:
+ int2store(buffer, (short)value);
+ break;
+ case MYSQL_TYPE_LONG:
+ int4store(buffer, (long)value);
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ int8store(buffer, (longlong)value);
+ break;
+ case MYSQL_TYPE_FLOAT:
+ {
+ float data= (float)value;
+ float4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double data= (double)value;
+ float8store(buffer, data);
+ break;
+ }
+ default:
+ {
+ uint length= my_sprintf(buffer,(buffer,"%g",value));
+ *param->length= length;
+ buffer[length]='\0';
+ }
+ }
+}
+
+/* Convert string to buffer types */
+static void send_data_str(MYSQL_BIND *param, char *value, uint length)
+{
+ char *buffer= param->buffer;
+ int err=0;
+
+ switch(param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ {
+ uchar data= (uchar)my_strntol(system_charset_info,value,length,10,NULL,
+ &err);
+ *buffer= data;
+ break;
+ }
+ case MYSQL_TYPE_SHORT:
+ {
+ short data= (short)my_strntol(system_charset_info,value,length,10,NULL,
+ &err);
+ int2store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_LONG:
+ {
+ int32 data= (int32)my_strntol(system_charset_info,value,length,10,NULL,
+ &err);
+ int4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong data= my_strntoll(system_charset_info,value,length,10,NULL,&err);
+ int8store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_FLOAT:
+ {
+ float data = (float)my_strntod(system_charset_info,value,length,NULL,&err);
+ float4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double data= my_strntod(system_charset_info,value,length,NULL,&err);
+ float8store(buffer, data);
+ break;
+ }
+ default:
+ *param->length= length;
+ length= min(length, param->buffer_length);
+ memcpy(buffer, value, length);
+ if (length != param->buffer_length)
+ buffer[length]='\0';
+ }
+}
+
+static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
+ uint length)
+{
+ switch (param->buffer_type) {
+
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
+
+ tm->year= ltime.year;
+ tm->month= ltime.month;
+ tm->day= ltime.day;
+
+ tm->hour= ltime.hour;
+ tm->minute= ltime.minute;
+ tm->second= ltime.second;
+
+ tm->second_part= ltime.second_part;
+ tm->neg= ltime.neg;
+ break;
+ }
+ default:
+ {
+ char buff[25];
+
+ if (!length)
+ ltime.time_type= MYSQL_TIMESTAMP_NONE;
+ switch (ltime.time_type) {
+ case MYSQL_TIMESTAMP_DATE:
+ length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year,
+ ltime.month,ltime.day));
+ break;
+ case MYSQL_TIMESTAMP_FULL:
+ length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
+ ltime.year,ltime.month,ltime.day,
+ ltime.hour,ltime.minute,ltime.second));
+ break;
+ case MYSQL_TIMESTAMP_TIME:
+ length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
+ ltime.hour,ltime.minute,ltime.second));
+ break;
+ default:
+ length= 0;
+ buff[0]='\0';
+ }
+ send_data_str(param, (char *)buff, length);
+ }
+ }
+}
+
+
+
+/* Fetch data to buffers */
+static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
+ my_bool field_is_unsigned)
+{
+ ulong length;
+
+ switch (field_type) {
+ case MYSQL_TYPE_TINY:
+ {
+ char value= (char) **row;
+ longlong data= (field_is_unsigned) ? (longlong) (unsigned char) value:
+ (longlong) value;
+ send_data_long(param,data);
+ length= 1;
+ break;
+ }
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ {
+ short value= sint2korr(*row);
+ longlong data= (field_is_unsigned) ? (longlong) (unsigned short) value:
+ (longlong) value;
+ send_data_long(param,data);
+ length= 2;
+ break;
+ }
+ case MYSQL_TYPE_LONG:
+ {
+ long value= sint4korr(*row);
+ longlong data= (field_is_unsigned) ? (longlong) (unsigned long) value:
+ (longlong) value;
+ send_data_long(param,data);
+ length= 4;
+ break;
+ }
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong value= (longlong)sint8korr(*row);
+ send_data_long(param,value);
+ length= 8;
+ break;
+ }
+ case MYSQL_TYPE_FLOAT:
+ {
+ float value;
+ float4get(value,*row);
+ send_data_double(param,value);
+ length= 4;
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double value;
+ float8get(value,*row);
+ send_data_double(param,value);
+ length= 8;
+ break;
+ }
+ case MYSQL_TYPE_DATE:
+ {
+ MYSQL_TIME tm;
+
+ length= read_binary_date(&tm,row);
+ tm.time_type= MYSQL_TIMESTAMP_DATE;
+ send_data_time(param, tm, length);
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ {
+ MYSQL_TIME tm;
+
+ length= read_binary_time(&tm, row);
+ tm.time_type= MYSQL_TIMESTAMP_TIME;
+ send_data_time(param, tm, length);
+ break;
+ }
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ MYSQL_TIME tm;
+
+ length= read_binary_datetime(&tm, row);
+ tm.time_type= MYSQL_TIMESTAMP_FULL;
+ send_data_time(param, tm, length);
+ break;
+ }
+ default:
+ length= net_field_length(row);
+ send_data_str(param,(char*) *row,length);
+ break;
+ }
+ *row+= length;
+}
+
+static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
+{
+ *param->buffer= (uchar) **row;
+ (*row)++;
+}
+
+static void fetch_result_short(MYSQL_BIND *param, uchar **row)
+{
+ short value = (short)sint2korr(*row);
+ int2store(param->buffer, value);
+ *row+= 2;
+}
+
+static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
+{
+ int32 value= (int32)sint4korr(*row);
+ int4store(param->buffer, value);
+ *row+= 4;
+}
+
+static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
+{
+ longlong value= (longlong)sint8korr(*row);
+ int8store(param->buffer, value);
+ *row+= 8;
+}
+
+static void fetch_result_float(MYSQL_BIND *param, uchar **row)
+{
+ float value;
+ float4get(value,*row);
+ float4store(param->buffer, value);
+ *row+= 4;
+}
+
+static void fetch_result_double(MYSQL_BIND *param, uchar **row)
+{
+ double value;
+ float8get(value,*row);
+ float8store(param->buffer, value);
+ *row+= 8;
+}
+
+static void fetch_result_time(MYSQL_BIND *param, uchar **row)
+{
+ MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
+ *row+= read_binary_time(tm, row);
+}
+
+static void fetch_result_date(MYSQL_BIND *param, uchar **row)
+{
+ MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
+ *row+= read_binary_date(tm, row);
+}
+
+static void fetch_result_datetime(MYSQL_BIND *param, uchar **row)
+{
+ MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
+ *row+= read_binary_datetime(tm, row);
+}
+
+static void fetch_result_str(MYSQL_BIND *param, uchar **row)
+{
+ ulong length= net_field_length(row);
+ ulong copy_length= min(length, param->buffer_length);
+ memcpy(param->buffer, (char *)*row, copy_length);
+ /* Add an end null if there is room in the buffer */
+ if (copy_length != param->buffer_length)
+ *(param->buffer+copy_length)= '\0';
+ *param->length= length; // return total length
+ *row+= length;
+}
+
+/*
+ Setup the bind buffers for resultset processing
+*/
+
+my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
+{
+ MYSQL_BIND *param, *end;
+ ulong bind_count;
+ uint param_count= 0;
+ DBUG_ENTER("mysql_bind_result");
+ DBUG_ASSERT(stmt != 0);
+
+#ifdef CHECK_EXTRA_ARGUMENTS
+ if (stmt->state == MY_ST_UNKNOWN)
+ {
+ set_stmt_error(stmt, CR_NO_PREPARE_STMT);
+ DBUG_RETURN(1);
+ }
+ if (!bind)
+ {
+ set_stmt_error(stmt, CR_NULL_POINTER);
+ DBUG_RETURN(1);
+ }
+#endif
+ if (!(bind_count= stmt->field_count) &&
+ !(bind_count= alloc_stmt_fields(stmt)))
+ DBUG_RETURN(0);
+
+ memcpy((char*) stmt->bind, (char*) bind,
+ sizeof(MYSQL_BIND)*bind_count);
+
+ for (param= stmt->bind, end= param+bind_count; param < end ; param++)
+ {
+ /*
+ Set param->is_null to point to a dummy variable if it's not set.
+ This is to make the excute code easier
+ */
+ if (!param->is_null)
+ param->is_null= &int_is_null_dummy;
+
+ if (!param->length)
+ param->length= &param_length_is_dummy;
+
+ param->param_number= param_count++;
+ /* Setup data copy functions for the different supported types */
+ switch (param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ param->fetch_result= fetch_result_tinyint;
+ *param->length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ param->fetch_result= fetch_result_short;
+ *param->length= 2;
+ break;
+ case MYSQL_TYPE_LONG:
+ param->fetch_result= fetch_result_int32;
+ *param->length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ param->fetch_result= fetch_result_int64;
+ *param->length= 8;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ param->fetch_result= fetch_result_float;
+ *param->length= 4;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ param->fetch_result= fetch_result_double;
+ *param->length= 8;
+ break;
+ case MYSQL_TYPE_TIME:
+ param->fetch_result= fetch_result_time;
+ *param->length= sizeof(MYSQL_TIME);
+ break;
+ case MYSQL_TYPE_DATE:
+ param->fetch_result= fetch_result_date;
+ *param->length= sizeof(MYSQL_TIME);
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ param->fetch_result= fetch_result_datetime;
+ *param->length= sizeof(MYSQL_TIME);
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ DBUG_ASSERT(param->buffer_length != 0);
+ param->fetch_result= fetch_result_str;
+ break;
+ default:
+ sprintf(stmt->last_error,
+ ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ param->buffer_type, param_count);
+ DBUG_RETURN(1);
+ }
+ }
+ stmt->res_buffers= 1;
+ DBUG_RETURN(0);
+}
+
+/*
+ Fetch row data to bind buffers
+*/
+
+static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
+{
+ MYSQL_BIND *bind, *end;
+ MYSQL_FIELD *field, *field_end;
+ uchar *null_ptr, bit;
+
+ if (!row || !stmt->res_buffers)
+ return 0;
+
+ null_ptr= row;
+ row+= (stmt->field_count+9)/8; /* skip null bits */
+ bit= 4; /* first 2 bits are reserved */
+
+ /* Copy complete row to application buffers */
+ for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count,
+ field= stmt->fields,
+ field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count;
+ bind < end && field < field_end;
+ bind++, field++)
+ {
+ if (*null_ptr & bit)
+ *bind->is_null= 1;
+ else
+ {
+ *bind->is_null= 0;
+ if (field->type == bind->buffer_type)
+ (*bind->fetch_result)(bind, &row);
+ else
+ {
+ my_bool field_is_unsigned= (field->flags & UNSIGNED_FLAG) ? 1: 0;
+ fetch_results(bind, field->type, &row, field_is_unsigned);
+ }
+ }
+ if (! ((bit<<=1) & 255))
+ {
+ bit= 1; /* To next byte */
+ null_ptr++;
+ }
+ }
+ return 0;
+}
+
+/*
+ Fetch and return row data to bound buffers, if any
+*/
+
+int STDCALL mysql_fetch(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ uchar *row;
+ DBUG_ENTER("mysql_fetch");
+
+ row= (uchar *)0;
+ if (stmt->result_buffered) /* buffered */
+ {
+ MYSQL_RES *res;
+
+ if (!(res= stmt->result) || !res->data_cursor)
+ goto no_data;
+
+ row= (uchar *)res->data_cursor->data;
+ res->data_cursor= res->data_cursor->next;
+ res->current_row= (MYSQL_ROW)row;
+ }
+ else /* un-buffered */
+ {
+ if (packet_error == net_safe_read(mysql))
+ {
+ set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
+ mysql->net.last_errno);
+ DBUG_RETURN(1);
+ }
+ if (mysql->net.read_pos[0] == 254)
+ {
+ mysql->status= MYSQL_STATUS_READY;
+ goto no_data;
+ }
+ row= mysql->net.read_pos+1;
+ }
+ DBUG_RETURN(stmt_fetch_row(stmt, row));
+
+no_data:
+ DBUG_PRINT("info", ("end of data"));
+ DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
+}
+
+/*
+ Read all rows of data from server (binary format)
+*/
+
+static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt)
+{
+ ulong pkt_len;
+ uchar *cp;
+ MYSQL *mysql= stmt->mysql;
+ MYSQL_DATA *result;
+ MYSQL_ROWS *cur, **prev_ptr;
+ NET *net = &mysql->net;
+ DBUG_ENTER("read_binary_rows");
+
+ mysql= mysql->last_used_con;
+ if ((pkt_len= net_safe_read(mysql)) == packet_error)
+ {
+ set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
+ mysql->net.last_errno);
+ DBUG_RETURN(0);
+ }
+ if (mysql->net.read_pos[0] == 254) /* end of data */
+ return 0;
+
+ if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ DBUG_RETURN(0);
+ }
+ init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
+ result->alloc.min_malloc= sizeof(MYSQL_ROWS);
+ prev_ptr= &result->data;
+ result->rows= 0;
+
+ while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
+ {
+ result->rows++;
+
+ if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,sizeof(MYSQL_ROWS))) ||
+ !(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len))))
+ {
+ free_rows(result);
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ DBUG_RETURN(0);
+ }
+ *prev_ptr= cur;
+ prev_ptr= &cur->next;
+ memcpy(cur->data, (char*)cp+1, pkt_len-1);
+
+ if ((pkt_len=net_safe_read(mysql)) == packet_error)
+ {
+ free_rows(result);
+ DBUG_RETURN(0);
+ }
+ }
+ *prev_ptr= 0;
+ if (pkt_len > 1)
+ {
+ mysql->warning_count= uint2korr(cp+1);
+ DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
+ }
+ DBUG_PRINT("exit",("Got %d rows",result->rows));
+ DBUG_RETURN(result);
+}
+
+/*
+ Store or buffer the binary results to stmt
+*/
+
+int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ MYSQL_RES *result;
+ DBUG_ENTER("mysql_stmt_store_result");
+
+ mysql= mysql->last_used_con;
+
+ if (!stmt->field_count)
+ DBUG_RETURN(0);
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC);
+ DBUG_RETURN(1);
+ }
+ mysql->status= MYSQL_STATUS_READY; /* server is ready */
+ if (!(result= (MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
+ sizeof(ulong) *
+ stmt->field_count),
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY);
+ DBUG_RETURN(1);
+ }
+ stmt->result_buffered= 1;
+ if (!(result->data= read_binary_rows(stmt)))
+ {
+ my_free((gptr) result,MYF(0));
+ DBUG_RETURN(0);
+ }
+ mysql->affected_rows= result->row_count= result->data->rows;
+ result->data_cursor= result->data->data;
+ result->fields= stmt->fields;
+ result->field_count= stmt->field_count;
+ stmt->result= result;
+ DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_fetch() */
+}
+
+
+/********************************************************************
+ Misc function implementations
+*********************************************************************/
+
+/*
+ Close the statement handle by freeing all alloced resources
+
+ SYNOPSIS
+ mysql_stmt_close()
+ stmt Statement handle
+ skip_list Flag to indicate delete from list or not
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
+{
+ MYSQL *mysql;
+ my_bool error= 0;
+ DBUG_ENTER("mysql_stmt_close");
+
+ DBUG_ASSERT(stmt != 0);
+
+ mysql= stmt->mysql;
+ if (mysql->status != MYSQL_STATUS_READY)
+ {
+ /* Clear the current execution status */
+ DBUG_PRINT("warning",("Not all packets read, clearing them"));
+ for (;;)
+ {
+ ulong pkt_len;
+ if ((pkt_len= net_safe_read(mysql)) == packet_error)
+ break;
+ if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ break;
+ }
+ mysql->status= MYSQL_STATUS_READY;
+ }
+ if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE)
+ {
+ char buff[4];
+ int4store(buff, stmt->stmt_id);
+ error= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1);
+ }
+ if (!error)
+ {
+ mysql_free_result(stmt->result);
+ free_root(&stmt->mem_root, MYF(0));
+ if (!skip_list)
+ mysql->stmts= list_delete(mysql->stmts, &stmt->list);
+ mysql->status= MYSQL_STATUS_READY;
+ my_free((gptr) stmt, MYF(MY_WME));
+ }
+ DBUG_RETURN(error);
+}
+
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
+{
+ return stmt_close(stmt, 0);
+}
+
+/*
+ Return statement error code
+*/
+
+uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
+{
+ DBUG_ENTER("mysql_stmt_errno");
+ DBUG_RETURN(stmt->last_errno);
+}
+
+/*
+ Return statement error message
+*/
+
+const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
+{
+ DBUG_ENTER("mysql_stmt_error");
+ DBUG_RETURN(stmt->last_error);
+}
+
+/*
+ Commit the current transaction
+*/
+
+my_bool STDCALL mysql_commit(MYSQL * mysql)
+{
+ DBUG_ENTER("mysql_commit");
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
+}
+
+/*
+ Rollback the current transaction
+*/
+
+my_bool STDCALL mysql_rollback(MYSQL * mysql)
+{
+ DBUG_ENTER("mysql_rollback");
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
+}
+
+
+/*
+ Set autocommit to either true or false
+*/
+
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
+{
+ DBUG_ENTER("mysql_autocommit");
+ DBUG_PRINT("enter", ("mode : %d", auto_mode));
+
+ if (auto_mode) /* set to true */
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16));
+}
+
+
+/********************************************************************
+ Multi query execution related implementations
+*********************************************************************/
+
+/*
+ Returns if there are any more query results exists to be read using
+ mysql_next_result()
+*/
+
+my_bool STDCALL mysql_more_results(MYSQL *mysql)
+{
+ if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)
+ return 1;
+ return 0;
+}
+
+/*
+ Reads and returns the next query results
+*/
+
+my_bool STDCALL mysql_next_result(MYSQL *mysql)
+{
+
+ mysql->net.last_error[0]=0;
+ mysql->net.last_errno=0;
+ mysql->affected_rows= ~(my_ulonglong) 0;
+
+ if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)
+ return mysql_read_query_result(mysql);
+ return 0;
+}
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 7f4edb445e1..e0e7ca48f48 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -1,6 +1,6 @@
LIBRARY LIBMYSQL
-DESCRIPTION 'MySQL 4.0 Client Library'
-VERSION 5.0
+DESCRIPTION 'MySQL 4.1 Client Library'
+VERSION 6.0
EXPORTS
mysql_affected_rows
mysql_close
@@ -59,7 +59,6 @@ EXPORTS
list_add
list_delete
max_allowed_packet
- my_casecmp
my_init
my_end
my_strdup
@@ -107,10 +106,24 @@ EXPORTS
my_print_variables
getopt_ull_limit_value
getopt_compare_strings
-
-
-
-
+ mysql_warning_count
+ mysql_prepare
+ mysql_execute
+ mysql_param_count
+ mysql_bind_param
+ mysql_bind_result
+ mysql_prepare_result
+ mysql_stmt_close
+ mysql_stmt_error
+ mysql_stmt_errno
+ mysql_fetch
+ mysql_send_long_data
+ mysql_next_result
+ mysql_commit
+ mysql_rollback
+ mysql_autocommit
+
+
diff --git a/libmysql/manager.c b/libmysql/manager.c
index d4bd8d5520b..1354b98d1c9 100644
--- a/libmysql/manager.c
+++ b/libmysql/manager.c
@@ -142,7 +142,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
}
sock_addr.sin_port = (ushort) htons((ushort) port);
if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
- 0) <0)
+ 0))
{
con->last_errno=errno;
sprintf(con->last_error ,"Could not connect to %-.64s", host);
diff --git a/libmysql/password.c b/libmysql/password.c
index 1c2c5589215..e69de29bb2d 100644..100755
--- a/libmysql/password.c
+++ b/libmysql/password.c
@@ -1,191 +0,0 @@
-/* Copyright (C) 2000 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU 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 */
-
-/* password checking routines */
-/*****************************************************************************
- The main idea is that no password are sent between client & server on
- connection and that no password are saved in mysql in a decodable form.
-
- On connection a random string is generated and sent to the client.
- The client generates a new string with a random generator inited with
- the hash values from the password and the sent string.
- This 'check' string is sent to the server where it is compared with
- a string generated from the stored hash_value of the password and the
- random string.
-
- The password is saved (in user.password) by using the PASSWORD() function in
- mysql.
-
- Example:
- update user set password=PASSWORD("hello") where user="test"
- This saves a hashed number as a string in the password field.
-*****************************************************************************/
-
-#include <my_global.h>
-#include <my_sys.h>
-#include <m_string.h>
-#include "mysql.h"
-
-
-void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
-{ /* For mysql 3.21.# */
-#ifdef HAVE_purify
- bzero((char*) rand_st,sizeof(*rand_st)); /* Avoid UMC varnings */
-#endif
- rand_st->max_value= 0x3FFFFFFFL;
- rand_st->max_value_dbl=(double) rand_st->max_value;
- rand_st->seed1=seed1%rand_st->max_value ;
- rand_st->seed2=seed2%rand_st->max_value;
-}
-
-static void old_randominit(struct rand_struct *rand_st,ulong seed1)
-{ /* For mysql 3.20.# */
- rand_st->max_value= 0x01FFFFFFL;
- rand_st->max_value_dbl=(double) rand_st->max_value;
- seed1%=rand_st->max_value;
- rand_st->seed1=seed1 ; rand_st->seed2=seed1/2;
-}
-
-double rnd(struct rand_struct *rand_st)
-{
- rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
- rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
- return (((double) rand_st->seed1)/rand_st->max_value_dbl);
-}
-
-void hash_password(ulong *result, const char *password)
-{
- register ulong nr=1345345333L, add=7, nr2=0x12345671L;
- ulong tmp;
- for (; *password ; password++)
- {
- if (*password == ' ' || *password == '\t')
- continue; /* skipp space in password */
- tmp= (ulong) (uchar) *password;
- nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
- nr2+=(nr2 << 8) ^ nr;
- add+=tmp;
- }
- result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
- result[1]=nr2 & (((ulong) 1L << 31) -1L);
- return;
-}
-
-void make_scrambled_password(char *to,const char *password)
-{
- ulong hash_res[2];
- hash_password(hash_res,password);
- sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
-}
-
-static inline unsigned int char_val(char X)
-{
- return (uint) (X >= '0' && X <= '9' ? X-'0' :
- X >= 'A' && X <= 'Z' ? X-'A'+10 :
- X-'a'+10);
-}
-
-/*
-** This code assumes that len(password) is divideable with 8 and that
-** res is big enough (2 in mysql)
-*/
-
-void get_salt_from_password(ulong *res,const char *password)
-{
- res[0]=res[1]=0;
- if (password)
- {
- while (*password)
- {
- ulong val=0;
- uint i;
- for (i=0 ; i < 8 ; i++)
- val=(val << 4)+char_val(*password++);
- *res++=val;
- }
- }
- return;
-}
-
-void make_password_from_salt(char *to, ulong *hash_res)
-{
- sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
-}
-
-
-/*
- * Genererate a new message based on message and password
- * The same thing is done in client and server and the results are checked.
- */
-
-char *scramble(char *to,const char *message,const char *password,
- my_bool old_ver)
-{
- struct rand_struct rand_st;
- ulong hash_pass[2],hash_message[2];
- if (password && password[0])
- {
- char *to_start=to;
- hash_password(hash_pass,password);
- hash_password(hash_message,message);
- if (old_ver)
- old_randominit(&rand_st,hash_pass[0] ^ hash_message[0]);
- else
- randominit(&rand_st,hash_pass[0] ^ hash_message[0],
- hash_pass[1] ^ hash_message[1]);
- while (*message++)
- *to++= (char) (floor(rnd(&rand_st)*31)+64);
- if (!old_ver)
- { /* Make it harder to break */
- char extra=(char) (floor(rnd(&rand_st)*31));
- while (to_start != to)
- *(to_start++)^=extra;
- }
- }
- *to=0;
- return to;
-}
-
-
-my_bool check_scramble(const char *scrambled, const char *message,
- ulong *hash_pass, my_bool old_ver)
-{
- struct rand_struct rand_st;
- ulong hash_message[2];
- char buff[16],*to,extra; /* Big enough for check */
- const char *pos;
-
- hash_password(hash_message,message);
- if (old_ver)
- old_randominit(&rand_st,hash_pass[0] ^ hash_message[0]);
- else
- randominit(&rand_st,hash_pass[0] ^ hash_message[0],
- hash_pass[1] ^ hash_message[1]);
- to=buff;
- for (pos=scrambled ; *pos ; pos++)
- *to++=(char) (floor(rnd(&rand_st)*31)+64);
- if (old_ver)
- extra=0;
- else
- extra=(char) (floor(rnd(&rand_st)*31));
- to=buff;
- while (*scrambled)
- {
- if (*scrambled++ != (char) (*to++ ^ extra))
- return 1; /* Wrong password */
- }
- return 0;
-}
diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am
index e01fc7634a1..265e31fafdb 100644
--- a/libmysql_r/Makefile.am
+++ b/libmysql_r/Makefile.am
@@ -21,8 +21,7 @@ target = libmysqlclient_r.la
target_defs = -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@
## LIBS = @LIBS@
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include \
- -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes)
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include $(openssl_includes)
## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include
include $(top_srcdir)/libmysql/Makefile.shared
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 7bd9127a7f0..daf65cb2f80 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -25,9 +25,8 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\""
-INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(srcdir)/../include \
- -I../include -I$(srcdir)/.. -I$(top_srcdir) -I.. \
- -I../sql -I../regex
+INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/sql -I$(top_srcdir)/regex
noinst_LIBRARIES = libmysqld_int.a
pkglib_LIBRARIES = libmysqld.a
@@ -43,17 +42,20 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
hostname.cc init.cc \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
- item_uniq.cc key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
- mini_client.cc net_pkg.cc net_serv.cc opt_ft.cc opt_range.cc \
+ item_uniq.cc item_subselect.cc item_row.cc\
+ key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
+ mini_client.cc protocol.cc net_serv.cc opt_ft.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
- sql_crypt.cc sql_db.cc sql_delete.cc sql_insert.cc sql_lex.cc \
- sql_list.cc sql_manager.cc sql_map.cc set_var.cc sql_parse.cc \
- sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.cc \
+ sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
+ sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \
+ sql_prepare.cc sql_derived.cc sql_rename.cc sql_repl.cc \
+ sql_select.cc sql_do.cc sql_show.cc set_var.cc \
sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
- unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc
+ unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
+ spatial.cc gstream.cc sql_help.cc
EXTRA_DIST = lib_vio.c
diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h
index e17b72e84d8..abbebec2aaa 100644
--- a/libmysqld/embedded_priv.h
+++ b/libmysqld/embedded_priv.h
@@ -23,9 +23,9 @@
#include <my_pthread.h>
C_MODE_START
-extern void start_embedded_connection(NET * net);
-extern void end_embedded_connection(NET * net);
extern void lib_connection_phase(NET *net, int phase);
-extern bool lib_dispatch_command(enum enum_server_command command, NET *net,
- const char *arg, ulong length);
+extern void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
+extern void *create_embedded_thd(int client_flag, char *db);
+extern my_bool simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ ulong length, my_bool skipp_check);
C_MODE_END
diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am
index 2b52b133133..69ff8f535fd 100644
--- a/libmysqld/examples/Makefile.am
+++ b/libmysqld/examples/Makefile.am
@@ -11,7 +11,7 @@ DEFS = -DEMBEDDED_LIBRARY
INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir) \
-I$(top_srcdir) -I$(top_srcdir)/client $(openssl_includes)
LIBS = @LIBS@
-LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS)
+LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @bdb_libs_with_path@ @LIBDL@ $(CXXLDFLAGS)
mysqltest_SOURCES = mysqltest.c
diff --git a/libmysqld/examples/builder-sample/emb_sample.tds b/libmysqld/examples/builder-sample/emb_sample.tds
deleted file mode 100644
index 2471b6c112f..00000000000
--- a/libmysqld/examples/builder-sample/emb_sample.tds
+++ /dev/null
Binary files differ
diff --git a/libmysqld/examples/builder-sample/libmysqld.lib b/libmysqld/examples/builder-sample/libmysqld.lib
deleted file mode 100644
index 994e67e675e..00000000000
--- a/libmysqld/examples/builder-sample/libmysqld.lib
+++ /dev/null
Binary files differ
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index fad596d30b9..a1fbaaae631 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -23,6 +23,11 @@
#define mysql_unix_port mysql_inix_port1
#define mysql_port mysql_port1
+static int fake_argc= 1;
+static char *fake_argv[]= {(char *)"", 0};
+static const char *fake_groups[] = { "server", "embedded", 0 };
+static char inited, org_my_init_done;
+
#if defined (__WIN__)
#include "../sql/mysqld.cpp"
#else
@@ -31,7 +36,8 @@
#define SCRAMBLE_LENGTH 8
C_MODE_START
-#include "lib_vio.c"
+#include <mysql.h>
+#include "errmsg.h"
static int check_connections1(THD * thd);
static int check_connections2(THD * thd);
@@ -41,224 +47,57 @@ static bool check_user(THD *thd, enum_server_command command,
char * get_mysql_home(){ return mysql_home;};
char * get_mysql_real_data_home(){ return mysql_real_data_home;};
-bool lib_dispatch_command(enum enum_server_command command, NET *net,
- const char *arg, ulong length)
+my_bool simple_command(MYSQL *mysql,enum enum_server_command command,
+ const char *arg,
+ ulong length, my_bool skipp_check)
{
- THD *thd=(THD *) net->vio->dest_thd;
- thd->store_globals(); // Fix if more than one connect
- thd->net.last_error[0]=0; // Clear error message
- thd->net.last_errno=0;
-
- net_new_transaction(&thd->net);
- return dispatch_command(command, thd, (char *) arg, length + 1);
-}
-
+ my_bool result= 1;
+ THD *thd=(THD *) mysql->thd;
-void lib_connection_phase(NET * net, int phase)
-{
- THD * thd;
- thd = (THD *)(net->vio->dest_thd);
- if (thd)
+ /* Check that we are calling the client functions in right order */
+ if (mysql->status != MYSQL_STATUS_READY)
{
- switch (phase)
- {
- case 2:
- check_connections2(thd);
- break;
- }
- }
-}
-C_MODE_END
-
-
-void start_embedded_conn1(NET * net)
-{
- THD * thd = new THD;
- my_net_init(&thd->net,NULL);
- /* if (protocol_version>9) */
- thd->net.return_errno=1;
- thd->thread_id = thread_id++;
-
- Vio * v = net->vio;
- if (!v)
- {
- v = vio_new(0,VIO_CLOSED,0);
- net->vio = v;
- }
- if (v)
- {
- v -> dest_thd = thd;
- }
- thd->net.vio = v;
- if (thd->store_globals())
- {
- fprintf(stderr,"store_globals failed.\n");
- return;
+ strmov(thd->net.last_error,
+ ER(thd->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ return 1;
}
- thd->mysys_var=my_thread_var;
- thd->dbug_thread_id=my_thread_id();
- thd->thread_stack= (char*) &thd;
+ /* Clear result variables */
+ thd->clear_error();
+ mysql->affected_rows= ~(my_ulonglong) 0;
- if (thd->variables.max_join_size == (ulong) HA_POS_ERROR)
- thd->options |= OPTION_BIG_SELECTS;
+ thd->store_globals(); // Fix if more than one connect
+ result= dispatch_command(command, thd, (char *) arg, length + 1);
- thd->proc_info=0; // Remove 'login'
- thd->command=COM_SLEEP;
- thd->version=refresh_version;
- thd->set_time();
- bzero(thd->scramble, sizeof(thd->scramble));
- init_sql_alloc(&thd->mem_root,8192,8192);
+ if (!skipp_check)
+ result= thd->net.last_errno ? -1 : 0;
- check_connections1(thd);
+ mysql->last_error= thd->net.last_error;
+ mysql->last_errno= thd->net.last_errno;
+ return result;
}
+C_MODE_END
-
-
-static int
-check_connections1(THD *thd)
-{
- uint connect_errors=0;
- NET *net= &thd->net;
- /*
- ** store the connection details
- */
- DBUG_PRINT("info", (("check_connections called by thread %d"),
- thd->thread_id));
- DBUG_PRINT("general",("New connection received on %s",
- vio_description(net->vio)));
- if (!thd->host) // If TCP/IP connection
- {
- thd->host=(char*) localhost;
- }
- else /* Hostname given means that the connection was on a socket */
- {
- DBUG_PRINT("general",("Host: %s",thd->host));
- thd->ip=0;
- bzero((char*) &thd->remote,sizeof(struct sockaddr));
- }
- //vio_keepalive(net->vio, TRUE);
-
- /* nasty, but any other way? */
- uint pkt_len = 0;
-
- char buff[80],*end;
- int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
- CLIENT_TRANSACTIONS;
- LINT_INIT(pkt_len);
-
- end=strmov(buff,server_version)+1;
- int4store((uchar*) end,thd->thread_id);
- end+=4;
- memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
- end+=SCRAMBLE_LENGTH +1;
- int2store(end,client_flags);
- end[2]=MY_CHARSET_CURRENT;
-
-#define MIN_HANDSHAKE_SIZE 6
-
- int2store(end+3,thd->server_status);
- bzero(end+5,13);
- end+=18;
- if (net_write_command(net,protocol_version, buff,
- (uint) (end-buff)))
- {
- inc_host_errors(&thd->remote.sin_addr);
- return(ER_HANDSHAKE_ERROR);
- }
- return 0;
-}
-
-static int
-check_connections2(THD * thd)
+void THD::clear_error()
{
- uint connect_errors=0;
- uint pkt_len = 0;
- NET * net = &thd -> net;
- if (protocol_version>9) net -> return_errno=1;
-
- if ( (pkt_len=my_net_read(net)) == packet_error ||
- pkt_len < MIN_HANDSHAKE_SIZE)
- {
- inc_host_errors(&thd->remote.sin_addr);
- return(ER_HANDSHAKE_ERROR);
- }
-
-#ifdef _CUSTOMCONFIG_
-#include "_cust_sql_parse.h"
-#endif
- if (connect_errors)
- reset_host_errors(&thd->remote.sin_addr);
- if (thd->packet.alloc(thd->variables.net_buffer_length))
- return(ER_OUT_OF_RESOURCES);
-
- thd->client_capabilities=uint2korr(net->read_pos);
-
- thd->max_client_packet_length=uint3korr(net->read_pos+2);
- char *user= (char*) net->read_pos+5;
- char *passwd= strend(user)+1;
- char *db=0;
- if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
- return ER_HANDSHAKE_ERROR;
- if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
- db=strend(passwd)+1;
- if (thd->client_capabilities & CLIENT_TRANSACTIONS)
- thd->net.return_status= &thd->server_status;
- net->read_timeout=thd->variables.net_read_timeout;
- if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
- return (-1);
- thd->password=test(passwd[0]);
- return 0;
+ net.last_error[0]= 0;
+ net.last_errno= 0;
+ net.report_error= 0;
}
static bool check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count)
{
- NET *net= &thd->net;
- USER_RESOURCES ur;
thd->db=0;
if (!(thd->user = my_strdup(user, MYF(0))))
{
- send_error(net,ER_OUT_OF_RESOURCES);
+ send_error(thd,ER_OUT_OF_RESOURCES);
return 1;
}
- thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
- passwd, thd->scramble, &thd->priv_user,
- protocol_version == 9 ||
- !(thd->client_capabilities &
- CLIENT_LONG_PASSWORD),&ur);
- DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
- thd->client_capabilities, thd->max_client_packet_length,
- thd->host_or_ip, thd->priv_user,
- passwd[0] ? "yes": "no",
- thd->master_access, thd->db ? thd->db : "*none*"));
- if (thd->master_access & NO_ACCESS)
- {
- net_printf(net, ER_ACCESS_DENIED_ERROR,
- thd->user,
- thd->host_or_ip,
- passwd[0] ? ER(ER_YES) : ER(ER_NO));
- mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
- thd->user,
- thd->host_or_ip,
- passwd[0] ? ER(ER_YES) : ER(ER_NO));
- return(1); // Error already given
- }
- if (check_count)
- {
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- bool tmp=(thread_count - delayed_insert_threads >= max_connections &&
- !(thd->master_access & PROCESS_ACL));
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- if (tmp)
- { // Too many connections
- send_error(net, ER_CON_COUNT_ERROR);
- return(1);
- }
- }
+ thd->master_access= ~0L; // No user checking
+ thd->priv_user= thd->user;
mysql_log.write(thd,command,
(thd->priv_user == thd->user ?
(char*) "%s@%s on %s" :
@@ -270,7 +109,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
if (db && db[0])
return test(mysql_change_db(thd,db));
else
- send_ok(net); // Ready to handle questions
+ send_ok(thd); // Ready to handle questions
return 0; // ok
}
@@ -305,7 +144,6 @@ char **copy_arguments(int argc, char **argv)
extern "C"
{
-static my_bool inited, org_my_init_done;
ulong max_allowed_packet, net_buffer_length;
char ** copy_arguments_ptr= 0;
@@ -322,19 +160,17 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
const char *fake_groups[] = { "server", "embedded", 0 };
if (argc)
{
- argcp = &argc;
- argvp = (char***) &argv;
+ argcp= &argc;
+ argvp= (char***) &argv;
}
else
{
- argcp = &fake_argc;
- argvp = (char ***) &fake_argv;
+ argcp= &fake_argc;
+ argvp= (char ***) &fake_argv;
}
if (!groups)
- groups = (char**) fake_groups;
+ groups= (char**) fake_groups;
- my_umask=0660; // Default umask for new files
- my_umask_dir=0700; // Default umask for new directories
/* Only call MY_INIT() if it hasn't been called before */
if (!inited)
@@ -347,43 +183,12 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads
}
- /*
- Make a copy of the arguments to guard against applications that
- may change or move the initial arguments.
- */
- if (argvp == &argv)
- if (!(copy_arguments_ptr= argv= copy_arguments(argc, argv)))
- return 1;
-
- tzset(); // Set tzname
-
- start_time=time((time_t*) 0);
-#ifdef HAVE_TZNAME
-#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
- {
- struct tm tm_tmp;
- localtime_r(&start_time,&tm_tmp);
- strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
- }
-#else
+ if (init_common_variables("my", argc, argv, (const char **)groups))
{
- struct tm *start_tm;
- start_tm=localtime(&start_time);
- strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
+ mysql_server_end();
+ return 1;
}
-#endif
-#endif
-
- if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
- strmov(glob_hostname,"mysql");
-#ifndef DBUG_OFF
- strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
-#else
- strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
-#endif
- load_defaults("my", (const char **) groups, argcp, argvp);
- defaults_argv=*argvp;
-
+
/* Get default temporary directory */
opt_mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
#if defined( __WIN__) || defined(OS2)
@@ -395,161 +200,29 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0])
opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
- set_options();
- get_options(*argcp, *argvp);
-
- if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
- strcat(server_version,"-log");
- DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
- server_version, SYSTEM_TYPE,MACHINE_TYPE));
-
- /* These must be set early */
-
- (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
- (void) pthread_cond_init(&COND_thread_count,NULL);
- (void) pthread_cond_init(&COND_refresh,NULL);
- (void) pthread_cond_init(&COND_thread_cache,NULL);
- (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
- (void) pthread_cond_init(&COND_manager,NULL);
- (void) pthread_cond_init(&COND_rpl_status, NULL);
-
- if (set_default_charset_by_name(sys_charset.value, MYF(MY_WME)))
+ if (init_thread_environment())
{
mysql_server_end();
return 1;
}
- charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));
-
- /* Parameter for threads created for connections */
- (void) pthread_attr_init(&connection_attrib);
- (void) pthread_attr_setdetachstate(&connection_attrib,
- PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&connection_attrib,thread_stack);
- pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
-#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
- /* connections and databases needs lots of files */
- {
- uint wanted_files=10+(uint) max(max_connections*5,
- max_connections+table_cache_size*2);
- set_if_bigger(wanted_files, open_files_limit);
- // Note that some system returns 0 if we succeed here:
- uint files=set_maximum_open_files(wanted_files);
- if (files && files < wanted_files && ! open_files_limit)
- {
- max_connections= (ulong) min((files-10),max_connections);
- table_cache_size= (ulong) max((files-10-max_connections)/2,64);
- DBUG_PRINT("warning",
- ("Changed limits: max_connections: %ld table_cache: %ld",
- max_connections,table_cache_size));
- sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size);
- }
- }
-#endif
- unireg_init(opt_specialflag); /* Set up extern variabels */
- init_errmessage(); /* Read error messages from file */
- lex_init();
- item_init();
- set_var_init();
- mysys_uses_curses=0;
-#ifdef USE_REGEX
- regex_init();
-#endif
- if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
+ umask(((~my_umask) & 0666));
+ if (init_server_components())
{
mysql_server_end();
return 1;
}
- /*
- We have enough space for fiddling with the argv, continue
- */
- umask(((~my_umask) & 0666));
- table_cache_init();
- hostname_cache_init();
- query_cache_result_size_limit(query_cache_limit);
- query_cache_resize(query_cache_size);
- randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
- reset_floating_point_exceptions();
- init_thr_lock();
- init_slave_list();
-
- /* Setup log files */
- if (opt_log)
- open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
- LOG_NORMAL);
- if (opt_update_log)
- {
- open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
- NullS, LOG_NEW);
- using_update_log=1;
- }
-
- if (opt_slow_log)
- open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
- NullS, LOG_NORMAL);
- if (ha_init())
- {
- sql_print_error("Can't init databases");
- exit(1);
- }
- ha_key_cache();
-#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
- if (locked_in_memory && !geteuid())
- {
- if (mlockall(MCL_CURRENT))
- {
- sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
- }
- else
- locked_in_memory=1;
- }
-#else
- locked_in_memory=0;
-#endif
-
- if (opt_myisam_log)
- (void) mi_log( 1 );
- ft_init_stopwords();
-
- /*
- init signals & alarm
- After this we can't quit by a simple unireg_abort
- */
error_handler_hook = my_message_sql;
- if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
- pthread_key_create(&THR_MALLOC,NULL))
- {
- sql_print_error("Can't create thread-keys");
- exit(1);
- }
+
opt_noacl = 1; // No permissions
- if (acl_init((THD*) 0,opt_noacl))
+ if (acl_init((THD *)0, opt_noacl))
{
mysql_server_end();
return 1;
}
if (!opt_noacl)
- (void) grant_init((THD*) 0);
+ (void) grant_init((THD *)0);
init_max_user_conn();
init_update_queries();
@@ -599,7 +272,6 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
return 0;
}
-
void STDCALL mysql_server_end()
{
my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR));
@@ -630,16 +302,218 @@ void STDCALL mysql_thread_end()
my_thread_end();
#endif
}
+} /* extern "C" */
-void start_embedded_connection(NET * net)
+C_MODE_START
+void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db)
{
- start_embedded_conn1(net);
+ THD *thd = (THD *)mysql->thd;
+ thd->mysql= mysql;
+ mysql->last_error= thd->net.last_error;
}
-void end_embedded_connection(NET * net)
+void *create_embedded_thd(int client_flag, char *db)
{
- THD *thd = (THD *) net->vio->dest_thd;
- delete thd;
+ THD * thd= new THD;
+ thd->thread_id= thread_id++;
+
+ if (thd->store_globals())
+ {
+ fprintf(stderr,"store_globals failed.\n");
+ return NULL;
+ }
+
+ thd->mysys_var= my_thread_var;
+ thd->dbug_thread_id= my_thread_id();
+ thd->thread_stack= (char*) &thd;
+
+ thd->proc_info=0; // Remove 'login'
+ thd->command=COM_SLEEP;
+ thd->version=refresh_version;
+ thd->set_time();
+ init_sql_alloc(&thd->mem_root,8192,8192);
+ thd->client_capabilities= client_flag;
+
+ thd->db= db;
+ thd->db_length= db ? strip_sp(db) : 0;
+ thd->db_access= DB_ACLS;
+ thd->master_access= ~NO_ACCESS;
+ thd->net.query_cache_query= 0;
+
+ return thd;
}
-} /* extern "C" */
+C_MODE_END
+
+bool Protocol::send_fields(List<Item> *list, uint flag)
+{
+ List_iterator_fast<Item> it(*list);
+ Item *item;
+ MYSQL_FIELD *field, *client_field;
+ MYSQL *mysql= thd->mysql;
+
+ DBUG_ENTER("send_fields");
+
+ field_count= list->elements;
+ if (!(mysql->result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+
+ sizeof(ulong) * (field_count + 1),
+ MYF(MY_WME | MY_ZEROFILL))))
+ goto err;
+ mysql->result->lengths= (ulong *)(mysql->result + 1);
+
+ mysql->field_count=field_count;
+ alloc= &mysql->field_alloc;
+ field= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count);
+ if (!field)
+ goto err;
+
+ client_field= field;
+ while ((item= it++))
+ {
+ Send_field server_field;
+ item->make_field(&server_field);
+
+ client_field->table= strdup_root(alloc, server_field.table_name);
+ client_field->name= strdup_root(alloc,server_field.col_name);
+ client_field->length= server_field.length;
+ client_field->type= server_field.type;
+ client_field->flags= server_field.flags;
+ client_field->decimals= server_field.decimals;
+
+ if (INTERNAL_NUM_FIELD(client_field))
+ client_field->flags|= NUM_FLAG;
+
+ if (flag & 2)
+ {
+ char buff[80];
+ String tmp(buff, sizeof(buff), default_charset_info), *res;
+
+ if (!(res=item->val_str(&tmp)))
+ client_field->def= strdup_root(alloc, "");
+ else
+ client_field->def= strdup_root(alloc, tmp.ptr());
+ }
+ else
+ client_field->def=0;
+ client_field->max_length= 0;
+ ++client_field;
+ }
+ mysql->result->fields = field;
+
+ if (!(mysql->result->data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
+ MYF(MY_WME | MY_ZEROFILL))))
+ goto err;
+
+ init_alloc_root(&mysql->result->data->alloc,8192,0); /* Assume rowlength < 8192 */
+ mysql->result->data->alloc.min_malloc=sizeof(MYSQL_ROWS);
+ mysql->result->data->rows=0;
+ mysql->result->data->fields=field_count;
+ mysql->result->field_count=field_count;
+ mysql->result->data->prev_ptr= &mysql->result->data->data;
+
+ mysql->result->field_alloc= mysql->field_alloc;
+ mysql->result->current_field=0;
+ mysql->result->current_row=0;
+
+ DBUG_RETURN(prepare_for_send(list));
+ err:
+ send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
+}
+
+bool Protocol::send_records_num(List<Item> *list, ulonglong records)
+{
+ return false;
+}
+
+bool Protocol::write()
+{
+ *next_field= 0;
+ return false;
+}
+
+void
+send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
+{
+ DBUG_ENTER("send_ok");
+ MYSQL *mysql= current_thd->mysql;
+ mysql->affected_rows= affected_rows;
+ mysql->insert_id= id;
+ if (message)
+ {
+ strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1);
+ }
+ DBUG_VOID_RETURN;
+}
+
+void
+send_eof(THD *thd, bool no_flush)
+{
+}
+
+uint STDCALL mysql_warning_count(MYSQL *mysql)
+{
+ return ((THD *)mysql->thd)->total_warn_count;
+}
+
+void Protocol_simple::prepare_for_resend()
+{
+ MYSQL_ROWS *cur;
+ ulong len;
+ MYSQL_DATA *result= thd->mysql->result->data;
+
+ DBUG_ENTER("send_data");
+
+ alloc= &result->alloc;
+ result->rows++;
+ if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *))))
+ {
+ my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ DBUG_VOID_RETURN;
+ }
+ cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
+
+ *result->prev_ptr= cur;
+ result->prev_ptr= &cur->next;
+ next_field=cur->data;
+ next_mysql_field= thd->mysql->result->fields;
+
+ DBUG_VOID_RETURN;
+}
+
+bool Protocol_simple::store_null()
+{
+ *(next_field++)= NULL;
+ ++next_mysql_field;
+ return false;
+}
+
+bool Protocol::net_store_data(const char *from, uint length)
+{
+ if (!(*next_field=alloc_root(alloc, length + 1)))
+ return true;
+ memcpy(*next_field, from, length);
+ (*next_field)[length]= 0;
+ if (next_mysql_field->max_length < length)
+ next_mysql_field->max_length=length;
+ ++next_field;
+ ++next_mysql_field;
+
+ return false;
+}
+
+/* The same as Protocol::net_store_data but does the converstion
+*/
+bool Protocol::convert_str(const char *from, uint length)
+{
+ if (!(*next_field=alloc_root(alloc, length + 1)))
+ return true;
+ convert->store_dest(*next_field, from, length);
+ (*next_field)[length]= 0;
+ if (next_mysql_field->max_length < length)
+ next_mysql_field->max_length=length;
+ ++next_field;
+ ++next_mysql_field;
+
+ return false;
+}
diff --git a/libmysqld/lib_vio.c b/libmysqld/lib_vio.c
index 29a70b7acbb..e9f86cead80 100644
--- a/libmysqld/lib_vio.c
+++ b/libmysqld/lib_vio.c
@@ -20,6 +20,7 @@
we are working on. In this case we should just return read errors from
the file descriptior.
*/
+#ifdef DUMMY
#include <my_global.h>
#include "mysql_embed.h"
@@ -42,14 +43,7 @@
struct st_vio
{
- my_socket sd; /* my_socket - real or imaginary */
- HANDLE hPipe;
- my_bool localhost; /* Are we from localhost? */
- int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
- struct sockaddr_in local; /* Local internet address */
- struct sockaddr_in remote; /* Remote internet address */
enum enum_vio_type type; /* Type of connection */
- char desc[30]; /* String description */
void *dest_thd;
char *packets, **last_packet;
char *where_in_packet, *end_of_packet;
@@ -57,6 +51,7 @@ struct st_vio
MEM_ROOT root;
};
+
/* Initialize the communication buffer */
Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
@@ -69,6 +64,7 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
init_alloc_root(&vio->root, 8192, 8192);
vio->root.min_malloc = sizeof(char *) + 4;
vio->last_packet = &vio->packets;
+ vio->type = type;
}
DBUG_RETURN(vio);
}
@@ -219,4 +215,24 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
return 0;
}
+int create_vio(NET *net, int separate_thread)
+{
+ Vio * v = net->vio;
+ if (!v)
+ {
+ v = vio_new(0, separate_thread ? VIO_CLOSED : VIO_TYPE_TCPIP, 0);
+ net->vio = v;
+ }
+ return !v;
+}
+
+void set_thd(Vio *v, void *thd)
+{
+ if (v)
+ {
+ v -> dest_thd = thd;
+ }
+}
#endif /* HAVE_VIO */
+#endif /* DUMMY */
+
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 3f7c666cd30..4ec37e12325 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -49,8 +49,12 @@
static my_bool mysql_client_init=0;
uint mysql_port=0;
my_string mysql_unix_port=0;
+const char *sql_protocol_names_lib[] =
+{ "TCP", "SOCKET", "PIPE", "MEMORY",NullS };
+TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
+ sql_protocol_names_lib};
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS)
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41)
#if defined(MSDOS) || defined(__WIN__)
#define ERRNO WSAGetLastError()
@@ -63,14 +67,8 @@ my_string mysql_unix_port=0;
#endif
void STDCALL mysql_once_init(void);
-static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields,
- uint field_count);
-static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
- ulong *lengths);
static void end_server(MYSQL *mysql);
-static void read_user_name(char *name);
static void append_wild(char *to,char *end,const char *wild);
-static int send_file_to_server(MYSQL *mysql,const char *filename);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length);
@@ -78,130 +76,6 @@ static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
#define set_sigpipe(mysql)
#define reset_sigpipe(mysql)
-/*****************************************************************************
-** read a packet from server. Give error message if socket was down
-** or packet is an error message
-*****************************************************************************/
-
-ulong
-net_safe_read(MYSQL *mysql)
-{
- NET *net= &mysql->net;
- uint len=0;
- //init_sigpipe_variables
- /* Don't give sigpipe errors if the client doesn't want them */
- set_sigpipe(mysql);
- if (net->vio != 0)
- len=my_net_read(net);
- reset_sigpipe(mysql);
- if (len == packet_error || len == 0)
- {
- DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
- vio_description(net->vio),len));
- end_server(mysql);
- net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ?
- CR_NET_PACKET_TOO_LARGE:
- CR_SERVER_LOST);
- strmov(net->last_error,ER(net->last_errno));
- return(packet_error);
- }
- if (net->read_pos[0] == 255)
- {
-
- if (len > 3)
- {
- char *pos=(char*) net->read_pos+1;
- if (mysql->protocol_version > 9)
- { /* New client protocol */
- net->last_errno=uint2korr(pos);
- pos+=2;
- len-=2;
- }
- else
- {
- net->last_errno=CR_UNKNOWN_ERROR;
- len--;
- }
- (void) strmake(net->last_error,(char*) pos,
- min(len,sizeof(net->last_error)-1));
- }
- else
- {
- net->last_errno=CR_UNKNOWN_ERROR;
- (void) strmov(net->last_error,ER(net->last_errno));
- }
- DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno,
- net->last_error));
- return(packet_error);
- }
- return len;
-}
-
-
-/* Get the length of next field. Change parameter to point at fieldstart */
-static ulong
-net_field_length(uchar **packet)
-{
- reg1 uchar *pos= *packet;
- if (*pos < 251)
- {
- (*packet)++;
- return (ulong) *pos;
- }
- if (*pos == 251)
- {
- (*packet)++;
- return NULL_LENGTH;
- }
- if (*pos == 252)
- {
- (*packet)+=3;
- return (ulong) uint2korr(pos+1);
- }
- if (*pos == 253)
- {
- (*packet)+=4;
- return (ulong) uint3korr(pos+1);
- }
- (*packet)+=9; /* Must be 254 when here */
- return (ulong) uint4korr(pos+1);
-}
-
-/* Same as above, but returns ulonglong values */
-
-static my_ulonglong
-net_field_length_ll(uchar **packet)
-{
- reg1 uchar *pos= *packet;
- if (*pos < 251)
- {
- (*packet)++;
- return (my_ulonglong) *pos;
- }
- if (*pos == 251)
- {
- (*packet)++;
- return (my_ulonglong) NULL_LENGTH;
- }
- if (*pos == 252)
- {
- (*packet)+=3;
- return (my_ulonglong) uint2korr(pos+1);
- }
- if (*pos == 253)
- {
- (*packet)+=4;
- return (my_ulonglong) uint3korr(pos+1);
- }
- (*packet)+=9; /* Must be 254 when here */
-#ifdef NO_CLIENT_LONGLONG
- return (my_ulonglong) uint4korr(pos+1);
-#else
- return (my_ulonglong) uint8korr(pos+1);
-#endif
-}
-
-
static void free_rows(MYSQL_DATA *cur)
{
if (cur)
@@ -211,40 +85,6 @@ static void free_rows(MYSQL_DATA *cur)
}
}
-
-int
-simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
- ulong length, my_bool skipp_check)
-{
- NET *net= &mysql->net;
- int result= -1;
-
- /* Check that we are calling the client functions in right order */
- if (mysql->status != MYSQL_STATUS_READY)
- {
- strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
- goto end;
- }
-
- /* Clear result variables */
- mysql->net.last_error[0]=0;
- mysql->net.last_errno=0;
- mysql->info=0;
- mysql->affected_rows= ~(my_ulonglong) 0;
-
- /* Clear receive buffer and vio packet list */
- net_clear(net);
- vio_reset(net->vio);
-
- result = lib_dispatch_command(command, net, arg,length);
- if (!skipp_check)
- result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
- -1 : 0);
- end:
- return result;
-}
-
-
static void free_old_query(MYSQL *mysql)
{
DBUG_ENTER("free_old_query");
@@ -261,53 +101,6 @@ struct passwd *getpwuid(uid_t);
char* getlogin(void);
#endif
-#if !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__)
-static void read_user_name(char *name)
-{
- DBUG_ENTER("read_user_name");
- if (geteuid() == 0)
- (void) strmov(name,"root"); /* allow use of surun */
- else
- {
-#ifdef HAVE_GETPWUID
- struct passwd *skr;
- const char *str;
-/*#ifdef __cplusplus
- extern "C" struct passwd *getpwuid(uid_t);
- extern "C" { char* getlogin(void); }
-#else
- char * getlogin();
- struct passwd *getpwuid(uid_t);
-#endif
-*/
- if ((str=getlogin()) == NULL)
- {
- if ((skr=getpwuid(geteuid())) != NULL)
- str=skr->pw_name;
- else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
- !(str=getenv("LOGIN")))
- str="UNKNOWN_USER";
- }
- (void) strmake(name,str,USERNAME_LENGTH);
-#elif HAVE_CUSERID
- (void) cuserid(name);
-#else
- strmov(name,"UNKNOWN_USER");
-#endif
- }
- DBUG_VOID_RETURN;
-}
-
-#else /* If MSDOS || VMS */
-
-static void read_user_name(char *name)
-{
- char *str=getenv("USER");
- strmov(name,str ? str : "ODBC"); /* ODBC will send user variable */
-}
-
-#endif
-
#ifdef __WIN__
static my_bool is_NT(void)
{
@@ -386,17 +179,10 @@ static void
end_server(MYSQL *mysql)
{
DBUG_ENTER("end_server");
- if (mysql->net.vio != 0)
- {
- end_embedded_connection(&mysql->net);
- mysql->net.vio= 0; /* Marker */
- }
- net_end(&mysql->net);
free_old_query(mysql);
DBUG_VOID_RETURN;
}
-
void STDCALL
mysql_free_result(MYSQL_RES *result)
{
@@ -404,19 +190,6 @@ mysql_free_result(MYSQL_RES *result)
DBUG_PRINT("enter",("mysql_res: %lx",result));
if (result)
{
- if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
- {
- DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
- for (;;)
- {
- uint pkt_len;
- if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error)
- break;
- if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
- break; /* End of data */
- }
- result->handle->status=MYSQL_STATUS_READY;
- }
free_rows(result->data);
if (result->fields)
free_root(&result->field_alloc,MYF(0));
@@ -427,22 +200,46 @@ mysql_free_result(MYSQL_RES *result)
DBUG_VOID_RETURN;
}
-
/****************************************************************************
** Get options from my.cnf
****************************************************************************/
static const char *default_options[]=
-{"port","socket","compress","password","pipe", "timeout", "user",
- "init-command", "host", "database", "debug", "return-found-rows",
- "ssl_key" ,"ssl_cert" ,"ssl_ca" ,"ssl_capath",
- "character-set-dir", "default-character-set",
- NullS
+{
+ "port","socket","compress","password","pipe", "timeout", "user",
+ "init-command", "host", "database", "debug", "return-found-rows",
+ "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
+ "character-sets-dir", "default-character-set", "interactive-timeout",
+ "connect-timeout", "local-infile", "disable-local-infile",
+ "replication-probe", "enable-reads-from-master", "repl-parse-query",
+ "ssl-cipher","protocol", "shared_memory_base_name",
+ NullS
};
static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options};
+static int add_init_command(struct st_mysql_options *options, const char *cmd)
+{
+ char *tmp;
+
+ if (!options->init_commands)
+ {
+ options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
+ MYF(MY_WME));
+ init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
+ }
+
+ if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
+ insert_dynamic(options->init_commands, (gptr)&tmp))
+ {
+ my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
+ return 1;
+ }
+
+ return 0;
+}
+
static void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
{
@@ -471,6 +268,9 @@ static void mysql_read_default_options(struct st_mysql_options *options,
opt_arg=end+1;
*end=0; /* Remove '=' */
}
+ /* Change all '_' in variable name to '-' */
+ for (end= *option ; *(end= strcend(end,'_')) ; )
+ *end= '-';
switch (find_type(*option+2,&option_types,2)) {
case 1: /* port */
if (opt_arg)
@@ -494,8 +294,9 @@ static void mysql_read_default_options(struct st_mysql_options *options,
}
break;
case 5: /* pipe */
- options->named_pipe=1; /* Force named pipe */
+ options->protocol = MYSQL_PROTOCOL_PIPE;
break;
+ case 20: /* connect_timeout */
case 6: /* timeout */
if (opt_arg)
options->connect_timeout=atoi(opt_arg);
@@ -508,11 +309,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
}
break;
case 8: /* init-command */
- if (opt_arg)
- {
- my_free(options->init_command,MYF(MY_ALLOW_ZERO_PTR));
- options->init_command=my_strdup(opt_arg,MYF(MY_WME));
- }
+ add_init_command(options,opt_arg);
break;
case 9: /* host */
if (opt_arg)
@@ -538,6 +335,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
case 14:
case 15:
case 16:
+ case 26:
break;
case 17: /* charset-lib */
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
@@ -547,6 +345,15 @@ static void mysql_read_default_options(struct st_mysql_options *options,
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
break;
+ case 19: /* Interactive-timeout */
+ case 21: /* client_local_files */
+ case 22:
+ case 23: /* Replication options */
+ case 24:
+ case 25:
+ case 27: /* Protocol */
+ case 28: /* Shared memory */
+ break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -558,169 +365,6 @@ static void mysql_read_default_options(struct st_mysql_options *options,
}
-/***************************************************************************
-** Change field rows to field structs
-***************************************************************************/
-
-static MYSQL_FIELD *
-unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
- my_bool default_value, my_bool long_flag_protocol)
-{
- MYSQL_ROWS *row;
- MYSQL_FIELD *field,*result;
- DBUG_ENTER("unpack_fields");
-
- field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
- if (!result)
- DBUG_RETURN(0);
-
- for (row=data->data; row ; row = row->next,field++)
- {
- field->table= strdup_root(alloc,(char*) row->data[0]);
- field->name= strdup_root(alloc,(char*) row->data[1]);
- field->length= (uint) uint3korr(row->data[2]);
- field->type= (enum enum_field_types) (uchar) row->data[3][0];
- if (long_flag_protocol)
- {
- field->flags= uint2korr(row->data[4]);
- field->decimals=(uint) (uchar) row->data[4][2];
- }
- else
- {
- field->flags= (uint) (uchar) row->data[4][0];
- field->decimals=(uint) (uchar) row->data[4][1];
- }
- if (INTERNAL_NUM_FIELD(field))
- field->flags|= NUM_FLAG;
- if (default_value && row->data[5])
- field->def=strdup_root(alloc,(char*) row->data[5]);
- else
- field->def=0;
- field->max_length= 0;
- }
- free_rows(data); /* Free old data */
- DBUG_RETURN(result);
-}
-
-
-/* Read all rows (fields or data) from server */
-
-static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- uint fields)
-{
- uint field,pkt_len;
- ulong len;
- uchar *cp;
- char *to;
- MYSQL_DATA *result;
- MYSQL_ROWS **prev_ptr,*cur;
- NET *net = &mysql->net;
- DBUG_ENTER("read_rows");
-
- if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
- DBUG_RETURN(0);
- if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
- MYF(MY_WME | MY_ZEROFILL))))
- {
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->last_error,ER(net->last_errno));
- DBUG_RETURN(0);
- }
- init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
- result->alloc.min_malloc=sizeof(MYSQL_ROWS);
- prev_ptr= &result->data;
- result->rows=0;
- result->fields=fields;
-
- while (*(cp=net->read_pos) != 254 || pkt_len != 1)
- {
- result->rows++;
- if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
- sizeof(MYSQL_ROWS))) ||
- !(cur->data= ((MYSQL_ROW)
- alloc_root(&result->alloc,
- (fields+1)*sizeof(char *)+pkt_len))))
- {
- free_rows(result);
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->last_error,ER(net->last_errno));
- DBUG_RETURN(0);
- }
- *prev_ptr=cur;
- prev_ptr= &cur->next;
- to= (char*) (cur->data+fields+1);
- for (field=0 ; field < fields ; field++)
- {
- if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
- { /* null field */
- cur->data[field] = 0;
- }
- else
- {
- cur->data[field] = to;
- memcpy(to,(char*) cp,len); to[len]=0;
- to+=len+1;
- cp+=len;
- if (mysql_fields)
- {
- if (mysql_fields[field].max_length < len)
- mysql_fields[field].max_length=len;
- }
- }
- }
- cur->data[field]=to; /* End of last field */
- if ((pkt_len=net_safe_read(mysql)) == packet_error)
- {
- free_rows(result);
- DBUG_RETURN(0);
- }
- }
- *prev_ptr=0; /* last pointer is null */
- DBUG_PRINT("exit",("Got %d rows",result->rows));
- DBUG_RETURN(result);
-}
-
-
-/*
-** Read one row. Uses packet buffer as storage for fields.
-** When next packet is read, the previous field values are destroyed
-*/
-
-
-static int
-read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
-{
- uint field;
- ulong pkt_len,len;
- uchar *pos,*prev_pos;
-
- if ((pkt_len=net_safe_read(mysql)) == packet_error)
- return -1;
- if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
- return 1; /* End of data */
- prev_pos= 0; /* allowed to write at packet[-1] */
- pos=mysql->net.read_pos;
- for (field=0 ; field < fields ; field++)
- {
- if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
- { /* null field */
- row[field] = 0;
- *lengths++=0;
- }
- else
- {
- row[field] = (char*) pos;
- pos+=len;
- *lengths++=len;
- }
- if (prev_pos)
- *prev_pos=0; /* Terminate prev field */
- prev_pos=pos;
- }
- row[field]=(char*) prev_pos+1; /* End of last field */
- *prev_pos=0; /* Terminate last field */
- return 0;
-}
/****************************************************************************
** Init MySQL structure or allocate one
@@ -735,7 +379,6 @@ mysql_init(MYSQL *mysql)
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
return 0;
mysql->free_me=1;
- mysql->net.vio = 0;
}
else
bzero((char*) (mysql),sizeof(*(mysql)));
@@ -743,11 +386,12 @@ mysql_init(MYSQL *mysql)
}
-static void mysql_once_init()
+void STDCALL mysql_once_init()
{
if (!mysql_client_init)
{
mysql_client_init=1;
+
my_init(); /* Will init threads */
init_client_errs();
mysql_port = MYSQL_PORT;
@@ -781,100 +425,10 @@ mysql_connect(MYSQL *mysql,const char *host,
}
}
-
-/*
-** Note that the mysql argument must be initialized with mysql_init()
-** before calling mysql_real_connect !
-*/
-
-MYSQL * STDCALL
-mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
- const char *passwd, const char *db,
- uint port, const char *unix_socket,uint client_flag)
+static inline int mysql_init_charset(MYSQL *mysql)
{
- char buff[100],charset_name_buff[16],*end,*host_info, *charset_name;
- uint pkt_length;
- ulong max_allowed_packet;
- NET *net= &mysql->net;
- DBUG_ENTER("mysql_real_connect");
- DBUG_PRINT("enter",("host: %s db: %s user: %s",
- host ? host : "(Null)",
- db ? db : "(Null)",
- user ? user : "(Null)"));
-
- net->vio = 0; /* If something goes wrong */
- /* use default options */
- if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
- {
- mysql_read_default_options(&mysql->options,
- (mysql->options.my_cnf_file ?
- mysql->options.my_cnf_file : "my"),
- mysql->options.my_cnf_group);
- my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
- mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
- }
-
- /* Some empty-string-tests are done because of ODBC */
- if (!host || !host[0])
- host=mysql->options.host;
- if (!user || !user[0])
- user=mysql->options.user;
- if (!passwd)
- {
- passwd=mysql->options.password;
- }
- if (!db || !db[0])
- db=mysql->options.db;
- port=0;
- unix_socket=0;
- mysql->reconnect=1; /* Reconnect as default */
- mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
- host_info=(char*) ER(CR_EMBEDDED_CONNECTION);
- if (my_net_init(net, net->vio))
- {
- vio_delete(net->vio);
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->last_error,ER(net->last_errno));
- goto error;
- }
-
- /* Get version info */
- mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
- start_embedded_connection(net);
+ char charset_name_buff[16], *charset_name;
- if ((pkt_length=net_safe_read(mysql)) == packet_error)
- goto error;
-
- /* Check if version of protocoll matches current one */
-
- mysql->protocol_version= net->read_pos[0];
- DBUG_DUMP("packet",(char*) net->read_pos,10);
- DBUG_PRINT("info",("mysql protocol version %d, server=%d",
- PROTOCOL_VERSION, mysql->protocol_version));
- if (mysql->protocol_version != PROTOCOL_VERSION &&
- mysql->protocol_version != PROTOCOL_VERSION-1)
- {
- net->last_errno= CR_VERSION_ERROR;
- sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version,
- PROTOCOL_VERSION);
- goto error;
- }
- end=strend((char*) net->read_pos+1);
- mysql->thread_id=uint4korr(end+1);
- end+=5;
- strmake(mysql->scramble_buff,end,8);
- end+=9;
- if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
- mysql->server_capabilities=uint2korr(end);
- if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
- {
- /* New protocol with 16 bytes to describe server characteristics */
- mysql->server_language=end[2];
- mysql->server_status=uint2korr(end+3);
- }
-
- /* Set character set */
if ((charset_name=mysql->options.charset_name))
{
const char *save=charsets_dir;
@@ -895,97 +449,91 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (!mysql->charset)
{
- net->last_errno=CR_CANT_READ_CHARSET;
+ mysql->last_errno=CR_CANT_READ_CHARSET;
if (mysql->options.charset_dir)
- sprintf(net->last_error,ER(net->last_errno),
+ sprintf(mysql->last_error,ER(mysql->last_errno),
charset_name ? charset_name : "unknown",
mysql->options.charset_dir);
else
{
char cs_dir_name[FN_REFLEN];
get_charsets_dir(cs_dir_name);
- sprintf(net->last_error,ER(net->last_errno),
+ sprintf(mysql->last_error,ER(mysql->last_errno),
charset_name ? charset_name : "unknown",
cs_dir_name);
}
- goto error;
+ return mysql->last_errno;
}
+ return 0;
+}
+
+/*
+** Note that the mysql argument must be initialized with mysql_init()
+** before calling mysql_real_connect !
+*/
+
+MYSQL * STDCALL
+mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
+ const char *passwd __attribute__((unused)), const char *db,
+ uint port, const char *unix_socket,ulong client_flag)
+{
+ char *db_name;
+ DBUG_ENTER("mysql_real_connect");
+ DBUG_PRINT("enter",("host: %s db: %s user: %s",
+ host ? host : "(Null)",
+ db ? db : "(Null)",
+ user ? user : "(Null)"));
- /* Save connection information */
- if (!user) user="";
- if (!passwd) passwd="";
- host=LOCAL_HOST;
- if (!my_multi_malloc(MYF(0),
- &mysql->host_info, (uint) strlen(host_info)+1,
- &mysql->host, (uint) strlen(host)+1,
- &mysql->unix_socket,unix_socket ?
- (uint) strlen(unix_socket)+1 : (uint) 1,
- &mysql->server_version,
- (uint) (end - (char*) net->read_pos),
- NullS) ||
- !(mysql->user=my_strdup(user,MYF(0))) ||
- !(mysql->passwd=my_strdup(passwd,MYF(0))))
+ /* use default options */
+ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
{
- strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY));
- goto error;
+ mysql_read_default_options(&mysql->options,
+ (mysql->options.my_cnf_file ?
+ mysql->options.my_cnf_file : "my"),
+ mysql->options.my_cnf_group);
+ my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
}
- strmov(mysql->host_info,host_info);
- strmov(mysql->host,host);
- if (unix_socket)
- strmov(mysql->unix_socket,unix_socket);
- else
- mysql->unix_socket=0;
- strmov(mysql->server_version,(char*) net->read_pos+1);
- mysql->port=port;
- mysql->client_flag=client_flag | mysql->options.client_flag;
- DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d",
- mysql->server_version,mysql->server_capabilities,
- mysql->server_status));
+
+ if (!db || !db[0])
+ db=mysql->options.db;
+
+ port=0;
+ unix_socket=0;
+ db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL;
+
+ mysql->thd= create_embedded_thd(client_flag, db_name);
+
+ init_embedded_mysql(mysql, client_flag, db_name);
+
+ if (mysql_init_charset(mysql))
+ goto error;
/* Send client information for access check */
client_flag|=CLIENT_CAPABILITIES;
client_flag&= ~CLIENT_COMPRESS;
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
- int2store(buff,client_flag);
- mysql->client_flag=client_flag;
-
- max_allowed_packet=net->max_packet_size;
- int3store(buff+2,max_allowed_packet);
- if (user && user[0])
- strmake(buff+5,user,32);
- else
- read_user_name((char*) buff+5);
-#ifdef _CUSTOMCONFIG_
-#include "_cust_libmysql.h";
-#endif
- DBUG_PRINT("info",("user: %s",buff+5));
- end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
- if (db)
+ if (mysql->options.init_commands)
{
- end=strmov(end+1,db);
- mysql->db=my_strdup(db,MYF(MY_WME));
- db=0;
- }
- if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
- goto error;
-
- lib_connection_phase(net,2);
+ DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
+ char **ptr= (char**)init_commands->buffer;
+ char **end= ptr + init_commands->elements;
- if( net_safe_read(mysql) == packet_error)
- goto error;
- if (db && mysql_select_db(mysql,db))
- goto error;
- if (mysql->options.init_command)
- {
- my_bool reconnect=mysql->reconnect;
- mysql->reconnect=0;
- if (mysql_query(mysql,mysql->options.init_command))
- goto error;
- mysql_free_result(mysql_use_result(mysql));
- mysql->reconnect=reconnect;
+ for (; ptr<end; ptr++)
+ {
+ MYSQL_RES *res;
+ if (mysql_query(mysql,*ptr))
+ goto error;
+ if (mysql->fields)
+ {
+ if (!(res= mysql_use_result(mysql)))
+ goto error;
+ mysql_free_result(res);
+ }
+ }
}
DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
@@ -994,7 +542,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
error:
reset_sigpipe(mysql);
- DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error));
+ DBUG_PRINT("error",("message: %u (%s)",mysql->last_errno,mysql->last_error));
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;
@@ -1011,9 +559,10 @@ error:
** Change user and database
**************************************************************************/
-my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
- const char *passwd, const char *db)
+my_bool STDCALL mysql_change_user(MYSQL *mysql __attribute__((unused)), const char *user __attribute__((unused)),
+ const char *passwd __attribute__((unused)), const char *db __attribute__((unused)))
{
+#ifdef DUMMY
char buff[512],*pos=buff;
DBUG_ENTER("mysql_change_user");
@@ -1037,6 +586,8 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
mysql->passwd=my_strdup(passwd,MYF(MY_WME));
mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
DBUG_RETURN(0);
+#endif
+ return 0;
}
@@ -1053,8 +604,6 @@ mysql_select_db(MYSQL *mysql, const char *db)
if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0)))
DBUG_RETURN(error);
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
- mysql->db=my_strdup(db,MYF(MY_WME));
DBUG_RETURN(0);
}
@@ -1070,18 +619,6 @@ mysql_close(MYSQL *mysql)
DBUG_ENTER("mysql_close");
if (mysql) /* Some simple safety */
{
- if (mysql->net.vio != 0)
- {
- free_old_query(mysql);
- mysql->status=MYSQL_STATUS_READY; /* Force command */
- simple_command(mysql,COM_QUIT,"",0,1);
- end_server(mysql);
- }
- my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
@@ -1091,10 +628,18 @@ mysql_close(MYSQL *mysql)
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ if (mysql->options.init_commands)
+ {
+ DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
+ char **ptr= (char**)init_commands->buffer;
+ char **end= ptr + init_commands->elements;
+ for (; ptr<end; ptr++)
+ my_free(*ptr,MYF(MY_WME));
+ delete_dynamic(init_commands);
+ my_free((char*)init_commands,MYF(MY_WME));
+ }
/* Clear pointers for better safety */
- mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
bzero((char*) &mysql->options,sizeof(mysql->options));
- mysql->net.vio = 0;
#ifdef HAVE_OPENSSL
((VioConnectorFd*)(mysql->connector_fd))->delete();
mysql->connector_fd = 0;
@@ -1117,64 +662,24 @@ mysql_query(MYSQL *mysql, const char *query)
return mysql_real_query(mysql,query, (ulong) strlen(query));
}
-int STDCALL
-mysql_send_query(MYSQL* mysql, const char* query, ulong length)
-{
- return simple_command(mysql, COM_QUERY, query, length, 1);
-}
-
-
-int STDCALL
+my_bool STDCALL
mysql_read_query_result(MYSQL *mysql)
{
- uchar *pos;
- ulong field_count;
- MYSQL_DATA *fields;
- uint length;
- DBUG_ENTER("mysql_read_query_result");
+ if (mysql->last_errno)
+ return -1;
- if ((length=net_safe_read(mysql)) == packet_error)
- DBUG_RETURN(-1);
- free_old_query(mysql); /* Free old result */
-get_info:
- pos=(uchar*) mysql->net.read_pos;
- if ((field_count= net_field_length(&pos)) == 0)
+ if (mysql->field_count)
{
- mysql->affected_rows= net_field_length_ll(&pos);
- mysql->insert_id= net_field_length_ll(&pos);
- if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
- {
- mysql->server_status=uint2korr(pos); pos+=2;
- }
- if (pos < mysql->net.read_pos+length && net_field_length(&pos))
- mysql->info=(char*) pos;
- DBUG_RETURN(0);
- }
- if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
- {
- int error=send_file_to_server(mysql,(char*) pos);
- if ((length=net_safe_read(mysql)) == packet_error || error)
- DBUG_RETURN(-1);
- goto get_info; /* Get info packet */
+ mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->affected_rows= mysql->result->row_count= mysql->result->data->rows;
+ mysql->result->data_cursor= mysql->result->data->data;
}
- if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
- mysql->server_status|= SERVER_STATUS_IN_TRANS;
- mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
- if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
- DBUG_RETURN(-1);
- if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
- (uint) field_count,0,
- (my_bool) test(mysql->server_capabilities &
- CLIENT_LONG_FLAG))))
- DBUG_RETURN(-1);
- mysql->status=MYSQL_STATUS_GET_RESULT;
- mysql->field_count=field_count;
- DBUG_RETURN(0);
+ return 0;
}
/****************************************************************************
-* A modified version of connect(). connect2() allows you to specify
+* A modified version of connect(). my_connect() allows you to specify
* a timeout value, in seconds, that we should wait until we
* derermine we can't connect to a particular host. If timeout is 0,
* my_connect() will behave exactly like connect().
@@ -1182,11 +687,11 @@ get_info:
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
-int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
- uint timeout)
+my_bool my_connect(my_socket s, const struct sockaddr *name, uint namelen,
+ uint timeout)
{
#if defined(__WIN__) || defined(OS2)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
#else
int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
@@ -1199,7 +704,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/
if (timeout == 0)
- return connect(s, (struct sockaddr*) name, namelen);
+ return connect(s, (struct sockaddr*) name, namelen) != 0;
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK
@@ -1212,7 +717,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
if ((res != 0) && (s_err != EINPROGRESS))
{
errno = s_err; /* Restore it */
- return(-1);
+ return(1);
}
if (res == 0) /* Connected quickly! */
return(0);
@@ -1252,7 +757,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
now_time=time(NULL);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
- return -1;
+ return 1;
}
/* select() returned something more interesting than zero, let's
@@ -1262,17 +767,33 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
- return(-1);
+ return(1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
- return(-1); /* but return an error... */
+ return(1); /* but return an error... */
}
return(0); /* It's all good! */
#endif
}
+int STDCALL
+mysql_send_query(MYSQL* mysql, const char* query, ulong length)
+{
+ DBUG_ENTER("mysql_send_query");
+
+ if (mysql->options.separate_thread)
+ {
+ return -1;
+ }
+
+ mysql->result= NULL;
+
+ free_old_query(mysql); /* Free old result */
+
+ DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1));
+}
int STDCALL
mysql_real_query(MYSQL *mysql, const char *query, ulong length)
@@ -1280,114 +801,43 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length)
DBUG_ENTER("mysql_real_query");
DBUG_PRINT("enter",("handle: %lx",mysql));
DBUG_PRINT("query",("Query = \"%s\"",query));
- if (mysql_send_query(mysql, query, length))
- DBUG_RETURN(-1);
- DBUG_RETURN(mysql_read_query_result(mysql));
-}
-
-static int
-send_file_to_server(MYSQL *mysql, const char *filename)
-{
- int fd, readcount;
- char buf[IO_SIZE*15],*tmp_name;
- DBUG_ENTER("send_file_to_server");
-
- fn_format(buf,filename,"","",4); /* Convert to client format */
- if (!(tmp_name=my_strdup(buf,MYF(0))))
+ if (mysql->options.separate_thread)
{
- strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
- DBUG_RETURN(-1);
- }
- if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0)
- {
- mysql->net.last_errno=EE_FILENOTFOUND;
- sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
- strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
- my_net_write(&mysql->net,"",0); net_flush(&mysql->net);
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
+ return -1;
}
- while ((readcount = (int) my_read(fd,buf,sizeof(buf),MYF(0))) > 0)
- {
- if (my_net_write(&mysql->net,buf,readcount))
- {
- mysql->net.last_errno=CR_SERVER_LOST;
- strmov(mysql->net.last_error,ER(mysql->net.last_errno));
- DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file"));
- (void) my_close(fd,MYF(0));
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
- }
- }
- (void) my_close(fd,MYF(0));
- /* Send empty packet to mark end of file */
- if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net))
- {
- mysql->net.last_errno=CR_SERVER_LOST;
- sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno);
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
- }
- if (readcount < 0)
- {
- mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */
- sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
- strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
- my_free(tmp_name,MYF(0));
+ mysql->result= NULL;
+
+ free_old_query(mysql); /* Free old result */
+
+ if (simple_command(mysql, COM_QUERY, query, length, 1))
DBUG_RETURN(-1);
- }
- DBUG_RETURN(0);
-}
+ DBUG_RETURN(mysql_read_query_result(mysql));
+}
/**************************************************************************
** Alloc result struct for buffered results. All rows are read to buffer.
** mysql_data_seek may be used.
**************************************************************************/
-
MYSQL_RES * STDCALL
mysql_store_result(MYSQL *mysql)
{
- MYSQL_RES *result;
- DBUG_ENTER("mysql_store_result");
+ MYSQL_RES *result= mysql->result;
+ if (!result)
+ return 0;
- if (!mysql->fields)
- DBUG_RETURN(0);
- if (mysql->status != MYSQL_STATUS_GET_RESULT)
- {
- strmov(mysql->net.last_error,
- ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
- DBUG_RETURN(0);
- }
- mysql->status=MYSQL_STATUS_READY; /* server is ready */
- if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+
- sizeof(ulong)*mysql->field_count,
- MYF(MY_WME | MY_ZEROFILL))))
- {
- mysql->net.last_errno=CR_OUT_OF_MEMORY;
- strmov(mysql->net.last_error, ER(mysql->net.last_errno));
- DBUG_RETURN(0);
- }
- result->eof=1; /* Marker for buffered */
- result->lengths=(ulong*) (result+1);
- if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count)))
- {
- my_free((gptr) result,MYF(0));
- DBUG_RETURN(0);
- }
+ mysql->result= NULL;
+ *result->data->prev_ptr= 0;
+ result->eof= 1;
+ result->lengths= (ulong*)(result + 1);
mysql->affected_rows= result->row_count= result->data->rows;
- result->data_cursor= result->data->data;
- result->fields= mysql->fields;
- result->field_alloc= mysql->field_alloc;
- result->field_count= mysql->field_count;
- result->current_field=0;
- result->current_row=0; /* Must do a fetch first */
- mysql->fields=0; /* fields is now in result */
- DBUG_RETURN(result); /* Data fetched */
-}
+ result->data_cursor= result->data->data;
+ mysql->status=MYSQL_STATUS_READY; /* server is ready */
+ return result;
+}
/**************************************************************************
** Alloc struct for use with unbuffered reads. Data is fetched by domand
@@ -1402,40 +852,12 @@ mysql_store_result(MYSQL *mysql)
MYSQL_RES * STDCALL
mysql_use_result(MYSQL *mysql)
{
- MYSQL_RES *result;
DBUG_ENTER("mysql_use_result");
-
- if (!mysql->fields)
- DBUG_RETURN(0);
- if (mysql->status != MYSQL_STATUS_GET_RESULT)
- {
- strmov(mysql->net.last_error,
- ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ if (mysql->options.separate_thread)
DBUG_RETURN(0);
- }
- if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
- sizeof(ulong)*mysql->field_count,
- MYF(MY_WME | MY_ZEROFILL))))
- DBUG_RETURN(0);
- result->lengths=(ulong*) (result+1);
- if (!(result->row=(MYSQL_ROW)
- my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
- { /* Ptrs: to one row */
- my_free((gptr) result,MYF(0));
- DBUG_RETURN(0);
- }
- result->fields= mysql->fields;
- result->field_alloc= mysql->field_alloc;
- result->field_count= mysql->field_count;
- result->current_field=0;
- result->handle= mysql;
- result->current_row= 0;
- mysql->fields=0; /* fields is now in result */
- mysql->status=MYSQL_STATUS_USE_RESULT;
- DBUG_RETURN(result); /* Data is read to be fetched */
-}
-
+ DBUG_RETURN(mysql_store_result(mysql));
+}
/**************************************************************************
** Return next field of the query results
@@ -1458,24 +880,6 @@ MYSQL_ROW STDCALL
mysql_fetch_row(MYSQL_RES *res)
{
DBUG_ENTER("mysql_fetch_row");
- if (!res->data)
- { /* Unbufferred fetch */
- if (!res->eof)
- {
- if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths)))
- {
- res->row_count++;
- DBUG_RETURN(res->current_row=res->row);
- }
- else
- {
- DBUG_PRINT("info",("end of data"));
- res->eof=1;
- res->handle->status=MYSQL_STATUS_READY;
- }
- }
- DBUG_RETURN((MYSQL_ROW) NULL);
- }
{
MYSQL_ROW tmp;
if (!res->data_cursor)
@@ -1489,6 +893,7 @@ mysql_fetch_row(MYSQL_RES *res)
}
}
+
/**************************************************************************
** Get column lengths of the current row
** If one uses mysql_use_result, res->lengths contains the length information,
@@ -1498,28 +903,17 @@ mysql_fetch_row(MYSQL_RES *res)
ulong * STDCALL
mysql_fetch_lengths(MYSQL_RES *res)
{
- ulong *lengths,*prev_length;
- byte *start;
+ ulong *lengths;
MYSQL_ROW column,end;
if (!(column=res->current_row))
return 0; /* Something is wrong */
if (res->data)
{
- start=0;
- prev_length=0; /* Keep gcc happy */
lengths=res->lengths;
- for (end=column+res->field_count+1 ; column != end ; column++,lengths++)
+ for (end=column+res->field_count; column != end ; column++,lengths++)
{
- if (!*column)
- {
- *lengths=0; /* Null */
- continue;
- }
- if (start) /* Found end of prev string */
- *prev_length= (uint) (*column-start-1);
- start= *column;
- prev_length=lengths;
+ *lengths= *column ? strlen(*column) : 0;
}
}
return res->lengths;
@@ -1607,8 +1001,9 @@ mysql_list_tables(MYSQL *mysql, const char *wild)
**************************************************************************/
MYSQL_RES * STDCALL
-mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
+mysql_list_fields(MYSQL *mysql __attribute__((unused)), const char *table __attribute__((unused)), const char *wild __attribute__((unused)))
{
+#ifdef DUMMY
MYSQL_RES *result;
MYSQL_DATA *query;
char buff[257],*end;
@@ -1638,9 +1033,12 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
CLIENT_LONG_FLAG));
result->eof=1;
DBUG_RETURN(result);
+#endif
+ return 0;
}
/* List all running processes (threads) in server */
+#ifdef DUMMY
MYSQL_RES * STDCALL
mysql_list_processes(MYSQL *mysql)
@@ -1665,7 +1063,9 @@ mysql_list_processes(MYSQL *mysql)
mysql->status=MYSQL_STATUS_GET_RESULT;
mysql->field_count=field_count;
DBUG_RETURN(mysql_store_result(mysql));
+ return (MYSQL_RES*)mysql;
}
+#endif /*DUMMY*/
int STDCALL
@@ -1723,9 +1123,10 @@ mysql_dump_debug_info(MYSQL *mysql)
const char * STDCALL
mysql_stat(MYSQL *mysql)
{
+#ifdef DUMMY
DBUG_ENTER("mysql_stat");
if (simple_command(mysql,COM_STATISTICS,"",0,0))
- return mysql->net.last_error;
+ return mysql->last_error;
mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
if (!mysql->net.read_pos[0])
{
@@ -1734,6 +1135,8 @@ mysql_stat(MYSQL *mysql)
return mysql->net.last_error;
}
DBUG_RETURN((char*) mysql->net.read_pos);
+#endif
+ return (char *)mysql;
}
@@ -1746,23 +1149,29 @@ mysql_ping(MYSQL *mysql)
const char * STDCALL
-mysql_get_server_info(MYSQL *mysql)
+mysql_get_server_info(MYSQL *mysql __attribute__((unused)))
{
- return((char*) mysql->server_version);
+ return MYSQL_SERVER_VERSION;
}
+ulong STDCALL
+mysql_get_server_version(MYSQL *mysql __attribute__((unused)))
+{
+ return MYSQL_VERSION_ID;
+}
+
const char * STDCALL
-mysql_get_host_info(MYSQL *mysql)
+mysql_get_host_info(MYSQL *mysql __attribute__((unused)))
{
- return(mysql->host_info);
+ return "localhost";
}
uint STDCALL
-mysql_get_proto_info(MYSQL *mysql)
+mysql_get_proto_info(MYSQL *mysql __attribute__((unused)))
{
- return (mysql->protocol_version);
+ return PROTOCOL_VERSION;
}
const char * STDCALL
@@ -1784,12 +1193,20 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
case MYSQL_OPT_COMPRESS:
mysql->options.compress=1; /* Remember for connect */
break;
+ case MYSQL_OPT_USE_RESULT:
+ mysql->options.separate_thread=1; /* Use separate thread for query execution*/
+ break;
case MYSQL_OPT_NAMED_PIPE:
- mysql->options.named_pipe=1; /* Force named pipe */
+ mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
+ break;
+ case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
+ if (!arg || test(*(uint*) arg))
+ mysql->options.client_flag|= CLIENT_LOCAL_FILES;
+ else
+ mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
break;
case MYSQL_INIT_COMMAND:
- my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
- mysql->options.init_command=my_strdup(arg,MYF(MY_WME));
+ add_init_command(&mysql->options,arg);
break;
case MYSQL_READ_DEFAULT_FILE:
my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
@@ -1807,6 +1224,11 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
break;
+ case MYSQL_OPT_PROTOCOL:
+ mysql->options.protocol= *(uint*) arg;
+ break;
+ case MYSQL_SHARED_MEMORY_BASE_NAME:
+ break;
default:
DBUG_RETURN(-1);
}
@@ -1873,22 +1295,28 @@ my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
uint STDCALL mysql_errno(MYSQL *mysql)
{
- return (mysql)->net.last_errno;
+ return mysql->last_errno;
}
const char * STDCALL mysql_error(MYSQL *mysql)
{
- return (mysql)->net.last_error;
+ return mysql->last_error;
}
-const char *STDCALL mysql_info(MYSQL *mysql)
+const char *STDCALL mysql_info(MYSQL *mysql __attribute__((unused)))
{
+#ifdef DUMMY
return (mysql)->info;
+#endif
+ return 0;
}
-ulong STDCALL mysql_thread_id(MYSQL *mysql)
+ulong STDCALL mysql_thread_id(MYSQL *mysql __attribute__((unused)))
{
+#ifdef DUMMY
return (mysql)->thread_id;
+#endif
+ return 0;
}
const char * STDCALL mysql_character_set_name(MYSQL *mysql)
@@ -1906,6 +1334,17 @@ uint STDCALL mysql_thread_safe(void)
#endif
}
+MYSQL_RES *STDCALL mysql_warnings(MYSQL *mysql)
+{
+ uint warning_count;
+ DBUG_ENTER("mysql_warnings");
+ /* Save warning count as mysql_real_query may change this */
+ warning_count= mysql_warning_count(mysql);
+ if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
+ DBUG_RETURN(0);
+ DBUG_RETURN(mysql_store_result(mysql));
+}
+
/****************************************************************************
** Some support functions
****************************************************************************/
diff --git a/merge/Makefile.am b/merge/Makefile.am
index 78441e84fac..25e15e9c6ec 100644
--- a/merge/Makefile.am
+++ b/merge/Makefile.am
@@ -14,7 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
pkglib_LIBRARIES = libmerge.a
noinst_HEADERS = mrg_def.h
libmerge_a_SOURCES = mrg_open.c mrg_extra.c mrg_info.c mrg_locking.c \
diff --git a/myisam/.cvsignore b/myisam/.cvsignore
index d9adcedd308..ef6d92c6e18 100644
--- a/myisam/.cvsignore
+++ b/myisam/.cvsignore
@@ -7,6 +7,8 @@ ft_test1
mi_test1
mi_test2
mi_test3
+rt_test
+sp_test
myisamchk
myisamlog
myisampack
diff --git a/myisam/Makefile.am b/myisam/Makefile.am
index aeb3b34ee15..f8225868d96 100644
--- a/myisam/Makefile.am
+++ b/myisam/Makefile.am
@@ -17,7 +17,7 @@
EXTRA_DIST = mi_test_all.sh mi_test_all.res
pkgdata_DATA = mi_test_all mi_test_all.res
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
pkglib_LIBRARIES = libmyisam.a
@@ -25,14 +25,16 @@ bin_PROGRAMS = myisamchk myisamlog myisampack
myisamchk_DEPENDENCIES= $(LIBRARIES)
myisamlog_DEPENDENCIES= $(LIBRARIES)
myisampack_DEPENDENCIES=$(LIBRARIES)
-noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 ft_dump #ft_test1 ft_eval
-noinst_HEADERS = myisamdef.h fulltext.h ftdefs.h ft_test1.h ft_eval.h
+noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 rt_test sp_test ft_dump #ft_test1 ft_eval
+noinst_HEADERS = myisamdef.h rt_index.h rt_key.h rt_mbr.h sp_defs.h fulltext.h ftdefs.h ft_test1.h ft_eval.h
mi_test1_DEPENDENCIES= $(LIBRARIES)
mi_test2_DEPENDENCIES= $(LIBRARIES)
mi_test3_DEPENDENCIES= $(LIBRARIES)
#ft_test1_DEPENDENCIES= $(LIBRARIES)
#ft_eval_DEPENDENCIES= $(LIBRARIES)
ft_dump_DEPENDENCIES= $(LIBRARIES)
+rt_test_DEPENDENCIES= $(LIBRARIES)
+sp_test_DEPENDENCIES= $(LIBRARIES)
libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_rnext.c mi_rnext_same.c \
mi_search.c mi_page.c mi_key.c mi_locking.c \
@@ -46,8 +48,9 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_changed.c mi_static.c mi_delete_all.c \
mi_delete_table.c mi_rename.c mi_check.c \
ft_parser.c ft_stopwords.c ft_static.c \
- ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c
-CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all
+ ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \
+ rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
+CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all rt_test.MY? sp_test.MY?
DEFS = -DMAP_TO_USE_RAID
# Move to automake rules ?
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 97c55c1d937..6fa71348002 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -21,6 +21,7 @@
#define FT_CORE
#include "ftdefs.h"
#include <queues.h>
+#include <assert.h> /* for DBUG_ASSERT() */
/* search with boolean queries */
@@ -63,42 +64,44 @@ struct st_ftb_expr
{
FTB_EXPR *up;
byte *quot, *qend;
- float weight;
- uint flags;
my_off_t docid[2]; /* for index search and for scan */
+ float weight;
float cur_weight;
- int yesses; /* number of "yes" words matched */
- int nos; /* number of "no" words matched */
- int ythresh; /* number of "yes" words in expr */
- int yweaks; /* number of "yes" words for scan only */
+ uint flags;
+ uint yesses; /* number of "yes" words matched */
+ uint nos; /* number of "no" words matched */
+ uint ythresh; /* number of "yes" words in expr */
+ uint yweaks; /* number of "yes" words for scan only */
};
typedef struct st_ftb_word
{
- FTB_EXPR *up;
- float weight;
- uint flags;
- my_off_t docid[2]; /* for index search and for scan */
- uint ndepth;
- int len;
- /* ... docid cache can be added here. SerG */
- byte word[1];
+ FTB_EXPR *up;
+ MI_KEYDEF *keyinfo;
+ my_off_t docid[2]; /* for index search and for scan */
+ my_off_t key_root;
+ float weight;
+ uint ndepth;
+ uint flags;
+ uint len;
+ uchar off;
+ byte word[1];
} FTB_WORD;
typedef struct st_ft_info
{
struct _ft_vft *please;
MI_INFO *info;
- uint keynr;
CHARSET_INFO *charset;
- enum { UNINITIALIZED, READY, INDEX_SEARCH, INDEX_DONE /*, SCAN*/ } state;
- uint with_scan;
- my_off_t lastpos;
FTB_EXPR *root;
- QUEUE queue;
- TREE no_dupes;
FTB_WORD **list;
MEM_ROOT mem_root;
+ QUEUE queue;
+ TREE no_dupes;
+ my_off_t lastpos;
+ uint keynr;
+ uchar with_scan;
+ enum { UNINITIALIZED, READY, INDEX_SEARCH, INDEX_DONE } state;
} FTB;
static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b)
@@ -119,7 +122,7 @@ static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b)
static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b)
{
/* ORDER BY word DESC, ndepth DESC */
- int i=_mi_compare_text(cs, (uchar*) (*b)->word+1,(*b)->len-1,
+ int i= mi_compare_text(cs, (uchar*) (*b)->word+1,(*b)->len-1,
(uchar*) (*a)->word+1,(*a)->len-1,0);
if (!i)
i=CMP_NUM((*b)->ndepth,(*a)->ndepth);
@@ -160,6 +163,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
ftbw->up=up;
ftbw->docid[0]=ftbw->docid[1]=HA_POS_ERROR;
ftbw->ndepth= (param.yesno<0) + depth;
+ ftbw->key_root=HA_POS_ERROR;
memcpy(ftbw->word+1, w.pos, w.len);
ftbw->word[0]=w.len;
if (param.yesno > 0) up->ythresh++;
@@ -194,22 +198,97 @@ static int _ftb_no_dupes_cmp(void* not_used __attribute__((unused)),
return CMP_NUM((*((my_off_t*)a)), (*((my_off_t*)b)));
}
+/* returns 1 if the search was finished (must-word wasn't found) */
+static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
+{
+ int r;
+ uint off;
+ int subkeys;
+ MI_INFO *info=ftb->info;
+
+ if (init_search)
+ {
+ ftbw->key_root=info->s->state.key_root[ftb->keynr];
+ ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
+ ftbw->off=0;
+
+ r=_mi_search(info, ftbw->keyinfo, (uchar*) ftbw->word, ftbw->len,
+ SEARCH_FIND | SEARCH_BIGGER, ftbw->key_root);
+ }
+ else
+ {
+ r=_mi_search(info, ftbw->keyinfo, (uchar*) ftbw->word+ftbw->off,
+ USE_WHOLE_KEY, SEARCH_BIGGER, ftbw->key_root);
+ }
+ if (!r && !ftbw->off)
+ {
+ r= mi_compare_text(ftb->charset,
+ info->lastkey + (ftbw->flags & FTB_FLAG_TRUNC),
+ ftbw->len - (ftbw->flags & FTB_FLAG_TRUNC),
+ (uchar*) ftbw->word + (ftbw->flags & FTB_FLAG_TRUNC),
+ ftbw->len - (ftbw->flags & FTB_FLAG_TRUNC),
+ 0);
+ }
+
+ if (r) /* not found */
+ {
+ if (!ftbw->off || !(ftbw->flags & FTB_FLAG_TRUNC))
+ {
+ ftbw->docid[0]=HA_POS_ERROR;
+ if ((ftbw->flags & FTB_FLAG_YES) && ftbw->up->up==0)
+ {
+ /*
+ This word MUST BE present in every document returned,
+ so we can stop the search right now
+ */
+ ftb->state=INDEX_DONE;
+ return 1; /* search is done */
+ }
+ else
+ return 0;
+ }
+
+ /* going up to the first-level tree to continue search there */
+ _mi_dpointer(info, ftbw->word+ftbw->off+HA_FT_WLEN, ftbw->key_root);
+ ftbw->key_root=info->s->state.key_root[ftb->keynr];
+ ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
+ ftbw->off=0;
+ return _ft2_search(ftb, ftbw, 0);
+ }
+
+ /* matching key found */
+ memcpy(ftbw->word+ftbw->off, info->lastkey, info->lastkey_length);
+ if (!ftbw->off && (init_search || (ftbw->flags & FTB_FLAG_TRUNC)))
+ {
+ /* going down ? */
+ get_key_full_length_rdonly(off, info->lastkey);
+ subkeys=ft_sintXkorr(info->lastkey+off);
+ if (subkeys<0)
+ {
+ /* yep, going down, to the second-level tree */
+ /* TODO here: subkey-based optimization */
+ ftbw->off=off;
+ ftbw->key_root=info->lastpos;
+ ftbw->keyinfo=& info->s->ft2_keyinfo;
+ r=_mi_search_first(info, ftbw->keyinfo, ftbw->key_root);
+ DBUG_ASSERT(r==0); /* found something */
+ memcpy(ftbw->word+off, info->lastkey, info->lastkey_length);
+ }
+ }
+ ftbw->docid[0]=info->lastpos;
+ return 0;
+}
+
static void _ftb_init_index_search(FT_INFO *ftb)
{
- int i, r;
+ int i;
FTB_WORD *ftbw;
- MI_INFO *info=ftb->info;
- MI_KEYDEF *keyinfo;
- my_off_t keyroot;
if ((ftb->state != READY && ftb->state !=INDEX_DONE) ||
ftb->keynr == NO_SUCH_KEY)
return;
ftb->state=INDEX_SEARCH;
- keyinfo=info->s->keyinfo+ftb->keynr;
- keyroot=info->s->state.key_root[ftb->keynr];
-
for (i=ftb->queue.elements; i; i--)
{
ftbw=(FTB_WORD *)(ftb->queue.root[i]);
@@ -243,39 +322,14 @@ static void _ftb_init_index_search(FT_INFO *ftb)
{
if (!is_tree_inited(& ftb->no_dupes))
{
- init_tree(& ftb->no_dupes,0,0,sizeof(my_off_t),
- _ftb_no_dupes_cmp,0,0,0);
+ init_tree(&ftb->no_dupes,0,0,sizeof(my_off_t),
+ _ftb_no_dupes_cmp, 0, NULL, NULL);
}
}
}
- r=_mi_search(info, keyinfo, (uchar*) ftbw->word, ftbw->len,
- SEARCH_FIND | SEARCH_BIGGER, keyroot);
- if (!r)
- {
- r=_mi_compare_text(ftb->charset,
- info->lastkey + (ftbw->flags&FTB_FLAG_TRUNC),
- ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
- (uchar*) ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
- ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
- 0);
- }
- if (r) /* not found */
- {
- if (ftbw->flags&FTB_FLAG_YES && ftbw->up->up==0)
- {
- /*
- This word MUST BE present in every document returned,
- so we can abort the search right now
- */
- ftb->state=INDEX_DONE;
- return;
- }
- }
- else
- {
- memcpy(ftbw->word, info->lastkey, info->lastkey_length);
- ftbw->docid[0]=info->lastpos;
- }
+
+ if (_ft2_search(ftb, ftbw, 1))
+ return;
}
queue_fix(& ftb->queue);
}
@@ -381,7 +435,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
{
weight /= ftbe->ythresh;
ftbe->cur_weight += weight;
- if (++ftbe->yesses == ythresh)
+ if ((int) ++ftbe->yesses == ythresh)
{
yn=ftbe->flags;
weight=ftbe->cur_weight*ftbe->weight;
@@ -422,9 +476,9 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
if (ftbe->ythresh)
weight/=3;
ftbe->cur_weight += weight;
- if (ftbe->yesses < ythresh)
+ if ((int) ftbe->yesses < ythresh)
break;
- yn= (ftbe->yesses++ == ythresh) ? ftbe->flags : 0 ;
+ yn= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : 0 ;
weight*= ftbe->weight;
}
}
@@ -436,10 +490,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
FTB_EXPR *ftbe;
FTB_WORD *ftbw;
MI_INFO *info=ftb->info;
- MI_KEYDEF *keyinfo=info->s->keyinfo+ftb->keynr;
- my_off_t keyroot=info->s->state.key_root[ftb->keynr];
my_off_t curdoc;
- int r;
if (ftb->state != INDEX_SEARCH && ftb->state != INDEX_DONE)
return -1;
@@ -461,39 +512,12 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
(curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid[0]) !=
HA_POS_ERROR)
{
- while (curdoc==(ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
+ while (curdoc == (ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
{
_ftb_climb_the_tree(ftb, ftbw, 0);
/* update queue */
- r=_mi_search(info, keyinfo, (uchar*) ftbw->word, USE_WHOLE_KEY,
- SEARCH_BIGGER , keyroot);
- if (!r)
- {
- r=_mi_compare_text(ftb->charset,
- info->lastkey + (ftbw->flags&FTB_FLAG_TRUNC),
- ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
- (uchar*) ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
- ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
- 0);
- }
- if (r) /* not found */
- {
- ftbw->docid[0]=HA_POS_ERROR;
- if (ftbw->flags&FTB_FLAG_YES && ftbw->up->up==0)
- {
- /*
- This word MUST BE present in every document returned,
- so we can stop the search right now
- */
- ftb->state=INDEX_DONE;
- }
- }
- else
- {
- memcpy(ftbw->word, info->lastkey, info->lastkey_length);
- ftbw->docid[0]=info->lastpos;
- }
+ _ft2_search(ftb, ftbw, 0);
queue_replaced(& ftb->queue);
}
@@ -502,12 +526,14 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
ftbe->yesses>=(ftbe->ythresh-ftbe->yweaks) && !ftbe->nos)
{
/* curdoc matched ! */
- if (is_tree_inited(& ftb->no_dupes) &&
- tree_insert(& ftb->no_dupes, &curdoc, 0)->count >1)
- /* but it managed to get past this line once */
+ if (is_tree_inited(&ftb->no_dupes) &&
+ tree_insert(&ftb->no_dupes, &curdoc, 0,
+ ftb->no_dupes.custom_arg)->count >1)
+ /* but it managed already to get past this line once */
continue;
info->lastpos=curdoc;
+ /* Clear all states, except that the table was updated */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (!(*info->read_record)(info,curdoc,record))
@@ -576,9 +602,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
for (a=0, b=ftb->queue.elements, c=(a+b)/2; b-a>1; c=(a+b)/2)
{
ftbw=ftb->list[c];
- if (_mi_compare_text(ftb->charset, (uchar*) word.pos, word.len,
- (uchar*) ftbw->word+1, ftbw->len-1,
- (my_bool) (ftbw->flags&FTB_FLAG_TRUNC)) >0)
+ if (mi_compare_text(ftb->charset, (uchar*) word.pos, word.len,
+ (uchar*) ftbw->word+1, ftbw->len-1,
+ (my_bool) (ftbw->flags&FTB_FLAG_TRUNC)) >0)
b=c;
else
a=c;
@@ -586,9 +612,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
for (; c>=0; c--)
{
ftbw=ftb->list[c];
- if (_mi_compare_text(ftb->charset, (uchar*) word.pos, word.len,
- (uchar*) ftbw->word+1,ftbw->len-1,
- (my_bool) (ftbw->flags&FTB_FLAG_TRUNC)))
+ if (mi_compare_text(ftb->charset, (uchar*) word.pos, word.len,
+ (uchar*) ftbw->word+1,ftbw->len-1,
+ (my_bool) (ftbw->flags&FTB_FLAG_TRUNC)))
break;
if (ftbw->docid[1] == docid)
continue;
diff --git a/myisam/ft_dump.c b/myisam/ft_dump.c
index d95e719e234..fc3252273e9 100644
--- a/myisam/ft_dump.c
+++ b/myisam/ft_dump.c
@@ -56,9 +56,9 @@ static struct my_option my_long_options[] =
int main(int argc,char *argv[])
{
- int error=0;
+ int error=0, subkeys;
uint keylen, keylen2=0, inx, doc_cnt=0;
- float weight;
+ float weight= 1.0;
double gws, min_gws=0, avg_gws=0;
MI_INFO *info;
char buf[MAX_LEN], buf2[MAX_LEN], buf_maxlen[MAX_LEN], buf_min_gws[MAX_LEN];
@@ -125,13 +125,15 @@ int main(int argc,char *argv[])
keylen=*(info->lastkey);
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
- mi_float4get(weight,info->lastkey+keylen+1);
+ subkeys=mi_sint4korr(info->lastkey+keylen+1);
+ if (subkeys >= 0)
+ weight=*(float*)&subkeys;
#else
#error
#endif
snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
- casedn_str(buf);
+ my_casedn_str(default_charset_info,buf);
total++;
lengths[keylen]++;
@@ -164,9 +166,13 @@ int main(int argc,char *argv[])
}
}
if (dump)
- printf("%9qx %20.7f %s\n",info->lastpos,weight,buf);
-
- if(verbose && (total%HOW_OFTEN_TO_WRITE)==0)
+ {
+ if (subkeys>=0)
+ printf("%9qx %20.7f %s\n",info->lastpos,weight,buf);
+ else
+ printf("%9qx => %17d %s\n",info->lastpos,-subkeys,buf);
+ }
+ if (verbose && (total%HOW_OFTEN_TO_WRITE)==0)
printf("%10ld\r",total);
}
@@ -216,18 +222,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
switch(optid) {
case 'd':
- dump=1;
+ dump=1;
complain(count || query);
break;
- case 's':
- stats=1;
+ case 's':
+ stats=1;
complain(query!=0);
break;
- case 'c':
+ case 'c':
count= 1;
complain(dump || query);
break;
- case 'l':
+ case 'l':
lstats=1;
complain(query!=0);
break;
diff --git a/myisam/ft_eval.h b/myisam/ft_eval.h
index 68be3a39f33..5501fe9d34b 100644
--- a/myisam/ft_eval.h
+++ b/myisam/ft_eval.h
@@ -33,7 +33,7 @@ FILE *df,*qf;
MI_COLUMNDEF recinfo[3];
MI_KEYDEF keyinfo[2];
-MI_KEYSEG keyseg[10];
+HA_KEYSEG keyseg[10];
#define SWL_INIT 500
#define SWL_PLUS 50
diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c
index 95ff700f815..b1d7d67ae79 100644
--- a/myisam/ft_nlq_search.c
+++ b/myisam/ft_nlq_search.c
@@ -42,8 +42,6 @@ typedef struct st_all_in_one
uint keynr;
CHARSET_INFO *charset;
uchar *keybuff;
- MI_KEYDEF *keyinfo;
- my_off_t key_root;
TREE dtree;
} ALL_IN_ONE;
@@ -66,13 +64,14 @@ static int FT_SUPERDOC_cmp(void* cmp_arg __attribute__((unused)),
static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
{
+ int subkeys;
uint keylen, r, doc_cnt;
-#ifdef EVAL_RUN
- uint cnt;
- double sum, sum2, suml;
-#endif /* EVAL_RUN */
FT_SUPERDOC sdoc, *sptr;
TREE_ELEMENT *selem;
+ MI_INFO *info=aio->info;
+ uchar *keybuff=aio->keybuff;
+ MI_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
+ my_off_t key_root=info->s->state.key_root[aio->keynr];
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
#else
@@ -83,47 +82,48 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
word->weight=LWS_FOR_QUERY;
- keylen=_ft_make_key(aio->info,aio->keynr,(char*) aio->keybuff,word,0);
-#ifdef EVAL_RUN
- keylen-=1+HA_FT_WLEN;
-#else /* EVAL_RUN */
+ keylen=_ft_make_key(info,aio->keynr,(char*) keybuff,word,0);
keylen-=HA_FT_WLEN;
-#endif /* EVAL_RUN */
-
-#ifdef EVAL_RUN
- sum=sum2=suml=
-#endif /* EVAL_RUN */
doc_cnt=0;
- r=_mi_search(aio->info, aio->keyinfo, aio->keybuff, keylen,
- SEARCH_FIND | SEARCH_PREFIX, aio->key_root);
- aio->info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
+ r=_mi_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root);
+ info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
while (!r)
{
- if (_mi_compare_text(aio->charset,
- aio->info->lastkey,keylen,
- aio->keybuff,keylen,0)) break;
+ if (keylen &&
+ mi_compare_text(aio->charset,info->lastkey,keylen, keybuff,keylen,0))
+ break;
+
+ subkeys=ft_sintXkorr(info->lastkey+keylen);
+ if (subkeys<0)
+ {
+ if (doc_cnt)
+ DBUG_RETURN(1); /* index is corrupted */
+ /*
+ TODO here: unsafe optimization, should this word
+ be skipped (based on subkeys) ?
+ */
+ keybuff+=keylen;
+ keyinfo=& info->s->ft2_keyinfo;
+ key_root=info->lastpos;
+ keylen=0;
+ r=_mi_search_first(info, keyinfo, key_root);
+ continue;
+ }
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
-#ifdef EVAL_RUN
- mi_float4get(tmp_weight,aio->info->lastkey+keylen+1);
-#else /* EVAL_RUN */
- mi_float4get(tmp_weight,aio->info->lastkey+keylen);
-#endif /* EVAL_RUN */
+ tmp_weight=*(float*)&subkeys;
#else
#error
#endif
- if(tmp_weight==0) DBUG_RETURN(doc_cnt); /* stopword, doc_cnt should be 0 */
-
-#ifdef EVAL_RUN
- cnt=*(byte *)(aio->info->lastkey+keylen);
-#endif /* EVAL_RUN */
+ if (tmp_weight==0)
+ DBUG_RETURN(doc_cnt); /* stopword, doc_cnt should be 0 */
- sdoc.doc.dpos=aio->info->lastpos;
+ sdoc.doc.dpos=info->lastpos;
/* saving document matched into dtree */
- if (!(selem=tree_insert(&aio->dtree, &sdoc, 0)))
+ if (!(selem=tree_insert(&aio->dtree, &sdoc, 0, aio->dtree.custom_arg)))
DBUG_RETURN(1);
sptr=(FT_SUPERDOC *)ELEMENT_KEY((&aio->dtree), selem);
@@ -137,20 +137,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
sptr->tmp_weight=tmp_weight;
doc_cnt++;
-#ifdef EVAL_RUN
- sum +=cnt;
- sum2+=cnt*cnt;
- suml+=cnt*log(cnt);
-#endif /* EVAL_RUN */
-
- if (_mi_test_if_changed(aio->info) == 0)
- r=_mi_search_next(aio->info, aio->keyinfo, aio->info->lastkey,
- aio->info->lastkey_length, SEARCH_BIGGER,
- aio->key_root);
+
+ if (_mi_test_if_changed(info) == 0)
+ r=_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
+ SEARCH_BIGGER, key_root);
else
- r=_mi_search(aio->info, aio->keyinfo, aio->info->lastkey,
- aio->info->lastkey_length, SEARCH_BIGGER,
- aio->key_root);
+ r=_mi_search(info, keyinfo, info->lastkey, info->lastkey_length,
+ SEARCH_BIGGER, key_root);
}
if (doc_cnt)
{
@@ -200,10 +193,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query,
aio.info=info;
aio.keynr=keynr;
- aio.keyinfo=info->s->keyinfo+keynr;
- aio.charset=aio.keyinfo->seg->charset;
+ aio.charset=info->s->keyinfo[keynr].seg->charset;
aio.keybuff=info->lastkey+info->s->base.max_key_length;
- aio.key_root=info->s->state.key_root[keynr];
bzero(&allocated_wtree,sizeof(allocated_wtree));
diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c
index c25ed6022a0..14c67333734 100644
--- a/myisam/ft_parser.c
+++ b/myisam/ft_parser.c
@@ -18,41 +18,22 @@
#include "ftdefs.h"
-#ifdef EVAL_RUN
-#ifdef PIVOT_STAT
-ulong collstat=0;
-#endif
-#endif /* EVAL_RUN */
-
typedef struct st_ft_docstat {
FT_WORD *list;
uint uniq;
double sum;
-#ifdef EVAL_RUN
- uint words, totlen;
- double max, nsum, nsum2;
-#endif /* EVAL_RUN */
-
} FT_DOCSTAT;
static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2)
{
- return _mi_compare_text(cs, (uchar*) w1->pos, w1->len,
- (uchar*) w2->pos, w2->len, 0);
+ return mi_compare_text(cs, (uchar*) w1->pos, w1->len,
+ (uchar*) w2->pos, w2->len, 0);
}
static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
{
word->weight=LWS_IN_USE;
-
-#ifdef EVAL_RUN
- word->cnt= (uchar) count;
- if(docstat->max < word->weight) docstat->max=word->weight;
- docstat->words+=count;
- docstat->totlen+=word->len;
-#endif /* EVAL_RUN */
docstat->sum+=word->weight;
-
memcpy_fixed((docstat->list)++,word,sizeof(FT_WORD));
return 0;
}
@@ -70,9 +51,6 @@ FT_WORD * ft_linearize(TREE *wtree)
{
docstat.list=wlist;
docstat.uniq=wtree->elements_in_tree;
-#ifdef EVAL_RUN
- docstat.nsum=docstat.nsum2=docstat.max=docstat.words=docstat.totlen=
-#endif /* EVAL_RUN */
docstat.sum=0;
tree_walk(wtree,(tree_walk_action)&walk_and_copy,&docstat,left_root_right);
}
@@ -85,18 +63,8 @@ FT_WORD * ft_linearize(TREE *wtree)
for (p=wlist;p->pos;p++)
{
p->weight=PRENORM_IN_USE;
-#ifdef EVAL_RUN
- docstat.nsum+=p->weight;
- docstat.nsum2+=p->weight*p->weight;
-#endif /* EVAL_RUN */
}
-#ifdef EVAL_RUN
-#ifdef PIVOT_STAT
- collstat+=PIVOT_STAT;
-#endif
-#endif /* EVAL_RUN */
-
for (p=wlist;p->pos;p++)
{
p->weight/=NORM_IN_USE;
@@ -105,13 +73,13 @@ FT_WORD * ft_linearize(TREE *wtree)
DBUG_RETURN(wlist);
}
-#define true_word_char(X) (isalnum(X) || (X)=='_')
+#define true_word_char(s,X) (my_isalnum(s,X) || (X)=='_')
#ifdef HYPHEN_IS_DELIM
#define misc_word_char(X) ((X)=='\'')
#else
#define misc_word_char(X) ((X)=='\'' || (X)=='-')
#endif
-#define word_char(X) (true_word_char(X) || misc_word_char(X))
+#define word_char(s,X) (true_word_char(s,X) || misc_word_char(X))
/* returns:
@@ -132,7 +100,11 @@ byte ft_get_word(byte **start, byte *end, FT_WORD *word, FTB_PARAM *param)
{
for (;doc<end;doc++)
{
- if (true_word_char(*doc)) break;
+ /*
+ BAR TODO: discuss with Serge how to remove
+ default_charset_info correctly
+ */
+ if (true_word_char(default_charset_info,*doc)) break;
if (*doc == FTB_RQUOT && param->quot) {
param->quot=doc;
*start=doc+1;
@@ -162,7 +134,7 @@ byte ft_get_word(byte **start, byte *end, FT_WORD *word, FTB_PARAM *param)
mwc=0;
for (word->pos=doc; doc<end; doc++)
- if (true_word_char(*doc))
+ if (true_word_char(default_charset_info,*doc))
mwc=0;
else if (!misc_word_char(*doc) || mwc++)
break;
@@ -192,12 +164,12 @@ byte ft_simple_get_word(byte **start, byte *end, FT_WORD *word)
{
for (;doc<end;doc++)
{
- if (true_word_char(*doc)) break;
+ if (true_word_char(default_charset_info,*doc)) break;
}
mwc=0;
for(word->pos=doc; doc<end; doc++)
- if (true_word_char(*doc))
+ if (true_word_char(default_charset_info,*doc))
mwc=0;
else if (!misc_word_char(*doc) || mwc++)
break;
@@ -230,7 +202,7 @@ int ft_parse(TREE *wtree, byte *doc, int doclen)
while (ft_simple_get_word(&doc,end,&w))
{
- if (!tree_insert(wtree, &w, 0))
+ if (!tree_insert(wtree, &w, 0, wtree->custom_arg))
goto err;
}
DBUG_RETURN(0);
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index 7f78a11bb2f..44e80847fd7 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -23,28 +23,24 @@ ulong ft_max_word_len=HA_FT_MAXLEN;
ulong ft_max_word_len_for_sort=20;
const char *ft_boolean_syntax="+ -><()~*:\"\"&|";
-const MI_KEYSEG ft_keysegs[FT_SEGS]={
+const HA_KEYSEG ft_keysegs[FT_SEGS]={
{
HA_KEYTYPE_VARTEXT, /* type */
- 7, /* language (will be overwritten) */
+ 63, /* language (will be overwritten) */
0, 0, 0, /* null_bit, bit_start, bit_end */
HA_VAR_LENGTH | HA_PACK_KEY, /* flag */
HA_FT_MAXLEN, /* length */
-#ifdef EVAL_RUN
- HA_FT_WLEN+1, /* start */
-#else /* EVAL_RUN */
HA_FT_WLEN, /* start */
-#endif /* EVAL_RUN */
0, /* null_pos */
- NULL /* sort_order */
+ NULL /* charset */
},
-#ifdef EVAL_RUN
{
- HA_KEYTYPE_INT8, 7, 0, 0, 0, 0, 1, HA_FT_WLEN, 0, NULL
- },
-#endif /* EVAL_RUN */
- {
- HA_FT_WTYPE, 7, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, 0, 0, NULL
+/*
+ Note, this (and the last HA_KEYTYPE_END) segment should NOT
+ be packed in any way, otherwise w_search() won't be able to
+ update key entry 'in vivo'
+*/
+ HA_FT_WTYPE, 63, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, 0, 0, NULL
}
};
diff --git a/myisam/ft_stopwords.c b/myisam/ft_stopwords.c
index 298df9a54cf..5163aca60bd 100644
--- a/myisam/ft_stopwords.c
+++ b/myisam/ft_stopwords.c
@@ -17,8 +17,10 @@
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
#include "ftdefs.h"
+#include "my_handler.h"
-typedef struct st_ft_stopwords {
+typedef struct st_ft_stopwords
+{
const char * pos;
uint len;
} FT_STOPWORD;
@@ -28,9 +30,9 @@ static TREE *stopwords3=NULL;
static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)),
FT_STOPWORD *w1, FT_STOPWORD *w2)
{
- return _mi_compare_text(default_charset_info,
- (uchar *)w1->pos,w1->len,
- (uchar *)w2->pos,w2->len,0);
+ return mi_compare_text(default_charset_info,
+ (uchar *)w1->pos,w1->len,
+ (uchar *)w2->pos,w2->len,0);
}
static void FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action,
@@ -45,7 +47,7 @@ static int ft_add_stopword(const char *w)
FT_STOPWORD sw;
return !w ||
(((sw.len= (uint) strlen(sw.pos=w)) >= ft_min_word_len) &&
- (tree_insert(stopwords3, &sw, 0)==NULL));
+ (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL));
}
int ft_init_stopwords()
@@ -111,7 +113,7 @@ int is_stopword(char *word, uint len)
FT_STOPWORD sw;
sw.pos=word;
sw.len=len;
- return tree_search(stopwords3,&sw) != NULL;
+ return tree_search(stopwords3,&sw, stopwords3->custom_arg) != NULL;
}
diff --git a/myisam/ft_test1.c b/myisam/ft_test1.c
index cb0b6054f0a..f4884f8ca39 100644
--- a/myisam/ft_test1.c
+++ b/myisam/ft_test1.c
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
static MI_COLUMNDEF recinfo[3];
static MI_KEYDEF keyinfo[2];
-static MI_KEYSEG keyseg[10];
+static HA_KEYSEG keyseg[10];
static int run_test(const char *filename)
{
diff --git a/myisam/ft_update.c b/myisam/ft_update.c
index a68cc2a4cf4..4b6d1c4bffc 100644
--- a/myisam/ft_update.c
+++ b/myisam/ft_update.c
@@ -31,7 +31,7 @@
void _mi_ft_segiterator_init(MI_INFO *info, uint keynr, const byte *record,
FT_SEG_ITERATOR *ftsi)
{
- ftsi->num=info->s->keyinfo[keynr].keysegs-FT_SEGS;
+ ftsi->num=info->s->keyinfo[keynr].keysegs;
ftsi->seg=info->s->keyinfo[keynr].seg;
ftsi->rec=record;
}
@@ -113,7 +113,7 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr,
if (_mi_ft_parse(&ptree, info, keynr, record))
return NULL;
- return ft_linearize(/*info, keynr, keybuf, */ &ptree);
+ return ft_linearize(&ptree);
}
static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf,
@@ -163,8 +163,8 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2)
{
if ((ftsi1.pos != ftsi2.pos) &&
(!ftsi1.pos || !ftsi2.pos ||
- _mi_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len,
- (uchar*) ftsi2.pos,ftsi2.len,0)))
+ mi_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len,
+ (uchar*) ftsi2.pos,ftsi2.len,0)))
return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
}
return GEE_THEY_ARE_ABSOLUTELY_IDENTICAL;
@@ -190,7 +190,7 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
error=0;
while(old_word->pos && new_word->pos)
{
- cmp=_mi_compare_text(cs, (uchar*) old_word->pos,old_word->len,
+ cmp= mi_compare_text(cs, (uchar*) old_word->pos,old_word->len,
(uchar*) new_word->pos,new_word->len,0);
cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5);
@@ -267,13 +267,7 @@ uint _ft_make_key(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wptr,
#error
#endif
-#ifdef EVAL_RUN
- *(buf+HA_FT_WLEN)=wptr->cnt;
- int2store(buf+HA_FT_WLEN+1,wptr->len);
- memcpy(buf+HA_FT_WLEN+3,wptr->pos,wptr->len);
-#else /* EVAL_RUN */
int2store(buf+HA_FT_WLEN,wptr->len);
memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len);
-#endif /* EVAL_RUN */
return _mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos);
}
diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h
index 62fa4362e19..88d7e79937b 100644
--- a/myisam/ftdefs.h
+++ b/myisam/ftdefs.h
@@ -60,16 +60,6 @@
#define NORM_SUM (docstat.nsum)
#define NORM_COS (sqrt(docstat.nsum2))
-#ifdef EVAL_RUN
-/*
-extern ulong collstat;
-#define PIVOT_STAT (docstat.uniq)
-#define PIVOT_SLOPE (0.69)
-#define PIVOT_PIVOT ((double)collstat/(info->state->records+1))
-#define NORM_PIVOT ((1-PIVOT_SLOPE)*PIVOT_PIVOT+PIVOT_SLOPE*docstat.uniq)
-*/
-#endif /* EVAL_RUN */
-
#define PIVOT_VAL (0.0115)
#define NORM_PIVOT (1+PIVOT_VAL*docstat.uniq)
/*---------------------------------------------------------------*/
@@ -102,9 +92,6 @@ typedef struct st_ft_word {
byte * pos;
uint len;
double weight;
-#ifdef EVAL_RUN
- byte cnt;
-#endif /* EVAL_RUN */
} FT_WORD;
typedef struct st_ftb_param {
@@ -125,7 +112,7 @@ byte ft_simple_get_word(byte **, byte *, FT_WORD *);
typedef struct _st_ft_seg_iterator {
uint num, len;
- MI_KEYSEG *seg;
+ HA_KEYSEG *seg;
const byte *rec, *pos;
} FT_SEG_ITERATOR;
diff --git a/myisam/fulltext.h b/myisam/fulltext.h
index f787c9bcfe8..ec267eb3e86 100644
--- a/myisam/fulltext.h
+++ b/myisam/fulltext.h
@@ -21,19 +21,16 @@
#include "myisamdef.h"
#include "ft_global.h"
-/* shoudn't be def'ed when linking with mysql */
-#undef EVAL_RUN
-
#define HA_FT_WTYPE HA_KEYTYPE_FLOAT
#define HA_FT_WLEN 4
-#ifdef EVAL_RUN
-#define FT_SEGS 3
-#else /* EVAL_RUN */
#define FT_SEGS 2
-#endif /* EVAL_RUN */
-extern const MI_KEYSEG ft_keysegs[FT_SEGS];
+#define ft_sintXkorr(A) mi_sint4korr(A)
+#define ft_intXstore(T,A) mi_int4store(T,A)
+
+extern const HA_KEYSEG ft_keysegs[FT_SEGS];
int _mi_ft_cmp(MI_INFO *, uint, const byte *, const byte *);
int _mi_ft_add(MI_INFO *, uint, byte *, const byte *, my_off_t);
int _mi_ft_del(MI_INFO *, uint, byte *, const byte *, my_off_t);
+
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 67a7d6f363d..d3000f63126 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -49,10 +49,11 @@ static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
static int sort_ft_key_read(MI_SORT_PARAM *sort_param,void *key);
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
+static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a);
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
uchar *key);
-static int sort_insert_key(MI_SORT_PARAM *sort_param,
+static int sort_insert_key(MI_SORT_PARAM *sort_param,
reg1 SORT_KEY_BLOCKS *key_block,
uchar *key, my_off_t prev_block);
static int sort_delete_record(MI_SORT_PARAM *sort_param);
@@ -62,22 +63,6 @@ static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
static ha_checksum mi_byte_checksum(const byte *buf, uint length);
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
-#ifdef __WIN__
-static double ulonglong2double(ulonglong value)
-{
- longlong nr=(longlong) value;
- if (nr >= 0)
- return (double) nr;
- return (18446744073709551616.0 + (double) nr);
-}
-
-#if SIZEOF_OFF_T > 4
-#define my_off_t2double(A) ulonglong2double(A)
-#else
-#define my_off_t2double(A) ((double) (A))
-#endif /* SIZEOF_OFF_T > 4 */
-#endif /* __WIN__ */
-
void myisamchk_init(MI_CHECK *param)
{
bzero((gptr) param,sizeof(*param));
@@ -583,8 +568,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
goto err;
}
if ((*keys)++ &&
- (flag=_mi_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
- comp_flag, &not_used)) >=0)
+ (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
+ comp_flag, &not_used)) >=0)
{
DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length);
DBUG_DUMP("new",(byte*) key, key_length);
@@ -601,9 +586,9 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (*keys != 1L) /* not first_key */
{
uint diff;
- _mi_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
- SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
- &diff);
+ ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
+ SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
+ &diff);
param->unique_count[diff-1]++;
}
}
@@ -670,7 +655,7 @@ static ha_checksum calc_checksum(ha_rows count)
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
{
uint length;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
DBUG_ENTER("isam_key_length");
length= info->s->rec_reflength;
@@ -1772,7 +1757,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
File new_file;
MI_SORT_PARAM sort_param;
MYISAM_SHARE *share=info->s;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
ulong *rec_per_key_part;
char llbuff[22];
SORT_INFO sort_info;
@@ -1891,7 +1876,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records :
(ha_rows) (sort_info.filelength/length+1));
sort_param.key_cmp=sort_key_cmp;
- sort_param.key_write=sort_key_write;
sort_param.lock_in_memory=lock_memory;
sort_param.tmpdir=param->tmpdir;
sort_param.sort_info=&sort_info;
@@ -1944,10 +1928,14 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
(ha_rows) (sort_info.filelength/ft_max_word_len_for_sort+1);
sort_param.key_read=sort_ft_key_read;
+ sort_param.key_write=sort_ft_key_write;
sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXLEN;
}
else
+ {
sort_param.key_read=sort_key_read;
+ sort_param.key_write=sort_key_write;
+ }
if (_create_index_by_sort(&sort_param,
(my_bool) (!(param->testflag & T_VERBOSE)),
@@ -1993,9 +1981,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
else
info->state->data_file_length=sort_param.max_pos;
- /*if (flush_pending_blocks(param))
- goto err;*/
-
param->read_cache.file=info->dfile; /* re-init read cache */
reinit_io_cache(&param->read_cache,READ_CACHE,share->pack.header_length,
1,1);
@@ -2094,6 +2079,7 @@ err:
MYF(MY_ALLOW_ZERO_PTR));
my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((gptr) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
@@ -2109,7 +2095,7 @@ err:
Threaded repair of table using sorting
SYNOPSIS
- mi_repair_by_sort_r()
+ mi_repair_by_sort_parallel()
param Repair parameters
info MyISAM handler to repair
name Name of table (for warnings)
@@ -2137,7 +2123,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
MI_SORT_PARAM *sort_param=0;
MYISAM_SHARE *share=info->s;
ulong *rec_per_key_part;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
char llbuff[22];
IO_CACHE_SHARE io_share;
SORT_INFO sort_info;
@@ -2282,10 +2268,17 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
istep=1;
if ((!(param->testflag & T_SILENT)))
printf ("- Fixing index %d\n",key+1);
- sort_param[i].key_read= ((sort_param[i].keyinfo->flag & HA_FULLTEXT) ?
- sort_ft_key_read : sort_key_read);
+ if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
+ {
+ sort_param[i].key_read=sort_ft_key_read;
+ sort_param[i].key_write=sort_ft_key_write;
+ }
+ else
+ {
+ sort_param[i].key_read=sort_key_read;
+ sort_param[i].key_write=sort_key_write;
+ }
sort_param[i].key_cmp=sort_key_cmp;
- sort_param[i].key_write=sort_key_write;
sort_param[i].lock_in_memory=lock_memory;
sort_param[i].tmpdir=param->tmpdir;
sort_param[i].sort_info=&sort_info;
@@ -2478,6 +2471,7 @@ err:
pthread_cond_destroy (&sort_info.cond);
pthread_mutex_destroy(&sort_info.mutex);
+ my_free((gptr) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) sort_param,MYF(MY_ALLOW_ZERO_PTR));
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
@@ -2510,7 +2504,7 @@ static int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
DBUG_RETURN(1);
}
sort_param->real_key_length=
- (info->s->rec_reflength+
+ (info->s->rec_reflength+
_mi_make_key(info, sort_param->key, (uchar*) key,
sort_param->record, sort_param->filepos));
#ifdef HAVE_purify
@@ -2589,6 +2583,9 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
char llbuff[22],llbuff2[22];
DBUG_ENTER("sort_get_next_record");
+ if (*killed_ptr(param))
+ DBUG_RETURN(1);
+
switch (share->data_file_type) {
case STATIC_RECORD:
for (;;)
@@ -3054,8 +3051,8 @@ static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
const void *b)
{
uint not_used;
- return (_mi_key_cmp(sort_param->keyinfo->seg,*((uchar**) a),*((uchar**) b),
- USE_WHOLE_KEY, SEARCH_SAME,&not_used));
+ return (ha_key_cmp(sort_param->keyinfo->seg, *((uchar**) a), *((uchar**) b),
+ USE_WHOLE_KEY, SEARCH_SAME,&not_used));
} /* sort_key_cmp */
@@ -3069,9 +3066,9 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
if (sort_info->key_block->inited)
{
- cmp=_mi_key_cmp(sort_param->keyinfo->seg, sort_info->key_block->lastkey,
- (uchar*) a, USE_WHOLE_KEY, SEARCH_FIND | SEARCH_UPDATE,
- &diff_pos);
+ cmp=ha_key_cmp(sort_param->keyinfo->seg,sort_info->key_block->lastkey,
+ (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
+ &diff_pos);
sort_param->unique[diff_pos-1]++;
}
else
@@ -3082,13 +3079,16 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
{
sort_info->dupp++;
sort_info->info->lastpos=get_record_for_key(sort_info->info,
- sort_param->keyinfo,
- (uchar*) a);
+ sort_param->keyinfo,
+ (uchar*) a);
mi_check_print_warning(param,
- "Duplicate key for record at %10s against record at %10s",
- llstr(sort_info->info->lastpos,llbuff),
- llstr(get_record_for_key(sort_info->info, sort_param->keyinfo,
- sort_info->key_block->lastkey), llbuff2));
+ "Duplicate key for record at %10s against record at %10s",
+ llstr(sort_info->info->lastpos,llbuff),
+ llstr(get_record_for_key(sort_info->info,
+ sort_param->keyinfo,
+ sort_info->key_block->
+ lastkey),
+ llbuff2));
param->testflag|=T_RETRY_WITHOUT_QUICK;
if (sort_info->param->testflag & T_VERBOSE)
_mi_print_key(stdout,sort_param->keyinfo->seg,(uchar*) a, USE_WHOLE_KEY);
@@ -3106,6 +3106,137 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
(uchar*) a, HA_OFFSET_ERROR));
} /* sort_key_write */
+int sort_ft_buf_flush(MI_SORT_PARAM *sort_param)
+{
+ SORT_INFO *sort_info=sort_param->sort_info;
+ SORT_KEY_BLOCKS *key_block=sort_info->key_block;
+ MYISAM_SHARE *share=sort_info->info->s;
+ uint val_off, val_len, error;
+ SORT_FT_BUF *ft_buf=sort_info->ft_buf;
+ uchar *from, *to;
+
+ val_len=share->ft2_keyinfo.keylength;
+ get_key_full_length_rdonly(val_off, ft_buf->lastkey);
+ to=ft_buf->lastkey+val_off;
+
+ if (ft_buf->buf)
+ { /* flushing first-level tree */
+ error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,HA_OFFSET_ERROR);
+ for (from=to+val_len;
+ !error && from < ft_buf->buf;
+ from+= val_len)
+ {
+ memcpy(to, from, val_len);
+ error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,HA_OFFSET_ERROR);
+ }
+ return error;
+ }
+ /* flushing second-level tree keyblocks */
+ error=flush_pending_blocks(sort_param);
+ /* updating lastkey with second-level tree info */
+ ft_intXstore(ft_buf->lastkey+val_off, -ft_buf->count);
+ _mi_dpointer(sort_info->info, ft_buf->lastkey+val_off+HA_FT_WLEN,
+ share->state.key_root[sort_param->key]);
+ /* restoring first level tree data in sort_info/sort_param */
+ sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks;
+ sort_param->keyinfo=share->keyinfo+sort_param->key;
+ share->state.key_root[sort_param->key]=HA_OFFSET_ERROR;
+ /* writing lastkey in first-level tree */
+ return error ? error :
+ sort_insert_key(sort_param,sort_info->key_block,
+ ft_buf->lastkey,HA_OFFSET_ERROR);
+}
+
+static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
+{
+ uint a_len, val_off, val_len, error;
+ uchar *p;
+ SORT_INFO *sort_info=sort_param->sort_info;
+ SORT_FT_BUF *ft_buf=sort_info->ft_buf;
+ SORT_KEY_BLOCKS *key_block=sort_info->key_block;
+
+ val_len=HA_FT_WLEN+sort_info->info->s->base.rec_reflength;
+ get_key_full_length_rdonly(a_len, (uchar *)a);
+
+ if (!ft_buf)
+ {
+ /*
+ use two-level tree only if key_reflength fits in rec_reflength place
+ and row format is NOT static - for _mi_dpointer not to garble offsets
+ */
+ if ((sort_info->info->s->base.key_reflength <=
+ sort_info->info->s->base.rec_reflength) &&
+ (sort_info->info->s->options &
+ (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
+ ft_buf=(SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
+ sizeof(SORT_FT_BUF), MYF(MY_WME));
+
+ if (!ft_buf)
+ {
+ sort_param->key_write=sort_key_write;
+ return sort_key_write(sort_param, a);
+ }
+ sort_info->ft_buf=ft_buf;
+ goto word_init_ft_buf; /* no need to duplicate the code */
+ }
+ get_key_full_length_rdonly(val_off, ft_buf->lastkey);
+
+ if (val_off == a_len &&
+ mi_compare_text(sort_param->keyinfo->seg->charset,
+ ((uchar *)a)+1,a_len-1,
+ ft_buf->lastkey+1,val_off-1, 0)==0)
+ {
+ if (!ft_buf->buf) /* store in second-level tree */
+ {
+ ft_buf->count++;
+ return sort_insert_key(sort_param,key_block,
+ ((uchar *)a)+val_off, HA_OFFSET_ERROR);
+ }
+
+ /* storing the key in the buffer. */
+ memcpy (ft_buf->buf, (char *)a+val_off, val_len);
+ ft_buf->buf+=val_len;
+ if (ft_buf->buf < ft_buf->end)
+ return 0;
+
+ /* converting to two-level tree */
+ p=ft_buf->lastkey+val_off;
+
+ while (key_block->inited)
+ key_block++;
+ sort_info->key_block=key_block;
+ sort_param->keyinfo=& sort_info->info->s->ft2_keyinfo;
+ ft_buf->count=(ft_buf->buf - p)/val_len;
+
+ /* flushing buffer to second-level tree */
+ for (error=0; !error && p < ft_buf->buf; p+= val_len)
+ error=sort_insert_key(sort_param,key_block,p,HA_OFFSET_ERROR);
+ ft_buf->buf=0;
+ return error;
+ }
+ else
+ {
+ /* flushing buffer */
+ if ((error=sort_ft_buf_flush(sort_param)))
+ return error;
+
+word_init_ft_buf:
+ a_len+=val_len;
+ memcpy(ft_buf->lastkey, a, a_len);
+ ft_buf->buf=ft_buf->lastkey+a_len;
+ ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
+ /* 32 is just a safety margin here
+ (at least max(val_len, sizeof(nod_flag)) should be there).
+ May be better performance could be achieved if we'd put
+ (sort_info->keyinfo->block_length-32)/XXX
+ instead.
+ TODO: benchmark the best value for XXX.
+ */
+
+ return 0;
+ }
+ return -1; /* impossible */
+} /* sort_ft_key_write */
/* get pointer to record from a key */
@@ -3265,7 +3396,7 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param)
my_off_t filepos,key_file_length;
SORT_KEY_BLOCKS *key_block;
SORT_INFO *sort_info= sort_param->sort_info;
- MI_CHECK *param=sort_info->param;
+ myf myf_rw=sort_info->param->myf_rw;
MI_INFO *info=sort_info->info;
MI_KEYDEF *keyinfo=sort_param->keyinfo;
DBUG_ENTER("flush_pending_blocks");
@@ -3290,7 +3421,7 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param)
DBUG_RETURN(1);
}
else if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
- (uint) keyinfo->block_length,filepos, param->myf_rw))
+ (uint) keyinfo->block_length,filepos, myf_rw))
DBUG_RETURN(1);
DBUG_DUMP("buff",(byte*) key_block->buff,length);
nod_flag=1;
@@ -3344,7 +3475,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
MI_INFO info;
MYISAM_SHARE share;
MI_KEYDEF *keyinfo,*key,*key_end;
- MI_KEYSEG *keysegs,*keyseg;
+ HA_KEYSEG *keysegs,*keyseg;
MI_COLUMNDEF *recdef,*rec,*end;
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
MI_STATUS_INFO status_info;
@@ -3366,7 +3497,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
key_parts= share.base.all_key_parts;
- if (!(keysegs=(MI_KEYSEG*) my_alloca(sizeof(MI_KEYSEG)*
+ if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
(key_parts+share.base.keys))))
{
my_afree((gptr) keyinfo);
@@ -3402,7 +3533,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
/* Change the new key to point at the saved key segments */
memcpy((byte*) keysegs,(byte*) share.keyparts,
- (size_t) (sizeof(MI_KEYSEG)*(key_parts+share.base.keys+
+ (size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
share.state.header.uniques)));
keyseg=keysegs;
for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
@@ -3678,10 +3809,7 @@ static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
key_maxlength+=ft_max_word_len_for_sort-HA_FT_MAXLEN;
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
((ulonglong) rows * key_maxlength >
- (ulonglong) myisam_max_temp_length ||
- (ulonglong) rows * (key_maxlength - key->minlength) / 2 >
- myisam_max_extra_temp_length ||
- (rows == 0 && (key_maxlength / key->minlength) > 2)));
+ (ulonglong) myisam_max_temp_length));
}
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 039066c5b37..843a92d9d10 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -17,6 +17,8 @@
/* Create a MyISAM table */
#include "fulltext.h"
+#include "sp_defs.h"
+
#if defined(MSDOS) || defined(__WIN__)
#ifdef __WIN__
#include <fcntl.h>
@@ -42,7 +44,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
uint fields,length,max_key_length,packed,pointer,
key_length,info_length,key_segs,options,min_key_length_skipp,
base_pos,varchar_count,long_varchar_count,varchar_length,
- max_key_block_length,unique_key_parts,offset;
+ max_key_block_length,unique_key_parts,fulltext_keys,offset;
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
@@ -51,7 +53,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
MYISAM_SHARE share;
MI_KEYDEF *keydef,tmp_keydef;
MI_UNIQUEDEF *uniquedef;
- MI_KEYSEG *keyseg,tmp_keyseg;
+ HA_KEYSEG *keyseg,tmp_keyseg;
MI_COLUMNDEF *rec;
ulong *rec_per_key_part;
my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
@@ -221,6 +223,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
reclength+=long_varchar_count; /* We need space for this! */
max_key_length=0; tot_length=0 ; key_segs=0;
+ fulltext_keys=0;
max_key_block_length=0;
share.state.rec_per_key_part=rec_per_key_part;
share.state.key_root=key_root;
@@ -233,28 +236,50 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
{
- share.state.key_root[i]= HA_OFFSET_ERROR;
+ share.state.key_root[i]= HA_OFFSET_ERROR;
min_key_length_skipp=length=0;
key_length=pointer;
-
- if (keydef->flag & HA_FULLTEXT) /* SerG */
+ if (keydef->flag & HA_SPATIAL)
{
- keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
- options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
+ /* BAR TODO to support 3D and more dimensions in the future */
+ uint sp_segs=SPDIMS*2;
+ keydef->flag=HA_SPATIAL;
if (flags & HA_DONT_TOUCH_DATA)
{
- /* called by myisamchk - i.e. table structure was taken from
- MYI file and FULLTEXT key *do has* additional FT_SEGS keysegs.
+ /*
+ called by myisamchk - i.e. table structure was taken from
+ MYI file and SPATIAL key *does have* additional sp_segs keysegs.
We'd better delete them now
*/
- keydef->keysegs-=FT_SEGS;
+ keydef->keysegs-=sp_segs;
}
for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
j++, keyseg++)
{
+ if (keyseg->type != HA_KEYTYPE_BINARY &&
+ keyseg->type != HA_KEYTYPE_VARBINARY)
+ {
+ my_errno=HA_WRONG_CREATE_OPTION;
+ goto err;
+ }
+ }
+ keydef->keysegs+=sp_segs;
+ key_length+=SPLEN*sp_segs;
+ length++; /* At least one length byte */
+ min_key_length_skipp+=SPLEN*2*SPDIMS;
+ }
+ else
+ if (keydef->flag & HA_FULLTEXT)
+ {
+ keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
+ options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
+
+ for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
+ j++, keyseg++)
+ {
if (keyseg->type != HA_KEYTYPE_TEXT &&
keyseg->type != HA_KEYTYPE_VARTEXT)
{
@@ -262,19 +287,11 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
}
}
- keydef->keysegs+=FT_SEGS;
+ fulltext_keys++;
key_length+= HA_FT_MAXLEN+HA_FT_WLEN;
-#ifdef EVAL_RUN
- key_length++;
-#endif
-
length++; /* At least one length byte */
min_key_length_skipp+=HA_FT_MAXLEN;
-#if HA_FT_MAXLEN >= 255
- min_key_length_skipp+=2; /* prefix may be 3 bytes */
- length+=2;
-#endif
}
else
{
@@ -411,7 +428,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
keys * MI_KEYDEF_SIZE+
uniques * MI_UNIQUEDEF_SIZE +
- (key_segs + unique_key_parts)*MI_KEYSEG_SIZE+
+ (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
columns*MI_COLUMNDEF_SIZE);
bmove(share.state.header.file_version,(byte*) myisam_file_magic,4);
@@ -440,8 +457,9 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_get_pointer_length((tot_length + max_key_block_length * keys *
MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH,
3);
- share.base.keys= share.state.header.keys = keys;
+ share.base.keys= share.state.header.keys= keys;
share.state.header.uniques= uniques;
+ share.state.header.fulltext_keys= fulltext_keys;
mi_int2store(share.state.header.key_parts,key_segs);
mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
@@ -533,7 +551,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
linkname_ptr=0;
create_flag=MY_DELETE_OLD;
}
- if ((dfile=
+ if ((dfile=
my_create_with_symlink(linkname_ptr, filename,
0,O_RDWR | O_TRUNC,
MYF(MY_WME | create_flag))) < 0)
@@ -557,18 +575,26 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Write key and keyseg definitions */
for (i=0 ; i < share.base.keys - uniques; i++)
{
- uint ft_segs=(keydefs[i].flag & HA_FULLTEXT) ? FT_SEGS : 0;
+ uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
if (mi_keydef_write(file, &keydefs[i]))
goto err;
- for (j=0 ; j < keydefs[i].keysegs-ft_segs ; j++)
+ for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
- goto err;
- for (j=0 ; j < ft_segs ; j++)
+ goto err;
+ for (j=0 ; j < sp_segs ; j++)
{
- MI_KEYSEG seg=ft_keysegs[j];
- seg.language= keydefs[i].seg[0].language;
- if (mi_keyseg_write(file, &seg))
+ HA_KEYSEG sseg;
+ sseg.type=SPTYPE;
+ sseg.language= 7;
+ sseg.null_bit=0;
+ sseg.bit_start=0;
+ sseg.bit_end=0;
+ sseg.length=SPLEN;
+ sseg.null_pos=0;
+ sseg.start=j*SPLEN;
+ sseg.flag= HA_SWAP_KEY;
+ if (mi_keyseg_write(file, &sseg))
goto err;
}
}
diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c
index 482287938c0..6548b38c135 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -20,7 +20,7 @@
/* Print a key in user understandable format */
-void _mi_print_key(FILE *stream, register MI_KEYSEG *keyseg,
+void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg,
const uchar *key, uint length)
{
int flag;
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index 6f94e3c4256..96c6400f078 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -17,20 +17,24 @@
/* Remove a row from a MyISAM table */
#include "fulltext.h"
+#include "rt_index.h"
+
#ifdef __WIN__
#include <errno.h>
#endif
-static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
- uint key_length, my_off_t page, uchar *anc_buff);
+static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint comp_flag,
+ uchar *key,uint key_length,my_off_t page,uchar *anc_buff);
static int del(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,uchar *anc_buff,
my_off_t leaf_page,uchar *leaf_buff,uchar *keypos,
my_off_t next_block,uchar *ret_key);
static int underflow(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *anc_buff,
- my_off_t leaf_page, uchar *leaf_buff,uchar *keypos);
+ my_off_t leaf_page,uchar *leaf_buff,uchar *keypos);
static uint remove_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
uchar *lastkey,uchar *page_end,
my_off_t *next_block);
+static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
+ uchar *key, uint key_length, my_off_t *root);
int mi_delete(MI_INFO *info,const byte *record)
@@ -71,7 +75,6 @@ int mi_delete(MI_INFO *info,const byte *record)
if (((ulonglong) 1 << i) & info->s->state.key_map)
{
info->s->keyinfo[i].version++;
- /* The following code block is for text searching by SerG */
if (info->s->keyinfo[i].flag & HA_FULLTEXT )
{
if (_mi_ft_del(info,i,(char*) old_key,record,info->lastpos))
@@ -79,9 +82,9 @@ int mi_delete(MI_INFO *info,const byte *record)
}
else
{
- uint key_length=_mi_make_key(info,i,old_key,record,info->lastpos);
- if (_mi_ck_delete(info,i,old_key,key_length))
- goto err;
+ if (info->s->keyinfo[i].ck_delete(info,i,old_key,
+ _mi_make_key(info,i,old_key,record,info->lastpos)))
+ goto err;
}
}
}
@@ -127,18 +130,24 @@ err:
int _mi_ck_delete(register MI_INFO *info, uint keynr, uchar *key,
uint key_length)
{
+ return _mi_ck_real_delete(info, info->s->keyinfo+keynr, key, key_length,
+ &info->s->state.key_root[keynr]);
+} /* _mi_ck_delete */
+
+
+static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
+ uchar *key, uint key_length, my_off_t *root)
+{
int error;
uint nod_flag;
my_off_t old_root;
uchar *root_buff;
- MI_KEYDEF *keyinfo;
- DBUG_ENTER("_mi_ck_delete");
+ DBUG_ENTER("_mi_ck_real_delete");
- if ((old_root=info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ if ((old_root=*root) == HA_OFFSET_ERROR)
{
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
}
- keyinfo=info->s->keyinfo+keynr;
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MI_MAX_KEY_BUFF*2)))
{
@@ -151,12 +160,15 @@ int _mi_ck_delete(register MI_INFO *info, uint keynr, uchar *key,
error= -1;
goto err;
}
- if ((error=d_search(info,keyinfo,key,key_length,old_root,root_buff)) >0)
+ if ((error=d_search(info,keyinfo,
+ (keyinfo->flag & HA_FULLTEXT ? SEARCH_FIND
+ : SEARCH_SAME),
+ key,key_length,old_root,root_buff)) >0)
{
if (error == 2)
{
DBUG_PRINT("test",("Enlarging of root when deleting"));
- error=_mi_enlarge_root(info,keynr,key);
+ error=_mi_enlarge_root(info,keyinfo,key,root);
}
else /* error == 1 */
{
@@ -164,10 +176,9 @@ int _mi_ck_delete(register MI_INFO *info, uint keynr, uchar *key,
{
error=0;
if (nod_flag)
- info->s->state.key_root[keynr]=_mi_kpos(nod_flag,
- root_buff+2+nod_flag);
+ *root=_mi_kpos(nod_flag,root_buff+2+nod_flag);
else
- info->s->state.key_root[keynr]= HA_OFFSET_ERROR;
+ *root=HA_OFFSET_ERROR;
if (_mi_dispose(info,keyinfo,old_root))
error= -1;
}
@@ -178,7 +189,7 @@ int _mi_ck_delete(register MI_INFO *info, uint keynr, uchar *key,
err:
my_afree((gptr) root_buff);
DBUG_RETURN(error);
-} /* _mi_ck_delete */
+} /* _mi_ck_real_delete */
/*
@@ -190,11 +201,11 @@ err:
*/
static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
- uchar *key, uint key_length, my_off_t page,
- uchar *anc_buff)
+ uint comp_flag, uchar *key, uint key_length,
+ my_off_t page, uchar *anc_buff)
{
int flag,ret_value,save_flag;
- uint length,nod_flag;
+ uint length,nod_flag,search_key_length;
my_bool last_key;
uchar *leaf_buff,*keypos;
my_off_t leaf_page,next_block;
@@ -202,9 +213,9 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_ENTER("d_search");
DBUG_DUMP("page",(byte*) anc_buff,mi_getint(anc_buff));
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, USE_WHOLE_KEY,
- SEARCH_SAME,
- &keypos, lastkey, &last_key);
+ search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
+ flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, search_key_length,
+ comp_flag, &keypos, lastkey, &last_key);
if (flag == MI_FOUND_WRONG_KEY)
{
DBUG_PRINT("error",("Found wrong key"));
@@ -212,6 +223,52 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
}
nod_flag=mi_test_if_nod(anc_buff);
+ if (!flag && keyinfo->flag & HA_FULLTEXT)
+ {
+ uint off;
+ int subkeys;
+
+ get_key_full_length_rdonly(off, lastkey);
+ subkeys=ft_sintXkorr(lastkey+off);
+ comp_flag=SEARCH_SAME;
+ if (subkeys >= 0)
+ {
+ /* normal word, one-level tree structure */
+ flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,USE_WHOLE_KEY,
+ comp_flag, &keypos, lastkey, &last_key);
+ /* fall through to normal delete */
+ }
+ else
+ {
+ /* popular word. two-level tree. going down */
+ uint tmp_key_length;
+ my_off_t root;
+ uchar *kpos=keypos;
+
+ tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey);
+ root=_mi_dpos(info,nod_flag,kpos);
+ if (subkeys == -1)
+ {
+ /* the last entry in sub-tree */
+ _mi_dispose(info, keyinfo, root);
+ /* fall through to normal delete */
+ }
+ else
+ {
+ keyinfo=&info->s->ft2_keyinfo;
+ kpos-=keyinfo->keylength; /* we'll modify key entry 'in vivo' */
+ key+=off;
+ ret_value=_mi_ck_real_delete(info, &info->s->ft2_keyinfo,
+ key, HA_FT_WLEN, &root);
+ _mi_dpointer(info, kpos+HA_FT_WLEN, root);
+ subkeys++;
+ ft_intXstore(kpos, subkeys);
+ if (!ret_value)
+ ret_value=_mi_write_keypage(info,keyinfo,page,anc_buff);
+ DBUG_RETURN(ret_value);
+ }
+ }
+ }
leaf_buff=0;
LINT_INIT(leaf_page);
if (nod_flag)
@@ -237,7 +294,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
goto err;
}
save_flag=0;
- ret_value=d_search(info,keyinfo,key,key_length,leaf_page,leaf_buff);
+ ret_value=d_search(info,keyinfo,comp_flag,key,key_length,
+ leaf_page,leaf_buff);
}
else
{ /* Found key */
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 9ec1ca99e0e..00a64bca269 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -18,6 +18,7 @@
#include "myisamdef.h"
#include "m_ctype.h"
+#include "sp_defs.h"
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
@@ -36,9 +37,17 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
{
byte *pos,*end;
uchar *start;
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
DBUG_ENTER("_mi_make_key");
+ if(info->s->keyinfo[keynr].flag & HA_SPATIAL)
+ {
+ /*
+ TODO: nulls processing
+ */
+ return sp_make_key(info,keynr,key,record,filepos);
+ }
+
start=key;
for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
{
@@ -144,7 +153,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
{
uint length;
uchar *pos,*end,*start_key=key;
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
enum ha_base_keytype type;
DBUG_ENTER("_mi_pack_key");
@@ -243,7 +252,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
{
reg2 byte *key;
byte *pos,*key_end;
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
byte *blob_ptr;
DBUG_ENTER("_mi_put_key_in_record");
@@ -377,7 +386,7 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
void update_auto_increment(MI_INFO *info,const byte *record)
{
ulonglong value;
- MI_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg;
+ HA_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg;
const uchar *key=(uchar*) record+keyseg->start;
switch (keyseg->type) {
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 077d8c7da3a..406facec164 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -17,6 +17,8 @@
/* open a isam-database */
#include "fulltext.h"
+#include "sp_defs.h"
+#include "rt_index.h"
#include <m_ctype.h>
#if defined(MSDOS) || defined(__WIN__)
@@ -65,9 +67,9 @@ static MI_INFO *test_if_reopen(char *filename)
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
{
- int lock_error,kfile,open_mode,save_errno;
+ int lock_error,kfile,open_mode,save_errno,have_rtree=0;
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
- key_parts,unique_key_parts,tmp_length,uniques;
+ key_parts,unique_key_parts,fulltext_keys,uniques;
char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN],
data_name[FN_REFLEN];
char *disk_cache,*disk_pos;
@@ -124,8 +126,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE))
{
- DBUG_PRINT("error",("wrong options: 0x%lx",
- share->options));
+ DBUG_PRINT("error",("wrong options: 0x%lx", share->options));
my_errno=HA_ERR_OLD_FILE;
goto err;
}
@@ -160,11 +161,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
len=mi_uint2korr(share->state.header.state_info_length);
keys= (uint) share->state.header.keys;
uniques= (uint) share->state.header.uniques;
+ fulltext_keys= (uint) share->state.header.fulltext_keys;
key_parts= mi_uint2korr(share->state.header.key_parts);
unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
- tmp_length=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
- key_parts*MI_STATE_KEYSEG_SIZE +
- share->state.header.max_block_size*MI_STATE_KEYBLOCK_SIZE);
if (len != MI_STATE_INFO_SIZE)
{
DBUG_PRINT("warning",
@@ -201,6 +200,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
goto err;
}
+ key_parts+=fulltext_keys*FT_SEGS;
if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
key_parts >= MI_MAX_KEY * MI_MAX_KEY_SEG)
{
@@ -209,7 +209,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
goto err;
}
- /* Correct max_file_length based on length of sizeof_t */
+ /* Correct max_file_length based on length of sizeof(off_t) */
max_data_file_length=
(share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
(((ulonglong) 1 << (share->base.rec_reflength*8))-1) :
@@ -254,7 +254,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
&share->keyparts,
(key_parts+unique_key_parts+keys+uniques) *
- sizeof(MI_KEYSEG),
+ sizeof(HA_KEYSEG),
&share->rec,
(share->base.fields+1)*sizeof(MI_COLUMNDEF),
&share->blobs,sizeof(MI_BLOB)*share->base.blobs,
@@ -284,15 +284,18 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share->blocksize=min(IO_SIZE,myisam_block_size);
{
- MI_KEYSEG *pos=share->keyparts;
+ HA_KEYSEG *pos=share->keyparts;
for (i=0 ; i < keys ; i++)
{
disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
+ if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
+ have_rtree=1;
set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
share->keyinfo[i].seg=pos;
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
{
disk_pos=mi_keyseg_read(disk_pos, pos);
+
if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
{
if (!pos->language)
@@ -304,11 +307,50 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
}
}
}
- if (share->keyinfo[i].flag & HA_FULLTEXT)
+ if (share->keyinfo[i].flag & HA_SPATIAL)
+ {
+ uint sp_segs=SPDIMS*2;
+ share->keyinfo[i].seg=pos-sp_segs;
+ share->keyinfo[i].keysegs--;
+ }
+ else if (share->keyinfo[i].flag & HA_FULLTEXT)
{
- share->keyinfo[i].seg=pos-FT_SEGS;
- share->fulltext_index=1;
+ if (!fulltext_keys)
+ { /* 4.0 compatibility code, to be removed in 5.0 */
+ share->keyinfo[i].seg=pos-FT_SEGS;
+ share->keyinfo[i].keysegs-=FT_SEGS;
+ share->state.header.fulltext_keys++;
+ }
+ else
+ {
+ uint j;
+ share->keyinfo[i].seg=pos;
+ for (j=0; j < FT_SEGS; j++)
+ {
+ *pos=ft_keysegs[j];
+ pos[0].language= pos[-1].language;
+ if (!(pos[0].charset= pos[-1].charset))
+ {
+ my_errno=HA_ERR_CRASHED;
+ goto err;
+ }
+ pos++;
+ }
+ }
+ if (!share->ft2_keyinfo.seg)
+ {
+ memcpy(& share->ft2_keyinfo, & share->keyinfo[i], sizeof(MI_KEYDEF));
+ share->ft2_keyinfo.keysegs=1;
+ share->ft2_keyinfo.flag=0;
+ share->ft2_keyinfo.keylength=
+ share->ft2_keyinfo.minlength=
+ share->ft2_keyinfo.maxlength=HA_FT_WLEN+share->base.rec_reflength;
+ share->ft2_keyinfo.seg=pos-1;
+ share->ft2_keyinfo.end=pos;
+ setup_key_functions(& share->ft2_keyinfo);
+ }
}
+ setup_key_functions(share->keyinfo+i);
share->keyinfo[i].end=pos;
pos->type=HA_KEYTYPE_END; /* End */
pos->length=share->base.rec_reflength;
@@ -341,8 +383,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
pos++;
}
}
- for (i=0 ; i < keys ; i++)
- setup_key_functions(share->keyinfo+i);
for (i=j=offset=0 ; i < share->base.fields ; i++)
{
@@ -421,7 +461,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
HA_OPTION_COMPRESS_RECORD |
HA_OPTION_TEMP_COMPRESS_RECORD)) ||
- (open_flags & HA_OPEN_TMP_TABLE)) ? 0 : 1;
+ (open_flags & HA_OPEN_TMP_TABLE) ||
+ have_rtree) ? 0 : 1;
if (share->concurrent_insert)
{
share->lock.get_status=mi_get_status;
@@ -451,6 +492,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&info.blobs,sizeof(MI_BLOB)*share->base.blobs,
&info.buff,(share->base.max_key_block_length*2+
share->base.max_key_length),
+ &info.rtree_recursion_state,have_rtree ? 1024 : 0,
&info.lastkey,share->base.max_key_length*3+1,
&info.filename,strlen(org_name)+1,
NullS))
@@ -658,6 +700,16 @@ void mi_setup_functions(register MYISAM_SHARE *share)
static void setup_key_functions(register MI_KEYDEF *keyinfo)
{
+ if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
+ {
+ keyinfo->ck_insert = rtree_insert;
+ keyinfo->ck_delete = rtree_delete;
+ }
+ else
+ {
+ keyinfo->ck_insert = _mi_ck_write;
+ keyinfo->ck_delete = _mi_ck_delete;
+ }
if (keyinfo->flag & HA_BINARY_PACK_KEY)
{ /* Simple prefix compression */
keyinfo->bin_search=_mi_seq_search;
@@ -670,7 +722,7 @@ static void setup_key_functions(register MI_KEYDEF *keyinfo)
keyinfo->get_key= _mi_get_pack_key;
if (keyinfo->seg[0].flag & HA_PACK_KEY)
{ /* Prefix compression */
- if (!keyinfo->seg->charset || use_strcoll(keyinfo->seg->charset) ||
+ if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
(keyinfo->seg->flag & HA_NULL_PART))
keyinfo->bin_search=_mi_seq_search;
else
@@ -696,9 +748,9 @@ static void setup_key_functions(register MI_KEYDEF *keyinfo)
}
-/***************************************************************************
-** Function to save and store the header in the index file (.MSI)
-***************************************************************************/
+/*
+ Function to save and store the header in the index file (.MYI)
+*/
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
{
@@ -923,7 +975,7 @@ uint mi_keydef_write(File file, MI_KEYDEF *keydef)
uchar *ptr=buff;
*ptr++ = (uchar) keydef->keysegs;
- *ptr++ = 0; /* not used */
+ *ptr++ = keydef->key_alg; /* Rtree or Btree */
mi_int2store(ptr,keydef->flag); ptr +=2;
mi_int2store(ptr,keydef->block_length); ptr +=2;
mi_int2store(ptr,keydef->keylength); ptr +=2;
@@ -935,7 +987,8 @@ uint mi_keydef_write(File file, MI_KEYDEF *keydef)
char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
{
keydef->keysegs = (uint) *ptr++;
- ptr++;
+ keydef->key_alg = *ptr++; /* Rtree or Btree */
+
keydef->flag = mi_uint2korr(ptr); ptr +=2;
keydef->block_length = mi_uint2korr(ptr); ptr +=2;
keydef->keylength = mi_uint2korr(ptr); ptr +=2;
@@ -951,9 +1004,9 @@ char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
** mi_keyseg
***************************************************************************/
-int mi_keyseg_write(File file, const MI_KEYSEG *keyseg)
+int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
{
- uchar buff[MI_KEYSEG_SIZE];
+ uchar buff[HA_KEYSEG_SIZE];
uchar *ptr=buff;
*ptr++ =keyseg->type;
@@ -971,7 +1024,7 @@ int mi_keyseg_write(File file, const MI_KEYSEG *keyseg)
}
-char *mi_keyseg_read(char *ptr, MI_KEYSEG *keyseg)
+char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg)
{
keyseg->type = *ptr++;
keyseg->language = *ptr++;
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 70694bf4620..4b98b48199a 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -20,6 +20,7 @@
*/
#include "myisamdef.h"
+#include "rt_index.h"
static ha_rows _mi_record_pos(MI_INFO *info,const byte *key,uint key_len,
enum ha_rkey_function search_flag);
@@ -39,7 +40,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
const byte *end_key, uint end_key_len,
enum ha_rkey_function end_search_flag)
{
- ha_rows start_pos,end_pos;
+ ha_rows start_pos,end_pos,res;
DBUG_ENTER("mi_records_in_range");
if ((inx = _mi_check_index(info,inx)) < 0)
@@ -50,20 +51,39 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
if (info->s->concurrent_insert)
rw_rdlock(&info->s->key_root_lock[inx]);
- start_pos= (start_key ?
+
+ switch(info->s->keyinfo[inx].key_alg){
+ case HA_KEY_ALG_RTREE:
+ {
+ uchar * key_buff;
+ if (start_key_len == 0)
+ start_key_len=USE_WHOLE_KEY;
+ key_buff=info->lastkey+info->s->base.max_key_length;
+ start_key_len=_mi_pack_key(info,inx,key_buff,(uchar*) start_key,start_key_len);
+ res=rtree_estimate(info, inx, key_buff, start_key_len, myisam_read_vec[start_search_flag]);
+ res=res?res:1;
+ break;
+ }
+ case HA_KEY_ALG_BTREE:
+ default:
+ start_pos= (start_key ?
_mi_record_pos(info,start_key,start_key_len,start_search_flag) :
(ha_rows) 0);
- end_pos= (end_key ?
+ end_pos= (end_key ?
_mi_record_pos(info,end_key,end_key_len,end_search_flag) :
info->state->records+ (ha_rows) 1);
+ res=end_pos < start_pos ? (ha_rows) 0 :
+ (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos);
+ if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
+ res=HA_POS_ERROR;
+ }
+
if (info->s->concurrent_insert)
rw_unlock(&info->s->key_root_lock[inx]);
fast_mi_writeinfo(info);
- if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
- DBUG_RETURN(HA_POS_ERROR);
- DBUG_PRINT("info",("records: %ld",(ulong) (end_pos-start_pos)));
- DBUG_RETURN(end_pos < start_pos ? (ha_rows) 0 :
- (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
+
+ DBUG_PRINT("info",("records: %ld",(ulong) (res)));
+ DBUG_RETURN(res);
}
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 86547d3ef04..4a3c76809e8 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -17,7 +17,7 @@
/* Read record based on a key */
#include "myisamdef.h"
-
+#include "rt_index.h"
/* Read a record using key */
/* Ordinary search_flag is 0 ; Give error if no record with key */
@@ -36,8 +36,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
DBUG_RETURN(my_errno);
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
+ info->last_key_func=search_flag;
- if (!info->use_packed_key)
+ if (info->once_flags & USE_PACKED_KEYS)
+ {
+ /* key is already packed! */
+ key_buff=info->lastkey+info->s->base.max_key_length;
+ info->last_rkey_length=pack_key_length=key_len;
+ bmove(key_buff,key,key_len);
+ info->once_flags&= ~USE_PACKED_KEYS;
+ }
+ else
{
if (key_len == 0)
key_len=USE_WHOLE_KEY;
@@ -47,13 +56,6 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg,
key_buff,pack_key_length););
}
- else
- {
- /* key is already packed! */
- key_buff=info->lastkey+info->s->base.max_key_length;
- info->last_rkey_length=pack_key_length=key_len;
- bmove(key_buff,key,key_len);
- }
if (fast_mi_readinfo(info))
goto err;
@@ -65,22 +67,33 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
use_key_length=USE_WHOLE_KEY;
- if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
+ switch(info->s->keyinfo[inx].key_alg){
+ case HA_KEY_ALG_RTREE:
+ if(rtree_find_first(info,inx,key_buff,use_key_length,nextflag)<0)
+ {
+ my_errno=HA_ERR_CRASHED;
+ goto err;
+ }
+ break;
+ case HA_KEY_ALG_BTREE:
+ default:
+ if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
myisam_read_vec[search_flag],info->s->state.key_root[inx]))
- {
- while (info->lastpos >= info->state->data_file_length)
{
- /*
- Skip rows that are inserted by other threads since we got a lock
- Note that this can only happen if we are not searching after an
- exact key, because the keys are sorted according to position
- */
-
- if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
+ while (info->lastpos >= info->state->data_file_length)
+ {
+ /*
+ Skip rows that are inserted by other threads since we got a lock
+ Note that this can only happen if we are not searching after an
+ exact key, because the keys are sorted according to position
+ */
+
+ if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
info->lastkey_length,
myisam_readnext_vec[search_flag],
info->s->state.key_root[inx]))
- break;
+ break;
+ }
}
}
if (share->concurrent_insert)
diff --git a/myisam/mi_rnext.c b/myisam/mi_rnext.c
index 6d135462f96..e1cf916d6d9 100644
--- a/myisam/mi_rnext.c
+++ b/myisam/mi_rnext.c
@@ -16,6 +16,8 @@
#include "myisamdef.h"
+#include "rt_index.h"
+
/*
Read next row with the same key as previous read
One may have done a write, update or delete of the previous row.
@@ -42,27 +44,55 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
changed=_mi_test_if_changed(info);
if (!flag)
{
- error=_mi_search_first(info,info->s->keyinfo+inx,
+ switch(info->s->keyinfo[inx].key_alg){
+ case HA_KEY_ALG_RTREE:
+ error=rtree_get_first(info,inx,info->lastkey_length);
+ break;
+ case HA_KEY_ALG_BTREE:
+ default:
+ error=_mi_search_first(info,info->s->keyinfo+inx,
info->s->state.key_root[inx]);
+ break;
+ }
}
- else if (!changed)
- error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
- info->lastkey_length,flag,
- info->s->state.key_root[inx]);
else
- error=_mi_search(info,info->s->keyinfo+inx,info->lastkey,
- USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
-
- if (!error)
{
- while (info->lastpos >= info->state->data_file_length)
+ switch(info->s->keyinfo[inx].key_alg)
{
- /* Skip rows that are inserted by other threads since we got a lock */
- if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
- info->lastkey_length,
- SEARCH_BIGGER,
- info->s->state.key_root[inx])))
- break;
+ case HA_KEY_ALG_RTREE:
+ /*
+ Note that rtree doesn't support that the table
+ may be changed since last call, so we do need
+ to skip rows inserted by other threads like in btree
+ */
+ error=rtree_get_next(info,inx,info->lastkey_length);
+ break;
+
+ case HA_KEY_ALG_BTREE:
+ default:
+ if (!changed)
+ {
+ error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
+ info->lastkey_length,flag,
+ info->s->state.key_root[inx]);
+ }
+ else
+ {
+ error=_mi_search(info,info->s->keyinfo+inx,info->lastkey,
+ USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
+ }
+ if (!error && info->s->concurrent_insert)
+ {
+ while (info->lastpos >= info->state->data_file_length)
+ {
+ /* Skip rows that are inserted by other threads since we got a lock */
+ if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
+ info->lastkey_length,
+ SEARCH_BIGGER,
+ info->s->state.key_root[inx])))
+ break;
+ }
+ }
}
}
diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c
index a9d1953323c..200e715bddc 100644
--- a/myisam/mi_rnext_same.c
+++ b/myisam/mi_rnext_same.c
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "myisamdef.h"
+#include "rt_index.h"
/*
Read next row with the same key as previous read, but abort if
@@ -37,26 +38,39 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
if (fast_mi_readinfo(info))
DBUG_RETURN(my_errno);
- memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
if (info->s->concurrent_insert)
rw_rdlock(&info->s->key_root_lock[inx]);
- for (;;)
+
+ switch(keyinfo->key_alg)
{
- if ((error=_mi_search_next(info,keyinfo,info->lastkey,
+ case HA_KEY_ALG_RTREE:
+ if((error=rtree_find_next(info,inx,myisam_read_vec[info->last_key_func])))
+ {
+ /* FIXME: What to do?*/
+ }
+ break;
+ case HA_KEY_ALG_BTREE:
+ default:
+
+ memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
+ for (;;)
+ {
+ if ((error=_mi_search_next(info,keyinfo,info->lastkey,
info->lastkey_length,SEARCH_BIGGER,
info->s->state.key_root[inx])))
- break;
- if (_mi_key_cmp(keyinfo->seg,info->lastkey2,info->lastkey,
+ break;
+ if (ha_key_cmp(keyinfo->seg,info->lastkey2,info->lastkey,
info->last_rkey_length, SEARCH_FIND, &not_used))
- {
- error=1;
- my_errno=HA_ERR_END_OF_FILE;
- info->lastpos= HA_OFFSET_ERROR;
- break;
- }
- /* Skip rows that are inserted by other threads since we got a lock */
- if (info->lastpos < info->state->data_file_length)
- break;
+ {
+ error=1;
+ my_errno=HA_ERR_END_OF_FILE;
+ info->lastpos= HA_OFFSET_ERROR;
+ break;
+ }
+ /* Skip rows that are inserted by other threads since we got a lock */
+ if (info->lastpos < info->state->data_file_length)
+ break;
+ }
}
if (info->s->concurrent_insert)
rw_unlock(&info->s->key_root_lock[inx]);
diff --git a/myisam/mi_rrnd.c b/myisam/mi_rrnd.c
index f8009441cff..29f686b0456 100644
--- a/myisam/mi_rrnd.c
+++ b/myisam/mi_rrnd.c
@@ -46,7 +46,10 @@ int mi_rrnd(MI_INFO *info, byte *buf, register my_off_t filepos)
filepos= info->nextpos;
}
- info->lastinx= -1; /* Can't forward or backward */
+ if (info->once_flags & RRND_PRESERVE_LASTINX)
+ info->once_flags&= ~RRND_PRESERVE_LASTINX;
+ else
+ info->lastinx= -1; /* Can't forward or backward */
/* Init all but update-flag */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 41d53e76241..04803d7a901 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -132,8 +132,8 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (_mi_get_prev_key(info,keyinfo, buff, info->lastkey, keypos,
&info->lastkey_length))
goto err;
- if ((nextflag & SEARCH_LAST) &&
- _mi_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
+ if (!(nextflag & SEARCH_SMALLER) &&
+ ha_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
&not_used))
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
@@ -191,7 +191,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
while (start != end)
{
mid= (start+end)/2;
- if ((flag=_mi_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
+ if ((flag=ha_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
comp_flag,&not_used))
>= 0)
end=mid;
@@ -199,7 +199,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
start=mid+1;
}
if (mid != start)
- flag=_mi_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
+ flag=ha_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
comp_flag,&not_used);
if (flag < 0)
start++; /* point at next, bigger key */
@@ -239,7 +239,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
length,page,end));
DBUG_RETURN(MI_FOUND_WRONG_KEY);
}
- if ((flag=_mi_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
+ if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
&not_used)) >= 0)
break;
#ifdef EXTRA_DEBUG
@@ -263,7 +263,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
/*
my_flag is raw comparison result to be changed according to
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
- flag is the value returned by _mi_key_cmp and as treated as final
+ flag is the value returned by ha_key_cmp and as treated as final
*/
int flag=0, my_flag=-1;
uint nod_flag, length, len, matched, cmplen, kseg_len;
@@ -353,7 +353,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,suffix_len,vseg));
{
uchar *from=vseg+suffix_len;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
uint l;
for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
@@ -425,7 +425,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
else if (key_len_left>0)
{
uint not_used;
- if ((flag = _mi_key_cmp(keyinfo->seg+1,vseg,
+ if ((flag = ha_key_cmp(keyinfo->seg+1,vseg,
k,key_len_left,nextflag,&not_used)) >= 0)
break;
}
@@ -653,414 +653,6 @@ void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
} /* _mi_dpointer */
-int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
- uchar *b, uint b_length, my_bool part_key)
-{
- int flag;
-
-#ifdef USE_STRCOLL
- if (use_strcoll(charset_info))
- {
- if (part_key && b_length < a_length)
- a_length=b_length;
- return my_strnncoll(charset_info, a, a_length, b, b_length);
- }
- else
-#endif
- {
- uint length= min(a_length,b_length);
- uchar *end= a+ length;
- uchar *sort_order=charset_info->sort_order;
- while (a < end)
- if ((flag= (int) sort_order[*a++] - (int) sort_order[*b++]))
- return flag;
- }
- if (part_key && b_length < a_length)
- return 0;
- return (int) (a_length-b_length);
-}
-
-
-static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
- my_bool part_key)
-{
- uint length= min(a_length,b_length);
- uchar *end= a+ length;
- int flag;
-
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return flag;
- if (part_key && b_length < a_length)
- return 0;
- return (int) (a_length-b_length);
-}
-
-
-/*
- Compare two keys
-
- SYNOPSIS
- _mi_key_cmp()
- keyseg Key segments of key to compare
- a First key to compare, in format from _mi_pack_key()
- This is normally key specified by user
- b Second key to compare. This is always from a row
- key_length Length of key to compare. This can be shorter than
- a to just compare sub keys
- next_flag How keys should be compared
- If bit SEARCH_FIND is not set the keys includes the row
- position and this should also be compared
-
- NOTES
- Number-keys can't be splited
-
- RETURN VALUES
- <0 If a < b
- 0 If a == b
- >0 If a > b
-*/
-
-#define FCMP(A,B) ((int) (A) - (int) (B))
-
-int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
- register uchar *b, uint key_length, uint nextflag,
- uint *diff_pos)
-{
- int flag;
- int16 s_1,s_2;
- int32 l_1,l_2;
- uint32 u_1,u_2;
- float f_1,f_2;
- double d_1,d_2;
- uint next_key_length;
-
- *diff_pos=0;
- for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
- {
- uchar *end;
- uint piks=! (keyseg->flag & HA_NO_SORT);
- (*diff_pos)++;
-
- /* Handle NULL part */
- if (keyseg->null_bit)
- {
- key_length--;
- if (*a != *b && piks)
- {
- flag = (int) *a - (int) *b;
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- b++;
- if (!*a++) /* If key was NULL */
- {
- if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
- nextflag=SEARCH_SAME; /* Allow duplicate keys */
- else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
- {
- /*
- This is only used from mi_check() to calculate cardinality.
- It can't be used when searching for a key as this would cause
- compare of (a,b) and (b,a) to return the same value.
- */
- return -1;
- }
- next_key_length=key_length;
- continue; /* To next key part */
- }
- }
- end= a+ min(keyseg->length,key_length);
- next_key_length=key_length-keyseg->length;
-
- switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
- if (keyseg->flag & HA_SPACE_PACK)
- {
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if (piks &&
- (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
- }
- else
- {
- uint length=(uint) (end-a), a_length=length, b_length=length;
- if (!(nextflag & SEARCH_PREFIX))
- {
- while (a_length && a[a_length-1] == ' ')
- a_length--;
- while (b_length && b[b_length-1] == ' ')
- b_length--;
- }
- if (piks &&
- (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a=end;
- b+=length;
- }
- break;
- case HA_KEYTYPE_BINARY:
- if (keyseg->flag & HA_SPACE_PACK)
- {
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if (piks &&
- (flag=compare_bin(a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
- }
- else
- {
- uint length=keyseg->length;
- if (piks &&
- (flag=compare_bin(a,length,b,length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=length;
- b+=length;
- }
- break;
- case HA_KEYTYPE_VARTEXT:
- {
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if (piks &&
- (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
- }
- break;
- case HA_KEYTYPE_VARBINARY:
- {
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if (piks &&
- (flag=compare_bin(a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
- }
- break;
- case HA_KEYTYPE_INT8:
- {
- int i_1= (int) *((signed char*) a);
- int i_2= (int) *((signed char*) b);
- if (piks && (flag = CMP_NUM(i_1,i_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b++;
- break;
- }
- case HA_KEYTYPE_SHORT_INT:
- s_1= mi_sint2korr(a);
- s_2= mi_sint2korr(b);
- if (piks && (flag = CMP_NUM(s_1,s_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 2; /* sizeof(short int); */
- break;
- case HA_KEYTYPE_USHORT_INT:
- {
- uint16 us_1,us_2;
- us_1= mi_sint2korr(a);
- us_2= mi_sint2korr(b);
- if (piks && (flag = CMP_NUM(us_1,us_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+=2; /* sizeof(short int); */
- break;
- }
- case HA_KEYTYPE_LONG_INT:
- l_1= mi_sint4korr(a);
- l_2= mi_sint4korr(b);
- if (piks && (flag = CMP_NUM(l_1,l_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(long int); */
- break;
- case HA_KEYTYPE_ULONG_INT:
- u_1= mi_sint4korr(a);
- u_2= mi_sint4korr(b);
- if (piks && (flag = CMP_NUM(u_1,u_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(long int); */
- break;
- case HA_KEYTYPE_INT24:
- l_1=mi_sint3korr(a);
- l_2=mi_sint3korr(b);
- if (piks && (flag = CMP_NUM(l_1,l_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 3;
- break;
- case HA_KEYTYPE_UINT24:
- l_1=mi_uint3korr(a);
- l_2=mi_uint3korr(b);
- if (piks && (flag = CMP_NUM(l_1,l_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 3;
- break;
- case HA_KEYTYPE_FLOAT:
- mi_float4get(f_1,a);
- mi_float4get(f_2,b);
- if (piks && (flag = CMP_NUM(f_1,f_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(float); */
- break;
- case HA_KEYTYPE_DOUBLE:
- mi_float8get(d_1,a);
- mi_float8get(d_2,b);
- if (piks && (flag = CMP_NUM(d_1,d_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 8; /* sizeof(double); */
- break;
- case HA_KEYTYPE_NUM: /* Numeric key */
- {
- int swap_flag= 0;
- int alength,blength;
-
- if (keyseg->flag & HA_REVERSE_SORT)
- {
- swap(uchar*,a,b);
- swap_flag=1; /* Remember swap of a & b */
- end= a+ (int) (end-b);
- }
- if (keyseg->flag & HA_SPACE_PACK)
- {
- alength= *a++; blength= *b++;
- end=a+alength;
- next_key_length=key_length-blength-1;
- }
- else
- {
- alength= (int) (end-a);
- blength=keyseg->length;
- /* remove pre space from keys */
- for ( ; alength && *a == ' ' ; a++, alength--) ;
- for ( ; blength && *b == ' ' ; b++, blength--) ;
- }
- if (piks)
- {
- if (*a == '-')
- {
- if (*b != '-')
- return -1;
- a++; b++;
- swap(uchar*,a,b);
- swap(int,alength,blength);
- swap_flag=1-swap_flag;
- alength--; blength--;
- end=a+alength;
- }
- else if (*b == '-')
- return 1;
- while (alength && (*a == '+' || *a == '0'))
- {
- a++; alength--;
- }
- while (blength && (*b == '+' || *b == '0'))
- {
- b++; blength--;
- }
- if (alength != blength)
- return (alength < blength) ? -1 : 1;
- while (a < end)
- if (*a++ != *b++)
- return ((int) a[-1] - (int) b[-1]);
- }
- else
- {
- b+=(end-a);
- a=end;
- }
-
- if (swap_flag) /* Restore pointers */
- swap(uchar*,a,b);
- break;
- }
-#ifdef HAVE_LONG_LONG
- case HA_KEYTYPE_LONGLONG:
- {
- longlong ll_a,ll_b;
- ll_a= mi_sint8korr(a);
- ll_b= mi_sint8korr(b);
- if (piks && (flag = CMP_NUM(ll_a,ll_b)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 8;
- break;
- }
- case HA_KEYTYPE_ULONGLONG:
- {
- ulonglong ll_a,ll_b;
- ll_a= mi_uint8korr(a);
- ll_b= mi_uint8korr(b);
- if (piks && (flag = CMP_NUM(ll_a,ll_b)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 8;
- break;
- }
-#endif
- case HA_KEYTYPE_END: /* Ready */
- goto end; /* diff_pos is incremented */
- }
- }
- (*diff_pos)++;
-end:
- if (!(nextflag & SEARCH_FIND))
- {
- uint i;
- if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
- return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
- flag=0;
- for (i=keyseg->length ; i-- > 0 ; )
- {
- if (*a++ != *b++)
- {
- flag= FCMP(a[-1],b[-1]);
- break;
- }
- }
- if (nextflag & SEARCH_SAME)
- return (flag); /* read same */
- if (nextflag & SEARCH_BIGGER)
- return (flag <= 0 ? -1 : 1); /* read next */
- return (flag < 0 ? -1 : 1); /* read previous */
- }
- return 0;
-} /* _mi_key_cmp */
-
-
/* Get key from key-block */
/* page points at previous key; its advanced to point at next key */
/* key should contain previous key */
@@ -1084,7 +676,7 @@ uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
register uchar **page_pos, register uchar *key)
{
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
uchar *start_key,*page=*page_pos;
uint length;
@@ -1217,7 +809,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
register uchar **page_pos, register uchar *key)
{
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
uchar *start_key,*page=*page_pos,*page_end,*from,*from_end;
uint length,tmp;
@@ -1416,7 +1008,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
{
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
uchar *start;
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
@@ -1682,7 +1274,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
uchar *org_key, uchar *prev_key, uchar *key,
MI_KEY_PARAM *s_temp)
{
- reg1 MI_KEYSEG *keyseg;
+ reg1 HA_KEYSEG *keyseg;
int length;
uint key_length,ref_length,org_key_length=0,
length_pack,new_key_length,diff_flag,pack_marker;
@@ -1697,7 +1289,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
if ((keyinfo->flag & HA_FULLTEXT) &&
((keyseg->type == HA_KEYTYPE_TEXT) ||
(keyseg->type == HA_KEYTYPE_VARTEXT)) &&
- !use_strcoll(keyseg->charset))
+ !use_strnxfrm(keyseg->charset))
sort_order=keyseg->charset->sort_order;
/* diff flag contains how many bytes is needed to pack key */
diff --git a/myisam/mi_static.c b/myisam/mi_static.c
index 37b9ac04b7a..a36c38e3c01 100644
--- a/myisam/mi_static.c
+++ b/myisam/mi_static.c
@@ -51,11 +51,12 @@ uint NEAR myisam_read_vec[]=
{
SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
- SEARCH_FIND | SEARCH_PREFIX, SEARCH_LAST
+ SEARCH_FIND | SEARCH_PREFIX, SEARCH_LAST, SEARCH_LAST | SEARCH_SMALLER,
+ MBR_CONTAIN, MBR_INTERSECT, MBR_WITHIN, MBR_DISJOINT, MBR_EQUAL
};
uint NEAR myisam_readnext_vec[]=
{
SEARCH_BIGGER, SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_BIGGER, SEARCH_SMALLER,
- SEARCH_BIGGER, SEARCH_SMALLER
+ SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_SMALLER
};
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index 8ea97c8e489..6aa4b9cf9f1 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -36,8 +36,8 @@ static my_bool key_cacheing, null_fields, silent, skip_update, opt_unique,
verbose;
static MI_COLUMNDEF recinfo[4];
static MI_KEYDEF keyinfo[10];
-static MI_KEYSEG keyseg[10];
-static MI_KEYSEG uniqueseg[10];
+static HA_KEYSEG keyseg[10];
+static HA_KEYSEG uniqueseg[10];
static int run_test(const char *filename);
static void get_options(int argc, char *argv[]);
@@ -92,6 +92,7 @@ static int run_test(const char *filename)
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= pack_seg;
keyinfo[0].seg[0].start=1;
@@ -460,19 +461,19 @@ static void update_record(char *record)
ptr=blob_key;
memcpy_fixed(pos+4,&ptr,sizeof(char*)); /* Store pointer to new key */
if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
- casedn(blob_key,length);
+ my_casedn(default_charset_info,blob_key,length);
pos+=recinfo[1].length;
}
else if (recinfo[1].type == FIELD_VARCHAR)
{
uint length=uint2korr(pos);
- casedn(pos+2,length);
+ my_casedn(default_charset_info,pos+2,length);
pos+=recinfo[1].length;
}
else
{
if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
- casedn(pos,keyinfo[0].seg[0].length);
+ my_casedn(default_charset_info,pos,keyinfo[0].seg[0].length);
pos+=recinfo[1].length;
}
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index 93538e3ead7..b5da87355c6 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -55,7 +55,7 @@ static uint use_blob=0;
static uint16 key1[1001],key3[5000];
static char record[300],record2[300],key[100],key2[100],
read_record[300],read_record2[300],read_record3[300];
-static MI_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
+static HA_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
/* Test program */
@@ -91,6 +91,7 @@ int main(int argc, char *argv[])
keyinfo[0].seg[0].flag=(uint8) pack_seg;
keyinfo[0].seg[0].null_bit=0;
keyinfo[0].seg[0].null_pos=0;
+ keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].keysegs=1;
keyinfo[0].flag = pack_type;
keyinfo[1].seg= &glob_keyseg[1][0];
@@ -106,6 +107,7 @@ int main(int argc, char *argv[])
keyinfo[1].seg[1].flag=HA_REVERSE_SORT;
keyinfo[1].seg[1].null_bit=0;
keyinfo[1].seg[1].null_pos=0;
+ keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
keyinfo[1].keysegs=2;
keyinfo[1].flag =0;
keyinfo[2].seg= &glob_keyseg[2][0];
@@ -115,6 +117,7 @@ int main(int argc, char *argv[])
keyinfo[2].seg[0].flag=HA_REVERSE_SORT;
keyinfo[2].seg[0].null_bit=0;
keyinfo[2].seg[0].null_pos=0;
+ keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
keyinfo[2].keysegs=1;
keyinfo[2].flag =HA_NOSAME;
keyinfo[3].seg= &glob_keyseg[3][0];
@@ -125,6 +128,7 @@ int main(int argc, char *argv[])
keyinfo[3].seg[0].flag=(uint8) pack_seg;
keyinfo[3].seg[0].null_bit=0;
keyinfo[3].seg[0].null_pos=0;
+ keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
keyinfo[3].keysegs=1;
keyinfo[3].flag = pack_type;
keyinfo[4].seg= &glob_keyseg[4][0];
@@ -135,6 +139,7 @@ int main(int argc, char *argv[])
keyinfo[4].seg[0].flag=0;
keyinfo[4].seg[0].null_bit=0;
keyinfo[4].seg[0].null_pos=0;
+ keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
keyinfo[4].keysegs=1;
keyinfo[4].flag = pack_type;
keyinfo[5].seg= &glob_keyseg[5][0];
@@ -145,6 +150,7 @@ int main(int argc, char *argv[])
keyinfo[5].seg[0].flag=pack_seg;
keyinfo[5].seg[0].null_bit=0;
keyinfo[5].seg[0].null_pos=0;
+ keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
keyinfo[5].keysegs=1;
keyinfo[5].flag = pack_type;
@@ -1013,7 +1019,7 @@ static void put_blob_in_record(char *blob_pos, char **blob_buffer)
static void copy_key(MI_INFO *info,uint inx,uchar *rec,uchar *key_buff)
{
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
for (keyseg=info->s->keyinfo[inx].seg ; keyseg->type ; keyseg++)
{
diff --git a/myisam/mi_test3.c b/myisam/mi_test3.c
index 6111167b38f..defe041a99f 100644
--- a/myisam/mi_test3.c
+++ b/myisam/mi_test3.c
@@ -61,7 +61,7 @@ int main(int argc,char **argv)
uint i=0;
MI_KEYDEF keyinfo[10];
MI_COLUMNDEF recinfo[10];
- MI_KEYSEG keyseg[10][2];
+ HA_KEYSEG keyseg[10][2];
MY_INIT(argv[0]);
get_options(argc,argv);
@@ -72,6 +72,7 @@ int main(int argc,char **argv)
keyinfo[0].seg[0].length=8;
keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
keyinfo[0].seg[0].flag=HA_SPACE_PACK;
+ keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].keysegs=1;
keyinfo[0].flag = (uint8) HA_PACK_KEY;
keyinfo[1].seg= &keyseg[1][0];
@@ -79,6 +80,7 @@ int main(int argc,char **argv)
keyinfo[1].seg[0].length=4; /* Long is always 4 in myisam */
keyinfo[1].seg[0].type=HA_KEYTYPE_LONG_INT;
keyinfo[1].seg[0].flag=0;
+ keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
keyinfo[1].keysegs=1;
keyinfo[1].flag =HA_NOSAME;
diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c
index ddba40214e7..3eb25aefe0e 100644
--- a/myisam/mi_unique.c
+++ b/myisam/mi_unique.c
@@ -70,7 +70,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
{
const byte *pos, *end;
ha_checksum crc=0;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
@@ -108,11 +108,9 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
- uchar *sort_order=keyseg->charset->sort_order;
- while (pos != end)
- crc=((crc << 8) +
- (((uchar) sort_order[*(uchar*) pos++]))) +
- (crc >> (8*sizeof(ha_checksum)-8));
+ ulong nr=1, nr2=4;
+ keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2);
+ crc=nr;
}
else
while (pos != end)
@@ -131,7 +129,7 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
my_bool null_are_equal)
{
const byte *pos_a, *pos_b, *end;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
@@ -181,8 +179,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
}
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
- if (_mi_compare_text(keyseg->charset, (uchar *)pos_a, length,
- (uchar *)pos_b, length, 0))
+ if (mi_compare_text(keyseg->charset, (uchar *) pos_a, length,
+ (uchar *) pos_b, length, 0))
return 1;
}
else
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index 1614d6ca19d..53c09a1d35c 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -17,6 +17,8 @@
/* Update an old row in a MyISAM table */
#include "fulltext.h"
+#include "rt_index.h"
+
#ifdef __WIN__
#include <errno.h>
#endif
@@ -61,6 +63,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
goto err_end; /* Record has changed */
}
+
/* Calculate and check all unique constraints */
key_changed=0;
for (i=0 ; i < share->state.header.uniques ; i++)
@@ -88,7 +91,6 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
{
if (((ulonglong) 1 << i) & share->state.key_map)
{
- /* The following code block is for text searching by SerG */
if (share->keyinfo[i].flag & HA_FULLTEXT )
{
if (_mi_ft_cmp(info,i,oldrec, newrec))
@@ -111,8 +113,8 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */
changed|=((ulonglong) 1 << i);
share->keyinfo[i].version++;
- if (_mi_ck_delete(info,i,old_key,old_length)) goto err;
- if (_mi_ck_write(info,i,new_key,new_length)) goto err;
+ if (share->keyinfo[i].ck_delete(info,i,old_key,old_length)) goto err;
+ if (share->keyinfo[i].ck_insert(info,i,new_key,new_length)) goto err;
if (share->base.auto_key == i+1)
auto_key_changed=1;
}
@@ -172,7 +174,6 @@ err:
{
if (((ulonglong) 1 << i) & changed)
{
- /* The following code block is for text searching by SerG */
if (share->keyinfo[i].flag & HA_FULLTEXT)
{
if ((flag++ && _mi_ft_del(info,i,(char*) new_key,newrec,pos)) ||
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index d39bbbf5fc7..59b4f0d29c3 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -17,6 +17,8 @@
/* Write a row to a MyISAM table */
#include "fulltext.h"
+#include "rt_index.h"
+
#ifdef __WIN__
#include <errno.h>
#endif
@@ -36,9 +38,9 @@ static int _mi_balance_page(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uint *return_key_length,
uchar **after_key);
-int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
+int _mi_ck_write_tree(register MI_INFO *info, uint keynr,uchar *key,
uint key_length);
-int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
+int _mi_ck_write_btree(register MI_INFO *info, uint keynr,uchar *key,
uint key_length);
/* Write new record to database */
@@ -121,17 +123,17 @@ int mi_write(MI_INFO *info, byte *record)
}
else
{
- uint key_length=_mi_make_key(info,i,buff,record,filepos);
- if (_mi_ck_write(info,i,buff,key_length))
- {
- if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
- DBUG_PRINT("error",("Got error: %d on write",my_errno));
- goto err;
- }
+ if (share->keyinfo[i].ck_insert(info,i,buff,
+ _mi_make_key(info,i,buff,record,filepos)))
+ {
+ if (local_lock_tree)
+ rw_unlock(&share->key_root_lock[i]);
+ DBUG_PRINT("error",("Got error: %d on write",my_errno));
+ goto err;
+ }
}
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&share->key_root_lock[i]);
}
}
if (share->calc_checksum)
@@ -248,11 +250,12 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
int error;
uint comp_flag;
MI_KEYDEF *keyinfo=info->s->keyinfo+keynr;
+ my_off_t *root=&info->s->state.key_root[keynr];
DBUG_ENTER("_mi_ck_write_btree");
if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
comp_flag=SEARCH_BIGGER; /* Put after same key */
- else if (keyinfo->flag & HA_NOSAME)
+ else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
{
comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
@@ -261,37 +264,34 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
else
comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
- if (info->s->state.key_root[keynr] == HA_OFFSET_ERROR ||
+ if (*root == HA_OFFSET_ERROR ||
(error=w_search(info, keyinfo, comp_flag, key, key_length,
- info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0,
+ *root, (uchar *) 0, (uchar*) 0,
(my_off_t) 0, 1)) > 0)
- error=_mi_enlarge_root(info,keynr,key);
+ error=_mi_enlarge_root(info,keyinfo,key,root);
DBUG_RETURN(error);
} /* _mi_ck_write_btree */
/* Make a new root with key as only pointer */
-int _mi_enlarge_root(register MI_INFO *info, uint keynr, uchar *key)
+int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ my_off_t *root)
{
uint t_length,nod_flag;
- reg2 MI_KEYDEF *keyinfo;
MI_KEY_PARAM s_temp;
MYISAM_SHARE *share=info->s;
DBUG_ENTER("_mi_enlarge_root");
- nod_flag= (share->state.key_root[keynr] != HA_OFFSET_ERROR) ?
- share->base.key_reflength : 0;
- _mi_kpointer(info,info->buff+2,share->state.key_root[keynr]); /* if nod */
- keyinfo=share->keyinfo+keynr;
+ nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0;
+ _mi_kpointer(info,info->buff+2,*root); /* if nod */
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0,
(uchar*) 0, (uchar*) 0, key,&s_temp);
mi_putint(info->buff,t_length+2+nod_flag,nod_flag);
(*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
info->buff_used=info->page_changed=1; /* info->buff is used */
- if ((share->state.key_root[keynr]= _mi_new(info,keyinfo)) ==
- HA_OFFSET_ERROR ||
- _mi_write_keypage(info,keyinfo,share->state.key_root[keynr],info->buff))
+ if ((*root= _mi_new(info,keyinfo)) == HA_OFFSET_ERROR ||
+ _mi_write_keypage(info,keyinfo,*root,info->buff))
DBUG_RETURN(-1);
DBUG_RETURN(0);
} /* _mi_enlarge_root */
@@ -331,15 +331,54 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (flag == 0)
{
uint tmp_key_length;
- my_errno=HA_ERR_FOUND_DUPP_KEY;
/* get position to record with duplicated key */
tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
if (tmp_key_length)
info->dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
else
info->dupp_key_pos= HA_OFFSET_ERROR;
- my_afree((byte*) temp_buff);
- DBUG_RETURN(-1);
+ if (keyinfo->flag & HA_FULLTEXT)
+ {
+ uint off;
+ int subkeys;
+
+ get_key_full_length_rdonly(off, keybuff);
+ subkeys=ft_sintXkorr(keybuff+off);
+ comp_flag=SEARCH_SAME;
+ if (subkeys >= 0)
+ {
+ /* normal word, one-level tree structure */
+ flag=(*keyinfo->bin_search)(info, keyinfo, temp_buff, key,
+ USE_WHOLE_KEY, comp_flag,
+ &keypos, keybuff, &was_last_key);
+ }
+ else
+ {
+ /* popular word. two-level tree. going down */
+ my_off_t root=info->dupp_key_pos;
+ keyinfo=&info->s->ft2_keyinfo;
+ key+=off;
+ keypos-=keyinfo->keylength; /* we'll modify key entry 'in vivo' */
+ if ((error=w_search(info, keyinfo, comp_flag, key, HA_FT_WLEN, root,
+ (uchar *) 0, (uchar*) 0, (my_off_t) 0, 1)) > 0)
+ {
+ error=_mi_enlarge_root(info, keyinfo, key, &root);
+ _mi_dpointer(info, keypos+HA_FT_WLEN, root);
+ }
+ subkeys--; /* should there be underflow protection ? */
+ ft_intXstore(keypos, subkeys);
+ if (!error)
+ error=_mi_write_keypage(info,keyinfo,page,temp_buff);
+ my_afree((byte*) temp_buff);
+ DBUG_RETURN(error);
+ }
+ }
+ else /* not HA_FULLTEXT, normal HA_NOSAME key */
+ {
+ my_afree((byte*) temp_buff);
+ my_errno=HA_ERR_FOUND_DUPP_KEY;
+ DBUG_RETURN(-1);
+ }
}
if (flag == MI_FOUND_WRONG_KEY)
DBUG_RETURN(-1);
@@ -392,7 +431,9 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
#ifndef DBUG_OFF
if (key_pos != anc_buff+2+nod_flag && (keyinfo->flag &
(HA_BINARY_PACK_KEY | HA_PACK_KEY)))
+ {
DBUG_DUMP("prev_key",(byte*) key_buff,_mi_keylength(keyinfo,key_buff));
+ }
if (keyinfo->flag & HA_PACK_KEY)
{
DBUG_PRINT("test",("t_length: %d ref_len: %d",
@@ -751,7 +792,8 @@ int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
DBUG_ENTER("_mi_ck_write_tree");
error= tree_insert(&info->bulk_insert[keynr], key,
- key_length + info->s->rec_reflength) ? 0 : HA_ERR_OUT_OF_MEM ;
+ key_length + info->s->rec_reflength,
+ info->bulk_insert[keynr].custom_arg) ? 0 : HA_ERR_OUT_OF_MEM ;
DBUG_RETURN(error);
} /* _mi_ck_write_tree */
@@ -762,7 +804,7 @@ int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2)
{
uint not_used;
- return _mi_key_cmp(param->info->s->keyinfo[param->keynr].seg,
+ return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg,
key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
&not_used);
}
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 6c541a444b7..0a5aa889a1a 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -41,9 +41,10 @@ SET_STACK_SIZE(9000) /* Minimum stack size for program */
static uint decode_bits;
static char **default_argv;
static const char *load_default_groups[]= { "myisamchk", 0 };
-static const char *set_charset_name;
+static const char *set_charset_name, *opt_tmpdir;
static CHARSET_INFO *set_charset;
static long opt_myisam_block_size;
+static MY_TMPDIR myisamchk_tmpdir;
static const char *type_names[]=
{ "?","char","binary", "short", "long", "float",
@@ -133,6 +134,7 @@ int main(int argc, char **argv)
llstr(check_param.total_deleted,buff2));
}
free_defaults(default_argv);
+ free_tmpdir(&myisamchk_tmpdir);
ft_free_stopwords();
my_end(check_param.testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
exit(error);
@@ -257,7 +259,7 @@ static struct my_option my_long_options[] =
0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"tmpdir", 't',
"Path for temporary files.",
- (gptr*) &check_param.tmpdir,
+ (gptr*) &opt_tmpdir,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"update-state", 'U',
"Mark tables as crashed if any errors were found.",
@@ -338,7 +340,15 @@ static void usage(void)
Change the value of a variable. Please note that\n\
this option is deprecated; you can set variables\n\
directly with '--variable-name=value'.\n\
- -t, --tmpdir=path Path for temporary files\n\
+ -t, --tmpdir=path Path for temporary files. Multiple paths can be\n\
+ specified, separated by "
+#if defined( __WIN__) || defined(OS2)
+ "semicolon (;)"
+#else
+ "colon (:)"
+#endif
+ ", they will be used\n\
+ in a round-robin fashion.\n\
-s, --silent Only print errors. One can use two -s to make\n\
myisamchk very silent\n\
-v, --verbose Print more information. This can be used with\n\
@@ -693,6 +703,11 @@ static void get_options(register int *argc,register char ***argv)
exit(1);
}
+ if (init_tmpdir(&myisamchk_tmpdir, opt_tmpdir))
+ exit(1);
+
+ check_param.tmpdir=&myisamchk_tmpdir;
+
if (set_charset_name)
if (!(set_charset=get_charset_by_name(set_charset_name, MYF(MY_WME))))
exit(1);
@@ -859,7 +874,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
}
else
{
- if (share->fulltext_index)
+ if (share->state.header.fulltext_keys)
ft_init_stopwords();
if (!(param->testflag & T_READONLY))
@@ -1107,7 +1122,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name)
{
uint key,keyseg_nr,field,start;
reg3 MI_KEYDEF *keyinfo;
- reg2 MI_KEYSEG *keyseg;
+ reg2 HA_KEYSEG *keyseg;
reg4 const char *text;
char buff[160],length[10],*pos,*end;
enum en_fieldtype type;
@@ -1622,6 +1637,10 @@ err:
DBUG_RETURN(1);
} /* sort_record_index */
+volatile bool *killed_ptr(MI_CHECK *param)
+{
+ return (bool *)(& param->thd); /* always NULL */
+}
/* print warnings and errors */
/* VARARGS */
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 92eead7b96c..ad07da12c12 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -55,7 +55,8 @@ typedef struct st_mi_state_info
uchar uniques; /* number of UNIQUE definitions */
uchar language; /* Language for indexes */
uchar max_block_size; /* max keyblock size */
- uchar not_used[2]; /* To align to 8 */
+ uchar fulltext_keys;
+ uchar not_used; /* To align to 8 */
} header;
MI_STATUS_INFO state;
@@ -90,13 +91,13 @@ typedef struct st_mi_state_info
} MI_STATE_INFO;
#define MI_STATE_INFO_SIZE (24+14*8+7*4+2*2+8)
-#define MI_STATE_KEY_SIZE 8
+#define MI_STATE_KEY_SIZE 8
#define MI_STATE_KEYBLOCK_SIZE 8
#define MI_STATE_KEYSEG_SIZE 4
#define MI_STATE_EXTRA_SIZE ((MI_MAX_KEY+MI_MAX_KEY_BLOCK_SIZE)*MI_STATE_KEY_SIZE + MI_MAX_KEY*MI_MAX_KEY_SEG*MI_STATE_KEYSEG_SIZE)
#define MI_KEYDEF_SIZE (2+ 5*2)
#define MI_UNIQUEDEF_SIZE (2+1+1)
-#define MI_KEYSEG_SIZE (6+ 2*2 + 4*2)
+#define HA_KEYSEG_SIZE (6+ 2*2 + 4*2)
#define MI_COLUMNDEF_SIZE (2*3+1)
#define MI_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16)
#define MI_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */
@@ -154,9 +155,10 @@ typedef struct st_mi_isam_pack {
typedef struct st_mi_isam_share { /* Shared between opens */
MI_STATE_INFO state;
MI_BASE_INFO base;
+ MI_KEYDEF ft2_keyinfo; /* Second-level ft-key definition */
MI_KEYDEF *keyinfo; /* Key definitions */
MI_UNIQUEDEF *uniqueinfo; /* unique definitions */
- MI_KEYSEG *keyparts; /* key part info */
+ HA_KEYSEG *keyparts; /* key part info */
MI_COLUMNDEF *rec; /* Pointer to field information */
MI_PACK pack; /* Data about packed records */
MI_BLOB *blobs; /* Pointer to blobs */
@@ -197,8 +199,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
global_changed, /* If changed since open */
not_flushed,
temporary,delay_key_write,
- concurrent_insert,
- fulltext_index;
+ concurrent_insert;
#ifdef THREAD
THR_LOCK lock;
pthread_mutex_t intern_lock; /* Locking for use with _locking */
@@ -229,6 +230,8 @@ struct st_myisam_info {
byte *rec_buff; /* Tempbuff for recordpack */
uchar *int_keypos, /* Save position for next/previous */
*int_maxpos; /* -""- */
+ uint int_nod_flag; /* -""- */
+ uint32 int_keytree_version; /* -""- */
int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
invalidator_by_filename invalidator; /* query cache invalidator */
ulong this_unique; /* uniq filenumber or thread */
@@ -247,10 +250,10 @@ struct st_myisam_info {
int dfile; /* The datafile */
uint opt_flag; /* Optim. for space/speed */
uint update; /* If file changed since open */
- uint int_nod_flag; /* -""- */
int lastinx; /* Last used index */
uint lastkey_length; /* Length of key in lastkey */
uint last_rkey_length; /* Last length in mi_rkey() */
+ enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */
uint save_lastkey_length;
int errkey; /* Got last error on this key */
int lock_type; /* How database was locked */
@@ -258,7 +261,6 @@ struct st_myisam_info {
uint data_changed; /* Somebody has changed data */
uint save_update; /* When using KEY_READ */
int save_lastinx;
- uint32 int_keytree_version; /* -""- */
LIST open_list;
IO_CACHE rec_cache; /* When cacheing records */
myf lock_wait; /* is 0 or MY_DONT_WAIT */
@@ -266,13 +268,49 @@ struct st_myisam_info {
my_bool quick_mode;
my_bool page_changed; /* If info->buff can't be used for rnext */
my_bool buff_used; /* If info->buff has to be reread for rnext */
- my_bool use_packed_key; /* For MYISAMMRG */
+ my_bool once_flags; /* For MYISAMMRG */
#ifdef THREAD
THR_LOCK_DATA lock;
#endif
+ uchar * rtree_recursion_state; /* For RTREE */
+ int rtree_recursion_depth;
};
+typedef struct st_buffpek {
+ my_off_t file_pos; /* Where we are in the sort file */
+ uchar *base,*key; /* Key pointers */
+ ha_rows count; /* Number of rows in table */
+ ulong mem_count; /* numbers of keys in memory */
+ ulong max_keys; /* Max keys in buffert */
+} BUFFPEK;
+typedef struct st_mi_sort_param
+{
+ pthread_t thr;
+ IO_CACHE read_cache, tempfile, tempfile_for_exceptions;
+ DYNAMIC_ARRAY buffpek;
+ ulonglong unique[MI_MAX_KEY_SEG+1];
+ my_off_t pos,max_pos,filepos,start_recpos;
+ uint key, key_length,real_key_length,sortbuff_size;
+ uint maxbuffers, keys, find_length, sort_keys_length;
+ my_bool fix_datafile, master;
+ MI_KEYDEF *keyinfo;
+ SORT_INFO *sort_info;
+ uchar **sort_keys;
+ byte *rec_buff;
+ void *wordlist, *wordptr;
+ char *record;
+ MY_TMPDIR *tmpdir;
+ int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *);
+ int (*key_read)(struct st_mi_sort_param *,void *);
+ int (*key_write)(struct st_mi_sort_param *, const void *);
+ void (*lock_in_memory)(MI_CHECK *);
+ NEAR int (*write_keys)(struct st_mi_sort_param *, register uchar **,
+ uint , struct st_buffpek *, IO_CACHE *);
+ NEAR uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint);
+ NEAR int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,char *,
+ uint, uint);
+} MI_SORT_PARAM;
/* Some defines used by isam-funktions */
#define USE_WHOLE_KEY MI_MAX_KEY_BUFF*2 /* Use whole key in _mi_search() */
@@ -285,6 +323,10 @@ struct st_myisam_info {
#define WRITEINFO_UPDATE_KEYFILE 1
#define WRITEINFO_NO_UNLOCK 2
+ /* once_flags */
+#define USE_PACKED_KEYS 1
+#define RRND_PRESERVE_LASTINX 2
+
/* bits in state.changed */
#define STATE_CHANGED 1
@@ -324,13 +366,6 @@ struct st_myisam_info {
{ *(key)=255; mi_int2store((key)+1,(length)); } \
}
-#define get_key_length(length,key) \
-{ if ((uchar) *(key) != 255) \
- length= (uint) (uchar) *((key)++); \
- else \
- { length=mi_uint2korr((key)+1); (key)+=3; } \
-}
-
#define get_key_full_length(length,key) \
{ if ((uchar) *(key) != 255) \
length= ((uint) (uchar) *((key)++))+1; \
@@ -338,11 +373,11 @@ struct st_myisam_info {
{ length=mi_uint2korr((key)+1)+3; (key)+=3; } \
}
-#define get_key_pack_length(length,length_pack,key) \
+#define get_key_full_length_rdonly(length,key) \
{ if ((uchar) *(key) != 255) \
- { length= (uint) (uchar) *((key)++); length_pack=1; }\
+ length= ((uint) (uchar) *((key)))+1; \
else \
- { length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
+ { length=mi_uint2korr((key)+1)+3; } \
}
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
@@ -365,10 +400,10 @@ struct st_myisam_info {
#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */
#define PACK_TYPE_SPACE_FIELDS 2
#define PACK_TYPE_ZERO_FILL 4
-#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from _mi_key_cmp */
+#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */
#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH)
-#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) ((((key_length+data_pointer+key_pointer)*4+key_pointer+2)/myisam_block_size+1)*myisam_block_size)
+#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/myisam_block_size+1)*myisam_block_size)
#define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */
#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */
@@ -428,7 +463,7 @@ extern int _mi_delete_static_record(MI_INFO *info);
extern int _mi_cmp_static_record(MI_INFO *info,const byte *record);
extern int _mi_read_rnd_static_record(MI_INFO*, byte *,my_off_t, my_bool);
extern int _mi_ck_write(MI_INFO *info,uint keynr,uchar *key,uint length);
-extern int _mi_enlarge_root(MI_INFO *info,uint keynr,uchar *key);
+extern int _mi_enlarge_root(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, my_off_t *root);
extern int _mi_insert(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
uchar *anc_buff,uchar *key_pos,uchar *key_buff,
uchar *father_buff, uchar *father_keypos,
@@ -483,14 +518,12 @@ extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
uchar *key,uint key_len,uint comp_flag,
uchar **ret_pos,uchar *buff, my_bool *was_last_key);
-extern int _mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
- my_bool);
extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key);
extern void _mi_kpointer(MI_INFO *info,uchar *buff,my_off_t pos);
extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag,uchar *after_key);
extern my_off_t _mi_rec_pos(MYISAM_SHARE *info, uchar *ptr);
extern void _mi_dpointer(MI_INFO *info, uchar *buff,my_off_t pos);
-extern int _mi_key_cmp(MI_KEYSEG *keyseg, uchar *a,uchar *b,
+extern int ha_key_cmp(HA_KEYSEG *keyseg, uchar *a,uchar *b,
uint key_length,uint nextflag,uint *diff_length);
extern uint _mi_get_static_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar * *page,
uchar *key);
@@ -537,7 +570,7 @@ extern my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *packpos);
extern int _mi_write_part_record(MI_INFO *info,my_off_t filepos,ulong length,
my_off_t next_filepos,byte **record,
ulong *reclength,int *flag);
-extern void _mi_print_key(FILE *stream,MI_KEYSEG *keyseg,const uchar *key,
+extern void _mi_print_key(FILE *stream,HA_KEYSEG *keyseg,const uchar *key,
uint length);
extern my_bool _mi_read_pack_info(MI_INFO *info,pbool fix_keys);
extern int _mi_read_pack_record(MI_INFO *info,my_off_t filepos,byte *buf);
@@ -627,8 +660,8 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state);
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead);
uint mi_base_info_write(File file, MI_BASE_INFO *base);
char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base);
-int mi_keyseg_write(File file, const MI_KEYSEG *keyseg);
-char *mi_keyseg_read(char *ptr, MI_KEYSEG *keyseg);
+int mi_keyseg_write(File file, const HA_KEYSEG *keyseg);
+char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg);
uint mi_keydef_write(File file, MI_KEYDEF *keydef);
char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef);
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *keydef);
@@ -659,15 +692,20 @@ int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
/* Functions needed by mi_check */
+volatile bool *killed_ptr(MI_CHECK *param);
void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_warning _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_info _VARARGS((MI_CHECK *param, const char *fmt,...));
int flush_pending_blocks(MI_SORT_PARAM *param);
+int sort_ft_buf_flush(MI_SORT_PARAM *sort_param);
int thr_write_keys(MI_SORT_PARAM *sort_param);
#ifdef THREAD
pthread_handler_decl(thr_find_all_keys,arg);
#endif
+int sort_write_record(MI_SORT_PARAM *sort_param);
+int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong);
+
#ifdef __cplusplus
}
#endif
diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c
index ceca8d2a0e3..d7fb3f24b85 100644
--- a/myisam/myisamlog.c
+++ b/myisam/myisamlog.c
@@ -345,7 +345,8 @@ static int examine_log(my_string file_name, char **table_names)
if (!opt_processes)
file_info.process=0;
result= mi_uint2korr(head+7);
- if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info)))
+ if ((curr_file_info=(struct file_info*) tree_search(&tree, &file_info,
+ tree.custom_arg)))
{
curr_file_info->accessed=access_time;
if (update && curr_file_info->used && curr_file_info->closed)
@@ -452,7 +453,7 @@ static int examine_log(my_string file_name, char **table_names)
else
file_info.isam->s->rnd= isamlog_process;
}
- VOID(tree_insert(&tree,(gptr) &file_info,0));
+ VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
if (file_info.used)
{
if (verbose && !record_pos_file)
@@ -471,7 +472,7 @@ static int examine_log(my_string file_name, char **table_names)
{
if (!curr_file_info->closed)
files_open--;
- VOID(tree_delete(&tree,(gptr) curr_file_info));
+ VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
}
break;
case MI_LOG_EXTRA:
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 4fc84ac5657..3eded3b52f2 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -665,7 +665,8 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL,
+ NULL);
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
@@ -763,7 +764,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->tree_buff)
{
global_count=count;
- if (!(element=tree_insert(&count->int_tree,pos,0)) ||
+ if (!(element=tree_insert(&count->int_tree,pos, 0,
+ count->int_tree.custom_arg)) ||
(element->count == 1 &&
count->tree_buff + tree_buff_length <
count->tree_pos + count->field_length) ||
@@ -1786,7 +1788,8 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
break;
case FIELD_INTERVALL:
global_count=count;
- pos=(byte*) tree_search(&count->int_tree,start_pos);
+ pos=(byte*) tree_search(&count->int_tree, start_pos,
+ count->int_tree.custom_arg);
intervall=(uint) (pos - count->tree_buff)/field_length;
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
start_pos=end_pos;
diff --git a/myisam/rt_index.c b/myisam/rt_index.c
new file mode 100644
index 00000000000..ad0d593ee0a
--- /dev/null
+++ b/myisam/rt_index.c
@@ -0,0 +1,914 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "myisamdef.h"
+
+#include "rt_index.h"
+#include "rt_key.h"
+#include "rt_mbr.h"
+
+#define REINSERT_BUFFER_INC 10
+
+typedef struct st_page_level
+{
+ uint level;
+ my_off_t offs;
+} stPageLevel;
+
+typedef struct st_page_list
+{
+ ulong n_pages;
+ ulong m_pages;
+ stPageLevel *pages;
+} stPageList;
+
+/*
+Find next key in r-tree according to search_flag recursively
+Used in rtree_find_first() and rtree_find_next()
+Result values:
+-1 - error
+ 0 - found
+ 1 - not found
+*/
+static int rtree_find_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint search_flag, uint nod_cmp_flag,
+ my_off_t page, int level)
+{
+ uchar *k;
+ uchar *last;
+ uint nod_flag;
+ int res;
+ uchar *page_buf;
+ int k_len;
+ int *saved_key = (int*)(info->rtree_recursion_state + level * sizeof(int));
+
+ if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
+ {
+ my_errno = HA_ERR_OUT_OF_MEM;
+ return -1;
+ }
+ if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(page_buf);
+
+ k_len = keyinfo->keylength - info->s->base.rec_reflength;
+
+ if(info->rtree_recursion_depth >= level)
+ {
+ k = page_buf + *saved_key;
+ if (!nod_flag)
+ {
+ /* Only leaf pages contain data references. */
+ /* Need to check next key with data reference. */
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
+ }
+ }
+ else
+ {
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ }
+ last = rt_PAGE_END(page_buf);
+
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
+ {
+ if (nod_flag)
+ {
+ /* this is an internal node in the tree */
+ if (!(res = rtree_key_cmp(keyinfo->seg, info->lastkey2, k,
+ info->last_rkey_length, nod_cmp_flag)))
+ {
+ switch ((res = rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag,
+ _mi_kpos(nod_flag, k), level + 1)))
+ {
+ case 0: /* found - exit from recursion */
+ *saved_key = k - page_buf;
+ goto ok;
+ case 1: /* not found - continue searching */
+ info->rtree_recursion_depth = level;
+ break;
+ default: /* error */
+ case -1:
+ goto err1;
+ }
+ }
+ }
+ else
+ {
+ /* this is a leaf */
+ if (!rtree_key_cmp(keyinfo->seg, info->lastkey2, k,
+ info->last_rkey_length, search_flag))
+ {
+ uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
+ info->lastpos = _mi_dpos(info, 0, after_key);
+ info->lastkey_length = k_len + info->s->base.rec_reflength;
+ memcpy(info->lastkey, k, k_len + info->s->base.rec_reflength);
+
+ info->rtree_recursion_depth = level;
+ *saved_key = k - page_buf;
+
+ if (after_key < last)
+ {
+ info->int_keypos = (uchar*)saved_key;
+ memcpy(info->buff, page_buf, keyinfo->block_length);
+ info->int_maxpos = rt_PAGE_END(info->buff);
+ info->buff_used = 0;
+ }
+
+ res = 0;
+ goto ok;
+ }
+ }
+ }
+ info->lastpos = HA_OFFSET_ERROR;
+ my_errno = HA_ERR_KEY_NOT_FOUND;
+ res = 1;
+
+ok:
+ my_afree((byte*)page_buf);
+ return res;
+
+err1:
+ my_afree((byte*)page_buf);
+ info->lastpos = HA_OFFSET_ERROR;
+ return -1;
+}
+
+/*
+Find first key in r-tree according to search_flag condition
+Result values:
+-1 - error
+ 0 - found
+ 1 - not found
+*/
+int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length,
+ uint search_flag)
+{
+ my_off_t root;
+ uint nod_cmp_flag;
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+
+ if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ return -1;
+
+ /* Save searched key */
+ memcpy(info->lastkey2, key, keyinfo->keylength - info->s->base.rec_reflength);
+ info->last_rkey_length = key_length;
+
+ info->rtree_recursion_depth = -1;
+ info->buff_used = 1;
+
+ nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ?
+ MBR_WITHIN : MBR_INTERSECT);
+ return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0);
+}
+
+/*
+Find next key in r-tree according to search_flag condition
+Result values:
+-1 - error
+ 0 - found
+ 1 - not found
+*/
+int rtree_find_next(MI_INFO *info, uint keynr, uint search_flag)
+{
+ my_off_t root;
+ uint nod_cmp_flag;
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+
+ if (!info->buff_used)
+ {
+ uint k_len = keyinfo->keylength - info->s->base.rec_reflength;
+ /* rt_PAGE_NEXT_KEY(info->int_keypos) */
+ uchar *key = info->buff + *(int*)info->int_keypos + k_len +
+ info->s->base.rec_reflength;
+
+ while (key < info->int_maxpos)
+ {
+ if (!rtree_key_cmp(keyinfo->seg, info->lastkey2, key,
+ info->last_rkey_length, search_flag))
+ {
+ /* rt_PAGE_NEXT_KEY(key) */
+ uchar *after_key = key + k_len + info->s->base.rec_reflength;
+
+ info->lastpos = _mi_dpos(info, 0, after_key);
+ info->lastkey_length = k_len + info->s->base.rec_reflength;
+ memcpy(info->lastkey, key, k_len + info->s->base.rec_reflength);
+
+ *(int*)info->int_keypos = key - info->buff;
+ if (after_key >= info->int_maxpos)
+ {
+ info->buff_used = 1;
+ }
+
+ return 0;
+ }
+ else
+ {
+ key += k_len + info->s->base.rec_reflength;
+ }
+ }
+ }
+ if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ return -1;
+
+ nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ?
+ MBR_WITHIN : MBR_INTERSECT);
+ return rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0);
+}
+
+/*
+Get next key in r-tree recursively
+Used in rtree_get_first() and rtree_get_next()
+Result values:
+-1 - error
+ 0 - found
+ 1 - not found
+*/
+static int rtree_get_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint key_length,
+ my_off_t page, int level)
+{
+ uchar *k;
+ uchar *last;
+ uint nod_flag;
+ int res;
+ uchar *page_buf;
+ uint k_len;
+ int *saved_key = (int*)(info->rtree_recursion_state + level*sizeof(int));
+
+ if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
+ return -1;
+ if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(page_buf);
+
+ k_len = keyinfo->keylength - info->s->base.rec_reflength;
+
+ if(info->rtree_recursion_depth >= level)
+ {
+ k = page_buf + *saved_key;
+ if (!nod_flag)
+ {
+ /* Only leaf pages contain data references. */
+ /* Need to check next key with data reference. */
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
+ }
+ }
+ else
+ {
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ }
+ last = rt_PAGE_END(page_buf);
+
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
+ {
+ if (nod_flag)
+ {
+ /* this is an internal node in the tree */
+ switch ((res = rtree_get_req(info, keyinfo, key_length,
+ _mi_kpos(nod_flag, k), level + 1)))
+ {
+ case 0: /* found - exit from recursion */
+ *saved_key = k - page_buf;
+ goto ok;
+ case 1: /* not found - continue searching */
+ info->rtree_recursion_depth = level;
+ break;
+ default:
+ case -1: /* error */
+ goto err1;
+ }
+ }
+ else
+ {
+ /* this is a leaf */
+ uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
+ info->lastpos = _mi_dpos(info, 0, after_key);
+ info->lastkey_length = k_len + info->s->base.rec_reflength;
+ memcpy(info->lastkey, k, k_len + info->s->base.rec_reflength);
+
+ info->rtree_recursion_depth = level;
+ *saved_key = k - page_buf;
+
+ if (after_key < last)
+ {
+ info->int_keypos = (uchar*)saved_key;
+ memcpy(info->buff, page_buf, keyinfo->block_length);
+ info->int_maxpos = rt_PAGE_END(info->buff);
+ info->buff_used = 0;
+ }
+
+ res = 0;
+ goto ok;
+ }
+ }
+ info->lastpos = HA_OFFSET_ERROR;
+ my_errno = HA_ERR_KEY_NOT_FOUND;
+ res = 1;
+
+ok:
+ my_afree((byte*)page_buf);
+ return res;
+
+err1:
+ my_afree((byte*)page_buf);
+ info->lastpos = HA_OFFSET_ERROR;
+ return -1;
+}
+
+/*
+Get first key in r-tree
+Result values:
+-1 - error
+ 0 - found
+ 1 - not found
+*/
+int rtree_get_first(MI_INFO *info, uint keynr, uint key_length)
+{
+ my_off_t root;
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+
+ if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ return -1;
+
+ info->rtree_recursion_depth = -1;
+ info->buff_used = 1;
+
+ return rtree_get_req(info, &keyinfo[keynr], key_length, root, 0);
+}
+
+/* Get next key in r-tree
+Result values:
+-1 - error
+ 0 - found
+ 1 - not found
+*/
+int rtree_get_next(MI_INFO *info, uint keynr, uint key_length)
+{
+ my_off_t root;
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+
+ if (!info->buff_used)
+ {
+ uint k_len = keyinfo->keylength - info->s->base.rec_reflength;
+ /* rt_PAGE_NEXT_KEY(info->int_keypos) */
+ uchar *key = info->buff + *(int*)info->int_keypos + k_len +
+ info->s->base.rec_reflength;
+ /* rt_PAGE_NEXT_KEY(key) */
+ uchar *after_key = key + k_len + info->s->base.rec_reflength;
+
+ info->lastpos = _mi_dpos(info, 0, after_key);
+ info->lastkey_length = k_len + info->s->base.rec_reflength;
+ memcpy(info->lastkey, key, k_len + info->s->base.rec_reflength);
+
+ *(int*)info->int_keypos = key - info->buff;
+ if (after_key >= info->int_maxpos)
+ {
+ info->buff_used = 1;
+ }
+
+ return 0;
+ }
+ else
+ {
+ if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ return -1;
+
+ return rtree_get_req(info, &keyinfo[keynr], key_length, root, 0);
+ }
+}
+
+/*
+Go down and insert key into tree
+Result values:
+-1 - error
+ 0 - child was not split
+ 1 - child was split
+*/
+static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, my_off_t page, my_off_t *new_page,
+ int ins_level, int level)
+{
+ uchar *k;
+ uint nod_flag;
+ uchar *page_buf;
+ int res;
+
+ if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length +
+ MI_MAX_KEY_BUFF)))
+ {
+ my_errno = HA_ERR_OUT_OF_MEM;
+ return -1;
+ }
+ if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(page_buf);
+
+ if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */
+ (ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */
+ {
+ if ((k = rtree_choose_key(info, keyinfo, key, key_length, page_buf,
+ nod_flag)) == NULL)
+ goto err1;
+ switch ((res = rtree_insert_req(info, keyinfo, key, key_length,
+ _mi_kpos(nod_flag, k), new_page, ins_level, level + 1)))
+ {
+ case 0: /* child was not split */
+ {
+ rtree_combine_rect(keyinfo->seg, k, key, k, key_length);
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ goto ok;
+ }
+ case 1: /* child was split */
+ {
+ uchar *new_key = page_buf + keyinfo->block_length + nod_flag;
+ /* set proper MBR for key */
+ if (rtree_set_key_mbr(info, keyinfo, k, key_length,
+ _mi_kpos(nod_flag, k)))
+ goto err1;
+ /* add new key for new page */
+ _mi_kpointer(info, new_key - nod_flag, *new_page);
+ if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, *new_page))
+ goto err1;
+ res = rtree_add_key(info, keyinfo, new_key, key_length,
+ page_buf, new_page);
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ goto ok;
+ }
+ default:
+ case -1: /* error */
+ {
+ goto err1;
+ }
+ }
+ }
+ else
+ {
+ res = rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page);
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ goto ok;
+ }
+
+ok:
+ my_afree((byte*)page_buf);
+ return res;
+
+err1:
+ my_afree((byte*)page_buf);
+ return -1;
+}
+
+/*
+Insert key into the tree
+Result values:
+-1 - error
+ 0 - root was not split
+ 1 - root was split
+*/
+static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
+ uint key_length, int ins_level)
+{
+ my_off_t old_root;
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+ int res;
+ my_off_t new_page;
+
+ if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ {
+ int res;
+
+ if ((old_root = _mi_new(info, keyinfo)) == HA_OFFSET_ERROR)
+ return -1;
+ info->buff_used = 1;
+ mi_putint(info->buff, 2, 0);
+ res = rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL);
+ if (_mi_write_keypage(info, keyinfo, old_root, info->buff))
+ return 1;
+ info->s->state.key_root[keynr] = old_root;
+ return res;
+ }
+
+ switch ((res = rtree_insert_req(info, keyinfo, key, key_length,
+ old_root, &new_page, ins_level, 0)))
+ {
+ case 0: /* root was not split */
+ {
+ break;
+ }
+ case 1: /* root was split, grow a new root */
+ {
+ uchar *new_root_buf;
+ my_off_t new_root;
+ uchar *new_key;
+ uint nod_flag = info->s->base.key_reflength;
+
+ if (!(new_root_buf = (uchar*)my_alloca((uint)keyinfo->block_length +
+ MI_MAX_KEY_BUFF)))
+ {
+ my_errno = HA_ERR_OUT_OF_MEM;
+ return -1;
+ }
+
+ mi_putint(new_root_buf, 2, nod_flag);
+ if ((new_root = _mi_new(info, keyinfo)) == HA_OFFSET_ERROR)
+ goto err1;
+
+ new_key = new_root_buf + keyinfo->block_length + nod_flag;
+
+ _mi_kpointer(info, new_key - nod_flag, old_root);
+ if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, old_root))
+ goto err1;
+ if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL)
+ == -1)
+ goto err1;
+ _mi_kpointer(info, new_key - nod_flag, new_page);
+ if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, new_page))
+ goto err1;
+ if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL)
+ == -1)
+ goto err1;
+ if (_mi_write_keypage(info, keyinfo, new_root, new_root_buf))
+ goto err1;
+ info->s->state.key_root[keynr] = new_root;
+
+ my_afree((byte*)new_root_buf);
+ break;
+err1:
+ my_afree((byte*)new_root_buf);
+ return -1;
+ }
+ default:
+ case -1: /* error */
+ {
+ break;
+ }
+ }
+ return res;
+}
+
+/*
+Insert key into the tree - interface function
+Result values:
+-1 - error
+ 0 - OK
+*/
+int rtree_insert(MI_INFO *info, uint keynr, uchar *key, uint key_length)
+{
+ return (rtree_insert_level(info, keynr, key, key_length, -1) == -1) ? -1 : 0;
+}
+
+/*
+Fill reinsert page buffer
+*/
+static int rtree_fill_reinsert_list(stPageList *ReinsertList, my_off_t page,
+ int level)
+{
+ if (ReinsertList->n_pages == ReinsertList->m_pages)
+ {
+ ReinsertList->m_pages += REINSERT_BUFFER_INC;
+ if (!(ReinsertList->pages = (stPageLevel*)my_realloc((gptr)ReinsertList->pages,
+ ReinsertList->m_pages * sizeof(stPageLevel), MYF(MY_ALLOW_ZERO_PTR))))
+ goto err1;
+ }
+ /* save page to ReinsertList */
+ ReinsertList->pages[ReinsertList->n_pages].offs = page;
+ ReinsertList->pages[ReinsertList->n_pages].level = level;
+ ReinsertList->n_pages++;
+ return 0;
+
+err1:
+ return -1;
+}
+
+/*
+Go down and delete key from the tree
+Result values:
+-1 - error
+ 0 - deleted
+ 1 - not found
+ 2 - empty leaf
+*/
+static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, my_off_t page, uint *page_size,
+ stPageList *ReinsertList, int level)
+{
+ uchar *k;
+ uchar *last;
+ ulong i;
+ uint nod_flag;
+ uchar *page_buf;
+ int res;
+
+ if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
+ {
+ my_errno = HA_ERR_OUT_OF_MEM;
+ return -1;
+ }
+ if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(page_buf);
+
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ last = rt_PAGE_END(page_buf);
+
+ for (i = 0; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag), ++i)
+ {
+ if (nod_flag)
+ {
+ /* not leaf */
+ if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
+ {
+ switch ((res = rtree_delete_req(info, keyinfo, key, key_length,
+ _mi_kpos(nod_flag, k), page_size, ReinsertList, level + 1)))
+ {
+ case 0: /* deleted */
+ {
+ /* test page filling */
+ if (*page_size + key_length >= rt_PAGE_MIN_SIZE(keyinfo->block_length))
+ {
+ /* OK */
+ if (rtree_set_key_mbr(info, keyinfo, k, key_length,
+ _mi_kpos(nod_flag, k)))
+ goto err1;
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ }
+ else
+ {
+ /* too small: delete key & add it descendant to reinsert list */
+ if (rtree_fill_reinsert_list(ReinsertList, _mi_kpos(nod_flag, k),
+ level + 1))
+ goto err1;
+ rtree_delete_key(info, page_buf, k, key_length, nod_flag);
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ *page_size = mi_getint(page_buf);
+ }
+
+ goto ok;
+ }
+ case 1: /* not found - continue searching */
+ {
+ break;
+ }
+ case 2: /* vacuous case: last key in the leaf */
+ {
+ rtree_delete_key(info, page_buf, k, key_length, nod_flag);
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ *page_size = mi_getint(page_buf);
+ res = 0;
+ goto ok;
+ }
+ default: /* error */
+ case -1:
+ {
+ goto err1;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* leaf */
+ if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_EQUAL | MBR_DATA))
+ {
+ rtree_delete_key(info, page_buf, k, key_length, nod_flag);
+ *page_size = mi_getint(page_buf);
+ if (*page_size == 2)
+ {
+ /* last key in the leaf */
+ res = 2;
+ if (_mi_dispose(info, keyinfo, page))
+ goto err1;
+ }
+ else
+ {
+ res = 0;
+ if (_mi_write_keypage(info, keyinfo, page, page_buf))
+ goto err1;
+ }
+ goto ok;
+ }
+ }
+ }
+ res = 1;
+
+ok:
+ my_afree((byte*)page_buf);
+ return res;
+
+err1:
+ my_afree((byte*)page_buf);
+ return -1;
+}
+
+/*
+Delete key - interface function
+Result values:
+-1 - error
+ 0 - deleted
+*/
+int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
+{
+ uint page_size;
+ stPageList ReinsertList;
+ my_off_t old_root;
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+
+ if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ {
+ my_errno = HA_ERR_KEY_NOT_FOUND;
+ return -1;
+ }
+
+ ReinsertList.pages = NULL;
+ ReinsertList.n_pages = 0;
+ ReinsertList.m_pages = 0;
+
+ switch (rtree_delete_req(info, keyinfo, key, key_length, old_root,
+ &page_size, &ReinsertList, 0))
+ {
+ case 2:
+ {
+ info->s->state.key_root[keynr] = HA_OFFSET_ERROR;
+ return 0;
+ }
+ case 0:
+ {
+ uint nod_flag;
+ ulong i;
+ for (i = 0; i < ReinsertList.n_pages; ++i)
+ {
+ uchar *page_buf;
+ uint nod_flag;
+ uchar *k;
+ uchar *last;
+
+ if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
+ {
+ my_errno = HA_ERR_OUT_OF_MEM;
+ goto err1;
+ }
+ if (!_mi_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs,
+ page_buf, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(page_buf);
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ last = rt_PAGE_END(page_buf);
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
+ {
+ if (rtree_insert_level(info, keynr, k, key_length,
+ ReinsertList.pages[i].level) == -1)
+ {
+ my_afree((byte*)page_buf);
+ goto err1;
+ }
+ }
+ my_afree((byte*)page_buf);
+ if (_mi_dispose(info, keyinfo, ReinsertList.pages[i].offs))
+ goto err1;
+ }
+ if (ReinsertList.pages)
+ free(ReinsertList.pages);
+
+ /* check for redundant root (not leaf, 1 child) and eliminate */
+ if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ goto err1;
+ if (!_mi_fetch_keypage(info, keyinfo, old_root, info->buff, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(info->buff);
+ page_size = mi_getint(info->buff);
+ if (nod_flag && (page_size == 2 + key_length +
+ (nod_flag ? nod_flag : info->s->base.rec_reflength)))
+ {
+ my_off_t new_root = _mi_kpos(nod_flag,
+ rt_PAGE_FIRST_KEY(info->buff, nod_flag));
+ if (_mi_dispose(info, keyinfo, old_root))
+ goto err1;
+ info->s->state.key_root[keynr] = new_root;
+ }
+ return 0;
+
+err1:
+ return -1;
+ }
+ case 1: /* not found */
+ {
+ my_errno = HA_ERR_KEY_NOT_FOUND;
+ return -1;
+ }
+ default:
+ case -1: /* error */
+ {
+ return -1;
+ }
+ }
+}
+
+/*
+Estimate number of suitable keys in the tree
+*/
+ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key,
+ uint key_length, uint flag)
+{
+ MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+ my_off_t root;
+ uint i = 0;
+ uchar *k;
+ uchar *last;
+ uint nod_flag;
+ uchar *page_buf;
+ uint k_len;
+ double area = 0;
+ ha_rows res = 0;
+
+ if (flag & MBR_DISJOINT)
+ return info->state->records;
+
+ if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ return HA_POS_ERROR;
+ if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
+ return HA_POS_ERROR;
+ if (!_mi_fetch_keypage(info, keyinfo, root, page_buf, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(page_buf);
+
+ k_len = keyinfo->keylength - info->s->base.rec_reflength;
+
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ last = rt_PAGE_END(page_buf);
+
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag), ++i)
+ {
+ if (nod_flag)
+ {
+ double k_area = rtree_rect_volume(keyinfo->seg, k, key_length);
+
+ if (k_area == 0)
+ {
+ if (flag & (MBR_CONTAIN | MBR_INTERSECT))
+ {
+ area += 1;
+ }
+ else if (flag & (MBR_WITHIN | MBR_EQUAL))
+ {
+ if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
+ area += 1;
+ }
+ else
+ goto err1;
+ }
+ else
+ {
+ if (flag & (MBR_CONTAIN | MBR_INTERSECT))
+ {
+ area += rtree_overlapping_area(keyinfo->seg, key, k, key_length) /
+ k_area;
+ }
+ else if (flag & (MBR_WITHIN | MBR_EQUAL))
+ {
+ if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
+ area += rtree_rect_volume(keyinfo->seg, key, key_length) /
+ k_area;
+ }
+ else
+ goto err1;
+ }
+ }
+ else
+ {
+ if (!rtree_key_cmp(keyinfo->seg, key, k, key_length, flag))
+ ++res;
+ }
+ }
+ if (nod_flag)
+ {
+ if (i)
+ res = (int)(area / i * info->state->records);
+ else
+ res = HA_POS_ERROR;
+ }
+
+ my_afree((byte*)page_buf);
+ return res;
+
+err1:
+ my_afree((byte*)page_buf);
+ return HA_POS_ERROR;
+}
diff --git a/myisam/rt_index.h b/myisam/rt_index.h
new file mode 100644
index 00000000000..1a0fce72a82
--- /dev/null
+++ b/myisam/rt_index.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 _rt_index_h
+#define _rt_index_h
+
+#define rt_PAGE_FIRST_KEY(page, nod_flag) (page + 2 + nod_flag)
+#define rt_PAGE_NEXT_KEY(key, key_length, nod_flag) (key + key_length + \
+ (nod_flag ? nod_flag : info->s->base.rec_reflength))
+#define rt_PAGE_END(page) (page + mi_getint(page))
+
+#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length) / 2)
+
+int rtree_insert(MI_INFO *info, uint keynr, uchar *key, uint key_length);
+int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length);
+
+int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length,
+ uint search_flag);
+int rtree_find_next(MI_INFO *info, uint keynr, uint search_flag);
+
+int rtree_get_first(MI_INFO *info, uint keynr, uint key_length);
+int rtree_get_next(MI_INFO *info, uint keynr, uint key_length);
+
+ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key,
+ uint key_length, uint flag);
+
+int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
+ uint key_length, my_off_t *new_page_offs);
+
+#endif /* _rt_index_h */
diff --git a/myisam/rt_key.c b/myisam/rt_key.c
new file mode 100644
index 00000000000..a48aec53c97
--- /dev/null
+++ b/myisam/rt_key.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "myisamdef.h"
+
+#include "rt_index.h"
+#include "rt_key.h"
+#include "rt_mbr.h"
+
+/*
+ Add key to the page
+
+ RESULT VALUES
+ -1 Error
+ 0 Not split
+ 1 Split
+*/
+
+int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, uchar *page_buf, my_off_t *new_page)
+{
+ uint page_size = mi_getint(page_buf);
+ uint nod_flag = mi_test_if_nod(page_buf);
+
+ if (page_size + key_length + nod_flag <= keyinfo->block_length)
+ {
+ /* split won't be necessary */
+ if (nod_flag)
+ {
+ /* save key */
+ memcpy(rt_PAGE_END(page_buf), key - nod_flag, key_length + nod_flag);
+ page_size += key_length + nod_flag;
+ }
+ else
+ {
+ /* save key */
+ memcpy(rt_PAGE_END(page_buf), key, key_length +
+ info->s->base.rec_reflength);
+ page_size += key_length + info->s->base.rec_reflength;
+ }
+ mi_putint(page_buf, page_size, nod_flag);
+ return 0;
+ }
+
+ return (rtree_split_page(info, keyinfo, page_buf, key, key_length,
+ new_page) ? -1 : 0);
+}
+
+/*
+ Delete key from the page
+*/
+int rtree_delete_key(MI_INFO *info, uchar *page_buf, uchar *key,
+ uint key_length, uint nod_flag)
+{
+ uint16 page_size = mi_getint(page_buf);
+ uchar *key_start;
+
+ key_start= key - nod_flag;
+ if (nod_flag)
+ key_length += info->s->base.rec_reflength;
+
+ memmove(key_start, key + key_length, page_size - key_length -
+ (key - page_buf));
+ page_size-= key_length + nod_flag;
+
+ mi_putint(page_buf, page_size, nod_flag);
+ return 0;
+}
+
+
+/*
+ Calculate and store key MBR
+*/
+
+int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, my_off_t child_page)
+{
+ uchar *k;
+ uchar *last;
+ uint nod_flag;
+
+ if (!_mi_fetch_keypage(info, keyinfo, child_page, info->buff, 0))
+ goto err1;
+ nod_flag = mi_test_if_nod(info->buff);
+
+ k = rt_PAGE_FIRST_KEY(info->buff, nod_flag);
+ last = rt_PAGE_END(info->buff);
+
+ rtree_page_mbr(info, keyinfo->seg, info->buff, key, key_length);
+
+ return 0;
+
+err1:
+ return -1;
+}
+
+
+/*
+ Choose non-leaf better key for insertion
+*/
+
+uchar *rtree_choose_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, uchar *page_buf, uint nod_flag)
+{
+ double increase;
+ double best_incr = DBL_MAX;
+ double area;
+ double best_area;
+ uchar *best_key;
+ uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ uchar *last = rt_PAGE_END(page_buf);
+
+ LINT_INIT(best_area);
+ LINT_INIT(best_key);
+
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
+ {
+ if ((increase = rtree_area_increase(keyinfo->seg, key, k, key_length,
+ &area)) == -1)
+ return NULL;
+ if (increase < best_incr)
+ {
+ best_key = k;
+ best_area = area;
+ best_incr = increase;
+ }
+ else
+ {
+ if ((increase == best_incr) && (area < best_area))
+ {
+ best_key = k;
+ best_area = area;
+ best_incr = increase;
+ }
+ }
+ }
+ return best_key;
+}
diff --git a/myisam/rt_key.h b/myisam/rt_key.h
new file mode 100644
index 00000000000..dfd7b874b54
--- /dev/null
+++ b/myisam/rt_key.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/* Written by Ramil Kalimullin, who has a shared copyright to this code */
+
+#ifndef _rt_key_h
+#define _rt_key_h
+
+int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, uchar *page_buf, my_off_t *new_page);
+int rtree_delete_key(MI_INFO *info, uchar *page, uchar *key,
+ uint key_length, uint nod_flag);
+int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, my_off_t child_page);
+uchar *rtree_choose_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, uchar *page_buf, uint nod_flag);
+#endif /* _rt_key_h */
diff --git a/myisam/rt_mbr.c b/myisam/rt_mbr.c
new file mode 100644
index 00000000000..bb13c0769b3
--- /dev/null
+++ b/myisam/rt_mbr.c
@@ -0,0 +1,759 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "myisamdef.h"
+
+#include "rt_index.h"
+#include "rt_mbr.h"
+
+#define INTERSECT_CMP(amin, amax, bmin, bmax) ((amin > bmax) || (bmin > amax))
+#define CONTAIN_CMP(amin, amax, bmin, bmax) ((bmin > amin) || (bmax < amax))
+#define WITHIN_CMP(amin, amax, bmin, bmax) ((amin > bmin) || (amax < bmax))
+#define DISJOINT_CMP(amin, amax, bmin, bmax) ((amin <= bmax) && (bmin <= amax))
+#define EQUAL_CMP(amix, amax, bmin, bmax) ((amix != bmin) || (amax != bmax))
+
+#define FCMP(A, B) ((int)(A) - (int)(B))
+#define p_inc(A, B, X) {A += X; B += X;}
+
+#define RT_CMP(nextflag) \
+ if (nextflag & MBR_INTERSECT) \
+ { \
+ if (INTERSECT_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else if (nextflag & MBR_CONTAIN) \
+ { \
+ if (CONTAIN_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else if (nextflag & MBR_WITHIN) \
+ { \
+ if (WITHIN_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else if (nextflag & MBR_EQUAL) \
+ { \
+ if (EQUAL_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else /* if (nextflag & MBR_DISJOINT) */ \
+ { \
+ if (DISJOINT_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ }
+
+#define RT_CMP_KORR(type, korr_func, len, nextflag) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ RT_CMP(nextflag); \
+ p_inc(a, b, len); \
+ break; \
+}
+
+#define RT_CMP_GET(type, get_func, len, nextflag) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ RT_CMP(nextflag); \
+ p_inc(a, b, len); \
+ break; \
+}
+
+/*
+ Compares two keys a and b depending on nextflag
+ nextflag can contain these flags:
+ MBR_INTERSECT(a,b) a overlaps b
+ MBR_CONTAIN(a,b) a contains b
+ MBR_DISJOINT(a,b) a disjoint b
+ MBR_WITHIN(a,b) a within b
+ MBR_EQUAL(a,b) All coordinates of MBRs are equal
+ MBR_DATA(a,b) Data reference is the same
+ Returns 0 on success.
+*/
+int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length,
+ uint nextflag)
+{
+ for (; (int) key_length > 0; keyseg += 2 )
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin,amax,bmin,bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ RT_CMP(nextflag);
+ p_inc(a, b, 1);
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_CMP_KORR(int16, mi_sint2korr, 2, nextflag);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_CMP_KORR(uint16, mi_uint2korr, 2, nextflag);
+ case HA_KEYTYPE_INT24:
+ RT_CMP_KORR(int32, mi_sint3korr, 3, nextflag);
+ case HA_KEYTYPE_UINT24:
+ RT_CMP_KORR(uint32, mi_uint3korr, 3, nextflag);
+ case HA_KEYTYPE_LONG_INT:
+ RT_CMP_KORR(int32, mi_sint4korr, 4, nextflag);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_CMP_KORR(uint32, mi_uint4korr, 4, nextflag);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_CMP_KORR(longlong, mi_sint8korr, 8, nextflag)
+ case HA_KEYTYPE_ULONGLONG:
+ RT_CMP_KORR(ulonglong, mi_uint8korr, 8, nextflag)
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_CMP_GET(float, mi_float4get, 4, nextflag);
+ case HA_KEYTYPE_DOUBLE:
+ RT_CMP_GET(double, mi_float8get, 8, nextflag);
+ case HA_KEYTYPE_END:
+ goto end;
+ }
+ }
+
+end:
+ if (nextflag & MBR_DATA)
+ {
+ uchar *end = a + keyseg->length;
+ do
+ {
+ if (*a++ != *b++)
+ return FCMP(a[-1], b[-1]);
+ } while (a != end);
+ }
+ return 0;
+}
+
+#define RT_VOL_KORR(type, korr_func, len, cast) \
+{ \
+ type amin, amax; \
+ amin = korr_func(a); \
+ a += len; \
+ amax = korr_func(a); \
+ a += len; \
+ res *= (cast(amax) - cast(amin)); \
+ break; \
+}
+
+#define RT_VOL_GET(type, get_func, len, cast) \
+{ \
+ type amin, amax; \
+ get_func(amin, a); \
+ a += len; \
+ get_func(amax, a); \
+ a += len; \
+ res *= (cast(amax) - cast(amin)); \
+ break; \
+}
+
+/*
+ Calculates rectangle volume
+*/
+double rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length)
+{
+ double res = 1;
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax;
+ amin = (int)*((signed char *)a);
+ a += 1;
+ amax = (int)*((signed char *)a);
+ a += 1;
+ res *= ((double)amax - (double)amin);
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_VOL_KORR(int16, mi_sint2korr, 2, (double));
+ case HA_KEYTYPE_USHORT_INT:
+ RT_VOL_KORR(uint16, mi_uint2korr, 2, (double));
+ case HA_KEYTYPE_INT24:
+ RT_VOL_KORR(int32, mi_sint3korr, 3, (double));
+ case HA_KEYTYPE_UINT24:
+ RT_VOL_KORR(uint32, mi_uint3korr, 3, (double));
+ case HA_KEYTYPE_LONG_INT:
+ RT_VOL_KORR(int32, mi_sint4korr, 4, (double));
+ case HA_KEYTYPE_ULONG_INT:
+ RT_VOL_KORR(uint32, mi_uint4korr, 4, (double));
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_VOL_KORR(longlong, mi_sint8korr, 8, (double));
+ case HA_KEYTYPE_ULONGLONG:
+ RT_VOL_KORR(longlong, mi_sint8korr, 8, ulonglong2double);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_VOL_GET(float, mi_float4get, 4, (double));
+ case HA_KEYTYPE_DOUBLE:
+ RT_VOL_GET(double, mi_float8get, 8, (double));
+ case HA_KEYTYPE_END:
+ key_length = 0;
+ break;
+ }
+ }
+ return res;
+}
+
+#define RT_D_MBR_KORR(type, korr_func, len, cast) \
+{ \
+ type amin, amax; \
+ amin = korr_func(a); \
+ a += len; \
+ amax = korr_func(a); \
+ a += len; \
+ *res++ = cast(amin); \
+ *res++ = cast(amax); \
+ break; \
+}
+
+#define RT_D_MBR_GET(type, get_func, len, cast) \
+{ \
+ type amin, amax; \
+ get_func(amin, a); \
+ a += len; \
+ get_func(amax, a); \
+ a += len; \
+ *res++ = cast(amin); \
+ *res++ = cast(amax); \
+ break; \
+}
+
+/*
+ Creates an MBR as an array of doubles.
+*/
+int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
+{
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax;
+ amin = (int)*((signed char *)a);
+ a += 1;
+ amax = (int)*((signed char *)a);
+ a += 1;
+ *res++ = (double)amin;
+ *res++ = (double)amax;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_D_MBR_KORR(int16, mi_sint2korr, 2, (double));
+ case HA_KEYTYPE_USHORT_INT:
+ RT_D_MBR_KORR(uint16, mi_uint2korr, 2, (double));
+ case HA_KEYTYPE_INT24:
+ RT_D_MBR_KORR(int32, mi_sint3korr, 3, (double));
+ case HA_KEYTYPE_UINT24:
+ RT_D_MBR_KORR(uint32, mi_uint3korr, 3, (double));
+ case HA_KEYTYPE_LONG_INT:
+ RT_D_MBR_KORR(int32, mi_sint4korr, 4, (double));
+ case HA_KEYTYPE_ULONG_INT:
+ RT_D_MBR_KORR(uint32, mi_uint4korr, 4, (double));
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_D_MBR_KORR(longlong, mi_sint8korr, 8, (double));
+ case HA_KEYTYPE_ULONGLONG:
+ RT_D_MBR_KORR(longlong, mi_sint8korr, 8, ulonglong2double);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_D_MBR_GET(float, mi_float4get, 4, (double));
+ case HA_KEYTYPE_DOUBLE:
+ RT_D_MBR_GET(double, mi_float8get, 8, (double));
+ case HA_KEYTYPE_END:
+ key_length = 0;
+ break;
+ }
+ }
+ return 0;
+}
+
+#define RT_COMB_KORR(type, korr_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ p_inc(a, b, len); \
+ amin = min(amin, bmin); \
+ amax = max(amax, bmax); \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ break; \
+}
+
+#define RT_COMB_GET(type, get_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ p_inc(a, b, len); \
+ amin = min(amin, bmin); \
+ amax = max(amax, bmax); \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ break; \
+}
+
+/*
+ Creates common minimal bounding rectungle
+ for two input rectagnles a and b
+ Result is written to c
+*/
+
+int rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c,
+ uint key_length)
+{
+
+ for ( ; (int) key_length > 0 ; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amin = min(amin, bmin);
+ amax = max(amax, bmax);
+ *((signed char*)c) = amin;
+ c += 1;
+ *((signed char*)c) = amax;
+ c += 1;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_COMB_KORR(int16, mi_sint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_COMB_KORR(uint16, mi_uint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_INT24:
+ RT_COMB_KORR(int32, mi_sint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_COMB_KORR(uint32, mi_uint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_COMB_KORR(int32, mi_sint4korr, mi_int4store, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_COMB_KORR(uint32, mi_uint4korr, mi_int4store, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_COMB_KORR(longlong, mi_sint8korr, mi_int8store, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_COMB_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_COMB_GET(float, mi_float4get, mi_float4store, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_COMB_GET(double, mi_float8get, mi_float8store, 8);
+ case HA_KEYTYPE_END:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+#define RT_OVL_AREA_KORR(type, korr_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ p_inc(a, b, len); \
+ amin = max(amin, bmin); \
+ amax = min(amax, bmax); \
+ if (amin >= amax) \
+ return 0; \
+ res *= amax - amin; \
+ break; \
+}
+
+#define RT_OVL_AREA_GET(type, get_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ p_inc(a, b, len); \
+ amin = max(amin, bmin); \
+ amax = min(amax, bmax); \
+ if (amin >= amax) \
+ return 0; \
+ res *= amax - amin; \
+ break; \
+}
+
+/*
+Calculates overlapping area of two MBRs a & b
+*/
+double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b,
+ uint key_length)
+{
+ double res = 1;
+ for (; (int) key_length > 0 ; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return -1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amin = max(amin, bmin);
+ amax = min(amax, bmax);
+ if (amin >= amax)
+ return 0;
+ res *= amax - amin;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_OVL_AREA_KORR(int16, mi_sint2korr, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_OVL_AREA_KORR(uint16, mi_uint2korr, 2);
+ case HA_KEYTYPE_INT24:
+ RT_OVL_AREA_KORR(int32, mi_sint3korr, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_OVL_AREA_KORR(uint32, mi_uint3korr, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_OVL_AREA_KORR(int32, mi_sint4korr, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_OVL_AREA_KORR(uint32, mi_uint4korr, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_OVL_AREA_GET(float, mi_float4get, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_OVL_AREA_GET(double, mi_float8get, 8);
+ case HA_KEYTYPE_END:
+ return res;
+ }
+ }
+ return res;
+}
+
+#define RT_AREA_INC_KORR(type, korr_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ p_inc(a, b, len); \
+ a_area *= (((double)amax) - ((double)amin)); \
+ *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
+ break; \
+}
+
+#define RT_AREA_INC_GET(type, get_func, len)\
+{\
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ p_inc(a, b, len); \
+ a_area *= (((double)amax) - ((double)amin)); \
+ *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
+ break; \
+}
+
+/*
+Calculates MBR_AREA(a+b) - MBR_AREA(a)
+*/
+double rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
+ uint key_length, double *ab_area)
+{
+ double a_area = 1;
+
+ *ab_area = 1;
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ /* Handle NULL part */
+ if (keyseg->null_bit)
+ {
+ return -1;
+ }
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ a_area *= (((double)amax) - ((double)amin));
+ *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin));
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_AREA_INC_KORR(int16, mi_sint2korr, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_AREA_INC_KORR(uint16, mi_uint2korr, 2);
+ case HA_KEYTYPE_INT24:
+ RT_AREA_INC_KORR(int32, mi_sint3korr, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_AREA_INC_KORR(int32, mi_uint3korr, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_AREA_INC_KORR(int32, mi_sint4korr, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_AREA_INC_KORR(uint32, mi_uint4korr, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_AREA_INC_GET(float, mi_float4get, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_AREA_INC_GET(double, mi_float8get, 8);
+ case HA_KEYTYPE_END:
+ return *ab_area - a_area;
+ }
+ }
+ return *ab_area - a_area;
+}
+
+#define RT_PAGE_MBR_KORR(type, korr_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(k + inc); \
+ amax = korr_func(k + inc + len); \
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \
+{ \
+ bmin = korr_func(k + inc); \
+ bmax = korr_func(k + inc + len); \
+ if (amin > bmin) \
+ amin = bmin; \
+ if (amax < bmax) \
+ amax = bmax; \
+} \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ inc += 2 * len; \
+ break; \
+}
+
+#define RT_PAGE_MBR_GET(type, get_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, k + inc); \
+ get_func(amax, k + inc + len); \
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \
+{ \
+ get_func(bmin, k + inc); \
+ get_func(bmax, k + inc + len); \
+ if (amin > bmin) \
+ amin = bmin; \
+ if (amax < bmax) \
+ amax = bmax; \
+} \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ inc += 2 * len; \
+ break; \
+}
+
+/*
+Calculates key page total MBR = MBR(key1) + MBR(key2) + ...
+*/
+int rtree_page_mbr(MI_INFO *info, HA_KEYSEG *keyseg, uchar *page_buf,
+ uchar *c, uint key_length)
+{
+ uint inc = 0;
+ uint k_len = key_length;
+ uint nod_flag = mi_test_if_nod(page_buf);
+ uchar *k;
+ uchar *last = rt_PAGE_END(page_buf);
+
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ /* Handle NULL part */
+ if (keyseg->null_bit)
+ {
+ return 1;
+ }
+
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)(k + inc));
+ amax = (int)*((signed char *)(k + inc + 1));
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
+ {
+ bmin = (int)*((signed char *)(k + inc));
+ bmax = (int)*((signed char *)(k + inc + 1));
+
+ if (amin > bmin)
+ amin = bmin;
+ if (amax < bmax)
+ amax = bmax;
+ }
+ *((signed char*)c) = amin;
+ c += 1;
+ *((signed char*)c) = amax;
+ c += 1;
+ inc += 1 * 2;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_PAGE_MBR_KORR(int16, mi_sint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_PAGE_MBR_KORR(uint16, mi_uint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_INT24:
+ RT_PAGE_MBR_KORR(int32, mi_sint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_PAGE_MBR_KORR(uint32, mi_uint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_PAGE_MBR_KORR(int32, mi_sint4korr, mi_int4store, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_PAGE_MBR_KORR(uint32, mi_uint4korr, mi_int4store, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_PAGE_MBR_KORR(longlong, mi_sint8korr, mi_int8store, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_PAGE_MBR_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_PAGE_MBR_GET(float, mi_float4get, mi_float4store, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_PAGE_MBR_GET(double, mi_float8get, mi_float8store, 8);
+ case HA_KEYTYPE_END:
+ return 0;
+ }
+ }
+ return 0;
+}
diff --git a/myisam/rt_mbr.h b/myisam/rt_mbr.h
new file mode 100644
index 00000000000..a68807370f9
--- /dev/null
+++ b/myisam/rt_mbr.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 _rt_mbr_h
+#define _rt_mbr_h
+
+int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *a, uchar *b, uint key_length,
+ uint nextflag);
+int rtree_combine_rect(HA_KEYSEG *keyseg,uchar *, uchar *, uchar*,
+ uint key_length);
+double rtree_rect_volume(HA_KEYSEG *keyseg, uchar*, uint key_length);
+int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res);
+double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar *a, uchar *b,
+ uint key_length);
+double rtree_area_increase(HA_KEYSEG *keyseg, uchar *a, uchar *b,
+ uint key_length, double *ab_area);
+int rtree_page_mbr(MI_INFO *info, HA_KEYSEG *keyseg, uchar *page_buf,
+ uchar* c, uint key_length);
+#endif /* _rt_mbr_h */
diff --git a/myisam/rt_split.c b/myisam/rt_split.c
new file mode 100644
index 00000000000..3363bbe2d9b
--- /dev/null
+++ b/myisam/rt_split.c
@@ -0,0 +1,343 @@
+/* Copyright (C) 2000 MySQL AB & Alexey Botchkov & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "myisamdef.h"
+
+#include "rt_index.h"
+#include "rt_key.h"
+#include "rt_mbr.h"
+
+typedef struct
+{
+ double square;
+ int n_node;
+ uchar *key;
+ double *coords;
+} SplitStruct;
+
+inline static double *reserve_coords(double **d_buffer, int n_dim)
+{
+ double *coords = *d_buffer;
+ (*d_buffer) += n_dim * 2;
+ return coords;
+}
+
+static void mbr_join(double *a, const double *b, int n_dim)
+{
+ double *end = a + n_dim * 2;
+ do
+ {
+ if (a[0] > b[0])
+ a[0] = b[0];
+
+ if (a[1] < b[1])
+ a[1] = b[1];
+
+ a += 2;
+ b += 2;
+ }while (a != end);
+}
+
+/*
+Counts the square of mbr which is a join of a and b
+*/
+static double mbr_join_square(const double *a, const double *b, int n_dim)
+{
+ const double *end = a + n_dim * 2;
+ double square = 1.0;
+ do
+ {
+ square *=
+ ((a[1] < b[1]) ? b[1] : a[1]) - ((a[0] > b[0]) ? b[0] : a[0]);
+
+ a += 2;
+ b += 2;
+ }while (a != end);
+
+ return square;
+}
+
+static double count_square(const double *a, int n_dim)
+{
+ const double *end = a + n_dim * 2;
+ double square = 1.0;
+ do
+ {
+ square *= a[1] - a[0];
+ a += 2;
+ }while (a != end);
+ return square;
+}
+
+inline static void copy_coords(double *dst, const double *src, int n_dim)
+{
+ memcpy(dst, src, sizeof(double) * (n_dim * 2));
+}
+
+/*
+Select two nodes to collect group upon
+*/
+static void pick_seeds(SplitStruct *node, int n_entries,
+ SplitStruct **seed_a, SplitStruct **seed_b, int n_dim)
+{
+ SplitStruct *cur1;
+ SplitStruct *lim1 = node + (n_entries - 1);
+ SplitStruct *cur2;
+ SplitStruct *lim2 = node + n_entries;
+
+ double max_d = -DBL_MAX;
+ double d;
+
+ for (cur1 = node; cur1 < lim1; ++cur1)
+ {
+ for (cur2=cur1 + 1; cur2 < lim2; ++cur2)
+ {
+
+ d = mbr_join_square(cur1->coords, cur2->coords, n_dim) - cur1->square -
+ cur2->square;
+ if (d > max_d)
+ {
+ max_d = d;
+ *seed_a = cur1;
+ *seed_b = cur2;
+ }
+ }
+ }
+}
+
+/*
+Select next node and group where to add
+*/
+static void pick_next(SplitStruct *node, int n_entries, double *g1, double *g2,
+ SplitStruct **choice, int *n_group, int n_dim)
+{
+ SplitStruct *cur = node;
+ SplitStruct *end = node + n_entries;
+
+ double max_diff = -DBL_MAX;
+
+ for (; cur<end; ++cur)
+ {
+ double diff;
+ double abs_diff;
+
+ if (cur->n_node)
+ {
+ continue;
+ }
+
+ diff = mbr_join_square(g1, cur->coords, n_dim) -
+ mbr_join_square(g2, cur->coords, n_dim);
+
+ abs_diff = fabs(diff);
+ if (abs_diff > max_diff)
+ {
+ max_diff = abs_diff;
+ *n_group = 1 + (diff > 0);
+ *choice = cur;
+ }
+ }
+}
+
+/*
+Mark not-in-group entries as n_group
+*/
+static void mark_all_entries(SplitStruct *node, int n_entries, int n_group)
+{
+ SplitStruct *cur = node;
+ SplitStruct *end = node + n_entries;
+ for (; cur<end; ++cur)
+ {
+ if (cur->n_node)
+ {
+ continue;
+ }
+ cur->n_node = n_group;
+ }
+}
+
+static int split_rtree_node(SplitStruct *node, int n_entries,
+ int all_size, /* Total key's size */
+ int key_size,
+ int min_size, /* Minimal group size */
+ int size1, int size2 /* initial group sizes */,
+ double **d_buffer, int n_dim)
+{
+ SplitStruct *cur;
+ SplitStruct *a;
+ SplitStruct *b;
+ double *g1 = reserve_coords(d_buffer, n_dim);
+ double *g2 = reserve_coords(d_buffer, n_dim);
+ SplitStruct *next;
+ int next_node;
+ int i;
+ SplitStruct *end = node + n_entries;
+
+ if (all_size < min_size * 2)
+ {
+ return 1;
+ }
+
+ cur = node;
+ for (; cur<end; ++cur)
+ {
+ cur->square = count_square(cur->coords, n_dim);
+ cur->n_node = 0;
+ }
+
+ pick_seeds(node, n_entries, &a, &b, n_dim);
+ a->n_node = 1;
+ b->n_node = 2;
+
+
+ copy_coords(g1, a->coords, n_dim);
+ size1 += key_size;
+ copy_coords(g2, b->coords, n_dim);
+ size2 += key_size;
+
+
+ for (i=n_entries - 2; i>0; --i)
+ {
+ if (all_size - (size2 + key_size) < min_size) /* Can't write into group 2 */
+ {
+ mark_all_entries(node, n_entries, 1);
+ break;
+ }
+
+ if (all_size - (size1 + key_size) < min_size) /* Can't write into group 1 */
+ {
+ mark_all_entries(node, n_entries, 2);
+ break;
+ }
+
+ pick_next(node, n_entries, g1, g2, &next, &next_node, n_dim);
+ if (next_node == 1)
+ {
+ size1 += key_size;
+ mbr_join(g1, next->coords, n_dim);
+ }
+ else
+ {
+ size2 += key_size;
+ mbr_join(g2, next->coords, n_dim);
+ }
+ next->n_node = next_node;
+ }
+
+ return 0;
+}
+
+int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
+ uint key_length, my_off_t *new_page_offs)
+{
+ int n1, n2; /* Number of items in groups */
+
+ SplitStruct *task;
+ SplitStruct *cur;
+ SplitStruct *stop;
+ double *coord_buf;
+ double *next_coord;
+ double *old_coord;
+ int n_dim;
+ uchar *source_cur, *cur1, *cur2;
+ uchar *new_page;
+ int err_code = 0;
+
+ uint nod_flag = mi_test_if_nod(page);
+ uint full_length = key_length + (nod_flag ? nod_flag :
+ info->s->base.rec_reflength);
+
+ int max_keys = (mi_getint(page)-2) / (full_length);
+
+ n_dim = (keyinfo->keysegs-1) / 2;
+
+ {
+ int coord_buf_size = n_dim * 2 * sizeof(double) * (max_keys + 1 + 4);
+ coord_buf =
+ my_alloca(coord_buf_size + sizeof(SplitStruct) * (max_keys + 1));
+
+ task = (SplitStruct *)(((char *)coord_buf) + coord_buf_size);
+ }
+ next_coord = coord_buf;
+
+ stop = task + max_keys;
+ source_cur = rt_PAGE_FIRST_KEY(page, nod_flag);
+
+ for (cur = task; cur < stop; ++cur, source_cur = rt_PAGE_NEXT_KEY(source_cur,
+ key_length, nod_flag))
+ {
+ cur->coords = reserve_coords(&next_coord, n_dim);
+ cur->key = source_cur;
+ rtree_d_mbr(keyinfo->seg, source_cur, key_length, cur->coords);
+ }
+
+ cur->coords = reserve_coords(&next_coord, n_dim);
+ rtree_d_mbr(keyinfo->seg, key, key_length, cur->coords);
+ cur->key = key;
+
+ old_coord = next_coord;
+
+ if (split_rtree_node(task, max_keys + 1,
+ mi_getint(page) + full_length + 2, full_length,
+ rt_PAGE_MIN_SIZE(keyinfo->block_length),
+ 2, 2, &next_coord, n_dim))
+ {
+ err_code = 1;
+ goto split_err;
+ }
+
+ if (!(new_page = (uchar*)my_alloca((uint)keyinfo->block_length)))
+ return -1;
+
+ stop = task + (max_keys + 1);
+ cur1 = rt_PAGE_FIRST_KEY(page, nod_flag);
+ cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag);
+
+ n1 = 0;
+ n2 = 0;
+ for (cur = task; cur < stop; ++cur)
+ {
+ uchar *to;
+ if (cur->n_node == 1)
+ {
+ to = cur1;
+ cur1 = rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag);
+ ++n1;
+ }
+ else
+ {
+ to = cur2;
+ cur2 = rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag);
+ ++n2;
+ }
+ memcpy(to - nod_flag, cur->key - nod_flag, full_length);
+ }
+
+ mi_putint(page, 2 + n1 * full_length, nod_flag);
+ mi_putint(new_page, 2 + n2 * full_length, nod_flag);
+
+ *new_page_offs=_mi_new(info, keyinfo);
+ _mi_write_keypage(info, keyinfo, *new_page_offs, new_page);
+ my_afree((byte*)new_page);
+
+split_err:
+ my_afree((byte*)coord_buf);
+ return err_code;
+}
+
+
+
diff --git a/myisam/rt_test.c b/myisam/rt_test.c
new file mode 100644
index 00000000000..65613bad47f
--- /dev/null
+++ b/myisam/rt_test.c
@@ -0,0 +1,421 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/* Testing of the basic functions of a MyISAM rtree table */
+/* Written by Alex Barkov who has a shared copyright to this code */
+
+
+#include "myisam.h"
+#include "rt_index.h"
+
+#define MAX_REC_LENGTH 1024
+#define ndims 2
+#define KEYALG HA_KEY_ALG_RTREE
+
+static int read_with_pos(MI_INFO * file, int silent);
+static void create_record(char *record,uint rownr);
+static void create_record1(char *record,uint rownr);
+static void print_record(char * record,my_off_t offs,const char * tail);
+static int run_test(const char *filename);
+
+
+int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
+{
+ MY_INIT(argv[0]);
+ exit(run_test("rt_test"));
+}
+
+
+
+int run_test(const char *filename)
+{
+ MI_INFO *file;
+ MI_UNIQUEDEF uniquedef;
+ MI_CREATE_INFO create_info;
+ MI_COLUMNDEF recinfo[20];
+ MI_KEYDEF keyinfo[20];
+ HA_KEYSEG keyseg[20];
+
+ int silent=0;
+ int opt_unique=0;
+ int create_flag=0;
+ int key_type=HA_KEYTYPE_DOUBLE;
+ int key_length=8;
+ int null_fields=0;
+ int nrecords=30;
+ int rec_length=0;
+ int uniques=0;
+ int i;
+ int error;
+ int row_count=0;
+ char record[MAX_REC_LENGTH];
+ char read_record[MAX_REC_LENGTH];
+ int upd= 10;
+ ha_rows hrows;
+
+
+
+ /* Define a column for NULLs and DEL markers*/
+
+ recinfo[0].type=FIELD_NORMAL;
+ recinfo[0].length=1; /* For NULL bits */
+ rec_length=1;
+
+
+ /* Define 2*ndims columns for coordinates*/
+
+ for (i=1; i<=2*ndims ;i++){
+ recinfo[i].type=FIELD_NORMAL;
+ recinfo[i].length=key_length;
+ rec_length+=key_length;
+ }
+
+
+ /* Define a key with 2*ndims segments */
+
+ keyinfo[0].seg=keyseg;
+ keyinfo[0].keysegs=2*ndims;
+ keyinfo[0].flag=0;
+ keyinfo[0].key_alg=KEYALG;
+
+ for (i=0; i<2*ndims; i++){
+ keyinfo[0].seg[i].type= key_type;
+ keyinfo[0].seg[i].flag=0; /* Things like HA_REVERSE_SORT */
+ keyinfo[0].seg[i].start= (key_length*i)+1;
+ keyinfo[0].seg[i].length=key_length;
+ keyinfo[0].seg[i].null_bit= null_fields ? 2 : 0;
+ keyinfo[0].seg[i].null_pos=0;
+ keyinfo[0].seg[i].language=MY_CHARSET_CURRENT;
+ }
+
+
+ if(!silent)
+ printf("- Creating isam-file\n");
+
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.max_rows=10000000;
+
+ if (mi_create(filename,
+ 1, /* keys */
+ keyinfo,
+ 1+2*ndims+opt_unique, /* columns */
+ recinfo,uniques,&uniquedef,&create_info,create_flag))
+ goto err;
+
+
+
+
+ if(!silent)
+ printf("- Open isam-file\n");
+
+ if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
+ goto err;
+
+
+ if (!silent)
+ printf("- Writing key:s\n");
+
+ for (i=0; i<nrecords; i++ )
+ {
+ create_record(record,i);
+ error=mi_write(file,record);
+ print_record(record,mi_position(file),"\n");
+ if (!error)
+ {
+ row_count++;
+ }
+ else
+ {
+ printf("mi_write: %d\n", error);
+ goto err;
+ }
+ }
+
+
+ if((error=read_with_pos(file,silent)))
+ goto err;
+
+
+ if (!silent)
+ printf("- Reading rows with key\n");
+
+ for (i=0 ; i < nrecords ; i++)
+ {
+ my_errno=0;
+ create_record(record,i);
+
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rkey(file,read_record,0,record+1,0,HA_READ_MBR_EQUAL);
+
+ if(error && error!=HA_ERR_KEY_NOT_FOUND)
+ {
+ printf(" mi_rkey: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ if(error == HA_ERR_KEY_NOT_FOUND)
+ {
+ print_record(record,mi_position(file)," NOT FOUND\n");
+ continue;
+ }
+ print_record(read_record,mi_position(file),"\n");
+ }
+
+
+
+
+
+ if (!silent)
+ printf("- Deleting rows\n");
+ for (i=0; i < nrecords/4; i++)
+ {
+ my_errno=0;
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
+ if(error)
+ {
+ printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file),"\n");
+
+ error=mi_delete(file,read_record);
+ if(error)
+ {
+ printf("pos: %2d mi_delete: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ }
+
+
+ if (!silent)
+ printf("- Updating rows with position\n");
+ for (i=0; i < (nrecords - nrecords/4) ; i++)
+ {
+ my_errno=0;
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
+ if(error)
+ {
+ if(error==HA_ERR_RECORD_DELETED)
+ continue;
+ printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file),"");
+ create_record(record,i+nrecords*upd);
+ printf("\t-> ");
+ print_record(record,mi_position(file),"\n");
+ error=mi_update(file,read_record,record);
+ if(error)
+ {
+ printf("pos: %2d mi_update: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ }
+
+
+ if((error=read_with_pos(file,silent)))
+ goto err;
+
+
+
+ if (!silent)
+ printf("- Test mi_rkey then a sequence of mi_rnext_same\n");
+
+ create_record(record, nrecords*4/5);
+ print_record(record,0," search for\n");
+
+ if ((error=mi_rkey(file,read_record,0,record+1,0,HA_READ_MBR_INTERSECT)))
+ {
+ printf("mi_rkey: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file)," mi_rkey\n");
+ row_count=1;
+
+
+ do {
+ if((error=mi_rnext_same(file,read_record)))
+ {
+ if(error==HA_ERR_END_OF_FILE)
+ break;
+ printf("mi_next: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file)," mi_rnext_same\n");
+ row_count++;
+ }while(1);
+ printf(" %d rows\n",row_count);
+
+
+
+
+
+
+ if (!silent)
+ printf("- Test mi_rfirst then a sequence of mi_rnext\n");
+
+ error=mi_rfirst(file,read_record,0);
+ if (error)
+ {
+ printf("mi_rfirst: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ row_count=1;
+ print_record(read_record,mi_position(file)," mi_frirst\n");
+
+ for(i=0;i<nrecords;i++) {
+ if((error=mi_rnext(file,read_record,0)))
+ {
+ if(error==HA_ERR_END_OF_FILE)
+ break;
+ printf("mi_next: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file)," mi_rnext\n");
+ row_count++;
+ }
+ printf(" %d rows\n",row_count);
+
+
+ if (!silent)
+ printf("- Test mi_records_in_range()\n");
+
+ create_record1(record, nrecords*4/5);
+ print_record(record,0,"\n");
+ hrows=mi_records_in_range(file,0,record+1,0,HA_READ_MBR_INTERSECT,record+1,0,0);
+ printf(" %ld rows\n",hrows);
+
+
+ if (mi_close(file)) goto err;
+ my_end(MY_CHECK_ERROR);
+
+ return 0;
+
+err:
+ printf("got error: %3d when using myisam-database\n",my_errno);
+ return 1; /* skipp warning */
+}
+
+
+
+static int read_with_pos (MI_INFO * file,int silent)
+{
+ int error;
+ int i;
+ char read_record[MAX_REC_LENGTH];
+
+ if (!silent)
+ printf("- Reading rows with position\n");
+ for (i=0;;i++)
+ {
+ my_errno=0;
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
+ if(error)
+ {
+ if(error==HA_ERR_END_OF_FILE)
+ break;
+ if(error==HA_ERR_RECORD_DELETED)
+ continue;
+ printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno);
+ return error;
+ }
+ print_record(read_record,mi_position(file),"\n");
+ }
+ return 0;
+}
+
+
+#ifdef NOT_USED
+static void bprint_record(char * record,
+ my_off_t offs __attribute__((unused)),
+ const char * tail)
+{
+ int i;
+ char * pos;
+ i=(unsigned char)record[0];
+ printf("%02X ",i);
+
+ for( pos=record+1, i=0; i<32; i++,pos++){
+ int b=(unsigned char)*pos;
+ printf("%02X",b);
+ }
+ printf("%s",tail);
+}
+#endif
+
+
+static void print_record(char * record,
+ my_off_t offs __attribute__((unused)),
+ const char * tail)
+{
+ int i;
+ char * pos;
+ double c;
+
+ printf(" rec=(%d)",(unsigned char)record[0]);
+ for ( pos=record+1, i=0; i<2*ndims; i++)
+ {
+ memcpy(&c,pos,sizeof(c));
+ float8get(c,pos);
+ printf(" %.14g ",c);
+ pos+=sizeof(c);
+ }
+ printf("pos=%ld",(long int)offs);
+ printf("%s",tail);
+}
+
+
+
+static void create_record1(char *record,uint rownr)
+{
+ int i;
+ char * pos;
+ double c=rownr+10;
+
+ bzero((char*) record,MAX_REC_LENGTH);
+ record[0]=0x01; /* DEL marker */
+
+ for ( pos=record+1, i=0; i<2*ndims; i++)
+ {
+ memcpy(pos,&c,sizeof(c));
+ float8store(pos,c);
+ pos+=sizeof(c);
+ }
+}
+
+
+static void create_record(char *record,uint rownr)
+{
+ int i;
+ char * pos;
+ double c=rownr+10;
+ double c0=0;
+
+ bzero((char*) record,MAX_REC_LENGTH);
+ record[0]=0x01; /* DEL marker */
+
+ for ( pos=record+1, i=0; i<ndims; i++)
+ {
+ memcpy(pos,&c0,sizeof(c0));
+ float8store(pos,c0);
+ pos+=sizeof(c0);
+ memcpy(pos,&c,sizeof(c));
+ float8store(pos,c);
+ pos+=sizeof(c);
+ }
+}
diff --git a/myisam/sort.c b/myisam/sort.c
index f45ecbaf3a1..d642638f06b 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -39,13 +39,10 @@
#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
#define DISK_BUFFER_SIZE (IO_SIZE*16)
-typedef struct st_buffpek {
- my_off_t file_pos; /* Where we are in the sort file */
- uchar *base,*key; /* Key pointers */
- ha_rows count; /* Number of rows in table */
- ulong mem_count; /* numbers of keys in memory */
- ulong max_keys; /* Max keys in buffert */
-} BUFFPEK;
+
+/*
+ Pointers of functions for store and read keys from temp file
+*/
extern void print_error _VARARGS((const char *fmt,...));
@@ -56,7 +53,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys,
DYNAMIC_ARRAY *buffpek,int *maxbuffer,
IO_CACHE *tempfile,
IO_CACHE *tempfile_for_exceptions);
-static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar * *sort_keys,
+static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar **sort_keys,
uint count, BUFFPEK *buffpek,IO_CACHE *tempfile);
static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key,
IO_CACHE *tempfile);
@@ -74,8 +71,20 @@ static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys,
BUFFPEK *Fb, BUFFPEK *Tb);
static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
IO_CACHE *);
-
-
+static int flush_ft_buf(MI_SORT_PARAM *info);
+
+static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys,
+ uint count, BUFFPEK *buffpek,
+ IO_CACHE *tempfile);
+static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek,
+ uint sort_length);
+static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,
+ char *key, uint sort_length, uint count);
+static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info,
+ IO_CACHE *to_file,
+ char* key, uint sort_length,
+ uint count);
+inline int my_var_write(MI_SORT_PARAM *info,IO_CACHE *to_file,char *bufs);
/*
Creates a index of sorted keys
@@ -102,6 +111,19 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
DBUG_ENTER("_create_index_by_sort");
DBUG_PRINT("enter",("sort_length: %d", info->key_length));
+ if (info->keyinfo->flag && HA_VAR_LENGTH_KEY)
+ {
+ info->write_keys=write_keys_varlen;
+ info->read_to_buffer=read_to_buffer_varlen;
+ info->write_key=write_merge_key_varlen;
+ }
+ else
+ {
+ info->write_keys=write_keys;
+ info->read_to_buffer=read_to_buffer;
+ info->write_key=write_merge_key;
+ }
+
my_b_clear(&tempfile);
my_b_clear(&tempfile_for_exceptions);
bzero((char*) &buffpek,sizeof(buffpek));
@@ -188,7 +210,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
goto err; /* purecov: inspected */
}
- if (flush_pending_blocks(info))
+ if (flush_ft_buf(info) || flush_pending_blocks(info))
goto err;
if (my_b_inited(&tempfile_for_exceptions))
@@ -249,7 +271,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
if (++idx == keys)
{
- if (write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek),
+ if (info->write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek),
tempfile))
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
@@ -263,7 +285,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ /* purecov: inspected */
if (buffpek->elements)
{
- if (write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek),
+ if (info->write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek),
tempfile))
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
*maxbuffer=buffpek->elements-1;
@@ -284,7 +306,7 @@ pthread_handler_decl(thr_find_all_keys,arg)
uint memavl,old_memavl,keys,sort_length;
uint idx, maxbuffer;
uchar **sort_keys=0;
-
+
error=1;
if (my_thread_init())
@@ -292,6 +314,19 @@ pthread_handler_decl(thr_find_all_keys,arg)
if (info->sort_info->got_error)
goto err;
+ if (info->keyinfo->flag && HA_VAR_LENGTH_KEY)
+ {
+ info->write_keys=write_keys_varlen;
+ info->read_to_buffer=read_to_buffer_varlen;
+ info->write_key=write_merge_key_varlen;
+ }
+ else
+ {
+ info->write_keys=write_keys;
+ info->read_to_buffer=read_to_buffer;
+ info->write_key=write_merge_key;
+ }
+
my_b_clear(&info->tempfile);
my_b_clear(&info->tempfile_for_exceptions);
bzero((char*) &info->buffpek,sizeof(info->buffpek));
@@ -364,7 +399,7 @@ pthread_handler_decl(thr_find_all_keys,arg)
if (++idx == keys)
{
- if (write_keys(info,sort_keys,idx-1,
+ if (info->write_keys(info,sort_keys,idx-1,
(BUFFPEK *)alloc_dynamic(&info->buffpek),
&info->tempfile))
goto err;
@@ -378,7 +413,7 @@ pthread_handler_decl(thr_find_all_keys,arg)
goto err;
if (info->buffpek.elements)
{
- if (write_keys(info,sort_keys, idx,
+ if (info->write_keys(info,sort_keys, idx,
(BUFFPEK *) alloc_dynamic(&info->buffpek), &info->tempfile))
goto err;
info->keys=(info->buffpek.elements-1)*(keys-1)+idx;
@@ -446,7 +481,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
fflush(stdout);
}
if (write_index(sinfo, sinfo->sort_keys, sinfo->keys) ||
- flush_pending_blocks(sinfo))
+ flush_ft_buf(sinfo) || flush_pending_blocks(sinfo))
got_error=1;
}
}
@@ -466,6 +501,18 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
{
if (got_error)
continue;
+ if (sinfo->keyinfo->flag && HA_VAR_LENGTH_KEY)
+ {
+ sinfo->write_keys=write_keys_varlen;
+ sinfo->read_to_buffer=read_to_buffer_varlen;
+ sinfo->write_key=write_merge_key_varlen;
+ }
+ else
+ {
+ sinfo->write_keys=write_keys;
+ sinfo->read_to_buffer=read_to_buffer;
+ sinfo->write_key=write_merge_key;
+ }
if (sinfo->buffpek.elements)
{
uint maxbuffer=sinfo->buffpek.elements-1;
@@ -507,6 +554,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
if (merge_index(sinfo, keys, (uchar **)mergebuf,
dynamic_element(&sinfo->buffpek,0,BUFFPEK *),
maxbuffer,&sinfo->tempfile) ||
+ flush_ft_buf(sinfo) ||
flush_pending_blocks(sinfo))
{
got_error=1;
@@ -555,8 +603,8 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
info);
if (!my_b_inited(tempfile) &&
- open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE,
- info->sort_info->param->myf_rw))
+ open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST",
+ DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
DBUG_RETURN(1); /* purecov: inspected */
buffpek->file_pos=my_b_tell(tempfile);
@@ -570,6 +618,43 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
DBUG_RETURN(0);
} /* write_keys */
+inline int my_var_write(MI_SORT_PARAM *info,IO_CACHE *to_file,char *bufs)
+{
+ int err;
+ uint16 len = _mi_keylength(info->keyinfo,bufs);
+
+ if ((err= my_b_write(to_file,(byte*)&len,sizeof(len))))
+ return (err);
+ if ((err= my_b_write(to_file,(byte*)bufs,(uint) len)))
+ return (err);
+ return (0);
+}
+
+
+static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info, register uchar **sort_keys,
+ uint count, BUFFPEK *buffpek, IO_CACHE *tempfile)
+{
+ uchar **end;
+ int err;
+ DBUG_ENTER("write_keys_varlen");
+
+ qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
+ info);
+ if (!my_b_inited(tempfile) &&
+ open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST",
+ DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
+ DBUG_RETURN(1); /* purecov: inspected */
+
+ buffpek->file_pos=my_b_tell(tempfile);
+ buffpek->count=count;
+ for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
+ {
+ if ((err= my_var_write(info,tempfile,*sort_keys)))
+ DBUG_RETURN(err);
+ }
+ DBUG_RETURN(0);
+} /* write_keys_varlen */
+
static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key,
IO_CACHE *tempfile)
@@ -578,8 +663,8 @@ static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key,
DBUG_ENTER("write_key");
if (!my_b_inited(tempfile) &&
- open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE,
- info->sort_info->param->myf_rw))
+ open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST",
+ DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
DBUG_RETURN(1);
if (my_b_write(tempfile,(byte*)&key_length,sizeof(key_length)) ||
@@ -621,8 +706,8 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys,
if (*maxbuffer < MERGEBUFF2)
DBUG_RETURN(0); /* purecov: inspected */
if (flush_io_cache(t_file) ||
- open_cached_file(&t_file2,info->tmpdir,"ST",DISK_BUFFER_SIZE,
- info->sort_info->param->myf_rw))
+ open_cached_file(&t_file2,my_tmpdir(info->tmpdir),"ST",
+ DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
DBUG_RETURN(1); /* purecov: inspected */
from_file= t_file ; to_file= &t_file2;
@@ -685,6 +770,62 @@ static uint NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
return (count*sort_length);
} /* read_to_buffer */
+static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
+ uint sort_length)
+{
+ register uint count;
+ uint16 length_of_key = 0;
+ uint idx;
+ uchar *buffp;
+
+ if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
+ {
+ buffp = buffpek->base;
+
+ for (idx=1;idx<=count;idx++)
+ {
+ if (my_pread(fromfile->file,(byte*)&length_of_key,sizeof(length_of_key),
+ buffpek->file_pos,MYF_RW))
+ return((uint) -1);
+ buffpek->file_pos+=sizeof(length_of_key);
+ if (my_pread(fromfile->file,(byte*) buffp,length_of_key,
+ buffpek->file_pos,MYF_RW))
+ return((uint) -1);
+ buffpek->file_pos+=length_of_key;
+ buffp = buffp + sort_length;
+ }
+ buffpek->key=buffpek->base;
+ buffpek->count-= count;
+ buffpek->mem_count= count;
+ }
+ return (count*sort_length);
+} /* read_to_buffer_varlen */
+
+
+static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info,
+ IO_CACHE *to_file,char* key,
+ uint sort_length, uint count)
+{
+ uint idx;
+
+ char *bufs = key;
+ for (idx=1;idx<=count;idx++)
+ {
+ int err;
+ if ((err= my_var_write(info,to_file,bufs)))
+ return (err);
+ bufs=bufs+sort_length;
+ }
+ return(0);
+}
+
+
+static int NEAR_F write_merge_key(MI_SORT_PARAM *info __attribute__((unused)),
+ IO_CACHE *to_file, char* key,
+ uint sort_length, uint count)
+{
+ return my_b_write(to_file,(byte*) key,(uint) sort_length*count);
+}
/*
Merge buffers to one buffer
@@ -703,6 +844,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar *strpos;
BUFFPEK *buffpek,**refpek;
QUEUE queue;
+ volatile bool *killed= killed_ptr(info->sort_info->param);
DBUG_ENTER("merge_buffers");
count=error=0;
@@ -723,8 +865,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
count+= buffpek->count;
buffpek->base= strpos;
buffpek->max_keys=maxcount;
- strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
- sort_length));
+ strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,sort_length));
if (error == -1)
goto err; /* purecov: inspected */
queue_insert(&queue,(char*) buffpek);
@@ -734,10 +875,14 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
{
for (;;)
{
+ if (*killed)
+ {
+ error=1; goto err;
+ }
buffpek=(BUFFPEK*) queue_top(&queue);
if (to_file)
{
- if (my_b_write(to_file,(byte*) buffpek->key,(uint) sort_length))
+ if (info->write_key(info,to_file,(byte*) buffpek->key,(uint) sort_length,1))
{
error=1; goto err; /* purecov: inspected */
}
@@ -752,7 +897,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
buffpek->key+=sort_length;
if (! --buffpek->mem_count)
{
- if (!(error=(int) read_to_buffer(from_file,buffpek,sort_length)))
+ if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length)))
{
uchar *base=buffpek->base;
uint max_keys=buffpek->max_keys;
@@ -792,8 +937,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
{
if (to_file)
{
- if (my_b_write(to_file,(byte*) buffpek->key,
- (sort_length*buffpek->mem_count)))
+ if (info->write_key(info,to_file,(byte*) buffpek->key,
+ sort_length,buffpek->mem_count))
{
error=1; goto err; /* purecov: inspected */
}
@@ -813,7 +958,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
}
}
}
- while ((error=(int) read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
+ while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
error != 0);
lastbuff->count=count;
@@ -838,3 +983,16 @@ merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys,
DBUG_RETURN(0);
} /* merge_index */
+static int
+flush_ft_buf(MI_SORT_PARAM *info)
+{
+ int err=0;
+ if (info->sort_info->ft_buf)
+ {
+ err=sort_ft_buf_flush(info);
+ my_free((gptr)info->sort_info->ft_buf, MYF(0));
+ info->sort_info->ft_buf=0;
+ }
+ return err;
+}
+
diff --git a/myisam/sp_defs.h b/myisam/sp_defs.h
new file mode 100644
index 00000000000..0acefe32f80
--- /dev/null
+++ b/myisam/sp_defs.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 _SP_DEFS_H
+#define _SP_DEFS_H
+
+#define SPDIMS 2
+#define SPTYPE HA_KEYTYPE_DOUBLE
+#define SPLEN 8
+
+enum wkbType
+{
+ wkbPoint = 1,
+ wkbLineString = 2,
+ wkbPolygon = 3,
+ wkbMultiPoint = 4,
+ wkbMultiLineString = 5,
+ wkbMultiPolygon = 6,
+ wkbGeometryCollection = 7
+};
+
+enum wkbByteOrder
+{
+ wkbXDR = 0, /* Big Endian */
+ wkbNDR = 1 /* Little Endian */
+};
+
+uint sp_make_key(register MI_INFO *info, uint keynr, uchar *key,
+ const byte *record, my_off_t filepos);
+
+#endif /* _SP_DEFS_H */
diff --git a/myisam/sp_key.c b/myisam/sp_key.c
new file mode 100644
index 00000000000..82c2b1f8510
--- /dev/null
+++ b/myisam/sp_key.c
@@ -0,0 +1,261 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "myisamdef.h"
+#include "sp_defs.h"
+
+static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr);
+static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr);
+static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr);
+static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr);
+static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ double *mbr, int top);
+static int sp_mbr_from_wkb(uchar (*wkb), uint size, uint n_dims, double *mbr);
+
+
+uint sp_make_key(register MI_INFO *info, uint keynr, uchar *key,
+ const byte *record, my_off_t filepos)
+{
+ HA_KEYSEG *keyseg;
+ MI_KEYDEF *keyinfo = &info->s->keyinfo[keynr];
+ uint len = 0;
+ byte *pos;
+ uint dlen;
+ uchar *dptr;
+ double mbr[SPDIMS * 2];
+ uint i;
+
+ keyseg = &keyinfo->seg[-1];
+ pos = (byte*)record + keyseg->start;
+
+ dlen = _mi_calc_blob_length(keyseg->bit_start, pos);
+ memcpy_fixed(&dptr, pos + keyseg->bit_start, sizeof(char*));
+ sp_mbr_from_wkb(dptr, dlen, SPDIMS, mbr);
+
+ for (i = 0, keyseg = keyinfo->seg; keyseg->type; keyseg++, i++)
+ {
+ uint length = keyseg->length;
+
+ pos = ((byte*)mbr) + keyseg->start;
+ if (keyseg->flag & HA_SWAP_KEY)
+ {
+ pos += length;
+ while (length--)
+ {
+ *key++ = *--pos;
+ }
+ }
+ else
+ {
+ memcpy((byte*)key, pos, length);
+ key += keyseg->length;
+ }
+ len += keyseg->length;
+ }
+ _mi_dpointer(info, key, filepos);
+ return len;
+}
+
+/*
+Calculate minimal bounding rectangle (mbr) of the spatial object
+stored in "well-known binary representation" (wkb) format.
+*/
+static int sp_mbr_from_wkb(uchar *wkb, uint size, uint n_dims, double *mbr)
+{
+ uint i;
+
+ for (i=0; i < n_dims; ++i)
+ {
+ mbr[i * 2] = DBL_MAX;
+ mbr[i * 2 + 1] = -DBL_MAX;
+ }
+
+ return sp_get_geometry_mbr(&wkb, wkb + size, n_dims, mbr, 1);
+}
+
+/*
+ Add one point stored in wkb to mbr
+*/
+
+static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order __attribute__((unused)),
+ double *mbr)
+{
+ double ord;
+ double *mbr_end = mbr + n_dims * 2;
+
+ while (mbr < mbr_end)
+ {
+ if ((*wkb) > end - 8)
+ return -1;
+ float8get(ord, (*wkb));
+ (*wkb) += 8;
+ if (ord < *mbr)
+ *mbr = ord;
+ mbr++;
+ if (ord > *mbr)
+ *mbr = ord;
+ mbr++;
+ }
+ return 0;
+}
+
+
+static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr)
+{
+ return sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr);
+}
+
+
+static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr)
+{
+ uint n_points;
+
+ n_points = uint4korr(*wkb);
+ (*wkb) += 4;
+ for (; n_points > 0; --n_points)
+ {
+ /* Add next point to mbr */
+ if (sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr))
+ return -1;
+ }
+ return 0;
+}
+
+
+static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ uchar byte_order, double *mbr)
+{
+ uint n_linear_rings;
+ uint n_points;
+
+ n_linear_rings = uint4korr((*wkb));
+ (*wkb) += 4;
+
+ for (; n_linear_rings > 0; --n_linear_rings)
+ {
+ n_points = uint4korr((*wkb));
+ (*wkb) += 4;
+ for (; n_points > 0; --n_points)
+ {
+ /* Add next point to mbr */
+ if (sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr))
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
+ double *mbr, int top)
+{
+ int res;
+ uchar byte_order;
+ uint wkb_type;
+
+ byte_order = *(*wkb);
+ ++(*wkb);
+
+ wkb_type = uint4korr((*wkb));
+ (*wkb) += 4;
+
+ switch ((enum wkbType) wkb_type)
+ {
+ case wkbPoint:
+ res = sp_get_point_mbr(wkb, end, n_dims, byte_order, mbr);
+ break;
+ case wkbLineString:
+ res = sp_get_linestring_mbr(wkb, end, n_dims, byte_order, mbr);
+ break;
+ case wkbPolygon:
+ res = sp_get_polygon_mbr(wkb, end, n_dims, byte_order, mbr);
+ break;
+ case wkbMultiPoint:
+ {
+ uint n_items;
+ n_items = uint4korr((*wkb));
+ (*wkb) += 4;
+ for (; n_items > 0; --n_items)
+ {
+ byte_order = *(*wkb);
+ ++(*wkb);
+ (*wkb) += 4;
+ if (sp_get_point_mbr(wkb, end, n_dims, byte_order, mbr))
+ return -1;
+ }
+ res = 0;
+ break;
+ }
+ case wkbMultiLineString:
+ {
+ uint n_items;
+ n_items = uint4korr((*wkb));
+ (*wkb) += 4;
+ for (; n_items > 0; --n_items)
+ {
+ byte_order = *(*wkb);
+ ++(*wkb);
+ (*wkb) += 4;
+ if (sp_get_linestring_mbr(wkb, end, n_dims, byte_order, mbr))
+ return -1;
+ }
+ res = 0;
+ break;
+ }
+ case wkbMultiPolygon:
+ {
+ uint n_items;
+ n_items = uint4korr((*wkb));
+ (*wkb) += 4;
+ for (; n_items > 0; --n_items)
+ {
+ byte_order = *(*wkb);
+ ++(*wkb);
+ (*wkb) += 4;
+ if (sp_get_polygon_mbr(wkb, end, n_dims, byte_order, mbr))
+ return -1;
+ }
+ res = 0;
+ break;
+ }
+ case wkbGeometryCollection:
+ {
+ uint n_items;
+
+ if (!top)
+ return -1;
+
+ n_items = uint4korr((*wkb));
+ (*wkb) += 4;
+ for (; n_items > 0; --n_items)
+ {
+ if (sp_get_geometry_mbr(wkb, end, n_dims, mbr, 0))
+ return -1;
+ }
+ res = 0;
+ break;
+ }
+ default:
+ res = -1;
+ }
+ return res;
+}
diff --git a/myisam/sp_test.c b/myisam/sp_test.c
new file mode 100644
index 00000000000..7ae41c2088c
--- /dev/null
+++ b/myisam/sp_test.c
@@ -0,0 +1,576 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/* Testing of the basic functions of a MyISAM spatial table */
+/* Written by Alex Barkov, who has a shared copyright to this code */
+
+#include "myisam.h"
+#include "sp_defs.h"
+
+#define MAX_REC_LENGTH 1024
+#define KEYALG HA_KEY_ALG_RTREE
+
+static void create_linestring(char *record,uint rownr);
+static void print_record(char * record,my_off_t offs,const char * tail);
+
+static void create_key(char *key,uint rownr);
+static void print_key(const char *key,const char * tail);
+
+static int run_test(const char *filename);
+static int read_with_pos(MI_INFO * file, int silent);
+
+static int rtree_CreateLineStringWKB(double *ords, uint n_dims, uint n_points, uchar *wkb);
+static void rtree_PrintWKB(uchar *wkb, uint n_dims);
+
+
+static char blob_key[MAX_REC_LENGTH];
+
+
+int main(int argc __attribute__((unused)),char *argv[])
+{
+ MY_INIT(argv[0]);
+ exit(run_test("sp_test"));
+}
+
+
+
+int run_test(const char *filename)
+{
+ MI_INFO *file;
+ MI_UNIQUEDEF uniquedef;
+ MI_CREATE_INFO create_info;
+ MI_COLUMNDEF recinfo[20];
+ MI_KEYDEF keyinfo[20];
+ HA_KEYSEG keyseg[20];
+
+ int silent=0;
+ int create_flag=0;
+ int null_fields=0;
+ int nrecords=30;
+ int uniques=0;
+ int i;
+ int error;
+ int row_count=0;
+ char record[MAX_REC_LENGTH];
+ char key[MAX_REC_LENGTH];
+ char read_record[MAX_REC_LENGTH];
+ int upd=10;
+ ha_rows hrows;
+
+ /* Define a column for NULLs and DEL markers*/
+
+ recinfo[0].type=FIELD_NORMAL;
+ recinfo[0].length=1; /* For NULL bits */
+
+
+ /* Define spatial column */
+
+ recinfo[1].type=FIELD_BLOB;
+ recinfo[1].length=4 + mi_portable_sizeof_char_ptr;
+
+
+
+ /* Define a key with 1 spatial segment */
+
+ keyinfo[0].seg=keyseg;
+ keyinfo[0].keysegs=1;
+ keyinfo[0].flag=HA_SPATIAL;
+ keyinfo[0].key_alg=KEYALG;
+
+ keyinfo[0].seg[0].type= HA_KEYTYPE_BINARY;
+ keyinfo[0].seg[0].flag=0;
+ keyinfo[0].seg[0].start= 1;
+ keyinfo[0].seg[0].length=1; /* Spatial ignores it anyway */
+ keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0;
+ keyinfo[0].seg[0].null_pos=0;
+ keyinfo[0].seg[0].language=MY_CHARSET_CURRENT;
+ keyinfo[0].seg[0].bit_start=4; /* Long BLOB */
+
+
+ if(!silent)
+ printf("- Creating isam-file\n");
+
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.max_rows=10000000;
+
+ if (mi_create(filename,
+ 1, /* keys */
+ keyinfo,
+ 2, /* columns */
+ recinfo,uniques,&uniquedef,&create_info,create_flag))
+ goto err;
+
+
+
+
+ if(!silent)
+ printf("- Open isam-file\n");
+
+ if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
+ goto err;
+
+
+
+ if (!silent)
+ printf("- Writing key:s\n");
+
+ for (i=0; i<nrecords; i++ )
+ {
+ create_linestring(record,i);
+ error=mi_write(file,record);
+ print_record(record,mi_position(file),"\n");
+ if (!error)
+ {
+ row_count++;
+ }
+ else
+ {
+ printf("mi_write: %d\n", error);
+ goto err;
+ }
+ }
+
+
+ if((error=read_with_pos(file,silent)))
+ goto err;
+
+
+ if (!silent)
+ printf("- Deleting rows with position\n");
+ for (i=0; i < nrecords/4; i++)
+ {
+ my_errno=0;
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
+ if(error)
+ {
+ printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file),"\n");
+ error=mi_delete(file,read_record);
+ if(error)
+ {
+ printf("pos: %2d mi_delete: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ }
+
+
+
+
+ if (!silent)
+ printf("- Updating rows with position\n");
+ for (i=0; i < nrecords/2 ; i++)
+ {
+ my_errno=0;
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
+ if(error)
+ {
+ if(error==HA_ERR_RECORD_DELETED)
+ continue;
+ printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file),"");
+ create_linestring(record,i+nrecords*upd);
+ printf("\t-> ");
+ print_record(record,mi_position(file),"\n");
+ error=mi_update(file,read_record,record);
+ if(error)
+ {
+ printf("pos: %2d mi_update: %3d errno: %3d\n",i,error,my_errno);
+ goto err;
+ }
+ }
+
+
+
+ if((error=read_with_pos(file,silent)))
+ goto err;
+
+
+
+ if (!silent)
+ printf("- Test mi_rkey then a sequence of mi_rnext_same\n");
+
+ create_key(key, nrecords*4/5);
+ print_key(key," search for INTERSECT\n");
+
+ if ((error=mi_rkey(file,read_record,0,key,0,HA_READ_MBR_INTERSECT)))
+ {
+ printf("mi_rkey: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file)," mi_rkey\n");
+ row_count=1;
+
+
+ do {
+ if((error=mi_rnext_same(file,read_record)))
+ {
+ if(error==HA_ERR_END_OF_FILE)
+ break;
+ printf("mi_next: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file)," mi_rnext_same\n");
+ row_count++;
+ }while(1);
+ printf(" %d rows\n",row_count);
+
+
+
+
+
+
+ if (!silent)
+ printf("- Test mi_rfirst then a sequence of mi_rnext\n");
+
+ error=mi_rfirst(file,read_record,0);
+ if (error)
+ {
+ printf("mi_rfirst: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ row_count=1;
+ print_record(read_record,mi_position(file)," mi_frirst\n");
+
+ for(i=0;i<nrecords;i++) {
+ if((error=mi_rnext(file,read_record,0)))
+ {
+ if(error==HA_ERR_END_OF_FILE)
+ break;
+ printf("mi_next: %3d errno: %3d\n",error,my_errno);
+ goto err;
+ }
+ print_record(read_record,mi_position(file)," mi_rnext\n");
+ row_count++;
+ }
+ printf(" %d rows\n",row_count);
+
+
+
+
+ if (!silent)
+ printf("- Test mi_records_in_range()\n");
+
+ create_key(key, nrecords*upd);
+ print_key(key," INTERSECT\n");
+ hrows=mi_records_in_range(file,0,key,0,HA_READ_MBR_INTERSECT,record+1,0,0);
+ printf(" %ld rows\n",hrows);
+
+
+ if (mi_close(file)) goto err;
+ my_end(MY_CHECK_ERROR);
+
+ return 0;
+
+err:
+ printf("got error: %3d when using myisam-database\n",my_errno);
+ return 1; /* skipp warning */
+}
+
+
+
+static int read_with_pos (MI_INFO * file,int silent)
+{
+ int error;
+ int i;
+ char read_record[MAX_REC_LENGTH];
+ int rows=0;
+
+ if (!silent)
+ printf("- Reading rows with position\n");
+ for (i=0;;i++)
+ {
+ my_errno=0;
+ bzero((char*) read_record,MAX_REC_LENGTH);
+ error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
+ if(error)
+ {
+ if(error==HA_ERR_END_OF_FILE)
+ break;
+ if(error==HA_ERR_RECORD_DELETED)
+ continue;
+ printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno);
+ return error;
+ }
+ rows++;
+ print_record(read_record,mi_position(file),"\n");
+ }
+ printf(" %d rows\n",rows);
+ return 0;
+}
+
+
+#ifdef NOT_USED
+static void bprint_record(char * record,
+ my_off_t offs __attribute__((unused)),
+ const char * tail)
+{
+ int i;
+ char * pos;
+ i=(unsigned char)record[0];
+ printf("%02X ",i);
+
+ for( pos=record+1, i=0; i<32; i++,pos++)
+ {
+ int b=(unsigned char)*pos;
+ printf("%02X",b);
+ }
+ printf("%s",tail);
+}
+#endif
+
+
+static void print_record(char * record, my_off_t offs,const char * tail)
+{
+ char *pos;
+ char *ptr;
+ uint len;
+
+ printf(" rec=(%d)",(unsigned char)record[0]);
+ pos=record+1;
+ len=sint4korr(pos);
+ pos+=4;
+ printf(" len=%d ",len);
+ memcpy_fixed(&ptr,pos,sizeof(char*));
+ if(ptr)
+ rtree_PrintWKB(ptr,SPDIMS);
+ else
+ printf("<NULL> ");
+ printf(" offs=%ld ",(long int)offs);
+ printf("%s",tail);
+}
+
+
+
+#ifdef NOT_USED
+static void create_point(char *record,uint rownr)
+{
+ uint tmp;
+ char *ptr;
+ char *pos=record;
+ double x[200];
+ int i;
+
+ for(i=0;i<SPDIMS;i++)
+ x[i]=rownr;
+
+ bzero((char*) record,MAX_REC_LENGTH);
+ *pos=0x01; /* DEL marker */
+ pos++;
+
+ memset(blob_key,0,sizeof(blob_key));
+ tmp=rtree_CreatePointWKB(x,SPDIMS,blob_key);
+
+ int4store(pos,tmp);
+ pos+=4;
+
+ ptr=blob_key;
+ memcpy_fixed(pos,&ptr,sizeof(char*));
+}
+#endif
+
+
+static void create_linestring(char *record,uint rownr)
+{
+ uint tmp;
+ char *ptr;
+ char *pos=record;
+ double x[200];
+ int i,j;
+ int npoints=2;
+
+ for(j=0;j<npoints;j++)
+ for(i=0;i<SPDIMS;i++)
+ x[i+j*SPDIMS]=rownr*j;
+
+ bzero((char*) record,MAX_REC_LENGTH);
+ *pos=0x01; /* DEL marker */
+ pos++;
+
+ memset(blob_key,0,sizeof(blob_key));
+ tmp=rtree_CreateLineStringWKB(x,SPDIMS,npoints,blob_key);
+
+ int4store(pos,tmp);
+ pos+=4;
+
+ ptr=blob_key;
+ memcpy_fixed(pos,&ptr,sizeof(char*));
+}
+
+
+static void create_key(char *key,uint rownr)
+{
+ double c=rownr;
+ char *pos;
+ uint i;
+
+ bzero(key,MAX_REC_LENGTH);
+ for ( pos=key, i=0; i<2*SPDIMS; i++)
+ {
+ float8store(pos,c);
+ pos+=sizeof(c);
+ }
+}
+
+static void print_key(const char *key,const char * tail)
+{
+ double c;
+ uint i;
+
+ printf(" key=");
+ for (i=0; i<2*SPDIMS; i++)
+ {
+ float8get(c,key);
+ key+=sizeof(c);
+ printf("%.14g ",c);
+ }
+ printf("%s",tail);
+}
+
+
+
+#ifdef NOT_USED
+
+static int rtree_CreatePointWKB(double *ords, uint n_dims, uchar *wkb)
+{
+ uint i;
+
+ *wkb = wkbXDR;
+ ++wkb;
+ int4store(wkb, wkbPoint);
+ wkb += 4;
+
+ for (i=0; i < n_dims; ++i)
+ {
+ float8store(wkb, ords[i]);
+ wkb += 8;
+ }
+ return 5 + n_dims * 8;
+}
+#endif
+
+
+static int rtree_CreateLineStringWKB(double *ords, uint n_dims, uint n_points,
+ uchar *wkb)
+{
+ uint i;
+ uint n_ords = n_dims * n_points;
+
+ *wkb = wkbXDR;
+ ++wkb;
+ int4store(wkb, wkbLineString);
+ wkb += 4;
+ int4store(wkb, n_points);
+ wkb += 4;
+ for (i=0; i < n_ords; ++i)
+ {
+ float8store(wkb, ords[i]);
+ wkb += 8;
+ }
+ return 9 + n_points * n_dims * 8;
+}
+
+static void rtree_PrintWKB(uchar *wkb, uint n_dims)
+{
+ uint wkb_type;
+
+ ++wkb;
+ wkb_type = uint4korr(wkb);
+ wkb += 4;
+
+ switch ((enum wkbType)wkb_type)
+ {
+ case wkbPoint:
+ {
+ uint i;
+ double ord;
+
+ printf("POINT(");
+ for (i=0; i < n_dims; ++i)
+ {
+ float8get(ord, wkb);
+ wkb += 8;
+ printf("%.14g", ord);
+ if (i < n_dims - 1)
+ printf(" ");
+ else
+ printf(")");
+ }
+ break;
+ }
+ case wkbLineString:
+ {
+ uint p, i;
+ uint n_points;
+ double ord;
+
+ printf("LineString(");
+ n_points = uint4korr(wkb);
+ wkb += 4;
+ for (p=0; p < n_points; ++p)
+ {
+ for (i=0; i < n_dims; ++i)
+ {
+ float8get(ord, wkb);
+ wkb += 8;
+ printf("%.14g", ord);
+ if (i < n_dims - 1)
+ printf(" ");
+ }
+ if (p < n_points - 1)
+ printf(", ");
+ else
+ printf(")");
+ }
+ break;
+ }
+ case wkbPolygon:
+ {
+ printf("POLYGON(...)");
+ break;
+ }
+ case wkbMultiPoint:
+ {
+ printf("MULTIPOINT(...)");
+ break;
+ }
+ case wkbMultiLineString:
+ {
+ printf("MULTILINESTRING(...)");
+ break;
+ }
+ case wkbMultiPolygon:
+ {
+ printf("MULTIPOLYGON(...)");
+ break;
+ }
+ case wkbGeometryCollection:
+ {
+ printf("GEOMETRYCOLLECTION(...)");
+ break;
+ }
+ default:
+ {
+ printf("UNKNOWN GEOMETRY TYPE");
+ break;
+ }
+ }
+}
diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am
index 6a6824affba..b5b1260385b 100644
--- a/myisammrg/Makefile.am
+++ b/myisammrg/Makefile.am
@@ -14,14 +14,15 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
pkglib_LIBRARIES = libmyisammrg.a
noinst_HEADERS = myrg_def.h
libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \
myrg_rrnd.c myrg_update.c myrg_delete.c myrg_rsame.c \
myrg_panic.c myrg_close.c myrg_create.c myrg_static.c \
myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \
- myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c
+ myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c \
+ myrg_rnext_same.c
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/myisammrg/myrg_queue.c b/myisammrg/myrg_queue.c
index b4f729fc2cf..08a248bdd64 100644
--- a/myisammrg/myrg_queue.c
+++ b/myisammrg/myrg_queue.c
@@ -23,7 +23,7 @@ static int queue_key_cmp(void *keyseg, byte *a, byte *b)
MI_INFO *aa=((MYRG_TABLE *)a)->table;
MI_INFO *bb=((MYRG_TABLE *)b)->table;
uint not_used;
- int ret= _mi_key_cmp((MI_KEYSEG *)keyseg, aa->lastkey, bb->lastkey,
+ int ret= ha_key_cmp((HA_KEYSEG *)keyseg, aa->lastkey, bb->lastkey,
USE_WHOLE_KEY, SEARCH_FIND, &not_used);
return ret < 0 ? -1 : ret > 0 ? 1 : 0;
} /* queue_key_cmp */
diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c
index ba042352a51..c0cef5a4eca 100644
--- a/myisammrg/myrg_rkey.c
+++ b/myisammrg/myrg_rkey.c
@@ -62,9 +62,8 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
}
else
{
- mi->use_packed_key=1;
+ mi->once_flags|= USE_PACKED_KEYS;
err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag);
- mi->use_packed_key=0;
}
info->last_used_table=table+1;
@@ -83,5 +82,6 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
return HA_ERR_KEY_NOT_FOUND;
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
+ mi->once_flags|= RRND_PRESERVE_LASTINX;
return mi_rrnd(mi,record,mi->lastpos);
}
diff --git a/myisammrg/myrg_rnext_same.c b/myisammrg/myrg_rnext_same.c
new file mode 100644
index 00000000000..b569459b77d
--- /dev/null
+++ b/myisammrg/myrg_rnext_same.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "myrg_def.h"
+
+int myrg_rnext_same(MYRG_INFO *info, byte *buf)
+{
+ uint err;
+ MI_INFO *mi;
+
+ if (!info->current_table)
+ return (HA_ERR_KEY_NOT_FOUND);
+
+ err=mi_rnext_same(info->current_table->table,buf);
+ if (err == HA_ERR_END_OF_FILE)
+ {
+ queue_remove(&(info->by_key),0);
+ if (!info->by_key.elements)
+ return HA_ERR_END_OF_FILE;
+
+ mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
+ mi->once_flags|= RRND_PRESERVE_LASTINX;
+ return mi_rrnd(mi,buf,mi->lastpos);
+ }
+ return err;
+}
+
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index 57b22f0edbc..84d4a5bba9a 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -30,7 +30,7 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(distdir)/t
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
- $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.001 $(distdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
install-data-local:
$(mkinstalldirs) \
diff --git a/mysql-test/README b/mysql-test/README
index c5dc3e219de..7c6efe7940e 100644
--- a/mysql-test/README
+++ b/mysql-test/README
@@ -1,6 +1,10 @@
This directory contains a test suite for mysql daemon. To run
the currently existing test cases, simply execute ./mysql-test-run in
this directory. It will fire up the newly built mysqld and test it.
+
+If you want to run the test with a running MySQL server use the --external
+option to mysql-test-run.
+
Note that you do not have to have to do make install, and you could
actually have a co-existing MySQL installation - the tests will not
conflict with it.
@@ -13,8 +17,7 @@ http://www.mysql.com/doc/M/y/MySQL_test_suite.html
You can create your own test cases. To create a test case:
- cd t
- vi test_case_name.test
+ xeamacs t/test_case_name.test
in the file, put a set of SQL commands that will create some tables,
load test data, run some queries to manipulate it.
diff --git a/mysql-test/create-test-result b/mysql-test/create-test-result
index bfd64f32fc5..b9be2300976 100755
--- a/mysql-test/create-test-result
+++ b/mysql-test/create-test-result
@@ -27,14 +27,13 @@ test_name=$1
[ -z $test_name ] && usage
result_file=$RESULT_DIR/$test_name.result
+reject_file=$RESULT_DIR/$test_name.reject
[ -f $result_file ] && die "result file $result_file has already been created"
touch $result_file
echo "Running the test case against empty file, will fail, but don't worry"
-./mysql-test-run --do-test=$test_name
-
-reject_file=$result_file.reject
+./mysql-test-run --local $test_name
if [ -f $reject_file ] ; then
echo "Below are the contents of the reject file:"
diff --git a/mysql-test/include/master-slave.inc b/mysql-test/include/master-slave.inc
index 474b1357e9e..008466c426f 100644
--- a/mysql-test/include/master-slave.inc
+++ b/mysql-test/include/master-slave.inc
@@ -4,16 +4,20 @@ connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT,);
connection slave;
--error 0,1199
-!slave stop;
+!stop slave;
@r/slave-stopped.result show status like 'Slave_running';
connection master;
+--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+--enable_warnings
reset master;
connection slave;
reset slave;
# Clean up old test tables
+--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+--enable_warnings
+start slave;
@r/slave-running.result show status like 'Slave_running';
# Set the default connection to 'master'
diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh
index 8f90301d2d8..fc3e00d8501 100644
--- a/mysql-test/install_test_db.sh
+++ b/mysql-test/install_test_db.sh
@@ -66,6 +66,9 @@ c_h="" i_h=""
c_u="" i_u=""
c_f="" i_f=""
c_t="" c_c=""
+c_hl="" c_hl=""
+c_hc="" c_hc=""
+c_clr="" c_clr=""
# Check for old tables
if test ! -f $mdata/db.frm
@@ -123,7 +126,7 @@ then
c_u="$c_u CREATE TABLE user ("
c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL,"
c_u="$c_u User char(16) binary DEFAULT '' NOT NULL,"
- c_u="$c_u Password char(16) binary DEFAULT '' NOT NULL,"
+ c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL,"
c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
@@ -207,6 +210,42 @@ then
c_c="$c_c comment='Column privileges';"
fi
+if test ! -f $mdata/help_topic.frm
+then
+ c_hl="$c_hl CREATE TABLE help_topic ("
+ c_hl="$c_hl help_topic_id int unsigned not null auto_increment,"
+ c_hl="$c_hl name varchar(64) not null,"
+ c_hl="$c_hl description text not null,"
+ c_hl="$c_hl example text not null,"
+ c_hl="$c_hl url varchar(128) not null,"
+ c_hl="$c_hl primary key (help_topic_id),"
+ c_hl="$c_hl unique index (name)"
+ c_hl="$c_hl )"
+ c_hl="$c_hl comment='help topics';"
+fi
+
+if test ! -f $mdata/help_category.frm
+then
+ c_clr="$c_clr CREATE TABLE help_category ("
+ c_clr="$c_clr help_category_id smallint unsigned not null auto_increment,"
+ c_clr="$c_clr name varchar(64) not null,"
+ c_clr="$c_clr url varchar(128) not null,"
+ c_clr="$c_clr primary key (help_category_id),"
+ c_clr="$c_clr unique index (name)"
+ c_clr="$c_clr )"
+ c_clr="$c_clr comment='help topics-categories relation';"
+fi
+
+if test ! -f $mdata/help_relation.frm
+then
+ c_hc="$c_hc CREATE TABLE help_relation ("
+ c_hc="$c_hc help_topic_id int unsigned not null references help_topic,"
+ c_hc="$c_hc help_category_id smallint unsigned not null references help_category,"
+ c_hc="$c_hc primary key (help_category_id, help_topic_id),"
+ c_hc="$c_hc )"
+ c_hc="$c_hc comment='categories of help topics';"
+fi
+
mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
--basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG"
echo "running $mysqld_boot"
@@ -227,6 +266,10 @@ $i_f
$c_t
$c_c
+
+$c_hl
+$c_hc
+$c_clr
END_OF_DATA
then
exit 0
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 3e498703ada..e276a48bb6a 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -191,7 +191,7 @@ USER_TEST=
EXTRA_MASTER_OPT=""
EXTRA_MYSQL_TEST_OPT=""
-USE_RUNNING_SERVER=1
+USE_RUNNING_SERVER=""
DO_GCOV=""
DO_GDB=""
MANUAL_GDB=""
@@ -207,6 +207,7 @@ CHARACTER_SET=latin1
DBUSER=""
START_WAIT_TIMEOUT=10
STOP_WAIT_TIMEOUT=10
+TEST_REPLICATION=0
while test $# -gt 0; do
case "$1" in
@@ -280,6 +281,9 @@ while test $# -gt 0; do
--user-test=*)
USER_TEST=`$ECHO "$1" | $SED -e "s;--user-test=;;"`
;;
+ --rpl)
+ TEST_REPLICATION=1
+ ;;
--mysqld=*)
TMP=`$ECHO "$1" | $SED -e "s;--mysqld=;;"`
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $TMP"
@@ -330,7 +334,7 @@ while test $# -gt 0; do
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc"
SLEEP_TIME_AFTER_RESTART=10
- SLEEP_TIME_FOR_DELETE=120
+ SLEEP_TIME_FOR_DELETE=60
;;
--valgrind-options=*)
TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"`
@@ -621,7 +625,7 @@ report_stats () {
# Find errors
for i in "^Warning:" "^Error:" "^==.* at 0x"
do
- if `$GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings`
+ if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings
then
found_error=1
fi
@@ -805,8 +809,6 @@ start_master()
if [ x$MASTER_RUNNING = x1 ] || [ x$LOCAL_MASTER = x1 ] ; then
return
fi
- # Remove old berkeley db log files that can confuse the server
- $RM -f $MASTER_MYDDIR/log.*
# Remove stale binary logs
$RM -f $MYSQL_TEST_DIR/var/log/master-bin.*
# Remove old master.info files
@@ -1321,6 +1323,9 @@ then
# Remove files that can cause problems
$RM -f $MYSQL_TEST_DIR/var/run/* $MYSQL_TEST_DIR/var/tmp/*
+ # Remove old berkeley db log files that can confuse the server
+ $RM -f $MASTER_MYDDIR/log.*
+
wait_for_master=$SLEEP_TIME_FOR_FIRST_MASTER
wait_for_slave=$SLEEP_TIME_FOR_FIRST_SLAVE
$ECHO "Installing Test Databases"
@@ -1372,15 +1377,22 @@ $ECHO $DASH72
if [ -z "$1" ] ;
then
- if [ x$RECORD = x1 ]; then
- $ECHO "Will not run in record mode without a specific test case."
- else
- for tf in $TESTDIR/*.$TESTSUFFIX
- do
- run_testcase $tf
- done
- $RM -f $TIMEFILE # Remove for full test
- fi
+ if [ x$RECORD = x1 ]; then
+ $ECHO "Will not run in record mode without a specific test case."
+ else
+ if [ x$TEST_REPLICATION = x1 ]; then
+ for tf in $TESTDIR/rpl*.$TESTSUFFIX
+ do
+ run_testcase $tf
+ done
+ else
+ for tf in $TESTDIR/*.$TESTSUFFIX
+ do
+ run_testcase $tf
+ done
+ fi
+ $RM -f $TIMEFILE # Remove for full test
+ fi
else
while [ ! -z "$1" ]; do
tname=`$BASENAME $1 .test`
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 096ef2fd79e..456dfa860df 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -50,10 +50,10 @@ PRIMARY KEY (GROUP_ID,LANG_ID),
KEY NAME (NAME));
ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null;
SHOW FULL COLUMNS FROM t1;
-Field Type Null Key Default Extra Privileges
-GROUP_ID int(10) unsigned PRI 0 select,insert,update,references
-LANG_ID smallint(5) unsigned PRI 0 select,insert,update,references
-NAME char(80) MUL select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+GROUP_ID int(10) unsigned binary PRI 0 select,insert,update,references
+LANG_ID smallint(5) unsigned binary PRI 0 select,insert,update,references
+NAME char(80) latin1 MUL select,insert,update,references
DROP TABLE t1;
create table t1 (n int);
insert into t1 values(9),(3),(12),(10);
@@ -118,7 +118,7 @@ create table t1 (i int unsigned not null auto_increment primary key);
alter table t1 rename t2;
alter table t2 rename t1, add c char(10) comment "no comment";
show columns from t1;
-Field Type Null Key Default Extra
-i int(10) unsigned PRI NULL auto_increment
-c char(10) YES NULL
+Field Type Collation Null Key Default Extra
+i int(10) unsigned binary PRI NULL auto_increment
+c char(10) latin1 YES NULL
drop table t1;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index c183530df48..48882f42219 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -1,6 +1,9 @@
drop table if exists t1,t2;
create table t1 (i int, j int);
insert into t1 values (1,2), (3,4), (5,6), (7,8);
+select count(*) from t1 procedure analyse();
+Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
+count(*) 4 4 1 1 0 0 4.0000 0.0000 ENUM('4') NOT NULL
select * from t1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
@@ -11,3 +14,7 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_
t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
drop table t1,t2;
+EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 1
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result
index 43d57d2d4f7..e4f41517f94 100644
--- a/mysql-test/r/backup.result
+++ b/mysql-test/r/backup.result
@@ -1,5 +1,5 @@
set SQL_LOG_BIN=0;
-drop table if exists t1;
+drop table if exists t1, t2, t3;
create table t1(n int);
backup table t1 to '../bogus';
Table Op Msg_type Msg_text
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index eb97d19136d..2c7d3136369 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -139,14 +139,14 @@ id parent_id level
1010 102 2
1015 102 2
explain select level from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
explain select level,id from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
explain select level,id,parent_id from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 1 Using where
select level,id from t1 where level=1;
level id
1 1002
@@ -624,8 +624,8 @@ id parent_id level
1025 102 2
1016 102 2
explain select level from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -797,7 +797,6 @@ select * from t1 where i=1 and j=2;
i j
1 2
drop table t1;
-drop table if exists t1, t2, t3, t4, t5, t6, t7;
create table t1
(
branch_id int auto_increment primary key,
@@ -806,7 +805,6 @@ branch_active int not null default 1,
unique branch_name(branch_name),
index branch_active(branch_active)
) type=bdb;
-drop table if exists t2 ;
create table t2
(
target_id int auto_increment primary key,
@@ -815,7 +813,6 @@ target_active int not null default 1,
unique target_name(target_name),
index target_active(target_active)
) type=bdb;
-drop table if exists t3 ;
create table t3
(
platform_id int auto_increment primary key,
@@ -824,7 +821,6 @@ platform_active int not null default 1,
unique platform_name(platform_name),
index platform_active(platform_active)
) type=bdb;
-drop table if exists t4 ;
create table t4
(
product_id int auto_increment primary key,
@@ -834,7 +830,6 @@ product_active int not null default 1,
unique product_name(product_name),
index product_active(product_active)
) type=bdb;
-drop table if exists t5 ;
create table t5
(
product_file_id int auto_increment primary key,
@@ -847,7 +842,6 @@ file_included int not null default 1,
unique product_file(product_id,file_name),
index file_included(file_included)
) type=bdb;
-drop table if exists t6 ;
create table t6
(
file_platform_id int auto_increment primary key,
@@ -860,7 +854,6 @@ build_filename varchar(255) not null,
archive_filename varchar(255) not null,
unique file_platform(product_file_id,platform_id,branch_id)
) type=bdb;
-drop table if exists t8 ;
create table t8
(
archive_id int auto_increment primary key,
@@ -872,7 +865,6 @@ status_id int not null default 1,
unique archive(branch_id,target_id,platform_id,product_id),
index status_id(status_id)
) type=bdb;
-drop table if exists t7 ;
create table t7
(
build_id int auto_increment primary key,
@@ -1057,7 +1049,6 @@ KINMU_DATE
select T1.KINMU_DATE from t1 T1 ,t2 T2 where T1.SYAIN_NO = '12345' and T1.KINMU_DATE = '200106' and T2.SYAIN_NO = T1.SYAIN_NO;
KINMU_DATE
DROP TABLE t1,t2;
-drop table if exists t1;
create table t1 (a int(11) not null, b int(11) not null, unique (a,b)) type=bdb;
insert into t1 values (1,1), (1,2);
select * from t1 where a = 1;
diff --git a/mysql-test/r/bdb_cache.result b/mysql-test/r/bdb_cache.result
index e5c6923162a..ea00feb2111 100644
--- a/mysql-test/r/bdb_cache.result
+++ b/mysql-test/r/bdb_cache.result
@@ -98,3 +98,4 @@ commit;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
+drop table if exists t1, t2, t3;
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index 8522ef0212f..2037085dfdb 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
select 0,256,00000000000000065536,2147483647,-2147483648,2147483648,+4294967296;
0 256 00000000000000065536 2147483647 -2147483648 2147483648 +4294967296
0 256 65536 2147483647 -2147483648 2147483648 4294967296
@@ -10,7 +11,6 @@ select +9999999999999999999,-9999999999999999999;
select 9223372036854775808+1;
9223372036854775808+1
9223372036854775808
-drop table if exists t1;
create table t1 (a bigint unsigned not null, primary key(a));
insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE);
select * from t1;
diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result
index cb82c6baa0f..890c85dc946 100644
--- a/mysql-test/r/bool.result
+++ b/mysql-test/r/bool.result
@@ -46,10 +46,9 @@ SELECT @a, @b;
@a @b
0 6
DROP TABLE t1;
-drop table if exists t;
-create table t(a int, b int);
-insert into t values(null, null), (0, null), (1, null), (null, 0), (null, 1), (0, 0), (0, 1), (1, 0), (1, 1);
-select ifnull(A, 'N') as A, ifnull(B, 'N') as B, ifnull(not A, 'N') as nA, ifnull(not B, 'N') as nB, ifnull(A and B, 'N') as AB, ifnull(not (A and B), 'N') as `n(AB)`, ifnull((not A or not B), 'N') as nAonB, ifnull(A or B, 'N') as AoB, ifnull(not(A or B), 'N') as `n(AoB)`, ifnull(not A and not B, 'N') as nAnB from t;
+create table t1 (a int, b int);
+insert into t1 values(null, null), (0, null), (1, null), (null, 0), (null, 1), (0, 0), (0, 1), (1, 0), (1, 1);
+select ifnull(A, 'N') as A, ifnull(B, 'N') as B, ifnull(not A, 'N') as nA, ifnull(not B, 'N') as nB, ifnull(A and B, 'N') as AB, ifnull(not (A and B), 'N') as `n(AB)`, ifnull((not A or not B), 'N') as nAonB, ifnull(A or B, 'N') as AoB, ifnull(not(A or B), 'N') as `n(AoB)`, ifnull(not A and not B, 'N') as nAnB from t1;
A B nA nB AB n(AB) nAonB AoB n(AoB) nAnB
N N N N N N N N N N
0 N 1 N 0 1 1 N N N
@@ -60,7 +59,7 @@ N 1 N 0 N N N 1 0 0
0 1 1 0 0 1 1 1 0 0
1 0 0 1 0 1 1 1 0 0
1 1 0 0 1 0 0 1 0 0
-select ifnull(A=1, 'N') as A, ifnull(B=1, 'N') as B, ifnull(not (A=1), 'N') as nA, ifnull(not (B=1), 'N') as nB, ifnull((A=1) and (B=1), 'N') as AB, ifnull(not ((A=1) and (B=1)), 'N') as `n(AB)`, ifnull((not (A=1) or not (B=1)), 'N') as nAonB, ifnull((A=1) or (B=1), 'N') as AoB, ifnull(not((A=1) or (B=1)), 'N') as `n(AoB)`, ifnull(not (A=1) and not (B=1), 'N') as nAnB from t;
+select ifnull(A=1, 'N') as A, ifnull(B=1, 'N') as B, ifnull(not (A=1), 'N') as nA, ifnull(not (B=1), 'N') as nB, ifnull((A=1) and (B=1), 'N') as AB, ifnull(not ((A=1) and (B=1)), 'N') as `n(AB)`, ifnull((not (A=1) or not (B=1)), 'N') as nAonB, ifnull((A=1) or (B=1), 'N') as AoB, ifnull(not((A=1) or (B=1)), 'N') as `n(AoB)`, ifnull(not (A=1) and not (B=1), 'N') as nAnB from t1;
A B nA nB AB n(AB) nAonB AoB n(AoB) nAnB
N N N N N N N N N N
0 N 1 N 0 1 1 N N N
@@ -71,4 +70,4 @@ N 1 N 0 N N N 1 0 0
0 1 1 0 0 1 1 1 0 0
1 0 0 1 0 1 1 1 0 0
1 1 0 0 1 0 0 1 0 0
-drop table t;
+drop table t1;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 4c16b375400..914e05efa7a 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -10,10 +10,10 @@ CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END
3
select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END;
CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END
-ok
+0
select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END;
CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END
-ok
+0
select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end;
CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end
a
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 572b32c171c..db28038526b 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -24,10 +24,10 @@ cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A"
0 1
select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME);
cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME)
-2001-1-1 2001-1-1
+2001-01-01 2001-01-01 00:00:00
select cast("1:2:3" as TIME);
cast("1:2:3" as TIME)
-1:2:3
+01:02:03
select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01"
0
diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index afd2a1a086b..3ad3465fac0 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -2,8 +2,8 @@ drop table if exists t1;
CREATE TABLE t1 (id CHAR(12) not null, PRIMARY KEY (id));
insert into t1 values ('000000000001'),('000000000002');
explain select * from t1 where id=000000000001;
-table type possible_keys key key_len ref rows Extra
-t1 index PRIMARY PRIMARY 12 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 12 NULL 2 Using where; Using index
select * from t1 where id=000000000001;
id
000000000001
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
new file mode 100644
index 00000000000..b7243ac5d0b
--- /dev/null
+++ b/mysql-test/r/connect.result
@@ -0,0 +1,43 @@
+show tables;
+Tables_in_mysql
+columns_priv
+db
+func
+help_category
+help_relation
+help_topic
+host
+tables_priv
+user
+show tables;
+Tables_in_test
+grant ALL on *.* to test@localhost identified by "gambling";
+grant ALL on *.* to test@127.0.0.1 identified by "gambling";
+show tables;
+Tables_in_mysql
+columns_priv
+db
+func
+help_category
+help_relation
+help_topic
+host
+tables_priv
+user
+show tables;
+Tables_in_test
+update mysql.user set password=old_password("gambling2") where user="test";
+flush privileges;
+show tables;
+Tables_in_mysql
+columns_priv
+db
+func
+help_category
+help_relation
+help_topic
+host
+tables_priv
+user
+show tables;
+Tables_in_test
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index c3083dbfb03..5228ae50a83 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
create table t1 (b char(0));
insert into t1 values (""),(null);
select * from t1;
@@ -13,23 +13,25 @@ select * from t1;
b
-drop table if exists t1;
+drop table t1;
create table t2 type=heap select * from t1;
Table 'test.t1' doesn't exist
create table t2 select auto+1 from t1;
Table 'test.t1' doesn't exist
drop table if exists t1,t2;
+Warnings:
+Note 1051 Unknown table 't1'
+Note 1051 Unknown table 't2'
create table t1 (b char(0) not null, index(b));
The used table handler can't index column 'b'
create table t1 (a int not null auto_increment,primary key (a)) type=heap;
-The used table type doesn't support AUTO_INCREMENT columns
create table t1 (a int not null,b text) type=heap;
The used table type doesn't support BLOB/TEXT columns
create table t1 (a int ,primary key(a)) type=heap;
All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
drop table if exists t1;
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
-The used table type doesn't support AUTO_INCREMENT columns
+Incorrect table definition; There can only be one auto column and it must be defined as a key
create table t1 (ordid int(8), primary key (ordid));
All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
create table not_existing_database.test (a int);
@@ -49,6 +51,8 @@ drop table 1ea10;
create table t1 (t1.index int);
drop table t1;
drop database if exists test_$1;
+Warnings:
+Note 1008 Can't drop database 'test_$1'. Database doesn't exist
create database test_$1;
create table test_$1.$test1 (a$1 int, $b int, c$ int);
insert into test_$1.$test1 values (1,2,3);
@@ -62,8 +66,8 @@ create table t1 (a int auto_increment not null primary key, B CHAR(20));
insert into t1 (b) values ("hello"),("my"),("world");
create table t2 (key (b)) select * from t1;
explain select * from t2 where b="world";
-table type possible_keys key key_len ref rows Extra
-t2 ref B B 21 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref B B 21 const 1 Using where
select * from t2 where b="world";
a B
3 world
@@ -71,29 +75,53 @@ drop table t1,t2;
create table t1(x varchar(50) );
create table t2 select x from t1 where 1=2;
describe t1;
-Field Type Null Key Default Extra
-x varchar(50) YES NULL
+Field Type Collation Null Key Default Extra
+x varchar(50) latin1 YES NULL
describe t2;
-Field Type Null Key Default Extra
-x char(50) YES NULL
+Field Type Collation Null Key Default Extra
+x char(50) latin1 YES NULL
drop table t2;
create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f;
describe t2;
-Field Type Null Key Default Extra
-a datetime 0000-00-00 00:00:00
-b time 00:00:00
-c date 0000-00-00
-d bigint(17) 0
-e double(18,1) 0.0
-f bigint(17) 0
+Field Type Collation Null Key Default Extra
+a datetime latin1 0000-00-00 00:00:00
+b time latin1 00:00:00
+c date latin1 0000-00-00
+d bigint(17) binary 0
+e double(18,1) binary 0.0
+f bigint(17) binary 0
drop table t2;
create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt;
describe t2;
-Field Type Null Key Default Extra
-d date 0000-00-00
-t time 00:00:00
-dt datetime 0000-00-00 00:00:00
+Field Type Collation Null Key Default Extra
+d date latin1 0000-00-00
+t time latin1 00:00:00
+dt datetime latin1 0000-00-00 00:00:00
drop table t1,t2;
+create table t1 (a tinyint);
+create table t2 (a int) select * from t1;
+describe t1;
+Field Type Collation Null Key Default Extra
+a tinyint(4) binary YES NULL
+describe t2;
+Field Type Collation Null Key Default Extra
+a int(11) binary YES NULL
+drop table if exists t2;
+create table t2 (a int, a float) select * from t1;
+Duplicate column name 'a'
+drop table if exists t2;
+Warnings:
+Note 1051 Unknown table 't2'
+create table t2 (a int) select a as b, a+1 as b from t1;
+Duplicate column name 'b'
+drop table if exists t2;
+Warnings:
+Note 1051 Unknown table 't2'
+create table t2 (b int) select a as b, a+1 as b from t1;
+Duplicate column name 'b'
+drop table if exists t1,t2;
+Warnings:
+Note 1051 Unknown table 't2'
create table t1 (a int not null, b int, primary key(a), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b));
show create table t1;
Table Create Table
@@ -132,7 +160,7 @@ t1 CREATE TABLE `t1` (
KEY `b_29` (`b`),
KEY `b_30` (`b`),
KEY `b_31` (`b`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
create table t1 select if(1,'1','0'), month("2002-08-02");
drop table t1;
@@ -141,3 +169,78 @@ select * from t1;
if('2002'='2002','Y','N')
Y
drop table if exists t1;
+create table t1 (a int, key(a));
+create table t2 (b int, foreign key(b) references t1(a), key(b));
+drop table if exists t1,t2;
+create table t1(id int not null, name char(20));
+insert into t1 values(10,'mysql'),(20,'monty- the creator');
+create table t2(id int not null);
+insert into t2 values(10),(20);
+create table t3 like t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) default NULL
+) TYPE=MyISAM CHARSET=latin1
+select * from t3;
+id name
+create table if not exists t3 like t1;
+Warnings:
+Warning 1050 Table 't3' already exists
+select @@warning_count;
+@@warning_count
+1
+create temporary table t3 like t2;
+show create table t3;
+Table Create Table
+t3 CREATE TEMPORARY TABLE `t3` (
+ `id` int(11) NOT NULL default '0'
+) TYPE=MyISAM CHARSET=latin1
+select * from t3;
+id
+drop table t3;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) default NULL
+) TYPE=MyISAM CHARSET=latin1
+select * from t3;
+id name
+drop table t2, t3;
+drop database if exists test_$1;
+Warnings:
+Note 1008 Can't drop database 'test_$1'. Database doesn't exist
+create database test_$1;
+create table test_$1.t3 like t1;
+create temporary table t3 like test_$1.t3;
+show create table t3;
+Table Create Table
+t3 CREATE TEMPORARY TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) default NULL
+) TYPE=MyISAM CHARSET=latin1
+create table t2 like t3;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) default NULL
+) TYPE=MyISAM CHARSET=latin1
+select * from t2;
+id name
+create table t3 like t1;
+create table t3 like test_$1.t3;
+Table 't3' already exists
+create table non_existing_database.t1 like t1;
+Got one of the listed errors
+create table t3 like non_existing_table;
+Unknown table 'non_existing_table'
+create temporary table t3 like t1;
+Table 't3' already exists
+create table t3 like `a/a`;
+Incorrect table name 'a/a'
+drop table t1, t2, t3;
+drop table t3;
+drop database test_$1;
diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result
new file mode 100644
index 00000000000..91a43634bcb
--- /dev/null
+++ b/mysql-test/r/ctype_many.result
@@ -0,0 +1,1399 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+comment CHAR(32) ASCII NOT NULL,
+koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL
+) CHARSET=latin5;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `comment` char(32) character set latin1 NOT NULL default '',
+ `koi8_ru_f` char(32) character set koi8r NOT NULL default ''
+) TYPE=MyISAM CHARSET=latin5
+ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `comment` char(32) character set latin2 NOT NULL default '',
+ `koi8_ru_f` char(32) character set koi8r NOT NULL default ''
+) TYPE=MyISAM CHARSET=latin5
+ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `comment` char(32) character set latin2 NOT NULL default '',
+ `koi8_ru_f` char(32) character set koi8r NOT NULL default '',
+ `latin5_f` char(32) NOT NULL default ''
+) TYPE=MyISAM CHARSET=latin5
+ALTER TABLE t1 CHARSET=latin2;
+ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `comment` char(32) NOT NULL default '',
+ `koi8_ru_f` char(32) character set koi8r NOT NULL default '',
+ `latin5_f` char(32) character set latin5 NOT NULL default '',
+ `latin2_f` char(32) NOT NULL default ''
+) TYPE=MyISAM CHARSET=latin2
+ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `comment` char(32) NOT NULL default '',
+ `koi8_ru_f` char(32) character set koi8r NOT NULL default ''
+) TYPE=MyISAM CHARSET=latin2
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA');
+SELECT CONVERT(koi8_ru_f USING utf8),MIN(comment),COUNT(*) FROM t1 GROUP BY 1;
+CONVERT(koi8_ru_f USING utf8) MIN(comment) COUNT(*)
+a LAT CAPIT A 2
+b LAT CAPIT B 2
+c LAT CAPIT C 2
+d LAT CAPIT D 2
+e LAT CAPIT E 2
+f LAT CAPIT F 2
+g LAT CAPIT G 2
+h LAT CAPIT H 2
+i LAT CAPIT I 2
+j LAT CAPIT J 2
+k LAT CAPIT K 2
+l LAT CAPIT L 2
+m LAT CAPIT M 2
+n LAT CAPIT N 2
+o LAT CAPIT O 2
+p LAT CAPIT P 2
+q LAT CAPIT Q 2
+r LAT CAPIT R 2
+s LAT CAPIT S 2
+t LAT CAPIT T 2
+u LAT CAPIT U 2
+v LAT CAPIT V 2
+w LAT CAPIT W 2
+x LAT CAPIT X 2
+y LAT CAPIT Y 2
+z LAT CAPIT Z 2
+а CYR CAPIT A 2
+б CYR CAPIT BE 2
+в CYR CAPIT VE 2
+г CYR CAPIT GE 2
+д CYR CAPIT DE 2
+е CYR CAPIT IE 4
+ж CYR CAPIT ZHE 2
+з CYR CAPIT ZE 2
+и CYR CAPIT I 2
+к CYR CAPIT KA 2
+л CYR CAPIT EL 2
+м CYR CAPIT EM 2
+н CYR CAPIT EN 2
+о CYR CAPIT O 2
+п CYR CAPIT PE 2
+Ñ€ CYR CAPIT ER 2
+Ñ CYR CAPIT ES 2
+Ñ‚ CYR CAPIT TE 2
+у CYR CAPIT U 2
+Ñ„ CYR CAPIT EF 2
+Ñ… CYR CAPIT HA 2
+ц CYR CAPIT TSE 2
+ч CYR CAPIT CHE 2
+ш CYR CAPIT SHA 2
+щ CYR CAPIT SCHA 2
+ÑŠ CYR CAPIT HARD SIGN 2
+Ñ‹ CYR CAPIT YERU 2
+ь CYR CAPIT SOFT SIGN 2
+Ñ CYR CAPIT E 2
+ÑŽ CYR CAPIT YU 2
+Ñ CYR CAPIT YA 2
+ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL;
+UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8);
+SELECT * FROM t1;
+comment koi8_ru_f utf8_f
+LAT SMALL A a a
+LAT SMALL B b b
+LAT SMALL C c c
+LAT SMALL D d d
+LAT SMALL E e e
+LAT SMALL F f f
+LAT SMALL G g g
+LAT SMALL H h h
+LAT SMALL I i i
+LAT SMALL J j j
+LAT SMALL K k k
+LAT SMALL L l l
+LAT SMALL M m m
+LAT SMALL N n n
+LAT SMALL O o o
+LAT SMALL P p p
+LAT SMALL Q q q
+LAT SMALL R r r
+LAT SMALL S s s
+LAT SMALL T t t
+LAT SMALL U u u
+LAT SMALL V v v
+LAT SMALL W w w
+LAT SMALL X x x
+LAT SMALL Y y y
+LAT SMALL Z z z
+LAT CAPIT A A A
+LAT CAPIT B B B
+LAT CAPIT C C C
+LAT CAPIT D D D
+LAT CAPIT E E E
+LAT CAPIT F F F
+LAT CAPIT G G G
+LAT CAPIT H H H
+LAT CAPIT I I I
+LAT CAPIT J J J
+LAT CAPIT K K K
+LAT CAPIT L L L
+LAT CAPIT M M M
+LAT CAPIT N N N
+LAT CAPIT O O O
+LAT CAPIT P P P
+LAT CAPIT Q Q Q
+LAT CAPIT R R R
+LAT CAPIT S S S
+LAT CAPIT T T T
+LAT CAPIT U U U
+LAT CAPIT V V V
+LAT CAPIT W W W
+LAT CAPIT X X X
+LAT CAPIT Y Y Y
+LAT CAPIT Z Z Z
+CYR SMALL A Á а
+CYR SMALL BE  б
+CYR SMALL VE × Ð²
+CYR SMALL GE Ç Ð³
+CYR SMALL DE Ä Ð´
+CYR SMALL IE Šе
+CYR SMALL IO £ Ñ‘
+CYR SMALL ZHE Ö Ð¶
+CYR SMALL ZE Ú Ð·
+CYR SMALL I É Ð¸
+CYR SMALL KA Ë Ðº
+CYR SMALL EL Ì Ð»
+CYR SMALL EM Í Ð¼
+CYR SMALL EN Πн
+CYR SMALL O Ï Ð¾
+CYR SMALL PE Рп
+CYR SMALL ER Ò Ñ€
+CYR SMALL ES Ó Ñ
+CYR SMALL TE Ô Ñ‚
+CYR SMALL U Õ Ñƒ
+CYR SMALL EF Æ Ñ„
+CYR SMALL HA È Ñ…
+CYR SMALL TSE à ц
+CYR SMALL CHE Þ Ñ‡
+CYR SMALL SHA Û Ñˆ
+CYR SMALL SCHA Ý Ñ‰
+CYR SMALL HARD SIGN ß ÑŠ
+CYR SMALL YERU Ù Ñ‹
+CYR SMALL SOFT SIGN Ø ÑŒ
+CYR SMALL E Ü Ñ
+CYR SMALL YU À ÑŽ
+CYR SMALL YA Ñ Ñ
+CYR CAPIT A á Ð
+CYR CAPIT BE â Б
+CYR CAPIT VE ÷ Ð’
+CYR CAPIT GE ç Г
+CYR CAPIT DE ä Д
+CYR CAPIT IE å Е
+CYR CAPIT IO ³ Ð
+CYR CAPIT ZHE ö Ж
+CYR CAPIT ZE ú З
+CYR CAPIT I é И
+CYR CAPIT KA ë К
+CYR CAPIT EL ì Л
+CYR CAPIT EM í Ðœ
+CYR CAPIT EN î Ð
+CYR CAPIT O ï О
+CYR CAPIT PE ð П
+CYR CAPIT ER ò Р
+CYR CAPIT ES ó С
+CYR CAPIT TE ô Т
+CYR CAPIT U õ У
+CYR CAPIT EF æ Ф
+CYR CAPIT HA è Ð¥
+CYR CAPIT TSE ã Ц
+CYR CAPIT CHE þ Ч
+CYR CAPIT SHA û Ш
+CYR CAPIT SCHA ý Щ
+CYR CAPIT HARD SIGN ÿ Ъ
+CYR CAPIT YERU ù Ы
+CYR CAPIT SOFT SIGN ø Ь
+CYR CAPIT E ü Э
+CYR CAPIT YU à Ю
+CYR CAPIT YA ñ Я
+ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL;
+UPDATE t1 SET bin_f=koi8_ru_f;
+SELECT COUNT(DISTINCT bin_f),COUNT(DISTINCT koi8_ru_f),COUNT(DISTINCT utf8_f) FROM t1;
+COUNT(DISTINCT bin_f) COUNT(DISTINCT koi8_ru_f) COUNT(DISTINCT utf8_f)
+116 58 57
+SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1;
+koi8_ru_f MIN(comment)
+a LAT CAPIT A
+b LAT CAPIT B
+c LAT CAPIT C
+d LAT CAPIT D
+e LAT CAPIT E
+f LAT CAPIT F
+g LAT CAPIT G
+h LAT CAPIT H
+i LAT CAPIT I
+j LAT CAPIT J
+k LAT CAPIT K
+l LAT CAPIT L
+m LAT CAPIT M
+n LAT CAPIT N
+o LAT CAPIT O
+p LAT CAPIT P
+q LAT CAPIT Q
+r LAT CAPIT R
+s LAT CAPIT S
+t LAT CAPIT T
+u LAT CAPIT U
+v LAT CAPIT V
+w LAT CAPIT W
+x LAT CAPIT X
+y LAT CAPIT Y
+z LAT CAPIT Z
+Á CYR CAPIT A
+Â CYR CAPIT BE
+× CYR CAPIT VE
+Ç CYR CAPIT GE
+Ä CYR CAPIT DE
+Å CYR CAPIT IE
+£ CYR CAPIT IO
+Ö CYR CAPIT ZHE
+Ú CYR CAPIT ZE
+É CYR CAPIT I
+Ë CYR CAPIT KA
+Ì CYR CAPIT EL
+Í CYR CAPIT EM
+Î CYR CAPIT EN
+Ï CYR CAPIT O
+Ð CYR CAPIT PE
+Ò CYR CAPIT ER
+Ó CYR CAPIT ES
+Ô CYR CAPIT TE
+Õ CYR CAPIT U
+Æ CYR CAPIT EF
+È CYR CAPIT HA
+Ã CYR CAPIT TSE
+Þ CYR CAPIT CHE
+Û CYR CAPIT SHA
+Ý CYR CAPIT SCHA
+ß CYR CAPIT HARD SIGN
+Ù CYR CAPIT YERU
+Ø CYR CAPIT SOFT SIGN
+Ü CYR CAPIT E
+À CYR CAPIT YU
+Ñ CYR CAPIT YA
+SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1;
+utf8_f MIN(comment)
+a LAT CAPIT A
+b LAT CAPIT B
+c LAT CAPIT C
+d LAT CAPIT D
+e LAT CAPIT E
+f LAT CAPIT F
+g LAT CAPIT G
+h LAT CAPIT H
+i LAT CAPIT I
+j LAT CAPIT J
+k LAT CAPIT K
+l LAT CAPIT L
+m LAT CAPIT M
+n LAT CAPIT N
+o LAT CAPIT O
+p LAT CAPIT P
+q LAT CAPIT Q
+r LAT CAPIT R
+s LAT CAPIT S
+t LAT CAPIT T
+u LAT CAPIT U
+v LAT CAPIT V
+w LAT CAPIT W
+x LAT CAPIT X
+y LAT CAPIT Y
+z LAT CAPIT Z
+а CYR CAPIT A
+б CYR CAPIT BE
+в CYR CAPIT VE
+г CYR CAPIT GE
+д CYR CAPIT DE
+е CYR CAPIT IE
+ж CYR CAPIT ZHE
+з CYR CAPIT ZE
+и CYR CAPIT I
+к CYR CAPIT KA
+л CYR CAPIT EL
+м CYR CAPIT EM
+н CYR CAPIT EN
+о CYR CAPIT O
+п CYR CAPIT PE
+Ñ€ CYR CAPIT ER
+Ñ CYR CAPIT ES
+Ñ‚ CYR CAPIT TE
+у CYR CAPIT U
+Ñ„ CYR CAPIT EF
+Ñ… CYR CAPIT HA
+ц CYR CAPIT TSE
+ч CYR CAPIT CHE
+ш CYR CAPIT SHA
+щ CYR CAPIT SCHA
+ÑŠ CYR CAPIT HARD SIGN
+Ñ‹ CYR CAPIT YERU
+ь CYR CAPIT SOFT SIGN
+Ñ CYR CAPIT E
+ÑŽ CYR CAPIT YU
+Ñ CYR CAPIT YA
+SELECT DISTINCT koi8_ru_f FROM t1;
+koi8_ru_f
+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
+SELECT DISTINCT utf8_f FROM t1;
+utf8_f
+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
+а
+б
+в
+г
+д
+е
+ж
+з
+и
+к
+л
+м
+н
+о
+п
+Ñ€
+Ñ‚
+у
+Ñ„
+Ñ…
+ц
+ч
+ш
+щ
+ÑŠ
+Ñ‹
+ь
+ÑŽ
+SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC;
+lower(koi8_ru_f)
+z
+z
+y
+y
+x
+x
+w
+w
+v
+v
+u
+u
+t
+t
+s
+s
+r
+r
+q
+q
+p
+p
+o
+o
+n
+n
+m
+m
+l
+l
+k
+k
+j
+j
+i
+i
+h
+h
+g
+g
+f
+f
+e
+e
+d
+d
+c
+c
+b
+b
+a
+a
+SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC;
+lower(utf8_f)
+ÑŽ
+ÑŽ
+ь
+ь
+Ñ‹
+Ñ‹
+ÑŠ
+ÑŠ
+щ
+щ
+ш
+ш
+ч
+ч
+ц
+ц
+Ñ…
+Ñ…
+Ñ„
+Ñ„
+у
+у
+Ñ‚
+Ñ‚
+Ñ€
+Ñ€
+п
+п
+о
+о
+н
+н
+м
+м
+л
+л
+к
+к
+и
+и
+з
+з
+ж
+ж
+е
+Ñ‘
+е
+Ñ‘
+д
+д
+г
+г
+в
+в
+б
+б
+а
+а
+z
+z
+y
+y
+x
+x
+w
+w
+v
+v
+u
+u
+t
+t
+s
+s
+r
+r
+q
+q
+p
+p
+o
+o
+n
+n
+m
+m
+l
+l
+k
+k
+j
+j
+i
+i
+h
+h
+g
+g
+f
+f
+e
+e
+d
+d
+c
+c
+b
+b
+a
+a
+SELECT t11.comment,t12.comment
+FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f
+ORDER BY t11.koi8_ru_f,t11.comment,t12.comment;
+comment comment
+LAT CAPIT A LAT CAPIT A
+LAT CAPIT A LAT SMALL A
+LAT SMALL A LAT CAPIT A
+LAT SMALL A LAT SMALL A
+LAT CAPIT B LAT CAPIT B
+LAT CAPIT B LAT SMALL B
+LAT SMALL B LAT CAPIT B
+LAT SMALL B LAT SMALL B
+LAT CAPIT C LAT CAPIT C
+LAT CAPIT C LAT SMALL C
+LAT SMALL C LAT CAPIT C
+LAT SMALL C LAT SMALL C
+LAT CAPIT D LAT CAPIT D
+LAT CAPIT D LAT SMALL D
+LAT SMALL D LAT CAPIT D
+LAT SMALL D LAT SMALL D
+LAT CAPIT E LAT CAPIT E
+LAT CAPIT E LAT SMALL E
+LAT SMALL E LAT CAPIT E
+LAT SMALL E LAT SMALL E
+LAT CAPIT F LAT CAPIT F
+LAT CAPIT F LAT SMALL F
+LAT SMALL F LAT CAPIT F
+LAT SMALL F LAT SMALL F
+LAT CAPIT G LAT CAPIT G
+LAT CAPIT G LAT SMALL G
+LAT SMALL G LAT CAPIT G
+LAT SMALL G LAT SMALL G
+LAT CAPIT H LAT CAPIT H
+LAT CAPIT H LAT SMALL H
+LAT SMALL H LAT CAPIT H
+LAT SMALL H LAT SMALL H
+LAT CAPIT I LAT CAPIT I
+LAT CAPIT I LAT SMALL I
+LAT SMALL I LAT CAPIT I
+LAT SMALL I LAT SMALL I
+LAT CAPIT J LAT CAPIT J
+LAT CAPIT J LAT SMALL J
+LAT SMALL J LAT CAPIT J
+LAT SMALL J LAT SMALL J
+LAT CAPIT K LAT CAPIT K
+LAT CAPIT K LAT SMALL K
+LAT SMALL K LAT CAPIT K
+LAT SMALL K LAT SMALL K
+LAT CAPIT L LAT CAPIT L
+LAT CAPIT L LAT SMALL L
+LAT SMALL L LAT CAPIT L
+LAT SMALL L LAT SMALL L
+LAT CAPIT M LAT CAPIT M
+LAT CAPIT M LAT SMALL M
+LAT SMALL M LAT CAPIT M
+LAT SMALL M LAT SMALL M
+LAT CAPIT N LAT CAPIT N
+LAT CAPIT N LAT SMALL N
+LAT SMALL N LAT CAPIT N
+LAT SMALL N LAT SMALL N
+LAT CAPIT O LAT CAPIT O
+LAT CAPIT O LAT SMALL O
+LAT SMALL O LAT CAPIT O
+LAT SMALL O LAT SMALL O
+LAT CAPIT P LAT CAPIT P
+LAT CAPIT P LAT SMALL P
+LAT SMALL P LAT CAPIT P
+LAT SMALL P LAT SMALL P
+LAT CAPIT Q LAT CAPIT Q
+LAT CAPIT Q LAT SMALL Q
+LAT SMALL Q LAT CAPIT Q
+LAT SMALL Q LAT SMALL Q
+LAT CAPIT R LAT CAPIT R
+LAT CAPIT R LAT SMALL R
+LAT SMALL R LAT CAPIT R
+LAT SMALL R LAT SMALL R
+LAT CAPIT S LAT CAPIT S
+LAT CAPIT S LAT SMALL S
+LAT SMALL S LAT CAPIT S
+LAT SMALL S LAT SMALL S
+LAT CAPIT T LAT CAPIT T
+LAT CAPIT T LAT SMALL T
+LAT SMALL T LAT CAPIT T
+LAT SMALL T LAT SMALL T
+LAT CAPIT U LAT CAPIT U
+LAT CAPIT U LAT SMALL U
+LAT SMALL U LAT CAPIT U
+LAT SMALL U LAT SMALL U
+LAT CAPIT V LAT CAPIT V
+LAT CAPIT V LAT SMALL V
+LAT SMALL V LAT CAPIT V
+LAT SMALL V LAT SMALL V
+LAT CAPIT W LAT CAPIT W
+LAT CAPIT W LAT SMALL W
+LAT SMALL W LAT CAPIT W
+LAT SMALL W LAT SMALL W
+LAT CAPIT X LAT CAPIT X
+LAT CAPIT X LAT SMALL X
+LAT SMALL X LAT CAPIT X
+LAT SMALL X LAT SMALL X
+LAT CAPIT Y LAT CAPIT Y
+LAT CAPIT Y LAT SMALL Y
+LAT SMALL Y LAT CAPIT Y
+LAT SMALL Y LAT SMALL Y
+LAT CAPIT Z LAT CAPIT Z
+LAT CAPIT Z LAT SMALL Z
+LAT SMALL Z LAT CAPIT Z
+LAT SMALL Z LAT SMALL Z
+CYR CAPIT A CYR CAPIT A
+CYR CAPIT A CYR SMALL A
+CYR SMALL A CYR CAPIT A
+CYR SMALL A CYR SMALL A
+CYR CAPIT BE CYR CAPIT BE
+CYR CAPIT BE CYR SMALL BE
+CYR SMALL BE CYR CAPIT BE
+CYR SMALL BE CYR SMALL BE
+CYR CAPIT VE CYR CAPIT VE
+CYR CAPIT VE CYR SMALL VE
+CYR SMALL VE CYR CAPIT VE
+CYR SMALL VE CYR SMALL VE
+CYR CAPIT GE CYR CAPIT GE
+CYR CAPIT GE CYR SMALL GE
+CYR SMALL GE CYR CAPIT GE
+CYR SMALL GE CYR SMALL GE
+CYR CAPIT DE CYR CAPIT DE
+CYR CAPIT DE CYR SMALL DE
+CYR SMALL DE CYR CAPIT DE
+CYR SMALL DE CYR SMALL DE
+CYR CAPIT IE CYR CAPIT IE
+CYR CAPIT IE CYR CAPIT IO
+CYR CAPIT IE CYR SMALL IE
+CYR CAPIT IE CYR SMALL IO
+CYR SMALL IE CYR CAPIT IE
+CYR SMALL IE CYR CAPIT IO
+CYR SMALL IE CYR SMALL IE
+CYR SMALL IE CYR SMALL IO
+CYR CAPIT IO CYR CAPIT IE
+CYR CAPIT IO CYR CAPIT IO
+CYR CAPIT IO CYR SMALL IE
+CYR CAPIT IO CYR SMALL IO
+CYR SMALL IO CYR CAPIT IE
+CYR SMALL IO CYR CAPIT IO
+CYR SMALL IO CYR SMALL IE
+CYR SMALL IO CYR SMALL IO
+CYR CAPIT ZHE CYR CAPIT ZHE
+CYR CAPIT ZHE CYR SMALL ZHE
+CYR SMALL ZHE CYR CAPIT ZHE
+CYR SMALL ZHE CYR SMALL ZHE
+CYR CAPIT ZE CYR CAPIT ZE
+CYR CAPIT ZE CYR SMALL ZE
+CYR SMALL ZE CYR CAPIT ZE
+CYR SMALL ZE CYR SMALL ZE
+CYR CAPIT I CYR CAPIT I
+CYR CAPIT I CYR SMALL I
+CYR SMALL I CYR CAPIT I
+CYR SMALL I CYR SMALL I
+CYR CAPIT KA CYR CAPIT KA
+CYR CAPIT KA CYR SMALL KA
+CYR SMALL KA CYR CAPIT KA
+CYR SMALL KA CYR SMALL KA
+CYR CAPIT EL CYR CAPIT EL
+CYR CAPIT EL CYR SMALL EL
+CYR SMALL EL CYR CAPIT EL
+CYR SMALL EL CYR SMALL EL
+CYR CAPIT EM CYR CAPIT EM
+CYR CAPIT EM CYR SMALL EM
+CYR SMALL EM CYR CAPIT EM
+CYR SMALL EM CYR SMALL EM
+CYR CAPIT EN CYR CAPIT EN
+CYR CAPIT EN CYR SMALL EN
+CYR SMALL EN CYR CAPIT EN
+CYR SMALL EN CYR SMALL EN
+CYR CAPIT O CYR CAPIT O
+CYR CAPIT O CYR SMALL O
+CYR SMALL O CYR CAPIT O
+CYR SMALL O CYR SMALL O
+CYR CAPIT PE CYR CAPIT PE
+CYR CAPIT PE CYR SMALL PE
+CYR SMALL PE CYR CAPIT PE
+CYR SMALL PE CYR SMALL PE
+CYR CAPIT ER CYR CAPIT ER
+CYR CAPIT ER CYR SMALL ER
+CYR SMALL ER CYR CAPIT ER
+CYR SMALL ER CYR SMALL ER
+CYR CAPIT ES CYR CAPIT ES
+CYR CAPIT ES CYR SMALL ES
+CYR SMALL ES CYR CAPIT ES
+CYR SMALL ES CYR SMALL ES
+CYR CAPIT TE CYR CAPIT TE
+CYR CAPIT TE CYR SMALL TE
+CYR SMALL TE CYR CAPIT TE
+CYR SMALL TE CYR SMALL TE
+CYR CAPIT U CYR CAPIT U
+CYR CAPIT U CYR SMALL U
+CYR SMALL U CYR CAPIT U
+CYR SMALL U CYR SMALL U
+CYR CAPIT EF CYR CAPIT EF
+CYR CAPIT EF CYR SMALL EF
+CYR SMALL EF CYR CAPIT EF
+CYR SMALL EF CYR SMALL EF
+CYR CAPIT HA CYR CAPIT HA
+CYR CAPIT HA CYR SMALL HA
+CYR SMALL HA CYR CAPIT HA
+CYR SMALL HA CYR SMALL HA
+CYR CAPIT TSE CYR CAPIT TSE
+CYR CAPIT TSE CYR SMALL TSE
+CYR SMALL TSE CYR CAPIT TSE
+CYR SMALL TSE CYR SMALL TSE
+CYR CAPIT CHE CYR CAPIT CHE
+CYR CAPIT CHE CYR SMALL CHE
+CYR SMALL CHE CYR CAPIT CHE
+CYR SMALL CHE CYR SMALL CHE
+CYR CAPIT SHA CYR CAPIT SHA
+CYR CAPIT SHA CYR SMALL SHA
+CYR SMALL SHA CYR CAPIT SHA
+CYR SMALL SHA CYR SMALL SHA
+CYR CAPIT SCHA CYR CAPIT SCHA
+CYR CAPIT SCHA CYR SMALL SCHA
+CYR SMALL SCHA CYR CAPIT SCHA
+CYR SMALL SCHA CYR SMALL SCHA
+CYR CAPIT HARD SIGN CYR CAPIT HARD SIGN
+CYR CAPIT HARD SIGN CYR SMALL HARD SIGN
+CYR SMALL HARD SIGN CYR CAPIT HARD SIGN
+CYR SMALL HARD SIGN CYR SMALL HARD SIGN
+CYR CAPIT YERU CYR CAPIT YERU
+CYR CAPIT YERU CYR SMALL YERU
+CYR SMALL YERU CYR CAPIT YERU
+CYR SMALL YERU CYR SMALL YERU
+CYR CAPIT SOFT SIGN CYR CAPIT SOFT SIGN
+CYR CAPIT SOFT SIGN CYR SMALL SOFT SIGN
+CYR SMALL SOFT SIGN CYR CAPIT SOFT SIGN
+CYR SMALL SOFT SIGN CYR SMALL SOFT SIGN
+CYR CAPIT E CYR CAPIT E
+CYR CAPIT E CYR SMALL E
+CYR SMALL E CYR CAPIT E
+CYR SMALL E CYR SMALL E
+CYR CAPIT YU CYR CAPIT YU
+CYR CAPIT YU CYR SMALL YU
+CYR SMALL YU CYR CAPIT YU
+CYR SMALL YU CYR SMALL YU
+CYR CAPIT YA CYR CAPIT YA
+CYR CAPIT YA CYR SMALL YA
+CYR SMALL YA CYR CAPIT YA
+CYR SMALL YA CYR SMALL YA
+SELECT t11.comment,t12.comment
+FROM t1 t11,t1 t12
+WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8r)
+ORDER BY t12.utf8_f,t11.comment,t12.comment;
+comment comment
+LAT CAPIT A LAT CAPIT A
+LAT CAPIT A LAT SMALL A
+LAT SMALL A LAT CAPIT A
+LAT SMALL A LAT SMALL A
+LAT CAPIT B LAT CAPIT B
+LAT CAPIT B LAT SMALL B
+LAT SMALL B LAT CAPIT B
+LAT SMALL B LAT SMALL B
+LAT CAPIT C LAT CAPIT C
+LAT CAPIT C LAT SMALL C
+LAT SMALL C LAT CAPIT C
+LAT SMALL C LAT SMALL C
+LAT CAPIT D LAT CAPIT D
+LAT CAPIT D LAT SMALL D
+LAT SMALL D LAT CAPIT D
+LAT SMALL D LAT SMALL D
+LAT CAPIT E LAT CAPIT E
+LAT CAPIT E LAT SMALL E
+LAT SMALL E LAT CAPIT E
+LAT SMALL E LAT SMALL E
+LAT CAPIT F LAT CAPIT F
+LAT CAPIT F LAT SMALL F
+LAT SMALL F LAT CAPIT F
+LAT SMALL F LAT SMALL F
+LAT CAPIT G LAT CAPIT G
+LAT CAPIT G LAT SMALL G
+LAT SMALL G LAT CAPIT G
+LAT SMALL G LAT SMALL G
+LAT CAPIT H LAT CAPIT H
+LAT CAPIT H LAT SMALL H
+LAT SMALL H LAT CAPIT H
+LAT SMALL H LAT SMALL H
+LAT CAPIT I LAT CAPIT I
+LAT CAPIT I LAT SMALL I
+LAT SMALL I LAT CAPIT I
+LAT SMALL I LAT SMALL I
+LAT CAPIT J LAT CAPIT J
+LAT CAPIT J LAT SMALL J
+LAT SMALL J LAT CAPIT J
+LAT SMALL J LAT SMALL J
+LAT CAPIT K LAT CAPIT K
+LAT CAPIT K LAT SMALL K
+LAT SMALL K LAT CAPIT K
+LAT SMALL K LAT SMALL K
+LAT CAPIT L LAT CAPIT L
+LAT CAPIT L LAT SMALL L
+LAT SMALL L LAT CAPIT L
+LAT SMALL L LAT SMALL L
+LAT CAPIT M LAT CAPIT M
+LAT CAPIT M LAT SMALL M
+LAT SMALL M LAT CAPIT M
+LAT SMALL M LAT SMALL M
+LAT CAPIT N LAT CAPIT N
+LAT CAPIT N LAT SMALL N
+LAT SMALL N LAT CAPIT N
+LAT SMALL N LAT SMALL N
+LAT CAPIT O LAT CAPIT O
+LAT CAPIT O LAT SMALL O
+LAT SMALL O LAT CAPIT O
+LAT SMALL O LAT SMALL O
+LAT CAPIT P LAT CAPIT P
+LAT CAPIT P LAT SMALL P
+LAT SMALL P LAT CAPIT P
+LAT SMALL P LAT SMALL P
+LAT CAPIT Q LAT CAPIT Q
+LAT CAPIT Q LAT SMALL Q
+LAT SMALL Q LAT CAPIT Q
+LAT SMALL Q LAT SMALL Q
+LAT CAPIT R LAT CAPIT R
+LAT CAPIT R LAT SMALL R
+LAT SMALL R LAT CAPIT R
+LAT SMALL R LAT SMALL R
+LAT CAPIT S LAT CAPIT S
+LAT CAPIT S LAT SMALL S
+LAT SMALL S LAT CAPIT S
+LAT SMALL S LAT SMALL S
+LAT CAPIT T LAT CAPIT T
+LAT CAPIT T LAT SMALL T
+LAT SMALL T LAT CAPIT T
+LAT SMALL T LAT SMALL T
+LAT CAPIT U LAT CAPIT U
+LAT CAPIT U LAT SMALL U
+LAT SMALL U LAT CAPIT U
+LAT SMALL U LAT SMALL U
+LAT CAPIT V LAT CAPIT V
+LAT CAPIT V LAT SMALL V
+LAT SMALL V LAT CAPIT V
+LAT SMALL V LAT SMALL V
+LAT CAPIT W LAT CAPIT W
+LAT CAPIT W LAT SMALL W
+LAT SMALL W LAT CAPIT W
+LAT SMALL W LAT SMALL W
+LAT CAPIT X LAT CAPIT X
+LAT CAPIT X LAT SMALL X
+LAT SMALL X LAT CAPIT X
+LAT SMALL X LAT SMALL X
+LAT CAPIT Y LAT CAPIT Y
+LAT CAPIT Y LAT SMALL Y
+LAT SMALL Y LAT CAPIT Y
+LAT SMALL Y LAT SMALL Y
+LAT CAPIT Z LAT CAPIT Z
+LAT CAPIT Z LAT SMALL Z
+LAT SMALL Z LAT CAPIT Z
+LAT SMALL Z LAT SMALL Z
+CYR CAPIT A CYR CAPIT A
+CYR CAPIT A CYR SMALL A
+CYR SMALL A CYR CAPIT A
+CYR SMALL A CYR SMALL A
+CYR CAPIT BE CYR CAPIT BE
+CYR CAPIT BE CYR SMALL BE
+CYR SMALL BE CYR CAPIT BE
+CYR SMALL BE CYR SMALL BE
+CYR CAPIT VE CYR CAPIT VE
+CYR CAPIT VE CYR SMALL VE
+CYR SMALL VE CYR CAPIT VE
+CYR SMALL VE CYR SMALL VE
+CYR CAPIT GE CYR CAPIT GE
+CYR CAPIT GE CYR SMALL GE
+CYR SMALL GE CYR CAPIT GE
+CYR SMALL GE CYR SMALL GE
+CYR CAPIT DE CYR CAPIT DE
+CYR CAPIT DE CYR SMALL DE
+CYR SMALL DE CYR CAPIT DE
+CYR SMALL DE CYR SMALL DE
+CYR CAPIT IE CYR CAPIT IE
+CYR CAPIT IE CYR SMALL IE
+CYR CAPIT IO CYR CAPIT IO
+CYR CAPIT IO CYR SMALL IO
+CYR SMALL IE CYR CAPIT IE
+CYR SMALL IE CYR SMALL IE
+CYR SMALL IO CYR CAPIT IO
+CYR SMALL IO CYR SMALL IO
+CYR CAPIT ZHE CYR CAPIT ZHE
+CYR CAPIT ZHE CYR SMALL ZHE
+CYR SMALL ZHE CYR CAPIT ZHE
+CYR SMALL ZHE CYR SMALL ZHE
+CYR CAPIT ZE CYR CAPIT ZE
+CYR CAPIT ZE CYR SMALL ZE
+CYR SMALL ZE CYR CAPIT ZE
+CYR SMALL ZE CYR SMALL ZE
+CYR CAPIT I CYR CAPIT I
+CYR CAPIT I CYR SMALL I
+CYR SMALL I CYR CAPIT I
+CYR SMALL I CYR SMALL I
+CYR CAPIT KA CYR CAPIT KA
+CYR CAPIT KA CYR SMALL KA
+CYR SMALL KA CYR CAPIT KA
+CYR SMALL KA CYR SMALL KA
+CYR CAPIT EL CYR CAPIT EL
+CYR CAPIT EL CYR SMALL EL
+CYR SMALL EL CYR CAPIT EL
+CYR SMALL EL CYR SMALL EL
+CYR CAPIT EM CYR CAPIT EM
+CYR CAPIT EM CYR SMALL EM
+CYR SMALL EM CYR CAPIT EM
+CYR SMALL EM CYR SMALL EM
+CYR CAPIT EN CYR CAPIT EN
+CYR CAPIT EN CYR SMALL EN
+CYR SMALL EN CYR CAPIT EN
+CYR SMALL EN CYR SMALL EN
+CYR CAPIT O CYR CAPIT O
+CYR CAPIT O CYR SMALL O
+CYR SMALL O CYR CAPIT O
+CYR SMALL O CYR SMALL O
+CYR CAPIT PE CYR CAPIT PE
+CYR CAPIT PE CYR SMALL PE
+CYR SMALL PE CYR CAPIT PE
+CYR SMALL PE CYR SMALL PE
+CYR CAPIT ER CYR CAPIT ER
+CYR CAPIT ER CYR SMALL ER
+CYR SMALL ER CYR CAPIT ER
+CYR SMALL ER CYR SMALL ER
+CYR CAPIT ES CYR CAPIT ES
+CYR CAPIT ES CYR SMALL ES
+CYR SMALL ES CYR CAPIT ES
+CYR SMALL ES CYR SMALL ES
+CYR CAPIT TE CYR CAPIT TE
+CYR CAPIT TE CYR SMALL TE
+CYR SMALL TE CYR CAPIT TE
+CYR SMALL TE CYR SMALL TE
+CYR CAPIT U CYR CAPIT U
+CYR CAPIT U CYR SMALL U
+CYR SMALL U CYR CAPIT U
+CYR SMALL U CYR SMALL U
+CYR CAPIT EF CYR CAPIT EF
+CYR CAPIT EF CYR SMALL EF
+CYR SMALL EF CYR CAPIT EF
+CYR SMALL EF CYR SMALL EF
+CYR CAPIT HA CYR CAPIT HA
+CYR CAPIT HA CYR SMALL HA
+CYR SMALL HA CYR CAPIT HA
+CYR SMALL HA CYR SMALL HA
+CYR CAPIT TSE CYR CAPIT TSE
+CYR CAPIT TSE CYR SMALL TSE
+CYR SMALL TSE CYR CAPIT TSE
+CYR SMALL TSE CYR SMALL TSE
+CYR CAPIT CHE CYR CAPIT CHE
+CYR CAPIT CHE CYR SMALL CHE
+CYR SMALL CHE CYR CAPIT CHE
+CYR SMALL CHE CYR SMALL CHE
+CYR CAPIT SHA CYR CAPIT SHA
+CYR CAPIT SHA CYR SMALL SHA
+CYR SMALL SHA CYR CAPIT SHA
+CYR SMALL SHA CYR SMALL SHA
+CYR CAPIT SCHA CYR CAPIT SCHA
+CYR CAPIT SCHA CYR SMALL SCHA
+CYR SMALL SCHA CYR CAPIT SCHA
+CYR SMALL SCHA CYR SMALL SCHA
+CYR CAPIT HARD SIGN CYR CAPIT HARD SIGN
+CYR CAPIT HARD SIGN CYR SMALL HARD SIGN
+CYR SMALL HARD SIGN CYR CAPIT HARD SIGN
+CYR SMALL HARD SIGN CYR SMALL HARD SIGN
+CYR CAPIT YERU CYR CAPIT YERU
+CYR CAPIT YERU CYR SMALL YERU
+CYR SMALL YERU CYR CAPIT YERU
+CYR SMALL YERU CYR SMALL YERU
+CYR CAPIT SOFT SIGN CYR CAPIT SOFT SIGN
+CYR CAPIT SOFT SIGN CYR SMALL SOFT SIGN
+CYR SMALL SOFT SIGN CYR CAPIT SOFT SIGN
+CYR SMALL SOFT SIGN CYR SMALL SOFT SIGN
+CYR CAPIT E CYR CAPIT E
+CYR CAPIT E CYR SMALL E
+CYR SMALL E CYR CAPIT E
+CYR SMALL E CYR SMALL E
+CYR CAPIT YU CYR CAPIT YU
+CYR CAPIT YU CYR SMALL YU
+CYR SMALL YU CYR CAPIT YU
+CYR SMALL YU CYR SMALL YU
+CYR CAPIT YA CYR CAPIT YA
+CYR CAPIT YA CYR SMALL YA
+CYR SMALL YA CYR CAPIT YA
+CYR SMALL YA CYR SMALL YA
+ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2;
+ALTER TABLE t1 CHANGE ucs2_f ucs2_f CHAR(32) UNICODE NOT NULL;
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA');
+ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL;
+ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL;
+UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%';
+UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%';
+UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f='';
+UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f='';
+SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f;
+min(comment) count(*)
+LAT CAPIT A 2
+LAT CAPIT B 2
+LAT CAPIT C 2
+LAT CAPIT D 2
+LAT CAPIT E 2
+LAT CAPIT F 2
+LAT CAPIT G 2
+LAT CAPIT H 2
+LAT CAPIT I 2
+LAT CAPIT J 2
+LAT CAPIT K 2
+LAT CAPIT L 2
+LAT CAPIT M 2
+LAT CAPIT N 2
+LAT CAPIT O 2
+LAT CAPIT P 2
+LAT CAPIT Q 2
+LAT CAPIT R 2
+LAT CAPIT S 2
+LAT CAPIT T 2
+LAT CAPIT U 2
+LAT CAPIT V 2
+LAT CAPIT W 2
+LAT CAPIT X 2
+LAT CAPIT Y 2
+LAT CAPIT Z 2
+GREEK CAPIT ALPHA 2
+GREEK CAPIT BETA 2
+GREEK CAPIT GAMMA 2
+GREEK CAPIT DELTA 2
+GREEK CAPIT EPSILON 2
+CYR CAPIT A 2
+CYR CAPIT BE 2
+CYR CAPIT VE 2
+CYR CAPIT GE 2
+CYR CAPIT DE 2
+CYR CAPIT IE 4
+CYR CAPIT ZHE 2
+CYR CAPIT ZE 2
+CYR CAPIT I 2
+CYR CAPIT KA 2
+CYR CAPIT EL 2
+CYR CAPIT EM 2
+CYR CAPIT EN 2
+CYR CAPIT O 2
+CYR CAPIT PE 2
+CYR CAPIT ER 2
+CYR CAPIT ES 2
+CYR CAPIT TE 2
+CYR CAPIT U 2
+CYR CAPIT EF 2
+CYR CAPIT HA 2
+CYR CAPIT TSE 2
+CYR CAPIT CHE 2
+CYR CAPIT SHA 2
+CYR CAPIT SCHA 2
+CYR CAPIT HARD SIGN 2
+CYR CAPIT YERU 2
+CYR CAPIT SOFT SIGN 2
+CYR CAPIT E 2
+CYR CAPIT YU 2
+CYR CAPIT YA 2
+ARMENIAN CAPIT AYB 2
+ARMENIAN CAPIT BEN 2
+ARMENIAN CAPIT GIM 2
+ARMENIAN CAPIT DA 2
+ARMENIAN CAPIT ECH 2
+ARMENIAN CAPIT ZA 2
+DROP TABLE t1;
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index 9e375203e49..8e4b52a8366 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -12,9 +12,9 @@ select * from t1 where tmsp=0;
a tmsp
select * from t1 where tmsp=19711006010203;
a tmsp
-5 19711006010203
-6 19711006010203
-8 19711006010203
+5 1971-10-06 01:02:03
+6 1971-10-06 01:02:03
+8 1971-10-06 01:02:03
drop table t1;
create table t1 (a int not null auto_increment primary key, b char(10));
insert delayed into t1 values (1,"b");
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index c2230722aa6..4fa85ea9cbc 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -24,3 +24,11 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
delete from t1 where a=27;
drop table t1;
+CREATE TABLE `t` (
+`i` int(10) NOT NULL default '0',
+`i2` int(10) NOT NULL default '0',
+PRIMARY KEY (`i`)
+) TYPE=MyISAM CHARSET=latin1;
+DELETE FROM t USING t WHERE post='1';
+Unknown column 'post' in 'where clause'
+drop table if exists t;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
new file mode 100644
index 00000000000..e1e823350d3
--- /dev/null
+++ b/mysql-test/r/derived.result
@@ -0,0 +1,148 @@
+drop table if exists t1,t2,t3;
+select * from (select 2 from DUAL) b;
+2
+2
+SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
+Unknown column 'a' in 'field list'
+SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
+Unknown column 'a' in 'field list'
+CREATE TABLE t1 (a int not null, b char (10) not null);
+insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
+CREATE TABLE t2 (a int not null, b char (10) not null);
+insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
+select t1.a,t3.y from t1,(select a as y from t2 where b='c') as t3 where t1.a = t3.y;
+a y
+3 3
+3 3
+select t1.a,t3.a from t1,(select * from t2 where b='c') as t3 where t1.a = t3.a;
+a a
+3 3
+3 3
+CREATE TABLE t3 (a int not null, b char (10) not null);
+insert into t3 values (3,'f'),(4,'y'),(5,'z'),(6,'c');
+select t1.a,t4.y from t1,(select t2.a as y from t2,(select t3.b from t3 where t3.a>3) as t5 where t2.b=t5.b) as t4 where t1.a = t4.y;
+a y
+3 3
+3 3
+SELECT a FROM (SELECT 1 FROM (SELECT 1) a HAVING a=1) b;
+Unknown column 'a' in 'having clause'
+SELECT a,b as a FROM (SELECT '1' as a,'2' as b) b HAVING a=1;
+Column: 'a' in having clause is ambiguous
+SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=2;
+a a
+1 2
+SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=1;
+a a
+SELECT 1 FROM (SELECT 1) a WHERE a=2;
+Unknown column 'a' in 'where clause'
+SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) as a;
+Unknown column 'a' in 'having clause'
+select * from t1 as x1, (select * from t1) as x2;
+a b a b
+1 a 1 a
+2 b 1 a
+3 c 1 a
+3 c 1 a
+1 a 2 b
+2 b 2 b
+3 c 2 b
+3 c 2 b
+1 a 3 c
+2 b 3 c
+3 c 3 c
+3 c 3 c
+1 a 3 c
+2 b 3 c
+3 c 3 c
+3 c 3 c
+explain select * from t1 as x1, (select * from t1) as x2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY x1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
+2 DERIVED x1 ALL NULL NULL NULL NULL 4
+drop table if exists t2,t3;
+select * from (select 1) as a;
+1
+1
+select a from (select 1 as a) as b;
+a
+1
+select 1 from (select 1) as a;
+1
+1
+select * from (select * from t1 union select * from t1) a;
+a b
+1 a
+2 b
+3 c
+select * from (select * from t1 union all select * from t1) a;
+a b
+1 a
+2 b
+3 c
+3 c
+1 a
+2 b
+3 c
+3 c
+explain select * from (select * from t1 union select * from t1) a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 4
+3 UNION t1 ALL NULL NULL NULL NULL 4
+explain select * from (select * from t1 union all select * from t1) a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
+2 DERIVED t1 ALL NULL NULL NULL NULL 4
+3 UNION t1 ALL NULL NULL NULL NULL 4
+CREATE TABLE t2 (a int not null);
+insert into t2 values(1);
+select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
+a b
+1 a
+select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
+a b
+1 a
+2 b
+3 c
+drop table t1, t2;
+create table t1(a int not null, t char(8), index(a));
+SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
+a t
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+10 10
+11 11
+12 12
+13 13
+14 14
+15 15
+16 16
+17 17
+18 18
+19 19
+20 20
+explain select count(*) from t1 as tt1, (select * from t1) as tt2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+2 DERIVED tt1 index NULL a 4 NULL 10000 Using index
+drop table t1;
+SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
+(SELECT * FROM (SELECT 1 as a) as a )
+1
+select * from (select 1 as a) b left join (select 2 as a) c using(a);
+a a
+1 NULL
+SELECT * FROM (SELECT 1 UNION SELECT a) b;
+Unknown column 'a' in 'field list'
+SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
+Unknown column 'a' in 'field list'
+SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
+Unknown column 'a' in 'field list'
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 5f4f7cced1e..1f459faa8f4 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -172,10 +172,10 @@ b
INSERT INTO t2 values (1),(2),(3);
INSERT INTO t3 VALUES (1,'1'),(2,'2'),(1,'1'),(2,'2');
explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
-table type possible_keys key key_len ref rows Extra
-t3 index a a 5 NULL 6 Using index; Using temporary
-t2 index a a 4 NULL 5 Using index; Distinct
-t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 Using where; Distinct
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index a a 5 NULL 6 Using index; Using temporary
+1 SIMPLE t2 index a a 4 NULL 5 Using index; Distinct
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 Using where; Distinct
SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
a
1
@@ -188,9 +188,9 @@ insert into t3 select * from t4;
insert into t4 select * from t3;
insert into t3 select * from t4;
explain select distinct t1.a from t1,t3 where t1.a=t3.a;
-table type possible_keys key key_len ref rows Extra
-t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary
-t3 ref a a 5 t1.a 10 Using where; Using index; Distinct
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary
+1 SIMPLE t3 ref a a 5 t1.a 10 Using where; Using index; Distinct
select distinct t1.a from t1,t3 where t1.a=t3.a;
a
1
@@ -199,29 +199,29 @@ select distinct 1 from t1,t3 where t1.a=t3.a;
1
1
explain SELECT distinct t1.a from t1;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 2 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT distinct t1.a from t1 order by a desc;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 2 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT t1.a from t1 group by a order by a desc;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 2 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT distinct t1.a from t1 order by a desc limit 1;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 2 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT distinct a from t3 order by a desc limit 2;
-table type possible_keys key key_len ref rows Extra
-t3 index NULL a 5 NULL 204 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index NULL a 5 NULL 204 Using index
explain SELECT distinct a,b from t3 order by a+1;
-table type possible_keys key key_len ref rows Extra
-t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
explain SELECT distinct a,b from t3 order by a limit 10;
-table type possible_keys key key_len ref rows Extra
-t3 index NULL a 5 NULL 204 Using temporary
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index NULL a 5 NULL 204 Using temporary
explain SELECT a,b from t3 group by a,b order by a+1;
-table type possible_keys key key_len ref rows Extra
-t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
drop table t1,t2,t3,t4;
CREATE TABLE t1 (name varchar(255));
INSERT INTO t1 VALUES ('aa'),('ab'),('ac'),('ad'),('ae');
@@ -298,14 +298,14 @@ on j_lj_t3.id=t3_lj.id
WHERE
((t1.id=j_lj_t2.id AND t2_lj.id IS NULL) OR (t1.id=t2.id AND t2.idx=2))
AND ((t1.id=j_lj_t3.id AND t3_lj.id IS NULL) OR (t1.id=t3.id AND t3.idx=2));
-table type possible_keys key key_len ref rows Extra
-t1 index id id 4 NULL 2 Using index; Using temporary
-t2 index id id 8 NULL 1 Using index; Distinct
-t3 index id id 8 NULL 1 Using index; Distinct
-j_lj_t2 index id id 4 NULL 2 Using where; Using index; Distinct
-t2_lj index id id 8 NULL 1 Using where; Using index; Distinct
-j_lj_t3 index id id 4 NULL 2 Using where; Using index; Distinct
-t3_lj index id id 8 NULL 1 Using where; Using index; Distinct
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index id id 4 NULL 2 Using index; Using temporary
+1 SIMPLE t2 index id id 8 NULL 1 Using index; Distinct
+1 SIMPLE t3 index id id 8 NULL 1 Using index; Distinct
+1 SIMPLE j_lj_t2 index id id 4 NULL 2 Using where; Using index; Distinct
+1 SIMPLE t2_lj index id id 8 NULL 1 Using where; Using index; Distinct
+1 SIMPLE j_lj_t3 index id id 4 NULL 2 Using where; Using index; Distinct
+1 SIMPLE t3_lj index id id 8 NULL 1 Using where; Using index; Distinct
SELECT DISTINCT
t1.id
from
@@ -326,7 +326,6 @@ AND ((t1.id=j_lj_t3.id AND t3_lj.id IS NULL) OR (t1.id=t3.id AND t3.idx=2));
id
2
drop table t1,t2,t3;
-drop table if exists t1;
create table t1 (a int not null, b int not null, t time);
insert into t1 values (1,1,"00:06:15"),(1,2,"00:06:15"),(1,2,"00:30:15"),(1,3,"00:06:15"),(1,3,"00:30:15");
select a,sec_to_time(sum(time_to_sec(t))) from t1 group by a,b;
@@ -410,7 +409,7 @@ INSERT INTO t2 VALUES (33,6,'Kevin','0','kevin@stileproject.com',1,'',0,'http://
SELECT DISTINCT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t2.userid = t1.touserid);
privatemessageid folderid userid touserid fromuserid title message dateline showsignature iconid messageread readtime receipt deleteprompt multiplerecipients userid usergroupid username password email styleid parentemail coppauser homepage icq aim yahoo signature adminemail showemail invisible usertitle customtitle joindate cookieuser daysprune lastvisit lastactivity lastpost posts timezoneoffset emailnotification buddylist ignorelist pmfolders receivepm emailonpm pmpopup avatarid avatarrevision options birthday maxposts startofweek ipaddress referrerid nosessionhash autorefresh messagepopup inforum ratenum ratetotal allowrate
128 0 33 33 8 :D 996121863 1 0 2 996122850 2 0 0 33 6 Kevin 0 kevin@stileproject.com 1 0 http://www.stileproject.com 1 1 0 Administrator 0 996120694 1 -1 1030996168 1031027028 1030599436 36 -6 0 1 0 1 0 0 15 0000-00-00 -1 1 64.0.0.0 0 1 -1 0 0 4 19 1
-DROP TABLE IF EXISTS t1,t2;
+DROP TABLE t1,t2;
CREATE TABLE t1 (a int primary key, b int, c int);
INSERT t1 VALUES (1,2,3);
CREATE TABLE t2 (a int primary key, b int, c int);
@@ -418,4 +417,4 @@ INSERT t2 VALUES (3,4,5);
SELECT DISTINCT t1.a, t2.b FROM t1, t2 WHERE t1.a=1 ORDER BY t2.c;
a b
1 4
-DROP TABLE IF EXISTS t1,t2;
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 178c3a8cb4f..a9048b65d51 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -1,5 +1,4 @@
drop table if exists t1;
-drop table if exists t1;
drop table t1;
Unknown table 't1'
create table t1(n int);
@@ -13,6 +12,8 @@ select * from t1;
n
1
drop database if exists mysqltest;
+Warnings:
+Note 1008 Can't drop database 'mysqltest'. Database doesn't exist
create database mysqltest;
drop database if exists mysqltest;
create database mysqltest;
@@ -25,6 +26,8 @@ drop database if exists mysqltest;
create database mysqltest;
drop database mysqltest;
drop database if exists mysqltest;
+Warnings:
+Note 1008 Can't drop database 'mysqltest'. Database doesn't exist
flush tables with read lock;
create database mysqltest;
Got one of the listed errors
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index d433078a251..63e4f4030d3 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -1,8 +1,8 @@
drop table if exists t1;
create table t1 (id int not null, str char(10), unique(str));
explain select * from t1;
-table type possible_keys key key_len ref rows Extra
-t1 system NULL NULL NULL NULL 0 const row not found
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found
insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar");
select * from t1 where str is null;
id str
@@ -12,35 +12,35 @@ select * from t1 where str="foo";
id str
3 foo
explain select * from t1 where str is null;
-table type possible_keys key key_len ref rows Extra
-t1 ref str str 11 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref str str 11 const 1 Using where
explain select * from t1 where str="foo";
-table type possible_keys key key_len ref rows Extra
-t1 const str str 11 const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const str str 11 const 1
explain select * from t1 ignore key (str) where str="foo";
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
explain select * from t1 use key (str,str) where str="foo";
-table type possible_keys key key_len ref rows Extra
-t1 const str str 11 const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const str str 11 const 1
explain select * from t1 use key (str,str,foo) where str="foo";
Key column 'foo' doesn't exist in table
explain select * from t1 ignore key (str,str,foo) where str="foo";
Key column 'foo' doesn't exist in table
drop table t1;
explain select 1;
-Comment
-No tables used
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
create table t1 (a int not null);
explain select count(*) from t1;
-Comment
-Select tables optimized away
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
insert into t1 values(1);
explain select count(*) from t1;
-Comment
-Select tables optimized away
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
insert into t1 values(1);
explain select count(*) from t1;
-Comment
-Select tables optimized away
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1;
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index 7080f2b6145..4e7e4769f1b 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -1,6 +1,6 @@
-drop table if exists t1;
+drop table if exists t1,t2;
+drop database if exists mysqltest;
create temporary table t1(n int not null primary key);
-drop table if exists t2;
create table t2(n int);
insert into t2 values(3);
select * from t1;
@@ -11,7 +11,6 @@ drop table t2;
Table 't2' was locked with a READ lock and can't be updated
drop table t2;
unlock tables;
-drop database if exists mysqltest;
create database mysqltest;
create table mysqltest.t1(n int);
insert into mysqltest.t1 values (23);
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index edf109fcc93..c40e9d9bfa2 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -16,6 +16,8 @@ select * from t1 where MATCH(a,b) AGAINST ("indexes collections");
a b
Full-text indexes are called collections
Only MyISAM tables support collections
+select * from t1 where MATCH(a,b) AGAINST ("only");
+a b
select * from t1 where MATCH(a,b) AGAINST ("collections") UNION ALL select * from t1 where MATCH(a,b) AGAINST ("indexes");
a b
Only MyISAM tables support collections
@@ -144,7 +146,7 @@ t2 CREATE TABLE `t2` (
`inhalt` text,
KEY `tig` (`ticket`),
FULLTEXT KEY `tix` (`inhalt`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
select * from t2 where MATCH inhalt AGAINST (NULL);
ticket inhalt
select * from t2 where MATCH inhalt AGAINST ('foobar');
@@ -206,7 +208,6 @@ select 8 from t1;
8
8
drop table t1;
-drop table if exists t1;
create table t1 (a text, fulltext key (a));
insert into t1 values ('aaaa');
repair table t1;
diff --git a/mysql-test/r/fulltext2.result b/mysql-test/r/fulltext2.result
new file mode 100644
index 00000000000..8086faadba4
--- /dev/null
+++ b/mysql-test/r/fulltext2.result
@@ -0,0 +1,871 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+i int(10) unsigned not null auto_increment primary key,
+a varchar(255) not null,
+FULLTEXT KEY (a)
+) TYPE=MyISAM;
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaaxxx');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaazzz');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+insert t1 (a) values ('aaayyy');
+repair table t1 quick;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+select count(*) from t1 where match a against ('aaaxxx');
+count(*)
+260
+select count(*) from t1 where match a against ('aaayyy');
+count(*)
+250
+select count(*) from t1 where match a against ('aaazzz');
+count(*)
+255
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+count(*)
+260
+select count(*) from t1 where match a against ('aaayyy' in boolean mode);
+count(*)
+250
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+count(*)
+255
+select count(*) from t1 where match a against ('aaaxxx aaayyy aaazzz');
+count(*)
+765
+select count(*) from t1 where match a against ('aaaxxx aaayyy aaazzz' in boolean mode);
+count(*)
+765
+select count(*) from t1 where match a against ('aaax*' in boolean mode);
+count(*)
+260
+select count(*) from t1 where match a against ('aaay*' in boolean mode);
+count(*)
+250
+select count(*) from t1 where match a against ('aaa*' in boolean mode);
+count(*)
+765
+insert t1 (a) values ('aaaxxx'),('aaayyy');
+insert t1 (a) values ('aaazzz'),('aaazzz'),('aaazzz'),('aaazzz'),('aaazzz');
+select count(*) from t1 where match a against ('aaaxxx');
+count(*)
+261
+select count(*) from t1 where match a against ('aaayyy');
+count(*)
+251
+select count(*) from t1 where match a against ('aaazzz');
+count(*)
+260
+insert t1 (a) values ('aaaxxx 000000');
+select count(*) from t1 where match a against ('000000');
+count(*)
+1
+delete from t1 where match a against ('000000');
+select count(*) from t1 where match a against ('000000');
+count(*)
+0
+select count(*) from t1 where match a against ('aaaxxx');
+count(*)
+261
+delete from t1 where match a against ('aaazzz');
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+count(*)
+261
+select count(*) from t1 where match a against ('aaayyy' in boolean mode);
+count(*)
+251
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+count(*)
+0
+select count(*) from t1 where a = 'aaaxxx';
+count(*)
+261
+select count(*) from t1 where a = 'aaayyy';
+count(*)
+251
+select count(*) from t1 where a = 'aaazzz';
+count(*)
+0
+insert t1 (a) values ('aaaxxx 000000');
+select count(*) from t1 where match a against ('000000');
+count(*)
+1
+update t1 set a='aaazzz' where match a against ('000000');
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+count(*)
+261
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+count(*)
+1
+update t1 set a='aaazzz' where a = 'aaaxxx';
+update t1 set a='aaaxxx' where a = 'aaayyy';
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+count(*)
+251
+select count(*) from t1 where match a against ('aaayyy' in boolean mode);
+count(*)
+0
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+count(*)
+262
+DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/r/fulltext_multi.result b/mysql-test/r/fulltext_multi.result
index 72b7102fd3f..968b00020e2 100644
--- a/mysql-test/r/fulltext_multi.result
+++ b/mysql-test/r/fulltext_multi.result
@@ -1,4 +1,3 @@
-use test;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
a int(11) NOT NULL auto_increment,
diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result
index c0e72ff789f..bfee9eba280 100644
--- a/mysql-test/r/fulltext_order_by.result
+++ b/mysql-test/r/fulltext_order_by.result
@@ -1,4 +1,3 @@
-use test;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
a INT AUTO_INCREMENT PRIMARY KEY,
diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index 742de833bf7..461ae1e7e09 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -1,9 +1,15 @@
select length(encrypt('foo', 'ff')) <> 0;
length(encrypt('foo', 'ff')) <> 0
1
-select old_password('test'), password('test');
-old_password('test') password('test')
-378b243e220ca493 378b243e220ca493
-select length(encrypt('test')), encrypt('test','aa');
-length(encrypt('test')) encrypt('test','aa')
-13 aaqPiZY5xR5l.
+select password("a",""), password("a",NULL), password("","a"), password(NULL,"a");
+password("a","") password("a",NULL) password("","a") password(NULL,"a")
+*2517f7235d68d4ba2e5019c93420523101157a792c01 NULL NULL
+select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa");
+password("aaaaaaaaaaaaaaaa","a") password("a","aaaaaaaaaaaaaaaa")
+*2cd3b9a44e9a9994789a30f935c92f45a96c5472f381 *37c7c5c794ff144819f2531bf03c57772cd84e40db09
+select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa');
+old_password('test') length(password("1")) length(encrypt('test')) encrypt('test','aa')
+378b243e220ca493 45 13 aaqPiZY5xR5l.
+select old_password(""), old_password(NULL), password(""), password(NULL);
+old_password("") old_password(NULL) password("") password(NULL)
+ NULL NULL
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index acdf2c5d7be..234fded9a68 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -31,17 +31,17 @@ INSERT INTO t1 VALUES (357917728,7,2,2,20000319145027);
select visitor_id,max(ts) as mts from t1 group by visitor_id
having mts < DATE_SUB(NOW(),INTERVAL 3 MONTH);
visitor_id mts
-48985536 20000319013932
-173865424 20000318233615
-357917728 20000319145027
-465931136 20000318160953
-1092858576 20000319013445
+48985536 2000-03-19 01:39:32
+173865424 2000-03-18 23:36:15
+357917728 2000-03-19 14:50:27
+465931136 2000-03-18 16:09:53
+1092858576 2000-03-19 01:34:45
select visitor_id,max(ts) as mts from t1 group by visitor_id
having DATE_ADD(mts,INTERVAL 3 MONTH) < NOW();
visitor_id mts
-48985536 20000319013932
-173865424 20000318233615
-357917728 20000319145027
-465931136 20000318160953
-1092858576 20000319013445
+48985536 2000-03-19 01:39:32
+173865424 2000-03-18 23:36:15
+357917728 2000-03-19 14:50:27
+465931136 2000-03-18 16:09:53
+1092858576 2000-03-19 01:34:45
drop table t1;
diff --git a/mysql-test/r/func_equal.result b/mysql-test/r/func_equal.result
index 32a911eedf8..352b76f2744 100644
--- a/mysql-test/r/func_equal.result
+++ b/mysql-test/r/func_equal.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t2;
select 0<=>0,0.0<=>0.0,"A"<=>"A",NULL<=>NULL;
0<=>0 0.0<=>0.0 "A"<=>"A" NULL<=>NULL
1 1 1 1
@@ -10,7 +11,6 @@ select 1.0<=>0.0,0.0<=>NULL,NULL<=>0.0;
select "A"<=>"B","A"<=>NULL,NULL<=>"A";
"A"<=>"B" "A"<=>NULL NULL<=>"A"
0 0 0
-drop table if exists t1,t2;
create table t1 (id int, value int);
create table t2 (id int, value int);
insert into t1 values (1,null);
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index b129beaac81..5cbc37d5690 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -42,21 +42,21 @@ insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp)
6 3
-select sum(all a),count(all a),avg(all a),std(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
-sum(all a) count(all a) avg(all a) std(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c)
-21 6 3.5000 1.7078 7 0 1 6 E
-select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
-grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
-NULL 0 0 NULL NULL 0 0 NULL NULL
-1 1 1 1.0000 0.0000 1 1 1 1 a a
-2 5 2 2.5000 0.5000 3 2 2 3 b c
-3 15 3 5.0000 0.8165 7 4 4 6 C E
-select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
+select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
+sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c)
+21 6 3.5000 1.7078 2.9167 7 0 1 6 E
+select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
+grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
+NULL 0 0 NULL NULL NULL 0 0 NULL NULL
+1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
+2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
+3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E
+select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
grp sum
NULL NULL
1 7
-2 20
-3 44.816496580928
+2 20.25
+3 45.483163247594
create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
replace into t2 select grp, a, c from t1 limit 2,1;
@@ -72,14 +72,14 @@ CREATE TABLE t1 (id int(11),value1 float(10,2));
INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
-select id, avg(value1), std(value1) from t1 group by id;
-id avg(value1) std(value1)
-1 1.000000 0.816497
-2 11.000000 0.816497
-select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id;
-name avg(value1) std(value1)
-Set One 1.000000 0.816497
-Set Two 11.000000 0.816497
+select id, avg(value1), std(value1), variance(value1) from t1 group by id;
+id avg(value1) std(value1) variance(value1)
+1 1.000000 0.816497 0.666667
+2 11.000000 0.816497 0.666667
+select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
+name avg(value1) std(value1) variance(value1)
+Set One 1.000000 0.816497 0.666667
+Set Two 11.000000 0.816497 0.666667
drop table t1,t2;
create table t1 (id int not null);
create table t2 (id int not null,rating int null);
@@ -173,11 +173,11 @@ select max(t2.a2), max(t1.a1) from t1, t2;
max(t2.a2) max(t1.a1)
NULL NULL
explain select min(a2) from t1;
-Comment
-Select tables optimized away
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
explain select max(t1.a1), max(t2.a2) from t1, t2;
-Comment
-No matching min/max row
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No matching min/max row
insert into t2 values('AAA', 10, 0.5);
select max(t1.a1), max(t2.a1) from t1, t2 where t2.a2=9;
max(t1.a1) max(t2.a1)
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index ba33ee0831d..006dc8abef0 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -1,11 +1,95 @@
drop table if exists t1;
+select 1 in (1,2,3);
+1 in (1,2,3)
+1
+select 10 in (1,2,3);
+10 in (1,2,3)
+0
+select NULL in (1,2,3);
+NULL in (1,2,3)
+NULL
+select 1 in (1,NULL,3);
+1 in (1,NULL,3)
+1
+select 3 in (1,NULL,3);
+3 in (1,NULL,3)
+1
+select 10 in (1,NULL,3);
+10 in (1,NULL,3)
+NULL
+select 1.5 in (1.5,2.5,3.5);
+1.5 in (1.5,2.5,3.5)
+1
+select 10.5 in (1.5,2.5,3.5);
+10.5 in (1.5,2.5,3.5)
+0
+select NULL in (1.5,2.5,3.5);
+NULL in (1.5,2.5,3.5)
+NULL
+select 1.5 in (1.5,NULL,3.5);
+1.5 in (1.5,NULL,3.5)
+1
+select 3.5 in (1.5,NULL,3.5);
+3.5 in (1.5,NULL,3.5)
+1
+select 10.5 in (1.5,NULL,3.5);
+10.5 in (1.5,NULL,3.5)
+NULL
+CREATE TABLE t1 (a int, b int, c int);
+insert into t1 values (1,2,3), (1,NULL,3);
+select 1 in (a,b,c) from t1;
+1 in (a,b,c)
+1
+1
+select 3 in (a,b,c) from t1;
+3 in (a,b,c)
+1
+1
+select 10 in (a,b,c) from t1;
+10 in (a,b,c)
+0
+NULL
+select NULL in (a,b,c) from t1;
+NULL in (a,b,c)
+NULL
+NULL
+drop table t1;
+CREATE TABLE t1 (a float, b float, c float);
+insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
+select 1.5 in (a,b,c) from t1;
+1.5 in (a,b,c)
+1
+1
+select 3.5 in (a,b,c) from t1;
+3.5 in (a,b,c)
+1
+1
+select 10.5 in (a,b,c) from t1;
+10.5 in (a,b,c)
+0
+NULL
+drop table t1;
+CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
+insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
+select 'A' in (a,b,c) from t1;
+'A' in (a,b,c)
+1
+1
+select 'EFD' in (a,b,c) from t1;
+'EFD' in (a,b,c)
+1
+1
+select 'XSFGGHF' in (a,b,c) from t1;
+'XSFGGHF' in (a,b,c)
+0
+NULL
+drop table t1;
CREATE TABLE t1 (field char(1));
INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL);
field
SELECT * from t1 WHERE field NOT IN (NULL);
field
-A
SELECT * from t1 where field = field;
field
A
@@ -16,6 +100,7 @@ NULL
DELETE FROM t1 WHERE field NOT IN (NULL);
SELECT * FROM t1;
field
+A
NULL
drop table t1;
create table t1 (id int(10) primary key);
diff --git a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result
index 5305c16c5d9..ab72e42eca9 100644
--- a/mysql-test/r/func_set.result
+++ b/mysql-test/r/func_set.result
@@ -25,3 +25,20 @@ find_in_set("","a,b,c") find_in_set("","a,b,c,") find_in_set("",",a,b,c")
select find_in_set("abc","abc"),find_in_set("ab","abc"),find_in_set("abcd","abc");
find_in_set("abc","abc") find_in_set("ab","abc") find_in_set("abcd","abc")
1 0 0
+drop table if exists t1,t2;
+create table t1 (id int(10) not null unique);
+create table t2 (id int(10) not null primary key,
+val int(10) not null);
+insert into t1 values (1),(2),(4);
+insert into t2 values (1,1),(2,1),(3,1),(4,2);
+select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
+id elt(two.val,'one','two')
+1 one
+2 one
+4 two
+select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
+id elt(two.val,'one','two')
+1 one
+2 one
+4 two
+drop table t1,t2;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 9e8f2b90f07..b3468586f32 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -80,6 +80,21 @@ this is a REAL test
select soundex(''),soundex('he'),soundex('hello all folks');
soundex('') soundex('he') soundex('hello all folks')
H000 H4142
+select 'mood' sounds like 'mud';
+'mood' sounds like 'mud'
+1
+select 'Glazgo' sounds like 'Liverpool';
+'Glazgo' sounds like 'Liverpool'
+0
+select null sounds like 'null';
+null sounds like 'null'
+NULL
+select 'null' sounds like null;
+'null' sounds like null
+NULL
+select null sounds like null;
+null sounds like null
+NULL
select md5('hello');
md5('hello')
5d41402abc4b2a76b9719d911017c592
@@ -216,14 +231,14 @@ bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL
) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4);
-SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"') FROM t1;
-CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"')
+SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter), '"') FROM t1;
+CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter), '"')
"Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4"
SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"')
"Link";"1";"1";"1";"0";"4"
-SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) FROM t1;
-CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter)
+SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter) FROM t1;
+CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter)
Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4
drop table t1;
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, tmp text NOT NULL, KEY id (id)) TYPE=MyISAM;
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index 5ea4ed5e4e0..83c2ad6e020 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -4,3 +4,6 @@ test 1
select version()>="3.23.29";
version()>="3.23.29"
1
+select TRUE,FALSE,NULL;
+TRUE FALSE NULL
+1 0 NULL
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index 8cfae44b9dd..9fcf03db838 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -46,6 +46,9 @@ select 3 ^ 11, 1 ^ 1, 1 ^ 0, 1 ^ NULL, NULL ^ 1;
select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 0, NULL XOR 1, 1 XOR NULL, 0 XOR NULL;
1 XOR 1 1 XOR 0 0 XOR 1 0 XOR 0 NULL XOR 1 1 XOR NULL 0 XOR NULL
0 1 1 0 NULL NULL NULL
+select 10 % 7, 10 mod 7, 10 div 3;
+10 % 7 10 mod 7 10 div 3
+3 3 3
select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1
0 1
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 2941352c776..d8491035f0b 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -392,11 +392,71 @@ CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
start ctime1 ctime2
-2002-11-04 00:00:00 20021029165106 20021105164731
+2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
start ctime1 ctime2
-2002-11-04 00:00:00 20021029165106 20021105164731
+2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
drop table t1,t2,t3;
+CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
+INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
+SELECT * from t1;
+datetime timestamp date time
+2001-01-02 03:04:05 2002-01-02 03:04:05 2003-01-02 06:07:08
+select date_add("1997-12-31",INTERVAL 1 SECOND);
+date_add("1997-12-31",INTERVAL 1 SECOND)
+1997-12-31 00:00:01
+select date_add("1997-12-31",INTERVAL "1 1" YEAR_MONTH);
+date_add("1997-12-31",INTERVAL "1 1" YEAR_MONTH)
+1999-01-31
+select date_add(datetime, INTERVAL 1 SECOND) from t1;
+date_add(datetime, INTERVAL 1 SECOND)
+2001-01-02 03:04:06
+select date_add(datetime, INTERVAL 1 YEAR) from t1;
+date_add(datetime, INTERVAL 1 YEAR)
+2002-01-02 03:04:05
+select date_add(date,INTERVAL 1 SECOND) from t1;
+date_add(date,INTERVAL 1 SECOND)
+2003-01-02 00:00:01
+select date_add(date,INTERVAL 1 MINUTE) from t1;
+date_add(date,INTERVAL 1 MINUTE)
+2003-01-02 00:01:00
+select date_add(date,INTERVAL 1 HOUR) from t1;
+date_add(date,INTERVAL 1 HOUR)
+2003-01-02 01:00:00
+select date_add(date,INTERVAL 1 DAY) from t1;
+date_add(date,INTERVAL 1 DAY)
+2003-01-03
+select date_add(date,INTERVAL 1 MONTH) from t1;
+date_add(date,INTERVAL 1 MONTH)
+2003-02-02
+select date_add(date,INTERVAL 1 YEAR) from t1;
+date_add(date,INTERVAL 1 YEAR)
+2004-01-02
+select date_add(date,INTERVAL "1:1" MINUTE_SECOND) from t1;
+date_add(date,INTERVAL "1:1" MINUTE_SECOND)
+2003-01-02 00:01:01
+select date_add(date,INTERVAL "1:1" HOUR_MINUTE) from t1;
+date_add(date,INTERVAL "1:1" HOUR_MINUTE)
+2003-01-02 01:01:00
+select date_add(date,INTERVAL "1:1" DAY_HOUR) from t1;
+date_add(date,INTERVAL "1:1" DAY_HOUR)
+2003-01-03 01:00:00
+select date_add(date,INTERVAL "1 1" YEAR_MONTH) from t1;
+date_add(date,INTERVAL "1 1" YEAR_MONTH)
+2004-02-02
+select date_add(date,INTERVAL "1:1:1" HOUR_SECOND) from t1;
+date_add(date,INTERVAL "1:1:1" HOUR_SECOND)
+2003-01-02 01:01:01
+select date_add(date,INTERVAL "1 1:1" DAY_MINUTE) from t1;
+date_add(date,INTERVAL "1 1:1" DAY_MINUTE)
+2003-01-03 01:01:00
+select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
+date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
+2003-01-03 01:01:01
+select date_add(time,INTERVAL 1 SECOND) from t1;
+date_add(time,INTERVAL 1 SECOND)
+2006-07-08 00:00:01
+drop table t1;
diff --git a/mysql-test/r/gcc296.result b/mysql-test/r/gcc296.result
index 8f78f70cc1f..628bbbf3f93 100644
--- a/mysql-test/r/gcc296.result
+++ b/mysql-test/r/gcc296.result
@@ -1,5 +1,5 @@
-drop table if exists obory;
-CREATE TABLE obory (
+drop table if exists t1;
+CREATE TABLE t1 (
kodoboru varchar(10) default NULL,
obor tinytext,
aobor tinytext,
@@ -7,14 +7,14 @@ UNIQUE INDEX kodoboru (kodoboru),
FULLTEXT KEY obor (obor),
FULLTEXT KEY aobor (aobor)
);
-INSERT INTO obory VALUES ('0101000000','aaa','AAA');
-INSERT INTO obory VALUES ('0102000000','bbb','BBB');
-INSERT INTO obory VALUES ('0103000000','ccc','CCC');
-INSERT INTO obory VALUES ('0104000000','xxx','XXX');
-select * from obory;
+INSERT INTO t1 VALUES ('0101000000','aaa','AAA');
+INSERT INTO t1 VALUES ('0102000000','bbb','BBB');
+INSERT INTO t1 VALUES ('0103000000','ccc','CCC');
+INSERT INTO t1 VALUES ('0104000000','xxx','XXX');
+select * from t1;
kodoboru obor aobor
0101000000 aaa AAA
0102000000 bbb BBB
0103000000 ccc CCC
0104000000 xxx XXX
-drop table obory;
+drop table t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 6627890f86c..e6f3256d779 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1,4 +1,6 @@
drop table if exists t1,t2,t3;
+SELECT 1 FROM (SELECT 1) as a GROUP BY SUM(1);
+Invalid use of group function
CREATE TABLE t1 (
spID int(10) unsigned,
userID int(10) unsigned,
@@ -49,7 +51,7 @@ SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1
userid MIN(t1.score+0.0)
1 1.0
2 2.0
-drop table test.t1,test.t2;
+drop table t1,t2;
CREATE TABLE t1 (
PID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
payDate date DEFAULT '0000-00-00' NOT NULL,
@@ -244,11 +246,11 @@ key (score)
);
INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3);
explain select userid,count(*) from t1 group by userid desc;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
explain select userid,count(*) from t1 group by userid desc order by null;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6 Using temporary
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary
select userid,count(*) from t1 group by userid desc;
userid count(*)
3 3
@@ -262,14 +264,14 @@ select userid,count(*) from t1 group by userid desc having 3 IN (1,COUNT(*));
userid count(*)
3 3
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
-table type possible_keys key key_len ref rows Extra
-t1 range spID spID 5 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid;
-table type possible_keys key key_len ref rows Extra
-t1 range spID spID 5 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid order by null;
-table type possible_keys key key_len ref rows Extra
-t1 range spID spID 5 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index
select spid,count(*) from t1 where spid between 1 and 2 group by spid;
spid count(*)
1 1
@@ -279,11 +281,11 @@ spid count(*)
2 2
1 1
explain select sql_big_result spid,sum(userid) from t1 group by spid desc;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6 Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort
explain select sql_big_result spid,sum(userid) from t1 group by spid desc order by null;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6
select sql_big_result spid,sum(userid) from t1 group by spid desc;
spid sum(userid)
5 3
@@ -292,11 +294,11 @@ spid sum(userid)
2 3
1 1
explain select sql_big_result score,count(*) from t1 group by score desc;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL score 3 NULL 6 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL score 3 NULL 6 Using index
explain select sql_big_result score,count(*) from t1 group by score desc order by null;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL score 3 NULL 6 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL score 3 NULL 6 Using index
select sql_big_result score,count(*) from t1 group by score desc;
score count(*)
3 3
@@ -411,7 +413,6 @@ CONCAT(a, b) count(*)
abcdef 1
hijklm 2
DROP TABLE t1;
-drop table if exists t1;
create table t1 (One int unsigned, Two int unsigned, Three int unsigned, Four int unsigned);
insert into t1 values (1,2,1,4),(1,2,2,4),(1,2,3,4),(1,2,4,4),(1,1,1,4),(1,1,2,4),(1,1,3,4),(1,1,4,4),(1,3,1,4),(1,3,2,4),(1,3,3,4),(1,3,4,4);
select One, Two, sum(Four) from t1 group by One,Two;
@@ -521,13 +522,13 @@ a b
2 2
1 1
explain select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
-t2 ALL a NULL NULL NULL 4 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
+1 SIMPLE t2 ALL a NULL NULL NULL 4 Using where
explain select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b ORDER BY NULL;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6 Using temporary
-t2 ALL a NULL NULL NULL 4 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary
+1 SIMPLE t2 ALL a NULL NULL NULL 4 Using where
drop table t1,t2;
create table t1 (a int, b int);
insert into t1 values (1, 4);
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index 9760719ecf2..9d3383efd8f 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -5,6 +5,8 @@ insert into t1 values
(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"),
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
+handler t2 read a=(SELECT 1);
+You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1
handler t2 read a first;
a b
14 aaa
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index a33ce457176..bd1bd523964 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -62,4 +62,8 @@ select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
Fld1 max(Fld2)
1 20
3 50
+select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
+Fld1 max(Fld2)
+1 20
+3 50
drop table t1;
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 73642d7f751..ffd62ceabb6 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -65,10 +65,10 @@ a
869751
alter table t1 type=myisam;
explain select * from t1 where a in (869751,736494,226312,802616);
-table type possible_keys key key_len ref rows Extra
-t1 range uniq_id uniq_id 4 NULL 4 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range uniq_id uniq_id 4 NULL 4 Using where; Using index
drop table t1;
-create table t1 (x int not null, y int not null, key x(x), unique y(y))
+create table t1 (x int not null, y int not null, key x (x), unique y (y))
type=heap;
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
select * from t1 where x=1;
@@ -84,9 +84,9 @@ x y x y
2 5 2 2
2 6 2 2
explain select * from t1,t1 as t2 where t1.x=t2.y;
-table type possible_keys key key_len ref rows Extra
-t1 ALL x NULL NULL NULL 6
-t2 eq_ref y y 4 t1.x 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL x NULL NULL NULL 6
+1 SIMPLE t2 eq_ref y y 4 t1.x 1
drop table t1;
create table t1 (a int) type=heap;
insert into t1 values(1);
@@ -158,18 +158,18 @@ drop table t1;
create table t1 (btn char(10) not null, key(btn)) type=heap;
insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
explain select * from t1 where btn like "q%";
-table type possible_keys key key_len ref rows Extra
-t1 ALL btn NULL NULL NULL 14 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
select * from t1 where btn like "q%";
btn
alter table t1 add column new_col char(1) not null, add key (btn,new_col), drop key btn;
update t1 set new_col=btn;
explain select * from t1 where btn="a";
-table type possible_keys key key_len ref rows Extra
-t1 ALL btn NULL NULL NULL 14 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
explain select * from t1 where btn="a" and new_col="a";
-table type possible_keys key key_len ref rows Extra
-t1 ref btn btn 11 const,const 10 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref btn btn 11 const,const 10 Using where
drop table t1;
CREATE TABLE t1 (
a int default NULL,
@@ -181,16 +181,16 @@ INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
SELECT * FROM t1 WHERE a=NULL;
a b
explain SELECT * FROM t1 WHERE a IS NULL;
-table type possible_keys key key_len ref rows Extra
-t1 ref a a 5 const 10 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 5 const 10 Using where
SELECT * FROM t1 WHERE a<=>NULL;
a b
NULL 99
SELECT * FROM t1 WHERE b=NULL;
a b
explain SELECT * FROM t1 WHERE b IS NULL;
-table type possible_keys key key_len ref rows Extra
-t1 ref b b 5 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref b b 5 const 1 Using where
SELECT * FROM t1 WHERE b<=>NULL;
a b
99 NULL
diff --git a/mysql-test/r/heap_auto_increment.result b/mysql-test/r/heap_auto_increment.result
new file mode 100644
index 00000000000..9a5ed57d741
--- /dev/null
+++ b/mysql-test/r/heap_auto_increment.result
@@ -0,0 +1,41 @@
+drop table if exists t1;
+create table t1 (a int not null auto_increment,b int, primary key (a)) type=heap auto_increment=3;
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+delete from t1 where a=4;
+insert into t1 values (NULL,5),(NULL,6);
+select * from t1;
+a b
+1 1
+3 3
+5 5
+6 6
+delete from t1 where a=6;
+replace t1 values (3,1);
+ALTER TABLE t1 add c int;
+replace t1 values (3,3,3);
+insert into t1 values (NULL,7,7);
+update t1 set a=8,b=b+1,c=c+1 where a=7;
+insert into t1 values (NULL,9,9);
+select * from t1;
+a b c
+1 1 NULL
+3 3 3
+5 5 NULL
+8 8 8
+9 9 9
+drop table t1;
+create table t1 (
+skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY,
+sval char(20)
+) type=heap;
+insert into t1 values (NULL, "hello");
+insert into t1 values (NULL, "hey");
+select * from t1;
+skey sval
+1 hello
+2 hey
+select _rowid,t1._rowid,skey,sval from t1;
+_rowid _rowid skey sval
+1 1 1 hello
+2 2 2 hey
+drop table t1;
diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result
new file mode 100644
index 00000000000..bf24f78321f
--- /dev/null
+++ b/mysql-test/r/heap_btree.result
@@ -0,0 +1,235 @@
+drop table if exists t1;
+create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a=1 or a=0;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A NULL NULL NULL BTREE
+select * from t1;
+a b
+2 2
+3 3
+4 4
+select * from t1 where a=4;
+a b
+4 4
+update t1 set b=5 where a=4;
+update t1 set b=b+1 where a>=3;
+replace t1 values (3,3);
+select * from t1;
+a b
+2 2
+3 3
+4 6
+alter table t1 add c int not null, add key using BTREE (c,a);
+drop table t1;
+create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a > 0;
+select * from t1;
+a b
+drop table t1;
+create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
+select * from t1;
+a b
+1 1
+2 2
+3 3
+4 4
+drop table t1;
+create table t1 (a int not null) type=heap;
+insert into t1 values (869751),(736494),(226312),(802616);
+select * from t1 where a > 736494;
+a
+869751
+802616
+alter table t1 add unique uniq_id using BTREE (a);
+select * from t1 where a > 736494;
+a
+802616
+869751
+select * from t1 where a = 736494;
+a
+736494
+select * from t1 where a=869751 or a=736494;
+a
+736494
+869751
+select * from t1 where a in (869751,736494,226312,802616);
+a
+226312
+736494
+802616
+869751
+alter table t1 type=myisam;
+explain select * from t1 where a in (869751,736494,226312,802616);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range uniq_id uniq_id 4 NULL 4 Using where; Using index
+drop table t1;
+create table t1 (x int not null, y int not null, key x using BTREE (x,y), unique y using BTREE (y))
+type=heap;
+insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
+explain select * from t1 where x=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref x x 4 const 1 Using where
+select * from t1 where x=1;
+x y
+1 1
+1 3
+select * from t1,t1 as t2 where t1.x=t2.y;
+x y x y
+1 1 1 1
+2 2 2 2
+1 3 1 1
+2 4 2 2
+2 5 2 2
+2 6 2 2
+explain select * from t1,t1 as t2 where t1.x=t2.y;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL x NULL NULL NULL 6
+1 SIMPLE t2 eq_ref y y 4 t1.x 1
+drop table t1;
+create table t1 (a int) type=heap;
+insert into t1 values(1);
+select max(a) from t1;
+max(a)
+1
+drop table t1;
+CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using BTREE (a,b), key using BTREE (b) ) TYPE=HEAP;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+a b
+1 1
+1 2
+1 3
+1 4
+1 5
+1 6
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+a b
+1 1
+1 1
+1 2
+1 2
+1 3
+1 3
+1 4
+1 4
+1 5
+1 5
+1 6
+1 6
+explain select * from tx where a=x order by a,b;
+id select_type table type possible_keys key key_len ref rows Extra
+x SIMPLE tx ref a a x const x Using where
+explain select * from tx where a=x order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+x SIMPLE tx ref a a x const x Using where
+select * from t1 where b=1;
+a b
+1 1
+1 1
+explain select * from tx where b=x;
+id select_type table type possible_keys key key_len ref rows Extra
+x SIMPLE tx ref b b x const x Using where
+drop table t1;
+create table t1 (id int unsigned not null, primary key using BTREE (id)) type=HEAP;
+insert into t1 values(1);
+select max(id) from t1;
+max(id)
+1
+insert into t1 values(2);
+select max(id) from t1;
+max(id)
+2
+replace into t1 values(1);
+drop table t1;
+create table t1 (n int) type=heap;
+drop table t1;
+create table t1 (n int) type=heap;
+drop table if exists t1;
+CREATE table t1(f1 int not null,f2 char(20) not
+null,index(f2)) type=heap;
+INSERT into t1 set f1=12,f2="bill";
+INSERT into t1 set f1=13,f2="bill";
+INSERT into t1 set f1=14,f2="bill";
+INSERT into t1 set f1=15,f2="bill";
+INSERT into t1 set f1=16,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+delete from t1 where f2="bill";
+select * from t1;
+f1 f2
+16 ted
+12 ted
+12 ted
+12 ted
+12 ted
+drop table t1;
+create table t1 (btn char(10) not null, key using BTREE (btn)) type=heap;
+insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
+explain select * from t1 where btn like "q%";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
+select * from t1 where btn like "q%";
+btn
+alter table t1 add column new_col char(1) not null, add key using BTREE (btn,new_col), drop key btn;
+update t1 set new_col=btn;
+explain select * from t1 where btn="a";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref btn btn 10 const 1 Using where
+explain select * from t1 where btn="a" and new_col="a";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref btn btn 11 const,const 1 Using where
+drop table t1;
+CREATE TABLE t1 (
+a int default NULL,
+b int default NULL,
+KEY a using BTREE (a),
+UNIQUE b using BTREE (b)
+) type=heap;
+INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
+SELECT * FROM t1 WHERE a=NULL;
+a b
+explain SELECT * FROM t1 WHERE a IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 5 const 1 Using where
+SELECT * FROM t1 WHERE a<=>NULL;
+a b
+NULL 99
+SELECT * FROM t1 WHERE b=NULL;
+a b
+explain SELECT * FROM t1 WHERE b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref b b 5 const 1 Using where
+SELECT * FROM t1 WHERE b<=>NULL;
+a b
+99 NULL
+INSERT INTO t1 VALUES (1,3);
+Duplicate entry '3' for key 1
+DROP TABLE t1;
+CREATE TABLE t1 (a int, b int, c int, key using BTREE (a, b, c)) type=heap;
+INSERT INTO t1 VALUES (1, NULL, NULL), (1, 1, NULL), (1, NULL, 1);
+SELECT * FROM t1 WHERE a=1 and b IS NULL;
+a b c
+1 NULL NULL
+1 NULL 1
+SELECT * FROM t1 WHERE a=1 and c IS NULL;
+a b c
+1 NULL NULL
+1 1 NULL
+SELECT * FROM t1 WHERE a=1 and b IS NULL and c IS NULL;
+a b c
+1 NULL NULL
+DROP TABLE t1;
+CREATE TABLE t1 (a int not null, primary key using BTREE (a)) type=heap;
+INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
+DELETE from t1 where a < 100;
+SELECT * from t1;
+a
+DROP TABLE t1;
diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result
new file mode 100644
index 00000000000..3c2baa645f7
--- /dev/null
+++ b/mysql-test/r/heap_hash.result
@@ -0,0 +1,205 @@
+drop table if exists t1;
+create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a=1 or a=0;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH
+select * from t1;
+a b
+2 2
+3 3
+4 4
+select * from t1 where a=4;
+a b
+4 4
+update t1 set b=5 where a=4;
+update t1 set b=b+1 where a>=3;
+replace t1 values (3,3);
+select * from t1;
+a b
+2 2
+3 3
+4 6
+alter table t1 add c int not null, add key using HASH (c,a);
+drop table t1;
+create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a > 0;
+select * from t1;
+a b
+drop table t1;
+create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
+select * from t1;
+a b
+1 1
+2 2
+3 3
+4 4
+drop table t1;
+create table t1 (a int not null) type=heap;
+insert into t1 values (869751),(736494),(226312),(802616);
+select * from t1 where a > 736494;
+a
+869751
+802616
+alter table t1 add unique uniq_id using HASH (a);
+select * from t1 where a > 736494;
+a
+869751
+802616
+select * from t1 where a = 736494;
+a
+736494
+select * from t1 where a=869751 or a=736494;
+a
+736494
+869751
+select * from t1 where a in (869751,736494,226312,802616);
+a
+226312
+736494
+802616
+869751
+alter table t1 type=myisam;
+explain select * from t1 where a in (869751,736494,226312,802616);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range uniq_id uniq_id 4 NULL 4 Using where; Using index
+drop table t1;
+create table t1 (x int not null, y int not null, key x using HASH (x), unique y using HASH (y))
+type=heap;
+insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
+select * from t1 where x=1;
+x y
+1 3
+1 1
+select * from t1,t1 as t2 where t1.x=t2.y;
+x y x y
+1 1 1 1
+2 2 2 2
+1 3 1 1
+2 4 2 2
+2 5 2 2
+2 6 2 2
+explain select * from t1,t1 as t2 where t1.x=t2.y;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL x NULL NULL NULL 6
+1 SIMPLE t2 eq_ref y y 4 t1.x 1
+drop table t1;
+create table t1 (a int) type=heap;
+insert into t1 values(1);
+select max(a) from t1;
+max(a)
+1
+drop table t1;
+CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using HASH (a), key using HASH (b) ) TYPE=HEAP;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+a b
+1 6
+1 5
+1 4
+1 3
+1 2
+1 1
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+a b
+1 6
+1 5
+1 4
+1 3
+1 2
+1 1
+1 6
+1 5
+1 4
+1 3
+1 2
+1 1
+drop table t1;
+create table t1 (id int unsigned not null, primary key using HASH (id)) type=HEAP;
+insert into t1 values(1);
+select max(id) from t1;
+max(id)
+1
+insert into t1 values(2);
+select max(id) from t1;
+max(id)
+2
+replace into t1 values(1);
+drop table t1;
+create table t1 (n int) type=heap;
+drop table t1;
+create table t1 (n int) type=heap;
+drop table if exists t1;
+CREATE table t1(f1 int not null,f2 char(20) not
+null,index(f2)) type=heap;
+INSERT into t1 set f1=12,f2="bill";
+INSERT into t1 set f1=13,f2="bill";
+INSERT into t1 set f1=14,f2="bill";
+INSERT into t1 set f1=15,f2="bill";
+INSERT into t1 set f1=16,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+delete from t1 where f2="bill";
+select * from t1;
+f1 f2
+16 ted
+12 ted
+12 ted
+12 ted
+12 ted
+drop table t1;
+create table t1 (btn char(10) not null, key using HASH (btn)) type=heap;
+insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
+explain select * from t1 where btn like "q%";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
+select * from t1 where btn like "q%";
+btn
+alter table t1 add column new_col char(1) not null, add key using HASH (btn,new_col), drop key btn;
+update t1 set new_col=btn;
+explain select * from t1 where btn="a";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
+explain select * from t1 where btn="a" and new_col="a";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref btn btn 11 const,const 10 Using where
+drop table t1;
+CREATE TABLE t1 (
+a int default NULL,
+b int default NULL,
+KEY a using HASH (a),
+UNIQUE b using HASH (b)
+) type=heap;
+INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
+SELECT * FROM t1 WHERE a=NULL;
+a b
+explain SELECT * FROM t1 WHERE a IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 5 const 10 Using where
+SELECT * FROM t1 WHERE a<=>NULL;
+a b
+NULL 99
+SELECT * FROM t1 WHERE b=NULL;
+a b
+explain SELECT * FROM t1 WHERE b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref b b 5 const 1 Using where
+SELECT * FROM t1 WHERE b<=>NULL;
+a b
+99 NULL
+INSERT INTO t1 VALUES (1,3);
+Duplicate entry '3' for key 1
+DROP TABLE t1;
+CREATE TABLE t1 (a int not null, primary key using HASH (a)) type=heap;
+INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
+DELETE from t1 where a < 100;
+SELECT * from t1;
+a
+DROP TABLE t1;
diff --git a/mysql-test/r/help.result b/mysql-test/r/help.result
new file mode 100644
index 00000000000..4da4a84d4ad
--- /dev/null
+++ b/mysql-test/r/help.result
@@ -0,0 +1,123 @@
+truncate mysql.help_topic;
+truncate mysql.help_category;
+truncate mysql.help_relation;
+insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1');
+SELECT @topic1_id:=LAST_INSERT_ID();
+@topic1_id:=LAST_INSERT_ID()
+1
+insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2');
+SELECT @topic2_id:=LAST_INSERT_ID();
+@topic2_id:=LAST_INSERT_ID()
+2
+insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3');
+SELECT @topic3_id:=LAST_INSERT_ID();
+@topic3_id:=LAST_INSERT_ID()
+3
+insert into mysql.help_category(name)values('impossible_category_1');
+SELECT @category1_id:=LAST_INSERT_ID();
+@category1_id:=LAST_INSERT_ID()
+1
+insert into mysql.help_category(name)values('impossible_category_2');
+SELECT @category2_id:=LAST_INSERT_ID();
+@category2_id:=LAST_INSERT_ID()
+2
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id);
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id);
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id);
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id);
+help 'function_of_my_dream';
+Name Category
+impossible_category_1 Y
+impossible_category_2 Y
+help '%possible_f%';
+Name Category
+impossible_function_1 N
+impossible_function_2 N
+impossible_function_3 N
+help 'impossible_func%';
+Name Category
+impossible_function_1 N
+impossible_function_2 N
+impossible_function_3 N
+help 'impossible_category%';
+Name Category
+impossible_category_1 Y
+impossible_category_2 Y
+help 'impossible_%';
+Name Category
+impossible_function_1 N
+impossible_function_2 N
+impossible_function_3 N
+impossible_category_1 Y
+impossible_category_2 Y
+help '%function_2';
+Name Category Description Example
+impossible_function_2 N description of
+ impossible_function2 example of
+ impossible_function2
+help '%category_2';
+Name Category Description Example
+impossible_category_2 Y impossible_function_2
+impossible_function_3
+
+help 'impossible_function_1';
+Name Category Description Example
+impossible_function_1 N description of
+ impossible_function1 example of
+ impossible_function1
+help 'impossible_category_1';
+Name Category Description Example
+impossible_category_1 Y impossible_function_1
+impossible_function_2
+
+alter table mysql.help_topic type=innodb;
+alter table mysql.help_category type=innodb;
+alter table mysql.help_relation type=innodb;
+help 'function_of_my_dream';
+Name Category
+impossible_category_1 Y
+impossible_category_2 Y
+help '%ble_f%';
+Name Category
+impossible_function_1 N
+impossible_function_2 N
+impossible_function_3 N
+help 'impossible_func%';
+Name Category
+impossible_function_1 N
+impossible_function_2 N
+impossible_function_3 N
+help 'impossible_category%';
+Name Category
+impossible_category_1 Y
+impossible_category_2 Y
+help 'impossible_%';
+Name Category
+impossible_function_1 N
+impossible_function_2 N
+impossible_function_3 N
+impossible_category_1 Y
+impossible_category_2 Y
+help '%function_2';
+Name Category Description Example
+impossible_function_2 N description of
+ impossible_function2 example of
+ impossible_function2
+help '%category_2';
+Name Category Description Example
+impossible_category_2 Y impossible_function_2
+impossible_function_3
+
+help 'impossible_function_1';
+Name Category Description Example
+impossible_function_1 N description of
+ impossible_function1 example of
+ impossible_function1
+help 'impossible_category_1';
+Name Category Description Example
+impossible_category_1 Y impossible_function_1
+impossible_function_2
+
+alter table mysql.help_topic type=myisam;
+alter table mysql.help_category type=myisam;
+alter table mysql.help_relation type=myisam;
diff --git a/mysql-test/r/innodb-deadlock.result b/mysql-test/r/innodb-deadlock.result
index 121bfa8c6cb..e1b3e38b243 100644
--- a/mysql-test/r/innodb-deadlock.result
+++ b/mysql-test/r/innodb-deadlock.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
create table t1 (id integer, x integer) type=INNODB;
insert into t1 values(0, 0);
set autocommit=0;
@@ -18,3 +18,79 @@ id x
0 2
commit;
drop table t1;
+create table t1 (id integer, x integer) type=INNODB;
+create table t2 (b integer, a integer) type=INNODB;
+insert into t1 values(0, 0), (300, 300);
+insert into t2 values(0, 10), (1, 20), (2, 30);
+commit;
+set autocommit=0;
+select * from t2;
+b a
+0 10
+1 20
+2 30
+update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE);
+select * from t2;
+b a
+0 100
+1 20
+2 30
+select * from t1;
+id x
+0 0
+300 300
+set autocommit=0;
+update t1 set x=2 where id = 0;
+update t1 set x=1 where id = 0;
+select * from t1;
+id x
+0 1
+300 300
+commit;
+commit;
+select * from t1;
+id x
+0 2
+300 300
+commit;
+drop table t1, t2;
+create table t1 (id integer, x integer) type=INNODB;
+create table t2 (b integer, a integer) type=INNODB;
+insert into t1 values(0, 0), (300, 300);
+insert into t2 values(0, 0), (1, 20), (2, 30);
+commit;
+select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
+a b
+0 0
+20 1
+30 2
+300 300
+select * from t2;
+b a
+0 0
+1 20
+2 30
+select * from t1;
+id x
+0 0
+300 300
+update t2 set a=2 where b = 0;
+select * from t2;
+b a
+0 2
+1 20
+2 30
+update t1 set x=2 where id = 0;
+update t1 set x=1 where id = 0;
+select * from t1;
+id x
+0 1
+300 300
+commit;
+commit;
+select * from t1;
+id x
+0 2
+300 300
+commit;
+drop table t1, t2;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 828bd2bab83..9ea2ea0f87c 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -139,14 +139,14 @@ id parent_id level
1010 102 2
1015 102 2
explain select level from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 12 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 12 Using where; Using index
explain select level,id from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 12 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 12 Using where; Using index
explain select level,id,parent_id from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 12 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 12 Using where
select level,id from t1 where level=1;
level id
1 1002
@@ -596,8 +596,8 @@ id parent_id level
1025 102 2
1016 102 2
explain select level from t1 where level=1;
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 6 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const 6 Using where; Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -758,8 +758,8 @@ DROP TABLE t1;
create table t1 (a int primary key,b int, c int, d int, e int, f int, g int, h int, i int, j int, k int, l int, m int, n int, o int, p int, q int, r int, s int, t int, u int, v int, w int, x int, y int, z int, a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, b1 int, b2 int, b3 int, b4 int, b5 int, b6 int) type = innodb;
insert into t1 values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
explain select * from t1 where a > 0 and a < 50;
-table type possible_keys key key_len ref rows Extra
-t1 range PRIMARY PRIMARY 4 NULL 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where
drop table t1;
create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=innodb;
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
@@ -807,7 +807,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` char(20) default NULL,
KEY `a` (`a`)
-) TYPE=InnoDB
+) TYPE=InnoDB CHARSET=latin1
drop table t1;
create temporary table t1 (a int not null auto_increment, primary key(a)) type=innodb;
insert into t1 values (NULL),(NULL),(NULL);
@@ -892,34 +892,34 @@ drop table t1;
create table t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) type=innodb;
insert into t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4);
explain select * from t1 order by a;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 4
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 4
explain select * from t1 order by b;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL b 4 NULL 4
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL 4
explain select * from t1 order by c;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4 Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
explain select a from t1 order by a;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 4 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 Using index
explain select b from t1 order by b;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL b 4 NULL 4 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL 4 Using index
explain select a,b from t1 order by b;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL b 4 NULL 4 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL 4 Using index
explain select a,b from t1;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL b 4 NULL 4 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL 4 Using index
explain select a,b,c from t1;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
drop table t1;
create table t1 (t int not null default 1, key (t)) type=innodb;
desc t1;
-Field Type Null Key Default Extra
-t int(11) MUL 1
+Field Type Collation Null Key Default Extra
+t int(11) binary MUL 1
drop table t1;
CREATE TABLE t1 (
number bigint(20) NOT NULL default '0',
@@ -959,29 +959,29 @@ INSERT INTO t2 VALUES (650,'San Francisco',90,0,20020109113158,342,0000000000000
INSERT INTO t2 VALUES (333,'tubs',99,2,20020109113453,501,20020109113453,500,3,10,0);
select * from t1;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
-4077711111 SeanWheeler 90 2 20020111112846 500 00000000000000 -1 2 3 1
-9197722223 berry 90 3 20020111112809 500 20020102114532 501 4 10 0
-650 San Francisco 0 0 20011227111336 342 00000000000000 -1 1 24 1
-302467 Sue's Subshop 90 3 20020109113241 500 20020102115111 501 7 24 0
-6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0
-333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0
+4077711111 SeanWheeler 90 2 2002-01-11 11:28:46 500 0000-00-00 00:00:00 -1 2 3 1
+9197722223 berry 90 3 2002-01-11 11:28:09 500 2002-01-02 11:45:32 501 4 10 0
+650 San Francisco 0 0 2001-12-27 11:13:36 342 0000-00-00 00:00:00 -1 1 24 1
+302467 Sue's Subshop 90 3 2002-01-09 11:32:41 500 2002-01-02 11:51:11 501 7 24 0
+6014911113 SudzCarwash 520 1 2002-01-02 11:52:34 500 2002-01-02 11:52:59 501 33 32768 0
+333 tubs 99 2 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
select * from t2;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
-4077711111 SeanWheeler 0 2 20020111112853 500 00000000000000 -1 2 3 1
-9197722223 berry 90 3 20020111112818 500 20020102114532 501 4 10 0
-650 San Francisco 90 0 20020109113158 342 00000000000000 -1 1 24 1
-333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
+4077711111 SeanWheeler 0 2 2002-01-11 11:28:53 500 0000-00-00 00:00:00 -1 2 3 1
+9197722223 berry 90 3 2002-01-11 11:28:18 500 2002-01-02 11:45:32 501 4 10 0
+650 San Francisco 90 0 2002-01-09 11:31:58 342 0000-00-00 00:00:00 -1 1 24 1
+333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
delete t1, t2 from t1 left join t2 on t1.number=t2.number where (t1.carrier_id=90 and t1.number=t2.number) or (t2.carrier_id=90 and t1.number=t2.number) or (t1.carrier_id=90 and t2.number is null);
select * from t1;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
-6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0
-333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0
+6014911113 SudzCarwash 520 1 2002-01-02 11:52:34 500 2002-01-02 11:52:59 501 33 32768 0
+333 tubs 99 2 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
select * from t2;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
-333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
+333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
select * from t2;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
-333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
+333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
drop table t1,t2;
create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=innodb;
BEGIN;
@@ -1021,7 +1021,6 @@ id code name
7 4 Matt
COMMIT;
DROP TABLE t1;
-drop table if exists t1,t2;
create table t1 (n int(10), d int(10)) type=innodb;
create table t2 (n int(10), d int(10)) type=innodb;
insert into t1 values(1,1),(1,2);
diff --git a/mysql-test/r/innodb_cache.result b/mysql-test/r/innodb_cache.result
index 47abcb45fe5..7d351a13e16 100644
--- a/mysql-test/r/innodb_cache.result
+++ b/mysql-test/r/innodb_cache.result
@@ -1,4 +1,4 @@
-drop table if exists t1, t2, t3;
+drop table if exists t1,t2,t3;
flush status;
set autocommit=0;
create table t1 (a int not null) type=innodb;
diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result
index a55114a0e3d..dc6a265fb29 100644
--- a/mysql-test/r/innodb_handler.result
+++ b/mysql-test/r/innodb_handler.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
create table t1 (a int, b char(10), key a(a), key b(a,b)) type=innodb;
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 69b790ff35b..ebd34dd7668 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -58,9 +58,9 @@ skr 2
test 1
test 2
drop table t1;
-drop database if exists foo;
-create database foo;
-use foo;
+drop database if exists test_$1;
+create database test_$1;
+use test_$1;
create table t1 (c int);
-insert into foo.t1 set foo.t1.c = '1';
-drop database foo;
+insert into test_$1.t1 set test_$1.t1.c = '1';
+drop database test_$1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index e24c3179a0c..9a65eaee573 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -21,8 +21,7 @@ payoutID
20
22
drop table t1,t2;
-DROP TABLE IF EXISTS crash1,crash2;
-CREATE TABLE `crash1` (
+CREATE TABLE `t1` (
`numeropost` bigint(20) unsigned NOT NULL default '0',
`icone` tinyint(4) unsigned NOT NULL default '0',
`numreponse` bigint(20) unsigned NOT NULL auto_increment,
@@ -37,7 +36,7 @@ KEY `date` (`date`),
KEY `pseudo` (`pseudo`),
KEY `numreponse` (`numreponse`)
) TYPE=MyISAM;
-CREATE TABLE `crash2` (
+CREATE TABLE `t2` (
`numeropost` bigint(20) unsigned NOT NULL default '0',
`icone` tinyint(4) unsigned NOT NULL default '0',
`numreponse` bigint(20) unsigned NOT NULL auto_increment,
@@ -52,17 +51,17 @@ KEY `date` (`date`),
KEY `pseudo` (`pseudo`),
KEY `numreponse` (`numreponse`)
) TYPE=MyISAM;
-INSERT INTO crash2
+INSERT INTO t2
(numeropost,icone,numreponse,contenu,pseudo,date,ip,signature) VALUES
(9,1,56,'test','joce','2001-07-25 13:50:53'
,3649052399,0);
-INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
-SELECT 1618,icone,contenu,pseudo,date,signature,ip FROM crash2
+INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1618,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC;
show variables like '%bulk%';
Variable_name Value
bulk_insert_buffer_size 8388608
-INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
-SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2
+INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC;
-DROP TABLE IF EXISTS crash1,crash2;
+DROP TABLE IF EXISTS t1,t2;
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result
new file mode 100644
index 00000000000..8cc79564679
--- /dev/null
+++ b/mysql-test/r/insert_update.result
@@ -0,0 +1,51 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
+INSERT t1 VALUES (1,2,10), (3,4,20);
+INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100;
+SELECT * FROM t1;
+a b c
+1 2 10
+3 4 20
+5 6 30
+INSERT t1 VALUES (5,7,40) ON DUPLICATE KEY UPDATE c=c+100;
+SELECT * FROM t1;
+a b c
+1 2 10
+3 4 20
+5 6 130
+INSERT t1 VALUES (8,4,50) ON DUPLICATE KEY UPDATE c=c+1000;
+SELECT * FROM t1;
+a b c
+1 2 10
+3 4 1020
+5 6 130
+INSERT t1 VALUES (1,4,60) ON DUPLICATE KEY UPDATE c=c+10000;
+SELECT * FROM t1;
+a b c
+1 2 10010
+3 4 1020
+5 6 130
+INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE c=c+100000, b=4;
+Duplicate entry '4' for key 2
+SELECT * FROM t1;
+a b c
+1 2 10010
+3 4 1020
+5 6 130
+TRUNCATE TABLE t1;
+INSERT t1 VALUES (1,2,10), (3,4,20);
+INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100;
+SELECT * FROM t1;
+a b c
+1 2 10
+3 4 120
+5 6 30
+8 9 60
+INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0;
+SELECT * FROM t1;
+a b c
+1 2 10
+3 4 120
+5 0 30
+8 9 60
+DROP TABLE t1;
diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result
index 0f7224f52da..7871e899773 100644
--- a/mysql-test/r/isam.result
+++ b/mysql-test/r/isam.result
@@ -38,6 +38,8 @@ Incorrect table definition; There can only be one auto column and it must be def
create table t1 (ordid int(8), unique (ordid)) type=isam;
Column 'ordid' is used with UNIQUE or INDEX but is not defined as NOT NULL
drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
create table t2 type=isam select * from t1;
@@ -62,15 +64,15 @@ Table Op Msg_type Msg_text
test.t2 check error Table 't2' was not locked with LOCK TABLES
test.t1 check status OK
show columns from t1;
-Field Type Null Key Default Extra
-a int(11) PRI 0
-b int(11) MUL 0
-c int(11) 0
+Field Type Collation Null Key Default Extra
+a int(11) binary PRI 0
+b int(11) binary MUL 0
+c int(11) binary 0
show full columns from t1;
-Field Type Null Key Default Extra Privileges
-a int(11) PRI 0 select,insert,update,references
-b int(11) MUL 0 select,insert,update,references
-c int(11) 0 select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+a int(11) binary PRI 0 select,insert,update,references
+b int(11) binary MUL 0 select,insert,update,references
+c int(11) binary 0 select,insert,update,references
show index from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 a A 4 NULL NULL BTREE
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index ddea0ac1a57..274a4dec85d 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -61,12 +61,12 @@ select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75
id id
NULL 75
explain select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null;
-table type possible_keys key key_len ref rows Extra
-t1 const PRIMARY NULL NULL NULL 1 Impossible ON condition
-t2 ALL NULL NULL NULL NULL 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY NULL NULL NULL 1 Impossible ON condition
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
explain select t1.id, t2.id from t1, t2 where t2.id = t1.id and t1.id <0 and t1.id > 0;
-Comment
-Impossible WHERE noticed after reading const tables
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1,t2;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 37e18b8b304..8abe6d517ee 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -90,12 +90,12 @@ grp a c id a c d
2 3 c NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
-Comment
-Impossible WHERE noticed after reading const tables
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 7
-t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 7
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 Using where
select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
grp a c id a c d a
1 1 a 1 1 a 1 1
@@ -181,7 +181,6 @@ SELECT t1.usr_id,t1.uniq_id,t1.increment,t2.usr2_id,t2.c_amount,t2.max FROM t1 L
usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
drop table t1,t2;
-drop table if exists t1,t2,t3,t4;
CREATE TABLE t1 (
cod_asig int(11) DEFAULT '0' NOT NULL,
desc_larga_cat varchar(80) DEFAULT '' NOT NULL,
@@ -311,13 +310,13 @@ select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where
name name id
Lilliana Angelovska NULL NULL
explain select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.id is null;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 3
-t2 ALL NULL NULL NULL NULL 3 Using where; Not exists
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where; Not exists
explain select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.name is null;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 3
-t2 ALL NULL NULL NULL NULL 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
select count(*) from t1 left join t2 on (t1.id = t2.owner);
count(*)
4
@@ -331,13 +330,13 @@ select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where
name name id
Lilliana Angelovska NULL NULL
explain select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.id is null;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 3
-t2 ALL NULL NULL NULL NULL 3 Using where; Not exists
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where; Not exists
explain select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.name is null;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 3
-t2 ALL NULL NULL NULL NULL 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
select count(*) from t2 right join t1 on (t1.id = t2.owner);
count(*)
4
@@ -618,9 +617,9 @@ UNIQUE id (id,idx)
);
INSERT INTO t2 VALUES (1,1);
explain SELECT * from t1 left join t2 on t1.id=t2.id where t2.id IS NULL;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 2
-t2 index id id 8 NULL 1 Using where; Using index; Not exists
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 index id id 8 NULL 1 Using where; Using index; Not exists
SELECT * from t1 left join t2 on t1.id=t2.id where t2.id IS NULL;
id name id idx
2 no NULL NULL
@@ -638,9 +637,9 @@ create table t2 (fooID smallint unsigned not null, barID smallint unsigned not n
insert into t1 (fooID) values (10),(20),(30);
insert into t2 values (10,1),(20,2),(30,3);
explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
-table type possible_keys key key_len ref rows Extra
-t2 index NULL PRIMARY 4 NULL 3 Using index
-t1 eq_ref PRIMARY PRIMARY 2 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL PRIMARY 4 NULL 3 Using index
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 2 const 1 Using where; Using index
select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
fooID barID fooID
10 1 NULL
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index 1cd9c9dfe79..9e1f743d132 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -147,7 +147,6 @@ t1 0 e 1 e A 0 NULL NULL BTREE
t1 0 b 1 b A NULL NULL NULL YES BTREE
t1 1 c 1 c A NULL NULL NULL YES BTREE
drop table t1;
-DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c CHAR(10) NOT NULL,i INT NOT NULL AUTO_INCREMENT,
UNIQUE (c,i));
INSERT INTO t1 (c) VALUES (NULL),(NULL);
diff --git a/mysql-test/r/key_diff.result b/mysql-test/r/key_diff.result
index 4eaccc696f9..8097186bde1 100644
--- a/mysql-test/r/key_diff.result
+++ b/mysql-test/r/key_diff.result
@@ -34,9 +34,9 @@ C c a a
D E a a
a a a a
explain select t1.*,t2.* from t1,t1 as t2 where t1.A=t2.B;
-table type possible_keys key key_len ref rows Extra
-t1 ALL a NULL NULL NULL 5
-t2 ALL b NULL NULL NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 5
+1 SIMPLE t2 ALL b NULL NULL NULL 5 Using where
select t1.*,t2.* from t1,t1 as t2 where t1.A=t2.B order by binary t1.a,t2.a;
a b a b
A B a a
diff --git a/mysql-test/r/key_primary.result b/mysql-test/r/key_primary.result
index 87289f1cf54..14ca90b3dd2 100644
--- a/mysql-test/r/key_primary.result
+++ b/mysql-test/r/key_primary.result
@@ -12,9 +12,9 @@ select * from t1 where t1 like "a_\%";
t1
AB%
describe select * from t1 where t1="ABC";
-table type possible_keys key key_len ref rows Extra
-t1 const PRIMARY PRIMARY 3 const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 3 const 1
describe select * from t1 where t1="ABCD";
-Comment
-Impossible WHERE noticed after reading const tables
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1;
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index 2ca36425841..c218379110f 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -3,7 +3,7 @@ create table t1 (time time, date date, timestamp timestamp);
insert into t1 values ("12:22:22","97:02:03","1997-01-02");
select * from t1;
time date timestamp
-12:22:22 1997-02-03 19970102000000
+12:22:22 1997-02-03 1997-01-02 00:00:00
select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time)
122222 19970203 19970102000000 1997-02-03 12:22:22
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 0bffc93c284..b28607218d1 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -34,11 +34,11 @@ insert into t2 select NULL,message from t1;
insert into t1 select NULL,message from t2;
create table t3 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,test.t2);
explain select * from t3 where a < 10;
-table type possible_keys key key_len ref rows Extra
-t3 range a a 4 NULL 18 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range a a 4 NULL 18 Using where
explain select * from t3 where a > 10 and a < 20;
-table type possible_keys key key_len ref rows Extra
-t3 range a a 4 NULL 16 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range a a 4 NULL 16 Using where
select * from t3 where a = 10;
a b
10 Testing
@@ -84,8 +84,8 @@ a b
19 Testing
19 Testing
explain select a from t3 order by a desc limit 10;
-table type possible_keys key key_len ref rows Extra
-t3 index NULL a 4 NULL 1131 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index NULL a 4 NULL 1131 Using index
select a from t3 order by a desc limit 10;
a
699
@@ -174,13 +174,15 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
-) TYPE=MRG_MyISAM UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
select * from t4;
Can't open file: 't4.MRG'. (errno: 143)
create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
Incorrect table definition; All MERGE tables must be in the same database
drop table if exists t5,t4,t3,t1,t2;
+Warnings:
+Note 1051 Unknown table 't5'
create table t1 (c char(10)) type=myisam;
create table t2 (c char(10)) type=myisam;
create table t3 (c char(10)) union=(t1,t2) type=merge;
@@ -249,20 +251,19 @@ t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0',
PRIMARY KEY (`incr`)
-) TYPE=MRG_MyISAM UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
alter table t3 drop primary key;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0'
-) TYPE=MRG_MyISAM UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
drop table t3,t2,t1;
create table t1 (a int not null, key(a)) type=merge;
select * from t1;
a
drop table t1;
-drop table if exists t3, t2, t1;
create table t1 (a int not null, b int not null, key(a,b));
create table t2 (a int not null, b int not null, key(a,b));
create table t3 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2);
@@ -274,7 +275,6 @@ a b
1 1
1 2
drop table t3,t1,t2;
-drop table if exists t6, t5, t4, t3, t2, t1;
create table t1 (a int not null, b int not null auto_increment, primary key(a,b));
create table t2 (a int not null, b int not null auto_increment, primary key(a,b));
create table t3 (a int not null, b int not null, key(a,b)) UNION=(t1,t2) INSERT_METHOD=NO;
@@ -287,28 +287,28 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
show create table t4;
Table Create Table
t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
-) TYPE=MRG_MyISAM INSERT_METHOD=FIRST UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(t1,t2)
show create table t6;
Table Create Table
t6 CREATE TABLE `t6` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
-) TYPE=MRG_MyISAM INSERT_METHOD=LAST UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=LAST UNION=(t1,t2)
insert into t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL);
insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL);
select * from t3 order by b,a limit 3;
@@ -373,7 +373,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM UNION=(t1,t2,t3)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2,t3)
select * from t4 order by a,b;
a b
1 1
@@ -399,7 +399,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM INSERT_METHOD=FIRST UNION=(t1,t2,t3)
+) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(t1,t2,t3)
insert into t4 values (4,1),(4,2);
select * from t1 order by a,b;
a b
@@ -533,15 +533,14 @@ CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '
INSERT INTO t1 VALUES (1,1), (2,1);
CREATE TABLE t2 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
INSERT INTO t2 VALUES (1,2), (2,2);
-CREATE TABLE t ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
-select max(b) from t where a = 2;
+CREATE TABLE t3 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
+select max(b) from t3 where a = 2;
max(b)
2
select max(b) from t1 where a = 2;
max(b)
1
-drop table if exists t,t1,t2;
-drop table if exists t1, t2, t3, t4, t5, t6;
+drop table if exists t3,t1,t2;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
@@ -560,8 +559,7 @@ select * from t6;
a
1
2
-drop table if exists t1, t2, t3, t4, t5, t6;
-DROP TABLE IF EXISTS t1, t2;
+drop table if exists t6, t3, t1, t2, t4, t5;
CREATE TABLE t1 (
fileset_id tinyint(3) unsigned NOT NULL default '0',
file_code varchar(32) NOT NULL default '',
@@ -581,18 +579,18 @@ KEY files (fileset_id,fileset_root_id)
) TYPE=MRG_MyISAM UNION=(t1);
EXPLAIN SELECT * FROM t2 IGNORE INDEX (files) WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
-table type possible_keys key key_len ref rows Extra
-t2 range PRIMARY PRIMARY 33 NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range PRIMARY PRIMARY 33 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
-table type possible_keys key key_len ref rows Extra
-t2 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range PRIMARY,files PRIMARY 33 NULL 5 Using where
EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
-table type possible_keys key key_len ref rows Extra
-t1 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,files PRIMARY 33 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
-table type possible_keys key key_len ref rows Extra
-t2 const PRIMARY,files PRIMARY 33 const,const 1
-DROP TABLE IF EXISTS t1, t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const PRIMARY,files PRIMARY 33 const,const 1
+DROP TABLE t2, t1;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index fe028a4cb95..4dbb3c8adb1 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -96,7 +96,7 @@ id mydate
5 2002-05-12 00:00:00
6 2002-06-22 00:00:00
7 2002-07-22 00:00:00
-DROP TABLE IF EXISTS t1,t2,t3;
+DROP TABLE t1,t2,t3;
CREATE TABLE IF NOT EXISTS `t1` (
`id` int(11) NOT NULL auto_increment,
`tst` text,
@@ -125,7 +125,7 @@ ID ParId tst tst1
1 1 MySQL MySQL AB
2 2 MSSQL Microsoft
3 3 ORACLE ORACLE
-drop table if exists t1, t2 ;
+drop table t1, t2 ;
create table t1 (n numeric(10));
create table t2 (n numeric(10));
insert into t2 values (1),(2),(4),(8),(16),(32);
@@ -235,8 +235,22 @@ select * from t2;
n d
1 30
1 30
+UPDATE t1 a ,t2 b SET a.d=b.d,b.d=30 WHERE a.n=b.n;
+select * from t1;
+n d
+1 30
+3 2
+select * from t2;
+n d
+1 30
+1 30
+DELETE t1, t2 FROM t1 a,t2 b where a.n=b.n;
+select * from t1;
+n d
+3 2
+select * from t2;
+n d
drop table t1,t2;
-drop table if exists t1,t2,t3;
CREATE TABLE t1 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,'jedan'),(2,'dva'),(3,'tri'),(4,'xxxxxxxxxx'),(5,'a'),(10,''),(11,''),(12,''),(13,'');
CREATE TABLE t2 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
@@ -245,4 +259,4 @@ CREATE TABLE t3 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT
INSERT INTO t3 VALUES (1,'jedan'),(2,'dva');
update t1,t2 set t1.naziv="aaaa" where t1.broj=t2.broj;
update t1,t2,t3 set t1.naziv="bbbb", t2.naziv="aaaa" where t1.broj=t2.broj and t2.broj=t3.broj;
-drop table if exists t1,t2,t3;
+drop table t1,t2,t3;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 3a3558eedcb..c0914e23992 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -1,7 +1,7 @@
drop table if exists t1,t2;
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
-KEY STRING_DATA (STRING_DATA)
+KEY string_data (STRING_DATA)
) TYPE=MyISAM;
INSERT INTO t1 VALUES ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
INSERT INTO t1 VALUES ('DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD');
@@ -51,29 +51,29 @@ drop table t1;
create table t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) type=myisam;
insert into t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4);
explain select * from t1 order by a;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4 Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
explain select * from t1 order by b;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4 Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
explain select * from t1 order by c;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4 Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
explain select a from t1 order by a;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL PRIMARY 4 NULL 4 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 Using index
explain select b from t1 order by b;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL b 4 NULL 4 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL 4 Using index
explain select a,b from t1 order by b;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4 Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
explain select a,b from t1;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
explain select a,b,c from t1;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4
drop table t1;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1), (2), (3);
@@ -83,7 +83,6 @@ OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
DROP TABLE t1;
-drop table if exists t1;
create table t1 ( t1 char(255), key(t1(250)));
insert t1 values ('137513751375137513751375137513751375137569516951695169516951695169516951695169');
insert t1 values ('178417841784178417841784178417841784178403420342034203420342034203420342034203');
@@ -121,7 +120,6 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
-drop table if exists t1;
create table t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
@@ -286,7 +284,7 @@ insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
-drop table if exists t1;
+drop table t1;
CREATE TABLE `t1` (
`post_id` mediumint(8) unsigned NOT NULL auto_increment,
`topic_id` mediumint(8) unsigned NOT NULL default '0',
@@ -334,29 +332,40 @@ t1 1 a 2 b A 5 NULL NULL YES BTREE
t1 1 c_2 1 c A 5 NULL NULL YES BTREE
t1 1 c_2 2 a A 5 NULL NULL BTREE
explain select * from t1,t2 where t1.a=t2.a;
-table type possible_keys key key_len ref rows Extra
-t1 ALL a NULL NULL NULL 5
-t2 ALL a NULL NULL NULL 2 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 5
+1 SIMPLE t2 ALL a NULL NULL NULL 2 Using where
explain select * from t1,t2 force index(a) where t1.a=t2.a;
-table type possible_keys key key_len ref rows Extra
-t2 ALL a NULL NULL NULL 2
-t1 ALL a NULL NULL NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL a NULL NULL NULL 2
+1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
-table type possible_keys key key_len ref rows Extra
-t2 ALL a NULL NULL NULL 2
-t1 ref a a 4 t2.a 3
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL a NULL NULL NULL 2
+1 SIMPLE t1 ref a a 4 t2.a 3
explain select * from t1,t2 where t1.b=t2.b;
-table type possible_keys key key_len ref rows Extra
-t2 ALL b NULL NULL NULL 2
-t1 ref b b 5 t2.b 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL b NULL NULL NULL 2
+1 SIMPLE t1 ref b b 5 t2.b 1 Using where
explain select * from t1,t2 force index(c) where t1.a=t2.a;
-table type possible_keys key key_len ref rows Extra
-t1 ALL a NULL NULL NULL 5
-t2 ALL NULL NULL NULL NULL 2 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 5
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where
explain select * from t1 where a=0 or a=2;
-table type possible_keys key key_len ref rows Extra
-t1 ALL a NULL NULL NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index (a) where a=0 or a=2;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 4 NULL 4 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 4 NULL 4 Using where
+explain select * from t1 where c=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c,c_2 c 5 const 1 Using where
+explain select * from t1 use index() where c=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
drop table t1,t2;
+CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
+This version of MySQL doesn't yet support 'RTREE INDEX'
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 't1'
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index ba2161d3147..08612fa191f 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
select null,\N,isnull(null),isnull(1/0),isnull(1/0 = null),ifnull(null,1),ifnull(null,"TRUE"),ifnull("TRUE","ERROR"),1/0 is null,1 is not null;
NULL NULL isnull(null) isnull(1/0) isnull(1/0 = null) ifnull(null,1) ifnull(null,"TRUE") ifnull("TRUE","ERROR") 1/0 is null 1 is not null
NULL NULL 1 1 1 1 TRUE TRUE 1 1
@@ -34,7 +35,6 @@ NULL AND 0 0 and NULL
select inet_ntoa(null),inet_aton(null),inet_aton("122.256"),inet_aton("122.226."),inet_aton("");
inet_ntoa(null) inet_aton(null) inet_aton("122.256") inet_aton("122.226.") inet_aton("")
NULL NULL NULL NULL NULL
-drop table if exists t1;
create table t1 (x int);
insert into t1 values (null);
select * from t1 where x != 0;
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index 236def64b5e..ce3af6c37cd 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -1,39 +1,39 @@
-drop table if exists t1;
+drop table if exists t1,t2;
create table t1 (a int, b int not null,unique key (a,b),index(b)) type=myisam;
insert ignore into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(null,7),(9,9),(8,8),(7,7),(null,9),(null,9),(6,6);
explain select * from t1 where a is null;
-table type possible_keys key key_len ref rows Extra
-t1 ref a a 5 const 3 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 5 const 3 Using where; Using index
explain select * from t1 where a is null and b = 2;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 9 const,const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 9 const,const 1 Using where; Using index
explain select * from t1 where a is null and b = 7;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 9 const,const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 9 const,const 1 Using where; Using index
explain select * from t1 where a=2 and b = 2;
-table type possible_keys key key_len ref rows Extra
-t1 const a,b a 9 const,const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const a,b a 9 const,const 1
explain select * from t1 where a<=>b limit 2;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL a 9 NULL 12 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 9 NULL 12 Using where; Using index
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
-table type possible_keys key key_len ref rows Extra
-t1 range a,b a 9 NULL 3 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a,b a 9 NULL 3 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b b 4 const 2 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b b 4 const 2 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 3 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 3 Using where; Using index
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
-table type possible_keys key key_len ref rows Extra
-t1 range a,b a 9 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a,b a 9 NULL 2 Using where; Using index
explain select * from t1 where a > 1 and a < 3 limit 1;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 5 NULL 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 5 NULL 1 Using where; Using index
explain select * from t1 where a > 8 and a < 9;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 5 NULL 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 5 NULL 1 Using where; Using index
select * from t1 where a is null;
a b
NULL 7
@@ -65,44 +65,44 @@ NULL 9
NULL 9
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b = 2 and c=0;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b = 7 and c=0;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a=2 and b = 2;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 1 Using where
explain select * from t1 where a<=>b limit 2;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 12 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 12 Using where
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 and c=0 limit 3;
-table type possible_keys key key_len ref rows Extra
-t1 range a,b a 5 NULL 5 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a,b a 5 NULL 5 Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
-table type possible_keys key key_len ref rows Extra
-t1 range a,b a 5 NULL 4 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a,b a 5 NULL 4 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
-table type possible_keys key key_len ref rows Extra
-t1 ref a,b a 5 const 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a > 1 and a < 3 limit 1;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 5 NULL 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 5 NULL 1 Using where
explain select * from t1 where a is null and b=7 or a > 1 and a < 3 limit 1;
-table type possible_keys key key_len ref rows Extra
-t1 range a,b a 5 NULL 4 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a,b a 5 NULL 4 Using where
explain select * from t1 where a > 8 and a < 9;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 5 NULL 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 5 NULL 1 Using where
explain select * from t1 where b like "6%";
-table type possible_keys key key_len ref rows Extra
-t1 range b b 12 NULL 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range b b 12 NULL 1 Using where
select * from t1 where a is null;
a b c
NULL 7 0
@@ -136,7 +136,6 @@ select * from t1 where b like "6%";
a b c
6 6 0
drop table t1;
-DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 (
id int(10) unsigned NOT NULL auto_increment,
uniq_id int(10) unsigned default NULL,
@@ -151,11 +150,11 @@ PRIMARY KEY (id)
INSERT INTO t1 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
INSERT INTO t2 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
explain select id from t1 where uniq_id is null;
-table type possible_keys key key_len ref rows Extra
-t1 ref idx1 idx1 5 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1 idx1 5 const 1 Using where
explain select id from t1 where uniq_id =1;
-table type possible_keys key key_len ref rows Extra
-t1 const idx1 idx1 5 const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const idx1 idx1 5 const 1
UPDATE t1 SET id=id+100 where uniq_id is null;
UPDATE t2 SET id=id+100 where uniq_id is null;
select id from t1 where uniq_id is null;
diff --git a/mysql-test/r/odbc.result b/mysql-test/r/odbc.result
index 5aa163a663e..c0b2ada0053 100644
--- a/mysql-test/r/odbc.result
+++ b/mysql-test/r/odbc.result
@@ -1,7 +1,7 @@
+drop table if exists t1;
select {fn length("hello")}, { date "1997-10-20" };
{fn length("hello")} 1997-10-20
5 1997-10-20
-drop table if exists t1;
create table t1 (a int not null auto_increment,b int not null,primary key (a,b));
insert into t1 SET A=NULL,B=1;
insert into t1 SET a=null,b=2;
@@ -11,6 +11,6 @@ a b
select * from t1 where a is null;
a b
explain select * from t1 where b is null;
-Comment
-Impossible WHERE noticed after reading const tables
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1;
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 52bd83df5ed..428d1052d19 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -1,6 +1,6 @@
-drop table if exists sales;
-create table sales ( product varchar(32), country varchar(32), year int, profit int);
-insert into sales values ( 'Computer', 'India',2000, 1200),
+drop table if exists t1;
+create table t1 ( product varchar(32), country varchar(32), year int, profit int);
+insert into t1 values ( 'Computer', 'India',2000, 1200),
( 'TV', 'United States', 1999, 150),
( 'Calculator', 'United States', 1999,50),
( 'Computer', 'United States', 1999,1500),
@@ -14,14 +14,14 @@ insert into sales values ( 'Computer', 'India',2000, 1200),
( 'Computer', 'India', 1999,1200),
( 'Computer', 'United States', 2000,1500),
( 'Calculator', 'United States', 2000,75);
-select product, country , year, sum(profit) from sales group by product, country, year with cube;
+select product, country , year, sum(profit) from t1 group by product, country, year with cube;
This version of MySQL doesn't yet support 'CUBE'
-explain select product, country , year, sum(profit) from sales group by product, country, year with cube;
+explain select product, country , year, sum(profit) from t1 group by product, country, year with cube;
This version of MySQL doesn't yet support 'CUBE'
-select product, country , year, sum(profit) from sales group by product, country, year with rollup;
+select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
This version of MySQL doesn't yet support 'ROLLUP'
-explain select product, country , year, sum(profit) from sales group by product, country, year with rollup;
+explain select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
This version of MySQL doesn't yet support 'ROLLUP'
-select product, country , year, sum(profit) from sales group by product, country, year with cube union all select product, country , year, sum(profit) from sales group by product, country, year with rollup;
+select product, country , year, sum(profit) from t1 group by product, country, year with cube union all select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
This version of MySQL doesn't yet support 'CUBE'
-drop table sales;
+drop table t1;
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 9238d9eafcb..d0d7a954c99 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -222,7 +222,6 @@ DateOfAction TransactionID
1999-07-27 834
1999-07-27 840
drop table t1,t2,t3;
-drop table if exists t1;
CREATE TABLE t1 (
member_id int(11) NOT NULL auto_increment,
inschrijf_datum varchar(20) NOT NULL default '',
@@ -263,14 +262,14 @@ drop table t1;
create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 20 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 20 NULL 2 Using where; Using index
select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
a b c
1 NULL b
explain select * from t1 where a >= 1 and a < 3 order by a desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 4 NULL 10 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 4 NULL 10 Using where; Using index
select * from t1 where a >= 1 and a < 3 order by a desc;
a b c
2 3 c
@@ -285,8 +284,8 @@ a b c
1 NULL b
1 NULL NULL
explain select * from t1 where a = 1 order by a desc, b desc;
-table type possible_keys key key_len ref rows Extra
-t1 ref a a 4 const 5 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 4 const 5 Using where; Using index
select * from t1 where a = 1 order by a desc, b desc;
a b c
1 3 b
@@ -296,34 +295,34 @@ a b c
1 NULL b
1 NULL NULL
explain select * from t1 where a = 1 and b is null order by a desc, b desc;
-table type possible_keys key key_len ref rows Extra
-t1 ref a a 9 const,const 2 Using where; Using index; Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 9 const,const 2 Using where; Using index; Using filesort
select * from t1 where a = 1 and b is null order by a desc, b desc;
a b c
1 NULL NULL
1 NULL b
explain select * from t1 where a >= 1 and a < 3 and b >0 order by a desc,b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 9 NULL 8 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 9 NULL 8 Using where; Using index
explain select * from t1 where a = 2 and b >0 order by a desc,b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 9 NULL 5 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
explain select * from t1 where a = 2 and b is null order by a desc,b desc;
-table type possible_keys key key_len ref rows Extra
-t1 ref a a 9 const,const 1 Using where; Using index; Using filesort
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 9 const,const 1 Using where; Using index; Using filesort
explain select * from t1 where a = 2 and (b is null or b > 0) order by a
desc,b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 9 NULL 6 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 9 NULL 6 Using where; Using index
explain select * from t1 where a = 2 and b > 0 order by a desc,b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 9 NULL 5 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
explain select * from t1 where a = 2 and b < 2 order by a desc,b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 9 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 9 NULL 2 Using where; Using index
explain select * from t1 where a = 1 order by b desc;
-table type possible_keys key key_len ref rows Extra
-t1 ref a a 4 const 5 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 4 const 5 Using where; Using index
select * from t1 where a = 1 order by b desc;
a b c
1 3 b
@@ -334,8 +333,8 @@ a b c
1 NULL NULL
alter table t1 modify b int not null, modify c varchar(10) not null;
explain select * from t1 order by a, b, c;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL a 18 NULL 11 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 18 NULL 11 Using index
select * from t1 order by a, b, c;
a b c
1 0
@@ -350,8 +349,8 @@ a b c
2 2 b
2 3 c
explain select * from t1 order by a desc, b desc, c desc;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL a 18 NULL 11 Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 18 NULL 11 Using index
select * from t1 order by a desc, b desc, c desc;
a b c
2 3 c
@@ -366,15 +365,15 @@ a b c
1 0 b
1 0
explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 18 NULL 3 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 18 NULL 3 Using where; Using index
select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
a b c
1 1 b
1 1 b
explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 4 NULL 6 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 4 NULL 6 Using where; Using index
select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
a b c
1 1 b
@@ -397,8 +396,8 @@ a b c
1 1 b
1 1
explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 8 NULL 10 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 8 NULL 10 Using where; Using index
select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
a b c
2 1 b
@@ -409,8 +408,8 @@ a b c
1 0 b
1 0
explain select * from t1 where a between 0 and 1 order by a desc, b desc;
-table type possible_keys key key_len ref rows Extra
-t1 range a a 4 NULL 5 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 4 NULL 5 Using where; Using index
select * from t1 where a between 0 and 1 order by a desc, b desc;
a b c
1 3 b
@@ -460,27 +459,27 @@ gid sid uid
104505 5 117
103853 5 250
EXPLAIN select t1.gid, t2.sid, t3.uid from t3, t2, t1 where t2.gid = t1.gid and t2.uid = t3.uid order by t1.gid, t3.uid;
-table type possible_keys key key_len ref rows Extra
-t1 index PRIMARY PRIMARY 4 NULL 6 Using index
-t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
-t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index
+1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t1.gid,t3.skr;
-table type possible_keys key key_len ref rows Extra
-t1 index PRIMARY PRIMARY 4 NULL 6 Using index
-t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
EXPLAIN SELECT t1.gid, t2.sid, t3.uid from t2, t1, t3 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid;
-table type possible_keys key key_len ref rows Extra
-t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
-t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
-t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
+1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t3.skr,t1.gid;
-table type possible_keys key key_len ref rows Extra
-t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
-t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
-t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 Using where
drop table t1,t2,t3;
CREATE TABLE t1 (
`titre` char(80) NOT NULL default '',
@@ -517,3 +516,37 @@ SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,des
titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest
test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug
drop table t1,t2;
+CREATE TABLE t1 (
+FieldKey varchar(36) NOT NULL default '',
+LongVal bigint(20) default NULL,
+StringVal mediumtext,
+KEY FieldKey (FieldKey),
+KEY LongField (FieldKey,LongVal),
+KEY StringField (FieldKey,StringVal(32))
+);
+INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
+EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 2 Using where
+SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
+FieldKey LongVal StringVal
+1 0 2
+1 1 3
+1 2 1
+EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 36 NULL 4 Using where; Using filesort
+SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
+FieldKey LongVal StringVal
+3 1 2
+3 2 1
+3 3 3
+EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range FieldKey,LongField,StringField LongField 36 NULL 4 Using where
+SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
+FieldKey LongVal StringVal
+3 1 2
+3 2 1
+3 3 3
+DROP TABLE t1;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 9d63050fc4e..7114c251e03 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -2,6 +2,7 @@ flush query cache;
flush query cache;
reset query cache;
flush status;
+drop database if exists mysqltest;
drop table if exists t1,t2,t3,t11,t21, mysqltest.t1;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
@@ -531,6 +532,7 @@ i
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
+update t1 set i=(select distinct 1 from (select * from t2) a);
drop table t1, t2, t3;
use mysql;
select * from db;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index a1d258455dc..86a93398a9f 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -15,8 +15,8 @@ event_date type event_id
1999-07-13 100600 26
1999-07-14 100600 10
explain select event_date,type,event_id from t1 WHERE type = 100601 and event_date >= "1999-07-01" AND event_date < "1999-07-15" AND (type=100600 OR type=100100) ORDER BY event_date;
-Comment
-Impossible WHERE
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select event_date,type,event_id from t1 WHERE event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND (type=100600 OR type=100100) or event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND type=100099;
event_date type event_id
1999-07-10 100100 24
@@ -193,7 +193,7 @@ INSERT INTO t1 (art) VALUES ('j'),('J'),('j'),('J'),('j'),('J'),('j'),('J'),('j'
('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j'),('j');
select count(*) from t1 where upper(art) = 'J';
count(*)
-602
+213
select count(*) from t1 where art = 'J' or art = 'j';
count(*)
602
diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result
index b2bb659502a..e422fbe49c1 100644
--- a/mysql-test/r/rename.result
+++ b/mysql-test/r/rename.result
@@ -37,3 +37,5 @@ select * from t3;
3 table 3
3 table 3
drop table if exists t1,t2,t3,t4;
+Warnings:
+Note 1051 Unknown table 't4'
diff --git a/mysql-test/r/replace.result b/mysql-test/r/replace.result
index 0aa80e18ccc..4a71428b2f4 100644
--- a/mysql-test/r/replace.result
+++ b/mysql-test/r/replace.result
@@ -12,15 +12,17 @@ replace into t1 (gesuchnr,benutzer_id) values (1,1);
alter table t1 type=heap;
replace into t1 (gesuchnr,benutzer_id) values (1,1);
drop table t1;
-create table t1 (a tinyint not null auto_increment primary key, b char(20));
-insert into t1 values (126,"first"),(0,"last");
+create table t1 (a tinyint not null auto_increment primary key, b char(20) default "default_value");
+insert into t1 values (126,"first"),(63, "middle"),(0,"last");
insert into t1 values (0,"error");
Duplicate entry '127' for key 1
replace into t1 values (0,"error");
Duplicate entry '127' for key 1
replace into t1 values (126,"first updated");
+replace into t1 values (63,default);
select * from t1;
a b
126 first updated
+63 default_value
127 last
drop table t1;
diff --git a/mysql-test/r/rollback.result b/mysql-test/r/rollback.result
index a5eb6f8729f..d87aa68dce4 100644
--- a/mysql-test/r/rollback.result
+++ b/mysql-test/r/rollback.result
@@ -4,9 +4,26 @@ begin work;
insert into t1 values (4);
insert into t1 values (5);
rollback;
-Warning: Some non-transactional changed tables couldn't be rolled back
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+select @@warning_count;
+@@warning_count
+1
+select @@error_count;
+@@error_count
+0
+show warnings;
+Level Code Message
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+show errors;
+Level Code Message
select * from t1;
n
4
5
+select @@warning_count;
+@@warning_count
+0
+show warnings;
+Level Code Message
drop table t1;
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result
new file mode 100644
index 00000000000..40beeb4d3a5
--- /dev/null
+++ b/mysql-test/r/row.result
@@ -0,0 +1,161 @@
+drop table if exists t1;
+select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3));
+(1,2,3) IN ((3,2,3), (1,2,3), (1,3,3))
+1
+select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
+0
+select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
+1
+select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
+0
+select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
+row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'))
+1
+select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
+row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3))
+1
+select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
+row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3))
+1
+select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
+1
+select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
+0
+select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
+row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3))
+NULL
+select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
+row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3))
+0
+select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)));
+(1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)))
+1
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
+Cardinality error (more/less than 2 columns)
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
+row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)))
+NULL
+SELECT (1,2,3)=(0,NULL,3);
+(1,2,3)=(0,NULL,3)
+0
+SELECT (1,2,3)=(1,NULL,3);
+(1,2,3)=(1,NULL,3)
+NULL
+SELECT (1,2,3)=(1,NULL,0);
+(1,2,3)=(1,NULL,0)
+NULL
+SELECT ROW(1,2,3)=ROW(1,2,3);
+ROW(1,2,3)=ROW(1,2,3)
+1
+SELECT ROW(2,2,3)=ROW(1+1,2,3);
+ROW(2,2,3)=ROW(1+1,2,3)
+1
+SELECT ROW(1,2,3)=ROW(1+1,2,3);
+ROW(1,2,3)=ROW(1+1,2,3)
+0
+SELECT ROW(1,2,3)<ROW(1+1,2,3);
+ROW(1,2,3)<ROW(1+1,2,3)
+1
+SELECT ROW(1,2,3)>ROW(1+1,2,3);
+ROW(1,2,3)>ROW(1+1,2,3)
+0
+SELECT ROW(1,2,3)<=ROW(1+1,2,3);
+ROW(1,2,3)<=ROW(1+1,2,3)
+1
+SELECT ROW(1,2,3)>=ROW(1+1,2,3);
+ROW(1,2,3)>=ROW(1+1,2,3)
+0
+SELECT ROW(1,2,3)<>ROW(1+1,2,3);
+ROW(1,2,3)<>ROW(1+1,2,3)
+1
+SELECT ROW(NULL,2,3)=ROW(NULL,2,3);
+ROW(NULL,2,3)=ROW(NULL,2,3)
+NULL
+SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3);
+ROW(NULL,2,3)<=>ROW(NULL,2,3)
+1
+SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
+ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5))
+1
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
+ROW('test',2,3.33)=ROW('test',2,3.33)
+1
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
+Cardinality error (more/less than 3 columns)
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
+ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33))
+1
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3));
+ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3))
+0
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
+ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL))
+NULL
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
+Cardinality error (more/less than 2 columns)
+create table t1 ( a int, b int, c int);
+insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
+select * from t1 where ROW(1,2,3)=ROW(a,b,c);
+a b c
+1 2 3
+select * from t1 where ROW(0,2,3)=ROW(a,b,c);
+a b c
+select * from t1 where ROW(1,2,3)<ROW(a,b,c);
+a b c
+2 3 1
+3 2 1
+select ROW(a,2,3) IN(row(1,b,c), row(2,3,1)) from t1;
+ROW(a,2,3) IN(row(1,b,c), row(2,3,1))
+1
+0
+0
+NULL
+select ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) from t1;
+ROW(c,2,3) IN(row(1,b,a), row(2,3,1))
+0
+0
+1
+NULL
+select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1;
+ROW(a,b,c) IN(row(1,2,3), row(3,2,1))
+1
+0
+1
+NULL
+select ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) from t1;
+ROW(1,2,3) IN(row(a,b,c), row(1,2,3))
+1
+1
+1
+1
+drop table t1;
+select ROW(1,1);
+Cardinality error (more/less than 1 columns)
+create table t1 (i int);
+select 1 from t1 where ROW(1,1);
+Cardinality error (more/less than 1 columns)
+select count(*) from t1 order by ROW(1,1);
+Cardinality error (more/less than 1 columns)
+select count(*) from t1 having (1,1) order by i;
+Cardinality error (more/less than 1 columns)
+drop table t1;
+create table t1 (a int, b int);
+insert into t1 values (1, 4);
+insert into t1 values (10, 40);
+insert into t1 values (1, 4);
+insert into t1 values (10, 43);
+insert into t1 values (1, 4);
+insert into t1 values (10, 41);
+insert into t1 values (1, 4);
+insert into t1 values (10, 43);
+insert into t1 values (1, 4);
+select a, MAX(b), (1, MAX(b)) = (1, 4) from t1 group by a;
+a MAX(b) (1, MAX(b)) = (1, 4)
+1 4 1
+10 43 0
+drop table t1;
diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result
index 2dc21e86152..dd569944f0e 100644
--- a/mysql-test/r/rpl000001.result
+++ b/mysql-test/r/rpl000001.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1,t2,t3;
+start slave;
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
load data local infile 'MYSQL_TEST_DIR/std_data/words.dat' into table t1;
@@ -30,9 +29,9 @@ abandoned
abandoning
abandonment
abandons
-slave stop;
+stop slave;
set password for root@"localhost" = password('foo');
-slave start;
+start slave;
set password for root@"localhost" = password('');
create table t3(n int);
insert into t3 values(1),(2);
@@ -45,13 +44,13 @@ sum(length(word))
141
drop table t1,t3;
reset master;
-slave stop;
+stop slave;
reset slave;
create table t1(n int);
select get_lock("hold_slave",10);
get_lock("hold_slave",10)
1
-slave start;
+start slave;
select release_lock("hold_slave");
release_lock("hold_slave")
1
@@ -68,7 +67,7 @@ kill @id;
drop table t2;
Server shutdown in progress
set global sql_slave_skip_counter=1;
-slave start;
+start slave;
select count(*) from t1;
count(*)
5000
diff --git a/mysql-test/r/rpl000002.result b/mysql-test/r/rpl000002.result
index 4c2b3bdfde6..56e34b4874f 100644
--- a/mysql-test/r/rpl000002.result
+++ b/mysql-test/r/rpl000002.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
+start slave;
create table t1 (n int auto_increment primary key);
set insert_id = 2000;
insert into t1 values (NULL),(NULL),(NULL);
@@ -17,15 +16,14 @@ show slave hosts;
Server_id Host Port Rpl_recovery_rank Master_id
2 127.0.0.1 9999 2 1
drop table t1;
-slave stop;
-drop table if exists t2;
+stop slave;
create table t2(id int auto_increment primary key, created datetime);
set timestamp=12345;
insert into t2 set created=now();
select * from t2;
id created
1 1970-01-01 06:25:45
-slave start;
+start slave;
select * from t2;
id created
1 1970-01-01 06:25:45
diff --git a/mysql-test/r/rpl000003.result b/mysql-test/r/rpl000003.result
deleted file mode 100644
index b123b3d98c5..00000000000
--- a/mysql-test/r/rpl000003.result
+++ /dev/null
@@ -1,17 +0,0 @@
-slave stop;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
-create table t1(n int primary key);
-insert into t1 values (1),(2),(2);
-Duplicate entry '2' for key 1
-insert into t1 values (3);
-select * from t1;
-n
-1
-2
-3
-drop table t1;
diff --git a/mysql-test/r/rpl000004.result b/mysql-test/r/rpl000004.result
index 82b208d0b58..067696345e4 100644
--- a/mysql-test/r/rpl000004.result
+++ b/mysql-test/r/rpl000004.result
@@ -1,22 +1,17 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
set SQL_LOG_BIN=0;
-drop table if exists t1;
create table t1 (word char(20) not null, index(word));
load data infile '../../std_data/words.dat' into table t1;
-drop table if exists t2;
create table t2 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t2;
create table t3 (word char(20) not null primary key);
-drop table if exists t1;
load table t1 from master;
-drop table if exists t2;
load table t2 from master;
-drop table if exists t3;
load table t3 from master;
check table t1;
Table Op Msg_type Msg_text
diff --git a/mysql-test/r/rpl000005.result b/mysql-test/r/rpl000005.result
index 3e9028bf2cf..0202e43dcb2 100644
--- a/mysql-test/r/rpl000005.result
+++ b/mysql-test/r/rpl000005.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
+start slave;
CREATE TABLE t1 (name varchar(64), age smallint(3));
INSERT INTO t1 SET name='Andy', age=31;
INSERT t1 SET name='Jacob', age=2;
diff --git a/mysql-test/r/rpl000006.result b/mysql-test/r/rpl000006.result
index e7fc5151ac4..7209ec3c3d1 100644
--- a/mysql-test/r/rpl000006.result
+++ b/mysql-test/r/rpl000006.result
@@ -1,17 +1,15 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
set SQL_LOG_BIN=0,timestamp=200006;
-drop table if exists t1;
create table t1(t timestamp not null,a char(1));
insert into t1 ( a) values ('F');
select unix_timestamp(t) from t1;
unix_timestamp(t)
200006
-drop table if exists t1;
load table t1 from master;
select unix_timestamp(t) from t1;
unix_timestamp(t)
diff --git a/mysql-test/r/rpl000008.result b/mysql-test/r/rpl000008.result
index a0230d55702..a88a3c690ed 100644
--- a/mysql-test/r/rpl000008.result
+++ b/mysql-test/r/rpl000008.result
@@ -1,25 +1,23 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
use test;
-drop table if exists foo;
-create table foo (n int);
-insert into foo values(4);
+drop table if exists mysqltest_foo;
+drop table if exists mysqltest_bar;
+create table mysqltest_foo (n int);
+insert into mysqltest_foo values(4);
use test;
-drop table if exists foo;
-create table foo (n int);
-insert into foo values(5);
-drop table if exists bar;
-create table bar (m int);
-insert into bar values(15);
-drop table if exists choo;
-create table choo (k int);
-insert into choo values(55);
-select foo.n,bar.m,choo.k from foo,bar,choo;
+create table mysqltest_foo (n int);
+insert into mysqltest_foo values(5);
+create table mysqltest_bar (m int);
+insert into mysqltest_bar values(15);
+create table t1 (k int);
+insert into t1 values(55);
+select mysqltest_foo.n,mysqltest_bar.m,t1.k from mysqltest_foo,mysqltest_bar,t1;
n m k
4 15 55
-drop table if exists foo,bar,choo;
-drop table if exists foo,bar,choo;
+drop table mysqltest_foo,mysqltest_bar,t1;
+drop table mysqltest_foo,mysqltest_bar,t1;
diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result
index 002f6843953..06f34842577 100644
--- a/mysql-test/r/rpl000009.result
+++ b/mysql-test/r/rpl000009.result
@@ -1,85 +1,85 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop database if exists foo;
-create database foo;
-drop database if exists bar;
-create database bar;
-create database foo;
-drop table if exists foo.foo;
-create table foo.foo (n int);
-insert into foo.foo values(4);
-drop table if exists foo.foo;
-create table foo.foo (n int);
-insert into foo.foo values(5);
-drop table if exists bar.bar;
-create table bar.bar (m int);
-insert into bar.bar values(15);
-select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
+start slave;
+drop database if exists mysqltest2;
+create database mysqltest2;
+drop database if exists mysqltest;
+create database mysqltest;
+create database mysqltest2;
+create table mysqltest2.foo (n int);
+insert into mysqltest2.foo values(4);
+create table mysqltest2.foo (n int);
+insert into mysqltest2.foo values(5);
+create table mysqltest.bar (m int);
+insert into mysqltest.bar values(15);
+select mysqltest2.foo.n,mysqltest.bar.m from mysqltest2.foo,mysqltest.bar;
n m
4 15
-drop database bar;
-drop database if exists foo;
-drop database bar;
-Can't drop database 'bar'. Database doesn't exist
-drop database foo;
+drop database mysqltest;
+drop database if exists mysqltest2;
+drop database mysqltest;
+Can't drop database 'mysqltest'. Database doesn't exist
+drop database mysqltest2;
set sql_log_bin = 0;
-create database foo;
-create database bar;
+create database mysqltest2;
+create database mysqltest;
show databases;
Database
-bar
-foo
mysql
+mysqltest
+mysqltest2
test
-create table foo.t1(n int, s char(20));
-create table foo.t2(n int, s text);
-insert into foo.t1 values (1, 'one'), (2, 'two'), (3, 'three');
-insert into foo.t2 values (11, 'eleven'), (12, 'twelve'), (13, 'thirteen');
-create table bar.t1(n int, s char(20));
-create table bar.t2(n int, s text);
-insert into bar.t1 values (1, 'one bar'), (2, 'two bar'), (3, 'three bar');
-insert into bar.t2 values (11, 'eleven bar'), (12, 'twelve bar'),
-(13, 'thirteen bar');
+create table mysqltest2.t1(n int, s char(20));
+create table mysqltest2.t2(n int, s text);
+insert into mysqltest2.t1 values (1, 'one'), (2, 'two'), (3, 'three');
+insert into mysqltest2.t2 values (11, 'eleven'), (12, 'twelve'), (13, 'thirteen');
+create table mysqltest.t1(n int, s char(20));
+create table mysqltest.t2(n int, s text);
+insert into mysqltest.t1 values (1, 'one test'), (2, 'two test'), (3, 'three test');
+insert into mysqltest.t2 values (11, 'eleven test'), (12, 'twelve test'),
+(13, 'thirteen test');
set sql_log_bin = 1;
show databases;
Database
mysql
test
load data from master;
+Warnings:
+Note 1008 Can't drop database 'mysqltest'. Database doesn't exist
+Note 1008 Can't drop database 'mysqltest2'. Database doesn't exist
show databases;
Database
-bar
-foo
mysql
+mysqltest
+mysqltest2
test
-use foo;
+use mysqltest2;
show tables;
-Tables_in_foo
-use bar;
+Tables_in_mysqltest2
+use mysqltest;
show tables;
-Tables_in_bar
+Tables_in_mysqltest
t1
t2
-select * from bar.t1;
+select * from mysqltest.t1;
n s
-1 one bar
-2 two bar
-3 three bar
-select * from bar.t2;
+1 one test
+2 two test
+3 three test
+select * from mysqltest.t2;
n s
-11 eleven bar
-12 twelve bar
-13 thirteen bar
-insert into bar.t1 values (4, 'four bar');
-select * from bar.t1;
+11 eleven test
+12 twelve test
+13 thirteen test
+insert into mysqltest.t1 values (4, 'four test');
+select * from mysqltest.t1;
n s
-1 one bar
-2 two bar
-3 three bar
-4 four bar
-drop database bar;
-drop database foo;
+1 one test
+2 two test
+3 three test
+4 four test
+drop database mysqltest;
+drop database mysqltest2;
diff --git a/mysql-test/r/rpl000010.result b/mysql-test/r/rpl000010.result
index 49538ed148e..65191ea411f 100644
--- a/mysql-test/r/rpl000010.result
+++ b/mysql-test/r/rpl000010.result
@@ -1,11 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
-drop table if exists t1;
+start slave;
create table t1 (n int not null auto_increment primary key);
insert into t1 values(NULL);
insert into t1 values(2);
diff --git a/mysql-test/r/rpl000011.result b/mysql-test/r/rpl000011.result
index 5d22c29bdba..dd0fa2fbe74 100644
--- a/mysql-test/r/rpl000011.result
+++ b/mysql-test/r/rpl000011.result
@@ -1,14 +1,13 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
+start slave;
create table t1 (n int);
insert into t1 values(1);
-slave stop;
-slave start;
+stop slave;
+start slave;
insert into t1 values(2);
select * from t1;
n
diff --git a/mysql-test/r/rpl000012.result b/mysql-test/r/rpl000012.result
index 45de6502bbd..17fb53010ab 100644
--- a/mysql-test/r/rpl000012.result
+++ b/mysql-test/r/rpl000012.result
@@ -1,21 +1,19 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1,t2,t3;
+start slave;
create table t2 (n int);
create temporary table t1 (n int);
insert into t1 values(1),(2),(3);
insert into t2 select * from t1;
-drop table if exists test.t3;
-create temporary table test.t3 (n int not null);
-alter table test.t3 add primary key(n);
+create temporary table t3 (n int not null);
+alter table t3 add primary key(n);
flush logs;
insert into t3 values (100);
insert into t2 select * from t3;
-drop table if exists test.t3;
+drop table if exists t3;
insert into t2 values (101);
create temporary table t1 (n int);
insert into t1 values (4),(5);
@@ -35,3 +33,5 @@ show status like 'Slave_open_temp_tables';
Variable_name Value
Slave_open_temp_tables 0
drop table if exists t1,t2;
+Warnings:
+Note 1051 Unknown table 't1'
diff --git a/mysql-test/r/rpl000013.result b/mysql-test/r/rpl000013.result
index 9e802da59c5..37838bb88e0 100644
--- a/mysql-test/r/rpl000013.result
+++ b/mysql-test/r/rpl000013.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t2;
+start slave;
create table t2(n int);
create temporary table t1 (n int);
insert into t1 values(1),(2),(3);
@@ -25,3 +24,5 @@ show status like 'Slave_open_temp_tables';
Variable_name Value
Slave_open_temp_tables 0
drop table if exists t1,t2;
+Warnings:
+Note 1051 Unknown table 't1'
diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result
index 7010349e5ff..349365e17ad 100644
--- a/mysql-test/r/rpl000015.result
+++ b/mysql-test/r/rpl000015.result
@@ -1,23 +1,23 @@
reset master;
show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.001 79
+master-bin.000001 79
reset slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
change master to master_host='127.0.0.1';
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.001 4 No No 0 0 0 4
+127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4
change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=MASTER_PORT;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.001 4 No No 0 0 0 4
-slave start;
+127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4
+start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 7 master-bin.001 79 slave-relay-bin.001 120 master-bin.001 Yes Yes 0 0 79 120
+127.0.0.1 root MASTER_PORT 7 master-bin.000001 79 slave-relay-bin.000001 123 master-bin.000001 Yes Yes 0 0 79 123
drop table if exists t1;
create table t1 (n int);
insert into t1 values (10),(45),(90);
diff --git a/mysql-test/r/rpl000017.result b/mysql-test/r/rpl000017.result
index bac0573165d..64e13042e9c 100644
--- a/mysql-test/r/rpl000017.result
+++ b/mysql-test/r/rpl000017.result
@@ -1,7 +1,7 @@
reset master;
grant replication slave on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
grant replication slave on *.* to replicate@127.0.0.1 identified by 'aaaaaaaaaaaaaaab';
-slave start;
+start slave;
drop table if exists t1;
create table t1(n int);
insert into t1 values(24);
diff --git a/mysql-test/r/rpl000018.result b/mysql-test/r/rpl000018.result
index ba51406bba0..7211d440524 100644
--- a/mysql-test/r/rpl000018.result
+++ b/mysql-test/r/rpl000018.result
@@ -1,9 +1,9 @@
reset slave;
-slave start;
-show master logs;
+start slave;
+show binary logs;
Log_name
-master-bin.001
-master-bin.002
+master-bin.000001
+master-bin.000002
drop table if exists t1;
create table t1(n int);
insert into t1 values (3351);
diff --git a/mysql-test/r/rpl_alter.result b/mysql-test/r/rpl_alter.result
index 1dc73c6524a..e7abc3b3b48 100644
--- a/mysql-test/r/rpl_alter.result
+++ b/mysql-test/r/rpl_alter.result
@@ -1,21 +1,21 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop database if exists d1;
-create database d1;
-create table d1.t1 ( n int);
-alter table d1.t1 add m int;
-insert into d1.t1 values (1,2);
-create table d1.t2 (n int);
-insert into d1.t2 values (45);
-rename table d1.t2 to d1.t3, d1.t1 to d1.t2;
-select * from d1.t2;
+start slave;
+drop database if exists test_$1;
+create database test_$1;
+create table test_$1.t1 ( n int);
+alter table test_$1.t1 add m int;
+insert into test_$1.t1 values (1,2);
+create table test_$1.t2 (n int);
+insert into test_$1.t2 values (45);
+rename table test_$1.t2 to test_$1.t3, test_$1.t1 to test_$1.t2;
+select * from test_$1.t2;
n m
1 2
-select * from d1.t3;
+select * from test_$1.t3;
n
45
-drop database d1;
+drop database test_$1;
diff --git a/mysql-test/r/rpl_empty_master_crash.result b/mysql-test/r/rpl_empty_master_crash.result
index 19e2bf28dcd..8818029ab99 100644
--- a/mysql-test/r/rpl_empty_master_crash.result
+++ b/mysql-test/r/rpl_empty_master_crash.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
+start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
load table t1 from master;
diff --git a/mysql-test/r/rpl_failsafe.result b/mysql-test/r/rpl_failsafe.result
index 7e8aeea64f7..956555f9318 100644
--- a/mysql-test/r/rpl_failsafe.result
+++ b/mysql-test/r/rpl_failsafe.result
@@ -1,9 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
show variables like 'rpl_recovery_rank';
Variable_name Value
rpl_recovery_rank 1
@@ -18,14 +18,14 @@ rpl_recovery_rank 2
show status like 'Rpl_status';
Variable_name Value
Rpl_status ACTIVE_SLAVE
-slave start;
+start slave;
show variables like 'rpl_recovery_rank';
Variable_name Value
rpl_recovery_rank 3
show status like 'Rpl_status';
Variable_name Value
Rpl_status ACTIVE_SLAVE
-slave start;
+start slave;
show variables like 'rpl_recovery_rank';
Variable_name Value
rpl_recovery_rank 4
diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result
index da2930f30c3..98d661e9af2 100644
--- a/mysql-test/r/rpl_flush_log_loop.result
+++ b/mysql-test/r/rpl_flush_log_loop.result
@@ -1,17 +1,17 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=MASTER_PORT;
-slave start;
-slave stop;
+start slave;
+stop slave;
change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=SLAVE_PORT;
-slave start;
+start slave;
flush logs;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root SLAVE_PORT 60 slave-bin.001 79 relay-log.001 119 slave-bin.001 Yes Yes 0 0 79 119
+127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 79 relay-log.000001 122 slave-bin.000001 Yes Yes 0 0 79 122
diff --git a/mysql-test/r/rpl_get_lock.result b/mysql-test/r/rpl_get_lock.result
index a8e602be03f..369fde7ef8f 100644
--- a/mysql-test/r/rpl_get_lock.result
+++ b/mysql-test/r/rpl_get_lock.result
@@ -1,9 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
create table t1(n int);
insert into t1 values(get_lock("lock",2));
select get_lock("lock",2);
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index d524818985e..82015bdf538 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
+start slave;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
insert into t1 values (1),(2),(3);
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result
index 27f3d185f63..8735cae47d5 100644
--- a/mysql-test/r/rpl_loaddata.result
+++ b/mysql-test/r/rpl_loaddata.result
@@ -1,9 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
create table t1(a int not null auto_increment, b int, primary key(a) );
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
select * from t1;
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index 835b5d6629a..ed54eb75f4b 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -1,10 +1,10 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-slave stop;
+start slave;
+stop slave;
reset master;
reset slave;
reset master;
@@ -16,77 +16,77 @@ load data infile '../../std_data/words.dat' into table t1;
drop table t1;
show binlog events;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
-master-bin.001 172 Intvar 1 172 INSERT_ID=1
-master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
-master-bin.001 263 Query 1 263 use test; drop table t1
-master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
-master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
-master-bin.001 556 Exec_load 1 556 ;file_id=1
-master-bin.001 579 Query 1 579 use test; drop table t1
+master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 172 Intvar 1 172 INSERT_ID=1
+master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
+master-bin.000001 263 Query 1 263 use `test`; drop table t1
+master-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
+master-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
+master-bin.000001 556 Exec_load 1 556 ;file_id=1
+master-bin.000001 579 Query 1 579 use `test`; drop table t1
show binlog events from 79 limit 1;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
show binlog events from 79 limit 2;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
-master-bin.001 172 Intvar 1 172 INSERT_ID=1
+master-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 172 Intvar 1 172 INSERT_ID=1
show binlog events from 79 limit 2,1;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
+master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
flush logs;
-slave start;
+start slave;
flush logs;
-slave stop;
+stop slave;
create table t1 (n int);
insert into t1 values (1);
drop table t1;
show binlog events;
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
-master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
-master-bin.001 172 Intvar 1 172 INSERT_ID=1
-master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
-master-bin.001 263 Query 1 263 use test; drop table t1
-master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
-master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
-master-bin.001 556 Exec_load 1 556 ;file_id=1
-master-bin.001 579 Query 1 579 use test; drop table t1
-master-bin.001 627 Rotate 1 627 master-bin.002;pos=4
-show binlog events in 'master-bin.002';
+master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 172 Intvar 1 172 INSERT_ID=1
+master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
+master-bin.000001 263 Query 1 263 use `test`; drop table t1
+master-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
+master-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
+master-bin.000001 556 Exec_load 1 556 ;file_id=1
+master-bin.000001 579 Query 1 579 use `test`; drop table t1
+master-bin.000001 627 Rotate 1 627 master-bin.000002;pos=4
+show binlog events in 'master-bin.000002';
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.002 4 Query 1 4 use test; create table t1 (n int)
-master-bin.002 62 Query 1 62 use test; insert into t1 values (1)
-master-bin.002 122 Query 1 122 use test; drop table t1
-show master logs;
+master-bin.000002 4 Query 1 4 use `test`; create table t1 (n int)
+master-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1)
+master-bin.000002 122 Query 1 122 use `test`; drop table t1
+show binary logs;
Log_name
-master-bin.001
-master-bin.002
-slave start;
-show master logs;
+master-bin.000001
+master-bin.000002
+start slave;
+show binary logs;
Log_name
-slave-bin.001
-slave-bin.002
-show binlog events in 'slave-bin.001' from 4;
+slave-bin.000001
+slave-bin.000002
+show binlog events in 'slave-bin.000001' from 4;
Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.001 4 Start 2 4 Server ver: VERSION, Binlog ver: 3
-slave-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
-slave-bin.001 172 Intvar 1 172 INSERT_ID=1
-slave-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
-slave-bin.001 263 Query 1 263 use test; drop table t1
-slave-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
-slave-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
-slave-bin.001 565 Exec_load 1 556 ;file_id=1
-slave-bin.001 588 Query 1 579 use test; drop table t1
-slave-bin.001 636 Rotate 2 636 slave-bin.002;pos=4
-show binlog events in 'slave-bin.002' from 4;
+slave-bin.000001 4 Start 2 4 Server ver: VERSION, Binlog ver: 3
+slave-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
+slave-bin.000001 172 Intvar 1 172 INSERT_ID=1
+slave-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
+slave-bin.000001 263 Query 1 263 use `test`; drop table t1
+slave-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
+slave-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
+slave-bin.000001 565 Exec_load 1 556 ;file_id=1
+slave-bin.000001 588 Query 1 579 use `test`; drop table t1
+slave-bin.000001 636 Rotate 2 636 slave-bin.000002;pos=4
+show binlog events in 'slave-bin.000002' from 4;
Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.002 4 Query 1 4 use test; create table t1 (n int)
-slave-bin.002 62 Query 1 62 use test; insert into t1 values (1)
-slave-bin.002 122 Query 1 122 use test; drop table t1
+slave-bin.000002 4 Query 1 4 use `test`; create table t1 (n int)
+slave-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1)
+slave-bin.000002 122 Query 1 122 use `test`; drop table t1
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.002 170 slave-relay-bin.002 957 master-bin.002 Yes Yes 0 0 170 961
-show binlog events in 'slave-bin.005' from 4;
+127.0.0.1 root MASTER_PORT 1 master-bin.000002 170 slave-relay-bin.000002 969 master-bin.000002 Yes Yes 0 0 170 973
+show binlog events in 'slave-bin.000005' from 4;
Error when executing command SHOW BINLOG EVENTS: Could not find target log
diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result
index e76b565813f..fa38e42ae73 100644
--- a/mysql-test/r/rpl_log_pos.result
+++ b/mysql-test/r/rpl_log_pos.result
@@ -1,43 +1,43 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.001 79
+master-bin.000001 79
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.001 79 slave-relay-bin.002 120 master-bin.001 Yes Yes 0 0 79 124
-slave stop;
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 127
+stop slave;
change master to master_log_pos=73;
-slave start;
-slave stop;
+start slave;
+stop slave;
change master to master_log_pos=73;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 4 master-bin.001 No No 0 0 73 4
-slave start;
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 73 4
+start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 4 master-bin.001 No Yes 0 0 73 4
-slave stop;
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 73 4
+stop slave;
change master to master_log_pos=173;
-slave start;
+start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.001 173 slave-relay-bin.001 4 master-bin.001 No Yes 0 0 173 4
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 173 4
show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.001 79
+master-bin.000001 79
create table if not exists t1 (n int);
drop table if exists t1;
create table t1 (n int);
insert into t1 values (1),(2),(3);
-slave stop;
+stop slave;
change master to master_log_pos=79;
-slave start;
+start slave;
select * from t1;
n
1
diff --git a/mysql-test/r/rpl_master_pos_wait.result b/mysql-test/r/rpl_master_pos_wait.result
index 22c7aef621c..801ffad6975 100644
--- a/mysql-test/r/rpl_master_pos_wait.result
+++ b/mysql-test/r/rpl_master_pos_wait.result
@@ -1,9 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
select master_pos_wait('master-bin.999999',0,10);
master_pos_wait('master-bin.999999',0,10)
-1
diff --git a/mysql-test/r/rpl_mystery22.result b/mysql-test/r/rpl_mystery22.result
index 5dd665fe9d5..348b3211cd5 100644
--- a/mysql-test/r/rpl_mystery22.result
+++ b/mysql-test/r/rpl_mystery22.result
@@ -1,20 +1,20 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
create table t1(n int auto_increment primary key);
insert into t1 values (2);
insert into t1 values(NULL);
insert into t1 values(NULL);
delete from t1 where n = 2;
-slave start;
-slave stop;
+start slave;
+stop slave;
create table t2(n int);
drop table t2;
insert into t1 values(NULL);
-slave start;
+start slave;
select * from t1;
n
1
diff --git a/mysql-test/r/rpl_redirect.result b/mysql-test/r/rpl_redirect.result
index 6103a075684..3807479fb54 100644
--- a/mysql-test/r/rpl_redirect.result
+++ b/mysql-test/r/rpl_redirect.result
@@ -1,15 +1,14 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
SHOW SLAVE STATUS;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
SHOW SLAVE HOSTS;
Server_id Host Port Rpl_recovery_rank Master_id
2 127.0.0.1 SLAVE_PORT 2 1
-drop table if exists t1;
create table t1 ( n int);
insert into t1 values (1),(2),(3),(4);
insert into t1 values(5);
diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result
index 372d8c07f64..9ae292c2709 100644
--- a/mysql-test/r/rpl_replicate_do.result
+++ b/mysql-test/r/rpl_replicate_do.result
@@ -1,9 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
drop table if exists t11;
drop table if exists t11;
create table t2 (n int);
@@ -25,4 +25,4 @@ n
4
select * from t11;
Table 'test.t11' doesn't exist
-drop table if exists t1,t2,t3,t11;
+drop table if exists t1,t2,t11;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 741c53fe52b..5275ef26b5c 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,36 +1,35 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
-slave start;
+start slave;
Could not initialize master info structure, check permisions on master.info
-slave start;
+start slave;
Could not initialize master info structure, check permisions on master.info
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
Could not initialize master info
reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
reset master;
-slave start;
+start slave;
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables");
create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.001 417 slave-relay-bin.001 458 master-bin.001 Yes Yes 0 0 417 458
+127.0.0.1 root MASTER_PORT 60 master-bin.000001 417 slave-relay-bin.000001 461 master-bin.000001 Yes Yes 0 0 417 461
select * from t1;
s
Could not break slave
Tried hard
flush logs;
-drop table if exists t2;
create table t2(m int not null auto_increment primary key);
insert into t2 values (34),(67),(123);
flush logs;
-show master logs;
+show binary logs;
Log_name
-master-bin.001
-master-bin.002
-master-bin.003
+master-bin.000001
+master-bin.000002
+master-bin.000003
create table t3 select * from temp_table;
select * from t3;
a
@@ -40,15 +39,15 @@ insert into t2 values(1234);
set insert_id=1234;
insert into t2 values(NULL);
set global sql_slave_skip_counter=1;
-slave start;
-purge master logs to 'master-bin.003';
-show master logs;
+start slave;
+purge master logs to 'master-bin.000003';
+show binary logs;
Log_name
-master-bin.003
+master-bin.000003
insert into t2 values (65);
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.003 290 slave-relay-bin.001 1073 master-bin.003 Yes Yes 0 0 290 1073
+127.0.0.1 root MASTER_PORT 60 master-bin.000003 290 slave-relay-bin.000001 1088 master-bin.000003 Yes Yes 0 0 290 1088
select * from t2;
m
34
@@ -58,24 +57,23 @@ m
1234
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables part 2");
-drop table if exists t3;
create table t3 (n int);
create table t4 select * from temp_table;
-show master logs;
+show binary logs;
Log_name
-master-bin.003
-master-bin.004
-master-bin.005
-master-bin.006
+master-bin.000003
+master-bin.000004
+master-bin.000005
+master-bin.000006
show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.006 838
+master-bin.000006 838
select * from t4;
a
testing temporary tables part 2
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.006 838 slave-relay-bin.001 8034 master-bin.006 Yes Yes 0 0 838 8034
+127.0.0.1 root MASTER_PORT 60 master-bin.000006 838 slave-relay-bin.000001 8067 master-bin.000006 Yes Yes 0 0 838 8067
lock tables t3 read;
select count(*) from t3 where n >= 4;
count(*)
diff --git a/mysql-test/r/rpl_skip_error.result b/mysql-test/r/rpl_skip_error.result
index 946d64ad7c5..e52426c381c 100644
--- a/mysql-test/r/rpl_skip_error.result
+++ b/mysql-test/r/rpl_skip_error.result
@@ -1,10 +1,9 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-drop table if exists t1;
+start slave;
create table t1 (n int not null primary key);
insert into t1 values (1);
insert into t1 values (1);
diff --git a/mysql-test/r/rpl_sporadic_master.result b/mysql-test/r/rpl_sporadic_master.result
index a6a58515f0a..789c3bf2b2b 100644
--- a/mysql-test/r/rpl_sporadic_master.result
+++ b/mysql-test/r/rpl_sporadic_master.result
@@ -1,16 +1,16 @@
-slave stop;
+stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
+start slave;
create table t2(n int);
create table t1(n int not null auto_increment primary key);
insert into t1 values (NULL),(NULL);
truncate table t1;
insert into t1 values (4),(NULL);
-slave stop;
-slave start;
+stop slave;
+start slave;
insert into t1 values (NULL),(NULL);
flush logs;
truncate table t1;
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
new file mode 100644
index 00000000000..c3243d3a227
--- /dev/null
+++ b/mysql-test/r/rpl_temporary.result
@@ -0,0 +1,73 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop table if exists t1,t2;
+create table t1(f int);
+create table t2(f int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+create temporary table t3(f int);
+insert into t3 select * from t1 where f<6;
+create temporary table t3(f int);
+insert into t2 select count(*) from t3;
+insert into t3 select * from t1 where f>=4;
+drop temporary table t3;
+insert into t2 select count(*) from t3;
+drop temporary table t3;
+select * from t2;
+f
+5
+7
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.000001 79 Query 1 79 use `test`; create table t1(f int)
+master-bin.000001 136 Query 1 136 use `test`; create table t2(f int)
+master-bin.000001 193 Query 1 193 use `test`; insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
+master-bin.000001 290 Query 1 290 use `test`; create temporary table t3(f int)
+master-bin.000001 357 Query 1 357 use `test`; insert into t3 select * from t1 where f<6
+master-bin.000001 433 Query 1 433 use `test`; create temporary table t3(f int)
+master-bin.000001 500 Query 1 500 use `test`; insert into t2 select count(*) from t3
+master-bin.000001 573 Query 1 573 use `test`; insert into t3 select * from t1 where f>=4
+master-bin.000001 650 Query 1 650 use `test`; drop temporary table t3
+master-bin.000001 708 Query 1 708 use `test`; insert into t2 select count(*) from t3
+master-bin.000001 781 Query 1 781 use `test`; drop temporary table t3
+drop table t1, t2;
+use test;
+SET TIMESTAMP=1040323920;
+create table t1(f int);
+SET TIMESTAMP=1040323931;
+create table t2(f int);
+SET TIMESTAMP=1040323938;
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+SET TIMESTAMP=1040323945;
+SET @@session.pseudo_thread_id=1;
+create temporary table t3(f int);
+SET TIMESTAMP=1040323952;
+SET @@session.pseudo_thread_id=1;
+insert into t3 select * from t1 where f<6;
+SET TIMESTAMP=1040324145;
+SET @@session.pseudo_thread_id=2;
+create temporary table t3(f int);
+SET TIMESTAMP=1040324186;
+SET @@session.pseudo_thread_id=1;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324200;
+SET @@session.pseudo_thread_id=2;
+insert into t3 select * from t1 where f>=4;
+SET TIMESTAMP=1040324211;
+SET @@session.pseudo_thread_id=1;
+drop temporary table t3;
+SET TIMESTAMP=1040324219;
+SET @@session.pseudo_thread_id=2;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324224;
+SET @@session.pseudo_thread_id=2;
+drop temporary table t3;
+select * from t2;
+f
+5
+7
+drop table t1,t2;
diff --git a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result
new file mode 100644
index 00000000000..618efb3840d
--- /dev/null
+++ b/mysql-test/r/rpl_user_variables.result
@@ -0,0 +1,78 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+stop slave;
+reset master;
+drop table if exists t1;
+create table t1(n char(30));
+set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
+set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
+set @n1:=null;
+set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def';
+insert into t1 values (@i1), (@i2), (@i3), (@i4);
+insert into t1 values (@r1), (@r2);
+insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5);
+insert into t1 values (@n1);
+insert into t1 values (@n2);
+insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1);
+insert into t1 values (@a+(@b:=@a+1));
+set @q:='abc';
+insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
+set @a:=5;
+insert into t1 values (@a),(@a);
+start slave;
+select * from t1;
+n
+12345678901234
+-12345678901234
+0
+-1
+12.5
+-12.5
+This is a test
+
+abc'def
+abc\def
+abc'def
+NULL
+NULL
+0
+1
+2
+5
+abc
+abcn1
+abcn1n2
+5
+5
+show binlog events from 141;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+slave-bin.000001 141 User var 2 141 @i1=12345678901234
+slave-bin.000001 184 User var 2 184 @i2=-12345678901234
+slave-bin.000001 227 User var 2 227 @i3=0
+slave-bin.000001 270 User var 2 270 @i4=-1
+slave-bin.000001 313 Query 1 313 use `test`; insert into t1 values (@i1), (@i2), (@i3), (@i4)
+slave-bin.000001 396 User var 2 396 @r1=12.5
+slave-bin.000001 439 User var 2 439 @r2=-12.5
+slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2)
+slave-bin.000001 551 User var 2 551 @s1='This is a test'
+slave-bin.000001 601 User var 2 601 @s2=''
+slave-bin.000001 637 User var 2 637 @s3='abc'def'
+slave-bin.000001 680 User var 2 680 @s4='abc\def'
+slave-bin.000001 723 User var 2 723 @s5='abc'def'
+slave-bin.000001 766 Query 1 766 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
+slave-bin.000001 856 User var 2 856 @n1=NULL
+slave-bin.000001 882 Query 1 882 use `test`; insert into t1 values (@n1)
+slave-bin.000001 944 Query 1 944 use `test`; insert into t1 values (@n2)
+slave-bin.000001 1006 Query 1 1006 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
+slave-bin.000001 1094 User var 2 1094 @a='2'
+slave-bin.000001 1130 Query 1 1130 use `test`; insert into t1 values (@a+(@b:=@a+1))
+slave-bin.000001 1202 User var 2 1202 @q='abc'
+slave-bin.000001 1240 Query 1 1240 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
+slave-bin.000001 1344 User var 2 1344 @a=5
+slave-bin.000001 1386 Query 1 1386 use `test`; insert into t1 values (@a),(@a)
+drop table t1;
+stop slave;
diff --git a/mysql-test/r/sel000001.result b/mysql-test/r/sel000001.result
deleted file mode 100644
index 28f6d3d1d5a..00000000000
--- a/mysql-test/r/sel000001.result
+++ /dev/null
@@ -1,7 +0,0 @@
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (s CHAR(20) PRIMARY KEY, id INT);
-INSERT INTO t1 VALUES ('cat', 1), ('mouse', 3), ('dog', 2), ('snake', 77);
-SELECT s, id FROM t1 WHERE s = 'mouse';
-s id
-mouse 3
-drop table t1;
diff --git a/mysql-test/r/sel000002.result b/mysql-test/r/sel000002.result
deleted file mode 100644
index b824de8de4a..00000000000
--- a/mysql-test/r/sel000002.result
+++ /dev/null
@@ -1,9 +0,0 @@
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (n INT);
-INSERT INTO t1 VALUES (1), (2), (3);
-SELECT * FROM t1;
-n
-1
-2
-3
-drop table t1;
diff --git a/mysql-test/r/sel000003.result b/mysql-test/r/sel000003.result
deleted file mode 100644
index c3853832f87..00000000000
--- a/mysql-test/r/sel000003.result
+++ /dev/null
@@ -1,8 +0,0 @@
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (name CHAR(20) NOT NULL PRIMARY KEY, score SMALLINT NOT NULL, KEY(score));
-INSERT INTO t1 VALUES ('Sasha', 20), ('Matt', 20), ('Monty', 10), ('David', 10), ('Tim', 10), ('Jeremy', 10);
-SELECT COUNT(*) as n, score FROM t1 GROUP BY score;
-n score
-4 10
-2 20
-drop table t1;
diff --git a/mysql-test/r/sel000031.result b/mysql-test/r/sel000031.result
deleted file mode 100644
index d3f01ab687f..00000000000
--- a/mysql-test/r/sel000031.result
+++ /dev/null
@@ -1,12 +0,0 @@
-drop table if exists t1,t2;
-create table t1 (id int(10) not null unique);
-create table t2 (id int(10) not null primary key,
-val int(10) not null);
-insert into t1 values (1),(2),(4);
-insert into t2 values (1,1),(2,1),(3,1),(4,2);
-select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
-id elt(two.val,'one','two')
-1 one
-2 one
-4 two
-drop table t1,t2;
diff --git a/mysql-test/r/sel000032.result b/mysql-test/r/sel000032.result
deleted file mode 100644
index 4cca245d75b..00000000000
--- a/mysql-test/r/sel000032.result
+++ /dev/null
@@ -1,12 +0,0 @@
-drop table if exists t1,t2;
-create table t1 (id int(10) not null unique);
-create table t2 (id int(10) not null primary key,
-val int(10) not null);
-insert into t1 values (1),(2),(4);
-insert into t2 values (1,1),(2,1),(3,1),(4,2);
-select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
-id elt(two.val,'one','two')
-1 one
-2 one
-4 two
-drop table t1,t2;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index a921d75f20a..9ed54f7c253 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1,4 +1,3 @@
-use test;
drop table if exists t1,t2,t3,t4;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
@@ -1327,20 +1326,20 @@ fld3
select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
fld3
explain select t2.fld3 from t2 where fld3 = 'honeysuckle';
-table type possible_keys key key_len ref rows Extra
-t2 ref fld3 fld3 30 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle';
-table type possible_keys key key_len ref rows Extra
-t2 ALL NULL NULL NULL NULL 1199 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle';
-table type possible_keys key key_len ref rows Extra
-t2 ALL NULL NULL NULL NULL 1199 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle';
-table type possible_keys key key_len ref rows Extra
-t2 ref fld3 fld3 30 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle';
-table type possible_keys key key_len ref rows Extra
-t2 ref fld3 fld3 30 const 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
explain select fld3 from t2 ignore index (fld3,not_used);
Key column 'not_used' doesn't exist in table
explain select fld3 from t2 use index (not_used);
@@ -1350,8 +1349,8 @@ fld3
honeysuckle
honoring
explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
-table type possible_keys key key_len ref rows Extra
-t2 range fld3 fld3 30 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index
select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
fld1 fld3
148504 Colombo
@@ -1370,8 +1369,8 @@ fld1
250501
250502
explain select fld1 from t2 where fld1=250501 or fld1="250502";
-table type possible_keys key key_len ref rows Extra
-t2 range fld1 fld1 4 NULL 2 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index
select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
fld1
250501
@@ -1379,8 +1378,8 @@ fld1
250505
250601
explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
-table type possible_keys key key_len ref rows Extra
-t2 range fld1 fld1 4 NULL 4 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index
select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
fld1 fld3
218401 faithful
@@ -1806,21 +1805,21 @@ companynr rtrim(space(512+companynr))
select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3;
fld3
explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3;
-table type possible_keys key key_len ref rows Extra
-t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
-t3 eq_ref PRIMARY PRIMARY 4 t2.fld1 1 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 t2.fld1 1 Using where; Using index
explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period;
-table type possible_keys key key_len ref rows Extra
-t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort
-t3 ref period period 4 t1.period 4181
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort
+1 SIMPLE t3 ref period period 4 t1.period 4181
explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10;
-table type possible_keys key key_len ref rows Extra
-t3 index period period 4 NULL 41810
-t1 ref period period 4 t3.period 4181
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index period period 4 NULL 41810
+1 SIMPLE t1 ref period period 4 t3.period 4181
explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10;
-table type possible_keys key key_len ref rows Extra
-t1 index period period 4 NULL 41810
-t3 ref period period 4 t1.period 4181
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index period period 4 NULL 41810
+1 SIMPLE t3 ref period period 4 t1.period 4181
select period from t1;
period
9410
@@ -1833,9 +1832,9 @@ select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.
fld3 period
breaking 1001
explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period;
-table type possible_keys key key_len ref rows Extra
-t2 const fld1 fld1 4 const 1
-t3 const PRIMARY,period PRIMARY 4 const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const fld1 fld1 4 const 1
+1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1
select fld3,period from t2,t1 where companynr*10 = 37*10;
fld3 period
breaking 9410
@@ -2493,7 +2492,6 @@ fld1 fld3 period price price2
018601 vacuuming 1001 5987435 234724
018801 inch 1001 5987435 234724
018811 repetitions 1001 5987435 234724
-drop table if exists company;
create table t4 (
companynr tinyint(2) unsigned zerofill NOT NULL default '00',
companyname char(30) NOT NULL default '',
@@ -2573,21 +2571,21 @@ fld1 fld1
select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
companynr companyname
explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
-table type possible_keys key key_len ref rows Extra
-t2 ALL NULL NULL NULL NULL 1199
-t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null;
-table type possible_keys key key_len ref rows Extra
-t4 ALL NULL NULL NULL NULL 12
-t2 ALL NULL NULL NULL NULL 1199 Using where; Not exists
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Not exists
select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
companynr companynr
37 36
41 40
explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
-table type possible_keys key key_len ref rows Extra
-t2 ALL NULL NULL NULL NULL 1199 Using temporary
-t4 index NULL PRIMARY 1 NULL 12 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using temporary
+1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using where; Using index
select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
fld1 companynr fld3 period
038008 37 reporters 1008
@@ -2656,14 +2654,14 @@ companynr count(*)
58 23
53 4
50 11
-select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>"";
-count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
-70 absentee vest 17788966 254128.0857 3272.5940
-select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3;
-companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
-00 82 Anthony windmills 10355753 126289.6707 115550.9757
-29 95 abut wetness 14473298 152350.5053 8368.5480
-34 70 absentee vest 17788966 254128.0857 3272.5940
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
+companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
+29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
+34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 1 1 5987435 5987435 5987435 5987435.0000
@@ -3096,11 +3094,11 @@ select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr =
fld1 sum(price)
038008 234298
explain select fld3 from t2 where 1>2 or 2>3;
-Comment
-Impossible WHERE
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
explain select fld3 from t2 where fld1=fld1;
-table type possible_keys key key_len ref rows Extra
-t2 ALL NULL NULL NULL NULL 1199
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
companynr fld1
34 250501
@@ -3151,8 +3149,8 @@ select count(*) from t3 where companynr=512 and price2=76234234;
count(*)
4181
explain select min(fld1),max(fld1),count(*) from t2;
-Comment
-Select tables optimized away
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
select min(fld1),max(fld1),count(*) from t2;
min(fld1) max(fld1) count(*)
0 1232609 1199
@@ -3219,23 +3217,23 @@ Tables_in_test (s%)
show tables from test like "t?";
Tables_in_test (t?)
show full columns from t2;
-Field Type Null Key Default Extra Privileges
-auto int(11) PRI NULL auto_increment select,insert,update,references
-fld1 int(6) unsigned zerofill UNI 000000 select,insert,update,references
-companynr tinyint(2) unsigned zerofill 00 select,insert,update,references
-fld3 char(30) MUL select,insert,update,references
-fld4 char(35) select,insert,update,references
-fld5 char(35) select,insert,update,references
-fld6 char(4) select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(11) binary PRI NULL auto_increment select,insert,update,references
+fld1 int(6) unsigned zerofill binary UNI 000000 select,insert,update,references
+companynr tinyint(2) unsigned zerofill binary 00 select,insert,update,references
+fld3 char(30) latin1 MUL select,insert,update,references
+fld4 char(35) latin1 select,insert,update,references
+fld5 char(35) latin1 select,insert,update,references
+fld6 char(4) latin1 select,insert,update,references
show full columns from t2 from test like 'f%';
-Field Type Null Key Default Extra Privileges
-fld1 int(6) unsigned zerofill UNI 000000 select,insert,update,references
-fld3 char(30) MUL select,insert,update,references
-fld4 char(35) select,insert,update,references
-fld5 char(35) select,insert,update,references
-fld6 char(4) select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+fld1 int(6) unsigned zerofill binary UNI 000000 select,insert,update,references
+fld3 char(30) latin1 MUL select,insert,update,references
+fld4 char(35) latin1 select,insert,update,references
+fld5 char(35) latin1 select,insert,update,references
+fld6 char(4) latin1 select,insert,update,references
show full columns from t2 from test like 's%';
-Field Type Null Key Default Extra Privileges
+Field Type Collation Null Key Default Extra Privileges Comment
show keys from t2;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE
@@ -3266,6 +3264,16 @@ select wss_type from t1 where wss_type =102935229216544093;
wss_type
102935229216544093
drop table t1;
+select 1+2,"aaaa",3.13*2.0 into @a,@b,@c;
+select @a;
+@a
+3
+select @b;
+@b
+aaaa
+select @c;
+@c
+6.26
create table t1 (a int not null auto_increment primary key);
insert into t1 values ();
insert into t1 values ();
@@ -3468,7 +3476,6 @@ a a a
2 2 2
3 3 3
drop table t1;
-drop table if exists t1,t2;
CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) TYPE=MyISAM;
INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
CREATE TABLE t2 ( id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;
@@ -3480,4 +3487,4 @@ aa id t2_id id
4 8302 2519 2519
5 8303 2520 2520
6 8304 2521 2521
-drop table if exists t1,t2;
+drop table t1,t2;
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
index 0a7f464cf7b..c8991696b5e 100644
--- a/mysql-test/r/select_found.result
+++ b/mysql-test/r/select_found.result
@@ -168,4 +168,24 @@ test2 2 2
SELECT FOUND_ROWS();
FOUND_ROWS()
2
+SELECT SQL_CALC_FOUND_ROWS 1 FROM (SELECT 1) as a LIMIT 0;
+1
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+1
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE numeropost > 1 LIMIT 0;
+titre numeropost maxnumrep
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+2
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 0;
+titre numeropost maxnumrep
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+3
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 ORDER BY numeropost LIMIT 0;
+titre numeropost maxnumrep
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+3
drop table t1;
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index fa2f381d905..de652b05154 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -43,7 +43,7 @@ wait_timeout 28800
show variables like "this_doesn't_exists%";
Variable_name Value
show table status from test like "this_doesn't_exists%";
-Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment
+Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Charset Create_options Comment
show databases;
Database
mysql
@@ -77,24 +77,31 @@ show create table t1;
Table Create Table
t1 CREATE TEMPORARY TABLE `t1` (
`a` int(11) NOT NULL default '0'
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
alter table t1 rename t2;
show create table t2;
Table Create Table
t2 CREATE TEMPORARY TABLE `t2` (
`a` int(11) NOT NULL default '0'
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t2;
create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
-name char(20) default 'O''Brien'
+name char(20) default 'O''Brien' comment 'O''Brien as default',
+c int not null comment 'int column'
) comment = 'it\'s a table' ;
show create table t1 ;
Table Create Table
t1 CREATE TABLE `t1` (
`test_set` set('val1','val2','val3') NOT NULL default '',
- `name` char(20) default 'O''Brien'
-) TYPE=MyISAM COMMENT='it''s a table'
+ `name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
+ `c` int(11) NOT NULL default '0' COMMENT 'int column'
+) TYPE=MyISAM CHARSET=latin1 COMMENT='it''s a table'
+show full columns from t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+test_set set('val1','val2','val3') latin1 select,insert,update,references
+name char(20) latin1 YES O'Brien select,insert,update,references O'Brien as default
+c int(11) binary 0 select,insert,update,references int column
drop table t1;
create table t1 (a int not null, unique aa (a));
show create table t1;
@@ -102,7 +109,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
UNIQUE KEY `aa` (`a`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
create table t1 (a int not null, primary key (a));
show create table t1;
@@ -110,7 +117,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
PRIMARY KEY (`a`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
flush tables;
show open tables;
@@ -128,7 +135,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` char(10) default NULL,
KEY `b` (`b`)
-) TYPE=MyISAM MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
+) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
show create table t1;
Table Create Table
@@ -136,7 +143,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL,
KEY `b` (`b`)
-) TYPE=MyISAM MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
+) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK_KEYS=DEFAULT DELAY_KEY_WRITE=0 ROW_FORMAT=default;
show create table t1;
Table Create Table
@@ -144,17 +151,25 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` varchar(10) default NULL,
KEY `b` (`b`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
create table t1 (a decimal(9,2), b decimal (9,0), e double(9,2), f double(5,0), h float(3,2), i float(3,0));
show columns from t1;
-Field Type Null Key Default Extra
-a decimal(9,2) YES NULL
-b decimal(9,0) YES NULL
-e double(9,2) YES NULL
-f double(5,0) YES NULL
-h float(3,2) YES NULL
-i float(3,0) YES NULL
+Field Type Collation Null Key Default Extra
+a decimal(9,2) binary YES NULL
+b decimal(9,0) binary YES NULL
+e double(9,2) binary YES NULL
+f double(5,0) binary YES NULL
+h float(3,2) binary YES NULL
+i float(3,0) binary YES NULL
+show full columns from t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+a decimal(9,2) binary YES NULL select,insert,update,references
+b decimal(9,0) binary YES NULL select,insert,update,references
+e double(9,2) binary YES NULL select,insert,update,references
+f double(5,0) binary YES NULL select,insert,update,references
+h float(3,2) binary YES NULL select,insert,update,references
+i float(3,0) binary YES NULL select,insert,update,references
drop table t1;
create table t1 (
type_bool bool not null,
@@ -193,7 +208,7 @@ t1 CREATE TABLE `t1` (
`empty_char` char(0) default NULL,
`type_char` char(2) default NULL,
`type_varchar` varchar(10) default NULL,
- `type_timestamp` timestamp(14) NOT NULL,
+ `type_timestamp` timestamp NOT NULL,
`type_date` date NOT NULL default '0000-00-00',
`type_time` time NOT NULL default '00:00:00',
`type_datetime` datetime NOT NULL default '0000-00-00 00:00:00',
@@ -206,24 +221,24 @@ t1 CREATE TABLE `t1` (
`type_long_blob` longblob,
PRIMARY KEY (`type_tiny`),
KEY `type_short` (`type_short`)
-) TYPE=MyISAM MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
+) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
insert into t1 (type_timestamp) values ("2003-02-07 10:00:01");
select * from t1;
type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_numeric empty_char type_char type_varchar type_timestamp type_date type_time type_datetime type_year type_enum type_set type_tinyblob type_blob type_medium_blob type_long_blob
-0 1 NULL NULL NULL NULL NULL NULL NULL NULL 20030207100001 0000-00-00 00:00:00 0000-00-00 00:00:00 NULL NULL NULL NULL NULL NULL NULL
+0 1 NULL NULL NULL NULL NULL NULL NULL NULL 2003-02-07 10:00:01 0000-00-00 00:00:00 0000-00-00 00:00:00 NULL NULL NULL NULL NULL NULL NULL
drop table t1;
create table t1 (c decimal, d double, f float, r real);
show columns from t1;
-Field Type Null Key Default Extra
-c decimal(10,0) YES NULL
-d double YES NULL
-f float YES NULL
-r double YES NULL
+Field Type Collation Null Key Default Extra
+c decimal(10,0) binary YES NULL
+d double binary YES NULL
+f float binary YES NULL
+r double binary YES NULL
drop table t1;
create table t1 (c decimal(3,3), d double(3,3), f float(3,3));
show columns from t1;
-Field Type Null Key Default Extra
-c decimal(4,3) YES NULL
-d double(4,3) YES NULL
-f float(4,3) YES NULL
+Field Type Collation Null Key Default Extra
+c decimal(4,3) binary YES NULL
+d double(4,3) binary YES NULL
+f float(4,3) binary YES NULL
drop table t1;
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
new file mode 100644
index 00000000000..8ded3daf114
--- /dev/null
+++ b/mysql-test/r/sql_mode.result
@@ -0,0 +1,87 @@
+drop table if exists t1;
+CREATE TABLE `t1` (
+a int not null auto_increment,
+`pseudo` varchar(35) character set latin2 NOT NULL default '',
+`email` varchar(60) character set latin2 NOT NULL default '',
+PRIMARY KEY (a),
+UNIQUE KEY `email` USING BTREE (`email`)
+) TYPE=HEAP CHARSET=latin1 ROW_FORMAT DYNAMIC;
+set @@sql_mode="";
+show variables like 'sql_mode';
+Variable_name Value
+sql_mode
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL auto_increment,
+ `pseudo` varchar(35) character set latin2 NOT NULL default '',
+ `email` varchar(60) character set latin2 NOT NULL default '',
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `email` TYPE BTREE (`email`)
+) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
+set @@sql_mode="ansi_quotes";
+show variables like 'sql_mode';
+Variable_name Value
+sql_mode ANSI_QUOTES
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) NOT NULL auto_increment,
+ "pseudo" varchar(35) character set latin2 NOT NULL default '',
+ "email" varchar(60) character set latin2 NOT NULL default '',
+ PRIMARY KEY ("a"),
+ UNIQUE KEY "email" TYPE BTREE ("email")
+) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
+set @@sql_mode="no_table_options";
+show variables like 'sql_mode';
+Variable_name Value
+sql_mode NO_TABLE_OPTIONS
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL auto_increment,
+ `pseudo` varchar(35) character set latin2 NOT NULL default '',
+ `email` varchar(60) character set latin2 NOT NULL default '',
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `email` TYPE BTREE (`email`)
+)
+set @@sql_mode="no_key_options";
+show variables like 'sql_mode';
+Variable_name Value
+sql_mode NO_KEY_OPTIONS
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL auto_increment,
+ `pseudo` varchar(35) character set latin2 NOT NULL default '',
+ `email` varchar(60) character set latin2 NOT NULL default '',
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `email` (`email`)
+) TYPE=HEAP CHARSET=latin1 ROW_FORMAT=DYNAMIC
+set @@sql_mode="no_field_options,mysql323,mysql40";
+show variables like 'sql_mode';
+Variable_name Value
+sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL auto_increment,
+ `pseudo` varchar(35) NOT NULL default '',
+ `email` varchar(60) NOT NULL default '',
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `email` (`email`)
+) TYPE=HEAP ROW_FORMAT=DYNAMIC
+set @@sql_mode="postgresql,oracle,mssql,db2,sapdb";
+show variables like 'sql_mode';
+Variable_name Value
+sql_mode POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) NOT NULL,
+ "pseudo" varchar(35) NOT NULL default '',
+ "email" varchar(60) NOT NULL default '',
+ PRIMARY KEY ("a"),
+ UNIQUE KEY "email" ("email")
+)
+drop table t1;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
new file mode 100644
index 00000000000..0d8c96fea85
--- /dev/null
+++ b/mysql-test/r/subselect.result
@@ -0,0 +1,1014 @@
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
+select (select 2);
+(select 2)
+2
+explain select (select 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+SELECT (SELECT 1) UNION SELECT (SELECT 2);
+(SELECT 1)
+1
+2
+explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+Note 1247 Select 4 was reduced during optimisation
+SELECT (SELECT (SELECT 0 UNION SELECT 0));
+(SELECT (SELECT 0 UNION SELECT 0))
+0
+explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
+4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
+Reference 'a' not supported (forward reference in item list)
+SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
+Reference 'b' not supported (forward reference in item list)
+SELECT (SELECT 1),MAX(1) FROM (SELECT 1) as a;
+(SELECT 1) MAX(1)
+1 1
+SELECT (SELECT a) as a;
+Reference 'a' not supported (forward reference in item list)
+EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 1
+3 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
+SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
+1
+1
+SELECT (SELECT 1), a;
+Unknown column 'a' in 'field list'
+SELECT 1 as a FROM (SELECT 1) as b HAVING (SELECT a)=1;
+a
+1
+SELECT 1 FROM (SELECT (SELECT a) b) c;
+Unknown column 'a' in 'field list'
+SELECT * FROM (SELECT 1 as id) b WHERE id IN (SELECT * FROM (SELECT 1 as id) c ORDER BY id);
+id
+1
+SELECT * FROM (SELECT 1) a WHERE 1 IN (SELECT 1,1);
+Cardinality error (more/less than 1 columns)
+SELECT 1 IN (SELECT 1);
+1 IN (SELECT 1)
+1
+SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
+1
+1
+select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
+Wrong usage of PROCEDURE and subquery
+SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
+Incorrect parameters to procedure 'ANALYSE'
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
+a
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
+a
+1
+SELECT (SELECT 1,2,3) = ROW(1,2,3);
+(SELECT 1,2,3) = ROW(1,2,3)
+1
+SELECT (SELECT 1,2,3) = ROW(1,2,1);
+(SELECT 1,2,3) = ROW(1,2,1)
+0
+SELECT (SELECT 1,2,3) < ROW(1,2,1);
+(SELECT 1,2,3) < ROW(1,2,1)
+0
+SELECT (SELECT 1,2,3) > ROW(1,2,1);
+(SELECT 1,2,3) > ROW(1,2,1)
+1
+SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
+(SELECT 1,2,3) = ROW(1,2,NULL)
+NULL
+SELECT ROW(1,2,3) = (SELECT 1,2,3);
+ROW(1,2,3) = (SELECT 1,2,3)
+1
+SELECT ROW(1,2,3) = (SELECT 1,2,1);
+ROW(1,2,3) = (SELECT 1,2,1)
+0
+SELECT ROW(1,2,3) < (SELECT 1,2,1);
+ROW(1,2,3) < (SELECT 1,2,1)
+0
+SELECT ROW(1,2,3) > (SELECT 1,2,1);
+ROW(1,2,3) > (SELECT 1,2,1)
+1
+SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
+ROW(1,2,3) = (SELECT 1,2,NULL)
+NULL
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
+(SELECT 1.5,2,'a') = ROW(1.5,2,'a')
+1
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
+(SELECT 1.5,2,'a') = ROW(1.5,2,'b')
+0
+SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
+(SELECT 1.5,2,'a') = ROW('b',2,'b')
+0
+SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
+(SELECT 'b',2,'a') = ROW(1.5,2,'a')
+0
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
+(SELECT 1.5,2,'a') = ROW(1.5,'c','a')
+0
+SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
+(SELECT 1.5,'c','a') = ROW(1.5,2,'a')
+0
+SELECT (SELECT * FROM (SELECT 'test' a,'test' b) a);
+Cardinality error (more/less than 1 columns)
+SELECT 1 as a,(SELECT a+a) b,(SELECT b);
+a b (SELECT b)
+1 2 2
+create table t1 (a int);
+create table t2 (a int, b int);
+create table t3 (a int);
+create table t4 (a int, b int);
+insert into t1 values (2);
+insert into t2 values (1,7),(2,7);
+insert into t4 values (4,8),(3,8),(5,9);
+select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
+Reference 'a1' not supported (forward reference in item list)
+select (select a from t1 where t1.a=t2.a), a from t2;
+(select a from t1 where t1.a=t2.a) a
+NULL 1
+2 2
+select (select a from t1 where t1.a=t2.b), a from t2;
+(select a from t1 where t1.a=t2.b) a
+NULL 1
+NULL 2
+select (select a from t1), a from t2;
+(select a from t1) a
+2 1
+2 2
+select (select a from t3), a from t2;
+(select a from t3) a
+NULL 1
+NULL 2
+select * from t2 where t2.a=(select a from t1);
+a b
+2 7
+insert into t3 values (6),(7),(3);
+select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
+a b
+1 7
+2 7
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+a b
+1 7
+2 7
+3 8
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
+a b
+1 7
+2 7
+3 8
+4 8
+explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
+2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
+3 UNION t4 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+4 SUBSELECT t2 ALL NULL NULL NULL NULL 2
+select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
+(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
+3 1
+7 2
+select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
+(select * from t2 where a>1) as tt;
+(select t3.a from t3 where a<8 order by 1 desc limit 1) a
+7 2
+explain select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
+(select * from t2 where a>1) as tt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived3> system NULL NULL NULL NULL 1
+3 DERIVED t2 ALL NULL NULL NULL NULL 2 Using where
+2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
+a
+2
+select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
+a
+2
+select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1);
+a
+select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
+b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
+8 7.5000
+8 4.5000
+9 7.5000
+explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t4 ALL NULL NULL NULL NULL 3
+2 DEPENDENT SUBSELECT t2 ALL NULL NULL NULL NULL 2
+3 DEPENDENT SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using where
+select * from t3 where exists (select * from t2 where t2.b=t3.a);
+a
+7
+select * from t3 where not exists (select * from t2 where t2.b=t3.a);
+a
+6
+3
+select * from t3 where a in (select b from t2);
+a
+7
+select * from t3 where a not in (select b from t2);
+a
+6
+3
+select * from t3 where a = some (select b from t2);
+a
+7
+select * from t3 where a <> any (select b from t2);
+a
+6
+3
+select * from t3 where a = all (select b from t2);
+a
+7
+select * from t3 where a <> all (select b from t2);
+a
+6
+3
+insert into t2 values (100, 5);
+select * from t3 where a < any (select b from t2);
+a
+6
+3
+select * from t3 where a < all (select b from t2);
+a
+3
+select * from t3 where a >= any (select b from t2);
+a
+6
+7
+select * from t3 where a >= all (select b from t2);
+a
+7
+delete from t2 where a=100;
+select * from t3 where a in (select a,b from t2);
+Cardinality error (more/less than 1 columns)
+select * from t3 where a in (select * from t2);
+Cardinality error (more/less than 1 columns)
+insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
+select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
+from t2 where t2.b=t4.b);
+b ma
+select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
+from t2 where t2.b=t4.b);
+b ma
+7 12
+create table t5 (a int);
+select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
+NULL 1
+2 2
+insert into t5 values (5);
+select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
+NULL 1
+2 2
+insert into t5 values (2);
+select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
+NULL 1
+2 2
+explain select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+2 DEPENDENT SUBSELECT t1 system NULL NULL NULL NULL 1
+3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where
+select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
+Subselect returns more than 1 record
+create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
+create table t7( uq int primary key, name char(25));
+insert into t7 values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta");
+insert into t6 values (1,1),(1,2),(2,2),(1,3);
+select * from t6 where exists (select * from t7 where uq = clinic_uq);
+patient_uq clinic_uq
+1 1
+1 2
+2 2
+select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
+Column: 'a' in field list is ambiguous
+drop table if exists t1,t2,t3;
+CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
+INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
+CREATE TABLE t2 (a varchar(20),b int NOT NULL default '0');
+INSERT INTO t2 VALUES ('W','1'),('A','3'),('J','2');
+CREATE TABLE t1 (a varchar(20),b date NOT NULL default '0000-00-00');
+INSERT INTO t1 VALUES ('W','1732-02-22'),('A','1735-10-30'),('J','1743-04-13');
+SELECT * FROM t1 WHERE b = (SELECT MIN(b) FROM t1);
+a b
+W 1732-02-22
+SELECT * FROM t2 WHERE b = (SELECT MIN(b) FROM t2);
+a b
+W 1
+SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3);
+a b
+W a
+CREATE TABLE `t8` (
+`pseudo` varchar(35) character set latin1 NOT NULL default '',
+`email` varchar(60) character set latin1 NOT NULL default '',
+PRIMARY KEY (`pseudo`),
+UNIQUE KEY `email` (`email`)
+) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
+INSERT INTO t8 (pseudo,email) VALUES ('joce','test');
+INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
+INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
+EXPLAIN SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t8 const PRIMARY PRIMARY 35 const 1
+4 SUBSELECT t8 const PRIMARY PRIMARY 35 1
+2 SUBSELECT t8 const PRIMARY PRIMARY 35 const 1
+3 SUBSELECT t8 const PRIMARY PRIMARY 35 1
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
+t8 WHERE pseudo='joce');
+Cardinality error (more/less than 1 columns)
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT * FROM t8 WHERE
+pseudo='joce');
+Cardinality error (more/less than 1 columns)
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
+pseudo
+joce
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo LIKE '%joce%');
+Subselect returns more than 1 record
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
+CREATE TABLE `t1` (
+`topic` mediumint(8) unsigned NOT NULL default '0',
+`date` date NOT NULL default '0000-00-00',
+`pseudo` varchar(35) character set latin1 NOT NULL default '',
+PRIMARY KEY (`pseudo`,`date`,`topic`),
+KEY `topic` (`topic`)
+) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
+INSERT INTO t1 (topic,date,pseudo) VALUES
+('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
+EXPLAIN SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
+EXPLAIN SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+2 SUBSELECT t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
+SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
+date
+2002-08-03
+SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
+(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')
+2002-08-03
+SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1;
+1
+1
+1
+1
+SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1;
+Subselect returns more than 1 record
+EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index NULL topic 3 NULL 2 Using index
+2 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+drop table t1;
+CREATE TABLE `t1` (
+`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
+`maxnumrep` int(10) unsigned NOT NULL default '0',
+PRIMARY KEY (`numeropost`),
+UNIQUE KEY `maxnumrep` (`maxnumrep`)
+) TYPE=MyISAM ROW_FORMAT=FIXED;
+INSERT INTO t1 (numeropost,maxnumrep) VALUES (40143,1),(43506,2);
+CREATE TABLE `t2` (
+`mot` varchar(30) NOT NULL default '',
+`topic` mediumint(8) unsigned NOT NULL default '0',
+`date` date NOT NULL default '0000-00-00',
+`pseudo` varchar(35) NOT NULL default '',
+PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`)
+) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
+INSERT INTO t2 (mot,topic,date,pseudo) VALUES ('joce','40143','2002-10-22','joce'), ('joce','43506','2002-10-22','joce');
+select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1);
+a
+40143
+SELECT numeropost,maxnumrep FROM t1 WHERE exists (SELECT 1 FROM t2 WHERE (mot='joce') AND date >= '2002-10-21' AND t1.numeropost = t2.topic) ORDER BY maxnumrep DESC LIMIT 0, 20;
+numeropost maxnumrep
+43506 2
+40143 1
+SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
+Unknown column 'a' in 'having clause'
+SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
+Unknown column 'a' in 'having clause'
+SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+joce 43506 2002-10-22 joce
+SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
+mot topic date pseudo
+SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
+mot topic date pseudo
+SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+joce 43506 2002-10-22 joce
+SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
+mot topic date pseudo
+SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
+mot topic date pseudo
+SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic);
+mot topic date pseudo
+SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+joce 43506 2002-10-22 joce
+SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100) from t2;
+mot topic date pseudo topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100)
+joce 40143 2002-10-22 joce 1
+joce 43506 2002-10-22 joce 1
+SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
+mot topic date pseudo
+SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+joce 43506 2002-10-22 joce
+SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
+mot topic date pseudo
+joce 40143 2002-10-22 joce
+SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000) from t2;
+mot topic date pseudo topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000)
+joce 40143 2002-10-22 joce 1
+joce 43506 2002-10-22 joce 0
+drop table t1,t2;
+CREATE TABLE `t1` (
+`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
+`maxnumrep` int(10) unsigned NOT NULL default '0',
+PRIMARY KEY (`numeropost`),
+UNIQUE KEY `maxnumrep` (`maxnumrep`)
+) TYPE=MyISAM ROW_FORMAT=FIXED;
+INSERT INTO t1 (numeropost,maxnumrep) VALUES (1,0),(2,1);
+select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1);
+Subselect returns more than 1 record
+select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1);
+Subselect returns more than 1 record
+drop table t1;
+CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b');
+INSERT INTO t1 VALUES ();
+SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b');
+Subselect returns more than 1 record
+drop table t1;
+CREATE TABLE `t1` (
+`numeropost` mediumint(8) unsigned NOT NULL default '0',
+`numreponse` int(10) unsigned NOT NULL auto_increment,
+`pseudo` varchar(35) NOT NULL default '',
+PRIMARY KEY (`numeropost`,`numreponse`),
+UNIQUE KEY `numreponse` (`numreponse`),
+KEY `pseudo` (`pseudo`,`numeropost`)
+) TYPE=MyISAM;
+SELECT (SELECT numeropost FROM t1 HAVING numreponse=a),numreponse FROM (SELECT * FROM t1) as a;
+Reference 'numreponse' not supported (forward reference in item list)
+SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=a) FROM (SELECT * FROM t1) as a;
+Unknown column 'a' in 'having clause'
+SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=1) FROM (SELECT * FROM t1) as a;
+numreponse (SELECT numeropost FROM t1 HAVING numreponse=1)
+INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
+EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
+Subselect returns more than 1 record
+EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1
+2 SUBSELECT NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1;
+CREATE TABLE t1 (a int(1));
+INSERT INTO t1 VALUES (1);
+SELECT 1 FROM (SELECT a FROM t1) b HAVING (SELECT b.a)=1;
+1
+1
+drop table t1;
+create table t1 (a int NOT NULL, b int, primary key (a));
+create table t2 (a int NOT NULL, b int, primary key (a));
+insert into t1 values (0, 10),(1, 11),(2, 12);
+insert into t2 values (1, 21),(2, 22),(3, 23);
+select * from t1;
+a b
+0 10
+1 11
+2 12
+update t1 set b= (select b from t1);
+You can't specify target table 't1' for update in FROM clause
+update t1 set b= (select b from t2);
+Subselect returns more than 1 record
+update t1 set b= (select b from t2 where t1.a = t2.a);
+select * from t1;
+a b
+0 NULL
+1 21
+2 22
+drop table t1, t2;
+create table t1 (a int NOT NULL, b int, primary key (a));
+create table t2 (a int NOT NULL, b int, primary key (a));
+insert into t1 values (0, 10),(1, 11),(2, 12);
+insert into t2 values (1, 21),(2, 12),(3, 23);
+select * from t1;
+a b
+0 10
+1 11
+2 12
+select * from t1 where b = (select b from t2 where t1.a = t2.a);
+a b
+2 12
+delete from t1 where b = (select b from t1);
+You can't specify target table 't1' for update in FROM clause
+delete from t1 where b = (select b from t2);
+Subselect returns more than 1 record
+delete from t1 where b = (select b from t2 where t1.a = t2.a);
+select * from t1;
+a b
+0 10
+1 11
+drop table t1, t2;
+create table t11 (a int NOT NULL, b int, primary key (a));
+create table t12 (a int NOT NULL, b int, primary key (a));
+create table t2 (a int NOT NULL, b int, primary key (a));
+insert into t11 values (0, 10),(1, 11),(2, 12);
+insert into t12 values (33, 10),(22, 11),(2, 12);
+insert into t2 values (1, 21),(2, 12),(3, 23);
+select * from t11;
+a b
+0 10
+1 11
+2 12
+select * from t12;
+a b
+33 10
+22 11
+2 12
+delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a);
+You can't specify target table 't12' for update in FROM clause
+delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2);
+Subselect returns more than 1 record
+delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a);
+select * from t11;
+a b
+0 10
+1 11
+select * from t12;
+a b
+33 10
+22 11
+drop table t11, t12, t2;
+CREATE TABLE t1 (x int);
+create table t2 (a int);
+create table t3 (a int);
+insert into t2 values (1);
+insert into t3 values (1),(2);
+INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
+You can't specify target table 't1' for update in FROM clause
+INSERT INTO t1 (x) VALUES ((SELECT a FROM t3));
+Subselect returns more than 1 record
+INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
+select * from t1;
+x
+1
+insert into t2 values (1);
+INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
+select * from t1;
+x
+1
+2
+INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2;
+select * from t1;
+x
+1
+2
+3
+3
+INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
+You can't specify target table 't1' for update in FROM clause
+INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
+select * from t1;
+x
+1
+2
+3
+3
+0
+drop table t1, t2, t3;
+CREATE TABLE t1 (x int not null, y int, primary key (x));
+create table t2 (a int);
+create table t3 (a int);
+insert into t2 values (1);
+insert into t3 values (1),(2);
+select * from t1;
+x y
+replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2));
+You can't specify target table 't1' for update in FROM clause
+replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2));
+Subselect returns more than 1 record
+replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2));
+select * from t1;
+x y
+1 2
+replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+2 FROM t2));
+select * from t1;
+x y
+1 3
+replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a FROM t2));
+select * from t1;
+x y
+1 3
+4 1
+replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a+1 FROM t2));
+select * from t1;
+x y
+1 3
+4 2
+replace LOW_PRIORITY into t1 (x, y) VALUES ((SELECT a+1 FROM t2), (SELECT a FROM t2));
+select * from t1;
+x y
+1 3
+4 2
+2 1
+drop table t1, t2, t3;
+SELECT * FROM (SELECT 1) b WHERE 1 IN (SELECT *);
+No tables used
+CREATE TABLE t2 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t2 VALUES (1),(2);
+SELECT * FROM t2 WHERE id IN (SELECT 1);
+id
+1
+EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ref id id 5 const 1 Using where; Using index
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
+id
+1
+SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
+id
+2
+EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ref id id 5 const 1 Using where; Using index
+3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 3 was reduced during optimisation
+Note 1247 Select 2 was reduced during optimisation
+EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index NULL id 5 NULL 2 Using where; Using index
+2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
+3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
+id
+SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
+id
+2
+INSERT INTO t2 VALUES ((SELECT * FROM t2));
+You can't specify target table 't2' for update in FROM clause
+SELECT * FROM t2;
+id
+1
+2
+CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t1 values (1),(1);
+UPDATE t2 SET id=(SELECT * FROM t1);
+Subselect returns more than 1 record
+drop table t2, t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+select 1 IN (SELECT * from t1);
+1 IN (SELECT * from t1)
+1
+select 10 IN (SELECT * from t1);
+10 IN (SELECT * from t1)
+0
+select NULL IN (SELECT * from t1);
+NULL IN (SELECT * from t1)
+NULL
+update t1 set a=NULL where a=2;
+select 1 IN (SELECT * from t1);
+1 IN (SELECT * from t1)
+1
+select 3 IN (SELECT * from t1);
+3 IN (SELECT * from t1)
+1
+select 10 IN (SELECT * from t1);
+10 IN (SELECT * from t1)
+NULL
+select 1 > ALL (SELECT * from t1);
+1 > ALL (SELECT * from t1)
+0
+select 10 > ALL (SELECT * from t1);
+10 > ALL (SELECT * from t1)
+NULL
+select 1 > ANY (SELECT * from t1);
+1 > ANY (SELECT * from t1)
+NULL
+select 10 > ANY (SELECT * from t1);
+10 > ANY (SELECT * from t1)
+1
+drop table t1;
+create table t1 (a varchar(20));
+insert into t1 values ('A'),('BC'),('DEF');
+select 'A' IN (SELECT * from t1);
+'A' IN (SELECT * from t1)
+1
+select 'XYZS' IN (SELECT * from t1);
+'XYZS' IN (SELECT * from t1)
+0
+select NULL IN (SELECT * from t1);
+NULL IN (SELECT * from t1)
+NULL
+update t1 set a=NULL where a='BC';
+select 'A' IN (SELECT * from t1);
+'A' IN (SELECT * from t1)
+1
+select 'DEF' IN (SELECT * from t1);
+'DEF' IN (SELECT * from t1)
+1
+select 'XYZS' IN (SELECT * from t1);
+'XYZS' IN (SELECT * from t1)
+NULL
+select 'A' > ALL (SELECT * from t1);
+'A' > ALL (SELECT * from t1)
+0
+select 'XYZS' > ALL (SELECT * from t1);
+'XYZS' > ALL (SELECT * from t1)
+NULL
+select 'A' > ANY (SELECT * from t1);
+'A' > ANY (SELECT * from t1)
+NULL
+select 'XYZS' > ANY (SELECT * from t1);
+'XYZS' > ANY (SELECT * from t1)
+1
+drop table t1;
+create table t1 (a float);
+insert into t1 values (1.5),(2.5),(3.5);
+select 1.5 IN (SELECT * from t1);
+1.5 IN (SELECT * from t1)
+1
+select 10.5 IN (SELECT * from t1);
+10.5 IN (SELECT * from t1)
+0
+select NULL IN (SELECT * from t1);
+NULL IN (SELECT * from t1)
+NULL
+update t1 set a=NULL where a=2.5;
+select 1.5 IN (SELECT * from t1);
+1.5 IN (SELECT * from t1)
+1
+select 3.5 IN (SELECT * from t1);
+3.5 IN (SELECT * from t1)
+1
+select 10.5 IN (SELECT * from t1);
+10.5 IN (SELECT * from t1)
+NULL
+select 1.5 > ALL (SELECT * from t1);
+1.5 > ALL (SELECT * from t1)
+0
+select 10.5 > ALL (SELECT * from t1);
+10.5 > ALL (SELECT * from t1)
+NULL
+select 1.5 > ANY (SELECT * from t1);
+1.5 > ANY (SELECT * from t1)
+NULL
+select 10.5 > ANY (SELECT * from t1);
+10.5 > ANY (SELECT * from t1)
+1
+explain select (select a+1) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+select (select a+1) from t1;
+(select a+1)
+2.5
+NULL
+4.5
+drop table t1;
+CREATE TABLE t1 (a int(11) NOT NULL default '0', PRIMARY KEY (a));
+CREATE TABLE t2 (a int(11) default '0', INDEX (a));
+INSERT INTO t1 VALUES (1),(2),(3),(4);
+INSERT INTO t2 VALUES (1),(2),(3);
+SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
+a t1.a in (select t2.a from t2)
+1 1
+2 1
+3 1
+4 0
+explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
+2 DEPENDENT SUBSELECT t2 index NULL a 5 NULL 3 Using where; Using index
+drop table t1,t2;
+create table t1 (a float);
+select 10.5 IN (SELECT * from t1 LIMIT 1);
+This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
+This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+drop table t1;
+create table t1 (a int, b int, c varchar(10));
+create table t2 (a int);
+insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
+insert into t2 values (1),(2),(NULL);
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t1 where a=t2.a) from t2;
+a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a') (select c from t1 where a=t2.a)
+1 1 a
+2 0 b
+NULL NULL NULL
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
+a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b') (select c from t1 where a=t2.a)
+1 0 a
+2 1 b
+NULL NULL NULL
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
+a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where a=t2.a)
+1 0 a
+2 0 b
+NULL NULL NULL
+drop table t1,t2;
+create table t1 (a int, b real, c varchar(10));
+insert into t1 values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
+select ROW(1, 1, 'a') IN (select a,b,c from t1);
+ROW(1, 1, 'a') IN (select a,b,c from t1)
+1
+select ROW(1, 2, 'a') IN (select a,b,c from t1);
+ROW(1, 2, 'a') IN (select a,b,c from t1)
+NULL
+select ROW(1, 1, 'a') IN (select b,a,c from t1);
+ROW(1, 1, 'a') IN (select b,a,c from t1)
+1
+select ROW(1, 1, 'a') IN (select a,b,c from t1 where a is not null);
+ROW(1, 1, 'a') IN (select a,b,c from t1 where a is not null)
+1
+select ROW(1, 2, 'a') IN (select a,b,c from t1 where a is not null);
+ROW(1, 2, 'a') IN (select a,b,c from t1 where a is not null)
+0
+select ROW(1, 1, 'a') IN (select b,a,c from t1 where a is not null);
+ROW(1, 1, 'a') IN (select b,a,c from t1 where a is not null)
+1
+select ROW(1, 1, 'a') IN (select a,b,c from t1 where c='b' or c='a');
+ROW(1, 1, 'a') IN (select a,b,c from t1 where c='b' or c='a')
+1
+select ROW(1, 2, 'a') IN (select a,b,c from t1 where c='b' or c='a');
+ROW(1, 2, 'a') IN (select a,b,c from t1 where c='b' or c='a')
+NULL
+select ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a');
+ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a')
+1
+select ROW(1, 1, 'a') IN (select b,a,c from t1 limit 2);
+This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1);
+do @a:=(SELECT a from t1);
+select @a;
+@a
+1
+set @a:=2;
+set @a:=(SELECT a from t1);
+select @a;
+@a
+1
+drop table t1;
+do (SELECT a from t1);
+Table 'test.t1' doesn't exist
+set @a:=(SELECT a from t1);
+Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a int, KEY(a));
+HANDLER t1 OPEN;
+HANDLER t1 READ a=((SELECT 1));
+You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
+HANDLER t1 CLOSE;
+drop table t1;
+create table t1 (a int);
+create table t2 (b int);
+insert into t1 values (1),(2);
+insert into t2 values (1);
+select a from t1 where a in (select a from t1 where a in (select b from t2));
+a
+1
+drop table t1, t2;
+create table t1 (a int, b int);
+create table t2 like t1;
+insert into t1 values (1,2),(1,3),(1,4),(1,5);
+insert into t2 values (1,2),(1,3);
+select * from t1 where row(a,b) in (select a,b from t2);
+a b
+1 2
+1 3
+drop table t1, t2;
+CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t1 VALUES (1);
+UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
+Invalid use of group function
+drop table t1;
+CREATE TABLE t1 (a int(1));
+EXPLAIN SELECT (SELECT RAND() FROM t1) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
+2 UNCACHEABLE SUBSELECT t1 system NULL NULL NULL NULL 0 const row not found
+EXPLAIN SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
+2 UNCACHEABLE SUBSELECT t1 system NULL NULL NULL NULL 0 const row not found
+EXPLAIN SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
+2 UNCACHEABLE SUBSELECT t1 system NULL NULL NULL NULL 0 const row not found
+drop table t1;
+CREATE TABLE `t1` (
+`mot` varchar(30) character set latin1 NOT NULL default '',
+`topic` mediumint(8) unsigned NOT NULL default '0',
+`date` date NOT NULL default '0000-00-00',
+`pseudo` varchar(35) character set latin1 NOT NULL default '',
+PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
+KEY `pseudo` (`pseudo`,`date`,`topic`),
+KEY `topic` (`topic`)
+) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
+CREATE TABLE `t2` (
+`mot` varchar(30) character set latin1 NOT NULL default '',
+`topic` mediumint(8) unsigned NOT NULL default '0',
+`date` date NOT NULL default '0000-00-00',
+`pseudo` varchar(35) character set latin1 NOT NULL default '',
+PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
+KEY `pseudo` (`pseudo`,`date`,`topic`),
+KEY `topic` (`topic`)
+) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
+CREATE TABLE `t3` (
+`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
+`maxnumrep` int(10) unsigned NOT NULL default '0',
+PRIMARY KEY (`numeropost`),
+UNIQUE KEY `maxnumrep` (`maxnumrep`)
+) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t1 VALUES ('joce','1','','joce'),('test','2','','test');
+INSERT INTO t2 VALUES ('joce','1','','joce'),('test','2','','test');
+INSERT INTO t3 VALUES (1,1);
+SELECT DISTINCT topic FROM t2 WHERE NOT EXISTS(SELECT * FROM t3 WHERE
+numeropost=topic);
+topic
+2
+select * from t1;
+mot topic date pseudo
+joce 1 0000-00-00 joce
+test 2 0000-00-00 test
+DELETE FROM t1 WHERE topic IN (SELECT DISTINCT topic FROM t2 WHERE NOT
+EXISTS(SELECT * FROM t3 WHERE numeropost=topic));
+select * from t1;
+mot topic date pseudo
+joce 1 0000-00-00 joce
+drop table t1, t2, t3;
+SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
+a (SELECT a)
+1 1
+CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT 1)) a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(1) NOT NULL default '0',
+ `(SELECT 1)` bigint(1) NOT NULL default '0'
+) TYPE=MyISAM CHARSET=latin1
+drop table t1;
+CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(1) NOT NULL default '0',
+ `(SELECT a)` bigint(1) NOT NULL default '0'
+) TYPE=MyISAM CHARSET=latin1
+drop table t1;
+CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(1) NOT NULL default '0',
+ `(SELECT a+0)` bigint(17) NOT NULL default '0'
+) TYPE=MyISAM CHARSET=latin1
+drop table t1;
+CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(17) NOT NULL default '0'
+) TYPE=MyISAM CHARSET=latin1
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+explain select a,(select (select rand() from t1 limit 1) from t1 limit 1)
+from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 UNCACHEABLE SUBSELECT t1 ALL NULL NULL NULL NULL 3
+3 UNCACHEABLE SUBSELECT t1 ALL NULL NULL NULL NULL 3
+drop table t1;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 5626bc0fe11..1eb595eb2a9 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -36,10 +36,10 @@ show create table t9;
Table Create Table
t9 CREATE TABLE `t9` (
`a` int(11) NOT NULL auto_increment,
- `b` char(16) NOT NULL default '',
+ `b` char(16) character set latin1 NOT NULL default '',
`c` int(11) NOT NULL default '0',
PRIMARY KEY (`a`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
alter table t9 rename t8, add column d int not null;
alter table t8 rename t7;
rename table t7 to t9;
@@ -57,9 +57,9 @@ show create table test_mysqltest.t9;
Table Create Table
t9 CREATE TABLE `t9` (
`a` int(11) NOT NULL auto_increment,
- `b` char(16) NOT NULL default '',
+ `b` char(16) character set latin1 NOT NULL default '',
`c` int(11) NOT NULL default '0',
`d` int(11) NOT NULL default '0',
PRIMARY KEY (`a`)
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop database test_mysqltest;
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 7c8d10cf0a6..5568e5b25d8 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -48,7 +48,6 @@ c d e
3 b 2
drop table t1;
drop table t1;
-drop table if exists t1;
CREATE TABLE t1 (pkCrash INTEGER PRIMARY KEY,strCrash VARCHAR(255));
INSERT INTO t1 ( pkCrash, strCrash ) VALUES ( 1, '1');
SELECT CONCAT_WS(pkCrash, strCrash) FROM t1;
@@ -77,7 +76,6 @@ insert into t1 values (1),(1);
alter table t1 add primary key (a);
Duplicate entry '1' for key 1
drop table t1;
-drop table if exists t1;
CREATE TABLE t1 (
d datetime default NULL
) TYPE=MyISAM;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 2047eed6227..ba8e01d6319 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -1,4 +1,36 @@
drop table if exists t1,t2,t3,t4,t5,t6,t7;
+CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
+show columns from t1;
+Field Type Collation Null Key Default Extra
+a blob binary YES NULL
+b text latin1 YES NULL
+c blob binary YES NULL
+d mediumtext latin1 YES NULL
+e longtext latin1 YES NULL
+CREATE TABLE t2 (a char(257), b varchar(70000) binary, c varchar(70000000));
+Warnings:
+Warning 1244 Converting column 'a' from CHAR to TEXT
+Warning 1244 Converting column 'b' from CHAR to BLOB
+Warning 1244 Converting column 'c' from CHAR to TEXT
+show columns from t2;
+Field Type Collation Null Key Default Extra
+a text latin1 YES NULL
+b mediumblob binary YES NULL
+c longtext latin1 YES NULL
+create table t3 (a long, b long byte);
+show create TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` mediumtext,
+ `b` mediumblob
+) TYPE=MyISAM CHARSET=latin1
+drop table t1,t2,t3
+#;
+CREATE TABLE t1 (a char(257) default "hello");
+Too big column length for column 'a' (max = 255). Use BLOB instead
+CREATE TABLE t2 (a blob default "hello");
+BLOB column 'a' can't have a default value
+drop table if exists t1,t2;
create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
insert into t1 values (null,"a","A");
insert into t1 values (null,"bbb","BBB");
@@ -37,18 +69,18 @@ insert into t1 values (NULL,NULL,NULL,NULL);
update t1 set c="",b=null where c="1";
lock tables t1 READ;
show full fields from t1;
-Field Type Null Key Default Extra Privileges
-t text YES NULL select,insert,update,references
-c varchar(10) YES NULL select,insert,update,references
-b blob YES NULL select,insert,update,references
-d varchar(10) binary YES NULL select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+t text latin1 YES NULL select,insert,update,references
+c varchar(10) latin1 YES NULL select,insert,update,references
+b blob binary YES NULL select,insert,update,references
+d varchar(10) binary binary YES NULL select,insert,update,references
lock tables t1 WRITE;
show full fields from t1;
-Field Type Null Key Default Extra Privileges
-t text YES NULL select,insert,update,references
-c varchar(10) YES NULL select,insert,update,references
-b blob YES NULL select,insert,update,references
-d varchar(10) binary YES NULL select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+t text latin1 YES NULL select,insert,update,references
+c varchar(10) latin1 YES NULL select,insert,update,references
+b blob binary YES NULL select,insert,update,references
+d varchar(10) binary binary YES NULL select,insert,update,references
unlock tables;
select t from t1 where t like "hello";
t
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 214328eab47..cf6533eef67 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t2;
create table t1 (a char(16), b date, c datetime);
insert into t1 SET a='test 2000-01-01', b='2000-01-01', c='2000-01-01';
select * from t1 where c = '2000-01-01';
@@ -7,7 +8,6 @@ select * from t1 where b = '2000-01-01';
a b c
test 2000-01-01 2000-01-01 2000-01-01 00:00:00
drop table t1;
-drop table if exists t1,t2;
CREATE TABLE t1 (name char(6),cdate date);
INSERT INTO t1 VALUES ('name1','1998-01-01');
INSERT INTO t1 VALUES ('name2','1998-01-01');
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 38b264b96b9..cac8cd3d71e 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -41,8 +41,8 @@ t
drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
insert into t1 (b,c,d) values(now(),curtime(),now());
-select date_format(a,"%Y-%m-%d")=b,right(a,6)=c+0,a=d+0 from t1;
-date_format(a,"%Y-%m-%d")=b right(a,6)=c+0 a=d+0
+select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1;
+date_format(a,"%Y-%m-%d")=b right(a+0,6)=c+0 a=d+0
1 1 1
drop table t1;
CREATE TABLE t1 (a datetime not null);
@@ -75,6 +75,6 @@ date numfacture expedition
0000-00-00 00:00:00 0 0001-00-00 00:00:00
0000-00-00 00:00:00 1212 0001-00-00 00:00:00
EXPLAIN SELECT * FROM t1 WHERE expedition='0001-00-00 00:00:00';
-table type possible_keys key key_len ref rows Extra
-t1 ref expedition expedition 8 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref expedition expedition 8 const 1 Using where
drop table t1;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index ee3bd077798..c0f0be246c9 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1627,12 +1627,12 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default ''
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
create table t1 (a enum (' ','a','b ') not null default 'b ');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default 'b'
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index e85bced353a..3914114d92c 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
SELECT 10,10.0,10.,.1e+2,100.0e-1;
10 10.0 10. .1e+2 100.0e-1
10 10.0 10 10 10
@@ -7,12 +8,11 @@ SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
1e1 1.e1 1.0e1 1e+1 1.e+1 1.0e+1 1e-1 1.e-1 1.0e-1
10 10 10 10 10 10 0.1 0.1 0.1
-drop table if exists t1;
create table t1 (f1 float(24),f2 float(52));
show full columns from t1;
-Field Type Null Key Default Extra Privileges
-f1 float YES NULL select,insert,update,references
-f2 double YES NULL select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+f1 float binary YES NULL select,insert,update,references
+f2 double binary YES NULL select,insert,update,references
insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150);
insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150);
select * from t1;
@@ -69,19 +69,19 @@ min(a)
drop table t1;
create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6));
show full columns from t1;
-Field Type Null Key Default Extra Privileges
-f float YES NULL select,insert,update,references
-f2 float YES NULL select,insert,update,references
-f3 float(6,2) YES NULL select,insert,update,references
-d double YES NULL select,insert,update,references
-d2 double YES NULL select,insert,update,references
-d3 double(10,3) YES NULL select,insert,update,references
-de decimal(10,0) YES NULL select,insert,update,references
-de2 decimal(6,0) YES NULL select,insert,update,references
-de3 decimal(5,2) YES NULL select,insert,update,references
-n decimal(10,0) YES NULL select,insert,update,references
-n2 decimal(8,0) YES NULL select,insert,update,references
-n3 decimal(7,6) YES NULL select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+f float binary YES NULL select,insert,update,references
+f2 float binary YES NULL select,insert,update,references
+f3 float(6,2) binary YES NULL select,insert,update,references
+d double binary YES NULL select,insert,update,references
+d2 double binary YES NULL select,insert,update,references
+d3 double(10,3) binary YES NULL select,insert,update,references
+de decimal(10,0) binary YES NULL select,insert,update,references
+de2 decimal(6,0) binary YES NULL select,insert,update,references
+de3 decimal(5,2) binary YES NULL select,insert,update,references
+n decimal(10,0) binary YES NULL select,insert,update,references
+n2 decimal(8,0) binary YES NULL select,insert,update,references
+n3 decimal(7,6) binary YES NULL select,insert,update,references
drop table t1;
create table t1 (a decimal(7,3) not null, key (a));
insert into t1 values ("0"),("-0.00"),("-0.01"),("-0.002"),("1");
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index fc7cc5255cf..8215977ea39 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -38,31 +38,31 @@ KEY (ulonglong,ulong),
KEY (options,flags)
);
show full fields from t1;
-Field Type Null Key Default Extra Privileges
-auto int(5) unsigned PRI NULL auto_increment select,insert,update,references
-string varchar(10) YES hello select,insert,update,references
-tiny tinyint(4) MUL 0 select,insert,update,references
-short smallint(6) MUL 1 select,insert,update,references
-medium mediumint(8) MUL 0 select,insert,update,references
-long_int int(11) 0 select,insert,update,references
-longlong bigint(13) MUL 0 select,insert,update,references
-real_float float(13,1) MUL 0.0 select,insert,update,references
-real_double double(16,4) YES NULL select,insert,update,references
-utiny tinyint(3) unsigned MUL 0 select,insert,update,references
-ushort smallint(5) unsigned zerofill MUL 00000 select,insert,update,references
-umedium mediumint(8) unsigned MUL 0 select,insert,update,references
-ulong int(11) unsigned MUL 0 select,insert,update,references
-ulonglong bigint(13) unsigned MUL 0 select,insert,update,references
-time_stamp timestamp(14) YES NULL select,insert,update,references
-date_field date YES NULL select,insert,update,references
-time_field time YES NULL select,insert,update,references
-date_time datetime YES NULL select,insert,update,references
-blob_col blob YES NULL select,insert,update,references
-tinyblob_col tinyblob YES NULL select,insert,update,references
-mediumblob_col mediumblob select,insert,update,references
-longblob_col longblob select,insert,update,references
-options enum('one','two','tree') MUL one select,insert,update,references
-flags set('one','two','tree') select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(5) unsigned binary PRI NULL auto_increment select,insert,update,references
+string varchar(10) latin1 YES hello select,insert,update,references
+tiny tinyint(4) binary MUL 0 select,insert,update,references
+short smallint(6) binary MUL 1 select,insert,update,references
+medium mediumint(8) binary MUL 0 select,insert,update,references
+long_int int(11) binary 0 select,insert,update,references
+longlong bigint(13) binary MUL 0 select,insert,update,references
+real_float float(13,1) binary MUL 0.0 select,insert,update,references
+real_double double(16,4) binary YES NULL select,insert,update,references
+utiny tinyint(3) unsigned binary MUL 0 select,insert,update,references
+ushort smallint(5) unsigned zerofill binary MUL 00000 select,insert,update,references
+umedium mediumint(8) unsigned binary MUL 0 select,insert,update,references
+ulong int(11) unsigned binary MUL 0 select,insert,update,references
+ulonglong bigint(13) unsigned binary MUL 0 select,insert,update,references
+time_stamp timestamp latin1 YES NULL select,insert,update,references
+date_field date latin1 YES NULL select,insert,update,references
+time_field time latin1 YES NULL select,insert,update,references
+date_time datetime latin1 YES NULL select,insert,update,references
+blob_col blob binary YES NULL select,insert,update,references
+tinyblob_col tinyblob binary YES NULL select,insert,update,references
+mediumblob_col mediumblob binary select,insert,update,references
+longblob_col longblob binary select,insert,update,references
+options enum('one','two','tree') latin1 MUL one select,insert,update,references
+flags set('one','two','tree') latin1 select,insert,update,references
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 auto A 0 NULL NULL BTREE
@@ -85,7 +85,7 @@ CREATE INDEX test3 on t1 ( medium ) ;
DROP INDEX test ON t1;
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
-insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
+insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
@@ -168,57 +168,57 @@ drop table t2;
create table t2 select * from t1;
update t2 set string="changed" where auto=16;
show full columns from t1;
-Field Type Null Key Default Extra Privileges
-auto int(5) unsigned MUL NULL auto_increment select,insert,update,references
-string varchar(10) YES new defaul select,insert,update,references
-tiny tinyint(4) MUL 0 select,insert,update,references
-short smallint(6) MUL 0 select,insert,update,references
-medium mediumint(8) MUL 0 select,insert,update,references
-long_int int(11) 0 select,insert,update,references
-longlong bigint(13) MUL 0 select,insert,update,references
-real_float float(13,1) MUL 0.0 select,insert,update,references
-real_double double(16,4) YES NULL select,insert,update,references
-utiny tinyint(3) unsigned 0 select,insert,update,references
-ushort smallint(5) unsigned zerofill 00000 select,insert,update,references
-umedium mediumint(8) unsigned MUL 0 select,insert,update,references
-ulong int(11) unsigned MUL 0 select,insert,update,references
-ulonglong bigint(13) unsigned MUL 0 select,insert,update,references
-time_stamp timestamp(14) YES NULL select,insert,update,references
-date_field varchar(10) YES NULL select,insert,update,references
-time_field time YES NULL select,insert,update,references
-date_time datetime YES NULL select,insert,update,references
-new_blob_col varchar(20) YES NULL select,insert,update,references
-tinyblob_col tinyblob YES NULL select,insert,update,references
-mediumblob_col mediumblob select,insert,update,references
-options enum('one','two','tree') MUL one select,insert,update,references
-flags set('one','two','tree') select,insert,update,references
-new_field varchar(10) new select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(5) unsigned binary MUL NULL auto_increment select,insert,update,references
+string varchar(10) latin1 YES new defaul select,insert,update,references
+tiny tinyint(4) binary MUL 0 select,insert,update,references
+short smallint(6) binary MUL 0 select,insert,update,references
+medium mediumint(8) binary MUL 0 select,insert,update,references
+long_int int(11) binary 0 select,insert,update,references
+longlong bigint(13) binary MUL 0 select,insert,update,references
+real_float float(13,1) binary MUL 0.0 select,insert,update,references
+real_double double(16,4) binary YES NULL select,insert,update,references
+utiny tinyint(3) unsigned binary 0 select,insert,update,references
+ushort smallint(5) unsigned zerofill binary 00000 select,insert,update,references
+umedium mediumint(8) unsigned binary MUL 0 select,insert,update,references
+ulong int(11) unsigned binary MUL 0 select,insert,update,references
+ulonglong bigint(13) unsigned binary MUL 0 select,insert,update,references
+time_stamp timestamp latin1 YES NULL select,insert,update,references
+date_field varchar(10) latin1 YES NULL select,insert,update,references
+time_field time latin1 YES NULL select,insert,update,references
+date_time datetime latin1 YES NULL select,insert,update,references
+new_blob_col varchar(20) latin1 YES NULL select,insert,update,references
+tinyblob_col tinyblob binary YES NULL select,insert,update,references
+mediumblob_col mediumblob binary select,insert,update,references
+options enum('one','two','tree') latin1 MUL one select,insert,update,references
+flags set('one','two','tree') latin1 select,insert,update,references
+new_field varchar(10) latin1 new select,insert,update,references
show full columns from t2;
-Field Type Null Key Default Extra Privileges
-auto int(5) unsigned 0 select,insert,update,references
-string varchar(10) YES new defaul select,insert,update,references
-tiny tinyint(4) 0 select,insert,update,references
-short smallint(6) 0 select,insert,update,references
-medium mediumint(8) 0 select,insert,update,references
-long_int int(11) 0 select,insert,update,references
-longlong bigint(13) 0 select,insert,update,references
-real_float float(13,1) 0.0 select,insert,update,references
-real_double double(16,4) YES NULL select,insert,update,references
-utiny tinyint(3) unsigned 0 select,insert,update,references
-ushort smallint(5) unsigned zerofill 00000 select,insert,update,references
-umedium mediumint(8) unsigned 0 select,insert,update,references
-ulong int(11) unsigned 0 select,insert,update,references
-ulonglong bigint(13) unsigned 0 select,insert,update,references
-time_stamp timestamp(14) YES NULL select,insert,update,references
-date_field varchar(10) YES NULL select,insert,update,references
-time_field time YES NULL select,insert,update,references
-date_time datetime YES NULL select,insert,update,references
-new_blob_col varchar(20) YES NULL select,insert,update,references
-tinyblob_col tinyblob YES NULL select,insert,update,references
-mediumblob_col mediumblob select,insert,update,references
-options enum('one','two','tree') one select,insert,update,references
-flags set('one','two','tree') select,insert,update,references
-new_field varchar(10) new select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(5) unsigned binary 0 select,insert,update,references
+string varchar(10) latin1 YES new defaul select,insert,update,references
+tiny tinyint(4) binary 0 select,insert,update,references
+short smallint(6) binary 0 select,insert,update,references
+medium mediumint(8) binary 0 select,insert,update,references
+long_int int(11) binary 0 select,insert,update,references
+longlong bigint(13) binary 0 select,insert,update,references
+real_float float(13,1) binary 0.0 select,insert,update,references
+real_double double(16,4) binary YES NULL select,insert,update,references
+utiny tinyint(3) unsigned binary 0 select,insert,update,references
+ushort smallint(5) unsigned zerofill binary 00000 select,insert,update,references
+umedium mediumint(8) unsigned binary 0 select,insert,update,references
+ulong int(11) unsigned binary 0 select,insert,update,references
+ulonglong bigint(13) unsigned binary 0 select,insert,update,references
+time_stamp timestamp latin1 YES NULL select,insert,update,references
+date_field varchar(10) latin1 YES NULL select,insert,update,references
+time_field time latin1 YES NULL select,insert,update,references
+date_time datetime latin1 YES NULL select,insert,update,references
+new_blob_col varchar(20) latin1 YES NULL select,insert,update,references
+tinyblob_col tinyblob binary YES NULL select,insert,update,references
+mediumblob_col mediumblob binary select,insert,update,references
+options enum('one','two','tree') latin1 one select,insert,update,references
+flags set('one','two','tree') latin1 select,insert,update,references
+new_field varchar(10) latin1 new select,insert,update,references
select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null)));
auto auto
16 16
@@ -228,12 +228,12 @@ auto auto
drop table t2;
create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, "a" as t2, repeat("a",256) as t3, binary repeat("b",256) as t4 from t1;
show full columns from t2;
-Field Type Null Key Default Extra Privileges
-auto bigint(17) unsigned PRI 0 select,insert,update,references
-t1 bigint(1) 0 select,insert,update,references
-t2 char(1) select,insert,update,references
-t3 mediumtext select,insert,update,references
-t4 mediumblob select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+auto bigint(17) unsigned binary PRI 0 select,insert,update,references
+t1 bigint(1) binary 0 select,insert,update,references
+t2 char(1) latin1 select,insert,update,references
+t3 mediumtext latin1 select,insert,update,references
+t4 mediumblob binary select,insert,update,references
select * from t2;
auto t1 t2 t3 t4
11 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
@@ -251,10 +251,10 @@ create table t3 select * from t1, t2;
Duplicate column name 'c'
create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2;
show full columns from t3;
-Field Type Null Key Default Extra Privileges
-c1 int(11) YES NULL select,insert,update,references
-c2 int(11) YES NULL select,insert,update,references
-const bigint(1) 0 select,insert,update,references
+Field Type Collation Null Key Default Extra Privileges Comment
+c1 int(11) binary YES NULL select,insert,update,references
+c2 int(11) binary YES NULL select,insert,update,references
+const bigint(1) binary 0 select,insert,update,references
drop table t1,t2,t3;
create table t1 ( myfield INT NOT NULL, UNIQUE INDEX (myfield), unique (myfield), index(myfield));
drop table t1;
diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result
index 59f8744e2ec..b0ea1b69e59 100644
--- a/mysql-test/r/type_set.result
+++ b/mysql-test/r/type_set.result
@@ -4,12 +4,12 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default ''
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
create table t1 (a set (' ','a','b ') not null default 'b ');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` set('','a','b') NOT NULL default 'b'
-) TYPE=MyISAM
+) TYPE=MyISAM CHARSET=latin1
drop table t1;
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 088f3b205b9..26dedf544c4 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -15,26 +15,26 @@ SET TIMESTAMP=1238;
insert into t1 (a) select a+1 from t2 where a=8;
select * from t1;
a t
-1 19700101032034
-2 20020303000000
-3 19700101032035
-4 19700101032036
-5 20020304000000
-6 19700101032037
-7 20020305000000
-8 00000000000000
-9 19700101032038
+1 1970-01-01 03:20:34
+2 2002-03-03 00:00:00
+3 1970-01-01 03:20:35
+4 1970-01-01 03:20:36
+5 2002-03-04 00:00:00
+6 1970-01-01 03:20:37
+7 2002-03-05 00:00:00
+8 0000-00-00 00:00:00
+9 1970-01-01 03:20:38
drop table t1,t2;
SET TIMESTAMP=1234;
CREATE TABLE t1 (value TEXT NOT NULL, id VARCHAR(32) NOT NULL, stamp timestamp, PRIMARY KEY (id));
INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
SELECT stamp FROM t1 WHERE id="myKey";
stamp
-19990402000000
+1999-04-02 00:00:00
UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey";
stamp
-19990402000000
+1999-04-02 00:00:00
drop table t1;
create table t1 (a timestamp);
insert into t1 values (now());
@@ -44,8 +44,8 @@ date_format(a,"%Y %y") year(a) year(now())
drop table t1;
create table t1 (ix timestamp);
insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
-select * from t1;
-ix
+select ix+0 from t1;
+ix+0
19991101000000
19990102030405
19990630232922
@@ -71,16 +71,16 @@ INSERT INTO t1 VALUES ("2005-01-01","2005-01-01 00:00:00",20050101000000);
INSERT INTO t1 VALUES ("2030-01-01","2030-01-01 00:00:00",20300101000000);
SELECT * FROM t1;
date date_time time_stamp
-1998-12-31 1998-12-31 23:59:59 19981231235959
-1999-01-01 1999-01-01 00:00:00 19990101000000
-1999-09-09 1999-09-09 23:59:59 19990909235959
-2000-01-01 2000-01-01 00:00:00 20000101000000
-2000-02-28 2000-02-28 00:00:00 20000228000000
-2000-02-29 2000-02-29 00:00:00 20000229000000
-2000-03-01 2000-03-01 00:00:00 20000301000000
-2000-12-31 2000-12-31 23:59:59 20001231235959
-2001-01-01 2001-01-01 00:00:00 20010101000000
-2004-12-31 2004-12-31 23:59:59 20041231235959
-2005-01-01 2005-01-01 00:00:00 20050101000000
-2030-01-01 2030-01-01 00:00:00 20300101000000
+1998-12-31 1998-12-31 23:59:59 1998-12-31 23:59:59
+1999-01-01 1999-01-01 00:00:00 1999-01-01 00:00:00
+1999-09-09 1999-09-09 23:59:59 1999-09-09 23:59:59
+2000-01-01 2000-01-01 00:00:00 2000-01-01 00:00:00
+2000-02-28 2000-02-28 00:00:00 2000-02-28 00:00:00
+2000-02-29 2000-02-29 00:00:00 2000-02-29 00:00:00
+2000-03-01 2000-03-01 00:00:00 2000-03-01 00:00:00
+2000-12-31 2000-12-31 23:59:59 2000-12-31 23:59:59
+2001-01-01 2001-01-01 00:00:00 2001-01-01 00:00:00
+2004-12-31 2004-12-31 23:59:59 2004-12-31 23:59:59
+2005-01-01 2005-01-01 00:00:00 2005-01-01 00:00:00
+2030-01-01 2030-01-01 00:00:00 2030-01-01 00:00:00
drop table t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 2af9d5a3584..cb3a8029a87 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -84,37 +84,34 @@ a b
3 c
2 b
1 a
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
+Table 't1' from one of SELECT's can not be used in global ORDER clause
explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
-t2 ALL NULL NULL NULL NULL 4 Using filesort
-t1 ALL NULL NULL NULL NULL 4
-(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
-a b
-1 a
-2 b
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+2 UNION t2 ALL NULL NULL NULL NULL 4 Using filesort
select found_rows();
found_rows()
-6
+0
explain select a,b from t1 union all select a,b from t2;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
-t2 ALL NULL NULL NULL NULL 4
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+2 UNION t2 ALL NULL NULL NULL NULL 4
explain select xx from t1 union select 1;
Unknown column 'xx' in 'field list'
explain select a,b from t1 union select 1;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
- 0 0 No tables used
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+2 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
explain select 1 union select a,b from t1 union select 1;
-table type possible_keys key key_len ref rows Extra
- 0 0 No tables used
-t1 ALL NULL NULL NULL NULL 4
- 0 0 No tables used
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+2 UNION t1 ALL NULL NULL NULL NULL 4
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
explain select a,b from t1 union select 1 limit 0;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 4
- 0 0 Impossible WHERE
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 UNION NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select a,b from t1 into outfile 'skr' union select a,b from t2;
Wrong usage of UNION and INTO
select a,b from t1 order by a union select a,b from t2;
@@ -173,7 +170,6 @@ testtt
tsestset
1
drop table t1;
-drop table if exists t1,t2;
create table t1 (a int);
create table t2 (a int);
insert into t1 values (1),(2),(3),(4),(5);
@@ -202,3 +198,8 @@ a
11
set SQL_SELECT_LIMIT=DEFAULT;
drop table t1,t2;
+select * union select 1;
+No tables used
+select 1 as a,(select a union select a);
+a (select a union select a)
+1 1
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index ba5c1c6e28f..159b971440b 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
create table t1 (a int auto_increment , primary key (a));
insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
update t1 set a=a+10 where a > 34;
@@ -106,9 +106,12 @@ create table t1 (a int not null, b int not null);
insert into t1 values (1,1),(1,2),(1,3);
update t1 set b=4 where a=1 order by b asc limit 1;
update t1 set b=4 where a=1 order by b desc limit 1;
+create table t2 (a int not null, b int not null);
+insert into t2 values (1,1),(1,2),(1,3);
select * from t1;
a b
1 4
1 2
1 4
-drop table t1;
+update t1 set b=(select distinct 1 from (select * from t2) a);
+drop table t1,t2;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 5e9f3a720c2..6e3b9309351 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -1,10 +1,10 @@
+drop table if exists t1,t2;
set @a := foo;
Unknown column 'foo' in 'field list'
set @a := connection_id() + 3;
select @a - connection_id();
@a - connection_id()
3
-drop table if exists t1,t2;
CREATE TABLE t1 ( i int not null, v int not null,index (i));
insert into t1 values (1,1),(1,3),(2,1);
create table t2 (i int not null, unique (i));
@@ -18,15 +18,15 @@ i @vv1:=if(sv1.i,1,0) @vv2:=if(sv2.i,1,0) @vv3:=if(sv3.i,1,0) @vv1+@vv2+@vv3
1 1 0 1 2
2 1 0 0 1
explain select * from t1 where i=@vv1;
-table type possible_keys key key_len ref rows Extra
-t1 ref i i 4 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref i i 4 const 1 Using where
explain select * from t1 where @vv1:=@vv1+1 and i=@vv1;
-table type possible_keys key key_len ref rows Extra
-t1 ALL NULL NULL NULL NULL 3 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
explain select @vv1:=i from t1 where i=@vv1;
-table type possible_keys key key_len ref rows Extra
-t1 index NULL i 4 NULL 3 Using where; Using index
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL i 4 NULL 3 Using where; Using index
explain select * from t1 where i=@vv1;
-table type possible_keys key key_len ref rows Extra
-t1 ref i i 4 const 1 Using where
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref i i 4 const 1 Using where
drop table t1,t2;
diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result
index 4eb34ebfd63..2d04da31caa 100644
--- a/mysql-test/r/varbinary.result
+++ b/mysql-test/r/varbinary.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
select 0x41,0x41+0,0x41 | 0x7fffffffffffffff | 0,0xffffffffffffffff | 0 ;
0x41 0x41+0 0x41 | 0x7fffffffffffffff | 0 0xffffffffffffffff | 0
A 65 9223372036854775807 18446744073709551615
@@ -7,13 +8,12 @@ select 0x31+1,concat(0x31)+1,-0xf;
select x'31',X'ffff'+0;
x'31' X'ffff'+0
1 65535
-drop table if exists t1;
create table t1 (ID int(8) unsigned zerofill not null auto_increment,UNIQ bigint(21) unsigned zerofill not null,primary key (ID),unique (UNIQ) );
insert into t1 set UNIQ=0x38afba1d73e6a18a;
insert into t1 set UNIQ=123;
explain select * from t1 where UNIQ=0x38afba1d73e6a18a;
-table type possible_keys key key_len ref rows Extra
-t1 const UNIQ UNIQ 8 const 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const UNIQ UNIQ 8 const 1
drop table t1;
select x'hello';
You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index ed477a8519b..b66d75e2b3a 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
set @`test`=1,@TEST=3,@select=2,@t5=1.23456;
select @test,@`select`,@TEST,@not_used;
@test @`select` @TEST @not_used
@@ -315,7 +315,6 @@ set tmp_table_size=100;
set tx_isolation="READ-COMMITTED";
set wait_timeout=100;
set log_warnings=1;
-DROP TABLE IF EXISTS t1,t2;
create table t1 (a int not null auto_increment, primary key(a));
create table t2 (a int not null auto_increment, primary key(a));
insert into t1 values(null),(null),(null);
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index e5713718db0..f2a105827da 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -1,4 +1,6 @@
drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
create table t1 (a int);
insert into t1 values (1);
insert into t1 values ("hej");
@@ -8,3 +10,23 @@ insert into t1 values ("hej");
insert into t1 values ("hej"),("då");
drop table t1;
set SQL_WARNINGS=0;
+drop temporary table if exists not_exists;
+Warnings:
+Note 1051 Unknown table 'not_exists'
+drop table if exists not_exists_table;
+Warnings:
+Note 1051 Unknown table 'not_exists_table'
+show warnings limit 1;
+Level Code Message
+Note 1051 Unknown table 'not_exists_table'
+drop database if exists not_exists_db;
+Warnings:
+Note 1008 Can't drop database 'not_exists_db'. Database doesn't exist
+show count(*) warnings;
+@@session.warning_count
+1
+create table t1(id int);
+create table if not exists t1(id int);
+select @@warning_count;
+@@warning_count
+0
diff --git a/mysql-test/std_data/master-bin.001 b/mysql-test/std_data/master-bin.000001
index 2ec2397acdd..2ec2397acdd 100644
--- a/mysql-test/std_data/master-bin.001
+++ b/mysql-test/std_data/master-bin.000001
Binary files differ
diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test
index 5c6813d93aa..64dd481d37d 100644
--- a/mysql-test/t/alias.test
+++ b/mysql-test/t/alias.test
@@ -1,4 +1,7 @@
+--disable_warnings
DROP TABLE IF EXISTS t1;
+--enable_warnings
+
CREATE TABLE t1 (
cont_nr int(11) NOT NULL auto_increment,
ver_nr int(11) NOT NULL default '0',
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 1c3987e2a31..64b657f1146 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -1,8 +1,10 @@
#
# Test of alter table
#
-
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (
col1 int not null auto_increment primary key,
col2 varchar(30) not null,
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index 3f56b3e47ce..117ca40ce54 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -2,10 +2,15 @@
# Test of procedure analyse
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
create table t1 (i int, j int);
insert into t1 values (1,2), (3,4), (5,6), (7,8);
+select count(*) from t1 procedure analyse();
select * from t1 procedure analyse();
create table t2 select * from t1 procedure analyse();
select * from t2;
drop table t1,t2;
+
+EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index d86466572d8..30979202bd7 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -1,8 +1,10 @@
#
# Test of auto_increment; The test for BDB tables is in bdb.test
#
-
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a int not null auto_increment,b int, primary key (a)) type=myisam auto_increment=3;
insert into t1 values (1,1),(NULL,3),(NULL,4);
delete from t1 where a=4;
diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test
index 55fe140850d..02ef72ef66d 100644
--- a/mysql-test/t/backup.test
+++ b/mysql-test/t/backup.test
@@ -2,7 +2,9 @@ connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
set SQL_LOG_BIN=0;
-drop table if exists t1;
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
create table t1(n int);
--replace_result "errno = 1" "errno = X" "errno = 2" "errno = X" "errno = 22" "errno = X" "errno = 23" "errno = X"
backup table t1 to '../bogus';
diff --git a/mysql-test/t/bdb-alter-table-1.test b/mysql-test/t/bdb-alter-table-1.test
index 5861c2fe0bf..7537cc358e8 100644
--- a/mysql-test/t/bdb-alter-table-1.test
+++ b/mysql-test/t/bdb-alter-table-1.test
@@ -2,7 +2,10 @@
# Test of problem when shutting down mysqld at once after ALTER TABLE
#
-- source include/have_bdb.inc
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1(objid BIGINT not null, tablename varchar(64), oid BIGINT not null, test BIGINT, PRIMARY KEY (objid), UNIQUE(tablename)) type=BDB;
insert into t1 values(1, 't1',4,9);
insert into t1 values(2, 'metatable',1,9);
diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test
index 0005b631a46..956645b1188 100644
--- a/mysql-test/t/bdb-crash.test
+++ b/mysql-test/t/bdb-crash.test
@@ -2,7 +2,9 @@
# test for bug reported by Mark Steele
+--disable_warnings
drop table if exists t1;
+--enable_warnings
CREATE TABLE t1 (
ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
ServiceID int(10) unsigned DEFAULT '0' NOT NULL,
diff --git a/mysql-test/t/bdb-deadlock.test b/mysql-test/t/bdb-deadlock.test
index b32b50c715b..2453c42e49a 100644
--- a/mysql-test/t/bdb-deadlock.test
+++ b/mysql-test/t/bdb-deadlock.test
@@ -11,7 +11,9 @@
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
connection con1;
create table t1 (id integer, x integer) type=BDB;
create table t2 (id integer, x integer) type=BDB;
@@ -30,13 +32,19 @@ select x from t1 where id = 0;
connection con1;
# This should generate a deadlock as we are trying to access a locked row
---error 1213
+--send
select x from t2 where id = 0;
-commit;
connection con2;
+--error 1213
reap;
commit;
+
+connection con1;
+reap;
+commit;
+
+connection con2;
select * from t1;
select * from t2;
commit;
@@ -45,4 +53,5 @@ connection con1;
select * from t1;
select * from t2;
commit;
+
drop table t1,t2;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 608d4bf5042..27755e51b7f 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -4,7 +4,9 @@
# Small basic test with ignore
#
+--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
+--enable_warnings
create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=bdb;
insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
@@ -441,7 +443,6 @@ drop table t1;
# This gave a wrong result because the row information was freed too early
#
-drop table if exists t1, t2, t3, t4, t5, t6, t7;
create table t1
(
branch_id int auto_increment primary key,
@@ -451,7 +452,6 @@ create table t1
unique branch_name(branch_name),
index branch_active(branch_active)
) type=bdb;
-drop table if exists t2 ;
create table t2
(
target_id int auto_increment primary key,
@@ -461,7 +461,6 @@ create table t2
unique target_name(target_name),
index target_active(target_active)
) type=bdb;
-drop table if exists t3 ;
create table t3
(
platform_id int auto_increment primary key,
@@ -471,7 +470,6 @@ create table t3
unique platform_name(platform_name),
index platform_active(platform_active)
) type=bdb;
-drop table if exists t4 ;
create table t4
(
product_id int auto_increment primary key,
@@ -482,7 +480,6 @@ create table t4
unique product_name(product_name),
index product_active(product_active)
) type=bdb;
-drop table if exists t5 ;
create table t5
(
product_file_id int auto_increment primary key,
@@ -496,7 +493,6 @@ create table t5
unique product_file(product_id,file_name),
index file_included(file_included)
) type=bdb;
-drop table if exists t6 ;
create table t6
(
file_platform_id int auto_increment primary key,
@@ -510,7 +506,6 @@ create table t6
unique file_platform(product_file_id,platform_id,branch_id)
) type=bdb;
-drop table if exists t8 ;
create table t8
(
archive_id int auto_increment primary key,
@@ -523,7 +518,6 @@ create table t8
unique archive(branch_id,target_id,platform_id,product_id),
index status_id(status_id)
) type=bdb;
-drop table if exists t7 ;
create table t7
(
build_id int auto_increment primary key,
@@ -727,7 +721,6 @@ DROP TABLE t1,t2;
# Test problem with joining table to itself on a multi-part unique key
#
-drop table if exists t1;
create table t1 (a int(11) not null, b int(11) not null, unique (a,b)) type=bdb;
insert into t1 values (1,1), (1,2);
select * from t1 where a = 1;
diff --git a/mysql-test/t/bdb_cache.test b/mysql-test/t/bdb_cache.test
index aa5572886c5..0d7de75ccf6 100644
--- a/mysql-test/t/bdb_cache.test
+++ b/mysql-test/t/bdb_cache.test
@@ -4,7 +4,9 @@
#
# Without auto_commit.
#
+--disable_warnings
drop table if exists t1, t2, t3;
+--enable_warnings
flush status;
set autocommit=0;
create table t1 (a int not null) type=bdb;
@@ -47,4 +49,5 @@ select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
commit;
-show status like "Qcache_queries_in_cache"; \ No newline at end of file
+show status like "Qcache_queries_in_cache";
+drop table if exists t1, t2, t3;
diff --git a/mysql-test/t/bench_count_distinct.test b/mysql-test/t/bench_count_distinct.test
index 9059428bea4..c1adeab2c44 100644
--- a/mysql-test/t/bench_count_distinct.test
+++ b/mysql-test/t/bench_count_distinct.test
@@ -1,4 +1,10 @@
+#
+# Test of count(distinct ..)
+#
+
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1(n int not null, key(n)) delay_key_write = 1;
let $1=100;
disable_query_log;
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index 023e50b7677..f627614c049 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -1,4 +1,11 @@
#
+# Initialize
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
# Test of reading of bigint values
#
select 0,256,00000000000000065536,2147483647,-2147483648,2147483648,+4294967296;
@@ -11,7 +18,6 @@ select 9223372036854775808+1;
# This will work on 4.0 as we then have internal handling of bigint variables.
#
-drop table if exists t1;
create table t1 (a bigint unsigned not null, primary key(a));
insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE);
select * from t1;
diff --git a/mysql-test/t/binary.test b/mysql-test/t/binary.test
index 95815cda60f..4f9ac7581d2 100644
--- a/mysql-test/t/binary.test
+++ b/mysql-test/t/binary.test
@@ -1,8 +1,10 @@
#
# test sort,min and max on binary fields
#
-
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (name char(20) not null, primary key (name));
create table t2 (name char(20) binary not null, primary key (name));
insert into t1 values ("å");
diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test
index 10f97fefb73..c001973baeb 100644
--- a/mysql-test/t/bool.test
+++ b/mysql-test/t/bool.test
@@ -2,7 +2,9 @@
# Test of boolean operations with NULL
#
+--disable_warnings
DROP TABLE IF EXISTS t1;
+--enable_warnings
SELECT IF(NULL AND 1, 1, 2), IF(1 AND NULL, 1, 2);
SELECT NULL AND 1, 1 AND NULL, 0 AND NULL, NULL and 0;
@@ -33,19 +35,17 @@ DROP TABLE t1;
# Read nA as !A, AB as A && B, AoB as A || B
# Result table makes ANSI happy
-drop table if exists t;
-create table t(a int, b int);
-insert into t values(null, null), (0, null), (1, null), (null, 0), (null, 1), (0, 0), (0, 1), (1, 0), (1, 1);
+create table t1 (a int, b int);
+insert into t1 values(null, null), (0, null), (1, null), (null, 0), (null, 1), (0, 0), (0, 1), (1, 0), (1, 1);
# Below test is valid untill we have True/False implemented as 1/0
# To comply to all rules it must show that: n(AB) = nAonB, n(AoB) = nAnB
-select ifnull(A, 'N') as A, ifnull(B, 'N') as B, ifnull(not A, 'N') as nA, ifnull(not B, 'N') as nB, ifnull(A and B, 'N') as AB, ifnull(not (A and B), 'N') as `n(AB)`, ifnull((not A or not B), 'N') as nAonB, ifnull(A or B, 'N') as AoB, ifnull(not(A or B), 'N') as `n(AoB)`, ifnull(not A and not B, 'N') as nAnB from t;
+select ifnull(A, 'N') as A, ifnull(B, 'N') as B, ifnull(not A, 'N') as nA, ifnull(not B, 'N') as nB, ifnull(A and B, 'N') as AB, ifnull(not (A and B), 'N') as `n(AB)`, ifnull((not A or not B), 'N') as nAonB, ifnull(A or B, 'N') as AoB, ifnull(not(A or B), 'N') as `n(AoB)`, ifnull(not A and not B, 'N') as nAnB from t1;
# This should work with any internal representation of True/False
# Result must be same as above
-select ifnull(A=1, 'N') as A, ifnull(B=1, 'N') as B, ifnull(not (A=1), 'N') as nA, ifnull(not (B=1), 'N') as nB, ifnull((A=1) and (B=1), 'N') as AB, ifnull(not ((A=1) and (B=1)), 'N') as `n(AB)`, ifnull((not (A=1) or not (B=1)), 'N') as nAonB, ifnull((A=1) or (B=1), 'N') as AoB, ifnull(not((A=1) or (B=1)), 'N') as `n(AoB)`, ifnull(not (A=1) and not (B=1), 'N') as nAnB from t;
+select ifnull(A=1, 'N') as A, ifnull(B=1, 'N') as B, ifnull(not (A=1), 'N') as nA, ifnull(not (B=1), 'N') as nB, ifnull((A=1) and (B=1), 'N') as AB, ifnull(not ((A=1) and (B=1)), 'N') as `n(AB)`, ifnull((not (A=1) or not (B=1)), 'N') as nAonB, ifnull((A=1) or (B=1), 'N') as AoB, ifnull(not((A=1) or (B=1)), 'N') as `n(AoB)`, ifnull(not (A=1) and not (B=1), 'N') as nAnB from t1;
-
-drop table t;
+drop table t1;
diff --git a/mysql-test/t/bulk_replace.test b/mysql-test/t/bulk_replace.test
index d366004c16f..755d34083f8 100644
--- a/mysql-test/t/bulk_replace.test
+++ b/mysql-test/t/bulk_replace.test
@@ -1,11 +1,10 @@
#
# this is a test of bulk-insert code
-# as used by REPLACE
-#
-# by Monty
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
CREATE TABLE t1 (a int, unique (a), b int not null, unique(b), c int not null, index(c));
replace into t1 values (1,1,1),(2,2,2),(3,1,3);
select * from t1;
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index 3ba3a292c77..6131d1500de 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -2,7 +2,9 @@
# Testing of CASE
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
select CASE "b" when "a" then 1 when "b" then 2 END;
select CASE "c" when "a" then 1 when "b" then 2 END;
diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test
index 947566e725b..bc61aea2d66 100644
--- a/mysql-test/t/check.test
+++ b/mysql-test/t/check.test
@@ -1,8 +1,11 @@
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
+--disable_warnings
drop table if exists t1;
-#add a lot of keys to slow down check
+--enable_warnings
+
+# Add a lot of keys to slow down check
create table t1(n int not null, key(n), key(n), key(n), key(n));
let $1=10000;
disable_query_log;
diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test
index 450d9c0961c..e5a2e310866 100644
--- a/mysql-test/t/compare.test
+++ b/mysql-test/t/compare.test
@@ -2,7 +2,10 @@
# Bug when using comparions of strings and integers.
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
CREATE TABLE t1 (id CHAR(12) not null, PRIMARY KEY (id));
insert into t1 values ('000000000001'),('000000000002');
explain select * from t1 where id=000000000001;
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
new file mode 100644
index 00000000000..7b441ee5f7b
--- /dev/null
+++ b/mysql-test/t/connect.test
@@ -0,0 +1,64 @@
+# This test is to check various cases of connections
+# with right and wrong password, with and without database
+# Unfortunately the check is incomplete as we can't handle errors on connect
+# Also we can't connect without database
+
+#connect (con1,localhost,root,,"");
+#show tables;
+connect (con1,localhost,root,,mysql);
+show tables;
+connect (con1,localhost,root,,test);
+show tables;
+
+# Re enable this one day if error handling on connect will take place
+
+#connect (con1,localhost,root,z,test2);
+#--error 1045
+#connect (con1,localhost,root,z,);
+#--error 1045
+
+grant ALL on *.* to test@localhost identified by "gambling";
+grant ALL on *.* to test@127.0.0.1 identified by "gambling";
+
+# Now check this user with different databases
+
+#connect (con1,localhost,test,gambling,"");
+#show tables;
+connect (con1,localhost,test,gambling,mysql);
+show tables;
+connect (con1,localhost,test,gambling,test);
+show tables;
+
+# Re enable this one day if error handling on connect will take place
+
+#connect (con1,localhost,test,,test2);
+#--error 1045
+#connect (con1,localhost,test,,"");
+#--error 1045
+#connect (con1,localhost,test,zorro,test2);
+#--error 1045
+#connect (con1,localhost,test,zorro,);
+#--error 1045
+
+
+# check if old password version also works
+update mysql.user set password=old_password("gambling2") where user="test";
+flush privileges;
+
+#connect (con1,localhost,test,gambling2,"");
+#show tables;
+connect (con1,localhost,test,gambling2,mysql);
+show tables;
+connect (con1,localhost,test,gambling2,test);
+show tables;
+
+# Re enable this one day if error handling on connect will take place
+
+#connect (con1,localhost,test,,test2);
+#--error 1045
+#connect (con1,localhost,test,,);
+#--error 1045
+#connect (con1,localhost,test,zorro,test2);
+#--error 1045
+#connect (con1,localhost,test,zorro,);
+#--error 1045
diff --git a/mysql-test/t/constraints.test b/mysql-test/t/constraints.test
index 8682cdc42a2..cc796e0abd2 100644
--- a/mysql-test/t/constraints.test
+++ b/mysql-test/t/constraints.test
@@ -2,7 +2,9 @@
# Testing of constraints
# Currently MySQL only ignores the syntax.
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (a int check (a>0));
insert into t1 values (1);
diff --git a/mysql-test/t/count_distinct.test b/mysql-test/t/count_distinct.test
index cb84d0211d7..1f0404876cb 100644
--- a/mysql-test/t/count_distinct.test
+++ b/mysql-test/t/count_distinct.test
@@ -2,7 +2,10 @@
# Problem with count(distinct)
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
+
create table t1 (libname varchar(21) not null, city text, primary key (libname));
create table t2 (isbn varchar(21) not null, author text, title text, primary key (isbn));
create table t3 (isbn varchar(21) not null, libname varchar(21) not null, quantity int ,primary key (isbn,libname));
diff --git a/mysql-test/t/count_distinct2.test b/mysql-test/t/count_distinct2.test
index d1bea7614c8..9100f622dec 100644
--- a/mysql-test/t/count_distinct2.test
+++ b/mysql-test/t/count_distinct2.test
@@ -1,4 +1,6 @@
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1(n1 int, n2 int, s char(20), vs varchar(20), t text);
insert into t1 values (1,11, 'one','eleven', 'eleven'),
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index bb0d6dc0d64..70a589c4be6 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -2,7 +2,10 @@
# Check some special create statements.
#
-drop table if exists t1,t2;
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
create table t1 (b char(0));
insert into t1 values (""),(null);
select * from t1;
@@ -12,7 +15,7 @@ create table t1 (b char(0) not null);
create table if not exists t1 (b char(0) not null);
insert into t1 values (""),(null);
select * from t1;
-drop table if exists t1;
+drop table t1;
#
# Test of some CREATE TABLE'S that should fail
@@ -22,12 +25,12 @@ drop table if exists t1;
!$1146 create table t2 select auto+1 from t1;
drop table if exists t1,t2;
!$1167 create table t1 (b char(0) not null, index(b));
-!$1164 create table t1 (a int not null auto_increment,primary key (a)) type=heap;
+create table t1 (a int not null auto_increment,primary key (a)) type=heap;
!$1163 create table t1 (a int not null,b text) type=heap;
!$1171 create table t1 (a int ,primary key(a)) type=heap;
drop table if exists t1;
-!$1164 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
+!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
!$1171 create table t1 (ordid int(8), primary key (ordid));
-- error 1044,1
@@ -83,6 +86,25 @@ describe t2;
drop table t1,t2;
#
+# Test of CREATE ... SELECT with duplicate fields
+#
+
+create table t1 (a tinyint);
+create table t2 (a int) select * from t1;
+describe t1;
+describe t2;
+drop table if exists t2;
+--error 1060
+create table t2 (a int, a float) select * from t1;
+drop table if exists t2;
+--error 1060
+create table t2 (a int) select a as b, a+1 as b from t1;
+drop table if exists t2;
+--error 1060
+create table t2 (b int) select a as b, a+1 as b from t1;
+drop table if exists t1,t2;
+
+#
# Test of primary key with 32 index
#
@@ -94,3 +116,46 @@ drop table t1;
create table t1 select if('2002'='2002','Y','N');
select * from t1;
drop table if exists t1;
+create table t1 (a int, key(a));
+create table t2 (b int, foreign key(b) references t1(a), key(b));
+drop table if exists t1,t2;
+
+#
+# Test for CREATE TABLE .. LIKE ..
+#
+
+create table t1(id int not null, name char(20));
+insert into t1 values(10,'mysql'),(20,'monty- the creator');
+create table t2(id int not null);
+insert into t2 values(10),(20);
+create table t3 like t1;
+show create table t3;
+select * from t3;
+create table if not exists t3 like t1;
+select @@warning_count;
+create temporary table t3 like t2;
+show create table t3;
+select * from t3;
+drop table t3;
+show create table t3;
+select * from t3;
+drop table t2, t3;
+drop database if exists test_$1;
+create database test_$1;
+create table test_$1.t3 like t1;
+create temporary table t3 like test_$1.t3;
+show create table t3;
+create table t2 like t3;
+show create table t2;
+select * from t2;
+create table t3 like t1;
+!$1050 create table t3 like test_$1.t3;
+--error 1044,1
+create table non_existing_database.t1 like t1;
+!$1051 create table t3 like non_existing_table;
+!$1050 create temporary table t3 like t1;
+!$1103 create table t3 like `a/a`;
+drop table t1, t2, t3;
+drop table t3;
+drop database test_$1;
+
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index e829005a229..a4b4b816ec4 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -1,7 +1,9 @@
#
# Test latin_de character set
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (a char (20) not null, b int not null auto_increment, index (a,b),index(b));
insert into t1 (a) values ('ä'),('ac'),('ae'),('ad'),('Äc'),('aeb');
insert into t1 (a) values ('üc'),('uc'),('ue'),('ud'),('Ü'),('ueb'),('uf');
diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test
new file mode 100644
index 00000000000..5530eee0dbe
--- /dev/null
+++ b/mysql-test/t/ctype_many.test
@@ -0,0 +1,197 @@
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (
+ comment CHAR(32) ASCII NOT NULL,
+ koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL
+) CHARSET=latin5;
+
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 CHARSET=latin2;
+ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
+SHOW CREATE TABLE t1;
+
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU');
+INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA');
+
+SELECT CONVERT(koi8_ru_f USING utf8),MIN(comment),COUNT(*) FROM t1 GROUP BY 1;
+
+ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL;
+UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8);
+SELECT * FROM t1;
+
+ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL;
+UPDATE t1 SET bin_f=koi8_ru_f;
+SELECT COUNT(DISTINCT bin_f),COUNT(DISTINCT koi8_ru_f),COUNT(DISTINCT utf8_f) FROM t1;
+
+SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1;
+SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1;
+SELECT DISTINCT koi8_ru_f FROM t1;
+SELECT DISTINCT utf8_f FROM t1;
+SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC;
+SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC;
+
+SELECT t11.comment,t12.comment
+FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f
+ORDER BY t11.koi8_ru_f,t11.comment,t12.comment;
+
+SELECT t11.comment,t12.comment
+FROM t1 t11,t1 t12
+WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8r)
+ORDER BY t12.utf8_f,t11.comment,t12.comment;
+
+ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2;
+ALTER TABLE t1 CHANGE ucs2_f ucs2_f CHAR(32) UNICODE NOT NULL;
+
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH');
+INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA');
+
+ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL;
+ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL;
+UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%';
+UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%';
+UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f='';
+UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f='';
+SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f;
+DROP TABLE t1;
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index 67111ea1734..4cf26b330c6 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -3,7 +3,9 @@
# (Can't be tested with purify :( )
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (a char(10), tmsp timestamp);
insert into t1 set a = 1;
insert delayed into t1 set a = 2;
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index 953e22cdd55..57321739bfb 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -2,7 +2,9 @@
# Check for problems with delete
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
CREATE TABLE t1 (a tinyint(3), b tinyint(5));
INSERT INTO t1 VALUES (1,1);
INSERT LOW_PRIORITY INTO t1 VALUES (1,2);
@@ -35,3 +37,12 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
delete from t1 where a=27;
drop table t1;
+
+CREATE TABLE `t` (
+ `i` int(10) NOT NULL default '0',
+ `i2` int(10) NOT NULL default '0',
+ PRIMARY KEY (`i`)
+) TYPE=MyISAM CHARSET=latin1;
+-- error 1054
+DELETE FROM t USING t WHERE post='1';
+drop table if exists t;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
new file mode 100644
index 00000000000..1dbdd6e0ae8
--- /dev/null
+++ b/mysql-test/t/derived.test
@@ -0,0 +1,64 @@
+# Initialize
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
+select * from (select 2 from DUAL) b;
+-- error 1054
+SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
+-- error 1054
+SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
+CREATE TABLE t1 (a int not null, b char (10) not null);
+insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
+CREATE TABLE t2 (a int not null, b char (10) not null);
+insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
+select t1.a,t3.y from t1,(select a as y from t2 where b='c') as t3 where t1.a = t3.y;
+select t1.a,t3.a from t1,(select * from t2 where b='c') as t3 where t1.a = t3.a;
+CREATE TABLE t3 (a int not null, b char (10) not null);
+insert into t3 values (3,'f'),(4,'y'),(5,'z'),(6,'c');
+select t1.a,t4.y from t1,(select t2.a as y from t2,(select t3.b from t3 where t3.a>3) as t5 where t2.b=t5.b) as t4 where t1.a = t4.y;
+--error 1054
+SELECT a FROM (SELECT 1 FROM (SELECT 1) a HAVING a=1) b;
+--error 1052
+SELECT a,b as a FROM (SELECT '1' as a,'2' as b) b HAVING a=1;
+SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=2;
+SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=1;
+--error 1054
+SELECT 1 FROM (SELECT 1) a WHERE a=2;
+--error 1054
+SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) as a;
+select * from t1 as x1, (select * from t1) as x2;
+explain select * from t1 as x1, (select * from t1) as x2;
+drop table if exists t2,t3;
+select * from (select 1) as a;
+select a from (select 1 as a) as b;
+select 1 from (select 1) as a;
+select * from (select * from t1 union select * from t1) a;
+select * from (select * from t1 union all select * from t1) a;
+explain select * from (select * from t1 union select * from t1) a;
+explain select * from (select * from t1 union all select * from t1) a;
+CREATE TABLE t2 (a int not null);
+insert into t2 values(1);
+select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
+select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
+drop table t1, t2;
+create table t1(a int not null, t char(8), index(a));
+disable_query_log;
+let $1 = 10000;
+while ($1)
+ {
+ eval insert into t1 values ($1,'$1');
+ dec $1;
+ }
+enable_query_log;
+SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
+explain select count(*) from t1 as tt1, (select * from t1) as tt2;
+drop table t1;
+SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
+select * from (select 1 as a) b left join (select 2 as a) c using(a);
+--error 1054
+SELECT * FROM (SELECT 1 UNION SELECT a) b;
+--error 1054
+SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
+--error 1054
+SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
diff --git a/mysql-test/t/dirty_close.test b/mysql-test/t/dirty_close.test
index 3ed22f26d5b..f965df8cfea 100644
--- a/mysql-test/t/dirty_close.test
+++ b/mysql-test/t/dirty_close.test
@@ -3,7 +3,11 @@ connect (con2,localhost,root,,);
connection con1;
dirty_close con1;
connection con2;
+
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (n int);
insert into t1 values (1),(2),(3);
select * from t1;
diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test
index 7f75b6b1687..859c4042b1d 100644
--- a/mysql-test/t/distinct.test
+++ b/mysql-test/t/distinct.test
@@ -3,7 +3,9 @@
# Bug with group by and not used fields
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
CREATE TABLE t1 (id int,facility char(20));
CREATE TABLE t2 (facility char(20));
@@ -198,7 +200,6 @@ drop table t1,t2,t3;
# This also test the case when one doesn't use all fields in GROUP BY.
#
-drop table if exists t1;
create table t1 (a int not null, b int not null, t time);
insert into t1 values (1,1,"00:06:15"),(1,2,"00:06:15"),(1,2,"00:30:15"),(1,3,"00:06:15"),(1,3,"00:30:15");
select a,sec_to_time(sum(time_to_sec(t))) from t1 group by a,b;
@@ -261,7 +262,7 @@ INSERT INTO t1 VALUES (128,0,33,33,8,':D','',996121863,1,0,2,996122850,2,0,0);
CREATE TABLE t2 (userid int(10) unsigned NOT NULL auto_increment, usergroupid smallint(5) unsigned NOT NULL default '0', username varchar(50) NOT NULL default '', password varchar(50) NOT NULL default '', email varchar(50) NOT NULL default '', styleid smallint(5) unsigned NOT NULL default '0', parentemail varchar(50) NOT NULL default '', coppauser smallint(6) NOT NULL default '0', homepage varchar(100) NOT NULL default '', icq varchar(20) NOT NULL default '', aim varchar(20) NOT NULL default '', yahoo varchar(20) NOT NULL default '', signature mediumtext NOT NULL, adminemail smallint(6) NOT NULL default '0', showemail smallint(6) NOT NULL default '0', invisible smallint(6) NOT NULL default '0', usertitle varchar(250) NOT NULL default '', customtitle smallint(6) NOT NULL default '0', joindate int(10) unsigned NOT NULL default '0', cookieuser smallint(6) NOT NULL default '0', daysprune smallint(6) NOT NULL default '0', lastvisit int(10) unsigned NOT NULL default '0', lastactivity int(10) unsigned NOT NULL default '0', lastpost int(10) unsigned NOT NULL default '0', posts smallint(5) unsigned NOT NULL default '0', timezoneoffset varchar(4) NOT NULL default '', emailnotification smallint(6) NOT NULL default '0', buddylist mediumtext NOT NULL, ignorelist mediumtext NOT NULL, pmfolders mediumtext NOT NULL, receivepm smallint(6) NOT NULL default '0', emailonpm smallint(6) NOT NULL default '0', pmpopup smallint(6) NOT NULL default '0', avatarid smallint(6) NOT NULL default '0', avatarrevision int(6) unsigned NOT NULL default '0', options smallint(6) NOT NULL default '15', birthday date NOT NULL default '0000-00-00', maxposts smallint(6) NOT NULL default '-1', startofweek smallint(6) NOT NULL default '1', ipaddress varchar(20) NOT NULL default '', referrerid int(10) unsigned NOT NULL default '0', nosessionhash smallint(6) NOT NULL default '0', autorefresh smallint(6) NOT NULL default '-1', messagepopup tinyint(2) NOT NULL default '0', inforum smallint(5) unsigned NOT NULL default '0', ratenum smallint(5) unsigned NOT NULL default '0', ratetotal smallint(5) unsigned NOT NULL default '0', allowrate smallint(5) unsigned NOT NULL default '1', PRIMARY KEY (userid), KEY usergroupid (usergroupid), KEY username (username), KEY inforum (inforum)) TYPE=MyISAM;
INSERT INTO t2 VALUES (33,6,'Kevin','0','kevin@stileproject.com',1,'',0,'http://www.stileproject.com','','','','',1,1,0,'Administrator',0,996120694,1,-1,1030996168,1031027028,1030599436,36,'-6',0,'','','',1,0,1,0,0,15,'0000-00-00',-1,1,'64.0.0.0',0,1,-1,0,0,4,19,1);
SELECT DISTINCT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t2.userid = t1.touserid);
-DROP TABLE IF EXISTS t1,t2;
+DROP TABLE t1,t2;
#
# test with const_item in ORDER BY
@@ -272,5 +273,4 @@ INSERT t1 VALUES (1,2,3);
CREATE TABLE t2 (a int primary key, b int, c int);
INSERT t2 VALUES (3,4,5);
SELECT DISTINCT t1.a, t2.b FROM t1, t2 WHERE t1.a=1 ORDER BY t2.c;
-DROP TABLE IF EXISTS t1,t2;
-
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test
index c92f2b1f3b9..307dd45654d 100644
--- a/mysql-test/t/drop.test
+++ b/mysql-test/t/drop.test
@@ -1,5 +1,8 @@
+# Initialise
+--disable_warnings
drop table if exists t1;
-drop table if exists t1;
+--enable_warnings
+
--error 1051;
drop table t1;
create table t1(n int);
diff --git a/mysql-test/t/empty_table.test b/mysql-test/t/empty_table.test
index 9ea79ee157f..db0a8e6a247 100644
--- a/mysql-test/t/empty_table.test
+++ b/mysql-test/t/empty_table.test
@@ -2,7 +2,10 @@
# Some special cases with empty tables
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
select count(*) from t1;
select * from t1;
diff --git a/mysql-test/t/err000001.test b/mysql-test/t/err000001.test
index d9898054a83..b558c90b0c6 100644
--- a/mysql-test/t/err000001.test
+++ b/mysql-test/t/err000001.test
@@ -2,18 +2,30 @@
# Test some error conditions
#
+--disable_warnings
drop table if exists t1;
-!$1146 insert into t1 values(1);
-!$1146 delete from t1;
-!$1146 update t1 set a=1;
+--enable_warnings
+--error 1146
+insert into t1 values(1);
+--error 1146
+delete from t1;
+--error 1146
+update t1 set a=1;
create table t1 (a int);
-!$1054 select count(test.t1.b) from t1;
-!$1109 select count(not_existing_database.t1) from t1;
-!$1109 select count(not_existing_database.t1.a) from t1;
+--error 1054
+select count(test.t1.b) from t1;
+--error 1109
+select count(not_existing_database.t1) from t1;
+--error 1109
+select count(not_existing_database.t1.a) from t1;
--error 1044,1146
select count(not_existing_database.t1.a) from not_existing_database.t1;
-!$1054 select 1 from t1 order by 2;
-!$1054 select 1 from t1 group by 2;
-!$1054 select 1 from t1 order by t1.b;
-!$1054 select count(*),b from t1;
+--error 1054
+select 1 from t1 order by 2;
+--error 1054
+select 1 from t1 group by 2;
+--error 1054
+select 1 from t1 order by t1.b;
+--error 1054
+select count(*),b from t1;
drop table t1;
diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test
index 045598e97df..ff1803368b9 100644
--- a/mysql-test/t/explain.test
+++ b/mysql-test/t/explain.test
@@ -1,7 +1,9 @@
#
# Test of different EXPLAIN's
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (id int not null, str char(10), unique(str));
explain select * from t1;
insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar");
diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test
index 540aa4235cc..44a821b63c2 100644
--- a/mysql-test/t/flush.test
+++ b/mysql-test/t/flush.test
@@ -9,9 +9,13 @@
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
-drop table if exists t1;
+
+--disable_warnings
+drop table if exists t1,t2;
+drop database if exists mysqltest;
+--enable_warnings
+
create temporary table t1(n int not null primary key);
-drop table if exists t2;
create table t2(n int);
insert into t2 values(3);
let $1=100;
@@ -44,7 +48,6 @@ reap;
#test if drop database will wait until we release the global read lock
connection con1;
-drop database if exists mysqltest;
create database mysqltest;
create table mysqltest.t1(n int);
insert into mysqltest.t1 values (23);
diff --git a/mysql-test/t/foreign_key.test b/mysql-test/t/foreign_key.test
index 1afcb546f6a..8c35fd65f74 100644
--- a/mysql-test/t/foreign_key.test
+++ b/mysql-test/t/foreign_key.test
@@ -2,7 +2,10 @@
# Test syntax of foreign keys
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (
a int not null references t2,
b int not null references t2 (c),
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 5a64f2614aa..214236268fa 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -2,7 +2,9 @@
# Test of fulltext index
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
CREATE TABLE t1 (a VARCHAR(200), b TEXT, FULLTEXT (a,b));
INSERT INTO t1 VALUES('MySQL has now support', 'for full-text search'),
@@ -16,6 +18,7 @@ INSERT INTO t1 VALUES('MySQL has now support', 'for full-text search'),
select * from t1 where MATCH(a,b) AGAINST ("collections");
select * from t1 where MATCH(a,b) AGAINST ("indexes");
select * from t1 where MATCH(a,b) AGAINST ("indexes collections");
+select * from t1 where MATCH(a,b) AGAINST ("only");
# UNION of fulltext's
select * from t1 where MATCH(a,b) AGAINST ("collections") UNION ALL select * from t1 where MATCH(a,b) AGAINST ("indexes");
@@ -166,7 +169,6 @@ drop table t1;
# ERROR 1030: Got error 127 from table handler
#
-drop table if exists t1;
create table t1 (a text, fulltext key (a));
insert into t1 values ('aaaa');
repair table t1;
diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test
new file mode 100644
index 00000000000..2c0d352a870
--- /dev/null
+++ b/mysql-test/t/fulltext2.test
@@ -0,0 +1,96 @@
+#
+# test of new fulltext search features
+#
+
+#
+# two-level tree
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (
+ i int(10) unsigned not null auto_increment primary key,
+ a varchar(255) not null,
+ FULLTEXT KEY (a)
+) TYPE=MyISAM;
+
+# two-level entry, second-level tree with depth 2
+let $1=260;
+while ($1)
+{
+ eval insert t1 (a) values ('aaaxxx');
+ dec $1;
+}
+
+# two-level entry, second-level tree has only one page
+let $1=255;
+while ($1)
+{
+ eval insert t1 (a) values ('aaazzz');
+ dec $1;
+}
+
+# one-level entry (entries)
+let $1=250;
+while ($1)
+{
+ eval insert t1 (a) values ('aaayyy');
+ dec $1;
+}
+
+# converting to two-level
+repair table t1 quick;
+
+select count(*) from t1 where match a against ('aaaxxx');
+select count(*) from t1 where match a against ('aaayyy');
+select count(*) from t1 where match a against ('aaazzz');
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+select count(*) from t1 where match a against ('aaayyy' in boolean mode);
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+select count(*) from t1 where match a against ('aaaxxx aaayyy aaazzz');
+select count(*) from t1 where match a against ('aaaxxx aaayyy aaazzz' in boolean mode);
+
+select count(*) from t1 where match a against ('aaax*' in boolean mode);
+select count(*) from t1 where match a against ('aaay*' in boolean mode);
+select count(*) from t1 where match a against ('aaa*' in boolean mode);
+
+# mi_write:
+
+insert t1 (a) values ('aaaxxx'),('aaayyy');
+# call to enlarge_root() below
+insert t1 (a) values ('aaazzz'),('aaazzz'),('aaazzz'),('aaazzz'),('aaazzz');
+select count(*) from t1 where match a against ('aaaxxx');
+select count(*) from t1 where match a against ('aaayyy');
+select count(*) from t1 where match a against ('aaazzz');
+
+# mi_delete
+insert t1 (a) values ('aaaxxx 000000');
+select count(*) from t1 where match a against ('000000');
+delete from t1 where match a against ('000000');
+select count(*) from t1 where match a against ('000000');
+select count(*) from t1 where match a against ('aaaxxx');
+delete from t1 where match a against ('aaazzz');
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+select count(*) from t1 where match a against ('aaayyy' in boolean mode);
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+# double-check without index
+select count(*) from t1 where a = 'aaaxxx';
+select count(*) from t1 where a = 'aaayyy';
+select count(*) from t1 where a = 'aaazzz';
+
+# update
+insert t1 (a) values ('aaaxxx 000000');
+select count(*) from t1 where match a against ('000000');
+update t1 set a='aaazzz' where match a against ('000000');
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+update t1 set a='aaazzz' where a = 'aaaxxx';
+update t1 set a='aaaxxx' where a = 'aaayyy';
+select count(*) from t1 where match a against ('aaaxxx' in boolean mode);
+select count(*) from t1 where match a against ('aaayyy' in boolean mode);
+select count(*) from t1 where match a against ('aaazzz' in boolean mode);
+
+DROP TABLE IF EXISTS t1;
+
diff --git a/mysql-test/t/fulltext_cache.test b/mysql-test/t/fulltext_cache.test
index 0b15e57a97b..15f32fdb5a0 100644
--- a/mysql-test/t/fulltext_cache.test
+++ b/mysql-test/t/fulltext_cache.test
@@ -2,7 +2,10 @@
# Bugreport due to Roy Nasser <roy@vem.ca>
#
+--disable_warnings
drop table if exists t1, t2;
+--enable_warnings
+
CREATE TABLE t1 (
id int(10) unsigned NOT NULL auto_increment,
q varchar(255) default NULL,
diff --git a/mysql-test/t/fulltext_distinct.test b/mysql-test/t/fulltext_distinct.test
index 86e2f7ca1b4..2ccfb94c819 100644
--- a/mysql-test/t/fulltext_distinct.test
+++ b/mysql-test/t/fulltext_distinct.test
@@ -3,7 +3,10 @@
# bug reported by Tibor Simko <tibor.simko@cern.ch>
#
+--disable_warnings
DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
CREATE TABLE t1 (
id mediumint unsigned NOT NULL auto_increment,
tag char(6) NOT NULL default '',
diff --git a/mysql-test/t/fulltext_left_join.test b/mysql-test/t/fulltext_left_join.test
index bcf7cbcc505..4fce8ee287e 100644
--- a/mysql-test/t/fulltext_left_join.test
+++ b/mysql-test/t/fulltext_left_join.test
@@ -2,7 +2,10 @@
# Test for bug from Jean-Cédric COSTA <jean-cedric.costa@ensmp.fr>
#
+--disable_warnings
drop table if exists t1, t2;
+--enable_warnings
+
CREATE TABLE t1 (
id VARCHAR(255) NOT NULL PRIMARY KEY,
sujet VARCHAR(255),
diff --git a/mysql-test/t/fulltext_multi.test b/mysql-test/t/fulltext_multi.test
index 233c243146e..c312a5938b2 100644
--- a/mysql-test/t/fulltext_multi.test
+++ b/mysql-test/t/fulltext_multi.test
@@ -1,6 +1,8 @@
# several FULLTEXT indexes in one table test
-use test;
+--disable_warnings
DROP TABLE IF EXISTS t1;
+--enable_warnings
+
CREATE TABLE t1 (
a int(11) NOT NULL auto_increment,
b text,
diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test
index 3b60ee77db2..f8afe49d95d 100644
--- a/mysql-test/t/fulltext_order_by.test
+++ b/mysql-test/t/fulltext_order_by.test
@@ -1,5 +1,7 @@
-use test;
+--disable_warnings
DROP TABLE IF EXISTS t1;
+--enable_warnings
+
CREATE TABLE t1 (
a INT AUTO_INCREMENT PRIMARY KEY,
message CHAR(20),
diff --git a/mysql-test/t/fulltext_update.test b/mysql-test/t/fulltext_update.test
index 9e2ce3ccba5..a1d133ba3fe 100644
--- a/mysql-test/t/fulltext_update.test
+++ b/mysql-test/t/fulltext_update.test
@@ -2,7 +2,9 @@
# Test for bug by voi@ims.at
#
+--disable_warnings
drop table if exists test;
+--enable_warnings
CREATE TABLE test (
gnr INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
url VARCHAR(80) DEFAULT '' NOT NULL,
diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test
index d6da1d6a603..147367a6d27 100644
--- a/mysql-test/t/func_concat.test
+++ b/mysql-test/t/func_concat.test
@@ -2,7 +2,10 @@
# Test of problem with CONCAT_WS() and long separators.
#
+--disable_warnings
DROP TABLE IF EXISTS t1;
+--enable_warnings
+
CREATE TABLE t1 ( number INT NOT NULL, alpha CHAR(6) NOT NULL );
INSERT INTO t1 VALUES (1413006,'idlfmv'),
(1413065,'smpsfz'),(1413127,'sljrhx'),(1413304,'qerfnd');
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index f403d96e885..c72356bda1a 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -2,5 +2,9 @@
select length(encrypt('foo', 'ff')) <> 0;
--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
-select old_password('test'), password('test');
-select length(encrypt('test')), encrypt('test','aa');
+
+# Test new and old password handling functions
+select password("a",""), password("a",NULL), password("","a"), password(NULL,"a");
+select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa");
+select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa');
+select old_password(""), old_password(NULL), password(""), password(NULL);
diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test
index c0250c6ece4..35acfe84bee 100644
--- a/mysql-test/t/func_date_add.test
+++ b/mysql-test/t/func_date_add.test
@@ -2,7 +2,10 @@
# Test of DATE_ADD
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
CREATE TABLE t1 (
visitor_id int(10) unsigned DEFAULT '0' NOT NULL,
group_id int(10) unsigned DEFAULT '0' NOT NULL,
diff --git a/mysql-test/t/func_encrypt.test b/mysql-test/t/func_encrypt.test
index 3b6acc54ec9..fbb71f850e2 100644
--- a/mysql-test/t/func_encrypt.test
+++ b/mysql-test/t/func_encrypt.test
@@ -1,6 +1,9 @@
-- source include/have_openssl.inc
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (x blob);
insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','The quick red fox jumped over the lazy brown dog'));
insert into t1 values (des_encrypt('a','The quick red fox jumped over the lazy brown dog'));
diff --git a/mysql-test/t/func_equal.test b/mysql-test/t/func_equal.test
index 0d7a4ed9778..cbf589ffcc2 100644
--- a/mysql-test/t/func_equal.test
+++ b/mysql-test/t/func_equal.test
@@ -1,3 +1,8 @@
+# Initialise
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
#
# Testing of the <=> operator
#
@@ -15,7 +20,6 @@ select "A"<=>"B","A"<=>NULL,NULL<=>"A";
# Test with tables
#
-drop table if exists t1,t2;
create table t1 (id int, value int);
create table t2 (id int, value int);
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 1915c2172ad..f0677ff98d5 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -2,7 +2,10 @@
# simple test of all group functions
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (grp int, a bigint unsigned, c char(10) not null);
insert into t1 values (1,1,"a");
insert into t1 values (2,2,"b");
@@ -21,9 +24,9 @@ select count(distinct a),count(distinct grp) from t1;
insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1;
-select sum(all a),count(all a),avg(all a),std(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
-select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
-select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
+select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
+select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
+select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
@@ -40,8 +43,8 @@ CREATE TABLE t1 (id int(11),value1 float(10,2));
INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
-select id, avg(value1), std(value1) from t1 group by id;
-select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id;
+select id, avg(value1), std(value1), variance(value1) from t1 group by id;
+select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
drop table t1,t2;
#
diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test
index 85553d1a2fd..21e5836c781 100644
--- a/mysql-test/t/func_if.test
+++ b/mysql-test/t/func_if.test
@@ -1,7 +1,9 @@
#
# Init section
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
#
# Simple IF tests
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index e5d42ec25c4..723f1707a42 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -1,8 +1,44 @@
+# Initialise
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
#
# test of IN (NULL)
#
-drop table if exists t1;
+select 1 in (1,2,3);
+select 10 in (1,2,3);
+select NULL in (1,2,3);
+select 1 in (1,NULL,3);
+select 3 in (1,NULL,3);
+select 10 in (1,NULL,3);
+select 1.5 in (1.5,2.5,3.5);
+select 10.5 in (1.5,2.5,3.5);
+select NULL in (1.5,2.5,3.5);
+select 1.5 in (1.5,NULL,3.5);
+select 3.5 in (1.5,NULL,3.5);
+select 10.5 in (1.5,NULL,3.5);
+
+CREATE TABLE t1 (a int, b int, c int);
+insert into t1 values (1,2,3), (1,NULL,3);
+select 1 in (a,b,c) from t1;
+select 3 in (a,b,c) from t1;
+select 10 in (a,b,c) from t1;
+select NULL in (a,b,c) from t1;
+drop table t1;
+CREATE TABLE t1 (a float, b float, c float);
+insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
+select 1.5 in (a,b,c) from t1;
+select 3.5 in (a,b,c) from t1;
+select 10.5 in (a,b,c) from t1;
+drop table t1;
+CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
+insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
+select 'A' in (a,b,c) from t1;
+select 'EFD' in (a,b,c) from t1;
+select 'XSFGGHF' in (a,b,c) from t1;
+drop table t1;
+
CREATE TABLE t1 (field char(1));
INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL);
diff --git a/mysql-test/t/func_isnull.test b/mysql-test/t/func_isnull.test
index bd3bcd8d04c..506efada0eb 100644
--- a/mysql-test/t/func_isnull.test
+++ b/mysql-test/t/func_isnull.test
@@ -2,7 +2,10 @@
# test of ISNULL()
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (id int auto_increment primary key not null, mydate date not null);
insert into t1 values (0,"2002-05-01"),(0,"2002-05-01"),(0,"2002-05-01");
flush tables;
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index 09746fcc817..47590ae7559 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -2,7 +2,10 @@
# Test of like
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a varchar(10), key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
select * from t1 where a like "abc%";
diff --git a/mysql-test/t/func_regexp.test b/mysql-test/t/func_regexp.test
index 7fbe4000cfc..6e5d601844e 100644
--- a/mysql-test/t/func_regexp.test
+++ b/mysql-test/t/func_regexp.test
@@ -2,7 +2,10 @@
# Some regexp tests
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (s1 char(64),s2 char(64));
insert into t1 values('aaa','aaa');
diff --git a/mysql-test/t/func_set.test b/mysql-test/t/func_set.test
index cb1aa543d43..60d67a77562 100644
--- a/mysql-test/t/func_set.test
+++ b/mysql-test/t/func_set.test
@@ -15,3 +15,21 @@ select export_set(9,"Y","N","-",5),export_set(9,"Y","N"),export_set(9,"Y","N",""
select elt(2,1),field(NULL,"a","b","c");
select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c");
select find_in_set("abc","abc"),find_in_set("ab","abc"),find_in_set("abcd","abc");
+
+#
+# test for a bug with elt()
+#
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1 (id int(10) not null unique);
+create table t2 (id int(10) not null primary key,
+val int(10) not null);
+insert into t1 values (1),(2),(4);
+insert into t2 values (1,1),(2,1),(3,1),(4,2);
+
+select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
+select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
+drop table t1,t2;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index f95cd901dfb..a87707746ba 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -4,7 +4,9 @@
# -----------
# Testing string functions
+--disable_warnings
drop table if exists t1;
+--enable_warnings
select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
select 'hello' 'monty';
@@ -36,6 +38,11 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c');
select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ;
select soundex(''),soundex('he'),soundex('hello all folks');
+select 'mood' sounds like 'mud';
+select 'Glazgo' sounds like 'Liverpool';
+select null sounds like 'null';
+select 'null' sounds like null;
+select null sounds like null;
select md5('hello');
select sha('abc');
select sha1('abc');
@@ -111,9 +118,9 @@ CREATE TABLE t1 (
) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4);
-SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"') FROM t1;
+SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter), '"') FROM t1;
SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1;
-SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) FROM t1;
+SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter) FROM t1;
drop table t1;
#
diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test
index 052e0530cf6..c69526644f4 100644
--- a/mysql-test/t/func_system.test
+++ b/mysql-test/t/func_system.test
@@ -4,3 +4,4 @@
select database(),user() like "%@%";
select version()>="3.23.29";
+select TRUE,FALSE,NULL;
diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test
index f5ad2e21c73..8810aefc20f 100644
--- a/mysql-test/t/func_test.test
+++ b/mysql-test/t/func_test.test
@@ -17,6 +17,7 @@ select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,
select -1.49 or -1.49,0.6 or 0.6;
select 3 ^ 11, 1 ^ 1, 1 ^ 0, 1 ^ NULL, NULL ^ 1;
select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 0, NULL XOR 1, 1 XOR NULL, 0 XOR NULL;
+select 10 % 7, 10 mod 7, 10 div 3;
#
# Wrong usage of functions
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index dd589ff2e66..903b80eb12a 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1,7 +1,9 @@
#
# time functions
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
select period_add("9602",-12),period_diff(199505,"9404") ;
@@ -183,3 +185,34 @@ select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
drop table t1,t2,t3;
+
+#
+# Test types from + INTERVAL
+#
+
+CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
+INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
+SELECT * from t1;
+select date_add("1997-12-31",INTERVAL 1 SECOND);
+select date_add("1997-12-31",INTERVAL "1 1" YEAR_MONTH);
+
+select date_add(datetime, INTERVAL 1 SECOND) from t1;
+select date_add(datetime, INTERVAL 1 YEAR) from t1;
+
+select date_add(date,INTERVAL 1 SECOND) from t1;
+select date_add(date,INTERVAL 1 MINUTE) from t1;
+select date_add(date,INTERVAL 1 HOUR) from t1;
+select date_add(date,INTERVAL 1 DAY) from t1;
+select date_add(date,INTERVAL 1 MONTH) from t1;
+select date_add(date,INTERVAL 1 YEAR) from t1;
+select date_add(date,INTERVAL "1:1" MINUTE_SECOND) from t1;
+select date_add(date,INTERVAL "1:1" HOUR_MINUTE) from t1;
+select date_add(date,INTERVAL "1:1" DAY_HOUR) from t1;
+select date_add(date,INTERVAL "1 1" YEAR_MONTH) from t1;
+select date_add(date,INTERVAL "1:1:1" HOUR_SECOND) from t1;
+select date_add(date,INTERVAL "1 1:1" DAY_MINUTE) from t1;
+select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
+
+# The following is not as one would expect...
+select date_add(time,INTERVAL 1 SECOND) from t1;
+drop table t1;
diff --git a/mysql-test/t/func_timestamp.test b/mysql-test/t/func_timestamp.test
index 74e541f782d..8583c16073d 100644
--- a/mysql-test/t/func_timestamp.test
+++ b/mysql-test/t/func_timestamp.test
@@ -2,7 +2,10 @@
# Tests that depend on the timestamp and the TZ variable
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (Zeit time, Tag tinyint not null, Monat tinyint not null,
Jahr smallint not null, index(Tag), index(Monat), index(Jahr) );
insert into t1 values ("09:26:00",16,9,1998),("09:26:00",16,9,1998);
diff --git a/mysql-test/t/gcc296.test b/mysql-test/t/gcc296.test
index 7c72b57ca54..ebca4dbc897 100644
--- a/mysql-test/t/gcc296.test
+++ b/mysql-test/t/gcc296.test
@@ -1,6 +1,9 @@
#try to crash gcc 2.96
-drop table if exists obory;
-CREATE TABLE obory (
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+CREATE TABLE t1 (
kodoboru varchar(10) default NULL,
obor tinytext,
aobor tinytext,
@@ -8,10 +11,10 @@ CREATE TABLE obory (
FULLTEXT KEY obor (obor),
FULLTEXT KEY aobor (aobor)
);
-INSERT INTO obory VALUES ('0101000000','aaa','AAA');
-INSERT INTO obory VALUES ('0102000000','bbb','BBB');
-INSERT INTO obory VALUES ('0103000000','ccc','CCC');
-INSERT INTO obory VALUES ('0104000000','xxx','XXX');
+INSERT INTO t1 VALUES ('0101000000','aaa','AAA');
+INSERT INTO t1 VALUES ('0102000000','bbb','BBB');
+INSERT INTO t1 VALUES ('0103000000','ccc','CCC');
+INSERT INTO t1 VALUES ('0104000000','xxx','XXX');
-select * from obory;
-drop table obory;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test
index 7dfbb3b8d83..2d704a770aa 100644
--- a/mysql-test/t/grant_cache.test
+++ b/mysql-test/t/grant_cache.test
@@ -3,12 +3,17 @@
#
# Test grants with query cache
#
+--disable_warnings
drop table if exists test.t1,mysqltest.t1,mysqltest.t2;
+--enable_warnings
+
reset query cache;
flush status;
connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock);
connection root;
+--disable_warnings
create database if not exists mysqltest;
+--enable_warnings
create table mysqltest.t1 (a int,b int,c int);
create table mysqltest.t2 (a int,b int,c int);
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index e54c32d0beb..dfcf72eb2c3 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1,8 +1,18 @@
+# Initialise
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
+#
+# Simple test without tables
+
+-- error 1111
+SELECT 1 FROM (SELECT 1) as a GROUP BY SUM(1);
+
#
# Test of group (Failed for Lars Hoss <lh@pbm.de>)
#
-drop table if exists t1,t2,t3;
CREATE TABLE t1 (
spID int(10) unsigned,
userID int(10) unsigned,
@@ -40,7 +50,7 @@ SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t
SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid;
SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid;
SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL;
-drop table test.t1,test.t2;
+drop table t1,t2;
#
# Bug in GROUP BY, by Nikki Chumakov <nikki@saddam.cityline.ru>
@@ -293,7 +303,6 @@ SELECT 1 FROM t1 GROUP BY CONCAT(a, b);
INSERT INTO t1 values ('hij','klm');
SELECT CONCAT(a, b),count(*) FROM t1 GROUP BY 1;
DROP TABLE t1;
-drop table if exists t1;
#
# Test problem with ORDER BY on a SUM() column
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
index f5bab7cf337..657185f5e2d 100644
--- a/mysql-test/t/handler.test
+++ b/mysql-test/t/handler.test
@@ -2,13 +2,18 @@
# test of HANDLER ...
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a int, b char(10), key a(a), key b(a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"),
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
+-- error 1064
+handler t2 read a=(SELECT 1);
handler t2 read a first;
handler t2 read a next;
handler t2 read a next;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 8dd7606d82b..4bd56400f98 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -1,7 +1,10 @@
# test of problems with having (Reported by Mark Rogers)
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a int);
select count(a) as b from t1 where a=0 having b > 0;
insert into t1 values (null);
@@ -59,4 +62,5 @@ select Fld1, max(Fld2) as q from t1 group by Fld1 having q is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having max(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having avg(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
+select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
drop table t1;
diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test
index ef7e3239a96..cd5dbd5afbe 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -2,7 +2,10 @@
# Test of heap tables.
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a int not null,b int not null, primary key (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
insert into t1 values(1,1),(2,2),(3,3),(4,4);
delete from t1 where a=1 or a=0;
@@ -42,7 +45,7 @@ alter table t1 type=myisam;
explain select * from t1 where a in (869751,736494,226312,802616);
drop table t1;
-create table t1 (x int not null, y int not null, key x(x), unique y(y))
+create table t1 (x int not null, y int not null, key x (x), unique y (y))
type=heap;
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
select * from t1 where x=1;
diff --git a/mysql-test/t/heap_auto_increment.test b/mysql-test/t/heap_auto_increment.test
new file mode 100644
index 00000000000..6f392f6830d
--- /dev/null
+++ b/mysql-test/t/heap_auto_increment.test
@@ -0,0 +1,33 @@
+#
+# Test of auto_increment; The test for BDB tables is in bdb.test
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int not null auto_increment,b int, primary key (a)) type=heap auto_increment=3;
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+delete from t1 where a=4;
+insert into t1 values (NULL,5),(NULL,6);
+select * from t1;
+delete from t1 where a=6;
+#show table status like "t1";
+replace t1 values (3,1);
+ALTER TABLE t1 add c int;
+replace t1 values (3,3,3);
+insert into t1 values (NULL,7,7);
+update t1 set a=8,b=b+1,c=c+1 where a=7;
+insert into t1 values (NULL,9,9);
+select * from t1;
+drop table t1;
+
+create table t1 (
+ skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY,
+ sval char(20)
+) type=heap;
+insert into t1 values (NULL, "hello");
+insert into t1 values (NULL, "hey");
+select * from t1;
+select _rowid,t1._rowid,skey,sval from t1;
+drop table t1;
diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test
new file mode 100644
index 00000000000..3c2ff249415
--- /dev/null
+++ b/mysql-test/t/heap_btree.test
@@ -0,0 +1,158 @@
+#
+# Test of heap tables.
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a=1 or a=0;
+#show table status like "t1";
+show keys from t1;
+select * from t1;
+select * from t1 where a=4;
+update t1 set b=5 where a=4;
+update t1 set b=b+1 where a>=3;
+replace t1 values (3,3);
+select * from t1;
+alter table t1 add c int not null, add key using BTREE (c,a);
+drop table t1;
+
+create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a > 0;
+select * from t1;
+drop table t1;
+
+create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
+#show table status like "t1";
+select * from t1;
+drop table t1;
+
+create table t1 (a int not null) type=heap;
+insert into t1 values (869751),(736494),(226312),(802616);
+select * from t1 where a > 736494;
+alter table t1 add unique uniq_id using BTREE (a);
+select * from t1 where a > 736494;
+select * from t1 where a = 736494;
+select * from t1 where a=869751 or a=736494;
+select * from t1 where a in (869751,736494,226312,802616);
+alter table t1 type=myisam;
+explain select * from t1 where a in (869751,736494,226312,802616);
+drop table t1;
+
+create table t1 (x int not null, y int not null, key x using BTREE (x,y), unique y using BTREE (y))
+type=heap;
+insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
+explain select * from t1 where x=1;
+select * from t1 where x=1;
+select * from t1,t1 as t2 where t1.x=t2.y;
+explain select * from t1,t1 as t2 where t1.x=t2.y;
+drop table t1;
+
+create table t1 (a int) type=heap;
+insert into t1 values(1);
+select max(a) from t1;
+drop table t1;
+
+CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using BTREE (a,b), key using BTREE (b) ) TYPE=HEAP;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+--replace_result 0 x 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 x 13 x 14 x
+explain select * from t1 where a=1 order by a,b;
+--replace_result 0 x 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 x 13 x 14 x
+explain select * from t1 where a=1 order by b;
+select * from t1 where b=1;
+--replace_result 0 x 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 x 13 x 14 x
+explain select * from t1 where b=1;
+drop table t1;
+
+create table t1 (id int unsigned not null, primary key using BTREE (id)) type=HEAP;
+insert into t1 values(1);
+select max(id) from t1;
+insert into t1 values(2);
+select max(id) from t1;
+replace into t1 values(1);
+drop table t1;
+
+create table t1 (n int) type=heap;
+drop table t1;
+
+create table t1 (n int) type=heap;
+drop table if exists t1;
+
+# Test of non unique index
+
+CREATE table t1(f1 int not null,f2 char(20) not
+null,index(f2)) type=heap;
+INSERT into t1 set f1=12,f2="bill";
+INSERT into t1 set f1=13,f2="bill";
+INSERT into t1 set f1=14,f2="bill";
+INSERT into t1 set f1=15,f2="bill";
+INSERT into t1 set f1=16,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+delete from t1 where f2="bill";
+select * from t1;
+drop table t1;
+
+#
+# Test when using part key searches
+#
+
+create table t1 (btn char(10) not null, key using BTREE (btn)) type=heap;
+insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
+explain select * from t1 where btn like "q%";
+select * from t1 where btn like "q%";
+alter table t1 add column new_col char(1) not null, add key using BTREE (btn,new_col), drop key btn;
+update t1 set new_col=btn;
+explain select * from t1 where btn="a";
+explain select * from t1 where btn="a" and new_col="a";
+drop table t1;
+
+#
+# Test of NULL keys
+#
+
+CREATE TABLE t1 (
+ a int default NULL,
+ b int default NULL,
+ KEY a using BTREE (a),
+ UNIQUE b using BTREE (b)
+) type=heap;
+INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
+SELECT * FROM t1 WHERE a=NULL;
+explain SELECT * FROM t1 WHERE a IS NULL;
+SELECT * FROM t1 WHERE a<=>NULL;
+SELECT * FROM t1 WHERE b=NULL;
+explain SELECT * FROM t1 WHERE b IS NULL;
+SELECT * FROM t1 WHERE b<=>NULL;
+
+--error 1062
+INSERT INTO t1 VALUES (1,3);
+DROP TABLE t1;
+
+CREATE TABLE t1 (a int, b int, c int, key using BTREE (a, b, c)) type=heap;
+INSERT INTO t1 VALUES (1, NULL, NULL), (1, 1, NULL), (1, NULL, 1);
+SELECT * FROM t1 WHERE a=1 and b IS NULL;
+SELECT * FROM t1 WHERE a=1 and c IS NULL;
+SELECT * FROM t1 WHERE a=1 and b IS NULL and c IS NULL;
+DROP TABLE t1;
+
+#
+# Test when deleting all rows
+#
+
+CREATE TABLE t1 (a int not null, primary key using BTREE (a)) type=heap;
+INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
+DELETE from t1 where a < 100;
+SELECT * from t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test
new file mode 100644
index 00000000000..7b375fdfa3c
--- /dev/null
+++ b/mysql-test/t/heap_hash.test
@@ -0,0 +1,143 @@
+#
+# Test of heap tables.
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a=1 or a=0;
+#show table status like "t1";
+show keys from t1;
+select * from t1;
+select * from t1 where a=4;
+update t1 set b=5 where a=4;
+update t1 set b=b+1 where a>=3;
+replace t1 values (3,3);
+select * from t1;
+alter table t1 add c int not null, add key using HASH (c,a);
+drop table t1;
+
+create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a > 0;
+select * from t1;
+drop table t1;
+
+create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
+#show table status like "t1";
+select * from t1;
+drop table t1;
+
+create table t1 (a int not null) type=heap;
+insert into t1 values (869751),(736494),(226312),(802616);
+select * from t1 where a > 736494;
+alter table t1 add unique uniq_id using HASH (a);
+select * from t1 where a > 736494;
+select * from t1 where a = 736494;
+select * from t1 where a=869751 or a=736494;
+select * from t1 where a in (869751,736494,226312,802616);
+alter table t1 type=myisam;
+explain select * from t1 where a in (869751,736494,226312,802616);
+drop table t1;
+
+create table t1 (x int not null, y int not null, key x using HASH (x), unique y using HASH (y))
+type=heap;
+insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
+select * from t1 where x=1;
+select * from t1,t1 as t2 where t1.x=t2.y;
+explain select * from t1,t1 as t2 where t1.x=t2.y;
+drop table t1;
+
+create table t1 (a int) type=heap;
+insert into t1 values(1);
+select max(a) from t1;
+drop table t1;
+
+CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using HASH (a), key using HASH (b) ) TYPE=HEAP;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
+drop table t1;
+
+create table t1 (id int unsigned not null, primary key using HASH (id)) type=HEAP;
+insert into t1 values(1);
+select max(id) from t1;
+insert into t1 values(2);
+select max(id) from t1;
+replace into t1 values(1);
+drop table t1;
+
+create table t1 (n int) type=heap;
+drop table t1;
+
+create table t1 (n int) type=heap;
+drop table if exists t1;
+
+# Test of non unique index
+
+CREATE table t1(f1 int not null,f2 char(20) not
+null,index(f2)) type=heap;
+INSERT into t1 set f1=12,f2="bill";
+INSERT into t1 set f1=13,f2="bill";
+INSERT into t1 set f1=14,f2="bill";
+INSERT into t1 set f1=15,f2="bill";
+INSERT into t1 set f1=16,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+delete from t1 where f2="bill";
+select * from t1;
+drop table t1;
+
+#
+# Test when using part key searches
+#
+
+create table t1 (btn char(10) not null, key using HASH (btn)) type=heap;
+insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
+explain select * from t1 where btn like "q%";
+select * from t1 where btn like "q%";
+alter table t1 add column new_col char(1) not null, add key using HASH (btn,new_col), drop key btn;
+update t1 set new_col=btn;
+explain select * from t1 where btn="a";
+explain select * from t1 where btn="a" and new_col="a";
+drop table t1;
+
+#
+# Test of NULL keys
+#
+
+CREATE TABLE t1 (
+ a int default NULL,
+ b int default NULL,
+ KEY a using HASH (a),
+ UNIQUE b using HASH (b)
+) type=heap;
+INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
+SELECT * FROM t1 WHERE a=NULL;
+explain SELECT * FROM t1 WHERE a IS NULL;
+SELECT * FROM t1 WHERE a<=>NULL;
+SELECT * FROM t1 WHERE b=NULL;
+explain SELECT * FROM t1 WHERE b IS NULL;
+SELECT * FROM t1 WHERE b<=>NULL;
+
+--error 1062
+INSERT INTO t1 VALUES (1,3);
+DROP TABLE t1;
+
+#
+# Test when deleting all rows
+#
+
+CREATE TABLE t1 (a int not null, primary key using HASH (a)) type=heap;
+INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
+DELETE from t1 where a < 100;
+SELECT * from t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/help.test b/mysql-test/t/help.test
new file mode 100644
index 00000000000..c36b670c6b3
--- /dev/null
+++ b/mysql-test/t/help.test
@@ -0,0 +1,50 @@
+-- source include/have_innodb.inc
+
+truncate mysql.help_topic;
+truncate mysql.help_category;
+truncate mysql.help_relation;
+
+insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1');
+SELECT @topic1_id:=LAST_INSERT_ID();
+insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2');
+SELECT @topic2_id:=LAST_INSERT_ID();
+insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3');
+SELECT @topic3_id:=LAST_INSERT_ID();
+
+insert into mysql.help_category(name)values('impossible_category_1');
+SELECT @category1_id:=LAST_INSERT_ID();
+insert into mysql.help_category(name)values('impossible_category_2');
+SELECT @category2_id:=LAST_INSERT_ID();
+
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id);
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id);
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id);
+insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id);
+
+help 'function_of_my_dream';
+help '%possible_f%';
+help 'impossible_func%';
+help 'impossible_category%';
+help 'impossible_%';
+help '%function_2';
+help '%category_2';
+help 'impossible_function_1';
+help 'impossible_category_1';
+
+alter table mysql.help_topic type=innodb;
+alter table mysql.help_category type=innodb;
+alter table mysql.help_relation type=innodb;
+
+help 'function_of_my_dream';
+help '%ble_f%';
+help 'impossible_func%';
+help 'impossible_category%';
+help 'impossible_%';
+help '%function_2';
+help '%category_2';
+help 'impossible_function_1';
+help 'impossible_category_1';
+
+alter table mysql.help_topic type=myisam;
+alter table mysql.help_category type=myisam;
+alter table mysql.help_relation type=myisam;
diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test
index bc2839bfb3a..ba4ec4a9ae4 100644
--- a/mysql-test/t/innodb-deadlock.test
+++ b/mysql-test/t/innodb-deadlock.test
@@ -2,7 +2,10 @@
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
-drop table if exists t1;
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
#
# Testing of FOR UPDATE
@@ -36,3 +39,75 @@ select * from t1;
commit;
drop table t1;
+#
+# Testing of FOR UPDATE
+#
+
+connection con1;
+create table t1 (id integer, x integer) type=INNODB;
+create table t2 (b integer, a integer) type=INNODB;
+insert into t1 values(0, 0), (300, 300);
+insert into t2 values(0, 10), (1, 20), (2, 30);
+commit;
+set autocommit=0;
+select * from t2;
+update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE);
+select * from t2;
+select * from t1;
+
+connection con2;
+set autocommit=0;
+
+# The following query should hang because con1 is locking the page
+--send
+update t1 set x=2 where id = 0;
+--sleep 2;
+
+connection con1;
+update t1 set x=1 where id = 0;
+select * from t1;
+commit;
+
+connection con2;
+reap;
+commit;
+
+connection con1;
+select * from t1;
+commit;
+
+drop table t1, t2;
+create table t1 (id integer, x integer) type=INNODB;
+create table t2 (b integer, a integer) type=INNODB;
+insert into t1 values(0, 0), (300, 300);
+insert into t2 values(0, 0), (1, 20), (2, 30);
+commit;
+
+connection con1;
+select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
+select * from t2;
+select * from t1;
+
+connection con2;
+
+# The following query should hang because con1 is locking the page
+update t2 set a=2 where b = 0;
+select * from t2;
+--send
+update t1 set x=2 where id = 0;
+--sleep 2;
+
+connection con1;
+update t1 set x=1 where id = 0;
+select * from t1;
+commit;
+
+connection con2;
+reap;
+commit;
+
+connection con1;
+select * from t1;
+commit;
+
+drop table t1, t2;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 250b68a3845..f3bf1b21824 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -4,7 +4,10 @@
# Small basic test with ignore
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=innodb;
insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
@@ -664,7 +667,6 @@ DROP TABLE t1;
#
# Test of multi-table-update
#
-drop table if exists t1,t2;
create table t1 (n int(10), d int(10)) type=innodb;
create table t2 (n int(10), d int(10)) type=innodb;
insert into t1 values(1,1),(1,2);
diff --git a/mysql-test/t/innodb_cache.test b/mysql-test/t/innodb_cache.test
index 9066a5f19ba..8a08c19703d 100644
--- a/mysql-test/t/innodb_cache.test
+++ b/mysql-test/t/innodb_cache.test
@@ -1,10 +1,14 @@
-- source include/have_innodb.inc
-- source include/have_query_cache.inc
+# Initialise
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
#
# Without auto_commit.
#
-drop table if exists t1, t2, t3;
flush status;
set autocommit=0;
create table t1 (a int not null) type=innodb;
diff --git a/mysql-test/t/innodb_handler.test b/mysql-test/t/innodb_handler.test
index 6b85be9c7ab..49178a6b6b7 100644
--- a/mysql-test/t/innodb_handler.test
+++ b/mysql-test/t/innodb_handler.test
@@ -4,7 +4,10 @@
# test of HANDLER ...
#
-drop table if exists t1;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a int, b char(10), key a(a), key b(a,b)) type=innodb;
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
diff --git a/mysql-test/t/ins000001.test b/mysql-test/t/ins000001.test
index 4d75b4e7fe3..afcd27ebfca 100644
--- a/mysql-test/t/ins000001.test
+++ b/mysql-test/t/ins000001.test
@@ -1,5 +1,8 @@
use test;
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (email varchar(50));
insert into t1 values ('sasha@mysql.com'),('monty@mysql.com'),
('foo@hotmail.com'),('foo@aol.com'),('bar@aol.com');
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 9b06b522028..bfa8aac7a1f 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -2,7 +2,10 @@
# Test of refering to old values
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a int not null);
insert into t1 values (1);
insert into t1 values (a+2);
@@ -54,9 +57,11 @@ drop table t1;
# Test of mysqld crash with fully qualified column names
#
-drop database if exists foo;
-create database foo;
-use foo;
+--disable_warnings
+drop database if exists test_$1;
+--enable_warnings
+create database test_$1;
+use test_$1;
create table t1 (c int);
-insert into foo.t1 set foo.t1.c = '1';
-drop database foo;
+insert into test_$1.t1 set test_$1.t1.c = '1';
+drop database test_$1;
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 42f65858d77..8fcb22e4684 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -2,7 +2,10 @@
# Problem with INSERT ... SELECT
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL);
insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12);
create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY);
@@ -12,13 +15,13 @@ insert into t2 (payoutID) SELECT payoutID+10 FROM t1;
insert ignore into t2 (payoutID) SELECT payoutID+10 FROM t1;
select * from t2;
drop table t1,t2;
+
#
# bug in bulk insert optimization
# test case by Fournier Jocelyn <joc@presence-pc.com>
#
-DROP TABLE IF EXISTS crash1,crash2;
-CREATE TABLE `crash1` (
+CREATE TABLE `t1` (
`numeropost` bigint(20) unsigned NOT NULL default '0',
`icone` tinyint(4) unsigned NOT NULL default '0',
`numreponse` bigint(20) unsigned NOT NULL auto_increment,
@@ -34,7 +37,7 @@ CREATE TABLE `crash1` (
KEY `numreponse` (`numreponse`)
) TYPE=MyISAM;
-CREATE TABLE `crash2` (
+CREATE TABLE `t2` (
`numeropost` bigint(20) unsigned NOT NULL default '0',
`icone` tinyint(4) unsigned NOT NULL default '0',
`numreponse` bigint(20) unsigned NOT NULL auto_increment,
@@ -50,21 +53,21 @@ CREATE TABLE `crash2` (
KEY `numreponse` (`numreponse`)
) TYPE=MyISAM;
-INSERT INTO crash2
+INSERT INTO t2
(numeropost,icone,numreponse,contenu,pseudo,date,ip,signature) VALUES
(9,1,56,'test','joce','2001-07-25 13:50:53'
,3649052399,0);
-INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
-SELECT 1618,icone,contenu,pseudo,date,signature,ip FROM crash2
+INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1618,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC;
show variables like '%bulk%';
-INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
-SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2
+INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC;
-DROP TABLE IF EXISTS crash1,crash2;
+DROP TABLE IF EXISTS t1,t2;
diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test
new file mode 100644
index 00000000000..f40391554cc
--- /dev/null
+++ b/mysql-test/t/insert_update.test
@@ -0,0 +1,24 @@
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
+INSERT t1 VALUES (1,2,10), (3,4,20);
+INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100;
+SELECT * FROM t1;
+INSERT t1 VALUES (5,7,40) ON DUPLICATE KEY UPDATE c=c+100;
+SELECT * FROM t1;
+INSERT t1 VALUES (8,4,50) ON DUPLICATE KEY UPDATE c=c+1000;
+SELECT * FROM t1;
+INSERT t1 VALUES (1,4,60) ON DUPLICATE KEY UPDATE c=c+10000;
+SELECT * FROM t1;
+-- error 1062
+INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE c=c+100000, b=4;
+SELECT * FROM t1;
+TRUNCATE TABLE t1;
+INSERT t1 VALUES (1,2,10), (3,4,20);
+INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100;
+SELECT * FROM t1;
+INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0;
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/isam.test b/mysql-test/t/isam.test
index c7308c4b999..fc2dbac439c 100644
--- a/mysql-test/t/isam.test
+++ b/mysql-test/t/isam.test
@@ -1,6 +1,8 @@
-- source include/have_isam.inc
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
#
# Test possible problem with rows that are about 65535 bytes long
@@ -41,10 +43,14 @@ drop table t1;
#
# Test of some CREATE TABLE's that should fail
#
-!$1121 create table t1 (a int,b text, index(a)) type=isam;
-!$1073 create table t1 (a int,b text, index(b)) type=isam;
-!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=isam;
-!$1121 create table t1 (ordid int(8), unique (ordid)) type=isam;
+--error 1121
+create table t1 (a int,b text, index(a)) type=isam;
+--error 1073
+create table t1 (a int,b text, index(b)) type=isam;
+--error 1075
+create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=isam;
+--error 1121
+create table t1 (ordid int(8), unique (ordid)) type=isam;
drop table if exists t1;
#
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 70980f656ab..59c0c37e40d 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -1,6 +1,8 @@
#
# Initialization
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
#
# Test different join syntaxes
@@ -25,7 +27,6 @@ drop table t1,t2;
# This failed for lia Perminov
#
-
create table t1 (id int primary key);
create table t2 (id int);
insert into t1 values (75);
diff --git a/mysql-test/t/join_crash.test b/mysql-test/t/join_crash.test
index 4606b23f726..ada6e56e664 100644
--- a/mysql-test/t/join_crash.test
+++ b/mysql-test/t/join_crash.test
@@ -2,7 +2,10 @@
# This test gave a core dump
#
+--disable_warnings
DROP TABLE IF EXISTS t1,t2,t3,t4;
+--enable_warnings
+
CREATE TABLE t1 (
project_id int(11) NOT NULL auto_increment,
project_row_lock int(11) NOT NULL default '0',
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index af5f377afb5..bfeb5bbb06b 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -2,7 +2,9 @@
# test of left outer join
#
+--disable_warnings
drop table if exists t1,t2,t3,t4,t5;
+--enable_warnings
CREATE TABLE t1 (
grp int(11) default NULL,
@@ -109,7 +111,6 @@ drop table t1,t2;
# Test of LEFT JOIN with const tables (failed for frankie@etsetb.upc.es)
#
-drop table if exists t1,t2,t3,t4;
CREATE TABLE t1 (
cod_asig int(11) DEFAULT '0' NOT NULL,
desc_larga_cat varchar(80) DEFAULT '' NOT NULL,
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index 1996c793880..4fd8cc86dd5 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -2,7 +2,10 @@
# This failed for Elizabeth Mattijsen
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
+
CREATE TABLE t1 (
ID CHAR(32) NOT NULL,
name CHAR(32) NOT NULL,
@@ -173,7 +176,6 @@ drop table t1;
# Problem with UNIQUE() with NULL parts and auto increment
#
-DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c CHAR(10) NOT NULL,i INT NOT NULL AUTO_INCREMENT,
UNIQUE (c,i));
INSERT INTO t1 (c) VALUES (NULL),(NULL);
diff --git a/mysql-test/t/key_diff.test b/mysql-test/t/key_diff.test
index 60afb5f81a4..b4e4339ae33 100644
--- a/mysql-test/t/key_diff.test
+++ b/mysql-test/t/key_diff.test
@@ -1,7 +1,10 @@
#
# Check on condition on different length keys.
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
CREATE TABLE t1 (
a char(5) NOT NULL,
b char(4) NOT NULL,
diff --git a/mysql-test/t/key_primary.test b/mysql-test/t/key_primary.test
index 2cdb117128f..816365c517c 100644
--- a/mysql-test/t/key_primary.test
+++ b/mysql-test/t/key_primary.test
@@ -2,7 +2,10 @@
# test of primary key conversions
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (t1 char(3) primary key);
insert into t1 values("ABC");
insert into t1 values("ABA");
diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test
index 3bd757aa069..e7ec63afe54 100644
--- a/mysql-test/t/keywords.test
+++ b/mysql-test/t/keywords.test
@@ -2,7 +2,10 @@
# Test keywords as fields
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (time time, date date, timestamp timestamp);
insert into t1 values ("12:22:22","97:02:03","1997-01-02");
select * from t1;
diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test
index 6bcc43ac916..65d4f27059f 100644
--- a/mysql-test/t/kill.test
+++ b/mysql-test/t/kill.test
@@ -11,7 +11,10 @@ connect (con2, localhost, root,,);
#remember id of con1
connection con1;
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (kill_id int);
insert into t1 values(connection_id());
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index d4f6ce186cf..88a9831aa68 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -2,7 +2,10 @@
# Test of update and delete with limit
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a int primary key, b int not null);
insert into t1 () values (); -- Testing default values
insert into t1 values (1,1),(2,1),(3,1);
diff --git a/mysql-test/t/lock.test b/mysql-test/t/lock.test
index 385713174d2..0868cf2c4b1 100644
--- a/mysql-test/t/lock.test
+++ b/mysql-test/t/lock.test
@@ -2,7 +2,9 @@
# Testing of table locking
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
CREATE TABLE t1 ( `id` int(11) NOT NULL default '0', `id2` int(11) NOT NULL default '0', `id3` int(11) NOT NULL default '0', `dummy1` char(30) default NULL, PRIMARY KEY (`id`,`id2`), KEY `index_id3` (`id3`)) TYPE=MyISAM;
insert into t1 (id,id2) values (1,1),(1,2),(1,3);
LOCK TABLE t1 WRITE;
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index 792ae956e2a..0c6c59d0444 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -6,8 +6,11 @@
#
-- source include/not_embedded.inc
+--disable_warnings
drop table if exists t1;
-#test to see if select will get the lock ahead of low priority update
+--enable_warnings
+
+# Test to see if select will get the lock ahead of low priority update
connect (locker,localhost,root,,);
connect (reader,localhost,root,,);
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index 0d04e6c7df7..f3a747c4d61 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -2,7 +2,10 @@
# Test of --lower-case-table-names
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
+
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c');
SELECT * FROM t1;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index e2cd8b57b7e..7a7678afca1 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -2,7 +2,10 @@
# test of MERGE TABLES
#
+--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6;
+--enable_warnings
+
create table t1 (a int not null primary key auto_increment, message char(20));
create table t2 (a int not null primary key auto_increment, message char(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
@@ -49,6 +52,7 @@ select * from t4;
create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
# Because of windows, it's important that we drop the merge tables first!
+# This should give a warning on table t5
drop table if exists t5,t4,t3,t1,t2;
create table t1 (c char(10)) type=myisam;
@@ -110,10 +114,9 @@ select * from t1;
drop table t1;
#
-# Bug found by Monty.
+# Bug in flush tables combined with MERGE tables
#
-drop table if exists t3, t2, t1;
create table t1 (a int not null, b int not null, key(a,b));
create table t2 (a int not null, b int not null, key(a,b));
create table t3 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2);
@@ -127,7 +130,6 @@ drop table t3,t1,t2;
# [phi] testing INSERT_METHOD stuff
#
-drop table if exists t6, t5, t4, t3, t2, t1;
# first testing of common stuff with new parameters
create table t1 (a int not null, b int not null auto_increment, primary key(a,b));
create table t2 (a int not null, b int not null auto_increment, primary key(a,b));
@@ -181,15 +183,14 @@ CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '
INSERT INTO t1 VALUES (1,1), (2,1);
CREATE TABLE t2 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
INSERT INTO t2 VALUES (1,2), (2,2);
-CREATE TABLE t ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
-select max(b) from t where a = 2;
+CREATE TABLE t3 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
+select max(b) from t3 where a = 2;
select max(b) from t1 where a = 2;
-drop table if exists t,t1,t2;
+drop table if exists t3,t1,t2;
#
# temporary merge tables
#
-drop table if exists t1, t2, t3, t4, t5, t6;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
@@ -202,13 +203,12 @@ insert into t4 values (1);
insert into t5 values (2);
create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
select * from t6;
-drop table if exists t1, t2, t3, t4, t5, t6;
+drop table if exists t6, t3, t1, t2, t4, t5;
#
# testing merge::records_in_range and optimizer
#
-DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (
fileset_id tinyint(3) unsigned NOT NULL default '0',
file_code varchar(32) NOT NULL default '',
@@ -235,5 +235,5 @@ EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
-DROP TABLE IF EXISTS t1, t2;
+DROP TABLE t2, t1;
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 088b355a17c..6156da82ec0 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -2,7 +2,10 @@
# Test of update statement that uses many tables.
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
+
create table t1(id1 int not null auto_increment primary key, t char(12));
create table t2(id2 int not null, t char(12));
create table t3(id3 int not null, t char(12), index(id3));
@@ -99,7 +102,7 @@ INSERT INTO t3 VALUES (1,'2002-02-04 00:00:00'),(3,'2002-05-12 00:00:00'),(5,'20
00:00:00'),(7,'2002-07-22 00:00:00');
delete t1,t2,t3 from t1,t2,t3 where to_days(now())-to_days(t3.mydate)>=30 and t3.id=t1.id and t3.id=t2.id;
select * from t3;
-DROP TABLE IF EXISTS t1,t2,t3;
+DROP TABLE t1,t2,t3;
CREATE TABLE IF NOT EXISTS `t1` (
`id` int(11) NOT NULL auto_increment,
@@ -127,8 +130,7 @@ select * from t2;
UPDATE t2, t1 SET t2.tst = t1.tst, t2.tst1 = t1.tst1 WHERE t2.ParId = t1.Id;
select * from t2;
-
-drop table if exists t1, t2 ;
+drop table t1, t2 ;
create table t1 (n numeric(10));
create table t2 (n numeric(10));
@@ -213,8 +215,14 @@ insert into t2 values(1,10),(1,20);
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
select * from t1;
select * from t2;
+UPDATE t1 a ,t2 b SET a.d=b.d,b.d=30 WHERE a.n=b.n;
+select * from t1;
+select * from t2;
+DELETE t1, t2 FROM t1 a,t2 b where a.n=b.n;
+select * from t1;
+select * from t2;
drop table t1,t2;
-drop table if exists t1,t2,t3;
+
CREATE TABLE t1 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,'jedan'),(2,'dva'),(3,'tri'),(4,'xxxxxxxxxx'),(5,'a'),(10,''),(11,''),(12,''),(13,'');
CREATE TABLE t2 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
@@ -223,4 +231,4 @@ CREATE TABLE t3 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT
INSERT INTO t3 VALUES (1,'jedan'),(2,'dva');
update t1,t2 set t1.naziv="aaaa" where t1.broj=t2.broj;
update t1,t2,t3 set t1.naziv="bbbb", t2.naziv="aaaa" where t1.broj=t2.broj and t2.broj=t3.broj;
-drop table if exists t1,t2,t3;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index c96a21e73dd..3cce93840e0 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -3,7 +3,9 @@
#
# Initialise
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
#
# Test problem with CHECK TABLE;
@@ -11,7 +13,7 @@ drop table if exists t1,t2;
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
- KEY STRING_DATA (STRING_DATA)
+ KEY string_data (STRING_DATA)
) TYPE=MyISAM;
INSERT INTO t1 VALUES ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
@@ -88,7 +90,6 @@ DROP TABLE t1;
# in ha_myisam::repair, and index size is changed (decreased).
#
-drop table if exists t1;
create table t1 ( t1 char(255), key(t1(250)));
insert t1 values ('137513751375137513751375137513751375137569516951695169516951695169516951695169');
insert t1 values ('178417841784178417841784178417841784178403420342034203420342034203420342034203');
@@ -127,7 +128,6 @@ drop table t1;
# test of myisam with huge number of packed fields
#
-drop table if exists t1;
create table t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
@@ -292,7 +292,7 @@ insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
-drop table if exists t1;
+drop table t1;
#
# Test of REPAIR that once failed
@@ -349,4 +349,15 @@ explain select * from t1,t2 where t1.b=t2.b;
explain select * from t1,t2 force index(c) where t1.a=t2.a;
explain select * from t1 where a=0 or a=2;
explain select * from t1 force index (a) where a=0 or a=2;
+explain select * from t1 where c=1;
+explain select * from t1 use index() where c=1;
drop table t1,t2;
+
+#
+# Test RTREE index
+#
+--error 1235
+CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
+# INSERT INTO t1 VALUES (1,1),(1,1);
+# DELETE FROM rt WHERE a<1;
+DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 6fea7f0d10d..fa36249dce0 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -1,3 +1,8 @@
+# Initialise
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
#
# Testing of NULL in a lot of different places
#
@@ -15,7 +20,6 @@ SELECT (NULL OR NULL) IS NULL;
select NULL AND 0, 0 and NULL;
select inet_ntoa(null),inet_aton(null),inet_aton("122.256"),inet_aton("122.226."),inet_aton("");
-drop table if exists t1;
create table t1 (x int);
insert into t1 values (null);
select * from t1 where x != 0;
diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test
index b1cbd5cdfb0..18d0d368891 100644
--- a/mysql-test/t/null_key.test
+++ b/mysql-test/t/null_key.test
@@ -1,7 +1,10 @@
#
# Check null keys
-drop table if exists t1;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a int, b int not null,unique key (a,b),index(b)) type=myisam;
insert ignore into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(null,7),(9,9),(8,8),(7,7),(null,9),(null,9),(6,6);
explain select * from t1 where a is null;
@@ -51,7 +54,6 @@ drop table t1;
# The following failed for Matt Loschert
#
-DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 (
id int(10) unsigned NOT NULL auto_increment,
uniq_id int(10) unsigned default NULL,
diff --git a/mysql-test/t/odbc.test b/mysql-test/t/odbc.test
index 3e0fc214d3e..9aac5948359 100644
--- a/mysql-test/t/odbc.test
+++ b/mysql-test/t/odbc.test
@@ -1,3 +1,8 @@
+# Initialise
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
#
# Test some ODBC compatibility
#
@@ -8,7 +13,6 @@ select {fn length("hello")}, { date "1997-10-20" };
# Test retreiving row with last insert_id value.
#
-drop table if exists t1;
create table t1 (a int not null auto_increment,b int not null,primary key (a,b));
insert into t1 SET A=NULL,B=1;
insert into t1 SET a=null,b=2;
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index 8fe547db615..99bb2656001 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -1,6 +1,9 @@
-drop table if exists sales;
-create table sales ( product varchar(32), country varchar(32), year int, profit int);
-insert into sales values ( 'Computer', 'India',2000, 1200),
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 ( product varchar(32), country varchar(32), year int, profit int);
+insert into t1 values ( 'Computer', 'India',2000, 1200),
( 'TV', 'United States', 1999, 150),
( 'Calculator', 'United States', 1999,50),
( 'Computer', 'United States', 1999,1500),
@@ -15,13 +18,14 @@ insert into sales values ( 'Computer', 'India',2000, 1200),
( 'Computer', 'United States', 2000,1500),
( 'Calculator', 'United States', 2000,75);
--error 1235
-select product, country , year, sum(profit) from sales group by product, country, year with cube;
+select product, country , year, sum(profit) from t1 group by product, country, year with cube;
--error 1235
-explain select product, country , year, sum(profit) from sales group by product, country, year with cube;
+explain select product, country , year, sum(profit) from t1 group by product, country, year with cube;
--error 1235
-select product, country , year, sum(profit) from sales group by product, country, year with rollup;
+select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
--error 1235
-explain select product, country , year, sum(profit) from sales group by product, country, year with rollup;
+explain select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
--error 1235
-select product, country , year, sum(profit) from sales group by product, country, year with cube union all select product, country , year, sum(profit) from sales group by product, country, year with rollup;
-drop table sales;
+select product, country , year, sum(profit) from t1 group by product, country, year with cube union all select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
+drop table t1;
+
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 8291a475d5e..f7677709ca4 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -2,7 +2,9 @@
# Bug with order by
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
CREATE TABLE t1 (
id int(6) DEFAULT '0' NOT NULL,
@@ -168,7 +170,6 @@ drop table t1,t2,t3;
#bug reported by Wouter de Jong
-drop table if exists t1;
CREATE TABLE t1 (
member_id int(11) NOT NULL auto_increment,
inschrijf_datum varchar(20) NOT NULL default '',
@@ -331,3 +332,24 @@ INSERT INTO t2 (numeropost,pseudo) VALUES (1,'joce'),(1,'bug');
SELECT titre,t1.numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
drop table t1,t2;
+
+#
+# Test of test_if_subkey() function
+#
+
+CREATE TABLE t1 (
+ FieldKey varchar(36) NOT NULL default '',
+ LongVal bigint(20) default NULL,
+ StringVal mediumtext,
+ KEY FieldKey (FieldKey),
+ KEY LongField (FieldKey,LongVal),
+ KEY StringField (FieldKey,StringVal(32))
+);
+INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
+EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
+SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
+EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
+SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
+EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
+SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
+DROP TABLE t1;
diff --git a/mysql-test/t/order_fill_sortbuf.test b/mysql-test/t/order_fill_sortbuf.test
index 6419f2a93df..37620ebe331 100644
--- a/mysql-test/t/order_fill_sortbuf.test
+++ b/mysql-test/t/order_fill_sortbuf.test
@@ -3,7 +3,10 @@
# rows MySQL needs to use a merge during the sort phase.
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
CREATE TABLE `t1` (
`id` int(11) NOT NULL default '0',
`id2` int(11) NOT NULL default '0',
diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test
index c126d221bd2..a944df01051 100644
--- a/mysql-test/t/outfile.test
+++ b/mysql-test/t/outfile.test
@@ -21,3 +21,8 @@
#select * into dumpfile "/tmp/select-test.99" from t1;
#select load_file("/tmp/select-test.not-exist");
#drop table t1;
+#drop table if exists t;
+#CREATE TABLE t ( t timestamp NOT NULL, c char(200) character set latin1 NOT NULL default '', i int(11), v varchar(200), b blob, KEY t (t)) TYPE=MyISAM;
+#INSERT INTO t VALUES ('2002-12-20 12:01:20','',1,"aaa","bbb");
+#select * from t into outfile "check";
+#drop table if exists t;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index f77ea3c3b2a..5f2cf8b5f56 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -10,7 +10,10 @@ flush query cache; # This crashed in some versions
flush query cache; # This crashed in some versions
reset query cache;
flush status;
+--disable_warnings
+drop database if exists mysqltest;
drop table if exists t1,t2,t3,t11,t21, mysqltest.t1;
+--enable_warnings
#
# First simple test
@@ -368,6 +371,7 @@ select * from t2;
show status like "Qcache_queries_in_cache";
select * from t3;
show status like "Qcache_queries_in_cache";
+update t1 set i=(select distinct 1 from (select * from t2) a);
drop table t1, t2, t3;
#
diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test
index 8b608c1069f..38c740201bc 100644
--- a/mysql-test/t/raid.test
+++ b/mysql-test/t/raid.test
@@ -5,7 +5,10 @@ show variables like "have_raid";
# Test of raided tables
#
+--disable_warnings
DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+
CREATE TABLE t1 (
id int unsigned not null auto_increment primary key,
c char(255) not null
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 278807eeea4..31b3ced6cc6 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -2,7 +2,10 @@
# Problem med range optimizer
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
CREATE TABLE t1 (
event_date date DEFAULT '0000-00-00' NOT NULL,
type int(11) DEFAULT '0' NOT NULL,
diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test
index ce4651d8de3..48a9cb401d9 100644
--- a/mysql-test/t/rename.test
+++ b/mysql-test/t/rename.test
@@ -2,7 +2,10 @@
# Test of rename table
#
+--disable_warnings
drop table if exists t0,t1,t2,t3,t4;
+--enable_warnings
+
create table t0 SELECT 1,"table 1";
create table t2 SELECT 2,"table 2";
create table t3 SELECT 3,"table 3";
@@ -29,4 +32,6 @@ rename table t3 to t4, t5 to t3, t1 to t2, t4 to t1;
select * from t1;
select * from t2;
select * from t3;
+
+# This should give a warning for t4
drop table if exists t1,t2,t3,t4;
diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test
index 6d79014b23d..bdc5a57a07c 100644
--- a/mysql-test/t/repair.test
+++ b/mysql-test/t/repair.test
@@ -2,7 +2,10 @@
# Test of repair table
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 SELECT 1,"table 1";
repair table t1 use_frm;
drop table if exists t1;
diff --git a/mysql-test/t/replace.test b/mysql-test/t/replace.test
index e9e01615a62..2afce2fcc84 100644
--- a/mysql-test/t/replace.test
+++ b/mysql-test/t/replace.test
@@ -4,7 +4,9 @@
# Test of REPLACE with ISAM and MyISAM and HEAP
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
CREATE TABLE t1 (
gesuchnr int(11) DEFAULT '0' NOT NULL,
@@ -25,12 +27,13 @@ drop table t1;
# Test when using replace on a key that has used up it's whole range
#
-create table t1 (a tinyint not null auto_increment primary key, b char(20));
-insert into t1 values (126,"first"),(0,"last");
+create table t1 (a tinyint not null auto_increment primary key, b char(20) default "default_value");
+insert into t1 values (126,"first"),(63, "middle"),(0,"last");
--error 1062
insert into t1 values (0,"error");
--error 1062
replace into t1 values (0,"error");
replace into t1 values (126,"first updated");
+replace into t1 values (63,default);
select * from t1;
drop table t1;
diff --git a/mysql-test/t/rollback.test b/mysql-test/t/rollback.test
index 6ea2cca887f..1673f1648d3 100644
--- a/mysql-test/t/rollback.test
+++ b/mysql-test/t/rollback.test
@@ -2,13 +2,20 @@
# This test should fail as MyISAM doesn't have rollback
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (n int not null primary key) type=myisam;
begin work;
insert into t1 values (4);
insert into t1 values (5);
-# Should give an error
-!$1196 rollback;
+rollback;
+select @@warning_count;
+select @@error_count;
+show warnings;
+show errors;
select * from t1;
+select @@warning_count;
+show warnings;
drop table t1;
diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test
new file mode 100644
index 00000000000..9d69e56f9ee
--- /dev/null
+++ b/mysql-test/t/row.test
@@ -0,0 +1,81 @@
+# Initialise
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3));
+select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
+select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
+select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
+select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
+select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
+select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)));
+-- error 1239
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
+
+SELECT (1,2,3)=(0,NULL,3);
+SELECT (1,2,3)=(1,NULL,3);
+# here's something for Sanja to fix :)
+SELECT (1,2,3)=(1,NULL,0);
+
+SELECT ROW(1,2,3)=ROW(1,2,3);
+SELECT ROW(2,2,3)=ROW(1+1,2,3);
+SELECT ROW(1,2,3)=ROW(1+1,2,3);
+SELECT ROW(1,2,3)<ROW(1+1,2,3);
+SELECT ROW(1,2,3)>ROW(1+1,2,3);
+SELECT ROW(1,2,3)<=ROW(1+1,2,3);
+SELECT ROW(1,2,3)>=ROW(1+1,2,3);
+SELECT ROW(1,2,3)<>ROW(1+1,2,3);
+SELECT ROW(NULL,2,3)=ROW(NULL,2,3);
+SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3);
+SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
+-- error 1239
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3));
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
+-- error 1239
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
+
+create table t1 ( a int, b int, c int);
+insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
+select * from t1 where ROW(1,2,3)=ROW(a,b,c);
+select * from t1 where ROW(0,2,3)=ROW(a,b,c);
+select * from t1 where ROW(1,2,3)<ROW(a,b,c);
+select ROW(a,2,3) IN(row(1,b,c), row(2,3,1)) from t1;
+select ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) from t1;
+select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1;
+select ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) from t1;
+drop table t1;
+
+-- error 1239
+select ROW(1,1);
+
+create table t1 (i int);
+-- error 1239
+select 1 from t1 where ROW(1,1);
+-- error 1239
+select count(*) from t1 order by ROW(1,1);
+-- error 1239
+select count(*) from t1 having (1,1) order by i;
+drop table t1;
+
+create table t1 (a int, b int);
+insert into t1 values (1, 4);
+insert into t1 values (10, 40);
+insert into t1 values (1, 4);
+insert into t1 values (10, 43);
+insert into t1 values (1, 4);
+insert into t1 values (10, 41);
+insert into t1 values (1, 4);
+insert into t1 values (10, 43);
+insert into t1 values (1, 4);
+select a, MAX(b), (1, MAX(b)) = (1, 4) from t1 group by a;
+drop table t1;
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 0f195c65fb0..3975f14e523 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -1,5 +1,5 @@
source include/master-slave.inc;
-drop table if exists t1,t2,t3;
+
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
@@ -12,11 +12,11 @@ select * from t1;
save_master_pos;
connection slave;
sync_with_master;
-slave stop;
+stop slave;
connection master;
set password for root@"localhost" = password('foo');
connection slave;
-slave start;
+start slave;
connection master;
#
# Give slave time to do at last one failed connect retry
@@ -43,7 +43,7 @@ sync_with_master;
connection master;
reset master;
connection slave;
-slave stop;
+stop slave;
reset slave;
connection master;
@@ -62,7 +62,7 @@ enable_query_log;
# Try to cause a large relay log lag on the slave
connection slave;
select get_lock("hold_slave",10);
-slave start;
+start slave;
#hope this is long enough for I/O thread to fetch over 16K relay log data
sleep 3;
select release_lock("hold_slave");
@@ -100,7 +100,7 @@ wait_for_slave_to_stop;
# show slave status;
set global sql_slave_skip_counter=1;
-slave start;
+start slave;
select count(*) from t1;
connection master1;
drop table t1;
diff --git a/mysql-test/t/rpl000002.test b/mysql-test/t/rpl000002.test
index caf0b4ef6d8..803eb069b66 100644
--- a/mysql-test/t/rpl000002.test
+++ b/mysql-test/t/rpl000002.test
@@ -1,33 +1,26 @@
source include/master-slave.inc;
-drop table if exists t1;
+
create table t1 (n int auto_increment primary key);
set insert_id = 2000;
insert into t1 values (NULL),(NULL),(NULL);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
select * from t1;
connection master;
--replace_result $SLAVE_MYPORT 9999
show slave hosts;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
-slave stop;
+sync_slave_with_master;
+stop slave;
connection master;
-drop table if exists t2;
create table t2(id int auto_increment primary key, created datetime);
set timestamp=12345;
insert into t2 set created=now();
select * from t2;
save_master_pos;
connection slave;
-slave start;
+start slave;
sync_with_master;
select * from t2;
connection master;
drop table t2;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl000003.test b/mysql-test/t/rpl000003.test
deleted file mode 100644
index f994ed94371..00000000000
--- a/mysql-test/t/rpl000003.test
+++ /dev/null
@@ -1,14 +0,0 @@
-source include/master-slave.inc;
-drop table if exists t1;
-create table t1(n int primary key);
-!insert into t1 values (1),(2),(2);
-insert into t1 values (3);
-save_master_pos;
-connection slave;
-sync_with_master;
-select * from t1;
-connection master;
-drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
diff --git a/mysql-test/t/rpl000004.test b/mysql-test/t/rpl000004.test
index 705e0d51b7b..8fc2977faab 100644
--- a/mysql-test/t/rpl000004.test
+++ b/mysql-test/t/rpl000004.test
@@ -1,18 +1,14 @@
source include/master-slave.inc;
+
set SQL_LOG_BIN=0;
-drop table if exists t1;
create table t1 (word char(20) not null, index(word));
load data infile '../../std_data/words.dat' into table t1;
-drop table if exists t2;
create table t2 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t2;
create table t3 (word char(20) not null primary key);
connection slave;
-drop table if exists t1;
load table t1 from master;
-drop table if exists t2;
load table t2 from master;
-drop table if exists t3;
load table t3 from master;
check table t1;
select count(*) from t2;
diff --git a/mysql-test/t/rpl000005.test b/mysql-test/t/rpl000005.test
index 1cfea242b69..ae713633df3 100644
--- a/mysql-test/t/rpl000005.test
+++ b/mysql-test/t/rpl000005.test
@@ -1,5 +1,5 @@
source include/master-slave.inc;
-drop table if exists t1;
+
CREATE TABLE t1 (name varchar(64), age smallint(3));
INSERT INTO t1 SET name='Andy', age=31;
INSERT t1 SET name='Jacob', age=2;
diff --git a/mysql-test/t/rpl000006.test b/mysql-test/t/rpl000006.test
index ad8622c2a81..c6438062bb7 100644
--- a/mysql-test/t/rpl000006.test
+++ b/mysql-test/t/rpl000006.test
@@ -5,12 +5,10 @@ source include/master-slave.inc;
# Don't log table creating to the slave as we want to test LOAD TABLE
set SQL_LOG_BIN=0,timestamp=200006;
-drop table if exists t1;
create table t1(t timestamp not null,a char(1));
insert into t1 ( a) values ('F');
select unix_timestamp(t) from t1;
connection slave;
-drop table if exists t1;
load table t1 from master;
select unix_timestamp(t) from t1;
diff --git a/mysql-test/t/rpl000008-slave.opt b/mysql-test/t/rpl000008-slave.opt
index 79b3bf6174b..177f89e0910 100644
--- a/mysql-test/t/rpl000008-slave.opt
+++ b/mysql-test/t/rpl000008-slave.opt
@@ -1 +1 @@
---replicate-ignore-table=test.foo
+--replicate-ignore-table=test.mysqltest_foo
diff --git a/mysql-test/t/rpl000008.test b/mysql-test/t/rpl000008.test
index 12760008b6d..ea782b99d28 100644
--- a/mysql-test/t/rpl000008.test
+++ b/mysql-test/t/rpl000008.test
@@ -1,29 +1,36 @@
-#this one assumes we are ignoring updates on table foo, but doing
-#the ones on all other tables
+# This one assumes we are ignoring updates on table mysqltest_foo, but doing
+# the ones on all other tables
+
source include/master-slave.inc;
connection slave;
+
+#
+# For this test we must be in the test database
+#
use test;
-drop table if exists foo;
-create table foo (n int);
-insert into foo values(4);
+
+--disable_warnings
+drop table if exists mysqltest_foo;
+drop table if exists mysqltest_bar;
+--enable_warnings
+
+create table mysqltest_foo (n int);
+insert into mysqltest_foo values(4);
connection master;
use test;
-drop table if exists foo;
-create table foo (n int);
-insert into foo values(5);
-drop table if exists bar;
-create table bar (m int);
-insert into bar values(15);
-drop table if exists choo;
-create table choo (k int);
-insert into choo values(55);
+create table mysqltest_foo (n int);
+insert into mysqltest_foo values(5);
+create table mysqltest_bar (m int);
+insert into mysqltest_bar values(15);
+create table t1 (k int);
+insert into t1 values(55);
save_master_pos;
connection slave;
sync_with_master;
-select foo.n,bar.m,choo.k from foo,bar,choo;
+select mysqltest_foo.n,mysqltest_bar.m,t1.k from mysqltest_foo,mysqltest_bar,t1;
connection master;
-drop table if exists foo,bar,choo;
+drop table mysqltest_foo,mysqltest_bar,t1;
save_master_pos;
connection slave;
sync_with_master;
-drop table if exists foo,bar,choo;
+drop table mysqltest_foo,mysqltest_bar,t1;
diff --git a/mysql-test/t/rpl000009-slave.opt b/mysql-test/t/rpl000009-slave.opt
index 245e310c5d8..c015c02ba78 100644
--- a/mysql-test/t/rpl000009-slave.opt
+++ b/mysql-test/t/rpl000009-slave.opt
@@ -1 +1 @@
---replicate-wild-do-table=bar.%
+--replicate-wild-do-table=mysqltest.%
diff --git a/mysql-test/t/rpl000009.test b/mysql-test/t/rpl000009.test
index 5f55355271a..ffec20c793e 100644
--- a/mysql-test/t/rpl000009.test
+++ b/mysql-test/t/rpl000009.test
@@ -1,38 +1,38 @@
-# This one assumes we are ignoring updates on tables in database foo, but doing
-# the ones in database bar
+# This one assumes we are ignoring updates on tables in database mysqltest2,
+# but doing the ones in database mysqltest
source include/master-slave.inc;
-drop database if exists foo;
-create database foo;
-drop database if exists bar;
-create database bar;
+--disable_warnings
+drop database if exists mysqltest2;
+create database mysqltest2;
+drop database if exists mysqltest;
+create database mysqltest;
+--enable_warnings
+
save_master_pos;
connection slave;
sync_with_master;
-create database foo;
-drop table if exists foo.foo;
-create table foo.foo (n int);
-insert into foo.foo values(4);
+create database mysqltest2;
+create table mysqltest2.foo (n int);
+insert into mysqltest2.foo values(4);
connection master;
-drop table if exists foo.foo;
-create table foo.foo (n int);
-insert into foo.foo values(5);
-drop table if exists bar.bar;
-create table bar.bar (m int);
-insert into bar.bar values(15);
+create table mysqltest2.foo (n int);
+insert into mysqltest2.foo values(5);
+create table mysqltest.bar (m int);
+insert into mysqltest.bar values(15);
save_master_pos;
connection slave;
sync_with_master;
-select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
+select mysqltest2.foo.n,mysqltest.bar.m from mysqltest2.foo,mysqltest.bar;
connection master;
-drop database bar;
-drop database if exists foo;
+drop database mysqltest;
+drop database if exists mysqltest2;
save_master_pos;
connection slave;
sync_with_master;
--error 1008
-drop database bar;
-drop database foo;
+drop database mysqltest;
+drop database mysqltest2;
# Now let's test load data from master
@@ -40,19 +40,19 @@ drop database foo;
connection master;
set sql_log_bin = 0;
-create database foo;
-create database bar;
+create database mysqltest2;
+create database mysqltest;
show databases;
-create table foo.t1(n int, s char(20));
-create table foo.t2(n int, s text);
-insert into foo.t1 values (1, 'one'), (2, 'two'), (3, 'three');
-insert into foo.t2 values (11, 'eleven'), (12, 'twelve'), (13, 'thirteen');
+create table mysqltest2.t1(n int, s char(20));
+create table mysqltest2.t2(n int, s text);
+insert into mysqltest2.t1 values (1, 'one'), (2, 'two'), (3, 'three');
+insert into mysqltest2.t2 values (11, 'eleven'), (12, 'twelve'), (13, 'thirteen');
-create table bar.t1(n int, s char(20));
-create table bar.t2(n int, s text);
-insert into bar.t1 values (1, 'one bar'), (2, 'two bar'), (3, 'three bar');
-insert into bar.t2 values (11, 'eleven bar'), (12, 'twelve bar'),
- (13, 'thirteen bar');
+create table mysqltest.t1(n int, s char(20));
+create table mysqltest.t2(n int, s text);
+insert into mysqltest.t1 values (1, 'one test'), (2, 'two test'), (3, 'three test');
+insert into mysqltest.t2 values (11, 'eleven test'), (12, 'twelve test'),
+ (13, 'thirteen test');
set sql_log_bin = 1;
save_master_pos;
connection slave;
@@ -64,26 +64,25 @@ load data from master;
# Now let's check if we have the right tables and the right data in them
show databases;
-use foo;
+use mysqltest2;
show tables;
-use bar;
+use mysqltest;
show tables;
-select * from bar.t1;
-select * from bar.t2;
+select * from mysqltest.t1;
+select * from mysqltest.t2;
# Now let's see if replication works
connection master;
-insert into bar.t1 values (4, 'four bar');
+insert into mysqltest.t1 values (4, 'four test');
save_master_pos;
connection slave;
sync_with_master;
-select * from bar.t1;
+select * from mysqltest.t1;
# Now time for cleanup
connection master;
-drop database bar;
-drop database foo;
+drop database mysqltest;
+drop database mysqltest2;
save_master_pos;
connection slave;
sync_with_master;
-
diff --git a/mysql-test/t/rpl000010.test b/mysql-test/t/rpl000010.test
index 05a211fbd85..0725214694a 100644
--- a/mysql-test/t/rpl000010.test
+++ b/mysql-test/t/rpl000010.test
@@ -1,10 +1,8 @@
-#this tests the offset off by 22 mystery bug
-#must run slave with --disconnect-slave-event-count=1 --master-connect-retry=1
+# This tests the offset off by 22 mystery bug
+# Must run slave with --disconnect-slave-event-count=1 --master-connect-retry=1
+
source include/master-slave.inc;
-connection slave;
-drop table if exists t1;
-connection master;
-drop table if exists t1;
+
create table t1 (n int not null auto_increment primary key);
insert into t1 values(NULL);
insert into t1 values(2);
diff --git a/mysql-test/t/rpl000011.test b/mysql-test/t/rpl000011.test
index d75937e3f81..3b00afe10e4 100644
--- a/mysql-test/t/rpl000011.test
+++ b/mysql-test/t/rpl000011.test
@@ -1,21 +1,15 @@
source include/master-slave.inc;
-drop table if exists t1;
+
create table t1 (n int);
insert into t1 values(1);
-save_master_pos;
-connection slave;
-sync_with_master;
-slave stop;
-slave start;
+sync_slave_with_master;
+stop slave;
+start slave;
connection master;
insert into t1 values(2);
-save_master_pos;
-connection slave;
#let slave catch up
-sync_with_master;
+sync_slave_with_master;
select * from t1;
connection master;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl000012.test b/mysql-test/t/rpl000012.test
index 9f8ba9a4f91..7f440eaaa13 100644
--- a/mysql-test/t/rpl000012.test
+++ b/mysql-test/t/rpl000012.test
@@ -1,18 +1,16 @@
source include/master-slave.inc;
connection master;
-drop table if exists t1,t2,t3;
create table t2 (n int);
create temporary table t1 (n int);
insert into t1 values(1),(2),(3);
insert into t2 select * from t1;
-drop table if exists test.t3;
-create temporary table test.t3 (n int not null);
-alter table test.t3 add primary key(n);
+create temporary table t3 (n int not null);
+alter table t3 add primary key(n);
flush logs;
insert into t3 values (100);
insert into t2 select * from t3;
-drop table if exists test.t3;
+drop table if exists t3;
insert into t2 values (101);
connection master1;
create temporary table t1 (n int);
diff --git a/mysql-test/t/rpl000013.test b/mysql-test/t/rpl000013.test
index 14619796e01..94d5feb3925 100644
--- a/mysql-test/t/rpl000013.test
+++ b/mysql-test/t/rpl000013.test
@@ -3,7 +3,7 @@ save_master_pos;
connection slave;
sync_with_master;
connection master;
-drop table if exists t2;
+
create table t2(n int);
create temporary table t1 (n int);
insert into t1 values(1),(2),(3);
@@ -31,6 +31,10 @@ show status like 'Slave_open_temp_tables';
#
connect (master2,localhost,root,,);
connection master2;
+
+# We will get a warning for t1 as this is a temporary table that doesn't
+# exist in this connection.
+
drop table if exists t1,t2;
save_master_pos;
connection slave;
diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test
index 26d32ea3e11..b5234373355 100644
--- a/mysql-test/t/rpl000015.test
+++ b/mysql-test/t/rpl000015.test
@@ -18,20 +18,18 @@ eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$MASTER_MYPORT;
--replace_result $MASTER_MYPORT MASTER_PORT
show slave status;
-slave start;
+start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
show slave status;
connection master;
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (n int);
insert into t1 values (10),(45),(90);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
select * from t1;
connection master;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl000016-slave.opt b/mysql-test/t/rpl000016-slave.opt
deleted file mode 100644
index f27601e0d7d..00000000000
--- a/mysql-test/t/rpl000016-slave.opt
+++ /dev/null
@@ -1 +0,0 @@
--O max_binlog_size=2048
diff --git a/mysql-test/t/rpl000017-slave.sh b/mysql-test/t/rpl000017-slave.sh
index 066b4880cc1..4dbbaec31ce 100755
--- a/mysql-test/t/rpl000017-slave.sh
+++ b/mysql-test/t/rpl000017-slave.sh
@@ -1,11 +1,11 @@
rm -f $MYSQL_TEST_DIR/var/log/*relay*
rm -f $MYSQL_TEST_DIR/var/slave-data/relay-log.info
cat > $MYSQL_TEST_DIR/var/slave-data/master.info <<EOF
-master-bin.001
+master-bin.000001
4
127.0.0.1
replicate
-aaaaaaaaaaaaaaabthispartofthepasswordisnotused
+aaaaaaaaaaaaaaab
$MASTER_MYPORT
1
0
diff --git a/mysql-test/t/rpl000017.test b/mysql-test/t/rpl000017.test
index d4f41f1e374..cf808a2cbc0 100644
--- a/mysql-test/t/rpl000017.test
+++ b/mysql-test/t/rpl000017.test
@@ -5,17 +5,15 @@ reset master;
grant replication slave on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
grant replication slave on *.* to replicate@127.0.0.1 identified by 'aaaaaaaaaaaaaaab';
connection slave;
-slave start;
+start slave;
connection master;
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1(n int);
insert into t1 values(24);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
select * from t1;
connection master;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl000018.test b/mysql-test/t/rpl000018.test
index 291b482b912..b8c09ed431d 100644
--- a/mysql-test/t/rpl000018.test
+++ b/mysql-test/t/rpl000018.test
@@ -10,18 +10,16 @@ server_stop master;
server_start master;
connection slave;
reset slave;
-slave start;
+start slave;
connection master;
-show master logs;
+show binary logs;
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1(n int);
insert into t1 values (3351);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
select * from t1;
connection master;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_alter.test b/mysql-test/t/rpl_alter.test
index 710dd2d09d6..6b8cf773150 100644
--- a/mysql-test/t/rpl_alter.test
+++ b/mysql-test/t/rpl_alter.test
@@ -1,19 +1,22 @@
source include/master-slave.inc;
-drop database if exists d1;
-create database d1;
-create table d1.t1 ( n int);
-alter table d1.t1 add m int;
-insert into d1.t1 values (1,2);
-create table d1.t2 (n int);
-insert into d1.t2 values (45);
-rename table d1.t2 to d1.t3, d1.t1 to d1.t2;
+--disable_warnings
+drop database if exists test_$1;
+--enable_warnings
+create database test_$1;
+
+create table test_$1.t1 ( n int);
+alter table test_$1.t1 add m int;
+insert into test_$1.t1 values (1,2);
+create table test_$1.t2 (n int);
+insert into test_$1.t2 values (45);
+rename table test_$1.t2 to test_$1.t3, test_$1.t1 to test_$1.t2;
save_master_pos;
connection slave;
sync_with_master;
-select * from d1.t2;
-select * from d1.t3;
+select * from test_$1.t2;
+select * from test_$1.t3;
connection master;
-drop database d1;
+drop database test_$1;
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/rpl_empty_master_crash.test b/mysql-test/t/rpl_empty_master_crash.test
index afa76ce10bb..9d5a7a173b0 100644
--- a/mysql-test/t/rpl_empty_master_crash.test
+++ b/mysql-test/t/rpl_empty_master_crash.test
@@ -1,6 +1,7 @@
source include/master-slave.inc;
-drop table if exists t1;
+
show slave status;
+
#
# Load table should not succeed on the master as this is not a slave
#
diff --git a/mysql-test/t/rpl_failsafe.test b/mysql-test/t/rpl_failsafe.test
index 866efbce5bf..ae61b061153 100644
--- a/mysql-test/t/rpl_failsafe.test
+++ b/mysql-test/t/rpl_failsafe.test
@@ -7,18 +7,16 @@ show variables like 'rpl_recovery_rank';
show status like 'Rpl_status';
create table t1(n int);
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
show variables like 'rpl_recovery_rank';
show status like 'Rpl_status';
connection slave_sec;
-slave start;
+start slave;
sync_with_master;
show variables like 'rpl_recovery_rank';
show status like 'Rpl_status';
connection slave_ter;
-slave start;
+start slave;
sync_with_master;
show variables like 'rpl_recovery_rank';
show status like 'Rpl_status';
diff --git a/mysql-test/t/rpl_flush_log_loop.test b/mysql-test/t/rpl_flush_log_loop.test
index c68fbb7111a..62bcf2c8b33 100644
--- a/mysql-test/t/rpl_flush_log_loop.test
+++ b/mysql-test/t/rpl_flush_log_loop.test
@@ -7,13 +7,13 @@ connection slave;
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$MASTER_MYPORT;
-slave start;
+start slave;
connection master;
-slave stop;
+stop slave;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$SLAVE_MYPORT;
-slave start;
+start slave;
flush logs;
sleep 5;
--replace_result $SLAVE_MYPORT SLAVE_PORT
diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test
index 3f3636d3082..93062f39c20 100644
--- a/mysql-test/t/rpl_insert_id.test
+++ b/mysql-test/t/rpl_insert_id.test
@@ -1,9 +1,7 @@
-#see if queries that use both
-#auto_increment and LAST_INSERT_ID()
-#are replicated well
+# See if queries that use both auto_increment and LAST_INSERT_ID()
+# are replicated well
source include/master-slave.inc;
connection master;
-drop table if exists t1;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
insert into t1 values (1),(2),(3);
diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test
index 85782e78142..dff57a77a45 100644
--- a/mysql-test/t/rpl_log.test
+++ b/mysql-test/t/rpl_log.test
@@ -2,7 +2,7 @@ source include/master-slave.inc;
#clean up slave binlogs
connection slave;
-slave stop;
+stop slave;
reset master;
reset slave;
let $VERSION=`select version()`;
@@ -26,10 +26,10 @@ flush logs;
save_master_pos;
connection slave;
-slave start;
+start slave;
sync_with_master;
flush logs;
-slave stop;
+stop slave;
connection master;
# Create some entries for second log
@@ -39,27 +39,27 @@ insert into t1 values (1);
drop table t1;
--replace_result $VERSION VERSION
show binlog events;
-show binlog events in 'master-bin.002';
-show master logs;
+show binlog events in 'master-bin.000002';
+show binary logs;
save_master_pos;
connection slave;
-slave start;
+start slave;
sync_with_master;
-show master logs;
+show binary logs;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION
-show binlog events in 'slave-bin.001' from 4;
+show binlog events in 'slave-bin.000001' from 4;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION
-show binlog events in 'slave-bin.002' from 4;
+show binlog events in 'slave-bin.000002' from 4;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
# Need to recode the following
-#show new master for slave with master_log_file='master-bin.001' and master_log_pos=4 and master_server_id=1;
-#show new master for slave with master_log_file='master-bin.001' and master_log_pos=79 and master_server_id=1;
-#show new master for slave with master_log_file='master-bin.001' and master_log_pos=311 and master_server_id=1;
-#show new master for slave with master_log_file='master-bin.002' and master_log_pos=4 and master_server_id=1;
-#show new master for slave with master_log_file='master-bin.002' and master_log_pos=122 and master_server_id=1;
+#show new master for slave with master_log_file='master-bin.000001' and master_log_pos=4 and master_server_id=1;
+#show new master for slave with master_log_file='master-bin.000001' and master_log_pos=79 and master_server_id=1;
+#show new master for slave with master_log_file='master-bin.000001' and master_log_pos=311 and master_server_id=1;
+#show new master for slave with master_log_file='master-bin.000002' and master_log_pos=4 and master_server_id=1;
+#show new master for slave with master_log_file='master-bin.000002' and master_log_pos=122 and master_server_id=1;
--error 1220
-show binlog events in 'slave-bin.005' from 4;
+show binlog events in 'slave-bin.000005' from 4;
diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test
index e11ba92cfa7..bc1349a959a 100644
--- a/mysql-test/t/rpl_log_pos.test
+++ b/mysql-test/t/rpl_log_pos.test
@@ -3,29 +3,28 @@
#
source include/master-slave.inc;
show master status;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
-slave stop;
+stop slave;
change master to master_log_pos=73;
-slave start;
+start slave;
sleep 5;
-slave stop;
+stop slave;
change master to master_log_pos=73;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
-slave start;
+start slave;
sleep 5;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
-slave stop;
+stop slave;
change master to master_log_pos=173;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
-slave start;
+start slave;
sleep 2;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
connection master;
show master status;
@@ -35,13 +34,11 @@ create table t1 (n int);
insert into t1 values (1),(2),(3);
save_master_pos;
connection slave;
-slave stop;
+stop slave;
change master to master_log_pos=79;
-slave start;
+start slave;
sync_with_master;
select * from t1;
connection master;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_mystery22.test b/mysql-test/t/rpl_mystery22.test
index 5280cb360dd..d49f1a210f4 100644
--- a/mysql-test/t/rpl_mystery22.test
+++ b/mysql-test/t/rpl_mystery22.test
@@ -4,9 +4,7 @@ source include/master-slave.inc;
# first, cause a duplicate key problem on the slave
create table t1(n int auto_increment primary key);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
insert into t1 values (2);
connection master;
insert into t1 values(NULL);
@@ -16,11 +14,11 @@ connection slave;
sleep 3; # there is no way around this sleep - we have to wait until
# the slave tries to run the query, fails and aborts slave thread
delete from t1 where n = 2;
-slave start;
+start slave;
sync_with_master;
#now the buggy slave would be confused on the offset but it can replicate
#in order to make it break, we need to stop/start the slave one more time
-slave stop;
+stop slave;
connection master;
# to be able to really confuse the slave, we need some non-auto-increment
# events in the log
@@ -29,7 +27,7 @@ drop table t2;
insert into t1 values(NULL);
save_master_pos;
connection slave;
-slave start;
+start slave;
#now the truth comes out - if the slave is buggy, it will never sync because
#the slave thread is not able to read events
sync_with_master;
@@ -37,7 +35,5 @@ select * from t1;
#clean up
connection master;
drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_redirect.test b/mysql-test/t/rpl_redirect.test
index 4082542f295..181d200b761 100644
--- a/mysql-test/t/rpl_redirect.test
+++ b/mysql-test/t/rpl_redirect.test
@@ -19,7 +19,6 @@ rpl_probe;
#turn on master/slave query direction auto-magic
enable_rpl_parse;
-drop table if exists t1;
create table t1 ( n int);
insert into t1 values (1),(2),(3),(4);
disable_rpl_parse;
diff --git a/mysql-test/t/rpl_replicate_do.test b/mysql-test/t/rpl_replicate_do.test
index 0800062dc05..dcb3c5034fd 100644
--- a/mysql-test/t/rpl_replicate_do.test
+++ b/mysql-test/t/rpl_replicate_do.test
@@ -2,9 +2,12 @@
# updates on t1
source include/master-slave.inc;
+--disable_warnings
drop table if exists t11;
connection slave;
drop table if exists t11;
+--enable_warnings
+
create table t2 (n int);
insert into t2 values(4);
connection master;
@@ -24,7 +27,7 @@ select * from t2;
--error 1146
select * from t11;
connection master;
-drop table if exists t1,t2,t3,t11;
+drop table if exists t1,t2,t11;
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index 6edbf363b1a..52c7bc290bb 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -1,5 +1,5 @@
#
-# Test are run with max_binlog_size=2048 to force automatic rotation of the
+# Test is run with max_binlog_size=2048 to force automatic rotation of the
# binary log
# Tests done:
# - Check that slaves reports correct failures if master.info has strange
@@ -8,19 +8,23 @@
# - Ensure that temporary tables works over flush logs and binary log
# changes
# - Test creating a duplicate key error and recover from it
-#
+
connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock);
+--disable_warnings
drop table if exists t1, t2, t3, t4;
+--enable_warnings
connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock);
system cat /dev/null > var/slave-data/master.info;
system chmod 000 var/slave-data/master.info;
connection slave;
+--disable_warnings
drop table if exists t1, t2, t3, t4;
+--enable_warnings
--error 1201
-slave start;
+start slave;
system chmod 600 var/slave-data/master.info;
--error 1201
-slave start;
+start slave;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
# Will get error 13 on Unix systems becasue file is not readable
!eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
@@ -30,7 +34,7 @@ eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master
connection master;
reset master;
connection slave;
-slave start;
+start slave;
connection master;
#
@@ -40,24 +44,19 @@ create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables");
create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
select * from t1;
connection master;
flush logs;
-drop table if exists t2;
create table t2(m int not null auto_increment primary key);
insert into t2 values (34),(67),(123);
flush logs;
-show master logs;
+show binary logs;
create table t3 select * from temp_table;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
select * from t3;
connection master;
@@ -83,21 +82,17 @@ wait_for_slave_to_stop;
#restart slave skipping one event
set global sql_slave_skip_counter=1;
-slave start;
+start slave;
connection master;
-save_master_pos;
#let slave catch up
-connection slave;
-sync_with_master;
+sync_slave_with_master;
connection master;
-purge master logs to 'master-bin.003';
-show master logs;
+purge master logs to 'master-bin.000003';
+show binary logs;
insert into t2 values (65);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
select * from t2;
@@ -110,7 +105,7 @@ connection master;
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables part 2");
let $1=100;
-drop table if exists t3;
+
create table t3 (n int);
disable_query_log;
while ($1)
@@ -121,12 +116,12 @@ while ($1)
}
enable_query_log;
create table t4 select * from temp_table;
-show master logs;
+show binary logs;
show master status;
save_master_pos;
connection slave;
-#slave stop;
-#slave start;
+#stop slave;
+#start slave;
sync_with_master;
select * from t4;
@@ -140,6 +135,4 @@ unlock tables;
#clean up
connection master;
drop table if exists t1,t2,t3,t4;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_skip_error.test b/mysql-test/t/rpl_skip_error.test
index d43c59ef024..86c89c70314 100644
--- a/mysql-test/t/rpl_skip_error.test
+++ b/mysql-test/t/rpl_skip_error.test
@@ -1,5 +1,4 @@
source include/master-slave.inc;
-drop table if exists t1;
create table t1 (n int not null primary key);
save_master_pos;
diff --git a/mysql-test/t/rpl_sporadic_master.test b/mysql-test/t/rpl_sporadic_master.test
index e59b93b4475..b24901c62a9 100644
--- a/mysql-test/t/rpl_sporadic_master.test
+++ b/mysql-test/t/rpl_sporadic_master.test
@@ -9,22 +9,16 @@ insert into t1 values (NULL),(NULL);
truncate table t1;
# We have to use 4 in the following to make this test work with all table types
insert into t1 values (4),(NULL);
-save_master_pos;
-connection slave;
-sync_with_master;
-slave stop;
-slave start;
+sync_slave_with_master;
+stop slave;
+start slave;
connection master;
insert into t1 values (NULL),(NULL);
flush logs;
truncate table t1;
insert into t1 values (10),(NULL),(NULL),(NULL),(NULL),(NULL);
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
select * from t1;
connection master;
drop table t1,t2;
-save_master_pos;
-connection slave;
-sync_with_master;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test
new file mode 100644
index 00000000000..f91880537e6
--- /dev/null
+++ b/mysql-test/t/rpl_temporary.test
@@ -0,0 +1,82 @@
+source include/master-slave.inc;
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+let $VERSION=`select version()`;
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1(f int);
+create table t2(f int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+connection con1;
+create temporary table t3(f int);
+insert into t3 select * from t1 where f<6;
+sleep 1;
+
+connection con2;
+create temporary table t3(f int);
+sleep 1;
+
+connection con1;
+insert into t2 select count(*) from t3;
+sleep 1;
+
+connection con2;
+insert into t3 select * from t1 where f>=4;
+sleep 1;
+
+connection con1;
+drop temporary table t3;
+sleep 1;
+
+connection con2;
+insert into t2 select count(*) from t3;
+drop temporary table t3;
+
+select * from t2;
+
+--replace_result $VERSION VERSION
+show binlog events;
+
+drop table t1, t2;
+
+use test;
+SET TIMESTAMP=1040323920;
+create table t1(f int);
+SET TIMESTAMP=1040323931;
+create table t2(f int);
+SET TIMESTAMP=1040323938;
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+SET TIMESTAMP=1040323945;
+SET @@session.pseudo_thread_id=1;
+create temporary table t3(f int);
+SET TIMESTAMP=1040323952;
+SET @@session.pseudo_thread_id=1;
+insert into t3 select * from t1 where f<6;
+SET TIMESTAMP=1040324145;
+SET @@session.pseudo_thread_id=2;
+create temporary table t3(f int);
+SET TIMESTAMP=1040324186;
+SET @@session.pseudo_thread_id=1;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324200;
+SET @@session.pseudo_thread_id=2;
+insert into t3 select * from t1 where f>=4;
+SET TIMESTAMP=1040324211;
+SET @@session.pseudo_thread_id=1;
+drop temporary table t3;
+SET TIMESTAMP=1040324219;
+SET @@session.pseudo_thread_id=2;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324224;
+SET @@session.pseudo_thread_id=2;
+drop temporary table t3;
+
+select * from t2;
+drop table t1,t2;
diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test
new file mode 100644
index 00000000000..7de52367fba
--- /dev/null
+++ b/mysql-test/t/rpl_user_variables.test
@@ -0,0 +1,39 @@
+source include/master-slave.inc;
+connection master;
+save_master_pos;
+connection slave;
+sync_with_master;
+stop slave;
+reset master;
+connection master;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1(n char(30));
+set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1;
+set @s1:='This is a test', @r1:=12.5, @r2:=-12.5;
+set @n1:=null;
+set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def';
+insert into t1 values (@i1), (@i2), (@i3), (@i4);
+insert into t1 values (@r1), (@r2);
+insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5);
+insert into t1 values (@n1);
+insert into t1 values (@n2);
+insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1);
+insert into t1 values (@a+(@b:=@a+1));
+set @q:='abc';
+insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
+set @a:=5;
+insert into t1 values (@a),(@a);
+save_master_pos;
+connection slave;
+start slave;
+sync_with_master;
+select * from t1;
+show binlog events from 141;
+connection master;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+stop slave;
diff --git a/mysql-test/t/sel000001.test b/mysql-test/t/sel000001.test
deleted file mode 100644
index 77355f8d535..00000000000
--- a/mysql-test/t/sel000001.test
+++ /dev/null
@@ -1,18 +0,0 @@
-# sel000001
-#
-# Versions
-# --------
-# 3.22
-# 3.23
-#
-# Description
-# -----------
-# This test is just a simple select.
-# Testing WHERE clause.
-#
-
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (s CHAR(20) PRIMARY KEY, id INT);
-INSERT INTO t1 VALUES ('cat', 1), ('mouse', 3), ('dog', 2), ('snake', 77);
-SELECT s, id FROM t1 WHERE s = 'mouse';
-drop table t1;
diff --git a/mysql-test/t/sel000002.test b/mysql-test/t/sel000002.test
deleted file mode 100644
index 9a89db2821c..00000000000
--- a/mysql-test/t/sel000002.test
+++ /dev/null
@@ -1,17 +0,0 @@
-# sel000002
-#
-# Versions
-# --------
-# 3.22
-# 3.23
-#
-# Description
-# -----------
-# This test is just a simple select.
-#
-
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (n INT);
-INSERT INTO t1 VALUES (1), (2), (3);
-SELECT * FROM t1;
-drop table t1;
diff --git a/mysql-test/t/sel000003.test b/mysql-test/t/sel000003.test
deleted file mode 100644
index a3f6a7337c2..00000000000
--- a/mysql-test/t/sel000003.test
+++ /dev/null
@@ -1,18 +0,0 @@
-# sel000003
-#
-# Versions
-# --------
-# 3.22
-# 3.23
-#
-# Description
-# -----------
-# This test is just a simple select.
-# Testing count() function and GROUP BY clause.
-#
-
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (name CHAR(20) NOT NULL PRIMARY KEY, score SMALLINT NOT NULL, KEY(score));
-INSERT INTO t1 VALUES ('Sasha', 20), ('Matt', 20), ('Monty', 10), ('David', 10), ('Tim', 10), ('Jeremy', 10);
-SELECT COUNT(*) as n, score FROM t1 GROUP BY score;
-drop table t1;
diff --git a/mysql-test/t/sel000031.test b/mysql-test/t/sel000031.test
deleted file mode 100644
index 29bafbb3040..00000000000
--- a/mysql-test/t/sel000031.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# sel000031
-#
-# Versions
-# --------
-# 3.22
-# 3.23
-#
-# Description
-# -----------
-# test for a bug with elt() and order by
-
-drop table if exists t1,t2;
-create table t1 (id int(10) not null unique);
-create table t2 (id int(10) not null primary key,
-val int(10) not null);
-insert into t1 values (1),(2),(4);
-insert into t2 values (1,1),(2,1),(3,1),(4,2);
-
-select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
-drop table t1,t2;
diff --git a/mysql-test/t/sel000032.test b/mysql-test/t/sel000032.test
deleted file mode 100644
index d31ba69e9d8..00000000000
--- a/mysql-test/t/sel000032.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# sel000032
-#
-# Versions
-# --------
-# 3.22
-# 3.23
-#
-# Description
-# -----------
-# test for a bug with elt()
-
-drop table if exists t1,t2;
-create table t1 (id int(10) not null unique);
-create table t2 (id int(10) not null primary key,
-val int(10) not null);
-insert into t1 values (1),(2),(4);
-insert into t2 values (1,1),(2,1),(3,1),(4,2);
-
-select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
-drop table t1,t2;
diff --git a/mysql-test/t/sel000033.test b/mysql-test/t/sel000033.test
index 165e43ad9f8..72e096311ce 100644
--- a/mysql-test/t/sel000033.test
+++ b/mysql-test/t/sel000033.test
@@ -9,7 +9,9 @@
# -----------
# test for a bug with in() and unique key
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/t/sel000100.test b/mysql-test/t/sel000100.test
index cedb78b17e7..2f9c06d5cf4 100644
--- a/mysql-test/t/sel000100.test
+++ b/mysql-test/t/sel000100.test
@@ -1,4 +1,6 @@
+--disable_warnings
DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
CREATE TABLE t1 (
ID int(11) NOT NULL auto_increment,
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index d9b75fca362..d4effd2026c 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -6,9 +6,9 @@
# Simple select test
#
-use test;
-
+--disable_warnings
drop table if exists t1,t2,t3,t4;
+--enable_warnings
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
@@ -1489,8 +1489,6 @@ select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.
# We need another table for join stuff..
#
-drop table if exists company;
-
create table t4 (
companynr tinyint(2) unsigned zerofill NOT NULL default '00',
companyname char(30) NOT NULL default '',
@@ -1577,8 +1575,8 @@ select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld
select count(*) from t1;
select companynr,count(*),sum(fld1) from t2 group by companynr;
select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
-select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>"";
-select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3;
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
@@ -1751,6 +1749,10 @@ select wss_type from t1 where wss_type ='102935229216544104';
select wss_type from t1 where wss_type ='102935229216544093';
select wss_type from t1 where wss_type =102935229216544093;
drop table t1;
+select 1+2,"aaaa",3.13*2.0 into @a,@b,@c;
+select @a;
+select @b;
+select @c;
#
# Test of removing redundant braces in the FROM part
@@ -1796,10 +1798,10 @@ select * from t1 natural right join (t1 as t2 left join t1 as t3 using (a));
select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
drop table t1;
-drop table if exists t1,t2;
+
CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) TYPE=MyISAM;
INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
CREATE TABLE t2 ( id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;
INSERT INTO t2 VALUES (2517), (2518), (2519), (2520), (2521), (2522);
select * from t1, t2 WHERE t1.t2_id = t2.id and t1.t2_id > 0 order by t1.id LIMIT 0, 5;
-drop table if exists t1,t2;
+drop table t1,t2;
diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test
index 0a483c860cb..06624d50a43 100644
--- a/mysql-test/t/select_found.test
+++ b/mysql-test/t/select_found.test
@@ -1,8 +1,10 @@
#
# Testing of found_rows()
#
-
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a int not null auto_increment, b int not null, primary key(a));
insert into t1 (b) values (2),(3),(5),(5),(5),(6),(7),(9);
select SQL_CALC_FOUND_ROWS * from t1;
@@ -84,4 +86,12 @@ INSERT INTO t1 (titre,maxnumrep) VALUES
('test1','1'),('test2','2'),('test3','3');
SELECT SQL_CALC_FOUND_ROWS titre,numeropost,maxnumrep FROM t1 WHERE numeropost IN (1,2) ORDER BY maxnumrep DESC LIMIT 0, 1;
SELECT FOUND_ROWS();
+SELECT SQL_CALC_FOUND_ROWS 1 FROM (SELECT 1) as a LIMIT 0;
+SELECT FOUND_ROWS();
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE numeropost > 1 LIMIT 0;
+SELECT FOUND_ROWS();
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 0;
+SELECT FOUND_ROWS();
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 ORDER BY numeropost LIMIT 0;
+SELECT FOUND_ROWS();
drop table t1;
diff --git a/mysql-test/t/select_safe.test b/mysql-test/t/select_safe.test
index e76b7558997..cd8bce6369c 100644
--- a/mysql-test/t/select_safe.test
+++ b/mysql-test/t/select_safe.test
@@ -2,7 +2,10 @@
# test of safe selects
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
create table t1 (a int primary key, b char(20));
insert into t1 values(1,"test");
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index ba6fa930e22..f6f0ac0b82b 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -2,7 +2,10 @@
# Test of some show commands
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
check table t1 fast;
@@ -49,9 +52,11 @@ drop table t2;
create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
- name char(20) default 'O''Brien'
+ name char(20) default 'O''Brien' comment 'O''Brien as default',
+ c int not null comment 'int column'
) comment = 'it\'s a table' ;
show create table t1 ;
+show full columns from t1;
drop table t1;
create table t1 (a int not null, unique aa (a));
@@ -78,6 +83,7 @@ drop table t1;
create table t1 (a decimal(9,2), b decimal (9,0), e double(9,2), f double(5,0), h float(3,2), i float(3,0));
show columns from t1;
+show full columns from t1;
drop table t1;
#
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
new file mode 100644
index 00000000000..fd464f74de4
--- /dev/null
+++ b/mysql-test/t/sql_mode.test
@@ -0,0 +1,30 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+CREATE TABLE `t1` (
+ a int not null auto_increment,
+ `pseudo` varchar(35) character set latin2 NOT NULL default '',
+ `email` varchar(60) character set latin2 NOT NULL default '',
+ PRIMARY KEY (a),
+ UNIQUE KEY `email` USING BTREE (`email`)
+) TYPE=HEAP CHARSET=latin1 ROW_FORMAT DYNAMIC;
+set @@sql_mode="";
+show variables like 'sql_mode';
+show create table t1;
+set @@sql_mode="ansi_quotes";
+show variables like 'sql_mode';
+show create table t1;
+set @@sql_mode="no_table_options";
+show variables like 'sql_mode';
+show create table t1;
+set @@sql_mode="no_key_options";
+show variables like 'sql_mode';
+show create table t1;
+set @@sql_mode="no_field_options,mysql323,mysql40";
+show variables like 'sql_mode';
+show create table t1;
+set @@sql_mode="postgresql,oracle,mssql,db2,sapdb";
+show variables like 'sql_mode';
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test
index cffca437cf1..90d7f814359 100644
--- a/mysql-test/t/status.test
+++ b/mysql-test/t/status.test
@@ -13,7 +13,10 @@ flush status;
show status like 'Table_lock%';
connection con1;
SET SQL_LOG_BIN=0;
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1(n int) type=myisam;
insert into t1 values(1);
connection con2;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
new file mode 100644
index 00000000000..1841e9f109a
--- /dev/null
+++ b/mysql-test/t/subselect.test
@@ -0,0 +1,597 @@
+# Initialise
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
+--enable_warnings
+
+select (select 2);
+explain select (select 2);
+SELECT (SELECT 1) UNION SELECT (SELECT 2);
+explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
+SELECT (SELECT (SELECT 0 UNION SELECT 0));
+explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
+-- error 1245
+SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
+-- error 1245
+SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
+SELECT (SELECT 1),MAX(1) FROM (SELECT 1) as a;
+-- error 1245
+SELECT (SELECT a) as a;
+EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
+SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
+-- error 1054
+SELECT (SELECT 1), a;
+SELECT 1 as a FROM (SELECT 1) as b HAVING (SELECT a)=1;
+-- error 1054
+SELECT 1 FROM (SELECT (SELECT a) b) c;
+SELECT * FROM (SELECT 1 as id) b WHERE id IN (SELECT * FROM (SELECT 1 as id) c ORDER BY id);
+-- error 1239
+SELECT * FROM (SELECT 1) a WHERE 1 IN (SELECT 1,1);
+SELECT 1 IN (SELECT 1);
+SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
+-- error 1221
+select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
+-- error 1108
+SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
+SELECT (SELECT 1,2,3) = ROW(1,2,3);
+SELECT (SELECT 1,2,3) = ROW(1,2,1);
+SELECT (SELECT 1,2,3) < ROW(1,2,1);
+SELECT (SELECT 1,2,3) > ROW(1,2,1);
+SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
+SELECT ROW(1,2,3) = (SELECT 1,2,3);
+SELECT ROW(1,2,3) = (SELECT 1,2,1);
+SELECT ROW(1,2,3) < (SELECT 1,2,1);
+SELECT ROW(1,2,3) > (SELECT 1,2,1);
+SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
+SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
+SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
+SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
+
+-- error 1239
+SELECT (SELECT * FROM (SELECT 'test' a,'test' b) a);
+
+SELECT 1 as a,(SELECT a+a) b,(SELECT b);
+
+create table t1 (a int);
+create table t2 (a int, b int);
+create table t3 (a int);
+create table t4 (a int, b int);
+insert into t1 values (2);
+insert into t2 values (1,7),(2,7);
+insert into t4 values (4,8),(3,8),(5,9);
+-- error 1245
+select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
+select (select a from t1 where t1.a=t2.a), a from t2;
+select (select a from t1 where t1.a=t2.b), a from t2;
+select (select a from t1), a from t2;
+select (select a from t3), a from t2;
+select * from t2 where t2.a=(select a from t1);
+insert into t3 values (6),(7),(3);
+select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
+explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
+select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
+select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
+(select * from t2 where a>1) as tt;
+explain select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
+(select * from t2 where a>1) as tt;
+select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
+select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
+select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1);
+select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
+explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
+select * from t3 where exists (select * from t2 where t2.b=t3.a);
+select * from t3 where not exists (select * from t2 where t2.b=t3.a);
+select * from t3 where a in (select b from t2);
+select * from t3 where a not in (select b from t2);
+select * from t3 where a = some (select b from t2);
+select * from t3 where a <> any (select b from t2);
+
+# Rewrite: select * from t3 where not exists (select b from t2 where a <> b);
+select * from t3 where a = all (select b from t2);
+
+select * from t3 where a <> all (select b from t2);
+insert into t2 values (100, 5);
+select * from t3 where a < any (select b from t2);
+select * from t3 where a < all (select b from t2);
+select * from t3 where a >= any (select b from t2);
+select * from t3 where a >= all (select b from t2);
+delete from t2 where a=100;
+-- error 1239
+select * from t3 where a in (select a,b from t2);
+-- error 1239
+select * from t3 where a in (select * from t2);
+insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
+select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
+from t2 where t2.b=t4.b);
+select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
+from t2 where t2.b=t4.b);
+create table t5 (a int);
+select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+insert into t5 values (5);
+select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+insert into t5 values (2);
+select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+explain select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+-- error 1240
+select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
+create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
+create table t7( uq int primary key, name char(25));
+insert into t7 values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta");
+insert into t6 values (1,1),(1,2),(2,2),(1,3);
+select * from t6 where exists (select * from t7 where uq = clinic_uq);
+
+# not unique fields
+-- error 1052
+select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
+
+# different tipes & group functions
+drop table if exists t1,t2,t3;
+
+CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
+INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
+CREATE TABLE t2 (a varchar(20),b int NOT NULL default '0');
+INSERT INTO t2 VALUES ('W','1'),('A','3'),('J','2');
+CREATE TABLE t1 (a varchar(20),b date NOT NULL default '0000-00-00');
+INSERT INTO t1 VALUES ('W','1732-02-22'),('A','1735-10-30'),('J','1743-04-13');
+SELECT * FROM t1 WHERE b = (SELECT MIN(b) FROM t1);
+SELECT * FROM t2 WHERE b = (SELECT MIN(b) FROM t2);
+SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3);
+
+CREATE TABLE `t8` (
+ `pseudo` varchar(35) character set latin1 NOT NULL default '',
+ `email` varchar(60) character set latin1 NOT NULL default '',
+ PRIMARY KEY (`pseudo`),
+ UNIQUE KEY `email` (`email`)
+) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
+
+INSERT INTO t8 (pseudo,email) VALUES ('joce','test');
+INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
+INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
+EXPLAIN SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
+-- error 1239
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
+t8 WHERE pseudo='joce');
+-- error 1239
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT * FROM t8 WHERE
+pseudo='joce');
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
+-- error 1240
+SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo LIKE '%joce%');
+
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
+
+#searchconthardwarefr3 forumconthardwarefr7
+CREATE TABLE `t1` (
+ `topic` mediumint(8) unsigned NOT NULL default '0',
+ `date` date NOT NULL default '0000-00-00',
+ `pseudo` varchar(35) character set latin1 NOT NULL default '',
+ PRIMARY KEY (`pseudo`,`date`,`topic`),
+ KEY `topic` (`topic`)
+) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
+INSERT INTO t1 (topic,date,pseudo) VALUES
+('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
+EXPLAIN SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
+EXPLAIN SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
+SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
+SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
+SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1;
+-- error 1240
+SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1;
+EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
+drop table t1;
+
+#forumconthardwarefr7 searchconthardwarefr7
+CREATE TABLE `t1` (
+ `numeropost` mediumint(8) unsigned NOT NULL auto_increment,
+ `maxnumrep` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`numeropost`),
+ UNIQUE KEY `maxnumrep` (`maxnumrep`)
+) TYPE=MyISAM ROW_FORMAT=FIXED;
+
+INSERT INTO t1 (numeropost,maxnumrep) VALUES (40143,1),(43506,2);
+
+CREATE TABLE `t2` (
+ `mot` varchar(30) NOT NULL default '',
+ `topic` mediumint(8) unsigned NOT NULL default '0',
+ `date` date NOT NULL default '0000-00-00',
+ `pseudo` varchar(35) NOT NULL default '',
+ PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`)
+ ) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
+
+INSERT INTO t2 (mot,topic,date,pseudo) VALUES ('joce','40143','2002-10-22','joce'), ('joce','43506','2002-10-22','joce');
+select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1);
+SELECT numeropost,maxnumrep FROM t1 WHERE exists (SELECT 1 FROM t2 WHERE (mot='joce') AND date >= '2002-10-21' AND t1.numeropost = t2.topic) ORDER BY maxnumrep DESC LIMIT 0, 20;
+-- error 1054
+SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
+-- error 1054
+SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
+
+SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic);
+SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
+SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
+SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic);
+SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
+SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
+SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic);
+SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
+SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100) from t2;
+SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
+SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
+SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
+SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
+SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
+SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000) from t2;
+drop table t1,t2;
+
+#forumconthardwarefr7
+CREATE TABLE `t1` (
+ `numeropost` mediumint(8) unsigned NOT NULL auto_increment,
+ `maxnumrep` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`numeropost`),
+ UNIQUE KEY `maxnumrep` (`maxnumrep`)
+) TYPE=MyISAM ROW_FORMAT=FIXED;
+
+INSERT INTO t1 (numeropost,maxnumrep) VALUES (1,0),(2,1);
+-- error 1240
+select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1);
+-- error 1240
+select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1);
+drop table t1;
+
+#iftest
+CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b');
+INSERT INTO t1 VALUES ();
+-- error 1240
+SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b');
+drop table t1;
+
+# threadhardwarefr7
+CREATE TABLE `t1` (
+ `numeropost` mediumint(8) unsigned NOT NULL default '0',
+ `numreponse` int(10) unsigned NOT NULL auto_increment,
+ `pseudo` varchar(35) NOT NULL default '',
+ PRIMARY KEY (`numeropost`,`numreponse`),
+ UNIQUE KEY `numreponse` (`numreponse`),
+ KEY `pseudo` (`pseudo`,`numeropost`)
+) TYPE=MyISAM;
+-- error 1245
+SELECT (SELECT numeropost FROM t1 HAVING numreponse=a),numreponse FROM (SELECT * FROM t1) as a;
+-- error 1054
+SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=a) FROM (SELECT * FROM t1) as a;
+SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=1) FROM (SELECT * FROM t1) as a;
+INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
+-- error 1240
+EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
+EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
+EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
+drop table t1;
+
+CREATE TABLE t1 (a int(1));
+INSERT INTO t1 VALUES (1);
+SELECT 1 FROM (SELECT a FROM t1) b HAVING (SELECT b.a)=1;
+drop table t1;
+
+#update with subselects
+create table t1 (a int NOT NULL, b int, primary key (a));
+create table t2 (a int NOT NULL, b int, primary key (a));
+insert into t1 values (0, 10),(1, 11),(2, 12);
+insert into t2 values (1, 21),(2, 22),(3, 23);
+select * from t1;
+-- error 1093
+update t1 set b= (select b from t1);
+-- error 1240
+update t1 set b= (select b from t2);
+update t1 set b= (select b from t2 where t1.a = t2.a);
+select * from t1;
+drop table t1, t2;
+
+#delete with subselects
+create table t1 (a int NOT NULL, b int, primary key (a));
+create table t2 (a int NOT NULL, b int, primary key (a));
+insert into t1 values (0, 10),(1, 11),(2, 12);
+insert into t2 values (1, 21),(2, 12),(3, 23);
+select * from t1;
+select * from t1 where b = (select b from t2 where t1.a = t2.a);
+-- error 1093
+delete from t1 where b = (select b from t1);
+-- error 1240
+delete from t1 where b = (select b from t2);
+delete from t1 where b = (select b from t2 where t1.a = t2.a);
+select * from t1;
+drop table t1, t2;
+
+#multi-delete with subselects
+
+create table t11 (a int NOT NULL, b int, primary key (a));
+create table t12 (a int NOT NULL, b int, primary key (a));
+create table t2 (a int NOT NULL, b int, primary key (a));
+insert into t11 values (0, 10),(1, 11),(2, 12);
+insert into t12 values (33, 10),(22, 11),(2, 12);
+insert into t2 values (1, 21),(2, 12),(3, 23);
+select * from t11;
+select * from t12;
+-- error 1093
+delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a);
+-- error 1240
+delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2);
+delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a);
+select * from t11;
+select * from t12;
+drop table t11, t12, t2;
+
+#insert with subselects
+CREATE TABLE t1 (x int);
+create table t2 (a int);
+create table t3 (a int);
+insert into t2 values (1);
+insert into t3 values (1),(2);
+-- error 1093
+INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
+-- error 1240
+INSERT INTO t1 (x) VALUES ((SELECT a FROM t3));
+INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
+select * from t1;
+insert into t2 values (1);
+INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
+-- sleep 1
+select * from t1;
+INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2;
+select * from t1;
+-- error 1093
+INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
+INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
+-- sleep 1
+select * from t1;
+drop table t1, t2, t3;
+
+#replace with subselects
+CREATE TABLE t1 (x int not null, y int, primary key (x));
+create table t2 (a int);
+create table t3 (a int);
+insert into t2 values (1);
+insert into t3 values (1),(2);
+select * from t1;
+-- error 1093
+replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2));
+-- error 1240
+replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2));
+replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2));
+select * from t1;
+replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+2 FROM t2));
+select * from t1;
+replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a FROM t2));
+-- sleep 1
+select * from t1;
+replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a+1 FROM t2));
+-- sleep 1
+select * from t1;
+replace LOW_PRIORITY into t1 (x, y) VALUES ((SELECT a+1 FROM t2), (SELECT a FROM t2));
+select * from t1;
+drop table t1, t2, t3;
+
+-- error 1096
+SELECT * FROM (SELECT 1) b WHERE 1 IN (SELECT *);
+
+CREATE TABLE t2 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t2 VALUES (1),(2);
+SELECT * FROM t2 WHERE id IN (SELECT 1);
+EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1);
+SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
+SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
+EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
+EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
+SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
+SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
+-- error 1093
+INSERT INTO t2 VALUES ((SELECT * FROM t2));
+SELECT * FROM t2;
+CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t1 values (1),(1);
+-- error 1240
+UPDATE t2 SET id=(SELECT * FROM t1);
+drop table t2, t1;
+
+#NULL test
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+select 1 IN (SELECT * from t1);
+select 10 IN (SELECT * from t1);
+select NULL IN (SELECT * from t1);
+update t1 set a=NULL where a=2;
+select 1 IN (SELECT * from t1);
+select 3 IN (SELECT * from t1);
+select 10 IN (SELECT * from t1);
+select 1 > ALL (SELECT * from t1);
+select 10 > ALL (SELECT * from t1);
+select 1 > ANY (SELECT * from t1);
+select 10 > ANY (SELECT * from t1);
+drop table t1;
+create table t1 (a varchar(20));
+insert into t1 values ('A'),('BC'),('DEF');
+select 'A' IN (SELECT * from t1);
+select 'XYZS' IN (SELECT * from t1);
+select NULL IN (SELECT * from t1);
+update t1 set a=NULL where a='BC';
+select 'A' IN (SELECT * from t1);
+select 'DEF' IN (SELECT * from t1);
+select 'XYZS' IN (SELECT * from t1);
+select 'A' > ALL (SELECT * from t1);
+select 'XYZS' > ALL (SELECT * from t1);
+select 'A' > ANY (SELECT * from t1);
+select 'XYZS' > ANY (SELECT * from t1);
+drop table t1;
+create table t1 (a float);
+insert into t1 values (1.5),(2.5),(3.5);
+select 1.5 IN (SELECT * from t1);
+select 10.5 IN (SELECT * from t1);
+select NULL IN (SELECT * from t1);
+update t1 set a=NULL where a=2.5;
+select 1.5 IN (SELECT * from t1);
+select 3.5 IN (SELECT * from t1);
+select 10.5 IN (SELECT * from t1);
+select 1.5 > ALL (SELECT * from t1);
+select 10.5 > ALL (SELECT * from t1);
+select 1.5 > ANY (SELECT * from t1);
+select 10.5 > ANY (SELECT * from t1);
+explain select (select a+1) from t1;
+select (select a+1) from t1;
+drop table t1;
+
+#
+# Null with keys
+#
+
+CREATE TABLE t1 (a int(11) NOT NULL default '0', PRIMARY KEY (a));
+CREATE TABLE t2 (a int(11) default '0', INDEX (a));
+INSERT INTO t1 VALUES (1),(2),(3),(4);
+INSERT INTO t2 VALUES (1),(2),(3);
+SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
+explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
+drop table t1,t2;
+
+#LIMIT is not supported now
+create table t1 (a float);
+-- error 1235
+select 10.5 IN (SELECT * from t1 LIMIT 1);
+-- error 1235
+select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
+drop table t1;
+
+create table t1 (a int, b int, c varchar(10));
+create table t2 (a int);
+insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
+insert into t2 values (1),(2),(NULL);
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t1 where a=t2.a) from t2;
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
+drop table t1,t2;
+
+create table t1 (a int, b real, c varchar(10));
+insert into t1 values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
+select ROW(1, 1, 'a') IN (select a,b,c from t1);
+select ROW(1, 2, 'a') IN (select a,b,c from t1);
+select ROW(1, 1, 'a') IN (select b,a,c from t1);
+select ROW(1, 1, 'a') IN (select a,b,c from t1 where a is not null);
+select ROW(1, 2, 'a') IN (select a,b,c from t1 where a is not null);
+select ROW(1, 1, 'a') IN (select b,a,c from t1 where a is not null);
+select ROW(1, 1, 'a') IN (select a,b,c from t1 where c='b' or c='a');
+select ROW(1, 2, 'a') IN (select a,b,c from t1 where c='b' or c='a');
+select ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a');
+-- error 1235
+select ROW(1, 1, 'a') IN (select b,a,c from t1 limit 2);
+drop table t1;
+
+create table t1 (a int);
+insert into t1 values (1);
+do @a:=(SELECT a from t1);
+select @a;
+set @a:=2;
+set @a:=(SELECT a from t1);
+select @a;
+drop table t1;
+-- error 1146
+do (SELECT a from t1);
+-- error 1146
+set @a:=(SELECT a from t1);
+
+CREATE TABLE t1 (a int, KEY(a));
+HANDLER t1 OPEN;
+-- error 1149
+HANDLER t1 READ a=((SELECT 1));
+HANDLER t1 CLOSE;
+drop table t1;
+
+create table t1 (a int);
+create table t2 (b int);
+insert into t1 values (1),(2);
+insert into t2 values (1);
+select a from t1 where a in (select a from t1 where a in (select b from t2));
+drop table t1, t2;
+
+create table t1 (a int, b int);
+create table t2 like t1;
+insert into t1 values (1,2),(1,3),(1,4),(1,5);
+insert into t2 values (1,2),(1,3);
+select * from t1 where row(a,b) in (select a,b from t2);
+drop table t1, t2;
+
+CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t1 VALUES (1);
+-- error 1111
+UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
+drop table t1;
+
+#test of uncacheable subqueries
+CREATE TABLE t1 (a int(1));
+EXPLAIN SELECT (SELECT RAND() FROM t1) FROM t1;
+EXPLAIN SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
+EXPLAIN SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
+drop table t1;
+
+
+CREATE TABLE `t1` (
+ `mot` varchar(30) character set latin1 NOT NULL default '',
+ `topic` mediumint(8) unsigned NOT NULL default '0',
+ `date` date NOT NULL default '0000-00-00',
+ `pseudo` varchar(35) character set latin1 NOT NULL default '',
+ PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
+ KEY `pseudo` (`pseudo`,`date`,`topic`),
+ KEY `topic` (`topic`)
+) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
+
+CREATE TABLE `t2` (
+ `mot` varchar(30) character set latin1 NOT NULL default '',
+ `topic` mediumint(8) unsigned NOT NULL default '0',
+ `date` date NOT NULL default '0000-00-00',
+ `pseudo` varchar(35) character set latin1 NOT NULL default '',
+ PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
+ KEY `pseudo` (`pseudo`,`date`,`topic`),
+ KEY `topic` (`topic`)
+) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
+
+CREATE TABLE `t3` (
+ `numeropost` mediumint(8) unsigned NOT NULL auto_increment,
+ `maxnumrep` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`numeropost`),
+ UNIQUE KEY `maxnumrep` (`maxnumrep`)
+) TYPE=MyISAM CHARSET=latin1;
+INSERT INTO t1 VALUES ('joce','1','','joce'),('test','2','','test');
+
+INSERT INTO t2 VALUES ('joce','1','','joce'),('test','2','','test');
+
+INSERT INTO t3 VALUES (1,1);
+
+SELECT DISTINCT topic FROM t2 WHERE NOT EXISTS(SELECT * FROM t3 WHERE
+numeropost=topic);
+select * from t1;
+DELETE FROM t1 WHERE topic IN (SELECT DISTINCT topic FROM t2 WHERE NOT
+EXISTS(SELECT * FROM t3 WHERE numeropost=topic));
+select * from t1;
+
+drop table t1, t2, t3;
+
+SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
+CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT 1)) a;
+SHOW CREATE TABLE t1;
+drop table t1;
+CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
+SHOW CREATE TABLE t1;
+drop table t1;
+CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a;
+SHOW CREATE TABLE t1;
+drop table t1;
+CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a;
+SHOW CREATE TABLE t1;
+drop table t1;
+
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+explain select a,(select (select rand() from t1 limit 1) from t1 limit 1)
+from t1;
+drop table t1;
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 586761921b8..67126930e60 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -3,10 +3,14 @@ disable_query_log;
show variables like "have_symlink";
enable_query_log;
+--disable_warnings
+drop table if exists t1,t2,t7,t8,t9;
+--enable_warnings
+
#
# First create little data to play with
#
-drop table if exists t1,t2,t7,t8,t9;
+
create table t1 (a int not null auto_increment, b char(16) not null, primary key (a));
create table t2 (a int not null auto_increment, b char(16) not null, primary key (a));
insert into t1 (b) values ("test"),("test1"),("test2"),("test3");
diff --git a/mysql-test/t/tablelock.test b/mysql-test/t/tablelock.test
index fa8c4f03675..fbc5d685096 100644
--- a/mysql-test/t/tablelock.test
+++ b/mysql-test/t/tablelock.test
@@ -2,7 +2,10 @@
# Test of lock tables
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
create table t1 ( n int auto_increment primary key);
lock tables t1 write;
insert into t1 values(NULL);
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index 665e690a322..03b6fa35bfa 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -2,7 +2,10 @@
# Test of temporary tables
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
CREATE TABLE t1 (c int not null, d char (10) not null);
insert into t1 values(1,""),(2,"a"),(3,"b");
CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
@@ -34,7 +37,6 @@ drop table t1;
# Test CONCAT_WS with temporary tables
#
-drop table if exists t1;
CREATE TABLE t1 (pkCrash INTEGER PRIMARY KEY,strCrash VARCHAR(255));
INSERT INTO t1 ( pkCrash, strCrash ) VALUES ( 1, '1');
SELECT CONCAT_WS(pkCrash, strCrash) FROM t1;
@@ -74,8 +76,6 @@ drop table t1;
# In MySQL 4.0.4 doing a GROUP BY on a NULL column created a disk based
# temporary table when a memory based one would be good enough.
-drop table if exists t1;
-
CREATE TABLE t1 (
d datetime default NULL
) TYPE=MyISAM;
diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test
index eeb79f497fa..dd80baba269 100644
--- a/mysql-test/t/truncate.test
+++ b/mysql-test/t/truncate.test
@@ -1,7 +1,10 @@
#
# Test of truncate
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a integer, b integer,c1 CHAR(10));
insert into t1 (a) values (1),(2);
truncate table t1;
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index 2b23617ec8b..6a55c61f8a1 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -1,8 +1,41 @@
#
+# Basic cleanup
+#
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5,t6,t7;
+--enable_warnings
+
+
+#
+# Check syntax for creating BLOB/TEXT
+#
+
+CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
+show columns from t1;
+CREATE TABLE t2 (a char(257), b varchar(70000) binary, c varchar(70000000));
+show columns from t2;
+create table t3 (a long, b long byte);
+show create TABLE t3;
+drop table t1,t2,t3
+
+#
+# Check errors with blob
+#
+
+--error 1074
+CREATE TABLE t1 (a char(257) default "hello");
+--error 1101
+CREATE TABLE t2 (a blob default "hello");
+
+# Safety to be able to continue with other tests if above fails
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+#
# test of full join with blob
#
-drop table if exists t1,t2,t3,t4,t5,t6,t7;
create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
insert into t1 values (null,"a","A");
insert into t1 values (null,"bbb","BBB");
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 68c2d55aac9..6319a3990e6 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -1,6 +1,10 @@
#
# test of problem with date fields
#
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a char(16), b date, c datetime);
insert into t1 SET a='test 2000-01-01', b='2000-01-01', c='2000-01-01';
select * from t1 where c = '2000-01-01';
@@ -11,7 +15,6 @@ drop table t1;
# problem with date conversions
#
-drop table if exists t1,t2;
CREATE TABLE t1 (name char(6),cdate date);
INSERT INTO t1 VALUES ('name1','1998-01-01');
INSERT INTO t1 VALUES ('name2','1998-01-01');
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index a516bc89f99..f791cd76d34 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -2,7 +2,10 @@
# testing different DATETIME ranges
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (t datetime);
insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959);
select * from t1;
@@ -19,7 +22,7 @@ drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
insert into t1 (b,c,d) values(now(),curtime(),now());
-select date_format(a,"%Y-%m-%d")=b,right(a,6)=c+0,a=d+0 from t1;
+select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1;
drop table t1;
#
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 7f73ec34e3a..9b10e8943ad 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -1,6 +1,9 @@
# bug in decimal() with negative numbers by kaido@tradenet.ee
+--disable_warnings
DROP TABLE IF EXISTS t1;
+--enable_warnings
+
CREATE TABLE t1 (
id int(11) DEFAULT '0' NOT NULL auto_increment,
datatype_id int(11) DEFAULT '0' NOT NULL,
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index 8f399e4364e..49ba73acaa8 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -2,7 +2,10 @@
# Problem with many enums
#
+--disable_warnings
DROP TABLE if exists t1;
+--enable_warnings
+
CREATE TABLE t1 (
field enum('001001','001004','001010','001018','001019','001020','001021','001027','001028','001029','001030','001031','001100','002003','002004','002005','002007','002008','002009','002012','002013','002014','003002','003003','003004','003005','003006','003007','003008','003009','003010','003011','003012','003013','003014','003015','003016','003017','003018','003019','004002','004003','004005','004006','004007','004008','004010','004012','004014','004016','004017','004020','004021','004022','004023','004024','004025','004026','006002','006004','006006','006010','006011','006012','006013','006014','007001','007002','007003','007004','007005','007006','007007','007008','007009','007010','007011','007012','007013','007014','007015','007016','007017','007018','007019','007020','007021','007022','007023','007024','007025','007026','007027','007028','007029','007030','007031','007032','007033','007034','007035','007036','007037','007038','007039','007040','007043','007044','009001','009002','009004','009005','009006','009007','009008','009009','009010','009011','009012','009013','010002','010003','010004','010005','010006','010007','010008','010009','010010','010011','010012','010013','010015','010016','010017','010018','010019','010020','010021','010022','010023','010024','010025','010026','010027','010028','011001','011002','011003','011004','011006','011012','011013','011014','011015','011016','012017','012018','012019','012023','012027','012028','012029','012030','012031','012032','012033','012034','012035','012036','012037','012038','012039','014001','016002','016003','016004','016007','016010','016011','016016','016019','016020','016021','016022','016023','016024','016026','016027','016028','016029','016030','016031','016032','016033','016034','017002','018001','019002','019004','020001','020003','020004','020005','020006','020007','020008','020009','022001','022002','022003','023001','023002','023003','023004','023005','023006','023007','023008','023010','023011','023012','023017','023019','023020','023021','023025','023026','023027','023028','023029','023030','023031','023032','023033','023034','023035','025001','025003','025004','025005','025006','025007','025008','025009','025010','025011','025012','025013','025014','025015','025016','025017','025018','025019','025020','025021','025022','025023','025024','025025','025026','025027','025028','025029','025030','025031','025032','025033','025034','025035','025036','025037','025038','025039','025040','025041','025042','025043','025044','025045','025046','025047','025048','025049','025050','025051','025052','025053','025054','025055','025056','025057','025058','025059','025060','025061','025062','025063','027001','027002','027011','035008','035012','036001','037001','037003','037004','037005','037006','037007','037008','037009','038004','038005','038006','038007','038009','039001','039002','039003','039004','039005','039006','046001','046002','046003','046004','046005','046007','046008','046009','046010','046011','046012','046013','046014','047001','047002','048001','051001','051002','051003','051004','052001','052002','052005','053015','053016','053019','053020','053023','053024','053026','053028','053029','053033','053034','053036','053037','053038','053039','053041','053042','053043','053045','053046','053047','053048','053051','053052','053054','053055','053056','053057','053068','053069','053070','053073','053074','053075','053086','053094','053095','053096','053097','053098','053099','053100','053101','053102','053103','053104','053105','053107','053122','053123','053124','053125','053127','053128','054001','054002','054003','054004','054005','054006','054007','054009','054010','056001','056002','056003','056004','056005','056006','056009','056010','056011','056016','056017','056018','056019','056020','056021','056022','057001','057002','057003','057004','058002','058003','058004','058005','060001','060003','060004','060005','060006','060007','061002','061003','061004','061005','061006','069006','069007','069010','069011','069012','069013','069014','069015','069016','069017','069018','069020','069021','069022','069023','069024','071002','071003','071004','071005','071006','071008','071011','071013','071020','071021','071022','072001','073001','073002','073003','073004','074001','074002','074003','074004','074005','074006','074007','074008','074009','074010','074011','074012','075001','075007','076101','076102','076103','077001','077002','077003','077004','077006','077007','077008','077009','078005','079002','079003','079004','079005','079006','079007','081001','082006','082007','082011','082013','082014','082015','082016','082017','082021','082022','082023','082024','082025','082026','082027','082028','082029','082030','082031','082032','082033','082034','082035','082036','082037','082038','082039','082040','082041','082042','082043','082044','084001','084002','084003','084004','084005','084007','084008','084009','084011','084013','084014','084016','084017','084027','084031','084032','084033','084035','084036','084037','084038','084039','084040','084041','084042','084043','084044','084045','084046','084047','084048','084049','084050','084051','085001','085002','085003','085004','085005','085006','085007','085009','085011','085012','085013','085014','085015','085016','085017','085018','085019','085020','085021','085022','085023','085028','085029','085030','085031','085033','085034','085035','085036','085037','085038','085040','085041','085042','085043','085044','085045','085046','085047','085048','085063','085064','085065','085068','085070','085071','085073','085082','085083','085086','085088','085089','085090','085091','085092','085093','085094','085095','085096','085097','085098','085099','085100','085101','085102','085103','085104','085105','085106','085107','085108','085109','085110','085111','085112','085113','085115','085119','085120','085121','085122','085123','085124','085125','085126','085127','085128','085129','085130','085132','085133','085134','085135','085136','085137','086001','086002','086003','086004','086005','088001','088003','088005','088006','088007','088008','088009','089001','090001','090002','090003','090004','090005','090006','090007','090008','090009','090010','090013','090015','090016','090017','090018','090019','090022','090027','090028','091001','091002','091005','091008','091009','091010','091011','091012','091013','091014','091015','091016','091017','091018','093001','093003','093098','093100','093102','093104','093141','093142','093146','093151','093153','093167','093168','093176','094001','094002','094004','094005','095004','099001','099002','100001','101001','102002','102003','105001','105002','106001','113001','113002','113003','113004','113005','113006','113007','113008','113009','113010','113011','113012','113013','113014','113015','113016','113017','113018','113019','113020','113021','113022','113023','113024','113025','113026','113027','113028','114001','115001','115002','115003','115004','115005','115006','115007','115008','115009','115010','115011','115012','115013','115014','115015','115016','115017','115018','115020','115021','115022','115023','115025','115026','115027','115028','115029','115030','115031','115032','115033','115034','115035','115036','115039','115040','115041','115042','115043','115044','115045','115046','115047','115048','115049','115050','115051','115052','115053','115054','115055','115056','115057','115059','115060','115061','115062','115063','115064','115065','115066','115067','115068','115069','115070','115071','115072','115073','115075','115076','115081','115082','115085','115086','115087','115088','115095','115096','115097','115098','115099','115101','115102','115103','115104','115105','115106','115108','115109','115110','115111','115112','115113','115114','115115','115116','115117','115118','115119','115120','115121','115122','116001','116002','116003','116004','116005','116006','116007','116008','116009','116010','116011','116012','117001','117002','117003','123001','124010','124014','124015','124019','124024','124025','124026','124027','124028','124029','124030','124031','124032','124033','124035','124036','124037','124038','124039','124040','124041','124042','124043','124044','124045','124046','124047','124048','124049','124050','124051','124052','124053','124054','124055','124056','124057','124058','124059','124060','124061','124062','124063','124064','124065','126001','126002','126003','126004','126005','126006','126007','126008','126009','126010','126011','126012','130001','132001','132002','132003','133001','133008','133009','133010','133011','133012','133013','133014','133015','133016','133017','133018','133019','133020','133021','133022','133023','133024','133025','133027','133028','133029','133030','133031','134001','135001','135002','135003','135004','135005','135006','135007','135008','135009','135010','136001','137009','137010','137011','137012','137013','137014','137015','137016','137017','137018','137019','138001','138002','138003','138004','139001','139003','140001','141001','141002','141003','141006','141007','141008','141009','141011','141012','141014','141015','141016','141017','141018','141019','141020','141021','141022','141023','141024','141025','141026','141027','141028','142001','142002','142003','142004','142005','142006','142007','142008','142010','142011','142012','144001','145001','145002','145003','145004','145005','145006','145007','145008','145009','145010','145011','145012','145013','145014','145015','145016','147001','150003','150005','150009','150013','150014','150015','150016','150017','150020','150021','152001','152002','152003','152004','152005','152006','152007','154001','154002','154003','155001','155002','155003','155004','155005','155006','159001','159002','159003','159004','160001','160002','160003','161001','162001','162002','162003','162004','162007','162010','162011','162012','163001','163002','163003','163005','163010','163011','163014','163015','163016','165001','165002','165003','165004','165005','165006','165007','165008','165009','165010','165011','165012','165013','165014','165015','165016','165017','165018','165019','165020','165021','165022','165023','165024','165025','165026','165027','165028','165029','165030','165031','165032','165033','165034','165035','165036','167001','168001','168002','168003','168004','168005','168007','168008','168009','168010','168011','168012','168013','168014','169001','169002','169003','169007','169008','169009','169010','170001','171001','171002','171003','171004','171005','171006','171007','171008','171009','172001','174001','174002','174003','176001','176002','176003','177001','177002','179001','179002','179003','179004','179005','179006','179007','179008','179009','179010','179011','179012','179013','179014','179015','179016','179017','179018','179019','179020','179021','179022','179023','179024','179025','179026','179027','179028','179029','179030','179031','179032','179033','179034','179035','179036','179037','179038','179039','179040','179041','179042','179043','179044','179045','179046','179047','180001','180010','180012','180013','180014','180015','180016','180017','180018','180019','180020','180021','180022','180023','180024','180025','180026','180027','180028','180030','180031','180032','180033','180034','180035','180036','180037','180038','180039','180041','180042','180043','180044','180045','180046','180047','180048','180049','180050','180051','180052','180053','180054','180055','180056','180057','180058','180059','180060','180061','180062','180063','180064','180065','180066','180067','180068','180069','180070','180071','182001','184001','184002','184005','184006','184007','184008','184009','184010','184011','185001','185003','187001','188001','188002','188003','188004','188005','188006','188007','188008','188009','188010','188011','191001','191002','192002','194001','194002','194003','194004','194005','194006','194007','195001','195002','195003','195004','195005','195006','195007','196001','196002','197001','197002','197003','197004','197005','197006','198001','198003','198004','198005','198006','198007','198008','198009','198010','198011','198012','198013','198014','198015','198016','198017','201001','201002','201005','202001','203001','203002','203003','203017','203018','203019','204001','204002','204003','205001','208001','208002','208003','208004','208005','209001','209002','209003','210001','210002','210003','210004','210005','210006','210007','210008','210009','210010','210011','210012','210013','211017','212001','212002','212003','212004','212005','212006','212007','212008','212009','212010','212011','212012','212013','218001','218003','218004','218006','218007','218008','218009','218011','218015','218016','218017','218018','218019','218020','218021','218022','218023','218024','218025','218026','218027','218028','218029','218030','218031','218032','218033','218034','218035','218036','221001','221002','221003','221004','221005','221006','221007','221008','221009','221010','221011','221012','221013','223001','223002','223003','224001','224002','224003','224006','224007','224008','225001','225002','225003','225004','225005','225006','225007','225008','225009','225010','225011','225012','225013','226001','226002','226003','226004','226005','226006','226007','226008','226009','227001','227002','227003','227004','227005','227006','227007','227008','227009','227010','227011','227012','227013','227014','227015','227016','227017','227018','227019','227020','227021','227022','227023','227024','227025','227026','227027','227028','227029','227030','227031','227032','227033','227034','227035','227036','227037','227038','227039','227040','227041','227042','227043','227044','227045','227046','227047','227048','227049','227050','227051','227052','227053','227054','227055','227056','227057','227058','227059','227060','227061','227062','227063','227064','227065','227066','227067','227068','227069','227070','227071','227072','227073','227074','227075','227076','227077','227078','227079','227080','227081','227082','227083','227084','227085','227086','227087','227088','227089','227090','227091','227092','227093','227094','227095','227096','227097','227098','227099','227100','227101','227102','227103','227104','227105','227106','227107','227108','227109','227110','227111','227112','227113','227114','227115','227116','227117','227118','227119','227120','227122','227123','227124','227125','227126','227127','227128','227129','227130','227131','227132','227133','227134','227135','227136','227137','227138','227139','227140','227141','227142','227143','227144','227145','227146','227147','227148','227149','227150','227151','227152','228001','229001','229002','229003','229004','229005','230001','230002','232001','233001','233002','233003','233004','233005','233006','233007','233008','234001','234002','234003','234004','234005','234006','234007','234008','234009','234010','234011','234012','234013','234014','234015','234016','234017','234018','234019','234020','234021','234022','234023','234024','234025','234026','234027','234028','234029','234030','235001','235002','235003','235004','235005','236001','236002','236003','237001','238002','238003','238004','238005','238006','238007','238008','333013','333014','333015','333016','333017','333018','333019','333020','333021','333022','333023','333024','333025','333030','333031','333032','333033','333034','333035','334001','334002','334003','334004','334005','334006','334007','336004','337001','337002','337003','337004','339001','339002','343001','344001','344002','344003','344004','344005','345001','345002','345003','347001','347002','348001','348002','348003','348004','348005','349001','349002','349003','350001','353001','353002','353003','353004','355001','355002','355003','355004','355005','355006','356001','358001','359001','359002','360001','360002','360003','360004','360005','366001','366002','366003','366004','369001','373001','373002','373003','373004','373005','373006','373007','373008','373009','373010','373011','373012','373013','373014','373015','373016','373017','373018','373019','373020','373021','374001','374002','374003','374004','374005','374006','374007','374008','374009','374010','374011','374012','374013','374014','374015','374016','376001','376002','376003','376004','376005','376006','376007','376008','376009','376010','376011','376012','376013','376016','376017','376018','376019','376020','376021','379003','382001','382002','383001','384001','384002','385001','385002','386001','386002','386003','386004','386005','386006','386007','386008','386009','386010','386011','386012','386013','386014','387001','389001','389002','389003','389004','392001','393001','393002','393003','393004','395001','396001','397001','397002','399001','399002','399003','400001','400002','401001','401002','401003','402001','402002','402003','402004','402005','403001','403002','403003','504001','504002','504004','504005','504006','504007','504008','504009','504010','504011','504012','504013','504014','504017','504018','504019','504021','504022','504023','504024','504025','506001','506002','508001','508002','511001','511002','511003','511004','511005','511006','511007','511008','511009','511010','511011','511012','511013','511014','511017','511018','511020','511021','511022','511024','511028','511029','513001','513002','513003','513004','514001','515001','515002','515003','515007','515008','515009','515010','515011','515012','515013','515014','515015','518001','518002','518003','520001','520002','521001','521002','521003','521004','521005','521006','521007','521008','521009','521010','521011','521012','521013','521014','521015','521016','523001','523002','523003','523004','523005','523006','523007','524001','700001','701001','701002','701003','702001','702002','702003','702004','702005','702006','702007','702008','703001','703002','703003','704001','704002','704003','704004','705001','706001','706002','707001','707002','707003','708001','709001','709002','710001','710002','711001','711002','712001','713001','713002','714001','714002','715001','716001','718001','718002','719001','719002','991001','991002','991003','991004','991005','991006','991007','991008','992001','995001','996001','996002','996003','998001','998002','998003','998004','998005','998006','998007','999001','999002','011017','011018','034001','034002','071010','208006','239001','519001','519003','126013','184012','053071','374017','374018','374019','374020','374021','404001','405002','405001','405003','405007','405006','405005','405004','240011','240010','240009','240008','240007','240006','240005','240004','240003','240002','240001','240012','240013','240014','240015','240016','240017','357001','235006','235007','712002','355008','355007','056023','999999','046015','019005','126014','241003','241002','241001','240018','240020','240019','242001','242002','242003','242004','242005','242006','089002','406001','406002','406003','406004','406005','406006','243001','243002','243003','243004','243005','243006','243007','243008','010030','010029','407001','407006','407005','407004','407003','407002','408001','366005','133032','016035','077010','996004','025064','011019','407007','407008','407009','409001','115123','504026','039007','039009','039008','039010','039011','039012','180072','240021','240023','408002','405008','235008','525001','525002','525003','525004','410001','410002','410003','410004','410005','410006','410007','410008','410009','410010','410011','410012','410013','410014','410015','410016','344006','240031','240030','240029','240028','240027','240026','240025','240024','240034','240033','240032','410017','410018','411001','411002','411003','411004','411005','411006','411007','411008','203020','203021','203022','412001','412002','412003','412004','069025','244001','244002','244009','244008','244007','244006','244005','244004','244003','244015','244014','244013','244012','244011','244010','244016','244017','240042','240041','240040','240039','240038','240037','240036','240035','405009','405010','240043','504034','504033','504032','504031','504030','504029','504028','504027','504042','504041','504040','504039','504038','504037','504036','504035','800001','410019','410020','410021','244018','244019','244020','399004','413001','504043','198018','198019','344007','082045','010031','010032','010033','010034','010035','504044','515016','801002','801003','801004','801005','802001','801001','414001','414002','414003','141029','141030','803001','803002','803003','803004','803005','803006','803007','803008','803009','803010','803011','803012','803013','803014','803015','803016','803017','410022','410023','803018','803019','803020','415002','415001','244021','011020','011023','011022','011021','025065','165037','165038','165039','416001','416002','416003','417001','418001','504045','803022','803021','240022','419001','420001','804010','804009','804008','804007','804006','804005','804004','804003','804002','804001','804020','804019','804018','804017','804016','804015','804014','804013','804012','804011','804024','804021','804023','804022','511019','511016','511015','511032','511031','511030','511027','511026','511025','511033','511023','133034','133033','169011','344008','344009','244022','244026','244025','244030','244023','244024','244027','244028','244029','244031','082046','082047','082048','126015','126016','416004','416005','421001','421002','016037','016036','115124','115125','115126','240049','240048','240047','240046','240045','240044','244032','244033','422001','422002','422003','422004','422005','184013','239002','805001','805002','805003','805004','805005','056024','423001','344010','235009','212014','056025','056026','802002','244034','244035','244036','244037','244038','244039','515017','504046','203015','245002','245001','071023','056027','056028','056029','056030','056031','056032','424001','056034','056033','805006','805007','805008','805009','805010','422008','422007','422006','422010','422009','422011','209004','150022','150023','100002','056035','023036','185004','185005','246001','247001','247002','425001','416006','165042','165041','165040','165043','010040','010039','010038','010037','010036','422012','422013','422014','422015','426000','248001','248002','248003','248004','248005','249001','249002','249003','249004','249005','249006','250007','250001','250002','250003','250004','250005','250006','250008','250009','250010','250011','250012','250013','251001','251002','422016','422017','422018','806001','806002','116013','235010','235011','091026','091027','091028','091029','091019','091020','091021','091022','091023','091024','091025','252001','243009','249007','249008','249009','011024','011025','427001','428002','428001','169012','429001','429002','429003') DEFAULT '001001' NOT NULL,
KEY field (field)
diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
index 23941ad2913..f6281ca6c21 100644
--- a/mysql-test/t/type_float.test
+++ b/mysql-test/t/type_float.test
@@ -2,11 +2,14 @@
# -----------
# Numeric floating point.
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
SELECT 10,10.0,10.,.1e+2,100.0e-1;
SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
-drop table if exists t1;
create table t1 (f1 float(24),f2 float(52));
show full columns from t1;
insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150);
@@ -44,6 +47,8 @@ drop table t1;
# Errors
-!$1063 create table t1 (f float(54)); # Should give an error
+--error 1063
+create table t1 (f float(54)); # Should give an error
+--disable_warnings
drop table if exists t1;
-
+--enable_warnings
diff --git a/mysql-test/t/type_ranges.test b/mysql-test/t/type_ranges.test
index a07a1d97f37..767012d0b34 100644
--- a/mysql-test/t/type_ranges.test
+++ b/mysql-test/t/type_ranges.test
@@ -2,7 +2,9 @@
# Test ranges for all types and some other basic tests
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
CREATE TABLE t1 (
auto int(5) unsigned DEFAULT 0 NOT NULL auto_increment,
@@ -53,7 +55,7 @@ DROP INDEX test ON t1;
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
-insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
+insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
diff --git a/mysql-test/t/type_set.test b/mysql-test/t/type_set.test
index 7f1a75e5dbd..4505e3f747b 100644
--- a/mysql-test/t/type_set.test
+++ b/mysql-test/t/type_set.test
@@ -2,7 +2,10 @@
# Test of SET with space
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (a set (' ','a','b') not null);
show create table t1;
drop table t1;
diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test
index 2496ec36915..2f342f8bf67 100644
--- a/mysql-test/t/type_time.test
+++ b/mysql-test/t/type_time.test
@@ -1,7 +1,11 @@
#
# testing of the TIME column type
#
+
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (t time);
insert into t1 values("10:22:33"),("12:34:56.78"),(10),(1234),(123456.78),(1234559.99),("1"),("1:23"),("1:23:45"), ("10.22"), ("-10 1:22:33.45"),("20 10:22:33"),("1999-02-03 20:33:34");
insert t1 values (30),(1230),("1230"),("12:30"),("12:30:35"),("1 12:30:31.32");
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 2929184df93..1c9275ecd0a 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -2,7 +2,10 @@
# Test timestamp
#
+--disable_warnings
drop table if exists t1,t2;
+--enable_warnings
+
CREATE TABLE t1 (a int, t timestamp);
CREATE TABLE t2 (a int, t datetime);
SET TIMESTAMP=1234;
@@ -35,7 +38,7 @@ drop table t1;
create table t1 (ix timestamp);
insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
-select * from t1;
+select ix+0 from t1;
drop table t1;
CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp);
diff --git a/mysql-test/t/type_uint.test b/mysql-test/t/type_uint.test
index 32bcd61ecdb..b4c88eae95d 100644
--- a/mysql-test/t/type_uint.test
+++ b/mysql-test/t/type_uint.test
@@ -2,7 +2,10 @@
# test of unsigned int
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (this int unsigned);
insert into t1 values (1);
insert into t1 values (-1);
diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test
index 8f4f23badb4..9922df447fc 100644
--- a/mysql-test/t/type_year.test
+++ b/mysql-test/t/type_year.test
@@ -1,7 +1,10 @@
#
# Test year
#
+--disable_warnings
drop table if exists t1;
+--enable_warnings
+
create table t1 (y year,y2 year(2));
insert into t1 values (0,0),(1999,1999),(2000,2000),(2001,2001),(70,70),(69,69);
select * from t1;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 6e6b43ebe3b..b46f54c5c41 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -2,7 +2,10 @@
# Test of unions
#
+--disable_warnings
drop table if exists t1,t2,t3;
+--enable_warnings
+
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null);
@@ -20,8 +23,10 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
(select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4;
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1);
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
+--error 1248
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
-(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
+#(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
select found_rows();
#
@@ -86,7 +91,7 @@ SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION SELECT pseudo FROM t1 WHERE pse
SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION ALL SELECT pseudo FROM t1 WHERE pseudo1='joce';
SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION SELECT 1;
drop table t1;
-drop table if exists t1,t2;
+
create table t1 (a int);
create table t2 (a int);
insert into t1 values (1),(2),(3),(4),(5);
@@ -98,3 +103,7 @@ set SQL_SELECT_LIMIT=2;
(select * from t1 limit 1) union (select * from t2 limit 3);
set SQL_SELECT_LIMIT=DEFAULT;
drop table t1,t2;
+
+--error 1096
+select * union select 1;
+select 1 as a,(select a union select a);
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 5cbbd2a350e..31d22c1f850 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -2,7 +2,10 @@
# test of updating of keys
#
-drop table if exists t1;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (a int auto_increment , primary key (a));
insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
update t1 set a=a+10 where a > 34;
@@ -85,5 +88,8 @@ create table t1 (a int not null, b int not null);
insert into t1 values (1,1),(1,2),(1,3);
update t1 set b=4 where a=1 order by b asc limit 1;
update t1 set b=4 where a=1 order by b desc limit 1;
+create table t2 (a int not null, b int not null);
+insert into t2 values (1,1),(1,2),(1,3);
select * from t1;
-drop table t1;
+update t1 set b=(select distinct 1 from (select * from t2) a);
+drop table t1,t2;
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index bb1a9b59611..6260db8c370 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -1,11 +1,15 @@
-error 1054;
+# Initialise
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+--error 1054
set @a := foo;
set @a := connection_id() + 3;
select @a - connection_id();
# Check using and setting variables with SELECT DISTINCT
-drop table if exists t1,t2;
CREATE TABLE t1 ( i int not null, v int not null,index (i));
insert into t1 values (1,1),(1,3),(2,1);
create table t2 (i int not null, unique (i));
diff --git a/mysql-test/t/varbinary.test b/mysql-test/t/varbinary.test
index cc9ee99b7f9..d58954a189b 100644
--- a/mysql-test/t/varbinary.test
+++ b/mysql-test/t/varbinary.test
@@ -1,3 +1,8 @@
+# Initialise
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
#
# varbinary as string and number
#
@@ -10,7 +15,6 @@ select x'31',X'ffff'+0;
# Test of hex constants in WHERE:
#
-drop table if exists t1;
create table t1 (ID int(8) unsigned zerofill not null auto_increment,UNIQ bigint(21) unsigned zerofill not null,primary key (ID),unique (UNIQ) );
insert into t1 set UNIQ=0x38afba1d73e6a18a;
insert into t1 set UNIQ=123;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 5863cb97d57..39aa5a20a71 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -1,7 +1,10 @@
#
# test variables
#
-drop table if exists t1;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
set @`test`=1,@TEST=3,@select=2,@t5=1.23456;
select @test,@`select`,@TEST,@not_used;
set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL;
@@ -229,7 +232,6 @@ set log_warnings=1;
# key buffer
#
-DROP TABLE IF EXISTS t1,t2;
create table t1 (a int not null auto_increment, primary key(a));
create table t2 (a int not null auto_increment, primary key(a));
insert into t1 values(null),(null),(null);
diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test
index 5fb536def71..8cff8706c43 100644
--- a/mysql-test/t/warnings.test
+++ b/mysql-test/t/warnings.test
@@ -1,7 +1,10 @@
#
# Test some warnings
#
+--disable-warnings
drop table if exists t1;
+--enable-warnings
+
create table t1 (a int);
insert into t1 values (1);
insert into t1 values ("hej");
@@ -11,3 +14,15 @@ insert into t1 values ("hej");
insert into t1 values ("hej"),("då");
drop table t1;
set SQL_WARNINGS=0;
+
+#
+# Test other warnings
+
+drop temporary table if exists not_exists;
+drop table if exists not_exists_table;
+show warnings limit 1;
+drop database if exists not_exists_db;
+show count(*) warnings;
+create table t1(id int);
+create table if not exists t1(id int);
+select @@warning_count;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index a927fa5e3a0..5b1c859cb2a 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -17,7 +17,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. -I$(srcdir)
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir)
pkglib_LIBRARIES = libmysys.a
LDADD = libmysys.a ../dbug/libdbug.a \
../strings/libmystrings.a
@@ -31,7 +31,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_pread.c my_write.c \
mf_keycache.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
- my_lock.c mf_brkhant.c my_alarm.c \
+ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
my_alloc.c safemalloc.c my_new.cc \
my_fopen.c my_fstream.c \
@@ -39,7 +39,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
mf_pack.c mf_unixpath.c mf_strip.c \
- mf_casecnv.c mf_soundex.c mf_wcomp.c mf_wfile.c \
+ mf_soundex.c mf_wcomp.c mf_wfile.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c \
tree.c list.c hash.c array.c string.c typelib.c \
@@ -49,18 +49,18 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_quick.c my_lockmem.c my_static.c \
my_getopt.c my_mkdir.c \
default.c my_compress.c checksum.c raid.cc \
- my_net.c my_semaphore.c my_port.c my_sleep.c \
- my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c \
+ my_net.c my_semaphore.c my_port.c my_sleep.c \
+ charset.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
- my_netware.c
+ my_handler.c my_netware.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
-# test_fn removed 980815 since it not up to date test_dir
-noinst_PROGRAMS = @THREAD_LPROGRAMS@
+noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
+# charset2html_DEPENDENCIES= $(LIBRARIES)
EXTRA_PROGRAMS =
DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
@@ -92,6 +92,7 @@ test_vsnprintf$(EXEEXT): my_vsnprintf.c $(LIBRARIES)
$(CP) $(srcdir)/my_vsnprintf.c test_vsnprintf.c
$(LINK) $(FLAGS) -DMAIN ./test_vsnprintf.c $(LDADD) $(LIBS)
$(RM) -f test_vsnprintf.c
+
test_io_cache$(EXEEXT): mf_iocache.c $(LIBRARIES)
$(CP) $(srcdir)/mf_iocache.c test_io_cache.c
$(LINK) $(FLAGS) -DMAIN ./test_io_cache.c $(LDADD) $(LIBS)
@@ -103,6 +104,9 @@ test_dir$(EXEEXT): test_dir.c $(LIBRARIES)
test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
+charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
+ $(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS)
+
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
diff --git a/mysys/charset.c b/mysys/charset.c
index 235fcb08023..1145a989958 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -19,76 +19,286 @@
#include <m_ctype.h>
#include <m_string.h>
#include <my_dir.h>
+#include <my_xml.h>
-typedef struct cs_id_st {
- char *name;
- uint number;
-} CS_ID;
-const char *charsets_dir = NULL;
-static DYNAMIC_ARRAY cs_info_table;
-static CS_ID **available_charsets;
-static int charset_initialized=0;
+/*
-#define MAX_LINE 1024
+ The code below implements this functionality:
+
+ - Initializing charset related structures
+ - Loading dynamic charsets
+ - Searching for a proper CHARSET_INFO
+ using charset name, collation name or collatio ID
+ - Setting server default character set
+*/
-#define CTYPE_TABLE_SIZE 257
-#define TO_LOWER_TABLE_SIZE 256
-#define TO_UPPER_TABLE_SIZE 256
-#define SORT_ORDER_TABLE_SIZE 256
-struct simpleconfig_buf_st {
- FILE *f;
- char buf[MAX_LINE];
- char *p;
-};
+static void set_max_sort_char(CHARSET_INFO *cs)
+{
+ uchar max_char;
+ uint i;
+
+ if (!cs->sort_order)
+ return;
+
+ max_char=cs->sort_order[(uchar) cs->max_sort_char];
+ for (i= 0; i < 256; i++)
+ {
+ if ((uchar) cs->sort_order[i] > max_char)
+ {
+ max_char=(uchar) cs->sort_order[i];
+ cs->max_sort_char= (char) i;
+ }
+ }
+}
+
-static uint num_from_csname(CS_ID **cs, const char *name)
+static void simple_cs_init_functions(CHARSET_INFO *cs)
{
- CS_ID **c;
- for (c = cs; *c; ++c)
- if (!strcmp((*c)->name, name))
- return (*c)->number;
- return 0; /* this mimics find_type() */
+
+ cs->strnxfrm = my_strnxfrm_simple;
+ cs->strnncoll = my_strnncoll_simple;
+ cs->strnncollsp = my_strnncollsp_simple;
+ cs->like_range = my_like_range_simple;
+ cs->wildcmp = my_wildcmp_8bit;
+ cs->mb_wc = my_mb_wc_8bit;
+ cs->wc_mb = my_wc_mb_8bit;
+ cs->caseup_str = my_caseup_str_8bit;
+ cs->casedn_str = my_casedn_str_8bit;
+ cs->caseup = my_caseup_8bit;
+ cs->casedn = my_casedn_8bit;
+ cs->tosort = my_tosort_8bit;
+ cs->strcasecmp = my_strcasecmp_8bit;
+ cs->strncasecmp = my_strncasecmp_8bit;
+ cs->hash_caseup = my_hash_caseup_simple;
+ cs->hash_sort = my_hash_sort_simple;
+ cs->snprintf = my_snprintf_8bit;
+ cs->long10_to_str= my_long10_to_str_8bit;
+ cs->longlong10_to_str= my_longlong10_to_str_8bit;
+ cs->fill = my_fill_8bit;
+ cs->strntol = my_strntol_8bit;
+ cs->strntoul = my_strntoul_8bit;
+ cs->strntoll = my_strntoll_8bit;
+ cs->strntoull = my_strntoull_8bit;
+ cs->strntod = my_strntod_8bit;
+ cs->scan = my_scan_8bit;
+ cs->mbmaxlen = 1;
+ cs->numchars = my_numchars_8bit;
+ cs->charpos = my_charpos_8bit;
}
-static char *name_from_csnum(CS_ID **cs, uint number)
+
+typedef struct
{
- CS_ID **c;
- if(cs)
- for (c = cs; *c; ++c)
- if ((*c)->number == number)
- return (*c)->name;
- return (char*) "?"; /* this mimics find_type() */
+ int nchars;
+ MY_UNI_IDX uidx;
+} uni_idx;
+
+#define PLANE_SIZE 0x100
+#define PLANE_NUM 0x100
+#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM)
+
+static int pcmp(const void * f, const void * s)
+{
+ const uni_idx *F= (const uni_idx*) f;
+ const uni_idx *S= (const uni_idx*) s;
+ int res;
+
+ if (!(res=((S->nchars)-(F->nchars))))
+ res=((F->uidx.from)-(S->uidx.to));
+ return res;
+}
+
+
+static my_bool create_fromuni(CHARSET_INFO *cs)
+{
+ uni_idx idx[PLANE_NUM];
+ int i,n;
+
+ /* Clear plane statistics */
+ bzero(idx,sizeof(idx));
+
+ /* Count number of characters in each plane */
+ for (i=0; i< 0x100; i++)
+ {
+ uint16 wc=cs->tab_to_uni[i];
+ int pl= PLANE_NUMBER(wc);
+
+ if (wc || !i)
+ {
+ if (!idx[pl].nchars)
+ {
+ idx[pl].uidx.from=wc;
+ idx[pl].uidx.to=wc;
+ }else
+ {
+ idx[pl].uidx.from=wc<idx[pl].uidx.from?wc:idx[pl].uidx.from;
+ idx[pl].uidx.to=wc>idx[pl].uidx.to?wc:idx[pl].uidx.to;
+ }
+ idx[pl].nchars++;
+ }
+ }
+
+ /* Sort planes in descending order */
+ qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp);
+
+ for (i=0; i < PLANE_NUM; i++)
+ {
+ int ch,numchars;
+
+ /* Skip empty plane */
+ if (!idx[i].nchars)
+ break;
+
+ numchars=idx[i].uidx.to-idx[i].uidx.from+1;
+ idx[i].uidx.tab=(unsigned char*)my_once_alloc(numchars *
+ sizeof(*idx[i].uidx.tab),
+ MYF(MY_WME));
+ bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
+
+ for (ch=1; ch < PLANE_SIZE; ch++)
+ {
+ uint16 wc=cs->tab_to_uni[ch];
+ if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc)
+ {
+ int ofs= wc - idx[i].uidx.from;
+ idx[i].uidx.tab[ofs]= ch;
+ }
+ }
+ }
+
+ /* Allocate and fill reverse table for each plane */
+ n=i;
+ cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1),
+ MYF(MY_WME));
+ for (i=0; i< n; i++)
+ cs->tab_from_uni[i]= idx[i].uidx;
+
+ /* Set end-of-list marker */
+ bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX));
+ return FALSE;
}
-static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf)
+
+static void simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
{
- char *endptr=fb->p;
+ to->number= from->number ? from->number : to->number;
+ to->state|= from->state;
+
+ if (from->csname)
+ to->csname= my_once_strdup(from->csname,MYF(MY_WME));
+
+ if (from->name)
+ to->name= my_once_strdup(from->name,MYF(MY_WME));
+
+ if (from->ctype)
+ to->ctype= (uchar*) my_once_memdup((char*) from->ctype,
+ MY_CS_CTYPE_TABLE_SIZE, MYF(MY_WME));
+ if (from->to_lower)
+ to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower,
+ MY_CS_TO_LOWER_TABLE_SIZE, MYF(MY_WME));
+ if (from->to_upper)
+ to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper,
+ MY_CS_TO_UPPER_TABLE_SIZE, MYF(MY_WME));
+ if (from->sort_order)
+ {
+ to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order,
+ MY_CS_SORT_ORDER_TABLE_SIZE,
+ MYF(MY_WME));
+ set_max_sort_char(to);
+ }
+ if (from->tab_to_uni)
+ {
+ uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16);
+ to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni, sz,
+ MYF(MY_WME));
+ create_fromuni(to);
+ }
+}
- for (;;)
+
+static my_bool simple_cs_is_full(CHARSET_INFO *cs)
+{
+ return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper &&
+ cs->to_lower) &&
+ (cs->number && cs->name && cs->sort_order));
+}
+
+
+static int add_collation(CHARSET_INFO *cs)
+{
+ if (cs->name && (cs->number || (cs->number=get_charset_number(cs->name))))
{
- while (isspace(*endptr))
- ++endptr;
- if (*endptr && *endptr != '#') /* Not comment */
- break; /* Found something */
- if ((fgets(fb->buf, sizeof(fb->buf), fb->f)) == NULL)
- return TRUE; /* end of file */
- endptr = fb->buf;
+ if (!all_charsets[cs->number])
+ {
+ if (!(all_charsets[cs->number]=
+ (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
+ return MY_XML_ERROR;
+ bzero((void*)all_charsets[cs->number],sizeof(CHARSET_INFO));
+ }
+
+ if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
+ {
+ simple_cs_copy_data(all_charsets[cs->number],cs);
+ if (simple_cs_is_full(all_charsets[cs->number]))
+ {
+ simple_cs_init_functions(all_charsets[cs->number]);
+ all_charsets[cs->number]->state |= MY_CS_LOADED;
+ }
+ }
+ cs->number= 0;
+ cs->name= NULL;
+ cs->state= 0;
+ cs->sort_order= NULL;
+ cs->state= 0;
}
+ return MY_XML_OK;
+}
- while (!isspace(*endptr))
- *buf++= *endptr++;
- *buf=0;
- fb->p = endptr;
+#define MAX_BUF 1024*16
+#define MY_CHARSET_INDEX "Index.xml"
+
+const char *charsets_dir= NULL;
+static int charset_initialized=0;
+
+
+static my_bool my_read_charset_file(const char *filename, myf myflags)
+{
+ char *buf;
+ int fd;
+ uint len;
+
+ if (!(buf= (char *)my_malloc(MAX_BUF,myflags)))
+ return FALSE;
+
+ if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
+ {
+ my_free(buf,myflags);
+ return TRUE;
+ }
+ len=read(fd,buf,MAX_BUF);
+ my_close(fd,myflags);
+
+ if (my_parse_charset_xml(buf,len,add_collation))
+ {
+#ifdef NOT_YET
+ printf("ERROR at line %d pos %d '%s'\n",
+ my_xml_error_lineno(&p)+1,
+ my_xml_error_pos(&p),
+ my_xml_error_string(&p));
+#endif
+ }
+
+ my_free(buf, myflags);
return FALSE;
}
char *get_charsets_dir(char *buf)
{
- const char *sharedir = SHAREDIR;
+ const char *sharedir= SHAREDIR;
DBUG_ENTER("get_charsets_dir");
if (charsets_dir != NULL)
@@ -103,269 +313,181 @@ char *get_charsets_dir(char *buf)
NullS);
}
convert_dirname(buf,buf,NullS);
- DBUG_PRINT("info",("charsets dir='%s'", buf));
+ DBUG_PRINT("info",("charsets dir: '%s'", buf));
DBUG_RETURN(strend(buf));
}
+CHARSET_INFO *all_charsets[256];
+CHARSET_INFO *default_charset_info = &my_charset_latin1;
+CHARSET_INFO *system_charset_info = &my_charset_latin1;
+
+#define MY_ADD_CHARSET(x) all_charsets[(x)->number]=(x)
-static my_bool read_charset_index(CS_ID ***charsets, myf myflags)
+
+static my_bool init_compiled_charsets(myf flags __attribute__((unused)))
{
- struct simpleconfig_buf_st fb;
- char buf[MAX_LINE], num_buf[MAX_LINE];
- DYNAMIC_ARRAY cs;
- CS_ID *csid;
+ CHARSET_INFO *cs;
- strmov(get_charsets_dir(buf), "Index");
+ MY_ADD_CHARSET(&my_charset_latin1);
+
+ MY_ADD_CHARSET(&my_charset_bin);
- if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL)
- return TRUE;
- fb.buf[0] = '\0';
- fb.p = fb.buf;
+#ifdef HAVE_CHARSET_big5
+ MY_ADD_CHARSET(&my_charset_big5);
+#endif
- if (my_init_dynamic_array(&cs, sizeof(CS_ID *), 32, 32))
- return TRUE;
+#ifdef HAVE_CHARSET_czech
+ MY_ADD_CHARSET(&my_charset_czech);
+#endif
- while (!get_word(&fb, buf) && !get_word(&fb, num_buf))
- {
- uint csnum;
- uint length;
+#ifdef HAVE_CHARSET_euc_kr
+ MY_ADD_CHARSET(&my_charset_euc_kr);
+#endif
- if (!(csnum = atoi(num_buf)))
- {
- /* corrupt Index file */
- my_fclose(fb.f,myflags);
- return TRUE;
- }
+#ifdef HAVE_CHARSET_gb2312
+ MY_ADD_CHARSET(&my_charset_gb2312);
+#endif
- if (!(csid = (CS_ID*) my_once_alloc(sizeof(CS_ID), myflags)) ||
- !(csid->name=
- (char*) my_once_alloc(length= (uint) strlen(buf)+1, myflags)))
- {
- my_fclose(fb.f,myflags);
- return TRUE;
- }
- memcpy(csid->name,buf,length);
- csid->number = csnum;
+#ifdef HAVE_CHARSET_gbk
+ MY_ADD_CHARSET(&my_charset_gbk);
+#endif
- insert_dynamic(&cs, (gptr) &csid);
- }
- my_fclose(fb.f,myflags);
+#ifdef HAVE_CHARSET_latin1_de
+ MY_ADD_CHARSET(&my_charset_latin1_de);
+#endif
+#ifdef HAVE_CHARSET_sjis
+ MY_ADD_CHARSET(&my_charset_sjis);
+#endif
- if (!(*charsets =
- (CS_ID **) my_once_alloc((cs.elements + 1) * sizeof(CS_ID *), myflags)))
- return TRUE;
- /* unwarranted chumminess with dynamic_array implementation? */
- memcpy((byte *) *charsets, cs.buffer, cs.elements * sizeof(CS_ID *));
- (*charsets)[cs.elements] = NULL;
- delete_dynamic(&cs);
+#ifdef HAVE_CHARSET_tis620
+ MY_ADD_CHARSET(&my_charset_tis620);
+#endif
+
+#ifdef HAVE_CHARSET_ucs2
+ MY_ADD_CHARSET(&my_charset_ucs2);
+#endif
+
+#ifdef HAVE_CHARSET_ujis
+ MY_ADD_CHARSET(&my_charset_ujis);
+#endif
+
+#ifdef HAVE_CHARSET_utf8
+ MY_ADD_CHARSET(&my_charset_utf8);
+#endif
+#ifdef HAVE_CHARSET_win1250ch
+ MY_ADD_CHARSET(&my_charset_win1250ch);
+#endif
+
+ /* Copy compiled charsets */
+ for (cs=compiled_charsets; cs->name; cs++)
+ {
+ all_charsets[cs->number]=cs;
+ }
+
return FALSE;
}
-
#ifdef __NETWARE__
my_bool STDCALL init_available_charsets(myf myflags)
#else
static my_bool init_available_charsets(myf myflags)
#endif
{
- my_bool error=0;
+ char fname[FN_REFLEN];
+ my_bool error=FALSE;
/*
We have to use charset_initialized to not lock on THR_LOCK_charset
inside get_internal_charset...
- */
+ */
if (!charset_initialized)
{
- /*
- To make things thread safe we are not allowing other threads to interfere
- while we may changing the cs_info_table
- */
+ CHARSET_INFO **cs;
+ /*
+ To make things thread safe we are not allowing other threads to interfere
+ while we may changing the cs_info_table
+ */
pthread_mutex_lock(&THR_LOCK_charset);
- if (!cs_info_table.buffer) /* If not initialized */
+
+ bzero(&all_charsets,sizeof(all_charsets));
+ init_compiled_charsets(myflags);
+
+ /* Copy compiled charsets */
+ for (cs=all_charsets; cs < all_charsets+255 ; cs++)
{
- my_init_dynamic_array(&cs_info_table, sizeof(CHARSET_INFO*), 16, 8);
- error = read_charset_index(&available_charsets, myflags);
+ if (*cs)
+ set_max_sort_char(*cs);
}
+
+ strmov(get_charsets_dir(fname), MY_CHARSET_INDEX);
+ error= my_read_charset_file(fname,myflags);
charset_initialized=1;
pthread_mutex_unlock(&THR_LOCK_charset);
}
- if(!available_charsets || !available_charsets[0])
- error = TRUE;
return error;
}
void free_charsets(void)
{
- delete_dynamic(&cs_info_table);
charset_initialized=0;
}
-static my_bool fill_array(uchar *array, int sz, struct simpleconfig_buf_st *fb)
-{
- char buf[MAX_LINE];
- while (sz--)
- {
- if (get_word(fb, buf))
- {
- DBUG_PRINT("error",("get_word failed, expecting %d more words", sz + 1));
- return 1;
- }
- *array++ = (uchar) strtol(buf, NULL, 16);
- }
- return 0;
-}
-
-
-static void get_charset_conf_name(uint cs_number, char *buf)
+static void get_charset_conf_name(const char *cs_name, char *buf)
{
- strxmov(get_charsets_dir(buf),
- name_from_csnum(available_charsets, cs_number), ".conf", NullS);
-}
-
-
-static my_bool read_charset_file(uint cs_number, CHARSET_INFO *set,
- myf myflags)
-{
- struct simpleconfig_buf_st fb;
- char buf[FN_REFLEN];
- my_bool result;
- DBUG_ENTER("read_charset_file");
- DBUG_PRINT("enter",("cs_number: %d", cs_number));
-
- if (cs_number <= 0)
- DBUG_RETURN(TRUE);
-
- get_charset_conf_name(cs_number, buf);
- DBUG_PRINT("info",("file name: %s", buf));
-
- if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL)
- DBUG_RETURN(TRUE);
-
- fb.buf[0] = '\0'; /* Init for get_word */
- fb.p = fb.buf;
-
- result=FALSE;
- if (fill_array(set->ctype, CTYPE_TABLE_SIZE, &fb) ||
- fill_array(set->to_lower, TO_LOWER_TABLE_SIZE, &fb) ||
- fill_array(set->to_upper, TO_UPPER_TABLE_SIZE, &fb) ||
- fill_array(set->sort_order, SORT_ORDER_TABLE_SIZE, &fb))
- result=TRUE;
-
- my_fclose(fb.f, MYF(0));
- DBUG_RETURN(result);
+ strxmov(get_charsets_dir(buf), cs_name, ".conf", NullS);
}
uint get_charset_number(const char *charset_name)
{
- uint number=compiled_charset_number(charset_name);
- if (number)
- return number;
+ CHARSET_INFO **cs;
if (init_available_charsets(MYF(0))) /* If it isn't initialized */
return 0;
- return num_from_csname(available_charsets, charset_name);
+
+ for (cs= all_charsets; cs < all_charsets+255; ++cs)
+ {
+ if ( cs[0] && cs[0]->name && !strcmp(cs[0]->name, charset_name))
+ return cs[0]->number;
+ }
+ return 0; /* this mimics find_type() */
}
+
const char *get_charset_name(uint charset_number)
{
- const char *name=compiled_charset_name(charset_number);
- if (*name != '?')
- return name;
+ CHARSET_INFO *cs;
if (init_available_charsets(MYF(0))) /* If it isn't initialized */
return "?";
- return name_from_csnum(available_charsets, charset_number);
-}
-
-
-static CHARSET_INFO *find_charset(CHARSET_INFO **table, uint cs_number,
- size_t tablesz)
-{
- uint i;
- for (i = 0; i < tablesz; ++i)
- if (table[i]->number == cs_number)
- return table[i];
- return NULL;
-}
-static CHARSET_INFO *find_charset_by_name(CHARSET_INFO **table,
- const char *name, size_t tablesz)
-{
- uint i;
- for (i = 0; i < tablesz; ++i)
- if (!strcmp(table[i]->name,name))
- return table[i];
- return NULL;
+ cs=all_charsets[charset_number];
+ if (cs && (cs->number == charset_number) && cs->name )
+ return (char*) cs->name;
+
+ return (char*) "?"; /* this mimics find_type() */
}
-static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name, myf flags)
-{
- CHARSET_INFO tmp_cs,*cs;
- uchar tmp_ctype[CTYPE_TABLE_SIZE];
- uchar tmp_to_lower[TO_LOWER_TABLE_SIZE];
- uchar tmp_to_upper[TO_UPPER_TABLE_SIZE];
- uchar tmp_sort_order[SORT_ORDER_TABLE_SIZE];
-
- /* Don't allocate memory if we are not sure we can find the char set */
- cs= &tmp_cs;
- bzero((char*) cs, sizeof(*cs));
- cs->ctype=tmp_ctype;
- cs->to_lower=tmp_to_lower;
- cs->to_upper=tmp_to_upper;
- cs->sort_order=tmp_sort_order;
- if (read_charset_file(cs_number, cs, flags))
- return NULL;
-
- cs = (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),
- MYF(MY_WME));
- *cs=tmp_cs;
- cs->name = (char *) my_once_alloc((uint) strlen(cs_name)+1, MYF(MY_WME));
- cs->ctype = (uchar*) my_once_alloc(CTYPE_TABLE_SIZE, MYF(MY_WME));
- cs->to_lower = (uchar*) my_once_alloc(TO_LOWER_TABLE_SIZE, MYF(MY_WME));
- cs->to_upper = (uchar*) my_once_alloc(TO_UPPER_TABLE_SIZE, MYF(MY_WME));
- cs->sort_order=(uchar*) my_once_alloc(SORT_ORDER_TABLE_SIZE, MYF(MY_WME));
- cs->number = cs_number;
- memcpy((char*) cs->name, (char*) cs_name, strlen(cs_name) + 1);
- memcpy((char*) cs->ctype, (char*) tmp_ctype, sizeof(tmp_ctype));
- memcpy((char*) cs->to_lower, (char*) tmp_to_lower, sizeof(tmp_to_lower));
- memcpy((char*) cs->to_upper, (char*) tmp_to_upper, sizeof(tmp_to_upper));
- memcpy((char*) cs->sort_order, (char*) tmp_sort_order,
- sizeof(tmp_sort_order));
- insert_dynamic(&cs_info_table, (gptr) &cs);
- return cs;
-}
static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
{
+ char buf[FN_REFLEN];
CHARSET_INFO *cs;
/*
To make things thread safe we are not allowing other threads to interfere
while we may changing the cs_info_table
*/
pthread_mutex_lock(&THR_LOCK_charset);
- if (!(cs = find_charset((CHARSET_INFO**) cs_info_table.buffer, cs_number,
- cs_info_table.elements)))
- if (!(cs = find_compiled_charset(cs_number)))
- cs=add_charset(cs_number, get_charset_name(cs_number), flags);
- pthread_mutex_unlock(&THR_LOCK_charset);
- return cs;
-}
+ cs= all_charsets[cs_number];
-static CHARSET_INFO *get_internal_charset_by_name(const char *name, myf flags)
-{
- CHARSET_INFO *cs;
- /*
- To make things thread safe we are not allowing other threads to interfere
- while we may changing the cs_info_table
- */
- pthread_mutex_lock(&THR_LOCK_charset);
- if (!(cs = find_charset_by_name((CHARSET_INFO**) cs_info_table.buffer, name,
- cs_info_table.elements)))
- if (!(cs = find_compiled_charset_by_name(name)))
- cs=add_charset(get_charset_number(name), name, flags);
+ if (cs && !(cs->state & (MY_CS_COMPILED | MY_CS_LOADED)))
+ {
+ strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
+ my_read_charset_file(buf,flags);
+ cs= (cs->state & MY_CS_LOADED) ? cs : NULL;
+ }
pthread_mutex_unlock(&THR_LOCK_charset);
return cs;
}
@@ -375,12 +497,16 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags)
{
CHARSET_INFO *cs;
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
+
+ if (!cs_number)
+ return NULL;
+
cs=get_internal_charset(cs_number, flags);
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN], cs_string[23];
- strmov(get_charsets_dir(index_file), "Index");
+ strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
cs_string[0]='#';
int10_to_str(cs_number, cs_string+1, 10);
my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
@@ -393,48 +519,85 @@ my_bool set_default_charset(uint cs, myf flags)
CHARSET_INFO *new_charset;
DBUG_ENTER("set_default_charset");
DBUG_PRINT("enter",("character set: %d",(int) cs));
- new_charset = get_charset(cs, flags);
+
+ new_charset= get_charset(cs, flags);
if (!new_charset)
{
DBUG_PRINT("error",("Couldn't set default character set"));
DBUG_RETURN(TRUE); /* error */
}
- default_charset_info = new_charset;
+ default_charset_info= new_charset;
+ system_charset_info= new_charset;
+
DBUG_RETURN(FALSE);
}
CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
{
+ uint cs_number;
CHARSET_INFO *cs;
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
- cs=get_internal_charset_by_name(cs_name, flags);
+
+ cs_number=get_charset_number(cs_name);
+ cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN];
- strmov(get_charsets_dir(index_file), "Index");
+ strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
}
return cs;
}
+
+CHARSET_INFO *get_charset_by_csname(const char *cs_name, myf flags)
+{
+ CHARSET_INFO *cs=NULL;
+ CHARSET_INFO **css;
+ (void) init_available_charsets(MYF(0)); /* If it isn't initialized */
+
+ for (css= all_charsets; css < all_charsets+255; ++css)
+ {
+ if ( css[0] && (css[0]->state & MY_CS_PRIMARY) &&
+ css[0]->csname && !strcmp(css[0]->csname, cs_name))
+ {
+ cs= css[0]->number ? get_internal_charset(css[0]->number,flags) : NULL;
+ break;
+ }
+ }
+
+ if (!cs && (flags & MY_WME))
+ {
+ char index_file[FN_REFLEN];
+ strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
+ my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
+ }
+
+ return cs;
+}
+
+
my_bool set_default_charset_by_name(const char *cs_name, myf flags)
{
CHARSET_INFO *new_charset;
DBUG_ENTER("set_default_charset_by_name");
DBUG_PRINT("enter",("character set: %s", cs_name));
- new_charset = get_charset_by_name(cs_name, flags);
+
+ new_charset= get_charset_by_name(cs_name, flags);
if (!new_charset)
{
DBUG_PRINT("error",("Couldn't set default character set"));
DBUG_RETURN(TRUE); /* error */
}
- default_charset_info = new_charset;
+ default_charset_info= new_charset;
+ system_charset_info= new_charset;
DBUG_RETURN(FALSE);
}
+
/* Only append name if it doesn't exist from before */
static my_bool charset_in_string(const char *name, DYNAMIC_STRING *s)
@@ -446,13 +609,14 @@ static my_bool charset_in_string(const char *name, DYNAMIC_STRING *s)
if (! pos[length] || pos[length] == ' ')
return TRUE; /* Already existed */
}
-
return FALSE;
}
+
static void charset_append(DYNAMIC_STRING *s, const char *name)
{
- if (!charset_in_string(name, s)) {
+ if (!charset_in_string(name, s))
+ {
dynstr_append(s, name);
dynstr_append(s, " ");
}
@@ -462,7 +626,7 @@ static void charset_append(DYNAMIC_STRING *s, const char *name)
/* Returns a dynamically-allocated string listing the character sets
requested. The caller is responsible for freeing the memory. */
-char * list_charsets(myf want_flags)
+char *list_charsets(myf want_flags)
{
DYNAMIC_STRING s;
char *p;
@@ -470,92 +634,57 @@ char * list_charsets(myf want_flags)
(void)init_available_charsets(MYF(0));
init_dynamic_string(&s, NullS, 256, 1024);
- if (want_flags & MY_COMPILED_SETS)
+ if (want_flags & MY_CS_COMPILED)
{
- CHARSET_INFO *cs;
- for (cs = compiled_charsets; cs->number > 0; cs++)
+ CHARSET_INFO **cs;
+ for (cs= all_charsets; cs < all_charsets+255; cs++)
{
- dynstr_append(&s, cs->name);
- dynstr_append(&s, " ");
+ if (cs[0])
+ {
+ dynstr_append(&s, cs[0]->name);
+ dynstr_append(&s, " ");
+ }
}
}
- if (want_flags & MY_CONFIG_SETS)
+ if (want_flags & MY_CS_CONFIG)
{
- CS_ID **c;
+ CHARSET_INFO **cs;
char buf[FN_REFLEN];
MY_STAT status;
- if((c=available_charsets))
- for (; *c; ++c)
- {
- if (charset_in_string((*c)->name, &s))
- continue;
- get_charset_conf_name((*c)->number, buf);
- if (!my_stat(buf, &status, MYF(0)))
- continue; /* conf file doesn't exist */
- dynstr_append(&s, (*c)->name);
- dynstr_append(&s, " ");
- }
+ for (cs=all_charsets; cs < all_charsets+255; cs++)
+ {
+ if (!cs[0] || !cs[0]->name || charset_in_string(cs[0]->name, &s))
+ continue;
+ get_charset_conf_name(cs[0]->name, buf);
+ if (!my_stat(buf, &status, MYF(0)))
+ continue; /* conf file doesn't exist */
+ dynstr_append(&s, cs[0]->name);
+ dynstr_append(&s, " ");
+ }
}
- if (want_flags & MY_INDEX_SETS)
+ if (want_flags & (MY_CS_INDEX|MY_CS_LOADED))
{
- CS_ID **c;
- for (c = available_charsets; *c; ++c)
- charset_append(&s, (*c)->name);
+ CHARSET_INFO **cs;
+ for (cs= all_charsets; cs < all_charsets + 255; cs++)
+ if (cs[0] && cs[0]->name && (cs[0]->state & want_flags) )
+ charset_append(&s, cs[0]->name);
}
-
- if (want_flags & MY_LOADED_SETS)
+
+ if (s.length)
+ {
+ s.str[s.length - 1]= '\0'; /* chop trailing space */
+ p= my_strdup(s.str, MYF(MY_WME));
+ }
+ else
{
- uint i;
- for (i = 0; i < cs_info_table.elements; i++)
- charset_append(&s,
- dynamic_element(&cs_info_table, i, CHARSET_INFO *)->name);
+ p= my_strdup("", MYF(MY_WME));
}
- s.str[s.length - 1] = '\0'; /* chop trailing space */
- p = my_strdup(s.str, MYF(MY_WME));
dynstr_free(&s);
-
+
return p;
}
-/****************************************************************************
-* Code for debugging.
-****************************************************************************/
-
-static void _print_array(uint8 *data, uint size)
-{
- uint i;
- for (i = 0; i < size; ++i)
- {
- if (i == 0 || i % 16 == size % 16) printf(" ");
- printf(" %02x", data[i]);
- if ((i+1) % 16 == size % 16) printf("\n");
- }
-}
-
-/* _print_csinfo is called from test_charset.c */
-void _print_csinfo(CHARSET_INFO *cs)
-{
- printf("%s #%d\n", cs->name, cs->number);
- printf("ctype:\n"); _print_array(cs->ctype, 257);
- printf("to_lower:\n"); _print_array(cs->to_lower, 256);
- printf("to_upper:\n"); _print_array(cs->to_upper, 256);
- printf("sort_order:\n"); _print_array(cs->sort_order, 256);
- printf("collate: %3s (%d, %p, %p, %p, %p, %p)\n",
- cs->strxfrm_multiply ? "yes" : "no",
- cs->strxfrm_multiply,
- cs->strcoll,
- cs->strxfrm,
- cs->strnncoll,
- cs->strnxfrm,
- cs->like_range);
- printf("multi-byte: %3s (%d, %p, %p, %p)\n",
- cs->mbmaxlen ? "yes" : "no",
- cs->mbmaxlen,
- cs->ismbchar,
- cs->ismbhead,
- cs->mbcharlen);
-}
diff --git a/mysys/charset2html.c b/mysys/charset2html.c
new file mode 100644
index 00000000000..0d6450a8116
--- /dev/null
+++ b/mysys/charset2html.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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
+ */
+
+/*
+ Written by Alexander Barkov to check what
+ a charset is in your favorite web browser
+*/
+
+#include <my_global.h>
+#include <m_ctype.h>
+#include <my_sys.h>
+#include <mysql_version.h>
+
+#include <stdio.h>
+
+typedef struct char_info_st
+{
+ int cod;
+ int srt;
+ int uni;
+ int low;
+ int upp;
+ int ctp;
+} MY_CH;
+
+static int chcmp(const void *vf, const void *vs)
+{
+ const MY_CH *f=vf;
+ const MY_CH *s=vs;
+
+ return f->srt-s->srt ? f->srt-s->srt : f->uni-s->uni;
+}
+
+static void print_cs(CHARSET_INFO *cs)
+{
+ uint i;
+ int srt;
+ int clr=0;
+ MY_CH ch[256];
+
+ printf("<HTML>\n");
+ printf("<HEAD>\n");
+ printf("</HEAD>\n");
+ printf("<BODY><PRE>\n");
+ printf("Charset %s\n",cs->name);
+
+ printf("<TABLE>\n");
+ printf("<TR><TH>Code<TH>Uni<TH>Sort<TH>Ctype<TH>Ch<TH>Lo<TH>Up</TR>");
+
+ for (i=0; i<256; i++)
+ {
+ ch[i].cod=i;
+ ch[i].srt=cs->sort_order[i];
+ ch[i].uni=cs->tab_to_uni[i];
+ ch[i].low=cs->tab_to_uni[cs->to_lower[i]];
+ ch[i].upp=cs->tab_to_uni[cs->to_upper[i]];
+ ch[i].ctp=cs->ctype[i+1];
+ }
+
+ qsort(ch,256,sizeof(MY_CH),&chcmp);
+ srt=ch[0].srt;
+
+ for (i=0; i<256; i++)
+ {
+ clr = (srt!=ch[i].srt) ? !clr : clr;
+
+ printf("<TR bgcolor=#%s>",clr ? "DDDDDD" : "EEEE99");
+ printf("<TD>%02X",ch[i].cod);
+ printf("<TD>%04X",ch[i].uni);
+ printf("<TD>%d",ch[i].srt);
+
+ printf("<TD>%s%s%s%s%s%s%s%s",
+ ch[i].ctp & _U ? "U" : "",
+ ch[i].ctp & _L ? "L" : "",
+ ch[i].ctp & _NMR ? "N" : "",
+ ch[i].ctp & _SPC ? "S" : "",
+ ch[i].ctp & _PNT ? "P" : "",
+ ch[i].ctp & _CTR ? "C" : "",
+ ch[i].ctp & _B ? "B" : "",
+ ch[i].ctp & _X ? "X" : "");
+
+ printf("<TD>&#%d;",ch[i].uni);
+ printf("<TD>&#%d;",ch[i].low);
+ printf("<TD>&#%d;",ch[i].upp);
+ printf("</TR>\n");
+ srt=ch[i].srt;
+ }
+ printf("</TABLE>\n");
+ printf("</PRE></BODY>\n");
+ printf("</HTML>\n");
+}
+
+
+int main(int argc, char **argv) {
+ const char *the_set = MYSQL_CHARSET;
+ int argcnt = 1;
+
+ my_init();
+
+ if (argc > argcnt && argv[argcnt][0] == '-' && argv[argcnt][1] == '#')
+ DBUG_PUSH(argv[argcnt++]+2);
+
+ if (argc > argcnt)
+ the_set = argv[argcnt++];
+
+ if (argc > argcnt)
+ charsets_dir = argv[argcnt++];
+
+ if (set_default_charset_by_name(the_set, MYF(MY_WME)))
+ return 1;
+
+ print_cs(default_charset_info);
+
+ return 0;
+}
diff --git a/mysys/default.c b/mysys/default.c
index c354e1744bc..06557f73d06 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -249,7 +249,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
{
line++;
/* Ignore comment and empty lines */
- for (ptr=buff ; isspace(*ptr) ; ptr++ ) ;
+ for (ptr=buff ; my_isspace(system_charset_info,*ptr) ; ptr++ ) ;
if (*ptr == '#' || *ptr == ';' || !*ptr)
continue;
if (*ptr == '[') /* Group name */
@@ -262,7 +262,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name,line);
goto err;
}
- for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
+ for ( ; my_isspace(system_charset_info,end[-1]) ; end--) ;/* Remove end space */
end[0]=0;
read_values=find_type(ptr,group,3) > 0;
continue;
@@ -278,7 +278,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
continue;
if (!(end=value=strchr(ptr,'=')))
end=strend(ptr); /* Option without argument */
- for ( ; isspace(end[-1]) ; end--) ;
+ for ( ; my_isspace(system_charset_info,end[-1]) ; end--) ;
if (!value)
{
if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
@@ -291,9 +291,9 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
{
/* Remove pre- and end space */
char *value_end;
- for (value++ ; isspace(*value); value++) ;
+ for (value++ ; my_isspace(system_charset_info,*value); value++) ;
value_end=strend(value);
- for ( ; isspace(value_end[-1]) ; value_end--) ;
+ for ( ; my_isspace(system_charset_info,value_end[-1]) ; value_end--) ;
if (value_end < value) /* Empty string */
value_end=value;
if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
diff --git a/mysys/hash.c b/mysys/hash.c
index 3afd31a079b..7707e7019c9 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -31,14 +31,15 @@
static uint hash_mask(uint hashnr,uint buffmax,uint maxlength);
static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink);
-static uint calc_hashnr(const byte *key,uint length);
-static uint calc_hashnr_caseup(const byte *key,uint length);
+static uint calc_hashnr(CHARSET_INFO *cs,const byte *key,uint length);
static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length);
-my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length,
- hash_get_key get_key,
- void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
+my_bool
+_hash_init(HASH *hash,CHARSET_INFO *charset,
+ uint size,uint key_offset,uint key_length,
+ hash_get_key get_key,
+ void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
{
DBUG_ENTER("hash_init");
DBUG_PRINT("enter",("hash: %lx size: %d",hash,size));
@@ -56,8 +57,9 @@ my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length,
hash->get_key=get_key;
hash->free=free_element;
hash->flags=flags;
+ hash->charset=charset;
if (flags & HASH_CASE_INSENSITIVE)
- hash->calc_hashnr=calc_hashnr_caseup;
+ hash->calc_hashnr=charset->hash_caseup;
else
hash->calc_hashnr=calc_hashnr;
DBUG_RETURN(0);
@@ -109,14 +111,16 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax,
{
uint length;
byte *key= (byte*) hash_key(hash,pos->data,&length,0);
- return hash_mask((*hash->calc_hashnr)(key,length),buffmax,maxlength);
+ return hash_mask((*hash->calc_hashnr)(hash->charset,key,length),
+ buffmax,maxlength);
}
#ifndef NEW_HASH_FUNCTION
/* Calc hashvalue for a key */
-static uint calc_hashnr(const byte *key,uint length)
+static uint calc_hashnr(CHARSET_INFO *cs __attribute__((unused)),
+ const byte *key,uint length)
{
register uint nr=1, nr2=4;
while (length--)
@@ -127,19 +131,6 @@ static uint calc_hashnr(const byte *key,uint length)
return((uint) nr);
}
- /* Calc hashvalue for a key, case indepenently */
-
-static uint calc_hashnr_caseup(const byte *key,uint length)
-{
- register uint nr=1, nr2=4;
- while (length--)
- {
- nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8);
- nr2+=3;
- }
- return((uint) nr);
-}
-
#else
/*
@@ -155,7 +146,7 @@ static uint calc_hashnr_caseup(const byte *key,uint length)
* This works well on both numbers and strings.
*/
-uint calc_hashnr(const byte *key, uint len)
+uint calc_hashnr(CHARSET_INFO *cs, const byte *key, uint len)
{
const byte *end=key+len;
uint hash;
@@ -167,18 +158,6 @@ uint calc_hashnr(const byte *key, uint len)
return (hash);
}
-uint calc_hashnr_caseup(const byte *key, uint len)
-{
- const byte *end=key+len;
- uint hash;
- for (hash = 0; key < end; key++)
- {
- hash *= 16777619;
- hash ^= (uint) (uchar) toupper(*key);
- }
- return (hash);
-}
-
#endif
@@ -189,7 +168,7 @@ unsigned int rec_hashnr(HASH *hash,const byte *record)
{
uint length;
byte *key= (byte*) hash_key(hash,record,&length,0);
- return (*hash->calc_hashnr)(key,length);
+ return (*hash->calc_hashnr)(hash->charset,key,length);
}
@@ -205,7 +184,7 @@ gptr hash_search(HASH *hash,const byte *key,uint length)
flag=1;
if (hash->records)
{
- idx=hash_mask((*hash->calc_hashnr)(key,length ? length :
+ idx=hash_mask((*hash->calc_hashnr)(hash->charset,key,length ? length :
hash->key_length),
hash->blength,hash->records);
do
@@ -278,7 +257,7 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length)
byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1);
return (length && length != rec_keylength) ||
(hash->flags & HASH_CASE_INSENSITIVE ?
- my_casecmp(rec_key,key,rec_keylength) :
+ my_strncasecmp(hash->charset, rec_key,key,rec_keylength) :
memcmp(rec_key,key,rec_keylength));
}
@@ -518,7 +497,7 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length)
/* Search after record with key */
- idx=hash_mask((*hash->calc_hashnr)(old_key,(old_key_length ?
+ idx=hash_mask((*hash->calc_hashnr)(hash->charset, old_key,(old_key_length ?
old_key_length :
hash->key_length)),
blength,records);
diff --git a/mysys/list.c b/mysys/list.c
index ac9e1b979a0..17028e8e183 100644
--- a/mysys/list.c
+++ b/mysys/list.c
@@ -55,7 +55,7 @@ LIST *list_delete(LIST *root, LIST *element)
}
-void list_free(LIST *root, pbool free_data)
+void list_free(LIST *root, uint free_data)
{
LIST *next;
while (root)
diff --git a/mysys/mf_casecnv.c b/mysys/mf_casecnv.c
deleted file mode 100644
index c037cbd0f16..00000000000
--- a/mysys/mf_casecnv.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* Copyright (C) 2000 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU 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 */
-
-/*
- Functions to convert to lover_case and to upper_case in scandinavia.
-
- case_sort converts a character string to a representaion that can
- be compared by strcmp to find with is alfabetical bigger.
- (lower- and uppercase letters is compared as the same)
-*/
-
-#include "mysys_priv.h"
-#include <m_ctype.h>
-#ifndef SCO
-#include <m_string.h>
-#endif
-
-/*
- Upcase string
-
- SYNOPSIS
- str IN/OUT String to upcase
-
- RETURN VALUE
- none
- DESCRIPTION
- Function changes input parameter so all chars it consist from
- are replaced with matching one in upper case.
- String should be writable with exception read-only empty string
- constant is handled correctly.
-*/
-
-
-void caseup_str(my_string str)
-{
-#ifdef USE_MB
- if (use_mb(default_charset_info))
- {
- register uint32 l;
- register char *end=str+strlen(str);
- while (*str)
- {
- if ((l=my_ismbchar(default_charset_info, str,end))) str+=l;
- else *str=toupper(*str),++str;
- }
- }
- else
-#endif
- while (*str!=0) /* iterate till the end of string */
- {
- *str= toupper(*str);
- str++;
- }
-} /* caseup_str */
-
-
-/*
- Downcase string
-
- SYNOPSIS
- str IN/OUT String to downcase
-
- RETURN VALUE
- none
- DESCRIPTION
- Function changes input parameter so all chars it consist from
- are replaced with matching one in lower case.
- String should be writable with exception read-only empty string
- constant is handled correctly.
-*/
-
-
-void casedn_str(my_string str)
-{
-#ifdef USE_MB
- if (use_mb(default_charset_info))
- {
- register uint32 l;
- register char *end=str+strlen(str);
- while (*str)
- {
- if ((l=my_ismbchar(default_charset_info, str,end))) str+=l;
- else *str=tolower(*str),++str;
- }
- }
- else
-#endif
- while (*str!=0) /* iterate till the end of string */
- {
- *str= tolower(*str);
- str++;
- }
-} /* casedn_str */
-
-
- /* to uppercase */
-
-void caseup(my_string str, uint length)
-{
-#ifdef USE_MB
- if (use_mb(default_charset_info))
- {
- register uint32 l;
- register char *end=str+length;
- while (str<end)
- {
- if ((l=my_ismbchar(default_charset_info, str,end))) str+=l;
- else *str=toupper(*str),++str;
- }
- }
- else
-#endif
- for ( ; length>0 ; length--, str++)
- *str= toupper(*str);
-} /* caseup */
-
- /* to lowercase */
-
-void casedn(my_string str, uint length)
-{
-#ifdef USE_MB
- if (use_mb(default_charset_info))
- {
- register uint32 l;
- register char *end=str+length;
- while (str<end)
- {
- if ((l=my_ismbchar(default_charset_info, str,end))) str+=l;
- else *str=tolower(*str),++str;
- }
- }
- else
-#endif
- for ( ; length>0 ; length--, str++)
- *str= tolower(*str);
-} /* casedn */
-
- /* to sort-string that can be compared to get text in order */
-
-void case_sort(my_string str, uint length)
-{
- for ( ; length>0 ; length--, str++)
- *str= (char) my_sort_order[(uchar) *str];
-} /* case_sort */
-
- /* find string in another with no case_sensivity */
-
-/* ToDo: This function should be modified to support multibyte charset.
- However it is not used untill 3.23.5.
- Wei He (hewei@mail.ied.ac.cn)
-*/
-
-my_string my_strcasestr(const char *str, const char *search)
-{
- uchar *i,*j,*pos;
-
- pos=(uchar*) str;
-skipp:
- while (*pos != '\0')
- {
- if (toupper((uchar) *pos++) == toupper((uchar) *search))
- {
- i=(uchar*) pos; j=(uchar*) search+1;
- while (*j)
- if (toupper(*i++) != toupper(*j++)) goto skipp;
- return ((char*) pos-1);
- }
- }
- return ((my_string) 0);
-} /* strcstr */
-
-
- /* compare strings without regarding to case */
-
-int my_strcasecmp(const char *s, const char *t)
-{
-#ifdef USE_MB
- if (use_mb(default_charset_info))
- {
- register uint32 l;
- register const char *end=s+strlen(s);
- while (s<end)
- {
- if ((l=my_ismbchar(default_charset_info, s,end)))
- {
- while (l--)
- if (*s++ != *t++) return 1;
- }
- else if (my_ismbhead(default_charset_info, *t)) return 1;
- else if (toupper((uchar) *s++) != toupper((uchar) *t++)) return 1;
- }
- return *t;
- }
- else
-#endif
- {
- while (toupper((uchar) *s) == toupper((uchar) *t++))
- if (!*s++) return 0;
- return ((int) toupper((uchar) s[0]) - (int) toupper((uchar) t[-1]));
- }
-}
-
-
-int my_casecmp(const char *s, const char *t, uint len)
-{
-#ifdef USE_MB
- if (use_mb(default_charset_info))
- {
- register uint32 l;
- register const char *end=s+len;
- while (s<end)
- {
- if ((l=my_ismbchar(default_charset_info, s,end)))
- {
- while (l--)
- if (*s++ != *t++) return 1;
- }
- else if (my_ismbhead(default_charset_info, *t)) return 1;
- else if (toupper((uchar) *s++) != toupper((uchar) *t++)) return 1;
- }
- return 0;
- }
- else
-#endif
- {
- while (len-- != 0 && toupper(*s++) == toupper(*t++)) ;
- return (int) len+1;
- }
-}
-
-
-int my_strsortcmp(const char *s, const char *t)
-{
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- return my_strcoll(default_charset_info, (uchar *)s, (uchar *)t);
- else
-#endif
- {
- while (my_sort_order[(uchar) *s] == my_sort_order[(uchar) *t++])
- if (!*s++) return 0;
- return ((int) my_sort_order[(uchar) s[0]] -
- (int) my_sort_order[(uchar) t[-1]]);
- }
-}
-
-int my_sortcmp(const char *s, const char *t, uint len)
-{
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- return my_strnncoll(default_charset_info,
- (uchar *)s, len, (uchar *)t, len);
- else
-#endif
- {
- while (len--)
- {
- if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++])
- return ((int) my_sort_order[(uchar) s[-1]] -
- (int) my_sort_order[(uchar) t[-1]]);
- }
- return 0;
- }
-}
-
-int my_sortncmp(const char *s, uint s_len, const char *t, uint t_len)
-{
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- return my_strnncoll(default_charset_info,
- (uchar *)s, s_len, (uchar *)t, t_len);
- else
-#endif
- {
- uint len= min(s_len,t_len);
- while (len--)
- {
- if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++])
- return ((int) my_sort_order[(uchar) s[-1]] -
- (int) my_sort_order[(uchar) t[-1]]);
- }
- return (int) (s_len - t_len);
- }
-}
diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c
index 6523abcdb12..320917c8f3e 100644
--- a/mysys/mf_dirname.c
+++ b/mysys/mf_dirname.c
@@ -108,11 +108,5 @@ char *convert_dirname(char *to, const char *from, const char *from_end)
*to++=FN_LIBCHAR;
*to=0;
}
-#ifdef FN_UPPER_CASE
- caseup_str(to_org);
-#endif
-#ifdef FN_LOWER_CASE
- casedn_str(to_org);
-#endif
return to; /* Pointer to end of dir */
} /* convert_dirname */
diff --git a/mysys/mf_format.c b/mysys/mf_format.c
index ab1904da162..e68f7df9d83 100644
--- a/mysys/mf_format.c
+++ b/mysys/mf_format.c
@@ -91,12 +91,6 @@ my_string fn_format(my_string to, const char *name, const char *dir,
name=buff;
}
pos=strmake(strmov(to,dev),name,length);
-#ifdef FN_UPPER_CASE
- caseup_str(to);
-#endif
-#ifdef FN_LOWER_CASE
- casedn_str(to);
-#endif
(void) strmov(pos,ext); /* Don't convert extension */
}
/*
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 344b7ac2251..8a7dfc7be09 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -267,7 +267,7 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
/* Found one '%' */
}
/* Skipp if max size is used (to be compatible with printf) */
- while (isdigit(*fmt) || *fmt == '.' || *fmt == '-')
+ while (my_isdigit(system_charset_info, *fmt) || *fmt == '.' || *fmt == '-')
fmt++;
if (*fmt == 's') /* String parameter */
{
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 6a037f13f05..9d45ec8d539 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -15,855 +15,1856 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
- This functions is handle keyblock cacheing for NISAM, MISAM and PISAM
- databases.
- One cache can handle many files. Every different blocksize has it owns
- set of buffers that are allocated from block_mem.
+ These functions are to handle keyblock cacheing
+ for NISAM, MISAM and PISAM databases.
+ One cache can handle many files.
+ It must contain buffers of the same blocksize.
init_key_cache() should be used to init cache handler.
- */
+*/
#include "mysys_priv.h"
#include "my_static.h"
#include <m_string.h>
#include <errno.h>
+#include <assert.h>
+#include <stdarg.h>
+
+/*
+ Some compilation flags have been added specifically for this module
+ to control the following:
+ - not to let a thread to yield the control when reading directly
+ from key cache, which might improve performance in many cases;
+ to enable this add:
+ #define SERIALIZED_READ_FROM_CACHE
+ - to set an upper bound for number of threads simultaneously
+ using the key cache; this setting helps to determine an optimal
+ size for hash table and improve performance when the number of
+ blocks in the key cache much less than the number of threads
+ accessing it;
+ to set this number equal to <N> add
+ #define MAX_THREADS <N>
+ - to substitute calls of pthread_cond_wait for calls of
+ pthread_cond_timedwait (wait with timeout set up);
+ this setting should be used only when you want to trap a deadlock
+ situation, which theoretically should not happen;
+ to set timeout equal to <T> seconds add
+ #define KEYCACHE_TIMEOUT <T>
+ - to enable the module traps and to send debug information from
+ key cache module to a special debug log add:
+ #define KEYCACHE_DEBUG
+ the name of this debug log file <LOG NAME> can be set through:
+ #define KEYCACHE_DEBUG_LOG <LOG NAME>
+ if the name is not defined, it's set by default;
+ if the KEYCACHE_DEBUG flag is not set up and we are in a debug
+ mode, i.e. when ! defined(DBUG_OFF), the debug information from the
+ module is sent to the regular debug log.
+
+ Example of the settings:
+ #define SERIALIZED_READ_FROM_CACHE
+ #define MAX_THREADS 100
+ #define KEYCACHE_TIMEOUT 1
+ #define KEYCACHE_DEBUG
+ #define KEYCACHE_DEBUG_LOG "my_key_cache_debug.log"
+*/
#if defined(MSDOS) && !defined(M_IC80386)
- /* We nead much memory */
+/* we nead much memory */
#undef my_malloc_lock
#undef my_free_lock
-#define my_malloc_lock(A,B) halloc((long) (A/IO_SIZE),IO_SIZE)
-#define my_free_lock(A,B) hfree(A)
-#endif
+#define my_malloc_lock(A,B) halloc((long) (A/IO_SIZE),IO_SIZE)
+#define my_free_lock(A,B) hfree(A)
+#endif /* defined(MSDOS) && !defined(M_IC80386) */
+
+#define STRUCT_PTR(TYPE, MEMBER, a) \
+ (TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER))
+
+/* types of condition variables */
+#define COND_FOR_REQUESTED 0
+#define COND_FOR_SAVED 1
+#define COND_FOR_READERS 2
+
+typedef pthread_cond_t KEYCACHE_CONDVAR;
+typedef struct st_keycache_wqueue
+{ /* info about requests in a waiting queue */
+ struct st_my_thread_var *last_thread; /* circular list of waiting threads */
+} KEYCACHE_WQUEUE;
+
+typedef struct st_keycache_page
+{ /* descriptor of the page in the key cache block buffer */
+ int file; /* file to which the page belongs to */
+ my_off_t filepos; /* position of the page in the file */
+} KEYCACHE_PAGE;
+
+typedef struct st_hash_link
+{ /* element in the chain of a hash table bucket */
+ struct st_hash_link *next, **prev; /* to connect links in the same bucket */
+ struct st_block_link *block; /* reference to the block for the page: */
+ File file; /* from such a file */
+ my_off_t diskpos; /* with such an offset */
+ uint requests; /* number of requests for the page */
+} HASH_LINK; /* offset is always alighed for key_cache_block_size */
+
+/* simple states of a block */
+#define BLOCK_ERROR 1 /* an error occured when performing disk i/o */
+#define BLOCK_READ 2 /* the is page in the block buffer */
+#define BLOCK_IN_SWITCH 4 /* block is preparing to read new page */
+#define BLOCK_REASSIGNED 8 /* block does not accept requests for old page */
+#define BLOCK_IN_FLUSH 16 /* block is in flush operation */
+#define BLOCK_CHANGED 32 /* block buffer contains a dirty page */
+
+/* page status, returned by find_key_block */
+#define PAGE_READ 0
+#define PAGE_TO_BE_READ 1
+#define PAGE_WAIT_TO_BE_READ 2
+
+typedef struct st_block_link
+{ /* key cache block */
+ struct st_block_link
+ *next_used, **prev_used; /* to connect links in the LRU chain (ring) */
+ struct st_block_link
+ *next_changed, **prev_changed; /* for lists of file dirty/clean blocks */
+ struct st_hash_link *hash_link; /* backward ptr to referring hash_link */
+ KEYCACHE_WQUEUE wqueue[2]; /* queues on waiting requests for new/old pages */
+ uint requests; /* number of requests for the block */
+ byte *buffer; /* buffer for the block page */
+ uint offset; /* beginning of modified data in the buffer */
+ uint length; /* end of data in the buffer */
+ uint status; /* state of the block */
+ KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event */
+} BLOCK_LINK;
-/* size of map to be used to find changed files */
+static int flush_all_key_blocks();
+static void test_key_cache(const char *where, my_bool lock);
-#define CHANGED_BLOCKS_HASH 128 /* Must be power of 2 */
-#define CHANGED_BLOCKS_MASK (CHANGED_BLOCKS_HASH-1)
-#define FLUSH_CACHE 2000 /* Sort this many blocks at once */
+uint key_cache_block_size= /* size of the page buffer of a cache block */
+ DEFAULT_KEYCACHE_BLOCK_SIZE;
+static uint key_cache_shift;
+
+#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
+#define FLUSH_CACHE 2000 /* sort this many blocks at once */
+
+static KEYCACHE_WQUEUE
+ waiting_for_hash_link; /* queue of requests waiting for a free hash link */
+static KEYCACHE_WQUEUE
+ waiting_for_block; /* queue of requests waiting for a free block */
+
+static HASH_LINK **_my_hash_root; /* arr. of entries into hash table buckets */
+static uint _my_hash_entries; /* max number of entries in the hash table */
+static HASH_LINK *_my_hash_link_root; /* memory for hash table links */
+static int _my_hash_links; /* max number of hash links */
+static int _my_hash_links_used; /* number of hash links currently used */
+static HASH_LINK *_my_free_hash_list; /* list of free hash links */
+static BLOCK_LINK *_my_block_root; /* memory for block links */
+static int _my_disk_blocks; /* max number of blocks in the cache */
+static byte HUGE_PTR *_my_block_mem; /* memory for block buffers */
+static BLOCK_LINK *_my_used_last; /* ptr to the last block of the LRU chain */
+ulong _my_blocks_used, /* number of currently used blocks */
+ _my_blocks_changed; /* number of currently dirty blocks */
+#if defined(KEYCACHE_DEBUG)
+static
+ulong _my_blocks_available; /* number of blocks available in the LRU chain */
+#endif /* defined(KEYCACHE_DEBUG) */
+ulong _my_cache_w_requests,_my_cache_write, /* counters */
+ _my_cache_r_requests,_my_cache_read; /* for statistics */
+static BLOCK_LINK
+ *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash table for file dirty blocks */
+static BLOCK_LINK
+ *file_blocks[CHANGED_BLOCKS_HASH]; /* hash table for other file blocks */
+ /* that are not free */
+#ifndef DBUG_OFF
+static my_bool _my_printed;
+#endif
-typedef struct sec_link {
- struct sec_link *next_hash,**prev_hash;/* Blocks linked acc. to hash-value */
- struct sec_link *next_used,*prev_used;
- struct sec_link *next_changed,**prev_changed;
- File file;
- my_off_t diskpos;
- byte *buffer;
- my_bool changed;
-} SEC_LINK;
+#define KEYCACHE_HASH(f, pos) \
+ (((ulong) ((pos) >> key_cache_shift)+(ulong) (f)) & (_my_hash_entries-1))
+#define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
+#define DEFAULT_KEYCACHE_DEBUG_LOG "keycache_debug.log"
-static SEC_LINK *find_key_block(int file,my_off_t filepos,int *error);
-static int flush_all_key_blocks();
+#if defined(KEYCACHE_DEBUG) && ! defined(KEYCACHE_DEBUG_LOG)
+#define KEYCACHE_DEBUG_LOG DEFAULT_KEYCACHE_DEBUG_LOG
+#endif
- /* static variables in this file */
-static SEC_LINK *_my_block_root,**_my_hash_root,
- *_my_used_first,*_my_used_last;
-static int _my_disk_blocks;
-static uint _my_disk_blocks_used, _my_hash_blocks;
-static uint key_cache_shift;
-ulong _my_blocks_used,_my_blocks_changed;
-ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests,
- _my_cache_read;
-uint key_cache_block_size=DEFAULT_KEYCACHE_BLOCK_SIZE;
-static byte HUGE_PTR *_my_block_mem;
-static SEC_LINK *changed_blocks[CHANGED_BLOCKS_HASH];
-static SEC_LINK *file_blocks[CHANGED_BLOCKS_HASH];
-#ifndef DBUG_OFF
-static my_bool _my_printed;
+#if defined(KEYCACHE_DEBUG_LOG)
+static FILE *keycache_debug_log=NULL;
+static void keycache_debug_print _VARARGS((const char *fmt,...));
+#define KEYCACHE_DEBUG_OPEN \
+ keycache_debug_log=fopen(KEYCACHE_DEBUG_LOG, "w")
+
+#define KEYCACHE_DEBUG_CLOSE \
+ if (keycache_debug_log) fclose(keycache_debug_log)
+#else
+#define KEYCACHE_DEBUG_OPEN
+#define KEYCACHE_DEBUG_CLOSE
+#endif /* defined(KEYCACHE_DEBUG_LOG) */
+
+#if defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG)
+#define KEYCACHE_DBUG_PRINT(l, m) \
+ { if (keycache_debug_log) fprintf(keycache_debug_log, "%s: ", l); \
+ keycache_debug_print m; }
+
+#define KEYCACHE_DBUG_ASSERT(a) \
+ { if (! (a) && keycache_debug_log) fclose(keycache_debug_log); \
+ assert(a); }
+#else
+#define KEYCACHE_DBUG_PRINT(l, m) DBUG_PRINT(l, m)
+#define KEYCACHE_DBUG_ASSERT(a) DBUG_ASSERT(a)
+#endif /* defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG) */
+
+#if defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF)
+static long keycache_thread_id;
+#define KEYCACHE_THREAD_TRACE(l) \
+ KEYCACHE_DBUG_PRINT(l,("|thread %ld",keycache_thread_id))
+
+#define KEYCACHE_THREAD_TRACE_BEGIN(l) \
+ { struct st_my_thread_var *thread_var =my_thread_var; \
+ keycache_thread_id=my_thread_var->id; \
+ KEYCACHE_DBUG_PRINT(l,("[thread %ld",keycache_thread_id)) }
+
+#define KEYCACHE_THREAD_TRACE_END(l) \
+ KEYCACHE_DBUG_PRINT(l,("]thread %ld",keycache_thread_id))
+#else
+#define KEYCACHE_THREAD_TRACE_BEGIN(l)
+#define KEYCACHE_THREAD_TRACE_END(l)
+#define KEYCACHE_THREAD_TRACE(l)
+#endif /* defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF) */
+
+#define BLOCK_NUMBER(b) \
+ ((uint) (((char*)(b) - (char *) _my_block_root) / sizeof(BLOCK_LINK)))
+#define HASH_LINK_NUMBER(h) \
+ ((uint) (((char*)(h) - (char *) _my_hash_link_root) / sizeof(HASH_LINK)))
+
+#if (defined(KEYCACHE_TIMEOUT) && !defined(__WIN__)) || defined(KEYCACHE_DEBUG)
+static int keycache_pthread_cond_wait(pthread_cond_t *cond,
+ pthread_mutex_t *mutex);
+#else
+#define keycache_pthread_cond_wait pthread_cond_wait
#endif
+#if defined(KEYCACHE_DEBUG)
+static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex);
+static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex);
+static int keycache_pthread_cond_signal(pthread_cond_t *cond);
+static int keycache_pthread_cond_broadcast(pthread_cond_t *cond);
+#else
+#define keycache_pthread_mutex_lock pthread_mutex_lock
+#define keycache_pthread_mutex_unlock pthread_mutex_unlock
+#define keycache_pthread_cond_signal pthread_cond_signal
+#define keycache_pthread_cond_broadcast pthread_cond_broadcast
+#endif /* defined(KEYCACHE_DEBUG) */
+
+static uint next_power(uint value)
+{
+ uint old_value=1;
+ while (value)
+ {
+ old_value=value;
+ value&= value-1;
+ }
+ return (old_value << 1);
+}
- /* Init of disk_buffert */
- /* Returns blocks in use */
- /* ARGSUSED */
+/*
+ Initialize the key cache,
+ return number of blocks in it
+*/
int init_key_cache(ulong use_mem)
{
- uint blocks,length;
+ uint blocks, hash_links, length;
+ int error;
+
DBUG_ENTER("init_key_cache");
-
+
+ KEYCACHE_DEBUG_OPEN;
if (key_cache_inited && _my_disk_blocks > 0)
{
- DBUG_PRINT("warning",("key cache already in use")); /* purecov: inspected */
- DBUG_RETURN(0); /* purecov: inspected */
+ DBUG_PRINT("warning",("key cache already in use"));
+ DBUG_RETURN(0);
}
if (! key_cache_inited)
{
key_cache_inited=TRUE;
_my_disk_blocks= -1;
key_cache_shift=my_bit_log2(key_cache_block_size);
- DBUG_PRINT("info",("key_cache_block_size: %u key_cache_shift: %u",
- key_cache_block_size, key_cache_shift));
+ DBUG_PRINT("info",("key_cache_block_size: %u",
+ key_cache_block_size));
#ifndef DBUG_OFF
_my_printed=0;
#endif
}
-
- blocks= (uint) (use_mem/(sizeof(SEC_LINK)+sizeof(SEC_LINK*)*5/4+
- key_cache_block_size));
- /* No use to have very few blocks */
+
+ _my_cache_w_requests=_my_cache_r_requests=_my_cache_read=_my_cache_write=0;
+
+ _my_block_mem=NULL;
+ _my_block_root=NULL;
+
+ blocks= (uint) (use_mem/(sizeof(BLOCK_LINK)+2*sizeof(HASH_LINK)+
+ sizeof(HASH_LINK*)*5/4+key_cache_block_size));
+ /* It doesn't make sense to have too few blocks (less than 8) */
if (blocks >= 8 && _my_disk_blocks < 0)
{
for (;;)
{
- /* Set my_hash_blocks to the next bigger 2 power */
- _my_hash_blocks=(uint) 1 << (my_bit_log2(blocks*5/4)+1);
- while ((length=(uint) blocks*sizeof(SEC_LINK)+
- sizeof(SEC_LINK*)*_my_hash_blocks)+
- ((ulong) blocks << key_cache_shift) >
- use_mem)
- blocks--;
- if ((_my_block_mem=my_malloc_lock((ulong) blocks << key_cache_shift,
- MYF(0))))
+ /* Set _my_hash_entries to the next bigger 2 power */
+ if ((_my_hash_entries=next_power(blocks)) < blocks*5/4)
+ _my_hash_entries<<=1;
+ hash_links=2*blocks;
+#if defined(MAX_THREADS)
+ if (hash_links < MAX_THREADS + blocks - 1)
+ hash_links=MAX_THREADS + blocks - 1;
+#endif
+ while ((length=blocks*sizeof(BLOCK_LINK)+hash_links*sizeof(HASH_LINK)+
+ sizeof(HASH_LINK*)*_my_hash_entries)+
+ ((ulong) blocks << key_cache_shift) >
+ use_mem)
+ blocks--;
+ /* Allocate memory for cache page buffers */
+ if ((_my_block_mem=my_malloc_lock((ulong) blocks*key_cache_block_size,
+ MYF(0))))
+ {
+ /*
+ Allocate memory for blocks, hash_links and hash entries;
+ For each block 2 hash links are allocated
+ */
+ if ((_my_block_root=(BLOCK_LINK*) my_malloc((uint) length,MYF(0))))
+ break;
+ my_free_lock(_my_block_mem,MYF(0));
+ }
+ if (blocks < 8)
{
- if ((_my_block_root=(SEC_LINK*) my_malloc((uint) length,MYF(0))) != 0)
- break;
- my_free_lock(_my_block_mem,MYF(0));
+ my_errno=ENOMEM;
+ goto err;
}
- if (blocks < 8)
- goto err;
blocks=blocks/4*3;
}
_my_disk_blocks=(int) blocks;
- _my_hash_root= (SEC_LINK**) (_my_block_root+blocks);
- bzero((byte*) _my_hash_root,_my_hash_blocks*sizeof(SEC_LINK*));
- _my_used_first=_my_used_last=0;
- _my_blocks_used=_my_disk_blocks_used=_my_blocks_changed=0;
- _my_cache_w_requests=_my_cache_r_requests=_my_cache_read=_my_cache_write=0;
- DBUG_PRINT("exit",("disk_blocks: %d block_root: %lx _my_hash_blocks: %d hash_root: %lx",
- _my_disk_blocks,_my_block_root,_my_hash_blocks,
- _my_hash_root));
+ _my_hash_links=hash_links;
+ _my_hash_root=(HASH_LINK**) (_my_block_root+blocks);
+ _my_hash_link_root=(HASH_LINK*) (_my_hash_root+_my_hash_entries);
+ bzero((byte*) _my_block_root,_my_disk_blocks*sizeof(BLOCK_LINK));
+ bzero((byte*) _my_hash_root,_my_hash_entries*sizeof(HASH_LINK*));
+ bzero((byte*) _my_hash_link_root,_my_hash_links*sizeof(HASH_LINK));
+ _my_hash_links_used=0;
+ _my_free_hash_list=NULL;
+ _my_blocks_used=_my_blocks_changed=0;
+#if defined(KEYCACHE_DEBUG)
+ _my_blocks_available=0;
+#endif
+ /* The LRU chain is empty after initialization */
+ _my_used_last=NULL;
+
+ waiting_for_hash_link.last_thread=NULL;
+ waiting_for_block.last_thread=NULL;
+ DBUG_PRINT("exit",
+ ("disk_blocks: %d block_root: %lx hash_entries: %d hash_root: %lx \
+ hash_links: %d hash_link_root %lx",
+ _my_disk_blocks,_my_block_root,_my_hash_entries,_my_hash_root,
+ _my_hash_links,_my_hash_link_root));
}
bzero((gptr) changed_blocks,sizeof(changed_blocks[0])*CHANGED_BLOCKS_HASH);
bzero((gptr) file_blocks,sizeof(file_blocks[0])*CHANGED_BLOCKS_HASH);
+
DBUG_RETURN((int) blocks);
-
+
err:
- my_errno=ENOMEM;
+ error=my_errno;
+ if (_my_block_mem)
+ my_free_lock((gptr) _my_block_mem,MYF(0));
+ if (_my_block_mem)
+ my_free((gptr) _my_block_root,MYF(0));
+ my_errno=error;
DBUG_RETURN(0);
-} /* init_key_cache */
+}
/*
- Resize the key cache
-
- SYNOPSIS
- resize_key_cache()
- use_mem Bytes to use for new key cache
-
- RETURN VALUES
- 0 Error
- # number of blocks in key cache
+ Resize the key cache
*/
-
-
int resize_key_cache(ulong use_mem)
{
- int block;
- pthread_mutex_lock(&THR_LOCK_keycache);
+ int blocks;
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
if (flush_all_key_blocks())
{
- /* TODO: If this happens, we should write a warning in the log file ! */
- pthread_mutex_unlock(&THR_LOCK_keycache);
+ /* TODO: if this happens, we should write a warning in the log file ! */
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
return 0;
}
end_key_cache();
- /* The following will work even if memory is 0 */
- block=init_key_cache(use_mem);
- pthread_mutex_unlock(&THR_LOCK_keycache);
- return block;
+ /* the following will work even if memory is 0 */
+ blocks=init_key_cache(use_mem);
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+ return blocks;
}
- /* Remove key_cache from memory */
-
+/*
+ Remove key_cache from memory
+*/
void end_key_cache(void)
{
DBUG_ENTER("end_key_cache");
- if (! _my_blocks_changed)
+ if (_my_disk_blocks > 0)
{
- if (_my_disk_blocks > 0)
+ if (_my_block_mem)
{
my_free_lock((gptr) _my_block_mem,MYF(0));
my_free((gptr) _my_block_root,MYF(0));
- _my_disk_blocks= -1;
}
+ _my_disk_blocks= -1;
}
+ KEYCACHE_DEBUG_CLOSE;
key_cache_inited=0;
- _my_hash_blocks=_my_blocks_used=0;
DBUG_PRINT("status",
- ("used: %d changed: %d w_requests: %ld writes: %ld r_requests: %ld reads: %ld",
- _my_blocks_used,_my_blocks_changed,_my_cache_w_requests,
- _my_cache_write,_my_cache_r_requests,_my_cache_read));
+ ("used: %d changed: %d w_requests: %ld \
+ writes: %ld r_requests: %ld reads: %ld",
+ _my_blocks_used,_my_blocks_changed,_my_cache_w_requests,
+ _my_cache_write,_my_cache_r_requests,_my_cache_read));
DBUG_VOID_RETURN;
} /* end_key_cache */
-static inline void link_into_file_blocks(SEC_LINK *next, int file)
+/*
+ Link a thread into double-linked queue of waiting threads
+*/
+static inline void link_into_queue(KEYCACHE_WQUEUE *wqueue,
+ struct st_my_thread_var *thread)
+{
+ struct st_my_thread_var *last;
+ if (! (last=wqueue->last_thread))
+ { /* Queue is empty */
+ thread->next=thread;
+ thread->prev=&thread->next;
+ }
+ else
+ {
+ thread->prev=last->next->prev;
+ last->next->prev=&thread->next;
+ thread->next=last->next;
+ last->next=thread;
+ }
+ wqueue->last_thread=thread;
+}
+
+/*
+ Unlink a thread from double-linked queue of waiting threads
+*/
+static inline void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
+ struct st_my_thread_var *thread)
+{
+ KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", thread->id));
+ if (thread->next == thread)
+ /* The queue contains only one member */
+ wqueue->last_thread=NULL;
+ else
+ {
+ thread->next->prev=thread->prev;
+ *thread->prev=thread->next;
+ if (wqueue->last_thread == thread)
+ wqueue->last_thread=STRUCT_PTR(struct st_my_thread_var, next,
+ thread->prev);
+ }
+ thread->next=NULL;
+}
+
+
+/*
+ Add a thread to single-linked queue of waiting threads
+*/
+static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
+ struct st_my_thread_var *thread)
+{
+ struct st_my_thread_var *last;
+ if (! (last=wqueue->last_thread))
+ thread->next=thread;
+ else
+ {
+ thread->next=last->next;
+ last->next=thread;
+ }
+ wqueue->last_thread=thread;
+}
+
+
+/*
+ Remove all threads from queue signaling them to proceed
+*/
+static inline void release_queue(KEYCACHE_WQUEUE *wqueue)
+{
+ struct st_my_thread_var *last=wqueue->last_thread;
+ struct st_my_thread_var *next=last->next;
+ struct st_my_thread_var *thread;
+ do
+ {
+ thread=next;
+ keycache_pthread_cond_signal(&thread->suspend);
+ KEYCACHE_DBUG_PRINT("release_queue: signal", ("thread %ld", thread->id));
+ next=thread->next;
+ thread->next=NULL;
+ }
+ while (thread != last);
+ wqueue->last_thread=NULL;
+}
+
+
+/*
+ Unlink a block from the chain of dirty/clean blocks
+*/
+static inline void unlink_changed(BLOCK_LINK *block)
{
- reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK];
- next->prev_changed= ptr;
- if ((next->next_changed= *ptr))
- (*ptr)->prev_changed= &next->next_changed;
- *ptr=next;
+ if (block->next_changed)
+ block->next_changed->prev_changed=block->prev_changed;
+ *block->prev_changed=block->next_changed;
}
-static inline void relink_into_file_blocks(SEC_LINK *next, int file)
+/*
+ Link a block into the chain of dirty/clean blocks
+*/
+static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
{
- reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK];
- if (next->next_changed)
- next->next_changed->prev_changed=next->prev_changed;
- *next->prev_changed=next->next_changed;
- next->prev_changed= ptr;
- if ((next->next_changed= *ptr))
- (*ptr)->prev_changed= &next->next_changed;
- *ptr=next;
+ block->prev_changed=phead;
+ if ((block->next_changed=*phead))
+ (*phead)->prev_changed= &block->next_changed;
+ *phead=block;
}
-static inline void link_changed_to_file(SEC_LINK *next,int file)
+
+/*
+ Unlink a block from the chain of dirty/clean blocks, if it's asked for,
+ and link it to the chain of clean blocks for the specified file
+*/
+static inline void link_to_file_list(BLOCK_LINK *block,int file,
+ my_bool unlink)
{
- reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK];
- if (next->next_changed)
- next->next_changed->prev_changed=next->prev_changed;
- *next->prev_changed=next->next_changed;
- next->prev_changed= ptr;
- if ((next->next_changed= *ptr))
- (*ptr)->prev_changed= &next->next_changed;
- *ptr=next;
- next->changed=0;
- _my_blocks_changed--;
+ if (unlink)
+ unlink_changed(block);
+ link_changed(block,&file_blocks[FILE_HASH(file)]);
+ if (block->status & BLOCK_CHANGED)
+ {
+ block->status&=~BLOCK_CHANGED;
+ _my_blocks_changed--;
+ }
}
-static inline void link_file_to_changed(SEC_LINK *next)
+
+/*
+ Unlink a block from the chain of clean blocks for the specified
+ file and link it to the chain of dirty blocks for this file
+*/
+static inline void link_to_changed_list(BLOCK_LINK *block)
{
- reg1 SEC_LINK **ptr= &changed_blocks[(uint) next->file & CHANGED_BLOCKS_MASK];
- if (next->next_changed)
- next->next_changed->prev_changed=next->prev_changed;
- *next->prev_changed=next->next_changed;
- next->prev_changed= ptr;
- if ((next->next_changed= *ptr))
- (*ptr)->prev_changed= &next->next_changed;
- *ptr=next;
- next->changed=1;
+ unlink_changed(block);
+ link_changed(block,&changed_blocks[FILE_HASH(block->hash_link->file)]);
+ block->status|=BLOCK_CHANGED;
_my_blocks_changed++;
}
-#if !defined(DBUG_OFF) && !defined(EXTRA_DEBUG)
-#define DBUG_OFF /* This should work */
+/*
+ Link a block to the LRU chain at the beginning or at the end
+*/
+static void link_block(BLOCK_LINK *block, my_bool at_end)
+{
+ KEYCACHE_DBUG_ASSERT(! (block->hash_link && block->hash_link->requests));
+ if (waiting_for_block.last_thread) {
+ /* Signal that in the LRU chain an available block has appeared */
+ struct st_my_thread_var *last_thread=waiting_for_block.last_thread;
+ struct st_my_thread_var *first_thread=last_thread->next;
+ struct st_my_thread_var *next_thread=first_thread;
+ HASH_LINK *hash_link= (HASH_LINK *) first_thread->opt_info;
+ struct st_my_thread_var *thread;
+ do
+ {
+ thread=next_thread;
+ next_thread=thread->next;
+ /*
+ We notify about the event all threads that ask
+ for the same page as the first thread in the queue
+ */
+ if ((HASH_LINK *) thread->opt_info == hash_link)
+ {
+ keycache_pthread_cond_signal(&thread->suspend);
+ unlink_from_queue(&waiting_for_block, thread);
+ block->requests++;
+ }
+ }
+ while (thread != last_thread);
+ hash_link->block=block;
+ KEYCACHE_THREAD_TRACE("link_block: after signaling");
+#if defined(KEYCACHE_DEBUG)
+ KEYCACHE_DBUG_PRINT("link_block",
+ ("linked,unlinked block %u status=%x #requests=%u #available=%u",
+ BLOCK_NUMBER(block),block->status,
+ block->requests,_my_blocks_available));
#endif
+ return;
+ }
+ if (_my_used_last)
+ {
+ _my_used_last->next_used->prev_used=&block->next_used;
+ block->next_used=_my_used_last->next_used;
+ block->prev_used=&_my_used_last->next_used;
+ _my_used_last->next_used=block;
+ if (at_end)
+ _my_used_last=block;
+ }
+ else
+ {
+ /* The LRU chain is empty */
+ _my_used_last=block->next_used=block;
+ block->prev_used=&block->next_used;
+ }
+ KEYCACHE_THREAD_TRACE("link_block");
+#if defined(KEYCACHE_DEBUG)
+ _my_blocks_available++;
+ KEYCACHE_DBUG_PRINT("link_block",
+ ("linked block %u:%1u status=%x #requests=%u #available=%u",
+ BLOCK_NUMBER(block),at_end,block->status,
+ block->requests,_my_blocks_available));
+ KEYCACHE_DBUG_ASSERT(_my_blocks_available <= _my_blocks_used);
+#endif
+}
-#ifndef DBUG_OFF
-static void test_key_cache(const char *where, my_bool lock);
+
+/*
+ Unlink a block from the LRU chain
+*/
+static inline void unlink_block(BLOCK_LINK *block)
+{
+ if (block->next_used == block)
+ /* The list contains only one member */
+ _my_used_last=NULL;
+ else
+ {
+ block->next_used->prev_used=block->prev_used;
+ *block->prev_used=block->next_used;
+ if (_my_used_last == block)
+ _my_used_last=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
+ }
+ block->next_used=NULL;
+
+ KEYCACHE_THREAD_TRACE("unlink_block");
+#if defined(KEYCACHE_DEBUG)
+ _my_blocks_available--;
+ KEYCACHE_DBUG_PRINT("unlink_block",
+ ("unlinked block %u status=%x #requests=%u #available=%u",
+ BLOCK_NUMBER(block),block->status,
+ block->requests,_my_blocks_available));
+ KEYCACHE_DBUG_ASSERT(_my_blocks_available >= 0);
+#endif
+}
+
+
+/*
+ Register requests for a block
+*/
+static inline void reg_requests(BLOCK_LINK *block, int count)
+{
+ if (! block->requests)
+ /* First request for the block unlinks it */
+ unlink_block(block);
+ block->requests+=count;
+}
+
+
+/*
+ Unregister request for a block
+ linking it to the LRU chain if it's the last request
+*/
+static inline void unreg_request(BLOCK_LINK *block, int at_end)
+{
+ if (! --block->requests)
+ link_block(block, at_end);
+}
+
+/*
+ Remove a reader of the page in block
+*/
+static inline void remove_reader(BLOCK_LINK *block)
+{
+ if (! --block->hash_link->requests && block->condvar)
+ keycache_pthread_cond_signal(block->condvar);
+}
+
+
+/*
+ Wait until the last reader of the page in block
+ signals on its termination
+*/
+static inline void wait_for_readers(BLOCK_LINK *block)
+{
+ struct st_my_thread_var *thread=my_thread_var;
+ while (block->hash_link->requests)
+ {
+ block->condvar=&thread->suspend;
+ keycache_pthread_cond_wait(&thread->suspend,&THR_LOCK_keycache);
+ block->condvar=NULL;
+ }
+}
+
+
+/*
+ add a hash link to a bucket in the hash_table
+*/
+static inline void link_hash(HASH_LINK **start, HASH_LINK *hash_link)
+{
+ if (*start)
+ (*start)->prev=&hash_link->next;
+ hash_link->next=*start;
+ hash_link->prev=start;
+ *start=hash_link;
+}
+
+
+/*
+ Remove a hash link from the hash table
+*/
+static inline void unlink_hash(HASH_LINK *hash_link)
+{
+ KEYCACHE_DBUG_PRINT("unlink_hash", ("file %u, filepos %lu #requests=%u",
+ (uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests));
+ KEYCACHE_DBUG_ASSERT(hash_link->requests == 0);
+ if ((*hash_link->prev=hash_link->next))
+ hash_link->next->prev=hash_link->prev;
+ hash_link->block=NULL;
+ if (waiting_for_hash_link.last_thread)
+ { /* Signal that A free hash link appeared */
+ struct st_my_thread_var *last_thread=waiting_for_hash_link.last_thread;
+ struct st_my_thread_var *first_thread=last_thread->next;
+ struct st_my_thread_var *next_thread=first_thread;
+ KEYCACHE_PAGE *first_page= (KEYCACHE_PAGE *) (first_thread->opt_info);
+ struct st_my_thread_var *thread;
+
+ hash_link->file=first_page->file;
+ hash_link->diskpos=first_page->filepos;
+ do
+ {
+ KEYCACHE_PAGE *page;
+ thread=next_thread;
+ page= (KEYCACHE_PAGE *) thread->opt_info;
+ next_thread=thread->next;
+ /*
+ We notify about the event all threads that ask
+ for the same page as the first thread in the queue
+ */
+ if (page->file == hash_link->file && page->filepos == hash_link->diskpos)
+ {
+ keycache_pthread_cond_signal(&thread->suspend);
+ unlink_from_queue(&waiting_for_hash_link, thread);
+ }
+ }
+ while (thread != last_thread);
+ link_hash(&_my_hash_root[KEYCACHE_HASH(hash_link->file,
+ hash_link->diskpos)], hash_link);
+ return;
+ }
+ hash_link->next=_my_free_hash_list;
+ _my_free_hash_list=hash_link;
+}
+
+/*
+ Get the hash link for a page
+*/
+static inline HASH_LINK *get_hash_link(int file, my_off_t filepos)
+{
+ reg1 HASH_LINK *hash_link, **start;
+ KEYCACHE_PAGE page;
+#if defined(KEYCACHE_DEBUG)
+ int cnt;
+#endif
+
+ KEYCACHE_DBUG_PRINT("get_hash_link", ("file %u, filepos %lu",
+ (uint) file,(ulong) filepos));
+
+restart:
+ /*
+ Find the bucket in the hash table for the pair (file, filepos);
+ start contains the head of the bucket list,
+ hash_link points to the first member of the list
+ */
+ hash_link=*(start=&_my_hash_root[KEYCACHE_HASH(file, filepos)]);
+#if defined(KEYCACHE_DEBUG)
+ cnt=0;
+#endif
+ /* Look for an element for the pair (file, filepos) in the bucket chain */
+ while (hash_link &&
+ (hash_link->diskpos != filepos || hash_link->file != file))
+ {
+ hash_link= hash_link->next;
+#if defined(KEYCACHE_DEBUG)
+ cnt++;
+ if (! (cnt <= _my_hash_links_used))
+ {
+ int i;
+ for (i=0, hash_link=*start ;
+ i < cnt ; i++, hash_link=hash_link->next)
+ {
+ KEYCACHE_DBUG_PRINT("get_hash_link", ("file %u, filepos %lu",
+ (uint) hash_link->file,(ulong) hash_link->diskpos));
+ }
+ }
+ KEYCACHE_DBUG_ASSERT(n <= _my_hash_links_used);
+#endif
+ }
+ if (! hash_link)
+ { /* There is no hash link in the hash table for the pair (file, filepos) */
+ if (_my_free_hash_list)
+ {
+ hash_link=_my_free_hash_list;
+ _my_free_hash_list=hash_link->next;
+ }
+ else if (_my_hash_links_used < _my_hash_links)
+ {
+ hash_link= &_my_hash_link_root[_my_hash_links_used++];
+ }
+ else
+ { /* Wait for a free hash link */
+ struct st_my_thread_var *thread=my_thread_var;
+ KEYCACHE_DBUG_PRINT("get_hash_link", ("waiting"));
+ page.file=file; page.filepos=filepos;
+ thread->opt_info= (void *) &page;
+ link_into_queue(&waiting_for_hash_link, thread);
+ keycache_pthread_cond_wait(&thread->suspend,&THR_LOCK_keycache);
+ thread->opt_info=NULL;
+ goto restart;
+ }
+ hash_link->file=file;
+ hash_link->diskpos=filepos;
+ link_hash(start, hash_link);
+ }
+ /* Register the request for the page */
+ hash_link->requests++;
+
+ return hash_link;
+}
+
+
+/*
+ Get a block for the file page requested by a keycache read/write operation;
+ If the page is not in the cache return a free block, if there is none
+ return the lru block after saving its buffer if the page is dirty
+*/
+static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
+ int wrmode, int *page_st)
+{
+ HASH_LINK *hash_link;
+ BLOCK_LINK *block;
+ int error=0;
+ int page_status;
+
+ DBUG_ENTER("find_key_block");
+ KEYCACHE_THREAD_TRACE("find_key_block:begin");
+ DBUG_PRINT("enter", ("file %u, filepos %lu, wrmode %lu",
+ (uint) file,(ulong) filepos,(uint) wrmode));
+ KEYCACHE_DBUG_PRINT("find_key_block", ("file %u, filepos %lu, wrmode %lu",
+ (uint) file,(ulong) filepos,(uint) wrmode));
+#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
+ DBUG_EXECUTE("check_keycache2",test_key_cache("start of find_key_block",0););
#endif
+
+restart:
+ /* Find the hash link for the requested page (file, filepos) */
+ hash_link=get_hash_link(file, filepos);
+
+ page_status=-1;
+ if ((block=hash_link->block) &&
+ block->hash_link == hash_link && (block->status & BLOCK_READ))
+ page_status=PAGE_READ;
+
+ if (page_status == PAGE_READ && (block->status & BLOCK_IN_SWITCH))
+ { /* This is a request for a page to be removed from cache */
+
+ KEYCACHE_DBUG_PRINT("find_key_block",
+ ("request for old page in block %u",BLOCK_NUMBER(block)));
+ /*
+ Only reading requests can proceed until the old dirty page is flushed,
+ all others are to be suspended, then resubmitted
+ */
+ if (!wrmode && !(block->status & BLOCK_REASSIGNED))
+ reg_requests(block,1);
+ else
+ {
+ hash_link->requests--;
+ KEYCACHE_DBUG_PRINT("find_key_block",
+ ("request waiting for old page to be saved"));
+ {
+ struct st_my_thread_var *thread=my_thread_var;
+ /* Put the request into the queue of those waiting for the old page */
+ add_to_queue(&block->wqueue[COND_FOR_SAVED], thread);
+ /* Wait until the request can be resubmitted */
+ do
+ {
+ keycache_pthread_cond_wait(&thread->suspend, &THR_LOCK_keycache);
+ }
+ while(thread->next);
+ }
+ KEYCACHE_DBUG_PRINT("find_key_block",
+ ("request for old page resubmitted"));
+ /* Resubmit the request */
+ goto restart;
+ }
+ }
+ else
+ { /* This is a request for a new page or for a page not to be removed */
+ if (! block)
+ { /* No block is assigned for the page yet */
+ if (_my_blocks_used < (uint) _my_disk_blocks)
+ { /* There are some never used blocks, take first of them */
+ hash_link->block=block= &_my_block_root[_my_blocks_used];
+ block->buffer=ADD_TO_PTR(_my_block_mem,
+ ((ulong) _my_blocks_used*key_cache_block_size),
+ byte*);
+ block->status=0;
+ block->length=0;
+ block->offset=key_cache_block_size;
+ block->requests=1;
+ _my_blocks_used++;
+ link_to_file_list(block, file, 0);
+ block->hash_link=hash_link;
+ page_status=PAGE_TO_BE_READ;
+ KEYCACHE_DBUG_PRINT("find_key_block",
+ ("got never used block %u",BLOCK_NUMBER(block)));
+ }
+ else
+ { /* There are no never used blocks, use a block from the LRU chain */
+ /*
+ Wait until a new block is added to the LRU chain;
+ several threads might wait here for the same page,
+ all of them must get the same block
+ */
+
+ if (! _my_used_last)
+ {
+ struct st_my_thread_var *thread=my_thread_var;
+ thread->opt_info=(void *) hash_link;
+ link_into_queue(&waiting_for_block, thread);
+ do
+ {
+ keycache_pthread_cond_wait(&thread->suspend,&THR_LOCK_keycache);
+ }
+ while (thread->next);
+ thread->opt_info=NULL;
+ }
+ block=hash_link->block;
+ if (! block)
+ {
+ /*
+ Take the first block from the LRU chain
+ unlinking it from the chain
+ */
+ block=_my_used_last->next_used;
+ reg_requests(block,1);
+ hash_link->block=block;
+ }
+
+ if (block->hash_link != hash_link && ! (block->status & BLOCK_IN_SWITCH) )
+ { /* this is a primary request for a new page */
+ block->status|=BLOCK_IN_SWITCH;
+
+ KEYCACHE_DBUG_PRINT("find_key_block",
+ ("got block %u for new page",BLOCK_NUMBER(block)));
+
+ if (block->status & BLOCK_CHANGED)
+ { /* The block contains a dirty page - push it out of the cache */
+
+ KEYCACHE_DBUG_PRINT("find_key_block",("block is dirty"));
+
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+ /*
+ The call is thread safe because only the current
+ thread might change the block->hash_link value
+ */
+ error=my_pwrite(block->hash_link->file,block->buffer,
+ block->length,block->hash_link->diskpos,
+ MYF(MY_NABP | MY_WAIT_IF_FULL));
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+ _my_cache_write++;
+ }
+
+ block->status|=BLOCK_REASSIGNED;
+ if (block->hash_link)
+ {
+ /*
+ Wait until all pending read requests
+ for this page are executed
+ (we could have avoided this waiting, if we had read
+ a page in the cache in a sweep, without yielding control)
+ */
+ wait_for_readers(block);
+
+ /* Remove the hash link for this page from the hash table */
+ unlink_hash(block->hash_link);
+ /* All pending requests for this page must be resubmitted */
+ if (block->wqueue[COND_FOR_SAVED].last_thread)
+ release_queue(&block->wqueue[COND_FOR_SAVED]);
+ }
+ link_to_file_list(block, file, block->hash_link ? 1 : 0);
+ block->status=error? BLOCK_ERROR : 0;
+ block->length=0;
+ block->offset=key_cache_block_size;
+ block->hash_link=hash_link;
+ page_status=PAGE_TO_BE_READ;
+
+ KEYCACHE_DBUG_ASSERT(block->hash_link->block == block);
+ KEYCACHE_DBUG_ASSERT(hash_link->block->hash_link == hash_link);
+ }
+ else
+ {
+ /* This is for secondary requests for a new page only */
+ page_status = block->hash_link == hash_link &&
+ (block->status & BLOCK_READ) ?
+ PAGE_READ : PAGE_WAIT_TO_BE_READ;
+ }
+ }
+
+ _my_cache_read++;
+ }
+ else
+ {
+ reg_requests(block,1);
+ page_status = block->hash_link == hash_link &&
+ (block->status & BLOCK_READ) ?
+ PAGE_READ : PAGE_WAIT_TO_BE_READ;
+ }
+ }
+
+ KEYCACHE_DBUG_ASSERT(page_status != -1);
+ *page_st=page_status;
+
+#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
+ DBUG_EXECUTE("check_keycache2",test_key_cache("end of find_key_block",0););
+#endif
+ KEYCACHE_THREAD_TRACE("find_key_block:end");
+ DBUG_RETURN(block);
+}
- /*
- ** read a key_buffer
- ** filepos must point at a even key_cache_block_size block
- ** if return_buffer is set then the intern buffer is returned if
- ** it can be used
- ** Returns adress to where data is read
- */
+/*
+ Read into a key cache block buffer from disk;
+ do not to report error when the size of successfully read
+ portion is less than read_length, but not less than min_length
+*/
+static void read_block(BLOCK_LINK *block, uint read_length,
+ uint min_length, my_bool primary)
+{
+ uint got_length;
+
+ /* On entry THR_LOCK_keycache is locked */
+
+ KEYCACHE_THREAD_TRACE("read_block");
+ if (primary)
+ { /*
+ This code is executed only by threads
+ that submitted primary requests
+ */
+
+ KEYCACHE_DBUG_PRINT("read_block",
+ ("page to be read by primary request"));
+
+ /* Page is not in buffer yet, is to be read from disk */
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+ got_length=my_pread(block->hash_link->file,block->buffer,
+ read_length,block->hash_link->diskpos,MYF(0));
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+ if (got_length < min_length)
+ block->status|=BLOCK_ERROR;
+ else
+ {
+ block->status=BLOCK_READ;
+ block->length=got_length;
+ }
+ KEYCACHE_DBUG_PRINT("read_block",
+ ("primary request: new page in cache"));
+ /* Signal that all pending requests for this page now can be processed */
+ if (block->wqueue[COND_FOR_REQUESTED].last_thread)
+ release_queue(&block->wqueue[COND_FOR_REQUESTED]);
+ }
+ else
+ { /*
+ This code is executed only by threads
+ that submitted secondary requests
+ */
+ KEYCACHE_DBUG_PRINT("read_block",
+ ("secondary request waiting for new page to be read"));
+ {
+ struct st_my_thread_var *thread=my_thread_var;
+ /* Put the request into a queue and wait until it can be processed */
+ add_to_queue(&block->wqueue[COND_FOR_REQUESTED],thread);
+ do
+ {
+ keycache_pthread_cond_wait(&thread->suspend,&THR_LOCK_keycache);
+ }
+ while (thread->next);
+ }
+ KEYCACHE_DBUG_PRINT("read_block",
+ ("secondary request: new page in cache"));
+ }
+}
+
+
+/*
+ Read a block of data from a cached file into a buffer;
+ if return_buffer is set then the cache buffer is returned if
+ it can be used;
+ filepos must be a multiple of 'block_length', but it doesn't
+ have to be a multiple of key_cache_block_size;
+ returns adress from where data is read
+*/
byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
- reg1 SEC_LINK *next;
int error=0;
DBUG_ENTER("key_cache_read");
DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
- (uint) file, (ulong) filepos, length));
-
-#ifndef THREAD
- if (block_length > key_cache_block_size)
- return_buffer=0;
-#endif
+ (uint) file,(ulong) filepos,length));
+
if (_my_disk_blocks > 0)
- { /* We have key_cacheing */
+ { /* Key cache is used */
+ reg1 BLOCK_LINK *block;
+ uint offset= (uint) (filepos & (key_cache_block_size-1));
byte *start=buff;
uint read_length;
- pthread_mutex_lock(&THR_LOCK_keycache);
- if (_my_disk_blocks <= 0) /* Resize failed */
- {
- pthread_mutex_unlock(&THR_LOCK_keycache);
- goto no_key_cache;
- }
+ uint status;
+ int page_st;
+
+#ifndef THREAD
+ if (block_length > key_cache_block_size || offset)
+ return_buffer=0;
+#endif
+
+ /* Read data in key_cache_block_size increments */
+ filepos-= offset;
do
{
+ read_length= length > key_cache_block_size ?
+ key_cache_block_size : length;
+ KEYCACHE_DBUG_ASSERT(read_length > 0);
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
_my_cache_r_requests++;
- read_length= (length > key_cache_block_size ? key_cache_block_size :
- length);
- if (!(next=find_key_block(file,filepos,&error)))
+ block=find_key_block(file,filepos,0,&page_st);
+ if (page_st != PAGE_READ)
{
- pthread_mutex_unlock(&THR_LOCK_keycache);
- DBUG_RETURN ((byte*) 0); /* Got a fatal error */
+ /* The requested page is to be read into the block buffer */
+ read_block(block,key_cache_block_size,read_length+offset,
+ page_st == PAGE_TO_BE_READ);
}
- if (error)
- { /* Didn't find it in cache */
- if (my_pread(file,next->buffer,read_length,filepos,MYF(MY_NABP)))
- {
- pthread_mutex_unlock(&THR_LOCK_keycache);
- DBUG_RETURN((byte*) 0);
- }
- _my_cache_read++;
+ else if (! (block->status & BLOCK_ERROR) &&
+ block->length < read_length + offset)
+ {
+ /*
+ Impossible if nothing goes wrong:
+ this could only happen if we are using a file with
+ small key blocks and are trying to read outside the file
+ */
+ my_errno=-1;
+ block->status|=BLOCK_ERROR;
}
-#ifndef THREAD /* buffer may be used a long time */
- if (return_buffer)
+
+ if (! ((status=block->status) & BLOCK_ERROR))
{
- pthread_mutex_unlock(&THR_LOCK_keycache);
- DBUG_RETURN (next->buffer);
+#ifndef THREAD
+ if (! return_buffer)
+#endif
+ {
+#if !defined(SERIALIZED_READ_FROM_CACHE)
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+#endif
+
+ /* Copy data from the cache buffer */
+ if (!(read_length & 511))
+ bmove512(buff,block->buffer+offset,read_length);
+ else
+ memcpy(buff,block->buffer+offset,(size_t) read_length);
+
+#if !defined(SERIALIZED_READ_FROM_CACHE)
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+#endif
+ }
}
+
+ remove_reader(block);
+ /*
+ Link the block into the LRU chain
+ if it's the last submitted request for the block
+ */
+ unreg_request(block,1);
+
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+
+ if (status & BLOCK_ERROR)
+ DBUG_RETURN((byte *) 0);
+
+#ifndef THREAD
+ if (return_buffer)
+ return (block->buffer);
#endif
- if (! (read_length & 511))
- bmove512(buff,next->buffer,read_length);
- else
- memcpy(buff,next->buffer,(size_t) read_length);
+
buff+=read_length;
filepos+=read_length;
+ offset=0;
+
} while ((length-= read_length));
- pthread_mutex_unlock(&THR_LOCK_keycache);
DBUG_RETURN(start);
}
-
-no_key_cache:
- _my_cache_r_requests++;
- _my_cache_read++;
+
+ /* Key cache is not used */
+ statistic_increment(_my_cache_r_requests,&THR_LOCK_keycache);
+ statistic_increment(_my_cache_read,&THR_LOCK_keycache);
if (my_pread(file,(byte*) buff,length,filepos,MYF(MY_NABP)))
error=1;
- DBUG_RETURN(error ? (byte*) 0 : buff);
-} /* key_cache_read */
-
+ DBUG_RETURN(error? (byte*) 0 : buff);
+}
- /* write a key_buffer */
- /* We don't have to use pwrite because of write locking */
- /* buff must point at a even key_cache_block_size block */
+/*
+ Write a buffer into disk;
+ filepos must be a multiple of 'block_length', but it doesn't
+ have to be a multiple of key cache block size;
+ if !dont_write then all dirty pages involved in writing should
+ have been flushed from key cache before the function starts
+*/
int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
- reg1 SEC_LINK *next;
+ reg1 BLOCK_LINK *block;
int error=0;
+
DBUG_ENTER("key_cache_write");
- DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
- (uint) file, (ulong) filepos, length));
+ DBUG_PRINT("enter", ("file %u, filepos %lu, length %u block_length %u",
+ (uint) file,(ulong) filepos,length,block_length));
if (!dont_write)
- { /* Forced write of buffer */
- _my_cache_write++;
+ { /* Force writing from buff into disk */
+ statistic_increment(_my_cache_write, &THR_LOCK_keycache);
if (my_pwrite(file,buff,length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
DBUG_RETURN(1);
}
-
+
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache",test_key_cache("start of key_cache_write",1););
#endif
+
if (_my_disk_blocks > 0)
- { /* We have key_cacheing */
+ { /* Key cache is used */
uint read_length;
- pthread_mutex_lock(&THR_LOCK_keycache);
- if (_my_disk_blocks <= 0) /* If resize failed */
- {
- pthread_mutex_unlock(&THR_LOCK_keycache);
- goto no_key_cache;
- }
-
- _my_cache_w_requests++;
+ uint offset= (uint) (filepos & (key_cache_block_size-1));
+ int page_st;
+
+ /* Write data in key_cache_block_size increments */
+ filepos-= offset;
do
{
- read_length= length > key_cache_block_size ? key_cache_block_size : length;
- if (!(next=find_key_block(file,filepos,&error)))
- goto end; /* Fatal error */
- if (!dont_write) /* If we wrote buff at start */
+ read_length= length > key_cache_block_size ?
+ key_cache_block_size : length;
+ KEYCACHE_DBUG_ASSERT(read_length > 0);
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+ _my_cache_w_requests++;
+ block=find_key_block(file, filepos, 1, &page_st);
+ if (page_st != PAGE_READ &&
+ (offset || read_length < key_cache_block_size))
+ read_block(block,
+ offset + read_length >= key_cache_block_size?
+ offset : key_cache_block_size,
+ offset,page_st == PAGE_TO_BE_READ);
+
+ if (!dont_write)
+ { /* buff has been written to disk at start */
+ if ((block->status & BLOCK_CHANGED) &&
+ (!offset && read_length >= key_cache_block_size))
+ link_to_file_list(block, block->hash_link->file, 1);
+ }
+ else if (! (block->status & BLOCK_CHANGED))
+ link_to_changed_list(block);
+
+ set_if_smaller(block->offset,offset)
+ set_if_bigger(block->length,read_length+offset);
+
+ if (! (block->status & BLOCK_ERROR))
{
- if (next->changed) /* Unlink from changed list */
- link_changed_to_file(next,next->file);
+ if (!(read_length & 511))
+ bmove512(block->buffer+offset,buff,read_length);
+ else
+ memcpy(block->buffer+offset,buff,(size_t) read_length);
}
- else if (!next->changed)
- link_file_to_changed(next); /* Add to changed list */
-
- if (!(read_length & 511))
- bmove512(next->buffer,buff,read_length);
- else
- memcpy(next->buffer,buff,(size_t) read_length);
+
+ block->status|=BLOCK_READ;
+
+ /* Unregister the request */
+ block->hash_link->requests--;
+ unreg_request(block,1);
+
+ if (block->status & BLOCK_ERROR)
+ {
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+ error=1;
+ break;
+ }
+
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+
buff+=read_length;
filepos+=read_length;
+ offset=0;
+
} while ((length-= read_length));
- error=0;
- pthread_mutex_unlock(&THR_LOCK_keycache);
- goto end;
- }
-
-no_key_cache:
- if (dont_write)
- { /* We must write, no cache */
- _my_cache_w_requests++;
- _my_cache_write++;
- if (my_pwrite(file,(byte*) buff,length,filepos,
- MYF(MY_NABP | MY_WAIT_IF_FULL)))
- error=1;
- }
-
-end:
-#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
- DBUG_EXECUTE("check_keycache",test_key_cache("end of key_cache_write",1););
-#endif
- DBUG_RETURN(error);
-} /* key_cache_write */
-
-
- /* Find block in cache */
- /* IF found sector and error is set then next->changed is cleared */
-
-static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error)
-{
- reg1 SEC_LINK *next,**start;
- DBUG_ENTER("find_key_block");
- DBUG_PRINT("enter", ("file %u, filepos %lu",
- (uint) file, (ulong) filepos));
-
-#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
- DBUG_EXECUTE("check_keycache2",test_key_cache("start of find_key_block",0););
-#endif
-
- *error=0;
- next= *(start= &_my_hash_root[((ulong) (filepos >> key_cache_shift)+(ulong) file) &
- (_my_hash_blocks-1)]);
- while (next && (next->diskpos != filepos || next->file != file))
- next= next->next_hash;
-
- if (next)
- { /* Found block */
- if (next != _my_used_last)
- { /* Relink used-chain */
- if (next == _my_used_first)
- _my_used_first=next->next_used;
- else
- {
- next->prev_used->next_used = next->next_used;
- next->next_used->prev_used = next->prev_used;
- }
- next->prev_used=_my_used_last;
- _my_used_last->next_used=next;
- }
}
else
- { /* New block */
- if (_my_disk_blocks_used+1 <= (uint) _my_disk_blocks)
- { /* There are unused blocks */
- next= &_my_block_root[_my_blocks_used++]; /* Link in hash-chain */
- next->buffer=ADD_TO_PTR(_my_block_mem,
- ((ulong) _my_disk_blocks_used << key_cache_shift),
- byte*);
- /* link first in file_blocks */
- next->changed=0;
- link_into_file_blocks(next,file);
- _my_disk_blocks_used++;
- if (!_my_used_first)
- _my_used_first=next;
- if (_my_used_last)
- _my_used_last->next_used=next; /* Last in used-chain */
+ {
+ /* Key cache is not used */
+ if (dont_write)
+ {
+ statistic_increment(_my_cache_w_requests, &THR_LOCK_keycache);
+ statistic_increment(_my_cache_write, &THR_LOCK_keycache);
+ if (my_pwrite(file,(byte*) buff,length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
+ error=1;
}
- else
- { /* Reuse old block */
- next= _my_used_first;
- if (next->changed)
- {
- if (my_pwrite(next->file,next->buffer,key_cache_block_size,
- next->diskpos,
- MYF(MY_NABP | MY_WAIT_IF_FULL)))
- {
- *error=1;
- return((SEC_LINK*) 0);
- }
- _my_cache_write++;
- link_changed_to_file(next,file);
- }
- else
- {
- if (next->file == -1)
- link_into_file_blocks(next,file);
- else
- relink_into_file_blocks(next,file);
- }
- if (next->prev_hash) /* If in hash-link */
- if ((*next->prev_hash=next->next_hash) != 0) /* Remove from link */
- next->next_hash->prev_hash= next->prev_hash;
+ }
- _my_used_last->next_used=next;
- _my_used_first=next->next_used;
- }
- if (*start) /* Link in first in h.-chain */
- (*start)->prev_hash= &next->next_hash;
- next->next_hash= *start; next->prev_hash=start; *start=next;
- next->prev_used=_my_used_last;
- next->file=file;
- next->diskpos=filepos;
- *error=1; /* Block wasn't in memory */
- }
- _my_used_last=next;
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
- DBUG_EXECUTE("check_keycache2",test_key_cache("end of find_key_block",0););
+ DBUG_EXECUTE("exec",test_key_cache("end of key_cache_write",1););
#endif
- DBUG_RETURN(next);
-} /* find_key_block */
+ DBUG_RETURN(error);
+}
-static void free_block(SEC_LINK *used)
+/*
+ Free block: remove reference to it from hash table,
+ remove it from the chain file of dirty/clean blocks
+ and add it at the beginning of the LRU chain
+*/
+static void free_block(BLOCK_LINK *block)
{
- used->file= -1;
- used->changed=0;
- if (used != _my_used_first) /* Relink used-chain */
+ KEYCACHE_THREAD_TRACE("free block");
+ KEYCACHE_DBUG_PRINT("free_block",
+ ("block %u to be freed",BLOCK_NUMBER(block)));
+ if (block->hash_link)
{
- if (used == _my_used_last)
- _my_used_last=used->prev_used;
- else
- {
- used->prev_used->next_used = used->next_used;
- used->next_used->prev_used = used->prev_used;
- }
- used->next_used=_my_used_first;
- used->next_used->prev_used=used;
- _my_used_first=used;
+ block->status|=BLOCK_REASSIGNED;
+ wait_for_readers(block);
+ unlink_hash(block->hash_link);
}
- if ((*used->prev_hash=used->next_hash)) /* Relink hash-chain */
- used->next_hash->prev_hash= used->prev_hash;
- if (used->next_changed) /* Relink changed/file list */
- used->next_changed->prev_changed=used->prev_changed;
- *used->prev_changed=used->next_changed;
- used->prev_hash=0; used->next_hash=0; /* Safety */
+
+ unlink_changed(block);
+ block->status=0;
+ block->length=0;
+ block->offset=key_cache_block_size;
+ KEYCACHE_THREAD_TRACE("free block");
+ KEYCACHE_DBUG_PRINT("free_block",
+ ("block is freed"));
+ unreg_request(block,0);
+ block->hash_link=NULL;
}
- /* Flush all changed blocks to disk. Free used blocks if requested */
-
-static int cmp_sec_link(SEC_LINK **a, SEC_LINK **b)
+static int cmp_sec_link(BLOCK_LINK **a, BLOCK_LINK **b)
{
- return (((*a)->diskpos < (*b)->diskpos) ? -1 :
- ((*a)->diskpos > (*b)->diskpos) ? 1 : 0);
+ return (((*a)->hash_link->diskpos < (*b)->hash_link->diskpos) ? -1 :
+ ((*a)->hash_link->diskpos > (*b)->hash_link->diskpos) ? 1 : 0);
}
-static int flush_cached_blocks(File file, SEC_LINK **cache, uint count)
+/*
+ Flush a portion of changed blocks to disk,
+ free used blocks if requested
+*/
+static int flush_cached_blocks(File file, BLOCK_LINK **cache,
+ BLOCK_LINK **end,
+ enum flush_type type)
{
- uint last_errno=0;
- qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
- for ( ; count-- ; cache++)
+ int error;
+ int last_errno=0;
+ uint count=end-cache;
+
+ /* Don't lock the cache during the flush */
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+ /*
+ As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
+ we are guarunteed no thread will change them
+ */
+ qsort((byte*) cache,count,sizeof(*cache),(qsort_cmp) cmp_sec_link);
+
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+ for ( ; cache != end ; cache++)
{
- if (my_pwrite(file,(*cache)->buffer,key_cache_block_size,
- (*cache)->diskpos,
- MYF(MY_NABP | MY_WAIT_IF_FULL)))
+ BLOCK_LINK *block= *cache;
+
+ KEYCACHE_DBUG_PRINT("flush_cached_blocks",
+ ("block %u to be flushed", BLOCK_NUMBER(block)));
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+ error=my_pwrite(file,block->buffer+block->offset,block->length,
+ block->hash_link->diskpos,MYF(MY_NABP | MY_WAIT_IF_FULL));
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+ _my_cache_write++;
+ if (error)
{
+ block->status|= BLOCK_ERROR;
if (!last_errno)
- last_errno=errno ? errno : -1;
+ last_errno=errno ? errno : -1;
+ }
+ /* type will never be FLUSH_IGNORE_CHANGED here */
+ if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE))
+ {
+ _my_blocks_changed--;
+ free_block(block);
+ }
+ else
+ {
+ block->status&=~BLOCK_IN_FLUSH;
+ link_to_file_list(block,file,1);
+ unreg_request(block,1);
}
+
}
return last_errno;
}
-static int flush_key_blocks_int(File file, enum flush_type type)
+/*
+ Flush all blocks for a file to disk
+*/
+int flush_key_blocks(File file, enum flush_type type)
{
- int error=0,last_errno=0;
- uint count=0;
- SEC_LINK *cache_buff[FLUSH_CACHE],**cache,**pos,**end;
- SEC_LINK *used,*next;
- DBUG_ENTER("flush_key_blocks_int");
+ int last_errno=0;
+ BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
+ DBUG_ENTER("flush_key_blocks");
DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
- file,_my_blocks_used,_my_blocks_changed));
-
- cache=cache_buff; /* If no key cache */
- if (_my_disk_blocks > 0 &&
- (!my_disable_flush_key_blocks || type != FLUSH_KEEP))
- {
+ file,_my_blocks_used,_my_blocks_changed));
+
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache",test_key_cache("start of flush_key_blocks",0););
#endif
+
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+
+ cache=cache_buff;
+ if (_my_disk_blocks > 0 &&
+ (!my_disable_flush_key_blocks || type != FLUSH_KEEP))
+ { /* Key cache exists and flush is not disabled */
+ int error=0;
+ uint count=0;
+ BLOCK_LINK **pos,**end;
+ BLOCK_LINK *first_in_switch=NULL;
+ BLOCK_LINK *block, *next;
+#if defined(KEYCACHE_DEBUG)
+ uint cnt=0;
+#endif
+
if (type != FLUSH_IGNORE_CHANGED)
{
- /* Count how many key blocks we have to cache to be able to
- write everything with so few seeks as possible */
-
- for (used=changed_blocks[(uint) file & CHANGED_BLOCKS_MASK];
- used ;
- used=used->next_changed)
+ /*
+ Count how many key blocks we have to cache to be able
+ to flush all dirty pages with minimum seek moves
+ */
+ for (block=changed_blocks[FILE_HASH(file)] ;
+ block ;
+ block=block->next_changed)
{
- if (used->file == file)
- count++;
- }
- /* Only allocate a new buffer if its bigger than the one we have */
- if (count > FLUSH_CACHE)
- {
- if (!(cache=(SEC_LINK**) my_malloc(sizeof(SEC_LINK*)*count,MYF(0))))
+ if (block->hash_link->file == file)
{
- cache=cache_buff; /* Fall back to safe buffer */
- count=FLUSH_CACHE;
+ count++;
+ KEYCACHE_DBUG_ASSERT(count<=_my_blocks_used);
}
}
+ /* Allocate a new buffer only if its bigger than the one we have */
+ if (count > FLUSH_CACHE &&
+ !(cache=(BLOCK_LINK**) my_malloc(sizeof(BLOCK_LINK*)*count,MYF(0))))
+ {
+ cache=cache_buff;
+ count=FLUSH_CACHE;
+ }
}
-
- /* Go through the keys and write them to buffer to be flushed */
+
+ /* Retrieve the blocks and write them to a buffer to be flushed */
+restart:
end=(pos=cache)+count;
- for (used=changed_blocks[(uint) file & CHANGED_BLOCKS_MASK];
- used ;
- used=next)
+ for (block=changed_blocks[FILE_HASH(file)] ;
+ block ;
+ block=next)
{
- next=used->next_changed;
- if (used->file == file)
+#if defined(KEYCACHE_DEBUG)
+ cnt++;
+ KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
+#endif
+ next=block->next_changed;
+ if (block->hash_link->file == file)
{
- if (type != FLUSH_IGNORE_CHANGED)
- {
- if (pos == end)
- {
- if ((error=flush_cached_blocks(file, cache, count)))
- last_errno=error;
- pos=cache;
- }
- *pos++=used;
- _my_cache_write++;
- }
- if (type != FLUSH_KEEP && type != FLUSH_FORCE_WRITE)
- {
- /* This will not destroy position or data */
- _my_blocks_changed--;
- free_block(used);
- }
- else
- link_changed_to_file(used,file);
+ /*
+ Mark the block with BLOCK_IN_FLUSH in order not to let
+ other threads to use it for new pages and interfere with
+ our sequence ot flushing dirty file pages
+ */
+ block->status|= BLOCK_IN_FLUSH;
+
+ if (! (block->status & BLOCK_IN_SWITCH))
+ { /*
+ We care only for the blocks for which flushing was not
+ initiated by other threads as a result of page swapping
+ */
+ reg_requests(block,1);
+ if (type != FLUSH_IGNORE_CHANGED)
+ { /* It's not a temporary file */
+ if (pos == end)
+ { /*
+ This happens only if there is not enough
+ memory for the big block
+ */
+ if ((error=flush_cached_blocks(file,cache,end,type)))
+ last_errno=error;
+ /*
+ Restart the scan as some other thread might have changed
+ the changed blocks chain: the blocks that were in switch
+ state before the flush started have to be excluded
+ */
+ goto restart;
+ }
+ *pos++=block;
+ }
+ else
+ {
+ /* It's a temporary file */
+ _my_blocks_changed--;
+ free_block(block);
+ }
+ }
+ else
+ { /* Link the block into a list of blocks 'in switch' */
+ unlink_changed(block);
+ link_changed(block,&first_in_switch);
+ }
}
}
if (pos != cache)
{
- if ((error=flush_cached_blocks(file, cache, (uint) (pos-cache))))
- last_errno=error;
+ if ((error=flush_cached_blocks(file,cache,pos,type)))
+ last_errno=error;
+ }
+ /* Wait until list of blocks in switch is empty */
+ while (first_in_switch)
+ {
+#if defined(KEYCACHE_DEBUG)
+ cnt=0;
+#endif
+ block=first_in_switch;
+ {
+ struct st_my_thread_var *thread=my_thread_var;
+ add_to_queue(&block->wqueue[COND_FOR_SAVED], thread);
+ do
+ {
+ keycache_pthread_cond_wait(&thread->suspend,&THR_LOCK_keycache);
+ }
+ while (thread->next);
+ }
+#if defined(KEYCACHE_DEBUG)
+ cnt++;
+ KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
+#endif
}
/* The following happens very seldom */
- if (type != FLUSH_KEEP && type != FLUSH_FORCE_WRITE)
+ if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE))
{
- for (used=file_blocks[(uint) file & CHANGED_BLOCKS_MASK];
- used ;
- used=next)
+#if defined(KEYCACHE_DEBUG)
+ cnt=0;
+#endif
+ for (block=file_blocks[FILE_HASH(file)] ;
+ block ;
+ block=next)
{
- next=used->next_changed;
- if (used->file == file && (!used->changed ||
- type == FLUSH_IGNORE_CHANGED))
- free_block(used);
+#if defined(KEYCACHE_DEBUG)
+ cnt++;
+ KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
+#endif
+ next=block->next_changed;
+ if (block->hash_link->file == file &&
+ (! (block->status & BLOCK_CHANGED)
+ || type == FLUSH_IGNORE_CHANGED))
+ {
+ reg_requests(block,1);
+ free_block(block);
+ }
}
}
+ }
+
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+
#ifndef DBUG_OFF
- DBUG_EXECUTE("check_keycache",test_key_cache("end of flush_key_blocks",0););
+ DBUG_EXECUTE("check_keycache",
+ test_key_cache("end of flush_key_blocks",0););
#endif
- }
if (cache != cache_buff)
my_free((gptr) cache,MYF(0));
if (last_errno)
- errno=last_errno; /* Return first error */
+ errno=last_errno; /* Return first error */
DBUG_RETURN(last_errno != 0);
}
-/*
- Flush all blocks for a specific file to disk
+/*
+ Flush all blocks in the key cache to disk
+*/
+static int flush_all_key_blocks()
+{
+#if defined(KEYCACHE_DEBUG)
+ uint cnt=0;
+#endif
+ while (_my_blocks_changed > 0)
+ {
+ BLOCK_LINK *block;
+ for (block=_my_used_last->next_used ; ; block=block->next_used)
+ {
+ if (block->hash_link)
+ {
+#if defined(KEYCACHE_DEBUG)
+ cnt++;
+ KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
+#endif
+ if (flush_key_blocks(block->hash_link->file, FLUSH_RELEASE))
+ return 1;
+ break;
+ }
+ if (block == _my_used_last)
+ break;
+ }
+ }
+ return 0;
+}
- SYNOPSIS
- flush_all_key_blocks()
- file File descriptor
- type Type of flush operation
- RETURN VALUES
- 0 Ok
- 1 Error
+#ifndef DBUG_OFF
+/*
+ Test if disk-cache is ok
*/
+static void test_key_cache(const char *where __attribute__((unused)),
+ my_bool lock __attribute__((unused)))
+{
+ /* TODO */
+}
+#endif
-int flush_key_blocks(File file, enum flush_type type)
+#if defined(KEYCACHE_TIMEOUT)
+
+#define KEYCACHE_DUMP_FILE "keycache_dump.txt"
+#define MAX_QUEUE_LEN 100
+
+
+static void keycache_dump()
{
- int res;
- pthread_mutex_lock(&THR_LOCK_keycache);
- res=flush_key_blocks_int(file, type);
- pthread_mutex_unlock(&THR_LOCK_keycache);
- return res;
+ FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
+ struct st_my_thread_var *thread_var =my_thread_var;
+ struct st_my_thread_var *last;
+ struct st_my_thread_var *thread;
+ BLOCK_LINK *block;
+ HASH_LINK *hash_link;
+ KEYCACHE_PAGE *page;
+ uint i;
+
+ fprintf(keycache_dump_file, "thread:%u\n", thread->id);
+
+ i=0;
+ thread=last=waiting_for_hash_link.last_thread;
+ fprintf(keycache_dump_file, "queue of threads waiting for hash link\n");
+ if (thread)
+ do
+ {
+ thread=thread->next;
+ page= (KEYCACHE_PAGE *) thread->opt_info;
+ fprintf(keycache_dump_file,
+ "thread:%u, (file,filepos)=(%u,%lu)\n",
+ thread->id,(uint) page->file,(ulong) page->filepos);
+ if (++i == MAX_QUEUE_LEN)
+ break;
+ }
+ while (thread != last);
+
+ i=0;
+ thread=last=waiting_for_block.last_thread;
+ fprintf(keycache_dump_file, "queue of threads waiting for block\n");
+ if (thread)
+ do
+ {
+ thread=thread->next;
+ hash_link= (HASH_LINK *) thread->opt_info;
+ fprintf(keycache_dump_file,
+ "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n",
+ thread->id, (uint) HASH_LINK_NUMBER(hash_link),
+ (uint) hash_link->file,(ulong) hash_link->diskpos);
+ if (++i == MAX_QUEUE_LEN)
+ break;
+ }
+ while (thread != last);
+
+ for (i=0 ; i< _my_blocks_used ; i++)
+ {
+ int j;
+ block=&_my_block_root[i];
+ hash_link=block->hash_link;
+ fprintf(keycache_dump_file,
+ "block:%u hash_link:%d status:%x #requests=%u waiting_for_readers:%d\n",
+ i, (int) (hash_link ? HASH_LINK_NUMBER(hash_link) : -1),
+ block->status, block->requests, block->condvar ? 1 : 0);
+ for (j=0 ; j < 2; j++)
+ {
+ KEYCACHE_WQUEUE *wqueue=&block->wqueue[j];
+ thread=last=wqueue->last_thread;
+ fprintf(keycache_dump_file, "queue #%d\n", j);
+ if (thread)
+ do
+ {
+ thread=thread->next;
+ fprintf(keycache_dump_file,
+ "thread:%u\n", thread->id);
+ if (++i == MAX_QUEUE_LEN)
+ break;
+ }
+ while (thread != last);
+ }
+ }
+ fprintf(keycache_dump_file, "LRU chain:");
+ block=_my_used_last;
+ if (block)
+ do
+ {
+ block=block->next_used;
+ fprintf(keycache_dump_file,
+ "block:%u, ", BLOCK_NUMBER(block));
+ }
+ while (block != _my_used_last);
+ fprintf(keycache_dump_file, "\n");
+
+ fclose(keycache_dump_file);
}
+#endif /* defined(KEYCACHE_TIMEOUT) */
-/*
- Flush all blocks in the key cache to disk
+#if defined(KEYCACHE_TIMEOUT) && !defined(__WIN__)
- SYNOPSIS
- flush_all_key_blocks()
- NOTE
- We must have a lock on THR_LOCK_keycache before calling this function
+static int keycache_pthread_cond_wait(pthread_cond_t *cond,
+ pthread_mutex_t *mutex)
+{
+ int rc;
+ struct timeval now; /* time when we started waiting */
+ struct timespec timeout; /* timeout value for the wait function */
+ struct timezone tz;
+#if defined(KEYCACHE_DEBUG)
+ int cnt=0;
+#endif
+
+ /* Get current time */
+ gettimeofday(&now, &tz);
+ /* Prepare timeout value */
+ timeout.tv_sec = now.tv_sec + KEYCACHE_TIMEOUT;
+ timeout.tv_nsec = now.tv_usec * 1000; /* timeval uses microseconds. */
+ /* timespec uses nanoseconds. */
+ /* 1 nanosecond = 1000 micro seconds. */
+ KEYCACHE_THREAD_TRACE_END("started waiting");
+#if defined(KEYCACHE_DEBUG)
+ cnt++;
+ if (cnt % 100 == 0)
+ fprintf(keycache_debug_log, "waiting...\n");
+ fflush(keycache_debug_log);
+#endif
+ rc = pthread_cond_timedwait(cond, mutex, &timeout);
+ KEYCACHE_THREAD_TRACE_BEGIN("finished waiting");
+#if defined(KEYCACHE_DEBUG)
+ if (rc == ETIMEDOUT)
+ {
+ fprintf(keycache_debug_log,"aborted by keycache timeout\n");
+ fclose(keycache_debug_log);
+ abort();
+ }
+#endif
+
+ if (rc == ETIMEDOUT)
+ keycache_dump();
+
+#if defined(KEYCACHE_DEBUG)
+ KEYCACHE_DBUG_ASSERT(rc != ETIMEDOUT);
+#else
+ assert(rc != ETIMEDOUT);
+#endif
+ return rc;
+}
+#else
+#if defined(KEYCACHE_DEBUG)
+static int keycache_pthread_cond_wait(pthread_cond_t *cond,
+ pthread_mutex_t *mutex)
+{
+ int rc;
+ KEYCACHE_THREAD_TRACE_END("started waiting");
+ rc = pthread_cond_wait(cond, mutex);
+ KEYCACHE_THREAD_TRACE_BEGIN("finished waiting");
+ return rc;
+}
+#endif
+#endif /* defined(KEYCACHE_TIMEOUT) && !defined(__WIN__) */
- RETURN VALUES
- 0 Ok
- 1 Error
-*/
+#if defined(KEYCACHE_DEBUG)
-static int flush_all_key_blocks()
+static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex)
{
- int error=0;
- while (_my_blocks_changed > 0)
- if (flush_key_blocks_int(_my_used_first->file, FLUSH_RELEASE))
- error=1;
- return error;
+ int rc;
+ rc=pthread_mutex_lock(mutex);
+ KEYCACHE_THREAD_TRACE_BEGIN("");
+ return rc;
}
-#ifndef DBUG_OFF
+static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+ KEYCACHE_THREAD_TRACE_END("");
+ pthread_mutex_unlock(mutex);
+}
- /* Test if disk-cache is ok */
-static void test_key_cache(const char *where, my_bool lock)
+static int keycache_pthread_cond_signal(pthread_cond_t *cond)
{
- reg1 uint i,error;
- ulong found,changed;
- SEC_LINK *pos,**prev;
+ int rc;
+ KEYCACHE_THREAD_TRACE("signal");
+ rc=pthread_cond_signal(cond);
+ return rc;
+}
- if (lock)
- {
- pthread_mutex_lock(&THR_LOCK_keycache);
- if (_my_disk_blocks <= 0) /* No active key cache */
- {
- pthread_mutex_unlock(&THR_LOCK_keycache);
- return;
- }
- }
- found=error=0;
- for (i= 0 ; i < _my_hash_blocks ; i++)
- {
- for (pos= *(prev= &_my_hash_root[i]) ;
- pos && found < _my_blocks_used+2 ;
- found++, pos= *(prev= &pos->next_hash))
- {
- if (prev != pos->prev_hash)
- {
- error=1;
- DBUG_PRINT("error",
- ("hash: %d pos: %lx : prev: %lx != pos->prev: %lx",
- i,(ulong) pos,(ulong) prev,(ulong) pos->prev_hash));
- }
+static int keycache_pthread_cond_broadcast(pthread_cond_t *cond)
+{
+ int rc;
+ KEYCACHE_THREAD_TRACE("signal");
+ rc=pthread_cond_broadcast(cond);
+ return rc;
+}
- if (((pos->diskpos >> key_cache_shift)+pos->file) % _my_hash_blocks != i)
- {
- DBUG_PRINT("error",("hash: %d pos: %lx : Wrong disk_buffer %ld",
- i,(ulong) pos,(ulong) pos->diskpos));
- error=1;
- }
- }
- }
- if (found > _my_blocks_used)
- {
- DBUG_PRINT("error",("Found too many hash_pointers"));
- error=1;
- }
- if (error && !_my_printed)
- { /* Write all hash-pointers */
- _my_printed=1;
- for (i=0 ; i < _my_hash_blocks ; i++)
- {
- DBUG_PRINT("loop",("hash: %d _my_hash_root: %lx",i,&_my_hash_root[i]));
- pos= _my_hash_root[i]; found=0;
- while (pos && found < 10)
- {
- DBUG_PRINT("loop",("pos: %lx prev: %lx next: %lx file: %d disk_buffer: %ld", (ulong) pos, (ulong) pos->prev_hash, (ulong) pos->next_hash, (ulong) pos->file, (ulong) pos->diskpos));
- found++; pos= pos->next_hash;
- }
- }
- }
+#if defined(KEYCACHE_DEBUG_LOG)
- found=changed=0;
- if ((pos=_my_used_first))
- {
- while (pos != _my_used_last && found < _my_blocks_used+2)
- {
- found++;
- if (pos->changed)
- changed++;
- if (pos->next_used->prev_used != pos)
- {
- DBUG_PRINT("error",("pos: %lx next_used: %lx next_used->prev: %lx",
- (ulong) pos,
- (ulong) pos->next_used,
- (ulong) pos->next_used->prev_hash));
- error=1;
- }
- pos=pos->next_used;
- }
- found++;
- if (pos->changed)
- changed++;
- }
- if (found != _my_blocks_used)
+static void keycache_debug_print(const char * fmt,...)
+{
+ va_list args;
+ va_start(args,fmt);
+ if (keycache_debug_log)
{
- DBUG_PRINT("error",("Found %lu of %lu keyblocks",found,_my_blocks_used));
- error=1;
+ VOID(vfprintf(keycache_debug_log, fmt, args));
+ VOID(fputc('\n',keycache_debug_log));
}
+ va_end(args);
+}
+#endif /* defined(KEYCACHE_DEBUG_LOG) */
- for (i= 0 ; i < CHANGED_BLOCKS_HASH ; i++)
- {
- found=0;
- prev= &changed_blocks[i];
- for (pos= *prev ; pos && found < _my_blocks_used+2; pos=pos->next_changed)
- {
- found++;
- if (pos->prev_changed != prev)
- {
- DBUG_PRINT("error",("changed_block list %d doesn't point backwards properly",i));
- error=1;
- }
- prev= &pos->next_changed;
- if (((uint) pos->file & CHANGED_BLOCKS_MASK) != i)
- {
- DBUG_PRINT("error",("Wrong file %d in changed blocks: %d",pos->file,i));
- error=1;
- }
- changed--;
- }
- if (pos)
- {
- DBUG_PRINT("error",("changed_blocks %d has recursive link",i));
- error=1;
- }
+#if defined(KEYCACHE_DEBUG_LOG)
+
+
+void keycache_debug_log_close(void)
+{
+ if (keycache_debug_log)
+ fclose(keycache_debug_log);
+}
+#endif /* defined(KEYCACHE_DEBUG_LOG) */
+
+#endif /* defined(KEYCACHE_DEBUG) */
- found=0;
- prev= &file_blocks[i];
- for (pos= *prev ; pos && found < _my_blocks_used+2; pos=pos->next_changed)
- {
- found++;
- if (pos->prev_changed != prev)
- {
- DBUG_PRINT("error",("file_block list %d doesn't point backwards properly",i));
- error=1;
- }
- prev= &pos->next_changed;
- if (((uint) pos->file & CHANGED_BLOCKS_MASK) != i)
- {
- DBUG_PRINT("error",("Wrong file %d in file_blocks: %d",pos->file,i));
- error=1;
- }
- }
- if (pos)
- {
- DBUG_PRINT("error",("File_blocks %d has recursive link",i));
- error=1;
- }
- }
- if (changed != 0)
- {
- DBUG_PRINT("error",("Found %lu blocks that wasn't in changed blocks",
- changed));
- error=1;
- }
- if (error)
- DBUG_PRINT("error",("Found error at %s",where));
- if (lock)
- pthread_mutex_unlock(&THR_LOCK_keycache);
- return;
-} /* test_key_cache */
-#endif
diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c
index 4f7aa7da601..459e304dfd7 100644
--- a/mysys/mf_soundex.c
+++ b/mysys/mf_soundex.c
@@ -34,24 +34,25 @@
#include <m_ctype.h>
#include "my_static.h"
-static char get_scode(char **ptr,pbool remove_garbage);
+static char get_scode(CHARSET_INFO * cs, char **ptr,pbool remove_garbage);
/* outputed string is 4 byte long */
/* out_pntr can be == in_pntr */
-void soundex(register my_string out_pntr, my_string in_pntr,
+void soundex(CHARSET_INFO * cs,register my_string out_pntr, my_string in_pntr,
pbool remove_garbage)
{
char ch,last_ch;
reg3 my_string end;
+ register uchar *map=cs->to_upper;
if (remove_garbage)
{
- while (*in_pntr && isspace(*in_pntr)) /* Skipp pre-space */
+ while (*in_pntr && my_isspace(cs,*in_pntr)) /* Skipp pre-space */
in_pntr++;
}
- *out_pntr++ = toupper(*in_pntr); /* Copy first letter */
- last_ch = get_scode(&in_pntr,0); /* code of the first letter */
+ *out_pntr++ = map[(uchar)*in_pntr]; /* Copy first letter */
+ last_ch = get_scode(cs,&in_pntr,0); /* code of the first letter */
/* for the first 'double-letter */
/* check. */
end=out_pntr+3; /* Loop on input letters until */
@@ -59,7 +60,7 @@ void soundex(register my_string out_pntr, my_string in_pntr,
/* letter code count = 3 */
in_pntr++;
- while (out_pntr < end && (ch = get_scode(&in_pntr,remove_garbage)) != 0)
+ while (out_pntr < end && (ch = get_scode(cs,&in_pntr,remove_garbage)) != 0)
{
in_pntr++;
if ((ch != '0') && (ch != last_ch)) /* if not skipped or double */
@@ -81,19 +82,19 @@ void soundex(register my_string out_pntr, my_string in_pntr,
else return 0
*/
-static char get_scode(char **ptr, pbool remove_garbage)
+static char get_scode(CHARSET_INFO * cs,char **ptr, pbool remove_garbage)
{
uchar ch;
if (remove_garbage)
{
- while (**ptr && !isalpha(**ptr))
+ while (**ptr && !my_isalpha(cs,**ptr))
(*ptr)++;
}
- ch=toupper(**ptr);
+ ch=my_toupper(cs,**ptr);
if (ch < 'A' || ch > 'Z')
{
- if (isalpha(ch)) /* If exetended alfa (country spec) */
+ if (my_isalpha(cs,ch)) /* If exetended alfa (country spec) */
return '0'; /* threat as vokal */
return 0; /* Can't map */
}
diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c
new file mode 100644
index 00000000000..1ae034af67d
--- /dev/null
+++ b/mysys/mf_tempdir.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "mysys_priv.h"
+#include <m_string.h>
+
+#if defined( __WIN__) || defined(OS2)
+#define DELIM ';'
+#else
+#define DELIM ':'
+#endif
+
+my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist)
+{
+ char *end, *copy;
+ char buff[FN_REFLEN];
+ DYNAMIC_ARRAY t_arr;
+ pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST);
+ if (my_init_dynamic_array(&t_arr, sizeof(char*), 1, 5))
+ return TRUE;
+ if (!pathlist || !pathlist[0])
+ {
+ /* Get default temporary directory */
+ pathlist=getenv("TMPDIR"); /* Use this if possible */
+#if defined( __WIN__) || defined(OS2)
+ if (!pathlist)
+ pathlist=getenv("TEMP");
+ if (!pathlist)
+ pathlist=getenv("TMP");
+#endif
+ if (!pathlist || !pathlist[0])
+ pathlist=(char*) P_tmpdir;
+ }
+ do
+ {
+ end=strcend(pathlist, DELIM);
+ convert_dirname(buff, pathlist, end);
+ if (!(copy=my_strdup(buff, MYF(MY_WME))))
+ return TRUE;
+ if (insert_dynamic(&t_arr, (gptr)&copy))
+ return TRUE;
+ pathlist=end+1;
+ }
+ while (*end);
+ freeze_size(&t_arr);
+ tmpdir->list=(char **)t_arr.buffer;
+ tmpdir->max=t_arr.elements-1;
+ tmpdir->cur=0;
+ return FALSE;
+}
+
+char *my_tmpdir(MY_TMPDIR *tmpdir)
+{
+ char *dir;
+ pthread_mutex_lock(&tmpdir->mutex);
+ dir=tmpdir->list[tmpdir->cur];
+ tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1;
+ pthread_mutex_unlock(&tmpdir->mutex);
+ return dir;
+}
+
+void free_tmpdir(MY_TMPDIR *tmpdir)
+{
+ uint i;
+ for (i=0; i<=tmpdir->max; i++)
+ my_free(tmpdir->list[i], MYF(0));
+ my_free((gptr)tmpdir->list, MYF(0));
+ pthread_mutex_destroy(&tmpdir->mutex);
+}
+
diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c
index e9e12c72755..3c10de1f238 100644
--- a/mysys/mf_wfile.c
+++ b/mysys/mf_wfile.c
@@ -54,13 +54,6 @@ WF_PACK *wf_comp(my_string str)
for (pos=str ; *pos ; pos++)
ant+= test(*pos == ' ' || *pos == ',');
-#ifdef FN_UPPER_CASE
- caseup(str,(int) (pos-str));
-#endif
-#ifdef FN_LOWER_CASE
- casedn(str,(int) (pos-str));
-#endif
-
if ((ret= (WF_PACK*) my_malloc((uint) ant*(sizeof(my_string*)+2)+
sizeof(WF_PACK)+ (uint) strlen(str)+1,
MYF(MY_WME)))
diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c
index 6b025bca699..e1eb1c00602 100644
--- a/mysys/mulalloc.c
+++ b/mysys/mulalloc.c
@@ -19,16 +19,18 @@
/*
Malloc many pointers at the same time
+ Only ptr1 can be free'd, and doing this will free all
+ the memory allocated. ptr2, etc all point inside big allocated
+ memory area.
SYNOPSIS
my_multi_malloc()
- myFlags Flags
- ... Multiple arguments terminated by null ptr
-
- ptr, length
- ptr, length
+ myFlags Flags
+ ptr1, length1 Multiple arguments terminated by null ptr
+ ptr2, length2 ...
+ ...
NULL
-*/
+*/
gptr my_multi_malloc(myf myFlags, ...)
{
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 5ce061212b5..cd41589f366 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -69,7 +69,7 @@ int my_error(int nr,myf MyFlags, ...)
else
{
/* Skipp if max size is used (to be compatible with printf) */
- while (isdigit(*tpos) || *tpos == '.' || *tpos == '-')
+ while (my_isdigit(system_charset_info, *tpos) || *tpos == '.' || *tpos == '-')
tpos++;
if (*tpos == 'l') /* Skipp 'l' argument */
tpos++;
@@ -120,7 +120,7 @@ int my_error(int nr,myf MyFlags, ...)
... variable list
*/
-int my_printf_error (uint error, const char *format, myf MyFlags, ...)
+int my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index 63ab17b4c51..adf131c5fd0 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -109,7 +109,8 @@ int my_setwd(const char *dir, myf MyFlags)
uint drive,drives;
pos++; /* Skipp FN_DEVCHAR */
- drive=(uint) (toupper(dir[0])-'A'+1); drives= (uint) -1;
+ drive=(uint) (my_toupper(system_charset_info,dir[0])-'A'+1);
+ drives= (uint) -1;
if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32)
{
#ifdef OS2
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
new file mode 100644
index 00000000000..2fd7f1fcdee
--- /dev/null
+++ b/mysys/my_handler.c
@@ -0,0 +1,411 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library 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 */
+
+#include "my_handler.h"
+
+int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
+ uchar *b, uint b_length, my_bool part_key)
+{
+ if (part_key && b_length < a_length)
+ a_length=b_length;
+ return my_strnncoll(charset_info, a, a_length, b, b_length);
+}
+
+static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
+ my_bool part_key)
+{
+ uint length= min(a_length,b_length);
+ uchar *end= a+ length;
+ int flag;
+
+ while (a < end)
+ if ((flag= (int) *a++ - (int) *b++))
+ return flag;
+ if (part_key && b_length < a_length)
+ return 0;
+ return (int) (a_length-b_length);
+}
+
+
+/*
+ Compare two keys
+
+ SYNOPSIS
+ ha_key_cmp()
+ keyseg Key segments of key to compare
+ a First key to compare, in format from _mi_pack_key()
+ This is normally key specified by user
+ b Second key to compare. This is always from a row
+ key_length Length of key to compare. This can be shorter than
+ a to just compare sub keys
+ next_flag How keys should be compared
+ If bit SEARCH_FIND is not set the keys includes the row
+ position and this should also be compared
+
+ NOTES
+ Number-keys can't be splited
+
+ RETURN VALUES
+ <0 If a < b
+ 0 If a == b
+ >0 If a > b
+*/
+
+#define FCMP(A,B) ((int) (A) - (int) (B))
+
+int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
+ register uchar *b, uint key_length, uint nextflag,
+ uint *diff_pos)
+{
+ int flag;
+ int16 s_1,s_2;
+ int32 l_1,l_2;
+ uint32 u_1,u_2;
+ float f_1,f_2;
+ double d_1,d_2;
+ uint next_key_length;
+
+ *diff_pos=0;
+ for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
+ {
+ uchar *end;
+ uint piks=! (keyseg->flag & HA_NO_SORT);
+ (*diff_pos)++;
+
+ /* Handle NULL part */
+ if (keyseg->null_bit)
+ {
+ key_length--;
+ if (*a != *b && piks)
+ {
+ flag = (int) *a - (int) *b;
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ }
+ b++;
+ if (!*a++) /* If key was NULL */
+ {
+ if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
+ nextflag=SEARCH_SAME; /* Allow duplicate keys */
+ else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
+ {
+ /*
+ This is only used from mi_check() to calculate cardinality.
+ It can't be used when searching for a key as this would cause
+ compare of (a,b) and (b,a) to return the same value.
+ */
+ return -1;
+ }
+ next_key_length=key_length;
+ continue; /* To next key part */
+ }
+ }
+ end= a+ min(keyseg->length,key_length);
+ next_key_length=key_length-keyseg->length;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
+ if (keyseg->flag & HA_SPACE_PACK)
+ {
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
+ }
+ else
+ {
+ uint length=(uint) (end-a), a_length=length, b_length=length;
+ if (!(nextflag & SEARCH_PREFIX))
+ {
+ while (a_length && a[a_length-1] == ' ')
+ a_length--;
+ while (b_length && b[b_length-1] == ' ')
+ b_length--;
+ }
+ if (piks &&
+ (flag= mi_compare_text(keyseg->charset, a, a_length, b, b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a=end;
+ b+=length;
+ }
+ break;
+ case HA_KEYTYPE_BINARY:
+ if (keyseg->flag & HA_SPACE_PACK)
+ {
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=compare_bin(a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
+ }
+ else
+ {
+ uint length=keyseg->length;
+ if (piks &&
+ (flag=compare_bin(a,length,b,length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=length;
+ b+=length;
+ }
+ break;
+ case HA_KEYTYPE_VARTEXT:
+ {
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
+ }
+ break;
+ case HA_KEYTYPE_VARBINARY:
+ {
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=compare_bin(a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
+ }
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int i_1= (int) *((signed char*) a);
+ int i_2= (int) *((signed char*) b);
+ if (piks && (flag = CMP_NUM(i_1,i_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b++;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ s_1= mi_sint2korr(a);
+ s_2= mi_sint2korr(b);
+ if (piks && (flag = CMP_NUM(s_1,s_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 2; /* sizeof(short int); */
+ break;
+ case HA_KEYTYPE_USHORT_INT:
+ {
+ uint16 us_1,us_2;
+ us_1= mi_sint2korr(a);
+ us_2= mi_sint2korr(b);
+ if (piks && (flag = CMP_NUM(us_1,us_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+=2; /* sizeof(short int); */
+ break;
+ }
+ case HA_KEYTYPE_LONG_INT:
+ l_1= mi_sint4korr(a);
+ l_2= mi_sint4korr(b);
+ if (piks && (flag = CMP_NUM(l_1,l_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 4; /* sizeof(long int); */
+ break;
+ case HA_KEYTYPE_ULONG_INT:
+ u_1= mi_sint4korr(a);
+ u_2= mi_sint4korr(b);
+ if (piks && (flag = CMP_NUM(u_1,u_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 4; /* sizeof(long int); */
+ break;
+ case HA_KEYTYPE_INT24:
+ l_1=mi_sint3korr(a);
+ l_2=mi_sint3korr(b);
+ if (piks && (flag = CMP_NUM(l_1,l_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 3;
+ break;
+ case HA_KEYTYPE_UINT24:
+ l_1=mi_uint3korr(a);
+ l_2=mi_uint3korr(b);
+ if (piks && (flag = CMP_NUM(l_1,l_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 3;
+ break;
+ case HA_KEYTYPE_FLOAT:
+ mi_float4get(f_1,a);
+ mi_float4get(f_2,b);
+ if (piks && (flag = CMP_NUM(f_1,f_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 4; /* sizeof(float); */
+ break;
+ case HA_KEYTYPE_DOUBLE:
+ mi_float8get(d_1,a);
+ mi_float8get(d_2,b);
+ if (piks && (flag = CMP_NUM(d_1,d_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 8; /* sizeof(double); */
+ break;
+ case HA_KEYTYPE_NUM: /* Numeric key */
+ {
+ int swap_flag= 0;
+ int alength,blength;
+
+ if (keyseg->flag & HA_REVERSE_SORT)
+ {
+ swap(uchar*,a,b);
+ swap_flag=1; /* Remember swap of a & b */
+ end= a+ (int) (end-b);
+ }
+ if (keyseg->flag & HA_SPACE_PACK)
+ {
+ alength= *a++; blength= *b++;
+ end=a+alength;
+ next_key_length=key_length-blength-1;
+ }
+ else
+ {
+ alength= (int) (end-a);
+ blength=keyseg->length;
+ /* remove pre space from keys */
+ for ( ; alength && *a == ' ' ; a++, alength--) ;
+ for ( ; blength && *b == ' ' ; b++, blength--) ;
+ }
+ if (piks)
+ {
+ if (*a == '-')
+ {
+ if (*b != '-')
+ return -1;
+ a++; b++;
+ swap(uchar*,a,b);
+ swap(int,alength,blength);
+ swap_flag=1-swap_flag;
+ alength--; blength--;
+ end=a+alength;
+ }
+ else if (*b == '-')
+ return 1;
+ while (alength && (*a == '+' || *a == '0'))
+ {
+ a++; alength--;
+ }
+ while (blength && (*b == '+' || *b == '0'))
+ {
+ b++; blength--;
+ }
+ if (alength != blength)
+ return (alength < blength) ? -1 : 1;
+ while (a < end)
+ if (*a++ != *b++)
+ return ((int) a[-1] - (int) b[-1]);
+ }
+ else
+ {
+ b+=(end-a);
+ a=end;
+ }
+
+ if (swap_flag) /* Restore pointers */
+ swap(uchar*,a,b);
+ break;
+ }
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ {
+ longlong ll_a,ll_b;
+ ll_a= mi_sint8korr(a);
+ ll_b= mi_sint8korr(b);
+ if (piks && (flag = CMP_NUM(ll_a,ll_b)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 8;
+ break;
+ }
+ case HA_KEYTYPE_ULONGLONG:
+ {
+ ulonglong ll_a,ll_b;
+ ll_a= mi_uint8korr(a);
+ ll_b= mi_uint8korr(b);
+ if (piks && (flag = CMP_NUM(ll_a,ll_b)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+= 8;
+ break;
+ }
+#endif
+ case HA_KEYTYPE_END: /* Ready */
+ goto end; /* diff_pos is incremented */
+ }
+ }
+ (*diff_pos)++;
+end:
+ if (!(nextflag & SEARCH_FIND))
+ {
+ uint i;
+ if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
+ return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
+ flag=0;
+ for (i=keyseg->length ; i-- > 0 ; )
+ {
+ if (*a++ != *b++)
+ {
+ flag= FCMP(a[-1],b[-1]);
+ break;
+ }
+ }
+ if (nextflag & SEARCH_SAME)
+ return (flag); /* read same */
+ if (nextflag & SEARCH_BIGGER)
+ return (flag <= 0 ? -1 : 1); /* read next */
+ return (flag < 0 ? -1 : 1); /* read previous */
+ }
+ return 0;
+} /* ha_key_cmp */
diff --git a/mysys/my_init.c b/mysys/my_init.c
index c6d590fc2aa..e18467b1235 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -17,7 +17,6 @@
#include "mysys_priv.h"
#include "my_static.h"
#include "mysys_err.h"
-#include "m_ctype.h"
#include <m_string.h>
#include <m_ctype.h>
#ifdef HAVE_GETRUSAGE
@@ -53,7 +52,7 @@ my_bool my_init_done=0;
static ulong atoi_octal(const char *str)
{
long int tmp;
- while (*str && isspace(*str))
+ while (*str && my_isspace(system_charset_info, *str))
str++;
str2int(str,
(*str == '0' ? 8 : 10), /* Octalt or decimalt */
@@ -132,6 +131,7 @@ void my_end(int infoflag)
}
}
free_charsets();
+ my_once_free();
if (infoflag & MY_GIVE_INFO || info_file != stderr)
{
#ifdef HAVE_GETRUSAGE
@@ -171,7 +171,6 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
}
#ifdef THREAD
DBUG_POP(); /* Must be done before my_thread_end */
- my_once_free();
my_thread_end();
my_thread_global_end();
#if defined(SAFE_MUTEX)
diff --git a/mysys/my_once.c b/mysys/my_once.c
index 1250ce24994..a4201810b03 100644
--- a/mysys/my_once.c
+++ b/mysys/my_once.c
@@ -23,6 +23,7 @@
#include "mysys_priv.h"
#include "my_static.h"
#include "mysys_err.h"
+#include <m_string.h>
/*
Alloc for things we don't nead to free
@@ -78,6 +79,25 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags)
} /* my_once_alloc */
+char *my_once_strdup(const char *src,myf myflags)
+{
+ uint len=strlen(src)+1;
+ char *dst=my_once_alloc(len, myflags);
+ if (dst)
+ memcpy(dst, src, len);
+ return dst;
+}
+
+
+char *my_once_memdup(const char *src, uint len, myf myflags)
+{
+ char *dst=my_once_alloc(len, myflags);
+ if (dst)
+ memcpy(dst, src, len);
+ return dst;
+}
+
+
/*
Deallocate everything used by my_once_alloc
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index e287930ff06..abef0096e28 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -103,7 +103,8 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#define BUFF_LEN FN_LEN
#endif
-int my_realpath(char *to, const char *filename, myf MyFlags)
+int my_realpath(char *to, const char *filename,
+ myf MyFlags __attribute__((unused)))
{
#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
int result=0;
diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c
deleted file mode 100644
index 7490ab4a9f2..00000000000
--- a/mysys/my_vsnprintf.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Copyright (C) 2000 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU 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 "mysys_priv.h"
-#include "mysys_err.h"
-#include <m_string.h>
-#include <stdarg.h>
-#include <m_ctype.h>
-#include <assert.h>
-
-int my_snprintf(char* to, size_t n, const char* fmt, ...)
-{
- va_list args;
- va_start(args,fmt);
- return my_vsnprintf(to, n, fmt, args);
-}
-
-int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
-{
- char *start=to, *end=to+n-1;
- for (; *fmt ; fmt++)
- {
- if (fmt[0] != '%')
- {
- if (to == end) /* End of buffer */
- break;
- *to++= *fmt; /* Copy ordinary char */
- continue;
- }
- /* Skip if max size is used (to be compatible with printf) */
- fmt++;
- while (isdigit(*fmt) || *fmt == '.' || *fmt == '-')
- fmt++;
- if (*fmt == 'l')
- fmt++;
- if (*fmt == 's') /* String parameter */
- {
- reg2 char *par = va_arg(ap, char *);
- uint plen,left_len = (uint)(end-to);
- if (!par) par = (char*)"(null)";
- plen = (uint) strlen(par);
- if (left_len <= plen)
- plen = left_len - 1;
- to=strnmov(to,par,plen);
- continue;
- }
- else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
- {
- register int iarg;
- if ((uint) (end-to) < 16)
- break;
- iarg = va_arg(ap, int);
- if (*fmt == 'd')
- to=int10_to_str((long) iarg,to, -10);
- else
- to=int10_to_str((long) (uint) iarg,to,10);
- continue;
- }
- /* We come here on '%%', unknown code or too long parameter */
- if (to == end)
- break;
- *to++='%'; /* % used as % or unknown code */
- }
- DBUG_ASSERT(to <= end);
- *to='\0'; /* End of errmessage */
- return (uint) (to - start);
-}
-
-#ifdef MAIN
-#define OVERRUN_SENTRY 250
-static void my_printf(const char * fmt, ...)
-{
- char buf[33];
- int n;
- va_list ar;
- va_start(ar, fmt);
- buf[sizeof(buf)-1]=OVERRUN_SENTRY;
- n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
- printf(buf);
- printf("n=%d, strlen=%d\n", n, strlen(buf));
- if (buf[sizeof(buf)-1] != OVERRUN_SENTRY)
- {
- fprintf(stderr, "Buffer overrun\n");
- abort();
- }
- va_end(ar);
-}
-
-int main()
-{
-
- my_printf("Hello\n");
- my_printf("Hello int, %d\n", 1);
- my_printf("Hello string '%s'\n", "I am a string");
- my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
- my_printf("Hello %d hack %d\n", 1, 4);
- my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
- my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
- my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
- my_printf("Hello %u\n", 1);
- my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
- `%-.64s' (%-.64s)", 1, 0,0,0,0);
- return 0;
-}
-#endif
diff --git a/mysys/queues.c b/mysys/queues.c
index fe642131d74..f077b38ca0b 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -24,7 +24,26 @@
#include <queues.h>
-/* Init queue */
+/*
+ Init queue
+
+ SYNOPSIS
+ init_queue()
+ queue Queue to initialise
+ max_elements Max elements that will be put in queue
+ offset_to_key Offset to key in element stored in queue
+ Used when sending pointers to compare function
+ max_at_top Set to 1 if you want biggest element on top.
+ compare Compare function for elements, takes 3 arguments.
+ first_cmp_arg First argument to compare function
+
+ NOTES
+ Will allocate max_element pointers for queue array
+
+ RETURN
+ 0 ok
+ 1 Could not allocate memory
+*/
int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
pbool max_at_top, int (*compare) (void *, byte *, byte *),
@@ -43,15 +62,32 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
DBUG_RETURN(0);
}
+
/*
- Reinitialize queue for new usage; Note that you can't currently resize
- the number of elements! If you need this, fix it :)
+ Reinitialize queue for other usage (deletes all elements)
+
+ SYNOPSIS
+ reinit_queue()
+ queue Queue to initialise
+ max_elements Max elements that will be put in queue
+ offset_to_key Offset to key in element stored in queue
+ Used when sending pointers to compare function
+ max_at_top Set to 1 if you want biggest element on top.
+ compare Compare function for elements, takes 3 arguments.
+ first_cmp_arg First argument to compare function
+
+ NOTES
+ You can't currently resize the number of elements! If you need this,
+ fix it :)
+
+ RETURN
+ 0 ok
+ EE_OUTOFMEMORY Wrong max_elements
*/
-
int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
- pbool max_at_top, int (*compare) (void *, byte *, byte *),
- void *first_cmp_arg)
+ pbool max_at_top, int (*compare) (void *, byte *, byte *),
+ void *first_cmp_arg)
{
DBUG_ENTER("reinit_queue");
if (queue->max_elements < max_elements)
@@ -66,6 +102,21 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
DBUG_RETURN(0);
}
+
+/*
+ Delete queue
+
+ SYNOPSIS
+ delete_queue()
+ queue Queue to delete
+
+ IMPLEMENTATION
+ Just free allocated memory.
+
+ NOTES
+ Can be called safely multiple times
+*/
+
void delete_queue(QUEUE *queue)
{
DBUG_ENTER("delete_queue");
@@ -116,7 +167,7 @@ byte *queue_remove(register QUEUE *queue, uint idx)
return 0;
#endif
{
- byte *element=queue->root[++idx]; /* Intern index starts from 1 */
+ byte *element=queue->root[++idx]; /* Intern index starts from 1 */
queue->root[idx]=queue->root[queue->elements--];
_downheap(queue,idx);
return element;
@@ -126,8 +177,7 @@ byte *queue_remove(register QUEUE *queue, uint idx)
/* Fix when element on top has been replaced */
#ifndef queue_replaced
-void queue_replaced(queue)
-QUEUE *queue;
+void queue_replaced(QUEUE *queue)
{
_downheap(queue,1);
}
@@ -169,8 +219,8 @@ void _downheap(register QUEUE *queue, uint idx)
static int queue_fix_cmp(QUEUE *queue, void **a, void **b)
{
return queue->compare(queue->first_cmp_arg,
- (char*) (*a)+queue->offset_to_key,
- (char*) (*b)+queue->offset_to_key);
+ (byte*) (*a)+queue->offset_to_key,
+ (byte*) (*b)+queue->offset_to_key);
}
/*
diff --git a/mysys/test_charset.c b/mysys/test_charset.c
index 15e46f3ff82..d031007a1da 100644
--- a/mysys/test_charset.c
+++ b/mysys/test_charset.c
@@ -21,7 +21,38 @@
#include <stdio.h>
-extern void _print_csinfo(CHARSET_INFO *cs);
+static void _print_array(uint8 *data, uint size)
+{
+ uint i;
+ for (i = 0; i < size; ++i)
+ {
+ if (i == 0 || i % 16 == size % 16) printf(" ");
+ printf(" %02x", data[i]);
+ if ((i+1) % 16 == size % 16) printf("\n");
+ }
+}
+
+static void _print_csinfo(CHARSET_INFO *cs)
+{
+ printf("%s #%d\n", cs->name, cs->number);
+ printf("ctype:\n"); _print_array(cs->ctype, 257);
+ printf("to_lower:\n"); _print_array(cs->to_lower, 256);
+ printf("to_upper:\n"); _print_array(cs->to_upper, 256);
+ printf("sort_order:\n"); _print_array(cs->sort_order, 256);
+ printf("collate: %3s (%d, %p, %p, %p)\n",
+ cs->strxfrm_multiply ? "yes" : "no",
+ cs->strxfrm_multiply,
+ cs->strnncoll,
+ cs->strnxfrm,
+ cs->like_range);
+ printf("multi-byte: %3s (%d, %p, %p, %p)\n",
+ cs->mbmaxlen > 1 ? "yes" : "no",
+ cs->mbmaxlen,
+ cs->ismbchar,
+ cs->ismbhead,
+ cs->mbcharlen);
+}
+
int main(int argc, char **argv) {
const char *the_set = MYSQL_CHARSET;
@@ -46,13 +77,13 @@ int main(int argc, char **argv) {
_print_csinfo(default_charset_info);
fflush(stdout);
- cs_list = list_charsets(MYF(MY_COMPILED_SETS | MY_CONFIG_SETS));
+ cs_list = list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG));
printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list);
- free(cs_list);
+ my_free(cs_list,MYF(0));
- cs_list = list_charsets(MYF(MY_INDEX_SETS | MY_LOADED_SETS));
+ cs_list = list_charsets(MYF(MY_CS_INDEX | MY_CS_LOADED));
printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list);
- free(cs_list);
+ my_free(cs_list,MYF(0));
return 0;
}
diff --git a/mysys/test_xml.c b/mysys/test_xml.c
new file mode 100644
index 00000000000..2a679906cbf
--- /dev/null
+++ b/mysys/test_xml.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "my_xml.h"
+
+static void mstr(char *str,const char *src,uint l1,uint l2)
+{
+ l1 = l1<l2 ? l1 : l2;
+ memcpy(str,src,l1);
+ str[l1]='\0';
+}
+
+static int dstr(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ char str[1024];
+
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("VALUE '%s'\n",str);
+ return MY_XML_OK;
+}
+
+static int bstr(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ char str[1024];
+
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("ENTER %s\n",str);
+ return MY_XML_OK;
+}
+
+
+static int estr(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ char str[1024];
+
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("LEAVE %s\n",str);
+ return MY_XML_OK;
+}
+
+static void usage(const char *prog)
+{
+ printf("Usage:\n");
+ printf("%s xmlfile\n",prog);
+}
+
+int main(int ac, char **av)
+{
+ char str[1024*64]="";
+ const char *fn;
+ int f;
+ uint len;
+ MY_XML_PARSER p;
+
+ if (ac<2)
+ {
+ usage(av[0]);
+ return 0;
+ }
+
+ fn=av[1]?av[1]:"test.xml";
+ if ((f=open(fn,O_RDONLY))<0)
+ {
+ fprintf(stderr,"Err '%s'\n",fn);
+ return 1;
+ }
+
+ len=read(f,str,sizeof(str)-1);
+ str[len]='\0';
+
+ my_xml_parser_create(&p);
+
+ my_xml_set_enter_handler(&p,bstr);
+ my_xml_set_value_handler(&p,dstr);
+ my_xml_set_leave_handler(&p,estr);
+
+ if (MY_XML_OK!=(f=my_xml_parse(&p,str,len)))
+ {
+ printf("ERROR at line %d pos %d '%s'\n",
+ my_xml_error_lineno(&p)+1,
+ my_xml_error_pos(&p),
+ my_xml_error_string(&p));
+ }
+
+ my_xml_parser_free(&p);
+
+ return 0;
+}
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 0288c7c1cbe..c796bd1956a 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -91,7 +91,7 @@ enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
#define MAX_LOCKS 100
-static LIST *thread_list; /* List of threads in use */
+LIST *thr_lock_thread_list; /* List of threads in use */
ulong max_write_lock_count= ~(ulong) 0L;
static inline pthread_cond_t *get_cond(void)
@@ -307,7 +307,7 @@ void thr_lock_init(THR_LOCK *lock)
pthread_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */
lock->list.data=(void*) lock;
- thread_list=list_add(thread_list,&lock->list);
+ thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list);
pthread_mutex_unlock(&THR_LOCK_lock);
DBUG_VOID_RETURN;
}
@@ -318,7 +318,7 @@ void thr_lock_delete(THR_LOCK *lock)
DBUG_ENTER("thr_lock_delete");
VOID(pthread_mutex_destroy(&lock->mutex));
pthread_mutex_lock(&THR_LOCK_lock);
- thread_list=list_delete(thread_list,&lock->list);
+ thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list);
pthread_mutex_unlock(&THR_LOCK_lock);
DBUG_VOID_RETURN;
}
@@ -1061,7 +1061,7 @@ void thr_print_locks(void)
pthread_mutex_lock(&THR_LOCK_lock);
puts("Current locks:");
- for (list=thread_list ; list && count++ < MAX_THREADS ; list=rest(list))
+ for (list=thr_lock_thread_list ; list && count++ < MAX_THREADS ; list=rest(list))
{
THR_LOCK *lock=(THR_LOCK*) list->data;
VOID(pthread_mutex_lock(&lock->mutex));
diff --git a/mysys/tree.c b/mysys/tree.c
index ea5cf79f084..a3b69ebff5e 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -17,31 +17,39 @@
/*
Code for handling red-black (balanced) binary trees.
key in tree is allocated accrding to following:
- 1) If free_element function is given to init_tree or size < 0 then tree
- will not allocate keys and only a pointer to each key is saved in tree.
- key_sizes must be 0 to init and search.
+
+ 1) If size < 0 then tree will not allocate keys and only a pointer to
+ each key is saved in tree.
+ compare and search functions uses and returns key-pointer
+
+ 2) If size == 0 then there are two options:
+ - key_size != 0 to tree_insert: The key will be stored in the tree.
+ - key_size == 0 to tree_insert: A pointer to the key is stored.
compare and search functions uses and returns key-pointer.
- 2) if key_size is given to init_tree then each node will continue the
+
+ 3) if key_size is given to init_tree then each node will continue the
key and calls to insert_key may increase length of key.
if key_size > sizeof(pointer) and key_size is a multiple of 8 (double
allign) then key will be put on a 8 alligned adress. Else
the key will be on adress (element+1). This is transparent for user
compare and search functions uses a pointer to given key-argument.
- 3) If init_tree - keysize is 0 then key_size must be given to tree_insert
- and tree_insert will alloc space for key.
- compare and search functions uses a pointer to given key-argument.
+
+ - If you use a free function for tree-elements and you are freeing
+ the element itself, you should use key_size = 0 to init_tree and
+ tree_search
The actual key in TREE_ELEMENT is saved as a pointer or after the
TREE_ELEMENT struct.
If one uses only pointers in tree one can use tree_set_pointer() to
change address of data.
- Copyright Monty Program KB.
- By monty.
+
+ Implemented by monty.
*/
#include "mysys_priv.h"
#include <m_string.h>
#include <my_tree.h>
+#include "my_base.h"
#define BLACK 1
#define RED 0
@@ -87,6 +95,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
tree->custom_arg = custom_arg;
tree->null_element.colour=BLACK;
tree->null_element.left=tree->null_element.right=0;
+ tree->flag= 0;
if (!free_element && size >= 0 &&
((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1))))
{
@@ -169,7 +178,8 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
parent[0] = & parent[-1][0]->right */
-TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
+TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
+ void* custom_arg)
{
int cmp;
TREE_ELEMENT *element,***parent;
@@ -179,8 +189,8 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
for (;;)
{
if (element == &tree->null_element ||
- (cmp=(*tree->compare)(tree->custom_arg,
- ELEMENT_KEY(tree,element),key)) == 0)
+ (cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
+ key)) == 0)
break;
if (cmp < 0)
{
@@ -200,7 +210,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
&& tree->allocated > tree->memory_limit)
{
reset_tree(tree);
- return tree_insert(tree, key, key_size);
+ return tree_insert(tree, key, key_size, custom_arg);
}
key_size+=tree->size_of_element;
@@ -231,13 +241,16 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
rb_insert(tree,parent,element); /* rebalance tree */
}
else
+ {
+ if (tree->flag & TREE_NO_DUPS)
+ return(NULL);
element->count++;
+ }
DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););
return element;
}
-
-int tree_delete(TREE *tree, void *key)
+int tree_delete(TREE *tree, void *key, void *custom_arg)
{
int cmp,remove_colour;
TREE_ELEMENT *element,***parent, ***org_parent, *nod;
@@ -250,8 +263,8 @@ int tree_delete(TREE *tree, void *key)
{
if (element == &tree->null_element)
return 1; /* Was not in tree */
- if ((cmp=(*tree->compare)(tree->custom_arg,
- ELEMENT_KEY(tree,element),key)) == 0)
+ if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
+ key)) == 0)
break;
if (cmp < 0)
{
@@ -298,7 +311,7 @@ int tree_delete(TREE *tree, void *key)
}
-void *tree_search(TREE *tree, void *key)
+void *tree_search(TREE *tree, void *key, void *custom_arg)
{
int cmp;
TREE_ELEMENT *element=tree->root;
@@ -307,8 +320,8 @@ void *tree_search(TREE *tree, void *key)
{
if (element == &tree->null_element)
return (void*) 0;
- if ((cmp=(*tree->compare)(tree->custom_arg,
- ELEMENT_KEY(tree,element),key)) == 0)
+ if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
+ key)) == 0)
return ELEMENT_KEY(tree,element);
if (cmp < 0)
element=element->right;
@@ -317,6 +330,181 @@ void *tree_search(TREE *tree, void *key)
}
}
+void *tree_search_key(TREE *tree, const void *key,
+ TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
+ enum ha_rkey_function flag, void *custom_arg)
+{
+ int cmp;
+ TREE_ELEMENT *element= tree->root;
+ TREE_ELEMENT **last_left_step_parent= NULL, **last_right_step_parent= NULL;
+ TREE_ELEMENT **last_equal_element= NULL;
+
+/*
+ TODO: support for HA_READ_KEY_OR_PREV, HA_READ_PREFIX flags if needed.
+*/
+
+ *parents = &tree->null_element;
+ while (element != &tree->null_element)
+ {
+ *++parents= element;
+ if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element),
+ key)) == 0)
+ {
+ switch (flag) {
+ case HA_READ_KEY_EXACT:
+ case HA_READ_KEY_OR_NEXT:
+ case HA_READ_BEFORE_KEY:
+ last_equal_element= parents;
+ cmp= 1;
+ break;
+ case HA_READ_AFTER_KEY:
+ cmp= -1;
+ break;
+ case HA_READ_PREFIX_LAST:
+ case HA_READ_PREFIX_LAST_OR_PREV:
+ last_equal_element= parents;
+ cmp= -1;
+ break;
+ default:
+ return NULL;
+ }
+ }
+ if (cmp < 0) /* element < key */
+ {
+ last_right_step_parent= parents;
+ element= element->right;
+ }
+ else
+ {
+ last_left_step_parent= parents;
+ element= element->left;
+ }
+ }
+ switch (flag) {
+ case HA_READ_KEY_EXACT:
+ case HA_READ_PREFIX_LAST:
+ *last_pos= last_equal_element;
+ break;
+ case HA_READ_KEY_OR_NEXT:
+ *last_pos= last_equal_element ? last_equal_element : last_left_step_parent;
+ break;
+ case HA_READ_AFTER_KEY:
+ *last_pos= last_left_step_parent;
+ break;
+ case HA_READ_PREFIX_LAST_OR_PREV:
+ *last_pos= last_equal_element ? last_equal_element : last_right_step_parent;
+ break;
+ case HA_READ_BEFORE_KEY:
+ *last_pos= last_right_step_parent;
+ break;
+ default:
+ return NULL;
+ }
+ return *last_pos ? ELEMENT_KEY(tree, **last_pos) : NULL;
+}
+
+/*
+ Search first (the most left) or last (the most right) tree element
+*/
+void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents,
+ TREE_ELEMENT ***last_pos, int child_offs)
+{
+ TREE_ELEMENT *element= tree->root;
+
+ *parents= &tree->null_element;
+ while (element != &tree->null_element)
+ {
+ *++parents= element;
+ element= ELEMENT_CHILD(element, child_offs);
+ }
+ *last_pos= parents;
+ return **last_pos != &tree->null_element ?
+ ELEMENT_KEY(tree, **last_pos) : NULL;
+}
+
+void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
+ int r_offs)
+{
+ TREE_ELEMENT *x= **last_pos;
+
+ if (ELEMENT_CHILD(x, r_offs) != &tree->null_element)
+ {
+ x= ELEMENT_CHILD(x, r_offs);
+ *++*last_pos= x;
+ while (ELEMENT_CHILD(x, l_offs) != &tree->null_element)
+ {
+ x= ELEMENT_CHILD(x, l_offs);
+ *++*last_pos= x;
+ }
+ return ELEMENT_KEY(tree, x);
+ }
+ else
+ {
+ TREE_ELEMENT *y= *--*last_pos;
+ while (y != &tree->null_element && x == ELEMENT_CHILD(y, r_offs))
+ {
+ x= y;
+ y= *--*last_pos;
+ }
+ return y == &tree->null_element ? NULL : ELEMENT_KEY(tree, y);
+ }
+}
+
+/*
+ Expected that tree is fully balanced
+ (each path from root to leaf has the same length)
+*/
+ha_rows tree_record_pos(TREE *tree, const void *key,
+ enum ha_rkey_function flag, void *custom_arg)
+{
+ int cmp;
+ TREE_ELEMENT *element= tree->root;
+ double left= 1;
+ double right= tree->elements_in_tree;
+ ha_rows last_equal_pos= HA_POS_ERROR;
+
+ while (element != &tree->null_element)
+ {
+ if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element),
+ key)) == 0)
+ {
+ switch (flag) {
+ case HA_READ_KEY_EXACT:
+ last_equal_pos= (ha_rows) ((left + right) / 2);
+ cmp= 1;
+ break;
+ case HA_READ_BEFORE_KEY:
+ cmp= 1;
+ break;
+ case HA_READ_AFTER_KEY:
+ cmp= -1;
+ break;
+ default:
+ return HA_POS_ERROR;
+ }
+ }
+ if (cmp < 0) /* element < key */
+ {
+ element= element->right;
+ left= (left + right) / 2;
+ }
+ else
+ {
+ element= element->left;
+ right= (left + right) / 2;
+ }
+ }
+ switch (flag) {
+ case HA_READ_KEY_EXACT:
+ return last_equal_pos;
+ case HA_READ_BEFORE_KEY:
+ return (ha_rows) right;
+ case HA_READ_AFTER_KEY:
+ return (ha_rows) left;
+ default:
+ return HA_POS_ERROR;
+ }
+}
int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit)
{
diff --git a/mysys/typelib.c b/mysys/typelib.c
index e2c8eade5c8..e524f903b5d 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -47,7 +47,9 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name)
find=0;
for (pos=0 ; (j=typelib->type_names[pos]) ; pos++)
{
- for (i=x ; *i && toupper(*i) == toupper(*j) ; i++, j++) ;
+ for (i=x ;
+ *i && my_toupper(system_charset_info,*i) ==
+ my_toupper(system_charset_info,*j) ; i++, j++) ;
if (! *j)
{
while (*i == ' ')
diff --git a/pstack/Makefile.am b/pstack/Makefile.am
index 863a52f4488..77f84d212cd 100644
--- a/pstack/Makefile.am
+++ b/pstack/Makefile.am
@@ -20,7 +20,7 @@
#
SUBDIRS = aout
-INCLUDES = -I$(srcdir)/../include -I../include
+INCLUDES = -I$(top_srcdir)/include
noinst_HEADERS = bucomm.h debug.h ieee.h budbg.h demangle.h \
linuxthreads.h pstack.h pstacktrace.h
SRC= bucomm.c filemode.c linuxthreads.c rddbg.c \
diff --git a/readline/COPYING b/readline/COPYING
deleted file mode 100644
index a43ea2126fb..00000000000
--- a/readline/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19yy name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/readline/INSTALL b/readline/INSTALL
deleted file mode 100644
index 95d84c820fb..00000000000
--- a/readline/INSTALL
+++ /dev/null
@@ -1,176 +0,0 @@
-Basic Installation
-==================
-
- These are generic installation instructions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, a file
-`config.cache' that saves the results of its tests to speed up
-reconfiguring, and a file `config.log' containing compiler output
-(useful mainly for debugging `configure').
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If at some point `config.cache'
-contains results you don't want to keep, you may remove or edit it.
-
- The file `configure.in' is used to create `configure' by a program
-called `autoconf'. You only need `configure.in' if you want to change
-it or regenerate `configure' using a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system. If you're
- using `csh' on an old version of System V, you might need to type
- `sh ./configure' instead to prevent `csh' from trying to execute
- `configure' itself.
-
- Running `configure' takes awhile. While running, it prints some
- messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. You can give `configure'
-initial values for variables by setting them in the environment. Using
-a Bourne-compatible shell, you can do that on the command line like
-this:
- CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
-
-Or on systems that have the `env' program, you can do it like this:
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- If you have to use a `make' that does not supports the `VPATH'
-variable, you have to compile the package for one architecture at a time
-in the source code directory. After you have installed the package for
-one architecture, use `make distclean' before reconfiguring for another
-architecture.
-
-Installation Names
-==================
-
- By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' can not figure out
-automatically, but needs to determine by the type of host the package
-will run on. Usually `configure' can figure that out, but if it prints
-a message saying it can not guess the host type, give it the
-`--host=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name with three fields:
- CPU-COMPANY-SYSTEM
-
-See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the host type.
-
- If you are building compiler tools for cross-compiling, you can also
-use the `--target=TYPE' option to select the type of system they will
-produce code for and the `--build=TYPE' option to select the type of
-system on which you are compiling the package.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Operation Controls
-==================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--cache-file=FILE'
- Use and save the results of the tests in FILE instead of
- `./config.cache'. Set FILE to `/dev/null' to disable caching, for
- debugging `configure'.
-
-`--help'
- Print a summary of the options to `configure', and exit.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made.
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`--version'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`configure' also accepts some other, not widely useful, options.
-
diff --git a/readline/Makefile.am b/readline/Makefile.am
deleted file mode 100644
index 37e97289e6b..00000000000
--- a/readline/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-## Process this file with automake to create Makefile.in
-# Makefile for the GNU readline library.
-# Copyright (C) 1994,1996,1997 Free Software Foundation, Inc.
-
-INCLUDES = -I$(srcdir)/../include -I$(srcdir)/.. -I..
-
-noinst_LIBRARIES = libreadline.a
-
-libreadline_a_SOURCES = readline.c funmap.c keymaps.c \
- vi_mode.c parens.c rltty.c \
- complete.c bind.c isearch.c \
- display.c signals.c \
- util.c kill.c \
- undo.c macro.c input.c \
- callback.c terminal.c xmalloc.c \
- history.c histsearch.c histexpand.c \
- histfile.c nls.c search.c \
- shell.c tilde.c
-
-pkginclude_HEADERS = readline.h chardefs.h keymaps.h history.h tilde.h
-
-noinst_HEADERS = rldefs.h histlib.h rlwinsize.h \
- posixstat.h posixdir.h posixjmp.h \
- tilde.h rlconf.h rltty.h ansi_stdlib.h \
- tcap.h rlstdc.h
-
-EXTRA_DIST= emacs_keymap.c vi_keymap.c
-
-DEFS = -DUNDEF_THREADS_HACK -DHAVE_CONFIG_H -DNO_KILL_INTR
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/readline/README b/readline/README
deleted file mode 100644
index 56565b2fb80..00000000000
--- a/readline/README
+++ /dev/null
@@ -1,163 +0,0 @@
-Introduction
-============
-
-This is the Gnu Readline library, version 4.0.
-
-The Readline library provides a set of functions for use by applications
-that allow users to edit command lines as they are typed in. Both
-Emacs and vi editing modes are available. The Readline library includes
-additional functions to maintain a list of previously-entered command
-lines, to recall and perhaps reedit those lines, and perform csh-like
-history expansion on previous commands.
-
-The history facilites are also placed into a separate library, the
-History library, as part of the build process. The History library
-may be used without Readline in applications which desire its
-capabilities.
-
-The Readline library is free software, distributed under the terms of
-the GNU Public License, version 2. For more information, see the file
-COPYING.
-
-To build the library, try typing `./configure', then `make'. The
-configuration process is automated, so no further intervention should
-be necessary. Readline builds with `gcc' by default if it is
-available. If you want to use `cc' instead, type
-
- CC=cc ./configure
-
-if you are using a Bourne-style shell. If you are not, the following
-may work:
-
- env CC=cc ./configure
-
-Read the file INSTALL in this directory for more information about how
-to customize and control the build process.
-
-The file rlconf.h contains C preprocessor defines that enable and disable
-certain Readline features.
-
-Examples
-========
-
-There are several example programs that use Readline features in the
-examples directory. The `rl' program is of particular interest. It
-is a command-line interface to Readline, suitable for use in shell
-scripts in place of `read'.
-
-Shared Libraries
-================
-
-There is skeletal support for building shared versions of the
-Readline and History libraries. The configure script creates
-a Makefile in the `shlib' subdirectory, and typing `make shared'
-will cause shared versions of the Readline and History libraries
-to be built on supported platforms.
-
-Configure calls the script support/shobj-conf to test whether or
-not shared library creation is supported and to generate the values
-of variables that are substituted into shlib/Makefile. If you
-try to build shared libraries on an unsupported platform, `make'
-will display a message asking you to update support/shobj-conf for
-your platform.
-
-If you need to update support/shobj-conf, you will need to create
-a `stanza' for your operating system and compiler. The script uses
-the value of host_os and ${CC} as determined by configure. For
-instance, FreeBSD 2.2.5 with any version of gcc is identified as
-`freebsd2.2.5-gcc*'.
-
-In the stanza for your operating system-compiler pair, you will need to
-define several variables. They are:
-
-SHOBJ_CC The C compiler used to compile source files into shareable
- object files. This is normally set to the value of ${CC}
- by configure, and should not need to be changed.
-
-SHOBJ_CFLAGS Flags to pass to the C compiler ($SHOBJ_CC) to create
- position-independent code. If you are using gcc, this
- should probably be set to `-fpic'.
-
-SHOBJ_LD The link editor to be used to create the shared library from
- the object files created by $SHOBJ_CC. If you are using
- gcc, a value of `gcc' will probably work.
-
-SHOBJ_LDFLAGS Flags to pass to SHOBJ_LD to enable shared object creation.
- If you are using gcc, `-shared' may be all that is necessary.
- These should be the flags needed for generic shared object
- creation.
-
-SHLIB_XLDFLAGS Additional flags to pass to SHOBJ_LD for shared library
- creation. Many systems use the -R option to the link
- editor to embed a path within the library for run-time
- library searches. A reasonable value for such systems would
- be `-R$(libdir)'.
-
-SHLIB_LIBS Any additional libraries that shared libraries should be
- linked against when they are created.
-
-SHLIB_LIBSUFF The suffix to add to `libreadline' and `libhistory' when
- generating the filename of the shared library. Many systems
- use `so'; HP-UX uses `sl'.
-
-SHLIB_LIBVERSION The string to append to the filename to indicate the version
- of the shared library. It should begin with $(SHLIB_LIBSUFF),
- and possibly include version information that allows the
- run-time loader to load the version of the shared library
- appropriate for a particular program. Systems using shared
- libraries similar to SunOS 4.x use major and minor library
- version numbers; for those systems a value of
- `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' is appropriate.
- Systems based on System V Release 4 don't use minor version
- numbers; use `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' on those systems.
- Other Unix versions use different schemes.
-
-SHLIB_STATUS Set this to `supported' when you have defined the other
- necessary variables. Make uses this to determine whether
- or not shared library creation should be attempted.
-
-You should look at the existing stanzas in support/shobj-conf for ideas.
-
-Once you have updated support/shobj-conf, re-run configure and type
-`make shared'. The shared libraries will be created in the shlib
-subdirectory.
-
-Since shared libraries are not created on all platforms, `make install'
-will not automatically install the shared libraries. To install them,
-change the current directory to shlib and type `make install'. Running
-`make install-shared' from the top-level build directory will also work.
-
-Documentation
-=============
-
-The documentation for the Readline and History libraries appears in the
-`doc' subdirectory. There are two texinfo files and a Unix-style manual
-page describing the programming facilities available in the Readline
-library. The texinfo files include both user and programmer's manuals.
-
-Reporting Bugs
-==============
-
-Bug reports for Readline should be sent to:
-
- bug-readline@gnu.org
-
-When reporting a bug, please include the following information:
-
- * the version number and release status of Readline (e.g., 4.0-release)
- * the machine and OS that it is running on
- * a list of the compilation flags or the contents of `config.h', if
- appropriate
- * a description of the bug
- * a recipe for recreating the bug reliably
- * a fix for the bug if you have one!
-
-If you would like to contact the Readline maintainer directly, send mail
-to bash-maintainers@gnu.org.
-
-Since Readline is developed along with bash, the bug-bash@gnu.org mailing
-list (mirrored to the Usenet newsgroup gnu.bash.bug) often contains
-Readline bug reports and fixes.
-
-Chet Ramey
-chet@po.cwru.edu
diff --git a/readline/ansi_stdlib.h b/readline/ansi_stdlib.h
deleted file mode 100644
index 52339da5d33..00000000000
--- a/readline/ansi_stdlib.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
-/* A minimal stdlib.h containing extern declarations for those functions
- that bash uses. */
-
-/* Copyright (C) 1993 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2, or (at your option) any later
- version.
-
- Bash is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License along
- with Bash; see the file COPYING. If not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_STDLIB_H_)
-#define _STDLIB_H_ 1
-
-/* String conversion functions. */
-extern int atoi ();
-extern long int atol ();
-
-/* Memory allocation functions. */
-extern char *malloc ();
-extern char *realloc ();
-extern void free ();
-
-/* Other miscellaneous functions. */
-extern void abort ();
-extern void exit ();
-extern char *getenv ();
-extern void qsort ();
-
-#endif /* _STDLIB_H */
diff --git a/readline/bind.c b/readline/bind.c
deleted file mode 100644
index f122bdf4860..00000000000
--- a/readline/bind.c
+++ /dev/null
@@ -1,1991 +0,0 @@
-/* bind.c -- key binding and startup file support for the readline library. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* HAVE_SYS_FILE_H */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <signal.h>
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#include "posixstat.h"
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-extern int _rl_horizontal_scroll_mode;
-extern int _rl_mark_modified_lines;
-extern int _rl_bell_preference;
-extern int _rl_meta_flag;
-extern int _rl_convert_meta_chars_to_ascii;
-extern int _rl_output_meta_chars;
-extern int _rl_complete_show_all;
-extern int _rl_complete_mark_directories;
-extern int _rl_print_completions_horizontally;
-extern int _rl_completion_case_fold;
-extern int _rl_enable_keypad;
-#if defined (PAREN_MATCHING)
-extern int rl_blink_matching_paren;
-#endif /* PAREN_MATCHING */
-#if defined (VISIBLE_STATS)
-extern int rl_visible_stats;
-#endif /* VISIBLE_STATS */
-extern int rl_complete_with_tilde_expansion;
-extern int rl_completion_query_items;
-extern int rl_inhibit_completion;
-extern char *_rl_comment_begin;
-extern unsigned char *_rl_isearch_terminators;
-
-extern int rl_explicit_arg;
-extern int rl_editing_mode;
-extern unsigned char _rl_parsing_conditionalized_out;
-extern Keymap _rl_keymap;
-
-extern char *possible_control_prefixes[], *possible_meta_prefixes[];
-
-/* Functions imported from funmap.c */
-extern char **rl_funmap_names ();
-extern int rl_add_funmap_entry ();
-
-/* Functions imported from util.c */
-extern char *_rl_strindex ();
-
-/* Functions imported from shell.c */
-extern char *get_env_value ();
-
-/* Variables exported by this file. */
-Keymap rl_binding_keymap;
-
-/* Forward declarations */
-void rl_set_keymap_from_edit_mode ();
-
-static int _rl_read_init_file (const char *filename, int include_level);
-static int glean_key_from_name ();
-static int substring_member_of_array ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Binding keys */
-/* */
-/* **************************************************************** */
-
-/* rl_add_defun (char *name, Function *function, int key)
- Add NAME to the list of named functions. Make FUNCTION be the function
- that gets called. If KEY is not -1, then bind it. */
-int
-rl_add_defun (name, function, key)
- char *name;
- Function *function;
- int key;
-{
- if (key != -1)
- rl_bind_key (key, function);
- rl_add_funmap_entry (name, function);
- return 0;
-}
-
-/* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */
-int
-rl_bind_key (key, function)
- int key;
- Function *function;
-{
- if (key < 0)
- return (key);
-
- if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
- {
- if (_rl_keymap[ESC].type == ISKMAP)
- {
- Keymap escmap;
-
- escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
- key = UNMETA (key);
- escmap[key].type = ISFUNC;
- escmap[key].function = function;
- return (0);
- }
- return (key);
- }
-
- _rl_keymap[key].type = ISFUNC;
- _rl_keymap[key].function = function;
- rl_binding_keymap = _rl_keymap;
- return (0);
-}
-
-/* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid
- KEY. */
-int
-rl_bind_key_in_map (key, function, map)
- int key;
- Function *function;
- Keymap map;
-{
- int result;
- Keymap oldmap;
-
- oldmap = _rl_keymap;
- _rl_keymap = map;
- result = rl_bind_key (key, function);
- _rl_keymap = oldmap;
- return (result);
-}
-
-/* Make KEY do nothing in the currently selected keymap.
- Returns non-zero in case of error. */
-int
-rl_unbind_key (key)
- int key;
-{
- return (rl_bind_key (key, (Function *)NULL));
-}
-
-/* Make KEY do nothing in MAP.
- Returns non-zero in case of error. */
-int
-rl_unbind_key_in_map (key, map)
- int key;
- Keymap map;
-{
- return (rl_bind_key_in_map (key, (Function *)NULL, map));
-}
-
-/* Unbind all keys bound to FUNCTION in MAP. */
-int
-rl_unbind_function_in_map (func, map)
- Function *func;
- Keymap map;
-{
- register int i, rval;
-
- for (i = rval = 0; i < KEYMAP_SIZE; i++)
- {
- if (map[i].type == ISFUNC && map[i].function == func)
- {
- map[i].function = (Function *)NULL;
- rval = 1;
- }
- }
- return rval;
-}
-
-int
-rl_unbind_command_in_map (command, map)
- char *command;
- Keymap map;
-{
- Function *func;
-
- func = rl_named_function (command);
- if (func == 0)
- return 0;
- return (rl_unbind_function_in_map (func, map));
-}
-
-/* Bind the key sequence represented by the string KEYSEQ to
- FUNCTION. This makes new keymaps as necessary. The initial
- place to do bindings is in MAP. */
-int
-rl_set_key (keyseq, function, map)
- char *keyseq;
- Function *function;
- Keymap map;
-{
- return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
-}
-
-/* Bind the key sequence represented by the string KEYSEQ to
- the string of characters MACRO. This makes new keymaps as
- necessary. The initial place to do bindings is in MAP. */
-int
-rl_macro_bind (keyseq, macro, map)
- char *keyseq, *macro;
- Keymap map;
-{
- char *macro_keys;
- int macro_keys_len;
-
- macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
-
- if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
- {
- free (macro_keys);
- return -1;
- }
- rl_generic_bind (ISMACR, keyseq, macro_keys, map);
- return 0;
-}
-
-/* Bind the key sequence represented by the string KEYSEQ to
- the arbitrary pointer DATA. TYPE says what kind of data is
- pointed to by DATA, right now this can be a function (ISFUNC),
- a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps
- as necessary. The initial place to do bindings is in MAP. */
-int
-rl_generic_bind (type, keyseq, data, map)
- int type;
- char *keyseq, *data;
- Keymap map;
-{
- char *keys;
- int keys_len;
- register int i;
-
- /* If no keys to bind to, exit right away. */
- if (!keyseq || !*keyseq)
- {
- if (type == ISMACR)
- free (data);
- return -1;
- }
-
- keys = xmalloc (1 + (2 * strlen (keyseq)));
-
- /* Translate the ASCII representation of KEYSEQ into an array of
- characters. Stuff the characters into KEYS, and the length of
- KEYS into KEYS_LEN. */
- if (rl_translate_keyseq (keyseq, keys, &keys_len))
- {
- free (keys);
- return -1;
- }
-
- /* Bind keys, making new keymaps as necessary. */
- for (i = 0; i < keys_len; i++)
- {
- int ic = (int) ((unsigned char)keys[i]);
-
- if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
- {
- ic = UNMETA (ic);
- if (map[ESC].type == ISKMAP)
- map = FUNCTION_TO_KEYMAP (map, ESC);
- }
-
- if ((i + 1) < keys_len)
- {
- if (map[ic].type != ISKMAP)
- {
- if (map[ic].type == ISMACR)
- free ((char *)map[ic].function);
-
- map[ic].type = ISKMAP;
- map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
- }
- map = FUNCTION_TO_KEYMAP (map, ic);
- }
- else
- {
- if (map[ic].type == ISMACR)
- free ((char *)map[ic].function);
-
- map[ic].function = KEYMAP_TO_FUNCTION (data);
- map[ic].type = type;
- }
-
- rl_binding_keymap = map;
- }
- free (keys);
- return 0;
-}
-
-/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
- an array of characters. LEN gets the final length of ARRAY. Return
- non-zero if there was an error parsing SEQ. */
-int
-rl_translate_keyseq (seq, array, len)
- char *seq, *array;
- int *len;
-{
- register int i, c, l, temp;
-
- for (i = l = 0; (c = seq[i]); i++)
- {
- if (c == '\\')
- {
- c = seq[++i];
-
- if (c == 0)
- break;
-
- /* Handle \C- and \M- prefixes. */
- if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
- {
- /* Handle special case of backwards define. */
- if (strncmp (&seq[i], "C-\\M-", 5) == 0)
- {
- array[l++] = ESC;
- i += 5;
- array[l++] = CTRL (_rl_to_upper (seq[i]));
- if (seq[i] == '\0')
- i--;
- }
- else if (c == 'M')
- {
- i++;
- array[l++] = ESC; /* XXX */
- }
- else if (c == 'C')
- {
- i += 2;
- /* Special hack for C-?... */
- array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
- }
- continue;
- }
-
- /* Translate other backslash-escaped characters. These are the
- same escape sequences that bash's `echo' and `printf' builtins
- handle, with the addition of \d -> RUBOUT. A backslash
- preceding a character that is not special is stripped. */
- switch (c)
- {
- case 'a':
- array[l++] = '\007';
- break;
- case 'b':
- array[l++] = '\b';
- break;
- case 'd':
- array[l++] = RUBOUT; /* readline-specific */
- break;
- case 'e':
- array[l++] = ESC;
- break;
- case 'f':
- array[l++] = '\f';
- break;
- case 'n':
- array[l++] = NEWLINE;
- break;
- case 'r':
- array[l++] = RETURN;
- break;
- case 't':
- array[l++] = TAB;
- break;
- case 'v':
- array[l++] = 0x0B;
- break;
- case '\\':
- array[l++] = '\\';
- break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- i++;
- for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++)
- c = (c * 8) + OCTVALUE (seq[i]);
- i--; /* auto-increment in for loop */
- array[l++] = c % (largest_char + 1);
- break;
- case 'x':
- i++;
- for (temp = 3, c = 0; isxdigit (seq[i]) && temp--; i++)
- c = (c * 16) + HEXVALUE (seq[i]);
- if (temp == 3)
- c = 'x';
- i--; /* auto-increment in for loop */
- array[l++] = c % (largest_char + 1);
- break;
- default: /* backslashes before non-special chars just add the char */
- array[l++] = c;
- break; /* the backslash is stripped */
- }
- continue;
- }
-
- array[l++] = c;
- }
-
- *len = l;
- array[l] = '\0';
- return (0);
-}
-
-char *
-rl_untranslate_keyseq (seq)
- int seq;
-{
- static char kseq[16];
- int i, c;
-
- i = 0;
- c = seq;
- if (META_CHAR (c))
- {
- kseq[i++] = '\\';
- kseq[i++] = 'M';
- kseq[i++] = '-';
- c = UNMETA (c);
- }
- else if (CTRL_CHAR (c))
- {
- kseq[i++] = '\\';
- kseq[i++] = 'C';
- kseq[i++] = '-';
- c = _rl_to_lower (UNCTRL (c));
- }
- else if (c == RUBOUT)
- {
- kseq[i++] = '\\';
- kseq[i++] = 'C';
- kseq[i++] = '-';
- c = '?';
- }
-
- if (c == ESC)
- {
- kseq[i++] = '\\';
- c = 'e';
- }
- else if (c == '\\' || c == '"')
- {
- kseq[i++] = '\\';
- }
-
- kseq[i++] = (unsigned char) c;
- kseq[i] = '\0';
- return kseq;
-}
-
-static char *
-_rl_untranslate_macro_value (seq)
- char *seq;
-{
- char *ret, *r, *s;
- int c;
-
- r = ret = xmalloc (7 * strlen (seq) + 1);
- for (s = seq; *s; s++)
- {
- c = *s;
- if (META_CHAR (c))
- {
- *r++ = '\\';
- *r++ = 'M';
- *r++ = '-';
- c = UNMETA (c);
- }
- else if (CTRL_CHAR (c) && c != ESC)
- {
- *r++ = '\\';
- *r++ = 'C';
- *r++ = '-';
- c = _rl_to_lower (UNCTRL (c));
- }
- else if (c == RUBOUT)
- {
- *r++ = '\\';
- *r++ = 'C';
- *r++ = '-';
- c = '?';
- }
-
- if (c == ESC)
- {
- *r++ = '\\';
- c = 'e';
- }
- else if (c == '\\' || c == '"')
- *r++ = '\\';
-
- *r++ = (unsigned char)c;
- }
- *r = '\0';
- return ret;
-}
-
-/* Return a pointer to the function that STRING represents.
- If STRING doesn't have a matching function, then a NULL pointer
- is returned. */
-Function *
-rl_named_function (string)
- char *string;
-{
- register int i;
-
- rl_initialize_funmap ();
-
- for (i = 0; funmap[i]; i++)
- if (_rl_stricmp (funmap[i]->name, string) == 0)
- return (funmap[i]->function);
- return ((Function *)NULL);
-}
-
-/* Return the function (or macro) definition which would be invoked via
- KEYSEQ if executed in MAP. If MAP is NULL, then the current keymap is
- used. TYPE, if non-NULL, is a pointer to an int which will receive the
- type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap),
- or ISMACR (macro). */
-Function *
-rl_function_of_keyseq (const char *keyseq, Keymap map, int *type)
-{
- register int i;
-
- if (!map)
- map = _rl_keymap;
-
- for (i = 0; keyseq && keyseq[i]; i++)
- {
- int ic = keyseq[i];
-
- if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
- {
- if (map[ESC].type != ISKMAP)
- {
- if (type)
- *type = map[ESC].type;
-
- return (map[ESC].function);
- }
- else
- {
- map = FUNCTION_TO_KEYMAP (map, ESC);
- ic = UNMETA (ic);
- }
- }
-
- if (map[ic].type == ISKMAP)
- {
- /* If this is the last key in the key sequence, return the
- map. */
- if (!keyseq[i + 1])
- {
- if (type)
- *type = ISKMAP;
-
- return (map[ic].function);
- }
- else
- map = FUNCTION_TO_KEYMAP (map, ic);
- }
- else
- {
- if (type)
- *type = map[ic].type;
-
- return (map[ic].function);
- }
- }
- return ((Function *) NULL);
-}
-
-/* The last key bindings file read. */
-static char *last_readline_init_file = (char *)NULL;
-
-/* The file we're currently reading key bindings from. */
-static const char *current_readline_init_file;
-static int current_readline_init_include_level;
-static int current_readline_init_lineno;
-
-/* Read FILENAME into a locally-allocated buffer and return the buffer.
- The size of the buffer is returned in *SIZEP. Returns NULL if any
- errors were encountered. */
-static char *
-_rl_read_file (filename, sizep)
- char *filename;
- size_t *sizep;
-{
- struct stat finfo;
- size_t file_size;
- char *buffer;
- int i, file;
-
- if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
- return ((char *)NULL);
-
- file_size = (size_t)finfo.st_size;
-
- /* check for overflow on very large files */
- if (file_size != finfo.st_size || file_size + 1 < file_size)
- {
- if (file >= 0)
- close (file);
-#if defined (EFBIG)
- errno = EFBIG;
-#endif
- return ((char *)NULL);
- }
-
- /* Read the file into BUFFER. */
- buffer = (char *)xmalloc (file_size + 1);
- i = read (file, buffer, file_size);
- close (file);
-
-#if 0
- if (i < file_size)
-#else
- if (i < 0)
-#endif
- {
- free (buffer);
- return ((char *)NULL);
- }
-
- buffer[file_size] = '\0';
- if (sizep)
- *sizep = file_size;
- return (buffer);
-}
-
-/* Re-read the current keybindings file. */
-int
-rl_re_read_init_file (int count __attribute__((unused)),
- int ignore __attribute__((unused)))
-{
- int r;
- r = rl_read_init_file ((char *)NULL);
- rl_set_keymap_from_edit_mode ();
- return r;
-}
-
-/* Do key bindings from a file. If FILENAME is NULL it defaults
- to the first non-null filename from this list:
- 1. the filename used for the previous call
- 2. the value of the shell variable `INPUTRC'
- 3. ~/.inputrc
- If the file existed and could be opened and read, 0 is returned,
- otherwise errno is returned. */
-int
-rl_read_init_file (const char *filename)
-{
- /* Default the filename. */
- if (filename == 0)
- {
- filename = last_readline_init_file;
- if (filename == 0)
- filename = get_env_value ("INPUTRC");
- if (filename == 0)
- filename = DEFAULT_INPUTRC;
- }
-
- if (*filename == 0)
- filename = DEFAULT_INPUTRC;
-
- return (_rl_read_init_file (filename, 0));
-}
-
-static int
-_rl_read_init_file (const char *filename, int include_level)
-{
- register int i;
- char *buffer, *openname, *line, *end;
- size_t file_size;
-
- current_readline_init_file = filename;
- current_readline_init_include_level = include_level;
-
- openname = tilde_expand (filename);
- buffer = _rl_read_file (openname, &file_size);
- free (openname);
-
- if (buffer == 0)
- return (errno);
-
- if (include_level == 0 && filename != last_readline_init_file)
- {
- FREE (last_readline_init_file);
- last_readline_init_file = savestring (filename);
- }
-
- /* Loop over the lines in the file. Lines that start with `#' are
- comments; all other lines are commands for readline initialization. */
- current_readline_init_lineno = 1;
- line = buffer;
- end = buffer + file_size;
- while (line < end)
- {
- /* Find the end of this line. */
- for (i = 0; line + i != end && line[i] != '\n'; i++);
-
- /* Mark end of line. */
- line[i] = '\0';
-
- /* Skip leading whitespace. */
- while (*line && whitespace (*line))
- {
- line++;
- i--;
- }
-
- /* If the line is not a comment, then parse it. */
- if (*line && *line != '#')
- rl_parse_and_bind (line);
-
- /* Move to the next line. */
- line += i + 1;
- current_readline_init_lineno++;
- }
-
- free (buffer);
- return (0);
-}
-
-static void
-_rl_init_file_error (msg)
- char *msg;
-{
- fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
- current_readline_init_lineno,
- msg);
-}
-
-/* **************************************************************** */
-/* */
-/* Parser Directives */
-/* */
-/* **************************************************************** */
-
-/* Conditionals. */
-
-/* Calling programs set this to have their argv[0]. */
-const char *rl_readline_name = "other";
-
-/* Stack of previous values of parsing_conditionalized_out. */
-static unsigned char *if_stack = (unsigned char *)NULL;
-static int if_stack_depth;
-static int if_stack_size;
-
-/* Push _rl_parsing_conditionalized_out, and set parser state based
- on ARGS. */
-static int
-parser_if (args)
- char *args;
-{
- register int i;
-
- /* Push parser state. */
- if (if_stack_depth + 1 >= if_stack_size)
- {
- if (!if_stack)
- if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
- else
- if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
- }
- if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
-
- /* If parsing is turned off, then nothing can turn it back on except
- for finding the matching endif. In that case, return right now. */
- if (_rl_parsing_conditionalized_out)
- return 0;
-
- /* Isolate first argument. */
- for (i = 0; args[i] && !whitespace (args[i]); i++);
-
- if (args[i])
- args[i++] = '\0';
-
- /* Handle "$if term=foo" and "$if mode=emacs" constructs. If this
- isn't term=foo, or mode=emacs, then check to see if the first
- word in ARGS is the same as the value stored in rl_readline_name. */
- if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
- {
- char *tem, *tname;
-
- /* Terminals like "aaa-60" are equivalent to "aaa". */
- tname = savestring (rl_terminal_name);
- tem = strchr (tname, '-');
- if (tem)
- *tem = '\0';
-
- /* Test the `long' and `short' forms of the terminal name so that
- if someone has a `sun-cmd' and does not want to have bindings
- that will be executed if the terminal is a `sun', they can put
- `$if term=sun-cmd' into their .inputrc. */
- _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
- _rl_stricmp (args + 5, rl_terminal_name);
- free (tname);
- }
-#if defined (VI_MODE)
- else if (_rl_strnicmp (args, "mode=", 5) == 0)
- {
- int mode;
-
- if (_rl_stricmp (args + 5, "emacs") == 0)
- mode = emacs_mode;
- else if (_rl_stricmp (args + 5, "vi") == 0)
- mode = vi_mode;
- else
- mode = no_mode;
-
- _rl_parsing_conditionalized_out = mode != rl_editing_mode;
- }
-#endif /* VI_MODE */
- /* Check to see if the first word in ARGS is the same as the
- value stored in rl_readline_name. */
- else if (_rl_stricmp (args, rl_readline_name) == 0)
- _rl_parsing_conditionalized_out = 0;
- else
- _rl_parsing_conditionalized_out = 1;
- return 0;
-}
-
-/* Invert the current parser state if there is anything on the stack. */
-static int
-parser_else (args)
-char *args __attribute__((unused));
-{
- register int i;
-
- if (if_stack_depth == 0)
- {
- _rl_init_file_error ("$else found without matching $if");
- return 0;
- }
-
- /* Check the previous (n - 1) levels of the stack to make sure that
- we haven't previously turned off parsing. */
- for (i = 0; i < if_stack_depth - 1; i++)
- if (if_stack[i] == 1)
- return 0;
-
- /* Invert the state of parsing if at top level. */
- _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
- return 0;
-}
-
-/* Terminate a conditional, popping the value of
- _rl_parsing_conditionalized_out from the stack. */
-static int
-parser_endif (args)
-char *args __attribute__((unused));
-{
- if (if_stack_depth)
- _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
- else
- _rl_init_file_error ("$endif without matching $if");
- return 0;
-}
-
-static int
-parser_include (args)
- char *args;
-{
- const char *old_init_file;
- char *e;
- int old_line_number, old_include_level, r;
-
- if (_rl_parsing_conditionalized_out)
- return (0);
-
- old_init_file = current_readline_init_file;
- old_line_number = current_readline_init_lineno;
- old_include_level = current_readline_init_include_level;
-
- e = strchr (args, '\n');
- if (e)
- *e = '\0';
- r = _rl_read_init_file (args, old_include_level + 1);
-
- current_readline_init_file = old_init_file;
- current_readline_init_lineno = old_line_number;
- current_readline_init_include_level = old_include_level;
-
- return r;
-}
-
-/* Associate textual names with actual functions. */
-static struct {
- const char *name;
- Function *function;
-} parser_directives [] = {
- { "if", parser_if },
- { "endif", parser_endif },
- { "else", parser_else },
- { "include", parser_include },
- { (char *)0x0, (Function *)0x0 }
-};
-
-/* Handle a parser directive. STATEMENT is the line of the directive
- without any leading `$'. */
-static int
-handle_parser_directive (statement)
- char *statement;
-{
- register int i;
- char *directive, *args;
-
- /* Isolate the actual directive. */
-
- /* Skip whitespace. */
- for (i = 0; whitespace (statement[i]); i++);
-
- directive = &statement[i];
-
- for (; statement[i] && !whitespace (statement[i]); i++);
-
- if (statement[i])
- statement[i++] = '\0';
-
- for (; statement[i] && whitespace (statement[i]); i++);
-
- args = &statement[i];
-
- /* Lookup the command, and act on it. */
- for (i = 0; parser_directives[i].name; i++)
- if (_rl_stricmp (directive, parser_directives[i].name) == 0)
- {
- (*parser_directives[i].function) (args);
- return (0);
- }
-
- /* display an error message about the unknown parser directive */
- _rl_init_file_error ("unknown parser directive");
- return (1);
-}
-
-/* Read the binding command from STRING and perform it.
- A key binding command looks like: Keyname: function-name\0,
- a variable binding command looks like: set variable value.
- A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
-int
-rl_parse_and_bind (string)
- char *string;
-{
- char *funname, *kname;
- register int c, i;
- int key, equivalency;
-
- while (string && whitespace (*string))
- string++;
-
- if (!string || !*string || *string == '#')
- return 0;
-
- /* If this is a parser directive, act on it. */
- if (*string == '$')
- {
- handle_parser_directive (&string[1]);
- return 0;
- }
-
- /* If we aren't supposed to be parsing right now, then we're done. */
- if (_rl_parsing_conditionalized_out)
- return 0;
-
- i = 0;
- /* If this keyname is a complex key expression surrounded by quotes,
- advance to after the matching close quote. This code allows the
- backslash to quote characters in the key expression. */
- if (*string == '"')
- {
- int passc = 0;
-
- for (i = 1; (c = string[i]); i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
-
- if (c == '\\')
- {
- passc++;
- continue;
- }
-
- if (c == '"')
- break;
- }
- /* If we didn't find a closing quote, abort the line. */
- if (string[i] == '\0')
- {
- _rl_init_file_error ("no closing `\"' in key binding");
- return 1;
- }
- }
-
- /* Advance to the colon (:) or whitespace which separates the two objects. */
- for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
-
- equivalency = (c == ':' && string[i + 1] == '=');
-
- /* Mark the end of the command (or keyname). */
- if (string[i])
- string[i++] = '\0';
-
- /* If doing assignment, skip the '=' sign as well. */
- if (equivalency)
- string[i++] = '\0';
-
- /* If this is a command to set a variable, then do that. */
- if (_rl_stricmp (string, "set") == 0)
- {
- char *var = string + i;
- char *value;
-
- /* Make VAR point to start of variable name. */
- while (*var && whitespace (*var)) var++;
-
- /* Make value point to start of value string. */
- value = var;
- while (*value && !whitespace (*value)) value++;
- if (*value)
- *value++ = '\0';
- while (*value && whitespace (*value)) value++;
-
- rl_variable_bind (var, value);
- return 0;
- }
-
- /* Skip any whitespace between keyname and funname. */
- for (; string[i] && whitespace (string[i]); i++);
- funname = &string[i];
-
- /* Now isolate funname.
- For straight function names just look for whitespace, since
- that will signify the end of the string. But this could be a
- macro definition. In that case, the string is quoted, so skip
- to the matching delimiter. We allow the backslash to quote the
- delimiter characters in the macro body. */
- /* This code exists to allow whitespace in macro expansions, which
- would otherwise be gobbled up by the next `for' loop.*/
- /* XXX - it may be desirable to allow backslash quoting only if " is
- the quoted string delimiter, like the shell. */
- if (*funname == '\'' || *funname == '"')
- {
- int delimiter = string[i++], passc;
-
- for (passc = 0; (c = string[i]); i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
-
- if (c == '\\')
- {
- passc = 1;
- continue;
- }
-
- if (c == delimiter)
- break;
- }
- if (c)
- i++;
- }
-
- /* Advance to the end of the string. */
- for (; string[i] && !whitespace (string[i]); i++);
-
- /* No extra whitespace at the end of the string. */
- string[i] = '\0';
-
- /* Handle equivalency bindings here. Make the left-hand side be exactly
- whatever the right-hand evaluates to, including keymaps. */
- if (equivalency)
- {
- return 0;
- }
-
- /* If this is a new-style key-binding, then do the binding with
- rl_set_key (). Otherwise, let the older code deal with it. */
- if (*string == '"')
- {
- char *seq;
- register int j, k, passc;
-
- seq = xmalloc (1 + strlen (string));
- for (j = 1, k = passc = 0; string[j]; j++)
- {
- /* Allow backslash to quote characters, but leave them in place.
- This allows a string to end with a backslash quoting another
- backslash, or with a backslash quoting a double quote. The
- backslashes are left in place for rl_translate_keyseq (). */
- if (passc || (string[j] == '\\'))
- {
- seq[k++] = string[j];
- passc = !passc;
- continue;
- }
-
- if (string[j] == '"')
- break;
-
- seq[k++] = string[j];
- }
- seq[k] = '\0';
-
- /* Binding macro? */
- if (*funname == '\'' || *funname == '"')
- {
- j = strlen (funname);
-
- /* Remove the delimiting quotes from each end of FUNNAME. */
- if (j && funname[j - 1] == *funname)
- funname[j - 1] = '\0';
-
- rl_macro_bind (seq, &funname[1], _rl_keymap);
- }
- else
- rl_set_key (seq, rl_named_function (funname), _rl_keymap);
-
- free (seq);
- return 0;
- }
-
- /* Get the actual character we want to deal with. */
- kname = strrchr (string, '-');
- if (!kname)
- kname = string;
- else
- kname++;
-
- key = glean_key_from_name (kname);
-
- /* Add in control and meta bits. */
- if (substring_member_of_array (string, possible_control_prefixes))
- key = CTRL (_rl_to_upper (key));
-
- if (substring_member_of_array (string, possible_meta_prefixes))
- key = META (key);
-
- /* Temporary. Handle old-style keyname with macro-binding. */
- if (*funname == '\'' || *funname == '"')
- {
- unsigned char useq[2];
- int fl = strlen (funname);
-
- useq[0] = key; useq[1] = '\0';
- if (fl && funname[fl - 1] == *funname)
- funname[fl - 1] = '\0';
-
- rl_macro_bind ((char*) useq, &funname[1], _rl_keymap);
- }
-#if defined (PREFIX_META_HACK)
- /* Ugly, but working hack to keep prefix-meta around. */
- else if (_rl_stricmp (funname, "prefix-meta") == 0)
- {
- char seq[2];
-
- seq[0] = key;
- seq[1] = '\0';
- rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
- }
-#endif /* PREFIX_META_HACK */
- else
- rl_bind_key (key, rl_named_function (funname));
- return 0;
-}
-
-/* Simple structure for boolean readline variables (i.e., those that can
- have one of two values; either "On" or 1 for truth, or "Off" or 0 for
- false. */
-
-static struct {
- const char *name;
- int *value;
-} boolean_varlist [] = {
-#if defined (PAREN_MATCHING)
- { "blink-matching-paren", &rl_blink_matching_paren },
-#endif
- { "completion-ignore-case", &_rl_completion_case_fold },
- { "convert-meta", &_rl_convert_meta_chars_to_ascii },
- { "disable-completion", &rl_inhibit_completion },
- { "enable-keypad", &_rl_enable_keypad },
- { "expand-tilde", &rl_complete_with_tilde_expansion },
- { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode },
- { "input-meta", &_rl_meta_flag },
- { "mark-directories", &_rl_complete_mark_directories },
- { "mark-modified-lines", &_rl_mark_modified_lines },
- { "meta-flag", &_rl_meta_flag },
- { "output-meta", &_rl_output_meta_chars },
- { "print-completions-horizontally", &_rl_print_completions_horizontally },
- { "show-all-if-ambiguous", &_rl_complete_show_all },
-#if defined (VISIBLE_STATS)
- { "visible-stats", &rl_visible_stats },
-#endif /* VISIBLE_STATS */
- { (char *)NULL, (int *)NULL }
-};
-
-int
-rl_variable_bind (name, value)
- char *name, *value;
-{
- register int i;
-
- /* Check for simple variables first. */
- for (i = 0; boolean_varlist[i].name; i++)
- {
- if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
- {
- /* A variable is TRUE if the "value" is "on", "1" or "". */
- *boolean_varlist[i].value = *value == 0 ||
- _rl_stricmp (value, "on") == 0 ||
- (value[0] == '1' && value[1] == '\0');
- return 0;
- }
- }
-
- /* Not a boolean variable, so check for specials. */
-
- /* Editing mode change? */
- if (_rl_stricmp (name, "editing-mode") == 0)
- {
- if (_rl_strnicmp (value, "vi", 2) == 0)
- {
-#if defined (VI_MODE)
- _rl_keymap = vi_insertion_keymap;
- rl_editing_mode = vi_mode;
-#endif /* VI_MODE */
- }
- else if (_rl_strnicmp (value, "emacs", 5) == 0)
- {
- _rl_keymap = emacs_standard_keymap;
- rl_editing_mode = emacs_mode;
- }
- }
-
- /* Comment string change? */
- else if (_rl_stricmp (name, "comment-begin") == 0)
- {
- if (*value)
- {
- if (_rl_comment_begin)
- free (_rl_comment_begin);
-
- _rl_comment_begin = savestring (value);
- }
- }
- else if (_rl_stricmp (name, "completion-query-items") == 0)
- {
- int nval = 100;
- if (*value)
- {
- nval = atoi (value);
- if (nval < 0)
- nval = 0;
- }
- rl_completion_query_items = nval;
- }
- else if (_rl_stricmp (name, "keymap") == 0)
- {
- Keymap kmap;
- kmap = rl_get_keymap_by_name (value);
- if (kmap)
- rl_set_keymap (kmap);
- }
- else if (_rl_stricmp (name, "bell-style") == 0)
- {
- if (!*value)
- _rl_bell_preference = AUDIBLE_BELL;
- else
- {
- if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
- _rl_bell_preference = NO_BELL;
- else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
- _rl_bell_preference = AUDIBLE_BELL;
- else if (_rl_stricmp (value, "visible") == 0)
- _rl_bell_preference = VISIBLE_BELL;
- }
- }
- else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
- {
- /* Backwards compatibility. */
- if (*value && (_rl_stricmp (value, "on") == 0 ||
- (*value == '1' && !value[1])))
- _rl_bell_preference = VISIBLE_BELL;
- else
- _rl_bell_preference = AUDIBLE_BELL;
- }
- else if (_rl_stricmp (name, "isearch-terminators") == 0)
- {
- /* Isolate the value and translate it into a character string. */
- int beg, end;
- char *v;
-
- v = savestring (value);
- FREE (_rl_isearch_terminators);
- if (v[0] == '"' || v[0] == '\'')
- {
- int delim = v[0];
- for (beg = end = 1; v[end] && v[end] != delim; end++)
- ;
- }
- else
- {
- for (beg = end = 0; whitespace (v[end]) == 0; end++)
- ;
- }
-
- v[end] = '\0';
- /* The value starts at v + beg. Translate it into a character string. */
- _rl_isearch_terminators = (unsigned char *)xmalloc (2 * strlen (v) + 1);
- rl_translate_keyseq (v + beg, (char*) _rl_isearch_terminators, &end);
- _rl_isearch_terminators[end] = '\0';
- free (v);
- }
-
- /* For the time being, unknown variable names are simply ignored. */
- return 0;
-}
-
-/* Return the character which matches NAME.
- For example, `Space' returns ' '. */
-
-typedef struct {
- const char *name;
- int value;
-} assoc_list;
-
-static assoc_list name_key_alist[] = {
- { "DEL", 0x7f },
- { "ESC", '\033' },
- { "Escape", '\033' },
- { "LFD", '\n' },
- { "Newline", '\n' },
- { "RET", '\r' },
- { "Return", '\r' },
- { "Rubout", 0x7f },
- { "SPC", ' ' },
- { "Space", ' ' },
- { "Tab", 0x09 },
- { (char *)0x0, 0 }
-};
-
-static int
-glean_key_from_name (name)
- char *name;
-{
- register int i;
-
- for (i = 0; name_key_alist[i].name; i++)
- if (_rl_stricmp (name, name_key_alist[i].name) == 0)
- return (name_key_alist[i].value);
-
- return (*(unsigned char *)name); /* XXX was return (*name) */
-}
-
-/* Auxiliary functions to manage keymaps. */
-static struct {
- const char *name;
- Keymap map;
-} keymap_names[] = {
- { "emacs", emacs_standard_keymap },
- { "emacs-standard", emacs_standard_keymap },
- { "emacs-meta", emacs_meta_keymap },
- { "emacs-ctlx", emacs_ctlx_keymap },
-#if defined (VI_MODE)
- { "vi", vi_movement_keymap },
- { "vi-move", vi_movement_keymap },
- { "vi-command", vi_movement_keymap },
- { "vi-insert", vi_insertion_keymap },
-#endif /* VI_MODE */
- { (char *)0x0, (Keymap)0x0 }
-};
-
-Keymap
-rl_get_keymap_by_name (name)
- char *name;
-{
- register int i;
-
- for (i = 0; keymap_names[i].name; i++)
- if (strcmp (name, keymap_names[i].name) == 0)
- return (keymap_names[i].map);
- return ((Keymap) NULL);
-}
-
-const char *
-rl_get_keymap_name (map)
- Keymap map;
-{
- register int i;
- for (i = 0; keymap_names[i].name; i++)
- if (map == keymap_names[i].map)
- return (keymap_names[i].name);
- return ((char *)NULL);
-}
-
-void
-rl_set_keymap (map)
- Keymap map;
-{
- if (map)
- _rl_keymap = map;
-}
-
-Keymap
-rl_get_keymap ()
-{
- return (_rl_keymap);
-}
-
-void
-rl_set_keymap_from_edit_mode ()
-{
- if (rl_editing_mode == emacs_mode)
- _rl_keymap = emacs_standard_keymap;
-#if defined (VI_MODE)
- else if (rl_editing_mode == vi_mode)
- _rl_keymap = vi_insertion_keymap;
-#endif /* VI_MODE */
-}
-
-const char *
-rl_get_keymap_name_from_edit_mode ()
-{
- if (rl_editing_mode == emacs_mode)
- return "emacs";
-#if defined (VI_MODE)
- else if (rl_editing_mode == vi_mode)
- return "vi";
-#endif /* VI_MODE */
- else
- return "none";
-}
-
-/* **************************************************************** */
-/* */
-/* Key Binding and Function Information */
-/* */
-/* **************************************************************** */
-
-/* Each of the following functions produces information about the
- state of keybindings and functions known to Readline. The info
- is always printed to rl_outstream, and in such a way that it can
- be read back in (i.e., passed to rl_parse_and_bind (). */
-
-/* Print the names of functions known to Readline. */
-void
-rl_list_funmap_names ()
-{
- register int i;
- char **funmap_names;
-
- funmap_names = rl_funmap_names ();
-
- if (!funmap_names)
- return;
-
- for (i = 0; funmap_names[i]; i++)
- fprintf (rl_outstream, "%s\n", funmap_names[i]);
-
- free (funmap_names);
-}
-
-static char *
-_rl_get_keyname (key)
- int key;
-{
- char *keyname;
- int i, c;
-
- keyname = (char *)xmalloc (8);
-
- c = key;
- /* Since this is going to be used to write out keysequence-function
- pairs for possible inclusion in an inputrc file, we don't want to
- do any special meta processing on KEY. */
-
-#if 0
- /* We might want to do this, but the old version of the code did not. */
-
- /* If this is an escape character, we don't want to do any more processing.
- Just add the special ESC key sequence and return. */
- if (c == ESC)
- {
- keyseq[0] = '\\';
- keyseq[1] = 'e';
- keyseq[2] = '\0';
- return keyseq;
- }
-#endif
-
- /* RUBOUT is translated directly into \C-? */
- if (key == RUBOUT)
- {
- keyname[0] = '\\';
- keyname[1] = 'C';
- keyname[2] = '-';
- keyname[3] = '?';
- keyname[4] = '\0';
- return keyname;
- }
-
- i = 0;
- /* Now add special prefixes needed for control characters. This can
- potentially change C. */
- if (CTRL_CHAR (c))
- {
- keyname[i++] = '\\';
- keyname[i++] = 'C';
- keyname[i++] = '-';
- c = _rl_to_lower (UNCTRL (c));
- }
-
- /* XXX experimental code. Turn the characters that are not ASCII or
- ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
- This changes C. */
- if (c >= 128 && c <= 159)
- {
- keyname[i++] = '\\';
- keyname[i++] = '2';
- c -= 128;
- keyname[i++] = (c / 8) + '0';
- c = (c % 8) + '0';
- }
-
- /* Now, if the character needs to be quoted with a backslash, do that. */
- if (c == '\\' || c == '"')
- keyname[i++] = '\\';
-
- /* Now add the key, terminate the string, and return it. */
- keyname[i++] = (char) c;
- keyname[i] = '\0';
-
- return keyname;
-}
-
-/* Return a NULL terminated array of strings which represent the key
- sequences that are used to invoke FUNCTION in MAP. */
-char **
-rl_invoking_keyseqs_in_map (function, map)
- Function *function;
- Keymap map;
-{
- register int key;
- char **result;
- int result_index, result_size;
-
- result = (char **)NULL;
- result_index = result_size = 0;
-
- for (key = 0; key < KEYMAP_SIZE; key++)
- {
- switch (map[key].type)
- {
- case ISMACR:
- /* Macros match, if, and only if, the pointers are identical.
- Thus, they are treated exactly like functions in here. */
- case ISFUNC:
- /* If the function in the keymap is the one we are looking for,
- then add the current KEY to the list of invoking keys. */
- if (map[key].function == function)
- {
- char *keyname;
-
- keyname = _rl_get_keyname (key);
-
- if (result_index + 2 > result_size)
- {
- result_size += 10;
- result = (char **) xrealloc (result, result_size * sizeof (char *));
- }
-
- result[result_index++] = keyname;
- result[result_index] = (char *)NULL;
- }
- break;
-
- case ISKMAP:
- {
- char **seqs;
- register int i;
-
- /* Find the list of keyseqs in this map which have FUNCTION as
- their target. Add the key sequences found to RESULT. */
- if (map[key].function)
- seqs =
- rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
- else
- break;
-
- if (seqs == 0)
- break;
-
- for (i = 0; seqs[i]; i++)
- {
- char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
-
- if (key == ESC)
- sprintf (keyname, "\\e");
- else if (CTRL_CHAR (key))
- sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
- else if (key == RUBOUT)
- sprintf (keyname, "\\C-?");
- else if (key == '\\' || key == '"')
- {
- keyname[0] = '\\';
- keyname[1] = (char) key;
- keyname[2] = '\0';
- }
- else
- {
- keyname[0] = (char) key;
- keyname[1] = '\0';
- }
-
- strcat (keyname, seqs[i]);
- free (seqs[i]);
-
- if (result_index + 2 > result_size)
- {
- result_size += 10;
- result = (char **) xrealloc (result, result_size * sizeof (char *));
- }
-
- result[result_index++] = keyname;
- result[result_index] = (char *)NULL;
- }
-
- free (seqs);
- }
- break;
- }
- }
- return (result);
-}
-
-/* Return a NULL terminated array of strings which represent the key
- sequences that can be used to invoke FUNCTION using the current keymap. */
-char **
-rl_invoking_keyseqs (function)
- Function *function;
-{
- return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
-}
-
-/* Print all of the functions and their bindings to rl_outstream. If
- PRINT_READABLY is non-zero, then print the output in such a way
- that it can be read back in. */
-void
-rl_function_dumper (print_readably)
- int print_readably;
-{
- register int i;
- char **names;
- char *name;
-
- names = rl_funmap_names ();
-
- fprintf (rl_outstream, "\n");
-
- for (i = 0; (name = names[i]); i++)
- {
- Function *function;
- char **invokers;
-
- function = rl_named_function (name);
- invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
-
- if (print_readably)
- {
- if (!invokers)
- fprintf (rl_outstream, "# %s (not bound)\n", name);
- else
- {
- register int j;
-
- for (j = 0; invokers[j]; j++)
- {
- fprintf (rl_outstream, "\"%s\": %s\n",
- invokers[j], name);
- free (invokers[j]);
- }
-
- free (invokers);
- }
- }
- else
- {
- if (!invokers)
- fprintf (rl_outstream, "%s is not bound to any keys\n",
- name);
- else
- {
- register int j;
-
- fprintf (rl_outstream, "%s can be found on ", name);
-
- for (j = 0; invokers[j] && j < 5; j++)
- {
- fprintf (rl_outstream, "\"%s\"%s", invokers[j],
- invokers[j + 1] ? ", " : ".\n");
- }
-
- if (j == 5 && invokers[j])
- fprintf (rl_outstream, "...\n");
-
- for (j = 0; invokers[j]; j++)
- free (invokers[j]);
-
- free (invokers);
- }
- }
- }
-}
-
-/* Print all of the current functions and their bindings to
- rl_outstream. If an explicit argument is given, then print
- the output in such a way that it can be read back in. */
-int
-rl_dump_functions (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (rl_dispatching)
- fprintf (rl_outstream, "\r\n");
- rl_function_dumper (rl_explicit_arg);
- rl_on_new_line ();
- return (0);
-}
-
-static void
-_rl_macro_dumper_internal (print_readably, map, prefix)
- int print_readably;
- Keymap map;
- char *prefix;
-{
- register int key;
- char *keyname, *out;
- int prefix_len;
-
- for (key = 0; key < KEYMAP_SIZE; key++)
- {
- switch (map[key].type)
- {
- case ISMACR:
- keyname = _rl_get_keyname (key);
-#if 0
- out = (char *)map[key].function;
-#else
- out = _rl_untranslate_macro_value ((char *)map[key].function);
-#endif
- if (print_readably)
- fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
- keyname,
- out ? out : "");
- else
- fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
- keyname,
- out ? out : "");
- free (keyname);
-#if 1
- free (out);
-#endif
- break;
- case ISFUNC:
- break;
- case ISKMAP:
- prefix_len = prefix ? strlen (prefix) : 0;
- if (key == ESC)
- {
- keyname = xmalloc (3 + prefix_len);
- if (prefix)
- strcpy (keyname, prefix);
- keyname[prefix_len] = '\\';
- keyname[prefix_len + 1] = 'e';
- keyname[prefix_len + 2] = '\0';
- }
- else
- {
- keyname = _rl_get_keyname (key);
- if (prefix)
- {
- out = xmalloc (strlen (keyname) + prefix_len + 1);
- strcpy (out, prefix);
- strcpy (out + prefix_len, keyname);
- free (keyname);
- keyname = out;
- }
- }
-
- _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
- free (keyname);
- break;
- }
- }
-}
-
-void
-rl_macro_dumper (print_readably)
- int print_readably;
-{
- _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
-}
-
-int
-rl_dump_macros (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (rl_dispatching)
- fprintf (rl_outstream, "\r\n");
- rl_macro_dumper (rl_explicit_arg);
- rl_on_new_line ();
- return (0);
-}
-
-void
-rl_variable_dumper (print_readably)
- int print_readably;
-{
- int i;
- const char *kname;
-
- for (i = 0; boolean_varlist[i].name; i++)
- {
- if (print_readably)
- fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
- *boolean_varlist[i].value ? "on" : "off");
- else
- fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
- *boolean_varlist[i].value ? "on" : "off");
- }
-
- /* bell-style */
- switch (_rl_bell_preference)
- {
- case NO_BELL:
- kname = "none"; break;
- case VISIBLE_BELL:
- kname = "visible"; break;
- case AUDIBLE_BELL:
- default:
- kname = "audible"; break;
- }
- if (print_readably)
- fprintf (rl_outstream, "set bell-style %s\n", kname);
- else
- fprintf (rl_outstream, "bell-style is set to `%s'\n", kname);
-
- /* comment-begin */
- if (print_readably)
- fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
- else
- fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : "");
-
- /* completion-query-items */
- if (print_readably)
- fprintf (rl_outstream, "set completion-query-items %d\n", rl_completion_query_items);
- else
- fprintf (rl_outstream, "completion-query-items is set to `%d'\n", rl_completion_query_items);
-
- /* editing-mode */
- if (print_readably)
- fprintf (rl_outstream, "set editing-mode %s\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
- else
- fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
-
- /* keymap */
- kname = rl_get_keymap_name (_rl_keymap);
- if (kname == 0)
- kname = rl_get_keymap_name_from_edit_mode ();
- if (print_readably)
- fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none");
- else
- fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none");
-
- /* isearch-terminators */
- if (_rl_isearch_terminators)
- {
- char *disp;
-
- disp = _rl_untranslate_macro_value (_rl_isearch_terminators);
-
- if (print_readably)
- fprintf (rl_outstream, "set isearch-terminators \"%s\"\n", disp);
- else
- fprintf (rl_outstream, "isearch-terminators is set to \"%s\"\n", disp);
-
- free (disp);
- }
-}
-
-/* Print all of the current variables and their values to
- rl_outstream. If an explicit argument is given, then print
- the output in such a way that it can be read back in. */
-int
-rl_dump_variables (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (rl_dispatching)
- fprintf (rl_outstream, "\r\n");
- rl_variable_dumper (rl_explicit_arg);
- rl_on_new_line ();
- return (0);
-}
-
-/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */
-void
-_rl_bind_if_unbound (keyseq, default_func)
- char *keyseq;
- Function *default_func;
-{
- Function *func;
-
- if (keyseq)
- {
- func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
- if (!func || func == rl_do_lowercase_version)
- rl_set_key (keyseq, default_func, _rl_keymap);
- }
-}
-
-/* Return non-zero if any members of ARRAY are a substring in STRING. */
-static int
-substring_member_of_array (string, array)
- char *string, **array;
-{
- while (*array)
- {
- if (_rl_strindex (string, *array))
- return (1);
- array++;
- }
- return (0);
-}
diff --git a/readline/callback.c b/readline/callback.c
deleted file mode 100644
index 200f3cc37f9..00000000000
--- a/readline/callback.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/* callback.c -- functions to use readline as an X `callback' mechanism. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include "rlconf.h"
-
-#if defined (READLINE_CALLBACKS)
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "readline.h"
-
-extern void readline_internal_setup ();
-extern char *readline_internal_teardown ();
-extern int readline_internal_char ();
-extern void _rl_init_line_state ();
-
-extern int _rl_meta_flag;
-extern char *rl_prompt;
-extern int rl_visible_prompt_length;
-
-/* **************************************************************** */
-/* */
-/* Callback Readline Functions */
-/* */
-/* **************************************************************** */
-
-/* Allow using readline in situations where a program may have multiple
- things to handle at once, and dispatches them via select(). Call
- rl_callback_handler_install() with the prompt and a function to call
- whenever a complete line of input is ready. The user must then
- call rl_callback_read_char() every time some input is available, and
- rl_callback_read_char() will call the user's function with the complete
- text read in at each end of line. The terminal is kept prepped and
- signals handled all the time, except during calls to the user's function. */
-
-VFunction *rl_linefunc; /* user callback function */
-static int in_handler; /* terminal_prepped and signals set? */
-
-/* Make sure the terminal is set up, initialize readline, and prompt. */
-static void
-_rl_callback_newline ()
-{
- rl_initialize ();
-
- if (in_handler == 0)
- {
- in_handler = 1;
-
- (*rl_prep_term_function) (_rl_meta_flag);
-
-#if defined (HANDLE_SIGNALS)
- rl_set_signals ();
-#endif
- }
-
- readline_internal_setup ();
-}
-
-/* Install a readline handler, set up the terminal, and issue the prompt. */
-void
-rl_callback_handler_install (prompt, linefunc)
- char *prompt;
- VFunction *linefunc;
-{
- rl_prompt = prompt;
- rl_visible_prompt_length = rl_prompt ? rl_expand_prompt (rl_prompt) : 0;
- rl_linefunc = linefunc;
- _rl_callback_newline ();
-}
-
-/* Read one character, and dispatch to the handler if it ends the line. */
-void
-rl_callback_read_char ()
-{
- char *line;
- int eof;
-
- if (rl_linefunc == NULL)
- {
- fprintf (stderr, "readline: readline_callback_read_char() called with no handler!\r\n");
- abort ();
- }
-
- eof = readline_internal_char ();
-
- if (rl_done)
- {
- line = readline_internal_teardown (eof);
-
- (*rl_deprep_term_function) ();
-#if defined (HANDLE_SIGNALS)
- rl_clear_signals ();
-#endif
- in_handler = 0;
- (*rl_linefunc) (line);
-
- /* If the user did not clear out the line, do it for him. */
- if (rl_line_buffer[0])
- _rl_init_line_state ();
-
- /* Redisplay the prompt if readline_handler_{install,remove} not called. */
- if (in_handler == 0 && rl_linefunc)
- _rl_callback_newline ();
- }
-}
-
-/* Remove the handler, and make sure the terminal is in its normal state. */
-void
-rl_callback_handler_remove ()
-{
- rl_linefunc = NULL;
- if (in_handler)
- {
- in_handler = 0;
- (*rl_deprep_term_function) ();
-#if defined (HANDLE_SIGNALS)
- rl_clear_signals ();
-#endif
- }
-}
-
-#endif
diff --git a/readline/chardefs.h b/readline/chardefs.h
deleted file mode 100644
index 740f14b185b..00000000000
--- a/readline/chardefs.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* chardefs.h -- Character definitions for readline. */
-
-/* Copyright (C) 1994 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef _CHARDEFS_H_
-#define _CHARDEFS_H_
-
-#ifndef _m_ctype_h
-#include <ctype.h>
-#endif
-
-#if defined (HAVE_CONFIG_H)
-# if defined (HAVE_STRING_H)
-# include <string.h>
-# else
-# include <strings.h>
-# endif /* HAVE_STRING_H */
-#else
-# include <string.h>
-#endif /* !HAVE_CONFIG_H */
-
-#ifndef whitespace
-#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
-#endif
-
-#ifdef CTRL
-#undef CTRL
-#endif
-
-/* Some character stuff. */
-#define control_character_threshold 0x020 /* Smaller than this is control. */
-#define control_character_mask 0x1f /* 0x20 - 1 */
-#define meta_character_threshold 0x07f /* Larger than this is Meta. */
-#define control_character_bit 0x40 /* 0x000000, must be off. */
-#define meta_character_bit 0x080 /* x0000000, must be on. */
-#define largest_char 255 /* Largest character value. */
-
-#define CTRL_CHAR(c) ((c) < control_character_threshold && (c) >= 0)
-#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
-
-#define CTRL(c) ((c) & control_character_mask)
-#define META(c) ((c) | meta_character_bit)
-
-#define UNMETA(c) ((c) & (~meta_character_bit))
-#define UNCTRL(c) _rl_to_upper(((c)|control_character_bit))
-
-/* Old versions
-#define _rl_lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
-#define _rl_uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
-#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9')
-*/
-
-#define _rl_lowercase_p(c) (islower(c))
-#define _rl_uppercase_p(c) (isupper(c))
-#define _rl_digit_p(x) (isdigit (x))
-
-#define _rl_pure_alphabetic(c) (_rl_lowercase_p(c) || _rl_uppercase_p(c))
-#define ALPHABETIC(c) (_rl_lowercase_p(c) || _rl_uppercase_p(c) || _rl_digit_p(c))
-
-/* Old versions
-# define _rl_to_upper(c) (_rl_lowercase_p(c) ? ((c) - 32) : (c))
-# define _rl_to_lower(c) (_rl_uppercase_p(c) ? ((c) + 32) : (c))
-*/
-
-#ifndef _rl_to_upper
-# define _rl_to_upper(c) (islower(c) ? toupper(c) : (c))
-# define _rl_to_lower(c) (isupper(c) ? tolower(c) : (c))
-#endif
-
-#ifndef _rl_digit_value
-#define _rl_digit_value(x) ((x) - '0')
-#endif
-
-#ifndef NEWLINE
-#define NEWLINE '\n'
-#endif
-
-#ifndef RETURN
-#define RETURN CTRL('M')
-#endif
-
-#ifndef RUBOUT
-#define RUBOUT 0x7f
-#endif
-
-#ifndef TAB
-#define TAB '\t'
-#endif
-
-#ifdef ABORT_CHAR
-#undef ABORT_CHAR
-#endif
-#define ABORT_CHAR CTRL('G')
-
-#ifdef PAGE
-#undef PAGE
-#endif
-#define PAGE CTRL('L')
-
-#ifdef SPACE
-#undef SPACE
-#endif
-#define SPACE ' ' /* XXX - was 0x20 */
-
-#ifdef ESC
-#undef ESC
-#endif
-#define ESC CTRL('[')
-
-#ifndef ISOCTAL
-#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
-#endif
-#define OCTVALUE(c) ((c) - '0')
-
-#ifndef isxdigit
-# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
-#endif
-
-#define HEXVALUE(c) \
- (((c) >= 'a' && (c) <= 'f') \
- ? (c)-'a'+10 \
- : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
-
-#endif /* _CHARDEFS_H_ */
diff --git a/readline/complete.c b/readline/complete.c
deleted file mode 100644
index 8810ca06d5f..00000000000
--- a/readline/complete.c
+++ /dev/null
@@ -1,1748 +0,0 @@
-/* complete.c -- filename completion for readline. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-#include <sys/file.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#include <pwd.h>
-#if !defined (HAVE_GETPW_DECLS)
-extern struct passwd *getpwent ();
-#endif /* USG && !HAVE_GETPW_DECLS */
-
-/* ISC systems don't define getpwent() if _POSIX_SOURCE is defined. */
-#if defined (isc386) && defined (_POSIX_SOURCE)
-# if defined (__STDC__)
-extern struct passwd *getpwent (void);
-# else
-extern struct passwd *getpwent ();
-# endif /* !__STDC__ */
-#endif /* isc386 && _POSIX_SOURCE */
-
-#include "posixdir.h"
-#include "posixstat.h"
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-
-extern char *tilde_expand ();
-extern char *rl_copy_text ();
-extern void _rl_abort_internal ();
-extern int _rl_qsort_string_compare ();
-extern void _rl_replace_text ();
-
-extern Function *rl_last_func;
-extern int rl_editing_mode;
-extern int screenwidth;
-
-extern void _rl_move_vert ();
-extern int _rl_vis_botlin;
-extern int rl_display_fixed;
-
-/* If non-zero, then this is the address of a function to call when
- completing a word would normally display the list of possible matches.
- This function is called instead of actually doing the display.
- It takes three arguments: (char **matches, int num_matches, int max_length)
- where MATCHES is the array of strings that matched, NUM_MATCHES is the
- number of strings in that array, and MAX_LENGTH is the length of the
- longest string in that array. */
-VFunction *rl_completion_display_matches_hook = (VFunction *)NULL;
-
-/* Forward declarations for functions defined and used in this file. */
-char *filename_completion_function (const char *text, int state);
-char **completion_matches ();
-
-#if defined (VISIBLE_STATS)
-# if !defined (X_OK)
-# define X_OK 1
-# endif
-static int stat_char ();
-#endif
-
-static char *rl_quote_filename ();
-static char *rl_strpbrk ();
-
-static char **remove_duplicate_matches ();
-static void insert_match ();
-static int append_to_match ();
-static void insert_all_matches ();
-static void display_matches ();
-static int compute_lcd_of_matches ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Completion matching, from readline's point of view. */
-/* */
-/* **************************************************************** */
-
-/* Variables known only to the readline library. */
-
-/* If non-zero, non-unique completions always show the list of matches. */
-int _rl_complete_show_all = 0;
-
-/* If non-zero, completed directory names have a slash appended. */
-int _rl_complete_mark_directories = 1;
-
-/* If non-zero, completions are printed horizontally in alphabetical order,
- like `ls -x'. */
-int _rl_print_completions_horizontally;
-
-/* Non-zero means that case is not significant in filename completion. */
-int _rl_completion_case_fold;
-
-/* Global variables available to applications using readline. */
-
-#if defined (VISIBLE_STATS)
-/* Non-zero means add an additional character to each filename displayed
- during listing completion iff rl_filename_completion_desired which helps
- to indicate the type of file being listed. */
-int rl_visible_stats = 0;
-#endif /* VISIBLE_STATS */
-
-/* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. */
-Function *rl_directory_completion_hook = (Function *)NULL;
-
-/* Non-zero means readline completion functions perform tilde expansion. */
-int rl_complete_with_tilde_expansion = 0;
-
-/* Pointer to the generator function for completion_matches ().
- NULL means to use filename_completion_function (), the default filename
- completer. */
-Function *rl_completion_entry_function = (Function *)NULL;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-CPPFunction *rl_attempted_completion_function = (CPPFunction *)NULL;
-
-/* Non-zero means to suppress normal filename completion after the
- user-specified completion function has been called. */
-int rl_attempted_completion_over = 0;
-
-/* Set to a character indicating the type of completion being performed
- by rl_complete_internal, available for use by application completion
- functions. */
-int rl_completion_type = 0;
-
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if
- she is sure she wants to see them all. */
-int rl_completion_query_items = 100;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The contents of this variable is what breaks words
- in the shell, i.e. " \t\n\"\\'`@$><=" */
-const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
-
-/* List of basic quoting characters. */
-const char *rl_basic_quote_characters = "\"'";
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-const char *rl_completer_word_break_characters = (char *)NULL;
-
-/* List of characters which can be used to quote a substring of the line.
- Completion occurs on the entire substring, and within the substring
- rl_completer_word_break_characters are treated as any other character,
- unless they also appear within this list. */
-char *rl_completer_quote_characters = (char *)NULL;
-
-/* List of characters that should be quoted in filenames by the completer. */
-char *rl_filename_quote_characters = (char *)NULL;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-char *rl_special_prefixes = (char *)NULL;
-
-/* If non-zero, then disallow duplicates in the matches. */
-int rl_ignore_completion_duplicates = 1;
-
-/* Non-zero means that the results of the matches are to be treated
- as filenames. This is ALWAYS zero on entry, and can only be changed
- within a completion entry finder function. */
-int rl_filename_completion_desired = 0;
-
-/* Non-zero means that the results of the matches are to be quoted using
- double quotes (or an application-specific quoting mechanism) if the
- filename contains any characters in rl_filename_quote_chars. This is
- ALWAYS non-zero on entry, and can only be changed within a completion
- entry finder function. */
-int rl_filename_quoting_desired = 1;
-
-/* This function, if defined, is called by the completer when real
- filename completion is done, after all the matching names have been
- generated. It is passed a (char**) known as matches in the code below.
- It consists of a NULL-terminated array of pointers to potential
- matching strings. The 1st element (matches[0]) is the maximal
- substring that is common to all matches. This function can re-arrange
- the list of matches as required, but all elements of the array must be
- free()'d if they are deleted. The main intent of this function is
- to implement FIGNORE a la SunOS csh. */
-Function *rl_ignore_some_completions_function = (Function *)NULL;
-
-/* Set to a function to quote a filename in an application-specific fashion.
- Called with the text to quote, the type of match found (single or multiple)
- and a pointer to the quoting character to be used, which the function can
- reset if desired. */
-CPFunction *rl_filename_quoting_function = rl_quote_filename;
-
-/* Function to call to remove quoting characters from a filename. Called
- before completion is attempted, so the embedded quotes do not interfere
- with matching names in the file system. Readline doesn't do anything
- with this; it's set only by applications. */
-CPFunction *rl_filename_dequoting_function = (CPFunction *)NULL;
-
-/* Function to call to decide whether or not a word break character is
- quoted. If a character is quoted, it does not break words for the
- completer. */
-Function *rl_char_is_quoted_p = (Function *)NULL;
-
-/* Character appended to completed words when at the end of the line. The
- default is a space. */
-int rl_completion_append_character = ' ';
-
-/* If non-zero, inhibit completion (temporarily). */
-int rl_inhibit_completion;
-
-/* Variables local to this file. */
-
-/* Local variable states what happened during the last completion attempt. */
-static int completion_changed_buffer;
-
-/*************************************/
-/* */
-/* Bindable completion functions */
-/* */
-/*************************************/
-
-/* Complete the word at or before point. You have supplied the function
- that does the initial simple matching selection algorithm (see
- completion_matches ()). The default is to do filename completion. */
-int
-rl_complete (ignore, invoking_key)
- int ignore, invoking_key;
-{
- if (rl_inhibit_completion)
- return (rl_insert (ignore, invoking_key));
- else if (rl_last_func == rl_complete && !completion_changed_buffer)
- return (rl_complete_internal ('?'));
- else if (_rl_complete_show_all)
- return (rl_complete_internal ('!'));
- else
- return (rl_complete_internal (TAB));
-}
-
-/* List the possible completions. See description of rl_complete (). */
-int
-rl_possible_completions (ignore, invoking_key)
- int ignore __attribute__((unused)), invoking_key __attribute__((unused));
-{
- return (rl_complete_internal ('?'));
-}
-
-int
-rl_insert_completions (ignore, invoking_key)
- int ignore __attribute__((unused)), invoking_key __attribute__((unused));
-{
- return (rl_complete_internal ('*'));
-}
-
-/************************************/
-/* */
-/* Completion utility functions */
-/* */
-/************************************/
-
-/* Find the first occurrence in STRING1 of any character from STRING2.
- Return a pointer to the character in STRING1. */
-static char *
-rl_strpbrk (string1, string2)
- char *string1, *string2;
-{
- register char *scan;
-
- for (; *string1; string1++)
- {
- for (scan = string2; *scan; scan++)
- {
- if (*string1 == *scan)
- {
- return (string1);
- }
- }
- }
- return ((char *)NULL);
-}
-
-/* The user must press "y" or "n". Non-zero return means "y" pressed. */
-static int
-get_y_or_n ()
-{
- int c;
-
- for (;;)
- {
- c = rl_read_key ();
- if (c == 'y' || c == 'Y' || c == ' ')
- return (1);
- if (c == 'n' || c == 'N' || c == RUBOUT)
- return (0);
- if (c == ABORT_CHAR)
- _rl_abort_internal ();
- ding ();
- }
-}
-
-#if defined (VISIBLE_STATS)
-/* Return the character which best describes FILENAME.
- `@' for symbolic links
- `/' for directories
- `*' for executables
- `=' for sockets
- `|' for FIFOs
- `%' for character special devices
- `#' for block special devices */
-static int
-stat_char (filename)
- char *filename;
-{
- struct stat finfo;
- int character, r;
-
-#if defined (HAVE_LSTAT) && defined (S_ISLNK)
- r = lstat (filename, &finfo);
-#else
- r = stat (filename, &finfo);
-#endif
-
- if (r == -1)
- return (0);
-
- character = 0;
- if (S_ISDIR (finfo.st_mode))
- character = '/';
-#if defined (S_ISCHR)
- else if (S_ISCHR (finfo.st_mode))
- character = '%';
-#endif /* S_ISCHR */
-#if defined (S_ISBLK)
- else if (S_ISBLK (finfo.st_mode))
- character = '#';
-#endif /* S_ISBLK */
-#if defined (S_ISLNK)
- else if (S_ISLNK (finfo.st_mode))
- character = '@';
-#endif /* S_ISLNK */
-#if defined (S_ISSOCK)
- else if (S_ISSOCK (finfo.st_mode))
- character = '=';
-#endif /* S_ISSOCK */
-#if defined (S_ISFIFO)
- else if (S_ISFIFO (finfo.st_mode))
- character = '|';
-#endif
- else if (S_ISREG (finfo.st_mode))
- {
- if (access (filename, X_OK) == 0)
- character = '*';
- }
- return (character);
-}
-#endif /* VISIBLE_STATS */
-
-/* Return the portion of PATHNAME that should be output when listing
- possible completions. If we are hacking filename completion, we
- are only interested in the basename, the portion following the
- final slash. Otherwise, we return what we were passed. */
-static char *
-printable_part (pathname)
- char *pathname;
-{
- char *temp;
-
- temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL;
- return (temp ? ++temp : pathname);
-}
-
-/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
- are using it, check for and output a single character for `special'
- filenames. Return the number of characters we output. */
-
-#define PUTX(c) \
- do { \
- if (CTRL_CHAR (c)) \
- { \
- putc ('^', rl_outstream); \
- putc (UNCTRL (c), rl_outstream); \
- printed_len += 2; \
- } \
- else if (c == RUBOUT) \
- { \
- putc ('^', rl_outstream); \
- putc ('?', rl_outstream); \
- printed_len += 2; \
- } \
- else \
- { \
- putc (c, rl_outstream); \
- printed_len++; \
- } \
- } while (0)
-
-static int
-print_filename (to_print, full_pathname)
- char *to_print, *full_pathname;
-{
- int printed_len = 0;
-#if !defined (VISIBLE_STATS)
- char *s;
-
- for (s = to_print; *s; s++)
- {
- PUTX (*s);
- }
-#else
- char *s, c, *new_full_pathname;
- int extension_char, slen, tlen;
-
- for (s = to_print; *s; s++)
- {
- PUTX (*s);
- }
-
- if (rl_filename_completion_desired && rl_visible_stats)
- {
- /* If to_print != full_pathname, to_print is the basename of the
- path passed. In this case, we try to expand the directory
- name before checking for the stat character. */
- if (to_print != full_pathname)
- {
- /* Terminate the directory name. */
- c = to_print[-1];
- to_print[-1] = '\0';
-
- s = tilde_expand (full_pathname);
- if (rl_directory_completion_hook)
- (*rl_directory_completion_hook) (&s);
-
- slen = strlen (s);
- tlen = strlen (to_print);
- new_full_pathname = xmalloc (slen + tlen + 2);
- strcpy (new_full_pathname, s);
- new_full_pathname[slen] = '/';
- strcpy (new_full_pathname + slen + 1, to_print);
-
- extension_char = stat_char (new_full_pathname);
-
- free (new_full_pathname);
- to_print[-1] = c;
- }
- else
- {
- s = tilde_expand (full_pathname);
- extension_char = stat_char (s);
- }
-
- free (s);
- if (extension_char)
- {
- putc (extension_char, rl_outstream);
- printed_len++;
- }
- }
-#endif /* VISIBLE_STATS */
- return printed_len;
-}
-
-static char *
-rl_quote_filename (s, rtype, qcp)
- char *s;
- int rtype __attribute__((unused));
- char *qcp;
-{
- char *r;
-
- r = xmalloc (strlen (s) + 2);
- *r = *rl_completer_quote_characters;
- strcpy (r + 1, s);
- if (qcp)
- *qcp = *rl_completer_quote_characters;
- return r;
-}
-
-/* Find the bounds of the current word for completion purposes, and leave
- rl_point set to the end of the word. This function skips quoted
- substrings (characters between matched pairs of characters in
- rl_completer_quote_characters. First we try to find an unclosed
- quoted substring on which to do matching. If one is not found, we use
- the word break characters to find the boundaries of the current word.
- We call an application-specific function to decide whether or not a
- particular word break character is quoted; if that function returns a
- non-zero result, the character does not break a word. This function
- returns the opening quote character if we found an unclosed quoted
- substring, '\0' otherwise. FP, if non-null, is set to a value saying
- which (shell-like) quote characters we found (single quote, double
- quote, or backslash) anywhere in the string. DP, if non-null, is set to
- the value of the delimiter character that caused a word break. */
-
-static char
-find_completion_word (fp, dp)
- int *fp, *dp;
-{
- int scan, end, found_quote, delimiter, pass_next, isbrk;
- char quote_char;
-
- end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_completer_quote_characters)
- {
- /* We have a list of characters which can be used in pairs to
- quote substrings for the completer. Try to find the start
- of an unclosed quoted substring. */
- /* FOUND_QUOTE is set so we know what kind of quotes we found. */
- for (scan = pass_next = 0; scan < end; scan++)
- {
- if (pass_next)
- {
- pass_next = 0;
- continue;
- }
-
- if (rl_line_buffer[scan] == '\\')
- {
- pass_next = 1;
- found_quote |= RL_QF_BACKSLASH;
- continue;
- }
-
- if (quote_char != '\0')
- {
- /* Ignore everything until the matching close quote char. */
- if (rl_line_buffer[scan] == quote_char)
- {
- /* Found matching close. Abandon this substring. */
- quote_char = '\0';
- rl_point = end;
- }
- }
- else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
- {
- /* Found start of a quoted substring. */
- quote_char = rl_line_buffer[scan];
- rl_point = scan + 1;
- /* Shell-like quoting conventions. */
- if (quote_char == '\'')
- found_quote |= RL_QF_SINGLE_QUOTE;
- else if (quote_char == '"')
- found_quote |= RL_QF_DOUBLE_QUOTE;
- }
- }
- }
-
- if (rl_point == end && quote_char == '\0')
- {
- /* We didn't find an unclosed quoted substring upon which to do
- completion, so use the word break characters to find the
- substring on which to complete. */
- while (--rl_point)
- {
- scan = rl_line_buffer[rl_point];
-
- if (strchr (rl_completer_word_break_characters, scan) == 0)
- continue;
-
- /* Call the application-specific function to tell us whether
- this word break character is quoted and should be skipped. */
- if (rl_char_is_quoted_p && found_quote &&
- (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
- continue;
-
- /* Convoluted code, but it avoids an n^2 algorithm with calls
- to char_is_quoted. */
- break;
- }
- }
-
- /* If we are at an unquoted word break, then advance past it. */
- scan = rl_line_buffer[rl_point];
-
- /* If there is an application-specific function to say whether or not
- a character is quoted and we found a quote character, let that
- function decide whether or not a character is a word break, even
- if it is found in rl_completer_word_break_characters. */
- if (rl_char_is_quoted_p)
- isbrk = (found_quote == 0 ||
- (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
- strchr (rl_completer_word_break_characters, scan) != 0;
- else
- isbrk = strchr (rl_completer_word_break_characters, scan) != 0;
-
- if (isbrk)
- {
- /* If the character that caused the word break was a quoting
- character, then remember it as the delimiter. */
- if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, scan) && (end - rl_point) > 1)
- delimiter = scan;
-
- /* If the character isn't needed to determine something special
- about what kind of completion to perform, then advance past it. */
- if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0)
- rl_point++;
- }
-
- if (fp)
- *fp = found_quote;
- if (dp)
- *dp = delimiter;
-
- return (quote_char);
-}
-
-static char **
-gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
- char *text;
- int start, end;
- Function *our_func;
- int found_quote, quote_char;
-{
- char **matches, *temp;
-
- /* If the user wants to TRY to complete, but then wants to give
- up and use the default completion function, they set the
- variable rl_attempted_completion_function. */
- if (rl_attempted_completion_function)
- {
- matches = (*rl_attempted_completion_function) (text, start, end);
-
- if (matches || rl_attempted_completion_over)
- {
- rl_attempted_completion_over = 0;
- return (matches);
- }
- }
-
- /* Beware -- we're stripping the quotes here. Do this only if we know
- we are doing filename completion and the application has defined a
- filename dequoting function. */
- temp = (char *)NULL;
-
- if (found_quote && our_func == (Function *)filename_completion_function &&
- rl_filename_dequoting_function)
- {
- /* delete single and double quotes */
- temp = (*rl_filename_dequoting_function) (text, quote_char);
- text = temp; /* not freeing text is not a memory leak */
- }
-
- matches = completion_matches (text, (CPFunction *)our_func);
- FREE (temp);
- return matches;
-}
-
-/* Filter out duplicates in MATCHES. This frees up the strings in
- MATCHES. */
-static char **
-remove_duplicate_matches (matches)
- char **matches;
-{
- char *lowest_common;
- int i, j, newlen;
- char dead_slot;
- char **temp_array;
-
- /* Sort the items. */
- for (i = 0; matches[i]; i++)
- ;
-
- /* Sort the array without matches[0], since we need it to
- stay in place no matter what. */
- if (i)
- qsort (matches+1, i-1, sizeof (char *), _rl_qsort_string_compare);
-
- /* Remember the lowest common denominator for it may be unique. */
- lowest_common = savestring (matches[0]);
-
- for (i = newlen = 0; matches[i + 1]; i++)
- {
- if (strcmp (matches[i], matches[i + 1]) == 0)
- {
- free (matches[i]);
- matches[i] = (char *)&dead_slot;
- }
- else
- newlen++;
- }
-
- /* We have marked all the dead slots with (char *)&dead_slot.
- Copy all the non-dead entries into a new array. */
- temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
- for (i = j = 1; matches[i]; i++)
- {
- if (matches[i] != (char *)&dead_slot)
- temp_array[j++] = matches[i];
- }
- temp_array[j] = (char *)NULL;
-
- if (matches[0] != (char *)&dead_slot)
- free (matches[0]);
-
- /* Place the lowest common denominator back in [0]. */
- temp_array[0] = lowest_common;
-
- /* If there is one string left, and it is identical to the
- lowest common denominator, then the LCD is the string to
- insert. */
- if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
- {
- free (temp_array[1]);
- temp_array[1] = (char *)NULL;
- }
- return (temp_array);
-}
-
-/* Find the common prefix of the list of matches, and put it into
- matches[0]. */
-static int
-compute_lcd_of_matches (match_list, matches, text)
- char **match_list;
- int matches;
- char *text;
-{
- register int i, c1, c2, si;
- int low; /* Count of max-matched characters. */
-
- /* If only one match, just use that. Otherwise, compare each
- member of the list with the next, finding out where they
- stop matching. */
- if (matches == 1)
- {
- match_list[0] = match_list[1];
- match_list[1] = (char *)NULL;
- return 1;
- }
-
- for (i = 1, low = 100000; i < matches; i++)
- {
- if (_rl_completion_case_fold)
- {
- for (si = 0;
- (c1 = _rl_to_lower(match_list[i][si])) &&
- (c2 = _rl_to_lower(match_list[i + 1][si]));
- si++)
- if (c1 != c2)
- break;
- }
- else
- {
- for (si = 0;
- (c1 = match_list[i][si]) &&
- (c2 = match_list[i + 1][si]);
- si++)
- if (c1 != c2)
- break;
- }
-
- if (low > si)
- low = si;
- }
-
- /* If there were multiple matches, but none matched up to even the
- first character, and the user typed something, use that as the
- value of matches[0]. */
- if (low == 0 && text && *text)
- {
- match_list[0] = xmalloc (strlen (text) + 1);
- strcpy (match_list[0], text);
- }
- else
- {
- match_list[0] = xmalloc (low + 1);
- strncpy (match_list[0], match_list[1], low);
- match_list[0][low] = '\0';
- }
-
- return matches;
-}
-
-static int
-postprocess_matches (matchesp, matching_filenames)
- char ***matchesp;
- int matching_filenames;
-{
- char *t, **matches, **temp_matches;
- int nmatch, i;
-
- matches = *matchesp;
-
- /* It seems to me that in all the cases we handle we would like
- to ignore duplicate possiblilities. Scan for the text to
- insert being identical to the other completions. */
- if (rl_ignore_completion_duplicates)
- {
- temp_matches = remove_duplicate_matches (matches);
- free (matches);
- matches = temp_matches;
- }
-
- /* If we are matching filenames, then here is our chance to
- do clever processing by re-examining the list. Call the
- ignore function with the array as a parameter. It can
- munge the array, deleting matches as it desires. */
- if (rl_ignore_some_completions_function && matching_filenames)
- {
- for (nmatch = 1; matches[nmatch]; nmatch++)
- ;
- (void)(*rl_ignore_some_completions_function) (matches);
- if (matches == 0 || matches[0] == 0)
- {
- FREE (matches);
- *matchesp = (char **)0;
- return 0;
- }
- else
- {
- /* If we removed some matches, recompute the common prefix. */
- for (i = 1; matches[i]; i++)
- ;
- if (i > 1 && i < nmatch)
- {
- t = matches[0];
- compute_lcd_of_matches (matches, i - 1, t);
- FREE (t);
- }
- }
- }
-
- *matchesp = matches;
- return (1);
-}
-
-/* A convenience function for displaying a list of strings in
- columnar format on readline's output stream. MATCHES is the list
- of strings, in argv format, LEN is the number of strings in MATCHES,
- and MAX is the length of the longest string in MATCHES. */
-void
-rl_display_match_list (matches, len, max)
- char **matches;
- int len, max;
-{
- int count, limit, printed_len;
- int i, j, k, l;
- char *temp;
-
- /* How many items of MAX length can we fit in the screen window? */
- max += 2;
- limit = screenwidth / max;
- if (limit != 1 && (limit * max == screenwidth))
- limit--;
-
- /* Avoid a possible floating exception. If max > screenwidth,
- limit will be 0 and a divide-by-zero fault will result. */
- if (limit == 0)
- limit = 1;
-
- /* How many iterations of the printing loop? */
- count = (len + (limit - 1)) / limit;
-
- /* Watch out for special case. If LEN is less than LIMIT, then
- just do the inner printing loop.
- 0 < len <= limit implies count = 1. */
-
- /* Sort the items if they are not already sorted. */
- if (rl_ignore_completion_duplicates == 0)
- qsort (matches + 1, len, sizeof (char *), _rl_qsort_string_compare);
-
- crlf ();
-
- if (_rl_print_completions_horizontally == 0)
- {
- /* Print the sorted items, up-and-down alphabetically, like ls. */
- for (i = 1; i <= count; i++)
- {
- for (j = 0, l = i; j < limit; j++)
- {
- if (l > len || matches[l] == 0)
- break;
- else
- {
- temp = printable_part (matches[l]);
- printed_len = print_filename (temp, matches[l]);
-
- if (j + 1 < limit)
- for (k = 0; k < max - printed_len; k++)
- putc (' ', rl_outstream);
- }
- l += count;
- }
- crlf ();
- }
- }
- else
- {
- /* Print the sorted items, across alphabetically, like ls -x. */
- for (i = 1; matches[i]; i++)
- {
- temp = printable_part (matches[i]);
- printed_len = print_filename (temp, matches[i]);
- /* Have we reached the end of this line? */
- if (matches[i+1])
- {
- if (i && (limit > 1) && (i % limit) == 0)
- crlf ();
- else
- for (k = 0; k < max - printed_len; k++)
- putc (' ', rl_outstream);
- }
- }
- crlf ();
- }
-}
-
-/* Display MATCHES, a list of matching filenames in argv format. This
- handles the simple case -- a single match -- first. If there is more
- than one match, we compute the number of strings in the list and the
- length of the longest string, which will be needed by the display
- function. If the application wants to handle displaying the list of
- matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
- address of a function, and we just call it. If we're handling the
- display ourselves, we just call rl_display_match_list. We also check
- that the list of matches doesn't exceed the user-settable threshold,
- and ask the user if he wants to see the list if there are more matches
- than RL_COMPLETION_QUERY_ITEMS. */
-static void
-display_matches (matches)
- char **matches;
-{
- int len, max, i;
- char *temp;
-
- /* Move to the last visible line of a possibly-multiple-line command. */
- _rl_move_vert (_rl_vis_botlin);
-
- /* Handle simple case first. What if there is only one answer? */
- if (matches[1] == 0)
- {
- temp = printable_part (matches[0]);
- crlf ();
- print_filename (temp, matches[0]);
- crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return;
- }
-
- /* There is more than one answer. Find out how many there are,
- and find the maximum printed length of a single entry. */
- for (max = 0, i = 1; matches[i]; i++)
- {
- temp = printable_part (matches[i]);
- len = strlen (temp);
-
- if (len > max)
- max = len;
- }
-
- len = i - 1;
-
- /* If the caller has defined a display hook, then call that now. */
- if (rl_completion_display_matches_hook)
- {
- (*rl_completion_display_matches_hook) (matches, len, max);
- return;
- }
-
- /* If there are many items, then ask the user if she really wants to
- see them all. */
- if (len >= rl_completion_query_items)
- {
- crlf ();
- fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
- fflush (rl_outstream);
- if (get_y_or_n () == 0)
- {
- crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return;
- }
- }
-
- rl_display_match_list (matches, len, max);
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-}
-
-static char *
-make_quoted_replacement (match, mtype, qc)
- char *match;
- int mtype;
- char *qc; /* Pointer to quoting character, if any */
-{
- int should_quote, do_replace;
- char *replacement;
-
- /* If we are doing completion on quoted substrings, and any matches
- contain any of the completer_word_break_characters, then auto-
- matically prepend the substring with a quote character (just pick
- the first one from the list of such) if it does not already begin
- with a quote string. FIXME: Need to remove any such automatically
- inserted quote character when it no longer is necessary, such as
- if we change the string we are completing on and the new set of
- matches don't require a quoted substring. */
- replacement = match;
-
- should_quote = match && rl_completer_quote_characters &&
- rl_filename_completion_desired &&
- rl_filename_quoting_desired;
-
- if (should_quote)
- should_quote = should_quote && (!qc || !*qc ||
- (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc)));
-
- if (should_quote)
- {
- /* If there is a single match, see if we need to quote it.
- This also checks whether the common prefix of several
- matches needs to be quoted. */
- should_quote = rl_filename_quote_characters
- ? (rl_strpbrk (match, rl_filename_quote_characters) != 0)
- : 0;
-
- do_replace = should_quote ? mtype : NO_MATCH;
- /* Quote the replacement, since we found an embedded
- word break character in a potential match. */
- if (do_replace != NO_MATCH && rl_filename_quoting_function)
- replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
- }
- return (replacement);
-}
-
-static void
-insert_match (match, start, mtype, qc)
- char *match;
- int start, mtype;
- char *qc;
-{
- char *replacement;
- char oqc;
-
- oqc = qc ? *qc : '\0';
- replacement = make_quoted_replacement (match, mtype, qc);
-
- /* Now insert the match. */
- if (replacement)
- {
- /* Don't double an opening quote character. */
- if (qc && *qc && start && rl_line_buffer[start - 1] == *qc &&
- replacement[0] == *qc)
- start--;
- /* If make_quoted_replacement changed the quoting character, remove
- the opening quote and insert the (fully-quoted) replacement. */
- else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc &&
- replacement[0] != oqc)
- start--;
- _rl_replace_text (replacement, start, rl_point - 1);
- if (replacement != match)
- free (replacement);
- }
-}
-
-/* Append any necessary closing quote and a separator character to the
- just-inserted match. If the user has specified that directories
- should be marked by a trailing `/', append one of those instead. The
- default trailing character is a space. Returns the number of characters
- appended. */
-static int
-append_to_match (text, delimiter, quote_char)
- char *text;
- int delimiter, quote_char;
-{
- char temp_string[4], *filename;
- int temp_string_index;
- struct stat finfo;
-
- temp_string_index = 0;
- if (quote_char && rl_point && rl_line_buffer[rl_point - 1] != quote_char)
- temp_string[temp_string_index++] = quote_char;
-
- if (delimiter)
- temp_string[temp_string_index++] = delimiter;
- else if (rl_completion_append_character)
- temp_string[temp_string_index++] = rl_completion_append_character;
-
- temp_string[temp_string_index++] = '\0';
-
- if (rl_filename_completion_desired)
- {
- filename = tilde_expand (text);
- if (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
- {
- if (_rl_complete_mark_directories && rl_line_buffer[rl_point] != '/')
- rl_insert_text ("/");
- }
- else
- {
- if (rl_point == rl_end)
- rl_insert_text (temp_string);
- }
- free (filename);
- }
- else
- {
- if (rl_point == rl_end)
- rl_insert_text (temp_string);
- }
-
- return (temp_string_index);
-}
-
-static void
-insert_all_matches (matches, point, qc)
- char **matches;
- int point;
- char *qc;
-{
- int i;
- char *rp;
-
- rl_begin_undo_group ();
- /* remove any opening quote character; make_quoted_replacement will add
- it back. */
- if (qc && *qc && point && rl_line_buffer[point - 1] == *qc)
- point--;
- rl_delete_text (point, rl_point);
- rl_point = point;
-
- if (matches[1])
- {
- for (i = 1; matches[i]; i++)
- {
- rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[i])
- free (rp);
- }
- }
- else
- {
- rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[0])
- free (rp);
- }
- rl_end_undo_group ();
-}
-
-static void
-free_match_list (matches)
- char **matches;
-{
- register int i;
-
- for (i = 0; matches[i]; i++)
- free (matches[i]);
- free (matches);
-}
-
-/* Complete the word at or before point.
- WHAT_TO_DO says what to do with the completion.
- `?' means list the possible completions.
- TAB means do standard completion.
- `*' means insert all of the possible completions.
- `!' means to do standard completion, and list all possible completions if
- there is more than one. */
-int
-rl_complete_internal (what_to_do)
- int what_to_do;
-{
- char **matches;
- Function *our_func;
- int start, end, delimiter, found_quote, i;
- char *text, *saved_line_buffer;
- char quote_char;
-
- /* Only the completion entry function can change these. */
- rl_filename_completion_desired = 0;
- rl_filename_quoting_desired = 1;
- rl_completion_type = what_to_do;
-
- saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
- our_func = rl_completion_entry_function
- ? rl_completion_entry_function
- : (Function *)filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word. */
- end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_point)
- /* This (possibly) changes rl_point. If it returns a non-zero char,
- we know we have an open quote. */
- quote_char = find_completion_word (&found_quote, &delimiter);
-
- start = rl_point;
- rl_point = end;
-
- text = rl_copy_text (start, end);
- matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
- free (text);
-
- if (matches == 0)
- {
- ding ();
- FREE (saved_line_buffer);
- return (0);
- }
-
-#if 0
- /* If we are matching filenames, our_func will have been set to
- filename_completion_function */
- i = our_func == (Function *)filename_completion_function;
-#else
- /* If we are matching filenames, the attempted completion function will
- have set rl_filename_completion_desired to a non-zero value. The basic
- filename_completion_function does this. */
- i = rl_filename_completion_desired;
-#endif
-
- if (postprocess_matches (&matches, i) == 0)
- {
- ding ();
- FREE (saved_line_buffer);
- completion_changed_buffer = 0;
- return (0);
- }
-
- switch (what_to_do)
- {
- case TAB:
- case '!':
- /* Insert the first match with proper quoting. */
- if (*matches[0])
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
-
- /* If there are more matches, ring the bell to indicate.
- If we are in vi mode, Posix.2 says to not ring the bell.
- If the `show-all-if-ambiguous' variable is set, display
- all the matches immediately. Otherwise, if this was the
- only match, and we are hacking files, check the file to
- see if it was a directory. If so, and the `mark-directories'
- variable is set, add a '/' to the name. If not, and we
- are at the end of the line, then add a space. */
- if (matches[1])
- {
- if (what_to_do == '!')
- {
- display_matches (matches);
- break;
- }
- else if (rl_editing_mode != vi_mode)
- ding (); /* There are other matches remaining. */
- }
- else
- append_to_match (matches[0], delimiter, quote_char);
-
- break;
-
- case '*':
- insert_all_matches (matches, start, &quote_char);
- break;
-
- case '?':
- display_matches (matches);
- break;
-
- default:
- fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do);
- ding ();
- FREE (saved_line_buffer);
- return 1;
- }
-
- free_match_list (matches);
-
- /* Check to see if the line has changed through all of this manipulation. */
- if (saved_line_buffer)
- {
- completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
- free (saved_line_buffer);
- }
-
- return 0;
-}
-
-/***************************************************************/
-/* */
-/* Application-callable completion match generator functions */
-/* */
-/***************************************************************/
-
-/* Return an array of (char *) which is a list of completions for TEXT.
- If there are no completions, return a NULL pointer.
- The first entry in the returned array is the substitution for TEXT.
- The remaining entries are the possible completions.
- The array is terminated with a NULL pointer.
-
- ENTRY_FUNCTION is a function of two args, and returns a (char *).
- The first argument is TEXT.
- The second is a state argument; it should be zero on the first call, and
- non-zero on subsequent calls. It returns a NULL pointer to the caller
- when there are no more matches.
- */
-char **
-completion_matches (const char *text, CPFunction *entry_function)
-{
- /* Number of slots in match_list. */
- int match_list_size;
-
- /* The list of matches. */
- char **match_list;
-
- /* Number of matches actually found. */
- int matches;
-
- /* Temporary string binder. */
- char *string;
-
- matches = 0;
- match_list_size = 10;
- match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
- match_list[1] = (char *)NULL;
-
- while ((string = (*entry_function) (text, matches)))
- {
- if (matches + 1 == match_list_size)
- match_list = (char **)xrealloc
- (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
-
- match_list[++matches] = string;
- match_list[matches + 1] = (char *)NULL;
- }
-
- /* If there were any matches, then look through them finding out the
- lowest common denominator. That then becomes match_list[0]. */
- if (matches)
- compute_lcd_of_matches (match_list, matches, text);
- else /* There were no matches. */
- {
- free (match_list);
- match_list = (char **)NULL;
- }
- return (match_list);
-}
-
-/* A completion function for usernames.
- TEXT contains a partial username preceded by a random
- character (usually `~'). */
-char *
-username_completion_function (const char *text, int state)
-{
-#if defined (__GO32__) || defined (__WIN__) || defined (__OPENNT)
- return (char *)NULL;
-#else /* !__GO32__ */
- static char *username = (char *)NULL;
- static struct passwd *entry;
- static int namelen, first_char, first_char_loc;
- char *value;
-
- if (state == 0)
- {
- FREE (username);
-
- first_char = *text;
- first_char_loc = first_char == '~';
-
- username = savestring (&text[first_char_loc]);
- namelen = strlen (username);
- setpwent ();
- }
-
- while ((entry = getpwent ()))
- {
- /* Null usernames should result in all users as possible completions. */
- if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
- break;
- }
-
- if (entry == 0)
- {
- endpwent ();
- return ((char *)NULL);
- }
- else
- {
- value = xmalloc (2 + strlen (entry->pw_name));
-
- *value = *text;
-
- strcpy (value + first_char_loc, entry->pw_name);
-
- if (first_char == '~')
- rl_filename_completion_desired = 1;
-
- return (value);
- }
-#endif /* !__GO32__ */
-}
-
-/* Okay, now we write the entry_function for filename completion. In the
- general case. Note that completion in the shell is a little different
- because of all the pathnames that must be followed when looking up the
- completion for a command. */
-char *
-filename_completion_function (const char *text, int state)
-{
- static DIR *directory = (DIR *)NULL;
- static char *filename = (char *)NULL;
- static char *dirname = (char *)NULL;
- static char *users_dirname = (char *)NULL;
- static int filename_len;
- char *temp;
- int dirlen;
- struct dirent *entry;
-
- /* If we don't have any state, then do some initialization. */
- if (state == 0)
- {
- /* If we were interrupted before closing the directory or reading
- all of its contents, close it. */
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- FREE (dirname);
- FREE (filename);
- FREE (users_dirname);
-
- filename = savestring (text);
- if (*text == 0)
- text = ".";
- dirname = savestring (text);
-
- temp = strrchr (dirname, '/');
-
- if (temp)
- {
- strcpy (filename, ++temp);
- *temp = '\0';
- }
- else
- {
- dirname[0] = '.';
- dirname[1] = '\0';
- }
-
- /* We aren't done yet. We also support the "~user" syntax. */
-
- /* Save the version of the directory that the user typed. */
- users_dirname = savestring (dirname);
-
- if (*dirname == '~')
- {
- temp = tilde_expand (dirname);
- free (dirname);
- dirname = temp;
- }
-
- if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
- {
- free (users_dirname);
- users_dirname = savestring (dirname);
- }
-
- directory = opendir (dirname);
- filename_len = strlen (filename);
-
- rl_filename_completion_desired = 1;
- }
-
- /* At this point we should entertain the possibility of hacking wildcarded
- filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name
- contains globbing characters, then build an array of directories, and
- then map over that list while completing. */
- /* *** UNIMPLEMENTED *** */
-
- /* Now that we have some state, we can read the directory. */
-
- entry = (struct dirent *)NULL;
- while (directory && (entry = readdir (directory)))
- {
- /* Special case for no filename.
- All entries except "." and ".." match. */
- if (filename_len == 0)
- {
- if (entry->d_name[0] != '.' ||
- (entry->d_name[1] &&
- (entry->d_name[1] != '.' || entry->d_name[2])))
- break;
- }
- else
- {
- /* Otherwise, if these match up to the length of filename, then
- it is a match. */
- if (_rl_completion_case_fold)
- {
- if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) &&
- (((int)D_NAMLEN (entry)) >= filename_len) &&
- (_rl_strnicmp (filename, entry->d_name, filename_len) == 0))
- break;
- }
- else
- {
- if ((entry->d_name[0] == filename[0]) &&
- (((int)D_NAMLEN (entry)) >= filename_len) &&
- (strncmp (filename, entry->d_name, filename_len) == 0))
- break;
- }
- }
- }
-
- if (entry == 0)
- {
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- if (dirname)
- {
- free (dirname);
- dirname = (char *)NULL;
- }
- if (filename)
- {
- free (filename);
- filename = (char *)NULL;
- }
- if (users_dirname)
- {
- free (users_dirname);
- users_dirname = (char *)NULL;
- }
-
- return (char *)NULL;
- }
- else
- {
- /* dirname && (strcmp (dirname, ".") != 0) */
- if (dirname && (dirname[0] != '.' || dirname[1]))
- {
- if (rl_complete_with_tilde_expansion && *users_dirname == '~')
- {
- dirlen = strlen (dirname);
- temp = xmalloc (2 + dirlen + D_NAMLEN (entry));
- strcpy (temp, dirname);
- /* Canonicalization cuts off any final slash present. We
- may need to add it back. */
- if (dirname[dirlen - 1] != '/')
- {
- temp[dirlen++] = '/';
- temp[dirlen] = '\0';
- }
- }
- else
- {
- dirlen = strlen (users_dirname);
- temp = xmalloc (1 + dirlen + D_NAMLEN (entry));
- strcpy (temp, users_dirname);
- }
-
- strcpy (temp + dirlen, entry->d_name);
- }
- else
- temp = savestring (entry->d_name);
-
- return (temp);
- }
-}
-
-/* An initial implementation of a menu completion function a la tcsh. The
- first time (if the last readline command was not rl_menu_complete), we
- generate the list of matches. This code is very similar to the code in
- rl_complete_internal -- there should be a way to combine the two. Then,
- for each item in the list of matches, we insert the match in an undoable
- fashion, with the appropriate character appended (this happens on the
- second and subsequent consecutive calls to rl_menu_complete). When we
- hit the end of the match list, we restore the original unmatched text,
- ring the bell, and reset the counter to zero. */
-int
-rl_menu_complete (int count, int ignore __attribute__((unused)))
-{
- Function *our_func;
- int matching_filenames, found_quote;
-
- static char *orig_text;
- static char **matches = (char **)0;
- static int match_list_index = 0;
- static int match_list_size = 0;
- static int orig_start, orig_end;
- static char quote_char;
- static int delimiter;
-
- /* The first time through, we generate the list of matches and set things
- up to insert them. */
- if (rl_last_func != rl_menu_complete)
- {
- /* Clean up from previous call, if any. */
- FREE (orig_text);
- if (matches)
- {
- for (match_list_index = 0; matches[match_list_index]; match_list_index++)
- free (matches[match_list_index]);
- free (matches);
- }
-
- match_list_index = match_list_size = 0;
- matches = (char **)NULL;
-
- /* Only the completion entry function can change these. */
- rl_filename_completion_desired = 0;
- rl_filename_quoting_desired = 1;
- rl_completion_type = '%';
-
- our_func = rl_completion_entry_function
- ? rl_completion_entry_function
- : (Function *)filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word. */
- orig_end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_point)
- /* This (possibly) changes rl_point. If it returns a non-zero char,
- we know we have an open quote. */
- quote_char = find_completion_word (&found_quote, &delimiter);
-
- orig_start = rl_point;
- rl_point = orig_end;
-
- orig_text = rl_copy_text (orig_start, orig_end);
- matches = gen_completion_matches (orig_text, orig_start, orig_end,
- our_func, found_quote, quote_char);
-
-#if 0
- /* If we are matching filenames, our_func will have been set to
- filename_completion_function */
- matching_filenames = our_func == (Function *)filename_completion_function;
-#else
- /* If we are matching filenames, the attempted completion function will
- have set rl_filename_completion_desired to a non-zero value. The basic
- filename_completion_function does this. */
- matching_filenames = rl_filename_completion_desired;
-#endif
- if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
- {
- ding ();
- FREE (matches);
- matches = (char **)0;
- FREE (orig_text);
- orig_text = (char *)0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- for (match_list_size = 0; matches[match_list_size]; match_list_size++)
- ;
- /* matches[0] is lcd if match_list_size > 1, but the circular buffer
- code below should take care of it. */
- }
-
- /* Now we have the list of matches. Replace the text between
- rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
- matches[match_list_index], and add any necessary closing char. */
-
- if (matches == 0 || match_list_size == 0)
- {
- ding ();
- FREE (matches);
- matches = (char **)0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- match_list_index = (match_list_index + count) % match_list_size;
- if (match_list_index < 0)
- match_list_index += match_list_size;
-
- if (match_list_index == 0 && match_list_size > 1)
- {
- ding ();
- insert_match (orig_text, orig_start, MULT_MATCH, &quote_char);
- }
- else
- {
- insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
- append_to_match (matches[match_list_index], delimiter, quote_char);
- }
-
- completion_changed_buffer = 1;
- return (0);
-}
diff --git a/readline/configure b/readline/configure
deleted file mode 100755
index 454a177e35d..00000000000
--- a/readline/configure
+++ /dev/null
@@ -1,2849 +0,0 @@
-#! /bin/sh
-
-# From configure.in for Readline 4.0, version 2.14, from autoconf version 2.12
-LIBVERSION=4.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.12
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-
-# Defaults:
-ac_help=
-ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
---with-curses use the curses library instead of the termcap library"
-
-# Initialize some variables set by options.
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
-exec_prefix=NONE
-host=NONE
-no_create=
-nonopt=NONE
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-target=NONE
-verbose=
-x_includes=NONE
-x_libraries=NONE
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
-ac_prev=
-for ac_option
-do
-
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case "$ac_option" in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir="$ac_optarg" ;;
-
- -disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.12"
- exit 0 ;;
-
- -with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "with_${ac_package}='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
-
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
- ;;
-
- *)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>./config.log
-
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
-
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
-do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
- esac
-done
-
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
-
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=readline.h
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
- else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
- fi
-fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
-
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
-else
- echo "creating cache $cache_file"
- > $cache_file
-fi
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-
-
-
-
-
-ac_aux_dir=
-for ac_dir in ./support $srcdir/./support; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in ./support $srcdir/./support" 1>&2; exit 1; }
-fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
-
-
-
-# Make sure we can run config.sub.
-if $ac_config_sub sun4 >/dev/null 2>&1; then :
-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:646: checking host system type" >&5
-
-host_alias=$host
-case "$host_alias" in
-NONE)
- case $nonopt in
- NONE)
- if host_alias=`$ac_config_guess`; then :
- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
- fi ;;
- *) host_alias=$nonopt ;;
- esac ;;
-esac
-
-host=`$ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$ac_t""$host" 1>&6
-
-
-opt_curses=no
-opt_shared=no
-
-# Check whether --with-curses or --without-curses was given.
-if test "${with_curses+set}" = set; then
- withval="$with_curses"
- opt_curses=$withval
-fi
-
-
-if test "$opt_curses" = "yes"; then
- prefer_curses=yes
-fi
-
-# We want these before the checks, so the checks can modify their values.
-test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1
-
-# Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:687: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:716: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- ac_prog_rejected=no
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
- fi
-fi
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:764: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext <<EOF
-#line 774 "configure"
-#include "confdefs.h"
-main(){return(0);}
-EOF
-if { (eval echo configure:778: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
- else
- ac_cv_prog_cc_cross=yes
- fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
-fi
-rm -fr conftest*
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:798: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:803: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:812: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
-else
- ac_cv_prog_gcc=no
-fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
-
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
- ac_test_CFLAGS="${CFLAGS+set}"
- ac_save_CFLAGS="$CFLAGS"
- CFLAGS=
- echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:827: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_g=yes
-else
- ac_cv_prog_cc_g=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
- if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
- elif test $ac_cv_prog_cc_g = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-O2"
- fi
-else
- GCC=
- test "${CFLAGS+set}" = set || CFLAGS="-g"
-fi
-
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:855: checking how to run the C preprocessor" >&5
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 870 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:876: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 887 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:893: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
-fi
-rm -f conftest*
-fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
-fi
- CPP="$ac_cv_prog_CPP"
-else
- ac_cv_prog_CPP="$CPP"
-fi
-echo "$ac_t""$CPP" 1>&6
-
-ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
-echo "configure:917: checking for minix/config.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 922 "configure"
-#include "confdefs.h"
-#include <minix/config.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- MINIX=yes
-else
- echo "$ac_t""no" 1>&6
-MINIX=
-fi
-
-if test "$MINIX" = yes; then
- cat >> confdefs.h <<\EOF
-#define _POSIX_SOURCE 1
-EOF
-
- cat >> confdefs.h <<\EOF
-#define _POSIX_1_SOURCE 2
-EOF
-
- cat >> confdefs.h <<\EOF
-#define _MINIX 1
-EOF
-
-fi
-
-
-# If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS.
-test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O"
-
-if test $ac_cv_prog_gcc = yes; then
- echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:970: checking whether ${CC-cc} needs -traditional" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_pattern="Autoconf.*'x'"
- cat > conftest.$ac_ext <<EOF
-#line 976 "configure"
-#include "confdefs.h"
-#include <sgtty.h>
-Autoconf TIOCGETP
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "$ac_pattern" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_prog_gcc_traditional=yes
-else
- rm -rf conftest*
- ac_cv_prog_gcc_traditional=no
-fi
-rm -f conftest*
-
-
- if test $ac_cv_prog_gcc_traditional = no; then
- cat > conftest.$ac_ext <<EOF
-#line 994 "configure"
-#include "confdefs.h"
-#include <termio.h>
-Autoconf TCGETA
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "$ac_pattern" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_prog_gcc_traditional=yes
-fi
-rm -f conftest*
-
- fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
- if test $ac_cv_prog_gcc_traditional = yes; then
- CC="$CC -traditional"
- fi
-fi
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1026: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- for ac_prog in ginstall installbsd scoinst install; do
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- # OSF/1 installbsd also uses dspmsg, but is usable.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
- done
- IFS="$ac_save_IFS"
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL="$ac_cv_path_install"
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL="$ac_install_sh"
- fi
-fi
-echo "$ac_t""$INSTALL" 1>&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-# Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1078: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$AR"; then
- ac_cv_prog_AR="$AR" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_AR="ar"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-AR="$ac_cv_prog_AR"
-if test -n "$AR"; then
- echo "$ac_t""$AR" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-test -n "$ARFLAGS" || ARFLAGS="cr"
-# Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1107: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
-fi
-fi
-RANLIB="$ac_cv_prog_RANLIB"
-if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-
-MAKE_SHELL=/bin/sh
-
-
-echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:1138: checking return type of signal handlers" >&5
-if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1143 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <signal.h>
-#ifdef signal
-#undef signal
-#endif
-#ifdef __cplusplus
-extern "C" void (*signal (int, void (*)(int)))(int);
-#else
-void (*signal ()) ();
-#endif
-
-int main() {
-int i;
-; return 0; }
-EOF
-if { (eval echo configure:1160: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_type_signal=void
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_type_signal=int
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_type_signal" 1>&6
-cat >> confdefs.h <<EOF
-#define RETSIGTYPE $ac_cv_type_signal
-EOF
-
-
-
-echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
-echo "configure:1180: checking whether stat file-mode macros are broken" >&5
-if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1185 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if defined(S_ISBLK) && defined(S_IFDIR)
-# if S_ISBLK (S_IFDIR)
-You lose.
-# endif
-#endif
-
-#if defined(S_ISBLK) && defined(S_IFCHR)
-# if S_ISBLK (S_IFCHR)
-You lose.
-# endif
-#endif
-
-#if defined(S_ISLNK) && defined(S_IFREG)
-# if S_ISLNK (S_IFREG)
-You lose.
-# endif
-#endif
-
-#if defined(S_ISSOCK) && defined(S_IFREG)
-# if S_ISSOCK (S_IFREG)
-You lose.
-# endif
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "You lose" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_header_stat_broken=yes
-else
- rm -rf conftest*
- ac_cv_header_stat_broken=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_header_stat_broken" 1>&6
-if test $ac_cv_header_stat_broken = yes; then
- cat >> confdefs.h <<\EOF
-#define STAT_MACROS_BROKEN 1
-EOF
-
-fi
-
-ac_header_dirent=no
-for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1240: checking for $ac_hdr that defines DIR" >&5
-if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1245 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <$ac_hdr>
-int main() {
-DIR *dirp = 0;
-; return 0; }
-EOF
-if { (eval echo configure:1253: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- eval "ac_cv_header_dirent_$ac_safe=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_dirent_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
- ac_header_dirent=$ac_hdr; break
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
-if test $ac_header_dirent = dirent.h; then
-echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1278: checking for opendir in -ldir" >&5
-ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldir $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1286 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir();
-
-int main() {
-opendir()
-; return 0; }
-EOF
-if { (eval echo configure:1297: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- LIBS="$LIBS -ldir"
-else
- echo "$ac_t""no" 1>&6
-fi
-
-else
-echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1319: checking for opendir in -lx" >&5
-ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lx $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1327 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir();
-
-int main() {
-opendir()
-; return 0; }
-EOF
-if { (eval echo configure:1338: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- LIBS="$LIBS -lx"
-else
- echo "$ac_t""no" 1>&6
-fi
-
-fi
-
-
-for ac_func in strcasecmp select setenv putenv tcgetattr setlocale lstat
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1364: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1369 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-
-echo $ac_n "checking for working strcoll""... $ac_c" 1>&6
-echo "configure:1418: checking for working strcoll" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strcoll_works'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- ac_cv_func_strcoll_works=no
-else
- cat > conftest.$ac_ext <<EOF
-#line 1426 "configure"
-#include "confdefs.h"
-#include <string.h>
-main ()
-{
- exit (strcoll ("abc", "def") >= 0 ||
- strcoll ("ABC", "DEF") >= 0 ||
- strcoll ("123", "456") >= 0);
-}
-EOF
-if { (eval echo configure:1436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_strcoll_works=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_strcoll_works=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$ac_cv_func_strcoll_works" 1>&6
-if test $ac_cv_func_strcoll_works = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_STRCOLL 1
-EOF
-
-fi
-
-
-for ac_hdr in unistd.h stdlib.h varargs.h stdarg.h string.h \
- sys/ptem.h sys/pte.h sys/stream.h sys/select.h \
- termcap.h termios.h termio.h sys/file.h locale.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1465: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1470 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1475: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-
-
-echo $ac_n "checking for type of signal functions""... $ac_c" 1>&6
-echo "configure:1504: checking for type of signal functions" >&5
-if eval "test \"`echo '$''{'bash_cv_signal_vintage'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 1510 "configure"
-#include "confdefs.h"
-#include <signal.h>
-int main() {
-
- sigset_t ss;
- struct sigaction sa;
- sigemptyset(&ss); sigsuspend(&ss);
- sigaction(SIGINT, &sa, (struct sigaction *) 0);
- sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0);
-
-; return 0; }
-EOF
-if { (eval echo configure:1523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- bash_cv_signal_vintage=posix
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 1532 "configure"
-#include "confdefs.h"
-#include <signal.h>
-int main() {
-
- int mask = sigmask(SIGINT);
- sigsetmask(mask); sigblock(mask); sigpause(mask);
-
-; return 0; }
-EOF
-if { (eval echo configure:1542: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- bash_cv_signal_vintage=4.2bsd
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 1551 "configure"
-#include "confdefs.h"
-
- #include <signal.h>
- RETSIGTYPE foo() { }
-int main() {
-
- int mask = sigmask(SIGINT);
- sigset(SIGINT, foo); sigrelse(SIGINT);
- sighold(SIGINT); sigpause(SIGINT);
-
-; return 0; }
-EOF
-if { (eval echo configure:1564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- bash_cv_signal_vintage=svr3
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_signal_vintage=v7
-
-fi
-rm -f conftest*
-
-fi
-rm -f conftest*
-
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$bash_cv_signal_vintage" 1>&6
-if test "$bash_cv_signal_vintage" = posix; then
-cat >> confdefs.h <<\EOF
-#define HAVE_POSIX_SIGNALS 1
-EOF
-
-elif test "$bash_cv_signal_vintage" = "4.2bsd"; then
-cat >> confdefs.h <<\EOF
-#define HAVE_BSD_SIGNALS 1
-EOF
-
-elif test "$bash_cv_signal_vintage" = svr3; then
-cat >> confdefs.h <<\EOF
-#define HAVE_USG_SIGHOLD 1
-EOF
-
-fi
-
-
-
-echo $ac_n "checking if signal handlers must be reinstalled when invoked""... $ac_c" 1>&6
-echo "configure:1605: checking if signal handlers must be reinstalled when invoked" >&5
-if eval "test \"`echo '$''{'bash_cv_must_reinstall_sighandlers'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- echo "configure: warning: cannot check signal handling if cross compiling -- defaulting to no" 1>&2
- bash_cv_must_reinstall_sighandlers=no
-
-else
- cat > conftest.$ac_ext <<EOF
-#line 1615 "configure"
-#include "confdefs.h"
-
-#include <signal.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-typedef RETSIGTYPE sigfunc();
-
-int nsigint;
-
-#ifdef HAVE_POSIX_SIGNALS
-sigfunc *
-set_signal_handler(sig, handler)
- int sig;
- sigfunc *handler;
-{
- struct sigaction act, oact;
- act.sa_handler = handler;
- act.sa_flags = 0;
- sigemptyset (&act.sa_mask);
- sigemptyset (&oact.sa_mask);
- sigaction (sig, &act, &oact);
- return (oact.sa_handler);
-}
-#else
-#define set_signal_handler(s, h) signal(s, h)
-#endif
-
-RETSIGTYPE
-sigint(s)
-int s;
-{
- nsigint++;
-}
-
-main()
-{
- nsigint = 0;
- set_signal_handler(SIGINT, sigint);
- kill((int)getpid(), SIGINT);
- kill((int)getpid(), SIGINT);
- exit(nsigint != 2);
-}
-
-EOF
-if { (eval echo configure:1662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- bash_cv_must_reinstall_sighandlers=no
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- bash_cv_must_reinstall_sighandlers=yes
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$bash_cv_must_reinstall_sighandlers" 1>&6
-if test $bash_cv_must_reinstall_sighandlers = yes; then
-cat >> confdefs.h <<\EOF
-#define MUST_REINSTALL_SIGHANDLERS 1
-EOF
-
-fi
-
-
-
-echo $ac_n "checking for presence of POSIX-style sigsetjmp/siglongjmp""... $ac_c" 1>&6
-echo "configure:1687: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5
-if eval "test \"`echo '$''{'bash_cv_func_sigsetjmp'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- echo "configure: warning: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" 1>&2
- bash_cv_func_sigsetjmp=missing
-
-else
- cat > conftest.$ac_ext <<EOF
-#line 1697 "configure"
-#include "confdefs.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <signal.h>
-#include <setjmp.h>
-
-main()
-{
-#if !defined (_POSIX_VERSION) || !defined (HAVE_POSIX_SIGNALS)
-exit (1);
-#else
-
-int code;
-sigset_t set, oset;
-sigjmp_buf xx;
-
-/* get the mask */
-sigemptyset(&set);
-sigemptyset(&oset);
-sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &set);
-sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset);
-
-/* save it */
-code = sigsetjmp(xx, 1);
-if (code)
- exit(0); /* could get sigmask and compare to oset here. */
-
-/* change it */
-sigaddset(&set, SIGINT);
-sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
-
-/* and siglongjmp */
-siglongjmp(xx, 10);
-exit(1);
-#endif
-}
-EOF
-if { (eval echo configure:1738: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- bash_cv_func_sigsetjmp=present
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- bash_cv_func_sigsetjmp=missing
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$bash_cv_func_sigsetjmp" 1>&6
-if test $bash_cv_func_sigsetjmp = present; then
-cat >> confdefs.h <<\EOF
-#define HAVE_POSIX_SIGSETJMP 1
-EOF
-
-fi
-
-echo $ac_n "checking for lstat""... $ac_c" 1>&6
-echo "configure:1761: checking for lstat" >&5
-if eval "test \"`echo '$''{'bash_cv_func_lstat'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1766 "configure"
-#include "confdefs.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-int main() {
- lstat(".",(struct stat *)0);
-; return 0; }
-EOF
-if { (eval echo configure:1776: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- bash_cv_func_lstat=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_func_lstat=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_func_lstat" 1>&6
-if test $bash_cv_func_lstat = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_LSTAT 1
-EOF
-
-fi
-
-echo $ac_n "checking whether programs are able to redeclare getpw functions""... $ac_c" 1>&6
-echo "configure:1797: checking whether programs are able to redeclare getpw functions" >&5
-if eval "test \"`echo '$''{'bash_cv_can_redecl_getpw'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1802 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <pwd.h>
-extern struct passwd *getpwent();
-extern struct passwd *getpwuid();
-extern struct passwd *getpwnam();
-int main() {
-struct passwd *z; z = getpwent(); z = getpwuid(0); z = getpwnam("root");
-; return 0; }
-EOF
-if { (eval echo configure:1813: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_can_redecl_getpw=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_can_redecl_getpw=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_can_redecl_getpw" 1>&6
-if test $bash_cv_can_redecl_getpw = no; then
-cat >> confdefs.h <<\EOF
-#define HAVE_GETPW_DECLS 1
-EOF
-
-fi
-
-
-echo $ac_n "checking whether or not strcoll and strcmp differ""... $ac_c" 1>&6
-echo "configure:1835: checking whether or not strcoll and strcmp differ" >&5
-if eval "test \"`echo '$''{'bash_cv_func_strcoll_broken'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- echo "configure: warning: cannot check strcoll if cross compiling -- defaulting to no" 1>&2
- bash_cv_func_strcoll_broken=no
-
-else
- cat > conftest.$ac_ext <<EOF
-#line 1845 "configure"
-#include "confdefs.h"
-
-#include <stdio.h>
-#if defined (HAVE_LOCALE_H)
-#include <locale.h>
-#endif
-
-main(c, v)
-int c;
-char *v[];
-{
- int r1, r2;
- char *deflocale, *defcoll;
-
-#ifdef HAVE_SETLOCALE
- deflocale = setlocale(LC_ALL, "");
- defcoll = setlocale(LC_COLLATE, "");
-#endif
-
-#ifdef HAVE_STRCOLL
- /* These two values are taken from tests/glob-test. */
- r1 = strcoll("abd", "aXd");
-#else
- r1 = 0;
-#endif
- r2 = strcmp("abd", "aXd");
-
- /* These two should both be greater than 0. It is permissible for
- a system to return different values, as long as the sign is the
- same. */
-
- /* Exit with 1 (failure) if these two values are both > 0, since
- this tests whether strcoll(3) is broken with respect to strcmp(3)
- in the default locale. */
- exit (r1 > 0 && r2 > 0);
-}
-
-EOF
-if { (eval echo configure:1884: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- bash_cv_func_strcoll_broken=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- bash_cv_func_strcoll_broken=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$bash_cv_func_strcoll_broken" 1>&6
-if test $bash_cv_func_strcoll_broken = yes; then
-cat >> confdefs.h <<\EOF
-#define STRCOLL_BROKEN 1
-EOF
-
-fi
-
-
-echo $ac_n "checking whether signal handlers are of type void""... $ac_c" 1>&6
-echo "configure:1908: checking whether signal handlers are of type void" >&5
-if eval "test \"`echo '$''{'bash_cv_void_sighandler'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1913 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <signal.h>
-#ifdef signal
-#undef signal
-#endif
-#ifdef __cplusplus
-extern "C"
-#endif
-void (*signal ()) ();
-int main() {
-int i;
-; return 0; }
-EOF
-if { (eval echo configure:1928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_void_sighandler=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_void_sighandler=no
-fi
-rm -f conftest*
-fi
-echo "$ac_t""$bash_cv_void_sighandler" 1>&6
-if test $bash_cv_void_sighandler = yes; then
-cat >> confdefs.h <<\EOF
-#define VOID_SIGHANDLER 1
-EOF
-
-fi
-
-echo $ac_n "checking for TIOCGWINSZ in sys/ioctl.h""... $ac_c" 1>&6
-echo "configure:1948: checking for TIOCGWINSZ in sys/ioctl.h" >&5
-if eval "test \"`echo '$''{'bash_cv_tiocgwinsz_in_ioctl'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1953 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/ioctl.h>
-int main() {
-int x = TIOCGWINSZ;
-; return 0; }
-EOF
-if { (eval echo configure:1961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_tiocgwinsz_in_ioctl=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_tiocgwinsz_in_ioctl=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_tiocgwinsz_in_ioctl" 1>&6
-if test $bash_cv_tiocgwinsz_in_ioctl = yes; then
-cat >> confdefs.h <<\EOF
-#define GWINSZ_IN_SYS_IOCTL 1
-EOF
-
-fi
-
-echo $ac_n "checking for TIOCSTAT in sys/ioctl.h""... $ac_c" 1>&6
-echo "configure:1982: checking for TIOCSTAT in sys/ioctl.h" >&5
-if eval "test \"`echo '$''{'bash_cv_tiocstat_in_ioctl'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1987 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/ioctl.h>
-int main() {
-int x = TIOCSTAT;
-; return 0; }
-EOF
-if { (eval echo configure:1995: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_tiocstat_in_ioctl=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_tiocstat_in_ioctl=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_tiocstat_in_ioctl" 1>&6
-if test $bash_cv_tiocstat_in_ioctl = yes; then
-cat >> confdefs.h <<\EOF
-#define TIOCSTAT_IN_SYS_IOCTL 1
-EOF
-
-fi
-
-echo $ac_n "checking for FIONREAD in sys/ioctl.h""... $ac_c" 1>&6
-echo "configure:2016: checking for FIONREAD in sys/ioctl.h" >&5
-if eval "test \"`echo '$''{'bash_cv_fionread_in_ioctl'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2021 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/ioctl.h>
-int main() {
-int x = FIONREAD;
-; return 0; }
-EOF
-if { (eval echo configure:2029: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_fionread_in_ioctl=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_fionread_in_ioctl=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_fionread_in_ioctl" 1>&6
-if test $bash_cv_fionread_in_ioctl = yes; then
-cat >> confdefs.h <<\EOF
-#define FIONREAD_IN_SYS_IOCTL 1
-EOF
-
-fi
-
-echo $ac_n "checking for speed_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:2050: checking for speed_t in sys/types.h" >&5
-if eval "test \"`echo '$''{'bash_cv_speed_t_in_sys_types'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2055 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-int main() {
-speed_t x;
-; return 0; }
-EOF
-if { (eval echo configure:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_speed_t_in_sys_types=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_speed_t_in_sys_types=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_speed_t_in_sys_types" 1>&6
-if test $bash_cv_speed_t_in_sys_types = yes; then
-cat >> confdefs.h <<\EOF
-#define SPEED_T_IN_SYS_TYPES 1
-EOF
-
-fi
-
-echo $ac_n "checking for struct winsize in sys/ioctl.h and termios.h""... $ac_c" 1>&6
-echo "configure:2083: checking for struct winsize in sys/ioctl.h and termios.h" >&5
-if eval "test \"`echo '$''{'bash_cv_struct_winsize_header'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2088 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/ioctl.h>
-int main() {
-struct winsize x;
-; return 0; }
-EOF
-if { (eval echo configure:2096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_struct_winsize_header=ioctl_h
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- cat > conftest.$ac_ext <<EOF
-#line 2104 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <termios.h>
-int main() {
-struct winsize x;
-; return 0; }
-EOF
-if { (eval echo configure:2112: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_struct_winsize_header=termios_h
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_struct_winsize_header=other
-fi
-rm -f conftest*
-
-fi
-rm -f conftest*
-fi
-
-if test $bash_cv_struct_winsize_header = ioctl_h; then
- echo "$ac_t""sys/ioctl.h" 1>&6
- cat >> confdefs.h <<\EOF
-#define STRUCT_WINSIZE_IN_SYS_IOCTL 1
-EOF
-
-elif test $bash_cv_struct_winsize_header = termios_h; then
- echo "$ac_t""termios.h" 1>&6
- cat >> confdefs.h <<\EOF
-#define STRUCT_WINSIZE_IN_TERMIOS 1
-EOF
-
-else
- echo "$ac_t""not found" 1>&6
-fi
-
-
-echo $ac_n "checking if struct dirent has a d_ino member""... $ac_c" 1>&6
-echo "configure:2145: checking if struct dirent has a d_ino member" >&5
-if eval "test \"`echo '$''{'bash_cv_dirent_has_dino'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2150 "configure"
-#include "confdefs.h"
-
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-#else
-# define dirent direct
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* SYSNDIR */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* SYSDIR */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif /* HAVE_DIRENT_H */
-
-int main() {
-
-struct dirent d; int z; z = d.d_ino;
-
-; return 0; }
-EOF
-if { (eval echo configure:2179: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_dirent_has_dino=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_dirent_has_dino=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_dirent_has_dino" 1>&6
-if test $bash_cv_dirent_has_dino = yes; then
-cat >> confdefs.h <<\EOF
-#define STRUCT_DIRENT_HAS_D_INO 1
-EOF
-
-fi
-
-
-echo $ac_n "checking if struct dirent has a d_fileno member""... $ac_c" 1>&6
-echo "configure:2201: checking if struct dirent has a d_fileno member" >&5
-if eval "test \"`echo '$''{'bash_cv_dirent_has_d_fileno'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2206 "configure"
-#include "confdefs.h"
-
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-#else
-# define dirent direct
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* SYSNDIR */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* SYSDIR */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif /* HAVE_DIRENT_H */
-
-int main() {
-
-struct dirent d; int z; z = d.d_fileno;
-
-; return 0; }
-EOF
-if { (eval echo configure:2235: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- bash_cv_dirent_has_d_fileno=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- bash_cv_dirent_has_d_fileno=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$bash_cv_dirent_has_d_fileno" 1>&6
-if test $bash_cv_dirent_has_d_fileno = yes; then
-cat >> confdefs.h <<\EOF
-#define STRUCT_DIRENT_HAS_D_FILENO 1
-EOF
-
-fi
-
-
-case "$host_os" in
-aix*) prefer_curses=yes ;;
-esac
-
-if test "X$bash_cv_termcap_lib" = "X"; then
-_bash_needmsg=yes
-else
-echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6
-echo "configure:2264: checking which library has the termcap functions" >&5
-_bash_needmsg=
-fi
-if eval "test \"`echo '$''{'bash_cv_termcap_lib'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6
-echo "configure:2271: checking for tgetent in -ltermcap" >&5
-ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ltermcap $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2279 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- bash_cv_termcap_lib=libtermcap
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6
-echo "configure:2309: checking for tgetent in -lcurses" >&5
-ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lcurses $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2317 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:2328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- bash_cv_termcap_lib=libcurses
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6
-echo "configure:2347: checking for tgetent in -lncurses" >&5
-ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lncurses $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2355 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:2366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- bash_cv_termcap_lib=libncurses
-else
- echo "$ac_t""no" 1>&6
-bash_cv_termcap_lib=gnutermcap
-fi
-
-fi
-
-fi
-
-fi
-
-if test "X$_bash_needmsg" = "Xyes"; then
-echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6
-echo "configure:2395: checking which library has the termcap functions" >&5
-fi
-echo "$ac_t""using $bash_cv_termcap_lib" 1>&6
-if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then
-LDFLAGS="$LDFLAGS -L./lib/termcap"
-TERMCAP_LIB="./lib/termcap/libtermcap.a"
-TERMCAP_DEP="./lib/termcap/libtermcap.a"
-elif test $bash_cv_termcap_lib = libtermcap && test -z "$prefer_curses"; then
-TERMCAP_LIB=-ltermcap
-TERMCAP_DEP=
-elif test $bash_cv_termcap_lib = libncurses; then
-TERMCAP_LIB=-lncurses
-TERMCAP_DEP=
-else
-TERMCAP_LIB=-lcurses
-TERMCAP_DEP=
-fi
-
-if test "$TERMCAP_LIB" = "./lib/termcap/libtermcap.a"; then
- TERMCAP_LIB=-ltermcap #default
-fi
-
-case "$host_cpu" in
-*cray*) LOCAL_CFLAGS=-DCRAY ;;
-esac
-
-case "$host_os" in
-isc*) LOCAL_CFLAGS=-Disc386 ;;
-esac
-
-# shared library configuration section
-#
-# Shared object configuration section. These values are generated by
-# ${srcdir}/support/shobj-conf
-#
-if test -f ${srcdir}/support/shobj-conf; then
- echo $ac_n "checking configuration for building shared libraries""... $ac_c" 1>&6
-echo "configure:2432: checking configuration for building shared libraries" >&5
- eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C ${CC} -c ${host_cpu} -o ${host_os} -v ${host_vendor}`
-
-
-
-
-
-
-
-
-
-
-
-
- echo "$ac_t""$SHLIB_STATUS" 1>&6
-fi
-
-BUILD_DIR=`pwd`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
-fi
-
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
-DEFS=-DHAVE_CONFIG_H
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
-
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
-# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
-# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
-
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
-do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.12"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
-done
-
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
-
-trap 'rm -fr `echo "Makefile doc/Makefile examples/Makefile shlib/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@host@%$host%g
-s%@host_alias@%$host_alias%g
-s%@host_cpu@%$host_cpu%g
-s%@host_vendor@%$host_vendor%g
-s%@host_os@%$host_os%g
-s%@CC@%$CC%g
-s%@CPP@%$CPP%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@AR@%$AR%g
-s%@RANLIB@%$RANLIB%g
-s%@MAKE_SHELL@%$MAKE_SHELL%g
-s%@SHOBJ_CC@%$SHOBJ_CC%g
-s%@SHOBJ_CFLAGS@%$SHOBJ_CFLAGS%g
-s%@SHOBJ_LD@%$SHOBJ_LD%g
-s%@SHOBJ_LDFLAGS@%$SHOBJ_LDFLAGS%g
-s%@SHOBJ_XLDFLAGS@%$SHOBJ_XLDFLAGS%g
-s%@SHOBJ_LIBS@%$SHOBJ_LIBS%g
-s%@SHOBJ_STATUS@%$SHOBJ_STATUS%g
-s%@SHLIB_STATUS@%$SHLIB_STATUS%g
-s%@SHLIB_XLDFLAGS@%$SHLIB_XLDFLAGS%g
-s%@SHLIB_LIBSUFF@%$SHLIB_LIBSUFF%g
-s%@SHLIB_LIBVERSION@%$SHLIB_LIBVERSION%g
-s%@SHLIB_LIBS@%$SHLIB_LIBS%g
-s%@BUILD_DIR@%$BUILD_DIR%g
-s%@LOCAL_CFLAGS@%$LOCAL_CFLAGS%g
-s%@LOCAL_LDFLAGS@%$LOCAL_LDFLAGS%g
-s%@LOCAL_DEFS@%$LOCAL_DEFS%g
-s%@ARFLAGS@%$ARFLAGS%g
-s%@LIBVERSION@%$LIBVERSION%g
-s%@TERMCAP_LIB@%$TERMCAP_LIB%g
-
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
- else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
- fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
-fi
-EOF
-
-cat >> $CONFIG_STATUS <<EOF
-
-CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile examples/Makefile shlib/Makefile"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
-
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
- else
- ac_dir_suffix= ac_dots=
- fi
-
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
- esac
-
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
- esac
-
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
- esac
-
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
-
-# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
-# NAME is the cpp macro being defined and VALUE is the value it is being given.
-#
-# ac_d sets the value in "#define NAME VALUE" lines.
-ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
-ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
-ac_dC='\3'
-ac_dD='%g'
-# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
-ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_uB='\([ ]\)%\1#\2define\3'
-ac_uC=' '
-ac_uD='\4%g'
-# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
-ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_eB='$%\1#\2define\3'
-ac_eC=' '
-ac_eD='%g'
-
-if test "${CONFIG_HEADERS+set}" != set; then
-EOF
-cat >> $CONFIG_STATUS <<EOF
- CONFIG_HEADERS="config.h"
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-fi
-for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- echo creating $ac_file
-
- rm -f conftest.frag conftest.in conftest.out
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- cat $ac_file_inputs > conftest.in
-
-EOF
-
-# Transform confdefs.h into a sed script conftest.vals that substitutes
-# the proper values into config.h.in to produce config.h. And first:
-# Protect against being on the right side of a sed subst in config.status.
-# Protect against being in an unquoted here document in config.status.
-rm -f conftest.vals
-cat > conftest.hdr <<\EOF
-s/[\\&%]/\\&/g
-s%[\\$`]%\\&%g
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
-s%ac_d%ac_u%gp
-s%ac_u%ac_e%gp
-EOF
-sed -n -f conftest.hdr confdefs.h > conftest.vals
-rm -f conftest.hdr
-
-# This sed command replaces #undef with comments. This is necessary, for
-# example, in the case of _POSIX_SOURCE, which is predefined and required
-# on some systems where configure will not decide to define it.
-cat >> conftest.vals <<\EOF
-s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
-EOF
-
-# Break up conftest.vals because some shells have a limit on
-# the size of here documents, and old seds have small limits too.
-
-rm -f conftest.tail
-while :
-do
- ac_lines=`grep -c . conftest.vals`
- # grep -c gives empty output for an empty file on some AIX systems.
- if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
- # Write a limited-size here document to conftest.frag.
- echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
- sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
- echo 'CEOF
- sed -f conftest.frag conftest.in > conftest.out
- rm -f conftest.in
- mv conftest.out conftest.in
-' >> $CONFIG_STATUS
- sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
- rm -f conftest.vals
- mv conftest.tail conftest.vals
-done
-rm -f conftest.vals
-
-cat >> $CONFIG_STATUS <<\EOF
- rm -f conftest.frag conftest.h
- echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
- cat conftest.in >> conftest.h
- rm -f conftest.in
- if cmp -s $ac_file conftest.h 2>/dev/null; then
- echo "$ac_file is unchanged"
- rm -f conftest.h
- else
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- fi
- rm -f $ac_file
- mv conftest.h $ac_file
- fi
-fi; done
-
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-
-# Makefile uses this timestamp file to record whether config.h is up to date.
-echo > stamp-h
-
-exit 0
-EOF
-chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
-
diff --git a/readline/configure.in b/readline/configure.in
deleted file mode 100644
index 240a3addc45..00000000000
--- a/readline/configure.in
+++ /dev/null
@@ -1,143 +0,0 @@
-dnl
-dnl Configure script for readline library
-dnl
-dnl report bugs to chet@po.cwru.edu
-dnl
-dnl Process this file with autoconf to produce a configure script.
-AC_REVISION([for Readline 4.0, version 2.14, from autoconf version] AC_ACVERSION)
-LIBVERSION=4.0
-
-AC_INIT(readline.h)
-AC_CONFIG_HEADER(config.h)
-
-dnl make sure we are using a recent autoconf version
-AC_PREREQ(2.10)
-
-AC_CONFIG_AUX_DIR(./support)
-
-AC_CANONICAL_HOST
-
-dnl configure defaults
-opt_curses=no
-opt_shared=no
-
-dnl arguments to configure
-AC_ARG_WITH(curses, --with-curses use the curses library instead of the termcap library,opt_curses=$withval)
-
-if test "$opt_curses" = "yes"; then
- prefer_curses=yes
-fi
-
-# We want these before the checks, so the checks can modify their values.
-test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1
-
-AC_PROG_CC
-AC_MINIX
-
-# If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS.
-test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O"
-
-AC_PROG_GCC_TRADITIONAL
-AC_PROG_INSTALL
-AC_CHECK_PROG(AR, ar, ar)
-dnl Set default for ARFLAGS, since autoconf does not have a macro for it.
-dnl This allows people to set it when running configure or make
-test -n "$ARFLAGS" || ARFLAGS="cr"
-AC_PROG_RANLIB
-
-MAKE_SHELL=/bin/sh
-AC_SUBST(MAKE_SHELL)
-
-AC_RETSIGTYPE
-
-AC_HEADER_STAT
-AC_HEADER_DIRENT
-
-AC_CHECK_FUNCS(strcasecmp select setenv putenv tcgetattr setlocale lstat)
-
-AC_FUNC_STRCOLL
-
-AC_CHECK_HEADERS(unistd.h stdlib.h varargs.h stdarg.h string.h \
- sys/ptem.h sys/pte.h sys/stream.h sys/select.h \
- termcap.h termios.h termio.h sys/file.h locale.h)
-
-BASH_SIGNAL_CHECK
-BASH_REINSTALL_SIGHANDLERS
-
-BASH_FUNC_POSIX_SETJMP
-BASH_FUNC_LSTAT
-BASH_CHECK_GETPW_FUNCS
-BASH_FUNC_STRCOLL
-
-BASH_TYPE_SIGHANDLER
-BASH_HAVE_TIOCGWINSZ
-BASH_HAVE_TIOCSTAT
-BASH_HAVE_FIONREAD
-BASH_MISC_SPEED_T
-BASH_STRUCT_WINSIZE
-BASH_STRUCT_DIRENT_D_INO
-BASH_STRUCT_DIRENT_D_FILENO
-
-dnl yuck
-case "$host_os" in
-aix*) prefer_curses=yes ;;
-esac
-BASH_CHECK_LIB_TERMCAP
-if test "$TERMCAP_LIB" = "./lib/termcap/libtermcap.a"; then
- TERMCAP_LIB=-ltermcap #default
-fi
-
-case "$host_cpu" in
-*cray*) LOCAL_CFLAGS=-DCRAY ;;
-esac
-
-case "$host_os" in
-isc*) LOCAL_CFLAGS=-Disc386 ;;
-esac
-
-# shared library configuration section
-#
-# Shared object configuration section. These values are generated by
-# ${srcdir}/support/shobj-conf
-#
-if test -f ${srcdir}/support/shobj-conf; then
- AC_MSG_CHECKING(configuration for building shared libraries)
- eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C ${CC} -c ${host_cpu} -o ${host_os} -v ${host_vendor}`
- AC_SUBST(SHOBJ_CC)
- AC_SUBST(SHOBJ_CFLAGS)
- AC_SUBST(SHOBJ_LD)
- AC_SUBST(SHOBJ_LDFLAGS)
- AC_SUBST(SHOBJ_XLDFLAGS)
- AC_SUBST(SHOBJ_LIBS)
- AC_SUBST(SHOBJ_STATUS)
- AC_SUBST(SHLIB_STATUS)
- AC_SUBST(SHLIB_XLDFLAGS)
- AC_SUBST(SHLIB_LIBSUFF)
- AC_SUBST(SHLIB_LIBVERSION)
- AC_SUBST(SHLIB_LIBS)
- AC_MSG_RESULT($SHLIB_STATUS)
-fi
-
-BUILD_DIR=`pwd`
-AC_SUBST(BUILD_DIR)
-
-AC_SUBST(CFLAGS)
-AC_SUBST(LOCAL_CFLAGS)
-AC_SUBST(LOCAL_LDFLAGS)
-AC_SUBST(LOCAL_DEFS)
-
-AC_SUBST(AR)
-AC_SUBST(ARFLAGS)
-
-AC_SUBST(host_cpu)
-AC_SUBST(host_os)
-
-AC_SUBST(LIBVERSION)
-
-AC_SUBST(TERMCAP_LIB)
-
-AC_OUTPUT([Makefile doc/Makefile examples/Makefile shlib/Makefile],
-[
-# Makefile uses this timestamp file to record whether config.h is up to date.
-echo > stamp-h
-])
diff --git a/readline/display.c b/readline/display.c
deleted file mode 100644
index df9e212ac0c..00000000000
--- a/readline/display.c
+++ /dev/null
@@ -1,1573 +0,0 @@
-/* display.c -- readline redisplay facility. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include "posixstat.h"
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-#if defined (__GO32__)
-# include <go32.h>
-# include <pc.h>
-#endif /* __GO32__ */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Termcap library stuff. */
-#include "tcap.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-/* Global and pseudo-global variables and functions
- imported from readline.c. */
-extern char *rl_prompt;
-extern int readline_echoing_p;
-
-extern int _rl_output_meta_chars;
-extern int _rl_horizontal_scroll_mode;
-extern int _rl_mark_modified_lines;
-extern int _rl_prefer_visible_bell;
-
-/* Variables and functions imported from terminal.c */
-extern void _rl_output_some_chars ();
-#ifdef _MINIX
-extern void _rl_output_character_function ();
-#else
-extern int _rl_output_character_function ();
-#endif
-extern int _rl_backspace ();
-
-extern const char *term_clreol, *term_clrpag;
-extern const char *term_im, *term_ic, *term_ei, *term_DC;
-extern const char *term_up, *term_dc, *term_cr, *term_IC;
-extern int screenheight, screenwidth, screenchars;
-extern int terminal_can_insert, _rl_term_autowrap;
-
-/* Pseudo-global functions (local to the readline library) exported
- by this file. */
-void _rl_move_cursor_relative (), _rl_output_some_chars ();
-void _rl_move_vert ();
-void _rl_clear_to_eol (), _rl_clear_screen ();
-
-static void update_line (), space_to_eol ();
-static void delete_chars (), insert_some_chars ();
-static void cr ();
-
-static int *inv_lbreaks, *vis_lbreaks;
-
-extern char *xmalloc (), *xrealloc ();
-
-/* Heuristic used to decide whether it is faster to move from CUR to NEW
- by backing up or outputting a carriage return and moving forward. */
-#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
-
-/* **************************************************************** */
-/* */
-/* Display stuff */
-/* */
-/* **************************************************************** */
-
-/* This is the stuff that is hard for me. I never seem to write good
- display routines in C. Let's see how I do this time. */
-
-/* (PWP) Well... Good for a simple line updater, but totally ignores
- the problems of input lines longer than the screen width.
-
- update_line and the code that calls it makes a multiple line,
- automatically wrapping line update. Careful attention needs
- to be paid to the vertical position variables. */
-
-/* Keep two buffers; one which reflects the current contents of the
- screen, and the other to draw what we think the new contents should
- be. Then compare the buffers, and make whatever changes to the
- screen itself that we should. Finally, make the buffer that we
- just drew into be the one which reflects the current contents of the
- screen, and place the cursor where it belongs.
-
- Commands that want to can fix the display themselves, and then let
- this function know that the display has been fixed by setting the
- RL_DISPLAY_FIXED variable. This is good for efficiency. */
-
-/* Application-specific redisplay function. */
-VFunction *rl_redisplay_function = rl_redisplay;
-
-/* Global variables declared here. */
-/* What YOU turn on when you have handled all redisplay yourself. */
-int rl_display_fixed = 0;
-
-int _rl_suppress_redisplay = 0;
-
-/* The stuff that gets printed out before the actual text of the line.
- This is usually pointing to rl_prompt. */
-const char *rl_display_prompt = (char *)NULL;
-
-/* Pseudo-global variables declared here. */
-/* The visible cursor position. If you print some text, adjust this. */
-int _rl_last_c_pos = 0;
-int _rl_last_v_pos = 0;
-
-/* Number of lines currently on screen minus 1. */
-int _rl_vis_botlin = 0;
-
-/* Variables used only in this file. */
-/* The last left edge of text that was displayed. This is used when
- doing horizontal scrolling. It shifts in thirds of a screenwidth. */
-static int last_lmargin;
-
-/* The line display buffers. One is the line currently displayed on
- the screen. The other is the line about to be displayed. */
-static char *visible_line = (char *)NULL;
-static char *invisible_line = (char *)NULL;
-
-/* A buffer for `modeline' messages. */
-static char msg_buf[128];
-
-/* Non-zero forces the redisplay even if we thought it was unnecessary. */
-static int forced_display;
-
-/* Default and initial buffer size. Can grow. */
-static int line_size = 1024;
-
-static char *local_prompt, *local_prompt_prefix;
-static int visible_length, prefix_length;
-
-/* The number of invisible characters in the line currently being
- displayed on the screen. */
-static int visible_wrap_offset;
-
-/* static so it can be shared between rl_redisplay and update_line */
-static int wrap_offset;
-
-/* The index of the last invisible_character in the prompt string. */
-static int last_invisible;
-
-/* The length (buffer offset) of the first line of the last (possibly
- multi-line) buffer displayed on the screen. */
-static int visible_first_line_len;
-
-/* Expand the prompt string S and return the number of visible
- characters in *LP, if LP is not null. This is currently more-or-less
- a placeholder for expansion. LIP, if non-null is a place to store the
- index of the last invisible character in ther eturned string. */
-
-/* Current implementation:
- \001 (^A) start non-visible characters
- \002 (^B) end non-visible characters
- all characters except \001 and \002 (following a \001) are copied to
- the returned string; all characters except those between \001 and
- \002 are assumed to be `visible'. */
-
-static char *
-expand_prompt (pmt, lp, lip)
- char *pmt;
- int *lp, *lip;
-{
- char *r, *ret, *p;
- int l, rl, last, ignoring;
-
- /* Short-circuit if we can. */
- if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
- {
- r = savestring (pmt);
- if (lp)
- *lp = strlen (r);
- return r;
- }
-
- l = strlen (pmt);
- r = ret = xmalloc (l + 1);
-
- for (rl = ignoring = last = 0, p = pmt; p && *p; p++)
- {
- /* This code strips the invisible character string markers
- RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
- if (*p == RL_PROMPT_START_IGNORE)
- {
- ignoring++;
- continue;
- }
- else if (ignoring && *p == RL_PROMPT_END_IGNORE)
- {
- ignoring = 0;
- last = r - ret - 1;
- continue;
- }
- else
- {
- *r++ = *p;
- if (!ignoring)
- rl++;
- }
- }
-
- *r = '\0';
- if (lp)
- *lp = rl;
- if (lip)
- *lip = last;
- return ret;
-}
-
-/*
- * Expand the prompt string into the various display components, if
- * necessary.
- *
- * local_prompt = expanded last line of string in rl_display_prompt
- * (portion after the final newline)
- * local_prompt_prefix = portion before last newline of rl_display_prompt,
- * expanded via expand_prompt
- * visible_length = number of visible characters in local_prompt
- * prefix_length = number of visible characters in local_prompt_prefix
- *
- * This function is called once per call to readline(). It may also be
- * called arbitrarily to expand the primary prompt.
- *
- * The return value is the number of visible characters on the last line
- * of the (possibly multi-line) prompt.
- */
-int
-rl_expand_prompt (prompt)
- char *prompt;
-{
- char *p, *t;
- int c;
-
- /* Clear out any saved values. */
- if (local_prompt)
- free (local_prompt);
- if (local_prompt_prefix)
- free (local_prompt_prefix);
- local_prompt = local_prompt_prefix = (char *)0;
- last_invisible = visible_length = 0;
-
- if (prompt == 0 || *prompt == 0)
- return (0);
-
- p = strrchr (prompt, '\n');
- if (!p)
- {
- /* The prompt is only one line. */
- local_prompt = expand_prompt (prompt, &visible_length, &last_invisible);
- local_prompt_prefix = (char *)0;
- return (visible_length);
- }
- else
- {
- /* The prompt spans multiple lines. */
- t = ++p;
- local_prompt = expand_prompt (p, &visible_length, &last_invisible);
- c = *t; *t = '\0';
- /* The portion of the prompt string up to and including the
- final newline is now null-terminated. */
- local_prompt_prefix = expand_prompt (prompt, &prefix_length, (int *)NULL);
- *t = c;
- return (prefix_length);
- }
-}
-
-/* Basic redisplay algorithm. */
-void
-rl_redisplay ()
-{
- register int in, out, c, linenum, cursor_linenum;
- register char *line;
- int c_pos, inv_botlin, lb_botlin, lb_linenum;
- int newlines, lpos, temp;
- const char *prompt_this_line;
-
- if (!readline_echoing_p)
- return;
-
- if (!rl_display_prompt)
- rl_display_prompt = "";
-
- if (invisible_line == 0)
- {
- visible_line = xmalloc (line_size);
- invisible_line = xmalloc (line_size);
- for (in = 0; in < line_size; in++)
- {
- visible_line[in] = 0;
- invisible_line[in] = 1;
- }
-
- /* should be enough, but then again, this is just for testing. */
- inv_lbreaks = (int *)malloc (256 * sizeof (int));
- vis_lbreaks = (int *)malloc (256 * sizeof (int));
- inv_lbreaks[0] = vis_lbreaks[0] = 0;
-
- rl_on_new_line ();
- }
-
- /* Draw the line into the buffer. */
- c_pos = -1;
-
- line = invisible_line;
- out = inv_botlin = 0;
-
- /* Mark the line as modified or not. We only do this for history
- lines. */
- if (_rl_mark_modified_lines && current_history () && rl_undo_list)
- {
- line[out++] = '*';
- line[out] = '\0';
- }
-
- /* If someone thought that the redisplay was handled, but the currently
- visible line has a different modification state than the one about
- to become visible, then correct the caller's misconception. */
- if (visible_line[0] != invisible_line[0])
- rl_display_fixed = 0;
-
- /* If the prompt to be displayed is the `primary' readline prompt (the
- one passed to readline()), use the values we have already expanded.
- If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
- number of non-visible characters in the prompt string. */
- if (rl_display_prompt == rl_prompt || local_prompt)
- {
- int local_len = local_prompt ? strlen (local_prompt) : 0;
- if (local_prompt_prefix && forced_display)
- _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
-
- if (local_len > 0)
- {
- temp = local_len + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = xrealloc (visible_line, line_size);
- line = invisible_line = xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, local_prompt, local_len);
- out += local_len;
- }
- line[out] = '\0';
- wrap_offset = local_len - visible_length;
- }
- else
- {
- int pmtlen;
- prompt_this_line = strrchr (rl_display_prompt, '\n');
- if (!prompt_this_line)
- prompt_this_line = rl_display_prompt;
- else
- {
- prompt_this_line++;
- if (forced_display)
- {
- _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt);
- /* Make sure we are at column zero even after a newline,
- regardless of the state of terminal output processing. */
- if (prompt_this_line[-2] != '\r')
- cr ();
- }
- }
-
- pmtlen = strlen (prompt_this_line);
- temp = pmtlen + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = xrealloc (visible_line, line_size);
- line = invisible_line = xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, prompt_this_line, pmtlen);
- out += pmtlen;
- line[out] = '\0';
- wrap_offset = 0;
- }
-
-#define CHECK_LPOS() \
- do { \
- lpos++; \
- if (lpos >= screenwidth) \
- { \
- inv_lbreaks[++newlines] = out; \
- lpos = 0; \
- } \
- } while (0)
-
- /* inv_lbreaks[i] is where line i starts in the buffer. */
- inv_lbreaks[newlines = 0] = 0;
- lpos = out - wrap_offset;
-
- /* XXX - what if lpos is already >= screenwidth before we start drawing the
- contents of the command line? */
- while (lpos >= screenwidth)
- {
-#if 0
- temp = ((newlines + 1) * screenwidth) - ((newlines == 0) ? wrap_offset : 0);
-#else
- /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt
- string with invisible characters that is longer than the screen
- width. */
- temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);
-#endif
- inv_lbreaks[++newlines] = temp;
- lpos -= screenwidth;
- }
-
- lb_linenum = 0;
- for (in = 0; in < rl_end; in++)
- {
- c = (unsigned char)rl_line_buffer[in];
-
- if (out + 8 >= line_size) /* XXX - 8 for \t */
- {
- line_size *= 2;
- visible_line = xrealloc (visible_line, line_size);
- invisible_line = xrealloc (invisible_line, line_size);
- line = invisible_line;
- }
-
- if (in == rl_point)
- {
- c_pos = out;
- lb_linenum = newlines;
- }
-
- if (META_CHAR (c))
- {
- if (_rl_output_meta_chars == 0)
- {
- sprintf (line + out, "\\%o", c);
-
- if (lpos + 4 >= screenwidth)
- {
- temp = screenwidth - lpos;
- inv_lbreaks[++newlines] = out + temp;
- lpos = 4 - temp;
- }
- else
- lpos += 4;
-
- out += 4;
- }
- else
- {
- line[out++] = c;
- CHECK_LPOS();
- }
- }
-#if defined (DISPLAY_TABS)
- else if (c == '\t')
- {
- register int temp, newout;
-
-#if 0
- newout = (out | (int)7) + 1;
-#else
- newout = out + 8 - lpos % 8;
-#endif
- temp = newout - out;
- if (lpos + temp >= screenwidth)
- {
- register int temp2;
- temp2 = screenwidth - lpos;
- inv_lbreaks[++newlines] = out + temp2;
- lpos = temp - temp2;
- while (out < newout)
- line[out++] = ' ';
- }
- else
- {
- while (out < newout)
- line[out++] = ' ';
- lpos += temp;
- }
- }
-#endif
- else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up)
- {
- line[out++] = '\0'; /* XXX - sentinel */
- inv_lbreaks[++newlines] = out;
- lpos = 0;
- }
- else if (CTRL_CHAR (c) || c == RUBOUT)
- {
- line[out++] = '^';
- CHECK_LPOS();
- line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
- CHECK_LPOS();
- }
- else
- {
- line[out++] = c;
- CHECK_LPOS();
- }
- }
- line[out] = '\0';
- if (c_pos < 0)
- {
- c_pos = out;
- lb_linenum = newlines;
- }
-
- inv_botlin = lb_botlin = newlines;
- inv_lbreaks[newlines+1] = out;
- cursor_linenum = lb_linenum;
-
- /* C_POS == position in buffer where cursor should be placed. */
-
- /* PWP: now is when things get a bit hairy. The visible and invisible
- line buffers are really multiple lines, which would wrap every
- (screenwidth - 1) characters. Go through each in turn, finding
- the changed region and updating it. The line order is top to bottom. */
-
- /* If we can move the cursor up and down, then use multiple lines,
- otherwise, let long lines display in a single terminal line, and
- horizontally scroll it. */
-
- if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)
- {
- int nleft, pos, changed_screen_line;
-
- if (!rl_display_fixed || forced_display)
- {
- forced_display = 0;
-
- /* If we have more than a screenful of material to display, then
- only display a screenful. We should display the last screen,
- not the first. */
- if (out >= screenchars)
- out = screenchars - 1;
-
- /* The first line is at character position 0 in the buffer. The
- second and subsequent lines start at inv_lbreaks[N], offset by
- OFFSET (which has already been calculated above). */
-
-#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
-#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
-#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
-#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
-#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
-#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
-
- /* For each line in the buffer, do the updating display. */
- for (linenum = 0; linenum <= inv_botlin; linenum++)
- {
- update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
- VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
-
- /* If this is the line with the prompt, we might need to
- compensate for invisible characters in the new line. Do
- this only if there is not more than one new line (which
- implies that we completely overwrite the old visible line)
- and the new line is shorter than the old. Make sure we are
- at the end of the new line before clearing. */
- if (linenum == 0 &&
- inv_botlin == 0 && _rl_last_c_pos == out &&
- (wrap_offset > visible_wrap_offset) &&
- (_rl_last_c_pos < visible_first_line_len))
- {
- nleft = screenwidth + wrap_offset - _rl_last_c_pos;
- if (nleft)
- _rl_clear_to_eol (nleft);
- }
-
- /* Since the new first line is now visible, save its length. */
- if (linenum == 0)
- visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
- }
-
- /* We may have deleted some lines. If so, clear the left over
- blank ones at the bottom out. */
- if (_rl_vis_botlin > inv_botlin)
- {
- char *tt;
- for (; linenum <= _rl_vis_botlin; linenum++)
- {
- tt = VIS_CHARS (linenum);
- _rl_move_vert (linenum);
- _rl_move_cursor_relative (0, tt);
- _rl_clear_to_eol
- ((linenum == _rl_vis_botlin) ? (int) strlen (tt) : screenwidth);
- }
- }
- _rl_vis_botlin = inv_botlin;
-
- /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
- different screen line during this redisplay. */
- changed_screen_line = _rl_last_v_pos != cursor_linenum;
- if (changed_screen_line)
- {
- _rl_move_vert (cursor_linenum);
- /* If we moved up to the line with the prompt using term_up,
- the physical cursor position on the screen stays the same,
- but the buffer position needs to be adjusted to account
- for invisible characters. */
- if (cursor_linenum == 0 && wrap_offset)
- _rl_last_c_pos += wrap_offset;
- }
-
- /* We have to reprint the prompt if it contains invisible
- characters, since it's not generally OK to just reprint
- the characters from the current cursor position. But we
- only need to reprint it if the cursor is before the last
- invisible character in the prompt string. */
- nleft = visible_length + wrap_offset;
- if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
- _rl_last_c_pos <= last_invisible && local_prompt)
- {
- if (term_cr)
- tputs (term_cr, 1, _rl_output_character_function);
- _rl_output_some_chars (local_prompt, nleft);
- _rl_last_c_pos = nleft;
- }
-
- /* Where on that line? And where does that line start
- in the buffer? */
- pos = inv_lbreaks[cursor_linenum];
- /* nleft == number of characters in the line buffer between the
- start of the line and the cursor position. */
- nleft = c_pos - pos;
-
- /* Since _rl_backspace() doesn't know about invisible characters in the
- prompt, and there's no good way to tell it, we compensate for
- those characters here and call _rl_backspace() directly. */
- if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
- {
- _rl_backspace (_rl_last_c_pos - nleft);
- _rl_last_c_pos = nleft;
- }
-
- if (nleft != _rl_last_c_pos)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
- }
- }
- else /* Do horizontal scrolling. */
- {
-#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
- int lmargin, ndisp, nleft, phys_c_pos, t;
-
- /* Always at top line. */
- _rl_last_v_pos = 0;
-
- /* Compute where in the buffer the displayed line should start. This
- will be LMARGIN. */
-
- /* The number of characters that will be displayed before the cursor. */
- ndisp = c_pos - wrap_offset;
- nleft = visible_length + wrap_offset;
- /* Where the new cursor position will be on the screen. This can be
- longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
- phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
- t = screenwidth / 3;
-
- /* If the number of characters had already exceeded the screenwidth,
- last_lmargin will be > 0. */
-
- /* If the number of characters to be displayed is more than the screen
- width, compute the starting offset so that the cursor is about
- two-thirds of the way across the screen. */
- if (phys_c_pos > screenwidth - 2)
- {
- lmargin = c_pos - (2 * t);
- if (lmargin < 0)
- lmargin = 0;
- /* If the left margin would be in the middle of a prompt with
- invisible characters, don't display the prompt at all. */
- if (wrap_offset && lmargin > 0 && lmargin < nleft)
- lmargin = nleft;
- }
- else if (ndisp < screenwidth - 2) /* XXX - was -1 */
- lmargin = 0;
- else if (phys_c_pos < 1)
- {
- /* If we are moving back towards the beginning of the line and
- the last margin is no longer correct, compute a new one. */
- lmargin = ((c_pos - 1) / t) * t; /* XXX */
- if (wrap_offset && lmargin > 0 && lmargin < nleft)
- lmargin = nleft;
- }
- else
- lmargin = last_lmargin;
-
- /* If the first character on the screen isn't the first character
- in the display line, indicate this with a special character. */
- if (lmargin > 0)
- line[lmargin] = '<';
-
- /* If SCREENWIDTH characters starting at LMARGIN do not encompass
- the whole line, indicate that with a special character at the
- right edge of the screen. If LMARGIN is 0, we need to take the
- wrap offset into account. */
- t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
- if (t < out)
- line[t - 1] = '>';
-
- if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
- {
- forced_display = 0;
- update_line (&visible_line[last_lmargin],
- &invisible_line[lmargin],
- 0,
- screenwidth + visible_wrap_offset,
- screenwidth + (lmargin ? 0 : wrap_offset),
- 0);
-
- /* If the visible new line is shorter than the old, but the number
- of invisible characters is greater, and we are at the end of
- the new line, we need to clear to eol. */
- t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
- if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
- (_rl_last_c_pos == out) &&
- t < visible_first_line_len)
- {
- nleft = screenwidth - t;
- _rl_clear_to_eol (nleft);
- }
- visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
- if (visible_first_line_len > screenwidth)
- visible_first_line_len = screenwidth;
-
- _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
- last_lmargin = lmargin;
- }
- }
- fflush (rl_outstream);
-
- /* Swap visible and non-visible lines. */
- {
- char *temp = visible_line;
- int *itemp = vis_lbreaks;
- visible_line = invisible_line;
- invisible_line = temp;
- vis_lbreaks = inv_lbreaks;
- inv_lbreaks = itemp;
- rl_display_fixed = 0;
- /* If we are displaying on a single line, and last_lmargin is > 0, we
- are not displaying any invisible characters, so set visible_wrap_offset
- to 0. */
- if (_rl_horizontal_scroll_mode && last_lmargin)
- visible_wrap_offset = 0;
- else
- visible_wrap_offset = wrap_offset;
- }
-}
-
-/* PWP: update_line() is based on finding the middle difference of each
- line on the screen; vis:
-
- /old first difference
- /beginning of line | /old last same /old EOL
- v v v v
-old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
-new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
- \new first difference
-
- All are character pointers for the sake of speed. Special cases for
- no differences, as well as for end of line additions must be handled.
-
- Could be made even smarter, but this works well enough */
-static void
-update_line (old, new, current_line, omax, nmax, inv_botlin)
- register char *old, *new;
- int current_line, omax, nmax, inv_botlin;
-{
- register char *ofd, *ols, *oe, *nfd, *nls, *ne;
- int temp, lendiff, wsatend, od, nd;
- int current_invis_chars;
-
- /* If we're at the right edge of a terminal that supports xn, we're
- ready to wrap around, so do so. This fixes problems with knowing
- the exact cursor position and cut-and-paste with certain terminal
- emulators. In this calculation, TEMP is the physical screen
- position of the cursor. */
- temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
- if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
- && _rl_last_v_pos == current_line - 1)
- {
- if (new[0])
- putc (new[0], rl_outstream);
- else
- putc (' ', rl_outstream);
- _rl_last_c_pos = 1; /* XXX */
- _rl_last_v_pos++;
- if (old[0] && new[0])
- old[0] = new[0];
- }
-
- /* Find first difference. */
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd && (*ofd == *nfd);
- ofd++, nfd++)
- ;
-
- /* Move to the end of the screen line. ND and OD are used to keep track
- of the distance between ne and new and oe and old, respectively, to
- move a subtraction out of each loop. */
- for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
- for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
-
- /* If no difference, continue to next line. */
- if (ofd == oe && nfd == ne)
- return;
-
- wsatend = 1; /* flag for trailing whitespace */
- ols = oe - 1; /* find last same */
- nls = ne - 1;
- while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
- {
- if (*ols != ' ')
- wsatend = 0;
- ols--;
- nls--;
- }
-
- if (wsatend)
- {
- ols = oe;
- nls = ne;
- }
- else if (*ols != *nls)
- {
- if (*ols) /* don't step past the NUL */
- ols++;
- if (*nls)
- nls++;
- }
-
- /* count of invisible characters in the current invisible line. */
- current_invis_chars = W_OFFSET (current_line, wrap_offset);
- if (_rl_last_v_pos != current_line)
- {
- _rl_move_vert (current_line);
- if (current_line == 0 && visible_wrap_offset)
- _rl_last_c_pos += visible_wrap_offset;
- }
-
- /* If this is the first line and there are invisible characters in the
- prompt string, and the prompt string has not changed, and the current
- cursor position is before the last invisible character in the prompt,
- and the index of the character to move to is past the end of the prompt
- string, then redraw the entire prompt string. We can only do this
- reliably if the terminal supports a `cr' capability.
-
- This is not an efficiency hack -- there is a problem with redrawing
- portions of the prompt string if they contain terminal escape
- sequences (like drawing the `unbold' sequence without a corresponding
- `bold') that manifests itself on certain terminals. */
-
- lendiff = local_prompt ? strlen (local_prompt) : 0;
- od = ofd - old; /* index of first difference in visible line */
- if (current_line == 0 && !_rl_horizontal_scroll_mode &&
- term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
- od > lendiff && _rl_last_c_pos < last_invisible)
- {
- tputs (term_cr, 1, _rl_output_character_function);
- _rl_output_some_chars (local_prompt, lendiff);
- _rl_last_c_pos = lendiff;
- }
-
- _rl_move_cursor_relative (od, old);
-
- /* if (len (new) > len (old)) */
- lendiff = (nls - nfd) - (ols - ofd);
-
- /* If we are changing the number of invisible characters in a line, and
- the spot of first difference is before the end of the invisible chars,
- lendiff needs to be adjusted. */
- if (current_line == 0 && !_rl_horizontal_scroll_mode &&
- current_invis_chars != visible_wrap_offset)
- lendiff += visible_wrap_offset - current_invis_chars;
-
- /* Insert (diff (len (old), len (new)) ch. */
- temp = ne - nfd;
- if (lendiff > 0)
- {
- /* Non-zero if we're increasing the number of lines. */
- int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
- /* Sometimes it is cheaper to print the characters rather than
- use the terminal's capabilities. If we're growing the number
- of lines, make sure we actually cause the new line to wrap
- around on auto-wrapping terminals. */
- if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
- {
- /* If lendiff > visible_length and _rl_last_c_pos == 0 and
- _rl_horizontal_scroll_mode == 1, inserting the characters with
- term_IC or term_ic will screw up the screen because of the
- invisible characters. We need to just draw them. */
- if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
- lendiff <= visible_length || !current_invis_chars))
- {
- insert_some_chars (nfd, lendiff);
- _rl_last_c_pos += lendiff;
- }
- else if (*ols == 0)
- {
- /* At the end of a line the characters do not have to
- be "inserted". They can just be placed on the screen. */
- /* However, this screws up the rest of this block, which
- assumes you've done the insert because you can. */
- _rl_output_some_chars (nfd, lendiff);
- _rl_last_c_pos += lendiff;
- }
- else
- {
- /* We have horizontal scrolling and we are not inserting at
- the end. We have invisible characters in this line. This
- is a dumb update. */
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += temp;
- return;
- }
- /* Copy (new) chars to screen from first diff to last match. */
- temp = nls - nfd;
- if ((temp - lendiff) > 0)
- {
- _rl_output_some_chars (nfd + lendiff, temp - lendiff);
- _rl_last_c_pos += temp - lendiff;
- }
- }
- else
- {
- /* cannot insert chars, write to EOL */
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += temp;
- }
- }
- else /* Delete characters from line. */
- {
- /* If possible and inexpensive to use terminal deletion, then do so. */
- if (term_dc && (2 * temp) >= -lendiff)
- {
- /* If all we're doing is erasing the invisible characters in the
- prompt string, don't bother. It screws up the assumptions
- about what's on the screen. */
- if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
- -lendiff == visible_wrap_offset)
- lendiff = 0;
-
- if (lendiff)
- delete_chars (-lendiff); /* delete (diff) characters */
-
- /* Copy (new) chars to screen from first diff to last match */
- temp = nls - nfd;
- if (temp > 0)
- {
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += temp;
- }
- }
- /* Otherwise, print over the existing material. */
- else
- {
- if (temp > 0)
- {
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += temp;
- }
- lendiff = (oe - old) - (ne - new);
- if (lendiff)
- {
- if (_rl_term_autowrap && current_line < inv_botlin)
- space_to_eol (lendiff);
- else
- _rl_clear_to_eol (lendiff);
- }
- }
- }
-}
-
-/* Tell the update routines that we have moved onto a new (empty) line. */
-int
-rl_on_new_line ()
-{
- if (visible_line)
- visible_line[0] = '\0';
-
- _rl_last_c_pos = _rl_last_v_pos = 0;
- _rl_vis_botlin = last_lmargin = 0;
- if (vis_lbreaks)
- vis_lbreaks[0] = vis_lbreaks[1] = 0;
- visible_wrap_offset = 0;
- return 0;
-}
-
-/* Actually update the display, period. */
-int
-rl_forced_update_display ()
-{
- if (visible_line)
- {
- register char *temp = visible_line;
-
- while (*temp)
- *temp++ = '\0';
- }
- rl_on_new_line ();
- forced_display++;
- (*rl_redisplay_function) ();
- return 0;
-}
-
-/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
- DATA is the contents of the screen line of interest; i.e., where
- the movement is being done. */
-void
-_rl_move_cursor_relative (new, data)
- int new;
- char *data;
-{
- register int i;
-
- /* If we don't have to do anything, then return. */
- if (_rl_last_c_pos == new) return;
-
- /* It may be faster to output a CR, and then move forwards instead
- of moving backwards. */
- /* i == current physical cursor position. */
- i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
- if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
- (_rl_term_autowrap && i == screenwidth))
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (term_cr, 1, _rl_output_character_function);
-#endif /* !__MSDOS__ */
- _rl_last_c_pos = 0;
- }
-
- if (_rl_last_c_pos < new)
- {
- /* Move the cursor forward. We do it by printing the command
- to move the cursor forward if there is one, else print that
- portion of the output buffer again. Which is cheaper? */
-
- /* The above comment is left here for posterity. It is faster
- to print one character (non-control) than to print a control
- sequence telling the terminal to move forward one character.
- That kind of control is for people who don't know what the
- data is underneath the cursor. */
-#if defined (HACK_TERMCAP_MOTION)
- extern char *term_forward_char;
-
- if (term_forward_char)
- for (i = _rl_last_c_pos; i < new; i++)
- tputs (term_forward_char, 1, _rl_output_character_function);
- else
- for (i = _rl_last_c_pos; i < new; i++)
- putc (data[i], rl_outstream);
-#else
- for (i = _rl_last_c_pos; i < new; i++)
- putc (data[i], rl_outstream);
-#endif /* HACK_TERMCAP_MOTION */
- }
- else if (_rl_last_c_pos > new)
- _rl_backspace (_rl_last_c_pos - new);
- _rl_last_c_pos = new;
-}
-
-/* PWP: move the cursor up or down. */
-void
-_rl_move_vert (to)
- int to;
-{
- register int delta, i;
-
- if (_rl_last_v_pos == to || to > screenheight)
- return;
-
-#if defined (__GO32__)
- {
- int row, col;
-
- ScreenGetCursor (&row, &col);
- ScreenSetCursor ((row + to - _rl_last_v_pos), col);
- }
-#else /* !__GO32__ */
-
- if ((delta = to - _rl_last_v_pos) > 0)
- {
- for (i = 0; i < delta; i++)
- putc ('\n', rl_outstream);
- tputs (term_cr, 1, _rl_output_character_function);
- _rl_last_c_pos = 0;
- }
- else
- { /* delta < 0 */
- if (term_up && *term_up)
- for (i = 0; i < -delta; i++)
- tputs (term_up, 1, _rl_output_character_function);
- }
-#endif /* !__GO32__ */
- _rl_last_v_pos = to; /* Now TO is here */
-}
-
-/* Physically print C on rl_outstream. This is for functions which know
- how to optimize the display. Return the number of characters output. */
-int
-rl_show_char (c)
- int c;
-{
- int n = 1;
- if (META_CHAR (c) && (_rl_output_meta_chars == 0))
- {
- fprintf (rl_outstream, "M-");
- n += 2;
- c = UNMETA (c);
- }
-
-#if defined (DISPLAY_TABS)
- if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
-#else
- if (CTRL_CHAR (c) || c == RUBOUT)
-#endif /* !DISPLAY_TABS */
- {
- fprintf (rl_outstream, "C-");
- n += 2;
- c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
- }
-
- putc (c, rl_outstream);
- fflush (rl_outstream);
- return n;
-}
-
-int
-rl_character_len (c, pos)
- register int c, pos;
-{
- unsigned char uc;
-
- uc = (unsigned char)c;
-
- if (META_CHAR (uc))
- return ((_rl_output_meta_chars == 0) ? 4 : 1);
-
- if (uc == '\t')
- {
-#if defined (DISPLAY_TABS)
- return (((pos | 7) + 1) - pos);
-#else
- return (2);
-#endif /* !DISPLAY_TABS */
- }
-
- if (CTRL_CHAR (c) || c == RUBOUT)
- return (2);
-
- return ((isprint (uc)) ? 1 : 2);
-}
-
-/* How to print things in the "echo-area". The prompt is treated as a
- mini-modeline. */
-
-#if defined (USE_VARARGS)
-int
-#if defined (PREFER_STDARG)
-rl_message (const char *format, ...)
-#else
-rl_message (va_alist)
- va_dcl
-#endif
-{
- va_list args;
-#if defined (PREFER_VARARGS)
- char *format;
-#endif
-
-#if defined (PREFER_STDARG)
- va_start (args, format);
-#else
- va_start (args);
- format = va_arg (args, char *);
-#endif
-
- vsprintf (msg_buf, format, args);
- va_end (args);
-
- rl_display_prompt = msg_buf;
- (*rl_redisplay_function) ();
- return 0;
-}
-#else /* !USE_VARARGS */
-int
-rl_message (char *format, void *arg1, void *arg2)
-{
- sprintf (msg_buf, format, arg1, arg2);
- rl_display_prompt = msg_buf;
- (*rl_redisplay_function) ();
- return 0;
-}
-#endif /* !USE_VARARGS */
-
-/* How to clear things from the "echo-area". */
-int
-rl_clear_message ()
-{
- rl_display_prompt = rl_prompt;
- (*rl_redisplay_function) ();
- return 0;
-}
-
-int
-rl_reset_line_state ()
-{
- rl_on_new_line ();
-
- rl_display_prompt = rl_prompt ? rl_prompt : "";
- forced_display = 1;
- return 0;
-}
-
-static char *saved_local_prompt;
-static char *saved_local_prefix;
-static int saved_last_invisible;
-static int saved_visible_length;
-
-void
-rl_save_prompt ()
-{
- saved_local_prompt = local_prompt;
- saved_local_prefix = local_prompt_prefix;
- saved_last_invisible = last_invisible;
- saved_visible_length = visible_length;
-
- local_prompt = local_prompt_prefix = (char *)0;
- last_invisible = visible_length = 0;
-}
-
-void
-rl_restore_prompt ()
-{
- if (local_prompt)
- free (local_prompt);
- if (local_prompt_prefix)
- free (local_prompt_prefix);
-
- local_prompt = saved_local_prompt;
- local_prompt_prefix = saved_local_prefix;
- last_invisible = saved_last_invisible;
- visible_length = saved_visible_length;
-}
-
-char *
-_rl_make_prompt_for_search (pchar)
- int pchar;
-{
- int len;
- char *pmt;
-
- rl_save_prompt ();
-
- if (saved_local_prompt == 0)
- {
- len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
- pmt = xmalloc (len + 2);
- if (len)
- strcpy (pmt, rl_prompt);
- pmt[len] = pchar;
- pmt[len+1] = '\0';
- }
- else
- {
- len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
- pmt = xmalloc (len + 2);
- if (len)
- strcpy (pmt, saved_local_prompt);
- pmt[len] = pchar;
- pmt[len+1] = '\0';
- local_prompt = savestring (pmt);
- last_invisible = saved_last_invisible;
- visible_length = saved_visible_length + 1;
- }
- return pmt;
-}
-
-/* Quick redisplay hack when erasing characters at the end of the line. */
-void
-_rl_erase_at_end_of_line (l)
- int l;
-{
- register int i;
-
- _rl_backspace (l);
- for (i = 0; i < l; i++)
- putc (' ', rl_outstream);
- _rl_backspace (l);
- for (i = 0; i < l; i++)
- visible_line[--_rl_last_c_pos] = '\0';
- rl_display_fixed++;
-}
-
-/* Clear to the end of the line. COUNT is the minimum
- number of character spaces to clear, */
-void
-_rl_clear_to_eol (count)
- int count;
-{
-#if !defined (__GO32__)
- if (term_clreol)
- tputs (term_clreol, 1, _rl_output_character_function);
- else if (count)
-#endif /* !__GO32__ */
- space_to_eol (count);
-}
-
-/* Clear to the end of the line using spaces. COUNT is the minimum
- number of character spaces to clear, */
-static void
-space_to_eol (count)
- int count;
-{
- register int i;
-
- for (i = 0; i < count; i++)
- putc (' ', rl_outstream);
-
- _rl_last_c_pos += count;
-}
-
-void
-_rl_clear_screen ()
-{
-#if !defined (__GO32__)
- if (term_clrpag)
- tputs (term_clrpag, 1, _rl_output_character_function);
- else
-#endif /* !__GO32__ */
- crlf ();
-}
-
-/* Insert COUNT characters from STRING to the output stream. */
-static void
-insert_some_chars (string, count)
- char *string;
- int count;
-{
-#if defined (__GO32__)
- int row, col, width;
- char *row_start;
-
- ScreenGetCursor (&row, &col);
- width = ScreenCols ();
- row_start = ScreenPrimary + (row * width);
-
- memcpy (row_start + col + count, row_start + col, width - col - count);
-
- /* Place the text on the screen. */
- _rl_output_some_chars (string, count);
-#else /* !_GO32 */
-
- /* If IC is defined, then we do not have to "enter" insert mode. */
- if (term_IC)
- {
- char *buffer;
- buffer = tgoto (term_IC, 0, count);
- tputs (buffer, 1, _rl_output_character_function);
- _rl_output_some_chars (string, count);
- }
- else
- {
- register int i;
-
- /* If we have to turn on insert-mode, then do so. */
- if (term_im && *term_im)
- tputs (term_im, 1, _rl_output_character_function);
-
- /* If there is a special command for inserting characters, then
- use that first to open up the space. */
- if (term_ic && *term_ic)
- {
- for (i = count; i--; )
- tputs (term_ic, 1, _rl_output_character_function);
- }
-
- /* Print the text. */
- _rl_output_some_chars (string, count);
-
- /* If there is a string to turn off insert mode, we had best use
- it now. */
- if (term_ei && *term_ei)
- tputs (term_ei, 1, _rl_output_character_function);
- }
-#endif /* !__GO32__ */
-}
-
-/* Delete COUNT characters from the display line. */
-static void
-delete_chars (count)
- int count;
-{
-#if defined (__GO32__)
- int row, col, width;
- char *row_start;
-
- ScreenGetCursor (&row, &col);
- width = ScreenCols ();
- row_start = ScreenPrimary + (row * width);
-
- memcpy (row_start + col, row_start + col + count, width - col - count);
- memset (row_start + width - count, 0, count * 2);
-#else /* !_GO32 */
-
- if (count > screenwidth) /* XXX */
- return;
-
- if (term_DC && *term_DC)
- {
- char *buffer;
- buffer = tgoto (term_DC, count, count);
- tputs (buffer, count, _rl_output_character_function);
- }
- else
- {
- if (term_dc && *term_dc)
- while (count--)
- tputs (term_dc, 1, _rl_output_character_function);
- }
-#endif /* !__GO32__ */
-}
-
-void
-_rl_update_final ()
-{
- int full_lines;
-
- full_lines = 0;
- /* If the cursor is the only thing on an otherwise-blank last line,
- compensate so we don't print an extra CRLF. */
- if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
- visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
- {
- _rl_vis_botlin--;
- full_lines = 1;
- }
- _rl_move_vert (_rl_vis_botlin);
- /* If we've wrapped lines, remove the final xterm line-wrap flag. */
- if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth))
- {
- char *last_line;
- last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
- _rl_move_cursor_relative (screenwidth - 1, last_line);
- _rl_clear_to_eol (0);
- putc (last_line[screenwidth - 1], rl_outstream);
- }
- _rl_vis_botlin = 0;
- crlf ();
- fflush (rl_outstream);
- rl_display_fixed++;
-}
-
-/* Move to the start of the current line. */
-static void
-cr ()
-{
- if (term_cr)
- {
- tputs (term_cr, 1, _rl_output_character_function);
- _rl_last_c_pos = 0;
- }
-}
-
-/* Redisplay the current line after a SIGWINCH is received. */
-void
-_rl_redisplay_after_sigwinch ()
-{
- char *t, *oldl, *oldlprefix;
- const char *oldp;
-
- /* Clear the current line and put the cursor at column 0. Make sure
- the right thing happens if we have wrapped to a new screen line. */
- if (term_cr)
- {
- tputs (term_cr, 1, _rl_output_character_function);
- _rl_last_c_pos = 0;
- if (term_clreol)
- tputs (term_clreol, 1, _rl_output_character_function);
- else
- {
- space_to_eol (screenwidth);
- tputs (term_cr, 1, _rl_output_character_function);
- }
- if (_rl_last_v_pos > 0)
- _rl_move_vert (0);
- }
- else
- crlf ();
-
- /* Redraw only the last line of a multi-line prompt. */
- t = strrchr (rl_display_prompt, '\n');
- if (t)
- {
- oldp = rl_display_prompt;
- oldl = local_prompt;
- oldlprefix = local_prompt_prefix;
- rl_display_prompt = ++t;
- local_prompt = local_prompt_prefix = (char *)NULL;
- rl_forced_update_display ();
- rl_display_prompt = oldp;
- local_prompt = oldl;
- local_prompt_prefix = oldlprefix;
- }
- else
- rl_forced_update_display ();
-}
-
-void
-_rl_clean_up_for_exit ()
-{
- if (readline_echoing_p)
- {
- _rl_move_vert (_rl_vis_botlin);
- _rl_vis_botlin = 0;
- fflush (rl_outstream);
- rl_restart_output (1, 0);
- }
-}
-
-void
-_rl_erase_entire_line ()
-{
- cr ();
- _rl_clear_to_eol (0);
- cr ();
- fflush (rl_outstream);
-}
diff --git a/readline/emacs_keymap.c b/readline/emacs_keymap.c
deleted file mode 100644
index 4ba385843f6..00000000000
--- a/readline/emacs_keymap.c
+++ /dev/null
@@ -1,885 +0,0 @@
-/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (BUFSIZ)
-#include <stdio.h>
-#endif /* !BUFSIZ */
-
-#include "readline.h"
-
-/* An array of function pointers, one for each possible key.
- If the type byte is ISKMAP, then the pointer is the address of
- a keymap. */
-
-KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
-
- /* Control keys. */
- { ISFUNC, rl_set_mark }, /* Control-@ */
- { ISFUNC, rl_beg_of_line }, /* Control-a */
- { ISFUNC, rl_backward }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, rl_delete }, /* Control-d */
- { ISFUNC, rl_end_of_line }, /* Control-e */
- { ISFUNC, rl_forward }, /* Control-f */
- { ISFUNC, rl_abort }, /* Control-g */
- { ISFUNC, rl_rubout }, /* Control-h */
- { ISFUNC, rl_complete }, /* Control-i */
- { ISFUNC, rl_newline }, /* Control-j */
- { ISFUNC, rl_kill_line }, /* Control-k */
- { ISFUNC, rl_clear_screen }, /* Control-l */
- { ISFUNC, rl_newline }, /* Control-m */
- { ISFUNC, rl_get_next_history }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, rl_get_previous_history }, /* Control-p */
- { ISFUNC, rl_quoted_insert }, /* Control-q */
- { ISFUNC, rl_reverse_search_history }, /* Control-r */
- { ISFUNC, rl_forward_search_history }, /* Control-s */
- { ISFUNC, rl_transpose_chars }, /* Control-t */
- { ISFUNC, rl_unix_line_discard }, /* Control-u */
- { ISFUNC, rl_quoted_insert }, /* Control-v */
- { ISFUNC, rl_unix_word_rubout }, /* Control-w */
- { ISKMAP, (Function *)emacs_ctlx_keymap }, /* Control-x */
- { ISFUNC, rl_yank }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
- { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, rl_char_search }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, rl_undo_command }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_insert }, /* SPACE */
- { ISFUNC, rl_insert }, /* ! */
- { ISFUNC, rl_insert }, /* " */
- { ISFUNC, rl_insert }, /* # */
- { ISFUNC, rl_insert }, /* $ */
- { ISFUNC, rl_insert }, /* % */
- { ISFUNC, rl_insert }, /* & */
- { ISFUNC, rl_insert }, /* ' */
- { ISFUNC, rl_insert }, /* ( */
-#if defined (PAREN_MATCHING)
- { ISFUNC, rl_insert_close }, /* ) */
-#else
- { ISFUNC, rl_insert }, /* ) */
-#endif /* !PAREN_MATCHING */
- { ISFUNC, rl_insert }, /* * */
- { ISFUNC, rl_insert }, /* + */
- { ISFUNC, rl_insert }, /* , */
- { ISFUNC, rl_insert }, /* - */
- { ISFUNC, rl_insert }, /* . */
- { ISFUNC, rl_insert }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_insert }, /* 0 */
- { ISFUNC, rl_insert }, /* 1 */
- { ISFUNC, rl_insert }, /* 2 */
- { ISFUNC, rl_insert }, /* 3 */
- { ISFUNC, rl_insert }, /* 4 */
- { ISFUNC, rl_insert }, /* 5 */
- { ISFUNC, rl_insert }, /* 6 */
- { ISFUNC, rl_insert }, /* 7 */
- { ISFUNC, rl_insert }, /* 8 */
- { ISFUNC, rl_insert }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, rl_insert }, /* : */
- { ISFUNC, rl_insert }, /* ; */
- { ISFUNC, rl_insert }, /* < */
- { ISFUNC, rl_insert }, /* = */
- { ISFUNC, rl_insert }, /* > */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_insert }, /* A */
- { ISFUNC, rl_insert }, /* B */
- { ISFUNC, rl_insert }, /* C */
- { ISFUNC, rl_insert }, /* D */
- { ISFUNC, rl_insert }, /* E */
- { ISFUNC, rl_insert }, /* F */
- { ISFUNC, rl_insert }, /* G */
- { ISFUNC, rl_insert }, /* H */
- { ISFUNC, rl_insert }, /* I */
- { ISFUNC, rl_insert }, /* J */
- { ISFUNC, rl_insert }, /* K */
- { ISFUNC, rl_insert }, /* L */
- { ISFUNC, rl_insert }, /* M */
- { ISFUNC, rl_insert }, /* N */
- { ISFUNC, rl_insert }, /* O */
- { ISFUNC, rl_insert }, /* P */
- { ISFUNC, rl_insert }, /* Q */
- { ISFUNC, rl_insert }, /* R */
- { ISFUNC, rl_insert }, /* S */
- { ISFUNC, rl_insert }, /* T */
- { ISFUNC, rl_insert }, /* U */
- { ISFUNC, rl_insert }, /* V */
- { ISFUNC, rl_insert }, /* W */
- { ISFUNC, rl_insert }, /* X */
- { ISFUNC, rl_insert }, /* Y */
- { ISFUNC, rl_insert }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, rl_insert }, /* [ */
- { ISFUNC, rl_insert }, /* \ */
-#if defined (PAREN_MATCHING)
- { ISFUNC, rl_insert_close }, /* ] */
-#else
- { ISFUNC, rl_insert }, /* ] */
-#endif /* !PAREN_MATCHING */
- { ISFUNC, rl_insert }, /* ^ */
- { ISFUNC, rl_insert }, /* _ */
- { ISFUNC, rl_insert }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, rl_insert }, /* a */
- { ISFUNC, rl_insert }, /* b */
- { ISFUNC, rl_insert }, /* c */
- { ISFUNC, rl_insert }, /* d */
- { ISFUNC, rl_insert }, /* e */
- { ISFUNC, rl_insert }, /* f */
- { ISFUNC, rl_insert }, /* g */
- { ISFUNC, rl_insert }, /* h */
- { ISFUNC, rl_insert }, /* i */
- { ISFUNC, rl_insert }, /* j */
- { ISFUNC, rl_insert }, /* k */
- { ISFUNC, rl_insert }, /* l */
- { ISFUNC, rl_insert }, /* m */
- { ISFUNC, rl_insert }, /* n */
- { ISFUNC, rl_insert }, /* o */
- { ISFUNC, rl_insert }, /* p */
- { ISFUNC, rl_insert }, /* q */
- { ISFUNC, rl_insert }, /* r */
- { ISFUNC, rl_insert }, /* s */
- { ISFUNC, rl_insert }, /* t */
- { ISFUNC, rl_insert }, /* u */
- { ISFUNC, rl_insert }, /* v */
- { ISFUNC, rl_insert }, /* w */
- { ISFUNC, rl_insert }, /* x */
- { ISFUNC, rl_insert }, /* y */
- { ISFUNC, rl_insert }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, rl_insert }, /* { */
- { ISFUNC, rl_insert }, /* | */
-#if defined (PAREN_MATCHING)
- { ISFUNC, rl_insert_close }, /* } */
-#else
- { ISFUNC, rl_insert }, /* } */
-#endif /* !PAREN_MATCHING */
- { ISFUNC, rl_insert }, /* ~ */
- { ISFUNC, rl_rubout }, /* RUBOUT */
-
-#if KEYMAP_SIZE > 128
- /* Pure 8-bit characters (128 - 159).
- These might be used in some
- character sets. */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
-
- /* ISO Latin-1 characters (160 - 255) */
- { ISFUNC, rl_insert }, /* No-break space */
- { ISFUNC, rl_insert }, /* Inverted exclamation mark */
- { ISFUNC, rl_insert }, /* Cent sign */
- { ISFUNC, rl_insert }, /* Pound sign */
- { ISFUNC, rl_insert }, /* Currency sign */
- { ISFUNC, rl_insert }, /* Yen sign */
- { ISFUNC, rl_insert }, /* Broken bar */
- { ISFUNC, rl_insert }, /* Section sign */
- { ISFUNC, rl_insert }, /* Diaeresis */
- { ISFUNC, rl_insert }, /* Copyright sign */
- { ISFUNC, rl_insert }, /* Feminine ordinal indicator */
- { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */
- { ISFUNC, rl_insert }, /* Not sign */
- { ISFUNC, rl_insert }, /* Soft hyphen */
- { ISFUNC, rl_insert }, /* Registered sign */
- { ISFUNC, rl_insert }, /* Macron */
- { ISFUNC, rl_insert }, /* Degree sign */
- { ISFUNC, rl_insert }, /* Plus-minus sign */
- { ISFUNC, rl_insert }, /* Superscript two */
- { ISFUNC, rl_insert }, /* Superscript three */
- { ISFUNC, rl_insert }, /* Acute accent */
- { ISFUNC, rl_insert }, /* Micro sign */
- { ISFUNC, rl_insert }, /* Pilcrow sign */
- { ISFUNC, rl_insert }, /* Middle dot */
- { ISFUNC, rl_insert }, /* Cedilla */
- { ISFUNC, rl_insert }, /* Superscript one */
- { ISFUNC, rl_insert }, /* Masculine ordinal indicator */
- { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */
- { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */
- { ISFUNC, rl_insert }, /* Vulgar fraction one half */
- { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */
- { ISFUNC, rl_insert }, /* Inverted questionk mark */
- { ISFUNC, rl_insert }, /* Latin capital letter a with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter a with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */
- { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */
- { ISFUNC, rl_insert }, /* Latin capital letter ae */
- { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */
- { ISFUNC, rl_insert }, /* Latin capital letter e with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter e with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter i with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter i with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */
- { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */
- { ISFUNC, rl_insert }, /* Latin capital letter o with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter o with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */
- { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */
- { ISFUNC, rl_insert }, /* Multiplication sign */
- { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */
- { ISFUNC, rl_insert }, /* Latin capital letter u with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter u with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */
- { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */
- { ISFUNC, rl_insert }, /* Latin small letter a with grave */
- { ISFUNC, rl_insert }, /* Latin small letter a with acute */
- { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter a with tilde */
- { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter a with ring above */
- { ISFUNC, rl_insert }, /* Latin small letter ae */
- { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */
- { ISFUNC, rl_insert }, /* Latin small letter e with grave */
- { ISFUNC, rl_insert }, /* Latin small letter e with acute */
- { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter i with grave */
- { ISFUNC, rl_insert }, /* Latin small letter i with acute */
- { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */
- { ISFUNC, rl_insert }, /* Latin small letter n with tilde */
- { ISFUNC, rl_insert }, /* Latin small letter o with grave */
- { ISFUNC, rl_insert }, /* Latin small letter o with acute */
- { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter o with tilde */
- { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */
- { ISFUNC, rl_insert }, /* Division sign */
- { ISFUNC, rl_insert }, /* Latin small letter o with stroke */
- { ISFUNC, rl_insert }, /* Latin small letter u with grave */
- { ISFUNC, rl_insert }, /* Latin small letter u with acute */
- { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter y with acute */
- { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */
- { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */
-#endif /* KEYMAP_SIZE > 128 */
-};
-
-KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
-
- /* Meta keys. Just like above, but the high bit is set. */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-a */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-b */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-c */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-d */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-e */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-f */
- { ISFUNC, rl_abort }, /* Meta-Control-g */
- { ISFUNC, rl_backward_kill_word }, /* Meta-Control-h */
- { ISFUNC, rl_tab_insert }, /* Meta-Control-i */
- { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-k */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-l */
- { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-n */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-o */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-p */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-q */
- { ISFUNC, rl_revert_line }, /* Meta-Control-r */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-s */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-t */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-u */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-v */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-w */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-x */
- { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-z */
-
- { ISFUNC, rl_complete }, /* Meta-Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */
- { ISFUNC, rl_backward_char_search }, /* Meta-Control-] */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_set_mark }, /* Meta-SPACE */
- { ISFUNC, (Function *)0x0 }, /* Meta-! */
- { ISFUNC, (Function *)0x0 }, /* Meta-" */
- { ISFUNC, rl_insert_comment },/* Meta-# */
- { ISFUNC, (Function *)0x0 }, /* Meta-$ */
- { ISFUNC, (Function *)0x0 }, /* Meta-% */
- { ISFUNC, rl_tilde_expand }, /* Meta-& */
- { ISFUNC, (Function *)0x0 }, /* Meta-' */
- { ISFUNC, (Function *)0x0 }, /* Meta-( */
- { ISFUNC, (Function *)0x0 }, /* Meta-) */
- { ISFUNC, rl_insert_completions }, /* Meta-* */
- { ISFUNC, (Function *)0x0 }, /* Meta-+ */
- { ISFUNC, (Function *)0x0 }, /* Meta-, */
- { ISFUNC, rl_digit_argument }, /* Meta-- */
- { ISFUNC, rl_yank_last_arg}, /* Meta-. */
- { ISFUNC, (Function *)0x0 }, /* Meta-/ */
-
- /* Regular digits. */
- { ISFUNC, rl_digit_argument }, /* Meta-0 */
- { ISFUNC, rl_digit_argument }, /* Meta-1 */
- { ISFUNC, rl_digit_argument }, /* Meta-2 */
- { ISFUNC, rl_digit_argument }, /* Meta-3 */
- { ISFUNC, rl_digit_argument }, /* Meta-4 */
- { ISFUNC, rl_digit_argument }, /* Meta-5 */
- { ISFUNC, rl_digit_argument }, /* Meta-6 */
- { ISFUNC, rl_digit_argument }, /* Meta-7 */
- { ISFUNC, rl_digit_argument }, /* Meta-8 */
- { ISFUNC, rl_digit_argument }, /* Meta-9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* Meta-: */
- { ISFUNC, (Function *)0x0 }, /* Meta-; */
- { ISFUNC, rl_beginning_of_history }, /* Meta-< */
- { ISFUNC, rl_possible_completions }, /* Meta-= */
- { ISFUNC, rl_end_of_history }, /* Meta-> */
- { ISFUNC, rl_possible_completions }, /* Meta-? */
- { ISFUNC, (Function *)0x0 }, /* Meta-@ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-A */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-B */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-C */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-D */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-E */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-F */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-G */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-H */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-I */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-J */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-K */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-L */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-M */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-N */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-O */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-P */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-R */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-S */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-T */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-U */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-V */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-W */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-X */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
-
- /* Some more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */
- { ISFUNC, rl_delete_horizontal_space }, /* Meta-\ */
- { ISFUNC, (Function *)0x0 }, /* Meta-] */
- { ISFUNC, (Function *)0x0 }, /* Meta-^ */
- { ISFUNC, rl_yank_last_arg }, /* Meta-_ */
- { ISFUNC, (Function *)0x0 }, /* Meta-` */
-
- /* Lowercase alphabet. */
- { ISFUNC, (Function *)0x0 }, /* Meta-a */
- { ISFUNC, rl_backward_word }, /* Meta-b */
- { ISFUNC, rl_capitalize_word }, /* Meta-c */
- { ISFUNC, rl_kill_word }, /* Meta-d */
- { ISFUNC, (Function *)0x0 }, /* Meta-e */
- { ISFUNC, rl_forward_word }, /* Meta-f */
- { ISFUNC, (Function *)0x0 }, /* Meta-g */
- { ISFUNC, (Function *)0x0 }, /* Meta-h */
- { ISFUNC, (Function *)0x0 }, /* Meta-i */
- { ISFUNC, (Function *)0x0 }, /* Meta-j */
- { ISFUNC, (Function *)0x0 }, /* Meta-k */
- { ISFUNC, rl_downcase_word }, /* Meta-l */
- { ISFUNC, (Function *)0x0 }, /* Meta-m */
- { ISFUNC, rl_noninc_forward_search }, /* Meta-n */
- { ISFUNC, (Function *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */
- { ISFUNC, rl_noninc_reverse_search }, /* Meta-p */
- { ISFUNC, (Function *)0x0 }, /* Meta-q */
- { ISFUNC, rl_revert_line }, /* Meta-r */
- { ISFUNC, (Function *)0x0 }, /* Meta-s */
- { ISFUNC, rl_transpose_words }, /* Meta-t */
- { ISFUNC, rl_upcase_word }, /* Meta-u */
- { ISFUNC, (Function *)0x0 }, /* Meta-v */
- { ISFUNC, (Function *)0x0 }, /* Meta-w */
- { ISFUNC, (Function *)0x0 }, /* Meta-x */
- { ISFUNC, rl_yank_pop }, /* Meta-y */
- { ISFUNC, (Function *)0x0 }, /* Meta-z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* Meta-{ */
- { ISFUNC, (Function *)0x0 }, /* Meta-| */
- { ISFUNC, (Function *)0x0 }, /* Meta-} */
- { ISFUNC, rl_tilde_expand }, /* Meta-~ */
- { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */
-
-#if KEYMAP_SIZE > 128
- /* Undefined keys. */
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 }
-#endif /* KEYMAP_SIZE > 128 */
-};
-
-KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
-
- /* Control keys. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Control-a */
- { ISFUNC, (Function *)0x0 }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, (Function *)0x0 }, /* Control-d */
- { ISFUNC, (Function *)0x0 }, /* Control-e */
- { ISFUNC, (Function *)0x0 }, /* Control-f */
- { ISFUNC, rl_abort }, /* Control-g */
- { ISFUNC, (Function *)0x0 }, /* Control-h */
- { ISFUNC, (Function *)0x0 }, /* Control-i */
- { ISFUNC, (Function *)0x0 }, /* Control-j */
- { ISFUNC, (Function *)0x0 }, /* Control-k */
- { ISFUNC, (Function *)0x0 }, /* Control-l */
- { ISFUNC, (Function *)0x0 }, /* Control-m */
- { ISFUNC, (Function *)0x0 }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, (Function *)0x0 }, /* Control-p */
- { ISFUNC, (Function *)0x0 }, /* Control-q */
- { ISFUNC, rl_re_read_init_file }, /* Control-r */
- { ISFUNC, (Function *)0x0 }, /* Control-s */
- { ISFUNC, (Function *)0x0 }, /* Control-t */
- { ISFUNC, rl_undo_command }, /* Control-u */
- { ISFUNC, (Function *)0x0 }, /* Control-v */
- { ISFUNC, (Function *)0x0 }, /* Control-w */
- { ISFUNC, rl_exchange_point_and_mark },/* Control-x */
- { ISFUNC, (Function *)0x0 }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
- { ISFUNC, (Function *)0x0 }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, (Function *)0x0 }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, (Function *)0x0 }, /* SPACE */
- { ISFUNC, (Function *)0x0 }, /* ! */
- { ISFUNC, (Function *)0x0 }, /* " */
- { ISFUNC, (Function *)0x0 }, /* # */
- { ISFUNC, (Function *)0x0 }, /* $ */
- { ISFUNC, (Function *)0x0 }, /* % */
- { ISFUNC, (Function *)0x0 }, /* & */
- { ISFUNC, (Function *)0x0 }, /* ' */
- { ISFUNC, rl_start_kbd_macro }, /* ( */
- { ISFUNC, rl_end_kbd_macro }, /* ) */
- { ISFUNC, (Function *)0x0 }, /* * */
- { ISFUNC, (Function *)0x0 }, /* + */
- { ISFUNC, (Function *)0x0 }, /* , */
- { ISFUNC, (Function *)0x0 }, /* - */
- { ISFUNC, (Function *)0x0 }, /* . */
- { ISFUNC, (Function *)0x0 }, /* / */
-
- /* Regular digits. */
- { ISFUNC, (Function *)0x0 }, /* 0 */
- { ISFUNC, (Function *)0x0 }, /* 1 */
- { ISFUNC, (Function *)0x0 }, /* 2 */
- { ISFUNC, (Function *)0x0 }, /* 3 */
- { ISFUNC, (Function *)0x0 }, /* 4 */
- { ISFUNC, (Function *)0x0 }, /* 5 */
- { ISFUNC, (Function *)0x0 }, /* 6 */
- { ISFUNC, (Function *)0x0 }, /* 7 */
- { ISFUNC, (Function *)0x0 }, /* 8 */
- { ISFUNC, (Function *)0x0 }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* : */
- { ISFUNC, (Function *)0x0 }, /* ; */
- { ISFUNC, (Function *)0x0 }, /* < */
- { ISFUNC, (Function *)0x0 }, /* = */
- { ISFUNC, (Function *)0x0 }, /* > */
- { ISFUNC, (Function *)0x0 }, /* ? */
- { ISFUNC, (Function *)0x0 }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_do_lowercase_version }, /* A */
- { ISFUNC, rl_do_lowercase_version }, /* B */
- { ISFUNC, rl_do_lowercase_version }, /* C */
- { ISFUNC, rl_do_lowercase_version }, /* D */
- { ISFUNC, rl_do_lowercase_version }, /* E */
- { ISFUNC, rl_do_lowercase_version }, /* F */
- { ISFUNC, rl_do_lowercase_version }, /* G */
- { ISFUNC, rl_do_lowercase_version }, /* H */
- { ISFUNC, rl_do_lowercase_version }, /* I */
- { ISFUNC, rl_do_lowercase_version }, /* J */
- { ISFUNC, rl_do_lowercase_version }, /* K */
- { ISFUNC, rl_do_lowercase_version }, /* L */
- { ISFUNC, rl_do_lowercase_version }, /* M */
- { ISFUNC, rl_do_lowercase_version }, /* N */
- { ISFUNC, rl_do_lowercase_version }, /* O */
- { ISFUNC, rl_do_lowercase_version }, /* P */
- { ISFUNC, rl_do_lowercase_version }, /* Q */
- { ISFUNC, rl_do_lowercase_version }, /* R */
- { ISFUNC, rl_do_lowercase_version }, /* S */
- { ISFUNC, rl_do_lowercase_version }, /* T */
- { ISFUNC, rl_do_lowercase_version }, /* U */
- { ISFUNC, rl_do_lowercase_version }, /* V */
- { ISFUNC, rl_do_lowercase_version }, /* W */
- { ISFUNC, rl_do_lowercase_version }, /* X */
- { ISFUNC, rl_do_lowercase_version }, /* Y */
- { ISFUNC, rl_do_lowercase_version }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* [ */
- { ISFUNC, (Function *)0x0 }, /* \ */
- { ISFUNC, (Function *)0x0 }, /* ] */
- { ISFUNC, (Function *)0x0 }, /* ^ */
- { ISFUNC, (Function *)0x0 }, /* _ */
- { ISFUNC, (Function *)0x0 }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, (Function *)0x0 }, /* a */
- { ISFUNC, (Function *)0x0 }, /* b */
- { ISFUNC, (Function *)0x0 }, /* c */
- { ISFUNC, (Function *)0x0 }, /* d */
- { ISFUNC, rl_call_last_kbd_macro }, /* e */
- { ISFUNC, (Function *)0x0 }, /* f */
- { ISFUNC, (Function *)0x0 }, /* g */
- { ISFUNC, (Function *)0x0 }, /* h */
- { ISFUNC, (Function *)0x0 }, /* i */
- { ISFUNC, (Function *)0x0 }, /* j */
- { ISFUNC, (Function *)0x0 }, /* k */
- { ISFUNC, (Function *)0x0 }, /* l */
- { ISFUNC, (Function *)0x0 }, /* m */
- { ISFUNC, (Function *)0x0 }, /* n */
- { ISFUNC, (Function *)0x0 }, /* o */
- { ISFUNC, (Function *)0x0 }, /* p */
- { ISFUNC, (Function *)0x0 }, /* q */
- { ISFUNC, (Function *)0x0 }, /* r */
- { ISFUNC, (Function *)0x0 }, /* s */
- { ISFUNC, (Function *)0x0 }, /* t */
- { ISFUNC, (Function *)0x0 }, /* u */
- { ISFUNC, (Function *)0x0 }, /* v */
- { ISFUNC, (Function *)0x0 }, /* w */
- { ISFUNC, (Function *)0x0 }, /* x */
- { ISFUNC, (Function *)0x0 }, /* y */
- { ISFUNC, (Function *)0x0 }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* { */
- { ISFUNC, (Function *)0x0 }, /* | */
- { ISFUNC, (Function *)0x0 }, /* } */
- { ISFUNC, (Function *)0x0 }, /* ~ */
- { ISFUNC, rl_backward_kill_line }, /* RUBOUT */
-
-#if KEYMAP_SIZE > 128
- /* Undefined keys. */
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 }
-#endif /* KEYMAP_SIZE > 128 */
-};
diff --git a/readline/funmap.c b/readline/funmap.c
deleted file mode 100644
index 472119bd80a..00000000000
--- a/readline/funmap.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* funmap.c -- attach names to functions. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-extern char *xmalloc (), *xrealloc ();
-
-#if !defined (BUFSIZ)
-#include <stdio.h>
-#endif /* BUFSIZ */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include "rlconf.h"
-#include "readline.h"
-
-extern int _rl_qsort_string_compare ();
-
-FUNMAP **funmap;
-static int funmap_size;
-static int funmap_entry;
-
-/* After initializing the function map, this is the index of the first
- program specific function. */
-int funmap_program_specific_entry_start;
-
-static FUNMAP default_funmap[] = {
- { "abort", rl_abort },
- { "accept-line", rl_newline },
- { "arrow-key-prefix", rl_arrow_keys },
- { "backward-char", rl_backward },
- { "backward-delete-char", rl_rubout },
- { "backward-kill-line", rl_backward_kill_line },
- { "backward-kill-word", rl_backward_kill_word },
- { "backward-word", rl_backward_word },
- { "beginning-of-history", rl_beginning_of_history },
- { "beginning-of-line", rl_beg_of_line },
- { "call-last-kbd-macro", rl_call_last_kbd_macro },
- { "capitalize-word", rl_capitalize_word },
- { "character-search", rl_char_search },
- { "character-search-backward", rl_backward_char_search },
- { "clear-screen", rl_clear_screen },
- { "complete", rl_complete },
- { "copy-backward-word", rl_copy_backward_word },
- { "copy-forward-word", rl_copy_forward_word },
- { "copy-region-as-kill", rl_copy_region_to_kill },
- { "delete-char", rl_delete },
- { "delete-char-or-list", rl_delete_or_show_completions },
- { "delete-horizontal-space", rl_delete_horizontal_space },
- { "digit-argument", rl_digit_argument },
- { "do-lowercase-version", rl_do_lowercase_version },
- { "downcase-word", rl_downcase_word },
- { "dump-functions", rl_dump_functions },
- { "dump-macros", rl_dump_macros },
- { "dump-variables", rl_dump_variables },
- { "emacs-editing-mode", rl_emacs_editing_mode },
- { "end-kbd-macro", rl_end_kbd_macro },
- { "end-of-history", rl_end_of_history },
- { "end-of-line", rl_end_of_line },
- { "exchange-point-and-mark", rl_exchange_point_and_mark },
- { "forward-backward-delete-char", rl_rubout_or_delete },
- { "forward-char", rl_forward },
- { "forward-search-history", rl_forward_search_history },
- { "forward-word", rl_forward_word },
- { "history-search-backward", rl_history_search_backward },
- { "history-search-forward", rl_history_search_forward },
- { "insert-comment", rl_insert_comment },
- { "insert-completions", rl_insert_completions },
- { "kill-whole-line", rl_kill_full_line },
- { "kill-line", rl_kill_line },
- { "kill-region", rl_kill_region },
- { "kill-word", rl_kill_word },
- { "menu-complete", rl_menu_complete },
- { "next-history", rl_get_next_history },
- { "non-incremental-forward-search-history", rl_noninc_forward_search },
- { "non-incremental-reverse-search-history", rl_noninc_reverse_search },
- { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
- { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
-#ifdef __CYGWIN32__
- { "paste-from-clipboard", rl_paste_from_clipboard },
-#endif
- { "possible-completions", rl_possible_completions },
- { "previous-history", rl_get_previous_history },
- { "quoted-insert", rl_quoted_insert },
- { "re-read-init-file", rl_re_read_init_file },
- { "redraw-current-line", rl_refresh_line},
- { "reverse-search-history", rl_reverse_search_history },
- { "revert-line", rl_revert_line },
- { "self-insert", rl_insert },
- { "set-mark", rl_set_mark },
- { "start-kbd-macro", rl_start_kbd_macro },
- { "tab-insert", rl_tab_insert },
- { "tilde-expand", rl_tilde_expand },
- { "transpose-chars", rl_transpose_chars },
- { "transpose-words", rl_transpose_words },
- { "tty-status", rl_tty_status },
- { "undo", rl_undo_command },
- { "universal-argument", rl_universal_argument },
- { "unix-line-discard", rl_unix_line_discard },
- { "unix-word-rubout", rl_unix_word_rubout },
- { "upcase-word", rl_upcase_word },
- { "yank", rl_yank },
- { "yank-last-arg", rl_yank_last_arg },
- { "yank-nth-arg", rl_yank_nth_arg },
- { "yank-pop", rl_yank_pop },
-
-#if defined (VI_MODE)
- { "vi-append-eol", rl_vi_append_eol },
- { "vi-append-mode", rl_vi_append_mode },
- { "vi-arg-digit", rl_vi_arg_digit },
- { "vi-back-to-indent", rl_vi_back_to_indent },
- { "vi-bWord", rl_vi_bWord },
- { "vi-bracktype", rl_vi_bracktype },
- { "vi-bword", rl_vi_bword },
- { "vi-change-case", rl_vi_change_case },
- { "vi-change-char", rl_vi_change_char },
- { "vi-change-to", rl_vi_change_to },
- { "vi-char-search", rl_vi_char_search },
- { "vi-column", rl_vi_column },
- { "vi-complete", rl_vi_complete },
- { "vi-delete", rl_vi_delete },
- { "vi-delete-to", rl_vi_delete_to },
- { "vi-eWord", rl_vi_eWord },
- { "vi-editing-mode", rl_vi_editing_mode },
- { "vi-end-word", rl_vi_end_word },
- { "vi-eof-maybe", rl_vi_eof_maybe },
- { "vi-eword", rl_vi_eword },
- { "vi-fWord", rl_vi_fWord },
- { "vi-fetch-history", rl_vi_fetch_history },
- { "vi-first-print", rl_vi_first_print },
- { "vi-fword", rl_vi_fword },
- { "vi-goto-mark", rl_vi_goto_mark },
- { "vi-insert-beg", rl_vi_insert_beg },
- { "vi-insertion-mode", rl_vi_insertion_mode },
- { "vi-match", rl_vi_match },
- { "vi-movement-mode", rl_vi_movement_mode },
- { "vi-next-word", rl_vi_next_word },
- { "vi-overstrike", rl_vi_overstrike },
- { "vi-overstrike-delete", rl_vi_overstrike_delete },
- { "vi-prev-word", rl_vi_prev_word },
- { "vi-put", rl_vi_put },
- { "vi-redo", rl_vi_redo },
- { "vi-replace", rl_vi_replace },
- { "vi-search", rl_vi_search },
- { "vi-search-again", rl_vi_search_again },
- { "vi-set-mark", rl_vi_set_mark },
- { "vi-subst", rl_vi_subst },
- { "vi-tilde-expand", rl_vi_tilde_expand },
- { "vi-yank-arg", rl_vi_yank_arg },
- { "vi-yank-to", rl_vi_yank_to },
-#endif /* VI_MODE */
-
- {(char *)NULL, (Function *)NULL }
-};
-
-int
-rl_add_funmap_entry (const char *name, Function *function)
-{
- if (funmap_entry + 2 >= funmap_size)
- {
- funmap_size += 64;
- funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *));
- }
-
- funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
- funmap[funmap_entry]->name = name;
- funmap[funmap_entry]->function = function;
-
- funmap[++funmap_entry] = (FUNMAP *)NULL;
- return funmap_entry;
-}
-
-static int funmap_initialized;
-
-/* Make the funmap contain all of the default entries. */
-void
-rl_initialize_funmap ()
-{
- register int i;
-
- if (funmap_initialized)
- return;
-
- for (i = 0; default_funmap[i].name; i++)
- rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
-
- funmap_initialized = 1;
- funmap_program_specific_entry_start = i;
-}
-
-/* Produce a NULL terminated array of known function names. The array
- is sorted. The array itself is allocated, but not the strings inside.
- You should free () the array when you done, but not the pointrs. */
-char **
-rl_funmap_names ()
-{
- char **result;
- int result_size, result_index;
-
- /* Make sure that the function map has been initialized. */
- rl_initialize_funmap ();
-
- for (result_index = result_size = 0, result = (char **)NULL; funmap[result_index]; result_index++)
- {
- if (result_index + 2 > result_size)
- {
- result_size += 20;
- result = (char **)xrealloc (result, result_size * sizeof (char *));
- }
-
- result[result_index] = (char*) funmap[result_index]->name;
- result[result_index + 1] = (char *)NULL;
- }
-
- qsort (result, result_index, sizeof (char *), _rl_qsort_string_compare);
- return (result);
-}
-
-/* Things that mean `Control'. */
-const char *possible_control_prefixes[] = {
- "Control-", "C-", "CTRL-", (char *)NULL
-};
-
-const char *possible_meta_prefixes[] = {
- "Meta", "M-", (char *)NULL
-};
diff --git a/readline/histexpand.c b/readline/histexpand.c
deleted file mode 100644
index f78838ef2ba..00000000000
--- a/readline/histexpand.c
+++ /dev/null
@@ -1,1360 +0,0 @@
-/* histexpand.c -- history expansion. */
-
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_UNISTD_H)
-# ifndef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#include "history.h"
-#include "histlib.h"
-
-#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
-#define HISTORY_QUOTE_CHARACTERS "\"'`"
-
-static char error_pointer;
-
-static char *subst_lhs;
-static char *subst_rhs;
-static int subst_lhs_len;
-static int subst_rhs_len;
-
-static char *get_history_word_specifier ();
-static char *history_find_word ();
-
-extern int history_offset;
-
-extern char *single_quote ();
-static char *quote_breaks ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables exported by this file. */
-/* The character that represents the start of a history expansion
- request. This is usually `!'. */
-char history_expansion_char = '!';
-
-/* The character that invokes word substitution if found at the start of
- a line. This is usually `^'. */
-char history_subst_char = '^';
-
-/* During tokenization, if this character is seen as the first character
- of a word, then it, and all subsequent characters upto a newline are
- ignored. For a Bourne shell, this should be '#'. Bash special cases
- the interactive comment character to not be a comment delimiter. */
-char history_comment_char = '\0';
-
-/* The list of characters which inhibit the expansion of text if found
- immediately following history_expansion_char. */
-const char *history_no_expand_chars = " \t\n\r=";
-
-/* If set to a non-zero value, single quotes inhibit history expansion.
- The default is 0. */
-int history_quotes_inhibit_expansion = 0;
-
-/* If set, this points to a function that is called to verify that a
- particular history expansion should be performed. */
-Function *history_inhibit_expansion_function;
-
-/* **************************************************************** */
-/* */
-/* History Expansion */
-/* */
-/* **************************************************************** */
-
-/* Hairy history expansion on text, not tokens. This is of general
- use, and thus belongs in this library. */
-
-/* The last string searched for by a !?string? search. */
-static char *search_string;
-
-/* The last string matched by a !?string? search. */
-static char *search_match;
-
-/* Return the event specified at TEXT + OFFSET modifying OFFSET to
- point to after the event specifier. Just a pointer to the history
- line is returned; NULL is returned in the event of a bad specifier.
- You pass STRING with *INDEX equal to the history_expansion_char that
- begins this specification.
- DELIMITING_QUOTE is a character that is allowed to end the string
- specification for what to search for in addition to the normal
- characters `:', ` ', `\t', `\n', and sometimes `?'.
- So you might call this function like:
- line = get_history_event ("!echo:p", &index, 0); */
-char *
-get_history_event (string, caller_index, delimiting_quote)
- char *string;
- int *caller_index;
- int delimiting_quote;
-{
- register int i;
- register char c;
- HIST_ENTRY *entry;
- int which, sign, local_index, substring_okay;
- Function *search_func;
- char *temp;
-
- /* The event can be specified in a number of ways.
-
- !! the previous command
- !n command line N
- !-n current command-line minus N
- !str the most recent command starting with STR
- !?str[?]
- the most recent command containing STR
-
- All values N are determined via HISTORY_BASE. */
-
- i = *caller_index;
-
- if (string[i] != history_expansion_char)
- return ((char *)NULL);
-
- /* Move on to the specification. */
- i++;
-
- sign = 1;
- substring_okay = 0;
-
-#define RETURN_ENTRY(e, w) \
- return ((e = history_get (w)) ? e->line : (char *)NULL)
-
- /* Handle !! case. */
- if (string[i] == history_expansion_char)
- {
- i++;
- which = history_base + (history_length - 1);
- *caller_index = i;
- RETURN_ENTRY (entry, which);
- }
-
- /* Hack case of numeric line specification. */
- if (string[i] == '-')
- {
- sign = -1;
- i++;
- }
-
- if (_rl_digit_p (string[i]))
- {
- /* Get the extent of the digits and compute the value. */
- for (which = 0; _rl_digit_p (string[i]); i++)
- which = (which * 10) + _rl_digit_value (string[i]);
-
- *caller_index = i;
-
- if (sign < 0)
- which = (history_length + history_base) - which;
-
- RETURN_ENTRY (entry, which);
- }
-
- /* This must be something to search for. If the spec begins with
- a '?', then the string may be anywhere on the line. Otherwise,
- the string must be found at the start of a line. */
- if (string[i] == '?')
- {
- substring_okay++;
- i++;
- }
-
- /* Only a closing `?' or a newline delimit a substring search string. */
- for (local_index = i; (c = string[i]); i++)
- if ((!substring_okay && (whitespace (c) || c == ':' ||
- (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
- string[i] == delimiting_quote)) ||
- string[i] == '\n' ||
- (substring_okay && string[i] == '?'))
- break;
-
- which = i - local_index;
- temp = xmalloc (1 + which);
- if (which)
- strncpy (temp, string + local_index, which);
- temp[which] = '\0';
-
- if (substring_okay && string[i] == '?')
- i++;
-
- *caller_index = i;
-
-#define FAIL_SEARCH() \
- do { \
- history_offset = history_length; free (temp) ; return (char *)NULL; \
- } while (0)
-
- /* If there is no search string, try to use the previous search string,
- if one exists. If not, fail immediately. */
- if (*temp == '\0' && substring_okay)
- {
- if (search_string)
- {
- free (temp);
- temp = savestring (search_string);
- }
- else
- FAIL_SEARCH ();
- }
-
- search_func = substring_okay ? history_search : history_search_prefix;
- while (1)
- {
- local_index = (*search_func) (temp, -1);
-
- if (local_index < 0)
- FAIL_SEARCH ();
-
- if (local_index == 0 || substring_okay)
- {
- entry = current_history ();
- history_offset = history_length;
-
- /* If this was a substring search, then remember the
- string that we matched for word substitution. */
- if (substring_okay)
- {
- FREE (search_string);
- search_string = temp;
-
- FREE (search_match);
- search_match = history_find_word (entry->line, local_index);
- }
- else
- free (temp);
-
- return (entry->line);
- }
-
- if (history_offset)
- history_offset--;
- else
- FAIL_SEARCH ();
- }
-#undef FAIL_SEARCH
-#undef RETURN_ENTRY
-}
-
-/* Function for extracting single-quoted strings. Used for inhibiting
- history expansion within single quotes. */
-
-/* Extract the contents of STRING as if it is enclosed in single quotes.
- SINDEX, when passed in, is the offset of the character immediately
- following the opening single quote; on exit, SINDEX is left pointing
- to the closing single quote. */
-static void
-hist_string_extract_single_quoted (string, sindex)
- char *string;
- int *sindex;
-{
- register int i;
-
- for (i = *sindex; string[i] && string[i] != '\''; i++)
- ;
-
- *sindex = i;
-}
-
-static char *
-quote_breaks (s)
- char *s;
-{
- register char *p, *r;
- char *ret;
- int len = 3;
-
- for (p = s; p && *p; p++, len++)
- {
- if (*p == '\'')
- len += 3;
- else if (whitespace (*p) || *p == '\n')
- len += 2;
- }
-
- r = ret = xmalloc (len);
- *r++ = '\'';
- for (p = s; p && *p; )
- {
- if (*p == '\'')
- {
- *r++ = '\'';
- *r++ = '\\';
- *r++ = '\'';
- *r++ = '\'';
- p++;
- }
- else if (whitespace (*p) || *p == '\n')
- {
- *r++ = '\'';
- *r++ = *p++;
- *r++ = '\'';
- }
- else
- *r++ = *p++;
- }
- *r++ = '\'';
- *r = '\0';
- return ret;
-}
-
-static char *
-hist_error(s, start, current, errtype)
- char *s;
- int start, current, errtype;
-{
- char *temp;
- const char *emsg;
- int ll, elen;
-
- ll = current - start;
-
- switch (errtype)
- {
- case EVENT_NOT_FOUND:
- emsg = "event not found";
- elen = 15;
- break;
- case BAD_WORD_SPEC:
- emsg = "bad word specifier";
- elen = 18;
- break;
- case SUBST_FAILED:
- emsg = "substitution failed";
- elen = 19;
- break;
- case BAD_MODIFIER:
- emsg = "unrecognized history modifier";
- elen = 29;
- break;
- case NO_PREV_SUBST:
- emsg = "no previous substitution";
- elen = 24;
- break;
- default:
- emsg = "unknown expansion error";
- elen = 23;
- break;
- }
-
- temp = xmalloc (ll + elen + 3);
- strncpy (temp, s + start, ll);
- temp[ll] = ':';
- temp[ll + 1] = ' ';
- strcpy (temp + ll + 2, emsg);
- return (temp);
-}
-
-/* Get a history substitution string from STR starting at *IPTR
- and return it. The length is returned in LENPTR.
-
- A backslash can quote the delimiter. If the string is the
- empty string, the previous pattern is used. If there is
- no previous pattern for the lhs, the last history search
- string is used.
-
- If IS_RHS is 1, we ignore empty strings and set the pattern
- to "" anyway. subst_lhs is not changed if the lhs is empty;
- subst_rhs is allowed to be set to the empty string. */
-
-static char *
-get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
- char *str;
- int *iptr, delimiter, is_rhs, *lenptr;
-{
- register int si, i, j, k;
- char *s = (char *) NULL;
-
- i = *iptr;
-
- for (si = i; str[si] && str[si] != delimiter; si++)
- if (str[si] == '\\' && str[si + 1] == delimiter)
- si++;
-
- if (si > i || is_rhs)
- {
- s = xmalloc (si - i + 1);
- for (j = 0, k = i; k < si; j++, k++)
- {
- /* Remove a backslash quoting the search string delimiter. */
- if (str[k] == '\\' && str[k + 1] == delimiter)
- k++;
- s[j] = str[k];
- }
- s[j] = '\0';
- if (lenptr)
- *lenptr = j;
- }
-
- i = si;
- if (str[i])
- i++;
- *iptr = i;
-
- return s;
-}
-
-static void
-postproc_subst_rhs ()
-{
- char *new;
- int i, j, new_size;
-
- new = xmalloc (new_size = subst_rhs_len + subst_lhs_len);
- for (i = j = 0; i < subst_rhs_len; i++)
- {
- if (subst_rhs[i] == '&')
- {
- if (j + subst_lhs_len >= new_size)
- new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
- strcpy (new + j, subst_lhs);
- j += subst_lhs_len;
- }
- else
- {
- /* a single backslash protects the `&' from lhs interpolation */
- if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
- i++;
- if (j >= new_size)
- new = xrealloc (new, new_size *= 2);
- new[j++] = subst_rhs[i];
- }
- }
- new[j] = '\0';
- free (subst_rhs);
- subst_rhs = new;
- subst_rhs_len = j;
-}
-
-/* Expand the bulk of a history specifier starting at STRING[START].
- Returns 0 if everything is OK, -1 if an error occurred, and 1
- if the `p' modifier was supplied and the caller should just print
- the returned string. Returns the new index into string in
- *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
-static int
-history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
- char *string;
- int start, *end_index_ptr;
- char **ret_string;
- char *current_line; /* for !# */
-{
- int i, n, starting_index;
- int substitute_globally, want_quotes, print_only;
- char *event, *temp, *result, *tstr, *t, c, *word_spec;
- int result_len;
-
- result = xmalloc (result_len = 128);
-
- i = start;
-
- /* If it is followed by something that starts a word specifier,
- then !! is implied as the event specifier. */
-
- if (member (string[i + 1], ":$*%^"))
- {
- char fake_s[3];
- int fake_i = 0;
- i++;
- fake_s[0] = fake_s[1] = history_expansion_char;
- fake_s[2] = '\0';
- event = get_history_event (fake_s, &fake_i, 0);
- }
- else if (string[i + 1] == '#')
- {
- i += 2;
- event = current_line;
- }
- else
- {
- int quoted_search_delimiter = 0;
-
- /* If the character before this `!' is a double or single
- quote, then this expansion takes place inside of the
- quoted string. If we have to search for some text ("!foo"),
- allow the delimiter to end the search string. */
- if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
- quoted_search_delimiter = string[i - 1];
- event = get_history_event (string, &i, quoted_search_delimiter);
- }
-
- if (event == 0)
- {
- *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
- free (result);
- return (-1);
- }
-
- /* If a word specifier is found, then do what that requires. */
- starting_index = i;
- word_spec = get_history_word_specifier (string, event, &i);
-
- /* There is no such thing as a `malformed word specifier'. However,
- it is possible for a specifier that has no match. In that case,
- we complain. */
- if (word_spec == (char *)&error_pointer)
- {
- *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
- free (result);
- return (-1);
- }
-
- /* If no word specifier, than the thing of interest was the event. */
- temp = word_spec ? savestring (word_spec) : savestring (event);
- FREE (word_spec);
-
- /* Perhaps there are other modifiers involved. Do what they say. */
- want_quotes = substitute_globally = print_only = 0;
- starting_index = i;
-
- while (string[i] == ':')
- {
- c = string[i + 1];
-
- if (c == 'g')
- {
- substitute_globally = 1;
- i++;
- c = string[i + 1];
- }
-
- switch (c)
- {
- default:
- *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
- free (result);
- free (temp);
- return -1;
-
- case 'q':
- want_quotes = 'q';
- break;
-
- case 'x':
- want_quotes = 'x';
- break;
-
- /* :p means make this the last executed line. So we
- return an error state after adding this line to the
- history. */
- case 'p':
- print_only++;
- break;
-
- /* :t discards all but the last part of the pathname. */
- case 't':
- tstr = strrchr (temp, '/');
- if (tstr)
- {
- tstr++;
- t = savestring (tstr);
- free (temp);
- temp = t;
- }
- break;
-
- /* :h discards the last part of a pathname. */
- case 'h':
- tstr = strrchr (temp, '/');
- if (tstr)
- *tstr = '\0';
- break;
-
- /* :r discards the suffix. */
- case 'r':
- tstr = strrchr (temp, '.');
- if (tstr)
- *tstr = '\0';
- break;
-
- /* :e discards everything but the suffix. */
- case 'e':
- tstr = strrchr (temp, '.');
- if (tstr)
- {
- t = savestring (tstr);
- free (temp);
- temp = t;
- }
- break;
-
- /* :s/this/that substitutes `that' for the first
- occurrence of `this'. :gs/this/that substitutes `that'
- for each occurrence of `this'. :& repeats the last
- substitution. :g& repeats the last substitution
- globally. */
-
- case '&':
- case 's':
- {
- char *new_event, *t;
- int delimiter, failed, si, l_temp;
-
- if (c == 's')
- {
- if (i + 2 < (int)strlen (string))
- delimiter = string[i + 2];
- else
- break; /* no search delimiter */
-
- i += 3;
-
- t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
- /* An empty substitution lhs with no previous substitution
- uses the last search string as the lhs. */
- if (t)
- {
- FREE (subst_lhs);
- subst_lhs = t;
- }
- else if (!subst_lhs)
- {
- if (search_string && *search_string)
- {
- subst_lhs = savestring (search_string);
- subst_lhs_len = strlen (subst_lhs);
- }
- else
- {
- subst_lhs = (char *) NULL;
- subst_lhs_len = 0;
- }
- }
-
- FREE (subst_rhs);
- subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
-
- /* If `&' appears in the rhs, it's supposed to be replaced
- with the lhs. */
- if (member ('&', subst_rhs))
- postproc_subst_rhs ();
- }
- else
- i += 2;
-
- /* If there is no lhs, the substitution can't succeed. */
- if (subst_lhs_len == 0)
- {
- *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
- free (result);
- free (temp);
- return -1;
- }
-
- l_temp = strlen (temp);
- /* Ignore impossible cases. */
- if (subst_lhs_len > l_temp)
- {
- *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
- free (result);
- free (temp);
- return (-1);
- }
-
- /* Find the first occurrence of THIS in TEMP. */
- si = 0;
- for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
- if (STREQN (temp+si, subst_lhs, subst_lhs_len))
- {
- int len = subst_rhs_len - subst_lhs_len + l_temp;
- new_event = xmalloc (1 + len);
- strncpy (new_event, temp, si);
- strncpy (new_event + si, subst_rhs, subst_rhs_len);
- strncpy (new_event + si + subst_rhs_len,
- temp + si + subst_lhs_len,
- l_temp - (si + subst_lhs_len));
- new_event[len] = '\0';
- free (temp);
- temp = new_event;
-
- failed = 0;
-
- if (substitute_globally)
- {
- si += subst_rhs_len;
- l_temp = strlen (temp);
- substitute_globally++;
- continue;
- }
- else
- break;
- }
-
- if (substitute_globally > 1)
- {
- substitute_globally = 0;
- continue; /* don't want to increment i */
- }
-
- if (failed == 0)
- continue; /* don't want to increment i */
-
- *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
- free (result);
- free (temp);
- return (-1);
- }
- }
- i += 2;
- }
- /* Done with modfiers. */
- /* Believe it or not, we have to back the pointer up by one. */
- --i;
-
- if (want_quotes)
- {
- char *x;
-
- if (want_quotes == 'q')
- x = single_quote (temp);
- else if (want_quotes == 'x')
- x = quote_breaks (temp);
- else
- x = savestring (temp);
-
- free (temp);
- temp = x;
- }
-
- n = strlen (temp);
- if (n >= result_len)
- result = xrealloc (result, n + 2);
- strcpy (result, temp);
- free (temp);
-
- *end_index_ptr = i;
- *ret_string = result;
- return (print_only);
-}
-
-/* Expand the string STRING, placing the result into OUTPUT, a pointer
- to a string. Returns:
-
- -1) If there was an error in expansion.
- 0) If no expansions took place (or, if the only change in
- the text was the de-slashifying of the history expansion
- character)
- 1) If expansions did take place
- 2) If the `p' modifier was given and the caller should print the result
-
- If an error ocurred in expansion, then OUTPUT contains a descriptive
- error message. */
-
-#define ADD_STRING(s) \
- do \
- { \
- int sl = strlen (s); \
- j += sl; \
- if (j >= result_len) \
- { \
- while (j >= result_len) \
- result_len += 128; \
- result = xrealloc (result, result_len); \
- } \
- strcpy (result + j - sl, s); \
- } \
- while (0)
-
-#define ADD_CHAR(c) \
- do \
- { \
- if (j >= result_len - 1) \
- result = xrealloc (result, result_len += 64); \
- result[j++] = c; \
- result[j] = '\0'; \
- } \
- while (0)
-
-int
-history_expand (hstring, output)
- char *hstring;
- char **output;
-{
- register int j;
- int i, r, l, passc, cc, modified, eindex, only_printing;
- char *string;
-
- /* The output string, and its length. */
- int result_len;
- char *result;
-
- /* Used when adding the string. */
- char *temp;
-
- /* Setting the history expansion character to 0 inhibits all
- history expansion. */
- if (history_expansion_char == 0)
- {
- *output = savestring (hstring);
- return (0);
- }
-
- /* Prepare the buffer for printing error messages. */
- result = xmalloc (result_len = 256);
- result[0] = '\0';
-
- only_printing = modified = 0;
- l = strlen (hstring);
-
- /* Grovel the string. Only backslash and single quotes can quote the
- history escape character. We also handle arg specifiers. */
-
- /* Before we grovel forever, see if the history_expansion_char appears
- anywhere within the text. */
-
- /* The quick substitution character is a history expansion all right. That
- is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
- that is the substitution that we do. */
- if (hstring[0] == history_subst_char)
- {
- string = xmalloc (l + 5);
-
- string[0] = string[1] = history_expansion_char;
- string[2] = ':';
- string[3] = 's';
- strcpy (string + 4, hstring);
- l += 4;
- }
- else
- {
- string = hstring;
- /* If not quick substitution, still maybe have to do expansion. */
-
- /* `!' followed by one of the characters in history_no_expand_chars
- is NOT an expansion. */
- for (i = 0; string[i]; i++)
- {
- cc = string[i + 1];
- /* The history_comment_char, if set, appearing that the beginning
- of a word signifies that the rest of the line should not have
- history expansion performed on it.
- Skip the rest of the line and break out of the loop. */
- if (history_comment_char && string[i] == history_comment_char &&
- (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS)))
- {
- while (string[i])
- i++;
- break;
- }
- else if (string[i] == history_expansion_char)
- {
- if (!cc || member (cc, history_no_expand_chars))
- continue;
- /* If the calling application has set
- history_inhibit_expansion_function to a function that checks
- for special cases that should not be history expanded,
- call the function and skip the expansion if it returns a
- non-zero value. */
- else if (history_inhibit_expansion_function &&
- (*history_inhibit_expansion_function) (string, i))
- continue;
- else
- break;
- }
- /* XXX - at some point, might want to extend this to handle
- double quotes as well. */
- else if (history_quotes_inhibit_expansion && string[i] == '\'')
- {
- /* If this is bash, single quotes inhibit history expansion. */
- i++;
- hist_string_extract_single_quoted (string, &i);
- }
- else if (history_quotes_inhibit_expansion && string[i] == '\\')
- {
- /* If this is bash, allow backslashes to quote single
- quotes and the history expansion character. */
- if (cc == '\'' || cc == history_expansion_char)
- i++;
- }
- }
-
- if (string[i] != history_expansion_char)
- {
- free (result);
- *output = savestring (string);
- return (0);
- }
- }
-
- /* Extract and perform the substitution. */
- for (passc = i = j = 0; i < l; i++)
- {
- int tchar = string[i];
-
- if (passc)
- {
- passc = 0;
- ADD_CHAR (tchar);
- continue;
- }
-
- if (tchar == history_expansion_char)
- tchar = -3;
- else if (tchar == history_comment_char)
- tchar = -2;
-
- switch (tchar)
- {
- default:
- ADD_CHAR (string[i]);
- break;
-
- case '\\':
- passc++;
- ADD_CHAR (tchar);
- break;
-
- case '\'':
- {
- /* If history_quotes_inhibit_expansion is set, single quotes
- inhibit history expansion. */
- if (history_quotes_inhibit_expansion)
- {
- int quote, slen;
-
- quote = i++;
- hist_string_extract_single_quoted (string, &i);
-
- slen = i - quote + 2;
- temp = xmalloc (slen);
- strncpy (temp, string + quote, slen);
- temp[slen - 1] = '\0';
- ADD_STRING (temp);
- free (temp);
- }
- else
- ADD_CHAR (string[i]);
- break;
- }
-
- case -2: /* history_comment_char */
- if (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS))
- {
- temp = xmalloc (l - i + 1);
- strcpy (temp, string + i);
- ADD_STRING (temp);
- free (temp);
- i = l;
- }
- else
- ADD_CHAR (string[i]);
- break;
-
- case -3: /* history_expansion_char */
- cc = string[i + 1];
-
- /* If the history_expansion_char is followed by one of the
- characters in history_no_expand_chars, then it is not a
- candidate for expansion of any kind. */
- if (member (cc, history_no_expand_chars))
- {
- ADD_CHAR (string[i]);
- break;
- }
-
-#if defined (NO_BANG_HASH_MODIFIERS)
- /* There is something that is listed as a `word specifier' in csh
- documentation which means `the expanded text to this point'.
- That is not a word specifier, it is an event specifier. If we
- don't want to allow modifiers with `!#', just stick the current
- output line in again. */
- if (cc == '#')
- {
- if (result)
- {
- temp = xmalloc (1 + strlen (result));
- strcpy (temp, result);
- ADD_STRING (temp);
- free (temp);
- }
- i++;
- break;
- }
-#endif
-
- r = history_expand_internal (string, i, &eindex, &temp, result);
- if (r < 0)
- {
- *output = temp;
- free (result);
- if (string != hstring)
- free (string);
- return -1;
- }
- else
- {
- if (temp)
- {
- modified++;
- if (*temp)
- ADD_STRING (temp);
- free (temp);
- }
- only_printing = r == 1;
- i = eindex;
- }
- break;
- }
- }
-
- *output = result;
- if (string != hstring)
- free (string);
-
- if (only_printing)
- {
- add_history (result);
- return (2);
- }
-
- return (modified != 0);
-}
-
-/* Return a consed string which is the word specified in SPEC, and found
- in FROM. NULL is returned if there is no spec. The address of
- ERROR_POINTER is returned if the word specified cannot be found.
- CALLER_INDEX is the offset in SPEC to start looking; it is updated
- to point to just after the last character parsed. */
-static char *
-get_history_word_specifier (spec, from, caller_index)
- char *spec, *from;
- int *caller_index;
-{
- register int i = *caller_index;
- int first, last;
- int expecting_word_spec = 0;
- char *result;
-
- /* The range of words to return doesn't exist yet. */
- first = last = 0;
- result = (char *)NULL;
-
- /* If we found a colon, then this *must* be a word specification. If
- it isn't, then it is an error. */
- if (spec[i] == ':')
- {
- i++;
- expecting_word_spec++;
- }
-
- /* Handle special cases first. */
-
- /* `%' is the word last searched for. */
- if (spec[i] == '%')
- {
- *caller_index = i + 1;
- return (search_match ? savestring (search_match) : savestring (""));
- }
-
- /* `*' matches all of the arguments, but not the command. */
- if (spec[i] == '*')
- {
- *caller_index = i + 1;
- result = history_arg_extract (1, '$', from);
- return (result ? result : savestring (""));
- }
-
- /* `$' is last arg. */
- if (spec[i] == '$')
- {
- *caller_index = i + 1;
- return (history_arg_extract ('$', '$', from));
- }
-
- /* Try to get FIRST and LAST figured out. */
-
- if (spec[i] == '-')
- first = 0;
- else if (spec[i] == '^')
- first = 1;
- else if (_rl_digit_p (spec[i]) && expecting_word_spec)
- {
- for (first = 0; _rl_digit_p (spec[i]); i++)
- first = (first * 10) + _rl_digit_value (spec[i]);
- }
- else
- return ((char *)NULL); /* no valid `first' for word specifier */
-
- if (spec[i] == '^' || spec[i] == '*')
- {
- last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
- i++;
- }
- else if (spec[i] != '-')
- last = first;
- else
- {
- i++;
-
- if (_rl_digit_p (spec[i]))
- {
- for (last = 0; _rl_digit_p (spec[i]); i++)
- last = (last * 10) + _rl_digit_value (spec[i]);
- }
- else if (spec[i] == '$')
- {
- i++;
- last = '$';
- }
- else if (!spec[i] || spec[i] == ':') /* could be modifier separator */
- last = -1; /* x- abbreviates x-$ omitting word `$' */
- }
-
- *caller_index = i;
-
- if (last >= first || last == '$' || last < 0)
- result = history_arg_extract (first, last, from);
-
- return (result ? result : (char *)&error_pointer);
-}
-
-/* Extract the args specified, starting at FIRST, and ending at LAST.
- The args are taken from STRING. If either FIRST or LAST is < 0,
- then make that arg count from the right (subtract from the number of
- tokens, so that FIRST = -1 means the next to last token on the line).
- If LAST is `$' the last arg from STRING is used. */
-char *
-history_arg_extract (first, last, string)
- int first, last;
- char *string;
-{
- register int i, len;
- char *result;
- int size, offset;
- char **list;
-
- /* XXX - think about making history_tokenize return a struct array,
- each struct in array being a string and a length to avoid the
- calls to strlen below. */
- if ((list = history_tokenize (string)) == NULL)
- return ((char *)NULL);
-
- for (len = 0; list[len]; len++)
- ;
-
- if (last < 0)
- last = len + last - 1;
-
- if (first < 0)
- first = len + first - 1;
-
- if (last == '$')
- last = len - 1;
-
- if (first == '$')
- first = len - 1;
-
- last++;
-
- if (first >= len || last > len || first < 0 || last < 0 || first > last)
- result = ((char *)NULL);
- else
- {
- for (size = 0, i = first; i < last; i++)
- size += strlen (list[i]) + 1;
- result = xmalloc (size + 1);
- result[0] = '\0';
-
- for (i = first, offset = 0; i < last; i++)
- {
- strcpy (result + offset, list[i]);
- offset += strlen (list[i]);
- if (i + 1 < last)
- {
- result[offset++] = ' ';
- result[offset] = 0;
- }
- }
- }
-
- for (i = 0; i < len; i++)
- free (list[i]);
- free (list);
-
- return (result);
-}
-
-#define slashify_in_quotes "\\`\"$"
-
-/* Parse STRING into tokens and return an array of strings. If WIND is
- not -1 and INDP is not null, we also want the word surrounding index
- WIND. The position in the returned array of strings is returned in
- *INDP. */
-static char **
-history_tokenize_internal (string, wind, indp)
- char *string;
- int wind, *indp;
-{
- char **result;
- register int i, start, result_index, size;
- int len, delimiter;
-
- /* Get a token, and stuff it into RESULT. The tokens are split
- exactly where the shell would split them. */
- for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
- {
- delimiter = 0;
-
- /* Skip leading whitespace. */
- for (; string[i] && whitespace (string[i]); i++)
- ;
- if (string[i] == 0 || string[i] == history_comment_char)
- return (result);
-
- start = i;
-
- if (member (string[i], "()\n"))
- {
- i++;
- goto got_token;
- }
-
- if (member (string[i], "<>;&|$"))
- {
- int peek = string[i + 1];
-
- if (peek == string[i] && peek != '$')
- {
- if (peek == '<' && string[i + 2] == '-')
- i++;
- i += 2;
- goto got_token;
- }
- else
- {
- if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
- ((peek == '>') && (string[i] == '&')) ||
- ((peek == '(') && (string[i] == '$')))
- {
- i += 2;
- goto got_token;
- }
- }
- if (string[i] != '$')
- {
- i++;
- goto got_token;
- }
- }
-
- /* Get word from string + i; */
-
- if (member (string[i], HISTORY_QUOTE_CHARACTERS))
- delimiter = string[i++];
-
- for (; string[i]; i++)
- {
- if (string[i] == '\\' && string[i + 1] == '\n')
- {
- i++;
- continue;
- }
-
- if (string[i] == '\\' && delimiter != '\'' &&
- (delimiter != '"' || member (string[i], slashify_in_quotes)))
- {
- i++;
- continue;
- }
-
- if (delimiter && string[i] == delimiter)
- {
- delimiter = 0;
- continue;
- }
-
- if (!delimiter && (member (string[i], HISTORY_WORD_DELIMITERS)))
- break;
-
- if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
- delimiter = string[i];
- }
-
- got_token:
-
- /* If we are looking for the word in which the character at a
- particular index falls, remember it. */
- if (indp && wind != -1 && wind >= start && wind < i)
- *indp = result_index;
-
- len = i - start;
- if (result_index + 2 >= size)
- result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
- result[result_index] = xmalloc (1 + len);
- strncpy (result[result_index], string + start, len);
- result[result_index][len] = '\0';
- result[++result_index] = (char *)NULL;
- }
-
- return (result);
-}
-
-/* Return an array of tokens, much as the shell might. The tokens are
- parsed out of STRING. */
-char **
-history_tokenize (string)
- char *string;
-{
- return (history_tokenize_internal (string, -1, (int *)NULL));
-}
-
-/* Find and return the word which contains the character at index IND
- in the history line LINE. Used to save the word matched by the
- last history !?string? search. */
-static char *
-history_find_word (line, ind)
- char *line;
- int ind;
-{
- char **words, *s;
- int i, wind;
-
- words = history_tokenize_internal (line, ind, &wind);
- if (wind == -1)
- return ((char *)NULL);
- s = words[wind];
- for (i = 0; i < wind; i++)
- free (words[i]);
- for (i = wind + 1; words[i]; i++)
- free (words[i]);
- free (words);
- return s;
-}
diff --git a/readline/histfile.c b/readline/histfile.c
deleted file mode 100644
index 1da45b00b58..00000000000
--- a/readline/histfile.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/* histfile.c - functions to manipulate the history file. */
-
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* The goal is to make the implementation transparent, so that you
- don't have to know what data types are used, just what functions
- you can call. I think I have done that. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include <sys/types.h>
-#ifndef _MINIX
-# include <sys/file.h>
-#endif
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#if defined (__EMX__)
-# ifndef O_BINARY
-# define O_BINARY 0
-# endif
-#else /* !__EMX__ */
- /* If we're not compiling for __EMX__, we don't want this at all. Ever. */
-# undef O_BINARY
-# define O_BINARY 0
-#endif /* !__EMX__ */
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#include "history.h"
-#include "histlib.h"
-
-/* Functions imported from shell.c */
-extern char *get_env_value ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* Return the string that should be used in the place of this
- filename. This only matters when you don't specify the
- filename to read_history (), or write_history (). */
-static char *
-history_filename (filename)
- char *filename;
-{
- char *return_val;
- const char *home;
- int home_len;
-
- return_val = filename ? savestring (filename) : (char *)NULL;
-
- if (return_val)
- return (return_val);
-
- home = get_env_value ("HOME");
-
- if (home == 0)
- {
- home = ".";
- home_len = 1;
- }
- else
- home_len = strlen (home);
-
- return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
- strcpy (return_val, home);
- return_val[home_len] = '/';
- strcpy (return_val + home_len + 1, ".history");
-
- return (return_val);
-}
-
-/* Add the contents of FILENAME to the history list, a line at a time.
- If FILENAME is NULL, then read from ~/.history. Returns 0 if
- successful, or errno if not. */
-int
-read_history (filename)
- char *filename;
-{
- return (read_history_range (filename, 0, -1));
-}
-
-/* Read a range of lines from FILENAME, adding them to the history list.
- Start reading at the FROM'th line and end at the TO'th. If FROM
- is zero, start at the beginning. If TO is less than FROM, read
- until the end of the file. If FILENAME is NULL, then read from
- ~/.history. Returns 0 if successful, or errno if not. */
-int
-read_history_range (filename, from, to)
- char *filename;
- int from, to;
-{
- char *input, *buffer;
- int file, current_line;
- struct stat finfo;
- size_t line_start, line_end, file_size;
-
- buffer = (char *)NULL;
- input = history_filename (filename);
- file = open (input, O_RDONLY|O_BINARY, 0666);
-
- if ((file < 0) || (fstat (file, &finfo) == -1))
- goto error_and_exit;
-
- file_size = (size_t)finfo.st_size;
-
- /* check for overflow on very large files */
- if (file_size != finfo.st_size || file_size + 1 < file_size)
- {
-#if defined (EFBIG)
- errno = EFBIG;
-#endif
- goto error_and_exit;
- }
-
- buffer = xmalloc (file_size + 1);
-#if 0
- if (read (file, buffer, file_size) != file_size)
-#else
- if (read (file, buffer, file_size) < 0)
-#endif
- {
- error_and_exit:
- if (file >= 0)
- close (file);
-
- FREE (input);
- FREE (buffer);
-
- return (errno);
- }
-
- close (file);
-
- /* Set TO to larger than end of file if negative. */
- if (to < 0)
- to = file_size;
-
- /* Start at beginning of file, work to end. */
- line_start = line_end = current_line = 0;
-
- /* Skip lines until we are at FROM. */
- while (line_start < file_size && current_line < from)
- {
- for (line_end = line_start; line_end < file_size; line_end++)
- if (buffer[line_end] == '\n')
- {
- current_line++;
- line_start = line_end + 1;
- if (current_line == from)
- break;
- }
- }
-
- /* If there are lines left to gobble, then gobble them now. */
- for (line_end = line_start; line_end < file_size; line_end++)
- if (buffer[line_end] == '\n')
- {
- buffer[line_end] = '\0';
-
- if (buffer[line_start])
- add_history (buffer + line_start);
-
- current_line++;
-
- if (current_line >= to)
- break;
-
- line_start = line_end + 1;
- }
-
- FREE (input);
- FREE (buffer);
-
- return (0);
-}
-
-/* Truncate the history file FNAME, leaving only LINES trailing lines.
- If FNAME is NULL, then use ~/.history. */
-int
-history_truncate_file (fname, lines)
- char *fname;
- int lines;
-{
- register int i;
- int file, chars_read;
- char *buffer, *filename;
- struct stat finfo;
- size_t file_size;
-
- buffer = (char *)NULL;
- filename = history_filename (fname);
- file = open (filename, O_RDONLY|O_BINARY, 0666);
-
- if (file == -1 || fstat (file, &finfo) == -1)
- goto truncate_exit;
-
- file_size = (size_t)finfo.st_size;
-
- /* check for overflow on very large files */
- if (file_size != finfo.st_size || file_size + 1 < file_size)
- {
- close (file);
-#if defined (EFBIG)
- errno = EFBIG;
-#endif
- goto truncate_exit;
- }
-
- buffer = xmalloc (file_size + 1);
- chars_read = read (file, buffer, file_size);
- close (file);
-
- if (chars_read <= 0)
- goto truncate_exit;
-
- /* Count backwards from the end of buffer until we have passed
- LINES lines. */
- for (i = chars_read - 1; lines && i; i--)
- {
- if (buffer[i] == '\n')
- lines--;
- }
-
- /* If this is the first line, then the file contains exactly the
- number of lines we want to truncate to, so we don't need to do
- anything. It's the first line if we don't find a newline between
- the current value of i and 0. Otherwise, write from the start of
- this line until the end of the buffer. */
- for ( ; i; i--)
- if (buffer[i] == '\n')
- {
- i++;
- break;
- }
-
- /* Write only if there are more lines in the file than we want to
- truncate to. */
- if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
- {
- write (file, buffer + i, file_size - i);
-
-#if defined (__BEOS__)
- /* BeOS ignores O_TRUNC. */
- ftruncate (file, file_size - i);
-#endif
-
- close (file);
- }
-
- truncate_exit:
-
- FREE (buffer);
-
- free (filename);
- return 0;
-}
-
-/* Workhorse function for writing history. Writes NELEMENT entries
- from the history list to FILENAME. OVERWRITE is non-zero if you
- wish to replace FILENAME with the entries. */
-static int
-history_do_write (filename, nelements, overwrite)
- char *filename;
- int nelements, overwrite;
-{
- register int i;
- char *output;
- int file, mode;
-
- mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
- output = history_filename (filename);
-
- if ((file = open (output, mode, 0600)) == -1)
- {
- FREE (output);
- return (errno);
- }
-
- if (nelements > history_length)
- nelements = history_length;
-
- /* Build a buffer of all the lines to write, and write them in one syscall.
- Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
- {
- HIST_ENTRY **the_history; /* local */
- register int j;
- int buffer_size;
- char *buffer;
-
- the_history = history_list ();
- /* Calculate the total number of bytes to write. */
- for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
- buffer_size += 1 + strlen (the_history[i]->line);
-
- /* Allocate the buffer, and fill it. */
- buffer = xmalloc (buffer_size);
-
- for (j = 0, i = history_length - nelements; i < history_length; i++)
- {
- strcpy (buffer + j, the_history[i]->line);
- j += strlen (the_history[i]->line);
- buffer[j++] = '\n';
- }
-
- write (file, buffer, buffer_size);
- free (buffer);
- }
-
- close (file);
-
- FREE (output);
-
- return (0);
-}
-
-/* Append NELEMENT entries to FILENAME. The entries appended are from
- the end of the list minus NELEMENTs up to the end of the list. */
-int
-append_history (nelements, filename)
- int nelements;
- char *filename;
-{
- return (history_do_write (filename, nelements, HISTORY_APPEND));
-}
-
-/* Overwrite FILENAME with the current history. If FILENAME is NULL,
- then write the history list to ~/.history. Values returned
- are as in read_history ().*/
-int
-write_history (filename)
- char *filename;
-{
- return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
-}
diff --git a/readline/histlib.h b/readline/histlib.h
deleted file mode 100644
index 422cf5974db..00000000000
--- a/readline/histlib.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* histlib.h -- internal definitions for the history library. */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_HISTLIB_H_)
-#define _HISTLIB_H_
-
-/* Function pointers can be declared as (Function *)foo. */
-#if !defined (_FUNCTION_DEF)
-# define _FUNCTION_DEF
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();
-typedef char **CPPFunction ();
-#endif /* _FUNCTION_DEF */
-
-#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
-#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
-
-#ifndef savestring
-# ifndef strcpy
-extern char *strcpy ();
-# endif
-#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
-#endif
-
-#ifndef whitespace
-#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
-#endif
-
-#ifndef _rl_digit_p
-#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9')
-#endif
-
-#ifndef _rl_digit_value
-#define _rl_digit_value(c) ((c) - '0')
-#endif
-
-#ifndef member
-# ifndef strchr
-extern char *strchr ();
-# endif
-#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
-#endif
-
-#ifndef FREE
-# define FREE(x) if (x) free (x)
-#endif
-
-/* Possible history errors passed to hist_error. */
-#define EVENT_NOT_FOUND 0
-#define BAD_WORD_SPEC 1
-#define SUBST_FAILED 2
-#define BAD_MODIFIER 3
-#define NO_PREV_SUBST 4
-
-/* Possible definitions for history starting point specification. */
-#define ANCHORED_SEARCH 1
-#define NON_ANCHORED_SEARCH 0
-
-/* Possible definitions for what style of writing the history file we want. */
-#define HISTORY_APPEND 0
-#define HISTORY_OVERWRITE 1
-
-#endif /* !_HISTLIB_H_ */
diff --git a/readline/history.c b/readline/history.c
deleted file mode 100644
index 804ffddcd89..00000000000
--- a/readline/history.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/* History.c -- standalone history library */
-
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* The goal is to make the implementation transparent, so that you
- don't have to know what data types are used, just what functions
- you can call. I think I have done that. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#include "history.h"
-#include "histlib.h"
-
-extern char *xmalloc (), *xrealloc ();
-
-/* The number of slots to increase the_history by. */
-#define DEFAULT_HISTORY_GROW_SIZE 50
-
-/* **************************************************************** */
-/* */
-/* History Functions */
-/* */
-/* **************************************************************** */
-
-/* An array of HIST_ENTRY. This is where we store the history. */
-static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
-
-/* Non-zero means that we have enforced a limit on the amount of
- history that we save. */
-static int history_stifled;
-
-/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
- entries to remember. */
-int max_input_history;
-
-/* The current location of the interactive history pointer. Just makes
- life easier for outside callers. */
-int history_offset;
-
-/* The number of strings currently stored in the history list. */
-int history_length;
-
-/* The current number of slots allocated to the input_history. */
-static int history_size;
-
-/* The logical `base' of the history array. It defaults to 1. */
-int history_base = 1;
-
-/* Return the current HISTORY_STATE of the history. */
-HISTORY_STATE *
-history_get_history_state ()
-{
- HISTORY_STATE *state;
-
- state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
- state->entries = the_history;
- state->offset = history_offset;
- state->length = history_length;
- state->size = history_size;
- state->flags = 0;
- if (history_stifled)
- state->flags |= HS_STIFLED;
-
- return (state);
-}
-
-/* Set the state of the current history array to STATE. */
-void
-history_set_history_state (state)
- HISTORY_STATE *state;
-{
- the_history = state->entries;
- history_offset = state->offset;
- history_length = state->length;
- history_size = state->size;
- if (state->flags & HS_STIFLED)
- history_stifled = 1;
-}
-
-/* Begin a session in which the history functions might be used. This
- initializes interactive variables. */
-void
-using_history ()
-{
- history_offset = history_length;
-}
-
-/* Return the number of bytes that the primary history entries are using.
- This just adds up the lengths of the_history->lines. */
-int
-history_total_bytes ()
-{
- register int i, result;
-
- result = 0;
-
- for (i = 0; the_history && the_history[i]; i++)
- result += strlen (the_history[i]->line);
-
- return (result);
-}
-
-/* Returns the magic number which says what history element we are
- looking at now. In this implementation, it returns history_offset. */
-int
-where_history ()
-{
- return (history_offset);
-}
-
-/* Make the current history item be the one at POS, an absolute index.
- Returns zero if POS is out of range, else non-zero. */
-int
-history_set_pos (pos)
- int pos;
-{
- if (pos > history_length || pos < 0 || !the_history)
- return (0);
- history_offset = pos;
- return (1);
-}
-
-/* Return the current history array. The caller has to be carefull, since this
- is the actual array of data, and could be bashed or made corrupt easily.
- The array is terminated with a NULL pointer. */
-HIST_ENTRY **
-history_list ()
-{
- return (the_history);
-}
-
-/* Return the history entry at the current position, as determined by
- history_offset. If there is no entry there, return a NULL pointer. */
-HIST_ENTRY *
-current_history ()
-{
- return ((history_offset == history_length) || the_history == 0)
- ? (HIST_ENTRY *)NULL
- : the_history[history_offset];
-}
-
-/* Back up history_offset to the previous history entry, and return
- a pointer to that entry. If there is no previous entry then return
- a NULL pointer. */
-HIST_ENTRY *
-previous_history ()
-{
- return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
-}
-
-/* Move history_offset forward to the next history entry, and return
- a pointer to that entry. If there is no next entry then return a
- NULL pointer. */
-HIST_ENTRY *
-next_history ()
-{
- return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
-}
-
-/* Return the history entry which is logically at OFFSET in the history array.
- OFFSET is relative to history_base. */
-HIST_ENTRY *
-history_get (offset)
- int offset;
-{
- int local_index;
-
- local_index = offset - history_base;
- return (local_index >= history_length || local_index < 0 || !the_history)
- ? (HIST_ENTRY *)NULL
- : the_history[local_index];
-}
-
-/* Place STRING at the end of the history list. The data field
- is set to NULL. */
-void
-add_history (string)
- char *string;
-{
- HIST_ENTRY *temp;
-
- if (history_stifled && (history_length == max_input_history))
- {
- register int i;
-
- /* If the history is stifled, and history_length is zero,
- and it equals max_input_history, we don't save items. */
- if (history_length == 0)
- return;
-
- /* If there is something in the slot, then remove it. */
- if (the_history[0])
- {
- free (the_history[0]->line);
- free (the_history[0]);
- }
-
- /* Copy the rest of the entries, moving down one slot. */
- for (i = 0; i < history_length; i++)
- the_history[i] = the_history[i + 1];
-
- history_base++;
- }
- else
- {
- if (history_size == 0)
- {
- history_size = DEFAULT_HISTORY_GROW_SIZE;
- the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
- history_length = 1;
- }
- else
- {
- if (history_length == (history_size - 1))
- {
- history_size += DEFAULT_HISTORY_GROW_SIZE;
- the_history = (HIST_ENTRY **)
- xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
- }
- history_length++;
- }
- }
-
- temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
- temp->line = savestring (string);
- temp->data = (char *)NULL;
-
- the_history[history_length] = (HIST_ENTRY *)NULL;
- the_history[history_length - 1] = temp;
-}
-
-/* Make the history entry at WHICH have LINE and DATA. This returns
- the old entry so you can dispose of the data. In the case of an
- invalid WHICH, a NULL pointer is returned. */
-HIST_ENTRY *
-replace_history_entry (which, line, data)
- int which;
- char *line;
- histdata_t data;
-{
- HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
- HIST_ENTRY *old_value;
-
- if (which >= history_length)
- return ((HIST_ENTRY *)NULL);
-
- old_value = the_history[which];
-
- temp->line = savestring (line);
- temp->data = data;
- the_history[which] = temp;
-
- return (old_value);
-}
-
-/* Remove history element WHICH from the history. The removed
- element is returned to you so you can free the line, data,
- and containing structure. */
-HIST_ENTRY *
-remove_history (which)
- int which;
-{
- HIST_ENTRY *return_value;
-
- if (which >= history_length || !history_length)
- return_value = (HIST_ENTRY *)NULL;
- else
- {
- register int i;
- return_value = the_history[which];
-
- for (i = which; i < history_length; i++)
- the_history[i] = the_history[i + 1];
-
- history_length--;
- }
-
- return (return_value);
-}
-
-/* Stifle the history list, remembering only MAX number of lines. */
-void
-stifle_history (max)
- int max;
-{
- if (max < 0)
- max = 0;
-
- if (history_length > max)
- {
- register int i, j;
-
- /* This loses because we cannot free the data. */
- for (i = 0, j = history_length - max; i < j; i++)
- {
- free (the_history[i]->line);
- free (the_history[i]);
- }
-
- history_base = i;
- for (j = 0, i = history_length - max; j < max; i++, j++)
- the_history[j] = the_history[i];
- the_history[j] = (HIST_ENTRY *)NULL;
- history_length = j;
- }
-
- history_stifled = 1;
- max_input_history = max;
-}
-
-/* Stop stifling the history. This returns the previous amount the
- history was stifled by. The value is positive if the history was
- stifled, negative if it wasn't. */
-int
-unstifle_history ()
-{
- if (history_stifled)
- {
- history_stifled = 0;
- return (-max_input_history);
- }
-
- return (max_input_history);
-}
-
-int
-history_is_stifled ()
-{
- return (history_stifled);
-}
-
-void
-clear_history ()
-{
- register int i;
-
- /* This loses because we cannot free the data. */
- for (i = 0; i < history_length; i++)
- {
- free (the_history[i]->line);
- free (the_history[i]);
- the_history[i] = (HIST_ENTRY *)NULL;
- }
-
- history_offset = history_length = 0;
-}
diff --git a/readline/history.h b/readline/history.h
deleted file mode 100644
index 88bf471bb62..00000000000
--- a/readline/history.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* History.h -- the names of functions that you can call in history. */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef _HISTORY_H_
-#define _HISTORY_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined READLINE_LIBRARY
-# include "rlstdc.h"
-#else
-# include <readline/rlstdc.h>
-#endif
-
-#if !defined (_FUNCTION_DEF)
-# define _FUNCTION_DEF
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();
-typedef char **CPPFunction ();
-#endif
-
-#ifdef __STDC__
-typedef void *histdata_t;
-#else
-typedef char *histdata_t;
-#endif
-
-/* The structure used to store a history entry. */
-typedef struct _hist_entry {
- char *line;
- histdata_t data;
-} HIST_ENTRY;
-
-/* A structure used to pass the current state of the history stuff around. */
-typedef struct _hist_state {
- HIST_ENTRY **entries; /* Pointer to the entries themselves. */
- int offset; /* The location pointer within this array. */
- int length; /* Number of elements within this array. */
- int size; /* Number of slots allocated to this array. */
- int flags;
-} HISTORY_STATE;
-
-/* Flag values for the `flags' member of HISTORY_STATE. */
-#define HS_STIFLED 0x01
-
-/* Initialization and state management. */
-
-/* Begin a session in which the history functions might be used. This
- just initializes the interactive variables. */
-extern void using_history __P((void));
-
-/* Return the current HISTORY_STATE of the history. */
-extern HISTORY_STATE *history_get_history_state __P((void));
-
-/* Set the state of the current history array to STATE. */
-extern void history_set_history_state __P((HISTORY_STATE *));
-
-/* Manage the history list. */
-
-/* Place STRING at the end of the history list.
- The associated data field (if any) is set to NULL. */
-extern void add_history __P((char *));
-
-/* A reasonably useless function, only here for completeness. WHICH
- is the magic number that tells us which element to delete. The
- elements are numbered from 0. */
-extern HIST_ENTRY *remove_history __P((int));
-
-/* Make the history entry at WHICH have LINE and DATA. This returns
- the old entry so you can dispose of the data. In the case of an
- invalid WHICH, a NULL pointer is returned. */
-extern HIST_ENTRY *replace_history_entry __P((int, char *, histdata_t));
-
-/* Clear the history list and start over. */
-extern void clear_history __P((void));
-
-/* Stifle the history list, remembering only MAX number of entries. */
-extern void stifle_history __P((int));
-
-/* Stop stifling the history. This returns the previous amount the
- history was stifled by. The value is positive if the history was
- stifled, negative if it wasn't. */
-extern int unstifle_history __P((void));
-
-/* Return 1 if the history is stifled, 0 if it is not. */
-extern int history_is_stifled __P((void));
-
-/* Information about the history list. */
-
-/* Return a NULL terminated array of HIST_ENTRY which is the current input
- history. Element 0 of this list is the beginning of time. If there
- is no history, return NULL. */
-extern HIST_ENTRY **history_list __P((void));
-
-/* Returns the number which says what history element we are now
- looking at. */
-extern int where_history __P((void));
-
-/* Return the history entry at the current position, as determined by
- history_offset. If there is no entry there, return a NULL pointer. */
-HIST_ENTRY *current_history __P((void));
-
-/* Return the history entry which is logically at OFFSET in the history
- array. OFFSET is relative to history_base. */
-extern HIST_ENTRY *history_get __P((int));
-
-/* Return the number of bytes that the primary history entries are using.
- This just adds up the lengths of the_history->lines. */
-extern int history_total_bytes __P((void));
-
-/* Moving around the history list. */
-
-/* Set the position in the history list to POS. */
-int history_set_pos __P((int));
-
-/* Back up history_offset to the previous history entry, and return
- a pointer to that entry. If there is no previous entry, return
- a NULL pointer. */
-extern HIST_ENTRY *previous_history __P((void));
-
-/* Move history_offset forward to the next item in the input_history,
- and return the a pointer to that entry. If there is no next entry,
- return a NULL pointer. */
-extern HIST_ENTRY *next_history __P((void));
-
-/* Searching the history list. */
-
-/* Search the history for STRING, starting at history_offset.
- If DIRECTION < 0, then the search is through previous entries,
- else through subsequent. If the string is found, then
- current_history () is the history entry, and the value of this function
- is the offset in the line of that history entry that the string was
- found in. Otherwise, nothing is changed, and a -1 is returned. */
-extern int history_search __P((char *, int));
-
-/* Search the history for STRING, starting at history_offset.
- The search is anchored: matching lines must begin with string.
- DIRECTION is as in history_search(). */
-extern int history_search_prefix __P((char *, int));
-
-/* Search for STRING in the history list, starting at POS, an
- absolute index into the list. DIR, if negative, says to search
- backwards from POS, else forwards.
- Returns the absolute index of the history element where STRING
- was found, or -1 otherwise. */
-extern int history_search_pos __P((char *, int, int));
-
-/* Managing the history file. */
-
-/* Add the contents of FILENAME to the history list, a line at a time.
- If FILENAME is NULL, then read from ~/.history. Returns 0 if
- successful, or errno if not. */
-extern int read_history __P((char *));
-
-/* Read a range of lines from FILENAME, adding them to the history list.
- Start reading at the FROM'th line and end at the TO'th. If FROM
- is zero, start at the beginning. If TO is less than FROM, read
- until the end of the file. If FILENAME is NULL, then read from
- ~/.history. Returns 0 if successful, or errno if not. */
-extern int read_history_range __P((char *, int, int));
-
-/* Write the current history to FILENAME. If FILENAME is NULL,
- then write the history list to ~/.history. Values returned
- are as in read_history (). */
-extern int write_history __P((char *));
-
-/* Append NELEMENT entries to FILENAME. The entries appended are from
- the end of the list minus NELEMENTs up to the end of the list. */
-int append_history __P((int, char *));
-
-/* Truncate the history file, leaving only the last NLINES lines. */
-extern int history_truncate_file __P((char *, int));
-
-/* History expansion. */
-
-/* Expand the string STRING, placing the result into OUTPUT, a pointer
- to a string. Returns:
-
- 0) If no expansions took place (or, if the only change in
- the text was the de-slashifying of the history expansion
- character)
- 1) If expansions did take place
- -1) If there was an error in expansion.
- 2) If the returned line should just be printed.
-
- If an error ocurred in expansion, then OUTPUT contains a descriptive
- error message. */
-extern int history_expand __P((char *, char **));
-
-/* Extract a string segment consisting of the FIRST through LAST
- arguments present in STRING. Arguments are broken up as in
- the shell. */
-extern char *history_arg_extract __P((int, int, char *));
-
-/* Return the text of the history event beginning at the current
- offset into STRING. Pass STRING with *INDEX equal to the
- history_expansion_char that begins this specification.
- DELIMITING_QUOTE is a character that is allowed to end the string
- specification for what to search for in addition to the normal
- characters `:', ` ', `\t', `\n', and sometimes `?'. */
-extern char *get_history_event __P((char *, int *, int));
-
-/* Return an array of tokens, much as the shell might. The tokens are
- parsed out of STRING. */
-extern char **history_tokenize __P((char *));
-
-/* Exported history variables. */
-extern int history_base;
-extern int history_length;
-extern int max_input_history;
-extern char history_expansion_char;
-extern char history_subst_char;
-extern char history_comment_char;
-extern const char *history_no_expand_chars;
-extern const char *history_search_delimiter_chars;
-extern int history_quotes_inhibit_expansion;
-
-/* If set, this function is called to decide whether or not a particular
- history expansion should be treated as a special case for the calling
- application and not expanded. */
-extern Function *history_inhibit_expansion_function;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_HISTORY_H_ */
diff --git a/readline/histsearch.c b/readline/histsearch.c
deleted file mode 100644
index eb17e9332e8..00000000000
--- a/readline/histsearch.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* histsearch.c -- searching the history list. */
-
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#include "history.h"
-#include "histlib.h"
-
-/* Variables imported from other history library files. */
-extern int history_offset;
-
-/* The list of alternate characters that can delimit a history search
- string. */
-const char *history_search_delimiter_chars = (char *)NULL;
-
-/* Search the history for STRING, starting at history_offset.
- If DIRECTION < 0, then the search is through previous entries, else
- through subsequent. If ANCHORED is non-zero, the string must
- appear at the beginning of a history line, otherwise, the string
- may appear anywhere in the line. If the string is found, then
- current_history () is the history entry, and the value of this
- function is the offset in the line of that history entry that the
- string was found in. Otherwise, nothing is changed, and a -1 is
- returned. */
-
-static int
-history_search_internal (string, direction, anchored)
- char *string;
- int direction, anchored;
-{
- register int i, reverse;
- register char *line;
- register int line_index;
- int string_len;
- HIST_ENTRY **the_history; /* local */
-
- i = history_offset;
- reverse = (direction < 0);
-
- /* Take care of trivial cases first. */
- if (string == 0 || *string == '\0')
- return (-1);
-
- if (!history_length || ((i == history_length) && !reverse))
- return (-1);
-
- if (reverse && (i == history_length))
- i--;
-
-#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
-
- the_history = history_list ();
- string_len = strlen (string);
- while (1)
- {
- /* Search each line in the history list for STRING. */
-
- /* At limit for direction? */
- if ((reverse && i < 0) || (!reverse && i == history_length))
- return (-1);
-
- line = the_history[i]->line;
- line_index = strlen (line);
-
- /* If STRING is longer than line, no match. */
- if (string_len > line_index)
- {
- NEXT_LINE ();
- continue;
- }
-
- /* Handle anchored searches first. */
- if (anchored == ANCHORED_SEARCH)
- {
- if (STREQN (string, line, string_len))
- {
- history_offset = i;
- return (0);
- }
-
- NEXT_LINE ();
- continue;
- }
-
- /* Do substring search. */
- if (reverse)
- {
- line_index -= string_len;
-
- while (line_index >= 0)
- {
- if (STREQN (string, line + line_index, string_len))
- {
- history_offset = i;
- return (line_index);
- }
- line_index--;
- }
- }
- else
- {
- register int limit;
-
- limit = line_index - string_len + 1;
- line_index = 0;
-
- while (line_index < limit)
- {
- if (STREQN (string, line + line_index, string_len))
- {
- history_offset = i;
- return (line_index);
- }
- line_index++;
- }
- }
- NEXT_LINE ();
- }
-}
-
-/* Do a non-anchored search for STRING through the history in DIRECTION. */
-int
-history_search (string, direction)
- char *string;
- int direction;
-{
- return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
-}
-
-/* Do an anchored search for string through the history in DIRECTION. */
-int
-history_search_prefix (string, direction)
- char *string;
- int direction;
-{
- return (history_search_internal (string, direction, ANCHORED_SEARCH));
-}
-
-/* Search for STRING in the history list. DIR is < 0 for searching
- backwards. POS is an absolute index into the history list at
- which point to begin searching. */
-int
-history_search_pos (string, dir, pos)
- char *string;
- int dir, pos;
-{
- int ret, old;
-
- old = where_history ();
- history_set_pos (pos);
- if (history_search (string, dir) == -1)
- {
- history_set_pos (old);
- return (-1);
- }
- ret = where_history ();
- history_set_pos (old);
- return ret;
-}
diff --git a/readline/input.c b/readline/input.c
deleted file mode 100644
index ea1342969b0..00000000000
--- a/readline/input.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/* input.c -- character input functions for readline. */
-
-/* Copyright (C) 1994 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 2, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* HAVE_SYS_FILE_H */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_SELECT)
-# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX) || defined(TIME_WITH_SYS_TIME)
-# include <sys/time.h>
-# endif
-#endif /* HAVE_SELECT */
-#if defined (HAVE_SYS_SELECT_H)
-# include <sys/select.h>
-#endif
-
-#if defined (FIONREAD_IN_SYS_IOCTL)
-# include <sys/ioctl.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-
-/* What kind of non-blocking I/O do we have? */
-#if !defined (O_NDELAY) && defined (O_NONBLOCK)
-# define O_NDELAY O_NONBLOCK /* Posix style */
-#endif
-
-/* Functions imported from other files in the library. */
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables and functions from macro.c. */
-extern void _rl_add_macro_char ();
-extern void _rl_with_macro_input ();
-extern int _rl_next_macro_key ();
-extern int _rl_defining_kbd_macro;
-
-#if defined (VI_MODE)
-extern void _rl_vi_set_last ();
-extern int _rl_vi_textmod_command ();
-#endif /* VI_MODE */
-
-extern FILE *rl_instream, *rl_outstream;
-extern Function *rl_last_func;
-extern int rl_key_sequence_length;
-extern int rl_pending_input;
-extern int rl_editing_mode;
-
-extern Keymap _rl_keymap;
-
-extern int _rl_convert_meta_chars_to_ascii;
-
-#if defined (__GO32__)
-# include <pc.h>
-#endif /* __GO32__ */
-
-/* Non-null means it is a pointer to a function to run while waiting for
- character input. */
-Function *rl_event_hook = (Function *)NULL;
-
-Function *rl_getc_function = rl_getc;
-
-/* **************************************************************** */
-/* */
-/* Character Input Buffering */
-/* */
-/* **************************************************************** */
-
-static int pop_index, push_index;
-static unsigned char ibuffer[512];
-static int ibuffer_len = sizeof (ibuffer) - 1;
-
-#define any_typein (push_index != pop_index)
-
-int
-_rl_any_typein ()
-{
- return any_typein;
-}
-
-/* Return the amount of space available in the buffer for stuffing
- characters. */
-static int
-ibuffer_space ()
-{
- if (pop_index > push_index)
- return (pop_index - push_index - 1);
- else
- return (ibuffer_len - (push_index - pop_index));
-}
-
-/* Get a key from the buffer of characters to be read.
- Return the key in KEY.
- Result is KEY if there was a key, or 0 if there wasn't. */
-static int
-rl_get_char (key)
- int *key;
-{
- if (push_index == pop_index)
- return (0);
-
- *key = ibuffer[pop_index++];
-
- if (pop_index >= ibuffer_len)
- pop_index = 0;
-
- return (1);
-}
-
-/* Stuff KEY into the *front* of the input buffer.
- Returns non-zero if successful, zero if there is
- no space left in the buffer. */
-static int
-rl_unget_char (key)
- int key;
-{
- if (ibuffer_space ())
- {
- pop_index--;
- if (pop_index < 0)
- pop_index = ibuffer_len - 1;
- ibuffer[pop_index] = key;
- return (1);
- }
- return (0);
-}
-
-#if defined(__EMX__)
-int waiting_char = -1;
-#endif
-
-/* If a character is available to be read, then read it
- and stuff it into IBUFFER. Otherwise, just return. */
-static void
-rl_gather_tyi ()
-{
-#if defined (__EMX__)
- if (isatty (0) && (waiting_char = _read_kbd(0, 0, 0)) != -1 && ibuffer_space ())
- {
- int i;
- i = (*rl_getc_function) (rl_instream);
- rl_stuff_char (i);
- }
-#elif defined (__GO32__)
- char input;
-
- if (isatty (0) && kbhit () && ibuffer_space ())
- {
- int i;
- i = (*rl_getc_function) (rl_instream);
- rl_stuff_char (i);
- }
-#else /* !__GO32__ */
-
- int tty;
- register int tem, result;
- int chars_avail;
- char input;
-#if defined(HAVE_SELECT)
- fd_set readfds, exceptfds;
- struct timeval timeout;
-#endif
-
- tty = fileno (rl_instream);
-
-#if defined (HAVE_SELECT)
- FD_ZERO (&readfds);
- FD_ZERO (&exceptfds);
- FD_SET (tty, &readfds);
- FD_SET (tty, &exceptfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = 100000; /* 0.1 seconds */
- if (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) <= 0)
- return; /* Nothing to read. */
-#endif
-
- result = -1;
-#if defined (FIONREAD)
- result = ioctl (tty, FIONREAD, &chars_avail);
-#endif
-
-#if defined (O_NDELAY)
- if (result == -1)
- {
- tem = fcntl (tty, F_GETFL, 0);
-
- fcntl (tty, F_SETFL, (tem | O_NDELAY));
- chars_avail = read (tty, &input, 1);
-
- fcntl (tty, F_SETFL, tem);
- if (chars_avail == -1 && errno == EAGAIN)
- return;
- }
-#endif /* O_NDELAY */
-
- /* If there's nothing available, don't waste time trying to read
- something. */
- if (chars_avail <= 0)
- return;
-
- tem = ibuffer_space ();
-
- if (chars_avail > tem)
- chars_avail = tem;
-
- /* One cannot read all of the available input. I can only read a single
- character at a time, or else programs which require input can be
- thwarted. If the buffer is larger than one character, I lose.
- Damn! */
- if (tem < ibuffer_len)
- chars_avail = 0;
-
- if (result != -1)
- {
- while (chars_avail--)
- rl_stuff_char ((*rl_getc_function) (rl_instream));
- }
- else
- {
- if (chars_avail)
- rl_stuff_char (input);
- }
-#endif /* !__GO32__ */
-}
-
-/* Is there input available to be read on the readline input file
- descriptor? Only works if the system has select(2) or FIONREAD. */
-int
-_rl_input_available ()
-{
-#if defined (__EMX__)
- if (isatty (0) && (waiting_char = _read_kbd(0, 0, 0)) != -1)
- return 1;
-#else /* __EMX__ */
-#if defined(HAVE_SELECT)
- fd_set readfds, exceptfds;
- struct timeval timeout;
-#endif
-#if defined(FIONREAD)
- int chars_avail;
-#endif
- int tty;
-
- tty = fileno (rl_instream);
-
-#if defined (HAVE_SELECT)
- FD_ZERO (&readfds);
- FD_ZERO (&exceptfds);
- FD_SET (tty, &readfds);
- FD_SET (tty, &exceptfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = 100000; /* 0.1 seconds */
- return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
-#endif
-
-#if defined (FIONREAD)
- if (ioctl (tty, FIONREAD, &chars_avail) == 0)
- return (chars_avail);
-#endif
-#endif /* !__EMX__ */
-
- return 0;
-}
-
-void
-_rl_insert_typein (c)
- int c;
-{
- int key, t, i;
- char *string;
-
- i = key = 0;
- string = xmalloc (ibuffer_len + 1);
- string[i++] = (char) c;
-
- while ((t = rl_get_char (&key)) &&
- _rl_keymap[key].type == ISFUNC &&
- _rl_keymap[key].function == rl_insert)
- string[i++] = key;
-
- if (t)
- rl_unget_char (key);
-
- string[i] = '\0';
- rl_insert_text (string);
- free (string);
-}
-
-/* Add KEY to the buffer of characters to be read. Returns 1 if the
- character was stuffed correctly; 0 otherwise. */
-int
-rl_stuff_char (key)
- int key;
-{
- if (ibuffer_space () == 0)
- return 0;
-
- if (key == EOF)
- {
- key = NEWLINE;
- rl_pending_input = EOF;
- }
- ibuffer[push_index++] = key;
- if (push_index >= ibuffer_len)
- push_index = 0;
-
- return 1;
-}
-
-/* Make C be the next command to be executed. */
-int
-rl_execute_next (c)
- int c;
-{
- rl_pending_input = c;
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Character Input */
-/* */
-/* **************************************************************** */
-
-/* Read a key, including pending input. */
-int
-rl_read_key ()
-{
- int c;
-
- rl_key_sequence_length++;
-
- if (rl_pending_input)
- {
- c = rl_pending_input;
- rl_pending_input = 0;
- }
- else
- {
- /* If input is coming from a macro, then use that. */
- if ((c = _rl_next_macro_key ()))
- return (c);
-
- /* If the user has an event function, then call it periodically. */
- if (rl_event_hook)
- {
- while (rl_event_hook && rl_get_char (&c) == 0)
- {
- (*rl_event_hook) ();
- rl_gather_tyi ();
- }
- }
- else
- {
- if (rl_get_char (&c) == 0)
- c = (*rl_getc_function) (rl_instream);
- }
- }
-
- return (c);
-}
-
-int
-rl_getc (stream)
- FILE *stream;
-{
- int result, flags;
- unsigned char c;
-
-#if defined (__EMX__)
- if (isatty (0))
- {
- int key;
-
- if (waiting_char != -1)
- {
- key = waiting_char;
- waiting_char = -1;
- }
- else
- {
-#ifdef __RSXNT__
- pc_flush();
-#endif
- key = _read_kbd(0, 1, 0);
- }
-
- while (key == 0)
- {
- key |= (_read_kbd(0, 1, 0) << 8);
- /* printf("<%04X> ", key);
- fflush(stdout); */
-
- switch (key)
- {
- case 0x4B00: /* left arrow */
- key = 'B' - 64;
- break;
- case 0x4D00: /* right arrow */
- key = 'F' - 64;
- break;
- case 0x7300: /* ctrl left arrow */
- key = 27;
- waiting_char = 'B';
- break;
- case 0x7400: /* ctrl right arrow */
- key = 27;
- waiting_char = 'F';
- break;
- case 0x4800: /* up arrow */
- key = 'P' - 64;
- break;
- case 0x5000: /* down arrow */
- key = 'N' - 64;
- break;
- case 0x8D00: /* ctrl up arrow */
- key = 'R' - 64;
- break;
- case 0x9100: /* ctrl down arrow */
- key = 'S' - 64;
- break;
- case 0x4700: /* home key */
- key = 'A' - 64;
- break;
- case 0x4F00: /* end key */
- key = 'E' - 64;
- break;
- case 0x7700: /* ctrl home key */
- key = 27;
- waiting_char = '<';
- break;
- case 0x7500: /* ctrl end key */
- key = 27;
- waiting_char = '>';
- break;
- case 0x5300: /* delete key */
- key = 'D' - 64;
- break;
- case 0x5200: /* insert key */
- key = 'V' - 64;
- break;
- default: /* ignore all other special keys, read next */
- key = _read_kbd(0, 1, 0);
- break;
- }
- }
-
- return (key & 0xFF);
- }
-#endif /* __EMX__ */
-
-#if defined (__GO32__)
- if (isatty (0))
- return (getkey () & 0x7F);
-#endif /* __GO32__ */
-
- while (1)
- {
- result = read (fileno (stream), &c, sizeof (unsigned char));
-
- if (result == sizeof (unsigned char))
- return (c);
-
- /* If zero characters are returned, then the file that we are
- reading from is empty! Return EOF in that case. */
- if (result == 0)
- return (EOF);
-
-#if defined (__BEOS__)
- if (errno == EINTR)
- continue;
-#endif
-
-#if defined (EWOULDBLOCK)
- if (errno == EWOULDBLOCK)
- {
- if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
- return (EOF);
- if (flags & O_NDELAY)
- {
- flags &= ~O_NDELAY;
- fcntl (fileno (stream), F_SETFL, flags);
- continue;
- }
- continue;
- }
-#endif /* EWOULDBLOCK */
-
-#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK)
- if (errno == EAGAIN)
- {
- if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
- return (EOF);
- if (flags & O_NONBLOCK)
- {
- flags &= ~O_NONBLOCK;
- fcntl (fileno (stream), F_SETFL, flags);
- continue;
- }
- }
-#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */
-
-#if !defined (__GO32__)
- /* If the error that we received was SIGINT, then try again,
- this is simply an interrupted system call to read ().
- Otherwise, some error ocurred, also signifying EOF. */
- if (errno != EINTR)
- return (EOF);
-#endif /* !__GO32__ */
- }
-}
diff --git a/readline/isearch.c b/readline/isearch.c
deleted file mode 100644
index a4a294b6b20..00000000000
--- a/readline/isearch.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/* **************************************************************** */
-/* */
-/* I-Search and Searching */
-/* */
-/* **************************************************************** */
-
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#include <stdio.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif
-
-#include "rldefs.h"
-#include "readline.h"
-#include "history.h"
-
-/* Variables exported to other files in the readline library. */
-unsigned char *_rl_isearch_terminators = (unsigned char *)NULL;
-
-/* Variables imported from other files in the readline library. */
-extern Keymap _rl_keymap;
-extern HIST_ENTRY *saved_line_for_history;
-extern int rl_line_buffer_len;
-extern int rl_point, rl_end;
-extern char *rl_line_buffer;
-
-extern int rl_execute_next ();
-extern void rl_extend_line_buffer ();
-
-extern int _rl_input_available ();
-
-extern char *xmalloc (), *xrealloc ();
-
-static int rl_search_history ();
-
-/* Last line found by the current incremental search, so we don't `find'
- identical lines many times in a row. */
-static char *prev_line_found;
-
-/* Search backwards through the history looking for a string which is typed
- interactively. Start with the current line. */
-int
-rl_reverse_search_history (sign, key)
- int sign, key;
-{
- return (rl_search_history (-sign, key));
-}
-
-/* Search forwards through the history looking for a string which is typed
- interactively. Start with the current line. */
-int
-rl_forward_search_history (sign, key)
- int sign, key;
-{
- return (rl_search_history (sign, key));
-}
-
-/* Display the current state of the search in the echo-area.
- SEARCH_STRING contains the string that is being searched for,
- DIRECTION is zero for forward, or 1 for reverse,
- WHERE is the history list number of the current line. If it is
- -1, then this line is the starting one. */
-static void
-rl_display_search (search_string, reverse_p, where)
- char *search_string;
- int reverse_p;
- int where __attribute__((unused));
-{
- char *message;
- int msglen, searchlen;
-
- searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
-
- message = xmalloc (searchlen + 33);
- msglen = 0;
-
-#if defined (NOTDEF)
- if (where != -1)
- {
- sprintf (message, "[%d]", where + history_base);
- msglen = strlen (message);
- }
-#endif /* NOTDEF */
-
- message[msglen++] = '(';
-
- if (reverse_p)
- {
- strcpy (message + msglen, "reverse-");
- msglen += 8;
- }
-
- strcpy (message + msglen, "i-search)`");
- msglen += 10;
-
- if (search_string)
- {
- strcpy (message + msglen, search_string);
- msglen += searchlen;
- }
-
- strcpy (message + msglen, "': ");
-
- rl_message ("%s", message, 0);
- free (message);
- (*rl_redisplay_function) ();
-}
-
-/* Search through the history looking for an interactively typed string.
- This is analogous to i-search. We start the search in the current line.
- DIRECTION is which direction to search; >= 0 means forward, < 0 means
- backwards. */
-static int
-rl_search_history (int direction, int invoking_key __attribute__((unused)))
-{
- /* The string that the user types in to search for. */
- char *search_string;
-
- /* The current length of SEARCH_STRING. */
- int search_string_index;
-
- /* The amount of space that SEARCH_STRING has allocated to it. */
- int search_string_size;
-
- /* The list of lines to search through. */
- char **lines, *allocated_line;
-
- /* The length of LINES. */
- int hlen;
-
- /* Where we get LINES from. */
- HIST_ENTRY **hlist;
-
- register int i;
- int orig_point, orig_line, last_found_line;
- int c, found, failed, sline_len;
-
- /* The line currently being searched. */
- char *sline;
-
- /* Offset in that line. */
- int line_index;
-
- /* Non-zero if we are doing a reverse search. */
- int reverse;
-
- /* The list of characters which terminate the search, but are not
- subsequently executed. If the variable isearch-terminators has
- been set, we use that value, otherwise we use ESC and C-J. */
- unsigned char *isearch_terminators;
-
- orig_point = rl_point;
- last_found_line = orig_line = where_history ();
- reverse = direction < 0;
- hlist = history_list ();
- allocated_line = (char *)NULL;
-
- isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
- : (unsigned char *)"\033\012";
-
- /* Create an arrary of pointers to the lines that we want to search. */
- maybe_replace_line ();
- i = 0;
- if (hlist)
- for (i = 0; hlist[i]; i++);
-
- /* Allocate space for this many lines, +1 for the current input line,
- and remember those lines. */
- lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
- for (i = 0; i < hlen; i++)
- lines[i] = hlist[i]->line;
-
- if (saved_line_for_history)
- lines[i] = saved_line_for_history->line;
- else
- {
- /* Keep track of this so we can free it. */
- allocated_line = xmalloc (1 + strlen (rl_line_buffer));
- strcpy (allocated_line, &rl_line_buffer[0]);
- lines[i] = allocated_line;
- }
-
- hlen++;
-
- /* The line where we start the search. */
- i = orig_line;
-
- rl_save_prompt ();
-
- /* Initialize search parameters. */
- search_string = xmalloc (search_string_size = 128);
- *search_string = '\0';
- search_string_index = 0;
- prev_line_found = (char *)0; /* XXX */
-
- /* Normalize DIRECTION into 1 or -1. */
- direction = (direction >= 0) ? 1 : -1;
-
- rl_display_search (search_string, reverse, -1);
-
- sline = rl_line_buffer;
- sline_len = strlen (sline);
- line_index = rl_point;
-
- found = failed = 0;
- for (;;)
- {
- Function *f = (Function *)NULL;
-
- /* Read a key and decide how to proceed. */
- c = rl_read_key ();
-
- if (_rl_keymap[c].type == ISFUNC)
- {
- f = _rl_keymap[c].function;
-
- if (f == rl_reverse_search_history)
- c = reverse ? -1 : -2;
- else if (f == rl_forward_search_history)
- c = !reverse ? -1 : -2;
- }
-
-#if 0
- /* Let NEWLINE (^J) terminate the search for people who don't like
- using ESC. ^M can still be used to terminate the search and
- immediately execute the command. */
- if (c == ESC || c == NEWLINE)
-#else
- /* The characters in isearch_terminators (set from the user-settable
- variable isearch-terminators) are used to terminate the search but
- not subsequently execute the character as a command. The default
- value is "\033\012" (ESC and C-J). */
- if (strchr((char*) isearch_terminators, c))
-#endif
- {
- /* ESC still terminates the search, but if there is pending
- input or if input arrives within 0.1 seconds (on systems
- with select(2)) it is used as a prefix character
- with rl_execute_next. WATCH OUT FOR THIS! This is intended
- to allow the arrow keys to be used like ^F and ^B are used
- to terminate the search and execute the movement command. */
- if (c == ESC && _rl_input_available ()) /* XXX */
- rl_execute_next (ESC);
- break;
- }
-
- if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G'))
- {
- rl_execute_next (c);
- break;
- }
-
- switch (c)
- {
- case -1:
- if (search_string_index == 0)
- continue;
- else if (reverse)
- --line_index;
- else if (line_index != sline_len)
- ++line_index;
- else
- ding ();
- break;
-
- /* switch directions */
- case -2:
- direction = -direction;
- reverse = direction < 0;
- break;
-
- case CTRL ('G'):
- strcpy (rl_line_buffer, lines[orig_line]);
- rl_point = orig_point;
- rl_end = strlen (rl_line_buffer);
- rl_restore_prompt();
- rl_clear_message ();
- if (allocated_line)
- free (allocated_line);
- free (lines);
- return 0;
-
-#if 0
- /* delete character from search string. */
- case -3:
- if (search_string_index == 0)
- ding ();
- else
- {
- search_string[--search_string_index] = '\0';
- /* This is tricky. To do this right, we need to keep a
- stack of search positions for the current search, with
- sentinels marking the beginning and end. */
- }
- break;
-#endif
-
- default:
- /* Add character to search string and continue search. */
- if (search_string_index + 2 >= search_string_size)
- {
- search_string_size += 128;
- search_string = xrealloc (search_string, search_string_size);
- }
- search_string[search_string_index++] = c;
- search_string[search_string_index] = '\0';
- break;
- }
-
- for (found = failed = 0;;)
- {
- int limit = sline_len - search_string_index + 1;
-
- /* Search the current line. */
- while (reverse ? (line_index >= 0) : (line_index < limit))
- {
- if (STREQN (search_string, sline + line_index, search_string_index))
- {
- found++;
- break;
- }
- else
- line_index += direction;
- }
- if (found)
- break;
-
- /* Move to the next line, but skip new copies of the line
- we just found and lines shorter than the string we're
- searching for. */
- do
- {
- /* Move to the next line. */
- i += direction;
-
- /* At limit for direction? */
- if (reverse ? (i < 0) : (i == hlen))
- {
- failed++;
- break;
- }
-
- /* We will need these later. */
- sline = lines[i];
- sline_len = strlen (sline);
- }
- while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
- (search_string_index > sline_len));
-
- if (failed)
- break;
-
- /* Now set up the line for searching... */
- line_index = reverse ? sline_len - search_string_index : 0;
- }
-
- if (failed)
- {
- /* We cannot find the search string. Ding the bell. */
- ding ();
- i = last_found_line;
- continue; /* XXX - was break */
- }
-
- /* We have found the search string. Just display it. But don't
- actually move there in the history list until the user accepts
- the location. */
- if (found)
- {
- int line_len;
-
- prev_line_found = lines[i];
- line_len = strlen (lines[i]);
-
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
-
- strcpy (rl_line_buffer, lines[i]);
- rl_point = line_index;
- rl_end = line_len;
- last_found_line = i;
- rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
- }
- }
-
- /* The searching is over. The user may have found the string that she
- was looking for, or else she may have exited a failing search. If
- LINE_INDEX is -1, then that shows that the string searched for was
- not found. We use this to determine where to place rl_point. */
-
- /* First put back the original state. */
- strcpy (rl_line_buffer, lines[orig_line]);
-
- rl_restore_prompt ();
-
- /* Free the search string. */
- free (search_string);
-
- if (last_found_line < orig_line)
- rl_get_previous_history (orig_line - last_found_line, 0);
- else
- rl_get_next_history (last_found_line - orig_line, 0);
-
- /* If the string was not found, put point at the end of the line. */
- if (line_index < 0)
- line_index = strlen (rl_line_buffer);
- rl_point = line_index;
- rl_clear_message ();
-
- if (allocated_line)
- free (allocated_line);
- free (lines);
-
- return 0;
-}
diff --git a/readline/keymaps.c b/readline/keymaps.c
deleted file mode 100644
index c73666bf273..00000000000
--- a/readline/keymaps.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
-
-/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include "rlconf.h"
-#include "keymaps.h"
-#include "emacs_keymap.c"
-
-#if defined (VI_MODE)
-#include "vi_keymap.c"
-#endif
-
-extern int rl_do_lowercase_version ();
-extern int rl_rubout (), rl_insert ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Functions for manipulating Keymaps. */
-/* */
-/* **************************************************************** */
-
-
-/* Return a new, empty keymap.
- Free it with free() when you are done. */
-Keymap
-rl_make_bare_keymap ()
-{
- register int i;
- Keymap keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY));
-
- for (i = 0; i < KEYMAP_SIZE; i++)
- {
- keymap[i].type = ISFUNC;
- keymap[i].function = (Function *)NULL;
- }
-
- for (i = 'A'; i < ('Z' + 1); i++)
- {
- keymap[i].type = ISFUNC;
- keymap[i].function = rl_do_lowercase_version;
- }
-
- return (keymap);
-}
-
-/* Return a new keymap which is a copy of MAP. */
-Keymap
-rl_copy_keymap (map)
- Keymap map;
-{
- register int i;
- Keymap temp = rl_make_bare_keymap ();
-
- for (i = 0; i < KEYMAP_SIZE; i++)
- {
- temp[i].type = map[i].type;
- temp[i].function = map[i].function;
- }
- return (temp);
-}
-
-/* Return a new keymap with the printing characters bound to rl_insert,
- the uppercase Meta characters bound to run their lowercase equivalents,
- and the Meta digits bound to produce numeric arguments. */
-Keymap
-rl_make_keymap ()
-{
- register int i;
- Keymap newmap;
-
- newmap = rl_make_bare_keymap ();
-
- /* All ASCII printing characters are self-inserting. */
- for (i = ' '; i < 127; i++)
- newmap[i].function = rl_insert;
-
- newmap[TAB].function = rl_insert;
- newmap[RUBOUT].function = rl_rubout; /* RUBOUT == 127 */
- newmap[CTRL('H')].function = rl_rubout;
-
-#if KEYMAP_SIZE > 128
- /* Printing characters in some 8-bit character sets. */
- for (i = 128; i < 160; i++)
- newmap[i].function = rl_insert;
-
- /* ISO Latin-1 printing characters should self-insert. */
- for (i = 160; i < 256; i++)
- newmap[i].function = rl_insert;
-#endif /* KEYMAP_SIZE > 128 */
-
- return (newmap);
-}
-
-/* Free the storage associated with MAP. */
-void
-rl_discard_keymap (map)
- Keymap map;
-{
- int i;
-
- if (!map)
- return;
-
- for (i = 0; i < KEYMAP_SIZE; i++)
- {
- switch (map[i].type)
- {
- case ISFUNC:
- break;
-
- case ISKMAP:
- rl_discard_keymap ((Keymap)map[i].function);
- break;
-
- case ISMACR:
- free ((char *)map[i].function);
- break;
- }
- }
-}
diff --git a/readline/keymaps.h b/readline/keymaps.h
deleted file mode 100644
index 5dff46f56c2..00000000000
--- a/readline/keymaps.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* keymaps.h -- Manipulation of readline keymaps. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef _KEYMAPS_H_
-#define _KEYMAPS_H_
-
-#if defined (READLINE_LIBRARY)
-# include "rlstdc.h"
-# include "chardefs.h"
-#else
-# include <readline/rlstdc.h>
-# include <readline/chardefs.h>
-#endif
-
-#if !defined (_FUNCTION_DEF)
-# define _FUNCTION_DEF
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();
-typedef char **CPPFunction ();
-#endif
-
-/* A keymap contains one entry for each key in the ASCII set.
- Each entry consists of a type and a pointer.
- FUNCTION is the address of a function to run, or the
- address of a keymap to indirect through.
- TYPE says which kind of thing FUNCTION is. */
-typedef struct _keymap_entry {
- char type;
- Function *function;
-} KEYMAP_ENTRY;
-
-/* This must be large enough to hold bindings for all of the characters
- in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x,
- and so on). */
-#define KEYMAP_SIZE 256
-
-/* I wanted to make the above structure contain a union of:
- union { Function *function; struct _keymap_entry *keymap; } value;
- but this made it impossible for me to create a static array.
- Maybe I need C lessons. */
-
-typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
-typedef KEYMAP_ENTRY *Keymap;
-
-/* The values that TYPE can have in a keymap entry. */
-#define ISFUNC 0
-#define ISKMAP 1
-#define ISMACR 2
-
-extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
-extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
-
-/* Return a new, empty keymap.
- Free it with free() when you are done. */
-extern Keymap rl_make_bare_keymap __P((void));
-
-/* Return a new keymap which is a copy of MAP. */
-extern Keymap rl_copy_keymap __P((Keymap));
-
-/* Return a new keymap with the printing characters bound to rl_insert,
- the lowercase Meta characters bound to run their equivalents, and
- the Meta digits bound to produce numeric arguments. */
-extern Keymap rl_make_keymap __P((void));
-
-/* Free the storage associated with a keymap. */
-extern void rl_discard_keymap __P((Keymap));
-
-/* These functions actually appear in bind.c */
-
-/* Return the keymap corresponding to a given name. Names look like
- `emacs' or `emacs-meta' or `vi-insert'. */
-extern Keymap rl_get_keymap_by_name __P((char *));
-
-/* Return the current keymap. */
-extern Keymap rl_get_keymap __P((void));
-
-/* Set the current keymap to MAP. */
-extern void rl_set_keymap __P((Keymap));
-
-#endif /* _KEYMAPS_H_ */
diff --git a/readline/kill.c b/readline/kill.c
deleted file mode 100644
index 78387e138c2..00000000000
--- a/readline/kill.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/* kill.c -- kill ring management. */
-
-/* Copyright (C) 1994 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h> /* for _POSIX_VERSION */
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-extern int _rl_last_command_was_kill;
-extern int rl_editing_mode;
-extern int rl_explicit_arg;
-extern Function *rl_last_func;
-
-extern void _rl_init_argument ();
-extern int _rl_set_mark_at_pos ();
-extern void _rl_fix_point ();
-extern void _rl_abort_internal ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Killing Mechanism */
-/* */
-/* **************************************************************** */
-
-/* What we assume for a max number of kills. */
-#define DEFAULT_MAX_KILLS 10
-
-/* The real variable to look at to find out when to flush kills. */
-static int rl_max_kills = DEFAULT_MAX_KILLS;
-
-/* Where to store killed text. */
-static char **rl_kill_ring = (char **)NULL;
-
-/* Where we are in the kill ring. */
-static int rl_kill_index;
-
-/* How many slots we have in the kill ring. */
-static int rl_kill_ring_length;
-
-/* How to say that you only want to save a certain amount
- of kill material. */
-int
-rl_set_retained_kills (int num __attribute__((unused)))
-{
- return 0;
-}
-
-/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary.
- This uses TEXT directly, so the caller must not free it. If APPEND is
- non-zero, and the last command was a kill, the text is appended to the
- current kill ring slot, otherwise prepended. */
-static int
-_rl_copy_to_kill_ring (text, append)
- char *text;
- int append;
-{
- char *old, *new;
- int slot;
-
- /* First, find the slot to work with. */
- if (_rl_last_command_was_kill == 0)
- {
- /* Get a new slot. */
- if (rl_kill_ring == 0)
- {
- /* If we don't have any defined, then make one. */
- rl_kill_ring = (char **)
- xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
- rl_kill_ring[slot = 0] = (char *)NULL;
- }
- else
- {
- /* We have to add a new slot on the end, unless we have
- exceeded the max limit for remembering kills. */
- slot = rl_kill_ring_length;
- if (slot == rl_max_kills)
- {
- register int i;
- free (rl_kill_ring[0]);
- for (i = 0; i < slot; i++)
- rl_kill_ring[i] = rl_kill_ring[i + 1];
- }
- else
- {
- slot = rl_kill_ring_length += 1;
- rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
- }
- rl_kill_ring[--slot] = (char *)NULL;
- }
- }
- else
- slot = rl_kill_ring_length - 1;
-
- /* If the last command was a kill, prepend or append. */
- if (_rl_last_command_was_kill && rl_editing_mode != vi_mode)
- {
- old = rl_kill_ring[slot];
- new = xmalloc (1 + strlen (old) + strlen (text));
-
- if (append)
- {
- strcpy (new, old);
- strcat (new, text);
- }
- else
- {
- strcpy (new, text);
- strcat (new, old);
- }
- free (old);
- free (text);
- rl_kill_ring[slot] = new;
- }
- else
- rl_kill_ring[slot] = text;
-
- rl_kill_index = slot;
- return 0;
-}
-
-/* The way to kill something. This appends or prepends to the last
- kill, if the last command was a kill command. if FROM is less
- than TO, then the text is appended, otherwise prepended. If the
- last command was not a kill command, then a new slot is made for
- this kill. */
-int
-rl_kill_text (from, to)
- int from, to;
-{
- char *text;
-
- /* Is there anything to kill? */
- if (from == to)
- {
- _rl_last_command_was_kill++;
- return 0;
- }
-
- text = rl_copy_text (from, to);
-
- /* Delete the copied text from the line. */
- rl_delete_text (from, to);
-
- _rl_copy_to_kill_ring (text, from < to);
-
- _rl_last_command_was_kill++;
- return 0;
-}
-
-/* Now REMEMBER! In order to do prepending or appending correctly, kill
- commands always make rl_point's original position be the FROM argument,
- and rl_point's extent be the TO argument. */
-
-/* **************************************************************** */
-/* */
-/* Killing Commands */
-/* */
-/* **************************************************************** */
-
-/* Delete the word at point, saving the text in the kill ring. */
-int
-rl_kill_word (count, key)
- int count, key;
-{
- int orig_point = rl_point;
-
- if (count < 0)
- return (rl_backward_kill_word (-count, key));
- else
- {
- rl_forward_word (count, key);
-
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
-
- rl_point = orig_point;
- }
- return 0;
-}
-
-/* Rubout the word before point, placing it on the kill ring. */
-int
-rl_backward_kill_word (count, ignore)
- int count, ignore;
-{
- int orig_point = rl_point;
-
- if (count < 0)
- return (rl_kill_word (-count, ignore));
- else
- {
- rl_backward_word (count, ignore);
-
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
- }
- return 0;
-}
-
-/* Kill from here to the end of the line. If DIRECTION is negative, kill
- back to the line start instead. */
-int
-rl_kill_line (direction, ignore)
- int direction, ignore;
-{
- int orig_point = rl_point;
-
- if (direction < 0)
- return (rl_backward_kill_line (1, ignore));
- else
- {
- rl_end_of_line (1, ignore);
- if (orig_point != rl_point)
- rl_kill_text (orig_point, rl_point);
- rl_point = orig_point;
- }
- return 0;
-}
-
-/* Kill backwards to the start of the line. If DIRECTION is negative, kill
- forwards to the line end instead. */
-int
-rl_backward_kill_line (direction, ignore)
- int direction, ignore;
-{
- int orig_point = rl_point;
-
- if (direction < 0)
- return (rl_kill_line (1, ignore));
- else
- {
- if (!rl_point)
- ding ();
- else
- {
- rl_beg_of_line (1, ignore);
- rl_kill_text (orig_point, rl_point);
- }
- }
- return 0;
-}
-
-/* Kill the whole line, no matter where point is. */
-int
-rl_kill_full_line (int count __attribute__((unused)),
- int ignore __attribute__((unused)))
-{
- rl_begin_undo_group ();
- rl_point = 0;
- rl_kill_text (rl_point, rl_end);
- rl_end_undo_group ();
- return 0;
-}
-
-/* The next two functions mimic unix line editing behaviour, except they
- save the deleted text on the kill ring. This is safer than not saving
- it, and since we have a ring, nobody should get screwed. */
-
-/* This does what C-w does in Unix. We can't prevent people from
- using behaviour that they expect. */
-int
-rl_unix_word_rubout (int count, int key __attribute__((unused)))
-{
- int orig_point;
-
- if (rl_point == 0)
- ding ();
- else
- {
- orig_point = rl_point;
- if (count <= 0)
- count = 1;
-
- while (count--)
- {
- while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
- rl_point--;
-
- while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0))
- rl_point--;
- }
-
- rl_kill_text (orig_point, rl_point);
- }
- return 0;
-}
-
-/* Here is C-u doing what Unix does. You don't *have* to use these
- key-bindings. We have a choice of killing the entire line, or
- killing from where we are to the start of the line. We choose the
- latter, because if you are a Unix weenie, then you haven't backspaced
- into the line at all, and if you aren't, then you know what you are
- doing. */
-int
-rl_unix_line_discard (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (rl_point == 0)
- ding ();
- else
- {
- rl_kill_text (rl_point, 0);
- rl_point = 0;
- }
- return 0;
-}
-
-/* Copy the text in the `region' to the kill ring. If DELETE is non-zero,
- delete the text from the line as well. */
-static int
-region_kill_internal (delete)
- int delete;
-{
- char *text;
-
- if (rl_mark == rl_point)
- {
- _rl_last_command_was_kill++;
- return 0;
- }
-
- text = rl_copy_text (rl_point, rl_mark);
- if (delete)
- rl_delete_text (rl_point, rl_mark);
- _rl_copy_to_kill_ring (text, rl_point < rl_mark);
-
- _rl_last_command_was_kill++;
- return 0;
-}
-
-/* Copy the text in the region to the kill ring. */
-int
-rl_copy_region_to_kill (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- return (region_kill_internal (0));
-}
-
-/* Kill the text between the point and mark. */
-int
-rl_kill_region (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- int r;
-
- r = region_kill_internal (1);
- _rl_fix_point (1);
- return r;
-}
-
-/* Copy COUNT words to the kill ring. DIR says which direction we look
- to find the words. */
-static int
-_rl_copy_word_as_kill (count, dir)
- int count, dir;
-{
- int om, op, r;
-
- om = rl_mark;
- op = rl_point;
-
- if (dir > 0)
- rl_forward_word (count, 0);
- else
- rl_backward_word (count, 0);
-
- rl_mark = rl_point;
-
- if (dir > 0)
- rl_backward_word (count, 0);
- else
- rl_forward_word (count, 0);
-
- r = region_kill_internal (0);
-
- rl_mark = om;
- rl_point = op;
-
- return r;
-}
-
-int
-rl_copy_forward_word (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_copy_backward_word (-count, key));
-
- return (_rl_copy_word_as_kill (count, 1));
-}
-
-int
-rl_copy_backward_word (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_copy_forward_word (-count, key));
-
- return (_rl_copy_word_as_kill (count, -1));
-}
-
-/* Yank back the last killed text. This ignores arguments. */
-int
-rl_yank (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (rl_kill_ring == 0)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- _rl_set_mark_at_pos (rl_point);
- rl_insert_text (rl_kill_ring[rl_kill_index]);
- return 0;
-}
-
-/* If the last command was yank, or yank_pop, and the text just
- before point is identical to the current kill item, then
- delete that text from the line, rotate the index down, and
- yank back some other text. */
-int
-rl_yank_pop (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- int l, n;
-
- if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
- !rl_kill_ring)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- l = strlen (rl_kill_ring[rl_kill_index]);
- n = rl_point - l;
- if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
- {
- rl_delete_text (n, rl_point);
- rl_point = n;
- rl_kill_index--;
- if (rl_kill_index < 0)
- rl_kill_index = rl_kill_ring_length - 1;
- rl_yank (1, 0);
- return 0;
- }
- else
- {
- _rl_abort_internal ();
- return -1;
- }
-}
-
-/* Yank the COUNTh argument from the previous history line, skipping
- HISTORY_SKIP lines before looking for the `previous line'. */
-static int
-rl_yank_nth_arg_internal (count, ignore, history_skip)
- int count, ignore, history_skip;
-{
- register HIST_ENTRY *entry;
- char *arg;
- int i;
-
- if (history_skip)
- {
- for (i = 0; i < history_skip; i++)
- entry = previous_history ();
- }
-
- entry = previous_history ();
- if (entry)
- {
- if (history_skip)
- {
- for (i = 0; i < history_skip; i++)
- next_history ();
- }
- next_history ();
- }
- else
- {
- ding ();
- return -1;
- }
-
- arg = history_arg_extract (count, count, entry->line);
- if (!arg || !*arg)
- {
- ding ();
- return -1;
- }
-
- rl_begin_undo_group ();
-
-#if defined (VI_MODE)
- /* Vi mode always inserts a space before yanking the argument, and it
- inserts it right *after* rl_point. */
- if (rl_editing_mode == vi_mode)
- {
- rl_vi_append_mode (1, ignore);
- rl_insert_text (" ");
- }
-#endif /* VI_MODE */
-
- rl_insert_text (arg);
- free (arg);
-
- rl_end_undo_group ();
- return 0;
-}
-
-/* Yank the COUNTth argument from the previous history line. */
-int
-rl_yank_nth_arg (count, ignore)
- int count, ignore;
-{
- return (rl_yank_nth_arg_internal (count, ignore, 0));
-}
-
-/* Yank the last argument from the previous history line. This `knows'
- how rl_yank_nth_arg treats a count of `$'. With an argument, this
- behaves the same as rl_yank_nth_arg. */
-int
-rl_yank_last_arg (count, key)
- int count, key;
-{
- static int history_skip = 0;
- static int explicit_arg_p = 0;
- static int count_passed = 1;
- static int direction = 1;
- static int undo_needed = 0;
- int retval;
-
- if (rl_last_func != rl_yank_last_arg)
- {
- history_skip = 0;
- explicit_arg_p = rl_explicit_arg;
- count_passed = count;
- direction = 1;
- }
- else
- {
- if (undo_needed)
- rl_do_undo ();
- if (count < 1)
- direction = -direction;
- history_skip += direction;
- if (history_skip < 0)
- history_skip = 0;
- }
-
- if (explicit_arg_p)
- retval = rl_yank_nth_arg_internal (count_passed, key, history_skip);
- else
- retval = rl_yank_nth_arg_internal ('$', key, history_skip);
-
- undo_needed = retval == 0;
- return retval;
-}
-
-/* A special paste command for users of Cygnus's cygwin32. */
-#if defined (__CYGWIN32__)
-#include <windows.h>
-
-int
-rl_paste_from_clipboard (count, key)
- int count, key;
-{
- char *data, *ptr;
- int len;
-
- if (OpenClipboard (NULL) == 0)
- return (0);
-
- data = (char *)GetClipboardData (CF_TEXT);
- if (data)
- {
- ptr = strchr (data, '\r');
- if (ptr)
- {
- len = ptr - data;
- ptr = xmalloc (len + 1);
- ptr[len] = '\0';
- strncpy (ptr, data, len);
- }
- else
- ptr = data;
- rl_insert_text (ptr);
- if (ptr != data)
- free (ptr);
- CloseClipboard ();
- }
- return (0);
-}
-#endif /* __CYGWIN32__ */
diff --git a/readline/macro.c b/readline/macro.c
deleted file mode 100644
index b4d7835c631..00000000000
--- a/readline/macro.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* macro.c -- keyboard macros for readline. */
-
-/* Copyright (C) 1994 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h> /* for _POSIX_VERSION */
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
-
-/* Forward definitions. */
-void _rl_push_executing_macro (), _rl_pop_executing_macro ();
-void _rl_add_macro_char ();
-
-/* Extern declarations. */
-extern int rl_explicit_arg;
-extern int rl_key_sequence_length;
-
-extern void _rl_abort_internal ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Hacking Keyboard Macros */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means to save keys that we dispatch on in a kbd macro. */
-int _rl_defining_kbd_macro = 0;
-
-/* The currently executing macro string. If this is non-zero,
- then it is a malloc ()'ed string where input is coming from. */
-char *_rl_executing_macro = (char *)NULL;
-
-/* The offset in the above string to the next character to be read. */
-static int executing_macro_index;
-
-/* The current macro string being built. Characters get stuffed
- in here by add_macro_char (). */
-static char *current_macro = (char *)NULL;
-
-/* The size of the buffer allocated to current_macro. */
-static int current_macro_size;
-
-/* The index at which characters are being added to current_macro. */
-static int current_macro_index;
-
-/* A structure used to save nested macro strings.
- It is a linked list of string/index for each saved macro. */
-struct saved_macro {
- struct saved_macro *next;
- const char *string;
- int sindex;
-};
-
-/* The list of saved macros. */
-static struct saved_macro *macro_list = (struct saved_macro *)NULL;
-
-/* Set up to read subsequent input from STRING.
- STRING is free ()'ed when we are done with it. */
-void
-_rl_with_macro_input (const char *string)
-{
- _rl_push_executing_macro ();
- _rl_executing_macro = (char*) string;
- executing_macro_index = 0;
-}
-
-/* Return the next character available from a macro, or 0 if
- there are no macro characters. */
-int
-_rl_next_macro_key ()
-{
- if (_rl_executing_macro == 0)
- return (0);
-
- if (_rl_executing_macro[executing_macro_index] == 0)
- {
- _rl_pop_executing_macro ();
- return (_rl_next_macro_key ());
- }
-
- return (_rl_executing_macro[executing_macro_index++]);
-}
-
-/* Save the currently executing macro on a stack of saved macros. */
-void
-_rl_push_executing_macro ()
-{
- struct saved_macro *saver;
-
- saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
- saver->next = macro_list;
- saver->sindex = executing_macro_index;
- saver->string = _rl_executing_macro;
-
- macro_list = saver;
-}
-
-/* Discard the current macro, replacing it with the one
- on the top of the stack of saved macros. */
-void
-_rl_pop_executing_macro ()
-{
- struct saved_macro *macro;
-
- if (_rl_executing_macro)
- free (_rl_executing_macro);
-
- _rl_executing_macro = (char *)NULL;
- executing_macro_index = 0;
-
- if (macro_list)
- {
- macro = macro_list;
- _rl_executing_macro = (char*) macro_list->string;
- executing_macro_index = macro_list->sindex;
- macro_list = macro_list->next;
- free (macro);
- }
-}
-
-/* Add a character to the macro being built. */
-void
-_rl_add_macro_char (c)
- int c;
-{
- if (current_macro_index + 1 >= current_macro_size)
- {
- if (current_macro == 0)
- current_macro = xmalloc (current_macro_size = 25);
- else
- current_macro = xrealloc (current_macro, current_macro_size += 25);
- }
-
- current_macro[current_macro_index++] = c;
- current_macro[current_macro_index] = '\0';
-}
-
-void
-_rl_kill_kbd_macro ()
-{
- if (current_macro)
- {
- free (current_macro);
- current_macro = (char *) NULL;
- }
- current_macro_size = current_macro_index = 0;
-
- if (_rl_executing_macro)
- {
- free (_rl_executing_macro);
- _rl_executing_macro = (char *) NULL;
- }
- executing_macro_index = 0;
-
- _rl_defining_kbd_macro = 0;
-}
-
-/* Begin defining a keyboard macro.
- Keystrokes are recorded as they are executed.
- End the definition with rl_end_kbd_macro ().
- If a numeric argument was explicitly typed, then append this
- definition to the end of the existing macro, and start by
- re-executing the existing macro. */
-int
-rl_start_kbd_macro (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (_rl_defining_kbd_macro)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- if (rl_explicit_arg)
- {
- if (current_macro)
- _rl_with_macro_input (savestring (current_macro));
- }
- else
- current_macro_index = 0;
-
- _rl_defining_kbd_macro = 1;
- return 0;
-}
-
-/* Stop defining a keyboard macro.
- A numeric argument says to execute the macro right now,
- that many times, counting the definition as the first time. */
-int
-rl_end_kbd_macro (int count, int ignore __attribute__((unused)))
-{
- if (_rl_defining_kbd_macro == 0)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- current_macro_index -= rl_key_sequence_length - 1;
- current_macro[current_macro_index] = '\0';
-
- _rl_defining_kbd_macro = 0;
-
- return (rl_call_last_kbd_macro (--count, 0));
-}
-
-/* Execute the most recently defined keyboard macro.
- COUNT says how many times to execute it. */
-int
-rl_call_last_kbd_macro (int count, int key __attribute__((unused)))
-{
- if (current_macro == 0)
- _rl_abort_internal ();
-
- if (_rl_defining_kbd_macro)
- {
- ding (); /* no recursive macros */
- current_macro[--current_macro_index] = '\0'; /* erase this char */
- return 0;
- }
-
- while (count--)
- _rl_with_macro_input (savestring (current_macro));
- return 0;
-}
-
-void
-rl_push_macro_input (macro)
- char *macro;
-{
- _rl_with_macro_input (macro);
-}
diff --git a/readline/nls.c b/readline/nls.c
deleted file mode 100644
index f2d413d59d5..00000000000
--- a/readline/nls.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/* nls.c -- skeletal internationalization code. */
-
-/* Copyright (C) 1996 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <ctype.h>
-
-#include "rldefs.h"
-
-extern int _rl_convert_meta_chars_to_ascii;
-extern int _rl_output_meta_chars;
-extern int _rl_meta_flag;
-
-/* Functions imported from shell.c */
-extern char *get_env_value ();
-
-#if !defined (HAVE_SETLOCALE)
-/* A list of legal values for the LANG or LC_CTYPE environment variables.
- If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
- or LANG environment variable (using the first of those with a value),
- readline eight-bit mode is enabled. */
-static char *legal_lang_values[] =
-{
- "iso88591",
- "iso88592",
- "iso88593",
- "iso88594",
- "iso88595",
- "iso88596",
- "iso88597",
- "iso88598",
- "iso88599",
- "iso885910",
- "koi8r",
- "koi8-r",
- 0
-};
-
-static char *normalize_codeset ();
-static char *find_codeset ();
-#endif /* !HAVE_SETLOCALE */
-
-/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
- to decide the defaults for 8-bit character input and output. Returns
- 1 if we set eight-bit mode. */
-int
-_rl_init_eightbit ()
-{
-/* If we have setlocale(3), just check the current LC_CTYPE category
- value, and go into eight-bit mode if it's not C or POSIX. */
-#if defined (HAVE_SETLOCALE)
- char *t;
-
- /* Set the LC_CTYPE locale category from environment variables. */
- t = setlocale (LC_CTYPE, "");
- if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
- {
- _rl_meta_flag = 1;
- _rl_convert_meta_chars_to_ascii = 0;
- _rl_output_meta_chars = 1;
- return (1);
- }
- else
- return (0);
-
-#else /* !HAVE_SETLOCALE */
- char *lspec, *t;
- int i;
-
- /* We don't have setlocale. Finesse it. Check the environment for the
- appropriate variables and set eight-bit mode if they have the right
- values. */
- lspec = get_env_value ("LC_ALL");
- if (lspec == 0) lspec = get_env_value ("LC_CTYPE");
- if (lspec == 0) lspec = get_env_value ("LANG");
- if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
- return (0);
- for (i = 0; t && legal_lang_values[i]; i++)
- if (STREQ (t, legal_lang_values[i]))
- {
- _rl_meta_flag = 1;
- _rl_convert_meta_chars_to_ascii = 0;
- _rl_output_meta_chars = 1;
- break;
- }
- free (t);
- return (legal_lang_values[i] ? 1 : 0);
-
-#endif /* !HAVE_SETLOCALE */
-}
-
-#if !defined (HAVE_SETLOCALE)
-static char *
-normalize_codeset (codeset)
- char *codeset;
-{
- size_t namelen, i;
- int len, all_digits;
- char *wp, *retval;
-
- codeset = find_codeset (codeset, &namelen);
-
- if (codeset == 0)
- return (codeset);
-
- all_digits = 1;
- for (len = 0, i = 0; i < namelen; i++)
- {
- if (isalnum (codeset[i]))
- {
- len++;
- all_digits &= isdigit (codeset[i]);
- }
- }
-
- retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
- if (retval == 0)
- return ((char *)0);
-
- wp = retval;
- /* Add `iso' to beginning of an all-digit codeset */
- if (all_digits)
- {
- *wp++ = 'i';
- *wp++ = 's';
- *wp++ = 'o';
- }
-
- for (i = 0; i < namelen; i++)
- if (isalpha (codeset[i]))
- *wp++ = (isupper (codeset[i])) ? tolower (codeset[i]) : codeset[i];
- else if (isdigit (codeset[i]))
- *wp++ = codeset[i];
- *wp = '\0';
-
- return retval;
-}
-
-/* Isolate codeset portion of locale specification. */
-static char *
-find_codeset (name, lenp)
- char *name;
- size_t *lenp;
-{
- char *cp, *language, *result;
-
- cp = language = name;
- result = (char *)0;
-
- while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
- cp++;
-
- /* This does not make sense: language has to be specified. As
- an exception we allow the variable to contain only the codeset
- name. Perhaps there are funny codeset names. */
- if (language == cp)
- {
- *lenp = strlen (language);
- result = language;
- }
- else
- {
- /* Next is the territory. */
- if (*cp == '_')
- do
- ++cp;
- while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
-
- /* Now, finally, is the codeset. */
- result = cp;
- if (*cp == '.')
- do
- ++cp;
- while (*cp && *cp != '@');
-
- if (cp - result > 2)
- {
- result++;
- *lenp = cp - result;
- }
- else
- {
- *lenp = strlen (language);
- result = language;
- }
- }
-
- return result;
-}
-#endif /* !HAVE_SETLOCALE */
diff --git a/readline/parens.c b/readline/parens.c
deleted file mode 100644
index a500c0afac7..00000000000
--- a/readline/parens.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* parens.c -- Implementation of matching parentheses feature. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#include "rlconf.h"
-
-#if !defined (PAREN_MATCHING)
-extern int rl_insert ();
-
-int
-rl_insert_close (count, invoking_key)
- int count, invoking_key;
-{
- return (rl_insert (count, invoking_key));
-}
-
-#else /* PAREN_MATCHING */
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#if defined (FD_SET) && !defined (HAVE_SELECT)
-# define HAVE_SELECT
-#endif
-
-#if defined (HAVE_SELECT)
-# include <sys/time.h>
-#endif /* HAVE_SELECT */
-#if defined (HAVE_SYS_SELECT_H)
-# include <sys/select.h>
-#endif
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-#include "readline.h"
-
-extern int rl_explicit_arg;
-
-/* Non-zero means try to blink the matching open parenthesis when the
- close parenthesis is inserted. */
-#if defined (HAVE_SELECT)
-int rl_blink_matching_paren = 1;
-#else /* !HAVE_SELECT */
-int rl_blink_matching_paren = 0;
-#endif /* !HAVE_SELECT */
-
-static int find_matching_open ();
-
-int
-rl_insert_close (count, invoking_key)
- int count, invoking_key;
-{
- if (rl_explicit_arg || !rl_blink_matching_paren)
- rl_insert (count, invoking_key);
- else
- {
-#if defined (HAVE_SELECT)
- int orig_point, match_point, ready;
- struct timeval timer;
- fd_set readfds;
-
- rl_insert (1, invoking_key);
- (*rl_redisplay_function) ();
- match_point =
- find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
-
- /* Emacs might message or ring the bell here, but I don't. */
- if (match_point < 0)
- return -1;
-
- FD_ZERO (&readfds);
- FD_SET (fileno (rl_instream), &readfds);
- timer.tv_sec = 0;
- timer.tv_usec = 500000;
-
- orig_point = rl_point;
- rl_point = match_point;
- (*rl_redisplay_function) ();
- ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
- rl_point = orig_point;
-#else /* !HAVE_SELECT */
- rl_insert (count, invoking_key);
-#endif /* !HAVE_SELECT */
- }
- return 0;
-}
-
-static int
-find_matching_open (string, from, closer)
- char *string;
- int from, closer;
-{
- register int i;
- int opener, level, delimiter;
-
- switch (closer)
- {
- case ']': opener = '['; break;
- case '}': opener = '{'; break;
- case ')': opener = '('; break;
- default:
- return (-1);
- }
-
- level = 1; /* The closer passed in counts as 1. */
- delimiter = 0; /* Delimited state unknown. */
-
- for (i = from; i > -1; i--)
- {
- if (delimiter && (string[i] == delimiter))
- delimiter = 0;
- else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i]))
- delimiter = string[i];
- else if (!delimiter && (string[i] == closer))
- level++;
- else if (!delimiter && (string[i] == opener))
- level--;
-
- if (!level)
- break;
- }
- return (i);
-}
-
-#endif /* PAREN_MATCHING */
diff --git a/readline/posixdir.h b/readline/posixdir.h
deleted file mode 100644
index 7480a93d5db..00000000000
--- a/readline/posixdir.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* posixdir.h -- Posix directory reading includes and defines. */
-
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- Bash is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* This file should be included instead of <dirent.h> or <sys/dir.h>. */
-
-#if !defined (_POSIXDIR_H_)
-#define _POSIXDIR_H_
-
-#if defined (HAVE_DIRENT_H)
-# include <dirent.h>
-# define D_NAMLEN(d) (strlen ((d)->d_name))
-#else
-# if defined (HAVE_SYS_NDIR_H)
-# include <sys/ndir.h>
-# endif
-# if defined (HAVE_SYS_DIR_H)
-# include <sys/dir.h>
-# endif
-# if defined (HAVE_NDIR_H)
-# include <ndir.h>
-# endif
-# if !defined (dirent)
-# define dirent direct
-# endif /* !dirent */
-# define D_NAMLEN(d) ((d)->d_namlen)
-#endif /* !HAVE_DIRENT_H */
-
-#if defined (STRUCT_DIRENT_HAS_D_INO) && !defined (STRUCT_DIRENT_HAS_D_FILENO)
-# define d_fileno d_ino
-#endif
-
-#endif /* !_POSIXDIR_H_ */
diff --git a/readline/posixjmp.h b/readline/posixjmp.h
deleted file mode 100644
index 1347cc07ebc..00000000000
--- a/readline/posixjmp.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* posixjmp.h -- wrapper for setjmp.h with changes for POSIX systems. */
-
-#ifndef _POSIXJMP_H_
-#define _POSIXJMP_H_
-
-#include <setjmp.h>
-
-/* This *must* be included *after* config.h */
-
-#if defined (HAVE_POSIX_SIGSETJMP)
-# define procenv_t sigjmp_buf
-# if !defined (__OPENNT)
-# undef setjmp
-# define setjmp(x) sigsetjmp((x), 1)
-# undef longjmp
-# define longjmp(x, n) siglongjmp((x), (n))
-# endif /* !__OPENNT */
-#else
-# define procenv_t jmp_buf
-#endif
-
-#endif /* _POSIXJMP_H_ */
diff --git a/readline/posixstat.h b/readline/posixstat.h
deleted file mode 100644
index bfce8c04fef..00000000000
--- a/readline/posixstat.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* posixstat.h -- Posix stat(2) definitions for systems that
- don't have them. */
-
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- Bash is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* This file should be included instead of <sys/stat.h>.
- It relies on the local sys/stat.h to work though. */
-#if !defined (_POSIXSTAT_H_)
-#define _POSIXSTAT_H_
-
-#include <sys/stat.h>
-
-#if defined (STAT_MACROS_BROKEN)
-# undef S_ISBLK
-# undef S_ISCHR
-# undef S_ISDIR
-# undef S_ISFIFO
-# undef S_ISREG
-# undef S_ISLNK
-#endif /* STAT_MACROS_BROKEN */
-
-/* These are guaranteed to work only on isc386 */
-#if !defined (S_IFDIR) && !defined (S_ISDIR)
-# define S_IFDIR 0040000
-#endif /* !S_IFDIR && !S_ISDIR */
-#if !defined (S_IFMT)
-# define S_IFMT 0170000
-#endif /* !S_IFMT */
-
-/* Posix 1003.1 5.6.1.1 <sys/stat.h> file types */
-
-/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but
- do not provide the S_IS* macros that Posix requires. */
-
-#if defined (_S_IFMT) && !defined (S_IFMT)
-#define S_IFMT _S_IFMT
-#endif
-#if defined (_S_IFIFO) && !defined (S_IFIFO)
-#define S_IFIFO _S_IFIFO
-#endif
-#if defined (_S_IFCHR) && !defined (S_IFCHR)
-#define S_IFCHR _S_IFCHR
-#endif
-#if defined (_S_IFDIR) && !defined (S_IFDIR)
-#define S_IFDIR _S_IFDIR
-#endif
-#if defined (_S_IFBLK) && !defined (S_IFBLK)
-#define S_IFBLK _S_IFBLK
-#endif
-#if defined (_S_IFREG) && !defined (S_IFREG)
-#define S_IFREG _S_IFREG
-#endif
-#if defined (_S_IFLNK) && !defined (S_IFLNK)
-#define S_IFLNK _S_IFLNK
-#endif
-#if defined (_S_IFSOCK) && !defined (S_IFSOCK)
-#define S_IFSOCK _S_IFSOCK
-#endif
-
-/* Test for each symbol individually and define the ones necessary (some
- systems claiming Posix compatibility define some but not all). */
-
-#if defined (S_IFBLK) && !defined (S_ISBLK)
-#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */
-#endif
-
-#if defined (S_IFCHR) && !defined (S_ISCHR)
-#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */
-#endif
-
-#if defined (S_IFDIR) && !defined (S_ISDIR)
-#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */
-#endif
-
-#if defined (S_IFREG) && !defined (S_ISREG)
-#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */
-#endif
-
-#if defined (S_IFIFO) && !defined (S_ISFIFO)
-#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */
-#endif
-
-#if defined (S_IFLNK) && !defined (S_ISLNK)
-#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */
-#endif
-
-#if defined (S_IFSOCK) && !defined (S_ISSOCK)
-#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */
-#endif
-
-/*
- * POSIX 1003.1 5.6.1.2 <sys/stat.h> File Modes
- */
-
-#if !defined (S_IRWXU)
-# if !defined (S_IREAD)
-# define S_IREAD 00400
-# define S_IWRITE 00200
-# define S_IEXEC 00100
-# endif /* S_IREAD */
-
-# if !defined (S_IRUSR)
-# define S_IRUSR S_IREAD /* read, owner */
-# define S_IWUSR S_IWRITE /* write, owner */
-# define S_IXUSR S_IEXEC /* execute, owner */
-
-# define S_IRGRP (S_IREAD >> 3) /* read, group */
-# define S_IWGRP (S_IWRITE >> 3) /* write, group */
-# define S_IXGRP (S_IEXEC >> 3) /* execute, group */
-
-# define S_IROTH (S_IREAD >> 6) /* read, other */
-# define S_IWOTH (S_IWRITE >> 6) /* write, other */
-# define S_IXOTH (S_IEXEC >> 6) /* execute, other */
-# endif /* !S_IRUSR */
-
-# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
-# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
-# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
-#endif /* !S_IRWXU */
-
-/* These are non-standard, but are used in builtins.c$symbolic_umask() */
-#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
-#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
-#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
-
-#endif /* _POSIXSTAT_H_ */
diff --git a/readline/readline.c b/readline/readline.c
deleted file mode 100644
index 1da73250773..00000000000
--- a/readline/readline.c
+++ /dev/null
@@ -1,2155 +0,0 @@
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include "posixstat.h"
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* HAVE_SYS_FILE_H */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <signal.h>
-#include <stdio.h>
-#include "posixjmp.h"
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-#if defined (__EMX__)
-# define INCL_DOSPROCESS
-# include <os2.h>
-#endif /* __EMX__ */
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#ifndef RL_LIBRARY_VERSION
-# define RL_LIBRARY_VERSION "4.0"
-#endif
-
-/* Evaluates its arguments multiple times. */
-#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
-
-/* NOTE: Functions and variables prefixed with `_rl_' are
- pseudo-global: they are global so they can be shared
- between files in the readline library, but are not intended
- to be visible to readline callers. */
-
-/* Variables and functions imported from terminal.c */
-extern int _rl_init_terminal_io ();
-extern void _rl_enable_meta_key ();
-#ifdef _MINIX
-extern void _rl_output_character_function ();
-#else
-extern int _rl_output_character_function ();
-#endif
-
-extern int _rl_enable_meta;
-extern int _rl_term_autowrap;
-extern int screenwidth, screenheight, screenchars;
-
-/* Variables and functions imported from rltty.c. */
-extern void rl_prep_terminal (), rl_deprep_terminal ();
-extern void rltty_set_default_bindings ();
-
-/* Functions imported from util.c. */
-extern void _rl_abort_internal ();
-extern void rl_extend_line_buffer ();
-extern int alphabetic ();
-
-/* Functions imported from bind.c. */
-extern void _rl_bind_if_unbound ();
-
-/* Functions imported from input.c. */
-extern int _rl_any_typein ();
-extern void _rl_insert_typein ();
-extern int rl_read_key ();
-
-/* Functions imported from nls.c */
-extern int _rl_init_eightbit ();
-
-/* Functions imported from shell.c */
-extern char *get_env_value ();
-
-/* External redisplay functions and variables from display.c */
-extern void _rl_move_vert ();
-extern void _rl_update_final ();
-extern void _rl_clear_to_eol ();
-extern void _rl_clear_screen ();
-extern void _rl_erase_entire_line ();
-
-extern void _rl_erase_at_end_of_line ();
-extern void _rl_move_cursor_relative ();
-
-extern int _rl_vis_botlin;
-extern int _rl_last_c_pos;
-extern int _rl_horizontal_scroll_mode;
-extern int rl_display_fixed;
-extern int _rl_suppress_redisplay;
-extern char *rl_display_prompt;
-
-/* Variables imported from complete.c. */
-extern const char *rl_completer_word_break_characters;
-extern const char *rl_basic_word_break_characters;
-extern int rl_completion_query_items;
-extern int rl_complete_with_tilde_expansion;
-
-/* Variables and functions from macro.c. */
-extern void _rl_add_macro_char ();
-extern void _rl_with_macro_input ();
-extern int _rl_next_macro_key ();
-extern int _rl_defining_kbd_macro;
-
-#if defined (VI_MODE)
-/* Functions imported from vi_mode.c. */
-extern void _rl_vi_set_last ();
-extern void _rl_vi_reset_last ();
-extern void _rl_vi_done_inserting ();
-extern int _rl_vi_textmod_command ();
-extern void _rl_vi_initialize_line ();
-#endif /* VI_MODE */
-
-extern UNDO_LIST *rl_undo_list;
-extern int _rl_doing_an_undo;
-
-/* Forward declarations used in this file. */
-void _rl_free_history_entry ();
-
-int _rl_dispatch ();
-int _rl_init_argument ();
-
-static char *readline_internal ();
-static void readline_initialize_everything ();
-static void start_using_history ();
-static void bind_arrow_keys ();
-
-#if !defined (__GO32__)
-static void readline_default_bindings ();
-#endif /* !__GO32__ */
-
-#if defined (__GO32__)
-# include <go32.h>
-# include <pc.h>
-# undef HANDLE_SIGNALS
-#endif /* __GO32__ */
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Line editing input utility */
-/* */
-/* **************************************************************** */
-
-const char *rl_library_version = RL_LIBRARY_VERSION;
-
-/* A pointer to the keymap that is currently in use.
- By default, it is the standard emacs keymap. */
-Keymap _rl_keymap = emacs_standard_keymap;
-
-/* The current style of editing. */
-int rl_editing_mode = emacs_mode;
-
-/* Non-zero if we called this function from _rl_dispatch(). It's present
- so functions can find out whether they were called from a key binding
- or directly from an application. */
-int rl_dispatching;
-
-/* Non-zero if the previous command was a kill command. */
-int _rl_last_command_was_kill = 0;
-
-/* The current value of the numeric argument specified by the user. */
-int rl_numeric_arg = 1;
-
-/* Non-zero if an argument was typed. */
-int rl_explicit_arg = 0;
-
-/* Temporary value used while generating the argument. */
-int rl_arg_sign = 1;
-
-/* Non-zero means we have been called at least once before. */
-static int rl_initialized;
-
-/* If non-zero, this program is running in an EMACS buffer. */
-static int running_in_emacs;
-
-/* The current offset in the current input line. */
-int rl_point;
-
-/* Mark in the current input line. */
-int rl_mark;
-
-/* Length of the current input line. */
-int rl_end;
-
-/* Make this non-zero to return the current input_line. */
-int rl_done;
-
-/* The last function executed by readline. */
-Function *rl_last_func = (Function *)NULL;
-
-/* Top level environment for readline_internal (). */
-procenv_t readline_top_level;
-
-/* The streams we interact with. */
-FILE *_rl_in_stream, *_rl_out_stream;
-
-/* The names of the streams that we do input and output to. */
-FILE *rl_instream = (FILE *)NULL;
-FILE *rl_outstream = (FILE *)NULL;
-
-/* Non-zero means echo characters as they are read. */
-int readline_echoing_p = 1;
-
-/* Current prompt. */
-char *rl_prompt;
-int rl_visible_prompt_length = 0;
-
-/* The number of characters read in order to type this complete command. */
-int rl_key_sequence_length = 0;
-
-/* If non-zero, then this is the address of a function to call just
- before readline_internal_setup () prints the first prompt. */
-Function *rl_startup_hook = (Function *)NULL;
-
-/* If non-zero, this is the address of a function to call just before
- readline_internal_setup () returns and readline_internal starts
- reading input characters. */
-Function *rl_pre_input_hook = (Function *)NULL;
-
-/* What we use internally. You should always refer to RL_LINE_BUFFER. */
-static char *the_line;
-
-/* The character that can generate an EOF. Really read from
- the terminal driver... just defaulted here. */
-int _rl_eof_char = CTRL ('D');
-
-/* Non-zero makes this the next keystroke to read. */
-int rl_pending_input = 0;
-
-/* Pointer to a useful terminal name. */
-char *rl_terminal_name = (char *)NULL;
-
-/* Non-zero means to always use horizontal scrolling in line display. */
-int _rl_horizontal_scroll_mode = 0;
-
-/* Non-zero means to display an asterisk at the starts of history lines
- which have been modified. */
-int _rl_mark_modified_lines = 0;
-
-/* The style of `bell' notification preferred. This can be set to NO_BELL,
- AUDIBLE_BELL, or VISIBLE_BELL. */
-int _rl_bell_preference = AUDIBLE_BELL;
-
-/* String inserted into the line by rl_insert_comment (). */
-char *_rl_comment_begin;
-
-/* Keymap holding the function currently being executed. */
-Keymap rl_executing_keymap;
-
-/* Non-zero means to erase entire line, including prompt, on empty input lines. */
-int rl_erase_empty_line = 0;
-
-/* Line buffer and maintenence. */
-char *rl_line_buffer = (char *)NULL;
-int rl_line_buffer_len = 0;
-
-/* Forward declarations used by the display and termcap code. */
-
-/* **************************************************************** */
-/* */
-/* `Forward' declarations */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means do not parse any lines other than comments and
- parser directives. */
-unsigned char _rl_parsing_conditionalized_out = 0;
-
-/* Non-zero means to convert characters with the meta bit set to
- escape-prefixed characters so we can indirect through
- emacs_meta_keymap or vi_escape_keymap. */
-int _rl_convert_meta_chars_to_ascii = 1;
-
-/* Non-zero means to output characters with the meta bit set directly
- rather than as a meta-prefixed escape sequence. */
-int _rl_output_meta_chars = 0;
-
-/* **************************************************************** */
-/* */
-/* Top Level Functions */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
-int _rl_meta_flag = 0; /* Forward declaration */
-
-/* Read a line of input. Prompt with PROMPT. An empty PROMPT means
- none. A return value of NULL means that EOF was encountered. */
-char *
-readline (prompt)
- char *prompt;
-{
- char *value;
-
- rl_prompt = prompt;
-
- /* If we are at EOF return a NULL string. */
- if (rl_pending_input == EOF)
- {
- rl_pending_input = 0;
- return ((char *)NULL);
- }
-
- rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
-
- rl_initialize ();
- (*rl_prep_term_function) (_rl_meta_flag);
-
-#if defined (HANDLE_SIGNALS)
- rl_set_signals ();
-#endif
-
- value = readline_internal ();
- (*rl_deprep_term_function) ();
-
-#if defined (HANDLE_SIGNALS)
- rl_clear_signals ();
-#endif
-
- return (value);
-}
-
-#if defined (READLINE_CALLBACKS)
-# define STATIC_CALLBACK
-#else
-# define STATIC_CALLBACK static
-#endif
-
-STATIC_CALLBACK void
-readline_internal_setup ()
-{
- _rl_in_stream = rl_instream;
- _rl_out_stream = rl_outstream;
-
- if (rl_startup_hook)
- (*rl_startup_hook) ();
-
- if (readline_echoing_p == 0)
- {
- if (rl_prompt)
- {
- fprintf (_rl_out_stream, "%s", rl_prompt);
- fflush (_rl_out_stream);
- }
- }
- else
- {
- rl_on_new_line ();
- (*rl_redisplay_function) ();
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_vi_insertion_mode (1, 0);
-#endif /* VI_MODE */
- }
-
- if (rl_pre_input_hook)
- (*rl_pre_input_hook) ();
-}
-
-STATIC_CALLBACK char *
-readline_internal_teardown (eof)
- int eof;
-{
- char *temp;
- HIST_ENTRY *entry;
-
- /* Restore the original of this history line, iff the line that we
- are editing was originally in the history, AND the line has changed. */
- entry = current_history ();
-
- if (entry && rl_undo_list)
- {
- temp = savestring (the_line);
- rl_revert_line (1, 0);
- entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
- _rl_free_history_entry (entry);
-
- strcpy (the_line, temp);
- free (temp);
- }
-
- /* At any rate, it is highly likely that this line has an undo list. Get
- rid of it now. */
- if (rl_undo_list)
- free_undo_list ();
-
- return (eof ? (char *)NULL : savestring (the_line));
-}
-
-STATIC_CALLBACK int
-#if defined (READLINE_CALLBACKS)
-readline_internal_char ()
-#else
-readline_internal_charloop ()
-#endif
-{
- static int lastc, eof_found;
- int c, code, lk;
-
- lastc = -1;
- eof_found = 0;
-
-#if !defined (READLINE_CALLBACKS)
- while (rl_done == 0)
- {
-#endif
- lk = _rl_last_command_was_kill;
-
- code = setjmp (readline_top_level);
-
- if (code)
- (*rl_redisplay_function) ();
-
- if (rl_pending_input == 0)
- {
- /* Then initialize the argument and number of keys read. */
- _rl_init_argument ();
- rl_key_sequence_length = 0;
- }
-
- c = rl_read_key ();
-
- /* EOF typed to a non-blank line is a <NL>. */
- if (c == EOF && rl_end)
- c = NEWLINE;
-
- /* The character _rl_eof_char typed to blank line, and not as the
- previous character is interpreted as EOF. */
- if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
- {
-#if defined (READLINE_CALLBACKS)
- return (rl_done = 1);
-#else
- eof_found = 1;
- break;
-#endif
- }
-
- lastc = c;
- _rl_dispatch (c, _rl_keymap);
-
- /* If there was no change in _rl_last_command_was_kill, then no kill
- has taken place. Note that if input is pending we are reading
- a prefix command, so nothing has changed yet. */
- if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
- _rl_last_command_was_kill = 0;
-
-#if defined (VI_MODE)
- /* In vi mode, when you exit insert mode, the cursor moves back
- over the previous character. We explicitly check for that here. */
- if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
- rl_vi_check ();
-#endif /* VI_MODE */
-
- if (rl_done == 0)
- (*rl_redisplay_function) ();
-
- /* If the application writer has told us to erase the entire line if
- the only character typed was something bound to rl_newline, do so. */
- if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline &&
- rl_point == 0 && rl_end == 0)
- _rl_erase_entire_line ();
-
-#if defined (READLINE_CALLBACKS)
- return 0;
-#else
- }
-
- return (eof_found);
-#endif
-}
-
-#if defined (READLINE_CALLBACKS)
-static int
-readline_internal_charloop ()
-{
- int eof = 1;
-
- while (rl_done == 0)
- eof = readline_internal_char ();
- return (eof);
-}
-#endif /* READLINE_CALLBACKS */
-
-/* Read a line of input from the global rl_instream, doing output on
- the global rl_outstream.
- If rl_prompt is non-null, then that is our prompt. */
-static char *
-readline_internal ()
-{
- int eof;
-
- readline_internal_setup ();
- eof = readline_internal_charloop ();
- return (readline_internal_teardown (eof));
-}
-
-void
-_rl_init_line_state ()
-{
- rl_point = rl_end = 0;
- the_line = rl_line_buffer;
- the_line[0] = 0;
-}
-
-void
-_rl_set_the_line ()
-{
- the_line = rl_line_buffer;
-}
-
-/* Do the command associated with KEY in MAP.
- If the associated command is really a keymap, then read
- another key, and dispatch into that map. */
-int
-_rl_dispatch (key, map)
- register int key;
- Keymap map;
-{
- int r, newkey;
- char *macro;
- Function *func;
-
- if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
- {
- if (map[ESC].type == ISKMAP)
- {
- if (_rl_defining_kbd_macro)
- _rl_add_macro_char (ESC);
- map = FUNCTION_TO_KEYMAP (map, ESC);
- key = UNMETA (key);
- rl_key_sequence_length += 2;
- return (_rl_dispatch (key, map));
- }
- else
- ding ();
- return 0;
- }
-
- if (_rl_defining_kbd_macro)
- _rl_add_macro_char (key);
-
- r = 0;
- switch (map[key].type)
- {
- case ISFUNC:
- func = map[key].function;
- if (func != (Function *)NULL)
- {
- /* Special case rl_do_lowercase_version (). */
- if (func == rl_do_lowercase_version)
- return (_rl_dispatch (_rl_to_lower (key), map));
-
- rl_executing_keymap = map;
-
-#if 0
- _rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available ();
-#endif
-
- rl_dispatching = 1;
- r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
- rl_dispatching = 0;
-
- /* If we have input pending, then the last command was a prefix
- command. Don't change the state of rl_last_func. Otherwise,
- remember the last command executed in this variable. */
- if (!rl_pending_input && map[key].function != rl_digit_argument)
- rl_last_func = map[key].function;
- }
- else
- {
- _rl_abort_internal ();
- return -1;
- }
- break;
-
- case ISKMAP:
- if (map[key].function != (Function *)NULL)
- {
- rl_key_sequence_length++;
- newkey = rl_read_key ();
- r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
- }
- else
- {
- _rl_abort_internal ();
- return -1;
- }
- break;
-
- case ISMACR:
- if (map[key].function != (Function *)NULL)
- {
- macro = savestring ((char *)map[key].function);
- _rl_with_macro_input (macro);
- return 0;
- }
- break;
- }
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
- _rl_vi_textmod_command (key))
- _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
-#endif
- return (r);
-}
-
-/* **************************************************************** */
-/* */
-/* Initializations */
-/* */
-/* **************************************************************** */
-
-/* Initialize readline (and terminal if not already). */
-int
-rl_initialize ()
-{
- /* If we have never been called before, initialize the
- terminal and data structures. */
- if (!rl_initialized)
- {
- readline_initialize_everything ();
- rl_initialized++;
- }
-
- /* Initalize the current line information. */
- _rl_init_line_state ();
-
- /* We aren't done yet. We haven't even gotten started yet! */
- rl_done = 0;
-
- /* Tell the history routines what is going on. */
- start_using_history ();
-
- /* Make the display buffer match the state of the line. */
- rl_reset_line_state ();
-
- /* No such function typed yet. */
- rl_last_func = (Function *)NULL;
-
- /* Parsing of key-bindings begins in an enabled state. */
- _rl_parsing_conditionalized_out = 0;
-
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- _rl_vi_initialize_line ();
-#endif
-
- return 0;
-}
-
-#if defined (__EMX__)
-static void
-_emx_build_environ ()
-{
- TIB *tibp;
- PIB *pibp;
- char *t, **tp;
- int c;
-
- DosGetInfoBlocks (&tibp, &pibp);
- t = pibp->pib_pchenv;
- for (c = 1; *t; c++)
- t += strlen (t) + 1;
- tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *));
- t = pibp->pib_pchenv;
- while (*t)
- {
- *tp++ = t;
- t += strlen (t) + 1;
- }
- *tp = 0;
-}
-#endif /* __EMX__ */
-
-/* Initialize the entire state of the world. */
-static void
-readline_initialize_everything ()
-{
-#if defined (__EMX__)
- if (environ == 0)
- _emx_build_environ ();
-#endif
-
- /* Find out if we are running in Emacs. */
- running_in_emacs = get_env_value ("EMACS") != (char *)0;
-
- /* Set up input and output if they are not already set up. */
- if (!rl_instream)
- rl_instream = stdin;
-
- if (!rl_outstream)
- rl_outstream = stdout;
-
- /* Bind _rl_in_stream and _rl_out_stream immediately. These values
- may change, but they may also be used before readline_internal ()
- is called. */
- _rl_in_stream = rl_instream;
- _rl_out_stream = rl_outstream;
-
- /* Allocate data structures. */
- if (rl_line_buffer == 0)
- rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
-
- /* Initialize the terminal interface. */
- _rl_init_terminal_io ((char *)NULL);
-
-#if !defined (__GO32__)
- /* Bind tty characters to readline functions. */
- readline_default_bindings ();
-#endif /* !__GO32__ */
-
- /* Initialize the function names. */
- rl_initialize_funmap ();
-
- /* Decide whether we should automatically go into eight-bit mode. */
- _rl_init_eightbit ();
-
- /* Read in the init file. */
- rl_read_init_file ((char *)NULL);
-
- /* XXX */
- if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
- {
- screenwidth--;
- screenchars -= screenheight;
- }
-
- /* Override the effect of any `set keymap' assignments in the
- inputrc file. */
- rl_set_keymap_from_edit_mode ();
-
- /* Try to bind a common arrow key prefix, if not already bound. */
- bind_arrow_keys ();
-
- /* Enable the meta key, if this terminal has one. */
- if (_rl_enable_meta)
- _rl_enable_meta_key ();
-
- /* If the completion parser's default word break characters haven't
- been set yet, then do so now. */
- if (rl_completer_word_break_characters == (char *)NULL)
- rl_completer_word_break_characters = rl_basic_word_break_characters;
-}
-
-/* If this system allows us to look at the values of the regular
- input editing characters, then bind them to their readline
- equivalents, iff the characters are not bound to keymaps. */
-static void
-readline_default_bindings ()
-{
- rltty_set_default_bindings (_rl_keymap);
-}
-
-static void
-bind_arrow_keys_internal ()
-{
- Function *f;
-
- f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL);
- if (!f || f == rl_do_lowercase_version)
- {
- _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
- _rl_bind_if_unbound ("\033[B", rl_get_next_history);
- _rl_bind_if_unbound ("\033[C", rl_forward);
- _rl_bind_if_unbound ("\033[D", rl_backward);
- }
-
- f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL);
- if (!f || f == rl_do_lowercase_version)
- {
- _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
- _rl_bind_if_unbound ("\033OB", rl_get_next_history);
- _rl_bind_if_unbound ("\033OC", rl_forward);
- _rl_bind_if_unbound ("\033OD", rl_backward);
- }
-}
-
-/* Try and bind the common arrow key prefix after giving termcap and
- the inputrc file a chance to bind them and create `real' keymaps
- for the arrow key prefix. */
-static void
-bind_arrow_keys ()
-{
- Keymap xkeymap;
-
- xkeymap = _rl_keymap;
-
- _rl_keymap = emacs_standard_keymap;
- bind_arrow_keys_internal ();
-
-#if defined (VI_MODE)
- _rl_keymap = vi_movement_keymap;
- bind_arrow_keys_internal ();
-#endif
-
- _rl_keymap = xkeymap;
-}
-
-
-/* **************************************************************** */
-/* */
-/* Numeric Arguments */
-/* */
-/* **************************************************************** */
-
-/* Handle C-u style numeric args, as well as M--, and M-digits. */
-static int
-rl_digit_loop ()
-{
- int key, c, sawminus, sawdigits;
-
- rl_save_prompt ();
-
- sawminus = sawdigits = 0;
- while (1)
- {
- if (rl_numeric_arg > 1000000)
- {
- sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
- ding ();
- rl_restore_prompt ();
- rl_clear_message ();
- return 1;
- }
- rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
- key = c = rl_read_key ();
-
- /* If we see a key bound to `universal-argument' after seeing digits,
- it ends the argument but is otherwise ignored. */
- if (_rl_keymap[c].type == ISFUNC &&
- _rl_keymap[c].function == rl_universal_argument)
- {
- if (sawdigits == 0)
- {
- rl_numeric_arg *= 4;
- continue;
- }
- else
- {
- key = rl_read_key ();
- rl_restore_prompt ();
- rl_clear_message ();
- return (_rl_dispatch (key, _rl_keymap));
- }
- }
-
- c = UNMETA (c);
-
- if (_rl_digit_p (c))
- {
- rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
- sawdigits = rl_explicit_arg = 1;
- }
- else if (c == '-' && rl_explicit_arg == 0)
- {
- rl_numeric_arg = sawminus = 1;
- rl_arg_sign = -1;
- }
- else
- {
- /* Make M-- command equivalent to M--1 command. */
- if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
- rl_explicit_arg = 1;
- rl_restore_prompt ();
- rl_clear_message ();
- return (_rl_dispatch (key, _rl_keymap));
- }
- }
-
- return 0;
-}
-
-/* Add the current digit to the argument in progress. */
-int
-rl_digit_argument (ignore, key)
- int ignore __attribute__((unused)), key;
-{
- rl_pending_input = key;
- return (rl_digit_loop ());
-}
-
-/* What to do when you abort reading an argument. */
-int
-rl_discard_argument ()
-{
- ding ();
- rl_clear_message ();
- _rl_init_argument ();
- return 0;
-}
-
-/* Create a default argument. */
-int
-_rl_init_argument ()
-{
- rl_numeric_arg = rl_arg_sign = 1;
- rl_explicit_arg = 0;
- return 0;
-}
-
-/* C-u, universal argument. Multiply the current argument by 4.
- Read a key. If the key has nothing to do with arguments, then
- dispatch on it. If the key is the abort character then abort. */
-int
-rl_universal_argument (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- rl_numeric_arg *= 4;
- return (rl_digit_loop ());
-}
-
-/* **************************************************************** */
-/* */
-/* Insert and Delete */
-/* */
-/* **************************************************************** */
-
-/* Insert a string of text into the line at point. This is the only
- way that you should do insertion. rl_insert () calls this
- function. */
-int
-rl_insert_text (const char *string)
-{
- register int i, l = strlen (string);
-
- if (rl_end + l >= rl_line_buffer_len)
- rl_extend_line_buffer (rl_end + l);
-
- for (i = rl_end; i >= rl_point; i--)
- the_line[i + l] = the_line[i];
- strncpy (the_line + rl_point, string, l);
-
- /* Remember how to undo this if we aren't undoing something. */
- if (!_rl_doing_an_undo)
- {
- /* If possible and desirable, concatenate the undos. */
- if ((l == 1) &&
- rl_undo_list &&
- (rl_undo_list->what == UNDO_INSERT) &&
- (rl_undo_list->end == rl_point) &&
- (rl_undo_list->end - rl_undo_list->start < 20))
- rl_undo_list->end++;
- else
- rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
- }
- rl_point += l;
- rl_end += l;
- the_line[rl_end] = '\0';
- return l;
-}
-
-/* Delete the string between FROM and TO. FROM is
- inclusive, TO is not. */
-int
-rl_delete_text (from, to)
- int from, to;
-{
- register char *text;
- register int diff, i;
-
- /* Fix it if the caller is confused. */
- if (from > to)
- SWAP (from, to);
-
- /* fix boundaries */
- if (to > rl_end)
- {
- to = rl_end;
- if (from > to)
- from = to;
- }
-
- text = rl_copy_text (from, to);
-
- /* Some versions of strncpy() can't handle overlapping arguments. */
- diff = to - from;
- for (i = from; i < rl_end - diff; i++)
- the_line[i] = the_line[i + diff];
-
- /* Remember how to undo this delete. */
- if (_rl_doing_an_undo == 0)
- rl_add_undo (UNDO_DELETE, from, to, text);
- else
- free (text);
-
- rl_end -= diff;
- the_line[rl_end] = '\0';
- return (diff);
-}
-
-/* Fix up point so that it is within the line boundaries after killing
- text. If FIX_MARK_TOO is non-zero, the mark is forced within line
- boundaries also. */
-
-#define _RL_FIX_POINT(x) \
- do { \
- if (x > rl_end) \
- x = rl_end; \
- else if (x < 0) \
- x = 0; \
- } while (0)
-
-void
-_rl_fix_point (fix_mark_too)
- int fix_mark_too;
-{
- _RL_FIX_POINT (rl_point);
- if (fix_mark_too)
- _RL_FIX_POINT (rl_mark);
-}
-#undef _RL_FIX_POINT
-
-void
-_rl_replace_text (text, start, end)
- char *text;
- int start, end;
-{
- rl_begin_undo_group ();
- rl_delete_text (start, end + 1);
- rl_point = start;
- rl_insert_text (text);
- rl_end_undo_group ();
-}
-
-/* **************************************************************** */
-/* */
-/* Readline character functions */
-/* */
-/* **************************************************************** */
-
-/* This is not a gap editor, just a stupid line input routine. No hair
- is involved in writing any of the functions, and none should be. */
-
-/* Note that:
-
- rl_end is the place in the string that we would place '\0';
- i.e., it is always safe to place '\0' there.
-
- rl_point is the place in the string where the cursor is. Sometimes
- this is the same as rl_end.
-
- Any command that is called interactively receives two arguments.
- The first is a count: the numeric arg pased to this command.
- The second is the key which invoked this command.
-*/
-
-/* **************************************************************** */
-/* */
-/* Movement Commands */
-/* */
-/* **************************************************************** */
-
-/* Note that if you `optimize' the display for these functions, you cannot
- use said functions in other functions which do not do optimizing display.
- I.e., you will have to update the data base for rl_redisplay, and you
- might as well let rl_redisplay do that job. */
-
-/* Move forward COUNT characters. */
-int
-rl_forward (count, key)
- int count, key;
-{
- if (count < 0)
- rl_backward (-count, key);
- else if (count > 0)
- {
- int end = rl_point + count;
-#if defined (VI_MODE)
- int lend = rl_end - (rl_editing_mode == vi_mode);
-#else
- int lend = rl_end;
-#endif
-
- if (end > lend)
- {
- rl_point = lend;
- ding ();
- }
- else
- rl_point = end;
- }
- return 0;
-}
-
-/* Move backward COUNT characters. */
-int
-rl_backward (count, key)
- int count, key;
-{
- if (count < 0)
- rl_forward (-count, key);
- else if (count > 0)
- {
- if (rl_point < count)
- {
- rl_point = 0;
- ding ();
- }
- else
- rl_point -= count;
- }
- return 0;
-}
-
-/* Move to the beginning of the line. */
-int
-rl_beg_of_line (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- rl_point = 0;
- return 0;
-}
-
-/* Move to the end of the line. */
-int
-rl_end_of_line (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- rl_point = rl_end;
- return 0;
-}
-
-/* Move forward a word. We do what Emacs does. */
-int
-rl_forward_word (count, key)
- int count, key;
-{
- int c;
-
- if (count < 0)
- {
- rl_backward_word (-count, key);
- return 0;
- }
-
- while (count)
- {
- if (rl_point == rl_end)
- return 0;
-
- /* If we are not in a word, move forward until we are in one.
- Then, move forward until we hit a non-alphabetic character. */
- c = the_line[rl_point];
- if (alphabetic (c) == 0)
- {
- while (++rl_point < rl_end)
- {
- c = the_line[rl_point];
- if (alphabetic (c))
- break;
- }
- }
- if (rl_point == rl_end)
- return 0;
- while (++rl_point < rl_end)
- {
- c = the_line[rl_point];
- if (alphabetic (c) == 0)
- break;
- }
- --count;
- }
- return 0;
-}
-
-/* Move backward a word. We do what Emacs does. */
-int
-rl_backward_word (count, key)
- int count, key;
-{
- int c;
-
- if (count < 0)
- {
- rl_forward_word (-count, key);
- return 0;
- }
-
- while (count)
- {
- if (!rl_point)
- return 0;
-
- /* Like rl_forward_word (), except that we look at the characters
- just before point. */
-
- c = the_line[rl_point - 1];
- if (alphabetic (c) == 0)
- {
- while (--rl_point)
- {
- c = the_line[rl_point - 1];
- if (alphabetic (c))
- break;
- }
- }
-
- while (rl_point)
- {
- c = the_line[rl_point - 1];
- if (alphabetic (c) == 0)
- break;
- else
- --rl_point;
- }
- --count;
- }
- return 0;
-}
-
-/* Clear the current line. Numeric argument to C-l does this. */
-int
-rl_refresh_line (ignore1, ignore2)
- int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
-{
- int curr_line, nleft;
-
- /* Find out whether or not there might be invisible characters in the
- editing buffer. */
- if (rl_display_prompt == rl_prompt)
- nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
- else
- nleft = _rl_last_c_pos - screenwidth;
-
- if (nleft > 0)
- curr_line = 1 + nleft / screenwidth;
- else
- curr_line = 0;
-
- _rl_move_vert (curr_line);
- _rl_move_cursor_relative (0, the_line); /* XXX is this right */
-
-#if defined (__GO32__)
- {
- int row, col, width, row_start;
-
- ScreenGetCursor (&row, &col);
- width = ScreenCols ();
- row_start = ScreenPrimary + (row * width);
- memset (row_start + col, 0, (width - col) * 2);
- }
-#else /* !__GO32__ */
- _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
-#endif /* !__GO32__ */
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return 0;
-}
-
-/* C-l typed to a line without quoting clears the screen, and then reprints
- the prompt and the current input line. Given a numeric arg, redraw only
- the current line. */
-int
-rl_clear_screen (count, key)
- int count, key;
-{
- if (rl_explicit_arg)
- {
- rl_refresh_line (count, key);
- return 0;
- }
-
- _rl_clear_screen (); /* calls termcap function to clear screen */
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return 0;
-}
-
-int
-rl_arrow_keys (count, c)
- int count, c __attribute__((unused));
-{
- int ch;
-
- ch = rl_read_key ();
-
- switch (_rl_to_upper (ch))
- {
- case 'A':
- rl_get_previous_history (count, ch);
- break;
-
- case 'B':
- rl_get_next_history (count, ch);
- break;
-
- case 'C':
- rl_forward (count, ch);
- break;
-
- case 'D':
- rl_backward (count, ch);
- break;
-
- default:
- ding ();
- }
- return 0;
-}
-
-
-/* **************************************************************** */
-/* */
-/* Text commands */
-/* */
-/* **************************************************************** */
-
-/* Insert the character C at the current location, moving point forward. */
-int
-rl_insert (count, c)
- int count, c;
-{
- register int i;
- char *string;
-
- if (count <= 0)
- return 0;
-
- /* If we can optimize, then do it. But don't let people crash
- readline because of extra large arguments. */
- if (count > 1 && count <= 1024)
- {
- string = xmalloc (1 + count);
-
- for (i = 0; i < count; i++)
- string[i] = c;
-
- string[i] = '\0';
- rl_insert_text (string);
- free (string);
-
- return 0;
- }
-
- if (count > 1024)
- {
- int decreaser;
- char str[1024+1];
-
- for (i = 0; i < 1024; i++)
- str[i] = c;
-
- while (count)
- {
- decreaser = (count > 1024 ? 1024 : count);
- str[decreaser] = '\0';
- rl_insert_text (str);
- count -= decreaser;
- }
-
- return 0;
- }
-
- /* We are inserting a single character.
- If there is pending input, then make a string of all of the
- pending characters that are bound to rl_insert, and insert
- them all. */
- if (_rl_any_typein ())
- _rl_insert_typein (c);
- else
- {
- /* Inserting a single character. */
- char str[2];
-
- str[1] = '\0';
- str[0] = c;
- rl_insert_text (str);
- }
- return 0;
-}
-
-/* Insert the next typed character verbatim. */
-int
-rl_quoted_insert (count, key)
- int count, key __attribute__((unused));
-{
- int c;
-
- c = rl_read_key ();
- return (rl_insert (count, c));
-}
-
-/* Insert a tab character. */
-int
-rl_tab_insert (count, key)
- int count, key __attribute__((unused));
-{
- return (rl_insert (count, '\t'));
-}
-
-/* What to do when a NEWLINE is pressed. We accept the whole line.
- KEY is the key that invoked this command. I guess it could have
- meaning in the future. */
-int
-rl_newline (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- rl_done = 1;
-
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- {
- _rl_vi_done_inserting ();
- _rl_vi_reset_last ();
- }
-#endif /* VI_MODE */
-
- /* If we've been asked to erase empty lines, suppress the final update,
- since _rl_update_final calls crlf(). */
- if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
- return 0;
-
- if (readline_echoing_p)
- _rl_update_final ();
- return 0;
-}
-
-/* What to do for some uppercase characters, like meta characters,
- and some characters appearing in emacs_ctlx_keymap. This function
- is just a stub, you bind keys to it and the code in _rl_dispatch ()
- is special cased. */
-int
-rl_do_lowercase_version (ignore1, ignore2)
- int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
-{
- return 0;
-}
-
-/* Rubout the character behind point. */
-int
-rl_rubout (count, key)
- int count, key;
-{
- if (count < 0)
- {
- rl_delete (-count, key);
- return 0;
- }
-
- if (!rl_point)
- {
- ding ();
- return -1;
- }
-
- if (count > 1 || rl_explicit_arg)
- {
- int orig_point = rl_point;
- rl_backward (count, key);
- rl_kill_text (orig_point, rl_point);
- }
- else
- {
- int c = the_line[--rl_point];
- rl_delete_text (rl_point, rl_point + 1);
-
- if (rl_point == rl_end && isprint (c) && _rl_last_c_pos)
- {
- int l;
- l = rl_character_len (c, rl_point);
- _rl_erase_at_end_of_line (l);
- }
- }
- return 0;
-}
-
-/* Delete the character under the cursor. Given a numeric argument,
- kill that many characters instead. */
-int
-rl_delete (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_rubout (-count, key));
-
- if (rl_point == rl_end)
- {
- ding ();
- return -1;
- }
-
- if (count > 1 || rl_explicit_arg)
- {
- int orig_point = rl_point;
- rl_forward (count, key);
- rl_kill_text (orig_point, rl_point);
- rl_point = orig_point;
- return 0;
- }
- else
- return (rl_delete_text (rl_point, rl_point + 1));
-}
-
-/* Delete the character under the cursor, unless the insertion
- point is at the end of the line, in which case the character
- behind the cursor is deleted. COUNT is obeyed and may be used
- to delete forward or backward that many characters. */
-int
-rl_rubout_or_delete (count, key)
- int count, key;
-{
- if (rl_end != 0 && rl_point == rl_end)
- return (rl_rubout (count, key));
- else
- return (rl_delete (count, key));
-}
-
-/* Delete all spaces and tabs around point. */
-int
-rl_delete_horizontal_space (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
-{
- int start = rl_point;
-
- while (rl_point && whitespace (the_line[rl_point - 1]))
- rl_point--;
-
- start = rl_point;
-
- while (rl_point < rl_end && whitespace (the_line[rl_point]))
- rl_point++;
-
- if (start != rl_point)
- {
- rl_delete_text (start, rl_point);
- rl_point = start;
- }
- return 0;
-}
-
-/* Like the tcsh editing function delete-char-or-list. The eof character
- is caught before this is invoked, so this really does the same thing as
- delete-char-or-list-or-eof, as long as it's bound to the eof character. */
-int
-rl_delete_or_show_completions (count, key)
- int count, key;
-{
- if (rl_end != 0 && rl_point == rl_end)
- return (rl_possible_completions (count, key));
- else
- return (rl_delete (count, key));
-}
-
-#ifndef RL_COMMENT_BEGIN_DEFAULT
-#define RL_COMMENT_BEGIN_DEFAULT "#"
-#endif
-
-/* Turn the current line into a comment in shell history.
- A K*rn shell style function. */
-int
-rl_insert_comment (count, key)
- int count __attribute__((unused)), key;
-{
- rl_beg_of_line (1, key);
- rl_insert_text (_rl_comment_begin ? _rl_comment_begin
- : RL_COMMENT_BEGIN_DEFAULT);
- (*rl_redisplay_function) ();
- rl_newline (1, '\n');
- return (0);
-}
-
-/* **************************************************************** */
-/* */
-/* Changing Case */
-/* */
-/* **************************************************************** */
-
-/* The three kinds of things that we know how to do. */
-#define UpCase 1
-#define DownCase 2
-#define CapCase 3
-
-static int rl_change_case ();
-
-/* Uppercase the word at point. */
-int
-rl_upcase_word (count, key)
- int count, key __attribute__((unused));
-{
- return (rl_change_case (count, UpCase));
-}
-
-/* Lowercase the word at point. */
-int
-rl_downcase_word (count, key)
- int count, key __attribute__((unused));
-{
- return (rl_change_case (count, DownCase));
-}
-
-/* Upcase the first letter, downcase the rest. */
-int
-rl_capitalize_word (count, key)
- int count, key __attribute__((unused));
-{
- return (rl_change_case (count, CapCase));
-}
-
-/* The meaty function.
- Change the case of COUNT words, performing OP on them.
- OP is one of UpCase, DownCase, or CapCase.
- If a negative argument is given, leave point where it started,
- otherwise, leave it where it moves to. */
-static int
-rl_change_case (count, op)
- int count, op;
-{
- register int start, end;
- int inword, c;
-
- start = rl_point;
- rl_forward_word (count, 0);
- end = rl_point;
-
- if (count < 0)
- SWAP (start, end);
-
- /* We are going to modify some text, so let's prepare to undo it. */
- rl_modifying (start, end);
-
- for (inword = 0; start < end; start++)
- {
- c = the_line[start];
- switch (op)
- {
- case UpCase:
- the_line[start] = _rl_to_upper (c);
- break;
-
- case DownCase:
- the_line[start] = _rl_to_lower (c);
- break;
-
- case CapCase:
- the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
- inword = alphabetic (the_line[start]);
- break;
-
- default:
- ding ();
- return -1;
- }
- }
- rl_point = end;
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Transposition */
-/* */
-/* **************************************************************** */
-
-/* Transpose the words at point. */
-int
-rl_transpose_words (count, key)
- int count, key;
-{
- char *word1, *word2;
- int w1_beg, w1_end, w2_beg, w2_end;
- int orig_point = rl_point;
-
- if (!count)
- return 0;
-
- /* Find the two words. */
- rl_forward_word (count, key);
- w2_end = rl_point;
- rl_backward_word (1, key);
- w2_beg = rl_point;
- rl_backward_word (count, key);
- w1_beg = rl_point;
- rl_forward_word (1, key);
- w1_end = rl_point;
-
- /* Do some check to make sure that there really are two words. */
- if ((w1_beg == w2_beg) || (w2_beg < w1_end))
- {
- ding ();
- rl_point = orig_point;
- return -1;
- }
-
- /* Get the text of the words. */
- word1 = rl_copy_text (w1_beg, w1_end);
- word2 = rl_copy_text (w2_beg, w2_end);
-
- /* We are about to do many insertions and deletions. Remember them
- as one operation. */
- rl_begin_undo_group ();
-
- /* Do the stuff at word2 first, so that we don't have to worry
- about word1 moving. */
- rl_point = w2_beg;
- rl_delete_text (w2_beg, w2_end);
- rl_insert_text (word1);
-
- rl_point = w1_beg;
- rl_delete_text (w1_beg, w1_end);
- rl_insert_text (word2);
-
- /* This is exactly correct since the text before this point has not
- changed in length. */
- rl_point = w2_end;
-
- /* I think that does it. */
- rl_end_undo_group ();
- free (word1);
- free (word2);
-
- return 0;
-}
-
-/* Transpose the characters at point. If point is at the end of the line,
- then transpose the characters before point. */
-int
-rl_transpose_chars (count, key)
- int count, key __attribute__((unused));
-{
- char dummy[2];
-
- if (!count)
- return 0;
-
- if (!rl_point || rl_end < 2)
- {
- ding ();
- return -1;
- }
-
- rl_begin_undo_group ();
-
- if (rl_point == rl_end)
- {
- --rl_point;
- count = 1;
- }
- rl_point--;
-
- dummy[0] = the_line[rl_point];
- dummy[1] = '\0';
-
- rl_delete_text (rl_point, rl_point + 1);
-
- rl_point += count;
- _rl_fix_point (0);
- rl_insert_text (dummy);
-
- rl_end_undo_group ();
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Character Searching */
-/* */
-/* **************************************************************** */
-
-int
-_rl_char_search_internal (count, dir, schar)
- int count, dir, schar;
-{
- int pos, inc;
-
- pos = rl_point;
- inc = (dir < 0) ? -1 : 1;
- while (count)
- {
- if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
- {
- ding ();
- return -1;
- }
-
- pos += inc;
- do
- {
- if (rl_line_buffer[pos] == schar)
- {
- count--;
- if (dir < 0)
- rl_point = (dir == BTO) ? pos + 1 : pos;
- else
- rl_point = (dir == FTO) ? pos - 1 : pos;
- break;
- }
- }
- while ((dir < 0) ? pos-- : ++pos < rl_end);
- }
- return (0);
-}
-
-/* Search COUNT times for a character read from the current input stream.
- FDIR is the direction to search if COUNT is non-negative; otherwise
- the search goes in BDIR. */
-static int
-_rl_char_search (count, fdir, bdir)
- int count, fdir, bdir;
-{
- int c;
-
- c = rl_read_key ();
- if (count < 0)
- return (_rl_char_search_internal (-count, bdir, c));
- else
- return (_rl_char_search_internal (count, fdir, c));
-}
-
-int
-rl_char_search (count, key)
- int count, key __attribute__((unused));
-{
- return (_rl_char_search (count, FFIND, BFIND));
-}
-
-int
-rl_backward_char_search (count, key)
- int count, key __attribute__((unused));
-{
- return (_rl_char_search (count, BFIND, FFIND));
-}
-
-/* **************************************************************** */
-/* */
-/* History Utilities */
-/* */
-/* **************************************************************** */
-
-/* We already have a history library, and that is what we use to control
- the history features of readline. This is our local interface to
- the history mechanism. */
-
-/* While we are editing the history, this is the saved
- version of the original line. */
-HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
-
-/* Set the history pointer back to the last entry in the history. */
-static void
-start_using_history ()
-{
- using_history ();
- if (saved_line_for_history)
- _rl_free_history_entry (saved_line_for_history);
-
- saved_line_for_history = (HIST_ENTRY *)NULL;
-}
-
-/* Free the contents (and containing structure) of a HIST_ENTRY. */
-void
-_rl_free_history_entry (entry)
- HIST_ENTRY *entry;
-{
- if (entry == 0)
- return;
- if (entry->line)
- free (entry->line);
- free (entry);
-}
-
-/* Perhaps put back the current line if it has changed. */
-int
-maybe_replace_line ()
-{
- HIST_ENTRY *temp;
-
- temp = current_history ();
- /* If the current line has changed, save the changes. */
- if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
- {
- temp = replace_history_entry (where_history (), the_line, (histdata_t)rl_undo_list);
- free (temp->line);
- free (temp);
- }
- return 0;
-}
-
-/* Put back the saved_line_for_history if there is one. */
-int
-maybe_unsave_line ()
-{
- int line_len;
-
- if (saved_line_for_history)
- {
- line_len = strlen (saved_line_for_history->line);
-
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
-
- strcpy (the_line, saved_line_for_history->line);
- rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
- _rl_free_history_entry (saved_line_for_history);
- saved_line_for_history = (HIST_ENTRY *)NULL;
- rl_end = rl_point = strlen (the_line);
- }
- else
- ding ();
- return 0;
-}
-
-/* Save the current line in saved_line_for_history. */
-int
-maybe_save_line ()
-{
- if (saved_line_for_history == 0)
- {
- saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
- saved_line_for_history->line = savestring (the_line);
- saved_line_for_history->data = (char *)rl_undo_list;
- }
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* History Commands */
-/* */
-/* **************************************************************** */
-
-/* Meta-< goes to the start of the history. */
-int
-rl_beginning_of_history (count, key)
- int count __attribute__((unused)), key;
-{
- return (rl_get_previous_history (1 + where_history (), key));
-}
-
-/* Meta-> goes to the end of the history. (The current line). */
-int
-rl_end_of_history (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- maybe_replace_line ();
- using_history ();
- maybe_unsave_line ();
- return 0;
-}
-
-/* Move down to the next history line. */
-int
-rl_get_next_history (count, key)
- int count, key;
-{
- HIST_ENTRY *temp;
- int line_len;
-
- if (count < 0)
- return (rl_get_previous_history (-count, key));
-
- if (count == 0)
- return 0;
-
- maybe_replace_line ();
-
- temp = (HIST_ENTRY *)NULL;
- while (count)
- {
- temp = next_history ();
- if (!temp)
- break;
- --count;
- }
-
- if (temp == 0)
- maybe_unsave_line ();
- else
- {
- line_len = strlen (temp->line);
-
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
-
- strcpy (the_line, temp->line);
- rl_undo_list = (UNDO_LIST *)temp->data;
- rl_end = rl_point = strlen (the_line);
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_point = 0;
-#endif /* VI_MODE */
- }
- return 0;
-}
-
-/* Get the previous item out of our interactive history, making it the current
- line. If there is no previous history, just ding. */
-int
-rl_get_previous_history (count, key)
- int count, key;
-{
- HIST_ENTRY *old_temp, *temp;
- int line_len;
-
- if (count < 0)
- return (rl_get_next_history (-count, key));
-
- if (count == 0)
- return 0;
-
- /* If we don't have a line saved, then save this one. */
- maybe_save_line ();
-
- /* If the current line has changed, save the changes. */
- maybe_replace_line ();
-
- temp = old_temp = (HIST_ENTRY *)NULL;
- while (count)
- {
- temp = previous_history ();
- if (temp == 0)
- break;
-
- old_temp = temp;
- --count;
- }
-
- /* If there was a large argument, and we moved back to the start of the
- history, that is not an error. So use the last value found. */
- if (!temp && old_temp)
- temp = old_temp;
-
- if (temp == 0)
- ding ();
- else
- {
- line_len = strlen (temp->line);
-
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
-
- strcpy (the_line, temp->line);
- rl_undo_list = (UNDO_LIST *)temp->data;
- rl_end = rl_point = line_len;
-
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_point = 0;
-#endif /* VI_MODE */
- }
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* The Mark and the Region. */
-/* */
-/* **************************************************************** */
-
-/* Set the mark at POSITION. */
-int
-_rl_set_mark_at_pos (position)
- int position;
-{
- if (position > rl_end)
- return -1;
-
- rl_mark = position;
- return 0;
-}
-
-/* A bindable command to set the mark. */
-int
-rl_set_mark (count, key)
- int count, key __attribute__((unused));
-{
- return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
-}
-
-/* Exchange the position of mark and point. */
-int
-rl_exchange_point_and_mark (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- if (rl_mark > rl_end)
- rl_mark = -1;
-
- if (rl_mark == -1)
- {
- ding ();
- return -1;
- }
- else
- SWAP (rl_point, rl_mark);
-
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Editing Modes */
-/* */
-/* **************************************************************** */
-/* How to toggle back and forth between editing modes. */
-int
-rl_vi_editing_mode (count, key)
- int count __attribute__((unused)), key;
-{
-#if defined (VI_MODE)
- rl_editing_mode = vi_mode;
- rl_vi_insertion_mode (1, key);
-#endif /* VI_MODE */
- return 0;
-}
-
-int
-rl_emacs_editing_mode (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- rl_editing_mode = emacs_mode;
- _rl_keymap = emacs_standard_keymap;
- return 0;
-}
diff --git a/readline/readline.h b/readline/readline.h
deleted file mode 100644
index 7804d31efb1..00000000000
--- a/readline/readline.h
+++ /dev/null
@@ -1,621 +0,0 @@
-/* Readline.h -- the names of functions callable from within readline. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_READLINE_H_)
-#define _READLINE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined (READLINE_LIBRARY)
-# include "rlstdc.h"
-# include "keymaps.h"
-# include "tilde.h"
-#else
-# include <readline/rlstdc.h>
-# include <readline/keymaps.h>
-# include <readline/tilde.h>
-#endif
-
-/* Readline data structures. */
-
-/* Maintaining the state of undo. We remember individual deletes and inserts
- on a chain of things to do. */
-
-/* The actions that undo knows how to undo. Notice that UNDO_DELETE means
- to insert some text, and UNDO_INSERT means to delete some text. I.e.,
- the code tells undo what to undo, not how to undo it. */
-enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
-
-/* What an element of THE_UNDO_LIST looks like. */
-typedef struct undo_list {
- struct undo_list *next;
- int start, end; /* Where the change took place. */
- char *text; /* The text to insert, if undoing a delete. */
- enum undo_code what; /* Delete, Insert, Begin, End. */
-} UNDO_LIST;
-
-/* The current undo list for RL_LINE_BUFFER. */
-extern UNDO_LIST *rl_undo_list;
-
-/* The data structure for mapping textual names to code addresses. */
-typedef struct _funmap {
- const char *name;
- Function *function;
-} FUNMAP;
-
-extern FUNMAP **funmap;
-
-/* **************************************************************** */
-/* */
-/* Functions available to bind to key sequences */
-/* */
-/* **************************************************************** */
-
-/* Bindable commands for numeric arguments. */
-extern int rl_digit_argument __P((int, int));
-extern int rl_universal_argument __P((int, int));
-
-/* Bindable commands for moving the cursor. */
-extern int rl_forward __P((int, int));
-extern int rl_backward __P((int, int));
-extern int rl_beg_of_line __P((int, int));
-extern int rl_end_of_line __P((int, int));
-extern int rl_forward_word __P((int, int));
-extern int rl_backward_word __P((int, int));
-extern int rl_refresh_line __P((int, int));
-extern int rl_clear_screen __P((int, int));
-extern int rl_arrow_keys __P((int, int));
-
-/* Bindable commands for inserting and deleting text. */
-extern int rl_insert __P((int, int));
-extern int rl_quoted_insert __P((int, int));
-extern int rl_tab_insert __P((int, int));
-extern int rl_newline __P((int, int));
-extern int rl_do_lowercase_version __P((int, int));
-extern int rl_rubout __P((int, int));
-extern int rl_delete __P((int, int));
-extern int rl_rubout_or_delete __P((int, int));
-extern int rl_delete_horizontal_space __P((int, int));
-extern int rl_delete_or_show_completions __P((int, int));
-extern int rl_insert_comment __P((int, int));
-
-/* Bindable commands for changing case. */
-extern int rl_upcase_word __P((int, int));
-extern int rl_downcase_word __P((int, int));
-extern int rl_capitalize_word __P((int, int));
-
-/* Bindable commands for transposing characters and words. */
-extern int rl_transpose_words __P((int, int));
-extern int rl_transpose_chars __P((int, int));
-
-/* Bindable commands for searching within a line. */
-extern int rl_char_search __P((int, int));
-extern int rl_backward_char_search __P((int, int));
-
-/* Bindable commands for readline's interface to the command history. */
-extern int rl_beginning_of_history __P((int, int));
-extern int rl_end_of_history __P((int, int));
-extern int rl_get_next_history __P((int, int));
-extern int rl_get_previous_history __P((int, int));
-
-/* Bindable commands for managing the mark and region. */
-extern int rl_set_mark __P((int, int));
-extern int rl_exchange_point_and_mark __P((int, int));
-
-/* Bindable commands to set the editing mode (emacs or vi). */
-extern int rl_vi_editing_mode __P((int, int));
-extern int rl_emacs_editing_mode __P((int, int));
-
-/* Bindable commands for managing key bindings. */
-extern int rl_re_read_init_file __P((int, int));
-extern int rl_dump_functions __P((int, int));
-extern int rl_dump_macros __P((int, int));
-extern int rl_dump_variables __P((int, int));
-
-/* Bindable commands for word completion. */
-extern int rl_complete __P((int, int));
-extern int rl_possible_completions __P((int, int));
-extern int rl_insert_completions __P((int, int));
-extern int rl_menu_complete __P((int, int));
-
-/* Bindable commands for killing and yanking text, and managing the kill ring. */
-extern int rl_kill_word __P((int, int));
-extern int rl_backward_kill_word __P((int, int));
-extern int rl_kill_line __P((int, int));
-extern int rl_backward_kill_line __P((int, int));
-extern int rl_kill_full_line __P((int, int));
-extern int rl_unix_word_rubout __P((int, int));
-extern int rl_unix_line_discard __P((int, int));
-extern int rl_copy_region_to_kill __P((int, int));
-extern int rl_kill_region __P((int, int));
-extern int rl_copy_forward_word __P((int, int));
-extern int rl_copy_backward_word __P((int, int));
-extern int rl_yank __P((int, int));
-extern int rl_yank_pop __P((int, int));
-extern int rl_yank_nth_arg __P((int, int));
-extern int rl_yank_last_arg __P((int, int));
-/* Not available unless __CYGWIN32__ is defined. */
-#ifdef __CYGWIN32__
-extern int rl_paste_from_clipboard __P((int, int));
-#endif
-
-/* Bindable commands for incremental searching. */
-extern int rl_reverse_search_history __P((int, int));
-extern int rl_forward_search_history __P((int, int));
-
-/* Bindable keyboard macro commands. */
-extern int rl_start_kbd_macro __P((int, int));
-extern int rl_end_kbd_macro __P((int, int));
-extern int rl_call_last_kbd_macro __P((int, int));
-
-/* Bindable undo commands. */
-extern int rl_revert_line __P((int, int));
-extern int rl_undo_command __P((int, int));
-
-/* Bindable tilde expansion commands. */
-extern int rl_tilde_expand __P((int, int));
-
-/* Bindable terminal control commands. */
-extern int rl_restart_output __P((int, int));
-extern int rl_stop_output __P((int, int));
-
-/* Miscellaneous bindable commands. */
-extern int rl_abort __P((int, int));
-extern int rl_tty_status __P((int, int));
-
-/* Bindable commands for incremental and non-incremental history searching. */
-extern int rl_history_search_forward __P((int, int));
-extern int rl_history_search_backward __P((int, int));
-extern int rl_noninc_forward_search __P((int, int));
-extern int rl_noninc_reverse_search __P((int, int));
-extern int rl_noninc_forward_search_again __P((int, int));
-extern int rl_noninc_reverse_search_again __P((int, int));
-
-/* Not available unless readline is compiled -DPAREN_MATCHING. */
-extern int rl_insert_close __P((int, int));
-
-/* Not available unless READLINE_CALLBACKS is defined. */
-extern void rl_callback_handler_install __P((char *, VFunction *));
-extern void rl_callback_read_char __P((void));
-extern void rl_callback_handler_remove __P((void));
-
-/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
-/* VI-mode bindable commands. */
-extern int rl_vi_redo __P((int, int));
-extern int rl_vi_undo __P((int, int));
-extern int rl_vi_yank_arg __P((int, int));
-extern int rl_vi_fetch_history __P((int, int));
-extern int rl_vi_search_again __P((int, int));
-extern int rl_vi_search __P((int, int));
-extern int rl_vi_complete __P((int, int));
-extern int rl_vi_tilde_expand __P((int, int));
-extern int rl_vi_prev_word __P((int, int));
-extern int rl_vi_next_word __P((int, int));
-extern int rl_vi_end_word __P((int, int));
-extern int rl_vi_insert_beg __P((int, int));
-extern int rl_vi_append_mode __P((int, int));
-extern int rl_vi_append_eol __P((int, int));
-extern int rl_vi_eof_maybe __P((int, int));
-extern int rl_vi_insertion_mode __P((int, int));
-extern int rl_vi_movement_mode __P((int, int));
-extern int rl_vi_arg_digit __P((int, int));
-extern int rl_vi_change_case __P((int, int));
-extern int rl_vi_put __P((int, int));
-extern int rl_vi_column __P((int, int));
-extern int rl_vi_delete_to __P((int, int));
-extern int rl_vi_change_to __P((int, int));
-extern int rl_vi_yank_to __P((int, int));
-extern int rl_vi_delete __P((int, int));
-extern int rl_vi_back_to_indent __P((int, int));
-extern int rl_vi_first_print __P((int, int));
-extern int rl_vi_char_search __P((int, int));
-extern int rl_vi_match __P((int, int));
-extern int rl_vi_change_char __P((int, int));
-extern int rl_vi_subst __P((int, int));
-extern int rl_vi_overstrike __P((int, int));
-extern int rl_vi_overstrike_delete __P((int, int));
-extern int rl_vi_replace __P((int, int));
-extern int rl_vi_set_mark __P((int, int));
-extern int rl_vi_goto_mark __P((int, int));
-
-/* VI-mode utility functions. */
-extern int rl_vi_check __P((void));
-extern int rl_vi_domove __P((int, int *));
-extern int rl_vi_bracktype __P((int));
-
-/* VI-mode pseudo-bindable commands, used as utility functions. */
-extern int rl_vi_fWord __P((int, int));
-extern int rl_vi_bWord __P((int, int));
-extern int rl_vi_eWord __P((int, int));
-extern int rl_vi_fword __P((int, int));
-extern int rl_vi_bword __P((int, int));
-extern int rl_vi_eword __P((int, int));
-
-/* **************************************************************** */
-/* */
-/* Well Published Functions */
-/* */
-/* **************************************************************** */
-
-/* Readline functions. */
-/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */
-extern char *readline __P((char *));
-
-extern int rl_initialize __P((void));
-
-extern int rl_discard_argument __P((void));
-
-/* Utility functions to bind keys to readline commands. */
-extern int rl_add_defun __P((char *, Function *, int));
-extern int rl_bind_key __P((int, Function *));
-extern int rl_bind_key_in_map __P((int, Function *, Keymap));
-extern int rl_unbind_key __P((int));
-extern int rl_unbind_key_in_map __P((int, Keymap));
-extern int rl_unbind_function_in_map __P((Function *, Keymap));
-extern int rl_unbind_command_in_map __P((char *, Keymap));
-extern int rl_set_key __P((char *, Function *, Keymap));
-extern int rl_generic_bind __P((int, char *, char *, Keymap));
-extern int rl_variable_bind __P((char *, char *));
-
-/* Backwards compatibility, use rl_generic_bind instead. */
-extern int rl_macro_bind __P((char *, char *, Keymap));
-
-/* Undocumented in the texinfo manual; not really useful to programs. */
-extern int rl_translate_keyseq __P((char *, char *, int *));
-extern char *rl_untranslate_keyseq __P((int));
-
-extern Function *rl_named_function __P((char *));
-extern Function *rl_function_of_keyseq __P((const char *, Keymap, int *));
-
-extern void rl_list_funmap_names __P((void));
-extern char **rl_invoking_keyseqs_in_map __P((Function *, Keymap));
-extern char **rl_invoking_keyseqs __P((Function *));
-
-extern void rl_function_dumper __P((int));
-extern void rl_macro_dumper __P((int));
-extern void rl_variable_dumper __P((int));
-
-extern int rl_read_init_file __P((const char *));
-extern int rl_parse_and_bind __P((char *));
-
-/* Functions for manipulating keymaps. */
-extern Keymap rl_make_bare_keymap __P((void));
-extern Keymap rl_copy_keymap __P((Keymap));
-extern Keymap rl_make_keymap __P((void));
-extern void rl_discard_keymap __P((Keymap));
-
-extern Keymap rl_get_keymap_by_name __P((char *));
-extern const char *rl_get_keymap_name __P((Keymap));
-extern void rl_set_keymap __P((Keymap));
-extern Keymap rl_get_keymap __P((void));
-extern void rl_set_keymap_from_edit_mode __P((void));
-extern const char *rl_get_keymap_name_from_edit_mode __P((void));
-
-/* Functions for manipulating the funmap, which maps command names to functions. */
-extern int rl_add_funmap_entry __P((const char *, Function *));
-extern void rl_initialize_funmap __P((void));
-extern char **rl_funmap_names __P((void));
-
-/* Utility functions for managing keyboard macros. */
-extern void rl_push_macro_input __P((char *));
-
-/* Functions for undoing, from undo.c */
-extern void rl_add_undo __P((enum undo_code, int, int, char *));
-extern void free_undo_list __P((void));
-extern int rl_do_undo __P((void));
-extern int rl_begin_undo_group __P((void));
-extern int rl_end_undo_group __P((void));
-extern int rl_modifying __P((int, int));
-
-/* Functions for redisplay. */
-extern void rl_redisplay __P((void));
-extern int rl_on_new_line __P((void));
-extern int rl_forced_update_display __P((void));
-extern int rl_clear_message __P((void));
-extern int rl_reset_line_state __P((void));
-
-#if defined (__STDC__) && defined (USE_VARARGS) && defined (PREFER_STDARG)
-extern int rl_message (const char *, ...);
-#else
-extern int rl_message ();
-#endif
-
-/* Undocumented in texinfo manual. */
-extern int rl_show_char __P((int));
-extern int rl_character_len __P((int, int));
-extern int crlf __P((void));
-
-/* Save and restore internal prompt redisplay information. */
-extern void rl_save_prompt __P((void));
-extern void rl_restore_prompt __P((void));
-
-/* Modifying text. */
-extern int rl_insert_text __P((const char *));
-extern int rl_delete_text __P((int, int));
-extern int rl_kill_text __P((int, int));
-extern char *rl_copy_text __P((int, int));
-
-/* Terminal and tty mode management. */
-extern void rl_prep_terminal __P((int));
-extern void rl_deprep_terminal __P((void));
-extern void rltty_set_default_bindings __P((Keymap));
-
-extern int rl_reset_terminal __P((char *));
-extern void rl_resize_terminal __P((void));
-
-/* `Public' utility functions . */
-extern void rl_extend_line_buffer __P((int));
-extern int ding __P((void));
-
-/* Functions for character input. */
-extern int rl_stuff_char __P((int));
-extern int rl_execute_next __P((int));
-extern int rl_read_key __P((void));
-extern int rl_getc __P((FILE *));
-
-/* Readline signal handling, from signals.c */
-extern int rl_set_signals __P((void));
-extern int rl_clear_signals __P((void));
-extern void rl_cleanup_after_signal __P((void));
-extern void rl_reset_after_signal __P((void));
-extern void rl_free_line_state __P((void));
-
-/* Undocumented. */
-extern int rl_expand_prompt __P((char *));
-
-extern int maybe_save_line __P((void));
-extern int maybe_unsave_line __P((void));
-extern int maybe_replace_line __P((void));
-
-/* Completion functions. */
-extern int rl_complete_internal __P((int));
-extern void rl_display_match_list __P((char **, int, int));
-
-extern char **completion_matches __P((const char *, CPFunction *));
-extern char *username_completion_function __P((const char *, int));
-extern char *filename_completion_function __P((const char *, int));
-
-/* **************************************************************** */
-/* */
-/* Well Published Variables */
-/* */
-/* **************************************************************** */
-
-/* The version of this incarnation of the readline library. */
-extern const char *rl_library_version;
-
-/* The name of the calling program. You should initialize this to
- whatever was in argv[0]. It is used when parsing conditionals. */
-extern const char *rl_readline_name;
-
-/* The prompt readline uses. This is set from the argument to
- readline (), and should not be assigned to directly. */
-extern char *rl_prompt;
-
-/* The line buffer that is in use. */
-extern char *rl_line_buffer;
-
-/* The location of point, and end. */
-extern int rl_point, rl_end;
-
-/* The mark, or saved cursor position. */
-extern int rl_mark;
-
-/* Flag to indicate that readline has finished with the current input
- line and should return it. */
-extern int rl_done;
-
-/* If set to a character value, that will be the next keystroke read. */
-extern int rl_pending_input;
-
-/* Non-zero if we called this function from _rl_dispatch(). It's present
- so functions can find out whether they were called from a key binding
- or directly from an application. */
-extern int rl_dispatching;
-
-/* The name of the terminal to use. */
-extern char *rl_terminal_name;
-
-/* The input and output streams. */
-extern FILE *rl_instream, *rl_outstream;
-
-/* If non-zero, then this is the address of a function to call just
- before readline_internal () prints the first prompt. */
-extern Function *rl_startup_hook;
-
-/* If non-zero, this is the address of a function to call just before
- readline_internal_setup () returns and readline_internal starts
- reading input characters. */
-extern Function *rl_pre_input_hook;
-
-/* The address of a function to call periodically while Readline is
- awaiting character input, or NULL, for no event handling. */
-extern Function *rl_event_hook;
-
-extern Function *rl_getc_function;
-extern VFunction *rl_redisplay_function;
-extern VFunction *rl_prep_term_function;
-extern VFunction *rl_deprep_term_function;
-
-/* Dispatch variables. */
-extern Keymap rl_executing_keymap;
-extern Keymap rl_binding_keymap;
-
-/* Display variables. */
-/* If non-zero, readline will erase the entire line, including any prompt,
- if the only thing typed on an otherwise-blank line is something bound to
- rl_newline. */
-extern int rl_erase_empty_line;
-
-/* Variables to control readline signal handling. */
-/* If non-zero, readline will install its own signal handlers for
- SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
-extern int rl_catch_signals;
-
-/* If non-zero, readline will install a signal handler for SIGWINCH
- that also attempts to call any calling application's SIGWINCH signal
- handler. Note that the terminal is not cleaned up before the
- application's signal handler is called; use rl_cleanup_after_signal()
- to do that. */
-extern int rl_catch_sigwinch;
-
-/* Completion variables. */
-/* Pointer to the generator function for completion_matches ().
- NULL means to use filename_entry_function (), the default filename
- completer. */
-extern Function *rl_completion_entry_function;
-
-/* If rl_ignore_some_completions_function is non-NULL it is the address
- of a function to call after all of the possible matches have been
- generated, but before the actual completion is done to the input line.
- The function is called with one argument; a NULL terminated array
- of (char *). If your function removes any of the elements, they
- must be free()'ed. */
-extern Function *rl_ignore_some_completions_function;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-extern CPPFunction *rl_attempted_completion_function;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The initial contents of this variable is what
- breaks words in the shell, i.e. "n\"\\'`@$>". */
-extern const char *rl_basic_word_break_characters;
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-extern const char *rl_completer_word_break_characters;
-
-/* List of characters which can be used to quote a substring of the line.
- Completion occurs on the entire substring, and within the substring
- rl_completer_word_break_characters are treated as any other character,
- unless they also appear within this list. */
-extern char *rl_completer_quote_characters;
-
-/* List of quote characters which cause a word break. */
-extern const char *rl_basic_quote_characters;
-
-/* List of characters that need to be quoted in filenames by the completer. */
-extern char *rl_filename_quote_characters;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-extern char *rl_special_prefixes;
-
-/* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. */
-extern Function *rl_directory_completion_hook;
-
-/* Backwards compatibility with previous versions of readline. */
-#define rl_symbolic_link_hook rl_directory_completion_hook
-
-/* If non-zero, then this is the address of a function to call when
- completing a word would normally display the list of possible matches.
- This function is called instead of actually doing the display.
- It takes three arguments: (char **matches, int num_matches, int max_length)
- where MATCHES is the array of strings that matched, NUM_MATCHES is the
- number of strings in that array, and MAX_LENGTH is the length of the
- longest string in that array. */
-extern VFunction *rl_completion_display_matches_hook;
-
-/* Non-zero means that the results of the matches are to be treated
- as filenames. This is ALWAYS zero on entry, and can only be changed
- within a completion entry finder function. */
-extern int rl_filename_completion_desired;
-
-/* Non-zero means that the results of the matches are to be quoted using
- double quotes (or an application-specific quoting mechanism) if the
- filename contains any characters in rl_word_break_chars. This is
- ALWAYS non-zero on entry, and can only be changed within a completion
- entry finder function. */
-extern int rl_filename_quoting_desired;
-
-/* Set to a function to quote a filename in an application-specific fashion.
- Called with the text to quote, the type of match found (single or multiple)
- and a pointer to the quoting character to be used, which the function can
- reset if desired. */
-extern CPFunction *rl_filename_quoting_function;
-
-/* Function to call to remove quoting characters from a filename. Called
- before completion is attempted, so the embedded quotes do not interfere
- with matching names in the file system. */
-extern CPFunction *rl_filename_dequoting_function;
-
-/* Function to call to decide whether or not a word break character is
- quoted. If a character is quoted, it does not break words for the
- completer. */
-extern Function *rl_char_is_quoted_p;
-
-/* Non-zero means to suppress normal filename completion after the
- user-specified completion function has been called. */
-extern int rl_attempted_completion_over;
-
-/* Set to a character describing the type of completion being attempted by
- rl_complete_internal; available for use by application completion
- functions. */
-extern int rl_completion_type;
-
-/* Character appended to completed words when at the end of the line. The
- default is a space. Nothing is added if this is '\0'. */
-extern int rl_completion_append_character;
-
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if she
- is sure she wants to see them all. The default value is 100. */
-extern int rl_completion_query_items;
-
-/* If non-zero, then disallow duplicates in the matches. */
-extern int rl_ignore_completion_duplicates;
-
-/* If this is non-zero, completion is (temporarily) inhibited, and the
- completion character will be inserted as any other. */
-extern int rl_inhibit_completion;
-
-/* Definitions available for use by readline clients. */
-#define RL_PROMPT_START_IGNORE '\001'
-#define RL_PROMPT_END_IGNORE '\002'
-
-/* Possible values for do_replace argument to rl_filename_quoting_function,
- called by rl_complete_internal. */
-#define NO_MATCH 0
-#define SINGLE_MATCH 1
-#define MULT_MATCH 2
-
-#if !defined (savestring)
-extern char *savestring (); /* XXX backwards compatibility */
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _READLINE_H_ */
diff --git a/readline/rlconf.h b/readline/rlconf.h
deleted file mode 100644
index 1356fd87924..00000000000
--- a/readline/rlconf.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* rlconf.h -- readline configuration definitions */
-
-/* Copyright (C) 1994 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_RLCONF_H_)
-#define _RLCONF_H_
-
-/* Define this if you want the vi-mode editing available. */
-#define VI_MODE
-
-/* Define this to get an indication of file type when listing completions. */
-#define VISIBLE_STATS
-
-/* If defined, readline shows opening parens and braces when closing
- paren or brace entered. */
-/* #define PAREN_MATCHING */
-
-/* This definition is needed by readline.c, rltty.c, and signals.c. */
-/* If on, then readline handles signals in a way that doesn't screw. */
-#define HANDLE_SIGNALS
-
-/* Ugly but working hack for binding prefix meta. */
-#define PREFIX_META_HACK
-
-/* The final, last-ditch effort file name for an init file. */
-#define DEFAULT_INPUTRC "~/.inputrc"
-
-/* If defined, expand tabs to spaces. */
-#define DISPLAY_TABS
-
-/* If defined, use the terminal escape sequence to move the cursor forward
- over a character when updating the line rather than rewriting it. */
-/* #define HACK_TERMCAP_MOTION */
-
-/* The string inserted by the `insert comment' command. */
-#define RL_COMMENT_BEGIN_DEFAULT "#"
-
-/* Define this if you want code that allows readline to be used in an
- X `callback' style. */
-#define READLINE_CALLBACKS
-
-#endif /* _RLCONF_H_ */
diff --git a/readline/rldefs.h b/readline/rldefs.h
deleted file mode 100644
index d4aced43e2a..00000000000
--- a/readline/rldefs.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* rldefs.h -- an attempt to isolate some of the system-specific defines
- for readline. This should be included after any files that define
- system-specific constants like _POSIX_VERSION or USG. */
-
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_RLDEFS_H_)
-#define _RLDEFS_H_
-
-#if defined (HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING)
-# define TERMIOS_TTY_DRIVER
-#else
-# if defined (HAVE_TERMIO_H)
-# define TERMIO_TTY_DRIVER
-# else
-# define NEW_TTY_DRIVER
-# endif
-#endif
-
-/* Posix macro to check file in statbuf for directory-ness.
- This requires that <sys/stat.h> be included before this test. */
-#if defined (S_IFDIR) && !defined (S_ISDIR)
-# define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
-#endif
-
-/* Decide which flavor of the header file describing the C library
- string functions to include and include it. */
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-#if defined (PREFER_STDARG)
-# include <stdarg.h>
-#else
-# if defined (PREFER_VARARGS)
-# include <varargs.h>
-# endif
-#endif
-
-#if defined (HAVE_STRCASECMP)
-#define _rl_stricmp strcasecmp
-#define _rl_strnicmp strncasecmp
-#else
-extern int _rl_stricmp (), _rl_strnicmp ();
-#endif
-
-#if !defined (emacs_mode)
-# define no_mode -1
-# define vi_mode 0
-# define emacs_mode 1
-#endif
-
-/* If you cast map[key].function to type (Keymap) on a Cray,
- the compiler takes the value of map[key].function and
- divides it by 4 to convert between pointer types (pointers
- to functions and pointers to structs are different sizes).
- This is not what is wanted. */
-#if defined (CRAY)
-# define FUNCTION_TO_KEYMAP(map, key) (Keymap)((int)map[key].function)
-# define KEYMAP_TO_FUNCTION(data) (Function *)((int)(data))
-#else
-# define FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function)
-# define KEYMAP_TO_FUNCTION(data) (Function *)(data)
-#endif
-
-#ifndef savestring
-extern char *xmalloc ();
-#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
-#endif
-
-/* Possible values for _rl_bell_preference. */
-#define NO_BELL 0
-#define AUDIBLE_BELL 1
-#define VISIBLE_BELL 2
-
-/* Definitions used when searching the line for characters. */
-/* NOTE: it is necessary that opposite directions are inverses */
-#define FTO 1 /* forward to */
-#define BTO -1 /* backward to */
-#define FFIND 2 /* forward find */
-#define BFIND -2 /* backward find */
-
-/* Possible values for the found_quote flags word used by the completion
- functions. It says what kind of (shell-like) quoting we found anywhere
- in the line. */
-#define RL_QF_SINGLE_QUOTE 0x1
-#define RL_QF_DOUBLE_QUOTE 0x2
-#define RL_QF_BACKSLASH 0x4
-
-/* Default readline line buffer length. */
-#define DEFAULT_BUFFER_SIZE 256
-
-#if !defined (STREQ)
-#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
-#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
-#endif
-
-#if !defined (FREE)
-# define FREE(x) if (x) free (x)
-#endif
-
-/* CONFIGURATION SECTION */
-#include "rlconf.h"
-
-#endif /* !_RLDEFS_H_ */
diff --git a/readline/rlstdc.h b/readline/rlstdc.h
deleted file mode 100644
index f79cf89fe76..00000000000
--- a/readline/rlstdc.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* stdc.h -- macros to make source compile on both ANSI C and K&R C
- compilers. */
-
-/* Copyright (C) 1993 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- Bash is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_RL_STDC_H_)
-#define _RL_STDC_H_
-
-/* Adapted from BSD /usr/include/sys/cdefs.h. */
-
-/* A function can be defined using prototypes and compile on both ANSI C
- and traditional C compilers with something like this:
- extern char *func __P((char *, char *, int)); */
-
-#if defined (__STDC__) || defined(__cplusplus)
-
-# if !defined (__P)
-# define __P(protos) protos
-# endif
-# define __STRING(x) #x
-
-# if !defined (__GNUC__) && !defined(__cplusplus) && !defined(inline)
-# define inline
-# endif
-
-#else /* !__STDC__ */
-
-# if !defined (__P)
-# define __P(protos) ()
-# endif
-# define __STRING(x) "x"
-
-#if defined (__GNUC__) /* gcc with -traditional */
-# if !defined (const)
-# define const __const
-# endif
-# if !defined (inline)
-# define inline __inline
-# endif
-# if !defined (signed)
-# define signed __signed
-# endif
-# if !defined (volatile)
-# define volatile __volatile
-# endif
-#else /* !__GNUC__ */
-# if !defined (const)
-# define const
-# endif
-# if !defined (inline)
-# define inline
-# endif
-# if !defined (signed)
-# define signed
-# endif
-# if !defined (volatile)
-# define volatile
-# endif
-#endif /* !__GNUC__ */
-
-#endif /* !__STDC__ */
-
-#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
-#define __attribute__(A)
-#endif
-
-#endif /* !_RL_STDC_H_ */
diff --git a/readline/rltty.c b/readline/rltty.c
deleted file mode 100644
index f87c1c9747f..00000000000
--- a/readline/rltty.c
+++ /dev/null
@@ -1,737 +0,0 @@
-/* rltty.c -- functions to prepare and restore the terminal for readline's
- use. */
-
-/* Copyright (C) 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdio.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include "rldefs.h"
-
-#if defined (GWINSZ_IN_SYS_IOCTL)
-# include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL */
-
-#include "rltty.h"
-#include "readline.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-extern int readline_echoing_p;
-extern int _rl_eof_char;
-
-extern int _rl_enable_keypad, _rl_enable_meta;
-
-extern void _rl_control_keypad ();
-
-#if defined (__GO32__)
-# include <pc.h>
-# undef HANDLE_SIGNALS
-#endif /* __GO32__ */
-
-/* Indirect functions to allow apps control over terminal management. */
-extern void rl_prep_terminal (), rl_deprep_terminal ();
-
-VFunction *rl_prep_term_function = rl_prep_terminal;
-VFunction *rl_deprep_term_function = rl_deprep_terminal;
-
-/* **************************************************************** */
-/* */
-/* Signal Management */
-/* */
-/* **************************************************************** */
-
-#if defined (HAVE_POSIX_SIGNALS)
-static sigset_t sigint_set, sigint_oset;
-#else /* !HAVE_POSIX_SIGNALS */
-# if defined (HAVE_BSD_SIGNALS)
-static int sigint_oldmask;
-# endif /* HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-static int sigint_blocked;
-
-/* Cause SIGINT to not be delivered until the corresponding call to
- release_sigint(). */
-static void
-block_sigint ()
-{
- if (sigint_blocked)
- return;
-
-#if defined (HAVE_POSIX_SIGNALS)
- sigemptyset (&sigint_set);
- sigemptyset (&sigint_oset);
- sigaddset (&sigint_set, SIGINT);
- sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
-#else /* !HAVE_POSIX_SIGNALS */
-# if defined (HAVE_BSD_SIGNALS)
- sigint_oldmask = sigblock (sigmask (SIGINT));
-# else /* !HAVE_BSD_SIGNALS */
-# if defined (HAVE_USG_SIGHOLD)
- sighold (SIGINT);
-# endif /* HAVE_USG_SIGHOLD */
-# endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
- sigint_blocked = 1;
-}
-
-/* Allow SIGINT to be delivered. */
-static void
-release_sigint ()
-{
- if (!sigint_blocked)
- return;
-
-#if defined (HAVE_POSIX_SIGNALS)
- sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
-#else
-# if defined (HAVE_BSD_SIGNALS)
- sigsetmask (sigint_oldmask);
-# else /* !HAVE_BSD_SIGNALS */
-# if defined (HAVE_USG_SIGHOLD)
- sigrelse (SIGINT);
-# endif /* HAVE_USG_SIGHOLD */
-# endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
- sigint_blocked = 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Saving and Restoring the TTY */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means that the terminal is in a prepped state. */
-static int terminal_prepped;
-
-/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
- and output is suspended. */
-#if defined (__ksr1__)
-static int ksrflow;
-#endif
-
-#if defined (TIOCGWINSZ)
-/* Dummy call to force a backgrounded readline to stop before it tries
- to get the tty settings. */
-static void
-set_winsize (tty)
- int tty;
-{
- struct winsize w;
-
- if (ioctl (tty, TIOCGWINSZ, &w) == 0)
- (void) ioctl (tty, TIOCSWINSZ, &w);
-}
-#else
-static void
-set_winsize (tty)
- int tty;
-{
-// dummy function, required by other code. What should be doing?
-}
-#endif /* TIOCGWINSZ */
-
-#if defined (NEW_TTY_DRIVER)
-
-/* Values for the `flags' field of a struct bsdtty. This tells which
- elements of the struct bsdtty have been fetched from the system and
- are valid. */
-#define SGTTY_SET 0x01
-#define LFLAG_SET 0x02
-#define TCHARS_SET 0x04
-#define LTCHARS_SET 0x08
-
-struct bsdtty {
- struct sgttyb sgttyb; /* Basic BSD tty driver information. */
- int lflag; /* Local mode flags, like LPASS8. */
-#if defined (TIOCGETC)
- struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
-#endif
-#if defined (TIOCGLTC)
- struct ltchars ltchars; /* 4.2 BSD editing characters */
-#endif
- int flags; /* Bitmap saying which parts of the struct are valid. */
-};
-
-#define TIOTYPE struct bsdtty
-
-static TIOTYPE otio;
-
-static int
-get_tty_settings (tty, tiop)
- int tty;
- TIOTYPE *tiop;
-{
- set_winsize (tty);
-
- tiop->flags = tiop->lflag = 0;
-
- ioctl (tty, TIOCGETP, &(tiop->sgttyb));
- tiop->flags |= SGTTY_SET;
-
-#if defined (TIOCLGET)
- ioctl (tty, TIOCLGET, &(tiop->lflag));
- tiop->flags |= LFLAG_SET;
-#endif
-
-#if defined (TIOCGETC)
- ioctl (tty, TIOCGETC, &(tiop->tchars));
- tiop->flags |= TCHARS_SET;
-#endif
-
-#if defined (TIOCGLTC)
- ioctl (tty, TIOCGLTC, &(tiop->ltchars));
- tiop->flags |= LTCHARS_SET;
-#endif
-
- return 0;
-}
-
-static int
-set_tty_settings (tty, tiop)
- int tty;
- TIOTYPE *tiop;
-{
- if (tiop->flags & SGTTY_SET)
- {
- ioctl (tty, TIOCSETN, &(tiop->sgttyb));
- tiop->flags &= ~SGTTY_SET;
- }
- readline_echoing_p = 1;
-
-#if defined (TIOCLSET)
- if (tiop->flags & LFLAG_SET)
- {
- ioctl (tty, TIOCLSET, &(tiop->lflag));
- tiop->flags &= ~LFLAG_SET;
- }
-#endif
-
-#if defined (TIOCSETC)
- if (tiop->flags & TCHARS_SET)
- {
- ioctl (tty, TIOCSETC, &(tiop->tchars));
- tiop->flags &= ~TCHARS_SET;
- }
-#endif
-
-#if defined (TIOCSLTC)
- if (tiop->flags & LTCHARS_SET)
- {
- ioctl (tty, TIOCSLTC, &(tiop->ltchars));
- tiop->flags &= ~LTCHARS_SET;
- }
-#endif
-
- return 0;
-}
-
-static void
-prepare_terminal_settings (meta_flag, otio, tiop)
- int meta_flag;
- TIOTYPE otio, *tiop;
-{
-#if !defined (__GO32__)
- readline_echoing_p = (otio.sgttyb.sg_flags & ECHO);
-
- /* Copy the original settings to the structure we're going to use for
- our settings. */
- tiop->sgttyb = otio.sgttyb;
- tiop->lflag = otio.lflag;
-#if defined (TIOCGETC)
- tiop->tchars = otio.tchars;
-#endif
-#if defined (TIOCGLTC)
- tiop->ltchars = otio.ltchars;
-#endif
- tiop->flags = otio.flags;
-
- /* First, the basic settings to put us into character-at-a-time, no-echo
- input mode. */
- tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
- tiop->sgttyb.sg_flags |= CBREAK;
-
- /* If this terminal doesn't care how the 8th bit is used, then we can
- use it for the meta-key. If only one of even or odd parity is
- specified, then the terminal is using parity, and we cannot. */
-#if !defined (ANYP)
-# define ANYP (EVENP | ODDP)
-#endif
- if (((otio.sgttyb.sg_flags & ANYP) == ANYP) ||
- ((otio.sgttyb.sg_flags & ANYP) == 0))
- {
- tiop->sgttyb.sg_flags |= ANYP;
-
- /* Hack on local mode flags if we can. */
-#if defined (TIOCLGET)
-# if defined (LPASS8)
- tiop->lflag |= LPASS8;
-# endif /* LPASS8 */
-#endif /* TIOCLGET */
- }
-
-#if defined (TIOCGETC)
-# if defined (USE_XON_XOFF)
- /* Get rid of terminal output start and stop characters. */
- tiop->tchars.t_stopc = -1; /* C-s */
- tiop->tchars.t_startc = -1; /* C-q */
-
- /* If there is an XON character, bind it to restart the output. */
- if (otio.tchars.t_startc != -1)
- rl_bind_key (otio.tchars.t_startc, rl_restart_output);
-# endif /* USE_XON_XOFF */
-
- /* If there is an EOF char, bind _rl_eof_char to it. */
- if (otio.tchars.t_eofc != -1)
- _rl_eof_char = otio.tchars.t_eofc;
-
-# if defined (NO_KILL_INTR)
- /* Get rid of terminal-generated SIGQUIT and SIGINT. */
- tiop->tchars.t_quitc = -1; /* C-\ */
- tiop->tchars.t_intrc = -1; /* C-c */
-# endif /* NO_KILL_INTR */
-#endif /* TIOCGETC */
-
-#if defined (TIOCGLTC)
- /* Make the interrupt keys go away. Just enough to make people happy. */
- tiop->ltchars.t_dsuspc = -1; /* C-y */
- tiop->ltchars.t_lnextc = -1; /* C-v */
-#endif /* TIOCGLTC */
-#endif /* !__GO32__ */
-}
-
-#else /* !defined (NEW_TTY_DRIVER) */
-
-#if !defined (VMIN)
-# define VMIN VEOF
-#endif
-
-#if !defined (VTIME)
-# define VTIME VEOL
-#endif
-
-#if defined (TERMIOS_TTY_DRIVER)
-# define TIOTYPE struct termios
-# define DRAIN_OUTPUT(fd) tcdrain (fd)
-# define GETATTR(tty, tiop) (tcgetattr (tty, tiop))
-# ifdef M_UNIX
-# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
-# else
-# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
-# endif /* !M_UNIX */
-#else
-# define TIOTYPE struct termio
-# define DRAIN_OUTPUT(fd)
-# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop))
-# define SETATTR(tty, tiop) (ioctl (tty, TCSETA, tiop))
-#endif /* !TERMIOS_TTY_DRIVER */
-
-static TIOTYPE otio;
-
-#if defined (FLUSHO)
-# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
-#else
-# define OUTPUT_BEING_FLUSHED(tp) 0
-#endif
-
-#if defined (_AIX) || (defined (FLUSHO) && defined (_AIX41))
-static void
-rltty_warning (msg)
- char *msg;
-{
- fprintf (stderr, "readline: warning: %s\n", msg);
-}
-#endif
-
-
-#if defined (_AIX)
-void
-setopost(tp)
-TIOTYPE *tp;
-{
- if ((tp->c_oflag & OPOST) == 0)
- {
- rltty_warning ("turning on OPOST for terminal\r");
- tp->c_oflag |= OPOST|ONLCR;
- }
-}
-#endif
-
-static int
-get_tty_settings (tty, tiop)
- int tty;
- TIOTYPE *tiop;
-{
- int ioctl_ret;
-
- set_winsize (tty);
-
- while (1)
- {
- ioctl_ret = GETATTR (tty, tiop);
- if (ioctl_ret < 0)
- {
- if (errno != EINTR)
- return -1;
- else
- continue;
- }
- if (OUTPUT_BEING_FLUSHED (tiop))
- {
-#if defined (FLUSHO) && defined (_AIX41)
- rltty_warning ("turning off output flushing");
- tiop->c_lflag &= ~FLUSHO;
- break;
-#else
- continue;
-#endif
- }
- break;
- }
-
-#if defined (_AIX)
- setopost(tiop);
-#endif
-
- return 0;
-}
-
-static int
-set_tty_settings (tty, tiop)
- int tty;
- TIOTYPE *tiop;
-{
- while (SETATTR (tty, tiop) < 0)
- {
- if (errno != EINTR)
- return -1;
- errno = 0;
- }
-
-#if 0
-
-#if defined (TERMIOS_TTY_DRIVER)
-# if defined (__ksr1__)
- if (ksrflow)
- {
- ksrflow = 0;
- tcflow (tty, TCOON);
- }
-# else /* !ksr1 */
- tcflow (tty, TCOON); /* Simulate a ^Q. */
-# endif /* !ksr1 */
-#else
- ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
-#endif /* !TERMIOS_TTY_DRIVER */
-
-#endif
-
- return 0;
-}
-
-static void
-prepare_terminal_settings (meta_flag, otio, tiop)
- int meta_flag;
- TIOTYPE otio, *tiop;
-{
- readline_echoing_p = (otio.c_lflag & ECHO);
-
- tiop->c_lflag &= ~(ICANON | ECHO);
-
- if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
- _rl_eof_char = otio.c_cc[VEOF];
-
-#if defined (USE_XON_XOFF)
-#if defined (IXANY)
- tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
-#else
- /* `strict' Posix systems do not define IXANY. */
- tiop->c_iflag &= ~(IXON | IXOFF);
-#endif /* IXANY */
-#endif /* USE_XON_XOFF */
-
- /* Only turn this off if we are using all 8 bits. */
- if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
- tiop->c_iflag &= ~(ISTRIP | INPCK);
-
- /* Make sure we differentiate between CR and NL on input. */
- tiop->c_iflag &= ~(ICRNL | INLCR);
-
-#if !defined (HANDLE_SIGNALS)
- tiop->c_lflag &= ~ISIG;
-#else
- tiop->c_lflag |= ISIG;
-#endif
-
- tiop->c_cc[VMIN] = 1;
- tiop->c_cc[VTIME] = 0;
-
-#if defined (FLUSHO)
- if (OUTPUT_BEING_FLUSHED (tiop))
- {
- tiop->c_lflag &= ~FLUSHO;
- otio.c_lflag &= ~FLUSHO;
- }
-#endif
-
- /* Turn off characters that we need on Posix systems with job control,
- just to be sure. This includes ^Y and ^V. This should not really
- be necessary. */
-#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
-
-#if defined (VLNEXT)
- tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
-#endif
-
-#if defined (VDSUSP)
- tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif
-
-#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
-}
-#endif /* NEW_TTY_DRIVER */
-
-/* Put the terminal in CBREAK mode so that we can detect key presses. */
-void
-rl_prep_terminal (meta_flag)
- int meta_flag;
-{
-#if !defined (__GO32__)
- int tty;
- TIOTYPE tio;
-
- if (terminal_prepped)
- return;
-
- /* Try to keep this function from being INTerrupted. */
- block_sigint ();
-
- tty = fileno (rl_instream);
-
- if (get_tty_settings (tty, &tio) < 0)
- {
- release_sigint ();
- return;
- }
-
- otio = tio;
-
- prepare_terminal_settings (meta_flag, otio, &tio);
-
- if (set_tty_settings (tty, &tio) < 0)
- {
- release_sigint ();
- return;
- }
-
- if (_rl_enable_keypad)
- _rl_control_keypad (1);
-
- fflush (rl_outstream);
- terminal_prepped = 1;
-
- release_sigint ();
-#endif /* !__GO32__ */
-}
-
-/* Restore the terminal's normal settings and modes. */
-void
-rl_deprep_terminal ()
-{
-#if !defined (__GO32__)
- int tty;
-
- if (!terminal_prepped)
- return;
-
- /* Try to keep this function from being interrupted. */
- block_sigint ();
-
- tty = fileno (rl_instream);
-
- if (_rl_enable_keypad)
- _rl_control_keypad (0);
-
- fflush (rl_outstream);
-
- if (set_tty_settings (tty, &otio) < 0)
- {
- release_sigint ();
- return;
- }
-
- terminal_prepped = 0;
-
- release_sigint ();
-#endif /* !__GO32__ */
-}
-
-/* **************************************************************** */
-/* */
-/* Bogus Flow Control */
-/* */
-/* **************************************************************** */
-
-int
-rl_restart_output (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- int fildes = fileno (rl_outstream);
-#if defined (TIOCSTART)
-#if defined (apollo)
- ioctl (&fildes, TIOCSTART, 0);
-#else
- ioctl (fildes, TIOCSTART, 0);
-#endif /* apollo */
-
-#else /* !TIOCSTART */
-# if defined (TERMIOS_TTY_DRIVER)
-# if defined (__ksr1__)
- if (ksrflow)
- {
- ksrflow = 0;
- tcflow (fildes, TCOON);
- }
-# else /* !ksr1 */
- tcflow (fildes, TCOON); /* Simulate a ^Q. */
-# endif /* !ksr1 */
-# else /* !TERMIOS_TTY_DRIVER */
-# if defined (TCXONC)
- ioctl (fildes, TCXONC, TCOON);
-# endif /* TCXONC */
-# endif /* !TERMIOS_TTY_DRIVER */
-#endif /* !TIOCSTART */
-
- return 0;
-}
-
-int
-rl_stop_output (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- int fildes = fileno (rl_instream);
-
-#if defined (TIOCSTOP)
-# if defined (apollo)
- ioctl (&fildes, TIOCSTOP, 0);
-# else
- ioctl (fildes, TIOCSTOP, 0);
-# endif /* apollo */
-#else /* !TIOCSTOP */
-# if defined (TERMIOS_TTY_DRIVER)
-# if defined (__ksr1__)
- ksrflow = 1;
-# endif /* ksr1 */
- tcflow (fildes, TCOOFF);
-# else
-# if defined (TCXONC)
- ioctl (fildes, TCXONC, TCOON);
-# endif /* TCXONC */
-# endif /* !TERMIOS_TTY_DRIVER */
-#endif /* !TIOCSTOP */
-
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Default Key Bindings */
-/* */
-/* **************************************************************** */
-void
-rltty_set_default_bindings (kmap)
- Keymap kmap;
-{
- TIOTYPE ttybuff;
- int tty = fileno (rl_instream);
-
-#if defined (NEW_TTY_DRIVER)
-
-#define SET_SPECIAL(sc, func) \
- do \
- { \
- int ic; \
- ic = sc; \
- if (ic != -1 && kmap[ic].type == ISFUNC) \
- kmap[ic].function = func; \
- } \
- while (0)
-
- if (get_tty_settings (tty, &ttybuff) == 0)
- {
- if (ttybuff.flags & SGTTY_SET)
- {
- SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
- SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
- }
-
-# if defined (TIOCGLTC)
- if (ttybuff.flags & LTCHARS_SET)
- {
- SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
- SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
- }
-# endif /* TIOCGLTC */
- }
-
-#else /* !NEW_TTY_DRIVER */
-
-#define SET_SPECIAL(sc, func) \
- do \
- { \
- unsigned char uc; \
- uc = ttybuff.c_cc[sc]; \
- if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
- kmap[uc].function = func; \
- } \
- while (0)
-
- if (get_tty_settings (tty, &ttybuff) == 0)
- {
- SET_SPECIAL (VERASE, rl_rubout);
- SET_SPECIAL (VKILL, rl_unix_line_discard);
-
-# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
- SET_SPECIAL (VLNEXT, rl_quoted_insert);
-# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
-
-# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
- SET_SPECIAL (VWERASE, rl_unix_word_rubout);
-# endif /* VWERASE && TERMIOS_TTY_DRIVER */
- }
-#endif /* !NEW_TTY_DRIVER */
-}
diff --git a/readline/rltty.h b/readline/rltty.h
deleted file mode 100644
index fe783463f6a..00000000000
--- a/readline/rltty.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* rltty.h - tty driver-related definitions used by some library files. */
-
-/* Copyright (C) 1995 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_RLTTY_H_)
-#define _RLTTY_H
-
-/* Posix systems use termios and the Posix signal functions. */
-#if defined (TERMIOS_TTY_DRIVER)
-# include <termios.h>
-#endif /* TERMIOS_TTY_DRIVER */
-
-/* System V machines use termio. */
-#if defined (TERMIO_TTY_DRIVER)
-# include <termio.h>
-# if !defined (TCOON)
-# define TCOON 1
-# endif
-#endif /* TERMIO_TTY_DRIVER */
-
-/* Other (BSD) machines use sgtty. */
-#if defined (NEW_TTY_DRIVER)
-# include <sgtty.h>
-#endif
-
-#include "rlwinsize.h"
-
-/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
- it is not already defined. It is used both to determine if a
- special character is disabled and to disable certain special
- characters. Posix systems should set to 0, USG systems to -1. */
-#if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
-# if defined (_SVR4_VDISABLE)
-# define _POSIX_VDISABLE _SVR4_VDISABLE
-# else
-# if defined (_POSIX_VERSION)
-# define _POSIX_VDISABLE 0
-# else /* !_POSIX_VERSION */
-# define _POSIX_VDISABLE -1
-# endif /* !_POSIX_VERSION */
-# endif /* !_SVR4_DISABLE */
-#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
-
-#endif /* _RLTTY_H_ */
diff --git a/readline/rlwinsize.h b/readline/rlwinsize.h
deleted file mode 100644
index 92b3de174bf..00000000000
--- a/readline/rlwinsize.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* rlwinsize.h -- an attempt to isolate some of the system-specific defines
- for `struct winsize' and TIOCGWINSZ. */
-
-/* Copyright (C) 1997 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_RLWINSIZE_H_)
-#define _RLWINSIZE_H_
-
-#if defined (HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
-
-#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
-# include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
-
-#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
-# include <termios.h>
-#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
-
-/* Not in either of the standard places, look around. */
-#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
-# if defined (HAVE_SYS_STREAM_H)
-# include <sys/stream.h>
-# endif /* HAVE_SYS_STREAM_H */
-# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
-# include <sys/ptem.h>
-# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
-# endif /* HAVE_SYS_PTEM_H */
-# if defined (HAVE_SYS_PTE_H) /* ??? */
-# include <sys/pte.h>
-# endif /* HAVE_SYS_PTE_H */
-#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
-
-#endif /* _RL_WINSIZE_H */
-
-
diff --git a/readline/search.c b/readline/search.c
deleted file mode 100644
index 0179d8da2f1..00000000000
--- a/readline/search.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/* search.c - code for non-incremental searching in emacs and vi modes. */
-
-/* Copyright (C) 1992 Free Software Foundation, Inc.
-
- This file is part of the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif
-
-#include "rldefs.h"
-#include "readline.h"
-#include "history.h"
-
-#ifdef abs
-# undef abs
-#endif
-#define abs(x) (((x) >= 0) ? (x) : -(x))
-
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables imported from readline.c */
-extern int rl_point, rl_end, rl_line_buffer_len;
-extern int rl_editing_mode;
-extern char *rl_prompt;
-extern char *rl_line_buffer;
-extern HIST_ENTRY *saved_line_for_history;
-extern Function *rl_last_func;
-
-/* Functions imported from the rest of the library. */
-extern int _rl_free_history_entry ();
-extern char *_rl_make_prompt_for_search ();
-extern void rl_extend_line_buffer ();
-
-static char *noninc_search_string = (char *) NULL;
-static int noninc_history_pos;
-static char *prev_line_found = (char *) NULL;
-
-/* Search the history list for STRING starting at absolute history position
- POS. If STRING begins with `^', the search must match STRING at the
- beginning of a history line, otherwise a full substring match is performed
- for STRING. DIR < 0 means to search backwards through the history list,
- DIR >= 0 means to search forward. */
-static int
-noninc_search_from_pos (string, pos, dir)
- char *string;
- int pos, dir;
-{
- int ret, old;
-
- old = where_history ();
- history_set_pos (pos);
-
- if (*string == '^')
- ret = history_search_prefix (string + 1, dir);
- else
- ret = history_search (string, dir);
-
- if (ret != -1)
- ret = where_history ();
-
- history_set_pos (old);
- return (ret);
-}
-
-/* Search for a line in the history containing STRING. If DIR is < 0, the
- search is backwards through previous entries, else through subsequent
- entries. */
-static void
-noninc_dosearch (string, dir)
- char *string;
- int dir;
-{
- int oldpos, pos, line_len;
- HIST_ENTRY *entry;
-
- if (string == 0 || *string == '\0' || noninc_history_pos < 0)
- {
- ding ();
- return;
- }
-
- pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
- if (pos == -1)
- {
- /* Search failed, current history position unchanged. */
- maybe_unsave_line ();
- rl_clear_message ();
- rl_point = 0;
- ding ();
- return;
- }
-
- noninc_history_pos = pos;
-
- oldpos = where_history ();
- history_set_pos (noninc_history_pos);
- entry = current_history ();
-#if defined (VI_MODE)
- if (rl_editing_mode != vi_mode)
-#endif
- history_set_pos (oldpos);
-
- line_len = strlen (entry->line);
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
- strcpy (rl_line_buffer, entry->line);
-
- rl_undo_list = (UNDO_LIST *)entry->data;
- rl_end = strlen (rl_line_buffer);
- rl_point = 0;
- rl_clear_message ();
-
- if (saved_line_for_history)
- _rl_free_history_entry (saved_line_for_history);
- saved_line_for_history = (HIST_ENTRY *)NULL;
-}
-
-/* Search non-interactively through the history list. DIR < 0 means to
- search backwards through the history of previous commands; otherwise
- the search is for commands subsequent to the current position in the
- history list. PCHAR is the character to use for prompting when reading
- the search string; if not specified (0), it defaults to `:'. */
-static void
-noninc_search (dir, pchar)
- int dir;
- int pchar;
-{
- int saved_point, c;
- char *p;
-
- maybe_save_line ();
- saved_point = rl_point;
-
- /* Use the line buffer to read the search string. */
- rl_line_buffer[0] = 0;
- rl_end = rl_point = 0;
-
- p = _rl_make_prompt_for_search (pchar ? pchar : ':');
- rl_message (p, 0, 0);
- free (p);
-
-#define SEARCH_RETURN rl_restore_prompt (); return
-
- /* Read the search string. */
- while ((c = rl_read_key ()))
- {
- switch (c)
- {
- case CTRL('H'):
- case RUBOUT:
- if (rl_point == 0)
- {
- maybe_unsave_line ();
- rl_clear_message ();
- rl_point = saved_point;
- SEARCH_RETURN;
- }
- rl_rubout (1, c);
- break;
-
- case CTRL('W'):
- rl_unix_word_rubout (1, c);
- break;
-
- case CTRL('U'):
- rl_unix_line_discard (1, c);
- break;
-
- case RETURN:
- case NEWLINE:
- goto dosearch;
- /* NOTREACHED */
- break;
-
- case CTRL('C'):
- case CTRL('G'):
- maybe_unsave_line ();
- rl_clear_message ();
- rl_point = saved_point;
- ding ();
- SEARCH_RETURN;
-
- default:
- rl_insert (1, c);
- break;
- }
- (*rl_redisplay_function) ();
- }
-
- dosearch:
- /* If rl_point == 0, we want to re-use the previous search string and
- start from the saved history position. If there's no previous search
- string, punt. */
- if (rl_point == 0)
- {
- if (!noninc_search_string)
- {
- ding ();
- SEARCH_RETURN;
- }
- }
- else
- {
- /* We want to start the search from the current history position. */
- noninc_history_pos = where_history ();
- if (noninc_search_string)
- free (noninc_search_string);
- noninc_search_string = savestring (rl_line_buffer);
- }
-
- rl_restore_prompt ();
- noninc_dosearch (noninc_search_string, dir);
-}
-
-/* Search forward through the history list for a string. If the vi-mode
- code calls this, KEY will be `?'. */
-int
-rl_noninc_forward_search (int count __attribute__((unused)), int key)
-{
- noninc_search (1, (key == '?') ? '?' : 0);
- return 0;
-}
-
-/* Reverse search the history list for a string. If the vi-mode code
- calls this, KEY will be `/'. */
-int
-rl_noninc_reverse_search (int count __attribute__((unused)), int key)
-{
- noninc_search (-1, (key == '/') ? '/' : 0);
- return 0;
-}
-
-/* Search forward through the history list for the last string searched
- for. If there is no saved search string, abort. */
-int
-rl_noninc_forward_search_again (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (!noninc_search_string)
- {
- ding ();
- return (-1);
- }
- noninc_dosearch (noninc_search_string, 1);
- return 0;
-}
-
-/* Reverse search in the history list for the last string searched
- for. If there is no saved search string, abort. */
-int
-rl_noninc_reverse_search_again (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (!noninc_search_string)
- {
- ding ();
- return (-1);
- }
- noninc_dosearch (noninc_search_string, -1);
- return 0;
-}
-
-static int
-rl_history_search_internal (count, direction)
- int count, direction;
-{
- HIST_ENTRY *temp, *old_temp;
- int line_len;
-
- maybe_save_line ();
-
- temp = old_temp = (HIST_ENTRY *)NULL;
- while (count)
- {
- temp = (direction < 0) ? previous_history () : next_history ();
- if (temp == 0)
- break;
- /* On an empty prefix, make this the same as previous-history. */
- if (rl_point == 0)
- {
- count--;
- continue;
- }
- if (STREQN (rl_line_buffer, temp->line, rl_point))
- {
- /* Don't find multiple instances of the same line. */
- if (prev_line_found && STREQ (prev_line_found, temp->line))
- continue;
- if (direction < 0)
- old_temp = temp;
- prev_line_found = temp->line;
- count--;
- }
- }
-
- if (temp == 0)
- {
- if (direction < 0 && old_temp)
- temp = old_temp;
- else
- {
- maybe_unsave_line ();
- ding ();
- return 1;
- }
- }
-
- line_len = strlen (temp->line);
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
- strcpy (rl_line_buffer, temp->line);
- rl_undo_list = (UNDO_LIST *)temp->data;
- rl_end = line_len;
- return 0;
-}
-
-/* Search forward in the history for the string of characters
- from the start of the line to rl_point. This is a non-incremental
- search. */
-int
-rl_history_search_forward (int count, int ignore __attribute__((unused)))
-{
- if (count == 0)
- return (0);
- if (rl_last_func != rl_history_search_forward)
- prev_line_found = (char *)NULL;
- return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
-}
-
-/* Search backward through the history for the string of characters
- from the start of the line to rl_point. This is a non-incremental
- search. */
-int
-rl_history_search_backward (int count, int ignore __attribute__((unused)))
-{
- if (count == 0)
- return (0);
- if (rl_last_func != rl_history_search_backward)
- prev_line_found = (char *)NULL;
- return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
-}
diff --git a/readline/shell.c b/readline/shell.c
deleted file mode 100644
index becd66e0f9a..00000000000
--- a/readline/shell.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* shell.c -- readline utility functions that are normally provided by
- bash when readline is linked as part of the shell. */
-
-/* Copyright (C) 1997 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_STDIO_H)
-# include <stdio.h>
-#endif /* HAVE_STDIO_H */
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#include <pwd.h>
-
-#if !defined (HAVE_GETPW_DECLS)
-extern struct passwd *getpwuid ();
-#endif /* !HAVE_GETPW_DECLS */
-
-extern char *xmalloc ();
-
-/* All of these functions are resolved from bash if we are linking readline
- as part of bash. */
-
-/* Does shell-like quoting using single quotes. */
-char *
-single_quote (string)
- char *string;
-{
- register int c;
- char *result, *r, *s;
-
- result = (char *)xmalloc (3 + (3 * strlen (string)));
- r = result;
- *r++ = '\'';
-
- for (s = string; s && (c = *s); s++)
- {
- *r++ = c;
-
- if (c == '\'')
- {
- *r++ = '\\'; /* insert escaped single quote */
- *r++ = '\'';
- *r++ = '\''; /* start new quoted string */
- }
- }
-
- *r++ = '\'';
- *r = '\0';
-
- return (result);
-}
-
-/* Set the environment variables LINES and COLUMNS to lines and cols,
- respectively. */
-void
-set_lines_and_columns (lines, cols)
- int lines, cols;
-{
- char *b;
-
-#if defined (HAVE_PUTENV)
- b = xmalloc (24);
- sprintf (b, "LINES=%d", lines);
- putenv (b);
- b = xmalloc (24);
- sprintf (b, "COLUMNS=%d", cols);
- putenv (b);
-#else /* !HAVE_PUTENV */
-# if defined (HAVE_SETENV)
- b = xmalloc (8);
- sprintf (b, "%d", lines);
- setenv ("LINES", b, 1);
- b = xmalloc (8);
- sprintf (b, "%d", cols);
- setenv ("COLUMNS", b, 1);
-# endif /* HAVE_SETENV */
-#endif /* !HAVE_PUTENV */
-}
-
-char *
-get_env_value (varname)
- char *varname;
-{
- return ((char *)getenv (varname));
-}
-
-char *
-get_home_dir ()
-{
- char *home_dir;
- struct passwd *entry;
-
- home_dir = (char *)NULL;
- entry = getpwuid (getuid ());
- if (entry)
- home_dir = entry->pw_dir;
- return (home_dir);
-}
diff --git a/readline/signals.c b/readline/signals.c
deleted file mode 100644
index 3a34432f143..00000000000
--- a/readline/signals.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/* signals.c -- signal handling support for readline. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h> /* Just for NULL. Yuck. */
-#include <sys/types.h>
-#include <signal.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-#if defined (GWINSZ_IN_SYS_IOCTL)
-# include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL */
-
-#if defined (__GO32__)
-# undef HANDLE_SIGNALS
-#endif /* __GO32__ */
-
-#if defined (HANDLE_SIGNALS)
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#if !defined (RETSIGTYPE)
-# if defined (VOID_SIGHANDLER)
-# define RETSIGTYPE void
-# else
-# define RETSIGTYPE int
-# endif /* !VOID_SIGHANDLER */
-#endif /* !RETSIGTYPE */
-
-#if defined (VOID_SIGHANDLER)
-# define SIGHANDLER_RETURN return
-#else
-# define SIGHANDLER_RETURN return (0)
-#endif
-
-/* This typedef is equivalant to the one for Function; it allows us
- to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
-typedef RETSIGTYPE SigHandler ();
-
-extern int readline_echoing_p;
-extern int rl_pending_input;
-extern int _rl_meta_flag;
-
-extern void free_undo_list ();
-extern void _rl_get_screen_size ();
-extern void _rl_redisplay_after_sigwinch ();
-extern void _rl_clean_up_for_exit ();
-extern void _rl_kill_kbd_macro ();
-extern void _rl_init_argument ();
-extern void rl_deprep_terminal (), rl_prep_terminal ();
-
-static SigHandler *rl_set_sighandler ();
-
-/* Exported variables for use by applications. */
-
-/* If non-zero, readline will install its own signal handlers for
- SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
-int rl_catch_signals = 1;
-
-/* If non-zero, readline will install a signal handler for SIGWINCH. */
-#ifdef SIGWINCH
-int rl_catch_sigwinch = 1;
-#endif
-
-static int signals_set_flag;
-static int sigwinch_set_flag;
-
-/* **************************************************************** */
-/* */
-/* Signal Handling */
-/* */
-/* **************************************************************** */
-
-#if defined (HAVE_POSIX_SIGNALS)
-typedef struct sigaction sighandler_cxt;
-# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
-#else
-typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
-# define sigemptyset(m)
-#endif /* !HAVE_POSIX_SIGNALS */
-
-static sighandler_cxt old_int, old_term, old_alrm, old_quit;
-#if defined (SIGTSTP)
-static sighandler_cxt old_tstp, old_ttou, old_ttin;
-#endif
-#if defined (SIGWINCH)
-static sighandler_cxt old_winch;
-#endif
-
-/* Readline signal handler functions. */
-
-static RETSIGTYPE
-rl_signal_handler (sig)
- int sig;
-{
-#if defined (HAVE_POSIX_SIGNALS)
- sigset_t set;
-#else /* !HAVE_POSIX_SIGNALS */
-# if defined (HAVE_BSD_SIGNALS)
- long omask;
-# else /* !HAVE_BSD_SIGNALS */
- sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
-# endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
- /* Since the signal will not be blocked while we are in the signal
- handler, ignore it until rl_clear_signals resets the catcher. */
- if (sig == SIGINT || sig == SIGALRM)
- rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
-#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
-
- switch (sig)
- {
- case SIGINT:
- rl_free_line_state ();
- /* FALLTHROUGH */
-
-#if defined (SIGTSTP)
- case SIGTSTP:
- case SIGTTOU:
- case SIGTTIN:
-#endif /* SIGTSTP */
- case SIGALRM:
- case SIGTERM:
- case SIGQUIT:
- rl_cleanup_after_signal ();
-
-#if defined (HAVE_POSIX_SIGNALS)
- sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
- sigdelset (&set, sig);
-#else /* !HAVE_POSIX_SIGNALS */
-# if defined (HAVE_BSD_SIGNALS)
- omask = sigblock (0);
-# endif /* HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
- kill (getpid (), sig);
-
- /* Let the signal that we just sent through. */
-#if defined (HAVE_POSIX_SIGNALS)
- sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
-#else /* !HAVE_POSIX_SIGNALS */
-# if defined (HAVE_BSD_SIGNALS)
- sigsetmask (omask & ~(sigmask (sig)));
-# endif /* HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
- rl_reset_after_signal ();
- }
-
- SIGHANDLER_RETURN;
-}
-
-#if defined (SIGWINCH)
-static RETSIGTYPE
-rl_sigwinch_handler (sig)
- int sig;
-{
- SigHandler *oh;
-
-#if defined (MUST_REINSTALL_SIGHANDLERS)
- sighandler_cxt dummy_winch;
-
- /* We don't want to change old_winch -- it holds the state of SIGWINCH
- disposition set by the calling application. We need this state
- because we call the application's SIGWINCH handler after updating
- our own idea of the screen size. */
- rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
-#endif
-
- rl_resize_terminal ();
-
- /* If another sigwinch handler has been installed, call it. */
- oh = (SigHandler *)old_winch.sa_handler;
- if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
- (*oh) (sig);
-
- SIGHANDLER_RETURN;
-}
-#endif /* SIGWINCH */
-
-/* Functions to manage signal handling. */
-
-#if !defined (HAVE_POSIX_SIGNALS)
-static int
-rl_sigaction (sig, nh, oh)
- int sig;
- sighandler_cxt *nh, *oh;
-{
- oh->sa_handler = signal (sig, nh->sa_handler);
- return 0;
-}
-#endif /* !HAVE_POSIX_SIGNALS */
-
-/* Set up a readline-specific signal handler, saving the old signal
- information in OHANDLER. Return the old signal handler, like
- signal(). */
-static SigHandler *
-rl_set_sighandler (sig, handler, ohandler)
- int sig;
- SigHandler *handler;
- sighandler_cxt *ohandler;
-{
-#if defined (HAVE_POSIX_SIGNALS)
- struct sigaction act;
-
- act.sa_handler = handler;
- act.sa_flags = 0;
- sigemptyset (&act.sa_mask);
- sigemptyset (&ohandler->sa_mask);
- sigaction (sig, &act, ohandler);
-#else
- ohandler->sa_handler = (SigHandler *)signal (sig, handler);
-#endif /* !HAVE_POSIX_SIGNALS */
- return (ohandler->sa_handler);
-}
-
-static void
-rl_maybe_set_sighandler (sig, handler, ohandler)
- int sig;
- SigHandler *handler;
- sighandler_cxt *ohandler;
-{
- sighandler_cxt dummy;
- SigHandler *oh;
-
- sigemptyset (&dummy.sa_mask);
- oh = rl_set_sighandler (sig, handler, ohandler);
- if (oh == (SigHandler *)SIG_IGN)
- rl_sigaction (sig, ohandler, &dummy);
-}
-
-int
-rl_set_signals ()
-{
- sighandler_cxt dummy;
- SigHandler *oh;
-
- if (rl_catch_signals && signals_set_flag == 0)
- {
- rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
- rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
- rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
-
- oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
- if (oh == (SigHandler *)SIG_IGN)
- rl_sigaction (SIGALRM, &old_alrm, &dummy);
-#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
- /* If the application using readline has already installed a signal
- handler with SA_RESTART, SIGALRM will cause reads to be restarted
- automatically, so readline should just get out of the way. Since
- we tested for SIG_IGN above, we can just test for SIG_DFL here. */
- if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
- rl_sigaction (SIGALRM, &old_alrm, &dummy);
-#endif /* HAVE_POSIX_SIGNALS */
-
-#if defined (SIGTSTP)
- rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
-#endif /* SIGTSTP */
-
-#if defined (SIGTTOU)
- rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
-#endif /* SIGTTOU */
-
-#if defined (SIGTTIN)
- rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
-#endif /* SIGTTIN */
-
- signals_set_flag = 1;
- }
-
-#if defined (SIGWINCH)
- if (rl_catch_sigwinch && sigwinch_set_flag == 0)
- {
- rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
- sigwinch_set_flag = 1;
- }
-#endif /* SIGWINCH */
-
- return 0;
-}
-
-int
-rl_clear_signals ()
-{
- sighandler_cxt dummy;
-
- if (rl_catch_signals && signals_set_flag == 1)
- {
- sigemptyset (&dummy.sa_mask);
-
- rl_sigaction (SIGINT, &old_int, &dummy);
- rl_sigaction (SIGTERM, &old_term, &dummy);
- rl_sigaction (SIGQUIT, &old_quit, &dummy);
- rl_sigaction (SIGALRM, &old_alrm, &dummy);
-
-#if defined (SIGTSTP)
- rl_sigaction (SIGTSTP, &old_tstp, &dummy);
-#endif /* SIGTSTP */
-
-#if defined (SIGTTOU)
- rl_sigaction (SIGTTOU, &old_ttou, &dummy);
-#endif /* SIGTTOU */
-
-#if defined (SIGTTIN)
- rl_sigaction (SIGTTIN, &old_ttin, &dummy);
-#endif /* SIGTTIN */
-
- signals_set_flag = 0;
- }
-
-#if defined (SIGWINCH)
- if (rl_catch_sigwinch && sigwinch_set_flag == 1)
- {
- sigemptyset (&dummy.sa_mask);
- rl_sigaction (SIGWINCH, &old_winch, &dummy);
- sigwinch_set_flag = 0;
- }
-#endif
-
- return 0;
-}
-
-/* Clean up the terminal and readline state after catching a signal, before
- resending it to the calling application. */
-void
-rl_cleanup_after_signal ()
-{
- _rl_clean_up_for_exit ();
- (*rl_deprep_term_function) ();
- rl_clear_signals ();
- rl_pending_input = 0;
-}
-
-/* Reset the terminal and readline state after a signal handler returns. */
-void
-rl_reset_after_signal ()
-{
- (*rl_prep_term_function) (_rl_meta_flag);
- rl_set_signals ();
-}
-
-/* Free up the readline variable line state for the current line (undo list,
- any partial history entry, any keyboard macros in progress, and any
- numeric arguments in process) after catching a signal, before calling
- rl_cleanup_after_signal(). */
-void
-rl_free_line_state ()
-{
- register HIST_ENTRY *entry;
-
- free_undo_list ();
-
- entry = current_history ();
- if (entry)
- entry->data = (char *)NULL;
-
- _rl_kill_kbd_macro ();
- rl_clear_message ();
- _rl_init_argument ();
-}
-
-#endif /* HANDLE_SIGNALS */
diff --git a/readline/tcap.h b/readline/tcap.h
deleted file mode 100644
index acb2d76ab48..00000000000
--- a/readline/tcap.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* tcap.h -- termcap library functions and variables. */
-
-/* Copyright (C) 1996 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_RLTCAP_H_)
-#define _RLTCAP_H_
-
-#if defined (HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#if defined (HAVE_TERMCAP_H)
-# if defined (__linux__) && !defined (SPEED_T_IN_SYS_TYPES)
-# include "rltty.h"
-# endif
-# include <termcap.h>
-#else
-
-/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
- Unfortunately, PC is a global variable used by the termcap library. */
-#ifdef PC
-# undef PC
-#endif
-
-extern char PC;
-extern char *UP, *BC;
-
-extern short ospeed;
-
-extern int tgetent ();
-extern int tgetflag ();
-extern int tgetnum ();
-extern char *tgetstr ();
-
-extern int tputs ();
-
-extern char *tgoto ();
-
-#endif /* HAVE_TERMCAP_H */
-
-#endif /* !_RLTCAP_H_ */
diff --git a/readline/terminal.c b/readline/terminal.c
deleted file mode 100644
index 1d2fead7768..00000000000
--- a/readline/terminal.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* terminal.c -- controlling the terminal with termcap. */
-
-/* Copyright (C) 1996 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include "posixstat.h"
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* HAVE_SYS_FILE_H */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <signal.h>
-#include <stdio.h>
-#include <setjmp.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
-# include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
-
-#include "rltty.h"
-#include "tcap.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-/* Variables and functions imported from readline.c */
-extern FILE *_rl_in_stream, *_rl_out_stream;
-extern int readline_echoing_p;
-extern int _rl_bell_preference;
-extern Keymap _rl_keymap;
-
-/* Functions imported from bind.c */
-extern void _rl_bind_if_unbound ();
-
-/* Functions imported from shell.c */
-extern void set_lines_and_columns ();
-extern char *get_env_value ();
-
-/* **************************************************************** */
-/* */
-/* Terminal and Termcap */
-/* */
-/* **************************************************************** */
-
-static char *term_buffer = (char *)NULL;
-static char *term_string_buffer = (char *)NULL;
-
-static int tcap_initialized;
-
-/* Non-zero means this terminal can't really do anything. */
-static int dumb_term;
-
-#if !defined (__linux__)
-# if defined (__EMX__) || defined (NEED_EXTERN_PC)
-extern
-# endif /* __EMX__ || NEED_EXTERN_PC */
-char PC, *BC, *UP;
-#endif /* __linux__ */
-
-/* Some strings to control terminal actions. These are output by tputs (). */
-char *term_goto, *term_clreol, *term_clrpag, *term_backspace;
-char *term_cr, *term_pc;
-
-/* Non-zero if we determine that the terminal can do character insertion. */
-int terminal_can_insert = 0;
-
-/* How to insert characters. */
-char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
-
-/* How to delete characters. */
-char *term_dc, *term_DC;
-
-#if defined (HACK_TERMCAP_MOTION)
-char *term_forward_char;
-#endif /* HACK_TERMCAP_MOTION */
-
-/* How to go up a line. */
-char *term_up;
-
-/* A visible bell, if the terminal can be made to flash the screen. */
-static char *visible_bell;
-
-/* Non-zero means the terminal can auto-wrap lines. */
-int _rl_term_autowrap;
-
-/* Non-zero means that this terminal has a meta key. */
-static int term_has_meta;
-
-/* The sequences to write to turn on and off the meta key, if this
- terminal has one. */
-static char *term_mm, *term_mo;
-
-/* The key sequences output by the arrow keys, if this terminal has any. */
-static char *term_ku, *term_kd, *term_kr, *term_kl;
-
-/* How to initialize and reset the arrow keys, if this terminal has any. */
-static char *term_ks, *term_ke;
-
-/* The key sequences sent by the Home and End keys, if any. */
-static char *term_kh, *term_kH;
-
-/* Variables that hold the screen dimensions, used by the display code. */
-int screenwidth, screenheight, screenchars;
-
-/* Non-zero means the user wants to enable the keypad. */
-int _rl_enable_keypad;
-
-/* Non-zero means the user wants to enable a meta key. */
-int _rl_enable_meta = 1;
-
-/* Get readline's idea of the screen size. TTY is a file descriptor open
- to the terminal. If IGNORE_ENV is true, we do not pay attention to the
- values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
- non-null serve to check whether or not we have initialized termcap. */
-void
-_rl_get_screen_size (tty, ignore_env)
- int tty, ignore_env;
-{
- char *ss;
-#if defined (TIOCGWINSZ)
- struct winsize window_size;
-#endif /* TIOCGWINSZ */
-#if defined (__EMX__)
- int sz[2];
-#endif
-
-#if defined (TIOCGWINSZ)
- if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
- {
- screenwidth = (int) window_size.ws_col;
- screenheight = (int) window_size.ws_row;
- }
-#endif /* TIOCGWINSZ */
-
-#if defined (__EMX__)
- _scrsize (sz);
- screenwidth = sz[0];
- screenheight = sz[1];
-#endif
-
- /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
- is unset. */
- if (screenwidth <= 0)
- {
- if (ignore_env == 0 && (ss = get_env_value ("COLUMNS")))
- screenwidth = atoi (ss);
-
- if (screenwidth <= 0 && term_string_buffer)
- screenwidth = tgetnum ("co");
- }
-
- /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
- is unset. */
- if (screenheight <= 0)
- {
- if (ignore_env == 0 && (ss = get_env_value ("LINES")))
- screenheight = atoi (ss);
-
- if (screenheight <= 0 && term_string_buffer)
- screenheight = tgetnum ("li");
- }
-
- /* If all else fails, default to 80x24 terminal. */
- if (screenwidth <= 1)
- screenwidth = 80;
-
- if (screenheight <= 0)
- screenheight = 24;
-
- /* If we're being compiled as part of bash, set the environment
- variables $LINES and $COLUMNS to new values. Otherwise, just
- do a pair of putenv () or setenv () calls. */
- set_lines_and_columns (screenheight, screenwidth);
-
- if (!_rl_term_autowrap)
- screenwidth--;
-
- screenchars = screenwidth * screenheight;
-}
-
-void
-_rl_set_screen_size (rows, cols)
- int rows, cols;
-{
- screenheight = rows;
- screenwidth = cols;
-
- if (_rl_term_autowrap == 0)
- screenwidth--;
-
- screenchars = screenwidth * screenheight;
-}
-
-extern void _rl_redisplay_after_sigwinch();
-
-void
-rl_resize_terminal ()
-{
- if (readline_echoing_p)
- {
- _rl_get_screen_size (fileno (rl_instream), 1);
- _rl_redisplay_after_sigwinch ();
- }
-}
-
-struct _tc_string {
- const char *tc_var;
- char **tc_value;
-};
-
-/* This should be kept sorted, just in case we decide to change the
- search algorithm to something smarter. */
-static struct _tc_string tc_strings[] =
-{
- {"DC", &term_DC},
- {"IC", &term_IC},
- {"ce", &term_clreol},
- {"cl", &term_clrpag},
- {"cr", &term_cr},
- {"dc", &term_dc},
- {"ei", &term_ei},
- {"ic", &term_ic},
- {"im", &term_im},
- {"kd", &term_kd},
- {"kh", &term_kh}, /* home */
- {"kH", &term_kH}, /* end */
- {"kl", &term_kl},
- {"kr", &term_kr},
- {"ku", &term_ku},
- {"ks", &term_ks},
- {"ke", &term_ke},
- {"le", &term_backspace},
- {"mm", &term_mm},
- {"mo", &term_mo},
-#if defined (HACK_TERMCAP_MOTION)
- {"nd", &term_forward_char},
-#endif
- {"pc", &term_pc},
- {"up", &term_up},
- {"vb", &visible_bell},
-};
-
-#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
-
-/* Read the desired terminal capability strings into BP. The capabilities
- are described in the TC_STRINGS table. */
-static void
-get_term_capabilities (bp)
- char **bp;
-{
- register int i;
-
- for (i = 0; i < (int) NUM_TC_STRINGS; i++)
- *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
- tcap_initialized = 1;
-}
-
-int
-_rl_init_terminal_io (terminal_name)
- char *terminal_name;
-{
-#if defined (__GO32__)
- screenwidth = ScreenCols ();
- screenheight = ScreenRows ();
- screenchars = screenwidth * screenheight;
- term_cr = (char*) "\r";
- term_im = term_ei = term_ic = term_IC = (char *)NULL;
- term_up = term_dc = term_DC = visible_bell = (char *)NULL;
-
- /* Does the __GO32__ have a meta key? I don't know. */
- term_has_meta = 0;
- term_mm = term_mo = (char *)NULL;
-
- /* It probably has arrow keys, but I don't know what they are. */
- term_ku = term_kd = term_kr = term_kl = (char *)NULL;
-
-#if defined (HACK_TERMCAP_MOTION)
- term_forward_char = (char *)NULL;
-#endif /* HACK_TERMCAP_MOTION */
- terminal_can_insert = _rl_term_autowrap = 0;
- return;
-#else /* !__GO32__ */
-
- const char *term;
- char *buffer;
- int tty;
- Keymap xkeymap;
-
- term = terminal_name ? terminal_name : get_env_value ("TERM");
-
- if (term_string_buffer == 0)
- term_string_buffer = xmalloc (2032);
-
- if (term_buffer == 0)
- term_buffer = xmalloc (4080);
-
- buffer = term_string_buffer;
-
- term_clrpag = term_cr = term_clreol = (char *)NULL;
-
- if (term == 0)
- term = "dumb";
-
- if (tgetent (term_buffer, term) <= 0)
- {
- dumb_term = 1;
- screenwidth = 79;
- screenheight = 24;
- screenchars = 79 * 24;
- term_cr = (char*) "\r";
- term_im = term_ei = term_ic = term_IC = (char *)NULL;
- term_up = term_dc = term_DC = visible_bell = (char *)NULL;
- term_ku = term_kd = term_kl = term_kr = (char *)NULL;
-#if defined (HACK_TERMCAP_MOTION)
- term_forward_char = (char *)NULL;
-#endif
- terminal_can_insert = 0;
- return 0;
- }
-
- get_term_capabilities (&buffer);
-
- /* Set up the variables that the termcap library expects the application
- to provide. */
- PC = term_pc ? *term_pc : 0;
- BC = term_backspace;
- UP = term_up;
-
- if (!term_cr)
- term_cr = (char*) "\r";
-
- tty = rl_instream ? fileno (rl_instream) : 0;
-
- screenwidth = screenheight = 0;
-
- _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
-
- _rl_get_screen_size (tty, 0);
-
- /* "An application program can assume that the terminal can do
- character insertion if *any one of* the capabilities `IC',
- `im', `ic' or `ip' is provided." But we can't do anything if
- only `ip' is provided, so... */
- terminal_can_insert = (term_IC || term_im || term_ic);
-
- /* Check to see if this terminal has a meta key and clear the capability
- variables if there is none. */
- term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
- if (!term_has_meta)
- term_mm = term_mo = (char *)NULL;
-
- /* Attempt to find and bind the arrow keys. Do not override already
- bound keys in an overzealous attempt, however. */
- xkeymap = _rl_keymap;
-
- _rl_keymap = emacs_standard_keymap;
- _rl_bind_if_unbound (term_ku, rl_get_previous_history);
- _rl_bind_if_unbound (term_kd, rl_get_next_history);
- _rl_bind_if_unbound (term_kr, rl_forward);
- _rl_bind_if_unbound (term_kl, rl_backward);
-
- _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
- _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
-
-#if defined (VI_MODE)
- _rl_keymap = vi_movement_keymap;
- _rl_bind_if_unbound (term_ku, rl_get_previous_history);
- _rl_bind_if_unbound (term_kd, rl_get_next_history);
- _rl_bind_if_unbound (term_kr, rl_forward);
- _rl_bind_if_unbound (term_kl, rl_backward);
-
- _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */
- _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */
-#endif /* VI_MODE */
-
- _rl_keymap = xkeymap;
-
-#endif /* !__GO32__ */
- return 0;
-}
-
-char *
-rl_get_termcap (cap)
- char *cap;
-{
- register int i;
-
- if (tcap_initialized == 0)
- return ((char *)NULL);
- for (i = 0; i < (int) NUM_TC_STRINGS; i++)
- {
- if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
- return *(tc_strings[i].tc_value);
- }
- return ((char *)NULL);
-}
-
-/* Re-initialize the terminal considering that the TERM/TERMCAP variable
- has changed. */
-int
-rl_reset_terminal (terminal_name)
- char *terminal_name;
-{
- _rl_init_terminal_io (terminal_name);
- return 0;
-}
-
-/* A function for the use of tputs () */
-#ifdef _MINIX
-void
-_rl_output_character_function (c)
- int c;
-{
- putc (c, _rl_out_stream);
-}
-#else /* !_MINIX */
-int
-_rl_output_character_function (c)
- int c;
-{
- return putc (c, _rl_out_stream);
-}
-#endif /* !_MINIX */
-/* Write COUNT characters from STRING to the output stream. */
-void
-_rl_output_some_chars (string, count)
- char *string;
- int count;
-{
- fwrite (string, 1, count, _rl_out_stream);
-}
-
-/* Move the cursor back. */
-int
-_rl_backspace (count)
- int count;
-{
- register int i;
-
-#if !defined (__GO32__)
- if (term_backspace)
- for (i = 0; i < count; i++)
- tputs (term_backspace, 1, _rl_output_character_function);
- else
-#endif /* !__GO32__ */
- for (i = 0; i < count; i++)
- putc ('\b', _rl_out_stream);
- return 0;
-}
-
-/* Move to the start of the next line. */
-int
-crlf ()
-{
-#if defined (NEW_TTY_DRIVER)
- if (term_cr)
- tputs (term_cr, 1, _rl_output_character_function);
-#endif /* NEW_TTY_DRIVER */
- putc ('\n', _rl_out_stream);
- return 0;
-}
-
-/* Ring the terminal bell. */
-int
-ding ()
-{
- if (readline_echoing_p)
- {
-#if !defined (__GO32__)
- switch (_rl_bell_preference)
- {
- case NO_BELL:
- default:
- break;
- case VISIBLE_BELL:
- if (visible_bell)
- {
- tputs (visible_bell, 1, _rl_output_character_function);
- break;
- }
- /* FALLTHROUGH */
- case AUDIBLE_BELL:
- fprintf (stderr, "\007");
- fflush (stderr);
- break;
- }
-#else /* __GO32__ */
- fprintf (stderr, "\007");
- fflush (stderr);
-#endif /* __GO32__ */
- return (0);
- }
- return (-1);
-}
-
-/* **************************************************************** */
-/* */
-/* Controlling the Meta Key and Keypad */
-/* */
-/* **************************************************************** */
-
-void
-_rl_enable_meta_key ()
-{
- if (term_has_meta && term_mm)
- tputs (term_mm, 1, _rl_output_character_function);
-}
-
-void
-_rl_control_keypad (on)
- int on;
-{
- if (on && term_ks)
- tputs (term_ks, 1, _rl_output_character_function);
- else if (!on && term_ke)
- tputs (term_ke, 1, _rl_output_character_function);
-}
diff --git a/readline/tilde.c b/readline/tilde.c
deleted file mode 100644
index 05c9ed741ed..00000000000
--- a/readline/tilde.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
-
-/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <sys/types.h>
-#include <pwd.h>
-
-#include "tilde.h"
-
-#if !defined (HAVE_GETPW_DECLS)
-extern struct passwd *getpwuid (), *getpwnam ();
-#endif /* !HAVE_GETPW_DECLS */
-
-#if !defined (savestring)
-extern char *xmalloc ();
-# ifndef strcpy
-extern char *strcpy ();
-# endif
-#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
-#endif /* !savestring */
-
-#if !defined (NULL)
-# if defined (__STDC__)
-# define NULL ((void *) 0)
-# else
-# define NULL 0x0
-# endif /* !__STDC__ */
-#endif /* !NULL */
-
-#if defined (TEST) || defined (STATIC_MALLOC)
-static char *xmalloc (), *xrealloc ();
-#else
-extern char *xmalloc (), *xrealloc ();
-#endif /* TEST || STATIC_MALLOC */
-
-/* If being compiled as part of bash, these will be satisfied from
- variables.o. If being compiled as part of readline, they will
- be satisfied from shell.o. */
-extern char *get_home_dir ();
-extern char *get_env_value ();
-
-/* The default value of tilde_additional_prefixes. This is set to
- whitespace preceding a tilde so that simple programs which do not
- perform any word separation get desired behaviour. */
-static const char *default_prefixes[] =
- { " ~", "\t~", (char *)NULL };
-
-/* The default value of tilde_additional_suffixes. This is set to
- whitespace or newline so that simple programs which do not
- perform any word separation get desired behaviour. */
-static const char *default_suffixes[] =
- { " ", "\n", (char *)NULL };
-
-/* If non-null, this contains the address of a function that the application
- wants called before trying the standard tilde expansions. The function
- is called with the text sans tilde, and returns a malloc()'ed string
- which is the expansion, or a NULL pointer if the expansion fails. */
-CPFunction *tilde_expansion_preexpansion_hook = (CPFunction *)NULL;
-
-/* If non-null, this contains the address of a function to call if the
- standard meaning for expanding a tilde fails. The function is called
- with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
- which is the expansion, or a NULL pointer if there is no expansion. */
-CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
-
-/* When non-null, this is a NULL terminated array of strings which
- are duplicates for a tilde prefix. Bash uses this to expand
- `=~' and `:~'. */
-const char ** tilde_additional_prefixes = default_prefixes;
-
-/* When non-null, this is a NULL terminated array of strings which match
- the end of a username, instead of just "/". Bash sets this to
- `:' and `=~'. */
-const char **tilde_additional_suffixes = default_suffixes;
-
-/* Find the start of a tilde expansion in STRING, and return the index of
- the tilde which starts the expansion. Place the length of the text
- which identified this tilde starter in LEN, excluding the tilde itself. */
-static int
-tilde_find_prefix (string, len)
- char *string;
- int *len;
-{
- register int i, j, string_len;
- register const char **prefixes = tilde_additional_prefixes;
-
- string_len = strlen (string);
- *len = 0;
-
- if (*string == '\0' || *string == '~')
- return (0);
-
- if (prefixes)
- {
- for (i = 0; i < string_len; i++)
- {
- for (j = 0; prefixes[j]; j++)
- {
- if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
- {
- *len = strlen (prefixes[j]) - 1;
- return (i + *len);
- }
- }
- }
- }
- return (string_len);
-}
-
-/* Find the end of a tilde expansion in STRING, and return the index of
- the character which ends the tilde definition. */
-static int
-tilde_find_suffix (string)
- char *string;
-{
- register int i, j, string_len;
- register const char **suffixes;
-
- suffixes = tilde_additional_suffixes;
- string_len = strlen (string);
-
- for (i = 0; i < string_len; i++)
- {
- if (string[i] == '/' /* || !string[i] */)
- break;
-
- for (j = 0; suffixes && suffixes[j]; j++)
- {
- if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
- return (i);
- }
- }
- return (i);
-}
-
-/* Return a new string which is the result of tilde expanding STRING. */
-char *
-tilde_expand (string)
- char *string;
-{
- char *result;
- int result_size, result_index;
-
- result_index = result_size = 0;
- if ((result = strchr (string, '~')))
- result = xmalloc (result_size = (strlen (string) + 16));
- else
- result = xmalloc (result_size = (strlen (string) + 1));
-
- /* Scan through STRING expanding tildes as we come to them. */
- while (1)
- {
- register int start, end;
- char *tilde_word, *expansion;
- int len;
-
- /* Make START point to the tilde which starts the expansion. */
- start = tilde_find_prefix (string, &len);
-
- /* Copy the skipped text into the result. */
- if ((result_index + start + 1) > result_size)
- result = xrealloc (result, 1 + (result_size += (start + 20)));
-
- strncpy (result + result_index, string, start);
- result_index += start;
-
- /* Advance STRING to the starting tilde. */
- string += start;
-
- /* Make END be the index of one after the last character of the
- username. */
- end = tilde_find_suffix (string);
-
- /* If both START and END are zero, we are all done. */
- if (!start && !end)
- break;
-
- /* Expand the entire tilde word, and copy it into RESULT. */
- tilde_word = xmalloc (1 + end);
- strncpy (tilde_word, string, end);
- tilde_word[end] = '\0';
- string += end;
-
- expansion = tilde_expand_word (tilde_word);
- free (tilde_word);
-
- len = strlen (expansion);
- if ((result_index + len + 1) > result_size)
- result = xrealloc (result, 1 + (result_size += (len + 20)));
-
- strcpy (result + result_index, expansion);
- result_index += len;
- free (expansion);
- }
-
- result[result_index] = '\0';
-
- return (result);
-}
-
-/* Take FNAME and return the tilde prefix we want expanded. If LENP is
- non-null, the index of the end of the prefix into FNAME is returned in
- the location it points to. */
-static char *
-isolate_tilde_prefix (fname, lenp)
- char *fname;
- int *lenp;
-{
- char *ret;
- int i;
-
- ret = xmalloc (strlen (fname));
- for (i = 1; fname[i] && fname[i] != '/'; i++)
- ret[i - 1] = fname[i];
- ret[i - 1] = '\0';
- if (lenp)
- *lenp = i;
- return ret;
-}
-
-/* Return a string that is PREFIX concatenated with SUFFIX starting at
- SUFFIND. */
-static char *
-glue_prefix_and_suffix (prefix, suffix, suffind)
- char *prefix, *suffix;
- int suffind;
-{
- char *ret;
- int plen, slen;
-
- plen = (prefix && *prefix) ? strlen (prefix) : 0;
- slen = strlen (suffix + suffind);
- ret = xmalloc (plen + slen + 1);
- if (prefix && *prefix)
- strcpy (ret, prefix);
- strcpy (ret + plen, suffix + suffind);
- return ret;
-}
-
-/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
- tilde. If there is no expansion, call tilde_expansion_failure_hook.
- This always returns a newly-allocated string, never static storage. */
-char *
-tilde_expand_word (filename)
- char *filename;
-{
- char *dirname, *expansion, *username;
- int user_len;
- struct passwd *user_entry;
-
- if (filename == 0)
- return ((char *)NULL);
-
- if (*filename != '~')
- return (savestring (filename));
-
- /* A leading `~/' or a bare `~' is *always* translated to the value of
- $HOME or the home directory of the current user, regardless of any
- preexpansion hook. */
- if (filename[1] == '\0' || filename[1] == '/')
- {
- /* Prefix $HOME to the rest of the string. */
- expansion = get_env_value ("HOME");
-
- /* If there is no HOME variable, look up the directory in
- the password database. */
- if (expansion == 0)
- expansion = get_home_dir ();
-
- return (glue_prefix_and_suffix (expansion, filename, 1));
- }
-
- username = isolate_tilde_prefix (filename, &user_len);
-
- if (tilde_expansion_preexpansion_hook)
- {
- expansion = (*tilde_expansion_preexpansion_hook) (username);
- if (expansion)
- {
- dirname = glue_prefix_and_suffix (expansion, filename, user_len);
- free (username);
- free (expansion);
- return (dirname);
- }
- }
-
- /* No preexpansion hook, or the preexpansion hook failed. Look in the
- password database. */
- dirname = (char *)NULL;
- user_entry = getpwnam (username);
- if (user_entry == 0)
- {
- /* If the calling program has a special syntax for expanding tildes,
- and we couldn't find a standard expansion, then let them try. */
- if (tilde_expansion_failure_hook)
- {
- expansion = (*tilde_expansion_failure_hook) (username);
- if (expansion)
- {
- dirname = glue_prefix_and_suffix (expansion, filename, user_len);
- free (expansion);
- }
- }
- free (username);
- /* If we don't have a failure hook, or if the failure hook did not
- expand the tilde, return a copy of what we were passed. */
- if (dirname == 0)
- dirname = savestring (filename);
- }
- else
- {
- free (username);
- dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
- }
-
- endpwent ();
- return (dirname);
-}
-
-
-#if defined (TEST)
-#undef NULL
-#include <stdio.h>
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- char *result, line[512];
- int done = 0;
-
- while (!done)
- {
- printf ("~expand: ");
- fflush (stdout);
-
- if (!gets (line))
- strcpy (line, "done");
-
- if ((strcmp (line, "done") == 0) ||
- (strcmp (line, "quit") == 0) ||
- (strcmp (line, "exit") == 0))
- {
- done = 1;
- break;
- }
-
- result = tilde_expand (line);
- printf (" --> %s\n", result);
- free (result);
- }
- exit (0);
-}
-
-static void memory_error_and_abort ();
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- char *temp;
-
- if (!pointer)
- temp = (char *)malloc (bytes);
- else
- temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
-
- return (temp);
-}
-
-static void
-memory_error_and_abort ()
-{
- fprintf (stderr, "readline: out of virtual memory\n");
- abort ();
-}
-
-/*
- * Local variables:
- * compile-command: "gcc -g -DTEST -o tilde tilde.c"
- * end:
- */
-#endif /* TEST */
diff --git a/readline/tilde.h b/readline/tilde.h
deleted file mode 100644
index 45eea1b66e5..00000000000
--- a/readline/tilde.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* tilde.h: Externally available variables and function in libtilde.a. */
-
-/* Copyright (C) 1992 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The 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 1, or (at your option)
- any later version.
-
- The 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_TILDE_H_)
-# define _TILDE_H_
-
-/* Function pointers can be declared as (Function *)foo. */
-#if !defined (_FUNCTION_DEF)
-# define _FUNCTION_DEF
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();
-typedef char **CPPFunction ();
-#endif /* _FUNCTION_DEF */
-
-/* If non-null, this contains the address of a function that the application
- wants called before trying the standard tilde expansions. The function
- is called with the text sans tilde, and returns a malloc()'ed string
- which is the expansion, or a NULL pointer if the expansion fails. */
-extern CPFunction *tilde_expansion_preexpansion_hook;
-
-/* If non-null, this contains the address of a function to call if the
- standard meaning for expanding a tilde fails. The function is called
- with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
- which is the expansion, or a NULL pointer if there is no expansion. */
-extern CPFunction *tilde_expansion_failure_hook;
-
-/* When non-null, this is a NULL terminated array of strings which
- are duplicates for a tilde prefix. Bash uses this to expand
- `=~' and `:~'. */
-extern const char **tilde_additional_prefixes;
-
-/* When non-null, this is a NULL terminated array of strings which match
- the end of a username, instead of just "/". Bash sets this to
- `:' and `=~'. */
-extern const char **tilde_additional_suffixes;
-
-/* Return a new string which is the result of tilde expanding STRING. */
-extern char *tilde_expand ();
-
-/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
- tilde. If there is no expansion, call tilde_expansion_failure_hook. */
-extern char *tilde_expand_word ();
-
-#endif /* _TILDE_H_ */
diff --git a/readline/undo.c b/readline/undo.c
deleted file mode 100644
index c8f4892b774..00000000000
--- a/readline/undo.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h> /* for _POSIX_VERSION */
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
-
-/* Non-zero tells rl_delete_text and rl_insert_text to not add to
- the undo list. */
-int _rl_doing_an_undo = 0;
-
-/* How many unclosed undo groups we currently have. */
-int _rl_undo_group_level = 0;
-
-/* The current undo list for THE_LINE. */
-UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
-
-/* **************************************************************** */
-/* */
-/* Undo, and Undoing */
-/* */
-/* **************************************************************** */
-
-/* Remember how to undo something. Concatenate some undos if that
- seems right. */
-void
-rl_add_undo (what, start, end, text)
- enum undo_code what;
- int start, end;
- char *text;
-{
- UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
- temp->what = what;
- temp->start = start;
- temp->end = end;
- temp->text = text;
- temp->next = rl_undo_list;
- rl_undo_list = temp;
-}
-
-/* Free the existing undo list. */
-void
-free_undo_list ()
-{
- while (rl_undo_list)
- {
- UNDO_LIST *release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
-
- if (release->what == UNDO_DELETE)
- free (release->text);
-
- free (release);
- }
- rl_undo_list = (UNDO_LIST *)NULL;
-}
-
-/* Undo the next thing in the list. Return 0 if there
- is nothing to undo, or non-zero if there was. */
-int
-rl_do_undo ()
-{
- UNDO_LIST *release;
- int waiting_for_begin = 0;
- int start = 0, end = 0;
-
-#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
-
- do
- {
- if (!rl_undo_list)
- return (0);
-
- _rl_doing_an_undo = 1;
-
- /* To better support vi-mode, a start or end value of -1 means
- rl_point, and a value of -2 means rl_end. */
- if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
- {
- start = TRANS (rl_undo_list->start);
- end = TRANS (rl_undo_list->end);
- }
-
- switch (rl_undo_list->what)
- {
- /* Undoing deletes means inserting some text. */
- case UNDO_DELETE:
- rl_point = start;
- rl_insert_text (rl_undo_list->text);
- free (rl_undo_list->text);
- break;
-
- /* Undoing inserts means deleting some text. */
- case UNDO_INSERT:
- rl_delete_text (start, end);
- rl_point = start;
- break;
-
- /* Undoing an END means undoing everything 'til we get to a BEGIN. */
- case UNDO_END:
- waiting_for_begin++;
- break;
-
- /* Undoing a BEGIN means that we are done with this group. */
- case UNDO_BEGIN:
- if (waiting_for_begin)
- waiting_for_begin--;
- else
- ding ();
- break;
- }
-
- _rl_doing_an_undo = 0;
-
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
- free (release);
- }
- while (waiting_for_begin);
-
- return (1);
-}
-#undef TRANS
-
-int
-_rl_fix_last_undo_of_type (type, start, end)
- int type, start, end;
-{
- UNDO_LIST *rl;
-
- for (rl = rl_undo_list; rl; rl = rl->next)
- {
- if ((int) rl->what == type)
- {
- rl->start = start;
- rl->end = end;
- return 0;
- }
- }
- return 1;
-}
-
-/* Begin a group. Subsequent undos are undone as an atomic operation. */
-int
-rl_begin_undo_group ()
-{
- rl_add_undo (UNDO_BEGIN, 0, 0, 0);
- _rl_undo_group_level++;
- return 0;
-}
-
-/* End an undo group started with rl_begin_undo_group (). */
-int
-rl_end_undo_group ()
-{
- rl_add_undo (UNDO_END, 0, 0, 0);
- _rl_undo_group_level--;
- return 0;
-}
-
-/* Save an undo entry for the text from START to END. */
-int
-rl_modifying (start, end)
- int start, end;
-{
- if (start > end)
- {
- SWAP (start, end);
- }
-
- if (start != end)
- {
- char *temp = rl_copy_text (start, end);
- rl_begin_undo_group ();
- rl_add_undo (UNDO_DELETE, start, end, temp);
- rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
- rl_end_undo_group ();
- }
- return 0;
-}
-
-/* Revert the current line to its previous state. */
-int
-rl_revert_line (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- if (!rl_undo_list)
- ding ();
- else
- {
- while (rl_undo_list)
- rl_do_undo ();
- }
- return 0;
-}
-
-/* Do some undoing of things that were done. */
-int
-rl_undo_command (int count, int key __attribute__((unused)))
-{
- if (count < 0)
- return 0; /* Nothing to do. */
-
- while (count)
- {
- if (rl_do_undo ())
- count--;
- else
- {
- ding ();
- break;
- }
- }
- return 0;
-}
diff --git a/readline/util.c b/readline/util.c
deleted file mode 100644
index bcd8f3bc5b2..00000000000
--- a/readline/util.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/* util.c -- readline utility functions */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include "posixjmp.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h> /* for _POSIX_VERSION */
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-#include <ctype.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-#if defined (TIOCSTAT_IN_SYS_IOCTL)
-# include <sys/ioctl.h>
-#endif /* TIOCSTAT_IN_SYS_IOCTL */
-
-/* Some standard library routines. */
-#include "readline.h"
-
-#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
-
-/* Pseudo-globals imported from readline.c */
-extern int readline_echoing_p;
-extern procenv_t readline_top_level;
-extern int rl_line_buffer_len;
-extern Function *rl_last_func;
-
-extern int _rl_defining_kbd_macro;
-extern char *_rl_executing_macro;
-
-/* Pseudo-global functions imported from other library files. */
-extern void _rl_replace_text ();
-extern void _rl_pop_executing_macro ();
-extern void _rl_set_the_line ();
-extern void _rl_init_argument ();
-
-extern char *xmalloc (), *xrealloc ();
-
-/* **************************************************************** */
-/* */
-/* Utility Functions */
-/* */
-/* **************************************************************** */
-
-/* Return 0 if C is not a member of the class of characters that belong
- in words, or 1 if it is. */
-
-int _rl_allow_pathname_alphabetic_chars = 0;
-static const char *pathname_alphabetic_chars = "/-_=~.#$";
-
-int
-alphabetic (c)
- int c;
-{
- if (ALPHABETIC (c))
- return (1);
-
- return (_rl_allow_pathname_alphabetic_chars &&
- strchr (pathname_alphabetic_chars, c) != NULL);
-}
-
-/* How to abort things. */
-int
-_rl_abort_internal ()
-{
- ding ();
- rl_clear_message ();
- _rl_init_argument ();
- rl_pending_input = 0;
-
- _rl_defining_kbd_macro = 0;
- while (_rl_executing_macro)
- _rl_pop_executing_macro ();
-
- rl_last_func = (Function *)NULL;
- longjmp (readline_top_level, 1);
- return (0);
-}
-
-int
-rl_abort (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
- return (_rl_abort_internal ());
-}
-
-int
-rl_tty_status (int count __attribute__((unused)),
- int key __attribute__((unused)))
-{
-#if defined (TIOCSTAT)
- ioctl (1, TIOCSTAT, (char *)0);
- rl_refresh_line (count, key);
-#else
- ding ();
-#endif
- return 0;
-}
-
-/* Return a copy of the string between FROM and TO.
- FROM is inclusive, TO is not. */
-char *
-rl_copy_text (from, to)
- int from, to;
-{
- register int length;
- char *copy;
-
- /* Fix it if the caller is confused. */
- if (from > to)
- SWAP (from, to);
-
- length = to - from;
- copy = xmalloc (1 + length);
- strncpy (copy, rl_line_buffer + from, length);
- copy[length] = '\0';
- return (copy);
-}
-
-/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
- LEN characters. */
-void
-rl_extend_line_buffer (len)
- int len;
-{
- while (len >= rl_line_buffer_len)
- {
- rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
- rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len);
- }
-
- _rl_set_the_line ();
-}
-
-
-/* A function for simple tilde expansion. */
-int
-rl_tilde_expand (int ignore __attribute__((unused)),
- int key __attribute__((unused)))
-{
- register int start, end;
- char *homedir, *temp;
- int len;
-
- end = rl_point;
- start = end - 1;
-
- if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
- {
- homedir = tilde_expand ("~");
- _rl_replace_text (homedir, start, end);
- return (0);
- }
- else if (rl_line_buffer[start] != '~')
- {
- for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
- ;
- start++;
- }
-
- end = start;
- do
- end++;
- while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
-
- if (whitespace (rl_line_buffer[end]) || end >= rl_end)
- end--;
-
- /* If the first character of the current word is a tilde, perform
- tilde expansion and insert the result. If not a tilde, do
- nothing. */
- if (rl_line_buffer[start] == '~')
- {
- len = end - start + 1;
- temp = xmalloc (len + 1);
- strncpy (temp, rl_line_buffer + start, len);
- temp[len] = '\0';
- homedir = tilde_expand (temp);
- free (temp);
-
- _rl_replace_text (homedir, start, end);
- }
-
- return (0);
-}
-
-/* **************************************************************** */
-/* */
-/* String Utility Functions */
-/* */
-/* **************************************************************** */
-
-/* Determine if s2 occurs in s1. If so, return a pointer to the
- match in s1. The compare is case insensitive. */
-char *
-_rl_strindex (s1, s2)
- register char *s1, *s2;
-{
- register int i, l, len;
-
- for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
- if (_rl_strnicmp (s1 + i, s2, l) == 0)
- return (s1 + i);
- return ((char *)NULL);
-}
-
-#if !defined (HAVE_STRCASECMP)
-/* Compare at most COUNT characters from string1 to string2. Case
- doesn't matter. */
-int
-_rl_strnicmp (string1, string2, count)
- char *string1, *string2;
- int count;
-{
- register char ch1, ch2;
-
- while (count)
- {
- ch1 = *string1++;
- ch2 = *string2++;
- if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
- count--;
- else
- break;
- }
- return (count);
-}
-
-/* strcmp (), but caseless. */
-int
-_rl_stricmp (string1, string2)
- char *string1, *string2;
-{
- register char ch1, ch2;
-
- while (*string1 && *string2)
- {
- ch1 = *string1++;
- ch2 = *string2++;
- if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
- return (1);
- }
- return (*string1 - *string2);
-}
-#endif /* !HAVE_STRCASECMP */
-
-/* Stupid comparison routine for qsort () ing strings. */
-int
-_rl_qsort_string_compare (s1, s2)
- char **s1, **s2;
-{
-#if defined (HAVE_STRCOLL)
- return (strcoll (*s1, *s2));
-#else
- int result;
-
- result = **s1 - **s2;
- if (result == 0)
- result = strcmp (*s1, *s2);
-
- return result;
-#endif
-}
-
-/* Function equivalents for the macros defined in chartypes.h. */
-#undef _rl_uppercase_p
-int
-_rl_uppercase_p (c)
- int c;
-{
- return (isupper (c));
-}
-
-#undef _rl_lowercase_p
-int
-_rl_lowercase_p (c)
- int c;
-{
- return (islower (c));
-}
-
-#undef _rl_pure_alphabetic
-int
-_rl_pure_alphabetic (c)
- int c;
-{
- return (isupper (c) || islower (c));
-}
-
-#undef _rl_digit_p
-int
-_rl_digit_p (c)
- int c;
-{
- return (isdigit (c));
-}
-
-#undef _rl_to_lower
-int
-_rl_to_lower (c)
- int c;
-{
- return (isupper (c) ? tolower (c) : c);
-}
-
-#undef _rl_to_upper
-int
-_rl_to_upper (c)
- int c;
-{
- return (islower (c) ? toupper (c) : c);
-}
-
-#undef _rl_digit_value
-int
-_rl_digit_value (c)
- int c;
-{
- return (isdigit (c) ? c - '0' : c);
-}
-
-/* Backwards compatibility, now that savestring has been removed from
- all `public' readline header files. */
-#undef _rl_savestring
-char *
-_rl_savestring (s)
- char *s;
-{
- return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s)));
-}
diff --git a/readline/vi_keymap.c b/readline/vi_keymap.c
deleted file mode 100644
index 14929a31930..00000000000
--- a/readline/vi_keymap.c
+++ /dev/null
@@ -1,877 +0,0 @@
-/* vi_keymap.c -- the keymap for vi_mode in readline (). */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (BUFSIZ)
-#include <stdio.h>
-#endif /* !BUFSIZ */
-
-#include "readline.h"
-
-#if 0
-extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
-#endif
-
-/* The keymap arrays for handling vi mode. */
-KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
- /* The regular control keys come first. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Control-a */
- { ISFUNC, (Function *)0x0 }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, rl_vi_eof_maybe }, /* Control-d */
- { ISFUNC, rl_emacs_editing_mode }, /* Control-e */
- { ISFUNC, (Function *)0x0 }, /* Control-f */
- { ISFUNC, rl_abort }, /* Control-g */
- { ISFUNC, rl_backward }, /* Control-h */
- { ISFUNC, (Function *)0x0 }, /* Control-i */
- { ISFUNC, rl_newline }, /* Control-j */
- { ISFUNC, rl_kill_line }, /* Control-k */
- { ISFUNC, rl_clear_screen }, /* Control-l */
- { ISFUNC, rl_newline }, /* Control-m */
- { ISFUNC, rl_get_next_history }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, rl_get_previous_history }, /* Control-p */
- { ISFUNC, rl_quoted_insert }, /* Control-q */
- { ISFUNC, rl_reverse_search_history }, /* Control-r */
- { ISFUNC, rl_forward_search_history }, /* Control-s */
- { ISFUNC, rl_transpose_chars }, /* Control-t */
- { ISFUNC, rl_unix_line_discard }, /* Control-u */
- { ISFUNC, rl_quoted_insert }, /* Control-v */
- { ISFUNC, rl_unix_word_rubout }, /* Control-w */
- { ISFUNC, (Function *)0x0 }, /* Control-x */
- { ISFUNC, rl_yank }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
-
- { ISFUNC, (Function *)0x0 }, /* Control-[ */ /* vi_escape_keymap */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, rl_vi_undo }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_forward }, /* SPACE */
- { ISFUNC, (Function *)0x0 }, /* ! */
- { ISFUNC, (Function *)0x0 }, /* " */
- { ISFUNC, rl_insert_comment }, /* # */
- { ISFUNC, rl_end_of_line }, /* $ */
- { ISFUNC, rl_vi_match }, /* % */
- { ISFUNC, rl_vi_tilde_expand }, /* & */
- { ISFUNC, (Function *)0x0 }, /* ' */
- { ISFUNC, (Function *)0x0 }, /* ( */
- { ISFUNC, (Function *)0x0 }, /* ) */
- { ISFUNC, rl_vi_complete }, /* * */
- { ISFUNC, rl_get_next_history}, /* + */
- { ISFUNC, rl_vi_char_search }, /* , */
- { ISFUNC, rl_get_previous_history }, /* - */
- { ISFUNC, rl_vi_redo }, /* . */
- { ISFUNC, rl_vi_search }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_beg_of_line }, /* 0 */
- { ISFUNC, rl_vi_arg_digit }, /* 1 */
- { ISFUNC, rl_vi_arg_digit }, /* 2 */
- { ISFUNC, rl_vi_arg_digit }, /* 3 */
- { ISFUNC, rl_vi_arg_digit }, /* 4 */
- { ISFUNC, rl_vi_arg_digit }, /* 5 */
- { ISFUNC, rl_vi_arg_digit }, /* 6 */
- { ISFUNC, rl_vi_arg_digit }, /* 7 */
- { ISFUNC, rl_vi_arg_digit }, /* 8 */
- { ISFUNC, rl_vi_arg_digit }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* : */
- { ISFUNC, rl_vi_char_search }, /* ; */
- { ISFUNC, (Function *)0x0 }, /* < */
- { ISFUNC, rl_vi_complete }, /* = */
- { ISFUNC, (Function *)0x0 }, /* > */
- { ISFUNC, rl_vi_search }, /* ? */
- { ISFUNC, (Function *)0x0 }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_vi_append_eol }, /* A */
- { ISFUNC, rl_vi_prev_word}, /* B */
- { ISFUNC, rl_vi_change_to }, /* C */
- { ISFUNC, rl_vi_delete_to }, /* D */
- { ISFUNC, rl_vi_end_word }, /* E */
- { ISFUNC, rl_vi_char_search }, /* F */
- { ISFUNC, rl_vi_fetch_history }, /* G */
- { ISFUNC, (Function *)0x0 }, /* H */
- { ISFUNC, rl_vi_insert_beg }, /* I */
- { ISFUNC, (Function *)0x0 }, /* J */
- { ISFUNC, (Function *)0x0 }, /* K */
- { ISFUNC, (Function *)0x0 }, /* L */
- { ISFUNC, (Function *)0x0 }, /* M */
- { ISFUNC, rl_vi_search_again }, /* N */
- { ISFUNC, (Function *)0x0 }, /* O */
- { ISFUNC, rl_vi_put }, /* P */
- { ISFUNC, (Function *)0x0 }, /* Q */
- { ISFUNC, rl_vi_replace }, /* R */
- { ISFUNC, rl_vi_subst }, /* S */
- { ISFUNC, rl_vi_char_search }, /* T */
- { ISFUNC, rl_revert_line }, /* U */
- { ISFUNC, (Function *)0x0 }, /* V */
- { ISFUNC, rl_vi_next_word }, /* W */
- { ISFUNC, rl_rubout }, /* X */
- { ISFUNC, rl_vi_yank_to }, /* Y */
- { ISFUNC, (Function *)0x0 }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* [ */
- { ISFUNC, rl_vi_complete }, /* \ */
- { ISFUNC, (Function *)0x0 }, /* ] */
- { ISFUNC, rl_vi_first_print }, /* ^ */
- { ISFUNC, rl_vi_yank_arg }, /* _ */
- { ISFUNC, rl_vi_goto_mark }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, rl_vi_append_mode }, /* a */
- { ISFUNC, rl_vi_prev_word }, /* b */
- { ISFUNC, rl_vi_change_to }, /* c */
- { ISFUNC, rl_vi_delete_to }, /* d */
- { ISFUNC, rl_vi_end_word }, /* e */
- { ISFUNC, rl_vi_char_search }, /* f */
- { ISFUNC, (Function *)0x0 }, /* g */
- { ISFUNC, rl_backward }, /* h */
- { ISFUNC, rl_vi_insertion_mode }, /* i */
- { ISFUNC, rl_get_next_history }, /* j */
- { ISFUNC, rl_get_previous_history }, /* k */
- { ISFUNC, rl_forward }, /* l */
- { ISFUNC, rl_vi_set_mark }, /* m */
- { ISFUNC, rl_vi_search_again }, /* n */
- { ISFUNC, (Function *)0x0 }, /* o */
- { ISFUNC, rl_vi_put }, /* p */
- { ISFUNC, (Function *)0x0 }, /* q */
- { ISFUNC, rl_vi_change_char }, /* r */
- { ISFUNC, rl_vi_subst }, /* s */
- { ISFUNC, rl_vi_char_search }, /* t */
- { ISFUNC, rl_vi_undo }, /* u */
- { ISFUNC, (Function *)0x0 }, /* v */
- { ISFUNC, rl_vi_next_word }, /* w */
- { ISFUNC, rl_vi_delete }, /* x */
- { ISFUNC, rl_vi_yank_to }, /* y */
- { ISFUNC, (Function *)0x0 }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* { */
- { ISFUNC, rl_vi_column }, /* | */
- { ISFUNC, (Function *)0x0 }, /* } */
- { ISFUNC, rl_vi_change_case }, /* ~ */
- { ISFUNC, (Function *)0x0 }, /* RUBOUT */
-
-#if KEYMAP_SIZE > 128
- /* Undefined keys. */
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 }
-#endif /* KEYMAP_SIZE > 128 */
-};
-
-
-KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
- /* The regular control keys come first. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, rl_insert }, /* Control-a */
- { ISFUNC, rl_insert }, /* Control-b */
- { ISFUNC, rl_insert }, /* Control-c */
- { ISFUNC, rl_vi_eof_maybe }, /* Control-d */
- { ISFUNC, rl_insert }, /* Control-e */
- { ISFUNC, rl_insert }, /* Control-f */
- { ISFUNC, rl_insert }, /* Control-g */
- { ISFUNC, rl_rubout }, /* Control-h */
- { ISFUNC, rl_complete }, /* Control-i */
- { ISFUNC, rl_newline }, /* Control-j */
- { ISFUNC, rl_insert }, /* Control-k */
- { ISFUNC, rl_insert }, /* Control-l */
- { ISFUNC, rl_newline }, /* Control-m */
- { ISFUNC, rl_insert }, /* Control-n */
- { ISFUNC, rl_insert }, /* Control-o */
- { ISFUNC, rl_insert }, /* Control-p */
- { ISFUNC, rl_insert }, /* Control-q */
- { ISFUNC, rl_reverse_search_history }, /* Control-r */
- { ISFUNC, rl_forward_search_history }, /* Control-s */
- { ISFUNC, rl_transpose_chars }, /* Control-t */
- { ISFUNC, rl_unix_line_discard }, /* Control-u */
- { ISFUNC, rl_quoted_insert }, /* Control-v */
- { ISFUNC, rl_unix_word_rubout }, /* Control-w */
- { ISFUNC, rl_insert }, /* Control-x */
- { ISFUNC, rl_yank }, /* Control-y */
- { ISFUNC, rl_insert }, /* Control-z */
-
- { ISFUNC, rl_vi_movement_mode }, /* Control-[ */
- { ISFUNC, rl_insert }, /* Control-\ */
- { ISFUNC, rl_insert }, /* Control-] */
- { ISFUNC, rl_insert }, /* Control-^ */
- { ISFUNC, rl_vi_undo }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_insert }, /* SPACE */
- { ISFUNC, rl_insert }, /* ! */
- { ISFUNC, rl_insert }, /* " */
- { ISFUNC, rl_insert }, /* # */
- { ISFUNC, rl_insert }, /* $ */
- { ISFUNC, rl_insert }, /* % */
- { ISFUNC, rl_insert }, /* & */
- { ISFUNC, rl_insert }, /* ' */
- { ISFUNC, rl_insert }, /* ( */
- { ISFUNC, rl_insert }, /* ) */
- { ISFUNC, rl_insert }, /* * */
- { ISFUNC, rl_insert }, /* + */
- { ISFUNC, rl_insert }, /* , */
- { ISFUNC, rl_insert }, /* - */
- { ISFUNC, rl_insert }, /* . */
- { ISFUNC, rl_insert }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_insert }, /* 0 */
- { ISFUNC, rl_insert }, /* 1 */
- { ISFUNC, rl_insert }, /* 2 */
- { ISFUNC, rl_insert }, /* 3 */
- { ISFUNC, rl_insert }, /* 4 */
- { ISFUNC, rl_insert }, /* 5 */
- { ISFUNC, rl_insert }, /* 6 */
- { ISFUNC, rl_insert }, /* 7 */
- { ISFUNC, rl_insert }, /* 8 */
- { ISFUNC, rl_insert }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, rl_insert }, /* : */
- { ISFUNC, rl_insert }, /* ; */
- { ISFUNC, rl_insert }, /* < */
- { ISFUNC, rl_insert }, /* = */
- { ISFUNC, rl_insert }, /* > */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_insert }, /* A */
- { ISFUNC, rl_insert }, /* B */
- { ISFUNC, rl_insert }, /* C */
- { ISFUNC, rl_insert }, /* D */
- { ISFUNC, rl_insert }, /* E */
- { ISFUNC, rl_insert }, /* F */
- { ISFUNC, rl_insert }, /* G */
- { ISFUNC, rl_insert }, /* H */
- { ISFUNC, rl_insert }, /* I */
- { ISFUNC, rl_insert }, /* J */
- { ISFUNC, rl_insert }, /* K */
- { ISFUNC, rl_insert }, /* L */
- { ISFUNC, rl_insert }, /* M */
- { ISFUNC, rl_insert }, /* N */
- { ISFUNC, rl_insert }, /* O */
- { ISFUNC, rl_insert }, /* P */
- { ISFUNC, rl_insert }, /* Q */
- { ISFUNC, rl_insert }, /* R */
- { ISFUNC, rl_insert }, /* S */
- { ISFUNC, rl_insert }, /* T */
- { ISFUNC, rl_insert }, /* U */
- { ISFUNC, rl_insert }, /* V */
- { ISFUNC, rl_insert }, /* W */
- { ISFUNC, rl_insert }, /* X */
- { ISFUNC, rl_insert }, /* Y */
- { ISFUNC, rl_insert }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, rl_insert }, /* [ */
- { ISFUNC, rl_insert }, /* \ */
- { ISFUNC, rl_insert }, /* ] */
- { ISFUNC, rl_insert }, /* ^ */
- { ISFUNC, rl_insert }, /* _ */
- { ISFUNC, rl_insert }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, rl_insert }, /* a */
- { ISFUNC, rl_insert }, /* b */
- { ISFUNC, rl_insert }, /* c */
- { ISFUNC, rl_insert }, /* d */
- { ISFUNC, rl_insert }, /* e */
- { ISFUNC, rl_insert }, /* f */
- { ISFUNC, rl_insert }, /* g */
- { ISFUNC, rl_insert }, /* h */
- { ISFUNC, rl_insert }, /* i */
- { ISFUNC, rl_insert }, /* j */
- { ISFUNC, rl_insert }, /* k */
- { ISFUNC, rl_insert }, /* l */
- { ISFUNC, rl_insert }, /* m */
- { ISFUNC, rl_insert }, /* n */
- { ISFUNC, rl_insert }, /* o */
- { ISFUNC, rl_insert }, /* p */
- { ISFUNC, rl_insert }, /* q */
- { ISFUNC, rl_insert }, /* r */
- { ISFUNC, rl_insert }, /* s */
- { ISFUNC, rl_insert }, /* t */
- { ISFUNC, rl_insert }, /* u */
- { ISFUNC, rl_insert }, /* v */
- { ISFUNC, rl_insert }, /* w */
- { ISFUNC, rl_insert }, /* x */
- { ISFUNC, rl_insert }, /* y */
- { ISFUNC, rl_insert }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, rl_insert }, /* { */
- { ISFUNC, rl_insert }, /* | */
- { ISFUNC, rl_insert }, /* } */
- { ISFUNC, rl_insert }, /* ~ */
- { ISFUNC, rl_rubout }, /* RUBOUT */
-
-#if KEYMAP_SIZE > 128
- /* Pure 8-bit characters (128 - 159).
- These might be used in some
- character sets. */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* ? */
-
- /* ISO Latin-1 characters (160 - 255) */
- { ISFUNC, rl_insert }, /* No-break space */
- { ISFUNC, rl_insert }, /* Inverted exclamation mark */
- { ISFUNC, rl_insert }, /* Cent sign */
- { ISFUNC, rl_insert }, /* Pound sign */
- { ISFUNC, rl_insert }, /* Currency sign */
- { ISFUNC, rl_insert }, /* Yen sign */
- { ISFUNC, rl_insert }, /* Broken bar */
- { ISFUNC, rl_insert }, /* Section sign */
- { ISFUNC, rl_insert }, /* Diaeresis */
- { ISFUNC, rl_insert }, /* Copyright sign */
- { ISFUNC, rl_insert }, /* Feminine ordinal indicator */
- { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */
- { ISFUNC, rl_insert }, /* Not sign */
- { ISFUNC, rl_insert }, /* Soft hyphen */
- { ISFUNC, rl_insert }, /* Registered sign */
- { ISFUNC, rl_insert }, /* Macron */
- { ISFUNC, rl_insert }, /* Degree sign */
- { ISFUNC, rl_insert }, /* Plus-minus sign */
- { ISFUNC, rl_insert }, /* Superscript two */
- { ISFUNC, rl_insert }, /* Superscript three */
- { ISFUNC, rl_insert }, /* Acute accent */
- { ISFUNC, rl_insert }, /* Micro sign */
- { ISFUNC, rl_insert }, /* Pilcrow sign */
- { ISFUNC, rl_insert }, /* Middle dot */
- { ISFUNC, rl_insert }, /* Cedilla */
- { ISFUNC, rl_insert }, /* Superscript one */
- { ISFUNC, rl_insert }, /* Masculine ordinal indicator */
- { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */
- { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */
- { ISFUNC, rl_insert }, /* Vulgar fraction one half */
- { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */
- { ISFUNC, rl_insert }, /* Inverted questionk mark */
- { ISFUNC, rl_insert }, /* Latin capital letter a with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter a with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */
- { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */
- { ISFUNC, rl_insert }, /* Latin capital letter ae */
- { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */
- { ISFUNC, rl_insert }, /* Latin capital letter e with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter e with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter i with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter i with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */
- { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */
- { ISFUNC, rl_insert }, /* Latin capital letter o with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter o with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */
- { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */
- { ISFUNC, rl_insert }, /* Multiplication sign */
- { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */
- { ISFUNC, rl_insert }, /* Latin capital letter u with grave */
- { ISFUNC, rl_insert }, /* Latin capital letter u with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */
- { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */
- { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */
- { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */
- { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */
- { ISFUNC, rl_insert }, /* Latin small letter a with grave */
- { ISFUNC, rl_insert }, /* Latin small letter a with acute */
- { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter a with tilde */
- { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter a with ring above */
- { ISFUNC, rl_insert }, /* Latin small letter ae */
- { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */
- { ISFUNC, rl_insert }, /* Latin small letter e with grave */
- { ISFUNC, rl_insert }, /* Latin small letter e with acute */
- { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter i with grave */
- { ISFUNC, rl_insert }, /* Latin small letter i with acute */
- { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */
- { ISFUNC, rl_insert }, /* Latin small letter n with tilde */
- { ISFUNC, rl_insert }, /* Latin small letter o with grave */
- { ISFUNC, rl_insert }, /* Latin small letter o with acute */
- { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter o with tilde */
- { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */
- { ISFUNC, rl_insert }, /* Division sign */
- { ISFUNC, rl_insert }, /* Latin small letter o with stroke */
- { ISFUNC, rl_insert }, /* Latin small letter u with grave */
- { ISFUNC, rl_insert }, /* Latin small letter u with acute */
- { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */
- { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */
- { ISFUNC, rl_insert }, /* Latin small letter y with acute */
- { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */
- { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */
-#endif /* KEYMAP_SIZE > 128 */
-};
-
-/* Unused for the time being. */
-#if 0
-KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
- /* The regular control keys come first. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Control-a */
- { ISFUNC, (Function *)0x0 }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, (Function *)0x0 }, /* Control-d */
- { ISFUNC, (Function *)0x0 }, /* Control-e */
- { ISFUNC, (Function *)0x0 }, /* Control-f */
- { ISFUNC, (Function *)0x0 }, /* Control-g */
- { ISFUNC, (Function *)0x0 }, /* Control-h */
- { ISFUNC, rl_tab_insert}, /* Control-i */
- { ISFUNC, rl_emacs_editing_mode}, /* Control-j */
- { ISFUNC, rl_kill_line }, /* Control-k */
- { ISFUNC, (Function *)0x0 }, /* Control-l */
- { ISFUNC, rl_emacs_editing_mode}, /* Control-m */
- { ISFUNC, (Function *)0x0 }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, (Function *)0x0 }, /* Control-p */
- { ISFUNC, (Function *)0x0 }, /* Control-q */
- { ISFUNC, (Function *)0x0 }, /* Control-r */
- { ISFUNC, (Function *)0x0 }, /* Control-s */
- { ISFUNC, (Function *)0x0 }, /* Control-t */
- { ISFUNC, (Function *)0x0 }, /* Control-u */
- { ISFUNC, (Function *)0x0 }, /* Control-v */
- { ISFUNC, (Function *)0x0 }, /* Control-w */
- { ISFUNC, (Function *)0x0 }, /* Control-x */
- { ISFUNC, (Function *)0x0 }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
-
- { ISFUNC, rl_vi_movement_mode }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, rl_vi_undo }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, (Function *)0x0 }, /* SPACE */
- { ISFUNC, (Function *)0x0 }, /* ! */
- { ISFUNC, (Function *)0x0 }, /* " */
- { ISFUNC, (Function *)0x0 }, /* # */
- { ISFUNC, (Function *)0x0 }, /* $ */
- { ISFUNC, (Function *)0x0 }, /* % */
- { ISFUNC, (Function *)0x0 }, /* & */
- { ISFUNC, (Function *)0x0 }, /* ' */
- { ISFUNC, (Function *)0x0 }, /* ( */
- { ISFUNC, (Function *)0x0 }, /* ) */
- { ISFUNC, (Function *)0x0 }, /* * */
- { ISFUNC, (Function *)0x0 }, /* + */
- { ISFUNC, (Function *)0x0 }, /* , */
- { ISFUNC, (Function *)0x0 }, /* - */
- { ISFUNC, (Function *)0x0 }, /* . */
- { ISFUNC, (Function *)0x0 }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_vi_arg_digit }, /* 0 */
- { ISFUNC, rl_vi_arg_digit }, /* 1 */
- { ISFUNC, rl_vi_arg_digit }, /* 2 */
- { ISFUNC, rl_vi_arg_digit }, /* 3 */
- { ISFUNC, rl_vi_arg_digit }, /* 4 */
- { ISFUNC, rl_vi_arg_digit }, /* 5 */
- { ISFUNC, rl_vi_arg_digit }, /* 6 */
- { ISFUNC, rl_vi_arg_digit }, /* 7 */
- { ISFUNC, rl_vi_arg_digit }, /* 8 */
- { ISFUNC, rl_vi_arg_digit }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* : */
- { ISFUNC, (Function *)0x0 }, /* ; */
- { ISFUNC, (Function *)0x0 }, /* < */
- { ISFUNC, (Function *)0x0 }, /* = */
- { ISFUNC, (Function *)0x0 }, /* > */
- { ISFUNC, (Function *)0x0 }, /* ? */
- { ISFUNC, (Function *)0x0 }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_do_lowercase_version }, /* A */
- { ISFUNC, rl_do_lowercase_version }, /* B */
- { ISFUNC, rl_do_lowercase_version }, /* C */
- { ISFUNC, rl_do_lowercase_version }, /* D */
- { ISFUNC, rl_do_lowercase_version }, /* E */
- { ISFUNC, rl_do_lowercase_version }, /* F */
- { ISFUNC, rl_do_lowercase_version }, /* G */
- { ISFUNC, rl_do_lowercase_version }, /* H */
- { ISFUNC, rl_do_lowercase_version }, /* I */
- { ISFUNC, rl_do_lowercase_version }, /* J */
- { ISFUNC, rl_do_lowercase_version }, /* K */
- { ISFUNC, rl_do_lowercase_version }, /* L */
- { ISFUNC, rl_do_lowercase_version }, /* M */
- { ISFUNC, rl_do_lowercase_version }, /* N */
- { ISFUNC, rl_do_lowercase_version }, /* O */
- { ISFUNC, rl_do_lowercase_version }, /* P */
- { ISFUNC, rl_do_lowercase_version }, /* Q */
- { ISFUNC, rl_do_lowercase_version }, /* R */
- { ISFUNC, rl_do_lowercase_version }, /* S */
- { ISFUNC, rl_do_lowercase_version }, /* T */
- { ISFUNC, rl_do_lowercase_version }, /* U */
- { ISFUNC, rl_do_lowercase_version }, /* V */
- { ISFUNC, rl_do_lowercase_version }, /* W */
- { ISFUNC, rl_do_lowercase_version }, /* X */
- { ISFUNC, rl_do_lowercase_version }, /* Y */
- { ISFUNC, rl_do_lowercase_version }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, rl_arrow_keys }, /* [ */
- { ISFUNC, (Function *)0x0 }, /* \ */
- { ISFUNC, (Function *)0x0 }, /* ] */
- { ISFUNC, (Function *)0x0 }, /* ^ */
- { ISFUNC, (Function *)0x0 }, /* _ */
- { ISFUNC, (Function *)0x0 }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, (Function *)0x0 }, /* a */
- { ISFUNC, (Function *)0x0 }, /* b */
- { ISFUNC, (Function *)0x0 }, /* c */
- { ISFUNC, (Function *)0x0 }, /* d */
- { ISFUNC, (Function *)0x0 }, /* e */
- { ISFUNC, (Function *)0x0 }, /* f */
- { ISFUNC, (Function *)0x0 }, /* g */
- { ISFUNC, (Function *)0x0 }, /* h */
- { ISFUNC, (Function *)0x0 }, /* i */
- { ISFUNC, (Function *)0x0 }, /* j */
- { ISFUNC, (Function *)0x0 }, /* k */
- { ISFUNC, (Function *)0x0 }, /* l */
- { ISFUNC, (Function *)0x0 }, /* m */
- { ISFUNC, (Function *)0x0 }, /* n */
- { ISFUNC, rl_arrow_keys }, /* o */
- { ISFUNC, (Function *)0x0 }, /* p */
- { ISFUNC, (Function *)0x0 }, /* q */
- { ISFUNC, (Function *)0x0 }, /* r */
- { ISFUNC, (Function *)0x0 }, /* s */
- { ISFUNC, (Function *)0x0 }, /* t */
- { ISFUNC, (Function *)0x0 }, /* u */
- { ISFUNC, (Function *)0x0 }, /* v */
- { ISFUNC, (Function *)0x0 }, /* w */
- { ISFUNC, (Function *)0x0 }, /* x */
- { ISFUNC, (Function *)0x0 }, /* y */
- { ISFUNC, (Function *)0x0 }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* { */
- { ISFUNC, (Function *)0x0 }, /* | */
- { ISFUNC, (Function *)0x0 }, /* } */
- { ISFUNC, (Function *)0x0 }, /* ~ */
- { ISFUNC, rl_backward_kill_word }, /* RUBOUT */
-
-#if KEYMAP_SIZE > 128
- /* Undefined keys. */
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 }
-#endif /* KEYMAP_SIZE > 128 */
-};
-#endif
diff --git a/readline/vi_mode.c b/readline/vi_mode.c
deleted file mode 100644
index eb392b643ba..00000000000
--- a/readline/vi_mode.c
+++ /dev/null
@@ -1,1389 +0,0 @@
-/* vi_mode.c -- A vi emulation mode for Bash.
- Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
-
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library, a library for
- reading lines of text with interactive input and history editing.
-
- The GNU Readline 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 1, or
- (at your option) any later version.
-
- The GNU Readline 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.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define READLINE_LIBRARY
-
-/* **************************************************************** */
-/* */
-/* VI Emulation Mode */
-/* */
-/* **************************************************************** */
-#include "rlconf.h"
-
-#if defined (VI_MODE)
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-
-/* Some standard library routines. */
-#include "rldefs.h"
-#include "readline.h"
-#include "history.h"
-
-#ifndef _rl_digit_p
-#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9')
-#endif
-
-#ifndef _rl_digit_value
-#define _rl_digit_value(c) ((c) - '0')
-#endif
-
-#ifndef member
-#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
-#endif
-
-#ifndef isident
-#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_'))
-#endif
-
-#ifndef exchange
-#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
-#endif
-
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables imported from readline.c */
-extern int rl_point, rl_end, rl_mark;
-extern FILE *rl_instream;
-extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;
-extern Keymap _rl_keymap;
-extern char *rl_prompt;
-extern char *rl_line_buffer;
-extern int rl_arg_sign;
-
-extern int _rl_doing_an_undo;
-extern int _rl_undo_group_level;
-
-extern void _rl_dispatch ();
-extern int _rl_char_search_internal ();
-
-extern void rl_extend_line_buffer ();
-extern int rl_vi_check ();
-
-/* Non-zero means enter insertion mode. */
-static int _rl_vi_doing_insert;
-
-/* Command keys which do movement for xxx_to commands. */
-static const char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
-
-/* Keymap used for vi replace characters. Created dynamically since
- rarely used. */
-static Keymap vi_replace_map;
-
-/* The number of characters inserted in the last replace operation. */
-static int vi_replace_count;
-
-/* If non-zero, we have text inserted after a c[motion] command that put
- us implicitly into insert mode. Some people want this text to be
- attached to the command so that it is `redoable' with `.'. */
-static int vi_continued_command;
-static char *vi_insert_buffer;
-static int vi_insert_buffer_size;
-
-static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
-static int _rl_vi_last_repeat = 1;
-static int _rl_vi_last_arg_sign = 1;
-static int _rl_vi_last_motion;
-static int _rl_vi_last_search_char;
-static int _rl_vi_last_replacement;
-
-static int _rl_vi_last_key_before_insert;
-
-static int vi_redoing;
-
-/* Text modification commands. These are the `redoable' commands. */
-static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
-
-/* Arrays for the saved marks. */
-static int vi_mark_chars[27];
-
-static int rl_digit_loop1 ();
-
-void
-_rl_vi_initialize_line ()
-{
-#ifndef __QNXNTO__
- register uint i;
-#else
- register unsigned int i;
-#endif
-
- for (i = 0; i < (int) sizeof (vi_mark_chars) / sizeof (int); i++)
- vi_mark_chars[i] = -1;
-}
-
-void
-_rl_vi_reset_last ()
-{
- _rl_vi_last_command = 'i';
- _rl_vi_last_repeat = 1;
- _rl_vi_last_arg_sign = 1;
- _rl_vi_last_motion = 0;
-}
-
-void
-_rl_vi_set_last (key, repeat, sign)
- int key, repeat, sign;
-{
- _rl_vi_last_command = key;
- _rl_vi_last_repeat = repeat;
- _rl_vi_last_arg_sign = sign;
-}
-
-/* Is the command C a VI mode text modification command? */
-int
-_rl_vi_textmod_command (c)
- int c;
-{
- return (member (c, vi_textmod));
-}
-
-static void
-_rl_vi_stuff_insert (count)
- int count;
-{
- rl_begin_undo_group ();
- while (count--)
- rl_insert_text (vi_insert_buffer);
- rl_end_undo_group ();
-}
-
-/* Bound to `.'. Called from command mode, so we know that we have to
- redo a text modification command. The default for _rl_vi_last_command
- puts you back into insert mode. */
-int
-rl_vi_redo (count, c)
- int count, c __attribute__((unused));
-{
- if (!rl_explicit_arg)
- {
- rl_numeric_arg = _rl_vi_last_repeat;
- rl_arg_sign = _rl_vi_last_arg_sign;
- }
-
- vi_redoing = 1;
- /* If we're redoing an insert with `i', stuff in the inserted text
- and do not go into insertion mode. */
- if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
- {
- _rl_vi_stuff_insert (count);
- /* And back up point over the last character inserted. */
- if (rl_point > 0)
- rl_point--;
- }
- else
- _rl_dispatch (_rl_vi_last_command, _rl_keymap);
- vi_redoing = 0;
-
- return (0);
-}
-
-/* A placeholder for further expansion. */
-int
-rl_vi_undo (count, key)
- int count, key;
-{
- return (rl_undo_command (count, key));
-}
-
-/* Yank the nth arg from the previous line into this line at point. */
-int
-rl_vi_yank_arg (count, key)
- int count, key __attribute__((unused));
-{
- /* Readline thinks that the first word on a line is the 0th, while vi
- thinks the first word on a line is the 1st. Compensate. */
- if (rl_explicit_arg)
- rl_yank_nth_arg (count - 1, 0);
- else
- rl_yank_nth_arg ('$', 0);
-
- return (0);
-}
-
-/* With an argument, move back that many history lines, else move to the
- beginning of history. */
-int
-rl_vi_fetch_history (count, c)
- int count, c;
-{
- int wanted;
-
- /* Giving an argument of n means we want the nth command in the history
- file. The command number is interpreted the same way that the bash
- `history' command does it -- that is, giving an argument count of 450
- to this command would get the command listed as number 450 in the
- output of `history'. */
- if (rl_explicit_arg)
- {
- wanted = history_base + where_history () - count;
- if (wanted <= 0)
- rl_beginning_of_history (0, 0);
- else
- rl_get_previous_history (wanted, c);
- }
- else
- rl_beginning_of_history (count, 0);
- return (0);
-}
-
-/* Search again for the last thing searched for. */
-int
-rl_vi_search_again (count, key)
- int count, key;
-{
- switch (key)
- {
- case 'n':
- rl_noninc_reverse_search_again (count, key);
- break;
-
- case 'N':
- rl_noninc_forward_search_again (count, key);
- break;
- }
- return (0);
-}
-
-/* Do a vi style search. */
-int
-rl_vi_search (count, key)
- int count, key;
-{
- switch (key)
- {
- case '?':
- rl_noninc_forward_search (count, key);
- break;
-
- case '/':
- rl_noninc_reverse_search (count, key);
- break;
-
- default:
- ding ();
- break;
- }
- return (0);
-}
-
-/* Completion, from vi's point of view. */
-int
-rl_vi_complete (ignore, key)
- int ignore __attribute__((unused)), key;
-{
- if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
- {
- if (!whitespace (rl_line_buffer[rl_point + 1]))
- rl_vi_end_word (1, 'E');
- rl_point++;
- }
-
- if (key == '*')
- rl_complete_internal ('*'); /* Expansion and replacement. */
- else if (key == '=')
- rl_complete_internal ('?'); /* List possible completions. */
- else if (key == '\\')
- rl_complete_internal (TAB); /* Standard Readline completion. */
- else
- rl_complete (0, key);
-
- if (key == '*' || key == '\\')
- {
- _rl_vi_set_last (key, 1, rl_arg_sign);
- rl_vi_insertion_mode (1, key);
- }
- return (0);
-}
-
-/* Tilde expansion for vi mode. */
-int
-rl_vi_tilde_expand (ignore, key)
- int ignore __attribute__((unused)), key;
-{
- rl_tilde_expand (0, key);
- _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
- rl_vi_insertion_mode (1, key);
- return (0);
-}
-
-/* Previous word in vi mode. */
-int
-rl_vi_prev_word (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_vi_next_word (-count, key));
-
- if (rl_point == 0)
- {
- ding ();
- return (0);
- }
-
- if (_rl_uppercase_p (key))
- rl_vi_bWord (count, key);
- else
- rl_vi_bword (count, key);
-
- return (0);
-}
-
-/* Next word in vi mode. */
-int
-rl_vi_next_word (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_vi_prev_word (-count, key));
-
- if (rl_point >= (rl_end - 1))
- {
- ding ();
- return (0);
- }
-
- if (_rl_uppercase_p (key))
- rl_vi_fWord (count, key);
- else
- rl_vi_fword (count, key);
- return (0);
-}
-
-/* Move to the end of the ?next? word. */
-int
-rl_vi_end_word (count, key)
- int count, key;
-{
- if (count < 0)
- {
- ding ();
- return -1;
- }
-
- if (_rl_uppercase_p (key))
- rl_vi_eWord (count, key);
- else
- rl_vi_eword (count, key);
- return (0);
-}
-
-/* Move forward a word the way that 'W' does. */
-int
-rl_vi_fWord (count, ignore)
- int count, ignore __attribute__((unused));
-{
- while (count-- && rl_point < (rl_end - 1))
- {
- /* Skip until whitespace. */
- while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
- rl_point++;
-
- /* Now skip whitespace. */
- while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
- rl_point++;
- }
- return (0);
-}
-
-int
-rl_vi_bWord (count, ignore)
- int count, ignore __attribute__((unused));
-{
- while (count-- && rl_point > 0)
- {
- /* If we are at the start of a word, move back to whitespace so
- we will go back to the start of the previous word. */
- if (!whitespace (rl_line_buffer[rl_point]) &&
- whitespace (rl_line_buffer[rl_point - 1]))
- rl_point--;
-
- while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
- rl_point--;
-
- if (rl_point > 0)
- {
- while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
- rl_point++;
- }
- }
- return (0);
-}
-
-int
-rl_vi_eWord (count, ignore)
- int count, ignore __attribute__((unused));
-{
- while (count-- && rl_point < (rl_end - 1))
- {
- if (!whitespace (rl_line_buffer[rl_point]))
- rl_point++;
-
- /* Move to the next non-whitespace character (to the start of the
- next word). */
- while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
-
- if (rl_point && rl_point < rl_end)
- {
- /* Skip whitespace. */
- while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
- rl_point++;
-
- /* Skip until whitespace. */
- while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
- rl_point++;
-
- /* Move back to the last character of the word. */
- rl_point--;
- }
- }
- return (0);
-}
-
-int
-rl_vi_fword (count, ignore)
- int count, ignore __attribute__((unused));
-{
- while (count-- && rl_point < (rl_end - 1))
- {
- /* Move to white space (really non-identifer). */
- if (isident (rl_line_buffer[rl_point]))
- {
- while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
- rl_point++;
- }
- else /* if (!whitespace (rl_line_buffer[rl_point])) */
- {
- while (!isident (rl_line_buffer[rl_point]) &&
- !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
- rl_point++;
- }
-
- /* Move past whitespace. */
- while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
- rl_point++;
- }
- return (0);
-}
-
-int
-rl_vi_bword (count, ignore)
- int count, ignore __attribute__((unused));
-{
- while (count-- && rl_point > 0)
- {
- int last_is_ident;
-
- /* If we are at the start of a word, move back to whitespace
- so we will go back to the start of the previous word. */
- if (!whitespace (rl_line_buffer[rl_point]) &&
- whitespace (rl_line_buffer[rl_point - 1]))
- rl_point--;
-
- /* If this character and the previous character are `opposite', move
- back so we don't get messed up by the rl_point++ down there in
- the while loop. Without this code, words like `l;' screw up the
- function. */
- last_is_ident = isident (rl_line_buffer[rl_point - 1]);
- if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
- (!isident (rl_line_buffer[rl_point]) && last_is_ident))
- rl_point--;
-
- while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
- rl_point--;
-
- if (rl_point > 0)
- {
- if (isident (rl_line_buffer[rl_point]))
- while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
- else
- while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
- !whitespace (rl_line_buffer[rl_point]));
- rl_point++;
- }
- }
- return (0);
-}
-
-int
-rl_vi_eword (count, ignore)
- int count, ignore __attribute__((unused));
-{
- while (count-- && rl_point < rl_end - 1)
- {
- if (!whitespace (rl_line_buffer[rl_point]))
- rl_point++;
-
- while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
- rl_point++;
-
- if (rl_point < rl_end)
- {
- if (isident (rl_line_buffer[rl_point]))
- while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
- else
- while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
- && !whitespace (rl_line_buffer[rl_point]));
- }
- rl_point--;
- }
- return (0);
-}
-
-int
-rl_vi_insert_beg (count, key)
- int count __attribute__((unused)), key;
-{
- rl_beg_of_line (1, key);
- rl_vi_insertion_mode (1, key);
- return (0);
-}
-
-int
-rl_vi_append_mode (count, key)
- int count __attribute__((unused)), key;
-{
- if (rl_point < rl_end)
- rl_point++;
- rl_vi_insertion_mode (1, key);
- return (0);
-}
-
-int
-rl_vi_append_eol (count, key)
- int count __attribute__((unused)), key;
-{
- rl_end_of_line (1, key);
- rl_vi_append_mode (1, key);
- return (0);
-}
-
-/* What to do in the case of C-d. */
-int
-rl_vi_eof_maybe (count, c)
- int count __attribute__((unused)), c __attribute__((unused));
-{
- return (rl_newline (1, '\n'));
-}
-
-/* Insertion mode stuff. */
-
-/* Switching from one mode to the other really just involves
- switching keymaps. */
-int
-rl_vi_insertion_mode (count, key)
- int count __attribute__((unused)), key;
-{
- _rl_keymap = vi_insertion_keymap;
- _rl_vi_last_key_before_insert = key;
- return (0);
-}
-
-static void
-_rl_vi_save_insert (up)
- UNDO_LIST *up;
-{
- int len, start, end;
-
- if (up == 0)
- {
- if (vi_insert_buffer_size >= 1)
- vi_insert_buffer[0] = '\0';
- return;
- }
-
- start = up->start;
- end = up->end;
- len = end - start + 1;
- if (len >= vi_insert_buffer_size)
- {
- vi_insert_buffer_size += (len + 32) - (len % 32);
- vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size);
- }
- strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
- vi_insert_buffer[len-1] = '\0';
-}
-
-void
-_rl_vi_done_inserting ()
-{
- if (_rl_vi_doing_insert)
- {
- rl_end_undo_group ();
- /* Now, the text between rl_undo_list->next->start and
- rl_undo_list->next->end is what was inserted while in insert
- mode. It gets copied to VI_INSERT_BUFFER because it depends
- on absolute indices into the line which may change (though they
- probably will not). */
- _rl_vi_doing_insert = 0;
- _rl_vi_save_insert (rl_undo_list->next);
- vi_continued_command = 1;
- }
- else
- {
- if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
- _rl_vi_save_insert (rl_undo_list);
- /* XXX - Other keys probably need to be checked. */
- else if (_rl_vi_last_key_before_insert == 'C')
- rl_end_undo_group ();
- while (_rl_undo_group_level > 0)
- rl_end_undo_group ();
- vi_continued_command = 0;
- }
-}
-
-int
-rl_vi_movement_mode (count, key)
- int count __attribute__((unused)), key;
-{
- if (rl_point > 0)
- rl_backward (1, key);
-
- _rl_keymap = vi_movement_keymap;
- _rl_vi_done_inserting ();
- return (0);
-}
-
-int
-rl_vi_arg_digit (count, c)
- int count, c;
-{
- if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
- return (rl_beg_of_line (1, c));
- else
- return (rl_digit_argument (count, c));
-}
-
-int
-rl_vi_change_case (count, ignore)
- int count, ignore __attribute__((unused));
-{
- char c = 0;
-
- /* Don't try this on an empty line. */
- if (rl_point >= rl_end)
- return (0);
-
- while (count-- && rl_point < rl_end)
- {
- if (_rl_uppercase_p (rl_line_buffer[rl_point]))
- c = _rl_to_lower (rl_line_buffer[rl_point]);
- else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
- c = _rl_to_upper (rl_line_buffer[rl_point]);
- else
- {
- /* Just skip over characters neither upper nor lower case. */
- rl_forward (1, c);
- continue;
- }
-
- /* Vi is kind of strange here. */
- if (c)
- {
- rl_begin_undo_group ();
- rl_delete (1, c);
- rl_insert (1, c);
- rl_end_undo_group ();
- rl_vi_check ();
- }
- else
- rl_forward (1, c);
- }
- return (0);
-}
-
-int
-rl_vi_put (count, key)
- int count __attribute__((unused)), key;
-{
- if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
- rl_point++;
-
- rl_yank (1, key);
- rl_backward (1, key);
- return (0);
-}
-
-int
-rl_vi_check ()
-{
- if (rl_point && rl_point == rl_end)
- rl_point--;
- return (0);
-}
-
-int
-rl_vi_column (count, key)
- int count, key;
-{
- if (count > rl_end)
- rl_end_of_line (1, key);
- else
- rl_point = count - 1;
- return (0);
-}
-
-int
-rl_vi_domove (key, nextkey)
- int key, *nextkey;
-{
- int c, save;
- int old_end;
-
- rl_mark = rl_point;
- c = rl_read_key ();
- *nextkey = c;
-
- if (!member (c, vi_motion))
- {
- if (_rl_digit_p (c))
- {
- save = rl_numeric_arg;
- rl_numeric_arg = _rl_digit_value (c);
- rl_digit_loop1 ();
- rl_numeric_arg *= save;
- c = rl_read_key (); /* real command */
- *nextkey = c;
- }
- else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
- {
- rl_mark = rl_end;
- rl_beg_of_line (1, c);
- _rl_vi_last_motion = c;
- return (0);
- }
- else
- return (-1);
- }
-
- _rl_vi_last_motion = c;
-
- /* Append a blank character temporarily so that the motion routines
- work right at the end of the line. */
- old_end = rl_end;
- rl_line_buffer[rl_end++] = ' ';
- rl_line_buffer[rl_end] = '\0';
-
- _rl_dispatch (c, _rl_keymap);
-
- /* Remove the blank that we added. */
- rl_end = old_end;
- rl_line_buffer[rl_end] = '\0';
- if (rl_point > rl_end)
- rl_point = rl_end;
-
- /* No change in position means the command failed. */
- if (rl_mark == rl_point)
- return (-1);
-
- /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
- word. If we are not at the end of the line, and we are on a
- non-whitespace character, move back one (presumably to whitespace). */
- if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
- !whitespace (rl_line_buffer[rl_point]))
- rl_point--;
-
- /* If cw or cW, back up to the end of a word, so the behaviour of ce
- or cE is the actual result. Brute-force, no subtlety. */
- if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
- {
- /* Don't move farther back than where we started. */
- while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
- rl_point--;
-
- /* Posix.2 says that if cw or cW moves the cursor towards the end of
- the line, the character under the cursor should be deleted. */
- if (rl_point == rl_mark)
- rl_point++;
- else
- {
- /* Move past the end of the word so that the kill doesn't
- remove the last letter of the previous word. Only do this
- if we are not at the end of the line. */
- if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
- rl_point++;
- }
- }
-
- if (rl_mark < rl_point)
- exchange (rl_point, rl_mark);
-
- return (0);
-}
-
-/* A simplified loop for vi. Don't dispatch key at end.
- Don't recognize minus sign? */
-static int
-rl_digit_loop1 ()
-{
- int key, c;
-
- while (1)
- {
- rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
- key = c = rl_read_key ();
-
- if (_rl_keymap[c].type == ISFUNC &&
- _rl_keymap[c].function == rl_universal_argument)
- {
- rl_numeric_arg *= 4;
- continue;
- }
-
- c = UNMETA (c);
- if (_rl_digit_p (c))
- {
- if (rl_explicit_arg)
- rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
- else
- rl_numeric_arg = _rl_digit_value (c);
- rl_explicit_arg = 1;
- }
- else
- {
- rl_clear_message ();
- rl_stuff_char (key);
- break;
- }
- }
- return (0);
-}
-
-int
-rl_vi_delete_to (count, key)
- int count __attribute__((unused)), key;
-{
- int c;
-
- if (_rl_uppercase_p (key))
- rl_stuff_char ('$');
- else if (vi_redoing)
- rl_stuff_char (_rl_vi_last_motion);
-
- if (rl_vi_domove (key, &c))
- {
- ding ();
- return -1;
- }
-
- /* These are the motion commands that do not require adjusting the
- mark. */
- if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
- rl_mark++;
-
- rl_kill_text (rl_point, rl_mark);
- return (0);
-}
-
-int
-rl_vi_change_to (count, key)
- int count, key;
-{
- int c, start_pos;
-
- if (_rl_uppercase_p (key))
- rl_stuff_char ('$');
- else if (vi_redoing)
- rl_stuff_char (_rl_vi_last_motion);
-
- start_pos = rl_point;
-
- if (rl_vi_domove (key, &c))
- {
- ding ();
- return -1;
- }
-
- /* These are the motion commands that do not require adjusting the
- mark. c[wW] are handled by special-case code in rl_vi_domove(),
- and already leave the mark at the correct location. */
- if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
- rl_mark++;
-
- /* The cursor never moves with c[wW]. */
- if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
- rl_point = start_pos;
-
- if (vi_redoing)
- {
- if (vi_insert_buffer && *vi_insert_buffer)
- rl_begin_undo_group ();
- rl_delete_text (rl_point, rl_mark);
- if (vi_insert_buffer && *vi_insert_buffer)
- {
- rl_insert_text (vi_insert_buffer);
- rl_end_undo_group ();
- }
- }
- else
- {
- rl_begin_undo_group (); /* to make the `u' command work */
- rl_kill_text (rl_point, rl_mark);
- /* `C' does not save the text inserted for undoing or redoing. */
- if (_rl_uppercase_p (key) == 0)
- _rl_vi_doing_insert = 1;
- _rl_vi_set_last (key, count, rl_arg_sign);
- rl_vi_insertion_mode (1, key);
- }
-
- return (0);
-}
-
-int
-rl_vi_yank_to (count, key)
- int count __attribute__((unused)), key;
-{
- int c, save = rl_point;
-
- if (_rl_uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove (key, &c))
- {
- ding ();
- return -1;
- }
-
- /* These are the motion commands that do not require adjusting the
- mark. */
- if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
- rl_mark++;
-
- rl_begin_undo_group ();
- rl_kill_text (rl_point, rl_mark);
- rl_end_undo_group ();
- rl_do_undo ();
- rl_point = save;
-
- return (0);
-}
-
-int
-rl_vi_delete (count, key)
- int count, key;
-{
- int end;
-
- if (rl_end == 0)
- {
- ding ();
- return -1;
- }
-
- end = rl_point + count;
-
- if (end >= rl_end)
- end = rl_end;
-
- rl_kill_text (rl_point, end);
-
- if (rl_point > 0 && rl_point == rl_end)
- rl_backward (1, key);
- return (0);
-}
-
-int
-rl_vi_back_to_indent (count, key)
- int count __attribute__((unused)), key;
-{
- rl_beg_of_line (1, key);
- while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
- rl_point++;
- return (0);
-}
-
-int
-rl_vi_first_print (count, key)
- int count __attribute__((unused)), key;
-{
- return (rl_vi_back_to_indent (1, key));
-}
-
-int
-rl_vi_char_search (count, key)
- int count, key;
-{
- static char target;
- static int orig_dir, dir;
-
- if (key == ';' || key == ',')
- dir = key == ';' ? orig_dir : -orig_dir;
- else
- {
- if (vi_redoing)
- target = _rl_vi_last_search_char;
- else
- _rl_vi_last_search_char = target = rl_getc (rl_instream);
-
- switch (key)
- {
- case 't':
- orig_dir = dir = FTO;
- break;
-
- case 'T':
- orig_dir = dir = BTO;
- break;
-
- case 'f':
- orig_dir = dir = FFIND;
- break;
-
- case 'F':
- orig_dir = dir = BFIND;
- break;
- }
- }
-
- return (_rl_char_search_internal (count, dir, target));
-}
-
-/* Match brackets */
-int
-rl_vi_match (ignore, key)
- int ignore __attribute__((unused)), key;
-{
- int count = 1, brack, pos;
-
- pos = rl_point;
- if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
- {
- while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
- rl_point < rl_end - 1)
- rl_forward (1, key);
-
- if (brack <= 0)
- {
- rl_point = pos;
- ding ();
- return -1;
- }
- }
-
- pos = rl_point;
-
- if (brack < 0)
- {
- while (count)
- {
- if (--pos >= 0)
- {
- int b = rl_vi_bracktype (rl_line_buffer[pos]);
- if (b == -brack)
- count--;
- else if (b == brack)
- count++;
- }
- else
- {
- ding ();
- return -1;
- }
- }
- }
- else
- { /* brack > 0 */
- while (count)
- {
- if (++pos < rl_end)
- {
- int b = rl_vi_bracktype (rl_line_buffer[pos]);
- if (b == -brack)
- count--;
- else if (b == brack)
- count++;
- }
- else
- {
- ding ();
- return -1;
- }
- }
- }
- rl_point = pos;
- return (0);
-}
-
-int
-rl_vi_bracktype (c)
- int c;
-{
- switch (c)
- {
- case '(': return 1;
- case ')': return -1;
- case '[': return 2;
- case ']': return -2;
- case '{': return 3;
- case '}': return -3;
- default: return 0;
- }
-}
-
-int
-rl_vi_change_char (count, key)
- int count, key __attribute__((unused));
-{
- int c;
-
- if (vi_redoing)
- c = _rl_vi_last_replacement;
- else
- _rl_vi_last_replacement = c = rl_getc (rl_instream);
-
- if (c == '\033' || c == CTRL ('C'))
- return -1;
-
- while (count-- && rl_point < rl_end)
- {
- rl_begin_undo_group ();
-
- rl_delete (1, c);
- rl_insert (1, c);
- if (count == 0)
- rl_backward (1, c);
-
- rl_end_undo_group ();
- }
- return (0);
-}
-
-int
-rl_vi_subst (count, key)
- int count, key;
-{
- rl_begin_undo_group ();
-
- if (_rl_uppercase_p (key))
- {
- rl_beg_of_line (1, key);
- rl_kill_line (1, key);
- }
- else
- rl_delete_text (rl_point, rl_point+count);
-
- rl_end_undo_group ();
-
- _rl_vi_set_last (key, count, rl_arg_sign);
-
- if (vi_redoing)
- {
- int o = _rl_doing_an_undo;
-
- _rl_doing_an_undo = 1;
- if (vi_insert_buffer && *vi_insert_buffer)
- rl_insert_text (vi_insert_buffer);
- _rl_doing_an_undo = o;
- }
- else
- {
- rl_begin_undo_group ();
- _rl_vi_doing_insert = 1;
- rl_vi_insertion_mode (1, key);
- }
-
- return (0);
-}
-
-int
-rl_vi_overstrike (count, key)
- int count, key;
-{
- int i;
-
- if (_rl_vi_doing_insert == 0)
- {
- _rl_vi_doing_insert = 1;
- rl_begin_undo_group ();
- }
-
- for (i = 0; i < count; i++)
- {
- vi_replace_count++;
- rl_begin_undo_group ();
-
- if (rl_point < rl_end)
- {
- rl_delete (1, key);
- rl_insert (1, key);
- }
- else
- rl_insert (1, key);
-
- rl_end_undo_group ();
- }
- return (0);
-}
-
-int
-rl_vi_overstrike_delete (count, key)
- int count, key;
-{
- int i, s;
-
- for (i = 0; i < count; i++)
- {
- if (vi_replace_count == 0)
- {
- ding ();
- break;
- }
- s = rl_point;
-
- if (rl_do_undo ())
- vi_replace_count--;
-
- if (rl_point == s)
- rl_backward (1, key);
- }
-
- if (vi_replace_count == 0 && _rl_vi_doing_insert)
- {
- rl_end_undo_group ();
- rl_do_undo ();
- _rl_vi_doing_insert = 0;
- }
- return (0);
-}
-
-int
-rl_vi_replace (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- int i;
-
- vi_replace_count = 0;
-
- if (!vi_replace_map)
- {
- vi_replace_map = rl_make_bare_keymap ();
-
- for (i = ' '; i < KEYMAP_SIZE; i++)
- vi_replace_map[i].function = rl_vi_overstrike;
-
- vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
- vi_replace_map[ESC].function = rl_vi_movement_mode;
- vi_replace_map[RETURN].function = rl_newline;
- vi_replace_map[NEWLINE].function = rl_newline;
-
- /* If the normal vi insertion keymap has ^H bound to erase, do the
- same here. Probably should remove the assignment to RUBOUT up
- there, but I don't think it will make a difference in real life. */
- if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
- vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
- vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
-
- }
- _rl_keymap = vi_replace_map;
- return (0);
-}
-
-#if 0
-/* Try to complete the word we are standing on or the word that ends with
- the previous character. A space matches everything. Word delimiters are
- space and ;. */
-int
-rl_vi_possible_completions()
-{
- int save_pos = rl_point;
-
- if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
- {
- while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
- rl_line_buffer[rl_point] != ';')
- rl_point++;
- }
- else if (rl_line_buffer[rl_point - 1] == ';')
- {
- ding ();
- return (0);
- }
-
- rl_possible_completions ();
- rl_point = save_pos;
-
- return (0);
-}
-#endif
-
-/* Functions to save and restore marks. */
-int
-rl_vi_set_mark (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- int ch;
-
- ch = rl_read_key ();
- if (_rl_lowercase_p (ch) == 0)
- {
- ding ();
- return -1;
- }
- ch -= 'a';
- vi_mark_chars[ch] = rl_point;
- return 0;
-}
-
-int
-rl_vi_goto_mark (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
-{
- int ch;
-
- ch = rl_read_key ();
- if (ch == '`')
- {
- rl_point = rl_mark;
- return 0;
- }
- else if (_rl_lowercase_p (ch) == 0)
- {
- ding ();
- return -1;
- }
-
- ch -= 'a';
- if (vi_mark_chars[ch] == -1)
- {
- ding ();
- return -1;
- }
- rl_point = vi_mark_chars[ch];
- return 0;
-}
-
-#endif /* VI_MODE */
diff --git a/readline/xmalloc.c b/readline/xmalloc.c
deleted file mode 100644
index 4160651191b..00000000000
--- a/readline/xmalloc.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* xmalloc.c -- safe versions of malloc and realloc */
-
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if defined (HAVE_CONFIG_H)
-#include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-static void memory_error_and_abort ();
-
-/* **************************************************************** */
-/* */
-/* Memory Allocation and Deallocation. */
-/* */
-/* **************************************************************** */
-
-/* Return a pointer to free()able block of memory large enough
- to hold BYTES number of bytes. If the memory cannot be allocated,
- print an error message and abort. */
-char *
-xmalloc (bytes)
- int bytes;
-{
- char *temp;
-
- temp = (char *)malloc (bytes);
- if (temp == 0)
- memory_error_and_abort ("xmalloc");
- return (temp);
-}
-
-char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- char *temp;
-
- temp = pointer ? (char *)realloc (pointer, bytes) : (char *)malloc (bytes);
-
- if (temp == 0)
- memory_error_and_abort ("xrealloc");
- return (temp);
-}
-
-static void
-memory_error_and_abort (fname)
- char *fname;
-{
- fprintf (stderr, "%s: out of virtual memory\n", fname);
- exit (2);
-}
-
-/* Use this as the function to call when adding unwind protects so we
- don't need to know what free() returns. */
-void
-xfree (string)
- char *string;
-{
- if (string)
- free (string);
-}
diff --git a/regex/Makefile.am b/regex/Makefile.am
index ee421b70bcf..2e23efcbf2a 100644
--- a/regex/Makefile.am
+++ b/regex/Makefile.am
@@ -15,7 +15,7 @@
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
noinst_LIBRARIES = libregex.a
LDADD = libregex.a ../strings/libmystrings.a
noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c regex.h
diff --git a/regex/debug.c b/regex/debug.c
index 35279941d48..bdd3e00d5a7 100644
--- a/regex/debug.c
+++ b/regex/debug.c
@@ -45,7 +45,7 @@ FILE *d;
if (g->nplus > 0)
fprintf(d, ", nplus %ld", (long)g->nplus);
fprintf(d, "\n");
- s_print(g, d);
+ s_print(r->charset, g, d);
for (i = 0; i < g->ncategories; i++) {
nincat[i] = 0;
for (c = CHAR_MIN; c <= CHAR_MAX; c++)
@@ -58,7 +58,7 @@ FILE *d;
for (c = CHAR_MIN; c <= CHAR_MAX; c++)
if (g->categories[c] == i)
break;
- fprintf(d, ", %d=%s", i, regchar(c,buf));
+ fprintf(d, ", %d=%s", i, regchar(r->charset,c,buf));
}
fprintf(d, "\n");
for (i = 1; i < g->ncategories; i++)
@@ -68,14 +68,14 @@ FILE *d;
for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */
if (c <= CHAR_MAX && g->categories[c] == i) {
if (last < 0) {
- fprintf(d, "%s", regchar(c,buf));
+ fprintf(d, "%s", regchar(r->charset,c,buf));
last = c;
}
} else {
if (last >= 0) {
if (last != c-1)
fprintf(d, "-%s",
- regchar(c-1,buf));
+ regchar(r->charset,c-1,buf));
last = -1;
}
}
@@ -88,7 +88,8 @@ FILE *d;
== static void s_print(register struct re_guts *g, FILE *d);
*/
static void
-s_print(g, d)
+s_print(charset, g, d)
+CHARSET_INFO *charset;
register struct re_guts *g;
FILE *d;
{
@@ -127,7 +128,7 @@ FILE *d;
if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
fprintf(d, "\\%c", (char)opnd);
else
- fprintf(d, "%s", regchar((char)opnd,buf));
+ fprintf(d, "%s", regchar(charset,(char)opnd,buf));
break;
case OBOL:
fprintf(d, "^");
@@ -151,14 +152,14 @@ FILE *d;
for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */
if (CHIN(cs, i) && i < g->csetsize) {
if (last < 0) {
- fprintf(d, "%s", regchar(i,buf));
+ fprintf(d, "%s", regchar(charset,i,buf));
last = i;
}
} else {
if (last >= 0) {
if (last != i-1)
fprintf(d, "-%s",
- regchar(i-1,buf));
+ regchar(charset,i-1,buf));
last = -1;
}
}
@@ -230,12 +231,13 @@ FILE *d;
== static char *regchar(int ch);
*/
static char * /* -> representation */
-regchar(ch,buf)
+regchar(charset,ch,buf)
+CHARSET_INFO *charset;
int ch;
char *buf;
{
- if (isprint(ch) || ch == ' ')
+ if (my_isprint(charset,ch) || ch == ' ')
sprintf(buf, "%c", ch);
else
sprintf(buf, "\\%o", ch);
diff --git a/regex/debug.ih b/regex/debug.ih
index 532ec5086e5..0d91e170437 100644
--- a/regex/debug.ih
+++ b/regex/debug.ih
@@ -5,8 +5,8 @@ extern "C" {
/* === debug.c === */
void regprint(regex_t *r, FILE *d);
-static void s_print(register struct re_guts *g, FILE *d);
-static char *regchar(int ch,char *buf);
+static void s_print(CHARSET_INFO *charset, register struct re_guts *g, FILE *d);
+static char *regchar(CHARSET_INFO *charset, int ch,char *buf);
#ifdef __cplusplus
}
diff --git a/regex/engine.c b/regex/engine.c
index e77fbd7cf89..6734560b9bf 100644
--- a/regex/engine.c
+++ b/regex/engine.c
@@ -63,7 +63,8 @@ struct match {
== size_t nmatch, regmatch_t pmatch[], int eflags);
*/
static int /* 0 success, REG_NOMATCH failure */
-matcher(g, str, nmatch, pmatch, eflags)
+matcher(charset,g, str, nmatch, pmatch, eflags)
+CHARSET_INFO *charset;
register struct re_guts *g;
char *str;
size_t nmatch;
@@ -120,7 +121,7 @@ int eflags;
/* this loop does only one repetition except for backrefs */
for (;;) {
- endp = fast(m, start, stop, gf, gl);
+ endp = fast(charset, m, start, stop, gf, gl);
if (endp == NULL) { /* a miss */
if (m->pmatch != NULL)
free((char *)m->pmatch);
@@ -136,7 +137,7 @@ int eflags;
assert(m->coldp != NULL);
for (;;) {
NOTE("finding start");
- endp = slow(m, m->coldp, stop, gf, gl);
+ endp = slow(charset, m, m->coldp, stop, gf, gl);
if (endp != NULL)
break;
assert(m->coldp < m->endp);
@@ -159,7 +160,7 @@ int eflags;
m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
if (!g->backrefs && !(m->eflags&REG_BACKR)) {
NOTE("dissecting");
- dp = dissect(m, m->coldp, endp, gf, gl);
+ dp = dissect(charset, m, m->coldp, endp, gf, gl);
} else {
if (g->nplus > 0 && m->lastpos == NULL)
m->lastpos = (char **)malloc((g->nplus+1) *
@@ -170,7 +171,7 @@ int eflags;
return(REG_ESPACE);
}
NOTE("backref dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ dp = backref(charset, m, m->coldp, endp, gf, gl, (sopno)0);
}
if (dp != NULL)
break;
@@ -182,7 +183,7 @@ int eflags;
if (dp != NULL || endp <= m->coldp)
break; /* defeat */
NOTE("backoff");
- endp = slow(m, m->coldp, endp-1, gf, gl);
+ endp = slow(charset, m, m->coldp, endp-1, gf, gl);
if (endp == NULL)
break; /* defeat */
/* try it on a shorter possibility */
@@ -193,7 +194,7 @@ int eflags;
}
#endif
NOTE("backoff dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ dp = backref(charset, m, m->coldp, endp, gf, gl, (sopno)0);
}
assert(dp == NULL || dp == endp);
if (dp != NULL) /* found a shorter one */
@@ -235,7 +236,8 @@ int eflags;
== char *stop, sopno startst, sopno stopst);
*/
static char * /* == stop (success) always */
-dissect(m, start, stop, startst, stopst)
+dissect(charset, m, start, stop, startst, stopst)
+CHARSET_INFO *charset;
register struct match *m;
char *start;
char *stop;
@@ -299,10 +301,10 @@ sopno stopst;
stp = stop;
for (;;) {
/* how long could this one be? */
- rest = slow(m, sp, stp, ss, es);
+ rest = slow(charset, m, sp, stp, ss, es);
assert(rest != NULL); /* it did match */
/* could the rest match the rest? */
- tail = slow(m, rest, stop, es, stopst);
+ tail = slow(charset, m, rest, stop, es, stopst);
if (tail == stop)
break; /* yes! */
/* no -- try a shorter match for this one */
@@ -312,8 +314,8 @@ sopno stopst;
ssub = ss + 1;
esub = es - 1;
/* did innards match? */
- if (slow(m, sp, rest, ssub, esub) != NULL) {
- dp = dissect(m, sp, rest, ssub, esub);
+ if (slow(charset, m, sp, rest, ssub, esub) != NULL) {
+ dp = dissect(charset, m, sp, rest, ssub, esub);
assert(dp == rest);
} else /* no */
assert(sp == rest);
@@ -323,10 +325,10 @@ sopno stopst;
stp = stop;
for (;;) {
/* how long could this one be? */
- rest = slow(m, sp, stp, ss, es);
+ rest = slow(charset, m, sp, stp, ss, es);
assert(rest != NULL); /* it did match */
/* could the rest match the rest? */
- tail = slow(m, rest, stop, es, stopst);
+ tail = slow(charset, m, rest, stop, es, stopst);
if (tail == stop)
break; /* yes! */
/* no -- try a shorter match for this one */
@@ -338,7 +340,7 @@ sopno stopst;
ssp = sp;
oldssp = ssp;
for (;;) { /* find last match of innards */
- sep = slow(m, ssp, rest, ssub, esub);
+ sep = slow(charset, m, ssp, rest, ssub, esub);
if (sep == NULL || sep == ssp)
break; /* failed or matched null */
oldssp = ssp; /* on to next try */
@@ -350,8 +352,8 @@ sopno stopst;
ssp = oldssp;
}
assert(sep == rest); /* must exhaust substring */
- assert(slow(m, ssp, sep, ssub, esub) == rest);
- dp = dissect(m, ssp, sep, ssub, esub);
+ assert(slow(charset, m, ssp, sep, ssub, esub) == rest);
+ dp = dissect(charset, m, ssp, sep, ssub, esub);
assert(dp == sep);
sp = rest;
break;
@@ -359,10 +361,10 @@ sopno stopst;
stp = stop;
for (;;) {
/* how long could this one be? */
- rest = slow(m, sp, stp, ss, es);
+ rest = slow(charset, m, sp, stp, ss, es);
assert(rest != NULL); /* it did match */
/* could the rest match the rest? */
- tail = slow(m, rest, stop, es, stopst);
+ tail = slow(charset, m, rest, stop, es, stopst);
if (tail == stop)
break; /* yes! */
/* no -- try a shorter match for this one */
@@ -373,7 +375,7 @@ sopno stopst;
esub = ss + OPND(m->g->strip[ss]) - 1;
assert(OP(m->g->strip[esub]) == OOR1);
for (;;) { /* find first matching branch */
- if (slow(m, sp, rest, ssub, esub) == rest)
+ if (slow(charset, m, sp, rest, ssub, esub) == rest)
break; /* it matched all of it */
/* that one missed, try next one */
assert(OP(m->g->strip[esub]) == OOR1);
@@ -386,7 +388,7 @@ sopno stopst;
else
assert(OP(m->g->strip[esub]) == O_CH);
}
- dp = dissect(m, sp, rest, ssub, esub);
+ dp = dissect(charset, m, sp, rest, ssub, esub);
assert(dp == rest);
sp = rest;
break;
@@ -423,7 +425,8 @@ sopno stopst;
== char *stop, sopno startst, sopno stopst, sopno lev);
*/
static char * /* == stop (success) or NULL (failure) */
-backref(m, start, stop, startst, stopst, lev)
+backref(charset,m, start, stop, startst, stopst, lev)
+CHARSET_INFO *charset;
register struct match *m;
char *start;
char *stop;
@@ -486,8 +489,8 @@ sopno lev; /* PLUS nesting level */
(sp < m->endp && *(sp-1) == '\n' &&
(m->g->cflags&REG_NEWLINE)) ||
(sp > m->beginp &&
- !ISWORD(*(sp-1))) ) &&
- (sp < m->endp && ISWORD(*sp)) )
+ !ISWORD(charset,*(sp-1))) ) &&
+ (sp < m->endp && ISWORD(charset,*sp)) )
{ /* yes */ }
else
return(NULL);
@@ -496,8 +499,8 @@ sopno lev; /* PLUS nesting level */
if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
(sp < m->endp && *sp == '\n' &&
(m->g->cflags&REG_NEWLINE)) ||
- (sp < m->endp && !ISWORD(*sp)) ) &&
- (sp > m->beginp && ISWORD(*(sp-1))) )
+ (sp < m->endp && !ISWORD(charset,*sp)) ) &&
+ (sp > m->beginp && ISWORD(charset,*(sp-1))) )
{ /* yes */ }
else
return(NULL);
@@ -543,28 +546,28 @@ sopno lev; /* PLUS nesting level */
return(NULL);
while (m->g->strip[ss] != SOP(O_BACK, i))
ss++;
- return(backref(m, sp+len, stop, ss+1, stopst, lev));
+ return(backref(charset, m, sp+len, stop, ss+1, stopst, lev));
break;
case OQUEST_: /* to null or not */
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(charset, m, sp, stop, ss+1, stopst, lev);
if (dp != NULL)
return(dp); /* not */
- return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+ return(backref(charset, m, sp, stop, ss+OPND(s)+1, stopst, lev));
break;
case OPLUS_:
assert(m->lastpos != NULL);
assert(lev+1 <= m->g->nplus);
m->lastpos[lev+1] = sp;
- return(backref(m, sp, stop, ss+1, stopst, lev+1));
+ return(backref(charset, m, sp, stop, ss+1, stopst, lev+1));
break;
case O_PLUS:
if (sp == m->lastpos[lev]) /* last pass matched null */
- return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ return(backref(charset, m, sp, stop, ss+1, stopst, lev-1));
/* try another pass */
m->lastpos[lev] = sp;
- dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+ dp = backref(charset, m, sp, stop, ss-OPND(s)+1, stopst, lev);
if (dp == NULL)
- return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ return(backref(charset, m, sp, stop, ss+1, stopst, lev-1));
else
return(dp);
break;
@@ -573,7 +576,7 @@ sopno lev; /* PLUS nesting level */
esub = ss + OPND(s) - 1;
assert(OP(m->g->strip[esub]) == OOR1);
for (;;) { /* find first matching branch */
- dp = backref(m, sp, stop, ssub, esub, lev);
+ dp = backref(charset, m, sp, stop, ssub, esub, lev);
if (dp != NULL)
return(dp);
/* that one missed, try next one */
@@ -594,7 +597,7 @@ sopno lev; /* PLUS nesting level */
assert(0 < i && i <= m->g->nsub);
offsave = m->pmatch[i].rm_so;
m->pmatch[i].rm_so = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(charset, m, sp, stop, ss+1, stopst, lev);
if (dp != NULL)
return(dp);
m->pmatch[i].rm_so = offsave;
@@ -605,7 +608,7 @@ sopno lev; /* PLUS nesting level */
assert(0 < i && i <= m->g->nsub);
offsave = m->pmatch[i].rm_eo;
m->pmatch[i].rm_eo = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(charset, m, sp, stop, ss+1, stopst, lev);
if (dp != NULL)
return(dp);
m->pmatch[i].rm_eo = offsave;
@@ -628,7 +631,8 @@ sopno lev; /* PLUS nesting level */
== char *stop, sopno startst, sopno stopst);
*/
static char * /* where tentative match ended, or NULL */
-fast(m, start, stop, startst, stopst)
+fast(charset, m, start, stop, startst, stopst)
+CHARSET_INFO *charset;
register struct match *m;
char *start;
char *stop;
@@ -678,12 +682,12 @@ sopno stopst;
}
/* how about a word boundary? */
- if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
- (c != OUT && ISWORD(c)) ) {
+ if ( (flagch == BOL || (lastc != OUT && !ISWORD(charset,lastc))) &&
+ (c != OUT && ISWORD(charset,c)) ) {
flagch = BOW;
}
- if ( (lastc != OUT && ISWORD(lastc)) &&
- (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+ if ( (lastc != OUT && ISWORD(charset,lastc)) &&
+ (flagch == EOL || (c != OUT && !ISWORD(charset,c))) ) {
flagch = EOW;
}
if (flagch == BOW || flagch == EOW) {
@@ -719,7 +723,8 @@ sopno stopst;
== char *stop, sopno startst, sopno stopst);
*/
static char * /* where it ended */
-slow(m, start, stop, startst, stopst)
+slow(charset, m, start, stop, startst, stopst)
+CHARSET_INFO *charset;
register struct match *m;
char *start;
char *stop;
@@ -767,12 +772,12 @@ sopno stopst;
}
/* how about a word boundary? */
- if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
- (c != OUT && ISWORD(c)) ) {
+ if ( (flagch == BOL || (lastc != OUT && !ISWORD(charset,lastc))) &&
+ (c != OUT && ISWORD(charset,c)) ) {
flagch = BOW;
}
- if ( (lastc != OUT && ISWORD(lastc)) &&
- (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+ if ( (lastc != OUT && ISWORD(charset,lastc)) &&
+ (flagch == EOL || (c != OUT && !ISWORD(charset,c))) ) {
flagch = EOW;
}
if (flagch == BOW || flagch == EOW) {
diff --git a/regex/engine.ih b/regex/engine.ih
index c65733b5756..7cfcb39fb2d 100644
--- a/regex/engine.ih
+++ b/regex/engine.ih
@@ -4,11 +4,11 @@ extern "C" {
#endif
/* === engine.c === */
-static int matcher(register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
-static char *dissect(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *backref(register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
-static char *fast(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *slow(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static int matcher(CHARSET_INFO *charset,register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static char *dissect(CHARSET_INFO *charset,register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *backref(CHARSET_INFO *charset, register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
+static char *fast(CHARSET_INFO *charset, register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *slow(CHARSET_INFO *charset, register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
static states step(register struct re_guts *g, sopno start, sopno stop, register states bef, int ch, register states aft);
#define BOL (OUT+1)
#define EOL (BOL+1)
diff --git a/regex/main.c b/regex/main.c
index 7844a4d8384..f43a112a661 100644
--- a/regex/main.c
+++ b/regex/main.c
@@ -74,7 +74,7 @@ char *argv[];
exit(status);
}
- err = regcomp(&re, argv[optind++], copts);
+ err = regcomp(&re, argv[optind++], copts, &my_charset_latin1);
if (err) {
len = regerror(err, &re, erbuf, sizeof(erbuf));
fprintf(stderr, "error %s, %d/%d `%s'\n",
@@ -226,7 +226,7 @@ int opts; /* may not match f1 */
strcpy(f0copy, f0);
re.re_endp = (opts&REG_PEND) ? f0copy + strlen(f0copy) : NULL;
fixstr(f0copy);
- err = regcomp(&re, f0copy, opts);
+ err = regcomp(&re, f0copy, opts, &my_charset_latin1);
if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
/* unexpected error or wrong error */
len = regerror(err, &re, erbuf, sizeof(erbuf));
diff --git a/regex/regcomp.c b/regex/regcomp.c
index 6f8221a706d..d95a0ddf5d0 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -28,6 +28,7 @@ struct parse {
# define NPAREN 10 /* we need to remember () 1-9 for back refs */
sopno pbegin[NPAREN]; /* -> ( ([0] unused) */
sopno pend[NPAREN]; /* -> ) ([0] unused) */
+ CHARSET_INFO *charset; /* for ctype things */
};
#include "regcomp.ih"
@@ -99,10 +100,11 @@ static int never = 0; /* for use in asserts; shuts lint up */
= #define REG_DUMP 0200
*/
int /* 0 success, otherwise REG_something */
-regcomp(preg, pattern, cflags)
+regcomp(preg, pattern, cflags, charset)
regex_t *preg;
const char *pattern;
int cflags;
+CHARSET_INFO *charset;
{
struct parse pa;
register struct re_guts *g;
@@ -115,7 +117,8 @@ int cflags;
# define GOODFLAGS(f) ((f)&~REG_DUMP)
#endif
- regex_init(); /* Init cclass if neaded */
+ regex_init(charset); /* Init cclass if neaded */
+ preg->charset=charset;
cflags = GOODFLAGS(cflags);
if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
return(REG_INVARG);
@@ -146,6 +149,7 @@ int cflags;
p->end = p->next + len;
p->error = 0;
p->ncsalloc = 0;
+ p->charset = preg->charset;
for (i = 0; i < NPAREN; i++) {
p->pbegin[i] = 0;
p->pend[i] = 0;
@@ -327,7 +331,7 @@ register struct parse *p;
ordinary(p, c);
break;
case '{': /* okay as ordinary except if digit follows */
- if(REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT)) {}
+ if(REQUIRE(!MORE() || !my_isdigit(p->charset,PEEK()), REG_BADRPT)) {}
/* FALLTHROUGH */
default:
ordinary(p, c);
@@ -339,7 +343,8 @@ register struct parse *p;
c = PEEK();
/* we call { a repetition if followed by a digit */
if (!( c == '*' || c == '+' || c == '?' ||
- (c == '{' && MORE2() && isdigit(PEEK2())) ))
+ (c == '{' && MORE2() &&
+ my_isdigit(p->charset,PEEK2())) ))
return; /* no repetition, we're done */
NEXT();
@@ -368,7 +373,7 @@ register struct parse *p;
case '{':
count = p_count(p);
if (EAT(',')) {
- if (isdigit(PEEK())) {
+ if (my_isdigit(p->charset,PEEK())) {
count2 = p_count(p);
if(REQUIRE(count <= count2, REG_BADBR)) {}
} else /* single number with comma */
@@ -389,7 +394,8 @@ register struct parse *p;
return;
c = PEEK();
if (!( c == '*' || c == '+' || c == '?' ||
- (c == '{' && MORE2() && isdigit(PEEK2())) ) )
+ (c == '{' && MORE2() &&
+ my_isdigit(p->charset,PEEK2())) ) )
return;
SETERROR(REG_BADRPT);
}
@@ -546,7 +552,7 @@ int starordinary; /* is a leading * an ordinary character? */
} else if (EATTWO('\\', '{')) {
count = p_count(p);
if (EAT(',')) {
- if (MORE() && isdigit(PEEK())) {
+ if (MORE() && my_isdigit(p->charset,PEEK())) {
count2 = p_count(p);
if(REQUIRE(count <= count2, REG_BADBR)) {}
} else /* single number with comma */
@@ -577,7 +583,7 @@ register struct parse *p;
register int count = 0;
register int ndigits = 0;
- while (MORE() && isdigit(PEEK()) && count <= DUPMAX) {
+ while (MORE() && my_isdigit(p->charset,PEEK()) && count <= DUPMAX) {
count = count*10 + (GETNEXT() - '0');
ndigits++;
}
@@ -632,8 +638,8 @@ register struct parse *p;
register int ci;
for (i = p->g->csetsize - 1; i >= 0; i--)
- if (CHIN(cs, i) && isalpha(i)) {
- ci = othercase(i);
+ if (CHIN(cs, i) && my_isalpha(p->charset,i)) {
+ ci = othercase(p->charset,i);
if (ci != i)
CHadd(cs, ci);
}
@@ -744,7 +750,7 @@ register cset *cs;
register char *u;
register char c;
- while (MORE() && isalpha(PEEK()))
+ while (MORE() && my_isalpha(p->charset,PEEK()))
NEXT();
len = p->next - sp;
for (cp = cclasses; cp->name != NULL; cp++)
@@ -837,14 +843,15 @@ int endc; /* name ended by endc,']' */
== static char othercase(int ch);
*/
static char /* if no counterpart, return ch */
-othercase(ch)
+othercase(charset,ch)
+CHARSET_INFO *charset;
int ch;
{
- assert(isalpha(ch));
- if (isupper(ch))
- return(tolower(ch));
- else if (islower(ch))
- return(toupper(ch));
+ assert(my_isalpha(charset,ch));
+ if (my_isupper(charset,ch))
+ return(my_tolower(charset,ch));
+ else if (my_islower(charset,ch))
+ return(my_toupper(charset,ch));
else /* peculiar, but could happen */
return(ch);
}
@@ -887,7 +894,8 @@ register int ch;
{
register cat_t *cap = p->g->categories;
- if ((p->g->cflags&REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+ if ((p->g->cflags&REG_ICASE) && my_isalpha(p->charset,ch) &&
+ othercase(p->charset,ch) != ch)
bothcases(p, ch);
else {
EMIT(OCHAR, (unsigned char)ch);
diff --git a/regex/regcomp.ih b/regex/regcomp.ih
index 4ae45bbf4a9..32f1f6e89eb 100644
--- a/regex/regcomp.ih
+++ b/regex/regcomp.ih
@@ -16,7 +16,7 @@ static void p_b_cclass(register struct parse *p, register cset *cs);
static void p_b_eclass(register struct parse *p, register cset *cs);
static char p_b_symbol(register struct parse *p);
static char p_b_coll_elem(register struct parse *p, int endc);
-static char othercase(int ch);
+static char othercase(CHARSET_INFO *charset,int ch);
static void bothcases(register struct parse *p, int ch);
static void ordinary(register struct parse *p, register int ch);
static void nonnewline(register struct parse *p);
diff --git a/regex/regex.h b/regex/regex.h
index 99a0077251e..e0fb0c77dc9 100644
--- a/regex/regex.h
+++ b/regex/regex.h
@@ -5,6 +5,8 @@
extern "C" {
#endif
+#include "m_ctype.h"
+
/* === regex2.h === */
#ifdef _WIN64
typedef __int64 regoff_t;
@@ -17,6 +19,7 @@ typedef struct {
size_t re_nsub; /* number of parenthesized subexpressions */
const char *re_endp; /* end pointer for REG_PEND */
struct re_guts *re_g; /* none of your business :-) */
+ CHARSET_INFO *charset; /* For ctype things */
} regex_t;
typedef struct {
regoff_t rm_so; /* start of match */
@@ -25,7 +28,7 @@ typedef struct {
/* === regcomp.c === */
-extern int regcomp(regex_t *, const char *, int);
+extern int regcomp(regex_t *, const char *, int, CHARSET_INFO *charset);
#define REG_BASIC 0000
#define REG_EXTENDED 0001
#define REG_ICASE 0002
@@ -73,7 +76,7 @@ extern void regfree(regex_t *);
/* === reginit.c === */
-extern void regex_init(void); /* Should be called for multithread progs */
+extern void regex_init(CHARSET_INFO *cs); /* Should be called for multithread progs */
extern void regex_end(void); /* If one wants a clean end */
#ifdef __cplusplus
diff --git a/regex/regex2.h b/regex/regex2.h
index 0d94baa310f..bba54ea2054 100644
--- a/regex/regex2.h
+++ b/regex/regex2.h
@@ -140,6 +140,6 @@ struct re_guts {
/* misc utilities */
#undef OUT /* May be defined in windows */
#define OUT (CHAR_MAX+1) /* a non-character value */
-#define ISWORD(c) (isalnum(c) || (c) == '_')
+#define ISWORD(s,c) (my_isalnum(s,c) || (c) == '_')
#endif /* __regex2_h__ */
diff --git a/regex/regexec.c b/regex/regexec.c
index 7f2704f8214..723289bd0ad 100644
--- a/regex/regexec.c
+++ b/regex/regexec.c
@@ -133,7 +133,7 @@ int eflags;
if ((size_t) g->nstates <= CHAR_BIT*sizeof(states1) &&
!(eflags&REG_LARGE))
- return(smatcher(g, (char *)str, nmatch, pmatch, eflags));
+ return(smatcher(preg->charset, g, (char *)str, nmatch, pmatch, eflags));
else
- return(lmatcher(g, (char *)str, nmatch, pmatch, eflags));
+ return(lmatcher(preg->charset, g, (char *)str, nmatch, pmatch, eflags));
}
diff --git a/regex/reginit.c b/regex/reginit.c
index 18647c386fc..09ffff37ef0 100644
--- a/regex/reginit.c
+++ b/regex/reginit.c
@@ -7,7 +7,7 @@
static bool regex_inited=0;
-void regex_init()
+void regex_init(CHARSET_INFO *cs)
{
char buff[CCLASS_LAST][256];
int count[CCLASS_LAST];
@@ -20,27 +20,27 @@ void regex_init()
for (i=1 ; i<= 255; i++)
{
- if (isalnum(i))
+ if (my_isalnum(cs,i))
buff[CCLASS_ALNUM][count[CCLASS_ALNUM]++]=(char) i;
- if (isalpha(i))
+ if (my_isalpha(cs,i))
buff[CCLASS_ALPHA][count[CCLASS_ALPHA]++]=(char) i;
- if (iscntrl(i))
+ if (my_iscntrl(cs,i))
buff[CCLASS_CNTRL][count[CCLASS_CNTRL]++]=(char) i;
- if (isdigit(i))
+ if (my_isdigit(cs,i))
buff[CCLASS_DIGIT][count[CCLASS_DIGIT]++]=(char) i;
- if (isgraph(i))
+ if (my_isgraph(cs,i))
buff[CCLASS_GRAPH][count[CCLASS_GRAPH]++]=(char) i;
- if (islower(i))
+ if (my_islower(cs,i))
buff[CCLASS_LOWER][count[CCLASS_LOWER]++]=(char) i;
- if (isprint(i))
+ if (my_isprint(cs,i))
buff[CCLASS_PRINT][count[CCLASS_PRINT]++]=(char) i;
- if (ispunct(i))
+ if (my_ispunct(cs,i))
buff[CCLASS_PUNCT][count[CCLASS_PUNCT]++]=(char) i;
- if (isspace(i))
+ if (my_isspace(cs,i))
buff[CCLASS_SPACE][count[CCLASS_SPACE]++]=(char) i;
- if (isupper(i))
+ if (my_isupper(cs,i))
buff[CCLASS_UPPER][count[CCLASS_UPPER]++]=(char) i;
- if (isxdigit(i))
+ if (my_isxdigit(cs,i))
buff[CCLASS_XDIGIT][count[CCLASS_XDIGIT]++]=(char) i;
}
buff[CCLASS_BLANK][0]=' ';
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 8f17d8519b8..458097499c9 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -20,7 +20,7 @@ bin_SCRIPTS = @server_scripts@ \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
- mysql_fix_extensions \
+ mysql_fix_extensions \
mysql_setpermission \
mysql_secure_installation \
mysql_zap \
@@ -38,7 +38,7 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \
msql2mysql.sh \
mysql_config.sh \
mysql_fix_privilege_tables.sh \
- mysql_fix_extensions.sh \
+ mysql_fix_extensions.sh \
mysql_install_db.sh \
mysql_setpermission.sh \
mysql_secure_installation.sh \
@@ -48,15 +48,17 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \
mysql_convert_table_format.sh \
mysql_find_rows.sh \
mysqlhotcopy.sh \
- mysqldumpslow.sh \
+ mysqldumpslow.sh \
mysql_explain_log.sh \
mysqld_multi.sh \
mysql_tableinfo.sh \
- mysqld_safe.sh
+ mysqld_safe.sh \
+ fill_help_tables.sh
EXTRA_DIST = $(EXTRA_SCRIPTS) \
mysqlaccess.conf \
- mysqlbug
+ mysqlbug \
+ fill_help_tables.sql
pkgdata_DATA = make_binary_distribution
@@ -67,7 +69,7 @@ CLEANFILES = @server_scripts@ \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
- mysql_fix_extensions \
+ mysql_fix_extensions \
mysql_setpermission \
mysql_secure_installation \
mysql_zap \
@@ -76,7 +78,9 @@ CLEANFILES = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
- mysqld_multi
+ mysqld_multi \
+ fill_help_tables \
+ fill_help_tables.sql
SUPERCLEANFILES = mysqlbug
@@ -130,3 +134,8 @@ SUFFIXES = .sh
# Don't update the files from bitkeeper
%::SCCS/s.%
+
+all: fill_help_tables.sql
+
+fill_help_tables.sql: fill_help_tables ../Docs/manual.texi
+ ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql
diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh
new file mode 100644
index 00000000000..52dfa018d6e
--- /dev/null
+++ b/scripts/fill_help_tables.sh
@@ -0,0 +1,239 @@
+#!@PERL@
+#
+# Usage: fill_help_tables <manual.texi>
+# Example: ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql
+#
+# This script generates the SQL statements required by mysql_install_db to
+# fill up the tables for the server-side online function help, which can be
+# invoked with "help <function>" from the MySQL client.
+#
+# Please note, that you first need to update Docs/manual.texi with the
+# manual file from the separate "mysqldoc" BitKeeper-Tree! The manual.texi
+# included in the source tree is just an empty stub file - the full manual
+# is now maintained in a separate tree.
+#
+# Original version by Victor Vagin <vva@mysql.com>
+#
+
+my $cat_name= "";
+my $func_name= "";
+my $text= "";
+my $example= "";
+
+local $mode= "";
+
+sub prepare_name
+{
+ my ($a)= @_;
+
+ $a =~ s/(\@itemize \@bullet)/ /g;
+ $a =~ s/(\@end itemize)/ /g;
+ $a =~ s/(\@end multitable)/ /g;
+ $a =~ s/(\@end table)/ /g;
+ $a =~ s/(\@cindex(.*?)\n)/ /g;
+ $a =~ s/(\@multitable \@columnfractions(.*?)\n)/ /g;
+ $a =~ s/(\@node(.*?)\n)/ /g;
+ $a =~ s/(\@tab)/\t/g;
+ $a =~ s/\@item/ /g;
+ $a =~ s/\@code\{((.|\n)+?)\}/$1/go;
+ $a =~ s/\@strong\{(.+?)\}/$1/go;
+ $a =~ s/\@samp\{(.+?)\}/$1/go;
+ $a =~ s/\@emph\{((.|\n)+?)\}/\/$1\//go;
+ $a =~ s/\@xref\{((.|\n)+?)\}/See also : [$1]/go;
+ $a =~ s/\@ref\{((.|\n)+?)\}/[$1]/go;
+ $a =~ s/\'/\'\'/g;
+ $a =~ s/\\/\\\\/g;
+ $a =~ s/\`/\`\`/g;
+
+ $a =~ s/\@table \@code/ /g;
+
+ $a =~ s/\(\)//g;
+
+ $a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3/gxs; #$a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3 $1/gxs;
+ $a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1/gxs;#$a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1 $2/gxs;
+ $a =~ s/((\w|\s)+)\((.+)\)/$1/gxs;
+
+ return $a;
+}
+
+sub prepare_text
+{
+ my ($a)= @_;
+
+ $a =~ s/(\@itemize \@bullet)/ /g;
+ $a =~ s/(\@end itemize)/ /g;
+ $a =~ s/(\@end multitable)/ /g;
+ $a =~ s/(\@end table)/ /g;
+ $a =~ s/(\@cindex(.*?)\n)/ /g;
+ $a =~ s/(\@multitable \@columnfractions(.*?)\n)/ /g;
+ $a =~ s/(\@node(.*?)\n)/ /g;
+ $a =~ s/(\@tab)/\t/g;
+ $a =~ s/\@itemx/ /g;
+ $a =~ s/\@item/ /g;
+ $a =~ s/\@code\{((.|\n)+?)\}/$1/go;
+ $a =~ s/\@strong\{(.+?)\}/$1/go;
+ $a =~ s/\@samp\{(.+?)\}/$1/go;
+ $a =~ s/\@emph\{((.|\n)+?)\}/\/$1\//go;
+ $a =~ s/\@xref\{((.|\n)+?)\}/See also : [$1]/go;
+ $a =~ s/\@ref\{((.|\n)+?)\}/[$1]/go;
+ $a =~ s/\'/\'\'/g;
+ $a =~ s/\\/\\\\/g;
+ $a =~ s/\`/\`\`/g;
+ $a =~ s/(\n*?)$//g;
+ $a =~ s/\n/\\n/g;
+
+ $a =~ s/\@table \@code/ /g;
+
+ return $a;
+}
+
+sub prepare_example
+{
+ my ($a)= @_;
+
+ $a =~ s/\'/\'\'/g;
+ $a =~ s/\\/\\\\/g;
+ $a =~ s/\`/\`\`/g;
+ $a =~ s/(\n*?)$//g;
+ $a =~ s/\n/\\n/g;
+
+ return $a;
+}
+
+sub flush_all
+{
+ my ($mode) = @_;
+
+ if ($mode eq ""){return;}
+
+ $func_name= prepare_name($func_name);
+ $text= prepare_text($text);
+ $example= prepare_example($example);
+
+ if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){
+ print "INSERT INTO help_topic (name,description,example) VALUES (";
+ print "'$func_name',";
+ print "'$text',";
+ print "'$example'";
+ print ");\n";
+ print "INSERT INTO help_relation (help_category_id,help_topic_id) VALUES (\@cur_category,LAST_INSERT_ID());\n";
+ }
+
+ $func_name= "";
+ $text= "";
+ $example= "";
+ $mode= "";
+}
+
+sub new_category
+{
+ my ($category)= @_;
+
+ $category= prepare_text($category);
+
+ print "INSERT INTO help_category (name) VALUES (\'$category\');\n";
+ print "SET \@cur_category=LAST_INSERT_ID();\n";
+}
+
+#print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n";
+#print "CREATE DATABASE mysql_help;\n";
+
+print "USE mysql;\n";
+
+print "DROP TABLE IF EXISTS help_topic;\n";
+print "CREATE TABLE help_topic (";
+print " help_topic_id int unsigned not null auto_increment,";
+print " name varchar(64) not null,";
+print " description text not null,";
+print " example text not null,";
+print " url varchar(128) not null,";
+print " primary key (help_topic_id),";
+print " unique index(name)";
+print ") type=myisam;\n\n";
+
+print "DROP TABLE IF EXISTS help_category;\n";
+print "CREATE TABLE help_category (";
+print " help_category_id smallint unsigned not null auto_increment,";
+print " name varchar(64) not null,";
+print " url varchar(128) not null,";
+print " primary key (help_category_id),";
+print " unique index (name)";
+print ") type=myisam;\n\n";
+
+print "DROP TABLE IF EXISTS help_relation;\n";
+print "CREATE TABLE help_relation (";
+print" help_topic_id int unsigned not null references help_topic,";
+print" help_category_id smallint unsigned not null references help_category,";
+print" primary key (help_category_id, help_topic_id),";
+print ") type=myisam;\n\n";
+
+print "SET \@cur_category=null;\n\n";
+
+my $in_section_6_3= 0;
+
+for(<>)
+{
+ if ($_=~/\@section Functions for Use in \@code{SELECT} and \@code{WHERE} Clauses/ &&
+ !$in_section_6_3){
+ $in_section_6_3= 1;
+ next;
+ }
+
+ if ($_=~/\@section/ && $in_section_6_3){
+ $in_section_6_3= 0;
+ next;
+ }
+
+ if (!$in_section_6_3) { next; }
+
+ my $c_name= "";
+
+ ($c_name)=m|\@c for_mysql_help,(.+?)$|;
+ if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){
+ ($cat_name)= $c_name;
+ new_category($cat_name);
+ next;
+ }
+
+ ($c_name)=m|\@subsubsection (.+?)$|;
+ if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){
+ ($cat_name)= $c_name;
+ new_category($cat_name);
+ next;
+ }
+
+ ($c_name)=m|\@subsection (.+?)$|;
+ if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){
+ ($cat_name)= $c_name;
+ new_category($cat_name);
+ next;
+ }
+
+ ($f_name)=m|\@findex (.+?)$|;
+ if (!($f_name eq "")){
+ flush_all($mode);
+ ($func_name)= ($f_name);
+ $mode= "text";
+ next;
+ }
+
+ if ($_=~/\@example/ && ($mode eq "text")){
+ $mode= "example";
+ next;
+ }
+
+ if ($_=~/\@end example/ && ($mode eq "example")){
+ flush_all($mode);
+ next;
+ }
+
+ if ($mode eq "text") { $text .= $_; }
+ if ($mode eq "example") { $example .= $_; }
+}
+
+
+print "DELETE help_category ";
+print "FROM help_category ";
+print "LEFT JOIN help_relation ON help_category.help_category_id=help_relation.help_category_id ";
+print "WHERE help_relation.help_category_id is null;"
+
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 09259779855..83ee5023b89 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -183,6 +183,15 @@ add max_updates int(11) unsigned NOT NULL AFTER max_questions,
add max_connections int(11) unsigned NOT NULL AFTER max_updates;
END_OF_DATA
+# Increase password length to handle new passwords
+
+@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+alter table user
+change password password char(45) not null;
+END_OF_DATA
+
+
+
#
# Add Create_tmp_table_priv and Lock_tables_priv to db and host
#
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 2f27f5d7c1a..862cffb0cb7 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -213,7 +213,7 @@ then
c_u="$c_u CREATE TABLE user ("
c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL,"
c_u="$c_u User char(16) binary DEFAULT '' NOT NULL,"
- c_u="$c_u Password char(16) binary DEFAULT '' NOT NULL,"
+ c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL,"
c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
@@ -307,8 +307,8 @@ then
fi
echo "Installing all prepared tables"
-if eval "$execdir/mysqld $defaults --bootstrap --skip-grant-tables \
- --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $args" << END_OF_DATA
+if (
+ cat << END_OF_DATA
use mysql;
$c_d
$i_d
@@ -325,6 +325,9 @@ $i_f
$c_t
$c_c
END_OF_DATA
+ cat fill_help_tables.sql
+) | eval "$execdir/mysqld $defaults --bootstrap --skip-grant-tables \
+ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $args"
then
echo ""
if test "$IN_RPM" -eq 0
diff --git a/sql-bench/test-insert.sh b/sql-bench/test-insert.sh
index b61ad00b557..fa8c4e98b54 100644
--- a/sql-bench/test-insert.sh
+++ b/sql-bench/test-insert.sh
@@ -282,6 +282,57 @@ if ($limits->{'unique_index'})
select_test:
+# ----------------- prepared+executed/prepared*executed tests
+
+print "Test of prepared+execute/once prepared many execute selects\n";
+$loop_time=new Benchmark;
+
+for ($i=1 ; $i <= $opt_loop_count ; $i++)
+{
+ my ($key_value)=$random[$i];
+ my ($query)= "select * from bench1 where id=$key_value";
+ print "$query\n" if ($opt_debug);
+ $sth = $dbh->prepare($query);
+ if (! $sth)
+ {
+ die "error in prepare select with id = $key_value : $DBI::errstr";
+ };
+ if (! $sth->execute)
+ {
+ die "cannot execute prepare select with id = $key_value : $DBI::errstr";
+ }
+ while ($sth->fetchrow_arrayref) { };
+ $sth->finish;
+};
+$end_time=new Benchmark;
+print "Time for prepared_select ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+$loop_time=new Benchmark;
+$query= "select * from bench1 where id=?";
+$sth = $dbh->prepare($query);
+if (! $sth)
+{
+ die "cannot prepare select: $DBI::errstr";
+};
+
+for ($i=1 ; $i <= $opt_loop_count ; $i++)
+{
+ my ($key_value)=$random[$i];
+ $sth->bind_param(1,$key_value);
+ print "$query , id = $key_value\n" if ($opt_debug);
+ if (! $sth->execute)
+ {
+ die "cannot execute prepare select with id = $key_value : $DBI::errstr";
+ }
+ while ($sth->fetchrow_arrayref) { };
+};
+$sth->finish;
+$end_time=new Benchmark;
+print "Time for once_prepared_select ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+
print "Retrieving data from the table\n";
$loop_time=new Benchmark;
$error=0;
diff --git a/sql/Makefile.am b/sql/Makefile.am
index a589f1379f9..b1d9149ddf4 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -22,9 +22,8 @@ MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
INCLUDES = @MT_INCLUDES@ \
@bdb_includes@ @innodb_includes@ \
- -I$(srcdir)/../include \
- -I$(srcdir)/../regex \
- -I$(srcdir) -I../include -I. $(openssl_includes)
+ -I$(top_srcdir)/include -I$(top_srcdir)/regex \
+ -I$(srcdir) $(openssl_includes)
WRAPLIBS= @WRAPLIBS@
SUBDIRS = share
libexec_PROGRAMS = mysqld
@@ -46,27 +45,31 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
$(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ @openssl_libs@
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
item_strfunc.h item_timefunc.h item_uniq.h \
- item_create.h mysql_priv.h \
+ item_create.h item_subselect.h item_row.h \
+ mysql_priv.h \
procedure.h sql_class.h sql_lex.h sql_list.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
field.h handler.h \
ha_isammrg.h ha_isam.h ha_myisammrg.h\
ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
- opt_range.h opt_ft.h \
+ opt_range.h opt_ft.h protocol.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
log_event.h mini_client.h sql_repl.h slave.h \
- stacktrace.h sql_sort.h sql_cache.h set_var.h
+ stacktrace.h sql_sort.h sql_cache.h set_var.h \
+ spatial.h gstream.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
- thr_malloc.cc item_create.cc \
+ thr_malloc.cc item_create.cc item_subselect.cc \
+ item_row.cc \
field.cc key.cc sql_class.cc sql_list.cc \
- net_serv.cc net_pkg.cc lock.cc my_lock.c \
+ net_serv.cc protocol.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc set_var.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
+ sql_prepare.cc sql_error.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \
@@ -79,9 +82,10 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
- slave.cc sql_repl.cc sql_union.cc \
+ slave.cc sql_repl.cc sql_union.cc sql_derived.cc \
mini_client.cc mini_client_errors.c \
- stacktrace.c repl_failsafe.h repl_failsafe.cc sql_olap.cc
+ stacktrace.c repl_failsafe.h repl_failsafe.cc sql_olap.cc\
+ gstream.cc spatial.cc sql_help.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
diff --git a/sql/convert.cc b/sql/convert.cc
index e4ae13d1e07..84003af3922 100644
--- a/sql/convert.cc
+++ b/sql/convert.cc
@@ -433,7 +433,7 @@ CONVERT *get_convert_set(const char *name)
{
for (CONVERT **ptr=convert_tables ; *ptr ; ptr++)
{
- if (!my_strcasecmp((*ptr)->name,name))
+ if (!my_strcasecmp(&my_charset_latin1,(*ptr)->name,name))
return (*ptr);
}
return 0;
@@ -457,9 +457,6 @@ bool CONVERT::store(String *packet,const char *from,uint length)
return 1;
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
(ulonglong)length);
-
- for (const char *end=from+length ; from != end ; from++)
- *to++= to_map[(uchar) *from];
- packet->length((uint) (to-packet->ptr()));
+ packet->length((uint) (store_dest(to, from, length)-packet->ptr()));
return 0;
}
diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc
index 891cf18ee53..5b25819b657 100644
--- a/sql/des_key_file.cc
+++ b/sql/des_key_file.cc
@@ -34,6 +34,8 @@ static int initialized;
1 Error
*/
+#define des_cs &my_charset_latin1
+
bool
load_des_key_file(const char *file_name)
{
@@ -70,9 +72,10 @@ load_des_key_file(const char *file_name)
{
offset=(char) (offset - '0');
// Remove newline and possible other control characters
- for (start=buf+1 ; isspace(*start) ; start++) ;
+ for (start=buf+1 ; my_isspace(des_cs, *start) ; start++) ;
end=buf+length;
- for (end=strend(buf) ; end > start && !isgraph(end[-1]) ; end--) ;
+ for (end=strend(buf) ;
+ end > start && !my_isgraph(des_cs, end[-1]) ; end--) ;
if (start != end)
{
diff --git a/sql/field.cc b/sql/field.cc
index aae4fac2a38..697de878c03 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -15,16 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*
- NOTES:
- Some of the number class uses the system functions strtol(), strtoll()...
- To avoid patching the end \0 or copying the buffer unnecessary, all calls
- to system functions are wrapped to a String object that adds the end null
- if it only if it isn't there.
- This adds some overhead when assigning numbers from strings but makes
- everything simpler.
- */
-
/*****************************************************************************
** This file implements classes defined in field.h
*****************************************************************************/
@@ -44,8 +34,6 @@
// Maximum allowed exponent value for converting string to decimal
#define MAX_EXPONENT 1024
-
-
/*****************************************************************************
Instansiate templates and static variables
*****************************************************************************/
@@ -77,44 +65,54 @@ void Field_num::prepend_zeros(String *value)
/*
Test if given number is a int (or a fixed format float with .000)
- This is only used to give warnings in ALTER TABLE or LOAD DATA...
+
+ SYNOPSIS
+ test_if_int()
+ str String to test
+ end Pointer to char after last used digit
+ cs Character set
+
+ NOTES
+ This is called after one has called my_strntol() or similar function.
+ This is only used to give warnings in ALTER TABLE or LOAD DATA...
+
+ TODO
+ Make this multi-byte-character safe
+
+ RETURN
+ 0 ok
+ 1 error
*/
-bool test_if_int(const char *str,int length)
+bool test_if_int(const char *str, int length, const char *int_end,
+ CHARSET_INFO *cs)
{
+ if (str == int_end)
+ return 0; // Empty string
const char *end=str+length;
+ if ((str= int_end) == end)
+ return 1; // All digits was used
- while (str != end && isspace(*str)) // Allow start space
- str++; /* purecov: inspected */
- if (str != end && (*str == '-' || *str == '+'))
- str++;
- if (str == end)
- return 0; // Error: Empty string
- for (; str != end ; str++)
+ /* Allow end .0000 */
+ if (*str == '.')
{
- if (!isdigit(*str))
- {
- if (*str == '.')
- { // Allow '.0000'
- for (str++ ; str != end && *str == '0'; str++) ;
- if (str == end)
- return 1;
- }
- if (!isspace(*str))
- return 0;
- for (str++ ; str != end ; str++)
- if (!isspace(*str))
- return 0;
- return 1;
- }
+ for (str++ ; str != end && *str == '0'; str++) ;
+ }
+ /* Allow end space */
+ for (str++ ; str != end ; str++)
+ {
+ if (!my_isspace(cs,*str))
+ return 0;
}
return 1;
}
-static bool test_if_real(const char *str,int length)
+static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
{
- while (length && isspace(*str))
+ cs= system_charset_info; // QQ move test_if_real into CHARSET_INFO struct
+
+ while (length && my_isspace(cs,*str))
{ // Allow start space
length--; str++;
}
@@ -123,10 +121,10 @@ static bool test_if_real(const char *str,int length)
if (*str == '+' || *str == '-')
{
length--; str++;
- if (!length || !(isdigit(*str) || *str == '.'))
+ if (!length || !(my_isdigit(cs,*str) || *str == '.'))
return 0;
}
- while (length && isdigit(*str))
+ while (length && my_isdigit(cs,*str))
{
length--; str++;
}
@@ -135,7 +133,7 @@ static bool test_if_real(const char *str,int length)
if (*str == '.')
{
length--; str++;
- while (length && isdigit(*str))
+ while (length && my_isdigit(cs,*str))
{
length--; str++;
}
@@ -144,18 +142,19 @@ static bool test_if_real(const char *str,int length)
return 1;
if (*str == 'E' || *str == 'e')
{
- if (length < 3 || (str[1] != '+' && str[1] != '-') || !isdigit(str[2]))
+ if (length < 3 || (str[1] != '+' && str[1] != '-') ||
+ !my_isdigit(cs,str[2]))
return 0;
length-=3;
str+=3;
- while (length && isdigit(*str))
+ while (length && my_isdigit(cs,*str))
{
length--; str++;
}
}
for (; length ; length--, str++)
{ // Allow end space
- if (!isspace(*str))
+ if (!my_isspace(cs,*str))
return 0;
}
return 1;
@@ -179,6 +178,8 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
field_length(length_arg),null_bit(null_bit_arg)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
+ comment.str= (char*) "";
+ comment.length=0;
}
uint Field::offset()
@@ -198,23 +199,17 @@ void Field::copy_from_tmp(int row_offset)
}
-bool Field::send(THD *thd, String *packet)
+bool Field::send_binary(Protocol *protocol)
{
- if (is_null())
- return net_store_null(packet);
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff),charset());
val_str(&tmp,&tmp);
- CONVERT *convert;
- if ((convert=thd->variables.convert_set))
- return convert->store(packet,tmp.ptr(),tmp.length());
- return net_store_data(packet,tmp.ptr(),tmp.length());
+ return protocol->store(tmp.ptr(), tmp.length());
}
void Field_num::add_zerofill_and_unsigned(String &res) const
{
- res.length((uint) strlen(res.ptr())); // Fix length
if (unsigned_flag)
res.append(" unsigned");
if (zerofill)
@@ -223,8 +218,12 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
void Field_num::make_field(Send_field *field)
{
+ /* table_cache_key is not set for temp tables */
+ field->db_name=table->table_cache_key ? table->table_cache_key : "";
+ field->org_table_name=table->real_name;
field->table_name=table_name;
- field->col_name=field_name;
+ field->col_name=field->org_col_name=field_name;
+ field->charsetnr= charset()->number;
field->length=field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
@@ -234,8 +233,12 @@ void Field_num::make_field(Send_field *field)
void Field_str::make_field(Send_field *field)
{
+ /* table_cache_key is not set for temp tables */
+ field->db_name=table->table_cache_key ? table->table_cache_key : "";
+ field->org_table_name=table->real_name;
field->table_name=table_name;
- field->col_name=field_name;
+ field->col_name=field->org_col_name=field_name;
+ field->charsetnr= charset()->number;
field->length=field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
@@ -243,6 +246,26 @@ void Field_str::make_field(Send_field *field)
}
+void Field_str::add_binary_or_charset(String &res) const
+{
+ if (binary())
+ res.append(" binary");
+ else if (field_charset != table->table_charset &&
+ !(current_thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) &&
+ !(current_thd->variables.sql_mode & MODE_MYSQL323) &&
+ !(current_thd->variables.sql_mode & MODE_MYSQL40) &&
+ !(current_thd->variables.sql_mode & MODE_POSTGRESQL) &&
+ !(current_thd->variables.sql_mode & MODE_ORACLE) &&
+ !(current_thd->variables.sql_mode & MODE_MSSQL) &&
+ !(current_thd->variables.sql_mode & MODE_DB2) &&
+ !(current_thd->variables.sql_mode & MODE_SAPDB))
+ {
+ res.append(" character set ");
+ res.append(field_charset->csname);
+ }
+}
+
+
uint Field::fill_cache_field(CACHE_FIELD *copy)
{
copy->str=ptr;
@@ -266,7 +289,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
bool Field::get_date(TIME *ltime,bool fuzzydate)
{
char buff[40];
- String tmp(buff,sizeof(buff)),tmp2,*res;
+ String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res;
if (!(res=val_str(&tmp,&tmp2)) ||
str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE)
return 1;
@@ -276,7 +299,7 @@ bool Field::get_date(TIME *ltime,bool fuzzydate)
bool Field::get_time(TIME *ltime)
{
char buff[40];
- String tmp(buff,sizeof(buff)),tmp2,*res;
+ String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res;
if (!(res=val_str(&tmp,&tmp2)) ||
str_to_time(res->ptr(),res->length(),ltime))
return 1;
@@ -290,24 +313,26 @@ void Field::store_time(TIME *ltime,timestamp_type type)
char buff[25];
switch (type) {
case TIMESTAMP_NONE:
- store("",0); // Probably an error
+ store("",0,&my_charset_bin); // Probably an error
break;
case TIMESTAMP_DATE:
sprintf(buff,"%04d-%02d-%02d", ltime->year,ltime->month,ltime->day);
- store(buff,10);
+ store(buff,10,&my_charset_bin);
break;
case TIMESTAMP_FULL:
sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
ltime->year,ltime->month,ltime->day,
ltime->hour,ltime->minute,ltime->second);
- store(buff,19);
+ store(buff,19,&my_charset_bin);
break;
case TIMESTAMP_TIME:
- sprintf(buff, "%02d:%02d:%02d",
- ltime->hour,ltime->minute,ltime->second);
- store(buff,(uint) strlen(buff));
+ {
+ ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
+ ltime->hour,ltime->minute,ltime->second));
+ store(buff,(uint) length, &my_charset_bin);
break;
}
+ }
}
@@ -317,6 +342,16 @@ bool Field::optimize_range(uint idx)
}
/****************************************************************************
+ Field_null, a field that always return NULL
+****************************************************************************/
+
+void Field_null::sql_type(String &res) const
+{
+ res.set_latin1("null", 4);
+}
+
+
+/****************************************************************************
Functions for the Field_decimal class
This is an number stored as a pre-space (or pre-zero) string
****************************************************************************/
@@ -324,7 +359,7 @@ bool Field::optimize_range(uint idx)
void
Field_decimal::reset(void)
{
- Field_decimal::store("0",1);
+ Field_decimal::store("0",1,&my_charset_bin);
}
void Field_decimal::overflow(bool negative)
@@ -366,8 +401,19 @@ void Field_decimal::overflow(bool negative)
}
-void Field_decimal::store(const char *from,uint len)
+int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
{
+ char buff[80];
+ String tmp(buff,sizeof(buff), &my_charset_bin);
+
+ /* Convert character set if the old one is multi byte */
+ if (cs->mbmaxlen > 1)
+ {
+ tmp.copy(from, len, cs, &my_charset_bin);
+ from= tmp.ptr();
+ len= tmp.length();
+ }
+
const char *end= from+len;
/* The pointer where the field value starts (i.e., "where to write") */
char *to=ptr;
@@ -377,13 +423,13 @@ void Field_decimal::store(const char *from,uint len)
specified), '+' or '-'
*/
char sign_char=0;
- /* The pointers where prezeros start and stop */
+ /* The pointers where prezeros start and stop */
const char *pre_zeros_from, *pre_zeros_end;
- /* The pointers where digits at the left of '.' start and stop */
+ /* The pointers where digits at the left of '.' start and stop */
const char *int_digits_from, *int_digits_end;
- /* The pointers where digits at the right of '.' start and stop */
+ /* The pointers where digits at the right of '.' start and stop */
const char *frac_digits_from, *frac_digits_end;
- /* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
+ /* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
char expo_sign_char=0;
uint exponent=0; // value of the exponent
/*
@@ -393,21 +439,21 @@ void Field_decimal::store(const char *from,uint len)
const char *int_digits_tail_from;
/* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */
uint int_digits_added_zeros;
- /*
- Pointer used when digits move from the right of the '.' to the left
- of the '.'
- */
+ /*
+ Pointer used when digits move from the right of the '.' to the left
+ of the '.'
+ */
const char *frac_digits_head_end;
- /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
+ /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
uint frac_digits_added_zeros;
char *pos,*tmp_left_pos,*tmp_right_pos;
/* Pointers that are used as limits (begin and end of the field buffer) */
char *left_wall,*right_wall;
char tmp_char;
- /*
- To remember if current_thd->cuted_fields has already been incremented,
- to do that only once
- */
+ /*
+ To remember if current_thd->cuted_fields has already been incremented,
+ to do that only once
+ */
bool is_cuted_fields_incr=0;
LINT_INIT(int_digits_tail_from);
@@ -417,16 +463,18 @@ void Field_decimal::store(const char *from,uint len)
/*
There are three steps in this function :
- - parse the input string
- - modify the position of digits around the decimal dot '.'
- according to the exponent value (if specified)
- - write the formatted number
+ - parse the input string
+ - modify the position of digits around the decimal dot '.'
+ according to the exponent value (if specified)
+ - write the formatted number
*/
if ((tmp_dec=dec))
tmp_dec++;
- for (; from !=end && isspace(*from); from++) ; // Read spaces
+ /* skip pre-space */
+ while (from != end && my_isspace(&my_charset_bin,*from))
+ from++;
if (from == end)
{
current_thd->cuted_fields++;
@@ -445,11 +493,11 @@ void Field_decimal::store(const char *from,uint len)
if (sign_char=='-')
{
Field_decimal::overflow(1);
- return;
+ return 1;
}
/*
- Defining this will not store "+" for unsigned decimal type even if
- it is passed in numeric string. This will make some tests to fail
+ Defining this will not store "+" for unsigned decimal type even if
+ it is passed in numeric string. This will make some tests to fail
*/
#ifdef DONT_ALLOW_UNSIGNED_PLUS
else
@@ -462,13 +510,13 @@ void Field_decimal::store(const char *from,uint len)
for (; from!=end && *from == '0'; from++) ; // Read prezeros
pre_zeros_end=int_digits_from=from;
/* Read non zero digits at the left of '.'*/
- for (; from!=end && isdigit(*from);from++) ;
+ for (; from != end && my_isdigit(&my_charset_bin, *from) ; from++) ;
int_digits_end=from;
if (from!=end && *from == '.') // Some '.' ?
from++;
frac_digits_from= from;
/* Read digits at the right of '.' */
- for (;from!=end && isdigit(*from); from++) ;
+ for (;from!=end && my_isdigit(&my_charset_bin, *from); from++) ;
frac_digits_end=from;
// Some exponentiation symbol ?
if (from != end && (*from == 'e' || *from == 'E'))
@@ -484,7 +532,7 @@ void Field_decimal::store(const char *from,uint len)
exponents will become small (e.g. 1e4294967296 will become 1e0, and the
field will finally contain 1 instead of its max possible value).
*/
- for (;from!=end && isdigit(*from); from++)
+ for (;from!=end && my_isdigit(&my_charset_bin, *from); from++)
{
exponent=10*exponent+(*from-'0');
if (exponent>MAX_EXPONENT)
@@ -501,7 +549,8 @@ void Field_decimal::store(const char *from,uint len)
if (current_thd->count_cuted_fields)
{
- for (;from != end && isspace(*from); from++) ; // Read end spaces
+ // Skip end spaces
+ for (;from != end && my_isspace(&my_charset_bin, *from); from++) ;
if (from != end) // If still something left, warn
{
current_thd->cuted_fields++;
@@ -513,21 +562,21 @@ void Field_decimal::store(const char *from,uint len)
Now "move" digits around the decimal dot according to the exponent value,
and add necessary zeros.
Examples :
- - 1E+3 : needs 3 more zeros at the left of '.' (int_digits_added_zeros=3)
- - 1E-3 : '1' moves at the right of '.', and 2 more zeros are needed
- between '.' and '1'
+ - 1E+3 : needs 3 more zeros at the left of '.' (int_digits_added_zeros=3)
+ - 1E-3 : '1' moves at the right of '.', and 2 more zeros are needed
+ between '.' and '1'
- 1234.5E-3 : '234' moves at the right of '.'
- These moves are implemented with pointers which point at the begin
- and end of each moved segment. Examples :
+ These moves are implemented with pointers which point at the begin
+ and end of each moved segment. Examples :
- 1234.5E-3 : before the code below is executed, the int_digits part is
- from '1' to '4' and the frac_digits part from '5' to '5'. After the code
- below, the int_digits part is from '1' to '1', the frac_digits_head
- part is from '2' to '4', and the frac_digits part from '5' to '5'.
+ from '1' to '4' and the frac_digits part from '5' to '5'. After the code
+ below, the int_digits part is from '1' to '1', the frac_digits_head
+ part is from '2' to '4', and the frac_digits part from '5' to '5'.
- 1234.5E3 : before the code below is executed, the int_digits part is
- from '1' to '4' and the frac_digits part from '5' to '5'. After the code
- below, the int_digits part is from '1' to '4', the int_digits_tail
- part is from '5' to '5', the frac_digits part is empty, and
- int_digits_added_zeros=2 (to make 1234500).
+ from '1' to '4' and the frac_digits part from '5' to '5'. After the code
+ below, the int_digits part is from '1' to '4', the int_digits_tail
+ part is from '5' to '5', the frac_digits part is empty, and
+ int_digits_added_zeros=2 (to make 1234500).
*/
/*
@@ -589,7 +638,7 @@ void Field_decimal::store(const char *from,uint len)
{
// too big number, change to max or min number
Field_decimal::overflow(sign_char == '-');
- return;
+ return 1;
}
/*
@@ -670,7 +719,7 @@ void Field_decimal::store(const char *from,uint len)
{
if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
break; // Go on below to see if we lose non zero digits
- return;
+ return 0;
}
*pos++='0';
}
@@ -683,7 +732,7 @@ void Field_decimal::store(const char *from,uint len)
{
if (!is_cuted_fields_incr)
current_thd->cuted_fields++;
- return;
+ return 0;
}
continue;
}
@@ -700,7 +749,7 @@ void Field_decimal::store(const char *from,uint len)
{
if (!is_cuted_fields_incr)
current_thd->cuted_fields++;
- return;
+ return 0;
}
continue;
}
@@ -709,26 +758,26 @@ void Field_decimal::store(const char *from,uint len)
while (pos != right_wall)
*pos++='0'; // Fill with zeros at right of '.'
-
+ return 0;
}
-void Field_decimal::store(double nr)
+int Field_decimal::store(double nr)
{
if (unsigned_flag && nr < 0)
{
overflow(1);
- return;
+ return 1;
}
#ifdef HAVE_FINITE
if (!finite(nr)) // Handle infinity as special case
{
overflow(nr < 0.0);
- return;
+ return 1;
}
#endif
-
+
reg4 uint i,length;
char fyllchar,*to;
char buff[320];
@@ -737,36 +786,43 @@ void Field_decimal::store(double nr)
#ifdef HAVE_SNPRINTF_
buff[sizeof(buff)-1]=0; // Safety
snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr);
+ length=(uint) strlen(buff);
#else
- sprintf(buff,"%.*f",dec,nr);
+ length=(uint) my_sprintf(buff,(buff,"%.*f",dec,nr));
#endif
- length=(uint) strlen(buff);
if (length > field_length)
+ {
overflow(nr < 0.0);
+ return 1;
+ }
else
{
to=ptr;
for (i=field_length-length ; i-- > 0 ;)
*to++ = fyllchar;
memcpy(to,buff,length);
+ return 0;
}
}
-void Field_decimal::store(longlong nr)
+int Field_decimal::store(longlong nr)
{
if (unsigned_flag && nr < 0)
{
overflow(1);
- return;
+ return 1;
}
char buff[22];
uint length=(uint) (longlong10_to_str(nr,buff,-10)-buff);
uint int_part=field_length- (dec ? dec+1 : 0);
if (length > int_part)
+ {
overflow(test(nr < 0L)); /* purecov: inspected */
+ return 1;
+ }
else
{
char fyllchar = zerofill ? (char) '0' : (char) ' ';
@@ -779,40 +835,40 @@ void Field_decimal::store(longlong nr)
to[length]='.';
bfill(to+length+1,dec,'0');
}
+ return 0;
}
}
double Field_decimal::val_real(void)
{
- char temp= *(ptr+field_length); *(ptr+field_length) = '\0';
- double nr=atod(ptr);
- *(ptr+field_length)=temp;
- return(nr);
+ int not_used;
+ return my_strntod(&my_charset_bin, ptr, field_length, NULL, &not_used);
}
longlong Field_decimal::val_int(void)
{
- char temp= *(ptr+field_length); *(ptr+field_length) = '\0';
- longlong nr;
+ int not_used;
if (unsigned_flag)
- nr=(longlong) strtoull(ptr,NULL,10);
+ return my_strntoull(&my_charset_bin, ptr, field_length, 10, NULL,
+ &not_used);
else
- nr=strtoll(ptr,NULL,10);
- *(ptr+field_length)=temp;
- return(nr);
+ return my_strntoll(&my_charset_bin, ptr, field_length, 10, NULL,
+ &not_used);
}
+
String *Field_decimal::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
char *str;
for (str=ptr ; *str == ' ' ; str++) ;
uint tmp_length=(uint) (str-ptr);
+ val_ptr->set_charset(&my_charset_bin);
if (field_length < tmp_length) // Error in data
val_ptr->length(0);
else
- val_ptr->set((const char*) str,field_length-tmp_length);
+ val_ptr->set_latin1((const char*) str, field_length-tmp_length);
return val_ptr;
}
@@ -829,8 +885,10 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr)
for (end=a_ptr+field_length;
a_ptr != end &&
(*a_ptr == *b_ptr ||
- ((isspace(*a_ptr) || *a_ptr == '+' || *a_ptr == '0') &&
- (isspace(*b_ptr) || *b_ptr == '+' || *b_ptr == '0')));
+ ((my_isspace(&my_charset_bin,*a_ptr) || *a_ptr == '+' ||
+ *a_ptr == '0') &&
+ (my_isspace(&my_charset_bin,*b_ptr) || *b_ptr == '+' ||
+ *b_ptr == '0')));
a_ptr++,b_ptr++)
{
if (*a_ptr == '-') // If both numbers are negative
@@ -857,8 +915,8 @@ void Field_decimal::sort_string(char *to,uint length)
char *str,*end;
for (str=ptr,end=ptr+length;
str != end &&
- ((isspace(*str) || *str == '+' || *str == '0')) ;
-
+ ((my_isspace(&my_charset_bin,*str) || *str == '+' ||
+ *str == '0')) ;
str++)
*to++=' ';
if (str == end)
@@ -869,7 +927,7 @@ void Field_decimal::sort_string(char *to,uint length)
*to++=1; // Smaller than any number
str++;
while (str != end)
- if (isdigit(*str))
+ if (my_isdigit(&my_charset_bin,*str))
*to++= (char) ('9' - *str++);
else
*to++= *str++;
@@ -877,14 +935,17 @@ void Field_decimal::sort_string(char *to,uint length)
else memcpy(to,str,(uint) (end-str));
}
+
void Field_decimal::sql_type(String &res) const
{
+ CHARSET_INFO *cs=res.charset();
uint tmp=field_length;
if (!unsigned_flag)
tmp--;
if (dec)
tmp--;
- sprintf((char*) res.ptr(),"decimal(%d,%d)",tmp,dec);
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "decimal(%d,%d)",tmp,dec));
add_zerofill_and_unsigned(res);
}
@@ -893,10 +954,12 @@ void Field_decimal::sql_type(String &res) const
** tiny int
****************************************************************************/
-void Field_tiny::store(const char *from,uint len)
+int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
{
- String tmp_str(from,len);
- long tmp= strtol(tmp_str.c_ptr(),NULL,10);
+ int not_used; // We can ignore result from str2int
+ char *end;
+ long tmp= my_strntol(cs, from, len, 10, &end, &not_used);
+ int error= 0;
if (unsigned_flag)
{
@@ -904,14 +967,19 @@ void Field_tiny::store(const char *from,uint len)
{
tmp=0; /* purecov: inspected */
current_thd->cuted_fields++; /* purecov: inspected */
+ error= 1;
}
else if (tmp > 255)
{
tmp= 255;
current_thd->cuted_fields++;
+ error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ {
current_thd->cuted_fields++;
+ error= 1;
+ }
}
else
{
@@ -919,21 +987,28 @@ void Field_tiny::store(const char *from,uint len)
{
tmp= -128;
current_thd->cuted_fields++;
+ error= 1;
}
else if (tmp >= 128)
{
tmp= 127;
current_thd->cuted_fields++;
+ error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ {
current_thd->cuted_fields++;
+ error= 1;
+ }
}
ptr[0]= (char) tmp;
+ return error;
}
-void Field_tiny::store(double nr)
+int Field_tiny::store(double nr)
{
+ int error= 0;
nr=rint(nr);
if (unsigned_flag)
{
@@ -941,11 +1016,13 @@ void Field_tiny::store(double nr)
{
*ptr=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > 255.0)
{
*ptr=(char) 255;
current_thd->cuted_fields++;
+ error= 1;
}
else
*ptr=(char) nr;
@@ -956,30 +1033,36 @@ void Field_tiny::store(double nr)
{
*ptr= (char) -128;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > 127.0)
{
*ptr=127;
current_thd->cuted_fields++;
+ error= 1;
}
else
*ptr=(char) nr;
}
+ return error;
}
-void Field_tiny::store(longlong nr)
+int Field_tiny::store(longlong nr)
{
+ int error= 0;
if (unsigned_flag)
{
if (nr < 0L)
{
*ptr=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > 255L)
{
*ptr= (char) 255;
current_thd->cuted_fields++;
+ error= 1;
}
else
*ptr=(char) nr;
@@ -990,15 +1073,18 @@ void Field_tiny::store(longlong nr)
{
*ptr= (char) -128;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > 127L)
{
*ptr=127;
current_thd->cuted_fields++;
+ error= 1;
}
else
*ptr=(char) nr;
}
+ return error;
}
@@ -1019,19 +1105,27 @@ longlong Field_tiny::val_int(void)
String *Field_tiny::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ CHARSET_INFO *cs= &my_charset_bin;
uint length;
- val_buffer->alloc(max(field_length+1,5));
+ uint mlength=max(field_length+1,5*cs->mbmaxlen);
+ val_buffer->alloc(mlength);
char *to=(char*) val_buffer->ptr();
+
if (unsigned_flag)
- length= (uint) (int10_to_str((long) *((uchar*) ptr),to,10)-to);
+ length= (uint) cs->long10_to_str(cs,to,mlength, 10,(long) *((uchar*) ptr));
else
- length= (uint) (int10_to_str((long) *((signed char*) ptr),to,-10)-to);
+ length= (uint) cs->long10_to_str(cs,to,mlength,-10,(long) *((signed char*) ptr));
+
val_buffer->length(length);
if (zerofill)
prepend_zeros(val_buffer);
return val_buffer;
}
+bool Field_tiny::send_binary(Protocol *protocol)
+{
+ return protocol->store_tiny((longlong) (int8) ptr[0]);
+}
int Field_tiny::cmp(const char *a_ptr, const char *b_ptr)
{
@@ -1052,36 +1146,42 @@ void Field_tiny::sort_string(char *to,uint length __attribute__((unused)))
void Field_tiny::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"tinyint(%d)",(int) field_length);
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "tinyint(%d)",(int) field_length));
add_zerofill_and_unsigned(res);
}
/****************************************************************************
-** short int
+ Field type short int (2 byte)
****************************************************************************/
-
-// Note: Sometimes this should be fixed to use one strtol() to use
-// len and check for garbage after number.
-
-void Field_short::store(const char *from,uint len)
+int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
{
- String tmp_str(from,len);
- long tmp= strtol(tmp_str.c_ptr(),NULL,10);
+ int not_used; // We can ignore result from str2int
+ char *end;
+ long tmp= my_strntol(cs, from, len, 10, &end, &not_used);
+ int error= 0;
+
if (unsigned_flag)
{
if (tmp < 0)
{
tmp=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (tmp > (uint16) ~0)
{
tmp=(uint16) ~0;
current_thd->cuted_fields++;
+ error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ {
current_thd->cuted_fields++;
+ error= 1;
+ }
}
else
{
@@ -1089,14 +1189,19 @@ void Field_short::store(const char *from,uint len)
{
tmp= INT_MIN16;
current_thd->cuted_fields++;
+ error= 1;
}
else if (tmp > INT_MAX16)
{
tmp=INT_MAX16;
current_thd->cuted_fields++;
+ error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ {
current_thd->cuted_fields++;
+ error= 1;
+ }
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1106,11 +1211,13 @@ void Field_short::store(const char *from,uint len)
else
#endif
shortstore(ptr,(short) tmp);
+ return error;
}
-void Field_short::store(double nr)
+int Field_short::store(double nr)
{
+ int error= 0;
int16 res;
nr=rint(nr);
if (unsigned_flag)
@@ -1119,11 +1226,13 @@ void Field_short::store(double nr)
{
res=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (double) (uint16) ~0)
{
res=(int16) (uint16) ~0;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int16) (uint16) nr;
@@ -1134,11 +1243,13 @@ void Field_short::store(double nr)
{
res=INT_MIN16;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (double) INT_MAX16)
{
res=INT_MAX16;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int16) nr;
@@ -1151,10 +1262,12 @@ void Field_short::store(double nr)
else
#endif
shortstore(ptr,res);
+ return error;
}
-void Field_short::store(longlong nr)
+int Field_short::store(longlong nr)
{
+ int error= 0;
int16 res;
if (unsigned_flag)
{
@@ -1162,11 +1275,13 @@ void Field_short::store(longlong nr)
{
res=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (longlong) (uint16) ~0)
{
res=(int16) (uint16) ~0;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int16) (uint16) nr;
@@ -1177,11 +1292,13 @@ void Field_short::store(longlong nr)
{
res=INT_MIN16;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > INT_MAX16)
{
res=INT_MAX16;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int16) nr;
@@ -1194,6 +1311,7 @@ void Field_short::store(longlong nr)
else
#endif
shortstore(ptr,res);
+ return error;
}
@@ -1221,11 +1339,14 @@ longlong Field_short::val_int(void)
return unsigned_flag ? (longlong) (unsigned short) j : (longlong) j;
}
+
String *Field_short::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ CHARSET_INFO *cs= &my_charset_bin;
uint length;
- val_buffer->alloc(max(field_length+1,7));
+ uint mlength=max(field_length+1,7*cs->mbmaxlen);
+ val_buffer->alloc(mlength);
char *to=(char*) val_buffer->ptr();
short j;
#ifdef WORDS_BIGENDIAN
@@ -1236,9 +1357,9 @@ String *Field_short::val_str(String *val_buffer,
shortget(j,ptr);
if (unsigned_flag)
- length=(uint) (int10_to_str((long) (uint16) j,to,10)-to);
+ length=(uint) cs->long10_to_str(cs, to, mlength, 10, (long) (uint16) j);
else
- length=(uint) (int10_to_str((long) j,to,-10)-to);
+ length=(uint) cs->long10_to_str(cs, to, mlength,-10, (long) j);
val_buffer->length(length);
if (zerofill)
prepend_zeros(val_buffer);
@@ -1246,6 +1367,12 @@ String *Field_short::val_str(String *val_buffer,
}
+bool Field_short::send_binary(Protocol *protocol)
+{
+ return protocol->store_short(Field_short::val_int());
+}
+
+
int Field_short::cmp(const char *a_ptr, const char *b_ptr)
{
short a,b;
@@ -1292,22 +1419,23 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
void Field_short::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"smallint(%d)",(int) field_length);
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "smallint(%d)",(int) field_length));
add_zerofill_and_unsigned(res);
}
/****************************************************************************
-** medium int
+ Field type medium int (3 byte)
****************************************************************************/
-// Note: Sometimes this should be fixed to use one strtol() to use
-// len and check for garbage after number.
-
-void Field_medium::store(const char *from,uint len)
+int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
{
- String tmp_str(from,len);
- long tmp= strtol(tmp_str.c_ptr(),NULL,10);
+ int not_used; // We can ignore result from str2int
+ char *end;
+ long tmp= my_strntol(cs, from, len, 10, &end, &not_used);
+ int error= 0;
if (unsigned_flag)
{
@@ -1315,14 +1443,19 @@ void Field_medium::store(const char *from,uint len)
{
tmp=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (tmp >= (long) (1L << 24))
{
tmp=(long) (1L << 24)-1L;
current_thd->cuted_fields++;
+ error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ {
current_thd->cuted_fields++;
+ error= 1;
+ }
}
else
{
@@ -1330,22 +1463,29 @@ void Field_medium::store(const char *from,uint len)
{
tmp= INT_MIN24;
current_thd->cuted_fields++;
+ error= 1;
}
else if (tmp > INT_MAX24)
{
tmp=INT_MAX24;
current_thd->cuted_fields++;
+ error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ {
current_thd->cuted_fields++;
+ error= 1;
+ }
}
int3store(ptr,tmp);
+ return error;
}
-void Field_medium::store(double nr)
+int Field_medium::store(double nr)
{
+ int error= 0;
nr=rint(nr);
if (unsigned_flag)
{
@@ -1353,12 +1493,14 @@ void Field_medium::store(double nr)
{
int3store(ptr,0);
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr >= (double) (long) (1L << 24))
{
uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
current_thd->cuted_fields++;
+ error= 1;
}
else
int3store(ptr,(uint32) nr);
@@ -1370,32 +1512,38 @@ void Field_medium::store(double nr)
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (double) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
+ error= 1;
}
else
int3store(ptr,(long) nr);
}
+ return error;
}
-void Field_medium::store(longlong nr)
+int Field_medium::store(longlong nr)
{
+ int error= 0;
if (unsigned_flag)
{
if (nr < 0L)
{
int3store(ptr,0);
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr >= (longlong) (long) (1L << 24))
{
long tmp=(long) (1L << 24)-1L;;
int3store(ptr,tmp);
current_thd->cuted_fields++;
+ error= 1;
}
else
int3store(ptr,(uint32) nr);
@@ -1407,16 +1555,19 @@ void Field_medium::store(longlong nr)
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (longlong) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
+ error= 1;
}
else
int3store(ptr,(long) nr);
}
+ return error;
}
@@ -1426,21 +1577,25 @@ double Field_medium::val_real(void)
return (double) j;
}
+
longlong Field_medium::val_int(void)
{
long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
return (longlong) j;
}
+
String *Field_medium::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ CHARSET_INFO *cs= &my_charset_bin;
uint length;
- val_buffer->alloc(max(field_length+1,10));
+ uint mlength=max(field_length+1,10*cs->mbmaxlen);
+ val_buffer->alloc(mlength);
char *to=(char*) val_buffer->ptr();
long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
- length=(uint) (int10_to_str(j,to,-10)-to);
+ length=(uint) cs->long10_to_str(cs,to,mlength,-10,j);
val_buffer->length(length);
if (zerofill)
prepend_zeros(val_buffer); /* purecov: inspected */
@@ -1448,6 +1603,12 @@ String *Field_medium::val_str(String *val_buffer,
}
+bool Field_medium::send_binary(Protocol *protocol)
+{
+ return protocol->store_long(Field_medium::val_int());
+}
+
+
int Field_medium::cmp(const char *a_ptr, const char *b_ptr)
{
long a,b;
@@ -1477,7 +1638,9 @@ void Field_medium::sort_string(char *to,uint length __attribute__((unused)))
void Field_medium::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"mediumint(%d)",(int) field_length);
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "mediumint(%d)",(int) field_length));
add_zerofill_and_unsigned(res);
}
@@ -1486,36 +1649,35 @@ void Field_medium::sql_type(String &res) const
****************************************************************************/
-// Note: Sometimes this should be fixed to use one strtol() to use
-// len and check for garbage after number.
-
-void Field_long::store(const char *from,uint len)
+int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
- char *end;
- while (len && isspace(*from))
- {
- len--; from++;
- }
long tmp;
- String tmp_str(from,len);
- from= tmp_str.c_ptr(); // Add end null if needed
- errno=0;
+ int error= 0;
+ char *end;
+
+ tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES);
+ len-= tmp;
+ from+= tmp;
+ my_errno=0;
if (unsigned_flag)
{
if (!len || *from == '-')
{
tmp=0; // Set negative to 0
- errno=ERANGE;
+ my_errno=ERANGE;
+ error= 1;
}
else
- tmp=(long) strtoul(from, &end, 10);
+ tmp=(long) my_strntoul(cs,from,len,10,&end,&error);
}
else
- tmp=strtol(from, &end, 10);
- if (errno ||
+ tmp=my_strntol(cs,from,len,10,&end,&error);
+ if (error ||
(from+len != end && current_thd->count_cuted_fields &&
- !test_if_int(from,len)))
+ !test_if_int(from,len,end,cs)))
+ {
current_thd->cuted_fields++;
+ }
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -1524,11 +1686,13 @@ void Field_long::store(const char *from,uint len)
else
#endif
longstore(ptr,tmp);
+ return error;
}
-void Field_long::store(double nr)
+int Field_long::store(double nr)
{
+ int error= 0;
int32 res;
nr=rint(nr);
if (unsigned_flag)
@@ -1537,11 +1701,13 @@ void Field_long::store(double nr)
{
res=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (double) (ulong) ~0L)
{
res=(int32) (uint32) ~0L;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int32) (ulong) nr;
@@ -1552,11 +1718,13 @@ void Field_long::store(double nr)
{
res=(int32) INT_MIN32;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (double) INT_MAX32)
{
res=(int32) INT_MAX32;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int32) nr;
@@ -1569,11 +1737,13 @@ void Field_long::store(double nr)
else
#endif
longstore(ptr,res);
+ return error;
}
-void Field_long::store(longlong nr)
+int Field_long::store(longlong nr)
{
+ int error= 0;
int32 res;
if (unsigned_flag)
{
@@ -1581,11 +1751,13 @@ void Field_long::store(longlong nr)
{
res=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr >= (LL(1) << 32))
{
res=(int32) (uint32) ~0L;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int32) (uint32) nr;
@@ -1596,11 +1768,13 @@ void Field_long::store(longlong nr)
{
res=(int32) INT_MIN32;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > (longlong) INT_MAX32)
{
res=(int32) INT_MAX32;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(int32) nr;
@@ -1613,6 +1787,7 @@ void Field_long::store(longlong nr)
else
#endif
longstore(ptr,res);
+ return error;
}
@@ -1643,8 +1818,10 @@ longlong Field_long::val_int(void)
String *Field_long::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ CHARSET_INFO *cs= &my_charset_bin;
uint length;
- val_buffer->alloc(max(field_length+1,12));
+ uint mlength=max(field_length+1,12*cs->mbmaxlen);
+ val_buffer->alloc(mlength);
char *to=(char*) val_buffer->ptr();
int32 j;
#ifdef WORDS_BIGENDIAN
@@ -1654,9 +1831,10 @@ String *Field_long::val_str(String *val_buffer,
#endif
longget(j,ptr);
- length=(uint) (int10_to_str((unsigned_flag ? (long) (uint32) j : (long) j),
- to,
- unsigned_flag ? 10 : -10)-to);
+ if (unsigned_flag)
+ length=cs->long10_to_str(cs,to,mlength, 10,(long) (uint32)j);
+ else
+ length=cs->long10_to_str(cs,to,mlength,-10,(long) j);
val_buffer->length(length);
if (zerofill)
prepend_zeros(val_buffer);
@@ -1664,6 +1842,11 @@ String *Field_long::val_str(String *val_buffer,
}
+bool Field_long::send_binary(Protocol *protocol)
+{
+ return protocol->store_long(Field_long::val_int());
+}
+
int Field_long::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -1713,40 +1896,42 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
void Field_long::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"int(%d)",(int) field_length);
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "int(%d)",(int) field_length));
add_zerofill_and_unsigned(res);
}
/****************************************************************************
-** longlong int
+ Field type longlong int (8 bytes)
****************************************************************************/
-void Field_longlong::store(const char *from,uint len)
+int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
{
- char *end;
- while (len && isspace(*from))
- { // For easy error check
- len--; from++;
- }
longlong tmp;
- String tmp_str(from,len);
- from= tmp_str.c_ptr(); // Add end null if needed
- errno=0;
+ int error= 0;
+ char *end;
+
+ tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES);
+ len-= (uint)tmp;
+ from+= tmp;
+ my_errno=0;
if (unsigned_flag)
{
if (!len || *from == '-')
{
tmp=0; // Set negative to 0
- errno=ERANGE;
+ my_errno= ERANGE;
+ error= 1;
}
else
- tmp=(longlong) strtoull(from, &end, 10);
+ tmp=(longlong) my_strntoull(cs,from,len,10,&end,&error);
}
else
- tmp=strtoll(from, &end, 10);
- if (errno ||
+ tmp=my_strntoll(cs,from,len,10,&end,&error);
+ if (error ||
(from+len != end && current_thd->count_cuted_fields &&
- !test_if_int(from,len)))
+ !test_if_int(from,len,end,cs)))
current_thd->cuted_fields++;
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1756,11 +1941,13 @@ void Field_longlong::store(const char *from,uint len)
else
#endif
longlongstore(ptr,tmp);
+ return error;
}
-void Field_longlong::store(double nr)
+int Field_longlong::store(double nr)
{
+ int error= 0;
longlong res;
nr=rint(nr);
if (unsigned_flag)
@@ -1769,11 +1956,13 @@ void Field_longlong::store(double nr)
{
res=0;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr >= (double) ~ (ulonglong) 0)
{
res= ~(longlong) 0;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(longlong) (ulonglong) nr;
@@ -1784,11 +1973,13 @@ void Field_longlong::store(double nr)
{
res=(longlong) LONGLONG_MIN;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr >= (double) LONGLONG_MAX)
{
res=(longlong) LONGLONG_MAX;
current_thd->cuted_fields++;
+ error= 1;
}
else
res=(longlong) nr;
@@ -1801,10 +1992,11 @@ void Field_longlong::store(double nr)
else
#endif
longlongstore(ptr,res);
+ return error;
}
-void Field_longlong::store(longlong nr)
+int Field_longlong::store(longlong nr)
{
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1814,6 +2006,7 @@ void Field_longlong::store(longlong nr)
else
#endif
longlongstore(ptr,nr);
+ return 0;
}
@@ -1847,8 +2040,10 @@ longlong Field_longlong::val_int(void)
String *Field_longlong::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ CHARSET_INFO *cs= &my_charset_bin;
uint length;
- val_buffer->alloc(max(field_length+1,22));
+ uint mlength=max(field_length+1,22*cs->mbmaxlen);
+ val_buffer->alloc(mlength);
char *to=(char*) val_buffer->ptr();
longlong j;
#ifdef WORDS_BIGENDIAN
@@ -1858,7 +2053,8 @@ String *Field_longlong::val_str(String *val_buffer,
#endif
longlongget(j,ptr);
- length=(uint) (longlong10_to_str(j,to,unsigned_flag ? 10 : -10)-to);
+ length=(uint) (cs->longlong10_to_str)(cs,to,mlength,
+ unsigned_flag ? 10 : -10, j);
val_buffer->length(length);
if (zerofill)
prepend_zeros(val_buffer);
@@ -1866,6 +2062,12 @@ String *Field_longlong::val_str(String *val_buffer,
}
+bool Field_longlong::send_binary(Protocol *protocol)
+{
+ return protocol->store_longlong(Field_longlong::val_int(), unsigned_flag);
+}
+
+
int Field_longlong::cmp(const char *a_ptr, const char *b_ptr)
{
longlong a,b;
@@ -1924,7 +2126,9 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
void Field_longlong::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"bigint(%d)",(int) field_length);
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "bigint(%d)",(int) field_length));
add_zerofill_and_unsigned(res);
}
@@ -1932,35 +2136,42 @@ void Field_longlong::sql_type(String &res) const
** single precision float
****************************************************************************/
-void Field_float::store(const char *from,uint len)
+int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
{
- String tmp_str(from,len);
- errno=0;
- Field_float::store(atof(tmp_str.c_ptr()));
- if (errno || current_thd->count_cuted_fields && !test_if_real(from,len))
+ int err;
+ Field_float::store(my_strntod(cs,(char*) from,len,(char**)NULL,&err));
+ if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs))
+ {
current_thd->cuted_fields++;
+ return 1;
+ }
+ return (err) ? 1 : 0;
}
-void Field_float::store(double nr)
+int Field_float::store(double nr)
{
float j;
+ int error= 0;
if (dec < NOT_FIXED_DEC)
nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point
if (unsigned_flag && nr < 0)
{
current_thd->cuted_fields++;
nr=0;
+ error= 1;
}
if (nr < -FLT_MAX)
{
j= -FLT_MAX;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr > FLT_MAX)
{
j=FLT_MAX;
current_thd->cuted_fields++;
+ error= 1;
}
else
j= (float) nr;
@@ -1972,16 +2183,19 @@ void Field_float::store(double nr)
else
#endif
memcpy_fixed(ptr,(byte*) &j,sizeof(j));
+ return error;
}
-void Field_float::store(longlong nr)
+int Field_float::store(longlong nr)
{
+ int error= 0;
float j= (float) nr;
if (unsigned_flag && j < 0)
{
current_thd->cuted_fields++;
j=0;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1991,6 +2205,7 @@ void Field_float::store(longlong nr)
else
#endif
memcpy_fixed(ptr,(byte*) &j,sizeof(j));
+ return error;
}
@@ -2090,10 +2305,10 @@ String *Field_float::val_str(String *val_buffer,
#ifdef HAVE_SNPRINTF
to[to_length-1]=0; // Safety
snprintf(to,to_length-1,"%.*f",dec,nr);
+ to=strend(to);
#else
- sprintf(to,"%.*f",dec,nr);
+ to+= my_sprintf(to,(to,"%.*f",dec,nr));
#endif
- to=strend(to);
#endif
}
#ifdef HAVE_FCONVERT
@@ -2169,12 +2384,24 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
}
+bool Field_float::send_binary(Protocol *protocol)
+{
+ return protocol->store((float) Field_float::val_real(), dec, (String*) 0);
+}
+
+
void Field_float::sql_type(String &res) const
{
if (dec == NOT_FIXED_DEC)
- strmov((char*) res.ptr(),"float");
+ {
+ res.set_latin1("float", 5);
+ }
else
- sprintf((char*) res.ptr(),"float(%d,%d)",(int) field_length,dec);
+ {
+ CHARSET_INFO *cs= res.charset();
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "float(%d,%d)",(int) field_length,dec));
+ }
add_zerofill_and_unsigned(res);
}
@@ -2182,17 +2409,19 @@ void Field_float::sql_type(String &res) const
** double precision floating point numbers
****************************************************************************/
-void Field_double::store(const char *from,uint len)
+int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
{
- String tmp_str(from,len);
- errno=0;
- double j= atof(tmp_str.c_ptr());
- if (errno || current_thd->count_cuted_fields && !test_if_real(from,len))
+ int err;
+ double j= my_strntod(cs,(char*) from,len,(char**)0,&err);
+ if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs))
+ {
current_thd->cuted_fields++;
+ }
if (unsigned_flag && j < 0)
{
current_thd->cuted_fields++;
j=0;
+ err= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2202,17 +2431,20 @@ void Field_double::store(const char *from,uint len)
else
#endif
doublestore(ptr,j);
+ return err;
}
-void Field_double::store(double nr)
+int Field_double::store(double nr)
{
+ int error= 0;
if (dec < NOT_FIXED_DEC)
nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point
if (unsigned_flag && nr < 0)
{
current_thd->cuted_fields++;
nr=0;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2222,15 +2454,18 @@ void Field_double::store(double nr)
else
#endif
doublestore(ptr,nr);
+ return error;
}
-void Field_double::store(longlong nr)
+int Field_double::store(longlong nr)
{
double j= (double) nr;
+ int error= 0;
if (unsigned_flag && j < 0)
{
current_thd->cuted_fields++;
+ error= 1;
j=0;
}
#ifdef WORDS_BIGENDIAN
@@ -2241,6 +2476,7 @@ void Field_double::store(longlong nr)
else
#endif
doublestore(ptr,j);
+ return error;
}
@@ -2339,10 +2575,10 @@ String *Field_double::val_str(String *val_buffer,
#ifdef HAVE_SNPRINTF
to[to_length-1]=0; // Safety
snprintf(to,to_length-1,"%.*f",dec,nr);
+ to=strend(to);
#else
- sprintf(to,"%.*f",dec,nr);
+ to+= my_sprintf(to,(to,"%.*f",dec,nr));
#endif
- to=strend(to);
#endif
}
#ifdef HAVE_FCONVERT
@@ -2355,6 +2591,11 @@ String *Field_double::val_str(String *val_buffer,
return val_buffer;
}
+bool Field_double::send_binary(Protocol *protocol)
+{
+ return protocol->store((double) Field_double::val_real(), dec, (String*) 0);
+}
+
int Field_double::cmp(const char *a_ptr, const char *b_ptr)
{
@@ -2407,10 +2648,16 @@ void Field_double::sort_string(char *to,uint length __attribute__((unused)))
void Field_double::sql_type(String &res) const
{
+ CHARSET_INFO *cs=res.charset();
if (dec == NOT_FIXED_DEC)
- strmov((char*) res.ptr(),"double");
+ {
+ res.set_latin1("double",6);
+ }
else
- sprintf((char*) res.ptr(),"double(%d,%d)",(int) field_length,dec);
+ {
+ res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
+ "double(%d,%d)",(int) field_length,dec));
+ }
add_zerofill_and_unsigned(res);
}
@@ -2424,10 +2671,10 @@ void Field_double::sql_type(String &res) const
Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg,
const char *field_name_arg,
- struct st_table *table_arg)
- :Field_num(ptr_arg, len_arg, (uchar*) 0,0,
- unireg_check_arg, field_name_arg, table_arg,
- 0, 1, 1)
+ struct st_table *table_arg,
+ CHARSET_INFO *cs)
+ :Field_str(ptr_arg, 19, (uchar*) 0,0,
+ unireg_check_arg, field_name_arg, table_arg, cs)
{
if (table && !table->timestamp_field)
{
@@ -2438,7 +2685,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
}
-void Field_timestamp::store(const char *from,uint len)
+int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
{
long tmp=(long) str_to_timestamp(from,len);
#ifdef WORDS_BIGENDIAN
@@ -2449,52 +2696,27 @@ void Field_timestamp::store(const char *from,uint len)
else
#endif
longstore(ptr,tmp);
+ return 0;
}
-void Field_timestamp::fill_and_store(char *from,uint len)
-{
- uint res_length;
- if (len <= field_length)
- res_length=field_length;
- else if (len <= 12)
- res_length=12; /* purecov: inspected */
- else if (len <= 14)
- res_length=14; /* purecov: inspected */
- else
- res_length=(len+1)/2*2; // must be even
- if (res_length != len)
- {
- bmove_upp(from+res_length,from+len,len);
- bfill(from,res_length-len,'0');
- len=res_length;
- }
- long tmp=(long) str_to_timestamp(from,len);
-#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int4store(ptr,tmp);
- }
- else
-#endif
- longstore(ptr,tmp);
-}
-
-
-void Field_timestamp::store(double nr)
+int Field_timestamp::store(double nr)
{
+ int error= 0;
if (nr < 0 || nr > 99991231235959.0)
{
- nr=0; // Avoid overflow on buff
+ nr= 0; // Avoid overflow on buff
current_thd->cuted_fields++;
+ error= 1;
}
- Field_timestamp::store((longlong) rint(nr));
+ error|= Field_timestamp::store((longlong) rint(nr));
+ return error;
}
/*
-** Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to
-** YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this
-** function.
+ Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to
+ YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this
+ function.
*/
static longlong fix_datetime(longlong nr)
@@ -2528,7 +2750,7 @@ static longlong fix_datetime(longlong nr)
}
-void Field_timestamp::store(longlong nr)
+int Field_timestamp::store(longlong nr)
{
TIME l_time;
time_t timestamp;
@@ -2556,6 +2778,7 @@ void Field_timestamp::store(longlong nr)
else
#endif
longstore(ptr,(uint32) timestamp);
+ return 0;
}
@@ -2566,7 +2789,6 @@ double Field_timestamp::val_real(void)
longlong Field_timestamp::val_int(void)
{
- uint len,pos;
int part_time;
uint32 temp;
time_t time_arg;
@@ -2586,44 +2808,34 @@ longlong Field_timestamp::val_int(void)
time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp;
- res=(longlong) 0;
- for (pos=len=0; len+1 < (uint) field_length ; len+=2,pos++)
- {
- bool year_flag=0;
- switch (dayord.pos[pos]) {
- case 0: part_time=l_time->tm_year % 100; year_flag=1 ; break;
- case 1: part_time=l_time->tm_mon+1; break;
- case 2: part_time=l_time->tm_mday; break;
- case 3: part_time=l_time->tm_hour; break;
- case 4: part_time=l_time->tm_min; break;
- case 5: part_time=l_time->tm_sec; break;
- default: part_time=0; break; /* purecov: deadcode */
- }
- if (year_flag && (field_length == 8 || field_length == 14))
- {
- res=res*(longlong) 10000+(part_time+
- ((part_time < YY_PART_YEAR) ? 2000 : 1900));
- len+=2;
- }
- else
- res=res*(longlong) 100+part_time;
- }
- return (longlong) res;
+
+ part_time= l_time->tm_year % 100;
+ res= ((longlong) (part_time+ ((part_time < YY_PART_YEAR) ? 2000 : 1900))*
+ LL(10000000000));
+ part_time= l_time->tm_mon+1;
+ res+= (longlong) part_time * LL(100000000);
+ part_time=l_time->tm_mday;
+ res+= (longlong) ((long) part_time * 1000000L);
+ part_time=l_time->tm_hour;
+ res+= (longlong) (part_time * 10000L);
+ part_time=l_time->tm_min;
+ res+= (longlong) (part_time * 100);
+ part_time=l_time->tm_sec;
+ return res+part_time;
}
String *Field_timestamp::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
- uint pos;
- int part_time;
- uint32 temp;
+ uint32 temp, temp2;
time_t time_arg;
struct tm *l_time;
struct tm tm_tmp;
val_buffer->alloc(field_length+1);
char *to=(char*) val_buffer->ptr(),*end=to+field_length;
+ val_buffer->length(field_length);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2634,44 +2846,58 @@ String *Field_timestamp::val_str(String *val_buffer,
if (temp == 0L)
{ /* Zero time is "000000" */
- VOID(strfill(to,field_length,'0'));
- val_buffer->length(field_length);
- return val_buffer;
+ val_ptr->set("0000-00-00 00:00:00", 19, &my_charset_bin);
+ return val_ptr;
}
+ val_buffer->set_charset(&my_charset_bin); // Safety
time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp;
- for (pos=0; to < end ; pos++)
- {
- bool year_flag=0;
- switch (dayord.pos[pos]) {
- case 0: part_time=l_time->tm_year % 100; year_flag=1; break;
- case 1: part_time=l_time->tm_mon+1; break;
- case 2: part_time=l_time->tm_mday; break;
- case 3: part_time=l_time->tm_hour; break;
- case 4: part_time=l_time->tm_min; break;
- case 5: part_time=l_time->tm_sec; break;
- default: part_time=0; break; /* purecov: deadcode */
- }
- if (year_flag && (field_length == 8 || field_length == 14))
- {
- if (part_time < YY_PART_YEAR)
- {
- *to++='2'; *to++='0'; /* purecov: inspected */
- }
- else
- {
- *to++='1'; *to++='9';
- }
- }
- *to++=(char) ('0'+((uint) part_time/10));
- *to++=(char) ('0'+((uint) part_time % 10));
- }
- *to=0; // Safeguard
- val_buffer->length((uint) (to-val_buffer->ptr()));
+
+ temp= l_time->tm_year % 100;
+ if (temp < YY_PART_YEAR)
+ {
+ *to++= '2';
+ *to++= '0';
+ }
+ else
+ {
+ *to++= '1';
+ *to++= '9';
+ }
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= '-';
+ temp=l_time->tm_mon+1;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= '-';
+ temp=l_time->tm_mday;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= ' ';
+ temp=l_time->tm_hour;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= ':';
+ temp=l_time->tm_min;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to++= ':';
+ temp=l_time->tm_sec;
+ temp2=temp/10; temp=temp-temp2*10;
+ *to++= (char) ('0'+(char) (temp2));
+ *to++= (char) ('0'+(char) (temp));
+ *to= 0;
return val_buffer;
}
+
bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
{
long temp;
@@ -2711,6 +2937,15 @@ bool Field_timestamp::get_time(TIME *ltime)
return Field_timestamp::get_date(ltime,0);
}
+
+bool Field_timestamp::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_timestamp::get_date(&tm, 1);
+ return protocol->store(&tm);
+}
+
+
int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -2729,6 +2964,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
}
+
void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
@@ -2752,8 +2988,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
void Field_timestamp::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"timestamp(%d)",(int) field_length);
- res.length((uint) strlen(res.ptr()));
+ res.set_latin1("timestamp", 9);
}
@@ -2777,12 +3012,16 @@ void Field_timestamp::set_time()
** Stored as a 3 byte unsigned int
****************************************************************************/
-void Field_time::store(const char *from,uint len)
+int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME ltime;
long tmp;
+ int error= 0;
if (str_to_time(from,len,&ltime))
+ {
tmp=0L;
+ error= 1;
+ }
else
{
if (ltime.month)
@@ -2792,26 +3031,31 @@ void Field_time::store(const char *from,uint len)
{
tmp=8385959;
current_thd->cuted_fields++;
+ error= 1;
}
}
if (ltime.neg)
tmp= -tmp;
- Field_time::store((longlong) tmp);
+ error |= Field_time::store((longlong) tmp);
+ return error;
}
-void Field_time::store(double nr)
+int Field_time::store(double nr)
{
long tmp;
+ int error= 0;
if (nr > 8385959.0)
{
tmp=8385959L;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr < -8385959.0)
{
tmp= -8385959L;
current_thd->cuted_fields++;
+ error= 1;
}
else
{
@@ -2822,24 +3066,29 @@ void Field_time::store(double nr)
{
tmp=0;
current_thd->cuted_fields++;
+ error= 1;
}
}
int3store(ptr,tmp);
+ return error;
}
-void Field_time::store(longlong nr)
+int Field_time::store(longlong nr)
{
long tmp;
+ int error= 0;
if (nr > (longlong) 8385959L)
{
tmp=8385959L;
current_thd->cuted_fields++;
+ error= 1;
}
else if (nr < (longlong) -8385959L)
{
tmp= -8385959L;
current_thd->cuted_fields++;
+ error= 1;
}
else
{
@@ -2848,9 +3097,11 @@ void Field_time::store(longlong nr)
{
tmp=0;
current_thd->cuted_fields++;
+ error= 1;
}
}
int3store(ptr,tmp);
+ return error;
}
@@ -2865,6 +3116,12 @@ longlong Field_time::val_int(void)
return (longlong) sint3korr(ptr);
}
+
+/*
+ This function is multi-byte safe as the result string is always of type
+ my_charset_bin
+*/
+
String *Field_time::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -2876,10 +3133,11 @@ String *Field_time::val_str(String *val_buffer,
tmp= -tmp;
sign= "-";
}
- sprintf((char*) val_buffer->ptr(),"%s%02d:%02d:%02d",
- sign,(int) (tmp/10000), (int) (tmp/100 % 100),
- (int) (tmp % 100));
- val_buffer->length((uint) strlen(val_buffer->ptr()));
+ long length= my_sprintf((char*) val_buffer->ptr(),
+ ((char*) val_buffer->ptr(),"%s%02d:%02d:%02d",
+ sign,(int) (tmp/10000), (int) (tmp/100 % 100),
+ (int) (tmp % 100)));
+ val_buffer->length(length);
return val_buffer;
}
@@ -2900,6 +3158,17 @@ bool Field_time::get_time(TIME *ltime)
return 0;
}
+
+bool Field_time::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_time::get_time(&tm);
+ tm.day= tm.hour/3600; // Move hours to days
+ tm.hour-= tm.day*3600;
+ return protocol->store_time(&tm);
+}
+
+
int Field_time::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -2917,7 +3186,7 @@ void Field_time::sort_string(char *to,uint length __attribute__((unused)))
void Field_time::sql_type(String &res) const
{
- res.set("time",4);
+ res.set_latin1("time", 4);
}
/****************************************************************************
@@ -2926,18 +3195,19 @@ void Field_time::sql_type(String &res) const
** Can handle 2 byte or 4 byte years!
****************************************************************************/
-void Field_year::store(const char *from, uint len)
+int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
{
- String tmp_str(from,len);
- long nr= strtol(tmp_str.c_ptr(),NULL,10);
+ int not_used; // We can ignore result from str2int
+ char *end;
+ long nr= my_strntol(cs, from, len, 10, &end, &not_used);
if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
{
*ptr=0;
current_thd->cuted_fields++;
- return;
+ return 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len))
+ else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
current_thd->cuted_fields++;
if (nr != 0 || len != 4)
{
@@ -2947,23 +3217,27 @@ void Field_year::store(const char *from, uint len)
nr-= 1900;
}
*ptr= (char) (unsigned char) nr;
+ return 0;
}
-void Field_year::store(double nr)
+int Field_year::store(double nr)
{
if (nr < 0.0 || nr >= 2155.0)
- Field_year::store((longlong) -1);
+ {
+ (void) Field_year::store((longlong) -1);
+ return 1;
+ }
else
- Field_year::store((longlong) nr);
+ return Field_year::store((longlong) nr);
}
-void Field_year::store(longlong nr)
+int Field_year::store(longlong nr)
{
if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
{
*ptr=0;
current_thd->cuted_fields++;
- return;
+ return 1;
}
if (nr != 0 || field_length != 4) // 0000 -> 0; 00 -> 2000
{
@@ -2973,8 +3247,14 @@ void Field_year::store(longlong nr)
nr-= 1900;
}
*ptr= (char) (unsigned char) nr;
+ return 0;
}
+bool Field_year::send_binary(Protocol *protocol)
+{
+ ulonglong tmp= Field_year::val_int();
+ return protocol->store_short(tmp);
+}
double Field_year::val_real(void)
{
@@ -3003,8 +3283,9 @@ String *Field_year::val_str(String *val_buffer,
void Field_year::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"year(%d)",(int) field_length);
- res.length((uint) strlen(res.ptr()));
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),
+ "year(%d)",(int) field_length));
}
@@ -3015,12 +3296,16 @@ void Field_year::sql_type(String &res) const
** Stored as a 4 byte unsigned int
****************************************************************************/
-void Field_date::store(const char *from, uint len)
+int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
{
TIME l_time;
uint32 tmp;
+ int error= 0;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
+ {
tmp=0;
+ error= 1;
+ }
else
tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
#ifdef WORDS_BIGENDIAN
@@ -3031,18 +3316,21 @@ void Field_date::store(const char *from, uint len)
else
#endif
longstore(ptr,tmp);
+ return error;
}
-void Field_date::store(double nr)
+int Field_date::store(double nr)
{
long tmp;
+ int error= 0;
if (nr >= 19000000000000.0 && nr <= 99991231235959.0)
nr=floor(nr/1000000.0); // Timestamp to date
if (nr < 0.0 || nr > 99991231.0)
{
tmp=0L;
current_thd->cuted_fields++;
+ error= 1;
}
else
tmp=(long) rint(nr);
@@ -3054,18 +3342,21 @@ void Field_date::store(double nr)
else
#endif
longstore(ptr,tmp);
+ return error;
}
-void Field_date::store(longlong nr)
+int Field_date::store(longlong nr)
{
long tmp;
+ int error= 0;
if (nr >= LL(19000000000000) && nr < LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0 || nr > LL(99991231))
{
tmp=0L;
current_thd->cuted_fields++;
+ error= 1;
}
else
tmp=(long) nr;
@@ -3077,6 +3368,18 @@ void Field_date::store(longlong nr)
else
#endif
longstore(ptr,tmp);
+ return error;
+}
+
+
+bool Field_date::send_binary(Protocol *protocol)
+{
+ longlong tmp= Field_date::val_int();
+ TIME tm;
+ tm.year= (uint32) tmp/10000L % 10000;
+ tm.month= (uint32) tmp/100 % 100;
+ tm.day= (uint32) tmp % 100;
+ return protocol->store_date(&tm);
}
@@ -3163,7 +3466,7 @@ void Field_date::sort_string(char *to,uint length __attribute__((unused)))
void Field_date::sql_type(String &res) const
{
- res.set("date",4);
+ res.set_latin1("date", 4);
}
/****************************************************************************
@@ -3172,35 +3475,45 @@ void Field_date::sql_type(String &res) const
** In number context: YYYYMMDD
****************************************************************************/
-void Field_newdate::store(const char *from,uint len)
+int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME l_time;
long tmp;
+ int error= 0;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
+ {
tmp=0L;
+ error= 1;
+ }
else
tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
int3store(ptr,tmp);
+ return error;
}
-void Field_newdate::store(double nr)
+int Field_newdate::store(double nr)
{
if (nr < 0.0 || nr > 99991231235959.0)
- Field_newdate::store((longlong) -1);
+ {
+ (void) Field_newdate::store((longlong) -1);
+ return 1;
+ }
else
- Field_newdate::store((longlong) rint(nr));
+ return Field_newdate::store((longlong) rint(nr));
}
-void Field_newdate::store(longlong nr)
+int Field_newdate::store(longlong nr)
{
int32 tmp;
+ int error= 0;
if (nr >= LL(100000000) && nr <= LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0L || nr > 99991231L)
{
tmp=0;
current_thd->cuted_fields++;
+ error= 1;
}
else
{
@@ -3218,11 +3531,13 @@ void Field_newdate::store(longlong nr)
{
tmp=0L; // Don't allow date to change
current_thd->cuted_fields++;
+ error= 1;
}
else
tmp= day + month*32 + (tmp/10000)*16*32;
}
int3store(ptr,(int32) tmp);
+ return error;
}
void Field_newdate::store_time(TIME *ltime,timestamp_type type)
@@ -3238,7 +3553,12 @@ void Field_newdate::store_time(TIME *ltime,timestamp_type type)
int3store(ptr,tmp);
}
-
+bool Field_newdate::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_newdate::get_date(&tm,0);
+ return protocol->store_date(&tm);
+}
double Field_newdate::val_real(void)
{
@@ -3314,7 +3634,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused)))
void Field_newdate::sql_type(String &res) const
{
- res.set("date",4);
+ res.set_latin1("date", 4);
}
@@ -3325,7 +3645,7 @@ void Field_newdate::sql_type(String &res) const
** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int.
****************************************************************************/
-void Field_datetime::store(const char *from,uint len)
+int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
{
longlong tmp=str_to_datetime(from,len,1);
#ifdef WORDS_BIGENDIAN
@@ -3336,26 +3656,32 @@ void Field_datetime::store(const char *from,uint len)
else
#endif
longlongstore(ptr,tmp);
+ return 0;
}
-void Field_datetime::store(double nr)
+int Field_datetime::store(double nr)
{
+ int error= 0;
if (nr < 0.0 || nr > 99991231235959.0)
{
nr=0.0;
current_thd->cuted_fields++;
+ error= 1;
}
- Field_datetime::store((longlong) rint(nr));
+ error |= Field_datetime::store((longlong) rint(nr));
+ return error;
}
-void Field_datetime::store(longlong nr)
+int Field_datetime::store(longlong nr)
{
+ int error= 0;
if (nr < 0 || nr > LL(99991231235959))
{
nr=0;
current_thd->cuted_fields++;
+ error= 1;
}
else
nr=fix_datetime(nr);
@@ -3367,6 +3693,7 @@ void Field_datetime::store(longlong nr)
else
#endif
longlongstore(ptr,nr);
+ return error;
}
void Field_datetime::store_time(TIME *ltime,timestamp_type type)
@@ -3390,6 +3717,13 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type)
longlongstore(ptr,tmp);
}
+bool Field_datetime::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_datetime::get_date(&tm, 1);
+ return protocol->store(&tm);
+}
+
double Field_datetime::val_real(void)
{
@@ -3531,7 +3865,7 @@ void Field_datetime::sort_string(char *to,uint length __attribute__((unused)))
void Field_datetime::sql_type(String &res) const
{
- res.set("datetime",8);
+ res.set_latin1("datetime", 8);
}
/****************************************************************************
@@ -3541,21 +3875,14 @@ void Field_datetime::sql_type(String &res) const
/* Copy a string and fill with space */
-void Field_string::store(const char *from,uint length)
+int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
-#ifdef USE_TIS620
- if (!binary_flag) {
- ThNormalize((uchar *)ptr, field_length, (uchar *)from, length);
- if (length < field_length) {
- bfill(ptr + length, field_length - length, ' ');
- }
- }
-#else
+ int error= 0;
if (length <= field_length)
{
memcpy(ptr,from,length);
if (length < field_length)
- bfill(ptr+length,field_length-length,' ');
+ field_charset->fill(field_charset,ptr+length,field_length-length,' ');
}
else
{
@@ -3563,57 +3890,52 @@ void Field_string::store(const char *from,uint length)
if (current_thd->count_cuted_fields)
{ // Check if we loosed some info
const char *end=from+length;
- for (from+=field_length ; from != end ; from++)
+ from+= field_length;
+ from+= field_charset->scan(field_charset, from, end, MY_SEQ_SPACES);
+ if (from != end)
{
- if (!isspace(*from))
- {
- current_thd->cuted_fields++;
- break;
- }
+ current_thd->cuted_fields++;
+ error=1;
}
}
}
-#endif /* USE_TIS620 */
+ return error;
}
-void Field_string::store(double nr)
+int Field_string::store(double nr)
{
char buff[MAX_FIELD_WIDTH],*end;
int width=min(field_length,DBL_DIG+5);
sprintf(buff,"%-*.*g",width,max(width-5,0),nr);
end=strcend(buff,' ');
- Field_string::store(buff,(uint) (end - buff));
+ return Field_string::store(buff,(uint) (end - buff), &my_charset_bin);
}
-void Field_string::store(longlong nr)
+int Field_string::store(longlong nr)
{
- char buff[22];
- char *end=longlong10_to_str(nr,buff,-10);
- Field_string::store(buff,(uint) (end-buff));
+ char buff[64];
+ int l;
+ CHARSET_INFO *cs=charset();
+ l= (cs->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr);
+ return Field_string::store(buff,(uint)l,cs);
}
double Field_string::val_real(void)
{
- double value;
- char save=ptr[field_length]; // Ok to patch record
- ptr[field_length]=0;
- value=atof(ptr);
- ptr[field_length]=save;
- return value;
+ int not_used;
+ CHARSET_INFO *cs=charset();
+ return my_strntod(cs,ptr,field_length,(char**)0,&not_used);
}
longlong Field_string::val_int(void)
{
- longlong value;
- char save=ptr[field_length]; // Ok to patch record
- ptr[field_length]=0;
- value=strtoll(ptr,NULL,10);
- ptr[field_length]=save;
- return value;
+ int not_used;
+ CHARSET_INFO *cs=charset();
+ return my_strntoll(cs,ptr,field_length,10,NULL,&not_used);
}
@@ -3626,51 +3948,40 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
#endif
while (end > ptr && end[-1] == ' ')
end--;
- val_ptr->set((const char*) ptr,(uint) (end - ptr));
+ val_ptr->set((const char*) ptr,(uint) (end - ptr),field_charset);
return val_ptr;
}
int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
- if (binary_flag)
- return memcmp(a_ptr,b_ptr,field_length);
- else
- return my_sortcmp(a_ptr,b_ptr,field_length);
+ return my_strnncoll(field_charset,
+ (const uchar*)a_ptr,field_length,
+ (const uchar*)b_ptr,field_length);
}
void Field_string::sort_string(char *to,uint length)
{
- if (binary_flag)
- memcpy((byte*) to,(byte*) ptr,(size_t) length);
- else
- {
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info)) {
- uint tmp=my_strnxfrm(default_charset_info,
- (unsigned char *)to, (unsigned char *) ptr,
- length, field_length);
- if (tmp < length)
- bzero(to + tmp, length - tmp);
- }
- else
-#endif
- for (char *from=ptr,*end=ptr+length ; from != end ;)
- *to++=(char) my_sort_order[(uint) (uchar) *from++];
- }
+ uint tmp=my_strnxfrm(field_charset,
+ (unsigned char *)to, length,
+ (unsigned char *) ptr, field_length);
+ if (tmp < length)
+ bzero(to + tmp, length - tmp);
}
void Field_string::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"%s(%d)",
- field_length > 3 &&
- (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
- "varchar" : "char",
- (int) field_length);
- res.length((uint) strlen(res.ptr()));
- if (binary_flag)
- res.append(" binary");
+ CHARSET_INFO *cs=res.charset();
+ ulong length= cs->snprintf(cs,(char*) res.ptr(),
+ res.alloced_length(), "%s(%d)",
+ (field_length > 3 &&
+ (table->db_options_in_use &
+ HA_OPTION_PACK_RECORD) ?
+ "varchar" : "char"),
+ (int) field_length);
+ res.length(length);
+ add_binary_or_charset(res);
}
@@ -3699,13 +4010,9 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length)
{
uint a_length= (uint) (uchar) *a++;
uint b_length= (uint) (uchar) *b++;
-
- if (binary_flag)
- {
- int cmp= memcmp(a,b,min(a_length,b_length));
- return cmp ? cmp : (int) (a_length - b_length);
- }
- return my_sortncmp(a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar*)a,a_length,
+ (const uchar*)b,b_length);
}
@@ -3716,13 +4023,9 @@ int Field_string::pack_cmp(const char *b, uint length)
while (end > ptr && end[-1] == ' ')
end--;
uint a_length = (uint) (end - ptr);
-
- if (binary_flag)
- {
- int cmp= memcmp(ptr,b,min(a_length,b_length));
- return cmp ? cmp : (int) (a_length - b_length);
- }
- return my_sortncmp(ptr,a_length, b, b_length);
+ return my_strnncoll(field_charset,
+ (const uchar*)ptr,a_length,
+ (const uchar*)b, b_length);
}
@@ -3745,68 +4048,56 @@ uint Field_string::max_packed_col_length(uint max_length)
****************************************************************************/
-void Field_varstring::store(const char *from,uint length)
+int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
-#ifdef USE_TIS620
- if (!binary_flag)
- {
- ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length);
- }
-#else
- if (length <= field_length)
- {
- memcpy(ptr+2,from,length);
- }
- else
+ int error= 0;
+ if (length > field_length)
{
length=field_length;
- memcpy(ptr+2,from,field_length);
current_thd->cuted_fields++;
+ error= 1;
}
-#endif /* USE_TIS620 */
- int2store(ptr,length);
+ memcpy(ptr+2,from,length);
+ int2store(ptr, length);
+ return error;
}
-void Field_varstring::store(double nr)
+int Field_varstring::store(double nr)
{
char buff[MAX_FIELD_WIDTH],*end;
int width=min(field_length,DBL_DIG+5);
sprintf(buff,"%-*.*g",width,max(width-5,0),nr);
end=strcend(buff,' ');
- Field_varstring::store(buff,(uint) (end - buff));
+ return Field_varstring::store(buff,(uint) (end - buff), &my_charset_bin);
}
-void Field_varstring::store(longlong nr)
+int Field_varstring::store(longlong nr)
{
- char buff[22];
- char *end=longlong10_to_str(nr,buff,-10);
- Field_varstring::store(buff,(uint) (end-buff));
+ char buff[64];
+ int l;
+ CHARSET_INFO *cs=charset();
+ l= (cs->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr);
+ return Field_varstring::store(buff,(uint)l,cs);
}
double Field_varstring::val_real(void)
{
- double value;
+ int not_used;
uint length=uint2korr(ptr)+2;
- char save=ptr[length]; // Ok to patch record
- ptr[length]=0;
- value=atof(ptr+2);
- ptr[length]=save;
- return value;
+ CHARSET_INFO *cs=charset();
+ return my_strntod(cs,ptr+2,length,(char**)0, &not_used);
}
longlong Field_varstring::val_int(void)
{
- longlong value;
+ int not_used;
uint length=uint2korr(ptr)+2;
- char save=ptr[length]; // Ok to patch record
- ptr[length]=0;
- value=strtoll(ptr+2,NULL,10);
- ptr[length]=save;
- return value;
+ CHARSET_INFO *cs=charset();
+ return my_strntoll(cs,ptr+2,length,10,NULL, &not_used);
}
@@ -3814,7 +4105,7 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
uint length=uint2korr(ptr);
- val_ptr->set((const char*) ptr+2,length);
+ val_ptr->set((const char*) ptr+2,length,field_charset);
return val_ptr;
}
@@ -3824,37 +4115,18 @@ int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
uint a_length=uint2korr(a_ptr);
uint b_length=uint2korr(b_ptr);
int diff;
- if (binary_flag)
- diff=memcmp(a_ptr+2,b_ptr+2,min(a_length,b_length));
- else
- diff=my_sortcmp(a_ptr+2,b_ptr+2,min(a_length,b_length));
+ diff=my_strnncoll(field_charset,
+ (const uchar*)a_ptr+2,min(a_length,b_length),
+ (const uchar*)b_ptr+2,min(a_length,b_length));
return diff ? diff : (int) (a_length - b_length);
}
void Field_varstring::sort_string(char *to,uint length)
{
uint tot_length=uint2korr(ptr);
- if (binary_flag)
- memcpy((byte*) to,(byte*) ptr+2,(size_t) tot_length);
- else
- {
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- tot_length=my_strnxfrm(default_charset_info,
- (unsigned char *) to, (unsigned char *)ptr+2,
- length, tot_length);
- else
- {
-#endif
- char *tmp=to;
- if (tot_length > length)
- tot_length=length;
- for (char *from=ptr+2,*end=from+tot_length ; from != end ;)
- *tmp++=(char) my_sort_order[(uint) (uchar) *from++];
-#ifdef USE_STRCOLL
- }
-#endif
- }
+ tot_length=my_strnxfrm(field_charset,
+ (unsigned char *) to, length,
+ (unsigned char *)ptr+2, tot_length);
if (tot_length < length)
bzero(to+tot_length,length-tot_length);
}
@@ -3862,10 +4134,12 @@ void Field_varstring::sort_string(char *to,uint length)
void Field_varstring::sql_type(String &res) const
{
- sprintf((char*) res.ptr(),"varchar(%d)",(int) field_length);
- res.length((uint) strlen(res.ptr()));
- if (binary_flag)
- res.append(" binary");
+ CHARSET_INFO *cs=res.charset();
+ ulong length= cs->snprintf(cs,(char*) res.ptr(),
+ res.alloced_length(),"varchar(%u)",
+ field_length);
+ res.length(length);
+ add_binary_or_charset(res);
}
char *Field_varstring::pack(char *to, const char *from, uint max_length)
@@ -3916,12 +4190,9 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- if (binary_flag)
- {
- int cmp= memcmp(a,b,min(a_length,b_length));
- return cmp ? cmp : (int) (a_length - b_length);
- }
- return my_sortncmp(a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
int Field_varstring::pack_cmp(const char *b, uint key_length)
@@ -3937,12 +4208,9 @@ int Field_varstring::pack_cmp(const char *b, uint key_length)
{
b_length= (uint) (uchar) *b++;
}
- if (binary_flag)
- {
- int cmp= memcmp(a,b,min(a_length,b_length));
- return cmp ? cmp : (int) (a_length - b_length);
- }
- return my_sortncmp(a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
@@ -3958,6 +4226,29 @@ uint Field_varstring::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
+void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
+ imagetype type)
+{
+ length-= HA_KEY_BLOB_LENGTH;
+ uint f_length=uint2korr(ptr);
+ if (f_length > length)
+ f_length= length;
+ int2store(buff,length);
+ memcpy(buff+2,ptr+2,length);
+#ifdef HAVE_purify
+ if (f_length < length)
+ bzero(buff+2+f_length, (length-f_length));
+#endif
+}
+
+void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+{
+ length=uint2korr(buff); // Real length is here
+ (void) Field_varstring::store(buff+2, length, cs);
+}
+
+
+
/****************************************************************************
** blob type
** A blob is saved as a length and a pointer. The length is stored in the
@@ -3967,15 +4258,13 @@ uint Field_varstring::max_packed_col_length(uint max_length)
Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
- bool binary_arg)
+ CHARSET_INFO *cs)
:Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
- table_arg),
- packlength(blob_pack_length),binary_flag(binary_arg)
+ table_arg, cs),
+ packlength(blob_pack_length), geom_flag(true)
{
flags|= BLOB_FLAG;
- if (binary_arg)
- flags|=BINARY_FLAG;
if (table)
table->blob_fields++;
}
@@ -4062,7 +4351,7 @@ uint32 Field_blob::get_length(const char *pos)
}
-void Field_blob::store(const char *from,uint len)
+int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs)
{
if (!len)
{
@@ -4070,78 +4359,56 @@ void Field_blob::store(const char *from,uint len)
}
else
{
-#ifdef USE_TIS620
- char *th_ptr=0;
-#endif
Field_blob::store_length(len);
if (table->copy_blobs || len <= MAX_FIELD_WIDTH)
{ // Must make a copy
-#ifdef USE_TIS620
- if (!binary_flag)
- {
- /* If there isn't enough memory, use original string */
- if ((th_ptr=(char * ) my_malloc(sizeof(char) * len,MYF(0))))
- {
- ThNormalize((uchar *) th_ptr, len, (uchar *) from, len);
- from= (const char*) th_ptr;
- }
- }
-#endif /* USE_TIS620 */
- value.copy(from,len);
+ value.copy(from,len,charset());
from=value.ptr();
-#ifdef USE_TIS620
- my_free(th_ptr,MYF(MY_ALLOW_ZERO_PTR));
-#endif
}
bmove(ptr+packlength,(char*) &from,sizeof(char*));
}
+ return 0;
}
-void Field_blob::store(double nr)
+int Field_blob::store(double nr)
{
- value.set(nr);
- Field_blob::store(value.ptr(),(uint) value.length());
+ CHARSET_INFO *cs=charset();
+ value.set(nr, 2, cs);
+ return Field_blob::store(value.ptr(),(uint) value.length(), cs);
}
-void Field_blob::store(longlong nr)
+int Field_blob::store(longlong nr)
{
- value.set(nr);
- Field_blob::store(value.ptr(), (uint) value.length());
+ CHARSET_INFO *cs=charset();
+ value.set(nr, cs);
+ return Field_blob::store(value.ptr(), (uint) value.length(), cs);
}
double Field_blob::val_real(void)
{
+ int not_used;
char *blob;
-
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0.0;
uint32 length=get_length(ptr);
-
- char save=blob[length]; // Ok to patch blob in NISAM
- blob[length]=0;
- double nr=atof(blob);
- blob[length]=save;
- return nr;
+ CHARSET_INFO *cs=charset();
+ return my_strntod(cs,blob,length,(char**)0, &not_used);
}
longlong Field_blob::val_int(void)
{
+ int not_used;
char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0;
uint32 length=get_length(ptr);
-
- char save=blob[length]; // Ok to patch blob in NISAM
- blob[length]=0;
- longlong nr=strtoll(blob,NULL,10);
- blob[length]=save;
- return nr;
+ return my_strntoll(charset(),blob,length,10,NULL,&not_used);
}
@@ -4151,9 +4418,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
- val_ptr->set("",0); // A bit safer than ->length(0)
+ val_ptr->set("",0,charset()); // A bit safer than ->length(0)
else
- val_ptr->set((const char*) blob,get_length(ptr));
+ val_ptr->set((const char*) blob,get_length(ptr),charset());
return val_ptr;
}
@@ -4161,11 +4428,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
uint32 b_length)
{
- int diff;
- if (binary_flag)
- diff=memcmp(a,b,min(a_length,b_length));
- else
- diff=my_sortcmp(a,b,min(a_length,b_length));
+ int diff=my_strnncoll(field_charset,
+ (const uchar*)a,min(a_length,b_length),
+ (const uchar*)b,min(a_length,b_length));
return diff ? diff : (int) (a_length - b_length);
}
@@ -4213,11 +4478,30 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
-void Field_blob::get_key_image(char *buff,uint length)
+void Field_blob::get_key_image(char *buff,uint length,
+ CHARSET_INFO *cs, imagetype type)
{
- length-=HA_KEY_BLOB_LENGTH;
- uint32 blob_length=get_length(ptr);
+ length-= HA_KEY_BLOB_LENGTH;
+ uint32 blob_length= get_length(ptr);
char *blob;
+
+ if (type == itMBR)
+ {
+ if (!blob_length)
+ return;
+ get_ptr(&blob);
+
+ MBR mbr;
+ Geometry gobj;
+ gobj.create_from_wkb(blob,blob_length);
+ gobj.get_mbr(&mbr);
+ float8store(buff, mbr.xmin);
+ float8store(buff+8, mbr.xmax);
+ float8store(buff+16, mbr.ymin);
+ float8store(buff+24, mbr.ymax);
+ return;
+ }
+
if ((uint32) length > blob_length)
{
/*
@@ -4232,10 +4516,41 @@ void Field_blob::get_key_image(char *buff,uint length)
memcpy(buff+2,blob,length);
}
-void Field_blob::set_key_image(char *buff,uint length)
+void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
{
length=uint2korr(buff);
- Field_blob::store(buff+2,length);
+ (void) Field_blob::store(buff+2,length,cs);
+}
+
+
+void Field_geom::get_key_image(char *buff,uint length,CHARSET_INFO *cs,
+ imagetype type)
+{
+ length-=HA_KEY_BLOB_LENGTH;
+ ulong blob_length=get_length(ptr);
+ char *blob;
+ get_ptr(&blob);
+ memcpy(buff+2,blob,length);
+
+ MBR mbr;
+ Geometry gobj;
+ gobj.create_from_wkb(blob,blob_length);
+ gobj.get_mbr(&mbr);
+ float8store(buff, mbr.xmin);
+ float8store(buff+8, mbr.xmax);
+ float8store(buff+16, mbr.ymin);
+ float8store(buff+24, mbr.ymax);
+ return;
+}
+
+void Field_geom::set_key_image(char *buff,uint length,CHARSET_INFO *cs)
+{
+ Field_blob::set_key_image(buff, length, cs);
+}
+
+void Field_geom::sql_type(String &res) const
+{
+ res.set("geometry", 8, default_charset_info);
}
int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
@@ -4259,39 +4574,18 @@ void Field_blob::sort_string(char *to,uint length)
{
char *blob;
uint blob_length=get_length();
-#ifdef USE_STRCOLL
- uint blob_org_length=blob_length;
-#endif
+
if (!blob_length)
bzero(to,length);
else
{
- if (blob_length > length)
- blob_length=length;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
- if (binary_flag)
- {
- memcpy(to,blob,blob_length);
- to+=blob_length;
- }
- else
- {
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- {
- blob_length=my_strnxfrm(default_charset_info,
- (unsigned char *)to,(unsigned char *)blob,
- length,blob_org_length);
- if (blob_length >= length)
- return;
- to+=blob_length;
- }
- else
-#endif
- for (char *end=blob+blob_length ; blob != end ;)
- *to++=(char) my_sort_order[(uint) (uchar) *blob++];
- }
- bzero(to,length-blob_length);
+
+ blob_length=my_strnxfrm(field_charset,
+ (unsigned char *)to, length,
+ (unsigned char *)blob, blob_length);
+ if (blob_length < length)
+ bzero(to+blob_length, length-blob_length);
}
}
@@ -4299,14 +4593,25 @@ void Field_blob::sort_string(char *to,uint length)
void Field_blob::sql_type(String &res) const
{
const char *str;
+ uint length;
switch (packlength) {
- default: str="tiny"; break;
- case 2: str=""; break;
- case 3: str="medium"; break;
- case 4: str="long"; break;
+ default: str="tiny"; length=4; break;
+ case 2: str=""; length=0; break;
+ case 3: str="medium"; length= 6; break;
+ case 4: str="long"; length=4; break;
+ }
+ res.set_latin1(str,length);
+ if (binary())
+ res.append("blob");
+ else
+ {
+ res.append("text");
+ if (field_charset != table->table_charset)
+ {
+ res.append(" character set ");
+ res.append(field_charset->csname);
+ }
}
- res.set(str,(uint) strlen(str));
- res.append(binary_flag ? "blob" : "text");
}
@@ -4362,12 +4667,9 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- if (binary_flag)
- {
- int cmp= memcmp(a,b,min(a_length,b_length));
- return cmp ? cmp : (int) (a_length - b_length);
- }
- return my_sortncmp(a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
@@ -4388,12 +4690,9 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
{
b_length= (uint) (uchar) *b++;
}
- if (binary_flag)
- {
- int cmp= memcmp(a,b,min(a_length,b_length));
- return cmp ? cmp : (int) (a_length - b_length);
- }
- return my_sortncmp(a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
/* Create a packed key that will be used for storage from a MySQL row */
@@ -4504,14 +4803,16 @@ void Field_enum::store_type(ulonglong value)
uint find_enum(TYPELIB *lib,const char *x, uint length)
{
const char *end=x+length;
- while (end > x && isspace(end[-1]))
+ while (end > x && my_isspace(system_charset_info,end[-1]))
end--;
const char *i;
const char *j;
for (uint pos=0 ; (j=lib->type_names[pos]) ; pos++)
{
- for (i=x ; i != end && toupper(*i) == toupper(*j) ; i++, j++) ;
+ for (i=x ; i != end &&
+ my_toupper(system_charset_info,*i) ==
+ my_toupper(system_charset_info,*j) ; i++, j++) ;
if (i == end && ! *j)
return(pos+1);
}
@@ -4524,24 +4825,18 @@ uint find_enum(TYPELIB *lib,const char *x, uint length)
** (if there isn't a empty value in the enum)
*/
-void Field_enum::store(const char *from,uint length)
+int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
+ int err= 0;
uint tmp=find_enum(typelib,from,length);
if (!tmp)
{
if (length < 6) // Can't be more than 99999 enums
{
/* This is for reading numbers with LOAD DATA INFILE */
- char buff[7], *end;
- const char *conv=from;
- if (from[length])
- {
- strmake(buff, from, length);
- conv=buff;
- }
- my_errno=0;
- tmp=(uint) strtoul(conv,&end,10);
- if (my_errno || end != conv+length || tmp > typelib->count)
+ char *end;
+ tmp=(uint) my_strntoul(cs,from,length,10,&end,&err);
+ if (err || end != from+length || tmp > typelib->count)
{
tmp=0;
current_thd->cuted_fields++;
@@ -4551,23 +4846,27 @@ void Field_enum::store(const char *from,uint length)
current_thd->cuted_fields++;
}
store_type((ulonglong) tmp);
+ return err;
}
-void Field_enum::store(double nr)
+int Field_enum::store(double nr)
{
- Field_enum::store((longlong) nr);
+ return Field_enum::store((longlong) nr);
}
-void Field_enum::store(longlong nr)
+int Field_enum::store(longlong nr)
{
+ int error= 0;
if ((uint) nr > typelib->count || nr == 0)
{
current_thd->cuted_fields++;
nr=0;
+ error=1;
}
store_type((ulonglong) (uint) nr);
+ return error;
}
@@ -4630,7 +4929,8 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)),
val_ptr->length(0);
else
val_ptr->set((const char*) typelib->type_names[tmp-1],
- (uint) strlen(typelib->type_names[tmp-1]));
+ (uint) strlen(typelib->type_names[tmp-1]),
+ field_charset);
return val_ptr;
}
@@ -4667,47 +4967,60 @@ void Field_enum::sql_type(String &res) const
{
if (flag)
res.append(',');
- res.append('\'');
- append_unescaped(&res,*pos);
- res.append('\'');
+ append_unescaped(&res, *pos, strlen(*pos));
flag=1;
}
res.append(')');
+ add_binary_or_charset(res);
}
-/****************************************************************************
-** set type.
-** This is a string which can have a collection of different values.
-** Each string value is separated with a ','.
-** For example "One,two,five"
-** If one uses this string in a number context one gets the bits as a longlong
-** number.
-****************************************************************************/
+/*
+ set type.
+ This is a string which can have a collection of different values.
+ Each string value is separated with a ','.
+ For example "One,two,five"
+ If one uses this string in a number context one gets the bits as a longlong
+ number.
+
+ If there was a value in string that wasn't in set, the 'err_pos' points to
+ the last invalid value found. 'err_len' will be set to length of the
+ error string.
+*/
-ulonglong find_set(TYPELIB *lib,const char *x,uint length)
+ulonglong find_set(TYPELIB *lib, const char *x, uint length, char **err_pos,
+ uint *err_len)
{
- const char *end=x+length;
- while (end > x && isspace(end[-1]))
+ const char *end= x + length;
+ *err_pos= 0; // No error yet
+ while (end > x && my_isspace(system_charset_info, end[-1]))
end--;
- ulonglong found=0;
+ *err_len= 0;
+ ulonglong found= 0;
if (x != end)
{
- const char *start=x;
- bool error=0;
+ const char *start= x;
+ bool error= 0;
for (;;)
{
- const char *pos=start;
- for (; pos != end && *pos != field_separator ; pos++) ;
- uint find=find_enum(lib,start,(uint) (pos-start));
+ const char *pos= start;
+ uint var_len;
+
+ for (; pos != end && *pos != field_separator; pos++) ;
+ var_len= (uint) (pos - start);
+ uint find= find_enum(lib, start, var_len);
if (!find)
- error=1;
+ {
+ *err_pos= (char*) start;
+ *err_len= var_len;
+ error= 1;
+ }
else
- found|= ((longlong) 1 << (find-1));
+ found|= ((longlong) 1 << (find - 1));
if (pos == end)
- break;
- start=pos+1;
+ break;
+ start= pos + 1;
}
if (error)
current_thd->cuted_fields++;
@@ -4716,40 +5029,43 @@ ulonglong find_set(TYPELIB *lib,const char *x,uint length)
}
-void Field_set::store(const char *from,uint length)
+int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ulonglong tmp=find_set(typelib,from,length);
+ int err= 0;
+ char *not_used;
+ uint not_used2;
+
+ ulonglong tmp= find_set(typelib, from, length, &not_used, &not_used2);
if (!tmp && length && length < 22)
{
/* This is for reading numbers with LOAD DATA INFILE */
- char buff[22], *end;
- const char *conv=from;
- if (from[length])
- {
- strmake(buff, from, length);
- conv=buff;
- }
- my_errno=0;
- tmp=strtoull(conv,&end,10);
- if (my_errno || end != conv+length ||
+ char *end;
+ tmp=my_strntoull(cs,from,length,10,&end,&err);
+ if (err || end != from+length ||
tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1))
+ {
tmp=0;
+ }
else
current_thd->cuted_fields--; // Remove warning from find_set
}
store_type(tmp);
+ return err;
}
-void Field_set::store(longlong nr)
+int Field_set::store(longlong nr)
{
+ int error= 0;
if ((ulonglong) nr > (ulonglong) (((longlong) 1 << typelib->count) -
(longlong) 1))
{
nr&= (longlong) (((longlong) 1 << typelib->count) - (longlong) 1);
current_thd->cuted_fields++;
+ error=1;
}
store_type((ulonglong) nr);
+ return error;
}
@@ -4767,7 +5083,8 @@ String *Field_set::val_str(String *val_buffer,
if (val_buffer->length())
val_buffer->append(field_separator);
String str(typelib->type_names[bitnr],
- (uint) strlen(typelib->type_names[bitnr]));
+ (uint) strlen(typelib->type_names[bitnr]),
+ field_charset);
val_buffer->append(str);
}
tmp>>=1;
@@ -4787,12 +5104,11 @@ void Field_set::sql_type(String &res) const
{
if (flag)
res.append(',');
- res.append('\'');
- append_unescaped(&res,*pos);
- res.append('\'');
+ append_unescaped(&res, *pos, strlen(*pos));
flag=1;
}
res.append(')');
+ add_binary_or_charset(res);
}
/* returns 1 if the fields are equally defined */
@@ -4814,7 +5130,8 @@ bool Field_enum::eq_def(Field *field)
if (typelib->count < from_lib->count)
return 0;
for (uint i=0 ; i < from_lib->count ; i++)
- if (my_strcasecmp(typelib->type_names[i],from_lib->type_names[i]))
+ if (my_strcasecmp(field_charset,
+ typelib->type_names[i],from_lib->type_names[i]))
return 0;
return 1;
}
@@ -4862,7 +5179,8 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_LONGLONG: return 8; /* Don't crash if no longlong */
case FIELD_TYPE_NULL : return 0;
case FIELD_TYPE_TINY_BLOB: return 1+portable_sizeof_char_ptr;
- case FIELD_TYPE_BLOB: return 2+portable_sizeof_char_ptr;
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_GEOMETRY: return 2+portable_sizeof_char_ptr;
case FIELD_TYPE_MEDIUM_BLOB: return 3+portable_sizeof_char_ptr;
case FIELD_TYPE_LONG_BLOB: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_SET:
@@ -4890,6 +5208,7 @@ Field *make_field(char *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
enum_field_types field_type,
+ CHARSET_INFO *field_charset,
Field::utype unireg_check,
TYPELIB *interval,
const char *field_name,
@@ -4904,30 +5223,30 @@ Field *make_field(char *ptr, uint32 field_length,
{
if (!f_is_packed(pack_flag))
return new Field_string(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name, table,
- f_is_binary(pack_flag) != 0);
+ unireg_check, field_name, table, field_charset);
uint pack_length=calc_pack_length((enum_field_types)
f_packtype(pack_flag),
field_length);
+ if (f_is_geom(pack_flag))
+ return new Field_geom(ptr,null_pos,null_bit,
+ unireg_check, field_name, table,
+ pack_length);
if (f_is_blob(pack_flag))
return new Field_blob(ptr,null_pos,null_bit,
unireg_check, field_name, table,
- pack_length,f_is_binary(pack_flag) != 0);
- if (f_is_geom(pack_flag))
- return 0;
-
+ pack_length, field_charset);
if (interval)
{
if (f_is_enum(pack_flag))
return new Field_enum(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
- pack_length, interval);
+ pack_length, interval, field_charset);
else
return new Field_set(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
- pack_length, interval);
+ pack_length, interval, field_charset);
}
}
@@ -4977,28 +5296,28 @@ Field *make_field(char *ptr, uint32 field_length,
f_is_dec(pack_flag) == 0);
case FIELD_TYPE_TIMESTAMP:
return new Field_timestamp(ptr,field_length,
- unireg_check, field_name, table);
+ unireg_check, field_name, table, field_charset);
case FIELD_TYPE_YEAR:
return new Field_year(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table);
case FIELD_TYPE_DATE:
return new Field_date(ptr,null_pos,null_bit,
- unireg_check, field_name, table);
+ unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NEWDATE:
return new Field_newdate(ptr,null_pos,null_bit,
- unireg_check, field_name, table);
+ unireg_check, field_name, table, field_charset);
case FIELD_TYPE_TIME:
return new Field_time(ptr,null_pos,null_bit,
- unireg_check, field_name, table);
+ unireg_check, field_name, table, field_charset);
case FIELD_TYPE_DATETIME:
return new Field_datetime(ptr,null_pos,null_bit,
- unireg_check, field_name, table);
+ unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NULL:
- return new Field_null(ptr,field_length,unireg_check,field_name,table);
+ return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
default: // Impossible (Wrong version)
break;
}
- return 0; // Impossible
+ return 0;
}
@@ -5013,6 +5332,8 @@ create_field::create_field(Field *old_field,Field *orig_field)
unireg_check=old_field->unireg_check;
pack_length=old_field->pack_length();
sql_type= old_field->real_type();
+ charset= old_field->charset(); // May be NULL ptr
+ comment= old_field->comment;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -5021,6 +5342,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
decimals= old_field->decimals();
if (sql_type == FIELD_TYPE_STRING)
{
+ /* Change CHAR -> VARCHAR if dynamic record length */
sql_type=old_field->type();
decimals=0;
}
@@ -5034,7 +5356,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
orig_field)
{
char buff[MAX_FIELD_WIDTH],*pos;
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff), charset);
/* Get the value from record[2] (the default value row) */
my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2);
@@ -5046,7 +5368,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
{
pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1);
pos[tmp.length()]=0;
- def=new Item_string(pos,tmp.length());
+ def=new Item_string(pos,tmp.length(), charset);
}
}
}
diff --git a/sql/field.h b/sql/field.h
index f064724f6a2..04225158270 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -27,10 +27,12 @@
#define NOT_FIXED_DEC 31
class Send_field;
+class Protocol;
struct st_cache_field;
void field_conv(Field *to,Field *from);
-class Field {
+class Field
+{
Field(const Item &); /* Prevent use of these */
void operator=(Field &);
public:
@@ -41,12 +43,16 @@ public:
uchar *null_ptr; // Byte where null_bit is
struct st_table *table; // Pointer for table
const char *table_name,*field_name;
+ LEX_STRING comment;
ulong query_id; // For quick test of used fields
/* Field is part of the following keys */
key_map key_start,part_of_key,part_of_sortkey;
enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
+
+ enum imagetype { itRAW, itMBR};
+
utype unireg_check;
uint32 field_length; // Length of field
uint16 flags;
@@ -56,9 +62,9 @@ public:
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg);
virtual ~Field() {}
- virtual void store(const char *to,uint length)=0;
- virtual void store(double nr)=0;
- virtual void store(longlong nr)=0;
+ virtual int store(const char *to,uint length,CHARSET_INFO *cs)=0;
+ virtual int store(double nr)=0;
+ virtual int store(longlong nr)=0;
virtual void store_time(TIME *ltime,timestamp_type t_type);
virtual double val_real(void)=0;
virtual longlong val_int(void)=0;
@@ -72,10 +78,11 @@ public:
virtual void reset_fields() {}
virtual void set_default()
{
- memcpy(ptr, ptr + table->rec_buff_length, pack_length());
+ my_ptrdiff_t offset = table->default_values() - table->record[0];
+ memcpy(ptr, ptr + offset, pack_length());
if (null_ptr)
*null_ptr= ((*null_ptr & (uchar) ~null_bit) |
- null_ptr[table->rec_buff_length] & null_bit);
+ null_ptr[offset] & null_bit);
}
virtual bool binary() const { return 1; }
virtual bool zero_pack() const { return 1; }
@@ -122,10 +129,14 @@ public:
Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
if (tmp)
{
- tmp->table=new_table;
- tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
+ tmp->table= new_table;
+ tmp->key_start= tmp->part_of_key= tmp->part_of_sortkey= 0;
tmp->unireg_check=Field::NONE;
- tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
+ ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+#ifdef PROBABLY_WRONG
+ tmp->table_name= new_table->table_name;
+#endif
tmp->reset_fields();
}
return tmp;
@@ -141,21 +152,16 @@ public:
if (null_ptr)
null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*);
}
- inline void get_image(char *buff,uint length)
+ inline void get_image(char *buff,uint length, CHARSET_INFO *cs)
{ memcpy(buff,ptr,length); }
- inline void set_image(char *buff,uint length)
+ inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
{ memcpy(ptr,buff,length); }
- virtual void get_key_image(char *buff,uint length)
- { get_image(buff,length); }
- virtual void set_key_image(char *buff,uint length)
- { set_image(buff,length); }
+ virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type)
+ { get_image(buff,length,cs); }
+ virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+ { set_image(buff,length,cs); }
inline int cmp_image(char *buff,uint length)
- {
- if (binary())
- return memcmp(ptr,buff,length);
- else
- return my_casecmp(ptr,buff,length);
- }
+ { return memcmp(ptr,buff,length); }
inline longlong val_int_offset(uint row_offset)
{
ptr+=row_offset;
@@ -163,7 +169,7 @@ public:
ptr-=row_offset;
return tmp;
}
- bool send(THD *thd, String *packet);
+ virtual bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
uint32 length=pack_length();
@@ -199,6 +205,8 @@ public:
uint fill_cache_field(struct st_cache_field *copy);
virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime);
+ virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
+ virtual void set_charset(CHARSET_INFO *charset) { }
friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value);
@@ -246,19 +254,37 @@ public:
class Field_str :public Field {
+protected:
+ CHARSET_INFO *field_charset;
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg,CHARSET_INFO *charset)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg)
- {}
+ {
+ field_charset=charset;
+ if (binary())
+ flags|=BINARY_FLAG;
+ }
Item_result result_type () const { return STRING_RESULT; }
+ void add_binary_or_charset(String &res) const;
uint decimals() const { return NOT_FIXED_DEC; }
- friend class create_field;
void make_field(Send_field *);
uint size_of() const { return sizeof(*this); }
+ CHARSET_INFO *charset(void) const { return field_charset; }
+
+ void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
+ bool binary() const { return field_charset->state & MY_CS_BINSORT ? 1 : 0; }
+ inline int cmp_image(char *buff,uint length)
+ {
+ if (binary())
+ return memcmp(ptr,buff,length);
+ else
+ return my_strncasecmp(field_charset,ptr,buff,length);
+ }
+ friend class create_field;
};
@@ -275,11 +301,11 @@ public:
{}
enum_field_types type() const { return FIELD_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
- { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
+ { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
void reset(void);
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -306,13 +332,14 @@ public:
enum_field_types type() const { return FIELD_TYPE_TINY;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; }
@@ -335,13 +362,14 @@ public:
enum_field_types type() const { return FIELD_TYPE_SHORT;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; }
@@ -364,13 +392,14 @@ public:
enum_field_types type() const { return FIELD_TYPE_INT24;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
@@ -398,12 +427,13 @@ public:
enum_field_types type() const { return FIELD_TYPE_LONG;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
+ bool send_binary(Protocol *protocol);
String *val_str(String*,String *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
@@ -434,13 +464,14 @@ public:
enum_field_types type() const { return FIELD_TYPE_LONGLONG;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
@@ -462,13 +493,14 @@ public:
{}
enum_field_types type() const { return FIELD_TYPE_FLOAT;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { bzero(ptr,sizeof(float)); }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); }
@@ -494,13 +526,14 @@ public:
{}
enum_field_types type() const { return FIELD_TYPE_DOUBLE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { bzero(ptr,sizeof(double)); }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(double); }
@@ -515,14 +548,14 @@ class Field_null :public Field_str {
public:
Field_null(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, len_arg, null, 1,
- unireg_check_arg, field_name_arg, table_arg)
+ unireg_check_arg, field_name_arg, table_arg, cs)
{}
enum_field_types type() const { return FIELD_TYPE_NULL;}
- void store(const char *to, uint length) { null[0]=1; }
- void store(double nr) { null[0]=1; }
- void store(longlong nr) { null[0]=1; }
+ int store(const char *to, uint length, CHARSET_INFO *cs) { null[0]=1; return 0; }
+ int store(double nr) { null[0]=1; return 0; }
+ int store(longlong nr) { null[0]=1; return 0; }
void reset(void) {}
double val_real(void) { return 0.0;}
longlong val_int(void) { return 0;}
@@ -531,26 +564,28 @@ public:
int cmp(const char *a, const char *b) { return 0;}
void sort_string(char *buff, uint length) {}
uint32 pack_length() const { return 0; }
- void sql_type(String &str) const { str.set("null",4); }
+ void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); }
};
-class Field_timestamp :public Field_num {
+class Field_timestamp :public Field_str {
public:
Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg);
- enum Item_result result_type () const { return field_length == 8 || field_length == 14 ? INT_RESULT : STRING_RESULT; }
+ struct st_table *table_arg,
+ CHARSET_INFO *cs);
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ enum Item_result cmp_type () const { return INT_RESULT; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
@@ -572,7 +607,6 @@ public:
longget(tmp,ptr);
return tmp;
}
- void fill_and_store(char *from,uint len);
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
};
@@ -588,12 +622,13 @@ public:
unireg_check_arg, field_name_arg, table_arg, 1, 1)
{}
enum_field_types type() const { return FIELD_TYPE_YEAR;}
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
void sql_type(String &str) const;
};
@@ -602,24 +637,25 @@ class Field_date :public Field_str {
public:
Field_date(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg)
+ unireg_check_arg, field_name_arg, table_arg, cs)
{}
Field_date(bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,10, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg) {}
+ NONE, field_name_arg, table_arg, cs) {}
enum_field_types type() const { return FIELD_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
enum Item_result cmp_type () const { return INT_RESULT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
@@ -632,22 +668,23 @@ class Field_newdate :public Field_str {
public:
Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg)
+ unireg_check_arg, field_name_arg, table_arg, cs)
{}
enum_field_types type() const { return FIELD_TYPE_DATE;}
enum_field_types real_type() const { return FIELD_TYPE_NEWDATE; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
enum Item_result cmp_type () const { return INT_RESULT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void store_time(TIME *ltime,timestamp_type type);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
@@ -663,24 +700,25 @@ class Field_time :public Field_str {
public:
Field_time(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, 8, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg)
+ unireg_check_arg, field_name_arg, table_arg, cs)
{}
Field_time(bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,8, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg) {}
+ NONE, field_name_arg, table_arg, cs) {}
enum_field_types type() const { return FIELD_TYPE_TIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
enum Item_result cmp_type () const { return INT_RESULT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
bool get_time(TIME *ltime);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
@@ -695,27 +733,28 @@ class Field_datetime :public Field_str {
public:
Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg)
+ unireg_check_arg, field_name_arg, table_arg, cs)
{}
Field_datetime(bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,19, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg) {}
+ NONE, field_name_arg, table_arg, cs) {}
enum_field_types type() const { return FIELD_TYPE_DATETIME;}
#ifdef HAVE_LONG_LONG
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
#endif
enum Item_result cmp_type () const { return INT_RESULT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void store_time(TIME *ltime,timestamp_type type);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
@@ -728,28 +767,17 @@ public:
class Field_string :public Field_str {
- bool binary_flag;
public:
Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg,bool binary_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg),
- binary_flag(binary_arg)
- {
- if (binary_arg)
- flags|=BINARY_FLAG;
- }
+ unireg_check_arg, field_name_arg, table_arg,cs) {};
Field_string(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, bool binary_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg),
- binary_flag(binary_arg)
- {
- if (binary_arg)
- flags|=BINARY_FLAG;
- }
+ NONE, field_name_arg, table_arg, cs) {};
enum_field_types type() const
{
@@ -758,13 +786,12 @@ public:
FIELD_TYPE_VAR_STRING : FIELD_TYPE_STRING);
}
enum ha_base_keytype key_type() const
- { return binary_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
+ { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
bool zero_pack() const { return 0; }
- bool binary() const { return binary_flag; }
- void reset(void) { bfill(ptr,field_length,' '); }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ void reset(void) { charset()->fill(charset(),ptr,field_length,' '); }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -783,45 +810,35 @@ public:
class Field_varstring :public Field_str {
- bool binary_flag;
public:
Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg,bool binary_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg),
- binary_flag(binary_arg)
- {
- if (binary_arg)
- flags|=BINARY_FLAG;
- }
+ unireg_check_arg, field_name_arg, table_arg, cs) {};
Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, bool binary_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg),
- binary_flag(binary_arg)
- {
- if (binary_arg)
- flags|=BINARY_FLAG;
- }
+ NONE, field_name_arg, table_arg, cs) {};
enum_field_types type() const { return FIELD_TYPE_VAR_STRING; }
enum ha_base_keytype key_type() const
- { return binary_flag ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
+ { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
bool zero_pack() const { return 0; }
- bool binary() const { return binary_flag; }
void reset(void) { bzero(ptr,field_length+2); }
uint32 pack_length() const { return (uint32) field_length+2; }
uint32 key_length() const { return (uint32) field_length; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
+ void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
+ void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
@@ -837,28 +854,26 @@ public:
class Field_blob :public Field_str {
uint packlength;
String value; // For temporaries
- bool binary_flag;
+ bool geom_flag;
public:
Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
- bool binary_arg);
+ CHARSET_INFO *cs);
Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, bool binary_arg)
+ struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg),
- packlength(3),binary_flag(binary_arg)
+ NONE, field_name_arg, table_arg, cs),
+ packlength(3), geom_flag(true)
{
flags|= BLOB_FLAG;
- if (binary_arg)
- flags|=BINARY_FLAG;
}
enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const
- { return binary_flag ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -879,7 +894,6 @@ public:
inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); }
uint32 get_length(const char *ptr);
- bool binary() const { return binary_flag; }
inline void get_ptr(char **str)
{
memcpy_fixed(str,ptr+packlength,sizeof(char*));
@@ -894,13 +908,13 @@ public:
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
- void get_key_image(char *buff,uint length);
- void set_key_image(char *buff,uint length);
+ void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
+ void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
void sql_type(String &str) const;
inline bool copy()
{ char *tmp;
get_ptr(&tmp);
- if (value.copy(tmp,get_length()))
+ if (value.copy(tmp,get_length(),charset()))
{
Field_blob::reset();
return 1;
@@ -923,6 +937,26 @@ public:
};
+class Field_geom :public Field_blob {
+public:
+ Field_geom(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ struct st_table *table_arg,uint blob_pack_length)
+ :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ field_name_arg, table_arg, blob_pack_length,&my_charset_bin) {}
+ Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg)
+ :Field_blob(len_arg, maybe_null_arg, field_name_arg,
+ table_arg, &my_charset_bin) {}
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
+ enum_field_types type() const { return FIELD_TYPE_GEOMETRY;}
+ void sql_type(String &str) const;
+
+ void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
+ void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+};
+
+
class Field_enum :public Field_str {
protected:
uint packlength;
@@ -932,9 +966,10 @@ public:
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint packlength_arg,
- TYPELIB *typelib_arg)
+ TYPELIB *typelib_arg,
+ CHARSET_INFO *charset_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg),
+ unireg_check_arg, field_name_arg, table_arg, charset_arg),
packlength(packlength_arg),typelib(typelib_arg)
{
flags|=ENUM_FLAG;
@@ -942,9 +977,9 @@ public:
enum_field_types type() const { return FIELD_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum ha_base_keytype key_type() const;
- void store(const char *to,uint length);
- void store(double nr);
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr);
void reset() { bzero(ptr,packlength); }
double val_real(void);
longlong val_int(void);
@@ -958,7 +993,6 @@ public:
enum_field_types real_type() const { return FIELD_TYPE_ENUM; }
virtual bool zero_pack() const { return 0; }
bool optimize_range(uint idx) { return 0; }
- bool binary() const { return 0; }
bool eq_def(Field *field);
};
@@ -969,17 +1003,17 @@ public:
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint32 packlength_arg,
- TYPELIB *typelib_arg)
+ TYPELIB *typelib_arg, CHARSET_INFO *charset_arg)
:Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
table_arg, packlength_arg,
- typelib_arg)
+ typelib_arg,charset_arg)
{
flags=(flags & ~ENUM_FLAG) | SET_FLAG;
}
- void store(const char *to,uint length);
- void store(double nr) { Field_set::store((longlong) nr); }
- void store(longlong nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr) { return Field_set::store((longlong) nr); }
+ int store(longlong nr);
virtual bool zero_pack() const { return 1; }
String *val_str(String*,String *);
void sql_type(String &str) const;
@@ -996,12 +1030,14 @@ public:
const char *field_name;
const char *change; // If done with alter table
const char *after; // Put column after this one
+ LEX_STRING comment; // Comment for field
Item *def; // Default value
enum enum_field_types sql_type;
uint32 length;
uint decimals,flags,pack_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
+ CHARSET_INFO *charset;
Field *field; // For alter table
uint8 row,col,sc_length,interval_id; // For rea_create_table
@@ -1017,8 +1053,11 @@ public:
class Send_field {
public:
- const char *table_name,*col_name;
- uint length,flags,decimals;
+ const char *db_name;
+ const char *table_name,*org_table_name;
+ const char *col_name,*org_col_name;
+ ulong length;
+ uint charsetnr, flags, decimals;
enum_field_types type;
Send_field() {}
};
@@ -1050,8 +1089,8 @@ public:
Field *make_field(char *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
- uint pack_flag,
- enum_field_types field_type,
+ uint pack_flag, enum_field_types field_type,
+ CHARSET_INFO *cs,
Field::utype unireg_check,
TYPELIB *interval, const char *field_name,
struct st_table *table);
@@ -1060,8 +1099,10 @@ uint32 calc_pack_length(enum_field_types type,uint32 length);
bool set_field_to_null(Field *field);
bool set_field_to_null_with_conversions(Field *field, bool no_conversions);
uint find_enum(TYPELIB *typelib,const char *x, uint length);
-ulonglong find_set(TYPELIB *typelib,const char *x, uint length);
-bool test_if_int(const char *str,int length);
+ulonglong find_set(TYPELIB *typelib,const char *x, uint length,
+ char **err_pos, uint *err_len);
+bool test_if_int(const char *str, int length, const char *int_end,
+ CHARSET_INFO *cs);
/*
The following are for the interface with the .frm file
@@ -1076,6 +1117,7 @@ bool test_if_int(const char *str,int length);
#define FIELDFLAG_BITFIELD 512 // mangled with dec!
#define FIELDFLAG_BLOB 1024 // mangled with dec!
#define FIELDFLAG_GEOM 2048
+
#define FIELDFLAG_LEFT_FULLSCREEN 8192
#define FIELDFLAG_RIGHT_FULLSCREEN 16384
#define FIELDFLAG_FORMAT_NUMBER 16384 // predit: ###,,## in output
@@ -1098,7 +1140,6 @@ bool test_if_int(const char *str,int length);
#define f_packtype(x) (((x) >> FIELDFLAG_PACK_SHIFT) & 15)
#define f_decimals(x) ((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC))
#define f_is_alpha(x) (!f_is_num(x))
-#define f_is_binary(x) ((x) & FIELDFLAG_BINARY)
#define f_is_enum(x) ((x) & FIELDFLAG_INTERVAL)
#define f_is_bitfield(x) ((x) & FIELDFLAG_BITFIELD)
#define f_is_blob(x) (((x) & (FIELDFLAG_BLOB | FIELDFLAG_NUMBER)) == FIELDFLAG_BLOB)
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 42272dd616f..47996606638 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -272,7 +272,8 @@ static void do_conv_blob(Copy_field *copy)
{
copy->from_field->val_str(&copy->tmp,&copy->tmp);
((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
- copy->tmp.length());
+ copy->tmp.length(),
+ copy->tmp.charset());
}
/* Save blob in copy->tmp for GROUP BY */
@@ -280,20 +281,21 @@ static void do_conv_blob(Copy_field *copy)
static void do_save_blob(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
- String res(buff,sizeof(buff));
+ String res(buff,sizeof(buff),copy->tmp.charset());
copy->from_field->val_str(&res,&res);
copy->tmp.copy(res);
((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
- copy->tmp.length());
+ copy->tmp.length(),
+ copy->tmp.charset());
}
static void do_field_string(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
- copy->tmp.set_quick(buff,sizeof(buff));
+ copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
copy->from_field->val_str(&copy->tmp,&copy->tmp);
- copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length());
+ copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),copy->tmp.charset());
}
@@ -320,7 +322,7 @@ static void do_cut_string(Copy_field *copy)
ptr != end ;
ptr++)
{
- if (!isspace(*ptr))
+ if (!my_isspace(system_charset_info, *ptr)) // QQ: ucs incompatible
{
current_thd->cuted_fields++; // Give a warning
break;
@@ -552,7 +554,7 @@ void field_conv(Field *to,Field *from)
if (!blob->value.is_alloced() &&
from->real_type() != FIELD_TYPE_STRING)
blob->value.copy();
- blob->store(blob->value.ptr(),blob->value.length());
+ blob->store(blob->value.ptr(),blob->value.length(),to->charset());
return;
}
if ((from->result_type() == STRING_RESULT &&
@@ -562,9 +564,10 @@ void field_conv(Field *to,Field *from)
to->type() == FIELD_TYPE_DECIMAL)
{
char buff[MAX_FIELD_WIDTH];
- String result(buff,sizeof(buff));
+ String result(buff,sizeof(buff),from->charset());
from->val_str(&result,&result);
- to->store(result.c_ptr_quick(),result.length());
+ to->store(result.c_ptr_quick(),result.length(),to->charset());
+ // QQ: what to do if "from" and "to" are of dirrent charsets?
}
else if (from->result_type() == REAL_RESULT)
to->store(from->val_real());
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 2ac05ef0496..fcee26278d1 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -49,7 +49,8 @@ static int merge_index(SORTPARAM *param,uchar *sort_buffer,
uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
-static uint sortlength(SORT_FIELD *sortorder,uint length);
+static uint sortlength(SORT_FIELD *sortorder, uint s_length,
+ bool *multi_byte_charset);
/*
Creates a set of pointers that can be used to read the rows
@@ -63,22 +64,21 @@ static uint sortlength(SORT_FIELD *sortorder,uint length);
table->record_pointers
*/
-ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
- SQL_SELECT *select, ha_rows special, ha_rows max_rows,
- ha_rows *examined_rows)
+ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
+ SQL_SELECT *select, ha_rows max_rows, ha_rows *examined_rows)
{
int error;
ulong memavl;
uint maxbuffer;
+ uint i;
BUFFPEK *buffpek;
ha_rows records;
uchar **sort_keys;
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
SORTPARAM param;
- THD *thd= current_thd;
-
+ bool multi_byte_charset;
DBUG_ENTER("filesort");
- DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length,special););
+ DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length););
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */
#endif
@@ -91,7 +91,8 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
error= 1;
bzero((char*) &param,sizeof(param));
param.ref_length= table->file->ref_length;
- param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
+ param.sort_length= (sortlength(sortorder,s_length, &multi_byte_charset)+
+ param.ref_length);
param.max_rows= max_rows;
if (select && select->quick)
@@ -102,27 +103,15 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
{
statistic_increment(filesort_scan_count, &LOCK_status);
}
- if (select && my_b_inited(&select->file))
- {
- records=special=select->records; /* purecov: deadcode */
- selected_records_file= &select->file; /* purecov: deadcode */
- reinit_io_cache(selected_records_file,READ_CACHE,0L,0,0); /* purecov: deadcode */
- }
- else if (special)
- {
- records=special; /* purecov: deadcode */
- selected_records_file= outfile; /* purecov: deadcode */
- reinit_io_cache(selected_records_file,READ_CACHE,0L,0,0); /* purecov: deadcode */
- }
#ifdef CAN_TRUST_RANGE
- else if (select && select->quick && select->quick->records > 0L)
+ if (select && select->quick && select->quick->records > 0L)
{
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
table->file->records)+EXTRA_RECORDS;
selected_records_file=0;
}
-#endif
else
+#endif
{
records=table->file->estimate_number_of_rows();
selected_records_file= 0;
@@ -130,11 +119,9 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (param.sort_length == param.ref_length && records > param.max_rows)
records=param.max_rows; /* purecov: inspected */
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info) &&
+ if (multi_byte_charset &&
!(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME))))
goto err;
-#endif
memavl= thd->variables.sortbuff_size;
while (memavl >= MIN_SORT_MEMORY)
@@ -207,10 +194,8 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
error =0;
err:
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
+ if (param.tmp_buffer)
x_free(param.tmp_buffer);
-#endif
x_free((gptr) sort_keys);
x_free((gptr) buffpek);
close_cached_file(&tempfile);
@@ -479,10 +464,11 @@ static void make_sortkey(register SORTPARAM *param,
switch (sort_field->result_type) {
case STRING_RESULT:
{
+ CHARSET_INFO *cs=item->charset();
if (item->maybe_null)
*to++=1;
/* All item->str() to use some extra byte for end null.. */
- String tmp((char*) to,sort_field->length+4);
+ String tmp((char*) to,sort_field->length+4,cs);
String *res=item->val_str(&tmp);
if (!res)
{
@@ -503,43 +489,28 @@ static void make_sortkey(register SORTPARAM *param,
diff=0; /* purecov: inspected */
length=sort_field->length;
}
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
+ if (sort_field->need_strxnfrm)
{
- if (item->binary)
- {
- if (res->ptr() != (char*) to)
- memcpy(to,res->ptr(),length);
- bzero((char*) to+length,diff);
- }
- else
- {
- char *from=(char*) res->ptr();
- if ((unsigned char *)from == to)
- {
- set_if_smaller(length,sort_field->length);
- memcpy(param->tmp_buffer,from,length);
- from=param->tmp_buffer;
- }
- uint tmp_length=my_strnxfrm(default_charset_info,
- to,(unsigned char *) from,
- sort_field->length,
- length);
- if (tmp_length < sort_field->length)
- bzero((char*) to+tmp_length,sort_field->length-tmp_length);
- }
+ char *from=(char*) res->ptr();
+ if ((unsigned char *)from == to)
+ {
+ set_if_smaller(length,sort_field->length);
+ memcpy(param->tmp_buffer,from,length);
+ from=param->tmp_buffer;
+ }
+ uint tmp_length=my_strnxfrm(cs,to,sort_field->length,
+ (unsigned char *) from, length);
+ if (tmp_length < sort_field->length)
+ bzero((char*) to+tmp_length,sort_field->length-tmp_length);
}
else
{
-#endif
if (res->ptr() != (char*) to)
memcpy(to,res->ptr(),length);
bzero((char *)to+length,diff);
- if (!item->binary)
- case_sort((char*) to,length);
-#ifdef USE_STRCOLL
+ if (!item->binary())
+ my_tosort(cs, (char*) to,length);
}
-#endif
break;
}
case INT_RESULT:
@@ -590,6 +561,10 @@ static void make_sortkey(register SORTPARAM *param,
change_double_for_sort(value,(byte*) to);
break;
}
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
}
}
if (sort_field->reverse)
@@ -919,17 +894,36 @@ static int merge_index(SORTPARAM *param, uchar *sort_buffer,
} /* merge_index */
- /* Calculate length of sort key */
+/*
+ Calculate length of sort key
+
+ SYNOPSIS
+ sortlength()
+ sortorder Order of items to sort
+ uint s_length Number of items to sort
+ multi_byte_charset (out)
+ Set to 1 if we are using multi-byte charset
+ (In which case we have to use strxnfrm())
+
+ NOTES
+ sortorder->length is updated for each sort item
+ sortorder->need_strxnfrm is set 1 if we have to use strxnfrm
+
+ RETURN
+ Total length of sort buffer in bytes
+*/
static uint
-sortlength(SORT_FIELD *sortorder, uint s_length)
+sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
{
reg2 uint length;
THD *thd= current_thd;
+ *multi_byte_charset= 0;
length=0;
for (; s_length-- ; sortorder++)
{
+ sortorder->need_strxnfrm= 0;
if (sortorder->field)
{
if (sortorder->field->type() == FIELD_TYPE_BLOB)
@@ -937,10 +931,16 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
else
{
sortorder->length=sortorder->field->pack_length();
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info) && !sortorder->field->binary())
- sortorder->length= sortorder->length*MY_STRXFRM_MULTIPLY;
-#endif
+ if (!sortorder->field->binary())
+ {
+ CHARSET_INFO *cs=sortorder->field->charset();
+ if (use_strnxfrm(cs))
+ {
+ sortorder->need_strxnfrm= 1;
+ *multi_byte_charset= 1;
+ sortorder->length= sortorder->length*cs->strxfrm_multiply;
+ }
+ }
}
if (sortorder->field->maybe_null())
length++; // Place for NULL marker
@@ -950,10 +950,16 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
switch ((sortorder->result_type=sortorder->item->result_type())) {
case STRING_RESULT:
sortorder->length=sortorder->item->max_length;
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info) && !sortorder->item->binary)
- sortorder->length= sortorder->length*MY_STRXFRM_MULTIPLY;
-#endif
+ if (!sortorder->item->binary())
+ {
+ CHARSET_INFO *cs=sortorder->item->charset();
+ if (use_strnxfrm(cs))
+ {
+ sortorder->length= sortorder->length*cs->strxfrm_multiply;
+ sortorder->need_strxnfrm= 1;
+ *multi_byte_charset= 1;
+ }
+ }
break;
case INT_RESULT:
#if SIZEOF_LONG_LONG > 4
@@ -965,6 +971,10 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
case REAL_RESULT:
sortorder->length=sizeof(double);
break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
}
if (sortorder->item->maybe_null)
length++; // Place for NULL marker
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 8139cf4fdb0..7ae28e0ce77 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -14,11 +14,68 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+
+The idea of presented algorithm see in
+"The Art of Computer Programming" by Donald E. Knuth
+Volume 3 "Sorting and searching"
+(chapter 6.3 "Digital searching" - name and number of chapter
+ is back translation from Russian edition :))
+
+as illustration of data structures, imagine next table:
+
+static SYMBOL symbols[] = {
+ { "ADD", SYM(ADD),0,0},
+ { "AND", SYM(AND),0,0},
+ { "DAY", SYM(DAY_SYM),0,0},
+};
+
+for this structure, presented program generate next searching-structure:
+
++-----------+-+-+-+
+| len |1|2|3|
++-----------+-+-+-+
+|first_char |0|0|a|
+|last_char |0|0|d|
+|link |0|0|+|
+ |
+ V
+ +----------+-+-+-+--+
+ | 1 char|a|b|c|d |
+ +----------+-+-+-+--+
+ |first_char|b|0|0|0 |
+ |last_char |n|0|0|-1|
+ |link |+|0|0|+ |
+ | |
+ | V
+ | symbols[2] ( "DAY" )
+ V
++----------+--+-+-+-+-+-+-+-+-+-+--+
+| 2 char|d |e|f|j|h|i|j|k|l|m|n |
++----------+--+-+-+-+-+-+-+-+-+-+--+
+|first_char|0 |0|0|0|0|0|0|0|0|0|0 |
+|last_char |-1|0|0|0|0|0|0|0|0|0|-1|
+|link |+ |0|0|0|0|0|0|0|0|0|+ |
+ | |
+ V V
+ symbols[0] ( "ADD" ) symbols[1] ( "AND" )
+
+for optimization, link is the 16-bit index in 'symbols' or 'sql_functions'
+or search-array..
+
+So, we can read full search-structure as 32-bit word
+
+TODO:
+1. use instead to_upper_lex, special array
+ (substitute chars) without skip codes..
+2. try use reverse order of comparing..
+
+*/
#define NO_YACC_SYMBOLS
-#include <my_global.h>
-#include <my_sys.h>
-#include <m_string.h>
+#include "my_global.h"
+#include "my_sys.h"
+#include "m_string.h"
#ifndef __GNU_LIBRARY__
#define __GNU_LIBRARY__ // Skip warnings in getopt.h
#endif
@@ -26,324 +83,230 @@
#include "mysql_version.h"
#include "lex.h"
-my_bool opt_search;
-int opt_verbose;
-ulong opt_count;
-
-#define max_allowed_array 8000 // Don't generate bigger arrays than this
-#define max_symbol 32767 // Use this for 'not found'
-#define how_much_for_plus 8 // 2-8
-#define type_count 1 // 1-5
-#define char_table_count 5
-#define total_symbols (sizeof(symbols)/sizeof(SYMBOL) +\
- sizeof(sql_functions)/sizeof(SYMBOL))
-
-#define how_much_and INT_MAX24
-
-/*
- The following only have to work with characters in the set
- used by SQL commands
-*/
-
-#undef tolower
-#define tolower(a) ((a) >= 'A' && (a) <= 'Z') ? ((a)- 'A' + 'a') : (a)
-
-static uint how_long_symbols,function_plus,function_mod,function_type;
-static uint char_table[256];
-static uchar unique_length[256];
-static uchar bits[how_much_and/8+1];
-static uint primes[max_allowed_array+1];
-static ulong hash_results[type_count][how_much_for_plus+1][total_symbols];
-static ulong start_value=0;
-static uint best_type;
-static ulong best_t1,best_t2, best_start_value;
-
static struct my_option my_long_options[] =
{
{"help", '?', "Display help and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"count", 'c', "Try count times to find a optimal hash table",
- (gptr*) &opt_count, (gptr*) &opt_count, 0, GET_ULONG, REQUIRED_ARG,
- 100000, 0, 0, 0, 0, 0},
- {"search", 'S', "Search after good rnd1 and rnd2 values",
- (gptr*) &opt_search, (gptr*) &opt_search, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
- 0, 0},
- {"verbose", 'v', "Write some information while the program executes",
- (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, GET_INT, NO_ARG, 0, 0, 0,
- 0, 0, 0},
{"version", 'V', "Output version information and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-struct rand_struct {
- unsigned long seed1,seed2,max_value;
- double max_value_dbl;
+struct hash_lex_struct
+{
+ char first_char;
+ char last_char;
+ union{
+ hash_lex_struct *char_tails;
+ int iresult;
+ };
+ int ithis;
};
-
-void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
-{ /* For mysql 3.21.# */
- rand_st->max_value= 0x3FFFFFFFL;
- rand_st->max_value_dbl=(double) rand_st->max_value;
- rand_st->seed1=seed1%rand_st->max_value ;
- rand_st->seed2=seed2%rand_st->max_value;
-}
-
-double rnd(struct rand_struct *rand_st)
+
+hash_lex_struct *get_hash_struct_by_len(hash_lex_struct **root_by_len,
+ int len, int *max_len)
{
- rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
- rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
- return (((double) rand_st->seed1)/rand_st->max_value_dbl);
+ if (*max_len<len){
+ *root_by_len= (hash_lex_struct *)realloc((char*)*root_by_len,
+ sizeof(hash_lex_struct)*len);
+ hash_lex_struct *cur, *end= *root_by_len + len;
+ for (cur= *root_by_len + *max_len; cur<end; cur++)
+ cur->first_char= 0;
+ *max_len= len;
+ }
+ return (*root_by_len)+(len-1);
}
-
-static void make_char_table(ulong t1,ulong t2,int type)
+void insert_into_hash(hash_lex_struct *root, const char *name,
+ int len_from_begin, int index, int function)
{
- uint i;
- struct rand_struct rand_st;
- randominit(&rand_st,t1,t2);
+ hash_lex_struct *end, *cur, *tails;
- for (i=0 ; i < 256 ; i++)
- {
- switch (type) {
- case 0: char_table[i]= i + (i << 8); break;
- case 1: char_table[i]= i + ((i ^255 ) << 8); break;
- case 2: char_table[i]= i; break;
- case 3: char_table[i]= i + ((uint) (rnd(&rand_st)*255) << 8); break;
- case 4: char_table[i]= (uint) (rnd(&rand_st)*255) + (i << 8); break;
- }
+ if (!root->first_char){
+ root->first_char= -1;
+ root->iresult= index;
+ return;
}
- char_table[0]|=1+257; // Avoid problems with 0
- for (i=0 ; i < 256 ; i++)
- {
- uint tmp=(uint) (rnd(&rand_st)*255);
- swap(uint,char_table[i],char_table[tmp]);
+
+ if (root->first_char==-1){
+ int index2= root->iresult;
+ const char *name2=
+ (index2<0 ? sql_functions[-index2-1] : symbols[index2]).name + len_from_begin;
+ root->first_char= name2[0];
+ root->last_char= root->first_char;
+ tails= (hash_lex_struct*)malloc(sizeof(hash_lex_struct));
+ root->char_tails= tails;
+ tails->first_char= -1;
+ tails->iresult= index2;
}
- /* lower characters should be mapped to upper */
- for (i= 'a' ; i <= 'z' ; i++)
- {
- /* This loop is coded with extra variables to avoid a bug in gcc 2.96 */
- uchar tmp= (uchar) (i - 'a'); // Assume ascii
- tmp+='A';
- char_table[i]=char_table[tmp];
+
+ size_t real_size= (root->last_char-root->first_char+1);
+
+ if (root->first_char>(*name)){
+ size_t new_size= root->last_char-(*name)+1;
+ if (new_size<real_size) printf("error!!!!\n");
+ tails= root->char_tails;
+ tails= (hash_lex_struct*)realloc((char*)tails,
+ sizeof(hash_lex_struct)*new_size);
+ root->char_tails= tails;
+ memmove(tails+(new_size-real_size),tails,real_size*sizeof(hash_lex_struct));
+ end= tails + new_size - real_size;
+ for (cur= tails; cur<end; cur++)
+ cur->first_char= 0;
+ root->first_char= (*name);
}
-}
-/* Fill array primes with primes between start and 'max_allowed_array' */
+ if (root->last_char<(*name)){
+ size_t new_size= (*name)-root->first_char+1;
+ if (new_size<real_size) printf("error!!!!\n");
+ tails= root->char_tails;
+ tails= (hash_lex_struct*)realloc((char*)tails,
+ sizeof(hash_lex_struct)*new_size);
+ root->char_tails= tails;
+ end= tails + new_size;
+ for (cur= tails+real_size; cur<end; cur++)
+ cur->first_char= 0;
+ root->last_char= (*name);
+ }
-static void make_prime_array(uint start)
-{
- uint i,j,*to;
- uint max_index=(uint) sqrt((double) max_allowed_array);
+ insert_into_hash (root->char_tails+(*name)-root->first_char,
+ name+1,len_from_begin+1,index,function);
+}
- bzero((char*) primes,sizeof(primes[0])*max_allowed_array);
+hash_lex_struct *root_by_len= 0;
+int max_len=0;
- i=2;
- while (i < max_index)
- {
- for (j=i+i ; j <= max_allowed_array ; j+=i)
- primes[j]=1;
- while (primes[++i]) ;
- }
+hash_lex_struct *root_by_len2= 0;
+int max_len2=0;
- to=primes;
- for (i=start ; i <= max_allowed_array ; i++)
- if (!primes[i])
- *to++=i;
- *to=0; // end marker
+void insert_symbols()
+{
+ size_t i= 0;
+ SYMBOL *cur;
+ for (cur= symbols; i<array_elements(symbols); cur++, i++){
+ hash_lex_struct *root=
+ get_hash_struct_by_len(&root_by_len,cur->length,&max_len);
+ insert_into_hash(root,cur->name,0,i,0);
+ }
}
-#define USE_char_table
-
-static ulong tab_index_function(const char *s,uint add, uint type)
+void insert_sql_functions()
{
- register ulong nr=start_value+char_table[(uchar) *s]; // Nice value
- ulong pos=3;
- uint tmp_length=unique_length[(uchar) *s]-1;
- while (*++s && tmp_length-- > 0)
- {
- switch (type) {
- case 0:
- nr= (nr ^ (char_table[(uchar) *s] + (nr << add)));
- break;
- case 1:
- nr= (nr + (char_table[(uchar) *s] + (nr << add)));
- break;
- case 2:
- nr= (nr ^ (char_table[(uchar) *s] ^ (nr << add)));
- break;
- case 3:
- nr= (char_table[(uchar) *s] ^ (nr << add));
- break;
- case 4:
- nr+= nr+nr+((nr & 63)+pos)*((ulong) char_table[(uchar) *s]);
- pos+=add;
- break;
- }
+ size_t i= 0;
+ SYMBOL *cur;
+ for (cur= sql_functions; i<array_elements(sql_functions); cur++, i++){
+ hash_lex_struct *root=
+ get_hash_struct_by_len(&root_by_len,cur->length,&max_len);
+ insert_into_hash(root,cur->name,0,-i-1,1);
}
- return nr & INT_MAX24;
}
-static int search(bool write_warning)
+void calc_length()
+{
+ SYMBOL *cur, *end= symbols + array_elements(symbols);
+ for (cur= symbols; cur < end; cur++)
+ cur->length=(uchar) strlen(cur->name);
+ end= sql_functions + array_elements(sql_functions);
+ for (cur= sql_functions; cur<end; cur++)
+ cur->length=(uchar) strlen(cur->name);
+}
+
+void generate_find_structs()
{
- uint size_symbols = sizeof(symbols)/sizeof(SYMBOL);
- uint size_functions = sizeof(sql_functions)/sizeof(SYMBOL);
- uint size=size_symbols + size_functions;
- uint i=0,found,*prime,type;
- int igra[max_allowed_array],test_count=INT_MAX;
- uint possible_plus[how_much_for_plus*type_count+type_count];
+ root_by_len= 0;
+ max_len=0;
+
+ insert_symbols();
+
+ root_by_len2= root_by_len;
+ max_len2= max_len;
+
+ root_by_len= 0;
+ max_len= 0;
- how_long_symbols = sizeof(symbols)/sizeof(SYMBOL);
+ insert_symbols();
+ insert_sql_functions();
+}
- bzero((char*) possible_plus,sizeof(possible_plus));
- found=0;
+char *hash_map= 0;
+int size_hash_map= 0;
- /* Check first which function_plus are possible */
- for (type=0 ; type < type_count ; type ++)
+void add_struct_to_map(hash_lex_struct *st)
+{
+ st->ithis= size_hash_map/4;
+ size_hash_map+= 4;
+ hash_map= (char*)realloc((char*)hash_map,size_hash_map);
+ hash_map[size_hash_map-4]= st->first_char==-1 ? 0 : st->first_char;
+ hash_map[size_hash_map-3]=
+ st->first_char==-1 || st->first_char==0 ? 0 : st->last_char;
+ if (st->first_char==-1)
{
- for (function_plus = 1;
- function_plus <= how_much_for_plus;
- function_plus++)
- {
- bzero((char*) bits,sizeof(bits));
- for (i=0; i < size; i++)
- {
- ulong order= tab_index_function ((i < how_long_symbols) ?
- symbols[i].name :
- sql_functions[i-how_long_symbols].name,
- function_plus, type);
- hash_results[type][function_plus][i]=order;
- uint pos=order/8;
- uint bit=order & 7;
- if (bits[pos] & (1 << bit))
- break;
- bits[pos]|=1 << bit;
- }
- if (i == size)
- {
- possible_plus[found++]=function_plus;
- }
- }
- possible_plus[found++]=0; // End marker
+ hash_map[size_hash_map-2]= ((unsigned int)(int16)st->iresult)&255;
+ hash_map[size_hash_map-1]= ((unsigned int)(int16)st->iresult)>>8;
}
- if (found == type_count)
+ else if (st->first_char==0)
{
- if (write_warning)
- fprintf(stderr,"\
-The hash function didn't return a unique value for any parameter\n\
-You have to change gen_lex_code.cc, function 'tab_index_function' to\n\
-generate unique values for some parameter. When you have succeeded in this,\n\
-you have to change 'main' to print out the new function\n");
- return(1);
+ hash_map[size_hash_map-2]= ((unsigned int)(int16)array_elements(symbols))&255;
+ hash_map[size_hash_map-1]= ((unsigned int)(int16)array_elements(symbols))>>8;
}
+};
- if (opt_verbose > 1)
- fprintf (stderr,"Info: Possible add values: %d\n",found-type_count);
+void add_structs_to_map(hash_lex_struct *st, int len)
+{
+ hash_lex_struct *cur, *end= st+len;
+ for (cur= st; cur<end; cur++)
+ add_struct_to_map(cur);
+ for (cur= st; cur<end; cur++)
+ if (cur->first_char && cur->first_char!=-1)
+ add_structs_to_map(cur->char_tails,cur->last_char-cur->first_char+1);
+}
- for (prime=primes; (function_mod=*prime) ; prime++)
- {
- uint *plus_ptr=possible_plus;
- for (type=0 ; type < type_count ; type++ )
- {
- while ((function_plus= *plus_ptr++))
- {
- ulong *order_pos= &hash_results[type][function_plus][0];
- if (test_count++ == INT_MAX)
- {
- test_count=1;
- bzero((char*) igra,sizeof(igra));
- }
- for (i=0; i<size ;i++)
- {
- ulong order;
- order = *order_pos++ % function_mod;
- if (igra[order] == test_count)
- break;
- igra[order] = test_count;
- }
- if (i == size)
- {
- *prime=0; // Mark this used
- function_type=type;
- return 0; // Found ok value
- }
- }
+void set_links(hash_lex_struct *st, int len)
+{
+ hash_lex_struct *cur, *end= st+len;
+ for (cur= st; cur<end; cur++)
+ if (cur->first_char!=0 && cur->first_char!=-1){
+ int ilink= cur->char_tails->ithis;
+ hash_map[cur->ithis*4+2]= ilink%256;
+ hash_map[cur->ithis*4+3]= ilink/256;
+ set_links(cur->char_tails,cur->last_char-cur->first_char+1);
}
- }
-
- function_mod=max_allowed_array;
- if (write_warning)
- fprintf (stderr,"Fatal error when generating hash for symbols\n\
-Didn't find suitable values for perfect hashing:\n\
-You have to edit gen_lex_hash.cc to generate a new hashing function.\n\
-You can try running gen_lex_hash with --search to find a suitable value\n\
-Symbol array size = %d\n",function_mod);
- return -1;
}
-
-void print_arrays()
+void print_hash_map(const char *name)
{
- uint size_symbols = sizeof(symbols)/sizeof(SYMBOL);
- uint size_functions = sizeof(sql_functions)/sizeof(SYMBOL);
- uint size=size_symbols + size_functions;
- uint i;
-
- fprintf(stderr,"Symbols: %d Functions: %d; Total: %d\nShifts per char: %d, Array size: %d\n",
- size_symbols,size_functions,size_symbols+size_functions,
- function_plus,function_mod);
-
- int *prva= (int*) my_alloca(sizeof(int)*function_mod);
- for (i=0 ; i <= function_mod; i++)
- prva[i]= max_symbol;
-
- for (i=0;i<size;i++)
- {
- const char *name= ((i < how_long_symbols) ?
- symbols[i].name :
- sql_functions[i - how_long_symbols].name);
- ulong order = tab_index_function(name,function_plus,function_type);
- order %= function_mod;
- /* This should never be true */
- if (prva[order] != max_symbol)
- {
- fprintf(stderr,"Error: Got duplicate value for symbol '%s'\n",name);
- exit(1);
+ printf("uchar %s[%d]= {\n",name,size_hash_map);
+ char *cur;
+ int i;
+ for (i=0, cur= hash_map; i<size_hash_map; i++, cur++){
+ switch(i%4){
+ case 0: case 1:
+ if (!*cur)
+ printf("0, ");
+ else
+ printf("\'%c\', ",*cur);
+ break;
+ case 2: printf("%u, ",(uint)(uchar)*cur); break;
+ case 3: printf("%u,\n",(uint)(uchar)*cur); break;
}
- prva [order] = i;
}
+ printf("};\n");
+}
-#ifdef USE_char_table
- printf("static uint16 char_table[] = {\n");
- for (i=0; i < 255 ;i++) // < 255 is correct
- {
- printf("%u,",char_table[i]);
- if (((i+1) & 15) == 0)
- puts("");
- }
- printf("%d\n};\n\n\n",char_table[i]);
-#endif
+void print_find_structs()
+{
+ add_structs_to_map(root_by_len,max_len);
+ set_links(root_by_len,max_len);
+ print_hash_map("sql_functions_map");
- printf("static uchar unique_length[] = {\n");
- for (i=0; i < 255 ;i++) // < 255 is correct
- {
- printf("%u,",unique_length[i]);
- if (((i+1) & 15) == 0)
- puts("");
- }
- printf("%d\n};\n\n\n",unique_length[i]);
+ hash_map= 0;
+ size_hash_map= 0;
- printf("static uint16 my_function_table[] = {\n");
- for (i=0; i < function_mod-1 ;i++)
- {
- printf("%d,",prva[i]);
- if (((i+1) % 12) == 0)
- puts("");
- }
- printf("%d\n};\n\n\n",prva[i]);
- my_afree((gptr) prva);
-}
+ printf("\n");
+ add_structs_to_map(root_by_len2,max_len2);
+ set_links(root_by_len2,max_len2);
+ print_hash_map("symbols_map");
+}
static void usage(int version)
{
@@ -351,23 +314,19 @@ static void usage(int version)
my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
if (version)
return;
- puts("Copyright (C) 2001 MySQL AB, by Sinisa and Monty");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
+ puts("Copyright (C) 2001 MySQL AB, by VVA and Monty");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
+and you are welcome to modify and redistribute it under the GPL license\n");
puts("This program generates a perfect hashing function for the sql_lex.cc");
printf("Usage: %s [OPTIONS]\n\n", my_progname);
my_print_help(my_long_options);
- my_print_variables(my_long_options);
}
-
extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument __attribute__((unused)))
{
- switch (optid) {
- case 'v':
- opt_verbose++;
- break;
+ switch(optid) {
case 'V':
usage(1);
exit(0);
@@ -379,7 +338,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
return 0;
}
-
static int get_options(int argc, char **argv)
{
int ho_error;
@@ -389,139 +347,58 @@ static int get_options(int argc, char **argv)
if (argc >= 1)
{
- fprintf(stderr,"%s: Too many arguments\n", my_progname);
usage(0);
- exit(1);
+ exit(1);
}
return(0);
}
-static uint max_prefix(const char *name)
+int check_dup_symbols(SYMBOL *s1, SYMBOL *s2)
{
- uint i;
- uint max_length=1;
- for (i=0 ; i < sizeof(symbols)/sizeof(SYMBOL) ; i++)
- {
- const char *str=symbols[i].name;
- if (str != name)
- {
- const char *str2=name;
- uint length;
- while (*str && *str == *str2)
- {
- str++;
- str2++;
- }
- length=(uint) (str2 - name)+1;
- if (length > max_length)
- max_length=length;
- }
- }
- for (i=0 ; i < sizeof(sql_functions)/sizeof(SYMBOL) ; i++)
- {
- const char *str=sql_functions[i].name;
- if (str != name)
- {
- const char *str2=name;
- uint length;
- while (*str && *str == *str2)
- {
- str++;
- str2++;
- }
- length=(uint) (str2 - name)+1;
- if (length > max_length)
- max_length=length;
- }
- }
- return max_length;
-}
+ if (s1->length!=s2->length || strncmp(s1->name,s2->name,s1->length))
+ return 0;
+ const char *err_tmpl= "\ngen_lex_hash fatal error : \
+Unfortunately gen_lex_hash can not generate a hash,\n since \
+your lex.h has duplicate definition for a symbol \"%s\"\n\n";
+ printf (err_tmpl,s1->name);
+ fprintf (stderr,err_tmpl,s1->name);
+
+ return 1;
+}
-static void make_max_length_table(void)
+int check_duplicates()
{
- uint i;
- for (i=0 ; i < sizeof(symbols)/sizeof(SYMBOL) ; i++)
- {
- uint length=max_prefix(symbols[i].name);
- if (length > unique_length[(uchar) symbols[i].name[0]])
- {
- unique_length[(uchar) symbols[i].name[0]]=length;
- unique_length[(uchar) tolower(symbols[i].name[0])]=length;
- }
- }
- for (i=0 ; i < sizeof(sql_functions)/sizeof(SYMBOL) ; i++)
+ SYMBOL *cur1, *cur2, *s_end, *f_end;
+
+ s_end= symbols + array_elements(symbols);
+ f_end= sql_functions + array_elements(sql_functions);
+
+ for (cur1= symbols; cur1<s_end; cur1++)
{
- uint length=max_prefix(sql_functions[i].name);
- if (length > unique_length[(uchar) sql_functions[i].name[0]])
- {
- unique_length[(uchar) sql_functions[i].name[0]]=length;
- unique_length[(uchar) tolower(sql_functions[i].name[0])]=length;
- }
+ for (cur2= cur1+1; cur2<s_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+ for (cur2= sql_functions; cur2<f_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
}
-}
+ for (cur1= sql_functions; cur1<f_end; cur1++)
+ for (cur2= cur1+1; cur2< f_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+
+ return 0;
+}
int main(int argc,char **argv)
{
- struct rand_struct rand_st;
- static uint best_mod,best_add,best_functype;
- int error;
-
MY_INIT(argv[0]);
- start_value=2925024L; best_t1=654916L; best_t2=1723390L; best_type=3; /* mode=4943 add=1 type: 0 */
+
if (get_options(argc,(char **) argv))
exit(1);
- make_max_length_table();
- make_char_table(best_t1,best_t2,best_type);
- make_prime_array(sizeof(symbols)/sizeof(SYMBOL) +
- sizeof(sql_functions)/sizeof(SYMBOL));
-
- if ((error=search(1)) > 0 || error && !opt_search)
- exit(1); // This should work
- best_mod=function_mod; best_add=function_plus; best_functype=function_type;
-
- if (opt_search)
- {
- time_t start_time=time((time_t*) 0);
- randominit(&rand_st,start_time,start_time/2); // Some random values
- printf("start_value=%ldL; best_t1=%ldL; best_t2=%ldL; best_type=%d; /* mode=%d add=%d type: %d */\n",
- start_value, best_t1,best_t2,best_type,best_mod,best_add,
- best_functype);
- best_start_value=start_value;
- for (uint i=1 ; i <= opt_count ; i++)
- {
- if (i % 10 == 0)
- {
- putchar('.');
- fflush(stdout);
- }
- ulong t1=(ulong) (rnd(&rand_st)*INT_MAX24);
- ulong t2=(ulong) (rnd(&rand_st)*INT_MAX24);
- uint type=(int) (rnd(&rand_st)*char_table_count);
- start_value=(ulong) (rnd(&rand_st)*INT_MAX24);
- make_char_table(t1,t2,type);
- if (!search(0))
- {
- best_mod=function_mod; best_add=function_plus;
- best_functype=function_type;
- best_t1=t1; best_t2=t2; best_type=type;
- best_start_value=start_value;
- printf("\nstart_value=%ldL; best_t1=%ldL; best_t2=%ldL; best_type=%d; /* mode=%d add=%d type: %d */\n",
- best_start_value,best_t1,best_t2,best_type,best_mod,best_add,
- best_functype);
- }
- if (opt_verbose && (i % 20000) == 0)
- printf("\nstart_value=%ldL; best_t1=%ldL; best_t2=%ldL; best_type=%d; /* mode=%d add=%d type: %d */\n",
- best_start_value,best_t1,best_t2,best_type,best_mod,best_add,
- best_functype);
- }
- }
-
- function_mod=best_mod; function_plus=best_add;
- make_char_table(best_t1,best_t2,best_type);
-
printf("/* Copyright (C) 2001 MySQL AB\n\
This program is free software; you can redistribute it and/or modify\n\
it under the terms of the GNU General Public License as published by\n\
@@ -533,38 +410,89 @@ int main(int argc,char **argv)
GNU General Public License for more details.\n\n\
You should have received a copy of the GNU General Public License\n\
along with this program; if not, write to the Free Software\n\
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */\n\n");
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307\
+ USA */\n\n");
-printf("/* This code is generated by gen_lex_hash.cc that seeks for a perfect\nhash function */\n\n");
+ printf("/* This code is generated by gen_lex_hash.cc that seeks for\
+ a perfect\nhash function */\n\n");
printf("#include \"lex.h\"\n\n");
- print_arrays();
+ calc_length();
+
+ if (check_duplicates())
+ exit(1);
- printf("/* start_value=%ldL; best_t1=%ldL; best_t2=%ldL; best_type=%d; */ /* mode=%d add=%d type: %d */\n\n",
- best_start_value, best_t1, best_t2, best_type,
- best_mod, best_add, best_functype);
+ generate_find_structs();
+ print_find_structs();
- printf("inline SYMBOL *get_hash_symbol(const char *s,unsigned int length,bool function)\n\
+ printf("\nunsigned int sql_functions_max_len=%d;\n",max_len);
+ printf("\nunsigned int symbols_max_len=%d;\n\n",max_len2);
+
+ printf
+(
+"inline SYMBOL *get_hash_symbol(const char *s,\n\
+ unsigned int len,bool function)\n\
{\n\
- ulong idx = %lu+char_table[(uchar) *s];\n\
- SYMBOL *sim;\n\
- const char *start=s;\n\
- int i=unique_length[(uchar) *s++];\n\
- if (i > (int) length) i=(int) length;\n\
- while (--i > 0)\n\
- idx= (idx ^ (char_table[(uchar) *s++] + (idx << %d)));\n\
- idx=my_function_table[(idx & %d) %% %d];\n\
- if (idx >= %d)\n\
- {\n\
- if (!function || idx >= %d) return (SYMBOL*) 0;\n\
- sim=sql_functions + (idx - %d);\n\
+ register uchar *hash_map;\n\
+ register const char *cur_str= s;\n\
+ if (function){\n\
+ if (len>sql_functions_max_len) return 0;\n\
+ hash_map= sql_functions_map;\n\
+ register uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\
+\n\
+ for(;;){\n\
+ register uchar first_char= (uchar)cur_struct;\n\
+\n\
+ if (first_char==0){\n\
+ register int16 ires= (int16)(cur_struct>>16);\n\
+ if (ires==array_elements(symbols)) return 0;\n\
+ register SYMBOL *res;\n\
+ if (ires>=0) \n\
+ res= symbols+ires;\n\
+ else\n\
+ res= sql_functions-ires-1;\n\
+ register uint count= cur_str-s;\n\
+ return lex_casecmp(cur_str,res->name+count,len-count) ? 0 : res;\n\
+ }\n\
+\n\
+ register uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\
+ if (cur_char<first_char) return 0;\n\
+ cur_struct>>=8;\n\
+ if (cur_char>(uchar)cur_struct) return 0;\n\
+\n\
+ cur_struct>>=8;\n\
+ cur_struct= uint4korr(hash_map+\n\
+ (((uint16)cur_struct + cur_char - first_char)*4));\n\
+ cur_str++;\n\
+ }\n\
+ }else{\n\
+ if (len>symbols_max_len) return 0;\n\
+ hash_map= symbols_map;\n\
+ register uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\
+\n\
+ for(;;){\n\
+ register uchar first_char= (uchar)cur_struct;\n\
+\n\
+ if (first_char==0){\n\
+ register int16 ires= (int16)(cur_struct>>16);\n\
+ if (ires==array_elements(symbols)) return 0;\n\
+ register SYMBOL *res= symbols+ires;\n\
+ register uint count= cur_str-s;\n\
+ return lex_casecmp(cur_str,res->name+count,len-count)!=0 ? 0 : res;\n\
+ }\n\
+\n\
+ register uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\
+ if (cur_char<first_char) return 0;\n\
+ cur_struct>>=8;\n\
+ if (cur_char>(uchar)cur_struct) return 0;\n\
+\n\
+ cur_struct>>=8;\n\
+ cur_struct= uint4korr(hash_map+\n\
+ (((uint16)cur_struct + cur_char - first_char)*4));\n\
+ cur_str++;\n\
+ }\n\
}\n\
- else\n\
- sim=symbols + idx;\n\
- if ((length != sim->length) || lex_casecmp(start,sim->name,length))\n\
- return (SYMBOL *)0;\n\
- return sim;\n\
-}\n",(ulong) start_value,(int) function_plus,(int) how_much_and,function_mod,how_long_symbols,max_symbol,how_long_symbols);
- exit(0);
- return 0;
+}\n"
+);
}
+
diff --git a/sql/gstream.cc b/sql/gstream.cc
new file mode 100644
index 00000000000..a97ed9cae03
--- /dev/null
+++ b/sql/gstream.cc
@@ -0,0 +1,139 @@
+#include "mysql_priv.h"
+
+int GTextReadStream::get_next_toc_type() const
+{
+ const char *cur = m_cur;
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
+ {
+ cur++;
+ }
+ if (!(*cur))
+ {
+ return eostream;
+ }
+
+ if (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
+ (*cur=='_'))
+ {
+ return word;
+ }
+
+ if (((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') ||
+ (*cur=='.'))
+ {
+ return numeric;
+ }
+
+ if (*cur == '(')
+ {
+ return l_bra;
+ }
+
+ if (*cur == ')')
+ {
+ return r_bra;
+ }
+
+ if (*cur == ',')
+ {
+ return comma;
+ }
+
+ return unknown;
+}
+
+const char *GTextReadStream::get_next_word(int *word_len)
+{
+ const char *cur = m_cur;
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
+ {
+ cur++;
+ }
+ m_last_text_position = cur;
+
+ if (!(*cur))
+ {
+ return 0;
+ }
+
+ const char *wd_start = cur;
+
+ if (((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
+ {
+ return NULL;
+ }
+
+ ++cur;
+
+ while (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
+ (*cur=='_') || ((*cur>='0') && (*cur<='9')))
+ {
+ ++cur;
+ }
+
+ *word_len = cur - wd_start;
+
+ m_cur = cur;
+
+ return wd_start;
+}
+
+int GTextReadStream::get_next_number(double *d)
+{
+ const char *cur = m_cur;
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
+ {
+ cur++;
+ }
+
+ m_last_text_position = cur;
+ if (!(*cur))
+ {
+ set_error_msg("Numeric constant expected");
+ return 1;
+ }
+
+ if (((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.'))
+ {
+ set_error_msg("Numeric constant expected");
+ return 1;
+ }
+
+ char *endptr;
+
+ *d = strtod(cur, &endptr);
+
+ if (endptr)
+ {
+ m_cur = endptr;
+ }
+
+ return 0;
+}
+
+char GTextReadStream::get_next_symbol()
+{
+ const char *cur = m_cur;
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
+ {
+ cur++;
+ }
+ if (!(*cur))
+ {
+ return 0;
+ }
+
+ m_cur = cur + 1;
+ m_last_text_position = cur;
+
+ return *cur;
+}
+
+void GTextReadStream::set_error_msg(const char *msg)
+{
+ size_t len = strlen(msg);
+ m_err_msg = (char *)my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
+ memcpy(m_err_msg, msg, len + 1);
+}
+
+
diff --git a/sql/gstream.h b/sql/gstream.h
new file mode 100644
index 00000000000..f26ef8899f8
--- /dev/null
+++ b/sql/gstream.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+
+class GTextReadStream
+{
+public:
+ enum TokTypes
+ {
+ unknown,
+ eostream,
+ word,
+ numeric,
+ l_bra,
+ r_bra,
+ comma,
+ };
+
+ GTextReadStream(const char *buffer, int size)
+ :m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer),
+ m_err_msg(NULL)
+ {}
+ GTextReadStream(): m_cur(NULL), m_limit(NULL), m_err_msg(NULL)
+ {}
+
+ ~GTextReadStream()
+ {
+ my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR));
+ }
+
+ int get_next_toc_type() const;
+ const char *get_next_word(int *word_len);
+ int get_next_number(double *d);
+ char get_next_symbol();
+
+ const char *get_last_text_position() const
+ {
+ return m_last_text_position;
+ }
+
+ void set_error_msg(const char *msg);
+
+ // caller should free this pointer
+ char *get_error_msg()
+ {
+ char *err_msg = m_err_msg;
+ m_err_msg = NULL;
+ return err_msg;
+ }
+
+protected:
+ const char *m_cur;
+ const char *m_limit;
+ const char *m_last_text_position;
+ char *m_err_msg;
+};
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 2154fbd7a32..cdb5a8c1219 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -55,7 +55,6 @@
#ifdef HAVE_BERKELEY_DB
#include <m_ctype.h>
#include <myisampack.h>
-#include <assert.h>
#include <hash.h>
#include "ha_berkeley.h"
#include "sql_manager.h"
@@ -168,7 +167,7 @@ bool berkeley_init(void)
db_env=0; /* purecov: inspected */
}
- (void) hash_init(&bdb_open_tables,32,0,0,
+ (void) hash_init(&bdb_open_tables,system_charset_info,32,0,0,
(hash_get_key) bdb_get_key,0,0);
pthread_mutex_init(&bdb_mutex,MY_MUTEX_INIT_FAST);
DBUG_RETURN(db_env == 0);
@@ -194,12 +193,12 @@ bool berkeley_flush_logs()
int error;
bool result=0;
DBUG_ENTER("berkeley_flush_logs");
- if ((error=log_flush(db_env,0)))
+ if ((error=db_env->log_flush(db_env,0)))
{
my_error(ER_ERROR_DURING_FLUSH_LOGS,MYF(0),error); /* purecov: inspected */
result=1; /* purecov: inspected */
}
- if ((error=txn_checkpoint(db_env,0,0,0)))
+ if ((error=db_env->txn_checkpoint(db_env,0,0,0)))
{
my_error(ER_ERROR_DURING_CHECKPOINT,MYF(0),error); /* purecov: inspected */
result=1; /* purecov: inspected */
@@ -231,10 +230,9 @@ int berkeley_rollback(THD *thd, void *trans)
}
-int berkeley_show_logs(THD *thd)
+int berkeley_show_logs(Protocol *protocol)
{
char **all_logs, **free_logs, **a, **f;
- String *packet= &thd->packet;
int error=1;
MEM_ROOT show_logs_root;
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
@@ -243,10 +241,9 @@ int berkeley_show_logs(THD *thd)
init_alloc_root(&show_logs_root, 1024, 1024);
my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root);
- if ((error= log_archive(db_env, &all_logs, DB_ARCH_ABS | DB_ARCH_LOG,
- (void* (*)(size_t)) sql_alloc)) ||
- (error= log_archive(db_env, &free_logs, DB_ARCH_ABS,
- (void* (*)(size_t)) sql_alloc)))
+ if ((error= db_env->log_archive(db_env, &all_logs,
+ DB_ARCH_ABS | DB_ARCH_LOG)) ||
+ (error= db_env->log_archive(db_env, &free_logs, DB_ARCH_ABS)))
{
DBUG_PRINT("error", ("log_archive failed (error %d)", error));
db_env->err(db_env, error, "log_archive: DB_ARCH_ABS");
@@ -259,18 +256,18 @@ int berkeley_show_logs(THD *thd)
{
for (a = all_logs, f = free_logs; *a; ++a)
{
- packet->length(0);
- net_store_data(packet,*a);
- net_store_data(packet,"BDB");
+ protocol->prepare_for_resend();
+ protocol->store(*a);
+ protocol->store("BDB", 3);
if (f && *f && strcmp(*a, *f) == 0)
{
- ++f;
- net_store_data(packet, SHOW_LOG_STATUS_FREE);
+ f++;
+ protocol->store(SHOW_LOG_STATUS_FREE);
}
else
- net_store_data(packet, SHOW_LOG_STATUS_INUSE);
+ protocol->store(SHOW_LOG_STATUS_INUSE);
- if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ if (protocol->write())
{
error=1;
goto err;
@@ -309,10 +306,10 @@ void berkeley_cleanup_log_files(void)
/* XXX: Probably this should be done somewhere else, and
* should be tunable by the user. */
- if ((error = txn_checkpoint(db_env, 0, 0, 0)))
+ if ((error = db_env->txn_checkpoint(db_env, 0, 0, 0)))
my_error(ER_ERROR_DURING_CHECKPOINT, MYF(0), error); /* purecov: inspected */
- if ((error = log_archive(db_env, &names, DB_ARCH_ABS, NULL)) != 0)
+ if ((error = db_env->log_archive(db_env, &names, DB_ARCH_ABS)) != 0)
{
DBUG_PRINT("error", ("log_archive failed (error %d)", error)); /* purecov: inspected */
db_env->err(db_env, error, "log_archive: DB_ARCH_ABS"); /* purecov: inspected */
@@ -512,9 +509,12 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
berkeley_cmp_packed_key));
if (!hidden_primary_key)
file->app_private= (void*) (table->key_info+table->primary_key);
- if ((error=(file->open(file, fn_format(name_buff,name,"", ha_berkeley_ext,
- 2 | 4),
- "main", DB_BTREE, open_mode,0))))
+ if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
+ (error= (file->open(file, transaction,
+ fn_format(name_buff, name, "", ha_berkeley_ext,
+ 2 | 4),
+ "main", DB_BTREE, open_mode, 0))) ||
+ (error= transaction->commit(transaction, 0)))
{
free_share(share,table, hidden_primary_key,1); /* purecov: inspected */
my_free((char*) rec_buff,MYF(0)); /* purecov: inspected */
@@ -545,8 +545,10 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
(*ptr)->app_private= (void*) (table->key_info+i);
if (!(table->key_info[i].flags & HA_NOSAME))
(*ptr)->set_flags(*ptr, DB_DUP);
- if ((error=((*ptr)->open(*ptr, name_buff, part, DB_BTREE,
- open_mode, 0))))
+ if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
+ (error=((*ptr)->open(*ptr, transaction, name_buff, part, DB_BTREE,
+ open_mode, 0))) ||
+ (error= transaction->commit(transaction, 0)))
{
close(); /* purecov: inspected */
my_errno=error; /* purecov: inspected */
@@ -1414,10 +1416,21 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
DBT row;
int error;
KEY *key_info= &table->key_info[active_index];
+ int do_prev= 0;
DBUG_ENTER("ha_berkeley::index_read");
statistic_increment(ha_read_key_count,&LOCK_status);
bzero((char*) &row,sizeof(row));
+ if (find_flag == HA_READ_BEFORE_KEY)
+ {
+ find_flag= HA_READ_KEY_OR_NEXT;
+ do_prev= 1;
+ }
+ else if (find_flag == HA_READ_PREFIX_LAST_OR_PREV)
+ {
+ find_flag= HA_READ_AFTER_KEY;
+ do_prev= 1;
+ }
if (key_len == key_info->key_length)
{
error=read_row(cursor->c_get(cursor, pack_key(&last_key,
@@ -1451,6 +1464,12 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
error=HA_ERR_KEY_NOT_FOUND;
}
}
+ if (do_prev)
+ {
+ bzero((char*) &row, sizeof(row));
+ error= read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV),
+ (char*) buf, active_index, &row, &last_key, 1);
+ }
DBUG_RETURN(error);
}
@@ -1836,7 +1855,7 @@ static int create_sub_table(const char *table_name, const char *sub_name,
if (!(error=db_create(&file, db_env, 0)))
{
file->set_flags(file, flags);
- error=(file->open(file, table_name, sub_name, type,
+ error=(file->open(file, NULL, table_name, sub_name, type,
DB_THREAD | DB_CREATE, my_umask));
if (error)
{
@@ -1892,7 +1911,7 @@ int ha_berkeley::create(const char *name, register TABLE *form,
DB *status_block;
if (!db_create(&status_block, db_env, 0))
{
- if (!status_block->open(status_block, name_buff,
+ if (!status_block->open(status_block, NULL, name_buff,
"status", DB_BTREE, DB_CREATE, 0))
{
char rec_buff[4+MAX_KEY*4];
@@ -1921,6 +1940,7 @@ int ha_berkeley::delete_table(const char *name)
DBUG_RETURN(error);
}
+
int ha_berkeley::rename_table(const char * from, const char * to)
{
int error;
@@ -2066,8 +2086,7 @@ void ha_berkeley::print_error(int error, myf errflag)
static void print_msg(THD *thd, const char *table_name, const char *op_name,
const char *msg_type, const char *fmt, ...)
{
- String* packet = &thd->packet;
- packet->length(0);
+ Protocol *protocol= thd->protocol;
char msgbuf[256];
msgbuf[0] = 0;
va_list args;
@@ -2075,15 +2094,15 @@ static void print_msg(THD *thd, const char *table_name, const char *op_name,
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
-
DBUG_PRINT(msg_type,("message: %s",msgbuf));
- net_store_data(packet, table_name);
- net_store_data(packet, op_name);
- net_store_data(packet, msg_type);
- net_store_data(packet, msgbuf);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
- thd->packet.length()))
+ protocol->set_nfields(4);
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(op_name);
+ protocol->store(msg_type);
+ protocol->store(msgbuf);
+ if (protocol->write())
thd->killed=1;
}
#endif
@@ -2100,7 +2119,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
free(stat);
stat=0;
}
- if ((key_file[i]->stat)(key_file[i], (void*) &stat, 0, 0))
+ if ((key_file[i]->stat)(key_file[i], (void*) &stat, 0))
goto err; /* purecov: inspected */
share->rec_per_key[i]= (stat->bt_ndata /
(stat->bt_nkeys ? stat->bt_nkeys : 1));
@@ -2113,7 +2132,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
free(stat);
stat=0;
}
- if ((file->stat)(file, (void*) &stat, 0, 0))
+ if ((file->stat)(file, (void*) &stat, 0))
goto err; /* purecov: inspected */
}
pthread_mutex_lock(&share->mutex);
@@ -2316,7 +2335,7 @@ void ha_berkeley::get_status()
fn_format(name_buff, share->table_name,"", ha_berkeley_ext, 2 | 4);
if (!db_create(&share->status_block, db_env, 0))
{
- if (share->status_block->open(share->status_block, name_buff,
+ if (share->status_block->open(share->status_block, NULL, name_buff,
"status", DB_BTREE, open_mode, 0))
{
share->status_block->close(share->status_block, 0); /* purecov: inspected */
@@ -2392,7 +2411,7 @@ static void update_status(BDB_SHARE *share, TABLE *table)
if (db_create(&share->status_block, db_env, 0)) /* purecov: inspected */
goto end; /* purecov: inspected */
share->status_block->set_flags(share->status_block,0); /* purecov: inspected */
- if (share->status_block->open(share->status_block,
+ if (share->status_block->open(share->status_block, NULL,
fn_format(name_buff,share->table_name,"",
ha_berkeley_ext,2 | 4),
"status", DB_BTREE,
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index d2dc5e3216d..dd42e7ab9e2 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -181,4 +181,4 @@ bool berkeley_end(void);
bool berkeley_flush_logs(void);
int berkeley_commit(THD *thd, void *trans);
int berkeley_rollback(THD *thd, void *trans);
-int berkeley_show_logs(THD *thd);
+int berkeley_show_logs(Protocol *protocol);
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 2edc3b1478e..fb4061b31e0 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -33,69 +33,14 @@ const char **ha_heap::bas_ext() const
int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
- uint key,parts,mem_per_row=0;
- ulong max_rows;
- HP_KEYDEF *keydef;
- HP_KEYSEG *seg;
- THD *thd= current_thd;
-
- for (key=parts=0 ; key < table->keys ; key++)
- parts+=table->key_info[key].key_parts;
-
- if (!(keydef=(HP_KEYDEF*) my_malloc(table->keys*sizeof(HP_KEYDEF)+
- parts*sizeof(HP_KEYSEG),MYF(MY_WME))))
- return my_errno;
- seg=my_reinterpret_cast(HP_KEYSEG*) (keydef+table->keys);
- for (key=0 ; key < table->keys ; key++)
+ if (!(file= heap_open(name, mode)) && my_errno == ENOENT)
{
- KEY *pos=table->key_info+key;
- KEY_PART_INFO *key_part= pos->key_part;
- KEY_PART_INFO *key_part_end= key_part+pos->key_parts;
-
- mem_per_row += (pos->key_length + (sizeof(char*) * 2));
-
- keydef[key].keysegs=(uint) pos->key_parts;
- keydef[key].flag = (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
- keydef[key].seg=seg;
-
- for (; key_part != key_part_end ; key_part++, seg++)
- {
- uint flag=key_part->key_type;
- Field *field=key_part->field;
- if (!f_is_packed(flag) &&
- f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
- !(flag & FIELDFLAG_BINARY))
- seg->type= (int) HA_KEYTYPE_TEXT;
- else
- seg->type= (int) HA_KEYTYPE_BINARY;
- seg->start=(uint) key_part->offset;
- seg->length=(uint) key_part->length;
- if (field->null_ptr)
- {
- seg->null_bit=field->null_bit;
- seg->null_pos= (uint) (field->null_ptr-
- (uchar*) table->record[0]);
- }
- else
- {
- seg->null_bit=0;
- seg->null_pos=0;
- }
- }
+ HA_CREATE_INFO create_info;
+ bzero(&create_info, sizeof(create_info));
+ if (!create(name, table, &create_info))
+ file= heap_open(name, mode);
}
- mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
- max_rows = (ulong) (thd->variables.max_heap_table_size / mem_per_row);
- file=heap_open(name,mode,
- table->keys,keydef,
- table->reclength,
- (ulong) ((table->max_rows < max_rows && table->max_rows) ?
- table->max_rows : max_rows),
- (ulong) table->min_rows);
- my_free((gptr) keydef,MYF(0));
- if (file)
- info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
- ref_length=sizeof(HEAP_PTR);
- return (!file ? errno : 0);
+ return (file ? 0 : 1);
}
int ha_heap::close(void)
@@ -108,6 +53,8 @@ int ha_heap::write_row(byte * buf)
statistic_increment(ha_write_count,&LOCK_status);
if (table->time_stamp)
update_timestamp(buf+table->time_stamp-1);
+ if (table->next_number_field && buf == table->record[0])
+ update_auto_increment();
return heap_write(file,buf);
}
@@ -125,28 +72,32 @@ int ha_heap::delete_row(const byte * buf)
return heap_delete(file,buf);
}
-int ha_heap::index_read(byte * buf, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
+int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
+ enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
- int error=heap_rkey(file,buf,active_index, key);
- table->status=error ? STATUS_NOT_FOUND: 0;
+ statistic_increment(ha_read_key_count, &LOCK_status);
+ int error = heap_rkey(file,buf,active_index, key, key_len, find_flag);
+ table->status = error ? STATUS_NOT_FOUND : 0;
return error;
}
-int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
+int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
- int error=heap_rkey(file, buf, index, key);
- table->status=error ? STATUS_NOT_FOUND: 0;
+ statistic_increment(ha_read_key_count, &LOCK_status);
+ int error= heap_rkey(file, buf, active_index, key, key_len,
+ HA_READ_PREFIX_LAST);
+ table->status= error ? STATUS_NOT_FOUND : 0;
return error;
}
+int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ statistic_increment(ha_read_key_count, &LOCK_status);
+ int error = heap_rkey(file, buf, index, key, key_len, find_flag);
+ table->status = error ? STATUS_NOT_FOUND : 0;
+ return error;
+}
int ha_heap::index_next(byte * buf)
{
@@ -167,7 +118,7 @@ int ha_heap::index_prev(byte * buf)
int ha_heap::index_first(byte * buf)
{
statistic_increment(ha_read_first_count,&LOCK_status);
- int error=heap_rfirst(file, buf);
+ int error=heap_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -175,7 +126,7 @@ int ha_heap::index_first(byte * buf)
int ha_heap::index_last(byte * buf)
{
statistic_increment(ha_read_last_count,&LOCK_status);
- int error=heap_rlast(file, buf);
+ int error=heap_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -222,6 +173,8 @@ void ha_heap::info(uint flag)
index_file_length=info.index_length;
max_data_file_length= info.max_records* info.reclength;
delete_length= info.deleted * info.reclength;
+ if (flag & HA_STATUS_AUTO)
+ auto_increment_value= info.auto_increment;
}
int ha_heap::extra(enum ha_extra_function operation)
@@ -255,7 +208,6 @@ THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
return to;
}
-
/*
We have to ignore ENOENT entries as the HEAP table is created on open and
not when doing a CREATE on the table.
@@ -272,7 +224,6 @@ int ha_heap::rename_table(const char * from, const char * to)
return heap_rename(from,to);
}
-
ha_rows ha_heap::records_in_range(int inx,
const byte *start_key,uint start_key_len,
enum ha_rkey_function start_search_flag,
@@ -280,18 +231,121 @@ ha_rows ha_heap::records_in_range(int inx,
enum ha_rkey_function end_search_flag)
{
KEY *pos=table->key_info+inx;
- if (start_key_len != end_key_len ||
- start_key_len != pos->key_length ||
- start_search_flag != HA_READ_KEY_EXACT ||
- end_search_flag != HA_READ_AFTER_KEY)
- return HA_POS_ERROR; // Can't only use exact keys
- return 10; // Good guess
+ if (pos->algorithm == HA_KEY_ALG_BTREE)
+ {
+ return hp_rb_records_in_range(file, inx, start_key, start_key_len,
+ start_search_flag, end_key, end_key_len,
+ end_search_flag);
+ }
+ else
+ {
+ if (start_key_len != end_key_len ||
+ start_key_len != pos->key_length ||
+ start_search_flag != HA_READ_KEY_EXACT ||
+ end_search_flag != HA_READ_AFTER_KEY)
+ return HA_POS_ERROR; // Can't only use exact keys
+ return 10; // Good guess
+ }
}
+int ha_heap::create(const char *name, TABLE *table,
+ HA_CREATE_INFO *create_info)
+{
+ uint key, parts, mem_per_row= 0;
+ uint auto_key= 0, auto_key_type= 0;
+ ha_rows max_rows;
+ HP_KEYDEF *keydef;
+ HA_KEYSEG *seg;
+ char buff[FN_REFLEN];
+ int error;
+
+ for (key= parts= 0; key < table->keys; key++)
+ parts+= table->key_info[key].key_parts;
+
+ if (!(keydef= (HP_KEYDEF*) my_malloc(table->keys * sizeof(HP_KEYDEF) +
+ parts * sizeof(HA_KEYSEG),
+ MYF(MY_WME))))
+ return my_errno;
+ seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + table->keys);
+ for (key= 0; key < table->keys; key++)
+ {
+ KEY *pos= table->key_info+key;
+ KEY_PART_INFO *key_part= pos->key_part;
+ KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
+
+ mem_per_row+= (pos->key_length + (sizeof(char*) * 2));
+
+ keydef[key].keysegs= (uint) pos->key_parts;
+ keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
+ keydef[key].seg= seg;
+ keydef[key].algorithm= ((pos->algorithm == HA_KEY_ALG_UNDEF) ?
+ HA_KEY_ALG_HASH : pos->algorithm);
+
+ for (; key_part != key_part_end; key_part++, seg++)
+ {
+ uint flag= key_part->key_type;
+ Field *field= key_part->field;
+ if (pos->algorithm == HA_KEY_ALG_BTREE)
+ seg->type= field->key_type();
+ else
+ {
+ if (!f_is_packed(flag) &&
+ f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
+ !(flag & FIELDFLAG_BINARY))
+ seg->type= (int) HA_KEYTYPE_TEXT;
+ else
+ seg->type= (int) HA_KEYTYPE_BINARY;
+ }
+ seg->start= (uint) key_part->offset;
+ seg->length= (uint) key_part->length;
+ seg->flag = 0;
+ seg->charset= field->charset();
+ if (field->null_ptr)
+ {
+ seg->null_bit= field->null_bit;
+ seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
+ }
+ else
+ {
+ seg->null_bit= 0;
+ seg->null_pos= 0;
+ }
+ if (field->flags & AUTO_INCREMENT_FLAG)
+ {
+ auto_key= key + 1;
+ auto_key_type= field->key_type();
+ }
+ }
+ }
+ mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
+ max_rows = (ha_rows) (current_thd->variables.max_heap_table_size /
+ mem_per_row);
+ HP_CREATE_INFO hp_create_info;
+ hp_create_info.auto_key= auto_key;
+ hp_create_info.auto_key_type= auto_key_type;
+ hp_create_info.auto_increment= (create_info->auto_increment_value ?
+ create_info->auto_increment_value - 1 : 0);
+ error= heap_create(fn_format(buff,name,"","",4+2),
+ table->keys,keydef, table->reclength,
+ (ulong) ((table->max_rows < max_rows && table->max_rows) ?
+ table->max_rows : max_rows),
+ (ulong) table->min_rows, &hp_create_info);
+ my_free((gptr) keydef, MYF(0));
+ if (file)
+ info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ ref_length= sizeof(HEAP_PTR);
+ return (error);
+}
-int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
+void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
+{
+ table->file->info(HA_STATUS_AUTO);
+ if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
+ create_info->auto_increment_value= auto_increment_value;
+}
+longlong ha_heap::get_auto_increment()
{
- char buff[FN_REFLEN];
- return heap_create(fn_format(buff,name,"","",4+2));
+ ha_heap::info(HA_STATUS_AUTO);
+ return auto_increment_value;
}
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 504f5262bf3..fe874dab3f2 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -40,8 +40,7 @@ class ha_heap: public handler
ulong table_flags() const
{
return (HA_READ_RND_SAME | HA_NO_INDEX | HA_KEYPOS_TO_RNDPOS |
- HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ |
- HA_NO_AUTO_INCREMENT);
+ HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ);
}
ulong index_flags(uint inx) const
{
@@ -63,10 +62,12 @@ class ha_heap: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
+ longlong get_auto_increment();
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
@@ -87,6 +88,7 @@ class ha_heap: public handler
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
+ void update_create_info(HA_CREATE_INFO *create_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index fce9500a47c..a037c6989aa 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -32,7 +32,6 @@ InnoDB */
#ifdef HAVE_INNOBASE_DB
#include <m_ctype.h>
-#include <assert.h>
#include <hash.h>
#include <myisampack.h>
@@ -82,7 +81,8 @@ are declared in mysqld.cc: */
long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_log_file_size, innobase_log_buffer_size,
- innobase_buffer_pool_size, innobase_additional_mem_pool_size,
+ innobase_buffer_pool_size, innobase_buffer_pool_awe_mem_mb,
+ innobase_additional_mem_pool_size,
innobase_file_io_threads, innobase_lock_wait_timeout,
innobase_thread_concurrency, innobase_force_recovery;
@@ -753,7 +753,25 @@ innobase_init(void)
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
- srv_pool_size = (ulint) innobase_buffer_pool_size;
+ /* We set srv_pool_size here in units of 1 kB. InnoDB internally
+ changes the value so that it becomes the number of database pages. */
+
+ if (innobase_buffer_pool_awe_mem_mb == 0) {
+ /* Careful here: we first convert the signed long int to ulint
+ and only after that divide */
+
+ srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
+ } else {
+ srv_use_awe = TRUE;
+ srv_pool_size = (ulint)
+ (1024 * innobase_buffer_pool_awe_mem_mb);
+ srv_awe_window_size = (ulint) innobase_buffer_pool_size;
+
+ /* Note that what the user specified as
+ innodb_buffer_pool_size is actually the AWE memory window
+ size in this case, and the real buffer pool size is
+ determined by .._awe_mem_mb. */
+ }
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
@@ -792,9 +810,8 @@ innobase_init(void)
DBUG_RETURN(1);
}
-
- (void) hash_init(&innobase_open_tables,32,0,0,
- (hash_get_key) innobase_get_key,0,0);
+ (void) hash_init(&innobase_open_tables,system_charset_info,32,0,0,
+ (hash_get_key) innobase_get_key,0,0);
pthread_mutex_init(&innobase_mutex,MY_MUTEX_INIT_FAST);
/* If this is a replication slave and we needed to do a crash recovery,
@@ -877,6 +894,7 @@ innobase_commit_low(
/*================*/
trx_t* trx) /* in: transaction handle */
{
+#ifdef HAVE_REPLICATION
if (current_thd->slave_thread) {
/* Update the replication position info inside InnoDB */
#ifdef NEED_TO_BE_FIXED
@@ -890,6 +908,7 @@ innobase_commit_low(
active_mi->rli.event_len +
active_mi->rli.pending));
}
+#endif /* HAVE_REPLICATION */
trx_commit_for_mysql(trx);
}
@@ -1419,8 +1438,11 @@ innobase_mysql_cmp(
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
- ret = my_sortncmp((const char*) a, a_length,
- (const char*) b, b_length);
+ // BAR TODO: Discuss with heikki.tuuri@innodb.com
+ // so that he sends CHARSET_INFO for the field to this function.
+ ret = my_strnncoll(default_charset_info,
+ a, a_length,
+ b, b_length);
if (ret < 0) {
return(-1);
} else if (ret > 0) {
@@ -1456,7 +1478,7 @@ get_innobase_type_from_mysql_type(
DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256);
switch (field->type()) {
- case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) {
+ case FIELD_TYPE_VAR_STRING: if (field->binary()) {
return(DATA_BINARY);
} else if (strcmp(
@@ -1466,7 +1488,7 @@ get_innobase_type_from_mysql_type(
} else {
return(DATA_VARMYSQL);
}
- case FIELD_TYPE_STRING: if (field->flags & BINARY_FLAG) {
+ case FIELD_TYPE_STRING: if (field->binary()) {
return(DATA_FIXBINARY);
} else if (strcmp(
@@ -1580,6 +1602,8 @@ build_template(
ibool fetch_all_in_key = FALSE;
ulint i;
+ ut_a(templ_type != ROW_MYSQL_REC_FIELDS || thd == current_thd);
+
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
if (!prebuilt->hint_no_need_to_fetch_extra_cols) {
@@ -1604,6 +1628,12 @@ build_template(
}
if (prebuilt->select_lock_type == LOCK_X) {
+ /* In versions < 3.23.50 we always retrieved the clustered
+ index record if prebuilt->select_lock_type == LOCK_S,
+ but there is really not need for that, and in some cases
+ performance could be seriously degraded because the MySQL
+ optimizer did not know about our convention! */
+
/* We always retrieve the whole clustered index record if we
use exclusive row level locks, for example, if the read is
done in an UPDATE statement. */
@@ -1612,12 +1642,6 @@ build_template(
}
if (templ_type == ROW_MYSQL_REC_FIELDS) {
- /* In versions < 3.23.50 we always retrieved the clustered
- index record if prebuilt->select_lock_type == LOCK_S,
- but there is really not need for that, and in some cases
- performance could be seriously degraded because the MySQL
- optimizer did not know about our convention! */
-
index = prebuilt->index;
} else {
index = clust_index;
@@ -1649,18 +1673,31 @@ build_template(
field = table->field[i];
if (templ_type == ROW_MYSQL_REC_FIELDS
+ && prebuilt->read_just_key
+ && dict_index_get_nth_col_pos(index, i)
+ == ULINT_UNDEFINED) {
+ /* Skip a column which is not in the index */
+
+ goto skip_field;
+ }
+
+
+ /* TODO: we have removed temporarily the test of which columns
+ to fetch, until the new client/server protocol of 4.1
+ is fixed!!!!!!!!!!!!!!!!!
+
+ if (templ_type == ROW_MYSQL_REC_FIELDS
&& !(fetch_all_in_key &&
- ULINT_UNDEFINED != dict_index_get_nth_col_pos(
- index, i))
+ ULINT_UNDEFINED != dict_index_get_nth_col_pos(
+ index, i))
&& thd->query_id != field->query_id
&& thd->query_id != (field->query_id ^ MAX_ULONG_BIT)
&& thd->query_id !=
(field->query_id ^ (MAX_ULONG_BIT >> 1))) {
- /* This field is not needed in the query, skip it */
-
goto skip_field;
}
+ */
n_requested_fields++;
@@ -2447,7 +2484,9 @@ ha_innobase::index_read_last(
}
/************************************************************************
-Changes the active index of a handle. */
+Changes the active index of a handle. Note that since we build also the
+template for a search, update_thd() must already have been called, in
+::external_lock, for example. */
int
ha_innobase::change_active_index(
@@ -2463,6 +2502,10 @@ ha_innobase::change_active_index(
DBUG_ENTER("change_active_index");
ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+ ut_a(user_thd == current_thd);
+
+ ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
active_index = keynr;
@@ -2490,11 +2533,13 @@ ha_innobase::change_active_index(
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
prebuilt->index->n_fields);
- /* Maybe MySQL changes the active index for a handle also
- during some queries, we do not know: then it is safest to build
- the template such that all columns will be fetched. */
+ /* MySQL changes the active index for a handle also during some
+ queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
+ and then calculates te sum. Previously we played safe and used
+ the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
+ copying. Starting from MySQL-4.1 we use a more efficient flag here. */
- build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
+ build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
DBUG_RETURN(0);
}
@@ -3279,8 +3324,8 @@ innobase_drop_database(
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
namebuf[len + 1] = '\0';
-#ifdef __WIN__
- casedn_str(namebuf);
+#ifdef FN_NO_CASE_SENCE
+ my_casedn_str(system_charset_info, namebuf);
#endif
trx = trx_allocate_for_mysql();
@@ -3826,8 +3871,18 @@ ha_innobase::extra(
obsolete! */
switch (operation) {
+ case HA_EXTRA_FLUSH:
+ if (prebuilt->blob_heap) {
+ row_mysql_prebuilt_free_blob_heap(prebuilt);
+ }
+ break;
case HA_EXTRA_RESET:
- case HA_EXTRA_RESET_STATE:
+ if (prebuilt->blob_heap) {
+ row_mysql_prebuilt_free_blob_heap(prebuilt);
+ }
+ prebuilt->read_just_key = 0;
+ break;
+ case HA_EXTRA_RESET_STATE:
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_NO_KEYREAD:
@@ -4032,9 +4087,8 @@ innodb_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
{
- String* packet = &thd->packet;
char* buf;
-
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("innodb_show_status");
if (innodb_skip) {
@@ -4055,27 +4109,20 @@ innodb_show_status(
field_list.push_back(new Item_empty_string("Status", strlen(buf)));
- if(send_fields(thd, field_list, 1)) {
-
+ if (protocol->send_fields(&field_list, 1))
+ {
ut_free(buf);
-
DBUG_RETURN(-1);
}
- packet->length(0);
-
- net_store_data(packet, buf);
-
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
- packet->length())) {
- ut_free(buf);
-
- DBUG_RETURN(-1);
- }
-
+ protocol->prepare_for_resend();
+ protocol->store(buf, strlen(buf));
ut_free(buf);
+
+ if (protocol->write())
+ DBUG_RETURN(-1);
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index d2639f39c5b..86fb5d1947b 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -178,7 +178,8 @@ extern char *innobase_home, *innobase_tmpdir, *innobase_logdir;
extern long innobase_lock_scan_time;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
extern long innobase_log_file_size, innobase_log_buffer_size;
-extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size;
+extern long innobase_buffer_pool_size, innobase_buffer_pool_awe_mem_mb,
+ innobase_additional_mem_pool_size;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
extern long innobase_force_recovery, innobase_thread_concurrency;
extern char *innobase_data_home_dir, *innobase_data_file_path;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 81b04cf5ba7..7cd5927bd24 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -28,6 +28,7 @@
#include "../srclib/myisam/myisamdef.h"
#else
#include "../myisam/myisamdef.h"
+#include "../myisam/rt_index.h"
#endif
ulong myisam_recover_options= HA_RECOVER_NONE;
@@ -49,36 +50,38 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
const char *fmt, va_list args)
{
THD* thd = (THD*)param->thd;
- String* packet = &thd->packet;
- uint length;
+ Protocol *protocol= thd->protocol;
+ uint length, msg_length;
char msgbuf[MI_MAX_MSG_BUF];
char name[NAME_LEN*2+2];
- packet->length(0);
- msgbuf[0] = 0; // healthy paranoia ?
- my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
+ msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
DBUG_PRINT(msg_type,("message: %s",msgbuf));
+#ifndef EMBEDDED_LIBRARY
if (thd->net.vio == 0)
{
sql_print_error(msgbuf);
return;
}
- if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR))
+#endif
+
+ if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
+ T_AUTO_REPAIR))
{
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
return;
}
length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
name);
- net_store_data(packet, name, length);
- net_store_data(packet, param->op_name);
- net_store_data(packet, msg_type);
-
- net_store_data(packet, msgbuf);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(name, length);
+ protocol->store(param->op_name);
+ protocol->store(msg_type);
+ protocol->store(msgbuf, msg_length);
+ if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
return;
@@ -86,6 +89,11 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
extern "C" {
+volatile bool *killed_ptr(MI_CHECK *param)
+{
+ return &(((THD *)(param->thd))->killed);
+}
+
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
{
param->error_printed|=1;
@@ -122,11 +130,16 @@ const char **ha_myisam::bas_ext() const
const char *ha_myisam::index_type(uint key_number)
{
- return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
+ return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
"FULLTEXT" :
+ (table->key_info[key_number].flags & HA_SPATIAL) ?
+ "SPATIAL" :
+ (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
+ "RTREE" :
"BTREE");
}
+#ifdef HAVE_REPLICATION
int ha_myisam::net_read_dump(NET* net)
{
int data_fd = file->dfile;
@@ -151,7 +164,6 @@ int ha_myisam::net_read_dump(NET* net)
goto err;
}
}
-
err:
return error;
}
@@ -208,6 +220,7 @@ err:
my_free((gptr) buf, MYF(0));
return error;
}
+#endif /* HAVE_REPLICATION */
/* Name is here without an extension */
@@ -554,7 +567,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
param.tmpfile_createflag = O_RDWR | O_TRUNC;
param.using_global_keycache = 1;
param.thd=thd;
- param.tmpdir=mysql_tmpdir;
+ param.tmpdir=&mysql_tmpdir_list;
param.out_flag=0;
strmov(fixed_name,file->filename);
@@ -727,7 +740,7 @@ bool ha_myisam::activate_all_index(THD *thd)
T_CREATE_MISSING_KEYS);
param.myf_rw&= ~MY_WAIT_IF_FULL;
param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
- param.tmpdir=mysql_tmpdir;
+ param.tmpdir=&mysql_tmpdir_list;
error=repair(thd,param,0) != HA_ADMIN_OK;
thd->proc_info=save_proc_info;
}
@@ -788,7 +801,7 @@ int ha_myisam::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
statistic_increment(ha_read_key_count,&LOCK_status);
- int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
+ int error=mi_rkey(file,buf,active_index, key, key_len, (enum ha_rkey_function)find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -797,7 +810,7 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
statistic_increment(ha_read_key_count,&LOCK_status);
- int error=mi_rkey(file,buf,index, key, key_len, find_flag);
+ int error=mi_rkey(file,buf,index, key, key_len, (enum ha_rkey_function)find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -1027,7 +1040,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
KEY *pos;
MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos;
- MI_KEYSEG *keyseg;
+ HA_KEYSEG *keyseg;
uint options=table_arg->db_options_in_use;
DBUG_ENTER("ha_myisam::create");
@@ -1036,14 +1049,17 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
&recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF),
&keydef, table_arg->keys*sizeof(MI_KEYDEF),
&keyseg,
- ((table_arg->key_parts + table_arg->keys) * sizeof(MI_KEYSEG)),
+ ((table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG)),
0)))
DBUG_RETURN(1);
pos=table_arg->key_info;
for (i=0; i < table_arg->keys ; i++, pos++)
{
- keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT));
+ keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
+ keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
+ (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
+ pos->algorithm;
keydef[i].seg=keyseg;
keydef[i].keysegs=pos->key_parts;
for (j=0 ; j < pos->key_parts ; j++)
@@ -1078,7 +1094,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].seg[j].start= pos->key_part[j].offset;
keydef[i].seg[j].length= pos->key_part[j].length;
keydef[i].seg[j].bit_start=keydef[i].seg[j].bit_end=0;
- keydef[i].seg[j].language=MY_CHARSET_CURRENT;
+ keydef[i].seg[j].language = field->charset()->number;
if (field->null_ptr)
{
@@ -1097,7 +1113,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].flag|=HA_AUTO_KEY;
found_auto_increment=1;
}
- if (field->type() == FIELD_TYPE_BLOB)
+ if ((field->type() == FIELD_TYPE_BLOB) || (field->type() == FIELD_TYPE_GEOMETRY))
{
keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 215608f8f0a..5dc294b3b9f 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -127,6 +127,8 @@ class ha_myisam: public handler
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt);
+#ifdef HAVE_REPLICATION
int dump(THD* thd, int fd);
int net_read_dump(NET* net);
+#endif
};
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 616248b2cf3..5f07bbc4140 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -160,6 +160,16 @@ int ha_myisammrg::index_last(byte * buf)
return error;
}
+int ha_myisammrg::index_next_same(byte * buf,
+ const byte *key __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+ statistic_increment(ha_read_next_count,&LOCK_status);
+ int error=myrg_rnext_same(file,buf);
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
int ha_myisammrg::rnd_init(bool scan)
{
return myrg_extra(file,HA_EXTRA_RESET,0);
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index 440b51e660f..008f5339caf 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -65,15 +65,16 @@ class ha_myisammrg: public handler
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
+ int index_next_same(byte *buf, const byte *key, uint keylen);
int rnd_init(bool scan=1);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
ha_rows records_in_range(int inx,
- const byte *start_key,uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key,uint end_key_len,
- enum ha_rkey_function end_search_flag);
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag);
my_off_t row_position() { return myrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
diff --git a/sql/handler.cc b/sql/handler.cc
index fb33888e91e..dcc732ba25a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -689,7 +689,7 @@ void handler::print_error(int error, myf errflag)
{
/* Write the dupplicated key in the error message */
char key[MAX_KEY_LENGTH];
- String str(key,sizeof(key));
+ String str(key,sizeof(key),default_charset_info);
key_unpack(&str,table,(uint) key_nr);
uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
if (str.length() >= max_length)
diff --git a/sql/handler.h b/sql/handler.h
index b9209d087a0..6cbd83af282 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -137,6 +137,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
#define HA_CREATE_USED_MAX_ROWS 32
#define HA_CREATE_USED_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128
+#define HA_CREATE_USED_CHARSET 256
typedef struct st_thd_trans {
void *bdb_tid;
@@ -149,21 +150,22 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
typedef struct st_ha_create_information
{
- ulong table_options;
- enum db_type db_type;
- enum row_type row_type;
- ulong avg_row_length;
- ulonglong max_rows,min_rows;
- ulonglong auto_increment_value;
+ CHARSET_INFO *table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
- uint options; /* OR of HA_CREATE_ options */
- uint raid_type,raid_chunks;
+ ulonglong max_rows,min_rows;
+ ulonglong auto_increment_value;
+ ulong table_options;
+ ulong avg_row_length;
ulong raid_chunksize;
- bool if_not_exists;
ulong used_fields;
SQL_LIST merge_list;
+ enum db_type db_type;
+ enum row_type row_type;
+ uint options; /* OR of HA_CREATE_ options */
+ uint raid_type,raid_chunks;
uint merge_insert_method;
+ bool if_not_exists;
} HA_CREATE_INFO;
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index 34584b45d8c..f7384cc6e32 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -75,8 +75,8 @@ public:
if (!locked)
(void) pthread_mutex_lock(&lock);
(void) hash_free(&cache);
- (void) hash_init(&cache,size,key_offset, key_length, get_key, free_element,
- 0);
+ (void) hash_init(&cache,system_charset_info,size,key_offset,
+ key_length, get_key, free_element,0);
if (!locked)
(void) pthread_mutex_unlock(&lock);
first_link=last_link=0;
diff --git a/sql/hostname.cc b/sql/hostname.cc
index ed56e199c3c..2905320cc15 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -223,10 +223,10 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
/* Don't accept hostnames that starts with digits because they may be
false ip:s */
- if (isdigit(name[0]))
+ if (my_isdigit(&my_charset_latin1,name[0]))
{
char *pos;
- for (pos= name+1 ; isdigit(*pos); pos++) ;
+ for (pos= name+1 ; my_isdigit(&my_charset_latin1,*pos); pos++) ;
if (*pos == '.')
{
DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'"));
diff --git a/sql/init.cc b/sql/init.cc
index df06ddd41ef..8834fd3a89c 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -52,17 +52,6 @@ void unireg_init(ulong options)
}
specialflag|=options; /* Set options from argv */
- // The following is needed because of like optimization in select.cc
-
- uchar max_char=my_sort_order[(uchar) max_sort_char];
- for (i = 0; i < 256; i++)
- {
- if ((uchar) my_sort_order[i] > max_char)
- {
- max_char=(uchar) my_sort_order[i];
- max_sort_char= (char) i;
- }
- }
thread_stack_min=thread_stack - STACK_MIN_SIZE;
DBUG_VOID_RETURN;
}
diff --git a/sql/item.cc b/sql/item.cc
index ec9b07c443c..ee7af1ae0fd 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -34,23 +34,67 @@ void item_init(void)
item_user_lock_init();
}
-Item::Item()
+Item::Item():
+ fixed(0)
{
- marker=0;
- binary=maybe_null=null_value=with_sum_func=unsigned_flag=0;
- name=0;
- decimals=0; max_length=0;
- next=current_thd->free_list; // Put in free list
- current_thd->free_list=this;
+ marker= 0;
+ maybe_null=null_value=with_sum_func=unsigned_flag=0;
+ name= 0;
+ decimals= 0; max_length= 0;
+ THD *thd= current_thd;
+ next= thd->free_list; // Put in free list
+ thd->free_list= this;
+ loop_id= 0;
}
-void Item::set_name(char *str,uint length)
+/*
+ Constructor used by Item_field, Item_ref & agregate (sum) functions.
+ Used for duplicating lists in processing queries with temporary
+ tables
+*/
+Item::Item(THD *thd, Item &item):
+ loop_id(0),
+ str_value(item.str_value),
+ name(item.name),
+ max_length(item.max_length),
+ marker(item.marker),
+ decimals(item.decimals),
+ maybe_null(item.maybe_null),
+ null_value(item.null_value),
+ unsigned_flag(item.unsigned_flag),
+ with_sum_func(item.with_sum_func),
+ fixed(item.fixed)
+{
+ next=thd->free_list; // Put in free list
+ thd->free_list= this;
+}
+
+// Constructor used by Item_field & Item_ref (see Item comment)
+Item_ident::Item_ident(THD *thd, Item_ident &item):
+ Item(thd, item),
+ db_name(item.db_name),
+ table_name(item.table_name),
+ field_name(item.field_name),
+ depended_from(item.depended_from)
+{}
+
+bool Item::check_cols(uint c)
+{
+ if (c != 1)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), c);
+ return 1;
+ }
+ return 0;
+}
+
+void Item::set_name(const char *str,uint length)
{
if (!length)
- name=str; // Used by AS
+ name= (char*) str; // Used by AS
else
{
- while (length && !isgraph(*str))
+ while (length && !my_isgraph(system_charset_info,*str))
{ // Fix problem with yacc
length--;
str++;
@@ -66,7 +110,7 @@ void Item::set_name(char *str,uint length)
bool Item::eq(const Item *item, bool binary_cmp) const
{
return type() == item->type() && name && item->name &&
- !my_strcasecmp(name,item->name);
+ !my_strcasecmp(system_charset_info,name,item->name);
}
bool Item_string::eq(const Item *item, bool binary_cmp) const
@@ -89,7 +133,7 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const
bool Item::get_date(TIME *ltime,bool fuzzydate)
{
char buff[40];
- String tmp(buff,sizeof(buff)),*res;
+ String tmp(buff,sizeof(buff), &my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE)
{
@@ -107,7 +151,7 @@ bool Item::get_date(TIME *ltime,bool fuzzydate)
bool Item::get_time(TIME *ltime)
{
char buff[40];
- String tmp(buff,sizeof(buff)),*res;
+ String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_time(res->ptr(),res->length(),ltime))
{
@@ -117,11 +161,23 @@ bool Item::get_time(TIME *ltime)
return 0;
}
+CHARSET_INFO * Item::thd_charset() const
+{
+ return current_thd->variables.thd_charset;
+}
+
Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
{
set_field(f);
+ fixed= 1; // This item is not needed in fix_fields
}
+// Constructor need to process subselect with temporary tables (see Item)
+Item_field::Item_field(THD *thd, Item_field &item):
+ Item_ident(thd, item),
+ field(item.field),
+ result_field(item.result_field)
+{}
void Item_field::set_field(Field *field_par)
{
@@ -131,8 +187,8 @@ void Item_field::set_field(Field *field_par)
decimals= field->decimals();
table_name=field_par->table_name;
field_name=field_par->field_name;
- binary=field_par->binary();
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
+ set_charset(field_par->charset());
}
const char *Item_ident::full_name() const
@@ -140,7 +196,7 @@ const char *Item_ident::full_name() const
char *tmp;
if (!table_name)
return field_name ? field_name : name ? name : "tmp_field";
- if (db_name)
+ if (db_name && db_name[0])
{
tmp=(char*) sql_alloc((uint) strlen(db_name)+(uint) strlen(table_name)+
(uint) strlen(field_name)+3);
@@ -160,6 +216,7 @@ String *Item_field::val_str(String *str)
{
if ((null_value=field->is_null()))
return 0;
+ str->set_charset(str_value.charset());
return field->val_str(str,&str_value);
}
@@ -182,6 +239,7 @@ String *Item_field::str_result(String *str)
{
if ((null_value=result_field->is_null()))
return 0;
+ str->set_charset(str_value.charset());
return result_field->val_str(str,&str_value);
}
@@ -228,13 +286,20 @@ table_map Item_field::used_tables() const
{
if (field->table->const_table)
return 0; // const item
- return field->table->map;
+ return (depended_from ? RAND_TABLE_BIT : field->table->map);
}
+Item *Item_field::get_tmp_table_item(THD *thd)
+{
+ Item_field *new_item= new Item_field(thd, *this);
+ if (new_item)
+ new_item->field= new_item->result_field;
+ return new_item;
+}
String *Item_int::val_str(String *str)
{
- str->set(value);
+ str->set(value, thd_charset());
return str;
}
@@ -242,7 +307,7 @@ void Item_int::print(String *str)
{
if (!name)
{
- str_value.set(value);
+ str_value.set(value, thd_charset());
name=str_value.c_ptr();
}
str->append(name);
@@ -250,7 +315,7 @@ void Item_int::print(String *str)
String *Item_uint::val_str(String *str)
{
- str->set((ulonglong) value);
+ str->set((ulonglong) value, thd_charset());
return str;
}
@@ -258,7 +323,7 @@ void Item_uint::print(String *str)
{
if (!name)
{
- str_value.set((ulonglong) value);
+ str_value.set((ulonglong) value, thd_charset());
name=str_value.c_ptr();
}
str->append(name);
@@ -267,7 +332,7 @@ void Item_uint::print(String *str)
String *Item_real::val_str(String *str)
{
- str->set(value,decimals);
+ str->set(value,decimals,thd_charset());
return str;
}
@@ -287,6 +352,136 @@ String *Item_null::val_str(String *str)
{ null_value=1; return 0;}
+/* Item_param related */
+void Item_param::set_null()
+{
+ maybe_null=null_value=1;
+}
+
+void Item_param::set_int(longlong i)
+{
+ int_value=(longlong)i;
+ item_type = INT_ITEM;
+}
+
+void Item_param::set_double(double value)
+{
+ real_value=value;
+ item_type = REAL_ITEM;
+}
+
+
+void Item_param::set_value(const char *str, uint length)
+{
+ str_value.set(str,length,thd_charset());
+ item_type = STRING_ITEM;
+}
+
+
+void Item_param::set_time(TIME *tm, timestamp_type type)
+{
+ ltime.year= tm->year;
+ ltime.month= tm->month;
+ ltime.day= tm->day;
+
+ ltime.hour= tm->hour;
+ ltime.minute= tm->minute;
+ ltime.second= tm->second;
+
+ ltime.second_part= tm->second_part;
+
+ ltime.time_type= type;
+
+ item_is_time= true;
+ item_type= STRING_ITEM;
+}
+
+
+void Item_param::set_longdata(const char *str, ulong length)
+{
+ str_value.append(str,length);
+ long_data_supplied= 1;
+}
+
+
+int Item_param::save_in_field(Field *field, bool no_conversions)
+{
+ if (null_value)
+ return (int) set_field_to_null(field);
+
+ field->set_notnull();
+ if (item_result_type == INT_RESULT)
+ {
+ longlong nr=val_int();
+ return (field->store(nr)) ? -1 : 0;
+ }
+ if (item_result_type == REAL_RESULT)
+ {
+ double nr=val();
+ return (field->store(nr)) ? -1 : 0;
+ }
+ if (item_is_time)
+ {
+ field->store_time(&ltime, ltime.time_type);
+ return 0;
+ }
+ String *result=val_str(&str_value);
+ return (field->store(result->ptr(),result->length(),field->charset())) ? -1 : 0;
+}
+
+bool Item_param::get_time(TIME *res)
+{
+ *res=ltime;
+ return 0;
+}
+
+double Item_param::val()
+{
+ int err;
+ switch (item_result_type) {
+ case STRING_RESULT:
+ return (double) my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), (char**) 0, &err);
+ case INT_RESULT:
+ return (double)int_value;
+ default:
+ return real_value;
+ }
+}
+
+
+longlong Item_param::val_int()
+{
+ int err;
+ switch (item_result_type) {
+ case STRING_RESULT:
+ return my_strntoll(str_value.charset(),
+ str_value.ptr(),str_value.length(),10,
+ (char**) 0,&err);
+ case REAL_RESULT:
+ return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5));
+ default:
+ return int_value;
+ }
+}
+
+
+String *Item_param::val_str(String* str)
+{
+ switch (item_result_type) {
+ case INT_RESULT:
+ str->set(int_value, thd_charset());
+ return str;
+ case REAL_RESULT:
+ str->set(real_value, 2, thd_charset());
+ return str;
+ default:
+ return (String*) &str_value;
+ }
+}
+/* End of Item_param related */
+
+
void Item_copy_string::copy()
{
String *res=item->val_str(&str_value);
@@ -304,23 +499,210 @@ String *Item_copy_string::val_str(String *str)
}
/*
-** Functions to convert item to field (for send_fields)
+ Functions to convert item to field (for send_fields)
*/
/* ARGSUSED */
bool Item::fix_fields(THD *thd,
- struct st_table_list *list)
+ struct st_table_list *list,
+ Item ** ref)
{
+ fixed= 1;
return 0;
}
-bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
+bool Item_asterisk_remover::fix_fields(THD *thd,
+ struct st_table_list *list,
+ Item ** ref)
+{
+ DBUG_ENTER("Item_asterisk_remover::fix_fields");
+
+ bool res= 1;
+ if (item)
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field_name[0] == '*')
+ {
+ Item_field *fitem= (Item_field*) item;
+ if (list)
+ if (!list->next || fitem->db_name || fitem->table_name)
+ {
+ TABLE_LIST *table= find_table_in_list(list,
+ fitem->db_name,
+ fitem->table_name);
+ if (table)
+ {
+ TABLE * tb= table->table;
+ if (find_table_in_list(table->next, fitem->db_name,
+ fitem->table_name) != 0 ||
+ tb->fields == 1)
+ {
+ if ((item= new Item_field(tb->field[0])))
+ {
+ res= 0;
+ tb->field[0]->query_id= thd->query_id;
+ tb->used_keys&= tb->field[0]->part_of_key;
+ tb->used_fields= tb->fields;
+ }
+ else
+ thd->fatal_error(); // can't create Item => out of memory
+ }
+ else
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ }
+ else
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name);
+ }
+ else
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ else
+ my_error(ER_NO_TABLES_USED, MYF(0));
+ }
+ else
+ res= item->fix_fields(thd, list, &item);
+ else
+ thd->fatal_error(); // no item given => out of memory
+ DBUG_RETURN(res);
+}
+
+bool Item_ref_on_list_position::fix_fields(THD *thd,
+ struct st_table_list *tables,
+ Item ** reference)
+{
+ if (select_lex->item_list.elements <= pos)
+ {
+ ref= 0;
+ my_error(ER_CARDINALITY_COL, MYF(0), pos);
+ return 1;
+ }
+ ref= select_lex->ref_pointer_array + pos;
+ return Item_ref_null_helper::fix_fields(thd, tables, reference);
+}
+
+double Item_ref_null_helper::val()
+{
+ double tmp= (*ref)->val_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+longlong Item_ref_null_helper::val_int()
+{
+ longlong tmp= (*ref)->val_int_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+String* Item_ref_null_helper::val_str(String* s)
+{
+ String* tmp= (*ref)->str_result(s);
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
+{
+ return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
+}
+
+bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!field) // If field is not checked
{
- Field *tmp;
- if (!(tmp=find_field_in_tables(thd,this,tables)))
- return 1;
+ TABLE_LIST *where= 0;
+ Field *tmp= (Field *)not_found_field;
+ if (outer_resolving ||
+ (tmp= find_field_in_tables(thd, this, tables, &where, 0)) ==
+ not_found_field)
+ {
+ /*
+ We can't find table field in table list of current select,
+ consequently we have to find it in outer subselect(s).
+ We can't join lists of outer & current select, because of scope
+ of view rules. For example if both tables (outer & current) have
+ field 'field' it is not mistake to refer to this field without
+ mention of table name, but if we join tables in one list it will
+ cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
+ */
+ SELECT_LEX *last= 0;
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0;
+#endif
+ Item **refer= (Item **)not_found_item;
+ uint counter;
+ // Prevent using outer fields in subselects, that is not supported now
+ SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
+ if (outer_resolving ||
+ cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
+ for (SELECT_LEX *sl=(outer_resolving?cursel:cursel->outer_select());
+ sl;
+ sl= sl->outer_select())
+ {
+ if ((tmp= find_field_in_tables(thd, this,
+ (last= sl)->get_table_list(), &where,
+ 0)) != not_found_field)
+ break;
+ if ((refer= find_item_in_list(this, sl->item_list, &counter,
+ REPORT_EXCEPT_NOT_FOUND)) !=
+ (Item **)not_found_item)
+ break;
+ if (sl->master_unit()->first_select()->linkage ==
+ DERIVED_TABLE_TYPE)
+ break; // do not look over derived table
+ }
+ if (!tmp)
+ return -1;
+ else if (!refer)
+ return 1;
+ else if (tmp == not_found_field && refer == (Item **)not_found_item)
+ {
+ // call to return error code
+ find_field_in_tables(thd, this, tables, &where, 1);
+ return -1;
+ }
+ else if (refer != (Item **)not_found_item)
+ {
+ if (!(*refer)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
+ }
+
+ Item_ref *r;
+ *ref= r= new Item_ref(last->ref_pointer_array + counter
+ , (char *)table_name,
+ (char *)field_name);
+ if (!r)
+ return 1;
+ if (r->fix_fields(thd, tables, ref) || r->check_cols(1))
+ return 1;
+ // store pointer on SELECT_LEX from which item is dependent
+ r->depended_from= last;
+ cursel->mark_as_dependent(last);
+ return 0;
+ }
+ else
+ {
+ // store pointer on SELECT_LEX from wich item is dependent
+ depended_from= last;
+ /*
+ Mark all selects from resolved to 1 before select where was
+ found table as depended (of select where was found table)
+ */
+ thd->lex.current_select->mark_as_dependent(last);
+ if (depended_from->having_fix_field)
+ {
+ Item_ref *rf;
+ *ref= rf= new Item_ref((where->db[0]?where->db:0),
+ (char *)where->alias,
+ (char *)field_name);
+ if (!rf)
+ return 1;
+ (rf)->outer_resolving= outer_resolving;
+ return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
+ }
+ }
+ }
+ else if (!tmp)
+ return -1;
+
set_field(tmp);
}
else if (thd && thd->set_query_id && field->query_id != thd->query_id)
@@ -331,15 +713,21 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
table->used_fields++;
table->used_keys&=field->part_of_key;
}
+ fixed= 1;
return 0;
}
void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type)
-{
- tmp_field->table_name=(char*) "";
- tmp_field->col_name=name;
+{
+ char *empty_name= (char*) "";
+ tmp_field->db_name= empty_name;
+ tmp_field->org_table_name= empty_name;
+ tmp_field->org_col_name= empty_name;
+ tmp_field->table_name= empty_name;
+ tmp_field->col_name= name;
+ tmp_field->charsetnr= charset()->number;
tmp_field->flags=maybe_null ? 0 : NOT_NULL_FLAG;
tmp_field->type=field_type;
tmp_field->length=max_length;
@@ -348,65 +736,24 @@ void Item::init_make_field(Send_field *tmp_field,
tmp_field->flags |= UNSIGNED_FLAG;
}
-/* ARGSUSED */
-void Item_field::make_field(Send_field *tmp_field)
-{
- field->make_field(tmp_field);
- if (name)
- tmp_field->col_name=name; // Use user supplied name
-}
-
-void Item_int::make_field(Send_field *tmp_field)
+void Item::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
+ init_make_field(tmp_field, field_type());
}
-void Item_uint::make_field(Send_field *tmp_field)
+enum_field_types Item::field_type() const
{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
- tmp_field->flags|= UNSIGNED_FLAG;
- unsigned_flag=1;
+ return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
+ (result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
+ FIELD_TYPE_DOUBLE);
}
-void Item_real::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
-}
-
-void Item_string::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_STRING);
-}
-
-void Item_datetime::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
-}
-
-
-void Item_null::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_NULL);
- tmp_field->length=4;
-}
-
-
-void Item_func::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
- FIELD_TYPE_VAR_STRING :
- (result_type() == INT_RESULT) ?
- FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
-}
-
-void Item_avg_field::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
-}
-
-void Item_std_field::make_field(Send_field *tmp_field)
+/* ARGSUSED */
+void Item_field::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
+ field->make_field(tmp_field);
+ if (name)
+ tmp_field->col_name=name; // Use user supplied name
}
/*
@@ -429,7 +776,7 @@ void Item_field::save_org_in_field(Field *to)
}
}
-bool Item_field::save_in_field(Field *to, bool no_conversions)
+int Item_field::save_in_field(Field *to, bool no_conversions)
{
if (result_field->is_null())
{
@@ -445,6 +792,7 @@ bool Item_field::save_in_field(Field *to, bool no_conversions)
return 0;
}
+
/*
Store null in field
@@ -461,7 +809,7 @@ bool Item_field::save_in_field(Field *to, bool no_conversions)
1 Field doesn't support NULL values and can't handle 'field = NULL'
*/
-bool Item_null::save_in_field(Field *field, bool no_conversions)
+int Item_null::save_in_field(Field *field, bool no_conversions)
{
return set_field_to_null_with_conversions(field, no_conversions);
}
@@ -479,27 +827,29 @@ bool Item_null::save_in_field(Field *field, bool no_conversions)
1 Field doesn't support NULL values
*/
-bool Item_null::save_safe_in_field(Field *field)
+int Item_null::save_safe_in_field(Field *field)
{
return set_field_to_null(field);
}
-bool Item::save_in_field(Field *field, bool no_conversions)
+int Item::save_in_field(Field *field, bool no_conversions)
{
+ int error;
if (result_type() == STRING_RESULT ||
result_type() == REAL_RESULT &&
field->result_type() == STRING_RESULT)
{
String *result;
+ CHARSET_INFO *cs=charset();
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
- str_value.set_quick(buff,sizeof(buff));
+ str_value.set_quick(buff,sizeof(buff),cs);
result=val_str(&str_value);
if (null_value)
return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
- field->store(result->ptr(),result->length());
- str_value.set_quick(0, 0);
+ error=field->store(result->ptr(),result->length(),cs);
+ str_value.set_quick(0, 0, cs);
}
else if (result_type() == REAL_RESULT)
{
@@ -507,7 +857,7 @@ bool Item::save_in_field(Field *field, bool no_conversions)
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- field->store(nr);
+ error=field->store(nr);
}
else
{
@@ -515,41 +865,40 @@ bool Item::save_in_field(Field *field, bool no_conversions)
if (null_value)
return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
- field->store(nr);
+ error=field->store(nr);
}
- return 0;
+ return (error) ? -1 : 0;
}
-bool Item_string::save_in_field(Field *field, bool no_conversions)
+int Item_string::save_in_field(Field *field, bool no_conversions)
{
String *result;
result=val_str(&str_value);
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- field->store(result->ptr(),result->length());
- return 0;
+ return (field->store(result->ptr(),result->length(),charset())) ? -1 : 0;
}
-bool Item_int::save_in_field(Field *field, bool no_conversions)
+
+int Item_int::save_in_field(Field *field, bool no_conversions)
{
longlong nr=val_int();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- field->store(nr);
- return 0;
+ return (field->store(nr)) ? -1 : 0;
}
-bool Item_real::save_in_field(Field *field, bool no_conversions)
+
+int Item_real::save_in_field(Field *field, bool no_conversions)
{
double nr=val();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- field->store(nr);
- return 0;
+ return (field->store(nr)) ? -1 : 0;
}
/****************************************************************************
@@ -572,7 +921,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
char *ptr=(char*) sql_alloc(max_length+1);
if (!ptr)
return;
- str_value.set(ptr,max_length);
+ str_value.set(ptr,max_length,&my_charset_bin);
char *end=ptr+max_length;
if (max_length*2 != str_length)
*ptr++=char_val(*str++); // Not even, assume 0 prefix
@@ -582,7 +931,6 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
str+=2;
}
*ptr=0; // Keep purify happy
- binary=1; // Binary is default
}
longlong Item_varbinary::val_int()
@@ -597,46 +945,135 @@ longlong Item_varbinary::val_int()
}
-bool Item_varbinary::save_in_field(Field *field, bool no_conversions)
+int Item_varbinary::save_in_field(Field *field, bool no_conversions)
{
+ int error;
field->set_notnull();
if (field->result_type() == STRING_RESULT)
{
- field->store(str_value.ptr(),str_value.length());
+ error=field->store(str_value.ptr(),str_value.length(),charset());
}
else
{
longlong nr=val_int();
- field->store(nr);
+ error=field->store(nr);
}
- return 0;
+ return (error) ? -1 : 0;
}
-void Item_varbinary::make_field(Send_field *tmp_field)
+/*
+ Pack data in buffer for sending
+*/
+
+bool Item_null::send(Protocol *protocol, String *packet)
{
- init_make_field(tmp_field,FIELD_TYPE_STRING);
+ return protocol->store_null();
}
/*
-** pack data in buffer for sending
+ This is only called from items that is not of type item_field
*/
-bool Item::send(THD *thd, String *packet)
+bool Item::send(Protocol *protocol, String *buffer)
{
- char buff[MAX_FIELD_WIDTH];
- CONVERT *convert;
- String s(buff,sizeof(buff)),*res;
- if (!(res=val_str(&s)))
- return net_store_null(packet);
- if ((convert=thd->variables.convert_set))
- return convert->store(packet,res->ptr(),res->length());
- return net_store_data(packet,res->ptr(),res->length());
+ bool result;
+ enum_field_types type;
+ LINT_INIT(result);
+
+ switch ((type=field_type())) {
+ default:
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ {
+ String *res;
+ if ((res=val_str(buffer)))
+ result= protocol->store(res->ptr(),res->length());
+ break;
+ }
+ case MYSQL_TYPE_TINY:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_tiny(nr);
+ break;
+ }
+ case MYSQL_TYPE_SHORT:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_short(nr);
+ break;
+ }
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_long(nr);
+ break;
+ }
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong nr;
+ nr= val_int();
+ if (!null_value)
+ result= protocol->store_longlong(nr, unsigned_flag);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double nr;
+ nr= val();
+ if (!null_value)
+ result= protocol->store(nr, decimals, buffer);
+ break;
+ }
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ TIME tm;
+ get_date(&tm, 1);
+ if (!null_value)
+ {
+ if (type == MYSQL_TYPE_DATE)
+ return protocol->store_date(&tm);
+ else
+ result= protocol->store(&tm);
+ }
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ {
+ TIME tm;
+ get_time(&tm);
+ if (!null_value)
+ result= protocol->store_time(&tm);
+ break;
+ }
+ }
+ if (null_value)
+ result= protocol->store_null();
+ return result;
}
-bool Item_null::send(THD *thd, String *packet)
+
+bool Item_field::send(Protocol *protocol, String *buffer)
{
- return net_store_null(packet);
+ return protocol->store(result_field);
}
/*
@@ -644,20 +1081,181 @@ bool Item_null::send(THD *thd, String *packet)
Find field in select list having the same name
*/
-bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables)
+bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
+ uint counter;
if (!ref)
{
- if (!(ref=find_item_in_list(this,thd->lex.select->item_list)))
+ TABLE_LIST *where= 0;
+ SELECT_LEX *sl= (outer_resolving?
+ thd->lex.current_select->select_lex():
+ thd->lex.current_select->outer_select());
+ /*
+ Finding only in current select will be performed for selects that have
+ not outer one and for derived tables (which not support using outer
+ fields for now)
+ */
+ if (outer_resolving ||
+ (ref= find_item_in_list(this,
+ *(thd->lex.current_select->get_item_list()),
+ &counter,
+ ((sl &&
+ thd->lex.current_select->master_unit()->
+ first_select()->linkage !=
+ DERIVED_TABLE_TYPE) ?
+ REPORT_EXCEPT_NOT_FOUND :
+ REPORT_ALL_ERRORS))) ==
+ (Item **)not_found_item)
+ {
+ Field *tmp= (Field*) not_found_field;
+ /*
+ We can't find table field in table list of current select,
+ consequently we have to find it in outer subselect(s).
+ We can't join lists of outer & current select, because of scope
+ of view rules. For example if both tables (outer & current) have
+ field 'field' it is not mistake to refer to this field without
+ mention of table name, but if we join tables in one list it will
+ cause error ER_NON_UNIQ_ERROR in find_item_in_list.
+ */
+ SELECT_LEX *last=0;
+ for ( ; sl ; sl= sl->outer_select())
+ {
+ if ((ref= find_item_in_list(this, (last= sl)->item_list,
+ &counter,
+ REPORT_EXCEPT_NOT_FOUND)) !=
+ (Item **)not_found_item)
+ break;
+ if ((tmp= find_field_in_tables(thd, this,
+ sl->get_table_list(), &where,
+ 0)) != not_found_field)
+ break;
+ if (sl->master_unit()->first_select()->linkage ==
+ DERIVED_TABLE_TYPE)
+ break; // do not look over derived table
+ }
+
+ if (!ref)
+ return 1;
+ else if (!tmp)
+ return -1;
+ else if (ref == (Item **)not_found_item && tmp == not_found_field)
+ {
+ // Call to report error
+ find_item_in_list(this,
+ *(thd->lex.current_select->get_item_list()),
+ &counter,
+ REPORT_ALL_ERRORS);
+ ref= 0;
+ return 1;
+ }
+ else if (tmp != not_found_field)
+ {
+ ref= 0; // To prevent "delete *ref;" on ~Item_erf() of this item
+ Item_field* f;
+ if (!((*reference)= f= new Item_field(tmp)))
+ return 1;
+ // store pointer on SELECT_LEX from wich item is dependent
+ f->depended_from= last;
+ thd->lex.current_select->mark_as_dependent(last);
+ return 0;
+ }
+ else
+ {
+ if (!(*ref)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
+ }
+ /*
+ depended_from: pointer on SELECT_LEX from wich item is dependent
+ */
+ ref= (depended_from= last)->ref_pointer_array + counter;
+ thd->lex.current_select->mark_as_dependent(last);
+ }
+ }
+ else if (!ref)
return 1;
- max_length= (*ref)->max_length;
- maybe_null= (*ref)->maybe_null;
- decimals= (*ref)->decimals;
- binary= (*ref)->binary;
+ else
+ {
+ if (!(*ref)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
+ }
+ ref= thd->lex.current_select->ref_pointer_array + counter;
+ }
}
+
+ if (((*ref)->with_sum_func &&
+ (depended_from ||
+ !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
+ thd->lex.current_select->select_lex()->having_fix_field))) ||
+ !(*ref)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ ((*ref)->with_sum_func?
+ "reference on group function":
+ "forward reference in item list"));
+ return 1;
+ }
+ max_length= (*ref)->max_length;
+ maybe_null= (*ref)->maybe_null;
+ decimals= (*ref)->decimals;
+ fixed= 1;
+ if (ref && (*ref)->check_cols(1))
+ return 1;
return 0;
}
+bool Item_default_value::eq(const Item *item, bool binary_cmp) const
+{
+ return item->type() == DEFAULT_VALUE_ITEM &&
+ ((Item_default_value *)item)->arg->eq(arg, binary_cmp);
+}
+
+bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items)
+{
+ if (!arg)
+ return false;
+ bool res= arg->fix_fields(thd, table_list, items);
+ if (res)
+ return res;
+ /* arg->type() can be only REF_ITEM or FIELD_ITEM for it defined as
+ simple_ident in sql_yacc.yy
+ */
+ if (arg->type() == REF_ITEM)
+ {
+ Item_ref *ref= (Item_ref *)arg;
+ if (ref->ref[0]->type() != FIELD_ITEM)
+ {
+ return 1;
+ }
+ arg= ref->ref[0];
+ }
+ Item_field *field_arg= (Item_field *)arg;
+ Field *def_field= (Field*) sql_alloc(field_arg->field->size_of());
+ if (!def_field)
+ return 1;
+ memcpy(def_field, field_arg->field, field_arg->field->size_of());
+ def_field->move_field(def_field->table->default_values() -
+ def_field->table->record[0]);
+ set_field(def_field);
+ return 0;
+}
+
+void Item_default_value::print(String *str)
+{
+ if (!arg)
+ {
+ str->append("DEFAULT");
+ return;
+ }
+ str->append("DEFAULT(");
+ arg->print(str);
+ str->append(')');
+}
/*
If item is a const function, calculate it and return a const item
@@ -670,6 +1268,8 @@ Item_result item_cmp_type(Item_result a,Item_result b)
return STRING_RESULT;
else if (a == INT_RESULT && b == INT_RESULT)
return INT_RESULT;
+ else if (a == ROW_RESULT || b == ROW_RESULT)
+ return ROW_RESULT;
else
return REAL_RESULT;
}
@@ -686,7 +1286,7 @@ Item *resolve_const_item(Item *item,Item *comp_item)
if (res_type == STRING_RESULT)
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff)),*result;
+ String tmp(buff,sizeof(buff),&my_charset_bin),*result;
result=item->val_str(&tmp);
if (item->null_value)
{
@@ -700,7 +1300,7 @@ Item *resolve_const_item(Item *item,Item *comp_item)
#ifdef DELETE_ITEMS
delete item;
#endif
- return new Item_string(name,tmp_str,length);
+ return new Item_string(name,tmp_str,length,result->charset());
}
if (res_type == INT_RESULT)
{
@@ -741,8 +1341,8 @@ bool field_is_equal_to_item(Field *field,Item *item)
{
char item_buff[MAX_FIELD_WIDTH];
char field_buff[MAX_FIELD_WIDTH];
- String item_tmp(item_buff,sizeof(item_buff)),*item_result;
- String field_tmp(field_buff,sizeof(field_buff));
+ String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result;
+ String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin);
item_result=item->val_str(&item_tmp);
if (item->null_value)
return 1; // This must be true
@@ -757,6 +1357,143 @@ bool field_is_equal_to_item(Field *field,Item *item)
return result == field->val_real();
}
+Item_cache* Item_cache::get_cache(Item_result type)
+{
+ switch (type)
+ {
+ case INT_RESULT:
+ return new Item_cache_int();
+ case REAL_RESULT:
+ return new Item_cache_real();
+ case STRING_RESULT:
+ return new Item_cache_str();
+ case ROW_RESULT:
+ return new Item_cache_row();
+ default:
+ // should never be in real life
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+void Item_cache_str::store(Item *item)
+{
+ str_value.set(buffer, sizeof(buffer), item->charset());
+ value= item->str_result(&str_value);
+ if ((null_value= item->null_value))
+ value= 0;
+ else if (value != &str_value)
+ {
+ /*
+ We copy string value to avoid changing value if 'item' is table field
+ in queries like following (where t1.c is varchar):
+ select a,
+ (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),
+ (select c from t1 where a=t2.a)
+ from t2;
+ */
+ str_value.copy(*value);
+ value= &str_value;
+ }
+
+}
+double Item_cache_str::val()
+{
+ int err;
+ if (value)
+ return my_strntod(value->charset(), (char*) value->ptr(),
+ value->length(), (char**) 0, &err);
+ else
+ return (double)0;
+}
+longlong Item_cache_str::val_int()
+{
+ int err;
+ if (value)
+ return my_strntoll(value->charset(), value->ptr(),
+ value->length(), 10, (char**) 0, &err);
+ else
+ return (longlong)0;
+}
+
+bool Item_cache_row::allocate(uint num)
+{
+ item_count= num;
+ THD *thd= current_thd;
+ return (!(values=
+ (Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count)));
+}
+
+bool Item_cache_row::setup(Item * item)
+{
+ if (!values && allocate(item->cols()))
+ return 1;
+ for (uint i= 0; i < item_count; i++)
+ {
+ Item *el= item->el(i);
+ Item_cache *tmp;
+ if (!(tmp= values[i]= Item_cache::get_cache(el->result_type())))
+ return 1;
+ tmp->setup(el);
+ }
+ return 0;
+}
+
+void Item_cache_row::store(Item * item)
+{
+ null_value= 0;
+ item->bring_value();
+ for (uint i= 0; i < item_count; i++)
+ {
+ values[i]->store(item->el(i));
+ null_value|= values[i]->null_value;
+ }
+}
+
+void Item_cache_row::illegal_method_call(const char *method)
+{
+ DBUG_ENTER("Item_cache_row::illegal_method_call");
+ DBUG_PRINT("error", ("!!! %s method was called for row item", method));
+ DBUG_ASSERT(0);
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ DBUG_VOID_RETURN;
+}
+
+bool Item_cache_row::check_cols(uint c)
+{
+ if (c != item_count)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), c);
+ return 1;
+ }
+ return 0;
+}
+
+bool Item_cache_row::null_inside()
+{
+ for (uint i= 0; i < item_count; i++)
+ {
+ if (values[i]->cols() > 1)
+ {
+ if (values[i]->null_inside())
+ return 1;
+ }
+ else
+ {
+ values[i]->val_int();
+ if (values[i]->null_value)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void Item_cache_row::bring_value()
+{
+ for (uint i= 0; i < item_count; i++)
+ values[i]->bring_value();
+ return;
+}
/*****************************************************************************
** Instantiate templates
diff --git a/sql/item.h b/sql/item.h
index c669c266f0f..531817c4844 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-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
@@ -19,20 +19,25 @@
#pragma interface /* gcc class implementation */
#endif
+class Protocol;
struct st_table_list;
-void item_init(void); /* Init item functions */
+void item_init(void); /* Init item functions */
class Item {
- Item(const Item &); /* Prevent use of these */
+ uint loop_id; /* Used to find selfrefering loops */
+ Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
- enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
- INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
- COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
- PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM};
+ enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
+ INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
+ COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
+ PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
+ FIELD_VARIANCE_ITEM, CONST_ITEM,
+ SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
+
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
String str_value; /* used to store value */
@@ -42,31 +47,38 @@ public:
uint8 marker,decimals;
my_bool maybe_null; /* If item may be null */
my_bool null_value; /* if item is null */
- my_bool binary;
my_bool unsigned_flag;
my_bool with_sum_func;
-
+ my_bool fixed; /* If item fixed with fix_fields */
// alloc & destruct is done as start of select using sql_alloc
Item();
+ /*
+ Constructor used by Item_field, Item_ref & agregate (sum) functions.
+ Used for duplicating lists in processing queries with temporary
+ tables
+ */
+ Item(THD *thd, Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */
- void set_name(char* str,uint length=0);
+ void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
- virtual bool fix_fields(THD *,struct st_table_list *);
- virtual bool save_in_field(Field *field, bool no_conversions);
+ virtual void make_field(Send_field *field);
+ virtual bool fix_fields(THD *, struct st_table_list *, Item **);
+ virtual int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field, 1); }
- virtual bool save_safe_in_field(Field *field)
+ virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); }
- virtual bool send(THD *thd, String *str);
+ virtual bool send(Protocol *protocol, String *str);
virtual bool eq(const Item *, bool binary_cmp) const;
virtual Item_result result_type () const { return REAL_RESULT; }
+ virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
virtual double val()=0;
virtual longlong val_int()=0;
virtual String *val_str(String*)=0;
- virtual void make_field(Send_field *field)=0;
- virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; }
+ virtual Field *tmp_table_field() { return 0; }
+ virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); }
@@ -80,31 +92,56 @@ public:
virtual bool const_item() const { return used_tables() == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); }
virtual void update_used_tables() {}
- virtual void split_sum_func(List<Item> &fields) {}
+ virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {}
virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime);
- virtual bool is_null() { return 0; }
- virtual unsigned int size_of()= 0;
+ virtual bool is_null() { return 0; };
virtual void top_level_item() {}
virtual void set_result_field(Field *field) {}
virtual bool is_result_field() { return 0; }
virtual void save_in_result_field(bool no_conversions) {}
virtual void no_rows_in_result() {}
+ virtual Item *copy_or_same(THD *thd) { return this; }
+ virtual Item *real_item() { return this; }
+ virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
+
+ virtual bool binary() const
+ { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
+ CHARSET_INFO *thd_charset() const;
+ CHARSET_INFO *charset() const { return str_value.charset(); };
+ void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
+ virtual void set_outer_resolving() {}
+
+ // Row emulation
+ virtual uint cols() { return 1; }
+ virtual Item* el(uint i) { return this; }
+ virtual Item** addr(uint i) { return 0; }
+ virtual bool check_cols(uint c);
+ // It is not row => null inside is impossible
+ virtual bool null_inside() { return 0; }
+ // used in row subselects to get value of elements
+ virtual void bring_value() {}
};
+class st_select_lex;
class Item_ident :public Item
{
public:
const char *db_name;
const char *table_name;
const char *field_name;
+ st_select_lex *depended_from;
+ bool outer_resolving; /* used for items from reduced subselect */
Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
- :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par)
+ :db_name(db_name_par), table_name(table_name_par),
+ field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; }
+ // Constructor used by Item_field & Item_ref (see Item comment)
+ Item_ident(THD *thd, Item_ident &item);
const char *full_name() const;
- unsigned int size_of() { return sizeof(*this);}
+ void set_outer_resolving() { outer_resolving= 1; }
};
@@ -119,6 +156,8 @@ public:
const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
{}
+ // Constructor need to process subselect with temporary tables (see Item)
+ Item_field(THD *thd, Item_field &item);
Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
@@ -128,27 +167,29 @@ public:
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
- bool send(THD *thd, String *str_arg)
- {
- return result_field->send(thd,str_arg);
- }
- void make_field(Send_field *field);
- bool fix_fields(THD *,struct st_table_list *);
- bool save_in_field(Field *field,bool no_conversions);
+ bool send(Protocol *protocol, String *str_arg);
+ bool fix_fields(THD *, struct st_table_list *, Item **);
+ void make_field(Send_field *tmp_field);
+ int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
table_map used_tables() const;
enum Item_result result_type () const
{
return field->result_type();
}
- Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
+ enum_field_types field_type() const
+ {
+ return field->type();
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); }
- unsigned int size_of() { return sizeof(*this);}
+ Item *get_tmp_table_item(THD *thd);
+ friend class Item_default_value;
};
-
class Item_null :public Item
{
public:
@@ -159,18 +200,64 @@ public:
double val();
longlong val_int();
String *val_str(String *str);
- void make_field(Send_field *field);
- bool save_in_field(Field *field, bool no_conversions);
- bool save_safe_in_field(Field *field);
- enum Item_result result_type () const
- { return STRING_RESULT; }
- bool send(THD *thd, String *str);
+ int save_in_field(Field *field, bool no_conversions);
+ int save_safe_in_field(Field *field);
+ bool send(Protocol *protocol, String *str);
+ enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
+ bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
+ {
+ bool res= Item::fix_fields(thd, list, item);
+ max_length=0;
+ return res;
+ }
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
- unsigned int size_of() { return sizeof(*this);}
};
+class Item_param :public Item
+{
+public:
+ longlong int_value;
+ double real_value;
+ TIME ltime;
+ enum Item_result item_result_type;
+ enum Type item_type;
+ enum enum_field_types buffer_type;
+ bool item_is_time;
+ my_bool long_data_supplied;
+
+ Item_param(char *name_par=0)
+ {
+ name= name_par ? name_par : (char*) "?";
+ long_data_supplied= false;
+ item_type= STRING_ITEM;
+ item_result_type = STRING_RESULT;
+ item_is_time= false;
+ }
+ enum Type type() const { return item_type; }
+ double val();
+ longlong val_int();
+ String *val_str(String*);
+ int save_in_field(Field *field, bool no_conversions);
+ void set_null();
+ void set_int(longlong i);
+ void set_double(double i);
+ void set_value(const char *str, uint length);
+ void set_long_str(const char *str, ulong length);
+ void set_long_binary(const char *str, ulong length);
+ void set_longdata(const char *str, ulong length);
+ void set_long_end();
+ void set_time(TIME *tm, timestamp_type type);
+ bool get_time(TIME *tm);
+ void reset() {}
+ void (*setup_param_func)(Item_param *param, uchar **pos);
+ enum Item_result result_type () const
+ { return item_result_type; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ Item *new_item() { return new Item_param(name); }
+};
class Item_int :public Item
{
@@ -189,16 +276,15 @@ public:
(longlong) strtoull(str_arg,(char**) 0,10))
{ max_length= (uint) strlen(str_arg); name=(char*) str_arg;}
enum Type type() const { return INT_ITEM; }
- virtual enum Item_result result_type () const { return INT_RESULT; }
+ enum Item_result result_type () const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
longlong val_int() { return value; }
double val() { return (double) value; }
String *val_str(String*);
- void make_field(Send_field *field);
- bool save_in_field(Field *field, bool no_conversions);
+ int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_int(name,value,max_length); }
void print(String *str);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -210,10 +296,14 @@ public:
Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
double val() { return ulonglong2double(value); }
String *val_str(String*);
- void make_field(Send_field *field);
Item *new_item() { return new Item_uint(name,max_length); }
+ bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
+ {
+ bool res= Item::fix_fields(thd, list, item);
+ unsigned_flag= 1;
+ return res;
+ }
void print(String *str);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -236,15 +326,14 @@ public:
max_length=length;
}
Item_real(double value_par) :value(value_par) {}
- bool save_in_field(Field *field, bool no_conversions);
+ int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
String *val_str(String*);
- void make_field(Send_field *field);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_real(name,value,decimals,max_length); }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -256,84 +345,87 @@ public:
decimals=NOT_FIXED_DEC;
max_length=DBL_DIG+8;
}
- unsigned int size_of() { return sizeof(*this);}
};
class Item_string :public Item
{
public:
- Item_string(const char *str,uint length)
+ Item_string(const char *str,uint length,CHARSET_INFO *cs)
{
- str_value.set(str,length);
+ str_value.set(str,length,cs);
max_length=length;
name=(char*) str_value.ptr();
decimals=NOT_FIXED_DEC;
}
- Item_string(const char *name_par,const char *str,uint length)
+ Item_string(const char *name_par, const char *str, uint length,
+ CHARSET_INFO *cs)
{
- str_value.set(str,length);
+ str_value.set(str,length,cs);
max_length=length;
name=(char*) name_par;
decimals=NOT_FIXED_DEC;
}
~Item_string() {}
enum Type type() const { return STRING_ITEM; }
- double val() { return atof(str_value.ptr()); }
- longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); }
+ double val()
+ {
+ int err;
+ return my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), (char**) 0, &err);
+ }
+ longlong val_int()
+ {
+ int err;
+ return my_strntoll(str_value.charset(), str_value.ptr(),
+ str_value.length(), 10, (char**) 0, &err);
+ }
String *val_str(String*) { return (String*) &str_value; }
- bool save_in_field(Field *field, bool no_conversions);
- void make_field(Send_field *field);
+ int save_in_field(Field *field, bool no_conversions);
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const;
- Item *new_item() { return new Item_string(name,str_value.ptr(),max_length); }
- String *const_string() { return &str_value; }
- inline void append(char *str,uint length) { str_value.append(str,length); }
- void print(String *str);
- unsigned int size_of() { return sizeof(*this);}
-};
-
-
-/* For INSERT ... VALUES (DEFAULT) */
-
-class Item_default :public Item
-{
-public:
- Item_default() { name= (char*) "DEFAULT"; }
- enum Type type() const { return DEFAULT_ITEM; }
- void make_field(Send_field *field) {}
- bool save_in_field(Field *field, bool no_conversions)
+ Item *new_item()
{
- field->set_default();
- return 0;
+ return new Item_string(name, str_value.ptr(), max_length,
+ default_charset_info);
}
- virtual double val() { return 0.0; }
- virtual longlong val_int() { return 0; }
- virtual String *val_str(String *str) { return 0; }
- bool basic_const_item() const { return 1; }
- unsigned int size_of() { return sizeof(*this);}
+ String *const_string() { return &str_value; }
+ inline void append(char *str, uint length) { str_value.append(str, length); }
+ void print(String *str);
};
-
/* for show tables */
class Item_datetime :public Item_string
{
public:
- Item_datetime(const char *item_name): Item_string(item_name,"",0)
+ Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info)
{ max_length=19;}
- void make_field(Send_field *field);
- unsigned int size_of() { return sizeof(*this);}
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
};
class Item_empty_string :public Item_string
{
public:
- Item_empty_string(const char *header,uint length) :Item_string("",0)
+ Item_empty_string(const char *header,uint length) :Item_string("",0,default_charset_info)
{ name=(char*) header; max_length=length;}
- unsigned int size_of() { return sizeof(*this);}
};
+class Item_return_int :public Item_int
+{
+ enum_field_types int_field_type;
+public:
+ Item_return_int(const char *name, uint length,
+ enum_field_types field_type_arg)
+ :Item_int(name, 0, length), int_field_type(field_type_arg)
+ {
+ unsigned_flag=1;
+ }
+ enum_field_types field_type() const { return int_field_type; }
+};
+
+
class Item_varbinary :public Item
{
public:
@@ -343,10 +435,9 @@ public:
double val() { return (double) Item_varbinary::val_int(); }
longlong val_int();
String *val_str(String*) { return &str_value; }
- bool save_in_field(Field *field, bool no_conversions);
- void make_field(Send_field *field);
+ int save_in_field(Field *field, bool no_conversions);
enum Item_result result_type () const { return INT_RESULT; }
- unsigned int size_of() { return sizeof(*this);}
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
};
@@ -355,11 +446,15 @@ class Item_result_field :public Item /* Item with result field */
public:
Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {}
+ // Constructor used for Item_sum (see Item comment)
+ Item_result_field(THD *thd, Item_result_field &item):
+ Item(thd, item), result_field(item.result_field)
+ {}
~Item_result_field() {} /* Required with gcc 2.95 */
- Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg) { return result_field; }
table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0;
- unsigned int size_of() { return sizeof(*this);}
void set_result_field(Field *field) { result_field= field; }
bool is_result_field() { return 1; }
void save_in_result_field(bool no_conversions)
@@ -374,14 +469,18 @@ class Item_ref :public Item_ident
public:
Field *result_field; /* Save result here */
Item **ref;
- Item_ref(char *db_par,char *table_name_par,char *field_name_par)
+ Item_ref(const char *db_par, const char *table_name_par,
+ const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
- Item_ref(Item **item, char *table_name_par,char *field_name_par)
+ Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
+ // Constructor need to process subselect with temporary tables (see Item)
+ Item_ref(THD *thd, Item_ref &item)
+ :Item_ident(thd, item), ref(item.ref) {}
enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const
- { return (*ref)->eq(item, binary_cmp); }
- ~Item_ref() { if (ref) delete *ref; }
+ { return ref && (*ref)->eq(item, binary_cmp); }
+ ~Item_ref() { if (ref && (*ref) != this) delete *ref; }
double val()
{
double tmp=(*ref)->val_result();
@@ -409,25 +508,84 @@ public:
{
return (null_value=(*ref)->get_date(ltime,fuzzydate));
}
- bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
+ bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); }
- bool fix_fields(THD *,struct st_table_list *);
- bool save_in_field(Field *field, bool no_conversions)
+ bool fix_fields(THD *, struct st_table_list *, Item **);
+ int save_in_field(Field *field, bool no_conversions)
{ return (*ref)->save_in_field(field, no_conversions); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
+ enum_field_types field_type() const { return (*ref)->field_type(); }
table_map used_tables() const { return (*ref)->used_tables(); }
- unsigned int size_of() { return sizeof(*this);}
void set_result_field(Field *field) { result_field= field; }
bool is_result_field() { return 1; }
void save_in_result_field(bool no_conversions)
{
(*ref)->save_in_field(result_field, no_conversions);
}
+ Item *real_item() { return *ref; }
+};
+
+class Item_in_subselect;
+class Item_ref_null_helper: public Item_ref
+{
+protected:
+ Item_in_subselect* owner;
+public:
+ Item_ref_null_helper(Item_in_subselect* master, Item **item,
+ const char *table_name_par, const char *field_name_par):
+ Item_ref(item, table_name_par, field_name_par), owner(master) {}
+ double val();
+ longlong val_int();
+ String* val_str(String* s);
+ bool get_date(TIME *ltime, bool fuzzydate);
};
/*
+ Used to find item in list of select items after '*' items processing.
+
+ Because item '*' can be used in item list. when we create
+ Item_ref_on_list_position we do not know how item list will be changed, but
+ we know number of item position (I mean queries like "select * from t").
+*/
+class Item_ref_on_list_position: public Item_ref_null_helper
+{
+protected:
+ /*
+ select_lex used for:
+ 1) receiving expanded variant of item list (to check max possible
+ number of elements);
+ 2) to have access to ref_pointer_array, via wich item will refered.
+ */
+ st_select_lex *select_lex;
+ uint pos;
+public:
+ Item_ref_on_list_position(Item_in_subselect* master,
+ st_select_lex *sl, uint num,
+ char *table_name, char *field_name):
+ Item_ref_null_helper(master, 0, table_name, field_name),
+ select_lex(sl), pos(num) {}
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref);
+};
+
+/*
+ To resolve '*' field moved to condition
+ and register NULL values
+*/
+class Item_asterisk_remover :public Item_ref_null_helper
+{
+ Item *item;
+public:
+ Item_asterisk_remover(Item_in_subselect *master, Item *it,
+ char *table, char *field):
+ Item_ref_null_helper(master, &item, table, field),
+ item(it)
+ {}
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref);
+};
+
+/*
The following class is used to optimize comparing of date columns
We need to save the original item, to be able to set the field to the
original value in 'opt_range'.
@@ -439,23 +597,27 @@ class Item_int_with_ref :public Item_int
public:
Item_int_with_ref(longlong i, Item *ref_arg) :Item_int(i), ref(ref_arg)
{}
- bool save_in_field(Field *field, bool no_conversions)
+ int save_in_field(Field *field, bool no_conversions)
{
return ref->save_in_field(field, no_conversions);
}
- unsigned int size_of() { return sizeof(*this);}
};
+#include "gstream.h"
+#include "spatial.h"
#include "item_sum.h"
#include "item_func.h"
+#include "item_row.h"
#include "item_cmpfunc.h"
#include "item_strfunc.h"
#include "item_timefunc.h"
#include "item_uniq.h"
+#include "item_subselect.h"
class Item_copy_string :public Item
{
+ enum enum_field_types cached_field_type;
public:
Item *item;
Item_copy_string(Item *i) :item(i)
@@ -464,21 +626,30 @@ public:
decimals=item->decimals;
max_length=item->max_length;
name=item->name;
+ cached_field_type= item->field_type();
}
~Item_copy_string() { delete item; }
enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return cached_field_type; }
double val()
- { return null_value ? 0.0 : atof(str_value.c_ptr()); }
+ {
+ int err;
+ return (null_value ? 0.0 :
+ my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(),NULL,&err));
+ }
longlong val_int()
- { return null_value ? LL(0) : strtoll(str_value.c_ptr(),(char**) 0,10); }
+ {
+ int err;
+ return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),10, (char**) 0,&err);
+ }
String *val_str(String*);
void make_field(Send_field *field) { item->make_field(field); }
void copy();
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
bool is_null() { return null_value; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -489,7 +660,6 @@ public:
Item_buff() :null_value(0) {}
virtual bool cmp(void)=0;
virtual ~Item_buff(); /*line -e1509 */
- unsigned int size_of() { return sizeof(*this);}
};
class Item_str_buff :public Item_buff
@@ -500,7 +670,6 @@ public:
Item_str_buff(Item *arg) :item(arg),value(arg->max_length) {}
bool cmp(void);
~Item_str_buff(); // Deallocate String:s
- unsigned int size_of() { return sizeof(*this);}
};
@@ -511,7 +680,6 @@ class Item_real_buff :public Item_buff
public:
Item_real_buff(Item *item_par) :item(item_par),value(0.0) {}
bool cmp(void);
- unsigned int size_of() { return sizeof(*this);}
};
class Item_int_buff :public Item_buff
@@ -521,7 +689,6 @@ class Item_int_buff :public Item_buff
public:
Item_int_buff(Item *item_par) :item(item_par),value(0) {}
bool cmp(void);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -538,7 +705,154 @@ public:
buff= (char*) sql_calloc(length=field->pack_length());
}
bool cmp(void);
- unsigned int size_of() { return sizeof(*this);}
+};
+
+class Item_default_value : public Item_field
+{
+public:
+ Item *arg;
+ Item_default_value() :
+ Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {}
+ Item_default_value(Item *a) :
+ Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ enum Type type() const { return DEFAULT_VALUE_ITEM; }
+ bool eq(const Item *item, bool binary_cmp) const;
+ bool fix_fields(THD *, struct st_table_list *, Item **);
+ void set_outer_resolving() { arg->set_outer_resolving(); }
+ void print(String *str);
+ virtual bool basic_const_item() const { return true; }
+ int save_in_field(Field *field, bool no_conversions)
+ {
+ if (!arg)
+ {
+ field->set_default();
+ return 0;
+ }
+ return Item_field::save_in_field(field, no_conversions);
+ }
+ table_map used_tables() const { return (table_map)0L; }
+};
+
+class Item_cache: public Item
+{
+ table_map used_table_map;
+public:
+ Item_cache(): used_table_map(0) {fixed= 1; null_value= 1;}
+
+ void set_used_tables(table_map map) { used_table_map= map; }
+
+ virtual bool allocate(uint i) { return 0; };
+ virtual bool setup(Item *) { return 0; };
+ virtual void store(Item *)= 0;
+ void set_len_n_dec(uint32 max_len, uint8 dec)
+ {
+ max_length= max_len;
+ decimals= dec;
+ }
+ enum Type type() const { return CACHE_ITEM; }
+ static Item_cache* get_cache(Item_result type);
+ table_map used_tables() const { return used_table_map; }
+};
+
+class Item_cache_int: public Item_cache
+{
+ longlong value;
+public:
+ Item_cache_int(): Item_cache() {}
+
+ void store(Item *item)
+ {
+ value= item->val_int_result();
+ null_value= item->null_value;
+ }
+ double val() { return (double) value; }
+ longlong val_int() { return value; }
+ String* val_str(String *str) { str->set(value, thd_charset()); return str; }
+ enum Item_result result_type() const { return INT_RESULT; }
+};
+
+class Item_cache_real: public Item_cache
+{
+ double value;
+public:
+ Item_cache_real(): Item_cache() {}
+
+ void store(Item *item)
+ {
+ value= item->val_result();
+ null_value= item->null_value;
+ }
+ double val() { return value; }
+ longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
+ String* val_str(String *str)
+ {
+ str->set(value, decimals, thd_charset());
+ return str;
+ }
+ enum Item_result result_type() const { return REAL_RESULT; }
+};
+
+class Item_cache_str: public Item_cache
+{
+ char buffer[80];
+ String *value;
+public:
+ Item_cache_str(): Item_cache() { }
+
+ void store(Item *item);
+ double val();
+ longlong val_int();
+ String* val_str(String *) { return value; }
+ enum Item_result result_type() const { return STRING_RESULT; }
+ CHARSET_INFO *charset() const { return value->charset(); };
+};
+
+class Item_cache_row: public Item_cache
+{
+ Item_cache **values;
+ uint item_count;
+public:
+ Item_cache_row(): Item_cache(), values(0), item_count(2) {}
+
+ /*
+ 'allocate' used only in row transformer, to preallocate space for row
+ cache.
+ */
+ bool allocate(uint num);
+ /*
+ 'setup' is needed only by row => it not called by simple row subselect
+ (only by IN subselect (in subselect optimizer))
+ */
+ bool setup(Item *item);
+ void store(Item *item);
+ void illegal_method_call(const char *);
+ void make_field(Send_field *)
+ {
+ illegal_method_call((const char*)"make_field");
+ };
+ double val()
+ {
+ illegal_method_call((const char*)"val");
+ return 0;
+ };
+ longlong val_int()
+ {
+ illegal_method_call((const char*)"val_int");
+ return 0;
+ };
+ String *val_str(String *)
+ {
+ illegal_method_call((const char*)"val_str");
+ return 0;
+ };
+ enum Item_result result_type() const { return ROW_RESULT; }
+
+ uint cols() { return item_count; }
+ Item* el(uint i) { return values[i]; }
+ Item** addr(uint i) { return (Item **) (values + i); }
+ bool check_cols(uint c);
+ bool null_inside();
+ void bring_value();
};
extern Item_buff *new_Item_buff(Item *item);
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index b55a4dc66a0..573d4ab17e3 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -56,7 +56,7 @@ bool Item_str_buff::cmp(void)
}
else if (null_value)
return 0; // new and old value was null
- else if (!item->binary)
+ else if (!item->binary())
tmp= sortcmp(&value,res) != 0;
else
tmp= stringcmp(&value,res) != 0;
@@ -99,7 +99,7 @@ bool Item_field_buff::cmp(void)
{
bool tmp= field->cmp(buff) != 0; // This is not a blob!
if (tmp)
- field->get_image(buff,length);
+ field->get_image(buff,length,field->charset());
if (null_value != field->is_null())
{
null_value= !null_value;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 55e8ef7c4b5..b189f34912c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-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
@@ -23,6 +23,30 @@
#include "mysql_priv.h"
#include <m_ctype.h>
+Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b)
+{
+ return new Item_func_eq(a, b);
+}
+Item_bool_func2* Item_bool_func2::ne_creator(Item *a, Item *b)
+{
+ return new Item_func_ne(a, b);
+}
+Item_bool_func2* Item_bool_func2::gt_creator(Item *a, Item *b)
+{
+ return new Item_func_gt(a, b);
+}
+Item_bool_func2* Item_bool_func2::lt_creator(Item *a, Item *b)
+{
+ return new Item_func_lt(a, b);
+}
+Item_bool_func2* Item_bool_func2::ge_creator(Item *a, Item *b)
+{
+ return new Item_func_ge(a, b);
+}
+Item_bool_func2* Item_bool_func2::le_creator(Item *a, Item *b)
+{
+ return new Item_func_le(a, b);
+}
/*
Test functions
@@ -42,14 +66,17 @@ longlong Item_func_not::val_int()
This is done when comparing DATE's of different formats and
also when comparing bigint to strings (in which case the string
is converted once to a bigint).
+
+ RESULT VALUES
+ 0 Can't convert item
+ 1 Item was replaced with an integer version of the item
*/
static bool convert_constant_item(Field *field, Item **item)
{
if ((*item)->const_item() && (*item)->type() != Item::INT_ITEM)
{
- if (!(*item)->save_in_field(field, 1) &&
- !((*item)->null_value))
+ if (!(*item)->save_in_field(field, 1) && !((*item)->null_value))
{
Item *tmp=new Item_int_with_ref(field->val_int(), *item);
if (tmp)
@@ -60,10 +87,9 @@ static bool convert_constant_item(Field *field, Item **item)
return 0;
}
-
void Item_bool_func2::fix_length_and_dec()
{
- max_length=1; // Function returns 0 or 1
+ max_length= 1; // Function returns 0 or 1
/*
As some compare functions are generated after sql_yacc,
@@ -79,7 +105,8 @@ void Item_bool_func2::fix_length_and_dec()
{
if (convert_constant_item(field,&args[1]))
{
- cmp_func= &Item_bool_func2::compare_int; // Works for all types.
+ cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
+ INT_RESULT); // Works for all types.
return;
}
}
@@ -91,164 +118,277 @@ void Item_bool_func2::fix_length_and_dec()
{
if (convert_constant_item(field,&args[0]))
{
- cmp_func= &Item_bool_func2::compare_int; // Works for all types.
+ cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
+ INT_RESULT); // Works for all types.
return;
}
}
}
- set_cmp_func(item_cmp_type(args[0]->result_type(),args[1]->result_type()));
+ set_cmp_func();
+ binary_cmp= args[0]->binary() || args[1]->binary();
}
-void Item_bool_func2::set_cmp_func(Item_result type)
+int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
{
- switch (type) {
- case STRING_RESULT:
- cmp_func=&Item_bool_func2::compare_string;
- break;
- case REAL_RESULT:
- cmp_func=&Item_bool_func2::compare_real;
- break;
- case INT_RESULT:
- cmp_func=&Item_bool_func2::compare_int;
- break;
+ owner= item;
+ func= comparator_matrix[type][(owner->functype() == Item_func::EQUAL_FUNC)?
+ 1:0];
+ if (type == ROW_RESULT)
+ {
+ uint n= (*a)->cols();
+ if (n != (*b)->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), n);
+ comparators= 0;
+ return 1;
+ }
+ if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n)))
+ for (uint i=0; i < n; i++)
+ {
+ if ((*a)->el(i)->cols() != (*b)->el(i)->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), (*a)->el(i)->cols());
+ return 1;
+ }
+ comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
+ }
+ else
+ return 1;
}
+ return 0;
}
-
-int Item_bool_func2::compare_string()
+int Arg_comparator::compare_string()
{
String *res1,*res2;
- if ((res1=args[0]->val_str(&tmp_value1)))
+ if ((res1= (*a)->val_str(&owner->tmp_value1)))
{
- if ((res2=args[1]->val_str(&tmp_value2)))
+ if ((res2= (*b)->val_str(&owner->tmp_value2)))
{
- null_value=0;
- return binary ? stringcmp(res1,res2) : sortcmp(res1,res2);
+ owner->null_value= 0;
+ return owner->binary_cmp ? stringcmp(res1,res2) : sortcmp(res1,res2);
}
}
- null_value=1;
+ owner->null_value= 1;
return -1;
}
-int Item_bool_func2::compare_real()
+int Arg_comparator::compare_e_string()
{
- double val1=args[0]->val();
- if (!args[0]->null_value)
+ String *res1,*res2;
+ res1= (*a)->val_str(&owner->tmp_value1);
+ res2= (*b)->val_str(&owner->tmp_value2);
+ if (!res1 || !res2)
+ return test(res1 == res2);
+ return (owner->binary_cmp ? test(stringcmp(res1, res2) == 0) :
+ test(sortcmp(res1, res2) == 0));
+}
+
+
+int Arg_comparator::compare_real()
+{
+ double val1= (*a)->val();
+ if (!(*a)->null_value)
{
- double val2=args[1]->val();
- if (!args[1]->null_value)
+ double val2= (*b)->val();
+ if (!(*b)->null_value)
{
- null_value=0;
+ owner->null_value= 0;
if (val1 < val2) return -1;
if (val1 == val2) return 0;
return 1;
}
}
- null_value=1;
+ owner->null_value= 1;
return -1;
}
+int Arg_comparator::compare_e_real()
+{
+ double val1= (*a)->val();
+ double val2= (*b)->val();
+ if ((*a)->null_value || (*b)->null_value)
+ return test((*a)->null_value && (*b)->null_value);
+ return test(val1 == val2);
+}
-int Item_bool_func2::compare_int()
+int Arg_comparator::compare_int()
{
- longlong val1=args[0]->val_int();
- if (!args[0]->null_value)
+ longlong val1= (*a)->val_int();
+ if (!(*a)->null_value)
{
- longlong val2=args[1]->val_int();
- if (!args[1]->null_value)
+ longlong val2= (*b)->val_int();
+ if (!(*b)->null_value)
{
- null_value=0;
+ owner->null_value= 0;
if (val1 < val2) return -1;
if (val1 == val2) return 0;
return 1;
}
}
- null_value=1;
+ owner->null_value= 1;
return -1;
}
+int Arg_comparator::compare_e_int()
+{
+ longlong val1= (*a)->val_int();
+ longlong val2= (*b)->val_int();
+ if ((*a)->null_value || (*b)->null_value)
+ return test((*a)->null_value && (*b)->null_value);
+ return test(val1 == val2);
+}
-longlong Item_func_eq::val_int()
+int Arg_comparator::compare_row()
{
- int value=(this->*cmp_func)();
- return value == 0 ? 1 : 0;
+ int res= 0;
+ (*a)->bring_value();
+ (*b)->bring_value();
+ uint n= (*a)->cols();
+ for (uint i= 0; i<n; i++)
+ {
+ if ((res= comparators[i].compare()))
+ return res;
+ if (owner->null_value)
+ return -1;
+ }
+ return res;
}
-/* Same as Item_func_eq, but NULL = NULL */
+int Arg_comparator::compare_e_row()
+{
+ int res= 0;
+ (*a)->bring_value();
+ (*b)->bring_value();
+ uint n= (*a)->cols();
+ for (uint i= 0; i<n; i++)
+ {
+ if ((res= comparators[i].compare()))
+ return 1;
+ }
+ return 1;
+}
-void Item_func_equal::fix_length_and_dec()
+bool Item_in_optimizer::preallocate_row()
{
- Item_bool_func2::fix_length_and_dec();
- cmp_result_type=item_cmp_type(args[0]->result_type(),args[1]->result_type());
- maybe_null=null_value=0;
+ return (!(cache= Item_cache::get_cache(ROW_RESULT)));
}
-longlong Item_func_equal::val_int()
+
+bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
+ Item ** ref)
{
- switch (cmp_result_type) {
- case STRING_RESULT:
+ if (args[0]->fix_fields(thd, tables, args))
+ return 1;
+ if (args[0]->maybe_null)
+ maybe_null=1;
+ /*
+ TODO: Check if following is right
+ (set_charset set type of result, not how compare should be used)
+ */
+ if (args[0]->binary())
+ set_charset(&my_charset_bin);
+ with_sum_func= args[0]->with_sum_func;
+ used_tables_cache= args[0]->used_tables();
+ const_item_cache= args[0]->const_item();
+ if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
+ return 1;
+ cache->setup(args[0]);
+ if (cache->cols() == 1)
+ cache->set_used_tables(RAND_TABLE_BIT);
+ else
{
- String *res1,*res2;
- res1=args[0]->val_str(&tmp_value1);
- res2=args[1]->val_str(&tmp_value2);
- if (!res1 || !res2)
- return test(res1 == res2);
- return (binary ? test(stringcmp(res1,res2) == 0) :
- test(sortcmp(res1,res2) == 0));
+ uint n= cache->cols();
+ for (uint i= 0; i < n; i++)
+ ((Item_cache *)cache->el(i))->set_used_tables(RAND_TABLE_BIT);
}
- case REAL_RESULT:
+ if (args[1]->fix_fields(thd, tables, args))
+ return 1;
+ Item_in_subselect * sub= (Item_in_subselect *)args[1];
+ if (args[0]->cols() != sub->engine->cols())
{
- double val1=args[0]->val();
- double val2=args[1]->val();
- if (args[0]->null_value || args[1]->null_value)
- return test(args[0]->null_value && args[1]->null_value);
- return test(val1 == val2);
+ my_error(ER_CARDINALITY_COL, MYF(0), args[0]->cols());
+ return 1;
}
- case INT_RESULT:
+ if (args[1]->maybe_null)
+ maybe_null=1;
+ with_sum_func= with_sum_func || args[1]->with_sum_func;
+ used_tables_cache|= args[1]->used_tables();
+ const_item_cache&= args[1]->const_item();
+ return 0;
+}
+
+longlong Item_in_optimizer::val_int()
+{
+ cache->store(args[0]);
+ if (cache->null_value)
{
- longlong val1=args[0]->val_int();
- longlong val2=args[1]->val_int();
- if (args[0]->null_value || args[1]->null_value)
- return test(args[0]->null_value && args[1]->null_value);
- return test(val1 == val2);
- }
+ null_value= 1;
+ return 0;
}
- return 0; // Impossible
+ longlong tmp= args[1]->val_int_result();
+ null_value= args[1]->null_value;
+ return tmp;
+}
+
+bool Item_in_optimizer::is_null()
+{
+ cache->store(args[0]);
+ return (null_value= (cache->null_value || args[1]->is_null()));
+}
+
+longlong Item_func_eq::val_int()
+{
+ int value= cmp.compare();
+ return value == 0 ? 1 : 0;
+}
+
+/* Same as Item_func_eq, but NULL = NULL */
+
+void Item_func_equal::fix_length_and_dec()
+{
+ Item_bool_func2::fix_length_and_dec();
+ maybe_null=null_value=0;
+ set_cmp_func();
}
+longlong Item_func_equal::val_int()
+{
+ return cmp.compare();
+}
longlong Item_func_ne::val_int()
{
- int value=(this->*cmp_func)();
+ int value= cmp.compare();
return value != 0 && !null_value ? 1 : 0;
}
longlong Item_func_ge::val_int()
{
- int value=(this->*cmp_func)();
+ int value= cmp.compare();
return value >= 0 ? 1 : 0;
}
longlong Item_func_gt::val_int()
{
- int value=(this->*cmp_func)();
+ int value= cmp.compare();
return value > 0 ? 1 : 0;
}
longlong Item_func_le::val_int()
{
- int value=(this->*cmp_func)();
+ int value= cmp.compare();
return value <= 0 && !null_value ? 1 : 0;
}
longlong Item_func_lt::val_int()
{
- int value=(this->*cmp_func)();
+ int value= cmp.compare();
return value < 0 && !null_value ? 1 : 0;
}
@@ -262,7 +402,7 @@ longlong Item_func_strcmp::val_int()
null_value=1;
return 0;
}
- int value= binary ? stringcmp(a,b) : sortcmp(a,b);
+ int value= binary_cmp ? stringcmp(a,b) : sortcmp(a,b);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
@@ -270,60 +410,45 @@ longlong Item_func_strcmp::val_int()
void Item_func_interval::fix_length_and_dec()
{
- bool nums=1;
- uint i;
- for (i=0 ; i < arg_count ; i++)
+ if (row->cols() > 8)
{
- if (!args[i])
- return; // End of memory
- if (args[i]->type() != Item::INT_ITEM &&
- args[i]->type() != Item::REAL_ITEM)
+ bool consts=1;
+
+ for (uint i=1 ; consts && i < row->cols() ; i++)
{
- nums=0;
- break;
+ consts&= row->el(i)->const_item();
}
- }
- if (nums && arg_count >= 8)
- {
- if ((intervals=(double*) sql_alloc(sizeof(double)*arg_count)))
+
+ if (consts &&
+ (intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1))))
{
- for (i=0 ; i < arg_count ; i++)
- intervals[i]=args[i]->val();
+ for (uint i=1 ; i < row->cols(); i++)
+ intervals[i-1]=row->el(i)->val();
}
}
- maybe_null=0; max_length=2;
- used_tables_cache|=item->used_tables();
- with_sum_func= with_sum_func || item->with_sum_func;
+ maybe_null= 0;
+ max_length= 2;
+ used_tables_cache|= row->used_tables();
+ with_sum_func= with_sum_func || row->with_sum_func;
}
-void Item_func_interval::split_sum_func(List<Item> &fields)
-{
- if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(fields);
- else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
- {
- fields.push_front(item);
- item= new Item_ref((Item**) fields.head_ref(), 0, item->name);
- }
- Item_int_func::split_sum_func(fields);
-}
/*
return -1 if null value,
0 if lower than lowest
- 1 - arg_count if between args[n] and args[n+1]
- arg_count+1 if higher than biggest argument
+ 1 - arg_count-1 if between args[n] and args[n+1]
+ arg_count if higher than biggest argument
*/
longlong Item_func_interval::val_int()
{
- double value=item->val();
- if (item->null_value)
- return -1; // -1 if null /* purecov: inspected */
+ double value=row->el(0)->val();
+ if (row->el(0)->null_value)
+ return -1; // -1 if null
if (intervals)
{ // Use binary search to find interval
uint start,end;
- start=0; end=arg_count-1;
+ start=1; end=row->cols()-2;
while (start != end)
{
uint mid=(start+end+1)/2;
@@ -334,28 +459,19 @@ longlong Item_func_interval::val_int()
}
return (value < intervals[start]) ? 0 : start+1;
}
- if (args[0]->val() > value)
- return 0;
- for (uint i=1 ; i < arg_count ; i++)
+
+ uint i;
+ for (i=1 ; i < row->cols() ; i++)
{
- if (args[i]->val() > value)
- return i;
+ if (row->el(i)->val() > value)
+ return i-1;
}
- return (longlong) arg_count;
-}
-
-
-void Item_func_interval::update_used_tables()
-{
- Item_func::update_used_tables();
- item->update_used_tables();
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
+ return i-1;
}
void Item_func_between::fix_length_and_dec()
{
- max_length=1;
+ max_length= 1;
/*
As some compare functions are generated after sql_yacc,
@@ -366,7 +482,7 @@ void Item_func_between::fix_length_and_dec()
cmp_type=item_cmp_type(args[0]->result_type(),
item_cmp_type(args[1]->result_type(),
args[2]->result_type()));
- if (args[0]->binary | args[1]->binary | args[2]->binary)
+ if (args[0]->binary() | args[1]->binary() | args[2]->binary())
string_compare=stringcmp;
else
string_compare=sortcmp;
@@ -540,21 +656,22 @@ Item_func_if::fix_length_and_dec()
if (null1)
{
cached_result_type= arg2_type;
- binary= args[2]->binary;
+ set_charset(args[2]->charset());
}
else if (null2)
{
cached_result_type= arg1_type;
- binary= args[1]->binary;
+ set_charset(args[1]->charset());
}
else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
{
cached_result_type = STRING_RESULT;
- binary=args[1]->binary | args[2]->binary;
+ set_charset((args[1]->binary() || args[2]->binary()) ?
+ &my_charset_bin : args[1]->charset());
}
else
{
- binary=1; // Number
+ set_charset(&my_charset_bin); // Number
if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT)
cached_result_type = REAL_RESULT;
else
@@ -615,7 +732,7 @@ double
Item_func_nullif::val()
{
double value;
- if (!(this->*cmp_func)() || null_value)
+ if (!cmp.compare() || null_value)
{
null_value=1;
return 0.0;
@@ -629,7 +746,7 @@ longlong
Item_func_nullif::val_int()
{
longlong value;
- if (!(this->*cmp_func)() || null_value)
+ if (!cmp.compare() || null_value)
{
null_value=1;
return 0;
@@ -643,7 +760,7 @@ String *
Item_func_nullif::val_str(String *str)
{
String *res;
- if (!(this->*cmp_func)() || null_value)
+ if (!cmp.compare() || null_value)
{
null_value=1;
return 0;
@@ -692,7 +809,7 @@ Item *Item_func_case::find_item(String *str)
}
if ((tmp=args[i]->val_str(str))) // If not null
{
- if (first_expr->binary || args[i]->binary)
+ if (first_expr_is_binary || args[i]->binary())
{
if (stringcmp(tmp,first_expr_str)==0)
return args[i+1];
@@ -722,6 +839,11 @@ Item *Item_func_case::find_item(String *str)
}
if (args[i]->val()==first_expr_real && !args[i]->null_value)
return args[i+1];
+ break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
}
}
// No, WHEN clauses all missed, return ELSE expression
@@ -750,7 +872,7 @@ String *Item_func_case::val_str(String *str)
longlong Item_func_case::val_int()
{
char buff[MAX_FIELD_WIDTH];
- String dummy_str(buff,sizeof(buff));
+ String dummy_str(buff,sizeof(buff),thd_charset());
Item *item=find_item(&dummy_str);
longlong res;
@@ -767,7 +889,7 @@ longlong Item_func_case::val_int()
double Item_func_case::val()
{
char buff[MAX_FIELD_WIDTH];
- String dummy_str(buff,sizeof(buff));
+ String dummy_str(buff,sizeof(buff),thd_charset());
Item *item=find_item(&dummy_str);
double res;
@@ -783,18 +905,21 @@ double Item_func_case::val()
bool
-Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables)
+Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
- if (first_expr && first_expr->fix_fields(thd,tables) ||
- else_expr && else_expr->fix_fields(thd,tables))
+ if (first_expr && (first_expr->fix_fields(thd, tables, &first_expr) ||
+ first_expr->check_cols(1)) ||
+ else_expr && (else_expr->fix_fields(thd, tables, &else_expr) ||
+ else_expr->check_cols(1)))
return 1;
- if (Item_func::fix_fields(thd,tables))
+ if (Item_func::fix_fields(thd, tables, ref))
return 1;
if (first_expr)
{
used_tables_cache|=(first_expr)->used_tables();
const_item_cache&= (first_expr)->const_item();
with_sum_func= with_sum_func || (first_expr)->with_sum_func;
+ first_expr_is_binary= first_expr->binary();
}
if (else_expr)
{
@@ -807,30 +932,43 @@ Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables)
return 0;
}
-void Item_func_case::split_sum_func(List<Item> &fields)
+
+void Item_func_case::split_sum_func(Item **ref_pointer_array,
+ List<Item> &fields)
{
if (first_expr)
{
if (first_expr->with_sum_func && first_expr->type() != SUM_FUNC_ITEM)
- first_expr->split_sum_func(fields);
+ first_expr->split_sum_func(ref_pointer_array, fields);
else if (first_expr->used_tables() || first_expr->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(first_expr);
- first_expr= new Item_ref((Item**) fields.head_ref(), 0,
- first_expr->name);
+ ref_pointer_array[el]= first_expr;
+ first_expr= new Item_ref(ref_pointer_array + el, 0, first_expr->name);
}
}
if (else_expr)
{
if (else_expr->with_sum_func && else_expr->type() != SUM_FUNC_ITEM)
- else_expr->split_sum_func(fields);
+ else_expr->split_sum_func(ref_pointer_array, fields);
else if (else_expr->used_tables() || else_expr->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(else_expr);
- else_expr= new Item_ref((Item**) fields.head_ref(), 0, else_expr->name);
+ ref_pointer_array[el]= else_expr;
+ else_expr= new Item_ref(ref_pointer_array + el, 0, else_expr->name);
}
}
- Item_func::split_sum_func(fields);
+ Item_func::split_sum_func(ref_pointer_array, fields);
+}
+
+
+void Item_func_case::set_outer_resolving()
+{
+ first_expr->set_outer_resolving();
+ else_expr->set_outer_resolving();
+ Item_func::set_outer_resolving();
}
void Item_func_case::update_used_tables()
@@ -919,8 +1057,8 @@ double Item_func_coalesce::val()
void Item_func_coalesce::fix_length_and_dec()
{
- max_length=0;
- decimals=0;
+ max_length= 0;
+ decimals= 0;
cached_result_type = args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
@@ -943,6 +1081,11 @@ static int cmp_double(double *a,double *b)
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
+static int cmp_row(cmp_item_row* a, cmp_item_row* b)
+{
+ return a->compare(b);
+}
+
int in_vector::find(Item *item)
{
byte *result=get_value(item);
@@ -965,15 +1108,19 @@ int in_vector::find(Item *item)
return (int) ((*compare)(base+start*size,result) == 0);
}
-
in_string::in_string(uint elements,qsort_cmp cmp_func)
- :in_vector(elements,sizeof(String),cmp_func),tmp(buff,sizeof(buff))
+ :in_vector(elements, sizeof(String), cmp_func),
+ tmp(buff, sizeof(buff), default_charset_info)
{}
in_string::~in_string()
{
- for (uint i=0 ; i < count ; i++)
- ((String*) base)[i].free();
+ if (base)
+ {
+ // base was allocated with help of sql_alloc => following is OK
+ for (uint i=0 ; i < count ; i++)
+ ((String*) base)[i].free();
+ }
}
void in_string::set(uint pos,Item *item)
@@ -982,6 +1129,9 @@ void in_string::set(uint pos,Item *item)
String *res=item->val_str(str);
if (res && res != str)
*str= *res;
+ // BAR TODO: I'm not sure this is absolutely correct
+ if (!str->charset())
+ str->set_charset(default_charset_info);
}
byte *in_string::get_value(Item *item)
@@ -989,6 +1139,33 @@ byte *in_string::get_value(Item *item)
return (byte*) item->val_str(&tmp);
}
+in_row::in_row(uint elements, Item * item)
+{
+ base= (char*) new cmp_item_row[count= elements];
+ size= sizeof(cmp_item_row);
+ compare= (qsort_cmp) cmp_row;
+ tmp.store_value(item);
+}
+
+in_row::~in_row()
+{
+ if (base)
+ delete [] (cmp_item_row*) base;
+}
+
+byte *in_row::get_value(Item *item)
+{
+ tmp.store_value(item);
+ return (byte *)&tmp;
+}
+
+void in_row::set(uint pos, Item *item)
+{
+ DBUG_ENTER("in_row::set");
+ DBUG_PRINT("enter", ("pos %u item 0x%lx", pos, (ulong) item));
+ ((cmp_item_row*) base)[pos].store_value_by_template(&tmp, item);
+ DBUG_VOID_RETURN;
+}
in_longlong::in_longlong(uint elements)
:in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong)
@@ -1001,13 +1178,12 @@ void in_longlong::set(uint pos,Item *item)
byte *in_longlong::get_value(Item *item)
{
- tmp=item->val_int();
+ tmp= item->val_int();
if (item->null_value)
- return 0; /* purecov: inspected */
+ return 0;
return (byte*) &tmp;
}
-
in_double::in_double(uint elements)
:in_vector(elements,sizeof(double),(qsort_cmp) cmp_double)
{}
@@ -1019,21 +1195,160 @@ void in_double::set(uint pos,Item *item)
byte *in_double::get_value(Item *item)
{
- tmp=item->val();
+ tmp= item->val();
if (item->null_value)
return 0; /* purecov: inspected */
return (byte*) &tmp;
}
+cmp_item* cmp_item::get_comparator(Item *item)
+{
+ switch (item->result_type()) {
+ case STRING_RESULT:
+ if (item->binary())
+ return new cmp_item_binary_string;
+ else
+ return new cmp_item_sort_string;
+ break;
+ case INT_RESULT:
+ return new cmp_item_int;
+ break;
+ case REAL_RESULT:
+ return new cmp_item_real;
+ break;
+ case ROW_RESULT:
+ return new cmp_item_row;
+ break;
+ }
+ return 0; // to satisfy compiler :)
+}
+
+cmp_item* cmp_item_sort_string::make_same()
+{
+ return new cmp_item_sort_string_in_static();
+}
+
+cmp_item* cmp_item_binary_string::make_same()
+{
+ return new cmp_item_binary_string_in_static();
+}
+
+cmp_item* cmp_item_int::make_same()
+{
+ return new cmp_item_int();
+}
+
+cmp_item* cmp_item_real::make_same()
+{
+ return new cmp_item_real();
+}
+
+cmp_item* cmp_item_row::make_same()
+{
+ return new cmp_item_row();
+}
+
+void cmp_item_row::store_value(Item *item)
+{
+ THD *thd= current_thd;
+ n= item->cols();
+ if ((comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *)*n)))
+ {
+ item->bring_value();
+ item->null_value= 0;
+ for (uint i=0; i < n; i++)
+ if ((comparators[i]= cmp_item::get_comparator(item->el(i))))
+ {
+ comparators[i]->store_value(item->el(i));
+ item->null_value|= item->el(i)->null_value;
+ }
+ else
+ return;
+ }
+ else
+ return;
+}
+
+void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
+{
+ cmp_item_row *tmpl= (cmp_item_row*) t;
+ if (tmpl->n != item->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), tmpl->n);
+ return;
+ }
+ n= tmpl->n;
+ if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
+ {
+ item->bring_value();
+ item->null_value= 0;
+ for (uint i=0; i < n; i++)
+ if ((comparators[i]= tmpl->comparators[i]->make_same()))
+ {
+ comparators[i]->store_value_by_template(tmpl->comparators[i],
+ item->el(i));
+ item->null_value|= item->el(i)->null_value;
+ }
+ else
+ return;
+ }
+ else
+ return;
+}
+
+int cmp_item_row::cmp(Item *arg)
+{
+ arg->null_value= 0;
+ if (arg->cols() != n)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), n);
+ return 1;
+ }
+ bool was_null= 0;
+ arg->bring_value();
+ for (uint i=0; i < n; i++)
+ if (comparators[i]->cmp(arg->el(i)))
+ {
+ if (!arg->el(i)->null_value)
+ return 1;
+ was_null= 1;
+ }
+ return (arg->null_value= was_null);
+}
+
+int cmp_item_row::compare(cmp_item *c)
+{
+ int res;
+ cmp_item_row *cmp= (cmp_item_row *) c;
+ for (uint i=0; i < n; i++)
+ if ((res= comparators[i]->compare(cmp->comparators[i])))
+ return res;
+ return 0;
+}
+
+bool Item_func_in::nulls_in_row()
+{
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
+ {
+ if ((*arg)->null_inside())
+ return 1;
+ }
+ return 0;
+}
void Item_func_in::fix_length_and_dec()
{
- if (const_item())
+ /*
+ Row item with NULLs inside can return NULL or FALSE =>
+ they can't be processed as static
+ */
+ if (const_item() && !nulls_in_row())
{
switch (item->result_type()) {
case STRING_RESULT:
- if (item->binary)
- array=new in_string(arg_count,(qsort_cmp) stringcmp); /* purecov: inspected */
+ if (item->binary())
+ array=new in_string(arg_count,(qsort_cmp) stringcmp);
else
array=new in_string(arg_count,(qsort_cmp) sortcmp);
break;
@@ -1043,6 +1358,9 @@ void Item_func_in::fix_length_and_dec()
case REAL_RESULT:
array= new in_double(arg_count);
break;
+ case ROW_RESULT:
+ array= new in_row(arg_count, item);
+ break;
}
uint j=0;
for (uint i=0 ; i < arg_count ; i++)
@@ -1050,29 +1368,18 @@ void Item_func_in::fix_length_and_dec()
array->set(j,args[i]);
if (!args[i]->null_value) // Skip NULL values
j++;
+ else
+ have_null= 1;
}
if ((array->used_count=j))
array->sort();
}
else
{
- switch (item->result_type()) {
- case STRING_RESULT:
- if (item->binary)
- in_item= new cmp_item_binary_string;
- else
- in_item= new cmp_item_sort_string;
- break;
- case INT_RESULT:
- in_item= new cmp_item_int;
- break;
- case REAL_RESULT:
- in_item= new cmp_item_real;
- break;
- }
+ in_item= cmp_item::get_comparator(item);
}
maybe_null= item->maybe_null;
- max_length=2;
+ max_length= 1;
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
}
@@ -1092,17 +1399,20 @@ longlong Item_func_in::val_int()
if (array)
{
int tmp=array->find(item);
- null_value=item->null_value;
+ null_value=item->null_value || (!tmp && have_null);
return tmp;
}
in_item->store_value(item);
if ((null_value=item->null_value))
return 0;
+ have_null= 0;
for (uint i=0 ; i < arg_count ; i++)
{
if (!in_item->cmp(args[i]) && !args[i]->null_value)
return 1; // Would maybe be nice with i ?
+ have_null|= args[i]->null_value;
}
+ null_value= have_null;
return 0;
}
@@ -1115,16 +1425,18 @@ void Item_func_in::update_used_tables()
const_item_cache&=item->const_item();
}
-void Item_func_in::split_sum_func(List<Item> &fields)
+void Item_func_in::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(fields);
+ item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(item);
- item= new Item_ref((Item**) fields.head_ref(), 0, item->name);
+ ref_pointer_array[el]= item;
+ item= new Item_ref(ref_pointer_array + el, 0, item->name);
}
- Item_func::split_sum_func(fields);
+ Item_func::split_sum_func(ref_pointer_array, fields);
}
@@ -1167,7 +1479,7 @@ longlong Item_func_bit_and::val_int()
bool
-Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
+Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
List_iterator<Item> li(list);
Item *item;
@@ -1191,7 +1503,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
}
if (abort_on_null)
item->top_level_item();
- if (item->fix_fields(thd,tables))
+ if (item->fix_fields(thd, tables, li.ref()) || item->check_cols(1))
return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func;
@@ -1202,11 +1514,20 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
if (thd)
thd->cond_count+=list.elements;
fix_length_and_dec();
+ fixed= 1;
return 0;
}
+void Item_cond::set_outer_resolving()
+{
+ Item_func::set_outer_resolving();
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ item->set_outer_resolving();
+}
-void Item_cond::split_sum_func(List<Item> &fields)
+void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{
List_iterator<Item> li(list);
Item *item;
@@ -1215,11 +1536,13 @@ void Item_cond::split_sum_func(List<Item> &fields)
while ((item=li++))
{
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(fields);
+ item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(item);
- li.replace(new Item_ref((Item**) fields.head_ref(),0,item->name));
+ ref_pointer_array[el]= item;
+ li.replace(new Item_ref(ref_pointer_array + el, 0, item->name));
}
item->update_used_tables();
used_tables_cache|=item->used_tables();
@@ -1375,12 +1698,6 @@ longlong Item_func_isnotnull::val_int()
}
-void Item_func_like::fix_length_and_dec()
-{
- decimals=0; max_length=1;
- // cmp_type=STRING_RESULT; // For quick select
-}
-
longlong Item_func_like::val_int()
{
String* res = args[0]->val_str(&tmp_value1);
@@ -1396,12 +1713,15 @@ longlong Item_func_like::val_int()
return 0;
}
null_value=0;
+ if ((res->charset()->state & MY_CS_BINSORT) ||
+ (res2->charset()->state & MY_CS_BINSORT))
+ set_charset(&my_charset_bin);
if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
- if (binary)
- return wild_compare(*res,*res2,escape) ? 0 : 1;
- else
- return wild_case_compare(*res,*res2,escape) ? 0 : 1;
+ return my_wildcmp(charset(),
+ res->ptr(),res->ptr()+res->length(),
+ res2->ptr(),res2->ptr()+res2->length(),
+ escape,wild_one,wild_many) ? 0 : 1;
}
@@ -1421,9 +1741,10 @@ Item_func::optimize_type Item_func_like::select_optimize() const
return OPTIMIZE_NONE;
}
-bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
+
+bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
- if (Item_bool_func2::fix_fields(thd, tlist))
+ if (Item_bool_func2::fix_fields(thd, tlist, ref))
return 1;
/*
@@ -1473,19 +1794,22 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
#ifdef USE_REGEX
bool
-Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables)
+Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
- if (args[0]->fix_fields(thd,tables) || args[1]->fix_fields(thd,tables))
+ if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) ||
+ args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1))
return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
- max_length=1; decimals=0;
- binary=args[0]->binary || args[1]->binary;
+ max_length= 1;
+ decimals= 0;
+ binary_cmp= (args[0]->binary() || args[1]->binary());
+
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
const_item_cache=args[0]->const_item() && args[1]->const_item();
if (!regex_compiled && args[1]->const_item())
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff),default_charset_info);
String *res=args[1]->val_str(&tmp);
if (args[1]->null_value)
{ // Will always return NULL
@@ -1494,8 +1818,9 @@ Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables)
}
int error;
if ((error=regcomp(&preg,res->c_ptr(),
- binary ? REG_EXTENDED | REG_NOSUB :
- REG_EXTENDED | REG_NOSUB | REG_ICASE)))
+ binary_cmp ? REG_EXTENDED | REG_NOSUB :
+ REG_EXTENDED | REG_NOSUB | REG_ICASE,
+ res->charset())))
{
(void) regerror(error,&preg,buff,sizeof(buff));
my_printf_error(ER_REGEXP_ERROR,ER(ER_REGEXP_ERROR),MYF(0),buff);
@@ -1506,13 +1831,15 @@ Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables)
}
else
maybe_null=1;
+ fixed= 1;
return 0;
}
+
longlong Item_func_regex::val_int()
{
char buff[MAX_FIELD_WIDTH];
- String *res, tmp(buff,sizeof(buff));
+ String *res, tmp(buff,sizeof(buff),default_charset_info);
res=args[0]->val_str(&tmp);
if (args[0]->null_value)
@@ -1523,7 +1850,7 @@ longlong Item_func_regex::val_int()
if (!regex_is_const)
{
char buff2[MAX_FIELD_WIDTH];
- String *res2, tmp2(buff2,sizeof(buff2));
+ String *res2, tmp2(buff2,sizeof(buff2),default_charset_info);
res2= args[1]->val_str(&tmp2);
if (args[1]->null_value)
@@ -1540,8 +1867,9 @@ longlong Item_func_regex::val_int()
regex_compiled=0;
}
if (regcomp(&preg,res2->c_ptr(),
- binary ? REG_EXTENDED | REG_NOSUB :
- REG_EXTENDED | REG_NOSUB | REG_ICASE))
+ binary_cmp ? REG_EXTENDED | REG_NOSUB :
+ REG_EXTENDED | REG_NOSUB | REG_ICASE,
+ res->charset()))
{
null_value=1;
@@ -1568,9 +1896,9 @@ Item_func_regex::~Item_func_regex()
#ifdef LIKE_CMP_TOUPPER
-#define likeconv(A) (uchar) toupper(A)
+#define likeconv(cs,A) (uchar) (cs)->toupper(A)
#else
-#define likeconv(A) (uchar) my_sort_order[(uchar) (A)]
+#define likeconv(cs,A) (uchar) (cs)->sort_order[(uchar) (A)]
#endif
@@ -1585,10 +1913,11 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
int f = 0;
int g = plm1;
int *const splm1 = suff + plm1;
+ CHARSET_INFO *cs=system_charset_info; // QQ Needs to be fixed
*splm1 = pattern_len;
- if (binary)
+ if (binary_cmp)
{
int i;
for (i = pattern_len - 2; i >= 0; i--)
@@ -1621,7 +1950,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
g = i; // g = min(i, g)
f = i;
while (g >= 0 &&
- likeconv(pattern[g]) == likeconv(pattern[g + plm1 - f]))
+ likeconv(cs, pattern[g]) == likeconv(cs, pattern[g + plm1 - f]))
g--;
suff[i] = f - g;
}
@@ -1684,12 +2013,14 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
{
int *i;
int *end = bmBc + alphabet_size;
+ int j;
+ const int plm1 = pattern_len - 1;
+ CHARSET_INFO *cs=system_charset_info; // QQ Needs to be fixed
+
for (i = bmBc; i < end; i++)
*i = pattern_len;
- int j;
- const int plm1 = pattern_len - 1;
- if (binary)
+ if (binary_cmp)
{
for (j = 0; j < plm1; j++)
bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
@@ -1697,7 +2028,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
else
{
for (j = 0; j < plm1; j++)
- bmBc[(uint) likeconv(pattern[j])] = plm1 - j;
+ bmBc[(uint) likeconv(cs,pattern[j])] = plm1 - j;
}
}
@@ -1714,12 +2045,13 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
int shift = pattern_len;
int j = 0;
int u = 0;
+ CHARSET_INFO *cs=system_charset_info; // QQ Needs to be fixed
const int plm1= pattern_len - 1;
const int tlmpl= text_len - pattern_len;
/* Searching */
- if (binary)
+ if (binary_cmp)
{
while (j <= tlmpl)
{
@@ -1755,7 +2087,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
while (j <= tlmpl)
{
register int i = plm1;
- while (i >= 0 && likeconv(pattern[i]) == likeconv(text[i + j]))
+ while (i >= 0 && likeconv(cs,pattern[i]) == likeconv(cs,text[i + j]))
{
i--;
if (i == plm1 - shift)
@@ -1766,7 +2098,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
register const int v = plm1 - i;
turboShift = u - v;
- bcShift = bmBc[(uint) likeconv(text[i + j])] - plm1 + i;
+ bcShift = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i;
shift = max(turboShift, bcShift);
shift = max(shift, bmGs[i]);
if (shift == bmGs[i])
@@ -1821,3 +2153,82 @@ longlong Item_cond_xor::val_int()
}
return (longlong) result;
}
+
+/****************************************************************
+ Classes and functions for spatial relations
+*****************************************************************/
+
+longlong Item_func_spatial_rel::val_int()
+{
+ String *res1=args[0]->val_str(&tmp_value1);
+ String *res2=args[1]->val_str(&tmp_value2);
+ Geometry g1, g2;
+ MBR mbr1,mbr2;
+
+ if ((null_value=(args[0]->null_value ||
+ args[1]->null_value ||
+ g1.create_from_wkb(res1->ptr(),res1->length()) ||
+ g2.create_from_wkb(res2->ptr(),res2->length()) ||
+ g1.get_mbr(&mbr1) ||
+ g2.get_mbr(&mbr2))))
+ return 0;
+
+ switch (spatial_rel)
+ {
+ case SP_CONTAINS_FUNC:
+ return mbr1.contains(&mbr2);
+ case SP_WITHIN_FUNC:
+ return mbr1.within(&mbr2);
+ case SP_EQUALS_FUNC:
+ return mbr1.equals(&mbr2);
+ case SP_DISJOINT_FUNC:
+ return mbr1.disjoint(&mbr2);
+ case SP_INTERSECTS_FUNC:
+ return mbr1.intersects(&mbr2);
+ case SP_TOUCHES_FUNC:
+ return mbr1.touches(&mbr2);
+ case SP_OVERLAPS_FUNC:
+ return mbr1.overlaps(&mbr2);
+ case SP_CROSSES_FUNC:
+ return 0;
+ default:
+ break;
+ }
+
+ null_value=1;
+ return 0;
+}
+
+longlong Item_func_isempty::val_int()
+{
+ String tmp;
+ null_value=0;
+ return args[0]->null_value ? 1 : 0;
+}
+
+longlong Item_func_issimple::val_int()
+{
+ String tmp;
+ String *wkb=args[0]->val_str(&tmp);
+
+ if ((null_value= (!wkb || args[0]->null_value )))
+ return 0;
+ /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
+ return 0;
+}
+
+longlong Item_func_isclosed::val_int()
+{
+ String tmp;
+ String *wkb=args[0]->val_str(&tmp);
+ Geometry geom;
+ int isclosed;
+
+ null_value= (!wkb ||
+ args[0]->null_value ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,is_closed) ||
+ geom.is_closed(&isclosed));
+
+ return (longlong) isclosed;
+}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index aaa15f415e7..8534150acd7 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,59 @@
#pragma interface /* gcc class implementation */
#endif
+extern Item_result item_cmp_type(Item_result a,Item_result b);
+class Item_bool_func2;
+class Arg_comparator;
+
+typedef int (Arg_comparator::*arg_cmp_func)();
+
+class Arg_comparator: public Sql_alloc
+{
+ Item **a, **b;
+ arg_cmp_func func;
+ Item_bool_func2 *owner;
+ Arg_comparator *comparators; // used only for compare_row()
+
+public:
+ Arg_comparator() {};
+ Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};
+
+ int set_compare_func(Item_bool_func2 *owner, Item_result type);
+ inline int set_compare_func(Item_bool_func2 *owner)
+ {
+ return set_compare_func(owner, item_cmp_type((*a)->result_type(),
+ (*b)->result_type()));
+ }
+ inline int set_cmp_func(Item_bool_func2 *owner,
+ Item **a1, Item **a2,
+ Item_result type)
+ {
+ a= a1;
+ b= a2;
+ return set_compare_func(owner, type);
+ }
+ inline int set_cmp_func(Item_bool_func2 *owner,
+ Item **a1, Item **a2)
+ {
+ return set_cmp_func(owner, a1, a2, item_cmp_type((*a1)->result_type(),
+ (*a2)->result_type()));
+ }
+ inline int compare() { return (this->*func)(); }
+
+ int compare_string(); // compare args[0] & args[1]
+ int compare_real(); // compare args[0] & args[1]
+ int compare_int(); // compare args[0] & args[1]
+ int compare_row(); // compare args[0] & args[1]
+ int compare_e_string(); // compare args[0] & args[1]
+ int compare_e_real(); // compare args[0] & args[1]
+ int compare_e_int(); // compare args[0] & args[1]
+ int compare_e_row(); // compare args[0] & args[1]
+
+ static arg_cmp_func comparator_matrix [4][2];
+
+ friend class Item_func;
+};
+
class Item_bool_func :public Item_int_func
{
public:
@@ -28,29 +81,72 @@ public:
Item_bool_func(Item *a) :Item_int_func(a) {}
Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
void fix_length_and_dec() { decimals=0; max_length=1; }
- unsigned int size_of() { return sizeof(*this);}
+};
+
+class Item_cache;
+class Item_in_optimizer: public Item_bool_func
+{
+protected:
+ Item_cache *cache;
+public:
+ Item_in_optimizer(Item *a, Item_in_subselect *b):
+ Item_bool_func(a, (Item *)b), cache(0) {}
+ // used by row in transformer
+ bool preallocate_row();
+ bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool is_null();
+ /*
+ Item_in_optimizer item is special boolean function. On value request
+ (one of val, val_int or val_str methods) it evaluate left expression
+ of IN by storing it value in cache item (one of Item_cache* items),
+ then it test cache is it NULL. If left expression (cache) is NULL then
+ Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
+ */
+ longlong val_int();
+
+ Item_cache **get_cache() { return &cache; }
};
class Item_bool_func2 :public Item_int_func
{ /* Bool with 2 string args */
protected:
+ Arg_comparator cmp;
String tmp_value1,tmp_value2;
+ bool binary_cmp;
+
public:
- Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_bool_func2(Item *a,Item *b):
+ Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
void fix_length_and_dec();
- void set_cmp_func(Item_result type);
- int (Item_bool_func2::*cmp_func)();
- int compare_string(); /* compare arg[0] & arg[1] */
- int compare_real(); /* compare arg[0] & arg[1] */
- int compare_int(); /* compare arg[0] & arg[1] */
+ void set_cmp_func()
+ {
+ cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
+ }
optimize_type select_optimize() const { return OPTIMIZE_OP; }
virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); }
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
- unsigned int size_of() { return sizeof(*this);}
+ virtual bool binary() const { return binary_cmp; }
+
+ static Item_bool_func2* eq_creator(Item *a, Item *b);
+ static Item_bool_func2* ne_creator(Item *a, Item *b);
+ static Item_bool_func2* gt_creator(Item *a, Item *b);
+ static Item_bool_func2* lt_creator(Item *a, Item *b);
+ static Item_bool_func2* ge_creator(Item *a, Item *b);
+ static Item_bool_func2* le_creator(Item *a, Item *b);
+
+ friend class Arg_comparator;
};
+class Item_bool_rowready_func2 :public Item_bool_func2
+{
+public:
+ Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b)
+ {
+ allowed_arg_cols= a->cols();
+ }
+};
class Item_func_not :public Item_bool_func
{
@@ -60,10 +156,10 @@ public:
const char *func_name() const { return "not"; }
};
-class Item_func_eq :public Item_bool_func2
+class Item_func_eq :public Item_bool_rowready_func2
{
public:
- Item_func_eq(Item *a,Item *b) :Item_bool_func2(a,b) { };
+ Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return EQ_FUNC; }
enum Functype rev_functype() const { return EQ_FUNC; }
@@ -71,25 +167,23 @@ public:
const char *func_name() const { return "="; }
};
-class Item_func_equal :public Item_bool_func2
+class Item_func_equal :public Item_bool_rowready_func2
{
- Item_result cmp_result_type;
public:
- Item_func_equal(Item *a,Item *b) :Item_bool_func2(a,b) { };
+ Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
void fix_length_and_dec();
enum Functype functype() const { return EQUAL_FUNC; }
enum Functype rev_functype() const { return EQUAL_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "<=>"; }
- unsigned int size_of() { return sizeof(*this);}
};
-class Item_func_ge :public Item_bool_func2
+class Item_func_ge :public Item_bool_rowready_func2
{
public:
- Item_func_ge(Item *a,Item *b) :Item_bool_func2(a,b) { };
+ Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return GE_FUNC; }
enum Functype rev_functype() const { return LE_FUNC; }
@@ -98,10 +192,10 @@ public:
};
-class Item_func_gt :public Item_bool_func2
+class Item_func_gt :public Item_bool_rowready_func2
{
public:
- Item_func_gt(Item *a,Item *b) :Item_bool_func2(a,b) { };
+ Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return GT_FUNC; }
enum Functype rev_functype() const { return LT_FUNC; }
@@ -110,10 +204,10 @@ public:
};
-class Item_func_le :public Item_bool_func2
+class Item_func_le :public Item_bool_rowready_func2
{
public:
- Item_func_le(Item *a,Item *b) :Item_bool_func2(a,b) { };
+ Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return LE_FUNC; }
enum Functype rev_functype() const { return GE_FUNC; }
@@ -122,10 +216,10 @@ public:
};
-class Item_func_lt :public Item_bool_func2
+class Item_func_lt :public Item_bool_rowready_func2
{
public:
- Item_func_lt(Item *a,Item *b) :Item_bool_func2(a,b) { }
+ Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
longlong val_int();
enum Functype functype() const { return LT_FUNC; }
enum Functype rev_functype() const { return GT_FUNC; }
@@ -134,10 +228,10 @@ public:
};
-class Item_func_ne :public Item_bool_func2
+class Item_func_ne :public Item_bool_rowready_func2
{
public:
- Item_func_ne(Item *a,Item *b) :Item_bool_func2(a,b) { }
+ Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
longlong val_int();
enum Functype functype() const { return NE_FUNC; }
cond_result eq_cmp_result() const { return COND_FALSE; }
@@ -166,7 +260,11 @@ class Item_func_strcmp :public Item_bool_func2
public:
Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
longlong val_int();
- void fix_length_and_dec() { max_length=2; }
+ void fix_length_and_dec()
+ {
+ max_length=2;
+ binary_cmp= args[0]->binary() || args[1]->binary();
+ }
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "strcmp"; }
};
@@ -174,22 +272,14 @@ public:
class Item_func_interval :public Item_int_func
{
- Item *item;
+ Item_row *row;
double *intervals;
public:
- Item_func_interval(Item *a,List<Item> &list)
- :Item_int_func(list),item(a),intervals(0) {}
+ Item_func_interval(Item_row *a)
+ :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); }
longlong val_int();
- bool fix_fields(THD *thd,struct st_table_list *tlist)
- {
- return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
- }
- void split_sum_func(List<Item> &fields);
void fix_length_and_dec();
- ~Item_func_interval() { delete item; }
const char *func_name() const { return "interval"; }
- void update_used_tables();
- unsigned int size_of() { return sizeof(*this);}
};
@@ -197,14 +287,15 @@ class Item_func_ifnull :public Item_func
{
enum Item_result cached_result_type;
public:
- Item_func_ifnull(Item *a,Item *b) :Item_func(a,b) { }
+ Item_func_ifnull(Item *a,Item *b)
+ :Item_func(a,b), cached_result_type(INT_RESULT)
+ {}
double val();
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
void fix_length_and_dec();
const char *func_name() const { return "ifnull"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -212,19 +303,20 @@ class Item_func_if :public Item_func
{
enum Item_result cached_result_type;
public:
- Item_func_if(Item *a,Item *b,Item *c) :Item_func(a,b,c) { }
+ Item_func_if(Item *a,Item *b,Item *c)
+ :Item_func(a,b,c), cached_result_type(INT_RESULT)
+ {}
double val();
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
- bool fix_fields(THD *thd,struct st_table_list *tlist)
+ bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
{
args[0]->top_level_item();
- return Item_func::fix_fields(thd,tlist);
+ return Item_func::fix_fields(thd, tlist, ref);
}
void fix_length_and_dec();
const char *func_name() const { return "if"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -232,14 +324,15 @@ class Item_func_nullif :public Item_bool_func2
{
enum Item_result cached_result_type;
public:
- Item_func_nullif(Item *a,Item *b) :Item_bool_func2(a,b) { }
+ Item_func_nullif(Item *a,Item *b)
+ :Item_bool_func2(a,b), cached_result_type(INT_RESULT)
+ {}
double val();
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
void fix_length_and_dec();
const char *func_name() const { return "nullif"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -247,14 +340,15 @@ class Item_func_coalesce :public Item_func
{
enum Item_result cached_result_type;
public:
- Item_func_coalesce(List<Item> &list) :Item_func(list) {}
+ Item_func_coalesce(List<Item> &list)
+ :Item_func(list),cached_result_type(INT_RESULT)
+ {}
double val();
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "coalesce"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_case :public Item_func
@@ -262,9 +356,12 @@ class Item_func_case :public Item_func
Item * first_expr, *else_expr;
enum Item_result cached_result_type;
String tmp_value;
+ bool first_expr_is_binary;
public:
- Item_func_case(List<Item> &list, Item *first_expr_, Item *else_expr_)
- :Item_func(list), first_expr(first_expr_), else_expr(else_expr_) {}
+ Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
+ :Item_func(list), first_expr(first_expr_arg), else_expr(else_expr_arg),
+ cached_result_type(INT_RESULT)
+ {}
double val();
longlong val_int();
String *val_str(String *);
@@ -273,10 +370,10 @@ public:
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
void print(String *str);
- bool fix_fields(THD *thd,struct st_table_list *tlist);
- void split_sum_func(List<Item> &fields);
+ bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
Item *find_item(String *str);
- unsigned int size_of() { return sizeof(*this);}
+ void set_outer_resolving();
};
@@ -291,6 +388,7 @@ class in_vector :public Sql_alloc
uint count;
public:
uint used_count;
+ in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
:base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements),
@@ -305,7 +403,6 @@ public:
int find(Item *item);
};
-
class in_string :public in_vector
{
char buff[80];
@@ -317,7 +414,6 @@ public:
byte *get_value(Item *item);
};
-
class in_longlong :public in_vector
{
longlong tmp;
@@ -327,7 +423,6 @@ public:
byte *get_value(Item *item);
};
-
class in_double :public in_vector
{
double tmp;
@@ -337,7 +432,6 @@ public:
byte *get_value(Item *item);
};
-
/*
** Classes for easy comparing of non const items
*/
@@ -347,89 +441,209 @@ class cmp_item :public Sql_alloc
public:
cmp_item() {}
virtual ~cmp_item() {}
- virtual void store_value(Item *item)=0;
- virtual int cmp(Item *item)=0;
+ virtual void store_value(Item *item)= 0;
+ virtual int cmp(Item *item)= 0;
+ // for optimized IN with row
+ virtual int compare(cmp_item *item)= 0;
+ static cmp_item* get_comparator(Item *);
+ virtual cmp_item *make_same()= 0;
+ virtual void store_value_by_template(cmp_item *tmpl, Item *item)
+ {
+ store_value(item);
+ }
};
+typedef int (*str_cmp_func_pointer)(const String *, const String *);
+class cmp_item_string :public cmp_item
+{
+protected:
+ str_cmp_func_pointer str_cmp_func;
+ String *value_res;
+public:
+ cmp_item_string (str_cmp_func_pointer cmp): str_cmp_func(cmp) {}
+ friend class cmp_item_sort_string;
+ friend class cmp_item_binary_string;
+ friend class cmp_item_sort_string_in_static;
+ friend class cmp_item_binary_string_in_static;
+};
-class cmp_item_sort_string :public cmp_item {
- protected:
+class cmp_item_sort_string :public cmp_item_string
+{
+protected:
char value_buff[80];
- String value,*value_res;
-public:
- cmp_item_sort_string() :value(value_buff,sizeof(value_buff)) {}
+ String value;
+public:
+ cmp_item_sort_string(str_cmp_func_pointer cmp):
+ cmp_item_string(cmp),
+ value(value_buff, sizeof(value_buff), default_charset_info) {}
+ cmp_item_sort_string():
+ cmp_item_string(&sortcmp),
+ value(value_buff, sizeof(value_buff), default_charset_info) {}
void store_value(Item *item)
- {
- value_res=item->val_str(&value);
- }
+ {
+ value_res= item->val_str(&value);
+ }
int cmp(Item *arg)
- {
- char buff[80];
- String tmp(buff,sizeof(buff)),*res;
- if (!(res=arg->val_str(&tmp)))
- return 1; /* Can't be right */
- return sortcmp(value_res,res);
- }
+ {
+ char buff[80];
+ String tmp(buff, sizeof(buff), default_charset_info), *res;
+ if (!(res= arg->val_str(&tmp)))
+ return 1; /* Can't be right */
+ return (*str_cmp_func)(value_res, res);
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_string *cmp= (cmp_item_string *)c;
+ return (*str_cmp_func)(value_res, cmp->value_res);
+ }
+ cmp_item *make_same();
};
class cmp_item_binary_string :public cmp_item_sort_string {
public:
- cmp_item_binary_string() {}
- int cmp(Item *arg)
- {
- char buff[80];
- String tmp(buff,sizeof(buff)),*res;
- if (!(res=arg->val_str(&tmp)))
- return 1; /* Can't be right */
- return stringcmp(value_res,res);
- }
+ cmp_item_binary_string(): cmp_item_sort_string(&stringcmp) {}
+ cmp_item *make_same();
};
-
class cmp_item_int :public cmp_item
{
longlong value;
public:
void store_value(Item *item)
- {
- value=item->val_int();
- }
+ {
+ value= item->val_int();
+ }
int cmp(Item *arg)
- {
- return value != arg->val_int();
- }
+ {
+ return value != arg->val_int();
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_int *cmp= (cmp_item_int *)c;
+ return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1);
+ }
+ cmp_item *make_same();
};
-
class cmp_item_real :public cmp_item
{
double value;
public:
void store_value(Item *item)
- {
- value= item->val();
- }
+ {
+ value= item->val();
+ }
int cmp(Item *arg)
+ {
+ return value != arg->val();
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_real *cmp= (cmp_item_real *)c;
+ return (value < cmp->value)? -1 : ((value == cmp->value) ? 0 : 1);
+ }
+ cmp_item *make_same();
+};
+
+class cmp_item_row :public cmp_item
+{
+ cmp_item **comparators;
+ uint n;
+public:
+ cmp_item_row(): comparators(0), n(0) {}
+ ~cmp_item_row()
+ {
+ if (comparators)
{
- return value != arg->val();
+ for (uint i= 0; i < n; i++)
+ {
+ if (comparators[i])
+ delete comparators[i];
+ }
}
+ }
+ void store_value(Item *item);
+ int cmp(Item *arg);
+ int compare(cmp_item *arg);
+ cmp_item *make_same();
+ void store_value_by_template(cmp_item *tmpl, Item *);
+};
+
+
+class in_row :public in_vector
+{
+ cmp_item_row tmp;
+public:
+ in_row(uint elements, Item *);
+ ~in_row();
+ void set(uint pos,Item *item);
+ byte *get_value(Item *item);
};
+/*
+ cmp_item for optimized IN with row (right part string, which never
+ be changed)
+*/
+
+class cmp_item_sort_string_in_static :public cmp_item_string
+{
+ protected:
+ String value;
+public:
+ cmp_item_sort_string_in_static(str_cmp_func_pointer cmp):
+ cmp_item_string(cmp) {}
+ cmp_item_sort_string_in_static(): cmp_item_string(&sortcmp) {}
+ void store_value(Item *item)
+ {
+ value_res= item->val_str(&value);
+ }
+ int cmp(Item *item)
+ {
+ // Should never be called
+ DBUG_ASSERT(0);
+ return 1;
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_string *cmp= (cmp_item_string *)c;
+ return (*str_cmp_func)(value_res, cmp->value_res);
+ }
+ cmp_item * make_same()
+ {
+ return new cmp_item_sort_string_in_static();
+ }
+};
+
+class cmp_item_binary_string_in_static :public cmp_item_sort_string_in_static {
+public:
+ cmp_item_binary_string_in_static():
+ cmp_item_sort_string_in_static(&stringcmp) {}
+ cmp_item * make_same()
+ {
+ return new cmp_item_binary_string_in_static();
+ }
+};
class Item_func_in :public Item_int_func
{
Item *item;
in_vector *array;
cmp_item *in_item;
+ bool have_null;
public:
Item_func_in(Item *a,List<Item> &list)
- :Item_int_func(list),item(a),array(0),in_item(0) {}
+ :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
+ {
+ allowed_arg_cols= item->cols();
+ }
longlong val_int();
- bool fix_fields(THD *thd,struct st_table_list *tlist)
+ bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
- bool res= (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
+ // We do not check item->cols(), because allowed_arg_cols assigned from it
+ bool res=(item->fix_fields(thd, tlist, &item) ||
+ Item_func::fix_fields(thd, tlist, ref));
with_sum_func= with_sum_func || item->with_sum_func;
- return res;
+ return res;
}
void fix_length_and_dec();
~Item_func_in() { delete item; delete array; delete in_item; }
@@ -440,12 +654,15 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
void update_used_tables();
- void split_sum_func(List<Item> &fields);
- unsigned int size_of() { return sizeof(*this);}
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
+ bool nulls_in_row();
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_int_func::set_outer_resolving();
+ }
};
-
-
/* Functions used by where clause */
class Item_func_isnull :public Item_bool_func
@@ -479,7 +696,6 @@ public:
}
}
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_isnotnull :public Item_bool_func
@@ -494,7 +710,6 @@ public:
}
const char *func_name() const { return "isnotnull"; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_like :public Item_bool_func2
@@ -526,9 +741,7 @@ public:
optimize_type select_optimize() const;
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; }
- void fix_length_and_dec();
- bool fix_fields(THD *thd,struct st_table_list *tlist);
- unsigned int size_of() { return sizeof(*this);}
+ bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
};
#ifdef USE_REGEX
@@ -541,14 +754,14 @@ class Item_func_regex :public Item_bool_func
bool regex_compiled;
bool regex_is_const;
String prev_regexp;
+ bool binary_cmp;
public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {}
~Item_func_regex();
longlong val_int();
- bool fix_fields(THD *thd,struct st_table_list *tlist);
+ bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
const char *func_name() const { return "regex"; }
- unsigned int size_of() { return sizeof(*this);}
};
#else
@@ -578,17 +791,17 @@ public:
{ list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
- bool fix_fields(THD *,struct st_table_list *);
+ bool fix_fields(THD *, struct st_table_list *, Item **ref);
enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; }
table_map used_tables() const;
void update_used_tables();
void print(String *str);
- void split_sum_func(List<Item> &fields);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
- unsigned int size_of() { return sizeof(*this);}
void top_level_item() { abort_on_null=1; }
+ void set_outer_resolving();
};
@@ -613,6 +826,17 @@ public:
};
+class Item_cond_xor :public Item_cond
+{
+public:
+ Item_cond_xor() :Item_cond() {}
+ Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) {}
+ enum Functype functype() const { return COND_XOR_FUNC; }
+ longlong val_int();
+ const char *func_name() const { return "xor"; }
+};
+
+
/* Some usefull inline functions */
inline Item *and_conds(Item *a,Item *b)
@@ -625,15 +849,80 @@ inline Item *and_conds(Item *a,Item *b)
return cond;
}
-class Item_cond_xor :public Item_cond
+Item *and_expressions(Item *a, Item *b, Item **org_item);
+
+/**************************************************************
+ Spatial relations
+***************************************************************/
+
+class Item_func_spatial_rel :public Item_bool_func2
{
+ enum Functype spatial_rel;
public:
- Item_cond_xor() :Item_cond() {}
- Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) {}
- enum Functype functype() const { return COND_XOR_FUNC; }
+ Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) :
+ Item_bool_func2(a,b) { spatial_rel = sp_rel; }
longlong val_int();
- const char *func_name() const { return "xor"; }
+ enum Functype functype() const
+ {
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return SP_WITHIN_FUNC;
+ case SP_WITHIN_FUNC:
+ return SP_CONTAINS_FUNC;
+ default:
+ return spatial_rel;
+ }
+ }
+ enum Functype rev_functype() const { return spatial_rel; }
+ const char *func_name() const
+ {
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return "contains";
+ case SP_WITHIN_FUNC:
+ return "within";
+ case SP_EQUALS_FUNC:
+ return "equals";
+ case SP_DISJOINT_FUNC:
+ return "disjoint";
+ case SP_INTERSECTS_FUNC:
+ return "intersects";
+ case SP_TOUCHES_FUNC:
+ return "touches";
+ case SP_CROSSES_FUNC:
+ return "crosses";
+ case SP_OVERLAPS_FUNC:
+ return "overlaps";
+ default:
+ return "sp_unknown";
+ }
+ }
};
-Item *and_expressions(Item *a, Item *b, Item **org_item);
+class Item_func_isempty :public Item_bool_func
+{
+public:
+ Item_func_isempty(Item *a) :Item_bool_func(a) {}
+ longlong val_int();
+ optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ const char *func_name() const { return "isempty"; }
+};
+
+class Item_func_issimple :public Item_bool_func
+{
+public:
+ Item_func_issimple(Item *a) :Item_bool_func(a) {}
+ longlong val_int();
+ optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ const char *func_name() const { return "issimple"; }
+};
+
+class Item_func_isclosed :public Item_bool_func
+{
+public:
+ Item_func_isclosed(Item *a) :Item_bool_func(a) {}
+ longlong val_int();
+ optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ const char *func_name() const { return "isclosed"; }
+};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 7e082bc174c..5c37abb230f 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,6 +52,13 @@ Item *create_func_ord(Item* a)
return new Item_func_ord(a);
}
+Item *create_func_old_password(Item* a)
+{
+ return new Item_func_old_password(a);
+}
+
+
+
Item *create_func_asin(Item* a)
{
return new Item_func_asin(a);
@@ -76,7 +83,7 @@ Item *create_func_ceiling(Item* a)
Item *create_func_connection_id(void)
{
THD *thd=current_thd;
- thd->safe_to_cache_query=0;
+ thd->lex.safe_to_cache_query=0;
return new Item_int(NullS,(longlong) thd->thread_id,10);
}
@@ -96,6 +103,11 @@ Item *create_func_cot(Item* a)
new Item_func_tan(a));
}
+Item *create_func_crc32(Item* a)
+{
+ return new Item_func_crc32(a);
+}
+
Item *create_func_date_format(Item* a,Item *b)
{
return new Item_func_date_format(a,b,0);
@@ -144,7 +156,7 @@ Item *create_func_floor(Item* a)
Item *create_func_found_rows(void)
{
THD *thd=current_thd;
- thd->safe_to_cache_query=0;
+ thd->lex.safe_to_cache_query=0;
return new Item_int(NullS,(longlong) thd->found_rows(),21);
}
@@ -155,7 +167,7 @@ Item *create_func_from_days(Item* a)
Item *create_func_get_lock(Item* a, Item *b)
{
- current_thd->safe_to_cache_query=0;
+ current_thd->lex.uncacheable();
return new Item_func_get_lock(a, b);
}
@@ -242,7 +254,7 @@ Item *create_func_lpad(Item* a, Item *b, Item *c)
Item *create_func_ltrim(Item* a)
{
- return new Item_func_ltrim(a,new Item_string(" ",1));
+ return new Item_func_ltrim(a,new Item_string(" ",1,default_charset_info));
}
Item *create_func_md5(Item* a)
@@ -299,7 +311,8 @@ Item *create_func_current_user()
length= (uint) (strxmov(buff, thd->priv_user, "@", thd->host_or_ip, NullS) -
buff);
- return new Item_string(NullS, thd->memdup(buff, length), length);
+ return new Item_string(NullS, thd->memdup(buff, length), length,
+ default_charset_info);
}
Item *create_func_quarter(Item* a)
@@ -319,7 +332,7 @@ Item *create_func_radians(Item *a)
Item *create_func_release_lock(Item* a)
{
- current_thd->safe_to_cache_query=0;
+ current_thd->lex.uncacheable();
return new Item_func_release_lock(a);
}
@@ -340,7 +353,7 @@ Item *create_func_rpad(Item* a, Item *b, Item *c)
Item *create_func_rtrim(Item* a)
{
- return new Item_func_rtrim(a,new Item_string(" ",1));
+ return new Item_func_rtrim(a,new Item_string(" ",1,default_charset_info));
}
Item *create_func_sec_to_time(Item* a)
@@ -365,7 +378,7 @@ Item *create_func_sha(Item* a)
Item *create_func_space(Item *a)
{
- return new Item_func_repeat(new Item_string(" ",1),a);
+ return new Item_func_repeat(new Item_string(" ",1,default_charset_info),a);
}
Item *create_func_soundex(Item* a)
@@ -410,7 +423,9 @@ Item *create_func_ucase(Item* a)
Item *create_func_version(void)
{
- return new Item_string(NullS,server_version, strlen(server_version));
+ return new Item_string(NullS,server_version,
+ (uint) strlen(server_version),
+ default_charset_info);
}
Item *create_func_weekday(Item* a)
@@ -425,10 +440,11 @@ Item *create_func_year(Item* a)
Item *create_load_file(Item* a)
{
- current_thd->safe_to_cache_query=0;
+ current_thd->lex.uncacheable();
return new Item_load_file(a);
}
+
Item *create_func_cast(Item *a, Item_cast cast_type)
{
Item *res;
@@ -447,7 +463,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type)
Item *create_func_is_free_lock(Item* a)
{
- current_thd->safe_to_cache_query=0;
+ current_thd->lex.uncacheable();
return new Item_func_is_free_lock(a);
}
@@ -455,3 +471,158 @@ Item *create_func_quote(Item* a)
{
return new Item_func_quote(a);
}
+
+Item *create_func_geometry_from_text(Item* a)
+{
+ return new Item_func_geometry_from_text(a);
+}
+
+Item *create_func_as_text(Item* a)
+{
+ return new Item_func_as_text(a);
+}
+
+Item *create_func_startpoint(Item* a)
+{
+ return new Item_func_spatial_decomp(a, Item_func::SP_STARTPOINT);
+}
+
+Item *create_func_endpoint(Item* a)
+{
+ return new Item_func_spatial_decomp(a, Item_func::SP_ENDPOINT);
+}
+
+Item *create_func_exteriorring(Item* a)
+{
+ return new Item_func_spatial_decomp(a, Item_func::SP_EXTERIORRING);
+}
+
+Item *create_func_pointn(Item* a, Item* b)
+{
+ return new Item_func_spatial_decomp_n(a,b,Item_func::SP_POINTN);
+}
+
+Item *create_func_interiorringn(Item* a, Item* b)
+{
+ return new Item_func_spatial_decomp_n(a,b,Item_func::SP_INTERIORRINGN);
+}
+
+Item *create_func_geometryn(Item* a, Item* b)
+{
+ return new Item_func_spatial_decomp_n(a,b,Item_func::SP_GEOMETRYN);
+}
+
+Item *create_func_centroid(Item* a)
+{
+ return new Item_func_centroid(a);
+}
+
+Item *create_func_envelope(Item* a)
+{
+ return new Item_func_envelope(a);
+}
+
+Item *create_func_equals(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_EQUALS_FUNC);
+}
+
+Item *create_func_disjoint(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_DISJOINT_FUNC);
+}
+
+Item *create_func_intersects(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_INTERSECTS_FUNC);
+}
+
+Item *create_func_touches(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_TOUCHES_FUNC);
+}
+
+Item *create_func_crosses(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_CROSSES_FUNC);
+}
+
+Item *create_func_within(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_WITHIN_FUNC);
+}
+
+Item *create_func_contains(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_CONTAINS_FUNC);
+}
+
+Item *create_func_overlaps(Item* a, Item* b)
+{
+ return new Item_func_spatial_rel(a, b, Item_func::SP_OVERLAPS_FUNC);
+}
+
+Item *create_func_isempty(Item* a)
+{
+ return new Item_func_isempty(a);
+}
+
+Item *create_func_issimple(Item* a)
+{
+ return new Item_func_issimple(a);
+}
+
+Item *create_func_isclosed(Item* a)
+{
+ return new Item_func_isclosed(a);
+}
+
+Item *create_func_geometry_type(Item* a)
+{
+ return new Item_func_geometry_type(a);
+}
+
+Item *create_func_dimension(Item* a)
+{
+ return new Item_func_dimension(a);
+}
+
+Item *create_func_x(Item* a)
+{
+ return new Item_func_x(a);
+}
+
+Item *create_func_y(Item* a)
+{
+ return new Item_func_y(a);
+}
+
+Item *create_func_numpoints(Item* a)
+{
+ return new Item_func_numpoints(a);
+}
+
+Item *create_func_numinteriorring(Item* a)
+{
+ return new Item_func_numinteriorring(a);
+}
+
+Item *create_func_numgeometries(Item* a)
+{
+ return new Item_func_numgeometries(a);
+}
+
+Item *create_func_area(Item* a)
+{
+ return new Item_func_area(a);
+}
+
+Item *create_func_glength(Item* a)
+{
+ return new Item_func_glength(a);
+}
+
+Item *create_func_point(Item* a, Item* b)
+{
+ return new Item_func_point(a,b);
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index 5381ad946ae..0c51886180f 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -27,10 +27,12 @@ Item *create_func_bit_count(Item* a);
Item *create_func_bit_length(Item* a);
Item *create_func_ceiling(Item* a);
Item *create_func_char_length(Item* a);
+Item *create_func_cast(Item *a, Item_cast cast_type);
Item *create_func_connection_id(void);
Item *create_func_conv(Item* a, Item *b, Item *c);
Item *create_func_cos(Item* a);
Item *create_func_cot(Item* a);
+Item *create_func_crc32(Item* a);
Item *create_func_date_format(Item* a,Item *b);
Item *create_func_dayname(Item* a);
Item *create_func_dayofmonth(Item* a);
@@ -64,6 +66,7 @@ Item *create_func_monthname(Item* a);
Item *create_func_nullif(Item* a, Item *b);
Item *create_func_oct(Item *);
Item *create_func_ord(Item* a);
+Item *create_func_old_password(Item* a);
Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
@@ -95,3 +98,41 @@ Item *create_func_weekday(Item* a);
Item *create_load_file(Item* a);
Item *create_func_is_free_lock(Item* a);
Item *create_func_quote(Item* a);
+
+Item *create_func_geometry_from_text(Item* a);
+Item *create_func_as_text(Item* a);
+Item *create_func_startpoint(Item* a);
+Item *create_func_endpoint(Item* a);
+Item *create_func_exteriorring(Item* a);
+Item *create_func_centroid(Item* a);
+Item *create_func_envelope(Item* a);
+Item *create_func_pointn(Item* a, Item* b);
+Item *create_func_interiorringn(Item* a, Item* b);
+Item *create_func_geometryn(Item* a, Item* b);
+
+Item *create_func_equals(Item* a, Item* b);
+Item *create_func_disjoint(Item* a, Item* b);
+Item *create_func_intersects(Item* a, Item* b);
+Item *create_func_touches(Item* a, Item* b);
+Item *create_func_crosses(Item* a, Item* b);
+Item *create_func_within(Item* a, Item* b);
+Item *create_func_contains(Item* a, Item* b);
+Item *create_func_overlaps(Item* a, Item* b);
+
+Item *create_func_isempty(Item* a);
+Item *create_func_issimple(Item* a);
+Item *create_func_isclosed(Item* a);
+
+Item *create_func_geometry_type(Item* a);
+Item *create_func_dimension(Item* a);
+Item *create_func_x(Item* a);
+Item *create_func_y(Item* a);
+Item *create_func_area(Item* a);
+Item *create_func_glength(Item* a);
+
+Item *create_func_numpoints(Item* a);
+Item *create_func_numinteriorring(Item* a);
+Item *create_func_numgeometries(Item* a);
+
+Item *create_func_point(Item* a,Item* b);
+
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ef629098d2a..2c8b9e97fb3 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,11 +22,12 @@
#endif
#include "mysql_priv.h"
+#include "slave.h" // for wait_for_master_pos
#include <m_ctype.h>
#include <hash.h>
#include <time.h>
#include <ft_global.h>
-#include "slave.h" // for wait_for_master_pos
+#include <zlib.h>
/* return TRUE if item is a constant */
@@ -37,7 +38,8 @@ eval_const_cond(COND *cond)
}
-Item_func::Item_func(List<Item> &list)
+Item_func::Item_func(List<Item> &list):
+ allowed_arg_cols(1)
{
arg_count=list.elements;
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
@@ -55,12 +57,47 @@ Item_func::Item_func(List<Item> &list)
list.empty(); // Fields are used
}
+
+/*
+ Resolve references to table column for a function and it's argument
+
+ SYNOPSIS:
+ fix_fields()
+ thd Thread object
+ tables List of all open tables involved in the query
+ ref Pointer to where this object is used. This reference
+ is used if we want to replace this object with another
+ one (for example in the summary functions).
+
+ DESCRIPTION
+ Call fix_fields() for all arguments to the function. The main intention
+ is to allow all Item_field() objects to setup pointers to the table fields.
+
+ Sets as a side effect the following class variables:
+ maybe_null Set if any argument may return NULL
+ with_sum_func Set if any of the arguments contains a sum function
+ used_table_cache Set to union of the arguments used table
+
+ str_value.charset If this is a string function, set this to the
+ character set for the first argument.
+ If any argument is binary, this is set to binary
+
+ If for any item any of the defaults are wrong, then this can
+ be fixed in the fix_length_and_dec() function that is called
+ after this one or by writing a specialized fix_fields() for the
+ item.
+
+ RETURN VALUES
+ 0 ok
+ 1 Got error. Stored with my_error().
+*/
+
bool
-Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
+Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function
- binary=0;
+
used_tables_cache=0;
const_item_cache=1;
@@ -68,35 +105,61 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
return 0; // Fatal error if flag is set!
if (arg_count)
{ // Print purify happy
+ CHARSET_INFO *charset= 0;
+ /*
+ Set return character set to first argument if we are returning a
+ string.
+ */
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
- if ((*arg)->fix_fields(thd,tables))
+ if ((*arg)->fix_fields(thd, tables, arg) ||
+ (*arg)->check_cols(allowed_arg_cols))
return 1; /* purecov: inspected */
if ((*arg)->maybe_null)
maybe_null=1;
- if ((*arg)->binary)
- binary=1;
+ if ((*arg)->binary())
+ charset= &my_charset_bin;
+ else if (!charset && (*arg)->result_type() == STRING_RESULT)
+ charset= (*arg)->charset();
with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item();
}
+ /*
+ We must set charset here as fix_length_and_dec() may want to change
+ charset
+ */
+ if (charset && result_type() == STRING_RESULT)
+ set_charset(charset);
}
fix_length_and_dec();
+ fixed= 1;
return 0;
}
+void Item_func::set_outer_resolving()
+{
+ if (arg_count)
+ {
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ (*arg)->set_outer_resolving();
+ }
+}
-void Item_func::split_sum_func(List<Item> &fields)
+void Item_func::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{
- Item **arg,**arg_end;
- for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
+ Item **arg, **arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
{
if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
- (*arg)->split_sum_func(fields);
+ (*arg)->split_sum_func(ref_pointer_array, fields);
else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(*arg);
- *arg=new Item_ref((Item**) fields.head_ref(),0,(*arg)->name);
+ ref_pointer_array[el]= *arg;
+ *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
}
}
}
@@ -165,14 +228,11 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
return 1;
}
-
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
Field *res;
LINT_INIT(res);
- if (!t_arg)
- return result_field;
switch (result_type()) {
case INT_RESULT:
if (max_length > 11)
@@ -187,9 +247,13 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
break;
case STRING_RESULT:
if (max_length > 255)
- res= new Field_blob(max_length, maybe_null, name, t_arg, binary);
+ res= new Field_blob(max_length, maybe_null, name, t_arg, charset());
else
- res= new Field_string(max_length, maybe_null, name, t_arg, binary);
+ res= new Field_string(max_length, maybe_null, name, t_arg, charset());
+ break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
break;
}
return res;
@@ -202,7 +266,7 @@ String *Item_real_func::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
@@ -215,9 +279,9 @@ String *Item_num_func::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else if (!unsigned_flag)
- str->set(nr);
+ str->set(nr,thd_charset());
else
- str->set((ulonglong) nr);
+ str->set((ulonglong) nr,thd_charset());
}
else
{
@@ -225,7 +289,7 @@ String *Item_num_func::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
}
return str;
}
@@ -239,15 +303,22 @@ void Item_func::fix_num_length_and_dec()
max_length=float_length(decimals);
}
+Item *Item_func::get_tmp_table_item(THD *thd)
+{
+ if (!with_sum_func && !const_item())
+ return new Item_field(result_field);
+ return copy_or_same(thd);
+}
+
String *Item_int_func::val_str(String *str)
{
longlong nr=val_int();
if (null_value)
return 0;
else if (!unsigned_flag)
- str->set(nr);
+ str->set(nr,thd_charset());
else
- str->set((ulonglong) nr);
+ str->set((ulonglong) nr,thd_charset());
return str;
}
@@ -274,9 +345,9 @@ String *Item_num_op::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else if (!unsigned_flag)
- str->set(nr);
+ str->set(nr,thd_charset());
else
- str->set((ulonglong) nr);
+ str->set((ulonglong) nr,thd_charset());
}
else
{
@@ -284,7 +355,7 @@ String *Item_num_op::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
}
return str;
}
@@ -320,7 +391,7 @@ void Item_func_minus::fix_length_and_dec()
{
Item_num_op::fix_length_and_dec();
if (unsigned_flag &&
- (current_thd->sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
+ (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
unsigned_flag=0;
}
@@ -398,6 +469,25 @@ void Item_func_div::fix_length_and_dec()
maybe_null=1;
}
+
+/* Integer division */
+longlong Item_func_int_div::val_int()
+{
+ longlong value=args[0]->val_int();
+ longlong val2=args[1]->val_int();
+ if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value))
+ return 0;
+ return value/val2;
+}
+
+
+void Item_func_int_div::fix_length_and_dec()
+{
+ max_length=args[0]->max_length - args[0]->decimals;
+ maybe_null=1;
+}
+
+
double Item_func_mod::val()
{
double value= floor(args[0]->val()+0.5);
@@ -753,7 +843,6 @@ void Item_func_min_max::fix_length_and_dec()
decimals=0;
max_length=0;
maybe_null=1;
- binary=0;
cmp_type=args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
@@ -764,9 +853,11 @@ void Item_func_min_max::fix_length_and_dec()
if (!args[i]->maybe_null)
maybe_null=0;
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
- if (args[i]->binary)
- binary=1;
+ if (args[i]->binary())
+ set_charset(&my_charset_bin);
}
+ if (cmp_type == STRING_RESULT)
+ str_cmp_function= binary() ? stringcmp : sortcmp;
}
@@ -779,9 +870,9 @@ String *Item_func_min_max::val_str(String *str)
if (null_value)
return 0;
else if (!unsigned_flag)
- str->set(nr);
+ str->set(nr,thd_charset());
else
- str->set((ulonglong) nr);
+ str->set((ulonglong) nr,thd_charset());
return str;
}
case REAL_RESULT:
@@ -790,7 +881,7 @@ String *Item_func_min_max::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
case STRING_RESULT:
@@ -811,7 +902,7 @@ String *Item_func_min_max::val_str(String *str)
res2= args[i]->val_str(res == str ? &tmp_value : str);
if (res2)
{
- int cmp=binary ? stringcmp(res,res2) : sortcmp(res,res2);
+ int cmp= (*str_cmp_function)(res,res2);
if ((cmp_sign < 0 ? cmp : -cmp) < 0)
res=res2;
}
@@ -819,6 +910,11 @@ String *Item_func_min_max::val_str(String *str)
}
return res;
}
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
+
}
return 0; // Keep compiler happy
}
@@ -867,6 +963,18 @@ longlong Item_func_min_max::val_int()
return value;
}
+longlong Item_func_crc32::val_int()
+{
+ String *res=args[0]->val_str(&value);
+ if (!res)
+ {
+ null_value=1;
+ return 0; /* purecov: inspected */
+ }
+ null_value=0;
+ return (longlong) crc32(0L, (Bytef*)res->ptr(), res->length());
+}
+
longlong Item_func_length::val_int()
{
@@ -889,7 +997,7 @@ longlong Item_func_char_length::val_int()
return 0; /* purecov: inspected */
}
null_value=0;
- return (longlong) (!args[0]->binary) ? res->numchars() : res->length();
+ return (longlong) (!args[0]->binary()) ? res->numchars() : res->length();
}
@@ -897,7 +1005,6 @@ longlong Item_func_locate::val_int()
{
String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2);
- bool binary_str = args[0]->binary || args[1]->binary;
if (!a || !b)
{
null_value=1;
@@ -912,10 +1019,10 @@ longlong Item_func_locate::val_int()
{
start=(uint) args[2]->val_int()-1;
#ifdef USE_MB
- if (use_mb(default_charset_info))
+ if (use_mb(a->charset()))
{
start0=start;
- if (!binary_str)
+ if (!binary_cmp)
start=a->charpos(start);
}
#endif
@@ -925,7 +1032,7 @@ longlong Item_func_locate::val_int()
if (!b->length()) // Found empty string at start
return (longlong) (start+1);
#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary_str)
+ if (use_mb(a->charset()) && !binary_cmp)
{
const char *ptr=a->ptr()+start;
const char *search=b->ptr();
@@ -944,14 +1051,15 @@ longlong Item_func_locate::val_int()
return (longlong) start0+1;
}
skipp:
- if ((l=my_ismbchar(default_charset_info,ptr,strend))) ptr+=l;
+ if ((l=my_ismbchar(a->charset(),ptr,strend)))
+ ptr+=l;
else ++ptr;
++start0;
}
return 0;
}
#endif /* USE_MB */
- return (longlong) (binary ? a->strstr(*b,start) :
+ return (longlong) (binary_cmp ? a->strstr(*b,start) :
(a->strstr_case(*b,start)))+1;
}
@@ -971,18 +1079,23 @@ longlong Item_func_field::val_int()
return 0;
}
-void Item_func_field::split_sum_func(List<Item> &fields)
+
+void Item_func_field::split_sum_func(Item **ref_pointer_array,
+ List<Item> &fields)
{
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(fields);
+ item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(item);
- item= new Item_ref((Item**) fields.head_ref(), 0, item->name);
- }
- Item_func::split_sum_func(fields);
+ ref_pointer_array[el]= item;
+ item= new Item_ref(ref_pointer_array + el, 0, item->name);
+ }
+ Item_func::split_sum_func(ref_pointer_array, fields);
}
+
longlong Item_func_ascii::val_int()
{
String *res=args[0]->val_str(&value);
@@ -1006,12 +1119,12 @@ longlong Item_func_ord::val_int()
null_value=0;
if (!res->length()) return 0;
#ifdef USE_MB
- if (use_mb(default_charset_info) && !args[0]->binary)
+ if (use_mb(res->charset()) && !args[0]->binary())
{
register const char *str=res->ptr();
- register uint32 n=0, l=my_ismbchar(default_charset_info,
- str,str+res->length());
- if (!l) return (longlong)((uchar) *str);
+ register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
+ if (!l)
+ return (longlong)((uchar) *str);
while (l--)
n=(n<<8)|(uint32)((uchar) *str++);
return (longlong) n;
@@ -1071,6 +1184,7 @@ longlong Item_func_find_in_set::val_int()
null_value=0;
int diff;
+ CHARSET_INFO *charset= find->charset();
if ((diff=buffer->length() - find->length()) >= 0)
{
const char *f_pos=find->ptr();
@@ -1084,7 +1198,7 @@ longlong Item_func_find_in_set::val_int()
const char *pos= f_pos;
while (pos != f_end)
{
- if (toupper(*str) != toupper(*pos))
+ if (my_toupper(charset,*str) != my_toupper(charset,*pos))
goto not_found;
str++;
pos++;
@@ -1179,7 +1293,7 @@ udf_handler::~udf_handler()
bool
-udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
+udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
uint arg_count, Item **arguments)
{
char buff[STACK_BUFF_ALLOC]; // Max argument in function
@@ -1192,11 +1306,11 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
}
else
thd=current_thd; // In WHERE / const clause
- udf_func *tmp_udf=find_udf(u_d->name,(uint) strlen(u_d->name),1);
+ udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
if (!tmp_udf)
{
- my_printf_error(ER_CANT_FIND_UDF,ER(ER_CANT_FIND_UDF),MYF(0),u_d->name,
+ my_printf_error(ER_CANT_FIND_UDF,ER(ER_CANT_FIND_UDF),MYF(0),u_d->name.str,
errno);
DBUG_RETURN(1);
}
@@ -1204,7 +1318,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
args=arguments;
/* Fix all arguments */
- func->binary=func->maybe_null=0;
+ func->maybe_null=0;
used_tables_cache=0;
const_item_cache=1;
@@ -1223,10 +1337,10 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
- if ((*arg)->fix_fields(thd,tables))
+ if ((*arg)->fix_fields(thd, tables, arg) || (*arg)->check_cols(1))
return 1;
- if ((*arg)->binary)
- func->binary=1;
+ if ((*arg)->binary())
+ func->set_charset(&my_charset_bin);
if ((*arg)->maybe_null)
func->maybe_null=1;
func->with_sum_func= func->with_sum_func || (*arg)->with_sum_func;
@@ -1352,6 +1466,10 @@ bool udf_handler::get_arguments()
to+= ALIGN_SIZE(sizeof(double));
}
break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ ;
}
}
return 0;
@@ -1389,7 +1507,7 @@ String *udf_handler::val_str(String *str,String *save_str)
str->length(res_length);
return str;
}
- save_str->set(res, res_length);
+ save_str->set(res, res_length, default_charset_info);
return save_str;
}
@@ -1410,7 +1528,7 @@ String *Item_func_udf_float::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
@@ -1431,9 +1549,9 @@ String *Item_func_udf_int::val_str(String *str)
if (null_value)
return 0;
else if (!unsigned_flag)
- str->set(nr);
+ str->set(nr,thd_charset());
else
- str->set((ulonglong) nr);
+ str->set((ulonglong) nr,thd_charset());
return str;
}
@@ -1514,7 +1632,8 @@ char *ull_get_key(const ULL *ull,uint *length,
void item_user_lock_init(void)
{
pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
- hash_init(&hash_user_locks,16,0,0,(hash_get_key) ull_get_key,NULL,0);
+ hash_init(&hash_user_locks,system_charset_info,
+ 16,0,0,(hash_get_key) ull_get_key,NULL,0);
}
void item_user_lock_free(void)
@@ -1529,9 +1648,9 @@ void item_user_lock_release(ULL *ull)
if (mysql_bin_log.is_open())
{
char buf[256];
- String tmp(buf,sizeof(buf));
- tmp.length(0);
- tmp.append("DO RELEASE_LOCK(\"");
+ const char *command="DO RELEASE_LOCK(\"";
+ String tmp(buf,sizeof(buf), system_charset_info);
+ tmp.copy(command, strlen(command), tmp.charset());
tmp.append(ull->key,ull->key_length);
tmp.append("\")");
Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1);
@@ -1553,7 +1672,7 @@ longlong Item_master_pos_wait::val_int()
{
THD* thd = current_thd;
String *log_name = args[0]->val_str(&value);
- int event_count;
+ int event_count= 0;
null_value=0;
if (thd->slave_thread || !log_name || !log_name->length())
@@ -1561,15 +1680,17 @@ longlong Item_master_pos_wait::val_int()
null_value = 1;
return 0;
}
- longlong pos = args[1]->val_int();
+ longlong pos = (ulong)args[1]->val_int();
longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
+#ifdef HAVE_REPLICATION
LOCK_ACTIVE_MI;
- if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
- {
+ if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
+ {
null_value = 1;
event_count=0;
}
UNLOCK_ACTIVE_MI;
+#endif
return event_count;
}
@@ -1790,7 +1911,7 @@ longlong Item_func_set_last_insert_id::val_int()
longlong Item_func_benchmark::val_int()
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff), &my_charset_bin);
THD *thd=current_thd;
for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++)
@@ -1805,6 +1926,10 @@ longlong Item_func_benchmark::val_int()
case STRING_RESULT:
(void) args[0]->val_str(&tmp);
break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
}
}
return 0;
@@ -1833,6 +1958,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
entry->value=0;
entry->length=0;
entry->update_query_id=0;
+ entry->used_query_id=current_thd->query_id;
entry->type=STRING_RESULT;
memcpy(entry->name.str, name.str, name.length+1);
if (hash_insert(hash,(byte*) entry))
@@ -1845,11 +1971,11 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
}
-bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables)
+bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
+ Item **ref)
{
- if (!thd)
- thd=current_thd; // Should never happen
- if (Item_func::fix_fields(thd,tables) ||
+ /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
+ if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return 1;
entry->update_query_id=thd->query_id;
@@ -1867,7 +1993,8 @@ Item_func_set_user_var::fix_length_and_dec()
}
void Item_func_set_user_var::update_hash(void *ptr, uint length,
- Item_result type)
+ Item_result type,
+ CHARSET_INFO *cs)
{
if ((null_value=args[0]->null_value))
{
@@ -1876,6 +2003,7 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length,
my_free(entry->value,MYF(0));
entry->value=0;
entry->length=0;
+ entry->var_charset=cs;
}
else
{
@@ -1906,11 +2034,12 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length,
memcpy(entry->value,ptr,length);
entry->length= length;
entry->type=type;
+ entry->var_charset=cs;
}
return;
err:
- current_thd->fatal_error=1; // Probably end of memory
+ current_thd->fatal_error(); // Probably end of memory
null_value=1;
return;
}
@@ -1927,12 +2056,18 @@ Item_func_set_user_var::update()
(void) val_int();
break;
case STRING_RESULT:
+ {
char buffer[MAX_FIELD_WIDTH];
- String tmp(buffer,sizeof(buffer));
+ String tmp(buffer,sizeof(buffer),&my_charset_bin);
(void) val_str(&tmp);
break;
}
- return current_thd->fatal_error;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
+ }
+ return current_thd->is_fatal_error;
}
@@ -1940,7 +2075,7 @@ double
Item_func_set_user_var::val()
{
double value=args[0]->val();
- update_hash((void*) &value,sizeof(value), REAL_RESULT);
+ update_hash((void*) &value,sizeof(value), REAL_RESULT, default_charset_info);
return value;
}
@@ -1948,7 +2083,7 @@ longlong
Item_func_set_user_var::val_int()
{
longlong value=args[0]->val_int();
- update_hash((void*) &value,sizeof(longlong),INT_RESULT);
+ update_hash((void*) &value,sizeof(longlong),INT_RESULT, default_charset_info);
return value;
}
@@ -1957,9 +2092,9 @@ Item_func_set_user_var::val_str(String *str)
{
String *res=args[0]->val_str(str);
if (!res) // Null value
- update_hash((void*) 0,0,STRING_RESULT);
+ update_hash((void*) 0, 0, STRING_RESULT, default_charset_info);
else
- update_hash(res->c_ptr(),res->length()+1,STRING_RESULT);
+ update_hash(res->c_ptr(),res->length()+1,STRING_RESULT,res->charset());
return res;
}
@@ -1994,18 +2129,22 @@ Item_func_get_user_var::val_str(String *str)
return NULL;
switch (entry->type) {
case REAL_RESULT:
- str->set(*(double*) entry->value,decimals);
+ str->set(*(double*) entry->value,decimals,thd_charset());
break;
case INT_RESULT:
- str->set(*(longlong*) entry->value);
+ str->set(*(longlong*) entry->value,thd_charset());
break;
case STRING_RESULT:
- if (str->copy(entry->value, entry->length-1))
+ if (str->copy(entry->value, entry->length-1, entry->var_charset))
{
null_value=1;
return NULL;
}
break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
}
return str;
}
@@ -2023,6 +2162,10 @@ double Item_func_get_user_var::val()
return (double) *(longlong*) entry->value;
case STRING_RESULT:
return atof(entry->value); // This is null terminated
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
}
return 0.0; // Impossible
}
@@ -2040,18 +2183,66 @@ longlong Item_func_get_user_var::val_int()
return *(longlong*) entry->value;
case STRING_RESULT:
return strtoull(entry->value,NULL,10); // String is null terminated
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
}
return LL(0); // Impossible
}
+/* From sql_parse.cc */
+extern bool is_update_query(enum enum_sql_command command);
void Item_func_get_user_var::fix_length_and_dec()
{
+ BINLOG_USER_VAR_EVENT *user_var_event;
THD *thd=current_thd;
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- var_entry= get_variable(&thd->user_vars, name, 0);
+
+ if ((var_entry= get_variable(&thd->user_vars, name, 0)))
+ {
+ if (opt_bin_log && is_update_query(thd->lex.sql_command) &&
+ var_entry->used_query_id != thd->query_id)
+ {
+ /*
+ First we need to store value of var_entry, when the next situation appers:
+ > set @a:=1;
+ > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
+ We have to write to binlog value @a= 1;
+ */
+ uint size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
+ if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
+ goto err;
+
+ user_var_event->value= (char*) user_var_event +
+ ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
+ user_var_event->user_var_event= var_entry;
+ user_var_event->type= var_entry->type;
+ user_var_event->charset_number= var_entry->var_charset->number;
+ if (!var_entry->value)
+ {
+ /* NULL value*/
+ user_var_event->length= 0;
+ user_var_event->value= 0;
+ }
+ else
+ {
+ user_var_event->length= var_entry->length;
+ memcpy(user_var_event->value, var_entry->value,
+ var_entry->length);
+ }
+ var_entry->used_query_id= thd->query_id;
+ if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event))
+ goto err;
+ }
+ }
+ return;
+err:
+ thd->fatal_error();
+ return;
}
@@ -2106,7 +2297,7 @@ longlong Item_func_inet_aton::val_int()
char c = '.'; // we mark c to indicate invalid IP in case length is 0
char buff[36];
- String *s,tmp(buff,sizeof(buff));
+ String *s,tmp(buff,sizeof(buff),&my_charset_bin);
if (!(s = args[0]->val_str(&tmp))) // If null value
goto err;
null_value=0;
@@ -2145,7 +2336,9 @@ void Item_func_match::init_search(bool no_order)
DBUG_VOID_RETURN;
if (key == NO_SUCH_KEY)
- concat= new Item_func_concat_ws(new Item_string(" ",1), fields);
+ concat=new Item_func_concat_ws(new Item_string(" ",1,
+ default_charset_info),
+ fields);
if (master)
{
@@ -2156,15 +2349,15 @@ void Item_func_match::init_search(bool no_order)
DBUG_VOID_RETURN;
}
- String *ft_tmp=0;
+ String *ft_tmp= 0;
char tmp1[FT_QUERY_MAXLEN];
- String tmp2(tmp1,sizeof(tmp1));
+ String tmp2(tmp1,sizeof(tmp1),default_charset_info);
// MATCH ... AGAINST (NULL) is meaningless, but possible
if (!(ft_tmp=key_item()->val_str(&tmp2)))
{
ft_tmp= &tmp2;
- tmp2.set("",0);
+ tmp2.set("",0,default_charset_info);
}
ft_handler=table->file->ft_init_ext(mode, key,
@@ -2179,7 +2372,7 @@ void Item_func_match::init_search(bool no_order)
}
-bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
+bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
List_iterator<Item> li(fields);
Item *item;
@@ -2193,7 +2386,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
modifications to find_best and auto_close as complement to auto_init code
above.
*/
- if (Item_func::fix_fields(thd,tlist) || !const_item())
+ if (Item_func::fix_fields(thd, tlist, ref) || !const_item())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
return 1;
@@ -2201,7 +2394,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
while ((item=li++))
{
- if (item->fix_fields(thd,tlist))
+ if (item->fix_fields(thd, tlist, li.ref()) || item->check_cols(1))
return 1;
if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref);
@@ -2225,6 +2418,14 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
return 0;
}
+void Item_func_match::set_outer_resolving()
+{
+ Item_real_func::set_outer_resolving();
+ List_iterator<Item> li(fields);
+ Item *item;
+ while ((item= li++))
+ item->set_outer_resolving();
+}
bool Item_func_match::fix_index()
{
@@ -2348,6 +2549,7 @@ double Item_func_match::val()
DBUG_RETURN(ft_handler->please->find_relevance(ft_handler, record, 0));
}
+
longlong Item_func_bit_xor::val_int()
{
ulonglong arg1= (ulonglong) args[0]->val_int();
@@ -2364,23 +2566,24 @@ longlong Item_func_bit_xor::val_int()
Item *get_system_var(enum_var_type var_type, LEX_STRING name)
{
- if (!my_strcasecmp(name.str,"VERSION"))
- return new Item_string("@@VERSION",server_version,
- (uint) strlen(server_version));
+ if (!my_strcasecmp(system_charset_info, name.str, "VERSION"))
+ return new Item_string("@@VERSION", server_version,
+ (uint) strlen(server_version),
+ system_charset_info);
THD *thd=current_thd;
Item *item;
sys_var *var;
char buff[MAX_SYS_VAR_LENGTH+3+8], *pos;
- if (!(var= find_sys_var(name.str)))
+ if (!(var= find_sys_var(name.str, name.length)))
{
- net_printf(&thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name.str);
+ net_printf(thd, ER_UNKNOWN_SYSTEM_VARIABLE, name.str);
return 0;
}
if (!(item=var->item(thd, var_type)))
return 0; // Impossible
- thd->safe_to_cache_query=0;
+ thd->lex.uncacheable();
buff[0]='@';
buff[1]='@';
pos=buff+2;
@@ -2395,6 +2598,23 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
}
+Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
+ const char *item_name)
+{
+ THD *thd=current_thd;
+ Item *item;
+ sys_var *var;
+
+ var= find_sys_var(var_name, length);
+ DBUG_ASSERT(var != 0);
+ if (!(item=var->item(thd, var_type)))
+ return 0; // Impossible
+ thd->lex.uncacheable();
+ item->set_name(item_name); // Will use original name
+ return item;
+}
+
+
/*
Check a user level lock.
@@ -2429,3 +2649,124 @@ longlong Item_func_is_free_lock::val_int()
return 1;
return 0;
}
+
+
+/**************************************************************************
+ Spatial functions
+***************************************************************************/
+
+longlong Item_func_dimension::val_int()
+{
+ uint32 dim;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ args[0]->null_value ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ geom.dimension(&dim));
+
+ return (longlong) dim;
+}
+
+longlong Item_func_numinteriorring::val_int()
+{
+ uint32 num;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,num_interior_ring) ||
+ geom.num_interior_ring(&num));
+
+ return (longlong) num;
+}
+
+longlong Item_func_numgeometries::val_int()
+{
+ uint32 num=0;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,num_geometries) ||
+ geom.num_geometries(&num));
+
+ return (longlong) num;
+}
+
+longlong Item_func_numpoints::val_int()
+{
+ uint32 num=0;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ args[0]->null_value ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,num_points) ||
+ geom.num_points(&num));
+
+ return (longlong) num;
+}
+
+
+double Item_func_x::val()
+{
+ double res=0;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,get_x) ||
+ geom.get_x(&res));
+
+ return res;
+}
+
+
+double Item_func_y::val()
+{
+ double res=0;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,get_y) ||
+ geom.get_y(&res));
+
+ return res;
+}
+
+
+double Item_func_area::val()
+{
+ double res=0;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,area) ||
+ geom.area(&res));
+
+ return res;
+}
+
+
+double Item_func_glength::val()
+{
+ double res=0;
+ String *wkb=args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!wkb ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,length) ||
+ geom.length(&res));
+ return res;
+}
diff --git a/sql/item_func.h b/sql/item_func.h
index 68e5335dc7e..68804b83d26 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -31,7 +31,8 @@ extern "C" /* Bug in BSDI include file */
class Item_func :public Item_result_field
{
protected:
- Item **args,*tmp_arg[2];
+ Item **args, *tmp_arg[2];
+ uint allowed_arg_cols;
public:
uint arg_count;
table_map used_tables_cache;
@@ -39,63 +40,72 @@ public:
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
GE_FUNC,GT_FUNC,FT_FUNC,
LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
- COND_AND_FUNC,COND_OR_FUNC,COND_XOR_FUNC,BETWEEN,IN_FUNC,INTERVAL_FUNC};
+ COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, BETWEEN, IN_FUNC,
+ INTERVAL_FUNC,
+ SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC,
+ SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
+ SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
+ SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING,
+ SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN};
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL };
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
- Item_func(void)
+ Item_func(void):
+ allowed_arg_cols(1), arg_count(0)
{
- arg_count=0; with_sum_func=0;
+ with_sum_func= 0;
}
- Item_func(Item *a)
+ Item_func(Item *a):
+ allowed_arg_cols(1), arg_count(1)
{
- arg_count=1;
- args=tmp_arg;
- args[0]=a;
- with_sum_func=a->with_sum_func;
+ args= tmp_arg;
+ args[0]= a;
+ with_sum_func= a->with_sum_func;
}
- Item_func(Item *a,Item *b)
+ Item_func(Item *a,Item *b):
+ allowed_arg_cols(1), arg_count(2)
{
- arg_count=2;
- args=tmp_arg;
- args[0]=a; args[1]=b;
- with_sum_func=a->with_sum_func || b->with_sum_func;
+ args= tmp_arg;
+ args[0]= a; args[1]= b;
+ with_sum_func= a->with_sum_func || b->with_sum_func;
}
- Item_func(Item *a,Item *b,Item *c)
+ Item_func(Item *a,Item *b,Item *c):
+ allowed_arg_cols(1)
{
- arg_count=0;
- if ((args=(Item**) sql_alloc(sizeof(Item*)*3)))
+ arg_count= 0;
+ if ((args= (Item**) sql_alloc(sizeof(Item*)*3)))
{
- arg_count=3;
- args[0]=a; args[1]=b; args[2]=c;
- with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func;
+ arg_count= 3;
+ args[0]= a; args[1]= b; args[2]= c;
+ with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
}
}
- Item_func(Item *a,Item *b,Item *c,Item *d)
+ Item_func(Item *a,Item *b,Item *c,Item *d):
+ allowed_arg_cols(1)
{
- arg_count=0;
- if ((args=(Item**) sql_alloc(sizeof(Item*)*4)))
+ arg_count= 0;
+ if ((args= (Item**) sql_alloc(sizeof(Item*)*4)))
{
- arg_count=4;
- args[0]=a; args[1]=b; args[2]=c; args[3]=d;
- with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func ||
- d->with_sum_func;
+ arg_count= 4;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d;
+ with_sum_func= a->with_sum_func || b->with_sum_func ||
+ c->with_sum_func || d->with_sum_func;
}
}
- Item_func(Item *a,Item *b,Item *c,Item *d,Item* e)
+ Item_func(Item *a,Item *b,Item *c,Item *d,Item* e):
+ allowed_arg_cols(1)
{
- arg_count=5;
- if ((args=(Item**) sql_alloc(sizeof(Item*)*5)))
+ arg_count= 5;
+ if ((args= (Item**) sql_alloc(sizeof(Item*)*5)))
{
- args[0]=a; args[1]=b; args[2]=c; args[3]=d; args[4]=e;
- with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func ||
- d->with_sum_func || e->with_sum_func ;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
+ with_sum_func= a->with_sum_func || b->with_sum_func ||
+ c->with_sum_func || d->with_sum_func || e->with_sum_func ;
}
}
Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */
- bool fix_fields(THD *,struct st_table_list *);
- void make_field(Send_field *field);
+ bool fix_fields(THD *,struct st_table_list *, Item **ref);
table_map used_tables() const;
void update_used_tables();
bool eq(const Item *item, bool binary_cmp) const;
@@ -107,7 +117,7 @@ public:
inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; }
- virtual void split_sum_func(List<Item> &fields);
+ virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void print(String *str);
void print_op(String *str);
void fix_num_length_and_dec();
@@ -121,8 +131,10 @@ public:
}
bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
- unsigned int size_of() { return sizeof(*this);}
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg);
+ void set_outer_resolving();
+ Item *get_tmp_table_item(THD *thd);
};
@@ -137,7 +149,6 @@ public:
longlong val_int() { return (longlong) val(); }
enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -153,7 +164,6 @@ public:
enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
bool is_null() { (void) val(); return null_value; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -169,7 +179,6 @@ class Item_num_op :public Item_func
void fix_length_and_dec() { fix_num_length_and_dec(); find_num_type(); }
void find_num_type(void);
bool is_null() { (void) val(); return null_value; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -251,6 +260,18 @@ public:
};
+class Item_func_int_div :public Item_num_op
+{
+public:
+ Item_func_int_div(Item *a,Item *b) :Item_num_op(a,b)
+ { hybrid_type=INT_RESULT; }
+ double val() { return (double) val_int(); }
+ longlong val_int();
+ const char *func_name() const { return "DIV"; }
+ void fix_length_and_dec();
+};
+
+
class Item_func_mod :public Item_num_op
{
public:
@@ -495,7 +516,6 @@ class Item_func_units :public Item_real_func
double val();
const char *func_name() const { return name; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -504,15 +524,15 @@ class Item_func_min_max :public Item_func
Item_result cmp_type;
String tmp_value;
int cmp_sign;
+ int (*str_cmp_function)(const String *x,const String *y);
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
- cmp_sign(cmp_sign_arg) {}
+ cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg) {}
double val();
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
enum Item_result result_type () const { return cmp_type; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_min :public Item_func_min_max
@@ -529,6 +549,16 @@ public:
const char *func_name() const { return "greatest"; }
};
+class Item_func_crc32 :public Item_int_func
+{
+ String value;
+public:
+ Item_func_crc32(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "crc32"; }
+ void fix_length_and_dec() { max_length=10; }
+};
+
class Item_func_length :public Item_int_func
{
@@ -538,7 +568,6 @@ public:
longlong val_int();
const char *func_name() const { return "length"; }
void fix_length_and_dec() { max_length=10; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_bit_length :public Item_func_length
@@ -557,19 +586,22 @@ public:
longlong val_int();
const char *func_name() const { return "char_length"; }
void fix_length_and_dec() { max_length=10; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_locate :public Item_int_func
{
String value1,value2;
+ bool binary_cmp;
public:
Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {}
Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
- void fix_length_and_dec() { maybe_null=0; max_length=11; }
- unsigned int size_of() { return sizeof(*this);}
+ void fix_length_and_dec()
+ {
+ maybe_null=0; max_length=11;
+ binary_cmp = args[0]->binary() || args[1]->binary();
+ }
};
@@ -581,11 +613,12 @@ public:
Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
~Item_func_field() { delete item; }
longlong val_int();
- bool fix_fields(THD *thd,struct st_table_list *tlist)
+ bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
{
- return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
+ return (item->fix_fields(thd, tlist, &item) || item->check_cols(1) ||
+ Item_func::fix_fields(thd, tlist, ref));
}
- void split_sum_func(List<Item> &fields);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void update_used_tables()
{
item->update_used_tables() ; Item_func::update_used_tables();
@@ -600,7 +633,11 @@ public:
const_item_cache&= item->const_item();
with_sum_func= with_sum_func || item->with_sum_func;
}
- unsigned int size_of() { return sizeof(*this);}
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_int_func::set_outer_resolving();
+ }
};
@@ -612,7 +649,6 @@ public:
longlong val_int();
const char *func_name() const { return "ascii"; }
void fix_length_and_dec() { max_length=3; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_ord :public Item_int_func
@@ -622,7 +658,6 @@ public:
Item_func_ord(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "ord"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_find_in_set :public Item_int_func
@@ -635,7 +670,6 @@ public:
longlong val_int();
const char *func_name() const { return "find_in_set"; }
void fix_length_and_dec();
- unsigned int size_of() { return sizeof(*this);}
};
@@ -711,7 +745,6 @@ class Item_func_benchmark :public Item_int_func
longlong val_int();
const char *func_name() const { return "benchmark"; }
void fix_length_and_dec() { max_length=1; maybe_null=0; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -728,15 +761,15 @@ public:
:Item_func(list), udf(udf_arg) {}
~Item_udf_func() {}
const char *func_name() const { return udf.name(); }
- bool fix_fields(THD *thd,struct st_table_list *tables)
+ bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
{
- bool res=udf.fix_fields(thd,tables,this,arg_count,args);
- used_tables_cache=udf.used_tables_cache;
- const_item_cache=udf.const_item_cache;
+ bool res= udf.fix_fields(thd, tables, this, arg_count, args);
+ used_tables_cache= udf.used_tables_cache;
+ const_item_cache= udf.const_item_cache;
+ fixed= 1;
return res;
}
Item_result result_type () const { return udf.result_type(); }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -779,13 +812,15 @@ public:
String *val_str(String *);
double val()
{
+ int err;
String *res; res=val_str(&str_value);
- return res ? atof(res->c_ptr()) : 0.0;
+ return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),0,&err) : 0.0;
}
longlong val_int()
{
+ int err;
String *res; res=val_str(&str_value);
- return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0;
+ return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,(char**) 0,&err) : (longlong) 0;
}
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
@@ -845,7 +880,6 @@ class Item_func_get_lock :public Item_int_func
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_release_lock :public Item_int_func
@@ -856,7 +890,6 @@ class Item_func_release_lock :public Item_int_func
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
- unsigned int size_of() { return sizeof(*this);}
};
/* replication functions */
@@ -870,7 +903,6 @@ class Item_master_pos_wait :public Item_int_func
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
void fix_length_and_dec() { max_length=21; maybe_null=1;}
- unsigned int size_of() { return sizeof(*this);}
};
@@ -885,18 +917,19 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry;
public:
- Item_func_set_user_var(LEX_STRING a,Item *b): Item_func(b), name(a) {}
+ Item_func_set_user_var(LEX_STRING a,Item *b)
+ :Item_func(b), cached_result_type(INT_RESULT), name(a)
+ {}
double val();
longlong val_int();
String *val_str(String *str);
- void update_hash(void *ptr, uint length, enum Item_result type);
+ void update_hash(void *ptr, uint length, enum Item_result type, CHARSET_INFO *cs);
bool update();
enum Item_result result_type () const { return cached_result_type; }
- bool fix_fields(THD *thd,struct st_table_list *tables);
+ bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
void fix_length_and_dec();
void print(String *str);
const char *func_name() const { return "set_user_var"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -915,12 +948,16 @@ public:
void fix_length_and_dec();
void print(String *str);
enum Item_result result_type() const;
+ /*
+ We must always return variables as strings to guard against selects of type
+ select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
+ */
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
const char *func_name() const { return "get_user_var"; }
bool const_item() const;
table_map used_tables() const
{ return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
- unsigned int size_of() { return sizeof(*this);}
};
@@ -960,7 +997,7 @@ public:
{
ft_handler->please->close_search(ft_handler);
ft_handler=0;
- if(join_key)
+ if (join_key)
table->file->ft_handler=0;
table->fulltext_searched=0;
}
@@ -969,14 +1006,98 @@ public:
}
enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {}
- bool fix_fields(THD *thd,struct st_table_list *tlist);
+ bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
longlong val_int() { return val()!=0.0; }
double val();
bool fix_index();
void init_search(bool no_order);
- unsigned int size_of() { return sizeof(*this);}
+ void set_outer_resolving();
+};
+
+
+class Item_func_dimension :public Item_int_func
+{
+ String value;
+public:
+ Item_func_dimension(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "dimension"; }
+ void fix_length_and_dec() { max_length=10; }
+};
+
+
+class Item_func_x :public Item_real_func
+{
+ String value;
+public:
+ Item_func_x(Item *a) :Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "x"; }
+};
+
+
+class Item_func_y :public Item_real_func
+{
+ String value;
+public:
+ Item_func_y(Item *a) :Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "y"; }
+};
+
+
+class Item_func_numgeometries :public Item_int_func
+{
+ String value;
+public:
+ Item_func_numgeometries(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "numgeometries"; }
+ void fix_length_and_dec() { max_length=10; }
+};
+
+
+class Item_func_numinteriorring :public Item_int_func
+{
+ String value;
+public:
+ Item_func_numinteriorring(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "numinteriorring"; }
+ void fix_length_and_dec() { max_length=10; }
+};
+
+
+class Item_func_numpoints :public Item_int_func
+{
+ String value;
+public:
+ Item_func_numpoints(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "numpoints"; }
+ void fix_length_and_dec() { max_length=10; }
+};
+
+
+class Item_func_area :public Item_real_func
+{
+ String value;
+public:
+ Item_func_area(Item *a) :Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "area"; }
+};
+
+
+class Item_func_glength :public Item_real_func
+{
+ String value;
+public:
+ Item_func_glength(Item *a) :Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "glength"; }
};
@@ -999,16 +1120,6 @@ public:
const char *func_name() const { return "match_bool"; }
};
-/* For type casts */
-
-enum Item_cast
-{
- ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
- ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR
-};
-
-Item *create_func_cast(Item *a, Item_cast cast_type);
-
class Item_func_bit_xor : public Item_int_func
{
@@ -1027,5 +1138,12 @@ public:
longlong val_int();
const char *func_name() const { return "check_lock"; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
- unsigned int size_of() { return sizeof(*this);}
+};
+
+/* For type casts */
+
+enum Item_cast
+{
+ ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
+ ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR
};
diff --git a/sql/item_row.cc b/sql/item_row.cc
new file mode 100644
index 00000000000..cf745e21e45
--- /dev/null
+++ b/sql/item_row.cc
@@ -0,0 +1,131 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "mysql_priv.h"
+
+/*
+ Row items used for comparing rows and IN operations on rows:
+
+ (a, b, c) > (10, 10, 30)
+ (a, b, c) = (select c, d, e, from t1 where x=12)
+ (a, b, c) IN ((1,2,2), (3,4,5), (6,7,8)
+ (a, b, c) IN (select c, d, e, from t1)
+*/
+
+Item_row::Item_row(List<Item> &arg):
+ Item(), used_tables_cache(0), array_holder(1), const_item_cache(1), with_null(0)
+{
+
+ //TODO: think placing 2-3 component items in item (as it done for function)
+ if ((arg_count= arg.elements))
+ items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
+ else
+ items= 0;
+ List_iterator<Item> li(arg);
+ uint i= 0;
+ Item *item;
+ while ((item= li++))
+ {
+ items[i]= item;
+ i++;
+ }
+}
+
+void Item_row::illegal_method_call(const char *method)
+{
+ DBUG_ENTER("Item_row::illegal_method_call");
+ DBUG_PRINT("error", ("!!! %s method was called for row item", method));
+ DBUG_ASSERT(0);
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ DBUG_VOID_RETURN;
+}
+
+bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
+{
+ null_value= 0;
+ maybe_null= 0;
+ Item **arg, **arg_end;
+ for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
+ {
+ if ((*arg)->fix_fields(thd, tabl, arg))
+ return 1;
+ used_tables_cache |= (*arg)->used_tables();
+ if (const_item_cache&= (*arg)->const_item() && !with_null)
+ {
+ if ((*arg)->cols() > 1)
+ with_null|= (*arg)->null_inside();
+ else
+ {
+ (*arg)->val_int();
+ with_null|= (*arg)->null_value;
+ }
+ }
+ maybe_null|= (*arg)->maybe_null;
+ with_sum_func= with_sum_func || (*arg)->with_sum_func;
+ }
+ return 0;
+}
+
+void Item_row::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
+{
+ Item **arg, **arg_end;
+ for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
+ {
+ if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
+ (*arg)->split_sum_func(ref_pointer_array, fields);
+ else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
+ {
+ uint el= fields.elements;
+ fields.push_front(*arg);
+ ref_pointer_array[el]= *arg;
+ *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
+ }
+ }
+}
+
+void Item_row::update_used_tables()
+{
+ used_tables_cache= 0;
+ const_item_cache= 1;
+ for (uint i= 0; i < arg_count; i++)
+ {
+ items[i]->update_used_tables();
+ used_tables_cache|= items[i]->used_tables();
+ const_item_cache&= items[i]->const_item();
+ }
+}
+
+bool Item_row::check_cols(uint c)
+{
+ if (c != arg_count)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), c);
+ return 1;
+ }
+ return 0;
+}
+
+void Item_row::bring_value()
+{
+ for (uint i= 0; i < arg_count; i++)
+ items[i]->bring_value();
+}
+
+void Item_row::set_outer_resolving()
+{
+ for (uint i= 0; i < arg_count; i++)
+ items[i]->set_outer_resolving();
+}
diff --git a/sql/item_row.h b/sql/item_row.h
new file mode 100644
index 00000000000..4f674d8a561
--- /dev/null
+++ b/sql/item_row.h
@@ -0,0 +1,79 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+class Item_row: public Item
+{
+ Item **items;
+ table_map used_tables_cache;
+ uint arg_count;
+ bool array_holder;
+ bool const_item_cache;
+ bool with_null;
+public:
+ Item_row(List<Item> &);
+ Item_row(Item_row *item):
+ Item(),
+ items(item->items),
+ used_tables_cache(item->used_tables_cache),
+ arg_count(item->arg_count),
+ array_holder(0),
+ const_item_cache(item->const_item_cache),
+ with_null(0)
+ {}
+
+ ~Item_row()
+ {
+ if (array_holder && items)
+ sql_element_free(items);
+ }
+
+ enum Type type() const { return ROW_ITEM; };
+ void illegal_method_call(const char *);
+ bool is_null() { return null_value; }
+ void make_field(Send_field *)
+ {
+ illegal_method_call((const char*)"make_field");
+ };
+ double val()
+ {
+ illegal_method_call((const char*)"val");
+ return 0;
+ };
+ longlong val_int()
+ {
+ illegal_method_call((const char*)"val_int");
+ return 0;
+ };
+ String *val_str(String *)
+ {
+ illegal_method_call((const char*)"val_str");
+ return 0;
+ };
+ bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
+ table_map used_tables() const { return used_tables_cache; };
+ bool const_item() const { return const_item_cache; };
+ enum Item_result result_type() const { return ROW_RESULT; }
+ void update_used_tables();
+ void set_outer_resolving();
+
+ uint cols() { return arg_count; }
+ Item* el(uint i) { return items[i]; }
+ Item** addr(uint i) { return items + i; }
+ bool check_cols(uint c);
+ bool null_inside() { return with_null; };
+ void bring_value();
+};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index f1e37889d5f..bb844feffb5 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -37,14 +37,14 @@
#include "sha1.h"
#include "my_aes.h"
-String empty_string("");
+String empty_string("",default_charset_info);
uint nr_of_decimals(const char *str)
{
if ((str=strchr(str,'.')))
{
const char *start= ++str;
- for (; isdigit(*str) ; str++) ;
+ for (; my_isdigit(system_charset_info,*str) ; str++) ;
return (uint) (str-start);
}
return 0;
@@ -52,16 +52,19 @@ uint nr_of_decimals(const char *str)
double Item_str_func::val()
{
+ int err;
String *res;
res=val_str(&str_value);
- return res ? atof(res->c_ptr()) : 0.0;
+ return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
+ NULL, &err) : 0.0;
}
longlong Item_str_func::val_int()
{
+ int err;
String *res;
res=val_str(&str_value);
- return res ? strtoll(res->c_ptr(),NULL,10) : (longlong) 0;
+ return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,NULL,&err) : (longlong) 0;
}
@@ -124,12 +127,12 @@ String *Item_func_sha::val_str(String *str)
digest[8], digest[9], digest[10], digest[11],
digest[12], digest[13], digest[14], digest[15],
digest[16], digest[17], digest[18], digest[19]);
-
+
str->length((uint) SHA1_HASH_SIZE*2);
null_value=0;
return str;
}
- }
+ }
null_value=1;
return 0;
}
@@ -145,7 +148,7 @@ void Item_func_sha::fix_length_and_dec()
String *Item_func_aes_encrypt::val_str(String *str)
{
char key_buff[80];
- String tmp_key_value(key_buff, sizeof(key_buff));
+ String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
String *sptr= args[0]->val_str(str); // String to encrypt
String *key= args[1]->val_str(&tmp_key_value); // key
int aes_length;
@@ -153,13 +156,13 @@ String *Item_func_aes_encrypt::val_str(String *str)
{
null_value=0;
aes_length=my_aes_get_size(sptr->length()); // Calculate result length
-
+
if (!str_value.alloc(aes_length)) // Ensure that memory is free
{
// finally encrypt directly to allocated buffer.
if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str_value.ptr(),
key->ptr(), key->length()) == aes_length)
- {
+ {
// We got the expected result length
str_value.length((uint) aes_length);
return &str_value;
@@ -180,7 +183,8 @@ void Item_func_aes_encrypt::fix_length_and_dec()
String *Item_func_aes_decrypt::val_str(String *str)
{
char key_buff[80];
- String tmp_key_value(key_buff, sizeof(key_buff)), *sptr, *key;
+ String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
+ String *sptr, *key;
DBUG_ENTER("Item_func_aes_decrypt::val_str");
sptr= args[0]->val_str(str); // String to decrypt
@@ -196,7 +200,7 @@ String *Item_func_aes_decrypt::val_str(String *str)
(char*) str_value.ptr(),
key->ptr(), key->length());
if (length >= 0) // if we got correct data data
- {
+ {
str_value.length((uint) length);
DBUG_RETURN(&str_value);
}
@@ -231,6 +235,8 @@ String *Item_func_concat::val_str(String *str)
use_as_buff= &tmp_value;
for (i=1 ; i < arg_count ; i++)
{
+ if (args[i]->binary())
+ set_charset(&my_charset_bin);
if (res->length() == 0)
{
if (!(res=args[i]->val_str(str)))
@@ -259,6 +265,7 @@ String *Item_func_concat::val_str(String *str)
str->append(*res2);
}
res=str;
+ res->set_charset(charset());
}
else if (res == &tmp_value)
{
@@ -270,6 +277,7 @@ String *Item_func_concat::val_str(String *str)
if (tmp_value.replace(0,0,*res))
goto null;
res= &tmp_value;
+ res->set_charset(charset());
use_as_buff=str; // Put next arg here
}
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
@@ -288,6 +296,7 @@ String *Item_func_concat::val_str(String *str)
*res))
goto null;
res= &tmp_value;
+ res->set_charset(charset());
use_as_buff=str; // Put next arg here
}
else
@@ -297,6 +306,7 @@ String *Item_func_concat::val_str(String *str)
tmp_value.append(*res2))
goto null;
res= &tmp_value;
+ res->set_charset(charset());
use_as_buff=str;
}
}
@@ -321,7 +331,7 @@ void Item_func_concat::fix_length_and_dec()
}
}
-/*
+/*
Function des_encrypt() by tonu@spam.ee & monty
Works only if compiled with OpenSSL library support.
This returns a binary string where first character is CHAR(128 | key-number).
@@ -378,10 +388,10 @@ String *Item_func_des_encrypt::val_str(String *str)
des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
}
- /*
+ /*
The problem: DES algorithm requires original data to be in 8-bytes
- chunks. Missing bytes get filled with '*'s and result of encryption
- can be up to 8 bytes longer than original string. When decrypted,
+ chunks. Missing bytes get filled with '*'s and result of encryption
+ can be up to 8 bytes longer than original string. When decrypted,
we do not know the size of original string :(
We add one byte with value 0x1..0x8 as the last byte of the padded
string marking change of string length.
@@ -452,7 +462,7 @@ String *Item_func_des_decrypt::val_str(String *str)
// Here we set all 64-bit keys (56 effective) one by one
des_set_key_unchecked(&keyblock.key1,keyschedule.ks1);
des_set_key_unchecked(&keyblock.key2,keyschedule.ks2);
- des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
+ des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
}
if (tmp_value.alloc(length-1))
goto error;
@@ -478,7 +488,7 @@ error:
}
-/*
+/*
concat with separator. First arg is the separator
concat_ws takes at least two arguments.
*/
@@ -486,7 +496,7 @@ error:
String *Item_func_concat_ws::val_str(String *str)
{
char tmp_str_buff[10];
- String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff)),
+ String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
*sep_str, *res, *res2,*use_as_buff;
uint i;
@@ -587,16 +597,19 @@ null:
return 0;
}
-void Item_func_concat_ws::split_sum_func(List<Item> &fields)
+void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array,
+ List<Item> &fields)
{
if (separator->with_sum_func && separator->type() != SUM_FUNC_ITEM)
- separator->split_sum_func(fields);
+ separator->split_sum_func(ref_pointer_array, fields);
else if (separator->used_tables() || separator->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(separator);
- separator= new Item_ref((Item**) fields.head_ref(), 0, separator->name);
- }
- Item_str_func::split_sum_func(fields);
+ ref_pointer_array[el]= separator;
+ separator= new Item_ref(ref_pointer_array + el, 0, separator->name);
+ }
+ Item_str_func::split_sum_func(ref_pointer_array, fields);
}
void Item_func_concat_ws::fix_length_and_dec()
@@ -637,7 +650,7 @@ String *Item_func_reverse::val_str(String *str)
ptr = (char *) res->ptr();
end=ptr+res->length();
#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
+ if (use_mb(res->charset()) && !binary())
{
String tmpstr;
tmpstr.copy(*res);
@@ -645,7 +658,7 @@ String *Item_func_reverse::val_str(String *str)
register uint32 l;
while (ptr < end)
{
- if ((l=my_ismbchar(default_charset_info, ptr,end)))
+ if ((l=my_ismbchar(res->charset(), ptr,end)))
tmp-=l, memcpy(tmp,ptr,l), ptr+=l;
else
*--tmp=*ptr++;
@@ -688,8 +701,7 @@ String *Item_func_replace::val_str(String *str)
#ifdef USE_MB
const char *ptr,*end,*strend,*search,*search_end;
register uint32 l;
- bool binary_str = (args[0]->binary || args[1]->binary ||
- !use_mb(default_charset_info));
+ bool binary_cmp;
#endif
null_value=0;
@@ -700,6 +712,10 @@ String *Item_func_replace::val_str(String *str)
if (args[1]->null_value)
goto null;
+#ifdef USE_MB
+ binary_cmp = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset()));
+#endif
+
if (res2->length() == 0)
return res;
#ifndef USE_MB
@@ -707,7 +723,7 @@ String *Item_func_replace::val_str(String *str)
return res;
#else
offset=0;
- if (binary_str && (offset=res->strstr(*res2)) < 0)
+ if (binary_cmp && (offset=res->strstr(*res2)) < 0)
return res;
#endif
if (!(res3=args[2]->val_str(&tmp_value2)))
@@ -716,7 +732,7 @@ String *Item_func_replace::val_str(String *str)
to_length= res3->length();
#ifdef USE_MB
- if (!binary_str)
+ if (!binary_cmp)
{
search=res2->ptr();
search_end=search+from_length;
@@ -746,7 +762,7 @@ redo:
goto redo;
}
skipp:
- if ((l=my_ismbchar(default_charset_info, ptr,strend))) ptr+=l;
+ if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
else ++ptr;
}
}
@@ -804,13 +820,8 @@ String *Item_func_insert::val_str(String *str)
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
args[3]->null_value)
goto null; /* purecov: inspected */
-#ifdef USE_MB
- if (use_mb(default_charset_info) && !args[0]->binary)
- {
- start=res->charpos(start);
- length=res->charpos(length,start);
- }
-#endif
+ start=res->charpos(start);
+ length=res->charpos(length,start);
if (start > res->length()+1)
return res; // Wrong param; skip insert
if (length > res->length()-start)
@@ -877,15 +888,13 @@ String *Item_func_left::val_str(String *str)
return 0;
if (length <= 0)
return &empty_string;
-#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
- length = res->charpos(length);
-#endif
+ length= res->charpos(length);
if (res->length() > (ulong) length)
{ // Safe even if const arg
if (!res->alloced_length())
{ // Don't change const str
str_value= *res; // Not malloced string
+ set_charset(res->charset());
res= &str_value;
}
res->length((uint) length);
@@ -925,19 +934,11 @@ String *Item_func_right::val_str(String *str)
return &empty_string; /* purecov: inspected */
if (res->length() <= (uint) length)
return res; /* purecov: inspected */
-#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
- {
- uint start=res->numchars()-(uint) length;
- if (start<=0) return res;
- start=res->charpos(start);
- tmp_value.set(*res,start,res->length()-start);
- }
- else
-#endif
- {
- tmp_value.set(*res,(res->length()- (uint) length),(uint) length);
- }
+
+ uint start=res->numchars()-(uint) length;
+ if (start<=0) return res;
+ start=res->charpos(start);
+ tmp_value.set(*res,start,res->length()-start);
return &tmp_value;
}
@@ -958,13 +959,8 @@ String *Item_func_substr::val_str(String *str)
if ((null_value=(args[0]->null_value || args[1]->null_value ||
(arg_count == 3 && args[2]->null_value))))
return 0; /* purecov: inspected */
-#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
- {
- start=res->charpos(start);
- length=res->charpos(length,start);
- }
-#endif
+ start=res->charpos(start);
+ length=res->charpos(length,start);
if (start < 0 || (uint) start+1 > res->length() || length <= 0)
return &empty_string;
@@ -1019,7 +1015,7 @@ String *Item_func_substr_index::val_str(String *str)
return &empty_string; // Wrong parameters
#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
+ if (use_mb(res->charset()) && !binary())
{
const char *ptr=res->ptr();
const char *strend = ptr+res->length();
@@ -1044,7 +1040,7 @@ String *Item_func_substr_index::val_str(String *str)
continue;
}
skipp:
- if ((l=my_ismbchar(default_charset_info, ptr,strend))) ptr+=l;
+ if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
else ++ptr;
} /* either not found or got total number when count<0 */
if (pass == 0) /* count<0 */
@@ -1116,7 +1112,7 @@ String *Item_func_ltrim::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff),res->charset());
String *remove_str=args[1]->val_str(&tmp);
uint remove_length;
LINT_INIT(remove_length);
@@ -1154,7 +1150,7 @@ String *Item_func_rtrim::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff),res->charset());
String *remove_str=args[1]->val_str(&tmp);
uint remove_length;
LINT_INIT(remove_length);
@@ -1173,11 +1169,11 @@ String *Item_func_rtrim::val_str(String *str)
{
char chr=(*remove_str)[0];
#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
+ if (use_mb(res->charset()) && !binary())
{
while (ptr < end)
{
- if ((l=my_ismbchar(default_charset_info, ptr,end))) ptr+=l,p=ptr;
+ if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr;
else ++ptr;
}
ptr=p;
@@ -1190,12 +1186,12 @@ String *Item_func_rtrim::val_str(String *str)
{
const char *r_ptr=remove_str->ptr();
#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
+ if (use_mb(res->charset()) && !binary())
{
loop:
while (ptr + remove_length < end)
{
- if ((l=my_ismbchar(default_charset_info, ptr,end))) ptr+=l;
+ if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
else ++ptr;
}
if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
@@ -1226,7 +1222,7 @@ String *Item_func_trim::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff),res->charset());
String *remove_str=args[1]->val_str(&tmp);
uint remove_length;
LINT_INIT(remove_length);
@@ -1241,14 +1237,14 @@ String *Item_func_trim::val_str(String *str)
while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
ptr+=remove_length;
#ifdef USE_MB
- if (use_mb(default_charset_info) && !binary)
+ if (use_mb(res->charset()) && !binary())
{
char *p=ptr;
register uint32 l;
loop:
while (ptr + remove_length < end)
{
- if ((l=my_ismbchar(default_charset_info, ptr,end))) ptr+=l;
+ if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
else ++ptr;
}
if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
@@ -1272,19 +1268,83 @@ String *Item_func_trim::val_str(String *str)
return &tmp_value;
}
+void Item_func_password::fix_length_and_dec()
+{
+ max_length= get_password_length(use_old_passwords);
+}
+
+/*
+ Password() function has 2 arguments. Second argument can be used
+ to make results repeatable
+*/
String *Item_func_password::val_str(String *str)
{
+ struct rand_struct rand_st; // local structure for 2 param version
+ ulong seed=0; // seed to initialise random generator to
+
+ String *res =args[0]->val_str(str);
+ if ((null_value=args[0]->null_value))
+ return 0;
+
+ if (arg_count == 1)
+ {
+ if (res->length() == 0)
+ return &empty_string;
+ make_scrambled_password(tmp_value,res->c_ptr(),use_old_passwords,
+ &current_thd->rand);
+ str->set(tmp_value,get_password_length(use_old_passwords),res->charset());
+ return str;
+ }
+ else
+ {
+ /* We'll need the buffer to get second parameter */
+ char key_buff[80];
+ String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
+ String *key =args[1]->val_str(&tmp_key_value);
+
+ /* Check second argument for NULL value. First one is already checked */
+ if ((null_value=args[1]->null_value))
+ return 0;
+
+ /* This shall be done after checking for null for proper results */
+ if (res->length() == 0)
+ return &empty_string;
+
+ /* Generate the seed first this allows to avoid double allocation */
+ char* seed_ptr=key->c_ptr();
+ while (*seed_ptr)
+ {
+ seed=(seed*211+*seed_ptr) & 0xffffffffL; /* Use simple hashing */
+ seed_ptr++;
+ }
+
+ /* Use constants which allow nice random values even with small seed */
+ randominit(&rand_st,
+ (ulong) ((ulonglong) seed*111111+33333333L) & (ulong) 0xffffffff,
+ (ulong) ((ulonglong) seed*1111+55555555L) & (ulong) 0xffffffff);
+
+ make_scrambled_password(tmp_value,res->c_ptr(),use_old_passwords,
+ &rand_st);
+ str->set(tmp_value,get_password_length(use_old_passwords),res->charset());
+ return str;
+ }
+}
+
+String *Item_func_old_password::val_str(String *str)
+{
String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
if (res->length() == 0)
return &empty_string;
- make_scrambled_password(tmp_value,res->c_ptr());
- str->set(tmp_value,16);
+ make_scrambled_password(tmp_value,res->c_ptr(),1,&current_thd->rand);
+ str->set(tmp_value,16,res->charset());
return str;
}
+
+
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
String *Item_func_encrypt::val_str(String *str)
@@ -1315,7 +1375,7 @@ String *Item_func_encrypt::val_str(String *str)
}
pthread_mutex_lock(&LOCK_crypt);
char *tmp=crypt(res->c_ptr(),salt_ptr);
- str->set(tmp,(uint) strlen(tmp));
+ str->set(tmp,(uint) strlen(tmp),res->charset());
str->copy();
pthread_mutex_unlock(&LOCK_crypt);
return str;
@@ -1364,20 +1424,30 @@ String *Item_func_decode::val_str(String *str)
String *Item_func_database::val_str(String *str)
{
- if (!current_thd->db)
+ THD *thd= current_thd;
+ if (!thd->db)
str->length(0);
else
- str->set((const char*) current_thd->db,(uint) strlen(current_thd->db));
+ str->copy((const char*) thd->db,(uint) strlen(thd->db),
+ system_charset_info, thd->variables.thd_charset);
return str;
}
String *Item_func_user::val_str(String *str)
{
- THD *thd=current_thd;
- if (str->copy((const char*) thd->user,(uint) strlen(thd->user)) ||
- str->append('@') ||
- str->append(thd->host ? thd->host : thd->ip ? thd->ip : ""))
- return &empty_string;
+ THD *thd=current_thd;
+ CHARSET_INFO *cs=thd->variables.thd_charset;
+ const char *host=thd->host ? thd->host : thd->ip ? thd->ip : "";
+ uint32 res_length=(strlen(thd->user)+strlen(host)+10) * cs->mbmaxlen;
+
+ if (str->alloc(res_length))
+ {
+ null_value=1;
+ return 0;
+ }
+ res_length=cs->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",thd->user,host);
+ str->length(res_length);
+ str->set_charset(cs);
return str;
}
@@ -1398,9 +1468,9 @@ extern "C" {
extern const char *soundex_map; // In mysys/static.c
}
-static char get_scode(char *ptr)
+static char get_scode(CHARSET_INFO *cs,char *ptr)
{
- uchar ch=toupper(*ptr);
+ uchar ch=my_toupper(cs,*ptr);
if (ch < 'A' || ch > 'Z')
{
// Thread extended alfa (country spec)
@@ -1414,6 +1484,8 @@ String *Item_func_soundex::val_str(String *str)
{
String *res =args[0]->val_str(str);
char last_ch,ch;
+ CHARSET_INFO *cs= &my_charset_latin1;
+
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
@@ -1421,22 +1493,23 @@ String *Item_func_soundex::val_str(String *str)
return str; /* purecov: inspected */
char *to= (char *) tmp_value.ptr();
char *from= (char *) res->ptr(), *end=from+res->length();
-
- while (from != end && isspace(*from)) // Skip pre-space
+ tmp_value.set_charset(cs);
+
+ while (from != end && my_isspace(cs,*from)) // Skip pre-space
from++; /* purecov: inspected */
if (from == end)
return &empty_string; // No alpha characters.
- *to++ = toupper(*from); // Copy first letter
- last_ch = get_scode(from); // code of the first letter
+ *to++ = my_toupper(cs,*from); // Copy first letter
+ last_ch = get_scode(cs,from); // code of the first letter
// for the first 'double-letter check.
// Loop on input letters until
// end of input (null) or output
// letter code count = 3
for (from++ ; from < end ; from++)
{
- if (!isalpha(*from))
+ if (!my_isalpha(cs,*from))
continue;
- ch=get_scode(from);
+ ch=get_scode(cs,from);
if ((ch != '0') && (ch != last_ch)) // if not skipped or double
{
*to++ = ch; // letter, copy to output
@@ -1470,7 +1543,7 @@ String *Item_func_format::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
dec= decimals ? decimals+1 : 0;
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
str_length=str->length();
if (nr < 0)
str_length--; // Don't count sign
@@ -1513,16 +1586,19 @@ void Item_func_elt::fix_length_and_dec()
}
-void Item_func_elt::split_sum_func(List<Item> &fields)
+void Item_func_elt::split_sum_func(Item **ref_pointer_array,
+ List<Item> &fields)
{
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(fields);
+ item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(item);
- item= new Item_ref((Item**) fields.head_ref(), 0, item->name);
- }
- Item_str_func::split_sum_func(fields);
+ ref_pointer_array[el]= item;
+ item= new Item_ref(ref_pointer_array + el, 0, item->name);
+ }
+ Item_str_func::split_sum_func(ref_pointer_array, fields);
}
@@ -1572,16 +1648,19 @@ String *Item_func_elt::val_str(String *str)
}
-void Item_func_make_set::split_sum_func(List<Item> &fields)
+void Item_func_make_set::split_sum_func(Item **ref_pointer_array,
+ List<Item> &fields)
{
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(fields);
+ item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
fields.push_front(item);
- item= new Item_ref((Item**) fields.head_ref(), 0, item->name);
- }
- Item_str_func::split_sum_func(fields);
+ ref_pointer_array[el]= item;
+ item= new Item_ref(ref_pointer_array + el, 0, item->name);
+ }
+ Item_str_func::split_sum_func(ref_pointer_array, fields);
}
@@ -1665,7 +1744,7 @@ String *Item_func_char::val_str(String *str)
int32 num=(int32) args[i]->val_int();
if (!args[i]->null_value)
#ifdef USE_MB
- if (use_mb(default_charset_info))
+ if (use_mb(charset()))
{
if (num&0xFF000000L) {
str->append((char)(num>>24));
@@ -1673,7 +1752,7 @@ String *Item_func_char::val_str(String *str)
} else if (num&0xFF0000L) {
b2: str->append((char)(num>>16));
goto b1;
- } else if (num&0xFF00L) {
+ } else if (num&0xFF00L) {
b1: str->append((char)(num>>8));
}
}
@@ -1913,6 +1992,7 @@ String *Item_func_conv::val_str(String *str)
longlong dec;
int from_base= (int) args[1]->val_int();
int to_base= (int) args[2]->val_int();
+ int err;
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
abs(to_base) > 36 || abs(to_base) < 2 ||
@@ -1923,16 +2003,239 @@ String *Item_func_conv::val_str(String *str)
}
null_value=0;
if (from_base < 0)
- dec= strtoll(res->c_ptr(),&endptr,-from_base);
+ dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err);
else
- dec= (longlong) strtoull(res->c_ptr(),&endptr,from_base);
+ dec= (longlong) my_strntoull(res->charset(),res->ptr(),res->length(),from_base,&endptr,&err);
ptr= longlong2str(dec,ans,to_base);
- if (str->copy(ans,(uint32) (ptr-ans)))
+ if (str->copy(ans,(uint32) (ptr-ans), thd_charset()))
return &empty_string;
return str;
}
+String *Item_func_conv_charset::val_str(String *str)
+{
+ my_wc_t wc;
+ int cnvres;
+ const uchar *s, *se;
+ uchar *d, *d0, *de;
+ uint32 dmaxlen;
+ String *arg= args[0]->val_str(str);
+ CHARSET_INFO *from,*to;
+
+ if (!arg)
+ {
+ null_value=1;
+ return 0;
+ }
+ null_value=0;
+
+ from=arg->charset();
+ to=conv_charset;
+
+ s=(const uchar*)arg->ptr();
+ se=s+arg->length();
+
+ dmaxlen=arg->length()*to->mbmaxlen+1;
+ str->alloc(dmaxlen);
+ d0=d=(unsigned char*)str->ptr();
+ de=d+dmaxlen;
+
+ while (1)
+ {
+ cnvres=from->mb_wc(from,&wc,s,se);
+ if (cnvres>0)
+ {
+ s+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILSEQ)
+ {
+ s++;
+ wc='?';
+ }
+ else
+ break;
+
+outp:
+ cnvres=to->wc_mb(to,wc,d,de);
+ if (cnvres>0)
+ {
+ d+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILUNI && wc!='?')
+ {
+ wc='?';
+ goto outp;
+ }
+ else
+ break;
+ };
+
+ str->length((uint32) (d-d0));
+ str->set_charset(to);
+ return str;
+}
+
+void Item_func_conv_charset::fix_length_and_dec()
+{
+ max_length = args[0]->max_length*conv_charset->mbmaxlen;
+ set_charset(conv_charset);
+}
+
+
+
+String *Item_func_conv_charset3::val_str(String *str)
+{
+ my_wc_t wc;
+ int cnvres;
+ const uchar *s, *se;
+ uchar *d, *d0, *de;
+ uint32 dmaxlen;
+ String *arg= args[0]->val_str(str);
+ String *to_cs= args[1]->val_str(str);
+ String *from_cs= args[2]->val_str(str);
+ CHARSET_INFO *from_charset;
+ CHARSET_INFO *to_charset;
+
+ if (!arg || args[0]->null_value ||
+ !to_cs || args[1]->null_value ||
+ !from_cs || args[2]->null_value ||
+ !(from_charset=get_charset_by_name(from_cs->ptr(), MYF(MY_WME))) ||
+ !(to_charset=get_charset_by_name(to_cs->ptr(), MYF(MY_WME))))
+ {
+ null_value=1;
+ return 0;
+ }
+
+ s=(const uchar*)arg->ptr();
+ se=s+arg->length();
+
+ dmaxlen=arg->length()*to_charset->mbmaxlen+1;
+ str->alloc(dmaxlen);
+ d0=d=(unsigned char*)str->ptr();
+ de=d+dmaxlen;
+
+ while (1)
+ {
+ cnvres=from_charset->mb_wc(from_charset,&wc,s,se);
+ if (cnvres>0)
+ {
+ s+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILSEQ)
+ {
+ s++;
+ wc='?';
+ }
+ else
+ break;
+
+outp:
+ cnvres=to_charset->wc_mb(to_charset,wc,d,de);
+ if (cnvres>0)
+ {
+ d+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILUNI && wc!='?')
+ {
+ wc='?';
+ goto outp;
+ }
+ else
+ break;
+ };
+
+ str->length((uint32) (d-d0));
+ str->set_charset(to_charset);
+ return str;
+}
+
+
+bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables, Item **ref)
+{
+ char buff[STACK_BUFF_ALLOC]; // Max argument in function
+ used_tables_cache=0;
+ const_item_cache=1;
+
+ if (thd && check_stack_overrun(thd,buff))
+ return 0; // Fatal error if flag is set!
+ if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1))
+ return 1;
+ maybe_null=args[0]->maybe_null;
+ const_item_cache=args[0]->const_item();
+ set_charset(conv_charset);
+ fix_length_and_dec();
+ fixed= 1;
+ return 0;
+}
+
+
+void Item_func_conv_charset3::fix_length_and_dec()
+{
+ max_length = args[0]->max_length;
+}
+
+String *Item_func_set_collation::val_str(String *str)
+{
+ str=args[0]->val_str(str);
+ if ((null_value=args[0]->null_value))
+ return 0;
+ str->set_charset(set_collation);
+ return str;
+}
+
+bool Item_func_set_collation::fix_fields(THD *thd,struct st_table_list *tables, Item **ref)
+{
+ char buff[STACK_BUFF_ALLOC]; // Max argument in function
+ used_tables_cache=0;
+ const_item_cache=1;
+
+ if (thd && check_stack_overrun(thd,buff))
+ return 0; // Fatal error if flag is set!
+ if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1))
+ return 1;
+ maybe_null=args[0]->maybe_null;
+ set_charset(set_collation);
+ with_sum_func= with_sum_func || args[0]->with_sum_func;
+ used_tables_cache=args[0]->used_tables();
+ const_item_cache=args[0]->const_item();
+ fix_length_and_dec();
+ fixed= 1;
+ return 0;
+}
+
+bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
+{
+ /* Assume we don't have rtti */
+ if (this == item)
+ return 1;
+ if (item->type() != FUNC_ITEM)
+ return 0;
+ Item_func *item_func=(Item_func*) item;
+ if (arg_count != item_func->arg_count ||
+ func_name() != item_func->func_name())
+ return 0;
+ Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item;
+ if (set_collation != item_func_sc->set_collation)
+ return 0;
+ for (uint i=0; i < arg_count ; i++)
+ if (!args[i]->eq(item_func_sc->args[i], binary_cmp))
+ return 0;
+ return 1;
+}
+
+String *Item_func_charset::val_str(String *str)
+{
+ String *res = args[0]->val_str(str);
+
+ if ((null_value=(args[0]->null_value || !res->charset())))
+ return 0;
+ str->copy(res->charset()->name,strlen(res->charset()->name),
+ &my_charset_latin1, thd_charset());
+ return str;
+}
+
+
String *Item_func_hex::val_str(String *str)
{
if (args[0]->result_type() != STRING_RESULT)
@@ -1943,7 +2246,7 @@ String *Item_func_hex::val_str(String *str)
if ((null_value= args[0]->null_value))
return 0;
ptr= longlong2str(dec,ans,16);
- if (str->copy(ans,(uint32) (ptr-ans)))
+ if (str->copy(ans,(uint32) (ptr-ans),default_charset_info))
return &empty_string; // End of memory
return str;
}
@@ -2017,11 +2320,11 @@ err:
String* Item_func_export_set::val_str(String* str)
{
ulonglong the_set = (ulonglong) args[0]->val_int();
- String yes_buf, *yes;
+ String yes_buf, *yes;
yes = args[1]->val_str(&yes_buf);
- String no_buf, *no;
+ String no_buf, *no;
no = args[2]->val_str(&no_buf);
- String *sep = NULL, sep_buf ;
+ String *sep = NULL, sep_buf ;
uint num_set_values = 64;
ulonglong mask = 0x1;
@@ -2052,7 +2355,7 @@ String* Item_func_export_set::val_str(String* str)
}
break;
case 3:
- sep_buf.set(",", 1);
+ sep_buf.set(",", 1, default_charset_info);
sep = &sep_buf;
}
null_value=0;
@@ -2095,7 +2398,7 @@ String* Item_func_inet_ntoa::val_str(String* str)
int4store(buf,n);
/* Now we can assume little endian. */
-
+
num[3]='.';
for (p=buf+4 ; p-- > buf ; )
{
@@ -2116,6 +2419,7 @@ String* Item_func_inet_ntoa::val_str(String* str)
return str;
}
+
/*
QUOTE() function returns argument string in single quotes suitable for
using in a SQL statement.
@@ -2123,7 +2427,7 @@ String* Item_func_inet_ntoa::val_str(String* str)
DESCRIPTION
Adds a \ before all characters that needs to be escaped in a SQL string.
We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when
- running commands from a file in windows.
+ running commands from a file in windows.
This function is very useful when you want to generate SQL statements
@@ -2139,7 +2443,7 @@ String *Item_func_quote::val_str(String *str)
/*
Bit mask that has 1 for set for the position of the following characters:
0, \, ' and ^Z
- */
+ */
static uchar escmask[32]=
{
@@ -2206,3 +2510,342 @@ null:
null_value= 1;
return 0;
}
+
+
+/*******************************************************
+General functions for spatial objects
+********************************************************/
+
+String *Item_func_geometry_from_text::val_str(String *str)
+{
+ Geometry geom;
+ String arg_val;
+ String *wkt = args[0]->val_str(&arg_val);
+ GTextReadStream trs(wkt->ptr(), wkt->length());
+
+ str->length(0);
+ if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0))))
+ return 0;
+ return str;
+}
+
+
+void Item_func_geometry_from_text::fix_length_and_dec()
+{
+ max_length=MAX_BLOB_WIDTH;
+}
+
+
+String *Item_func_as_text::val_str(String *str)
+{
+ String arg_val;
+ String *wkt = args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value=(args[0]->null_value ||
+ geom.create_from_wkb(wkt->ptr(),wkt->length()))))
+ return 0;
+
+ str->length(0);
+
+ if ((null_value=geom.as_wkt(str)))
+ return 0;
+
+ return str;
+}
+
+void Item_func_as_text::fix_length_and_dec()
+{
+ max_length=MAX_BLOB_WIDTH;
+}
+
+String *Item_func_geometry_type::val_str(String *str)
+{
+ String *wkt = args[0]->val_str(str);
+ Geometry geom;
+
+ if ((null_value=(args[0]->null_value ||
+ geom.create_from_wkb(wkt->ptr(),wkt->length()))))
+ return 0;
+ str->copy(geom.get_class_info()->m_name,
+ strlen(geom.get_class_info()->m_name),
+ default_charset_info);
+ return str;
+}
+
+
+String *Item_func_envelope::val_str(String *str)
+{
+ String *res = args[0]->val_str(str);
+ Geometry geom;
+
+ if ((null_value = args[0]->null_value ||
+ geom.create_from_wkb(res->ptr(),res->length())))
+ return 0;
+
+ res->length(0);
+ return (null_value= geom.envelope(res)) ? 0 : res;
+}
+
+
+String *Item_func_centroid::val_str(String *str)
+{
+ String arg_val;
+ String *wkb = args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ null_value = args[0]->null_value ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
+ !GEOM_METHOD_PRESENT(geom,centroid) ||
+ geom.centroid(str);
+
+ return null_value ? 0: str;
+}
+
+
+/***********************************************
+ Spatial decomposition functions
+***********************************************/
+
+String *Item_func_spatial_decomp::val_str(String *str)
+{
+ String arg_val;
+ String *wkb = args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value = (args[0]->null_value ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()))))
+ return 0;
+
+ null_value=1;
+ str->length(0);
+ switch(decomp_func)
+ {
+ case SP_STARTPOINT:
+ if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
+ goto ret;
+ break;
+
+ case SP_ENDPOINT:
+ if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
+ goto ret;
+ break;
+
+ case SP_EXTERIORRING:
+ if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
+ goto ret;
+ break;
+
+ default:
+ goto ret;
+ }
+ null_value=0;
+
+ret:
+ return null_value ? 0 : str;
+}
+
+
+String *Item_func_spatial_decomp_n::val_str(String *str)
+{
+ String arg_val;
+ String *wkb = args[0]->val_str(&arg_val);
+ long n = (long) args[1]->val_int();
+ Geometry geom;
+
+ if ((null_value = (args[0]->null_value ||
+ args[1]->null_value ||
+ geom.create_from_wkb(wkb->ptr(),wkb->length()) )))
+ return 0;
+
+ null_value=1;
+
+ switch(decomp_func_n)
+ {
+ case SP_POINTN:
+ if (!GEOM_METHOD_PRESENT(geom,point_n) ||
+ geom.point_n(n,str))
+ goto ret;
+ break;
+
+ case SP_GEOMETRYN:
+ if (!GEOM_METHOD_PRESENT(geom,geometry_n) ||
+ geom.geometry_n(n,str))
+ goto ret;
+ break;
+
+ case SP_INTERIORRINGN:
+ if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
+ geom.interior_ring_n(n,str))
+ goto ret;
+ break;
+
+ default:
+ goto ret;
+ }
+ null_value=0;
+
+ret:
+ return null_value ? 0 : str;
+}
+
+
+
+/***********************************************
+Functions to concatinate various spatial objects
+************************************************/
+
+
+/*
+* Concatinate doubles into Point
+*/
+
+
+String *Item_func_point::val_str(String *str)
+{
+ double x= args[0]->val();
+ double y= args[1]->val();
+
+ if ( (null_value = (args[0]->null_value ||
+ args[1]->null_value ||
+ str->realloc(1+4+8+8))))
+ return 0;
+
+ str->length(0);
+ str->q_append((char)Geometry::wkbNDR);
+ str->q_append((uint32)Geometry::wkbPoint);
+ str->q_append(x);
+ str->q_append(y);
+ return str;
+}
+
+
+/*
+ Concatinates various items into various collections
+ with checkings for valid wkb type of items.
+ For example, MultiPoint can be a collection of Points only.
+ coll_type contains wkb type of target collection.
+ item_type contains a valid wkb type of items.
+ In the case when coll_type is wkbGeometryCollection,
+ we do not check wkb type of items, any is valid.
+*/
+
+String *Item_func_spatial_collection::val_str(String *str)
+{
+ String arg_value;
+ uint i;
+
+ null_value=1;
+
+ str->length(0);
+ if (str->reserve(9,512))
+ return 0;
+
+ str->q_append((char)Geometry::wkbNDR);
+ str->q_append((uint32)coll_type);
+ str->q_append((uint32)arg_count);
+
+ for (i = 0; i < arg_count; ++i)
+ {
+ String *res = args[i]->val_str(&arg_value);
+ if (args[i]->null_value)
+ goto ret;
+
+ if ( coll_type == Geometry::wkbGeometryCollection )
+ {
+ /*
+ In the case of GeometryCollection we don't need
+ any checkings for item types, so just copy them
+ into target collection
+ */
+ if ((null_value=(str->reserve(res->length(),512))))
+ goto ret;
+
+ str->q_append(res->ptr(),res->length());
+ }
+ else
+ {
+ enum Geometry::wkbType wkb_type;
+ uint32 len=res->length();
+ const char *data=res->ptr()+1;
+
+ /*
+ In the case of named collection we must to
+ check that items are of specific type, let's
+ do this checking now
+ */
+
+ if (len < 5)
+ goto ret;
+ wkb_type= (Geometry::wkbType) uint4korr(data);
+ data+=4;
+ len-=5;
+ if (wkb_type != item_type)
+ goto ret;
+
+ switch (coll_type) {
+ case Geometry::wkbMultiPoint:
+ case Geometry::wkbMultiLineString:
+ case Geometry::wkbMultiPolygon:
+ if (len < WKB_HEADER_SIZE)
+ goto ret;
+
+ data-=WKB_HEADER_SIZE;
+ len+=WKB_HEADER_SIZE;
+ if (str->reserve(len,512))
+ goto ret;
+ str->q_append(data,len);
+ break;
+
+ case Geometry::wkbLineString:
+ if (str->reserve(POINT_DATA_SIZE,512))
+ goto ret;
+ str->q_append(data,POINT_DATA_SIZE);
+ break;
+
+ case Geometry::wkbPolygon:
+ {
+ uint32 n_points;
+ double x1, y1, x2, y2;
+
+ if (len < 4 + 2 * POINT_DATA_SIZE)
+ goto ret;
+
+ uint32 llen=len;
+ const char *ldata=data;
+
+ n_points=uint4korr(data);
+ data+=4;
+ float8get(x1,data);
+ data+=8;
+ float8get(y1,data);
+ data+=8;
+
+ data+=(n_points-2) * POINT_DATA_SIZE;
+
+ float8get(x2,data);
+ float8get(y2,data+8);
+
+ if ((x1 != x2) || (y1 != y2))
+ goto ret;
+
+ if (str->reserve(llen,512))
+ goto ret;
+ str->q_append(ldata, llen);
+ }
+ break;
+
+ default:
+ goto ret;
+ }
+ }
+ }
+
+ if (str->length() > current_thd->variables.max_allowed_packet)
+ goto ret;
+
+ null_value = 0;
+
+ret:
+ return null_value ? 0 : str;
+}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 5c9706ed633..b2e54474494 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,10 +35,8 @@ public:
double val();
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
- unsigned int size_of() { return sizeof(*this);}
};
-
class Item_func_md5 :public Item_str_func
{
String tmp_value;
@@ -47,7 +45,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "md5"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -88,7 +85,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "concat"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_concat_ws :public Item_str_func
@@ -103,13 +99,19 @@ public:
String *val_str(String *);
void fix_length_and_dec();
void update_used_tables();
- bool fix_fields(THD *thd,struct st_table_list *tlist)
+ bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
- return (separator->fix_fields(thd,tlist)
- || Item_func::fix_fields(thd,tlist));
+ return (separator->fix_fields(thd, tlist, &separator) ||
+ separator->check_cols(1) ||
+ Item_func::fix_fields(thd, tlist, ref));
}
- void split_sum_func(List<Item> &fields);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
const char *func_name() const { return "concat_ws"; }
+ void set_outer_resolving()
+ {
+ separator->set_outer_resolving();
+ Item_func::set_outer_resolving();
+ }
};
class Item_func_reverse :public Item_str_func
@@ -130,7 +132,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "replace"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -143,7 +144,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "insert"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -190,7 +190,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "right"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -203,7 +202,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "substr"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -215,7 +213,6 @@ public:
String *val_str(String *);
void fix_length_and_dec() { max_length= args[0]->max_length; }
const char *func_name() const { return "substr_index"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -227,7 +224,6 @@ public:
String *val_str(String *);
void fix_length_and_dec() { max_length= args[0]->max_length; }
const char *func_name() const { return "ltrim"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -239,7 +235,6 @@ public:
String *val_str(String *);
void fix_length_and_dec() { max_length= args[0]->max_length; }
const char *func_name() const { return "rtrim"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_trim :public Item_str_func
@@ -250,21 +245,33 @@ public:
String *val_str(String *);
void fix_length_and_dec() { max_length= args[0]->max_length; }
const char *func_name() const { return "trim"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_password :public Item_str_func
{
- char tmp_value[17];
+ char tmp_value[64]; /* This should be enough for new password format */
public:
Item_func_password(Item *a) :Item_str_func(a) {}
+ Item_func_password(Item *a, Item *b) :Item_str_func(a,b) {}
String *val_str(String *);
- void fix_length_and_dec() { max_length = 16; }
+ void fix_length_and_dec();
const char *func_name() const { return "password"; }
- unsigned int size_of() { return sizeof(*this);}
};
+
+class Item_func_old_password :public Item_str_func
+{
+ char tmp_value[17]; /* old password length +1 */
+public:
+ Item_func_old_password(Item *a) :Item_str_func(a) {}
+ String *val_str(String *);
+ void fix_length_and_dec() { max_length = get_password_length(1); }
+ const char *func_name() const { return "old_password"; }
+};
+
+
+
class Item_func_des_encrypt :public Item_str_func
{
String tmp_value;
@@ -275,7 +282,6 @@ public:
void fix_length_and_dec()
{ maybe_null=1; max_length = args[0]->max_length+8; }
const char *func_name() const { return "des_encrypt"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_des_decrypt :public Item_str_func
@@ -287,7 +293,6 @@ public:
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = args[0]->max_length; }
const char *func_name() const { return "des_decrypt"; }
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_encrypt :public Item_str_func
@@ -298,7 +303,6 @@ public:
Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
- unsigned int size_of() { return sizeof(*this);}
};
#include "sql_crypt.h"
@@ -312,7 +316,6 @@ public:
Item_str_func(a),sql_crypt(seed) {}
String *val_str(String *);
void fix_length_and_dec();
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_decode :public Item_func_encode
@@ -328,7 +331,11 @@ class Item_func_database :public Item_str_func
public:
Item_func_database() {}
String *val_str(String *);
- void fix_length_and_dec() { max_length= MAX_FIELD_NAME; }
+ void fix_length_and_dec()
+ {
+ max_length= MAX_FIELD_NAME * thd_charset()->mbmaxlen;
+ set_charset(thd_charset());
+ }
const char *func_name() const { return "database"; }
};
@@ -337,7 +344,11 @@ class Item_func_user :public Item_str_func
public:
Item_func_user() {}
String *val_str(String *);
- void fix_length_and_dec() { max_length= USERNAME_LENGTH+HOSTNAME_LENGTH+1; }
+ void fix_length_and_dec()
+ {
+ max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*thd_charset()->mbmaxlen;
+ set_charset(thd_charset());
+ }
const char *func_name() const { return "user"; }
};
@@ -350,7 +361,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "soundex"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -364,15 +374,21 @@ public:
double val();
longlong val_int();
String *val_str(String *str);
- bool fix_fields(THD *thd,struct st_table_list *tlist)
+ bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
- return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
+ return (item->fix_fields(thd, tlist, &item) ||
+ item->check_cols(1) ||
+ Item_func::fix_fields(thd, tlist, ref));
}
- void split_sum_func(List<Item> &fields);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void fix_length_and_dec();
void update_used_tables();
const char *func_name() const { return "elt"; }
- unsigned int size_of() { return sizeof(*this);}
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_str_func::set_outer_resolving();
+ }
};
@@ -385,15 +401,21 @@ public:
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
~Item_func_make_set() { delete item; }
String *val_str(String *str);
- bool fix_fields(THD *thd,struct st_table_list *tlist)
+ bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
- return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
+ return (item->fix_fields(thd, tlist, &item) ||
+ item->check_cols(1) ||
+ Item_func::fix_fields(thd, tlist, ref));
}
- void split_sum_func(List<Item> &fields);
+ void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void fix_length_and_dec();
void update_used_tables();
const char *func_name() const { return "make_set"; }
- unsigned int size_of() { return sizeof(*this);}
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_str_func::set_outer_resolving();
+ }
};
@@ -408,7 +430,6 @@ public:
max_length=args[0]->max_length+(args[0]->max_length-args[0]->decimals)/3;
}
const char *func_name() const { return "format"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -417,7 +438,7 @@ class Item_func_char :public Item_str_func
public:
Item_func_char(List<Item> &list) :Item_str_func(list) {}
String *val_str(String *);
- void fix_length_and_dec() { maybe_null=0; max_length=arg_count; binary=0;}
+ void fix_length_and_dec() { maybe_null=0; max_length=arg_count; }
const char *func_name() const { return "char"; }
};
@@ -430,7 +451,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "repeat"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -443,7 +463,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "rpad"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -456,7 +475,6 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "lpad"; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -478,7 +496,6 @@ public:
const char *func_name() const { return "hex"; }
String *val_str(String *);
void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length*2; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -491,9 +508,14 @@ public:
{
String *tmp=args[0]->val_str(a);
null_value=args[0]->null_value;
+ tmp->set_charset(&my_charset_bin);
return tmp;
- }
- void fix_length_and_dec() { binary=1; max_length=args[0]->max_length; }
+ }
+ void fix_length_and_dec()
+ {
+ set_charset(&my_charset_bin);
+ max_length=args[0]->max_length;
+ }
void print(String *str) { print_op(str); }
};
@@ -506,8 +528,11 @@ public:
String *val_str(String *);
const char *func_name() const { return "load_file"; }
void fix_length_and_dec()
- { binary=1; maybe_null=1; max_length=MAX_BLOB_WIDTH;}
- unsigned int size_of() { return sizeof(*this);}
+ {
+ set_charset(&my_charset_bin);
+ maybe_null=1;
+ max_length=MAX_BLOB_WIDTH;
+ }
};
@@ -522,7 +547,7 @@ class Item_func_export_set: public Item_str_func
const char *func_name() const { return "export_set"; }
};
- class Item_func_inet_ntoa : public Item_str_func
+class Item_func_inet_ntoa : public Item_str_func
{
public:
Item_func_inet_ntoa(Item *a) :Item_str_func(a)
@@ -541,3 +566,245 @@ public:
String *val_str(String *);
void fix_length_and_dec() { max_length= args[0]->max_length * 2 + 2; }
};
+
+class Item_func_conv_charset :public Item_str_func
+{
+ CHARSET_INFO *conv_charset;
+public:
+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
+ { conv_charset=cs; }
+ bool fix_fields(THD *thd,struct st_table_list *tables,Item **ref);
+ String *val_str(String *);
+ void fix_length_and_dec();
+ const char *func_name() const { return "conv_charset"; }
+};
+
+class Item_func_set_collation :public Item_str_func
+{
+ CHARSET_INFO *set_collation;
+public:
+ Item_func_set_collation(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
+ { set_collation=cs; }
+ bool fix_fields(THD *thd,struct st_table_list *tables, Item **ref);
+ String *val_str(String *);
+ void fix_length_and_dec()
+ { max_length = args[0]->max_length; }
+ bool eq(const Item *item, bool binary_cmp) const;
+ const char *func_name() const { return "set_collation"; }
+};
+
+class Item_func_conv_charset3 :public Item_str_func
+{
+public:
+ Item_func_conv_charset3(Item *arg1,Item *arg2,Item *arg3)
+ :Item_str_func(arg1,arg2,arg3) {}
+ String *val_str(String *);
+ void fix_length_and_dec();
+ const char *func_name() const { return "conv_charset3"; }
+};
+
+class Item_func_charset :public Item_str_func
+{
+public:
+ Item_func_charset(Item *a) :Item_str_func(a) {}
+ String *val_str(String *);
+ const char *func_name() const { return "charset"; }
+ void fix_length_and_dec()
+ {
+ max_length=40; // should be enough
+ set_charset(thd_charset());
+ };
+};
+
+
+/*******************************************************
+Spatial functions
+********************************************************/
+
+class Item_func_geometry_from_text :public Item_str_func
+{
+public:
+ Item_func_geometry_from_text(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "geometryfromtext"; }
+ String *val_str(String *);
+ void fix_length_and_dec();
+};
+
+class Item_func_as_text :public Item_str_func
+{
+public:
+ Item_func_as_text(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "astext"; }
+ String *val_str(String *);
+ void fix_length_and_dec();
+};
+
+class Item_func_geometry_type :public Item_str_func
+{
+public:
+ Item_func_geometry_type(Item *a) :Item_str_func(a) {}
+ String *val_str(String *);
+ const char *func_name() const { return "geometrytype"; }
+ void fix_length_and_dec()
+ {
+ max_length=20; // "GeometryCollection" is the most long
+ };
+};
+
+class Item_func_centroid :public Item_str_func
+{
+public:
+ Item_func_centroid(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "centroid"; }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_envelope :public Item_str_func
+{
+public:
+ Item_func_envelope(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "envelope"; }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_point :public Item_str_func
+{
+public:
+ Item_func_point(Item *a,Item *b) :Item_str_func(a,b) {}
+ const char *func_name() const { return "point"; }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_spatial_decomp :public Item_str_func
+{
+ enum Functype decomp_func;
+public:
+ Item_func_spatial_decomp(Item *a, Item_func::Functype ft) :
+ Item_str_func(a) { decomp_func = ft; }
+ const char *func_name() const
+ {
+ switch (decomp_func)
+ {
+ case SP_STARTPOINT:
+ return "startpoint";
+ case SP_ENDPOINT:
+ return "endpoint";
+ case SP_EXTERIORRING:
+ return "exteriorring";
+ default:
+ return "spatial_decomp_unknown";
+ }
+ }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_spatial_decomp_n :public Item_str_func
+{
+ enum Functype decomp_func_n;
+public:
+ Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft) :
+ Item_str_func(a, b) { decomp_func_n = ft; }
+ const char *func_name() const
+ {
+ switch (decomp_func_n)
+ {
+ case SP_POINTN:
+ return "pointn";
+ case SP_GEOMETRYN:
+ return "geometryn";
+ case SP_INTERIORRINGN:
+ return "interiorringn";
+ default:
+ return "spatial_decomp_n_unknown";
+ }
+ }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+
+class Item_func_spatial_collection :public Item_str_func
+{
+ String tmp_value;
+ enum Geometry::wkbType coll_type;
+ enum Geometry::wkbType item_type;
+public:
+ Item_func_spatial_collection(
+ List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it) :
+ Item_str_func(list)
+ {
+ coll_type=ct;
+ item_type=it;
+ }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "multipoint"; }
+};
+
+
+/*
+class Item_func_multipoint :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_multipoint(List<Item> &list) :Item_str_func(list) {}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "multipoint"; }
+};
+
+class Item_func_linestring :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_linestring(List<Item> &list) :Item_str_func(list) {}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "linestring"; }
+};
+
+class Item_func_multilinestring :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_multilinestring(List<Item> &list) :Item_str_func(list) {}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "multilinestring"; }
+};
+
+class Item_func_polygon :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_polygon(List<Item> &list) :Item_str_func(list) {}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "polygon"; }
+};
+
+class Item_func_multipolygon :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_multipolygon(List<Item> &list) :Item_str_func(list) {}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "multipolygon"; }
+};
+
+class Item_func_geometrycollection :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_geometrycollection(List<Item> &list) :Item_str_func(list) {}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "geometrycollection"; }
+};
+
+*/
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
new file mode 100644
index 00000000000..fb51b5561e9
--- /dev/null
+++ b/sql/item_subselect.cc
@@ -0,0 +1,860 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/*
+ subselect Item
+
+SUBSELECT TODO:
+ - add function from mysql_select that use JOIN* as parameter to JOIN methods
+ (sql_select.h/sql_select.cc)
+ - remove double 'having' & 'having_list' from JOIN
+ (sql_select.h/sql_select.cc)
+
+*/
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include "sql_select.h"
+
+inline Item * and_items(Item* cond, Item *item)
+{
+ return (cond? (new Item_cond_and(cond, item)) : item);
+}
+
+Item_subselect::Item_subselect():
+ Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
+ have_to_be_excluded(0)
+{
+ reset();
+ /*
+ item value is NULL if select_subselect not changed this value
+ (i.e. some rows will be found returned)
+ */
+ null_value= 1;
+}
+
+void Item_subselect::init(THD *thd, st_select_lex *select_lex,
+ select_subselect *result)
+{
+
+ DBUG_ENTER("Item_subselect::init");
+ DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
+
+ select_transformer(thd, select_lex->master_unit());
+ if (select_lex->next_select())
+ engine= new subselect_union_engine(thd, select_lex->master_unit(), result,
+ this);
+ else
+ engine= new subselect_single_select_engine(thd, select_lex, result,
+ this);
+ DBUG_VOID_RETURN;
+}
+
+Item_subselect::~Item_subselect()
+{
+ if (engine_owner)
+ delete engine;
+}
+
+void Item_subselect::select_transformer(THD *thd, st_select_lex_unit *unit)
+{
+ DBUG_ENTER("Item_subselect::select_transformer");
+ DBUG_VOID_RETURN;
+}
+
+
+bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+{
+ if (substitution)
+ {
+ (*ref)= substitution;
+ substitution->name= name;
+ if (have_to_be_excluded)
+ engine->exclude();
+ substitution= 0;
+ return (*ref)->fix_fields(thd, tables, ref);
+ }
+
+ char const *save_where= thd->where;
+ int res= engine->prepare();
+ if (!res)
+ {
+ // Is it one field subselect?
+ if (engine->cols() > max_columns)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ return 1;
+ }
+ fix_length_and_dec();
+ }
+ fixed= 1;
+ thd->where= save_where;
+ return res;
+}
+
+Item::Type Item_subselect::type() const
+{
+ return SUBSELECT_ITEM;
+}
+
+void Item_subselect::fix_length_and_dec()
+{
+ engine->fix_length_and_dec(0);
+}
+
+inline table_map Item_subselect::used_tables() const
+{
+ return (table_map) (engine->dependent() ? 1L :
+ (engine->uncacheable() ? RAND_TABLE_BIT : 0L));
+}
+
+Item_singlerow_subselect::Item_singlerow_subselect(THD *thd,
+ st_select_lex *select_lex):
+ Item_subselect(), value(0)
+{
+ DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect");
+ init(thd, select_lex, new select_singlerow_subselect(this));
+ max_columns= 1;
+ maybe_null= 1;
+ max_columns= UINT_MAX;
+ DBUG_VOID_RETURN;
+}
+
+void Item_singlerow_subselect::reset()
+{
+ null_value= 1;
+ if (value)
+ value->null_value= 1;
+}
+
+void Item_singlerow_subselect::select_transformer(THD *thd,
+ st_select_lex_unit *unit)
+{
+ SELECT_LEX *select_lex= unit->first_select();
+
+ if (!select_lex->next_select() && !select_lex->table_list.elements &&
+ select_lex->item_list.elements == 1 &&
+ /*
+ We cant change name of Item_field or Item_ref, because it will
+ prevent it's correct resolving, but we should save name of
+ removed item => we do not make optimization if top item of
+ list is field or reference.
+ TODO: solve above problem
+ */
+ !(select_lex->item_list.head()->type() == FIELD_ITEM ||
+ select_lex->item_list.head()->type() == REF_ITEM)
+ )
+ {
+
+ have_to_be_excluded= 1;
+ if (thd->lex.describe)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_SELECT_REDUCED, warn_buff);
+ }
+ substitution= select_lex->item_list.head();
+ substitution->set_outer_resolving();
+
+ if (select_lex->where || select_lex->having)
+ {
+ Item *cond;
+ if (!select_lex->having)
+ cond= select_lex->where;
+ else if (!select_lex->where)
+ cond= select_lex->having;
+ else
+ if (!(cond= new Item_cond_and(select_lex->having, select_lex->where)))
+ return;
+ if (!(substitution= new Item_func_if(cond, substitution,
+ new Item_null())))
+ return;
+ }
+ }
+}
+
+void Item_singlerow_subselect::store(uint i, Item *item)
+{
+ row[i]->store(item);
+}
+
+enum Item_result Item_singlerow_subselect::result_type() const
+{
+ return engine->type();
+}
+
+void Item_singlerow_subselect::fix_length_and_dec()
+{
+ if ((max_columns= engine->cols()) == 1)
+ {
+ engine->fix_length_and_dec(row= &value);
+ if (!(value= Item_cache::get_cache(engine->type())))
+ return;
+ }
+ else
+ {
+ THD *thd= current_thd;
+ if (!(row= (Item_cache**)thd->alloc(sizeof(Item_cache*)*max_columns)))
+ return;
+ engine->fix_length_and_dec(row);
+ value= *row;
+ }
+ maybe_null= engine->may_be_null();
+}
+
+uint Item_singlerow_subselect::cols()
+{
+ return engine->cols();
+}
+
+bool Item_singlerow_subselect::check_cols(uint c)
+{
+ if (c != engine->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), c);
+ return 1;
+ }
+ return 0;
+}
+
+bool Item_singlerow_subselect::null_inside()
+{
+ for (uint i= 0; i < max_columns ; i++)
+ {
+ if (row[i]->null_value)
+ return 1;
+ }
+ return 0;
+}
+
+void Item_singlerow_subselect::bring_value()
+{
+ engine->exec();
+}
+
+double Item_singlerow_subselect::val ()
+{
+ if (!engine->exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val();
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+longlong Item_singlerow_subselect::val_int ()
+{
+ if (!engine->exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_int();
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+String *Item_singlerow_subselect::val_str (String *str)
+{
+ if (!engine->exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_str(str);
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+Item_exists_subselect::Item_exists_subselect(THD *thd,
+ st_select_lex *select_lex):
+ Item_subselect()
+{
+ DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
+ init(thd, select_lex, new select_exists_subselect(this));
+ max_columns= UINT_MAX;
+ null_value= 0; //can't be NULL
+ maybe_null= 0; //can't be NULL
+ value= 0;
+ // We need only 1 row to determinate existence
+ select_lex->master_unit()->global_parameters->select_limit= 1;
+ DBUG_VOID_RETURN;
+}
+
+Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
+ st_select_lex *select_lex):
+ Item_exists_subselect()
+{
+ DBUG_ENTER("Item_in_subselect::Item_in_subselect");
+ left_expr= left_exp;
+ init(thd, select_lex, new select_exists_subselect(this));
+ max_columns= UINT_MAX;
+ maybe_null= 1;
+ reset();
+ // We need only 1 row to determinate existence
+ select_lex->master_unit()->global_parameters->select_limit= 1;
+ DBUG_VOID_RETURN;
+}
+
+Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
+ compare_func_creator f,
+ st_select_lex *select_lex):
+ Item_in_subselect()
+{
+ DBUG_ENTER("Item_in_subselect::Item_in_subselect");
+ left_expr= left_exp;
+ func= f;
+ init(thd, select_lex, new select_exists_subselect(this));
+ max_columns= 1;
+ reset();
+ // We need only 1 row to determinate existence
+ select_lex->master_unit()->global_parameters->select_limit= 1;
+ DBUG_VOID_RETURN;
+}
+
+
+void Item_exists_subselect::fix_length_and_dec()
+{
+ decimals= 0;
+ max_length= 1;
+ max_columns= engine->cols();
+}
+
+double Item_exists_subselect::val ()
+{
+ if (engine->exec())
+ {
+ reset();
+ return 0;
+ }
+ return (double) value;
+}
+
+longlong Item_exists_subselect::val_int ()
+{
+ if (engine->exec())
+ {
+ reset();
+ return 0;
+ }
+ return value;
+}
+
+String *Item_exists_subselect::val_str(String *str)
+{
+ if (engine->exec())
+ {
+ reset();
+ return 0;
+ }
+ str->set(value,thd_charset());
+ return str;
+}
+
+double Item_in_subselect::val ()
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return (double) value;
+}
+
+longlong Item_in_subselect::val_int ()
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return value;
+}
+
+String *Item_in_subselect::val_str(String *str)
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ {
+ null_value= 1;
+ return 0;
+ }
+ str->set(value,thd_charset());
+ return str;
+}
+
+Item_in_subselect::Item_in_subselect(Item_in_subselect *item):
+ Item_exists_subselect(item)
+{
+ left_expr= item->left_expr;
+}
+
+Item_allany_subselect::Item_allany_subselect(Item_allany_subselect *item):
+ Item_in_subselect(item)
+{
+ func= item->func;
+}
+
+void Item_in_subselect::single_value_transformer(THD *thd,
+ st_select_lex_unit *unit,
+ Item *left_expr,
+ compare_func_creator func)
+{
+ DBUG_ENTER("Item_in_subselect::single_value_transformer");
+
+ if (unit->global_parameters->select_limit != HA_POS_ERROR)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "LIMIT & IN/ALL/ANY/SOME subquery");
+ DBUG_VOID_RETURN;
+ }
+ // no sense in ORDER BY without LIMIT
+ unit->global_parameters->order_list.empty();
+
+ Item_in_optimizer *optimizer;
+ substitution= optimizer= new Item_in_optimizer(left_expr, this);
+ if (!optimizer)
+ DBUG_VOID_RETURN;
+
+ /*
+ As far as Item_ref_in_optimizer do not substitude itself on fix_fields
+ we can use same item for all selects.
+ */
+ Item *expr= new Item_ref((Item**)optimizer->get_cache(),
+ (char *)"<no matter>",
+ (char*)"<left expr>");
+ unit->dependent= 1;
+ for (SELECT_LEX * sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->select_limit != HA_POS_ERROR)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "LIMIT & IN/ALL/ANY/SOME subquery");
+ DBUG_VOID_RETURN;
+ }
+
+ sl->dependent= 1;
+ Item *item;
+ if (sl->item_list.elements > 1)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ DBUG_VOID_RETURN;
+ }
+ else
+ item= (Item*) sl->item_list.pop();
+
+ sl->order_list.empty(); // no sense in ORDER BY without LIMIT
+
+ if (sl->having || sl->with_sum_func || sl->group_list.elements)
+ {
+ sl->item_list.push_back(item);
+ setup_ref_array(thd, &sl->ref_pointer_array,
+ 1 + sl->with_sum_func +
+ sl->order_list.elements + sl->group_list.elements);
+ item= (*func)(expr, new Item_ref_null_helper(this,
+ sl->ref_pointer_array,
+ (char *)"<ref>",
+ this->full_name()));
+ sl->having= and_items(sl->having, item);
+ }
+ else
+ {
+ sl->item_list.empty();
+ sl->item_list.push_back(new Item_int("Not_used", (longlong) 1, 21));
+ if (sl->table_list.elements)
+ {
+ item= (*func)(expr, new Item_asterisk_remover(this, item,
+ (char *)"<no matter>",
+ (char*)"<result>"));
+ sl->where= and_items(sl->where, item);
+ }
+ else
+ {
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field_name[0] == '*')
+ {
+ my_error(ER_NO_TABLES_USED, MYF(0));
+ DBUG_VOID_RETURN;
+ }
+ if (unit->first_select()->next_select())
+ {
+ /*
+ It is in union => we should perform it.
+ Item_asterisk_remover used only as wrapper to receine NULL value
+ */
+ sl->having= (*func)(expr,
+ new Item_asterisk_remover(this, item,
+ (char *)"<no matter>",
+ (char*)"<result>"));
+ }
+ else
+ {
+ // it is single select without tables => possible optimization
+ item= (*func)(left_expr, item);
+ substitution= item;
+ have_to_be_excluded= 1;
+ if (thd->lex.describe)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff, ER(ER_SELECT_REDUCED), sl->select_number);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_SELECT_REDUCED, warn_buff);
+ }
+ }
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+void Item_in_subselect::row_value_transformer(THD *thd,
+ st_select_lex_unit *unit,
+ Item *left_expr)
+{
+ DBUG_ENTER("Item_in_subselect::row_value_transformer");
+ if (unit->global_parameters->select_limit !=
+ HA_POS_ERROR)
+ {
+ /*
+ Because we do the following (not exactly, following is just explenation)
+ transformation
+ SELECT * from t1 WHERE t1.a IN (SELECT t2.a FROM t2)
+ ->
+ SELECT * from t1 WHERE EXISTS(SELECT 1 FROM t2 t1.a = t2.a LIMIT 1)
+
+ it's impossible to support limit in the sub select.
+ */
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "LIMIT & IN/ALL/ANY/SOME subquery");
+ DBUG_VOID_RETURN;
+ }
+ // no sense in ORDER BY without LIMIT
+ unit->global_parameters->order_list.empty();
+
+ Item_in_optimizer *optimizer;
+ substitution= optimizer= new Item_in_optimizer(left_expr, this);
+ if (!optimizer)
+ DBUG_VOID_RETURN;
+
+ unit->dependent= 1;
+ uint n= left_expr->cols();
+ if (optimizer->preallocate_row() || (*optimizer->get_cache())->allocate(n))
+ DBUG_VOID_RETURN;
+ for (SELECT_LEX * sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->select_limit != HA_POS_ERROR)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "LIMIT & IN/ALL/ANY/SOME subquery");
+ DBUG_VOID_RETURN;
+ }
+ sl->order_list.empty(); // no sense in ORDER BY without LIMIT
+
+ sl->dependent= 1;
+
+ Item *item= 0;
+ List_iterator_fast<Item> li(sl->item_list);
+ for (uint i= 0; i < n; i++)
+ {
+ Item *func=
+ new Item_ref_on_list_position(this, sl, i,
+ (char *) "<no matter>",
+ (char *) "<list ref>");
+ func=
+ Item_bool_func2::eq_creator(new Item_ref((*optimizer->get_cache())->
+ addr(i),
+ (char *)"<no matter>",
+ (char *)"<left expr>"),
+ func);
+ item= and_items(item, func);
+ }
+
+ if (sl->having || sl->with_sum_func || sl->group_list.first ||
+ !sl->table_list.elements)
+ sl->having= and_items(sl->having, item);
+ else
+ sl->where= and_items(sl->where, item);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void Item_in_subselect::select_transformer(THD *thd, st_select_lex_unit *unit)
+{
+ if (left_expr->cols() == 1)
+ single_value_transformer(thd, unit, left_expr,
+ &Item_bool_func2::eq_creator);
+ else
+ row_value_transformer(thd, unit, left_expr);
+}
+
+void Item_allany_subselect::select_transformer(THD *thd,
+ st_select_lex_unit *unit)
+{
+ single_value_transformer(thd, unit, left_expr, func);
+}
+
+subselect_single_select_engine::subselect_single_select_engine(THD *thd,
+ st_select_lex *select,
+ select_subselect *result,
+ Item_subselect *item):
+ subselect_engine(thd, item, result),
+ prepared(0), optimized(0), executed(0)
+{
+ select_lex= select;
+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
+ unit->offset_limit_cnt= unit->global_parameters->offset_limit;
+ unit->select_limit_cnt= unit->global_parameters->select_limit+
+ unit->global_parameters ->offset_limit;
+ if (unit->select_limit_cnt < unit->global_parameters->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR; // no limit
+ if (unit->select_limit_cnt == HA_POS_ERROR)
+ select_lex->options&= ~OPTION_FOUND_ROWS;
+ join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
+ if (!join || !result)
+ //out of memory
+ thd->fatal_error();
+ unit->item= item;
+ this->select_lex= select_lex;
+}
+
+subselect_union_engine::subselect_union_engine(THD *thd,
+ st_select_lex_unit *u,
+ select_subselect *result,
+ Item_subselect *item):
+ subselect_engine(thd, item, result)
+{
+ unit= u;
+ if (!result)
+ //out of memory
+ thd->fatal_error();
+ unit->item= item;
+}
+
+int subselect_single_select_engine::prepare()
+{
+ if (prepared)
+ return 0;
+ prepared= 1;
+ SELECT_LEX_NODE *save_select= thd->lex.current_select;
+ thd->lex.current_select= select_lex;
+ if (join->prepare(&select_lex->ref_pointer_array,
+ (TABLE_LIST*) select_lex->table_list.first,
+ select_lex->with_wild,
+ select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) 0, select_lex,
+ select_lex->master_unit(), 0, 0))
+ return 1;
+ thd->lex.current_select= save_select;
+ return 0;
+}
+
+int subselect_union_engine::prepare()
+{
+ return unit->prepare(thd, result, 0);
+}
+
+static Item_result set_row(SELECT_LEX *select_lex, Item * item,
+ Item_cache **row, bool *maybe_null)
+{
+ Item_result res_type= STRING_RESULT;
+ Item *sel_item;
+ List_iterator_fast<Item> li(select_lex->item_list);
+ for (uint i= 0; (sel_item= li++); i++)
+ {
+ item->max_length= sel_item->max_length;
+ res_type= sel_item->result_type();
+ item->decimals= sel_item->decimals;
+ *maybe_null= sel_item->maybe_null;
+ if (row)
+ {
+ if (!(row[i]= Item_cache::get_cache(res_type)))
+ return STRING_RESULT; // we should return something
+ row[i]->set_len_n_dec(sel_item->max_length, sel_item->decimals);
+ }
+ }
+ if (select_lex->item_list.elements > 1)
+ res_type= ROW_RESULT;
+ return res_type;
+}
+
+void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
+{
+ DBUG_ASSERT(row || select_lex->item_list.elements==1);
+ res_type= set_row(select_lex, item, row, &maybe_null);
+ if (cols() != 1)
+ maybe_null= 0;
+}
+
+void subselect_union_engine::fix_length_and_dec(Item_cache **row)
+{
+ DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
+
+ if (unit->first_select()->item_list.elements == 1)
+ {
+ uint32 mlen= 0, len;
+ Item *sel_item= 0;
+ for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ List_iterator_fast<Item> li(sl->item_list);
+ Item *s_item= li++;
+ if ((len= s_item->max_length) > mlen)
+ mlen= len;
+ if (!sel_item)
+ sel_item= s_item;
+ maybe_null= s_item->maybe_null;
+ }
+ item->max_length= mlen;
+ res_type= sel_item->result_type();
+ item->decimals= sel_item->decimals;
+ if (row)
+ {
+ if (!(row[0]= Item_cache::get_cache(res_type)))
+ return;
+ row[0]->set_len_n_dec(mlen, sel_item->decimals);
+ }
+ }
+ else
+ {
+ SELECT_LEX *sl= unit->first_select();
+ bool fake= 0;
+ res_type= set_row(sl, item, row, &fake);
+ for (sl= sl->next_select(); sl; sl->next_select())
+ {
+ List_iterator_fast<Item> li(sl->item_list);
+ Item *sel_item;
+ for (uint i= 0; (sel_item= li++); i++)
+ {
+ if (sel_item->max_length > row[i]->max_length)
+ row[i]->max_length= sel_item->max_length;
+ }
+ }
+ }
+}
+
+int subselect_single_select_engine::exec()
+{
+ DBUG_ENTER("subselect_single_select_engine::exec");
+ char const *save_where= join->thd->where;
+ if (!optimized)
+ {
+ optimized=1;
+ if (join->optimize())
+ {
+ join->thd->where= save_where;
+ executed= 1;
+ DBUG_RETURN(join->error?join->error:1);
+ }
+ }
+ if ((select_lex->dependent || select_lex->uncacheable) && executed)
+ {
+ if (join->reinit())
+ {
+ join->thd->where= save_where;
+ DBUG_RETURN(1);
+ }
+ item->reset();
+ item->assigned((executed= 0));
+ }
+ if (!executed)
+ {
+ SELECT_LEX_NODE *save_select= join->thd->lex.current_select;
+ join->thd->lex.current_select= select_lex;
+ join->exec();
+ join->thd->lex.current_select= save_select;
+ executed= 1;
+ join->thd->where= save_where;
+ DBUG_RETURN(join->error||thd->is_fatal_error);
+ }
+ join->thd->where= save_where;
+ DBUG_RETURN(0);
+}
+
+int subselect_union_engine::exec()
+{
+ char const *save_where= unit->thd->where;
+ int res= unit->exec();
+ unit->thd->where= save_where;
+ return res;
+}
+
+uint subselect_single_select_engine::cols()
+{
+ return select_lex->item_list.elements;
+}
+
+uint subselect_union_engine::cols()
+{
+ return unit->first_select()->item_list.elements;
+}
+
+bool subselect_single_select_engine::dependent()
+{
+ return select_lex->dependent;
+}
+
+bool subselect_union_engine::dependent()
+{
+ return unit->dependent;
+}
+
+bool subselect_single_select_engine::uncacheable()
+{
+ return select_lex->uncacheable;
+}
+
+bool subselect_union_engine::uncacheable()
+{
+ return unit->uncacheable;
+}
+
+void subselect_single_select_engine::exclude()
+{
+ select_lex->master_unit()->exclude_level();
+}
+
+void subselect_union_engine::exclude()
+{
+ unit->exclude_level();
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
new file mode 100644
index 00000000000..351c4af7f33
--- /dev/null
+++ b/sql/item_subselect.h
@@ -0,0 +1,267 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/* subselect Item */
+
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
+class st_select_lex;
+class st_select_lex_unit;
+class JOIN;
+class select_subselect;
+class subselect_engine;
+class Item_bool_func2;
+
+typedef Item_bool_func2* (*compare_func_creator)(Item*, Item*);
+
+/* base class for subselects */
+
+class Item_subselect :public Item_result_field
+{
+ my_bool engine_owner; /* Is this item owner of engine */
+ my_bool value_assigned; /* value already assigned to subselect */
+protected:
+ /* substitution instead of subselect in case of optimization */
+ Item *substitution;
+ /* engine that perform execution of subselect (single select or union) */
+ subselect_engine *engine;
+ /* allowed number of columns (1 for single value subqueries) */
+ uint max_columns;
+ /* work with 'substitution' */
+ bool have_to_be_excluded;
+
+public:
+ Item_subselect();
+ Item_subselect(Item_subselect *item)
+ {
+ substitution= item->substitution;
+ null_value= item->null_value;
+ decimals= item->decimals;
+ max_columns= item->max_columns;
+ engine= item->engine;
+ engine_owner= 0;
+ name= item->name;
+ }
+
+ /*
+ We need this method, because some compilers do not allow 'this'
+ pointer in constructor initialization list, but we need pass pointer
+ to subselect Item class to select_subselect classes constructor.
+ */
+ virtual void init (THD *thd, st_select_lex *select_lex,
+ select_subselect *result);
+
+ ~Item_subselect();
+ virtual void reset()
+ {
+ null_value= 1;
+ }
+ virtual void select_transformer(THD *thd, st_select_lex_unit *unit);
+ bool assigned() { return value_assigned; }
+ void assigned(bool a) { value_assigned= a; }
+ enum Type type() const;
+ bool is_null()
+ {
+ val_int();
+ return null_value;
+ }
+ bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
+ virtual void fix_length_and_dec();
+ table_map used_tables() const;
+
+ friend class select_subselect;
+ friend class Item_in_optimizer;
+};
+
+/* single value subselect */
+
+class Item_cache;
+class Item_singlerow_subselect :public Item_subselect
+{
+protected:
+ Item_cache *value, **row;
+public:
+ Item_singlerow_subselect(THD *thd, st_select_lex *select_lex);
+ Item_singlerow_subselect(Item_singlerow_subselect *item):
+ Item_subselect(item)
+ {
+ value= item->value;
+ max_length= item->max_length;
+ decimals= item->decimals;
+ }
+ void reset();
+ void select_transformer(THD *thd, st_select_lex_unit *unit);
+ void store(uint i, Item* item);
+ double val();
+ longlong val_int ();
+ String *val_str (String *);
+ Item *new_item() { return new Item_singlerow_subselect(this); }
+ enum Item_result result_type() const;
+ void fix_length_and_dec();
+
+ uint cols();
+ Item* el(uint i) { return (Item*)row[i]; }
+ Item** addr(uint i) { return (Item**)row + i; }
+ bool check_cols(uint c);
+ bool null_inside();
+ void bring_value();
+
+ friend class select_singlerow_subselect;
+};
+
+/* exists subselect */
+
+class Item_exists_subselect :public Item_subselect
+{
+protected:
+ longlong value; /* value of this item (boolean: exists/not-exists) */
+
+public:
+ Item_exists_subselect(THD *thd, st_select_lex *select_lex);
+ Item_exists_subselect(Item_exists_subselect *item):
+ Item_subselect(item)
+ {
+ value= item->value;
+ }
+ Item_exists_subselect(): Item_subselect() {}
+
+ void reset()
+ {
+ value= 0;
+ }
+
+ Item *new_item() { return new Item_exists_subselect(this); }
+ enum Item_result result_type() const { return INT_RESULT;}
+ longlong val_int();
+ double val();
+ String *val_str(String*);
+ void fix_length_and_dec();
+
+ friend class select_exists_subselect;
+};
+
+/* IN subselect */
+
+class Item_in_subselect :public Item_exists_subselect
+{
+protected:
+ Item * left_expr;
+ bool was_null;
+public:
+ Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
+ Item_in_subselect(Item_in_subselect *item);
+ Item_in_subselect(): Item_exists_subselect() {}
+ void reset()
+ {
+ value= 0;
+ null_value= 0;
+ was_null= 0;
+ }
+ virtual void select_transformer(THD *thd, st_select_lex_unit *unit);
+ void single_value_transformer(THD *thd, st_select_lex_unit *unit,
+ Item *left_expr, compare_func_creator func);
+ void row_value_transformer(THD *thd, st_select_lex_unit *unit,
+ Item *left_expr);
+ longlong val_int();
+ double val();
+ String *val_str(String*);
+
+ friend class Item_asterisk_remover;
+ friend class Item_ref_null_helper;
+};
+
+/* ALL/ANY/SOME subselect */
+class Item_allany_subselect :public Item_in_subselect
+{
+protected:
+ compare_func_creator func;
+
+public:
+ Item_allany_subselect(THD *thd, Item * left_expr, compare_func_creator f,
+ st_select_lex *select_lex);
+ Item_allany_subselect(Item_allany_subselect *item);
+ virtual void select_transformer(THD *thd, st_select_lex_unit *unit);
+};
+
+class subselect_engine: public Sql_alloc
+{
+protected:
+ select_subselect *result; /* results storage class */
+ THD *thd; /* pointer to current THD */
+ Item_subselect *item; /* item, that use this engine */
+ enum Item_result res_type; /* type of results */
+ bool maybe_null; /* may be null (first item in select) */
+public:
+
+ subselect_engine(THD *thd, Item_subselect *si, select_subselect *res)
+ {
+ result= res;
+ item= si;
+ this->thd= thd;
+ res_type= STRING_RESULT;
+ maybe_null= 0;
+ }
+ virtual ~subselect_engine() {}; // to satisfy compiler
+
+ virtual int prepare()= 0;
+ virtual void fix_length_and_dec(Item_cache** row)= 0;
+ virtual int exec()= 0;
+ virtual uint cols()= 0; /* return number of columnss in select */
+ virtual bool dependent()= 0; /* depended from outer select */
+ virtual bool uncacheable()= 0; /* query is uncacheable */
+ enum Item_result type() { return res_type; }
+ virtual void exclude()= 0;
+ bool may_be_null() { return maybe_null; };
+};
+
+class subselect_single_select_engine: public subselect_engine
+{
+ my_bool prepared; /* simple subselect is prepared */
+ my_bool optimized; /* simple subselect is optimized */
+ my_bool executed; /* simple subselect is executed */
+ st_select_lex *select_lex; /* corresponding select_lex */
+ JOIN * join; /* corresponding JOIN structure */
+public:
+ subselect_single_select_engine(THD *thd, st_select_lex *select,
+ select_subselect *result,
+ Item_subselect *item);
+ int prepare();
+ void fix_length_and_dec(Item_cache** row);
+ int exec();
+ uint cols();
+ bool dependent();
+ bool uncacheable();
+ void exclude();
+};
+
+class subselect_union_engine: public subselect_engine
+{
+ st_select_lex_unit *unit; /* corresponding unit structure */
+public:
+ subselect_union_engine(THD *thd,
+ st_select_lex_unit *u,
+ select_subselect *result,
+ Item_subselect *item);
+ int prepare();
+ void fix_length_and_dec(Item_cache** row);
+ int exec();
+ uint cols();
+ bool dependent();
+ bool uncacheable();
+ void exclude();
+};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index b6bbc12efd6..c2db50345d1 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -23,7 +23,6 @@
#include "mysql_priv.h"
-
Item_sum::Item_sum(List<Item> &list)
{
arg_count=list.elements;
@@ -38,32 +37,45 @@ Item_sum::Item_sum(List<Item> &list)
args[i++]= item;
}
}
- with_sum_func=1;
+ mark_as_sum_func();
list.empty(); // Fields are used
}
+// Constructor used in processing select with temporary tebles
+Item_sum::Item_sum(THD *thd, Item_sum &item):
+ Item_result_field(thd, item), quick_group(item.quick_group)
+{
+ arg_count= item.arg_count;
+ if (arg_count <= 2)
+ args=tmp_args;
+ else
+ if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
+ return;
+ for (uint i= 0; i < arg_count; i++)
+ args[i]= item.args[i];
+}
+
+void Item_sum::mark_as_sum_func()
+{
+ current_thd->lex.current_select->with_sum_func++;
+ with_sum_func= 1;
+}
+
void Item_sum::make_field(Send_field *tmp_field)
{
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
- ((Item_field*) args[0])->field->make_field(tmp_field);
- else
{
- tmp_field->flags=0;
- if (!maybe_null)
- tmp_field->flags|= NOT_NULL_FLAG;
- if (unsigned_flag)
- tmp_field->flags |= UNSIGNED_FLAG;
- tmp_field->length=max_length;
- tmp_field->decimals=decimals;
- tmp_field->type=(result_type() == INT_RESULT ? FIELD_TYPE_LONG :
- result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
- FIELD_TYPE_VAR_STRING);
+ ((Item_field*) args[0])->field->make_field(tmp_field);
+ tmp_field->db_name=(char*)"";
+ tmp_field->org_table_name=tmp_field->table_name=(char*)"";
+ tmp_field->org_col_name=tmp_field->col_name=name;
}
- tmp_field->table_name=(char*)"";
- tmp_field->col_name=name;
+ else
+ init_make_field(tmp_field, field_type());
}
+
void Item_sum::print(String *str)
{
str->append(func_name());
@@ -85,6 +97,26 @@ void Item_sum::fix_num_length_and_dec()
max_length=float_length(decimals);
}
+Item *Item_sum::get_tmp_table_item(THD *thd)
+{
+ Item_sum* sum_item= (Item_sum *) copy_or_same(thd);
+ if (sum_item && sum_item->result_field) // If not a const sum func
+ {
+ Field *result_field= sum_item->result_field;
+ for (uint i=0 ; i < sum_item->arg_count ; i++)
+ {
+ Item *arg= sum_item->args[i];
+ if (!arg->const_item())
+ {
+ if (arg->type() == Item::FIELD_ITEM)
+ ((Item_field*) arg)->field= result_field++;
+ else
+ sum_item->args[i]= new Item_field(result_field++);
+ }
+ }
+ }
+ return sum_item;
+}
String *
Item_sum_num::val_str(String *str)
@@ -92,7 +124,7 @@ Item_sum_num::val_str(String *str)
double nr=val();
if (null_value)
return 0;
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
@@ -103,15 +135,13 @@ Item_sum_int::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- char buff[21];
- uint length= (uint) (longlong10_to_str(nr,buff,-10)-buff);
- str->copy(buff,length);
+ str->set(nr,thd_charset());
return str;
}
bool
-Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
+Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!thd->allow_sum_func)
{
@@ -123,7 +153,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
maybe_null=0;
for (uint i=0 ; i < arg_count ; i++)
{
- if (args[i]->fix_fields(thd,tables))
+ if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
return 1;
if (decimals < args[i]->decimals)
decimals=args[i]->decimals;
@@ -134,12 +164,13 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
null_value=1;
fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions
+ fixed= 1;
return 0;
}
bool
-Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
+Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
Item *item=args[0];
if (!thd->allow_sum_func)
@@ -148,7 +179,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1;
}
thd->allow_sum_func=0; // No included group funcs
- if (item->fix_fields(thd,tables))
+ if (item->fix_fields(thd, tables, args) || item->check_cols(1))
return 1;
hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT)
@@ -156,15 +187,22 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
else if (hybrid_type == REAL_RESULT)
max_length=float_length(decimals);
else
+ {
+ str_cmp_function= binary() ? stringcmp : sortcmp;
max_length=item->max_length;
+ }
decimals=item->decimals;
maybe_null=item->maybe_null;
- binary=item->binary;
unsigned_flag=item->unsigned_flag;
result_field=0;
null_value=1;
fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions
+ if (item->type() == Item::FIELD_ITEM)
+ hybrid_field_type= ((Item_field*) item)->field->type();
+ else
+ hybrid_field_type= Item::field_type();
+ fixed= 1;
return 0;
}
@@ -249,12 +287,24 @@ double Item_sum_avg::val()
** Standard deviation
*/
-void Item_sum_std::reset()
+double Item_sum_std::val()
+{
+ double tmp= Item_sum_variance::val();
+ return tmp <= 0.0 ? 0.0 : sqrt(tmp);
+}
+
+/*
+** variance
+*/
+
+void Item_sum_variance::reset()
{
- sum=sum_sqr=0.0; count=0; (void) Item_sum_std::add();
+ sum=sum_sqr=0.0;
+ count=0;
+ (void) Item_sum_variance::add();
}
-bool Item_sum_std::add()
+bool Item_sum_variance::add()
{
double nr=args[0]->val();
if (!args[0]->null_value)
@@ -266,7 +316,7 @@ bool Item_sum_std::add()
return 0;
}
-double Item_sum_std::val()
+double Item_sum_variance::val()
{
if (!count)
{
@@ -277,11 +327,10 @@ double Item_sum_std::val()
/* Avoid problems when the precision isn't good enough */
double tmp=ulonglong2double(count);
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
- return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
+ return tmp2 <= 0.0 ? 0.0 : tmp2;
}
-
-void Item_sum_std::reset_field()
+void Item_sum_variance::reset_field()
{
double nr=args[0]->val();
char *res=result_field->ptr;
@@ -298,7 +347,7 @@ void Item_sum_std::reset_field()
}
}
-void Item_sum_std::update_field(int offset)
+void Item_sum_variance::update_field(int offset)
{
double nr,old_nr,old_sqr;
longlong field_count;
@@ -324,18 +373,24 @@ void Item_sum_std::update_field(int offset)
double Item_sum_hybrid::val()
{
+ int err;
if (null_value)
return 0.0;
switch (hybrid_type) {
case STRING_RESULT:
String *res; res=val_str(&str_value);
- return res ? atof(res->c_ptr()) : 0.0;
+ return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
+ (char**) 0, &err) : 0.0);
case INT_RESULT:
if (unsigned_flag)
return ulonglong2double(sum_int);
return (double) sum_int;
case REAL_RESULT:
return sum;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
}
return 0; // Keep compiler happy
}
@@ -359,13 +414,17 @@ Item_sum_hybrid::val_str(String *str)
case STRING_RESULT:
return &value;
case REAL_RESULT:
- str->set(sum,decimals);
+ str->set(sum,decimals,thd_charset());
break;
case INT_RESULT:
if (unsigned_flag)
- str->set((ulonglong) sum_int);
+ str->set((ulonglong) sum_int,thd_charset());
else
- str->set((longlong) sum_int);
+ str->set((longlong) sum_int,thd_charset());
+ break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
break;
}
return str; // Keep compiler happy
@@ -378,8 +437,7 @@ bool Item_sum_min::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
- (null_value ||
- (binary ? stringcmp(&value,result) : sortcmp(&value,result)) > 0))
+ (null_value || (*str_cmp_function)(&value,result) > 0))
{
value.copy(*result);
null_value=0;
@@ -409,6 +467,10 @@ bool Item_sum_min::add()
}
}
break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
}
return 0;
}
@@ -421,8 +483,7 @@ bool Item_sum_max::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
- (null_value ||
- (binary ? stringcmp(&value,result) : sortcmp(&value,result)) < 0))
+ (null_value || (*str_cmp_function)(&value,result) < 0))
{
value.copy(*result);
null_value=0;
@@ -452,6 +513,11 @@ bool Item_sum_max::add()
}
}
break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
+
}
return 0;
}
@@ -513,7 +579,7 @@ void Item_sum_hybrid::reset_field()
if (hybrid_type == STRING_RESULT)
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff)),*res;
+ String tmp(buff,sizeof(buff),result_field->charset()),*res;
res=args[0]->val_str(&tmp);
if (args[0]->null_value)
@@ -524,7 +590,7 @@ void Item_sum_hybrid::reset_field()
else
{
result_field->set_notnull();
- result_field->store(res->ptr(),res->length());
+ result_field->store(res->ptr(),res->length(),tmp.charset());
}
}
else if (hybrid_type == INT_RESULT)
@@ -692,9 +758,8 @@ Item_sum_hybrid::min_max_update_str_field(int offset)
result_field->ptr-=offset;
if (result_field->is_null() ||
- (cmp_sign * (binary ? stringcmp(res_str,&tmp_value) :
- sortcmp(res_str,&tmp_value)) < 0))
- result_field->store(res_str->ptr(),res_str->length());
+ (cmp_sign * (*str_cmp_function)(res_str,&tmp_value)) < 0)
+ result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
else
{ // Use old value
char *res=result_field->ptr;
@@ -810,11 +875,22 @@ String *Item_avg_field::val_str(String *str)
double nr=Item_avg_field::val();
if (null_value)
return 0;
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
Item_std_field::Item_std_field(Item_sum_std *item)
+ : Item_variance_field(item)
+{
+}
+
+double Item_std_field::val()
+{
+ double tmp= Item_variance_field::val();
+ return tmp <= 0.0 ? 0.0 : sqrt(tmp);
+}
+
+Item_variance_field::Item_variance_field(Item_sum_variance *item)
{
name=item->name;
decimals=item->decimals;
@@ -823,7 +899,7 @@ Item_std_field::Item_std_field(Item_sum_std *item)
maybe_null=1;
}
-double Item_std_field::val()
+double Item_variance_field::val()
{
double sum,sum_sqr;
longlong count;
@@ -839,15 +915,15 @@ double Item_std_field::val()
null_value=0;
double tmp= (double) count;
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
- return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
+ return tmp2 <= 0.0 ? 0.0 : tmp2;
}
-String *Item_std_field::val_str(String *str)
+String *Item_variance_field::val_str(String *str)
{
double nr=val();
if (null_value)
return 0;
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
@@ -857,14 +933,17 @@ String *Item_std_field::val_str(String *str)
#include "sql_select.h"
-static int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
+int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
{
return memcmp(key1, key2, *(uint*) arg);
}
-static int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
+int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
{
- return my_sortcmp((char*) key1, (char*) key2, *(uint*) arg);
+ Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
+ CHARSET_INFO *cs=item->key_charset;
+ uint len=item->key_length;
+ return my_strnncoll(cs, (const uchar*) key1, len, (const uchar*) key2, len);
}
/*
@@ -907,7 +986,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
The first item->rec_offset bytes are taken care of with
restore_record(table,2) in setup()
*/
- memcpy(buf + item->rec_offset, key, item->tree.size_of_element);
+ memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
if ((error = item->table->file->write_row(buf)))
{
if (error != HA_ERR_FOUND_DUPP_KEY &&
@@ -920,16 +999,24 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct::~Item_sum_count_distinct()
{
- if (table)
- free_tmp_table(current_thd, table);
- delete tmp_table_param;
- if (use_tree)
- delete_tree(&tree);
+ /*
+ Free table and tree if they belong to this item (if item have not pointer
+ to original item from which was made copy => it own its objects )
+ */
+ if (!original)
+ {
+ if (table)
+ free_tmp_table(current_thd, table);
+ delete tmp_table_param;
+ if (use_tree)
+ delete_tree(tree);
+ }
}
-bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
+bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
+ Item **ref)
{
- if (Item_sum_num::fix_fields(thd,tables) ||
+ if (Item_sum_num::fix_fields(thd, tables, ref) ||
!(tmp_table_param= new TMP_TABLE_PARAM))
return 1;
return 0;
@@ -938,6 +1025,10 @@ bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
+ SELECT_LEX *select_lex= current_lex->current_select->select_lex();
+ if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
+ return 1;
+
/* Create a table with an unique key over all parameters */
for (uint i=0; i < arg_count ; i++)
{
@@ -959,9 +1050,10 @@ bool Item_sum_count_distinct::setup(THD *thd)
free_tmp_table(thd, table);
tmp_table_param->cleanup();
}
- if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
- 0, 0,
- current_lex->select->options | thd->options)))
+ if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
+ 0,
+ select_lex->options | thd->options,
+ HA_POS_ERROR)))
return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1;
@@ -987,14 +1079,22 @@ bool Item_sum_count_distinct::setup(THD *thd)
Field* field = table->field[0];
switch(field->type())
{
- /*
- If we have a string, we must take care of charsets and case
- sensitivity
- */
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
- compare_key = (qsort_cmp2)(field->binary() ? simple_raw_key_cmp:
- simple_str_key_cmp);
+ if (field->binary())
+ {
+ compare_key = (qsort_cmp2)simple_raw_key_cmp;
+ cmp_arg = (void*) &key_length;
+ }
+ else
+ {
+ /*
+ If we have a string, we must take care of charsets and case
+ sensitivity
+ */
+ compare_key = (qsort_cmp2)simple_str_key_cmp;
+ cmp_arg = (void*) this;
+ }
break;
default:
/*
@@ -1002,11 +1102,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
be compared with memcmp
*/
compare_key = (qsort_cmp2)simple_raw_key_cmp;
+ cmp_arg = (void*) &key_length;
break;
}
- key_length = field->pack_length();
- cmp_arg = (void*) &key_length;
- rec_offset = 1;
+ key_charset = field->charset();
+ key_length = field->pack_length();
+ rec_offset = 1;
}
else // too bad, cannot cheat - there is more than one field
{
@@ -1039,8 +1140,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
}
}
- init_tree(&tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
+ init_tree(tree, min(thd->variables.max_heap_table_size,
+ thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1;
@@ -1052,6 +1153,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
*/
max_elements_in_tree = ((key_length) ?
thd->variables.max_heap_table_size/key_length : 1);
+
+ }
+ if (original)
+ {
+ original->table= table;
+ original->use_tree= use_tree;
}
return 0;
}
@@ -1059,12 +1166,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
int Item_sum_count_distinct::tree_to_myisam()
{
- if (create_myisam_from_heap(table, tmp_table_param,
+ if (create_myisam_from_heap(current_thd, table, tmp_table_param,
HA_ERR_RECORD_FILE_FULL, 1) ||
- tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this,
+ tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
left_root_right))
return 1;
- delete_tree(&tree);
+ delete_tree(tree);
use_tree = 0;
return 0;
}
@@ -1072,7 +1179,7 @@ int Item_sum_count_distinct::tree_to_myisam()
void Item_sum_count_distinct::reset()
{
if (use_tree)
- reset_tree(&tree);
+ reset_tree(tree);
else if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
@@ -1100,12 +1207,13 @@ bool Item_sum_count_distinct::add()
If the tree got too big, convert to MyISAM, otherwise insert into the
tree.
*/
- if (tree.elements_in_tree > max_elements_in_tree)
+ if (tree->elements_in_tree > max_elements_in_tree)
{
if (tree_to_myisam())
return 1;
}
- else if (!tree_insert(&tree, table->record[0] + rec_offset, 0))
+ else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
+ tree->custom_arg))
return 1;
}
else if ((error=table->file->write_row(table->record[0])))
@@ -1113,19 +1221,21 @@ bool Item_sum_count_distinct::add()
if (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)
{
- if (create_myisam_from_heap(table, tmp_table_param, error,1))
+ if (create_myisam_from_heap(current_thd, table, tmp_table_param, error,
+ 1))
return 1; // Not a table_is_full error
}
}
return 0;
}
+
longlong Item_sum_count_distinct::val_int()
{
if (!table) // Empty query
return LL(0);
if (use_tree)
- return tree.elements_in_tree;
+ return tree->elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records;
}
@@ -1167,7 +1277,7 @@ String *Item_sum_udf_float::val_str(String *str)
if (null_value)
return 0; /* purecov: inspected */
else
- str->set(nr,decimals);
+ str->set(nr,decimals,thd_charset());
return str;
}
@@ -1186,7 +1296,7 @@ String *Item_sum_udf_int::val_str(String *str)
if (null_value)
return 0;
else
- str->set(nr);
+ str->set(nr,thd_charset());
return str;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 29ac1f1d1b1..db8bded9946 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -27,30 +27,37 @@ class Item_sum :public Item_result_field
{
public:
enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
- MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,SUM_BIT_FUNC,
+ MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
UDF_SUM_FUNC };
Item **args,*tmp_args[2];
uint arg_count;
bool quick_group; /* If incremental update of fields */
- Item_sum() : arg_count(0),quick_group(1) { with_sum_func=1; }
+ void mark_as_sum_func();
+ Item_sum() : arg_count(0),quick_group(1)
+ {
+ mark_as_sum_func();
+ }
Item_sum(Item *a) :quick_group(1)
{
arg_count=1;
args=tmp_args;
args[0]=a;
- with_sum_func = 1;
+ mark_as_sum_func();
}
Item_sum( Item *a, Item *b ) :quick_group(1)
{
arg_count=2;
args=tmp_args;
args[0]=a; args[1]=b;
- with_sum_func=1;
+ mark_as_sum_func();
}
Item_sum(List<Item> &list);
+ //Copy constructor, need to perform subselects with temporary tables
+ Item_sum(THD *thd, Item_sum &item);
~Item_sum() { result_field=0; }
+
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
virtual void reset()=0;
@@ -71,7 +78,7 @@ public:
void fix_num_length_and_dec();
void no_rows_in_result() { reset(); }
virtual bool setup(THD *thd) {return 0;}
- unsigned int size_of() { return sizeof(*this);}
+ Item *get_tmp_table_item(THD *thd);
};
@@ -82,11 +89,11 @@ public:
Item_sum_num(Item *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {}
- bool fix_fields(THD *,struct st_table_list *);
+ Item_sum_num(THD *thd, Item_sum_num &item) :Item_sum(thd, item) {}
+ bool fix_fields(THD *, TABLE_LIST *, Item **);
longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str);
void reset_field();
- unsigned int size_of() { return sizeof(*this);}
};
@@ -98,10 +105,10 @@ class Item_sum_int :public Item_sum_num
public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
+ Item_sum_int(THD *thd, Item_sum_int &item) :Item_sum_num(thd, item) {}
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
- unsigned int size_of() { return sizeof(*this);}
};
@@ -112,6 +119,8 @@ class Item_sum_sum :public Item_sum_num
public:
Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {}
+ Item_sum_sum(THD *thd, Item_sum_sum &item)
+ :Item_sum_num(thd, item), sum(item.sum) {}
enum Sumfunctype sum_func () const {return SUM_FUNC;}
void reset();
bool add();
@@ -119,7 +128,7 @@ class Item_sum_sum :public Item_sum_num
void reset_field();
void update_field(int offset);
const char *func_name() const { return "sum"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_sum(thd, *this); }
};
@@ -132,6 +141,10 @@ class Item_sum_count :public Item_sum_int
Item_sum_count(Item *item_par)
:Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0)
{}
+ Item_sum_count(THD *thd, Item_sum_count &item)
+ :Item_sum_int(thd, item), count(item.count),
+ used_table_cache(item.used_table_cache)
+ {}
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
@@ -143,7 +156,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void update_field(int offset);
const char *func_name() const { return "count"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_count(thd, *this); }
};
@@ -153,12 +166,20 @@ class Item_sum_count_distinct :public Item_sum_int
{
TABLE *table;
table_map used_table_cache;
- bool fix_fields(THD *thd,TABLE_LIST *tables);
+ bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
- TREE tree;
- uint key_length;
+ TREE tree_base;
+ TREE *tree;
+ /*
+ Following is 0 normal object and pointer to original one for copy
+ (to correctly free resources)
+ */
+ Item_sum_count_distinct *original;
+ uint key_length;
+ CHARSET_INFO *key_charset;
+
// calculated based on max_heap_table_size. If reached,
// walk the tree and dump it into MyISAM table
uint max_elements_in_tree;
@@ -177,14 +198,26 @@ class Item_sum_count_distinct :public Item_sum_int
int tree_to_myisam();
friend int composite_key_cmp(void* arg, byte* key1, byte* key2);
+ friend int simple_str_key_cmp(void* arg, byte* key1, byte* key2);
+ friend int simple_raw_key_cmp(void* arg, byte* key1, byte* key2);
friend int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct* item);
public:
Item_sum_count_distinct(List<Item> &list)
- :Item_sum_int(list),table(0),used_table_cache(~(table_map) 0),
- tmp_table_param(0),use_tree(0),always_null(0)
- { quick_group=0; }
+ :Item_sum_int(list), table(0), used_table_cache(~(table_map) 0),
+ tmp_table_param(0), tree(&tree_base), original(0), use_tree(0),
+ always_null(0)
+ { quick_group= 0; }
+ Item_sum_count_distinct(THD *thd, Item_sum_count_distinct &item)
+ :Item_sum_int(thd, item), table(item.table),
+ used_table_cache(item.used_table_cache),
+ field_lengths(item.field_lengths), tmp_table_param(item.tmp_table_param),
+ tree(item.tree), original(&item), key_length(item.key_length),
+ max_elements_in_tree(item.max_elements_in_tree),
+ rec_offset(item.rec_offset), use_tree(item.use_tree),
+ always_null(item.always_null)
+ {}
~Item_sum_count_distinct();
table_map used_tables() const { return used_table_cache; }
@@ -196,8 +229,11 @@ class Item_sum_count_distinct :public Item_sum_int
void update_field(int offset) { return ; } // Never called
const char *func_name() const { return "count_distinct"; }
bool setup(THD *thd);
+ Item *copy_or_same(THD* thd)
+ {
+ return new Item_sum_count_distinct(thd, *this);
+ }
void no_rows_in_result() {}
- unsigned int size_of() { return sizeof(*this);}
};
@@ -215,9 +251,8 @@ public:
longlong val_int() { return (longlong) val(); }
bool is_null() { (void) val_int(); return null_value; }
String *val_str(String*);
- void make_field(Send_field *field);
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() {}
- unsigned int size_of() { return sizeof(*this);}
};
@@ -230,6 +265,8 @@ class Item_sum_avg :public Item_sum_num
public:
Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ Item_sum_avg(THD *thd, Item_sum_avg &item)
+ :Item_sum_num(thd, item), sum(item.sum), count(item.count) {}
enum Sumfunctype sum_func () const {return AVG_FUNC;}
void reset();
bool add();
@@ -239,47 +276,86 @@ class Item_sum_avg :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_avg_field(this); }
const char *func_name() const { return "avg"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_avg(thd, *this); }
};
-class Item_sum_std;
+class Item_sum_variance;
-class Item_std_field :public Item_result_field
+class Item_variance_field :public Item_result_field
{
public:
Field *field;
- Item_std_field(Item_sum_std *item);
- enum Type type() const { return FIELD_STD_ITEM; }
+ Item_variance_field(Item_sum_variance *item);
+ enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val();
longlong val_int() { return (longlong) val(); }
String *val_str(String*);
bool is_null() { (void) val_int(); return null_value; }
- void make_field(Send_field *field);
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() {}
- unsigned int size_of() { return sizeof(*this);}
};
-class Item_sum_std :public Item_sum_num
+/*
+
+variance(a) =
+
+= sum (ai - avg(a))^2 / count(a) )
+= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
+= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
+= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
+= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
+= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
+= (sum(ai^2) - sum(a)^2/count(a))/count(a)
+
+*/
+
+class Item_sum_variance : public Item_sum_num
{
- double sum;
- double sum_sqr;
+ double sum, sum_sqr;
ulonglong count;
void fix_length_and_dec() { decimals+=4; maybe_null=1; }
public:
- Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {}
- enum Sumfunctype sum_func () const { return STD_FUNC; }
+ Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ Item_sum_variance(THD *thd, Item_sum_variance &item):
+ Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr),
+ count(item.count) {}
+ enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset();
bool add();
double val();
void reset_field();
void update_field(int offset);
Item *result_item(Field *field)
- { return new Item_std_field(this); }
- const char *func_name() const { return "std"; }
- unsigned int size_of() { return sizeof(*this);}
+ { return new Item_variance_field(this); }
+ const char *func_name() const { return "variance"; }
+ Item *copy_or_same(THD* thd) { return new Item_sum_variance(thd, *this); }
+};
+
+class Item_sum_std;
+
+class Item_std_field :public Item_variance_field
+{
+public:
+ Item_std_field(Item_sum_std *item);
+ enum Type type() const { return FIELD_STD_ITEM; }
+ double val();
};
+/*
+ standard_deviation(a) = sqrt(variance(a))
+*/
+
+class Item_sum_std :public Item_sum_variance
+{
+ public:
+ Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
+ enum Sumfunctype sum_func () const { return STD_FUNC; }
+ double val();
+ Item *result_item(Field *field)
+ { return new Item_std_field(this); }
+ const char *func_name() const { return "std"; }
+};
// This class is a string or number function depending on num_func
@@ -290,14 +366,21 @@ class Item_sum_hybrid :public Item_sum
double sum;
longlong sum_int;
Item_result hybrid_type;
+ enum_field_types hybrid_field_type;
int cmp_sign;
table_map used_table_cache;
+ int (*str_cmp_function)(const String *x,const String *y);
public:
- Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
+ Item_sum_hybrid(Item *item_par,int sign)
+ :Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign),
used_table_cache(~(table_map) 0)
{}
- bool fix_fields(THD *,struct st_table_list *);
+ Item_sum_hybrid(THD *thd, Item_sum_hybrid &item):
+ Item_sum(thd, item), value(item.value), tmp_value(item.tmp_value),
+ sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type),
+ cmp_sign(item.cmp_sign), used_table_cache(used_table_cache) {}
+ bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
@@ -316,11 +399,11 @@ class Item_sum_hybrid :public Item_sum
void make_const() { used_table_cache=0; }
bool keep_field_type(void) const { return 1; }
enum Item_result result_type () const { return hybrid_type; }
+ enum enum_field_types field_type() const { return hybrid_field_type; }
void update_field(int offset);
void min_max_update_str_field(int offset);
void min_max_update_real_field(int offset);
void min_max_update_int_field(int offset);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -328,11 +411,12 @@ class Item_sum_min :public Item_sum_hybrid
{
public:
Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {}
+ Item_sum_min(THD *thd, Item_sum_min &item) :Item_sum_hybrid(thd, item) {}
enum Sumfunctype sum_func () const {return MIN_FUNC;}
bool add();
const char *func_name() const { return "min"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_min(thd, *this); }
};
@@ -340,11 +424,12 @@ class Item_sum_max :public Item_sum_hybrid
{
public:
Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {}
+ Item_sum_max(THD *thd, Item_sum_max &item) :Item_sum_hybrid(thd, item) {}
enum Sumfunctype sum_func () const {return MAX_FUNC;}
bool add();
const char *func_name() const { return "max"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_max(thd, *this); }
};
@@ -356,11 +441,12 @@ class Item_sum_bit :public Item_sum_int
public:
Item_sum_bit(Item *item_par,ulonglong reset_arg)
:Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {}
+ Item_sum_bit(THD *thd, Item_sum_bit &item):
+ Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {}
enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
void reset();
longlong val_int();
void reset_field();
- unsigned int size_of() { return sizeof(*this);}
};
@@ -368,10 +454,11 @@ class Item_sum_or :public Item_sum_bit
{
public:
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
+ Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {}
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_or"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_or(thd, *this); }
};
@@ -379,10 +466,11 @@ class Item_sum_and :public Item_sum_bit
{
public:
Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {}
+ Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {}
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_and"; }
- unsigned int size_of() { return sizeof(*this);}
+ Item *copy_or_same(THD* thd) { return new Item_sum_and(thd, *this); }
};
/*
@@ -400,10 +488,13 @@ public:
Item_udf_sum( udf_func *udf_arg, List<Item> &list )
:Item_sum( list ), udf(udf_arg)
{ quick_group=0;}
+ Item_udf_sum(THD *thd, Item_udf_sum &item)
+ :Item_sum(thd, item), udf(item.udf) {}
~Item_udf_sum() {}
const char *func_name() const { return udf.name(); }
- bool fix_fields(THD *thd,struct st_table_list *tables)
+ bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ fixed= 1;
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
@@ -413,7 +504,6 @@ public:
bool add();
void reset_field() {};
void update_field(int offset_arg) {};
- unsigned int size_of() { return sizeof(*this);}
};
@@ -423,11 +513,14 @@ class Item_sum_udf_float :public Item_udf_sum
Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
+ Item_sum_udf_float(THD *thd, Item_sum_udf_float &item)
+ :Item_udf_sum(thd, item) {}
~Item_sum_udf_float() {}
longlong val_int() { return (longlong) Item_sum_udf_float::val(); }
double val();
String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
+ Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); }
};
@@ -437,12 +530,15 @@ public:
Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
+ Item_sum_udf_int(THD *thd, Item_sum_udf_int &item)
+ :Item_udf_sum(thd, item) {}
~Item_sum_udf_int() {}
longlong val_int();
double val() { return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
+ Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); }
};
@@ -452,20 +548,26 @@ public:
Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
+ Item_sum_udf_str(THD *thd, Item_sum_udf_str &item)
+ :Item_udf_sum(thd, item) {}
~Item_sum_udf_str() {}
String *val_str(String *);
double val()
{
+ int err;
String *res; res=val_str(&str_value);
- return res ? atof(res->c_ptr()) : 0.0;
+ return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),
+ (char**) 0, &err) : 0.0;
}
longlong val_int()
{
+ int err;
String *res; res=val_str(&str_value);
- return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0;
+ return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10, (char**) 0, &err) : (longlong) 0;
}
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
+ Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); }
};
#else /* Dummy functions to get sql_yacc.cc compiled */
@@ -475,12 +577,15 @@ class Item_sum_udf_float :public Item_sum_num
public:
Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_float(THD *thd, Item_sum_udf_float &item)
+ :Item_sum_num(thd, item) {}
~Item_sum_udf_float() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
double val() { return 0.0; }
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); }
};
@@ -489,6 +594,8 @@ class Item_sum_udf_int :public Item_sum_num
public:
Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_int(THD *thd, Item_sum_udf_int &item)
+ :Item_sum_num(thd, item) {}
~Item_sum_udf_int() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { return 0; }
@@ -496,6 +603,7 @@ public:
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); }
};
@@ -504,6 +612,8 @@ class Item_sum_udf_str :public Item_sum_num
public:
Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {}
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_str(THD *thd, Item_sum_udf_str &item)
+ :Item_sum_num(thd, item) {}
~Item_sum_udf_str() {}
String *val_str(String *) { null_value=1; return 0; }
double val() { null_value=1; return 0.0; }
@@ -514,6 +624,7 @@ public:
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); }
};
#endif /* HAVE_DLOPEN */
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 6a95c15a226..a032e25cec8 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -29,11 +29,31 @@
** Todo: Move month and days to language files
*/
-static String month_names[] = { "January", "February", "March", "April",
- "May", "June", "July", "August",
- "September", "October", "November", "December" };
-static String day_names[] = { "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday" ,"Sunday" };
+static String month_names[] =
+{
+ String("January", &my_charset_latin1),
+ String("February", &my_charset_latin1),
+ String("March", &my_charset_latin1),
+ String("April", &my_charset_latin1),
+ String("May", &my_charset_latin1),
+ String("June", &my_charset_latin1),
+ String("July", &my_charset_latin1),
+ String("August", &my_charset_latin1),
+ String("September", &my_charset_latin1),
+ String("October", &my_charset_latin1),
+ String("November", &my_charset_latin1),
+ String("December", &my_charset_latin1)
+};
+static String day_names[] =
+{
+ String("Monday", &my_charset_latin1),
+ String("Tuesday", &my_charset_latin1),
+ String("Wednesday", &my_charset_latin1),
+ String("Thursday", &my_charset_latin1),
+ String("Friday", &my_charset_latin1),
+ String("Saturday", &my_charset_latin1),
+ String("Sunday", &my_charset_latin1)
+};
/*
** Get a array of positive numbers from a string object.
@@ -44,21 +64,21 @@ static String day_names[] = { "Monday", "Tuesday", "Wednesday",
** DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
*/
-bool get_interval_info(const char *str,uint length,uint count,
- long *values)
+bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
+ uint count, long *values)
{
const char *end=str+length;
uint i;
- while (str != end && !isdigit(*str))
+ while (str != end && !my_isdigit(cs,*str))
str++;
for (i=0 ; i < count ; i++)
{
long value;
- for (value=0; str != end && isdigit(*str) ; str++)
+ for (value=0; str != end && my_isdigit(cs,*str) ; str++)
value=value*10L + (long) (*str - '0');
values[i]= value;
- while (str != end && !isdigit(*str))
+ while (str != end && !my_isdigit(cs,*str))
str++;
if (str == end && i != count-1)
{
@@ -133,14 +153,17 @@ longlong Item_func_month::val_int()
String* Item_func_monthname::val_str(String* str)
{
- uint month=(uint) Item_func_month::val_int();
+ uint month=(uint) Item_func_month::val_int();
if (!month) // This is also true for NULL
{
null_value=1;
return (String*) 0;
}
null_value=0;
- return &month_names[month-1];
+
+ String *m=&month_names[month-1];
+ str->copy(m->ptr(), m->length(), m->charset(), thd_charset());
+ return str;
}
// Returns the quarter of the year
@@ -227,7 +250,10 @@ String* Item_func_dayname::val_str(String* str)
uint weekday=(uint) val_int(); // Always Item_func_daynr()
if (null_value)
return (String*) 0;
- return &day_names[weekday];
+
+ String *d=&day_names[weekday];
+ str->copy(d->ptr(), d->length(), d->charset(), thd_charset());
+ return str;
}
@@ -269,8 +295,8 @@ longlong Item_func_time_to_sec::val_int()
/*
-** Convert a string to a interval value
-** To make code easy, allow interval objects without separators.
+ Convert a string to a interval value
+ To make code easy, allow interval objects without separators.
*/
static bool get_interval_value(Item *args,interval_type int_type,
@@ -280,6 +306,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
const char *str;
uint32 length;
LINT_INIT(value); LINT_INIT(str); LINT_INIT(length);
+ CHARSET_INFO *cs=str_value->charset();
bzero((char*) t,sizeof(*t));
if ((int) int_type <= INTERVAL_SECOND)
@@ -302,7 +329,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
/* record negative intervalls in t->neg */
str=res->ptr();
const char *end=str+res->length();
- while (str != end && isspace(*str))
+ while (str != end && my_isspace(cs,*str))
str++;
if (str != end && *str == '-')
{
@@ -332,26 +359,26 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->second=value;
break;
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
- if (get_interval_info(str,length,2,array))
+ if (get_interval_info(str,length,cs,2,array))
return (1);
t->year=array[0];
t->month=array[1];
break;
case INTERVAL_DAY_HOUR:
- if (get_interval_info(str,length,2,array))
+ if (get_interval_info(str,length,cs,2,array))
return (1);
t->day=array[0];
t->hour=array[1];
break;
case INTERVAL_DAY_MINUTE:
- if (get_interval_info(str,length,3,array))
+ if (get_interval_info(str,length,cs,3,array))
return (1);
t->day=array[0];
t->hour=array[1];
t->minute=array[2];
break;
case INTERVAL_DAY_SECOND:
- if (get_interval_info(str,length,4,array))
+ if (get_interval_info(str,length,cs,4,array))
return (1);
t->day=array[0];
t->hour=array[1];
@@ -359,20 +386,20 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->second=array[3];
break;
case INTERVAL_HOUR_MINUTE:
- if (get_interval_info(str,length,2,array))
+ if (get_interval_info(str,length,cs,2,array))
return (1);
t->hour=array[0];
t->minute=array[1];
break;
case INTERVAL_HOUR_SECOND:
- if (get_interval_info(str,length,3,array))
+ if (get_interval_info(str,length,cs,3,array))
return (1);
t->hour=array[0];
t->minute=array[1];
t->second=array[2];
break;
case INTERVAL_MINUTE_SECOND:
- if (get_interval_info(str,length,2,array))
+ if (get_interval_info(str,length,cs,2,array))
return (1);
t->minute=array[0];
t->second=array[1];
@@ -389,21 +416,21 @@ String *Item_date::val_str(String *str)
return (String*) 0;
if (!value) // zero daynr
{
- str->copy("0000-00-00");
+ str->copy("0000-00-00",10,&my_charset_latin1,thd_charset());
return str;
}
- if (str->alloc(11))
- return &empty_string; /* purecov: inspected */
- sprintf((char*) str->ptr(),"%04d-%02d-%02d",
+
+ char tmpbuff[11];
+ sprintf(tmpbuff,"%04d-%02d-%02d",
(int) (value/10000L) % 10000,
(int) (value/100)%100,
(int) (value%100));
- str->length(10);
+ str->copy(tmpbuff,10,&my_charset_latin1,thd_charset());
return str;
}
-bool Item_date::save_in_field(Field *field, bool no_conversions)
+int Item_date::save_in_field(Field *field, bool no_conversions)
{
TIME ltime;
timestamp_type t_type=TIMESTAMP_FULL;
@@ -435,7 +462,10 @@ void Item_func_curdate::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- decimals=0; max_length=10;
+
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
localtime_r(&query_start,&tm_tmp);
start=&tm_tmp;
value=(longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
@@ -460,28 +490,50 @@ bool Item_func_curdate::get_date(TIME *res,
return 0;
}
+String *Item_func_curtime::val_str(String *str)
+{
+ str_value.set(buff,buff_length,thd_charset());
+ return &str_value;
+}
+
void Item_func_curtime::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- decimals=0; max_length=8;
+ CHARSET_INFO *cs=thd_charset();
+
+ decimals=0;
+ max_length=8*cs->mbmaxlen;
localtime_r(&query_start,&tm_tmp);
start=&tm_tmp;
+ set_charset(cs);
value=(longlong) ((ulong) ((uint) start->tm_hour)*10000L+
(ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec));
- sprintf(buff,"%02d:%02d:%02d",
- (int) start->tm_hour,
- (int) start->tm_min,
- (int) start->tm_sec);
- buff_length=(uint) strlen(buff);
+
+ buff_length=cs->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d",
+ (int) start->tm_hour,
+ (int) start->tm_min,
+ (int) start->tm_sec);
+}
+
+
+String *Item_func_now::val_str(String *str)
+{
+ str_value.set(buff,buff_length,thd_charset());
+ return &str_value;
}
+
void Item_func_now::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- decimals=0; max_length=19;
+ CHARSET_INFO *cs= &my_charset_bin;
+
+ decimals=0;
+ max_length=19*cs->mbmaxlen;
+ set_charset(cs);
localtime_r(&query_start,&tm_tmp);
start=&tm_tmp;
value=((longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
@@ -490,14 +542,15 @@ void Item_func_now::fix_length_and_dec()
(longlong) ((ulong) ((uint) start->tm_hour)*10000L+
(ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec)));
- sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
- ((int) (start->tm_year+1900)) % 10000,
- (int) start->tm_mon+1,
- (int) start->tm_mday,
- (int) start->tm_hour,
- (int) start->tm_min,
- (int) start->tm_sec);
- buff_length=(uint) strlen(buff);
+
+ buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ ((int) (start->tm_year+1900)) % 10000,
+ (int) start->tm_mon+1,
+ (int) start->tm_mday,
+ (int) start->tm_hour,
+ (int) start->tm_min,
+ (int) start->tm_sec);
/* For getdate */
ltime.year= start->tm_year+1900;
ltime.month= start->tm_mon+1;
@@ -518,7 +571,7 @@ bool Item_func_now::get_date(TIME *res,
}
-bool Item_func_now::save_in_field(Field *to, bool no_conversions)
+int Item_func_now::save_in_field(Field *to, bool no_conversions)
{
to->set_notnull();
to->store_time(&ltime,TIMESTAMP_FULL);
@@ -528,9 +581,10 @@ bool Item_func_now::save_in_field(Field *to, bool no_conversions)
String *Item_func_sec_to_time::val_str(String *str)
{
- char buff[23];
+ char buff[23*2];
const char *sign="";
longlong seconds=(longlong) args[0]->val_int();
+ ulong length;
if ((null_value=args[0]->null_value))
return (String*) 0;
if (seconds < 0)
@@ -539,9 +593,9 @@ String *Item_func_sec_to_time::val_str(String *str)
sign= "-";
}
uint sec= (uint) ((ulonglong) seconds % 3600);
- sprintf(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600),
- sec/60, sec % 60);
- str->copy(buff,(uint) strlen(buff));
+ length= my_sprintf(buff,(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600),
+ sec/60, sec % 60));
+ str->copy(buff, length, &my_charset_latin1, thd_charset());
return str;
}
@@ -651,6 +705,7 @@ String *Item_func_date_format::val_str(String *str)
TIME l_time;
char intbuff[15];
uint size,weekday;
+ ulong length;
if (!date_or_time)
{
@@ -743,40 +798,39 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- sprintf(intbuff,"%d",l_time.day);
- str->append(intbuff);
+ length= my_sprintf(intbuff, (intbuff,"%d",l_time.day));
+ str->append(intbuff, length);
if (l_time.day >= 10 && l_time.day <= 19)
str->append("th");
else
{
- switch (l_time.day %10)
- {
+ switch (l_time.day %10) {
case 1:
- str->append("st");
+ str->append("st",2);
break;
case 2:
- str->append("nd");
+ str->append("nd",2);
break;
case 3:
- str->append("rd");
+ str->append("rd",2);
break;
default:
- str->append("th");
+ str->append("th",2);
break;
}
}
break;
case 'Y':
sprintf(intbuff,"%04d",l_time.year);
- str->append(intbuff);
+ str->append(intbuff,4);
break;
case 'y':
sprintf(intbuff,"%02d",l_time.year%100);
- str->append(intbuff);
+ str->append(intbuff,2);
break;
case 'm':
sprintf(intbuff,"%02d",l_time.month);
- str->append(intbuff);
+ str->append(intbuff,2);
break;
case 'c':
sprintf(intbuff,"%d",l_time.month);
@@ -784,7 +838,7 @@ String *Item_func_date_format::val_str(String *str)
break;
case 'd':
sprintf(intbuff,"%02d",l_time.day);
- str->append(intbuff);
+ str->append(intbuff,2);
break;
case 'e':
sprintf(intbuff,"%d",l_time.day);
@@ -792,16 +846,16 @@ String *Item_func_date_format::val_str(String *str)
break;
case 'H':
sprintf(intbuff,"%02d",l_time.hour);
- str->append(intbuff);
+ str->append(intbuff,2);
break;
case 'h':
case 'I':
sprintf(intbuff,"%02d", (l_time.hour+11)%12+1);
- str->append(intbuff);
+ str->append(intbuff,2);
break;
case 'i': /* minutes */
sprintf(intbuff,"%02d",l_time.minute);
- str->append(intbuff);
+ str->append(intbuff,2);
break;
case 'j':
if (date_or_time)
@@ -812,7 +866,7 @@ String *Item_func_date_format::val_str(String *str)
sprintf(intbuff,"%03d",
(int) (calc_daynr(l_time.year,l_time.month,l_time.day) -
calc_daynr(l_time.year,1,1)) + 1);
- str->append(intbuff);
+ str->append(intbuff,3);
break;
case 'k':
sprintf(intbuff,"%d",l_time.hour);
@@ -823,7 +877,7 @@ String *Item_func_date_format::val_str(String *str)
str->append(intbuff);
break;
case 'p':
- str->append(l_time.hour < 12 ? "AM" : "PM");
+ str->append(l_time.hour < 12 ? "AM" : "PM",2);
break;
case 'r':
sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" :
@@ -837,7 +891,8 @@ String *Item_func_date_format::val_str(String *str)
str->append(intbuff);
break;
case 'T':
- sprintf(intbuff,"%02d:%02d:%02d",l_time.hour,l_time.minute,l_time.second);
+ sprintf(intbuff,"%02d:%02d:%02d", l_time.hour, l_time.minute,
+ l_time.second);
str->append(intbuff);
break;
case 'U':
@@ -845,7 +900,7 @@ String *Item_func_date_format::val_str(String *str)
{
uint year;
sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
- str->append(intbuff);
+ str->append(intbuff,2);
}
break;
case 'v':
@@ -853,7 +908,7 @@ String *Item_func_date_format::val_str(String *str)
{
uint year;
sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
- str->append(intbuff);
+ str->append(intbuff,2);
}
break;
case 'x':
@@ -862,13 +917,13 @@ String *Item_func_date_format::val_str(String *str)
uint year;
(void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
sprintf(intbuff,"%04d",year);
- str->append(intbuff);
+ str->append(intbuff,4);
}
break;
case 'w':
weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1);
- sprintf(intbuff,"%01d",weekday);
- str->append(intbuff);
+ sprintf(intbuff,"%d",weekday);
+ str->append(intbuff,1);
break;
default:
str->append(*ptr);
@@ -884,20 +939,26 @@ String *Item_func_from_unixtime::val_str(String *str)
{
struct tm tm_tmp,*start;
time_t tmp=(time_t) args[0]->val_int();
+ uint32 l;
+ CHARSET_INFO *cs=thd_charset();
+
if ((null_value=args[0]->null_value))
return 0;
localtime_r(&tmp,&tm_tmp);
start=&tm_tmp;
- if (str->alloc(20))
+
+ l=20*cs->mbmaxlen+32;
+ if (str->alloc(l))
return str; /* purecov: inspected */
- sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d",
+ l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
(int) start->tm_year+1900,
(int) start->tm_mon+1,
(int) start->tm_mday,
(int) start->tm_hour,
(int) start->tm_min,
(int) start->tm_sec);
- str->length(19);
+ str->length(l);
+ str->set_charset(cs);
return str;
}
@@ -938,7 +999,42 @@ bool Item_func_from_unixtime::get_date(TIME *ltime,
return 0;
}
- /* Here arg[1] is a Item_interval object */
+
+void Item_date_add_interval::fix_length_and_dec()
+{
+ enum_field_types arg0_field_type;
+ set_charset(thd_charset());
+ maybe_null=1;
+ max_length=19*thd_charset()->mbmaxlen;
+ value.alloc(32);
+
+ /*
+ The field type for the result of an Item_date function is defined as
+ follows:
+
+ - If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
+ - If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
+ minutes or seconds then type is MYSQL_TYPE_DATETIME.
+ - Otherwise the result is MYSQL_TYPE_STRING
+ (This is because you can't know if the string contains a DATE, TIME or
+ DATETIME argument)
+ */
+ cached_field_type= MYSQL_TYPE_STRING;
+ arg0_field_type= args[0]->field_type();
+ if (arg0_field_type == MYSQL_TYPE_DATETIME ||
+ arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ else if (arg0_field_type == MYSQL_TYPE_DATE)
+ {
+ if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
+ cached_field_type= arg0_field_type;
+ else
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ }
+}
+
+
+/* Here arg[1] is a Item_interval object */
bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
{
@@ -1028,26 +1124,31 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
+ CHARSET_INFO *cs=thd_charset();
+ uint32 l;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
if (ltime.time_type == TIMESTAMP_DATE)
{
- if (str->alloc(11))
+ l=11*cs->mbmaxlen+32;
+ if (str->alloc(l))
goto null_date;
- sprintf((char*) str->ptr(),"%04d-%02d-%02d",
+ l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d",
ltime.year,ltime.month,ltime.day);
- str->length(10);
+ str->length(l);
}
else
{
- if (str->alloc(20))
+ l=20*cs->mbmaxlen+32;
+ if (str->alloc(l))
goto null_date;
- sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d",
+ l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
ltime.year,ltime.month,ltime.day,
ltime.hour,ltime.minute,ltime.second);
- str->length(19);
+ str->length(l);
}
+ str->set_charset(cs);
return str;
null_date:
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 0ca2a36609d..03180793d8a 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -27,7 +27,10 @@ public:
Item_func_period_add(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "period_add"; }
- void fix_length_and_dec() { max_length=6; }
+ void fix_length_and_dec()
+ {
+ max_length=6*thd_charset()->mbmaxlen;
+ }
};
@@ -37,7 +40,11 @@ public:
Item_func_period_diff(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "period_diff"; }
- void fix_length_and_dec() { decimals=0; max_length=6; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*thd_charset()->mbmaxlen;
+ }
};
@@ -47,7 +54,12 @@ public:
Item_func_to_days(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "to_days"; }
- void fix_length_and_dec() { decimals=0; max_length=6; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -57,7 +69,12 @@ public:
Item_func_dayofmonth(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "dayofmonth"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -67,10 +84,20 @@ public:
Item_func_month(Item *a) :Item_func(a) {}
longlong val_int();
double val() { return (double) Item_func_month::val_int(); }
- String *val_str(String *str) { str->set(val_int()); return null_value ? 0 : str;}
+ String *val_str(String *str)
+ {
+ str->set(val_int(), thd_charset());
+ return null_value ? 0 : str;
+ }
const char *func_name() const { return "month"; }
enum Item_result result_type () const { return INT_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -81,7 +108,13 @@ public:
const char *func_name() const { return "monthname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -91,7 +124,12 @@ public:
Item_func_dayofyear(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "dayofyear"; }
- void fix_length_and_dec() { decimals=0; max_length=3; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=3*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -101,7 +139,12 @@ public:
Item_func_hour(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "hour"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -111,7 +154,12 @@ public:
Item_func_minute(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "minute"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -121,7 +169,12 @@ public:
Item_func_quarter(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "quarter"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=1*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -131,7 +184,12 @@ public:
Item_func_second(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "second"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -141,7 +199,12 @@ public:
Item_func_week(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "week"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
class Item_func_yearweek :public Item_int_func
@@ -150,7 +213,12 @@ public:
Item_func_yearweek(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "yearweek"; }
- void fix_length_and_dec() { decimals=0; max_length=6; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -160,7 +228,12 @@ public:
Item_func_year(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "year"; }
- void fix_length_and_dec() { decimals=0; max_length=4; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=4*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -172,11 +245,20 @@ public:
:Item_func(a), odbc_type(type_arg) {}
longlong val_int();
double val() { return (double) val_int(); }
- String *val_str(String *str) { str->set(val_int()); return null_value ? 0 : str;}
+ String *val_str(String *str)
+ {
+ str->set(val_int(), thd_charset());
+ return null_value ? 0 : str;
+ }
const char *func_name() const { return "weekday"; }
enum Item_result result_type () const { return INT_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; }
- unsigned int size_of() { return sizeof(*this);}
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=1*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
class Item_func_dayname :public Item_func_weekday
@@ -186,7 +268,13 @@ class Item_func_dayname :public Item_func_weekday
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=9; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=9*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -200,9 +288,9 @@ public:
const char *func_name() const { return "timestamp"; }
void fix_length_and_dec()
{
- decimals=0; max_length=10;
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
}
- unsigned int size_of() { return sizeof(*this);}
};
@@ -214,7 +302,8 @@ public:
const char *func_name() const { return "time_to_sec"; }
void fix_length_and_dec()
{
- decimals=0; max_length=10;
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
}
};
@@ -227,20 +316,22 @@ public:
Item_date() :Item_func() {}
Item_date(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str);
double val() { return (double) val_int(); }
const char *func_name() const { return "date"; }
- void fix_length_and_dec() { decimals=0; max_length=10; }
- bool save_in_field(Field *to, bool no_conversions);
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATE);
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
}
+ int save_in_field(Field *to, bool no_conversions);
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg);
+ return (new Field_date(maybe_null, name, t_arg, thd_charset()));
}
- unsigned int size_of() { return sizeof(*this);}
};
@@ -250,43 +341,35 @@ public:
Item_date_func() :Item_str_func() {}
Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
- t_arg);
+ return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
}
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_curtime :public Item_func
{
longlong value;
- char buff[9];
+ char buff[9*2+32];
uint buff_length;
public:
Item_func_curtime() :Item_func() {}
Item_func_curtime(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
double val() { return (double) value; }
longlong val_int() { return value; }
- String *val_str(String *str)
- { str_value.set(buff,buff_length); return &str_value; }
+ String *val_str(String *str);
const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_TIME);
- }
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg);
+ return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
- unsigned int size_of() { return sizeof(*this);}
};
@@ -300,14 +383,13 @@ public:
const char *func_name() const { return "curdate"; }
void fix_length_and_dec(); /* Retrieves curtime */
bool get_date(TIME *res,bool fuzzy_date);
- unsigned int size_of() { return sizeof(*this);}
};
class Item_func_now :public Item_date_func
{
longlong value;
- char buff[20];
+ char buff[20*2+32]; // +32 to make my_snprintf_{8bit|ucs2} happy
uint buff_length;
TIME ltime;
public:
@@ -316,13 +398,11 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
double val() { return (double) value; }
longlong val_int() { return value; }
- bool save_in_field(Field *to, bool no_conversions);
- String *val_str(String *str)
- { str_value.set(buff,buff_length); return &str_value; }
+ int save_in_field(Field *to, bool no_conversions);
+ String *val_str(String *str);
const char *func_name() const { return "now"; }
void fix_length_and_dec();
bool get_date(TIME *res,bool fuzzy_date);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -347,7 +427,6 @@ public:
const char *func_name() const { return "date_format"; }
void fix_length_and_dec();
uint format_length(const String *format);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -359,8 +438,12 @@ class Item_func_from_unixtime :public Item_date_func
longlong val_int();
String *val_str(String *str);
const char *func_name() const { return "from_unixtime"; }
- void fix_length_and_dec() { decimals=0; max_length=19; }
-// enum Item_result result_type () const { return STRING_RESULT; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=19*thd_charset()->mbmaxlen;
+ }
bool get_date(TIME *res,bool fuzzy_date);
};
@@ -372,42 +455,52 @@ public:
double val() { return (double) Item_func_sec_to_time::val_int(); }
longlong val_int();
String *val_str(String *);
- void fix_length_and_dec() { maybe_null=1; max_length=13; }
- const char *func_name() const { return "sec_to_time"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_TIME);
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ maybe_null=1;
+ max_length=13*thd_charset()->mbmaxlen;
}
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ const char *func_name() const { return "sec_to_time"; }
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg);
+ return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
+/*
+ The following must be sorted so that simple intervals comes first.
+ (get_interval_value() depends on this)
+*/
+
+enum interval_type
+{
+ INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
+ INTERVAL_SECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
+ INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
+ INTERVAL_MINUTE_SECOND
+};
-enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY,
- INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND,
- INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
- INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND,
- INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
- INTERVAL_MINUTE_SECOND};
class Item_date_add_interval :public Item_date_func
{
const interval_type int_type;
String value;
const bool date_sub_interval;
+ enum_field_types cached_field_type;
public:
Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg)
:Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
String *val_str(String *);
const char *func_name() const { return "date_add_interval"; }
- void fix_length_and_dec() { maybe_null=1; max_length=19; value.alloc(32);}
+ void fix_length_and_dec();
+ enum_field_types field_type() const { return cached_field_type; }
double val() { return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res,bool fuzzy_date);
- unsigned int size_of() { return sizeof(*this);}
};
@@ -422,7 +515,6 @@ class Item_extract :public Item_int_func
longlong val_int();
const char *func_name() const { return "extract"; }
void fix_length_and_dec();
- unsigned int size_of() { return sizeof(*this);}
};
@@ -432,8 +524,17 @@ public:
Item_typecast(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "char"; }
String *val_str(String *a)
- { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; }
- void fix_length_and_dec() { max_length=args[0]->max_length; }
+ {
+ String *tmp=args[0]->val_str(a);
+ null_value=args[0]->null_value;
+ tmp->set_charset(charset());
+ return tmp;
+ }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ max_length=args[0]->max_length;
+ }
void print(String *str);
};
@@ -442,7 +543,11 @@ class Item_char_typecast :public Item_typecast
{
public:
Item_char_typecast(Item *a) :Item_typecast(a) {}
- void fix_length_and_dec() { binary=0; max_length=args[0]->max_length; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ max_length=args[0]->max_length;
+ }
};
@@ -451,13 +556,11 @@ class Item_date_typecast :public Item_typecast
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATE);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg);
+ return (new Field_date(maybe_null, name, t_arg, thd_charset()));
}
};
@@ -467,13 +570,11 @@ class Item_time_typecast :public Item_typecast
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_TIME);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg);
+ return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
@@ -483,13 +584,10 @@ class Item_datetime_typecast :public Item_typecast
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; }
- void make_field(Send_field *tmp_field)
- {
- init_make_field(tmp_field,FIELD_TYPE_DATETIME);
- }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
- t_arg);
+ return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
}
};
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index cc087832f49..5ffd10be7a5 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -29,20 +29,29 @@ public:
:Item_real_func(list) {}
double val() { return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; }
- unsigned int size_of() { return sizeof(*this);}
};
+
class Item_sum_unique_users :public Item_sum_num
{
public:
Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg)
:Item_sum_num(item_arg) {}
+ Item_sum_unique_users(THD *thd, Item_sum_unique_users &item)
+ :Item_sum_num(thd, item) {}
double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void reset() {}
bool add() { return 0; }
void reset_field() {}
void update_field(int offset) {}
- bool fix_fields(THD *thd,struct st_table_list *tlist) { return 0;}
- unsigned int size_of() { return sizeof(*this);}
+ bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
+ {
+ fixed= 1;
+ return 0;
+ }
+ Item *copy_or_same(THD* thd)
+ {
+ return new Item_sum_unique_users(thd, *this);
+ }
};
diff --git a/sql/key.cc b/sql/key.cc
index d103c07eb72..38ab596e213 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -192,8 +192,10 @@ int key_cmp(TABLE *table,const byte *key,uint idx,uint key_length)
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
FIELDFLAG_PACK)))
{
- if (my_sortcmp((char*) key,(char*) table->record[0]+key_part->offset,
- length))
+ if (my_strnncoll(key_part->field->charset(),
+ (const uchar*) key, length,
+ (const uchar*) table->record[0]+key_part->offset,
+ length))
return 1;
}
else if (memcmp(key,table->record[0]+key_part->offset,length))
diff --git a/sql/lex.h b/sql/lex.h
index a9e44e034d0..d4ae8c32828 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2002 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -56,8 +56,10 @@ static SYMBOL symbols[] = {
{ "AGAINST", SYM(AGAINST),0,0},
{ "ANALYZE", SYM(ANALYZE_SYM),0,0},
{ "AND", SYM(AND),0,0},
+ { "ANY", SYM(ANY_SYM),0,0},
{ "AS", SYM(AS),0,0},
{ "ASC", SYM(ASC),0,0},
+ { "ASCII", SYM(ASCII_SYM),0,0},
{ "AVG", SYM(AVG_SYM),0,0},
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH),0,0},
{ "AUTO_INCREMENT", SYM(AUTO_INC),0,0},
@@ -74,7 +76,9 @@ static SYMBOL symbols[] = {
{ "BOOL", SYM(BOOL_SYM),0,0},
{ "BOOLEAN", SYM(BOOLEAN_SYM),0,0},
{ "BOTH", SYM(BOTH),0,0},
+ { "BTREE", SYM(BTREE_SYM),0,0},
{ "BY", SYM(BY),0,0},
+ { "BYTE", SYM(BYTE_SYM), 0, 0},
{ "CACHE", SYM(CACHE_SYM),0,0},
{ "CASCADE", SYM(CASCADE),0,0},
{ "CASE", SYM(CASE_SYM),0,0},
@@ -88,6 +92,7 @@ static SYMBOL symbols[] = {
{ "CIPHER", SYM(CIPHER_SYM),0,0},
{ "CLIENT", SYM(CLIENT_SYM),0,0},
{ "CLOSE", SYM(CLOSE_SYM),0,0},
+ { "COLLATE", SYM(COLLATE_SYM),0,0},
{ "COLUMN", SYM(COLUMN_SYM),0,0},
{ "COLUMNS", SYM(COLUMNS),0,0},
{ "COMMENT", SYM(COMMENT_SYM),0,0},
@@ -124,11 +129,15 @@ static SYMBOL symbols[] = {
{ "DISABLE", SYM(DISABLE_SYM),0,0},
{ "DISTINCT", SYM(DISTINCT),0,0},
{ "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */
+ { "DIV", SYM(DIV_SYM),0,0},
{ "DO", SYM(DO_SYM),0,0},
{ "DOUBLE", SYM(DOUBLE_SYM),0,0},
+ { "DUAL", SYM(DUAL_SYM),0,0},
{ "DROP", SYM(DROP),0,0},
{ "DUMPFILE", SYM(DUMPFILE),0,0},
{ "DYNAMIC", SYM(DYNAMIC_SYM),0,0},
+ { "DUPLICATE", SYM(DUPLICATE_SYM),0,0},
+ { "ERRORS", SYM(ERRORS),0,0},
{ "END", SYM(END),0,0},
{ "ELSE", SYM(ELSE),0,0},
{ "ESCAPE", SYM(ESCAPE_SYM),0,0},
@@ -150,6 +159,7 @@ static SYMBOL symbols[] = {
{ "FLOAT4", SYM(FLOAT_SYM),0,0},
{ "FLOAT8", SYM(DOUBLE_SYM),0,0},
{ "FLUSH", SYM(FLUSH_SYM),0,0},
+ { "FALSE", SYM(FALSE_SYM),0,0},
{ "FOREIGN", SYM(FOREIGN),0,0},
{ "FORCE", SYM(FORCE_SYM),0,0},
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
@@ -161,13 +171,16 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL),0,0},
{ "FULLTEXT", SYM(FULLTEXT_SYM),0,0},
{ "FUNCTION", SYM(UDF_SYM),0,0},
+ { "GEOMETRY", SYM(GEOMETRY_SYM),0,0},
{ "GLOBAL", SYM(GLOBAL_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0},
{ "GROUP", SYM(GROUP),0,0},
{ "HAVING", SYM(HAVING),0,0},
{ "HANDLER", SYM(HANDLER_SYM),0,0},
+ { "HASH", SYM(HASH_SYM),0,0},
{ "HEAP", SYM(HEAP_SYM),0,0},
+ { "HELP", SYM(HELP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0},
@@ -209,6 +222,7 @@ static SYMBOL symbols[] = {
{ "LEVEL", SYM(LEVEL_SYM),0,0},
{ "LIKE", SYM(LIKE),0,0},
{ "LINES", SYM(LINES),0,0},
+ { "LINESTRING", SYM(LINESTRING),0,0},
{ "LIMIT", SYM(LIMIT),0,0},
{ "LOAD", SYM(LOAD),0,0},
{ "LOCAL", SYM(LOCAL_SYM),0,0},
@@ -244,9 +258,13 @@ static SYMBOL symbols[] = {
{ "MIN_ROWS", SYM(MIN_ROWS),0,0},
{ "MINUTE", SYM(MINUTE_SYM),0,0},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0},
+ { "MOD", SYM(MOD_SYM),0,0},
{ "MODE", SYM(MODE_SYM),0,0},
{ "MODIFY", SYM(MODIFY_SYM),0,0},
{ "MONTH", SYM(MONTH_SYM),0,0},
+ { "MULTILINESTRING", SYM(MULTILINESTRING),0,0},
+ { "MULTIPOINT", SYM(MULTIPOINT),0,0},
+ { "MULTIPOLYGON", SYM(MULTIPOLYGON),0,0},
{ "MRG_MYISAM", SYM(MERGE_SYM),0,0},
{ "MYISAM", SYM(MYISAM_SYM),0,0},
{ "NATURAL", SYM(NATURAL),0,0},
@@ -272,6 +290,8 @@ static SYMBOL symbols[] = {
{ "PACK_KEYS", SYM(PACK_KEYS_SYM),0,0},
{ "PARTIAL", SYM(PARTIAL),0,0},
{ "PASSWORD", SYM(PASSWORD),0,0},
+ { "POINT", SYM(POINT),0,0},
+ { "POLYGON", SYM(POLYGON),0,0},
{ "PURGE", SYM(PURGE),0,0},
{ "PRECISION", SYM(PRECISION),0,0},
{ "PREV", SYM(PREV_SYM),0,0},
@@ -308,25 +328,31 @@ static SYMBOL symbols[] = {
{ "ROLLUP", SYM(ROLLUP_SYM),0,0},
{ "ROW", SYM(ROW_SYM),0,0},
{ "ROWS", SYM(ROWS_SYM),0,0},
+ { "RTREE", SYM(RTREE_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
+ { "SERIAL", SYM(SERIAL_SYM),0,0},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
{ "SESSION", SYM(SESSION_SYM),0,0},
{ "SET", SYM(SET),0,0},
{ "SIGNED", SYM(SIGNED_SYM),0,0},
+ { "SIMPLE", SYM(SIMPLE_SYM),0,0},
{ "SHARE", SYM(SHARE_SYM),0,0},
{ "SHOW", SYM(SHOW),0,0},
{ "SHUTDOWN", SYM(SHUTDOWN),0,0},
{ "SLAVE", SYM(SLAVE),0,0},
{ "SMALLINT", SYM(SMALLINT),0,0},
+ { "SOME", SYM(ANY_SYM),0,0},
{ "SONAME", SYM(UDF_SONAME_SYM),0,0},
+ { "SPATIAL", SYM(SPATIAL_SYM),0,0},
{ "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT),0,0},
{ "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0},
{ "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0},
{ "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0},
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
- { "SQL_THREAD", SYM(SQL_THREAD),0,0},
+ { "SQL_THREAD", SYM(SQL_THREAD),0,0},
+ { "SOUNDS", SYM(SOUNDS_SYM),0,0},
{ "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0},
@@ -351,9 +377,12 @@ static SYMBOL symbols[] = {
{ "TRAILING", SYM(TRAILING),0,0},
{ "TRANSACTION", SYM(TRANSACTION_SYM),0,0},
{ "TRUNCATE", SYM(TRUNCATE_SYM),0,0},
+ { "TRUE", SYM(TRUE_SYM),0,0},
{ "TO", SYM(TO_SYM),0,0},
{ "TYPE", SYM(TYPE_SYM),0,0},
+ { "TYPES", SYM(TYPES_SYM),0,0},
{ "UNCOMMITTED", SYM(UNCOMMITTED_SYM),0,0},
+ { "UNICODE", SYM(UNICODE_SYM),0,0},
{ "UNION", SYM(UNION_SYM),0,0},
{ "UNIQUE", SYM(UNIQUE_SYM),0,0},
{ "UNLOCK", SYM(UNLOCK_SYM),0,0},
@@ -363,11 +392,14 @@ static SYMBOL symbols[] = {
{ "USING", SYM(USING),0,0},
{ "UPDATE", SYM(UPDATE_SYM),0,0},
{ "USAGE", SYM(USAGE),0,0},
+ { "VALUE", SYM(VALUE_SYM),0,0},
{ "VALUES", SYM(VALUES),0,0},
{ "VARCHAR", SYM(VARCHAR),0,0},
+ { "VARCHARACTER", SYM(VARCHAR),0,0},
{ "VARIABLES", SYM(VARIABLES),0,0},
{ "VARYING", SYM(VARYING),0,0},
{ "VARBINARY", SYM(VARBINARY),0,0},
+ { "WARNINGS", SYM(WARNINGS),0,0},
{ "WITH", SYM(WITH),0,0},
{ "WORK", SYM(WORK_SYM),0,0},
{ "WRITE", SYM(WRITE_SYM),0,0},
@@ -388,8 +420,9 @@ static SYMBOL sql_functions[] = {
{ "ADDDATE", SYM(DATE_ADD_INTERVAL),0,0},
{ "AES_ENCRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)},
{ "AES_DECRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)},
- { "ASCII", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ascii)},
+ { "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)},
{ "ASIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)},
+ { "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_text)},
{ "ATAN", SYM(ATAN),0,0},
{ "ATAN2", SYM(ATAN),0,0},
{ "BENCHMARK", SYM(BENCHMARK_SYM),0,0},
@@ -402,17 +435,21 @@ static SYMBOL sql_functions[] = {
{ "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
{ "CURRENT_USER", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)},
{ "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
+ { "CENTROID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)},
{ "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "COALESCE", SYM(COALESCE),0,0},
{ "CONCAT", SYM(CONCAT),0,0},
{ "CONCAT_WS", SYM(CONCAT_WS),0,0},
{ "CONNECTION_ID", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
+ { "CONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
{ "CONV", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
{ "CONVERT", SYM(CONVERT_SYM),0,0},
{ "COUNT", SYM(COUNT_SYM),0,0},
{ "COS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
{ "COT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
+ { "CRC32", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)},
+ { "CROSSES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_crosses)},
{ "CURDATE", SYM(CURDATE),0,0},
{ "CURTIME", SYM(CURTIME),0,0},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL),0,0},
@@ -426,9 +463,15 @@ static SYMBOL sql_functions[] = {
{ "DEGREES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)},
{ "DES_ENCRYPT", SYM(DES_ENCRYPT_SYM),0,0},
{ "DES_DECRYPT", SYM(DES_DECRYPT_SYM),0,0},
+ { "DIMENSION", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dimension)},
+ { "DISJOINT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_disjoint)},
{ "ELT", SYM(ELT_FUNC),0,0},
{ "ENCODE", SYM(ENCODE_SYM),0,0},
{ "ENCRYPT", SYM(ENCRYPT),0,0},
+ { "ENDPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_endpoint)},
+ { "ENVELOPE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_envelope)},
+ { "EQUALS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_equals)},
+ { "EXTERIORRING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exteriorring)},
{ "EXTRACT", SYM(EXTRACT_SYM),0,0},
{ "EXP", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)},
{ "EXPORT_SET", SYM(EXPORT_SET),0,0},
@@ -440,6 +483,12 @@ static SYMBOL sql_functions[] = {
{ "FROM_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)},
{ "FROM_UNIXTIME", SYM(FROM_UNIXTIME),0,0},
{ "GET_LOCK", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)},
+ { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION),0,0},
+ { "GEOMETRYN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_geometryn)},
+ { "GEOMETRYTYPE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_geometry_type)},
+ { "GEOMCOLLFROMTEXT", SYM(GEOMCOLLFROMTEXT),0,0},
+ { "GEOMFROMTEXT", SYM(GEOMFROMTEXT),0,0},
+ { "GLENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_glength)},
{ "GREATEST", SYM(GREATEST_SYM),0,0},
{ "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS),0,0},
{ "HEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)},
@@ -447,13 +496,20 @@ static SYMBOL sql_functions[] = {
{ "INET_ATON", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)},
{ "INET_NTOA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)},
{ "INSTR", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)},
+ { "INTERIORRINGN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_interiorringn)},
+ { "INTERSECTS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_intersects)},
+ { "ISCLOSED", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isclosed)},
+ { "ISEMPTY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isempty)},
{ "ISNULL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)},
{ "IS_FREE_LOCK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)},
{ "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
+ { "ISSIMPLE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_issimple)},
{ "LCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
{ "LEAST", SYM(LEAST_SYM),0,0},
{ "LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "LN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)},
+ { "LINEFROMTEXT", SYM(LINEFROMTEXT),0,0},
+ { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT),0,0},
{ "LOAD_FILE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)},
{ "LOCATE", SYM(LOCATE),0,0},
{ "LOG", SYM(LOG_SYM),0,0},
@@ -468,17 +524,29 @@ static SYMBOL sql_functions[] = {
{ "MD5", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
{ "MID", SYM(SUBSTRING),0,0}, /* unireg function */
{ "MIN", SYM(MIN_SYM),0,0},
- { "MOD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_mod)},
+ { "MLINEFROMTEXT", SYM(MLINEFROMTEXT),0,0},
+ { "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT),0,0},
+ { "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT),0,0},
{ "MONTHNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)},
+ { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT),0,0},
+ { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT),0,0},
{ "NOW", SYM(NOW_SYM),0,0},
{ "NULLIF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)},
+ { "NUMGEOMETRIES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numgeometries)},
+ { "NUMINTERIORRINGS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numinteriorring)},
+ { "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)},
{ "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)},
- { "OLD_PASSWORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_password)},
+ { "OLD_PASSWORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_old_password)},
{ "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)},
+ { "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
{ "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},
{ "PERIOD_DIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)},
{ "PI", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)},
+ { "POINTFROMTEXT", SYM(POINTFROMTEXT),0,0},
+ { "POINTN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pointn)},
+ { "POLYFROMTEXT", SYM(POLYFROMTEXT),0,0},
+ { "POLYGONFROMTEXT", SYM(POLYFROMTEXT),0,0},
{ "POSITION", SYM(POSITION_SYM),0,0},
{ "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
@@ -502,6 +570,7 @@ static SYMBOL sql_functions[] = {
{ "SOUNDEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
{ "SPACE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
{ "SQRT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
+ { "STARTPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_startpoint)},
{ "STD", SYM(STD_SYM),0,0},
{ "STDDEV", SYM(STD_SYM),0,0},
{ "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
@@ -514,14 +583,19 @@ static SYMBOL sql_functions[] = {
{ "TIME_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
{ "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
{ "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
+ { "TOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
{ "TRIM", SYM(TRIM),0,0},
{ "UCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0},
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0},
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "USER", SYM(USER),0,0},
+ { "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
+ { "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
+ { "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
+ { "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
{ "YEARWEEK", SYM(YEARWEEK),0,0}
};
diff --git a/sql/lock.cc b/sql/lock.cc
index 4c84bbb6e69..8f342b28d67 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -68,7 +68,12 @@ TODO:
#include "mysql_priv.h"
#include <hash.h>
-#include <assert.h>
+#include "ha_myisammrg.h"
+#ifndef MASTER
+#include "../srclib/myisammrg/myrg_def.h"
+#else
+#include "../myisammrg/myrg_def.h"
+#endif
extern HASH open_cache;
@@ -156,6 +161,7 @@ retry:
sql_lock=0;
}
}
+
thd->lock_time();
DBUG_RETURN (sql_lock);
}
@@ -412,8 +418,12 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
return 0;
}
}
+ THR_LOCK_DATA **org_locks = locks;
locks=table->file->store_lock(thd, locks, get_old_locks ? TL_IGNORE :
lock_type);
+ if (locks)
+ for ( ; org_locks != locks ; org_locks++)
+ (*org_locks)->debug_print_param= (void *) table;
}
return sql_lock;
}
diff --git a/sql/log.cc b/sql/log.cc
index 073b7f691e8..6b06bd781ce 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -29,7 +29,6 @@
#include <my_dir.h>
#include <stdarg.h>
#include <m_ctype.h> // For test_if_number
-#include <assert.h>
MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
@@ -45,16 +44,19 @@ static bool test_if_number(const char *str,
static int find_uniq_filename(char *name)
{
- long number;
- uint i,length;
- char buff[FN_REFLEN];
- struct st_my_dir *dir_info;
+ long number;
+ uint i;
+ char buff[FN_REFLEN];
+ struct st_my_dir *dir_info;
reg1 struct fileinfo *file_info;
- ulong max_found=0;
+ ulong max_found=0;
+
DBUG_ENTER("find_uniq_filename");
- length=dirname_part(buff,name);
- char *start=name+length,*end=strend(start);
+ uint length = dirname_part(buff,name);
+ char *start = name + length;
+ char *end = strend(start);
+
*end='.';
length= (uint) (end-start+1);
@@ -75,7 +77,7 @@ static int find_uniq_filename(char *name)
my_dirend(dir_info);
*end++='.';
- sprintf(end,"%03ld",max_found+1);
+ sprintf(end,"%06ld",max_found+1);
DBUG_RETURN(0);
}
@@ -204,7 +206,9 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
case LOG_NORMAL:
{
char *end;
-#ifdef __NT__
+#ifdef EMBEDDED_LIBRARY
+ sprintf(buff, "%s, Version: %s, embedded library\n", my_progname, server_version);
+#elif __NT__
sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port);
#else
sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port);
@@ -220,15 +224,18 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
time_t skr=time(NULL);
struct tm tm_tmp;
localtime_r(&skr,&tm_tmp);
- sprintf(buff,"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n",
- my_progname,server_version,
- tm_tmp.tm_year % 100,
- tm_tmp.tm_mon+1,
- tm_tmp.tm_mday,
- tm_tmp.tm_hour,
- tm_tmp.tm_min,
- tm_tmp.tm_sec);
- if (my_b_write(&log_file, (byte*) buff,(uint) strlen(buff)) ||
+ ulong length;
+ length= my_sprintf(buff,
+ (buff,
+ "# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n",
+ my_progname,server_version,
+ tm_tmp.tm_year % 100,
+ tm_tmp.tm_mon+1,
+ tm_tmp.tm_mday,
+ tm_tmp.tm_hour,
+ tm_tmp.tm_min,
+ tm_tmp.tm_sec));
+ if (my_b_write(&log_file, (byte*) buff, length) ||
flush_io_cache(&log_file))
goto err;
break;
@@ -611,6 +618,8 @@ err:
LOG_INFO_IO Got IO error while reading file
*/
+#ifdef HAVE_REPLICATION
+
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
{
int error;
@@ -745,6 +754,8 @@ err:
DBUG_RETURN(error);
}
+#endif /* HAVE_REPLICATION */
+
/*
Create a new log file name
@@ -947,7 +958,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
{
if (is_open() && (what_to_log & (1L << (uint) command)))
{
- int error=0;
+ uint length;
+ int error= 0;
VOID(pthread_mutex_lock(&LOCK_log));
/* Test if someone closed between the is_open test and lock */
@@ -996,8 +1008,10 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
}
else if (my_b_write(&log_file, (byte*) "\t\t",2) < 0)
error=errno;
- sprintf(buff,"%7ld %-11.11s", id,command_name[(uint) command]);
- if (my_b_write(&log_file, (byte*) buff,strlen(buff)))
+ length=my_sprintf(buff,
+ (buff, "%7ld %-11.11s", id,
+ command_name[(uint) command]));
+ if (my_b_write(&log_file, (byte*) buff,length))
error=errno;
if (format)
{
@@ -1051,6 +1065,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
#else
IO_CACHE *file = &log_file;
#endif
+#ifdef HAVE_REPLICATION
if ((thd && !(thd->options & OPTION_BIN_LOG) &&
(thd->master_access & SUPER_ACL)) ||
(local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db)))
@@ -1059,6 +1074,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
DBUG_PRINT("error",("!db_ok"));
DBUG_RETURN(0);
}
+#endif /* HAVE_REPLICATION */
error=1;
/*
@@ -1093,6 +1109,23 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (e.write(file))
goto err;
}
+ if (thd->user_var_events.elements)
+ {
+ for (uint i= 0; i < thd->user_var_events.elements; i++)
+ {
+ BINLOG_USER_VAR_EVENT *user_var_event;
+ get_dynamic(&thd->user_var_events,(gptr) &user_var_event, i);
+ User_var_log_event e(thd, user_var_event->user_var_event->name.str,
+ user_var_event->user_var_event->name.length,
+ user_var_event->value,
+ user_var_event->length,
+ user_var_event->type,
+ user_var_event->charset_number);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
+ }
if (thd->variables.convert_set)
{
char buf[256], *p;
@@ -1270,11 +1303,7 @@ err:
/*
Write update log in a format suitable for incremental backup
-
- NOTE
- - This code should be deleted in MySQL 5,0 as the binary log
- is a full replacement for the update log.
-
+ This is also used by the slow query log.
*/
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
@@ -1449,6 +1478,7 @@ void MYSQL_LOG::close(bool exiting)
DBUG_PRINT("enter",("exiting: %d", (int) exiting));
if (is_open())
{
+#ifdef HAVE_REPLICATION
if (log_type == LOG_BIN && !no_auto_events && exiting)
{
Stop_log_event s;
@@ -1456,6 +1486,7 @@ void MYSQL_LOG::close(bool exiting)
s.write(&log_file);
signal_update();
}
+#endif /* HAVE_REPLICATION */
end_io_cache(&log_file);
if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
{
@@ -1513,8 +1544,8 @@ static bool test_if_number(register const char *str,
while (*str++ == ' ') ;
if (*--str == '-' || *str == '+')
str++;
- while (isdigit(*str) || (allow_wildcards &&
- (*str == wild_many || *str == wild_one)))
+ while (my_isdigit(files_charset_info,*str) ||
+ (allow_wildcards && (*str == wild_many || *str == wild_one)))
{
flag=1;
str++;
@@ -1522,7 +1553,7 @@ static bool test_if_number(register const char *str,
if (*str == '.')
{
for (str++ ;
- isdigit(*str) ||
+ my_isdigit(files_charset_info,*str) ||
(allow_wildcards && (*str == wild_many || *str == wild_one)) ;
str++, flag=1) ;
}
@@ -1625,3 +1656,6 @@ bool flush_error_log()
}
return result;
}
+
+
+
diff --git a/sql/log_event.cc b/sql/log_event.cc
index e243a953c63..0631e21fbd1 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -24,8 +24,13 @@
#include <my_dir.h>
#endif /* MYSQL_CLIENT */
-#include <assert.h>
+#define log_cs &my_charset_latin1
+/*****************************************************************************
+
+ my_b_safe_write()
+
+ ****************************************************************************/
inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
int len)
{
@@ -40,6 +45,11 @@ inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
return my_b_write(file, buf,len);
}
+/*****************************************************************************
+
+ pretty_print_str()
+
+ ****************************************************************************/
#ifdef MYSQL_CLIENT
static void pretty_print_str(FILE* file, char* str, int len)
{
@@ -63,40 +73,58 @@ static void pretty_print_str(FILE* file, char* str, int len)
}
fputc('\'', file);
}
-#endif
+#endif // MYSQL_CLIENT
-#ifndef MYSQL_CLIENT
+/*****************************************************************************
+ ignored_error_code()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
inline int ignored_error_code(int err_code)
{
return use_slave_mask && bitmap_is_set(&slave_error_mask, err_code);
}
+#endif
+
+/*****************************************************************************
+ pretty_print_str()
-static void pretty_print_str(String* packet, char* str, int len)
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
+static char* pretty_print_str(char* packet, char* str, int len)
{
char* end = str + len;
- packet->append('\'');
+ char* pos= packet;
+ *pos++= '\'';
while (str < end)
{
char c;
switch ((c=*str++)) {
- case '\n': packet->append( "\\n"); break;
- case '\r': packet->append( "\\r"); break;
- case '\\': packet->append( "\\\\"); break;
- case '\b': packet->append( "\\b"); break;
- case '\t': packet->append( "\\t"); break;
- case '\'': packet->append( "\\'"); break;
- case 0 : packet->append( "\\0"); break;
+ case '\n': pos= strmov(pos, "\\n"); break;
+ case '\r': pos= strmov(pos, "\\r"); break;
+ case '\\': pos= strmov(pos, "\\\\"); break;
+ case '\b': pos= strmov(pos, "\\b"); break;
+ case '\t': pos= strmov(pos, "\\t"); break;
+ case '\'': pos= strmov(pos, "\\'"); break;
+ case 0 : pos= strmov(pos, "\\0"); break;
default:
- packet->append((char)c);
+ *pos++= (char)c;
break;
}
}
- packet->append('\'');
+ *pos++= '\'';
+ return pos;
}
+#endif // !MYSQL_CLIENT
+
+/*****************************************************************************
+ slave_load_file_stem()
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static inline char* slave_load_file_stem(char*buf, uint file_id,
int event_server_id)
{
@@ -108,9 +136,81 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
*buf++ = '-';
return int10_to_str(file_id, buf, 10);
}
+#endif
+
+/*****************************************************************************
+
+ cleanup_load_tmpdir()
+
+ Delete all temporary files used for SQL_LOAD.
+
+ TODO
+ - When we get a 'server start' event, we should only remove
+ the files associated with the server id that just started.
+ Easily fixable by adding server_id as a prefix to the log files.
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+static void cleanup_load_tmpdir()
+{
+ MY_DIR *dirp;
+ FILEINFO *file;
+ uint i;
+ if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME))))
+ return;
+
+ for (i=0 ; i < (uint)dirp->number_off_files; i++)
+ {
+ file=dirp->dir_entry+i;
+ if (is_prefix(file->name,"SQL_LOAD-"))
+ my_delete(file->name, MYF(0));
+ }
+ my_dirend(dirp);
+}
#endif
+/*****************************************************************************
+
+ write_str()
+
+ ****************************************************************************/
+static bool write_str(IO_CACHE *file, char *str, byte length)
+{
+ return (my_b_safe_write(file, &length, 1) ||
+ my_b_safe_write(file, (byte*) str, (int) length));
+}
+
+/*****************************************************************************
+
+ read_str()
+
+ ****************************************************************************/
+static inline int read_str(char * &buf, char *buf_end, char * &str,
+ uint8 &len)
+{
+ if (buf + (uint) (uchar) *buf >= buf_end)
+ return 1;
+ len = (uint8) *buf;
+ str= buf+1;
+ buf+= (uint) len+1;
+ return 0;
+}
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Log_event::get_type_str()
+
+ ****************************************************************************/
const char* Log_event::get_type_str()
{
switch(get_type_code()) {
@@ -126,20 +226,27 @@ const char* Log_event::get_type_str()
case APPEND_BLOCK_EVENT: return "Append_block";
case DELETE_FILE_EVENT: return "Delete_file";
case EXEC_LOAD_EVENT: return "Exec_load";
+ case RAND_EVENT: return "RAND";
+ case USER_VAR_EVENT: return "User var";
default: /* impossible */ return "Unknown";
}
}
+/*****************************************************************************
+
+ Log_event::Log_event()
+
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
:temp_buf(0), exec_time(0), cached_event_len(0), flags(flags_arg),
thd(thd_arg)
{
- server_id = thd->server_id;
- when = thd->start_time;
- log_pos = thd->log_pos;
- cache_stmt= (using_trans &&
- (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+ server_id= thd->server_id;
+ when= thd->start_time;
+ log_pos= thd->log_pos;
+ cache_stmt= (using_trans &&
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
}
@@ -147,40 +254,17 @@ Log_event::Log_event()
:temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
thd(0)
{
- server_id = ::server_id;
- when = time(NULL);
- log_pos=0;
+ server_id= ::server_id;
+ when= time(NULL);
+ log_pos= 0;
}
+#endif // !MYSQL_CLIENT
-/*
- Delete all temporary files used for SQL_LOAD.
-
- TODO
- - When we get a 'server start' event, we should only remove
- the files associated with the server id that just started.
- Easily fixable by adding server_id as a prefix to the log files.
-*/
-
-static void cleanup_load_tmpdir()
-{
- MY_DIR *dirp;
- FILEINFO *file;
- uint i;
- if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME))))
- return;
-
- for (i=0 ; i < (uint)dirp->number_off_files; i++)
- {
- file=dirp->dir_entry+i;
- if (is_prefix(file->name,"SQL_LOAD-"))
- my_delete(file->name, MYF(0));
- }
-
- my_dirend(dirp);
-}
+/*****************************************************************************
-#endif
+ Log_event::Log_event()
+ ****************************************************************************/
Log_event::Log_event(const char* buf, bool old_format)
:temp_buf(0), cached_event_len(0), cache_stmt(0)
{
@@ -203,7 +287,13 @@ Log_event::Log_event(const char* buf, bool old_format)
#ifndef MYSQL_CLIENT
+#ifdef HAVE_REPLICATION
+
+/*****************************************************************************
+
+ Log_event::exec_event()
+ ****************************************************************************/
int Log_event::exec_event(struct st_relay_log_info* rli)
{
/*
@@ -231,217 +321,79 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
return 0;
}
-void Log_event::pack_info(String* packet)
-{
- net_store_data(packet, "", 0);
-}
-
-void Query_log_event::pack_info(String* packet)
-{
- char buf[256];
- String tmp(buf, sizeof(buf));
- tmp.length(0);
- if (db && db_len)
- {
- tmp.append("use ");
- tmp.append(db, db_len);
- tmp.append("; ", 2);
- }
+/*****************************************************************************
- if (query && q_len)
- tmp.append(query, q_len);
- net_store_data(packet, (char*)tmp.ptr(), tmp.length());
-}
+ Log_event::pack_info()
-void Start_log_event::pack_info(String* packet)
+ ****************************************************************************/
+void Log_event::pack_info(Protocol *protocol)
{
- char buf1[256];
- String tmp(buf1, sizeof(buf1));
- tmp.length(0);
- char buf[22];
-
- tmp.append("Server ver: ");
- tmp.append(server_version);
- tmp.append(", Binlog ver: ");
- tmp.append(llstr(binlog_version, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ protocol->store("",0);
}
-void Load_log_event::pack_info(String* packet)
-{
- char buf[256];
- String tmp(buf, sizeof(buf));
- tmp.length(0);
- if (db && db_len)
- {
- tmp.append("use ");
- tmp.append(db, db_len);
- tmp.append("; ", 2);
- }
-
- tmp.append("LOAD DATA INFILE '");
- tmp.append(fname, fname_len);
- tmp.append("' ", 2);
- if (sql_ex.opt_flags && REPLACE_FLAG )
- tmp.append(" REPLACE ");
- else if (sql_ex.opt_flags && IGNORE_FLAG )
- tmp.append(" IGNORE ");
-
- tmp.append("INTO TABLE ");
- tmp.append(table_name);
- if (sql_ex.field_term_len)
- {
- tmp.append(" FIELDS TERMINATED BY ");
- pretty_print_str(&tmp, sql_ex.field_term, sql_ex.field_term_len);
- }
- if (sql_ex.enclosed_len)
- {
- if (sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
- tmp.append(" OPTIONALLY ");
- tmp.append( " ENCLOSED BY ");
- pretty_print_str(&tmp, sql_ex.enclosed, sql_ex.enclosed_len);
- }
-
- if (sql_ex.escaped_len)
- {
- tmp.append( " ESCAPED BY ");
- pretty_print_str(&tmp, sql_ex.escaped, sql_ex.escaped_len);
- }
-
- if (sql_ex.line_term_len)
- {
- tmp.append(" LINES TERMINATED BY ");
- pretty_print_str(&tmp, sql_ex.line_term, sql_ex.line_term_len);
- }
-
- if (sql_ex.line_start_len)
- {
- tmp.append(" LINES STARTING BY ");
- pretty_print_str(&tmp, sql_ex.line_start, sql_ex.line_start_len);
- }
-
- if ((int)skip_lines > 0)
- tmp.append( " IGNORE %ld LINES ", (long) skip_lines);
-
- if (num_fields)
- {
- uint i;
- const char* field = fields;
- tmp.append(" (");
- for (i = 0; i < num_fields; i++)
- {
- if (i)
- tmp.append(" ,");
- tmp.append( field);
-
- field += field_lens[i] + 1;
- }
- tmp.append(')');
- }
+/*****************************************************************************
- net_store_data(packet, tmp.ptr(), tmp.length());
-}
+ Log_event::net_send()
-void Rotate_log_event::pack_info(String* packet)
-{
- char buf1[256], buf[22];
- String tmp(buf1, sizeof(buf1));
- tmp.length(0);
- tmp.append(new_log_ident, ident_len);
- tmp.append(";pos=");
- tmp.append(llstr(pos,buf));
- if (flags & LOG_EVENT_FORCED_ROTATE_F)
- tmp.append("; forced by master");
- net_store_data(packet, tmp.ptr(), tmp.length());
-}
+ Only called by SHOW BINLOG EVENTS
-void Intvar_log_event::pack_info(String* packet)
-{
- char buf1[256], buf[22];
- String tmp(buf1, sizeof(buf1));
- tmp.length(0);
- tmp.append(get_var_type_name());
- tmp.append('=');
- tmp.append(llstr(val, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
-}
+ ****************************************************************************/
-void Rand_log_event::pack_info(String* packet)
+int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
{
- char buf1[256], *pos;
- pos=strmov(buf1,"rand_seed1=");
- pos=int10_to_str((long) seed1, pos, 10);
- pos=strmov(pos, ",rand_seed2=");
- pos=int10_to_str((long) seed2, pos, 10);
- net_store_data(packet, buf1, (uint) (pos-buf1));
+ const char *p= strrchr(log_name, FN_LIBCHAR);
+ const char *event_type;
+ if (p)
+ log_name = p + 1;
+
+ protocol->prepare_for_resend();
+ protocol->store(log_name);
+ protocol->store((ulonglong) pos);
+ event_type = get_type_str();
+ protocol->store(event_type, strlen(event_type));
+ protocol->store((uint32) server_id);
+ protocol->store((ulonglong) log_pos);
+ pack_info(protocol);
+ return protocol->write();
}
+#endif /* HAVE_REPLICATION */
-void Slave_log_event::pack_info(String* packet)
-{
- char buf1[256], buf[22], *end;
- String tmp(buf1, sizeof(buf1));
- tmp.length(0);
- tmp.append("host=");
- tmp.append(master_host);
- tmp.append(",port=");
- end= int10_to_str((long) master_port, buf, 10);
- tmp.append(buf, (uint32) (end-buf));
- tmp.append(",log=");
- tmp.append(master_log);
- tmp.append(",pos=");
- tmp.append(llstr(master_pos,buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
-}
+/*****************************************************************************
+ Log_event::init_show_field_list()
+ ****************************************************************************/
void Log_event::init_show_field_list(List<Item>* field_list)
{
field_list->push_back(new Item_empty_string("Log_name", 20));
- field_list->push_back(new Item_empty_string("Pos", 20));
+ field_list->push_back(new Item_return_int("Pos", 11,
+ MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Event_type", 20));
- field_list->push_back(new Item_empty_string("Server_id", 20));
- field_list->push_back(new Item_empty_string("Orig_log_pos", 20));
+ field_list->push_back(new Item_return_int("Server_id", 10,
+ MYSQL_TYPE_LONG));
+ field_list->push_back(new Item_return_int("Orig_log_pos", 11,
+ MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Info", 20));
}
-/*
- * only called by SHOW BINLOG EVENTS
- */
-int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos)
-{
- String* packet = &thd_arg->packet;
- const char* p = strrchr(log_name, FN_LIBCHAR);
- const char* event_type;
- if (p)
- log_name = p + 1;
-
- packet->length(0);
- net_store_data(packet, log_name, strlen(log_name));
- net_store_data(packet, (longlong) pos);
- event_type = get_type_str();
- net_store_data(packet, event_type, strlen(event_type));
- net_store_data(packet, server_id);
- net_store_data(packet, (longlong) log_pos);
- pack_info(packet);
- return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length());
-}
-
-#endif /* MYSQL_CLIENT */
-
+#endif // !MYSQL_CLIENT
-int Query_log_event::write(IO_CACHE* file)
-{
- return query ? Log_event::write(file) : -1;
-}
+/*****************************************************************************
+ Log_event::write()
+ ****************************************************************************/
int Log_event::write(IO_CACHE* file)
{
return (write_header(file) || write_data(file)) ? -1 : 0;
}
+/*****************************************************************************
+ Log_event::write_header()
+
+ ****************************************************************************/
int Log_event::write_header(IO_CACHE* file)
{
char buf[LOG_EVENT_HEADER_LEN];
@@ -461,8 +413,13 @@ int Log_event::write_header(IO_CACHE* file)
return (my_b_safe_write(file, (byte*) buf, (uint) (pos - buf)));
}
-#ifndef MYSQL_CLIENT
+/*****************************************************************************
+
+ Log_event::read_log_event()
+
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock)
{
@@ -517,8 +474,7 @@ end:
pthread_mutex_unlock(log_lock);
DBUG_RETURN(result);
}
-
-#endif // MYSQL_CLIENT
+#endif // !MYSQL_CLIENT
#ifndef MYSQL_CLIENT
#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock);
@@ -529,7 +485,13 @@ end:
#define LOCK_MUTEX
#endif
-// allocates memory - the caller is responsible for clean-up
+/*****************************************************************************
+
+ Log_event::read_log_event()
+
+ Allocates memory--the caller is responsible for clean-up
+
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
Log_event* Log_event::read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
@@ -592,7 +554,11 @@ data_len=%d,event_type=%d",error,data_len,head[EVENT_TYPE_OFFSET]);
return res;
}
+/*****************************************************************************
+ Log_event::read_log_event()
+
+ ****************************************************************************/
Log_event* Log_event::read_log_event(const char* buf, int event_len,
const char **error, bool old_format)
{
@@ -610,7 +576,7 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
ev = new Query_log_event(buf, event_len, old_format);
break;
case LOAD_EVENT:
- ev = new Create_file_log_event(buf, event_len, old_format);
+ ev = new Load_log_event(buf, event_len, old_format);
break;
case NEW_LOAD_EVENT:
ev = new Load_log_event(buf, event_len, old_format);
@@ -618,9 +584,11 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
case ROTATE_EVENT:
ev = new Rotate_log_event(buf, event_len, old_format);
break;
+#ifdef HAVE_REPLICATION
case SLAVE_EVENT:
ev = new Slave_log_event(buf, event_len);
break;
+#endif /* HAVE_REPLICATION */
case CREATE_FILE_EVENT:
ev = new Create_file_log_event(buf, event_len, old_format);
break;
@@ -636,15 +604,20 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
case START_EVENT:
ev = new Start_log_event(buf, old_format);
break;
+#ifdef HAVE_REPLICATION
case STOP_EVENT:
ev = new Stop_log_event(buf, old_format);
break;
+#endif /* HAVE_REPLICATION */
case INTVAR_EVENT:
ev = new Intvar_log_event(buf, old_format);
break;
case RAND_EVENT:
ev = new Rand_log_event(buf, old_format);
break;
+ case USER_VAR_EVENT:
+ ev = new User_var_log_event(buf, old_format);
+ break;
default:
break;
}
@@ -658,8 +631,13 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
return ev;
}
-
#ifdef MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Log_event::print_header()
+
+ ****************************************************************************/
void Log_event::print_header(FILE* file)
{
char llbuff[22];
@@ -669,6 +647,11 @@ void Log_event::print_header(FILE* file)
llstr(log_pos,llbuff));
}
+/*****************************************************************************
+
+ Log_event::print_timestamp()
+
+ ****************************************************************************/
void Log_event::print_timestamp(FILE* file, time_t* ts)
{
struct tm *res;
@@ -690,117 +673,102 @@ void Log_event::print_timestamp(FILE* file, time_t* ts)
res->tm_sec);
}
+#endif // MYSQL_CLIENT
-void Start_log_event::print(FILE* file, bool short_form, char* last_db)
-{
- if (short_form)
- return;
+/*****************************************************************************
- print_header(file);
- fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
- server_version);
- print_timestamp(file, (time_t*)&created);
- fputc('\n', file);
- fflush(file);
-}
+ Log_event::set_log_pos()
-void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
+void Log_event::set_log_pos(MYSQL_LOG* log)
{
- if (short_form)
- return;
-
- print_header(file);
- fprintf(file, "\tStop\n");
- fflush(file);
+ if (!log_pos)
+ log_pos = my_b_tell(&log->log_file);
}
+#endif // !MYSQL_CLIENT
-void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
-{
- char buf[22];
- if (short_form)
- return;
- print_header(file);
- fprintf(file, "\tRotate to ");
- if (new_log_ident)
- my_fwrite(file, (byte*) new_log_ident, (uint)ident_len,
- MYF(MY_NABP | MY_WME));
- fprintf(file, " pos: %s", llstr(pos, buf));
- if (flags & LOG_EVENT_FORCED_ROTATE_F)
- fprintf(file," forced by master");
- fputc('\n', file);
- fflush(file);
-}
-#endif /* #ifdef MYSQL_CLIENT */
+/*****************************************************************************
+ *****************************************************************************
+ Query_log_event methods
-Start_log_event::Start_log_event(const char* buf,
- bool old_format)
- :Log_event(buf, old_format)
-{
- buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- binlog_version = uint2korr(buf+ST_BINLOG_VER_OFFSET);
- memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
- ST_SERVER_VER_LEN);
- created = uint4korr(buf+ST_CREATED_OFFSET);
-}
+ *****************************************************************************
+ ****************************************************************************/
-int Start_log_event::write_data(IO_CACHE* file)
-{
- char buff[START_HEADER_LEN];
- int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
- memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
- int4store(buff + ST_CREATED_OFFSET,created);
- return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
-}
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+/*****************************************************************************
+ Query_log_event::pack_info()
-Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
- bool old_format)
- :Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
+ ****************************************************************************/
+void Query_log_event::pack_info(Protocol *protocol)
{
- // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
- int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- uint ident_offset;
- if (event_len < header_size)
+ char *buf, *pos;
+ if (!(buf= my_malloc(9 + db_len + q_len, MYF(MY_WME))))
return;
- buf += header_size;
- if (old_format)
+ pos= buf;
+ if (db && db_len)
{
- ident_len = (uint)(event_len - OLD_HEADER_LEN);
- pos = 4;
- ident_offset = 0;
+ pos= strmov(buf, "use `");
+ memcpy(pos, db, db_len);
+ pos+= db_len;
+ pos= strmov(pos, "`; ");
}
- else
+ if (query && q_len)
{
- ident_len = (uint)(event_len - ROTATE_EVENT_OVERHEAD);
- pos = uint8korr(buf + R_POS_OFFSET);
- ident_offset = ROTATE_HEADER_LEN;
+ memcpy(pos, query, q_len);
+ pos+= q_len;
}
- set_if_smaller(ident_len,FN_REFLEN-1);
- if (!(new_log_ident= my_strdup_with_length((byte*) buf +
- ident_offset,
- (uint) ident_len,
- MYF(MY_WME))))
- return;
- alloced = 1;
+ protocol->store(buf, pos-buf);
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
}
+#endif
+/*****************************************************************************
-int Rotate_log_event::write_data(IO_CACHE* file)
+ Query_log_event::write()
+
+ ****************************************************************************/
+int Query_log_event::write(IO_CACHE* file)
{
- char buf[ROTATE_HEADER_LEN];
- int8store(buf, pos + R_POS_OFFSET);
- return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
- my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
+ return query ? Log_event::write(file) : -1;
}
+/*****************************************************************************
+
+ Query_log_event::write_data()
+ ****************************************************************************/
+int Query_log_event::write_data(IO_CACHE* file)
+{
+ if (!query)
+ return -1;
+
+ char buf[QUERY_HEADER_LEN];
+ int4store(buf + Q_THREAD_ID_OFFSET, thread_id);
+ int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
+ buf[Q_DB_LEN_OFFSET] = (char) db_len;
+ int2store(buf + Q_ERR_CODE_OFFSET, error_code);
+
+ return (my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) ||
+ my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
+ my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
+}
+
+/*****************************************************************************
+
+ Query_log_event::Query_log_event()
+
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
- :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg),
+ :Log_event(thd_arg, !thd_arg->tmp_table_used ?
+ 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans),
+ data_buf(0), query(query_arg),
db(thd_arg->db), q_len((uint32) query_length),
error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
thread_id(thd_arg->thread_id)
@@ -810,8 +778,13 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
exec_time = (ulong) (end_time - thd->start_time);
db_len = (db) ? (uint32) strlen(db) : 0;
}
-#endif
+#endif // MYSQL_CLIENT
+/*****************************************************************************
+
+ Query_log_event::Query_log_event()
+
+ ****************************************************************************/
Query_log_event::Query_log_event(const char* buf, int event_len,
bool old_format)
:Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
@@ -847,9 +820,12 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
*((char*)query+q_len) = 0;
}
+/*****************************************************************************
-#ifdef MYSQL_CLIENT
+ Query_log_event::print()
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
void Query_log_event::print(FILE* file, bool short_form, char* last_db)
{
char buff[40],*end; // Enough for SET TIMESTAMP
@@ -874,116 +850,357 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
*end++=';';
*end++='\n';
my_fwrite(file, (byte*) buff, (uint) (end-buff),MYF(MY_NABP | MY_WME));
+ if (flags & LOG_EVENT_THREAD_SPECIFIC_F)
+ fprintf(file,"SET @@session.pseudo_thread_id=%lu;\n",(ulong)thread_id);
my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
fprintf(file, ";\n");
}
-#endif
+#endif // MYSQL_CLIENT
+
+/*****************************************************************************
+ Query_log_event::exec_event()
-int Query_log_event::write_data(IO_CACHE* file)
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
- if (!query)
- return -1;
-
- char buf[QUERY_HEADER_LEN];
- int4store(buf + Q_THREAD_ID_OFFSET, thread_id);
- int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
- buf[Q_DB_LEN_OFFSET] = (char) db_len;
- int2store(buf + Q_ERR_CODE_OFFSET, error_code);
+ int expected_error,actual_error = 0;
+ init_sql_alloc(&thd->mem_root, 8192,0);
+ thd->db = rewrite_db((char*)db);
- return (my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) ||
- my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
- my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
-}
+ /*
+ InnoDB internally stores the master log position it has processed so far;
+ position to store is really pos + pending + event_len
+ since we must store the pos of the END of the current log event
+ */
+ rli->event_len= get_event_len();
-Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
- :Log_event(buf, old_format)
-{
- buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- type = buf[I_TYPE_OFFSET];
- val = uint8korr(buf+I_VAL_OFFSET);
-}
+ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ {
+ thd->set_time((time_t)when);
+ thd->current_tablenr = 0;
+ thd->query_length= q_len;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query = (char*)query;
+ thd->query_id = query_id++;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ thd->query_error= 0; // clear error
+ thd->clear_error();
+
+ thd->variables.pseudo_thread_id= thread_id; // for temp tables
+
+ /*
+ Sanity check to make sure the master did not get a really bad
+ error on the query.
+ */
+ if (ignored_error_code((expected_error = error_code)) ||
+ !check_expected_error(thd,rli,expected_error))
+ {
+ mysql_log.write(thd,COM_QUERY,"%s",thd->query);
+ DBUG_PRINT("query",("%s",thd->query));
+ mysql_parse(thd, thd->query, q_len);
-const char* Intvar_log_event::get_var_type_name()
-{
- switch(type) {
- case LAST_INSERT_ID_EVENT: return "LAST_INSERT_ID";
- case INSERT_ID_EVENT: return "INSERT_ID";
- default: /* impossible */ return "UNKNOWN";
+ /*
+ Set a flag if we are inside an transaction so that we can restart
+ the transaction from the start if we are killed
+
+ This will only be done if we are supporting transactional tables
+ in the slave.
+ */
+ if (!strcmp(thd->query,"BEGIN"))
+ rli->inside_transaction= opt_using_transactions;
+ else if (!strcmp(thd->query,"COMMIT"))
+ rli->inside_transaction=0;
+
+ DBUG_PRINT("info",("expected_error: %d last_errno: %d",
+ expected_error, thd->net.last_errno));
+ if ((expected_error != (actual_error= thd->net.last_errno)) &&
+ expected_error &&
+ !ignored_error_code(actual_error) &&
+ !ignored_error_code(expected_error))
+ {
+ const char* errmsg = "Slave: did not get the expected error\
+ running query from master - expected: '%s' (%d), got '%s' (%d)";
+ sql_print_error(errmsg, ER_SAFE(expected_error),
+ expected_error,
+ actual_error ? thd->net.last_error: "no error",
+ actual_error);
+ thd->query_error = 1;
+ }
+ else if (expected_error == actual_error ||
+ ignored_error_code(actual_error))
+ {
+ DBUG_PRINT("info",("error ignored"));
+ thd->query_error = 0;
+ *rli->last_slave_error = 0;
+ rli->last_slave_errno = 0;
+ }
+ }
+ else
+ {
+ // master could be inconsistent, abort and tell DBA to check/fix it
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->db = thd->query = 0;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ thd->variables.convert_set = 0;
+ close_thread_tables(thd);
+ free_root(&thd->mem_root,0);
+ return 1;
+ }
+ }
+ thd->db= 0; // prevent db from being freed
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query= 0; // just to be sure
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ // assume no convert for next query unless set explictly
+ thd->variables.convert_set = 0;
+ close_thread_tables(thd);
+
+ if (thd->query_error || thd->is_fatal_error)
+ {
+ slave_print_error(rli,actual_error, "error '%s' on query '%s'",
+ actual_error ? thd->net.last_error :
+ "unexpected success or fatal error", query);
+ free_root(&thd->mem_root,0);
+ return 1;
}
+ free_root(&thd->mem_root,0);
+ return Log_event::exec_event(rli);
}
+#endif
-int Intvar_log_event::write_data(IO_CACHE* file)
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Start_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Start_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Start_log_event::pack_info(Protocol *protocol)
{
- char buf[9];
- buf[I_TYPE_OFFSET] = type;
- int8store(buf + I_VAL_OFFSET, val);
- return my_b_safe_write(file, (byte*) buf, sizeof(buf));
+ char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
+ pos= strmov(buf, "Server ver: ");
+ pos= strmov(pos, server_version);
+ pos= strmov(pos, ", Binlog ver: ");
+ pos=int10_to_str(binlog_version, pos, 10);
+ protocol->store(buf, pos-buf);
}
+#endif
+/*****************************************************************************
+
+ Start_log_event::print()
+
+ ****************************************************************************/
#ifdef MYSQL_CLIENT
-void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
+void Start_log_event::print(FILE* file, bool short_form, char* last_db)
{
- char llbuff[22];
- const char *msg;
- LINT_INIT(msg);
-
- if (!short_form)
- {
- print_header(file);
- fprintf(file, "\tIntvar\n");
- }
+ if (short_form)
+ return;
- fprintf(file, "SET ");
- switch (type) {
- case LAST_INSERT_ID_EVENT:
- msg="LAST_INSERT_ID";
- break;
- case INSERT_ID_EVENT:
- msg="INSERT_ID";
- break;
- }
- fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff));
+ print_header(file);
+ fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
+ server_version);
+ print_timestamp(file, (time_t*)&created);
+ fputc('\n', file);
fflush(file);
}
-#endif
+#endif // MYSQL_CLIENT
/*****************************************************************************
- *
- * Rand log event
- *
+
+ Start_log_event::Start_log_event()
+
****************************************************************************/
-Rand_log_event::Rand_log_event(const char* buf, bool old_format)
+Start_log_event::Start_log_event(const char* buf,
+ bool old_format)
:Log_event(buf, old_format)
{
buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- seed1 = uint8korr(buf+RAND_SEED1_OFFSET);
- seed2 = uint8korr(buf+RAND_SEED2_OFFSET);
+ binlog_version = uint2korr(buf+ST_BINLOG_VER_OFFSET);
+ memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
+ ST_SERVER_VER_LEN);
+ created = uint4korr(buf+ST_CREATED_OFFSET);
}
-int Rand_log_event::write_data(IO_CACHE* file)
+/*****************************************************************************
+
+ Start_log_event::write_data()
+
+ ****************************************************************************/
+int Start_log_event::write_data(IO_CACHE* file)
{
- char buf[16];
- int8store(buf + RAND_SEED1_OFFSET, seed1);
- int8store(buf + RAND_SEED2_OFFSET, seed2);
- return my_b_safe_write(file, (byte*) buf, sizeof(buf));
+ char buff[START_HEADER_LEN];
+ int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
+ memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
+ int4store(buff + ST_CREATED_OFFSET,created);
+ return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
}
-#ifdef MYSQL_CLIENT
-void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
+/*****************************************************************************
+
+ Start_log_event::exec_event()
+
+ The master started
+
+ IMPLEMENTATION
+ - To handle the case where the master died without a stop event,
+ we clean up all temporary tables + locks that we got.
+
+ TODO
+ - Remove all active user locks
+ - If we have an active transaction at this point, the master died
+ in the middle while writing the transaction to the binary log.
+ In this case we should stop the slave.
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Start_log_event::exec_event(struct st_relay_log_info* rli)
{
- char llbuff[22];
- if (!short_form)
+ /* All temporary tables was deleted on the master */
+ close_temporary_tables(thd);
+ /*
+ If we have old format, load_tmpdir is cleaned up by the I/O thread
+ */
+ if (!rli->mi->old_format)
+ cleanup_load_tmpdir();
+ return Log_event::exec_event(rli);
+}
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Load_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Load_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Load_log_event::pack_info(Protocol *protocol)
+{
+ char *buf, *pos;
+ uint buf_len;
+
+ buf_len=
+ 5 + db_len + 3 + // "use DB; "
+ 18 + fname_len + 2 + // "LOAD DATA INFILE 'file''"
+ 9 + // " REPLACE or IGNORE "
+ 11 + table_name_len + // "INTO TABLE table"
+ 21 + sql_ex.field_term_len*4 + 2 + // " FIELDS TERMINATED BY 'str'"
+ 23 + sql_ex.enclosed_len*4 + 2 + // " OPTIONALLY ENCLOSED BY 'str'"
+ 12 + sql_ex.escaped_len*4 + 2 + // " ESCAPED BY 'str'"
+ 21 + sql_ex.line_term_len*4 + 2 + // " FIELDS TERMINATED BY 'str'"
+ 19 + sql_ex.line_start_len*4 + 2 + // " LINES STARTING BY 'str'"
+ 15 + 22 + // " IGNORE xxx LINES"
+ 3 + (num_fields-1)*2 + field_block_len; // " (field1, field2, ...)"
+
+ buf= my_malloc(buf_len, MYF(MY_WME));
+ if (!buf)
+ return;
+ pos= buf;
+ if (db && db_len)
{
- print_header(file);
- fprintf(file, "\tRand\n");
+ pos= strmov(pos, "use `");
+ memcpy(pos, db, db_len);
+ pos+= db_len;
+ pos= strmov(pos, "`; ");
}
- fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n",
- llstr(seed1, llbuff),llstr(seed2, llbuff));
- fflush(file);
+
+ pos= strmov(pos, "LOAD DATA INFILE '");
+ memcpy(pos, fname, fname_len);
+ pos+= fname_len;
+ pos= strmov(pos, "' ");
+
+ if (sql_ex.opt_flags && REPLACE_FLAG )
+ pos= strmov(pos, " REPLACE ");
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
+ pos= strmov(pos, " IGNORE ");
+
+ pos= strmov(pos ,"INTO TABLE ");
+ memcpy(pos, table_name, table_name_len);
+ pos+= table_name_len;
+
+ if (sql_ex.field_term_len)
+ {
+ pos= strmov(pos, " FIELDS TERMINATED BY ");
+ pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len);
+ }
+
+ if (sql_ex.enclosed_len)
+ {
+ if (sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
+ pos= strmov(pos, " OPTIONALLY ");
+ pos= strmov(pos, " ENCLOSED BY ");
+ pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len);
+ }
+
+ if (sql_ex.escaped_len)
+ {
+ pos= strmov(pos, " ESCAPED BY ");
+ pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len);
+ }
+
+ if (sql_ex.line_term_len)
+ {
+ pos= strmov(pos, " LINES TERMINATED BY ");
+ pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len);
+ }
+
+ if (sql_ex.line_start_len)
+ {
+ pos= strmov(pos, " LINES STARTING BY ");
+ pos= pretty_print_str(pos, sql_ex.line_start, sql_ex.line_start_len);
+ }
+
+ if ((int)skip_lines > 0)
+ {
+ pos= strmov(pos, " IGNORE ");
+ pos= longlong10_to_str((long) skip_lines, pos, 10);
+ pos= strmov(pos," LINES ");
+ }
+
+ if (num_fields)
+ {
+ uint i;
+ const char* field = fields;
+ pos= strmov(pos, " (");
+ for (i = 0; i < num_fields; i++)
+ {
+ if (i)
+ pos= strmov(pos, " ,");
+ memcpy(pos, field, field_lens[i]);
+ pos+= field_lens[i];
+ field += field_lens[i] + 1;
+ }
+ *pos++= ')';
+ }
+
+ protocol->store(buf, pos-buf);
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
}
#endif
+/*****************************************************************************
+
+ Load_log_event::write_data_header()
+
+ ****************************************************************************/
int Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
@@ -996,6 +1213,11 @@ int Load_log_event::write_data_header(IO_CACHE* file)
return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN);
}
+/*****************************************************************************
+
+ Load_log_event::write_data_body()
+
+ ****************************************************************************/
int Load_log_event::write_data_body(IO_CACHE* file)
{
if (sql_ex.write_data(file))
@@ -1011,110 +1233,21 @@ int Load_log_event::write_data_body(IO_CACHE* file)
my_b_safe_write(file, (byte*)fname, fname_len));
}
+/*****************************************************************************
+ Load_log_event::Load_log_event()
-static bool write_str(IO_CACHE *file, char *str, byte length)
-{
- return (my_b_safe_write(file, &length, 1) ||
- my_b_safe_write(file, (byte*) str, (int) length));
-}
-
-
-int sql_ex_info::write_data(IO_CACHE* file)
-{
- if (new_format())
- {
- return (write_str(file, field_term, field_term_len) ||
- write_str(file, enclosed, enclosed_len) ||
- write_str(file, line_term, line_term_len) ||
- write_str(file, line_start, line_start_len) ||
- write_str(file, escaped, escaped_len) ||
- my_b_safe_write(file,(byte*) &opt_flags,1));
- }
- else
- {
- old_sql_ex old_ex;
- old_ex.field_term= *field_term;
- old_ex.enclosed= *enclosed;
- old_ex.line_term= *line_term;
- old_ex.line_start= *line_start;
- old_ex.escaped= *escaped;
- old_ex.opt_flags= opt_flags;
- old_ex.empty_flags=empty_flags;
- return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex));
- }
-}
-
-
-static inline int read_str(char * &buf, char *buf_end, char * &str,
- uint8 &len)
-{
- if (buf + (uint) (uchar) *buf >= buf_end)
- return 1;
- len = (uint8) *buf;
- str= buf+1;
- buf+= (uint) len+1;
- return 0;
-}
-
-
-char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
-{
- cached_new_format = use_new_format;
- if (use_new_format)
- {
- empty_flags=0;
- /*
- The code below assumes that buf will not disappear from
- under our feet during the lifetime of the event. This assumption
- holds true in the slave thread if the log is in new format, but is not
- the case when we have old format because we will be reusing net buffer
- to read the actual file before we write out the Create_file event.
- */
- if (read_str(buf, buf_end, field_term, field_term_len) ||
- read_str(buf, buf_end, enclosed, enclosed_len) ||
- read_str(buf, buf_end, line_term, line_term_len) ||
- read_str(buf, buf_end, line_start, line_start_len) ||
- read_str(buf, buf_end, escaped, escaped_len))
- return 0;
- opt_flags = *buf++;
- }
- else
- {
- field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
- field_term = buf++; // Use first byte in string
- enclosed= buf++;
- line_term= buf++;
- line_start= buf++;
- escaped= buf++;
- opt_flags = *buf++;
- empty_flags= *buf++;
- if (empty_flags & FIELD_TERM_EMPTY)
- field_term_len=0;
- if (empty_flags & ENCLOSED_EMPTY)
- enclosed_len=0;
- if (empty_flags & LINE_TERM_EMPTY)
- line_term_len=0;
- if (empty_flags & LINE_START_EMPTY)
- line_start_len=0;
- if (empty_flags & ESCAPED_EMPTY)
- escaped_len=0;
- }
- return buf;
-}
-
-
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
-Load_log_event::Load_log_event(THD* thd_arg, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg,
+Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
+ const char *db_arg, const char *table_name_arg,
+ List<Item> &fields_arg,
enum enum_duplicates handle_dup,
bool using_trans)
- :Log_event(thd_arg, 0, using_trans),thread_id(thd_arg->thread_id),
- num_fields(0),fields(0),
- field_lens(0),field_block_len(0),
- table_name(table_name_arg ? table_name_arg : ""),
- db(db_arg), fname(ex->file_name)
+ :Log_event(thd_arg, 0, using_trans), thread_id(thd_arg->thread_id),
+ num_fields(0), fields(0), field_lens(0),field_block_len(0),
+ table_name(table_name_arg ? table_name_arg : ""),
+ db(db_arg), fname(ex->file_name)
{
time_t end_time;
time(&end_time);
@@ -1144,9 +1277,15 @@ Load_log_event::Load_log_event(THD* thd_arg, sql_exchange* ex,
sql_ex.empty_flags = 0;
switch (handle_dup) {
- case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
- case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
- case DUP_ERROR: break;
+ case DUP_IGNORE:
+ sql_ex.opt_flags |= IGNORE_FLAG;
+ break;
+ case DUP_REPLACE:
+ sql_ex.opt_flags |= REPLACE_FLAG;
+ break;
+ case DUP_UPDATE: // Impossible here
+ case DUP_ERROR:
+ break;
}
if (!ex->field_term->length())
@@ -1178,25 +1317,32 @@ Load_log_event::Load_log_event(THD* thd_arg, sql_exchange* ex,
field_lens = (const uchar*)field_lens_buf.ptr();
fields = fields_buf.ptr();
}
+#endif // !MYSQL_CLIENT
-#endif
+/*****************************************************************************
+
+ Load_log_event::Load_log_event()
-/*
The caller must do buf[event_len] = 0 before he starts using the
constructed event.
-*/
-Load_log_event::Load_log_event(const char* buf, int event_len,
+ ****************************************************************************/
+Load_log_event::Load_log_event(const char *buf, int event_len,
bool old_format)
:Log_event(buf, old_format),num_fields(0),fields(0),
- field_lens(0),field_block_len(0),
- table_name(0),db(0),fname(0)
+ field_lens(0),field_block_len(0),
+ table_name(0),db(0),fname(0)
{
if (!event_len) // derived class, will call copy_log_event() itself
return;
copy_log_event(buf, event_len, old_format);
}
+/*****************************************************************************
+
+ Load_log_event::copy_log_event()
+
+ ****************************************************************************/
int Load_log_event::copy_log_event(const char *buf, ulong event_len,
bool old_format)
{
@@ -1241,8 +1387,12 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
return 0;
}
-#ifdef MYSQL_CLIENT
+/*****************************************************************************
+
+ Load_log_event::print()
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
void Load_log_event::print(FILE* file, bool short_form, char* last_db)
{
if (!short_form)
@@ -1262,7 +1412,10 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
if (db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
- fprintf(file, "LOAD DATA INFILE '%-*s' ", fname_len, fname);
+ fprintf(file, "LOAD ");
+ if (check_fname_outside_temp_buf())
+ fprintf(file, "LOCAL ");
+ fprintf(file, "DATA INFILE '%-*s' ", fname_len, fname);
if (sql_ex.opt_flags && REPLACE_FLAG )
fprintf(file," REPLACE ");
@@ -1323,33 +1476,794 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, ";\n");
}
-
#endif /* #ifdef MYSQL_CLIENT */
-#ifndef MYSQL_CLIENT
-
-void Log_event::set_log_pos(MYSQL_LOG* log)
-{
- if (!log_pos)
- log_pos = my_b_tell(&log->log_file);
-}
+/*****************************************************************************
+ Load_log_event::set_fields()
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
void Load_log_event::set_fields(List<Item> &field_list)
{
uint i;
- const char *field= fields;
+ const char* field = fields;
for (i= 0; i < num_fields; i++)
{
field_list.push_back(new Item_field(db, table_name, field));
field+= field_lens[i] + 1;
}
}
+#endif // !MYSQL_CLIENT
+
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+/*
+ Does the data loading job when executing a LOAD DATA on the slave
+
+ SYNOPSIS
+ Load_log_event::exec_event
+ net
+ rli
+ use_rli_only_for_errors - if set to 1, rli is provided to
+ Load_log_event::exec_event only for this
+ function to have RPL_LOG_NAME and
+ rli->last_slave_error, both being used by
+ error reports. rli's position advancing
+ is skipped (done by the caller which is
+ Execute_load_log_event::exec_event).
+ - if set to 0, rli is provided for full use,
+ i.e. for error reports and position
+ advancing.
+
+ DESCRIPTION
+ Does the data loading job when executing a LOAD DATA on the slave
+
+ RETURN VALUE
+ 0 Success
+ 1 Failure
+*/
+
+int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
+ bool use_rli_only_for_errors)
+{
+ init_sql_alloc(&thd->mem_root, 8192,0);
+ thd->db = rewrite_db((char*)db);
+ DBUG_ASSERT(thd->query == 0);
+ thd->query = 0; // Should not be needed
+ thd->query_error = 0;
+
+ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ {
+ thd->set_time((time_t)when);
+ thd->current_tablenr = 0;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query_id = query_id++;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+
+ TABLE_LIST tables;
+ bzero((char*) &tables,sizeof(tables));
+ tables.db = thd->db;
+ tables.alias = tables.real_name = (char*)table_name;
+ tables.lock_type = TL_WRITE;
+ // the table will be opened in mysql_load
+ if (table_rules_on && !tables_ok(thd, &tables))
+ {
+ // TODO: this is a bug - this needs to be moved to the I/O thread
+ if (net)
+ skip_load_data_infile(net);
+ }
+ else
+ {
+ char llbuff[22];
+ enum enum_duplicates handle_dup = DUP_IGNORE;
+ if (sql_ex.opt_flags && REPLACE_FLAG)
+ handle_dup = DUP_REPLACE;
+ sql_exchange ex((char*)fname, sql_ex.opt_flags &&
+ DUMPFILE_FLAG );
+ String field_term(sql_ex.field_term,sql_ex.field_term_len,log_cs);
+ String enclosed(sql_ex.enclosed,sql_ex.enclosed_len,log_cs);
+ String line_term(sql_ex.line_term,sql_ex.line_term_len,log_cs);
+ String line_start(sql_ex.line_start,sql_ex.line_start_len,log_cs);
+ String escaped(sql_ex.escaped,sql_ex.escaped_len, log_cs);
+
+ ex.opt_enclosed = (sql_ex.opt_flags & OPT_ENCLOSED_FLAG);
+ if (sql_ex.empty_flags & FIELD_TERM_EMPTY)
+ ex.field_term->length(0);
+
+ ex.skip_lines = skip_lines;
+ List<Item> field_list;
+ set_fields(field_list);
+ thd->variables.pseudo_thread_id= thd->thread_id;
+ if (net)
+ {
+ // mysql_load will use thd->net to read the file
+ thd->net.vio = net->vio;
+ /*
+ Make sure the client does not get confused about the packet sequence
+ */
+ thd->net.pkt_nr = net->pkt_nr;
+ }
+ if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0,
+ TL_WRITE))
+ thd->query_error = 1;
+ if (thd->cuted_fields)
+ {
+ /*
+ log_pos is the position of the LOAD
+ event in the master log
+ */
+ sql_print_error("Slave: load data infile at position %s in log \
+'%s' produced %d warning(s)", llstr(log_pos,llbuff), RPL_LOG_NAME,
+ thd->cuted_fields );
+ }
+ if (net)
+ net->pkt_nr= thd->net.pkt_nr;
+ }
+ }
+ else
+ {
+ /*
+ We will just ask the master to send us /dev/null if we do not
+ want to load the data.
+ TODO: this a bug - needs to be done in I/O thread
+ */
+ if (net)
+ skip_load_data_infile(net);
+ }
+
+ thd->net.vio = 0;
+ thd->db= 0; // prevent db from being freed
+ close_thread_tables(thd);
+ if (thd->query_error)
+ {
+ int sql_error = thd->net.last_errno;
+ if (!sql_error)
+ sql_error = ER_UNKNOWN_ERROR;
+
+ slave_print_error(rli,sql_error,
+ "Slave: Error '%s' running load data infile ",
+ ER_SAFE(sql_error));
+ free_root(&thd->mem_root,0);
+ return 1;
+ }
+ free_root(&thd->mem_root,0);
+
+ if (thd->is_fatal_error)
+ {
+ sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
+ return 1;
+ }
+
+ return ( use_rli_only_for_errors ? 0 : Log_event::exec_event(rli) );
+}
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Rotate_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Rotate_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Rotate_log_event::pack_info(Protocol *protocol)
+{
+ char *buf, *b_pos;
+ if (!(buf= my_malloc(ident_len + 45, MYF(MY_WME))))
+ return;
+ b_pos= buf;
+ memcpy(buf, new_log_ident, ident_len);
+ b_pos+= ident_len;
+ b_pos= strmov(b_pos, ";pos=");
+ b_pos=longlong10_to_str(pos, b_pos, 10);
+ if (flags & LOG_EVENT_FORCED_ROTATE_F)
+ b_pos= strmov(b_pos ,"; forced by master");
+ protocol->store(buf, b_pos-buf);
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
+}
+#endif
+
+/*****************************************************************************
+
+ Rotate_log_event::print()
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
+void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ char buf[22];
+ if (short_form)
+ return;
+
+ print_header(file);
+ fprintf(file, "\tRotate to ");
+ if (new_log_ident)
+ my_fwrite(file, (byte*) new_log_ident, (uint)ident_len,
+ MYF(MY_NABP | MY_WME));
+ fprintf(file, " pos: %s", llstr(pos, buf));
+ if (flags & LOG_EVENT_FORCED_ROTATE_F)
+ fprintf(file," forced by master");
+ fputc('\n', file);
+ fflush(file);
+}
+#endif // MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Rotate_log_event::Rotate_log_event()
+
+ ****************************************************************************/
+Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
+ bool old_format)
+ :Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
+{
+ // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
+ int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ uint ident_offset;
+ if (event_len < header_size)
+ return;
+ buf += header_size;
+ if (old_format)
+ {
+ ident_len = (uint)(event_len - OLD_HEADER_LEN);
+ pos = 4;
+ ident_offset = 0;
+ }
+ else
+ {
+ ident_len = (uint)(event_len - ROTATE_EVENT_OVERHEAD);
+ pos = uint8korr(buf + R_POS_OFFSET);
+ ident_offset = ROTATE_HEADER_LEN;
+ }
+ set_if_smaller(ident_len,FN_REFLEN-1);
+ if (!(new_log_ident= my_strdup_with_length((byte*) buf +
+ ident_offset,
+ (uint) ident_len,
+ MYF(MY_WME))))
+ return;
+ alloced = 1;
+}
+
+/*****************************************************************************
+
+ Rotate_log_event::write_data()
+
+ ****************************************************************************/
+int Rotate_log_event::write_data(IO_CACHE* file)
+{
+ char buf[ROTATE_HEADER_LEN];
+ int8store(buf, pos + R_POS_OFFSET);
+ return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
+ my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
+}
+
+/*****************************************************************************
+
+ Rotate_log_event::exec_event()
+
+ Got a rotate log even from the master
+
+ IMPLEMENTATION
+ This is mainly used so that we can later figure out the logname and
+ position for the master.
+
+ We can't rotate the slave as this will cause infinitive rotations
+ in a A -> B -> A setup.
+
+ RETURN VALUES
+ 0 ok
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char* log_name = rli->master_log_name;
+ DBUG_ENTER("Rotate_log_event::exec_event");
+
+ pthread_mutex_lock(&rli->data_lock);
+ memcpy(log_name, new_log_ident, ident_len+1);
+ rli->master_log_pos = pos;
+ rli->relay_log_pos += get_event_len();
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) rli->master_log_pos));
+ pthread_mutex_unlock(&rli->data_lock);
+ pthread_cond_broadcast(&rli->data_cond);
+ flush_relay_log_info(rli);
+ DBUG_RETURN(0);
+}
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Intvar_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Intvar_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Intvar_log_event::pack_info(Protocol *protocol)
+{
+ char buf[64], *pos;
+ pos= strmov(buf, get_var_type_name());
+ *(pos++)='=';
+ pos= longlong10_to_str(val, pos, -10);
+ protocol->store(buf, pos-buf);
+}
+#endif
+
+/*****************************************************************************
+
+ Intvar_log_event::Intvar_log_event()
+
+ ****************************************************************************/
+Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
+ :Log_event(buf, old_format)
+{
+ buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ type = buf[I_TYPE_OFFSET];
+ val = uint8korr(buf+I_VAL_OFFSET);
+}
+
+/*****************************************************************************
+
+ Intvar_log_event::get_var_type_name()
+
+ ****************************************************************************/
+const char* Intvar_log_event::get_var_type_name()
+{
+ switch(type) {
+ case LAST_INSERT_ID_EVENT: return "LAST_INSERT_ID";
+ case INSERT_ID_EVENT: return "INSERT_ID";
+ default: /* impossible */ return "UNKNOWN";
+ }
+}
+
+/*****************************************************************************
+
+ Intvar_log_event::write_data()
+
+ ****************************************************************************/
+int Intvar_log_event::write_data(IO_CACHE* file)
+{
+ char buf[9];
+ buf[I_TYPE_OFFSET] = type;
+ int8store(buf + I_VAL_OFFSET, val);
+ return my_b_safe_write(file, (byte*) buf, sizeof(buf));
+}
+
+/*****************************************************************************
+
+ Intvar_log_event::print()
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
+void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ char llbuff[22];
+ const char *msg;
+ LINT_INIT(msg);
+
+ if (!short_form)
+ {
+ print_header(file);
+ fprintf(file, "\tIntvar\n");
+ }
+
+ fprintf(file, "SET ");
+ switch (type) {
+ case LAST_INSERT_ID_EVENT:
+ msg="LAST_INSERT_ID";
+ break;
+ case INSERT_ID_EVENT:
+ msg="INSERT_ID";
+ break;
+ }
+ fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff));
+ fflush(file);
+}
+#endif // MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Intvar_log_event::exec_event()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
+int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ switch (type) {
+ case LAST_INSERT_ID_EVENT:
+ thd->last_insert_id_used = 1;
+ thd->last_insert_id = val;
+ break;
+ case INSERT_ID_EVENT:
+ thd->next_insert_id = val;
+ break;
+ }
+ rli->inc_pending(get_event_len());
+ return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Rand_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+ Rand_log_event::pack_info()
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Rand_log_event::pack_info(Protocol *protocol)
+{
+ char buf1[256], *pos;
+ pos= strmov(buf1,"rand_seed1=");
+ pos= int10_to_str((long) seed1, pos, 10);
+ pos= strmov(pos, ",rand_seed2=");
+ pos= int10_to_str((long) seed2, pos, 10);
+ protocol->store(buf1, (uint) (pos-buf1));
+}
+#endif
+
+/*****************************************************************************
+
+ Rand_log_event::Rand_log_event()
+
+ ****************************************************************************/
+Rand_log_event::Rand_log_event(const char* buf, bool old_format)
+ :Log_event(buf, old_format)
+{
+ buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ seed1 = uint8korr(buf+RAND_SEED1_OFFSET);
+ seed2 = uint8korr(buf+RAND_SEED2_OFFSET);
+}
+
+/*****************************************************************************
+
+ Rand_log_event::write_data()
+
+ ****************************************************************************/
+int Rand_log_event::write_data(IO_CACHE* file)
+{
+ char buf[16];
+ int8store(buf + RAND_SEED1_OFFSET, seed1);
+ int8store(buf + RAND_SEED2_OFFSET, seed2);
+ return my_b_safe_write(file, (byte*) buf, sizeof(buf));
+}
+
+/*****************************************************************************
+
+ Rand_log_event::print()
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
+void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ char llbuff[22];
+ if (!short_form)
+ {
+ print_header(file);
+ fprintf(file, "\tRand\n");
+ }
+ fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n",
+ llstr(seed1, llbuff),llstr(seed2, llbuff));
+ fflush(file);
+}
+#endif // MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Rand_log_event::exec_event()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Rand_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ thd->rand.seed1= (ulong) seed1;
+ thd->rand.seed2= (ulong) seed2;
+ rli->inc_pending(get_event_len());
+ return 0;
+}
+#endif // !MYSQL_CLIENT
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ User_var_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ User_var_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void User_var_log_event::pack_info(Protocol* protocol)
+{
+ char *buf= 0;
+ uint val_offset= 2 + name_len;
+ uint event_len= val_offset;
+
+ if (is_null)
+ {
+ buf= my_malloc(val_offset + 5, MYF(MY_WME));
+ strmov(buf + val_offset, "NULL");
+ event_len= val_offset + 4;
+ }
+ else
+ {
+ switch (type) {
+ case REAL_RESULT:
+ double real_val;
+ float8get(real_val, val);
+ buf= my_malloc(val_offset + FLOATING_POINT_BUFFER, MYF(MY_WME));
+ event_len += my_sprintf(buf + val_offset,
+ (buf + val_offset, "%.14g", real_val));
+ break;
+ case INT_RESULT:
+ buf= my_malloc(val_offset + 22, MYF(MY_WME));
+ event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf;
+ break;
+ case STRING_RESULT:
+ /*
+ This is correct as pack_info is used for SHOW BINLOG command
+ only. But be carefull this is may be incorrect in other cases as
+ string may contain \ and '.
+ */
+ buf= my_malloc(val_offset + 2 + val_len, MYF(MY_WME));
+ buf[val_offset]= '\'';
+ memcpy(buf + val_offset + 1, val, val_len);
+ buf[val_offset + val_len]= '\'';
+ event_len= val_offset + 1 + val_len;
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(1);
+ return;
+ }
+ }
+ buf[0]= '@';
+ buf[1+name_len]= '=';
+ memcpy(buf+1, name, name_len);
+ protocol->store(buf, event_len);
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
+}
+#endif // !MYSQL_CLIENT
+/*****************************************************************************
+
+ User_var_log_event::User_var_log_event()
+
+ ****************************************************************************/
+User_var_log_event::User_var_log_event(const char* buf, bool old_format)
+ :Log_event(buf, old_format)
+{
+ buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ name_len= uint4korr(buf);
+ name= (char *) buf + UV_NAME_LEN_SIZE;
+ is_null= buf[UV_NAME_LEN_SIZE + name_len];
+ if (is_null)
+ {
+ type= STRING_RESULT;
+ val_len= 0;
+ val= 0;
+ }
+ else
+ {
+ type= (Item_result) buf[UV_VAL_IS_NULL + UV_NAME_LEN_SIZE + name_len];
+ charset_number= uint4korr(buf + UV_NAME_LEN_SIZE + name_len +
+ UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
+ val_len= uint4korr(buf + UV_NAME_LEN_SIZE + name_len +
+ UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
+ UV_CHARSET_NUMBER_SIZE);
+ val= (char *) buf + UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL +
+ UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE;
+ }
+}
+
+/*****************************************************************************
+
+ User_var_log_event::write_data()
+
+ ****************************************************************************/
+int User_var_log_event::write_data(IO_CACHE* file)
+{
+ char buf[UV_NAME_LEN_SIZE];
+ char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
+ UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE];
+ char buf2[8];
+ char *pos= buf2;
+ int4store(buf, name_len);
+ buf1[0]= is_null;
+ if (!is_null)
+ {
+ buf1[1]= type;
+ int4store(buf1 + 2, charset_number);
+ int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
+
+ switch (type) {
+ case REAL_RESULT:
+ float8store(buf2, *(double*) val);
+ break;
+ case INT_RESULT:
+ int8store(buf2, *(longlong*) val);
+ break;
+ case STRING_RESULT:
+ pos= val;
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(1);
+ return 0;
+ }
+ return (my_b_safe_write(file, (byte*) buf, sizeof(buf)) ||
+ my_b_safe_write(file, (byte*) name, name_len) ||
+ my_b_safe_write(file, (byte*) buf1, sizeof(buf1)) ||
+ my_b_safe_write(file, (byte*) pos, val_len));
+ }
+
+ return (my_b_safe_write(file, (byte*) buf, sizeof(buf)) ||
+ my_b_safe_write(file, (byte*) name, name_len) ||
+ my_b_safe_write(file, (byte*) buf1, 1));
+}
+
+/*****************************************************************************
+
+ User_var_log_event::print()
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
+void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ if (!short_form)
+ {
+ print_header(file);
+ fprintf(file, "\tUser_var\n");
+ }
+
+ fprintf(file, "SET @");
+ my_fwrite(file, (byte*) name, (uint) (name_len), MYF(MY_NABP | MY_WME));
+
+ if (is_null)
+ {
+ fprintf(file, ":=NULL;\n");
+ }
+ else
+ {
+ switch (type) {
+ case REAL_RESULT:
+ double real_val;
+ float8get(real_val, val);
+ fprintf(file, ":=%.14g;\n", real_val);
+ break;
+ case INT_RESULT:
+ char int_buf[22];
+ longlong10_to_str(uint8korr(val), int_buf, -10);
+ fprintf(file, ":=%s;\n", int_buf);
+ break;
+ case STRING_RESULT:
+ fprintf(file, ":='%s';\n", val);
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(1);
+ return;
+ }
+ }
+ fflush(file);
+}
+#endif
+
+/*****************************************************************************
+
+ User_var_log_event::exec_event()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int User_var_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ Item *it= 0;
+ CHARSET_INFO *charset= log_cs;
+ LEX_STRING user_var_name;
+ user_var_name.str= name;
+ user_var_name.length= name_len;
+
+ if (type != ROW_RESULT)
+ init_sql_alloc(&thd->mem_root, 8192,0);
+
+ if (is_null)
+ {
+ it= new Item_null();
+ }
+ else
+ {
+ switch (type) {
+ case REAL_RESULT:
+ double real_val;
+ float8get(real_val, val);
+ it= new Item_real(real_val);
+ break;
+ case INT_RESULT:
+ it= new Item_int((longlong) uint8korr(val));
+ break;
+ case STRING_RESULT:
+ it= new Item_string(val, val_len, charset);
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(1);
+ return 0;
+ }
+ charset= get_charset(charset_number, MYF(0));
+ }
+ Item_func_set_user_var e(user_var_name, it);
+ e.fix_fields(thd, 0, 0);
+ e.update_hash(val, val_len, type, charset);
+ free_root(&thd->mem_root,0);
+
+ rli->inc_pending(get_event_len());
+ return 0;
+}
+#endif // !MYSQL_CLIENT
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Slave_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Slave_log_event::pack_info()
+
+ ****************************************************************************/
+#ifdef HAVE_REPLICATION
+
+#ifndef MYSQL_CLIENT
+void Slave_log_event::pack_info(Protocol *protocol)
+{
+ char buf[256], *pos;
+ pos= strmov(buf, "host=");
+ pos= strnmov(pos, master_host, HOSTNAME_LENGTH);
+ pos= strmov(pos, ",port=");
+ pos= int10_to_str((long) master_port, pos, 10);
+ pos= strmov(pos, ",log=");
+ pos= strmov(pos, master_log);
+ pos= strmov(pos, ",pos=");
+ pos= longlong10_to_str(master_pos, pos, 10);
+ protocol->store(buf, pos-buf);
+}
+#endif // !MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Slave_log_event::Slave_log_event()
+
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
Slave_log_event::Slave_log_event(THD* thd_arg,
- struct st_relay_log_info* rli):
- Log_event(thd_arg,0,0),mem_pool(0),master_host(0)
+ struct st_relay_log_info* rli)
+ :Log_event(thd_arg, 0, 0), mem_pool(0), master_host(0)
{
DBUG_ENTER("Slave_log_event");
if (!rli->inited) // QQ When can this happen ?
@@ -1380,17 +2294,24 @@ Slave_log_event::Slave_log_event(THD* thd_arg,
pthread_mutex_unlock(&mi->data_lock);
DBUG_VOID_RETURN;
}
+#endif // !MYSQL_CLIENT
-#endif /* ! MYSQL_CLIENT */
+/*****************************************************************************
+ Slave_log_event dtor
+ ****************************************************************************/
Slave_log_event::~Slave_log_event()
{
my_free(mem_pool, MYF(MY_ALLOW_ZERO_PTR));
}
-#ifdef MYSQL_CLIENT
+/*****************************************************************************
+ Slave_log_event::print()
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
@@ -1402,14 +2323,23 @@ void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
master_log: '%s' master_pos: %s\n",
master_host, master_port, master_log, llstr(master_pos, llbuff));
}
+#endif // MYSQL_CLIENT
-#endif /* MYSQL_CLIENT */
+/*****************************************************************************
+ Slave_log_event::get_data_size()
+
+ ****************************************************************************/
int Slave_log_event::get_data_size()
{
return master_host_len + master_log_len + 1 + SL_MASTER_HOST_OFFSET;
}
+/*****************************************************************************
+
+ Slave_log_event::write_data()
+
+ ****************************************************************************/
int Slave_log_event::write_data(IO_CACHE* file)
{
int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos);
@@ -1418,7 +2348,11 @@ int Slave_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, (byte*)mem_pool, get_data_size());
}
+/*****************************************************************************
+
+ Slave_log_event::init_from_mem_pool()
+ ****************************************************************************/
void Slave_log_event::init_from_mem_pool(int data_size)
{
master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET);
@@ -1435,6 +2369,11 @@ void Slave_log_event::init_from_mem_pool(int data_size)
master_log_len = strlen(master_log);
}
+/*****************************************************************************
+
+ Slave_log_event::Slave_log_event()
+
+ ****************************************************************************/
Slave_log_event::Slave_log_event(const char* buf, int event_len)
:Log_event(buf,0),mem_pool(0),master_host(0)
{
@@ -1448,6 +2387,94 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len)
init_from_mem_pool(event_len);
}
+/*****************************************************************************
+
+ Slave_log_event::exec_event()
+
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
+int Slave_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ return Log_event::exec_event(rli);
+}
+#endif // !MYSQL_CLIENT
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Stop_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Stop_log_event::print()
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
+void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ if (short_form)
+ return;
+
+ print_header(file);
+ fprintf(file, "\tStop\n");
+ fflush(file);
+}
+#endif // MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Stop_log_event::exec_event()
+
+ The master stopped. Clean up all temporary tables + locks that the
+ master may have set.
+
+ TODO
+ - Remove all active user locks
+
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
+int Stop_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ // do not clean up immediately after rotate event
+ if (rli->master_log_pos > BIN_LOG_HEADER_SIZE)
+ {
+ close_temporary_tables(thd);
+ cleanup_load_tmpdir();
+ }
+ /*
+ We do not want to update master_log pos because we get a rotate event
+ before stop, so by now master_log_name is set to the next log.
+ If we updated it, we will have incorrect master coordinates and this
+ could give false triggers in MASTER_POS_WAIT() that we have reached
+ the target position when in fact we have not.
+ */
+ rli->inc_pos(get_event_len(), 0);
+ flush_relay_log_info(rli);
+ return 0;
+}
+#endif // !MYSQL_CLIENT
+#endif /* HAVE_REPLICATION */
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Create_file_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Create_file_log_event ctor
+
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
Create_file_log_event::
Create_file_log_event(THD* thd_arg, sql_exchange* ex,
@@ -1461,8 +2488,13 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex,
{
sql_ex.force_new_format();
}
-#endif
+#endif // !MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Create_file_log_event::write_data_body()
+ ****************************************************************************/
int Create_file_log_event::write_data_body(IO_CACHE* file)
{
int res;
@@ -1472,6 +2504,11 @@ int Create_file_log_event::write_data_body(IO_CACHE* file)
my_b_safe_write(file, (byte*) block, block_len));
}
+/*****************************************************************************
+
+ Create_file_log_event::write_data_header()
+
+ ****************************************************************************/
int Create_file_log_event::write_data_header(IO_CACHE* file)
{
int res;
@@ -1482,6 +2519,11 @@ int Create_file_log_event::write_data_header(IO_CACHE* file)
return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN);
}
+/*****************************************************************************
+
+ Create_file_log_event::write_base()
+
+ ****************************************************************************/
int Create_file_log_event::write_base(IO_CACHE* file)
{
int res;
@@ -1491,6 +2533,11 @@ int Create_file_log_event::write_base(IO_CACHE* file)
return res;
}
+/*****************************************************************************
+
+ Create_file_log_event ctor
+
+ ****************************************************************************/
Create_file_log_event::Create_file_log_event(const char* buf, int len,
bool old_format)
:Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
@@ -1517,38 +2564,141 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
}
}
+/*****************************************************************************
+
+ Create_file_log_event::print()
+ ****************************************************************************/
#ifdef MYSQL_CLIENT
-void Create_file_log_event::print(FILE* file, bool short_form,
- char* last_db)
+void Create_file_log_event::print(FILE* file, bool short_form,
+ char* last_db, bool enable_local)
{
if (short_form)
+ {
+ if (enable_local && check_fname_outside_temp_buf())
+ Load_log_event::print(file, 1, last_db);
return;
- Load_log_event::print(file, 1, last_db);
+ }
+
+ if (enable_local)
+ {
+ if (!check_fname_outside_temp_buf())
+ fprintf(file, "#");
+ Load_log_event::print(file, 1, last_db);
+ fprintf(file, "#");
+ }
+
fprintf(file, " file_id: %d block_len: %d\n", file_id, block_len);
}
+
+void Create_file_log_event::print(FILE* file, bool short_form,
+ char* last_db)
+{
+ print(file,short_form,last_db,0);
+}
+#endif // MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Create_file_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Create_file_log_event::pack_info(Protocol *protocol)
+{
+ char buf[NAME_LEN*2 + 30 + 21*2], *pos;
+ pos= strmov(buf, "db=");
+ memcpy(pos, db, db_len);
+ pos+= db_len;
+ pos= strmov(pos, ";table=");
+ memcpy(pos, table_name, table_name_len);
+ pos+= table_name_len;
+ pos= strmov(pos, ";file_id=");
+ pos= int10_to_str((long) file_id, pos, 10);
+ pos= strmov(pos, ";block_len=");
+ pos= int10_to_str((long) block_len, pos, 10);
+ protocol->store(buf, pos-buf);
+}
#endif
-#ifndef MYSQL_CLIENT
-void Create_file_log_event::pack_info(String* packet)
-{
- char buf1[256],buf[22], *end;
- String tmp(buf1, sizeof(buf1));
- tmp.length(0);
- tmp.append("db=");
- tmp.append(db, db_len);
- tmp.append(";table=");
- tmp.append(table_name, table_name_len);
- tmp.append(";file_id=");
- end= int10_to_str((long) file_id, buf, 10);
- tmp.append(buf, (uint32) (end-buf));
- tmp.append(";block_len=");
- end= int10_to_str((long) block_len, buf, 10);
- tmp.append(buf, (uint32) (end-buf));
- net_store_data(packet, (char*) tmp.ptr(), tmp.length());
+/*****************************************************************************
+
+ Create_file_log_event::exec_event()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname_buf[FN_REFLEN+10];
+ char *p;
+ int fd = -1;
+ IO_CACHE file;
+ int error = 1;
+
+ bzero((char*)&file, sizeof(file));
+ p = slave_load_file_stem(fname_buf, file_id, server_id);
+ strmov(p, ".info"); // strmov takes less code than memcpy
+ if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
+ MYF(MY_WME))) < 0 ||
+ init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
+ MYF(MY_WME|MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname_buf);
+ goto err;
+ }
+
+ // a trick to avoid allocating another buffer
+ strmov(p, ".data");
+ fname = fname_buf;
+ fname_len = (uint)(p-fname) + 5;
+ if (write_base(&file))
+ {
+ strmov(p, ".info"); // to have it right in the error message
+ slave_print_error(rli,my_errno, "Could not write to file '%s'", fname_buf);
+ goto err;
+ }
+ end_io_cache(&file);
+ my_close(fd, MYF(0));
+
+ // fname_buf now already has .data, not .info, because we did our trick
+ if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
+ MYF(MY_WME))) < 0)
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname_buf);
+ goto err;
+ }
+ if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Write to '%s' failed", fname_buf);
+ goto err;
+ }
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ error=0; // Everything is ok
+
+err:
+ if (error)
+ end_io_cache(&file);
+ if (fd >= 0)
+ my_close(fd, MYF(0));
+ return error ? 1 : Log_event::exec_event(rli);
}
-#endif
+#endif
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Append_block_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Append_block_log_event ctor
+
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
uint block_len_arg,
@@ -1557,8 +2707,13 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
block_len(block_len_arg), file_id(thd_arg->file_id)
{
}
-#endif
-
+#endif // !MYSQL_CLIENT
+
+/*****************************************************************************
+
+ Append_block_log_event ctor
+
+ ****************************************************************************/
Append_block_log_event::Append_block_log_event(const char* buf, int len)
:Log_event(buf, 0),block(0)
{
@@ -1569,6 +2724,11 @@ Append_block_log_event::Append_block_log_event(const char* buf, int len)
block_len = len - APPEND_BLOCK_EVENT_OVERHEAD;
}
+/*****************************************************************************
+
+ Append_block_log_event::write_data()
+
+ ****************************************************************************/
int Append_block_log_event::write_data(IO_CACHE* file)
{
byte buf[APPEND_BLOCK_HEADER_LEN];
@@ -1577,6 +2737,11 @@ int Append_block_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*) block, block_len));
}
+/*****************************************************************************
+
+ Append_block_log_event::print()
+
+ ****************************************************************************/
#ifdef MYSQL_CLIENT
void Append_block_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -1588,23 +2753,86 @@ void Append_block_log_event::print(FILE* file, bool short_form,
fprintf(file, "#Append_block: file_id: %d block_len: %d\n",
file_id, block_len);
}
-#endif
+#endif // MYSQL_CLIENT
-#ifndef MYSQL_CLIENT
-void Append_block_log_event::pack_info(String* packet)
+/*****************************************************************************
+
+ Append_block_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Append_block_log_event::pack_info(Protocol *protocol)
{
- char buf1[256];
- sprintf(buf1, ";file_id=%u;block_len=%u", file_id, block_len);
- net_store_data(packet, buf1);
+ char buf[256];
+ uint length;
+ length= (uint) my_sprintf(buf,
+ (buf, ";file_id=%u;block_len=%u", file_id,
+ block_len));
+ protocol->store(buf, (int32) length);
}
+#endif
-Delete_file_log_event::Delete_file_log_event(THD* thd_arg, bool using_trans)
- :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
+/*****************************************************************************
+
+ Append_block_log_event::exec_event()
+
+ ****************************************************************************/
+#if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname[FN_REFLEN+10];
+ char *p= slave_load_file_stem(fname, file_id, server_id);
+ int fd;
+ int error = 1;
+
+ memcpy(p, ".data", 6);
+ if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0)
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname);
+ goto err;
+ }
+ if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Write to '%s' failed", fname);
+ goto err;
+ }
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ error=0;
+
+err:
+ if (fd >= 0)
+ my_close(fd, MYF(0));
+ return error ? error : Log_event::exec_event(rli);
+}
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ Delete_file_log_event methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Delete_file_log_event ctor
+
+ ****************************************************************************/
+#ifndef MYSQL_CLIENT
+Delete_file_log_event::Delete_file_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans),file_id(thd_arg->file_id)
{
}
-#endif
+#endif // !MYSQL_CLIENT
+
+/*****************************************************************************
+ Delete_file_log_event ctor
+ ****************************************************************************/
Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
:Log_event(buf, 0),file_id(0)
{
@@ -1613,7 +2841,11 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
}
+/*****************************************************************************
+
+ Delete_file_log_event::write_data()
+ ****************************************************************************/
int Delete_file_log_event::write_data(IO_CACHE* file)
{
byte buf[DELETE_FILE_HEADER_LEN];
@@ -1621,6 +2853,11 @@ int Delete_file_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, buf, DELETE_FILE_HEADER_LEN);
}
+/*****************************************************************************
+
+ Delete_file_log_event::print()
+
+ ****************************************************************************/
#ifdef MYSQL_CLIENT
void Delete_file_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -1631,25 +2868,69 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
fputc('\n', file);
fprintf(file, "#Delete_file: file_id=%u\n", file_id);
}
-#endif
+#endif // MYSQL_CLIENT
-#ifndef MYSQL_CLIENT
-void Delete_file_log_event::pack_info(String* packet)
+/*****************************************************************************
+
+ Delete_file_log_event::pack_info()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Delete_file_log_event::pack_info(Protocol *protocol)
{
- char buf1[64];
- sprintf(buf1, ";file_id=%u", (uint) file_id);
- net_store_data(packet, buf1);
+ char buf[64];
+ uint length;
+ length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id));
+ protocol->store(buf, (int32) length);
}
-#endif
+#endif
+
+/*****************************************************************************
+
+ Delete_file_log_event::exec_event()
+
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname[FN_REFLEN+10];
+ char *p= slave_load_file_stem(fname, file_id, server_id);
+ memcpy(p, ".data", 6);
+ (void) my_delete(fname, MYF(MY_WME));
+ memcpy(p, ".info", 6);
+ (void) my_delete(fname, MYF(MY_WME));
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ return Log_event::exec_event(rli);
+}
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+ Execute_load_log_event methods
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ Execute_load_log_event ctor
+
+ ****************************************************************************/
#ifndef MYSQL_CLIENT
-Execute_load_log_event::Execute_load_log_event(THD* thd_arg, bool using_trans)
+Execute_load_log_event::Execute_load_log_event(THD *thd_arg, bool using_trans)
:Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
{
}
-#endif
+#endif // !MYSQL_CLIENT
+/*****************************************************************************
+
+ Execute_load_log_event ctor
+
+ ****************************************************************************/
Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
:Log_event(buf, 0), file_id(0)
{
@@ -1658,6 +2939,11 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
}
+/*****************************************************************************
+
+ Execute_load_log_event::write_data()
+
+ ****************************************************************************/
int Execute_load_log_event::write_data(IO_CACHE* file)
{
byte buf[EXEC_LOAD_HEADER_LEN];
@@ -1665,6 +2951,11 @@ int Execute_load_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, buf, EXEC_LOAD_HEADER_LEN);
}
+/*****************************************************************************
+
+ Execute_load_log_event::print()
+
+ ****************************************************************************/
#ifdef MYSQL_CLIENT
void Execute_load_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -1676,474 +2967,27 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
fprintf(file, "#Exec_load: file_id=%d\n",
file_id);
}
-#endif
-#ifndef MYSQL_CLIENT
-void Execute_load_log_event::pack_info(String* packet)
-{
- char buf[64];
- sprintf(buf, ";file_id=%u", (uint) file_id);
- net_store_data(packet, buf);
-}
-#endif
-
-#ifndef MYSQL_CLIENT
-int Query_log_event::exec_event(struct st_relay_log_info* rli)
-{
- int expected_error,actual_error = 0;
- init_sql_alloc(&thd->mem_root, 8192,0);
- thd->db = rewrite_db((char*)db);
-
- /*
- InnoDB internally stores the master log position it has processed so far;
- position to store is really pos + pending + event_len
- since we must store the pos of the END of the current log event
- */
- rli->event_len= get_event_len();
-
- if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
- {
- thd->set_time((time_t)when);
- thd->current_tablenr = 0;
- thd->query_length= q_len;
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query = (char*)query;
- thd->query_id = query_id++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- thd->query_error = 0; // clear error
- thd->net.last_errno = 0;
- thd->net.last_error[0] = 0;
- thd->slave_proxy_id = thread_id; // for temp tables
-
- /*
- Sanity check to make sure the master did not get a really bad
- error on the query.
- */
- if (ignored_error_code((expected_error = error_code)) ||
- !check_expected_error(thd,rli,expected_error))
- {
- mysql_log.write(thd,COM_QUERY,"%s",thd->query);
- DBUG_PRINT("query",("%s",thd->query));
- mysql_parse(thd, thd->query, q_len);
-
- /*
- Set a flag if we are inside an transaction so that we can restart
- the transaction from the start if we are killed
-
- This will only be done if we are supporting transactional tables
- in the slave.
- */
- if (!strcmp(thd->query,"BEGIN"))
- rli->inside_transaction= opt_using_transactions;
- else if (!strcmp(thd->query,"COMMIT"))
- rli->inside_transaction=0;
-
- if ((expected_error != (actual_error = thd->net.last_errno)) &&
- expected_error &&
- !ignored_error_code(actual_error) &&
- !ignored_error_code(expected_error))
- {
- const char* errmsg = "Slave: did not get the expected error\
- running query from master - expected: '%s' (%d), got '%s' (%d)";
- sql_print_error(errmsg, ER_SAFE(expected_error),
- expected_error,
- actual_error ? thd->net.last_error: "no error",
- actual_error);
- thd->query_error = 1;
- }
- else if (expected_error == actual_error ||
- ignored_error_code(actual_error))
- {
- thd->query_error = 0;
- *rli->last_slave_error = 0;
- rli->last_slave_errno = 0;
- }
- }
- else
- {
- // master could be inconsistent, abort and tell DBA to check/fix it
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->db = thd->query = 0;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- thd->variables.convert_set = 0;
- close_thread_tables(thd);
- free_root(&thd->mem_root,0);
- return 1;
- }
- }
- thd->db= 0; // prevent db from being freed
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query= 0; // just to be sure
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- // assume no convert for next query unless set explictly
- thd->variables.convert_set = 0;
- close_thread_tables(thd);
-
- if (thd->query_error || thd->fatal_error)
- {
- slave_print_error(rli,actual_error, "error '%s' on query '%s'",
- actual_error ? thd->net.last_error :
- "unexpected success or fatal error", query);
- free_root(&thd->mem_root,0);
- return 1;
- }
- free_root(&thd->mem_root,0);
- return Log_event::exec_event(rli);
-}
-
-/*
- Does the data loading job when executing a LOAD DATA on the slave
-
- SYNOPSIS
- Load_log_event::exec_event
- net
- rli
- use_rli_only_for_errors - if set to 1, rli is provided to
- Load_log_event::exec_event only for this
- function to have RPL_LOG_NAME and
- rli->last_slave_error, both being used by
- error reports. rli's position advancing
- is skipped (done by the caller which is
- Execute_load_log_event::exec_event).
- - if set to 0, rli is provided for full use,
- i.e. for error reports and position
- advancing.
-
- DESCRIPTION
- Does the data loading job when executing a LOAD DATA on the slave
-
- RETURN VALUE
- 0 Success
- 1 Failure
-*/
-
-int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
- bool use_rli_only_for_errors)
-{
- init_sql_alloc(&thd->mem_root, 8192,0);
- thd->db = rewrite_db((char*)db);
- DBUG_ASSERT(thd->query == 0);
- thd->query = 0; // Should not be needed
- thd->query_error = 0;
-
- if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
- {
- thd->set_time((time_t)when);
- thd->current_tablenr = 0;
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query_id = query_id++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-
- TABLE_LIST tables;
- bzero((char*) &tables,sizeof(tables));
- tables.db = thd->db;
- tables.alias = tables.real_name = (char*)table_name;
- tables.lock_type = TL_WRITE;
- // the table will be opened in mysql_load
- if (table_rules_on && !tables_ok(thd, &tables))
- {
- // TODO: this is a bug - this needs to be moved to the I/O thread
- if (net)
- skip_load_data_infile(net);
- }
- else
- {
- char llbuff[22];
- enum enum_duplicates handle_dup = DUP_IGNORE;
- if (sql_ex.opt_flags && REPLACE_FLAG)
- handle_dup = DUP_REPLACE;
- sql_exchange ex((char*)fname, sql_ex.opt_flags &&
- DUMPFILE_FLAG );
- String field_term(sql_ex.field_term,sql_ex.field_term_len);
- String enclosed(sql_ex.enclosed,sql_ex.enclosed_len);
- String line_term(sql_ex.line_term,sql_ex.line_term_len);
- String line_start(sql_ex.line_start,sql_ex.line_start_len);
- String escaped(sql_ex.escaped,sql_ex.escaped_len);
-
- ex.opt_enclosed = (sql_ex.opt_flags & OPT_ENCLOSED_FLAG);
- if (sql_ex.empty_flags & FIELD_TERM_EMPTY)
- ex.field_term->length(0);
-
- ex.skip_lines = skip_lines;
- List<Item> field_list;
- set_fields(field_list);
- thd->slave_proxy_id = thd->thread_id;
- if (net)
- {
- // mysql_load will use thd->net to read the file
- thd->net.vio = net->vio;
- /*
- Make sure the client does not get confused about the packet sequence
- */
- thd->net.pkt_nr = net->pkt_nr;
- }
- if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0,
- TL_WRITE))
- thd->query_error = 1;
- if (thd->cuted_fields)
- /*
- log_pos is the position of the LOAD
- event in the master log
- */
- sql_print_error("Slave: load data infile at position %s in log \
-'%s' produced %d warning(s)", llstr(log_pos,llbuff), RPL_LOG_NAME,
- thd->cuted_fields );
- if (net)
- net->pkt_nr= thd->net.pkt_nr;
- }
- }
- else
- {
- /*
- We will just ask the master to send us /dev/null if we do not
- want to load the data.
- TODO: this a bug - needs to be done in I/O thread
- */
- if (net)
- skip_load_data_infile(net);
- }
-
- thd->net.vio = 0;
- thd->db= 0; // prevent db from being freed
- close_thread_tables(thd);
- if (thd->query_error)
- {
- int sql_error = thd->net.last_errno;
- if (!sql_error)
- sql_error = ER_UNKNOWN_ERROR;
-
- slave_print_error(rli,sql_error,
- "Slave: Error '%s' running load data infile ",
- ER_SAFE(sql_error));
- free_root(&thd->mem_root,0);
- return 1;
- }
- free_root(&thd->mem_root,0);
-
- if (thd->fatal_error)
- {
- sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
- return 1;
- }
-
- return ( use_rli_only_for_errors ? 0 : Log_event::exec_event(rli) );
-}
-
-
-/*
- The master started
-
- IMPLEMENTATION
- - To handle the case where the master died without a stop event,
- we clean up all temporary tables + locks that we got.
-
- TODO
- - Remove all active user locks
- - If we have an active transaction at this point, the master died
- in the middle while writing the transaction to the binary log.
- In this case we should stop the slave.
-*/
-
-int Start_log_event::exec_event(struct st_relay_log_info* rli)
-{
- /* All temporary tables was deleted on the master */
- close_temporary_tables(thd);
- /*
- If we have old format, load_tmpdir is cleaned up by the I/O thread
- */
- if (!rli->mi->old_format)
- cleanup_load_tmpdir();
- return Log_event::exec_event(rli);
-}
-
-
-/*
- The master stopped. Clean up all temporary tables + locks that the
- master may have set.
-
- TODO
- - Remove all active user locks
-*/
-
-int Stop_log_event::exec_event(struct st_relay_log_info* rli)
-{
- // do not clean up immediately after rotate event
- if (rli->master_log_pos > BIN_LOG_HEADER_SIZE)
- {
- close_temporary_tables(thd);
- cleanup_load_tmpdir();
- }
- /*
- We do not want to update master_log pos because we get a rotate event
- before stop, so by now master_log_name is set to the next log.
- If we updated it, we will have incorrect master coordinates and this
- could give false triggers in MASTER_POS_WAIT() that we have reached
- the target position when in fact we have not.
- */
- rli->inc_pos(get_event_len(), 0);
- flush_relay_log_info(rli);
- return 0;
-}
-
-
-/*
- Got a rotate log even from the master
-
- IMPLEMENTATION
- This is mainly used so that we can later figure out the logname and
- position for the master.
-
- We can't rotate the slave as this will cause infinitive rotations
- in a A -> B -> A setup.
-
- RETURN VALUES
- 0 ok
- */
-
-
-int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
-{
- char* log_name = rli->master_log_name;
- DBUG_ENTER("Rotate_log_event::exec_event");
-
- pthread_mutex_lock(&rli->data_lock);
- memcpy(log_name, new_log_ident, ident_len+1);
- rli->master_log_pos = pos;
- rli->relay_log_pos += get_event_len();
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) rli->master_log_pos));
- pthread_mutex_unlock(&rli->data_lock);
- pthread_cond_broadcast(&rli->data_cond);
- flush_relay_log_info(rli);
- DBUG_RETURN(0);
-}
-
-
-int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
-{
- switch (type) {
- case LAST_INSERT_ID_EVENT:
- thd->last_insert_id_used = 1;
- thd->last_insert_id = val;
- break;
- case INSERT_ID_EVENT:
- thd->next_insert_id = val;
- break;
- }
- rli->inc_pending(get_event_len());
- return 0;
-}
-
-int Rand_log_event::exec_event(struct st_relay_log_info* rli)
-{
- thd->rand.seed1 = (ulong) seed1;
- thd->rand.seed2 = (ulong) seed2;
- rli->inc_pending(get_event_len());
- return 0;
-}
-
-int Slave_log_event::exec_event(struct st_relay_log_info* rli)
-{
- if (mysql_bin_log.is_open())
- mysql_bin_log.write(this);
- return Log_event::exec_event(rli);
-}
-
-int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
-{
- char fname_buf[FN_REFLEN+10];
- char *p;
- int fd = -1;
- IO_CACHE file;
- int error = 1;
+#endif // MYSQL_CLIENT
- bzero((char*)&file, sizeof(file));
- p = slave_load_file_stem(fname_buf, file_id, server_id);
- strmov(p, ".info"); // strmov takes less code than memcpy
- if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
- MYF(MY_WME))) < 0 ||
- init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
- MYF(MY_WME|MY_NABP)))
- {
- slave_print_error(rli,my_errno, "Could not open file '%s'", fname_buf);
- goto err;
- }
-
- // a trick to avoid allocating another buffer
- strmov(p, ".data");
- fname = fname_buf;
- fname_len = (uint)(p-fname) + 5;
- if (write_base(&file))
- {
- strmov(p, ".info"); // to have it right in the error message
- slave_print_error(rli,my_errno, "Could not write to file '%s'", fname_buf);
- goto err;
- }
- end_io_cache(&file);
- my_close(fd, MYF(0));
-
- // fname_buf now already has .data, not .info, because we did our trick
- if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
- MYF(MY_WME))) < 0)
- {
- slave_print_error(rli,my_errno, "Could not open file '%s'", fname_buf);
- goto err;
- }
- if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
- {
- slave_print_error(rli,my_errno, "Write to '%s' failed", fname_buf);
- goto err;
- }
- if (mysql_bin_log.is_open())
- mysql_bin_log.write(this);
- error=0; // Everything is ok
+/*****************************************************************************
-err:
- if (error)
- end_io_cache(&file);
- if (fd >= 0)
- my_close(fd, MYF(0));
- return error ? 1 : Log_event::exec_event(rli);
-}
+ Execute_load_log_event::pack_info()
-int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
+ ****************************************************************************/
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Execute_load_log_event::pack_info(Protocol *protocol)
{
- char fname[FN_REFLEN+10];
- char *p= slave_load_file_stem(fname, file_id, server_id);
- memcpy(p, ".data", 6);
- (void) my_delete(fname, MYF(MY_WME));
- memcpy(p, ".info", 6);
- (void) my_delete(fname, MYF(MY_WME));
- if (mysql_bin_log.is_open())
- mysql_bin_log.write(this);
- return Log_event::exec_event(rli);
+ char buf[64];
+ uint length;
+ length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id));
+ protocol->store(buf, (int32) length);
}
-int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
-{
- char fname[FN_REFLEN+10];
- char *p= slave_load_file_stem(fname, file_id, server_id);
- int fd;
- int error = 1;
+/*****************************************************************************
- memcpy(p, ".data", 6);
- if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0)
- {
- slave_print_error(rli,my_errno, "Could not open file '%s'", fname);
- goto err;
- }
- if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
- {
- slave_print_error(rli,my_errno, "Write to '%s' failed", fname);
- goto err;
- }
- if (mysql_bin_log.is_open())
- mysql_bin_log.write(this);
- error=0;
+ Execute_load_log_event::exec_event()
-err:
- if (fd >= 0)
- my_close(fd, MYF(0));
- return error ? error : Log_event::exec_event(rli);
-}
+ ****************************************************************************/
int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2208,4 +3052,95 @@ err:
return error ? error : Log_event::exec_event(rli);
}
-#endif /* !MYSQL_CLIENT */
+#endif
+
+
+/*****************************************************************************
+ *****************************************************************************
+
+ sql_ex_info methods
+
+ *****************************************************************************
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ sql_ex_info::write_data()
+
+ ****************************************************************************/
+int sql_ex_info::write_data(IO_CACHE* file)
+{
+ if (new_format())
+ {
+ return (write_str(file, field_term, field_term_len) ||
+ write_str(file, enclosed, enclosed_len) ||
+ write_str(file, line_term, line_term_len) ||
+ write_str(file, line_start, line_start_len) ||
+ write_str(file, escaped, escaped_len) ||
+ my_b_safe_write(file,(byte*) &opt_flags,1));
+ }
+ else
+ {
+ old_sql_ex old_ex;
+ old_ex.field_term= *field_term;
+ old_ex.enclosed= *enclosed;
+ old_ex.line_term= *line_term;
+ old_ex.line_start= *line_start;
+ old_ex.escaped= *escaped;
+ old_ex.opt_flags= opt_flags;
+ old_ex.empty_flags=empty_flags;
+ return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex));
+ }
+}
+
+/*****************************************************************************
+
+ sql_ex_info::init()
+
+ ****************************************************************************/
+char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
+{
+ cached_new_format = use_new_format;
+ if (use_new_format)
+ {
+ empty_flags=0;
+ /*
+ The code below assumes that buf will not disappear from
+ under our feet during the lifetime of the event. This assumption
+ holds true in the slave thread if the log is in new format, but is not
+ the case when we have old format because we will be reusing net buffer
+ to read the actual file before we write out the Create_file event.
+ */
+ if (read_str(buf, buf_end, field_term, field_term_len) ||
+ read_str(buf, buf_end, enclosed, enclosed_len) ||
+ read_str(buf, buf_end, line_term, line_term_len) ||
+ read_str(buf, buf_end, line_start, line_start_len) ||
+ read_str(buf, buf_end, escaped, escaped_len))
+ return 0;
+ opt_flags = *buf++;
+ }
+ else
+ {
+ field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
+ field_term = buf++; // Use first byte in string
+ enclosed= buf++;
+ line_term= buf++;
+ line_start= buf++;
+ escaped= buf++;
+ opt_flags = *buf++;
+ empty_flags= *buf++;
+ if (empty_flags & FIELD_TERM_EMPTY)
+ field_term_len=0;
+ if (empty_flags & ENCLOSED_EMPTY)
+ enclosed_len=0;
+ if (empty_flags & LINE_TERM_EMPTY)
+ line_term_len=0;
+ if (empty_flags & LINE_START_EMPTY)
+ line_start_len=0;
+ if (empty_flags & ESCAPED_EMPTY)
+ escaped_len=0;
+ }
+ return buf;
+}
+
+
diff --git a/sql/log_event.h b/sql/log_event.h
index 5b9f30b3afd..567bf279ff1 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -54,6 +54,11 @@
#define LINE_START_EMPTY 0x8
#define ESCAPED_EMPTY 0x10
+/*****************************************************************************
+
+ old_sql_ex struct
+
+ ****************************************************************************/
struct old_sql_ex
{
char field_term;
@@ -67,6 +72,11 @@ struct old_sql_ex
#define NUM_LOAD_DELIM_STRS 5
+/*****************************************************************************
+
+ sql_ex_info struct
+
+ ****************************************************************************/
struct sql_ex_info
{
char* field_term;
@@ -99,13 +109,19 @@ struct sql_ex_info
}
};
-/*
- Binary log consists of events. Each event has a fixed length header,
- followed by possibly variable ( depending on the type of event) length
- data body. The data body consists of an optional fixed length segment
- (post-header), and an optional variable length segment. See #defines and
- comments below for the format specifics
-*/
+/*****************************************************************************
+
+ MySQL Binary Log
+
+ This log consists of events. Each event has a fixed-length header,
+ possibly followed by a variable length data body.
+
+ The data body consists of an optional fixed length segment (post-header)
+ and an optional variable length segment.
+
+ See the #defines below for the format specifics.
+
+ ****************************************************************************/
/* event-specific post-header sizes */
#define LOG_EVENT_HEADER_LEN 19
@@ -157,6 +173,14 @@ struct sql_ex_info
#define RAND_SEED1_OFFSET 0
#define RAND_SEED2_OFFSET 8
+/* User_var event post-header */
+
+#define UV_VAL_LEN_SIZE 4
+#define UV_VAL_IS_NULL 1
+#define UV_VAL_TYPE_SIZE 1
+#define UV_NAME_LEN_SIZE 4
+#define UV_CHARSET_NUMBER_SIZE 4
+
/* Load event post-header */
#define L_THREAD_ID_OFFSET 0
@@ -196,15 +220,17 @@ struct sql_ex_info
#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
-#define LOG_EVENT_TIME_F 0x1
-#define LOG_EVENT_FORCED_ROTATE_F 0x2
+#define LOG_EVENT_TIME_F 0x1
+#define LOG_EVENT_FORCED_ROTATE_F 0x2
+#define LOG_EVENT_THREAD_SPECIFIC_F 0x4 /* query depends on thread
+ (for example: TEMPORARY TABLE) */
enum Log_event_type
{
START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, ROTATE_EVENT = 4,
INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
- NEW_LOAD_EVENT=12, RAND_EVENT=13
+ NEW_LOAD_EVENT=12, RAND_EVENT=13, USER_VAR_EVENT=14
};
enum Int_event_type
@@ -221,6 +247,13 @@ class THD;
struct st_relay_log_info;
+/*****************************************************************************
+
+ Log_event class
+
+ This is the abstract base class for binary log events.
+
+ ****************************************************************************/
class Log_event
{
public:
@@ -244,10 +277,12 @@ public:
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
void set_log_pos(MYSQL_LOG* log);
- virtual void pack_info(String* packet);
- int net_send(THD* thd, const char* log_name, my_off_t pos);
static void init_show_field_list(List<Item>* field_list);
+#ifdef HAVE_REPLICATION
+ int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
+ virtual void pack_info(Protocol *protocol);
virtual int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
virtual const char* get_db()
{
return thd ? thd->db : 0;
@@ -304,6 +339,13 @@ public:
};
+/*****************************************************************************
+
+ Query Log Event class
+
+ Logs SQL queries
+
+ ****************************************************************************/
class Query_log_event: public Log_event
{
protected:
@@ -325,8 +367,10 @@ public:
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
bool using_trans);
const char* get_db() { return db; }
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -353,7 +397,13 @@ public:
}
};
+#ifdef HAVE_REPLICATION
+
+/*****************************************************************************
+
+ Slave Log Event class
+ ****************************************************************************/
class Slave_log_event: public Log_event
{
protected:
@@ -369,7 +419,7 @@ public:
#ifndef MYSQL_CLIENT
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -383,6 +433,14 @@ public:
int write_data(IO_CACHE* file );
};
+#endif /* HAVE_REPLICATION */
+
+
+/*****************************************************************************
+
+ Load Log Event class
+
+ ****************************************************************************/
class Load_log_event: public Log_event
{
protected:
@@ -404,6 +462,13 @@ public:
uint32 skip_lines;
sql_ex_info sql_ex;
+ /* fname doesn't point to memory inside Log_event::temp_buf */
+ void set_fname_outside_temp_buf(const char *afname, uint alen)
+ {fname=afname;fname_len=alen;}
+ /* fname doesn't point to memory inside Log_event::temp_buf */
+ int check_fname_outside_temp_buf()
+ {return fname<temp_buf || fname>temp_buf+cached_event_len;}
+
#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
@@ -413,14 +478,16 @@ public:
List<Item>& fields_arg, enum enum_duplicates handle_dup,
bool using_trans);
void set_fields(List<Item> &fields_arg);
- void pack_info(String* packet);
const char* get_db() { return db; }
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli)
{
return exec_event(thd->slave_net,rli,0);
}
int exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -449,6 +516,11 @@ public:
extern char server_version[SERVER_VERSION_LENGTH];
+/*****************************************************************************
+
+ Start Log Event class
+
+ ****************************************************************************/
class Start_log_event: public Log_event
{
public:
@@ -462,8 +534,10 @@ public:
created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -480,6 +554,13 @@ public:
};
+/*****************************************************************************
+
+ Intvar Log Event class
+
+ Logs special variables such as auto_increment values
+
+ ****************************************************************************/
class Intvar_log_event: public Log_event
{
public:
@@ -490,8 +571,10 @@ public:
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
:Log_event(),val(val_arg),type(type_arg)
{}
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -506,9 +589,11 @@ public:
};
/*****************************************************************************
- *
- * Rand log event class
- *
+
+ Rand Log Event class
+
+ Logs random seed used by the next RAND()
+
****************************************************************************/
class Rand_log_event: public Log_event
{
@@ -520,8 +605,10 @@ class Rand_log_event: public Log_event
Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
:Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -534,11 +621,58 @@ class Rand_log_event: public Log_event
bool is_valid() { return 1; }
};
+/*****************************************************************************
+
+ User var Log Event class
+
+ ****************************************************************************/
+class User_var_log_event: public Log_event
+{
+public:
+ char *name;
+ uint name_len;
+ char *val;
+ ulong val_len;
+ Item_result type;
+ uint charset_number;
+ byte is_null;
+#ifndef MYSQL_CLIENT
+ User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
+ char *val_arg, ulong val_len_arg, Item_result type_arg,
+ uint charset_number_arg)
+ :Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg),
+ val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg)
+ { is_null= !val; }
+ void pack_info(Protocol* protocol);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+
+ User_var_log_event(const char* buf, bool old_format);
+ ~User_var_log_event() {}
+ Log_event_type get_type_code() { return USER_VAR_EVENT;}
+ int get_data_size()
+ {
+ return (is_null ? UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL :
+ UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
+ UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE + val_len);
+ }
+ int write_data(IO_CACHE* file);
+ bool is_valid() { return 1; }
+};
+
+/*****************************************************************************
+
+ Stop Log Event class
+
+ ****************************************************************************/
+#ifdef HAVE_REPLICATION
class Stop_log_event: public Log_event
{
public:
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
Stop_log_event() :Log_event()
{}
int exec_event(struct st_relay_log_info* rli);
@@ -554,7 +688,16 @@ public:
bool is_valid() { return 1; }
};
+#endif /* HAVE_REPLICATION */
+
+
+/*****************************************************************************
+
+ Rotate Log Event class
+
+ This will be depricated when we move to using sequence ids.
+ ****************************************************************************/
class Rotate_log_event: public Log_event
{
public:
@@ -570,8 +713,10 @@ public:
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -590,6 +735,11 @@ public:
/* the classes below are for the new LOAD DATA INFILE logging */
+/*****************************************************************************
+
+ Create File Log Event class
+
+ ****************************************************************************/
class Create_file_log_event: public Load_log_event
{
protected:
@@ -612,10 +762,13 @@ public:
enum enum_duplicates handle_dup,
char* block_arg, uint block_len_arg,
bool using_trans);
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+ void print(FILE* file, bool short_form, char* last_db, bool enable_local);
#endif
Create_file_log_event(const char* buf, int event_len, bool old_format);
@@ -647,6 +800,11 @@ public:
};
+/*****************************************************************************
+
+ Append Block Log Event class
+
+ ****************************************************************************/
class Append_block_log_event: public Log_event
{
public:
@@ -657,8 +815,10 @@ public:
#ifndef MYSQL_CLIENT
Append_block_log_event(THD* thd, char* block_arg,
uint block_len_arg, bool using_trans);
+#ifdef HAVE_REPLICATION
int exec_event(struct st_relay_log_info* rli);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -671,7 +831,11 @@ public:
int write_data(IO_CACHE* file);
};
+/*****************************************************************************
+
+ Delete File Log Event class
+ ****************************************************************************/
class Delete_file_log_event: public Log_event
{
public:
@@ -679,8 +843,10 @@ public:
#ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd, bool using_trans);
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -693,6 +859,11 @@ public:
int write_data(IO_CACHE* file);
};
+/*****************************************************************************
+
+ Execute Load Log Event class
+
+ ****************************************************************************/
class Execute_load_log_event: public Log_event
{
public:
@@ -700,8 +871,10 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd, bool using_trans);
- void pack_info(String* packet);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index 1bc65eebd23..4b0575c8579 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -32,12 +32,12 @@
#define MAP_TO_USE_RAID
#include "mysql_priv.h"
+#ifdef HAVE_REPLICATION
#ifdef HAVE_AIOWAIT
#include <mysys_err.h>
#include <errno.h>
static void my_aiowait(my_aio_result *result);
#endif
-#include <assert.h>
extern "C" {
@@ -81,3 +81,6 @@ int _my_b_net_read(register IO_CACHE *info, byte *Buffer,
}
} /* extern "C" */
+#endif /* HAVE_REPLICATION */
+
+
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index 38b3c22b91b..2ee4b551d71 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -23,6 +23,8 @@
*/
#include <my_global.h>
+#ifdef HAVE_EXTERNAL_CLIENT
+
/* my_pthread must be included early to be able to fix things */
#if defined(THREAD)
#include <my_pthread.h> /* because of signal() */
@@ -40,6 +42,7 @@
#include "mysql_version.h"
#include "mysqld_error.h"
#include "errmsg.h"
+#include <assert.h>
#if defined( OS2) && defined(MYSQL_SERVER)
#undef ER
@@ -86,7 +89,9 @@ static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
+ CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION)
+
#if defined(MSDOS) || defined(__WIN__)
#define perror(A)
@@ -124,7 +129,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
if (!host || !strcmp(host,LOCAL_HOST))
host=LOCAL_HOST_NAMEDPIPE;
- sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket);
+ sprintf(szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket);
DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s",
host, unix_socket));
@@ -325,7 +330,7 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name,
** or packet is an error message
*****************************************************************************/
-ulong
+ulong
mc_net_safe_read(MYSQL *mysql)
{
NET *net= &mysql->net;
@@ -430,7 +435,7 @@ my_bool mc_mysql_reconnect(MYSQL *mysql)
-int
+int
mc_simple_command(MYSQL *mysql,enum enum_server_command command,
const char *arg, uint length, my_bool skipp_check)
{
@@ -450,21 +455,21 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
mysql->net.last_error[0]=0;
mysql->net.last_errno=0;
+ mysql->net.report_error=0;
mysql->info=0;
mysql->affected_rows= ~(my_ulonglong) 0;
net_clear(net); /* Clear receive buffer */
if (!arg)
arg="";
- if (net_write_command(net,(uchar) command,arg,
- length ? length :(uint) strlen(arg)))
+ if (net_write_command(net, (uchar) command, NullS, 0, arg, length))
{
- DBUG_PRINT("error",("Can't send command to server. Error: %d",socket_errno));
+ DBUG_PRINT("error",("Can't send command to server. Error: %d",
+ socket_errno));
mc_end_server(mysql);
if (mc_mysql_reconnect(mysql))
goto end;
- if (net_write_command(net,(uchar) command,arg,
- length ? length :(uint) strlen(arg)))
+ if (net_write_command(net,(uchar) command, NullS, 0, arg, length))
{
net->last_errno=CR_SERVER_GONE_ERROR;
strmov(net->last_error,ER(net->last_errno));
@@ -480,13 +485,14 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
}
-MYSQL *
+MYSQL *
mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag,
uint net_read_timeout)
{
char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info;
+ char password_hash[SCRAMBLE41_LENGTH];
my_socket sock;
ulong ip_addr;
struct sockaddr_in sock_addr;
@@ -509,7 +515,6 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
user ? user : "(Null)",
net_read_timeout,
(uint) slave_net_timeout));
-
net->vio = 0; /* If something goes wrong */
mysql->charset=default_charset_info; /* Set character set */
if (!port)
@@ -664,7 +669,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
vio_poll_read(net->vio, mysql->options.connect_timeout))
{
net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
if ((pkt_length=mc_net_safe_read(mysql)) == packet_error)
@@ -779,7 +784,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
if (my_net_write(net,buff,(uint) (2)) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Do the SSL layering. */
@@ -803,22 +808,103 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
}
DBUG_PRINT("info",("user: %s",buff+5));
- end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
- if (db)
+
+ /*
+ We always start with old type handshake the only difference is message sent
+ If server handles secure connection type we'll not send the real scramble
+ */
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ if (passwd[0])
+ {
+ /* Prepare false scramble */
+ end=strend(buff+5)+1;
+ bfill(end, SCRAMBLE_LENGTH, 'x');
+ end+=SCRAMBLE_LENGTH;
+ *end=0;
+ }
+ else /* For empty password*/
+ {
+ end=strend(buff+5)+1;
+ *end=0; /* Store zero length scramble */
+ }
+ }
+ else
+ /*
+ Real scramble is only sent to old servers. This can be blocked
+ by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
+ */
+ end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
+ (my_bool) (mysql->protocol_version == 9));
+
+ /* Add database if needed */
+ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end=strmake(end+1,db,NAME_LEN);
mysql->db=my_strdup(db,MYF(MY_WME));
db=0;
}
+ /* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ strmov(net->last_error,ER(net->last_errno));
goto error;
}
- if (mc_net_safe_read(mysql) == packet_error)
+
+ /* We shall only query sever if it expect us to do so */
+
+ if ( (pkt_length=mc_net_safe_read(mysql)) == packet_error)
goto error;
+
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ /* This should always happen with new server unless empty password */
+ if (pkt_length==24 && net->read_pos[0])
+ /* OK/Error message has zero as the first character */
+ {
+ /* Old passwords will have zero at the first byte of hash */
+ if (net->read_pos[0] != '*')
+ {
+ /* Build full password hash as it is required to decode scramble */
+ password_hash_stage1(buff, passwd);
+ /* Store copy as we'll need it later */
+ memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
+ /* Finally hash complete password using hash we got from server */
+ password_hash_stage2(password_hash,(char*)net->read_pos);
+ /* Decypt and store scramble 4 = hash for stage2 */
+ password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,
+ SCRAMBLE41_LENGTH);
+ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
+ /* Encode scramble with password. Recycle buffer */
+ password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
+ }
+ else
+ {
+ /* Create password to decode scramble */
+ create_key_from_old_password(passwd,password_hash);
+ /* Decypt and store scramble 4 = hash for stage2 */
+ password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,
+ SCRAMBLE41_LENGTH);
+ mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
+ /* Finally scramble decoded scramble with password */
+ scramble(buff, mysql->scramble_buff, passwd,0);
+ }
+ /* Write second package of authentication */
+ if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+ /* Read What server thinks about out new auth message report */
+ if (mc_net_safe_read(mysql) == packet_error)
+ goto error;
+ }
+ }
+
+ /* End of authentication part of handshake */
+
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
@@ -845,7 +931,7 @@ error:
** NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************
*/
-int
+int
mysql_ssl_clear(MYSQL *mysql)
{
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
@@ -870,7 +956,7 @@ mysql_ssl_clear(MYSQL *mysql)
** If handle is alloced by mysql connect free it.
*************************************************************************/
-void
+void
mc_mysql_close(MYSQL *mysql)
{
DBUG_ENTER("mysql_close");
@@ -1032,18 +1118,19 @@ get_info:
DBUG_RETURN(0);
}
-int mc_mysql_query(MYSQL *mysql, const char *query, uint length)
+
+int mc_mysql_query(MYSQL *mysql, const char *query, uint length)
{
- DBUG_ENTER("mysql_real_query");
+ DBUG_ENTER("mc_mysql_query");
DBUG_PRINT("enter",("handle: %lx",mysql));
DBUG_PRINT("query",("Query = \"%s\"",query));
- if (!length)
- length = strlen(query);
+ DBUG_ASSERT(length == strlen(query));
if (mc_simple_command(mysql,COM_QUERY,query,length,1))
DBUG_RETURN(-1);
DBUG_RETURN(mc_mysql_read_query_result(mysql));
}
+
static int mc_send_file_to_server(MYSQL *mysql, const char *filename)
{
int fd, readcount, result= -1;
@@ -1391,3 +1478,5 @@ MYSQL_RES *mc_mysql_store_result(MYSQL *mysql)
mysql->fields=0; /* fields is now in result */
DBUG_RETURN(result); /* Data fetched */
}
+
+#endif /* HAVE_EXTERNAL_CLIENT */
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index d9a4302ce0c..dd5bee2eed5 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
#include <thr_lock.h>
#include <my_base.h> /* Needed by field.h */
#include <my_bitmap.h>
+#include <assert.h>
#ifdef __EMX__
#undef write /* remove pthread.h macro definition for EMX */
@@ -53,12 +54,25 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
#define all_bits_set(A,B) ((A) & (B) != (B))
+#ifndef LL
+#ifdef HAVE_LONG_LONG
+#define LL(A) A ## LL
+#else
+#define LL(A) A ## L
+#endif
+#endif
+
+#define my_thd_charset default_charset_info
+#define files_charset_info system_charset_info
+
/***************************************************************************
Configuration parameters
****************************************************************************/
#define ACL_CACHE_SIZE 256
-#define HASH_PASSWORD_LENGTH 16
+/* Password lengh for 4.1 version previous versions had 16 bytes password hash */
+#define HASH_PASSWORD_LENGTH 45
+#define HASH_OLD_PASSWORD_LENGTH 16
#define HOST_CACHE_SIZE 128
#define MAX_ACCEPT_RETRY 10 // Test accept this many times
#define MAX_FIELDS_BEFORE_HASH 32
@@ -192,6 +206,16 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define MODE_SERIALIZABLE 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
+#define MODE_POSTGRESQL 128
+#define MODE_ORACLE 256
+#define MODE_MSSQL 512
+#define MODE_DB2 1024
+#define MODE_SAPDB 2048
+#define MODE_NO_KEY_OPTIONS 4096
+#define MODE_NO_TABLE_OPTIONS 8192
+#define MODE_NO_FIELD_OPTIONS 16384
+#define MODE_MYSQL323 32768
+#define MODE_MYSQL40 65536
#define RAID_BLOCK_SIZE 1024
@@ -270,8 +294,10 @@ inline THD *_current_thd(void)
#include "handler.h"
#include "table.h"
#include "field.h" /* Field definitions */
+#include "protocol.h"
#include "sql_udf.h"
#include "item.h"
+typedef compare_func_creator (*chooser_compare_func_creator)(bool invert);
#include "sql_class.h"
#include "opt_range.h"
@@ -302,22 +328,30 @@ inline THD *_current_thd(void)
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
#endif /*HAVE_QUERY_CACHE*/
-int mysql_create_db(THD *thd, char *db, uint create_info, bool silent);
+#define prepare_execute(A) ((A)->command == COM_EXECUTE)
+
+int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
+int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
-int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
+int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary);
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool log_query);
+ bool drop_temporary, bool log_query);
int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
- bool if_exists,
+ bool if_exists, bool drop_temporary,
bool log_query);
int quick_rm_table(enum db_type base,const char *db,
const char *table_name);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length);
+void free_items(Item *item);
+bool alloc_query(THD *thd, char *packet, ulong packet_length);
void mysql_init_select(LEX *lex);
-bool mysql_new_select(LEX *lex);
+void mysql_init_query(THD *thd);
+bool mysql_new_select(LEX *lex, bool move_down);
+void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
@@ -326,7 +360,7 @@ extern "C" pthread_handler_decl(handle_one_connection,arg);
extern "C" pthread_handler_decl(handle_bootstrap,arg);
void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
-void mysql_execute_command(void);
+void mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
@@ -356,45 +390,39 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
bool check_simple_select();
-/* net_pkg.c */
-void send_warning(NET *net, uint sql_errno, const char *err=0);
-void net_printf(NET *net,uint sql_errno, ...);
-void send_ok(NET *net,ha_rows affected_rows=0L,ulonglong id=0L,
- const char *info=0);
-void send_eof(NET *net,bool no_flush=0);
-char *net_store_length(char *packet,ulonglong length);
-char *net_store_length(char *packet,uint length);
-char *net_store_data(char *to,const char *from);
-char *net_store_data(char *to,int32 from);
-char *net_store_data(char *to,longlong from);
-
-bool net_store_null(String *packet);
-bool net_store_data(String *packet,uint32 from);
-bool net_store_data(String *packet,longlong from);
-bool net_store_data(String *packet,const char *from);
-bool net_store_data(String *packet,const char *from,uint length);
-bool net_store_data(String *packet,struct tm *tmp);
-bool net_store_data(String* packet, I_List<i_string>* str_list);
-bool net_store_data(String *packet,CONVERT *convert, const char *from,
- uint length);
-bool net_store_data(String *packet, CONVERT *convert, const char *from);
-
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
-int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
- List <Item> &all_fields, ORDER *order);
+int setup_ref_array(THD *thd, Item ***rref_pointer_array, uint elements);
+int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, List <Item> &all_fields, ORDER *order);
+int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, List<Item> &all_fields, ORDER *order,
+ bool *hidden_group_fields);
int handle_select(THD *thd, LEX *lex, select_result *result);
-int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
- ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
- ulong select_type,select_result *result);
-int mysql_union(THD *thd,LEX *lex,select_result *result);
+int mysql_select(THD *thd, Item ***rref_pointer_array,
+ TABLE_LIST *tables, uint wild_num, List<Item> &list,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, ulong select_type,
+ select_result *result, SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex, bool fake_select_lex,
+ bool tables_and_fields_initied);
+void free_underlaid_joins(THD *thd, SELECT_LEX *select);
+void fix_tables_pointers(SELECT_LEX *select_lex);
+void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
+int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
+ select_result *result);
+int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
+ select_result *result);
+int mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit, bool tables_and_fields_initied);
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
bool group,bool modify_item);
int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
List<create_field> &fields, List<Key> &keys,
- bool tmp_table, bool no_log);
+ bool tmp_table, bool no_log, uint select_field_count);
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
const char *db, const char *name,
List<create_field> *extra_fields,
@@ -407,11 +435,14 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
- ORDER *order,
+ uint order_num, ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
- bool simple_alter=0);
+ bool simple_alter=0);
+int mysql_create_like_table(THD *thd, TABLE_LIST *table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *src_table);
bool mysql_rename_table(enum db_type base,
const char *old_db,
const char * old_name,
@@ -422,15 +453,17 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &values,COND *conds,
- ORDER *order, ha_rows limit,
+ List<Item> &values,COND *conds,
+ uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values,
COND *conds, ulong options,
- enum enum_duplicates handle_duplicates);
+ enum enum_duplicates handle_duplicates,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
- List<List_item> &values, enum_duplicates flag);
+ List<List_item> &values, List<Item> &update_fields,
+ List<Item> &update_values, enum_duplicates flag);
void kill_delayed_threads(void);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
ha_rows rows, ulong options);
@@ -449,13 +482,15 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
-Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
+extern const Field *not_found_field;
+Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
+ TABLE_LIST **where, bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
-struct st_des_keyblock
-{
- des_cblock key1, key2, key3;
+struct st_des_keyblock
+{
+ des_cblock key1, key2, key3;
};
struct st_des_keyschedule
{
@@ -472,7 +507,7 @@ void free_des_key_file();
/* sql_do.cc */
int mysql_do(THD *thd, List<Item> &values);
-/* sql_list.c */
+/* sql_show.cc */
int mysqld_show_dbs(THD *thd,const char *wild);
int mysqld_show_open_tables(THD *thd,const char *wild);
int mysqld_show_tables(THD *thd,const char *db,const char *wild);
@@ -484,12 +519,36 @@ int mysqld_show_logs(THD *thd);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
+int mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild);
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
enum enum_var_type value_type);
+int mysqld_show_charsets(THD *thd,const char *wild);
+int mysqld_show_table_types(THD *thd);
+int mysqld_show_privileges(THD *thd);
+int mysqld_show_column_types(THD *thd);
+int mysqld_help (THD *thd, const char *text);
+
+/* sql_prepare.cc */
+int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key);
+void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used);
+bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
+void mysql_stmt_execute(THD *thd, char *packet);
+void mysql_stmt_free(THD *thd, char *packet);
+void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
+int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
+ List<Item> &values, ulong counter);
+
+/* sql_error.cc */
+void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
+ const char *msg);
+void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *format, ...);
+void mysql_reset_errors(THD *thd);
+my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
/* sql_handler.cc */
int mysql_ha_open(THD *thd, TABLE_LIST *tables);
@@ -500,18 +559,13 @@ int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
/* sql_base.cc */
void set_item_name(Item *item,char *pos,uint length);
-bool add_field_to_list(char *field_name, enum enum_field_types type,
+bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
char *length, char *decimal,
- uint type_modifier, Item *default_value,char *change,
- TYPELIB *interval);
+ uint type_modifier,
+ Item *default_value, Item *comment,
+ char *change, TYPELIB *interval,CHARSET_INFO *cs);
void store_position_for_column(const char *name);
-bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
-TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias,
- ulong table_option,
- thr_lock_type flags=TL_UNLOCK,
- List<String> *use_index=0,
- List<String> *ignore_index=0);
-void set_lock_for_tables(thr_lock_type lock_type);
+bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
bool add_proc_to_list(THD *thd, Item *item);
@@ -519,17 +573,23 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error);
-Item ** find_item_in_list(Item *item,List<Item> &items);
-bool insert_fields(THD *thd,TABLE_LIST *tables,
+enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
+ IGNORE_ERRORS};
+extern const Item **not_found_item;
+Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
+ find_item_error_report_type report_error);
+bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables);
-int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
- bool set_query_id,List<Item> *sum_func_list,
- bool allow_sum_func);
+int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
+ List<Item> *sum_func_list, uint wild_num);
+int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &item, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
-int setup_ftfuncs(THD *thd);
-int init_ftfuncs(THD *thd, bool no_order);
+int setup_ftfuncs(SELECT_LEX* select);
+int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
void wait_for_refresh(THD *thd);
int open_tables(THD *thd,TABLE_LIST *tables);
int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
@@ -537,13 +597,16 @@ int lock_tables(THD *thd,TABLE_LIST *tables);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
bool rm_temporary_table(enum db_type base, char *path);
-bool send_fields(THD *thd,List<Item> &item,uint send_field_count);
void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr);
-void close_thread_tables(THD *thd,bool locked=0);
-bool close_thread_table(THD *thd, TABLE **table_ptr);
+void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
void close_temporary_tables(THD *thd);
+TABLE_LIST * find_table_in_list(TABLE_LIST *table,
+ const char *db_name, const char *table_name);
+TABLE_LIST * find_real_table_in_list(TABLE_LIST *table,
+ const char *db_name,
+ const char *table_name);
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name);
bool close_temporary_table(THD *thd, const char *db, const char *table_name);
void close_temporary(TABLE *table, bool delete_table=1);
@@ -580,7 +643,7 @@ extern "C" pthread_handler_decl(handle_manager, arg);
#ifndef DBUG_OFF
void print_where(COND *cond,const char *info);
void print_cached_tables(void);
-void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special);
+void TEST_filesort(SORT_FIELD *sortorder,uint s_length);
#endif
void mysql_print_status(THD *thd);
/* key.cc */
@@ -602,8 +665,6 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
const char *index_file_name,
enum_log_type type, bool read_append = 0,
bool no_auto_events = 0);
-/* mysqld.cc */
-void clear_error_message(THD *thd);
/*
External variables
@@ -611,8 +672,9 @@ void clear_error_message(THD *thd);
extern time_t start_time;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
- max_sort_char, mysql_real_data_home[], *charsets_list;
-extern my_string mysql_tmpdir;
+ mysql_real_data_home[], *charsets_list, *opt_mysql_tmpdir;
+#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
+extern MY_TMPDIR mysql_tmpdir_list;
extern const char *command_name[];
extern const char *first_keyword, *localhost, *delayed_user;
extern const char **errmesg; /* Error messages */
@@ -667,18 +729,21 @@ extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_enable_named_pipe;
+extern my_bool opt_old_passwords, use_old_passwords;
+extern char *shared_memory_base_name;
+extern bool opt_enable_shared_memory;
extern char f_fyllchar;
extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
extern pthread_key(MEM_ROOT*,THR_MALLOC);
-extern pthread_key(NET*, THR_NET);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
- LOCK_grant, LOCK_error_log, LOCK_delayed_insert,
+ LOCK_error_log, LOCK_delayed_insert,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
LOCK_global_system_variables;
+extern rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
extern I_List<THD> threads;
@@ -686,6 +751,10 @@ extern MY_BITMAP temp_pool;
extern DATE_FORMAT dayord;
extern String empty_string;
extern SHOW_VAR init_vars[],status_vars[], internal_vars[];
+extern struct show_table_type_st table_type_vars[];
+extern SHOW_COMP_OPTION have_isam;
+extern SHOW_COMP_OPTION have_innodb;
+extern SHOW_COMP_OPTION have_berkeley_db;
extern struct system_variables global_system_variables;
extern struct system_variables max_system_variables;
extern struct rand_struct sql_rand;
@@ -728,7 +797,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
void unireg_init(ulong options);
void unireg_end(void);
-int rea_create_table(my_string file_name,HA_CREATE_INFO *create_info,
+int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
uint key_count,KEY *key_info);
int format_number(uint inputflag,uint max_length,my_string pos,uint length,
@@ -753,6 +822,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
bool fuzzy_date);
+void localtime_to_TIME(TIME *to, struct tm *from);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
@@ -761,9 +831,9 @@ void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select,
int use_record_cache, bool print_errors);
void end_read_record(READ_RECORD *info);
-ha_rows filesort(TABLE *form,struct st_sort_field *sortorder, uint s_length,
- SQL_SELECT *select, ha_rows special,ha_rows max_rows,
- ha_rows *examined_rows);
+ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
+ uint s_length, SQL_SELECT *select,
+ ha_rows max_rows, ha_rows *examined_rows);
void change_double_for_sort(double nr,byte *to);
int get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week);
@@ -776,7 +846,7 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);
ulong next_io_size(ulong pos);
-void append_unescaped(String *res,const char *pos);
+void append_unescaped(String *res, const char *pos, uint length);
int create_frm(char *name,uint reclength,uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys);
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
@@ -784,12 +854,8 @@ int rename_file_ext(const char * from,const char * to,const char * ext);
bool check_db_name(char *db);
bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length);
-char *get_field(MEM_ROOT *mem,TABLE *table,uint fieldnr);
-int wild_case_compare(const char *str,const char *wildstr);
-int wild_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape);
-int wild_case_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape);
+char *get_field(MEM_ROOT *mem, Field *field);
+int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
/* from hostname.cc */
struct in_addr;
@@ -808,31 +874,44 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
/* item.cc */
Item *get_system_var(enum_var_type var_type, LEX_STRING name);
-
+Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
+ const char *item_name);
/* log.cc */
bool flush_error_log(void);
/* Some inline functions for more speed */
-inline bool add_item_to_list(Item *item)
+inline bool add_item_to_list(THD *thd, Item *item)
{
- return current_lex->select->item_list.push_back(item);
+ return thd->lex.current_select->add_item_to_list(thd, item);
}
-inline bool add_value_to_list(Item *value)
+
+inline bool add_value_to_list(THD *thd, Item *value)
{
- return current_lex->value_list.push_back(value);
+ return thd->lex.value_list.push_back(value);
}
-inline bool add_order_to_list(Item *item,bool asc)
+
+inline bool add_order_to_list(THD *thd, Item *item, bool asc)
{
- return add_to_list(current_lex->select->order_list,item,asc);
+ return thd->lex.current_select->add_order_to_list(thd, item, asc);
}
-inline bool add_group_to_list(Item *item,bool asc)
+
+inline bool add_group_to_list(THD *thd, Item *item, bool asc)
{
- return add_to_list(current_lex->select->group_list,item,asc);
+ return thd->lex.current_select->add_group_to_list(thd, item, asc);
}
+
inline void mark_as_null_row(TABLE *table)
{
table->null_row=1;
table->status|=STATUS_NULL_ROW;
bfill(table->null_flags,table->null_bytes,255);
}
+
+compare_func_creator comp_eq_creator(bool invert);
+compare_func_creator comp_ge_creator(bool invert);
+compare_func_creator comp_gt_creator(bool invert);
+compare_func_creator comp_le_creator(bool invert);
+compare_func_creator comp_lt_creator(bool invert);
+compare_func_creator comp_ne_creator(bool invert);
+
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 98cb5159e93..147f56b535a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -32,7 +32,8 @@
#include <nisam.h>
#include <thr_alarm.h>
#include <ft_global.h>
-#include <assert.h>
+
+#define mysqld_charset &my_charset_latin1
#ifndef DBUG_OFF
#define ONE_THREAD
@@ -57,7 +58,7 @@ char pstack_file_name[80];
#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
#define HAVE_CLOSE_SERVER_SOCK 1
-#endif
+#endif
extern "C" { // Because of SCO 3.2V4.2
#include <errno.h>
@@ -191,10 +192,11 @@ static char szPipeName [ 257 ];
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
-static pthread_cond_t COND_handler_count;
-static uint handler_count;
+static bool opt_enable_named_pipe = 0;
#endif
#ifdef __WIN__
+static pthread_cond_t COND_handler_count;
+static uint handler_count;
static bool start_mode=0, use_opt_args;
static int opt_argc;
static char **opt_argv;
@@ -257,6 +259,8 @@ SHOW_COMP_OPTION have_crypt=SHOW_OPTION_YES;
SHOW_COMP_OPTION have_crypt=SHOW_OPTION_NO;
#endif
+const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
+
bool opt_large_files= sizeof(my_off_t) > 4;
#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
#define GET_HA_ROWS GET_ULL
@@ -274,7 +278,7 @@ my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted
If set, some standard measures to enforce slave data integrity will not
be performed
*/
-my_bool opt_reckless_slave = 0;
+my_bool opt_reckless_slave = 0;
ulong back_log, connect_timeout, concurrency;
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], time_zone[30];
@@ -302,7 +306,8 @@ static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool lower_case_table_names, opt_old_rpl_compat;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
-my_bool opt_log_slave_updates= 0, opt_console= 0;
+my_bool opt_log_slave_updates= 0, opt_old_passwords=0, use_old_passwords=0;
+my_bool opt_console= 0;
volatile bool mqh_used = 0;
FILE *bootstrap_file=0;
@@ -359,6 +364,15 @@ ulong query_cache_size=0;
ulong query_cache_limit=0;
Query_cache query_cache;
#endif
+arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
+{{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
+ {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
+ {&Arg_comparator::compare_int, &Arg_comparator::compare_e_int},
+ {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row}};
+#ifdef HAVE_SMEM
+char *shared_memory_base_name=default_shared_memory_base_name;
+bool opt_enable_shared_memory = 0;
+#endif
volatile ulong cached_thread_count=0;
@@ -368,7 +382,7 @@ my_string master_user = (char*) "test", master_password = 0, master_host=0,
relay_log_info_file = (char*) "relay-log.info",
master_ssl_key=0, master_ssl_cert=0, master_ssl_capath=0, master_ssl_cipher=0;
my_string report_user = 0, report_password = 0, report_host=0;
-
+
const char *localhost=LOCAL_HOST;
const char *delayed_user="DELAYED";
uint master_port = MYSQL_PORT, master_connect_retry = 60;
@@ -397,7 +411,7 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections,
max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0;
-
+
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN],
mysql_charsets_dir[FN_REFLEN], *charsets_list,
@@ -420,7 +434,8 @@ const char *myisam_recover_options_str="OFF";
const char *sql_mode_str="OFF";
ulong rpl_recovery_rank=0;
-my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL, mysql_tmpdir=NULL;
+my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL;
+MY_TMPDIR mysql_tmpdir_list;
ulong my_bind_addr; /* the address we bind to */
char *my_bind_addr_str;
DATE_FORMAT dayord;
@@ -428,10 +443,14 @@ double log_10[32]; /* 10 potences */
I_List<THD> threads,thread_cache;
time_t start_time;
-ulong opt_sql_mode = 0L;
const char *sql_mode_names[] =
-{ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "SERIALIZE","ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",NullS };
+{
+ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
+ "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS",
+ "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40",
+ NullS
+};
TYPELIB sql_mode_typelib= {array_elements(sql_mode_names)-1,"",
sql_mode_names};
@@ -440,15 +459,14 @@ my_bool use_temp_pool=0;
pthread_key(MEM_ROOT*,THR_MALLOC);
pthread_key(THD*, THR_THD);
-pthread_key(NET*, THR_NET);
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
- LOCK_mapped_file, LOCK_status, LOCK_grant,
+ LOCK_mapped_file, LOCK_status,
LOCK_error_log,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_global_system_variables,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
-
+rw_lock_t LOCK_grant;
pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
COND_slave_start;
pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
@@ -484,6 +502,9 @@ static bool read_init_file(char *file_name);
#ifdef __NT__
extern "C" pthread_handler_decl(handle_connections_namedpipes,arg);
#endif
+#ifdef HAVE_SMEM
+static pthread_handler_decl(handle_connections_shared_memory,arg);
+#endif
extern "C" pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit);
@@ -492,6 +513,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
static void clean_up(bool print_message);
static void clean_up_mutexes(void);
+#ifndef EMBEDDED_LIBRARY
/****************************************************************************
** Code to end mysqld
****************************************************************************/
@@ -565,7 +587,7 @@ static void close_connections(void)
{
HANDLE temp;
DBUG_PRINT( "quit", ("Closing named pipes") );
-
+
/* Create connection to the handle named pipe handler to break the loop */
if ((temp = CreateFile(szPipeName,
GENERIC_READ | GENERIC_WRITE,
@@ -663,6 +685,7 @@ static void close_connections(void)
DBUG_PRINT("quit",("close_connections thread"));
DBUG_VOID_RETURN;
}
+#endif /*EMBEDDED_LIBRARY*/
static void close_server_sock()
@@ -681,7 +704,7 @@ static void close_server_sock()
The following code is disabled for normal systems as it causes MySQL
to hang on AIX 4.3 during shutdown
*/
- DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
+ DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
VOID(closesocket(tmp_sock));
#endif
}
@@ -713,7 +736,7 @@ void kill_mysql(void)
#ifdef SIGNALS_DONT_BREAK_READ
abort_loop=1; // Break connection loops
close_server_sock(); // Force accept to wake up
-#endif
+#endif
#if defined(__WIN__)
#if !defined(EMBEDDED_LIBRARY)
@@ -751,11 +774,10 @@ void kill_mysql(void)
(void*) 0))
sql_print_error("Error: Can't create thread to kill server");
}
-#endif
+#endif
DBUG_VOID_RETURN;
}
-
/* Force server down. kill all connections and threads and exit */
#if defined(OS2) || defined(__NETWARE__)
@@ -771,7 +793,7 @@ static void __cdecl kill_server(int sig_ptr)
{
int sig=(int) (long) sig_ptr; // This is passed a int
DBUG_ENTER("kill_server");
-
+#ifndef EMBEDDED_LIBRARY
// if there is a signal during the kill in progress, ignore the other
if (kill_in_progress) // Safety
RETURN_FROM_KILL_SERVER;
@@ -794,13 +816,14 @@ static void __cdecl kill_server(int sig_ptr)
unireg_abort(1); /* purecov: inspected */
else
unireg_end();
-
#ifdef __NETWARE__
pthread_join(select_thread, NULL); // wait for main thread
#else
pthread_exit(0); /* purecov: deadcode */
#endif /* __NETWARE__ */
+pthread_exit(0); /* purecov: deadcode */
+#endif /* EMBEDDED_LIBRARY */
RETURN_FROM_KILL_SERVER;
}
@@ -891,8 +914,10 @@ void clean_up(bool print_message)
mysql_update_log.cleanup();
mysql_bin_log.cleanup();
+#ifdef HAVE_REPLICATION
if (use_slave_mask)
bitmap_free(&slave_error_mask);
+#endif
acl_free(1);
grant_free();
query_cache_destroy();
@@ -913,13 +938,17 @@ void clean_up(bool print_message)
if (defaults_argv)
free_defaults(defaults_argv);
my_free(charsets_list, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
+ free_tmpdir(&mysql_tmpdir_list);
+#ifdef HAVE_REPLICATION
my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
+#endif
x_free(opt_bin_logname);
x_free(opt_relay_logname);
bitmap_free(&temp_pool);
free_max_user_conn();
+#ifdef HAVE_REPLICATION
end_slave_list();
+#endif
#ifdef HAVE_OPENSSL
free_des_key_file();
#endif /* HAVE_OPENSSL */
@@ -954,7 +983,7 @@ static void clean_up_mutexes()
{
(void) pthread_mutex_destroy(&LOCK_mysql_create_db);
(void) pthread_mutex_destroy(&LOCK_Acl);
- (void) pthread_mutex_destroy(&LOCK_grant);
+ (void) rwlock_destroy(&LOCK_grant);
(void) pthread_mutex_destroy(&LOCK_open);
(void) pthread_mutex_destroy(&LOCK_thread_count);
(void) pthread_mutex_destroy(&LOCK_mapped_file);
@@ -969,7 +998,10 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_bytes_received);
(void) pthread_mutex_destroy(&LOCK_timezone);
(void) pthread_mutex_destroy(&LOCK_user_conn);
+#ifdef HAVE_REPLICATION
(void) pthread_mutex_destroy(&LOCK_rpl_status);
+ (void) pthread_cond_destroy(&COND_rpl_status);
+#endif
(void) pthread_mutex_destroy(&LOCK_active_mi);
(void) pthread_mutex_destroy(&LOCK_global_system_variables);
(void) pthread_cond_destroy(&COND_thread_count);
@@ -977,7 +1009,6 @@ static void clean_up_mutexes()
(void) pthread_cond_destroy(&COND_thread_cache);
(void) pthread_cond_destroy(&COND_flush_thread_cache);
(void) pthread_cond_destroy(&COND_manager);
- (void) pthread_cond_destroy(&COND_rpl_status);
}
/****************************************************************************
@@ -1040,7 +1071,7 @@ static void set_user(const char *user)
{
// allow a numeric uid to be used
const char *pos;
- for (pos=user; isdigit(*pos); pos++) ;
+ for (pos=user; my_isdigit(mysqld_charset,*pos); pos++) ;
if (*pos) // Not numeric id
{
fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
@@ -1083,6 +1114,7 @@ static void set_root(const char *path)
#endif
}
+
static void server_init(void)
{
struct sockaddr_in IPaddr;
@@ -1144,7 +1176,7 @@ static void server_init(void)
if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap &&
opt_enable_named_pipe)
{
- sprintf( szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port );
+ sprintf(szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port );
ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) );
ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) );
if ( !InitializeSecurityDescriptor(&sdPipeDescriptor,
@@ -1194,7 +1226,7 @@ static void server_init(void)
{
DBUG_PRINT("general",("UNIX Socket is %s",mysql_unix_port));
- if ((unix_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
unireg_abort(1); /* purecov: inspected */
@@ -1229,15 +1261,16 @@ static void server_init(void)
void yyerror(const char *s)
{
- NET *net=my_pthread_getspecific_ptr(NET*,THR_NET);
- char *yytext=(char*) current_lex->tok_start;
+ THD *thd=current_thd;
+ char *yytext=(char*) thd->lex.tok_start;
if (!strcmp(s,"parse error"))
s=ER(ER_SYNTAX_ERROR);
- net_printf(net,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
- current_lex->yylineno);
+ net_printf(thd,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
+ thd->lex.yylineno);
}
+#ifndef EMBEDDED_LIBRARY
void close_connection(NET *net,uint errcode,bool lock)
{
st_vio* vio;
@@ -1250,13 +1283,15 @@ void close_connection(NET *net,uint errcode,bool lock)
if ((vio=net->vio) != 0)
{
if (errcode)
- send_error(net,errcode,ER(errcode)); /* purecov: inspected */
+ net_send_error(net,errcode,ER(errcode)); /* purecov: inspected */
vio_close(vio); /* vio is freed in delete thd */
}
if (lock)
(void) pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
}
+#endif /* EMBEDDED_LIBRARY */
+
/* Called when a thread is aborted */
/* ARGSUSED */
@@ -1527,7 +1562,7 @@ extern "C" sig_handler handle_segfault(int sig)
fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
exit(1);
}
-
+
segfaulted = 1;
fprintf(stderr,"\
mysqld got signal %d;\n\
@@ -1552,7 +1587,7 @@ bytes of memory\n", ((ulong) keybuff_size +
thd->variables.sortbuff_size) *
max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
-
+
#if defined(HAVE_LINUXTHREADS)
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
{
@@ -1682,7 +1717,7 @@ static void start_signal_handler(void)
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
- pthread_attr_setstacksize(&thr_attr,32768);
+ pthread_attr_setstacksize(&thr_attr, 129*1024);
#endif
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -1739,8 +1774,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0)
{
char buff[21];
- sprintf(buff,"%lu",(ulong) getpid());
- (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME));
+ ulong length= my_sprintf(buff, (buff,"%lu",(ulong) getpid()));
+ (void) my_write(pidFile, buff, length, MYF(MY_WME));
(void) my_close(pidFile,MYF(0));
}
}
@@ -1845,11 +1880,13 @@ static void check_data_home(const char *path)
extern "C" int my_message_sql(uint error, const char *str,
myf MyFlags __attribute__((unused)))
{
- NET *net;
+ THD *thd;
DBUG_ENTER("my_message_sql");
DBUG_PRINT("error",("Message: '%s'",str));
- if ((net=my_pthread_getspecific_ptr(NET*,THR_NET)))
+ if ((thd=current_thd))
{
+ NET *net= &thd->net;
+ net->report_error= 1;
if (!net->last_error[0]) // Return only first message
{
strmake(net->last_error,str,sizeof(net->last_error)-1);
@@ -1861,17 +1898,6 @@ extern "C" int my_message_sql(uint error, const char *str,
DBUG_RETURN(0);
}
-
-/*
- Forget last error message (if we got one)
-*/
-
-void clear_error_message(THD *thd)
-{
- thd->net.last_error[0]= 0;
-}
-
-
#ifdef __WIN__
struct utsname
@@ -1897,7 +1923,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
#if !defined(EMBEDDED_LIBRARY)
if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
-#endif
+#endif /* EMBEDDED_LIBRARY */
kill_server(MYSQL_KILL_SIGNAL);
return 0;
}
@@ -1914,6 +1940,7 @@ int __stdcall handle_kill(ulong ctrl_type)
}
#endif
+
#ifdef OS2
extern "C" pthread_handler_decl(handle_shutdown,arg)
{
@@ -1981,28 +2008,15 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
}
-
-#ifdef __WIN__
-int win_main(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
+static int init_common_variables(const char *conf_file_name, int argc,
+ char **argv, const char **groups)
{
- DEBUGGER_OFF;
-
my_umask=0660; // Default umask for new files
my_umask_dir=0700; // Default umask for new directories
- MAIN_THD;
- /*
- Initialize signal_th and shutdown_th to main_th for default value
- as we need to initialize them to something safe. They are used
- when compiled with safemalloc.
- */
- SIGNAL_THD;
- SHUTDOWN_THD;
- MY_INIT(argv[0]); // init my_sys library & pthreads
+ umask(((~my_umask) & 0666));
tzset(); // Set tzname
+ max_system_variables.pseudo_thread_id= (ulong)~0;
start_time=time((time_t*) 0);
#ifdef __NETWARE__
@@ -2038,32 +2052,15 @@ int main(int argc, char **argv)
strmov(glob_hostname,"mysql");
strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
+
#ifndef DBUG_OFF
strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
#else
strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
#endif
-#ifdef _CUSTOMSTARTUPCONFIG_
- if (_cust_check_startup())
- {
- /* _cust_check_startup will report startup failure error */
- exit( 1 );
- }
-#endif
- load_defaults(MYSQL_CONFIG_NAME,load_default_groups,&argc,&argv);
- defaults_argv=argv;
-
- /* Get default temporary directory */
- opt_mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
-#if defined( __WIN__) || defined(OS2)
- if (!opt_mysql_tmpdir)
- opt_mysql_tmpdir=getenv("TEMP");
- if (!opt_mysql_tmpdir)
- opt_mysql_tmpdir=getenv("TMP");
-#endif
- if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0])
- opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
+ load_defaults(conf_file_name, groups, &argc, &argv);
+ defaults_argv=argv;
set_options();
get_options(argc,argv);
if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
@@ -2071,11 +2068,48 @@ int main(int argc, char **argv)
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
server_version, SYSTEM_TYPE,MACHINE_TYPE));
- /* These must be set early */
+#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
+ /* connections and databases needs lots of files */
+ {
+ uint wanted_files=10+(uint) max(max_connections*5,
+ max_connections+table_cache_size*2);
+ set_if_bigger(wanted_files, open_files_limit);
+ // Note that some system returns 0 if we succeed here:
+ uint files=set_maximum_open_files(wanted_files);
+ if (files && files < wanted_files && ! open_files_limit)
+ {
+ max_connections= (ulong) min((files-10),max_connections);
+ table_cache_size= (ulong) max((files-10-max_connections)/2,64);
+ DBUG_PRINT("warning",
+ ("Changed limits: max_connections: %ld table_cache: %ld",
+ max_connections,table_cache_size));
+ sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size);
+ }
+ }
+#endif
+ unireg_init(opt_specialflag); /* Set up extern variabels */
+ init_errmessage(); /* Read error messages from file */
+ lex_init();
+ item_init();
+ set_var_init();
+ mysys_uses_curses=0;
+#ifdef USE_REGEX
+ regex_init(&my_charset_latin1);
+#endif
+ if (set_default_charset_by_name(sys_charset.value, MYF(MY_WME)))
+ return 1;
+ charsets_list= list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG));
+
+ if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
+ return 1;
+ return 0;
+}
+
+static int init_thread_environment()
+{
(void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
@@ -2090,21 +2124,38 @@ int main(int argc, char **argv)
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
+ (void) my_rwlock_init(&LOCK_grant, NULL);
(void) pthread_cond_init(&COND_thread_count,NULL);
(void) pthread_cond_init(&COND_refresh,NULL);
(void) pthread_cond_init(&COND_thread_cache,NULL);
(void) pthread_cond_init(&COND_flush_thread_cache,NULL);
(void) pthread_cond_init(&COND_manager,NULL);
+#ifdef HAVE_REPLICATION
+ (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_rpl_status, NULL);
- init_signals();
+#endif
+ /* Parameter for threads created for connections */
+ (void) pthread_attr_init(&connection_attrib);
+ (void) pthread_attr_setdetachstate(&connection_attrib,
+ PTHREAD_CREATE_DETACHED);
+ pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
+ if (!(opt_specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
+
+ if (pthread_key_create(&THR_THD,NULL) ||
+ pthread_key_create(&THR_MALLOC,NULL))
+ {
+ sql_print_error("Can't create thread-keys");
+ return 1;
+ }
+ return 0;
+}
- if (set_default_charset_by_name(sys_charset.value, MYF(MY_WME)))
- exit(1);
- charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));
+static void init_ssl()
+{
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
{
@@ -2116,81 +2167,14 @@ int main(int argc, char **argv)
if (!ssl_acceptor_fd)
opt_use_ssl = 0;
}
+ if (des_key_file)
+ load_des_key_file(des_key_file);
#endif /* HAVE_OPENSSL */
+}
-#ifdef HAVE_LIBWRAP
- libwrapName= my_progname+dirname_length(my_progname);
- openlog(libwrapName, LOG_PID, LOG_AUTH);
-#endif
-
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
- /* Parameter for threads created for connections */
- (void) pthread_attr_init(&connection_attrib);
- (void) pthread_attr_setdetachstate(&connection_attrib,
- PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&connection_attrib,thread_stack);
- {
- /* Retrieve used stack size; Needed for checking stack overflows */
- size_t stack_size;
- pthread_attr_getstacksize(&connection_attrib, &stack_size);
- if (global_system_variables.log_warnings && stack_size != thread_stack)
- {
- sql_print_error("Warning: Asked for %ld thread stack, but got %ld",
- thread_stack, stack_size);
- thread_stack= stack_size;
- }
- }
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
- pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
-
-#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
- /* connections and databases needs lots of files */
- {
- uint wanted_files=10+(uint) max(max_connections*5,
- max_connections+table_cache_size*2);
- set_if_bigger(wanted_files, open_files_limit);
- // Note that some system returns 0 if we succeed here:
- uint files=set_maximum_open_files(wanted_files);
- if (files && files < wanted_files && ! open_files_limit)
- {
- max_connections= (ulong) min((files-10),max_connections);
- table_cache_size= (ulong) max((files-10-max_connections)/2,64);
- DBUG_PRINT("warning",
- ("Changed limits: max_connections: %ld table_cache: %ld",
- max_connections,table_cache_size));
- sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size);
- }
- }
-#endif
- unireg_init(opt_specialflag); /* Set up extern variabels */
- init_errmessage(); /* Read error messages from file */
- lex_init();
- item_init();
- set_var_init();
- mysys_uses_curses=0;
-#ifdef USE_REGEX
- regex_init();
-#endif
- select_thread=pthread_self();
- select_thread_in_use=1;
- if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
- unireg_abort(1);
- /*
- We have enough space for fiddling with the argv, continue
- */
- umask(((~my_umask) & 0666));
- check_data_home(mysql_real_data_home);
- if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
- {
- unireg_abort(1); /* purecov: inspected */
- }
- mysql_data_home= mysql_data_home_buff;
- mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
- mysql_data_home[1]=0;
- server_init();
+static int init_server_components()
+{
table_cache_init();
hostname_cache_init();
query_cache_result_size_limit(query_cache_limit);
@@ -2198,12 +2182,9 @@ int main(int argc, char **argv)
randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
reset_floating_point_exceptions();
init_thr_lock();
+#ifdef HAVE_REPLICATION
init_slave_list();
-#ifdef HAVE_OPENSSL
- if (des_key_file)
- load_des_key_file(des_key_file);
-#endif /* HAVE_OPENSSL */
-
+#endif
/* Setup log files */
if (opt_log)
open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
@@ -2214,11 +2195,17 @@ int main(int argc, char **argv)
NullS, LOG_NEW);
using_update_log=1;
}
-
if (opt_slow_log)
open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
NullS, LOG_NORMAL);
+ if (opt_bin_log)
+ {
+ open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
+ opt_binlog_index_name,LOG_BIN);
+ using_update_log=1;
+ }
+
if (opt_error_log)
{
if (!log_error_file_ptr[0])
@@ -2234,14 +2221,16 @@ int main(int argc, char **argv)
freopen(log_error_file, "a+", stderr);
}
}
+
if (ha_init())
{
sql_print_error("Can't init databases");
- if (unix_sock != INVALID_SOCKET)
- unlink(mysql_unix_port);
unireg_abort(1);
}
+ if (opt_myisam_log)
+ (void) mi_log(1);
ha_key_cache();
+
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !geteuid())
{
@@ -2256,13 +2245,205 @@ int main(int argc, char **argv)
locked_in_memory=0;
#endif
- if (opt_myisam_log)
- (void) mi_log(1);
ft_init_stopwords();
+ init_max_user_conn();
+ init_update_queries();
+ return 0;
+}
+
+
+static void create_maintenance_thread()
+{
+ if (
+#ifdef HAVE_BERKELEY_DB
+ !berkeley_skip ||
+#endif
+ (flush_time && flush_time != ~(ulong) 0L))
+ {
+ pthread_t hThread;
+ if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
+ sql_print_error("Warning: Can't create thread to manage maintenance");
+ }
+}
+
+
+static void create_shutdown_thread()
+{
+#ifdef __WIN__
+ hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
+ pthread_t hThread;
+ if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
+ sql_print_error("Warning: Can't create thread to handle shutdown requests");
+
+ // On "Stop Service" we have to do regular shutdown
+ Service.SetShutdownEvent(hEventShutdown);
+#endif
+#ifdef OS2
+ pthread_cond_init(&eventShutdown, NULL);
+ pthread_t hThread;
+ if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
+ sql_print_error("Warning: Can't create thread to handle shutdown requests");
+#endif
+}
+
+
+#if defined(__NT__) || defined(HAVE_SMEM)
+static void handle_connections_methods()
+{
+ pthread_t hThread;
+ DBUG_ENTER("handle_connections_methods");
+#ifdef __NT__
+ if (hPipe == INVALID_HANDLE_VALUE &&
+ (!have_tcpip || opt_disable_networking) &&
+ !opt_enable_shared_memory)
+ {
+ sql_print_error("TCP/IP,--shared-memory or --named-pipe should be configured on NT OS");
+ unireg_abort(1); // Will not return
+ }
+#endif
+
+ pthread_mutex_lock(&LOCK_thread_count);
+ (void) pthread_cond_init(&COND_handler_count,NULL);
+ handler_count=0;
+#ifdef __NT__
+ if (hPipe != INVALID_HANDLE_VALUE)
+ {
+ handler_count++;
+ if (pthread_create(&hThread,&connection_attrib,
+ handle_connections_namedpipes, 0))
+ {
+ sql_print_error("Warning: Can't create thread to handle named pipes");
+ handler_count--;
+ }
+ }
+#endif /* __NT__ */
+ if (have_tcpip && !opt_disable_networking)
+ {
+ handler_count++;
+ if (pthread_create(&hThread,&connection_attrib,
+ handle_connections_sockets, 0))
+ {
+ sql_print_error("Warning: Can't create thread to handle TCP/IP");
+ handler_count--;
+ }
+ }
+#ifdef HAVE_SMEM
+ if (opt_enable_shared_memory)
+ {
+ handler_count++;
+ if (pthread_create(&hThread,&connection_attrib,
+ handle_connections_shared_memory, 0))
+ {
+ sql_print_error("Warning: Can't create thread to handle shared memory");
+ handler_count--;
+ }
+ }
+#endif
+
+ while (handler_count > 0)
+ pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
+ pthread_mutex_unlock(&LOCK_thread_count);
+ DBUG_VOID_RETURN;
+}
+#endif /* defined(__NT__) || defined(HAVE_SMEM) */
+
+
+#ifndef EMBEDDED_LIBRARY
+#ifdef __WIN__
+int win_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+ DEBUGGER_OFF;
+
+ MY_INIT(argv[0]); // init my_sys library & pthreads
+
+#ifdef _CUSTOMSTARTUPCONFIG_
+ if (_cust_check_startup())
+ {
+ / * _cust_check_startup will report startup failure error * /
+ exit( 1 );
+ }
+#endif
+
+ if (init_common_variables(MYSQL_CONFIG_NAME,
+ argc, argv, load_default_groups))
+ unireg_abort(1); // Will do exit
+
+ init_signals();
+ if (!(opt_specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
+ if (init_thread_environment())
+ unireg_abort(1);
+ pthread_attr_setstacksize(&connection_attrib,thread_stack);
+ {
+ /* Retrieve used stack size; Needed for checking stack overflows */
+ size_t stack_size;
+ pthread_attr_getstacksize(&connection_attrib, &stack_size);
+ if (global_system_variables.log_warnings && stack_size != thread_stack)
+ {
+ sql_print_error("Warning: Asked for %ld thread stack, but got %ld",
+ thread_stack, stack_size);
+ thread_stack= stack_size;
+ }
+ }
+ (void) thr_setconcurrency(concurrency); // 10 by default
+
+ select_thread=pthread_self();
+ select_thread_in_use=1;
+ init_ssl();
+
+#ifdef HAVE_LIBWRAP
+ libwrapName= my_progname+dirname_length(my_progname);
+ openlog(libwrapName, LOG_PID, LOG_AUTH);
+#endif
+
+ /*
+ We have enough space for fiddling with the argv, continue
+ */
+ check_data_home(mysql_real_data_home);
+ if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
+ {
+ unireg_abort(1); /* purecov: inspected */
+ }
+ mysql_data_home= mysql_data_home_buff;
+ mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
+ mysql_data_home[1]=0;
+ server_init();
+
+ if (opt_bin_log && !server_id)
+ {
+ server_id= !master_host ? 1 : 2;
+#ifdef EXTRA_DEBUG
+ switch (server_id) {
+ case 1:
+ sql_print_error("\
+Warning: You have enabled the binary log, but you haven't set server-id:\n\
+Updates will be logged to the binary log, but connections to slaves will\n\
+not be accepted.");
+ break;
+ case 2:
+ sql_print_error("\
+Warning: You should set server-id to a non-0 value if master_host is set.\n\
+The server will not act as a slave.");
+ break;
+ }
+#endif
+ }
+
+ if (init_server_components())
+ exit(1);
+
#ifdef __WIN__
+#define MYSQL_ERR_FILE "mysql.err"
if (!opt_console)
+ {
+ freopen(MYSQL_ERR_FILE,"a+",stdout);
+ freopen(MYSQL_ERR_FILE,"a+",stderr);
FreeConsole(); // Remove window
+ }
#endif
/*
@@ -2270,16 +2451,8 @@ int main(int argc, char **argv)
After this we can't quit by a simple unireg_abort
*/
error_handler_hook = my_message_sql;
- if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
- pthread_key_create(&THR_MALLOC,NULL))
- {
- sql_print_error("Can't create thread-keys");
- if (unix_sock != INVALID_SOCKET)
- unlink(mysql_unix_port);
- unireg_abort(1);
- }
start_signal_handler(); // Creates pidfile
- if (acl_init((THD*) 0, opt_noacl))
+ if (acl_init((THD *)0, opt_noacl))
{
abort_loop=1;
select_thread_in_use=0;
@@ -2292,13 +2465,10 @@ int main(int argc, char **argv)
#endif
if (unix_sock != INVALID_SOCKET)
unlink(mysql_unix_port);
- unireg_abort(1);
+ exit(1);
}
if (!opt_noacl)
- (void) grant_init((THD*) 0);
- init_max_user_conn();
- init_update_queries();
- DBUG_ASSERT(current_thd == 0);
+ (void) grant_init((THD *)0);
#ifdef HAVE_DLOPEN
if (!opt_noacl)
@@ -2307,34 +2477,6 @@ int main(int argc, char **argv)
/* init_slave() must be called after the thread keys are created */
init_slave();
- DBUG_ASSERT(current_thd == 0);
- if (opt_bin_log && !server_id)
- {
- server_id= !master_host ? 1 : 2;
- switch (server_id) {
-#ifdef EXTRA_DEBUG
- case 1:
- sql_print_error("\
-Warning: You have enabled the binary log, but you haven't set server-id:\n\
-Updates will be logged to the binary log, but connections to slaves will\n\
-not be accepted.");
- break;
-#endif
- case 2:
- sql_print_error("\
-Warning: You should set server-id to a non-0 value if master_host is set.\n\
-The server will not act as a slave.");
- break;
- }
- }
- if (opt_bin_log)
- {
- open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
- opt_binlog_index_name,LOG_BIN);
- using_update_log=1;
- }
-
-
if (opt_bootstrap)
{
int error=bootstrap(stdin);
@@ -2349,87 +2491,19 @@ The server will not act as a slave.");
unireg_abort(1);
}
}
- (void) thr_setconcurrency(concurrency); // 10 by default
-#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) //IRENA
- {
- hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
- sql_print_error("Warning: Can't create thread to handle shutdown requests");
- // On "Stop Service" we have to do regular shutdown
- Service.SetShutdownEvent(hEventShutdown);
- }
-#endif
-#ifdef OS2
- {
- pthread_cond_init( &eventShutdown, NULL);
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
- sql_print_error("Warning: Can't create thread to handle shutdown requests");
- }
-#endif
-
- if (
-#ifdef HAVE_BERKELEY_DB
- !berkeley_skip ||
-#endif
- (flush_time && flush_time != ~(ulong) 0L))
- {
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
- sql_print_error("Warning: Can't create thread to manage maintenance");
- }
+ create_shutdown_thread();
+ create_maintenance_thread();
printf(ER(ER_READY),my_progname,server_version,
((unix_sock == INVALID_SOCKET) ? (char*) "" : mysql_unix_port),
mysql_port);
fflush(stdout);
-#ifdef __NT__
- if (hPipe == INVALID_HANDLE_VALUE &&
- (!have_tcpip || opt_disable_networking))
- {
- sql_print_error("TCP/IP or --enable-named-pipe should be configured on NT OS");
- unireg_abort(1);
- }
- else
- {
- pthread_mutex_lock(&LOCK_thread_count);
- (void) pthread_cond_init(&COND_handler_count,NULL);
- {
- pthread_t hThread;
- handler_count=0;
- if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_namedpipes, 0))
- {
- sql_print_error("Warning: Can't create thread to handle named pipes");
- handler_count--;
- }
- }
- if (have_tcpip && !opt_disable_networking)
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_sockets, 0))
- {
- sql_print_error("Warning: Can't create thread to handle named pipes");
- handler_count--;
- }
- }
- while (handler_count > 0)
- pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
- }
- pthread_mutex_unlock(&LOCK_thread_count);
- }
+#if defined(__NT__) || defined(HAVE_SMEM)
+ handle_connections_methods();
#else
handle_connections_sockets(0);
-#ifdef EXTRA_DEBUG2
- sql_print_error("Exiting main thread");
-#endif
#endif /* __NT__ */
/* (void) pthread_attr_destroy(&connection_attrib); */
@@ -2487,6 +2561,8 @@ The server will not act as a slave.");
return(0); /* purecov: deadcode */
}
+#endif /* EMBEDDED_LIBRARY */
+
/****************************************************************************
Main and thread entry function for Win32
@@ -2508,7 +2584,7 @@ int mysql_service(void *p)
SYNOPSIS
default_service_handling()
- argv Pointer to argument list
+ argv Pointer to argument list
servicename Internal name of service
displayname Display name of service (in taskbar ?)
file_path Path to this program
@@ -2559,7 +2635,7 @@ int main(int argc, char **argv)
fn_format(file_path,argv[0],file_path,"",1+4+16); /* Force full path */
if (argc == 2)
- {
+ {
if (!default_service_handling(argv,MYSQL_SERVICENAME, MYSQL_SERVICENAME,
file_path))
return 0;
@@ -2628,10 +2704,11 @@ int main(int argc, char **argv)
static int bootstrap(FILE *file)
{
- THD *thd= new THD;
- int error;
+ THD *thd;
+ int error= 0;
DBUG_ENTER("bootstrap");
-
+#ifndef EMBEDDED_LIBRARY // TODO: Enable this
+ thd= new THD;
thd->bootstrap=1;
thd->client_capabilities=0;
my_net_init(&thd->net,(st_vio*) 0);
@@ -2644,7 +2721,7 @@ static int bootstrap(FILE *file)
if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap,
(void*) thd))
{
- sql_print_error("Warning: Can't create thread to handle bootstrap");
+ sql_print_error("Warning: Can't create thread to handle bootstrap");
DBUG_RETURN(-1);
}
/* Wait for thread to die */
@@ -2655,13 +2732,15 @@ static int bootstrap(FILE *file)
DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
}
(void) pthread_mutex_unlock(&LOCK_thread_count);
- error= thd->fatal_error;
+ error= thd->is_fatal_error;
net_end(&thd->net);
thd->cleanup();
delete thd;
+#endif /* EMBEDDED_LIBRARY */
DBUG_RETURN(error);
}
+
static bool read_init_file(char *file_name)
{
FILE *file;
@@ -2675,6 +2754,7 @@ static bool read_init_file(char *file_name)
}
+#ifndef EMBEDDED_LIBRARY
static void create_new_thread(THD *thd)
{
DBUG_ENTER("create_new_thread");
@@ -2699,6 +2779,9 @@ static void create_new_thread(THD *thd)
for (uint i=0; i < 8 ; i++) // Generate password teststring
thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
thd->scramble[8]=0;
+ // Back it up as old clients may need it
+ memcpy(thd->old_scramble,thd->scramble,9);
+
thd->real_id=pthread_self(); // Keep purify happy
@@ -2738,7 +2821,7 @@ static void create_new_thread(THD *thd)
thread_count--;
thd->killed=1; // Safety
(void) pthread_mutex_unlock(&LOCK_thread_count);
- net_printf(net,ER_CANT_CREATE_THREAD,error);
+ net_printf(thd,ER_CANT_CREATE_THREAD,error);
(void) pthread_mutex_lock(&LOCK_thread_count);
close_connection(net,0,0);
delete thd;
@@ -2752,6 +2835,8 @@ static void create_new_thread(THD *thd)
DBUG_PRINT("info",("Thread created"));
DBUG_VOID_RETURN;
}
+#endif /* EMBEDDED_LIBRARY */
+
#ifdef SIGNALS_DONT_BREAK_READ
inline void kill_broken_server()
@@ -2774,6 +2859,7 @@ inline void kill_broken_server()
/* Handle new connections and spawn new process to handle them */
+#ifndef EMBEDDED_LIBRARY
extern "C" pthread_handler_decl(handle_connections_sockets,
arg __attribute__((unused)))
{
@@ -3072,31 +3158,248 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
#endif /* __NT__ */
-/******************************************************************************
-** handle start options
+/*
+ Thread of shared memory's service
+
+ SYNOPSIS
+ pthread_handler_decl()
+ handle_connections_shared_memory Thread handle
+ arg Arguments of thread
+*/
+
+#ifdef HAVE_SMEM
+pthread_handler_decl(handle_connections_shared_memory,arg)
+{
+/*
+ event_connect_request is event object for start connection actions
+ event_connect_answer is event object for confirm, that server put data
+ handle_connect_file_map is file-mapping object, use for create shared memory
+ handle_connect_map is pointer on shared memory
+ handle_map is pointer on shared memory for client
+ event_server_wrote,
+ event_server_read,
+ event_client_wrote,
+ event_client_read are events for transfer data between server and client
+ handle_file_map is file-mapping object, use for create shared memory
+*/
+ HANDLE handle_connect_file_map = NULL;
+ char *handle_connect_map = NULL;
+ HANDLE event_connect_request = NULL;
+ HANDLE event_connect_answer = NULL;
+ ulong smem_buffer_length = shared_memory_buffer_length + 4;
+ ulong connect_number = 1;
+ my_bool error_allow;
+ THD *thd;
+ char tmp[63];
+ char *suffix_pos;
+ char connect_number_char[22], *p;
+
+ my_thread_init();
+ DBUG_ENTER("handle_connections_shared_memorys");
+ DBUG_PRINT("general",("Waiting for allocated shared memory."));
+
+
+ /*
+ The name of event and file-mapping events create agree next rule:
+ shared_memory_base_name+unique_part
+ Where:
+ shared_memory_base_name is unique value for each server
+ unique_part is unique value for each object (events and file-mapping)
+ */
+ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS);
+ strmov(suffix_pos, "CONNECT_REQUEST");
+ if ((event_connect_request = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create shared memory service ! The request event don't create.");
+ goto error;
+ }
+ strmov(suffix_pos, "CONNECT_ANSWER");
+ if ((event_connect_answer = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create shared memory service ! The answer event don't create.");
+ goto error;
+ }
+ strmov(suffix_pos, "CONNECT_DATA");
+ if ((handle_connect_file_map = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,
+ 0,sizeof(connect_number),tmp)) == 0)
+ {
+ sql_perror("Can't create shared memory service ! File mapping don't create.");
+ goto error;
+ }
+ if ((handle_connect_map = (char *)MapViewOfFile(handle_connect_file_map,FILE_MAP_WRITE,0,0,
+ sizeof(DWORD))) == 0)
+ {
+ sql_perror("Can't create shared memory service ! Map of memory don't create.");
+ goto error;
+ }
+
+
+ while (!abort_loop)
+ {
+/*
+ Wait a request from client
+*/
+ WaitForSingleObject(event_connect_request,INFINITE);
+ error_allow = FALSE;
+
+ HANDLE handle_client_file_map = NULL;
+ char *handle_client_map = NULL;
+ HANDLE event_client_wrote = NULL;
+ HANDLE event_client_read = NULL;
+ HANDLE event_server_wrote = NULL;
+ HANDLE event_server_read = NULL;
+
+ p = int2str(connect_number, connect_number_char, 10);
+/*
+ The name of event and file-mapping events create agree next rule:
+ shared_memory_base_name+unique_part+number_of_connection
+ Where:
+ shared_memory_base_name is uniquel value for each server
+ unique_part is unique value for each object (events and file-mapping)
+ number_of_connection is number of connection between server and client
+*/
+ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char,"_",NullS);
+ strmov(suffix_pos, "DATA");
+ if ((handle_client_file_map = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,
+ PAGE_READWRITE,0,smem_buffer_length,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! File mapping don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+ if ((handle_client_map = (char*)MapViewOfFile(handle_client_file_map,FILE_MAP_WRITE,0,0,smem_buffer_length)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! Map of memory don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "CLIENT_WROTE");
+ if ((event_client_wrote = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! CW event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "CLIENT_READ");
+ if ((event_client_read = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! CR event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "SERVER_READ");
+ if ((event_server_read = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! SR event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "SERVER_WROTE");
+ if ((event_server_wrote = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! SW event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ if (abort_loop) break;
+ if ( !(thd = new THD))
+ {
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+/*
+Send number of connection to client
+*/
+ int4store(handle_connect_map, connect_number);
+
+/*
+ Send number of connection to client
+*/
+ if (!SetEvent(event_connect_answer))
+ {
+ sql_perror("Can't create connection with client in shared memory service ! Can't send answer event.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+/*
+ Set event that client should receive data
+*/
+ if (!SetEvent(event_client_read))
+ {
+ sql_perror("Can't create connection with client in shared memory service ! Can't set client to read's mode.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+ if (!(thd->net.vio = vio_new_win32shared_memory(&thd->net,handle_client_file_map,handle_client_map,event_client_wrote,
+ event_client_read,event_server_wrote,event_server_read)) ||
+ my_net_init(&thd->net, thd->net.vio))
+ {
+ close_connection(&thd->net,ER_OUT_OF_RESOURCES);
+ delete thd;
+ error_allow = TRUE;
+ }
+ /* host name is unknown */
+errorconn:
+ if (error_allow)
+ {
+ if (!handle_client_map) UnmapViewOfFile(handle_client_map);
+ if (!handle_client_file_map) CloseHandle(handle_client_file_map);
+ if (!event_server_wrote) CloseHandle(event_server_wrote);
+ if (!event_server_read) CloseHandle(event_server_read);
+ if (!event_client_wrote) CloseHandle(event_client_wrote);
+ if (!event_client_read) CloseHandle(event_client_read);
+ continue;
+ }
+ thd->host = my_strdup(localhost,MYF(0)); /* Host is unknown */
+ create_new_thread(thd);
+ uint4korr(connect_number++);
+ }
+error:
+ if (!handle_connect_map) UnmapViewOfFile(handle_connect_map);
+ if (!handle_connect_file_map) CloseHandle(handle_connect_file_map);
+ if (!event_connect_answer) CloseHandle(event_connect_answer);
+ if (!event_connect_request) CloseHandle(event_connect_request);
+ pthread_mutex_lock(&LOCK_thread_count);
+ pthread_mutex_unlock(&LOCK_thread_count);
+ DBUG_RETURN(0);
+}
+#endif /* HAVE_SMEM */
+#endif /* EMBEDDED_LIBRARY */
+
+
+/****************************************************************************
+ Handle start options
******************************************************************************/
-enum options {
- OPT_ISAM_LOG=256, OPT_SKIP_NEW,
- OPT_SKIP_GRANT, OPT_SKIP_LOCK,
+enum options
+{
+ OPT_ISAM_LOG=256, OPT_SKIP_NEW,
+ OPT_SKIP_GRANT, OPT_SKIP_LOCK,
OPT_ENABLE_LOCK, OPT_USE_LOCKING,
- OPT_SOCKET, OPT_UPDATE_LOG,
- OPT_BIN_LOG, OPT_SKIP_RESOLVE,
+ OPT_SOCKET, OPT_UPDATE_LOG,
+ OPT_BIN_LOG, OPT_SKIP_RESOLVE,
OPT_SKIP_NETWORKING, OPT_BIN_LOG_INDEX,
OPT_BIND_ADDRESS, OPT_PID_FILE,
- OPT_SKIP_PRIOR, OPT_BIG_TABLES,
+ OPT_SKIP_PRIOR, OPT_BIG_TABLES,
OPT_STANDALONE, OPT_ONE_THREAD,
OPT_CONSOLE, OPT_LOW_PRIORITY_UPDATES,
- OPT_SKIP_HOST_CACHE, OPT_LONG_FORMAT,
- OPT_FLUSH, OPT_SAFE,
+ OPT_SKIP_HOST_CACHE, OPT_LONG_FORMAT,
+ OPT_FLUSH, OPT_SAFE,
OPT_BOOTSTRAP, OPT_SKIP_SHOW_DB,
- OPT_TABLE_TYPE, OPT_INIT_FILE,
- OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG,
+ OPT_TABLE_TYPE, OPT_INIT_FILE,
+ OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG,
OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR,
- OPT_BDB_HOME, OPT_BDB_LOG,
+ OPT_BDB_HOME, OPT_BDB_LOG,
OPT_BDB_TMP, OPT_BDB_NOSYNC,
- OPT_BDB_LOCK, OPT_BDB_SKIP,
- OPT_BDB_NO_RECOVER, OPT_BDB_SHARED,
+ OPT_BDB_LOCK, OPT_BDB_SKIP,
+ OPT_BDB_NO_RECOVER, OPT_BDB_SHARED,
OPT_MASTER_HOST, OPT_MASTER_USER,
OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
@@ -3104,26 +3407,26 @@ enum options {
OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
OPT_MASTER_SSL_CIPHER,
- OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
+ OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
OPT_WANT_CORE, OPT_CONCURRENT_INSERT,
OPT_MEMLOCK, OPT_MYISAM_RECOVER,
- OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID,
+ OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID,
OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE,
- OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE,
- OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE,
- OPT_REPLICATE_WILD_IGNORE_TABLE,
- OPT_DISCONNECT_SLAVE_EVENT_COUNT,
+ OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE,
+ OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE,
+ OPT_REPLICATE_WILD_IGNORE_TABLE,
+ OPT_DISCONNECT_SLAVE_EVENT_COUNT,
OPT_ABORT_SLAVE_EVENT_COUNT,
OPT_INNODB_DATA_HOME_DIR,
OPT_INNODB_DATA_FILE_PATH,
- OPT_INNODB_LOG_GROUP_HOME_DIR,
- OPT_INNODB_LOG_ARCH_DIR,
- OPT_INNODB_LOG_ARCHIVE,
- OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
- OPT_INNODB_FLUSH_METHOD,
- OPT_INNODB_FAST_SHUTDOWN,
+ OPT_INNODB_LOG_GROUP_HOME_DIR,
+ OPT_INNODB_LOG_ARCH_DIR,
+ OPT_INNODB_LOG_ARCHIVE,
+ OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
+ OPT_INNODB_FLUSH_METHOD,
+ OPT_INNODB_FAST_SHUTDOWN,
OPT_SAFE_SHOW_DB,
OPT_INNODB_SKIP, OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION,
@@ -3155,11 +3458,12 @@ enum options {
OPT_MAX_JOIN_SIZE, OPT_MAX_SORT_LENGTH,
OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
+ OPT_MAX_ERROR_COUNT, OPT_MAX_PREP_STMT,
OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
- OPT_OPEN_FILES_LIMIT,
+ OPT_OPEN_FILES_LIMIT,
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_SIZE,
OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT,
@@ -3173,6 +3477,7 @@ enum options {
OPT_INNODB_LOG_FILE_SIZE,
OPT_INNODB_LOG_BUFFER_SIZE,
OPT_INNODB_BUFFER_POOL_SIZE,
+ OPT_INNODB_BUFFER_POOL_AWE_MEM_MB,
OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
OPT_INNODB_FILE_IO_THREADS,
OPT_INNODB_LOCK_WAIT_TIMEOUT,
@@ -3182,7 +3487,10 @@ enum options {
OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK,
OPT_ERROR_LOG_FILE,
- OPT_AUTOCLOSE
+ OPT_AUTOCLOSE,
+ OPT_ENABLE_SHARED_MEMORY,
+ OPT_SHARED_MEMORY_BASE_NAME,
+ OPT_OLD_PASSWORDS
};
@@ -3222,13 +3530,13 @@ struct my_option my_long_options[] =
#endif /* HAVE_BERKELEY_DB */
{"skip-bdb", OPT_BDB_SKIP, "Don't use berkeley db (will save memory)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"big-tables", OPT_BIG_TABLES,
+ {"big-tables", OPT_BIG_TABLES,
"Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"binlog-do-db", OPT_BINLOG_DO_DB,
"Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
+ {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
"Tells the master that updates to the given database should not be logged tothe binary log",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bind-address", OPT_BIND_ADDRESS, "IP address to bind to",
@@ -3264,7 +3572,7 @@ struct my_option my_long_options[] =
#endif
#endif
#ifdef HAVE_OPENSSL
- {"des-key-file", OPT_DES_KEY_FILE,
+ {"des-key-file", OPT_DES_KEY_FILE,
"Load keys for des_encrypt() and des_encrypt from given file",
(gptr*) &des_key_file, (gptr*) &des_key_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
@@ -3292,6 +3600,11 @@ struct my_option my_long_options[] =
{"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure",
(gptr*) &opt_do_pstack, (gptr*) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared-memory", OPT_ENABLE_SHARED_MEMORY,
+ "Enable the shared memory.",(gptr*) &opt_enable_shared_memory, (gptr*) &opt_enable_shared_memory,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0,
GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"flush", OPT_FLUSH, "Flush tables to disk between SQL commands", 0, 0, 0,
@@ -3309,7 +3622,7 @@ struct my_option my_long_options[] =
(gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
0},
{"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR,
- "Path to innodb log files.", (gptr*) &innobase_log_group_home_dir,
+ "Path to innodb log files.", (gptr*) &innobase_log_group_home_dir,
(gptr*) &innobase_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
0, 0},
{"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,
@@ -3369,7 +3682,7 @@ struct my_option my_long_options[] =
{"log-long-format", OPT_LONG_FORMAT,
"Log some extra information to update log", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
- {"log-slave-updates", OPT_LOG_SLAVE_UPDATES,
+ {"log-slave-updates", OPT_LOG_SLAVE_UPDATES,
"Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.",
(gptr*) &opt_log_slave_updates, (gptr*) &opt_log_slave_updates, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -3378,7 +3691,7 @@ struct my_option my_long_options[] =
(gptr*) &global_system_variables.low_priority_updates,
(gptr*) &max_system_variables.low_priority_updates,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"master-host", OPT_MASTER_HOST,
+ {"master-host", OPT_MASTER_HOST,
"Master hostname or IP address for replication. If not set, the slave thread will not be started. Note that the setting of master-host will be ignored if there exists a valid master.info file.",
(gptr*) &master_host, (gptr*) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
0, 0, 0, 0},
@@ -3431,6 +3744,7 @@ struct my_option my_long_options[] =
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"memlock", OPT_MEMLOCK, "Lock mysqld in memory", (gptr*) &locked_in_memory,
(gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_REPLICATION
{"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT,
"Option used by mysql-test for debugging and testing of replication",
(gptr*) &disconnect_slave_event_count,
@@ -3449,6 +3763,7 @@ struct my_option my_long_options[] =
(gptr*) &opt_sporadic_binlog_dump_fail,
(gptr*) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
+#endif /* HAVE_REPLICATION */
{"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT,
"Simulate memory shortage when compiled with the --with-debug=full option",
0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -3527,6 +3842,8 @@ struct my_option my_long_options[] =
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients)",
+ (gptr*) &opt_old_passwords, (gptr*) &opt_old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB,
"Deprecated option; One should use GRANT SHOW DATABASES instead...",
@@ -3543,6 +3860,11 @@ struct my_option my_long_options[] =
{"set-variable", 'O',
"Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name",OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO,
"Show user and password in SHOW SLAVE STATUS",
(gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0,
@@ -3587,12 +3909,14 @@ struct my_option my_long_options[] =
{"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, "Undocumented",
(gptr*) &relay_log_info_file, (gptr*) &relay_log_info_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_REPLICATION
{"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, "Undocumented",
(gptr*) &slave_load_tmpdir, (gptr*) &slave_load_tmpdir, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS,
"Tells the slave thread to continue replication when a query returns an error from the provided list",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"socket", OPT_SOCKET, "Socket file to use for connection",
(gptr*) &mysql_unix_port, (gptr*) &mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -3607,11 +3931,19 @@ struct my_option my_long_options[] =
#ifdef HAVE_OPENSSL
#include "sslopt-longopts.h"
#endif
- {"temp-pool", OPT_TEMP_POOL,
+ {"temp-pool", OPT_TEMP_POOL,
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
(gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
- {"tmpdir", 't', "Path for temporary files", (gptr*) &opt_mysql_tmpdir,
+ {"tmpdir", 't',
+ "Path for temporary files. Several paths may be specified, separated by a "
+#if defined( __WIN__) || defined(OS2)
+ "semicolon (;)"
+#else
+ "colon (:)"
+#endif
+ ", in this case they are used in a round-robin fashion.",
+ (gptr*) &opt_mysql_tmpdir,
(gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"transaction-isolation", OPT_TX_ISOLATION,
"Default transaction isolation level", 0, 0, 0, GET_STR, REQUIRED_ARG, 0,
@@ -3664,7 +3996,7 @@ struct my_option my_long_options[] =
"The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.",
(gptr*) &binlog_cache_size, (gptr*) &binlog_cache_size, 0, GET_ULONG,
REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0},
- {"connect_timeout", OPT_CONNECT_TIMEOUT,
+ {"connect_timeout", OPT_CONNECT_TIMEOUT,
"The number of seconds the mysqld server is waiting for a connect packet before responding with Bad handshake",
(gptr*) &connect_timeout, (gptr*) &connect_timeout,
0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
@@ -3702,7 +4034,7 @@ struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_INNOBASE_DB
{"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS,
- "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
+ "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
(gptr*) &innobase_mirrored_log_groups,
(gptr*) &innobase_mirrored_log_groups, 0, GET_LONG, REQUIRED_ARG, 1, 1, 10,
0, 1, 0},
@@ -3722,6 +4054,10 @@ struct my_option my_long_options[] =
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
(gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
GET_LONG, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, ~0L, 0, 1024*1024L, 0},
+ {"innodb_buffer_pool_awe_mem_mb", OPT_INNODB_BUFFER_POOL_AWE_MEM_MB,
+ "If Windows AWE is used, the size of InnoDB buffer pool allocated from the AWE memory.",
+ (gptr*) &innobase_buffer_pool_awe_mem_mb, (gptr*) &innobase_buffer_pool_awe_mem_mb, 0,
+ GET_LONG, REQUIRED_ARG, 0, 0, 63000, 0, 1, 0},
{"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
(gptr*) &innobase_additional_mem_pool_size,
@@ -3800,6 +4136,11 @@ struct my_option my_long_options[] =
"Don't start more than this number of threads to handle INSERT DELAYED statements.",
(gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads,
0, GET_ULONG, REQUIRED_ARG, 20, 1, 16384, 0, 1, 0},
+ {"max_error_count", OPT_MAX_ERROR_COUNT,
+ "Max number of errors/warnings to store for a statement",
+ (gptr*) &global_system_variables.max_error_count,
+ (gptr*) &max_system_variables.max_error_count,
+ 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 1, 65535, 0, 1, 0},
{"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
"Don't allow creation of heap tables bigger than this.",
(gptr*) &global_system_variables.max_heap_table_size,
@@ -3810,6 +4151,11 @@ struct my_option my_long_options[] =
(gptr*) &global_system_variables.max_join_size,
(gptr*) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
~0L, 1, ~0L, 0, 1, 0},
+ {"max_prepared_statements", OPT_MAX_PREP_STMT,
+ "Max number of prepared_statements for a thread",
+ (gptr*) &global_system_variables.max_prep_stmt_count,
+ (gptr*) &max_system_variables.max_prep_stmt_count, 0, GET_ULONG,
+ REQUIRED_ARG, DEFAULT_PREP_STMT_COUNT, 0, ~0L, 0, 1, 0},
{"max_sort_length", OPT_MAX_SORT_LENGTH,
"The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).",
(gptr*) &global_system_variables.max_sort_length,
@@ -3856,7 +4202,7 @@ struct my_option my_long_options[] =
(gptr*) &max_system_variables.myisam_sort_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH,
- "Buffer length for TCP/IP and socket communication.",
+ "Buffer length for TCP/IP and socket communication.",
(gptr*) &global_system_variables.net_buffer_length,
(gptr*) &max_system_variables.net_buffer_length, 0, GET_ULONG,
REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0},
@@ -3912,6 +4258,7 @@ struct my_option my_long_options[] =
(gptr*) &global_system_variables.read_buff_size,
(gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+#ifdef HAVE_REPLICATION
{"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT,
"Max space to use for all relay logs",
(gptr*) &relay_log_space_limit,
@@ -3926,6 +4273,7 @@ struct my_option my_long_options[] =
"Number of seconds to wait for more data from a master/slave connection before aborting the read.",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
+#endif /* HAVE_REPLICATION */
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
(gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG,
@@ -3973,6 +4321,7 @@ struct show_var_st status_vars[]= {
{"Bytes_sent", (char*) &bytes_sent, SHOW_LONG},
{"Com_admin_commands", (char*) &com_other, SHOW_LONG},
{"Com_alter_table", (char*) (com_stat+(uint) SQLCOM_ALTER_TABLE),SHOW_LONG},
+ {"Com_alter_db", (char*) (com_stat+(uint) SQLCOM_ALTER_DB),SHOW_LONG},
{"Com_analyze", (char*) (com_stat+(uint) SQLCOM_ANALYZE),SHOW_LONG},
{"Com_backup_table", (char*) (com_stat+(uint) SQLCOM_BACKUP_TABLE),SHOW_LONG},
{"Com_begin", (char*) (com_stat+(uint) SQLCOM_BEGIN),SHOW_LONG},
@@ -3986,6 +4335,7 @@ struct show_var_st status_vars[]= {
{"Com_create_table", (char*) (com_stat+(uint) SQLCOM_CREATE_TABLE),SHOW_LONG},
{"Com_delete", (char*) (com_stat+(uint) SQLCOM_DELETE),SHOW_LONG},
{"Com_delete_multi", (char*) (com_stat+(uint) SQLCOM_DELETE_MULTI),SHOW_LONG},
+ {"Com_do", (char*) (com_stat+(uint) SQLCOM_DO),SHOW_LONG},
{"Com_drop_db", (char*) (com_stat+(uint) SQLCOM_DROP_DB),SHOW_LONG},
{"Com_drop_function", (char*) (com_stat+(uint) SQLCOM_DROP_FUNCTION),SHOW_LONG},
{"Com_drop_index", (char*) (com_stat+(uint) SQLCOM_DROP_INDEX),SHOW_LONG},
@@ -3995,11 +4345,12 @@ struct show_var_st status_vars[]= {
{"Com_ha_close", (char*) (com_stat+(uint) SQLCOM_HA_CLOSE),SHOW_LONG},
{"Com_ha_open", (char*) (com_stat+(uint) SQLCOM_HA_OPEN),SHOW_LONG},
{"Com_ha_read", (char*) (com_stat+(uint) SQLCOM_HA_READ),SHOW_LONG},
+ {"Com_help", (char*) (com_stat+(uint) SQLCOM_HELP),SHOW_LONG},
{"Com_insert", (char*) (com_stat+(uint) SQLCOM_INSERT),SHOW_LONG},
{"Com_insert_select", (char*) (com_stat+(uint) SQLCOM_INSERT_SELECT),SHOW_LONG},
{"Com_kill", (char*) (com_stat+(uint) SQLCOM_KILL),SHOW_LONG},
{"Com_load", (char*) (com_stat+(uint) SQLCOM_LOAD),SHOW_LONG},
- {"Com_load_master_data", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_DATA),SHOW_LONG},
+ {"Com_load_master_data", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_DATA),SHOW_LONG},
{"Com_load_master_table", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_TABLE),SHOW_LONG},
{"Com_lock_tables", (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG},
{"Com_optimize", (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG},
@@ -4016,8 +4367,12 @@ struct show_var_st status_vars[]= {
{"Com_set_option", (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG},
{"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG},
{"Com_show_binlogs", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG},
- {"Com_show_create", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG},
+ {"Com_show_charsets", (char*) (com_stat+(uint) SQLCOM_SHOW_CHARSETS),SHOW_LONG},
+ {"Com_show_column_types", (char*) (com_stat+(uint) SQLCOM_SHOW_COLUMN_TYPES),SHOW_LONG},
+ {"Com_show_create_table", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG},
+ {"Com_show_create_db", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE_DB),SHOW_LONG},
{"Com_show_databases", (char*) (com_stat+(uint) SQLCOM_SHOW_DATABASES),SHOW_LONG},
+ {"Com_show_errors", (char*) (com_stat+(uint) SQLCOM_SHOW_ERRORS),SHOW_LONG},
{"Com_show_fields", (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG},
{"Com_show_grants", (char*) (com_stat+(uint) SQLCOM_SHOW_GRANTS),SHOW_LONG},
{"Com_show_keys", (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG},
@@ -4025,18 +4380,22 @@ struct show_var_st status_vars[]= {
{"Com_show_master_status", (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG},
{"Com_show_new_master", (char*) (com_stat+(uint) SQLCOM_SHOW_NEW_MASTER),SHOW_LONG},
{"Com_show_open_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_OPEN_TABLES),SHOW_LONG},
+ {"Com_show_privileges", (char*) (com_stat+(uint) SQLCOM_SHOW_PRIVILEGES),SHOW_LONG},
{"Com_show_processlist", (char*) (com_stat+(uint) SQLCOM_SHOW_PROCESSLIST),SHOW_LONG},
{"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG},
{"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
{"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
{"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG},
{"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
+ {"Com_show_table_types", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLE_TYPES),SHOW_LONG},
{"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG},
+ {"Com_show_warnings", (char*) (com_stat+(uint) SQLCOM_SHOW_WARNS),SHOW_LONG},
{"Com_slave_start", (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG},
{"Com_slave_stop", (char*) (com_stat+(uint) SQLCOM_SLAVE_STOP),SHOW_LONG},
{"Com_truncate", (char*) (com_stat+(uint) SQLCOM_TRUNCATE),SHOW_LONG},
{"Com_unlock_tables", (char*) (com_stat+(uint) SQLCOM_UNLOCK_TABLES),SHOW_LONG},
{"Com_update", (char*) (com_stat+(uint) SQLCOM_UPDATE),SHOW_LONG},
+ {"Com_update_multi", (char*) (com_stat+(uint) SQLCOM_UPDATE_MULTI),SHOW_LONG},
{"Connections", (char*) &thread_id, SHOW_LONG_CONST},
{"Created_tmp_disk_tables", (char*) &created_tmp_disk_tables,SHOW_LONG},
{"Created_tmp_tables", (char*) &created_tmp_tables, SHOW_LONG},
@@ -4075,7 +4434,7 @@ struct show_var_st status_vars[]= {
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
{"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
- {"Qcache_free_memory", (char*) &query_cache.free_memory,
+ {"Qcache_free_memory", (char*) &query_cache.free_memory,
SHOW_LONG_CONST},
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks,
SHOW_LONG_CONST},
@@ -4192,12 +4551,12 @@ static void set_options(void)
sizeof(mysql_real_data_home)-1);
/* Set default values for some variables */
- global_system_variables.table_type=DB_TYPE_MYISAM;
- global_system_variables.tx_isolation=ISO_REPEATABLE_READ;
- global_system_variables.select_limit= HA_POS_ERROR;
- max_system_variables.select_limit= HA_POS_ERROR;
- global_system_variables.max_join_size= HA_POS_ERROR;
- max_system_variables.max_join_size= HA_POS_ERROR;
+ global_system_variables.table_type= DB_TYPE_MYISAM;
+ global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
+ global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
+ max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
+ global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
+ max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
#if defined(__WIN__) || defined(__NETWARE__)
/* Allow Win32 and NetWare users to move MySQL anywhere */
@@ -4232,9 +4591,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_endinfo=1; /* unireg: memory allocation */
break;
case 'a':
- opt_sql_mode = (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
- MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE
- | MODE_ONLY_FULL_GROUP_BY);
+ global_system_variables.sql_mode=
+ (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
+ MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE |
+ MODE_ONLY_FULL_GROUP_BY);
global_system_variables.tx_isolation= ISO_SERIALIZABLE;
break;
case 'b':
@@ -4257,13 +4617,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'o':
protocol_version=PROTOCOL_VERSION-1;
break;
+#ifdef HAVE_REPLICATION
case OPT_SLAVE_SKIP_ERRORS:
init_slave_skip_errors(argument);
break;
+#endif
case OPT_SAFEMALLOC_MEM_LIMIT:
-#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
+#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
safemalloc_mem_limit = atoi(argument);
-#endif
+#endif
break;
#ifdef EMBEDDED_LIBRARY
case OPT_MAX_ALLOWED_PACKET:
@@ -4302,6 +4664,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int) OPT_ERROR_LOG_FILE:
opt_error_log= 1;
break;
+#ifdef HAVE_REPLICATION
case (int) OPT_INIT_RPL_ROLE:
{
int role;
@@ -4328,7 +4691,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int)OPT_REPLICATE_REWRITE_DB:
{
char* key = argument,*p, *val;
-
+
if (!(p= strstr(argument, "->")))
{
fprintf(stderr,
@@ -4336,7 +4699,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
exit(1);
}
val= p--;
- while (isspace(*p) && p > argument)
+ while (my_isspace(mysqld_charset, *p) && p > argument)
*p-- = 0;
if (p == argument)
{
@@ -4346,7 +4709,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
*val= 0;
val+= 2;
- while (*val && isspace(*val))
+ while (*val && my_isspace(mysqld_charset, *val))
*val++;
if (!*val)
{
@@ -4422,13 +4785,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
table_rules_on = 1;
break;
}
- case (int) OPT_SLOW_QUERY_LOG:
- opt_slow_log=1;
- break;
case (int)OPT_RECKLESS_SLAVE:
opt_reckless_slave = 1;
init_slave_skip_errors("all");
break;
+#endif /* HAVE_REPLICATION */
+ case (int) OPT_SLOW_QUERY_LOG:
+ opt_slow_log=1;
+ break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
@@ -4488,7 +4852,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
have_symlink=SHOW_OPTION_DISABLED;
break;
case (int) OPT_BIND_ADDRESS:
- if (argument && isdigit(argument[0]))
+ if (argument && my_isdigit(mysqld_charset, argument[0]))
{
my_bind_addr = (ulong) inet_addr(argument);
}
@@ -4608,8 +4972,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
berkeley_lock_type=berkeley_lock_types[type-1];
else
{
- if (test_if_int(argument,(uint) strlen(argument)))
- berkeley_lock_scan_time=atoi(argument);
+ int err;
+ char *end;
+ uint length= strlen(argument);
+ long value= my_strntol(&my_charset_latin1, argument, length, 10, &end, &err);
+ if (test_if_int(argument,(uint) length, end, &my_charset_latin1))
+ berkeley_lock_scan_time= value;
else
{
fprintf(stderr,"Unknown lock type: %s\n",argument);
@@ -4670,16 +5038,17 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
case OPT_SQL_MODE:
{
- sql_mode_str = argument;
- if ((opt_sql_mode =
- find_bit_type(argument, &sql_mode_typelib)) == ~(ulong) 0)
+ sql_mode_str= argument;
+ if ((global_system_variables.sql_mode=
+ find_bit_type(argument, &sql_mode_typelib)) == ~(ulong) 0)
{
fprintf(stderr, "Unknown option to sql-mode: %s\n", argument);
exit(1);
}
- global_system_variables.tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
- ISO_SERIALIZABLE :
- ISO_REPEATABLE_READ);
+ global_system_variables.tx_isolation=
+ ((global_system_variables.sql_mode & MODE_SERIALIZABLE) ?
+ ISO_SERIALIZABLE :
+ ISO_REPEATABLE_READ);
break;
}
case OPT_MASTER_PASSWORD:
@@ -4729,7 +5098,7 @@ static void get_options(int argc,char **argv)
myisam_max_temp_length=
(my_off_t) min(global_system_variables.myisam_max_sort_file_size,
(ulonglong) MAX_FILE_SIZE);
- myisam_max_extra_temp_length=
+ myisam_max_extra_temp_length=
(my_off_t) min(global_system_variables.myisam_max_extra_sort_file_size,
(ulonglong) MAX_FILE_SIZE);
@@ -4809,15 +5178,15 @@ static void fix_paths(void)
charsets_dir=mysql_charsets_dir;
}
- char *end=convert_dirname(buff, opt_mysql_tmpdir, NullS);
- if (!(mysql_tmpdir= my_memdup((byte*) buff,(uint) (end-buff)+1,
- MYF(MY_FAE))))
+ if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
exit(1);
+#ifdef HAVE_REPLICATION
if (!slave_load_tmpdir)
{
if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE))))
exit(1);
}
+#endif /* HAVE_REPLICATION */
}
@@ -4912,7 +5281,8 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
j=pos;
while (j != end)
{
- if (toupper(*i++) != toupper(*j++))
+ if (my_toupper(mysqld_charset,*i++) !=
+ my_toupper(mysqld_charset,*j++))
goto skipp;
}
found_int=bit;
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
deleted file mode 100644
index 2ce811157af..00000000000
--- a/sql/net_pkg.cc
+++ /dev/null
@@ -1,402 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU 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 "mysql_priv.h"
-#include <stdarg.h>
-
- /* Send a error string to client */
-
-void send_error(NET *net, uint sql_errno, const char *err)
-{
- uint length;
- char buff[MYSQL_ERRMSG_SIZE+2];
- THD *thd=current_thd;
- DBUG_ENTER("send_error");
- DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
- err ? err : net->last_error[0] ?
- net->last_error : "NULL"));
-
- query_cache_abort(net);
- if (thd)
- thd->query_error = 1; // needed to catch query errors during replication
- if (!err)
- {
- if (sql_errno)
- err=ER(sql_errno);
- else
- {
- if ((err=net->last_error)[0])
- sql_errno=net->last_errno;
- else
- {
- sql_errno=ER_UNKNOWN_ERROR;
- err=ER(sql_errno); /* purecov: inspected */
- }
- }
- }
- if (net->vio == 0)
- {
- if (thd && thd->bootstrap)
- {
- /* In bootstrap it's ok to print on stderr */
- fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
- }
- DBUG_VOID_RETURN;
- }
-
- if (net->return_errno)
- { // new client code; Add errno before message
- int2store(buff,sql_errno);
- length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
- err=buff;
- }
- else
- {
- length=(uint) strlen(err);
- set_if_smaller(length,MYSQL_ERRMSG_SIZE);
- }
- VOID(net_write_command(net,(uchar) 255,(char*) err,length));
- if (thd)
- thd->fatal_error=0; // Error message is given
- DBUG_VOID_RETURN;
-}
-
-/*
- At some point we need to be able to distinguish between warnings and
- errors; The following function will help make this easier.
-*/
-
-void send_warning(NET *net, uint sql_errno, const char *err)
-{
- DBUG_ENTER("send_warning");
- send_error(net,sql_errno,err);
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Write error package and flush to client
- It's a little too low level, but I don't want to allow another buffer
-*/
-/* VARARGS3 */
-
-void
-net_printf(NET *net, uint errcode, ...)
-{
- va_list args;
- uint length,offset;
- const char *format,*text_pos;
- int head_length= NET_HEADER_SIZE;
- THD *thd=current_thd;
- DBUG_ENTER("net_printf");
- DBUG_PRINT("enter",("message: %u",errcode));
-
- if (thd)
- thd->query_error = 1; // if we are here, something is wrong :-)
- query_cache_abort(net); // Safety
- va_start(args,errcode);
- /*
- The following is needed to make net_printf() work with 0 argument for
- errorcode and use the argument after that as the format string. This
- is useful for rare errors that are not worth the hassle to put in
- errmsg.sys, but at the same time, the message is not fixed text
- */
- if (errcode)
- format= ER(errcode);
- else
- {
- format=va_arg(args,char*);
- errcode= ER_UNKNOWN_ERROR;
- }
- offset= net->return_errno ? 2 : 0;
- text_pos=(char*) net->buff+head_length+offset+1;
- (void) vsprintf(my_const_cast(char*) (text_pos),format,args);
- length=(uint) strlen((char*) text_pos);
- if (length >= sizeof(net->last_error))
- length=sizeof(net->last_error)-1; /* purecov: inspected */
- va_end(args);
-
- if (net->vio == 0)
- {
- if (thd && thd->bootstrap)
- {
- /*
- In bootstrap it's ok to print on stderr
- This may also happen when we get an error from a slave thread
- */
- fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
- thd->fatal_error=1;
- }
- DBUG_VOID_RETURN;
- }
-
- int3store(net->buff,length+1+offset);
- net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
- net->buff[head_length]=(uchar) 255; // Error package
- if (offset)
- int2store(text_pos-2, errcode);
- VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
- if (thd)
- thd->fatal_error=0; // Error message is given
- DBUG_VOID_RETURN;
-}
-
-
-void
-send_ok(NET *net,ha_rows affected_rows,ulonglong id,const char *message)
-{
- if (net->no_send_ok) // hack for re-parsing queries
- return;
-
- char buff[MYSQL_ERRMSG_SIZE+10],*pos;
- DBUG_ENTER("send_ok");
- buff[0]=0; // No fields
- pos=net_store_length(buff+1,(ulonglong) affected_rows);
- pos=net_store_length(pos, (ulonglong) id);
- if (net->return_status)
- {
- int2store(pos,*net->return_status);
- pos+=2;
- }
- if (message)
- pos=net_store_data((char*) pos,message);
- if (net->vio != 0)
- {
- VOID(my_net_write(net,buff,(uint) (pos-buff)));
- VOID(net_flush(net));
- }
- DBUG_VOID_RETURN;
-}
-
-void
-send_eof(NET *net,bool no_flush)
-{
- static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
- DBUG_ENTER("send_eof");
- if (net->vio != 0)
- {
- VOID(my_net_write(net,eof_buff,1));
- if (!no_flush)
- VOID(net_flush(net));
- }
- DBUG_VOID_RETURN;
-}
-
-
-/****************************************************************************
-** Store a field length in logical packet
-****************************************************************************/
-
-char *
-net_store_length(char *pkg, ulonglong length)
-{
- uchar *packet=(uchar*) pkg;
- if (length < LL(251))
- {
- *packet=(uchar) length;
- return (char*) packet+1;
- }
- /* 251 is reserved for NULL */
- if (length < LL(65536))
- {
- *packet++=252;
- int2store(packet,(uint) length);
- return (char*) packet+2;
- }
- if (length < LL(16777216))
- {
- *packet++=253;
- int3store(packet,(ulong) length);
- return (char*) packet+3;
- }
- *packet++=254;
- int8store(packet,length);
- return (char*) packet+8;
-}
-
-char *
-net_store_length(char *pkg, uint length)
-{
- uchar *packet=(uchar*) pkg;
- if (length < 251)
- {
- *packet=(uchar) length;
- return (char*) packet+1;
- }
- *packet++=252;
- int2store(packet,(uint) length);
- return (char*) packet+2;
-}
-
-/* The following will only be used for short strings < 65K */
-char *
-net_store_data(char *to,const char *from)
-{
- uint length=(uint) strlen(from);
- to=net_store_length(to,length);
- memcpy(to,from,length);
- return to+length;
-}
-
-
-char *
-net_store_data(char *to,int32 from)
-{
- char buff[20];
- uint length=(uint) (int10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
- memcpy(to,buff,length);
- return to+length;
-}
-
-char *
-net_store_data(char *to,longlong from)
-{
- char buff[22];
- uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
- memcpy(to,buff,length);
- return to+length;
-}
-
-
-bool net_store_null(String *packet)
-{
- return packet->append((char) 251);
-}
-
-bool
-net_store_data(String *packet,const char *from,uint length)
-{
- ulong packet_length=packet->length();
-/*
- We have added net5store in net_store_length.
- Before that largest size was int3store.
- Therefore +5 is changed to +9
-*/
- if (packet_length+9+length > packet->alloced_length() &&
- packet->realloc(packet_length+9+length))
- return 1;
- char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
- (ulonglong) length);
- memcpy(to,from,length);
- packet->length((uint) (to+length-packet->ptr()));
- return 0;
-}
-
-/* The following is only used at short, null terminated data */
-
-bool
-net_store_data(String *packet,const char *from)
-{
- uint length=(uint) strlen(from);
- uint packet_length=packet->length();
- if (packet_length+9+length > packet->alloced_length() &&
- packet->realloc(packet_length+9+length))
- return 1;
- char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
- length);
- memcpy(to,from,length);
- packet->length((uint) (to+length-packet->ptr()));
- return 0;
-}
-
-
-bool
-net_store_data(String *packet,uint32 from)
-{
- char buff[20];
- return net_store_data(packet,(char*) buff,
- (uint) (int10_to_str(from,buff,10)-buff));
-}
-
-bool
-net_store_data(String *packet, longlong from)
-{
- char buff[22];
- return net_store_data(packet,(char*) buff,
- (uint) (longlong10_to_str(from,buff,10)-buff));
-}
-
-bool
-net_store_data(String *packet,struct tm *tmp)
-{
- char buff[20];
- sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
- ((int) (tmp->tm_year+1900)) % 10000,
- (int) tmp->tm_mon+1,
- (int) tmp->tm_mday,
- (int) tmp->tm_hour,
- (int) tmp->tm_min,
- (int) tmp->tm_sec);
- return net_store_data(packet,(char*) buff,19);
-}
-
-bool net_store_data(String* packet, I_List<i_string>* str_list)
-{
- char buf[256];
- String tmp(buf, sizeof(buf));
- tmp.length(0);
- I_List_iterator<i_string> it(*str_list);
- i_string* s;
-
- while ((s=it++))
- {
- if (tmp.length())
- tmp.append(',');
- tmp.append(s->ptr);
- }
-
- return net_store_data(packet, (char*)tmp.ptr(), tmp.length());
-}
-
-/*
-** translate and store data; These are mainly used by the SHOW functions
-*/
-
-bool
-net_store_data(String *packet,CONVERT *convert, const char *from,uint length)
-{
- if (convert)
- return convert->store(packet, from, length);
- return net_store_data(packet,from,length);
-}
-
-bool
-net_store_data(String *packet, CONVERT *convert, const char *from)
-{
- uint length=(uint) strlen(from);
- if (convert)
- return convert->store(packet, from, length);
- return net_store_data(packet,from,length);
-}
-
-/*
- Function called by my_net_init() to set some check variables
-*/
-
-extern "C" {
-void my_net_local_init(NET *net)
-{
- net->max_packet= (uint) global_system_variables.net_buffer_length;
- net->read_timeout= (uint) global_system_variables.net_read_timeout;
- net->write_timeout=(uint) global_system_variables.net_write_timeout;
- net->retry_count= (uint) global_system_variables.net_retry_count;
- net->max_packet_size= max(global_system_variables.net_buffer_length,
- global_system_variables.max_allowed_packet);
-}
-}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 19f68e0b631..550fb772fce 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -23,6 +23,7 @@
3 byte length & 1 byte package-number.
*/
+#ifndef EMBEDDED_LIBRARY
#ifdef __WIN__
#include <winsock.h>
#endif
@@ -80,7 +81,7 @@ static my_bool net_write_buff(NET *net,const char *packet,ulong len);
/* Init with packet info */
-int my_net_init(NET *net, Vio* vio)
+my_bool my_net_init(NET *net, Vio* vio)
{
DBUG_ENTER("my_net_init");
my_net_local_init(net); /* Set some limits */
@@ -99,6 +100,7 @@ int my_net_init(NET *net, Vio* vio)
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
net->query_cache_query=0;
+ net->report_error= 0;
if (vio != 0) /* If real connection */
{
@@ -127,7 +129,7 @@ void net_end(NET *net)
/* Realloc the packet buffer */
-static my_bool net_realloc(NET *net, ulong length)
+my_bool net_realloc(NET *net, ulong length)
{
uchar *buff;
ulong pkt_length;
@@ -138,8 +140,9 @@ static my_bool net_realloc(NET *net, ulong length)
{
DBUG_PRINT("error",("Packet too large. Max sixe: %lu",
net->max_packet_size));
- net->error=1;
- net->last_errno=ER_NET_PACKET_TOO_LARGE;
+ net->error= 1;
+ net->report_error= 1;
+ net->last_errno= ER_NET_PACKET_TOO_LARGE;
DBUG_RETURN(1);
}
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
@@ -151,9 +154,10 @@ static my_bool net_realloc(NET *net, ulong length)
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
- net->error=1;
+ net->error= 1;
+ net->report_error= 1;
#ifdef MYSQL_SERVER
- net->last_errno=ER_OUT_OF_RESOURCES;
+ net->last_errno= ER_OUT_OF_RESOURCES;
#endif
DBUG_RETURN(1);
}
@@ -188,14 +192,14 @@ void net_clear(NET *net)
/* Flush write_buffer if not empty. */
-int net_flush(NET *net)
+my_bool net_flush(NET *net)
{
- int error=0;
+ my_bool error= 0;
DBUG_ENTER("net_flush");
if (net->buff != net->write_pos)
{
- error=net_real_write(net,(char*) net->buff,
- (ulong) (net->write_pos - net->buff));
+ error=test(net_real_write(net,(char*) net->buff,
+ (ulong) (net->write_pos - net->buff)));
net->write_pos=net->buff;
}
/* Sync packet number if using compression */
@@ -216,7 +220,7 @@ int net_flush(NET *net)
** NOTE: If compression is used the original package is modified!
*/
-int
+my_bool
my_net_write(NET *net,const char *packet,ulong len)
{
uchar buff[NET_HEADER_SIZE];
@@ -247,17 +251,38 @@ my_net_write(NET *net,const char *packet,ulong len)
/*
Send a command to the server.
- As the command is part of the first data packet, we have to do some data
- juggling to put the command in there, without having to create a new
- packet.
- This function will split big packets into sub-packets if needed.
- (Each sub packet can only be 2^24 bytes)
+
+ SYNOPSIS
+ net_write_command()
+ net NET handler
+ command Command in MySQL server (enum enum_server_command)
+ header Header to write after command
+ head_len Length of header
+ packet Query or parameter to query
+ len Length of packet
+
+ DESCRIPTION
+ The reason for having both header and packet is so that libmysql
+ can easy add a header to a special command (like prepared statements)
+ without having to re-alloc the string.
+
+ As the command is part of the first data packet, we have to do some data
+ juggling to put the command in there, without having to create a new
+ packet.
+ This function will split big packets into sub-packets if needed.
+ (Each sub packet can only be 2^24 bytes)
+
+ RETURN VALUES
+ 0 ok
+ 1 error
*/
-int
-net_write_command(NET *net,uchar command,const char *packet,ulong len)
+my_bool
+net_write_command(NET *net,uchar command,
+ const char *header, ulong head_len,
+ const char *packet, ulong len)
{
- ulong length=len+1; /* 1 extra byte for command */
+ ulong length=len+1+head_len; /* 1 extra byte for command */
uchar buff[NET_HEADER_SIZE+1];
uint header_size=NET_HEADER_SIZE+1;
DBUG_ENTER("net_write_command");
@@ -268,25 +293,28 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
if (length >= MAX_PACKET_LENGTH)
{
/* Take into account that we have the command in the first header */
- len= MAX_PACKET_LENGTH -1;
+ len= MAX_PACKET_LENGTH - 1 - head_len;
do
{
int3store(buff, MAX_PACKET_LENGTH);
buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff, header_size) ||
- net_write_buff(net,packet,len))
+ net_write_buff(net, header, head_len) ||
+ net_write_buff(net, packet, len))
DBUG_RETURN(1);
packet+= len;
length-= MAX_PACKET_LENGTH;
len= MAX_PACKET_LENGTH;
+ head_len= 0;
header_size= NET_HEADER_SIZE;
} while (length >= MAX_PACKET_LENGTH);
len=length; /* Data left to be written */
}
int3store(buff,length);
buff[3]= (uchar) net->pkt_nr++;
- DBUG_RETURN(test(net_write_buff(net,(char*) buff,header_size) ||
- net_write_buff(net,packet,len) || net_flush(net)));
+ DBUG_RETURN(test(net_write_buff(net, (char*) buff, header_size) ||
+ (head_len && net_write_buff(net, (char*) header, head_len)) ||
+ net_write_buff(net, packet, len) || net_flush(net)));
}
/*
@@ -402,10 +430,12 @@ net_real_write(NET *net,const char *packet,ulong len)
COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
- net->last_errno=ER_OUT_OF_RESOURCES;
- net->error=2;
+ net->last_errno= ER_OUT_OF_RESOURCES;
+ net->error= 2;
+ //TODO is it needed to set this variable if we have no socket
+ net->report_error= 1;
#endif
- net->reading_or_writing=0;
+ net->reading_or_writing= 0;
DBUG_RETURN(1);
}
memcpy(b+header_length,packet,len);
@@ -451,9 +481,10 @@ net_real_write(NET *net,const char *packet,ulong len)
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
#ifdef MYSQL_SERVER
- net->last_errno=ER_NET_ERROR_ON_WRITE;
+ net->last_errno= ER_NET_ERROR_ON_WRITE;
#endif
- net->error=2; /* Close socket */
+ net->error= 2; /* Close socket */
+ net->report_error= 1;
goto end;
}
retry_count=0;
@@ -479,7 +510,8 @@ net_real_write(NET *net,const char *packet,ulong len)
continue;
}
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
- net->error=2; /* Close socket */
+ net->error= 2; /* Close socket */
+ net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
ER_NET_ERROR_ON_WRITE);
@@ -652,9 +684,10 @@ my_real_read(NET *net, ulong *complen)
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
len= packet_error;
- net->error=2; /* Close socket */
+ net->error= 2; /* Close socket */
+ net->report_error= 1;
#ifdef MYSQL_SERVER
- net->last_errno=ER_NET_FCNTL_ERROR;
+ net->last_errno= ER_NET_FCNTL_ERROR;
#endif
goto end;
}
@@ -683,7 +716,8 @@ my_real_read(NET *net, ulong *complen)
DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld",
remain, vio_errno(net->vio), length));
len= packet_error;
- net->error=2; /* Close socket */
+ net->error= 2; /* Close socket */
+ net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR);
@@ -713,6 +747,7 @@ my_real_read(NET *net, ulong *complen)
#endif
}
len= packet_error;
+ net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
#endif
@@ -890,7 +925,8 @@ my_net_read(NET *net)
if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
&complen))
{
- net->error=2; /* caller will close socket */
+ net->error= 2; /* caller will close socket */
+ net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
#endif
@@ -911,12 +947,5 @@ my_net_read(NET *net)
return len;
}
-bool net_request_file(NET* net, const char* fname)
-{
- char tmp [FN_REFLEN+1],*end;
- DBUG_ENTER("net_request_file");
- tmp[0] = (char) 251; /* NULL_LENGTH */
- end=strnmov(tmp+1,fname,sizeof(tmp)-2);
- DBUG_RETURN(my_net_write(net,tmp,(uint) (end-tmp)) ||
- net_flush(net));
-}
+#endif /* EMBEDDED_LIBRARY */
+
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index b917c91ce15..93bae6f444d 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -431,7 +431,7 @@ BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
if (ret_error == ERROR_ACCESS_DENIED)
{
printf("Install/Remove of the Service Denied!\n");
- if(!is_super_user())
+ if (!is_super_user())
printf("That operation should be made by an user with Administrator privileges!\n");
}
else
@@ -530,13 +530,13 @@ BOOL NTService::is_super_user()
UINT x;
BOOL ret_value=FALSE;
- if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
{
- if(GetLastError() != ERROR_NO_TOKEN)
- return FALSE;
+ if (GetLastError() != ERROR_NO_TOKEN)
+ return FALSE;
- if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
- return FALSE;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
+ return FALSE;
}
ret_value= GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
@@ -544,21 +544,21 @@ BOOL NTService::is_super_user()
CloseHandle(hAccessToken);
- if(!ret_value )
- return FALSE;
+ if (!ret_value )
+ return FALSE;
- if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
- SECURITY_BUILTIN_DOMAIN_RID,
- DOMAIN_ALIAS_RID_ADMINS,
- 0, 0, 0, 0, 0, 0,
- &psidAdministrators))
- return FALSE;
+ if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &psidAdministrators))
+ return FALSE;
ret_value = FALSE;
- for(x=0;x<ptgGroups->GroupCount;x++)
+ for (x=0;x<ptgGroups->GroupCount;x++)
{
- if( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
+ if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
{
ret_value = TRUE;
break;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c1b03ed629f..9c546c99057 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -31,8 +31,6 @@
#include <m_ctype.h>
#include <nisam.h>
#include "sql_select.h"
-#include <assert.h>
-
#ifndef EXTRA_DEBUG
#define test_rb_tree(A,B) {}
@@ -172,8 +170,9 @@ public:
void store(uint length,char **min_key,uint min_key_flag,
char **max_key, uint max_key_flag)
{
- if (!(min_flag & NO_MIN_RANGE) &&
- !(min_key_flag & (NO_MIN_RANGE | NEAR_MIN)))
+ if ((min_flag & GEOM_FLAG) ||
+ (!(min_flag & NO_MIN_RANGE) &&
+ !(min_key_flag & (NO_MIN_RANGE | NEAR_MIN))))
{
if (maybe_null && *min_value)
{
@@ -296,9 +295,6 @@ static SEL_TREE * get_mm_parts(PARAM *param,Field *field,
Item_result cmp_type);
static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part,
Item_func::Functype type,Item *value);
-static bool like_range(const char *ptr,uint length,char wild_prefix,
- uint field_length, char *min_str,char *max_str,
- char max_sort_char,uint *min_length,uint *max_length);
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
@@ -662,6 +658,8 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
key_parts->null_bit= key_info->key_part[part].null_bit;
if (key_parts->field->type() == FIELD_TYPE_BLOB)
key_parts->part_length+=HA_KEY_BLOB_LENGTH;
+ key_parts->image_type =
+ (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
}
param.real_keynr[param.keys++]=idx;
}
@@ -679,6 +677,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
{
SEL_ARG **key,**end,**best_key=0;
+
for (idx=0,key=tree->keys, end=key+param.keys ;
key != end ;
key++,idx++)
@@ -929,10 +928,10 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
{
bool like_error;
char buff1[MAX_FIELD_WIDTH],*min_str,*max_str;
- String tmp(buff1,sizeof(buff1)),*res;
+ String tmp(buff1,sizeof(buff1),value->charset()),*res;
uint length,offset,min_length,max_length;
- if (!field->optimize_range((uint) key_part->key))
+ if (!field->optimize_range(param->real_keynr[key_part->key]))
DBUG_RETURN(0); // Can't optimize this
if (!(res= value->val_str(&tmp)))
DBUG_RETURN(&null_element);
@@ -970,25 +969,14 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
max_str=min_str+length;
if (maybe_null)
max_str[0]= min_str[0]=0;
- if (field->binary())
- like_error=like_range(res->ptr(),res->length(),wild_prefix,field_length,
- min_str+offset,max_str+offset,(char) 255,
- &min_length,&max_length);
- else
- {
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- like_error= my_like_range(default_charset_info,
- res->ptr(),res->length(),wild_prefix,
- field_length, min_str+maybe_null,
- max_str+maybe_null,&min_length,&max_length);
- else
-#endif
- like_error=like_range(res->ptr(),res->length(),wild_prefix,
- field_length,
- min_str+offset,max_str+offset,
- max_sort_char,&min_length,&max_length);
- }
+
+ like_error= my_like_range(field->charset(),
+ res->ptr(),res->length(),
+ wild_prefix,wild_one,wild_many,
+ field_length,
+ min_str+offset, max_str+offset,
+ &min_length,&max_length);
+
if (like_error) // Can't optimize with LIKE
DBUG_RETURN(0);
if (offset != maybe_null) // Blob
@@ -1016,7 +1004,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN(tree);
}
- if (!field->optimize_range((uint) key_part->key) &&
+ if (!field->optimize_range(param->real_keynr[key_part->key]) &&
type != Item_func::EQ_FUNC &&
type != Item_func::EQUAL_FUNC)
DBUG_RETURN(0); // Can't optimize this
@@ -1030,7 +1018,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
field->cmp_type() != value->result_type())
DBUG_RETURN(0);
- if (value->save_in_field(field, 1))
+ if (value->save_in_field(field, 1) > 0)
{
/* This happens when we try to insert a NULL field in a not null column */
DBUG_RETURN(&null_element); // cmp with NULL is never true
@@ -1042,7 +1030,8 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN(0);
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
- field->get_key_image(str+maybe_null,key_part->part_length);
+ field->get_key_image(str+maybe_null,key_part->part_length,
+ field->charset(),key_part->image_type);
if (!(tree=new SEL_ARG(field,str,str)))
DBUG_RETURN(0);
@@ -1067,73 +1056,45 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
case Item_func::GE_FUNC:
tree->max_flag=NO_MAX_RANGE;
break;
- default:
- break;
- }
- DBUG_RETURN(tree);
-}
-
+ case Item_func::SP_EQUALS_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_EQUAL;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
+ case Item_func::SP_DISJOINT_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_DISJOINT;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
+ case Item_func::SP_INTERSECTS_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
+ case Item_func::SP_TOUCHES_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
-/*
-** Calculate min_str and max_str that ranges a LIKE string.
-** Arguments:
-** ptr Pointer to LIKE string.
-** ptr_length Length of LIKE string.
-** escape Escape character in LIKE. (Normally '\').
-** All escape characters should be removed from min_str and max_str
-** res_length Length of min_str and max_str.
-** min_str Smallest case sensitive string that ranges LIKE.
-** Should be space padded to res_length.
-** max_str Largest case sensitive string that ranges LIKE.
-** Normally padded with the biggest character sort value.
-**
-** The function should return 0 if ok and 1 if the LIKE string can't be
-** optimized !
-*/
+ case Item_func::SP_CROSSES_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
+ case Item_func::SP_WITHIN_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_WITHIN;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
-static bool like_range(const char *ptr,uint ptr_length,char escape,
- uint res_length, char *min_str,char *max_str,
- char max_sort_chr, uint *min_length, uint *max_length)
-{
- const char *end=ptr+ptr_length;
- char *min_org=min_str;
- char *min_end=min_str+res_length;
+ case Item_func::SP_CONTAINS_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_CONTAIN;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
+ case Item_func::SP_OVERLAPS_FUNC:
+ tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
+ tree->max_flag=NO_MAX_RANGE;
+ break;
- for (; ptr != end && min_str != min_end ; ptr++)
- {
- if (*ptr == escape && ptr+1 != end)
- {
- ptr++; // Skip escape
- *min_str++= *max_str++ = *ptr;
- continue;
- }
- if (*ptr == wild_one) // '_' in SQL
- {
- *min_str++='\0'; // This should be min char
- *max_str++=max_sort_chr;
- continue;
- }
- if (*ptr == wild_many) // '%' in SQL
- {
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
- do {
- *min_str++ = ' '; // Because if key compression
- *max_str++ = max_sort_chr;
- } while (min_str != min_end);
- return 0;
- }
- *min_str++= *max_str++ = *ptr;
+ default:
+ break;
}
- *min_length= *max_length = (uint) (min_str - min_org);
-
- /* Temporary fix for handling wild_one at end of string (key compression) */
- for (char *tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
- *--tmp=' ';
-
- while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; // Because if key compression
- return 0;
+ DBUG_RETURN(tree);
}
@@ -2188,18 +2149,31 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
!memcmp(param->min_key,param->max_key,min_key_length))
tmp=1; // Max one record
else
+ {
+ if (tmp_min_flag & GEOM_FLAG)
+ {
+ tmp= param->table->file->
+ records_in_range((int) keynr, (byte*)(param->min_key + 1),
+ min_key_length,
+ (ha_rkey_function)(tmp_min_flag ^ GEOM_FLAG),
+ (byte *)NullS, 0, HA_READ_KEY_EXACT);
+ }
+ else
+ {
tmp=param->table->file->
records_in_range((int) keynr,
(byte*) (!min_key_length ? NullS :
param->min_key),
min_key_length,
- (tmp_min_flag & NEAR_MIN ?
- HA_READ_AFTER_KEY : HA_READ_KEY_EXACT),
+ tmp_min_flag & NEAR_MIN ?
+ HA_READ_AFTER_KEY : HA_READ_KEY_EXACT,
(byte*) (!max_key_length ? NullS :
param->max_key),
max_key_length,
(tmp_max_flag & NEAR_MAX ?
HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY));
+ }
+ }
end:
if (tmp == HA_POS_ERROR) // Impossible range
return tmp;
@@ -2295,19 +2269,26 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
}
}
else
- flag=key_tree->min_flag | key_tree->max_flag;
-
- /* Ensure that some part of min_key and max_key are used. If not,
- regard this as no lower/upper range */
- if (tmp_min_key != param->min_key)
- flag&= ~NO_MIN_RANGE;
- else
- flag|= NO_MIN_RANGE;
- if (tmp_max_key != param->max_key)
- flag&= ~NO_MAX_RANGE;
- else
- flag|= NO_MAX_RANGE;
+ {
+ flag = (key_tree->min_flag & GEOM_FLAG) ?
+ key_tree->min_flag : key_tree->min_flag | key_tree->max_flag;
+ }
+ /*
+ Ensure that some part of min_key and max_key are used. If not,
+ regard this as no lower/upper range
+ */
+ if ((flag & GEOM_FLAG) == 0)
+ {
+ if (tmp_min_key != param->min_key)
+ flag&= ~NO_MIN_RANGE;
+ else
+ flag|= NO_MIN_RANGE;
+ if (tmp_max_key != param->max_key)
+ flag&= ~NO_MAX_RANGE;
+ else
+ flag|= NO_MAX_RANGE;
+ }
if (flag == 0)
{
uint length= (uint) (tmp_min_key - param->min_key);
@@ -2440,13 +2421,19 @@ int QUICK_SELECT::get_next()
int result;
if (range)
{ // Already read through key
- result=((range->flag & EQ_RANGE) ?
+/* result=((range->flag & EQ_RANGE) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
+*/
+ result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ?
+ file->index_next_same(record, (byte*) range->min_key,
+ range->min_length) :
+ file->index_next(record));
+
if (!result)
{
- if (!cmp_next(*it.ref()))
+ if ((range->flag & GEOM_FLAG) || !cmp_next(*it.ref()))
DBUG_RETURN(0);
}
else if (result != HA_ERR_END_OF_FILE)
@@ -2455,6 +2442,23 @@ int QUICK_SELECT::get_next()
if (!(range=it++))
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
+
+ if (range->flag & GEOM_FLAG)
+ {
+ if ((result = file->index_read(record,
+ (byte*) (range->min_key +1),
+ range->min_length,
+ (ha_rkey_function)(range->flag ^
+ GEOM_FLAG))))
+ {
+ if (result != HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(result);
+ range=0; // Not found, to next range
+ continue;
+ }
+ DBUG_RETURN(0);
+ }
+
if (range->flag & NO_MIN_RANGE) // Read first record
{
int local_error;
@@ -2465,13 +2469,15 @@ int QUICK_SELECT::get_next()
range=0; // No matching records; go to next range
continue;
}
- if ((result = file->index_read(record,(byte*) range->min_key,
- range->min_length,
- ((range->flag & NEAR_MIN) ?
- HA_READ_AFTER_KEY:
- (range->flag & EQ_RANGE) ?
- HA_READ_KEY_EXACT :
- HA_READ_KEY_OR_NEXT))))
+ if ((result = file->index_read(record,
+ (byte*) (range->min_key +
+ test(range->flag & GEOM_FLAG)),
+ range->min_length,
+ (range->flag & NEAR_MIN) ?
+ HA_READ_AFTER_KEY:
+ (range->flag & EQ_RANGE) ?
+ HA_READ_KEY_EXACT :
+ HA_READ_KEY_OR_NEXT)))
{
if (result != HA_ERR_KEY_NOT_FOUND)
@@ -2489,8 +2495,11 @@ int QUICK_SELECT::get_next()
}
}
- /* compare if found key is over max-value */
- /* Returns 0 if key <= range->max_key */
+
+/*
+ Compare if found key is over max-value
+ Returns 0 if key <= range->max_key
+*/
int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
{
@@ -2618,20 +2627,28 @@ int QUICK_SELECT_DESC::get_next()
}
else
{
+ DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
+#ifdef NOT_IMPLEMENTED_YET
+ result=file->index_read(record, (byte*) range->max_key,
+ range->max_length,
+ ((range->flag & NEAR_MAX) ?
+ HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV));
+#else
/* Heikki changed Sept 11, 2002: since InnoDB does not store the cursor
position if READ_KEY_EXACT is used to a primary key with all
key columns specified, we must use below HA_READ_KEY_OR_NEXT,
so that InnoDB stores the cursor position and is able to move
the cursor one step backward after the search. */
- DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
/* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
* do the right thing - go past all keys which match the prefix */
+
result=file->index_read(record, (byte*) range->max_key,
range->max_length,
((range->flag & NEAR_MAX) ?
HA_READ_KEY_OR_NEXT : HA_READ_AFTER_KEY));
result = file->index_prev(record);
+#endif
}
if (result)
{
@@ -2766,7 +2783,7 @@ static void
print_key(KEY_PART *key_part,const char *key,uint used_length)
{
char buff[1024];
- String tmp(buff,sizeof(buff));
+ String tmp(buff,sizeof(buff),&my_charset_bin);
for (uint length=0;
length < used_length ;
@@ -2786,7 +2803,8 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
}
field->set_key_image((char*) key,key_part->part_length -
((field->type() == FIELD_TYPE_BLOB) ?
- HA_KEY_BLOB_LENGTH : 0));
+ HA_KEY_BLOB_LENGTH : 0),
+ field->charset());
field->val_str(&tmp,&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 6a6b5ae3810..bc56fb99b4b 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -31,11 +31,14 @@
#define UNIQUE_RANGE 16
#define EQ_RANGE 32
#define NULL_RANGE 64
+#define GEOM_FLAG 128
+
typedef struct st_key_part {
- uint16 key,part,part_length;
- uint8 null_bit;
- Field *field;
+ uint16 key,part,part_length;
+ uint8 null_bit;
+ Field *field;
+ Field::imagetype image_type;
} KEY_PART;
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 41771646082..d8c61fa1a1d 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -412,7 +412,8 @@ static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond)
// Save found constant
if (part->null_bit)
*key_ptr++= (byte) test(part->field->is_null());
- part->field->get_key_image((char*) key_ptr,part->length);
+ part->field->get_key_image((char*) key_ptr,part->length,
+ part->field->charset(), Field::itRAW);
key_ptr+=part->store_length - test(part->null_bit);
left_length-=part->store_length;
}
diff --git a/sql/password.c b/sql/password.c
index 318c8e84db3..5ed05ae6c0e 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -32,14 +32,55 @@
Example:
update user set password=PASSWORD("hello") where user="test"
This saves a hashed number as a string in the password field.
+
+
+ New in MySQL 4.1 authentication works even more secure way.
+ At the first step client sends user name to the sever, and password if
+ it is empty. So in case of empty password authentication is as fast as before.
+ At the second stap servers sends scramble to client, which is encoded with
+ password stage2 hash stored in the password database as well as salt, needed
+ for client to build stage2 password to decrypt scramble.
+ Client decrypts the scramble and encrypts it once again with stage1 password.
+ This information is sent to server.
+ Server decrypts the scramble to get stage1 password and hashes it to get
+ stage2 hash. This hash is when compared to hash stored in the database.
+
+ This authentication needs 2 packet round trips instead of one but it is much
+ stronger. Now if one will steal mysql database content he will not be able
+ to break into MySQL.
+
+ New Password handling functions by Peter Zaitsev
+
+
*****************************************************************************/
#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
+#include <sha1.h>
#include "mysql.h"
+
+/* Character to use as version identifier for version 4.1 */
+#define PVERSION41_CHAR '*'
+
+/* Scramble length for new password version */
+
+
+/*
+ New (MySQL 3.21+) random generation structure initialization
+
+ SYNOPSIS
+ randominit()
+ rand_st OUT Structure to initialize
+ seed1 IN First initialization parameter
+ seed2 IN Second initialization parameter
+
+ RETURN
+ none
+*/
+
void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
{ /* For mysql 3.21.# */
#ifdef HAVE_purify
@@ -51,6 +92,19 @@ void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
rand_st->seed2=seed2%rand_st->max_value;
}
+
+/*
+ Old (MySQL 3.20) random generation structure initialization
+
+ SYNOPSIS
+ old_randominit()
+ rand_st OUT Structure to initialize
+ seed1 IN First initialization parameter
+
+ RETURN
+ none
+*/
+
static void old_randominit(struct rand_struct *rand_st,ulong seed1)
{ /* For mysql 3.20.# */
rand_st->max_value= 0x01FFFFFFL;
@@ -59,6 +113,18 @@ static void old_randominit(struct rand_struct *rand_st,ulong seed1)
rand_st->seed1=seed1 ; rand_st->seed2=seed1/2;
}
+
+/*
+ Generate Random number
+
+ SYNOPSIS
+ rnd()
+ rand_st INOUT Structure used for number generation
+
+ RETURN
+ Generated pseudo random number
+*/
+
double rnd(struct rand_struct *rand_st)
{
rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
@@ -66,6 +132,67 @@ double rnd(struct rand_struct *rand_st)
return (((double) rand_st->seed1)/rand_st->max_value_dbl);
}
+
+/*
+ Generate String of printable random characters of requested length
+ String will not be zero terminated.
+
+ SYNOPSIS
+ create_random_string()
+ length IN Lenght of
+ rand_st INOUT Structure used for number generation
+ target OUT Buffer for generation
+
+ RETURN
+ none
+*/
+
+void create_random_string(int length,struct rand_struct *rand_st,char *target)
+{
+ char *end=target+length;
+ /* Use pointer arithmetics as it is faster way to do so. */
+ for (; target<end ; target++)
+ *target= (char) (rnd(rand_st)*94+33);
+}
+
+
+/*
+ Encrypt/Decrypt function used for password encryption in authentication
+ Simple XOR is used here but it is OK as we crypt random strings
+
+ SYNOPSIS
+ password_crypt()
+ from IN Data for encryption
+ to OUT Encrypt data to the buffer (may be the same)
+ password IN Password used for encryption (same length)
+ length IN Length of data to encrypt
+
+ RETURN
+ none
+*/
+
+void password_crypt(const char *from,char *to, const char *password,int length)
+{
+ const char *from_end=from+length;
+
+ while (from < from_end)
+ *to++= *(from++) ^* (password++);
+}
+
+
+/*
+ Generate binary hash from raw text password
+ Used for Pre-4.1 Password handling
+
+ SYNOPSIS
+ hash_pasword()
+ result OUT Store hash in this location
+ password IN Plain text password to build hash
+
+ RETURN
+ none
+*/
+
void hash_password(ulong *result, const char *password)
{
register ulong nr=1345345333L, add=7, nr2=0x12345671L;
@@ -84,13 +211,230 @@ void hash_password(ulong *result, const char *password)
return;
}
-void make_scrambled_password(char *to,const char *password)
+
+/*
+ Stage one password hashing.
+ Used in MySQL 4.1 password handling
+
+ SYNOPSIS
+ password_hash_stage1()
+ to OUT Store stage one hash to this location
+ password IN Plain text password to build hash
+
+ RETURN
+ none
+*/
+
+void password_hash_stage1(char *to, const char *password)
{
- ulong hash_res[2];
- hash_password(hash_res,password);
- sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+ SHA1_CONTEXT context;
+ sha1_reset(&context);
+ for (; *password ; password++)
+ {
+ if (*password == ' ' || *password == '\t')
+ continue;/* skip space in password */
+ sha1_input(&context,(uint8*) &password[0],1);
+ }
+ sha1_result(&context,(uint8*)to);
}
+
+/*
+ Stage two password hashing.
+ Used in MySQL 4.1 password handling
+
+ SYNOPSIS
+ password_hash_stage2()
+ to INOUT Use this as stage one hash and store stage two hash here
+ salt IN Salt used for stage two hashing
+
+ RETURN
+ none
+*/
+
+void password_hash_stage2(char *to, const char *salt)
+{
+ SHA1_CONTEXT context;
+ sha1_reset(&context);
+ sha1_input(&context,(uint8*) salt, 4);
+ sha1_input(&context,(uint8*) to, SHA1_HASH_SIZE);
+ sha1_result(&context,(uint8*) to);
+}
+
+
+/*
+ Create password to be stored in user database from raw string
+ Handles both MySQL 4.1 and Pre-MySQL 4.1 passwords
+
+ SYNOPSIS
+ make_scramble_password()
+ to OUT Store scrambled password here
+ password IN Raw string password
+ force_old_scramle
+ IN Force generation of old scramble variant
+ rand_st INOUT Structure for temporary number generation.
+ RETURN
+ none
+*/
+
+void make_scrambled_password(char *to,const char *password,
+ my_bool force_old_scramble,
+ struct rand_struct *rand_st)
+{
+ ulong hash_res[2]; /* Used for pre 4.1 password hashing */
+ unsigned short salt; /* Salt for 4.1 version password */
+ uint8 digest[SHA1_HASH_SIZE];
+ if (force_old_scramble) /* Pre 4.1 password encryption */
+ {
+ hash_password(hash_res,password);
+ sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+ }
+ else /* New password 4.1 password scrambling */
+ {
+ to[0]=PVERSION41_CHAR; /* New passwords have version prefix */
+ /* Rnd returns number from 0 to 1 so this would be good salt generation.*/
+ salt=(unsigned short) (rnd(rand_st)*65535+1);
+ /* Use only 2 first bytes from it */
+ sprintf(to+1,"%04x",salt);
+ /* First hasing is done without salt */
+ password_hash_stage1((char*) digest, password);
+ /* Second stage is done with salt */
+ password_hash_stage2((char*) digest,(char*)to+1),
+ /* Print resulting hash into the password*/
+ sprintf(to+5,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ digest[0],digest[1],digest[2],digest[3],digest[4],digest[5],digest[6],
+ digest[7],digest[8],digest[9],digest[10],digest[11],digest[12],digest[13],
+ digest[14],digest[15],digest[16],digest[17],digest[18],digest[19]);
+ }
+}
+
+
+/*
+ Convert password from binary string form to salt form
+ Used for MySQL 4.1 password handling
+
+ SYNOPSIS
+ get_salt_from_bin_password()
+ res OUT Store salt form password here
+ password IN Binary password to be converted
+ salt IN hashing-salt to be used for salt form generation
+
+ RETURN
+ none
+*/
+
+void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
+{
+ unsigned char *password_end=password+SCRAMBLE41_LENGTH;
+ *res=salt;
+ res++;
+
+ /* Process password of known length*/
+ while (password<password_end)
+ {
+ ulong val=0;
+ uint i;
+ for (i=0 ; i < 4 ; i++)
+ val=(val << 8)+(*password++);
+ *res++=val;
+ }
+}
+
+
+/*
+ Validate password for MySQL 4.1 password handling.
+
+ SYNOPSIS
+ validate_password()
+ password IN Encrypted Scramble which we got from the client
+ message IN Original scramble which we have sent to the client before
+ salt IN Password in the salted form to match to
+
+ RETURN
+ 0 for correct password
+ !0 for invalid password
+*/
+
+my_bool validate_password(const char *password, const char *message,
+ ulong *salt)
+{
+ char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */
+ char tmpsalt[8]; /* Temporary value to convert salt to string form */
+ ulong salt_candidate[6]; /* Computed candidate salt */
+ ulong *sc=salt_candidate; /* we need to be able to increment */
+ ulong *salt_end;
+
+ /* Now we shall get stage1 encrypted password in buffer*/
+ password_crypt(password,buffer,message,SCRAMBLE41_LENGTH);
+
+ /* For compatibility reasons we use ulong to store salt while we need char */
+ sprintf(tmpsalt,"%04x",(unsigned short)salt[0]);
+
+ password_hash_stage2(buffer,tmpsalt);
+ /* Convert password to salt to compare */
+ get_salt_from_bin_password(salt_candidate,(uchar*) buffer,salt[0]);
+
+ /* Now we shall get exactly the same password as we have stored for user */
+ for (salt_end=salt+5 ; salt < salt_end; )
+ if (*++salt != *++sc)
+ return 1;
+
+ /* Or password correct*/
+ return 0;
+}
+
+
+/*
+ Get length of password string which is stored in mysql.user table
+
+ SYNOPSIS
+ get_password_length()
+ force_old_scramble IN If we wish to use pre 4.1 scramble format
+
+ RETURN
+ password length >0
+*/
+
+int get_password_length(my_bool force_old_scramble)
+{
+ return (force_old_scramble) ? 16 : SHA1_HASH_SIZE*2+4+1;
+}
+
+
+/*
+ Get version of the password based on mysql.user password string
+
+ SYNOPSIS
+ get_password_version()
+ password IN Password string as stored in mysql.user
+
+ RETURN
+ 0 for pre 4.1 passwords
+ !0 password version char for newer passwords
+*/
+
+char get_password_version(const char *password)
+{
+ if (password==NULL) return 0;
+ if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR;
+ return 0;
+}
+
+
+/*
+ Get integer value of Hex character
+
+ SYNOPSIS
+ char_val()
+ X IN Character to find value for
+
+ RETURN
+ Appropriate integer value
+*/
+
+
+
inline uint char_val(char X)
{
return (uint) (X >= '0' && X <= '9' ? X-'0' :
@@ -98,16 +442,44 @@ inline uint char_val(char X)
X-'a'+10);
}
+
/*
-** This code assumes that len(password) is divideable with 8 and that
-** res is big enough (2 in mysql)
+ Get Binary salt from password as in mysql.user format
+
+ SYNOPSIS
+ get_salt_from_password()
+ res OUT Store binary salt here
+ password IN Password string as stored in mysql.user
+
+ RETURN
+ none
+
+ NOTE
+ This function does not have length check for passwords. It will just crash
+ Password hashes in old format must have length divisible by 8
*/
void get_salt_from_password(ulong *res,const char *password)
{
- res[0]=res[1]=0;
- if (password)
+ if (password) /* zero salt corresponds to empty password */
{
+ if (password[0]==PVERSION41_CHAR) /* if new password */
+ {
+ uint val=0;
+ uint i;
+ password++; /* skip version identifier */
+
+ /*get hashing salt from password and store in in the start of array */
+ for (i=0 ; i < 4 ; i++)
+ val=(val << 4)+char_val(*password++);
+ *res++=val;
+ }
+ /* We process old passwords the same way as new ones in other case */
+#ifdef EXTRA_DEBUG
+ if (strlen(password)%8!=0)
+ fprintf(stderr,"Warning: Incorrect password length for salting: %d\n",
+ strlen(password));
+#endif
while (*password)
{
ulong val=0;
@@ -120,33 +492,166 @@ void get_salt_from_password(ulong *res,const char *password)
return;
}
-void make_password_from_salt(char *to, ulong *hash_res)
+
+/*
+ Get string version as stored in mysql.user from salt form
+
+ SYNOPSIS
+ make_password_from_salt()
+ to OUT Store resulting string password here
+ hash_res IN Password in salt format
+ password_version
+ IN According to which version salt should be treated
+
+ RETURN
+ none
+*/
+
+void make_password_from_salt(char *to, ulong *hash_res,uint8 password_version)
{
- sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+ if (!password_version) /* Handling of old passwords. */
+ sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+ else
+ if (password_version==PVERSION41_CHAR)
+ sprintf(to,"%c%04x%08lx%08lx%08lx%08lx%08lx",PVERSION41_CHAR,(unsigned short)hash_res[0],hash_res[1],
+ hash_res[2],hash_res[3],hash_res[4],hash_res[5]);
+ else /* Just use empty password if we can't handle it. This should not happen */
+ to[0]='\0';
}
/*
- * Genererate a new message based on message and password
- * The same thing is done in client and server and the results are checked.
- */
+ Convert password in salted form to binary string password and hash-salt
+ For old password this involes one more hashing
+
+ SYNOPSIS
+ get_hash_and_password()
+ salt IN Salt to convert from
+ pversion IN Password version to use
+ hash OUT Store zero ended hash here
+ bin_password OUT Store binary password here (no zero at the end)
+
+ RETURN
+ 0 for pre 4.1 passwords
+ !0 password version char for newer passwords
+*/
+
+void get_hash_and_password(ulong *salt, uint8 pversion, char *hash,
+ unsigned char *bin_password)
+{
+ int t;
+ ulong* salt_end;
+ ulong val;
+ SHA1_CONTEXT context;
+
+ if (pversion) /* New password version assumed */
+ {
+ salt_end=salt+5;
+ sprintf(hash,"%04x",(unsigned short)salt[0]);
+ while (salt<salt_end)
+ {
+ val=*(++salt);
+ for (t=3; t>=0; t--)
+ {
+ bin_password[t]= (char) (val & 255);
+ val>>=8; /* Scroll 8 bits to get next part*/
+ }
+ bin_password+=4; /* Get to next 4 chars*/
+ }
+ }
+ else
+ {
+ unsigned char *bp= bin_password; /* Binary password loop pointer */
+
+ /* Use zero starting hash as an indication of old password */
+ hash[0]=0;
+ salt_end=salt+2;
+ /* Encode salt using SHA1 here */
+ sha1_reset(&context);
+ while (salt<salt_end) /* Iterate over these elements*/
+ {
+ val= *salt;
+ for (t=3;t>=0;t--)
+ {
+ bp[t]= (uchar) (val & 255);
+ val>>=8; /* Scroll 8 bits to get next part*/
+ }
+ bp+= 4; /* Get to next 4 chars*/
+ salt++;
+ }
+ /* Use 8 bytes of binary password for hash */
+ sha1_input(&context,(uint8*)bin_password,8);
+ sha1_result(&context,(uint8*)bin_password);
+ }
+}
+
+
+/*
+ Create key from old password to decode scramble
+ Used in 4.1 authentication with passwords stored old way
+
+ SYNOPSIS
+ create_key_from_old_password()
+ passwd IN Password used for key generation
+ key OUT Created 20 bytes key
+
+ RETURN
+ None
+*/
+
+
+void create_key_from_old_password(const char *passwd, char *key)
+{
+ char buffer[SCRAMBLE41_LENGTH]; /* Buffer for various needs */
+ ulong salt[6]; /* Salt (large for safety) */
+ /* At first hash password to the string stored in password */
+ make_scrambled_password(buffer,passwd,1,(struct rand_struct *)NULL);
+ /* Now convert it to the salt form */
+ get_salt_from_password(salt,buffer);
+ /* Finally get hash and bin password from salt */
+ get_hash_and_password(salt,0,buffer,(unsigned char*) key);
+}
+
+
+/*
+ Scramble string with password
+ Used at pre 4.1 authentication phase.
+
+ SYNOPSIS
+ scramble()
+ to OUT Store scrambled message here
+ message IN Message to scramble
+ password IN Password to use while scrambling
+ old_ver IN Forse old version random number generator
+
+ RETURN
+ End of scrambled string
+*/
char *scramble(char *to,const char *message,const char *password,
my_bool old_ver)
{
struct rand_struct rand_st;
ulong hash_pass[2],hash_message[2];
+ char message_buffer[9]; /* Real message buffer */
+ char *msg=message_buffer;
+
+ /* We use special message buffer now as new server can provide longer hash */
+
+ memcpy(message_buffer,message,8);
+ message_buffer[8]=0;
+
if (password && password[0])
{
char *to_start=to;
hash_password(hash_pass,password);
- hash_password(hash_message,message);
+ hash_password(hash_message,message_buffer);
if (old_ver)
old_randominit(&rand_st,hash_pass[0] ^ hash_message[0]);
else
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
hash_pass[1] ^ hash_message[1]);
- while (*message++)
+ while (*msg++)
*to++= (char) (floor(rnd(&rand_st)*31)+64);
if (!old_ver)
{ /* Make it harder to break */
@@ -160,15 +665,45 @@ char *scramble(char *to,const char *message,const char *password,
}
+/*
+ Check scrambled message
+ Used for pre 4.1 password handling
+
+ SYNOPSIS
+ scramble()
+ scrambled IN Scrambled message to check
+ message IN Original message which was scramble
+ hash_pass IN Password which should be used for scrambling
+ old_ver IN Forse old version random number generator
+
+ RETURN
+ 0 Password correct
+ !0 Password invalid
+*/
+
my_bool check_scramble(const char *scrambled, const char *message,
ulong *hash_pass, my_bool old_ver)
{
struct rand_struct rand_st;
ulong hash_message[2];
- char buff[16],*to,extra; /* Big enough for check */
+ char buff[16],*to,extra; /* Big enough for check */
const char *pos;
+ char message_buffer[SCRAMBLE_LENGTH+1]; /* Copy of message */
+
+ /* We need to copy the message as this function can be called for MySQL 4.1
+ scramble which is not zero ended and can have zeroes inside
+ We could just write zero to proper place in original message but
+ this would make it harder to understand code for next generations
+ */
+
+ memcpy(message_buffer,message,SCRAMBLE_LENGTH); /* Ignore the rest */
+ message_buffer[SCRAMBLE_LENGTH]=0;
+
+ /* Check if this exactly N bytes. Overwise this is something fishy */
+ if (strlen(message_buffer)!=SCRAMBLE_LENGTH)
+ return 1; /* Wrong password */
- hash_password(hash_message,message);
+ hash_password(hash_message,message_buffer);
if (old_ver)
old_randominit(&rand_st,hash_pass[0] ^ hash_message[0]);
else
diff --git a/sql/procedure.cc b/sql/procedure.cc
index 437bd82d6e5..7779f5ce085 100644
--- a/sql/procedure.cc
+++ b/sql/procedure.cc
@@ -57,7 +57,8 @@ setup_procedure(THD *thd,ORDER *param,select_result *result,
DBUG_RETURN(0);
for (i=0 ; i < array_elements(sql_procs) ; i++)
{
- if (!my_strcasecmp((*param->item)->name,sql_procs[i].name))
+ if (!my_strcasecmp(system_charset_info,
+ (*param->item)->name,sql_procs[i].name))
{
Procedure *proc=(*sql_procs[i].init)(thd,param,result,field_list);
*error= !proc;
diff --git a/sql/procedure.h b/sql/procedure.h
index 349908a8d84..03a45488b03 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -35,10 +35,10 @@ public:
}
enum Type type() const { return Item::PROC_ITEM; }
virtual void set(double nr)=0;
- virtual void set(const char *str,uint length)=0;
+ virtual void set(const char *str,uint length,CHARSET_INFO *cs)=0;
virtual void set(longlong nr)=0;
virtual enum_field_types field_type() const=0;
- void set(const char *str) { set(str,(uint) strlen(str)); }
+ void set(const char *str) { set(str,(uint) strlen(str), thd_charset()); }
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,field_type());
@@ -55,14 +55,14 @@ public:
decimals=dec; max_length=float_length(dec);
}
enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return FIELD_TYPE_DOUBLE; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void set(double nr) { value=nr; }
void set(longlong nr) { value=(double) nr; }
- void set(const char *str,uint length __attribute__((unused)))
- { value=atof(str); }
+ void set(const char *str,uint length,CHARSET_INFO *cs)
+ { int err; value=my_strntod(cs,(char*) str,length,(char**)0,&err); }
double val() { return value; }
longlong val_int() { return (longlong) value; }
- String *val_str(String *s) { s->set(value,decimals); return s; }
+ String *val_str(String *s) { s->set(value,decimals,thd_charset()); return s; }
unsigned int size_of() { return sizeof(*this);}
};
@@ -73,14 +73,14 @@ public:
Item_proc_int(const char *name_par) :Item_proc(name_par)
{ max_length=11; }
enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return FIELD_TYPE_LONG; }
+ enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
void set(double nr) { value=(longlong) nr; }
void set(longlong nr) { value=nr; }
- void set(const char *str,uint length __attribute__((unused)))
- { value=strtoll(str,NULL,10); }
+ void set(const char *str,uint length, CHARSET_INFO *cs)
+ { int err; value=my_strntoll(cs,str,length,10,NULL,&err); }
double val() { return (double) value; }
longlong val_int() { return value; }
- String *val_str(String *s) { s->set(value); return s; }
+ String *val_str(String *s) { s->set(value, thd_charset()); return s; }
unsigned int size_of() { return sizeof(*this);}
};
@@ -91,12 +91,24 @@ public:
Item_proc_string(const char *name_par,uint length) :Item_proc(name_par)
{ this->max_length=length; }
enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return FIELD_TYPE_STRING; }
- void set(double nr) { str_value.set(nr); }
- void set(longlong nr) { str_value.set(nr); }
- void set(const char *str, uint length) { str_value.copy(str,length); }
- double val() { return atof(str_value.ptr()); }
- longlong val_int() { return strtoll(str_value.ptr(),NULL,10); }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ void set(double nr) { str_value.set(nr, 2, thd_charset()); }
+ void set(longlong nr) { str_value.set(nr, thd_charset()); }
+ void set(const char *str, uint length, CHARSET_INFO *cs)
+ { str_value.copy(str,length,cs); }
+ double val()
+ {
+ int err;
+ CHARSET_INFO *cs=str_value.charset();
+ return my_strntod(cs, (char*) str_value.ptr(), str_value.length(),
+ (char**) 0, &err);
+ }
+ longlong val_int()
+ {
+ int err;
+ CHARSET_INFO *cs=str_value.charset();
+ return my_strntoll(cs,str_value.ptr(),str_value.length(),10,NULL,&err);
+ }
String *val_str(String*)
{
return null_value ? (String*) 0 : (String*) &str_value;
diff --git a/sql/protocol.cc b/sql/protocol.cc
new file mode 100644
index 00000000000..c338feea9bc
--- /dev/null
+++ b/sql/protocol.cc
@@ -0,0 +1,1085 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/*
+ Low level functions for storing data to be send to the MySQL client
+ The actual communction is handled by the net_xxx functions in net_serv.cc
+*/
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include <stdarg.h>
+
+#ifndef EMBEDDED_LIBRARY
+bool Protocol::net_store_data(const char *from, uint length)
+{
+ ulong packet_length=packet->length();
+ /*
+ The +9 comes from that strings of length longer than 16M require
+ 9 bytes to be stored (see net_store_length).
+ */
+ if (packet_length+9+length > packet->alloced_length() &&
+ packet->realloc(packet_length+9+length))
+ return 1;
+ char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
+ (ulonglong) length);
+ memcpy(to,from,length);
+ packet->length((uint) (to+length-packet->ptr()));
+ return 0;
+}
+
+inline bool Protocol::convert_str(const char *from, uint length)
+{
+ return convert->store(packet, from, length);
+}
+#endif
+
+
+ /* Send a error string to client */
+
+void send_error(THD *thd, uint sql_errno, const char *err)
+{
+ uint length;
+ char buff[MYSQL_ERRMSG_SIZE+2];
+ NET *net= &thd->net;
+ DBUG_ENTER("send_error");
+ DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
+ err ? err : net->last_error[0] ?
+ net->last_error : "NULL"));
+
+#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
+ query_cache_abort(net);
+#endif
+ thd->query_error= 1; // needed to catch query errors during replication
+ if (!err)
+ {
+ if (sql_errno)
+ err=ER(sql_errno);
+ else
+ {
+ if ((err=net->last_error)[0])
+ sql_errno=net->last_errno;
+ else
+ {
+ sql_errno=ER_UNKNOWN_ERROR;
+ err=ER(sql_errno); /* purecov: inspected */
+ }
+ }
+ }
+
+#ifdef EMBEDDED_LIBRARY
+ net->last_errno= sql_errno;
+ strmake(net->last_error, err, sizeof(net->last_error)-1);
+#else
+
+ if (net->vio == 0)
+ {
+ if (thd->bootstrap)
+ {
+ /* In bootstrap it's ok to print on stderr */
+ fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ if (net->return_errno)
+ { // new client code; Add errno before message
+ int2store(buff,sql_errno);
+ length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
+ err=buff;
+ }
+ else
+ {
+ length=(uint) strlen(err);
+ set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+ }
+ VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
+#endif /* EMBEDDED_LIBRARY*/
+ thd->is_fatal_error=0; // Error message is given
+ thd->net.report_error= 0;
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Send an error to the client when a connection is forced close
+ This is used by mysqld.cc, which doesn't have a THD
+*/
+
+#ifndef EMBEDDED_LIBRARY
+void net_send_error(NET *net, uint sql_errno, const char *err)
+{
+ char buff[2];
+ uint length;
+ DBUG_ENTER("send_net_error");
+
+ int2store(buff,sql_errno);
+ length=(uint) strlen(err);
+ set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+ net_write_command(net,(uchar) 255, buff, 2, err, length);
+ DBUG_VOID_RETURN;
+}
+#endif
+
+
+/*
+ Send a warning to the end user
+
+ SYNOPSIS
+ send_warning()
+ thd Thread handler
+ sql_errno Warning number (error message)
+ err Error string. If not set, use ER(sql_errno)
+
+ DESCRIPTION
+ Register the warning so that the user can get it with mysql_warnings()
+ Send an ok (+ warning count) to the end user.
+*/
+
+void send_warning(THD *thd, uint sql_errno, const char *err)
+{
+ DBUG_ENTER("send_warning");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
+ err ? err : ER(sql_errno));
+ send_ok(thd);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Write error package and flush to client
+ It's a little too low level, but I don't want to use another buffer for
+ this
+*/
+
+void
+net_printf(THD *thd, uint errcode, ...)
+{
+ va_list args;
+ uint length,offset;
+ const char *format;
+#ifndef EMBEDDED_LIBRARY
+ const char *text_pos;
+#else
+ char text_pos[500];
+#endif
+ int head_length= NET_HEADER_SIZE;
+ NET *net= &thd->net;
+
+ DBUG_ENTER("net_printf");
+ DBUG_PRINT("enter",("message: %u",errcode));
+
+ thd->query_error= 1; // needed to catch query errors during replication
+#ifndef EMBEDDED_LIBRARY
+ query_cache_abort(net); // Safety
+#endif
+ va_start(args,errcode);
+ /*
+ The following is needed to make net_printf() work with 0 argument for
+ errorcode and use the argument after that as the format string. This
+ is useful for rare errors that are not worth the hassle to put in
+ errmsg.sys, but at the same time, the message is not fixed text
+ */
+ if (errcode)
+ format= ER(errcode);
+ else
+ {
+ format=va_arg(args,char*);
+ errcode= ER_UNKNOWN_ERROR;
+ }
+ offset= net->return_errno ? 2 : 0;
+#ifndef EMBEDDED_LIBRARY
+ text_pos=(char*) net->buff+head_length+offset+1;
+#endif
+ (void) vsprintf(my_const_cast(char*) (text_pos),format,args);
+ length=(uint) strlen((char*) text_pos);
+ if (length >= sizeof(net->last_error))
+ length=sizeof(net->last_error)-1; /* purecov: inspected */
+ va_end(args);
+
+#ifndef EMBEDDED_LIBRARY
+ if (net->vio == 0)
+ {
+ if (thd->bootstrap)
+ {
+ /*
+ In bootstrap it's ok to print on stderr
+ This may also happen when we get an error from a slave thread
+ */
+ fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
+ thd->fatal_error();
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ int3store(net->buff,length+1+offset);
+ net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
+ net->buff[head_length]=(uchar) 255; // Error package
+ if (offset)
+ int2store(text_pos-2, errcode);
+ VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
+#else
+ net->last_errno= errcode;
+ strmake(net->last_error, text_pos, length);
+#endif
+ thd->is_fatal_error=0; // Error message is given
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Function called by my_net_init() to set some check variables
+*/
+
+#ifndef EMBEDDED_LIBRARY
+extern "C" {
+void my_net_local_init(NET *net)
+{
+ net->max_packet= (uint) global_system_variables.net_buffer_length;
+ net->read_timeout= (uint) global_system_variables.net_read_timeout;
+ net->write_timeout=(uint) global_system_variables.net_write_timeout;
+ net->retry_count= (uint) global_system_variables.net_retry_count;
+ net->max_packet_size= max(global_system_variables.net_buffer_length,
+ global_system_variables.max_allowed_packet);
+}
+}
+
+#else /* EMBEDDED_LIBRARY */
+void my_net_local_init(NET *net __attribute__(unused))
+{
+}
+#endif /* EMBEDDED_LIBRARY */
+
+/*
+ Return ok to the client.
+
+ SYNOPSIS
+ send_ok()
+ thd Thread handler
+ affected_rows Number of rows changed by statement
+ id Auto_increment id for first row (if used)
+ message Message to send to the client (Used by mysql_status)
+
+ DESCRIPTION
+ The ok packet has the following structure
+
+ 0 Marker (1 byte)
+ affected_rows Stored in 1-9 bytes
+ id Stored in 1-9 bytes
+ server_status Copy of thd->server_status; Can be used by client
+ to check if we are inside an transaction
+ New in 4.0 protocol
+ warning_count Stored in 2 bytes; New in 4.1 protocol
+ message Stored as packed length (1-9 bytes) + message
+ Is not stored if no message
+
+ If net->no_send_ok return without sending packet
+*/
+
+#ifndef EMBEDDED_LIBRARY
+void
+send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
+{
+ NET *net= &thd->net;
+ if (net->no_send_ok || !net->vio) // hack for re-parsing queries
+ return;
+
+ char buff[MYSQL_ERRMSG_SIZE+10],*pos;
+ DBUG_ENTER("send_ok");
+ buff[0]=0; // No fields
+ pos=net_store_length(buff+1,(ulonglong) affected_rows);
+ pos=net_store_length(pos, (ulonglong) id);
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ int2store(pos,thd->server_status);
+ pos+=2;
+
+ /* We can only return up to 65535 warnings in two bytes */
+ uint tmp= min(thd->total_warn_count, 65535);
+ int2store(pos, tmp);
+ pos+= 2;
+ }
+ else if (net->return_status) // For 4.0 protocol
+ {
+ int2store(pos,thd->server_status);
+ pos+=2;
+ }
+ if (message)
+ pos=net_store_data((char*) pos, message, strlen(message));
+ VOID(my_net_write(net,buff,(uint) (pos-buff)));
+ VOID(net_flush(net));
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Send eof (= end of result set) to the client
+
+ SYNOPSIS
+ send_eof()
+ thd Thread handler
+ no_flush Set to 1 if there will be more data to the client,
+ like in send_fields().
+
+ DESCRIPTION
+ The eof packet has the following structure
+
+ 254 Marker (1 byte)
+ warning_count Stored in 2 bytes; New in 4.1 protocol
+ status_flag Stored in 2 bytes;
+ For flags like SERVER_STATUS_MORE_RESULTS
+
+ Note that the warning count will not be sent if 'no_flush' is set as
+ we don't want to report the warning count until all data is sent to the
+ client.
+*/
+
+void
+send_eof(THD *thd, bool no_flush)
+{
+ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
+ NET *net= &thd->net;
+ DBUG_ENTER("send_eof");
+ if (net->vio != 0)
+ {
+ if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
+ {
+ uchar buff[5];
+ uint tmp= min(thd->total_warn_count, 65535);
+ buff[0]=254;
+ int2store(buff+1, tmp);
+ int2store(buff+3, 0); // No flags yet
+ VOID(my_net_write(net,(char*) buff,5));
+ VOID(net_flush(net));
+ }
+ else
+ {
+ VOID(my_net_write(net,eof_buff,1));
+ if (!no_flush)
+ VOID(net_flush(net));
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+#endif /* EMBEDDED_LIBRARY */
+
+
+/****************************************************************************
+ Store a field length in logical packet
+ This is used to code the string length for normal protocol
+****************************************************************************/
+
+char *
+net_store_length(char *pkg, ulonglong length)
+{
+ uchar *packet=(uchar*) pkg;
+ if (length < LL(251))
+ {
+ *packet=(uchar) length;
+ return (char*) packet+1;
+ }
+ /* 251 is reserved for NULL */
+ if (length < LL(65536))
+ {
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+ }
+ if (length < LL(16777216))
+ {
+ *packet++=253;
+ int3store(packet,(ulong) length);
+ return (char*) packet+3;
+ }
+ *packet++=254;
+ int8store(packet,length);
+ return (char*) packet+8;
+}
+
+
+/*
+ Faster net_store_length when we know length is a 32 bit integer
+*/
+
+char *net_store_length(char *pkg, uint length)
+{
+ uchar *packet=(uchar*) pkg;
+ if (length < 251)
+ {
+ *packet=(uchar) length;
+ return (char*) packet+1;
+ }
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+}
+
+
+/****************************************************************************
+ Functions used by the protocol functions (like send_ok) to store strings
+ and numbers in the header result packet.
+****************************************************************************/
+
+/* The following will only be used for short strings < 65K */
+
+char *net_store_data(char *to,const char *from, uint length)
+{
+ to=net_store_length(to,length);
+ memcpy(to,from,length);
+ return to+length;
+}
+
+char *net_store_data(char *to,int32 from)
+{
+ char buff[20];
+ uint length=(uint) (int10_to_str(from,buff,10)-buff);
+ to=net_store_length(to,length);
+ memcpy(to,buff,length);
+ return to+length;
+}
+
+char *net_store_data(char *to,longlong from)
+{
+ char buff[22];
+ uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
+ to=net_store_length(to,length);
+ memcpy(to,buff,length);
+ return to+length;
+}
+
+
+/*****************************************************************************
+ Default Protocol functions
+*****************************************************************************/
+
+void Protocol::init(THD *thd_arg)
+{
+ thd=thd_arg;
+ convert=thd->variables.convert_set;
+ packet= &thd->packet;
+#ifndef DEBUG_OFF
+ field_types= 0;
+#endif
+}
+
+
+/*
+ Send name and type of result to client.
+
+ SYNOPSIS
+ send_fields()
+ THD Thread data object
+ list List of items to send to client
+ convert object used to convertation to another character set
+ flag Bit mask with the following functions:
+ 1 send number of rows
+ 2 send default values
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+ Uses send_fields_convert() and send_fields() depending on
+ if we have an active character set convert or not.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Note that in this case the error is not sent to the client)
+*/
+
+#ifndef EMBEDDED_LIBRARY
+bool Protocol::send_fields(List<Item> *list, uint flag)
+{
+ List_iterator_fast<Item> it(*list);
+ Item *item;
+ char buff[80];
+ String tmp((char*) buff,sizeof(buff),default_charset_info);
+ Protocol_simple prot(thd);
+ String *packet= prot.storage_packet();
+ DBUG_ENTER("send_fields");
+
+ if (flag & 1)
+ { // Packet with number of elements
+ char *pos=net_store_length(buff, (uint) list->elements);
+ (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
+ }
+
+#ifndef DEBUG_OFF
+ field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
+ list->elements);
+ uint count= 0;
+#endif
+
+ while ((item=it++))
+ {
+ char *pos;
+ Send_field field;
+ item->make_field(&field);
+ prot.prepare_for_resend();
+
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ if (prot.store(field.db_name, (uint) strlen(field.db_name)) ||
+ prot.store(field.table_name, (uint) strlen(field.table_name)) ||
+ prot.store(field.org_table_name,
+ (uint) strlen(field.org_table_name)) ||
+ prot.store(field.col_name, (uint) strlen(field.col_name)) ||
+ prot.store(field.org_col_name, (uint) strlen(field.org_col_name)) ||
+ packet->realloc(packet->length()+12))
+ goto err;
+ /* Store fixed length fields */
+ pos= (char*) packet->ptr()+packet->length();
+ *pos++= 11; // Length of packed fields
+ int2store(pos, field.charsetnr);
+ int3store(pos+2, field.length);
+ pos[5]= field.type;
+ int2store(pos+6,field.flags);
+ pos[8]= (char) field.decimals;
+ pos[9]= 0; // For the future
+ pos[10]= 0; // For the future
+ pos+= 11;
+ }
+ else
+ {
+ if (prot.store(field.table_name, (uint) strlen(field.table_name)) ||
+ prot.store(field.col_name, (uint) strlen(field.col_name)) ||
+ packet->realloc(packet->length()+10))
+ goto err;
+ pos= (char*) packet->ptr()+packet->length();
+
+#ifdef TO_BE_DELETED_IN_6
+ if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
+ {
+ pos[0]=3;
+ int3store(pos+1,field.length);
+ pos[4]=1;
+ pos[5]=field.type;
+ pos[6]=2;
+ pos[7]= (char) field.flags;
+ pos[8]= (char) field.decimals;
+ pos+= 9;
+ }
+ else
+#endif
+ {
+ pos[0]=3;
+ int3store(pos+1,field.length);
+ pos[4]=1;
+ pos[5]=field.type;
+ pos[6]=3;
+ int2store(pos+7,field.flags);
+ pos[9]= (char) field.decimals;
+ pos+= 10;
+ }
+ }
+ packet->length((uint) (pos - packet->ptr()));
+ if (flag & 2)
+ item->send(&prot, &tmp); // Send default value
+ if (prot.write())
+ break; /* purecov: inspected */
+#ifndef DEBUG_OFF
+ field_types[count++]= field.type;
+#endif
+ }
+
+ send_eof(thd);
+ DBUG_RETURN(prepare_for_send(list));
+
+err:
+ send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
+}
+
+
+bool Protocol::send_records_num(List<Item> *list, ulonglong records)
+{
+ char *pos;
+ char buff[20];
+ pos=net_store_length(buff, (uint) list->elements);
+ pos=net_store_length(pos, records);
+ return my_net_write(&thd->net, buff,(uint) (pos-buff));
+}
+
+
+bool Protocol::write()
+{
+ DBUG_ENTER("Protocol::write");
+ DBUG_RETURN(my_net_write(&thd->net, packet->ptr(), packet->length()));
+}
+#endif /* EMBEDDED_LIBRARY */
+
+
+/*
+ Send \0 end terminated string
+
+ SYNOPSIS
+ store()
+ from NullS or \0 terminated string
+
+ NOTES
+ In most cases one should use store(from, length) instead of this function
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+bool Protocol::store(const char *from)
+{
+ if (!from)
+ return store_null();
+ uint length= strlen(from);
+ return store(from, length);
+}
+
+
+/*
+ Send a set of strings as one long string with ',' in between
+*/
+
+bool Protocol::store(I_List<i_string>* str_list)
+{
+ char buf[256];
+ String tmp(buf, sizeof(buf), default_charset_info);
+ uint32 len;
+ I_List_iterator<i_string> it(*str_list);
+ i_string* s;
+
+ tmp.length(0);
+ while ((s=it++))
+ {
+ tmp.append(s->ptr);
+ tmp.append(',');
+ }
+ if ((len= tmp.length()))
+ len--; // Remove last ','
+ return store((char*) tmp.ptr(), len);
+}
+
+
+/****************************************************************************
+ Functions to handle the simple (default) protocol where everything is
+ This protocol is the one that is used by default between the MySQL server
+ and client when you are not using prepared statements.
+
+ All data are sent as 'packed-string-length' followed by 'string-data'
+****************************************************************************/
+
+#ifndef EMBEDDED_LIBRARY
+void Protocol_simple::prepare_for_resend()
+{
+ packet->length(0);
+#ifndef DEBUG_OFF
+ field_pos= 0;
+#endif
+}
+
+bool Protocol_simple::store_null()
+{
+#ifndef DEBUG_OFF
+ field_pos++;
+#endif
+ char buff[1];
+ buff[0]= (char)251;
+ return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
+}
+#endif
+
+
+bool Protocol_simple::store(const char *from, uint length)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
+ field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
+ field_pos++;
+#endif
+ if (convert)
+ return convert_str(from, length);
+ return net_store_data(from, length);
+}
+
+
+bool Protocol_simple::store_tiny(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_TINY);
+#endif
+ char buff[20];
+ return net_store_data((char*) buff,
+ (uint) (int10_to_str((int) from,buff, -10)-buff));
+}
+
+
+bool Protocol_simple::store_short(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_SHORT);
+#endif
+ char buff[20];
+ return net_store_data((char*) buff,
+ (uint) (int10_to_str((int) from,buff, -10)-buff));
+}
+
+
+bool Protocol_simple::store_long(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_LONG);
+#endif
+ char buff[20];
+ return net_store_data((char*) buff,
+ (uint) (int10_to_str((int) from,buff, -10)-buff));
+}
+
+
+bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_LONGLONG);
+#endif
+ char buff[22];
+ return net_store_data((char*) buff,
+ (uint) (longlong10_to_str(from,buff,
+ unsigned_flag ? 10 : -10)-
+ buff));
+}
+
+
+bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_FLOAT);
+#endif
+ buffer->set((double) from, decimals, thd->variables.thd_charset);
+ return net_store_data((char*) buffer->ptr(), buffer->length());
+}
+
+
+bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_DOUBLE);
+#endif
+ buffer->set(from, decimals, thd->variables.thd_charset);
+ return net_store_data((char*) buffer->ptr(), buffer->length());
+}
+
+
+bool Protocol_simple::store(Field *field)
+{
+ if (field->is_null())
+ return store_null();
+#ifndef DEBUG_OFF
+ field_pos++;
+#endif
+ char buff[MAX_FIELD_WIDTH];
+ String tmp(buff,sizeof(buff),default_charset_info);
+ field->val_str(&tmp,&tmp);
+ if (convert)
+ return convert_str(tmp.ptr(), tmp.length());
+ return net_store_data(tmp.ptr(), tmp.length());
+}
+
+
+bool Protocol_simple::store(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DATETIME ||
+ field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
+ field_pos++;
+#endif
+ char buff[40];
+ uint length;
+ length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
+ (int) tm->year,
+ (int) tm->month,
+ (int) tm->day,
+ (int) tm->hour,
+ (int) tm->minute,
+ (int) tm->second));
+ return net_store_data((char*) buff, length);
+}
+
+
+bool Protocol_simple::store_date(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_DATE);
+#endif
+ char buff[40];
+ uint length;
+ length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
+ (int) tm->year,
+ (int) tm->month,
+ (int) tm->day));
+ return net_store_data((char*) buff, length);
+}
+
+
+bool Protocol_simple::store_time(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos++] == MYSQL_TYPE_TIME);
+#endif
+ char buff[40];
+ uint length;
+ length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
+ tm->neg ? "-" : "",
+ (long) tm->day*3600L+(long) tm->hour,
+ (int) tm->minute,
+ (int) tm->second));
+ return net_store_data((char*) buff, length);
+}
+
+
+/****************************************************************************
+ Functions to handle the binary protocol used with prepared statements
+
+ Data format:
+
+ [ok:1] reserved ok packet
+ [null_field:(field_count+7+2)/8] reserved to send null data. The size is
+ calculated using:
+ bit_fields= (field_count+7+2)/8;
+ 2 bits are reserved for identifying type
+ of package.
+ [[length]data] data field (the length applies only for
+ string/binary/time/timestamp fields and
+ rest of them are not sent as they have
+ the default length that client understands
+ based on the field type
+ [..]..[[length]data] data
+****************************************************************************/
+
+bool Protocol_prep::prepare_for_send(List<Item> *item_list)
+{
+ Protocol::prepare_for_send(item_list);
+ bit_fields= (field_count+9)/8;
+ if (packet->alloc(bit_fields+1))
+ return 1;
+ /* prepare_for_resend will be called after this one */
+ return 0;
+}
+
+
+void Protocol_prep::prepare_for_resend()
+{
+ packet->length(bit_fields+1);
+ bzero((char*) packet->ptr(), 1+bit_fields);
+ field_pos=0;
+}
+
+
+bool Protocol_prep::store(const char *from,uint length)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
+ field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
+#endif
+ field_pos++;
+ if (convert)
+ return convert_str(from, length);
+ return net_store_data(from, length);
+}
+
+bool Protocol_prep::store_null()
+{
+ uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
+ /* Room for this as it's allocated in prepare_for_send */
+ char *to= (char*) packet->ptr()+offset;
+ *to= (char) ((uchar) *to | (uchar) bit);
+ field_pos++;
+ return 0;
+}
+
+
+bool Protocol_prep::store_tiny(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_TINY);
+#endif
+ char buff[1];
+ field_pos++;
+ buff[0]= (uchar) from;
+ return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
+}
+
+
+bool Protocol_prep::store_short(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_SHORT ||
+ field_types[field_pos] == MYSQL_TYPE_YEAR);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(2, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ int2store(to, (int) from);
+ return 0;
+}
+
+
+bool Protocol_prep::store_long(longlong from)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_INT24 ||
+ field_types[field_pos] == MYSQL_TYPE_LONG);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ int4store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_LONGLONG);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ int8store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_FLOAT);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ float4store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DOUBLE);
+#endif
+ field_pos++;
+ char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
+ if (!to)
+ return 1;
+ float8store(to, from);
+ return 0;
+}
+
+
+bool Protocol_prep::store(Field *field)
+{
+ /*
+ We should not increment field_pos here as send_binary() will call another
+ protocol function to do this for us
+ */
+ if (field->is_null())
+ return store_null();
+ return field->send_binary(this);
+}
+
+
+bool Protocol_prep::store(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_DATETIME ||
+ field_types[field_pos] == MYSQL_TYPE_DATE ||
+ field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
+#endif
+ char buff[12],*pos;
+ uint length;
+ field_pos++;
+ pos= buff+1;
+
+ int2store(pos, tm->year);
+ pos[2]= (uchar) tm->month;
+ pos[3]= (uchar) tm->day;
+ pos[4]= (uchar) tm->hour;
+ pos[5]= (uchar) tm->minute;
+ pos[6]= (uchar) tm->second;
+ int4store(pos+7, tm->second_part);
+ if (tm->second_part)
+ length=11;
+ else if (tm->hour || tm->minute || tm->second)
+ length=7;
+ else if (tm->year || tm->month || tm->day)
+ length=4;
+ else
+ length=0;
+ buff[0]=(char) length; // Length is stored first
+ return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
+}
+
+bool Protocol_prep::store_date(TIME *tm)
+{
+ tm->hour= tm->minute= tm->second=0;
+ tm->second_part= 0;
+ return Protocol_prep::store(tm);
+}
+
+
+bool Protocol_prep::store_time(TIME *tm)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_TIME);
+#endif
+ char buff[15],*pos;
+ uint length;
+ field_pos++;
+ pos= buff+1;
+ pos[0]= tm->neg ? 1 : 0;
+ int4store(pos+1, tm->day);
+ pos[5]= (uchar) tm->hour;
+ pos[6]= (uchar) tm->minute;
+ pos[7]= (uchar) tm->second;
+ int4store(pos+8, tm->second_part);
+ if (tm->second_part)
+ length=11;
+ else if (tm->hour || tm->minute || tm->second || tm->day)
+ length=8;
+ else
+ length=0;
+ buff[0]=(char) length; // Length is stored first
+ return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
+}
diff --git a/sql/protocol.h b/sql/protocol.h
new file mode 100644
index 00000000000..f57652af670
--- /dev/null
+++ b/sql/protocol.h
@@ -0,0 +1,144 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
+#define PACKET_BUFFET_EXTRA_ALLOC 1024
+
+class CONVERT;
+class i_string;
+class THD;
+#ifdef EMBEDDED_LIBRARY
+typedef struct st_mysql_field MYSQL_FIELD;
+#endif
+class Protocol
+{
+protected:
+ THD *thd;
+ String *packet;
+ uint field_pos;
+#ifndef DEBUG_OFF
+ enum enum_field_types *field_types;
+#endif
+ uint field_count;
+ bool net_store_data(const char *from, uint length);
+ bool convert_str(const char *from, uint length);
+#ifdef EMBEDDED_LIBRARY
+ char **next_field;
+ MYSQL_FIELD *next_mysql_field;
+ MEM_ROOT *alloc;
+#endif
+public:
+ CONVERT *convert;
+
+ Protocol() {}
+ Protocol(THD *thd) { init(thd); }
+ void init(THD* thd);
+ bool send_fields(List<Item> *list, uint flag);
+ bool send_records_num(List<Item> *list, ulonglong records);
+ bool store(I_List<i_string> *str_list);
+ bool store(const char *from);
+ String *storage_packet() { return packet; }
+ inline void free() { packet->free(); }
+ bool write();
+ inline bool store(uint32 from)
+ { return store_long((longlong) from); }
+ inline bool store(longlong from)
+ { return store_longlong((longlong) from, 0); }
+ inline bool store(ulonglong from)
+ { return store_longlong((longlong) from, 1); }
+
+ virtual bool prepare_for_send(List<Item> *item_list)
+ {
+ field_count=item_list->elements;
+ return 0;
+ }
+ virtual void prepare_for_resend()=0;
+
+ virtual bool store_null()=0;
+ virtual bool store_tiny(longlong from)=0;
+ virtual bool store_short(longlong from)=0;
+ virtual bool store_long(longlong from)=0;
+ virtual bool store_longlong(longlong from, bool unsigned_flag)=0;
+ virtual bool store(const char *from, uint length)=0;
+ virtual bool store(float from, uint32 decimals, String *buffer)=0;
+ virtual bool store(double from, uint32 decimals, String *buffer)=0;
+ virtual bool store(TIME *time)=0;
+ virtual bool store_date(TIME *time)=0;
+ virtual bool store_time(TIME *time)=0;
+ virtual bool store(Field *field)=0;
+};
+
+
+/* Class used for the old (MySQL 4.0 protocol) */
+
+class Protocol_simple :public Protocol
+{
+public:
+ Protocol_simple() {}
+ Protocol_simple(THD *thd) :Protocol(thd) {}
+ virtual void prepare_for_resend();
+ virtual bool store_null();
+ virtual bool store_tiny(longlong from);
+ virtual bool store_short(longlong from);
+ virtual bool store_long(longlong from);
+ virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store(const char *from, uint length);
+ virtual bool store(TIME *time);
+ virtual bool store_date(TIME *time);
+ virtual bool store_time(TIME *time);
+ virtual bool store(float nr, uint32 decimals, String *buffer);
+ virtual bool store(double from, uint32 decimals, String *buffer);
+ virtual bool store(Field *field);
+};
+
+
+class Protocol_prep :public Protocol
+{
+private:
+ uint bit_fields;
+public:
+ Protocol_prep() {}
+ Protocol_prep(THD *thd) :Protocol(thd) {}
+ virtual bool prepare_for_send(List<Item> *item_list);
+ virtual void prepare_for_resend();
+ virtual bool store_null();
+ virtual bool store_tiny(longlong from);
+ virtual bool store_short(longlong from);
+ virtual bool store_long(longlong from);
+ virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store(const char *from,uint length);
+ virtual bool store(TIME *time);
+ virtual bool store_date(TIME *time);
+ virtual bool store_time(TIME *time);
+ virtual bool store(float nr, uint32 decimals, String *buffer);
+ virtual bool store(double from, uint32 decimals, String *buffer);
+ virtual bool store(Field *field);
+};
+
+void send_warning(THD *thd, uint sql_errno, const char *err=0);
+void net_printf(THD *thd,uint sql_errno, ...);
+void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
+ const char *info=0);
+void send_eof(THD *thd, bool no_flush=0);
+void net_send_error(NET *net, uint sql_errno, const char *err);
+char *net_store_length(char *packet,ulonglong length);
+char *net_store_length(char *packet,uint length);
+char *net_store_data(char *to,const char *from, uint length);
+char *net_store_data(char *to,int32 from);
+char *net_store_data(char *to,longlong from);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index cbb30cafdc4..9a7fb2282f4 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -17,6 +17,8 @@
// Sasha Pachev <sasha@mysql.com> is currently in charge of this file
#include "mysql_priv.h"
+#ifdef HAVE_REPLICATION
+
#include "repl_failsafe.h"
#include "sql_repl.h"
#include "slave.h"
@@ -184,7 +186,7 @@ err:
my_message(ER_UNKNOWN_ERROR, "Wrong parameters to function register_slave",
MYF(0));
err2:
- send_error(&thd->net);
+ send_error(thd);
return 1;
}
@@ -203,7 +205,7 @@ extern "C" void slave_info_free(void *s)
void init_slave_list()
{
- hash_init(&slave_list, SLAVE_LIST_CHUNK, 0, 0,
+ hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
(hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0);
pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
}
@@ -416,6 +418,7 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
int show_new_master(THD* thd)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_new_master");
List<Item> field_list;
char errmsg[SLAVE_ERRMSG_SIZE];
@@ -431,17 +434,17 @@ int show_new_master(THD* thd)
}
else
{
- String* packet = &thd->packet;
field_list.push_back(new Item_empty_string("Log_name", 20));
- field_list.push_back(new Item_empty_string("Log_pos", 20));
- if (send_fields(thd, field_list, 1))
+ field_list.push_back(new Item_return_int("Log_pos", 10,
+ MYSQL_TYPE_LONGLONG));
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
- packet->length(0);
- net_store_data(packet, lex_mi->log_file_name);
- net_store_data(packet, (longlong)lex_mi->pos);
- if (my_net_write(&thd->net, packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(lex_mi->log_file_name);
+ protocol->store((ulonglong) lex_mi->pos);
+ if (protocol->write())
DBUG_RETURN(-1);
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
}
@@ -456,7 +459,7 @@ int update_slave_list(MYSQL* mysql)
int port_ind;
DBUG_ENTER("update_slave_list");
- if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",0) ||
+ if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",16) ||
!(res = mc_mysql_store_result(mysql)))
{
error = "Query error";
@@ -580,21 +583,24 @@ int show_slave_hosts(THD* thd)
{
List<Item> field_list;
NET* net = &thd->net;
- String* packet = &thd->packet;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_slave_hosts");
- field_list.push_back(new Item_empty_string("Server_id", 20));
+ field_list.push_back(new Item_return_int("Server_id", 10,
+ MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Host", 20));
if (opt_show_slave_auth_info)
{
field_list.push_back(new Item_empty_string("User",20));
field_list.push_back(new Item_empty_string("Password",20));
}
- field_list.push_back(new Item_empty_string("Port",20));
- field_list.push_back(new Item_empty_string("Rpl_recovery_rank", 20));
- field_list.push_back(new Item_empty_string("Master_id", 20));
+ field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Rpl_recovery_rank", 7,
+ MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Master_id", 10,
+ MYSQL_TYPE_LONG));
- if (send_fields(thd, field_list, 1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
pthread_mutex_lock(&LOCK_slave_list);
@@ -602,25 +608,25 @@ int show_slave_hosts(THD* thd)
for (uint i = 0; i < slave_list.records; ++i)
{
SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
- packet->length(0);
- net_store_data(packet, si->server_id);
- net_store_data(packet, si->host);
+ protocol->prepare_for_resend();
+ protocol->store((uint32) si->server_id);
+ protocol->store(si->host);
if (opt_show_slave_auth_info)
{
- net_store_data(packet, si->user);
- net_store_data(packet, si->password);
+ protocol->store(si->user);
+ protocol->store(si->password);
}
- net_store_data(packet, (uint32) si->port);
- net_store_data(packet, si->rpl_recovery_rank);
- net_store_data(packet, si->master_id);
- if (my_net_write(net, (char*)packet->ptr(), packet->length()))
+ protocol->store((uint32) si->port);
+ protocol->store((uint32) si->rpl_recovery_rank);
+ protocol->store((uint32) si->master_id);
+ if (protocol->write())
{
pthread_mutex_unlock(&LOCK_slave_list);
DBUG_RETURN(-1);
}
}
pthread_mutex_unlock(&LOCK_slave_list);
- send_eof(net);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -706,7 +712,7 @@ int load_master_data(THD* thd)
(error=terminate_slave_threads(active_mi,restart_thread_mask,
1 /*skip lock*/)))
{
- send_error(&thd->net,error);
+ send_error(thd,error);
unlock_slave_threads(active_mi);
UNLOCK_ACTIVE_MI;
return 1;
@@ -714,7 +720,7 @@ int load_master_data(THD* thd)
if (connect_to_master(thd, &mysql, active_mi))
{
- net_printf(&thd->net, error= ER_CONNECT_TO_MASTER,
+ net_printf(thd, error= ER_CONNECT_TO_MASTER,
mc_mysql_error(&mysql));
goto err;
}
@@ -724,10 +730,10 @@ int load_master_data(THD* thd)
MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res;
uint num_dbs;
- if (mc_mysql_query(&mysql, "show databases", 0) ||
+ if (mc_mysql_query(&mysql, "SHOW DATABASES", 14) ||
!(db_res = mc_mysql_store_result(&mysql)))
{
- net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ net_printf(thd, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql));
goto err;
}
@@ -741,7 +747,7 @@ int load_master_data(THD* thd)
if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
{
- net_printf(&thd->net, error = ER_OUTOFMEMORY);
+ net_printf(thd, error = ER_OUTOFMEMORY);
goto err;
}
@@ -751,11 +757,11 @@ int load_master_data(THD* thd)
we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
can to minimize the lock time.
*/
- if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 0) ||
- mc_mysql_query(&mysql, "SHOW MASTER STATUS",0) ||
+ if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 27) ||
+ mc_mysql_query(&mysql, "SHOW MASTER STATUS",18) ||
!(master_status_res = mc_mysql_store_result(&mysql)))
{
- net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ net_printf(thd, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql));
goto err;
}
@@ -795,16 +801,16 @@ int load_master_data(THD* thd)
if (mysql_rm_db(thd, db, 1,1) ||
mysql_create_db(thd, db, 0, 1))
{
- send_error(&thd->net, 0, 0);
+ send_error(thd, 0, 0);
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
}
if (mc_mysql_select_db(&mysql, db) ||
- mc_mysql_query(&mysql, "show tables", 0) ||
+ mc_mysql_query(&mysql, "SHOW TABLES", 11) ||
!(*cur_table_res = mc_mysql_store_result(&mysql)))
{
- net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ net_printf(thd, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql));
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
@@ -845,9 +851,9 @@ int load_master_data(THD* thd)
mc_mysql_free_result(master_status_res);
}
- if (mc_mysql_query(&mysql, "UNLOCK TABLES", 0))
+ if (mc_mysql_query(&mysql, "UNLOCK TABLES", 13))
{
- net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ net_printf(thd, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql));
goto err;
}
@@ -857,7 +863,7 @@ int load_master_data(THD* thd)
0 /* not only reset, but also reinit */,
&errmsg))
{
- send_error(&thd->net, 0, "Failed purging old relay logs");
+ send_error(thd, 0, "Failed purging old relay logs");
unlock_slave_threads(active_mi);
UNLOCK_ACTIVE_MI;
return 1;
@@ -885,7 +891,10 @@ err:
mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init()
if (!error)
- send_ok(&thd->net);
+ send_ok(thd);
return error;
}
+
+#endif /* HAVE_REPLICATION */
+
diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h
index ef1dc1f8778..72ea0cf2a56 100644
--- a/sql/repl_failsafe.h
+++ b/sql/repl_failsafe.h
@@ -1,3 +1,4 @@
+#ifdef HAVE_REPLICATION
#ifndef REPL_FAILSAFE_H
#define REPL_FAILSAFE_H
@@ -35,3 +36,4 @@ int register_slave(THD* thd, uchar* packet, uint packet_length);
void unregister_slave(THD* thd, bool only_mine, bool need_mutex);
#endif
+#endif /* HAVE_REPLICATION */
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 5cfd027bc58..5686adb765e 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -21,11 +21,14 @@
- If the variable is thread specific, add it to 'system_variables' struct.
If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
+ - Don't forget to initialize new fields in global_system_variables and
+ max_system_variables!
- Use one of the 'sys_var... classes from set_var.h or write a specific
one for the variable type.
- Define it in the 'variable definition list' in this file.
- - If the variable should be changeable, it should be added to the
- 'list of all variables' list in this file.
+ - If the variable should be changeable or one should be able to access it
+ with @@variable_name, it should be added to the 'list of all variables'
+ list in this file.
- If the variable should be changed from the command line, add a definition
of it in the my_option structure list in mysqld.dcc
- If the variable should show up in 'show variables' add it to the
@@ -44,6 +47,7 @@
#endif
#include "mysql_priv.h"
+#include <mysql.h>
#include "slave.h"
#include "sql_acl.h"
#include <my_getopt.h>
@@ -82,6 +86,8 @@ static void fix_net_retry_count(THD *thd, enum_var_type type);
static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_key_buffer_size(THD *thd, enum_var_type type);
+static byte *get_error_count(THD *thd);
+static byte *get_warning_count(THD *thd);
/*
Variable definition list
@@ -147,8 +153,12 @@ sys_var_long_ptr sys_max_connect_errors("max_connect_errors",
&max_connect_errors);
sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads",
&max_insert_delayed_threads);
+sys_var_thd_ulong sys_max_error_count("max_error_count",
+ &SV::max_error_count);
sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
&SV::max_heap_table_size);
+sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id",
+ &SV::pseudo_thread_id);
sys_var_thd_ha_rows sys_max_join_size("max_join_size",
&SV::max_join_size,
fix_max_join_size);
@@ -157,6 +167,8 @@ sys_var_thd_ha_rows sys_sql_max_join_size("sql_max_join_size",
&SV::max_join_size,
fix_max_join_size);
#endif
+sys_var_thd_ulong sys_max_prep_stmt_count("max_prepared_statements",
+ &SV::max_prep_stmt_count);
sys_var_thd_ulong sys_max_sort_length("max_sort_length",
&SV::max_sort_length);
sys_var_long_ptr sys_max_user_connections("max_user_connections",
@@ -198,14 +210,18 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type",
sys_var_long_ptr sys_server_id("server_id",&server_id);
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol);
+#ifdef HAVE_REPLICATION
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
&slave_net_timeout);
+#endif
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
&slow_launch_time);
sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
&SV::sortbuff_size);
-sys_var_thd_enum sys_table_type("table_type", &SV::table_type,
- &ha_table_typelib);
+sys_var_thd_sql_mode sys_sql_mode("sql_mode",
+ &SV::sql_mode);
+sys_var_thd_enum sys_table_type("table_type", &SV::table_type,
+ &ha_table_typelib);
sys_var_long_ptr sys_table_cache_size("table_cache",
&table_cache_size);
sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
@@ -218,8 +234,6 @@ sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout);
-
-
/*
Variables that are bits in THD
*/
@@ -281,8 +295,19 @@ static sys_var_timestamp sys_timestamp("timestamp");
static sys_var_last_insert_id sys_last_insert_id("last_insert_id");
static sys_var_last_insert_id sys_identity("identity");
static sys_var_insert_id sys_insert_id("insert_id");
+static sys_var_readonly sys_error_count("error_count",
+ OPT_SESSION,
+ SHOW_LONG,
+ get_error_count);
+static sys_var_readonly sys_warning_count("warning_count",
+ OPT_SESSION,
+ SHOW_LONG,
+ get_warning_count);
+
/* alias for last_insert_id() to be compatible with Sybase */
+#ifdef HAVE_REPLICATION
static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
+#endif
static sys_var_rand_seed1 sys_rand_seed1("rand_seed1");
static sys_var_rand_seed2 sys_rand_seed2("rand_seed2");
@@ -311,6 +336,7 @@ sys_var *sys_variables[]=
&sys_delayed_insert_limit,
&sys_delayed_insert_timeout,
&sys_delayed_queue_size,
+ &sys_error_count,
&sys_flush,
&sys_flush_time,
&sys_foreign_key_checks,
@@ -333,8 +359,10 @@ sys_var *sys_variables[]=
&sys_max_connect_errors,
&sys_max_connections,
&sys_max_delayed_threads,
+ &sys_max_error_count,
&sys_max_heap_table_size,
&sys_max_join_size,
+ &sys_max_prep_stmt_count,
&sys_max_sort_length,
&sys_max_tmp_tables,
&sys_max_user_connections,
@@ -347,6 +375,7 @@ sys_var *sys_variables[]=
&sys_net_retry_count,
&sys_net_wait_timeout,
&sys_net_write_timeout,
+ &sys_pseudo_thread_id,
&sys_query_cache_size,
#ifdef HAVE_QUERY_CACHE
&sys_query_cache_limit,
@@ -361,14 +390,17 @@ sys_var *sys_variables[]=
&sys_safe_updates,
&sys_select_limit,
&sys_server_id,
+#ifdef HAVE_REPLICATION
&sys_slave_compressed_protocol,
&sys_slave_net_timeout,
&sys_slave_skip_counter,
+#endif
&sys_slow_launch_time,
&sys_sort_buffer,
&sys_sql_big_tables,
&sys_sql_low_priority_updates,
&sys_sql_max_join_size,
+ &sys_sql_mode,
&sys_sql_warnings,
&sys_table_cache_size,
&sys_table_type,
@@ -376,7 +408,8 @@ sys_var *sys_variables[]=
&sys_timestamp,
&sys_tmp_table_size,
&sys_tx_isolation,
- &sys_unique_checks
+ &sys_unique_checks,
+ &sys_warning_count
};
@@ -428,6 +461,7 @@ struct show_var_st init_vars[]= {
#ifdef HAVE_INNOBASE_DB
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
{"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
+ {"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG },
{"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
{"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
{"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
@@ -457,7 +491,9 @@ struct show_var_st init_vars[]= {
{"log", (char*) &opt_log, SHOW_BOOL},
{"log_update", (char*) &opt_update_log, SHOW_BOOL},
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
+#ifdef HAVE_REPLICATION
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL},
+#endif
{"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
{sys_log_warnings.name, (char*) &sys_log_warnings, SHOW_SYS},
{sys_long_query_time.name, (char*) &sys_long_query_time, SHOW_SYS},
@@ -468,9 +504,11 @@ struct show_var_st init_vars[]= {
{sys_max_binlog_size.name, (char*) &sys_max_binlog_size, SHOW_SYS},
{sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS},
{sys_max_connect_errors.name, (char*) &sys_max_connect_errors, SHOW_SYS},
+ {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS},
{sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads, SHOW_SYS},
{sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size, SHOW_SYS},
{sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS},
+ {sys_max_prep_stmt_count.name,(char*) &sys_max_prep_stmt_count, SHOW_SYS},
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
{sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
{sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
@@ -495,6 +533,7 @@ struct show_var_st init_vars[]= {
{"log_error", (char*) log_error_file, SHOW_CHAR},
{"port", (char*) &mysql_port, SHOW_INT},
{"protocol_version", (char*) &protocol_version, SHOW_INT},
+ {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
{sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
@@ -503,8 +542,14 @@ struct show_var_st init_vars[]= {
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
+#ifdef HAVE_SMEM
+ {"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},
+ {"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR},
+#endif
{sys_server_id.name, (char*) &sys_server_id, SHOW_SYS},
+#ifdef HAVE_REPLICATION
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
+#endif
{"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL},
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
@@ -513,7 +558,7 @@ struct show_var_st init_vars[]= {
{"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
#endif
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
- {"sql_mode", (char*) &opt_sql_mode, SHOW_LONG},
+ {sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS},
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
{sys_table_type.name, (char*) &sys_table_type, SHOW_SYS},
{sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS},
@@ -526,7 +571,7 @@ struct show_var_st init_vars[]= {
{"timezone", time_zone, SHOW_CHAR},
#endif
{sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
- {"tmpdir", (char*) &mysql_tmpdir, SHOW_CHAR_PTR},
+ {"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR},
{"version", server_version, SHOW_CHAR},
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
{NullS, NullS, SHOW_LONG}
@@ -604,6 +649,7 @@ static void fix_tx_isolation(THD *thd, enum_var_type type)
If we are changing the thread variable, we have to copy it to NET too
*/
+#ifdef HAVE_REPLICATION
static void fix_net_read_timeout(THD *thd, enum_var_type type)
{
if (type != OPT_GLOBAL)
@@ -622,6 +668,17 @@ static void fix_net_retry_count(THD *thd, enum_var_type type)
if (type != OPT_GLOBAL)
thd->net.retry_count=thd->variables.net_retry_count;
}
+#else /* HAVE_REPLICATION */
+static void fix_net_read_timeout(THD *thd __attribute__(unused),
+ enum_var_type type __attribute__(unused))
+{}
+static void fix_net_write_timeout(THD *thd __attribute__(unused),
+ enum_var_type type __attribute__(unused))
+{}
+static void fix_net_retry_count(THD *thd __attribute__(unused),
+ enum_var_type type __attribute__(unused))
+{}
+#endif /* HAVE_REPLICATION */
static void fix_query_cache_size(THD *thd, enum_var_type type)
@@ -818,7 +875,7 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
if (type == OPT_GLOBAL)
{
pthread_mutex_lock(&LOCK_global_system_variables);
- global_system_variables.*offset= (ulong) option_limits->def_value;
+ global_system_variables.*offset= (ulonglong) option_limits->def_value;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
@@ -864,7 +921,7 @@ byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type)
bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
{
char buff[80], *value;
- String str(buff,sizeof(buff)), *res;
+ String str(buff, sizeof(buff), system_charset_info), *res;
if (var->value->result_type() == STRING_RESULT)
{
@@ -895,6 +952,44 @@ err:
return 1;
}
+
+
+bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
+{
+ char buff[80], *error= 0;
+ uint error_len= 0;
+ String str(buff, sizeof(buff), system_charset_info), *res;
+
+ if (var->value->result_type() == STRING_RESULT)
+ {
+ if (!(res= var->value->val_str(&str)))
+ goto err;
+ var->save_result.ulong_value= (ulong)
+ find_set(enum_names, res->c_ptr(), res->length(), &error, &error_len);
+ if (error_len)
+ {
+ strmake(buff, error, min(sizeof(buff), error_len));
+ goto err;
+ }
+ }
+ else
+ {
+ ulonglong tmp= var->value->val_int();
+ if (tmp >= enum_names->count)
+ {
+ llstr(tmp, buff);
+ goto err;
+ }
+ var->save_result.ulong_value= (ulong) tmp; // Save for update
+ }
+ return 0;
+
+err:
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
+ return 1;
+}
+
+
/*
Return an Item for a variable. Used with @@[global.]variable_name
@@ -902,6 +997,10 @@ err:
We have to use netprintf() instead of my_error() here as this is
called on the parsing stage.
+
+ TODO:
+ With prepared statements/stored procedures this has to be fixed
+ to create an item that gets the current value at fix_fields() stage.
*/
Item *sys_var::item(THD *thd, enum_var_type var_type)
@@ -910,7 +1009,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type)
{
if (var_type != OPT_DEFAULT)
{
- net_printf(&thd->net,
+ net_printf(thd,
var_type == OPT_GLOBAL ? ER_LOCAL_VARIABLE :
ER_GLOBAL_VARIABLE, name);
return 0;
@@ -930,10 +1029,10 @@ Item *sys_var::item(THD *thd, enum_var_type var_type)
case SHOW_CHAR:
{
char *str= (char*) value_ptr(thd, var_type);
- return new Item_string(str,strlen(str));
+ return new Item_string(str, strlen(str), system_charset_info);
}
default:
- net_printf(&thd->net, ER_VAR_CANT_BE_READ, name);
+ net_printf(thd, ER_VAR_CANT_BE_READ, name);
}
return 0;
}
@@ -967,6 +1066,40 @@ byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type)
}
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
+{
+ ulong val;
+ char buff[256];
+ String tmp(buff, sizeof(buff), default_charset_info);
+ my_bool found= 0;
+
+ tmp.length(0);
+ val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
+ thd->variables.*offset);
+ for (uint i= 0; val; val>>= 1, i++)
+ {
+ if (val & 1)
+ {
+ tmp.append(enum_names->type_names[i]);
+ tmp.append(',');
+ }
+ }
+ if (tmp.length())
+ tmp.length(tmp.length() - 1);
+ return (byte*) thd->strdup(tmp.c_ptr());
+}
+
+
+void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.*offset= 0;
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+
bool sys_var_thd_bit::update(THD *thd, set_var *var)
{
int res= (*update_func)(thd, var);
@@ -991,7 +1124,7 @@ bool sys_var_thd_conv_charset::check(THD *thd, set_var *var)
{
CONVERT *tmp;
char buff[80];
- String str(buff,sizeof(buff)), *res;
+ String str(buff,sizeof(buff), system_charset_info), *res;
if (!var->value) // Default value
{
@@ -1018,8 +1151,12 @@ bool sys_var_thd_conv_charset::update(THD *thd, set_var *var)
if (var->type == OPT_GLOBAL)
global_system_variables.convert_set= var->save_result.convert;
else
+ {
thd->lex.convert_set= thd->variables.convert_set=
var->save_result.convert;
+ thd->protocol_simple.init(thd);
+ thd->protocol_prep.init(thd);
+ }
return 0;
}
@@ -1081,6 +1218,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type)
}
+#ifdef HAVE_REPLICATION
bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
{
int result= 0;
@@ -1116,7 +1254,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
UNLOCK_ACTIVE_MI;
return 0;
}
-
+#endif /* HAVE_REPLICATION */
bool sys_var_rand_seed1::update(THD *thd, set_var *var)
{
@@ -1186,6 +1324,21 @@ static bool set_log_update(THD *thd, set_var *var)
return 0;
}
+static byte *get_warning_count(THD *thd)
+{
+ thd->sys_var_tmp.long_value=
+ (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ return (byte*) &thd->sys_var_tmp.long_value;
+}
+
+static byte *get_error_count(THD *thd)
+{
+ thd->sys_var_tmp.long_value=
+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ return (byte*) &thd->sys_var_tmp.long_value;
+}
+
/****************************************************************************
Main handling of variables:
@@ -1247,7 +1400,8 @@ void set_var_init()
{
extern struct my_option my_long_options[]; // From mysqld
- hash_init(&system_variable_hash,array_elements(sys_variables),0,0,
+ hash_init(&system_variable_hash, system_charset_info,
+ array_elements(sys_variables),0,0,
(hash_get_key) get_sys_var_length,0, HASH_CASE_INSENSITIVE);
sys_var **var, **end;
for (var= sys_variables, end= sys_variables+array_elements(sys_variables) ;
@@ -1299,7 +1453,7 @@ sys_var *find_sys_var(const char *str, uint length)
length ? length :
strlen(str));
if (!var)
- net_printf(&current_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str);
+ net_printf(current_thd, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str);
return var;
}
@@ -1371,7 +1525,7 @@ int set_var::check(THD *thd)
return 0;
}
- if (value->fix_fields(thd,0))
+ if (value->fix_fields(thd, 0, &value) || value->check_cols(1))
return -1;
if (var->check_update_type(value->result_type()))
{
@@ -1400,7 +1554,7 @@ int set_var::update(THD *thd)
int set_var_user::check(THD *thd)
{
- return user_var_item->fix_fields(thd,0) ? -1 : 0;
+ return user_var_item->fix_fields(thd,0, (Item**) 0) ? -1 : 0;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index c74f1e827bd..3b4ec9d5bfe 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -28,7 +28,7 @@
class sys_var;
class set_var;
typedef struct system_variables SV;
-extern TYPELIB bool_typelib, delay_key_write_typelib;
+extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib;
enum enum_var_type
{
@@ -39,6 +39,7 @@ typedef bool (*sys_check_func)(THD *, set_var *);
typedef bool (*sys_update_func)(THD *, set_var *);
typedef void (*sys_after_update_func)(THD *,enum_var_type);
typedef void (*sys_set_default_func)(THD *, enum_var_type);
+typedef byte *(*sys_value_ptr_func)(THD *thd);
class sys_var
{
@@ -55,6 +56,7 @@ public:
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var) { return 0; }
bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names);
+ bool check_set(THD *thd, set_var *var, TYPELIB *enum_names);
virtual bool update(THD *thd, set_var *var)=0;
virtual void set_default(THD *thd, enum_var_type type) {}
virtual SHOW_TYPE type() { return SHOW_UNDEF; }
@@ -236,6 +238,10 @@ public:
sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg)
:sys_var_thd(name_arg), offset(offset_arg)
{}
+ sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg,
+ sys_after_update_func func)
+ :sys_var_thd(name_arg,func), offset(offset_arg)
+ {}
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
@@ -268,6 +274,7 @@ public:
class sys_var_thd_enum :public sys_var_thd
{
+protected:
ulong SV::*offset;
TYPELIB *enum_names;
public:
@@ -292,6 +299,21 @@ public:
};
+class sys_var_thd_sql_mode :public sys_var_thd_enum
+{
+public:
+ sys_var_thd_sql_mode(const char *name_arg, ulong SV::*offset_arg)
+ :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return check_set(thd, var, enum_names);
+ }
+ void set_default(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
class sys_var_thd_bit :public sys_var_thd
{
sys_update_func update_func;
@@ -352,6 +374,7 @@ public:
};
+#ifndef EMBEDDED_LIBRARY
class sys_var_slave_skip_counter :public sys_var
{
public:
@@ -364,7 +387,7 @@ public:
type() or value_ptr()
*/
};
-
+#endif
class sys_var_rand_seed1 :public sys_var
{
@@ -401,6 +424,31 @@ public:
};
+/* Variable that you can only read from */
+
+class sys_var_readonly: public sys_var
+{
+public:
+ enum_var_type var_type;
+ SHOW_TYPE show_type;
+ sys_value_ptr_func value_ptr_func;
+ sys_var_readonly(const char *name_arg, enum_var_type type,
+ SHOW_TYPE show_type_arg,
+ sys_value_ptr_func value_ptr_func_arg)
+ :sys_var(name_arg), var_type(type),
+ show_type(show_type_arg), value_ptr_func(value_ptr_func_arg)
+ {}
+ bool update(THD *thd, set_var *var) { return 1; }
+ bool check_default(enum_var_type type) { return 1; }
+ bool check_type(enum_var_type type) { return type != var_type; }
+ bool check_update_type(Item_result type) { return 1; }
+ byte *value_ptr(THD *thd, enum_var_type type)
+ {
+ return (*value_ptr_func)(thd);
+ }
+ SHOW_TYPE type() { return show_type; }
+};
+
/****************************************************************************
Classes for parsing of the SET command
****************************************************************************/
@@ -439,7 +487,8 @@ public:
if (value_arg && value_arg->type() == Item::FIELD_ITEM)
{
Item_field *item= (Item_field*) value_arg;
- if (!(value=new Item_string(item->field_name, strlen(item->field_name))))
+ if (!(value=new Item_string(item->field_name, strlen(item->field_name),
+ item->charset())))
value=value_arg; /* Give error message later */
}
else
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index c70ac9ccf57..35202ff4722 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -7,7 +7,7 @@ dist-hook:
done; \
sleep 1 ; touch $(srcdir)/*/errmsg.sys
$(INSTALL_DATA) $(srcdir)/charsets/README $(distdir)/charsets
- $(INSTALL_DATA) $(srcdir)/charsets/Index $(distdir)/charsets
+ $(INSTALL_DATA) $(srcdir)/charsets/Index.xml $(distdir)/charsets
all: @AVAILABLE_LANGUAGES_ERRORS@
@@ -25,8 +25,7 @@ install-data-local:
done
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/charsets
$(INSTALL_DATA) $(srcdir)/charsets/README $(DESTDIR)$(pkgdatadir)/charsets/README
- $(INSTALL_DATA) $(srcdir)/charsets/Index $(DESTDIR)$(pkgdatadir)/charsets/Index
- $(INSTALL_DATA) $(srcdir)/charsets/*.conf $(DESTDIR)$(pkgdatadir)/charsets
+ $(INSTALL_DATA) $(srcdir)/charsets/*.xml $(DESTDIR)$(pkgdatadir)/charsets
fix_errors:
for lang in @AVAILABLE_LANGUAGES@; \
diff --git a/sql/share/charsets/Index b/sql/share/charsets/Index
deleted file mode 100644
index 5cf30682cc0..00000000000
--- a/sql/share/charsets/Index
+++ /dev/null
@@ -1,38 +0,0 @@
-# sql/share/charsets/Index
-#
-# This file lists all of the available character sets. Please keep this
-# file sorted by character set number.
-
-
-big5 1
-czech 2
-dec8 3
-dos 4
-german1 5
-hp8 6
-koi8_ru 7
-latin1 8
-latin2 9
-swe7 10
-usa7 11
-ujis 12
-sjis 13
-cp1251 14
-danish 15
-hebrew 16
-# The win1251 character set is deprecated. Please use cp1251 instead.
-win1251 17
-tis620 18
-euc_kr 19
-estonia 20
-hungarian 21
-koi8_ukr 22
-win1251ukr 23
-gb2312 24
-greek 25
-win1250 26
-croat 27
-gbk 28
-cp1257 29
-latin5 30
-latin1_de 31
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
new file mode 100644
index 00000000000..e6cea7bc615
--- /dev/null
+++ b/sql/share/charsets/Index.xml
@@ -0,0 +1,460 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets max-id=63>
+
+<description>
+This file lists all of the available character sets.
+To make maintaining easier please:
+ - keep records sorted by collation number.
+ - change charsets.max-id when adding a new collation.
+</description>
+
+<charset name="big5">
+ <family>Traditional Chinese</family>
+ <alias>big-5</alias>
+ <alias>bigfive</alias>
+ <alias>big-five</alias>
+ <alias>cn-big5</alias>
+ <alias>csbig5</alias>
+ <collation name="big5" id="1" order="Chinese" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="latin2">
+ <family>Central European</family>
+ <alias>csisolatin2</alias>
+ <alias>iso-8859-2</alias>
+ <alias>iso-ir-101</alias>
+ <alias>iso_8859-2</alias>
+ <alias>iso_8859-2:1987</alias>
+ <alias>l2</alias>
+ <collation name="czech" id="2" order="Czech" flag="compiled"/>
+ <collation name="latin2" id="9" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="hungarian" id="21" order="Hungarian"/>
+ <collation name="croat" id="27" order="Croatian"/>
+</charset>
+
+<charset name="dec8">
+ <family>Western</family>
+ <collation name="dec8" id="3" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="pclatin1">
+ <family>Western</family>
+ <alias>850</alias>
+ <alias>cp850</alias>
+ <alias>cspc850multilingual</alias>
+ <alias>ibm850</alias>
+ <collation name="pclatin1" id="4" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="latin1">
+ <family>Western</family>
+ <alias>csisolatin1</alias>
+ <alias>iso-8859-1</alias>
+ <alias>iso-ir-100</alias>
+ <alias>iso_8859-1</alias>
+ <alias>iso_8859-1:1987</alias>
+ <alias>l1</alias>
+ <alias>latin1</alias>
+ <collation name="german1" id="5" order="German Duden"/>
+ <collation name="latin1" id="8" order="Finnish, Swedish" flag="primary"/>
+ <collation name="danish" id="15" order="Danish"/>
+ <collation name="latin1_de" id="31" order="German DIN" flag="compiled"/>
+ <collation name="latin1_bin" id="47" order="Binary"/>
+ <collation name="latin1_ci_as" id="48">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="latin1_cs_as" id="49">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="hp8">
+ <family>Western</family>
+ <alias>hproman8</alias>
+ <collation name="hp8" id="6" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="koi8r">
+ <family>Cyrillic</family>
+ <alias>koi8-r</alias>
+ <alias>cskoi8r</alias>
+ <collation name="koi8r" id="7" order="Russian" flag="primary"/>
+</charset>
+
+<charset name="swe7">
+ <family>Western</family>
+ <alias>iso-646-se</alias>
+ <collation name="swe7" id="10" order="Swedish" flag="primary"/>
+</charset>
+
+<charset name="ascii">
+ <family>Western</family>
+ <alias>us</alias>
+ <alias>us-ascii</alias>
+ <alias>csascii</alias>
+ <alias>iso-ir-6</alias>
+ <alias>iso646-us</alias>
+ <collation name="ascii" id="11" order="English" flag="primary"/>
+</charset>
+
+<charset name="ujis">
+ <family>Japanese</family>
+ <alias>euc-jp</alias>
+ <collation name="ujis" id="12" order="Japanese" flag="primary"/>
+</charset>
+
+<charset name="sjis">
+ <family>Japanese</family>
+ <alias>s-jis</alias>
+ <alias>shift-jis</alias>
+ <alias>x-sjis</alias>
+ <collation name="sjis" id="13" order="Japanese" flag="primary"/>
+</charset>
+
+<charset name="cp1251">
+ <family>Cyrillic</family>
+ <alias>windows-1251</alias>
+ <alias>ms-cyr</alias>
+ <alias>ms-cyrillic</alias>
+ <collation name="cp1251" id="14" flag="primary">
+ <order>Belarusian</order>
+ <order>Bulgarian</order>
+ <order>Macedonian</order>
+ <order>Russian</order>
+ <order>Serbian</order>
+ <order>Mongolian</order>
+ <order>Ukrainian</order>
+ </collation>
+ <collation name="win1251ukr" id="23" order="<Depreciated>"/>
+ <collation name="cp1251_bin" id="50" order="Binary"/>
+ <collation name="cp1251_ci_as" id="51">
+ <order>Belarusian</order>
+ <order>Bulgarian</order>
+ <order>Macedonian</order>
+ <order>Russian</order>
+ <order>Serbian</order>
+ <order>Mongolian</order>
+ <order>Ukrainian</order>
+ </collation>
+ <collation name="cp1251_cs_as" id="52">
+ <order>Belarusian</order>
+ <order>Bulgarian</order>
+ <order>Macedonian</order>
+ <order>Russian</order>
+ <order>Serbian</order>
+ <order>Mongolian</order>
+ <order>Ukrainian</order>
+ </collation>
+</charset>
+
+<charset name="hebrew">
+ <family>Hebrew</family>
+ <alias>csisolatinhebrew</alias>
+ <alias>iso-8859-8</alias>
+ <alias>iso-ir-138</alias>
+ <collation name="hebrew" id="16" order="Hebrew" flag="primary"/>
+</charset>
+
+<charset name="tis620">
+ <family>Thai</family>
+ <alias>tis-620</alias>
+ <collation name="tis620" id="18" order="Thai" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="euckr">
+ <family>Korean</family>
+ <alias>euc_kr</alias>
+ <alias>euc-kr</alias>
+ <collation name="euckr" id="19" order="Korean" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="latin7">
+ <family>Baltic</family>
+ <alias>BalticRim</alias>
+ <alias>iso-8859-13</alias>
+ <alias>l7</alias>
+ <collation name="estonia" id="20" order="Estonian" flag="primary"/>
+ <collation name="latvian" id="41" order="Latvian"/>
+ <collation name="latvian1" id="42" order="Latvian"/>
+</charset>
+
+<charset name="koi8u">
+ <family>Cyrillic</family>
+ <alias>koi8-u</alias>
+ <collation name="koi8u" id="22" order="Ukranian" flag="primary"/>
+</charset>
+
+<charset name="gb2312">
+ <family>Simplified Chinese</family>
+ <alias>chinese</alias>
+ <alias>iso-ir-58</alias>
+ <collation name="gb2312" id="24" order="Chinese" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="greek">
+ <family>Greek</family>
+ <alias>csisolatingreek</alias>
+ <alias>ecma-118</alias>
+ <alias>greek8</alias>
+ <alias>iso-8859-7</alias>
+ <alias>iso-ir-126</alias>
+ <collation name="greek" id="25" order="Greek" flag="primary"/>
+</charset>
+
+<charset name="cp1250">
+ <family>Central European</family>
+ <alias>ms-ce</alias>
+ <alias>windows-1250</alias>
+ <collation name="cp1250" id="26" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="cp1250_czech" id="34" order="Czech"/>
+</charset>
+
+<charset name="gbk">
+ <family>East Asian</family>
+ <alias>cp936</alias>
+ <collation name="gbk" id="28" order="Chinese" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="cp1257">
+ <family>Baltic</family>
+ <alias>WinBaltRim</alias>
+ <alias>windows-1257</alias>
+ <collation name="cp1257" id="29" order="<Depreciated>"/>
+ <collation name="cp1257_bin" id="58" order="Binary"/>
+ <collation name="cp1257_ci_ai" id="59" flag="primary">
+ <order>Latvian</order>
+ <order>Lithuanian</order>
+ </collation>
+ <collation name="cp1257_ci_as" id="60">
+ <order>Latvian</order>
+ <order>Lithuanian</order>
+ </collation>
+ <collation name="cp1257_cs_as" id="61">
+ <order>Latvian</order>
+ <order>Lithuanian</order>
+ </collation>
+</charset>
+
+<charset name="latin5">
+ <family>South Asian</family>
+ <alias>csisolatin5</alias>
+ <alias>iso-8859-9</alias>
+ <alias>iso-ir-148</alias>
+ <alias>l5</alias>
+ <alias>latin5</alias>
+ <alias>turkish</alias>
+ <collation name="latin5" id="30" order="Turkish" flag="primary"/>
+</charset>
+
+<charset name="armscii8">
+ <family>South Asian</family>
+ <alias>armscii-8</alias>
+ <collation name="armscii8" id="32" order="Armenian" flag="primary"/>
+</charset>
+
+<charset name="utf8">
+ <family>Unicode</family>
+ <alias>utf-8</alias>
+ <collation name="utf8" id="33" flag="primary"/>
+</charset>
+
+<charset name="ucs2">
+ <family>Unicode</family>
+ <collation name="ucs2" id="35" flag="primary"/>
+</charset>
+
+<charset name="cp866">
+ <family>Cyrillic</family>
+ <alias>866</alias>
+ <alias>csibm866</alias>
+ <alias>ibm866</alias>
+ <alias>DOSCyrillicRussian</alias>
+ <collation name="cp866" id="36" order="Russian" flag="primary"/>
+</charset>
+
+<charset name="keybcs2">
+ <family>Central European</family>
+ <collation name="keybcs2" id="37" order="Czech" flag="primary"/>
+</charset>
+
+<charset name="MacCE">
+ <family>Central European</family>
+ <alias>MacCentralEurope</alias>
+ <collation name="macce" id="38" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="macce_bin" id="43" order="Binary"/>
+ <collation name="macce_ci_ai" id="44">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="macce_ci_as" id="45">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="macce_cs_as" id="46">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+</charset>
+
+<charset name="MacRoman">
+ <family>Western</family>
+ <alias>Mac</alias>
+ <alias>Macintosh</alias>
+ <alias>csmacintosh</alias>
+ <collation name="macroman" id="39" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="macroman_bin" id="53" order="Binary"/>
+ <collation name="macroman_ci_as" id="54">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="macroman_ci_ai" id="55">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="macroman_cs_as" id="56">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="pclatin2">
+ <family>Central European</family>
+ <alias>852</alias>
+ <alias>cp852</alias>
+ <alias>ibm852</alias>
+ <collation name="pclatin2" id="40" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+</charset>
+
+<charset name="cp1256">
+ <family>Arabic</family>
+ <alias>ms-arab</alias>
+ <alias>windows-1256</alias>
+ <collation name="cp1256" id="57" order="Arabic" flag="primary">
+ <order>Arabic</order>
+ <order>Persian</order>
+ <order>Pakistani</order>
+ <order>Urdu</order>
+ </collation>
+</charset>
+
+<charset name="binary">
+ <collation name="binary" id="63" order="Binary" flag="primary" flag="compiled"/>
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/MacCE.xml b/sql/share/charsets/MacCE.xml
new file mode 100644
index 00000000000..fe64fd18abc
--- /dev/null
+++ b/sql/share/charsets/MacCE.xml
@@ -0,0 +1,209 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="MacCE">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 01 01 02 01 01 01 01 02 02 01 02 02 01 02 02 01
+ 02 01 02 02 01 02 01 02 02 02 02 02 02 01 02 02
+ 00 00 01 00 00 00 00 02 00 00 00 02 00 00 02 01
+ 02 01 00 00 02 01 00 00 02 01 02 01 02 01 02 01
+ 02 01 00 00 02 01 00 00 00 00 00 02 01 01 02 01
+ 00 00 00 00 00 00 00 00 02 01 02 01 00 00 02 01
+ 02 01 00 00 02 01 02 01 01 02 01 01 02 01 01 01
+ 02 01 01 02 01 02 01 02 01 02 02 01 01 02 01 00
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 54 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 54 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 8A 82 82 8E 88 9A 9F 87 88 8B 8A 8B 8D 8D 8E 90
+ 90 93 92 93 95 95 98 97 98 99 9A 9B 9C 9E 9E 9F
+ A0 A1 AB A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE B0
+ B0 B4 B2 B3 B4 FA B6 B7 B8 BA BA BC BC BE BE C0
+ C0 C4 C2 C3 C4 CB C6 C7 C8 C9 CA CB CE 9B CE D8
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 DA DA DE DC DD DE E0
+ E0 E4 E2 E3 E4 E6 E6 87 E9 E9 92 EC EC F0 97 99
+ F0 F3 9C F3 F5 F5 F7 F7 F9 F9 FA FD B8 FD AE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 74 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 74 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 81 83 84 85 86 E7 84 89 80 89 8C 8C 83 8F
+ 8F 91 EA 91 94 94 96 EE 96 EF 85 CD F2 9D 9D 86
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA A2 AC AD FE AF
+ AF B1 B2 B3 B1 B5 B6 B7 FC B9 B9 BB BB BD BD BF
+ BF C1 C2 C3 C1 C5 C6 C7 C8 C9 CA C5 CC CD CC CF
+ D0 D1 D2 D3 D4 D5 D6 D7 CF D9 D9 DB DC DD DB DF
+ DF E1 E2 E3 E1 E5 E5 E7 E8 E8 EA EB EB ED EE EF
+ ED F1 F2 F1 F4 F4 F6 F6 F8 F8 B5 FB FC FB FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 00C4 0100 0101 00C9 0104 00D6 00DC 00E1 0105 010C 00E4 010D 0106 0107 00E9 0179
+ 017A 010E 00ED 010F 0112 0113 0116 00F3 0117 00F4 00F6 00F5 00FA 011A 011B 00FC
+ 2020 00B0 0118 00A3 00A7 2022 00B6 00DF 00AE 00A9 2122 0119 00A8 2260 0123 012E
+ 012F 012A 2264 2265 012B 0136 2202 2211 0142 013B 013C 013D 013E 0139 013A 0145
+ 0146 0143 00AC 221A 0144 0147 2206 00AB 00BB 2026 00A0 0148 0150 00D5 0151 014C
+ 2013 2014 201C 201D 2018 2019 00F7 25CA 014D 0154 0155 0158 2039 203A 0159 0156
+ 0157 0160 201A 201E 0161 015A 015B 00C1 0164 0165 00CD 017D 017E 016A 00D3 00D4
+ 016B 016E 00DA 016F 0170 0171 0172 0173 00DD 00FD 0137 017B 0141 017C 0122 02C7
+</map>
+</unicode>
+
+
+<collation name="macce">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 46 47 4A 4C 52 53 55 56 5A 5B 5D 62 62 67
+ 6F 70 71 75 79 81 88 89 8A 8B 8D 90 91 92 93 94
+ 95 41 46 47 4A 4C 52 53 55 56 5A 5B 5D 62 62 67
+ 6F 70 71 75 79 81 88 89 8A 8B 8D 96 97 98 99 9A
+ 41 41 41 4C 41 67 81 41 41 47 41 47 47 47 4C 8D
+ 8D 4A 56 4A 4C 4C 4C 67 4C 67 67 67 81 4C 4C 81
+ A0 A1 4C A3 A4 A5 A6 75 A8 A9 AA 4C AC AD 53 56
+ 56 56 B2 B3 56 5B B6 B7 5D 5D 5D 5D 5D 5D 5D 62
+ 62 62 C2 C3 62 62 C6 C7 C8 C9 CA 62 67 67 67 67
+ D0 D1 D2 D3 D4 D5 D6 D7 67 71 71 71 DC DD 71 71
+ 71 75 E2 E3 75 75 75 41 79 79 56 8D 8D 81 67 67
+ 81 81 81 81 81 81 81 81 8B 8B 5B 8D 5D 8D 53 FF
+</map>
+</collation>
+
+
+<collation name="macce_bin">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+
+<collation name="macce_ci_ai">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 4B 4D 53 57 63 65 69 6B 73 75 79 83 85 8D
+ 9B 9D 9F A7 AE B2 C0 C2 C4 C6 CA D2 D3 D4 D5 D6
+ D7 41 4B 4D 53 57 63 65 69 6B 73 75 79 83 85 8D
+ 9B 9D 9F A7 AE B2 C0 C2 C4 C6 CA D8 D9 DA DB DC
+ 41 41 41 57 41 8D B2 41 41 4D 41 4D 4D 4D 57 CA
+ CA 53 6B 53 57 57 57 8D 57 8D 8D 8D B2 57 57 B2
+ DD DE 57 DF E0 E1 E2 A7 E3 E4 E5 57 E6 E7 65 6B
+ 6B 6B E8 E9 6B 75 EA EB 79 79 79 79 79 79 79 85
+ 85 85 EC ED 85 85 EE EF F0 F1 F2 85 8D 8D 8D 8D
+ F3 F4 F5 F6 F7 F8 F9 FA 8D 9F 9F 9F FB FC 9F 9F
+ 9F A7 FD FE A7 A7 A7 41 BE BE 6B CA CA B2 8D 8D
+ B2 B2 B2 B2 B2 B2 B2 B2 C6 C6 75 CA 79 CA 65 FF
+</map>
+</collation>
+
+
+<collation name="macce_ci_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 4B 4D 53 57 63 65 69 6B 73 75 79 83 85 8D
+ 9B 9D 9F A7 AE B2 C0 C2 C4 C6 CA D2 D3 D4 D5 D6
+ D7 41 4B 4D 53 57 63 65 69 6B 73 75 79 83 85 8D
+ 9B 9D 9F A7 AE B2 C0 C2 C4 C6 CA D8 D9 DA DB DC
+ 45 47 47 59 49 91 B6 43 49 4F 45 4F 51 51 59 CE
+ CE 55 71 55 5B 5B 5D 8F 5D 99 91 97 B8 5F 5F B6
+ DD DE 61 DF E0 E1 E2 AD E3 E4 E5 61 E6 E7 67 6F
+ 6F 6D E8 E9 6D 77 EA EB 7B 81 82 7F 7F 7D 7D 8B
+ 8B 87 EC ED 87 89 EE EF F0 F1 F2 89 93 97 93 95
+ F3 F4 F5 F6 F7 F8 F9 FA 95 A1 A1 A3 FB FC A3 A5
+ A5 A9 FD FE A9 AB AB 43 B0 B0 71 CC CC BC 8F 99
+ BC B4 B8 B4 BA BA BE BE C8 C8 77 D0 7B D0 67 FF
+
+</map>
+</collation>
+
+
+<collation name="macce_cs_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 4B 4D 53 57 63 65 69 6B 73 75 79 83 85 8D
+ 9B 9D 9F A7 AE B2 C0 C2 C4 C6 CA D2 D3 D4 D5 D6
+ D7 42 4C 4E 54 58 64 66 6A 6C 74 76 7A 84 86 8E
+ 9C 9E A0 A8 AF B3 C1 C3 C5 C7 CB D8 D9 DA DB DC
+ 45 47 48 59 49 91 B6 44 4A 4F 46 50 51 52 5A CE
+ CF 55 72 56 5B 5C 5D 90 5E 9A 92 98 B8 5F 60 B7
+ DD DE 61 DF E0 E1 E2 AD E3 E4 E5 62 E6 E7 68 6F
+ 70 6D E8 E9 6E 77 EA EB 7C 81 82 7F 80 7D 7E 8B
+ 8C 87 EC ED 88 89 EE EF F0 F1 F2 8A 93 97 94 95
+ F3 F4 F5 F6 F7 F8 F9 FA 96 A1 A2 A3 FB FC A4 A5
+ A6 A9 FD FE AA AB AC 43 B0 B1 71 CC CD BC 8F 99
+ BD B4 B9 B5 BA BB BE BF C8 C9 78 D0 7B D1 67 FF
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/MacRoman.xml b/sql/share/charsets/MacRoman.xml
new file mode 100644
index 00000000000..b17860f56b2
--- /dev/null
+++ b/sql/share/charsets/MacRoman.xml
@@ -0,0 +1,201 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="MacRoman">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 10
+ 20 01 01 01 01 01 01 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 00 00 00 00 00 00 00 02 00 00 00 00 00 00 01 01
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 02
+ 00 00 00 00 02 00 00 00 00 00 00 20 01 01 00 00
+ 00 00 00 00 00 00 00 00 02 01 00 00 00 00 00 00
+ 00 00 00 00 00 20 01 01 01 01 01 01 01 01 01 01
+ 00 01 01 01 01 02 00 00 00 00 00 00 00 00 00 00
+</map>
+</ctype>
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 8A 8C 8D 8E 96 9A 9F 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD BE BF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA 88 8B 9B CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D8 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 89 90 87 91 8F 92 94 95 93 97 99
+ F0 98 9C 9E 9D F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 E7 CB E5 80 CC 81 82 83 E9
+ E6 E8 EA ED EB EC 84 EE F1 EF 85 CD F2 F4 F3 86
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD AE AF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D9 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 00C4 00C5 00C7 00C9 00D1 00D6 00DC 00E1 00E0 00E2 00E4 00E3 00E5 00E7 00E9 00E8
+ 00EA 00EB 00ED 00EC 00EE 00EF 00F1 00F3 00F2 00F4 00F6 00F5 00FA 00F9 00FB 00FC
+ 2020 00B0 00A2 00A3 00A7 2022 00B6 00DF 00AE 00A9 2122 00B4 00A8 2260 00C6 00D8
+ 221E 00B1 2264 2265 00A5 00B5 2202 2211 220F 03C0 222B 00AA 00BA 03A9 00E6 00F8
+ 00BF 00A1 00AC 221A 0192 2248 2206 00AB 00BB 2026 00A0 00C0 00C3 00D5 0152 0153
+ 2013 2014 201C 201D 2018 2019 00F7 25CA 00FF 0178 2044 20AC 2039 203A FB01 FB02
+ 2021 00B7 201A 201E 2030 00C2 00CA 00C1 00CB 00C8 00CD 00CE 00CF 00CC 00D3 00D4
+ F8FF 00D2 00DA 00DB 00D9 0131 02C6 02DC 00AF 02D8 02D9 02DA 00B8 02DD 02DB 02C7
+</map>
+</unicode>
+
+<collation name="macroman">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 49 50 52 53 57 59 60 61 67 68 69 70 71 72
+ 79 80 81 82 84 85 90 91 92 93 95 A0 A1 A2 A3 A4
+ A5 41 49 50 52 53 57 59 60 61 67 68 69 70 71 72
+ 79 80 81 82 84 85 90 91 92 93 95 A6 A7 A8 A9 AA
+ 41 41 50 53 71 72 85 41 41 41 41 41 41 50 53 53
+ 53 53 61 61 61 61 71 72 72 72 72 72 85 85 85 85
+ AB AC AD AE AF B0 B1 82 B2 B3 B4 B5 B6 B7 48 72
+ B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 48 72
+ C6 C7 C8 C9 57 CA CB CC CD CE CF 41 41 72 D0 D1
+ D2 D3 D4 D5 D6 D7 D8 D9 93 93 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 41 53 41 53 53 61 61 61 61 72 72
+ F0 72 85 85 85 61 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+<collation name="macroman_bin">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+<collation name="macroman_ci_ai">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 51 53 57 59 63 66 68 6A 75 77 79 7B 7D 81
+ 91 93 95 97 9A 9C A6 A8 AA AC B0 B2 B3 B4 B5 B6
+ B7 41 51 53 57 59 63 66 68 6A 75 77 79 7B 7D 81
+ 91 93 95 97 9A 9C A6 A8 AA AC B0 B8 B9 BA BB BC
+ 41 41 53 59 7D 81 9C 41 41 41 41 41 41 53 59 59
+ 59 59 6A 6A 6A 6A 7D 81 81 81 81 81 9C 9C 9C 9C
+ BD BE BF C0 C1 C2 C3 97 C4 C5 C6 C7 C8 C9 41 81
+ CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 41 81
+ D8 D9 DA DB 63 DC DD DE DF E0 E1 41 41 81 81 81
+ E2 E3 E4 E5 E6 E7 E8 E9 AC AC EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 41 59 41 59 59 6A 6A 6A 6A 81 81
+ F0 81 9C 9C 9C 6A F6 F7 F8 F9 FA FB FC FD FE FF
+
+</map>
+</collation>
+
+<collation name="macroman_ci_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 51 53 57 59 63 66 68 6A 75 77 79 7B 7D 81
+ 91 93 95 97 9A 9C A6 A8 AA AC B0 B2 B3 B4 B5 B6
+ B7 41 51 53 57 59 63 66 68 6A 75 77 79 7B 7D 81
+ 91 93 95 97 9A 9C A6 A8 AA AC B0 B8 B9 BA BB BC
+ 4B 4D 55 5D 7F 8B A4 45 43 47 4B 49 4D 55 5D 5B
+ 5F 61 6E 6C 70 72 7F 85 83 87 8B 89 A0 9E A2 A4
+ BD BE BF C0 C1 C2 C3 99 C4 C5 C6 C7 C8 C9 4F 8D
+ CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 4F 8D
+ D8 D9 DA DB 65 DC DD DE DF E0 E1 43 49 89 8F 8F
+ E2 E3 E4 E5 E6 E7 E8 E9 AE AE EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 47 5F 45 61 5B 6E 70 70 6C 85 87
+ F0 83 A0 A2 9E 72 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+<collation name="macroman_cs_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 51 53 57 59 63 66 68 6A 75 77 79 7B 7D 81
+ 91 93 95 97 9A 9C A6 A8 AA AC B0 B2 B3 B4 B5 B6
+ B7 42 52 54 58 5A 64 67 69 6B 76 78 7A 7C 7E 82
+ 92 94 96 98 9B 9D A7 A9 AB AD B1 B8 B9 BA BB BC
+ 4B 4D 55 5D 7F 8B A4 46 44 48 4C 4A 4E 56 5E 5C
+ 60 62 6F 6D 71 73 80 86 84 88 8C 8A A1 9F A3 A5
+ BD BE BF C0 C1 C2 C3 99 C4 C5 C6 C7 C8 C9 4F 8D
+ CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 50 8E
+ D8 D9 DA DB 65 DC DD DE DF E0 E1 43 49 89 8F 90
+ E2 E3 E4 E5 E6 E7 E8 E9 AF AE EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 47 5F 45 61 5B 6E 70 72 6C 85 87
+ F0 83 A0 A2 9E 74 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/armscii8.xml b/sql/share/charsets/armscii8.xml
new file mode 100644
index 00000000000..99ab5eb336d
--- /dev/null
+++ b/sql/share/charsets/armscii8.xml
@@ -0,0 +1,119 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="armscii8">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 01 02 01 02 01 02 01 02 01 02 01 02 01 02
+ 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01 02
+ 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01 02
+ 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01 02
+ 01 02 01 02 01 02 01 02 01 02 01 02 01 02 10 10
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 AA AB AC AD AE AF
+ B0 B1 B3 B3 B5 B5 B7 B7 B9 B9 BB BB BD BD BF BF
+ C1 C1 C3 C3 C5 C5 C7 C7 C9 C9 CB CB CD CD CF CF
+ D1 D1 D3 D3 D5 D5 D7 D7 D9 D9 DB DB DD DD DF DF
+ E1 E1 E3 E3 E5 E5 E7 E7 E9 E9 EB EB ED ED EF EF
+ F1 F1 F3 F3 F5 F5 F7 F7 F9 F9 FB FB FD FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B2 B4 B4 B6 B6 B8 B8 BA BA BC BC BE BE
+ C0 C0 C2 C2 C4 C4 C6 C6 C8 C8 CA CA CC CC CE CE
+ D0 D0 D2 D2 D4 D4 D6 D6 D8 D8 DA DA DC DC DE DE
+ E0 E0 E2 E2 E4 E4 E6 E6 E8 E8 EA EA EC EC EE EE
+ F0 F0 F2 F2 F4 F4 F6 F6 F8 F8 FA FA FC FC FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 2741 00A7 0589 0029 0028 00BB 00AB 2014 002E 055D 002C 002D 055F 2026 055C
+055B 055E 0531 0561 0532 0562 0533 0563 0534 0564 0535 0565 0536 0566 0537 0567
+0538 0568 0539 0569 053A 056A 053B 056B 053C 056C 053D 056D 053E 056E 053F 056F
+0540 0570 0541 0571 0542 0572 0543 0573 0544 0574 0545 0575 0546 0576 0547 0577
+0548 0578 0549 0579 054A 057A 054B 057B 054C 057C 054D 057D 054E 057E 054F 057F
+0550 0580 0551 0581 0552 0582 0553 0583 0554 0584 0555 0585 0556 0586 2019 0027
+</map>
+</unicode>
+
+
+<collation name="armscii8">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/ascii.xml b/sql/share/charsets/ascii.xml
new file mode 100644
index 00000000000..67ab57de88f
--- /dev/null
+++ b/sql/share/charsets/ascii.xml
@@ -0,0 +1,119 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="ascii">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+</map>
+</unicode>
+
+
+<collation name="ascii">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 5E 5F
+ 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 59 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/cp1250.xml b/sql/share/charsets/cp1250.xml
new file mode 100644
index 00000000000..a863aceffc9
--- /dev/null
+++ b/sql/share/charsets/cp1250.xml
@@ -0,0 +1,121 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="cp1250">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 20 20 10 20 10 10 10 10 20 10 01 10 01 01 01 01
+ 20 10 10 10 10 10 10 10 20 10 02 10 02 02 02 02
+ 48 10 10 01 10 01 10 01 10 10 01 10 10 10 10 01
+ 10 10 10 02 10 10 10 10 10 02 02 10 01 10 02 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 10
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 9A 8B 9C 9D 9E 9F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 B3 A4 B9 A6 DF A8 A9 BA AB AC AD AE BF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BE BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 8A 9B 8C 8D 8E 8F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 A3 B4 B5 B6 B7 B8 A5 AA BB BC BD BC AF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE A7
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+20AC 0000 201A 0000 201E 2026 2020 2021 0000 2030 0160 2039 015A 0164 017D 0179
+0000 2018 2019 201C 201D 2022 2013 2014 0000 2122 0161 203A 015B 0165 017E 017A
+00A0 02C7 02D8 0141 00A4 0104 00A6 00A7 00A8 00A9 015E 00AB 00AC 00AD 00AE 017B
+00B0 00B1 02DB 0142 00B4 00B5 00B6 00B7 00B8 0105 015F 00BB 013D 02DD 013E 017C
+0154 00C1 00C2 0102 00C4 0139 0106 00C7 010C 00C9 0118 00CB 011A 00CD 00CE 010E
+0110 0143 0147 00D3 00D4 0150 00D6 00D7 0158 016E 00DA 0170 00DC 00DD 0162 00DF
+0155 00E1 00E2 0103 00E4 013A 0107 00E7 010D 00E9 0119 00EB 011B 00ED 00EE 010F
+0111 0144 0148 00F3 00F4 0151 00F6 00F7 0159 016F 00FA 0171 00FC 00FD 0163 02D9
+</map>
+</unicode>
+
+
+<collation name="cp1250">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 46 49 4A 4B 4C 4D 4E 4F 50 52 53 55
+ 56 57 58 59 5B 5C 5D 5E 5F 60 61 63 64 65 66 67
+ 68 41 42 43 46 49 4A 4B 4C 4D 4E 4F 50 52 53 55
+ 56 57 58 59 5B 5C 5D 5E 5F 60 61 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 5A 8B 5A 5B 62 62
+ 90 91 92 93 94 95 96 97 98 99 5A 9B 5A 5B 62 62
+ 20 A1 A2 50 A4 41 A6 59 A8 A9 59 AB AC AD AE 62
+ B0 B1 B2 50 B4 B5 B6 B7 B8 41 59 BB 50 BD 50 62
+ 58 41 41 41 41 50 45 43 44 49 49 49 49 4D 4D 46
+ 47 53 53 55 55 55 55 D7 58 5C 5C 5C 5C 60 5B 59
+ 58 41 41 41 41 50 45 43 44 49 49 49 49 4D 4D 46
+ 47 53 53 55 55 55 55 F7 58 5C 5C 5C 5C 60 5B FF
+</map>
+</collation>
+
+<collation name="cp1250_czech"/>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/cp1251.conf b/sql/share/charsets/cp1251.conf
deleted file mode 100644
index 6af97c891b8..00000000000
--- a/sql/share/charsets/cp1251.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the cp1251 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 A8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7C 7D 7E 7F 80
- 81 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 82 83 84 85 FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF 61 FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF 61 FF FF FF FF FF FF FF
- 5B 5C 5D 5E 5F 60 62 63 64 65 66 67 68 69 6A 6B
- 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B
- 5B 5C 5D 5E 5F 60 62 63 64 65 66 67 68 69 6A 6B
- 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B
diff --git a/sql/share/charsets/cp1251.xml b/sql/share/charsets/cp1251.xml
new file mode 100644
index 00000000000..48c525eb797
--- /dev/null
+++ b/sql/share/charsets/cp1251.xml
@@ -0,0 +1,216 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="cp1251">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 01 01 00 02 00 00 00 00 00 00 01 00 01 01 01 01
+ 02 00 00 00 00 00 00 00 00 00 02 00 02 02 02 02
+ 00 01 02 01 00 01 00 00 01 00 01 00 00 00 00 01
+ 00 00 01 02 02 00 00 00 02 00 02 00 02 01 02 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 54 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 54 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 90 83 82 83 84 85 86 87 88 89 9A 8B 9C 9D 9E 9F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A2 A2 BC A4 B4 A6 A7 B8 A9 BA AB AC AD AE BF
+ B0 B1 B3 B3 B4 B5 B6 B7 B8 B9 BA BB BC BE BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 74 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 74 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 81 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 80 91 92 93 94 95 96 97 98 99 8A 9B 8C 9D 8E 8F
+ A0 A1 A1 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B2 A5 B5 B6 B7 A8 B9 AA BB A3 BD BD AF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 0402 0403 201A 0453 201E 2026 2020 2021 0000 2030 0409 2039 040A 040C 040B 040F
+ 0452 2018 2019 201C 201D 2022 2013 2014 0000 2122 0459 203A 045A 045C 045B 045F
+ 00A0 040E 045E 0408 00A4 0490 00A6 00A7 0401 00A9 0404 00AB 00AC 00AD 00AE 0407
+ 00B0 00B1 0406 0456 0491 00B5 00B6 00B7 0451 2116 0454 00BB 0458 0405 0455 0457
+ 0410 0411 0412 0413 0414 0415 0416 0417 0418 0419 041A 041B 041C 041D 041E 041F
+ 0420 0421 0422 0423 0424 0425 0426 0427 0428 0429 042A 042B 042C 042D 042E 042F
+ 0430 0431 0432 0433 0434 0435 0436 0437 0438 0439 043A 043B 043C 043D 043E 043F
+ 0440 0441 0442 0443 0444 0445 0446 0447 0448 0449 044A 044B 044C 044D 044E 044F
+
+</map>
+</unicode>
+
+
+<collation name="cp1251">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7C 7D 7E 7F 80
+ 81 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 82 83 84 85 FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF 61 FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF 61 FF FF FF FF FF FF FF
+ 5B 5C 5D 5E 5F 60 62 63 64 65 66 67 68 69 6A 6B
+ 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B
+ 5B 5C 5D 5E 5F 60 62 63 64 65 66 67 68 69 6A 6B
+ 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B
+</map>
+</collation>
+
+
+<collation name="cp1251_bin">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+
+<collation name="cp1251_ci_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 43 45 47 49 4B 4D 4F 51 53 55 57 59 5B 5D
+ 5F 61 63 65 67 69 6B 6D 6F 71 73 D3 D4 D5 D6 D7
+ D8 41 43 45 47 49 4B 4D 4F 51 53 55 57 59 5B 5D
+ 5F 61 63 65 67 69 6B 6D 6F 71 73 D9 DA DB DC DD
+ 81 83 DE 83 DF E0 E1 E2 E3 E4 A1 E5 A7 9D B3 C1
+ 81 E6 E7 E8 E9 EA EB EC ED EE A1 EF A7 9D B3 C1
+ F0 B7 B7 99 F1 7D F2 F3 87 F4 89 F5 F6 F7 F8 95
+ F9 FA 93 93 7D FB FC FD 87 FE 89 FF 99 8F 8F 95
+ 75 77 79 7B 7F 85 8B 8D 91 97 9B 9F A3 A5 A9 AB
+ AD AF B1 B5 B9 BB BD BF C3 C5 C7 C9 CB CD CF D1
+ 75 77 79 7B 7F 85 8B 8D 91 97 9B 9F A3 A5 A9 AB
+ AD AF B1 B5 B9 BB BD BF C3 C5 C7 C9 CB CD CF D1
+</map>
+</collation>
+
+
+<collation name="cp1251_cs_as">
+<!--
+# Case insensitive, accent sensitive
+# Sort order is correct for Belarusian, Bulgarian, Macedonian,
+# Russian, Serbian, Mongolian languages. Almost good for Ukrainian,
+# except that "CYRILLIC LETTER SOFT SIGN" is not in the end of alphabet,
+# but between YERU and E.
+-->
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 43 45 47 49 4B 4D 4F 51 53 55 57 59 5B 5D
+ 5F 61 63 65 67 69 6B 6D 6F 71 73 D3 D4 D5 D6 D7
+ D8 42 44 46 48 4A 4C 4E 50 52 54 56 58 5A 5C 5E
+ 60 62 64 66 68 6A 6C 6E 70 72 74 D9 DA DB DC DD
+ 81 83 DE 84 DF E0 E1 E2 E3 E4 A1 E5 A7 9D B3 C1
+ 82 E6 E7 E8 E9 EA EB EC ED EE A2 EF A8 9E B4 C2
+ F0 B7 B8 99 F1 7D F2 F3 87 F4 89 F5 F6 F7 F8 95
+ F9 FA 93 94 7E FB FC FD 88 FE 8A FF 9A 8F 90 96
+ 75 77 79 7B 7F 85 8B 8D 91 97 9B 9F A3 A5 A9 AB
+ AD AF B1 B5 B9 BB BD BF C3 C5 C7 C9 CB CD CF D1
+ 76 78 7A 7C 80 86 8C 8E 92 98 9C A0 A4 A6 AA AC
+ AE B0 B2 B6 BA BC BE C0 C4 C6 C8 CA CC CE D0 D2
+</map>
+</collation>
+
+
+<collation name="win1251ukr">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4
+ B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4
+ C5 C6 C7 C8 C9 84 CA CB 88 CC 87 CD CE CF D0 8D
+ D1 D2 8C 8C 84 D3 D4 D5 88 D6 87 D7 D8 D9 DA 8D
+ 80 81 82 83 85 86 89 8A 8B 8E 8F 90 91 92 93 94
+ 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4
+ 80 81 82 83 85 86 89 8A 8B 8E 8F 90 91 92 93 94
+ 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/cp1256.xml b/sql/share/charsets/cp1256.xml
new file mode 100644
index 00000000000..2a6f6032358
--- /dev/null
+++ b/sql/share/charsets/cp1256.xml
@@ -0,0 +1,123 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<!-- Arabic, Persian, Pakistani, Urdu -->
+
+<charsets>
+
+<charset name="cp1256">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 00 00
+ 00 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 03 00 02 00 00 00 00 00 00 00 00 01 03 03 00
+ 03 10 10 10 10 00 00 00 00 00 00 00 02 00 00 00
+ 00 10 00 00 00 00 00 00 00 00 00 10 10 10 00 00
+ 10 10 00 00 00 00 00 00 00 00 10 10 00 00 00 10
+ 00 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
+ 03 03 03 03 03 03 03 00 03 03 03 03 03 03 03 03
+ 02 03 02 03 03 03 03 02 02 02 02 02 03 03 02 02
+ 03 03 03 03 02 03 03 00 03 02 03 02 02 00 00 00
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 54 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 54 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 9C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 74 55 56 57 58 59 5A 5B 5C 5F 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 74 55 56 57 58 59 5A 7B 7C 7F 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 8C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 20AC 067E 201A 0192 201E 2026 2020 2021 02C6 2030 0000 2039 0152 0686 0698 0000
+ 06AF 2018 2019 201C 201D 2022 2013 2014 0000 2122 0000 203A 0153 200C 200D 0000
+ 00A0 060C 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 0000 00AB 00AC 00AD 00AE 00AF
+ 00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 061B 00BB 00BC 00BD 00BE 061F
+ 0000 0621 0622 0623 0624 0625 0626 0627 0628 0629 062A 062B 062C 062D 062E 062F
+ 0630 0631 0632 0633 0634 0635 0636 00D7 0637 0638 0639 063A 0640 0641 0642 0643
+ 00E0 0644 00E2 0645 0646 0647 0648 00E7 00E8 00E9 00EA 00EB 0649 064A 00EE 00EF
+ 064B 064C 064D 064E 00F4 064F 0650 00F7 0651 00F9 0652 00FB 00FC 200E 200F 0000
+</map>
+</unicode>
+
+
+<collation name="cp1256">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 45 47 4A 4C 52 55 57 59 5D 5F 61 63 65 67
+ 6C 6E 70 72 74 76 7B 7D 7F 81 83 B9 BA BB BC BD
+ BE 41 45 47 4A 4C 52 55 57 59 5D 5F 61 63 65 67
+ 6C 6E 70 72 74 76 7B 7D 7F 81 83 BF C0 C1 C2 C3
+ C4 8E C5 54 C6 C7 C8 C9 CA CB CC CD 6A 92 99 CE
+ A5 CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 6A DA DB DC
+ DD B6 DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB
+ EC ED EE EF F0 F1 F2 F3 F4 F5 B7 F6 F7 F8 F9 B8
+ FA 85 86 87 88 89 8A 8B 8C 8D 9F 90 91 93 94 95
+ 96 97 98 9A 9B 9C 9D FB 9E 9F A0 A1 AD A2 A3 A4
+ 43 A6 44 A7 A8 A9 AA 49 4E 4F 50 51 AB AC 5B 5C
+ AE AF B0 B1 69 B2 B3 FC B4 78 B5 79 7A FD FE FF
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
+
diff --git a/sql/share/charsets/cp1257.conf b/sql/share/charsets/cp1257.conf
deleted file mode 100644
index 610ed5a646f..00000000000
--- a/sql/share/charsets/cp1257.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the cp1257 character set.
-
-# The ctype array must have 257 elements.
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 01 01 00 00 00 00 01 00 01 00 00 01 00 00 00 00
- 01 00 00 00 00 00 00 00 01 00 00 01 00 00 01 00
- 02 02 00 00 00 00 02 00 02 00 00 02 00 00 00 00
- 02 00 00 00 00 00 00 00 02 00 00 02 00 00 02 00
-
-# The to_lower array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 C2 C3 C4 C5 E6 C7 E8 C9 CA EB CC CD CE CF
- F0 D1 D2 D3 D4 D5 D6 D7 F8 D9 DA FB DC DD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# The to_upper array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 E2 E3 E4 E5 C6 E7 C8 E9 EA CB EC ED EE EF
- D0 F1 F2 F3 F4 F5 F6 F7 D8 F9 FA DB FC FD DE FF
-
-# The sort_order array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 43 44 46 47 4A 4B 4C 4D 50 51 52 53 54 55
- 56 57 58 59 5B 5C 5F 60 61 4E FF 62 63 64 65 66
- 67 41 43 44 46 47 4A 4B 4C 4D 50 51 52 53 54 55
- 56 57 58 59 5B 5C 5F 60 61 4E FF 68 69 6A 6B FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- 42 4F FF FF FF FF 48 FF 45 FF FF 49 FF FF FF FF
- 5A FF FF FF FF FF FF FF 5E FF FF 5D FF FF FF FF
- FF 4F FF FF FF FF 48 FF 45 FF FF 49 FF FF FF FF
- 5A FF FF FF FF FF FF FF 5E FF FF 5D FF FF FF FF
diff --git a/sql/share/charsets/cp1257.xml b/sql/share/charsets/cp1257.xml
new file mode 100644
index 00000000000..5ac2b746ff9
--- /dev/null
+++ b/sql/share/charsets/cp1257.xml
@@ -0,0 +1,229 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="cp1257">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 01 00 01 00 00 00 00 01
+ 00 00 00 00 00 00 00 00 02 00 02 00 00 00 00 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 00 01 01 01 01 01 01 01 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 00 02 02 02 02 02 02 02 00
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 BA AB AC AD AE BF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 BA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 A8 B9 BA BB BC BD BE AF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 20AC 0000 201A 0000 201E 2026 2020 2021 0000 2030 0000 2039 0000 00A8 02C7 00B8
+ 0000 2018 2019 201C 201D 2022 2013 2014 0000 2122 0000 203A 0000 00AF 02DB 0000
+ 00A0 0000 00A2 00A3 00A4 0000 00A6 00A7 00D8 00A9 0156 00AB 00AC 00AD 00AE 00C6
+ 00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00F8 00B9 0157 00BB 00BC 00BD 00BE 00E6
+ 0104 012E 0100 0106 00C4 00C5 0118 0112 010C 00C9 0179 0116 0122 0136 012A 013B
+ 0160 0143 0145 00D3 014C 00D5 00D6 00D7 0172 0141 015A 016A 00DC 017B 017D 00DF
+ 0105 012F 0101 0107 00E4 00E5 0119 0113 010D 00E9 017A 0117 0123 0137 012B 013C
+ 0161 0144 0146 00F3 014D 00F5 00F6 00F7 0173 0142 015B 016B 00FC 017C 017E 02D9
+</map>
+</unicode>
+
+
+<collation name="cp1257">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 43 44 46 47 4A 4B 4C 4D 50 51 52 53 54 55
+ 56 57 58 59 5B 5C 5F 60 61 4E FF 62 63 64 65 66
+ 67 41 43 44 46 47 4A 4B 4C 4D 50 51 52 53 54 55
+ 56 57 58 59 5B 5C 5F 60 61 4E FF 68 69 6A 6B FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ 42 4F FF FF FF FF 48 FF 45 FF FF 49 FF FF FF FF
+ 5A FF FF FF FF FF FF FF 5E FF FF 5D FF FF FF FF
+ FF 4F FF FF FF FF 48 FF 45 FF FF 49 FF FF FF FF
+ 5A FF FF FF FF FF FF FF 5E FF FF 5D FF FF FF FF
+</map>
+</collation>
+
+
+<collation name="cp1257_bin">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+
+<collation name="cp1257_ci_ai">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 4D 4F 55 57 61 63 67 69 6F 71 75 7B 7D 83
+ 8F 91 93 97 9E A0 A8 AA AC AE B0 B8 B9 BA BB BC
+ BD 41 4D 4F 55 57 61 63 67 69 6F 71 75 7B 7D 83
+ 8F 91 93 97 9E A0 A8 AA AC AE B0 BE BF C0 C1 C4
+ C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4
+ D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4
+ E5 E6 E7 E8 E9 EA EB EC 83 ED 93 EE EF F0 F1 41
+ F2 F3 F4 F5 F6 F7 F8 F9 83 FA 93 FB FC FD FE 41
+ 41 69 41 4F 41 41 57 57 4F 57 B0 57 63 71 69 75
+ 97 7D 7D 83 83 83 83 C2 A0 75 97 A0 A0 B0 B0 97
+ 41 69 41 4F 41 41 57 57 4F 57 B0 57 63 71 69 75
+ 97 7D 7D 83 83 83 83 C3 A0 75 97 A0 A0 B0 B0 FF
+</map>
+</collation>
+
+
+<collation name="cp1257_ci_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 4D 4F 55 57 61 63 67 69 6F 71 75 7B 7D 83
+ 8F 91 93 97 9E A0 A8 AA AC AE B0 B8 B9 BA BB BC
+ BD 41 4D 4F 55 57 61 63 67 69 6F 71 75 7B 7D 83
+ 8F 91 93 97 9E A0 A8 AA AC AE B0 BE BF C0 C1 C4
+ C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4
+ D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4
+ E5 E6 E7 E8 E9 EA EB EC 85 ED 95 EE EF F0 F1 4B
+ F2 F3 F4 F5 F6 F7 F8 F9 85 FA 95 FB FC FD FE 4B
+ 43 6B 45 51 47 49 59 5B 53 5D B2 5F 65 73 6D 77
+ 99 7F 81 87 89 8B 8D C2 A2 79 9B A4 A6 B4 B6 9D
+ 43 6B 45 51 47 49 59 5B 53 5D B2 5F 65 73 6D 77
+ 99 7F 81 87 89 8B 8D C3 A2 79 9B A4 A6 B4 B6 FF
+</map>
+</collation>
+
+
+<collation name="cp1257_cs_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 4D 4F 55 57 61 63 67 69 6F 71 75 7B 7D 83
+ 8F 91 93 97 9E A0 A8 AA AC AE B0 B8 B9 BA BB BC
+ BD 42 4E 50 56 58 62 64 68 6A 70 72 76 7C 7E 84
+ 90 92 94 98 9F A1 A9 AB AD AF B1 BE BF C0 C1 C4
+ C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4
+ D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4
+ E5 E6 E7 E8 E9 EA EB EC 85 ED 95 EE EF F0 F1 4B
+ F2 F3 F4 F5 F6 F7 F8 F9 86 FA 96 FB FC FD FE 4C
+ 43 6B 45 51 47 49 59 5B 53 5D B2 5F 65 73 6D 77
+ 99 7F 81 87 89 8B 8D C2 A2 79 9B A4 A6 B4 B6 9D
+ 44 6C 46 52 48 4A 5A 5C 54 5E B3 60 66 74 6E 78
+ 9A 80 82 88 8A 8C 8E C3 A3 7A 9C A5 A7 B5 B7 FF
+</map>
+</collation>
+
+
+<collation name="cp1257ltlv">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 47 49 4D 4F 57 59 5D 5F 65 67 6B 6F 71 75
+ 79 7B 7D 81 85 87 8D 8F 91 93 95 FF FF FF FF FF
+ FF 42 48 4A 4E 50 58 5A 5E 60 66 68 6C 70 72 76
+ 7A 7C 7E 82 86 88 8E 90 92 94 96 FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF 7F FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF 80 FF FF FF FF FF
+ 45 63 43 FF FF FF 53 51 4B FF FF 55 5B 69 61 6D
+ 83 FF 73 FF 77 FF FF FF 8B FF FF 89 FF 99 97 FF
+ 46 64 44 FF FF FF 54 52 4C FF FF 56 5C 6A 62 6E
+ 84 FF 74 FF 78 FF FF FF 8C FF FF 8A FF 9A 98 FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/cp866.xml b/sql/share/charsets/cp866.xml
new file mode 100644
index 00000000000..2b050f3c993
--- /dev/null
+++ b/sql/share/charsets/cp866.xml
@@ -0,0 +1,122 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="cp866">
+<!-- cp866_DOSCyrillicRussian -->
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 01 02 01 02 01 02 01 02 00 00 00 00 00 00 00 48
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ A0 A1 A2 A3 A4 A5 86 87 88 89 AA AB AC AD AE AF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ A0 A1 A2 A3 A4 A5 86 87 88 89 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F1 F1 F3 F3 F5 F5 F7 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ F0 F0 F2 F2 F4 F4 F6 F6 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 0410 0411 0412 0413 0414 0415 0416 0417 0418 0419 041A 041B 041C 041D 041E 041F
+ 0420 0421 0422 0423 0424 0425 0426 0427 0428 0429 042A 042B 042C 042D 042E 042F
+ 0430 0431 0432 0433 0434 0435 0436 0437 0438 0439 043A 043B 043C 043D 043E 043F
+ 2591 2592 2593 2502 2524 2561 2562 2556 2555 2563 2551 2557 255D 255C 255B 2510
+ 2514 2534 252C 251C 2500 253C 255E 255F 255A 2554 2569 2566 2560 2550 256C 2567
+ 2568 2564 2565 2559 2558 2552 2553 256B 256A 2518 250C 2588 2584 258C 2590 2580
+ 0440 0441 0442 0443 0444 0445 0446 0447 0448 0449 044A 044B 044C 044D 044E 044F
+ 0401 0451 0404 0454 0407 0457 040E 045E 00B0 2219 00B7 221A 207F 00B2 25A0 00A0
+</map>
+</unicode>
+
+
+<collation name="cp866">
+<!-- Case insensitive, accent sensitive -->
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 43 45 47 49 4B 4D 4F 51 53 55 57 59 5B 5D
+ 5F 61 63 65 67 69 6B 6D 6F 71 73 BD BE BF C0 C1
+ C2 41 43 45 47 49 4B 4D 4F 51 54 55 57 59 5B 5D
+ 5F 61 63 65 67 69 6B 6D 6F 71 73 C3 C4 C5 C6 C7
+ 75 77 79 7B 7D 7F 85 87 89 8D 8F 91 93 95 97 99
+ 9B 9D 9F A1 A5 A7 A9 AB AD AF B1 B3 B5 B7 B9 BB
+ 75 77 79 7B 7D 7F 85 87 89 8D 8F 91 93 95 97 99
+ C8 C9 CA D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ 9B 9D 9F A1 A5 A7 A9 AB AD AF B1 B3 B5 B7 B9 BB
+ 81 81 83 83 8B 8B A3 A3 CB CC CD CE CF D0 D1 D2
+</map>
+</collation>
+
+</charset>
+
+</charsets>
+
diff --git a/sql/share/charsets/croat.conf b/sql/share/charsets/croat.conf
deleted file mode 100644
index fbbe3328547..00000000000
--- a/sql/share/charsets/croat.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the croat character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00
- 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 9A 8B 8C 8D 9E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 8A 9B 9C 9D 8E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 46 48 49 4A 4B 4C 4D 4E 4F 50 51 52
- 53 54 55 56 58 59 5A 5B 5C 5D 5E 5B 5C 5D 5E 5F
- 60 41 42 43 46 48 49 4A 4B 4C 4D 4E 4F 50 51 52
- 53 54 55 56 58 59 5A 5B 5C 5D 5E 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 57 8B 8C 8D 5F 8F
- 90 91 92 93 94 95 96 97 98 99 57 9B 9C 9D 5F 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- 41 41 41 41 5C 5B 45 43 44 45 45 45 49 49 49 49
- 47 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
- 41 41 41 41 5C 5B 45 43 44 45 45 45 49 49 49 49
- 47 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
diff --git a/sql/share/charsets/danish.conf b/sql/share/charsets/danish.conf
deleted file mode 100644
index f99590ed6f3..00000000000
--- a/sql/share/charsets/danish.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the danish character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
- 44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF
- 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
- 44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
diff --git a/sql/share/charsets/dec8.conf b/sql/share/charsets/dec8.conf
deleted file mode 100644
index a4849aaa04c..00000000000
--- a/sql/share/charsets/dec8.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the dec8 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
- 44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
- 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
- 44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
diff --git a/sql/share/charsets/dec8.xml b/sql/share/charsets/dec8.xml
new file mode 100644
index 00000000000..4e76bbffd14
--- /dev/null
+++ b/sql/share/charsets/dec8.xml
@@ -0,0 +1,121 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="dec8">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 00A1 00A2 00A3 0000 00A5 0000 00A7 00A4 00A9 00AA 00AB 0000 0000 0000 0000
+00B0 00B1 00B2 00B3 0000 00B5 00B6 00B7 0000 00B9 00BA 00BB 00BC 00BD 0000 00BF
+00C0 00C1 00C2 00C3 00C4 00C5 00C6 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF
+0000 00D1 00D2 00D3 00D4 00D5 00D6 0152 00D8 00D9 00DA 00DB 00DC 0178 0000 00DF
+00E0 00E1 00E2 00E3 00E4 00E5 00E6 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF
+0000 00F1 00F2 00F3 00F4 00F5 00F6 0153 00F8 00F9 00FA 00FB 00FC 00FF 0000 0000
+</map>
+</unicode>
+
+
+<collation name="dec8">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
+ 44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
+ 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
+ 44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
+</map>
+</collation>
+
+
+</charset>
+
+
+</charsets>
diff --git a/sql/share/charsets/dos.conf b/sql/share/charsets/dos.conf
deleted file mode 100644
index dda86d0f3e8..00000000000
--- a/sql/share/charsets/dos.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the dos character set
-
-# ctype array (must have 257 elements)
- 00
- 20 30 30 30 30 30 30 20 20 28 28 28 28 28 30 30
- 30 30 30 30 30 30 30 30 30 30 20 30 30 30 30 30
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 30
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 01 01
- 01 02 01 02 02 02 02 02 02 01 01 10 10 10 10 10
- 02 02 02 02 02 01 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 20
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 87 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 84 86
- 82 91 91 93 94 95 96 97 98 94 81 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A4 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 9A 90 41 8E 41 8F 80 45 45 45 49 49 49 8E 8F
- 90 92 92 4F 99 4F 55 55 59 99 9A 9B 9C 9D 9E 9F
- 41 49 4F 55 A5 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 43 59 45 41 5C 41 5B 43 45 45 45 49 49 49 5C 5B
- 45 5C 5C 4F 5D 4F 55 55 59 5D 59 24 24 24 24 24
- 41 49 4F 55 4E 4E A6 A7 3F A9 AA AB AC 21 22 22
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
diff --git a/sql/share/charsets/estonia.conf b/sql/share/charsets/estonia.conf
deleted file mode 100644
index 76bbc021b0c..00000000000
--- a/sql/share/charsets/estonia.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the estonia character set.
-
-# The ctype array must have 257 elements.
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# The to_lower array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 BA AB AC AD AE BF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# The to_upper array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 A8 B9 AA BB BC BD BE AF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# The sort_order array must have 256 elements.
- 00 02 03 04 05 06 07 08 09 2E 2F 30 31 32 0A 0B
- 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B
- 2C 33 34 35 36 37 38 27 39 3A 3B 5D 3C 28 3D 3E
- 76 7A 7C 7E 80 81 82 83 84 85 3F 40 5E 5F 60 41
- 42 86 90 92 98 9A A4 A6 AA AC B2 B4 B8 BE C0 C6
- CE D0 D2 D6 E5 E8 EE F0 FA FC DD 43 44 45 46 47
- 48 87 91 93 99 9B A5 A7 AB AD B3 B5 B9 BF C1 C7
- CF D1 D3 D7 E6 E9 EF F1 FB FD DE 49 4A 4B 4C 1C
- 01 1D 57 1E 5A 74 71 72 1F 75 20 5B 21 4E 52 51
- 22 55 56 58 59 73 2A 2B 23 E7 24 5C 25 4F 54 26
- 2D FE 66 67 68 FF 4D 69 CC 6A D4 62 6B 29 6C 8E
- 6D 61 7D 7F 50 6E 6F 70 CD 7B D5 63 77 78 79 8F
- 8C B0 88 94 F4 8A A2 A0 96 9C DF 9E A8 B6 AE BA
- DB C2 C4 C8 CA F2 F6 64 EC BC D8 EA F8 E1 E3 DA
- 8D B1 89 95 F5 8B A3 A1 97 9D E0 9F A9 B7 AF BB
- DC C3 C5 C9 CB F3 F7 65 ED BD D9 EB F9 E2 E4 53
diff --git a/sql/share/charsets/german1.conf b/sql/share/charsets/german1.conf
deleted file mode 100644
index 3090c921ebe..00000000000
--- a/sql/share/charsets/german1.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the german1 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- 41 41 41 41 41 41 41 43 45 45 45 45 49 49 49 49
- D0 4E 4F 4F 4F 4F 4F D7 4F 55 55 55 55 59 DE 53
- 41 41 41 41 41 41 41 43 45 45 45 45 49 49 49 49
- D0 4E 4F 4F 4F 4F 4F F7 4F 55 55 55 55 59 DE FF
diff --git a/sql/share/charsets/greek.conf b/sql/share/charsets/greek.conf
deleted file mode 100644
index 73d67d6ee71..00000000000
--- a/sql/share/charsets/greek.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the greek character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 00 00 10 10 10 10 00 10 10 10 00 10
- 10 10 10 10 10 10 01 10 01 01 01 10 01 10 01 01
- 02 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 00 01 01 01 01 01 01 01 01 01 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 DC B7 DD DE DF BB FC BD FD FE
- C0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 D2 F3 F4 F5 F6 F7 F8 F9 FA FB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- DA C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB C1 C5 C7 C9
- DB C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D3 D3 D4 D5 D6 D7 D8 D9 DA DB CF D5 D9 FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 C1 B7 C5 C7 C9 BB CF BD D5 D9
- C9 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 C9 D5 C1 C5 C7 C9
- D5 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D3 D3 D4 D5 D6 D7 D8 D9 C9 D5 CF D5 D9 FF
diff --git a/sql/share/charsets/greek.xml b/sql/share/charsets/greek.xml
new file mode 100644
index 00000000000..eeb22236675
--- /dev/null
+++ b/sql/share/charsets/greek.xml
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="greek">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 48 10 10 10 00 00 10 10 10 10 00 10 10 10 00 10
+ 10 10 10 10 10 10 01 10 01 01 01 10 01 10 01 01
+ 02 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 00 01 01 01 01 01 01 01 01 01 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 00
+ </map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 DC B7 DD DE DF BB FC BD FD FE
+ C0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 D2 F3 F4 F5 F6 F7 F8 F9 FA FB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ DA C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB C1 C5 C7 C9
+ DB C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D3 D3 D4 D5 D6 D7 D8 D9 DA DB CF D5 D9 FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 02BD 02BC 00A3 0000 0000 00A6 00A7 00A8 00A9 0000 00AB 00AC 00AD 0000 2015
+00B0 00B1 00B2 00B3 0384 0385 0386 00B7 0388 0389 038A 00BB 038C 00BD 038E 038F
+0390 0391 0392 0393 0394 0395 0396 0397 0398 0399 039A 039B 039C 039D 039E 039F
+03A0 03A1 0000 03A3 03A4 03A5 03A6 03A7 03A8 03A9 03AA 03AB 03AC 03AD 03AE 03AF
+03B0 03B1 03B2 03B3 03B4 03B5 03B6 03B7 03B8 03B9 03BA 03BB 03BC 03BD 03BE 03BF
+03C0 03C1 03C2 03C3 03C4 03C5 03C6 03C7 03C8 03C9 03CA 03CB 03CC 03CD 03CE 0000
+</map>
+</unicode>
+
+
+<collation name="greek">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 C1 B7 C5 C7 C9 BB CF BD D5 D9
+ C9 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 C9 D5 C1 C5 C7 C9
+ D5 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D3 D3 D4 D5 D6 D7 D8 D9 C9 D5 CF D5 D9 FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
+
diff --git a/sql/share/charsets/hebrew.conf b/sql/share/charsets/hebrew.conf
deleted file mode 100644
index 6a5f88eb228..00000000000
--- a/sql/share/charsets/hebrew.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the hebrew character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 00 00 00 00 00
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
diff --git a/sql/share/charsets/hebrew.xml b/sql/share/charsets/hebrew.xml
new file mode 100644
index 00000000000..3bf8bec370e
--- /dev/null
+++ b/sql/share/charsets/hebrew.xml
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="hebrew">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 00 00 00 00 00
+ </map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 0000 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 00D7 00AB 00AC 00AD 00AE 203E
+00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 00F7 00BB 00BC 00BD 00BE 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 2017
+05D0 05D1 05D2 05D3 05D4 05D5 05D6 05D7 05D8 05D9 05DA 05DB 05DC 05DD 05DE 05DF
+05E0 05E1 05E2 05E3 05E4 05E5 05E6 05E7 05E8 05E9 05EA 0000 0000 0000 0000 0000
+</map>
+</unicode>
+
+
+<collation name="hebrew">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
+
diff --git a/sql/share/charsets/hp8.conf b/sql/share/charsets/hp8.conf
deleted file mode 100644
index e9fadacbf76..00000000000
--- a/sql/share/charsets/hp8.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the hp8 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 20 20 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 02 10 10 10 10 10 10 02 10 02 02
- 01 10 10 01 02 10 10 02 01 10 01 01 01 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 20 20 20 20 10 10 10 10 10 10 10 10 10 20
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 C8 C0 C9 C1 CD D1 DD A8 A9 AA AB AC CB C3 AF
- B0 B2 B2 B3 B5 B5 B7 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D4 D1 D6 D7 D4 D5 D6 D7 CC D9 CE CF C5 DD DE C2
- C4 E2 E2 E4 E4 D5 D9 C6 CA EA EA EC EC C7 EF EF
- F1 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B1 B3 B4 B4 B6 B6 B8 B9 BA BB BC BD BE BF
- A2 A4 DF AE E0 DC E7 ED A1 A3 E8 AD D8 A5 DA DB
- D0 A6 D2 D3 D0 E5 D2 D3 D8 E6 DA DB DC A7 DE DF
- E0 E1 E1 E3 E3 E5 E6 E7 E8 E9 E9 EB EB ED EE EE
- F0 F0 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
diff --git a/sql/share/charsets/hp8.xml b/sql/share/charsets/hp8.xml
new file mode 100644
index 00000000000..036f1cd067c
--- /dev/null
+++ b/sql/share/charsets/hp8.xml
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="hp8">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 20 20 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 02 10 10 10 10 10 10 02 10 02 02
+ 01 10 10 01 02 10 10 02 01 10 01 01 01 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 20 20 20 20 10 10 10 10 10 10 10 10 10 20
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 C8 C0 C9 C1 CD D1 DD A8 A9 AA AB AC CB C3 AF
+ B0 B2 B2 B3 B5 B5 B7 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D4 D1 D6 D7 D4 D5 D6 D7 CC D9 CE CF C5 DD DE C2
+ C4 E2 E2 E4 E4 D5 D9 C6 CA EA EA EC EC C7 EF EF
+ F1 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B1 B3 B4 B4 B6 B6 B8 B9 BA BB BC BD BE BF
+ A2 A4 DF AE E0 DC E7 ED A1 A3 E8 AD D8 A5 DA DB
+ D0 A6 D2 D3 D0 E5 D2 D3 D8 E6 DA DB DC A7 DE DF
+ E0 E1 E1 E3 E3 E5 E6 E7 E8 E9 E9 EB EB ED EE EE
+ F0 F0 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 00C0 00C2 00C8 00CA 00CB 00CE 00CF 00B4 02CB 02C6 00A8 02DC 00D9 00DB 20A4
+00AF 00DD 00FD 00B0 00C7 00E7 00D1 00F1 00A1 00BF 00A4 00A3 00A5 00A7 0192 00A2
+00E2 00EA 00F4 00FB 00E1 00E9 00F3 00FA 00E0 00E8 00F2 00F9 00E4 00EB 00F6 00FC
+00C5 00EE 00D8 00C6 00E5 00ED 00F8 00E6 00C4 00EC 00D6 00DC 00C9 00EF 00DF 00D4
+00C1 00C3 00E3 00D0 00F0 00CD 00CC 00D3 00D2 00D5 00F5 0160 0161 00DA 0178 00FF
+00DE 00FE 00B7 00B5 00B6 00BE 2014 00BC 00BD 00AA 00BA 00AB 25A0 00BB 00B1 0000
+
+</map>
+</unicode>
+
+
+<collation name="hp8">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/hungarian.conf b/sql/share/charsets/hungarian.conf
deleted file mode 100644
index db58d62575f..00000000000
--- a/sql/share/charsets/hungarian.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the hungarian character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 48
- 01 10 01 10 01 01 10 00 00 01 01 01 01 10 01 01
- 10 02 10 02 10 02 02 10 10 02 02 02 02 10 02 02
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 10 01 01 01 01 01 01 10 01 01 01 01 01 01 01 10
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 10
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8B 8B A1 A1 8E A0
- 82 91 92 93 94 A2 96 A3 96 94 81 9B 9C 9D 9E 9F
- A0 A1 A2 A3 B5 B6 A6 93 A8 B9 BA BB BC AD BE BF
- B0 B1 B2 B3 B4 E1 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- D0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- A2 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA 96 EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 9A 90 83 84 85 86 87 88 89 8A 8A 8C 8D 8E 8F
- 90 91 92 A7 99 95 98 97 98 99 9A 9B 9C 9D 9E 9F
- 8F 8D 95 97 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 A0 B2 A2 B4 B5 A5 B7 B8 A9 AA AB AC BD AE AF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA EB CC CD CE CF
- F0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 47 48 4C 4E 53 54 55 56 5A 5B 5C 60 61 64
- 69 6A 6B 6E 72 75 7A 7B 7C 7D 7F 83 84 85 86 87
- 88 41 47 48 4C 4E 53 54 55 56 5A 5B 5C 60 61 64
- 69 6A 6B 6E 72 75 7A 7B 7C 7D 7F 89 8A 8B 8C 00
- 01 78 4E 04 05 06 07 08 09 0A 67 67 56 56 0F 41
- 4E 12 13 67 67 64 78 75 78 67 78 1C 1D 1E 1F FF
- 41 56 64 75 5E 6F FF 67 FF 70 71 73 80 FF 81 82
- FF 42 FF 5D FF 41 6F FF FF 70 71 73 80 FF 81 82
- 6C 41 44 45 46 5F 49 4B 4A 4E 51 52 50 56 57 4D
- FF 62 63 64 66 67 67 FF 6D 77 75 78 78 7E 74 FF
- 64 41 44 45 46 5F 49 4B 4A 4E 51 78 50 56 58 4D
- FF 62 63 64 66 67 67 FF 6D 77 75 78 78 7E 74 FF
diff --git a/sql/share/charsets/keybcs2.xml b/sql/share/charsets/keybcs2.xml
new file mode 100644
index 00000000000..bdbb364822f
--- /dev/null
+++ b/sql/share/charsets/keybcs2.xml
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="keybcs2">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 01 02 82 02 02 01 01 02 82 81 01 01 02 02 01 01
+ 81 02 01 02 02 01 02 01 02 01 01 01 01 01 01 02
+ 02 02 02 02 02 01 01 01 02 02 02 01 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 02 02 01 02 01 02 00 02 01 01 01 02 00 02 02 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 87 81 82 83 84 83 86 87 88 88 8D A1 8C 8D 84 A0
+ 82 91 91 93 94 A2 96 A3 98 94 81 9B 8C 98 A9 9F
+ A0 A1 A2 A3 A4 A4 96 93 9B A9 AA AA AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 ED E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 68 59 5A 7B 7C 7D 7E 7F
+ 87 9A 90 85 8E 85 86 80 89 89 8A 8B 9C 8A 8E 8F
+ 90 92 92 A7 99 95 A6 97 9D 99 9A A8 9C 9D 9E 9F
+ 8F 8B 95 97 A5 A5 A6 A7 A8 9E AB AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC E8 EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 010C 00FC 00E9 010F 00E4 010E 0164 010D 011B 011A 0139 00CD 013E 013A 00C4 00C1
+ 00C9 017E 017D 00F4 00F6 00D3 016F 00DA 00FD 00D6 00DC 0160 013D 00DD 0158 0165
+ 00E1 00ED 00F3 00FA 0148 0147 016E 00D4 0161 0159 0155 0154 00BC 00A1 00AB 00BB
+ 2591 2592 2593 2502 2524 2561 2562 2556 2555 2563 2551 2557 255D 255C 255B 2510
+ 2514 2534 252C 251C 2500 253C 255E 255F 255A 2554 2569 2566 2560 2550 256C 2567
+ 2568 2564 2565 2559 2558 2552 2553 256B 256A 2518 250C 2588 2584 258C 2590 2580
+ 03B1 00DF 0393 03C0 03A3 03C3 00B5 03C4 03A6 0398 03A9 03B4 221E 03C6 03B5 2229
+ 2261 00B1 2265 2264 2320 2321 00F7 2248 00B0 2219 00B7 221A 207F 00B2 25A0 00A0
+</map>
+</unicode>
+
+
+<collation name="keybcs2">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 44 45 47 49 50 51 52 53 54 55 56 57 58 5A
+ 5E 5F 60 63 66 68 6C 6D 6E 6F 72 90 91 92 93 94
+ 95 41 44 45 47 49 50 51 52 53 54 55 56 57 58 5A
+ 5E 5F 60 63 66 68 6C 6D 6E 6F 72 96 97 98 99 9A
+ 45 68 49 47 41 47 66 45 49 49 56 53 56 56 41 41
+ 49 72 72 5A 5A 5A 68 68 6F 5A 68 63 56 6F 60 66
+ 41 53 5A 68 58 58 68 5A 63 60 60 60 A0 A1 A2 A3
+ A4 A5 A6 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC
+ BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC
+ CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC
+ 80 65 83 87 88 89 DD 8A 85 8B 84 81 DE 85 82 DF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
+
diff --git a/sql/share/charsets/koi8_ru.conf b/sql/share/charsets/koi8_ru.conf
deleted file mode 100644
index 4cfee67a236..00000000000
--- a/sql/share/charsets/koi8_ru.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the koi8_ru character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 02 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 01 10 10 10 10 10 10 10 10 10 10 10 10
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 A3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 B3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 E5 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE
- AF B0 B1 E5 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD
- FE DF E0 F6 E3 E4 F4 E2 F5 E8 E9 EA EB EC ED EE
- EF FF F0 F1 F2 F3 E6 E1 FC FB E7 F8 FD F9 F7 FA
- FE DF E0 F6 E3 E4 F4 E2 F5 E8 E9 EA EB EC ED EE
- EF FF F0 F1 F2 F3 E6 E1 FC FB E7 F8 FD F9 F7 FA
diff --git a/sql/share/charsets/koi8_ukr.conf b/sql/share/charsets/koi8_ukr.conf
deleted file mode 100644
index 3e2c8e27325..00000000000
--- a/sql/share/charsets/koi8_ukr.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the koi8_ukr character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 02 02 10 02 02 10 10 10 10 10 02 10 10
- 10 10 10 01 01 10 01 01 10 10 10 10 10 01 10 10
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 20 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 A3 A4 20 A6 A7 20 20 20 20 20 AD 20 20
- 20 20 20 A3 A4 20 A6 A7 20 20 20 20 20 AD 20 20
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 B3 B4 20 B6 B7 20 20 20 20 20 BD 20 20
- 20 20 20 B3 B4 20 B6 B7 20 20 20 20 20 BD 20 20
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4
- B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4
- C5 C6 C7 88 87 C8 8C 8D C9 CA CB CC CD 84 CE CF
- D0 D1 D2 88 87 D3 8C 8D D4 D5 D6 D7 D8 84 D9 DA
- A3 80 81 9B 85 86 99 83 9A 8B 8E 8F 90 91 92 93
- 94 A4 95 96 97 98 89 82 A1 A0 8A 9D A2 9E 9C 9F
- A3 80 81 9B 85 86 99 83 9A 8B 8E 8F 90 91 92 93
- 94 A4 95 96 97 98 89 82 A1 A0 8A 9D A2 9E 9C 9F
diff --git a/sql/share/charsets/koi8r.xml b/sql/share/charsets/koi8r.xml
new file mode 100644
index 00000000000..dae780f14fc
--- /dev/null
+++ b/sql/share/charsets/koi8r.xml
@@ -0,0 +1,119 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="koi8r">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 02 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 01 10 10 10 10 10 10 10 10 10 10 10 10
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 A3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 B3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000a 000b 000c 000d 000e 000f
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001a 001b 001c 001d 001e 001f
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002a 002b 002c 002d 002e 002f
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003a 003b 003c 003d 003e 003f
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004a 004b 004c 004d 004e 004f
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005a 005b 005c 005d 005e 005f
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006a 006b 006c 006d 006e 006f
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007a 007b 007c 007d 007e 007f
+2500 2502 250c 2510 2514 2518 251c 2524 252c 2534 253c 2580 2584 2588 258c 2590
+2591 2592 2593 2320 25a0 2219 221a 2248 2264 2265 00a0 2321 00b0 00b2 00b7 00f7
+2550 2551 2552 0451 2553 2554 2555 2556 2557 2558 2559 255a 255b 255c 255d 255e
+255f 2560 2561 0401 2562 2563 2564 2565 2566 2567 2568 2569 256a 256b 256c 00a9
+044e 0430 0431 0446 0434 0435 0444 0433 0445 0438 0439 043a 043b 043c 043d 043e
+043f 044f 0440 0441 0442 0443 0436 0432 044c 044b 0437 0448 044d 0449 0447 044a
+042e 0410 0411 0426 0414 0415 0424 0413 0425 0418 0419 041a 041b 041c 041d 041e
+041f 042f 0420 0421 0422 0423 0416 0412 042c 042b 0417 0428 042d 0429 0427 042a
+</map>
+</unicode>
+
+
+<collation name="koi8r">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 E5 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE
+ AF B0 B1 E5 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD
+ FE DF E0 F6 E3 E4 F4 E2 F5 E8 E9 EA EB EC ED EE
+ EF FF F0 F1 F2 F3 E6 E1 FC FB E7 F8 FD F9 F7 FA
+ FE DF E0 F6 E3 E4 F4 E2 F5 E8 E9 EA EB EC ED EE
+ EF FF F0 F1 F2 F3 E6 E1 FC FB E7 F8 FD F9 F7 FA
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/koi8u.xml b/sql/share/charsets/koi8u.xml
new file mode 100644
index 00000000000..e6cba068997
--- /dev/null
+++ b/sql/share/charsets/koi8u.xml
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="koi8u">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 02 02 10 02 02 10 10 10 10 10 02 10 10
+ 10 10 10 01 01 10 01 01 10 10 10 10 10 01 10 10
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 20 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 20 20 A3 A4 20 A6 A7 20 20 20 20 20 AD 20 20
+ 20 20 20 A3 A4 20 A6 A7 20 20 20 20 20 AD 20 20
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 20 20 B3 B4 20 B6 B7 20 20 20 20 20 BD 20 20
+ 20 20 20 B3 B4 20 B6 B7 20 20 20 20 20 BD 20 20
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+2500 2502 250C 2510 2514 2518 251C 2524 252C 2534 253C 2580 2584 2588 258C 2590
+2591 2592 2593 2320 25A0 2022 221A 2248 2264 2265 00A0 2321 00B0 00B2 00B7 00F7
+2550 2551 2552 0451 0454 2554 0456 0457 2557 2558 2559 255A 255B 0491 255D 255E
+255F 2560 2561 0401 0404 2563 0406 0407 2566 2567 2568 2569 256A 0490 256C 00A9
+044E 0430 0431 0446 0434 0435 0444 0433 0445 0438 0439 043A 043B 043C 043D 043E
+043F 044F 0440 0441 0442 0443 0436 0432 044C 044B 0437 0448 044D 0449 0447 044A
+042E 0410 0411 0426 0414 0415 0424 0413 0425 0418 0419 041A 041B 041C 041D 041E
+041F 042F 0420 0421 0422 0423 0416 0412 042C 042B 0417 0428 042D 0429 0427 042A
+</map>
+</unicode>
+
+
+<collation name="koi8u">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4
+ B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4
+ C5 C6 C7 88 87 C8 8C 8D C9 CA CB CC CD 84 CE CF
+ D0 D1 D2 88 87 D3 8C 8D D4 D5 D6 D7 D8 84 D9 DA
+ A3 80 81 9B 85 86 99 83 9A 8B 8E 8F 90 91 92 93
+ 94 A4 95 96 97 98 89 82 A1 A0 8A 9D A2 9E 9C 9F
+ A3 80 81 9B 85 86 99 83 9A 8B 8E 8F 90 91 92 93
+ 94 A4 95 96 97 98 89 82 A1 A0 8A 9D A2 9E 9C 9F
+</map>
+</collation>
+
+</charset>
+
+</charsets>
+
diff --git a/sql/share/charsets/latin1.conf b/sql/share/charsets/latin1.conf
deleted file mode 100644
index cf974aefa14..00000000000
--- a/sql/share/charsets/latin1.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the latin1 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
- 44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
- 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
- 44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
diff --git a/sql/share/charsets/latin1.xml b/sql/share/charsets/latin1.xml
new file mode 100644
index 00000000000..c14e369454e
--- /dev/null
+++ b/sql/share/charsets/latin1.xml
@@ -0,0 +1,233 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="latin1">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 00 01 01 01 01 01 01 01 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 00 02 02 02 02 02 02 02 02
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+ 0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+ 00A0 00A1 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 00AA 00AB 00AC 00AD 00AE 00AF
+ 00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 00BA 00BB 00BC 00BD 00BE 00BF
+ 00C0 00C1 00C2 00C3 00C4 00C5 00C6 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF
+ 00D0 00D1 00D2 00D3 00D4 00D5 00D6 00D7 00D8 00D9 00DA 00DB 00DC 00DD 00DE 00DF
+ 00E0 00E1 00E2 00E3 00E4 00E5 00E6 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF
+ 00F0 00F1 00F2 00F3 00F4 00F5 00F6 00F7 00F8 00F9 00FA 00FB 00FC 00FD 00FE 00FF
+</map>
+</unicode>
+
+
+<collation name="latin1">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
+ 44 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
+ 41 41 41 41 5C 5B 5C 43 45 45 45 45 49 49 49 49
+ 44 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
+</map>
+</collation>
+
+
+<collation name="german1">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ 41 41 41 41 41 41 41 43 45 45 45 45 49 49 49 49
+ D0 4E 4F 4F 4F 4F 4F D7 4F 55 55 55 55 59 DE 53
+ 41 41 41 41 41 41 41 43 45 45 45 45 49 49 49 49
+ D0 4E 4F 4F 4F 4F 4F F7 4F 55 55 55 55 59 DE FF
+</map>
+</collation>
+
+
+<collation name="danish">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
+ 44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF
+ 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
+ 44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
+</map>
+</collation>
+
+
+<collation name="latin1_de"/>
+
+
+<collation name="latin1_bin">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+
+<collation name="latin1_ci_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
+ 8F 91 93 95 98 9A A4 A6 A8 AA AF B3 B4 B5 B6 B7
+ B8 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
+ 8F 91 93 95 98 9A A4 A6 A8 AA AF B9 BA BB BC BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ 43 45 47 49 4B 4D 4F 55 5D 5F 61 63 6D 6F 71 73
+ 59 7F 83 85 87 89 8B BD 8D 9C 9E A0 A2 AC B1 97
+ 43 45 47 49 4B 4D 4F 55 5D 5F 61 63 6D 6F 71 73
+ 59 7F 83 85 87 89 8B BE 8D 9C 9E A0 A2 AC B1 AE
+</map>
+</collation>
+
+
+<collation name="latin1_cs_as">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
+ 8F 91 93 95 98 9A A4 A6 A8 AA AF B3 B4 B5 B6 B7
+ B8 42 52 54 58 5C 66 68 6A 6C 76 78 7A 7C 7E 82
+ 90 92 94 96 99 9B A5 A7 A9 AB B0 B9 BA BB BC BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ 43 45 47 49 4B 4D 4F 55 5D 5F 61 63 6D 6F 71 73
+ 59 7F 83 85 87 89 8B BD 8D 9C 9E A0 A2 AC B1 97
+ 44 46 48 4A 4C 4E 50 56 5E 60 62 64 6E 70 72 74
+ 5A 80 84 86 88 8A 8C BE 8E 9D 9F A1 A3 AD B2 AE
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/latin2.conf b/sql/share/charsets/latin2.conf
deleted file mode 100644
index cc18c22c0a2..00000000000
--- a/sql/share/charsets/latin2.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the latin2 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 01 10 01 10 01 01 10 10 01 01 01 01 10 01 01
- 10 02 10 02 10 02 02 10 10 02 02 02 02 10 02 02
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 10 01 01 01 01 01 01 10 01 01 01 01 01 01 01 10
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 10
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 B1 A2 B3 A4 B5 B6 A7 A8 B9 BA BB BC AD BE BF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- D0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 A1 B2 A3 B4 A5 A6 B7 B8 A9 AA AB AC BD AE AF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- F0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 44 45 48 49 4B 4C 4D 4E 4F 50 51 53 54 56
- 58 59 5A 5B 5E 5F 60 61 62 63 64 68 69 6A 6B 6C
- 6D 41 44 45 48 49 4B 4C 4D 4E 4F 50 51 53 54 56
- 58 59 5A 5B 5E 5F 60 61 62 63 64 6E 6F 70 71 FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
- FF 42 FF 52 FF 51 5C FF FF 5D 5B 5E 65 FF 67 66
- FF 42 FF 52 FF 51 5C FF FF 5D 5B 5E 65 FF 67 66
- 5A 43 43 43 43 51 46 45 47 49 4A 49 49 4E 4E 48
- FF 55 54 57 56 56 56 FF 5A 5F 5F 5F 5F 63 5E FF
- 5A 43 43 43 43 51 46 45 47 49 4A 49 49 4E 4E 48
- FF 55 54 57 56 56 56 FF 5A 5F 5F 5F 5F 63 5E FF
diff --git a/sql/share/charsets/latin2.xml b/sql/share/charsets/latin2.xml
new file mode 100644
index 00000000000..377ab19e8ad
--- /dev/null
+++ b/sql/share/charsets/latin2.xml
@@ -0,0 +1,167 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="latin2">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 48 01 10 01 10 01 01 10 10 01 01 01 01 10 01 01
+ 10 02 10 02 10 02 02 10 10 02 02 02 02 10 02 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 10 01 01 01 01 01 01 10 01 01 01 01 01 01 01 10
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 10
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 B1 A2 B3 A4 B5 B6 A7 A8 B9 BA BB BC AD BE BF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ D0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 A1 B2 A3 B4 A5 A6 B7 B8 A9 AA AB AC BD AE AF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ F0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 0104 02D8 0141 00A4 013D 015A 00A7 00A8 0160 015E 0164 0179 00AD 017D 017B
+00B0 0105 02DB 0142 00B4 013E 015B 02C7 00B8 0161 015F 0165 017A 02DD 017E 017C
+0154 00C1 00C2 0102 00C4 0139 0106 00C7 010C 00C9 0118 00CB 011A 00CD 00CE 010E
+0110 0143 0147 00D3 00D4 0150 00D6 00D7 0158 016E 00DA 0170 00DC 00DD 0162 00DF
+0155 00E1 00E2 0103 00E4 013A 0107 00E7 010D 00E9 0119 00EB 011B 00ED 00EE 010F
+0111 0144 0148 00F3 00F4 0151 00F6 00F7 0159 016F 00FA 0171 00FC 00FD 0163 02D9
+</map>
+</unicode>
+
+
+<collation name="latin2">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 44 45 48 49 4B 4C 4D 4E 4F 50 51 53 54 56
+ 58 59 5A 5B 5E 5F 60 61 62 63 64 68 69 6A 6B 6C
+ 6D 41 44 45 48 49 4B 4C 4D 4E 4F 50 51 53 54 56
+ 58 59 5A 5B 5E 5F 60 61 62 63 64 6E 6F 70 71 FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ FF 42 FF 52 FF 51 5C FF FF 5D 5B 5E 65 FF 67 66
+ FF 42 FF 52 FF 51 5C FF FF 5D 5B 5E 65 FF 67 66
+ 5A 43 43 43 43 51 46 45 47 49 4A 49 49 4E 4E 48
+ FF 55 54 57 56 56 56 FF 5A 5F 5F 5F 5F 63 5E FF
+ 5A 43 43 43 43 51 46 45 47 49 4A 49 49 4E 4E 48
+ FF 55 54 57 56 56 56 FF 5A 5F 5F 5F 5F 63 5E FF
+</map>
+</collation>
+
+
+<collation name="croat">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 46 48 49 4A 4B 4C 4D 4E 4F 50 51 52
+ 53 54 55 56 58 59 5A 5B 5C 5D 5E 5B 5C 5D 5E 5F
+ 60 41 42 43 46 48 49 4A 4B 4C 4D 4E 4F 50 51 52
+ 53 54 55 56 58 59 5A 5B 5C 5D 5E 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 57 8B 8C 8D 5F 8F
+ 90 91 92 93 94 95 96 97 98 99 57 9B 9C 9D 5F 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ 41 41 41 41 5C 5B 45 43 44 45 45 45 49 49 49 49
+ 47 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
+ 41 41 41 41 5C 5B 45 43 44 45 45 45 49 49 49 49
+ 47 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
+</map>
+</collation>
+
+
+<collation name="czech"/>
+
+
+<collation name="hungarian">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 47 48 4C 4E 53 54 55 56 5A 5B 5C 60 61 64
+ 69 6A 6B 6E 72 75 7A 7B 7C 7D 7F 83 84 85 86 87
+ 88 41 47 48 4C 4E 53 54 55 56 5A 5B 5C 60 61 64
+ 69 6A 6B 6E 72 75 7A 7B 7C 7D 7F 89 8A 8B 8C 00
+ 01 78 4E 04 05 06 07 08 09 0A 67 67 56 56 0F 41
+ 4E 12 13 67 67 64 78 75 78 67 78 1C 1D 1E 1F FF
+ 41 56 64 75 5E 6F FF 67 FF 70 71 73 80 FF 81 82
+ FF 42 FF 5D FF 41 6F FF FF 70 71 73 80 FF 81 82
+ 6C 41 44 45 46 5F 49 4B 4A 4E 51 52 50 56 57 4D
+ FF 62 63 64 66 67 67 FF 6D 77 75 78 78 7E 74 FF
+ 64 41 44 45 46 5F 49 4B 4A 4E 51 78 50 56 58 4D
+ FF 62 63 64 66 67 67 FF 6D 77 75 78 78 7E 74 FF
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/latin5.conf b/sql/share/charsets/latin5.conf
deleted file mode 100644
index 92fbd2299bb..00000000000
--- a/sql/share/charsets/latin5.conf
+++ /dev/null
@@ -1,78 +0,0 @@
-# Configuration file for the latin5 (turkish) character set
-
-# Note: all accented characters are compared separately (this
-# is different from the default latin1 character set, where
-# e.g. a = ä = á, etc.).
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 FD 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC 69 FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 DD 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC 49 DE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 45 46 47 48 4A 4B 4D 4E 4F 50 51 52
- 54 55 56 57 59 5A 5C 5D 5E 5F 60 61 62 63 64 65
- 66 41 42 43 45 46 47 48 4A 4C 4D 4E 4F 50 51 52
- 54 55 56 57 59 5A 5C 5D 5E 5F 60 87 88 89 8A 8B
- 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B
- 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB
- AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB
- BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB
- CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA
- 49 DB DC DD DE DF 53 E0 E1 E2 E3 E4 5B 4C 58 E5
- CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA
- 49 DB DC DD DE DF 53 FA E1 E2 E3 E4 5B 4B 58 FF
diff --git a/sql/share/charsets/latin5.xml b/sql/share/charsets/latin5.xml
new file mode 100644
index 00000000000..a072ffc5072
--- /dev/null
+++ b/sql/share/charsets/latin5.xml
@@ -0,0 +1,125 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="latin5">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 FD 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC 69 FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 DD 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC 49 DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 00A1 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 00AA 00AB 00AC 00AD 00AE 00AF
+00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 00BA 00BB 00BC 00BD 00BE 00BF
+00C0 00C1 00C2 00C3 00C4 00C5 00C6 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF
+011E 00D1 00D2 00D3 00D4 00D5 00D6 00D7 00D8 00D9 00DA 00DB 00DC 0130 015E 00DF
+00E0 00E1 00E2 00E3 00E4 00E5 00E6 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF
+011F 00F1 00F2 00F3 00F4 00F5 00F6 00F7 00F8 00F9 00FA 00FB 00FC 0131 015F 00FF
+</map>
+</unicode>
+
+
+<collation name="latin5">
+<!--
+# Note: all accented characters are compared separately (this
+# is different from the default latin1 character set, where
+# e.g. a = ä = á, etc.).
+-->
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 45 46 47 48 4A 4B 4D 4E 4F 50 51 52
+ 54 55 56 57 59 5A 5C 5D 5E 5F 60 61 62 63 64 65
+ 66 41 42 43 45 46 47 48 4A 4C 4D 4E 4F 50 51 52
+ 54 55 56 57 59 5A 5C 5D 5E 5F 60 87 88 89 8A 8B
+ 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B
+ 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB
+ AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB
+ BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB
+ CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA
+ 49 DB DC DD DE DF 53 E0 E1 E2 E3 E4 5B 4C 58 E5
+ CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA
+ 49 DB DC DD DE DF 53 FA E1 E2 E3 E4 5B 4B 58 FF
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/latin7.xml b/sql/share/charsets/latin7.xml
new file mode 100644
index 00000000000..eae4d501f44
--- /dev/null
+++ b/sql/share/charsets/latin7.xml
@@ -0,0 +1,168 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="latin7">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
+ 01 20 10 20 10 10 00 00 20 10 20 10 20 10 10 10
+ 20 10 10 10 10 10 10 10 20 00 20 10 20 10 10 20
+ 48 20 10 10 10 20 10 10 10 10 01 10 10 10 10 01
+ 10 10 10 10 10 10 10 10 10 10 02 10 10 10 10 02
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 10
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 BA AB AC AD AE BF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 A8 B9 AA BB BC BD BE AF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 008A 008B 008C 008D 008E 008F
+0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 009A 009B 009C 009D 009E 009F
+00A0 201D 00A2 00A3 00A4 201E 00A6 00A7 00D8 00A9 0156 00AB 00AC 00AD 00AE 00C6
+00B0 00B1 00B2 00B3 201C 00B5 00B6 00B7 00F8 00B9 0157 00BB 00BC 00BD 00BE 00E6
+0104 012E 0100 0106 00C4 00C5 0118 0112 010C 00C9 0179 0116 0122 0136 012A 013B
+0160 0143 0145 00D3 014C 00D5 00D6 00D7 0172 0141 015A 016A 00DC 017B 017D 00DF
+0105 012F 0101 0107 00E4 00E5 0119 0113 010D 00E9 017A 0117 0123 0137 012B 013C
+0161 0144 0146 00F3 014D 00F5 00F6 00F7 0173 0142 015B 016B 00FC 017C 017E 2019
+</map>
+</unicode>
+
+
+<collation name="estonia">
+<map>
+ 00 02 03 04 05 06 07 08 09 2E 2F 30 31 32 0A 0B
+ 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B
+ 2C 33 34 35 36 37 38 27 39 3A 3B 5D 3C 28 3D 3E
+ 76 7A 7C 7E 80 81 82 83 84 85 3F 40 5E 5F 60 41
+ 42 86 90 92 98 9A A4 A6 AA AC B2 B4 B8 BE C0 C6
+ CE D0 D2 D6 E5 E8 EE F0 FA FC DD 43 44 45 46 47
+ 48 87 91 93 99 9B A5 A7 AB AD B3 B5 B9 BF C1 C7
+ CF D1 D3 D7 E6 E9 EF F1 FB FD DE 49 4A 4B 4C 1C
+ 01 1D 57 1E 5A 74 71 72 1F 75 20 5B 21 4E 52 51
+ 22 55 56 58 59 73 2A 2B 23 E7 24 5C 25 4F 54 26
+ 2D FE 66 67 68 FF 4D 69 CC 6A D4 62 6B 29 6C 8E
+ 6D 61 7D 7F 50 6E 6F 70 CD 7B D5 63 77 78 79 8F
+ 8C B0 88 94 F4 8A A2 A0 96 9C DF 9E A8 B6 AE BA
+ DB C2 C4 C8 CA F2 F6 64 EC BC D8 EA F8 E1 E3 DA
+ 8D B1 89 95 F5 8B A3 A1 97 9D E0 9F A9 B7 AF BB
+ DC C3 C5 C9 CB F3 F7 65 ED BD D9 EB F9 E2 E4 53
+</map>
+</collation>
+
+
+<collation name="latvian">
+<!-- Created for case-sensitive record search -->
+<!-- by Andis Grasis & Rihards Grasis e-mail:andis@cata.lv -->
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 30 32 33 34 35 36 37 2B 38 39 3A 5C 3B 2C 3C 3D
+ 76 7A 7C 7E 80 81 82 83 84 85 3E 3F 5D 5E 5F 40
+ 41 86 92 94 9A 9C A6 A8 AC AE B4 B6 BA C0 C2 C8
+ D4 D6 D8 DC E3 E6 EE F0 F2 F4 F6 42 43 44 45 46
+ 47 87 93 95 9B 9D A7 A9 AD AF B5 B7 BB C1 C3 C9
+ D5 D7 D9 DD E4 E7 EF F1 F3 F5 F7 48 49 4A 4B 20
+ 75 21 56 22 59 73 70 71 23 74 24 5A 25 4D 51 50
+ 26 54 55 57 58 72 2E 2F 27 E5 28 5B 29 4E 53 2A
+ 31 FE 65 66 67 FF 4C 68 D3 69 DA 61 6A 2D 6B 90
+ 6C 60 7D 7F 4F 6D 6E 6F D2 7B DB 62 77 78 79 91
+ 8E B2 8A 96 88 8C A4 A2 98 9E F8 A0 AA B8 B0 BE
+ E1 C4 C6 CA CE D0 CC 63 EC BC DE EA E8 FA FC E0
+ 8F B3 8B 97 89 8D A5 A3 99 9F F9 A1 AB B9 B1 BF
+ E2 C5 C7 CB CF D1 CD 64 ED BD DF EB E9 FB FD 52
+</map>
+</collation>
+
+
+<collation name="latvian1">
+<!-- Created for case-insensitive record search -->
+<!-- Created by Andis & Rihards -->
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 30 32 33 34 35 36 37 2B 38 39 3A 5C 3B 2C 3C 3D
+ 76 7A 7C 7E 80 81 82 83 84 85 3E 3F 5D 5E 5F 40
+ 41 86 92 94 9A 9C A6 A8 AC AE B4 B6 BA C0 C2 C8
+ D4 D6 D8 DC E3 E6 EE F0 F2 F4 F6 42 43 44 45 46
+ 47 86 92 94 9A 9C A6 A8 AC AE B4 B6 BA C0 C2 C8
+ D4 D6 D8 DC E2 E6 EE F0 F2 F4 F6 48 49 4A 4B 20
+ 75 21 56 22 59 73 70 71 23 74 24 5A 25 4D 51 50
+ 26 54 55 57 58 72 2E 2F 27 E5 28 5B 29 4E 53 2A
+ 31 FE 65 66 67 FF 4C 68 2D 69 DA 61 6A 2D 6B 90
+ 6C 60 7D 7F 4F 6D 6E 6F D3 7B DB 62 77 78 79 90
+ 8E B2 8A 96 88 8C A4 A2 98 9E F8 A0 AA B8 B0 BE
+ E1 C4 C6 CA CE D0 CC 63 EC BC DE EA E8 FA FC E0
+ 8E B2 8A 96 88 8C A4 A2 98 9E F8 A0 AA B8 B0 BE
+ E1 C4 C6 CA CE D0 CC 64 EC BC DE EA E8 FA FC 52
+</map>
+</collation>
+
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/pclatin1.xml b/sql/share/charsets/pclatin1.xml
new file mode 100644
index 00000000000..742dcaec459
--- /dev/null
+++ b/sql/share/charsets/pclatin1.xml
@@ -0,0 +1,119 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="pclatin1">
+
+<ctype>
+<map>
+ 00
+ 20 30 30 30 30 30 30 20 20 28 28 28 28 28 30 30
+ 30 30 30 30 30 30 30 30 30 30 20 30 30 30 30 30
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 30
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 01 01
+ 01 02 01 02 02 02 02 02 02 01 01 10 10 10 10 10
+ 02 02 02 02 02 01 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 20
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 87 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 84 86
+ 82 91 91 93 94 95 96 97 98 94 81 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A4 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 9A 90 41 8E 41 8F 80 45 45 45 49 49 49 8E 8F
+ 90 92 92 4F 99 4F 55 55 59 99 9A 9B 9C 9D 9E 9F
+ 41 49 4F 55 A5 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000a 000b 000c 000d 000e 000f
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001a 001b 001c 001d 001e 001f
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002a 002b 002c 002d 002e 002f
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003a 003b 003c 003d 003e 003f
+0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004a 004b 004c 004d 004e 004f
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005a 005b 005c 005d 005e 005f
+0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006a 006b 006c 006d 006e 006f
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007a 007b 007c 007d 007e 007f
+00c7 00fc 00e9 00e2 00e4 00e0 00e5 00e7 00ea 00eb 00e8 00ef 00ee 00ec 00c4 00c5
+00c9 00e6 00c6 00f4 00f6 00f2 00fb 00f9 00ff 00d6 00dc 00a2 00a3 00a5 20a7 0192
+00e1 00ed 00f3 00fa 00f1 00d1 00aa 00ba 00bf 2310 00ac 00bd 00bc 00a1 00ab 00bb
+2591 2592 2593 2502 2524 2561 2562 2556 2555 2563 2551 2557 255d 255c 255b 2510
+2514 2534 252c 251c 2500 253c 255e 255f 255a 2554 2569 2566 2560 2550 256c 2567
+2568 2564 2565 2559 2558 2552 2553 256b 256a 2518 250c 2588 2584 258c 2590 2580
+03b1 00df 0393 03c0 03a3 03c3 00b5 03c4 03a6 0398 03a9 03b4 221e 03c6 03b5 2229
+2261 00b1 2265 2264 2320 2321 00f7 2248 00b0 2219 00b7 221a 207f 00b2 25a0 00a0
+</map>
+</unicode>
+
+
+<collation name="pclatin1">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 43 59 45 41 5C 41 5B 43 45 45 45 49 49 49 5C 5B
+ 45 5C 5C 4F 5D 4F 55 55 59 5D 59 24 24 24 24 24
+ 41 49 4F 55 4E 4E A6 A7 3F A9 AA AB AC 21 22 22
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/pclatin2.xml b/sql/share/charsets/pclatin2.xml
new file mode 100644
index 00000000000..4402edcd847
--- /dev/null
+++ b/sql/share/charsets/pclatin2.xml
@@ -0,0 +1,119 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="pclatin2">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
+ 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 00
+ 01 02 02 02 02 02 02 02 02 02 01 02 02 01 01 01
+ 01 01 02 02 02 01 02 01 02 01 01 01 02 01 00 02
+ 02 02 02 02 01 02 01 02 01 02 00 02 01 01 00 00
+ 00 00 00 00 00 01 01 01 02 00 00 00 00 01 02 00
+ 00 00 00 00 00 00 01 02 00 00 00 00 00 00 00 00
+ 02 01 01 01 02 01 01 01 02 00 00 00 00 01 01 00
+ 01 02 01 01 02 02 01 02 01 01 02 01 02 01 02 00
+ 00 00 00 00 00 00 00 00 00 00 00 02 01 02 00 48
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 87 81 82 83 84 85 86 87 88 89 8B 8B 8C AB 84 86
+ 82 92 92 93 94 96 96 98 98 94 81 9C 9C 88 9E 9F
+ A0 A1 A2 A3 A5 A5 A7 A7 A9 A9 AA AB 9F B8 AE AF
+ B0 B1 B2 B3 B4 A0 83 D8 B8 B9 BA BB BC BE BE BF
+ C0 C1 C2 C3 C4 C5 C7 C7 C8 C9 CA CB CC CD CE CF
+ D0 D0 D4 89 D4 E5 A1 8C D8 D9 DA DB DC EE 85 DF
+ A2 E1 93 E4 E4 E5 E7 E7 EA A3 E8 FB EC EC EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
+ 80 9A 90 B6 8E DE 8F 80 9D D3 8A 8A D7 8D 8E 8F
+ 90 91 91 E2 99 95 95 97 97 99 9A 9B 9B 9D 9E AC
+ B5 D6 E0 E9 A4 A4 A6 A6 A8 A8 AA 8D AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 AD B9 BA BB BC BE BD BF
+ C0 C1 C2 C3 C4 C5 C6 C6 C8 C9 CA CB CC CD CE CF
+ D1 D1 D2 D3 D2 D5 D6 D7 B7 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E3 D5 E6 E6 E8 E9 E8 EB ED ED DD EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA EB FC FC FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+ 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+ 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+ 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+ 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+ 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+ 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
+ 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+ 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
+ 00C7 00FC 00E9 00E2 00E4 016F 0107 00E7 0142 00EB 0150 0151 00EE 0179 00C4 0106
+ 00C9 0139 013A 00F4 00F6 013D 013E 015A 015B 00D6 00DC 0164 0165 0141 00D7 010D
+ 00E1 00ED 00F3 00FA 0104 0105 017D 017E 0118 0119 00AC 017A 010C 015F 00AB 00BB
+ 2591 2592 2593 2502 2524 00C1 00C2 011A 015E 2563 2551 2557 255D 017B 017C 2510
+ 2514 2534 252C 251C 2500 253C 0102 0103 255A 2554 2569 2566 2560 2550 256C 00A4
+ 0111 0110 010E 00CB 010F 0147 00CD 00CE 011B 2518 250C 2588 2584 0162 016E 2580
+ 00D3 00DF 00D4 0143 0144 0148 0160 0161 0154 00DA 0155 0170 00FD 00DD 0163 00B4
+ 00AD 02DD 02DB 02C7 02D8 00A7 00F7 00B8 00B0 00A8 02D9 0171 0158 0159 25A0 00A0
+</map>
+</unicode>
+
+
+<collation name="pclatin2">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 47 48 4C 4F 54 55 56 57 5A 5B 5C 5E 5F 62
+ 67 68 69 6C 71 74 75 76 77 78 7B 90 91 92 93 94
+ 95 41 47 48 4C 4F 54 55 56 57 5A 5B 5C 5E 5F 62
+ 67 68 69 6C 71 74 75 76 77 78 7B 96 97 98 99 9A
+ 48 74 4F 41 41 74 48 48 5C 4F 62 62 57 7B 41 48
+ 4F 5C 5C 62 62 5C 5C 6C 6C 62 74 71 71 5C 9E 48
+ 41 57 62 74 41 41 7B 7B 4F 4F AA 7B 48 6C AE AF
+ B0 B1 B2 B3 B4 41 41 4F 6C B5 BA BB BC 7B 7B BF
+ C0 C1 C2 C3 C4 C5 41 41 C8 C9 CA CB CC CD CE CF
+ 4C 4C 4C 4F 4C 60 57 57 4F D9 DA DB DC 71 74 DF
+ 62 70 62 60 60 60 6C 6C 69 74 69 74 78 78 71 EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA 74 69 69 FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
diff --git a/sql/share/charsets/swe7.conf b/sql/share/charsets/swe7.conf
deleted file mode 100644
index d2de48b4d1c..00000000000
--- a/sql/share/charsets/swe7.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the swe7 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 01 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 10
- 01 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 59 5F
- 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 59 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
diff --git a/sql/share/charsets/swe7.xml b/sql/share/charsets/swe7.xml
new file mode 100644
index 00000000000..ffa1d90608d
--- /dev/null
+++ b/sql/share/charsets/swe7.xml
@@ -0,0 +1,121 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets>
+
+<charset name="swe7">
+
+<ctype>
+<map>
+ 00
+ 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
+ 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+ 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
+ 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
+ 01 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
+ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 10
+ 01 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
+ 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+</map>
+</ctype>
+
+
+<lower>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 5F
+ 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+ 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</lower>
+
+
+<upper>
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+ 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</upper>
+
+
+<unicode>
+<map>
+0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F
+0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F
+0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F
+0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F
+00C9 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
+0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 00C4 00D6 00C5 00DC 005F
+00E9 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 00E4 00F6 00E5 00FC 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+</map>
+</unicode>
+
+
+<collation name="swe7">
+<map>
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 59 5F
+ 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+ 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 59 7F
+ 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
+ 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
+ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
+ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+</map>
+</collation>
+
+</charset>
+
+</charsets>
+
+
diff --git a/sql/share/charsets/usa7.conf b/sql/share/charsets/usa7.conf
deleted file mode 100644
index b9e7a44c894..00000000000
--- a/sql/share/charsets/usa7.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the usa7 character set
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 5E 5F
- 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 59 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
diff --git a/sql/share/charsets/win1250.conf b/sql/share/charsets/win1250.conf
deleted file mode 100644
index 31d253d7381..00000000000
--- a/sql/share/charsets/win1250.conf
+++ /dev/null
@@ -1,74 +0,0 @@
-# Configuration file for the win1250 character set.
-
-# The ctype array must have 257 elements.
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 20 20 10 20 10 10 10 10 20 10 01 10 01 01 01 01
- 20 10 10 10 10 10 10 10 20 10 02 10 02 02 02 02
- 48 10 10 01 10 01 10 01 10 10 01 10 10 10 10 01
- 10 10 10 02 10 10 10 10 10 02 02 10 01 10 02 02
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 10
-
-# The to_lower array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 9A 8B 9C 9D 9E 9F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 B3 A4 B9 A6 DF A8 A9 BA AB AC AD AE BF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BE BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# The to_upper array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 8A 9B 8C 8D 8E 8F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 A3 B4 B5 B6 B7 B8 A5 AA BB BC BD BC AF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE A7
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
-
-# The sort_order array must have 256 elements.
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 46 49 4A 4B 4C 4D 4E 4F 50 52 53 55
- 56 57 58 59 5B 5C 5D 5E 5F 60 61 63 64 65 66 67
- 68 41 42 43 46 49 4A 4B 4C 4D 4E 4F 50 52 53 55
- 56 57 58 59 5B 5C 5D 5E 5F 60 61 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 5A 8B 5A 5B 62 62
- 90 91 92 93 94 95 96 97 98 99 5A 9B 5A 5B 62 62
- 20 A1 A2 50 A4 41 A6 59 A8 A9 59 AB AC AD AE 62
- B0 B1 B2 50 B4 B5 B6 B7 B8 41 59 BB 50 BD 50 62
- 58 41 41 41 41 50 45 43 44 49 49 49 49 4D 4D 46
- 47 53 53 55 55 55 55 D7 58 5C 5C 5C 5C 60 5B 59
- 58 41 41 41 41 50 45 43 44 49 49 49 49 4D 4D 46
- 47 53 53 55 55 55 55 F7 58 5C 5C 5C 5C 60 5B FF
diff --git a/sql/share/charsets/win1251.conf b/sql/share/charsets/win1251.conf
deleted file mode 100644
index a5ccc3190ad..00000000000
--- a/sql/share/charsets/win1251.conf
+++ /dev/null
@@ -1,82 +0,0 @@
-# Configuration file for the win1251 character set
-
-# NOTE: this character set is deprecated. Please don't use it
-# unless you must because of old tables.
-#
-# If you want to convert your files to charset cp1251, you can do:
-#
-# myisamchk -rq --set-character-set-name=cp1251 *.MYI
-
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 01 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 02 10 10 10 10 10 10 10
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F5 F7 F8 F9 FA FB FC FD FE FF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 A8 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D5 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
- 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 A3 A4 A5 A6 A7 C6 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 C6 B9 BA BB BC BD BE BF
- C0 C1 C2 C3 C4 C5 C7 C8 C9 CA CB CC CD CE CF D0
- D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0
- C0 C1 C2 C3 C4 C5 C7 C8 C9 CA CB CC CD CE CF D0
- D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0
diff --git a/sql/share/charsets/win1251ukr.conf b/sql/share/charsets/win1251ukr.conf
deleted file mode 100644
index e693958910e..00000000000
--- a/sql/share/charsets/win1251ukr.conf
+++ /dev/null
@@ -1,77 +0,0 @@
-# Configuration file for the win1251ukr character set
-
-# it's really, just a cp1251 charset with Ukranian letter
-# marked as "letters"
-
-# ctype array (must have 257 elements)
- 00
- 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
- 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
- 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
- 10 10 10 10 10 10 10 10 01 10 01 10 10 10 10 01
- 10 10 01 02 10 10 10 10 02 10 02 10 10 10 10 02
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
- 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
-
-# to_lower array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
- 20 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
- 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 A5 20 20 A8 20 AA 20 20 20 20 AF
- 20 20 B2 B2 A5 20 20 20 A8 20 AA 20 20 20 20 AF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
- C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
-
-# to_upper array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
- 20 20 20 20 20 B4 20 20 B8 20 BA 20 20 20 20 BF
- 20 20 B3 B3 B4 20 20 20 B8 20 BA 20 20 20 20 BF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
- E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
-
-# sort_order array (must have 256 elements)
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
- 20 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
- 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
- A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4
- B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4
- C5 C6 C7 C8 C9 84 CA CB 88 CC 87 CD CE CF D0 8D
- D1 D2 8C 8C 84 D3 D4 D5 88 D6 87 D7 D8 D9 DA 8D
- 80 81 82 83 85 86 89 8A 8B 8E 8F 90 91 92 93 94
- 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4
- 80 81 82 83 85 86 89 8A 8B 8E 8F 90 91 92 93 94
- 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index b69484cb38b..6c3196bfeba 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -1,4 +1,4 @@
-/*
+v/*
Modifikoval Petr -B©najdr, snajdr@pvt.net, snajdr@cpress.cz v.0.01 -A
ISO LATIN-8852-2
Dal-B¹í verze Jan Pazdziora, adelton@fi.muni.cz-A
@@ -103,7 +103,7 @@
"Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE",
"Nemohu zru-B¹it '%-.64s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe",
"Z-Báznamù: %ld Zdvojených: %ld Varování: %ld",
-"INSERT TABLE '%-.64s' nen-Bí dovoleno v seznamu tabulek FROM",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Nezn-Bámá identifikace threadu: %lu",
"Nejste vlastn-Bíkem threadu %lu",
"Nejsou pou-B¾ity ¾ádné tabulky",
@@ -206,10 +206,10 @@
"Nezn-Bámá systémová promìnná '%-.64s'",
"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena",
"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -247,3 +247,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index ccbc53a0d29..dcc016511dd 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -97,7 +97,7 @@
"Man kan ikke slette alle felter med ALTER TABLE. Brug DROP TABLE i stedet.",
"Kan ikke udføre DROP '%-.64s'. Undersøg om feltet/nøglen eksisterer.",
"Poster: %ld Ens: %ld Advarsler: %ld",
-"INSERT TABLE '%-.64s' er ikke tilladt i FROM tabel liste",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Ukendt tråd id: %lu",
"Du er ikke ejer af tråden %lu",
"Ingen tabeller i brug",
@@ -202,8 +202,8 @@
"Tabellen '%-.64s' er markeret med fejl og sidste (automatiske?) REPAIR fejlede",
"Advarsel: Visse data i tabeller der ikke understøtter transaktioner kunne ikke tilbagestilles",
"Fler-udtryks transaktion krævede mere plads en 'max_binlog_cache_size' bytes. Forhøj værdien af denne variabel og prøv igen',
-"Denne handling kunne ikke udføres med kørende slave, brug først kommandoen SLAVE STOP",
-"Denne handling kræver en kørende slave. Konfigurer en slave og brug kommandoen SLAVE START",
+"Denne handling kunne ikke udføres med kørende slave, brug først kommandoen STOP SLAVE",
+"Denne handling kræver en kørende slave. Konfigurer en slave og brug kommandoen START SLAVE",
"Denne server er ikke konfigureret som slave. Ret in config-filen eller brug kommandoen CHANGE MASTER TO",
"Kunne ikke initialisere master info-struktur. Check om rettigheder i master.info",
"Kunne ikke danne en slave-tråd. Check systemressourcerne",
@@ -241,3 +241,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 7fce0c7b4f9..6091616fc4a 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -105,7 +105,7 @@
"Het is niet mogelijk alle velden te verwijderen met ALTER TABLE. Gebruik a.u.b. DROP TABLE hiervoor!",
"Kan '%-.64s' niet weggooien. Controleer of het veld of de zoeksleutel daadwerkelijk bestaat.",
"Records: %ld Dubbel: %ld Waarschuwing: %ld",
-"INSERT TABLE '%-.64s' is niet toegestaan in de FROM tabel-lijst",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Onbekend thread id: %lu",
"U bent geen bezitter van thread %lu",
"Geen tabellen gebruikt.",
@@ -210,8 +210,8 @@
"Tabel '%-.64s' staat als gecrashed gemarkeerd en de laatste (automatische?) reparatie poging mislukte",
"Waarschuwing: Roll back mislukt voor sommige buiten transacties gewijzigde tabellen",
"Multi-statement transactie vereist meer dan 'max_binlog_cache_size' bytes opslag. Verhoog deze mysqld variabele en probeer opnieuw',
-"Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst SLAVE STOP",
-"Deze operatie vereist een actieve slave, configureer slave en doe dan SLAVE START",
+"Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst STOP SLAVE",
+"Deze operatie vereist een actieve slave, configureer slave en doe dan START SLAVE",
"De server is niet geconfigureerd als slave, fix in configuratie bestand of met CHANGE MASTER TO",
"Kon master info structuur niet initialiseren, controleer permissies in master.info",
"Kon slave thread niet aanmaken, controleer systeem resources",
@@ -249,3 +249,16 @@
"Foutieve toepassing/plaatsing van '%s'",
"Deze versie van MySQL ondersteunt nog geen '%s'",
"Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index a11be9b0e7f..954b7cd2fb3 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -94,7 +94,7 @@
"You can't delete all columns with ALTER TABLE. Use DROP TABLE instead",
"Can't DROP '%-.64s'. Check that column/key exists",
"Records: %ld Duplicates: %ld Warnings: %ld",
-"INSERT TABLE '%-.64s' isn't allowed in FROM table list",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Unknown thread id: %lu",
"You are not owner of thread %lu",
"No tables used",
@@ -197,10 +197,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -238,3 +238,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias",
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index d0a30b2f434..43eb5de89a5 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -99,7 +99,7 @@
"ALTER TABLE kasutades ei saa kustutada kõiki tulpasid. Kustuta tabel DROP TABLE abil",
"Ei suuda kustutada '%-.64s'. Kontrolli kas tulp/võti eksisteerib",
"Kirjeid: %ld Kattuvaid: %ld Hoiatusi: %ld",
-"INSERT TABLE '%-.64s' ei ole lubatud FROM tabelite nimekirjas",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Tundmatu lõim: %lu",
"Ei ole lõime %lu omanik",
"Ühtegi tabelit pole kasutusel",
@@ -204,8 +204,8 @@
"Tabel '%-.64s' on märgitud vigaseks ja viimane (automaatne?) parandus ebaõnnestus",
"Hoiatus: mõnesid transaktsioone mittetoetavaid tabeleid ei suudetud tagasi kerida",
"Mitme lausendiga transaktsioon nõudis rohkem ruumi kui lubatud 'max_binlog_cache_size' muutujaga. Suurenda muutuja väärtust ja proovi uuesti",
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -243,3 +243,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index ab1761ca042..d7bb19c2876 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -94,7 +94,7 @@
"Vous ne pouvez effacer tous les champs avec ALTER TABLE. Utilisez DROP TABLE",
"Ne peut effacer (DROP) '%-.64s'. Vérifiez s'il existe",
"Enregistrements: %ld Doublons: %ld Avertissements: %ld",
-"INSERT TABLE '%-.64s' n'est pas permis dans FROM liste des tables",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Numéro de tâche inconnu: %lu",
"Vous n'êtes pas propriétaire de la tâche no: %lu",
"Aucune table utilisée",
@@ -199,8 +199,8 @@
"La table '%-.64s' est marquée 'crashed' et le dernier 'repair' a échoué",
"Attention: certaines tables ne supportant pas les transactions ont été changées et elles ne pourront pas être restituées",
"Cette transaction à commandes multiples nécessite plus de 'max_binlog_cache_size' octets de stockage, augmentez cette variable de mysqld et réessayez',
-"Cette opération ne peut être réalisée avec un esclave actif, faites SLAVE STOP d'abord",
-"Cette opération nécessite un esclave actif, configurez les esclaves et faites SLAVE START",
+"Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord",
+"Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE",
"Le server n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO",
"Impossible d'initialiser les structures d'information de maître, vérifiez les permissions sur master.info",
"Impossible de créer une tâche esclave, vérifiez les ressources système",
@@ -238,3 +238,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index a99aea38563..765fbd875e2 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -2,7 +2,13 @@
This file is public domain and comes with NO WARRANTY of any kind
Dirk Munzinger (dmun@4t2.com)
- Version: 07.06.2001 */
+ Version: 07.06.2001
+
+ Georg Richter (georg@php.net)
+ fixed typos and translation
+ translated new error messages
+ 2002-12-11
+ */
"hashchk",
"isamchk",
@@ -13,41 +19,41 @@
"Kann Datenbank '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits.",
"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden.",
-"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehler %d)",
-"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehler %d)",
+"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
+"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
"Fehler beim Löschen von '%-.64s'. (Fehler: %d)",
"Datensatz in der Systemtabelle nicht lesbar.",
-"Kann Status von '%-.64s' nicht erhalten. (Fehler: %d)",
-"Kann Arbeitsverzeichnis nicht erhalten. (Fehler: %d)",
-"File nicht sperrbar. (Fehler: %d)",
+"Kann Status von '%-.64s' nicht ermitteln. (Fehler: %d)",
+"Kann Arbeitsverzeichnis nicht ermitteln. (Fehler: %d)",
+"Datei nicht sperrbar. (Fehler: %d)",
"Kann Datei '%-.64s' nicht öffnen. (Fehler: %d)",
"Kann Datei '%-.64s' nicht finden. (Fehler: %d)",
"Verzeichnis von '%-.64s' nicht lesbar. (Fehler: %d)",
-"Verzeichnis kann nicht nach '%-.64s' gewechselt werden. (Fehler: %d)",
+"Kann nicht in das Verzeichnis '%-.64s' wechseln. (Fehler: %d)",
"Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert.",
"Festplatte voll (%-.64s). Warte bis jemand Platz schafft ...",
"Kann nicht speichern, doppelter Schlüssel in Tabelle '%-.64s'.",
"Fehler beim Schließen von '%-.64s'. (Fehler: %d)",
"Fehler beim Lesen der Datei '%-.64s'. (Fehler: %d)",
-"Fehler beim Umbennenen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
+"Fehler beim Umbenennen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
"Fehler beim Speichern der Datei '%-.64s'. (Fehler: %d)",
"'%-.64s' ist für Veränderungen gesperrt.",
"Sortieren abgebrochen.",
"View '%-.64s' existiert für '%-.64s' nicht.",
-"Fehler %d. (table handler)",
-"Diese Option gibt es nicht. (table handler)",
+"Fehler %d. (Tabellenhandler)",
+"Diese Option gibt es nicht. (Tabellenhandler)",
"Kann Datensatz nicht finden.",
"Falsche Information in Datei: '%-.64s'",
"Falsche Schlüssel-Datei für Tabelle '%-.64s'. Versuche zu reparieren!",
"Alte Schlüssel-Datei für Tabelle '%-.64s'. Repariere!
"'%-.64s' ist nur lesbar.",
-"Kein Speicher (benötigt %d bytes). Server neu starten.",
-"Kein Speicher zum Sortieren. Server Sortier-Buffer erhöhen.",
-"Unerwartetes EOF beim Lesen der Datei '%-.64s'. (Fehler: %d)",
+"Kein Speicher vorhanden (benötigt %d bytes). Server neu starten.",
+"Kein Speicher zum Sortieren. sort_buffer_size sollte erhöht werden.",
+"Unerwartetes Ende beim Lesen der Datei '%-.64s'. (Fehler: %d)",
"Zu viele Verbindungen.",
"Zuwenig Speicher.",
"Kann Hostname für diese Adresse nicht erhalten.",
-"Schlechter handshake.",
+"Schlechter Handshake.",
"Keine Zugriffsberechtigung für Benutzer: '%-.32s@%-.64s' für Datenbank '%-.64s'.",
"Keine Zugriffsberechtigung für Benutzer: '%-.32s@%-.64s'. (Verwendetes Passwort: %-.64s)",
"Keine Datenbank ausgewählt.",
@@ -61,16 +67,16 @@
"Unbekanntes Tabellenfeld '%-.64s' in %-.64s.",
"'%-.64s' ist nicht in GROUP BY.",
"Gruppierung nicht möglich bei '%-.64s'.",
-"Im Statement wurden sowohl sum-Funktionen als auch Spalten verwendet. Nicht möglich.",
+"Die Verwendung von sum-Funktionen und Spalten ist nicht möglich.",
"Spaltenzähler entspricht nicht dem Wertzähler.",
-"Name des Identifizierers '%-.64s' ist zu lang.",
+"Name des Bezeichners '%-.64s' ist zu lang.",
"Doppelter Spaltenname vorhanden: '%-.64s'",
"Doppelter Name für Schlüssel (Key) vorhanden: '%-.64s'",
"Doppelter Eintrag '%-.64s' für Schlüssel %d.",
"Falsche Spalten-Spezifizierung für Spalte '%-.64s'.",
"%-.64s bei '%-.64s' in Zeile %d.",
"Leere Abfrage.",
-"Keine eindeutige(n) Tabelle/Alias: '%-.64s'",
+"Keine eindeutiger Tabellenname/Alias: '%-.64s'",
"Fehlerhafter Vorgabewert (Default-Wert): '%-.64s'",
"Mehrfacher Primärschlüssel (Primary Key) definiert.",
"Zuviele Schlüssel definiert. Maximal %d Schlüssel erlaubt.",
@@ -78,37 +84,37 @@
"Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d.",
"In der Tabelle gibt es keine Schlüsselspalte '%-.64s'.",
"BLOB-Feld '%-.64s' kann nicht als Schlüssel verwendet werden.",
-"Feldlänge für Feld '%-.64s' zu groß (max = %d). BLOB-Feld verwenden!",
+"Feldlänge für Feld '%-.64s' zu groß (max. = %d). BLOB-Feld verwenden!",
"Nur ein Auto-Feld möglich, welches als Schlüssel definiert werden muß.",
-"%-.64s: Warten auf Verbindungen.\n",
+"%-.64s: Warte auf Verbindungen.\n",
"%-.64s: Normal beendet.\n",
"%-.64s: Signal %d erhalten. Abbruch!\n",
"%-.64s: Shutdown ausgeführt.\n",
-"%-.64s: Beendigung des Thread %ld veranlaßt. Benutzer: '%-.64s'\n",
+"%-.64s: Beendigung des Thread %ld veranlasst. Benutzer: '%-.64s'\n",
"Kann IP-Socket nicht erstellen.",
-"Tabelle '%-.64s' hat keinen solchen Index wie in CREATE INDEX verwendet. Index neu anlegen.",
-"Feld-Separator Argument ist nicht in der Form wie erwartet. Bitte im Manual nachlesen.",
+"Tabelle '%-.64s' besitzt keinen wie in CREATE INDEX verwendeten Index. Index neu anlegen.",
+"Feldbegrenzer Argument ist nicht in der Form wie erwartet. Bitte im Manual nachlesen.",
"Eine feste Reihenlänge kann für BLOBs nicht verwendet werden. Verwende 'fields terminated by' stattdessen.",
-"Feld '%-.64s' muß im Datenbank-Directory vorhanden und lesbar für alle sein.",
-"File '%-.64s' bereits vorhanden.",
+"Feld '%-.64s' muß im Datenbank-Verzeichnis vorhanden und lesbar für alle sein.",
+"Datei '%-.64s' bereits vorhanden.",
"Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld",
"Datensätze: %ld Duplikate: %ld",
-"Falscher Subteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String oder die verwendete Länge ist länger als der Teilschlüssel.",
+"Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder der Tabellenhandler unterstützt keine Unterteilschlüssel.",
"Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Verwende DROP TABLE stattdessen.",
"Kann '%-.64s' nicht löschen (DROP). Existiert das Feld/der Schlüssel?",
"Datensätze: %ld Duplikate: %ld Warnungen: %ld",
-"INSERT TABLE '%-.64s' nicht erlaubt im FROM Abschnitt.",
+"Die Verwendung der Zieltabelle '%-.64s' ist bei Update in FROM Teil nicht zulässig.",
"Unbekannte Thread-ID: %lu",
-"Nicht Besitzer des Threads %lu.",
+"Threads %lu. ist einem anderen Besitzer zugeordnet.",
"Keine Tabellen in Verwendung.",
-"Zuviele Strings für Spalte %-.64s und SET.",
-"Kann keinen eindeutigen Log-Filenamen erstellen %-.64s.(1-999)\n",
-"Tabelle '%-.64s' mit Lese-Sperre versehen und kann nicht upgedated werden.",
+"Zuviele Angaben für Spalte %-.64s und SET.",
+"Kann keinen eindeutigen Dateinamen für die Logdatei ermitteln %-.64s.(1-999)\n",
+"Tabelle '%-.64s' mit Lese-Sperre versehen und kann nicht aktualisiert werden.",
"Tabelle '%-.64s' wurde nicht mittels LOCK TABLES gesperrt.",
"BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.",
"Unerlaubter Datenbankname '%-.64s'.",
"Unerlaubter Tabellenname '%-.64s'.",
-"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET OPTION SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.",
+"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET OPTION SQL_BIG_SELECTS=1 verwenden.",
"Unbekannter Fehler.",
"Unbekannte Procedure %-.64s.",
"Falsche Parameterzahl für Procedure %-.64s.",
@@ -135,51 +141,51 @@
"Funktion '%-.64s' ist nicht definiert.",
"Host blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'.",
"Host hat keine Berechtigung, eine Verbindung zu diesem MySQL Server herzustellen.",
-"Sie benutzen MySQL als anonymer User; diese User dürfen keine Passwörter ändern.",
-"Sie müssen autorisiert sein zum UPDATE von Tabellen in der mysql Datenbank, um für andere Benutzer Passwörter ändern zu können.",
-"Kann keinen passenden Datensatz in der User-Tabelle finden.",
+"Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern.",
+"Sie müssen autorisiert sein zum Aktualisieren von Tabellen in der mysql Datenbank, um für andere Benutzer Passwörter ändern zu können.",
+"Kann keinen passenden Datensatz in der Benutzer-Tabelle finden.",
"Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld",
-"Kann keinen neuen Thread erzeugen (errno %d). Sollte nicht die Speichergrenze erreicht sein, bitte im Manual nach vorhanden OS-Abhängigen Fehlern nachschauen.",
+"Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte die Speichergrenze nicht erreicht sein, bitte in der Dokumentation nach evtl. Betriebssystem abhängigen Fehlern nachlesen.",
"Spaltenzahl stimmt nicht mit der Anzahl der Werte überein in Reihe%ld",
"Kann Tabelle'%-.64s' nicht wieder öffnen",
"Unerlaubte Verwendung eines NULL-Wertes",
"Fehler '%-.64s' von regexp",
"Das Vermischen von GROUP Spalten (MIN(),MAX(),COUNT()...) mit Nicht-GROUP Spalten ist nicht erlaubt, sofern keine GROUP BY Klausel vorhanden ist.",
"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s'",
-"%-.16s Kommando abgelehnt für User: '%-.32s@%-.64s' für Tabelle '%-.64s'",
-"%-.16s Kommando abgelehnt für User: '%-.32s@%-.64s' in Spalte '%-.64s' in Tabelle '%-.64s'",
-"Unzulässiges GRANT/REVOKE Kommando. Weiteres zum Thema Berechtigungen im Manual.",
+"%-.16s Befehl nicht erlaubt für User: '%-.32s@%-.64s' für Tabelle '%-.64s'",
+"%-.16s Befehl nicht erlaubt für User: '%-.32s@%-.64s' in Spalte '%-.64s' in Tabelle '%-.64s'",
+"Unzulässiger GRANT/REVOKE Befehl. Weiteres zum Thema Berechtigungen im Manual.",
"Das Host oder User Argument für GRANT ist zu lang",
"Tabelle '%-.64s.%-.64s' existiert nicht",
"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s'",
-"Das used Kommando ist mit dieser MySQL Version nicht erlaubt",
+"Der used Befehl ist mit dieser MySQL Version nicht erlaubt",
"Fehler in der Syntax",
-"Verzögerter Einfüge-Thread konnte den angeforderten Lock für Tabelle %-.64s nicht bekommen",
+"Verzögerter Einfüge-Thread konnte den angeforderten Lock für Tabelle %-.64s nicht erhalten",
"Zu viele Delayed Threads in Verwendung",
"Abbruch der Verbindung %ld zur Datenbank: '%-.64s' User: '%-.64s' (%-.64s)",
"Empfangenes Paket ist größer als 'max_allowed_packet'",
"Lese-Fehler bei einer Kommunikations-Pipe",
"Fehler von fcntl()",
"Empfangenes Paket ist nicht in Reihenfolge",
-"Communikation-Packet läßt sich nicht entpacken",
-"Fehler beim Lesen eines Communication-Packets"
-"Timeout beim Lesen eines Communication-Packets",
-"Fehler beim Schreiben eines Communication-Packets",
-"Timeout beim Schreiben eines Communication-Packets",
-"Ergebnisstring ist länger als max_allowed_packet",
+"Kommunikationspaket läßt sich nicht entpacken",
+"Fehler beim Lesen eines Kommunikationspakets"
+"Zeitüberschreitung beim Lesen eines Kommunikationspakets.",
+"Fehler beim Schreiben eines Kommunikationspakets.",
+"Zeitüberschreitung beim Schreiben eines Kommunikationspakets.",
+"Ergebnis ist länger als max_allowed_packet",
"Der verwendete Tabellentyp unterstützt keine BLOB/TEXT Spalten",
"Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT Spalte",
"INSERT DELAYED kann nicht auf Tabelle '%-.64s' angewendet werden, da diese mit LOCK TABLES gesperrt ist",
"Falscher Spaltenname '%-.100s'",
"Der verwendete Tabellen-Handler kann die Spalte '%-.64s' nicht indizieren",
-"Alle Tabelle in der MERGE-Tabelle sind nicht gleich definiert",
+"Alle Tabellen in der MERGE-Tabelle sind nicht gleich definiert",
"Schreiben in Tabelle '%-.64s' nicht möglich wegen eines Unique Constraint",
"BLOB Spalte '%-.64s' wird in der Key-Definition ohne Längenangabe verwendet",
"Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein; Wenn NULL benötigt wird sollte ein UNIQUE Key verwendet werden",
"Ergebnis besteht aus mehr als einer Reihe",
"Dieser Tabellentyp verlangt nach einem PRIMARY KEY",
"Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert",
-"Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel",
+"Unter Verwendung des sicheren Aktualisierungsmodus wurde versucht eine Tabelle zu aktualisieren ohne eine KEY-Spalte in der WHERE-Klausel",
"Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'",
"Kann Tabelle nicht öffnen",
"Der Tabellen-Handler für diese Tabelle unterstützt kein %s",
@@ -191,53 +197,67 @@
"Verbindungsabbruch %ld zu db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
"Der Tabellenhandler für die Tabelle unterstützt kein Binary Tabellendump",
"Binlog wurde beendet wärend FLUSH MASTER",
-"Neubau des Index der gedumpten Tabelle '%-.64s' fehlgeschlagen",
+"Neuerstellung des Index der gedumpten Tabelle '%-.64s' fehlgeschlagen",
"Fehler vom Master: '%-.64s'",
"Netzfehler beim Lesen vom Master",
"Netzfehler beim Schreiben zum Master",
-"Kann keinen FULLTEXT-Index finden der der Spaltenliste entspricht",
+"Kann keinen FULLTEXT-Index finden, der der Spaltenliste entspricht",
"Kann das aktuelle Kommando wegen aktiver Tabellensperre oder aktiver Transaktion nicht ausführen",
-"Unbekannte System-Variabel '%-.64s'",
+"Unbekannte Systemvariable '%-.64s'",
"Tabelle '%-.64s' ist als defekt makiert und sollte repariert werden",
"Tabelle '%-.64s' ist als defekt makiert und der letzte (automatische) Reparaturversuch schlug fehl.",
"Warnung: Das Rollback konnte bei einigen Tabellen, die nicht mittels Transaktionen geändert wurden, nicht ausgeführt werden.",
-"Multi-Statement Transaktionen benötigen mehr als 'max_binlog_cache_size' Bytes An Speicher. Diese mysqld-Variabel vergrössern und nochmal versuchen.',
-"Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Das Kommand SLAVE STOP muss zuerst ausgeführt werden.",
-"Diese Operationbenötigt einen aktiven Slave. Slave konfigurieren und mittels SLAVE START aktivieren.",
+"Multi-Statement Transaktionen benötigen mehr als 'max_binlog_cache_size' Bytes An Speicher. Diese mysqld-Variable vergrössern und erneut versuchen.',
+"Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Das Kommand STOP SLAVE muss zuerst ausgeführt werden.",
+"Diese Operation benötigt einen aktiven Slave. Slave konfigurieren und mittels START SLAVE aktivieren.",
"Der Server ist nicht als Slave konfigiriert. Im Konfigurations-File oder mittel CHANGE MASTER TO beheben.",
"Konnte Master-Info-Struktur nicht initialisieren; Berechtigungen von master.info prüfen.",
"Konnte keinen Slave-Thread starten. System-Resourcen überprüfen.",
"Benutzer %-.64s hat mehr als 'max_user_connections' aktive Verbindungen",
-"Bei der Verwendung mit SET dürfen nur Constante Ausdrücke verwendet werden",
-"Lock wait timeout exceeded",
-"The total number of locks exceeds the lock table size",
-"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
-"DROP DATABASE not allowed while thread is holding global read lock",
-"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
-"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
-"The used table type doesn't support FULLTEXT indexes",
-"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
-"The used SELECT statements have a different number of columns",
-"Can't execute the query because you have a conflicting read lock",
-"Mixing of transactional and non-transactional tables is disabled",
-"Option '%s' used twice in statement",
-"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
-"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
-"Variable '%-.64s' doesn't have a default value",
-"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
-"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
-"This version of MySQL doesn't yet support '%s'",
-"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Bei der Verwendung mit SET dürfen nur konstante Ausdrücke verwendet werden",
+"Beim Warten auf einen LOCK wurde die zulässige Wartezeit überschritten.",
+"Die Gesamtanzahl der LOCKS überschreitet die Grösse der Locktabelle.",
+"Während einer READ UNCOMMITED Transaktion kann keine Update LOCK angefordert werden.",
+"Solange ein globaler Read LOCK gesetzt ist, ist DROP DATABASE nicht zulässig.",
+"Solange ein globaler Read LOCK gesetzt ist, ist CREATE DATABASE nicht zulässig.",
+"Falsche Argumente für %s",
+"%-.32s@%-.64s is nicht berechtigt neue Benutzer hinzuzufügen.",
+"Falsche Tabellendefinition: Sämtliche MERGE-Tabellen müssen in derselben Datenbank sein.",
+"Beim Versuch einen Lock anzufordern ist ein Deadlock aufgetreten. Es wird versucht die Transaktion erneut zu starten.",
+"Der verwendete Tabellentyp unterstützt keinen FULLTEXT-Index.",
+"Foreign_Key Beschränkung konnte nicht hinzugefügt werden."
+"Hinzufügen eines Kind-Datensatzes schlug aufgrund einer Foreign-Key Beschränkung fehl.",
+"Löschen eines Eltern-Datensatzes schlug aufgrund einer Foreign-Key Beschränkung fehl.",
+"Datensatz kann aufgrund einer Foreign-Key Beschränkung nicht gelöscht werden.",
+"Fehler bei der Verbindung zum Master: %-.128s",
+"Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %-.128s.",
+"Fehler beim Ausführen des Befehls %s: %-.128s.",
+"Falsche Verwendung von %s und %s.",
+"Die verwendeten SELECTs liefern eine unterschiedliche Anzahl von Spalten zurück.",
+"Augrund eines READ LOCK Konflikts kann die Abfrage nicht ausgeführt werden.",
+"Die Verwendung von transaktions- und nicht transaktionsaktionsunterstützenden Tabellen ist deaktiviert.",
+"Option '%s' wird im Befehl zweimal verwendet.",
+"Benutzer '%-.64s' hat Limit '%s' überschritten. (Momentaner Wert: %ld)",
+"Befehl nicht zulässig. Hierfür wird die Berechtigung %-.128s benötigt.",
+"Variable '%-.64s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden.",
+"Variable '%-.64s' ist eine globale Variable und muss mit SET GLOBAL verändert werden.",
+"Variable '%-.64s' besitzt keinen vorgegebenen Wert.",
+"Der Variablen '%-.64s' kann nicht der Wert '%-.64s' zugewiesen werden.",
+"Falscher Typ für Variable '%-.64s'",
+"Variable '%-.64s' kann nur verändert, nicht aber gelesen werden.",
+"Falsche Verwendung oder Platzierung von '%s'",
+"Diese MySQL-Version unterstützt momentan nicht '%s'.",
+"Schwerer Fehler %d: '%-.128s vom Master beim Lesen des Binary Logs.",
+"Falsche Foreign-Key Definition für '%-64s': %s",
+"Schlüssel- und Tabellenreferenz passen nicht zueinander.",
+"Kardinalitäts-Fehler (mehr/oder weniger als %d Spalten).",
+"Unterabfrage lieferte mehr als einen Datensatz zurück.",
+"Unbekannter prepared statement handler (%ld) für %s angegeben.",
+"Die Hilfedatenbank ist beschädigt oder existiert nicht.",
+"Zyklische Referenz in den Unterabfragen.",
+"Spalte '%s' wird von %s nach %s umgewandelt",
+"Referenz '%-.64s' wird nicht unterstützt (%s)",
+"Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden.",
+"Select %u wurde während der Optimierung reduziert.",
+"Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde kann nicht in %-.32s verwendet werden."
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 554176e340b..8831d4e47b9 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -94,7 +94,7 @@
"Äåí åßíáé äõíáôÞ ç äéáãñáöÞ üëùí ôùí ðåäßùí ìå ALTER TABLE. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå DROP TABLE",
"Áäýíáôç ç äéáãñáöÞ (DROP) '%-.64s'. Ðáñáêáëþ åëÝãîôå áí ôï ðåäßï/êëåéäß õðÜñ÷åé",
"ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld ÐñïåéäïðïéÞóåéò: %ld",
-"INSERT TABLE '%-.64s' äåí åðéôñÝðåôáé óôï FROM table list",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Áãíùóôï thread id: %lu",
"Äåí åßóèå owner ôïõ thread %lu",
"Äåí ÷ñçóéìïðïéÞèçêáí ðßíáêåò",
@@ -197,10 +197,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -238,3 +238,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 32333ce4439..8d6c321d316 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -96,7 +96,7 @@
"Az osszes mezo nem torolheto az ALTER TABLE-lel. Hasznalja a DROP TABLE-t helyette",
"A DROP '%-.64s' nem lehetseges. Ellenorizze, hogy a mezo/kulcs letezik-e",
"Rekordok: %ld Duplikalva: %ld Warnings: %ld",
-"INSERT TABLE '%-.64s' nem engedelyezett a FROM table listabol",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Ervenytelen szal (thread) id: %lu",
"A %lu thread-nek mas a tulajdonosa",
"Nincs hasznalt tabla",
@@ -199,10 +199,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -240,3 +240,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index cc26818aa41..451ad3e058b 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -94,7 +94,7 @@
"Non si possono cancellare tutti i campi con una ALTER TABLE. Utilizzare DROP TABLE",
"Impossibile cancellare '%-.64s'. Controllare che il campo chiave esista",
"Records: %ld Duplicati: %ld Avvertimenti: %ld",
-"INSERT TABLE '%-.64s' non e` permesso nella FROM table list",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Thread id: %lu sconosciuto",
"Utente non proprietario del thread %lu",
"Nessuna tabella usata",
@@ -199,8 +199,8 @@
"La tabella '%-.64s' e` segnalata come corrotta e l'ultima ricostruzione (automatica?) e` fallita",
"Attenzione: Alcune delle modifiche alle tabelle non transazionali non possono essere ripristinate (roll back impossibile)",
"La transazione a comandi multipli (multi-statement) ha richiesto piu` di 'max_binlog_cache_size' bytes di disco: aumentare questa variabile di mysqld e riprovare',
-"Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima SLAVE STOP",
-"Questa operaione richiede un database 'slave', configurarlo ed eseguire SLAVE START",
+"Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima STOP SLAVE",
+"Questa operaione richiede un database 'slave', configurarlo ed eseguire START SLAVE",
"Il server non e' configurato come 'slave', correggere il file di configurazione cambiando CHANGE MASTER TO",
"Impossibile inizializzare la struttura 'master info', controllare i permessi sul file master.info",
"Impossibile creare il thread 'slave', controllare le risorse di sistema",
@@ -238,3 +238,16 @@
"Uso/posizione di '%s' sbagliato",
"Questa versione di MySQL non supporta ancora '%s'",
"Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 663676e0cf3..70ab2d6d42d 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -96,7 +96,7 @@
"ALTER TABLE ¤ÇÁ´¤Æ¤Î column ¤Ïºï½ü¤Ç¤­¤Þ¤»¤ó. DROP TABLE ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤",
"'%-.64s' ¤òÇË´þ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿. Check that column/key exists",
"¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£¿ô: %ld Warnings: %ld",
-"INSERT TABLE '%-.64s' isn't allowed in FROM table list",
+"You can't specify target table '%-.64s' for update in FROM clause",
"thread id: %lu ¤Ï¤¢¤ê¤Þ¤»¤ó",
"thread %lu ¤Î¥ª¡¼¥Ê¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó",
"No tables used",
@@ -199,10 +199,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -240,3 +240,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index da1ee97f6b6..c18c3ed3873 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -94,7 +94,7 @@
"ALTER TABLE ¸í·ÉÀ¸·Î´Â ¸ðµç Ä®·³À» Áö¿ï ¼ö ¾ø½À´Ï´Ù. DROP TABLE ¸í·ÉÀ» ÀÌ¿ëÇϼ¼¿ä.",
"'%-.64s'¸¦ DROPÇÒ ¼ö ¾ø½À´Ï´Ù. Ä®·³À̳ª Å°°¡ Á¸ÀçÇÏ´ÂÁö äũÇϼ¼¿ä.",
"·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³ °æ°í: %ld°³",
-"INSERT TABLE '%-.64s' ´Â FROM Å×À̺í list¿¡¼­ Çã°¡µÇÁö ¾Ê¾Ò½À´Ï´Ù.",
+"You can't specify target table '%-.64s' for update in FROM clause",
"¾Ë¼ö ¾ø´Â ¾²·¹µå id: %lu",
"¾²·¹µå(Thread) %luÀÇ ¼ÒÀ¯ÀÚ°¡ ¾Æ´Õ´Ï´Ù.",
"¾î¶² Å×ÀÌºíµµ »ç¿ëµÇÁö ¾Ê¾Ò½À´Ï´Ù.",
@@ -197,10 +197,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -238,3 +238,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index bc334ace9f1..9cd99613f52 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -96,7 +96,7 @@
"Ein kan ikkje slette alle felt med ALTER TABLE. Bruk DROP TABLE istadenfor.",
"Kan ikkje DROP '%-.64s'. Undersøk om felt/nøkkel eksisterar.",
"Postar: %ld Like: %ld Åtvaringar: %ld",
-"INSERT TABLE '%-.64s' er ikkje tillate i FROM tabell liste",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Ukjent tråd id: %lu",
"Du er ikkje eigar av tråd %lu",
"Ingen tabellar i bruk",
@@ -199,10 +199,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -240,3 +240,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index e7f54549462..32fe6c30b34 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -96,7 +96,7 @@
"En kan ikke slette alle felt med ALTER TABLE. Bruk DROP TABLE isteden.",
"Kan ikke DROP '%-.64s'. Undersøk om felt/nøkkel eksisterer.",
"Poster: %ld Like: %ld Advarsler: %ld",
-"INSERT TABLE '%-.64s' er ikke tillatt i FROM tabell liste",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Ukjent tråd id: %lu",
"Du er ikke eier av tråden %lu",
"Ingen tabeller i bruk",
@@ -199,10 +199,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -240,3 +240,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 0e92bf2f9b8..4b59a62f991 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -98,7 +98,7 @@
"Nie mo¿na usun?æ wszystkich pól wykorzystuj?c ALTER TABLE. W zamian u¿yj DROP TABLE",
"Nie mo¿na wykonaæ operacji DROP '%-.64s'. Sprawd¥, czy to pole/klucz istnieje",
"Rekordów: %ld Duplikatów: %ld Ostrze¿eñ: %ld",
-"Operacja INSERT TABLE '%-.64s' nie jest dozwolona w li?cie tabel w FROM",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Nieznany identyfikator w?tku: %lu",
"Nie jeste? w³a?cicielem w?tku %lu",
"Nie ma ¿adej u¿ytej tabeli",
@@ -201,10 +201,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -242,3 +242,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 6f4f86f9024..7236bd86652 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -94,7 +94,7 @@
"Você não pode deletar todas as colunas com ALTER TABLE. Use DROP TABLE em seu lugar",
"Não se pode fazer DROP '%-.64s'. Confira se esta coluna/chave existe",
"Registros: %ld - Duplicados: %ld - Avisos: %ld",
-"INSERT TABLE '%-.64s' não é permitido na lista de tabelas contidas em FROM",
+"You can't specify target table '%-.64s' for update in FROM clause",
"'Id' de 'thread' %lu desconhecido",
"Você não é proprietário da 'thread' %lu",
"Nenhuma tabela usada",
@@ -199,8 +199,8 @@
"Tabela '%-.64s' está marcada como danificada e a última reparação (automática?) falhou",
"Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas (rolled back)",
"Transações multi-declaradas (multi-statement transactions) requeriram mais do que o valor limite (max_binlog_cache_size) de bytes para armazenagem. Aumente o valor desta variável do mysqld e tente novamente",
-"Esta operação não pode ser realizada com um 'slave' em execução. Execute SLAVE STOP primeiro",
-"Esta operação requer um 'slave' em execução. Configure o 'slave' e execute SLAVE START",
+"Esta operação não pode ser realizada com um 'slave' em execução. Execute STOP SLAVE primeiro",
+"Esta operação requer um 'slave' em execução. Configure o 'slave' e execute START SLAVE",
"O servidor não está configurado como 'slave'. Acerte o arquivo de configuração ou use CHANGE MASTER TO",
"Não pode inicializar a estrutura de informação do 'master'. Verifique as permissões em 'master.info'",
"Não conseguiu criar 'thread' de 'slave'. Verifique os recursos do sistema",
@@ -238,3 +238,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index b888a2bc8cd..0b8bbe1c219 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -98,7 +98,7 @@
"Nu poti sterge toate coloanele cu ALTER TABLE. Foloseste DROP TABLE in schimb",
"Nu pot sa DROP '%-.64s'. Verifica daca coloana/cheia exista",
"Recorduri: %ld Duplicate: %ld Atentionari (warnings): %ld",
-"INSERT TABLE '%-.64s' nu este permis in lista FROM de tabele",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Id-ul: %lu thread-ului este necunoscut",
"Nu sinteti proprietarul threadului %lu",
"Nici o tabela folosita",
@@ -201,10 +201,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -242,3 +242,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 0329f760e38..2f1eedd207c 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -97,7 +97,7 @@
"îÅÌØÚÑ ÕÄÁÌÉÔØ ×ÓÅ ÐÏÌÑ ÞÅÒÅÚ ALTER TABLE. ÷ÏÓÐÏÌØÚÕÊÔÅÓØ DROP TABLE",
"îÅ ÍÏÇÕ ÓÂÒÏÓÉÔØ '%-.64s'. ðÒÏ×ÅÒØÔÅ, ÞÔÏ ÜÔÏ ÐÏÌÅ/ËÌÀÞ ÓÕÝÅÓÔ×ÕÀÔ",
"úÁÐÉÓÅÊ: %ld äÕÂÌÅÊ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld",
-"INSERT TABLE '%-.64s' ÎÅ ÒÁÚÒÅÛÅÎÏ × ÓÐÉÓËÅ FROM TABLE",
+"÷Ù ÎÅ ÍÏÖÅÔÅ ÕËÁÚÁÔØ ÉÚÍÅÎÅÑÍÕÀ ÔÁÂÌÉÃÕ '%-.64s' × ÓÐÉÓËÅ ÔÁÂÌÉÃ FROM",
"îÅÉÚ×ÅÓÔÎÁÑ ÎÉÔØ: %lu",
"÷Ù ÎÅ ×ÌÁÄÅÌÅà ÎÉÔÉ %lu",
"ôÁÂÌÉÃÙ ÎÅ ÉÓÐÏÌØÚÏ×ÁÎÙ",
@@ -202,8 +202,8 @@
"ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÐÏÓÌÅÄÎÑÑ ÐÏÐÙÔËÁ ÉÓÐÒÁ×ÌÅÎÉÑ (Á×ÔÏÍÁÔÉÞÅÓËÁÑ?) ÎÅ ÕÄÁÌÁÓØ",
"ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÎÅËÏÔÏÒÙÅ ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÅ ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÞÉÎÑÀÔÓÑ ROLLBACK",
"íÎÏÇÏÚÁÐÒÏÓÎÁÑ ÔÒÁÎÚÁËÃÉÑ ÔÒÅÂÕÅÔ Õ×ÅÌÉÞÅÎÉÑ 'max_binlog_cache_size' - Õ×ÅÌÉÞÔÅ ÜÔÕ ÐÅÒÅÍÅÎÎÕÀ É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ",
-"üÔÁ ÏÐÅÒÁÃÉÑ ÎÅ×ÏÚÍÏÖÎÁ Ó ÁËÔÉ×ÎÙÍ slave, ÎÁÄÏ SLAVE STOP",
-"üÔÁ ÏÐÅÒÁÃÉÑ ÎÅ×ÏÚÍÏÖÎÁ Ó ÐÁÓÓÉ×ÎÙÍ slave, ÎÁÄÏ SLAVE START",
+"üÔÁ ÏÐÅÒÁÃÉÑ ÎÅ×ÏÚÍÏÖÎÁ Ó ÁËÔÉ×ÎÙÍ slave, ÎÁÄÏ STOP SLAVE",
+"üÔÁ ÏÐÅÒÁÃÉÑ ÎÅ×ÏÚÍÏÖÎÁ Ó ÐÁÓÓÉ×ÎÙÍ slave, ÎÁÄÏ START SLAVE",
"üÔÏÔ ÓÅÒ×ÅÒ ÎÅ slave, ÉÓÐÒÁ×ØÔÅ × ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÍ ÆÁÊÌÅ ÉÌÉ ËÏÍÍÁÎÄÏÊ CHANGE MASTER TO",
"îÅ ÐÏÌÕÞÉÌÏÓØ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ÓÔÒÕËÔÕÒÕ master info, ÐÒÏ×ÅÒÔÅ persmissions ÎÁ ÆÁÊÌÅ master.info",
"îÅ ÍÏÇÕ ÓÏÚÄÁÔØ ÐÒÏÃÅÓÓ SLAVE, ÐÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ",
@@ -241,3 +241,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"ïÛÉÂËÁ ÍÏÝØÎÏÓÔÉ ÍÎÏÖÅÓÔ×Á (ÂÏÌØÛÅ/ÍÅÎØÛÅ %d ËÏÌÏÎÏË)",
+"ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÊ ÚÁÐÉÓÉ",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"ãÉËÌÉÞÅÓËÁÑ ÓÓÙÌËÁ ÎÁ ÐÏÄÚÁÐÒÏÓ",
+"ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÐÏÌÑ '%s' ÉÚ %s × %s",
+"óÓÙÌËÁ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ (%s)",
+"Every derived table must have it's own alias"
+"Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
new file mode 100644
index 00000000000..75cfd73f3f0
--- /dev/null
+++ b/sql/share/serbian/errmsg.txt
@@ -0,0 +1,249 @@
+/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
+ This file is public domain and comes with NO WARRANTY of any kind */
+
+/* Serbian Translation, version 1.0:
+ Copyright 2002 Vladimir Kraljevic, vladimir_kraljevic@yahoo.com
+ This file is public domain and comes with NO WARRANTY of any kind.
+ Charset: cp1250
+*/
+
+"hashchk",
+"isamchk",
+"NE",
+"DA",
+"Ne mogu da kreiram file '%-.64s' (errno: %d)",
+"Ne mogu da kreiram tabelu '%-.64s' (errno: %d)",
+"Ne mogu da kreiram bazu '%-.64s'. (errno: %d)",
+"Ne mogu da kreiram bazu '%-.64s'. Baza veæ postoji.",
+"Ne mogu da izbrišem bazu '%-.64s'. Baza ne postoji.",
+"Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.64s', errno: %d)",
+"Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.64s', errno: %d)",
+"Greška pri brisanju '%-.64s' (errno: %d)",
+"Ne mogu da proèitam slog iz sistemske tabele",
+"Ne mogu da dobijem stanje file-a '%-.64s' (errno: %d)",
+"Ne mogu da dobijem trenutni direktorijum (errno: %d)",
+"Ne mogu da zakljuèam file (errno: %d)",
+"Ne mogu da otvorim file: '%-.64s'. (errno: %d)",
+"Ne mogu da pronaðem file: '%-.64s' (errno: %d)",
+"Ne mogu da proèitam direktorijum '%-.64s' (errno: %d)",
+"Ne mogu da promenim direktorijum na '%-.64s' (errno: %d)",
+"Slog je promenjen od zadnjeg èitanja tabele '%-.64s'",
+"Disk je pun (%s). Èekam nekoga da doðe i oslobodi nešto mesta....",
+"Ne mogu da pišem pošto postoji duplirani kljuè u tabeli '%-.64s'",
+"Greška pri zatvaranju '%-.64s' (errno: %d)",
+"Greška pri èitanju file-a '%-.64s' (errno: %d)",
+"Greška pri promeni imena '%-.64s' na '%-.64s' (errno: %d)",
+"Greška pri upisu '%-.64s' (errno: %d)",
+"'%-.64s' je zakljuèan za upis",
+"Sortiranje je prekinuto",
+"View '%-.64s' ne postoji za '%-.64s'",
+"Handler tabela je vratio grešku %d",
+"Handler tabela za '%-.64s' nema ovu opciju",
+"Ne mogu da pronaðem slog u '%-.64s'",
+"Pogrešna informacija u file-u: '%-.64s'",
+"Pogrešan key file za tabelu: '%-.64s'. Probajte da ga ispravite",
+"Zastareo key file za tabelu '%-.64s'; Ispravite ga",
+"Tabelu '%-.64s' je dozvoljeno samo èitati",
+"Nema memorije. Restartujte MySQL server i probajte ponovo (potrebno je %d byte-ova)",
+"Nema memorije za sortiranje. Poveæajte velièinu sort buffer-a MySQL server-u",
+"Neoèekivani kraj pri èitanju file-a '%-.64s' (errno: %d)",
+"Previše konekcija",
+"Nema memorije; Proverite da li MySQL server ili neki drugi proces koristi svu slobodnu memoriju. (UNIX: Ako ne, probajte da upotrebite 'ulimit' komandu da biste dozvolili daemon-u da koristi više memorije ili probajte da dodate više swap memorije)",
+"Ne mogu da dobijem ime host-a za vašu IP adresu",
+"Loš poèetak komunikacije (handshake)",
+"Pristup je zabranjen korisniku '%-.32s@%-.64s' za bazu '%-.64s'",
+"Pristup je zabranjen korisniku '%-.32s@%-.64s' (koristi lozinku: '%s')",
+"Ni jedna baza nije selektovana",
+"Nepoznata komanda",
+"Kolona '%-.64s' ne može biti NULL",
+"Nepoznata baza '%-.64s'",
+"Tabela '%-.64s' veæ postoji",
+"Nepoznata tabela '%-.64s'",
+"Kolona '%-.64s' u %-.64s nije jedinstvena u kontekstu",
+"Gašenje servera je u toku",
+"Nepoznata kolona '%-.64s' u '%-.64s'",
+"Entitet '%-.64s' nije naveden u komandi 'GROUP BY'",
+"Ne mogu da grupišem po '%-.64s'",
+"Izraz ima 'SUM' agregatnu funkciju i kolone u isto vreme",
+"Broj kolona ne odgovara broju vrednosti",
+"Ime '%-.100s' je predugaèko",
+"Duplirano ime kolone '%-.64s'",
+"Duplirano ime kljuèa '%-.64s'",
+"Dupliran unos '%-.64s' za kljuè '%d'",
+"Pogrešan naziv kolone za kolonu '%-.64s'",
+"'%s' u iskazu '%-.80s' na liniji %d",
+"Upit je bio prazan",
+"Tabela ili alias nisu bili jedinstveni: '%-.64s'",
+"Loša default vrednost za '%-.64s'",
+"Definisani višestruki primarni kljuèevi",
+"Navedeno je previše kljuèeva. Maksimum %d kljuèeva je dozvoljeno",
+"Navedeno je previše delova kljuèa. Maksimum %d delova je dozvoljeno",
+"Navedeni kljuè je predug. Maksimalna dužina kljuèa je %d",
+"Kljuèna kolona '%-.64s' ne postoji u tabeli",
+"BLOB kolona '%-.64s' ne može biti upotrebljena za navoðenje kljuèa sa tipom tabele koji se trenutno koristi",
+"Previše podataka za kolonu '%-.64s' (maksimum je %d). Upotrebite BLOB polje",
+"Pogrešna definicija tabele; U tabeli može postojati samo jedna 'AUTO' kolona i ona mora biti istovremeno definisana kao kolona kljuèa",
+"%s: Spreman za konekcije\n",
+"%s: Normalno gašenje\n",
+"%s: Dobio signal %d. Prekidam!\n",
+"%s: Gašenje završeno\n",
+"%s: Usiljeno gašenje thread-a %ld koji pripada korisniku: '%-.32s'\n",
+"Ne mogu da kreiram IP socket",
+"Tabela '%-.64s' nema isti indeks kao onaj upotrebljen pri komandi 'CREATE INDEX'. Napravite tabelu ponovo",
+"Argument separatora polja nije ono što se oèekivalo. Proverite uputstvo MySQL server-a",
+"Ne možete koristiti fiksnu velièinu sloga kada imate BLOB polja. Molim koristite 'fields terminated by' opciju.",
+"File '%-.64s' mora biti u direktorijumu gde su file-ovi baze i mora imati odgovarajuæa prava pristupa",
+"File '%-.80s' veæ postoji",
+"Slogova: %ld Izbrisano: %ld Preskoèeno: %ld Upozorenja: %ld",
+"Slogova: %ld Duplikata: %ld",
+"Pogrešan pod-kljuè dela kljuèa. Upotrebljeni deo kljuèa nije string, upotrebljena dužina je veæa od dela kljuèa ili handler tabela ne podržava jedinstvene pod-kljuèeve",
+"Ne možete da izbrišete sve kolone pomoæu komande 'ALTER TABLE'. Upotrebite komandu 'DROP TABLE' ako želite to da uradite",
+"Ne mogu da izvršim komandu drop 'DROP' na '%-.64s'. Proverite da li ta kolona (odnosno kljuè) postoji",
+"Slogova: %ld Duplikata: %ld Upozorenja: %ld",
+"You can't specify target table '%-.64s' for update in FROM clause",
+"Nepoznat thread identifikator: %lu",
+"Vi niste vlasnik thread-a %lu",
+"Nema upotrebljenih tabela",
+"Previše string-ova za kolonu '%-.64s' i komandu 'SET'",
+"Ne mogu da generišem jedinstveno ime log-file-a: '%-.64s.(1-999)'\n",
+"Tabela '%-.64s' je zakljuèana READ lock-om; iz nje se može samo èitati ali u nju se ne može pisati",
+"Tabela '%-.64s' nije bila zakljuèana komandom 'LOCK TABLES'",
+"BLOB kolona '%-.64s' ne može imati default vrednost",
+"Pogrešno ime baze '%-.100s'",
+"Pogrešno ime tabele '%-.100s'",
+"Komanda 'SELECT' æe ispitati previše slogova i potrošiti previše vremena. Proverite vaš 'WHERE' filter i upotrebite 'SET OPTION SQL_BIG_SELECTS=1' ako želite baš ovakvu komandu",
+"Nepoznata greška",
+"Nepoznata procedura '%-.64s'",
+"Pogrešan broj parametara za proceduru '%-.64s'",
+"Pogrešni parametri prosleðeni proceduri '%-.64s'",
+"Nepoznata tabela '%-.64s' u '%-.32s'",
+"Kolona '%-.64s' je navedena dva puta",
+"Pogrešna upotreba 'GROUP' funkcije",
+"Tabela '%-.64s' koristi ekstenziju koje ne postoji u ovoj verziji MySQL-a",
+"Tabela mora imati najmanje jednu kolonu",
+"Tabela '%-.64s' je popunjena do kraja",
+"Nepoznati karakter-set: '%-.64s'",
+"Previše tabela. MySQL može upotrebiti maksimum %d tabela pri 'JOIN' operaciji",
+"Previše kolona",
+"Prevelik slog. Maksimalna velièina sloga, ne raèunajuæi BLOB polja, je %d. Trebali bi da promenite tip nekih polja u BLOB",
+"Prepisivanje thread stack-a: Upotrebljeno: %ld od %ld stack memorije. Upotrebite 'mysqld -O thread_stack=#' da navedete veæi stack ako je potrebno",
+"Unakrsna zavisnost pronaðena u komandi 'OUTER JOIN'. Istražite vaše 'ON' uslove",
+"Kolona '%-.64s' je upotrebljena kao 'UNIQUE' ili 'INDEX' ali nije definisana kao 'NOT NULL'",
+"Ne mogu da uèitam funkciju '%-.64s'",
+"Ne mogu da inicijalizujem funkciju '%-.64s'; %-.80s",
+"Ne postoje dozvoljene putanje do share-ovane biblioteke",
+"Funkcija '%-.64s' veæ postoji",
+"Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %-.64s)",
+"Ne mogu da pronadjem funkciju '%-.64s' u biblioteci",
+"Funkcija '%-.64s' nije definisana",
+"Host '%-.64s' je blokiran zbog previše grešaka u konekciji. Možete ga odblokirati pomoæu komande 'mysqladmin flush-hosts'",
+"Host-u '%-.64s' nije dozvoljeno da se konektuje na ovaj MySQL server",
+"Vi koristite MySQL kao anonimni korisnik a anonimnim korisnicima nije dozvoljeno da menjaju lozinke",
+"Morate imati privilegije da možete da update-ujete odreðene tabele ako želite da menjate lozinke za druge korisnike",
+"Ne mogu da pronaðem odgovarajuæi slog u 'user' tabeli",
+"Odgovarajuæih slogova: %ld Promenjeno: %ld Upozorenja: %ld",
+"Ne mogu da kreiram novi thread (errno %d). Ako imate još slobodne memorije, trebali biste da pogledate u priruèniku da li je ovo specifièna greška vašeg operativnog sistema",
+"Broj kolona ne odgovara broju vrednosti u slogu %ld",
+"Ne mogu da ponovo otvorim tabelu '%-.64s'",
+"Pogrešna upotreba vrednosti NULL",
+"Funkcija regexp je vratila grešku '%-.64s'",
+"Upotreba agregatnih funkcija (MIN(),MAX(),COUNT()...) bez 'GROUP' kolona je pogrešna ako ne postoji 'GROUP BY' iskaz",
+"Ne postoji odobrenje za pristup korisniku '%-.32s' na host-u '%-.64s'",
+"%-.16s komanda zabranjena za korisnika '%-.32s@%-.64s' za tabelu '%-.64s'",
+"%-.16s komanda zabranjena za korisnika '%-.32s@%-.64s' za kolonu '%-.64s' iz tabele '%-.64s'",
+"Pogrešna 'GRANT' odnosno 'REVOKE' komanda. Molim Vas pogledajte u priruèniku koje vrednosti mogu biti upotrebljene.",
+"Argument 'host' ili 'korisnik' prosleðen komandi 'GRANT' je predugaèak",
+"Tabela '%-.64s.%-.64s' ne postoji",
+"Ne postoji odobrenje za pristup korisniku '%-.32s' na host-u '%-.64s' tabeli '%-.64s'",
+"Upotrebljena komanda nije dozvoljena sa ovom verzijom MySQL servera",
+"Imate grešku u vašoj SQL sintaksi",
+"Prolongirani 'INSERT' thread nije mogao da dobije traženo zakljuèavanje tabele '%-.64s'",
+"Previše prolongiranih thread-ova je u upotrebi",
+"Prekinuta konekcija broj %ld ka bazi: '%-.64s' korisnik je bio: '%-.32s' (%-.64s)",
+"Primio sam mrežni paket veæi od definisane vrednosti 'max_allowed_packet'",
+"Greška pri èitanju podataka sa pipe-a",
+"Greška pri izvršavanju funkcije fcntl()",
+"Primio sam mrežne pakete van reda",
+"Ne mogu da dekompresujem mrežne pakete",
+"Greška pri primanju mrežnih paketa",
+"Vremenski limit za èitanje mrežnih paketa je istekao",
+"Greška pri slanju mrežnih paketa",
+"Vremenski limit za slanje mrežnih paketa je istekao",
+"Rezultujuèi string je duži nego što to dozvoljava parametar servera 'max_allowed_packet'",
+"Iskorišteni tip tabele ne podržava kolone tipa 'BLOB' odnosno 'TEXT'",
+"Iskorišteni tip tabele ne podržava kolone tipa 'AUTO_INCREMENT'",
+"Komanda 'INSERT DELAYED' ne može biti iskorištena u tabeli '%-.64s', zbog toga što je zakljuèana komandom 'LOCK TABLES'",
+"Pogrešno ime kolone '%-.100s'",
+"Handler tabele ne može da indeksira kolonu '%-.64s'",
+"Tabele iskorištene u 'MERGE' tabeli nisu definisane na isti naèin",
+"Zbog provere jedinstvenosti ne mogu da upišem podatke u tabelu '%-.64s'",
+"BLOB kolona '%-.64s' je upotrebljena u specifikaciji kljuèa bez navoðenja dužine kljuèa",
+"Svi delovi primarnog kljuèa moraju biti razlièiti od NULL; Ako Vam ipak treba NULL vrednost u kljuèu, upotrebite 'UNIQUE'",
+"Rezultat je saèinjen od više slogova",
+"Ovaj tip tabele zahteva da imate definisan primarni kljuè",
+"Ova verzija MySQL servera nije kompajlirana sa podrškom za RAID ureðaje",
+"Vi koristite safe update mod servera, a probali ste da promenite podatke bez 'WHERE' komande koja koristi kolonu kljuèa",
+"Kljuè '%-.64s' ne postoji u tabeli '%-.64s'",
+"Ne mogu da otvorim tabelu",
+"Handler za ovu tabelu ne dozvoljava 'check' odnosno 'repair' komande",
+"Nije Vam dozvoljeno da izvršite ovu komandu u transakciji",
+"Greška %d za vreme izvršavanja komande 'COMMIT'",
+"Greška %d za vreme izvršavanja komande 'ROLLBACK'",
+"Greška %d za vreme izvršavanja komande 'FLUSH_LOGS'",
+"Greška %d za vreme izvršavanja komande 'CHECKPOINT'",
+"Prekinuta konekcija broj %ld ka bazi: '%-.64s' korisnik je bio: '%-.32s' a host: `%-.64s' (%-.64s)",
+"Handler tabele ne podržava binarni dump tabele",
+"Binarni log file zatvoren, ne mogu da izvršim komandu 'RESET MASTER'",
+"Izgradnja indeksa dump-ovane tabele '%-.64s' nije uspela",
+"Greška iz glavnog servera '%-.64s' u klasteru",
+"Greška u primanju mrežnih paketa sa glavnog servera u klasteru",
+"Greška u slanju mrežnih paketa na glavni server u klasteru",
+"Ne mogu da pronaðem 'FULLTEXT' indeks koli odgovara listi kolona",
+"Ne mogu da izvršim datu komandu zbog toga što su tabele zakljuèane ili je transakcija u toku",
+"Nepoznata sistemska promenljiva '%-.64'",
+"Tabela '%-.64s' je markirana kao ošteæena i trebala bi biti popravljena",
+"Tabela '%-.64s' je markirana kao ošteæena, a zadnja (automatska?) popravka je bila neuspela",
+"Upozorenje: Neke izmenjene tabele ne podržavaju komandu 'ROLLBACK'",
+"Transakcija sa više stavki zahtevala je više od 'max_binlog_cache_size' bajtova skladišnog prostora. Uveæajte ovu promenljivu servera i pokušajte ponovo',
+"Ova operacija ne može biti izvršena dok je aktivan podreðeni server. Zadajte prvo komandu 'STOP SLAVE' da zaustavite podreðeni server.",
+"Ova operacija zahteva da je aktivan podreðeni server. Konfigurišite prvo podreðeni server i onda izvršite komandu 'START SLAVE'",
+"Server nije konfigurisan kao podreðeni server, ispravite konfiguracioni file ili na njemu izvršite komandu 'CHANGE MASTER TO'",
+"Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info'",
+"Nisam mogao da startujem thread za podreðeni server, proverite sistemske resurse",
+"Korisnik %-.64s veæ ima više aktivnih konekcija nego što je to odreðeno 'max_user_connections' promenljivom",
+"Možete upotrebiti samo konstantan iskaz sa komandom 'SET'",
+"Vremenski limit za zakljuèavanje tabele je istekao; Probajte da ponovo startujete transakciju",
+"Broj totalnih zakljuèavanja tabele premašuje velièinu tabele zakljuèavanja",
+"Zakljuèavanja izmena ne mogu biti realizovana sve dok traje 'READ UNCOMMITTED' transakcija",
+"Komanda 'DROP DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka",
+"Komanda 'CREATE DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka",
+"Pogrešni argumenti prosleðeni na %s",
+"Korisniku %-.32s@%-.64s nije dozvoljeno da kreira nove korisnike",
+"Pogrešna definicija tabele; Sve 'MERGE' tabele moraju biti u istoj bazi podataka",
+"Unakrsno zakljuèavanje pronaðeno kada sam pokušao da dobijem pravo na zakljuèavanje; Probajte da restartujete transakciju",
+"Upotrebljeni tip tabele ne podržava 'FULLTEXT' indekse",
+"Ne mogu da dodam proveru spoljnog kljuèa",
+"Ne mogu da dodam slog: provera spoljnog kljuèa je neuspela",
+"Ne mogu da izbrišem roditeljski slog: provera spoljnog kljuèa je neuspela",
+"Greška pri povezivanju sa glavnim serverom u klasteru: %-.128s",
+"Greška pri izvršavanju upita na glavnom serveru u klasteru: %-.128s",
+"Greška pri izvršavanju komande %s: %-.128s",
+"Pogrešna upotreba %s i %s",
+"Upotrebljene 'SELECT' komande adresiraju razlièit broj kolona",
+"Ne mogu da izvršim upit zbog toga što imate zakljuèavanja èitanja podataka u konfliktu",
+"Mešanje tabela koje podržavaju transakcije i onih koje ne podržavaju transakcije je iskljuèeno",
+"Opcija '%s' je upotrebljena dva puta u istom iskazu",
+"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 1dd696affb0..de354f234c7 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -102,7 +102,7 @@
"One nemô¾em zmaza» all fields with ALTER TABLE. Use DROP TABLE instead",
"Nemô¾em zru¹i» (DROP) '%-.64s'. Skontrolujte, èi neexistujú záznamy/kµúèe",
"Záznamov: %ld Opakovaných: %ld Varovania: %ld",
-"INSERT TABLE '%-.64s' nie je dovolené v zozname tabuliek FROM",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Neznáma identifikácia vlákna: %lu",
"Nie ste vlastníkom vlákna %lu",
"Nie je pou¾itá ¾iadna tabuµka",
@@ -205,10 +205,10 @@
"Unknown system variable '%-.64s'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
+"Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
-"This operation cannot be performed with a running slave, run SLAVE STOP first",
-"This operation requires a running slave, configure slave and do SLAVE START",
+"This operation cannot be performed with a running slave, run STOP SLAVE first",
+"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
@@ -246,3 +246,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index c91726a6557..a528c3e6b36 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -95,7 +95,7 @@
"No puede borrar todos los campos con ALTER TABLE. Usa DROP TABLE para hacerlo",
"No puedo ELIMINAR '%-.64s'. compuebe que el campo/clave existe",
"Registros: %ld Duplicados: %ld Peligros: %ld",
-"INSERT TABLE '%-.64s' no esta permitido en FROM tabla lista",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Identificador del thread: %lu desconocido",
"Tu no eres el propietario del thread%lu",
"No ha tablas usadas",
@@ -200,8 +200,8 @@
"Tabla '%-.64s' está marcada como crashed y la última reparación (automactica?) falló",
"Aviso: Algunas tablas no transancionales no pueden tener rolled back",
"Multipla transición necesita mas que 'max_binlog_cache_size' bytes de almacenamiento. Aumente esta variable mysqld y tente de nuevo',
-"Esta operación no puede ser hecha con el esclavo funcionando, primero use SLAVE STOP",
-"Esta operación necesita el esclavo funcionando, configure esclavo y haga el SLAVE START",
+"Esta operación no puede ser hecha con el esclavo funcionando, primero use STOP SLAVE",
+"Esta operación necesita el esclavo funcionando, configure esclavo y haga el START SLAVE",
"El servidor no está configurado como esclavo, edite el archivo config file o con CHANGE MASTER TO",
"No puedo inicializar la estructura info del master, verifique permisiones en el master.info",
"No puedo crear el thread esclavo, verifique recursos del sistema",
@@ -239,3 +239,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (more/less than %d columns)",
+"Subselect returns more than 1 record",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 5b7ed499038..5473f4e8e42 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -94,7 +94,7 @@
"Man kan inte radera alla fält med ALTER TABLE. Använd DROP TABLE istället",
"Kan inte ta bort '%-.64s'. Kontrollera att fältet/nyckel finns",
"Rader: %ld Dubletter: %ld Varningar: %ld",
-"INSERT table '%-.64s' får inte finnas i FROM tabell-listan",
+"You can't specify target table '%-.64s' for update in FROM clause",
"Finns inget thread med id %lu",
"Du är inte ägare till thread %lu",
"Inga tabeller angivna",
@@ -197,10 +197,10 @@
"Okänd system variabel '%-.64s'",
"Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE",
"Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades",
-"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
+"Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt",
-"Denna operation kan inte göras under replikering; Gör SLAVE STOP först",
-"Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START",
+"Denna operation kan inte göras under replikering; Gör STOP SLAVE först",
+"Denna operation kan endast göras under replikering; Konfigurera slaven och gör START SLAVE",
"Servern är inte konfigurerade som en replikations slav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO",
"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'",
"Kunde inte starta en tråd för replikering",
@@ -229,12 +229,25 @@
"Option '%s' användes två gånger",
"Användare '%-.64s' har överskridit '%s' (nuvarande värde: %ld)",
"Du har inte privlegiet '%-.128s' som behövs för denna operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
-"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
-"Variable '%-.64s' doesn't have a default value",
-"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
-"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
-"This version of MySQL doesn't yet support '%s'",
-"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Variable '%-.64s' är en LOCAL variabel och kan inte ändrad med SET GLOBAL",
+"Variable '%-.64s' är en GLOBAL variabel och bör sättas med SET GLOBAL",
+"Variable '%-.64s' har inte ett DEFAULT värde",
+"Variable '%-.64s' kan inte be satt till '%-.64s'",
+"Fel typ av argument till variabel '%-.64s'",
+"Variabeln '%-.64s' kan endast sättas, inte läsas",
+"Fel använding/placering av '%s'",
+"Denna version av MySQL kan inte utföra '%s'",
+"Fick fatalt fel %d: '%-.128s' från master vid läsning av binär loggen",
+"Felaktig FOREIGN KEY definition för '%-.64s': %s",
+"Nyckel referensen och table referensen stämmer inte överens",
+"Cardinality error (more/less than %d columns)",
+"Subselect returnerade mer än 1 rad",
+"Okänd PREPARED STATEMENT id (%ld) var given till %s",
+"Hjälp databasen finns inte eller är skadad",
+"Syklisk referens i subselect",
+"Konvertar kolumn '%s' från %s till %s",
+"Reference '%-.64s' not supported (%s)",
+"Every derived table must have it's own alias"
+"Select %u was reduced during optimisation",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 6eeefa11ff2..0b91786d1f3 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -99,7 +99,7 @@
"îÅ ÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ×Ó¦ ÓÔÏ×Âæ ÚÁ ÄÏÐÏÍÏÇÏÀ ALTER TABLE. äÌÑ ÃØÏÇÏ ÓËÏÒÉÓÔÁÊÔÅÓÑ DROP TABLE",
"îÅ ÍÏÖÕ DROP '%-.64s'. ðÅÒÅצÒÔÅ, ÞÉ ÃÅÊ ÓÔÏ×ÂÅÃØ/ËÌÀÞ ¦ÓÎÕ¤",
"úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld úÁÓÔÅÒÅÖÅÎØ: %ld",
-"INSERT TABLE '%-.64s' ÎÅ ÄÏÚ×ÏÌÅÎÏ Õ ÐÅÒÅ̦ËÕ FROM TABLE",
+"ôÁÂÌÉÃÑ '%-.64s' ÝÏ ÚͦÎÀ¤ÔØÓÑ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ ÐÅÒÅ̦ËÕ ÔÁÂÌÉÃØ FROM",
"îÅצÄÏÍÉÊ ¦ÄÅÎÔÉƦËÁÔÏÒ Ç¦ÌËÉ: %lu",
"÷É ÎÅ ×ÏÌÏÄÁÒ Ç¦ÌËÉ %lu",
"îÅ ×ÉËÏÒÉÓÔÁÎÏ ÔÁÂÌÉÃØ",
@@ -204,8 +204,8 @@
"ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ ÏÓÔÁÎΤ (Á×ÔÏÍÁÔÉÞÎÅ?) צÄÎÏ×ÌÅÎÎÑ ÎÅ ×ÄÁÌÏÓÑ",
"úÁÓÔÅÒÅÖÅÎÎÑ: äÅÑ˦ ÎÅÔÒÁÎÚÁËæÊΦ ÚͦÎÉ ÔÁÂÌÉÃØ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ÐÏ×ÅÒÎÕÔÉ",
"ôÒÁÎÚÁËÃ¦Ñ Ú ÂÁÇÁÔØÍÁ ×ÉÒÁÚÁÍÉ ×ÉÍÁÇÁ¤ ¦ÌØÛÅ Î¦Ö 'max_binlog_cache_size' ÂÁÊÔ¦× ÄÌÑ ÚÂÅÒ¦ÇÁÎÎÑ. ú¦ÌØÛÔÅ ÃÀ ÚͦÎÎÕ mysqld ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ',
-"ïÐÅÒÁÃ¦Ñ ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÎÁÎÁ Ú ÚÁÐÕÝÅÎÉÍ Ð¦ÄÌÅÇÌÉÍ, ÓÐÏÞÁÔËÕ ×ÉËÏÎÁÊÔÅ SLAVE STOP",
-"ïÐÅÒÁÃ¦Ñ ×ÉÍÁÇÁ¤ ÚÁÐÕÝÅÎÏÇÏ Ð¦ÄÌÅÇÌÏÇÏ, ÚËÏÎƦÇÕÒÕÊÔŠЦÄÌÅÇÌÏÇÏ ÔÁ ×ÉËÏÎÁÊÔÅ SLAVE START",
+"ïÐÅÒÁÃ¦Ñ ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÎÁÎÁ Ú ÚÁÐÕÝÅÎÉÍ Ð¦ÄÌÅÇÌÉÍ, ÓÐÏÞÁÔËÕ ×ÉËÏÎÁÊÔÅ STOP SLAVE",
+"ïÐÅÒÁÃ¦Ñ ×ÉÍÁÇÁ¤ ÚÁÐÕÝÅÎÏÇÏ Ð¦ÄÌÅÇÌÏÇÏ, ÚËÏÎƦÇÕÒÕÊÔŠЦÄÌÅÇÌÏÇÏ ÔÁ ×ÉËÏÎÁÊÔÅ START SLAVE",
"óÅÒ×ÅÒ ÎÅ ÚËÏÎƦÇÕÒÏ×ÁÎÏ ÑË Ð¦ÄÌÅÇÌÉÊ, ×ÉÐÒÁ×ÔÅ ÃÅ Õ ÆÁÊ̦ ËÏÎƦÇÕÒÁæ§ ÁÂÏ Ú CHANGE MASTER TO",
"îÅ ÍÏÖÕ ¦Î¦Ã¦Á̦ÚÕ×ÁÔÉ ÓÔÒÕËÔÕÒÕ ÉÎÆÏÒÍÁæ§ ÇÏÌÏ×ÎÏÇÏ, ÐÅÒÅצÒÔÅ ÐÒÁ×Á ÄÏÓÔÕÐÕ ÎÁ master.info",
"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ Ð¦ÄÌÅÇÌÕ Ç¦ÌËÕ, ÐÅÒÅצÒÔÅ ÓÉÓÔÅÍΦ ÒÅÓÕÒÓÉ",
@@ -243,3 +243,16 @@
"Wrong usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Wrong foreign key definition for '%-.64s': %s",
+"Key reference and table reference doesn't match",
+"Cardinality error (¦ÌØÛÅ/ÍÅÎØÛÅ Î¦Ö %d ÓÔÏ×Âæ×)",
+"ð¦ÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ¦ÌØÛ ÎiÖ 1 ÚÁÐÉÓ",
+"Unknown prepared statement handler (%ld) given to %s",
+"Help database is corrupt or does not exist",
+"ãÉË̦ÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ЦÄÚÁÐÉÔ",
+"ðÅÒÅÔ×ÏÒÅÎÎÑ ÓÔÏ×ÂÃÁ '%s' Ú %s Õ %s",
+"ðÏÓÉÌÁÎÎÑ '%-.64s' ÎÅ ÐiÄÔÒÉÍÕÅÔÓÑ (%s)",
+"Every derived table must have it's own alias"
+"Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii",
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/slave.cc b/sql/slave.cc
index 64d54be113e..4b6ebfab5c8 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -14,8 +14,10 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
#include "mysql_priv.h"
+
+#ifdef HAVE_REPLICATION
+
#include <mysql.h>
#include <myisam.h>
#include "mini_client.h"
@@ -24,7 +26,6 @@
#include "repl_failsafe.h"
#include <thr_alarm.h>
#include <my_dir.h>
-#include <assert.h>
bool use_slave_mask = 0;
MY_BITMAP slave_error_mask;
@@ -55,7 +56,6 @@ static int events_till_disconnect = -1;
typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
-void skip_load_data_infile(NET* net);
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev);
static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli);
@@ -78,8 +78,21 @@ char* rewrite_db(char* db);
/*
- Get a bit mask for which threads are running so that we later can
- restart these threads
+ Find out which replications threads are running
+
+ SYNOPSIS
+ init_thread_mask()
+ mask Return value here
+ mi master_info for slave
+ inverse If set, returns which threads are not running
+
+ IMPLEMENTATION
+ Get a bit mask for which threads are running so that we can later restart
+ these threads.
+
+ RETURN
+ mask If inverse == 0, running threads
+ If inverse == 1, stopped threads
*/
void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse)
@@ -96,6 +109,10 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse)
}
+/*
+ lock_slave_threads()
+*/
+
void lock_slave_threads(MASTER_INFO* mi)
{
//TODO: see if we can do this without dual mutex
@@ -103,6 +120,11 @@ void lock_slave_threads(MASTER_INFO* mi)
pthread_mutex_lock(&mi->rli.run_lock);
}
+
+/*
+ unlock_slave_threads()
+*/
+
void unlock_slave_threads(MASTER_INFO* mi)
{
//TODO: see if we can do this without dual mutex
@@ -111,6 +133,8 @@ void unlock_slave_threads(MASTER_INFO* mi)
}
+/* Initialize slave structures */
+
int init_slave()
{
DBUG_ENTER("init_slave");
@@ -166,6 +190,7 @@ static void free_table_ent(TABLE_RULE_ENT* e)
my_free((gptr) e, MYF(0));
}
+
static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
my_bool not_used __attribute__((unused)))
{
@@ -284,7 +309,16 @@ err:
}
-/* called from get_options() in mysqld.cc on start-up */
+/*
+ Init functio to set up array for errors that should be skipped for slave
+
+ SYNOPSIS
+ init_slave_skip_errors()
+ arg List of errors numbers to skip, separated with ','
+
+ NOTES
+ Called from get_options() in mysqld.cc on start-up
+*/
void init_slave_skip_errors(const char* arg)
{
@@ -295,9 +329,9 @@ void init_slave_skip_errors(const char* arg)
exit(1);
}
use_slave_mask = 1;
- for (;isspace(*arg);++arg)
+ for (;my_isspace(system_charset_info,*arg);++arg)
/* empty */;
- if (!my_casecmp(arg,"all",3))
+ if (!my_strncasecmp(system_charset_info,arg,"all",3))
{
bitmap_set_all(&slave_error_mask);
return;
@@ -309,15 +343,17 @@ void init_slave_skip_errors(const char* arg)
break;
if (err_code < MAX_SLAVE_ERROR)
bitmap_set_bit(&slave_error_mask,(uint)err_code);
- while (!isdigit(*p) && *p)
+ while (!my_isdigit(system_charset_info,*p) && *p)
p++;
}
}
/*
- We assume we have a run lock on rli and that both slave thread
- are not running
+ purge_relay_logs()
+
+ NOTES
+ Assumes to have a run lock on rli and that no slave thread are running.
*/
int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
@@ -515,9 +551,12 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
/*
- SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
- sense to do that for starting a slave - we always care if it actually
- started the threads that were not previously running
+ start_slave_threads()
+
+ NOTES
+ SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
+ sense to do that for starting a slave--we always care if it actually
+ started the threads that were not previously running
*/
int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
@@ -562,12 +601,13 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
void init_table_rule_hash(HASH* h, bool* h_inited)
{
- hash_init(h, TABLE_RULE_HASH_SIZE,0,0,
+ hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
(hash_get_key) get_table_key,
(hash_free_key) free_table_ent, 0);
*h_inited = 1;
}
+
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited)
{
my_init_dynamic_array(a, sizeof(TABLE_RULE_ENT*), TABLE_RULE_ARR_SIZE,
@@ -575,6 +615,7 @@ void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited)
*a_inited = 1;
}
+
static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
{
uint i;
@@ -584,8 +625,10 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
{
TABLE_RULE_ENT* e ;
get_dynamic(a, (gptr)&e, i);
- if (!wild_case_compare(key, key_end, (const char*)e->db,
- (const char*)(e->db + e->key_len),'\\'))
+ if (!my_wildcmp(system_charset_info, key, key_end,
+ (const char*)e->db,
+ (const char*)(e->db + e->key_len),
+ '\\',wild_one,wild_many))
return e;
}
@@ -724,6 +767,11 @@ int add_table_rule(HASH* h, const char* table_spec)
return 0;
}
+
+/*
+ Add table expression with wildcards to dynamic array
+*/
+
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
{
const char* dot = strchr(table_spec, '.');
@@ -740,6 +788,7 @@ int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
return 0;
}
+
static void free_string_array(DYNAMIC_ARRAY *a)
{
uint i;
@@ -752,8 +801,8 @@ static void free_string_array(DYNAMIC_ARRAY *a)
delete_dynamic(a);
}
-#ifdef NOT_USED_YET
+#ifdef NOT_USED_YET
static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
{
end_master_info(mi);
@@ -762,6 +811,13 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
#endif
+/*
+ Free all resources used by slave
+
+ SYNOPSIS
+ end_slave()
+*/
+
void end_slave()
{
if (active_mi)
@@ -814,13 +870,25 @@ void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...)
rli->last_slave_errno = err_code;
}
+/*
+ skip_load_data_infile()
-void skip_load_data_infile(NET* net)
+ NOTES
+ This is used to tell a 3.23 master to break send_file()
+*/
+
+void skip_load_data_infile(NET *net)
{
- (void)my_net_write(net, "\xfb/dev/null", 10);
- (void)net_flush(net);
- (void)my_net_read(net); // discard response
- send_ok(net); // the master expects it
+ (void)net_request_file(net, "/dev/null");
+ (void)my_net_read(net); // discard response
+ (void)net_write_command(net, 0, "", 0, "", 0); // Send ok
+}
+
+
+bool net_request_file(NET* net, const char* fname)
+{
+ DBUG_ENTER("net_request_file");
+ DBUG_RETURN(net_write_command(net, 251, fname, strlen(fname), "", 0));
}
@@ -982,13 +1050,13 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
if (packet_len == packet_error)
{
- send_error(&thd->net, ER_MASTER_NET_READ);
+ send_error(thd, ER_MASTER_NET_READ);
return 1;
}
if (net->read_pos[0] == 255) // error from master
{
net->read_pos[packet_len] = 0;
- net_printf(&thd->net, ER_MASTER, net->read_pos + 3);
+ net_printf(thd, ER_MASTER, net->read_pos + 3);
return 1;
}
thd->command = COM_TABLE_DUMP;
@@ -996,7 +1064,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
if (!(query = sql_alloc(packet_len + 1)))
{
sql_print_error("create_table_from_dump: out of memory");
- net_printf(&thd->net, ER_GET_ERRNO, "Out of memory");
+ net_printf(thd, ER_GET_ERRNO, "Out of memory");
return 1;
}
memcpy(query, net->read_pos, packet_len);
@@ -1034,7 +1102,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
thd->proc_info = "Opening master dump table";
if (!open_ltable(thd, &tables, TL_WRITE))
{
- send_error(&thd->net,0,0); // Send error from open_ltable
+ send_error(thd,0,0); // Send error from open_ltable
sql_print_error("create_table_from_dump: could not open created table");
goto err;
}
@@ -1043,7 +1111,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
thd->proc_info = "Reading master dump table data";
if (file->net_read_dump(net))
{
- net_printf(&thd->net, ER_MASTER_NET_READ);
+ net_printf(thd, ER_MASTER_NET_READ);
sql_print_error("create_table_from_dump::failed in\
handler::net_read_dump()");
goto err;
@@ -1062,7 +1130,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
error=file->repair(thd,&check_opt) != 0;
thd->net.vio = save_vio;
if (error)
- net_printf(&thd->net, ER_INDEX_REBUILD,tables.table->real_name);
+ net_printf(thd, ER_INDEX_REBUILD,tables.table->real_name);
err:
close_thread_tables(thd);
@@ -1070,6 +1138,7 @@ err:
return error;
}
+
int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
MASTER_INFO *mi, MYSQL *mysql)
{
@@ -1084,12 +1153,12 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
{
if (!(mysql = mc_mysql_init(NULL)))
{
- send_error(&thd->net); // EOM
+ send_error(thd); // EOM
DBUG_RETURN(1);
}
if (connect_to_master(thd, mysql, mi))
{
- net_printf(&thd->net, ER_CONNECT_TO_MASTER, mc_mysql_error(mysql));
+ net_printf(thd, ER_CONNECT_TO_MASTER, mc_mysql_error(mysql));
mc_mysql_close(mysql);
DBUG_RETURN(1);
}
@@ -1113,7 +1182,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
if (!called_connected)
mc_mysql_close(mysql);
if (errmsg && thd->net.vio)
- send_error(&thd->net, error, errmsg);
+ send_error(thd, error, errmsg);
DBUG_RETURN(test(error)); // Return 1 on error
}
@@ -1298,9 +1367,11 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
THD* thd = mi->io_thd;
DBUG_ENTER("wait_for_relay_log_space");
+
pthread_mutex_lock(&rli->log_space_lock);
save_proc_info = thd->proc_info;
thd->proc_info = "Waiting for relay log space to free";
+
while (rli->log_space_limit < rli->log_space_total &&
!(slave_killed=io_slave_killed(thd,mi)))
{
@@ -1451,109 +1522,115 @@ err:
int register_slave_on_master(MYSQL* mysql)
{
- String packet;
- char buf[4];
+ char buf[1024], *pos= buf;
+ uint report_host_len, report_user_len=0, report_password_len=0;
if (!report_host)
return 0;
-
- int4store(buf, server_id);
- packet.append(buf, 4);
-
- net_store_data(&packet, report_host);
+ report_host_len= strlen(report_host);
if (report_user)
- net_store_data(&packet, report_user);
- else
- packet.append((char)0);
-
+ report_user_len= strlen(report_user);
if (report_password)
- net_store_data(&packet, report_user);
- else
- packet.append((char)0);
-
- int2store(buf, (uint16)report_port);
- packet.append(buf, 2);
- int4store(buf, rpl_recovery_rank);
- packet.append(buf, 4);
- int4store(buf, 0); /* tell the master will fill in master_id */
- packet.append(buf, 4);
-
- if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
- packet.length(), 0))
+ report_password_len= strlen(report_password);
+ /* 30 is a good safety margin */
+ if (report_host_len + report_user_len + report_password_len + 30 >
+ sizeof(buf))
+ return 0; // safety
+
+ int4store(pos, server_id); pos+= 4;
+ pos= net_store_data(pos, report_host, report_host_len);
+ pos= net_store_data(pos, report_user, report_user_len);
+ pos= net_store_data(pos, report_password, report_password_len);
+ int2store(pos, (uint16) report_port); pos+= 2;
+ int4store(pos, rpl_recovery_rank); pos+= 4;
+ /* The master will fill in master_id */
+ int4store(pos, 0); pos+= 4;
+
+ if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf,
+ (uint) (pos- buf), 0))
{
sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'",
mc_mysql_errno(mysql),
mc_mysql_error(mysql));
return 1;
}
-
return 0;
}
+
int show_master_info(THD* thd, MASTER_INFO* mi)
{
// TODO: fix this for multi-master
- DBUG_ENTER("show_master_info");
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("show_master_info");
+
field_list.push_back(new Item_empty_string("Master_Host",
sizeof(mi->host)));
field_list.push_back(new Item_empty_string("Master_User",
sizeof(mi->user)));
- field_list.push_back(new Item_empty_string("Master_Port", 6));
- field_list.push_back(new Item_empty_string("Connect_retry", 6));
+ field_list.push_back(new Item_return_int("Master_Port", 7,
+ MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Connect_retry", 10,
+ MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Master_Log_File",
- FN_REFLEN));
- field_list.push_back(new Item_empty_string("Read_Master_Log_Pos", 12));
+ FN_REFLEN));
+ field_list.push_back(new Item_return_int("Read_Master_Log_Pos", 10,
+ MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Log_File",
- FN_REFLEN));
- field_list.push_back(new Item_empty_string("Relay_Log_Pos", 12));
+ FN_REFLEN));
+ field_list.push_back(new Item_return_int("Relay_Log_Pos", 10,
+ MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
- FN_REFLEN));
+ FN_REFLEN));
field_list.push_back(new Item_empty_string("Slave_IO_Running", 3));
field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3));
field_list.push_back(new Item_empty_string("Replicate_do_db", 20));
field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20));
- field_list.push_back(new Item_empty_string("Last_errno", 4));
+ field_list.push_back(new Item_return_int("Last_errno", 4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_error", 20));
- field_list.push_back(new Item_empty_string("Skip_counter", 12));
- field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12));
- field_list.push_back(new Item_empty_string("Relay_log_space", 12));
- if (send_fields(thd, field_list, 1))
+ field_list.push_back(new Item_return_int("Skip_counter", 10,
+ MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_return_int("Exec_master_log_pos", 10,
+ MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_return_int("Relay_log_space", 10,
+ MYSQL_TYPE_LONGLONG));
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
if (mi->host[0])
{
String *packet= &thd->packet;
- packet->length(0);
+ protocol->prepare_for_resend();
pthread_mutex_lock(&mi->data_lock);
pthread_mutex_lock(&mi->rli.data_lock);
- net_store_data(packet, mi->host);
- net_store_data(packet, mi->user);
- net_store_data(packet, (uint32) mi->port);
- net_store_data(packet, (uint32) mi->connect_retry);
- net_store_data(packet, mi->master_log_name);
- net_store_data(packet, (longlong) mi->master_log_pos);
- net_store_data(packet, mi->rli.relay_log_name +
+ protocol->store(mi->host);
+ protocol->store(mi->user);
+ protocol->store((uint32) mi->port);
+ protocol->store((uint32) mi->connect_retry);
+ protocol->store(mi->master_log_name);
+ protocol->store((ulonglong) mi->master_log_pos);
+ protocol->store(mi->rli.relay_log_name +
dirname_length(mi->rli.relay_log_name));
- net_store_data(packet, (longlong) mi->rli.relay_log_pos);
- net_store_data(packet, mi->rli.master_log_name);
- net_store_data(packet, mi->slave_running ? "Yes":"No");
- net_store_data(packet, mi->rli.slave_running ? "Yes":"No");
- net_store_data(packet, &replicate_do_db);
- net_store_data(packet, &replicate_ignore_db);
- net_store_data(packet, (uint32)mi->rli.last_slave_errno);
- net_store_data(packet, mi->rli.last_slave_error);
- net_store_data(packet, mi->rli.slave_skip_counter);
- net_store_data(packet, (longlong) mi->rli.master_log_pos);
- net_store_data(packet, (longlong) mi->rli.log_space_total);
+ protocol->store((ulonglong) mi->rli.relay_log_pos);
+ protocol->store(mi->rli.master_log_name);
+ protocol->store(mi->slave_running ? "Yes":"No");
+ protocol->store(mi->rli.slave_running ? "Yes":"No");
+ protocol->store(&replicate_do_db);
+ protocol->store(&replicate_ignore_db);
+ protocol->store((uint32) mi->rli.last_slave_errno);
+ protocol->store(mi->rli.last_slave_error);
+ protocol->store((uint32) mi->rli.slave_skip_counter);
+ protocol->store((ulonglong) mi->rli.master_log_pos);
+ protocol->store((ulonglong) mi->rli.log_space_total);
pthread_mutex_unlock(&mi->rli.data_lock);
pthread_mutex_unlock(&mi->data_lock);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
DBUG_RETURN(-1);
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -1569,8 +1646,7 @@ bool flush_master_info(MASTER_INFO* mi)
my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
- mi->password, mi->port, mi->connect_retry
- );
+ mi->password, mi->port, mi->connect_retry);
flush_io_cache(file);
DBUG_RETURN(0);
}
@@ -1779,6 +1855,10 @@ improper_arguments: %d timed_out: %d",
}
+/*
+ init_slave_thread()
+*/
+
static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{
DBUG_ENTER("init_slave_thread");
@@ -1916,7 +1996,7 @@ command");
/*
- read one event from the master
+ Read one event from the master
SYNOPSIS
read_event()
@@ -1930,7 +2010,6 @@ command");
RETURN VALUES
'packet_error' Error
number Length of packet
-
*/
static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
@@ -2069,7 +2148,8 @@ This may also be a network problem, or just a bug in the master or slave code.\
}
-/* slave I/O thread */
+/* Slave I/O Thread entry point */
+
extern "C" pthread_handler_decl(handle_slave_io,arg)
{
THD *thd; // needs to be first for thread_stack
@@ -2343,7 +2423,7 @@ err:
}
-/* slave SQL logic thread */
+/* Slave SQL Thread entry point */
extern "C" pthread_handler_decl(handle_slave_sql,arg)
{
@@ -2477,7 +2557,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
if (abort_slave_event_count && !rli->events_till_abort)
goto slave_begin;
#endif
- my_thread_end(); // clean-up before broadcasting termination
+ my_thread_end();
#ifndef __NETWARE__
pthread_exit(0);
#endif /* __NETWARE__ */
@@ -2485,13 +2565,17 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
}
+/*
+ process_io_create_file()
+*/
+
static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
{
int error = 1;
ulong num_bytes;
bool cev_not_written;
- THD* thd;
- NET* net = &mi->mysql->net;
+ THD *thd = mi->io_thd;
+ NET *net = &mi->mysql->net;
DBUG_ENTER("process_io_create_file");
if (unlikely(!cev->is_valid()))
@@ -2505,7 +2589,6 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
DBUG_RETURN(0);
}
DBUG_ASSERT(cev->inited_from_old);
- thd = mi->io_thd;
thd->file_id = cev->file_id = mi->file_id++;
thd->server_id = cev->server_id;
cev_not_written = 1;
@@ -2535,7 +2618,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
}
if (unlikely(!num_bytes)) /* eof */
{
- send_ok(net); /* 3.23 master wants it */
+ net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
Execute_load_log_event xev(thd,0);
xev.log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(&xev)))
@@ -2581,6 +2664,7 @@ err:
DBUG_RETURN(error);
}
+
/*
Start using a new binary log on the master
@@ -2599,6 +2683,7 @@ err:
RETURN VALUES
0 ok
1 Log event is illegal
+
*/
static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
@@ -2625,7 +2710,10 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
DBUG_RETURN(0);
}
+
/*
+ queue_old_event()
+
TODO:
Test this code before release - it has to be tested on a separate
setup with 3.23 master
@@ -2718,7 +2806,10 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
DBUG_RETURN(0);
}
+
/*
+ queue_event()
+
TODO: verify the issue with stop events, see if we need them at all
in the relay log
*/
@@ -2800,7 +2891,20 @@ void end_relay_log_info(RELAY_LOG_INFO* rli)
DBUG_VOID_RETURN;
}
-/* try to connect until successful or slave killed */
+/*
+ Try to connect until successful or slave killed
+
+ SYNPOSIS
+ safe_connect()
+ thd Thread handler for slave
+ mysql MySQL connection handle
+ mi Replication handle
+
+ RETURN
+ 0 ok
+ # Error
+*/
+
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
{
return connect_to_master(thd, mysql, mi, 0, 0);
@@ -2808,8 +2912,12 @@ static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
/*
- Try to connect until successful or slave killed or we have retried
- master_retry_count times
+ SYNPOSIS
+ connect_to_master()
+
+ IMPLEMENTATION
+ Try to connect until successful or slave killed or we have retried
+ master_retry_count times
*/
static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
@@ -2892,8 +3000,11 @@ replication resumed in log '%s' at position %s", mi->user,
/*
- Try to connect until successful or slave killed or we have retried
- master_retry_count times
+ safe_reconnect()
+
+ IMPLEMENTATION
+ Try to connect until successful or slave killed or we have retried
+ master_retry_count times
*/
static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
@@ -2962,8 +3073,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli)
/*
- This function is called when we notice that the current "hot" log
- got rotated under our feet.
+ Called when we notice that the current "hot" log got rotated under our feet.
*/
static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
@@ -3193,3 +3303,5 @@ err:
template class I_List_iterator<i_string>;
template class I_List_iterator<i_string_pair>;
#endif
+
+#endif /* HAVE_REPLICATION */
diff --git a/sql/slave.h b/sql/slave.h
index ea7e2b4ef16..5dd7fe8072b 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -1,3 +1,5 @@
+#ifdef HAVE_REPLICATION
+
#ifndef SLAVE_H
#define SLAVE_H
@@ -7,22 +9,28 @@
#define MAX_SLAVE_ERRMSG 1024
#define MAX_SLAVE_ERROR 2000
-/*
- The replication is accomplished by starting two threads - I/O
- thread, and SQL thread. I/O thread is associated with its
- MASTER_INFO struct, so MASTER_INFO can be viewed as I/O thread
- descriptor. SQL thread is associated with RELAY_LOG_INFO struct.
-
- I/O thread reads maintains a connection to the master, and reads log
- events from the master as they arrive, queueing them by writing them
- out into the temporary slave binary log (relay log). The SQL thread,
- in turn, reads the slave binary log executing each event.
-
- Relay log is needed to be able to handle situations when there is a large
- backlog of unprocessed events from the master (eg. one particular update
- takes a day to finish), and to be able to restart the slave server without
- having to re-read the master updates.
- */
+/*****************************************************************************
+
+ MySQL Replication
+
+ Replication is implemented via two types of threads:
+
+ I/O Thread - One of these threads is started for each master server.
+ They maintain a connection to their master server, read log
+ events from the master as they arrive, and queues them into
+ a single, shared relay log file. A MASTER_INFO struct
+ represents each of these threads.
+
+ SQL Thread - One of these threads is started and reads from the relay log
+ file, executing each event. A RELAY_LOG_INFO struct
+ represents this thread.
+
+ Buffering in the relay log file makes it unnecessary to reread events from
+ a master server across a slave restart. It also decouples the slave from
+ the master where long-running updates and event logging are concerned--ie
+ it can continue to log new events while a slow query executes on the slave.
+
+*****************************************************************************/
extern ulong slave_net_timeout, master_retry_count;
extern MY_BITMAP slave_error_mask;
@@ -48,11 +56,16 @@ struct st_master_info;
--active_mi_in_use; \
pthread_mutex_unlock(&LOCK_active_mi); }
-/*
- st_relay_log_info contains information on the current relay log and
- relay log offset, and master log name and log sequence corresponding to the
- last update. Additionally, misc information specific to the SQL thread is
- included.
+/*****************************************************************************
+
+ Replication SQL Thread
+
+ st_relay_log_info contains:
+ - the current relay log
+ - the current relay log offset
+ - master log name
+ - master log sequence corresponding to the last update
+ - misc information specific to the SQL thread
st_relay_log_info is initialized from the slave.info file if such exists.
Otherwise, data members are intialized with defaults. The initialization is
@@ -66,7 +79,8 @@ struct st_master_info;
master_log_pos
To clean up, call end_relay_log_info()
- */
+
+*****************************************************************************/
typedef struct st_relay_log_info
{
@@ -128,13 +142,18 @@ typedef struct st_relay_log_info
uint32 cur_log_old_open_count;
/*
- Current offset in the relay log.
- pending - in some cases we do not increment offset immediately after
- processing an event, because the following event needs to be processed
- atomically together with this one ( so far, there is only one type of
- such event - Intvar_event that sets auto_increment value). However, once
- both events have been processed, we need to increment by the cumulative
- offset. pending stored the extra offset to be added to the position.
+ relay_log_pos - Current offset in the relay log.
+ pending - In some cases we do not increment offset immediately
+ after processing an event, because the following event
+ needs to be processed atomically together with this one
+ such as:
+
+ Intvar_event - sets auto_increment value
+ Rand_event - sets the random seed
+
+ However, once both events have been processed, we need to
+ increment by the cumulative offset. 'pending' stores the
+ extra offset to be added to the position.
*/
ulonglong relay_log_pos, pending;
ulonglong log_space_limit,log_space_total;
@@ -208,10 +227,15 @@ typedef struct st_relay_log_info
Log_event* next_event(RELAY_LOG_INFO* rli);
-/*
- st_master_info contains information about how to connect to a master,
- current master log name, and current log offset, as well as misc
- control variables
+/*****************************************************************************
+
+ Replication IO Thread
+
+ st_master_info contains:
+ - information about how to connect to a master
+ - current master log name
+ - current master log offset
+ - misc control variables
st_master_info is initialized once from the master.info file if such
exists. Otherwise, data members corresponding to master.info fields
@@ -233,9 +257,9 @@ Log_event* next_event(RELAY_LOG_INFO* rli);
flush_master_info() is required.
To clean up, call end_master_info()
-*/
-
+*****************************************************************************/
+
typedef struct st_master_info
{
char master_log_name[FN_REFLEN];
@@ -418,3 +442,7 @@ extern I_List<i_string_pair> replicate_rewrite_db;
extern I_List<THD> threads;
#endif
+#else
+#define SLAVE_IO 1
+#define SLAVE_SQL 2
+#endif /* HAVE_REPLICATION */
diff --git a/sql/spatial.cc b/sql/spatial.cc
new file mode 100644
index 00000000000..42dd74a697a
--- /dev/null
+++ b/sql/spatial.cc
@@ -0,0 +1,1443 @@
+#include "mysql_priv.h"
+
+
+#define MAX_DIGITS_IN_DOUBLE 16
+
+/***************************** GClassInfo *******************************/
+
+#define IMPLEMENT_GEOM(class_name, type_id, name) \
+{ \
+ (GF_InitFromText) &class_name::init_from_text, \
+ (GF_GetDataAsText) &class_name::get_data_as_text, \
+ (GF_GetDataSize) &class_name::get_data_size, \
+ (GF_GetMBR) &class_name::get_mbr, \
+ (GF_GetD) &class_name::get_x, \
+ (GF_GetD) &class_name::get_y, \
+ (GF_GetD) &class_name::length, \
+ (GF_GetD) &class_name::area, \
+ (GF_GetI) &class_name::is_closed, \
+ (GF_GetUI) &class_name::num_interior_ring, \
+ (GF_GetUI) &class_name::num_points, \
+ (GF_GetUI) &class_name::num_geometries, \
+ (GF_GetUI) &class_name::dimension, \
+ (GF_GetWS) &class_name::start_point, \
+ (GF_GetWS) &class_name::end_point, \
+ (GF_GetWS) &class_name::exterior_ring, \
+ (GF_GetWS) &class_name::centroid, \
+ (GF_GetUIWS) &class_name::point_n, \
+ (GF_GetUIWS) &class_name::interior_ring_n, \
+ (GF_GetUIWS) &class_name::geometry_n, \
+ class_name::type_id, \
+ name, \
+ NULL \
+},
+
+
+static Geometry::GClassInfo ci_collection[] =
+{
+ IMPLEMENT_GEOM(GPoint, wkbPoint, "POINT")
+ IMPLEMENT_GEOM(GLineString, wkbLineString, "LINESTRING")
+ IMPLEMENT_GEOM(GPolygon, wkbPolygon, "POLYGON")
+ IMPLEMENT_GEOM(GMultiPoint, wkbMultiPoint, "MULTIPOINT")
+ IMPLEMENT_GEOM(GMultiLineString, wkbMultiLineString, "MULTILINESTRING")
+ IMPLEMENT_GEOM(GMultiPolygon, wkbMultiPolygon, "MULTIPOLYGON")
+ IMPLEMENT_GEOM(GGeometryCollection, wkbGeometryCollection, "GEOMETRYCOLLECTION")
+};
+
+static Geometry::GClassInfo *ci_collection_end = ci_collection + sizeof(ci_collection)/sizeof(ci_collection[0]);
+
+/***************************** Geometry *******************************/
+
+Geometry::GClassInfo *Geometry::find_class(int type_id)
+{
+ for (GClassInfo *cur_rt = ci_collection; cur_rt < ci_collection_end; ++cur_rt)
+ {
+ if (cur_rt->m_type_id == type_id)
+ {
+ return cur_rt;
+ }
+ }
+ return NULL;
+}
+
+Geometry::GClassInfo *Geometry::find_class(const char *name, size_t len)
+{
+ for (GClassInfo *cur_rt = ci_collection;
+ cur_rt < ci_collection_end; ++cur_rt)
+ {
+ if ((cur_rt->m_name[len] == 0) &&
+ (default_charset_info->strncasecmp(default_charset_info,
+ cur_rt->m_name, name, len) == 0))
+ {
+ return cur_rt;
+ }
+ }
+ return NULL;
+}
+
+int Geometry::create_from_wkb(const char *data, uint32 data_len)
+{
+ uint32 geom_type;
+
+ if (data_len < 1+4)
+ return 1;
+ data += sizeof(char);
+
+//FIXME: check byte ordering
+ geom_type = uint4korr(data);
+ data += 4;
+ m_vmt = find_class(geom_type);
+ if (!m_vmt) return -1;
+ m_data = data;
+ m_data_end = data + data_len;
+ return 0;
+}
+
+int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream)
+{
+ int name_len;
+ const char *name = trs->get_next_word(&name_len);
+ if (!name)
+ {
+ trs->set_error_msg("Geometry name expected");
+ return -1;
+ }
+ if (!(m_vmt = find_class(name, name_len)))
+ return -1;
+ if (wkt->reserve(1 + 4, 512))
+ return 1;
+ wkt->q_append((char)wkbNDR);
+ wkt->q_append((uint32)get_class_info()->m_type_id);
+ if (trs->get_next_symbol() != '(')
+ {
+ trs->set_error_msg("'(' expected");
+ return -1;
+ }
+ if (init_from_text(trs, wkt)) return 1;
+ if (trs->get_next_symbol() != ')')
+ {
+ trs->set_error_msg("')' expected");
+ return -1;
+ }
+ if (init_stream)
+ {
+ init_from_wkb(wkt->ptr(), wkt->length());
+ shift_wkb_header();
+ }
+ return 0;
+}
+
+int Geometry::envelope(String *result) const
+{
+ MBR mbr;
+
+ get_mbr(&mbr);
+
+ if (result->reserve(1+4*3+sizeof(double)*10))
+ return 1;
+
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbPolygon);
+ result->q_append((uint32)1);
+ result->q_append((uint32)5);
+ result->q_append(mbr.xmin);
+ result->q_append(mbr.ymin);
+ result->q_append(mbr.xmax);
+ result->q_append(mbr.ymin);
+ result->q_append(mbr.xmax);
+ result->q_append(mbr.ymax);
+ result->q_append(mbr.xmin);
+ result->q_append(mbr.ymax);
+ result->q_append(mbr.xmin);
+ result->q_append(mbr.ymin);
+
+ return 0;
+}
+
+/***************************** Point *******************************/
+
+size_t GPoint::get_data_size() const
+{
+ return POINT_DATA_SIZE;
+}
+
+int GPoint::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ double x, y;
+ if (wkb->reserve(sizeof(double)*2))
+ return 1;
+ if (trs->get_next_number(&x))
+ return 1;
+ if (trs->get_next_number(&y))
+ return 1;
+ wkb->q_append(x);
+ wkb->q_append(y);
+
+ return 0;
+}
+
+int GPoint::get_data_as_text(String *txt) const
+{
+ double x, y;
+ if (get_xy(&x, &y))
+ return 1;
+ if (txt->reserve(MAX_DIGITS_IN_DOUBLE * 2 + 1))
+ return 1;
+ txt->qs_append(x);
+ txt->qs_append(' ');
+ txt->qs_append(y);
+ return 0;
+}
+
+int GPoint::get_mbr(MBR *mbr) const
+{
+ double x, y;
+ if (get_xy(&x, &y))
+ return 1;
+ mbr->add_xy(x, y);
+ return 0;
+}
+
+/***************************** LineString *******************************/
+
+size_t GLineString::get_data_size() const
+{
+ uint32 n_points = uint4korr(m_data);
+
+ return 4 + n_points*POINT_DATA_SIZE;
+}
+
+int GLineString::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ uint32 n_points = 0;
+ int np_pos = wkb->length();
+ GPoint p;
+
+ if (wkb->reserve(4, 512))
+ return 1;
+
+ wkb->q_append((uint32)n_points);
+
+ for (;;)
+ {
+ if (p.init_from_text(trs, wkb))
+ return 1;
+ ++n_points;
+ if (trs->get_next_toc_type() == GTextReadStream::comma)
+ trs->get_next_symbol();
+ else break;
+ }
+
+ if (n_points<2)
+ {
+ trs->set_error_msg("Too few points in LINESTRING");
+ return 1;
+ }
+
+ wkb->WriteAtPosition(np_pos, n_points);
+
+ return 0;
+}
+
+int GLineString::get_data_as_text(String *txt) const
+{
+ uint32 n_points;
+ const char *data = m_data;
+
+ if (no_data(data, 4))
+ return 1;
+
+ n_points = uint4korr(data);
+ data += 4;
+
+ if (no_data(data, sizeof(double) * 2 * n_points))
+ return 1;
+
+ if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
+ return 1;
+ for (; n_points>0; --n_points)
+ {
+ double x, y;
+ float8get(x, data);
+ data += sizeof(double);
+ float8get(y, data);
+ data += sizeof(double);
+ txt->qs_append(x);
+ txt->qs_append(' ');
+ txt->qs_append(y);
+ txt->qs_append(',');
+ }
+ txt->length(txt->length() - 1);
+ return 0;
+}
+
+int GLineString::get_mbr(MBR *mbr) const
+{
+ uint32 n_points;
+ const char *data = m_data;
+
+ if (no_data(data, 4))
+ return 1;
+
+ n_points = uint4korr(data);
+ data += 4;
+
+ if (no_data(data, sizeof(double) * 2 * n_points))
+ return 1;
+ for (; n_points>0; --n_points)
+ {
+ mbr->add_xy(data, data + 8);
+ data += 8+8;
+ }
+
+ return 0;
+}
+
+int GLineString::length(double *len) const
+{
+ uint32 n_points;
+ double prev_x, prev_y;
+ const char *data = m_data;
+
+ *len=0;
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+ data += 4;
+
+ if (no_data(data, sizeof(double) * 2 * n_points))
+ return 1;
+
+ --n_points;
+ float8get(prev_x, data);
+ data += 8;
+ float8get(prev_y, data);
+ data += 8;
+
+ for (; n_points>0; --n_points)
+ {
+ double x, y;
+ float8get(x, data);
+ data += 8;
+ float8get(y, data);
+ data += 8;
+ *len+=sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
+ prev_x=x;
+ prev_y=y;
+ }
+ return 0;
+}
+
+int GLineString::is_closed(int *closed) const
+
+{
+ uint32 n_points;
+ double x1, y1, x2, y2;
+
+ const char *data = m_data;
+
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, (8+8) * n_points))
+ return 1;
+ float8get(x1, data);
+ data += 8;
+ float8get(y1, data);
+ data += 8 + (n_points-2)*POINT_DATA_SIZE;
+ float8get(x2, data);
+ data += 8;
+ float8get(y2, data);
+
+ *closed=(x1==x2)&&(y1==y2);
+
+ return 0;
+}
+
+int GLineString::num_points(uint32 *n_points) const
+{
+ *n_points = uint4korr(m_data);
+ return 0;
+}
+
+int GLineString::start_point(String *result) const
+{
+ const char *data = m_data + 4;
+ if (no_data(data, 8+8))
+ return 1;
+
+ if (result->reserve(1 + 4 + sizeof(double) * 2))
+ return 1;
+
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbPoint);
+ result->q_append((double *)data);
+ result->q_append((double *)(data + 8));
+
+ return 0;
+}
+
+int GLineString::end_point(String *result) const
+{
+ const char *data = m_data;
+ uint32 n_points;
+
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+
+ data += 4 + (n_points-1)*POINT_DATA_SIZE;
+
+ if (no_data(data, 8+8))
+ return 1;
+
+ if (result->reserve(1 + 4 + sizeof(double) * 2))
+ return 1;
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbPoint);
+ result->q_append((double *)data);
+ result->q_append((double *)(data + 8));
+
+ return 0;
+}
+
+
+int GLineString::point_n(uint32 num, String *result) const
+{
+ const char *data = m_data;
+ uint32 n_points;
+
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+
+ if ((uint32)(num-1) >= n_points) // really means (num > n_points || num < 1)
+ return 1;
+
+ data += 4 + (num - 1)*POINT_DATA_SIZE;
+
+ if (no_data(data, 8+8))
+ return 1;
+ if (result->reserve(1 + 4 + sizeof(double) * 2))
+ return 1;
+
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbPoint);
+ result->q_append((double *)data);
+ result->q_append((double *)(data + 8));
+
+ return 0;
+}
+
+/***************************** Polygon *******************************/
+
+size_t GPolygon::get_data_size() const
+{
+ uint32 n_linear_rings = 0;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+
+ n_linear_rings = uint4korr(data);
+ data += 4;
+ for (; n_linear_rings>0; --n_linear_rings)
+ {
+ if (no_data(data, 4))
+ return 1;
+ data += 4 + uint4korr(data)*POINT_DATA_SIZE;
+ }
+ return data - m_data;
+}
+
+int GPolygon::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ uint32 n_linear_rings = 0;
+ int lr_pos = wkb->length();
+
+ if (wkb->reserve(4, 512))
+ return 1;
+
+ wkb->q_append((uint32)n_linear_rings);
+
+ for (;;)
+ {
+ GLineString ls;
+ size_t ls_pos=wkb->length();
+ if (trs->get_next_symbol() != '(')
+ {
+ trs->set_error_msg("'(' expected");
+ return 1;
+ }
+ if (ls.init_from_text(trs, wkb))
+ return 1;
+ if (trs->get_next_symbol() != ')')
+ {
+ trs->set_error_msg("')' expected");
+ return 1;
+ }
+ ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos);
+ int closed;
+ ls.is_closed(&closed);
+ if (!closed)
+ {
+ trs->set_error_msg("POLYGON's linear ring isn't closed");
+ return 1;
+ }
+ ++n_linear_rings;
+ if (trs->get_next_toc_type() == GTextReadStream::comma)
+ trs->get_next_symbol();
+ else
+ break;
+ }
+ wkb->WriteAtPosition(lr_pos, n_linear_rings);
+ return 0;
+}
+
+int GPolygon::get_data_as_text(String *txt) const
+{
+ uint32 n_linear_rings;
+ const char *data = m_data;
+
+ if (no_data(data, 4))
+ return 1;
+
+ n_linear_rings = uint4korr(data);
+ data += 4;
+
+ for (; n_linear_rings>0; --n_linear_rings)
+ {
+ if (no_data(data, 4))
+ return 1;
+ uint32 n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, (8+8) * n_points))
+ return 1;
+
+ if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
+ return 1;
+ txt->qs_append('(');
+ for (; n_points>0; --n_points)
+ {
+ txt->qs_append((double *)data);
+ txt->qs_append(' ');
+ txt->qs_append((double *)(data + 8));
+ txt->qs_append(',');
+
+ data += 8+8;
+ }
+ (*txt)[txt->length()-1] = ')';
+ txt->qs_append(',');
+ }
+ txt->length(txt->length() - 1);
+ return 0;
+}
+
+int GPolygon::get_mbr(MBR *mbr) const
+{
+ uint32 n_linear_rings;
+
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_linear_rings = uint4korr(data);
+ data += 4;
+ for (; n_linear_rings>0; --n_linear_rings)
+ {
+ if (no_data(data, 4))
+ return 1;
+ uint32 n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, (8+8) * n_points))
+ return 1;
+ for (; n_points>0; --n_points)
+ {
+ mbr->add_xy(data, data + 8);
+ data += 8+8;
+ }
+ }
+ return 0;
+}
+
+int GPolygon::area(double *ar) const
+{
+ uint32 n_linear_rings;
+ double result = -1.0;
+
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_linear_rings = uint4korr(data);
+ data += 4;
+ for (; n_linear_rings>0; --n_linear_rings)
+ {
+ double prev_x, prev_y;
+ double lr_area=0;
+ if (no_data(data, 4))
+ return 1;
+ uint32 n_points = uint4korr(data);
+ if (no_data(data, (8+8) * n_points))
+ return 1;
+ float8get(prev_x, data+4);
+ float8get(prev_y, data+(4+8));
+ data += (4+8+8);
+
+ --n_points;
+ for (; n_points>0; --n_points)
+ {
+ double x, y;
+ float8get(x, data);
+ float8get(y, data + 8);
+ lr_area+=(prev_x+x)*(prev_y-y);
+ prev_x=x;
+ prev_y=y;
+ data += (8+8);
+ }
+ lr_area=fabs(lr_area)/2;
+ if (result==-1) result=lr_area;
+ else result-=lr_area;
+ }
+ *ar=fabs(result);
+ return 0;
+}
+
+
+int GPolygon::exterior_ring(String *result) const
+{
+ uint32 n_points;
+ const char *data = m_data + 4; // skip n_linerings
+
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, n_points * POINT_DATA_SIZE))
+ return 1;
+
+ if (result->reserve(1+4+4+ n_points * POINT_DATA_SIZE))
+ return 1;
+
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbLineString);
+ result->q_append(n_points);
+ result->q_append(data, n_points * POINT_DATA_SIZE);
+
+ return 0;
+}
+
+int GPolygon::num_interior_ring(uint32 *n_int_rings) const
+{
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ *n_int_rings = uint4korr(data);
+ --(*n_int_rings);
+
+ return 0;
+}
+
+int GPolygon::interior_ring_n(uint32 num, String *result) const
+{
+ const char *data = m_data;
+ uint32 n_linear_rings;
+ uint32 n_points;
+
+ if (no_data(data, 4))
+ return 1;
+
+ n_linear_rings = uint4korr(data);
+ data += 4;
+ if ((num >= n_linear_rings) || (num < 1))
+ return -1;
+
+ for (; num > 0; --num)
+ {
+ if (no_data(data, 4))
+ return 1;
+ data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ }
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+ int points_size = n_points * POINT_DATA_SIZE;
+ data += 4;
+ if (no_data(data, points_size))
+ return 1;
+
+ if (result->reserve(1+4+4+ points_size))
+ return 1;
+
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbLineString);
+ result->q_append(n_points);
+ result->q_append(data, points_size);
+
+ return 0;
+}
+
+int GPolygon::centroid_xy(double *x, double *y) const
+{
+ uint32 n_linear_rings;
+ uint32 i;
+ double res_area, res_cx, res_cy;
+ const char *data = m_data;
+ LINT_INIT(res_area);
+ LINT_INIT(res_cx);
+ LINT_INIT(res_cy);
+
+ if (no_data(data, 4))
+ return 1;
+ n_linear_rings = uint4korr(data);
+ data += 4;
+
+ for (i = 0; i < n_linear_rings; ++i)
+ {
+ if (no_data(data, 4))
+ return 1;
+ uint32 n_points = uint4korr(data);
+ double prev_x, prev_y;
+ double cur_area = 0;
+ double cur_cx = 0;
+ double cur_cy = 0;
+
+ data += 4;
+ if (no_data(data, (8+8) * n_points))
+ return 1;
+ float8get(prev_x, data);
+ float8get(prev_y, data+8);
+ data += (8+8);
+
+ uint32 n = n_points - 1;
+ for (; n > 0; --n)
+ {
+ double x, y;
+ float8get(x, data);
+ float8get(y, data + 8);
+
+ cur_area += (prev_x + x) * (prev_y - y);
+ cur_cx += x;
+ cur_cy += y;
+ prev_x = x;
+ prev_y = y;
+ data += (8+8);
+ }
+ cur_area = fabs(cur_area) / 2;
+ cur_cx = cur_cx / (n_points - 1);
+ cur_cy = cur_cy / (n_points - 1);
+
+ if (i)
+ {
+ double d_area = res_area - cur_area;
+ if (d_area <= 0)
+ return 1;
+ res_cx = (res_area * res_cx - cur_area * cur_cx) / d_area;
+ res_cy = (res_area * res_cy - cur_area * cur_cy) / d_area;
+ }
+ else
+ {
+ res_area = cur_area;
+ res_cx = cur_cx;
+ res_cy = cur_cy;
+ }
+ }
+
+ *x = res_cx;
+ *y = res_cy;
+
+ return 0;
+}
+
+int GPolygon::centroid(String *result) const
+{
+ double x, y;
+
+ this->centroid_xy(&x, &y);
+ if (result->reserve(1 + 4 + sizeof(double) * 2))
+ return 1;
+
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbPoint);
+ result->q_append(x);
+ result->q_append(y);
+
+ return 0;
+}
+
+
+/***************************** MultiPoint *******************************/
+
+size_t GMultiPoint::get_data_size() const
+{
+ return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
+}
+
+int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ uint32 n_points = 0;
+ int np_pos = wkb->length();
+ GPoint p;
+
+ if (wkb->reserve(4, 512))
+ return 1;
+ wkb->q_append((uint32)n_points);
+
+ for (;;)
+ {
+ if (wkb->reserve(1+4, 512))
+ return 1;
+ wkb->q_append((char)wkbNDR);
+ wkb->q_append((uint32)wkbPoint);
+ if (p.init_from_text(trs, wkb))
+ return 1;
+ ++n_points;
+ if (trs->get_next_toc_type() == GTextReadStream::comma)
+ trs->get_next_symbol();
+ else
+ break;
+ }
+ wkb->WriteAtPosition(np_pos, n_points);
+
+ return 0;
+}
+
+int GMultiPoint::get_data_as_text(String *txt) const
+{
+ uint32 n_points;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+
+ n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, n_points * (8+8+WKB_HEADER_SIZE)))
+ return 1;
+
+ if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
+ return 1;
+
+ for (; n_points>0; --n_points)
+ {
+ txt->qs_append((double *)(data + WKB_HEADER_SIZE));
+ txt->qs_append(' ');
+ txt->qs_append((double *)(data + (8 + WKB_HEADER_SIZE)));
+ txt->qs_append(',');
+ data += 8+8+WKB_HEADER_SIZE;
+ }
+ txt->length(txt->length()-1);
+ return 0;
+}
+
+int GMultiPoint::get_mbr(MBR *mbr) const
+{
+ uint32 n_points;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, n_points * (8+8+WKB_HEADER_SIZE)))
+ return 1;
+ for (; n_points>0; --n_points)
+ {
+ mbr->add_xy(data + WKB_HEADER_SIZE, data + 8 + WKB_HEADER_SIZE);
+ data += (8+8+WKB_HEADER_SIZE);
+ }
+ return 0;
+}
+
+/***************************** MultiLineString *******************************/
+
+size_t GMultiLineString::get_data_size() const
+{
+ uint32 n_line_strings = 0;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_line_strings = uint4korr(data);
+ data += 4;
+
+ for (; n_line_strings>0; --n_line_strings)
+ {
+ if (no_data(data, WKB_HEADER_SIZE + 4))
+ return 1;
+ data += WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * POINT_DATA_SIZE;
+ }
+ return data - m_data;
+}
+
+int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ uint32 n_line_strings = 0;
+ int ls_pos = wkb->length();
+
+ if (wkb->reserve(4, 512))
+ return 1;
+
+ wkb->q_append((uint32)n_line_strings);
+
+ for (;;)
+ {
+ GLineString ls;
+
+ if (wkb->reserve(1+4, 512))
+ return 1;
+ wkb->q_append((char)wkbNDR);
+ wkb->q_append((uint32)wkbLineString);
+
+ if (trs->get_next_symbol() != '(')
+ {
+ trs->set_error_msg("'(' expected");
+ return 1;
+ }
+ if (ls.init_from_text(trs, wkb))
+ return 1;
+
+ if (trs->get_next_symbol() != ')')
+ {
+ trs->set_error_msg("')' expected");
+ return 1;
+ }
+ ++n_line_strings;
+ if (trs->get_next_toc_type() == GTextReadStream::comma)
+ trs->get_next_symbol();
+ else
+ break;
+ }
+ wkb->WriteAtPosition(ls_pos, n_line_strings);
+
+ return 0;
+}
+
+int GMultiLineString::get_data_as_text(String *txt) const
+{
+ uint32 n_line_strings;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_line_strings = uint4korr(data);
+ data += 4;
+ for (; n_line_strings>0; --n_line_strings)
+ {
+ if (no_data(data, (WKB_HEADER_SIZE + 4)))
+ return 1;
+ uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
+ data += WKB_HEADER_SIZE + 4;
+ if (no_data(data, n_points * (8+8)))
+ return 1;
+
+ if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
+ return 1;
+ txt->qs_append('(');
+ for (; n_points>0; --n_points)
+ {
+ txt->qs_append((double *)data);
+ txt->qs_append(' ');
+ txt->qs_append((double *)(data + 8));
+ txt->qs_append(',');
+ data += 8+8;
+ }
+ (*txt)[txt->length()-1] = ')';
+ txt->qs_append(',');
+ }
+ txt->length(txt->length() - 1);
+ return 0;
+}
+
+int GMultiLineString::get_mbr(MBR *mbr) const
+{
+ uint32 n_line_strings;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_line_strings = uint4korr(data);
+ data += 4;
+
+ for (; n_line_strings>0; --n_line_strings)
+ {
+ if (no_data(data, WKB_HEADER_SIZE + 4))
+ return 1;
+ uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
+ data += 4+WKB_HEADER_SIZE;
+ if (no_data(data, (8+8)*n_points))
+ return 1;
+
+ for (; n_points>0; --n_points)
+ {
+ mbr->add_xy(data, data + 8);
+ data += 8+8;
+ }
+ }
+ return 0;
+}
+
+int GMultiLineString::length(double *len) const
+{
+ uint32 n_line_strings;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_line_strings = uint4korr(data);
+ data += 4;
+ *len=0;
+ for (; n_line_strings>0; --n_line_strings)
+ {
+ double ls_len;
+ GLineString ls;
+ data += WKB_HEADER_SIZE;
+ ls.init_from_wkb(data, m_data_end - data);
+ if (ls.length(&ls_len))
+ return 1;
+ *len+=ls_len;
+ data += ls.get_data_size();
+ }
+ return 0;
+}
+
+int GMultiLineString::is_closed(int *closed) const
+{
+ uint32 n_line_strings;
+ const char *data = m_data;
+ if (no_data(data, 1))
+ return 1;
+ n_line_strings = uint4korr(data);
+ data += 4 + WKB_HEADER_SIZE;
+ for (; n_line_strings>0; --n_line_strings)
+ {
+ GLineString ls;
+ ls.init_from_wkb(data, m_data_end - data);
+ if (ls.is_closed(closed))
+ return 1;
+ if (!*closed)
+ return 0;
+ data += ls.get_data_size() + WKB_HEADER_SIZE;
+ }
+ return 0;
+}
+
+/***************************** MultiPolygon *******************************/
+
+size_t GMultiPolygon::get_data_size() const
+{
+ uint32 n_polygons;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_polygons = uint4korr(data);
+ data += 4;
+
+ for (; n_polygons>0; --n_polygons)
+ {
+ if (no_data(data, 4 + WKB_HEADER_SIZE))
+ return 1;
+ uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
+ data += 4 + WKB_HEADER_SIZE;
+
+ for (; n_linear_rings > 0; --n_linear_rings)
+ {
+ data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ }
+ }
+ return data - m_data;
+}
+
+int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ uint32 n_polygons = 0;
+ int np_pos = wkb->length();
+ GPolygon p;
+
+ if (wkb->reserve(4, 512))
+ return 1;
+
+ wkb->q_append((uint32)n_polygons);
+
+ for (;;)
+ {
+ if (wkb->reserve(1+4, 512))
+ return 1;
+ wkb->q_append((char)wkbNDR);
+ wkb->q_append((uint32)wkbPolygon);
+
+ if (trs->get_next_symbol() != '(')
+ {
+ trs->set_error_msg("'(' expected");
+ return 1;
+ }
+ if (p.init_from_text(trs, wkb))
+ return 1;
+ if (trs->get_next_symbol() != ')')
+ {
+ trs->set_error_msg("')' expected");
+ return 1;
+ }
+ ++n_polygons;
+ if (trs->get_next_toc_type() == GTextReadStream::comma)
+ trs->get_next_symbol();
+ else
+ break;
+ }
+ wkb->WriteAtPosition(np_pos, n_polygons);
+ return 0;
+}
+
+int GMultiPolygon::get_data_as_text(String *txt) const
+{
+ uint32 n_polygons;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_polygons = uint4korr(data);
+ data += 4;
+
+ for (; n_polygons>0; --n_polygons)
+ {
+ if (no_data(data, 4 + WKB_HEADER_SIZE))
+ return 1;
+ data += WKB_HEADER_SIZE;
+ uint32 n_linear_rings = uint4korr(data);
+ data += 4;
+
+ if (txt->reserve(1, 512))
+ return 1;
+ txt->q_append('(');
+ for (; n_linear_rings>0; --n_linear_rings)
+ {
+ if (no_data(data, 4))
+ return 1;
+ uint32 n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, (8+8)*n_points)) return 1;
+
+ if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points,
+ 512)) return 1;
+ txt->qs_append('(');
+ for (; n_points>0; --n_points)
+ {
+ txt->qs_append((double *)data);
+ txt->qs_append(' ');
+ txt->qs_append((double *)(data + 8));
+ txt->qs_append(',');
+ data += 8+8;
+ }
+ (*txt)[txt->length()-1] = ')';
+ txt->qs_append(',');
+ }
+ (*txt)[txt->length()-1] = ')';
+ txt->qs_append(',');
+ }
+ txt->length(txt->length() - 1);
+ return 0;
+}
+
+int GMultiPolygon::get_mbr(MBR *mbr) const
+{
+ uint32 n_polygons;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_polygons = uint4korr(data);
+ data += 4;
+
+ for (; n_polygons>0; --n_polygons)
+ {
+ if (no_data(data, 4+WKB_HEADER_SIZE))
+ return 1;
+ uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
+ data += WKB_HEADER_SIZE + 4;
+
+ for (; n_linear_rings>0; --n_linear_rings)
+ {
+ if (no_data(data, 4))
+ return 1;
+ uint32 n_points = uint4korr(data);
+ data += 4;
+ if (no_data(data, (8+8)*n_points))
+ return 1;
+
+ for (; n_points>0; --n_points)
+ {
+ mbr->add_xy(data, data + 8);
+ data += 8+8;
+ }
+ }
+ }
+ return 0;
+}
+
+
+int GMultiPolygon::area(double *ar) const
+{
+ uint32 n_polygons;
+ const char *data = m_data;
+ double result = 0;
+ if (no_data(data, 4))
+ return 1;
+ n_polygons = uint4korr(data);
+ data += 4;
+
+ for (; n_polygons>0; --n_polygons)
+ {
+ double p_area;
+
+ GPolygon p;
+ data += WKB_HEADER_SIZE;
+ p.init_from_wkb(data, m_data_end - data);
+ if (p.area(&p_area))
+ return 1;
+ result += p_area;
+ data += p.get_data_size();
+ }
+ *ar = result;
+ return 0;
+}
+
+int GMultiPolygon::centroid(String *result) const
+{
+ uint32 n_polygons;
+ uint i;
+ GPolygon p;
+ double res_area, res_cx, res_cy;
+ double cur_area, cur_cx, cur_cy;
+
+ LINT_INIT(res_area);
+ LINT_INIT(res_cx);
+ LINT_INIT(res_cy);
+
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_polygons = uint4korr(data);
+ data += 4;
+
+ for (i = 0; i < n_polygons; ++i)
+ {
+ data += WKB_HEADER_SIZE;
+ p.init_from_wkb(data, m_data_end - data);
+ if (p.area(&cur_area))
+ return 1;
+
+ if (p.centroid_xy(&cur_cx, &cur_cy))
+ return 1;
+
+ if (i)
+ {
+ double sum_area = res_area + cur_area;
+ res_cx = (res_area * res_cx + cur_area * cur_cx) / sum_area;
+ res_cy = (res_area * res_cy + cur_area * cur_cy) / sum_area;
+ }
+ else
+ {
+ res_area = cur_area;
+ res_cx = cur_cx;
+ res_cy = cur_cy;
+ }
+
+ data += p.get_data_size();
+ }
+
+ if (result->reserve(1 + 4 + sizeof(double) * 2))
+ return 1;
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkbPoint);
+ result->q_append(res_cx);
+ result->q_append(res_cy);
+
+ return 0;
+}
+
+/***************************** GeometryCollection *******************************/
+
+size_t GGeometryCollection::get_data_size() const
+{
+ uint32 n_objects;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_objects = uint4korr(data);
+ data += 4;
+
+ for (; n_objects>0; --n_objects)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ uint32 wkb_type = uint4korr(data + sizeof(char));
+ data += WKB_HEADER_SIZE;
+
+ Geometry geom;
+
+ if (geom.init(wkb_type))
+ return 0;
+
+ geom.init_from_wkb(data, m_data_end - data);
+ size_t object_size=geom.get_data_size();
+ data += object_size;
+ }
+ return data - m_data;
+}
+
+int GGeometryCollection::init_from_text(GTextReadStream *trs, String *wkb)
+{
+ uint32 n_objects = 0;
+ int no_pos = wkb->length();
+ Geometry g;
+
+ if (wkb->reserve(4, 512))
+ return 1;
+ wkb->q_append((uint32)n_objects);
+
+ for (;;)
+ {
+ if (g.create_from_wkt(trs, wkb))
+ return 1;
+
+ if (g.get_class_info()->m_type_id==wkbGeometryCollection)
+ {
+ trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
+ return 1;
+ }
+ ++n_objects;
+ if (trs->get_next_toc_type() == GTextReadStream::comma)
+ trs->get_next_symbol();
+ else break;
+ }
+ wkb->WriteAtPosition(no_pos, n_objects);
+
+ return 0;
+}
+
+int GGeometryCollection::get_data_as_text(String *txt) const
+{
+ uint32 n_objects;
+ const char *data = m_data;
+ Geometry geom;
+ if (no_data(data, 4))
+ return 1;
+ n_objects = uint4korr(data);
+ data += 4;
+
+ for (; n_objects>0; --n_objects)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ uint32 wkb_type = uint4korr(data + sizeof(char));
+ data += WKB_HEADER_SIZE;
+
+ if (geom.init(wkb_type))
+ return 1;
+ geom.init_from_wkb(data, m_data_end - data);
+ if (geom.as_wkt(txt))
+ return 1;
+ data += geom.get_data_size();
+ txt->reserve(1, 512);
+ txt->q_append(',');
+ }
+ txt->length(txt->length() - 1);
+ return 0;
+}
+
+int GGeometryCollection::get_mbr(MBR *mbr) const
+{
+ uint32 n_objects;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_objects = uint4korr(data);
+ data += 4;
+ for (; n_objects>0; --n_objects)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ uint32 wkb_type = uint4korr(data + sizeof(char));
+ data += WKB_HEADER_SIZE;
+ Geometry geom;
+
+ if (geom.init(wkb_type))
+ return 1;
+ geom.init_from_wkb(data, m_data_end - data);
+ geom.get_mbr(mbr);
+ data += geom.get_data_size();
+ }
+ return 0;
+}
+
+int GGeometryCollection::num_geometries(uint32 *num) const
+{
+ *num = uint4korr(m_data);
+ return 0;
+}
+
+int GGeometryCollection::geometry_n(uint32 num, String *result) const
+{
+ const char *data = m_data;
+ uint32 n_objects;
+ if (no_data(data, 4))
+ return 1;
+ n_objects = uint4korr(data);
+ data += 4;
+
+ if ((num > n_objects) || (num < 1))
+ {
+ return -1;
+ }
+ for (; num > 0; --num)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ uint32 wkb_type = uint4korr(data + sizeof(char));
+ data += WKB_HEADER_SIZE;
+
+ Geometry geom;
+ if (geom.init(wkb_type))
+ return 1;
+ geom.init_from_wkb(data, m_data_end - data);
+ if (num == 1)
+ {
+ if (result->reserve(1+4+geom.get_data_size()))
+ return 1;
+ result->q_append((char)wkbNDR);
+ result->q_append((uint32)wkb_type);
+ result->q_append(data, geom.get_data_size());
+ break;
+ }
+ else
+ {
+ data += geom.get_data_size();
+ }
+ }
+ return 0;
+}
+
+int GGeometryCollection::dimension(uint32 *dim) const
+{
+ uint32 n_objects;
+ *dim = 0;
+ const char *data = m_data;
+ if (no_data(data, 4))
+ return 1;
+ n_objects = uint4korr(data);
+ data += 4;
+
+ for (; n_objects > 0; --n_objects)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ uint32 wkb_type = uint4korr(data + sizeof(char));
+ data += WKB_HEADER_SIZE;
+
+ uint32 d;
+
+ Geometry geom;
+ if (geom.init(wkb_type))
+ return 1;
+ geom.init_from_wkb(data, m_data_end - data);
+ if (geom.dimension(&d))
+ return 1;
+
+ if (d > *dim)
+ *dim = d;
+ data += geom.get_data_size();
+ }
+ return 0;
+}
+
+/***************************** /objects *******************************/
diff --git a/sql/spatial.h b/sql/spatial.h
new file mode 100644
index 00000000000..3f09e86e823
--- /dev/null
+++ b/sql/spatial.h
@@ -0,0 +1,497 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 _spatial_h
+#define _spatial_h
+
+const uint POINT_DATA_SIZE = 8+8;
+const uint WKB_HEADER_SIZE = 1+4;
+
+struct stPoint2D
+{
+ double x;
+ double y;
+};
+
+struct stLinearRing
+{
+ size_t n_points;
+ stPoint2D points;
+};
+
+/***************************** MBR *******************************/
+
+struct MBR
+{
+ MBR()
+ {
+ xmin=DBL_MAX;
+ ymin=DBL_MAX;
+ xmax=-DBL_MAX;
+ ymax=-DBL_MAX;
+ }
+
+ MBR(const double &_xmin, const double &_ymin,
+ const double &_xmax, const double &_ymax)
+ {
+ xmin=_xmin;
+ ymin=_ymin;
+ xmax=_xmax;
+ ymax=_ymax;
+ }
+
+ MBR(const stPoint2D &min, const stPoint2D &max)
+ {
+ xmin=min.x;
+ ymin=min.y;
+ xmax=max.x;
+ ymax=max.y;
+ }
+
+ double xmin;
+ double ymin;
+ double xmax;
+ double ymax;
+
+ void add_xy(double x, double y)
+ {
+ /* Not using "else" for proper one point MBR calculation */
+ if (x<xmin)
+ {
+ xmin=x;
+ }
+ if (x>xmax)
+ {
+ xmax=x;
+ }
+ if (y<ymin)
+ {
+ ymin=y;
+ }
+ if (y>ymax)
+ {
+ ymax=y;
+ }
+ }
+
+ void add_xy(const char *px, const char *py)
+ {
+ double x, y;
+ float8get(x, px);
+ float8get(y, py);
+ /* Not using "else" for proper one point MBR calculation */
+ if (x<xmin)
+ {
+ xmin=x;
+ }
+ if (x>xmax)
+ {
+ xmax=x;
+ }
+ if (y<ymin)
+ {
+ ymin=y;
+ }
+ if (y>ymax)
+ {
+ ymax=y;
+ }
+ }
+
+ void add_mbr(const MBR *mbr)
+ {
+ if (mbr->xmin<xmin)
+ {
+ xmin=mbr->xmin;
+ }
+ if (mbr->xmax>xmax)
+ {
+ xmax=mbr->xmax;
+ }
+ if (mbr->ymin<ymin)
+ {
+ ymin=mbr->ymin;
+ }
+ if (mbr->ymax>ymax)
+ {
+ ymax=mbr->ymax;
+ }
+ }
+
+ int equals(const MBR *mbr)
+ {
+ return ((mbr->xmin == xmin) && (mbr->ymin == ymin) &&
+ (mbr->xmax == xmax) && (mbr->ymax == ymax));
+ }
+
+ int disjoint(const MBR *mbr)
+ {
+ return ((mbr->xmin > xmax) || (mbr->ymin > ymax) ||
+ (mbr->xmax < xmin) || (mbr->ymax < ymin));
+ }
+
+ int intersects(const MBR *mbr)
+ {
+ return !disjoint(mbr);
+ }
+
+ int touches(const MBR *mbr)
+ {
+ return ((((mbr->xmin == xmax) || (mbr->xmax == xmin)) &&
+ ((mbr->ymin >= ymin) && (mbr->ymin <= ymax) ||
+ (mbr->ymax >= ymin) && (mbr->ymax <= ymax))) ||
+ (((mbr->ymin == ymax) || (mbr->ymax == ymin)) &&
+ ((mbr->xmin >= xmin) && (mbr->xmin <= xmax) ||
+ (mbr->xmax >= xmin) && (mbr->xmax <= xmax))));
+ }
+
+ int within(const MBR *mbr)
+ {
+ return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) &&
+ (mbr->xmax >= xmax) && (mbr->ymax >= ymax));
+ }
+
+ int contains(const MBR *mbr)
+ {
+ return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) &&
+ (mbr->xmax <= xmax) && (mbr->ymax <= ymax));
+ }
+
+ bool inner_point(double x, double y) const
+ {
+ return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>x);
+ }
+
+ int overlaps(const MBR *mbr)
+ {
+ int lb = mbr->inner_point(xmin, ymin);
+ int rb = mbr->inner_point(xmax, ymin);
+ int rt = mbr->inner_point(xmax, ymax);
+ int lt = mbr->inner_point(xmin, ymax);
+
+ int a = lb+rb+rt+lt;
+ return (a>0) && (a<4) && (!within(mbr));
+ }
+};
+
+
+/***************************** Geometry *******************************/
+
+class Geometry;
+
+typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *);
+typedef int (Geometry::*GF_GetDataAsText)(String *) const;
+typedef size_t (Geometry::*GF_GetDataSize)() const;
+typedef int (Geometry::*GF_GetMBR)(MBR *) const;
+
+typedef int (Geometry::*GF_GetD)(double *) const;
+typedef int (Geometry::*GF_GetI)(int *) const;
+typedef int (Geometry::*GF_GetUI)(uint32 *) const;
+typedef int (Geometry::*GF_GetWS)(String *) const;
+typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const;
+
+#define GEOM_METHOD_PRESENT(geom_obj, method)\
+ (geom_obj.m_vmt->method != &Geometry::method)
+
+class Geometry
+{
+public:
+ enum wkbType
+ {
+ wkbPoint = 1,
+ wkbLineString = 2,
+ wkbPolygon = 3,
+ wkbMultiPoint = 4,
+ wkbMultiLineString = 5,
+ wkbMultiPolygon = 6,
+ wkbGeometryCollection = 7
+ };
+ enum wkbByteOrder
+ {
+ wkbXDR = 0, /* Big Endian */
+ wkbNDR = 1 /* Little Endian */
+ };
+
+
+ class GClassInfo
+ {
+ public:
+ GF_InitFromText init_from_text;
+ GF_GetDataAsText get_data_as_text;
+ GF_GetDataSize get_data_size;
+ GF_GetMBR get_mbr;
+ GF_GetD get_x;
+ GF_GetD get_y;
+ GF_GetD length;
+ GF_GetD area;
+
+ GF_GetI is_closed;
+
+ GF_GetUI num_interior_ring;
+ GF_GetUI num_points;
+ GF_GetUI num_geometries;
+ GF_GetUI dimension;
+
+ GF_GetWS start_point;
+ GF_GetWS end_point;
+ GF_GetWS exterior_ring;
+ GF_GetWS centroid;
+
+ GF_GetUIWS point_n;
+ GF_GetUIWS interior_ring_n;
+ GF_GetUIWS geometry_n;
+
+ int m_type_id;
+ const char *m_name;
+ GClassInfo *m_next_rt;
+ };
+ GClassInfo *m_vmt;
+
+ const GClassInfo *get_class_info() const { return m_vmt; }
+ size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); }
+
+ int init_from_text(GTextReadStream *trs, String *wkb)
+ { return (this->*m_vmt->init_from_text)(trs, wkb); }
+
+ int get_data_as_text(String *txt) const
+ { return (this->*m_vmt->get_data_as_text)(txt); }
+
+ int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); }
+ int dimension(uint32 *dim) const
+ { return (this->*m_vmt->dimension)(dim); }
+
+ int get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
+ int get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
+ int length(double *len) const { return (this->*m_vmt->length)(len); }
+ int area(double *ar) const { return (this->*m_vmt->area)(ar); }
+
+ int is_closed(int *closed) const
+ { return (this->*m_vmt->is_closed)(closed); }
+
+ int num_interior_ring(uint32 *n_int_rings) const
+ { return (this->*m_vmt->num_interior_ring)(n_int_rings); }
+ int num_points(uint32 *n_points) const
+ { return (this->*m_vmt->num_points)(n_points); }
+
+ int num_geometries(uint32 *num) const
+ { return (this->*m_vmt->num_geometries)(num); }
+
+ int start_point(String *point) const
+ { return (this->*m_vmt->start_point)(point); }
+ int end_point(String *point) const
+ { return (this->*m_vmt->end_point)(point); }
+ int exterior_ring(String *ring) const
+ { return (this->*m_vmt->exterior_ring)(ring); }
+ int centroid(String *point) const
+ { return (this->*m_vmt->centroid)(point); }
+
+ int point_n(uint32 num, String *result) const
+ { return (this->*m_vmt->point_n)(num, result); }
+ int interior_ring_n(uint32 num, String *result) const
+ { return (this->*m_vmt->interior_ring_n)(num, result); }
+ int geometry_n(uint32 num, String *result) const
+ { return (this->*m_vmt->geometry_n)(num, result); }
+
+public:
+ int create_from_wkb(const char *data, uint32 data_len);
+ int create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream=1);
+ int init(int type_id)
+ {
+ m_vmt = find_class(type_id);
+ return !m_vmt;
+ }
+ int new_geometry(const char *name, size_t len)
+ {
+ m_vmt = find_class(name, len);
+ return !m_vmt;
+ }
+
+ int as_wkt(String *wkt) const
+ {
+ if (wkt->reserve(strlen(get_class_info()->m_name) + 2, 512))
+ return 1;
+ wkt->qs_append(get_class_info()->m_name);
+ wkt->qs_append('(');
+ if (get_data_as_text(wkt))
+ return 1;
+ wkt->qs_append(')');
+ return 0;
+ }
+
+ void init_from_wkb(const char *data, uint32 data_len)
+ {
+ m_data = data;
+ m_data_end = data + data_len;
+ }
+
+ void shift_wkb_header()
+ {
+ m_data += WKB_HEADER_SIZE;
+ }
+
+ int envelope(String *result) const;
+
+protected:
+ static GClassInfo *find_class(int type_id);
+ static GClassInfo *find_class(const char *name, size_t len);
+
+ bool no_data(const char *cur_data, uint32 data_amount) const
+ {
+ return (cur_data + data_amount > m_data_end);
+ }
+
+ const char *m_data;
+ const char *m_data_end;
+};
+
+#define SIZEOF_STORED_DOUBLE 8
+
+/***************************** Point *******************************/
+
+class GPoint: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+
+ int get_xy(double *x, double *y) const
+ {
+ const char *data = m_data;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
+ float8get(*x, data);
+ float8get(*y, data + SIZEOF_STORED_DOUBLE);
+ return 0;
+ }
+
+ int get_x(double *x) const
+ {
+ if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1;
+ float8get(*x, m_data);
+ return 0;
+ }
+
+ int get_y(double *y) const
+ {
+ const char *data = m_data;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
+ float8get(*y, data + SIZEOF_STORED_DOUBLE);
+ return 0;
+ }
+
+ int dimension(uint32 *dim) const { *dim = 0; return 0; }
+};
+
+/***************************** LineString *******************************/
+
+class GLineString: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+
+ int length(double *len) const;
+ int is_closed(int *closed) const;
+ int num_points(uint32 *n_points) const;
+ int start_point(String *point) const;
+ int end_point(String *point) const;
+ int point_n(uint32 n, String *result) const;
+ int dimension(uint32 *dim) const { *dim = 1; return 0; }
+// IsRing
+};
+
+/***************************** Polygon *******************************/
+
+class GPolygon: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+
+ int area(double *ar) const;
+ int exterior_ring(String *result) const;
+ int num_interior_ring(uint32 *n_int_rings) const;
+ int interior_ring_n(uint32 num, String *result) const;
+ int centroid_xy(double *x, double *y) const;
+ int centroid(String *result) const;
+ int dimension(uint32 *dim) const { *dim = 2; return 0; }
+// PointOnSurface
+};
+
+/***************************** MultiPoint *******************************/
+
+class GMultiPoint: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+ int dimension(uint32 *dim) const { *dim = 0; return 0; }
+};
+
+/***************************** MultiLineString *******************************/
+
+class GMultiLineString: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+
+ int length(double *len) const;
+ int is_closed(int *closed) const;
+ int dimension(uint32 *dim) const { *dim = 1; return 0; }
+};
+
+/***************************** MultiPolygon *******************************/
+
+class GMultiPolygon: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+
+ int area(double *ar) const;
+ int centroid(String *result) const;
+ int dimension(uint32 *dim) const { *dim = 2; return 0; }
+// PointOnSurface
+};
+
+/***************************** GeometryCollection *******************************/
+
+class GGeometryCollection: public Geometry
+{
+public:
+ size_t get_data_size() const;
+ int init_from_text(GTextReadStream *trs, String *wkb);
+ int get_data_as_text(String *txt) const;
+ int get_mbr(MBR *mbr) const;
+
+ int num_geometries(uint32 *num) const;
+ int geometry_n(uint32 num, String *result) const;
+ int dimension(uint32 *dim) const;
+};
+
+#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ee9d3f1c1ea..40dddaad08e 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -29,53 +29,8 @@
#include "sql_acl.h"
#include "hash_filo.h"
#include <m_ctype.h>
-#include <assert.h>
#include <stdarg.h>
-struct acl_host_and_ip
-{
- char *hostname;
- long ip,ip_mask; // Used with masked ip:s
-};
-
-
-class ACL_ACCESS {
-public:
- ulong sort;
- ulong access;
-};
-
-
-/* ACL_HOST is used if no host is specified */
-
-class ACL_HOST :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *db;
-};
-
-
-class ACL_USER :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- uint hostname_length;
- USER_RESOURCES user_resource;
- char *user,*password;
- ulong salt[2];
- enum SSL_type ssl_type;
- const char *ssl_cipher, *x509_issuer, *x509_subject;
-};
-
-
-class ACL_DB :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *user,*db;
-};
-
class acl_entry :public hash_filo_element
{
@@ -99,10 +54,11 @@ static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
static bool initialized=0;
static bool allow_all_hosts=1;
-static HASH acl_check_hosts, hash_tables;
+static HASH acl_check_hosts, column_priv_hash;
static DYNAMIC_ARRAY acl_wild_hosts;
static hash_filo *acl_cache;
static uint grant_version=0;
+static uint priv_version=0; /* Version of priv tables. incremented by acl_init */
static ulong get_access(TABLE *form,uint fieldnr);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...);
@@ -143,7 +99,11 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
(hash_get_key) acl_entry_get_key,
(hash_free_key) free);
if (dont_read_acl_tables)
+ {
DBUG_RETURN(0); /* purecov: tested */
+ }
+
+ priv_version++; /* Privileges updated */
/*
To be able to run this from boot, we allocate a temporary THD
@@ -151,6 +111,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals();
+ /* Use passwords according to command line option */
+ use_old_passwords= opt_old_passwords;
acl_cache->clear(1); // Clear locked hostname cache
thd->db= my_strdup("mysql",MYF(0));
@@ -186,8 +148,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_HOST host;
- update_hostname(&host.host,get_field(&mem, table,0));
- host.db= get_field(&mem, table,1);
+ update_hostname(&host.host,get_field(&mem, table->field[0]));
+ host.db= get_field(&mem, table->field[1]);
host.access= get_access(table,2);
host.access= fix_rights_for_db(host.access);
host.sort= get_sort(2,host.host.hostname,host.db);
@@ -215,15 +177,22 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
protocol_version=9; /* purecov: tested */
}
- DBUG_PRINT("info",("user table fields: %d",table->fields));
+ DBUG_PRINT("info",("user table fields: %d, password length: %d",
+ table->fields, table->field[2]->field_length));
+ if (table->field[2]->field_length < 45 && !use_old_passwords)
+ {
+ sql_print_error("mysql.user table is not updated to new password format; Disabling new password usage until mysql_fix_privilege_tables is run");
+ use_old_passwords= 1;
+ }
+
allow_all_hosts=0;
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
uint length=0;
- update_hostname(&user.host,get_field(&mem, table,0));
- user.user=get_field(&mem, table,1);
- user.password=get_field(&mem, table,2);
+ update_hostname(&user.host,get_field(&mem, table->field[0]));
+ user.user=get_field(&mem, table->field[1]);
+ user.password=get_field(&mem, table->field[2]);
if (user.password && (length=(uint) strlen(user.password)) == 8 &&
protocol_version == PROTOCOL_VERSION)
{
@@ -231,13 +200,18 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
"Found old style password for user '%s'. Ignoring user. (You may want to restart mysqld using --old-protocol)",
user.user ? user.user : ""); /* purecov: tested */
}
- else if (length % 8) // This holds true for passwords
+ else /* non empty and not short passwords */
{
- sql_print_error(
- "Found invalid password for user: '%s@%s'; Ignoring user",
- user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : ""); /* purecov: tested */
- continue; /* purecov: tested */
+ user.pversion=get_password_version(user.password);
+ /* Only passwords of specific lengths depending on version are allowed */
+ if ( (!user.pversion && length % 8) || (user.pversion && length!=45 ))
+ {
+ sql_print_error(
+ "Found invalid password for user: '%s@%s'; Ignoring user",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : ""); /* purecov: tested */
+ continue; /* purecov: tested */
+ }
}
get_salt_from_password(user.salt,user.password);
user.access=get_access(table,3) & GLOBAL_ACLS;
@@ -246,7 +220,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
(uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{
- char *ssl_type=get_field(&mem, table, 24);
+ char *ssl_type=get_field(&mem, table->field[24]);
if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE;
else if (!strcmp(ssl_type, "ANY"))
@@ -256,15 +230,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
- user.ssl_cipher= get_field(&mem, table, 25);
- user.x509_issuer= get_field(&mem, table, 26);
- user.x509_subject= get_field(&mem, table, 27);
+ user.ssl_cipher= get_field(&mem, table->field[25]);
+ user.x509_issuer= get_field(&mem, table->field[26]);
+ user.x509_subject= get_field(&mem, table->field[27]);
- char *ptr = get_field(&mem, table, 28);
+ char *ptr = get_field(&mem, table->field[28]);
user.user_resource.questions=atoi(ptr);
- ptr = get_field(&mem, table, 29);
+ ptr = get_field(&mem, table->field[29]);
user.user_resource.updates=atoi(ptr);
- ptr = get_field(&mem, table, 30);
+ ptr = get_field(&mem, table->field[30]);
user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections)
@@ -303,14 +277,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_DB db;
- update_hostname(&db.host,get_field(&mem, table,0));
- db.db=get_field(&mem, table,1);
+ update_hostname(&db.host,get_field(&mem, table->field[0]));
+ db.db=get_field(&mem, table->field[1]);
if (!db.db)
{
sql_print_error("Found an entry in the 'db' table with empty database name; Skipped");
continue;
}
- db.user=get_field(&mem, table,2);
+ db.user=get_field(&mem, table->field[2]);
db.access=get_access(table,3);
db.access=fix_rights_for_db(db.access);
db.sort=get_sort(3,db.host.hostname,db.db,db.user);
@@ -392,6 +366,7 @@ void acl_reload(THD *thd)
if (acl_init(thd, 0))
{ // Error. Revert to old list
+ DBUG_PRINT("error",("Reverting to old privileges"));
acl_free(); /* purecov: inspected */
acl_hosts=old_acl_hosts;
acl_users=old_acl_users;
@@ -422,7 +397,7 @@ static ulong get_access(TABLE *form, uint fieldnr)
{
ulong access_bits=0,bit;
char buff[2];
- String res(buff,sizeof(buff));
+ String res(buff,sizeof(buff),&my_charset_latin1);
Field **pos;
for (pos=form->field+fieldnr, bit=1;
@@ -431,7 +406,7 @@ static ulong get_access(TABLE *form, uint fieldnr)
pos++ , bit<<=1)
{
(*pos)->val_str(&res,&res);
- if (toupper(res[0]) == 'Y')
+ if (my_toupper(&my_charset_latin1, res[0]) == 'Y')
access_bits|= bit;
}
return access_bits;
@@ -484,16 +459,49 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
/*
+ Prepare crypted scramble to be sent to the client
+*/
+
+void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
+{
+ /* Binary password format to be used for generation*/
+ char bin_password[SCRAMBLE41_LENGTH];
+ /* Generate new long scramble for the thread */
+ create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
+ thd->scramble[SCRAMBLE41_LENGTH]=0;
+ /* Get binary form, First 4 bytes of prepared scramble is salt */
+ get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,
+ (unsigned char*) bin_password);
+ /* Store "*" as identifier for old passwords */
+ if (!acl_user->pversion)
+ prepared_scramble[0]='*';
+ /* Finally encrypt password to get prepared scramble */
+ password_crypt(thd->scramble, prepared_scramble+4, bin_password,
+ SCRAMBLE41_LENGTH);
+}
+
+
+/*
Get master privilges for user (priviliges for all tables).
Required before connecting to MySQL
+
+ as we have 2 stage handshake now we cache user not to lookup
+ it second time. At the second stage we do not lookup user in case
+ we already know it;
+
*/
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_user,
- bool old_ver, USER_RESOURCES *mqh)
+ bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble,
+ uint *cur_priv_version,ACL_USER** hint_user)
{
ulong user_access=NO_ACCESS;
- *priv_user=(char*) user;
+ *priv_user= (char*) user;
+ bool password_correct= 0;
+ int stage= (*hint_user != NULL); /* NULL passed as first stage */
+ ACL_USER *acl_user= NULL;
+
DBUG_ENTER("acl_getroot");
bzero(mqh,sizeof(USER_RESOURCES));
@@ -504,126 +512,176 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
}
VOID(pthread_mutex_lock(&acl_cache->lock));
+
/*
Get possible access from user_list. This is or'ed to others not
fully specified
+
+ If we have cached user use it, in other case look it up.
*/
- for (uint i=0 ; i < acl_users.elements ; i++)
+
+ if (stage && (*cur_priv_version==priv_version))
+ acl_user=*hint_user;
+ else
+ for (uint i=0 ; i < acl_users.elements ; i++)
+ {
+ ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*);
+ if (!acl_user_search->user || !strcmp(user,acl_user_search->user))
+ {
+ if (compare_hostname(&acl_user_search->host,host,ip))
+ {
+ /* Found mathing user */
+ acl_user=acl_user_search;
+ /* Store it as a cache */
+ *hint_user=acl_user;
+ *cur_priv_version=priv_version;
+ break;
+ }
+ }
+ }
+
+
+ /* Now we have acl_user found and may start our checks */
+
+ if (acl_user)
{
- ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
- if (!acl_user->user || !strcmp(user,acl_user->user))
+ /* Password should present for both or absend for both */
+ if (!acl_user->password && !*password ||
+ (acl_user->password && *password))
{
- if (compare_hostname(&acl_user->host,host,ip))
+ /* Quick check and accept for empty passwords*/
+ if (!acl_user->password && !*password)
+ password_correct=1;
+ else /* Normal password presents */
{
- if (!acl_user->password && !*password ||
- (acl_user->password && *password &&
- !check_scramble(password,message,acl_user->salt,
- (my_bool) old_ver)))
- {
-#ifdef HAVE_OPENSSL
- Vio *vio=thd->net.vio;
- /*
- In this point we know that user is allowed to connect
- from given host by given username/password pair. Now
- we check if SSL is required, if user is using SSL and
- if X509 certificate attributes are OK
- */
- switch (acl_user->ssl_type) {
- case SSL_TYPE_NOT_SPECIFIED: // Impossible
- case SSL_TYPE_NONE: /* SSL is not required to connect */
- user_access=acl_user->access;
- break;
- case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
- if (vio_type(vio) == VIO_TYPE_SSL)
- user_access=acl_user->access;
- break;
- case SSL_TYPE_X509: /* Client should have any valid certificate. */
- /*
- Connections with non-valid certificates are dropped already
- in sslaccept() anyway, so we do not check validity here.
- */
- if (SSL_get_peer_certificate(vio->ssl_))
- user_access=acl_user->access;
- break;
- case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
- /*
- We do not check for absence of SSL because without SSL it does
- not pass all checks here anyway.
- If cipher name is specified, we compare it to actual cipher in
- use.
- */
- if (acl_user->ssl_cipher)
- {
- DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
- acl_user->ssl_cipher,
- SSL_get_cipher(vio->ssl_)));
- if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
- user_access=acl_user->access;
- else
- {
- user_access=NO_ACCESS;
- break;
- }
- }
- /* Prepare certificate (if exists) */
- DBUG_PRINT("info",("checkpoint 1"));
- X509* cert=SSL_get_peer_certificate(vio->ssl_);
- DBUG_PRINT("info",("checkpoint 2"));
- /* If X509 issuer is speified, we check it... */
- if (acl_user->x509_issuer)
- {
- DBUG_PRINT("info",("checkpoint 3"));
- char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
- acl_user->x509_issuer, ptr));
- if (strcmp(acl_user->x509_issuer, ptr))
- {
- user_access=NO_ACCESS;
- free(ptr);
- break;
- }
- user_access=acl_user->access;
- free(ptr);
- }
- DBUG_PRINT("info",("checkpoint 4"));
- /* X509 subject is specified, we check it .. */
- if (acl_user->x509_subject)
- {
- char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
- acl_user->x509_subject, ptr));
- if (strcmp(acl_user->x509_subject,ptr))
- user_access=NO_ACCESS;
- else
- user_access=acl_user->access;
- free(ptr);
- }
- break;
+ /* New version password is checked differently */
+ if (acl_user->pversion)
+ {
+ if (stage) /* We check password only on the second stage */
+ {
+ if (!validate_password(password,message,acl_user->salt))
+ password_correct=1;
+ }
+ else /* First stage - just prepare scramble */
+ prepare_scramble(thd,acl_user,prepared_scramble);
+ }
+ /* Old way to check password */
+ else
+ {
+ /* Checking the scramble at any stage. First - old clients */
+ if (!check_scramble(password,message,acl_user->salt,
+ (my_bool) old_ver))
+ password_correct=1;
+ else if (!stage) /* Here if password incorrect */
+ {
+ /* At the first stage - prepare scramble */
+ prepare_scramble(thd,acl_user,prepared_scramble);
}
-#else /* HAVE_OPENSSL */
+ }
+ }
+ }
+ }
+
+ /* If user not found password_correct will also be zero */
+ if (!password_correct)
+ goto unlock_and_exit;
+
+ /* OK. User found and password checked continue validation */
+
+#ifdef HAVE_OPENSSL
+ {
+ Vio *vio=thd->net.vio;
+ /*
+ In this point we know that user is allowed to connect
+ from given host by given username/password pair. Now
+ we check if SSL is required, if user is using SSL and
+ if X509 certificate attributes are OK
+ */
+ switch (acl_user->ssl_type) {
+ case SSL_TYPE_NOT_SPECIFIED: // Impossible
+ case SSL_TYPE_NONE: /* SSL is not required to connect */
+ user_access=acl_user->access;
+ break;
+ case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
+ if (vio_type(vio) == VIO_TYPE_SSL)
+ user_access=acl_user->access;
+ break;
+ case SSL_TYPE_X509: /* Client should have any valid certificate. */
+ /*
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+ */
+ if (SSL_get_peer_certificate(vio->ssl_))
+ user_access=acl_user->access;
+ break;
+ case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
+ /*
+ We do not check for absence of SSL because without SSL it does
+ not pass all checks here anyway.
+ If cipher name is specified, we compare it to actual cipher in
+ use.
+ */
+ if (acl_user->ssl_cipher)
+ {
+ DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
+ acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)));
+ if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
user_access=acl_user->access;
-#endif /* HAVE_OPENSSL */
- *mqh=acl_user->user_resource;
- if (!acl_user->user)
- *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
+ else
+ {
+ user_access=NO_ACCESS;
break;
}
-#ifndef ALLOW_DOWNGRADE_OF_USERS
- break; // Wrong password breaks loop /* purecov: inspected */
-#endif
}
+ /* Prepare certificate (if exists) */
+ DBUG_PRINT("info",("checkpoint 1"));
+ X509* cert=SSL_get_peer_certificate(vio->ssl_);
+ DBUG_PRINT("info",("checkpoint 2"));
+ /* If X509 issuer is speified, we check it... */
+ if (acl_user->x509_issuer)
+ {
+ DBUG_PRINT("info",("checkpoint 3"));
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ acl_user->x509_issuer, ptr));
+ if (strcmp(acl_user->x509_issuer, ptr))
+ {
+ user_access=NO_ACCESS;
+ free(ptr);
+ break;
+ }
+ user_access=acl_user->access;
+ free(ptr);
+ }
+ DBUG_PRINT("info",("checkpoint 4"));
+ /* X509 subject is specified, we check it .. */
+ if (acl_user->x509_subject)
+ {
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (strcmp(acl_user->x509_subject,ptr))
+ user_access=NO_ACCESS;
+ else
+ user_access=acl_user->access;
+ free(ptr);
+ }
+ break;
}
}
+#else /* HAVE_OPENSSL */
+ user_access=acl_user->access;
+#endif /* HAVE_OPENSSL */
+ *mqh=acl_user->user_resource;
+ if (!acl_user->user)
+ *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
+
+unlock_and_exit:
VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(user_access);
}
-/*
-** Functions to add and change user and database privileges when one
-** changes things with GRANT
-*/
-
static byte* check_get_key(ACL_USER *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -632,12 +690,12 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
}
static void acl_update_user(const char *user, const char *host,
- const char *password,
+ const char *password,
enum SSL_type ssl_type,
const char *ssl_cipher,
const char *x509_issuer,
const char *x509_subject,
- USER_RESOURCES *mqh,
+ USER_RESOURCES *mqh,
ulong privileges)
{
for (uint i=0 ; i < acl_users.elements ; i++)
@@ -649,7 +707,7 @@ static void acl_update_user(const char *user, const char *host,
{
if (!acl_user->host.hostname && !host[0] ||
acl_user->host.hostname &&
- !my_strcasecmp(host,acl_user->host.hostname))
+ !my_strcasecmp(&my_charset_latin1, host, acl_user->host.hostname))
{
acl_user->access=privileges;
if (mqh->bits & 1)
@@ -670,12 +728,16 @@ static void acl_update_user(const char *user, const char *host,
}
if (password)
{
- if (!password[0])
+ if (!password[0]) /* If password is empty set it to null */
+ {
acl_user->password=0;
+ acl_user->pversion=0; // just initialize
+ }
else
{
acl_user->password=(char*) ""; // Just point at something
get_salt_from_password(acl_user->salt,password);
+ acl_user->pversion=get_password_version(acl_user->password);
}
}
break;
@@ -686,7 +748,7 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host,
- const char *password,
+ const char *password,
enum SSL_type ssl_type,
const char *ssl_cipher,
const char *x509_issuer,
@@ -711,6 +773,7 @@ static void acl_insert_user(const char *user, const char *host,
{
acl_user.password=(char*) ""; // Just point at something
get_salt_from_password(acl_user.salt,password);
+ acl_user.pversion=get_password_version(password);
}
VOID(push_dynamic(&acl_users,(gptr) &acl_user));
@@ -738,7 +801,8 @@ static void acl_update_db(const char *user, const char *host, const char *db,
!strcmp(user,acl_db->user))
{
if (!acl_db->host.hostname && !host[0] ||
- acl_db->host.hostname && !my_strcasecmp(host,acl_db->host.hostname))
+ acl_db->host.hostname &&
+ !my_strcasecmp(&my_charset_latin1, host, acl_db->host.hostname))
{
if (!acl_db->db && !db[0] ||
acl_db->db && !strcmp(db,acl_db->db))
@@ -802,7 +866,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip,
end=strmov((tmp_db=strmov(key+sizeof(struct in_addr),user)+1),db);
if (lower_case_table_names)
{
- casedn_str(tmp_db);
+ my_casedn_str(&my_charset_latin1, tmp_db);
db=tmp_db;
}
key_length=(uint) (end-key);
@@ -866,7 +930,7 @@ exit:
}
-int wild_case_compare(const char *str,const char *wildstr)
+int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
{
reg3 int flag;
DBUG_ENTER("wild_case_compare");
@@ -877,7 +941,8 @@ int wild_case_compare(const char *str,const char *wildstr)
{
if (*wildstr == wild_prefix && wildstr[1])
wildstr++;
- if (toupper(*wildstr++) != toupper(*str++)) DBUG_RETURN(1);
+ if (my_toupper(cs, *wildstr++) !=
+ my_toupper(cs, *str++)) DBUG_RETURN(1);
}
if (! *wildstr ) DBUG_RETURN (*str != 0);
if (*wildstr++ == wild_one)
@@ -895,12 +960,12 @@ int wild_case_compare(const char *str,const char *wildstr)
char cmp;
if ((cmp= *wildstr) == wild_prefix && wildstr[1])
cmp=wildstr[1];
- cmp=toupper(cmp);
- while (*str && toupper(*str) != cmp)
+ cmp=my_toupper(cs, cmp);
+ while (*str && my_toupper(cs, *str) != cmp)
str++;
if (!*str) DBUG_RETURN (1);
}
- if (wild_case_compare(str,wildstr) == 0) DBUG_RETURN (0);
+ if (wild_case_compare(cs, str,wildstr) == 0) DBUG_RETURN (0);
} while (*str++);
DBUG_RETURN(1);
}
@@ -919,7 +984,7 @@ static void init_check_host(void)
DBUG_ENTER("init_check_host");
VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip),
acl_users.elements,1));
- VOID(hash_init(&acl_check_hosts,acl_users.elements,0,0,
+ VOID(hash_init(&acl_check_hosts,&my_charset_latin1,acl_users.elements,0,0,
(hash_get_key) check_get_key,0,HASH_CASE_INSENSITIVE));
if (!allow_all_hosts)
{
@@ -935,7 +1000,8 @@ static void init_check_host(void)
{ // Check if host already exists
acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j,
acl_host_and_ip *);
- if (!my_strcasecmp(acl_user->host.hostname,acl->hostname))
+ if (!my_strcasecmp(&my_charset_latin1,
+ acl_user->host.hostname, acl->hostname))
break; // already stored
}
if (j == acl_wild_hosts.elements) // If new
@@ -1008,19 +1074,19 @@ bool check_change_password(THD *thd, const char *host, const char *user)
{
if (!initialized)
{
- send_error(&thd->net, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */
+ send_error(thd, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */
return(1); /* purecov: inspected */
}
if (!thd->slave_thread &&
(strcmp(thd->user,user) ||
- my_strcasecmp(host,thd->host ? thd->host : thd->ip)))
+ my_strcasecmp(&my_charset_latin1, host, thd->host_or_ip)))
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1))
return(1);
}
if (!thd->slave_thread && !thd->user[0])
{
- send_error(&thd->net, ER_PASSWORD_ANONYMOUS_USER);
+ send_error(thd, ER_PASSWORD_ANONYMOUS_USER);
return(1);
}
return(0);
@@ -1040,7 +1106,7 @@ bool check_change_password(THD *thd, const char *host, const char *user)
RETURN VALUES
0 ok
1 ERROR; In this case the error is sent to the client.
-*/
+*/
bool change_password(THD *thd, const char *host, const char *user,
char *new_password)
@@ -1054,15 +1120,17 @@ bool change_password(THD *thd, const char *host, const char *user,
if (check_change_password(thd, host, user))
DBUG_RETURN(1);
- /* password should always be 0 or 16 chars; simple hack to avoid cracking */
+ /* password should always be 0,16 or 45 chars; simple hack to avoid cracking */
length=(uint) strlen(new_password);
- new_password[length & 16]=0;
+
+ if (length!=45)
+ new_password[length & 16]=0;
VOID(pthread_mutex_lock(&acl_cache->lock));
ACL_USER *acl_user;
if (!(acl_user= find_acl_user(host,user)))
{
- send_error(&thd->net, ER_PASSWORD_NO_MATCH);
+ send_error(thd, ER_PASSWORD_NO_MATCH);
VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(1);
}
@@ -1072,18 +1140,20 @@ bool change_password(THD *thd, const char *host, const char *user,
new_password))
{
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
- send_error(&thd->net,0); /* purecov: deadcode */
+ send_error(thd,0); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */
}
get_salt_from_password(acl_user->salt,new_password);
+ acl_user->pversion=get_password_version(new_password);
if (!new_password[0])
acl_user->password=0;
else
acl_user->password=(char*) ""; // Point at something
+
acl_cache->clear(1); // Clear locked hostname cache
VOID(pthread_mutex_unlock(&acl_cache->lock));
- char buff[460];
+ char buff[512]; /* Extend with extended password length*/
ulong query_length=
my_sprintf(buff,
(buff,"SET PASSWORD FOR \"%-.120s\"@\"%-.120s\"=\"%-.120s\"",
@@ -1173,7 +1243,8 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
return (tmp & host->ip_mask) == host->ip;
}
return (!host->hostname ||
- (hostname && !wild_case_compare(hostname,host->hostname)) ||
+ (hostname && !wild_case_compare(&my_charset_latin1,
+ hostname,host->hostname)) ||
(ip && !wild_compare(ip,host->hostname)));
}
@@ -1196,8 +1267,8 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
tables.db=(char*) "mysql";
if (!(table=open_ltable(thd,&tables,TL_WRITE)))
DBUG_RETURN(1); /* purecov: deadcode */
- table->field[0]->store(host,(uint) strlen(host));
- table->field[1]->store(user,(uint) strlen(user));
+ table->field[0]->store(host,(uint) strlen(host), &my_charset_latin1);
+ table->field[1]->store(user,(uint) strlen(user), &my_charset_latin1);
if (table->file->index_read_idx(table->record[0],0,
(byte*) table->field[0]->ptr,0,
@@ -1207,7 +1278,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,1);
- table->field[2]->store(new_password,(uint) strlen(new_password));
+ table->field[2]->store(new_password,(uint) strlen(new_password), &my_charset_latin1);
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
@@ -1265,7 +1336,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (combo.password.str && combo.password.str[0])
{
- if (combo.password.length != HASH_PASSWORD_LENGTH)
+ if ((combo.password.length != HASH_PASSWORD_LENGTH)
+ && combo.password.length != HASH_OLD_PASSWORD_LENGTH)
{
my_printf_error(ER_PASSWORD_NO_MATCH,
"Password hash should be a %d-digit hexadecimal number",
@@ -1275,8 +1347,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
password=combo.password.str;
}
- table->field[0]->store(combo.host.str,combo.host.length);
- table->field[1]->store(combo.user.str,combo.user.length);
+ table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1);
table->file->index_init(0);
if (table->file->index_read(table->record[0],
(byte*) table->field[0]->ptr,0,
@@ -1296,17 +1368,17 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
goto end;
}
old_row_exists = 0;
- restore_record(table,2); // cp empty row from record[2]
- table->field[0]->store(combo.host.str,combo.host.length);
- table->field[1]->store(combo.user.str,combo.user.length);
- table->field[2]->store(password,(uint) strlen(password));
+ restore_record(table,2); // cp empty row from record[2]
+ table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1);
+ table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1);
}
else
{
old_row_exists = 1;
store_record(table,1); // Save copy for update
if (combo.password.str) // If password given
- table->field[2]->store(password,(uint) strlen(password));
+ table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1);
}
/* Update table columns with new privileges */
@@ -1319,7 +1391,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
tmp_field++, priv <<= 1)
{
if (priv & rights) // set requested privileges
- (*tmp_field)->store(&what,1);
+ (*tmp_field)->store(&what, 1, &my_charset_latin1);
}
rights=get_access(table,3);
DBUG_PRINT("info",("table->fields: %d",table->fields));
@@ -1328,39 +1400,39 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
/* We write down SSL related ACL stuff */
switch (thd->lex.ssl_type) {
case SSL_TYPE_ANY:
- table->field[24]->store("ANY",3);
- table->field[25]->store("",0);
- table->field[26]->store("",0);
- table->field[27]->store("",0);
+ table->field[24]->store("ANY",3, &my_charset_latin1);
+ table->field[25]->store("", 0, &my_charset_latin1);
+ table->field[26]->store("", 0, &my_charset_latin1);
+ table->field[27]->store("", 0, &my_charset_latin1);
break;
case SSL_TYPE_X509:
- table->field[24]->store("X509",4);
- table->field[25]->store("",0);
- table->field[26]->store("",0);
- table->field[27]->store("",0);
+ table->field[24]->store("X509",4, &my_charset_latin1);
+ table->field[25]->store("", 0, &my_charset_latin1);
+ table->field[26]->store("", 0, &my_charset_latin1);
+ table->field[27]->store("", 0, &my_charset_latin1);
break;
case SSL_TYPE_SPECIFIED:
- table->field[24]->store("SPECIFIED",9);
- table->field[25]->store("",0);
- table->field[26]->store("",0);
- table->field[27]->store("",0);
+ table->field[24]->store("SPECIFIED",9, &my_charset_latin1);
+ table->field[25]->store("", 0, &my_charset_latin1);
+ table->field[26]->store("", 0, &my_charset_latin1);
+ table->field[27]->store("", 0, &my_charset_latin1);
if (thd->lex.ssl_cipher)
table->field[25]->store(thd->lex.ssl_cipher,
- strlen(thd->lex.ssl_cipher));
+ strlen(thd->lex.ssl_cipher), &my_charset_latin1);
if (thd->lex.x509_issuer)
table->field[26]->store(thd->lex.x509_issuer,
- strlen(thd->lex.x509_issuer));
+ strlen(thd->lex.x509_issuer), &my_charset_latin1);
if (thd->lex.x509_subject)
table->field[27]->store(thd->lex.x509_subject,
- strlen(thd->lex.x509_subject));
+ strlen(thd->lex.x509_subject), &my_charset_latin1);
break;
case SSL_TYPE_NOT_SPECIFIED:
break;
case SSL_TYPE_NONE:
- table->field[24]->store("",0);
- table->field[25]->store("",0);
- table->field[26]->store("",0);
- table->field[27]->store("",0);
+ table->field[24]->store("", 0, &my_charset_latin1);
+ table->field[25]->store("", 0, &my_charset_latin1);
+ table->field[26]->store("", 0, &my_charset_latin1);
+ table->field[27]->store("", 0, &my_charset_latin1);
break;
}
@@ -1449,9 +1521,9 @@ static int replace_db_table(TABLE *table, const char *db,
DBUG_RETURN(-1);
}
- table->field[0]->store(combo.host.str,combo.host.length);
- table->field[1]->store(db,(uint) strlen(db));
- table->field[2]->store(combo.user.str,combo.user.length);
+ table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
+ table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
table->file->index_init(0);
if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,0,
HA_READ_KEY_EXACT))
@@ -1464,9 +1536,9 @@ static int replace_db_table(TABLE *table, const char *db,
}
old_row_exists = 0;
restore_record(table,2); // cp empty row from record[2]
- table->field[0]->store(combo.host.str,combo.host.length);
- table->field[1]->store(db,(uint) strlen(db));
- table->field[2]->store(combo.user.str,combo.user.length);
+ table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
+ table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
}
else
{
@@ -1478,7 +1550,7 @@ static int replace_db_table(TABLE *table, const char *db,
for (i= 3, priv= 1; i < table->fields; i++, priv <<= 1)
{
if (priv & store_rights) // do it if priv is chosen
- table->field [i]->store(&what,1); // set requested privileges
+ table->field [i]->store(&what,1, &my_charset_latin1);// set requested privileges
}
rights=get_access(table,3);
rights=fix_rights_for_db(rights);
@@ -1559,13 +1631,14 @@ public:
tname= strdup_root(&memex,t);
if (lower_case_table_names)
{
- casedn_str(db);
- casedn_str(tname);
+ my_casedn_str(&my_charset_latin1, db);
+ my_casedn_str(&my_charset_latin1, tname);
}
key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3;
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
- (void) hash_init(&hash_columns,0,0,0, (hash_get_key) get_key_column,0,
+ (void) hash_init(&hash_columns,&my_charset_latin1,
+ 0,0,0, (hash_get_key) get_key_column,0,
HASH_CASE_INSENSITIVE);
}
@@ -1573,12 +1646,12 @@ public:
{
byte key[MAX_KEY_LENGTH];
- host = get_field(&memex,form,0);
- db = get_field(&memex,form,1);
- user = get_field(&memex,form,2);
+ host = get_field(&memex,form->field[0]);
+ db = get_field(&memex,form->field[1]);
+ user = get_field(&memex,form->field[2]);
if (!user)
user=(char*) "";
- tname = get_field(&memex,form,3);
+ tname = get_field(&memex,form->field[3]);
if (!host || !db || !tname)
{
/* Wrong table row; Ignore it */
@@ -1587,8 +1660,8 @@ public:
}
if (lower_case_table_names)
{
- casedn_str(db);
- casedn_str(tname);
+ my_casedn_str(&my_charset_latin1, db);
+ my_casedn_str(&my_charset_latin1, tname);
}
key_length = ((uint) strlen(db) + (uint) strlen(user) +
(uint) strlen(tname) + 3);
@@ -1599,21 +1672,22 @@ public:
privs = fix_rights_for_table(privs);
cols = fix_rights_for_column(cols);
- (void) hash_init(&hash_columns,0,0,0, (hash_get_key) get_key_column,0,
+ (void) hash_init(&hash_columns,&my_charset_latin1,
+ 0,0,0, (hash_get_key) get_key_column,0,
HASH_CASE_INSENSITIVE);
if (cols)
{
int key_len;
- col_privs->field[0]->store(host,(uint) strlen(host));
- col_privs->field[1]->store(db,(uint) strlen(db));
- col_privs->field[2]->store(user,(uint) strlen(user));
- col_privs->field[3]->store(tname,(uint) strlen(tname));
+ col_privs->field[0]->store(host,(uint) strlen(host), &my_charset_latin1);
+ col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
+ col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1);
+ col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1);
key_len=(col_privs->field[0]->pack_length()+
col_privs->field[1]->pack_length()+
col_privs->field[2]->pack_length()+
col_privs->field[3]->pack_length());
key_copy(key,col_privs,0,key_len);
- col_privs->field[4]->store("",0);
+ col_privs->field[4]->store("",0, &my_charset_latin1);
col_privs->file->index_init(0);
if (col_privs->file->index_read(col_privs->record[0],
(byte*) col_privs->field[0]->ptr,
@@ -1669,24 +1743,28 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
char helping [NAME_LEN*2+USERNAME_LENGTH+3];
uint len;
GRANT_TABLE *grant_table,*found=0;
- safe_mutex_assert_owner(&LOCK_grant);
len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1;
- for (grant_table=(GRANT_TABLE*) hash_search(&hash_tables,(byte*) helping,
+ for (grant_table=(GRANT_TABLE*) hash_search(&column_priv_hash,
+ (byte*) helping,
len) ;
grant_table ;
- grant_table= (GRANT_TABLE*) hash_next(&hash_tables,(byte*) helping,len))
+ grant_table= (GRANT_TABLE*) hash_next(&column_priv_hash,(byte*) helping,
+ len))
{
if (exact)
{
- if ((host && !my_strcasecmp(host,grant_table->host)) ||
+ if ((host &&
+ !my_strcasecmp(&my_charset_latin1, host, grant_table->host)) ||
(ip && !strcmp(ip,grant_table->host)))
return grant_table;
}
else
{
- if ((host && !wild_case_compare(host,grant_table->host)) ||
- (ip && !wild_case_compare(ip,grant_table->host)))
+ if ((host && !wild_case_compare(&my_charset_latin1,
+ host,grant_table->host)) ||
+ (ip && !wild_case_compare(&my_charset_latin1,
+ ip,grant_table->host)))
found=grant_table; // Host ok
}
}
@@ -1713,10 +1791,10 @@ static int replace_column_table(GRANT_TABLE *g_t,
byte key[MAX_KEY_LENGTH];
DBUG_ENTER("replace_column_table");
- table->field[0]->store(combo.host.str,combo.host.length);
- table->field[1]->store(db,(uint) strlen(db));
- table->field[2]->store(combo.user.str,combo.user.length);
- table->field[3]->store(table_name,(uint) strlen(table_name));
+ table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
+ table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
+ table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1);
key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+
table->field[2]->pack_length()+ table->field[3]->pack_length());
key_copy(key,table,0,key_length);
@@ -1733,7 +1811,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
ulong privileges = xx->rights;
bool old_row_exists=0;
key_restore(table,key,0,key_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length());
+ table->field[4]->store(xx->column.ptr(),xx->column.length(),&my_charset_latin1);
if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,
0, HA_READ_KEY_EXACT))
@@ -1747,9 +1825,9 @@ static int replace_column_table(GRANT_TABLE *g_t,
continue; /* purecov: inspected */
}
old_row_exists = 0;
- restore_record(table,2); // Get empty record
+ restore_record(table,2); // Get empty record
key_restore(table,key,0,key_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length());
+ table->field[4]->store(xx->column.ptr(),xx->column.length(), &my_charset_latin1);
}
else
{
@@ -1821,7 +1899,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
GRANT_COLUMN *grant_column = NULL;
char colum_name_buf[HOSTNAME_LENGTH+1];
- String column_name(colum_name_buf,sizeof(colum_name_buf));
+ String column_name(colum_name_buf,sizeof(colum_name_buf),&my_charset_latin1);
privileges&= ~rights;
table->field[6]->store((longlong)
@@ -1877,7 +1955,6 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
int error=0;
ulong store_table_rights, store_col_rights;
DBUG_ENTER("replace_table_table");
- safe_mutex_assert_owner(&LOCK_grant);
strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
@@ -1892,10 +1969,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
restore_record(table,2); // Get empty record
- table->field[0]->store(combo.host.str,combo.host.length);
- table->field[1]->store(db,(uint) strlen(db));
- table->field[2]->store(combo.user.str,combo.user.length);
- table->field[3]->store(table_name,(uint) strlen(table_name));
+ table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
+ table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
+ table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1);
store_record(table,1); // store at pos 1
if (table->file->index_read_idx(table->record[0],0,
@@ -1940,7 +2017,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
}
- table->field[4]->store(grantor,(uint) strlen(grantor));
+ table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1);
table->field[6]->store((longlong) store_table_rights);
table->field[7]->store((longlong) store_col_rights);
rights=fix_rights_for_table(store_table_rights);
@@ -1970,7 +2047,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
else
{
- hash_delete(&hash_tables,(byte*) grant_table);
+ hash_delete(&column_priv_hash,(byte*) grant_table);
}
DBUG_RETURN(0);
@@ -1995,7 +2072,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
if (!initialized)
{
- send_error(&(thd->net), ER_UNKNOWN_COM_ERROR); /* purecov: inspected */
+ send_error(thd, ER_UNKNOWN_COM_ERROR); /* purecov: inspected */
return 1; /* purecov: inspected */
}
if (rights & ~TABLE_ACLS)
@@ -2061,7 +2138,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
int result=0;
- pthread_mutex_lock(&LOCK_grant);
+ rw_wrlock(&LOCK_grant);
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
my_pthread_setspecific_ptr(THR_MALLOC,&memex);
@@ -2116,7 +2193,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
result= -1; /* purecov: deadcode */
continue; /* purecov: deadcode */
}
- hash_insert(&hash_tables,(byte*) grant_table);
+ hash_insert(&column_priv_hash,(byte*) grant_table);
}
/* If revoke_grant, calculate the new column privilege for tables_priv */
@@ -2174,9 +2251,9 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
}
grant_option=TRUE;
my_pthread_setspecific_ptr(THR_MALLOC,old_root);
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
if (!result)
- send_ok(&thd->net);
+ send_ok(thd);
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -2191,17 +2268,16 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
bool create_new_users=0;
TABLE_LIST tables[2];
DBUG_ENTER("mysql_grant");
-
if (!initialized)
{
- send_error(&(thd->net), ER_UNKNOWN_COM_ERROR); /* purecov: tested */
- return 1; /* purecov: tested */
+ send_error(thd, ER_UNKNOWN_COM_ERROR); /* purecov: tested */
+ return 1; /* purecov: tested */
}
if (lower_case_table_names && db)
{
strmov(tmp_db,db);
- casedn_str(tmp_db);
+ my_casedn_str(&my_charset_latin1, tmp_db);
db=tmp_db;
}
@@ -2224,7 +2300,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
create_new_users= test_if_create_new_users(thd);
// go through users in user_list
- pthread_mutex_lock(&LOCK_grant);
+ rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
grant_version++;
@@ -2257,11 +2333,11 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
}
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (!result)
- send_ok(&thd->net);
+ send_ok(thd);
DBUG_RETURN(result);
}
@@ -2272,7 +2348,7 @@ void grant_free(void)
{
DBUG_ENTER("grant_free");
grant_option = FALSE;
- hash_free(&hash_tables);
+ hash_free(&column_priv_hash);
free_root(&memex,MYF(0));
DBUG_VOID_RETURN;
}
@@ -2290,7 +2366,8 @@ my_bool grant_init(THD *org_thd)
DBUG_ENTER("grant_init");
grant_option = FALSE;
- (void) hash_init(&hash_tables,0,0,0, (hash_get_key) get_grant_table,
+ (void) hash_init(&column_priv_hash,&my_charset_latin1,
+ 0,0,0, (hash_get_key) get_grant_table,
(hash_free_key) free_grant_table,0);
init_sql_alloc(&memex,1024,0);
@@ -2336,7 +2413,7 @@ my_bool grant_init(THD *org_thd)
{
GRANT_TABLE *mem_check;
if (!(mem_check=new GRANT_TABLE(t_table,c_table)) ||
- mem_check->ok() && hash_insert(&hash_tables,(byte*) mem_check))
+ mem_check->ok() && hash_insert(&column_priv_hash,(byte*) mem_check))
{
/* This could only happen if we are out memory */
grant_option = FALSE; /* purecov: deadcode */
@@ -2365,35 +2442,37 @@ end:
}
-/* Reload grant array if possible */
+/* Reload grant array (table and column privileges) if possible */
void grant_reload(THD *thd)
{
- HASH old_hash_tables;bool old_grant_option;
+ HASH old_column_priv_hash;
+ bool old_grant_option;
MEM_ROOT old_mem;
DBUG_ENTER("grant_reload");
// Locked tables are checked by acl_init and doesn't have to be checked here
- pthread_mutex_lock(&LOCK_grant);
+ rw_wrlock(&LOCK_grant);
grant_version++;
- old_hash_tables=hash_tables;
+ old_column_priv_hash= column_priv_hash;
old_grant_option = grant_option;
old_mem = memex;
if (grant_init(thd))
{ // Error. Revert to old hash
+ DBUG_PRINT("error",("Reverting to old privileges"));
grant_free(); /* purecov: deadcode */
- hash_tables=old_hash_tables; /* purecov: deadcode */
+ column_priv_hash= old_column_priv_hash; /* purecov: deadcode */
grant_option = old_grant_option; /* purecov: deadcode */
memex = old_mem; /* purecov: deadcode */
}
else
{
- hash_free(&old_hash_tables);
+ hash_free(&old_column_priv_hash);
free_root(&old_mem,MYF(0));
}
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
DBUG_VOID_RETURN;
}
@@ -2413,7 +2492,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
if (!want_access)
return 0; // ok
- pthread_mutex_lock(&LOCK_grant);
+ rw_rdlock(&LOCK_grant);
for (table=tables; table ;table=table->next)
{
if (!(~table->grant.privilege & want_access))
@@ -2447,11 +2526,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
goto err; // impossible
}
}
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
return 0;
err:
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
if (!no_errors) // Not a silent skip of table
{
const char *command="";
@@ -2473,7 +2552,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
command = "index";
else if (want_access & GRANT_ACL)
command = "grant";
- net_printf(&thd->net,ER_TABLEACCESS_DENIED_ERROR,
+ net_printf(thd,ER_TABLEACCESS_DENIED_ERROR,
command,
thd->priv_user,
thd->host_or_ip,
@@ -2493,7 +2572,7 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name,
if (!want_access)
return 0; // Already checked
- pthread_mutex_lock(&LOCK_grant);
+ rw_rdlock(&LOCK_grant);
// reload table if someone has modified any grants
@@ -2511,20 +2590,20 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name,
grant_column=column_hash_search(grant_table, name, length);
if (grant_column && !(~grant_column->rights & want_access))
{
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
return 0;
}
#ifdef NOT_USED
if (show_tables && (grant_column || table->grant.privilege & COL_ACLS))
{
- pthread_mutex_unlock(&LOCK_grant); /* purecov: deadcode */
+ rw_unlock(&LOCK_grant); /* purecov: deadcode */
return 0; /* purecov: deadcode */
}
#endif
/* We must use my_printf_error() here! */
err:
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
if (!show_tables)
{
char command[128];
@@ -2552,7 +2631,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
if (!want_access)
return 0; // Already checked
- pthread_mutex_lock(&LOCK_grant);
+ rw_rdlock(&LOCK_grant);
// reload table if someone has modified any grants
@@ -2575,12 +2654,12 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
if (!grant_column || (~grant_column->rights & want_access))
goto err;
}
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
return 0;
/* We must use my_printf_error() here! */
err:
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
const char *command="";
if (want_access & SELECT_ACL)
@@ -2612,21 +2691,24 @@ bool check_grant_db(THD *thd,const char *db)
bool error=1;
len = (uint) (strmov(strmov(helping,thd->priv_user)+1,db)-helping)+ 1;
- pthread_mutex_lock(&LOCK_grant);
+ rw_rdlock(&LOCK_grant);
- for (uint idx=0 ; idx < hash_tables.records ; idx++)
+ for (uint idx=0 ; idx < column_priv_hash.records ; idx++)
{
- GRANT_TABLE *grant_table = (GRANT_TABLE*) hash_element(&hash_tables,idx);
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ idx);
if (len < grant_table->key_length &&
!memcmp(grant_table->hash_key,helping,len) &&
- (thd->host && !wild_case_compare(thd->host,grant_table->host) ||
- (thd->ip && !wild_case_compare(thd->ip,grant_table->host))))
+ (thd->host && !wild_case_compare(&my_charset_latin1,
+ thd->host,grant_table->host) ||
+ (thd->ip && !wild_case_compare(&my_charset_latin1,
+ thd->ip,grant_table->host))))
{
error=0; // Found match
break;
}
}
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
return error;
}
@@ -2636,20 +2718,24 @@ bool check_grant_db(THD *thd,const char *db)
ulong get_table_grant(THD *thd, TABLE_LIST *table)
{
- uint privilege;
+ ulong privilege;
char *user = thd->priv_user;
const char *db = table->db ? table->db : thd->db;
GRANT_TABLE *grant_table;
- pthread_mutex_lock(&LOCK_grant);
+ rw_rdlock(&LOCK_grant);
+#ifdef EMBEDDED_LIBRARY
+ grant_table= NULL;
+#else
grant_table = table_hash_search(thd->host,thd->ip,db,user,
table->real_name,0);
+#endif
table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version;
if (grant_table)
table->grant.privilege|= grant_table->privs;
privilege= table->grant.privilege;
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
return privilege;
}
@@ -2660,7 +2746,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
GRANT_COLUMN *grant_column;
ulong priv;
- pthread_mutex_lock(&LOCK_grant);
+ rw_rdlock(&LOCK_grant);
// reload table if someone has modified any grants
if (table->grant.version != grant_version)
{
@@ -2682,7 +2768,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
else
priv=table->grant.privilege | grant_column->rights;
}
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
return priv;
}
@@ -2705,19 +2791,20 @@ static uint command_lengths[]=
};
-int mysql_show_grants(THD *thd,LEX_USER *lex_user)
+int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
ulong want_access;
uint counter,index;
int error = 0;
ACL_USER *acl_user; ACL_DB *acl_db;
char buff[1024];
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysql_show_grants");
LINT_INIT(acl_user);
if (!initialized)
{
- send_error(&(thd->net), ER_UNKNOWN_COM_ERROR);
+ send_error(thd, ER_UNKNOWN_COM_ERROR);
DBUG_RETURN(-1);
}
if (!lex_user->host.str)
@@ -2741,33 +2828,33 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!(host=acl_user->host.hostname))
host="%";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(lex_user->host.str,host))
+ !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
break;
}
- if (counter == acl_users.elements)
+ if (counter == acl_users.elements)
{
my_printf_error(ER_NONEXISTING_GRANT,ER(ER_NONEXISTING_GRANT),
MYF(0),lex_user->user.str,lex_user->host.str);
DBUG_RETURN(-1);
}
- Item_string *field=new Item_string("",0);
+ Item_string *field=new Item_string("",0,&my_charset_latin1);
List<Item> field_list;
field->name=buff;
field->max_length=1024;
strxmov(buff,"Grants for ",lex_user->user.str,"@",
lex_user->host.str,NullS);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(-1);
- pthread_mutex_lock(&LOCK_grant);
+ rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
/* Add first global access grants */
{
want_access=acl_user->access;
- String global(buff,sizeof(buff));
+ String global(buff,sizeof(buff),&my_charset_latin1);
global.length(0);
global.append("GRANT ",6);
@@ -2775,13 +2862,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append("ALL PRIVILEGES",14);
else if (!(want_access & ~GRANT_ACL))
global.append("USAGE",5);
- else
+ else
{
bool found=0;
ulong j,test_access= want_access & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1)
{
- if (test_access & j)
+ if (test_access & j)
{
if (found)
global.append(", ",2);
@@ -2791,14 +2878,14 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
global.append (" ON *.* TO '",12);
- global.append(lex_user->user.str,lex_user->user.length);
+ global.append(lex_user->user.str,lex_user->user.length);
global.append ("'@'",3);
global.append(lex_user->host.str,lex_user->host.length);
global.append ('\'');
if (acl_user->password)
{
char passd_buff[HASH_PASSWORD_LENGTH+1];
- make_password_from_salt(passd_buff,acl_user->salt);
+ make_password_from_salt(passd_buff,acl_user->salt,acl_user->pversion);
global.append(" IDENTIFIED BY PASSWORD '",25);
global.append(passd_buff);
global.append('\'');
@@ -2840,9 +2927,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
(acl_user->user_resource.questions | acl_user->user_resource.updates |
acl_user->user_resource.connections))
{
- global.append(" WITH",5);
+ global.append(" WITH",5);
if (want_access & GRANT_ACL)
- global.append(" GRANT OPTION",13);
+ global.append(" GRANT OPTION",13);
if (acl_user->user_resource.questions)
{
char buff[22], *p; // just as in int2str
@@ -2865,12 +2952,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(buff,p-buff);
}
}
- thd->packet.length(0);
- net_store_data(&thd->packet,global.ptr(),global.length());
- if (my_net_write(&thd->net,(char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(global.ptr(),global.length());
+ if (protocol->write())
{
- error=-1; goto end;
+ error=-1;
+ goto end;
}
}
@@ -2886,12 +2973,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
host="";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(lex_user->host.str,host))
+ !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
{
want_access=acl_db->access;
- if (want_access)
+ if (want_access)
{
- String db(buff,sizeof(buff));
+ String db(buff,sizeof(buff),&my_charset_latin1);
db.length(0);
db.append("GRANT ",6);
@@ -2917,16 +3004,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
db.append (" ON `",5);
db.append(acl_db->db);
db.append ("`.* TO '",8);
- db.append(lex_user->user.str,lex_user->user.length);
+ db.append(lex_user->user.str,lex_user->user.length);
db.append ("'@'",3);
db.append(lex_user->host.str, lex_user->host.length);
- db.append ('\'');
+ db.append ('\'');
if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18);
- thd->packet.length(0);
- net_store_data(&thd->packet,db.ptr(),db.length());
- if (my_net_write(&thd->net,(char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(db.ptr(),db.length());
+ if (protocol->write())
{
error=-1;
goto end;
@@ -2936,10 +3022,11 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
/* Add column access */
- for (index=0 ; index < hash_tables.records ; index++)
+ for (index=0 ; index < column_priv_hash.records ; index++)
{
const char *user,*host;
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index);
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ index);
if (!(user=grant_table->user))
user="";
@@ -2947,32 +3034,32 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
host="";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(lex_user->host.str,host))
+ !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
{
want_access=grant_table->privs;
if ((want_access | grant_table->cols) != 0)
{
- String global(buff,sizeof(buff));
+ String global(buff,sizeof(buff),&my_charset_latin1);
global.length(0);
global.append("GRANT ",6);
if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL)))
global.append("ALL PRIVILEGES",14);
- else
+ else
{
int found=0;
ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1)
{
- if (test_access & j)
+ if (test_access & j)
{
if (found)
global.append(", ",2);
found = 1;
global.append(command_array[counter],command_lengths[counter]);
- if (grant_table->cols)
+ if (grant_table->cols)
{
uint found_col=0;
for (uint col_index=0 ;
@@ -2981,9 +3068,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
hash_element(&grant_table->hash_columns,col_index);
- if (grant_column->rights & j)
+ if (grant_column->rights & j)
{
- if (!found_col)
+ if (!found_col)
{
global.append(" (",2);
found_col=1;
@@ -3005,29 +3092,27 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(".",1);
global.append(grant_table->tname);
global.append(" TO '",5);
- global.append(lex_user->user.str,lex_user->user.length);
+ global.append(lex_user->user.str,lex_user->user.length);
global.append("'@'",3);
- global.append(lex_user->host.str,lex_user->host.length);
+ global.append(lex_user->host.str,lex_user->host.length);
global.append('\'');
if (want_access & GRANT_ACL)
- global.append(" WITH GRANT OPTION",18);
- thd->packet.length(0);
- net_store_data(&thd->packet,global.ptr(),global.length());
- if (my_net_write(&thd->net,(char*) thd->packet.ptr(),
- thd->packet.length()))
+ global.append(" WITH GRANT OPTION",18);
+ protocol->prepare_for_resend();
+ protocol->store(global.ptr(),global.length());
+ if (protocol->write())
{
- error=-1;
+ error= -1;
break;
}
}
}
}
-
end:
VOID(pthread_mutex_unlock(&acl_cache->lock));
- pthread_mutex_unlock(&LOCK_grant);
+ rw_unlock(&LOCK_grant);
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(error);
}
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 6925b6b406c..ceb866d809f 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -79,6 +79,55 @@
#define fix_rights_for_column(A) (((A) & COL_ACLS) | ((A & ~COL_ACLS) << 7))
#define get_rights_for_column(A) (((A) & COL_ACLS) | ((A & ~COL_ACLS) >> 7))
+/* Classes */
+
+struct acl_host_and_ip
+{
+ char *hostname;
+ long ip,ip_mask; // Used with masked ip:s
+};
+
+
+class ACL_ACCESS {
+public:
+ ulong sort;
+ ulong access;
+};
+
+
+/* ACL_HOST is used if no host is specified */
+
+class ACL_HOST :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *db;
+};
+
+
+class ACL_USER :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ uint hostname_length;
+ USER_RESOURCES user_resource;
+ char *user,*password;
+ ulong salt[6]; // New password has longer length
+ uint8 pversion; // password version
+ enum SSL_type ssl_type;
+ const char *ssl_cipher, *x509_issuer, *x509_subject;
+};
+
+
+class ACL_DB :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *user,*db;
+};
+
+
+
/* prototypes */
my_bool acl_init(THD *thd, bool dont_read_acl_tables);
@@ -88,7 +137,8 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db);
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *scramble,char **priv_user,
- bool old_ver, USER_RESOURCES *max);
+ bool old_ver, USER_RESOURCES *max,char* prepared_scramble,
+ uint *cur_priv_version, ACL_USER **cached_user);
bool acl_check_host(const char *host, const char *ip);
bool check_change_password(THD *thd, const char *host, const char *user);
bool change_password(THD *thd, const char *host, const char *user,
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index cbd586b8d30..a424d877919 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -89,21 +89,21 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
if ((*param->item)->type() != Item::INT_ITEM ||
(*param->item)->val() < 0)
{
- net_printf(&thd->net, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name);
+ my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
DBUG_RETURN(0);
}
pc->max_tree_elements = (uint) (*param->item)->val_int();
param = param->next;
if (param->next) // no third parameter possible
{
- net_printf(&thd->net, ER_WRONG_PARAMCOUNT_TO_PROCEDURE, proc_name);
+ my_error(ER_WRONG_PARAMCOUNT_TO_PROCEDURE, MYF(0), proc_name);
DBUG_RETURN(0);
}
// second parameter
if ((*param->item)->type() != Item::INT_ITEM ||
(*param->item)->val() < 0)
{
- net_printf(&thd->net, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name);
+ my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
DBUG_RETURN(0);
}
pc->max_treemem = (uint) (*param->item)->val_int();
@@ -111,7 +111,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
else if ((*param->item)->type() != Item::INT_ITEM ||
(*param->item)->val() < 0)
{
- net_printf(&thd->net, ER_WRONG_PARAMETERS_TO_PROCEDURE, proc_name);
+ my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
DBUG_RETURN(0);
}
// if only one parameter was given, it will be the value of max_tree_elements
@@ -168,7 +168,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
MySQL removes any endspaces of a string, so we must take care only of
spaces in front of a string
*/
- for (; str != end && isspace(*str); str++) ;
+ for (; str != end && my_isspace(system_charset_info, *str); str++) ;
if (str == end)
return 0;
@@ -181,10 +181,10 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
else
info->negative = 0;
begin = str;
- for (; str != end && isdigit(*str); str++)
+ for (; str != end && my_isdigit(system_charset_info,*str); str++)
{
if (!info->integers && *str == '0' && (str + 1) != end &&
- isdigit(*(str + 1)))
+ my_isdigit(system_charset_info,*(str + 1)))
info->zerofill = 1; // could be a postnumber for example
info->integers++;
}
@@ -210,7 +210,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
str++;
if (*str != '-' && *str != '+')
return 0;
- for (str++; str != end && isdigit(*str); str++) ;
+ for (str++; str != end && my_isdigit(system_charset_info,*str); str++) ;
if (str == end)
{
info->is_float = 1; // we can't use variable decimals here
@@ -225,7 +225,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
info->ullval = (ulonglong) strtoull(begin, NULL, 10);
return 1;
}
- for (; str != end && isdigit(*str); str++)
+ for (; str != end && my_isdigit(system_charset_info,*str); str++)
info->decimals++;
if (str == end)
{
@@ -275,7 +275,7 @@ void free_string(String *s)
void field_str::add()
{
char buff[MAX_FIELD_WIDTH], *ptr;
- String s(buff, sizeof(buff)), *res;
+ String s(buff, sizeof(buff),default_charset_info), *res;
ulong length;
if (!(res = item->val_str(&s)))
@@ -310,6 +310,7 @@ void field_str::add()
was_maybe_zerofill = num_info.maybe_zerofill;
}
+ /* Update min and max arguments */
if (!found)
{
found = 1;
@@ -325,7 +326,7 @@ void field_str::add()
if (length > max_length)
max_length = length;
- if (item->binary)
+ if (item->binary())
{
if (stringcmp(res, &min_arg) < 0)
min_arg.copy(*res);
@@ -345,10 +346,10 @@ void field_str::add()
{
if (res != &s)
s.copy(*res);
- if (!tree_search(&tree, (void*) &s)) // If not in tree
+ if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
{
s.copy(); // slow, when SAFE_MALLOC is in use
- if (!tree_insert(&tree, (void*) &s, 0))
+ if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
{
room_in_tree = 0; // Remove tree, out of RAM ?
delete_tree(&tree);
@@ -388,8 +389,7 @@ void field_real::add()
if ((decs = decimals()) == NOT_FIXED_DEC)
{
- sprintf(buff, "%g", num);
- length = (uint) strlen(buff);
+ length= my_sprintf(buff, (buff, "%g", num));
if (rint(num) != num)
max_notzero_dec_len = 1;
}
@@ -398,12 +398,11 @@ void field_real::add()
#ifdef HAVE_SNPRINTF
buff[sizeof(buff)-1]=0; // Safety
snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num);
+ length = (uint) strlen(buff);
#else
- sprintf(buff, "%-.*f", (int) decs, num);
+ length= my_sprintf(buff, (buff, "%-.*f", (int) decs, num));
#endif
- length = (uint) strlen(buff);
-
// We never need to check further than this
end = buff + length - 1 - decs + max_notzero_dec_len;
@@ -417,7 +416,7 @@ void field_real::add()
if (room_in_tree)
{
- if (!(element = tree_insert(&tree, (void*) &num, 0)))
+ if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
{
room_in_tree = 0; // Remove tree, out of RAM ?
delete_tree(&tree);
@@ -470,7 +469,7 @@ void field_longlong::add()
if (room_in_tree)
{
- if (!(element = tree_insert(&tree, (void*) &num, 0)))
+ if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
{
room_in_tree = 0; // Remove tree, out of RAM ?
delete_tree(&tree);
@@ -524,7 +523,7 @@ void field_ulonglong::add()
if (room_in_tree)
{
- if (!(element = tree_insert(&tree, (void*) &num, 0)))
+ if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
{
room_in_tree = 0; // Remove tree, out of RAM ?
delete_tree(&tree);
@@ -579,8 +578,9 @@ bool analyse::end_of_records()
{
field_info **f = f_info;
char buff[MAX_FIELD_WIDTH];
- String *res, s_min(buff, sizeof(buff)), s_max(buff, sizeof(buff)),
- ans(buff, sizeof(buff));
+ String *res, s_min(buff, sizeof(buff),default_charset_info),
+ s_max(buff, sizeof(buff),default_charset_info),
+ ans(buff, sizeof(buff),default_charset_info);
for (; f != f_end; f++)
{
@@ -594,23 +594,23 @@ bool analyse::end_of_records()
{
func_items[1]->null_value = 0;
res = (*f)->get_min_arg(&s_min);
- func_items[1]->set(res->ptr(), res->length());
+ func_items[1]->set(res->ptr(), res->length(), res->charset());
func_items[2]->null_value = 0;
res = (*f)->get_max_arg(&s_max);
- func_items[2]->set(res->ptr(), res->length());
+ func_items[2]->set(res->ptr(), res->length(), res->charset());
}
func_items[3]->set((longlong) (*f)->min_length);
func_items[4]->set((longlong) (*f)->max_length);
func_items[5]->set((longlong) (*f)->empty);
func_items[6]->set((longlong) (*f)->nulls);
res = (*f)->avg(&s_max, rows);
- func_items[7]->set(res->ptr(), res->length());
+ func_items[7]->set(res->ptr(), res->length(), res->charset());
func_items[8]->null_value = 0;
res = (*f)->std(&s_max, rows);
if (!res)
func_items[8]->null_value = 1;
else
- func_items[8]->set(res->ptr(), res->length());
+ func_items[8]->set(res->ptr(), res->length(), res->charset());
// count the dots, quotas, etc. in (ENUM("a","b","c"...))
// if tree has been removed, don't suggest ENUM.
// treemem is used to measure the size of tree for strings,
@@ -626,14 +626,14 @@ bool analyse::end_of_records()
((*f)->tree.elements_in_tree * 3 - 1 + 6))))
{
char tmp[331]; //331, because one double prec. num. can be this long
- String tmp_str(tmp, sizeof(tmp));
+ String tmp_str(tmp, sizeof(tmp),default_charset_info);
TREE_INFO tree_info;
tree_info.str = &tmp_str;
tree_info.found = 0;
tree_info.item = (*f)->item;
- tmp_str.set("ENUM(", 5);
+ tmp_str.set("ENUM(", 5,default_charset_info);
tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info,
left_root_right);
tmp_str.append(')');
@@ -641,7 +641,7 @@ bool analyse::end_of_records()
if (!(*f)->nulls)
tmp_str.append(" NOT NULL");
output_str_length = tmp_str.length();
- func_items[9]->set(tmp_str.ptr(), tmp_str.length());
+ func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset());
if (result->send_data(result_fields))
return -1;
continue;
@@ -688,7 +688,7 @@ bool analyse::end_of_records()
}
if (!(*f)->nulls)
ans.append(" NOT NULL");
- func_items[9]->set(ans.ptr(), ans.length());
+ func_items[9]->set(ans.ptr(), ans.length(), ans.charset());
if (result->send_data(result_fields))
return -1;
}
@@ -739,7 +739,7 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
{
if (must_be_blob)
{
- if (item->binary)
+ if (item->binary())
answer->append("TINYBLOB", 8);
else
answer->append("TINYTEXT", 8);
@@ -757,21 +757,21 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
}
else if (max_length < (1L << 16))
{
- if (item->binary)
+ if (item->binary())
answer->append("BLOB", 4);
else
answer->append("TEXT", 4);
}
else if (max_length < (1L << 24))
{
- if (item->binary)
+ if (item->binary())
answer->append("MEDIUMBLOB", 10);
else
answer->append("MEDIUMTEXT", 10);
}
else
{
- if (item->binary)
+ if (item->binary())
answer->append("LONGBLOB", 8);
else
answer->append("LONGTEXT", 8);
@@ -897,14 +897,14 @@ int collect_real(double *element, element_count count __attribute__((unused)),
TREE_INFO *info)
{
char buff[MAX_FIELD_WIDTH];
- String s(buff, sizeof(buff));
+ String s(buff, sizeof(buff),current_thd->variables.thd_charset);
if (info->found)
info->str->append(',');
else
info->found = 1;
info->str->append('\'');
- s.set(*element, info->item->decimals);
+ s.set(*element, info->item->decimals, current_thd->variables.thd_charset);
info->str->append(s);
info->str->append('\'');
return 0;
@@ -916,14 +916,14 @@ int collect_longlong(longlong *element,
TREE_INFO *info)
{
char buff[MAX_FIELD_WIDTH];
- String s(buff, sizeof(buff));
+ String s(buff, sizeof(buff),default_charset_info);
if (info->found)
info->str->append(',');
else
info->found = 1;
info->str->append('\'');
- s.set(*element);
+ s.set(*element,default_charset_info);
info->str->append(s);
info->str->append('\'');
return 0;
@@ -935,14 +935,14 @@ int collect_ulonglong(ulonglong *element,
TREE_INFO *info)
{
char buff[MAX_FIELD_WIDTH];
- String s(buff, sizeof(buff));
+ String s(buff, sizeof(buff),default_charset_info);
if (info->found)
info->str->append(',');
else
info->found = 1;
info->str->append('\'');
- s.set(*element);
+ s.set(*element,default_charset_info);
info->str->append(s);
info->str->append('\'');
return 0;
diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h
index 1c60d0c150f..ada46374a15 100644
--- a/sql/sql_analyse.h
+++ b/sql/sql_analyse.h
@@ -110,11 +110,12 @@ class field_str :public field_info
EV_NUM_INFO ev_num_info;
public:
- field_str(Item* a, analyse* b) :field_info(a,b), min_arg(""),
- max_arg(""), sum(0),
+ field_str(Item* a, analyse* b) :field_info(a,b),
+ min_arg("",default_charset_info),
+ max_arg("",default_charset_info), sum(0),
must_be_blob(0), was_zero_fill(0),
was_maybe_zerofill(0), can_be_still_num(1)
- { init_tree(&tree, 0, 0, sizeof(String), a->binary ?
+ { init_tree(&tree, 0, 0, sizeof(String), a->binary() ?
(qsort_cmp2) stringcmp2 : (qsort_cmp2) sortcmp2,
0, (tree_element_free) free_string, NULL); };
@@ -127,10 +128,10 @@ public:
String *avg(String *s, ha_rows rows)
{
if (!(rows - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
s->set((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
- DEC_IN_AVG);
+ DEC_IN_AVG,my_thd_charset);
return s;
}
friend int collect_string(String *element, element_count count,
@@ -159,26 +160,34 @@ public:
void add();
void get_opt_type(String*, ha_rows);
- String *get_min_arg(String *s) { s->set(min_arg, item->decimals); return s; }
- String *get_max_arg(String *s) { s->set(max_arg, item->decimals); return s; }
+ String *get_min_arg(String *s)
+ {
+ s->set(min_arg, item->decimals,my_thd_charset);
+ return s;
+ }
+ String *get_max_arg(String *s)
+ {
+ s->set(max_arg, item->decimals,my_thd_charset);
+ return s;
+ }
String *avg(String *s, ha_rows rows)
{
if (!(rows - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
- s->set(((double)sum / (double) (rows - nulls)), item->decimals);
+ s->set(((double)sum / (double) (rows - nulls)), item->decimals,my_thd_charset);
return s;
}
String *std(String *s, ha_rows rows)
{
double tmp = ulonglong2double(rows);
if (!(tmp - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
{
double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
(tmp - nulls));
- s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), item->decimals);
+ s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), item->decimals,my_thd_charset);
}
return s;
}
@@ -205,26 +214,26 @@ public:
void add();
void get_opt_type(String*, ha_rows);
- String *get_min_arg(String *s) { s->set(min_arg); return s; }
- String *get_max_arg(String *s) { s->set(max_arg); return s; }
+ String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; }
+ String *get_max_arg(String *s) { s->set(max_arg,my_thd_charset); return s; }
String *avg(String *s, ha_rows rows)
{
if (!(rows - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
- s->set(((double) sum / (double) (rows - nulls)), DEC_IN_AVG);
+ s->set(((double) sum / (double) (rows - nulls)), DEC_IN_AVG,my_thd_charset);
return s;
}
String *std(String *s, ha_rows rows)
{
double tmp = ulonglong2double(rows);
if (!(tmp - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
{
double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
(tmp - nulls));
- s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG);
+ s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset);
}
return s;
}
@@ -249,28 +258,28 @@ public:
(qsort_cmp2) compare_ulonglong2, 0, NULL, NULL); }
void add();
void get_opt_type(String*, ha_rows);
- String *get_min_arg(String *s) { s->set(min_arg); return s; }
- String *get_max_arg(String *s) { s->set(max_arg); return s; }
+ String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; }
+ String *get_max_arg(String *s) { s->set(max_arg,my_thd_charset); return s; }
String *avg(String *s, ha_rows rows)
{
if (!(rows - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
s->set((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
- DEC_IN_AVG);
+ DEC_IN_AVG,my_thd_charset);
return s;
}
String *std(String *s, ha_rows rows)
{
double tmp = ulonglong2double(rows);
if (!(tmp - nulls))
- s->set((double) 0.0, 1);
+ s->set((double) 0.0, 1,my_thd_charset);
else
{
double tmp2 = ((ulonglong2double(sum_sqr) -
ulonglong2double(sum * sum) / (tmp - nulls)) /
(tmp - nulls));
- s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG);
+ s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset);
}
return s;
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b53c05c0357..d3a049a11da 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -19,11 +19,11 @@
#include "mysql_priv.h"
#include "sql_acl.h"
+#include "sql_select.h"
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
#include <nisam.h>
-#include <assert.h>
#ifdef __WIN__
#include <io.h>
#endif
@@ -49,7 +49,8 @@ extern "C" byte *table_cache_key(const byte *record,uint *length,
void table_cache_init(void)
{
- VOID(hash_init(&open_cache,table_cache_size+16,0,0,table_cache_key,
+ VOID(hash_init(&open_cache,system_charset_info,
+ table_cache_size+16,0,0,table_cache_key,
(hash_free_key) free_cache_entry,0));
mysql_rm_tmp_tables();
}
@@ -194,92 +195,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list);
}
-
-/******************************************************************************
-** Send name and type of result to client.
-** Sum fields has table name empty and field_name.
-** flag is a bit mask with the following functions:
-** 1 send number of rows
-** 2 send default values
-** 4 Don't convert field names
-******************************************************************************/
-
-bool
-send_fields(THD *thd,List<Item> &list,uint flag)
-{
- List_iterator_fast<Item> it(list);
- Item *item;
- char buff[80];
- CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->variables.convert_set;
- DBUG_ENTER("send_fields");
-
- String tmp((char*) buff,sizeof(buff)),*res,*packet= &thd->packet;
-
- if (thd->fatal_error) // We have got an error
- goto err;
-
- if (flag & 1)
- { // Packet with number of elements
- char *pos=net_store_length(buff,(uint) list.elements);
- (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
- }
- while ((item=it++))
- {
- char *pos;
- Send_field field;
- item->make_field(&field);
- packet->length(0);
-
- if (convert)
- {
- if (convert->store(packet,field.table_name,
- (uint) strlen(field.table_name)) ||
- convert->store(packet,field.col_name,
- (uint) strlen(field.col_name)) ||
- packet->realloc(packet->length()+10))
- goto err;
- }
- else if (net_store_data(packet,field.table_name) ||
- net_store_data(packet,field.col_name) ||
- packet->realloc(packet->length()+10))
- goto err; /* purecov: inspected */
- pos= (char*) packet->ptr()+packet->length();
-
- if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
- {
- packet->length(packet->length()+9);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
- }
- else
- {
- packet->length(packet->length()+10);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
- }
- if (flag & 2)
- { // Send default value
- if (!(res=item->val_str(&tmp)))
- {
- if (net_store_null(packet))
- goto err;
- }
- else if (net_store_data(packet,res->ptr(),res->length()))
- goto err;
- }
- if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
- break; /* purecov: inspected */
- }
- send_eof(&thd->net,1);
- DBUG_RETURN(0);
- err:
- send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
-}
-
-
/*****************************************************************************
* Functions to free open table cache
****************************************************************************/
@@ -325,6 +240,7 @@ static void free_cache_entry(TABLE *table)
DBUG_VOID_RETURN;
}
+/* Free resources allocated by filesort() and read_record() */
void free_io_cache(TABLE *table)
{
@@ -391,7 +307,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
close_old_data_files(thd,thd->open_tables,1,1);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
- DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
+ DBUG_PRINT("info",
+ ("Waiting for others threads to close their open tables"));
while (found && ! thd->killed)
{
found=0;
@@ -432,12 +349,40 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
}
-/* Put all tables used by thread in free list */
+/*
+ Close all tables used by thread
-void close_thread_tables(THD *thd, bool locked)
+ SYNOPSIS
+ close_thread_tables()
+ thd Thread handler
+ lock_in_use Set to 1 (0 = default) if caller has a lock on
+ LOCK_open
+ skip_derived Set to 1 (0 = default) if we should not free derived
+ tables.
+
+ IMPLEMENTATION
+ Unlocks tables and frees derived tables.
+ Put all normal tables used by thread in free list.
+*/
+
+void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
{
DBUG_ENTER("close_thread_tables");
+ if (thd->derived_tables && !skip_derived)
+ {
+ TABLE *table, *next;
+ /*
+ Close all derived tables generated from questions like
+ SELECT * from (select * from t1))
+ */
+ for (table= thd->derived_tables ; table ; table= next)
+ {
+ next= table->next;
+ free_tmp_table(thd, table);
+ }
+ thd->derived_tables= 0;
+ }
if (thd->locked_tables)
{
ha_commit_stmt(thd); // If select statement
@@ -448,10 +393,11 @@ void close_thread_tables(THD *thd, bool locked)
if (thd->lock)
{
- mysql_unlock_tables(thd, thd->lock); thd->lock=0;
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0;
}
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
- if (!locked)
+ if (!lock_in_use)
VOID(pthread_mutex_lock(&LOCK_open));
safe_mutex_assert_owner(&LOCK_open);
@@ -470,7 +416,7 @@ void close_thread_tables(THD *thd, bool locked)
/* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh));
}
- if (!locked)
+ if (!lock_in_use)
VOID(pthread_mutex_unlock(&LOCK_open));
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */
DBUG_VOID_RETURN;
@@ -583,6 +529,54 @@ void close_temporary_tables(THD *thd)
thd->temporary_tables=0;
}
+/*
+ Find first suitable table by alias in given list.
+
+ SYNOPSIS
+ find_table_in_list()
+ table - pointer to table list
+ db_name - data base name or 0 for any
+ table_name - table name or 0 for any
+
+ RETURN VALUES
+ NULL Table not found
+ # Pointer to found table.
+*/
+
+TABLE_LIST * find_table_in_list(TABLE_LIST *table,
+ const char *db_name, const char *table_name)
+{
+ for (; table; table= table->next)
+ if ((!db_name || !strcmp(table->db, db_name)) &&
+ (!table_name || !strcmp(table->alias, table_name)))
+ break;
+ return table;
+}
+
+/*
+ Find real table in given list.
+
+ SYNOPSIS
+ find_table_in_list()
+ table - pointer to table list
+ db_name - data base name
+ table_name - table name
+
+ RETURN VALUES
+ NULL Table not found
+ # Pointer to found table.
+*/
+
+TABLE_LIST * find_real_table_in_list(TABLE_LIST *table,
+ const char *db_name,
+ const char *table_name)
+{
+ for (; table; table= table->next)
+ if (!strcmp(table->db, db_name) &&
+ !strcmp(table->real_name, table_name))
+ break;
+ return table;
+}
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
{
@@ -590,7 +584,7 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
uint key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
TABLE *table,**prev;
- int4store(key+key_length,thd->slave_proxy_id);
+ int4store(key+key_length,thd->variables.pseudo_thread_id);
key_length += 4;
prev= &thd->temporary_tables;
@@ -630,7 +624,7 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
(strmov((table->real_name=strmov(table->table_cache_key=key,
db)+1),
table_name) - table->table_cache_key)+1;
- int4store(key+table->key_length,thd->slave_proxy_id);
+ int4store(key+table->key_length,thd->variables.pseudo_thread_id);
table->key_length += 4;
return 0;
}
@@ -784,7 +778,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
if (thd->killed)
DBUG_RETURN(0);
key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
- int4store(key + key_length, thd->slave_proxy_id);
+ int4store(key + key_length, thd->variables.pseudo_thread_id);
for (table=thd->temporary_tables; table ; table=table->next)
{
@@ -798,6 +792,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
DBUG_RETURN(0);
}
table->query_id=thd->query_id;
+ thd->tmp_table_used= 1;
goto reset;
}
}
@@ -808,7 +803,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
{
if (table->key_length == key_length &&
!memcmp(table->table_cache_key,key,key_length) &&
- !my_strcasecmp(table->table_name,alias))
+ !my_strcasecmp(system_charset_info,table->table_name,alias))
goto reset;
}
my_printf_error(ER_TABLE_NOT_LOCKED,ER(ER_TABLE_NOT_LOCKED),MYF(0),alias);
@@ -1301,9 +1296,8 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
}
}
pthread_mutex_unlock(&LOCK_open);
- thd->net.last_error[0]=0; // Clear error message
- thd->net.last_errno=0;
- error=0;
+ thd->clear_error(); // Clear error message
+ error= 0;
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
@@ -1313,8 +1307,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
(entry->file->is_crashed() && entry->file->check_and_repair(thd)))
{
/* Give right error message */
- thd->net.last_error[0]=0;
- thd->net.last_errno=0;
+ thd->clear_error();
my_error(ER_NOT_KEYFILE, MYF(0), name, my_errno);
sql_print_error("Error: Couldn't repair table: %s.%s",db,name);
if (entry->file)
@@ -1323,8 +1316,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
}
else
{
- thd->net.last_error[0]=0; // Clear error message
- thd->net.last_errno=0;
+ thd->clear_error(); // Clear error message
}
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd,&table_list);
@@ -1469,6 +1461,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
while (!(table=open_table(thd,table_list->db,
table_list->real_name,table_list->alias,
&refresh)) && refresh) ;
+
if (table)
{
#if defined( __WIN__) || defined(OS2)
@@ -1488,6 +1481,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
}
else
{
+ DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
table= 0;
@@ -1519,6 +1513,11 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
thd Thread handler
tables Tables to lock
+ NOTES
+ You can't call lock_tables twice, as this would break the dead-lock-free
+ handling thr_lock gives us. You most always get all needed locks at
+ once.
+
RETURN VALUES
0 ok
-1 Error
@@ -1532,6 +1531,7 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
if (!thd->locked_tables)
{
+ DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
uint count=0;
for (table = tables ; table ; table=table->next)
count++;
@@ -1601,7 +1601,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
+1), table_name)
- tmp_table->table_cache_key)+1;
int4store(tmp_table->table_cache_key + tmp_table->key_length,
- thd->slave_proxy_id);
+ thd->variables.pseudo_thread_id);
tmp_table->key_length += 4;
if (link_in_list)
@@ -1650,14 +1650,17 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
}
else
{
- Field **ptr=table->field;
+ Field **ptr;
+ if (!(ptr=table->field))
+ return (Field *)0;
while ((field = *ptr++))
{
- if (!my_strcasecmp(field->field_name, name))
+ if (!my_strcasecmp(system_charset_info, field->field_name, name))
goto found;
}
}
- if (allow_rowid && !my_strcasecmp(name,"_rowid") &&
+ if (allow_rowid &&
+ !my_strcasecmp(system_charset_info, name, "_rowid") &&
(field=table->rowid_field))
goto found;
return (Field*) 0;
@@ -1681,8 +1684,33 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
}
+/*
+ Find field in table list.
+
+ SYNOPSIS
+ find_field_in_tables()
+ thd Pointer to current thread structure
+ item Field item that should be found
+ tables Tables for scaning
+ where Table where field found will be returned via
+ this parameter
+ report_error If FALSE then do not report error if item not found
+ and return not_found_field
+
+ RETURN VALUES
+ 0 Field is not found or field is not unique- error
+ message is reported
+ not_found_field Function was called with report_error == FALSE and
+ field was not found. no error message reported.
+ found field
+*/
+
+// Special Field pointer for find_field_in_tables returning
+const Field *not_found_field= (Field*) 0x1;
+
Field *
-find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
+find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
+ TABLE_LIST **where, bool report_error)
{
Field *found=0;
const char *db=item->db_name;
@@ -1690,19 +1718,20 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
const char *name=item->field_name;
uint length=(uint) strlen(name);
- if (table_name)
+ if (table_name && table_name[0])
{ /* Qualified field */
bool found_table=0;
for (; tables ; tables=tables->next)
{
if (!strcmp(tables->alias,table_name) &&
- (!db || !strcmp(db,tables->db)))
+ (!db || !tables->db || !tables->db[0] || !strcmp(db,tables->db)))
{
found_table=1;
Field *find=find_field_in_table(thd,tables->table,name,length,
grant_option && !thd->master_access,1);
if (find)
{
+ (*where)= tables;
if (find == WRONG_GRANT)
return (Field*) 0;
if (db || !thd->where)
@@ -1719,25 +1748,41 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
}
if (found)
return found;
- if (!found_table)
+ if (!found_table && report_error)
{
char buff[NAME_LEN*2+1];
- if (db)
+ if (db && db[0])
{
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff;
}
- my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),table_name,
- thd->where);
+ if (report_error)
+ {
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ table_name, thd->where);
+ }
+ else
+ return (Field*) not_found_field;
}
else
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
- item->full_name(),thd->where);
+ if (report_error)
+ my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
+ item->full_name(),thd->where);
+ else
+ return (Field*) not_found_field;
return (Field*) 0;
}
bool allow_rowid= tables && !tables->next; // Only one table
for (; tables ; tables=tables->next)
{
+ if (!tables->table)
+ {
+ if (report_error)
+ my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
+ item->full_name(),thd->where);
+ return (Field*) not_found_field;
+ }
+
Field *field=find_field_in_table(thd,tables->table,name,length,
grant_option &&
!thd->master_access, allow_rowid);
@@ -1745,6 +1790,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
{
if (field == WRONG_GRANT)
return (Field*) 0;
+ (*where)= tables;
if (found)
{
if (!thd->where) // Returns first found
@@ -1758,13 +1804,49 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
}
if (found)
return found;
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
- MYF(0),item->full_name(),thd->where);
+ if (report_error)
+ my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
+ MYF(0), item->full_name(), thd->where);
+ else
+ return (Field*) not_found_field;
return (Field*) 0;
}
+
+/*
+ Find Item in list of items (find_field_in_tables analog)
+
+ TODO
+ is it better return only counter?
+
+ SYNOPSIS
+ find_item_in_list()
+ find Item to find
+ items List of items
+ counter To return number of found item
+ report_error
+ REPORT_ALL_ERRORS report errors, return 0 if error
+ REPORT_EXCEPT_NOT_FOUND Do not report 'not found' error and
+ return not_found_item, report other errors,
+ return 0
+ IGNORE_ERRORS Do not report errors, return 0 if error
+
+ RETURN VALUES
+ 0 Item is not found or item is not unique,
+ error message is reported
+ not_found_item Function was called with
+ report_error == REPORT_EXCEPT_NOT_FOUND and
+ item was not found. No error message was reported
+ found field
+*/
+
+// Special Item pointer for find_item_in_list returning
+const Item **not_found_item= (const Item**) 0x1;
+
+
Item **
-find_item_in_list(Item *find,List<Item> &items)
+find_item_in_list(Item *find, List<Item> &items, uint *counter,
+ find_item_error_report_type report_error)
{
List_iterator<Item> li(items);
Item **found=0,*item;
@@ -1776,11 +1858,12 @@ find_item_in_list(Item *find,List<Item> &items)
table_name= ((Item_ident*) find)->table_name;
}
- while ((item=li++))
+ for (uint i= 0; (item=li++); i++)
{
if (field_name && item->type() == Item::FIELD_ITEM)
{
- if (!my_strcasecmp(((Item_field*) item)->name,field_name))
+ if (!my_strcasecmp(system_charset_info,
+ ((Item_field*) item)->name,field_name))
{
if (!table_name)
{
@@ -1788,59 +1871,66 @@ find_item_in_list(Item *find,List<Item> &items)
{
if ((*found)->eq(item,0))
continue; // Same field twice (Access?)
- if (current_thd->where)
+ if (report_error != IGNORE_ERRORS)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
find->full_name(), current_thd->where);
return (Item**) 0;
}
- found=li.ref();
+ found= li.ref();
+ *counter= i;
}
else if (!strcmp(((Item_field*) item)->table_name,table_name))
{
- found=li.ref();
+ found= li.ref();
+ *counter= i;
break;
}
}
}
else if (!table_name && (item->eq(find,0) ||
- find->name &&
- !my_strcasecmp(item->name,find->name)))
+ find->name &&
+ !my_strcasecmp(system_charset_info,
+ item->name,find->name)))
{
- found=li.ref();
+ found= li.ref();
+ *counter= i;
break;
}
}
- if (!found && current_thd->where)
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
- find->full_name(),current_thd->where);
- return found;
+ if (found)
+ return found;
+ else if (report_error != REPORT_EXCEPT_NOT_FOUND)
+ {
+ if (report_error == REPORT_ALL_ERRORS)
+ my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
+ find->full_name(), current_thd->where);
+ return (Item **) 0;
+ }
+ else
+ return (Item **) not_found_item;
}
/****************************************************************************
-** Check that all given fields exists and fill struct with current data
+** Expand all '*' in given fields
****************************************************************************/
-int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
- bool set_query_id, List<Item> *sum_func_list,
- bool allow_sum_func)
+int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
+ List<Item> *sum_func_list,
+ uint wild_num)
{
+ if (!wild_num)
+ return 0;
reg2 Item *item;
List_iterator<Item> it(fields);
- DBUG_ENTER("setup_fields");
-
- thd->set_query_id=set_query_id;
- thd->allow_sum_func= allow_sum_func;
- thd->where="field list";
-
- while ((item=it++))
- {
- if (item->type() == Item::FIELD_ITEM &&
+ while ( wild_num && (item= it++))
+ {
+ if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*')
{
- uint elem=fields.elements;
+ uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
- ((Item_field*) item)->table_name,&it))
- DBUG_RETURN(-1); /* purecov: inspected */
+ ((Item_field*) item)->table_name, &it))
+ return (-1);
if (sum_func_list)
{
/*
@@ -1850,25 +1940,52 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/
sum_func_list->elements+= fields.elements - elem;
}
- }
- else
- {
- if (item->fix_fields(thd,tables))
- DBUG_RETURN(-1); /* purecov: inspected */
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
- sum_func_list)
- item->split_sum_func(*sum_func_list);
- thd->used_tables|=item->used_tables();
+ wild_num--;
}
}
- DBUG_RETURN(test(thd->fatal_error));
+ return 0;
}
+/****************************************************************************
+** Check that all given fields exists and fill struct with current data
+****************************************************************************/
+
+int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func)
+{
+ reg2 Item *item;
+ List_iterator<Item> it(fields);
+ DBUG_ENTER("setup_fields");
+
+ thd->set_query_id=set_query_id;
+ thd->allow_sum_func= allow_sum_func;
+ thd->where="field list";
+
+ Item **ref= ref_pointer_array;
+ while ((item= it++))
+ {
+ if (item->fix_fields(thd, tables, it.ref()) ||
+ item->check_cols(1))
+ DBUG_RETURN(-1); /* purecov: inspected */
+ item= *(it.ref()); //Item can be changed in fix fields
+ if (ref)
+ *(ref++)= item;
+ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
+ sum_func_list)
+ item->split_sum_func(ref_pointer_array, *sum_func_list);
+ thd->used_tables|=item->used_tables();
+ }
+ DBUG_RETURN(test(thd->net.report_error));
+}
/*
Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the
table structure accordingly
+
+ This has to be called for all tables that are used by items, as otherwise
+ table->map is not set and all Item_field will be regarded as const items.
*/
bool setup_tables(TABLE_LIST *tables)
@@ -2007,12 +2124,12 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
DBUG_ENTER("setup_conds");
thd->set_query_id=1;
- thd->cond_count=0;
- thd->allow_sum_func=0;
+
+ thd->cond_count= 0;
if (*conds)
{
thd->where="where clause";
- if ((*conds)->fix_fields(thd,tables))
+ if ((*conds)->fix_fields(thd, tables, conds) || (*conds)->check_cols(1))
DBUG_RETURN(1);
}
@@ -2023,7 +2140,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
/* Make a join an a expression */
thd->where="on clause";
- if (table->on_expr->fix_fields(thd,tables))
+ if (table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
+ table->on_expr->check_cols(1))
DBUG_RETURN(1);
thd->cond_count++;
@@ -2051,7 +2169,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
// TODO: This could be optimized to use hashed names if t2 had a hash
for (j=0 ; j < t2->fields ; j++)
{
- if (!my_strcasecmp(t1->field[i]->field_name,
+ if (!my_strcasecmp(system_charset_info,
+ t1->field[i]->field_name,
t2->field[j]->field_name))
{
Item_func_eq *tmp=new Item_func_eq(new Item_field(t1->field[i]),
@@ -2080,7 +2199,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
table->on_expr=and_conds(table->on_expr,cond_and);
}
}
- DBUG_RETURN(test(thd->fatal_error));
+ DBUG_RETURN(test(thd->net.report_error));
}
@@ -2100,7 +2219,7 @@ fill_record(List<Item> &fields,List<Item> &values)
while ((field=(Item_field*) f++))
{
value=v++;
- if (value->save_in_field(field->field, 0))
+ if (value->save_in_field(field->field, 0) > 0)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -2118,7 +2237,7 @@ fill_record(Field **ptr,List<Item> &values)
while ((field = *ptr++))
{
value=v++;
- if (value->save_in_field(field, 0))
+ if (value->save_in_field(field, 0) == 1)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -2127,39 +2246,41 @@ fill_record(Field **ptr,List<Item> &values)
static void mysql_rm_tmp_tables(void)
{
- uint idx;
- char filePath[FN_REFLEN];
+ uint i, idx;
+ char filePath[FN_REFLEN], *tmpdir;
MY_DIR *dirp;
FILEINFO *file;
DBUG_ENTER("mysql_rm_tmp_tables");
+ for (i=0; i<=mysql_tmpdir_list.max; i++)
+ {
+ tmpdir=mysql_tmpdir_list.list[i];
/* See if the directory exists */
- if (!(dirp = my_dir(mysql_tmpdir,MYF(MY_WME | MY_DONT_SORT))))
- DBUG_VOID_RETURN; /* purecov: inspected */
+ if (!(dirp = my_dir(tmpdir,MYF(MY_WME | MY_DONT_SORT))))
+ continue;
- /*
- ** Remove all SQLxxx tables from directory
- */
+ /* Remove all SQLxxx tables from directory */
for (idx=2 ; idx < (uint) dirp->number_off_files ; idx++)
{
file=dirp->dir_entry+idx;
if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length))
{
- sprintf(filePath,"%s%s",mysql_tmpdir,file->name); /* purecov: inspected */
- VOID(my_delete(filePath,MYF(MY_WME))); /* purecov: inspected */
+ sprintf(filePath,"%s%s",tmpdir,file->name);
+ VOID(my_delete(filePath,MYF(MY_WME)));
}
}
my_dirend(dirp);
+ }
DBUG_VOID_RETURN;
}
/*
-** CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
-** the proper arguments. This isn't very fast but it should work for most
-** cases.
-** One should normally create all indexes with CREATE TABLE or ALTER TABLE.
+ CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
+ the proper arguments. This isn't very fast but it should work for most
+ cases.
+ One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
@@ -2171,9 +2292,11 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
+ /* TODO: Fix to use database character set */
+ create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
- fields, keys, drop, alter, (ORDER*)0, FALSE,
+ fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR));
}
@@ -2187,9 +2310,10 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
- fields, keys, drop, alter, (ORDER*)0, FALSE,
+ fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR));
}
@@ -2286,10 +2410,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
DBUG_RETURN(result);
}
-int setup_ftfuncs(THD *thd)
+int setup_ftfuncs(SELECT_LEX *select_lex)
{
- List_iterator<Item_func_match> li(thd->lex.select->ftfunc_list),
- lj(thd->lex.select->ftfunc_list);
+ List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)),
+ lj(*(select_lex->ftfunc_list));
Item_func_match *ftf, *ftf2;
while ((ftf=li++))
@@ -2308,11 +2432,11 @@ int setup_ftfuncs(THD *thd)
}
-int init_ftfuncs(THD *thd, bool no_order)
+int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
{
- if (thd->lex.select->ftfunc_list.elements)
+ if (select_lex->ftfunc_list->elements)
{
- List_iterator<Item_func_match> li(thd->lex.select->ftfunc_list);
+ List_iterator<Item_func_match> li(*(select_lex->ftfunc_list));
Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT initialization";
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 64c62345182..90fd61ebeb7 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -278,6 +278,21 @@ TODO list:
- Move MRG_MYISAM table type processing to handlers, something like:
tables_used->table->file->register_used_filenames(callback,
first_argument);
+ - Make derived tables cachable.
+ - QC improvement suggested by Monty:
+ - Add a counter in open_table() for how many MERGE (ISAM or MyISAM)
+ tables are cached in the table cache.
+ (This will be trivial when we have the new table cache in place I
+ have been working on)
+ - After this we can add the following test around the for loop in
+ is_cacheable::
+
+ if (thd->temp_tables || global_merge_table_count)
+
+ - Another option would be to set thd->lex.safe_to_cache_query to 0
+ in 'get_lock_data' if any of the tables was a tmp table or a
+ MRG_ISAM table.
+ (This could be done with almost no speed penalty)
*/
#include "mysql_priv.h"
@@ -292,7 +307,6 @@ TODO list:
#else
#include "../myisammrg/myrg_def.h"
#endif
-#include <assert.h>
#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
@@ -342,12 +356,6 @@ TODO list:
#define DUMP(C)
#endif
-#ifdef FN_NO_CASE_SENCE
-#define DB_NAME_PREPROCESS(C) tolower(C)
-#else
-#define DB_NAME_PREPROCESS(C) (C)
-#endif
-
const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS };
TYPELIB query_cache_type_typelib=
{
@@ -746,7 +754,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
if ((local_tables = is_cacheable(thd, thd->query_length,
thd->query, &thd->lex, tables_used)))
{
- NET *net = &thd->net;
+ NET *net= &thd->net;
byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
STRUCT_LOCK(&structure_guard_mutex);
@@ -849,6 +857,7 @@ end:
DBUG_VOID_RETURN;
}
+
/*
Check if the query is in the cache. If it was cached, send it
to the user.
@@ -859,8 +868,6 @@ end:
-1 The query was cached but we didn't have rights to use it.
No error is sent to the client yet.
*/
-
-
int
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
@@ -885,7 +892,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
/* Check that we haven't forgot to reset the query cache variables */
DBUG_ASSERT(thd->net.query_cache_query == 0);
- if (!thd->safe_to_cache_query)
+ if (!thd->lex.safe_to_cache_query)
{
DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
goto err;
@@ -895,8 +902,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Test if the query is a SELECT
(pre-space is removed in dispatch_command)
*/
- if (toupper(sql[0]) != 'S' || toupper(sql[1]) != 'E' ||
- toupper(sql[2]) !='L')
+ if (my_toupper(system_charset_info, sql[0]) != 'S' ||
+ my_toupper(system_charset_info, sql[1]) != 'E' ||
+ my_toupper(system_charset_info,sql[2]) !='L')
{
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
@@ -978,7 +986,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
table_list.db, table_list.alias));
refused++; // This is actually a hit
STRUCT_UNLOCK(&structure_guard_mutex);
- thd->safe_to_cache_query=0; // Don't try to cache this
+ thd->lex.safe_to_cache_query=0; // Don't try to cache this
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(-1); // Privilege error
}
@@ -987,7 +995,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s",
table_list.db, table_list.alias));
BLOCK_UNLOCK_RD(query_block);
- thd->safe_to_cache_query=0; // Don't try to cache this
+ thd->lex.safe_to_cache_query=0; // Don't try to cache this
goto err_unlock; // Parse query
}
}
@@ -1006,11 +1014,13 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
ALIGN_SIZE(sizeof(Query_cache_result))));
Query_cache_result *result = result_block->result();
+#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
if (net_real_write(&thd->net, result->data(),
result_block->used -
result_block->headers_len() -
ALIGN_SIZE(sizeof(Query_cache_result))))
break; // Client aborted
+#endif
result_block = result_block->next;
} while (result_block != first_result_block);
@@ -1046,6 +1056,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
for (; tables_used; tables_used=tables_used->next)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
+ if (tables_used->derived)
+ continue;
if (using_transactions &&
tables_used->table->file->has_transactions())
/*
@@ -1383,16 +1395,16 @@ ulong Query_cache::init_cache()
DUMP(this);
- VOID(hash_init(&queries,def_query_hash_size, 0, 0,
+ VOID(hash_init(&queries,system_charset_info,def_query_hash_size, 0, 0,
query_cache_query_get_key, 0, 0));
#ifndef FN_NO_CASE_SENCE
- VOID(hash_init(&tables,def_table_hash_size, 0, 0,
+ VOID(hash_init(&tables,system_charset_info,def_table_hash_size, 0, 0,
query_cache_table_get_key, 0, 0));
#else
// windows, OS/2 or other case insensitive file names work around
- VOID(hash_init(&tables,def_table_hash_size, 0, 0,
+ VOID(hash_init(&tables,system_charset_info,def_table_hash_size, 0, 0,
query_cache_table_get_key, 0,
- (lower_case_table_names?0:HASH_CASE_INSENSITIVE)));
+ (lower_case_table_names?0:HASH_CASE_INSENSITIVE)));
#endif
queries_in_cache = 0;
@@ -2439,14 +2451,14 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
if (lex->sql_command == SQLCOM_SELECT &&
(thd->variables.query_cache_type == 1 ||
- (thd->variables.query_cache_type == 2 && (lex->select->options &
+ (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
OPTION_TO_QUERY_CACHE))) &&
- thd->safe_to_cache_query)
+ lex->safe_to_cache_query)
{
my_bool has_transactions = 0;
DBUG_PRINT("qcache", ("options %lx %lx, type %u",
OPTION_TO_QUERY_CACHE,
- lex->select->options,
+ lex->select_lex.options,
(int) thd->variables.query_cache_type));
for (; tables_used; tables_used= tables_used->next)
@@ -2460,12 +2472,20 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
if (tables_used->table->db_type == DB_TYPE_MRG_ISAM ||
tables_used->table->tmp_table != NO_TMP_TABLE ||
- (tables_used->db_length == 5 &&
- DB_NAME_PREPROCESS(tables_used->db[0])=='m' &&
- DB_NAME_PREPROCESS(tables_used->db[1])=='y' &&
- DB_NAME_PREPROCESS(tables_used->db[2])=='s' &&
- DB_NAME_PREPROCESS(tables_used->db[3])=='q' &&
- DB_NAME_PREPROCESS(tables_used->db[4])=='l'))
+ (tables_used->db_length == 5 &&
+#ifdef FN_NO_CASE_SENCE
+ // TODO: latin1 charset should be replaced with system charset
+ my_strncasecmp(&my_charset_latin1,
+ tables_used->db,
+ "mysql",5) == 0
+#else
+ tables_used->db[0]=='m' &&
+ tables_used->db[1]=='y' &&
+ tables_used->db[2]=='s' &&
+ tables_used->db[3]=='q' &&
+ tables_used->db[4]=='l'
+#endif
+ ))
{
DBUG_PRINT("qcache",
("select not cacheable: used MRG_ISAM, temporary or system table(s)"));
@@ -2493,7 +2513,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
("not interesting query: %d or not cacheable, options %lx %lx, type %u",
(int) lex->sql_command,
OPTION_TO_QUERY_CACHE,
- lex->select->options,
+ lex->select_lex.options,
(int) thd->variables.query_cache_type));
DBUG_RETURN(0);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 727807415da..23a8a6fa8f1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -35,7 +35,6 @@
#include <io.h>
#endif
#include <mysys_err.h>
-#include <assert.h>
/*****************************************************************************
@@ -78,35 +77,40 @@ extern "C" void free_user_var(user_var_entry *entry)
** Thread specific functions
****************************************************************************/
-THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
- insert_id_used(0),rand_used(0),in_lock_tables(0),
- global_read_lock(0),bootstrap(0)
+THD::THD():user_time(0), is_fatal_error(0),
+ last_insert_id_used(0),
+ insert_id_used(0), rand_used(0), in_lock_tables(0),
+ global_read_lock(0), bootstrap(0)
{
host=user=priv_user=db=query=ip=0;
host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
- query_start_used=safe_to_cache_query=0;
+ query_start_used=prepare_command=0;
db_length=query_length=col_access=0;
- query_error=0;
+ query_error= tmp_table_used= 0;
next_insert_id=last_insert_id=0;
- open_tables=temporary_tables=handler_tables=0;
+ open_tables= temporary_tables= handler_tables= derived_tables= 0;
current_tablenr=0;
handler_items=0;
tmp_table=0;
lock=locked_tables=0;
used_tables=0;
- cuted_fields=sent_row_count=0L;
+ cuted_fields= sent_row_count= current_stmt_id= 0L;
start_time=(time_t) 0;
current_linfo = 0;
slave_thread = 0;
- slave_proxy_id = 0;
+ variables.pseudo_thread_id= 0;
file_id = 0;
cond_count=0;
+ warn_id= 0;
+ db_charset=default_charset_info;
mysys_var=0;
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
-#endif
+#endif
+#ifndef EMBEDDED_LIBRARY
net.vio=0;
+#endif
net.last_error[0]=0; // If error on boot
ull=0;
system_thread=cleanup_done=0;
@@ -134,10 +138,36 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
+ bzero((char*) &con_root,sizeof(con_root));
+ bzero((char*) &warn_root,sizeof(warn_root));
+ init_alloc_root(&warn_root, 1024, 0);
user_connect=(USER_CONN *)0;
- hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
+ hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(hash_free_key) free_user_var,0);
+
+ /* For user vars replication*/
+ if (opt_bin_log)
+ my_init_dynamic_array(&user_var_events,
+ sizeof(BINLOG_USER_VAR_EVENT *),
+ 16,
+ 16);
+ else
+ bzero((char*) &user_var_events, sizeof(user_var_events));
+
+
+
+ /* Prepared statements */
+ last_prepared_stmt= 0;
+ init_tree(&prepared_statements, 0, 0, sizeof(PREP_STMT),
+ (qsort_cmp2) compare_prep_stmt, 1,
+ (tree_element_free) free_prep_stmt, 0);
+
+ /* Protocol */
+ protocol= &protocol_simple; // Default protocol
+ protocol_simple.init(this);
+ protocol_prep.init(this);
+
#ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction));
if (opt_using_transactions)
@@ -171,15 +201,18 @@ void THD::init(void)
{
pthread_mutex_lock(&LOCK_global_system_variables);
variables= global_system_variables;
+ variables.thd_charset=default_charset_info;
pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT;
options= thd_startup_options;
- sql_mode=(uint) opt_sql_mode;
open_options=ha_open_options;
update_lock_default= (variables.low_priority_updates ?
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
+ warn_list.empty();
+ bzero((char*) warn_count, sizeof(warn_count));
+ total_warn_count= 0;
}
/*
@@ -196,11 +229,11 @@ void THD::init(void)
void THD::change_user(void)
{
cleanup();
- cleanup_done=0;
+ cleanup_done= 0;
init();
- hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
+ hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
- (hash_free_key) free_user_var,0);
+ (hash_free_key) free_user_var, 0);
}
@@ -210,6 +243,7 @@ void THD::cleanup(void)
{
DBUG_ENTER("THD::cleanup");
ha_rollback(this);
+ delete_tree(&prepared_statements);
if (locked_tables)
{
lock=locked_tables; locked_tables=0;
@@ -221,6 +255,7 @@ void THD::cleanup(void)
close_thread_tables(this);
}
close_temporary_tables(this);
+ delete_dynamic(&user_var_events);
hash_free(&user_vars);
if (global_read_lock)
unlock_global_read_lock(this);
@@ -245,11 +280,13 @@ THD::~THD()
pthread_mutex_unlock(&LOCK_delete);
/* Close connection */
+#ifndef EMBEDDED_LIBRARY
if (net.vio)
{
vio_delete(net.vio);
net_end(&net);
}
+#endif
if (!cleanup_done)
cleanup();
#ifdef USING_TRANSACTIONS
@@ -268,6 +305,8 @@ THD::~THD()
safeFree(db);
safeFree(ip);
free_root(&mem_root,MYF(0));
+ free_root(&con_root,MYF(0));
+ free_root(&warn_root,MYF(0));
free_root(&transaction.mem_root,MYF(0));
mysys_var=0; // Safety (shouldn't be needed)
pthread_mutex_destroy(&LOCK_delete);
@@ -318,8 +357,7 @@ void THD::awake(bool prepare_to_die)
bool THD::store_globals()
{
if (my_pthread_setspecific_ptr(THR_THD, this) ||
- my_pthread_setspecific_ptr(THR_MALLOC, &mem_root) ||
- my_pthread_setspecific_ptr(THR_NET, &net))
+ my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
return 1;
mysys_var=my_thread_var;
dbug_thread_id=my_thread_id();
@@ -415,19 +453,45 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
return new_table;
}
+int THD::send_explain_fields(select_result *result)
+{
+ List<Item> field_list;
+ Item *item;
+ field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("select_type",19));
+ field_list.push_back(new Item_empty_string("table",NAME_LEN));
+ field_list.push_back(new Item_empty_string("type",10));
+ field_list.push_back(item=new Item_empty_string("possible_keys",
+ NAME_LEN*MAX_KEY));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_return_int("key_len",3,
+ MYSQL_TYPE_LONGLONG));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("ref",
+ NAME_LEN*MAX_REF_PARTS));
+ item->maybe_null=1;
+ field_list.push_back(new Item_return_int("rows",10, MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("Extra",255));
+ return (result->send_fields(field_list,1));
+}
#ifdef SIGNAL_WITH_VIO_CLOSE
void THD::close_active_vio()
{
safe_mutex_assert_owner(&LOCK_delete);
+#ifndef EMBEDDED_LIBRARY
if (active_vio)
{
vio_close(active_vio);
active_vio = 0;
}
+#endif
}
#endif
+
/*****************************************************************************
** Functions to provide a interface to select results
*****************************************************************************/
@@ -437,8 +501,10 @@ select_result::select_result()
thd=current_thd;
}
-static String default_line_term("\n"),default_escaped("\\"),
- default_field_term("\t");
+static String
+ default_line_term("\n",default_charset_info),
+ default_escaped("\\",default_charset_info),
+ default_field_term("\t",default_charset_info);
sql_exchange::sql_exchange(char *name,bool flag)
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
@@ -451,37 +517,40 @@ sql_exchange::sql_exchange(char *name,bool flag)
bool select_send::send_fields(List<Item> &list,uint flag)
{
- return ::send_fields(thd,list,flag);
+ return thd->protocol->send_fields(&list,flag);
}
-
/* Send data to client. Returns 0 if ok */
bool select_send::send_data(List<Item> &items)
{
+ if (unit->offset_limit_cnt)
+ { // using limit offset,count
+ unit->offset_limit_cnt--;
+ return 0;
+ }
+
List_iterator_fast<Item> li(items);
- String *packet= &thd->packet;
+ Protocol *protocol= thd->protocol;
+ char buff[MAX_FIELD_WIDTH];
+ String buffer(buff, sizeof(buff), &my_charset_bin);
DBUG_ENTER("send_data");
- if (thd->offset_limit)
- { // using limit offset,count
- thd->offset_limit--;
- DBUG_RETURN(0);
- }
- packet->length(0); // Reset packet
+ protocol->prepare_for_resend();
Item *item;
while ((item=li++))
{
- if (item->send(thd, packet))
+ if (item->send(protocol, &buffer))
{
- packet->free(); // Free used
- my_error(ER_OUT_OF_RESOURCES,MYF(0));
- DBUG_RETURN(1);
+ protocol->free(); // Free used buffer
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ break;
}
}
thd->sent_row_count++;
- bool error=my_net_write(&thd->net,(char*) packet->ptr(),packet->length());
- DBUG_RETURN(error);
+ if (!thd->net.report_error)
+ DBUG_RETURN(protocol->write());
+ DBUG_RETURN(1);
}
bool select_send::send_eof()
@@ -491,8 +560,13 @@ bool select_send::send_eof()
{
mysql_unlock_tables(thd, thd->lock); thd->lock=0;
}
- ::send_eof(&thd->net);
- return 0;
+ if (!thd->net.report_error)
+ {
+ ::send_eof(thd);
+ return 0;
+ }
+ else
+ return 1;
}
@@ -513,11 +587,12 @@ select_export::~select_export()
}
int
-select_export::prepare(List<Item> &list)
+select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
char path[FN_REFLEN];
uint option=4;
bool blob_flag=0;
+ unit= u;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|=1; // Force use of db directory
#endif
@@ -527,7 +602,7 @@ select_export::prepare(List<Item> &list)
option);
if (!access(path,F_OK))
{
- my_error(ER_FILE_EXISTS_ERROR,MYF(0),exchange->file_name);
+ my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
return 1;
}
/* Create the file world readable */
@@ -581,12 +656,12 @@ bool select_export::send_data(List<Item> &items)
DBUG_ENTER("send_data");
char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
bool space_inited=0;
- String tmp(buff,sizeof(buff)),*res;
+ String tmp(buff,sizeof(buff),&my_charset_bin),*res;
tmp.length(0);
- if (thd->offset_limit)
+ if (unit->offset_limit_cnt)
{ // using limit offset,count
- thd->offset_limit--;
+ unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
row_count++;
@@ -642,10 +717,11 @@ bool select_export::send_data(List<Item> &items)
pos++)
{
#ifdef USE_MB
- if (use_mb(default_charset_info))
+ CHARSET_INFO *res_charset=res->charset();
+ if (use_mb(res_charset))
{
int l;
- if ((l=my_ismbchar(default_charset_info, pos, end)))
+ if ((l=my_ismbchar(res_charset, pos, end)))
{
pos += l-1;
continue;
@@ -713,9 +789,9 @@ err:
}
-void select_export::send_error(uint errcode,const char *err)
+void select_export::send_error(uint errcode, const char *err)
{
- ::send_error(&thd->net,errcode,err);
+ my_message(errcode, err, MYF(0));;
(void) end_io_cache(&cache);
(void) my_close(file,MYF(0));
file= -1;
@@ -727,10 +803,8 @@ bool select_export::send_eof()
int error=test(end_io_cache(&cache));
if (my_close(file,MYF(MY_WME)))
error=1;
- if (error)
- ::send_error(&thd->net);
- else
- ::send_ok(&thd->net,row_count);
+ if (!error)
+ ::send_ok(thd,row_count);
file= -1;
return error;
}
@@ -752,9 +826,11 @@ select_dump::~select_dump()
}
int
-select_dump::prepare(List<Item> &list __attribute__((unused)))
+select_dump::prepare(List<Item> &list __attribute__((unused)),
+ SELECT_LEX_UNIT *u)
{
uint option=4;
+ unit= u;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|=1; // Force use of db directory
#endif
@@ -788,19 +864,19 @@ bool select_dump::send_data(List<Item> &items)
{
List_iterator_fast<Item> li(items);
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff)),*res;
+ String tmp(buff,sizeof(buff),&my_charset_bin),*res;
tmp.length(0);
Item *item;
DBUG_ENTER("send_data");
- if (thd->offset_limit)
+ if (unit->offset_limit_cnt)
{ // using limit offset,count
- thd->offset_limit--;
+ unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
if (row_count++ > 1)
{
- my_error(ER_TOO_MANY_ROWS,MYF(0));
+ my_error(ER_TOO_MANY_ROWS, MYF(0));
goto err;
}
while ((item=li++))
@@ -825,23 +901,122 @@ err:
void select_dump::send_error(uint errcode,const char *err)
{
- ::send_error(&thd->net,errcode,err);
+ my_message(errcode, err, MYF(0));
(void) end_io_cache(&cache);
(void) my_close(file,MYF(0));
(void) my_delete(path,MYF(0)); // Delete file on error
file= -1;
}
-
bool select_dump::send_eof()
{
int error=test(end_io_cache(&cache));
if (my_close(file,MYF(MY_WME)))
error=1;
- if (error)
- ::send_error(&thd->net);
- else
- ::send_ok(&thd->net,row_count);
+ if (!error)
+ ::send_ok(thd,row_count);
file= -1;
return error;
}
+
+select_subselect::select_subselect(Item_subselect *item)
+{
+ this->item=item;
+}
+
+bool select_singlerow_subselect::send_data(List<Item> &items)
+{
+ DBUG_ENTER("select_singlerow_subselect::send_data");
+ Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
+ if (it->assigned())
+ {
+ my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
+ DBUG_RETURN(1);
+ }
+ if (unit->offset_limit_cnt)
+ { // Using limit offset,count
+ unit->offset_limit_cnt--;
+ DBUG_RETURN(0);
+ }
+ List_iterator_fast<Item> li(items);
+ Item *val_item;
+ for (uint i= 0; (val_item= li++); i++)
+ it->store(i, val_item);
+ it->assigned(1);
+ DBUG_RETURN(0);
+}
+
+bool select_exists_subselect::send_data(List<Item> &items)
+{
+ DBUG_ENTER("select_exists_subselect::send_data");
+ Item_exists_subselect *it= (Item_exists_subselect *)item;
+ if (unit->offset_limit_cnt)
+ { // Using limit offset,count
+ unit->offset_limit_cnt--;
+ DBUG_RETURN(0);
+ }
+ it->value= 1;
+ it->assigned(1);
+ DBUG_RETURN(0);
+}
+
+
+/***************************************************************************
+** Dump of select to variables
+***************************************************************************/
+int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
+{
+ List_iterator_fast<Item> li(list);
+ List_iterator_fast<LEX_STRING> gl(var_list);
+ Item *item;
+ LEX_STRING *ls;
+ if (var_list.elements != list.elements)
+ {
+ my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, MYF(0));
+ return 1;
+ }
+ unit=u;
+ while ((item=li++))
+ {
+ ls= gl++;
+ Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
+ xx->fix_fields(thd,(TABLE_LIST*) thd->lex.select_lex.table_list.first,&item);
+ xx->fix_length_and_dec();
+ vars.push_back(xx);
+ }
+ return 0;
+}
+bool select_dumpvar::send_data(List<Item> &items)
+{
+ List_iterator_fast<Item_func_set_user_var> li(vars);
+ Item_func_set_user_var *xx;
+ DBUG_ENTER("send_data");
+
+ if (unit->offset_limit_cnt)
+ { // Using limit offset,count
+ unit->offset_limit_cnt--;
+ DBUG_RETURN(0);
+ }
+ if (row_count++)
+ {
+ my_error(ER_TOO_MANY_ROWS, MYF(0));
+ DBUG_RETURN(1);
+ }
+ while ((xx=li++))
+ xx->update();
+ DBUG_RETURN(0);
+}
+
+bool select_dumpvar::send_eof()
+{
+ if (row_count)
+ {
+ ::send_ok(thd,row_count);
+ return 0;
+ }
+ else
+ {
+ my_error(ER_EMPTY_QUERY,MYF(0));
+ return 1;
+ }
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 802052d553a..ccbd7a194f2 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -29,12 +29,12 @@ class Slave_log_event;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY };
-enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE };
+enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE, DUP_UPDATE };
enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
DELAY_KEY_WRITE_ALL };
-// log info errors
+// log info errors
#define LOG_INFO_EOF -1
#define LOG_INFO_IO -2
#define LOG_INFO_INVALID -3
@@ -57,6 +57,15 @@ typedef struct st_log_info
~st_log_info() { pthread_mutex_destroy(&lock);}
} LOG_INFO;
+typedef struct st_user_var_events
+{
+ user_var_entry *user_var_event;
+ char *value;
+ ulong length;
+ Item_result type;
+ uint charset_number;
+} BINLOG_USER_VAR_EVENT;
+
class Log_event;
class MYSQL_LOG {
@@ -73,14 +82,14 @@ class MYSQL_LOG {
// current file sequence number for load data infile binary logging
uint file_id;
uint open_count; // For replication
+ volatile enum_log_type log_type;
+ enum cache_type io_cache_type;
+ bool write_error,inited;
/*
For binlog - if log name can never change we should not try to rotate it
or write any rotation events. The user should use FLUSH MASTER instead
of FLUSH LOGS for purging.
*/
- volatile enum_log_type log_type;
- enum cache_type io_cache_type;
- bool write_error,inited;
bool no_rotate;
bool need_start_event;
bool no_auto_events; // for relay binlog
@@ -178,6 +187,12 @@ public:
{
convert_array(from_map, (uchar*) a,length);
}
+ char *store_dest(char *to, const char *from, uint length)
+ {
+ for (const char *end=from+length ; from != end ; from++)
+ *to++= to_map[(uchar) *from];
+ return to;
+ }
bool store(String *, const char *,uint);
inline uint number() { return numb; }
};
@@ -189,6 +204,9 @@ typedef struct st_copy_info {
ha_rows error_count;
enum enum_duplicates handle_duplicates;
int escape_char, last_errno;
+/* for INSERT ... UPDATE */
+ List<Item> *update_fields;
+ List<Item> *update_values;
} COPY_INFO;
@@ -221,19 +239,40 @@ public:
class Key :public Sql_alloc {
public:
- enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT };
+ enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
enum Keytype type;
enum ha_key_alg algorithm;
List<key_part_spec> columns;
- const char *Name;
+ const char *name;
- Key(enum Keytype type_par,const char *name_arg,List<key_part_spec> &cols)
- :type(type_par), algorithm(HA_KEY_ALG_UNDEF), columns(cols), Name(name_arg)
+ Key(enum Keytype type_par, const char *name_arg, enum ha_key_alg alg_par,
+ List<key_part_spec> &cols)
+ :type(type_par), algorithm(alg_par), columns(cols), name(name_arg)
{}
~Key() {}
- const char *name() { return Name; }
};
+class Table_ident;
+
+class foreign_key: public Key {
+public:
+ enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
+ FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
+ enum fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
+ FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT};
+
+ Table_ident *ref_table;
+ List<key_part_spec> ref_columns;
+ uint delete_opt, update_opt, match_opt;
+ foreign_key(const char *name_arg, List<key_part_spec> &cols,
+ Table_ident *table, List<key_part_spec> &ref_cols,
+ uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
+ :Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, cols),
+ ref_table(table), ref_columns(cols),
+ delete_opt(delete_opt_arg), update_opt(update_opt_arg),
+ match_opt(match_opt_arg)
+ {}
+};
typedef struct st_mysql_lock
{
@@ -253,8 +292,8 @@ public:
#include "sql_lex.h" /* Must be here */
-// needed to be able to have an I_List of char* strings.in mysqld.cc where we cannot use String
-// because it is Sql_alloc'ed
+/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
+
class i_string: public ilink
{
public:
@@ -263,7 +302,7 @@ public:
i_string(char* s) : ptr(s) {}
};
-//needed for linked list of two strings for replicate-rewrite-db
+/* needed for linked list of two strings for replicate-rewrite-db */
class i_string_pair: public ilink
{
public:
@@ -274,11 +313,52 @@ public:
};
+class MYSQL_ERROR: public Sql_alloc
+{
+public:
+ enum enum_warning_level
+ { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
+
+ uint code;
+ enum_warning_level level;
+ char *msg;
+
+ MYSQL_ERROR(uint code_arg, enum_warning_level level_arg,
+ const char *msg_arg)
+ :code(code_arg), level(level_arg)
+ {
+ msg=sql_strdup(msg_arg);
+ }
+};
+
+
+/* This is a struct as it's allocated in tree_insert */
+
+typedef struct st_prep_stmt
+{
+ THD *thd;
+ LEX lex;
+ Item_param **param;
+ Item *free_list;
+ MEM_ROOT mem_root;
+ ulong stmt_id;
+ uint param_count;
+ uint last_errno;
+ char last_error[MYSQL_ERRMSG_SIZE];
+ bool error_in_prepare, long_data_used;
+} PREP_STMT;
+
+
class delayed_insert;
+class select_result;
#define THD_SENTRY_MAGIC 0xfeedd1ff
#define THD_SENTRY_GONE 0xdeadbeef
+#ifdef EMBEDDED_LIBRARY
+typedef struct st_mysql;
+#endif
+
#define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC)
struct system_variables
@@ -291,31 +371,41 @@ struct system_variables
ulong join_buff_size;
ulong long_query_time;
ulong max_allowed_packet;
+ ulong max_error_count;
ulong max_heap_table_size;
+ ulong max_prep_stmt_count;
ulong max_sort_length;
ulong max_tmp_tables;
ulong myisam_sort_buff_size;
ulong net_buffer_length;
ulong net_interactive_timeout;
ulong net_read_timeout;
+ ulong net_retry_count;
ulong net_wait_timeout;
ulong net_write_timeout;
- ulong net_retry_count;
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
ulong sortbuff_size;
+ ulong table_type;
ulong tmp_table_size;
ulong tx_isolation;
- ulong table_type;
+ ulong sql_mode;
+
+ /*
+ In slave thread we need to know in behalf of which
+ thread the query is being run to replicate temp tables properly
+ */
+ ulong pseudo_thread_id;
my_bool log_warnings;
my_bool low_priority_updates;
- CONVERT *convert_set;
+ CONVERT *convert_set;
+ CHARSET_INFO *thd_charset;
};
-
+void free_tmp_table(THD *thd, TABLE *entry);
/*
For each client connection we create a separate thread with THD serving as
a thread/connection descriptor
@@ -324,10 +414,19 @@ struct system_variables
class THD :public ilink
{
public:
+#ifdef EMBEDDED_LIBRARY
+ struct st_mysql *mysql;
+#endif
NET net; // client connection descriptor
LEX lex; // parse tree descriptor
MEM_ROOT mem_root; // 1 command-life memory pool
+ MEM_ROOT con_root; // connection-life memory
+ MEM_ROOT warn_root; // For warnings and errors
+ Protocol *protocol; // Current protocol
+ Protocol_simple protocol_simple; // Normal protocol
+ Protocol_prep protocol_prep; // Binary protocol
HASH user_vars; // hash for user variables
+ TREE prepared_statements;
String packet; // dynamic buffer for network I/O
struct sockaddr_in remote; // client socket address
struct rand_struct rand; // used for authentication
@@ -345,8 +444,7 @@ public:
host - host of the client
user - user of the client, set to NULL until the user has been read from
the connection
- priv_user - not sure why we have it, but it is set to "boot" when we run
- with --bootstrap
+ priv_user - The user privilege we are using. May be '' for anonymous user.
db - currently selected database
ip - client IP
*/
@@ -357,24 +455,24 @@ public:
/* points to host if host is available, otherwise points to ip */
const char *host_or_ip;
- uint client_capabilities; /* What the client supports */
+ ulong client_capabilities; /* What the client supports */
/* Determines if which non-standard SQL behaviour should be enabled */
- uint sql_mode;
ulong max_client_packet_length;
ulong master_access; /* Global privileges from mysql.user */
ulong db_access; /* Privileges for current db */
-
/*
open_tables - list of regular tables in use by this thread
temporary_tables - list of temp tables in use by this thread
handler_tables - list of tables that were opened with HANDLER OPEN
and are still in use by this thread
*/
- TABLE *open_tables,*temporary_tables, *handler_tables;
+ TABLE *open_tables,*temporary_tables, *handler_tables, *derived_tables;
// TODO: document the variables below
- MYSQL_LOCK *lock,*locked_tables;
- ULL *ull;
+ MYSQL_LOCK *lock; /* Current locks */
+ MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */
+ ULL *ull;
+ PREP_STMT *last_prepared_stmt;
#ifndef DBUG_OFF
uint dbug_sentry; // watch out for memory corruption
#endif
@@ -420,7 +518,13 @@ public:
sent_row_count, examined_row_count;
table_map used_tables;
USER_CONN *user_connect;
- ulong query_id,version, options,thread_id, col_access;
+ CHARSET_INFO *db_charset;
+ List<TABLE> temporary_tables_should_be_free; // list of temporary tables
+ List <MYSQL_ERROR> warn_list;
+ uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
+ uint total_warn_count, old_total_warn_count;
+ ulong query_id, warn_id, version, options, thread_id, col_access;
+ ulong current_stmt_id;
ulong rand_saved_seed1, rand_saved_seed2;
long dbug_thread_id;
pthread_t real_id;
@@ -428,32 +532,34 @@ public:
uint server_status,open_options;
uint32 query_length;
uint32 db_length;
+ uint select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
- char scramble[9];
+ /* for user variables replication*/
+ DYNAMIC_ARRAY user_var_events;
+ // extend scramble to handle new auth
+ char scramble[SCRAMBLE41_LENGTH+1];
+ // old scramble is needed to handle old clients
+ char old_scramble[SCRAMBLE_LENGTH+1];
uint8 query_cache_type; // type of query cache processing
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
- bool no_errors, allow_sum_func, password, fatal_error;
+ bool no_errors, allow_sum_func, password, is_fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
bool system_thread,in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
- bool safe_to_cache_query;
bool volatile killed;
+ bool prepare_command;
+ bool tmp_table_used;
+
/*
If we do a purge of binary logs, log index info of the threads
that are currently reading it needs to be adjusted. To do that
each thread that is using LOG_INFO needs to adjust the pointer to it
*/
LOG_INFO* current_linfo;
- /*
- In slave thread we need to know in behalf of which
- thread the query is being run to replicate temp tables properly
- */
- ulong slave_proxy_id;
NET* slave_net; // network connection from slave -> m.
my_off_t log_pos;
-
/* Used by the sys_var class to store temporary values */
union
{
@@ -463,6 +569,7 @@ public:
THD();
~THD();
+
void init(void);
void change_user(void);
void cleanup(void);
@@ -557,6 +664,22 @@ public:
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, long key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
+ int send_explain_fields(select_result *result);
+#ifndef EMBEDDED_LIBRARY
+ inline void clear_error()
+ {
+ net.last_error[0]= 0;
+ net.last_errno= 0;
+ net.report_error= 0;
+ }
+#else
+ void clear_error();
+#endif
+ inline void fatal_error()
+ {
+ is_fatal_error= 1;
+ net.report_error= 1;
+ }
};
/*
@@ -578,26 +701,31 @@ public:
#include "log_event.h"
/*
-** This is used to get result from a select
+ This is used to get result from a select
*/
class JOIN;
-void send_error(NET *net,uint sql_errno=0, const char *err=0);
+void send_error(THD *thd, uint sql_errno=0, const char *err=0);
class select_result :public Sql_alloc {
protected:
THD *thd;
+ SELECT_LEX_UNIT *unit;
public:
select_result();
virtual ~select_result() {};
- virtual int prepare(List<Item> &list) { return 0; }
+ virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
+ {
+ unit= u;
+ return 0;
+ }
virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; }
virtual void send_error(uint errcode,const char *err)
{
- ::send_error(&thd->net,errcode,err);
+ my_message(errcode, err, MYF(0));
}
virtual bool send_eof()=0;
virtual void abort() {}
@@ -624,7 +752,7 @@ class select_export :public select_result {
public:
select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {}
~select_export();
- int prepare(List<Item> &list);
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
@@ -643,7 +771,7 @@ public:
select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L)
{ path[0]=0; }
~select_dump();
- int prepare(List<Item> &list);
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
@@ -666,7 +794,7 @@ class select_insert :public select_result {
info.handle_duplicates=duplic;
}
~select_insert();
- int prepare(List<Item> &list);
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items);
@@ -695,7 +823,7 @@ public:
create_info(create_info_par),
lock(0)
{}
- int prepare(List<Item> &list);
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &values);
bool send_eof();
void abort();
@@ -710,7 +838,7 @@ class select_union :public select_result {
select_union(TABLE *table_par);
~select_union();
- int prepare(List<Item> &list);
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items);
@@ -718,14 +846,45 @@ class select_union :public select_result {
bool flush();
};
+/* Base subselect interface class */
+class select_subselect :public select_result
+{
+protected:
+ Item_subselect *item;
+public:
+ select_subselect(Item_subselect *item);
+ bool send_fields(List<Item> &list, uint flag) { return 0; };
+ bool send_data(List<Item> &items)=0;
+ bool send_eof() { return 0; };
+
+ friend class Ttem_subselect;
+};
+
+/* Single value subselect interface class */
+class select_singlerow_subselect :public select_subselect
+{
+public:
+ select_singlerow_subselect(Item_subselect *item):select_subselect(item){}
+ bool send_data(List<Item> &items);
+};
+
+/* EXISTS subselect interface class */
+class select_exists_subselect :public select_subselect
+{
+public:
+ select_exists_subselect(Item_subselect *item):select_subselect(item){}
+ bool send_data(List<Item> &items);
+};
+
/* Structs used when sorting */
typedef struct st_sort_field {
Field *field; /* Field to sort */
Item *item; /* Item if not sorting fields */
uint length; /* Length of sort field */
- my_bool reverse; /* if descending sort */
Item_result result_type; /* Type of item */
+ bool reverse; /* if descending sort */
+ bool need_strxnfrm; /* If we have to use strxnfrm() */
} SORT_FIELD;
@@ -740,21 +899,33 @@ typedef struct st_sort_buffer {
/* Structure for db & table in sql_yacc */
-class Table_ident :public Sql_alloc {
+class Table_ident :public Sql_alloc
+{
public:
LEX_STRING db;
LEX_STRING table;
- inline Table_ident(LEX_STRING db_arg,LEX_STRING table_arg,bool force)
- :table(table_arg)
+ SELECT_LEX_UNIT *sel;
+ inline Table_ident(LEX_STRING db_arg, LEX_STRING table_arg, bool force)
+ :table(table_arg), sel((SELECT_LEX_UNIT *)0)
{
if (!force && (current_thd->client_capabilities & CLIENT_NO_SCHEMA))
db.str=0;
else
db= db_arg;
}
- inline Table_ident(LEX_STRING table_arg) :table(table_arg) {db.str=0;}
+ inline Table_ident(LEX_STRING table_arg)
+ :table(table_arg), sel((SELECT_LEX_UNIT *)0)
+ {
+ db.str=0;
+ }
+ inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
+ {
+ db.str=0; table.str=(char *)""; table.length=0;
+ }
inline void change_db(char *db_name)
- { db.str= db_name; db.length=(uint) strlen(db_name); }
+ {
+ db.str= db_name; db.length= (uint) strlen(db_name);
+ }
};
// this is needed for user_vars hash
@@ -763,8 +934,9 @@ class user_var_entry
public:
LEX_STRING name;
char *value;
- ulong length, update_query_id;
+ ulong length, update_query_id, used_query_id;
Item_result type;
+ CHARSET_INFO *var_charset;
};
/* Class for unique (removing of duplicates) */
@@ -787,7 +959,7 @@ public:
{
if (tree.elements_in_tree > max_elements && flush())
return 1;
- return !tree_insert(&tree,ptr,0);
+ return !tree_insert(&tree, ptr, 0, tree.custom_arg);
}
bool get(TABLE *table);
@@ -796,26 +968,28 @@ public:
friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique);
};
- class multi_delete : public select_result {
- TABLE_LIST *delete_tables, *table_being_deleted;
- Unique **tempfiles;
- THD *thd;
- ha_rows deleted;
- uint num_of_tables;
- int error;
- bool do_delete, transactional_tables, log_delayed, normal_tables;
- public:
- multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
- ~multi_delete();
- int prepare(List<Item> &list);
- bool send_fields(List<Item> &list,
+class multi_delete : public select_result
+{
+ TABLE_LIST *delete_tables, *table_being_deleted;
+ Unique **tempfiles;
+ THD *thd;
+ ha_rows deleted;
+ uint num_of_tables;
+ int error;
+ bool do_delete, transactional_tables, log_delayed, normal_tables;
+public:
+ multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
+ ~multi_delete();
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+ bool send_fields(List<Item> &list,
uint flag) { return 0; }
- bool send_data(List<Item> &items);
- bool initialize_tables (JOIN *join);
- void send_error(uint errcode,const char *err);
- int do_deletes (bool from_send_error);
- bool send_eof();
- };
+ bool send_data(List<Item> &items);
+ bool initialize_tables (JOIN *join);
+ void send_error(uint errcode,const char *err);
+ int do_deletes (bool from_send_error);
+ bool send_eof();
+};
+
class multi_update : public select_result
{
@@ -835,7 +1009,7 @@ public:
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> *fields,
List<Item> *values, enum_duplicates handle_duplicates);
~multi_update();
- int prepare(List<Item> &list);
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag) { return 0; }
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
@@ -844,3 +1018,16 @@ public:
bool send_eof();
};
+
+class select_dumpvar :public select_result {
+ ha_rows row_count;
+public:
+ List<LEX_STRING> var_list;
+ List<Item_func_set_user_var> vars;
+ select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
+ ~select_dumpvar() {}
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+ bool send_fields(List<Item> &list, uint flag) {return 0;}
+ bool send_data(List<Item> &items);
+ bool send_eof();
+};
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 900c87d83a5..c2efd392495 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,20 +25,141 @@
#include <direct.h>
#endif
+#define MY_DB_OPT_FILE "db.opt"
+
+const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
+static TYPELIB deletable_extentions=
+{array_elements(del_exts)-1,"del_exts", del_exts};
+
+const char *known_exts[]=
+{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db",NullS};
+static TYPELIB known_extentions=
+{array_elements(known_exts)-1,"known_exts", known_exts};
+
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path,
uint level);
-/* db-name is already validated when we come here */
+/*
+ Create database options file:
+
+ DESCRIPTION
+ Currently database default charset is only stored there.
+
+ RETURN VALUES
+ 0 ok
+ 1 Could not create file or write to it. Error sent through my_error()
+*/
+
+static bool write_db_opt(const char *path, HA_CREATE_INFO *create)
+{
+ register File file;
+ char buf[256]; // Should be enough for one option
+ bool error=1;
+
+ if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
+ {
+ ulong length;
+ length= my_sprintf(buf,(buf, "default-character-set=%s\n",
+ (create && create->table_charset) ?
+ create->table_charset->name : "DEFAULT"));
+
+ /* Error is written by my_write */
+ if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME)))
+ error=0;
+ my_close(file,MYF(0));
+ }
+ return error;
+}
+
+
+/*
+ Load database options file
+
+ load_db_opt()
+ path Path for option file
+ create Where to store the read options
+
+ DESCRIPTION
+ For now, only default-character-set is read.
+
+ RETURN VALUES
+ 0 File found
+ 1 No database file or could not open it
+
+*/
+
+static bool load_db_opt(const char *path, HA_CREATE_INFO *create)
+{
+ File file;
+ char buf[256];
+ DBUG_ENTER("load_db_opt");
+ bool error=1;
+ uint nbytes;
+
+ bzero((char*) create,sizeof(*create));
+ if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
+ {
+ IO_CACHE cache;
+ init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0));
+
+ while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
+ {
+ char *pos= buf+nbytes-1;
+ /* Remove end space and control characters */
+ while (pos > buf && !my_isgraph(system_charset_info, pos[-1]))
+ pos--;
+ *pos=0;
+ if ((pos= strchr(buf, '=')))
+ {
+ if (!strncmp(buf,"default-character-set", (pos-buf)))
+ {
+ if (strcmp(pos+1,"DEFAULT"))
+ {
+ if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0))))
+ {
+ sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
+ }
+ }
+ }
+ }
+ }
+ error=0;
+ end_io_cache(&cache);
+ my_close(file,MYF(0));
+ }
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Create a database
-int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
+ SYNOPSIS
+ mysql_create_db()
+ thd Thread handler
+ db Name of database to create
+ Function assumes that this is already validated.
+ create_info Database create options (like character set)
+ silent Used by replication when internally creating a database.
+ In this case the entry should not be logged.
+
+ RETURN VALUES
+ 0 ok
+ -1 Error
+
+*/
+
+int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
+ bool silent)
{
char path[FN_REFLEN+16];
MY_DIR *dirp;
long result=1;
int error = 0;
+ uint create_options = create_info ? create_info->options : 0;
DBUG_ENTER("mysql_create_db");
-
+
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
// do not create database if another thread is holding read lock
@@ -73,30 +194,49 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
}
}
+ unpack_dirname(path, path);
+ strcat(path,MY_DB_OPT_FILE);
+ if (write_db_opt(path, create_info))
+ {
+ /*
+ Could not create options file.
+ Restore things to beginning.
+ */
+ if (rmdir(path) >= 0)
+ {
+ error= -1;
+ goto exit;
+ }
+ /*
+ We come here when we managed to create the database, but not the option
+ file. In this case it's best to just continue as if nothing has
+ happened. (This is a very unlikely senario)
+ */
+ }
+
if (!silent)
{
- if (!thd->query)
+ char *query;
+ uint query_length;
+
+ if (!thd->query) // Only in replication
{
- /* The client used the old obsolete mysql_create_db() call */
- thd->query_length= (uint) (strxmov(path,"create database `", db, "`",
- NullS) - path);
- thd->query= path;
+ query= path;
+ query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) -
+ path);
}
+ else
{
- mysql_update_log.write(thd,thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
- mysql_bin_log.write(&qinfo);
- }
+ query= thd->query;
+ query_length= thd->query_length;
}
- if (thd->query == path)
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
{
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query= 0;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ Query_log_event qinfo(thd, query, query_length, 0);
+ mysql_bin_log.write(&qinfo);
}
- send_ok(&thd->net, result);
+ send_ok(thd, result);
}
exit:
@@ -106,14 +246,56 @@ exit2:
DBUG_RETURN(error);
}
-const char *del_exts[]= {".frm", ".BAK", ".TMD", NullS};
-static TYPELIB deletable_extentions=
-{array_elements(del_exts)-1,"del_exts", del_exts};
-const char *known_exts[]=
-{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db",NullS};
-static TYPELIB known_extentions=
-{array_elements(known_exts)-1,"known_exts", known_exts};
+/* db-name is already validated when we come here */
+
+int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
+{
+ char path[FN_REFLEN+16];
+ long result=1;
+ int error = 0;
+ uint create_options = create_info ? create_info->options : 0;
+ DBUG_ENTER("mysql_alter_db");
+
+ VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
+ // do not alter database if another thread is holding read lock
+ if (wait_if_global_read_lock(thd,0))
+ {
+ error= -1;
+ goto exit2;
+ }
+
+ /* Check directory */
+ (void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE);
+ fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
+ if ((error=write_db_opt(path, create_info)))
+ goto exit;
+
+ /*
+ Change options if current database is being altered
+ TODO: Delete this code
+ */
+ if (thd->db && !strcmp(thd->db,db))
+ {
+ thd->db_charset= create_info ? create_info->table_charset : NULL;
+ }
+
+ mysql_update_log.write(thd,thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd, result);
+
+exit:
+ start_waiting_global_read_lock(thd);
+exit2:
+ VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
+ DBUG_RETURN(error);
+}
+
/*
Drop all tables in a database.
@@ -151,8 +333,13 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
error= -1;
my_error(ER_DB_DROP_EXISTS,MYF(0),db);
}
- else if (!silent)
- send_ok(&thd->net,0);
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
+ if (!silent)
+ send_ok(thd,0);
+ }
goto exit;
}
pthread_mutex_lock(&LOCK_open);
@@ -166,26 +353,27 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
query_cache_invalidate1(db);
if (!silent)
{
+ const char *query;
+ ulong query_length;
if (!thd->query)
{
- thd->query_length= (uint) (strxmov(path,"drop database `", db, "`",
- NullS)-
- path);
- thd->query= path;
+ /* The client used the old obsolete mysql_drop_db() call */
+ query= path;
+ query_length = (uint) (strxmov(path,"drop database `", db, "`",
+ NullS)- path);
}
- mysql_update_log.write(thd, thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
+ else
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
- mysql_bin_log.write(&qinfo);
+ query=thd->query;
+ query_length=thd->query_length;
}
- if (thd->query == path)
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
{
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query= 0;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ Query_log_event qinfo(thd, query, query_length, 0);
+ mysql_bin_log.write(&qinfo);
}
- send_ok(&thd->net,(ulong) deleted);
+ send_ok(thd,(ulong) deleted);
}
error = 0;
}
@@ -224,7 +412,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
DBUG_PRINT("info",("Examining: %s", file->name));
/* Check if file is a raid directory */
- if (isdigit(file->name[0]) && isdigit(file->name[1]) &&
+ if (my_isdigit(system_charset_info,file->name[0]) &&
+ my_isdigit(system_charset_info,file->name[1]) &&
!file->name[2] && !level)
{
char newpath[FN_REFLEN];
@@ -249,7 +438,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
continue;
}
strxmov(filePath,org_path,"/",file->name,NullS);
- if (db && !my_strcasecmp(fn_ext(file->name), reg_ext))
+ if (db && !my_strcasecmp(system_charset_info,
+ fn_ext(file->name), reg_ext))
{
/* Drop the table nicely */
*fn_ext(file->name)=0; // Remove extension
@@ -281,7 +471,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
my_dirend(dirp);
if (thd->killed ||
- (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 1)))
+ (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
DBUG_RETURN(-1);
/*
@@ -331,23 +521,42 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
}
-bool mysql_change_db(THD *thd,const char *name)
+/*
+ Change default database.
+
+ SYNOPSIS
+ mysql_change_db()
+ thd Thread handler
+ name Databasename
+
+ DESCRIPTION
+ Becasue the database name may have been given directly from the
+ communication packet (in case of 'connect' or 'COM_INIT_DB')
+ we have to do end space removal in this function.
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+bool mysql_change_db(THD *thd, const char *name)
{
int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME));
char path[FN_REFLEN];
ulong db_access;
+ HA_CREATE_INFO create;
DBUG_ENTER("mysql_change_db");
if (!dbname || !(db_length=strip_sp(dbname)))
{
x_free(dbname); /* purecov: inspected */
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if ((db_length > NAME_LEN) || check_db_name(dbname))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
+ net_printf(thd,ER_WRONG_DB_NAME, dbname);
x_free(dbname);
DBUG_RETURN(1);
}
@@ -360,7 +569,7 @@ bool mysql_change_db(THD *thd,const char *name)
thd->master_access);
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
{
- net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
+ net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
thd->host_or_ip,
dbname);
@@ -378,14 +587,106 @@ bool mysql_change_db(THD *thd,const char *name)
path[length-1]=0; // remove ending '\'
if (access(path,F_OK))
{
- net_printf(&thd->net,ER_BAD_DB_ERROR,dbname);
+ net_printf(thd,ER_BAD_DB_ERROR,dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
- send_ok(&thd->net);
+ send_ok(thd);
x_free(thd->db);
- thd->db=dbname;
+ thd->db=dbname; // THD::~THD will free this
thd->db_length=db_length;
thd->db_access=db_access;
+
+ strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
+ load_db_opt(path, &create);
+ thd->db_charset=create.table_charset;
+ thd->variables.thd_charset=thd->db_charset ? thd->db_charset : default_charset_info;
+ DBUG_RETURN(0);
+}
+
+
+int mysqld_show_create_db(THD *thd, char *dbname,
+ HA_CREATE_INFO *create_info)
+{
+ int length;
+ char path[FN_REFLEN], *to;
+ uint db_access;
+ bool found_libchar;
+ HA_CREATE_INFO create;
+ CONVERT *convert=thd->variables.convert_set;
+ uint create_options = create_info ? create_info->options : 0;
+ Protocol *protocol=thd->protocol;
+ DBUG_ENTER("mysql_show_create_db");
+
+ if (check_db_name(dbname))
+ {
+ net_printf(thd,ER_WRONG_DB_NAME, dbname);
+ DBUG_RETURN(1);
+ }
+
+ if (test_all_bits(thd->master_access,DB_ACLS))
+ db_access=DB_ACLS;
+ else
+ db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
+ thd->priv_user,dbname) |
+ thd->master_access);
+ if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
+ {
+ net_printf(thd,ER_DBACCESS_DENIED_ERROR,
+ thd->priv_user,
+ thd->host_or_ip,
+ dbname);
+ mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
+ thd->priv_user,
+ thd->host_or_ip,
+ dbname);
+ DBUG_RETURN(1);
+ }
+
+ (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
+ length=unpack_dirname(path,path); // Convert if not unix
+ found_libchar= 0;
+ if (length && path[length-1] == FN_LIBCHAR)
+ {
+ found_libchar= 1;
+ path[length-1]=0; // remove ending '\'
+ }
+ if (access(path,F_OK))
+ {
+ net_printf(thd,ER_BAD_DB_ERROR,dbname);
+ DBUG_RETURN(1);
+ }
+ if (found_libchar)
+ path[length-1]= FN_LIBCHAR;
+ strmov(path+length, MY_DB_OPT_FILE);
+ load_db_opt(path, &create);
+
+ List<Item> field_list;
+ field_list.push_back(new Item_empty_string("Database",NAME_LEN));
+ field_list.push_back(new Item_empty_string("Create Database",1024));
+
+ if (protocol->send_fields(&field_list,1))
+ DBUG_RETURN(1);
+
+ protocol->prepare_for_resend();
+ protocol->store(dbname, strlen(dbname));
+ to= strxmov(path, "CREATE DATABASE ", NullS);
+ if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS);
+ to=strxmov(to,"`",dbname,"`", NullS);
+
+ if (create.table_charset)
+ {
+ int cl= (create.table_charset->state & MY_CS_PRIMARY) ? 0 : 1;
+ to= strxmov(to," /*!40100"
+ " DEFAULT CHARACTER SET ",create.table_charset->csname,
+ cl ? " COLLATE " : "", cl ? create.table_charset->name : "",
+ " */",NullS);
+ }
+ protocol->store(path, (uint) (to-path));
+
+ if (protocol->write())
+ DBUG_RETURN(1);
+ send_eof(thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 4997305de6b..703eafd0af6 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -35,27 +35,40 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
SQL_SELECT *select=0;
READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR;
- bool transactional_table, log_delayed, safe_update;
+ bool transactional_table, log_delayed, safe_update, const_cond;
ha_rows deleted;
+ TABLE_LIST *delete_table_list= (TABLE_LIST*)
+ thd->lex.select_lex.table_list.first;
DBUG_ENTER("mysql_delete");
- if (((safe_update=thd->options & OPTION_SAFE_UPDATES)) && !conds)
- {
- send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
- }
-
- if (!(table = open_ltable(thd, table_list, table_list->lock_type)))
+ if ((open_and_lock_tables(thd, table_list)))
DBUG_RETURN(-1);
+ fix_tables_pointers(thd->lex.all_selects_list);
+ table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
table->map=1;
- if (setup_conds(thd,table_list,&conds) || setup_ftfuncs(thd))
+ if (setup_conds(thd, delete_table_list, &conds) ||
+ setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1);
+ if (find_real_table_in_list(table_list->next,
+ table_list->db, table_list->real_name))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
+ DBUG_RETURN(-1);
+ }
+
+ const_cond= (!conds || conds->const_item());
+ safe_update=test(thd->options & OPTION_SAFE_UPDATES);
+ if (safe_update && const_cond)
+ {
+ send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
+ DBUG_RETURN(1);
+ }
/* Test if the user wants to delete all rows */
- if (!using_limit && (!conds || conds->const_item()) &&
- !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && !safe_update)
+ if (!using_limit && const_cond &&
+ !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
{
deleted= table->file->records;
if (!(error=table->file->delete_all_rows()))
@@ -76,12 +89,11 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
select=make_select(table,0,0,conds,&error);
if (error)
DBUG_RETURN(-1);
- if ((select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES),
- limit)) ||
- !limit)
+ if ((select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
- send_ok(&thd->net,0L);
+ free_underlaid_joins(thd, &thd->lex.select_lex);
+ send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete
}
@@ -92,7 +104,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (safe_update && !using_limit)
{
delete select;
- send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
+ free_underlaid_joins(thd, &thd->lex.select_lex);
+ send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1);
}
}
@@ -113,25 +126,28 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
- if (setup_order(thd, &tables, fields, all_fields, order) ||
+ if (setup_order(thd, 0, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (table->found_records = filesort(table, sortorder, length,
- (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ (table->found_records = filesort(thd, table, sortorder, length,
+ (SQL_SELECT *) 0, HA_POS_ERROR,
&examined_rows))
== HA_POS_ERROR)
{
delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); // This will force out message
}
}
init_read_record(&info,thd,table,select,1,1);
deleted=0L;
- init_ftfuncs(thd,1);
+ init_ftfuncs(thd, &thd->lex.select_lex, 1);
thd->proc_info="updating";
- while (!(error=info.read_record(&info)) && !thd->killed)
+ while (!(error=info.read_record(&info)) && !thd->killed &&
+ !thd->net.report_error)
{
- if (!(select && select->skipp_record()))
+ // thd->net.report_error is tested to disallow delete row on error
+ if (!(select && select->skipp_record())&& !thd->net.report_error )
{
if (!(error=table->file->delete_row(table->record[0])))
{
@@ -194,11 +210,12 @@ cleanup:
thd->lock=0;
}
delete select;
- if (error >= 0) // Fatal error
- send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0);
+ free_underlaid_joins(thd, &thd->lex.select_lex);
+ if (error >= 0 || thd->net.report_error)
+ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else
{
- send_ok(&thd->net,deleted);
+ send_ok(thd,deleted);
DBUG_PRINT("info",("%d records deleted",deleted));
}
DBUG_RETURN(0);
@@ -228,9 +245,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
int
-multi_delete::prepare(List<Item> &values)
+multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("multi_delete::prepare");
+ unit= u;
do_delete= 1;
thd->proc_info="deleting from main table";
DBUG_RETURN(0);
@@ -282,8 +300,8 @@ multi_delete::initialize_tables(JOIN *join)
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
}
- init_ftfuncs(thd,1);
- DBUG_RETURN(thd->fatal_error != 0);
+ init_ftfuncs(thd, thd->lex.current_select->select_lex(), 1);
+ DBUG_RETURN(thd->is_fatal_error != 0);
}
@@ -353,7 +371,7 @@ void multi_delete::send_error(uint errcode,const char *err)
DBUG_ENTER("multi_delete::send_error");
/* First send error what ever it is ... */
- ::send_error(&thd->net,errcode,err);
+ ::send_error(thd,errcode,err);
/* If nothing deleted return */
if (!deleted)
@@ -453,6 +471,7 @@ bool multi_delete::send_eof()
/* reset used flags */
thd->proc_info="end";
+
/*
Write the SQL statement to the binlog if we deleted
rows and we succeeded, or also in an error case when there
@@ -481,9 +500,9 @@ bool multi_delete::send_eof()
query_cache_invalidate3(thd, delete_tables, 1);
if (local_error)
- ::send_error(&thd->net);
+ ::send_error(thd);
else
- ::send_ok(&thd->net,deleted);
+ ::send_ok(thd, deleted);
return 0;
}
@@ -521,8 +540,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
bzero((char*) &create_info,sizeof(create_info));
create_info.auto_increment_value= table->file->auto_increment_value;
- db_type table_type=table->db_type;
+ create_info.table_charset=table->table_charset;
+ db_type table_type=table->db_type;
strmov(path,table->path);
*table_ptr= table->next; // Unlink table from list
close_temporary(table,0);
@@ -533,8 +553,8 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
table_list->real_name, 1))))
(void) rm_temporary_table(table_type, path);
/*
- Sasha: if we return here we will not have binloged the truncation and
- we will not send_ok() to the client.
+ If we return here we will not have logged the truncation to the bin log
+ and we will not send_ok() to the client.
*/
goto end;
}
@@ -564,6 +584,8 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
}
bzero((char*) &create_info,sizeof(create_info));
+ create_info.table_charset=table_list->table->table_charset;
+
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
query_cache_invalidate3(thd, table_list, 0);
@@ -580,7 +602,7 @@ end:
thd->tmp_table);
mysql_bin_log.write(&qinfo);
}
- send_ok(&thd->net); // This should return record count
+ send_ok(thd); // This should return record count
}
VOID(pthread_mutex_lock(&LOCK_open));
unlock_table_name(thd, table_list);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
new file mode 100644
index 00000000000..528bdb7b6f5
--- /dev/null
+++ b/sql/sql_derived.cc
@@ -0,0 +1,217 @@
+/* Copyright (C) 2002-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+
+/*
+ Derived tables
+ These were introduced by Sinisa <sinisa@mysql.com>
+*/
+
+
+#include "mysql_priv.h"
+#include "sql_select.h"
+#include "sql_acl.h"
+
+extern const char *any_db; // Special symbol for check_access
+
+/*
+ Resolve derived tables in all queries
+
+ SYNOPSIS
+ mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
+ thd Thread handle
+ lex LEX for this thread
+ unit node that contains all SELECT's for derived tables
+ t TABLE_LIST for the upper SELECT
+
+ IMPLEMENTATION
+ Derived table is resolved with temporary table. It is created based on the
+ queries defined. After temporary table is created, if this is not EXPLAIN,
+ then the entire unit / node is deleted. unit is deleted if UNION is used
+ for derived table and node is deleted is it is a simple SELECT.
+
+ After table creation, the above TABLE_LIST is updated with a new table.
+
+ This function is called before any command containing derived table
+ is executed.
+
+ Derived tables is stored in thd->derived_tables and freed in
+ close_thread_tables()
+
+ TODO
+ Move creation of derived tables in open_and_lock_tables()
+
+ RETURN
+ 0 ok
+ 1 Error
+ -1 Error and error message given
+*/
+
+
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
+ TABLE_LIST *org_table_list)
+{
+ SELECT_LEX *sl= unit->first_select();
+ List<Item> item_list;
+ TABLE *table;
+ int res;
+ select_union *derived_result;
+ TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
+ TMP_TABLE_PARAM tmp_table_param;
+ bool is_union= sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
+ bool is_subsel= sl->first_inner_unit() ? 1: 0;
+ SELECT_LEX_NODE *save_current_select= lex->current_select;
+ DBUG_ENTER("mysql_derived");
+
+ /*
+ In create_total_list, derived tables have to be treated in case of
+ EXPLAIN, This is because unit/node is not deleted in that
+ case. Current code in this function has to be improved to
+ recognize better when this function is called from derived tables
+ and when from other functions.
+ */
+ if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
+ DBUG_RETURN(-1);
+
+ /*
+ We have to do access checks here as this code is executed before any
+ sql command is started to execute.
+ */
+ if (tables)
+ res= check_table_access(thd,SELECT_ACL, tables);
+ else
+ res= check_access(thd, SELECT_ACL, any_db);
+ if (res)
+ DBUG_RETURN(-1);
+
+ if (!(res=open_and_lock_tables(thd,tables)))
+ {
+ if (is_union || is_subsel)
+ {
+ /*
+ The following code is a re-do of fix_tables_pointers() found
+ in sql_select.cc for UNION's within derived tables. The only
+ difference is in navigation, as in derived tables we care for
+ this level only.
+
+ */
+ fix_tables_pointers(unit);
+ }
+
+ lex->current_select= sl;
+ TABLE_LIST *first_table= (TABLE_LIST*) sl->table_list.first;
+ if (setup_tables(first_table) ||
+ setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild))
+ {
+ res= -1;
+ goto exit;
+ }
+
+ item_list= sl->item_list;
+ sl->with_wild= 0;
+ if (setup_ref_array(thd, &sl->ref_pointer_array,
+ (item_list.elements + sl->with_sum_func +
+ sl->order_list.elements + sl->group_list.elements)) ||
+ setup_fields(thd, sl->ref_pointer_array, first_table, item_list,
+ 0, 0, 1))
+ {
+ res= -1;
+ goto exit;
+ }
+ bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
+ tmp_table_param.field_count= item_list.elements;
+ if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
+ (ORDER*) 0,
+ is_union && !unit->union_option, 1,
+ (sl->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR)))
+ {
+ res= -1;
+ goto exit;
+ }
+
+ if ((derived_result=new select_union(table)))
+ {
+ derived_result->tmp_table_param=&tmp_table_param;
+ unit->offset_limit_cnt= sl->offset_limit;
+ unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
+ if (unit->select_limit_cnt < sl->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR;
+ if (unit->select_limit_cnt == HA_POS_ERROR)
+ sl->options&= ~OPTION_FOUND_ROWS;
+
+ if (is_union)
+ res= mysql_union(thd, lex, derived_result, unit, 1);
+ else
+ res= mysql_select(thd, &sl->ref_pointer_array,
+ (TABLE_LIST*) sl->table_list.first,
+ sl->with_wild,
+ sl->item_list, sl->where,
+ sl->order_list.elements+sl->group_list.elements,
+ (ORDER *) sl->order_list.first,
+ (ORDER *) sl->group_list.first,
+ sl->having, (ORDER*) NULL,
+ sl->options | thd->options | SELECT_NO_UNLOCK,
+ derived_result, unit, sl, 0, 1);
+
+ if (!res)
+ {
+ /*
+ Here we entirely fix both TABLE_LIST and list of SELECT's as
+ there were no derived tables
+ */
+ if (derived_result->flush())
+ res= 1;
+ else
+ {
+ org_table_list->real_name=table->real_name;
+ org_table_list->table=table;
+ table->derived_select_number= sl->select_number;
+ table->tmp_table= TMP_TABLE;
+ if (lex->describe)
+ {
+ // to fix a problem in EXPLAIN
+ if (tables)
+ tables->table_list->table=tables->table;
+ }
+ else
+ unit->exclude();
+ org_table_list->db= (char *)"";
+#ifndef DBUG_OFF
+ /* Try to catch errors if this is accessed */
+ org_table_list->derived=(SELECT_LEX_UNIT *) 1;
+#endif
+ table->file->info(HA_STATUS_VARIABLE);
+ }
+ }
+ delete derived_result;
+ }
+ if (res)
+ free_tmp_table(thd, table);
+ else
+ {
+ /* Add new temporary table to list of open derived tables */
+ table->next= thd->derived_tables;
+ thd->derived_tables= table;
+ }
+
+exit:
+ lex->current_select= save_current_select;
+ close_thread_tables(thd, 0, 1);
+ }
+ DBUG_RETURN(res);
+}
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 70124c2d796..f25c4632e1e 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -25,10 +25,10 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values);
Item *value;
DBUG_ENTER("mysql_do");
- if (setup_fields(thd,0, values, 0, 0, 0))
+ if (setup_fields(thd, 0, 0, values, 0, 0, 0))
DBUG_RETURN(-1);
while ((value = li++))
value->val_int();
- send_ok(&thd->net);
+ send_ok(thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
new file mode 100644
index 00000000000..5508be5167a
--- /dev/null
+++ b/sql/sql_error.cc
@@ -0,0 +1,193 @@
+/* Copyright (C) 1995-2002 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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
+*/
+
+/**********************************************************************
+This file contains the implementation of error and warnings related
+
+ - Whenever an error or warning occurred, it pushes it to a warning list
+ that the user can retrieve with SHOW WARNINGS or SHOW ERRORS.
+
+ - For each statement, we return the number of warnings generated from this
+ command. Note that this can be different from @@warning_count as
+ we reset the warning list only for questions that uses a table.
+ This is done to allow on to do:
+ INSERT ...;
+ SELECT @@warning_count;
+ SHOW WARNINGS;
+ (If we would reset after each command, we could not retrieve the number
+ of warnings)
+
+ - When client requests the information using SHOW command, then
+ server processes from this list and returns back in the form of
+ resultset.
+
+ Supported syntaxes:
+
+ SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows]
+ SHOW [COUNT(*)] WARNINGS [LIMIT [offset,] rows]
+ SELECT @@warning_count, @@error_count;
+
+***********************************************************************/
+
+#include "mysql_priv.h"
+
+/*
+ Reset all warnings for the thread
+
+ SYNOPSIS
+ mysql_reset_errors()
+ thd Thread handle
+
+ IMPLEMENTATION
+ Don't reset warnings if this has already been called for this query.
+ This may happen if one gets a warning during the parsing stage,
+ in which case push_warnings() has already called this function.
+*/
+
+void mysql_reset_errors(THD *thd)
+{
+ if (thd->query_id != thd->warn_id)
+ {
+ thd->warn_id= thd->query_id;
+ free_root(&thd->warn_root,MYF(0));
+ bzero((char*) thd->warn_count, sizeof(thd->warn_count));
+ thd->warn_list.empty();
+ }
+}
+
+
+/*
+ Push the warning/error to error list if there is still room in the list
+
+ SYNOPSIS
+ push_warning()
+ thd Thread handle
+ level Severity of warning (note, warning, error ...)
+ code Error number
+ msg Clear error message
+*/
+
+void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
+ const char *msg)
+{
+ if (thd->query_id != thd->warn_id)
+ mysql_reset_errors(thd);
+
+ if (thd->warn_list.elements < thd->variables.max_error_count)
+ {
+ /*
+ The following code is here to change the allocation to not
+ use the thd->mem_root, which is freed after each query
+ */
+ MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
+ my_pthread_setspecific_ptr(THR_MALLOC, &thd->warn_root);
+ MYSQL_ERROR *err= new MYSQL_ERROR(code, level, msg);
+ if (err)
+ thd->warn_list.push_back(err);
+ my_pthread_setspecific_ptr(THR_MALLOC, old_root);
+ }
+ thd->warn_count[(uint) level]++;
+ thd->total_warn_count++;
+}
+
+/*
+ Push the warning/error to error list if there is still room in the list
+
+ SYNOPSIS
+ push_warning_printf()
+ thd Thread handle
+ level Severity of warning (note, warning, error ...)
+ code Error number
+ msg Clear error message
+*/
+
+void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *format, ...)
+{
+ va_list args;
+ char warning[ERRMSGSIZE+20];
+ DBUG_ENTER("push_warning_printf");
+ DBUG_PRINT("enter",("warning: %u", code));
+
+ va_start(args,format);
+ my_vsnprintf(warning, sizeof(warning), format, args);
+ va_end(args);
+ push_warning(thd, level, code, warning);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Send all notes, errors or warnings to the client in a result set
+
+ SYNOPSIS
+ mysqld_show_warnings()
+ thd Thread handler
+ levels_to_show Bitmap for which levels to show
+
+ DESCRIPTION
+ Takes into account the current LIMIT
+
+ RETURN VALUES
+ 0 ok
+ 1 Error sending data to client
+*/
+
+static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
+static int warning_level_length[]= { 4, 7, 5, 1 };
+
+my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
+{
+ List<Item> field_list;
+ DBUG_ENTER("mysqld_show_warnings");
+
+ field_list.push_back(new Item_empty_string("Level", 7));
+ field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
+
+ if (thd->protocol->send_fields(&field_list,1))
+ DBUG_RETURN(1);
+
+ MYSQL_ERROR *err;
+ SELECT_LEX *sel= &thd->lex.select_lex;
+ ha_rows offset= sel->offset_limit, limit= sel->select_limit;
+ Protocol *protocol=thd->protocol;
+
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ while ((err= it++))
+ {
+ /* Skip levels that the user is not interested in */
+ if (!(levels_to_show & ((ulong) 1 << err->level)))
+ continue;
+ if (offset)
+ {
+ offset--;
+ continue;
+ }
+ protocol->prepare_for_resend();
+ protocol->store(warning_level_names[err->level],
+ warning_level_length[err->level]);
+ protocol->store((uint32) err->code);
+ protocol->store(err->msg, strlen(err->msg));
+ if (protocol->write())
+ DBUG_RETURN(1);
+ if (!--limit)
+ break;
+ }
+ send_eof(thd);
+ DBUG_RETURN(0);
+}
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index eeaa574c69d..954dceff303 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
#include "mysql_priv.h"
#include "sql_select.h"
-#include <assert.h>
/* TODO:
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
@@ -62,7 +61,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables)
return -1;
}
- send_ok(&thd->net);
+ send_ok(thd);
return 0;
}
@@ -83,7 +82,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
return -1;
}
if (!dont_send_ok)
- send_ok(&thd->net);
+ send_ok(thd);
return 0;
}
@@ -103,7 +102,7 @@ int mysql_ha_closeall(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
}
static enum enum_ha_read_modes rkey_to_rnext[]=
- { RNEXT, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
+ { RNEXT, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
int mysql_ha_read(THD *thd, TABLE_LIST *tables,
@@ -121,10 +120,12 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
tables->table=table;
- if (cond && cond->fix_fields(thd,tables))
+ if (cond && (cond->fix_fields(thd, tables, &cond) || cond->check_cols(1)))
return -1;
- table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
+ /* InnoDB needs to know that this table handle is used in the HANDLER */
+
+ table->file->init_table_handle_for_HANDLER();
if (keyname)
{
@@ -140,13 +141,16 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
List<Item> list;
list.push_front(new Item_field(NULL,NULL,"*"));
List_iterator<Item> it(list);
+ Protocol *protocol= thd->protocol;
+ char buff[MAX_FIELD_WIDTH];
+ String buffer(buff, sizeof(buff), system_charset_info);
uint num_rows;
it++;
insert_fields(thd,tables,tables->db,tables->alias,&it);
select_limit+=offset_limit;
- send_fields(thd,list,1);
+ protocol->send_fields(&list,1);
HANDLER_TABLES_HACK(thd);
MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
@@ -154,11 +158,17 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (!lock)
goto err0; // mysql_lock_tables() printed error message already
- table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
+ /*
+ In ::external_lock InnoDB resets the fields which tell it that
+ the handle is used in the HANDLER interface. Tell it again that
+ we are using it for HANDLER.
+ */
+
+ table->file->init_table_handle_for_HANDLER();
for (num_rows=0; num_rows < select_limit; )
{
- switch(mode) {
+ switch (mode) {
case RFIRST:
err=keyname ?
table->file->index_first(table->record[0]) :
@@ -197,12 +207,12 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++)
{
- item->save_in_field(key_part->field, 1);
+ (void) item->save_in_field(key_part->field, 1);
key_len+=key_part->store_length;
}
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
{
- send_error(&thd->net,ER_OUTOFMEMORY);
+ send_error(thd,ER_OUTOFMEMORY);
goto err;
}
key_copy(key, table, keyno, key_len);
@@ -212,7 +222,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
break;
}
default:
- send_error(&thd->net,ER_ILLEGAL_HA);
+ send_error(thd,ER_ILLEGAL_HA);
goto err;
}
@@ -233,31 +243,31 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (!cond->val_int())
continue;
}
- if (num_rows>=offset_limit)
+ if (num_rows >= offset_limit)
{
if (!err)
{
String *packet = &thd->packet;
Item *item;
- packet->length(0);
+ protocol->prepare_for_resend();
it.rewind();
while ((item=it++))
{
- if (item->send(thd,packet))
+ if (item->send(thd->protocol, &buffer))
{
- packet->free(); // Free used
+ protocol->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0));
goto err;
}
}
- my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
+ protocol->write();
}
}
num_rows++;
}
ok:
mysql_unlock_tables(thd,lock);
- send_eof(&thd->net);
+ send_eof(thd);
return 0;
err:
mysql_unlock_tables(thd,lock);
@@ -265,6 +275,7 @@ err0:
return -1;
}
+
static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *table_name, bool is_alias)
{
@@ -274,15 +285,16 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
if (!db || ! *db)
db= thd->db ? thd->db : "";
dblen=strlen(db)+1;
- ptr=&(thd->handler_tables);
+ ptr= &(thd->handler_tables);
- for (TABLE *table=*ptr; table ; table=*ptr)
+ for (TABLE *table= *ptr; table ; table= *ptr)
{
if (!memcmp(table->table_cache_key, db, dblen) &&
- !my_strcasecmp((is_alias ? table->table_name : table->real_name),table_name))
+ !my_strcasecmp(system_charset_info,
+ (is_alias ? table->table_name : table->real_name),
+ table_name))
break;
- ptr=&(table->next);
+ ptr= &(table->next);
}
return ptr;
}
-
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
new file mode 100644
index 00000000000..24ea2e9734e
--- /dev/null
+++ b/sql/sql_help.cc
@@ -0,0 +1,519 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "mysql_priv.h"
+
+struct st_find_field
+{
+ const char *table_name, *field_name;
+ Field *field;
+};
+
+/* Used fields */
+
+static struct st_find_field init_used_fields[]=
+{
+ { "help_topic", "name", 0},
+ { "help_topic","description", 0},
+ { "help_topic","example", 0},
+ { "help_topic", "help_topic_id", 0},
+ { "help_category","name", 0},
+ { "help_category","help_category_id", 0},
+ { "help_relation","help_topic_id", 0},
+ { "help_relation","help_category_id", 0}
+};
+
+enum enum_used_fields
+{
+ help_topic_name=0, help_topic_description, help_topic_example,
+ help_topic_help_topic_id,
+ help_category_name, help_category_help_category_id,
+ help_relation_help_topic_id, help_relation_help_category_id
+};
+
+/*
+ Fill local used field structure with pointer to fields */
+
+static bool init_fields(THD *thd, TABLE_LIST *tables,
+ struct st_find_field *find_field,
+ uint count)
+{
+ for (; count-- ; find_field++)
+ {
+ TABLE_LIST *not_used;
+ /* We have to use 'new' here as field will be re_linked on free */
+ Item_field *field= new Item_field("mysql", find_field->table_name,
+ find_field->field_name);
+ if (!(find_field->field= find_field_in_tables(thd, field, tables,
+ &not_used,
+ TRUE)))
+ return 1;
+ }
+ return 0;
+}
+
+
+#define help_charset &my_charset_latin1
+
+/*
+ Look for topics by mask
+
+ SYNOPSIS
+ search_topics()
+ thd Thread handler
+ topics Table of topic
+ select Function to test for if matching help topic.
+ Normally 'help_topic.name like 'bit%'
+ pfname Pointer to Field structure for field "name"
+ names List of founded topic's names (out)
+ name Name of founded topic (out),
+ Only set if founded exactly one topic)
+ description Description of founded topic (out)
+ Only set if founded exactly one topic.
+ example Example for founded topic (out)
+ Only if founded exactly one topic.
+ RETURN VALUES
+ # number of topics founded
+*/
+
+int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
+ SQL_SELECT *select, List<char> *names,
+ char **name, char **description, char **example)
+{
+ DBUG_ENTER("search_functions");
+ int count= 0;
+
+ READ_RECORD read_record_info;
+ init_read_record(&read_record_info, thd, topics, select,1,0);
+ while (!read_record_info.read_record(&read_record_info))
+ {
+ if (!select->cond->val_int()) // Dosn't match like
+ continue;
+
+ char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field);
+ count++;
+ if (count > 2)
+ {
+ names->push_back(lname);
+ }
+ else if (count == 1)
+ {
+ *description= get_field(&thd->mem_root,
+ find_field[help_topic_description].field);
+ *example= get_field(&thd->mem_root,
+ find_field[help_topic_example].field);
+ *name= lname;
+ }
+ else
+ {
+ names->push_back(*name);
+ names->push_back(lname);
+ *name= 0;
+ *description= 0;
+ *example= 0;
+ }
+ }
+ end_read_record(&read_record_info);
+ DBUG_RETURN(count);
+}
+
+/*
+ Look for categories by mask
+
+ SYNOPSIS
+ search_categories()
+ thd THD for init_read_record
+ categories Table of categories
+ select Function to test for if matching help topic.
+ Normally 'help_topic.name like 'bit%'
+ names List of founded topic's names (out)
+ res_id Primary index of founded category (only if
+ founded exactly one category)
+
+ RETURN VALUES
+ # Number of categories founded
+*/
+
+int search_categories(THD *thd, TABLE *categories,
+ struct st_find_field *find_fields,
+ SQL_SELECT *select, List<char> *names, int16 *res_id)
+{
+ Field *pfname= find_fields[help_category_name].field;
+ DBUG_ENTER("search_categories");
+ int count= 0;
+
+ READ_RECORD read_record_info;
+ init_read_record(&read_record_info, thd, categories, select,1,0);
+ while (!read_record_info.read_record(&read_record_info))
+ {
+ if (select && !select->cond->val_int())
+ continue;
+ char *lname= get_field(&thd->mem_root,pfname);
+ if (++count == 1 && res_id)
+ {
+ Field *pcat_id= find_fields[help_category_help_category_id].field;
+ *res_id= (int16) pcat_id->val_int();
+ }
+ names->push_back(lname);
+ }
+ end_read_record(&read_record_info);
+
+ DBUG_RETURN(count);
+}
+
+
+/*
+ Send to client rows in format:
+ column1 : <name>
+ column2 : <is_it_category>
+
+ SYNOPSIS
+ send_variant_2_list()
+ protocol Protocol for sending
+ names List of names
+ cat Value of the column <is_it_category>
+
+ RETURN VALUES
+ -1 Writing fail
+ 0 Data was successefully send
+*/
+
+int send_variant_2_list(Protocol *protocol, List<char> *names,
+ const char *cat)
+{
+ DBUG_ENTER("send_names");
+
+ List_iterator<char> it(*names);
+ const char *cur_name;
+ while ((cur_name= it++))
+ {
+ protocol->prepare_for_resend();
+ protocol->store(cur_name);
+ protocol->store(cat);
+ if (protocol->write())
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Look for all topics of category
+
+ SYNOPSIS
+ get_all_topics_for_category()
+ thd Thread handler
+ topics Table of topics
+ relations Table of m:m relation "topic/category"
+ cat_id Primary index looked for category
+ res List of founded topic's names (out)
+
+ RETURN VALUES
+ -1 corrupt database
+ 0 succesefull
+*/
+
+int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
+ struct st_find_field *find_fields,
+ int16 cat_id, List<char> *res)
+{
+ char buff[8]; // Max int length
+ DBUG_ENTER("get_all_topics_for_category");
+
+ int iindex_topic, iindex_relations;
+ Field *rtopic_id, *rcat_id;
+
+ if ((iindex_topic= find_type((char*) "PRIMARY",
+ &topics->keynames, 1+2)-1)<0 ||
+ (iindex_relations= find_type((char*) "PRIMARY",
+ &relations->keynames, 1+2)-1)<0)
+ {
+ send_error(thd,ER_CORRUPT_HELP_DB);
+ DBUG_RETURN(-1);
+ }
+ rtopic_id= find_fields[help_relation_help_topic_id].field;
+ rcat_id= find_fields[help_relation_help_category_id].field;
+
+ topics->file->index_init(iindex_topic);
+ relations->file->index_init(iindex_relations);
+
+ rcat_id->store((longlong) cat_id);
+ rcat_id->get_key_image(buff, rcat_id->pack_length(), help_charset,
+ Field::itRAW);
+ int key_res= relations->file->index_read(relations->record[0],
+ buff, rcat_id->pack_length(),
+ HA_READ_KEY_EXACT);
+
+ for ( ; !key_res && cat_id == (int16) rcat_id->val_int() ;
+ key_res= relations->file->index_next(relations->record[0]))
+ {
+ char topic_id_buff[8];
+ longlong topic_id= rtopic_id->val_int();
+ Field *field= find_fields[help_topic_help_topic_id].field;
+ field->store((longlong) topic_id);
+ field->get_key_image(topic_id_buff, field->pack_length(), help_charset,
+ Field::itRAW);
+
+ if (!topics->file->index_read(topics->record[0], topic_id_buff,
+ field->pack_length(),
+ HA_READ_KEY_EXACT))
+ res->push_back(get_field(&thd->mem_root,
+ find_fields[help_topic_name].field));
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Send to client answer for help request
+
+ SYNOPSIS
+ send_answer_1()
+ protocol - protocol for sending
+ s1 - value of column "Name"
+ s2 - value of column "Category"
+ s3 - value of column "Description"
+ s4 - value of column "Example"
+
+ IMPLEMENTATION
+ Format used:
+ +----------+---------+------------+------------+
+ |Name: |Category |Description |Example |
+ +----------+---------+------------+------------+
+ |String(64)|String(1)|String(1000)|String(1000)|
+ +----------+---------+------------+------------+
+ with exactly one row!
+
+ RETURN VALUES
+ 1 Writing of head failed
+ -1 Writing of row failed
+ 0 Successeful send
+*/
+
+int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
+ const char *s3, const char *s4)
+{
+ DBUG_ENTER("send_answer_1");
+ List<Item> field_list;
+ field_list.push_back(new Item_empty_string("Name",64));
+ field_list.push_back(new Item_empty_string("Category",1));
+ field_list.push_back(new Item_empty_string("Description",1000));
+ field_list.push_back(new Item_empty_string("Example",1000));
+
+ if (protocol->send_fields(&field_list,1))
+ DBUG_RETURN(1);
+
+ protocol->prepare_for_resend();
+ protocol->store(s1);
+ protocol->store(s2);
+ protocol->store(s3);
+ protocol->store(s4);
+ if (protocol->write())
+ DBUG_RETURN(-1);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Send to client help header
+
+ SYNOPSIS
+ send_header_2()
+ protocol - protocol for sending
+
+ IMPLEMENTATION
+ +----------+---------+
+ |Name: |Category |
+ +----------+---------+
+ |String(64)|String(1)|
+ +----------+---------+
+
+ RETURN VALUES
+ result of protocol->send_fields
+*/
+
+int send_header_2(Protocol *protocol)
+{
+ DBUG_ENTER("send_header2");
+ List<Item> field_list;
+ field_list.push_back(new Item_empty_string("Name",64));
+ field_list.push_back(new Item_empty_string("Category",1));
+ DBUG_RETURN(protocol->send_fields(&field_list,1));
+}
+
+
+/*
+ Server-side function 'help'
+
+ SYNOPSIS
+ mysqld_help()
+ thd Thread handler
+
+ RETURN VALUES
+ 0 Success
+ 1 Error and send_error already commited
+ -1 error && send_error should be issued (normal case)
+*/
+
+int mysqld_help(THD *thd, const char *mask)
+{
+ Protocol *protocol= thd->protocol;
+ SQL_SELECT *select= 0, *select_cat= 0;
+ Item *cond_topic, *cond_cat;
+ st_find_field used_fields[array_elements(init_used_fields)];
+ DBUG_ENTER("mysqld_help");
+
+ TABLE_LIST tables[3];
+ bzero((gptr)tables,sizeof(tables));
+ tables[0].alias= tables[0].real_name= (char*) "help_topic";
+ tables[0].lock_type= TL_READ;
+ tables[0].db= (char*) "mysql";
+ tables[0].next= &tables[1];
+ tables[1].alias= tables[1].real_name= (char*) "help_category";
+ tables[1].lock_type= TL_READ;
+ tables[1].db= (char*) "mysql";
+ tables[1].next= &tables[2];
+ tables[2].alias= tables[2].real_name= (char*) "help_relation";
+ tables[2].lock_type= TL_READ;
+ tables[2].db= (char*) "mysql";
+ tables[2].next= 0;
+
+ List<char> function_list, categories_list;
+ char *name, *description, *example;
+ int res, count_topics, count_categories, error;
+
+ if (open_and_lock_tables(thd, tables))
+ {
+ res= -1;
+ goto end;
+ }
+ /* Init tables and fields to be usable from items */
+ setup_tables(tables);
+ memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
+ if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
+ {
+ res= -1;
+ goto end;
+ }
+
+ /* TODO: Find out why these are needed (should not be) */
+ tables[0].table->file->init_table_handle_for_HANDLER();
+ tables[1].table->file->init_table_handle_for_HANDLER();
+ tables[2].table->file->init_table_handle_for_HANDLER();
+
+ cond_topic= new Item_func_like(new Item_field(used_fields[help_topic_name].
+ field),
+ new Item_string(mask, strlen(mask),
+ help_charset),
+ (char*) "\\");
+ cond_topic->fix_fields(thd, tables, &cond_topic); // can never fail
+ select= make_select(tables[0].table,0,0,cond_topic,&error);
+ if (error || (select && select->check_quick(0, HA_POS_ERROR)))
+ {
+ res= -1;
+ goto end;
+ }
+
+ cond_cat= new Item_func_like(new Item_field(used_fields[help_category_name].
+ field),
+ new Item_string(mask, strlen(mask),
+ help_charset),
+ (char*) "\\");
+ cond_cat->fix_fields(thd, tables, &cond_topic); // can never fail
+ select_cat= make_select(tables[1].table,0,0,cond_cat,&error);
+ if (error || (select_cat && select_cat->check_quick(0, HA_POS_ERROR)))
+ {
+ res= -1;
+ goto end;
+ }
+
+ res= 1;
+ count_topics= search_topics(thd,tables[0].table, used_fields, select,
+ &function_list, &name, &description, &example);
+ if (count_topics == 0)
+ {
+ int16 category_id;
+ Item *cond=
+ new Item_func_like(new
+ Item_field(used_fields[help_category_name].field),
+ new Item_string(mask, strlen(mask),
+ help_charset),
+ (char*) "\\");
+ (void) cond->fix_fields(thd, tables, &cond); // can never fail
+
+ count_categories= search_categories(thd, tables[1].table, used_fields,
+ select_cat, &categories_list,
+ &category_id);
+ if (count_categories == 1)
+ {
+ if (get_all_topics_for_category(thd,tables[0].table,
+ tables[2].table, used_fields,
+ category_id, &function_list))
+ {
+ res= -1;
+ goto end;
+ }
+ List_iterator<char> it(function_list);
+ char *cur_topic;
+ char buff[1024];
+ String example(buff, sizeof(buff), help_charset);
+ example.length(0);
+
+ while ((cur_topic= it++))
+ {
+ example.append(cur_topic);
+ example.append("\n",1);
+ }
+ if ((send_answer_1(protocol, categories_list.head(),
+ "Y","",example.ptr())))
+ goto end;
+ }
+ else
+ {
+ if (send_header_2(protocol))
+ goto end;
+ if (count_categories == 0)
+ search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0,
+ &categories_list, 0);
+ if (send_variant_2_list(protocol,&categories_list,"Y"))
+ goto end;
+ }
+ }
+ else if (count_topics == 1)
+ {
+ if (send_answer_1(protocol,name,"N",description, example))
+ goto end;
+ }
+ else
+ {
+ /* First send header and functions */
+ if (send_header_2(protocol) ||
+ send_variant_2_list(protocol, &function_list, "N"))
+ goto end;
+ search_categories(thd, tables[1].table, used_fields, select_cat,
+ &categories_list, 0);
+ /* Then send categories */
+ if (send_variant_2_list(protocol, &categories_list, "Y"))
+ goto end;
+ }
+ res= 0;
+
+ send_eof(thd);
+end:
+ delete select;
+ delete select_cat;
+ DBUG_RETURN(res);
+}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 23563239558..0a06822d36e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -45,7 +45,7 @@ static void unlink_blobs(register TABLE *table);
if timestamp should be updated or not.
*/
-static int
+int
check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter)
{
@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
thd->dupp_field=0;
if (setup_tables(&table_list) ||
- setup_fields(thd,&table_list,fields,1,0,0))
+ setup_fields(thd, 0, &table_list,fields,1,0,0))
return -1;
if (thd->dupp_field)
{
@@ -99,8 +99,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
}
-int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
- List<List_item> &values_list,enum_duplicates duplic)
+int mysql_insert(THD *thd,TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list,
+ List<Item> &update_fields,
+ List<Item> &update_values,
+ enum_duplicates duplic)
{
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
@@ -115,6 +119,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
List_item *values;
char *query=thd->query;
thr_lock_type lock_type = table_list->lock_type;
+ TABLE_LIST *insert_table_list= (TABLE_LIST*)
+ thd->lex.select_lex.table_list.first;
DBUG_ENTER("mysql_insert");
/*
@@ -125,9 +131,12 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if ((lock_type == TL_WRITE_DELAYED &&
((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) ||
thd->slave_thread)) ||
- (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE))
+ (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE) ||
+ (duplic == DUP_UPDATE))
lock_type=TL_WRITE;
+ table_list->lock_type= lock_type;
+ int res;
if (lock_type == TL_WRITE_DELAYED)
{
if (thd->locked_tables)
@@ -142,21 +151,40 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
DBUG_RETURN(-1);
}
}
- if (!(table = delayed_get_table(thd,table_list)) && !thd->fatal_error)
- table = open_ltable(thd,table_list,lock_type=thd->update_lock_default);
+ if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error)
+ if (table_list->next && table)
+ res= open_and_lock_tables(thd, table_list->next);
+ else
+ res= (table == 0);
+ else
+ res= open_and_lock_tables(thd, table_list);
}
else
- table = open_ltable(thd,table_list,lock_type);
- if (!table)
+ res= open_and_lock_tables(thd, table_list);
+ if (res)
DBUG_RETURN(-1);
+ fix_tables_pointers(thd->lex.all_selects_list);
+
+ table= table_list->table;
thd->proc_info="init";
thd->used_tables=0;
values= its++;
if (check_insert_fields(thd,table,fields,*values,1) ||
- setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0,0))
+ setup_tables(insert_table_list) ||
+ setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
+ (duplic == DUP_UPDATE &&
+ (setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
+ setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
+ goto abort;
+ if (find_real_table_in_list(table_list->next,
+ table_list->db, table_list->real_name))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
goto abort;
+ }
+
value_count= values->elements;
- while ((values = its++))
+ while ((values= its++))
{
counter++;
if (values->elements != value_count)
@@ -166,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
MYF(0),counter);
goto abort;
}
- if (setup_fields(thd,table_list,*values,0,0,0))
+ if (setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0))
goto abort;
}
its.rewind ();
@@ -176,6 +204,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
info.records=info.deleted=info.copied=0;
info.handle_duplicates=duplic;
+ info.update_fields=&update_fields;
+ info.update_values=&update_values;
// Don't count warnings for simple inserts
if (values_list.elements > 1 || (thd->options & OPTION_WARNINGS))
thd->count_cuted_fields = 1;
@@ -185,7 +215,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
error=0;
id=0;
thd->proc_info="update";
- if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
+ if (duplic != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if ((lock_type != TL_WRITE_DELAYED && !(specialflag & SPECIAL_SAFE_MODE)) &&
values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT)
@@ -204,9 +234,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if (fields.elements || !value_count)
{
restore_record(table,2); // Get empty record
- if (fill_record(fields,*values) || check_null_fields(thd,table))
+ if (fill_record(fields,*values)|| thd->net.report_error ||
+ check_null_fields(thd,table))
{
- if (values_list.elements != 1)
+ if (values_list.elements != 1 && !thd->net.report_error)
{
info.records++;
continue;
@@ -221,9 +252,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
restore_record(table,2); // Get empty record
else
table->record[0][0]=table->record[2][0]; // Fix delete marker
- if (fill_record(table->field,*values))
+ if (fill_record(table->field,*values) || thd->net.report_error)
{
- if (values_list.elements != 1)
+ if (values_list.elements != 1 && ! thd->net.report_error)
{
info.records++;
continue;
@@ -324,14 +355,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
table->next_number_field=0;
thd->count_cuted_fields=0;
thd->next_insert_id=0; // Reset this if wrongly used
- if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
+ if (duplic != DUP_ERROR)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if (error)
goto abort;
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
!thd->cuted_fields))
- send_ok(&thd->net,info.copied+info.deleted,id);
+ send_ok(thd,info.copied+info.deleted,id);
else
{
char buff[160];
@@ -343,13 +374,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields);
- ::send_ok(&thd->net,info.copied+info.deleted,(ulonglong)id,buff);
+ ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
}
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(0);
abort:
if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd);
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
@@ -376,7 +409,8 @@ int write_record(TABLE *table,COPY_INFO *info)
char *key=0;
info->records++;
- if (info->handle_duplicates == DUP_REPLACE)
+ if (info->handle_duplicates == DUP_REPLACE ||
+ info->handle_duplicates == DUP_UPDATE)
{
while ((error=table->file->write_row(table->record[0])))
{
@@ -393,7 +427,9 @@ int write_record(TABLE *table,COPY_INFO *info)
was used. This ensures that we don't get a problem when the
whole range of the key has been used.
*/
- if (table->next_number_field && key_nr == table->next_number_index &&
+ if (info->handle_duplicates == DUP_REPLACE &&
+ table->next_number_field &&
+ key_nr == table->next_number_index &&
table->file->auto_increment_column_changed)
goto err;
if (table->file->table_flags() & HA_DUPP_POS)
@@ -425,16 +461,33 @@ int write_record(TABLE *table,COPY_INFO *info)
HA_READ_KEY_EXACT))))
goto err;
}
- if (last_uniq_key(table,key_nr))
+ if (info->handle_duplicates == DUP_UPDATE)
{
- if ((error=table->file->update_row(table->record[1],table->record[0])))
- goto err;
- info->deleted++;
- break; /* Update logfile and count */
+ /* we don't check for other UNIQUE keys - the first row
+ that matches, is updated. If update causes a conflict again,
+ an error is returned
+ */
+ restore_record(table,1);
+ if (fill_record(*info->update_fields,*info->update_values))
+ goto err;
+ if ((error=table->file->update_row(table->record[1],table->record[0])))
+ goto err;
+ info->deleted++;
+ break;
+ }
+ else /* DUP_REPLACE */
+ {
+ if (last_uniq_key(table,key_nr))
+ {
+ if ((error=table->file->update_row(table->record[1],table->record[0])))
+ goto err;
+ info->deleted++;
+ break; /* Update logfile and count */
+ }
+ else if ((error=table->file->delete_row(table->record[1])))
+ goto err;
+ info->deleted++;
}
- else if ((error=table->file->delete_row(table->record[1])))
- goto err;
- info->deleted++;
}
info->copied++;
}
@@ -632,7 +685,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
{
if (!(tmp=new delayed_insert()))
{
- thd->fatal_error=1;
+ thd->fatal_error();
my_error(ER_OUTOFMEMORY,MYF(0),sizeof(delayed_insert));
pthread_mutex_unlock(&LOCK_delayed_create);
DBUG_RETURN(0);
@@ -644,7 +697,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
!(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME))))
{
delete tmp;
- thd->fatal_error=1;
+ thd->fatal_error();
my_error(ER_OUT_OF_RESOURCES,MYF(0));
pthread_mutex_unlock(&LOCK_delayed_create);
DBUG_RETURN(0);
@@ -663,9 +716,9 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
pthread_mutex_unlock(&tmp->mutex);
tmp->unlock();
delete tmp;
- thd->fatal_error=1;
+ thd->fatal_error();
pthread_mutex_unlock(&LOCK_delayed_create);
- net_printf(&thd->net,ER_CANT_CREATE_THREAD,error);
+ net_printf(thd,ER_CANT_CREATE_THREAD,error);
DBUG_RETURN(0);
}
@@ -679,10 +732,10 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
thd->proc_info="got old table";
if (tmp->thd.killed)
{
- if (tmp->thd.fatal_error)
+ if (tmp->thd.is_fatal_error)
{
/* Copy error message and abort */
- thd->fatal_error=1;
+ thd->fatal_error();
strmov(thd->net.last_error,tmp->thd.net.last_error);
thd->net.last_errno=tmp->thd.net.last_errno;
}
@@ -706,8 +759,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
tmp->unlock();
if (table)
thd->di=tmp;
- else if (tmp->thd.fatal_error)
- thd->fatal_error=1;
+ else if (tmp->thd.is_fatal_error)
+ thd->fatal_error();
DBUG_RETURN((table_list->table=table));
}
@@ -935,7 +988,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
DBUG_ENTER("handle_delayed_insert");
if (init_thr_lock() || thd->store_globals())
{
- thd->fatal_error=1;
+ thd->fatal_error();
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
goto end;
}
@@ -949,12 +1002,12 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
if (!(di->table=open_ltable(thd,&di->table_list,TL_WRITE_DELAYED)))
{
- thd->fatal_error=1; // Abort waiting inserts
+ thd->fatal_error(); // Abort waiting inserts
goto end;
}
if (di->table->file->has_transactions())
{
- thd->fatal_error=1;
+ thd->fatal_error();
my_error(ER_ILLEGAL_HA, MYF(0), di->table_list.real_name);
goto end;
}
@@ -1176,7 +1229,7 @@ bool delayed_insert::handle_inserts(void)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
using_ignore=1;
}
- thd.net.last_errno = 0; // reset error for binlog
+ thd.clear_error(); // reset error for binlog
if (write_record(table,&info))
{
info.error_count++; // Ignore errors
@@ -1270,10 +1323,11 @@ bool delayed_insert::handle_inserts(void)
***************************************************************************/
int
-select_insert::prepare(List<Item> &values)
+select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("select_insert::prepare");
+ unit= u;
if (check_insert_fields(thd,table,*fields,values,1))
DBUG_RETURN(1);
@@ -1303,16 +1357,16 @@ select_insert::~select_insert()
bool select_insert::send_data(List<Item> &values)
{
- if (thd->offset_limit)
+ if (unit->offset_limit_cnt)
{ // using limit offset,count
- thd->offset_limit--;
+ unit->offset_limit_cnt--;
return 0;
}
if (fields->elements)
fill_record(*fields,values);
else
fill_record(table->field,values);
- if (write_record(table,&info))
+ if (thd->net.report_error || write_record(table,&info))
return 1;
if (table->next_number_field) // Clear for next record
{
@@ -1326,7 +1380,8 @@ bool select_insert::send_data(List<Item> &values)
void select_insert::send_error(uint errcode,const char *err)
{
- ::send_error(&thd->net,errcode,err);
+ //TODO error should be sent at the query processing end
+ ::send_error(thd,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd);
ha_rollback_stmt(thd);
@@ -1352,7 +1407,8 @@ bool select_insert::send_eof()
if (error)
{
table->file->print_error(error,MYF(0));
- ::send_error(&thd->net);
+ //TODO error should be sent at the query processing end
+ ::send_error(thd);
return 1;
}
else
@@ -1366,7 +1422,7 @@ bool select_insert::send_eof()
thd->cuted_fields);
if (last_insert_id)
thd->insert_id(last_insert_id); // For update log
- ::send_ok(&thd->net,info.copied,last_insert_id,buff);
+ ::send_ok(thd,info.copied,last_insert_id,buff);
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
@@ -1384,10 +1440,11 @@ bool select_insert::send_eof()
***************************************************************************/
int
-select_create::prepare(List<Item> &values)
+select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("select_create::prepare");
+ unit= u;
table=create_table_from_items(thd, create_info, db, name,
extra_fields, keys, &values, &lock);
if (!table)
@@ -1416,13 +1473,13 @@ select_create::prepare(List<Item> &values)
bool select_create::send_data(List<Item> &values)
{
- if (thd->offset_limit)
+ if (unit->offset_limit_cnt)
{ // using limit offset,count
- thd->offset_limit--;
+ unit->offset_limit_cnt--;
return 0;
}
fill_record(field,values);
- if (write_record(table,&info))
+ if (thd->net.report_error ||write_record(table,&info))
return 1;
if (table->next_number_field) // Clear for next record
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 854f3924155..0fe3d11e404 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -75,7 +75,7 @@ inline int lex_casecmp(const char *s, const char *t, uint len)
#include "lex_hash.h"
-static uchar state_map[256];
+static uchar state_map[256], ident_map[256];
void lex_init(void)
@@ -90,23 +90,23 @@ void lex_init(void)
VOID(pthread_key_create(&THR_LEX,NULL));
/* Fill state_map with states to get a faster parser */
- for (i=0; i < 256 ; i++)
+ for (i=0; i < sizeof(state_map) ; i++)
{
- if (isalpha(i))
+ if (my_isalpha(system_charset_info,i))
state_map[i]=(uchar) STATE_IDENT;
- else if (isdigit(i))
+ else if (my_isdigit(system_charset_info,i))
state_map[i]=(uchar) STATE_NUMBER_IDENT;
#if defined(USE_MB) && defined(USE_MB_IDENT)
- else if (use_mb(default_charset_info) && my_ismbhead(default_charset_info, i))
+ else if (use_mb(system_charset_info) && my_ismbhead(system_charset_info, i))
state_map[i]=(uchar) STATE_IDENT;
#endif
- else if (!isgraph(i))
+ else if (!my_isgraph(system_charset_info,i))
state_map[i]=(uchar) STATE_SKIP;
else
state_map[i]=(uchar) STATE_CHAR;
}
state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) STATE_IDENT;
- state_map[(uchar)'\'']=state_map[(uchar)'"']=(uchar) STATE_STRING;
+ state_map[(uchar)'\'']=(uchar) STATE_STRING;
state_map[(uchar)'-']=state_map[(uchar)'+']=(uchar) STATE_SIGNED_NUMBER;
state_map[(uchar)'.']=(uchar) STATE_REAL_OR_POINT;
state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) STATE_CMP_OP;
@@ -121,10 +121,21 @@ void lex_init(void)
state_map[(uchar)'*']= (uchar) STATE_END_LONG_COMMENT;
state_map[(uchar)'@']= (uchar) STATE_USER_END;
state_map[(uchar) '`']= (uchar) STATE_USER_VARIABLE_DELIMITER;
- if (opt_sql_mode & MODE_ANSI_QUOTES)
+ state_map[(uchar)'"']= (uchar) STAT_STRING_OR_DELIMITER;
+
+ /*
+ Create a second map to make it faster to find identifiers
+ */
+ for (i=0; i < sizeof(ident_map) ; i++)
{
- state_map[(uchar) '"'] = STATE_USER_VARIABLE_DELIMITER;
+ ident_map[i]= (uchar) (state_map[i] == STATE_IDENT ||
+ state_map[i] == STATE_NUMBER_IDENT);
}
+
+ /* Special handling of hex and binary strings */
+ state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) STATE_IDENT_OR_HEX;
+ state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) STATE_IDENT_OR_BIN;
+
DBUG_VOID_RETURN;
}
@@ -136,29 +147,36 @@ void lex_free(void)
}
+/*
+ This is called before every query that is to be parsed.
+ Because of this, it's critical to not do too much things here.
+ (We already do too much here)
+*/
+
LEX *lex_start(THD *thd, uchar *buf,uint length)
{
LEX *lex= &thd->lex;
lex->next_state=STATE_START;
lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1;
- lex->select->create_refs=lex->in_comment=0;
+ lex->select_lex.create_refs=lex->in_comment=0;
lex->length=0;
- lex->select->in_sum_expr=0;
- lex->select->expr_list.empty();
- lex->select->ftfunc_list.empty();
- lex->convert_set=(lex->thd=thd)->variables.convert_set;
+ lex->select_lex.in_sum_expr=0;
+ lex->select_lex.expr_list.empty();
+ lex->select_lex.ftfunc_list_alloc.empty();
+ lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
+ lex->current_select= &lex->select_lex;
+ lex->convert_set= (lex->thd= thd)->variables.convert_set;
+ lex->thd_charset= lex->thd->variables.thd_charset;
lex->yacc_yyss=lex->yacc_yyvs=0;
- lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
- lex->slave_thd_opt=0;
+ lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command=SQLCOM_END;
- bzero(&lex->mi,sizeof(lex->mi));
return lex;
}
void lex_end(LEX *lex)
{
- lex->select->expr_list.delete_elements(); // If error when parsing sql-varargs
+ lex->select_lex.expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs);
}
@@ -180,7 +198,7 @@ static int find_keyword(LEX *lex, uint len, bool function)
udf_func *udf;
if (function && using_udf_functions && (udf=find_udf((char*) tok, len)))
{
- lex->thd->safe_to_cache_query=0;
+ lex->safe_to_cache_query=0;
lex->yylval->udf=udf;
switch (udf->returns) {
case STRING_RESULT:
@@ -189,6 +207,10 @@ static int find_keyword(LEX *lex, uint len, bool function)
return (udf->type == UDFTYPE_FUNCTION) ? UDF_FLOAT_FUNC : UDA_FLOAT_SUM;
case INT_RESULT:
return (udf->type == UDFTYPE_FUNCTION) ? UDF_INT_FUNC : UDA_INT_SUM;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
}
}
#endif
@@ -198,7 +220,7 @@ static int find_keyword(LEX *lex, uint len, bool function)
/* make a copy of token before ptr and set yytoklen */
-LEX_STRING get_token(LEX *lex,uint length)
+static LEX_STRING get_token(LEX *lex,uint length)
{
LEX_STRING tmp;
yyUnget(); // ptr points now after last token char
@@ -207,8 +229,29 @@ LEX_STRING get_token(LEX *lex,uint length)
return tmp;
}
-/* Return an unescaped text literal without quotes */
-/* Fix sometimes to do only one scan of the string */
+static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote)
+{
+ LEX_STRING tmp;
+ byte *from, *to, *end;
+ yyUnget(); // ptr points now after last token char
+ tmp.length=lex->yytoklen=length;
+ tmp.str=(char*) lex->thd->alloc(tmp.length+1);
+ for (from= (byte*) lex->tok_start, to= (byte*) tmp.str, end= to+length ;
+ to != end ;
+ )
+ {
+ if ((*to++= *from++) == quote)
+ from++; // Skip double quotes
+ }
+ *to= 0; // End null for safety
+ return tmp;
+}
+
+
+/*
+ Return an unescaped text literal without quotes
+ Fix sometimes to do only one scan of the string
+*/
static char *get_text(LEX *lex)
{
@@ -222,8 +265,8 @@ static char *get_text(LEX *lex)
c = yyGet();
#ifdef USE_MB
int l;
- if (use_mb(default_charset_info) &&
- (l = my_ismbchar(default_charset_info,
+ if (use_mb(system_charset_info) &&
+ (l = my_ismbchar(system_charset_info,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query))) {
lex->ptr += l-1;
@@ -267,8 +310,8 @@ static char *get_text(LEX *lex)
{
#ifdef USE_MB
int l;
- if (use_mb(default_charset_info) &&
- (l = my_ismbchar(default_charset_info,
+ if (use_mb(system_charset_info) &&
+ (l = my_ismbchar(system_charset_info,
(const char *)str, (const char *)end))) {
while (l--)
*to++ = *str++;
@@ -420,13 +463,13 @@ inline static uint int_token(const char *str,uint length)
// STATE_OPERATOR_OR_IDENT ; last state was an ident, text or number
// (which can't be followed by a signed number)
-int yylex(void *arg)
+int yylex(void *arg, void *yythd)
{
reg1 uchar c;
int tokval;
uint length;
enum lex_states state,prev_state;
- LEX *lex=current_lex;
+ LEX *lex= &(((THD *)yythd)->lex);
YYSTYPE *yylval=(YYSTYPE*) arg;
lex->yylval=yylval; // The global state
@@ -436,7 +479,7 @@ int yylex(void *arg)
LINT_INIT(c);
for (;;)
{
- switch(state) {
+ switch (state) {
case STATE_OPERATOR_OR_IDENT: // Next is operator or keyword
case STATE_START: // Start of token
// Skip startspace
@@ -457,7 +500,7 @@ int yylex(void *arg)
}
case STATE_CHAR: // Unknown or single char token
case STATE_SKIP: // This should not happen
- yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first char
+ yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr
yylval->lex_str.length=1;
c=yyGet();
if (c != ')')
@@ -466,18 +509,21 @@ int yylex(void *arg)
lex->tok_start=lex->ptr; // Let tok_start point at next item
return((int) c);
- case STATE_IDENT: // Incomplete keyword or ident
- if ((c == 'x' || c == 'X') && yyPeek() == '\'')
+ case STATE_IDENT_OR_HEX:
+ if (yyPeek() == '\'')
{ // Found x'hex-number'
- state=STATE_HEX_NUMBER;
+ state= STATE_HEX_NUMBER;
break;
}
+ /* Fall through */
+ case STATE_IDENT_OR_BIN: // TODO: Add binary string handling
+ case STATE_IDENT:
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(default_charset_info))
+ if (use_mb(system_charset_info))
{
- if (my_ismbhead(default_charset_info, yyGetLast()))
+ if (my_ismbhead(system_charset_info, yyGetLast()))
{
- int l = my_ismbchar(default_charset_info,
+ int l = my_ismbchar(system_charset_info,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query);
if (l == 0) {
@@ -486,13 +532,12 @@ int yylex(void *arg)
}
lex->ptr += l - 1;
}
- while (state_map[c=yyGet()] == STATE_IDENT ||
- state_map[c] == STATE_NUMBER_IDENT)
+ while (ident_map[c=yyGet()])
{
- if (my_ismbhead(default_charset_info, c))
+ if (my_ismbhead(system_charset_info, c))
{
int l;
- if ((l = my_ismbchar(default_charset_info,
+ if ((l = my_ismbchar(system_charset_info,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query)) == 0)
break;
@@ -502,15 +547,13 @@ int yylex(void *arg)
}
else
#endif
- while (state_map[c=yyGet()] == STATE_IDENT ||
- state_map[c] == STATE_NUMBER_IDENT) ;
+ while (ident_map[c=yyGet()]) ;
length= (uint) (lex->ptr - lex->tok_start)-1;
if (lex->ignore_space)
{
for (; state_map[c] == STATE_SKIP ; c= yyGet());
}
- if (c == '.' && (state_map[yyPeek()] == STATE_IDENT ||
- state_map[yyPeek()] == STATE_NUMBER_IDENT))
+ if (c == '.' && ident_map[yyPeek()])
lex->next_state=STATE_IDENT_SEP;
else
{ // '(' must follow directly if function
@@ -525,7 +568,19 @@ int yylex(void *arg)
yylval->lex_str=get_token(lex,length);
if (lex->convert_set)
lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
- return(IDENT);
+
+ /*
+ Note: "SELECT _bla AS 'alias'"
+ _bla should be considered as a IDENT if charset haven't been found.
+ So we don't use MYF(MY_WME) with get_charset_by_name to avoid
+ producing an error.
+ */
+
+ if ((yylval->lex_str.str[0]=='_') &&
+ (lex->charset=get_charset_by_csname(yylval->lex_str.str+1,MYF(0))))
+ return(UNDERSCORE_CHARSET);
+ else
+ return(IDENT);
case STATE_IDENT_SEP: // Found ident and now '.'
lex->next_state=STATE_IDENT_START;// Next is an ident (not a keyword)
@@ -535,8 +590,8 @@ int yylex(void *arg)
return((int) c);
case STATE_NUMBER_IDENT: // number or ident which num-start
- while (isdigit((c = yyGet()))) ;
- if (state_map[c] != STATE_IDENT)
+ while (my_isdigit(system_charset_info,(c = yyGet()))) ;
+ if (!ident_map[c])
{ // Can't be identifier
state=STATE_INT_OR_REAL;
break;
@@ -544,12 +599,13 @@ int yylex(void *arg)
if (c == 'e' || c == 'E')
{
// The following test is written this way to allow numbers of type 1e1
- if (isdigit(yyPeek()) || (c=(yyGet())) == '+' || c == '-')
+ if (my_isdigit(system_charset_info,yyPeek()) ||
+ (c=(yyGet())) == '+' || c == '-')
{ // Allow 1E+10
- if (isdigit(yyPeek())) // Number must have digit after sign
+ if (my_isdigit(system_charset_info,yyPeek())) // Number must have digit after sign
{
yySkip();
- while (isdigit(yyGet())) ;
+ while (my_isdigit(system_charset_info,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength());
return(FLOAT_NUM);
}
@@ -559,8 +615,8 @@ int yylex(void *arg)
else if (c == 'x' && (lex->ptr - lex->tok_start) == 2 &&
lex->tok_start[0] == '0' )
{ // Varbinary
- while (isxdigit((c = yyGet()))) ;
- if ((lex->ptr - lex->tok_start) >= 4 && state_map[c] != STATE_IDENT)
+ while (my_isxdigit(system_charset_info,(c = yyGet()))) ;
+ if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
{
yylval->lex_str=get_token(lex,yyLength());
yylval->lex_str.str+=2; // Skip 0x
@@ -573,11 +629,11 @@ int yylex(void *arg)
// fall through
case STATE_IDENT_START: // Incomplete ident
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(default_charset_info))
+ if (use_mb(system_charset_info))
{
- if (my_ismbhead(default_charset_info, yyGetLast()))
+ if (my_ismbhead(system_charset_info, yyGetLast()))
{
- int l = my_ismbchar(default_charset_info,
+ int l = my_ismbchar(system_charset_info,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query);
if (l == 0)
@@ -587,13 +643,12 @@ int yylex(void *arg)
}
lex->ptr += l - 1;
}
- while (state_map[c=yyGet()] == STATE_IDENT ||
- state_map[c] == STATE_NUMBER_IDENT)
+ while (ident_map[c=yyGet()])
{
- if (my_ismbhead(default_charset_info, c))
+ if (my_ismbhead(system_charset_info, c))
{
int l;
- if ((l = my_ismbchar(default_charset_info,
+ if ((l = my_ismbchar(system_charset_info,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query)) == 0)
break;
@@ -603,11 +658,9 @@ int yylex(void *arg)
}
else
#endif
- while (state_map[c = yyGet()] == STATE_IDENT ||
- state_map[c] == STATE_NUMBER_IDENT) ;
+ while (ident_map[c = yyGet()]) ;
- if (c == '.' && (state_map[yyPeek()] == STATE_IDENT ||
- state_map[yyPeek()] == STATE_NUMBER_IDENT))
+ if (c == '.' && ident_map[yyPeek()])
lex->next_state=STATE_IDENT_SEP;// Next is '.'
// fall through
@@ -618,52 +671,72 @@ int yylex(void *arg)
return(IDENT);
case STATE_USER_VARIABLE_DELIMITER:
+ {
+ char delim= c; // Used char
lex->tok_start=lex->ptr; // Skip first `
#ifdef USE_MB
- if (use_mb(default_charset_info))
+ if (use_mb(system_charset_info))
{
- while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER &&
- c != (uchar) NAMES_SEP_CHAR)
+ while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR)
{
- if (my_ismbhead(default_charset_info, c))
+ if (my_ismbhead(system_charset_info, c))
{
int l;
- if ((l = my_ismbchar(default_charset_info,
+ if ((l = my_ismbchar(system_charset_info,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query)) == 0)
break;
lex->ptr += l-1;
}
}
+ yylval->lex_str=get_token(lex,yyLength());
}
else
#endif
{
- while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER &&
- c != (uchar) NAMES_SEP_CHAR) ;
+ uint double_quotes= 0;
+ char quote_char= c;
+ while ((c=yyGet()))
+ {
+ if (c == quote_char)
+ {
+ if (yyPeek() != quote_char)
+ break;
+ c=yyGet();
+ double_quotes++;
+ continue;
+ }
+ if (c == (uchar) NAMES_SEP_CHAR)
+ break;
+ }
+ if (double_quotes)
+ yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes,
+ quote_char);
+ else
+ yylval->lex_str=get_token(lex,yyLength());
}
- yylval->lex_str=get_token(lex,yyLength());
if (lex->convert_set)
lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
- if (state_map[c] == STATE_USER_VARIABLE_DELIMITER)
+ if (c == delim)
yySkip(); // Skip end `
return(IDENT);
-
+ }
case STATE_SIGNED_NUMBER: // Incomplete signed number
if (prev_state == STATE_OPERATOR_OR_IDENT)
{
if (c == '-' && yyPeek() == '-' &&
- (isspace(yyPeek2()) || iscntrl(yyPeek2())))
+ (my_isspace(system_charset_info,yyPeek2()) ||
+ my_iscntrl(system_charset_info,yyPeek2())))
state=STATE_COMMENT;
else
state= STATE_CHAR; // Must be operator
break;
}
- if (!isdigit(c=yyGet()) || yyPeek() == 'x')
+ if (!my_isdigit(system_charset_info,c=yyGet()) || yyPeek() == 'x')
{
if (c != '.')
{
- if (c == '-' && isspace(yyPeek()))
+ if (c == '-' && my_isspace(system_charset_info,yyPeek()))
state=STATE_COMMENT;
else
state = STATE_CHAR; // Return sign as single char
@@ -671,9 +744,9 @@ int yylex(void *arg)
}
yyUnget(); // Fix for next loop
}
- while (isdigit(c=yyGet())) ; // Incomplete real or int number
+ while (my_isdigit(system_charset_info,c=yyGet())) ; // Incomplete real or int number
if ((c == 'e' || c == 'E') &&
- (yyPeek() == '+' || yyPeek() == '-' || isdigit(yyPeek())))
+ (yyPeek() == '+' || yyPeek() == '-' || my_isdigit(system_charset_info,yyPeek())))
{ // Real number
yyUnget();
c= '.'; // Fool next test
@@ -687,19 +760,19 @@ int yylex(void *arg)
}
// fall through
case STATE_REAL: // Incomplete real number
- while (isdigit(c = yyGet())) ;
+ while (my_isdigit(system_charset_info,c = yyGet())) ;
if (c == 'e' || c == 'E')
{
c = yyGet();
if (c == '-' || c == '+')
c = yyGet(); // Skip sign
- if (!isdigit(c))
+ if (!my_isdigit(system_charset_info,c))
{ // No digit after sign
state= STATE_CHAR;
break;
}
- while (isdigit(yyGet())) ;
+ while (my_isdigit(system_charset_info,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength());
return(FLOAT_NUM);
}
@@ -708,7 +781,7 @@ int yylex(void *arg)
case STATE_HEX_NUMBER: // Found x'hexstring'
yyGet(); // Skip '
- while (isxdigit((c = yyGet()))) ;
+ while (my_isxdigit(system_charset_info,(c = yyGet()))) ;
length=(lex->ptr - lex->tok_start); // Length of hexnum+3
if (!(length & 1) || c != '\'')
{
@@ -760,6 +833,13 @@ int yylex(void *arg)
lex->next_state= STATE_START; // Allow signed numbers
return(tokval);
+ case STAT_STRING_OR_DELIMITER:
+ if (((THD *) yythd)->variables.sql_mode & MODE_ANSI_QUOTES)
+ {
+ state= STATE_USER_VARIABLE_DELIMITER;
+ break;
+ }
+ /* " used for strings */
case STATE_STRING: // Incomplete text string
if (!(yylval->lex_str.str = get_text(lex)))
{
@@ -788,7 +868,7 @@ int yylex(void *arg)
ulong version=MYSQL_VERSION_ID;
yySkip();
state=STATE_START;
- if (isdigit(yyPeek()))
+ if (my_isdigit(system_charset_info,yyPeek()))
{ // Version number
version=strtol((char*) lex->ptr,(char**) &lex->ptr,10);
}
@@ -829,7 +909,15 @@ int yylex(void *arg)
case STATE_COLON: // optional line terminator
if (yyPeek())
{
- state=STATE_CHAR; // Return ';'
+ if (((THD *)yythd)->client_capabilities & CLIENT_MULTI_QUERIES)
+ {
+ lex->found_colon=(char*)lex->ptr;
+ ((THD *)yythd)->server_status |= SERVER_MORE_RESULTS_EXISTS;
+ lex->next_state=STATE_END;
+ return(END_OF_INPUT);
+ }
+ else
+ state=STATE_CHAR; // Return ';'
break;
}
/* fall true */
@@ -839,11 +927,10 @@ int yylex(void *arg)
case STATE_END:
lex->next_state=STATE_END;
return(0); // We found end of input last time
-
- // Actually real shouldn't start
- // with . but allow them anyhow
+
+ /* Actually real shouldn't start with . but allow them anyhow */
case STATE_REAL_OR_POINT:
- if (isdigit(yyPeek()))
+ if (my_isdigit(system_charset_info,yyPeek()))
state = STATE_REAL; // Real
else
{
@@ -855,6 +942,7 @@ int yylex(void *arg)
switch (state_map[yyPeek()]) {
case STATE_STRING:
case STATE_USER_VARIABLE_DELIMITER:
+ case STAT_STRING_OR_DELIMITER:
break;
case STATE_USER_END:
lex->next_state=STATE_SYSTEM_VAR;
@@ -868,7 +956,8 @@ int yylex(void *arg)
return((int) '@');
case STATE_HOSTNAME: // end '@' of user@hostname
for (c=yyGet() ;
- isalnum(c) || c == '.' || c == '_' || c == '$';
+ my_isalnum(system_charset_info,c) || c == '.' || c == '_' ||
+ c == '$';
c= yyGet()) ;
yylval->lex_str=get_token(lex,yyLength());
return(LEX_HOSTNAME);
@@ -885,8 +974,7 @@ int yylex(void *arg)
[(global | local | session) .]variable_name
*/
- while (state_map[c=yyGet()] == STATE_IDENT ||
- state_map[c] == STATE_NUMBER_IDENT) ;
+ while (ident_map[c=yyGet()]) ;
if (c == '.')
lex->next_state=STATE_IDENT_SEP;
length= (uint) (lex->ptr - lex->tok_start)-1;
@@ -902,3 +990,416 @@ int yylex(void *arg)
}
}
}
+
+/*
+ st_select_lex structures initialisations
+*/
+
+void st_select_lex_node::init_query()
+{
+ no_table_names_allowed= uncacheable= dependent= 0;
+ ref_pointer_array= 0;
+}
+
+void st_select_lex_node::init_select()
+{
+ order_list.elements= 0;
+ order_list.first= 0;
+ order_list.next= (byte**) &order_list.first;
+ select_limit= HA_POS_ERROR;
+ offset_limit= 0;
+ with_sum_func= 0;
+ create_refs= 0;
+}
+
+void st_select_lex_unit::init_query()
+{
+ linkage= GLOBAL_OPTIONS_TYPE;
+ st_select_lex_node::init_query();
+ global_parameters= this;
+ select_limit_cnt= HA_POS_ERROR;
+ offset_limit_cnt= 0;
+ union_option= 0;
+ prepared= optimized= executed= 0;
+ item= 0;
+ union_result= 0;
+ table= 0;
+}
+
+void st_select_lex::init_query()
+{
+ st_select_lex_node::init_query();
+ table_list.elements= 0;
+ table_list.first= 0;
+ table_list.next= (byte**) &table_list.first;
+ item_list.empty();
+ join= 0;
+ olap= UNSPECIFIED_OLAP_TYPE;
+ having_fix_field= 0;
+ with_wild= 0;
+}
+
+void st_select_lex::init_select()
+{
+ st_select_lex_node::init_select();
+ group_list.elements= 0;
+ group_list.first= 0;
+ group_list.next= (byte**) &group_list.first;
+ options= 0;
+ where= having= 0;
+ when_list.empty();
+ expr_list.empty();
+ interval_list.empty();
+ use_index.empty();
+ ftfunc_list_alloc.empty();
+ ftfunc_list= &ftfunc_list_alloc;
+ linkage= UNSPECIFIED_TYPE;
+}
+
+/*
+ st_select_lex structures linking
+*/
+
+/* include on level down */
+void st_select_lex_node::include_down(st_select_lex_node *upper)
+{
+ if ((next= upper->slave))
+ next->prev= &next;
+ prev= &upper->slave;
+ upper->slave= this;
+ master= upper;
+ slave= 0;
+}
+
+/* include neighbour (on same level) */
+void st_select_lex_node::include_neighbour(st_select_lex_node *before)
+{
+ if ((next= before->next))
+ next->prev= &next;
+ prev= &before->next;
+ before->next= this;
+ master= before->master;
+ slave= 0;
+}
+
+/* including in global SELECT_LEX list */
+void st_select_lex_node::include_global(st_select_lex_node **plink)
+{
+ if ((link_next= *plink))
+ link_next->link_prev= &link_next;
+ link_prev= plink;
+ *plink= this;
+}
+
+//excluding from global list (internal function)
+void st_select_lex_node::fast_exclude()
+{
+ if (link_prev)
+ {
+ if ((*link_prev= link_next))
+ link_next->link_prev= link_prev;
+ // Remove slave structure
+ for (; slave; slave= slave->next)
+ slave->fast_exclude();
+ }
+}
+
+/*
+ excluding select_lex structure (except first (first select can't be
+ deleted, because it is most upper select))
+*/
+void st_select_lex_node::exclude()
+{
+ //exclude from global list
+ fast_exclude();
+ //exclude from other structures
+ if ((*prev= next))
+ next->prev= prev;
+ /*
+ We do not need following statements, because prev pointer of first
+ list element point to master->slave
+ if (master->slave == this)
+ master->slave= next;
+ */
+}
+
+void st_select_lex_unit::exclude_level()
+{
+ SELECT_LEX_UNIT *units= 0, **units_last= &units;
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->link_prev && (*sl->link_prev= sl->link_next))
+ sl->link_next->link_prev= sl->link_prev;
+ SELECT_LEX_UNIT **last= 0;
+ for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
+ {
+ u->master= master;
+ last= (SELECT_LEX_UNIT**)&(u->next);
+ }
+ if (last)
+ {
+ (*units_last)= sl->first_inner_unit();
+ units_last= last;
+ }
+ }
+ if (units)
+ {
+ (*prev)= units;
+ (*units_last)= (SELECT_LEX_UNIT*)next;
+ }
+ else
+ (*prev)= next;
+}
+
+st_select_lex* st_select_lex_node::select_lex()
+{
+ DBUG_ENTER("st_select_lex_node::select_lex (never should be called)");
+ DBUG_ASSERT(0);
+ DBUG_RETURN(0);
+}
+
+bool st_select_lex_node::add_item_to_list(THD *thd, Item *item)
+{
+ return 1;
+}
+
+bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
+{
+ return 1;
+}
+
+bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc)
+{
+ return add_to_list(thd, order_list, item, asc);
+}
+
+bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func)
+{
+ return 1;
+}
+
+/*
+ st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
+ this to 'last' as dependent
+
+ SYNOPSIS
+ last - pointer to last st_select_lex struct, before wich all
+ st_select_lex have to be marked as dependent
+
+ NOTE
+ 'last' should be reachable from this st_select_lex_node
+
+*/
+
+void st_select_lex_node::mark_as_dependent(SELECT_LEX *last)
+{
+ /*
+ Mark all selects from resolved to 1 before select where was
+ found table as depended (of select where was found table)
+ */
+ for (SELECT_LEX_NODE *s= this;
+ s &&s != last;
+ s= s->outer_select())
+ if ( !s->dependent )
+ {
+ // Select is dependent of outer select
+ s->dependent= 1;
+ if (s->linkage != GLOBAL_OPTIONS_TYPE)
+ {
+ //s is st_select_lex*
+
+ s->master_unit()->dependent= 1;
+ //Tables will be reopened many times
+ for (TABLE_LIST *tbl=
+ s->get_table_list();
+ tbl;
+ tbl= tbl->next)
+ tbl->shared= 1;
+ }
+ }
+}
+
+bool st_select_lex_node::set_braces(bool value) { return 1; }
+bool st_select_lex_node::inc_in_sum_expr() { return 1; }
+uint st_select_lex_node::get_in_sum_expr() { return 0; }
+TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
+List<Item>* st_select_lex_node::get_item_list() { return 0; }
+List<String>* st_select_lex_node::get_use_index() { return 0; }
+List<String>* st_select_lex_node::get_ignore_index() { return 0; }
+TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
+ LEX_STRING *alias,
+ ulong table_join_options,
+ thr_lock_type flags,
+ List<String> *use_index,
+ List<String> *ignore_index)
+{
+ return 0;
+}
+ulong st_select_lex_node::get_table_join_options() { return 0; }
+
+/*
+ This is used for UNION & subselect to create a new table list of all used
+ tables.
+ The table_list->table entry in all used tables are set to point
+ to the entries in this list.
+*/
+
+// interface
+bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex,
+ TABLE_LIST **result,
+ bool check_derived)
+{
+ *result= 0;
+ return create_total_list_n_last_return(thd, lex, &result, check_derived);
+}
+
+// list creator
+bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
+ TABLE_LIST ***result,
+ bool check_derived)
+{
+ TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
+ TABLE_LIST **new_table_list= *result, *aux;
+ SELECT_LEX *sl= (SELECT_LEX*)slave;
+ for (; sl; sl= sl->next_select())
+ {
+ // check usage of ORDER BY in union
+ if (sl->order_list.first && sl->next_select() && !sl->braces)
+ {
+ net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
+ return 1;
+ }
+ if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
+ continue;
+ for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
+ inner;
+ inner= inner->next_unit())
+ if (inner->create_total_list_n_last_return(thd, lex,
+ &slave_list_last, 0))
+ return 1;
+ if ((aux= (TABLE_LIST*) sl->table_list.first))
+ {
+ TABLE_LIST *next;
+ for (; aux; aux= next)
+ {
+ TABLE_LIST *cursor;
+ next= aux->next;
+ for (cursor= **result; cursor; cursor= cursor->next)
+ if (!strcmp(cursor->db, aux->db) &&
+ !strcmp(cursor->real_name, aux->real_name) &&
+ !strcmp(cursor->alias, aux->alias))
+ break;
+ if (!cursor)
+ {
+ /* Add not used table to the total table list */
+ if (!(cursor= (TABLE_LIST *) thd->memdup((char*) aux,
+ sizeof(*aux))))
+ {
+ send_error(thd,0);
+ return 1;
+ }
+ *new_table_list= cursor;
+ new_table_list= &cursor->next;
+ *new_table_list= 0; // end result list
+ }
+ else
+ aux->shared= 1; // Mark that it's used twice
+ aux->table_list= cursor;
+ }
+ }
+ }
+ if (slave_list_first)
+ {
+ *new_table_list= slave_list_first;
+ new_table_list= slave_list_last;
+ }
+ *result= new_table_list;
+ return 0;
+}
+
+st_select_lex_unit* st_select_lex_unit::master_unit()
+{
+ return this;
+}
+
+st_select_lex* st_select_lex_unit::outer_select()
+{
+ return (st_select_lex*) master;
+}
+
+st_select_lex* st_select_lex::select_lex()
+{
+ return this;
+}
+
+bool st_select_lex::add_item_to_list(THD *thd, Item *item)
+{
+ return item_list.push_back(item);
+}
+
+bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
+{
+ return add_to_list(thd, group_list, item, asc);
+}
+
+bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
+{
+ return !func || ftfunc_list->push_back(func); // end of memory?
+}
+
+st_select_lex_unit* st_select_lex::master_unit()
+{
+ return (st_select_lex_unit*) master;
+}
+
+st_select_lex* st_select_lex::outer_select()
+{
+ return (st_select_lex*) master->get_master();
+}
+
+bool st_select_lex::set_braces(bool value)
+{
+ braces= value;
+ return 0;
+}
+
+bool st_select_lex::inc_in_sum_expr()
+{
+ in_sum_expr++;
+ return 0;
+}
+
+uint st_select_lex::get_in_sum_expr()
+{
+ return in_sum_expr;
+}
+
+TABLE_LIST* st_select_lex::get_table_list()
+{
+ return (TABLE_LIST*) table_list.first;
+}
+
+List<Item>* st_select_lex::get_item_list()
+{
+ return &item_list;
+}
+
+List<String>* st_select_lex::get_use_index()
+{
+ return use_index_ptr;
+}
+
+List<String>* st_select_lex::get_ignore_index()
+{
+ return ignore_index_ptr;
+}
+
+ulong st_select_lex::get_table_join_options()
+{
+ return table_join_options;
+}
+
+/*
+ There are st_select_lex::add_table_to_list &
+ st_select_lex::set_lock_for_tables in sql_parse.cc
+*/
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a905871e629..00852f302d8 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -37,6 +37,11 @@ class LEX_COLUMN;
#define LEX_YYSTYPE YYSTYPE *
#endif
+/*
+ When a command is added here, be sure it's also added in mysqld.cc
+ in "struct show_var_st status_vars[]= {" ...
+*/
+
enum enum_sql_command {
SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE,
SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT,
@@ -46,11 +51,13 @@ enum enum_sql_command {
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_INNODB_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
- SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE,
+ SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
+ SQLCOM_SHOW_CREATE_DB,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
- SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB,
- SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
+ SQLCOM_GRANT,
+ SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
+ SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
@@ -60,9 +67,13 @@ enum enum_sql_command {
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
- SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
+ SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
- SQLCOM_EMPTY_QUERY,
+ SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
+ SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES,
+ SQLCOM_HELP,
+
+ /* This should be the last !!! */
SQLCOM_END
};
@@ -75,9 +86,11 @@ enum lex_states
STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT,
STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END,
STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR,
- STATE_IDENT_OR_KEYWORD
+ STATE_IDENT_OR_KEYWORD, STATE_IDENT_OR_HEX, STATE_IDENT_OR_BIN,
+ STAT_STRING_OR_DELIMITER
};
+
typedef List<Item> List_item;
typedef struct st_lex_master_info
@@ -93,7 +106,8 @@ typedef struct st_lex_master_info
enum sub_select_type
{
- UNSPECIFIED_TYPE, UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, OLAP_TYPE, NOT_A_SELECT
+ UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,
+ EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE
};
enum olap_type
@@ -101,27 +115,296 @@ enum olap_type
UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE
};
-/* The state of the lex parsing for selects */
+/*
+ The state of the lex parsing for selects
+
+ All select describing structures linked with following pointers:
+ - list of neighbors (next/prev) (prev of first element point to slave
+ pointer of upper structure)
+ - one level units for unit (union) structure
+ - member of one union(unit) for ordinary select_lex
+ - pointer to master
+ - outer select_lex for unit (union)
+ - unit structure for ordinary select_lex
+ - pointer to slave
+ - first list element of select_lex belonged to this unit for unit
+ - first unit in list of units that belong to this select_lex (as
+ subselects or derived tables) for ordinary select_lex
+ - list of all select_lex (for group operation like correcting list of opened
+ tables)
+ for example for following query:
-typedef struct st_select_lex
-{
+ select *
+ from table1
+ where table1.field IN (select * from table1_1_1 union
+ select * from table1_1_2)
+ union
+ select *
+ from table2
+ where table2.field=(select (select f1 from table2_1_1_1_1
+ where table2_1_1_1_1.f2=table2_1_1.f3)
+ from table2_1_1
+ where table2_1_1.f1=table2.f2)
+ union
+ select * from table3;
+
+ we will have following structure:
+
+
+ main unit
+ select1 select2 select3
+ |^^ |^
+ s||| ||master
+ l||| |+---------------------------------+
+ a||| +---------------------------------+|
+ v|||master slave ||
+ e||+-------------------------+ ||
+ V| neighbor | V|
+ unit 1.1<==================>unit1.2 unit2.1
+ select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2
+ |^
+ ||
+ V|
+ unit2.1.1.1
+ select2.1.1.1.1
+
+
+ relation in main unit will be following:
+
+ main unit
+ |^^^
+ ||||
+ |||+------------------------------+
+ ||+--------------+ |
+ slave||master | |
+ V| neighbor | neighbor |
+ select1<========>select2<========>select3
+
+ list of all select_lex will be following (as it will be constructed by
+ parser):
+
+ select1->select2->select3->select2.1.1->select 2.1.2->select2.1.1.1.1-+
+ |
+ +---------------------------------------------------------------------+
+ |
+ +->select1.1.1->select1.1.2
+
+*/
+
+/*
+ Base class for st_select_lex (SELECT_LEX) &
+ st_select_lex_unit (SELECT_LEX_UNIT)
+*/
+struct st_lex;
+class st_select_lex;
+class st_select_lex_unit;
+class st_select_lex_node {
+protected:
+ st_select_lex_node *next, **prev, /* neighbor list */
+ *master, *slave, /* vertical links */
+ *link_next, **link_prev; /* list of whole SELECT_LEX */
+public:
+ ulong options;
enum sub_select_type linkage;
- enum olap_type olap;
- char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
- Item *where,*having;
- ha_rows select_limit,offset_limit;
- ulong options, table_join_options;
+ SQL_LIST order_list; /* ORDER clause */
List<List_item> expr_list;
- List<List_item> when_list;
- SQL_LIST order_list,table_list,group_list;
- List<Item> item_list;
- List<String> interval_list,use_index, *use_index_ptr,
+ List<List_item> when_list; /* WHEN clause (expression) */
+ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
+ // Arrays of pointers to top elements of all_fields list
+ Item **ref_pointer_array;
+
+ uint with_sum_func; /* sum function indicator and number of it */
+ bool create_refs;
+ bool dependent; /* dependent from outer select subselect */
+ bool uncacheable; /* result of this query can't be cached */
+ bool no_table_names_allowed; /* used for global order by */
+
+ static void *operator new(size_t size)
+ {
+ // TODO: Change to alloc() and explicitely clear elements in constructors
+ return (void*) sql_calloc((uint) size);
+ }
+ static void operator delete(void *ptr,size_t size) {}
+ st_select_lex_node() {}
+ virtual ~st_select_lex_node() {}
+ inline st_select_lex_node* get_master() { return master; }
+ virtual void init_query();
+ virtual void init_select();
+ void include_down(st_select_lex_node *upper);
+ void include_neighbour(st_select_lex_node *before);
+ void include_global(st_select_lex_node **plink);
+ void exclude();
+
+ virtual st_select_lex* select_lex();
+ virtual bool add_item_to_list(THD *thd, Item *item);
+ bool add_order_to_list(THD *thd, Item *item, bool asc);
+ virtual bool add_group_to_list(THD *thd, Item *item, bool asc);
+ virtual bool add_ftfunc_to_list(Item_func_match *func);
+
+ virtual st_select_lex_unit* master_unit()= 0;
+ virtual st_select_lex* outer_select()= 0;
+
+ virtual bool set_braces(bool value);
+ virtual bool inc_in_sum_expr();
+ virtual uint get_in_sum_expr();
+ virtual TABLE_LIST* get_table_list();
+ virtual List<Item>* get_item_list();
+ virtual List<String>* get_use_index();
+ virtual List<String>* get_ignore_index();
+ virtual ulong get_table_join_options();
+ virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
+ LEX_STRING *alias,
+ ulong table_options,
+ thr_lock_type flags= TL_UNLOCK,
+ List<String> *use_index= 0,
+ List<String> *ignore_index= 0);
+ virtual void set_lock_for_tables(thr_lock_type lock_type) {}
+ void mark_as_dependent(st_select_lex *last);
+
+ friend class st_select_lex_unit;
+ friend bool mysql_new_select(struct st_lex *lex, bool move_down);
+private:
+ void fast_exclude();
+};
+typedef class st_select_lex_node SELECT_LEX_NODE;
+
+/*
+ SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group
+ SELECT_LEXs
+*/
+struct st_lex;
+class THD;
+class select_result;
+class JOIN;
+class select_union;
+class st_select_lex_unit: public st_select_lex_node {
+protected:
+ List<Item> item_list;
+ TABLE_LIST result_table_list;
+ select_union *union_result;
+ TABLE *table; /* temporary table using for appending UNION results */
+
+ select_result *result;
+ int res;
+ bool describe, found_rows_for_union,
+ prepared, // prepare phase already performed for UNION (unit)
+ optimized, // optimize phase already performed for UNION (unit)
+ executed; // already executed
+public:
+ /*
+ Pointer to 'last' select or pointer to unit where stored
+ global parameters for union
+ */
+ st_select_lex_node *global_parameters;
+ /* LIMIT clause runtime counters */
+ ha_rows select_limit_cnt, offset_limit_cnt;
+ /* not NULL if union used in subselect, point to subselect item */
+ Item_subselect *item;
+ THD *thd;
+
+ uint union_option;
+
+ void init_query();
+ bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result,
+ bool check_current_derived);
+ st_select_lex_unit* master_unit();
+ st_select_lex* outer_select();
+ st_select_lex* first_select() { return (st_select_lex*) slave; }
+ st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
+ void exclude_level();
+
+ /* UNION methods */
+ int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);
+ int exec();
+ int cleanup();
+
+ friend void mysql_init_query(THD *thd);
+ friend int subselect_union_engine::exec();
+private:
+ bool create_total_list_n_last_return(THD *thd, st_lex *lex,
+ TABLE_LIST ***result,
+ bool check_current_derived);
+};
+typedef class st_select_lex_unit SELECT_LEX_UNIT;
+
+/*
+ SELECT_LEX - store information of parsed SELECT_LEX statment
+*/
+class st_select_lex: public st_select_lex_node
+{
+public:
+ char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
+ Item *where, *having; /* WHERE & HAVING clauses */
+ enum olap_type olap;
+ SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
+ List<Item> item_list; /* list of fields & expressions */
+ List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
- List<Item_func_match> ftfunc_list;
- uint in_sum_expr, sort_default;
- bool create_refs, braces;
- st_select_lex *next;
-} SELECT_LEX;
+ /*
+ Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
+ select_lex for calling mysql_select under results of union
+ */
+ List<Item_func_match> *ftfunc_list;
+ List<Item_func_match> ftfunc_list_alloc;
+ JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
+ const char *type; /* type of select for EXPLAIN */
+ ulong table_join_options;
+ uint in_sum_expr;
+ uint select_number; /* number of select (used for EXPLAIN) */
+ uint with_wild; /* item list contain '*' */
+ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
+ /* TRUE when having fix field called in processing of this SELECT */
+ bool having_fix_field;
+
+ void init_query();
+ void init_select();
+ st_select_lex_unit* master_unit();
+ st_select_lex_unit* first_inner_unit()
+ {
+ return (st_select_lex_unit*) slave;
+ }
+ st_select_lex* outer_select();
+ st_select_lex* next_select() { return (st_select_lex*) next; }
+ st_select_lex* next_select_in_list()
+ {
+ return (st_select_lex*) link_next;
+ }
+ st_select_lex_node** next_select_in_list_addr()
+ {
+ return &link_next;
+ }
+
+ bool set_braces(bool value);
+ bool inc_in_sum_expr();
+ uint get_in_sum_expr();
+
+ st_select_lex* select_lex();
+ bool add_item_to_list(THD *thd, Item *item);
+ bool add_group_to_list(THD *thd, Item *item, bool asc);
+ bool add_ftfunc_to_list(Item_func_match *func);
+
+ TABLE_LIST* get_table_list();
+ List<Item>* get_item_list();
+ List<String>* get_use_index();
+ List<String>* get_ignore_index();
+ ulong get_table_join_options();
+ TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
+ LEX_STRING *alias,
+ ulong table_options,
+ thr_lock_type flags= TL_UNLOCK,
+ List<String> *use_index= 0,
+ List<String> *ignore_index= 0);
+ void set_lock_for_tables(thr_lock_type lock_type);
+ inline void init_order()
+ {
+ order_list.elements= 0;
+ order_list.first= 0;
+ order_list.next= (byte**) &order_list.first;
+ }
+
+ friend void mysql_init_query(THD *thd);
+};
+typedef class st_select_lex SELECT_LEX;
/* The state of the lex parsing. This is saved in the THD struct */
@@ -130,17 +413,25 @@ typedef struct st_lex
{
uint yylineno,yytoklen; /* Simulate lex */
LEX_YYSTYPE yylval;
- SELECT_LEX select_lex, *select, *last_selects;
+ SELECT_LEX_UNIT unit; /* most upper unit */
+ SELECT_LEX select_lex; /* first SELECT_LEX */
+ /* current SELECT_LEX in parsing */
+ SELECT_LEX_NODE *current_select;
+ /* list of all SELECT_LEX */
+ SELECT_LEX *all_selects_list;
uchar *ptr,*tok_start,*tok_end,*end_of_query;
char *length,*dec,*change,*name;
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
char* x509_subject,*x509_issuer,*ssl_cipher;
+ char* found_colon; /* For multi queries - next query */
enum SSL_type ssl_type; /* defined in violite.h */
String *wild;
sql_exchange *exchange;
+ select_result *result;
List<key_part_spec> col_list;
+ List<key_part_spec> ref_list;
List<Alter_drop> drop_list;
List<Alter_column> alter_list;
List<String> interval_list;
@@ -151,12 +442,13 @@ typedef struct st_lex
List<Item> *insert_list,field_list,value_list;
List<List_item> many_values;
List<set_var_base> var_list;
+ List<Item> param_list;
SQL_LIST proc_list, auxilliary_table_list;
TYPELIB *interval;
create_field *last_field;
- Item *default_value;
+ Item *default_value, *comment;
CONVERT *convert_set;
- CONVERT *thd_convert_set; // Set with SET CHAR SET
+ CHARSET_INFO *thd_charset;
LEX_USER *grant_user;
gptr yacc_yyss,yacc_yyvs;
THD *thd;
@@ -167,6 +459,7 @@ typedef struct st_lex
USER_RESOURCES mqh;
ulong thread_id,type;
enum_sql_command sql_command;
+ thr_lock_type lock_option;
enum lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
@@ -174,11 +467,33 @@ typedef struct st_lex
enum ha_rkey_function ha_rkey_mode;
enum enum_enable_or_disable alter_keys_onoff;
enum enum_var_type option_type;
- uint grant,grant_tot_col,which_columns, union_option;
- thr_lock_type lock_option;
- bool drop_primary, drop_if_exists, drop_temporary, local_file, olap;
- bool in_comment,ignore_space,verbose,simple_alter;
+ uint grant, grant_tot_col, which_columns;
+ uint fk_delete_opt, fk_update_opt, fk_match_option;
+ uint param_count;
+ bool drop_primary, drop_if_exists, drop_temporary, local_file;
+ bool in_comment, ignore_space, verbose, simple_alter;
+ bool derived_tables, describe;
+ bool safe_to_cache_query;
uint slave_thd_opt;
+ CHARSET_INFO *charset;
+ char *help_arg;
+
+ inline void uncacheable()
+ {
+ safe_to_cache_query= 0;
+
+ /*
+ There are no sense to mark select_lex and union fields of LEX,
+ but we should merk all subselects as uncacheable from current till
+ most upper
+ */
+ for (SELECT_LEX_NODE *sl= current_select;
+ sl != &select_lex;
+ sl= sl->outer_select())
+ {
+ sl->uncacheable = sl->master_unit()->uncacheable= 1;
+ }
+ }
} LEX;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 542eef623f0..505ea994d42 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -25,8 +25,16 @@
class Sql_alloc
{
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
+ static void *operator new[](size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
+ static void operator delete[](void *ptr, size_t size) {}
#ifdef HAVE_purify
bool dummy;
inline Sql_alloc() :dummy(0) {}
@@ -82,6 +90,7 @@ public:
first=tmp.first;
last=tmp.last;
}
+ inline base_list(bool error) { }
inline bool push_back(void *info)
{
if (((*last)=new list_node(info, &end_of_list)))
@@ -122,11 +131,15 @@ public:
last= &first;
return tmp->info;
}
+ inline list_node* last_node() { return *last; }
+ inline list_node* first_node() { return first;}
inline void *head() { return first->info; }
inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
inline bool is_empty() { return first == &end_of_list ; }
inline list_node *last_ref() { return &end_of_list; }
friend class base_list_iterator;
+ friend class error_list;
+ friend class error_list_iterator;
protected:
void after(void *info,list_node *node)
@@ -142,12 +155,20 @@ protected:
class base_list_iterator
{
+protected:
base_list *list;
list_node **el,**prev,*current;
+ void sublist(base_list &ls, uint elm)
+ {
+ ls.first= *el;
+ ls.last= list->last;
+ ls.elements= elm;
+ }
public:
- base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first),
- prev(0),current(0)
+ base_list_iterator(base_list &list_par)
+ :list(&list_par), el(&list_par.first), prev(0), current(0)
{}
+
inline void *next(void)
{
prev=el;
@@ -204,9 +225,9 @@ public:
{
return el == &list->last_ref()->next;
}
+ friend class error_list_iterator;
};
-
template <class T> class List :public base_list
{
public:
@@ -254,6 +275,10 @@ public:
List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); }
+ void sublist(List<T> &list, uint el)
+ {
+ base_list_iterator::sublist(list, el);
+ }
};
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index c1c6267879e..49b4f2f7c2f 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -77,6 +77,8 @@ static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
String &enclosed);
+#ifndef EMBEDDED_LIBRARY
+
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
List<Item> &fields, enum enum_duplicates handle_duplicates,
bool read_file_from_client,thr_lock_type lock_type)
@@ -117,7 +119,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
{ // Part field list
thd->dupp_field=0;
- if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0))
+ if (setup_tables(table_list) ||
+ setup_fields(thd, 0, table_list, fields, 1, 0, 0))
DBUG_RETURN(-1);
if (thd->dupp_field)
{
@@ -156,12 +159,14 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (read_file_from_client && handle_duplicates == DUP_ERROR)
handle_duplicates=DUP_IGNORE;
+#ifndef EMBEDDED_LIBRARY
if (read_file_from_client)
{
(void)net_request_file(&thd->net,ex->file_name);
file = -1;
}
else
+#endif
{
read_file_from_client=0;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
@@ -306,7 +311,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted,
info.records-info.copied,thd->cuted_fields);
- send_ok(&thd->net,info.copied+info.deleted,0L,name);
+ send_ok(thd,info.copied+info.deleted,0L,name);
// on the slave thd->query is never initialized
if (!thd->slave_thread)
mysql_update_log.write(thd,thd->query,thd->query_length);
@@ -346,6 +351,7 @@ err:
DBUG_RETURN(error);
}
+#endif /* EMBEDDED_LIBRARY */
/****************************************************************************
** Read of rows of fixed size + optional garage + optonal newline
@@ -393,7 +399,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
field->field_length)
length=field->field_length;
save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc
- field->store((char*) pos,length);
+ field->store((char*) pos,length,default_charset_info);
pos[length]=save_chr;
if ((pos+=length) > read_info.row_end)
pos= read_info.row_end; /* Fills rest with space */
@@ -474,7 +480,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
}
field->set_notnull();
read_info.row_end[0]=0; // Safe to change end marker
- field->store((char*) read_info.row_start,length);
+ field->store((char*) read_info.row_start,length,default_charset_info);
}
if (read_info.error)
break;
@@ -604,9 +610,11 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
cache.read_function = _my_b_net_read;
need_end_io_cache = 1;
+#ifndef EMBEDDED_LIBRARY
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
cache.pre_read = cache.pre_close =
(IO_CACHE_CALLBACK) log_loaded_block;
+#endif
}
}
}
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 6eb4fbcaaf6..a5f164e1e38 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -62,7 +62,7 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new
List_iterator<Item> list_it(select_lex->item_list);
List_iterator<Item> new_it(new_fields);
- while((item=list_it++))
+ while ((item=list_it++))
{
bool not_found=true;
if (item->type()==Item::FIELD_ITEM)
@@ -109,15 +109,15 @@ static int olap_combos(List<Item> old_fields, List<Item> new_fields, Item *item
int num_new_fields)
{
int sl_return = 0;
- if(position == num_new_fields)
+ if (position == num_new_fields)
{
- if(item)
+ if (item)
new_fields.push_front(item);
sl_return = make_new_olap_select(lex, select_lex, new_fields);
}
else
{
- if(item)
+ if (item)
new_fields.push_front(item);
while ((num_fields - num_new_fields >= selection - position) && !sl_return)
{
@@ -164,18 +164,20 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
- setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,select_lex->item_list,1,&all_fields,1) ||
- setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1))
+ setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
+ select_lex->item_list, 1, &all_fields,1) ||
+ setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
+ item_list_copy, 1, &all_fields, 1))
return -1;
if (select_lex->olap == CUBE_TYPE)
{
- for( int i=count-1; i>=0 && !sl_return; i--)
+ for ( int i=count-1; i>=0 && !sl_return; i--)
sl_return=olap_combos(item_list_copy, new_item_list, (Item *)0, lex, select_lex, 0, 0, count, i);
}
else if (select_lex->olap == ROLLUP_TYPE)
{
- for( int i=count-1; i>=0 && !sl_return; i--)
+ for ( int i=count-1; i>=0 && !sl_return; i--)
{
Item *item;
item_list_copy.pop();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6249c769015..ba5862a7fde 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -21,7 +21,6 @@
#include <m_ctype.h>
#include <myisam.h>
#include <my_dir.h>
-#include <assert.h>
#ifdef HAVE_INNOBASE_DB
#include "ha_innodb.h"
@@ -44,30 +43,26 @@
#else
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
-#define SCRAMBLE_LENGTH 8
#define MEM_ROOT_BLOCK_SIZE 8192
#define MEM_ROOT_PREALLOC 8192
#define TRANS_MEM_ROOT_BLOCK_SIZE 4096
#define TRANS_MEM_ROOT_PREALLOC 4096
-extern int yyparse(void);
+extern int yyparse(void *thd);
extern "C" pthread_mutex_t THR_LOCK_keycache;
#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif
-static int check_for_max_user_connections(USER_CONN *uc);
+static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
-static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
-static void mysql_init_query(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, char **filename_ptr,
char *table_name);
-static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result);
const char *any_db="*any*"; // Special symbol for check_access
@@ -76,10 +71,11 @@ const char *command_name[]={
"Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist",
"Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user",
"Binlog Dump","Table Dump", "Connect Out", "Register Slave",
+ "Prepare", "Prepare Execute", "Long Data", "Close stmt",
"Error" // Last command number
};
-bool volatile abort_slave = 0;
+static char empty_c_string[1]= {0}; // Used for not defined 'db'
#ifdef __WIN__
static void test_signal(int sig_ptr)
@@ -130,7 +126,7 @@ extern pthread_mutex_t LOCK_user_conn;
static int get_or_create_user_conn(THD *thd, const char *user,
const char *host,
- USER_RESOURCES *mqh)
+ USER_RESOURCES *mqh)
{
int return_val=0;
uint temp_len, user_len, host_len;
@@ -152,7 +148,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
my_malloc(sizeof(struct user_conn) + temp_len+1,
MYF(MY_WME)))))
{
- send_error(&current_thd->net, 0, NullS); // Out of memory
+ send_error(thd, 0, NullS); // Out of memory
return_val=1;
goto end;
}
@@ -164,13 +160,13 @@ static int get_or_create_user_conn(THD *thd, const char *user,
uc->connections = 1;
uc->questions=uc->updates=uc->conn_per_hour=0;
uc->user_resources=*mqh;
- if (max_user_connections && mqh->connections > max_user_connections)
+ if (max_user_connections && mqh->connections > max_user_connections)
uc->user_resources.connections = max_user_connections;
uc->intime=thd->thr_create_time;
if (hash_insert(&hash_user_connections, (byte*) uc))
{
my_free((char*) uc,0);
- send_error(&current_thd->net, 0, NullS); // Out of memory
+ send_error(thd, 0, NullS); // Out of memory
return_val=1;
goto end;
}
@@ -179,7 +175,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
end:
(void) pthread_mutex_unlock(&LOCK_user_conn);
return return_val;
-
+
}
@@ -189,44 +185,71 @@ end:
thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access
*/
-static bool check_user(THD *thd,enum_server_command command, const char *user,
- const char *passwd, const char *db, bool check_count)
+static int check_user(THD *thd,enum_server_command command, const char *user,
+ const char *passwd, const char *db, bool check_count,
+ bool simple_connect, bool do_send_error,
+ char *crypted_scramble, bool had_password,
+ uint *cur_priv_version, ACL_USER** hint_user)
{
- NET *net= &thd->net;
thd->db=0;
thd->db_length=0;
USER_RESOURCES ur;
- if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
- return 1;
- if (!(thd->user = my_strdup(user, MYF(0))))
+ /* We shall avoid dupplicate user allocations here */
+ if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
{
- send_error(net,ER_OUT_OF_RESOURCES);
+ send_error(thd,ER_OUT_OF_RESOURCES);
return 1;
}
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
passwd, thd->scramble, &thd->priv_user,
- protocol_version == 9 ||
- !(thd->client_capabilities &
- CLIENT_LONG_PASSWORD),&ur);
+ (protocol_version == 9 ||
+ !(thd->client_capabilities &
+ CLIENT_LONG_PASSWORD)),
+ &ur,crypted_scramble,
+ cur_priv_version,hint_user);
+
DBUG_PRINT("info",
("Capabilities: %d packet_length: %ld Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
thd->host_or_ip, thd->priv_user,
- passwd[0] ? "yes": "no",
+ had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
+
+ /*
+ In case we're going to retry we should not send error message at this
+ point
+ */
if (thd->master_access & NO_ACCESS)
{
- net_printf(net, ER_ACCESS_DENIED_ERROR,
- thd->user,
- thd->host_or_ip,
- passwd[0] ? ER(ER_YES) : ER(ER_NO));
- mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
- thd->user,
- thd->host_or_ip,
- passwd[0] ? ER(ER_YES) : ER(ER_NO));
- return(1); // Error already given
+ if (do_send_error)
+ {
+ /*
+ Old client should get nicer error message if password version is
+ not supported
+ */
+ if (simple_connect && *hint_user && (*hint_user)->pversion)
+ {
+ net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ }
+ else
+ {
+ net_printf(thd, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ thd->host_or_ip,
+ had_password ? ER(ER_YES) : ER(ER_NO));
+ mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
+ thd->user,
+ thd->host_or_ip,
+ had_password ? ER(ER_YES) : ER(ER_NO));
+ }
+ return(1); // Error already given
+ }
+ else
+ return(-1); // do not report error in special handshake
}
+
if (check_count)
{
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -235,7 +258,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (tmp)
{ // Too many connections
- send_error(net, ER_CON_COUNT_ERROR);
+ send_error(thd, ER_CON_COUNT_ERROR);
return(1);
}
}
@@ -251,9 +274,10 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
if ((ur.questions || ur.updates || ur.connections) &&
get_or_create_user_conn(thd,user,thd->host_or_ip,&ur))
return -1;
- if (thd->user_connect && thd->user_connect->user_resources.connections &&
- check_for_max_user_connections(thd->user_connect))
+ if (thd->user_connect && thd->user_connect->user_resources.connections &&
+ check_for_max_user_connections(thd, thd->user_connect))
return -1;
+
if (db && db[0])
{
bool error=test(mysql_change_db(thd,db));
@@ -262,7 +286,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
return error;
}
else
- send_ok(net); // Ready to handle questions
+ send_ok(thd); // Ready to handle questions
return 0; // ok
}
@@ -284,35 +308,35 @@ extern "C" void free_user(struct user_conn *uc)
my_free((char*) uc,MYF(0));
}
-void init_max_user_conn(void)
+void init_max_user_conn(void)
{
- (void) hash_init(&hash_user_connections,max_connections,0,0,
+ (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
+ 0,0,
(hash_get_key) get_key_conn, (hash_free_key) free_user,
0);
}
-static int check_for_max_user_connections(USER_CONN *uc)
+static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
DBUG_ENTER("check_for_max_user_connections");
-
+
if (max_user_connections &&
(max_user_connections <= (uint) uc->connections))
{
- net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user);
+ net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user);
error=1;
goto end;
}
- uc->connections++;
+ uc->connections++;
if (uc->user_resources.connections &&
uc->conn_per_hour++ >= uc->user_resources.connections)
{
- net_printf(&current_thd->net, ER_USER_LIMIT_REACHED, uc->user,
+ net_printf(thd, ER_USER_LIMIT_REACHED, uc->user,
"max_connections",
(long) uc->user_resources.connections);
error=1;
- goto end;
}
end:
DBUG_RETURN(error);
@@ -367,9 +391,13 @@ void init_update_queries(void)
uc_update_queries[SQLCOM_RESTORE_TABLE]=1;
uc_update_queries[SQLCOM_DELETE_MULTI]=1;
uc_update_queries[SQLCOM_DROP_INDEX]=1;
- uc_update_queries[SQLCOM_MULTI_UPDATE]=1;
+ uc_update_queries[SQLCOM_UPDATE_MULTI]=1;
}
+bool is_update_query(enum enum_sql_command command)
+{
+ return uc_update_queries[command];
+}
/*
Check if maximum queries per hour limit has been reached
@@ -403,7 +431,7 @@ static bool check_mqh(THD *thd, uint check_command)
if (uc->user_resources.questions &&
uc->questions++ >= uc->user_resources.questions)
{
- net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
+ net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
(long) uc->user_resources.questions);
error=1;
goto end;
@@ -414,7 +442,7 @@ static bool check_mqh(THD *thd, uint check_command)
if (uc->user_resources.updates && uc_update_queries[check_command] &&
uc->updates++ >= uc->user_resources.updates)
{
- net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
+ net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
(long) uc->user_resources.updates);
error=1;
goto end;
@@ -429,7 +457,7 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
{
(void) pthread_mutex_lock(&LOCK_user_conn);
- if (lu) // for GRANT
+ if (lu) // for GRANT
{
USER_CONN *uc;
uint temp_len=lu->user.length+lu->host.length+2;
@@ -468,16 +496,20 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
Returns 0 on ok, -1 < if error is given > 0 on error.
*/
+#ifndef EMBEDDED_LIBRARY
static int
check_connections(THD *thd)
{
uint connect_errors=0;
NET *net= &thd->net;
- /* Store the connection details */
- DBUG_PRINT("info", (("check_connections called by thread %d"),
- thd->thread_id));
+ char *end, *user, *passwd, *db;
+ char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
+ ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
+ uint cur_priv_version;
DBUG_PRINT("info",("New connection received on %s",
- vio_description(net->vio)));
+ vio_description(net->vio)));
+ /* Remove warning from valgrind. TODO: Fix it in password.c */
+ bzero((char*) prepared_scramble, sizeof(prepared_scramble));
if (!thd->host) // If TCP/IP connection
{
char ip[30];
@@ -493,15 +525,17 @@ check_connections(THD *thd)
thd->host=(char*) localhost;
else
#endif
- if (!(specialflag & SPECIAL_NO_RESOLVE))
{
- vio_in_addr(net->vio,&thd->remote.sin_addr);
- thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
- /* Cut very long hostnames to avoid possible overflows */
- if (thd->host)
- thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
- if (connect_errors > max_connect_errors)
- return(ER_HOST_IS_BLOCKED);
+ if (!(specialflag & SPECIAL_NO_RESOLVE))
+ {
+ vio_in_addr(net->vio,&thd->remote.sin_addr);
+ thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
+ /* Cut very long hostnames to avoid possible overflows */
+ if (thd->host)
+ thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
+ if (connect_errors > max_connect_errors)
+ return(ER_HOST_IS_BLOCKED);
+ }
}
DBUG_PRINT("info",("Host: %s ip: %s",
thd->host ? thd->host : "unknown host",
@@ -522,8 +556,9 @@ check_connections(THD *thd)
ulong pkt_len=0;
{
/* buff[] needs to big enough to hold the server_version variable */
- char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end;
- int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB;
+ char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
+ int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
@@ -545,9 +580,11 @@ check_connections(THD *thd)
int2store(end+3,thd->server_status);
bzero(end+5,13);
end+=18;
- if (net_write_command(net,(uchar) protocol_version, buff,
+
+ // At this point we write connection message and read reply
+ if (net_write_command(net,(uchar) protocol_version, "", 0, buff,
(uint) (end-buff)) ||
- (pkt_len= my_net_read(net)) == packet_error ||
+ (pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
{
inc_host_errors(&thd->remote.sin_addr);
@@ -563,8 +600,20 @@ check_connections(THD *thd)
return(ER_OUT_OF_RESOURCES);
thd->client_capabilities=uint2korr(net->read_pos);
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
+ thd->max_client_packet_length= uint4korr(net->read_pos+4);
+ end= (char*) net->read_pos+8;
+ }
+ else
+ {
+ thd->max_client_packet_length= uint3korr(net->read_pos+2);
+ end= (char*) net->read_pos+5;
+ }
+
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
- thd->sql_mode|= MODE_IGNORE_SPACE;
+ thd->variables.sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
@@ -576,7 +625,7 @@ check_connections(THD *thd)
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
pkt_len));
inc_host_errors(&thd->remote.sin_addr);
- return(ER_HANDSHAKE_ERROR);
+ return(ER_HANDSHAKE_ERROR);
}
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error ||
@@ -588,36 +637,87 @@ check_connections(THD *thd)
return(ER_HANDSHAKE_ERROR);
}
}
- else
+#endif
+
+ if (end >= (char*) net->read_pos+ pkt_len +2)
{
- DBUG_PRINT("info", ("Leaving IO layer intact"));
- if (pkt_len < NORMAL_HANDSHAKE_SIZE)
- {
- inc_host_errors(&thd->remote.sin_addr);
- return ER_HANDSHAKE_ERROR;
- }
+ inc_host_errors(&thd->remote.sin_addr);
+ return(ER_HANDSHAKE_ERROR);
}
-#endif
- thd->max_client_packet_length=uint3korr(net->read_pos+2);
- char *user= (char*) net->read_pos+5;
- char *passwd= strend(user)+1;
- char *db=0;
+ user= end;
+ passwd= strend(user)+1;
+ db=0;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1;
+
+ /* We can get only old hash at this point */
+ if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
+ return ER_HANDSHAKE_ERROR;
+
if (thd->client_capabilities & CLIENT_INTERACTIVE)
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
- thd->net.return_status= &thd->server_status;
+ net->return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout;
- if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
- return (-1);
- thd->password=test(passwd[0]);
+
+ /* Simple connect only for old clients. New clients always use secure auth */
+ bool simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
+
+ /* Store information if we used password. passwd will be dammaged */
+ bool using_password=test(passwd[0]);
+
+ /* Check user permissions. If password failure we'll get scramble back */
+ if (check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
+ simple_connect, prepared_scramble, using_password,
+ &cur_priv_version,
+ &cached_user)<0)
+ {
+ /* Store current used and database as they are erased with next packet */
+ char tmp_user[USERNAME_LENGTH+1];
+ char tmp_db[NAME_LEN+1];
+
+ tmp_user[0]= tmp_db[0]= 0;
+ /* If The client is old we just have to return error */
+ if (simple_connect)
+ return -1;
+
+ if (user)
+ strmake(tmp_user,user,USERNAME_LENGTH);
+ if (db)
+ strmake(tmp_db,db,NAME_LEN);
+
+ /* Write hash and encrypted scramble to client */
+ if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
+ net_flush(net))
+ {
+ inc_host_errors(&thd->remote.sin_addr);
+ return ER_HANDSHAKE_ERROR;
+ }
+ /* Reading packet back */
+ if ((pkt_len= my_net_read(net)) == packet_error)
+ {
+ inc_host_errors(&thd->remote.sin_addr);
+ return ER_HANDSHAKE_ERROR;
+ }
+ /* We have to get very specific packet size */
+ if (pkt_len != SCRAMBLE41_LENGTH)
+ {
+ inc_host_errors(&thd->remote.sin_addr);
+ return ER_HANDSHAKE_ERROR;
+ }
+ /* Final attempt to check the user based on reply */
+ if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
+ tmp_db, 1, 0, 1, prepared_scramble, using_password,
+ &cur_priv_version,
+ &cached_user))
+ return -1;
+ }
+ thd->password=using_password;
return 0;
}
-
pthread_handler_decl(handle_one_connection,arg)
{
THD *thd=(THD*) arg;
@@ -674,10 +774,10 @@ pthread_handler_decl(handle_one_connection,arg)
if ((error=check_connections(thd)))
{ // Wrong permissions
if (error > 0)
- net_printf(net,error,thd->host_or_ip);
+ net_printf(thd,error,thd->host_or_ip);
#ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
- sleep(1); /* must wait after eof() */
+ my_sleep(1000); /* must wait after eof() */
#endif
statistic_increment(aborted_connects,&LOCK_status);
goto end_thread;
@@ -705,7 +805,7 @@ pthread_handler_decl(handle_one_connection,arg)
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
free_root(&thd->mem_root,MYF(0));
- if (net->error && net->vio != 0)
+ if (net->error && net->vio != 0 && net->report_error)
{
if (!thd->killed && thd->variables.log_warnings)
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
@@ -714,10 +814,10 @@ pthread_handler_decl(handle_one_connection,arg)
thd->host_or_ip,
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
- send_error(net,net->last_errno,NullS);
+ send_error(thd,net->last_errno,NullS);
statistic_increment(aborted_threads,&LOCK_status);
}
-
+
end_thread:
close_connection(net);
end_thread(thd,1);
@@ -746,7 +846,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
if (my_thread_init() || thd->store_globals())
{
close_connection(&thd->net,ER_OUT_OF_RESOURCES);
- thd->fatal_error=1;
+ thd->fatal_error();
goto end;
}
DBUG_ENTER("handle_bootstrap");
@@ -773,7 +873,8 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
while (fgets(buff, thd->net.max_packet, file))
{
uint length=(uint) strlen(buff);
- while (length && (isspace(buff[length-1]) || buff[length-1] == ';'))
+ while (length && (my_isspace(system_charset_info, buff[length-1]) ||
+ buff[length-1] == ';'))
length--;
buff[length]=0;
thd->current_tablenr=0;
@@ -790,7 +891,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
}
mysql_parse(thd,thd->query,length);
close_thread_tables(thd); // Free tables
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
break;
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
@@ -807,11 +908,13 @@ end:
DBUG_RETURN(0); // Never reached
}
+#endif /* EMBEDDED_LIBRARY */
-inline void free_items(THD *thd)
-{
/* This works because items are allocated with sql_alloc() */
- for (Item *item=thd->free_list ; item ; item=item->next)
+
+void free_items(Item *item)
+{
+ for (; item ; item=item->next)
delete item;
}
@@ -831,12 +934,12 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if (!db || check_db_name(db))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
+ net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
goto err;
}
if (lower_case_table_names)
- casedn_str(tbl_name);
- remove_escape(tbl_name);
+ my_casedn_str(files_charset_info, tbl_name);
+ remove_escape(table_list->real_name);
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
@@ -851,7 +954,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
thd->query = tbl_name;
if ((error = mysqld_dump_create_info(thd, table, -1)))
{
- my_error(ER_GET_ERRNO, MYF(0));
+ my_error(ER_GET_ERRNO, MYF(0), my_errno);
goto err;
}
net_flush(&thd->net);
@@ -866,6 +969,7 @@ err:
/* Execute one command from socket (query or simple command) */
+#ifndef EMBEDDED_LIBRARY
bool do_command(THD *thd)
{
char *packet;
@@ -882,8 +986,7 @@ bool do_command(THD *thd)
old_timeout=net->read_timeout;
// Wait max for 8 hours
net->read_timeout=(uint) thd->variables.net_wait_timeout;
- net->last_error[0]=0; // Clear error message
- net->last_errno=0;
+ thd->clear_error(); // Clear error message
net_new_transaction(net);
if ((packet_length=my_net_read(net)) == packet_error)
@@ -894,7 +997,7 @@ bool do_command(THD *thd)
/* Check if we can continue without closing the connection */
if (net->error != 3)
DBUG_RETURN(TRUE); // We have to close it.
- send_error(net,net->last_errno,NullS);
+ send_error(thd,net->last_errno,NullS);
net->error= 0;
DBUG_RETURN(FALSE);
}
@@ -912,6 +1015,7 @@ bool do_command(THD *thd)
DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
}
+#endif /* EMBEDDED_LIBRARY */
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length)
@@ -941,12 +1045,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db);
break;
+#ifndef EMBEDDED_LIBRARY
case COM_REGISTER_SLAVE:
{
if (!register_slave(thd, (uchar*)packet, packet_length))
- send_ok(&thd->net);
+ send_ok(thd);
break;
}
+#endif
case COM_TABLE_DUMP:
{
statistic_increment(com_other, &LOCK_status);
@@ -960,13 +1066,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
memcpy(tbl_name, packet + db_len + 2, tbl_len);
tbl_name[tbl_len] = 0;
if (mysql_table_dump(thd, db, tbl_name, -1))
- send_error(&thd->net); // dump to NET
+ send_error(thd); // dump to NET
break;
}
+#ifndef EMBEDDED_LIBRARY
case COM_CHANGE_USER:
{
thd->change_user();
- clear_error_message(thd); // If errors from rollback
+ thd->clear_error(); // If errors from rollback
statistic_increment(com_other,&LOCK_status);
char *user= (char*) packet;
@@ -978,63 +1085,156 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint save_db_access= thd->db_access;
uint save_db_length= thd->db_length;
char *save_user= thd->user;
+ thd->user=NULL; /* Needed for check_user to allocate new user */
char *save_priv_user= thd->priv_user;
char *save_db= thd->db;
- thd->user=0;
- USER_CONN *save_uc= thd->user_connect;
+ USER_CONN *save_uc= thd->user_connect;
+ bool simple_connect;
+ bool using_password;
+ char prepared_scramble[SCRAMBLE41_LENGTH+4];/* Buffer for scramble,hash */
+ char tmp_user[USERNAME_LENGTH+1];
+ char tmp_db[NAME_LEN+1];
+ ACL_USER* cached_user ; /* Cached user */
+ uint cur_priv_version; /* Cached grant version */
+ ulong pkt_len=0; /* Length of reply packet */
+
+ /* Small check for incomming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
- { // Check if protocol is ok
- send_error(net, ER_UNKNOWN_COM_ERROR);
- break;
- }
- if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0))
- { // Restore old user
- x_free(thd->user);
- thd->master_access=save_master_access;
- thd->db_access=save_db_access;
- thd->db=save_db;
- thd->db_length=save_db_length;
- thd->user=save_user;
- thd->priv_user=save_priv_user;
- break;
+ goto restore_user_err;
+
+ /* Now we shall basically perform authentication again */
+
+ /* We can get only old hash at this point */
+ if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
+ goto restore_user_err;
+
+ cached_user= NULL;
+
+ /* Simple connect only for old clients. New clients always use sec. auth*/
+ simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
+
+ /* Store information if we used password. passwd will be dammaged */
+ using_password=test(passwd[0]);
+
+ if (simple_connect) /* Restore scramble for old clients */
+ memcpy(thd->scramble,thd->old_scramble,9);
+
+ /*
+ Check user permissions. If password failure we'll get scramble back
+ Do not retry if we already have sent error (result>0)
+ */
+ if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect,
+ simple_connect, prepared_scramble, using_password, &cur_priv_version,
+ &cached_user) < 0)
+ {
+ /* If The client is old we just have to have auth failure */
+ if (simple_connect)
+ goto restore_user; /* Error is already reported */
+
+ /* Store current used and database as they are erased with next packet */
+ tmp_user[0]= tmp_db[0]= 0;
+ if (user)
+ strmake(tmp_user,user,USERNAME_LENGTH);
+ if (db)
+ strmake(tmp_db,db,NAME_LEN);
+
+ /* Write hash and encrypted scramble to client */
+ if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
+ net_flush(net))
+ goto restore_user_err;
+
+ /* Reading packet back */
+ if ((pkt_len=my_net_read(net)) == packet_error)
+ goto restore_user_err;
+
+ /* We have to get very specific packet size */
+ if (pkt_len!=SCRAMBLE41_LENGTH)
+ goto restore_user;
+
+ /* Final attempt to check the user based on reply */
+ if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*) net->read_pos,
+ tmp_db, 0, 0, 1, prepared_scramble, using_password,
+ &cur_priv_version,
+ &cached_user))
+ goto restore_user;
}
+ /* Finally we've authenticated new user */
if (max_connections && save_uc)
decrease_user_connections(save_uc);
x_free((gptr) save_db);
x_free((gptr) save_user);
- thd->password=test(passwd[0]);
+ thd->password=using_password;
break;
- }
+ /* Bad luck we shall restore old user */
+ restore_user_err:
+ send_error(thd, ER_UNKNOWN_COM_ERROR);
+
+ restore_user:
+ x_free(thd->user);
+ thd->master_access=save_master_access;
+ thd->db_access=save_db_access;
+ thd->db=save_db;
+ thd->db_length=save_db_length;
+ thd->user=save_user;
+ thd->priv_user=save_priv_user;
+ break;
+ }
+#endif /* EMBEDDED_LIBRARY */
+ case COM_EXECUTE:
+ {
+ mysql_stmt_execute(thd, packet);
+ break;
+ }
+ case COM_LONG_DATA:
+ {
+ mysql_stmt_get_longdata(thd, packet, packet_length);
+ break;
+ }
+ case COM_PREPARE:
+ {
+ mysql_stmt_prepare(thd, packet, packet_length);
+ break;
+ }
+ case COM_CLOSE_STMT:
+ {
+ mysql_stmt_free(thd, packet);
+ break;
+ }
case COM_QUERY:
{
- packet_length--; // Remove end null
- /* Remove garage at start and end of query */
- while (isspace(packet[0]) && packet_length > 0)
- {
- packet++;
- packet_length--;
- }
- char *pos=packet+packet_length; // Point at end null
- while (packet_length > 0 && (pos[-1] == ';' || isspace(pos[-1])))
- {
- pos--;
- packet_length--;
- }
- /* We must allocate some extra memory for query cache */
- if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
- packet_length,
- thd->db_length+2)))
- break;
- thd->query[packet_length]=0;
- thd->packet.shrink(thd->variables.net_buffer_length);// Reclaim some memory
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+ if (alloc_query(thd, packet, packet_length))
+ break; // fatal error is set
mysql_log.write(thd,command,"%s",thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
- /* thd->query_length is set by mysql_parse() */
- mysql_parse(thd,thd->query,packet_length);
+ mysql_parse(thd,thd->query, thd->query_length);
+
+ while (!thd->killed && !thd->is_fatal_error && thd->lex.found_colon)
+ {
+ char *packet= thd->lex.found_colon;
+ /*
+ Multiple queries exits, execute them individually
+ */
+ if (thd->lock || thd->open_tables || thd->derived_tables)
+ close_thread_tables(thd);
+
+ ulong length= thd->query_length-(ulong)(thd->lex.found_colon-thd->query);
+
+ /* Remove garbage at start of query */
+ while (my_isspace(system_charset_info, *packet) && length > 0)
+ {
+ packet++;
+ length--;
+ }
+ thd->query_length= length;
+ thd->query= packet;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query_id= query_id++;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ mysql_parse(thd, packet, length);
+ }
+
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
DBUG_PRINT("info",("query ready"));
@@ -1042,7 +1242,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_FIELD_LIST: // This isn't actually needed
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
break;
#else
{
@@ -1052,7 +1252,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
- send_error(net,ER_NO_DB_ERROR);
+ send_error(thd,ER_NO_DB_ERROR);
break;
}
thd->free_list=0;
@@ -1063,7 +1263,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
if (lower_case_table_names)
- casedn_str(table_list.real_name);
+ my_casedn_str(files_charset_info, table_list.real_name);
remove_escape(table_list.real_name); // This can't have wildcards
if (check_access(thd,SELECT_ACL,table_list.db,&thd->col_access))
@@ -1072,7 +1272,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2))
break;
mysqld_list_fields(thd,&table_list,fields);
- free_items(thd);
+ free_items(thd->free_list);
break;
}
#endif
@@ -1090,7 +1290,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
+ net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
if (check_access(thd,CREATE_ACL,db,0,1))
@@ -1106,20 +1306,21 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
+ net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
if (check_access(thd,DROP_ACL,db,0,1))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
break;
}
mysql_log.write(thd,command,db);
mysql_rm_db(thd,db,0,0);
break;
}
+#ifndef EMBEDDED_LIBRARY
case COM_BINLOG_DUMP:
{
statistic_increment(com_other,&LOCK_status);
@@ -1144,6 +1345,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
net->error = 0;
break;
}
+#endif
case COM_REFRESH:
{
statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
@@ -1155,18 +1357,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
reload_acl_and_cache(thd, options, (TABLE_LIST*) 0) ;
break;
}
+#ifndef EMBEDDED_LIBRARY
case COM_SHUTDOWN:
statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
DBUG_PRINT("quit",("Got shutdown command"));
mysql_log.write(thd,command,NullS);
- send_eof(net);
+ send_eof(thd);
#ifdef __WIN__
sleep(1); // must wait after eof()
#endif
#ifndef OS2
- send_eof(net); // This is for 'quit request'
+ send_eof(thd); // This is for 'quit request'
#endif
close_connection(net);
close_thread_tables(thd); // Free before kill
@@ -1175,7 +1378,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
kill_mysql();
error=TRUE;
break;
-
+#endif
+#ifndef EMBEDDED_LIBRARY
case COM_STATISTICS:
{
mysql_log.write(thd,command,NullS);
@@ -1197,9 +1401,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
VOID(net_flush(net));
break;
}
+#endif
case COM_PING:
statistic_increment(com_other,&LOCK_status);
- send_ok(net); // Tell client we are alive
+ send_ok(thd); // Tell client we are alive
break;
case COM_PROCESS_INFO:
statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
@@ -1222,7 +1427,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; /* purecov: inspected */
mysql_print_status(thd);
mysql_log.write(thd,command,NullS);
- send_eof(net);
+ send_eof(thd);
break;
case COM_SLEEP:
case COM_CONNECT: // Impossible here
@@ -1230,17 +1435,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_DELAYED_INSERT:
case COM_END:
default:
- send_error(net, ER_UNKNOWN_COM_ERROR);
+ send_error(thd, ER_UNKNOWN_COM_ERROR);
break;
}
- if (thd->lock || thd->open_tables)
+ if (thd->lock || thd->open_tables || thd->derived_tables)
{
thd->proc_info="closing tables";
close_thread_tables(thd); /* Free tables */
}
- if (thd->fatal_error)
- send_error(net,0); // End of memory ?
+ if (thd->is_fatal_error)
+ send_error(thd,0); // End of memory ?
time_t start_of_query=thd->start_time;
thd->end_time(); // Set start time
@@ -1272,24 +1477,84 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_RETURN(error);
}
+
+/*
+ Read query from packet and store in thd->query
+ Used in COM_QUERY and COM_PREPARE
+
+ DESCRIPTION
+ Sets the following THD variables:
+ query
+ query_length
+
+ RETURN VALUES
+ 0 ok
+ 1 error; In this case thd->fatal_error is set
+*/
+
+bool alloc_query(THD *thd, char *packet, ulong packet_length)
+{
+ packet_length--; // Remove end null
+ /* Remove garbage at start and end of query */
+ while (my_isspace(system_charset_info,packet[0]) && packet_length > 0)
+ {
+ packet++;
+ packet_length--;
+ }
+ char *pos=packet+packet_length; // Point at end null
+ while (packet_length > 0 &&
+ (pos[-1] == ';' || my_isspace(system_charset_info,pos[-1])))
+ {
+ pos--;
+ packet_length--;
+ }
+ /* We must allocate some extra memory for query cache */
+ if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
+ packet_length,
+ thd->db_length+2)))
+ return 1;
+ thd->query[packet_length]=0;
+ thd->query_length= packet_length;
+ thd->packet.shrink(thd->variables.net_buffer_length);// Reclaim some memory
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+ return 0;
+}
+
/****************************************************************************
** mysql_execute_command
** Execute command saved in thd and current_lex->sql_command
****************************************************************************/
void
-mysql_execute_command(void)
+mysql_execute_command(THD *thd)
{
- int res=0;
- THD *thd=current_thd;
+ int res= 0;
LEX *lex= &thd->lex;
- TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
- SELECT_LEX *select_lex = lex->select;
+ TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
+ /*
+ Reset warning count for each query that uses tables
+ A better approach would be to reset this for any commands
+ that is not a SHOW command or a select that only access local
+ variables, but for now this is probably good enough.
+ */
+ if (tables || &lex->select_lex != lex->all_selects_list)
+ mysql_reset_errors(thd);
+ /*
+ Save old warning count to be able to send to client how many warnings we
+ got
+ */
+ thd->old_total_warn_count= thd->total_warn_count;
+
+#ifndef EMBEDDED_LIBRARY
if (thd->slave_thread)
{
- /*
+ /*
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated
*/
@@ -1308,23 +1573,47 @@ mysql_execute_command(void)
}
#endif
}
-
+#endif /* EMBEDDED_LIBRARY */
/*
- Skip if we are in the slave thread, some table rules have been given
- and the table list says the query should not be replicated
+ TODO: make derived tables processing 'inside' SELECT processing.
+ TODO: solve problem with depended derived tables in subselects
*/
- if ((lex->select_lex.next && create_total_list(thd,lex,&tables)) ||
+ if (lex->derived_tables)
+ {
+ for (SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ for (TABLE_LIST *cursor= sl->get_table_list();
+ cursor;
+ cursor= cursor->next)
+ {
+ if (cursor->derived && (res=mysql_derived(thd, lex,
+ cursor->derived,
+ cursor)))
+ {
+ if (res < 0 || thd->net.report_error)
+ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ DBUG_VOID_RETURN;
+ }
+ }
+ }
+ }
+ if ((&lex->select_lex != lex->all_selects_list &&
+ lex->unit.create_total_list(thd, lex, &tables, 0))
+#ifdef HAVE_REPLICATION
+ ||
(table_rules_on && tables && thd->slave_thread &&
- !tables_ok(thd,tables)))
+ !tables_ok(thd,tables))
+#endif
+ )
DBUG_VOID_RETURN;
statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
- select_result *result;
- if (select_lex->options & SELECT_DESCRIBE)
- lex->exchange=0;
+ select_result *result=lex->result;
if (tables)
{
res=check_table_access(thd,
@@ -1341,72 +1630,73 @@ mysql_execute_command(void)
break; // Error message is given
}
- thd->offset_limit=select_lex->offset_limit;
- thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
- if (thd->select_limit < select_lex->select_limit)
- thd->select_limit= HA_POS_ERROR; // no limit
- if (thd->select_limit == HA_POS_ERROR)
+ unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit;
+ unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+
+ unit->global_parameters->offset_limit);
+ if (unit->select_limit_cnt <
+ (ha_rows) unit->global_parameters->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR; // no limit
+ if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS;
- if (lex->exchange)
+ if (!(res=open_and_lock_tables(thd,tables)))
{
- if (lex->exchange->dumpfile)
+ if (lex->describe)
{
- if (!(result=new select_dump(lex->exchange)))
+ if (!(result= new select_send()))
{
- res= -1;
- break;
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
}
+ else
+ thd->send_explain_fields(result);
+ fix_tables_pointers(lex->all_selects_list);
+ res= mysql_explain_union(thd, &thd->lex.unit, result);
+ MYSQL_LOCK *save_lock= thd->lock;
+ thd->lock= (MYSQL_LOCK *)0;
+ result->send_eof();
+ thd->lock= save_lock;
}
else
{
- if (!(result=new select_export(lex->exchange)))
+ if (!result)
{
- res= -1;
- break;
- }
- }
- }
- else if (!(result=new select_send()))
- {
- res= -1;
+ if (!(result=new select_send()))
+ {
+ res= -1;
#ifdef DELETE_ITEMS
- delete select_lex->having;
- delete select_lex->where;
+ delete select_lex->having;
+ delete select_lex->where;
#endif
- break;
- }
- else
- {
- /*
- Normal select:
- Change lock if we are using SELECT HIGH PRIORITY,
- FOR UPDATE or IN SHARE MODE
-
- TODO: Delete the following loop when locks is set by sql_yacc
- */
- TABLE_LIST *table;
- for (table = tables ; table ; table=table->next)
- table->lock_type= lex->lock_option;
- }
-
- if (!(res=open_and_lock_tables(thd,tables)))
- {
- query_cache_store_query(thd, tables);
- res=handle_select(thd, lex, result);
+ break;
+ }
+ }
+ query_cache_store_query(thd, tables);
+ res=handle_select(thd, lex, result);
+ }
}
- else
- delete result;
break;
}
case SQLCOM_DO:
- res=mysql_do(thd, *lex->insert_list);
+ if (tables && ((res= check_table_access(thd, SELECT_ACL, tables)) ||
+ (res= open_and_lock_tables(thd,tables))))
+ break;
+
+ fix_tables_pointers(lex->all_selects_list);
+ res= mysql_do(thd, *lex->insert_list);
+ if (thd->net.report_error)
+ res= -1;
break;
case SQLCOM_EMPTY_QUERY:
- send_ok(&thd->net);
+ send_ok(thd);
break;
+ case SQLCOM_HELP:
+ res= mysqld_help(thd,lex->help_arg);
+ break;
+
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_PURGE:
{
if (check_global_access(thd, SUPER_ACL))
@@ -1414,18 +1704,37 @@ mysql_execute_command(void)
res = purge_master_logs(thd, lex->to_log);
break;
}
+#endif
+
+ case SQLCOM_SHOW_WARNS:
+ {
+ res= mysqld_show_warnings(thd, (ulong)
+ ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) |
+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) |
+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)
+ ));
+ break;
+ }
+ case SQLCOM_SHOW_ERRORS:
+ {
+ res= mysqld_show_warnings(thd, (ulong)
+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
+ break;
+ }
case SQLCOM_SHOW_NEW_MASTER:
{
if (check_global_access(thd, REPL_SLAVE_ACL))
goto error;
#ifndef WORKING_NEW_MASTER
- net_printf(&thd->net, ER_NOT_SUPPORTED_YET, "SHOW NEW MASTER");
+ net_printf(thd, ER_NOT_SUPPORTED_YET, "SHOW NEW MASTER");
res= 1;
#else
res = show_new_master(thd);
#endif
break;
}
+
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_SHOW_SLAVE_HOSTS:
{
if (check_global_access(thd, REPL_SLAVE_ACL))
@@ -1440,6 +1749,8 @@ mysql_execute_command(void)
res = show_binlog_events(thd);
break;
}
+#endif
+
case SQLCOM_BACKUP_TABLE:
{
if (check_db_used(thd,tables) ||
@@ -1459,6 +1770,8 @@ mysql_execute_command(void)
res = mysql_restore_table(thd, tables);
break;
}
+
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_CHANGE_MASTER:
{
if (check_global_access(thd, SUPER_ACL))
@@ -1484,7 +1797,7 @@ mysql_execute_command(void)
res = show_binlog_info(thd);
break;
}
-
+
case SQLCOM_LOAD_MASTER_DATA: // sync with master
if (check_global_access(thd, SUPER_ACL))
goto error;
@@ -1493,7 +1806,8 @@ mysql_execute_command(void)
else
res = load_master_data(thd);
break;
-
+#endif /* EMBEDDED_LIBRARY */
+
#ifdef HAVE_INNOBASE_DB
case SQLCOM_SHOW_INNODB_STATUS:
{
@@ -1504,6 +1818,7 @@ mysql_execute_command(void)
}
#endif
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_LOAD_MASTER_TABLE:
{
if (!tables->db)
@@ -1522,7 +1837,7 @@ mysql_execute_command(void)
}
if (strlen(tables->real_name) > NAME_LEN)
{
- net_printf(&thd->net,ER_WRONG_TABLE_NAME,tables->real_name);
+ net_printf(thd,ER_WRONG_TABLE_NAME,tables->real_name);
break;
}
LOCK_ACTIVE_MI;
@@ -1530,11 +1845,13 @@ mysql_execute_command(void)
if (!fetch_master_table(thd, tables->db, tables->real_name,
active_mi, 0))
{
- send_ok(&thd->net);
+ send_ok(thd);
}
UNLOCK_ACTIVE_MI;
break;
}
+#endif /* EMBEDDED_LIBRARY */
+
case SQLCOM_CREATE_TABLE:
{
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
@@ -1558,7 +1875,7 @@ mysql_execute_command(void)
}
if (strlen(tables->real_name) > NAME_LEN)
{
- net_printf(&thd->net, ER_WRONG_TABLE_NAME, tables->alias);
+ net_printf(thd, ER_WRONG_TABLE_NAME, tables->alias);
res=0;
break;
}
@@ -1580,24 +1897,21 @@ mysql_execute_command(void)
select_result *result;
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- check_dup(tables->db, tables->real_name, tables->next))
+ find_real_table_in_list(tables->next, tables->db, tables->real_name))
{
- net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
+ net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
if (tables->next)
{
- TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next))
goto error; // Error message is given
- /* TODO: Delete the following loop when locks is set by sql_yacc */
- for (table = tables->next ; table ; table=table->next)
- table->lock_type= lex->lock_option;
}
- thd->offset_limit=select_lex->offset_limit;
- thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
- if (thd->select_limit < select_lex->select_limit)
- thd->select_limit= HA_POS_ERROR; // No limit
+ unit->offset_limit_cnt= select_lex->offset_limit;
+ unit->select_limit_cnt= select_lex->select_limit+
+ select_lex->offset_limit;
+ if (unit->select_limit_cnt < select_lex->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR; // No limit
/* Skip first table, which is the table we are creating */
lex->select_lex.table_list.first=
@@ -1616,12 +1930,16 @@ mysql_execute_command(void)
}
else // regular create
{
- res = mysql_create_table(thd,tables->db ? tables->db : thd->db,
- tables->real_name, &lex->create_info,
- lex->create_list,
- lex->key_list,0, 0); // do logging
+ if (lex->name)
+ res= mysql_create_like_table(thd, tables, &lex->create_info,
+ (Table_ident *)lex->name);
+ else
+ res= mysql_create_table(thd,tables->db ? tables->db : thd->db,
+ tables->real_name, &lex->create_info,
+ lex->create_list,
+ lex->key_list,0,0,0); // do logging
if (!res)
- send_ok(&thd->net);
+ send_ok(thd);
}
break;
}
@@ -1638,6 +1956,7 @@ mysql_execute_command(void)
res = mysql_create_index(thd, tables, lex->key_list);
break;
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_SLAVE_START:
{
LOCK_ACTIVE_MI;
@@ -1661,7 +1980,7 @@ mysql_execute_command(void)
*/
if (thd->locked_tables || thd->active_transaction())
{
- send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
break;
}
{
@@ -1670,16 +1989,18 @@ mysql_execute_command(void)
UNLOCK_ACTIVE_MI;
break;
}
+#endif
+
case SQLCOM_ALTER_TABLE:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
break;
#else
{
ulong priv=0;
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
- net_printf(&thd->net,ER_WRONG_TABLE_NAME,lex->name);
+ net_printf(thd,ER_WRONG_TABLE_NAME,lex->name);
res=0;
break;
}
@@ -1689,7 +2010,7 @@ mysql_execute_command(void)
select_lex->db=tables->db;
if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) ||
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv) ||
- check_merge_table_access(thd, tables->db,
+ check_merge_table_access(thd, tables->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
@@ -1721,6 +2042,7 @@ mysql_execute_command(void)
&lex->create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
+ select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter);
@@ -1760,9 +2082,10 @@ mysql_execute_command(void)
res= -1;
break;
}
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_SHOW_BINLOGS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
@@ -1771,10 +2094,11 @@ mysql_execute_command(void)
res = show_binlogs(thd);
break;
}
-#endif
+#endif
+#endif /* EMBEDDED_LIBRARY */
case SQLCOM_SHOW_CREATE:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
@@ -1828,11 +2152,12 @@ mysql_execute_command(void)
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.row_type=ROW_TYPE_DEFAULT;
+ create_info.table_charset=default_charset_info;
res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
- (ORDER *) 0,
- 0,DUP_ERROR);
+ 0, (ORDER *) 0,
+ 0, DUP_ERROR);
}
else
res = mysql_optimize_table(thd, tables, &lex->check_opt);
@@ -1845,31 +2170,40 @@ mysql_execute_command(void)
goto error;
if (select_lex->item_list.elements != lex->value_list.elements)
{
- send_error(&thd->net,ER_WRONG_VALUE_COUNT);
+ send_error(thd,ER_WRONG_VALUE_COUNT);
DBUG_VOID_RETURN;
}
- if (select_lex->table_list.elements == 1)
+ res= mysql_update(thd,tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ select_lex->order_list.elements,
+ (ORDER *) select_lex->order_list.first,
+ select_lex->select_limit,
+ lex->duplicates);
+ if (thd->net.report_error)
+ res= -1;
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege))
+ goto error;
+ if (grant_option && check_grant(thd,UPDATE_ACL,tables))
+ goto error;
+ if (select_lex->item_list.elements != lex->value_list.elements)
{
- res= mysql_update(thd,tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- (ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
- lex->duplicates);
+ send_error(thd,ER_WRONG_VALUE_COUNT);
+ DBUG_VOID_RETURN;
}
- else
{
const char *msg= 0;
- lex->sql_command= SQLCOM_MULTI_UPDATE;
if (select_lex->order_list.elements)
- msg="ORDER BY";
+ msg= "ORDER BY";
else if (select_lex->select_limit && select_lex->select_limit !=
HA_POS_ERROR)
- msg="LIMIT";
+ msg= "LIMIT";
if (msg)
{
- net_printf(&thd->net, ER_WRONG_USAGE, "UPDATE", msg);
+ net_printf(thd, ER_WRONG_USAGE, "UPDATE", msg);
res= 1;
break;
}
@@ -1878,28 +2212,31 @@ mysql_execute_command(void)
&lex->value_list,
select_lex->where,
select_lex->options,
- lex->duplicates);
+ lex->duplicates, unit, select_lex);
}
break;
- case SQLCOM_INSERT:
- if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege))
- goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,INSERT_ACL,tables))
- goto error;
- res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- lex->duplicates);
- break;
case SQLCOM_REPLACE:
- if (check_access(thd,INSERT_ACL | DELETE_ACL,
- tables->db,&tables->grant.privilege))
+ case SQLCOM_INSERT:
+ {
+ my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0);
+ ulong privilege= (lex->duplicates == DUP_REPLACE ?
+ INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
+ if (check_access(thd,privilege,tables->db,&tables->grant.privilege))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,INSERT_ACL | DELETE_ACL,
- tables))
-
+ if (grant_option && check_grant(thd,privilege,tables))
goto error;
+ if (select_lex->item_list.elements != lex->value_list.elements)
+ {
+ send_error(thd,ER_WRONG_VALUE_COUNT);
+ DBUG_VOID_RETURN;
+ }
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- DUP_REPLACE);
+ select_lex->item_list, lex->value_list,
+ (update ? DUP_UPDATE : lex->duplicates));
+ if (thd->net.report_error)
+ res= -1;
break;
+ }
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
@@ -1909,8 +2246,8 @@ mysql_execute_command(void)
select privileges for the rest
*/
{
- ulong privilege= (lex->sql_command == SQLCOM_INSERT_SELECT ?
- INSERT_ACL : INSERT_ACL | DELETE_ACL);
+ ulong privilege= (lex->duplicates == DUP_REPLACE ?
+ INSERT_ACL | DELETE_ACL : INSERT_ACL);
TABLE_LIST *save_next=tables->next;
tables->next=0;
if (check_access(thd, privilege,
@@ -1923,22 +2260,16 @@ mysql_execute_command(void)
}
select_result *result;
- thd->offset_limit=select_lex->offset_limit;
- thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
- if (thd->select_limit < select_lex->select_limit)
- thd->select_limit= HA_POS_ERROR; // No limit
+ unit->offset_limit_cnt= select_lex->offset_limit;
+ unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit;
+ if (unit->select_limit_cnt < select_lex->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR; // No limit
- if (check_dup(tables->db, tables->real_name, tables->next))
+ if (find_real_table_in_list(tables->next, tables->db, tables->real_name))
{
- net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
+ net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
- {
- /* TODO: Delete the following loop when locks is set by sql_yacc */
- TABLE_LIST *table;
- for (table = tables->next ; table ; table=table->next)
- table->lock_type= lex->lock_option;
- }
/* Skip first table, which is the table we are inserting in */
lex->select_lex.table_list.first=
@@ -1948,6 +2279,8 @@ mysql_execute_command(void)
if ((result=new select_insert(tables->table,&lex->field_list,
lex->duplicates)))
res=handle_select(thd,lex,result);
+ if (thd->net.report_error)
+ res= -1;
}
else
res= -1;
@@ -1962,7 +2295,7 @@ mysql_execute_command(void)
*/
if (thd->locked_tables || thd->active_transaction())
{
- send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS);
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS);
goto error;
}
res=mysql_truncate(thd,tables);
@@ -1978,6 +2311,8 @@ mysql_execute_command(void)
res = mysql_delete(thd,tables, select_lex->where,
(ORDER*) select_lex->order_list.first,
select_lex->select_limit, select_lex->options);
+ if (thd->net.report_error)
+ res= -1;
break;
}
case SQLCOM_DELETE_MULTI:
@@ -1989,12 +2324,12 @@ mysql_execute_command(void)
/* sql_yacc guarantees that tables and aux_tables are not zero */
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
- check_table_access(thd,SELECT_ACL, tables) ||
+ check_table_access(thd,SELECT_ACL, tables) ||
check_table_access(thd,DELETE_ACL, aux_tables))
goto error;
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
- {
- send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
+ {
+ send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
goto error;
}
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
@@ -2010,36 +2345,52 @@ mysql_execute_command(void)
}
if (!walk)
{
- net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name);
+ net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name);
goto error;
}
walk->lock_type= auxi->lock_type;
- // Store address to table as we need it later
- auxi->table= my_reinterpret_cast(TABLE *) (walk);
+ auxi->table_list= walk; // Remember corresponding table
}
- if (add_item_to_list(new Item_null()))
+ if (add_item_to_list(thd, new Item_null()))
{
res= -1;
break;
}
- tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
thd->proc_info="init";
if ((res=open_and_lock_tables(thd,tables)))
break;
/* Fix tables-to-be-deleted-from list to point at opened tables */
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
- auxi->table= (my_reinterpret_cast(TABLE_LIST*) (auxi->table))->table;
-
- if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
- table_count)))
- {
- res=mysql_select(thd,tables,select_lex->item_list,
- select_lex->where,
- (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
- (ORDER *)NULL,
- select_lex->options | thd->options |
- SELECT_NO_JOIN_CACHE,
- result);
+ auxi->table= auxi->table_list->table;
+ if (&lex->select_lex != lex->all_selects_list)
+ {
+ for (TABLE_LIST *t= select_lex->get_table_list();
+ t; t= t->next)
+ {
+ if (find_real_table_in_list(t->table_list->next, t->db, t->real_name))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name);
+ res= -1;
+ break;
+ }
+ }
+ }
+ fix_tables_pointers(lex->all_selects_list);
+ if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
+ table_count)))
+ {
+ res= mysql_select(thd, &select_lex->ref_pointer_array,
+ select_lex->get_table_list(),
+ select_lex->with_wild,
+ select_lex->item_list,
+ select_lex->where,
+ 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
+ (ORDER *)NULL,
+ select_lex->options | thd->options |
+ SELECT_NO_JOIN_CACHE,
+ result, unit, select_lex, 0, 0);
+ if (thd->net.report_error)
+ res= -1;
delete result;
}
else
@@ -2049,12 +2400,17 @@ mysql_execute_command(void)
}
case SQLCOM_DROP_TABLE:
{
- if (check_table_access(thd,DROP_ACL,tables))
- goto error; /* purecov: inspected */
- if (end_active_trans(thd))
- res= -1;
- else
- res = mysql_rm_table(thd,tables,lex->drop_if_exists);
+ if (!lex->drop_temporary)
+ {
+ if (check_table_access(thd,DROP_ACL,tables))
+ goto error; /* purecov: inspected */
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
+ }
+ res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
}
break;
case SQLCOM_DROP_INDEX:
@@ -2071,7 +2427,7 @@ mysql_execute_command(void)
break;
case SQLCOM_SHOW_DATABASES:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
@@ -2086,6 +2442,15 @@ mysql_execute_command(void)
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
thd->priv_user,lex->verbose);
break;
+ case SQLCOM_SHOW_TABLE_TYPES:
+ res= mysqld_show_table_types(thd);
+ break;
+ case SQLCOM_SHOW_PRIVILEGES:
+ res= mysqld_show_privileges(thd);
+ break;
+ case SQLCOM_SHOW_COLUMN_TYPES:
+ res= mysqld_show_column_types(thd);
+ break;
case SQLCOM_SHOW_STATUS:
res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars,
OPT_GLOBAL);
@@ -2095,27 +2460,34 @@ mysql_execute_command(void)
init_vars, lex->option_type);
break;
case SQLCOM_SHOW_LOGS:
- {
- res= mysqld_show_logs(thd);
- break;
- }
+#ifdef DONT_ALLOW_SHOW_COMMANDS
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ DBUG_VOID_RETURN;
+#else
+ {
+ if (grant_option && check_access(thd, FILE_ACL, any_db))
+ goto error;
+ res= mysqld_show_logs(thd);
+ break;
+ }
+#endif
case SQLCOM_SHOW_TABLES:
/* FALL THROUGH */
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
char *db=select_lex->db ? select_lex->db : thd->db;
if (!db)
{
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
goto error; /* purecov: inspected */
}
remove_escape(db); // Fix escaped '_'
if (check_db_name(db))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, db);
+ net_printf(thd,ER_WRONG_DB_NAME, db);
goto error;
}
if (check_access(thd,SELECT_ACL,db,&thd->col_access))
@@ -2133,16 +2505,19 @@ mysql_execute_command(void)
case SQLCOM_SHOW_OPEN_TABLES:
res= mysqld_show_open_tables(thd,(lex->wild ? lex->wild->ptr() : NullS));
break;
+ case SQLCOM_SHOW_CHARSETS:
+ res= mysqld_show_charsets(thd,(lex->wild ? lex->wild->ptr() : NullS));
+ break;
case SQLCOM_SHOW_FIELDS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
char *db=tables->db;
if (!*db)
{
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
goto error; /* purecov: inspected */
}
remove_escape(db); // Fix escaped '_'
@@ -2160,14 +2535,14 @@ mysql_execute_command(void)
#endif
case SQLCOM_SHOW_KEYS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
char *db=tables->db;
if (!db)
{
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
goto error; /* purecov: inspected */
}
remove_escape(db); // Fix escaped '_'
@@ -2186,10 +2561,11 @@ mysql_execute_command(void)
case SQLCOM_CHANGE_DB:
mysql_change_db(thd,select_lex->db);
break;
+#ifndef EMBEDDED_LIBRARY
case SQLCOM_LOAD:
{
uint privilege= (lex->duplicates == DUP_REPLACE ?
- INSERT_ACL | UPDATE_ACL | DELETE_ACL : INSERT_ACL);
+ INSERT_ACL | DELETE_ACL : INSERT_ACL);
if (!lex->local_file)
{
@@ -2201,7 +2577,7 @@ mysql_execute_command(void)
if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
! opt_local_infile)
{
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND);
+ send_error(thd,ER_NOT_ALLOWED_COMMAND);
goto error;
}
if (check_access(thd,privilege,tables->db,&tables->grant.privilege) ||
@@ -2212,10 +2588,18 @@ mysql_execute_command(void)
lex->duplicates, (bool) lex->local_file, lex->lock_option);
break;
}
+#endif /* EMBEDDED_LIBRARY */
case SQLCOM_SET_OPTION:
- if (!(res=sql_set_variables(thd, &lex->var_list)))
- send_ok(&thd->net);
+ if (tables && ((res= check_table_access(thd, SELECT_ACL, tables)) ||
+ (res= open_and_lock_tables(thd,tables))))
+ break;
+ fix_tables_pointers(lex->all_selects_list);
+ if (!(res= sql_set_variables(thd, &lex->var_list)))
+ send_ok(thd);
+ if (thd->net.report_error)
+ res= -1;
break;
+
case SQLCOM_UNLOCK_TABLES:
unlock_locked_tables(thd);
if (thd->options & OPTION_TABLE_LOCK)
@@ -2225,7 +2609,7 @@ mysql_execute_command(void)
}
if (thd->global_read_lock)
unlock_global_read_lock(thd);
- send_ok(&thd->net);
+ send_ok(thd);
break;
case SQLCOM_LOCK_TABLES:
unlock_locked_tables(thd);
@@ -2239,7 +2623,7 @@ mysql_execute_command(void)
{
thd->locked_tables=thd->lock;
thd->lock=0;
- send_ok(&thd->net);
+ send_ok(thd);
}
else
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
@@ -2249,7 +2633,7 @@ mysql_execute_command(void)
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
+ net_printf(thd,ER_WRONG_DB_NAME, lex->name);
break;
}
/*
@@ -2259,21 +2643,22 @@ mysql_execute_command(void)
do_db/ignore_db. And as this query involves no tables, tables_ok()
above was not called. So we have to check rules again here.
*/
+#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
break;
-
+#endif
if (check_access(thd,CREATE_ACL,lex->name,0,1))
break;
- res=mysql_create_db(thd,lex->name,lex->create_info.options,0);
+ res=mysql_create_db(thd,lex->name,&lex->create_info,0);
break;
}
case SQLCOM_DROP_DB:
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
+ net_printf(thd,ER_WRONG_DB_NAME, lex->name);
break;
}
/*
@@ -2283,26 +2668,62 @@ mysql_execute_command(void)
do_db/ignore_db. And as this query involves no tables, tables_ok()
above was not called. So we have to check rules again here.
*/
+#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
break;
+#endif
if (check_access(thd,DROP_ACL,lex->name,0,1))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
goto error;
}
res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0);
break;
}
+ case SQLCOM_ALTER_DB:
+ {
+ if (!strip_sp(lex->name) || check_db_name(lex->name))
+ {
+ net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ break;
+ }
+ if (check_access(thd,ALTER_ACL,lex->name,0,1))
+ break;
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ goto error;
+ }
+ res=mysql_alter_db(thd,lex->name,&lex->create_info);
+ break;
+ }
+ case SQLCOM_SHOW_CREATE_DB:
+ {
+ if (!strip_sp(lex->name) || check_db_name(lex->name))
+ {
+ net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ break;
+ }
+ if (check_access(thd,DROP_ACL,lex->name,0,1))
+ break;
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ goto error;
+ }
+ res=mysqld_show_create_db(thd,lex->name,&lex->create_info);
+ break;
+ }
case SQLCOM_CREATE_FUNCTION:
if (check_access(thd,INSERT_ACL,"mysql",0,1))
break;
#ifdef HAVE_DLOPEN
if (!(res = mysql_create_function(thd,&lex->udf)))
- send_ok(&thd->net);
+ send_ok(thd);
#else
res= -1;
#endif
@@ -2311,8 +2732,8 @@ mysql_execute_command(void)
if (check_access(thd,DELETE_ACL,"mysql",0,1))
break;
#ifdef HAVE_DLOPEN
- if (!(res = mysql_drop_function(thd,lex->udf.name)))
- send_ok(&thd->net);
+ if (!(res = mysql_drop_function(thd,&lex->udf.name)))
+ send_ok(thd);
#else
res= -1;
#endif
@@ -2340,7 +2761,8 @@ mysql_execute_command(void)
if (user->password.str &&
(strcmp(thd->user,user->user.str) ||
user->host.str &&
- my_strcasecmp(user->host.str, thd->host_or_ip)))
+ my_strcasecmp(&my_charset_latin1,
+ user->host.str, thd->host_or_ip)))
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1))
goto error;
@@ -2371,7 +2793,7 @@ mysql_execute_command(void)
{
if (lex->columns.elements)
{
- send_error(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(thd,ER_ILLEGAL_GRANT_FOR_TABLE);
res=1;
}
else
@@ -2451,7 +2873,7 @@ mysql_execute_command(void)
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
- send_ok(&thd->net);
+ send_ok(thd);
}
break;
case SQLCOM_COMMIT:
@@ -2465,7 +2887,7 @@ mysql_execute_command(void)
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_commit(thd))
{
- send_ok(&thd->net);
+ send_ok(thd);
}
else
res= -1;
@@ -2476,21 +2898,21 @@ mysql_execute_command(void)
if (!ha_rollback(thd))
{
if (thd->options & OPTION_STATUS_NO_TRANS_UPDATE)
- send_warning(&thd->net,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
+ send_warning(thd,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
else
- send_ok(&thd->net);
+ send_ok(thd);
}
else
res= -1;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
break;
default: /* Impossible */
- send_ok(&thd->net);
+ send_ok(thd);
break;
}
thd->proc_info="query end"; // QQ
if (res < 0)
- send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
error:
DBUG_VOID_RETURN;
@@ -2523,7 +2945,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{
if (!no_errors)
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -2536,7 +2958,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
! db && dont_check_global_grants)
{ // We can never grant this
if (!no_errors)
- net_printf(&thd->net,ER_ACCESS_DENIED_ERROR,
+ net_printf(thd,ER_ACCESS_DENIED_ERROR,
thd->priv_user,
thd->host_or_ip,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
@@ -2561,7 +2983,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
!(want_access & ~TABLE_ACLS)))
DBUG_RETURN(FALSE); /* Ok */
if (!no_errors)
- net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
+ net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
thd->host_or_ip,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
@@ -2577,7 +2999,7 @@ bool check_global_access(THD *thd, ulong want_access)
if ((thd->master_access & want_access) == want_access)
return 0;
get_privilege_desc(command, sizeof(command), want_access);
- net_printf(&thd->net,ER_SPECIFIC_ACCESS_DENIED_ERROR,
+ net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
command);
return 1;
}
@@ -2597,6 +3019,8 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
TABLE_LIST *org_tables=tables;
for (; tables ; tables=tables->next)
{
+ if (tables->derived || (tables->table && (int)tables->table->tmp_table))
+ continue;
if ((thd->master_access & want_access) == (want_access & ~EXTRA_ACL) &&
thd->db)
tables->grant.privilege= want_access;
@@ -2632,7 +3056,7 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
if (!(tables->db=thd->db))
{
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
return TRUE; /* purecov: tested */
}
}
@@ -2655,7 +3079,7 @@ static bool check_merge_table_access(THD *thd, char *db,
tmp->db=db;
else if (strcmp(tmp->db,db))
{
- send_error(&thd->net,ER_UNION_TABLES_IN_DIFFERENT_DIR);
+ send_error(thd,ER_UNION_TABLES_IN_DIFFERENT_DIR);
return 1;
}
}
@@ -2684,7 +3108,7 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
{
sprintf(errbuff[0],ER(ER_STACK_OVERRUN),stack_used,thread_stack);
my_message(ER_STACK_OVERRUN,errbuff[0],MYF(0));
- thd->fatal_error=1;
+ thd->fatal_error();
return 1;
}
return 0;
@@ -2723,111 +3147,175 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
/****************************************************************************
- Initialize global thd variables needed for query
+ Initialize global thd variables needed for query
****************************************************************************/
-static void
+void
mysql_init_query(THD *thd)
{
DBUG_ENTER("mysql_init_query");
- thd->lex.select_lex.item_list.empty();
- thd->lex.value_list.empty();
- thd->lex.select_lex.table_list.elements=0;
- thd->free_list=0; thd->lex.union_option=0;
- thd->lex.select = &thd->lex.select_lex;
- thd->lex.select_lex.table_list.first=0;
- thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first;
- thd->lex.select_lex.next=0;
- thd->lex.olap=0;
- thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE;
- thd->fatal_error=0; // Safety
- thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
- thd->rand_used=0;
- thd->sent_row_count=thd->examined_row_count=0;
- thd->safe_to_cache_query=1;
+ LEX *lex=&thd->lex;
+ lex->unit.init_query();
+ lex->unit.init_select();
+ lex->unit.thd= thd;
+ lex->select_lex.init_query();
+ lex->value_list.empty();
+ lex->param_list.empty();
+ lex->unit.next= lex->unit.master= lex->unit.link_next= 0;
+ lex->unit.prev= lex->unit.link_prev= 0;
+ lex->unit.global_parameters= lex->unit.slave= lex->current_select=
+ lex->all_selects_list= &lex->select_lex;
+ lex->select_lex.master= &lex->unit;
+ lex->select_lex.prev= &lex->unit.slave;
+ lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
+ lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
+ lex->describe= 0;
+ lex->derived_tables= FALSE;
+ lex->lock_option= TL_READ;
+ lex->found_colon= 0;
+ lex->safe_to_cache_query= 1;
+ thd->select_number= lex->select_lex.select_number= 1;
+ thd->free_list= 0;
+ thd->total_warn_count=0; // Warnings for this query
+ thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
+ thd->sent_row_count= thd->examined_row_count= 0;
+ thd->is_fatal_error= thd->rand_used= 0;
+ thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ thd->tmp_table_used= 0;
+ if (opt_bin_log)
+ reset_dynamic(&thd->user_var_events);
+ thd->clear_error();
DBUG_VOID_RETURN;
}
+
void
mysql_init_select(LEX *lex)
{
- SELECT_LEX *select_lex = lex->select;
- select_lex->where=select_lex->having=0;
- select_lex->select_limit= lex->thd->variables.select_limit;
- select_lex->offset_limit=0;
- select_lex->options=0;
- select_lex->linkage=UNSPECIFIED_TYPE;
- select_lex->olap= UNSPECIFIED_OLAP_TYPE;
- lex->exchange = 0;
- lex->proc_list.first=0;
- select_lex->order_list.empty();
- select_lex->group_list.empty();
- select_lex->next = (SELECT_LEX *)NULL;
+ SELECT_LEX *select_lex= lex->current_select->select_lex();
+ select_lex->init_select();
+ select_lex->master_unit()->select_limit= select_lex->select_limit=
+ lex->thd->variables.select_limit;
+ if (select_lex == &lex->select_lex)
+ {
+ lex->exchange= 0;
+ lex->result= 0;
+ lex->proc_list.first= 0;
+ }
}
bool
-mysql_new_select(LEX *lex)
+mysql_new_select(LEX *lex, bool move_down)
{
- SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
+ SELECT_LEX *select_lex = new SELECT_LEX();
+ select_lex->select_number= ++lex->thd->select_number;
if (!select_lex)
return 1;
- lex->select->next=select_lex;
- lex->select=select_lex;
- select_lex->table_list.next= (byte**) &select_lex->table_list.first;
- select_lex->item_list.empty();
- select_lex->when_list.empty();
- select_lex->expr_list.empty();
- select_lex->interval_list.empty();
- select_lex->use_index.empty();
- select_lex->ftfunc_list.empty();
+ select_lex->init_query();
+ select_lex->init_select();
+ if (move_down)
+ {
+ /* first select_lex of subselect or derived table */
+ SELECT_LEX_UNIT *unit= new SELECT_LEX_UNIT();
+ if (!unit)
+ return 1;
+ unit->init_query();
+ unit->init_select();
+ unit->thd= lex->thd;
+ unit->include_down(lex->current_select);
+ unit->link_next= 0;
+ unit->link_prev= 0;
+ select_lex->include_down(unit);
+ }
+ else
+ select_lex->include_neighbour(lex->current_select);
+
+ select_lex->master_unit()->global_parameters= select_lex;
+ DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
+ select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
+ lex->current_select= select_lex;
return 0;
}
+/*
+ Create a select to return the same output as 'SELECT @@var_name'.
+
+ SYNOPSIS
+ create_select_for_variable()
+ var_name Variable name
+
+ DESCRIPTION
+ Used for SHOW COUNT(*) [ WARNINGS | ERROR]
+
+ This will crash with a core dump if the variable doesn't exists
+*/
+
+void create_select_for_variable(const char *var_name)
+{
+ LEX *lex;
+ LEX_STRING tmp;
+ DBUG_ENTER("create_select_for_variable");
+ lex= current_lex;
+ mysql_init_select(lex);
+ lex->sql_command= SQLCOM_SELECT;
+ tmp.str= (char*) var_name;
+ tmp.length=strlen(var_name);
+ add_item_to_list(lex->thd, get_system_var(OPT_SESSION, tmp));
+ DBUG_VOID_RETURN;
+}
+
void mysql_init_multi_delete(LEX *lex)
{
- lex->sql_command = SQLCOM_DELETE_MULTI;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
- lex->select->select_limit=lex->thd->select_limit=HA_POS_ERROR;
- lex->auxilliary_table_list=lex->select_lex.table_list;
- lex->select->table_list.elements=0;
- lex->select->table_list.first=0;
- lex->select->table_list.next= (byte**) &(lex->select->table_list.first);
+ lex->select_lex.select_limit= lex->unit.select_limit_cnt=
+ HA_POS_ERROR;
+ lex->auxilliary_table_list= lex->select_lex.table_list;
+ lex->select_lex.init_query();
}
void
-mysql_parse(THD *thd,char *inBuf,uint length)
+mysql_parse(THD *thd, char *inBuf, uint length)
{
DBUG_ENTER("mysql_parse");
mysql_init_query(thd);
- thd->query_length = length;
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
- if (!yyparse() && ! thd->fatal_error)
+ if (!yyparse((void *)thd) && ! thd->is_fatal_error)
{
if (mqh_used && thd->user_connect &&
- check_mqh(thd, thd->lex.sql_command))
+ check_mqh(thd, lex->sql_command))
{
thd->net.error = 0;
}
else
{
- mysql_execute_command();
- query_cache_end_of_result(&thd->net);
+ if (thd->net.report_error)
+ send_error(thd, 0, NullS);
+ else
+ {
+ mysql_execute_command(thd);
+#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
+ query_cache_end_of_result(&thd->net);
+#endif
+ }
}
}
else
{
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
- thd->fatal_error));
+ thd->is_fatal_error));
+#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_abort(&thd->net);
+#endif
}
thd->proc_info="freeing items";
- free_items(thd); /* Free strings used by items */
+ free_items(thd->free_list); /* Free strings used by items */
lex_end(lex);
}
DBUG_VOID_RETURN;
@@ -2839,33 +3327,34 @@ mysql_parse(THD *thd,char *inBuf,uint length)
** Return 0 if ok
******************************************************************************/
-bool add_field_to_list(char *field_name, enum_field_types type,
+bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
- uint type_modifier, Item *default_value,char *change,
- TYPELIB *interval)
+ uint type_modifier,
+ Item *default_value, Item *comment,
+ char *change, TYPELIB *interval, CHARSET_INFO *cs)
{
register create_field *new_field;
- THD *thd=current_thd;
LEX *lex= &thd->lex;
uint allowed_type_modifier=0;
+ char warn_buff[MYSQL_ERRMSG_SIZE];
DBUG_ENTER("add_field_to_list");
if (strlen(field_name) > NAME_LEN)
{
- net_printf(&thd->net, ER_TOO_LONG_IDENT, field_name); /* purecov: inspected */
+ net_printf(thd, ER_TOO_LONG_IDENT, field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if (type_modifier & PRI_KEY_FLAG)
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::PRIMARY,NullS,
+ lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
lex->col_list));
lex->col_list.empty();
}
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::UNIQUE,NullS,
+ lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF,
lex->col_list));
lex->col_list.empty();
}
@@ -2875,7 +3364,7 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
NOT_NULL_FLAG)
{
- net_printf(&thd->net,ER_INVALID_DEFAULT,field_name);
+ net_printf(thd,ER_INVALID_DEFAULT,field_name);
DBUG_RETURN(1);
}
default_value=0;
@@ -2895,6 +3384,19 @@ bool add_field_to_list(char *field_name, enum_field_types type,
new_field->change=change;
new_field->interval=0;
new_field->pack_length=0;
+ new_field->charset=cs;
+
+ if (!comment)
+ {
+ new_field->comment.str=0;
+ new_field->comment.length=0;
+ }
+ else
+ {
+ /* In this case comment is always of type Item_string */
+ new_field->comment.str= (char*) comment->str_value.ptr();
+ new_field->comment.length=comment->str_value.length();
+ }
if (length)
if (!(new_field->length= (uint) atoi(length)))
length=0; /* purecov: inspected */
@@ -2926,10 +3428,7 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (!length) new_field->length=20;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_NULL:
- case FIELD_TYPE_GEOMETRY:
break;
case FIELD_TYPE_DECIMAL:
if (!length)
@@ -2938,17 +3437,43 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (new_field->decimals)
new_field->length++;
break;
+ case FIELD_TYPE_STRING:
+ case FIELD_TYPE_VAR_STRING:
+ if (new_field->length < MAX_FIELD_WIDTH || default_value)
+ break;
+ /* Convert long CHAR() and VARCHAR columns to TEXT or BLOB */
+ new_field->sql_type= FIELD_TYPE_BLOB;
+ sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR",
+ (cs == &my_charset_bin) ? "BLOB" : "TEXT");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_AUTO_CONVERT,
+ warn_buff);
+ /* fall through */
case FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_GEOMETRY:
+ if (new_field->length)
+ {
+ /* The user has given a length to the blob column */
+ if (new_field->length < 256)
+ type= FIELD_TYPE_TINY_BLOB;
+ if (new_field->length < 65536)
+ type= FIELD_TYPE_BLOB;
+ else if (new_field->length < 256L*256L*256L)
+ type= FIELD_TYPE_MEDIUM_BLOB;
+ else
+ type= FIELD_TYPE_LONG_BLOB;
+ new_field->length= 0;
+ }
+ new_field->sql_type= type;
if (default_value) // Allow empty as default value
{
String str,*res;
res=default_value->val_str(&str);
if (res->length())
{
- net_printf(&thd->net,ER_BLOB_CANT_HAVE_DEFAULT,field_name); /* purecov: inspected */
+ net_printf(thd,ER_BLOB_CANT_HAVE_DEFAULT,field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
new_field->def=0;
@@ -2968,7 +3493,7 @@ bool add_field_to_list(char *field_name, enum_field_types type,
uint tmp_length=new_field->length;
if (tmp_length > PRECISION_FOR_DOUBLE)
{
- net_printf(&thd->net,ER_WRONG_FIELD_SPEC,field_name);
+ net_printf(thd,ER_WRONG_FIELD_SPEC,field_name);
DBUG_RETURN(1);
}
else if (tmp_length > PRECISION_FOR_FLOAT)
@@ -3022,7 +3547,7 @@ bool add_field_to_list(char *field_name, enum_field_types type,
{
if (interval->count > sizeof(longlong)*8)
{
- net_printf(&thd->net,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
+ net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
new_field->pack_length=(interval->count+7)/8;
@@ -3038,13 +3563,17 @@ bool add_field_to_list(char *field_name, enum_field_types type,
set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
if (default_value)
{
+ char *not_used;
+ uint not_used2;
+
thd->cuted_fields=0;
String str,*res;
res=default_value->val_str(&str);
- (void) find_set(interval,res->ptr(),res->length());
+ (void) find_set(interval, res->ptr(), res->length(), &not_used,
+ &not_used2);
if (thd->cuted_fields)
{
- net_printf(&thd->net,ER_INVALID_DEFAULT,field_name);
+ net_printf(thd,ER_INVALID_DEFAULT,field_name);
DBUG_RETURN(1);
}
}
@@ -3067,7 +3596,7 @@ bool add_field_to_list(char *field_name, enum_field_types type,
res=default_value->val_str(&str);
if (!find_enum(interval,res->ptr(),res->length()))
{
- net_printf(&thd->net,ER_INVALID_DEFAULT,field_name);
+ net_printf(thd,ER_INVALID_DEFAULT,field_name);
DBUG_RETURN(1);
}
}
@@ -3077,16 +3606,17 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (new_field->length >= MAX_FIELD_WIDTH ||
(!new_field->length && !(new_field->flags & BLOB_FLAG) &&
- type != FIELD_TYPE_STRING && type != FIELD_TYPE_VAR_STRING))
+ type != FIELD_TYPE_STRING &&
+ type != FIELD_TYPE_VAR_STRING && type != FIELD_TYPE_GEOMETRY))
{
- net_printf(&thd->net,ER_TOO_BIG_FIELDLENGTH,field_name,
+ net_printf(thd,ER_TOO_BIG_FIELDLENGTH,field_name,
MAX_FIELD_WIDTH-1); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier)
{
- net_printf(&thd->net,ER_WRONG_FIELD_SPEC,field_name);
+ net_printf(thd,ER_WRONG_FIELD_SPEC,field_name);
DBUG_RETURN(1);
}
if (!new_field->pack_length)
@@ -3113,7 +3643,7 @@ add_proc_to_list(THD* thd, Item *item)
ORDER *order;
Item **item_ptr;
- if (!(order = (ORDER *) sql_alloc(sizeof(ORDER)+sizeof(Item*))))
+ if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*))))
return 1;
item_ptr = (Item**) (order+1);
*item_ptr= item;
@@ -3139,8 +3669,8 @@ static void remove_escape(char *name)
#ifdef USE_MB
int l;
/* if ((l = ismbchar(name, name+MBMAXLEN))) { Wei He: I think it's wrong */
- if (use_mb(default_charset_info) &&
- (l = my_ismbchar(default_charset_info, name, strend)))
+ if (use_mb(system_charset_info) &&
+ (l = my_ismbchar(system_charset_info, name, strend)))
{
while (l--)
*to++ = *name++;
@@ -3160,12 +3690,12 @@ static void remove_escape(char *name)
****************************************************************************/
-bool add_to_list(SQL_LIST &list,Item *item,bool asc)
+bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
{
ORDER *order;
Item **item_ptr;
DBUG_ENTER("add_to_list");
- if (!(order = (ORDER *) sql_alloc(sizeof(ORDER)+sizeof(Item*))))
+ if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*))))
DBUG_RETURN(1);
item_ptr = (Item**) (order+1);
*item_ptr=item;
@@ -3197,14 +3727,15 @@ bool add_to_list(SQL_LIST &list,Item *item,bool asc)
# Pointer to TABLE_LIST element added to the total table list
*/
-TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
- ulong table_options,
- thr_lock_type lock_type,
- List<String> *use_index,
- List<String> *ignore_index)
+TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
+ Table_ident *table,
+ LEX_STRING *alias,
+ ulong table_options,
+ thr_lock_type lock_type,
+ List<String> *use_index,
+ List<String> *ignore_index)
{
register TABLE_LIST *ptr;
- THD *thd=current_thd;
char *alias_str;
DBUG_ENTER("add_table_to_list");
@@ -3212,20 +3743,27 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
DBUG_RETURN(0); // End of memory
alias_str= alias ? alias->str : table->table.str;
if (table->table.length > NAME_LEN ||
- check_table_name(table->table.str,table->table.length) ||
+ (table->table.length &&
+ check_table_name(table->table.str,table->table.length)) ||
table->db.str && check_db_name(table->db.str))
{
- net_printf(&thd->net,ER_WRONG_TABLE_NAME,table->table.str);
+ net_printf(thd,ER_WRONG_TABLE_NAME,table->table.str);
DBUG_RETURN(0);
}
if (!alias) /* Alias is case sensitive */
+ {
+ if (table->sel)
+ {
+ net_printf(thd,ER_DERIVED_MUST_HAVE_ALIAS);
+ DBUG_RETURN(0);
+ }
if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
DBUG_RETURN(0);
-
+ }
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(0); /* purecov: inspected */
- if (table->db.str)
+ if (table->db.str)
{
ptr->db= table->db.str;
ptr->db_length= table->db.length;
@@ -3237,18 +3775,20 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
}
else
{
- ptr->db= (char*) "";
+ /* The following can't be "" as we may do 'casedn_str()' on it */
+ ptr->db= empty_c_string;
ptr->db_length= 0;
}
-
+
ptr->alias= alias_str;
if (lower_case_table_names)
- casedn_str(table->table.str);
+ my_casedn_str(files_charset_info,table->table.str);
ptr->real_name=table->table.str;
ptr->real_name_length=table->table.length;
- ptr->lock_type= lock_type;
+ ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
+ ptr->derived= table->sel;
if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
sizeof(*use_index));
@@ -3259,21 +3799,22 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
/* check that used name is unique */
if (lock_type != TL_IGNORE)
{
- for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ;
+ for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
tables ;
tables=tables->next)
{
if (!strcmp(alias_str,tables->alias) && !strcmp(ptr->db, tables->db))
{
- net_printf(&thd->net,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */
+ net_printf(thd,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
}
}
}
- thd->lex.select->table_list.link_in_list((byte*) ptr,(byte**) &ptr->next);
+ table_list.link_in_list((byte*) ptr, (byte**) &ptr->next);
DBUG_RETURN(ptr);
}
+
/*
Set lock for all tables in current select level
@@ -3287,15 +3828,14 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
query
*/
-void set_lock_for_tables(thr_lock_type lock_type)
+void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
{
- THD *thd=current_thd;
bool for_update= lock_type >= TL_READ_NO_INSERT;
DBUG_ENTER("set_lock_for_tables");
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
for_update));
- for (TABLE_LIST *tables= (TABLE_LIST*) thd->lex.select->table_list.first ;
+ for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first ;
tables ;
tables=tables->next)
{
@@ -3306,68 +3846,6 @@ void set_lock_for_tables(thr_lock_type lock_type)
}
-/*
-** This is used for UNION to create a new table list of all used tables
-** The table_list->table entry in all used tables are set to point
-** to the entries in this list.
-*/
-
-static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
-{
- /* Handle the case when we are not using union */
- if (!lex->select_lex.next)
- {
- *result= (TABLE_LIST*) lex->select_lex.table_list.first;
- return 0;
- }
-
- SELECT_LEX *sl;
- TABLE_LIST **new_table_list= result, *aux;
-
- *new_table_list=0; // end result list
- for (sl= &lex->select_lex; sl; sl=sl->next)
- {
- if (sl->order_list.first && sl->next && !sl->braces)
- {
- net_printf(&thd->net,ER_WRONG_USAGE,"UNION","ORDER BY");
- return 1;
- }
- if ((aux= (TABLE_LIST*) sl->table_list.first))
- {
- TABLE_LIST *next;
- for (; aux; aux=next)
- {
- TABLE_LIST *cursor;
- aux->do_redirect=true;
- next= aux->next;
- for (cursor= *result; cursor; cursor=cursor->next)
- if (!strcmp(cursor->db,aux->db) &&
- !strcmp(cursor->real_name,aux->real_name) &&
- !strcmp(cursor->alias, aux->alias))
- break;
- if (!cursor)
- {
- /* Add not used table to the total table list */
- if (!(cursor = (TABLE_LIST *) thd->memdup((char*) aux,
- sizeof(*aux))))
- {
- send_error(&thd->net,0);
- return 1;
- }
- *new_table_list= cursor;
- new_table_list= &cursor->next;
- *new_table_list=0; // end result list
- }
- else
- aux->shared=1; // Mark that it's used twice
- aux->table= my_reinterpret_cast(TABLE *) (cursor);
- }
- }
- }
- return 0;
-}
-
-
void add_join_on(TABLE_LIST *b,Item *expr)
{
if (expr)
@@ -3389,16 +3867,6 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
b->natural_join=a;
}
- /* Check if name is used in table list */
-
-static bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
-{
- for (; tables ; tables=tables->next)
- if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db))
- return 1;
- return 0;
-}
-
/*
Reload/resets privileges and the different caches
@@ -3453,9 +3921,11 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
refresh_status();
if (options & REFRESH_THREADS)
flush_thread_cache();
+#ifndef EMBEDDED_LIBRARY
if (options & REFRESH_MASTER)
if (reset_master(thd))
result=1;
+#endif
#ifdef OPENSSL
if (options & REFRESH_DES_KEY_FILE)
{
@@ -3463,6 +3933,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
result=load_des_key_file(des_key_file);
}
#endif
+#ifndef EMBEDDED_LIBRARY
if (options & REFRESH_SLAVE)
{
LOCK_ACTIVE_MI;
@@ -3479,15 +3950,16 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
}
UNLOCK_ACTIVE_MI;
}
+#endif
if (options & REFRESH_USER_RESOURCES)
reset_mqh(thd,(LEX_USER *) NULL);
if (thd && !error_already_sent)
{
if (result)
- send_error(&thd->net,0);
+ send_error(thd,0);
else
- send_ok(&thd->net);
+ send_ok(thd);
}
return result;
@@ -3535,9 +4007,9 @@ void kill_one_thread(THD *thd, ulong id)
}
if (!error)
- send_ok(&thd->net);
+ send_ok(thd);
else
- net_printf(&thd->net,error,id);
+ net_printf(thd,error,id);
}
/* Clear most status variables */
@@ -3595,13 +4067,43 @@ static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
bool check_simple_select()
{
THD *thd= current_thd;
- if (thd->lex.select != &thd->lex.select_lex)
+ if (thd->lex.current_select != &thd->lex.select_lex)
{
char command[80];
strmake(command, thd->lex.yylval->symbol.str,
min(thd->lex.yylval->symbol.length, sizeof(command)-1));
- net_printf(&thd->net, ER_CANT_USE_OPTION_HERE, command);
+ net_printf(thd, ER_CANT_USE_OPTION_HERE, command);
return 1;
}
return 0;
}
+
+compare_func_creator comp_eq_creator(bool invert)
+{
+ return invert?&Item_bool_func2::ne_creator:&Item_bool_func2::eq_creator;
+}
+
+compare_func_creator comp_ge_creator(bool invert)
+{
+ return invert?&Item_bool_func2::lt_creator:&Item_bool_func2::ge_creator;
+}
+
+compare_func_creator comp_gt_creator(bool invert)
+{
+ return invert?&Item_bool_func2::le_creator:&Item_bool_func2::gt_creator;
+}
+
+compare_func_creator comp_le_creator(bool invert)
+{
+ return invert?&Item_bool_func2::gt_creator:&Item_bool_func2::le_creator;
+}
+
+compare_func_creator comp_lt_creator(bool invert)
+{
+ return invert?&Item_bool_func2::ge_creator:&Item_bool_func2::lt_creator;
+}
+
+compare_func_creator comp_ne_creator(bool invert)
+{
+ return invert?&Item_bool_func2::eq_creator:&Item_bool_func2::ne_creator;
+}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
new file mode 100644
index 00000000000..3cb4c4e8244
--- /dev/null
+++ b/sql/sql_prepare.cc
@@ -0,0 +1,951 @@
+/* Copyright (C) 1995-2002 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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
+*/
+
+/**********************************************************************
+This file contains the implementation of prepare and executes.
+
+Prepare:
+
+ - Server gets the query from client with command 'COM_PREPARE';
+ in the following format:
+ [COM_PREPARE:1] [query]
+ - Parse the query and recognize any parameter markers '?' and
+ store its information list in lex->param_list
+ - Allocate a new statement for this prepare; and keep this in
+ 'thd->prepared_statements' pool.
+ - Without executing the query, return back to client the total
+ number of parameters along with result-set metadata information
+ (if any) in the following format:
+ [STMT_ID:4]
+ [Column_count:2]
+ [Param_count:2]
+ [Columns meta info] (if Column_count > 0)
+ [Params meta info] (if Param_count > 0 ) (TODO : 4.1.1)
+
+Prepare-execute:
+
+ - Server gets the command 'COM_EXECUTE' to execute the
+ previously prepared query. If there is any param markers; then client
+ will send the data in the following format:
+ [COM_EXECUTE:1]
+ [STMT_ID:4]
+ [NULL_BITS:(param_count+7)/8)]
+ [TYPES_SUPPLIED_BY_CLIENT(0/1):1]
+ [[length]data]
+ [[length]data] .. [[length]data].
+ (Note: Except for string/binary types; all other types will not be
+ supplied with length field)
+ - Replace the param items with this new data. If it is a first execute
+ or types altered by client; then setup the conversion routines.
+ - Execute the query without re-parsing and send back the results
+ to client
+
+Long data handling:
+
+ - Server gets the long data in pieces with command type 'COM_LONG_DATA'.
+ - The packet recieved will have the format as:
+ [COM_LONG_DATA:1][STMT_ID:4][parameter_number:2][type:2][data]
+ - Checks if the type is specified by client, and if yes reads the type,
+ and stores the data in that format.
+ - It's up to the client to check for read data ended. The server doesn't
+ care; and also server doesn't notify to the client that it got the
+ data or not; if there is any error; then during execute; the error
+ will be returned
+
+***********************************************************************/
+
+#include "mysql_priv.h"
+#include "sql_acl.h"
+#include "sql_select.h" // for JOIN
+#include <m_ctype.h> // for isspace()
+
+#define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7)
+
+extern int yyparse(void *thd);
+
+/*
+ Find prepared statement in thd
+
+ SYNOPSIS
+ find_prepared_statement()
+ thd Thread handler
+ stmt_id Statement id server specified to the client on prepare
+
+ RETURN VALUES
+ 0 error. In this case the error is sent with my_error()
+ ptr Pointer to statement
+*/
+
+static PREP_STMT *find_prepared_statement(THD *thd, ulong stmt_id,
+ const char *when)
+{
+ PREP_STMT *stmt;
+ DBUG_ENTER("find_prepared_statement");
+ DBUG_PRINT("enter",("stmt_id: %d", stmt_id));
+
+ if (thd->last_prepared_stmt && thd->last_prepared_stmt->stmt_id == stmt_id)
+ DBUG_RETURN(thd->last_prepared_stmt);
+ if ((stmt= (PREP_STMT*) tree_search(&thd->prepared_statements, &stmt_id,
+ (void*) 0)))
+ DBUG_RETURN (thd->last_prepared_stmt= stmt);
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_id, when);
+ DBUG_RETURN(0);
+}
+
+/*
+ Compare two prepared statements; Used to find a prepared statement
+*/
+
+int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key)
+{
+ return (stmt->stmt_id == *key) ? 0 : (stmt->stmt_id < *key) ? -1 : 1;
+}
+
+
+/*
+ Free prepared statement.
+
+ SYNOPSIS
+ standard tree_element_free function.
+
+ DESCRIPTION
+ We don't have to free the stmt itself as this was stored in the tree
+ and will be freed when the node is deleted
+*/
+
+void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used)
+{
+ my_free((char *)stmt->param, MYF(MY_ALLOW_ZERO_PTR));
+ free_items(stmt->free_list);
+ free_root(&stmt->mem_root, MYF(0));
+}
+
+/*
+ Send prepared stmt info to client after prepare
+*/
+
+static bool send_prep_stmt(PREP_STMT *stmt, uint columns)
+{
+ NET *net=&stmt->thd->net;
+ char buff[8];
+ int4store(buff, stmt->stmt_id);
+ int2store(buff+4, columns);
+ int2store(buff+6, stmt->param_count);
+#ifndef EMBEDDED_LIBRARY
+ /* This should be fixed to work with prepared statements
+ */
+ return (my_net_write(net, buff, sizeof(buff)) || net_flush(net));
+#else
+ return true;
+#endif
+}
+
+/*
+ Send information about all item parameters
+
+ TODO: Not yet ready
+*/
+
+static bool send_item_params(PREP_STMT *stmt)
+{
+#if 0
+ char buff[1];
+ buff[0]=0;
+ if (my_net_write(&stmt->thd->net, buff, sizeof(buff)))
+ return 1;
+ send_eof(stmt->thd);
+#endif
+ return 0;
+}
+
+/*
+ Read the length of the parameter data and retun back to
+ caller by positing the pointer to param data
+*/
+
+static ulong get_param_length(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (ulong) *pos;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (ulong) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (ulong) uint3korr(pos+1);
+ }
+ (*packet)+=9; // Must be 254 when here
+ return (ulong) uint4korr(pos+1);
+}
+ /*
+ Setup param conversion routines
+
+ setup_param_xx()
+ param Parameter Item
+ pos Input data buffer
+
+ All these functions reads the data from pos and sets up that data
+ through 'param' and advances the buffer position to predifined
+ length position.
+
+ Make a note that the NULL handling is examined at first execution
+ (i.e. when input types altered) and for all subsequent executions
+ we don't read any values for this.
+
+ RETURN VALUES
+
+*/
+
+static void setup_param_tiny(Item_param *param, uchar **pos)
+{
+ param->set_int((longlong)(**pos));
+ *pos+= 1;
+}
+
+static void setup_param_short(Item_param *param, uchar **pos)
+{
+ param->set_int((longlong)sint2korr(*pos));
+ *pos+= 2;
+}
+
+static void setup_param_int32(Item_param *param, uchar **pos)
+{
+ param->set_int((longlong)sint4korr(*pos));
+ *pos+= 4;
+}
+
+static void setup_param_int64(Item_param *param, uchar **pos)
+{
+ param->set_int((longlong)sint8korr(*pos));
+ *pos+= 8;
+}
+
+static void setup_param_float(Item_param *param, uchar **pos)
+{
+ float data;
+ float4get(data,*pos);
+ param->set_double((double) data);
+ *pos+= 4;
+}
+
+static void setup_param_double(Item_param *param, uchar **pos)
+{
+ double data;
+ float8get(data,*pos);
+ param->set_double((double) data);
+ *pos+= 8;
+}
+
+static void setup_param_time(Item_param *param, uchar **pos)
+{
+ ulong length;
+
+ if ((length= get_param_length(pos)))
+ {
+ uchar *to= *pos;
+ TIME tm;
+
+ tm.second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
+
+ tm.day= (ulong) sint4korr(to+1);
+ tm.hour= (uint) to[5];
+ tm.minute= (uint) to[6];
+ tm.second= (uint) to[7];
+
+ tm.year= tm.month= 0;
+ tm.neg= (bool)to[0];
+
+ param->set_time(&tm, TIMESTAMP_TIME);
+ }
+ *pos+= length;
+}
+
+static void setup_param_datetime(Item_param *param, uchar **pos)
+{
+ uint length= get_param_length(pos);
+
+ if (length)
+ {
+ uchar *to= *pos;
+ TIME tm;
+
+ tm.second_part= (length > 7 ) ? (ulong) sint4korr(to+7): 0;
+
+ if (length > 4)
+ {
+ tm.hour= (uint) to[4];
+ tm.minute= (uint) to[5];
+ tm.second= (uint) to[6];
+ }
+ else
+ tm.hour= tm.minute= tm.second= 0;
+
+ tm.year= (uint) sint2korr(to);
+ tm.month= (uint) to[2];
+ tm.day= (uint) to[3];
+ tm.neg= 0;
+
+ param->set_time(&tm, TIMESTAMP_FULL);
+ }
+ *pos+= length;
+}
+
+static void setup_param_date(Item_param *param, uchar **pos)
+{
+ ulong length;
+
+ if ((length= get_param_length(pos)))
+ {
+ uchar *to= *pos;
+ TIME tm;
+
+ tm.year= (uint) sint2korr(to);
+ tm.month= (uint) to[2];
+ tm.day= (uint) to[3];
+
+ tm.hour= tm.minute= tm.second= 0;
+ tm.second_part= 0;
+ tm.neg= 0;
+
+ param->set_time(&tm, TIMESTAMP_DATE);
+ }
+ *pos+= length;
+}
+
+static void setup_param_str(Item_param *param, uchar **pos)
+{
+ ulong len= get_param_length(pos);
+ param->set_value((const char *)*pos, len);
+ *pos+= len;
+}
+
+static void setup_param_functions(Item_param *param, uchar param_type)
+{
+ switch (param_type) {
+ case FIELD_TYPE_TINY:
+ param->setup_param_func= setup_param_tiny;
+ param->item_result_type= INT_RESULT;
+ break;
+ case FIELD_TYPE_SHORT:
+ param->setup_param_func= setup_param_short;
+ param->item_result_type= INT_RESULT;
+ break;
+ case FIELD_TYPE_LONG:
+ param->setup_param_func= setup_param_int32;
+ param->item_result_type= INT_RESULT;
+ break;
+ case FIELD_TYPE_LONGLONG:
+ param->setup_param_func= setup_param_int64;
+ param->item_result_type= INT_RESULT;
+ break;
+ case FIELD_TYPE_FLOAT:
+ param->setup_param_func= setup_param_float;
+ param->item_result_type= REAL_RESULT;
+ break;
+ case FIELD_TYPE_DOUBLE:
+ param->setup_param_func= setup_param_double;
+ param->item_result_type= REAL_RESULT;
+ break;
+ case FIELD_TYPE_TIME:
+ param->setup_param_func= setup_param_time;
+ param->item_result_type= STRING_RESULT;
+ break;
+ case FIELD_TYPE_DATE:
+ param->setup_param_func= setup_param_date;
+ param->item_result_type= STRING_RESULT;
+ break;
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_TIMESTAMP:
+ param->setup_param_func= setup_param_datetime;
+ param->item_result_type= STRING_RESULT;
+ break;
+ default:
+ param->setup_param_func= setup_param_str;
+ param->item_result_type= STRING_RESULT;
+ }
+}
+
+/*
+ Update the parameter markers by reading the data
+ from client ..
+*/
+
+static bool setup_params_data(PREP_STMT *stmt)
+{
+ THD *thd= stmt->thd;
+ List<Item> &params= thd->lex.param_list;
+ List_iterator<Item> param_iterator(params);
+ Item_param *param;
+ DBUG_ENTER("setup_params_data");
+
+#ifndef EMBEDDED_LIBRARY
+ uchar *pos=(uchar*) thd->net.read_pos+1+MYSQL_STMT_HEADER; //skip header
+#else
+ uchar *pos= 0; //just to compile TODO code for embedded case
+#endif
+ uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits
+
+ if (*read_pos++) //types supplied / first execute
+ {
+ /*
+ First execute or types altered by the client, setup the
+ conversion routines for all parameters (one time)
+ */
+ while ((param= (Item_param *)param_iterator++))
+ {
+ setup_param_functions(param,*read_pos);
+ read_pos+= 2;
+ }
+ param_iterator.rewind();
+ }
+ ulong param_no= 0;
+ while ((param= (Item_param *)param_iterator++))
+ {
+ if (!param->long_data_supplied)
+ {
+ if (IS_PARAM_NULL(pos,param_no))
+ param->maybe_null= param->null_value= 1;
+ else
+ {
+ param->maybe_null= param->null_value= 0;
+ param->setup_param_func(param,&read_pos);
+ }
+ }
+ param_no++;
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ Validate the following information for INSERT statement:
+ - field existance
+ - fields count
+*/
+
+static bool mysql_test_insert_fields(PREP_STMT *stmt,
+ TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list)
+{
+ THD *thd= stmt->thd;
+ TABLE *table;
+ List_iterator_fast<List_item> its(values_list);
+ List_item *values;
+ DBUG_ENTER("mysql_test_insert_fields");
+
+ if (!(table= open_ltable(thd,table_list,table_list->lock_type)))
+ DBUG_RETURN(1);
+
+ if ((values= its++))
+ {
+ uint value_count;
+ ulong counter= 0;
+
+ if (check_insert_fields(thd,table,fields,*values,1))
+ DBUG_RETURN(1);
+
+ value_count= values->elements;
+ its.rewind();
+
+ while ((values= its++))
+ {
+ counter++;
+ if (values->elements != value_count)
+ {
+ my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
+ ER(ER_WRONG_VALUE_COUNT_ON_ROW),
+ MYF(0), counter);
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ if (send_prep_stmt(stmt, 0) || send_item_params(stmt))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Validate the following information
+ UPDATE - set and where clause DELETE - where clause
+
+ And send update-set clause column list fields info
+ back to client. For DELETE, just validate where clause
+ and return no fields information back to client.
+*/
+
+static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
+ List<Item> &fields, List<Item> &values,
+ COND *conds)
+{
+ THD *thd= stmt->thd;
+ DBUG_ENTER("mysql_test_upd_fields");
+
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(1);
+
+ if (setup_tables(table_list) ||
+ setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
+ setup_conds(thd, table_list, &conds) || thd->net.report_error)
+ DBUG_RETURN(1);
+
+ /*
+ Currently return only column list info only, and we are not
+ sending any info on where clause.
+ */
+ if (send_prep_stmt(stmt, 0) || send_item_params(stmt))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
+
+/*
+ Validate the following information:
+
+ SELECT - column list
+ - where clause
+ - order clause
+ - having clause
+ - group by clause
+ - if no column spec i.e. '*', then setup all fields
+
+ And send column list fields info back to client.
+*/
+static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
+ uint wild_num,
+ List<Item> &fields, COND *conds,
+ uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc,
+ ulong select_options,
+ SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex)
+{
+ THD *thd= stmt->thd;
+ LEX *lex= &thd->lex;
+ select_result *result= thd->lex.result;
+ DBUG_ENTER("mysql_test_select_fields");
+
+ if ((&lex->select_lex != lex->all_selects_list &&
+ lex->unit.create_total_list(thd, lex, &tables, 0)))
+ DBUG_RETURN(1);
+
+ if (open_and_lock_tables(thd, tables))
+ DBUG_RETURN(1);
+
+ fix_tables_pointers(thd->lex.all_selects_list);
+
+ if (!result && !(result= new select_send()))
+ {
+ delete select_lex->having;
+ delete select_lex->where;
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_RETURN(1);
+ }
+
+ JOIN *join= new JOIN(thd, fields, select_options, result);
+ thd->used_tables= 0; // Updated by setup_fields
+
+ if (join->prepare(&select_lex->ref_pointer_array, tables,
+ wild_num, conds, og_num, order, group, having, proc,
+ select_lex, unit, 0, 0))
+ DBUG_RETURN(1);
+
+ /*
+ Currently return only column list info only, and we are not
+ sending any info on where clause.
+ */
+ if (send_prep_stmt(stmt, fields.elements) ||
+ thd->protocol_simple.send_fields(&fields, 0) ||
+ send_item_params(stmt))
+ DBUG_RETURN(1);
+ join->cleanup(thd);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Send the prepare query results back to client
+*/
+
+static bool send_prepare_results(PREP_STMT *stmt)
+{
+ THD *thd= stmt->thd;
+ LEX *lex= &thd->lex;
+ enum enum_sql_command sql_command= thd->lex.sql_command;
+ DBUG_ENTER("send_prepare_results");
+ DBUG_PRINT("enter",("command: %d, param_count: %ld",
+ sql_command, lex->param_count));
+
+ /* Setup prepared stmt */
+ stmt->param_count= lex->param_count;
+ stmt->free_list= thd->free_list; // Save items used in stmt
+ thd->free_list= 0;
+
+ SELECT_LEX *select_lex= &lex->select_lex;
+ TABLE_LIST *tables=(TABLE_LIST*) select_lex->table_list.first;
+
+ switch (sql_command) {
+
+ case SQLCOM_INSERT:
+ if (mysql_test_insert_fields(stmt, tables, lex->field_list,
+ lex->many_values))
+ goto abort;
+ break;
+
+ case SQLCOM_UPDATE:
+ if (mysql_test_upd_fields(stmt, tables, select_lex->item_list,
+ lex->value_list, select_lex->where))
+ goto abort;
+ break;
+
+ case SQLCOM_DELETE:
+ if (mysql_test_upd_fields(stmt, tables, select_lex->item_list,
+ lex->value_list, select_lex->where))
+ goto abort;
+ break;
+
+ case SQLCOM_SELECT:
+ if (mysql_test_select_fields(stmt, tables, select_lex->with_wild,
+ select_lex->item_list,
+ select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*)lex->proc_list.first,
+ select_lex->options | thd->options,
+ &(lex->unit), select_lex))
+ goto abort;
+ break;
+
+ default:
+ {
+ /*
+ Rest fall through to default category, no parsing
+ for non-DML statements
+ */
+ if (send_prep_stmt(stmt, 0))
+ goto abort;
+ }
+ }
+ DBUG_RETURN(0);
+
+abort:
+ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ DBUG_RETURN(1);
+}
+
+/*
+ Parse the prepare query
+*/
+
+static bool parse_prepare_query(PREP_STMT *stmt,
+ char *packet, uint length)
+{
+ bool error= 1;
+ THD *thd= stmt->thd;
+ DBUG_ENTER("parse_prepare_query");
+
+ mysql_log.write(thd,COM_PREPARE,"%s",packet);
+ mysql_init_query(thd);
+ LEX *lex=lex_start(thd, (uchar*) packet, length);
+ lex->safe_to_cache_query= 0;
+ thd->prepare_command= TRUE;
+ thd->lex.param_count= 0;
+ if (!yyparse((void *)thd) && !thd->is_fatal_error)
+ error= send_prepare_results(stmt);
+ lex_end(lex);
+ DBUG_RETURN(error);
+}
+
+/*
+ Initialize parameter items in statement
+*/
+
+static bool init_param_items(PREP_STMT *stmt)
+{
+ List<Item> &params= stmt->thd->lex.param_list;
+ Item_param **to;
+
+ stmt->lex= stmt->thd->lex;
+ if (!stmt->param_count)
+ stmt->param= (Item_param **)0;
+ else
+ {
+ if (!(stmt->param= to= (Item_param **)
+ my_malloc(sizeof(Item_param *)*(stmt->param_count+1),
+ MYF(MY_WME))))
+ return 1;
+ List_iterator<Item> param_iterator(params);
+ while ((*(to++)= (Item_param *)param_iterator++));
+ }
+ return 0;
+}
+
+/*
+ Initialize stmt execution
+*/
+
+static void init_stmt_execute(PREP_STMT *stmt)
+{
+ THD *thd= stmt->thd;
+ TABLE_LIST *tables= (TABLE_LIST*) thd->lex.select_lex.table_list.first;
+
+ /*
+ TODO: When the new table structure is ready, then have a status bit
+ to indicate the table is altered, and re-do the setup_*
+ and open the tables back.
+ */
+ if (tables)
+ tables->table= 0; //safety - nasty init
+}
+
+/*
+ Parse the query and send the total number of parameters
+ and resultset metadata information back to client (if any),
+ without executing the query i.e. with out any log/disk
+ writes. This will allow the queries to be re-executed
+ without re-parsing during execute.
+
+ If parameter markers are found in the query, then store
+ the information using Item_param along with maintaining a
+ list in lex->param_list, so that a fast and direct
+ retrieveal can be made without going through all field
+ items.
+*/
+
+bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
+{
+ MEM_ROOT thd_root= thd->mem_root;
+ PREP_STMT stmt;
+ DBUG_ENTER("mysql_stmt_prepare");
+
+ bzero((char*) &stmt, sizeof(stmt));
+
+ stmt.stmt_id= ++thd->current_stmt_id;
+ init_sql_alloc(&stmt.mem_root, 8192, 8192);
+
+ stmt.thd= thd;
+ stmt.thd->mem_root= stmt.mem_root;
+
+ if (alloc_query(stmt.thd, packet, packet_length))
+ goto err;
+
+ if (parse_prepare_query(&stmt, thd->query, thd->query_length))
+ goto err;
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),WAIT_PRIOR);
+
+ if (init_param_items(&stmt))
+ goto err;
+
+ stmt.mem_root= stmt.thd->mem_root;
+ tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
+ thd->mem_root= thd_root; // restore main mem_root
+ DBUG_RETURN(0);
+
+err:
+ stmt.mem_root= stmt.thd->mem_root;
+ free_prep_stmt(&stmt, free_free, (void*) 0);
+ thd->mem_root= thd_root; // restore main mem_root
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Executes previously prepared query
+
+ If there is any parameters(thd->param_count), then replace
+ markers with the data supplied from client, and then
+ execute the query
+*/
+
+void mysql_stmt_execute(THD *thd, char *packet)
+{
+ ulong stmt_id= uint4korr(packet);
+ PREP_STMT *stmt;
+ DBUG_ENTER("mysql_stmt_execute");
+
+ if (!(stmt=find_prepared_statement(thd, stmt_id, "execute")))
+ {
+ send_error(thd);
+ DBUG_VOID_RETURN;
+ }
+
+ /* Check if we got an error when sending long data */
+ if (stmt->error_in_prepare)
+ {
+ send_error(thd, stmt->last_errno, stmt->last_error);
+ DBUG_VOID_RETURN;
+ }
+
+ LEX thd_lex= thd->lex;
+ thd->lex= stmt->lex;
+ init_stmt_execute(stmt);
+
+ if (stmt->param_count && setup_params_data(stmt))
+ DBUG_VOID_RETURN;
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+
+ /*
+ TODO:
+ Also, have checks on basic executions such as mysql_insert(),
+ mysql_delete(), mysql_update() and mysql_select() to not to
+ have re-check on setup_* and other things ..
+ */
+ thd->protocol= &thd->protocol_prep; // Switch to binary protocol
+ mysql_execute_command(thd);
+ thd->protocol= &thd->protocol_simple; // Use normal protocol
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(), WAIT_PRIOR);
+
+ thd->lex= thd_lex;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Reset a prepared statement
+
+ SYNOPSIS
+ mysql_stmt_reset()
+ thd Thread handle
+ packet Packet with stmt handle
+
+ DESCRIPTION
+ This function is useful when one gets an error after calling
+ mysql_stmt_getlongdata() and one wants to reset the handle
+ so that one can call execute again.
+*/
+
+void mysql_stmt_reset(THD *thd, char *packet)
+{
+ ulong stmt_id= uint4korr(packet);
+ PREP_STMT *stmt;
+ DBUG_ENTER("mysql_stmt_reset");
+
+ if (!(stmt=find_prepared_statement(thd, stmt_id, "close")))
+ {
+ send_error(thd);
+ DBUG_VOID_RETURN;
+ }
+
+ stmt->error_in_prepare= 0;
+ Item_param *item= *stmt->param, *end= item + stmt->param_count;
+
+ /* Free long data if used */
+ if (stmt->long_data_used)
+ {
+ stmt->long_data_used= 0;
+ for (; item < end ; item++)
+ item->reset();
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Delete a prepared statement from memory
+*/
+
+void mysql_stmt_free(THD *thd, char *packet)
+{
+ ulong stmt_id= uint4korr(packet);
+ PREP_STMT *stmt;
+ DBUG_ENTER("mysql_stmt_free");
+
+ if (!(stmt=find_prepared_statement(thd, stmt_id, "close")))
+ {
+ send_error(thd); // Not seen by the client
+ DBUG_VOID_RETURN;
+ }
+ tree_delete(&thd->prepared_statements, (void*) &stmt_id, (void *)0);
+ thd->last_prepared_stmt= (PREP_STMT *)0;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Long data in pieces from client
+
+ SYNOPSIS
+ mysql_stmt_get_longdata()
+ thd Thread handle
+ pos String to append
+ packet_length Length of string
+
+ DESCRIPTION
+ Get a part of a long data.
+ To make the protocol efficient, we are not sending any return packages
+ here.
+ If something goes wrong, then we will send the error on 'execute'
+
+ We assume that the client takes care of checking that all parts are sent
+ to the server. (No checking that we get a 'end of column' in the server)
+*/
+
+void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
+{
+ PREP_STMT *stmt;
+ DBUG_ENTER("mysql_stmt_get_longdata");
+
+ /* The following should never happen */
+ if (packet_length < MYSQL_LONG_DATA_HEADER+1)
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "get_longdata");
+ DBUG_VOID_RETURN;
+ }
+
+ ulong stmt_id= uint4korr(pos);
+ uint param_number= uint2korr(pos+4);
+ pos+= MYSQL_LONG_DATA_HEADER; // Point to data
+
+ if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata")))
+ {
+ /*
+ There is a chance that the client will never see this as
+ it doesn't expect an answer from this call...
+ */
+ send_error(thd);
+ DBUG_VOID_RETURN;
+ }
+
+ if (param_number >= stmt->param_count)
+ {
+ /* Error will be sent in execute call */
+ stmt->error_in_prepare= 1;
+ stmt->last_errno= ER_WRONG_ARGUMENTS;
+ sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "get_longdata");
+ DBUG_VOID_RETURN;
+ }
+ Item_param *param= *(stmt->param+param_number);
+ param->set_longdata(pos, packet_length-MYSQL_LONG_DATA_HEADER-1);
+ stmt->long_data_used= 1;
+ DBUG_VOID_RETURN;
+}
+
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 3eddd2646d5..5b0ec2ec843 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -97,7 +97,7 @@ end:
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
- send_ok(&thd->net);
+ send_ok(thd);
}
for (TABLE_LIST *table=table_list ; table != lock_table ; table=table->next)
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 6a14a7c5d16..05a70c24bfd 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -17,12 +17,13 @@
// Sasha Pachev <sasha@mysql.com> is currently in charge of this file
#include "mysql_priv.h"
+#ifdef HAVE_REPLICATION
+
#include "sql_repl.h"
#include "sql_acl.h"
#include "log_event.h"
#include "mini_client.h"
#include <my_dir.h>
-#include <assert.h>
extern const char* any_db;
@@ -283,11 +284,11 @@ binlog purge"; break;
if (errmsg)
{
- send_error(&thd->net, 0, errmsg);
+ send_error(thd, 0, errmsg);
return 1;
}
else
- send_ok(&thd->net);
+ send_ok(thd);
return 0;
}
@@ -372,7 +373,7 @@ impossible position";
We need to start a packet with something other than 255
to distiquish it from error
*/
- packet->set("\0", 1);
+ packet->set("\0", 1, system_charset_info);
// if we are at the start of the log
if (pos == BIN_LOG_HEADER_SIZE)
@@ -383,7 +384,7 @@ impossible position";
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
- packet->set("\0", 1);
+ packet->set("\0", 1, system_charset_info);
}
while (!net->error && net->vio != 0 && !thd->killed)
@@ -418,7 +419,7 @@ impossible position";
goto err;
}
}
- packet->set("\0", 1);
+ packet->set("\0", 1, system_charset_info);
}
/*
TODO: now that we are logging the offset, check to make sure
@@ -538,7 +539,7 @@ Increase max_allowed_packet on master";
goto err;
}
}
- packet->set("\0", 1);
+ packet->set("\0", 1, system_charset_info);
/*
No need to net_flush because we will get to flush later when
we hit EOF pretty quick
@@ -593,7 +594,7 @@ Increase max_allowed_packet on master";
end_io_cache(&log);
(void)my_close(file, MYF(MY_WME));
- send_eof(&thd->net);
+ send_eof(thd);
thd->proc_info = "waiting to finalize termination";
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
@@ -615,15 +616,15 @@ Increase max_allowed_packet on master";
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
(void) my_close(file, MYF(MY_WME));
- send_error(&thd->net, my_errno, errmsg);
+ send_error(thd, my_errno, errmsg);
DBUG_VOID_RETURN;
}
int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
{
int slave_errno = 0;
- if (!thd) thd = current_thd;
- NET* net = &thd->net;
+ if (!thd)
+ thd = current_thd;
int thread_mask;
DBUG_ENTER("start_slave");
@@ -654,20 +655,21 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
if (slave_errno)
{
if (net_report)
- send_error(net, slave_errno);
+ send_error(thd, slave_errno);
DBUG_RETURN(1);
}
else if (net_report)
- send_ok(net);
+ send_ok(thd);
DBUG_RETURN(0);
}
+
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
{
int slave_errno = 0;
- if (!thd) thd = current_thd;
- NET* net = &thd->net;
+ if (!thd)
+ thd = current_thd;
if (check_access(thd, SUPER_ACL, any_db))
return 1;
@@ -686,11 +688,11 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (slave_errno)
{
if (net_report)
- send_error(net, slave_errno);
+ send_error(thd, slave_errno);
return 1;
}
else if (net_report)
- send_ok(net);
+ send_ok(thd);
return 0;
}
@@ -756,7 +758,7 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
err:
unlock_slave_threads(mi);
if (thd && error)
- send_error(&thd->net, sql_errno, errmsg);
+ send_error(thd, sql_errno, errmsg);
DBUG_RETURN(error);
}
@@ -801,7 +803,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
if (thread_mask) // We refuse if any slave thread is running
{
- net_printf(&thd->net,ER_SLAVE_MUST_STOP);
+ net_printf(thd,ER_SLAVE_MUST_STOP);
unlock_slave_threads(mi);
DBUG_RETURN(1);
}
@@ -811,7 +813,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
// TODO: see if needs re-write
if (init_master_info(mi, master_info_file, relay_log_info_file, 0))
{
- send_error(&thd->net, 0, "Could not initialize master info");
+ send_error(thd, 0, "Could not initialize master info");
unlock_slave_threads(mi);
DBUG_RETURN(1);
}
@@ -873,7 +875,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
0 /* not only reset, but also reinit */,
&errmsg))
{
- net_printf(&thd->net, 0, "Failed purging old relay logs: %s",errmsg);
+ net_printf(thd, 0, "Failed purging old relay logs: %s",errmsg);
unlock_slave_threads(mi);
DBUG_RETURN(1);
}
@@ -888,7 +890,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
0 /*no data lock*/,
&msg))
{
- net_printf(&thd->net,0,"Failed initializing relay log position: %s",msg);
+ net_printf(thd,0,"Failed initializing relay log position: %s",msg);
unlock_slave_threads(mi);
DBUG_RETURN(1);
}
@@ -907,7 +909,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
unlock_slave_threads(mi);
thd->proc_info = 0;
- send_ok(&thd->net);
+ send_ok(thd);
DBUG_RETURN(0);
}
@@ -941,14 +943,15 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
int show_binlog_events(THD* thd)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_events");
List<Item> field_list;
- const char* errmsg = 0;
+ const char *errmsg = 0;
IO_CACHE log;
File file = -1;
Log_event::init_show_field_list(&field_list);
- if (send_fields(thd, field_list, 1))
+ if (protocol-> send_fields(&field_list, 1))
DBUG_RETURN(-1);
if (mysql_bin_log.is_open())
@@ -962,8 +965,8 @@ int show_binlog_events(THD* thd)
LOG_INFO linfo;
Log_event* ev;
- limit_start = thd->lex.select->offset_limit;
- limit_end = thd->lex.select->select_limit + limit_start;
+ limit_start = thd->lex.current_select->offset_limit;
+ limit_end = thd->lex.current_select->select_limit + limit_start;
name= search_file_name;
if (log_file_name)
@@ -996,7 +999,7 @@ int show_binlog_events(THD* thd)
(ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,0)); )
{
if (event_count >= limit_start &&
- ev->net_send(thd, linfo.log_file_name, pos))
+ ev->net_send(protocol, linfo.log_file_name, pos))
{
errmsg = "Net error";
delete ev;
@@ -1035,38 +1038,39 @@ err:
DBUG_RETURN(-1);
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
int show_binlog_info(THD* thd)
{
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_info");
List<Item> field_list;
field_list.push_back(new Item_empty_string("File", FN_REFLEN));
- field_list.push_back(new Item_empty_string("Position",20));
- field_list.push_back(new Item_empty_string("Binlog_do_db",20));
- field_list.push_back(new Item_empty_string("Binlog_ignore_db",20));
+ field_list.push_back(new Item_return_int("Position",20,
+ MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("Binlog_do_db",255));
+ field_list.push_back(new Item_empty_string("Binlog_ignore_db",255));
- if (send_fields(thd, field_list, 1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
- String* packet = &thd->packet;
- packet->length(0);
+ protocol->prepare_for_resend();
if (mysql_bin_log.is_open())
{
LOG_INFO li;
mysql_bin_log.get_current_log(&li);
int dir_len = dirname_length(li.log_file_name);
- net_store_data(packet, li.log_file_name + dir_len);
- net_store_data(packet, (longlong)li.pos);
- net_store_data(packet, &binlog_do_db);
- net_store_data(packet, &binlog_ignore_db);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
+ protocol->store(li.log_file_name + dir_len);
+ protocol->store((ulonglong) li.pos);
+ protocol->store(&binlog_do_db);
+ protocol->store(&binlog_ignore_db);
+ if (protocol->write())
DBUG_RETURN(-1);
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -1092,6 +1096,8 @@ int show_binlogs(THD* thd)
List<Item> field_list;
String *packet = &thd->packet;
uint length;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("show_binlogs");
if (!mysql_bin_log.is_open())
{
@@ -1101,8 +1107,8 @@ int show_binlogs(THD* thd)
}
field_list.push_back(new Item_empty_string("Log_name", 255));
- if (send_fields(thd, field_list, 1))
- return 1;
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(1);
mysql_bin_log.lock_index();
index_file=mysql_bin_log.get_index_file();
@@ -1111,22 +1117,22 @@ int show_binlogs(THD* thd)
/* The file ends with EOF or empty line */
while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
{
+ protocol->prepare_for_resend();
int dir_len = dirname_length(fname);
- packet->length(0);
/* The -1 is for removing newline from fname */
- net_store_data(packet, fname + dir_len, length-1-dir_len);
- if (my_net_write(net, (char*) packet->ptr(), packet->length()))
+ protocol->store(fname + dir_len, length-1-dir_len);
+ if (protocol->write())
goto err;
}
mysql_bin_log.unlock_index();
- send_eof(net);
- return 0;
+ send_eof(thd);
+ DBUG_RETURN(0);
err_with_msg:
- send_error(net, 0, errmsg);
+ send_error(thd, ER_UNKNOWN_ERROR, errmsg);
err:
mysql_bin_log.unlock_index();
- return 1;
+ DBUG_RETURN(1);
}
@@ -1162,3 +1168,7 @@ int log_loaded_block(IO_CACHE* file)
}
return 0;
}
+
+#endif /* HAVE_REPLICATION */
+
+
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 15435382b08..f1fda45fe4b 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -1,3 +1,4 @@
+#ifdef HAVE_REPLICATION
#include "slave.h"
typedef struct st_slave_info
@@ -53,3 +54,6 @@ typedef struct st_load_file_info
} LOAD_FILE_INFO;
int log_loaded_block(IO_CACHE* file);
+
+#endif /* HAVE_REPLICATION */
+
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index cf7f310bbd5..4543c6bc5d0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -29,7 +29,6 @@
#include <m_ctype.h>
#include <hash.h>
#include <ft_global.h>
-#include <assert.h>
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"MAYBE_REF","ALL","range","index","fulltext" };
@@ -38,7 +37,8 @@ static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
JOIN_TAB *join_tab,
- uint tables,COND *conds,table_map table_map);
+ uint tables, COND *conds,
+ table_map table_map, SELECT_LEX *select_lex);
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
@@ -56,8 +56,8 @@ static store_key *get_store_key(THD *thd,
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
-static void join_free(JOIN *join);
-static bool only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables);
+static void join_free(JOIN *join, bool full);
+static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
static void update_depend_map(JOIN *join);
static void update_depend_map(JOIN *join, ORDER *order);
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
@@ -65,7 +65,8 @@ static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
List<Item> &fields, bool send_row,
uint select_options, const char *info,
- Item *having, Procedure *proc);
+ Item *having, Procedure *proc,
+ SELECT_LEX_UNIT *unit);
static COND *optimize_cond(COND *conds,Item::cond_result *cond_value);
static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
@@ -111,7 +112,9 @@ static Item* part_of_refkey(TABLE *form,Field *field);
static uint find_shortest_key(TABLE *table, key_map usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes);
-static int create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows filesort_limit,
+static int create_sort_index(THD *thd, JOIN_TAB *tab,ORDER *order,
+ ha_rows filesort_limit, ha_rows select_limit);
+static int create_sort_index(THD *thd, JOIN_TAB *tab,ORDER *order,
ha_rows select_limit);
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
Item *having);
@@ -126,8 +129,6 @@ static bool store_record_in_cache(JOIN_CACHE *cache);
static void reset_cache(JOIN_CACHE *cache);
static void read_cached_record(JOIN_TAB *tab);
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
-static int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order, bool *hidden);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields,ORDER *new_order);
static ORDER *create_distinct_group(THD *thd, ORDER *order,
@@ -138,8 +139,16 @@ static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
static bool alloc_group_fields(JOIN *join,ORDER *group);
static bool make_sum_func_list(JOIN *join,List<Item> &fields);
-static bool change_to_use_tmp_fields(List<Item> &func);
-static bool change_refs_to_tmp_fields(THD *thd, List<Item> &func);
+// Create list for using with tempory table
+static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &new_list1,
+ List<Item> &new_list2,
+ uint elements, List<Item> &items);
+// Create list for using with tempory table
+static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &new_list1,
+ List<Item> &new_list2,
+ uint elements, List<Item> &items);
static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr);
@@ -148,7 +157,7 @@ static void init_sum_functions(Item_sum **func);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct, const char *message=NullS);
-static void describe_info(JOIN *join, const char *info);
+
/*
This handles SELECT with and without UNION
@@ -158,100 +167,154 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
{
int res;
register SELECT_LEX *select_lex = &lex->select_lex;
-
-#ifdef DISABLED_UNTIL_REWRITTEN_IN_4_1
- if (lex->olap)
- {
- SELECT_LEX *sl, *sl_next;
- int error;
- for (sl= &select_lex; sl; sl=sl_next)
- {
- sl_next=sl->next; // Save if sl->next changes
- if (sl->olap != UNSPECIFIED_OLAP_TYPE)
- {
- if ((error=handle_olaps(lex,sl)))
- return error;
- lex->last_selects->next=sl_next;
- }
- }
- lex->select = select_lex;
- }
-#endif /* DISABLED_UNTIL_REWRITTEN_IN_4_1 */
- if (select_lex->next)
- res=mysql_union(thd,lex,result);
+ fix_tables_pointers(lex->all_selects_list);
+ if (select_lex->next_select())
+ res=mysql_union(thd, lex, result, &lex->unit, 0);
else
- res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
- select_lex->item_list,
- select_lex->where,
- (ORDER*) select_lex->order_list.first,
- (ORDER*) select_lex->group_list.first,
- select_lex->having,
- (ORDER*) lex->proc_list.first,
- select_lex->options | thd->options,
- result);
+ res= mysql_select(thd, &select_lex->ref_pointer_array,
+ (TABLE_LIST*) select_lex->table_list.first,
+ select_lex->with_wild, select_lex->item_list,
+ select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) lex->proc_list.first,
+ select_lex->options | thd->options,
+ result, &(lex->unit), &(lex->select_lex), 0, 0);
if (res && result)
result->abort();
+
+ if (res || thd->net.report_error)
+ {
+ send_error(thd, 0, NullS);
+ res= 1;
+ }
delete result;
return res;
}
+void relink_tables(SELECT_LEX *select_lex)
+{
+ for (TABLE_LIST *cursor= (TABLE_LIST *) select_lex->table_list.first;
+ cursor;
+ cursor=cursor->next)
+ cursor->table= cursor->table_list->table;
+}
+
+
+void fix_tables_pointers(SELECT_LEX *select_lex)
+{
+ if (select_lex->next_select_in_list())
+ {
+ /* Fix tables 'to-be-unioned-from' list to point at opened tables */
+ for (SELECT_LEX *sl= select_lex;
+ sl;
+ sl= sl->next_select_in_list())
+ relink_tables(sl);
+ }
+}
+
+void fix_tables_pointers(SELECT_LEX_UNIT *unit)
+{
+ for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ relink_tables(sl);
+ for (SELECT_LEX_UNIT *un= sl->first_inner_unit(); un; un= un->next_unit())
+ fix_tables_pointers(un);
+ }
+}
+
+
+/*
+ Function to setup clauses without sum functions
+*/
+inline int setup_without_group(THD *thd, Item **ref_pointer_array,
+ TABLE_LIST *tables,
+ List<Item> &fields,
+ List<Item> &all_fields,
+ COND **conds,
+ ORDER *order,
+ ORDER *group, bool *hidden_group_fields)
+{
+ bool save_allow_sum_func= thd->allow_sum_func;
+ thd->allow_sum_func= 0;
+ int res= (setup_conds(thd, tables, conds) ||
+ setup_order(thd, ref_pointer_array, tables, fields, all_fields,
+ order) ||
+ setup_group(thd, ref_pointer_array, tables, fields, all_fields,
+ group, hidden_group_fields));
+ thd->allow_sum_func= save_allow_sum_func;
+ return res;
+}
+
/*****************************************************************************
Check fields, find best join, do the select and output fields.
mysql_select assumes that all tables are already opened
*****************************************************************************/
+/*
+ Prepare of whole select (including subselect in future).
+ return -1 on error
+ 0 on success
+*/
int
-mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
- ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
- ulong select_options,select_result *result)
-{
- TABLE *tmp_table;
- int error, tmp_error;
- bool need_tmp,hidden_group_fields;
- bool simple_order,simple_group,no_order, skip_sort_order;
- ha_rows select_limit;
- Item::cond_result cond_value;
- SQL_SELECT *select;
- DYNAMIC_ARRAY keyuse;
- JOIN join;
- Procedure *procedure;
- List<Item> all_fields(fields);
- bool select_distinct;
- SELECT_LEX *cur_sel = thd->lex.select;
- DBUG_ENTER("mysql_select");
+JOIN::prepare(Item ***rref_pointer_array,
+ TABLE_LIST *tables_init,
+ uint wild_num, COND *conds_init, uint og_num,
+ ORDER *order_init, ORDER *group_init,
+ Item *having_init,
+ ORDER *proc_param_init, SELECT_LEX *select,
+ SELECT_LEX_UNIT *unit,
+ bool fake_select_lex, bool tables_and_fields_initied)
+{
+ DBUG_ENTER("JOIN::prepare");
+
+ conds= conds_init;
+ order= order_init;
+ group_list= group_init;
+ having= having_init;
+ proc_param= proc_param_init;
+ tables_list= tables_init;
+ select_lex= select;
+ if (!fake_select_lex)
+ select_lex->join= this;
+ union_part= (unit->first_select()->next_select() != 0);
/* Check that all tables, fields, conds and order are ok */
- select_distinct=test(select_options & SELECT_DISTINCT);
- tmp_table=0;
- select=0;
- no_order=skip_sort_order=0;
- bzero((char*) &keyuse,sizeof(keyuse));
- thd->proc_info="init";
- thd->used_tables=0; // Updated by setup_fields
- /* select_limit is used to decide if we are likely to scan the whole table */
- select_limit= thd->select_limit;
- if (having || (select_options & OPTION_FOUND_ROWS))
- select_limit= HA_POS_ERROR;
-
- if (setup_tables(tables) ||
- setup_fields(thd,tables,fields,1,&all_fields,1) ||
- setup_conds(thd,tables,&conds) ||
- setup_order(thd,tables,fields,all_fields,order) ||
- setup_group(thd,tables,fields,all_fields,group,&hidden_group_fields))
+ if ((tables_and_fields_initied ? 0 : (setup_tables(tables_list) ||
+ setup_wild(thd, tables_list,
+ fields_list,
+ &all_fields, wild_num))) ||
+ setup_ref_array(thd, rref_pointer_array, (fields_list.elements +
+ select_lex->with_sum_func +
+ og_num)) ||
+ setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
+ &all_fields, 1) ||
+ setup_without_group(thd, (*rref_pointer_array), tables_list, fields_list,
+ all_fields, &conds, order, group_list,
+ &hidden_group_fields))
DBUG_RETURN(-1); /* purecov: inspected */
+ ref_pointer_array= *rref_pointer_array;
+
if (having)
{
thd->where="having clause";
thd->allow_sum_func=1;
- if (having->fix_fields(thd,tables) || thd->fatal_error)
+ select_lex->having_fix_field= 1;
+ bool having_fix_rc= (having->fix_fields(thd, tables_list, &having) ||
+ having->check_cols(1));
+ select_lex->having_fix_field= 0;
+ if (having_fix_rc || thd->net.report_error)
DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func)
- having->split_sum_func(all_fields);
+ having->split_sum_func(ref_pointer_array, all_fields);
}
- if (setup_ftfuncs(thd)) /* should be after having->fix_fields */
+ if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1);
/*
Check if one one uses a not constant column with group functions
@@ -259,13 +322,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
TODO: Add check of calculation of GROUP functions and fields:
SELECT COUNT(*)+table.col1 from table1;
*/
- join.table=0;
- join.tables=0;
{
- if (!group)
+ if (!group_list)
{
uint flag=0;
- List_iterator_fast<Item> it(fields);
+ List_iterator_fast<Item> it(fields_list);
Item *item;
while ((item= it++))
{
@@ -281,22 +342,23 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
}
TABLE_LIST *table;
- for (table=tables ; table ; table=table->next)
- join.tables++;
+ for (table=tables_list ; table ; table=table->next)
+ tables++;
}
- procedure=setup_procedure(thd,proc_param,result,fields,&error);
+ procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
if (error)
DBUG_RETURN(-1); /* purecov: inspected */
if (procedure)
{
- if (setup_new_fields(thd,tables,fields,all_fields,procedure->param_fields))
+ if (setup_new_fields(thd, tables_list, fields_list, all_fields,
+ procedure->param_fields))
{ /* purecov: inspected */
delete procedure; /* purecov: inspected */
DBUG_RETURN(-1); /* purecov: inspected */
}
if (procedure->group)
{
- if (!test_if_subpart(procedure->group,group))
+ if (!test_if_subpart(procedure->group,group_list))
{ /* purecov: inspected */
my_message(0,"Can't handle procedures with differents groups yet",
MYF(0)); /* purecov: inspected */
@@ -305,7 +367,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
}
#ifdef NOT_NEEDED
- else if (!group && procedure->flags & PROC_GROUP)
+ else if (!group_list && procedure->flags & PROC_GROUP)
{
my_message(0,"Select must have a group with this procedure",MYF(0));
delete procedure;
@@ -321,153 +383,136 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
/* Init join struct */
- join.thd=thd;
- join.lock=thd->lock;
- join.join_tab=0;
- join.tmp_table_param.copy_field=0;
- join.sum_funcs=0;
- join.send_records=join.found_records=join.examined_rows=0;
- join.tmp_table_param.end_write_records= HA_POS_ERROR;
- join.first_record=join.sort_and_group=0;
- join.select_options=select_options;
- join.result=result;
- count_field_types(&join.tmp_table_param,all_fields,0);
- join.const_tables=0;
- join.having=0;
- join.do_send_rows = 1;
- join.group= group != 0;
- join.row_limit= ((select_distinct || order || group) ? HA_POS_ERROR :
- thd->select_limit);
+ count_field_types(&tmp_table_param, all_fields, 0);
+ this->group= group_list != 0;
+ row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
+ unit->select_limit_cnt);
+ /* select_limit is used to decide if we are likely to scan the whole table */
+ select_limit= unit->select_limit_cnt;
+ if (having || (select_options & OPTION_FOUND_ROWS))
+ select_limit= HA_POS_ERROR;
+ do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
+ this->unit= unit;
#ifdef RESTRICTED_GROUP
- if (join.sum_func_count && !group && (join.func_count || join.field_count))
+ if (sum_func_count && !group_list && (func_count || field_count))
{
my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
delete procedure;
DBUG_RETURN(-1);
}
#endif
- if (!procedure && result->prepare(fields))
+ if (!procedure && result->prepare(fields_list, unit))
{ /* purecov: inspected */
DBUG_RETURN(-1); /* purecov: inspected */
}
+ DBUG_RETURN(0); // All OK
+}
+
+/*
+ global select optimisation.
+ return 0 - success
+ 1 - go out
+ -1 - go out with cleaning
+ error code saved in field 'error'
+*/
+int
+JOIN::optimize()
+{
+ DBUG_ENTER("JOIN::optimize");
+ // to prevent double initialization on EXPLAIN
+ if (optimized)
+ DBUG_RETURN(0);
+ optimized= 1;
#ifdef HAVE_REF_TO_FIELDS // Not done yet
/* Add HAVING to WHERE if possible */
- if (having && !group && ! join.sum_func_count)
+ if (having && !group_list && ! sum_func_count)
{
if (!conds)
{
- conds=having;
- having=0;
+ conds= having;
+ having= 0;
}
else if ((conds=new Item_cond_and(conds,having)))
{
- conds->fix_fields(thd,tables);
- conds->change_ref_to_fields(thd,tables);
+ conds->fix_fields(thd, tables_list, &conds);
+ conds->change_ref_to_fields(thd, tables_list);
conds->top_level_item();
- having=0;
+ having= 0;
}
}
#endif
- conds=optimize_cond(conds,&cond_value);
- if (thd->fatal_error) // Out of memory
+ conds= optimize_cond(conds,&cond_value);
+ if (thd->net.report_error)
{
+ // quick abort
delete procedure;
- DBUG_RETURN(0);
- }
- if (cond_value == Item::COND_FALSE || !thd->select_limit)
- { /* Impossible cond */
- error=return_zero_rows(&join, result, tables, fields,
- join.tmp_table_param.sum_func_count != 0 && !group,
- select_options,"Impossible WHERE",having,
- procedure);
- delete procedure;
+ error= thd->is_fatal_error ? -1 : 1;
DBUG_RETURN(error);
}
+ if (cond_value == Item::COND_FALSE ||
+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
+ { /* Impossible cond */
+ zero_result_cause= "Impossible WHERE";
+ DBUG_RETURN(0);
+ }
+
/* Optimize count(*), min() and max() */
- if (tables && join.tmp_table_param.sum_func_count && ! group)
+ if (tables_list && tmp_table_param.sum_func_count && ! group_list)
{
int res;
- if ((res=opt_sum_query(tables, all_fields, conds)))
+ if ((res=opt_sum_query(tables_list, all_fields, conds)))
{
if (res < 0)
{
- error=return_zero_rows(&join, result, tables, fields, !group,
- select_options,"No matching min/max row",
- having,procedure);
- delete procedure;
- DBUG_RETURN(error);
- }
- if (select_options & SELECT_DESCRIBE)
- {
- describe_info(&join, "Select tables optimized away");
- delete procedure;
- DBUG_RETURN(error);
- }
- tables=0; // All tables resolved
- }
- }
- if (!tables)
- { // Only test of functions
- error=0;
- if (select_options & SELECT_DESCRIBE)
- describe_info(&join, "No tables used");
- else
- {
- result->send_fields(fields,1);
- if (!having || having->val_int())
- {
- if (join.do_send_rows && result->send_data(fields))
- {
- result->send_error(0,NullS); /* purecov: inspected */
- error=1;
- }
- else
- error=(int) result->send_eof();
+ zero_result_cause= "No matching min/max row";
+ DBUG_RETURN(0);
}
- else
- error=(int) result->send_eof();
+ zero_result_cause= "Select tables optimized away";
+ tables_list= 0; // All tables resolved
}
- delete procedure;
- DBUG_RETURN(error);
}
- error = -1;
- join.sort_by_table=get_sort_by_table(order,group,tables);
+ if (!tables_list)
+ DBUG_RETURN(0);
+
+ error= -1; // Error is sent to client
+ sort_by_table= get_sort_by_table(order, group_list, tables_list);
/* Calculate how to do the join */
- thd->proc_info="statistics";
- if (make_join_statistics(&join,tables,conds,&keyuse) || thd->fatal_error)
- goto err;
+ thd->proc_info= "statistics";
+ if (make_join_statistics(this, tables_list, conds, &keyuse) ||
+ thd->is_fatal_error)
+ DBUG_RETURN(1);
- thd->proc_info="preparing";
- if (result->initialize_tables(&join))
- goto err;
- if (join.const_table_map != join.found_const_table_map &&
+ thd->proc_info= "preparing";
+ if (result->initialize_tables(this))
+ {
+ DBUG_RETURN(1); // error = -1
+ }
+ if (const_table_map != found_const_table_map &&
!(select_options & SELECT_DESCRIBE))
{
- error=return_zero_rows(&join,result,tables,fields,
- join.tmp_table_param.sum_func_count != 0 &&
- !group,0,"no matching row in const table",having,
- procedure);
- goto err;
+ zero_result_cause= "no matching row in const table";
+ select_options= 0; //TODO why option in return_zero_rows was droped
+ DBUG_RETURN(0);
}
if (!(thd->options & OPTION_BIG_SELECTS) &&
- join.best_read > (double) thd->variables.max_join_size &&
+ best_read > (double) thd->variables.max_join_size &&
!(select_options & SELECT_DESCRIBE))
{ /* purecov: inspected */
- result->send_error(ER_TOO_BIG_SELECT,ER(ER_TOO_BIG_SELECT)); /* purecov: inspected */
+ my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0));
error= 1; /* purecov: inspected */
- goto err; /* purecov: inspected */
+ DBUG_RETURN(1);
}
- if (join.const_tables && !thd->locked_tables &&
+ if (const_tables && !thd->locked_tables &&
!(select_options & SELECT_NO_UNLOCK))
{
TABLE **table, **end;
- for (table=join.table, end=table + join.const_tables ;
+ for (table=this->table, end=table + const_tables ;
table != end;
table++)
{
@@ -479,28 +524,25 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
(*table)->file->index_end();
}
- mysql_unlock_some_tables(thd, join.table,join.const_tables);
+ mysql_unlock_some_tables(thd, this->table, const_tables);
}
- if (!conds && join.outer_join)
+ if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true
}
- select=make_select(*join.table, join.const_table_map,
- join.const_table_map,conds,&error);
+ select=make_select(*table, const_table_map,
+ const_table_map, conds, &error);
if (error)
- { /* purecov: inspected */
- error= -1; /* purecov: inspected */
- goto err; /* purecov: inspected */
+ { /* purecov: inspected */
+ error= -1; /* purecov: inspected */
+ DBUG_RETURN(1);
}
- if (make_join_select(&join,select,conds))
+ if (make_join_select(this, select, conds))
{
- error=return_zero_rows(&join, result, tables, fields,
- join.tmp_table_param.sum_func_count != 0 && !group,
- select_options,
- "Impossible WHERE noticed after reading const tables",
- having,procedure);
- goto err;
+ zero_result_cause=
+ "Impossible WHERE noticed after reading const tables";
+ DBUG_RETURN(0);
}
error= -1; /* if goto err */
@@ -508,7 +550,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/* Optimize distinct away if possible */
{
ORDER *org_order= order;
- order=remove_const(&join,order,conds,&simple_order);
+ order=remove_const(this, order,conds,&simple_order);
/*
If we are using ORDER BY NULL or ORDER BY const_expression,
return result in any order (even if we are using a GROUP BY)
@@ -516,12 +558,13 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (!order && org_order)
skip_sort_order= 1;
}
- if (group || join.tmp_table_param.sum_func_count)
+ order= remove_const(this, order, conds, &simple_order);
+ if (group_list || tmp_table_param.sum_func_count)
{
if (! hidden_group_fields)
select_distinct=0;
}
- else if (select_distinct && join.tables - join.const_tables == 1)
+ else if (select_distinct && tables - const_tables == 1)
{
/*
We are only using one table. In this case we change DISTINCT to a
@@ -538,15 +581,15 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
because in this case we can just create a temporary table that
holds LIMIT rows and stop when this table is full.
*/
- JOIN_TAB *tab= &join.join_tab[join.const_tables];
+ JOIN_TAB *tab= &join_tab[const_tables];
bool all_order_fields_used;
if (order)
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
- if ((group=create_distinct_group(thd, order, fields,
- &all_order_fields_used)))
+ if ((group_list=create_distinct_group(thd, order, fields_list,
+ &all_order_fields_used)))
{
bool skip_group= (skip_sort_order &&
- test_if_skip_sort_order(tab, group, select_limit,
+ test_if_skip_sort_order(tab, group_list, select_limit,
1) != 0);
if ((skip_group && all_order_fields_used) ||
select_limit == HA_POS_ERROR ||
@@ -557,37 +600,38 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
no_order= !order;
if (all_order_fields_used)
order=0;
- join.group=1; // For end_write_group
+ group=1; // For end_write_group
}
else
- group= 0;
- } else if (thd->fatal_error) // End of memory
- goto err;
+ group_list= 0;
+ }
+ else if (thd->is_fatal_error) // End of memory
+ DBUG_RETURN(1);
}
- group=remove_const(&join,group,conds,&simple_group);
- if (!group && join.group)
+ group_list= remove_const(this, group_list, conds, &simple_group);
+ if (!group_list && group)
{
order=0; // The output has only one row
simple_order=1;
}
- calc_group_buffer(&join,group);
- join.send_group_parts=join.tmp_table_param.group_parts; /* Save org parts */
+ calc_group_buffer(this, group_list);
+ send_group_parts= tmp_table_param.group_parts; /* Save org parts */
if (procedure && procedure->group)
{
- group=procedure->group=remove_const(&join,procedure->group,conds,
- &simple_group);
- calc_group_buffer(&join,group);
+ group_list= procedure->group= remove_const(this, procedure->group, conds,
+ &simple_group);
+ calc_group_buffer(this, group_list);
}
- if (test_if_subpart(group,order) ||
- (!group && join.tmp_table_param.sum_func_count))
+ if (test_if_subpart(group_list, order) ||
+ (!group_list && tmp_table_param.sum_func_count))
order=0;
// Can't use sort on head table if using row cache
- if (join.full_join)
+ if (full_join)
{
- if (group)
+ if (group_list)
simple_group=0;
if (order)
simple_order=0;
@@ -602,17 +646,18 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
- We are using different ORDER BY and GROUP BY orders
- The user wants us to buffer the result.
*/
- need_tmp= (join.const_tables != join.tables &&
+ need_tmp= (const_tables != tables &&
((select_distinct || !simple_order || !simple_group) ||
- (group && order) ||
+ (group_list && order) ||
test(select_options & OPTION_BUFFER_RESULT)));
// No cache for MATCH
- make_join_readinfo(&join,
+ make_join_readinfo(this,
(select_options & (SELECT_DESCRIBE |
SELECT_NO_JOIN_CACHE)) |
- (cur_sel->ftfunc_list.elements ? SELECT_NO_JOIN_CACHE :
- 0));
+ (select_lex->ftfunc_list->elements ?
+ SELECT_NO_JOIN_CACHE : 0));
+
/*
Need to tell Innobase that to play it safe, it should fetch all
columns of the tables: this is because MySQL may build row
@@ -622,174 +667,365 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
*/
#ifdef HAVE_INNOBASE_DB
- if (need_tmp || select_distinct || group || order)
+ if (need_tmp || select_distinct || group_list || order)
{
- for (uint i_h = join.const_tables; i_h < join.tables; i_h++)
+ for (uint i_h = const_tables; i_h < tables; i_h++)
{
- TABLE* table_h = join.join_tab[i_h].table;
+ TABLE* table_h = join_tab[i_h].table;
if (table_h->db_type == DB_TYPE_INNODB)
table_h->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
}
}
#endif
- DBUG_EXECUTE("info",TEST_join(&join););
+ DBUG_EXECUTE("info",TEST_join(this););
/*
Because filesort always does a full table scan or a quick range scan
we must add the removed reference to the select for the table.
We only need to do this when we have a simple_order or simple_group
as in other cases the join is done before the sort.
- */
- if ((order || group) && join.join_tab[join.const_tables].type != JT_ALL &&
- join.join_tab[join.const_tables].type != JT_FT &&
- (order && simple_order || group && simple_group))
+ */
+ if ((order || group_list) && join_tab[const_tables].type != JT_ALL &&
+ join_tab[const_tables].type != JT_FT &&
+ (order && simple_order || group_list && simple_group))
{
- if (add_ref_to_table_cond(thd,&join.join_tab[join.const_tables]))
- goto err;
+ if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
+ DBUG_RETURN(1);
}
if (!(select_options & SELECT_BIG_RESULT) &&
- ((group && join.const_tables != join.tables &&
+ ((group_list && const_tables != tables &&
(!simple_group ||
- !test_if_skip_sort_order(&join.join_tab[join.const_tables], group,
- thd->select_limit,0))) ||
+ !test_if_skip_sort_order(&join_tab[const_tables], group_list,
+ unit->select_limit_cnt,
+ 0))) ||
select_distinct) &&
- join.tmp_table_param.quick_group && !procedure)
+ tmp_table_param.quick_group && !procedure)
{
need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
}
if (select_options & SELECT_DESCRIBE)
- {
- if (!order && !no_order)
- order=group;
- if (order &&
- (join.const_tables == join.tables ||
- ((simple_order || skip_sort_order) &&
- test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
- select_limit, 0))))
- order=0;
- select_describe(&join,need_tmp,
- order != 0 && !skip_sort_order,
- select_distinct);
- error=0;
- goto err;
- }
+ DBUG_RETURN(0);
- /* Perform FULLTEXT search before all regular searches */
- init_ftfuncs(thd,test(order));
+ tmp_having= having;
+ having= 0;
+ /* Perform FULLTEXT search before all regular searches */
+ init_ftfuncs(thd, select_lex, test(order));
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
{
DBUG_PRINT("info",("Creating tmp table"));
thd->proc_info="Creating tmp table";
- join.tmp_table_param.hidden_field_count= (all_fields.elements -
- fields.elements);
- if (!(tmp_table =
- create_tmp_table(thd,&join.tmp_table_param,all_fields,
+ init_items_ref_array();
+
+ tmp_table_param.hidden_field_count= (all_fields.elements -
+ fields_list.elements);
+ if (!(exec_tmp_table1 =
+ create_tmp_table(thd, &tmp_table_param, all_fields,
((!simple_group && !procedure &&
!(test_flags & TEST_NO_KEY_GROUP)) ?
- group : (ORDER*) 0),
- group ? 0 : select_distinct,
- group && simple_group,
- (order == 0 || skip_sort_order) &&
- select_limit != HA_POS_ERROR,
- join.select_options)))
- goto err; /* purecov: inspected */
+ group_list : (ORDER*) 0),
+ group_list ? 0 : select_distinct,
+ group_list && simple_group,
+ select_options,
+ (order == 0 || skip_sort_order) ? select_limit :
+ HA_POS_ERROR)))
+ DBUG_RETURN(1);
- if (having && (join.sort_and_group || (tmp_table->distinct && !group)))
- join.having=having;
+ /*
+ We don't have to store rows in temp table that doesn't match HAVING if:
+ - we are sorting the table and writing complete group rows to the
+ temp table.
+ - We are using DISTINCT without resolving the distinct as a GROUP BY
+ on all columns.
+
+ If having is not handled here, it will be checked before the row
+ is sent to the client.
+ */
+ if (having &&
+ (sort_and_group || (exec_tmp_table1->distinct && !group_list)))
+ having= tmp_having;
/* if group or order on first table, sort first */
- if (group && simple_group)
+ if (group_list && simple_group)
{
DBUG_PRINT("info",("Sorting for group"));
thd->proc_info="Sorting for group";
- if (create_sort_index(&join.join_tab[join.const_tables],group,
+ if (create_sort_index(thd, &join_tab[const_tables], group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
- make_sum_func_list(&join,all_fields) ||
- alloc_group_fields(&join,group))
- goto err;
- group=0;
+ make_sum_func_list(this, all_fields) ||
+ alloc_group_fields(this, group_list))
+ DBUG_RETURN(1);
+ group_list=0;
}
else
{
- if (make_sum_func_list(&join,all_fields))
- goto err;
- if (!group && ! tmp_table->distinct && order && simple_order)
+ if (make_sum_func_list(this, all_fields))
+ DBUG_RETURN(1);
+ if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
DBUG_PRINT("info",("Sorting for order"));
thd->proc_info="Sorting for order";
- if (create_sort_index(&join.join_tab[join.const_tables],order,
- HA_POS_ERROR, HA_POS_ERROR))
- goto err; /* purecov: inspected */
+ if (create_sort_index(thd, &join_tab[const_tables], order,
+ HA_POS_ERROR, HA_POS_ERROR))
+ DBUG_RETURN(1);
order=0;
}
}
-
+
/*
Optimize distinct when used on some of the tables
SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b
In this case we can stop scanning t2 when we have found one t1.a
*/
- if (tmp_table->distinct)
+ if (exec_tmp_table1->distinct)
{
table_map used_tables= thd->used_tables;
- JOIN_TAB *join_tab=join.join_tab+join.tables-1;
+ JOIN_TAB *join_tab= this->join_tab+tables-1;
do
{
if (used_tables & join_tab->table->map)
break;
join_tab->not_used_in_distinct=1;
- } while (join_tab-- != join.join_tab);
+ } while (join_tab-- != this->join_tab);
/* Optimize "select distinct b from t1 order by key_part_1 limit #" */
if (order && skip_sort_order)
{
- /* Should always succeed */
- if (test_if_skip_sort_order(&join.join_tab[join.const_tables],
- order, thd->select_limit,0))
+ /* Should always succeed */
+ if (test_if_skip_sort_order(&this->join_tab[const_tables],
+ order, unit->select_limit_cnt, 0))
order=0;
}
}
+
+ if (select_lex != &thd->lex.select_lex &&
+ select_lex->linkage != DERIVED_TABLE_TYPE)
+ {
+ if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
+ DBUG_RETURN(-1);
+ restore_tmp();
+ }
+ }
- /* Copy data to the temporary table */
- thd->proc_info="Copying to tmp table";
- if ((tmp_error=do_select(&join,(List<Item> *) 0,tmp_table,0)))
+ DBUG_RETURN(0);
+}
+
+/*
+ Restore values in temporary join
+*/
+
+void JOIN::restore_tmp()
+{
+ memcpy(tmp_join, this, (size_t) sizeof(JOIN));
+}
+
+
+int
+JOIN::reinit()
+{
+ DBUG_ENTER("JOIN::reinit");
+ //TODO move to unit reinit
+ unit->offset_limit_cnt =select_lex->offset_limit;
+ unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
+ if (unit->select_limit_cnt < select_lex->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR; // no limit
+ if (unit->select_limit_cnt == HA_POS_ERROR)
+ select_lex->options&= ~OPTION_FOUND_ROWS;
+
+ if (setup_tables(tables_list))
+ DBUG_RETURN(1);
+
+ // Reset of sum functions
+ first_record= 0;
+ if (sum_funcs)
+ {
+ Item_sum *func, **func_ptr= sum_funcs;
+ while ((func= *(func_ptr++)))
+ func->null_value= 1;
+ }
+
+ if (exec_tmp_table1)
+ {
+ exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE);
+ exec_tmp_table1->file->delete_all_rows();
+ free_io_cache(exec_tmp_table1);
+ }
+ if (exec_tmp_table2)
+ {
+ exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE);
+ exec_tmp_table2->file->delete_all_rows();
+ free_io_cache(exec_tmp_table2);
+ }
+ if (items0)
+ memcpy(ref_pointer_array, items0, ref_pointer_array_size);
+
+ if (tmp_join)
+ restore_tmp();
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Exec select
+*/
+void
+JOIN::exec()
+{
+ int tmp_error;
+
+ DBUG_ENTER("JOIN::exec");
+
+ if (procedure)
+ {
+ if (procedure->change_columns(fields_list) ||
+ result->prepare(fields_list, unit))
+ DBUG_VOID_RETURN;
+ }
+
+ if (!tables_list)
+ { // Only test of functions
+ error=0;
+ if (select_options & SELECT_DESCRIBE)
+ select_describe(this, false, false, false,
+ (zero_result_cause?zero_result_cause:"No tables used"));
+ else
{
- error=tmp_error;
- goto err; /* purecov: inspected */
+ result->send_fields(fields_list,1);
+ if (!having || having->val_int())
+ {
+ if (do_send_rows && (procedure ? (procedure->send_row(fields_list) ||
+ procedure->end_of_records())
+ : result->send_data(fields_list)))
+ error= 1;
+ else
+ {
+ error= (int) result->send_eof();
+ send_records=1;
+ }
+ }
+ else
+ error=(int) result->send_eof();
}
- if (join.having)
- join.having=having=0; // Allready done
+ DBUG_VOID_RETURN;
+ }
+
+ if (zero_result_cause)
+ {
+ error=0;
+
+ (void) return_zero_rows(this, result, tables_list, fields_list,
+ tmp_table_param.sum_func_count != 0 &&
+ !group_list,
+ select_options,
+ zero_result_cause,
+ having, procedure,
+ unit);
+ DBUG_VOID_RETURN;
+ }
+ if (select_options & SELECT_DESCRIBE)
+ {
+ if (!order && !no_order)
+ order=group_list;
+ if (order &&
+ (const_tables == tables ||
+ ((simple_order || skip_sort_order) &&
+ test_if_skip_sort_order(&join_tab[const_tables], order,
+ select_limit, 0))))
+ order=0;
+ having= tmp_having;
+ select_describe(this, need_tmp,
+ order != 0 && !skip_sort_order,
+ select_distinct);
+ error=0;
+ DBUG_VOID_RETURN;
+ }
+
+ /* Perform FULLTEXT search before all regular searches */
+ //init_ftfuncs(thd, select_lex, test(order));
+
+ JOIN *curr_join= this;
+ List<Item> *curr_all_fields= &all_fields;
+ List<Item> *curr_fields_list= &fields_list;
+ TABLE *curr_tmp_table= 0;
+
+ /* Create a tmp table if distinct or if the sort is too complicated */
+ if (need_tmp)
+ {
+ if (tmp_join)
+ curr_join= tmp_join;
+ curr_tmp_table= exec_tmp_table1;
+
+ /* Copy data to the temporary table */
+ thd->proc_info= "Copying to tmp table";
+
+ if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
+ {
+ error= tmp_error;
+ DBUG_VOID_RETURN;
+ }
+ curr_tmp_table->file->info(HA_STATUS_VARIABLE);
+
+ if (curr_join->having)
+ curr_join->having= curr_join->tmp_having= 0; // Allready done
+
/* Change sum_fields reference to calculated fields in tmp_table */
- if (join.sort_and_group || tmp_table->group)
+ curr_join->all_fields= *curr_all_fields;
+ if (!items1)
{
- if (change_to_use_tmp_fields(all_fields))
- goto err;
- join.tmp_table_param.field_count+=join.tmp_table_param.sum_func_count+
- join.tmp_table_param.func_count;
- join.tmp_table_param.sum_func_count=join.tmp_table_param.func_count=0;
+ items1= items0 + all_fields.elements;
+ if (sort_and_group || curr_tmp_table->group)
+ {
+ if (change_to_use_tmp_fields(thd, items1,
+ tmp_fields_list1, tmp_all_fields1,
+ fields_list.elements, all_fields))
+ DBUG_VOID_RETURN;
+ }
+ else
+ {
+ if (change_refs_to_tmp_fields(thd, items1,
+ tmp_fields_list1, tmp_all_fields1,
+ fields_list.elements, all_fields))
+ DBUG_VOID_RETURN;
+ }
+ curr_join->tmp_all_fields1= tmp_all_fields1;
+ curr_join->tmp_fields_list1= tmp_fields_list1;
+ curr_join->items1= items1;
+ }
+ curr_all_fields= &tmp_all_fields1;
+ curr_fields_list= &tmp_fields_list1;
+ memcpy(ref_pointer_array, items1, ref_pointer_array_size);
+
+ if (sort_and_group || curr_tmp_table->group)
+ {
+ curr_join->tmp_table_param.field_count+=
+ curr_join->tmp_table_param.sum_func_count+
+ curr_join->tmp_table_param.func_count;
+ curr_join->tmp_table_param.sum_func_count=
+ curr_join->tmp_table_param.func_count= 0;
}
else
{
- if (change_refs_to_tmp_fields(thd,all_fields))
- goto err;
- join.tmp_table_param.field_count+=join.tmp_table_param.func_count;
- join.tmp_table_param.func_count=0;
+ curr_join->tmp_table_param.field_count+=
+ curr_join->tmp_table_param.func_count;
+ curr_join->tmp_table_param.func_count= 0;
}
+
+ // procedure can't be used inside subselect => we do nothing special for it
if (procedure)
procedure->update_refs();
- if (tmp_table->group)
+
+ if (curr_tmp_table->group)
{ // Already grouped
- if (!order && !no_order && !skip_sort_order)
- order=group; /* order by group */
- group=0;
+ if (!curr_join->order && !curr_join->no_order && !skip_sort_order)
+ curr_join->order= curr_join->group_list; /* order by group */
+ curr_join->group_list= 0;
}
-
+
/*
If we have different sort & group then we must sort the data by group
and copy it to another tmp table
@@ -798,181 +1034,331 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
like SEC_TO_TIME(SUM(...)).
*/
- if (group && (!test_if_subpart(group,order) || select_distinct) ||
- (select_distinct &&
- join.tmp_table_param.using_indirect_summary_function))
+ if (curr_join->group_list && (!test_if_subpart(curr_join->group_list,
+ curr_join->order) ||
+ curr_join->select_distinct) ||
+ (curr_join->select_distinct &&
+ curr_join->tmp_table_param.using_indirect_summary_function))
{ /* Must copy to another table */
- TABLE *tmp_table2;
DBUG_PRINT("info",("Creating group table"));
-
+
/* Free first data from old join */
- join_free(&join);
- if (make_simple_join(&join,tmp_table))
- goto err;
- calc_group_buffer(&join,group);
- count_field_types(&join.tmp_table_param,all_fields,
- select_distinct && !group);
- join.tmp_table_param.hidden_field_count=(all_fields.elements-
- fields.elements);
-
- /* group data to new table */
- if (!(tmp_table2 = create_tmp_table(thd,&join.tmp_table_param,all_fields,
- (ORDER*) 0,
- select_distinct && !group,
- 1, 0,
- join.select_options)))
- goto err; /* purecov: inspected */
- if (group)
+ join_free(curr_join, 0);
+ if (make_simple_join(curr_join, curr_tmp_table))
+ DBUG_VOID_RETURN;
+ calc_group_buffer(curr_join, group_list);
+ count_field_types(&curr_join->tmp_table_param, curr_join->tmp_all_fields1,
+ curr_join->select_distinct && !curr_join->group_list);
+ curr_join->tmp_table_param.hidden_field_count=
+ (curr_join->tmp_all_fields1.elements-
+ curr_join->tmp_fields_list1.elements);
+
+
+ if (exec_tmp_table2)
+ curr_tmp_table= exec_tmp_table2;
+ else
{
- thd->proc_info="Creating sort index";
- if (create_sort_index(join.join_tab,group,HA_POS_ERROR, HA_POS_ERROR) ||
- alloc_group_fields(&join,group))
+ /* group data to new table */
+ if (!(curr_tmp_table=
+ exec_tmp_table2= create_tmp_table(thd,
+ &curr_join->tmp_table_param,
+ *curr_all_fields,
+ (ORDER*) 0,
+ curr_join->select_distinct &&
+ !curr_join->group_list,
+ 1, curr_join->select_options,
+ HA_POS_ERROR)))
+ DBUG_VOID_RETURN;
+ curr_join->exec_tmp_table2= exec_tmp_table2;
+ }
+ if (group_list)
+ {
+ thd->proc_info= "Creating sort index";
+ if (create_sort_index(thd, curr_join->join_tab, curr_join->group_list,
+ HA_POS_ERROR, HA_POS_ERROR) ||
+ alloc_group_fields(curr_join, curr_join->group_list))
{
- free_tmp_table(thd,tmp_table2); /* purecov: inspected */
- goto err; /* purecov: inspected */
+ DBUG_VOID_RETURN;
}
- group=0;
+ curr_join->group_list= 0;
}
+
thd->proc_info="Copying to group table";
tmp_error= -1;
- if (make_sum_func_list(&join,all_fields) ||
- (tmp_error=do_select(&join,(List<Item> *) 0,tmp_table2,0)))
+ if (make_sum_func_list(curr_join, *curr_all_fields) ||
+ (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
+ 0)))
{
- error=tmp_error;
- free_tmp_table(thd,tmp_table2);
- goto err; /* purecov: inspected */
+ error= tmp_error;
+ DBUG_VOID_RETURN;
}
- end_read_record(&join.join_tab->read_record);
- free_tmp_table(thd,tmp_table);
- join.const_tables=join.tables; // Mark free for join_free()
- tmp_table=tmp_table2;
- join.join_tab[0].table=0; // Table is freed
-
- if (change_to_use_tmp_fields(all_fields)) // No sum funcs anymore
- goto err;
- join.tmp_table_param.field_count+=join.tmp_table_param.sum_func_count;
- join.tmp_table_param.sum_func_count=0;
- }
-
- if (tmp_table->distinct)
- select_distinct=0; /* Each row is unique */
-
- join_free(&join); /* Free quick selects */
- if (select_distinct && ! group)
+ end_read_record(&curr_join->join_tab->read_record);
+ curr_join->const_tables= curr_join->tables; // Mark free for join_free()
+ curr_join->join_tab[0].table= 0; // Table is freed
+
+ // No sum funcs anymore
+ if (!items2)
+ {
+ items2= items1 + all_fields.elements;
+ if (change_to_use_tmp_fields(thd, items2,
+ tmp_fields_list2, tmp_all_fields2,
+ fields_list.elements, tmp_all_fields1))
+ DBUG_VOID_RETURN;
+ curr_join->tmp_fields_list2= tmp_fields_list2;
+ curr_join->tmp_all_fields2= tmp_all_fields2;
+ }
+ curr_fields_list= &curr_join->tmp_fields_list2;
+ curr_all_fields= &curr_join->tmp_all_fields2;
+ memcpy(ref_pointer_array, items2, ref_pointer_array_size);
+ curr_join->tmp_table_param.field_count+=
+ curr_join->tmp_table_param.sum_func_count;
+ curr_join->tmp_table_param.sum_func_count= 0;
+ }
+ if (curr_tmp_table->distinct)
+ curr_join->select_distinct=0; /* Each row is unique */
+
+ join_free(curr_join, 0); /* Free quick selects */
+ if (select_distinct && ! group_list)
{
thd->proc_info="Removing duplicates";
- if (having)
- having->update_used_tables();
- if (remove_duplicates(&join,tmp_table,fields, having))
- goto err; /* purecov: inspected */
- having=0;
- select_distinct=0;
- }
- tmp_table->reginfo.lock_type=TL_UNLOCK;
- if (make_simple_join(&join,tmp_table))
- goto err;
- calc_group_buffer(&join,group);
- count_field_types(&join.tmp_table_param,all_fields,0);
+ if (curr_join->tmp_having)
+ curr_join->tmp_having->update_used_tables();
+ if (remove_duplicates(curr_join, curr_tmp_table,
+ curr_join->fields_list, curr_join->tmp_having))
+ DBUG_VOID_RETURN;
+ curr_join->tmp_having=0;
+ curr_join->select_distinct=0;
+ }
+ curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
+ if (make_simple_join(curr_join, curr_tmp_table))
+ DBUG_VOID_RETURN;
+ calc_group_buffer(curr_join, curr_join->group_list);
+ count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
+
}
if (procedure)
{
- if (procedure->change_columns(fields) ||
- result->prepare(fields))
- goto err;
- count_field_types(&join.tmp_table_param,all_fields,0);
+ count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
}
- if (join.group || join.tmp_table_param.sum_func_count ||
+
+ if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
{
- alloc_group_fields(&join,group);
- setup_copy_fields(thd, &join.tmp_table_param,all_fields);
- if (make_sum_func_list(&join,all_fields) || thd->fatal_error)
- goto err; /* purecov: inspected */
+ alloc_group_fields(curr_join, curr_join->group_list);
+ if (!items3)
+ {
+ if (!items0)
+ init_items_ref_array();
+ items3= ref_pointer_array + (all_fields.elements*4);
+ setup_copy_fields(thd, &curr_join->tmp_table_param,
+ items3, tmp_fields_list3, tmp_all_fields3,
+ curr_fields_list->elements, *curr_all_fields);
+ tmp_table_param.save_copy_funcs= curr_join->tmp_table_param.copy_funcs;
+ tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
+ tmp_table_param.save_copy_field_end=
+ curr_join->tmp_table_param.copy_field_end;
+ curr_join->tmp_all_fields3= tmp_all_fields3;
+ curr_join->tmp_fields_list3= tmp_fields_list3;
+ }
+ else
+ {
+ curr_join->tmp_table_param.copy_funcs= tmp_table_param.save_copy_funcs;
+ curr_join->tmp_table_param.copy_field= tmp_table_param.save_copy_field;
+ curr_join->tmp_table_param.copy_field_end=
+ tmp_table_param.save_copy_field_end;
+ }
+ curr_fields_list= &tmp_fields_list3;
+ curr_all_fields= &tmp_all_fields3;
+ memcpy(ref_pointer_array, items3, ref_pointer_array_size);
+
+ if (make_sum_func_list(curr_join, *curr_all_fields) ||
+ thd->is_fatal_error)
+ DBUG_VOID_RETURN;
}
- if (group || order)
+ if (curr_join->group_list || curr_join->order)
{
DBUG_PRINT("info",("Sorting for send_fields"));
thd->proc_info="Sorting result";
/* If we have already done the group, add HAVING to sorted table */
- if (having && ! group && ! join.sort_and_group)
+ if (curr_join->tmp_having && ! curr_join->group_list &&
+ ! curr_join->sort_and_group)
{
- having->update_used_tables(); // Some tables may have been const
- JOIN_TAB *table=&join.join_tab[join.const_tables];
- table_map used_tables= join.const_table_map | table->table->map;
+ // Some tables may have been const
+ curr_join->tmp_having->update_used_tables();
+ JOIN_TAB *table= &curr_join->join_tab[const_tables];
+ table_map used_tables= curr_join->const_table_map | table->table->map;
- Item* sort_table_cond=make_cond_for_table(having,used_tables,used_tables);
+ Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
+ used_tables,
+ used_tables);
if (sort_table_cond)
{
if (!table->select)
- if (!(table->select=new SQL_SELECT))
- goto err;
+ if (!(table->select= new SQL_SELECT))
+ DBUG_VOID_RETURN;
if (!table->select->cond)
- table->select->cond=sort_table_cond;
+ table->select->cond= sort_table_cond;
else // This should never happen
- if (!(table->select->cond=new Item_cond_and(table->select->cond,
- sort_table_cond)))
- goto err;
+ if (!(table->select->cond= new Item_cond_and(table->select->cond,
+ sort_table_cond)))
+ DBUG_VOID_RETURN;
table->select_cond=table->select->cond;
table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select->cond,
"select and having"););
- having=make_cond_for_table(having,~ (table_map) 0,~used_tables);
+ curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
+ ~ (table_map) 0,
+ ~used_tables);
DBUG_EXECUTE("where",print_where(conds,"having after sort"););
}
}
- if (group)
- select_limit= HA_POS_ERROR;
- else
{
- /*
- We can abort sorting after thd->select_limit rows if we there is no
- WHERE clause for any tables after the sorted one.
- */
- JOIN_TAB *table= &join.join_tab[join.const_tables+1];
- JOIN_TAB *end_table= &join.join_tab[join.tables];
- for (; table < end_table ; table++)
+ if (group)
+ curr_join->select_limit= HA_POS_ERROR;
+ else
{
/*
- table->keyuse is set in the case there was an original WHERE clause
- on the table that was optimized away.
- table->on_expr tells us that it was a LEFT JOIN and there will be
- at least one row generated from the table.
+ We can abort sorting after thd->select_limit rows if we there is no
+ WHERE clause for any tables after the sorted one.
*/
- if (table->select_cond || (table->keyuse && !table->on_expr))
+ JOIN_TAB *table= &curr_join->join_tab[const_tables+1];
+ JOIN_TAB *end_table= &curr_join->join_tab[tables];
+ for (; table < end_table ; table++)
{
- /* We have to sort all rows */
- select_limit= HA_POS_ERROR;
- break;
+ /*
+ table->keyuse is set in the case there was an original WHERE clause
+ on the table that was optimized away.
+ table->on_expr tells us that it was a LEFT JOIN and there will be
+ at least one row generated from the table.
+ */
+ if (table->select_cond || (table->keyuse && !table->on_expr))
+ {
+ /* We have to sort all rows */
+ curr_join->select_limit= HA_POS_ERROR;
+ break;
+ }
}
}
+ if (create_sort_index(thd, &curr_join->join_tab[curr_join->const_tables],
+ curr_join->group_list ?
+ curr_join->group_list : curr_join->order,
+ curr_join->select_limit, unit->select_limit_cnt))
+ DBUG_VOID_RETURN;
}
- if (create_sort_index(&join.join_tab[join.const_tables],
- group ? group : order,
- select_limit,
- thd->select_limit))
- goto err; /* purecov: inspected */
}
- join.having=having; // Actually a parameter
+ curr_join->having= curr_join->tmp_having;
thd->proc_info="Sending data";
- error=do_select(&join,&fields,NULL,procedure);
+ error= thd->net.report_error ||
+ do_select(curr_join, curr_fields_list, NULL, procedure);
+ DBUG_VOID_RETURN;
+}
-err:
- thd->limit_found_rows = join.send_records;
- thd->examined_row_count = join.examined_rows;
- thd->proc_info="end";
- join.lock=0; // It's faster to unlock later
- join_free(&join);
- thd->proc_info="end2"; // QQ
- if (tmp_table)
- free_tmp_table(thd,tmp_table);
- thd->proc_info="end3"; // QQ
+/*
+ Clean up join. Return error that hold JOIN.
+*/
+
+int
+JOIN::cleanup(THD *thd)
+{
+ DBUG_ENTER("JOIN::cleanup");
+
+ select_lex->join= 0;
+
+ if (tmp_join)
+ memcpy(this, tmp_join, sizeof(tmp_join));
+
+
+ lock=0; // It's faster to unlock later
+ join_free(this, 1);
+ if (exec_tmp_table1)
+ free_tmp_table(thd, exec_tmp_table1);
+ if (exec_tmp_table2)
+ free_tmp_table(thd, exec_tmp_table2);
delete select;
delete_dynamic(&keyuse);
delete procedure;
- thd->proc_info="end4"; // QQ
+ for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit();
+ unit != 0;
+ unit= unit->next_unit())
+ {
+ error|= unit->cleanup();
+ }
DBUG_RETURN(error);
}
+int
+mysql_select(THD *thd, Item ***rref_pointer_array,
+ TABLE_LIST *tables, uint wild_num, List<Item> &fields,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, ulong select_options,
+ select_result *result, SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex, bool fake_select_lex,
+ bool tables_and_fields_initied)
+{
+ int err;
+ bool free_join= 1;
+ DBUG_ENTER("mysql_select");
+
+ JOIN *join;
+ if (!fake_select_lex && select_lex->join != 0)
+ {
+ //here is EXPLAIN of subselect or derived table
+ join= select_lex->join;
+ join->result= result;
+ if (!join->procedure && result->prepare(join->fields_list, unit))
+ {
+ DBUG_RETURN(-1);
+ }
+ join->select_options= select_options;
+ free_join= 0;
+ }
+ else
+ {
+ join= new JOIN(thd, fields, select_options, result);
+ thd->proc_info="init";
+ thd->used_tables=0; // Updated by setup_fields
+
+ if (join->prepare(rref_pointer_array, tables, wild_num,
+ conds, og_num, order, group, having, proc_param,
+ select_lex, unit, fake_select_lex,
+ tables_and_fields_initied))
+ {
+ DBUG_RETURN(-1);
+ }
+ }
+
+ if ((err= join->optimize()))
+ {
+ if (err == -1)
+ DBUG_RETURN(join->error);
+ DBUG_ASSERT(err == 1);
+ goto err; // 1
+ }
+
+ if (thd->net.report_error)
+ goto err;
+
+ join->exec();
+
+err:
+ if (free_join)
+ {
+ JOIN *curr_join= (join->need_tmp&&join->tmp_join?
+ (join->tmp_join->error=join->error,join->tmp_join):
+ join);
+
+ thd->limit_found_rows= curr_join->send_records;
+ thd->examined_row_count= curr_join->examined_rows;
+ thd->proc_info="end";
+ err= (fake_select_lex ? curr_join->error : join->cleanup(thd));
+ if (thd->net.report_error)
+ err= -1;
+ delete join;
+ DBUG_RETURN(err);
+ }
+ DBUG_RETURN(join->error);
+}
+
/*****************************************************************************
Create JOIN_TABS, make a guess about the table types,
Approximate how many records will be used in each table
@@ -1119,8 +1505,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
}
if (conds || outer_join)
- if (update_ref_and_keys(join->thd,keyuse_array,stat,join->tables,
- conds,~outer_join))
+ if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
+ conds, ~outer_join, join->select_lex))
DBUG_RETURN(1);
/* Read tables with 0 or 1 rows (system tables) */
@@ -1516,9 +1902,10 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
case Item_func::OPTIMIZE_NONE:
break;
case Item_func::OPTIMIZE_KEY:
- if (cond_func->key_item()->type() == Item::FIELD_ITEM)
+ if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM)
add_key_field(key_fields,*and_level,
- ((Item_field*) (cond_func->key_item()))->field,
+ ((Item_field*) (cond_func->key_item()->real_item()))
+ ->field,
0,(Item*) 0,usable_tables);
break;
case Item_func::OPTIMIZE_OP:
@@ -1526,18 +1913,20 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
cond_func->functype() == Item_func::EQUAL_FUNC);
- if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
{
add_key_field(key_fields,*and_level,
- ((Item_field*) (cond_func->arguments()[0]))->field,
+ ((Item_field*) (cond_func->arguments()[0])->real_item())
+ ->field,
equal_func,
(cond_func->arguments()[1]),usable_tables);
}
- if (cond_func->arguments()[1]->type() == Item::FIELD_ITEM &&
+ if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
cond_func->functype() != Item_func::LIKE_FUNC)
{
add_key_field(key_fields,*and_level,
- ((Item_field*) (cond_func->arguments()[1]))->field,
+ ((Item_field*) (cond_func->arguments()[1])->real_item())
+ ->field,
equal_func,
(cond_func->arguments()[0]),usable_tables);
}
@@ -1545,10 +1934,11 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
}
case Item_func::OPTIMIZE_NULL:
/* column_name IS [NOT] NULL */
- if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
{
add_key_field(key_fields,*and_level,
- ((Item_field*) (cond_func->arguments()[0]))->field,
+ ((Item_field*) (cond_func->arguments()[0])->real_item())
+ ->field,
cond_func->functype() == Item_func::ISNULL_FUNC,
new Item_null, usable_tables);
}
@@ -1701,7 +2091,8 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
static bool
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
- uint tables, COND *cond, table_map normal_tables)
+ uint tables, COND *cond, table_map normal_tables,
+ SELECT_LEX *select_lex)
{
uint and_level,i,found_eq_constant;
@@ -1729,7 +2120,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
add_key_part(keyuse,field);
}
- if (thd->lex.select->ftfunc_list.elements)
+ if (select_lex->ftfunc_list->elements)
{
add_ft_keys(keyuse,join_tab,cond,normal_tables);
}
@@ -1829,7 +2220,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
ha_rows rec;
double tmp;
- THD *thd= current_thd;
+ THD *thd= join->thd;
if (!rest_tables)
{
@@ -2118,7 +2509,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
join->positions[idx].table= s;
if (!best_key && idx == join->const_tables &&
s->table == join->sort_by_table &&
- join->thd->select_limit >= records)
+ join->unit->select_limit_cnt >= records)
join->sort_by_table= (TABLE*) 1; // Must use temporary table
/*
@@ -2372,7 +2763,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
(char*) key_buff : 0,
keyinfo->key_part[i].length,
keyuse->val);
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
{
return TRUE;
}
@@ -2480,8 +2871,8 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->sum_funcs=0;
join->send_records=(ha_rows) 0;
join->group=0;
- join->do_send_rows = 1;
- join->row_limit=join->thd->select_limit;
+ join->row_limit=join->unit->select_limit_cnt;
+ join->do_send_rows = (join->row_limit) ? 1 : 0;
join_tab->cache.buff=0; /* No cacheing */
join_tab->table=tmp_table;
@@ -2598,7 +2989,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if ((tab->keys & ~ tab->const_keys && i > 0) ||
(tab->const_keys && i == join->const_tables &&
- join->thd->select_limit < join->best_positions[i].records_read &&
+ join->unit->select_limit_cnt <
+ join->best_positions[i].records_read &&
!(join->select_options & OPTION_FOUND_ROWS)))
{
/* Join with outer join condition */
@@ -2609,7 +3001,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
- join->thd->select_limit)) < 0)
+ join->unit->select_limit_cnt)) < 0)
DBUG_RETURN(1); // Impossible range
sel->cond=orig_cond;
}
@@ -2651,7 +3043,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
static void
-make_join_readinfo(JOIN *join,uint options)
+make_join_readinfo(JOIN *join, uint options)
{
uint i;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
@@ -2832,7 +3224,7 @@ bool error_if_full_join(JOIN *join)
static void
-join_free(JOIN *join)
+join_free(JOIN *join, bool full)
{
JOIN_TAB *tab,*end;
DBUG_ENTER("join_free");
@@ -2845,25 +3237,51 @@ join_free(JOIN *join)
*/
if (join->tables > join->const_tables) // Test for not-const tables
free_io_cache(join->table[join->const_tables]);
- for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
+ if (join->select_lex->dependent && !full)
{
- delete tab->select;
- delete tab->quick;
- x_free(tab->cache.buff);
- if (tab->table)
+ for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
{
- if (tab->table->key_read)
+ if (tab->table)
{
- tab->table->key_read=0;
- tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ if (tab->table->key_read)
+ {
+ tab->table->key_read= 0;
+ tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ /* Don't free index if we are using read_record */
+ if (!tab->read_record.table)
+ tab->table->file->index_end();
}
- /* Don't free index if we are using read_record */
- if (!tab->read_record.table)
- tab->table->file->index_end();
}
- end_read_record(&tab->read_record);
}
- join->table=0;
+ else
+ {
+ for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
+ {
+ delete tab->select;
+ delete tab->quick;
+ x_free(tab->cache.buff);
+ tab->cache.buff= 0;
+ if (tab->table)
+ {
+ if (tab->table->key_read)
+ {
+ tab->table->key_read= 0;
+ tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ /* Don't free index if we are using read_record */
+ if (!tab->read_record.table)
+ tab->table->file->index_end();
+ /*
+ We need to reset this for next select
+ (Tested in part_of_refkey)
+ */
+ tab->table->reginfo.join_tab= 0;
+ }
+ end_read_record(&tab->read_record);
+ }
+ join->table= 0;
+ }
}
/*
We are not using tables anymore
@@ -2875,9 +3293,12 @@ join_free(JOIN *join)
mysql_unlock_read_tables(join->thd, join->lock);// Don't free join->lock
join->lock=0;
}
- join->group_fields.delete_elements();
- join->tmp_table_param.copy_funcs.delete_elements();
- join->tmp_table_param.cleanup();
+ if (full)
+ {
+ join->group_fields.delete_elements();
+ join->tmp_table_param.copy_funcs.delete_elements();
+ join->tmp_table_param.cleanup();
+ }
DBUG_VOID_RETURN;
}
@@ -3080,18 +3501,20 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
static int
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
List<Item> &fields, bool send_row, uint select_options,
- const char *info, Item *having, Procedure *procedure)
+ const char *info, Item *having, Procedure *procedure,
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("return_zero_rows");
if (select_options & SELECT_DESCRIBE)
- {
- describe_info(join, info);
+ {
+ select_describe(join, false, false, false, info);
DBUG_RETURN(0);
}
+
if (procedure)
{
- if (result->prepare(fields)) // This hasn't been done yet
+ if (result->prepare(fields, unit)) // This hasn't been done yet
DBUG_RETURN(-1);
}
if (send_row)
@@ -3199,8 +3622,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
if ((tmp2=new COND_CMP(and_father,func)))
save_list->push_back(tmp2);
}
- func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(),
- func->arguments()[1]->result_type()));
+ func->set_cmp_func();
}
}
else if (left_item->eq(field,0) && right_item != value)
@@ -3220,8 +3642,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
if ((tmp2=new COND_CMP(and_father,func)))
save_list->push_back(tmp2);
}
- func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(),
- func->arguments()[1]->result_type()));
+ func->set_cmp_func();
}
}
}
@@ -3408,7 +3829,9 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
(thd->options & OPTION_AUTO_IS_NULL) &&
thd->insert_id())
{
+#ifndef EMBEDDED_LIBRARY
query_cache_abort(&thd->net);
+#endif
COND *new_cond;
if ((new_cond= new Item_func_eq(args[0],
new Item_int("last_insert_id()",
@@ -3416,7 +3839,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
21))))
{
cond=new_cond;
- cond->fix_fields(thd,0);
+ cond->fix_fields(thd, 0, &cond);
}
thd->insert_id(0); // Clear for next request
}
@@ -3430,7 +3853,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
{
cond=new_cond;
- cond->fix_fields(thd,0);
+ cond->fix_fields(thd, 0, &cond);
}
}
}
@@ -3556,17 +3979,18 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item_sum::AVG_FUNC: /* Place for sum & count */
if (group)
return new Field_string(sizeof(double)+sizeof(longlong),
- maybe_null, item->name,table,1);
+ maybe_null, item->name,table,&my_charset_bin);
else
return new Field_double(item_sum->max_length,maybe_null,
item->name, table, item_sum->decimals);
- case Item_sum::STD_FUNC: /* Place for sum & count */
+ case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
+ case Item_sum::STD_FUNC:
if (group)
return new Field_string(sizeof(double)*2+sizeof(longlong),
- maybe_null, item->name,table,1);
+ maybe_null, item->name,table,&my_charset_bin);
else
return new Field_double(item_sum->max_length, maybe_null,
- item->name,table,item_sum->decimals);
+ item->name,table,item_sum->decimals);
case Item_sum::UNIQUE_USERS_FUNC:
return new Field_long(9,maybe_null,item->name,table,1);
default:
@@ -3580,12 +4004,16 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case STRING_RESULT:
if (item_sum->max_length > 255)
return new Field_blob(item_sum->max_length,maybe_null,
- item->name,table,item->binary);
+ item->name,table,item->charset());
return new Field_string(item_sum->max_length,maybe_null,
- item->name,table,item->binary);
+ item->name,table,item->charset());
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
}
}
- thd->fatal_error=1;
+ thd->fatal_error();
return 0; // Error
}
case Item::FIELD_ITEM:
@@ -3609,6 +4037,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
case Item::FIELD_STD_ITEM:
+ case Item::SUBSELECT_ITEM:
/* The following can only happen with 'CREATE TABLE ... SELECT' */
case Item::PROC_ITEM:
case Item::INT_ITEM:
@@ -3633,10 +4062,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case STRING_RESULT:
if (item->max_length > 255)
new_field= new Field_blob(item->max_length,maybe_null,
- item->name,table,item->binary);
+ item->name,table,item->str_value.charset());
else
new_field= new Field_string(item->max_length,maybe_null,
- item->name,table,item->binary);
+ item->name,table,item->str_value.charset());
+ break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
break;
}
if (copy_func && item->is_result_field())
@@ -3661,7 +4094,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- bool allow_distinct_limit, ulong select_options)
+ ulong select_options, ha_rows rows_limit)
{
TABLE *table;
uint i,field_count,reclength,null_count,null_pack_length,
@@ -3681,9 +4114,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
uint temp_pool_slot=MY_BIT_NONE;
DBUG_ENTER("create_tmp_table");
- DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d allow_distinct_limit: %d group: %d",
+ DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
(int) distinct, (int) save_sum_fields,
- (int) allow_distinct_limit,test(group)));
+ (ulong) rows_limit,test(group)));
statistic_increment(created_tmp_tables, &LOCK_status);
@@ -3759,6 +4192,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->blob_ptr_size=mi_portable_sizeof_char_ptr;
table->map=1;
table->tmp_table= TMP_TABLE;
+ table->derived_select_number= 0;
table->db_low_byte_first=1; // True for HEAP and MyISAM
table->temp_pool_slot = temp_pool_slot;
table->copy_blobs= 1;
@@ -3833,7 +4267,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
not_all_columns || group !=0);
if (!new_field)
{
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
goto err; // Got OOM
continue; // Some kindf of const item
}
@@ -4003,6 +4437,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->usable_key_parts=keyinfo->key_parts= param->group_parts;
keyinfo->key_length=0;
keyinfo->rec_per_key=0;
+ keyinfo->algorithm= HA_KEY_ALG_UNDEF;
for (; group ; group=group->next,key_part_info++)
{
Field *field=(*group->item)->tmp_table_field();
@@ -4057,13 +4492,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_pack_length-=hidden_null_pack_length;
keyinfo->key_parts= ((field_count-param->hidden_field_count)+
test(null_pack_length));
- if (allow_distinct_limit)
- {
- set_if_smaller(table->max_rows,thd->select_limit);
- param->end_write_records=thd->select_limit;
- }
- else
- param->end_write_records= HA_POS_ERROR;
+ set_if_smaller(table->max_rows, rows_limit);
+ param->end_write_records= rows_limit;
table->distinct=1;
table->keys=1;
if (blob_count)
@@ -4079,6 +4509,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
keyinfo->key_length=(uint16) reclength;
keyinfo->name=(char*) "tmp";
+ keyinfo->algorithm= HA_KEY_ALG_UNDEF;
if (null_pack_length)
{
key_part_info->null_bit=0;
@@ -4089,7 +4520,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
(uchar*) 0,
(uint) 0,
Field::NONE,
- NullS, table, (bool) 1);
+ NullS, table, &my_charset_bin);
key_part_info->key_type=FIELDFLAG_BINARY;
key_part_info->type= HA_KEYTYPE_BINARY;
key_part_info++;
@@ -4110,7 +4541,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
0 : FIELDFLAG_BINARY;
}
}
- if (thd->fatal_error) // If end of memory
+ if (thd->is_fatal_error) // If end of memory
goto err; /* purecov: inspected */
table->db_record_offset=1;
if (table->db_type == DB_TYPE_MYISAM)
@@ -4161,7 +4592,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
if (table->keys)
{ // Get keys for ni_create
bool using_unique_constraint=0;
- MI_KEYSEG *seg= (MI_KEYSEG*) sql_calloc(sizeof(*seg) *
+ HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
keyinfo->key_parts);
if (!seg)
goto err;
@@ -4198,7 +4629,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
{
Field *field=keyinfo->key_part[i].field;
seg->flag= 0;
- seg->language= MY_CHARSET_CURRENT;
+ seg->language= field->charset()->number;
seg->length= keyinfo->key_part[i].length;
seg->start= keyinfo->key_part[i].offset;
if (field->flags & BLOB_FLAG)
@@ -4237,6 +4668,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
}
MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
+
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
OPTION_BIG_TABLES)
create_info.data_file_length= ~(ulonglong) 0;
@@ -4295,12 +4727,11 @@ free_tmp_table(THD *thd, TABLE *entry)
* If a HEAP table gets full, create a MyISAM table and copy all rows to this
*/
-bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
- bool ignore_last_dupp_key_error)
+bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
+ int error, bool ignore_last_dupp_key_error)
{
TABLE new_table;
const char *save_proc_info;
- THD *thd=current_thd;
int write_err;
DBUG_ENTER("create_myisam_from_heap");
@@ -4380,7 +4811,7 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
static int
do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
- int error;
+ int error= 0;
JOIN_TAB *join_tab;
int (*end_select)(JOIN *, struct st_join_table *,bool);
DBUG_ENTER("do_select");
@@ -4396,7 +4827,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
empty_record(table);
}
- join->tmp_table=table; /* Save for easy recursion */
+ join->tmp_table= table; /* Save for easy recursion */
join->fields= fields;
/* Set up select_end */
@@ -4441,30 +4872,29 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
join->send_records=0;
if (join->tables == join->const_tables)
{
- if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
- error=(*end_select)(join,join_tab,1);
+ if (!join->select_lex->dependent ||
+ ((!join->conds || join->conds->val_int()) &&
+ (!join->having || join->having->val_int())))
+ {
+ if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
+ error=(*end_select)(join,join_tab,1);
+ }
}
else
{
- error=sub_select(join,join_tab,0);
+ error= sub_select(join,join_tab,0);
if (error >= 0)
- error=sub_select(join,join_tab,1);
+ error= sub_select(join,join_tab,1);
if (error == -3)
- error=0; /* select_limit used */
+ error= 0; /* select_limit used */
}
- /* Return 1 if error is sent; -1 if error should be sent */
- if (error < 0)
- {
- join->result->send_error(0,NullS); /* purecov: inspected */
- error=1; // Error sent
- }
- else
+ if (error >= 0)
{
error=0;
if (!table) // If sending data to client
{
- join_free(join); // Unlock all cursors
+ join_free(join, 0); // Unlock all cursors
if (join->result->send_eof())
error= 1; // Don't send error
}
@@ -4486,7 +4916,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (error == -1)
table->file->print_error(my_errno,MYF(0));
}
- DBUG_RETURN(error);
+ DBUG_RETURN(error || join->thd->net.report_error);
}
@@ -5132,7 +5562,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
error=join->result->send_data(*join->fields);
if (error)
DBUG_RETURN(-1); /* purecov: inspected */
- if (++join->send_records >= join->thd->select_limit &&
+ if (++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (join->select_options & OPTION_FOUND_ROWS)
@@ -5161,8 +5591,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
else
{
- join->do_send_rows=0;
- join->thd->select_limit = HA_POS_ERROR;
+ join->do_send_rows= 0;
+ join->unit->select_limit= HA_POS_ERROR;
DBUG_RETURN(0);
}
}
@@ -5225,14 +5655,13 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
join->send_records++;
DBUG_RETURN(0);
}
- if (!error &&
- ++join->send_records >= join->thd->select_limit &&
+ if (!error && ++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
DBUG_RETURN(-3); // Abort nicely
join->do_send_rows=0;
- join->thd->select_limit = HA_POS_ERROR;
+ join->unit->select_limit_cnt = HA_POS_ERROR;
}
}
}
@@ -5303,7 +5732,8 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (error == HA_ERR_FOUND_DUPP_KEY ||
error == HA_ERR_FOUND_DUPP_UNIQUE)
goto end;
- if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
+ if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
+ error,1))
DBUG_RETURN(-1); // Not a table_is_full error
table->uniques=0; // To ensure rows are the same
}
@@ -5313,7 +5743,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (!(join->select_options & OPTION_FOUND_ROWS))
DBUG_RETURN(-3);
join->do_send_rows=0;
- join->thd->select_limit = HA_POS_ERROR;
+ join->unit->select_limit_cnt = HA_POS_ERROR;
DBUG_RETURN(0);
}
}
@@ -5349,6 +5779,9 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
Item *item= *group->item;
item->save_org_in_field(group->field);
+#ifdef EMBEDDED_LIBRARY
+ join->thd->net.last_errno= 0;
+#endif
/* Store in the used key if the field was 0 */
if (item->maybe_null)
group->buff[-1]=item->null_value ? 1 : 0;
@@ -5380,7 +5813,8 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
copy_funcs(join->tmp_table_param.items_to_copy);
if ((error=table->file->write_row(table->record[0])))
{
- if (create_myisam_from_heap(table, &join->tmp_table_param, error, 0))
+ if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
+ error, 0))
DBUG_RETURN(-1); // Not a table_is_full error
/* Change method to update rows */
table->file->index_init(0);
@@ -5474,7 +5908,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
if ((error=table->file->write_row(table->record[0])))
{
- if (create_myisam_from_heap(table, &join->tmp_table_param,
+ if (create_myisam_from_heap(join->thd, table,
+ &join->tmp_table_param,
error, 0))
DBUG_RETURN(-1); // Not a table_is_full error
}
@@ -5636,6 +6071,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
static Item *
part_of_refkey(TABLE *table,Field *field)
{
+ if (!table->reginfo.join_tab)
+ return (Item*) 0; // field from outer non-select (UPDATE,...)
+
uint ref_parts=table->reginfo.join_tab->ref.key_parts;
if (ref_parts)
{
@@ -5714,6 +6152,69 @@ static uint find_shortest_key(TABLE *table, key_map usable_keys)
return best;
}
+/*
+ SYNOPSIS
+ is_subkey()
+ key_part - first key parts
+ ref_key_part - second key parts
+ ref_key_part_end - last+1 part of the second key
+ DESCRIPTION
+ Test if a second key is the subkey of the first one.
+ NOTE
+ Second key MUST be shorter than the first one.
+ RETURN
+ 1 - is the subkey
+ 0 - otherwise
+*/
+
+inline bool
+is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part,
+ KEY_PART_INFO *ref_key_part_end)
+{
+ for (; ref_key_part < ref_key_part_end; key_part++, ref_key_part++)
+ if (!key_part->field->eq(ref_key_part->field))
+ return 0;
+ return 1;
+}
+
+/*
+ SYNOPSIS
+ test_if_subkey()
+ ref - number of key, used for WHERE clause
+ usable_keys - keys for testing
+ DESCRIPTION
+ Test if we can use one of the 'usable_keys' instead of 'ref' key.
+ RETURN
+ MAX_KEY - if we can't use other key
+ the number of found key - otherwise
+*/
+
+static uint
+test_if_subkey(ORDER *order, TABLE *table, uint ref, key_map usable_keys)
+{
+ uint nr;
+ uint min_length= (uint) ~0;
+ uint best= MAX_KEY;
+ uint not_used;
+ KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part;
+ uint ref_key_parts= table->key_info[ref].key_parts;
+ KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts;
+
+ for (nr= 0; usable_keys; usable_keys>>= 1, nr++)
+ {
+ if ((usable_keys & 1) &&
+ table->key_info[nr].key_length < min_length &&
+ table->key_info[nr].key_parts >= ref_key_parts &&
+ is_subkey(table->key_info[nr].key_part, ref_key_part,
+ ref_key_part_end) &&
+ test_if_order_by_key(order, table, nr, &not_used))
+ {
+ min_length= table->key_info[nr].key_length;
+ best= nr;
+ }
+ }
+ return best;
+}
/*
Test if we can skip the ORDER BY by using an index.
@@ -5761,6 +6262,27 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
int order_direction;
uint used_key_parts;
+ if (!(usable_keys & ((key_map) 1 << ref_key)))
+ {
+ /*
+ We come here when ref_key is not among usable_keys
+ */
+ uint a;
+ if ((a= test_if_subkey(order, table, ref_key, usable_keys)) < MAX_KEY)
+ {
+ if (tab->ref.key >= 0)
+ {
+ tab->ref.key= a;
+ table->file->index_init(a);
+ }
+ else
+ {
+ select->quick->index= a;
+ select->quick->init();
+ }
+ ref_key= a;
+ }
+ }
/* Check if we get the rows in requested sorted order by using the key */
if ((usable_keys & ((key_map) 1 << ref_key)) &&
(order_direction = test_if_order_by_key(order,table,ref_key,
@@ -5851,16 +6373,36 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
-/*****************************************************************************
+/*
If not selecting by given key, create an index how records should be read
- return: 0 ok
- -1 some fatal error
- 1 no records
-*****************************************************************************/
+
+ SYNOPSIS
+ create_sort_index()
+ thd Thread handler
+ tab Table to sort (in join structure)
+ order How table should be sorted
+ filesort_limit Max number of rows that needs to be sorted
+ select_limit Max number of rows in final output
+ Used to decide if we should use index or not
+
+
+ IMPLEMENTATION
+ - If there is an index that can be used, 'tab' is modified to use
+ this index.
+ - If no index, create with filesort() an index file that can be used to
+ retrieve rows in order (should be done with 'read_record').
+ The sorted data is stored in tab->table and will be freed when calling
+ free_io_cache(tab->table).
+
+ RETURN VALUES
+ 0 ok
+ -1 Some fatal error
+ 1 No records
+*/
static int
-create_sort_index(JOIN_TAB *tab, ORDER *order, ha_rows filesort_limit,
- ha_rows select_limit)
+create_sort_index(THD *thd, JOIN_TAB *tab, ORDER *order,
+ ha_rows filesort_limit, ha_rows select_limit)
{
SORT_FIELD *sortorder;
uint length;
@@ -5904,8 +6446,8 @@ create_sort_index(JOIN_TAB *tab, ORDER *order, ha_rows filesort_limit,
}
if (table->tmp_table)
table->file->info(HA_STATUS_VARIABLE); // Get record count
- table->found_records=filesort(table,sortorder,length,
- select, 0L, filesort_limit, &examined_rows);
+ table->found_records=filesort(thd, table,sortorder, length,
+ select, filesort_limit, &examined_rows);
tab->records=table->found_records; // For SQL_CALC_ROWS
delete select; // filesort did select
tab->select=0;
@@ -6004,7 +6546,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
int error;
ulong reclength,offset;
uint field_count;
- THD *thd= current_thd;
+ THD *thd= join->thd;
DBUG_ENTER("remove_duplicates");
entry->reginfo.lock_type=TL_WRITE;
@@ -6021,7 +6563,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
if (!field_count)
{ // only const items
- join->thd->select_limit=1; // Only send first row
+ join->unit->select_limit_cnt= 1; // Only send first row
DBUG_RETURN(0);
}
Field **first_field=entry->field+entry->fields - field_count;
@@ -6158,8 +6700,10 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
(uint) (field_count*sizeof(*field_lengths)),
NullS))
DBUG_RETURN(1);
- if (hash_init(&hash, (uint) file->records, 0, key_length,
- (hash_get_key) 0, 0, 0))
+
+ // BAR TODO: this must be fixed to use charset from "table" argument
+ if (hash_init(&hash, default_charset_info, (uint) file->records, 0,
+ key_length,(hash_get_key) 0, 0, 0))
{
my_free((char*) key_buffer,MYF(0));
DBUG_RETURN(1);
@@ -6404,12 +6948,14 @@ store_record_in_cache(JOIN_CACHE *cache)
{
if (last_record)
{
- copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*));
+ copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*),
+ copy->blob_field->charset());
pos+=copy->length+sizeof(char*);
}
else
{
- copy->blob_field->get_image((char*) pos,copy->length); // blob length
+ copy->blob_field->get_image((char*) pos,copy->length, // blob length
+ copy->blob_field->charset());
memcpy(pos+copy->length,copy->str,copy->blob_length); // Blob data
pos+=copy->length+copy->blob_length;
}
@@ -6466,7 +7012,8 @@ read_cached_record(JOIN_TAB *tab)
{
if (last_record)
{
- copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*));
+ copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*),
+ copy->blob_field->charset());
pos+=copy->length+sizeof(char*);
}
else
@@ -6531,73 +7078,89 @@ cp_buffer_from_ref(TABLE_REF *ref)
*/
static int
-find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
+find_order_in_list(THD *thd, Item **ref_pointer_array,
+ TABLE_LIST *tables,ORDER *order, List<Item> &fields,
List<Item> &all_fields)
{
if ((*order->item)->type() == Item::INT_ITEM)
{ /* Order by position */
Item *item=0;
- List_iterator<Item> li(fields);
- for (uint count= (uint) ((Item_int*) (*order->item))->value ;
- count-- && (item=li++) ;) ;
- if (!item)
+ uint count= (uint) ((Item_int*) (*order->item))->value;
+ if (count > fields.elements)
{
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
MYF(0),(*order->item)->full_name(),
thd->where);
return 1;
}
- order->item=li.ref();
- order->in_field_list=1;
+ order->item= ref_pointer_array + count-1;
+ order->in_field_list= 1;
return 0;
}
- const char *save_where=thd->where;
- thd->where=0; // No error if not found
- Item **item=find_item_in_list(*order->item,fields);
- thd->where=save_where;
+ uint counter;
+ Item **item= find_item_in_list(*order->item, fields, &counter,
+ IGNORE_ERRORS);
if (item)
{
- order->item=item; // use it
+ order->item= ref_pointer_array + counter;
order->in_field_list=1;
return 0;
}
order->in_field_list=0;
- if ((*order->item)->fix_fields(thd,tables) || thd->fatal_error)
+ Item *it= *order->item;
+ if (it->fix_fields(thd, tables, order->item) || it->check_cols(1) ||
+ thd->is_fatal_error)
return 1; // Wrong field
- all_fields.push_front(*order->item); // Add new field to field list
- order->item=(Item**) all_fields.head_ref();
+ uint el= all_fields.elements;
+ all_fields.push_front(it); // Add new field to field list
+ ref_pointer_array[el]= it;
+ order->item= ref_pointer_array + el;
return 0;
}
+/*
+ Allocate array of references to address all_fileds list elements
+*/
+
+int setup_ref_array(THD* thd, Item ***rref_pointer_array, uint elements)
+{
+ if (*rref_pointer_array)
+ return 0;
+
+ return (*rref_pointer_array=
+ (Item **)thd->alloc(sizeof(Item*) * elements * 5)) == 0;
+}
/*
Change order to point at item in select list. If item isn't a number
and doesn't exits in the select list, add it the the field list.
*/
-int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order)
+int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, List<Item> &all_fields, ORDER *order)
{
thd->where="order clause";
for (; order; order=order->next)
{
- if (find_order_in_list(thd,tables,order,fields,all_fields))
+ if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
+ all_fields))
return 1;
}
return 0;
}
-static int
-setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order, bool *hidden_group_fields)
+int
+setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, List<Item> &all_fields, ORDER *order,
+ bool *hidden_group_fields)
{
*hidden_group_fields=0;
if (!order)
return 0; /* Everything is ok */
- if (thd->sql_mode & MODE_ONLY_FULL_GROUP_BY)
+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
{
Item *item;
List_iterator<Item> li(fields);
@@ -6609,7 +7172,8 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->where="group statement";
for (; order; order=order->next)
{
- if (find_order_in_list(thd,tables,order,fields,all_fields))
+ if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
+ all_fields))
return 1;
(*order->item)->marker=1; /* Mark found */
if ((*order->item)->with_sum_func)
@@ -6619,7 +7183,7 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
return 1;
}
}
- if (thd->sql_mode & MODE_ONLY_FULL_GROUP_BY)
+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
{
/* Don't allow one to use fields that is not used in GROUP BY */
Item *item;
@@ -6653,17 +7217,17 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER("setup_new_fields");
thd->set_query_id=1; // Not really needed, but...
- thd->where=0; // Don't give error
- for (; new_field ; new_field=new_field->next)
+ uint counter;
+ for (; new_field ; new_field= new_field->next)
{
- if ((item=find_item_in_list(*new_field->item,fields)))
+ if ((item= find_item_in_list(*new_field->item, fields, &counter,
+ IGNORE_ERRORS)))
new_field->item=item; /* Change to shared Item */
else
{
thd->where="procedure list";
- if ((*new_field->item)->fix_fields(thd,tables))
+ if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
DBUG_RETURN(1); /* purecov: inspected */
- thd->where=0;
all_fields.push_front(*new_field->item);
new_field->item=all_fields.head_ref();
}
@@ -6902,47 +7466,77 @@ test_if_group_changed(List<Item_buff> &list)
/*
Setup copy_fields to save fields at start of new group
- Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
- Change old item_field to use a new field with points at saved fieldvalue
- This function is only called before use of send_fields
+
+ setup_copy_fields()
+ thd - THD pointer
+ param - temporary table parameters
+ ref_pointer_array - array of pointers to top elements of filed list
+ res_selected_fields - new list of items of select item list
+ res_all_fields - new list of all items
+ elements - number of elements in select item list
+ all_fields - all fields list
+
+ DESCRIPTION
+ Setup copy_fields to save fields at start of new group
+ Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
+ Change old item_field to use a new field with points at saved fieldvalue
+ This function is only called before use of send_fields
+
+ RETURN
+ 0 - ok
+ !=0 - error
*/
bool
-setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
+setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
+ Item **ref_pointer_array,
+ List<Item> &res_selected_fields, List<Item> &res_all_fields,
+ uint elements, List<Item> &all_fields)
{
Item *pos;
- List_iterator<Item> li(fields);
+ List_iterator_fast<Item> li(all_fields);
Copy_field *copy;
DBUG_ENTER("setup_copy_fields");
+ res_selected_fields.empty();
+ res_all_fields.empty();
+ List_iterator_fast<Item> itr(res_all_fields);
+
+ uint i, border= all_fields.elements - elements;
if (!(copy=param->copy_field= new Copy_field[param->field_count]))
goto err2;
param->copy_funcs.empty();
- while ((pos=li++))
+ for (i= 0; (pos= li++); i++)
{
if (pos->type() == Item::FIELD_ITEM)
{
- Item_field *item=(Item_field*) pos;
+ Item_field *item;
+ if (!(item= new Item_field(thd, *((Item_field*) pos))))
+ goto err;
+ pos= item;
if (item->field->flags & BLOB_FLAG)
{
- if (!(pos=new Item_copy_string(pos)))
+ if (!(pos= new Item_copy_string(pos)))
goto err;
- VOID(li.replace(pos));
if (param->copy_funcs.push_back(pos))
goto err;
- continue;
}
-
- /* set up save buffer and change result_field to point at saved value */
- Field *field= item->field;
- item->result_field=field->new_field(&thd->mem_root,field->table);
- char *tmp=(char*) sql_alloc(field->pack_length()+1);
- if (!tmp)
- goto err;
- copy->set(tmp, item->result_field);
- item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
- copy++;
+ else
+ {
+ /*
+ set up save buffer and change result_field to point at
+ saved value
+ */
+ Field *field= item->field;
+ item->result_field=field->new_field(&thd->mem_root,field->table);
+ char *tmp=(char*) sql_alloc(field->pack_length()+1);
+ if (!tmp)
+ goto err;
+ copy->set(tmp, item->result_field);
+ item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
+ copy++;
+ }
}
else if ((pos->type() == Item::FUNC_ITEM ||
pos->type() == Item::COND_ITEM) &&
@@ -6956,12 +7550,18 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
*/
if (!(pos=new Item_copy_string(pos)))
goto err;
- VOID(li.replace(pos));
if (param->copy_funcs.push_back(pos))
goto err;
}
+ res_all_fields.push_back(pos);
+ ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
+ pos;
}
param->copy_field_end= copy;
+
+ for (i= 0; i < border; i++)
+ itr++;
+ itr.sublist(res_selected_fields, elements);
DBUG_RETURN(0);
err:
@@ -7026,51 +7626,78 @@ make_sum_func_list(JOIN *join,List<Item> &fields)
/*
- Change all funcs and sum_funcs to fields in tmp table
+ Change all funcs and sum_funcs to fields in tmp table, and create
+ new list of all items.
+
+ change_to_use_tmp_fields()
+ thd - THD pointer
+ ref_pointer_array - array of pointers to top elements of filed list
+ res_selected_fields - new list of items of select item list
+ res_all_fields - new list of all items
+ elements - number of elements in select item list
+ all_fields - all fields list
+
+ RETURN
+ 0 - ok
+ !=0 - error
*/
static bool
-change_to_use_tmp_fields(List<Item> &items)
+change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &res_selected_fields,
+ List<Item> &res_all_fields,
+ uint elements, List<Item> &all_fields)
{
- List_iterator<Item> it(items);
+ List_iterator_fast<Item> it(all_fields);
Item *item_field,*item;
+ res_selected_fields.empty();
+ res_all_fields.empty();
- while ((item=it++))
+ uint i, border= all_fields.elements - elements;
+ for (i= 0; (item= it++); i++)
{
Field *field;
+
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
- continue;
- if (item->type() == Item::FIELD_ITEM)
- {
- ((Item_field*) item)->field=
- ((Item_field*) item)->result_field;
- }
- else if ((field=item->tmp_table_field()))
+ item_field= item;
+ else
{
- if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
- item_field=((Item_sum*) item)->result_item(field);
- else
- item_field=(Item*) new Item_field(field);
- if (!item_field)
- return TRUE; // Fatal error
- item_field->name=item->name; /*lint -e613 */
-#ifndef DBUG_OFF
- if (_db_on_ && !item_field->name)
+ if (item->type() == Item::FIELD_ITEM)
{
- char buff[256];
- String str(buff,sizeof(buff));
- str.length(0);
- item->print(&str);
- item_field->name=sql_strmake(str.ptr(),str.length());
+ item_field= item->get_tmp_table_item(thd);
}
+ else if ((field= item->tmp_table_field()))
+ {
+ if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
+ item_field= ((Item_sum*) item)->result_item(field);
+ else
+ item_field= (Item*) new Item_field(field);
+ if (!item_field)
+ return TRUE; // Fatal error
+ item_field->name= item->name; /*lint -e613 */
+#ifndef DBUG_OFF
+ if (_db_on_ && !item_field->name)
+ {
+ char buff[256];
+ String str(buff,sizeof(buff),default_charset_info);
+ str.length(0);
+ item->print(&str);
+ item_field->name= sql_strmake(str.ptr(),str.length());
+ }
#endif
-#ifdef DELETE_ITEMS
- delete it.replace(item_field); /*lint -e613 */
-#else
- (void) it.replace(item_field); /*lint -e613 */
-#endif
+ }
+ else
+ item_field= item;
}
+ res_all_fields.push_back(item_field);
+ ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
+ item_field;
}
+
+ List_iterator_fast<Item> itr(res_all_fields);
+ for (i= 0; i < border; i++)
+ itr++;
+ itr.sublist(res_selected_fields, elements);
return FALSE;
}
@@ -7078,56 +7705,45 @@ change_to_use_tmp_fields(List<Item> &items)
/*
Change all sum_func refs to fields to point at fields in tmp table
Change all funcs to be fields in tmp table
+
+ change_refs_to_tmp_fields()
+ thd - THD pointer
+ ref_pointer_array - array of pointers to top elements of filed list
+ res_selected_fields - new list of items of select item list
+ res_all_fields - new list of all items
+ elements - number of elements in select item list
+ all_fields - all fields list
+
+ RETURN
+ 0 - ok
+ !=0 - error
*/
static bool
-change_refs_to_tmp_fields(THD *thd,List<Item> &items)
+change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &res_selected_fields,
+ List<Item> &res_all_fields, uint elements,
+ List<Item> &all_fields)
{
- List_iterator<Item> it(items);
- Item *item;
+ List_iterator_fast<Item> it(all_fields);
+ Item *item, *new_item;
+ res_selected_fields.empty();
+ res_all_fields.empty();
- while ((item= it++))
+ uint i, border= all_fields.elements - elements;
+ for (i= 0; (item= it++); i++)
{
- if (item->type() == Item::SUM_FUNC_ITEM)
- {
- if (!item->const_item())
- {
- Item_sum *sum_item= (Item_sum*) item;
- if (sum_item->result_field) // If not a const sum func
- {
- Field *result_field=sum_item->result_field;
- for (uint i=0 ; i < sum_item->arg_count ; i++)
- {
- Item *arg= sum_item->args[i];
- if (!arg->const_item())
- {
- if (arg->type() == Item::FIELD_ITEM)
- ((Item_field*) arg)->field= result_field++;
- else
- sum_item->args[i]= new Item_field(result_field++);
- }
- }
- }
- }
- }
- else if (item->with_sum_func)
- continue;
- else if ((item->type() == Item::FUNC_ITEM ||
- item->type() == Item::COND_ITEM) &&
- !item->const_item())
- { /* All funcs are stored */
-#ifdef DELETE_ITEMS
- delete it.replace(new Item_field(((Item_func*) item)->result_field));
-#else
- (void) it.replace(new Item_field(((Item_func*) item)->result_field));
-#endif
- }
- else if (item->type() == Item::FIELD_ITEM) /* Change refs */
- {
- ((Item_field*)item)->field=((Item_field*) item)->result_field;
- }
+ res_all_fields.push_back(new_item= item->get_tmp_table_item(thd));
+ ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
+ new_item;
}
- return thd->fatal_error;
+
+ List_iterator_fast<Item> itr(res_all_fields);
+ for (i= 0; i < border; i++)
+ itr++;
+ itr.sublist(res_selected_fields, elements);
+
+ return thd->is_fatal_error;
}
@@ -7222,14 +7838,14 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
Item *value=join_tab->ref.items[i];
cond->add(new Item_func_equal(new Item_field(field),value));
}
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
DBUG_RETURN(TRUE);
/*
Here we pass 0 as the first argument to fix_fields that don't need
to do any stack checking (This is already done in the initial fix_fields).
*/
- cond->fix_fields((THD *) 0,(TABLE_LIST *) 0);
+ cond->fix_fields((THD *) 0,(TABLE_LIST *) 0, (Item**)&cond);
if (join_tab->select)
{
error=(int) cond->add(join_tab->select->cond);
@@ -7249,46 +7865,31 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct,const char *message)
{
List<Item> field_list;
- Item *item;
List<Item> item_list;
THD *thd=join->thd;
- MYSQL_LOCK *save_lock;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
select_result *result=join->result;
Item *item_null= new Item_null();
DBUG_ENTER("select_describe");
-
+ DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
+ (ulong)join->select_lex, join->select_lex->type,
+ message));
/* Don't log this into the slow query log */
select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
- thd->offset_limit=0;
- if (thd->lex.select == select_lex)
- {
- field_list.push_back(new Item_empty_string("table",NAME_LEN));
- field_list.push_back(new Item_empty_string("type",10));
- field_list.push_back(item=new Item_empty_string("possible_keys",
- NAME_LEN*MAX_KEY));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("key_len",0,3));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("ref",
- NAME_LEN*MAX_REF_PARTS));
- item->maybe_null=1;
- field_list.push_back(new Item_real("rows",0.0,0,10));
- field_list.push_back(new Item_empty_string("Extra",255));
- if (result->send_fields(field_list,1))
- return;
- }
+ join->unit->offset_limit_cnt= 0;
if (message)
{
- Item *empty= new Item_empty_string("",0);
+ item_list.push_back(new Item_int((int32) join->select_lex->select_number));
+ item_list.push_back(new Item_string(join->select_lex->type,
+ strlen(join->select_lex->type),
+ default_charset_info));
for (uint i=0 ; i < 7; i++)
- item_list.push_back(empty);
- item_list.push_back(new Item_string(message,strlen(message)));
+ item_list.push_back(item_null);
+ item_list.push_back(new Item_string(message,strlen(message),
+ default_charset_info));
if (result->send_data(item_list))
- result->send_error(0,NullS);
+ join->error= 1;
}
else
{
@@ -7298,19 +7899,35 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
char buff[512],*buff_ptr=buff;
- char buff1[512], buff2[512], buff3[512];
- String tmp1(buff1,sizeof(buff1));
- String tmp2(buff2,sizeof(buff2));
+ char buff1[512], buff2[512];
+ String tmp1(buff1,sizeof(buff1),default_charset_info);
+ String tmp2(buff2,sizeof(buff2),default_charset_info);
tmp1.length(0);
tmp2.length(0);
- item_list.empty();
+ item_list.empty();
+ item_list.push_back(new Item_int((int32)
+ join->select_lex->select_number));
+ item_list.push_back(new Item_string(join->select_lex->type,
+ strlen(join->select_lex->type),
+ default_charset_info));
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
- item_list.push_back(new Item_string(table->table_name,
- strlen(table->table_name)));
+ if (table->tmp_table == TMP_TABLE && table->derived_select_number != 0)
+ {
+ // Derived table name generation
+ char buff[512];
+ int len= my_snprintf(buff, 512, "<derived%u>",
+ table->derived_select_number);
+ item_list.push_back(new Item_string(buff, len, default_charset_info));
+ }
+ else
+ item_list.push_back(new Item_string(table->table_name,
+ strlen(table->table_name),
+ default_charset_info));
item_list.push_back(new Item_string(join_type_str[tab->type],
- strlen(join_type_str[tab->type])));
+ strlen(join_type_str[tab->type]),
+ default_charset_info));
key_map bits;
uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
@@ -7323,14 +7940,16 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
}
if (tmp1.length())
- item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length()));
+ item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),
+ default_charset_info));
else
- item_list.push_back(item_null);
+ item_list.push_back(item_null);
if (tab->ref.key_parts)
{
KEY *key_info=table->key_info+ tab->ref.key;
item_list.push_back(new Item_string(key_info->name,
- strlen(key_info->name)));
+ strlen(key_info->name),
+ system_charset_info));
item_list.push_back(new Item_int((int32) tab->ref.key_length));
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
{
@@ -7338,13 +7957,15 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
tmp2.append(',');
tmp2.append((*ref)->name());
}
- item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length()));
+ item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),
+ default_charset_info));
}
else if (tab->type == JT_NEXT)
{
KEY *key_info=table->key_info+ tab->index;
item_list.push_back(new Item_string(key_info->name,
- strlen(key_info->name)));
+ strlen(key_info->name),
+ default_charset_info));
item_list.push_back(new Item_int((int32) key_info->key_length));
item_list.push_back(item_null);
}
@@ -7352,8 +7973,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
KEY *key_info=table->key_info+ tab->select->quick->index;
item_list.push_back(new Item_string(key_info->name,
- strlen(key_info->name)));
- item_list.push_back(new Item_int((int32) tab->select->quick->max_used_key_length));
+ strlen(key_info->name),
+ default_charset_info));
+ item_list.push_back(new Item_int((int32) tab->select->quick->
+ max_used_key_length));
item_list.push_back(item_null);
}
else
@@ -7362,15 +7985,17 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null);
item_list.push_back(item_null);
}
- sprintf(buff3,"%.0f",join->best_positions[i].records_read);
- item_list.push_back(new Item_string(buff3,strlen(buff3)));
+ item_list.push_back(new Item_int((longlong) (ulonglong)
+ join->best_positions[i]. records_read,
+ 21));
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index))))
key_read=1;
if (tab->info)
- item_list.push_back(new Item_string(tab->info,strlen(tab->info)));
+ item_list.push_back(new Item_string(tab->info,strlen(tab->info),
+ default_charset_info));
else
{
if (tab->select)
@@ -7398,49 +8023,100 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
need_order=0;
buff_ptr= strmov(buff_ptr,"; Using filesort");
}
- if (distinct && test_all_bits(used_tables,thd->used_tables))
+ if (distinct & test_all_bits(used_tables,thd->used_tables))
buff_ptr= strmov(buff_ptr,"; Distinct");
if (buff_ptr == buff)
- buff_ptr+= 2;
- item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2));
+ buff_ptr+= 2; // Skip inital "; "
+ item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
+ default_charset_info));
}
// For next iteration
used_tables|=table->map;
if (result->send_data(item_list))
- result->send_error(0,NullS);
+ join->error= 1;
}
}
- if (!thd->lex.select->next) // Not union
+ for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
{
- save_lock=thd->lock;
- thd->lock=(MYSQL_LOCK *)0;
- result->send_eof();
- thd->lock=save_lock;
+ if (mysql_explain_union(thd, unit, result))
+ DBUG_VOID_RETURN;
}
DBUG_VOID_RETURN;
}
-static void describe_info(JOIN *join, const char *info)
+int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
- THD *thd= join->thd;
+ DBUG_ENTER("mysql_explain_union");
+ int res= 0;
+ SELECT_LEX *first= unit->first_select();
+ for (SELECT_LEX *sl= first;
+ sl;
+ sl= sl->next_select())
+ {
+ res= mysql_explain_select(thd, sl,
+ (((&thd->lex.select_lex)==sl)?
+ ((thd->lex.all_selects_list != sl)?"PRIMARY":
+ "SIMPLE"):
+ ((sl == first)?
+ ((sl->linkage == DERIVED_TABLE_TYPE) ?
+ "DERIVED":
+ ((sl->dependent)?"DEPENDENT SUBSELECT":
+ (sl->uncacheable?"UNCACHEABLE SUBSELECT":
+ "SUBSELECT"))):
+ ((sl->dependent)?"DEPENDENT UNION":
+ sl->uncacheable?"UNCACHEABLE UNION":
+ "UNION"))),
+ result);
+ if (res)
+ break;
- if (thd->lex.select_lex.next) /* If in UNION */
- {
- select_describe(join,FALSE,FALSE,FALSE,info);
- return;
}
- List<Item> field_list;
- String *packet= &thd->packet;
+ if (res > 0 || thd->net.report_error)
+ res= -1; // mysql_explain_select do not report error
+ DBUG_RETURN(res);
+}
- /* Don't log this into the slow query log */
- thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED |
- QUERY_NO_GOOD_INDEX_USED);
- field_list.push_back(new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
- return; /* purecov: inspected */
- packet->length(0);
- net_store_data(packet,info);
- if (!my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
- send_eof(&thd->net);
+
+int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
+ select_result *result)
+{
+ DBUG_ENTER("mysql_explain_select");
+ DBUG_PRINT("info", ("Select 0x%lx, type %s", (ulong)select_lex, type))
+ select_lex->type= type;
+ thd->lex.current_select= select_lex;
+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
+ int res= mysql_select(thd, &select_lex->ref_pointer_array,
+ (TABLE_LIST*) select_lex->table_list.first,
+ select_lex->with_wild, select_lex->item_list,
+ select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) thd->lex.proc_list.first,
+ select_lex->options | thd->options | SELECT_DESCRIBE,
+ result, unit, select_lex, 0, 0);
+ DBUG_RETURN(res);
+}
+
+/*
+ Free joins of subselect of this select.
+
+ free_underlaid_joins()
+ thd - THD pointer
+ select - pointer to st_select_lex which subselects joins we will free
+*/
+
+void free_underlaid_joins(THD *thd, SELECT_LEX *select)
+{
+ for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ unit->cleanup();
}
+
+
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 332778aafe6..bb928846186 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc
{
public:
List<Item> copy_funcs;
+ List<Item> save_copy_funcs;
List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end;
+ Copy_field *save_copy_field, *save_copy_field_end;
byte *group_buff;
Item **items_to_copy; /* Fields in tmp table */
MI_COLUMNDEF *recinfo,*start_recinfo;
@@ -150,8 +152,8 @@ class TMP_TABLE_PARAM :public Sql_alloc
}
};
-
-class JOIN {
+class JOIN :public Sql_alloc
+{
public:
JOIN_TAB *join_tab,**best_ref,**map2table;
TABLE **table,**all_tables,*sort_by_table;
@@ -160,20 +162,114 @@ class JOIN {
bool sort_and_group,first_record,full_join,group, no_field_update;
bool do_send_rows;
table_map const_table_map,found_const_table_map,outer_join;
- ha_rows send_records,found_records,examined_rows,row_limit;
+ ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
double best_read;
List<Item> *fields;
List<Item_buff> group_fields;
TABLE *tmp_table;
+ // used to store 2 possible tmp table of SELECT
+ TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd;
Item_sum **sum_funcs;
Procedure *procedure;
Item *having;
+ Item *tmp_having; // To store Having when processed tenporary table
uint select_options;
select_result *result;
TMP_TABLE_PARAM tmp_table_param;
MYSQL_LOCK *lock;
+ // unit structure (with global parameters) for this select
+ SELECT_LEX_UNIT *unit;
+ // select that processed
+ SELECT_LEX *select_lex;
+
+ JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
+
+ bool select_distinct, //Is select distinct?
+ no_order, simple_order, simple_group,
+ skip_sort_order, need_tmp,
+ hidden_group_fields,
+ buffer_result;
+ DYNAMIC_ARRAY keyuse;
+ Item::cond_result cond_value;
+ List<Item> all_fields; // to store all fields that used in query
+ //Above list changed to use temporary table
+ List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
+ //Part, shared with list above, emulate following list
+ List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
+ List<Item> & fields_list; // hold field list passed to mysql_select
+ int error;
+
+ ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
+ COND *conds; // ---"---
+ TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
+ SQL_SELECT *select; //created in optimisation phase
+ Item **ref_pointer_array; //used pointer reference for this select
+ // Copy of above to be used with different lists
+ Item **items0, **items1, **items2, **items3;
+ uint ref_pointer_array_size; // size of above in bytes
+ const char *zero_result_cause; // not 0 if exec must return zero result
+
+ bool union_part; // this subselect is part of union
+ bool optimized; // flag to avoid double optimization in EXPLAIN
+
+ JOIN(THD *thd, List<Item> &fields,
+ ulong select_options, select_result *result):
+ join_tab(0),
+ table(0),
+ tables(0), const_tables(0),
+ sort_and_group(0), first_record(0),
+ do_send_rows(1),
+ send_records(0), found_records(0), examined_rows(0),
+ exec_tmp_table1(0), exec_tmp_table2(0),
+ thd(thd),
+ sum_funcs(0),
+ procedure(0),
+ having(0), tmp_having(0),
+ select_options(select_options),
+ result(result),
+ lock(thd->lock),
+ select_lex(0), //for safety
+ tmp_join(0),
+ select_distinct(test(select_options & SELECT_DISTINCT)),
+ no_order(0), simple_order(0), simple_group(0), skip_sort_order(0),
+ need_tmp(0),
+ hidden_group_fields (0), /*safety*/
+ buffer_result(test(select_options & OPTION_BUFFER_RESULT) &&
+ !test(select_options & OPTION_FOUND_ROWS)),
+ all_fields(fields),
+ fields_list(fields),
+ error(0),
+ select(0),
+ ref_pointer_array(0), items0(0), items1(0), items2(0), items3(0),
+ ref_pointer_array_size(0),
+ zero_result_cause(0),
+ optimized(0)
+ {
+ fields_list = fields;
+ bzero((char*) &keyuse,sizeof(keyuse));
+ tmp_table_param.copy_field=0;
+ tmp_table_param.end_write_records= HA_POS_ERROR;
+ }
+
+ int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, SELECT_LEX *select,
+ SELECT_LEX_UNIT *unit, bool fake_select_lex,
+ bool tables_and_fields_initied);
+ int optimize();
+ int reinit();
+ void exec();
+ int cleanup(THD *thd);
+ void restore_tmp();
+
+ inline void init_items_ref_array()
+ {
+ items0= ref_pointer_array + all_fields.elements;
+ ref_pointer_array_size= all_fields.elements*sizeof(Item*);
+ memcpy(items0, ref_pointer_array, ref_pointer_array_size);
+ }
};
@@ -188,15 +284,18 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- bool allow_distinct_limit, ulong select_options);
+ ulong select_options, ha_rows rows_limit);
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
-bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields);
+bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
+ Item **ref_pointer_array,
+ List<Item> &new_list1, List<Item> &new_list2,
+ uint elements, List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item **func_ptr);
-bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
- bool ignore_last_dupp_error);
+bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
+ int error, bool ignore_last_dupp_error);
/* functions from opt_sum.cc */
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
@@ -218,7 +317,7 @@ class store_key :public Sql_alloc
if (field_arg->type() == FIELD_TYPE_BLOB)
to_field=new Field_varstring(ptr, length, (uchar*) null, 1,
Field::NONE, field_arg->field_name,
- field_arg->table, field_arg->binary());
+ field_arg->table, field_arg->charset());
else
{
to_field=field_arg->new_field(&thd->mem_root,field_arg->table);
@@ -303,3 +402,4 @@ public:
bool cp_buffer_from_ref(TABLE_REF *ref);
bool error_if_full_join(JOIN *join);
+void relink_tables(SELECT_LEX *select_lex);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 4faee7d248f..7cda3d59c59 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -53,15 +53,15 @@ extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
** A database is a directory in the mysql_data_home directory
****************************************************************************/
-
int
mysqld_show_dbs(THD *thd,const char *wild)
{
- Item_string *field=new Item_string("",0);
+ Item_string *field=new Item_string("",0,default_charset_info);
List<Item> field_list;
char *end;
List<char> files;
char *file_name;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_dbs");
field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
@@ -71,11 +71,12 @@ mysqld_show_dbs(THD *thd,const char *wild)
strxmov(end," (",wild,")",NullS);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
DBUG_RETURN(1);
List_iterator_fast<char> it(files);
+
while ((file_name=it++))
{
if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
@@ -83,52 +84,52 @@ mysqld_show_dbs(THD *thd,const char *wild)
thd->priv_user, file_name) ||
(grant_option && !check_grant_db(thd, file_name)))
{
- thd->packet.length(0);
- net_store_data(&thd->packet, thd->variables.convert_set, file_name);
- if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
+
/***************************************************************************
-** List all open tables in a database
+ List all open tables in a database
***************************************************************************/
int mysqld_show_open_tables(THD *thd,const char *wild)
{
List<Item> field_list;
OPEN_TABLE_LIST *open_list;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_open_tables");
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_int("In_use",0, 4));
- field_list.push_back(new Item_int("Name_locked",0, 4));
+ field_list.push_back(new Item_return_int("In_use", 1, MYSQL_TYPE_TINY));
+ field_list.push_back(new Item_return_int("Name_locked", 4, MYSQL_TYPE_TINY));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
- if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
+ if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
DBUG_RETURN(-1);
for (; open_list ; open_list=open_list->next)
{
- thd->packet.length(0);
- net_store_data(&thd->packet,convert, open_list->db);
- net_store_data(&thd->packet,convert, open_list->table);
- net_store_data(&thd->packet,open_list->in_use);
- net_store_data(&thd->packet,open_list->locked);
- if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(open_list->db);
+ protocol->store(open_list->table);
+ protocol->store_tiny((longlong) open_list->in_use);
+ protocol->store_tiny((longlong) open_list->locked);
+ if (protocol->write())
{
DBUG_RETURN(-1);
}
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -140,14 +141,16 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
int mysqld_show_tables(THD *thd,const char *db,const char *wild)
{
- Item_string *field=new Item_string("",0);
+ Item_string *field=new Item_string("",0,default_charset_info);
List<Item> field_list;
char path[FN_LEN],*end;
List<char> files;
char *file_name;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_tables");
- field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0));
+ field->name=(char*) thd->alloc(20+(uint) strlen(db)+
+ (wild ? (uint) strlen(wild)+4:0));
end=strxmov(field->name,"Tables_in_",db,NullS);
if (wild && wild[0])
strxmov(end," (",wild,")",NullS);
@@ -155,19 +158,233 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
(void) sprintf(path,"%s/%s",mysql_data_home,db);
(void) unpack_dirname(path,path);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
List_iterator_fast<char> it(files);
while ((file_name=it++))
{
- thd->packet.length(0);
- net_store_data(&thd->packet, thd->variables.convert_set, file_name);
- if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
+ DBUG_RETURN(-1);
+ }
+ send_eof(thd);
+ DBUG_RETURN(0);
+}
+
+/***************************************************************************
+** List all table types supported
+***************************************************************************/
+
+struct show_table_type_st {
+ const char *type;
+ SHOW_COMP_OPTION *value;
+ const char *comment;
+};
+
+
+SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
+
+static struct show_table_type_st sys_table_types[]=
+{
+ {"MyISAM", &have_yes,
+ "Default type from 3.23 with great performance"},
+ {"HEAP" , &have_yes,
+ "Hash based, stored in memory, useful for temporary tables"},
+ {"MERGE", &have_yes,
+ "Collection of identical MyISAM tables"},
+ {"ISAM", &have_isam,
+ "Obsolete table type; Is replaced by MyISAM"},
+ {"InnoDB", &have_innodb,
+ "Supports transactions, row-level locking and foreign keys"},
+ {"BDB", &have_berkeley_db,
+ "Supports transactions and page-level locking"},
+ {NullS, NULL, NullS}
+};
+
+
+int mysqld_show_table_types(THD *thd)
+{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("mysqld_show_table_types");
+
+ field_list.push_back(new Item_empty_string("Type",10));
+ field_list.push_back(new Item_empty_string("Support",10));
+ field_list.push_back(new Item_empty_string("Comment",80));
+
+ if (protocol->send_fields(&field_list,1))
+ DBUG_RETURN(1);
+
+ const char *default_type_name=
+ ha_table_typelib.type_names[thd->variables.table_type];
+
+ show_table_type_st *types;
+ for (types= sys_table_types; types->type; types++)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(types->type);
+ const char *option_name= show_comp_option_name[(int) *types->value];
+
+ if (*types->value == SHOW_OPTION_YES &&
+ !my_strcasecmp(system_charset_info, default_type_name, types->type))
+ option_name= "DEFAULT";
+ protocol->store(option_name);
+ protocol->store(types->comment);
+ if (protocol->write())
+ DBUG_RETURN(-1);
+ }
+ send_eof(thd);
+ DBUG_RETURN(0);
+}
+
+
+/***************************************************************************
+ List all privileges supported
+***************************************************************************/
+
+struct show_privileges_st {
+ const char *privilege;
+ const char *context;
+ const char *comment;
+};
+
+
+/*
+ TODO: Update with new privileges
+*/
+static struct show_privileges_st sys_privileges[]=
+{
+ {"Select", "Tables", "To retrieve rows from table"},
+ {"Insert", "Tables", "To insert data into tables"},
+ {"Update", "Tables", "To update existing rows "},
+ {"Delete", "Tables", "To delete existing rows"},
+ {"Index", "Tables", "To create or drop indexes"},
+ {"Alter", "Tables", "To alter the table"},
+ {"Create", "Databases,Tables,Indexes", "To create new databases and tables"},
+ {"Drop", "Databases,Tables", "To drop databases and tables"},
+ {"Grant", "Databases,Tables", "To give to other users those privileges you possess"},
+ {"References", "Databases,Tables", "To have references on tables"},
+ {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
+ {"Shutdown","Server Admin", "To shutdown the server"},
+ {"Process", "Server Admin", "To view the plain text of currently executing queries"},
+ {"File", "File access on server", "To read and write files on the server"},
+ {NullS, NullS, NullS}
+};
+
+
+int mysqld_show_privileges(THD *thd)
+{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("mysqld_show_privileges");
+
+ field_list.push_back(new Item_empty_string("Privilege",10));
+ field_list.push_back(new Item_empty_string("Context",15));
+ field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
+
+ if (protocol->send_fields(&field_list,1))
+ DBUG_RETURN(1);
+
+ show_privileges_st *privilege= sys_privileges;
+ for (privilege= sys_privileges; privilege->privilege ; privilege++)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(privilege->privilege);
+ protocol->store(privilege->context);
+ protocol->store(privilege->comment);
+ if (protocol->write())
+ DBUG_RETURN(-1);
+ }
+ send_eof(thd);
+ DBUG_RETURN(0);
+}
+
+
+/***************************************************************************
+ List all column types
+***************************************************************************/
+
+struct show_column_type_st
+{
+ const char *type;
+ uint size;
+ const char *min_value;
+ const char *max_value;
+ uint precision;
+ uint scale;
+ const char *nullable;
+ const char *auto_increment;
+ const char *unsigned_attr;
+ const char *zerofill;
+ const char *searchable;
+ const char *case_sensitivity;
+ const char *default_value;
+ const char *comment;
+};
+
+/* TODO: Add remaning types */
+
+static struct show_column_type_st sys_column_types[]=
+{
+ {"tinyint",
+ 1, "-128", "127", 0, 0, "YES", "YES",
+ "NO", "YES", "YES", "NO", "NULL,0",
+ "A very small integer"},
+ {"tinyint unsigned",
+ 1, "0" , "255", 0, 0, "YES", "YES",
+ "YES", "YES", "YES", "NO", "NULL,0",
+ "A very small integer"},
+};
+
+int mysqld_show_column_types(THD *thd)
+{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("mysqld_show_column_types");
+
+ field_list.push_back(new Item_empty_string("Type",30));
+ field_list.push_back(new Item_int("Size",(longlong) 1,21));
+ field_list.push_back(new Item_empty_string("Min_Value",20));
+ field_list.push_back(new Item_empty_string("Max_Value",20));
+ field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
+ field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
+ field_list.push_back(new Item_empty_string("Nullable",4));
+ field_list.push_back(new Item_empty_string("Auto_Increment",4));
+ field_list.push_back(new Item_empty_string("Unsigned",4));
+ field_list.push_back(new Item_empty_string("Zerofill",4));
+ field_list.push_back(new Item_empty_string("Searchable",4));
+ field_list.push_back(new Item_empty_string("Case_Sensitive",4));
+ field_list.push_back(new Item_empty_string("Default",NAME_LEN));
+ field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
+
+ if (protocol->send_fields(&field_list,1))
+ DBUG_RETURN(1);
+
+ /* TODO: Change the loop to not use 'i' */
+ for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(sys_column_types[i].type);
+ protocol->store((ulonglong) sys_column_types[i].size);
+ protocol->store(sys_column_types[i].min_value);
+ protocol->store(sys_column_types[i].max_value);
+ protocol->store_short((longlong) sys_column_types[i].precision);
+ protocol->store_short((longlong) sys_column_types[i].scale);
+ protocol->store(sys_column_types[i].nullable);
+ protocol->store(sys_column_types[i].auto_increment);
+ protocol->store(sys_column_types[i].unsigned_attr);
+ protocol->store(sys_column_types[i].zerofill);
+ protocol->store(sys_column_types[i].searchable);
+ protocol->store(sys_column_types[i].case_sensitivity);
+ protocol->store(sys_column_types[i].default_value);
+ protocol->store(sys_column_types[i].comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -211,7 +428,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
else
{
// Return only .frm files which aren't temp files.
- if (my_strcasecmp(ext=fn_ext(file->name),reg_ext) ||
+ if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) ||
is_prefix(file->name,tmp_file_prefix))
continue;
*ext=0;
@@ -219,7 +436,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
{
if (lower_case_table_names)
{
- if (wild_case_compare(file->name,wild))
+ if (wild_case_compare(system_charset_info,file->name,wild))
continue;
}
else if (wild_compare(file->name,wild))
@@ -246,8 +463,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
DBUG_RETURN(0);
}
+
/***************************************************************************
-** Extended version of mysqld_show_tables
+ Extended version of mysqld_show_tables
***************************************************************************/
int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
@@ -258,13 +476,12 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
char path[FN_LEN];
char *file_name;
TABLE *table;
- String *packet= &thd->packet;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ TIME time;
DBUG_ENTER("mysqld_extend_show_tables");
(void) sprintf(path,"%s/%s",mysql_data_home,db);
(void) unpack_dirname(path,path);
-
field_list.push_back(item=new Item_empty_string("Name",NAME_LEN));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Type",10));
@@ -291,10 +508,12 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
item->maybe_null=1;
field_list.push_back(item=new Item_datetime("Check_time"));
item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("Charset",32));
+ item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Create_options",255));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
@@ -304,70 +523,76 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
{
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
- packet->length(0);
- net_store_data(packet,convert, file_name);
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
table_list.db=(char*) db;
table_list.real_name= table_list.alias= file_name;
if (lower_case_table_names)
- casedn_str(file_name);
+ my_casedn_str(files_charset_info, file_name);
if (!(table = open_ltable(thd, &table_list, TL_READ)))
{
for (uint i=0 ; i < field_list.elements ; i++)
- net_store_null(packet);
- net_store_data(packet,convert, thd->net.last_error);
+ protocol->store_null();
+ protocol->store(thd->net.last_error);
thd->net.last_error[0]=0;
}
else
{
struct tm tm_tmp;
+ const char *str;
handler *file=table->file;
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
- net_store_data(packet, convert, file->table_type());
- net_store_data(packet, convert,
- (table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
- "Compressed" :
- (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
- "Dynamic" : "Fixed");
- net_store_data(packet, (longlong) file->records);
- net_store_data(packet, (uint32) file->mean_rec_length);
- net_store_data(packet, (longlong) file->data_file_length);
+ protocol->store(file->table_type());
+ str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
+ "Compressed" :
+ (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
+ "Dynamic" : "Fixed");
+ protocol->store(str);
+ protocol->store((ulonglong) file->records);
+ protocol->store((ulonglong) file->mean_rec_length);
+ protocol->store((ulonglong) file->data_file_length);
if (file->max_data_file_length)
- net_store_data(packet, (longlong) file->max_data_file_length);
+ protocol->store((ulonglong) file->max_data_file_length);
else
- net_store_null(packet);
- net_store_data(packet, (longlong) file->index_file_length);
- net_store_data(packet, (longlong) file->delete_length);
+ protocol->store_null();
+ protocol->store((ulonglong) file->index_file_length);
+ protocol->store((ulonglong) file->delete_length);
if (table->found_next_number_field)
{
table->next_number_field=table->found_next_number_field;
table->next_number_field->reset();
file->update_auto_increment();
- net_store_data(packet, table->next_number_field->val_int());
+ protocol->store(table->next_number_field->val_int());
table->next_number_field=0;
}
else
- net_store_null(packet);
+ protocol->store_null();
if (!file->create_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->create_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
if (!file->update_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->update_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
if (!file->check_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->check_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
+ str= (table->table_charset ? table->table_charset->name : "default");
+ protocol->store(str);
{
char option_buff[350],*ptr;
ptr=option_buff;
@@ -404,27 +629,25 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
ptr=strmov(ptr,buff);
}
- net_store_data(packet, convert, option_buff+1,
- (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
+ protocol->store(option_buff+1,
+ (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
}
{
char *comment=table->file->update_table_comment(table->comment);
- net_store_data(packet, comment);
+ protocol->store(comment);
if (comment != table->comment)
my_free(comment,MYF(0));
}
close_thread_tables(thd,0);
}
- if (my_net_write(&thd->net,(char*) packet->ptr(),
- packet->length()))
+ if (protocol->write())
DBUG_RETURN(-1);
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
-
/***************************************************************************
** List all columns in a table_list->real_name
***************************************************************************/
@@ -437,14 +660,14 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
handler *file;
char tmp[MAX_FIELD_WIDTH];
Item *item;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
- send_error(&thd->net);
+ send_error(thd);
DBUG_RETURN(1);
}
file=table->file;
@@ -454,23 +677,20 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
List<Item> field_list;
field_list.push_back(new Item_empty_string("Field",NAME_LEN));
field_list.push_back(new Item_empty_string("Type",40));
+ field_list.push_back(new Item_empty_string("Collation",40));
field_list.push_back(new Item_empty_string("Null",1));
field_list.push_back(new Item_empty_string("Key",3));
field_list.push_back(item=new Item_empty_string("Default",NAME_LEN));
item->maybe_null=1;
field_list.push_back(new Item_empty_string("Extra",20));
if (verbose)
- field_list.push_back(new Item_empty_string("Privileges",80));
-
- // Send first number of fields and records
{
- char *pos;
- pos=net_store_length(tmp, (uint) field_list.elements);
- pos=net_store_length(pos,(ulonglong) file->records);
- (void) my_net_write(&thd->net,tmp,(uint) (pos-tmp));
+ field_list.push_back(new Item_empty_string("Privileges",80));
+ field_list.push_back(new Item_empty_string("Comment",255));
}
-
- if (send_fields(thd,field_list,0))
+ // Send first number of fields and records
+ if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
+ protocol->send_fields(&field_list,0))
DBUG_RETURN(1);
restore_record(table,2); // Get empty record
@@ -478,7 +698,8 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
String *packet= &thd->packet;
for (ptr=table->field; (field= *ptr) ; ptr++)
{
- if (!wild || !wild[0] || !wild_case_compare(field->field_name,wild))
+ if (!wild || !wild[0] ||
+ !wild_case_compare(system_charset_info, field->field_name,wild))
{
#ifdef NOT_USED
if (thd->col_access & TABLE_ACLS ||
@@ -488,48 +709,49 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
{
byte *pos;
uint flags=field->flags;
- String type(tmp,sizeof(tmp));
+ String type(tmp,sizeof(tmp),current_thd->variables.thd_charset);
uint col_access;
bool null_default_value=0;
- packet->length(0);
- net_store_data(packet,convert,field->field_name);
+ protocol->prepare_for_resend();
+ protocol->store(field->field_name);
field->sql_type(type);
- net_store_data(packet,convert,type.ptr(),type.length());
+ protocol->store(type.ptr(), type.length());
+ protocol->store(field->charset()->name);
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
field->type() != FIELD_TYPE_TIMESTAMP ?
"" : "YES");
- net_store_data(packet,convert,(const char*) pos);
+ protocol->store((const char*) pos);
pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
- net_store_data(packet,convert,(char*) pos);
+ protocol->store((char*) pos);
if (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER)
null_default_value=1;
if (!null_default_value && !field->is_null())
{ // Not null by default
- type.set(tmp,sizeof(tmp));
+ type.set(tmp,sizeof(tmp),default_charset_info);
field->val_str(&type,&type);
- net_store_data(packet,convert,type.ptr(),type.length());
+ protocol->store(type.ptr(),type.length());
}
else if (field->maybe_null() || null_default_value)
- net_store_null(packet); // Null as default
+ protocol->store_null(); // Null as default
else
- net_store_data(packet,convert,tmp,0);
+ protocol->store("",0); // empty string
char *end=tmp;
if (field->unireg_check == Field::NEXT_NUMBER)
end=strmov(tmp,"auto_increment");
- net_store_data(packet,convert,tmp,(uint) (end-tmp));
+ protocol->store(tmp,(uint) (end-tmp));
if (verbose)
{
- /* Add grant options */
- col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
+ /* Add grant options & comments */
end=tmp;
+ col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
{
if (col_access & 1)
@@ -538,22 +760,26 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
end=strmov(end,grant_types.type_names[bitnr]);
}
}
- net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
+ protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
+ protocol->store(field->comment.str, field->comment.length);
}
- if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ if (protocol->write())
DBUG_RETURN(1);
}
}
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
+
int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -561,54 +787,25 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
/* Only one table for now */
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
- send_error(&thd->net);
+ send_error(thd);
DBUG_RETURN(1);
}
List<Item> field_list;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_empty_string("Create Table",1024));
+ field_list.push_back(new Item_empty_string("Create Table", MAX_BLOB_WIDTH));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(1);
-
- String *packet = &thd->packet;
- {
- packet->length(0);
- net_store_data(packet,convert, table->table_name);
- /*
- A hack - we need to reserve some space for the length before
- we know what it is - let's assume that the length of create table
- statement will fit into 3 bytes ( 16 MB max :-) )
- */
- ulong store_len_offset = packet->length();
- packet->length(store_len_offset + 4);
- if (store_create_info(thd, table, packet))
- DBUG_RETURN(-1);
- ulong create_len = packet->length() - store_len_offset - 4;
- if (create_len > 0x00ffffff) // better readable in HEX ...
- {
- /*
- Just in case somebody manages to create a table
- with *that* much stuff in the definition
- */
- DBUG_RETURN(1);
- }
-
- /*
- Now we have to store the length in three bytes, even if it would fit
- into fewer bytes, so we cannot use net_store_data() anymore,
- and do it ourselves
- */
- char* p = (char*)packet->ptr() + store_len_offset;
- *p++ = (char) 253; // The client the length is stored using 3-bytes
- int3store(p, create_len);
-
- // now we are in business :-)
- if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
- DBUG_RETURN(1);
- }
- send_eof(&thd->net);
+ protocol->prepare_for_resend();
+ protocol->store(table->table_name);
+ buffer.length(0);
+ if (store_create_info(thd, table, &buffer))
+ DBUG_RETURN(-1);
+ protocol->store(buffer.ptr(), buffer.length());
+ if (protocol->write())
+ DBUG_RETURN(1);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -616,22 +813,23 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
int
mysqld_show_logs(THD *thd)
{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_logs");
- List<Item> field_list;
field_list.push_back(new Item_empty_string("File",FN_REFLEN));
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Status",10));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip && berkeley_show_logs(thd))
+ if (!berkeley_skip && berkeley_show_logs(protocol))
DBUG_RETURN(-1);
#endif
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
@@ -640,30 +838,30 @@ int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
- char buff[256];
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
- send_error(&thd->net);
+ send_error(thd);
DBUG_RETURN(1);
}
List<Item> field_list;
Item *item;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_int("Non_unique",0,1));
+ field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
- field_list.push_back(new Item_int("Seq_in_index",0,2));
+ field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Cardinality",0,21));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("Sub_part",0,3));
+ field_list.push_back(item=new Item_return_int("Sub_part",3,
+ MYSQL_TYPE_TINY));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Packed",10));
item->maybe_null=1;
@@ -672,7 +870,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
field_list.push_back(new Item_empty_string("Comment",255));
item->maybe_null=1;
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
String *packet= &thd->packet;
@@ -681,65 +879,59 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
for (uint i=0 ; i < table->keys ; i++,key_info++)
{
KEY_PART_INFO *key_part= key_info->key_part;
- char *end;
+ const char *str;
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
- packet->length(0);
- net_store_data(packet,convert,table->table_name);
- net_store_data(packet,convert,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1);
- net_store_data(packet,convert,key_info->name);
- end=int10_to_str((long) (j+1),(char*) buff,10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
- net_store_data(packet,convert,
- key_part->field ? key_part->field->field_name :
- "?unknown field?");
+ protocol->prepare_for_resend();
+ protocol->store(table->table_name);
+ protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
+ protocol->store(key_info->name);
+ protocol->store_tiny((longlong) (j+1));
+ str=(key_part->field ? key_part->field->field_name :
+ "?unknown field?");
+ protocol->store(str);
if (table->file->index_flags(i) & HA_READ_ORDER)
- net_store_data(packet,convert,
- ((key_part->key_part_flag & HA_REVERSE_SORT) ?
- "D" : "A"), 1);
+ protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
+ "D" : "A"), 1);
else
- net_store_null(packet); /* purecov: inspected */
+ protocol->store_null(); /* purecov: inspected */
KEY *key=table->key_info+i;
if (key->rec_per_key[j])
{
ha_rows records=(table->file->records / key->rec_per_key[j]);
- end=longlong10_to_str((longlong) records, buff, 10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
+ protocol->store((ulonglong) records);
}
else
- net_store_null(packet);
+ protocol->store_null();
/* Check if we have a key part that only uses part of the field */
if (!key_part->field ||
key_part->length !=
table->field[key_part->fieldnr-1]->key_length())
- {
- end=int10_to_str((long) key_part->length, buff,10); /* purecov: inspected */
- net_store_data(packet,convert,buff,(uint) (end-buff)); /* purecov: inspected */
- }
+ protocol->store_tiny((longlong) key_part->length);
else
- net_store_null(packet);
- net_store_null(packet); // No pack_information yet
+ protocol->store_null();
+ protocol->store_null(); // No pack_information yet
/* Null flag */
uint flags= key_part->field ? key_part->field->flags : 0;
char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
- net_store_data(packet,convert,(const char*) pos);
- net_store_data(packet,convert,table->file->index_type(i));
+ protocol->store((const char*) pos);
+ protocol->store(table->file->index_type(i));
/* Comment */
- net_store_data(packet,convert,"");
- if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ protocol->store("", 0);
+ if (protocol->write())
DBUG_RETURN(1); /* purecov: inspected */
}
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
}
/****************************************************************************
-** Return only fields for API mysql_list_fields
-** Use "show table wildcard" in mysql instead of this
+ Return only fields for API mysql_list_fields
+ Use "show table wildcard" in mysql instead of this
****************************************************************************/
void
@@ -751,7 +943,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
{
- send_error(&thd->net);
+ send_error(thd);
DBUG_VOID_RETURN;
}
List<Item> field_list;
@@ -759,35 +951,37 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
Field **ptr,*field;
for (ptr=table->field ; (field= *ptr); ptr++)
{
- if (!wild || !wild[0] || !wild_case_compare(field->field_name,wild))
+ if (!wild || !wild[0] ||
+ !wild_case_compare(system_charset_info, field->field_name,wild))
field_list.push_back(new Item_field(field));
}
restore_record(table,2); // Get empty record
- if (send_fields(thd,field_list,2))
+ if (thd->protocol->send_fields(&field_list,2))
DBUG_VOID_RETURN;
- VOID(net_flush(&thd->net));
+ net_flush(&thd->net);
DBUG_VOID_RETURN;
}
+
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ String *packet= protocol->storage_packet();
DBUG_ENTER("mysqld_dump_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
- String* packet = &thd->packet;
- packet->length(0);
- if (store_create_info(thd,table,packet))
+ protocol->prepare_for_resend();
+ if (store_create_info(thd, table, packet))
DBUG_RETURN(-1);
- if (convert)
- convert->convert((char*) packet->ptr(), packet->length());
+ if (protocol->convert)
+ protocol->convert->convert((char*) packet->ptr(), packet->length());
if (fd < 0)
{
- if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
+ if (protocol->write())
DBUG_RETURN(-1);
- VOID(net_flush(&thd->net));
+ net_flush(&thd->net);
}
else
{
@@ -798,14 +992,26 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
DBUG_RETURN(0);
}
+
static void
append_identifier(THD *thd, String *packet, const char *name)
{
+ char qtype;
+ if ((thd->variables.sql_mode & MODE_ANSI_QUOTES) ||
+ (thd->variables.sql_mode & MODE_POSTGRESQL) ||
+ (thd->variables.sql_mode & MODE_ORACLE) ||
+ (thd->variables.sql_mode & MODE_MSSQL) ||
+ (thd->variables.sql_mode & MODE_DB2) ||
+ (thd->variables.sql_mode & MODE_SAPDB))
+ qtype= '\"';
+ else
+ qtype= '`';
+
if (thd->options & OPTION_QUOTE_SHOW_CREATE)
{
- packet->append("`", 1);
+ packet->append(&qtype, 1);
packet->append(name);
- packet->append("`", 1);
+ packet->append(&qtype, 1);
}
else
{
@@ -813,9 +1019,20 @@ append_identifier(THD *thd, String *packet, const char *name)
}
}
+
static int
store_create_info(THD *thd, TABLE *table, String *packet)
{
+ my_bool foreign_db_mode= ((thd->variables.sql_mode & MODE_POSTGRESQL) ||
+ (thd->variables.sql_mode & MODE_ORACLE) ||
+ (thd->variables.sql_mode & MODE_MSSQL) ||
+ (thd->variables.sql_mode & MODE_DB2) ||
+ (thd->variables.sql_mode & MODE_SAPDB));
+ my_bool limited_mysql_mode= ((thd->variables.sql_mode &
+ MODE_NO_FIELD_OPTIONS) ||
+ (thd->variables.sql_mode & MODE_MYSQL323) ||
+ (thd->variables.sql_mode & MODE_MYSQL40));
+
DBUG_ENTER("store_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
@@ -823,7 +1040,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH];
- String type(tmp, sizeof(tmp));
+ String type(tmp, sizeof(tmp),default_charset_info);
if (table->tmp_table)
packet->append("CREATE TEMPORARY TABLE ", 23);
else
@@ -843,7 +1060,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
if (type.ptr() != tmp)
- type.set(tmp, sizeof(tmp));
+ type.set(tmp, sizeof(tmp),default_charset_info);
field->sql_type(type);
packet->append(type.ptr(),type.length());
@@ -851,6 +1068,17 @@ store_create_info(THD *thd, TABLE *table, String *packet)
bool has_default = (field->type() != FIELD_TYPE_BLOB &&
field->type() != FIELD_TYPE_TIMESTAMP &&
field->unireg_check != Field::NEXT_NUMBER);
+
+ /*
+ For string types dump collation name only if
+ collation is not primary for the given charset
+ */
+ if (!field->binary() && !(field->charset()->state & MY_CS_PRIMARY) &&
+ !limited_mysql_mode && !foreign_db_mode)
+ {
+ packet->append(" collate ", 9);
+ packet->append(field->charset()->name);
+ }
if (flags & NOT_NULL_FLAG)
packet->append(" NOT NULL", 9);
@@ -859,12 +1087,12 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(" default ", 9);
if (!field->is_null())
{ // Not null by default
- type.set(tmp,sizeof(tmp));
+ type.set(tmp,sizeof(tmp),default_charset_info);
field->val_str(&type,&type);
- packet->append('\'');
if (type.length())
- append_unescaped(packet, type.c_ptr());
- packet->append('\'');
+ append_unescaped(packet, type.ptr(), type.length());
+ else
+ packet->append("''",2);
}
else if (field->maybe_null())
packet->append("NULL", 4); // Null as default
@@ -872,8 +1100,14 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(tmp,0);
}
- if (field->unireg_check == Field::NEXT_NUMBER)
- packet->append(" auto_increment", 15 );
+ if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode)
+ packet->append(" auto_increment", 15 );
+
+ if (field->comment.length)
+ {
+ packet->append(" COMMENT ",9);
+ append_unescaped(packet, field->comment.str, field->comment.length);
+ }
}
KEY *key_info=table->key_info;
@@ -895,11 +1129,25 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("UNIQUE ", 7);
else if (key_info->flags & HA_FULLTEXT)
packet->append("FULLTEXT ", 9);
+ else if (key_info->flags & HA_SPATIAL)
+ packet->append("SPATIAL ", 8);
packet->append("KEY ", 4);
if (!found_primary)
- append_identifier(thd,packet,key_info->name);
+ append_identifier(thd, packet, key_info->name);
+ if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
+ !limited_mysql_mode && !foreign_db_mode)
+ {
+ if (table->db_type == DB_TYPE_HEAP &&
+ key_info->algorithm == HA_KEY_ALG_BTREE)
+ packet->append(" TYPE BTREE", 11);
+
+ // +BAR: send USING only in non-default case: non-spatial rtree
+ if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
+ !(key_info->flags & HA_SPATIAL))
+ packet->append(" TYPE RTREE", 11);
+ }
packet->append(" (", 2);
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
@@ -938,65 +1186,80 @@ store_create_info(THD *thd, TABLE *table, String *packet)
}
packet->append("\n)", 2);
- packet->append(" TYPE=", 6);
- packet->append(file->table_type());
- char buff[128];
- char* p;
-
- if (table->min_rows)
+ if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
{
- packet->append(" MIN_ROWS=");
- p = longlong10_to_str(table->min_rows, buff, 10);
- packet->append(buff, (uint) (p - buff));
- }
+ packet->append(" TYPE=", 6);
+ packet->append(file->table_type());
+ char buff[128];
+ char* p;
+
+ if (table->table_charset &&
+ !(thd->variables.sql_mode & MODE_MYSQL323) &&
+ !(thd->variables.sql_mode & MODE_MYSQL40))
+ {
+ packet->append(" CHARSET=");
+ packet->append(table->table_charset->csname);
+ if (!(table->table_charset->state & MY_CS_PRIMARY))
+ {
+ packet->append(" COLLATE=");
+ packet->append(table->table_charset->name);
+ }
+ }
- if (table->max_rows)
- {
- packet->append(" MAX_ROWS=");
- p = longlong10_to_str(table->max_rows, buff, 10);
- packet->append(buff, (uint) (p - buff));
- }
- if (table->avg_row_length)
- {
- packet->append(" AVG_ROW_LENGTH=");
- p=longlong10_to_str(table->avg_row_length, buff,10);
- packet->append(buff, (uint) (p - buff));
- }
+ if (table->min_rows)
+ {
+ packet->append(" MIN_ROWS=");
+ p = longlong10_to_str(table->min_rows, buff, 10);
+ packet->append(buff, (uint) (p - buff));
+ }
- if (table->db_create_options & HA_OPTION_PACK_KEYS)
- packet->append(" PACK_KEYS=1", 12);
- if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
- packet->append(" PACK_KEYS=0", 12);
- if (table->db_create_options & HA_OPTION_CHECKSUM)
- packet->append(" CHECKSUM=1", 11);
- if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
- packet->append(" DELAY_KEY_WRITE=1",18);
- if (table->row_type != ROW_TYPE_DEFAULT)
- {
- packet->append(" ROW_FORMAT=",12);
- packet->append(ha_row_type[(uint) table->row_type]);
- }
- table->file->append_create_info(packet);
- if (table->comment && table->comment[0])
- {
- packet->append(" COMMENT='", 10);
- append_unescaped(packet, table->comment);
- packet->append('\'');
- }
- if (file->raid_type)
- {
- char buff[100];
- sprintf(buff," RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld",
- my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
- packet->append(buff);
+ if (table->max_rows)
+ {
+ packet->append(" MAX_ROWS=");
+ p = longlong10_to_str(table->max_rows, buff, 10);
+ packet->append(buff, (uint) (p - buff));
+ }
+ if (table->avg_row_length)
+ {
+ packet->append(" AVG_ROW_LENGTH=");
+ p=longlong10_to_str(table->avg_row_length, buff,10);
+ packet->append(buff, (uint) (p - buff));
+ }
+
+ if (table->db_create_options & HA_OPTION_PACK_KEYS)
+ packet->append(" PACK_KEYS=1", 12);
+ if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
+ packet->append(" PACK_KEYS=0", 12);
+ if (table->db_create_options & HA_OPTION_CHECKSUM)
+ packet->append(" CHECKSUM=1", 11);
+ if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
+ packet->append(" DELAY_KEY_WRITE=1",18);
+ if (table->row_type != ROW_TYPE_DEFAULT)
+ {
+ packet->append(" ROW_FORMAT=",12);
+ packet->append(ha_row_type[(uint) table->row_type]);
+ }
+ table->file->append_create_info(packet);
+ if (table->comment && table->comment[0])
+ {
+ packet->append(" COMMENT=", 9);
+ append_unescaped(packet, table->comment, strlen(table->comment));
+ }
+ if (file->raid_type)
+ {
+ char buff[100];
+ sprintf(buff," RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld",
+ my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
+ packet->append(buff);
+ }
}
DBUG_RETURN(0);
}
/****************************************************************************
-** Return info about all processes
-** returns for each thread: thread id, user, host, db, command, info
+ Return info about all processes
+ returns for each thread: thread id, user, host, db, command, info
****************************************************************************/
class thread_info :public ilink {
@@ -1016,7 +1279,6 @@ public:
template class I_List<thread_info>;
#endif
-
void mysqld_list_processes(THD *thd,const char *user, bool verbose)
{
Item *field;
@@ -1024,21 +1286,21 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
I_List<thread_info> thread_infos;
ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
PROCESS_LIST_WIDTH);
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_list_processes");
- field_list.push_back(new Item_int("Id",0,7));
+ field_list.push_back(new Item_int("Id",0,11));
field_list.push_back(new Item_empty_string("User",16));
field_list.push_back(new Item_empty_string("Host",64));
field_list.push_back(field=new Item_empty_string("db",NAME_LEN));
field->maybe_null=1;
field_list.push_back(new Item_empty_string("Command",16));
- field_list.push_back(new Item_empty_string("Time",7));
+ field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
field_list.push_back(field=new Item_empty_string("State",30));
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
field->maybe_null=1;
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_VOID_RETURN;
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
@@ -1049,8 +1311,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
while ((tmp=it++))
{
struct st_my_thread_var *mysys_var;
+#ifndef EMBEDDED_LIBRARY
if ((tmp->net.vio || tmp->system_thread) &&
(!user || (tmp->user && !strcmp(tmp->user,user))))
+#else
+ if (tmp->system_thread &&
+ (!user || (tmp->user && !strcmp(tmp->user,user))))
+#endif
{
thread_info *thd_info=new thread_info;
@@ -1068,6 +1335,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if ((mysys_var= tmp->mysys_var))
pthread_mutex_lock(&mysys_var->mutex);
thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
+#ifndef EMBEDDED_LIBRARY
thd_info->state_info= (char*) (tmp->locked ? "Locked" :
tmp->net.reading_or_writing ?
(tmp->net.reading_or_writing == 2 ?
@@ -1078,6 +1346,9 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
tmp->mysys_var &&
tmp->mysys_var->current_cond ?
"Waiting on cond" : NullS);
+#else
+ thd_info->state_info= (char*)"Writing to net";
+#endif
if (mysys_var)
pthread_mutex_unlock(&mysys_var->mutex);
@@ -1105,308 +1376,358 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thread_info *thd_info;
- String *packet= &thd->packet;
+ time_t now= time(0);
while ((thd_info=thread_infos.get()))
{
- char buff[20],*end;
- packet->length(0);
- end=int10_to_str((long) thd_info->thread_id, buff,10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
- net_store_data(packet,convert,thd_info->user);
- net_store_data(packet,convert,thd_info->host);
- if (thd_info->db)
- net_store_data(packet,convert,thd_info->db);
- else
- net_store_null(packet);
+ protocol->prepare_for_resend();
+ protocol->store((ulonglong) thd_info->thread_id);
+ protocol->store(thd_info->user);
+ protocol->store(thd_info->host);
+ protocol->store(thd_info->db);
if (thd_info->proc_info)
- net_store_data(packet,convert,thd_info->proc_info);
+ protocol->store(thd_info->proc_info);
else
- net_store_data(packet,convert,command_name[thd_info->command]);
+ protocol->store(command_name[thd_info->command]);
if (thd_info->start_time)
- net_store_data(packet,
- (uint32) (time((time_t*) 0) - thd_info->start_time));
- else
- net_store_null(packet);
- if (thd_info->state_info)
- net_store_data(packet,convert,thd_info->state_info);
+ protocol->store((uint32) (now - thd_info->start_time));
else
- net_store_null(packet);
- if (thd_info->query)
- net_store_data(packet,convert,thd_info->query);
- else
- net_store_null(packet);
- if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
+ protocol->store_null();
+ protocol->store(thd_info->state_info);
+ protocol->store(thd_info->query);
+ if (protocol->write())
break; /* purecov: inspected */
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_VOID_RETURN;
}
-
/*****************************************************************************
-** Status functions
+ Status functions
*****************************************************************************/
+int mysqld_show_charsets(THD *thd, const char *wild)
+{
+ char buff[8192];
+ String packet2(buff,sizeof(buff),default_charset_info);
+ List<Item> field_list;
+ CHARSET_INFO **cs;
+ Protocol *protocol= thd->protocol;
+ char flags[64];
+
+ DBUG_ENTER("mysqld_show_charsets");
+
+ field_list.push_back(new Item_empty_string("CS_Name",30));
+ field_list.push_back(new Item_empty_string("COL_Name",30));
+ field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
+ field_list.push_back(new Item_empty_string("Flags",30));
+ field_list.push_back(new Item_return_int("strx_maxlen",3, FIELD_TYPE_TINY));
+ field_list.push_back(new Item_return_int("mb_maxlen",3, FIELD_TYPE_TINY));
+
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(1);
+
+ for (cs=all_charsets ; cs < all_charsets+255 ; cs++ )
+ {
+ if (cs[0] && !(wild && wild[0] &&
+ wild_case_compare(system_charset_info,cs[0]->name,wild)))
+ {
+ protocol->prepare_for_resend();
+ protocol->store(cs[0]->csname);
+ protocol->store(cs[0]->name);
+ protocol->store_short((longlong) cs[0]->number);
+ flags[0]='\0';
+ if (cs[0]->state & MY_CS_PRIMARY)
+ strcat(flags,"pri");
+ protocol->store(flags);
+ protocol->store_tiny((longlong) cs[0]->strxfrm_multiply);
+ protocol->store_tiny((longlong) cs[0]->mbmaxlen);
+ if (protocol->write())
+ goto err;
+ }
+ }
+ send_eof(thd);
+ DBUG_RETURN(0);
+err:
+ DBUG_RETURN(1);
+}
+
+
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
enum enum_var_type value_type)
{
- char buff[8192];
- String packet2(buff,sizeof(buff));
+ char buff[1024];
List<Item> field_list;
- CONVERT *convert=thd->variables.convert_set;
-
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show");
+
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
/* pthread_mutex_lock(&THR_LOCK_keycache); */
pthread_mutex_lock(&LOCK_status);
for (; variables->name; variables++)
{
- if (!(wild && wild[0] && wild_case_compare(variables->name,wild)))
+ if (!(wild && wild[0] && wild_case_compare(system_charset_info,
+ variables->name,wild)))
{
- packet2.length(0);
- net_store_data(&packet2,convert,variables->name);
+ protocol->prepare_for_resend();
+ protocol->store(variables->name);
SHOW_TYPE show_type=variables->type;
char *value=variables->value;
+ const char *pos, *end;
+ long nr;
+
if (show_type == SHOW_SYS)
{
show_type= ((sys_var*) value)->type();
value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
}
+ pos= end= buff;
switch (show_type) {
case SHOW_LONG:
case SHOW_LONG_CONST:
- net_store_data(&packet2,(uint32) *(ulong*) value);
+ end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_LONGLONG:
- net_store_data(&packet2,(longlong) *(longlong*) value);
- break;
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
case SHOW_HA_ROWS:
- net_store_data(&packet2,(longlong) *(ha_rows*) value);
+ end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
break;
case SHOW_BOOL:
- net_store_data(&packet2,(ulong) *(bool*) value ? "ON" : "OFF");
+ end= strmov(buff, *(bool*) value ? "ON" : "OFF");
break;
case SHOW_MY_BOOL:
- net_store_data(&packet2,(ulong) *(my_bool*) value ? "ON" : "OFF");
+ end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_INT_CONST:
case SHOW_INT:
- net_store_data(&packet2,(uint32) *(int*) value);
+ end= int10_to_str((long) *(uint32*) value, buff, 10);
break;
case SHOW_HAVE:
{
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
- net_store_data(&packet2, (tmp == SHOW_OPTION_NO ? "NO" :
- tmp == SHOW_OPTION_YES ? "YES" :
- "DISABLED"));
+ pos= show_comp_option_name[(int) tmp];
+ end= strend(pos);
break;
}
case SHOW_CHAR:
- net_store_data(&packet2,convert, value);
+ pos= value;
+ end= strend(pos);
break;
case SHOW_STARTTIME:
- net_store_data(&packet2,(uint32) (thd->query_start() - start_time));
+ nr= (long) (thd->query_start() - start_time);
+ end= int10_to_str(nr, buff, 10);
break;
case SHOW_QUESTION:
- net_store_data(&packet2,(uint32) thd->query_id);
+ end= int10_to_str((long) thd->query_id, buff, 10);
break;
+#ifndef EMBEDDED_LIBRARY
case SHOW_RPL_STATUS:
- net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
+ end= strmov(buff, rpl_status_type[(int)rpl_status]);
break;
-#ifndef EMBEDDED_LIBRARY
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
- net_store_data(&packet2, (active_mi->slave_running &&
- active_mi->rli.slave_running)
- ? "ON" : "OFF");
+ end= strmov(buff, (active_mi->slave_running &&
+ active_mi->rli.slave_running) ? "ON" : "OFF");
UNLOCK_ACTIVE_MI;
break;
}
-#endif
+#endif /* EMBEDDED_LIBRARY */
case SHOW_OPENTABLES:
- net_store_data(&packet2,(uint32) cached_tables());
+ end= int10_to_str((long) cached_tables(), buff, 10);
break;
case SHOW_CHAR_PTR:
{
- value= *(char**) value;
- net_store_data(&packet2,convert, value ? value : "");
+ if (!(pos= *(char**) value))
+ pos= "";
+ end= strend(pos);
break;
}
#ifdef HAVE_OPENSSL
/* First group - functions relying on CTX */
case SHOW_SSL_CTX_SESS_ACCEPT:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CB_HITS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_HITS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_hits(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CACHE_FULL:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_MISSES:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_misses(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_TIMEOUTS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_NUMBER:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_CONNECT:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_VERIFY_MODE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
if (!ssl_acceptor_fd)
{
- net_store_data(&packet2,"NONE" );
+ pos= "NONE";
+ end= pos+4;
break;
}
switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
{
case SSL_SESS_CACHE_OFF:
- net_store_data(&packet2,"OFF" );
+ pos= "OFF";
break;
case SSL_SESS_CACHE_CLIENT:
- net_store_data(&packet2,"CLIENT" );
+ pos= "CLIENT";
break;
case SSL_SESS_CACHE_SERVER:
- net_store_data(&packet2,"SERVER" );
+ pos= "SERVER";
break;
case SSL_SESS_CACHE_BOTH:
- net_store_data(&packet2,"BOTH" );
+ pos= "BOTH";
break;
case SSL_SESS_CACHE_NO_AUTO_CLEAR:
- net_store_data(&packet2,"NO_AUTO_CLEAR" );
+ pos= "NO_AUTO_CLEAR";
break;
case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
- net_store_data(&packet2,"NO_INTERNAL_LOOKUP" );
+ pos= "NO_INTERNAL_LOOKUP";
break;
default:
- net_store_data(&packet2,"Unknown");
+ pos= "Unknown";
break;
}
+ pos= strend(pos);
break;
/* First group - functions relying on SSL */
case SHOW_SSL_GET_VERSION:
- net_store_data(&packet2, thd->net.vio->ssl_ ?
- SSL_get_version(thd->net.vio->ssl_) : "");
+ pos= thd->net.vio->ssl_ ? SSL_get_version(thd->net.vio->ssl_) : "";
+ end= strend(pos);
break;
case SHOW_SSL_SESSION_REUSED:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_session_reused(thd->net.vio->ssl_) : 0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_session_reused(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_DEFAULT_TIMEOUT:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_default_timeout(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_default_timeout(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_VERIFY_MODE:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_verify_mode(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_verify_mode(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_VERIFY_DEPTH:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_verify_depth(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_verify_depth(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_CIPHER:
- net_store_data(&packet2, thd->net.vio->ssl_ ?
- SSL_get_cipher(thd->net.vio->ssl_) : "");
+ pos= thd->net.vio->ssl_ ? SSL_get_cipher(thd->net.vio->ssl_) : "";
+ end= strend(pos);
break;
case SHOW_SSL_GET_CIPHER_LIST:
if (thd->net.vio->ssl_)
{
- char buf[1024], *pos;
- pos=buf;
+ char *to= buff;
for (int i=0 ; i++ ;)
{
- const char *p=SSL_get_cipher_list(thd->net.vio->ssl_,i);
+ const char *p= SSL_get_cipher_list(thd->net.vio->ssl_,i);
if (p == NULL)
break;
- pos=strmov(pos, p);
- *pos++= ':';
+ to= strmov(to, p);
+ *to++= ':';
}
- if (pos != buf)
- pos--; // Remove last ':'
- *pos=0;
- net_store_data(&packet2, buf);
+ if (to != buff)
+ to--; // Remove last ':'
+ end= to;
}
- else
- net_store_data(&packet2, "");
break;
#endif /* HAVE_OPENSSL */
case SHOW_UNDEF: // Show never happen
case SHOW_SYS:
- net_store_data(&packet2, ""); // Safety
+ break; // Return empty string
+ default:
break;
}
- if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
+ if (protocol->store(pos, (uint32) (end - pos)) ||
+ protocol->write())
goto err; /* purecov: inspected */
}
}
pthread_mutex_unlock(&LOCK_status);
/* pthread_mutex_unlock(&THR_LOCK_keycache); */
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
err:
diff --git a/sql/sql_sort.h b/sql/sql_sort.h
index 62c5f1cb164..14463a67a28 100644
--- a/sql/sql_sort.h
+++ b/sql/sql_sort.h
@@ -38,9 +38,7 @@ typedef struct st_sort_param {
SORT_FIELD *end;
uchar *unique_buff;
bool not_killable;
-#ifdef USE_STRCOLL
char* tmp_buffer;
-#endif
} SORTPARAM;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 2dcda2d40c2..21e38397842 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -30,6 +30,9 @@
extern gptr sql_alloc(unsigned size);
extern void sql_element_free(void *ptr);
+static uint32
+copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length, CHARSET_INFO *from_cs);
#include "sql_string.h"
@@ -91,36 +94,44 @@ bool String::realloc(uint32 alloc_length)
return FALSE;
}
-bool String::set(longlong num)
+bool String::set(longlong num, CHARSET_INFO *cs)
{
- if (alloc(21))
+ uint l=20*cs->mbmaxlen+1;
+
+ if (alloc(l))
return TRUE;
- str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
+ str_length=(uint32) (cs->longlong10_to_str)(cs,Ptr,l,-10,num);
+ str_charset=cs;
return FALSE;
}
-bool String::set(ulonglong num)
+bool String::set(ulonglong num, CHARSET_INFO *cs)
{
- if (alloc(21))
+ uint l=20*cs->mbmaxlen+1;
+
+ if (alloc(l))
return TRUE;
- str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
+ str_length=(uint32) (cs->longlong10_to_str)(cs,Ptr,l,10,num);
+ str_charset=cs;
return FALSE;
}
-bool String::set(double num,uint decimals)
+bool String::set(double num,uint decimals, CHARSET_INFO *cs)
{
char buff[331];
+
+ str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
sprintf(buff,"%.14g",num); // Enough for a DATETIME
- return copy(buff, (uint32) strlen(buff));
+ return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
char *pos,*to;
VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
- if (!isdigit(buff[1]))
+ if (!my_isdigit(&my_charset_latin1, buff[1]))
{ // Nan or Inf
pos=buff+1;
if (sign)
@@ -128,7 +139,7 @@ bool String::set(double num,uint decimals)
buff[0]='-';
pos=buff;
}
- return copy(pos,(uint32) strlen(pos));
+ return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs);
}
if (alloc((uint32) ((uint32) decpt+3+decimals)))
return TRUE;
@@ -178,7 +189,7 @@ end:
#else
sprintf(buff,"%.*f",(int) decimals,num);
#endif
- return copy(buff,(uint32) strlen(buff));
+ return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs);
#endif
}
@@ -200,19 +211,66 @@ bool String::copy(const String &str)
str_length=str.str_length;
bmove(Ptr,str.Ptr,str_length); // May be overlapping
Ptr[str_length]=0;
+ str_charset=str.str_charset;
return FALSE;
}
-bool String::copy(const char *str,uint32 arg_length)
+bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
{
if (alloc(arg_length))
return TRUE;
if ((str_length=arg_length))
memcpy(Ptr,str,arg_length);
Ptr[arg_length]=0;
+ str_charset=cs;
+ return FALSE;
+}
+
+ /* Copy with charset convertion */
+
+bool String::copy(const char *str, uint32 arg_length,
+ CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+{
+ uint32 new_length= to_cs->mbmaxlen*arg_length;
+ if (alloc(new_length))
+ return TRUE;
+ str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
+ str, arg_length, from_cs);
+ str_charset=to_cs;
return FALSE;
}
+
+/*
+ Set a string to the value of a latin1-string, keeping the original charset
+
+ SYNOPSIS
+ copy_or_set()
+ str String of a simple charset (latin1)
+ arg_length Length of string
+
+ IMPLEMENTATION
+ If string object is of a simple character set, set it to point to the
+ given string.
+ If not, make a copy and convert it to the new character set.
+
+ RETURN
+ 0 ok
+ 1 Could not allocate result buffer
+
+*/
+
+bool String::set_latin1(const char *str, uint32 arg_length)
+{
+ if (str_charset->mbmaxlen == 1)
+ {
+ set(str, arg_length, str_charset);
+ return 0;
+ }
+ return copy(str, arg_length, &my_charset_latin1, str_charset);
+}
+
+
/* This is used by mysql.cc */
bool String::fill(uint32 max_length,char fill_char)
@@ -231,7 +289,7 @@ bool String::fill(uint32 max_length,char fill_char)
void String::strip_sp()
{
- while (str_length && isspace(Ptr[str_length-1]))
+ while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
str_length--;
}
@@ -247,11 +305,26 @@ bool String::append(const String &s)
return FALSE;
}
+
+/*
+ Append a latin1 string to the a string of the current character set
+*/
+
+
bool String::append(const char *s,uint32 arg_length)
{
if (!arg_length) // Default argument
if (!(arg_length= (uint32) strlen(s)))
return FALSE;
+ if (str_charset->mbmaxlen > 1)
+ {
+ uint32 add_length=arg_length * str_charset->mbmaxlen;
+ if (realloc(str_length+ add_length))
+ return TRUE;
+ str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
+ s, arg_length, &my_charset_latin1);
+ return FALSE;
+ }
if (realloc(str_length+arg_length))
return TRUE;
memcpy(Ptr+str_length,s,arg_length);
@@ -259,6 +332,7 @@ bool String::append(const char *s,uint32 arg_length)
return FALSE;
}
+
#ifdef TO_BE_REMOVED
bool String::append(FILE* file, uint32 arg_length, myf my_flags)
{
@@ -289,46 +363,13 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
uint32 String::numchars()
{
-#ifdef USE_MB
- register uint32 n=0,mblen;
- register const char *mbstr=Ptr;
- register const char *end=mbstr+str_length;
- if (use_mb(default_charset_info))
- {
- while (mbstr < end) {
- if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
- else ++mbstr;
- ++n;
- }
- return n;
- }
- else
-#endif
- return str_length;
+ return str_charset->numchars(str_charset, Ptr, Ptr+str_length);
}
int String::charpos(int i,uint32 offset)
{
-#ifdef USE_MB
- register uint32 mblen;
- register const char *mbstr=Ptr+offset;
- register const char *end=Ptr+str_length;
- if (use_mb(default_charset_info))
- {
- if (i<=0) return i;
- while (i && mbstr < end) {
- if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
- else ++mbstr;
- --i;
- }
- if ( INT_MAX32-i <= (int) (mbstr-Ptr-offset))
- return INT_MAX32;
- else
- return (int) ((mbstr-Ptr-offset)+i);
- }
- else
-#endif
- return i;
+ if (i<0) return i;
+ return str_charset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
}
int String::strstr(const String &s,uint32 offset)
@@ -377,12 +418,14 @@ int String::strstr_case(const String &s,uint32 offset)
skipp:
while (str != end)
{
- if (my_sort_order[*str++] == my_sort_order[*search])
+ if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
{
register char *i,*j;
i=(char*) str; j=(char*) search+1;
while (j != search_end)
- if (my_sort_order[*i++] != my_sort_order[*j++]) goto skipp;
+ if (str_charset->sort_order[*i++] !=
+ str_charset->sort_order[*j++])
+ goto skipp;
return (int) (str-Ptr) -1;
}
}
@@ -456,61 +499,51 @@ bool String::replace(uint32 offset,uint32 arg_length,const String &to)
return FALSE;
}
-
-int sortcmp(const String *x,const String *y)
+// added by Holyfoot for "geometry" needs
+int String::reserve(uint32 space_needed, uint32 grow_by)
{
- const char *s= x->ptr();
- const char *t= y->ptr();
- uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
-
-#ifdef USE_STRCOLL
- if (use_strcoll(default_charset_info))
- {
-#ifndef CMP_ENDSPACE
- while (x_len && isspace(s[x_len-1]))
- x_len--;
- while (y_len && isspace(t[y_len-1]))
- y_len--;
-#endif
- return my_strnncoll(default_charset_info,
- (unsigned char *)s,x_len,(unsigned char *)t,y_len);
- }
- else
+ if (Alloced_length < str_length + space_needed)
{
-#endif /* USE_STRCOLL */
- x_len-=len; // For easy end space test
- y_len-=len;
- while (len--)
- {
- if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++])
- return ((int) my_sort_order[(uchar) s[-1]] -
- (int) my_sort_order[(uchar) t[-1]]);
- }
-#ifndef CMP_ENDSPACE
- /* Don't compare end space in strings */
- {
- if (y_len)
- {
- const char *end=t+y_len;
- for (; t != end ; t++)
- if (!isspace(*t))
- return -1;
- }
- else
- {
- const char *end=s+x_len;
- for (; s != end ; s++)
- if (!isspace(*s))
- return 1;
- }
- return 0;
- }
-#else
- return (int) (x_len-y_len);
-#endif /* CMP_ENDSPACE */
-#ifdef USE_STRCOLL
+ if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
+ return TRUE;
}
-#endif
+ return FALSE;
+}
+
+void String::qs_append(const char *str)
+{
+ int len = strlen(str);
+ memcpy(Ptr + str_length, str, len + 1);
+ str_length += len;
+}
+
+void String::qs_append(double d)
+{
+ char *buff = Ptr + str_length;
+ sprintf(buff,"%.14g", d);
+ str_length += strlen(buff);
+}
+
+void String::qs_append(double *d)
+{
+ double ld;
+ float8get(ld, (char*) d);
+ qs_append(ld);
+}
+
+void String::qs_append(const char &c)
+{
+ Ptr[str_length] = c;
+ str_length += sizeof(c);
+}
+
+
+int sortcmp(const String *x,const String *y)
+{
+ CHARSET_INFO *cs= x->str_charset;
+ return cs->strnncollsp(cs,
+ (unsigned char *) x->ptr(),x->length(),
+ (unsigned char *) y->ptr(),y->length());
}
@@ -542,263 +575,66 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
return from; // Actually an error
if ((to->str_length=min(from->str_length,from_length)))
memcpy(to->Ptr,from->Ptr,to->str_length);
+ to->str_charset=from->str_charset;
return to;
}
-/* Make it easier to handle different charactersets */
-#ifdef USE_MB
-#define INC_PTR(A,B) A+=((use_mb_flag && \
- my_ismbchar(default_charset_info,A,B)) ? \
- my_ismbchar(default_charset_info,A,B) : 1)
-#else
-#define INC_PTR(A,B) A++
-#endif
+/****************************************************************************
+ Help functions
+****************************************************************************/
/*
-** Compare string against string with wildcard
-** 0 if matched
-** -1 if not matched with wildcard
-** 1 if matched with wildcard
+ copy a string from one character set to another
+
+ SYNOPSIS
+ copy_and_convert()
+ to Store result here
+ to_cs Character set of result string
+ from Copy from here
+ from_length Length of from string
+ from_cs From character set
+
+ NOTES
+ 'to' must be big enough as form_length * to_cs->mbmaxlen
+
+ RETURN
+ length of bytes copied to 'to'
*/
-#ifdef LIKE_CMP_TOUPPER
-#define likeconv(A) (uchar) toupper(A)
-#else
-#define likeconv(A) (uchar) my_sort_order[(uchar) (A)]
-#endif
-int wild_case_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,
- char escape)
+static uint32
+copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length, CHARSET_INFO *from_cs)
{
- int result= -1; // Not found, using wildcards
-#ifdef USE_MB
- bool use_mb_flag=use_mb(default_charset_info);
-#endif
- while (wildstr != wildend)
- {
- while (*wildstr != wild_many && *wildstr != wild_one)
- {
- if (*wildstr == escape && wildstr+1 != wildend)
- wildstr++;
-#ifdef USE_MB
- int l;
- if (use_mb_flag &&
- (l = my_ismbchar(default_charset_info, wildstr, wildend)))
- {
- if (str+l > str_end || memcmp(str, wildstr, l) != 0)
- return 1;
- str += l;
- wildstr += l;
- }
- else
-#endif
- if (str == str_end || likeconv(*wildstr++) != likeconv(*str++))
- return(1); // No match
- if (wildstr == wildend)
- return (str != str_end); // Match if both are at end
- result=1; // Found an anchor char
- }
- if (*wildstr == wild_one)
- {
- do
- {
- if (str == str_end) // Skip one char if possible
- return (result);
- INC_PTR(str,str_end);
- } while (++wildstr < wildend && *wildstr == wild_one);
- if (wildstr == wildend)
- break;
- }
- if (*wildstr == wild_many)
- { // Found wild_many
- wildstr++;
- /* Remove any '%' and '_' from the wild search string */
- for (; wildstr != wildend ; wildstr++)
- {
- if (*wildstr == wild_many)
- continue;
- if (*wildstr == wild_one)
- {
- if (str == str_end)
- return (-1);
- INC_PTR(str,str_end);
- continue;
- }
- break; // Not a wild character
- }
- if (wildstr == wildend)
- return(0); // Ok if wild_many is last
- if (str == str_end)
- return -1;
-
- uchar cmp;
- if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
- cmp= *++wildstr;
-#ifdef USE_MB
- const char* mb = wildstr;
- int mblen;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(default_charset_info, wildstr, wildend);
-#endif
- INC_PTR(wildstr,wildend); // This is compared trough cmp
- cmp=likeconv(cmp);
- do
- {
-#ifdef USE_MB
- if (use_mb_flag)
- {
- for (;;)
- {
- if (str >= str_end)
- return -1;
- if (mblen)
- {
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(default_charset_info, str, str_end) &&
- likeconv(*str) == cmp)
- {
- str++;
- break;
- }
- INC_PTR(str, str_end);
- }
- }
- else
- {
-#endif /* USE_MB */
- while (str != str_end && likeconv(*str) != cmp)
- str++;
- if (str++ == str_end) return (-1);
-#ifdef USE_MB
- }
-#endif
- {
- int tmp=wild_case_compare(str,str_end,wildstr,wildend,escape);
- if (tmp <= 0)
- return (tmp);
- }
- } while (str != str_end && wildstr[0] != wild_many);
- return(-1);
- }
- }
- return (str != str_end ? 1 : 0);
-}
-
-
-int wild_case_compare(String &match,String &wild, char escape)
-{
- DBUG_ENTER("wild_case_compare");
- DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
- ,match.ptr(),wild.ptr(),escape));
- DBUG_RETURN(wild_case_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape));
-}
+ int cnvres;
+ my_wc_t wc;
+ const uchar *from_end= (const uchar*) from+from_length;
+ char *to_start= to;
+ uchar *to_end= (uchar*) to+to_length;
-/*
-** The following is used when using LIKE on binary strings
-*/
-
-int wild_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape)
-{
- DBUG_ENTER("wild_compare");
- DBUG_PRINT("enter",("str='%s', str_end='%s', wildstr='%s', wildend='%s', escape='%c'"
- ,str,str_end,wildstr,wildend,escape));
- int result= -1; // Not found, using wildcards
- while (wildstr != wildend)
+ while (1)
{
- while (*wildstr != wild_many && *wildstr != wild_one)
+ if ((cnvres=from_cs->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0)
+ from+= cnvres;
+ else if (cnvres == MY_CS_ILSEQ)
{
- if (*wildstr == escape && wildstr+1 != wildend)
- wildstr++;
- if (str == str_end || *wildstr++ != *str++)
- {
- DBUG_RETURN(1);
- }
- if (wildstr == wildend)
- {
- DBUG_RETURN(str != str_end); // Match if both are at end
- }
- result=1; // Found an anchor char
+ from++;
+ wc= '?';
}
- if (*wildstr == wild_one)
+ else
+ break; // Impossible char.
+
+outp:
+ if ((cnvres= to_cs->wc_mb(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
{
- do
- {
- if (str == str_end) // Skip one char if possible
- DBUG_RETURN(result);
- str++;
- } while (*++wildstr == wild_one && wildstr != wildend);
- if (wildstr == wildend)
- break;
- }
- if (*wildstr == wild_many)
- { // Found wild_many
- wildstr++;
- /* Remove any '%' and '_' from the wild search string */
- for (; wildstr != wildend ; wildstr++)
- {
- if (*wildstr == wild_many)
- continue;
- if (*wildstr == wild_one)
- {
- if (str == str_end)
- {
- DBUG_RETURN(-1);
- }
- str++;
- continue;
- }
- break; // Not a wild character
- }
- if (wildstr == wildend)
- {
- DBUG_RETURN(0); // Ok if wild_many is last
- }
- if (str == str_end)
- {
- DBUG_RETURN(-1);
- }
- char cmp;
- if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
- cmp= *++wildstr;
- wildstr++; // This is compared trough cmp
- do
- {
- while (str != str_end && *str != cmp)
- str++;
- if (str++ == str_end)
- {
- DBUG_RETURN(-1);
- }
- {
- int tmp=wild_compare(str,str_end,wildstr,wildend,escape);
- if (tmp <= 0)
- {
- DBUG_RETURN(tmp);
- }
- }
- } while (str != str_end && wildstr[0] != wild_many);
- DBUG_RETURN(-1);
+ wc= '?';
+ goto outp;
}
+ else
+ break;
}
- DBUG_RETURN(str != str_end ? 1 : 0);
-}
-
-
-int wild_compare(String &match,String &wild, char escape)
-{
- DBUG_ENTER("wild_compare");
- DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
- ,match.ptr(),wild.ptr(),escape));
- DBUG_RETURN(wild_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape));
+ return (uint32) (to - to_start);
}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index ad7455ecbf1..6d54373f642 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -28,34 +28,52 @@ class String;
int sortcmp(const String *a,const String *b);
int stringcmp(const String *a,const String *b);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
-int wild_case_compare(String &match,String &wild,char escape);
-int wild_compare(String &match,String &wild,char escape);
class String
{
char *Ptr;
uint32 str_length,Alloced_length;
bool alloced;
+ CHARSET_INFO *str_charset;
public:
String()
- { Ptr=0; str_length=Alloced_length=0; alloced=0; }
+ {
+ Ptr=0; str_length=Alloced_length=0; alloced=0;
+ str_charset=default_charset_info;
+ }
String(uint32 length_arg)
- { alloced=0; Alloced_length=0; (void) real_alloc(length_arg); }
- String(const char *str)
- { Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;}
- String(const char *str,uint32 len)
- { Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;}
- String(char *str,uint32 len)
- { Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;}
+ {
+ alloced=0; Alloced_length=0; (void) real_alloc(length_arg);
+ str_charset=default_charset_info;
+ }
+ String(const char *str, CHARSET_INFO *cs)
+ {
+ Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;
+ str_charset=cs;
+ }
+ String(const char *str,uint32 len, CHARSET_INFO *cs)
+ {
+ Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;
+ str_charset=cs;
+ }
+ String(char *str,uint32 len, CHARSET_INFO *cs)
+ {
+ Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;
+ str_charset=cs;
+ }
String(const String &str)
- { Ptr=str.Ptr ; str_length=str.str_length ;
- Alloced_length=str.Alloced_length; alloced=0; }
-
+ {
+ Ptr=str.Ptr ; str_length=str.str_length ;
+ Alloced_length=str.Alloced_length; alloced=0;
+ str_charset=str.str_charset;
+ }
static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
{ sql_element_free(ptr_arg); }
~String() { free(); }
+ inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; }
+ inline CHARSET_INFO *charset() const { return str_charset; }
inline uint32 length() const { return str_length;}
inline uint32 alloced_length() const { return Alloced_length;}
inline char& operator [] (uint32 i) const { return Ptr[i]; }
@@ -83,28 +101,32 @@ public:
Alloced_length=str.Alloced_length-offset;
else
Alloced_length=0;
+ str_charset=str.str_charset;
}
- inline void set(char *str,uint32 arg_length)
+ inline void set(char *str,uint32 arg_length, CHARSET_INFO *cs)
{
free();
Ptr=(char*) str; str_length=Alloced_length=arg_length ; alloced=0;
+ str_charset=cs;
}
- inline void set(const char *str,uint32 arg_length)
+ inline void set(const char *str,uint32 arg_length, CHARSET_INFO *cs)
{
free();
Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0;
+ str_charset=cs;
}
- inline void set_quick(char *str,uint32 arg_length)
+ bool set_latin1(const char *str, uint32 arg_length);
+ inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs)
{
if (!alloced)
{
Ptr=(char*) str; str_length=Alloced_length=arg_length;
}
+ str_charset=cs;
}
- bool set(longlong num);
- /* bool set(long num); */
- bool set(ulonglong num);
- bool set(double num,uint decimals=2);
+ bool set(longlong num, CHARSET_INFO *cs);
+ bool set(ulonglong num, CHARSET_INFO *cs);
+ bool set(double num,uint decimals, CHARSET_INFO *cs);
inline void free()
{
if (alloced)
@@ -155,7 +177,9 @@ public:
bool copy(); // Alloc string if not alloced
bool copy(const String &s); // Allocate new string
- bool copy(const char *s,uint32 arg_length); // Allocate new string
+ bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string
+ bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
+ CHARSET_INFO *csto);
bool append(const String &s);
bool append(const char *s,uint32 arg_length=0);
bool append(IO_CACHE* file, uint32 arg_length);
@@ -179,13 +203,82 @@ public:
}
bool fill(uint32 max_length,char fill);
void strip_sp();
- inline void caseup() { ::caseup(Ptr,str_length); }
- inline void casedn() { ::casedn(Ptr,str_length); }
+ inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
+ inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
friend int sortcmp(const String *a,const String *b);
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
- friend int wild_case_compare(String &match,String &wild,char escape);
- friend int wild_compare(String &match,String &wild,char escape);
uint32 numchars();
int charpos(int i,uint32 offset=0);
+
+ int reserve(uint32 space_needed)
+ {
+ return realloc(str_length + space_needed);
+ }
+ int reserve(uint32 space_needed, uint32 grow_by);
+
+ /*
+ The following append operations do NOT check alloced memory
+ q_*** methods writes values of parameters itself
+ qs_*** methods writes string representation of value
+ */
+ void q_append(const char &c)
+ {
+ Ptr[str_length++] = c;
+ }
+ void q_append(const uint32 n)
+ {
+ int4store(Ptr + str_length, n);
+ str_length += 4;
+ }
+ void q_append(double d)
+ {
+ float8store(Ptr + str_length, d);
+ str_length += 8;
+ }
+ void q_append(double *d)
+ {
+ float8store(Ptr + str_length, *d);
+ str_length += 8;
+ }
+ void q_append(const char *data, uint32 data_len)
+ {
+ memcpy(Ptr + str_length, data, data_len);
+ str_length += data_len;
+ }
+
+ void WriteAtPosition(int position, uint32 value)
+ {
+ int4store(Ptr + position,value);
+ }
+
+ void qs_append(const char *str);
+ void qs_append(double d);
+ void qs_append(double *d);
+ void qs_append(const char &c);
+
+ /* Inline (general) functions used by the protocol functions */
+
+ inline char *prep_append(uint32 arg_length, uint32 step_alloc)
+ {
+ uint32 new_length= arg_length + str_length;
+ if (new_length > Alloced_length)
+ {
+ if (realloc(new_length + step_alloc))
+ return 0;
+ }
+ uint32 old_length= str_length;
+ str_length+= arg_length;
+ return Ptr+ old_length; /* Area to use */
+ }
+
+ inline bool append(const char *s, uint32 arg_length, uint32 step_alloc)
+ {
+ uint32 new_length= arg_length + str_length;
+ if (new_length > Alloced_length && realloc(new_length + step_alloc))
+ return TRUE;
+ memcpy(Ptr+str_length, s, arg_length);
+ str_length+= arg_length;
+ return FALSE;
+ }
};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e8857a7faeb..81adda55deb 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -23,7 +23,6 @@
#endif
#include <hash.h>
#include <myisam.h>
-#include <assert.h>
#ifdef __WIN__
#include <io.h>
@@ -37,7 +36,7 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
enum enum_duplicates handle_duplicates,
- ORDER *order,
+ uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
/*
@@ -63,7 +62,8 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
*/
-int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
+int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary)
{
int error;
DBUG_ENTER("mysql_rm_table");
@@ -74,7 +74,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- if (global_read_lock)
+ if (!drop_temporary && global_read_lock)
{
if (thd->global_read_lock)
{
@@ -89,7 +89,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
}
}
- error=mysql_rm_table_part2(thd,tables,if_exists,0);
+ error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, 0);
err:
pthread_mutex_unlock(&LOCK_open);
@@ -102,7 +102,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
if (error)
DBUG_RETURN(-1);
- send_ok(&thd->net);
+ send_ok(thd);
DBUG_RETURN(0);
}
@@ -128,14 +128,15 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
int mysql_rm_table_part2_with_lock(THD *thd,
TABLE_LIST *tables, bool if_exists,
- bool dont_log_query)
+ bool drop_temporary, bool dont_log_query)
{
int error;
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- error=mysql_rm_table_part2(thd,tables, if_exists, dont_log_query);
+ error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
+ dont_log_query);
pthread_mutex_unlock(&LOCK_open);
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
@@ -149,6 +150,17 @@ int mysql_rm_table_part2_with_lock(THD *thd,
/*
+ Execute the drop of a normal or temporary table
+
+ SYNOPSIS
+ mysql_rm_table_part2()
+ thd Thread handler
+ tables Tables to drop
+ if_exists If set, don't give an error if table doesn't exists.
+ In this case we give an warning of level 'NOTE'
+ drop_temporary Only drop temporary tables
+ dont_log_query Don't log the query
+
TODO:
When logging to the binary log, we should log
tmp_tables and transactional tables as separate statements if we
@@ -158,10 +170,15 @@ int mysql_rm_table_part2_with_lock(THD *thd,
The current code only writes DROP statements that only uses temporary
tables to the cache binary log. This should be ok on most cases, but
not all.
+
+ RETURN
+ 0 ok
+ 1 Error
+ -1 Thread was killed
*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool dont_log_query)
+ bool drop_temporary, bool dont_log_query)
{
TABLE_LIST *table;
char path[FN_REFLEN];
@@ -181,29 +198,35 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
continue; // removed temporary table
}
- abort_locked_tables(thd,db,table->real_name);
- while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed)
- {
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
- }
- drop_locked_tables(thd,db,table->real_name);
- if (thd->killed)
- DBUG_RETURN(-1);
-
- /* remove form file and isam files */
- strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
- NullS);
- (void) unpack_filename(path,path);
error=0;
+ if (!drop_temporary)
+ {
+ abort_locked_tables(thd,db,table->real_name);
+ while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed)
+ {
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
+ }
+ drop_locked_tables(thd,db,table->real_name);
+ if (thd->killed)
+ DBUG_RETURN(-1);
- table_type=get_table_type(path);
+ /* remove form file and isam files */
+ strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
+ NullS);
+ (void) unpack_filename(path,path);
- if (access(path,F_OK))
+ table_type=get_table_type(path);
+ }
+ if (drop_temporary || access(path,F_OK))
{
- if (!if_exists)
- error=1;
+ if (if_exists)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
+ table->real_name);
+ else
+ error= 1;
}
else
{
@@ -224,9 +247,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
{
if (wrong_tables.length())
wrong_tables.append(',');
- wrong_tables.append(String(table->real_name));
+ wrong_tables.append(String(table->real_name,default_charset_info));
}
}
+ thd->tmp_table_used= tmp_table_deleted;
if (some_tables_deleted || tmp_table_deleted)
{
query_cache_invalidate3(thd, tables, 0);
@@ -278,7 +302,6 @@ int quick_rm_table(enum db_type base,const char *db,
PRIMARY keys are prioritized.
*/
-
static int sort_keys(KEY *a, KEY *b)
{
if (a->flags & HA_NOSAME)
@@ -343,7 +366,8 @@ static int sort_keys(KEY *a, KEY *b)
int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
List<create_field> &fields,
- List<Key> &keys,bool tmp_table,bool no_log)
+ List<Key> &keys,bool tmp_table,bool no_log,
+ uint select_field_count)
{
char path[FN_REFLEN];
const char *key_name;
@@ -351,14 +375,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
int error= -1;
uint db_options,field,null_fields,blob_columns;
ulong pos;
- KEY *key_info,*key_info_buffer;
+ KEY *key_info,*key_info_buffer;
KEY_PART_INFO *key_part_info;
int auto_increment=0;
handler *file;
+ int field_no,dup_no;
DBUG_ENTER("mysql_create_table");
/*
- ** Check for duplicate fields and check type of table to create
+ Check for duplicate fields and check type of table to create
*/
if (!fields.elements)
@@ -367,6 +392,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
List_iterator<create_field> it(fields),it2(fields);
+ int select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0;
db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
@@ -380,10 +406,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
- /* Don't pack keys in old tables if the user has requested this */
-
- while ((sql_field=it++))
+ for (field_no=0; (sql_field=it++) ; field_no++)
{
+ /* Don't pack keys in old tables if the user has requested this */
if ((sql_field->flags & BLOB_FLAG) ||
sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
create_info->row_type != ROW_TYPE_FIXED)
@@ -392,12 +417,36 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
- while ((dup_field=it2++) != sql_field)
+
+ /* Check if we have used the same field name before */
+ for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
{
- if (my_strcasecmp(sql_field->field_name, dup_field->field_name) == 0)
+ if (my_strcasecmp(system_charset_info,
+ sql_field->field_name,
+ dup_field->field_name) == 0)
{
- my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
- DBUG_RETURN(-1);
+ /*
+ If this was a CREATE ... SELECT statement, accept a field
+ redefinition if we are changing a field in the SELECT part
+ */
+ if (field_no < select_field_pos || dup_no >= select_field_pos)
+ {
+ my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+ else
+ {
+ /* Field redefined */
+ sql_field->length= dup_field->length;
+ sql_field->decimals= dup_field->decimals;
+ sql_field->flags= dup_field->flags;
+ sql_field->pack_length= dup_field->pack_length;
+ sql_field->unireg_check= dup_field->unireg_check;
+ sql_field->sql_type= dup_field->sql_type;
+ it2.remove(); // Remove first (create) definition
+ select_field_pos--;
+ break;
+ }
}
}
it2.rewind();
@@ -410,6 +459,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
it.rewind();
while ((sql_field=it++))
{
+ if (!sql_field->charset)
+ sql_field->charset = create_info->table_charset ?
+ create_info->table_charset :
+ thd->db_charset? thd->db_charset :
+ default_charset_info;
+
switch (sql_field->sql_type) {
case FIELD_TYPE_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
@@ -418,7 +473,17 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
sql_field->pack_flag=FIELDFLAG_BLOB |
pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr);
- if (sql_field->flags & BINARY_FLAG)
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->length=8; // Unireg field length
+ sql_field->unireg_check=Field::BLOB_FIELD;
+ blob_columns++;
+ break;
+ case FIELD_TYPE_GEOMETRY:
+ sql_field->pack_flag=FIELDFLAG_GEOM |
+ pack_length_to_packflag(sql_field->pack_length -
+ portable_sizeof_char_ptr);
+ if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
@@ -427,17 +492,21 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_STRING:
sql_field->pack_flag=0;
- if (sql_field->flags & BINARY_FLAG)
+ if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
break;
case FIELD_TYPE_ENUM:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_INTERVAL;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD;
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_BITFIELD;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD;
break;
case FIELD_TYPE_DATE: // Rest of string types
@@ -488,35 +557,50 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Create keys */
List_iterator<Key> key_iterator(keys);
- uint key_parts=0,key_count=keys.elements;
+ uint key_parts=0, key_count=0, fk_key_count=0;
List<Key> keys_in_order; // Add new keys here
bool primary_key=0,unique_key=0;
Key *key;
uint tmp, key_number;
- tmp=min(file->max_keys(), MAX_KEY);
- if (key_count > tmp)
- {
- my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
- DBUG_RETURN(-1);
- }
/* Calculate number of key segements */
while ((key=key_iterator++))
{
+ if (key->type == Key::FOREIGN_KEY)
+ {
+ fk_key_count++;
+ foreign_key *fk_key= (foreign_key*) key;
+ if (fk_key->ref_columns.elements &&
+ fk_key->ref_columns.elements != fk_key->columns.elements)
+ {
+ my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
+ "foreign key without name",
+ ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
+ DBUG_RETURN(-1);
+ }
+ continue;
+ }
+ key_count++;
tmp=max(file->max_key_parts(),MAX_REF_PARTS);
if (key->columns.elements > tmp)
{
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
DBUG_RETURN(-1);
}
- if (key->name() && strlen(key->name()) > NAME_LEN)
+ if (key->name && strlen(key->name) > NAME_LEN)
{
- my_error(ER_TOO_LONG_IDENT, MYF(0), key->name());
+ my_error(ER_TOO_LONG_IDENT, MYF(0), key->name);
DBUG_RETURN(-1);
}
key_parts+=key->columns.elements;
}
+ tmp=min(file->max_keys(), MAX_KEY);
+ if (key_count > tmp)
+ {
+ my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
+ DBUG_RETURN(-1);
+ }
key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count);
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
@@ -525,13 +609,28 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_iterator.rewind();
key_number=0;
- for (; (key=key_iterator++) ; key_info++, key_number++)
+ for (; (key=key_iterator++) ; key_number++)
{
uint key_length=0;
key_part_spec *column;
- key_info->flags= (key->type == Key::MULTIPLE) ? 0 :
- (key->type == Key::FULLTEXT) ? HA_FULLTEXT : HA_NOSAME;
+ switch(key->type){
+ case Key::MULTIPLE:
+ key_info->flags = 0;
+ break;
+ case Key::FULLTEXT:
+ key_info->flags = HA_FULLTEXT;
+ break;
+ case Key::SPATIAL:
+ key_info->flags = HA_SPATIAL;
+ break;
+ case Key::FOREIGN_KEY:
+ key_number--; // Skip this key
+ continue;
+ default:
+ key_info->flags = HA_NOSAME;
+ }
+
key_info->key_parts=(uint8) key->columns.elements;
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
@@ -546,14 +645,46 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
}
-
+ /*
+ Make SPATIAL to be RTREE by default
+ SPATIAL only on BLOB or at least BINARY, this
+ actually should be replaced by special GEOM type
+ in near future when new frm file is ready
+ checking for proper key parts number:
+ */
+
+ if (key_info->flags == HA_SPATIAL)
+ {
+ if (key_info->key_parts != 1)
+ {
+ my_printf_error(ER_WRONG_ARGUMENTS,
+ ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX");
+ DBUG_RETURN(-1);
+ }
+ }
+ else if (key_info->algorithm == HA_KEY_ALG_RTREE)
+ {
+ if ((key_info->key_parts & 1) == 1)
+ {
+ my_printf_error(ER_WRONG_ARGUMENTS,
+ ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
+ DBUG_RETURN(-1);
+ }
+ /* TODO: To be deleted */
+ my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
+ MYF(0), "RTREE INDEX");
+ DBUG_RETURN(-1);
+ }
+
List_iterator<key_part_spec> cols(key->columns);
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
it.rewind();
field=0;
while ((sql_field=it++) &&
- my_strcasecmp(column->field_name,sql_field->field_name))
+ my_strcasecmp(system_charset_info,
+ column->field_name,
+ sql_field->field_name))
field++;
if (!sql_field)
{
@@ -574,6 +705,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (key->type == Key::FULLTEXT)
column->length=1; /* ft-code ignores it anyway :-) */
+ else if (key->type == Key::SPATIAL)
+ {
+ /*
+ BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
+ Lately we'll extend this code to support more dimensions
+ */
+ column->length=4*sizeof(double);
+ }
else
{
my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
@@ -665,7 +804,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_name=primary_key_name;
primary_key=1;
}
- else if (!(key_name = key->name()))
+ else if (!(key_name = key->name))
key_name=make_unique_key_name(sql_field->field_name,
key_info_buffer,key_info);
if (check_if_keyname_exists(key_name,key_info_buffer,key_info))
@@ -685,6 +824,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
DBUG_RETURN(-1);
}
+ key_info++;
}
if (!unique_key && !primary_key &&
(file->table_flags() & HA_REQUIRE_PRIMARY_KEY))
@@ -735,7 +875,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
thd->proc_info="creating table";
create_info->table_options=db_options;
- if (rea_create_table(path, create_info, fields, key_count,
+ if (rea_create_table(thd, path, create_info, fields, key_count,
key_info_buffer))
{
/* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
@@ -749,6 +889,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
(void) rm_temporary_table(create_info->db_type, path);
goto end;
}
+ thd->tmp_table_used= 1;
}
if (!tmp_table && !no_log)
{
@@ -777,7 +918,7 @@ static bool
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
{
for (KEY *key=start ; key != end ; key++)
- if (!my_strcasecmp(name,key->name))
+ if (!my_strcasecmp(system_charset_info,name,key->name))
return 1;
return 0;
}
@@ -813,6 +954,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
TABLE tmp_table; // Used during 'create_field()'
TABLE *table;
tmp_table.table_name=0;
+ uint select_field_count= items->elements;
DBUG_ENTER("create_table_from_items");
/* Add selected items to field list */
@@ -850,7 +992,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
/* create and lock table */
/* QQ: This should be done atomic ! */
if (mysql_create_table(thd,db,name,create_info,*extra_fields,
- *keys,0,1)) // no logging
+ *keys,0,1,select_field_count)) // no logging
DBUG_RETURN(0);
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
{
@@ -951,20 +1093,18 @@ bool close_cached_table(THD *thd,TABLE *table)
DBUG_RETURN(result);
}
-static int send_check_errmsg(THD* thd, TABLE_LIST* table,
+static int send_check_errmsg(THD *thd, TABLE_LIST* table,
const char* operator_name, const char* errmsg)
{
-
- String* packet = &thd->packet;
- packet->length(0);
- net_store_data(packet, table->alias);
- net_store_data(packet, (char*)operator_name);
- net_store_data(packet, "error");
- net_store_data(packet, errmsg);
+ Protocol *protocol= thd->protocol;
+ protocol->prepare_for_resend();
+ protocol->store(table->alias);
+ protocol->store((char*) operator_name);
+ protocol->store("error", 5);
+ protocol->store(errmsg);
thd->net.last_error[0]=0;
- if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
return -1;
return 1;
}
@@ -1110,8 +1250,8 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
TABLE_LIST *table;
List<Item> field_list;
- Item* item;
- String* packet = &thd->packet;
+ Item *item;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysql_admin_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@@ -1122,7 +1262,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1;
- if (send_fields(thd, field_list, 1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
for (table = tables; table; table = table->next)
@@ -1134,8 +1274,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->open_options|= extra_open_options;
table->table = open_ltable(thd, table, lock_type);
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0; // these errors shouldn't get client
+#endif
thd->open_options&= ~extra_open_options;
- packet->length(0);
+
if (prepare_func)
{
switch ((*prepare_func)(thd, table, check_opt)) {
@@ -1148,30 +1291,30 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (!table->table)
{
const char *err_msg;
- net_store_data(packet, table_name);
- net_store_data(packet, operator_name);
- net_store_data(packet, "error");
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(operator_name);
+ protocol->store("error",5);
if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
- net_store_data(packet, err_msg);
+ protocol->store(err_msg);
thd->net.last_error[0]=0;
- if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
continue;
}
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
- net_store_data(packet, table_name);
- net_store_data(packet, operator_name);
- net_store_data(packet, "error");
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(operator_name);
+ protocol->store("error", 5);
sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name);
- net_store_data(packet, buff);
+ protocol->store(buff);
close_thread_tables(thd);
table->table=0; // For query cache
- if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
continue;
}
@@ -1199,50 +1342,53 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
int result_code = (table->table->file->*operator_func)(thd, check_opt);
- packet->length(0);
- net_store_data(packet, table_name);
- net_store_data(packet, operator_name);
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0; // these errors shouldn't get client
+#endif
+ protocol->prepare_for_resend();
+ protocol->store(table_name);
+ protocol->store(operator_name);
switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED:
{
char buf[ERRMSGSIZE+20];
- my_snprintf(buf, ERRMSGSIZE,
- ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
- net_store_data(packet, "error");
- net_store_data(packet, buf);
+ uint length=my_snprintf(buf, ERRMSGSIZE,
+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
+ protocol->store("error", 5);
+ protocol->store(buf, length);
}
break;
case HA_ADMIN_OK:
- net_store_data(packet, "status");
- net_store_data(packet, "OK");
+ protocol->store("status", 6);
+ protocol->store("OK",2);
break;
case HA_ADMIN_FAILED:
- net_store_data(packet, "status");
- net_store_data(packet, "Operation failed");
+ protocol->store("status", 6);
+ protocol->store("Operation failed",16);
break;
case HA_ADMIN_ALREADY_DONE:
- net_store_data(packet, "status");
- net_store_data(packet, "Table is already up to date");
+ protocol->store("status", 6);
+ protocol->store("Table is already up to date", 27);
break;
case HA_ADMIN_CORRUPT:
- net_store_data(packet, "error");
- net_store_data(packet, "Corrupt");
+ protocol->store("error", 5);
+ protocol->store("Corrupt", 8);
fatal_error=1;
break;
case HA_ADMIN_INVALID:
- net_store_data(packet, "error");
- net_store_data(packet, "Invalid argument");
+ protocol->store("error", 5);
+ protocol->store("Invalid argument",16);
break;
default: // Probably HA_ADMIN_INTERNAL_ERROR
- net_store_data(packet, "error");
- net_store_data(packet, "Unknown - internal error during operation");
+ protocol->store("error", 5);
+ protocol->store("Unknown - internal error during operation", 41);
fatal_error=1;
break;
}
@@ -1259,12 +1405,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
close_thread_tables(thd);
table->table=0; // For query cache
- if (my_net_write(&thd->net, (char*) packet->ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
}
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_RETURN(0);
err:
close_thread_tables(thd); // Shouldn't be needed
@@ -1312,6 +1457,127 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
}
+/*
+ Create a table identical to the specified table
+
+ SYNOPSIS
+ mysql_create_like_table()
+ thd Thread object
+ table Table list (one table only)
+ create_info Create info
+ table_ident Src table_ident
+
+ RETURN VALUES
+ 0 ok
+ -1 error
+*/
+
+int mysql_create_like_table(THD* thd, TABLE_LIST* table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *table_ident)
+{
+ TABLE **tmp_table;
+ char src_path[FN_REFLEN], dst_path[FN_REFLEN];
+ char *db= table->db;
+ char *table_name= table->real_name;
+ char *src_db= thd->db;
+ char *src_table= table_ident->table.str;
+ int err;
+
+ DBUG_ENTER("mysql_create_like_table");
+
+ /*
+ Validate the source table
+ */
+ if (table_ident->table.length > NAME_LEN ||
+ (table_ident->table.length &&
+ check_table_name(src_table,table_ident->table.length)) ||
+ table_ident->db.str && check_db_name((src_db= table_ident->db.str)))
+ {
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
+ DBUG_RETURN(-1);
+ }
+
+ if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
+ strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
+ else
+ {
+ strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
+ reg_ext, NullS);
+ if (access(src_path, F_OK))
+ {
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
+ DBUG_RETURN(-1);
+ }
+ }
+
+ /*
+ Validate the destination table
+
+ skip the destination table name checking as this is already
+ validated.
+ */
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ if (find_temporary_table(thd, db, table_name))
+ goto table_exists;
+ sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix,
+ current_pid, thd->thread_id, thd->tmp_table++,reg_ext);
+ create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
+ }
+ else
+ {
+ strxmov(dst_path, mysql_data_home, "/", db, "/", table_name,
+ reg_ext, NullS);
+ if (!access(dst_path, F_OK))
+ goto table_exists;
+ }
+
+ /*
+ Create a new table by copying from source table
+ */
+ if (my_copy(src_path, dst_path, MYF(MY_WME)))
+ DBUG_RETURN(-1);
+
+ /*
+ As mysql_truncate don't work on a new table at this stage of
+ creation, instead create the table directly (for both normal
+ and temporary tables).
+ */
+ *fn_ext(dst_path)= 0;
+ err= ha_create_table(dst_path, create_info, 1);
+
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ if (err || !open_temporary_table(thd, dst_path, db, table_name, 1))
+ {
+ (void) rm_temporary_table(create_info->db_type,
+ dst_path); /* purecov: inspected */
+ DBUG_RETURN(-1); /* purecov: inspected */
+ }
+ }
+ else if (err)
+ {
+ (void) quick_rm_table(create_info->db_type, db,
+ table_name); /* purecov: inspected */
+ DBUG_RETURN(-1); /* purecov: inspected */
+ }
+ DBUG_RETURN(0);
+
+table_exists:
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_EXISTS_ERROR,warn_buff);
+ DBUG_RETURN(0);
+ }
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+ DBUG_RETURN(-1);
+}
+
+
int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
#ifdef OS2
@@ -1349,7 +1615,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
- ORDER *order,
+ uint order_num, ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff,
@@ -1383,9 +1649,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
strmov(new_name_buff,new_name);
fn_same(new_name_buff,table_name,3);
if (lower_case_table_names)
- casedn_str(new_name);
+ my_casedn_str(system_charset_info,new_name);
if ((lower_case_table_names &&
- !my_strcasecmp(new_name_buff,table_name)) ||
+ !my_strcasecmp(system_charset_info, new_name_buff,table_name)) ||
(!lower_case_table_names &&
!strcmp(new_name_buff,table_name)))
new_name=table_name; // No. Make later check easier
@@ -1469,7 +1735,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
- send_ok(&thd->net);
+ send_ok(thd);
}
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
@@ -1485,7 +1751,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<Key> key_list; // Add new keys here
/*
- ** First collect all fields from table which isn't in drop_list
+ First collect all fields from table which isn't in drop_list
*/
create_field *def;
@@ -1498,7 +1764,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
while ((drop=drop_it++))
{
if (drop->type == Alter_drop::COLUMN &&
- !my_strcasecmp(field->field_name, drop->name))
+ !my_strcasecmp(system_charset_info,field->field_name, drop->name))
{
/* Reset auto_increment value if it was dropped */
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
@@ -1519,7 +1785,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
def_it.rewind();
while ((def=def_it++))
{
- if (def->change && !my_strcasecmp(field->field_name, def->change))
+ if (def->change &&
+ !my_strcasecmp(system_charset_info,field->field_name, def->change))
break;
}
if (def)
@@ -1543,7 +1810,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Alter_column *alter;
while ((alter=alter_it++))
{
- if (!my_strcasecmp(field->field_name, alter->name))
+ if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
break;
}
if (alter)
@@ -1577,7 +1844,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
find_it.rewind();
while ((find=find_it++)) // Add new columns
{
- if (!my_strcasecmp(def->after, find->field_name))
+ if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
break;
}
if (!find)
@@ -1600,8 +1867,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
/*
- ** Collect all keys which isn't in drop list. Add only those
- ** for which some fields exists.
+ Collect all keys which isn't in drop list. Add only those
+ for which some fields exists.
*/
List_iterator<Key> key_it(keys);
@@ -1623,7 +1890,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
while ((drop=drop_it++))
{
if (drop->type == Alter_drop::KEY &&
- !my_strcasecmp(key_name, drop->name))
+ !my_strcasecmp(system_charset_info,key_name, drop->name))
break;
}
if (drop)
@@ -1645,11 +1912,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (cfield->change)
{
- if (!my_strcasecmp(key_part_name, cfield->change))
+ if (!my_strcasecmp(system_charset_info, key_part_name,
+ cfield->change))
break;
}
- else if (!my_strcasecmp(key_part_name, cfield->field_name))
- break;
+ else if (!my_strcasecmp(system_charset_info,
+ key_part_name, cfield->field_name))
+ break;
}
if (!cfield)
continue; // Field is removed
@@ -1666,18 +1935,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
key_part_length));
}
if (key_parts.elements)
- key_list.push_back(new Key(key_info->flags & HA_NOSAME ?
- (!my_strcasecmp(key_name, "PRIMARY") ?
+ key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
+ (key_info->flags & HA_NOSAME ?
+ (!my_strcasecmp(system_charset_info,
+ key_name, "PRIMARY") ?
Key::PRIMARY : Key::UNIQUE) :
- (key_info->flags & HA_FULLTEXT ?
- Key::FULLTEXT : Key::MULTIPLE),
- key_name,key_parts));
+ (key_info->flags & HA_FULLTEXT ?
+ Key::FULLTEXT : Key::MULTIPLE)),
+ key_name,
+ key_info->algorithm,
+ key_parts));
}
- key_it.rewind();
{
Key *key;
while ((key=key_it++)) // Add new keys
- key_list.push_back(key);
+ {
+ if (key->type != Key::FOREIGN_KEY)
+ key_list.push_back(key);
+ }
}
if (drop_list.elements)
@@ -1705,6 +1980,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->max_rows=table->max_rows;
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
create_info->avg_row_length=table->avg_row_length;
+ if (!(used_fields & HA_CREATE_USED_CHARSET))
+ create_info->table_charset=table->table_charset;
table->file->update_create_info(create_info);
if ((create_info->table_options &
@@ -1772,7 +2049,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info,
- create_list,key_list,1,1))) // no logging
+ create_list,key_list,1,1,0))) // no logging
DBUG_RETURN(error);
if (table->tmp_table)
@@ -1802,7 +2079,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates,
- order, &copied, &deleted);
+ order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields=0; // Don`t calc cuted fields
new_table->time_stamp=save_time_stamp;
@@ -1852,9 +2129,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
/*
- ** Data is copied. Now we rename the old table to a temp name,
- ** rename the new one to the old name, remove all entries from the old table
- ** from the cash, free all locks, close the old table and remove it.
+ Data is copied. Now we rename the old table to a temp name,
+ rename the new one to the old name, remove all entries from the old table
+ from the cash, free all locks, close the old table and remove it.
*/
thd->proc_info="rename result table";
@@ -1999,7 +2276,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
end_temporary:
sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted),
(ulong) deleted, thd->cuted_fields);
- send_ok(&thd->net,copied+deleted,0L,tmp_name);
+ send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(0);
@@ -2012,7 +2289,7 @@ static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
enum enum_duplicates handle_duplicates,
- ORDER *order,
+ uint order_num, ORDER *order,
ha_rows *copied,
ha_rows *deleted)
{
@@ -2060,10 +2337,13 @@ copy_data_between_tables(TABLE *from,TABLE *to,
tables.db = from->table_cache_key;
error=1;
- if (setup_order(thd, &tables, fields, all_fields, order) ||
+ if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
+ order_num)||
+ setup_order(thd, thd->lex.select_lex.ref_pointer_array,
+ &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (from->found_records = filesort(from, sortorder, length,
- (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ (from->found_records = filesort(thd, from, sortorder, length,
+ (SQL_SELECT *) 0, HA_POS_ERROR,
&examined_rows))
== HA_POS_ERROR)
goto err;
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index b226bc1300a..8984bcc6463 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -26,6 +26,24 @@
/* Intern key cache variables */
extern "C" pthread_mutex_t THR_LOCK_keycache;
+static const char *lock_descriptions[] =
+{
+ "No lock",
+ "Low priority read lock",
+ "Shared Read lock",
+ "High priority read lock",
+ "Read lock without concurrent inserts",
+ "Write lock that allows other writers",
+ "Write lock, but allow reading",
+ "Concurrent insert lock",
+ "Lock Used by delayed insert",
+ "Low priority write lock",
+ "High priority write lock",
+ "Highest priority write lock"
+};
+extern HASH open_cache;
+
+
#ifndef DBUG_OFF
void
@@ -34,7 +52,7 @@ print_where(COND *cond,const char *info)
if (cond)
{
char buff[256];
- String str(buff,(uint32) sizeof(buff));
+ String str(buff,(uint32) sizeof(buff), default_charset_info);
str.length(0);
cond->print(&str);
str.append('\0');
@@ -45,10 +63,8 @@ print_where(COND *cond,const char *info)
DBUG_UNLOCK_FILE;
}
}
-
/* This is for debugging purposes */
-extern HASH open_cache;
extern TABLE *unused_tables;
void print_cached_tables(void)
@@ -57,16 +73,16 @@ void print_cached_tables(void)
TABLE *start_link,*lnk;
VOID(pthread_mutex_lock(&LOCK_open));
- puts("DB Table Version Thread L.thread Open");
+ puts("DB Table Version Thread L.thread Open Lock");
for (idx=unused=0 ; idx < open_cache.records ; idx++)
{
TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
- printf("%-14.14s %-32s%6ld%8ld%10ld%6d\n",
+ printf("%-14.14s %-32s%6ld%8ld%10ld%6d %s\n",
entry->table_cache_key,entry->real_name,entry->version,
entry->in_use ? entry->in_use->thread_id : 0L,
entry->in_use ? entry->in_use->dbug_thread_id : 0L,
- entry->db_stat ? 1 : 0);
+ entry->db_stat ? 1 : 0, entry->in_use ? lock_descriptions[(int)entry->reginfo.lock_type] : "Not in use");
if (!entry->in_use)
unused++;
}
@@ -97,10 +113,11 @@ void print_cached_tables(void)
}
-void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special)
+void TEST_filesort(SORT_FIELD *sortorder,uint s_length)
{
char buff[256],buff2[256];
- String str(buff,sizeof(buff)),out(buff2,sizeof(buff2));
+ String str(buff,sizeof(buff),default_charset_info);
+ String out(buff2,sizeof(buff2),default_charset_info);
const char *sep;
DBUG_ENTER("TEST_filesort");
@@ -130,8 +147,6 @@ void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special)
out.append('\0'); // Purify doesn't like c_ptr()
DBUG_LOCK_FILE;
VOID(fputs("\nInfo about FILESORT\n",DBUG_FILE));
- if (special)
- fprintf(DBUG_FILE,"Records to sort: %ld\n",special);
fprintf(DBUG_FILE,"Sortorder: %s\n",out.ptr());
DBUG_UNLOCK_FILE;
DBUG_VOID_RETURN;
@@ -187,6 +202,100 @@ TEST_join(JOIN *join)
#endif
+typedef struct st_debug_lock
+{
+ ulong thread_id;
+ char table_name[FN_REFLEN];
+ bool waiting;
+ const char *lock_text;
+ enum thr_lock_type type;
+} TABLE_LOCK_INFO;
+
+static int dl_compare(TABLE_LOCK_INFO *a,TABLE_LOCK_INFO *b)
+{
+ if (a->thread_id > b->thread_id)
+ return 1;
+ if (a->thread_id < b->thread_id)
+ return -1;
+ if (a->waiting == b->waiting)
+ return 0;
+ else if (a->waiting)
+ return -1;
+ return 1;
+}
+
+static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data, bool wait, const char *text)
+{
+ if (data)
+ {
+ TABLE *table=(TABLE *)data->debug_print_param;
+ if (table && table->tmp_table == NO_TMP_TABLE)
+ {
+ TABLE_LOCK_INFO table_lock_info;
+ table_lock_info.thread_id=table->in_use->thread_id;
+ memcpy(table_lock_info.table_name, table->table_cache_key, table->key_length);
+ table_lock_info.table_name[strlen(table_lock_info.table_name)]='.';
+ table_lock_info.waiting=wait;
+ table_lock_info.lock_text=text;
+ table_lock_info.type=table->reginfo.lock_type; // obtainable also from THR_LOCK_DATA
+ VOID(push_dynamic(ar,(gptr) &table_lock_info));
+ }
+ }
+}
+/*
+ Regarding MERGE tables:
+
+For now, the best option is to use the common TABLE *pointer for all
+cases; The drawback is that for MERGE tables we will see many locks
+for the merge tables even if some of them are for individual tables.
+
+The way to solve this is to add to 'THR_LOCK' structure a pointer to
+the filename and use this when printing the data.
+(We can for now ignore this and just print the same name for all merge
+table parts; Please add the above as a comment to the display_lock
+function so that we can easily add this if we ever need this.
+
+*/
+
+static void display_table_locks (void)
+{
+ LIST *list;
+ DYNAMIC_ARRAY saved_table_locks;
+
+ VOID(my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO),open_cache.records + 20,50));
+ VOID(pthread_mutex_lock(&THR_LOCK_lock));
+ for (list=thr_lock_thread_list ; list ; list=rest(list))
+ {
+ THR_LOCK *lock=(THR_LOCK*) list->data;
+
+ VOID(pthread_mutex_lock(&lock->mutex));
+ push_locks_into_array(&saved_table_locks, lock->write.data, false, "Locked - write");
+ push_locks_into_array(&saved_table_locks, lock->write_wait.data, true, "Waiting - write");
+ push_locks_into_array(&saved_table_locks, lock->read.data, false, "Locked - read");
+ push_locks_into_array(&saved_table_locks, lock->read_wait.data, true, "Waiting - read");
+ VOID(pthread_mutex_unlock(&lock->mutex));
+ }
+ VOID(pthread_mutex_unlock(&THR_LOCK_lock));
+ if (!saved_table_locks.elements) goto end;
+
+ qsort((gptr) dynamic_element(&saved_table_locks,0,TABLE_LOCK_INFO *),saved_table_locks.elements,sizeof(TABLE_LOCK_INFO),(qsort_cmp) dl_compare);
+ freeze_size(&saved_table_locks);
+
+ puts("\nThread database.table_name Locked/Waiting Lock_type\n");
+
+ unsigned int i;
+ for (i=0 ; i < saved_table_locks.elements ; i++)
+ {
+ TABLE_LOCK_INFO *dl_ptr=dynamic_element(&saved_table_locks,i,TABLE_LOCK_INFO*);
+ printf("%-8ld%-28.28s%-22s%s\n",
+ dl_ptr->thread_id,dl_ptr->table_name,dl_ptr->lock_text,lock_descriptions[(int)dl_ptr->type]);
+ }
+ puts("\n\n");
+end:
+ delete_dynamic(&saved_table_locks);
+}
+
+
void mysql_print_status(THD *thd)
{
char current_dir[FN_REFLEN];
@@ -252,6 +361,7 @@ Next alarm time: %lu\n",
alarm_info.max_used_alarms,
alarm_info.next_alarm_time);
#endif
+ display_table_locks();
fflush(stdout);
if (thd)
thd->proc_info="malloc";
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 8a1c19568ae..387c9970e34 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -33,6 +33,7 @@
#endif
#include "mysql_priv.h"
+#include <my_pthread.h>
#ifdef HAVE_DLOPEN
extern "C"
@@ -70,10 +71,10 @@ extern "C"
static bool initialized = 0;
static MEM_ROOT mem;
static HASH udf_hash;
-static pthread_mutex_t THR_LOCK_udf;
+static rw_lock_t THR_LOCK_udf;
-static udf_func *add_udf(char *name, Item_result ret, char *dl,
+static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
Item_udftype typ);
static void del_udf(udf_func *udf);
static void *find_udf_dl(const char *dl);
@@ -83,8 +84,8 @@ static void init_syms(udf_func *tmp)
{
char nm[MAX_FIELD_NAME+16],*end;
- tmp->func = dlsym(tmp->dlhandle, tmp->name);
- end=strmov(nm,tmp->name);
+ tmp->func = dlsym(tmp->dlhandle, tmp->name.str);
+ end=strmov(nm,tmp->name.str);
(void) strmov(end,"_init");
tmp->func_init = dlsym(tmp->dlhandle, nm);
(void) strmov(end,"_deinit");
@@ -102,8 +103,8 @@ extern "C" byte* get_hash_key(const byte *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
udf_func *udf=(udf_func*) buff;
- *length=(uint) udf->name_length;
- return (byte*) udf->name;
+ *length=(uint) udf->name.length;
+ return (byte*) udf->name.str;
}
/*
@@ -122,12 +123,13 @@ void udf_init()
if (initialized)
DBUG_VOID_RETURN;
- pthread_mutex_init(&THR_LOCK_udf,MY_MUTEX_INIT_SLOW);
-
+ my_rwlock_init(&THR_LOCK_udf,NULL);
+
init_sql_alloc(&mem, 1024,0);
THD *new_thd = new THD;
if (!new_thd ||
- hash_init(&udf_hash,32,0,0,get_hash_key, NULL, HASH_CASE_INSENSITIVE))
+ hash_init(&udf_hash,system_charset_info,
+ 32,0,0,get_hash_key, NULL, HASH_CASE_INSENSITIVE))
{
sql_print_error("Can't allocate memory for udf structures");
hash_free(&udf_hash);
@@ -159,14 +161,16 @@ void udf_init()
while (!(error = read_record_info.read_record(&read_record_info)))
{
DBUG_PRINT("info",("init udf record"));
- char *name=get_field(&mem, table, 0);
- char *dl_name= get_field(&mem, table, 2);
+ LEX_STRING name;
+ name.str=get_field(&mem, table->field[0]);
+ name.length = strlen(name.str);
+ char *dl_name= get_field(&mem, table->field[2]);
bool new_dl=0;
Item_udftype udftype=UDFTYPE_FUNCTION;
if (table->fields >= 4) // New func table
udftype=(Item_udftype) table->field[3]->val_int();
- if (!(tmp = add_udf(name,(Item_result) table->field[1]->val_int(),
+ if (!(tmp = add_udf(&name,(Item_result) table->field[1]->val_int(),
dl_name, udftype)))
{
sql_print_error("Can't alloc memory for udf function: name");
@@ -232,7 +236,7 @@ void udf_free()
if (initialized)
{
initialized= 0;
- pthread_mutex_destroy(&THR_LOCK_udf);
+ rwlock_destroy(&THR_LOCK_udf);
}
DBUG_VOID_RETURN;
}
@@ -253,10 +257,10 @@ static void del_udf(udf_func *udf)
The functions will be automaticly removed when the least threads
doesn't use it anymore
*/
- char *name= udf->name;
- uint name_length=udf->name_length;
- udf->name=(char*) "*";
- udf->name_length=1;
+ char *name= udf->name.str;
+ uint name_length=udf->name.length;
+ udf->name.str=(char*) "*";
+ udf->name.length=1;
hash_update(&udf_hash,(byte*) udf,(byte*) name,name_length);
}
DBUG_VOID_RETURN;
@@ -266,7 +270,7 @@ static void del_udf(udf_func *udf)
void free_udf(udf_func *udf)
{
DBUG_ENTER("free_udf");
- pthread_mutex_lock(&THR_LOCK_udf);
+ rw_wrlock(&THR_LOCK_udf);
if (!--udf->usage_count)
{
/*
@@ -278,7 +282,7 @@ void free_udf(udf_func *udf)
if (!find_udf_dl(udf->dl))
dlclose(udf->dlhandle);
}
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_VOID_RETURN;
}
@@ -291,7 +295,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
DBUG_ENTER("find_udf");
/* TODO: This should be changed to reader locks someday! */
- pthread_mutex_lock(&THR_LOCK_udf);
+ rw_rdlock(&THR_LOCK_udf);
if ((udf=(udf_func*) hash_search(&udf_hash,(byte*) name,
length ? length : (uint) strlen(name))))
{
@@ -300,7 +304,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
else if (mark_used)
udf->usage_count++;
}
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(udf);
}
@@ -325,7 +329,7 @@ static void *find_udf_dl(const char *dl)
/* Assume that name && dl is already allocated */
-static udf_func *add_udf(char *name, Item_result ret, char *dl,
+static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
Item_udftype type)
{
if (!name || !dl || !(uint) type || (uint) type > (uint) UDFTYPE_AGGREGATE)
@@ -334,8 +338,7 @@ static udf_func *add_udf(char *name, Item_result ret, char *dl,
if (!tmp)
return 0;
bzero((char*) tmp,sizeof(*tmp));
- tmp->name = name;
- tmp->name_length=(uint) strlen(tmp->name);
+ tmp->name = *name; //dup !!
tmp->dl = dl;
tmp->returns = ret;
tmp->type = type;
@@ -359,7 +362,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (!initialized)
{
- send_error(&thd->net, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
DBUG_RETURN(1);
}
@@ -370,19 +373,19 @@ int mysql_create_function(THD *thd,udf_func *udf)
*/
if (strchr(udf->dl, '/'))
{
- send_error(&thd->net, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS));
+ send_error(thd, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS));
DBUG_RETURN(1);
}
- if (udf->name_length > NAME_LEN)
+ if (udf->name.length > NAME_LEN)
{
- net_printf(&thd->net, ER_TOO_LONG_IDENT,udf->name);
+ net_printf(thd, ER_TOO_LONG_IDENT,udf->name);
DBUG_RETURN(1);
}
- pthread_mutex_lock(&THR_LOCK_udf);
- if ((hash_search(&udf_hash,(byte*) udf->name, udf->name_length)))
+ rw_wrlock(&THR_LOCK_udf);
+ if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
{
- net_printf(&thd->net, ER_UDF_EXISTS, udf->name);
+ net_printf(thd, ER_UDF_EXISTS, udf->name);
goto err;
}
if (!(dl = find_udf_dl(udf->dl)))
@@ -391,7 +394,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
{
DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)",
udf->dl,errno,dlerror()));
- net_printf(&thd->net, ER_CANT_OPEN_LIBRARY, udf->dl, errno, dlerror());
+ net_printf(thd, ER_CANT_OPEN_LIBRARY, udf->dl, errno, dlerror());
goto err;
}
new_dl=1;
@@ -401,14 +404,14 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (udf->func == NULL)
{
- net_printf(&thd->net, ER_CANT_FIND_DL_ENTRY, udf->name);
+ net_printf(thd, ER_CANT_FIND_DL_ENTRY, udf->name);
goto err;
}
- udf->name=strdup_root(&mem,udf->name);
+ udf->name.str=strdup_root(&mem,udf->name.str);
udf->dl=strdup_root(&mem,udf->dl);
- if (!(u_d=add_udf(udf->name,udf->returns,udf->dl,udf->type)))
+ if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type)))
{
- send_error(&thd->net,0); // End of memory
+ send_error(thd,0); // End of memory
goto err;
}
u_d->dlhandle = dl;
@@ -428,9 +431,9 @@ int mysql_create_function(THD *thd,udf_func *udf)
goto err;
restore_record(table,2); // Get default values for fields
- table->field[0]->store(u_d->name, u_d->name_length);
+ table->field[0]->store(u_d->name.str, u_d->name.length, default_charset_info);
table->field[1]->store((longlong) u_d->returns);
- table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl));
+ table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl), default_charset_info);
if (table->fields >= 4) // If not old func format
table->field[3]->store((longlong) u_d->type);
error = table->file->write_row(table->record[0]);
@@ -438,22 +441,22 @@ int mysql_create_function(THD *thd,udf_func *udf)
close_thread_tables(thd);
if (error)
{
- net_printf(&thd->net, ER_ERROR_ON_WRITE, "func@mysql",error);
+ net_printf(thd, ER_ERROR_ON_WRITE, "func@mysql",error);
del_udf(u_d);
goto err;
}
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(0);
err:
if (new_dl)
dlclose(dl);
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(1);
}
-int mysql_drop_function(THD *thd,const char *udf_name)
+int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
{
TABLE *table;
TABLE_LIST tables;
@@ -461,14 +464,14 @@ int mysql_drop_function(THD *thd,const char *udf_name)
DBUG_ENTER("mysql_drop_function");
if (!initialized)
{
- send_error(&thd->net, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
DBUG_RETURN(1);
}
- pthread_mutex_lock(&THR_LOCK_udf);
- if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name,
- (uint) strlen(udf_name))))
+ rw_wrlock(&THR_LOCK_udf);
+ if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str,
+ (uint) udf_name->length)))
{
- net_printf(&thd->net, ER_FUNCTION_NOT_DEFINED, udf_name);
+ net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name);
goto err;
}
del_udf(udf);
@@ -484,8 +487,8 @@ int mysql_drop_function(THD *thd,const char *udf_name)
tables.real_name= tables.alias= (char*) "func";
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
goto err;
- if (!table->file->index_read_idx(table->record[0],0,(byte*) udf_name,
- (uint) strlen(udf_name),
+ if (!table->file->index_read_idx(table->record[0],0,(byte*) udf_name->str,
+ (uint) udf_name->length,
HA_READ_KEY_EXACT))
{
int error;
@@ -494,10 +497,10 @@ int mysql_drop_function(THD *thd,const char *udf_name)
}
close_thread_tables(thd);
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(0);
err:
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(1);
}
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index 1ee9c44ce48..29a351ac52f 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -25,8 +25,7 @@ enum Item_udftype {UDFTYPE_FUNCTION=1,UDFTYPE_AGGREGATE};
typedef struct st_udf_func
{
- char *name;
- int name_length;
+ LEX_STRING name;
Item_result returns;
Item_udftype type;
char *dl;
@@ -61,7 +60,7 @@ class udf_handler :public Sql_alloc
initialized(0)
{}
~udf_handler();
- const char *name() const { return u_d ? u_d->name : "?"; }
+ const char *name() const { return u_d ? u_d->name.str : "?"; }
Item_result result_type () const
{ return u_d ? u_d->returns : STRING_RESULT;}
bool get_arguments();
@@ -140,5 +139,5 @@ void udf_init(void),udf_free(void);
udf_func *find_udf(const char *name, uint len=0,bool mark_used=0);
void free_udf(udf_func *udf);
int mysql_create_function(THD *thd,udf_func *udf);
-int mysql_drop_function(THD *thd,const char *name);
+int mysql_drop_function(THD *thd,const LEX_STRING *name);
#endif
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 4e36ccafefc..bc1449aeda0 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,108 +24,147 @@
#include "mysql_priv.h"
#include "sql_select.h"
-
-int mysql_union(THD *thd, LEX *lex,select_result *result)
+int mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit, bool tables_and_fields_initied)
{
- SELECT_LEX *sl, *last_sl, *lex_sl;
- ORDER *order;
- List<Item> item_list;
- TABLE *table;
- int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0;
- int res;
- bool found_rows_for_union= 0;
- TABLE_LIST result_table_list;
- TABLE_LIST *first_table=(TABLE_LIST *)lex->select_lex.table_list.first;
- TMP_TABLE_PARAM tmp_table_param;
- select_union *union_result;
DBUG_ENTER("mysql_union");
+ int res= 0;
+ if (!(res= unit->prepare(thd, result, tables_and_fields_initied)))
+ res= unit->exec();
+ res|= unit->cleanup();
+ DBUG_RETURN(res);
+}
+
- /* Fix tables 'to-be-unioned-from' list to point at opened tables */
- last_sl= &lex->select_lex;
- for (sl= last_sl;
- sl && sl->linkage != NOT_A_SELECT;
- last_sl=sl, sl=sl->next)
+/***************************************************************************
+** store records in temporary table for UNION
+***************************************************************************/
+
+select_union::select_union(TABLE *table_par)
+ :table(table_par), not_describe(0)
+{
+ bzero((char*) &info,sizeof(info));
+ /*
+ We can always use DUP_IGNORE because the temporary table will only
+ contain a unique key if we are using not using UNION ALL
+ */
+ info.handle_duplicates= DUP_IGNORE;
+}
+
+select_union::~select_union()
+{
+}
+
+
+int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
+{
+ unit= u;
+ if (not_describe && list.elements != table->fields)
{
- for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
- cursor;
- cursor=cursor->next)
- {
- if (cursor->do_redirect) // False if CUBE/ROLLUP
- {
- cursor->table= (my_reinterpret_cast(TABLE_LIST*) (cursor->table))->table;
- cursor->do_redirect= 0;
- }
- }
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
+ return -1;
}
+ return 0;
+}
- /* last_sel now points at the last select where the ORDER BY is stored */
- if (sl)
+bool select_union::send_data(List<Item> &values)
+{
+ if (unit->offset_limit_cnt)
+ { // using limit offset,count
+ unit->offset_limit_cnt--;
+ return 0;
+ }
+ fill_record(table->field,values);
+ if (thd->net.report_error || write_record(table,&info))
{
- /*
- The found SL is an extra SELECT_LEX argument that contains
- the ORDER BY and LIMIT parameter for the whole UNION
- */
- lex_sl= sl;
- order= (ORDER *) lex_sl->order_list.first;
- found_rows_for_union = (lex->select_lex.options & OPTION_FOUND_ROWS &&
- !describe && sl->select_limit);
- if (found_rows_for_union)
- lex->select_lex.options ^= OPTION_FOUND_ROWS;
- // This is done to eliminate unnecessary slowing down of the first query
- if (!order || !describe)
- last_sl->next=0; // Remove this extra element
+ if (thd->net.last_errno == ER_RECORD_FILE_FULL)
+ {
+ thd->clear_error(); // do not report user about table overflow
+ if (create_myisam_from_heap(thd, table, tmp_table_param,
+ info.last_errno, 0))
+ return 1;
+ }
+ else
+ return 1;
}
- else if (!last_sl->braces)
+ return 0;
+}
+
+bool select_union::send_eof()
+{
+ return 0;
+}
+
+bool select_union::flush()
+{
+ int error;
+ if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{
- lex_sl= last_sl; // ORDER BY is here
- order= (ORDER *) lex_sl->order_list.first;
+ table->file->print_error(error,MYF(0));
+ ::send_error(thd);
+ return 1;
}
- else
+ return 0;
+}
+
+int st_select_lex_unit::prepare(THD *thd, select_result *result,
+ bool tables_and_fields_initied)
+{
+ DBUG_ENTER("st_select_lex_unit::prepare");
+
+ if (prepared)
+ DBUG_RETURN(0);
+ prepared= 1;
+ res= 0;
+ found_rows_for_union= 0;
+ TMP_TABLE_PARAM tmp_table_param;
+ this->result= result;
+ SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
+ SELECT_LEX *sl;
+
+ thd->lex.current_select= sl= first_select();
+ /* Global option */
+ if (((void*)(global_parameters)) == ((void*)this))
{
- lex_sl=0;
- order=0;
+ found_rows_for_union= first_select()->options & OPTION_FOUND_ROWS &&
+ global_parameters->select_limit;
+ if (found_rows_for_union)
+ first_select()->options ^= OPTION_FOUND_ROWS;
}
-
- if (describe)
+ if (tables_and_fields_initied)
{
- Item *item;
- item_list.push_back(new Item_empty_string("table",NAME_LEN));
- item_list.push_back(new Item_empty_string("type",10));
- item_list.push_back(item=new Item_empty_string("possible_keys",
- NAME_LEN*MAX_KEY));
- item->maybe_null=1;
- item_list.push_back(item=new Item_empty_string("key",NAME_LEN));
- item->maybe_null=1;
- item_list.push_back(item=new Item_int("key_len",0,3));
- item->maybe_null=1;
- item_list.push_back(item=new Item_empty_string("ref",
- NAME_LEN*MAX_REF_PARTS));
- item->maybe_null=1;
- item_list.push_back(new Item_real("rows",0.0,0,10));
- item_list.push_back(new Item_empty_string("Extra",255));
+ // Item list and tables will be initialized by mysql_derived
+ item_list= sl->item_list;
}
else
{
- Item *item;
- List_iterator<Item> it(lex->select_lex.item_list);
- TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
+ item_list.empty();
+ TABLE_LIST *first_table= (TABLE_LIST*) first_select()->table_list.first;
- /* Create a list of items that will be in the result set */
- while ((item= it++))
- if (item_list.push_back(item))
- DBUG_RETURN(-1);
- if (setup_fields(thd,first_table,item_list,0,0,1))
- DBUG_RETURN(-1);
+ if (setup_tables(first_table) ||
+ setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild))
+ goto err;
+
+ item_list= sl->item_list;
+ sl->with_wild= 0;
+ if (setup_ref_array(thd, &sl->ref_pointer_array,
+ (item_list.elements + sl->with_sum_func +
+ sl->order_list.elements + sl->group_list.elements)) ||
+ setup_fields(thd, sl->ref_pointer_array, first_table, item_list,
+ 0, 0, 1))
+ goto err;
+ tables_and_fields_initied= 1;
}
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements;
- if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
- (ORDER*) 0, !describe & !lex->union_option,
- 1, 0,
- (lex->select_lex.options | thd->options |
- TMP_TABLE_ALL_COLUMNS))))
- DBUG_RETURN(-1);
+ if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
+ (ORDER*) 0, !union_option,
+ 1, (first_select()->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR)))
+ goto err;
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list,sizeof(result_table_list));
@@ -134,157 +173,173 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
result_table_list.table=table;
if (!(union_result=new select_union(table)))
- {
- res= -1;
- goto exit;
- }
- union_result->not_describe= !describe;
+ goto err;
+
+ union_result->not_describe=1;
union_result->tmp_table_param=&tmp_table_param;
- for (sl= &lex->select_lex; sl; sl=sl->next)
+
+ // prepare selects
+ for (sl= first_select(); sl; sl= sl->next_select())
{
- lex->select=sl;
- thd->offset_limit=sl->offset_limit;
- thd->select_limit=sl->select_limit+sl->offset_limit;
- if (thd->select_limit < sl->select_limit)
- thd->select_limit= HA_POS_ERROR; // no limit
- if (thd->select_limit == HA_POS_ERROR)
+ JOIN *join= new JOIN(thd, sl->item_list,
+ sl->options | thd->options | SELECT_NO_UNLOCK,
+ union_result);
+ thd->lex.current_select= sl;
+ offset_limit_cnt= sl->offset_limit;
+ select_limit_cnt= sl->select_limit+sl->offset_limit;
+ if (select_limit_cnt < sl->select_limit)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+ if (select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
- res=mysql_select(thd, (describe && sl->linkage==NOT_A_SELECT) ?
- first_table : (TABLE_LIST*) sl->table_list.first,
- sl->item_list,
- sl->where,
- (sl->braces) ? (ORDER *)sl->order_list.first :
- (ORDER *) 0,
- (ORDER*) sl->group_list.first,
- sl->having,
- (ORDER*) NULL,
- sl->options | thd->options | SELECT_NO_UNLOCK |
- ((describe) ? SELECT_DESCRIBE : 0),
- union_result);
- if (res)
- goto exit;
+ res= join->prepare(&sl->ref_pointer_array,
+ (TABLE_LIST*) sl->table_list.first, sl->with_wild,
+ sl->where,
+ ((sl->braces) ? sl->order_list.elements : 0) +
+ sl->group_list.elements,
+ (sl->braces) ?
+ (ORDER *)sl->order_list.first : (ORDER *) 0,
+ (ORDER*) sl->group_list.first,
+ sl->having,
+ (ORDER*) NULL,
+ sl, this, 0, tables_and_fields_initied);
+ tables_and_fields_initied= 0;
+ if (res | thd->is_fatal_error)
+ goto err;
+ }
+ item_list.empty();
+ thd->lex.current_select= lex_select_save;
+ {
+ List_iterator<Item> it(first_select()->item_list);
+ Field **field;
+
+ for (field= table->field; *field; field++)
+ {
+ (void) it++;
+ if (item_list.push_back(new Item_field(*field)))
+ DBUG_RETURN(-1);
+ }
}
+
+ DBUG_RETURN(res | thd->is_fatal_error);
+err:
+ thd->lex.current_select= lex_select_save;
+ DBUG_RETURN(-1);
+}
+
+int st_select_lex_unit::exec()
+{
+ DBUG_ENTER("st_select_lex_unit::exec");
+ SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
+
+ if (executed && !(dependent || uncacheable))
+ DBUG_RETURN(0);
+ executed= 1;
+
+ if ((dependent||uncacheable) || !item || !item->assigned())
+ {
+ if (optimized && item && item->assigned())
+ {
+ item->assigned(0); // We will reinit & rexecute unit
+ item->reset();
+ table->file->delete_all_rows();
+ }
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ {
+ thd->lex.current_select= sl;
+ offset_limit_cnt= sl->offset_limit;
+ select_limit_cnt= sl->select_limit+sl->offset_limit;
+ if (select_limit_cnt < sl->select_limit)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+ if (select_limit_cnt == HA_POS_ERROR)
+ sl->options&= ~OPTION_FOUND_ROWS;
+
+ if (!optimized)
+ res= sl->join->optimize();
+ else
+ res= sl->join->reinit();
+
+ if (!res)
+ {
+ sl->join->exec();
+ res= sl->join->error;
+ }
+ if (res)
+ {
+ thd->lex.current_select= lex_select_save;
+ DBUG_RETURN(res);
+ }
+ }
+ optimized= 1;
+ }
+
if (union_result->flush())
{
- res= 1; // Error is already sent
- goto exit;
+ thd->lex.current_select= lex_select_save;
+ DBUG_RETURN(1);
}
- delete union_result;
/* Send result to 'result' */
- lex->select = &lex->select_lex;
+
+ // to correct ORDER BY reference resolving
+ thd->lex.current_select = first_select();
res =-1;
{
- /* Create a list of fields in the temporary table */
- List_iterator<Item> it(item_list);
- Field **field;
#if 0
List<Item_func_match> ftfunc_list;
ftfunc_list.empty();
#else
- thd->lex.select_lex.ftfunc_list.empty();
+ List<Item_func_match> empty_list;
+ empty_list.empty();
+ thd->lex.select_lex.ftfunc_list= &empty_list;
#endif
- for (field=table->field ; *field ; field++)
+ if (!thd->is_fatal_error) // Check if EOM
{
- (void) it++;
- (void) it.replace(new Item_field(*field));
- }
- if (!thd->fatal_error) // Check if EOM
- {
- if (lex_sl)
- {
- thd->offset_limit=lex_sl->offset_limit;
- thd->select_limit=lex_sl->select_limit+lex_sl->offset_limit;
- if (thd->select_limit < lex_sl->select_limit)
- thd->select_limit= HA_POS_ERROR; // no limit
- if (thd->select_limit == HA_POS_ERROR)
- thd->options&= ~OPTION_FOUND_ROWS;
- }
- else
- {
- thd->offset_limit= 0;
- thd->select_limit= thd->variables.select_limit;
- }
- if (describe)
- thd->select_limit= HA_POS_ERROR; // no limit
- res=mysql_select(thd,&result_table_list,
- item_list, NULL, (describe) ? 0 : order,
- (ORDER*) NULL, NULL, (ORDER*) NULL,
- thd->options, result);
+ SELECT_LEX *sl=thd->lex.current_select->master_unit()->first_select();
+ offset_limit_cnt= (sl->braces) ? global_parameters->offset_limit : 0;
+ select_limit_cnt= (sl->braces) ? global_parameters->select_limit+
+ global_parameters->offset_limit : HA_POS_ERROR;
+ if (select_limit_cnt < global_parameters->select_limit)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+ if (select_limit_cnt == HA_POS_ERROR)
+ thd->options&= ~OPTION_FOUND_ROWS;
+ res= mysql_select(thd, &ref_pointer_array, &result_table_list,
+ 0, item_list, NULL,
+ global_parameters->order_list.elements,
+ (ORDER*)global_parameters->order_list.first,
+ (ORDER*) NULL, NULL, (ORDER*) NULL,
+ thd->options, result, this, first_select(), 1, 0);
if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records;
}
}
-
-exit:
- free_tmp_table(thd,table);
+ thd->lex.select_lex.ftfunc_list= &thd->lex.select_lex.ftfunc_list_alloc;
+ thd->lex.current_select= lex_select_save;
DBUG_RETURN(res);
}
-
-/***************************************************************************
-** store records in temporary table for UNION
-***************************************************************************/
-
-select_union::select_union(TABLE *table_par)
- :table(table_par), not_describe(0)
+int st_select_lex_unit::cleanup()
{
- bzero((char*) &info,sizeof(info));
- /*
- We can always use DUP_IGNORE because the temporary table will only
- contain a unique key if we are using not using UNION ALL
- */
- info.handle_duplicates=DUP_IGNORE;
-}
-
-select_union::~select_union()
-{
-}
-
-
-int select_union::prepare(List<Item> &list)
-{
- if (not_describe && list.elements != table->fields)
- {
- my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
- ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
- return -1;
- }
- return 0;
-}
+ DBUG_ENTER("st_select_lex_unit::cleanup");
-bool select_union::send_data(List<Item> &values)
-{
- if (thd->offset_limit)
- { // using limit offset,count
- thd->offset_limit--;
- return 0;
- }
+ int error= 0;
- fill_record(table->field,values);
- if ((write_record(table,&info)))
+ if (union_result)
{
- if (create_myisam_from_heap(table, tmp_table_param, info.last_errno, 0))
- return 1;
+ delete union_result;
+ if (table)
+ free_tmp_table(thd, table);
+ table= 0; // Safety
}
- return 0;
-}
-
-bool select_union::send_eof()
-{
- return 0;
-}
-
-bool select_union::flush()
-{
- int error;
- if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
- table->file->print_error(error,MYF(0));
- ::send_error(&thd->net);
- return 1;
+ JOIN *join;
+ if ((join= sl->join))
+ {
+ error|= sl->join->cleanup(thd);
+ delete join;
+ }
}
- return 0;
+ DBUG_RETURN(error);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 9817dcd2be5..88f677938ad 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -50,7 +50,7 @@ int mysql_update(THD *thd,
List<Item> &fields,
List<Item> &values,
COND *conds,
- ORDER *order,
+ uint order_num, ORDER *order,
ha_rows limit,
enum enum_duplicates handle_duplicates)
{
@@ -64,12 +64,17 @@ int mysql_update(THD *thd,
TABLE *table;
SQL_SELECT *select;
READ_RECORD info;
+ TABLE_LIST *update_table_list= (TABLE_LIST*)
+ thd->lex.select_lex.table_list.first;
DBUG_ENTER("mysql_update");
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
- DBUG_RETURN(-1); /* purecov: inspected */
+ if ((open_and_lock_tables(thd, table_list)))
+ DBUG_RETURN(-1);
+ fix_tables_pointers(thd->lex.all_selects_list);
+ table= table_list->table;
+
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
@@ -78,9 +83,17 @@ int mysql_update(THD *thd,
table->quick_keys=0;
want_privilege=table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
- if (setup_tables(table_list) || setup_conds(thd,table_list,&conds)
- || setup_ftfuncs(thd))
+ if (setup_tables(update_table_list) ||
+ setup_conds(thd,update_table_list,&conds)
+ || setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1); /* purecov: inspected */
+ if (find_real_table_in_list(table_list->next,
+ table_list->db, table_list->real_name))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
+ DBUG_RETURN(-1);
+ }
+
old_used_keys=table->used_keys; // Keys used in WHERE
/*
@@ -96,7 +109,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege;
- if (setup_fields(thd,table_list,fields,1,0,0))
+ if (setup_fields(thd, 0, update_table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field)
{
@@ -109,8 +122,9 @@ int mysql_update(THD *thd,
/* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
- if (setup_fields(thd,table_list,values,0,0,0))
+ if (setup_fields(thd, 0, update_table_list, values, 0, 0, 0))
{
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); /* purecov: inspected */
}
@@ -121,11 +135,12 @@ int mysql_update(THD *thd,
(select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
if (error)
{
DBUG_RETURN(-1); // Error in where
}
- send_ok(&thd->net); // No matching records
+ send_ok(thd); // No matching records
DBUG_RETURN(0);
}
/* If running in safe sql mode, don't allow updates without keys */
@@ -135,11 +150,12 @@ int mysql_update(THD *thd,
if (safe_update && !using_limit)
{
delete select;
- send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
+ free_underlaid_joins(thd, &thd->lex.select_lex);
+ send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1);
}
}
- init_ftfuncs(thd,1);
+ init_ftfuncs(thd, &thd->lex.select_lex, 1);
/* Check if we are modifying a key that we are used to search with */
if (select && select->quick)
used_key_is_modified= (!select->quick->unique_key_range() &&
@@ -162,6 +178,7 @@ int mysql_update(THD *thd,
DISK_BUFFER_SIZE, MYF(MY_WME)))
{
delete select; /* purecov: inspected */
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
if (old_used_keys & ((key_map) 1 << used_index))
@@ -184,14 +201,18 @@ int mysql_update(THD *thd,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
- if (setup_order(thd, &tables, fields, all_fields, order) ||
+ if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
+ order_num)||
+ setup_order(thd, thd->lex.select_lex.ref_pointer_array,
+ &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (table->found_records = filesort(table, sortorder, length,
- (SQL_SELECT *) 0, 0L,
+ (table->found_records = filesort(thd, table, sortorder, length,
+ (SQL_SELECT *) 0,
HA_POS_ERROR, &examined_rows))
== HA_POS_ERROR)
{
delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
@@ -220,6 +241,7 @@ int mysql_update(THD *thd,
}
}
end_read_record(&info);
+
if (table->key_read)
{
table->key_read=0;
@@ -245,6 +267,7 @@ int mysql_update(THD *thd,
if (error >= 0)
{
delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
@@ -264,7 +287,7 @@ int mysql_update(THD *thd,
if (!(select && select->skipp_record()))
{
store_record(table,1);
- if (fill_record(fields,values))
+ if (fill_record(fields,values) || thd->net.report_error)
break; /* purecov: inspected */
found++;
if (compare_record(table, query_id))
@@ -330,20 +353,22 @@ int mysql_update(THD *thd,
}
delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
if (error >= 0)
- send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
+ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else
{
char buff[80];
sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
(long) thd->cuted_fields);
- send_ok(&thd->net,
+ send_ok(thd,
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
DBUG_PRINT("info",("%d records updated",updated));
}
thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table);
+
DBUG_RETURN(0);
}
@@ -362,7 +387,8 @@ int mysql_multi_update(THD *thd,
List<Item> *values,
COND *conds,
ulong options,
- enum enum_duplicates handle_duplicates)
+ enum enum_duplicates handle_duplicates,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
{
int res;
multi_update *result;
@@ -374,7 +400,7 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(res);
thd->select_limit=HA_POS_ERROR;
- if (setup_fields(thd, table_list, *fields, 1, 0, 0))
+ if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0))
DBUG_RETURN(-1);
/*
@@ -397,11 +423,12 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(-1);
List<Item> total_list;
- res= mysql_select(thd,table_list,total_list,
- conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
+ res= mysql_select(thd, &select_lex->ref_pointer_array,
+ table_list, select_lex->with_wild, total_list,
+ conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE,
- result);
+ result, unit, select_lex, 0, 0);
delete result;
DBUG_RETURN(res);
}
@@ -421,7 +448,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
Connect fields with tables and create list of tables that are updated
*/
-int multi_update::prepare(List<Item> &not_used_values)
+int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
{
TABLE_LIST *table_ref;
SQL_LIST update;
@@ -451,7 +478,7 @@ int multi_update::prepare(List<Item> &not_used_values)
reference tables
*/
- if (setup_fields(thd, all_tables, *values, 1,0,0))
+ if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
DBUG_RETURN(1);
/*
@@ -487,14 +514,14 @@ int multi_update::prepare(List<Item> &not_used_values)
table_count);
values_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
table_count);
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
DBUG_RETURN(1);
for (i=0 ; i < table_count ; i++)
{
fields_for_table[i]= new List_item;
values_for_table[i]= new List_item;
}
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
DBUG_RETURN(1);
/* Split fields into fields_for_table[] and values_by_table[] */
@@ -507,7 +534,7 @@ int multi_update::prepare(List<Item> &not_used_values)
fields_for_table[offset]->push_back(item);
values_for_table[offset]->push_back(value);
}
- if (thd->fatal_error)
+ if (thd->is_fatal_error)
DBUG_RETURN(1);
/* Allocate copy fields */
@@ -515,7 +542,7 @@ int multi_update::prepare(List<Item> &not_used_values)
for (i=0 ; i < table_count ; i++)
set_if_bigger(max_fields, fields_for_table[i]->elements);
copy_field= new Copy_field[max_fields];
- DBUG_RETURN(thd->fatal_error != 0);
+ DBUG_RETURN(thd->is_fatal_error != 0);
}
@@ -558,7 +585,7 @@ multi_update::initialize_tables(JOIN *join)
/* ok to be on stack as this is not referenced outside of this func */
Field_string offset(table->file->ref_length, 0, "offset",
- table, 1);
+ table, &my_charset_bin);
if (temp_fields.push_front(new Item_field(((Field *) &offset))))
DBUG_RETURN(1);
@@ -574,8 +601,9 @@ multi_update::initialize_tables(JOIN *join)
if (!(tmp_tables[cnt]=create_tmp_table(thd,
tmp_param,
temp_fields,
- (ORDER*) &group, 0, 0, 0,
- TMP_TABLE_ALL_COLUMNS)))
+ (ORDER*) &group, 0, 0,
+ TMP_TABLE_ALL_COLUMNS,
+ HA_POS_ERROR)))
DBUG_RETURN(1);
tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE);
}
@@ -665,7 +693,8 @@ bool multi_update::send_data(List<Item> &not_used_values)
(error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE))
{
- if (create_myisam_from_heap(table, tmp_table_param + offset, error, 1))
+ if (create_myisam_from_heap(thd, table, tmp_table_param + offset,
+ error, 1))
{
do_update=0;
DBUG_RETURN(1); // Not a table_is_full error
@@ -680,7 +709,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
void multi_update::send_error(uint errcode,const char *err)
{
/* First send error what ever it is ... */
- ::send_error(&thd->net,errcode,err);
+ ::send_error(thd,errcode,err);
/* If nothing updated return */
if (!updated)
@@ -851,7 +880,7 @@ bool multi_update::send_eof()
/* Safety: If we haven't got an error before (should not happen) */
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
MYF(0));
- ::send_error(&thd->net);
+ ::send_error(thd);
return 1;
}
@@ -862,7 +891,7 @@ bool multi_update::send_eof()
{
query_cache_invalidate3(thd, update_tables, 1);
}
- ::send_ok(&thd->net,
+ ::send_ok(thd,
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
return 0;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 8be025d0423..b9c0167bc05 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -17,26 +17,35 @@
/* sql_yacc.yy */
%{
+/* thd is passed as an arg to yyparse(), and subsequently to yylex().
+** The type will be void*, so it must be cast to (THD*) when used.
+** Use the YYTHD macro for this.
+*/
+#define YYPARSE_PARAM yythd
+#define YYLEX_PARAM yythd
+#define YYTHD ((THD *)yythd)
+
#define MYSQL_YACC
#define YYINITDEPTH 100
#define YYMAXDEPTH 3200 /* Because of 64K stack */
-#define Lex current_lex
-#define Select Lex->select
+#define Lex (&(YYTHD->lex))
+#define Select Lex->current_select
#include "mysql_priv.h"
#include "slave.h"
#include "sql_acl.h"
#include "lex_symbol.h"
+#include "item_create.h"
#include <myisam.h>
#include <myisammrg.h>
extern void yyerror(const char*);
-int yylex(void *yylval);
+int yylex(void *yylval, void *yythd);
#define yyoverflow(A,B,C,D,E,F) if (my_yyoverflow((B),(D),(int*) (F))) { yyerror((char*) (A)); return 2; }
-inline Item *or_or_concat(Item* A, Item* B)
+inline Item *or_or_concat(THD *thd, Item* A, Item* B)
{
- return (current_thd->sql_mode & MODE_PIPES_AS_CONCAT ?
+ return (thd->variables.sql_mode & MODE_PIPES_AS_CONCAT ?
(Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B));
}
@@ -60,14 +69,18 @@ inline Item *or_or_concat(Item* A, Item* B)
LEX_USER *lex_user;
sys_var *variable;
Key::Keytype key_type;
+ enum ha_key_alg key_alg;
enum db_type db_type;
enum row_type row_type;
enum ha_rkey_function ha_rkey_mode;
enum enum_tx_isolation tx_isolation;
enum Item_cast cast_type;
enum Item_udftype udf_type;
+ CHARSET_INFO *charset;
thr_lock_type lock_type;
interval_type interval;
+ st_select_lex *select_lex;
+ chooser_compare_func_creator boolfunc2creator;
}
%{
@@ -84,14 +97,17 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NEXT_SYM
%token PREV_SYM
+%token DIV_SYM
%token EQ
%token EQUAL_SYM
+%token SOUNDS_SYM
%token GE
%token GT_SYM
%token LE
%token LT
%token NE
%token IS
+%token MOD_SYM
%token SHIFT_LEFT
%token SHIFT_RIGHT
%token SET_VAR
@@ -101,6 +117,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token AFTER_SYM
%token ALTER
%token ANALYZE_SYM
+%token ANY_SYM
%token AVG_SYM
%token BEGIN_SYM
%token BINLOG_SYM
@@ -113,11 +130,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CROSS
%token CUBE_SYM
%token DELETE_SYM
+%token DUAL_SYM
%token DO_SYM
%token DROP
%token EVENTS_SYM
%token EXECUTE_SYM
%token FLUSH_SYM
+%token HELP_SYM
%token INSERT
%token IO_THREAD
%token KILL_SYM
@@ -141,6 +160,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_THREAD
%token START_SYM
%token STD_SYM
+%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
%token SUPER_SYM
@@ -163,7 +183,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token BOOL_SYM
%token BOOLEAN_SYM
%token BOTH
+%token BTREE_SYM
%token BY
+%token BYTE_SYM
%token CACHE_SYM
%token CASCADE
%token CAST_SYM
@@ -171,6 +193,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CHECKSUM_SYM
%token CHECK_SYM
%token COMMITTED_SYM
+%token COLLATE_SYM
%token COLUMNS
%token COLUMN_SYM
%token CONCURRENT
@@ -186,6 +209,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DES_KEY_FILE
%token DISABLE_SYM
%token DISTINCT
+%token DUPLICATE_SYM
%token DYNAMIC_SYM
%token ENABLE_SYM
%token ENCLOSED
@@ -194,6 +218,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ESCAPE_SYM
%token EXISTS
%token EXTENDED_SYM
+%token FALSE_SYM
%token FILE_SYM
%token FIRST_SYM
%token FIXED_SYM
@@ -209,6 +234,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GREATEST_SYM
%token GROUP
%token HAVING
+%token HASH_SYM
%token HEAP_SYM
%token HEX_NUM
%token HIGH_PRIORITY
@@ -304,11 +330,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROWS_SYM
%token ROW_FORMAT_SYM
%token ROW_SYM
+%token RTREE_SYM
%token SET
+%token SERIAL_SYM
%token SERIALIZABLE_SYM
%token SESSION_SYM
+%token SIMPLE_SYM
%token SHUTDOWN
-%token SSL_SYM
+%token SPATIAL_SYM
+%token SSL_SYM
%token STARTING
%token STATUS_SYM
%token STRAIGHT_JOIN
@@ -321,7 +351,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token TO_SYM
%token TRAILING
%token TRANSACTION_SYM
+%token TRUE_SYM
%token TYPE_SYM
+%token TYPES_SYM
%token FUNC_ARG0
%token FUNC_ARG1
%token FUNC_ARG2
@@ -330,21 +362,28 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UDF_SONAME_SYM
%token UDF_SYM
%token UNCOMMITTED_SYM
+%token UNDERSCORE_CHARSET
+%token UNICODE_SYM
%token UNION_SYM
%token UNIQUE_SYM
%token USAGE
%token USE_FRM
%token USE_SYM
%token USING
+%token VALUE_SYM
%token VALUES
%token VARIABLES
%token WHERE
%token WITH
%token WRITE_SYM
%token X509_SYM
-%token XOR
+%token XOR
%token COMPRESSED_SYM
+%token ERRORS
+%token WARNINGS
+
+%token ASCII_SYM
%token BIGINT
%token BLOB_SYM
%token CHAR_SYM
@@ -357,6 +396,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ENUM
%token FAST_SYM
%token FLOAT_SYM
+%token GEOMETRY_SYM
%token INT_SYM
%token LIMIT
%token LONGBLOB
@@ -414,6 +454,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FORMAT_SYM
%token FOR_SYM
%token FROM_UNIXTIME
+%token GEOMCOLLFROMTEXT
+%token GEOMFROMTEXT
+%token GEOMETRYCOLLECTION
%token GROUP_UNIQUE_USERS
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
@@ -424,6 +467,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token INTERVAL_SYM
%token LAST_INSERT_ID
%token LEFT
+%token LINEFROMTEXT
+%token LINESTRING
%token LOCATE
%token MAKE_SET_SYM
%token MASTER_POS_WAIT
@@ -432,8 +477,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MODE_SYM
%token MODIFY_SYM
%token MONTH_SYM
+%token MLINEFROMTEXT
+%token MPOINTFROMTEXT
+%token MPOLYFROMTEXT
+%token MULTILINESTRING
+%token MULTIPOINT
+%token MULTIPOLYGON
%token NOW_SYM
%token PASSWORD
+%token POINTFROMTEXT
+%token POINT
+%token POLYFROMTEXT
+%token POLYGON
%token POSITION_SYM
%token PROCEDURE
%token RAND
@@ -484,13 +539,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+'
-%left '*' '/' '%'
+%left '*' '/' '%' DIV_SYM MOD_SYM
%left NEG '~'
%left XOR
%left '^'
%right NOT
-%right BINARY
-
+%right BINARY COLLATE_SYM
/* These don't actually affect the way the query is really evaluated, but
they silence a few warnings for shift/reduce conflicts. */
%left ','
@@ -500,25 +554,26 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text
+ UNDERSCORE_CHARSET
%type <lex_str_ptr>
opt_table_alias
%type <table>
- table_ident
+ table_ident references
%type <simple_string>
- remember_name remember_end opt_len opt_ident opt_db text_or_password
+ remember_name remember_end opt_ident opt_db text_or_password
opt_escape
%type <string>
- text_string
+ text_string
%type <num>
type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_var_type opt_var_ident_type
- opt_temporary
+ delete_option opt_temporary all_or_any
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -533,7 +588,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
- using_list expr_or_default set_expr_or_default
+ using_list expr_or_default set_expr_or_default interval_expr
+ param_marker singlerow_subselect singlerow_subselect_init
+ exists_subselect exists_subselect_init
%type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg
@@ -541,6 +598,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <key_type>
key_type opt_unique_or_fulltext
+%type <key_alg>
+ key_alg opt_btree_or_rtree
+
%type <string_list>
key_usage_list
@@ -548,7 +608,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
key_part
%type <table_list>
- join_table_list join_table
+ join_table_list join_table
%type <udf>
UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC
@@ -572,8 +632,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_user> user grant_user
+%type <charset>
+ charset_name
+ charset_name_or_default
+ collation_name
+ collation_name_or_default
+
%type <variable> internal_variable_name
+%type <select_lex> in_subselect in_subselect_init
+
+%type <boolfunc2creator> comp_op
+
%type <NONE>
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
@@ -582,13 +652,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
repair restore backup analyze check start
field_list field_list_item field_spec kill
select_item_list select_item values_list no_braces
- limit_clause delete_limit_clause fields opt_values values
+ opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
when_list2 expr_list2 handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock varchar
- references opt_on_delete opt_on_delete_list opt_on_delete_item use
+ ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option
opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
@@ -599,26 +669,29 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild opt_union union_list
- precision union_option opt_and
+ single_multi table_wild_list table_wild_one opt_wild
+ union_clause union_list union_option
+ precision subselect_start opt_and
+ subselect_end select_var_list select_var_list_init help opt_len
END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
- ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM THEN_SYM WHEN_SYM
+ ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM
+ THEN_SYM WHEN_SYM DIV_SYM MOD_SYM
%%
query:
END_OF_INPUT
{
- THD *thd=current_thd;
+ THD *thd= YYTHD;
if (!thd->bootstrap &&
(!(thd->lex.select_lex.options & OPTION_FOUND_COMMENT)))
{
- send_error(&current_thd->net,ER_EMPTY_QUERY);
+ send_error(thd,ER_EMPTY_QUERY);
YYABORT;
- }
+ }
else
{
thd->lex.sql_command = SQLCOM_EMPTY_QUERY;
@@ -646,7 +719,7 @@ verb_clause:
| lock
| kill
| optimize
- | purge
+ | purge
| rename
| repair
| replace
@@ -663,7 +736,18 @@ verb_clause:
| handler
| unlock
| update
- | use;
+ | use
+ | help;
+
+/* help */
+
+help:
+ HELP_SYM ident_or_text
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_HELP;
+ lex->help_arg= $2.str;
+ };
/* change master */
@@ -726,7 +810,8 @@ master_def:
RELAY_LOG_POS_SYM EQ ULONG_NUM
{
Lex->mi.relay_log_pos = $3;
- };
+ }
+ ;
/* create a table */
@@ -734,12 +819,18 @@ master_def:
create:
CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident
{
+ THD *thd= YYTHD;
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_TABLE;
- if (!add_table_to_list($5,
- ($2 & HA_LEX_CREATE_TMP_TABLE ?
- &tmp_table_alias : (LEX_STRING*) 0),
- TL_OPTION_UPDATING))
+ if (!lex->select_lex.add_table_to_list(thd,$5,
+ ($2 &
+ HA_LEX_CREATE_TMP_TABLE ?
+ &tmp_table_alias :
+ (LEX_STRING*) 0),
+ TL_OPTION_UPDATING,
+ ((using_update_log)?
+ TL_READ_NO_INSERT:
+ TL_READ)))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
@@ -748,39 +839,44 @@ create:
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
+ lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info;
+ lex->name=0;
}
create2
- {}
- | CREATE opt_unique_or_fulltext INDEX ident ON table_ident
+ {}
+ | CREATE opt_unique_or_fulltext INDEX ident key_alg ON table_ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
- if (!add_table_to_list($6, NULL, TL_OPTION_UPDATING))
+ if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
+ TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
lex->col_list.empty();
lex->change=NullS;
}
- '(' key_list ')'
+ '(' key_list ')'
{
LEX *lex=Lex;
- lex->key_list.push_back(new Key($2,$4.str,lex->col_list));
+
+ lex->key_list.push_back(new Key($2,$4.str, $5, lex->col_list));
lex->col_list.empty();
}
- | CREATE DATABASE opt_if_not_exists ident
+ | CREATE DATABASE opt_if_not_exists ident
+ { Lex->create_info.table_charset=NULL; }
+ opt_create_database_options
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_CREATE_DB;
lex->name=$4.str;
lex->create_info.options=$3;
}
- | CREATE udf_func_type UDF_SYM ident
+ | CREATE udf_func_type UDF_SYM IDENT
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_CREATE_FUNCTION;
- lex->udf.name=$4.str;
- lex->udf.name_length=$4.length;
+ lex->udf.name = $4;
lex->udf.type= $2;
}
UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING
@@ -788,11 +884,19 @@ create:
LEX *lex=Lex;
lex->udf.returns=(Item_result) $7;
lex->udf.dl=$9.str;
- };
+ }
+ ;
create2:
'(' field_list ')' opt_create_table_options create3 {}
- | opt_create_table_options create3 {};
+ | opt_create_table_options create3 {}
+ | LIKE table_ident
+ {
+ LEX *lex=Lex;
+ if (!(lex->name= (char *)$2))
+ YYABORT;
+ }
+ ;
create3:
/* empty */ {}
@@ -802,12 +906,29 @@ create3:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
}
- select_options select_item_list opt_select_from opt_union {};
+ select_options select_item_list opt_select_from union_clause {}
+ ;
opt_as:
/* empty */ {}
| AS {};
+opt_create_database_options:
+ /* empty */ {}
+ | create_database_options {};
+
+create_database_options:
+ create_database_option {}
+ | create_database_options create_database_option {};
+
+create_database_option:
+ COLLATE_SYM collation_name_or_default
+ { Lex->create_info.table_charset=$2; }
+ | opt_default CHAR_SYM SET charset_name_or_default
+ { Lex->create_info.table_charset=$4; }
+ | opt_default CHARSET charset_name_or_default
+ { Lex->create_info.table_charset=$3; };
+
opt_table_options:
/* empty */ { $$= 0; }
| table_options { $$= $1;};
@@ -827,44 +948,62 @@ opt_create_table_options:
/* empty */
| create_table_options;
+create_table_options_space_separated:
+ create_table_option
+ | create_table_option create_table_options_space_separated;
+
create_table_options:
create_table_option
- | create_table_option create_table_options;
+ | create_table_option create_table_options
+ | create_table_option ',' create_table_options;
create_table_option:
- TYPE_SYM EQ table_types { Lex->create_info.db_type= $3; }
- | MAX_ROWS EQ ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
- | MIN_ROWS EQ ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
- | AVG_ROW_LENGTH EQ ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
- | PASSWORD EQ TEXT_STRING { Lex->create_info.password=$3.str; }
- | COMMENT_SYM EQ TEXT_STRING { Lex->create_info.comment=$3.str; }
- | AUTO_INC EQ ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
- | PACK_KEYS_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
- | PACK_KEYS_SYM EQ DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
- | CHECKSUM_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; }
- | DELAY_KEY_WRITE_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; }
- | ROW_FORMAT_SYM EQ row_types { Lex->create_info.row_type= $3; }
- | RAID_TYPE EQ raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
- | RAID_CHUNKS EQ ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
- | RAID_CHUNKSIZE EQ ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
- | UNION_SYM EQ '(' table_list ')'
+ TYPE_SYM opt_equal table_types { Lex->create_info.db_type= $3; }
+ | MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
+ | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
+ | AVG_ROW_LENGTH opt_equal ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
+ | PASSWORD opt_equal TEXT_STRING { Lex->create_info.password=$3.str; }
+ | COMMENT_SYM opt_equal TEXT_STRING { Lex->create_info.comment=$3.str; }
+ | AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
+ | PACK_KEYS_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
+ | PACK_KEYS_SYM opt_equal DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
+ | CHECKSUM_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; }
+ | DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; }
+ | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; }
+ | RAID_TYPE opt_equal raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+ | RAID_CHUNKS opt_equal ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+ | RAID_CHUNKSIZE opt_equal ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+ | UNION_SYM opt_equal '(' table_list ')'
{
/* Move the union list to the merge_list */
LEX *lex=Lex;
- TABLE_LIST *table_list= (TABLE_LIST*) lex->select->table_list.first;
- lex->create_info.merge_list= lex->select->table_list;
+ TABLE_LIST *table_list= lex->select_lex.get_table_list();
+ lex->create_info.merge_list= lex->select_lex.table_list;
lex->create_info.merge_list.elements--;
lex->create_info.merge_list.first= (byte*) (table_list->next);
- lex->select->table_list.elements=1;
- lex->select->table_list.next= (byte**) &(table_list->next);
+ lex->select_lex.table_list.elements=1;
+ lex->select_lex.table_list.next= (byte**) &(table_list->next);
table_list->next=0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION;
}
- | CHARSET opt_equal ident {}
- | CHAR_SYM SET opt_equal ident {}
- | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
- | DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; }
- | INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; };
+ | opt_default CHARSET opt_equal charset_name_or_default
+ {
+ Lex->create_info.table_charset= $4;
+ Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
+ }
+ | opt_default CHAR_SYM SET opt_equal charset_name_or_default
+ {
+ Lex->create_info.table_charset= $5;
+ Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
+ }
+ | COLLATE_SYM opt_equal collation_name_or_default
+ {
+ Lex->create_info.table_charset= $3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
+ }
+ | INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
+ | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING { Lex->create_info.data_file_name= $4.str; }
+ | INDEX DIRECTORY_SYM opt_equal TEXT_STRING { Lex->create_info.index_file_name= $4.str; };
table_types:
ISAM_SYM { $$= DB_TYPE_ISAM; }
@@ -891,7 +1030,8 @@ merge_insert_types:
| LAST_SYM { $$= MERGE_INSERT_TO_LAST; };
opt_select_from:
- /* empty */
+ opt_limit_clause {}
+ | FROM DUAL_SYM {}
| select_from select_lock_type;
udf_func_type:
@@ -914,15 +1054,22 @@ field_list_item:
{
Lex->col_list.empty(); /* Alloced by sql_alloc */
}
- | key_type opt_ident '(' key_list ')'
+ | key_type opt_ident key_alg '(' key_list ')'
{
LEX *lex=Lex;
- lex->key_list.push_back(new Key($1,$2,lex->col_list));
+ lex->key_list.push_back(new Key($1,$2, $3, lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
{
- Lex->col_list.empty(); /* Alloced by sql_alloc */
+ LEX *lex=Lex;
+ lex->key_list.push_back(new foreign_key($4, lex->col_list,
+ $8,
+ lex->ref_list,
+ lex->fk_delete_opt,
+ lex->fk_update_opt,
+ lex->fk_match_option));
+ lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint check_constraint
{
@@ -944,77 +1091,110 @@ field_spec:
{
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0;
- lex->default_value=0;
+ lex->default_value=lex->comment=0;
+ lex->charset=NULL;
}
type opt_attribute
{
LEX *lex=Lex;
- if (add_field_to_list($1.str,
+ if (add_field_to_list(lex->thd, $1.str,
(enum enum_field_types) $3,
lex->length,lex->dec,lex->type,
- lex->default_value,lex->change,
- lex->interval))
+ lex->default_value, lex->comment,
+ lex->change,lex->interval,lex->charset))
YYABORT;
};
type:
- int_type opt_len field_options { Lex->length=$2; $$=$1; }
+ int_type opt_len field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
| BIT_SYM opt_len { Lex->length=(char*) "1";
$$=FIELD_TYPE_TINY; }
| BOOL_SYM { Lex->length=(char*) "1";
$$=FIELD_TYPE_TINY; }
- | char '(' NUM ')' opt_binary { Lex->length=$3.str;
+ | BOOLEAN_SYM { Lex->length=(char*) "1";
+ $$=FIELD_TYPE_TINY; }
+ | char '(' NUM ')' opt_binary { Lex->length=$3.str;
$$=FIELD_TYPE_STRING; }
| char opt_binary { Lex->length=(char*) "1";
$$=FIELD_TYPE_STRING; }
- | BINARY '(' NUM ')' { Lex->length=$3.str;
- Lex->type|=BINARY_FLAG;
+ | BINARY '(' NUM ')' { Lex->length=$3.str;
+ Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_STRING; }
| varchar '(' NUM ')' opt_binary { Lex->length=$3.str;
$$=FIELD_TYPE_VAR_STRING; }
| VARBINARY '(' NUM ')' { Lex->length=$3.str;
- Lex->type|=BINARY_FLAG;
+ Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_VAR_STRING; }
- | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; Lex->length=$2; }
+ | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
| DATE_SYM { $$=FIELD_TYPE_DATE; }
| TIME_SYM { $$=FIELD_TYPE_TIME; }
- | TIMESTAMP { $$=FIELD_TYPE_TIMESTAMP; }
+ | TIMESTAMP
+ {
+ if (YYTHD->variables.sql_mode & MODE_SAPDB)
+ $$=FIELD_TYPE_DATETIME;
+ else
+ $$=FIELD_TYPE_TIMESTAMP;
+ }
| TIMESTAMP '(' NUM ')' { Lex->length=$3.str;
$$=FIELD_TYPE_TIMESTAMP; }
| DATETIME { $$=FIELD_TYPE_DATETIME; }
- | TINYBLOB { Lex->type|=BINARY_FLAG;
+ | TINYBLOB { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_TINY_BLOB; }
- | BLOB_SYM { Lex->type|=BINARY_FLAG;
+ | BLOB_SYM opt_len { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_BLOB; }
- | MEDIUMBLOB { Lex->type|=BINARY_FLAG;
+ | GEOMETRY_SYM { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | POINT { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | MULTIPOINT { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | LINESTRING { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | MULTILINESTRING { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | POLYGON { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | MULTIPOLYGON { Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_GEOMETRY; }
+ | MEDIUMBLOB { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_MEDIUM_BLOB; }
- | LONGBLOB { Lex->type|=BINARY_FLAG;
+ | LONGBLOB { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_LONG_BLOB; }
- | LONG_SYM VARBINARY { Lex->type|=BINARY_FLAG;
+ | LONG_SYM VARBINARY { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_MEDIUM_BLOB; }
- | LONG_SYM varchar { $$=FIELD_TYPE_MEDIUM_BLOB; }
- | TINYTEXT { $$=FIELD_TYPE_TINY_BLOB; }
- | TEXT_SYM { $$=FIELD_TYPE_BLOB; }
- | MEDIUMTEXT { $$=FIELD_TYPE_MEDIUM_BLOB; }
- | LONGTEXT { $$=FIELD_TYPE_LONG_BLOB; }
+ | LONG_SYM varchar opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
+ | TINYTEXT opt_binary { $$=FIELD_TYPE_TINY_BLOB; }
+ | TEXT_SYM opt_len opt_binary { $$=FIELD_TYPE_BLOB; }
+ | MEDIUMTEXT opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
+ | LONGTEXT opt_binary { $$=FIELD_TYPE_LONG_BLOB; }
| DECIMAL_SYM float_options field_options
{ $$=FIELD_TYPE_DECIMAL;}
| NUMERIC_SYM float_options field_options
{ $$=FIELD_TYPE_DECIMAL;}
- | ENUM {Lex->interval_list.empty();} '(' string_list ')'
+ | FIXED_SYM float_options field_options
+ { $$=FIELD_TYPE_DECIMAL;}
+ | ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
{
LEX *lex=Lex;
lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_ENUM;
}
- | SET { Lex->interval_list.empty();} '(' string_list ')'
+ | SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
{
LEX *lex=Lex;
lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_SET;
- };
+ }
+ | LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
+ | SERIAL_SYM
+ {
+ $$=FIELD_TYPE_LONGLONG;
+ Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
+ UNIQUE_FLAG);
+ }
+ ;
char:
CHAR_SYM {}
@@ -1035,7 +1215,7 @@ int_type:
| BIGINT { $$=FIELD_TYPE_LONGLONG; };
real_type:
- REAL { $$= current_thd->sql_mode & MODE_REAL_AS_FLOAT ?
+ REAL { $$= YYTHD->variables.sql_mode & MODE_REAL_AS_FLOAT ?
FIELD_TYPE_FLOAT : FIELD_TYPE_DOUBLE; }
| DOUBLE_SYM { $$=FIELD_TYPE_DOUBLE; }
| DOUBLE_SYM PRECISION { $$=FIELD_TYPE_DOUBLE; };
@@ -1067,8 +1247,8 @@ field_option:
| ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; };
opt_len:
- /* empty */ { $$=(char*) 0; } /* use default length */
- | '(' NUM ')' { $$=$2.str; };
+ /* empty */ { Lex->length=(char*) 0; } /* use default length */
+ | '(' NUM ')' { Lex->length= $2.str; };
opt_precision:
/* empty */ {}
@@ -1087,23 +1267,87 @@ attribute:
| NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT literal { Lex->default_value=$2; }
| AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
- | PRIMARY_SYM KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; }
+ | SERIAL_SYM DEFAULT VALUE_SYM
+ { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; }
+ | opt_primary KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; }
| UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; }
| UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; }
- | COMMENT_SYM text_literal {};
+ | COMMENT_SYM text_literal { Lex->comment= $2; }
+ | COLLATE_SYM collation_name { Lex->charset=$2; };
-opt_binary:
+
+charset_name:
+ ident
+ {
+ if (!($$=get_charset_by_csname($1.str,MYF(0))))
+ {
+ net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str);
+ YYABORT;
+ }
+ };
+
+charset_name_or_default:
+ charset_name { $$=$1; }
+ | DEFAULT { $$=NULL; } ;
+
+collation_name:
+ ident
+ {
+ if (!($$=get_charset_by_name($1.str,MYF(0))))
+ {
+ net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str);
+ YYABORT;
+ }
+ };
+
+collation_name_or_default:
+ collation_name { $$=$1; }
+ | DEFAULT { $$=NULL; } ;
+
+opt_default:
/* empty */ {}
- | BINARY { Lex->type|=BINARY_FLAG; }
- | CHAR_SYM SET opt_equal ident {}
+ | DEFAULT {};
+
+opt_binary:
+ /* empty */ { Lex->charset=NULL; }
+ | ASCII_SYM { Lex->charset=&my_charset_latin1; }
+ | BYTE_SYM { Lex->charset=&my_charset_bin; }
+ | BINARY { Lex->charset=&my_charset_bin; }
+ | UNICODE_SYM
+ {
+ if (!(Lex->charset=get_charset_by_name("ucs2",MYF(0))))
+ {
+ net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,"ucs2");
+ YYABORT;
+ }
+ }
+ | CHAR_SYM SET charset_name { Lex->charset=$3; } ;
+
+opt_primary:
+ /* empty */
+ | PRIMARY_SYM
;
references:
- REFERENCES table_ident opt_on_delete {}
- | REFERENCES table_ident '(' key_list ')' opt_on_delete
- {
- Lex->col_list.empty(); /* Alloced by sql_alloc */
- };
+ REFERENCES table_ident
+ {
+ LEX *lex=Lex;
+ lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0;
+ lex->ref_list.empty();
+ }
+ opt_ref_list
+ {
+ $$=$2;
+ };
+
+opt_ref_list:
+ /* empty */ opt_on_delete {}
+ | '(' ref_list ')' opt_on_delete {};
+
+ref_list:
+ ref_list ',' ident { Lex->ref_list.push_back(new key_part_spec($3.str)); }
+ | ident { Lex->ref_list.push_back(new key_part_spec($1.str)); };
+
opt_on_delete:
/* empty */ {}
@@ -1113,25 +1357,27 @@ opt_on_delete_list:
opt_on_delete_list opt_on_delete_item {}
| opt_on_delete_item {};
-
opt_on_delete_item:
- ON DELETE_SYM delete_option {}
- | ON UPDATE_SYM delete_option {}
- | MATCH FULL {}
- | MATCH PARTIAL {};
+ ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; }
+ | ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; }
+ | MATCH FULL { Lex->fk_match_option= foreign_key::FK_MATCH_FULL; }
+ | MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; }
+ | MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; };
delete_option:
- RESTRICT {}
- | CASCADE {}
- | SET NULL_SYM {}
- | NO_SYM ACTION {}
- | SET DEFAULT {};
+ RESTRICT { $$= (int) foreign_key::FK_OPTION_RESTRICT; }
+ | CASCADE { $$= (int) foreign_key::FK_OPTION_CASCADE; }
+ | SET NULL_SYM { $$= (int) foreign_key::FK_OPTION_SET_NULL; }
+ | NO_SYM ACTION { $$= (int) foreign_key::FK_OPTION_NO_ACTION; }
+ | SET DEFAULT { $$= (int) foreign_key::FK_OPTION_DEFAULT; };
key_type:
opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
| key_or_index { $$= Key::MULTIPLE; }
| FULLTEXT_SYM { $$= Key::FULLTEXT; }
| FULLTEXT_SYM key_or_index { $$= Key::FULLTEXT; }
+ | SPATIAL_SYM { $$= Key::SPATIAL; }
+ | SPATIAL_SYM key_or_index { $$= Key::SPATIAL; }
| opt_constraint UNIQUE_SYM { $$= Key::UNIQUE; }
| opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; };
@@ -1147,7 +1393,17 @@ keys_or_index:
opt_unique_or_fulltext:
/* empty */ { $$= Key::MULTIPLE; }
| UNIQUE_SYM { $$= Key::UNIQUE; }
- | FULLTEXT_SYM { $$= Key::FULLTEXT; };
+ | SPATIAL_SYM { $$= Key::SPATIAL; };
+
+key_alg:
+ /* empty */ { $$= HA_KEY_ALG_UNDEF; }
+ | USING opt_btree_or_rtree { $$= $2; }
+ | TYPE_SYM opt_btree_or_rtree { $$= $2; };
+
+opt_btree_or_rtree:
+ BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
+ | RTREE_SYM { $$= HA_KEY_ALG_RTREE; }
+ | HASH_SYM { $$= HA_KEY_ALG_HASH; };
key_list:
key_list ',' key_part order_dir { Lex->col_list.push_back($3); }
@@ -1172,10 +1428,12 @@ string_list:
alter:
ALTER opt_ignore TABLE_SYM table_ident
{
- LEX *lex=Lex;
+ THD *thd= YYTHD;
+ LEX *lex=&thd->lex;
lex->sql_command = SQLCOM_ALTER_TABLE;
lex->name=0;
- if (!add_table_to_list($4, NULL, TL_OPTION_UPDATING))
+ if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
+ TL_OPTION_UPDATING))
YYABORT;
lex->drop_primary=0;
lex->create_list.empty();
@@ -1183,20 +1441,25 @@ alter:
lex->col_list.empty();
lex->drop_list.empty();
lex->alter_list.empty();
- lex->select->order_list.elements=0;
- lex->select->order_list.first=0;
- lex->select->order_list.next= (byte**) &lex->select->order_list.first;
- lex->select->db=lex->name=0;
- bzero((char*) &lex->create_info,sizeof(lex->create_info));
+ lex->select_lex.init_order();
+ lex->select_lex.db=lex->name=0;
+ bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT;
+ lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_keys_onoff=LEAVE_AS_IS;
lex->simple_alter=1;
}
alter_list
{}
- ;
-
+ | ALTER DATABASE ident opt_create_database_options
+ {
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_ALTER_DB;
+ lex->name=$3.str;
+ };
+
+
alter_list:
| alter_list_item
| alter_list ',' alter_list_item;
@@ -1213,24 +1476,24 @@ alter_list_item:
lex->change= $3.str; lex->simple_alter=0;
}
field_spec opt_place
- | MODIFY_SYM opt_column field_ident
- {
- LEX *lex=Lex;
- lex->length=lex->dec=0; lex->type=0; lex->interval=0;
- lex->default_value=0;
+ | MODIFY_SYM opt_column field_ident
+ {
+ LEX *lex=Lex;
+ lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->default_value=lex->comment=0;
lex->simple_alter=0;
- }
- type opt_attribute
- {
- LEX *lex=Lex;
- if (add_field_to_list($3.str,
- (enum enum_field_types) $5,
- lex->length,lex->dec,lex->type,
- lex->default_value, $3.str,
- lex->interval))
- YYABORT;
- }
- opt_place
+ }
+ type opt_attribute
+ {
+ LEX *lex=Lex;
+ if (add_field_to_list(lex->thd,$3.str,
+ (enum enum_field_types) $5,
+ lex->length,lex->dec,lex->type,
+ lex->default_value, lex->comment,
+ $3.str, lex->interval, lex->charset))
+ YYABORT;
+ }
+ opt_place
| DROP opt_column field_ident opt_restrict
{
LEX *lex=Lex;
@@ -1265,12 +1528,12 @@ alter_list_item:
lex->simple_alter=0;
}
| RENAME opt_to table_ident
- {
+ {
LEX *lex=Lex;
- lex->select->db=$3->db.str;
+ lex->select_lex.db=$3->db.str;
lex->name= $3->table.str;
}
- | create_table_options { Lex->simple_alter=0; }
+ | create_table_options_space_separated { Lex->simple_alter=0; }
| order_clause { Lex->simple_alter=0; };
opt_column:
@@ -1298,36 +1561,23 @@ opt_to:
| AS {};
/*
- * The first two deprecate the last two--delete the last two for 4.1 release
- */
+ The first two deprecate the last two--delete the last two for 4.1 release
+*/
+
slave:
START_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
- lex->type = 0;
- }
- |
- STOP_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
- lex->type = 0;
- }
- |
- SLAVE START_SYM slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
- lex->type = 0;
- }
- |
- SLAVE STOP_SYM slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
- lex->type = 0;
- };
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_START;
+ lex->type = 0;
+ }
+ | STOP_SYM SLAVE slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->type = 0;
+ }
+ ;
start:
START_SYM TRANSACTION_SYM { Lex->sql_command = SQLCOM_BEGIN;}
@@ -1335,15 +1585,21 @@ start:
;
slave_thread_opts:
+ { Lex->slave_thd_opt= 0; }
+ slave_thread_opt_list
+ ;
+
+slave_thread_opt_list:
slave_thread_opt
- | slave_thread_opts ',' slave_thread_opt;
+ | slave_thread_opt_list ',' slave_thread_opt
+ ;
slave_thread_opt:
- /*empty*/ {}
+ /*empty*/ {}
| SQL_THREAD { Lex->slave_thd_opt|=SLAVE_SQL; }
| IO_THREAD { Lex->slave_thd_opt|=SLAVE_IO; }
;
-
+
restore:
RESTORE_SYM table_or_tables
{
@@ -1452,10 +1708,14 @@ table_to_table_list:
table_to_table:
table_ident TO_SYM table_ident
{
- if (!add_table_to_list($1, NULL, TL_OPTION_UPDATING, TL_IGNORE) ||
- !add_table_to_list($3, NULL, TL_OPTION_UPDATING, TL_IGNORE))
- YYABORT;
- };
+ LEX *lex=Lex;
+ SELECT_LEX_NODE *sl= lex->current_select;
+ if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
+ TL_IGNORE) ||
+ !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
+ TL_IGNORE))
+ YYABORT;
+ };
/*
Select : retrieve data from table
@@ -1465,29 +1725,73 @@ table_to_table:
select:
select_init { Lex->sql_command=SQLCOM_SELECT; };
+/* Need select_init2 for subselects. */
select_init:
- SELECT_SYM select_part2 { Select->braces= 0; } opt_union
+ SELECT_SYM select_init2
|
- '(' SELECT_SYM select_part2 ')' { Select->braces= 1;} union_opt;
+ '(' SELECT_SYM select_part2 ')'
+ {
+ LEX *lex= Lex;
+ SELECT_LEX * sel= lex->current_select->select_lex();
+ if (sel->set_braces(1))
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ if (sel->linkage == UNION_TYPE &&
+ !sel->master_unit()->first_select()->braces)
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ /* select in braces, can't contain global parameters */
+ sel->master_unit()->global_parameters=
+ sel->master_unit();
+ } union_opt;
+select_init2:
+ select_part2
+ {
+ LEX *lex= Lex;
+ SELECT_LEX * sel= lex->current_select->select_lex();
+ if (lex->current_select->set_braces(0))
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ if (sel->linkage == UNION_TYPE &&
+ sel->master_unit()->first_select()->braces)
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ }
+ union_clause
+ ;
select_part2:
{
LEX *lex=Lex;
- lex->lock_option=TL_READ;
- mysql_init_select(lex);
+ SELECT_LEX * sel= lex->current_select->select_lex();
+ if (lex->current_select == &lex->select_lex)
+ lex->lock_option= TL_READ; /* Only for global SELECT */
+ mysql_init_select(lex);
}
select_options select_item_list select_into select_lock_type;
select_into:
- limit_clause {}
+ opt_limit_clause {}
+ | FROM DUAL_SYM /* oracle compatibility: oracle always requires FROM
+ clause, and DUAL is system table without fields.
+ Is "SELECT 1 FROM DUAL" any better than
+ "SELECT 1" ? Hmmm :) */
+ | into
| select_from
- | opt_into select_from
- | select_from opt_into;
+ | into select_from
+ | select_from into;
select_from:
- FROM join_table_list where_clause group_clause having_clause opt_order_clause limit_clause procedure_clause;
-
+ FROM join_table_list where_clause group_clause having_clause opt_order_clause opt_limit_clause procedure_clause;
select_options:
/* empty*/
@@ -1520,7 +1824,7 @@ select_option:
YYABORT;
Select->options|= OPTION_FOUND_ROWS;
}
- | SQL_NO_CACHE_SYM { current_thd->safe_to_cache_query=0; }
+ | SQL_NO_CACHE_SYM { Lex->uncacheable(); }
| SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; }
| ALL {}
;
@@ -1530,18 +1834,15 @@ select_lock_type:
| FOR_SYM UPDATE_SYM
{
LEX *lex=Lex;
- if (check_simple_select())
- YYABORT;
- lex->lock_option= TL_WRITE;
- lex->thd->safe_to_cache_query=0;
+ lex->current_select->set_lock_for_tables(TL_WRITE);
+ lex->safe_to_cache_query=0;
}
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
{
LEX *lex=Lex;
- if (check_simple_select())
- YYABORT;
- lex->lock_option= TL_READ_WITH_SHARED_LOCKS;
- lex->thd->safe_to_cache_query=0;
+ lex->current_select->
+ set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
+ lex->safe_to_cache_query=0;
}
;
@@ -1550,15 +1851,17 @@ select_item_list:
| select_item
| '*'
{
- if (add_item_to_list(new Item_field(NULL,NULL,"*")))
+ THD *thd= YYTHD;
+ if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
YYABORT;
+ (thd->lex.current_select->select_lex()->with_wild)++;
};
select_item:
remember_name select_item2 remember_end select_alias
{
- if (add_item_to_list($2))
+ if (add_item_to_list(YYTHD, $2))
YYABORT;
if ($4.str)
$2->set_name($4.str);
@@ -1588,50 +1891,79 @@ optional_braces:
| '(' ')' {};
/* all possible expressions */
-expr: expr_expr {$$ = $1; }
- | simple_expr {$$ = $1; };
+expr:
+ expr_expr { $$= $1; }
+ | simple_expr { $$= $1; }
+ ;
+
+comp_op: EQ { $$ = &comp_eq_creator; }
+ | GE { $$ = &comp_ge_creator; }
+ | GT_SYM { $$ = &comp_gt_creator; }
+ | LE { $$ = &comp_le_creator; }
+ | LT { $$ = &comp_lt_creator; }
+ | NE { $$ = &comp_ne_creator; }
+ ;
+
+all_or_any: ALL { $$ = 1; }
+ | ANY_SYM { $$ = 0; }
+ ;
/* expressions that begin with 'expr' */
expr_expr:
- expr IN_SYM '(' expr_list ')'
+ expr IN_SYM '(' expr_list ')'
{ $$= new Item_func_in($1,*$4); }
| expr NOT IN_SYM '(' expr_list ')'
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
+ | expr IN_SYM in_subselect
+ { $$= new Item_in_subselect(YYTHD, $1, $3); }
+ | expr NOT IN_SYM in_subselect
+ {
+ $$= new Item_func_not(new Item_in_subselect(YYTHD, $1, $4));
+ }
| expr BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_between($1,$3,$5); }
| expr NOT BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
- | expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); }
+ | expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| expr OR expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr AND expr { $$= new Item_cond_and($1,$3); }
+ | expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
| expr REGEXP expr { $$= new Item_func_regex($1,$3); }
| expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); }
| expr IS NULL_SYM { $$= new Item_func_isnull($1); }
| expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | expr EQ expr { $$= new Item_func_eq($1,$3); }
| expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | expr GE expr { $$= new Item_func_ge($1,$3); }
- | expr GT_SYM expr { $$= new Item_func_gt($1,$3); }
- | expr LE expr { $$= new Item_func_le($1,$3); }
- | expr LT expr { $$= new Item_func_lt($1,$3); }
- | expr NE expr { $$= new Item_func_ne($1,$3); }
+ | expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); }
+ | expr comp_op all_or_any in_subselect %prec EQ
+ {
+ Item_allany_subselect *it=
+ new Item_allany_subselect(YYTHD, $1, (*$2)($3), $4);
+ if ($3)
+ $$ = new Item_func_not(it); /* ALL */
+ else
+ $$ = it; /* ANY/SOME */
+ }
| expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
| expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
| expr '+' expr { $$= new Item_func_plus($1,$3); }
| expr '-' expr { $$= new Item_func_minus($1,$3); }
| expr '*' expr { $$= new Item_func_mul($1,$3); }
| expr '/' expr { $$= new Item_func_div($1,$3); }
+ | expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
+ | expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
| expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
+ | expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| expr '%' expr { $$= new Item_func_mod($1,$3); }
- | expr '+' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,0); }
- | expr '-' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,1); };
+ | expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
+ | expr COLLATE_SYM collation_name
+ { $$= new Item_func_set_collation($1,$3); };
/* expressions that begin with 'expr' that do NOT follow IN_SYM */
no_in_expr:
@@ -1639,93 +1971,118 @@ no_in_expr:
{ $$= new Item_func_between($1,$3,$5); }
| no_in_expr NOT BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
- | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); }
+ | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_in_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr AND expr { $$= new Item_cond_and($1,$3); }
+ | no_in_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
| no_in_expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); }
| no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
| no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | no_in_expr EQ expr { $$= new Item_func_eq($1,$3); }
| no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | no_in_expr GE expr { $$= new Item_func_ge($1,$3); }
- | no_in_expr GT_SYM expr { $$= new Item_func_gt($1,$3); }
- | no_in_expr LE expr { $$= new Item_func_le($1,$3); }
- | no_in_expr LT expr { $$= new Item_func_lt($1,$3); }
- | no_in_expr NE expr { $$= new Item_func_ne($1,$3); }
+ | no_in_expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); }
+ | no_in_expr comp_op all_or_any in_subselect %prec EQ
+ {
+ Item_allany_subselect *it=
+ new Item_allany_subselect(YYTHD, $1, (*$2)($3), $4);
+ if ($3)
+ $$ = new Item_func_not(it); /* ALL */
+ else
+ $$ = it; /* ANY/SOME */
+ }
| no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
| no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
| no_in_expr '+' expr { $$= new Item_func_plus($1,$3); }
| no_in_expr '-' expr { $$= new Item_func_minus($1,$3); }
| no_in_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_in_expr '/' expr { $$= new Item_func_div($1,$3); }
+ | no_in_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
| no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
| no_in_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_in_expr '%' expr { $$= new Item_func_mod($1,$3); }
- | no_in_expr '+' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,0); }
- | no_in_expr '-' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,1); }
+ | no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
+ | no_in_expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | no_in_expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
| simple_expr;
/* expressions that begin with 'expr' that does NOT follow AND */
no_and_expr:
- no_and_expr IN_SYM '(' expr_list ')'
- { $$= new Item_func_in($1,*$4); }
+ no_and_expr IN_SYM '(' expr_list ')'
+ { $$= new Item_func_in($1,*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
+ | no_and_expr IN_SYM in_subselect
+ { $$= new Item_in_subselect(YYTHD, $1, $3); }
+ | no_and_expr NOT IN_SYM in_subselect
+ {
+ $$= new Item_func_not(new Item_in_subselect(YYTHD, $1, $4));
+ }
| no_and_expr BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_between($1,$3,$5); }
| no_and_expr NOT BETWEEN_SYM no_and_expr AND expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
- | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); }
+ | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
+ | no_and_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
| no_and_expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); }
| no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
| no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | no_and_expr EQ expr { $$= new Item_func_eq($1,$3); }
| no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | no_and_expr GE expr { $$= new Item_func_ge($1,$3); }
- | no_and_expr GT_SYM expr { $$= new Item_func_gt($1,$3); }
- | no_and_expr LE expr { $$= new Item_func_le($1,$3); }
- | no_and_expr LT expr { $$= new Item_func_lt($1,$3); }
- | no_and_expr NE expr { $$= new Item_func_ne($1,$3); }
+ | no_and_expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); }
+ | no_and_expr comp_op all_or_any in_subselect %prec EQ
+ {
+ Item_allany_subselect *it=
+ new Item_allany_subselect(YYTHD, $1, (*$2)($3), $4);
+ if ($3)
+ $$ = new Item_func_not(it); /* ALL */
+ else
+ $$ = it; /* ANY/SOME */
+ }
| no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
| no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
| no_and_expr '+' expr { $$= new Item_func_plus($1,$3); }
| no_and_expr '-' expr { $$= new Item_func_minus($1,$3); }
| no_and_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_and_expr '/' expr { $$= new Item_func_div($1,$3); }
+ | no_and_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
| no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
| no_and_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_and_expr '%' expr { $$= new Item_func_mod($1,$3); }
- | no_and_expr '+' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,0); }
- | no_and_expr '-' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,1); }
+ | no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
+ | no_and_expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | no_and_expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
| simple_expr;
+interval_expr:
+ INTERVAL_SYM expr { $$=$2; }
+ ;
+
simple_expr:
simple_ident
| literal
+ | param_marker
| '@' ident_or_text SET_VAR expr
{
$$= new Item_func_set_user_var($2,$4);
- current_thd->safe_to_cache_query=0;
+ Lex->uncacheable();;
}
- | '@' ident_or_text
+ | '@' ident_or_text
{
$$= new Item_func_get_user_var($2);
- current_thd->safe_to_cache_query=0;
+ Lex->uncacheable();;
}
| '@' '@' opt_var_ident_type ident_or_text
{
@@ -1738,18 +2095,37 @@ simple_expr:
| NOT expr %prec NEG { $$= new Item_func_not($2); }
| '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; }
+ | '(' expr ',' expr_list ')'
+ {
+ $4->push_front($2);
+ $$= new Item_row(*$4);
+ }
+ | ROW_SYM '(' expr ',' expr_list ')'
+ {
+ $5->push_front($3);
+ $$= new Item_row(*$5);
+ }
+ | EXISTS exists_subselect { $$= $2; }
+ | singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
- { Select->ftfunc_list.push_back((Item_func_match *)
+ { Select->add_ftfunc_to_list((Item_func_match *)
($$=new Item_func_match_nl(*$2,$5))); }
| MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')'
- { Select->ftfunc_list.push_back((Item_func_match *)
+ { Select->add_ftfunc_to_list((Item_func_match *)
($$=new Item_func_match_bool(*$2,$5))); }
- | BINARY expr %prec NEG { $$= new Item_func_binary($2); }
+ | ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); }
+ | BINARY expr %prec NEG { $$= new Item_func_set_collation($2,&my_charset_bin); }
| CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); }
| CASE_SYM opt_expr WHEN_SYM when_list opt_else END
{ $$= new Item_func_case(* $4, $2, $5 ); }
| CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); }
+ | CONVERT_SYM '(' expr USING charset_name ')'
+ { $$= new Item_func_conv_charset($3,$5); }
+ | CONVERT_SYM '(' expr ',' expr ',' expr ')'
+ { $$= new Item_func_conv_charset3($3,$7,$5); }
+ | DEFAULT '(' simple_ident ')'
+ { $$= new Item_default_value($3); }
| FUNC_ARG0 '(' ')'
{ $$= ((Item*(*)(void))($1.symbol->create_func))();}
| FUNC_ARG1 '(' expr ')'
@@ -1764,6 +2140,8 @@ simple_expr:
{ $$= new Item_func_atan($3,$5); }
| CHAR_SYM '(' expr_list ')'
{ $$= new Item_func_char(*$3); }
+ | CHARSET '(' expr ')'
+ { $$= new Item_func_charset($3); }
| COALESCE '(' expr_list ')'
{ $$= new Item_func_coalesce(* $3); }
| CONCAT '(' expr_list ')'
@@ -1771,22 +2149,22 @@ simple_expr:
| CONCAT_WS '(' expr ',' expr_list ')'
{ $$= new Item_func_concat_ws($3, *$5); }
| CURDATE optional_braces
- { $$= new Item_func_curdate(); current_thd->safe_to_cache_query=0; }
+ { $$= new Item_func_curdate(); Lex->safe_to_cache_query=0; }
| CURTIME optional_braces
- { $$= new Item_func_curtime(); current_thd->safe_to_cache_query=0; }
+ { $$= new Item_func_curtime(); Lex->safe_to_cache_query=0; }
| CURTIME '(' expr ')'
- {
- $$= new Item_func_curtime($3);
- current_thd->safe_to_cache_query=0;
+ {
+ $$= new Item_func_curtime($3);
+ Lex->safe_to_cache_query=0;
}
- | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
- { $$= new Item_date_add_interval($3,$6,$7,0); }
- | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
- { $$= new Item_date_add_interval($3,$6,$7,1); }
+ | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
+ { $$= new Item_date_add_interval($3,$5,$6,0); }
+ | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
+ { $$= new Item_date_add_interval($3,$5,$6,1); }
| DATABASE '(' ')'
- {
+ {
$$= new Item_func_database();
- current_thd->safe_to_cache_query=0;
+ Lex->safe_to_cache_query=0;
}
| ELT_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_elt($3, *$5); }
@@ -1795,7 +2173,7 @@ simple_expr:
| ENCRYPT '(' expr ')'
{
$$= new Item_func_encrypt($3);
- current_thd->safe_to_cache_query=0;
+ Lex->uncacheable();;
}
| ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); }
| DECODE_SYM '(' expr ',' TEXT_STRING ')'
@@ -1816,6 +2194,8 @@ simple_expr:
{ $$= new Item_func_export_set($3, $5, $7, $9); }
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')'
{ $$= new Item_func_export_set($3, $5, $7, $9, $11); }
+ | FALSE_SYM
+ { $$= new Item_int((char*) "FALSE",0,1); }
| FORMAT_SYM '(' expr ',' NUM ')'
{ $$= new Item_func_format($3,atoi($5.str)); }
| FROM_UNIXTIME '(' expr ')'
@@ -1826,70 +2206,132 @@ simple_expr:
}
| FIELD_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_field($3, *$5); }
+ | GEOMFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | GEOMFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | GEOMETRYCOLLECTION '(' expr_list ')'
+ { $$= new Item_func_spatial_collection(* $3,
+ Geometry::wkbGeometryCollection,
+ Geometry::wkbPoint); }
| HOUR_SYM '(' expr ')'
{ $$= new Item_func_hour($3); }
| IF '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_if($3,$5,$7); }
| INSERT '(' expr ',' expr ',' expr ',' expr ')'
{ $$= new Item_func_insert($3,$5,$7,$9); }
- | INTERVAL_SYM expr interval '+' expr
+ | interval_expr interval '+' expr
/* we cannot put interval before - */
- { $$= new Item_date_add_interval($5,$2,$3,0); }
- | INTERVAL_SYM '(' expr ',' expr_list ')'
- { $$= new Item_func_interval($3,* $5); }
+ { $$= new Item_date_add_interval($4,$1,$2,0); }
+ | interval_expr
+ {
+ if ($1->type() != Item::ROW_ITEM)
+ {
+ send_error(Lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ $$= new Item_func_interval((Item_row *)$1);
+ }
| LAST_INSERT_ID '(' ')'
{
- $$= new Item_int((char*) "last_insert_id()",
- current_thd->insert_id(),21);
- current_thd->safe_to_cache_query=0;
+ $$= get_system_var(OPT_SESSION, "last_insert_id", 14,
+ "last_insert_id()");
+ Lex->safe_to_cache_query= 0;
}
| LAST_INSERT_ID '(' expr ')'
{
$$= new Item_func_set_last_insert_id($3);
- current_thd->safe_to_cache_query=0;
+ Lex->safe_to_cache_query= 0;
}
| LEFT '(' expr ',' expr ')'
{ $$= new Item_func_left($3,$5); }
+ | LINESTRING '(' expr_list ')'
+ { $$= new Item_func_spatial_collection(* $3,
+ Geometry::wkbLineString, Geometry::wkbPoint); }
| LOCATE '(' expr ',' expr ')'
{ $$= new Item_func_locate($5,$3); }
| LOCATE '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_locate($5,$3,$7); }
- | GREATEST_SYM '(' expr ',' expr_list ')'
+ | GEOMCOLLFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | GEOMCOLLFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | GREATEST_SYM '(' expr ',' expr_list ')'
{ $5->push_front($3); $$= new Item_func_max(*$5); }
| LEAST_SYM '(' expr ',' expr_list ')'
{ $5->push_front($3); $$= new Item_func_min(*$5); }
| LOG_SYM '(' expr ')'
- { $$= new Item_func_log($3); }
+ { $$= new Item_func_log($3); }
| LOG_SYM '(' expr ',' expr ')'
- { $$= new Item_func_log($3, $5); }
+ { $$= new Item_func_log($3, $5); }
+ | LINEFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | LINEFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
| MASTER_POS_WAIT '(' expr ',' expr ')'
{
$$= new Item_master_pos_wait($3, $5);
- current_thd->safe_to_cache_query=0;
- }
+ Lex->safe_to_cache_query=0;
+ }
| MASTER_POS_WAIT '(' expr ',' expr ',' expr ')'
{
$$= new Item_master_pos_wait($3, $5, $7);
- current_thd->safe_to_cache_query=0;
+ Lex->safe_to_cache_query=0;
}
| MINUTE_SYM '(' expr ')'
{ $$= new Item_func_minute($3); }
+ | MOD_SYM '(' expr ',' expr ')'
+ { $$ = new Item_func_mod( $3, $5); }
| MONTH_SYM '(' expr ')'
{ $$= new Item_func_month($3); }
+ | MULTILINESTRING '(' expr_list ')'
+ { $$= new Item_func_spatial_collection(* $3,
+ Geometry::wkbMultiLineString, Geometry::wkbLineString); }
+ | MLINEFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | MLINEFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | MPOINTFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | MPOINTFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | MPOLYFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | MPOLYFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | MULTIPOINT '(' expr_list ')'
+ { $$= new Item_func_spatial_collection(* $3,
+ Geometry::wkbMultiPoint, Geometry::wkbPoint); }
+ | MULTIPOLYGON '(' expr_list ')'
+ { $$= new Item_func_spatial_collection(* $3,
+ Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); }
| NOW_SYM optional_braces
- { $$= new Item_func_now(); current_thd->safe_to_cache_query=0;}
+ { $$= new Item_func_now(); Lex->safe_to_cache_query=0;}
| NOW_SYM '(' expr ')'
- { $$= new Item_func_now($3); current_thd->safe_to_cache_query=0;}
+ { $$= new Item_func_now($3); Lex->safe_to_cache_query=0;}
| PASSWORD '(' expr ')'
- {
- $$= new Item_func_password($3);
- }
+ { $$= new Item_func_password($3); }
+ | PASSWORD '(' expr ',' expr ')'
+ { $$= new Item_func_password($3,$5); }
+ | POINT '(' expr ',' expr ')'
+ { $$= new Item_func_point($3,$5); }
+ | POINTFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | POINTFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | POLYFROMTEXT '(' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | POLYFROMTEXT '(' expr ',' expr ')'
+ { $$= new Item_func_geometry_from_text($3); }
+ | POLYGON '(' expr_list ')'
+ { $$= new Item_func_spatial_collection(* $3,
+ Geometry::wkbPolygon, Geometry::wkbLineString); }
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
| RAND '(' expr ')'
- { $$= new Item_func_rand($3); current_thd->safe_to_cache_query=0;}
+ { $$= new Item_func_rand($3); Lex->uncacheable();}
| RAND '(' ')'
- { $$= new Item_func_rand(); current_thd->safe_to_cache_query=0;}
+ { $$= new Item_func_rand(); Lex->uncacheable();}
| REPLACE '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_replace($3,$5,$7); }
| RIGHT '(' expr ',' expr ')'
@@ -1910,7 +2352,7 @@ simple_expr:
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
| TRIM '(' expr ')'
- { $$= new Item_func_trim($3,new Item_string(" ",1)); }
+ { $$= new Item_func_trim($3,new Item_string(" ",1,default_charset_info)); }
| TRIM '(' LEADING opt_pad FROM expr ')'
{ $$= new Item_func_ltrim($6,$4); }
| TRIM '(' TRAILING opt_pad FROM expr ')'
@@ -1921,6 +2363,8 @@ simple_expr:
{ $$= new Item_func_trim($5,$3); }
| TRUNCATE_SYM '(' expr ',' expr ')'
{ $$= new Item_func_round($3,$5,1); }
+ | TRUE_SYM
+ { $$= new Item_int((char*) "TRUE",1,1); }
| UDA_CHAR_SUM '(' udf_expr_list ')'
{
if ($3 != NULL)
@@ -1964,18 +2408,18 @@ simple_expr:
$$ = new Item_func_udf_int($1);
}
| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
- {
+ {
$$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9);
}
| UNIX_TIMESTAMP '(' ')'
{
$$= new Item_func_unix_timestamp();
- current_thd->safe_to_cache_query=0;
+ Lex->safe_to_cache_query=0;
}
| UNIX_TIMESTAMP '(' expr ')'
{ $$= new Item_func_unix_timestamp($3); }
| USER '(' ')'
- { $$= new Item_func_user(); current_thd->safe_to_cache_query=0; }
+ { $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
| WEEK_SYM '(' expr ')'
{ $$= new Item_func_week($3,new Item_int((char*) "0",0,1)); }
| WEEK_SYM '(' expr ',' expr ')'
@@ -1987,9 +2431,9 @@ simple_expr:
| YEARWEEK '(' expr ',' expr ')'
{ $$= new Item_func_yearweek($3, $5); }
| BENCHMARK_SYM '(' ULONG_NUM ',' expr ')'
- {
+ {
$$=new Item_func_benchmark($3,$5);
- current_thd->safe_to_cache_query=0;
+ Lex->uncacheable();
}
| EXTRACT_SYM '(' interval FROM expr ')'
{ $$=new Item_extract( $3, $5); };
@@ -2019,20 +2463,29 @@ sum_expr:
{ $$=new Item_sum_max($3); }
| STD_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_std($3); }
+ | VARIANCE_SYM '(' in_sum_expr ')'
+ { $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); };
in_sum_expr:
opt_all
- { Select->in_sum_expr++; }
+ {
+ LEX *lex= Lex;
+ if (lex->current_select->inc_in_sum_expr())
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ }
expr
{
- Select->in_sum_expr--;
- $$=$3;
+ Select->select_lex()->in_sum_expr--;
+ $$= $3;
};
cast_type:
- BINARY { $$=ITEM_CAST_BINARY; }
+ BINARY { $$=ITEM_CAST_BINARY; }
| CHAR_SYM { $$=ITEM_CAST_CHAR; }
| SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; }
| SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; }
@@ -2081,19 +2534,19 @@ when_list:
when_list2:
expr THEN_SYM expr
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX_NODE *sel=Select;
sel->when_list.head()->push_back($1);
sel->when_list.head()->push_back($3);
}
| when_list2 WHEN_SYM expr THEN_SYM expr
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX_NODE *sel=Select;
sel->when_list.head()->push_back($3);
sel->when_list.head()->push_back($5);
};
opt_pad:
- /* empty */ { $$=new Item_string(" ",1); }
+ /* empty */ { $$=new Item_string(" ",1,default_charset_info); }
| expr { $$=$1; };
join_table_list:
@@ -2108,7 +2561,7 @@ join_table_list:
| join_table_list normal_join join_table_list
USING
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->db1=$1->db; sel->table1=$1->alias;
sel->db2=$3->db; sel->table2=$3->alias;
}
@@ -2119,7 +2572,7 @@ join_table_list:
{ add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list LEFT opt_outer JOIN_SYM join_table_list
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->db1=$1->db; sel->table1=$1->alias;
sel->db2=$5->db; sel->table2=$5->alias;
}
@@ -2131,7 +2584,7 @@ join_table_list:
{ add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
| join_table_list RIGHT opt_outer JOIN_SYM join_table_list
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->db1=$1->db; sel->table1=$1->alias;
sel->db2=$5->db; sel->table2=$5->alias;
}
@@ -2150,20 +2603,54 @@ normal_join:
join_table:
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->use_index_ptr=sel->ignore_index_ptr=0;
sel->table_join_options= 0;
}
table_ident opt_table_alias opt_key_definition
{
- SELECT_LEX *sel=Select;
- if (!($$=add_table_to_list($2, $3, sel->table_join_options,
- TL_UNLOCK, sel->use_index_ptr,
- sel->ignore_index_ptr)))
+ LEX *lex= Lex;
+ SELECT_LEX_NODE *sel= lex->current_select;
+ if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
+ sel->get_table_join_options(),
+ lex->lock_option,
+ sel->get_use_index(),
+ sel->get_ignore_index())))
YYABORT;
}
| '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}'
- { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; };
+ { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
+ | '(' SELECT_SYM select_derived ')' opt_table_alias
+ {
+ LEX *lex=Lex;
+ SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
+ lex->current_select= unit->outer_select();
+ if (!($$= lex->current_select->
+ add_table_to_list(lex->thd, new Table_ident(unit), $5, 0,
+ TL_READ,(List<String> *)0,
+ (List<String> *)0)))
+
+ YYABORT;
+ };
+
+select_derived:
+ {
+ LEX *lex= Lex;
+ lex->derived_tables= 1;
+ if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN &&
+ lex->sql_command <= (int)SQLCOM_HA_READ) || lex->sql_command == (int)SQLCOM_KILL)
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
+ mysql_new_select(lex, 1))
+ YYABORT;
+ mysql_init_select(lex);
+ lex->current_select->linkage= DERIVED_TABLE_TYPE;
+ }
+ select_options select_item_list opt_select_from union_opt
+ ;
opt_outer:
/* empty */ {}
@@ -2173,47 +2660,62 @@ opt_key_definition:
/* empty */ {}
| USE_SYM key_usage_list
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
}
| FORCE_SYM key_usage_list
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
}
| IGNORE_SYM key_usage_list
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
sel->ignore_index= *$2;
sel->ignore_index_ptr= &sel->ignore_index;
- }
- ;
+ };
key_usage_list:
- key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')'
- { $$= &Select->interval_list; };
+ key_or_index { Select->select_lex()->interval_list.empty(); }
+ '(' key_list_or_empty ')'
+ { $$= &Select->select_lex()->interval_list; }
+ ;
+
+key_list_or_empty:
+ /* empty */ {}
+ | key_usage_list2 {}
+ ;
key_usage_list2:
key_usage_list2 ',' ident
- { Select->interval_list.push_back(new String((const char*) $3.str,$3.length)); }
+ { Select->select_lex()->
+ interval_list.push_back(new String((const char*) $3.str, $3.length,
+ default_charset_info)); }
| ident
- { Select->interval_list.push_back(new String((const char*) $1.str,$1.length)); }
+ { Select->select_lex()->
+ interval_list.push_back(new String((const char*) $1.str, $1.length,
+ default_charset_info)); }
| PRIMARY_SYM
- { Select->interval_list.push_back(new String("PRIMARY",7)); };
+ { Select->select_lex()->
+ interval_list.push_back(new String("PRIMARY", 7,
+ default_charset_info)); };
using_list:
ident
{
- SELECT_LEX *sel=Select;
- if (!($$= new Item_func_eq(new Item_field(sel->db1,sel->table1, $1.str), new Item_field(sel->db2,sel->table2,$1.str))))
+ SELECT_LEX *sel= Select->select_lex();
+ if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
+ $1.str),
+ new Item_field(sel->db2, sel->table2,
+ $1.str))))
YYABORT;
}
| using_list ',' ident
{
- SELECT_LEX *sel=Select;
+ SELECT_LEX *sel= Select->select_lex();
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
YYABORT;
};
@@ -2249,25 +2751,24 @@ opt_all:
;
where_clause:
- /* empty */ { Select->where= 0; }
+ /* empty */ { Select->select_lex()->where= 0; }
| WHERE expr
{
- Select->where= $2;
+ Select->select_lex()->where= $2;
if ($2)
$2->top_level_item();
}
- ;
+ ;
having_clause:
/* empty */
- | HAVING { Select->create_refs=1; } expr
- {
- SELECT_LEX *sel=Select;
- sel->having= $3;
- sel->create_refs=0;
- if ($3)
- $3->top_level_item();
- }
+ | HAVING { Select->select_lex()->create_refs= 1; } expr
+ {
+ SELECT_LEX *sel= Select->select_lex();
+ sel->having= $3; sel->create_refs=0;
+ if ($3)
+ $3->top_level_item();
+ }
;
opt_escape:
@@ -2285,26 +2786,36 @@ group_clause:
group_list:
group_list ',' order_ident order_dir
- { if (add_group_to_list($3,(bool) $4)) YYABORT; }
+ { if (add_group_to_list(YYTHD, $3,(bool) $4)) YYABORT; }
| order_ident order_dir
- { if (add_group_to_list($1,(bool) $2)) YYABORT; };
+ { if (add_group_to_list(YYTHD, $1,(bool) $2)) YYABORT; };
olap_opt:
/* empty */ {}
| WITH CUBE_SYM
{
LEX *lex=Lex;
- lex->olap = true;
- lex->select->olap= CUBE_TYPE;
- net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE");
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+ {
+ net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
+ "global union parameters");
+ YYABORT;
+ }
+ lex->current_select->select_lex()->olap= CUBE_TYPE;
+ net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
YYABORT; /* To be deleted in 4.1 */
}
| WITH ROLLUP_SYM
{
- LEX *lex=Lex;
- lex->olap = true;
- lex->select->olap= ROLLUP_TYPE;
- net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP");
+ LEX *lex= Lex;
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+ {
+ net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
+ "global union parameters");
+ YYABORT;
+ }
+ lex->current_select->select_lex()->olap= ROLLUP_TYPE;
+ net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP");
YYABORT; /* To be deleted in 4.1 */
}
;
@@ -2318,24 +2829,25 @@ opt_order_clause:
| order_clause;
order_clause:
- ORDER_SYM BY
- {
+ ORDER_SYM BY
+ {
LEX *lex=Lex;
- if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+ if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
+ lex->current_select->select_lex()->olap !=
+ UNSPECIFIED_OLAP_TYPE)
{
- net_printf(&lex->thd->net, ER_WRONG_USAGE,
+ net_printf(lex->thd, ER_WRONG_USAGE,
"CUBE/ROLLUP",
"ORDER BY");
YYABORT;
}
- lex->select->sort_default=1;
} order_list;
order_list:
order_list ',' order_ident order_dir
- { if (add_order_to_list($3,(bool) $4)) YYABORT; }
+ { if (add_order_to_list(YYTHD, $3,(bool) $4)) YYABORT; }
| order_ident order_dir
- { if (add_order_to_list($1,(bool) $2)) YYABORT; };
+ { if (add_order_to_list(YYTHD, $1,(bool) $2)) YYABORT; };
order_dir:
/* empty */ { $$ = 1; }
@@ -2343,48 +2855,65 @@ order_dir:
| DESC { $$ =0; };
+opt_limit_clause_init:
+ /* empty */
+ {
+ SELECT_LEX_NODE *sel= Select;
+ sel->offset_limit= 0L;
+ sel->select_limit= Lex->thd->variables.select_limit;
+ }
+ | limit_clause {}
+ ;
+
+opt_limit_clause:
+ /* empty */ {}
+ | limit_clause {}
+ ;
+
limit_clause:
- /* empty */ {}
- | LIMIT
+ LIMIT
{
- LEX *lex=Lex;
- if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+ LEX *lex= Lex;
+ if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
+ lex->current_select->select_lex()->olap !=
+ UNSPECIFIED_OLAP_TYPE)
{
- net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP",
+ net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
"LIMIT");
YYABORT;
}
}
limit_options
{}
- ;
+ ;
limit_options:
ULONG_NUM
{
- SELECT_LEX *sel= Select;
+ SELECT_LEX_NODE *sel= Select;
sel->select_limit= $1;
sel->offset_limit= 0L;
}
| ULONG_NUM ',' ULONG_NUM
{
- SELECT_LEX *sel= Select;
+ SELECT_LEX_NODE *sel= Select;
sel->select_limit= $3;
sel->offset_limit= $1;
}
| ULONG_NUM OFFSET_SYM ULONG_NUM
{
- SELECT_LEX *sel= Select;
+ SELECT_LEX_NODE *sel= Select;
sel->select_limit= $1;
sel->offset_limit= $3;
}
;
+
delete_limit_clause:
/* empty */
{
LEX *lex=Lex;
- lex->select->select_limit= HA_POS_ERROR;
+ lex->current_select->select_limit= HA_POS_ERROR;
}
| LIMIT ulonglong_num
{ Select->select_limit= (ha_rows) $2; };
@@ -2408,12 +2937,19 @@ procedure_clause:
| PROCEDURE ident /* Procedure name */
{
LEX *lex=Lex;
+ if (&lex->select_lex != lex->current_select)
+ {
+ net_printf(lex->thd, ER_WRONG_USAGE,
+ "PROCEDURE",
+ "subquery");
+ YYABORT;
+ }
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= (byte**) &lex->proc_list.first;
if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
YYABORT;
- current_thd->safe_to_cache_query=0;
+ Lex->uncacheable();
}
'(' procedure_list ')';
@@ -2434,26 +2970,68 @@ procedure_item:
YYABORT;
if (!$2->name)
$2->set_name($1,(uint) ((char*) lex->tok_end - $1));
- };
+ }
+ ;
+
-opt_into:
- INTO OUTFILE TEXT_STRING
+select_var_list_init:
+ {
+ LEX *lex=Lex;
+ if (!lex->describe && (!(lex->result= new select_dumpvar())))
+ YYABORT;
+ }
+ select_var_list
+ {}
+ ;
+
+select_var_list:
+ select_var_list ',' select_var_ident
+ | select_var_ident {}
+ ;
+
+select_var_ident: '@' ident_or_text
+ {
+ LEX *lex=Lex;
+ if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
+ YYABORT;
+ }
+ ;
+
+into:
+ INTO OUTFILE TEXT_STRING
{
- if (!(Lex->exchange= new sql_exchange($3.str,0)))
- YYABORT;
+ LEX *lex=Lex;
+ if (!lex->describe)
+ {
+ if (!(lex->exchange= new sql_exchange($3.str,0)))
+ YYABORT;
+ if (!(lex->result= new select_export(lex->exchange)))
+ YYABORT;
+ }
}
opt_field_term opt_line_term
| INTO DUMPFILE TEXT_STRING
{
- if (!(Lex->exchange= new sql_exchange($3.str,1)))
- YYABORT;
- };
+ LEX *lex=Lex;
+ if (!lex->describe)
+ {
+ if (!(lex->exchange= new sql_exchange($3.str,1)))
+ YYABORT;
+ if (!(lex->result= new select_dump(lex->exchange)))
+ YYABORT;
+ }
+ }
+ | INTO select_var_list_init
+ {
+ Lex->uncacheable();
+ }
+ ;
/*
DO statement
*/
-do: DO_SYM
+do: DO_SYM
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DO;
@@ -2483,7 +3061,8 @@ drop:
lex->drop_list.empty();
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
- if (!add_table_to_list($5, NULL, TL_OPTION_UPDATING))
+ if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
+ TL_OPTION_UPDATING))
YYABORT;
}
| DROP DATABASE if_exists ident
@@ -2493,11 +3072,11 @@ drop:
lex->drop_if_exists=$3;
lex->name=$4.str;
}
- | DROP UDF_SYM ident
+ | DROP UDF_SYM IDENT
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_FUNCTION;
- lex->udf.name=$3.str;
+ lex->udf.name = $3;
};
@@ -2507,7 +3086,11 @@ table_list:
table_name:
table_ident
- { if (!add_table_to_list($1,NULL,TL_OPTION_UPDATING)) YYABORT; };
+ {
+ if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING))
+ YYABORT;
+ }
+ ;
if_exists:
/* empty */ { $$= 0; }
@@ -2523,28 +3106,35 @@ opt_temporary:
*/
insert:
- INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option
- opt_ignore insert2
+ INSERT
{
- set_lock_for_tables($3);
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_INSERT;
+ /* for subselects */
+ lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
+ } insert_lock_option
+ opt_ignore insert2
+ {
+ Select->set_lock_for_tables($3);
}
- insert_field_spec
+ insert_field_spec opt_insert_update
{}
;
replace:
REPLACE
{
- LEX *lex=Lex;
+ LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
}
replace_lock_option insert2
{
- set_lock_for_tables($3);
+ Select->set_lock_for_tables($3);
}
insert_field_spec
{}
+ {}
;
insert_lock_option:
@@ -2552,7 +3142,7 @@ insert_lock_option:
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
| DELAYED_SYM { $$= TL_WRITE_DELAYED; }
| HIGH_PRIORITY { $$= TL_WRITE; }
- ;
+ ;
replace_lock_option:
opt_low_priority { $$= $1; }
@@ -2593,6 +3183,7 @@ fields:
insert_values:
VALUES values_list {}
+ | VALUE_SYM values_list {}
| SELECT_SYM
{
LEX *lex=Lex;
@@ -2601,8 +3192,9 @@ insert_values:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
}
- select_options select_item_list select_from select_lock_type
- opt_union {};
+ select_options select_item_list opt_select_from select_lock_type
+ union_clause {}
+ ;
values_list:
values_list ',' no_braces
@@ -2662,55 +3254,70 @@ values:
;
expr_or_default:
- expr { $$= $1;}
- | DEFAULT {$$= new Item_default(); }
+ expr { $$= $1;}
+ | DEFAULT {$$= new Item_default_value(); }
;
+opt_insert_update:
+ /* empty */
+ | ON DUPLICATE_SYM
+ { /* for simplisity, let's forget about
+ INSERT ... SELECT ... UPDATE
+ for a moment */
+ if (Lex->sql_command != SQLCOM_INSERT)
+ {
+ send_error(Lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ }
+ KEY_SYM UPDATE_SYM update_list
+ ;
+
/* Update rows in a table */
update:
- UPDATE_SYM
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_UPDATE;
- lex->select->order_list.elements=0;
- lex->select->order_list.first=0;
- lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+ UPDATE_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_UPDATE;
+ lex->select_lex.init_order();
}
opt_low_priority opt_ignore join_table_list
SET update_list where_clause opt_order_clause delete_limit_clause
{
- set_lock_for_tables($3);
+ LEX *lex= Lex;
+ Select->set_lock_for_tables($3);
+ if (lex->select_lex.table_list.elements > 1)
+ lex->sql_command=SQLCOM_UPDATE_MULTI;
}
;
update_list:
- update_list ',' simple_ident equal expr
+ update_list ',' simple_ident equal expr_or_default
{
- if (add_item_to_list($3) || add_value_to_list($5))
+ if (add_item_to_list(YYTHD, $3) || add_value_to_list(YYTHD, $5))
YYABORT;
}
- | simple_ident equal expr
+ | simple_ident equal expr_or_default
{
- if (add_item_to_list($1) || add_value_to_list($3))
+ if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3))
YYABORT;
};
opt_low_priority:
- /* empty */ { $$= current_thd->update_lock_default; }
+ /* empty */ { $$= YYTHD->update_lock_default; }
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
/* Delete rows from a table */
delete:
DELETE_SYM
- {
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_DELETE; lex->select->options=0;
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE;
+ lex->select_lex.options= 0;
lex->lock_option= lex->thd->update_lock_default;
- lex->select->order_list.elements=0;
- lex->select->order_list.first=0;
- lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+ lex->select_lex.init_order();
}
opt_delete_options single_multi {}
;
@@ -2718,8 +3325,8 @@ delete:
single_multi:
FROM table_ident
{
- if (!add_table_to_list($2, NULL, TL_OPTION_UPDATING,
- Lex->lock_option))
+ if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING,
+ Lex->lock_option))
YYABORT;
}
where_clause opt_order_clause
@@ -2738,23 +3345,23 @@ table_wild_list:
| table_wild_list ',' table_wild_one {};
table_wild_one:
- ident opt_wild
- {
- if (!add_table_to_list(new Table_ident($1), NULL,
- TL_OPTION_UPDATING, Lex->lock_option))
- YYABORT;
- }
- | ident '.' ident opt_wild
- {
- if (!add_table_to_list(new Table_ident($1,$3,0), NULL,
- TL_OPTION_UPDATING,
- Lex->lock_option))
+ ident opt_wild opt_table_alias
+ {
+ if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3,
+ TL_OPTION_UPDATING, Lex->lock_option))
+ YYABORT;
+ }
+ | ident '.' ident opt_wild opt_table_alias
+ {
+ if (!Select->add_table_to_list(YYTHD, new Table_ident($1, $3, 0),
+ $5, TL_OPTION_UPDATING,
+ Lex->lock_option))
YYABORT;
- }
+ }
;
opt_wild:
- /* empty */ {}
+ /* empty */ {}
| '.' '*' {};
@@ -2769,22 +3376,26 @@ opt_delete_option:
truncate:
TRUNCATE_SYM opt_table_sym table_name
{
- LEX* lex = Lex;
+ LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
- lex->select->options=0;
- lex->select->order_list.elements=0;
- lex->select->order_list.first=0;
- lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+ lex->select_lex.options= 0;
+ lex->select_lex.init_order();
}
;
opt_table_sym:
/* empty */
| TABLE_SYM;
-
+
/* Show things */
-show: SHOW { Lex->wild=0;} show_param
+show: SHOW
+ {
+ LEX *lex=Lex;
+ lex->wild=0;
+ bzero((char*) &lex->create_info,sizeof(lex->create_info));
+ }
+ show_param
{}
;
@@ -2793,33 +3404,34 @@ show_param:
{ Lex->sql_command= SQLCOM_SHOW_DATABASES; }
| TABLES opt_db wild
{
- LEX *lex=Lex;
+ LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select->db= $2; lex->select->options=0;
+ lex->select_lex.db= $2;
+ lex->select_lex.options= 0;
}
| TABLE_SYM STATUS_SYM opt_db wild
{
- LEX *lex=Lex;
+ LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select->options|= SELECT_DESCRIBE;
- lex->select->db= $3;
+ lex->select_lex.options|= SELECT_DESCRIBE;
+ lex->select_lex.db= $3;
}
| OPEN_SYM TABLES opt_db wild
{
- LEX *lex=Lex;
+ LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- lex->select->db= $3;
- lex->select->options=0;
+ lex->select_lex.db= $3;
+ lex->select_lex.options= 0;
}
| opt_full COLUMNS from_or_in table_ident opt_db wild
{
Lex->sql_command= SQLCOM_SHOW_FIELDS;
if ($5)
$4->change_db($5);
- if (!add_table_to_list($4, NULL, 0))
+ if (!Select->add_table_to_list(YYTHD, $4, NULL, 0))
YYABORT;
}
- | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
+ | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
TEXT_STRING AND MASTER_LOG_POS_SYM EQ ulonglong_num
AND MASTER_SERVER_ID_SYM EQ
ULONG_NUM
@@ -2829,7 +3441,7 @@ show_param:
Lex->mi.pos = $12;
Lex->mi.server_id = $16;
}
- | MASTER_SYM LOGS_SYM
+ | BINARY LOGS_SYM
{
Lex->sql_command = SQLCOM_SHOW_BINLOGS;
}
@@ -2839,19 +3451,40 @@ show_param:
}
| BINLOG_SYM EVENTS_SYM binlog_in binlog_from
{
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS;
- lex->select->select_limit= lex->thd->variables.select_limit;
- lex->select->offset_limit= 0L;
- } limit_clause
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
+ } opt_limit_clause_init
| keys_or_index FROM table_ident opt_db
{
Lex->sql_command= SQLCOM_SHOW_KEYS;
if ($4)
$3->change_db($4);
- if (!add_table_to_list($3, NULL, 0))
+ if (!Select->add_table_to_list(YYTHD, $3, NULL, 0))
YYABORT;
}
+ | COLUMN_SYM TYPES_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_COLUMN_TYPES;
+ }
+ | TABLE_SYM TYPES_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_TABLE_TYPES;
+ }
+ | PRIVILEGES
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_PRIVILEGES;
+ }
+ | COUNT_SYM '(' '*' ')' WARNINGS
+ { (void) create_select_for_variable("warning_count"); }
+ | COUNT_SYM '(' '*' ')' ERRORS
+ { (void) create_select_for_variable("error_count"); }
+ | WARNINGS opt_limit_clause_init
+ { Lex->sql_command = SQLCOM_SHOW_WARNS;}
+ | ERRORS opt_limit_clause_init
+ { Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| STATUS_SYM wild
{ Lex->sql_command= SQLCOM_SHOW_STATUS; }
| INNOBASE_SYM STATUS_SYM
@@ -2859,11 +3492,13 @@ show_param:
| opt_full PROCESSLIST_SYM
{ Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
| opt_var_type VARIABLES wild
- {
- THD *thd= current_thd;
+ {
+ THD *thd= YYTHD;
thd->lex.sql_command= SQLCOM_SHOW_VARIABLES;
thd->lex.option_type= (enum_var_type) $1;
}
+ | CHAR_SYM SET wild
+ { Lex->sql_command= SQLCOM_SHOW_CHARSETS; }
| LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; }
| GRANTS FOR_SYM user
@@ -2873,10 +3508,16 @@ show_param:
lex->grant_user=$3;
lex->grant_user->password.str=NullS;
}
+ | CREATE DATABASE opt_if_not_exists ident
+ {
+ Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
+ Lex->create_info.options=$3;
+ Lex->name=$4.str;
+ }
| CREATE TABLE_SYM table_ident
{
Lex->sql_command = SQLCOM_SHOW_CREATE;
- if(!add_table_to_list($3, NULL, 0))
+ if (!Select->add_table_to_list(YYTHD, $3, NULL,0))
YYABORT;
}
| MASTER_SYM STATUS_SYM
@@ -2921,13 +3562,16 @@ describe:
lex->wild=0;
lex->verbose=0;
lex->sql_command=SQLCOM_SHOW_FIELDS;
- if (!add_table_to_list($2, NULL, 0))
+ if (!Select->add_table_to_list(lex->thd, $2, NULL,0))
YYABORT;
}
opt_describe_column {}
- | describe_command select
- { Lex->select_lex.options|= SELECT_DESCRIBE; };
-
+ | describe_command { Lex->describe=1; } select
+ {
+ LEX *lex=Lex;
+ lex->select_lex.options|= SELECT_DESCRIBE;
+ }
+ ;
describe_command:
DESC
@@ -2937,7 +3581,7 @@ opt_describe_column:
/* empty */ {}
| text_string { Lex->wild= $1; }
| ident
- { Lex->wild= new String((const char*) $1.str,$1.length); };
+ { Lex->wild= new String((const char*) $1.str,$1.length,default_charset_info); };
/* flush things */
@@ -3009,9 +3653,9 @@ kill:
KILL_SYM expr
{
LEX *lex=Lex;
- if ($2->fix_fields(lex->thd,0))
- {
- send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY);
+ if ($2->fix_fields(lex->thd, 0, &$2) || $2->check_cols(1))
+ {
+ send_error(lex->thd, ER_SET_CONSTANTS_ONLY);
YYABORT;
}
lex->sql_command=SQLCOM_KILL;
@@ -3023,7 +3667,8 @@ kill:
use: USE_SYM ident
{
LEX *lex=Lex;
- lex->sql_command=SQLCOM_CHANGE_DB; lex->select->db= $2.str;
+ lex->sql_command=SQLCOM_CHANGE_DB;
+ lex->select_lex.db= $2.str;
};
/* import, export of files */
@@ -3041,14 +3686,14 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
opt_ignore_lines opt_field_spec
{
- if (!add_table_to_list($11, NULL, TL_OPTION_UPDATING))
+ if (!Select->add_table_to_list(YYTHD, $11, NULL, TL_OPTION_UPDATING))
YYABORT;
}
|
LOAD TABLE_SYM table_ident FROM MASTER_SYM
{
Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
- if (!add_table_to_list($3, NULL, TL_OPTION_UPDATING))
+ if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
YYABORT;
}
@@ -3063,7 +3708,7 @@ opt_local:
| LOCAL_SYM { $$=1;};
load_data_lock:
- /* empty */ { $$= current_thd->update_lock_default; }
+ /* empty */ { $$= YYTHD->update_lock_default; }
| CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; }
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
@@ -3112,17 +3757,40 @@ opt_ignore_lines:
/* Common definitions */
text_literal:
- TEXT_STRING { $$ = new Item_string($1.str,$1.length); }
+ TEXT_STRING
+ { $$ = new Item_string($1.str,$1.length,
+ YYTHD->variables.thd_charset); }
+ | UNDERSCORE_CHARSET TEXT_STRING
+ { $$ = new Item_string($2.str,$2.length,Lex->charset); }
| text_literal TEXT_STRING
- { ((Item_string*) $1)->append($2.str,$2.length); };
+ { ((Item_string*) $1)->append($2.str,$2.length); };
text_string:
- TEXT_STRING { $$= new String($1.str,$1.length); }
+ TEXT_STRING
+ { $$= new String($1.str,$1.length,YYTHD->variables.thd_charset); }
| HEX_NUM
{
Item *tmp = new Item_varbinary($1.str,$1.length);
$$= tmp ? tmp->val_str((String*) 0) : (String*) 0;
- };
+ }
+ ;
+
+param_marker:
+ '?'
+ {
+ LEX *lex=Lex;
+ if (YYTHD->prepare_command)
+ {
+ lex->param_list.push_back($$=new Item_param());
+ lex->param_count++;
+ }
+ else
+ {
+ yyerror("You have an error in your SQL syntax");
+ YYABORT;
+ }
+ }
+ ;
literal:
text_literal { $$ = $1; }
@@ -3147,10 +3815,19 @@ insert_ident:
| table_wild { $$=$1; };
table_wild:
- ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); }
+ ident '.' '*'
+ {
+ $$ = new Item_field(NullS,$1.str,"*");
+ Lex->current_select->select_lex()->with_wild++;
+ }
| ident '.' ident '.' '*'
- { $$ = new Item_field((current_thd->client_capabilities &
- CLIENT_NO_SCHEMA ? NullS : $1.str),$3.str,"*"); };
+ {
+ $$ = new Item_field((YYTHD->client_capabilities &
+ CLIENT_NO_SCHEMA ? NullS : $1.str),
+ $3.str,"*");
+ Lex->current_select->select_lex()->with_wild++;
+ }
+ ;
order_ident:
expr { $$=$1; };
@@ -3158,23 +3835,47 @@ order_ident:
simple_ident:
ident
{
- SELECT_LEX *sel=Select;
- $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
+ SELECT_LEX_NODE *sel=Select;
+ $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
}
| ident '.' ident
{
- SELECT_LEX *sel=Select;
- $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
+ THD *thd= YYTHD;
+ LEX *lex= &thd->lex;
+ SELECT_LEX_NODE *sel= lex->current_select;
+ if (sel->no_table_names_allowed)
+ {
+ my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ ER(ER_TABLENAME_NOT_ALLOWED_HERE),
+ MYF(0), $1.str, thd->where);
+ }
+ $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
}
| '.' ident '.' ident
{
- SELECT_LEX *sel=Select;
- $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
+ THD *thd= YYTHD;
+ LEX *lex= &thd->lex;
+ SELECT_LEX_NODE *sel= lex->current_select;
+ if (sel->no_table_names_allowed)
+ {
+ my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ ER(ER_TABLENAME_NOT_ALLOWED_HERE),
+ MYF(0), $2.str, thd->where);
+ }
+ $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
}
| ident '.' ident '.' ident
{
- SELECT_LEX *sel=Select;
- $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
+ THD *thd= YYTHD;
+ LEX *lex= &thd->lex;
+ SELECT_LEX_NODE *sel= lex->current_select;
+ if (sel->no_table_names_allowed)
+ {
+ my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ ER(ER_TABLENAME_NOT_ALLOWED_HERE),
+ MYF(0), $3.str, thd->where);
+ }
+ $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
};
@@ -3209,13 +3910,15 @@ ident_or_text:
user:
ident_or_text
{
- if (!($$=(LEX_USER*) sql_alloc(sizeof(st_lex_user))))
+ THD *thd= YYTHD;
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
YYABORT;
$$->user = $1; $$->host.str=NullS;
}
| ident_or_text '@' ident_or_text
{
- if (!($$=(LEX_USER*) sql_alloc(sizeof(st_lex_user))))
+ THD *thd= YYTHD;
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
YYABORT;
$$->user = $1; $$->host=$3;
};
@@ -3227,6 +3930,8 @@ keyword:
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
+ | ANY_SYM {}
+ | ASCII_SYM {}
| AUTO_INC {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
@@ -3237,6 +3942,7 @@ keyword:
| BIT_SYM {}
| BOOL_SYM {}
| BOOLEAN_SYM {}
+ | BYTE_SYM {}
| CACHE_SYM {}
| CHANGED {}
| CHARSET {}
@@ -3258,7 +3964,9 @@ keyword:
| DES_KEY_FILE {}
| DIRECTORY_SYM {}
| DO_SYM {}
+ | DUAL_SYM {}
| DUMPFILE {}
+ | DUPLICATE_SYM {}
| DYNAMIC_SYM {}
| END {}
| ENUM {}
@@ -3267,17 +3975,19 @@ keyword:
| EXECUTE_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
- | DISABLE_SYM {}
- | ENABLE_SYM {}
+ | DISABLE_SYM {}
+ | ENABLE_SYM {}
| FULL {}
| FILE_SYM {}
| FIRST_SYM {}
| FIXED_SYM {}
| FLUSH_SYM {}
- | GRANTS {}
+ | GEOMETRY_SYM {}
+ | GRANTS {}
| GLOBAL_SYM {}
- | HEAP_SYM {}
| HANDLER_SYM {}
+ | HEAP_SYM {}
+ | HELP_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
@@ -3287,9 +3997,10 @@ keyword:
| ISSUER_SYM {}
| INNOBASE_SYM {}
| INSERT_METHOD {}
- | IO_THREAD {}
+ | IO_THREAD {}
| LAST_SYM {}
| LEVEL_SYM {}
+ | LINESTRING {}
| LOCAL_SYM {}
| LOCKS_SYM {}
| LOGS_SYM {}
@@ -3302,9 +4013,9 @@ keyword:
| MASTER_USER_SYM {}
| MASTER_PASSWORD_SYM {}
| MASTER_CONNECT_RETRY_SYM {}
- | MAX_CONNECTIONS_PER_HOUR {}
- | MAX_QUERIES_PER_HOUR {}
- | MAX_UPDATES_PER_HOUR {}
+ | MAX_CONNECTIONS_PER_HOUR {}
+ | MAX_QUERIES_PER_HOUR {}
+ | MAX_UPDATES_PER_HOUR {}
| MEDIUM_SYM {}
| MERGE_SYM {}
| MINUTE_SYM {}
@@ -3312,6 +4023,9 @@ keyword:
| MODIFY_SYM {}
| MODE_SYM {}
| MONTH_SYM {}
+ | MULTILINESTRING {}
+ | MULTIPOINT {}
+ | MULTIPOLYGON {}
| MYISAM_SYM {}
| NATIONAL_SYM {}
| NCHAR_SYM {}
@@ -3322,19 +4036,22 @@ keyword:
| OFFSET_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
+ | PARTIAL {}
| PASSWORD {}
+ | POINT {}
+ | POLYGON {}
| PREV_SYM {}
| PROCESS {}
| PROCESSLIST_SYM {}
| QUERY_SYM {}
| QUICK {}
- | RAID_0_SYM {}
+ | RAID_0_SYM {}
| RAID_CHUNKS {}
| RAID_CHUNKSIZE {}
- | RAID_STRIPED_SYM {}
+ | RAID_STRIPED_SYM {}
| RAID_TYPE {}
- | RELAY_LOG_FILE_SYM {}
- | RELAY_LOG_POS_SYM {}
+ | RELAY_LOG_FILE_SYM {}
+ | RELAY_LOG_POS_SYM {}
| RELOAD {}
| REPAIR {}
| REPEATABLE_SYM {}
@@ -3348,16 +4065,18 @@ keyword:
| ROW_FORMAT_SYM {}
| ROW_SYM {}
| SECOND_SYM {}
+ | SERIAL_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
| SIGNED_SYM {}
+ | SIMPLE_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
- | SLAVE {}
+ | SLAVE {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
- | SQL_THREAD {}
+ | SQL_THREAD {}
| START_SYM {}
| STATUS_SYM {}
| STOP_SYM {}
@@ -3373,10 +4092,14 @@ keyword:
| TYPE_SYM {}
| UDF_SYM {}
| UNCOMMITTED_SYM {}
+ | UNICODE_SYM {}
| USE_FRM {}
| VARIABLES {}
+ | VALUE_SYM {}
| WORK_SYM {}
- | YEAR_SYM {};
+ | YEAR_SYM {}
+ | SOUNDS_SYM {}
+ ;
/* Option functions */
@@ -3409,16 +4132,16 @@ option_type:
opt_var_type:
/* empty */ { $$=OPT_SESSION; }
+ | GLOBAL_SYM { $$=OPT_GLOBAL; }
| LOCAL_SYM { $$=OPT_SESSION; }
| SESSION_SYM { $$=OPT_SESSION; }
- | GLOBAL_SYM { $$=OPT_GLOBAL; }
;
opt_var_ident_type:
/* empty */ { $$=OPT_DEFAULT; }
+ | GLOBAL_SYM '.' { $$=OPT_GLOBAL; }
| LOCAL_SYM '.' { $$=OPT_SESSION; }
| SESSION_SYM '.' { $$=OPT_SESSION; }
- | GLOBAL_SYM '.' { $$=OPT_GLOBAL; }
;
option_value:
@@ -3452,9 +4175,9 @@ option_value:
}
| PASSWORD equal text_or_password
{
- THD *thd=current_thd;
+ THD *thd=YYTHD;
LEX_USER *user;
- if (!(user=(LEX_USER*) sql_alloc(sizeof(LEX_USER))))
+ if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
YYABORT;
user->host.str=0;
user->user.str=thd->priv_user;
@@ -3474,7 +4197,7 @@ internal_variable_name:
YYABORT;
$$=tmp;
}
- ;
+ ;
isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
@@ -3491,18 +4214,20 @@ text_or_password:
$$=$3.str;
else
{
- char *buff=(char*) sql_alloc(HASH_PASSWORD_LENGTH+1);
- make_scrambled_password(buff,$3.str);
+ char *buff=(char*) YYTHD->alloc(HASH_PASSWORD_LENGTH+1);
+ make_scrambled_password(buff,$3.str,use_old_passwords,
+ &YYTHD->rand);
$$=buff;
}
- };
+ }
+ ;
set_expr_or_default:
expr { $$=$1; }
| DEFAULT { $$=0; }
- | ON { $$=new Item_string("ON",2); }
- | ALL { $$=new Item_string("ALL",3); }
+ | ON { $$=new Item_string("ON", 2, system_charset_info); }
+ | ALL { $$=new Item_string("ALL", 3, system_charset_info); }
;
@@ -3527,16 +4252,22 @@ table_lock_list:
table_lock:
table_ident opt_table_alias lock_option
- { if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; };
+ {
+ if (!Select->add_table_to_list(YYTHD, $1, $2, 0, (thr_lock_type) $3))
+ YYABORT;
+ }
+ ;
lock_option:
READ_SYM { $$=TL_READ_NO_INSERT; }
- | WRITE_SYM { $$=current_thd->update_lock_default; }
+ | WRITE_SYM { $$=YYTHD->update_lock_default; }
| LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; }
- | READ_SYM LOCAL_SYM { $$= TL_READ; };
+ | READ_SYM LOCAL_SYM { $$= TL_READ; }
+ ;
unlock:
- UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; };
+ UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
+ ;
/*
@@ -3546,14 +4277,16 @@ unlock:
handler:
HANDLER_SYM table_ident OPEN_SYM opt_table_alias
{
- Lex->sql_command = SQLCOM_HA_OPEN;
- if (!add_table_to_list($2,$4,0))
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_HA_OPEN;
+ if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
YYABORT;
}
| HANDLER_SYM table_ident CLOSE_SYM
{
- Lex->sql_command = SQLCOM_HA_CLOSE;
- if (!add_table_to_list($2,0,0))
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_HA_CLOSE;
+ if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
}
| HANDLER_SYM table_ident READ_SYM
@@ -3561,20 +4294,23 @@ handler:
LEX *lex=Lex;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
- lex->select->select_limit= 1;
- lex->select->offset_limit= 0L;
- if (!add_table_to_list($2,0,0))
+ lex->current_select->select_limit= 1;
+ lex->current_select->offset_limit= 0L;
+ if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
}
- handler_read_or_scan where_clause limit_clause { };
+ handler_read_or_scan where_clause opt_limit_clause {}
+ ;
handler_read_or_scan:
handler_scan_function { Lex->backup_dir= 0; }
- | ident handler_rkey_function { Lex->backup_dir= $1.str; };
+ | ident handler_rkey_function { Lex->backup_dir= $1.str; }
+ ;
handler_scan_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
- | NEXT_SYM { Lex->ha_read_mode = RNEXT; };
+ | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
+ ;
handler_rkey_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
@@ -3588,14 +4324,16 @@ handler_rkey_function:
lex->ha_rkey_mode=$1;
if (!(lex->insert_list = new List_item))
YYABORT;
- } '(' values ')' { };
+ } '(' values ')' { }
+ ;
handler_rkey_mode:
EQ { $$=HA_READ_KEY_EXACT; }
| GE { $$=HA_READ_KEY_OR_NEXT; }
| LE { $$=HA_READ_KEY_OR_PREV; }
| GT_SYM { $$=HA_READ_AFTER_KEY; }
- | LT { $$=HA_READ_BEFORE_KEY; };
+ | LT { $$=HA_READ_BEFORE_KEY; }
+ ;
/* GRANT / REVOKE */
@@ -3607,7 +4345,7 @@ revoke:
lex->users_list.empty();
lex->columns.empty();
lex->grant= lex->grant_tot_col=0;
- lex->select->db=0;
+ lex->select_lex.db=0;
lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
bzero((char*) &lex->mqh, sizeof(lex->mqh));
@@ -3624,7 +4362,7 @@ grant:
lex->columns.empty();
lex->sql_command = SQLCOM_GRANT;
lex->grant= lex->grant_tot_col= 0;
- lex->select->db= 0;
+ lex->select_lex.db= 0;
lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
bzero(&(lex->mqh),sizeof(lex->mqh));
@@ -3637,7 +4375,8 @@ grant:
grant_privileges:
grant_privilege_list {}
| ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
- | ALL { Lex->grant = GLOBAL_ACLS;};
+ | ALL { Lex->grant = GLOBAL_ACLS;}
+ ;
grant_privilege_list:
grant_privilege
@@ -3685,7 +4424,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->x509_subject)
{
- net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "SUBJECT");
+ net_printf(lex->thd,ER_DUP_ARGUMENT, "SUBJECT");
YYABORT;
}
lex->x509_subject=$2.str;
@@ -3695,7 +4434,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->x509_issuer)
{
- net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "ISSUER");
+ net_printf(lex->thd,ER_DUP_ARGUMENT, "ISSUER");
YYABORT;
}
lex->x509_issuer=$2.str;
@@ -3705,58 +4444,59 @@ require_list_element:
LEX *lex=Lex;
if (lex->ssl_cipher)
{
- net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "CIPHER");
+ net_printf(lex->thd,ER_DUP_ARGUMENT, "CIPHER");
YYABORT;
}
lex->ssl_cipher=$2.str;
}
;
-
+
opt_table:
'*'
{
- LEX *lex=Lex;
- lex->select->db=lex->thd->db;
+ LEX *lex= Lex;
+ lex->current_select->select_lex()->db= lex->thd->db;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
| ident '.' '*'
{
- LEX *lex=Lex;
- lex->select->db = $1.str;
+ LEX *lex= Lex;
+ lex->current_select->select_lex()->db = $1.str;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
| '*' '.' '*'
{
- LEX *lex=Lex;
- lex->select->db = NULL;
+ LEX *lex= Lex;
+ lex->current_select->select_lex()->db = NULL;
if (lex->grant == GLOBAL_ACLS)
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
| table_ident
{
LEX *lex=Lex;
- if (!add_table_to_list($1,NULL,0))
+ if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,0))
YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL;
- };
+ }
+ ;
user_list:
@@ -3775,10 +4515,11 @@ grant_user:
$$=$1; $1->password=$4;
if ($4.length)
{
- char *buff=(char*) sql_alloc(HASH_PASSWORD_LENGTH+1);
+ char *buff=(char*) YYTHD->alloc(HASH_PASSWORD_LENGTH+1);
if (buff)
{
- make_scrambled_password(buff,$4.str);
+ make_scrambled_password(buff,$4.str,use_old_passwords,
+ &YYTHD->rand);
$1->password.str=buff;
$1->password.length=HASH_PASSWORD_LENGTH;
}
@@ -3787,7 +4528,8 @@ grant_user:
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$=$1; $1->password=$5 ; }
| user
- { $$=$1; $1->password.str=NullS; };
+ { $$=$1; $1->password.str=NullS; }
+ ;
opt_column_list:
@@ -3805,13 +4547,14 @@ column_list:
column_list_id:
ident
{
- String *new_str = new String((const char*) $1.str,$1.length);
+ String *new_str = new String((const char*) $1.str,$1.length,default_charset_info);
List_iterator <LEX_COLUMN> iter(Lex->columns);
class LEX_COLUMN *point;
LEX *lex=Lex;
while ((point=iter++))
{
- if (!my_strcasecmp(point->column.ptr(),new_str->ptr()))
+ if (!my_strcasecmp(system_charset_info,
+ point->column.ptr(), new_str->ptr()))
break;
}
lex->grant_tot_col|= lex->which_columns;
@@ -3819,11 +4562,12 @@ column_list_id:
point->rights |= lex->which_columns;
else
lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
- };
+ }
+ ;
require_clause: /* empty */
- | REQUIRE_SYM require_list
+ | REQUIRE_SYM require_list
{
Lex->ssl_type=SSL_TYPE_SPECIFIED;
}
@@ -3839,7 +4583,7 @@ require_clause: /* empty */
{
Lex->ssl_type=SSL_TYPE_NONE;
}
- ;
+ ;
grant_options:
/* empty */ {}
@@ -3847,7 +4591,8 @@ grant_options:
grant_option_list:
grant_option_list grant_option {}
- | grant_option {};
+ | grant_option {}
+ ;
grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;}
@@ -3865,7 +4610,8 @@ grant_option:
{
Lex->mqh.connections=$2;
Lex->mqh.bits |= 4;
- };
+ }
+ ;
begin:
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work {}
@@ -3873,7 +4619,8 @@ begin:
opt_work:
/* empty */ {}
- | WORK_SYM {;};
+ | WORK_SYM {;}
+ ;
commit:
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
@@ -3883,63 +4630,132 @@ rollback:
/*
-** UNIONS : glue selects together
+ UNIONS : glue selects together
*/
-opt_union:
+union_clause:
/* empty */ {}
- | union_list;
+ | union_list
+ ;
union_list:
- UNION_SYM union_option
+ UNION_SYM union_option
{
LEX *lex=Lex;
if (lex->exchange)
{
/* Only the last SELECT can have INTO...... */
- net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
+ net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "INTO");
YYABORT;
}
- if (lex->select->linkage == NOT_A_SELECT)
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- send_error(&lex->thd->net, ER_SYNTAX_ERROR);
+ send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
}
- if (mysql_new_select(lex))
+ if (mysql_new_select(lex, 0))
YYABORT;
- lex->select->linkage=UNION_TYPE;
- }
+ lex->current_select->linkage=UNION_TYPE;
+ }
select_init {}
;
union_opt:
union_list {}
- | optional_order_or_limit {};
+ | optional_order_or_limit {}
+ ;
optional_order_or_limit:
- /* empty
- intentional reduce/reduce conflict here !!!
- { code } below should not be executed
- when neither ORDER BY nor LIMIT are used */ {}
+ /* Empty */ {}
|
{
- LEX *lex=Lex;
- if (!lex->select->braces)
- {
- send_error(&lex->thd->net, ER_SYNTAX_ERROR);
- YYABORT;
- }
- if (mysql_new_select(lex))
- YYABORT;
- mysql_init_select(lex);
- lex->select->linkage=NOT_A_SELECT;
- lex->select->select_limit=lex->thd->variables.select_limit;
+ THD *thd= YYTHD;
+ LEX *lex= &thd->lex;
+ DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
+ SELECT_LEX *sel= lex->current_select->select_lex();
+ sel->master_unit()->global_parameters=
+ sel->master_unit();
+ lex->current_select= sel->master_unit();
+ lex->current_select->no_table_names_allowed= 1;
+ thd->where= "global ORDER clause";
}
- opt_order_clause limit_clause
+ order_or_limit
+ {
+ THD *thd= YYTHD;
+ thd->lex.current_select->no_table_names_allowed= 0;
+ thd->where= "";
+ }
+ ;
+
+order_or_limit:
+ order_clause opt_limit_clause_init
+ | limit_clause
;
union_option:
/* empty */ {}
- | ALL { Lex->union_option=1; }
- ;
+ | ALL {Select->master_unit()->union_option= 1;};
+
+singlerow_subselect:
+ subselect_start singlerow_subselect_init
+ subselect_end
+ {
+ $$= $2;
+ };
+
+singlerow_subselect_init:
+ select_init2
+ {
+ $$= new Item_singlerow_subselect(YYTHD,
+ Lex->current_select->master_unit()->
+ first_select());
+ };
+
+exists_subselect:
+ subselect_start exists_subselect_init
+ subselect_end
+ {
+ $$= $2;
+ };
+
+exists_subselect_init:
+ select_init2
+ {
+ $$= new Item_exists_subselect(YYTHD,
+ Lex->current_select->master_unit()->
+ first_select());
+ };
+
+in_subselect:
+ subselect_start in_subselect_init
+ subselect_end
+ {
+ $$= $2;
+ };
+
+in_subselect_init:
+ select_init2
+ {
+ $$= Lex->current_select->master_unit()->first_select();
+ };
+
+subselect_start:
+ '(' SELECT_SYM
+ {
+ LEX *lex=Lex;
+ if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN &&
+ lex->sql_command <= (int)SQLCOM_HA_READ) || lex->sql_command == (int)SQLCOM_KILL) {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ if (mysql_new_select(Lex, 1))
+ YYABORT;
+ };
+
+subselect_end:
+ ')'
+ {
+ LEX *lex=Lex;
+ lex->current_select = lex->current_select->outer_select();
+ };
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index f5c0a59b572..762c45e7184 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -38,7 +38,7 @@ void safe_print_str(const char* name, const char* val, int max_len)
}
fprintf(stderr, "= ");
- for(; max_len && PTR_SANE(val) && *val; --max_len)
+ for (; max_len && PTR_SANE(val) && *val; --max_len)
fputc(*val++, stderr);
fputc('\n', stderr);
}
@@ -59,7 +59,7 @@ void safe_print_str(const char* name, const char* val, int max_len)
inline uchar** find_prev_fp(uint32* pc, uchar** fp)
{
int i;
- for(i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
{
uchar* p = (uchar*)pc;
if (p[2] == 222 && p[3] == 35)
@@ -73,7 +73,7 @@ inline uchar** find_prev_fp(uint32* pc, uchar** fp)
inline uint32* find_prev_pc(uint32* pc, uchar** fp)
{
int i;
- for(i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
{
char* p = (char*)pc;
if (p[1] == 0 && p[2] == 94 && p[3] == -73)
diff --git a/sql/structs.h b/sql/structs.h
index be50c8fc24d..59b9335a5c4 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -113,7 +113,8 @@ enum timestamp_type { TIMESTAMP_NONE, TIMESTAMP_DATE, TIMESTAMP_FULL,
TIMESTAMP_TIME };
typedef struct st_time {
- uint year,month,day,hour,minute,second,second_part;
+ uint year,month,day,hour,minute,second;
+ ulong second_part;
bool neg;
timestamp_type time_type;
} TIME;
@@ -148,14 +149,19 @@ enum SHOW_TYPE
};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
+
+extern const char *show_comp_option_name[];
+
typedef int *(*update_var)(THD *, struct show_var_st *);
+
typedef struct show_var_st {
const char *name;
char *value;
SHOW_TYPE type;
} SHOW_VAR;
+
typedef struct lex_string {
char *str;
uint length;
diff --git a/sql/table.cc b/sql/table.cc
index 1635c85eca8..dd5a957f984 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -37,7 +37,27 @@ static byte* get_field_name(Field *buff,uint *length,
return (byte*) buff->field_name;
}
- /* Open a .frm file */
+/*
+ Open a .frm file
+
+ SYNOPSIS
+ openfrm()
+
+ name path to table-file "db/name"
+ alias alias for table
+ db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..)
+ can be 0 (example in ha_example_table)
+ prgflag READ_ALL etc..
+ ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
+ outparam result table
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (see frm_error)
+ 2 Error (see frm_error)
+ 3 Wrong data in .frm file
+ 4 Error (see frm_error)
+*/
int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam)
@@ -49,7 +69,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
interval_count,interval_parts,read_length,db_create_options;
uint key_info_length, com_length;
ulong pos;
- char index_file[FN_REFLEN], *names, *keynames;
+ char index_file[FN_REFLEN], *names, *keynames, *comment_pos;
uchar head[288],*disk_buff,new_field_pack_flag;
my_string record;
const char **int_array;
@@ -117,6 +137,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->raid_type= head[41];
outparam->raid_chunks= head[42];
outparam->raid_chunksize= uint4korr(head+43);
+ if (!(outparam->table_charset=get_charset((uint) head[38],MYF(0))))
+ outparam->table_charset=NULL; // QQ display error message?
null_field_first=1;
}
outparam->db_record_offset=1;
@@ -258,7 +280,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (db_stat & HA_READ_ONLY)
outparam->record[1]=outparam->record[0]; /* purecov: inspected */
}
-
+
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open;
if (crypted)
@@ -279,7 +301,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->comment=strdup_root(&outparam->mem_root,
(char*) head+47);
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length, com_length));
if (!(field_ptr = (Field **)
alloc_root(&outparam->mem_root,
@@ -310,6 +332,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->intervals=0; // For better debugging
memcpy((char*) names, strpos+(outparam->fields*field_pack_length),
(uint) (n_length+int_length));
+ comment_pos=names+(n_length+int_length);
+ memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
fix_type_pointers(&int_array,outparam->intervals,interval_count,
@@ -337,6 +361,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH;
if (use_hash)
use_hash= !hash_init(&outparam->name_hash,
+ system_charset_info,
outparam->fields,0,0,
(hash_get_key) get_field_name,0,
HASH_CASE_INSENSITIVE);
@@ -345,6 +370,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{
uint pack_flag, interval_nr, unireg_type, recpos, field_length;
enum_field_types field_type;
+ CHARSET_INFO *charset=NULL;
+ LEX_STRING comment;
if (new_frm_ver == 3)
{
@@ -354,36 +381,58 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
pack_flag= uint2korr(strpos+8);
unireg_type= (uint) strpos[10];
interval_nr= (uint) strpos[12];
- field_type= (enum_field_types) (uint) strpos[13];
+
+ uint comment_length=uint2korr(strpos+15);
+ field_type=(enum_field_types) (uint) strpos[13];
+ if (!(charset=get_charset((uint) strpos[14], MYF(0))))
+ charset= (outparam->table_charset ? outparam->table_charset:
+ default_charset_info);
+ if (!comment_length)
+ {
+ comment.str= (char*) "";
+ comment.length=0;
+ }
+ else
+ {
+ comment.str= (char*) comment_pos;
+ comment.length= comment_length;
+ comment_pos+= comment_length;
+ }
}
else
{
- /* old frm file */
field_length= (uint) strpos[3];
recpos= uint2korr(strpos+4),
pack_flag= uint2korr(strpos+6);
unireg_type= (uint) strpos[8];
interval_nr= (uint) strpos[10];
+
+ /* old frm file */
field_type= (enum_field_types) f_packtype(pack_flag);
+ charset=(outparam->table_charset ? outparam->table_charset :
+ default_charset_info);
+ bzero((char*) &comment, sizeof(comment));
}
-
*field_ptr=reg_field=
make_field(record+recpos,
(uint32) field_length,
null_pos,null_bit,
pack_flag,
field_type,
+ charset,
(Field::utype) MTYP_TYPENR(unireg_type),
(interval_nr ?
outparam->intervals+interval_nr-1 :
(TYPELIB*) 0),
outparam->fieldnames.type_names[i],
outparam);
- if (!*field_ptr) // Field in 4.1
+ if (!reg_field) // Not supported field type
{
error= 4;
goto err_not_open; /* purecov: inspected */
}
+ reg_field->comment=comment;
+ reg_field->set_charset(charset);
if (!(reg_field->flags & NOT_NULL_FLAG))
{
if ((null_bit<<=1) == 256)
@@ -481,13 +530,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
keyinfo->key_length ? UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
if (i == 0)
field->key_start|= ((key_map) 1 << key);
- if ((index_flags & HA_KEY_READ_ONLY) &&
- field->key_length() == key_part->length &&
+ if (field->key_length() == key_part->length &&
field->type() != FIELD_TYPE_BLOB)
{
- if (field->key_type() != HA_KEYTYPE_TEXT ||
- (!(ha_option & HA_KEY_READ_WRONG_STR) &&
- !(keyinfo->flags & HA_FULLTEXT)))
+ if ((index_flags & HA_KEY_READ_ONLY) &&
+ (field->key_type() != HA_KEYTYPE_TEXT ||
+ (!(ha_option & HA_KEY_READ_WRONG_STR) &&
+ !(keyinfo->flags & HA_FULLTEXT))))
field->part_of_key|= ((key_map) 1 << key);
if ((field->key_type() != HA_KEYTYPE_TEXT ||
!(keyinfo->flags & HA_FULLTEXT)) &&
@@ -977,9 +1026,14 @@ ulong next_io_size(register ulong pos)
} /* next_io_size */
-void append_unescaped(String *res,const char *pos)
+ /* Store in String an SQL quoted string */
+
+void append_unescaped(String *res,const char *pos, uint length)
{
- for (; *pos ; pos++)
+ const char *end= pos+length;
+ res->append('\'');
+
+ for (; pos != end ; pos++)
{
switch (*pos) {
case 0: /* Must be escaped for 'mysql' */
@@ -1007,6 +1061,7 @@ void append_unescaped(String *res,const char *pos)
break;
}
}
+ res->append('\'');
}
/* Create a .frm file */
@@ -1030,7 +1085,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
bzero((char*) fileinfo,64);
- fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+1; // Header
+ fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header
fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
@@ -1046,6 +1101,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
int2store(fileinfo+30,create_info->table_options);
fileinfo[32]=0; // No filename anymore
int4store(fileinfo+34,create_info->avg_row_length);
+ fileinfo[38]= create_info->table_charset?create_info->table_charset->number:0;
fileinfo[40]= (uchar) create_info->row_type;
fileinfo[41]= (uchar) create_info->raid_type;
fileinfo[42]= (uchar) create_info->raid_chunks;
@@ -1076,6 +1132,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
create_info->raid_type=table->raid_type;
create_info->raid_chunks=table->raid_chunks;
create_info->raid_chunksize=table->raid_chunksize;
+ create_info->table_charset=table->table_charset;
DBUG_VOID_RETURN;
}
@@ -1090,15 +1147,22 @@ rename_file_ext(const char * from,const char * to,const char * ext)
/*
- Alloc a value as a string and return it
- If field is empty, return NULL
+ Allocate string field in MEM_ROOT and return it as NULL-terminated string
+
+ SYNOPSIS
+ get_field()
+ mem MEM_ROOT for allocating
+ field Field for retrieving of string
+
+ RETURN VALUES
+ NullS string is empty
+ # pointer to NULL-terminated string value of field
*/
-char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
+char *get_field(MEM_ROOT *mem, Field *field)
{
- Field *field=table->field[fieldnr];
char buff[MAX_FIELD_WIDTH];
- String str(buff,sizeof(buff));
+ String str(buff,sizeof(buff),default_charset_info);
field->val_str(&str,&str);
uint length=str.length();
if (!length)
@@ -1130,14 +1194,15 @@ bool check_db_name(char *name)
char *start=name;
if (lower_case_table_names)
- casedn_str(name);
+ my_casedn_str(files_charset_info, name);
while (*name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(default_charset_info))
+ if (use_mb(system_charset_info))
{
- int len=my_ismbchar(default_charset_info, name, name+MBMAXLEN);
+ int len=my_ismbchar(system_charset_info, name,
+ name+system_charset_info->mbmaxlen);
if (len)
{
name += len;
@@ -1150,7 +1215,7 @@ bool check_db_name(char *name)
return 1;
name++;
}
- return (uint) (name - start) > NAME_LEN;
+ return (uint) (name - start) > NAME_LEN || name == start;
}
@@ -1168,9 +1233,9 @@ bool check_table_name(const char *name, uint length)
while (name != end)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(default_charset_info))
+ if (use_mb(system_charset_info))
{
- int len=my_ismbchar(default_charset_info, name, end);
+ int len=my_ismbchar(system_charset_info, name, end);
if (len)
{
name += len;
@@ -1190,9 +1255,10 @@ bool check_column_name(const char *name)
while (*name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(default_charset_info))
+ if (use_mb(system_charset_info))
{
- int len=my_ismbchar(default_charset_info, name, name+MBMAXLEN);
+ int len=my_ismbchar(system_charset_info, name,
+ name+system_charset_info->mbmaxlen);
if (len)
{
name += len;
diff --git a/sql/table.h b/sql/table.h
index c3f469115b5..1f7df0c6d64 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -19,6 +19,7 @@
class Item; /* Needed by ORDER */
class GRANT_TABLE;
+class st_select_lex_unit;
/* Order clause list element */
@@ -107,6 +108,7 @@ struct st_table {
*rowid_field;
Field_timestamp *timestamp_field;
my_string comment; /* Comment about table */
+ CHARSET_INFO *table_charset; /* Default charset of string fields */
REGINFO reginfo; /* field connections */
MEM_ROOT mem_root;
GRANT_INFO grant;
@@ -118,7 +120,7 @@ struct st_table {
table_map map; /* ID bit of table (1,2,4,8,16...) */
ulong version,flush_version;
uchar *null_flags;
- IO_CACHE *io_cache; /* If sorted trough file*/
+ IO_CACHE *io_cache; /* If sorted trough filebyte */
byte *record_pointers; /* If sorted in memory */
ha_rows found_records; /* How many records in sort */
ORDER *group;
@@ -132,9 +134,11 @@ struct st_table {
uint temp_pool_slot; /* Used by intern temp tables */
struct st_table_list *pos_in_table_list;
};
-
+ /* number of select if it is derived table */
+ uint derived_select_number;
THD *in_use; /* Which thread uses this */
struct st_table *next,*prev;
+ byte *default_values() { return record[2]; }
};
@@ -148,9 +152,18 @@ typedef struct st_table_list
Item *on_expr; /* Used with outer join */
struct st_table_list *natural_join; /* natural join on this table*/
/* ... join ... USE INDEX ... IGNORE INDEX */
- List<String> *use_index,*ignore_index;
- TABLE *table;
- GRANT_INFO grant;
+ List<String> *use_index, *ignore_index;
+ /*
+ Usually hold reference on opened table, but may hold reference
+ to node of complete list of tables used in UNION & subselect.
+ */
+ union
+ {
+ TABLE *table; /* opened table */
+ st_table_list *table_list; /* pointer to node of list of all tables */
+ };
+ class st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
+ GRANT_INFO grant;
thr_lock_type lock_type;
uint outer_join; /* Which join type */
uint shared; /* Used in union or in multi-upd */
@@ -161,7 +174,6 @@ typedef struct st_table_list
bool force_index; /* Prefer index over table scan */
} TABLE_LIST;
-
typedef struct st_changed_table_list
{
struct st_changed_table_list *next;
@@ -169,7 +181,6 @@ typedef struct st_changed_table_list
uint32 key_length;
} CHANGED_TABLE_LIST;
-
typedef struct st_open_table_list
{
struct st_open_table_list *next;
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index 8b9baa6f045..57560715fbe 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -24,7 +24,7 @@ extern "C" {
{
THD *thd=current_thd;
if (thd) // QQ; To be removed
- thd->fatal_error=1; /* purecov: inspected */
+ thd->fatal_error(); /* purecov: inspected */
sql_print_error(ER(ER_OUT_OF_RESOURCES));
}
}
diff --git a/sql/time.cc b/sql/time.cc
index 4fe79966404..6b2f8b710da 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -268,13 +268,13 @@ void find_date(string pos,uint *vek,uint flag)
DBUG_PRINT("enter",("pos: '%s' flag: %d",pos,flag));
bzero((char*) vek,sizeof(int)*4);
- while (*pos && !isdigit(*pos))
+ while (*pos && !my_isdigit(my_charset_latin1,*pos))
pos++;
length=(uint) strlen(pos);
for (uint i=0 ; i< 3; i++)
{
start=pos; value=0;
- while (isdigit(pos[0]) &&
+ while (my_isdigit(my_charset_latin1,pos[0]) &&
((pos-start) < 2 || ((pos-start) < 4 && length >= 8 &&
!(flag & 3))))
{
@@ -282,7 +282,8 @@ void find_date(string pos,uint *vek,uint flag)
pos++;
}
vek[flag & 3]=value; flag>>=2;
- while (*pos && (ispunct(*pos) || isspace(*pos)))
+ while (*pos && (my_ispunct(my_charset_latin1,*pos) ||
+ my_isspace(my_charset_latin1,*pos)))
pos++;
}
DBUG_PRINT("exit",("year: %d month: %d day: %d",vek[0],vek[1],vek[2]));
@@ -417,13 +418,29 @@ ulong convert_month_to_period(ulong month)
}
-/*****************************************************************************
-** convert a timestamp string to a TIME value.
-** At least the following formats are recogniced (based on number of digits)
-** YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS
-** YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS
-** Returns the type of string
-*****************************************************************************/
+/*
+ Convert a timestamp string to a TIME value.
+
+ SYNOPSIS
+ str_to_TIME()
+ str String to parse
+ length Length of string
+ l_time Date is stored here
+ fuzzy_date 1 if we should allow dates where one part is zero
+
+ DESCRIPTION
+ At least the following formats are recogniced (based on number of digits)
+ YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS
+ YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS
+ YYYYMMDDTHHMMSS where T is a the character T (ISO8601)
+ Also dates where all parts are zero are allowed
+
+ RETURN VALUES
+ TIMESTAMP_NONE String wasn't a timestamp, like
+ [DD [HH:[MM:[SS]]]].fraction
+ TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
+ TIMESTAMP_FULL Full timestamp
+*/
timestamp_type
str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
@@ -432,53 +449,66 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
uint not_zero_date;
const char *pos;
const char *end=str+length;
+ bool found_delimitier= 0;
DBUG_ENTER("str_to_TIME");
DBUG_PRINT("enter",("str: %.*s",length,str));
- for (; str != end && !isdigit(*str) ; str++) ; // Skip garbage
+ // Skip garbage
+ for (; str != end && !my_isdigit(&my_charset_latin1, *str) ; str++) ;
if (str == end)
DBUG_RETURN(TIMESTAMP_NONE);
/*
- ** calculate first number of digits.
- ** If length= 8 or >= 14 then year is of format YYYY.
- (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
+ Calculate first number of digits.
+ If length= 8 or >= 14 then year is of format YYYY.
+ (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
*/
- for (pos=str; pos != end && isdigit(*pos) ; pos++) ;
+ for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++) ;
digits= (uint) (pos-str);
year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
field_length=year_length-1;
not_zero_date= 0;
- for (i=0 ; i < 6 && str != end && isdigit(*str) ; i++)
+ for (i=0 ; i < 6 && str != end && my_isdigit(&my_charset_latin1,*str) ; i++)
{
uint tmp_value=(uint) (uchar) (*str++ - '0');
- while (str != end && isdigit(str[0]) && field_length--)
+ while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
+ field_length--)
{
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
str++;
}
+ if (found_delimitier && (int) field_length < 0)
+ {
+ /* The number can't match any valid date or datetime string */
+ DBUG_RETURN(TIMESTAMP_NONE);
+ }
date[i]=tmp_value;
not_zero_date|= tmp_value;
if (i == 2 && str != end && *str == 'T')
str++; // ISO8601: CCYYMMDDThhmmss
else if ( i != 5 ) // Skip inter-field delimiters
{
- while (str != end && (ispunct(*str) || isspace(*str)))
+ while (str != end &&
+ (my_ispunct(&my_charset_latin1,*str) ||
+ my_isspace(&my_charset_latin1,*str)))
{
// Only allow space between days and hours
- if (isspace(*str) && i != 2)
+ if (my_isspace(&my_charset_latin1,*str) && i != 2)
DBUG_RETURN(TIMESTAMP_NONE);
str++;
+ found_delimitier=1; // Should be a 'normal' date
}
}
field_length=1; // Rest fields can only be 2
}
/* Handle second fractions */
- if (i == 6 && (uint) (end-str) >= 2 && *str == '.' && isdigit(str[1]))
+ if (i == 6 && (uint) (end-str) >= 2 && *str == '.' &&
+ my_isdigit(&my_charset_latin1,str[1]))
{
str++;
uint tmp_value=(uint) (uchar) (*str - '0');
- field_length=3;
- while (str++ != end && isdigit(str[0]) && field_length--)
+ field_length=5;
+ while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) &&
+ field_length--)
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
date[6]=tmp_value;
not_zero_date|= tmp_value;
@@ -500,7 +530,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
{
for (; str != end ; str++)
{
- if (!isspace(*str))
+ if (!my_isspace(&my_charset_latin1, *str))
{
not_zero_date= 1; // Give warning
break;
@@ -515,7 +545,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
{
for (; str != end ; str++)
{
- if (!isspace(*str))
+ if (!my_isspace(&my_charset_latin1,*str))
{
current_thd->cuted_fields++;
break;
@@ -561,12 +591,22 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date)
}
-/*****************************************************************************
-** convert a time string to a (ulong) value.
-** Can use all full timestamp formats and
-** [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, [M]MSS or [S]S
-** There may be an optional [.second_part] after seconds
-*****************************************************************************/
+/*
+ Convert a time string to a TIME struct.
+
+ SYNOPSIS
+ str_to_time()
+ str A string in full TIMESTAMP format or
+ [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS,
+ [M]MSS or [S]S
+ There may be an optional [.second_part] after seconds
+ length Length of str
+ l_time Store result here
+
+ RETURN
+ 0 ok
+ 1 error
+*/
bool str_to_time(const char *str,uint length,TIME *l_time)
{
@@ -576,7 +616,8 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
uint state;
l_time->neg=0;
- for (; str != end && !isdigit(*str) && *str != '-' ; str++)
+ for (; str != end &&
+ !my_isdigit(&my_charset_latin1,*str) && *str != '-' ; str++)
length--;
if (str != end && *str == '-')
{
@@ -595,7 +636,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
}
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
- for (value=0; str != end && isdigit(*str) ; str++)
+ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
value=value*10L + (long) (*str - '0');
if (*str == ' ')
@@ -606,14 +647,16 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
LINT_INIT(state);
found_days=found_hours=0;
- if ((uint) (end-str) > 1 && (*str == ' ' && isdigit(str[1])))
+ if ((uint) (end-str) > 1 && (*str == ' ' &&
+ my_isdigit(&my_charset_latin1,str[1])))
{ // days !
date[0]=value;
state=1; // Assume next is hours
found_days=1;
str++; // Skip space;
}
- else if ((end-str) > 1 && *str == ':' && isdigit(str[1]))
+ else if ((end-str) > 1 && *str == ':' &&
+ my_isdigit(&my_charset_latin1,str[1]))
{
date[0]=0; // Assume we found hours
date[1]=value;
@@ -635,10 +678,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
/* Read hours, minutes and seconds */
for (;;)
{
- for (value=0; str != end && isdigit(*str) ; str++)
+ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
value=value*10L + (long) (*str - '0');
date[state++]=value;
- if (state == 4 || (end-str) < 2 || *str != ':' || !isdigit(str[1]))
+ if (state == 4 || (end-str) < 2 || *str != ':' ||
+ !my_isdigit(&my_charset_latin1,str[1]))
break;
str++; // Skip ':'
}
@@ -658,11 +702,13 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
fractional:
/* Get fractional second part */
- if ((end-str) >= 2 && *str == '.' && isdigit(str[1]))
+ if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
{
uint field_length=3;
str++; value=(uint) (uchar) (*str - '0');
- while (++str != end && isdigit(str[0]) && field_length--)
+ while (++str != end &&
+ my_isdigit(&my_charset_latin1,str[0]) &&
+ field_length--)
value=value*10 + (uint) (uchar) (*str - '0');
date[4]=value;
}
@@ -687,7 +733,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
{
do
{
- if (!isspace(*str))
+ if (!my_isspace(&my_charset_latin1,*str))
{
current_thd->cuted_fields++;
break;
@@ -696,3 +742,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
}
return 0;
}
+
+
+/*
+ Convert a system time structure to TIME
+*/
+
+void localtime_to_TIME(TIME *to, struct tm *from)
+{
+ to->neg=0;
+ to->second_part=0;
+ to->year= (int) ((from->tm_year+1900) % 10000);
+ to->month= (int) from->tm_mon+1;
+ to->day= (int) from->tm_mday;
+ to->hour= (int) from->tm_hour;
+ to->minute= (int) from->tm_min;
+ to->second= (int) from->tm_sec;
+}
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index 176ddeb10a3..dfe8177bfce 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -126,6 +126,8 @@ typedef long long longlong;
#include <m_ctype.h>
#include <m_string.h> // To get strmov()
+static pthread_mutex_t LOCK_hostname;
+
#ifdef HAVE_DLOPEN
/* These must be right or mysqld will not find the symbol! */
@@ -282,8 +284,8 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
for (n = ntrans + 1, n_end = ntrans + sizeof(ntrans)-2;
word != w_end && n < n_end; word++ )
- if ( isalpha ( *word ))
- *n++ = toupper ( *word );
+ if ( my_isalpha ( my_charset_latin1, *word ))
+ *n++ = my_toupper ( my_charset_latin1, *word );
if ( n == ntrans + 1 ) /* return empty string if 0 bytes */
{
@@ -583,6 +585,8 @@ longlong myfunc_int(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
case REAL_RESULT: // Add numers as longlong
val += (longlong) *((double*) args->args[i]);
break;
+ default:
+ break;
}
}
return val;
@@ -642,8 +646,6 @@ longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
**
****************************************************************************/
-#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
-
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -651,9 +653,11 @@ longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
extern "C" {
my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
+void lookup_deinit(UDF_INIT *initid);
char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *null_value, char *error);
my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
+void reverse_lookup_deinit(UDF_INIT *initid);
char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *null_value, char *error);
}
@@ -676,9 +680,19 @@ my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
}
initid->max_length=11;
initid->maybe_null=1;
+#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
+ (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW);
+#endif
return 0;
}
+void lookup_deinit(UDF_INIT *initid)
+{
+#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
+ (void) pthread_mutex_destroy(&LOCK_hostname);
+#endif
+}
+
char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *null_value, char *error)
{
@@ -696,13 +710,23 @@ char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
length=sizeof(name_buff)-1;
memcpy(name_buff,args->args[0],length);
name_buff[length]=0;
-
+#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
if (!(hostent=gethostbyname_r(name_buff,&tmp_hostent,hostname_buff,
sizeof(hostname_buff), &tmp_errno)))
{
*null_value=1;
return 0;
}
+#else
+ VOID(pthread_mutex_lock(&LOCK_hostname));
+ if (!(hostent= gethostbyname((char*) name_buff)))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_hostname));
+ *null_value= 1;
+ return 0;
+ }
+ VOID(pthread_mutex_unlock(&LOCK_hostname));
+#endif
struct in_addr in;
memcpy_fixed((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr));
*res_length= (ulong) (strmov(result, inet_ntoa(in)) - result);
@@ -731,9 +755,18 @@ my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
}
initid->max_length=32;
initid->maybe_null=1;
+#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
+ (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW);
+#endif
return 0;
}
+void reverse_lookup_deinit(UDF_INIT *initid)
+{
+#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
+ (void) pthread_mutex_destroy(&LOCK_hostname);
+#endif
+}
char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *null_value, char *error)
@@ -776,6 +809,7 @@ char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
return 0;
}
struct hostent *hp;
+#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
int tmp_errno;
if (!(hp=gethostbyaddr_r((char*) &taddr,sizeof(taddr), AF_INET,
&tmp_hostent, name_buff,sizeof(name_buff),
@@ -784,10 +818,19 @@ char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
*null_value=1;
return 0;
}
+#else
+ VOID(pthread_mutex_lock(&LOCK_hostname));
+ if (!(hp= gethostbyaddr((char*) &taddr, sizeof(taddr), AF_INET)))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_hostname));
+ *null_value= 1;
+ return 0;
+ }
+ VOID(pthread_mutex_unlock(&LOCK_hostname));
+#endif
*res_length=(ulong) (strmov(result,hp->h_name) - result);
return result;
}
-#endif // defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
/*
** Syntax for the new aggregate commands are:
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 5183f471fa2..1cd38d4d161 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -28,7 +28,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
-#define FCOMP 11 /* Byte per packat f{lt */
+#define FCOMP 17 /* Bytes for a packed field */
static uchar * pack_screens(List<create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
@@ -46,7 +46,7 @@ static bool make_empty_rec(int file, enum db_type table_type,
uint reclength,uint null_fields);
-int rea_create_table(my_string file_name,
+int rea_create_table(THD *thd, my_string file_name,
HA_CREATE_INFO *create_info,
List<create_field> &create_fields,
uint keys, KEY *key_info)
@@ -67,13 +67,12 @@ int rea_create_table(my_string file_name,
if (pack_header(forminfo, create_info->db_type,create_fields,info_length,
screens, create_info->table_options, db_file))
{
- NET *net=my_pthread_getspecific_ptr(NET*,THR_NET);
my_free((gptr) screen_buff,MYF(0));
- if (net->last_errno != ER_TOO_MANY_FIELDS)
+ if (thd->net.last_errno != ER_TOO_MANY_FIELDS)
DBUG_RETURN(1);
// Try again without UNIREG screens (to get more columns)
- net->last_error[0]=0;
+ thd->net.last_error[0]=0;
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
DBUG_RETURN(1);
if (pack_header(forminfo, create_info->db_type, create_fields,info_length,
@@ -246,7 +245,7 @@ static uchar * pack_screens(List<create_field> &create_fields,
static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
{
uint key_parts,length;
- uchar *pos, *keyname_pos, *key_alg_pos;
+ uchar *pos, *keyname_pos;
KEY *key,*end;
KEY_PART_INFO *key_part,*key_part_end;
DBUG_ENTER("pack_keys");
@@ -255,10 +254,12 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
key_parts=0;
for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
{
- pos[0]=(uchar) (key->flags ^ HA_NOSAME);
- int2store(pos+1,key->key_length);
- pos[3]=key->key_parts;
- pos+=4;
+ int2store(pos, (key->flags ^ HA_NOSAME));
+ int2store(pos+2,key->key_length);
+ pos[4]= (uchar) key->key_parts;
+ pos[5]= (uchar) key->algorithm;
+ pos[6]=pos[7]=0; // For the future
+ pos+=8;
key_parts+=key->key_parts;
DBUG_PRINT("loop",("flags: %d key_parts: %d at %lx",
key->flags,key->key_parts,
@@ -290,18 +291,11 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
}
*(pos++)=0;
- /* For MySQL 4.0; Store key algoritms last */
- key_alg_pos= pos;
- for (key=keyinfo ; key != end ; key++)
- {
- *(pos++)= (uchar) key->algorithm;
- }
-
keybuff[0]=(uchar) key_count;
keybuff[1]=(uchar) key_parts;
length=(uint) (keyname_pos-keybuff);
int2store(keybuff+2,length);
- length=(uint) (key_alg_pos-keyname_pos);
+ length=(uint) (pos-keyname_pos);
int2store(keybuff+4,length);
DBUG_RETURN((uint) (pos-keybuff));
} /* pack_keys */
@@ -314,9 +308,9 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
uint info_length, uint screens,uint table_options,
handler *file)
{
- uint length,int_count,int_length,no_empty, int_parts,
- time_stamp_pos,null_fields;
- ulong reclength,totlength,n_length;
+ uint length,int_count,int_length,no_empty, int_parts;
+ uint time_stamp_pos,null_fields;
+ ulong reclength, totlength, n_length, com_length;
DBUG_ENTER("pack_header");
if (create_fields.elements > MAX_FIELDS)
@@ -326,7 +320,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
}
totlength=reclength=0L;
- no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
+ no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
+ com_length=0;
n_length=2L;
/* Check fields */
@@ -336,6 +331,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
while ((field=it++))
{
totlength+= field->length;
+ com_length+= field->comment.length;
if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
field->unireg_check & MTYP_NOEMPTY_BIT)
{
@@ -378,14 +374,15 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
/* Hack to avoid bugs with small static rows in MySQL */
reclength=max(file->min_record_length(table_options),reclength);
if (info_length+(ulong) create_fields.elements*FCOMP+288+
- n_length+int_length > 65535L || int_count > 255)
+ n_length+int_length+com_length > 65535L || int_count > 255)
{
my_error(ER_TOO_MANY_FIELDS,MYF(0));
DBUG_RETURN(1);
}
bzero((char*)forminfo,288);
- length=info_length+create_fields.elements*FCOMP+288+n_length+int_length;
+ length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
+ com_length);
int2store(forminfo,length);
forminfo[256] = (uint8) screens;
int2store(forminfo+258,create_fields.elements);
@@ -401,6 +398,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
int2store(forminfo+278,80); /* Columns needed */
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
+ int2store(forminfo+284,com_length);
DBUG_RETURN(0);
} /* pack_header */
@@ -438,7 +436,7 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
static bool pack_fields(File file,List<create_field> &create_fields)
{
reg2 uint i;
- uint int_count;
+ uint int_count, comment_length=0;
uchar buff[MAX_FIELD_WIDTH];
create_field *field;
DBUG_ENTER("pack_fields");
@@ -453,12 +451,16 @@ static bool pack_fields(File file,List<create_field> &create_fields)
buff[0]= (uchar) field->row;
buff[1]= (uchar) field->col;
buff[2]= (uchar) field->sc_length;
- buff[3]= (uchar) field->length;
+ int2store(buff+3, field->length);
uint recpos=(uint) field->offset+1;
- int2store(buff+4,recpos);
- int2store(buff+6,field->pack_flag);
- int2store(buff+8,field->unireg_check);
- buff[10]= (uchar) field->interval_id;
+ int3store(buff+5,recpos);
+ int2store(buff+8,field->pack_flag);
+ int2store(buff+10,field->unireg_check);
+ buff[12]= (uchar) field->interval_id;
+ buff[13]= (uchar) field->sql_type;
+ buff[14]= (uchar) field->charset->number;
+ int2store(buff+15, field->comment.length);
+ comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
if (my_write(file,(byte*) buff,FCOMP,MYF_RW))
DBUG_RETURN(1);
@@ -484,7 +486,7 @@ static bool pack_fields(File file,List<create_field> &create_fields)
/* Write intervals */
if (int_count)
{
- String tmp((char*) buff,sizeof(buff));
+ String tmp((char*) buff,sizeof(buff), default_charset_info);
tmp.length(0);
it.rewind();
int_count=0;
@@ -505,6 +507,18 @@ static bool pack_fields(File file,List<create_field> &create_fields)
if (my_write(file,(byte*) tmp.ptr(),tmp.length(),MYF_RW))
DBUG_RETURN(1);
}
+ if (comment_length)
+ {
+ it.rewind();
+ int_count=0;
+ while ((field=it++))
+ {
+ if (field->comment.length)
+ if (my_write(file, (byte*) field->comment.str, field->comment.length,
+ MYF_RW))
+ DBUG_RETURN(1);
+ }
+ }
DBUG_RETURN(0);
}
@@ -558,10 +572,12 @@ static bool make_empty_rec(File file,enum db_type table_type,
1 << (null_count & 7),
field->pack_flag,
field->sql_type,
+ field->charset,
field->unireg_check,
field->interval,
field->field_name,
&table);
+
if (!(field->flags & NOT_NULL_FLAG))
null_count++;
@@ -574,7 +590,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
if (field->def &&
(regfield->real_type() != FIELD_TYPE_YEAR ||
field->def->val_int() != 0))
- field->def->save_in_field(regfield, 1);
+ (void) field->def->save_in_field(regfield, 1);
else if (regfield->real_type() == FIELD_TYPE_ENUM &&
(field->flags & NOT_NULL_FLAG))
{
@@ -582,9 +598,9 @@ static bool make_empty_rec(File file,enum db_type table_type,
regfield->store((longlong) 1);
}
else if (type == Field::YES) // Old unireg type
- regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)));
+ regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)),default_charset_info);
else if (type == Field::NO) // Old unireg type
- regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)));
+ regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),default_charset_info);
else
regfield->reset();
delete regfield;
diff --git a/sql/unireg.h b/sql/unireg.h
index eec89fcee0f..2dc84720b2d 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -63,6 +63,8 @@
#define MAX_SORT_MEMORY (2048*1024-MALLOC_OVERHEAD)
#define MIN_SORT_MEMORY (32*1024-MALLOC_OVERHEAD)
+#define DEFAULT_ERROR_COUNT 64
+#define DEFAULT_PREP_STMT_COUNT 64
#define EXTRA_RECORDS 10 /* Extra records in sort */
#define SCROLL_EXTRA 5 /* Extra scroll-rows. */
#define FIELD_NAME_USED ((uint) 32768) /* Bit set if fieldname used */
@@ -134,6 +136,8 @@ bfill((A)->null_flags,(A)->null_bytes,255);\
#define BIN_LOG_HEADER_SIZE 4
+#define FLOATING_POINT_BUFFER 331
+
/* Include prototypes for unireg */
#include "mysqld_error.h"
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 89b5d8c03e9..ee1ce59d0d1 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -16,25 +16,25 @@
# This file is public domain and comes with NO WARRANTY of any kind
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
pkglib_LIBRARIES = libmystrings.a
# Exact one of ASSEMBLER_X
if ASSEMBLER_x86
ASRCS = strings-x86.s longlong2str-x86.s
-CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c ctype.c strnlen.c
+CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c
else
if ASSEMBLER_sparc32
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s
-CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c ctype.c strnlen.c strxmov.c
+CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c
else
#no assembler
ASRCS =
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
-CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c ctype.c strnlen.c
+CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c
endif
endif
@@ -42,10 +42,10 @@ libmystrings_a_SOURCES = $(ASRCS) $(CSRCS)
noinst_PROGRAMS = conf_to_src
DISTCLEANFILES = ctype_autoconf.c
# Default charset definitions
-EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c \
- ctype-gb2312.c ctype-gbk.c ctype-sjis.c \
+EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-win1250ch.c \
+ ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \
ctype-tis620.c ctype-ujis.c ctype-latin1_de.c \
- strto.c strings-x86.s \
+ xml.c strto.c strings-x86.s \
longlong2str.c longlong2str-x86.s \
strxmov.c bmove_upp.c strappend.c strcont.c strend.c \
strfill.c strcend.c is_prefix.c strstr.c strinstr.c \
@@ -55,23 +55,16 @@ EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c \
strnmov-sparc.s strstr-sparc.s strxmov-sparc.s \
t_ctype.h
-libmystrings_a_LIBADD= @CHARSET_OBJS@
-ctype.o: ctype_extra_sources.c
-
-ctype_extra_sources.c: conf_to_src
- ./conf_to_src $(top_srcdir) @CHARSETS_NEED_SOURCE@ > \
- $(srcdir)/ctype_extra_sources.c
-conf_to_src_SOURCES = conf_to_src.c
+libmystrings_a_LIBADD=
+conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c
conf_to_src_LDADD=
#force static linking of conf_to_src - essential when linking against
#custom installation of libc
conf_to_src_LDFLAGS= @NOINST_LDFLAGS@
# This is because the dependency tracking misses @FOO@ vars in sources.
-strtoull.o: @CHARSET_OBJS@
+#strtoull.o: @CHARSET_OBJS@
-clean-local:
- rm -f ctype_extra_sources.c
if ASSEMBLER
# On Linux gcc can compile the assembly files
diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c
index 22e04337b14..69dccbca0a7 100644
--- a/strings/conf_to_src.c
+++ b/strings/conf_to_src.c
@@ -14,129 +14,293 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* can't use -lmysys because this prog is used to create -lstrings */
-
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
-#define CHARSETS_SUBDIR "sql/share/charsets"
-#define CTYPE_TABLE_SIZE 257
-#define TO_LOWER_TABLE_SIZE 256
-#define TO_UPPER_TABLE_SIZE 256
-#define SORT_ORDER_TABLE_SIZE 256
-#define ROW_LEN 16
+#include <my_global.h>
+#include <m_ctype.h>
+#include <my_xml.h>
-void print_arrays_for(char *set);
-char *prog;
-char buf[1024], *p, *endptr;
+#define ROW_LEN 16
+#define ROW16_LEN 8
+#define MAX_BUF 16*1024
-int
-main(int argc, char **argv)
+static CHARSET_INFO all_charsets[256];
+
+
+void
+print_array(FILE *f, const char *set, const char *name, uchar *a, int n)
{
- prog = *argv;
+ int i;
- if (argc < 2) {
- fprintf(stderr, "usage: %s source-dir [charset [, charset]]\n", prog);
- exit(EXIT_FAILURE);
+ fprintf(f,"uchar %s_%s[] = {\n", name, set);
+
+ for (i=0 ;i<n ; i++)
+ {
+ fprintf(f,"0x%02X",a[i]);
+ fprintf(f, (i+1<n) ? "," :"" );
+ fprintf(f, ((i+1) % ROW_LEN == n % ROW_LEN) ? "\n" : "" );
}
+ fprintf(f,"};\n\n");
+}
- --argc; ++argv; /* skip program name */
- if (chdir(*argv) != 0) {
- fprintf(stderr, "%s: can't cd to %s\n", prog, *argv);
- exit(EXIT_FAILURE);
- }
- --argc; ++argv;
+void
+print_array16(FILE *f, const char *set, const char *name, uint16 *a, int n)
+{
+ int i;
- if (chdir(CHARSETS_SUBDIR) != 0) {
- fprintf(stderr, "%s: can't cd to %s\n", prog, CHARSETS_SUBDIR);
- exit(EXIT_FAILURE);
+ fprintf(f,"uchar %s_%s[] = {\n", name, set);
+
+ for (i=0 ;i<n ; i++)
+ {
+ fprintf(f,"0x%04X",a[i]);
+ fprintf(f, (i+1<n) ? "," :"" );
+ fprintf(f, ((i+1) % ROW16_LEN == n % ROW16_LEN) ? "\n" : "" );
}
+ fprintf(f,"};\n\n");
+}
- while (argc--)
- print_arrays_for(*argv++);
- exit(EXIT_SUCCESS);
+static int get_charset_number(const char *charset_name)
+{
+ CHARSET_INFO *cs;
+ for (cs= all_charsets; cs < all_charsets+255; ++cs)
+ {
+ if ( cs->name && !strcmp(cs->name, charset_name))
+ return cs->number;
+ }
+ return 0;
}
-void
-print_array(FILE *f, const char *set, const char *name, int n)
+char *mdup(const char *src, uint len)
{
- int i;
- char val[100];
+ char *dst=(char*)malloc(len);
+ memcpy(dst,src,len);
+ return dst;
+}
- printf("uchar %s_%s[] = {\n", name, set);
+static void simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
+{
+ to->number= from->number ? from->number : to->number;
+ to->state|= from->state;
+
+ if (from->csname)
+ to->csname= strdup(from->csname);
+
+ if (from->name)
+ to->name= strdup(from->name);
+
+ if (from->ctype)
+ to->ctype= (uchar*) mdup((char*) from->ctype, MY_CS_CTYPE_TABLE_SIZE);
+ if (from->to_lower)
+ to->to_lower= (uchar*) mdup((char*) from->to_lower, MY_CS_TO_LOWER_TABLE_SIZE);
+ if (from->to_upper)
+ to->to_upper= (uchar*) mdup((char*) from->to_upper, MY_CS_TO_UPPER_TABLE_SIZE);
+ if (from->sort_order)
+ {
+ to->sort_order= (uchar*) mdup((char*) from->sort_order, MY_CS_SORT_ORDER_TABLE_SIZE);
+ /*
+ set_max_sort_char(to);
+ */
+ }
+ if (from->tab_to_uni)
+ {
+ uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16);
+ to->tab_to_uni= (uint16*) mdup((char*)from->tab_to_uni, sz);
+ /*
+ create_fromuni(to);
+ */
+ }
+}
+
+static my_bool simple_cs_is_full(CHARSET_INFO *cs)
+{
+ return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper &&
+ cs->to_lower) &&
+ (cs->number && cs->name && cs->sort_order));
+}
- p = buf;
- *buf = '\0';
- for (i = 0; i < n; ++i)
+static int add_collation(CHARSET_INFO *cs)
+{
+ if (cs->name && (cs->number || (cs->number=get_charset_number(cs->name))))
{
- /* get a word from f */
- endptr = p;
- for (;;)
+ if (!(all_charsets[cs->number].state & MY_CS_COMPILED))
{
- while (isspace((* (unsigned char*) endptr)))
- ++endptr;
- if (*endptr && *endptr != '#') /* not comment */
- break;
- if ((fgets(buf, sizeof(buf), f)) == NULL)
- return; /* XXX: break silently */
- endptr = buf;
+ simple_cs_copy_data(&all_charsets[cs->number],cs);
+
}
+
+ cs->number= 0;
+ cs->name= NULL;
+ cs->state= 0;
+ cs->sort_order= NULL;
+ cs->state= 0;
+ }
+ return MY_XML_OK;
+}
- p = val;
- while (!isspace((* (unsigned char*) endptr)))
- *p++ = *endptr++;
- *p = '\0';
- p = endptr;
-
- /* write the value out */
-
- if (i == 0 || i % ROW_LEN == n % ROW_LEN)
- printf(" ");
-
- printf("%3d", (unsigned char) strtol(val, (char **) NULL, 16));
-
- if (i < n - 1)
- printf(",");
- if ((i+1) % ROW_LEN == n % ROW_LEN)
- printf("\n");
+static int my_read_charset_file(const char *filename)
+{
+ char buf[MAX_BUF];
+ int fd;
+ uint len;
+
+ if ((fd=open(filename,O_RDONLY)) < 0)
+ {
+ fprintf(stderr,"Can't open '%s'\n",filename);
+ return 1;
}
-
- printf("};\n\n");
+
+ len=read(fd,buf,MAX_BUF);
+ close(fd);
+
+ if (my_parse_charset_xml(buf,len,add_collation))
+ {
+#if 0
+ printf("ERROR at line %d pos %d '%s'\n",
+ my_xml_error_lineno(&p)+1,
+ my_xml_error_pos(&p),
+ my_xml_error_string(&p));
+#endif
+ }
+
+ return FALSE;
}
-void
-print_arrays_for(char *set)
+void dispcset(FILE *f,CHARSET_INFO *cs)
{
- FILE *f;
+ fprintf(f,"{\n");
+ fprintf(f," %d,\n",cs->number);
+ fprintf(f," MY_CS_COMPILED,\n");
+
+ if (cs->name)
+ {
+ fprintf(f," \"%s\",\n",cs->name);
+ fprintf(f," \"%s\",\n",cs->csname);
+ fprintf(f," \"\",\n");
+ fprintf(f," ctype_%s,\n",cs->name);
+ fprintf(f," to_lower_%s,\n",cs->name);
+ fprintf(f," to_upper_%s,\n",cs->name);
+ fprintf(f," sort_order_%s,\n",cs->name);
+ fprintf(f," to_uni_%s,\n",cs->name);
+ fprintf(f," from_uni_%s,\n",cs->name);
+ }
+ else
+ {
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ }
+
+ fprintf(f," %d,\n",cs->strxfrm_multiply);
+ fprintf(f," my_strnncoll_simple,\n");
+ fprintf(f," my_strnxfrm_simple,\n");
+ fprintf(f," my_like_range_simple,\n");
+ fprintf(f," my_wild_cmp_8bit,\n");
+ fprintf(f," %d,\n",cs->mbmaxlen);
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," NULL,\n");
+ fprintf(f," my_mb_wc_8bit,\n");
+ fprintf(f," my_wc_mb_8bit,\n");
+ fprintf(f," my_caseup_str_8bit,\n");
+ fprintf(f," my_casedn_str_8bit,\n");
+ fprintf(f," my_caseup_8bit,\n");
+ fprintf(f," my_casedn_8bit,\n");
+ fprintf(f," my_tosort_8bit,\n");
+ fprintf(f," my_strcasecmp_8bit,\n");
+ fprintf(f," my_strncasecmp_8bit,\n");
+ fprintf(f," my_hash_caseup_simple,\n");
+ fprintf(f," my_hash_sort_simple,\n");
+ fprintf(f," 0,\n");
+ fprintf(f," my_snprintf_8bit,\n");
+ fprintf(f," my_long10_to_str_8bit,\n");
+ fprintf(f," my_longlong10_to_str_8bit,\n");
+ fprintf(f," my_fill_8bit,\n");
+ fprintf(f," my_strntol_8bit,\n");
+ fprintf(f," my_strntoul_8bit,\n");
+ fprintf(f," my_strntoll_8bit,\n");
+ fprintf(f," my_strntoull_8bit,\n");
+ fprintf(f," my_strntod_8bit,\n");
+ fprintf(f," my_scan_8bit\n");
+ fprintf(f,"}\n");
+}
- sprintf(buf, "%s.conf", set);
- if ((f = fopen(buf, "r")) == NULL) {
- fprintf(stderr, "%s: can't read conf file for charset %s\n", prog, set);
+int
+main(int argc, char **argv __attribute__((unused)))
+{
+ CHARSET_INFO ncs;
+ CHARSET_INFO *cs;
+ char filename[256];
+ FILE *f= stdout;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "usage: %s source-dir\n", argv[0]);
exit(EXIT_FAILURE);
}
-
- printf("\
-/* The %s character set. Generated automatically by configure and\n\
- * the %s program\n\
- */\n\n",
- set, prog);
-
- /* it would be nice if this used the code in mysys/charset.c, but... */
- print_array(f, set, "ctype", CTYPE_TABLE_SIZE);
- print_array(f, set, "to_lower", TO_LOWER_TABLE_SIZE);
- print_array(f, set, "to_upper", TO_UPPER_TABLE_SIZE);
- print_array(f, set, "sort_order", SORT_ORDER_TABLE_SIZE);
- printf("\n");
-
- fclose(f);
-
- return;
+
+ bzero((void*)&ncs,sizeof(ncs));
+ bzero((void*)&all_charsets,sizeof(all_charsets));
+
+ sprintf(filename,"%s/%s",argv[1],"Index.xml");
+ my_read_charset_file(filename);
+
+ for (cs=all_charsets; cs < all_charsets+256; cs++)
+ {
+ if (cs->number)
+ {
+ if ( (!simple_cs_is_full(cs)) && (cs->csname) )
+ {
+ sprintf(filename,"%s/%s.xml",argv[1],cs->csname);
+ my_read_charset_file(filename);
+ }
+ }
+ }
+
+ for (cs=all_charsets; cs < all_charsets+256; cs++)
+ {
+ if (simple_cs_is_full(cs))
+ {
+ fprintf(f,"#ifdef HAVE_CHARSET_%s\n",cs->csname);
+ print_array(f, cs->name, "ctype", cs->ctype, MY_CS_CTYPE_TABLE_SIZE);
+ print_array(f, cs->name, "to_lower", cs->to_lower, MY_CS_TO_LOWER_TABLE_SIZE);
+ print_array(f, cs->name, "to_upper", cs->to_upper, MY_CS_TO_UPPER_TABLE_SIZE);
+ print_array(f, cs->name, "sort_order", cs->sort_order, MY_CS_SORT_ORDER_TABLE_SIZE);
+ print_array16(f, cs->name, "to_uni", cs->tab_to_uni, MY_CS_TO_UNI_TABLE_SIZE);
+ fprintf(f,"#endif\n");
+ fprintf(f,"\n");
+ }
+ }
+
+ fprintf(f,"CHARSET_INFO compiled_charsets[] = {\n");
+ for (cs=all_charsets; cs < all_charsets+256; cs++)
+ {
+ if (simple_cs_is_full(cs))
+ {
+ fprintf(f,"#ifdef HAVE_CHARSET_%s\n",cs->csname);
+ dispcset(f,cs);
+ fprintf(f,",\n");
+ fprintf(f,"#endif\n");
+ }
+ }
+
+ dispcset(f,&ncs);
+ fprintf(f,"};\n");
+
+ return 0;
}
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 44f8a100897..7827b8714ec 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -31,8 +31,13 @@
#include "m_string.h"
#include "m_ctype.h"
-/* Support for Chinese(BIG5) characters, by jou@nematic.ieo.nctu.edu.tw
- modified by Wei He (hewei@mail.ied.ac.cn) */
+#ifdef HAVE_CHARSET_big5
+
+/*
+ Support for Chinese(BIG5) characters, by jou@nematic.ieo.nctu.edu.tw
+ modified by Wei He (hewei@mail.ied.ac.cn)
+ modified by Alex Barkov <bar@udm.net>
+*/
#define isbig5head(c) (0xa1<=(uchar)(c) && (uchar)(c)<=0xf9)
#define isbig5tail(c) ((0x40<=(uchar)(c) && (uchar)(c)<=0x7e) || \
@@ -43,7 +48,7 @@
#define big5head(e) ((uchar)(e>>8))
#define big5tail(e) ((uchar)(e&0xff))
-uchar NEAR ctype_big5[257] =
+static uchar NEAR ctype_big5[257] =
{
0, /* For standard library */
32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
@@ -64,7 +69,7 @@ uchar NEAR ctype_big5[257] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
-uchar NEAR to_lower_big5[]=
+static uchar NEAR to_lower_big5[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -100,7 +105,7 @@ uchar NEAR to_lower_big5[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR to_upper_big5[]=
+static uchar NEAR to_upper_big5[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -136,7 +141,7 @@ uchar NEAR to_upper_big5[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR sort_order_big5[]=
+static uchar NEAR sort_order_big5[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -213,7 +218,9 @@ static uint16 big5strokexfrm(uint16 i)
return 0xA140;
}
-int my_strnncoll_big5(const uchar * s1, int len1, const uchar * s2, int len2)
+static int my_strnncoll_big5(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar * s1, uint len1,
+ const uchar * s2, uint len2)
{
uint len;
@@ -235,10 +242,21 @@ int my_strnncoll_big5(const uchar * s1, int len1, const uchar * s2, int len2)
return (int) (len1-len2);
}
-int my_strnxfrm_big5(uchar * dest, const uchar * src, int len, int srclen)
+static
+int my_strnncollsp_big5(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_big5(cs,s,slen,t,tlen);
+}
+
+static int my_strnxfrm_big5(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar * src, uint srclen)
{
uint16 e;
- /*uchar *d = dest; XXX: unused*/
len = srclen;
while (len--)
@@ -256,7 +274,8 @@ int my_strnxfrm_big5(uchar * dest, const uchar * src, int len, int srclen)
return srclen;
}
-int my_strcoll_big5(const uchar * s1, const uchar * s2)
+#if 0
+static int my_strcoll_big5(const uchar * s1, const uchar * s2)
{
while (*s1 && *s2)
@@ -275,7 +294,7 @@ int my_strcoll_big5(const uchar * s1, const uchar * s2)
return 0;
}
-int my_strxfrm_big5(uchar * dest, const uchar * src, int len)
+static int my_strxfrm_big5(uchar * dest, const uchar * src, int len)
{
uint16 e;
uchar *d = dest;
@@ -301,6 +320,8 @@ int my_strxfrm_big5(uchar * dest, const uchar * src, int len)
*d = '\0';
return (int) (d-dest);
}
+#endif
+
/*
** Calculate min_str and max_str that ranges a LIKE string.
@@ -320,10 +341,10 @@ int my_strxfrm_big5(uchar * dest, const uchar * src, int len)
*/
#define max_sort_char ((char) 255)
-#define wild_one '_'
-#define wild_many '%'
-my_bool my_like_range_big5(const char *ptr,uint ptr_length,pchar escape,
+static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
+ const char *ptr,uint ptr_length,
+ int escape, int w_one, int w_many,
uint res_length, char *min_str,char *max_str,
uint *min_length,uint *max_length)
{
@@ -345,13 +366,13 @@ my_bool my_like_range_big5(const char *ptr,uint ptr_length,pchar escape,
*min_str++= *max_str++ = *ptr;
continue;
}
- if (*ptr == wild_one) /* '_' in SQL */
+ if (*ptr == w_one) /* '_' in SQL */
{
*min_str++='\0'; /* This should be min char */
*max_str++=max_sort_char;
continue;
}
- if (*ptr == wild_many) /* '%' in SQL */
+ if (*ptr == w_many) /* '%' in SQL */
{
*min_length= (uint) (min_str-min_org);
*max_length= res_length;
@@ -372,17 +393,5893 @@ my_bool my_like_range_big5(const char *ptr,uint ptr_length,pchar escape,
return 0;
}
-int ismbchar_big5(const char* p, const char *e)
+static int ismbchar_big5(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
{
return (isbig5head(*(p)) && (e)-(p)>1 && isbig5tail(*((p)+1))? 2: 0);
}
-my_bool ismbhead_big5(uint c)
+static my_bool ismbhead_big5(CHARSET_INFO *cs __attribute__((unused)), uint c)
{
return isbig5head(c);
}
-int mbcharlen_big5(uint c)
+static int mbcharlen_big5(CHARSET_INFO *cs __attribute__((unused)), uint c)
{
return (isbig5head(c)? 2: 0);
}
+
+/* page 0 0xA140-0xC7FC */
+static uint16 tab_big5_uni0[]={
+0x3000,0xFF0C,0x3001,0x3002,0xFF0E,0x2022,0xFF1B,0xFF1A,
+0xFF1F,0xFF01,0xFE30,0x2026,0x2025,0xFE50,0xFF64,0xFE52,
+0x00B7,0xFE54,0xFE55,0xFE56,0xFE57,0xFF5C,0x2013,0xFE31,
+0x2014,0xFE33,0xFFFD,0xFE34,0xFE4F,0xFF08,0xFF09,0xFE35,
+0xFE36,0xFF5B,0xFF5D,0xFE37,0xFE38,0x3014,0x3015,0xFE39,
+0xFE3A,0x3010,0x3011,0xFE3B,0xFE3C,0x300A,0x300B,0xFE3D,
+0xFE3E,0x3008,0x3009,0xFE3F,0xFE40,0x300C,0x300D,0xFE41,
+0xFE42,0x300E,0x300F,0xFE43,0xFE44,0xFE59,0xFE5A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFE5B,0xFE5C,0xFE5D,0xFE5E,0x2018,0x2019,0x201C,
+0x201D,0x301D,0x301E,0x2035,0x2032,0xFF03,0xFF06,0xFF0A,
+0x203B,0x00A7,0x3003,0x25CB,0x25CF,0x25B3,0x25B2,0x25CE,
+0x2606,0x2605,0x25C7,0x25C6,0x25A1,0x25A0,0x25BD,0x25BC,
+0x32A3,0x2105,0x203E,0xFFFD,0xFF3F,0xFFFD,0xFE49,0xFE4A,
+0xFE4D,0xFE4E,0xFE4B,0xFE4C,0xFE5F,0xFE60,0xFE61,0xFF0B,
+0xFF0D,0x00D7,0x00F7,0x00B1,0x221A,0xFF1C,0xFF1E,0xFF1D,
+0x2266,0x2267,0x2260,0x221E,0x2252,0x2261,0xFE62,0xFE63,
+0xFE64,0xFE65,0xFE66,0x223C,0x2229,0x222A,0x22A5,0x2220,
+0x221F,0x22BF,0x33D2,0x33D1,0x222B,0x222E,0x2235,0x2234,
+0x2640,0x2642,0x2641,0x2609,0x2191,0x2193,0x2190,0x2192,
+0x2196,0x2197,0x2199,0x2198,0x2225,0x2223,0xFFFD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFFFD,0xFF0F,0xFF3C,0xFF04,0x00A5,0x3012,0x00A2,0x00A3,
+0xFF05,0xFF20,0x2103,0x2109,0xFE69,0xFE6A,0xFE6B,0x33D5,
+0x339C,0x339D,0x339E,0x33CE,0x33A1,0x338E,0x338F,0x33C4,
+0x00B0,0x5159,0x515B,0x515E,0x515D,0x5161,0x5163,0x55E7,
+0x74E9,0x7CCE,0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,
+0x2587,0x2588,0x258F,0x258E,0x258D,0x258C,0x258B,0x258A,
+0x2589,0x253C,0x2534,0x252C,0x2524,0x251C,0x2594,0x2500,
+0x2502,0x2595,0x250C,0x2510,0x2514,0x2518,0x256D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x256E,0x2570,0x256F,0x2550,0x255E,0x256A,0x2561,
+0x25E2,0x25E3,0x25E5,0x25E4,0x2571,0x2572,0x2573,0xFF10,
+0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,
+0xFF19,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,
+0x2167,0x2168,0x2169,0x3021,0x3022,0x3023,0x3024,0x3025,
+0x3026,0x3027,0x3028,0x3029,0xFFFD,0x5344,0xFFFD,0xFF21,
+0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,0xFF29,
+0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,0xFF31,
+0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,0xFF39,
+0xFF3A,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,
+0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,
+0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFF57,0xFF58,0xFF59,0xFF5A,0x0391,0x0392,0x0393,0x0394,
+0x0395,0x0396,0x0397,0x0398,0x0399,0x039A,0x039B,0x039C,
+0x039D,0x039E,0x039F,0x03A0,0x03A1,0x03A3,0x03A4,0x03A5,
+0x03A6,0x03A7,0x03A8,0x03A9,0x03B1,0x03B2,0x03B3,0x03B4,
+0x03B5,0x03B6,0x03B7,0x03B8,0x03B9,0x03BA,0x03BB,0x03BC,
+0x03BD,0x03BE,0x03BF,0x03C0,0x03C1,0x03C3,0x03C4,0x03C5,
+0x03C6,0x03C7,0x03C8,0x03C9,0x3105,0x3106,0x3107,0x3108,
+0x3109,0x310A,0x310B,0x310C,0x310D,0x310E,0x310F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,
+0x3117,0x3118,0x3119,0x311A,0x311B,0x311C,0x311D,0x311E,
+0x311F,0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,
+0x3127,0x3128,0x3129,0x02D9,0x02C9,0x02CA,0x02C7,0x02CB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E00,0x4E59,0x4E01,0x4E03,0x4E43,0x4E5D,0x4E86,0x4E8C,
+0x4EBA,0x513F,0x5165,0x516B,0x51E0,0x5200,0x5201,0x529B,
+0x5315,0x5341,0x535C,0x53C8,0x4E09,0x4E0B,0x4E08,0x4E0A,
+0x4E2B,0x4E38,0x51E1,0x4E45,0x4E48,0x4E5F,0x4E5E,0x4E8E,
+0x4EA1,0x5140,0x5203,0x52FA,0x5343,0x53C9,0x53E3,0x571F,
+0x58EB,0x5915,0x5927,0x5973,0x5B50,0x5B51,0x5B53,0x5BF8,
+0x5C0F,0x5C22,0x5C38,0x5C71,0x5DDD,0x5DE5,0x5DF1,0x5DF2,
+0x5DF3,0x5DFE,0x5E72,0x5EFE,0x5F0B,0x5F13,0x624D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4E11,0x4E10,0x4E0D,0x4E2D,0x4E30,0x4E39,0x4E4B,
+0x5C39,0x4E88,0x4E91,0x4E95,0x4E92,0x4E94,0x4EA2,0x4EC1,
+0x4EC0,0x4EC3,0x4EC6,0x4EC7,0x4ECD,0x4ECA,0x4ECB,0x4EC4,
+0x5143,0x5141,0x5167,0x516D,0x516E,0x516C,0x5197,0x51F6,
+0x5206,0x5207,0x5208,0x52FB,0x52FE,0x52FF,0x5316,0x5339,
+0x5348,0x5347,0x5345,0x535E,0x5384,0x53CB,0x53CA,0x53CD,
+0x58EC,0x5929,0x592B,0x592A,0x592D,0x5B54,0x5C11,0x5C24,
+0x5C3A,0x5C6F,0x5DF4,0x5E7B,0x5EFF,0x5F14,0x5F15,0x5FC3,
+0x6208,0x6236,0x624B,0x624E,0x652F,0x6587,0x6597,0x65A4,
+0x65B9,0x65E5,0x66F0,0x6708,0x6728,0x6B20,0x6B62,0x6B79,
+0x6BCB,0x6BD4,0x6BDB,0x6C0F,0x6C34,0x706B,0x722A,0x7236,
+0x723B,0x7247,0x7259,0x725B,0x72AC,0x738B,0x4E19, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E16,0x4E15,0x4E14,0x4E18,0x4E3B,0x4E4D,0x4E4F,0x4E4E,
+0x4EE5,0x4ED8,0x4ED4,0x4ED5,0x4ED6,0x4ED7,0x4EE3,0x4EE4,
+0x4ED9,0x4EDE,0x5145,0x5144,0x5189,0x518A,0x51AC,0x51F9,
+0x51FA,0x51F8,0x520A,0x52A0,0x529F,0x5305,0x5306,0x5317,
+0x531D,0x4EDF,0x534A,0x5349,0x5361,0x5360,0x536F,0x536E,
+0x53BB,0x53EF,0x53E4,0x53F3,0x53EC,0x53EE,0x53E9,0x53E8,
+0x53FC,0x53F8,0x53F5,0x53EB,0x53E6,0x53EA,0x53F2,0x53F1,
+0x53F0,0x53E5,0x53ED,0x53FB,0x56DB,0x56DA,0x5916, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x592E,0x5931,0x5974,0x5976,0x5B55,0x5B83,0x5C3C,
+0x5DE8,0x5DE7,0x5DE6,0x5E02,0x5E03,0x5E73,0x5E7C,0x5F01,
+0x5F18,0x5F17,0x5FC5,0x620A,0x6253,0x6254,0x6252,0x6251,
+0x65A5,0x65E6,0x672E,0x672C,0x672A,0x672B,0x672D,0x6B63,
+0x6BCD,0x6C11,0x6C10,0x6C38,0x6C41,0x6C40,0x6C3E,0x72AF,
+0x7384,0x7389,0x74DC,0x74E6,0x7518,0x751F,0x7528,0x7529,
+0x7530,0x7531,0x7532,0x7533,0x758B,0x767D,0x76AE,0x76BF,
+0x76EE,0x77DB,0x77E2,0x77F3,0x793A,0x79BE,0x7A74,0x7ACB,
+0x4E1E,0x4E1F,0x4E52,0x4E53,0x4E69,0x4E99,0x4EA4,0x4EA6,
+0x4EA5,0x4EFF,0x4F09,0x4F19,0x4F0A,0x4F15,0x4F0D,0x4F10,
+0x4F11,0x4F0F,0x4EF2,0x4EF6,0x4EFB,0x4EF0,0x4EF3,0x4EFD,
+0x4F01,0x4F0B,0x5149,0x5147,0x5146,0x5148,0x5168, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5171,0x518D,0x51B0,0x5217,0x5211,0x5212,0x520E,0x5216,
+0x52A3,0x5308,0x5321,0x5320,0x5370,0x5371,0x5409,0x540F,
+0x540C,0x540A,0x5410,0x5401,0x540B,0x5404,0x5411,0x540D,
+0x5408,0x5403,0x540E,0x5406,0x5412,0x56E0,0x56DE,0x56DD,
+0x5733,0x5730,0x5728,0x572D,0x572C,0x572F,0x5729,0x5919,
+0x591A,0x5937,0x5938,0x5984,0x5978,0x5983,0x597D,0x5979,
+0x5982,0x5981,0x5B57,0x5B58,0x5B87,0x5B88,0x5B85,0x5B89,
+0x5BFA,0x5C16,0x5C79,0x5DDE,0x5E06,0x5E76,0x5E74, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F0F,0x5F1B,0x5FD9,0x5FD6,0x620E,0x620C,0x620D,
+0x6210,0x6263,0x625B,0x6258,0x6536,0x65E9,0x65E8,0x65EC,
+0x65ED,0x66F2,0x66F3,0x6709,0x673D,0x6734,0x6731,0x6735,
+0x6B21,0x6B64,0x6B7B,0x6C16,0x6C5D,0x6C57,0x6C59,0x6C5F,
+0x6C60,0x6C50,0x6C55,0x6C61,0x6C5B,0x6C4D,0x6C4E,0x7070,
+0x725F,0x725D,0x767E,0x7AF9,0x7C73,0x7CF8,0x7F36,0x7F8A,
+0x7FBD,0x8001,0x8003,0x800C,0x8012,0x8033,0x807F,0x8089,
+0x808B,0x808C,0x81E3,0x81EA,0x81F3,0x81FC,0x820C,0x821B,
+0x821F,0x826E,0x8272,0x827E,0x866B,0x8840,0x884C,0x8863,
+0x897F,0x9621,0x4E32,0x4EA8,0x4F4D,0x4F4F,0x4F47,0x4F57,
+0x4F5E,0x4F34,0x4F5B,0x4F55,0x4F30,0x4F50,0x4F51,0x4F3D,
+0x4F3A,0x4F38,0x4F43,0x4F54,0x4F3C,0x4F46,0x4F63, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4F5C,0x4F60,0x4F2F,0x4F4E,0x4F36,0x4F59,0x4F5D,0x4F48,
+0x4F5A,0x514C,0x514B,0x514D,0x5175,0x51B6,0x51B7,0x5225,
+0x5224,0x5229,0x522A,0x5228,0x52AB,0x52A9,0x52AA,0x52AC,
+0x5323,0x5373,0x5375,0x541D,0x542D,0x541E,0x543E,0x5426,
+0x544E,0x5427,0x5446,0x5443,0x5433,0x5448,0x5442,0x541B,
+0x5429,0x544A,0x5439,0x543B,0x5438,0x542E,0x5435,0x5436,
+0x5420,0x543C,0x5440,0x5431,0x542B,0x541F,0x542C,0x56EA,
+0x56F0,0x56E4,0x56EB,0x574A,0x5751,0x5740,0x574D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5747,0x574E,0x573E,0x5750,0x574F,0x573B,0x58EF,
+0x593E,0x599D,0x5992,0x59A8,0x599E,0x59A3,0x5999,0x5996,
+0x598D,0x59A4,0x5993,0x598A,0x59A5,0x5B5D,0x5B5C,0x5B5A,
+0x5B5B,0x5B8C,0x5B8B,0x5B8F,0x5C2C,0x5C40,0x5C41,0x5C3F,
+0x5C3E,0x5C90,0x5C91,0x5C94,0x5C8C,0x5DEB,0x5E0C,0x5E8F,
+0x5E87,0x5E8A,0x5EF7,0x5F04,0x5F1F,0x5F64,0x5F62,0x5F77,
+0x5F79,0x5FD8,0x5FCC,0x5FD7,0x5FCD,0x5FF1,0x5FEB,0x5FF8,
+0x5FEA,0x6212,0x6211,0x6284,0x6297,0x6296,0x6280,0x6276,
+0x6289,0x626D,0x628A,0x627C,0x627E,0x6279,0x6273,0x6292,
+0x626F,0x6298,0x626E,0x6295,0x6293,0x6291,0x6286,0x6539,
+0x653B,0x6538,0x65F1,0x66F4,0x675F,0x674E,0x674F,0x6750,
+0x6751,0x675C,0x6756,0x675E,0x6749,0x6746,0x6760, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6753,0x6757,0x6B65,0x6BCF,0x6C42,0x6C5E,0x6C99,0x6C81,
+0x6C88,0x6C89,0x6C85,0x6C9B,0x6C6A,0x6C7A,0x6C90,0x6C70,
+0x6C8C,0x6C68,0x6C96,0x6C92,0x6C7D,0x6C83,0x6C72,0x6C7E,
+0x6C74,0x6C86,0x6C76,0x6C8D,0x6C94,0x6C98,0x6C82,0x7076,
+0x707C,0x707D,0x7078,0x7262,0x7261,0x7260,0x72C4,0x72C2,
+0x7396,0x752C,0x752B,0x7537,0x7538,0x7682,0x76EF,0x77E3,
+0x79C1,0x79C0,0x79BF,0x7A76,0x7CFB,0x7F55,0x8096,0x8093,
+0x809D,0x8098,0x809B,0x809A,0x80B2,0x826F,0x8292, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x828B,0x828D,0x898B,0x89D2,0x8A00,0x8C37,0x8C46,
+0x8C55,0x8C9D,0x8D64,0x8D70,0x8DB3,0x8EAB,0x8ECA,0x8F9B,
+0x8FB0,0x8FC2,0x8FC6,0x8FC5,0x8FC4,0x5DE1,0x9091,0x90A2,
+0x90AA,0x90A6,0x90A3,0x9149,0x91C6,0x91CC,0x9632,0x962E,
+0x9631,0x962A,0x962C,0x4E26,0x4E56,0x4E73,0x4E8B,0x4E9B,
+0x4E9E,0x4EAB,0x4EAC,0x4F6F,0x4F9D,0x4F8D,0x4F73,0x4F7F,
+0x4F6C,0x4F9B,0x4F8B,0x4F86,0x4F83,0x4F70,0x4F75,0x4F88,
+0x4F69,0x4F7B,0x4F96,0x4F7E,0x4F8F,0x4F91,0x4F7A,0x5154,
+0x5152,0x5155,0x5169,0x5177,0x5176,0x5178,0x51BD,0x51FD,
+0x523B,0x5238,0x5237,0x523A,0x5230,0x522E,0x5236,0x5241,
+0x52BE,0x52BB,0x5352,0x5354,0x5353,0x5351,0x5366,0x5377,
+0x5378,0x5379,0x53D6,0x53D4,0x53D7,0x5473,0x5475, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5496,0x5478,0x5495,0x5480,0x547B,0x5477,0x5484,0x5492,
+0x5486,0x547C,0x5490,0x5471,0x5476,0x548C,0x549A,0x5462,
+0x5468,0x548B,0x547D,0x548E,0x56FA,0x5783,0x5777,0x576A,
+0x5769,0x5761,0x5766,0x5764,0x577C,0x591C,0x5949,0x5947,
+0x5948,0x5944,0x5954,0x59BE,0x59BB,0x59D4,0x59B9,0x59AE,
+0x59D1,0x59C6,0x59D0,0x59CD,0x59CB,0x59D3,0x59CA,0x59AF,
+0x59B3,0x59D2,0x59C5,0x5B5F,0x5B64,0x5B63,0x5B97,0x5B9A,
+0x5B98,0x5B9C,0x5B99,0x5B9B,0x5C1A,0x5C48,0x5C45, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5C46,0x5CB7,0x5CA1,0x5CB8,0x5CA9,0x5CAB,0x5CB1,
+0x5CB3,0x5E18,0x5E1A,0x5E16,0x5E15,0x5E1B,0x5E11,0x5E78,
+0x5E9A,0x5E97,0x5E9C,0x5E95,0x5E96,0x5EF6,0x5F26,0x5F27,
+0x5F29,0x5F80,0x5F81,0x5F7F,0x5F7C,0x5FDD,0x5FE0,0x5FFD,
+0x5FF5,0x5FFF,0x600F,0x6014,0x602F,0x6035,0x6016,0x602A,
+0x6015,0x6021,0x6027,0x6029,0x602B,0x601B,0x6216,0x6215,
+0x623F,0x623E,0x6240,0x627F,0x62C9,0x62CC,0x62C4,0x62BF,
+0x62C2,0x62B9,0x62D2,0x62DB,0x62AB,0x62D3,0x62D4,0x62CB,
+0x62C8,0x62A8,0x62BD,0x62BC,0x62D0,0x62D9,0x62C7,0x62CD,
+0x62B5,0x62DA,0x62B1,0x62D8,0x62D6,0x62D7,0x62C6,0x62AC,
+0x62CE,0x653E,0x65A7,0x65BC,0x65FA,0x6614,0x6613,0x660C,
+0x6606,0x6602,0x660E,0x6600,0x660F,0x6615,0x660A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6607,0x670D,0x670B,0x676D,0x678B,0x6795,0x6771,0x679C,
+0x6773,0x6777,0x6787,0x679D,0x6797,0x676F,0x6770,0x677F,
+0x6789,0x677E,0x6790,0x6775,0x679A,0x6793,0x677C,0x676A,
+0x6772,0x6B23,0x6B66,0x6B67,0x6B7F,0x6C13,0x6C1B,0x6CE3,
+0x6CE8,0x6CF3,0x6CB1,0x6CCC,0x6CE5,0x6CB3,0x6CBD,0x6CBE,
+0x6CBC,0x6CE2,0x6CAB,0x6CD5,0x6CD3,0x6CB8,0x6CC4,0x6CB9,
+0x6CC1,0x6CAE,0x6CD7,0x6CC5,0x6CF1,0x6CBF,0x6CBB,0x6CE1,
+0x6CDB,0x6CCA,0x6CAC,0x6CEF,0x6CDC,0x6CD6,0x6CE0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7095,0x708E,0x7092,0x708A,0x7099,0x722C,0x722D,
+0x7238,0x7248,0x7267,0x7269,0x72C0,0x72CE,0x72D9,0x72D7,
+0x72D0,0x73A9,0x73A8,0x739F,0x73AB,0x73A5,0x753D,0x759D,
+0x7599,0x759A,0x7684,0x76C2,0x76F2,0x76F4,0x77E5,0x77FD,
+0x793E,0x7940,0x7941,0x79C9,0x79C8,0x7A7A,0x7A79,0x7AFA,
+0x7CFE,0x7F54,0x7F8C,0x7F8B,0x8005,0x80BA,0x80A5,0x80A2,
+0x80B1,0x80A1,0x80AB,0x80A9,0x80B4,0x80AA,0x80AF,0x81E5,
+0x81FE,0x820D,0x82B3,0x829D,0x8299,0x82AD,0x82BD,0x829F,
+0x82B9,0x82B1,0x82AC,0x82A5,0x82AF,0x82B8,0x82A3,0x82B0,
+0x82BE,0x82B7,0x864E,0x8671,0x521D,0x8868,0x8ECB,0x8FCE,
+0x8FD4,0x8FD1,0x90B5,0x90B8,0x90B1,0x90B6,0x91C7,0x91D1,
+0x9577,0x9580,0x961C,0x9640,0x963F,0x963B,0x9644, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9642,0x96B9,0x96E8,0x9752,0x975E,0x4E9F,0x4EAD,0x4EAE,
+0x4FE1,0x4FB5,0x4FAF,0x4FBF,0x4FE0,0x4FD1,0x4FCF,0x4FDD,
+0x4FC3,0x4FB6,0x4FD8,0x4FDF,0x4FCA,0x4FD7,0x4FAE,0x4FD0,
+0x4FC4,0x4FC2,0x4FDA,0x4FCE,0x4FDE,0x4FB7,0x5157,0x5192,
+0x5191,0x51A0,0x524E,0x5243,0x524A,0x524D,0x524C,0x524B,
+0x5247,0x52C7,0x52C9,0x52C3,0x52C1,0x530D,0x5357,0x537B,
+0x539A,0x53DB,0x54AC,0x54C0,0x54A8,0x54CE,0x54C9,0x54B8,
+0x54A6,0x54B3,0x54C7,0x54C2,0x54BD,0x54AA,0x54C1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x54C4,0x54C8,0x54AF,0x54AB,0x54B1,0x54BB,0x54A9,
+0x54A7,0x54BF,0x56FF,0x5782,0x578B,0x57A0,0x57A3,0x57A2,
+0x57CE,0x57AE,0x5793,0x5955,0x5951,0x594F,0x594E,0x5950,
+0x59DC,0x59D8,0x59FF,0x59E3,0x59E8,0x5A03,0x59E5,0x59EA,
+0x59DA,0x59E6,0x5A01,0x59FB,0x5B69,0x5BA3,0x5BA6,0x5BA4,
+0x5BA2,0x5BA5,0x5C01,0x5C4E,0x5C4F,0x5C4D,0x5C4B,0x5CD9,
+0x5CD2,0x5DF7,0x5E1D,0x5E25,0x5E1F,0x5E7D,0x5EA0,0x5EA6,
+0x5EFA,0x5F08,0x5F2D,0x5F65,0x5F88,0x5F85,0x5F8A,0x5F8B,
+0x5F87,0x5F8C,0x5F89,0x6012,0x601D,0x6020,0x6025,0x600E,
+0x6028,0x604D,0x6070,0x6068,0x6062,0x6046,0x6043,0x606C,
+0x606B,0x606A,0x6064,0x6241,0x62DC,0x6316,0x6309,0x62FC,
+0x62ED,0x6301,0x62EE,0x62FD,0x6307,0x62F1,0x62F7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x62EF,0x62EC,0x62FE,0x62F4,0x6311,0x6302,0x653F,0x6545,
+0x65AB,0x65BD,0x65E2,0x6625,0x662D,0x6620,0x6627,0x662F,
+0x661F,0x6628,0x6631,0x6624,0x66F7,0x67FF,0x67D3,0x67F1,
+0x67D4,0x67D0,0x67EC,0x67B6,0x67AF,0x67F5,0x67E9,0x67EF,
+0x67C4,0x67D1,0x67B4,0x67DA,0x67E5,0x67B8,0x67CF,0x67DE,
+0x67F3,0x67B0,0x67D9,0x67E2,0x67DD,0x67D2,0x6B6A,0x6B83,
+0x6B86,0x6BB5,0x6BD2,0x6BD7,0x6C1F,0x6CC9,0x6D0B,0x6D32,
+0x6D2A,0x6D41,0x6D25,0x6D0C,0x6D31,0x6D1E,0x6D17, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6D3B,0x6D3D,0x6D3E,0x6D36,0x6D1B,0x6CF5,0x6D39,
+0x6D27,0x6D38,0x6D29,0x6D2E,0x6D35,0x6D0E,0x6D2B,0x70AB,
+0x70BA,0x70B3,0x70AC,0x70AF,0x70AD,0x70B8,0x70AE,0x70A4,
+0x7230,0x7272,0x726F,0x7274,0x72E9,0x72E0,0x72E1,0x73B7,
+0x73CA,0x73BB,0x73B2,0x73CD,0x73C0,0x73B3,0x751A,0x752D,
+0x754F,0x754C,0x754E,0x754B,0x75AB,0x75A4,0x75A5,0x75A2,
+0x75A3,0x7678,0x7686,0x7687,0x7688,0x76C8,0x76C6,0x76C3,
+0x76C5,0x7701,0x76F9,0x76F8,0x7709,0x770B,0x76FE,0x76FC,
+0x7707,0x77DC,0x7802,0x7814,0x780C,0x780D,0x7946,0x7949,
+0x7948,0x7947,0x79B9,0x79BA,0x79D1,0x79D2,0x79CB,0x7A7F,
+0x7A81,0x7AFF,0x7AFD,0x7C7D,0x7D02,0x7D05,0x7D00,0x7D09,
+0x7D07,0x7D04,0x7D06,0x7F38,0x7F8E,0x7FBF,0x8004, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8010,0x800D,0x8011,0x8036,0x80D6,0x80E5,0x80DA,0x80C3,
+0x80C4,0x80CC,0x80E1,0x80DB,0x80CE,0x80DE,0x80E4,0x80DD,
+0x81F4,0x8222,0x82E7,0x8303,0x8305,0x82E3,0x82DB,0x82E6,
+0x8304,0x82E5,0x8302,0x8309,0x82D2,0x82D7,0x82F1,0x8301,
+0x82DC,0x82D4,0x82D1,0x82DE,0x82D3,0x82DF,0x82EF,0x8306,
+0x8650,0x8679,0x867B,0x867A,0x884D,0x886B,0x8981,0x89D4,
+0x8A08,0x8A02,0x8A03,0x8C9E,0x8CA0,0x8D74,0x8D73,0x8DB4,
+0x8ECD,0x8ECC,0x8FF0,0x8FE6,0x8FE2,0x8FEA,0x8FE5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8FED,0x8FEB,0x8FE4,0x8FE8,0x90CA,0x90CE,0x90C1,
+0x90C3,0x914B,0x914A,0x91CD,0x9582,0x9650,0x964B,0x964C,
+0x964D,0x9762,0x9769,0x97CB,0x97ED,0x97F3,0x9801,0x98A8,
+0x98DB,0x98DF,0x9996,0x9999,0x4E58,0x4EB3,0x500C,0x500D,
+0x5023,0x4FEF,0x5026,0x5025,0x4FF8,0x5029,0x5016,0x5006,
+0x503C,0x501F,0x501A,0x5012,0x5011,0x4FFA,0x5000,0x5014,
+0x5028,0x4FF1,0x5021,0x500B,0x5019,0x5018,0x4FF3,0x4FEE,
+0x502D,0x502A,0x4FFE,0x502B,0x5009,0x517C,0x51A4,0x51A5,
+0x51A2,0x51CD,0x51CC,0x51C6,0x51CB,0x5256,0x525C,0x5254,
+0x525B,0x525D,0x532A,0x537F,0x539F,0x539D,0x53DF,0x54E8,
+0x5510,0x5501,0x5537,0x54FC,0x54E5,0x54F2,0x5506,0x54FA,
+0x5514,0x54E9,0x54ED,0x54E1,0x5509,0x54EE,0x54EA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x54E6,0x5527,0x5507,0x54FD,0x550F,0x5703,0x5704,0x57C2,
+0x57D4,0x57CB,0x57C3,0x5809,0x590F,0x5957,0x5958,0x595A,
+0x5A11,0x5A18,0x5A1C,0x5A1F,0x5A1B,0x5A13,0x59EC,0x5A20,
+0x5A23,0x5A29,0x5A25,0x5A0C,0x5A09,0x5B6B,0x5C58,0x5BB0,
+0x5BB3,0x5BB6,0x5BB4,0x5BAE,0x5BB5,0x5BB9,0x5BB8,0x5C04,
+0x5C51,0x5C55,0x5C50,0x5CED,0x5CFD,0x5CFB,0x5CEA,0x5CE8,
+0x5CF0,0x5CF6,0x5D01,0x5CF4,0x5DEE,0x5E2D,0x5E2B,0x5EAB,
+0x5EAD,0x5EA7,0x5F31,0x5F92,0x5F91,0x5F90,0x6059, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6063,0x6065,0x6050,0x6055,0x606D,0x6069,0x606F,
+0x6084,0x609F,0x609A,0x608D,0x6094,0x608C,0x6085,0x6096,
+0x6247,0x62F3,0x6308,0x62FF,0x634E,0x633E,0x632F,0x6355,
+0x6342,0x6346,0x634F,0x6349,0x633A,0x6350,0x633D,0x632A,
+0x632B,0x6328,0x634D,0x634C,0x6548,0x6549,0x6599,0x65C1,
+0x65C5,0x6642,0x6649,0x664F,0x6643,0x6652,0x664C,0x6645,
+0x6641,0x66F8,0x6714,0x6715,0x6717,0x6821,0x6838,0x6848,
+0x6846,0x6853,0x6839,0x6842,0x6854,0x6829,0x68B3,0x6817,
+0x684C,0x6851,0x683D,0x67F4,0x6850,0x6840,0x683C,0x6843,
+0x682A,0x6845,0x6813,0x6818,0x6841,0x6B8A,0x6B89,0x6BB7,
+0x6C23,0x6C27,0x6C28,0x6C26,0x6C24,0x6CF0,0x6D6A,0x6D95,
+0x6D88,0x6D87,0x6D66,0x6D78,0x6D77,0x6D59,0x6D93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6D6C,0x6D89,0x6D6E,0x6D5A,0x6D74,0x6D69,0x6D8C,0x6D8A,
+0x6D79,0x6D85,0x6D65,0x6D94,0x70CA,0x70D8,0x70E4,0x70D9,
+0x70C8,0x70CF,0x7239,0x7279,0x72FC,0x72F9,0x72FD,0x72F8,
+0x72F7,0x7386,0x73ED,0x7409,0x73EE,0x73E0,0x73EA,0x73DE,
+0x7554,0x755D,0x755C,0x755A,0x7559,0x75BE,0x75C5,0x75C7,
+0x75B2,0x75B3,0x75BD,0x75BC,0x75B9,0x75C2,0x75B8,0x768B,
+0x76B0,0x76CA,0x76CD,0x76CE,0x7729,0x771F,0x7720,0x7728,
+0x77E9,0x7830,0x7827,0x7838,0x781D,0x7834,0x7837, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7825,0x782D,0x7820,0x781F,0x7832,0x7955,0x7950,
+0x7960,0x795F,0x7956,0x795E,0x795D,0x7957,0x795A,0x79E4,
+0x79E3,0x79E7,0x79DF,0x79E6,0x79E9,0x79D8,0x7A84,0x7A88,
+0x7AD9,0x7B06,0x7B11,0x7C89,0x7D21,0x7D17,0x7D0B,0x7D0A,
+0x7D20,0x7D22,0x7D14,0x7D10,0x7D15,0x7D1A,0x7D1C,0x7D0D,
+0x7D19,0x7D1B,0x7F3A,0x7F5F,0x7F94,0x7FC5,0x7FC1,0x8006,
+0x8018,0x8015,0x8019,0x8017,0x803D,0x803F,0x80F1,0x8102,
+0x80F0,0x8105,0x80ED,0x80F4,0x8106,0x80F8,0x80F3,0x8108,
+0x80FD,0x810A,0x80FC,0x80EF,0x81ED,0x81EC,0x8200,0x8210,
+0x822A,0x822B,0x8228,0x822C,0x82BB,0x832B,0x8352,0x8354,
+0x834A,0x8338,0x8350,0x8349,0x8335,0x8334,0x834F,0x8332,
+0x8339,0x8336,0x8317,0x8340,0x8331,0x8328,0x8343, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8654,0x868A,0x86AA,0x8693,0x86A4,0x86A9,0x868C,0x86A3,
+0x869C,0x8870,0x8877,0x8881,0x8882,0x887D,0x8879,0x8A18,
+0x8A10,0x8A0E,0x8A0C,0x8A15,0x8A0A,0x8A17,0x8A13,0x8A16,
+0x8A0F,0x8A11,0x8C48,0x8C7A,0x8C79,0x8CA1,0x8CA2,0x8D77,
+0x8EAC,0x8ED2,0x8ED4,0x8ECF,0x8FB1,0x9001,0x9006,0x8FF7,
+0x9000,0x8FFA,0x8FF4,0x9003,0x8FFD,0x9005,0x8FF8,0x9095,
+0x90E1,0x90DD,0x90E2,0x9152,0x914D,0x914C,0x91D8,0x91DD,
+0x91D7,0x91DC,0x91D9,0x9583,0x9662,0x9663,0x9661, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x965B,0x965D,0x9664,0x9658,0x965E,0x96BB,0x98E2,
+0x99AC,0x9AA8,0x9AD8,0x9B25,0x9B32,0x9B3C,0x4E7E,0x507A,
+0x507D,0x505C,0x5047,0x5043,0x504C,0x505A,0x5049,0x5065,
+0x5076,0x504E,0x5055,0x5075,0x5074,0x5077,0x504F,0x500F,
+0x506F,0x506D,0x515C,0x5195,0x51F0,0x526A,0x526F,0x52D2,
+0x52D9,0x52D8,0x52D5,0x5310,0x530F,0x5319,0x533F,0x5340,
+0x533E,0x53C3,0x66FC,0x5546,0x556A,0x5566,0x5544,0x555E,
+0x5561,0x5543,0x554A,0x5531,0x5556,0x554F,0x5555,0x552F,
+0x5564,0x5538,0x552E,0x555C,0x552C,0x5563,0x5533,0x5541,
+0x5557,0x5708,0x570B,0x5709,0x57DF,0x5805,0x580A,0x5806,
+0x57E0,0x57E4,0x57FA,0x5802,0x5835,0x57F7,0x57F9,0x5920,
+0x5962,0x5A36,0x5A41,0x5A49,0x5A66,0x5A6A,0x5A40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5A3C,0x5A62,0x5A5A,0x5A46,0x5A4A,0x5B70,0x5BC7,0x5BC5,
+0x5BC4,0x5BC2,0x5BBF,0x5BC6,0x5C09,0x5C08,0x5C07,0x5C60,
+0x5C5C,0x5C5D,0x5D07,0x5D06,0x5D0E,0x5D1B,0x5D16,0x5D22,
+0x5D11,0x5D29,0x5D14,0x5D19,0x5D24,0x5D27,0x5D17,0x5DE2,
+0x5E38,0x5E36,0x5E33,0x5E37,0x5EB7,0x5EB8,0x5EB6,0x5EB5,
+0x5EBE,0x5F35,0x5F37,0x5F57,0x5F6C,0x5F69,0x5F6B,0x5F97,
+0x5F99,0x5F9E,0x5F98,0x5FA1,0x5FA0,0x5F9C,0x607F,0x60A3,
+0x6089,0x60A0,0x60A8,0x60CB,0x60B4,0x60E6,0x60BD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x60C5,0x60BB,0x60B5,0x60DC,0x60BC,0x60D8,0x60D5,
+0x60C6,0x60DF,0x60B8,0x60DA,0x60C7,0x621A,0x621B,0x6248,
+0x63A0,0x63A7,0x6372,0x6396,0x63A2,0x63A5,0x6377,0x6367,
+0x6398,0x63AA,0x6371,0x63A9,0x6389,0x6383,0x639B,0x636B,
+0x63A8,0x6384,0x6388,0x6399,0x63A1,0x63AC,0x6392,0x638F,
+0x6380,0x637B,0x6369,0x6368,0x637A,0x655D,0x6556,0x6551,
+0x6559,0x6557,0x555F,0x654F,0x6558,0x6555,0x6554,0x659C,
+0x659B,0x65AC,0x65CF,0x65CB,0x65CC,0x65CE,0x665D,0x665A,
+0x6664,0x6668,0x6666,0x665E,0x66F9,0x52D7,0x671B,0x6881,
+0x68AF,0x68A2,0x6893,0x68B5,0x687F,0x6876,0x68B1,0x68A7,
+0x6897,0x68B0,0x6883,0x68C4,0x68AD,0x6886,0x6885,0x6894,
+0x689D,0x68A8,0x689F,0x68A1,0x6882,0x6B32,0x6BBA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6BEB,0x6BEC,0x6C2B,0x6D8E,0x6DBC,0x6DF3,0x6DD9,0x6DB2,
+0x6DE1,0x6DCC,0x6DE4,0x6DFB,0x6DFA,0x6E05,0x6DC7,0x6DCB,
+0x6DAF,0x6DD1,0x6DAE,0x6DDE,0x6DF9,0x6DB8,0x6DF7,0x6DF5,
+0x6DC5,0x6DD2,0x6E1A,0x6DB5,0x6DDA,0x6DEB,0x6DD8,0x6DEA,
+0x6DF1,0x6DEE,0x6DE8,0x6DC6,0x6DC4,0x6DAA,0x6DEC,0x6DBF,
+0x6DE6,0x70F9,0x7109,0x710A,0x70FD,0x70EF,0x723D,0x727D,
+0x7281,0x731C,0x731B,0x7316,0x7313,0x7319,0x7387,0x7405,
+0x740A,0x7403,0x7406,0x73FE,0x740D,0x74E0,0x74F6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x74F7,0x751C,0x7522,0x7565,0x7566,0x7562,0x7570,
+0x758F,0x75D4,0x75D5,0x75B5,0x75CA,0x75CD,0x768E,0x76D4,
+0x76D2,0x76DB,0x7737,0x773E,0x773C,0x7736,0x7738,0x773A,
+0x786B,0x7843,0x784E,0x7965,0x7968,0x796D,0x79FB,0x7A92,
+0x7A95,0x7B20,0x7B28,0x7B1B,0x7B2C,0x7B26,0x7B19,0x7B1E,
+0x7B2E,0x7C92,0x7C97,0x7C95,0x7D46,0x7D43,0x7D71,0x7D2E,
+0x7D39,0x7D3C,0x7D40,0x7D30,0x7D33,0x7D44,0x7D2F,0x7D42,
+0x7D32,0x7D31,0x7F3D,0x7F9E,0x7F9A,0x7FCC,0x7FCE,0x7FD2,
+0x801C,0x804A,0x8046,0x812F,0x8116,0x8123,0x812B,0x8129,
+0x8130,0x8124,0x8202,0x8235,0x8237,0x8236,0x8239,0x838E,
+0x839E,0x8398,0x8378,0x83A2,0x8396,0x83BD,0x83AB,0x8392,
+0x838A,0x8393,0x8389,0x83A0,0x8377,0x837B,0x837C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8386,0x83A7,0x8655,0x5F6A,0x86C7,0x86C0,0x86B6,0x86C4,
+0x86B5,0x86C6,0x86CB,0x86B1,0x86AF,0x86C9,0x8853,0x889E,
+0x8888,0x88AB,0x8892,0x8896,0x888D,0x888B,0x8993,0x898F,
+0x8A2A,0x8A1D,0x8A23,0x8A25,0x8A31,0x8A2D,0x8A1F,0x8A1B,
+0x8A22,0x8C49,0x8C5A,0x8CA9,0x8CAC,0x8CAB,0x8CA8,0x8CAA,
+0x8CA7,0x8D67,0x8D66,0x8DBE,0x8DBA,0x8EDB,0x8EDF,0x9019,
+0x900D,0x901A,0x9017,0x9023,0x901F,0x901D,0x9010,0x9015,
+0x901E,0x9020,0x900F,0x9022,0x9016,0x901B,0x9014, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x90E8,0x90ED,0x90FD,0x9157,0x91CE,0x91F5,0x91E6,
+0x91E3,0x91E7,0x91ED,0x91E9,0x9589,0x966A,0x9675,0x9673,
+0x9678,0x9670,0x9674,0x9676,0x9677,0x966C,0x96C0,0x96EA,
+0x96E9,0x7AE0,0x7ADF,0x9802,0x9803,0x9B5A,0x9CE5,0x9E75,
+0x9E7F,0x9EA5,0x9EBB,0x50A2,0x508D,0x5085,0x5099,0x5091,
+0x5080,0x5096,0x5098,0x509A,0x6700,0x51F1,0x5272,0x5274,
+0x5275,0x5269,0x52DE,0x52DD,0x52DB,0x535A,0x53A5,0x557B,
+0x5580,0x55A7,0x557C,0x558A,0x559D,0x5598,0x5582,0x559C,
+0x55AA,0x5594,0x5587,0x558B,0x5583,0x55B3,0x55AE,0x559F,
+0x553E,0x55B2,0x559A,0x55BB,0x55AC,0x55B1,0x557E,0x5589,
+0x55AB,0x5599,0x570D,0x582F,0x582A,0x5834,0x5824,0x5830,
+0x5831,0x5821,0x581D,0x5820,0x58F9,0x58FA,0x5960, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5A77,0x5A9A,0x5A7F,0x5A92,0x5A9B,0x5AA7,0x5B73,0x5B71,
+0x5BD2,0x5BCC,0x5BD3,0x5BD0,0x5C0A,0x5C0B,0x5C31,0x5D4C,
+0x5D50,0x5D34,0x5D47,0x5DFD,0x5E45,0x5E3D,0x5E40,0x5E43,
+0x5E7E,0x5ECA,0x5EC1,0x5EC2,0x5EC4,0x5F3C,0x5F6D,0x5FA9,
+0x5FAA,0x5FA8,0x60D1,0x60E1,0x60B2,0x60B6,0x60E0,0x611C,
+0x6123,0x60FA,0x6115,0x60F0,0x60FB,0x60F4,0x6168,0x60F1,
+0x610E,0x60F6,0x6109,0x6100,0x6112,0x621F,0x6249,0x63A3,
+0x638C,0x63CF,0x63C0,0x63E9,0x63C9,0x63C6,0x63CD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x63D2,0x63E3,0x63D0,0x63E1,0x63D6,0x63ED,0x63EE,
+0x6376,0x63F4,0x63EA,0x63DB,0x6452,0x63DA,0x63F9,0x655E,
+0x6566,0x6562,0x6563,0x6591,0x6590,0x65AF,0x666E,0x6670,
+0x6674,0x6676,0x666F,0x6691,0x667A,0x667E,0x6677,0x66FE,
+0x66FF,0x671F,0x671D,0x68FA,0x68D5,0x68E0,0x68D8,0x68D7,
+0x6905,0x68DF,0x68F5,0x68EE,0x68E7,0x68F9,0x68D2,0x68F2,
+0x68E3,0x68CB,0x68CD,0x690D,0x6912,0x690E,0x68C9,0x68DA,
+0x696E,0x68FB,0x6B3E,0x6B3A,0x6B3D,0x6B98,0x6B96,0x6BBC,
+0x6BEF,0x6C2E,0x6C2F,0x6C2C,0x6E2F,0x6E38,0x6E54,0x6E21,
+0x6E32,0x6E67,0x6E4A,0x6E20,0x6E25,0x6E23,0x6E1B,0x6E5B,
+0x6E58,0x6E24,0x6E56,0x6E6E,0x6E2D,0x6E26,0x6E6F,0x6E34,
+0x6E4D,0x6E3A,0x6E2C,0x6E43,0x6E1D,0x6E3E,0x6ECB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E89,0x6E19,0x6E4E,0x6E63,0x6E44,0x6E72,0x6E69,0x6E5F,
+0x7119,0x711A,0x7126,0x7130,0x7121,0x7136,0x716E,0x711C,
+0x724C,0x7284,0x7280,0x7336,0x7325,0x7334,0x7329,0x743A,
+0x742A,0x7433,0x7422,0x7425,0x7435,0x7436,0x7434,0x742F,
+0x741B,0x7426,0x7428,0x7525,0x7526,0x756B,0x756A,0x75E2,
+0x75DB,0x75E3,0x75D9,0x75D8,0x75DE,0x75E0,0x767B,0x767C,
+0x7696,0x7693,0x76B4,0x76DC,0x774F,0x77ED,0x785D,0x786C,
+0x786F,0x7A0D,0x7A08,0x7A0B,0x7A05,0x7A00,0x7A98, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7A97,0x7A96,0x7AE5,0x7AE3,0x7B49,0x7B56,0x7B46,
+0x7B50,0x7B52,0x7B54,0x7B4D,0x7B4B,0x7B4F,0x7B51,0x7C9F,
+0x7CA5,0x7D5E,0x7D50,0x7D68,0x7D55,0x7D2B,0x7D6E,0x7D72,
+0x7D61,0x7D66,0x7D62,0x7D70,0x7D73,0x5584,0x7FD4,0x7FD5,
+0x800B,0x8052,0x8085,0x8155,0x8154,0x814B,0x8151,0x814E,
+0x8139,0x8146,0x813E,0x814C,0x8153,0x8174,0x8212,0x821C,
+0x83E9,0x8403,0x83F8,0x840D,0x83E0,0x83C5,0x840B,0x83C1,
+0x83EF,0x83F1,0x83F4,0x8457,0x840A,0x83F0,0x840C,0x83CC,
+0x83FD,0x83F2,0x83CA,0x8438,0x840E,0x8404,0x83DC,0x8407,
+0x83D4,0x83DF,0x865B,0x86DF,0x86D9,0x86ED,0x86D4,0x86DB,
+0x86E4,0x86D0,0x86DE,0x8857,0x88C1,0x88C2,0x88B1,0x8983,
+0x8996,0x8A3B,0x8A60,0x8A55,0x8A5E,0x8A3C,0x8A41, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8A54,0x8A5B,0x8A50,0x8A46,0x8A34,0x8A3A,0x8A36,0x8A56,
+0x8C61,0x8C82,0x8CAF,0x8CBC,0x8CB3,0x8CBD,0x8CC1,0x8CBB,
+0x8CC0,0x8CB4,0x8CB7,0x8CB6,0x8CBF,0x8CB8,0x8D8A,0x8D85,
+0x8D81,0x8DCE,0x8DDD,0x8DCB,0x8DDA,0x8DD1,0x8DCC,0x8DDB,
+0x8DC6,0x8EFB,0x8EF8,0x8EFC,0x8F9C,0x902E,0x9035,0x9031,
+0x9038,0x9032,0x9036,0x9102,0x90F5,0x9109,0x90FE,0x9163,
+0x9165,0x91CF,0x9214,0x9215,0x9223,0x9209,0x921E,0x920D,
+0x9210,0x9207,0x9211,0x9594,0x958F,0x958B,0x9591, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9593,0x9592,0x958E,0x968A,0x968E,0x968B,0x967D,
+0x9685,0x9686,0x968D,0x9672,0x9684,0x96C1,0x96C5,0x96C4,
+0x96C6,0x96C7,0x96EF,0x96F2,0x97CC,0x9805,0x9806,0x9808,
+0x98E7,0x98EA,0x98EF,0x98E9,0x98F2,0x98ED,0x99AE,0x99AD,
+0x9EC3,0x9ECD,0x9ED1,0x4E82,0x50AD,0x50B5,0x50B2,0x50B3,
+0x50C5,0x50BE,0x50AC,0x50B7,0x50BB,0x50AF,0x50C7,0x527F,
+0x5277,0x527D,0x52DF,0x52E6,0x52E4,0x52E2,0x52E3,0x532F,
+0x55DF,0x55E8,0x55D3,0x55E6,0x55CE,0x55DC,0x55C7,0x55D1,
+0x55E3,0x55E4,0x55EF,0x55DA,0x55E1,0x55C5,0x55C6,0x55E5,
+0x55C9,0x5712,0x5713,0x585E,0x5851,0x5858,0x5857,0x585A,
+0x5854,0x586B,0x584C,0x586D,0x584A,0x5862,0x5852,0x584B,
+0x5967,0x5AC1,0x5AC9,0x5ACC,0x5ABE,0x5ABD,0x5ABC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5AB3,0x5AC2,0x5AB2,0x5D69,0x5D6F,0x5E4C,0x5E79,0x5EC9,
+0x5EC8,0x5F12,0x5F59,0x5FAC,0x5FAE,0x611A,0x610F,0x6148,
+0x611F,0x60F3,0x611B,0x60F9,0x6101,0x6108,0x614E,0x614C,
+0x6144,0x614D,0x613E,0x6134,0x6127,0x610D,0x6106,0x6137,
+0x6221,0x6222,0x6413,0x643E,0x641E,0x642A,0x642D,0x643D,
+0x642C,0x640F,0x641C,0x6414,0x640D,0x6436,0x6416,0x6417,
+0x6406,0x656C,0x659F,0x65B0,0x6697,0x6689,0x6687,0x6688,
+0x6696,0x6684,0x6698,0x668D,0x6703,0x6994,0x696D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x695A,0x6977,0x6960,0x6954,0x6975,0x6930,0x6982,
+0x694A,0x6968,0x696B,0x695E,0x6953,0x6979,0x6986,0x695D,
+0x6963,0x695B,0x6B47,0x6B72,0x6BC0,0x6BBF,0x6BD3,0x6BFD,
+0x6EA2,0x6EAF,0x6ED3,0x6EB6,0x6EC2,0x6E90,0x6E9D,0x6EC7,
+0x6EC5,0x6EA5,0x6E98,0x6EBC,0x6EBA,0x6EAB,0x6ED1,0x6E96,
+0x6E9C,0x6EC4,0x6ED4,0x6EAA,0x6EA7,0x6EB4,0x714E,0x7159,
+0x7169,0x7164,0x7149,0x7167,0x715C,0x716C,0x7166,0x714C,
+0x7165,0x715E,0x7146,0x7168,0x7156,0x723A,0x7252,0x7337,
+0x7345,0x733F,0x733E,0x746F,0x745A,0x7455,0x745F,0x745E,
+0x7441,0x743F,0x7459,0x745B,0x745C,0x7576,0x7578,0x7600,
+0x75F0,0x7601,0x75F2,0x75F1,0x75FA,0x75FF,0x75F4,0x75F3,
+0x76DE,0x76DF,0x775B,0x776B,0x7766,0x775E,0x7763, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7779,0x776A,0x776C,0x775C,0x7765,0x7768,0x7762,0x77EE,
+0x788E,0x78B0,0x7897,0x7898,0x788C,0x7889,0x787C,0x7891,
+0x7893,0x787F,0x797A,0x797F,0x7981,0x842C,0x79BD,0x7A1C,
+0x7A1A,0x7A20,0x7A14,0x7A1F,0x7A1E,0x7A9F,0x7AA0,0x7B77,
+0x7BC0,0x7B60,0x7B6E,0x7B67,0x7CB1,0x7CB3,0x7CB5,0x7D93,
+0x7D79,0x7D91,0x7D81,0x7D8F,0x7D5B,0x7F6E,0x7F69,0x7F6A,
+0x7F72,0x7FA9,0x7FA8,0x7FA4,0x8056,0x8058,0x8086,0x8084,
+0x8171,0x8170,0x8178,0x8165,0x816E,0x8173,0x816B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8179,0x817A,0x8166,0x8205,0x8247,0x8482,0x8477,
+0x843D,0x8431,0x8475,0x8466,0x846B,0x8449,0x846C,0x845B,
+0x843C,0x8435,0x8461,0x8463,0x8469,0x846D,0x8446,0x865E,
+0x865C,0x865F,0x86F9,0x8713,0x8708,0x8707,0x8700,0x86FE,
+0x86FB,0x8702,0x8703,0x8706,0x870A,0x8859,0x88DF,0x88D4,
+0x88D9,0x88DC,0x88D8,0x88DD,0x88E1,0x88CA,0x88D5,0x88D2,
+0x899C,0x89E3,0x8A6B,0x8A72,0x8A73,0x8A66,0x8A69,0x8A70,
+0x8A87,0x8A7C,0x8A63,0x8AA0,0x8A71,0x8A85,0x8A6D,0x8A62,
+0x8A6E,0x8A6C,0x8A79,0x8A7B,0x8A3E,0x8A68,0x8C62,0x8C8A,
+0x8C89,0x8CCA,0x8CC7,0x8CC8,0x8CC4,0x8CB2,0x8CC3,0x8CC2,
+0x8CC5,0x8DE1,0x8DDF,0x8DE8,0x8DEF,0x8DF3,0x8DFA,0x8DEA,
+0x8DE4,0x8DE6,0x8EB2,0x8F03,0x8F09,0x8EFE,0x8F0A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8F9F,0x8FB2,0x904B,0x904A,0x9053,0x9042,0x9054,0x903C,
+0x9055,0x9050,0x9047,0x904F,0x904E,0x904D,0x9051,0x903E,
+0x9041,0x9112,0x9117,0x916C,0x916A,0x9169,0x91C9,0x9237,
+0x9257,0x9238,0x923D,0x9240,0x923E,0x925B,0x924B,0x9264,
+0x9251,0x9234,0x9249,0x924D,0x9245,0x9239,0x923F,0x925A,
+0x9598,0x9698,0x9694,0x9695,0x96CD,0x96CB,0x96C9,0x96CA,
+0x96F7,0x96FB,0x96F9,0x96F6,0x9756,0x9774,0x9776,0x9810,
+0x9811,0x9813,0x980A,0x9812,0x980C,0x98FC,0x98F4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x98FD,0x98FE,0x99B3,0x99B1,0x99B4,0x9AE1,0x9CE9,
+0x9E82,0x9F0E,0x9F13,0x9F20,0x50E7,0x50EE,0x50E5,0x50D6,
+0x50ED,0x50DA,0x50D5,0x50CF,0x50D1,0x50F1,0x50CE,0x50E9,
+0x5162,0x51F3,0x5283,0x5282,0x5331,0x53AD,0x55FE,0x5600,
+0x561B,0x5617,0x55FD,0x5614,0x5606,0x5609,0x560D,0x560E,
+0x55F7,0x5616,0x561F,0x5608,0x5610,0x55F6,0x5718,0x5716,
+0x5875,0x587E,0x5883,0x5893,0x588A,0x5879,0x5885,0x587D,
+0x58FD,0x5925,0x5922,0x5924,0x596A,0x5969,0x5AE1,0x5AE6,
+0x5AE9,0x5AD7,0x5AD6,0x5AD8,0x5AE3,0x5B75,0x5BDE,0x5BE7,
+0x5BE1,0x5BE5,0x5BE6,0x5BE8,0x5BE2,0x5BE4,0x5BDF,0x5C0D,
+0x5C62,0x5D84,0x5D87,0x5E5B,0x5E63,0x5E55,0x5E57,0x5E54,
+0x5ED3,0x5ED6,0x5F0A,0x5F46,0x5F70,0x5FB9,0x6147, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x613F,0x614B,0x6177,0x6162,0x6163,0x615F,0x615A,0x6158,
+0x6175,0x622A,0x6487,0x6458,0x6454,0x64A4,0x6478,0x645F,
+0x647A,0x6451,0x6467,0x6434,0x646D,0x647B,0x6572,0x65A1,
+0x65D7,0x65D6,0x66A2,0x66A8,0x669D,0x699C,0x69A8,0x6995,
+0x69C1,0x69AE,0x69D3,0x69CB,0x699B,0x69B7,0x69BB,0x69AB,
+0x69B4,0x69D0,0x69CD,0x69AD,0x69CC,0x69A6,0x69C3,0x69A3,
+0x6B49,0x6B4C,0x6C33,0x6F33,0x6F14,0x6EFE,0x6F13,0x6EF4,
+0x6F29,0x6F3E,0x6F20,0x6F2C,0x6F0F,0x6F02,0x6F22, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6EFF,0x6EEF,0x6F06,0x6F31,0x6F38,0x6F32,0x6F23,
+0x6F15,0x6F2B,0x6F2F,0x6F88,0x6F2A,0x6EEC,0x6F01,0x6EF2,
+0x6ECC,0x6EF7,0x7194,0x7199,0x717D,0x718A,0x7184,0x7192,
+0x723E,0x7292,0x7296,0x7344,0x7350,0x7464,0x7463,0x746A,
+0x7470,0x746D,0x7504,0x7591,0x7627,0x760D,0x760B,0x7609,
+0x7613,0x76E1,0x76E3,0x7784,0x777D,0x777F,0x7761,0x78C1,
+0x789F,0x78A7,0x78B3,0x78A9,0x78A3,0x798E,0x798F,0x798D,
+0x7A2E,0x7A31,0x7AAA,0x7AA9,0x7AED,0x7AEF,0x7BA1,0x7B95,
+0x7B8B,0x7B75,0x7B97,0x7B9D,0x7B94,0x7B8F,0x7BB8,0x7B87,
+0x7B84,0x7CB9,0x7CBD,0x7CBE,0x7DBB,0x7DB0,0x7D9C,0x7DBD,
+0x7DBE,0x7DA0,0x7DCA,0x7DB4,0x7DB2,0x7DB1,0x7DBA,0x7DA2,
+0x7DBF,0x7DB5,0x7DB8,0x7DAD,0x7DD2,0x7DC7,0x7DAC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7F70,0x7FE0,0x7FE1,0x7FDF,0x805E,0x805A,0x8087,0x8150,
+0x8180,0x818F,0x8188,0x818A,0x817F,0x8182,0x81E7,0x81FA,
+0x8207,0x8214,0x821E,0x824B,0x84C9,0x84BF,0x84C6,0x84C4,
+0x8499,0x849E,0x84B2,0x849C,0x84CB,0x84B8,0x84C0,0x84D3,
+0x8490,0x84BC,0x84D1,0x84CA,0x873F,0x871C,0x873B,0x8722,
+0x8725,0x8734,0x8718,0x8755,0x8737,0x8729,0x88F3,0x8902,
+0x88F4,0x88F9,0x88F8,0x88FD,0x88E8,0x891A,0x88EF,0x8AA6,
+0x8A8C,0x8A9E,0x8AA3,0x8A8D,0x8AA1,0x8A93,0x8AA4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8AAA,0x8AA5,0x8AA8,0x8A98,0x8A91,0x8A9A,0x8AA7,
+0x8C6A,0x8C8D,0x8C8C,0x8CD3,0x8CD1,0x8CD2,0x8D6B,0x8D99,
+0x8D95,0x8DFC,0x8F14,0x8F12,0x8F15,0x8F13,0x8FA3,0x9060,
+0x9058,0x905C,0x9063,0x9059,0x905E,0x9062,0x905D,0x905B,
+0x9119,0x9118,0x911E,0x9175,0x9178,0x9177,0x9174,0x9278,
+0x9280,0x9285,0x9298,0x9296,0x927B,0x9293,0x929C,0x92A8,
+0x927C,0x9291,0x95A1,0x95A8,0x95A9,0x95A3,0x95A5,0x95A4,
+0x9699,0x969C,0x969B,0x96CC,0x96D2,0x9700,0x977C,0x9785,
+0x97F6,0x9817,0x9818,0x98AF,0x98B1,0x9903,0x9905,0x990C,
+0x9909,0x99C1,0x9AAF,0x9AB0,0x9AE6,0x9B41,0x9B42,0x9CF4,
+0x9CF6,0x9CF3,0x9EBC,0x9F3B,0x9F4A,0x5104,0x5100,0x50FB,
+0x50F5,0x50F9,0x5102,0x5108,0x5109,0x5105,0x51DC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5287,0x5288,0x5289,0x528D,0x528A,0x52F0,0x53B2,0x562E,
+0x563B,0x5639,0x5632,0x563F,0x5634,0x5629,0x5653,0x564E,
+0x5657,0x5674,0x5636,0x562F,0x5630,0x5880,0x589F,0x589E,
+0x58B3,0x589C,0x58AE,0x58A9,0x58A6,0x596D,0x5B09,0x5AFB,
+0x5B0B,0x5AF5,0x5B0C,0x5B08,0x5BEE,0x5BEC,0x5BE9,0x5BEB,
+0x5C64,0x5C65,0x5D9D,0x5D94,0x5E62,0x5E5F,0x5E61,0x5EE2,
+0x5EDA,0x5EDF,0x5EDD,0x5EE3,0x5EE0,0x5F48,0x5F71,0x5FB7,
+0x5FB5,0x6176,0x6167,0x616E,0x615D,0x6155,0x6182, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x617C,0x6170,0x616B,0x617E,0x61A7,0x6190,0x61AB,
+0x618E,0x61AC,0x619A,0x61A4,0x6194,0x61AE,0x622E,0x6469,
+0x646F,0x6479,0x649E,0x64B2,0x6488,0x6490,0x64B0,0x64A5,
+0x6493,0x6495,0x64A9,0x6492,0x64AE,0x64AD,0x64AB,0x649A,
+0x64AC,0x6499,0x64A2,0x64B3,0x6575,0x6577,0x6578,0x66AE,
+0x66AB,0x66B4,0x66B1,0x6A23,0x6A1F,0x69E8,0x6A01,0x6A1E,
+0x6A19,0x69FD,0x6A21,0x6A13,0x6A0A,0x69F3,0x6A02,0x6A05,
+0x69ED,0x6A11,0x6B50,0x6B4E,0x6BA4,0x6BC5,0x6BC6,0x6F3F,
+0x6F7C,0x6F84,0x6F51,0x6F66,0x6F54,0x6F86,0x6F6D,0x6F5B,
+0x6F78,0x6F6E,0x6F8E,0x6F7A,0x6F70,0x6F64,0x6F97,0x6F58,
+0x6ED5,0x6F6F,0x6F60,0x6F5F,0x719F,0x71AC,0x71B1,0x71A8,
+0x7256,0x729B,0x734E,0x7357,0x7469,0x748B,0x7483, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x747E,0x7480,0x757F,0x7620,0x7629,0x761F,0x7624,0x7626,
+0x7621,0x7622,0x769A,0x76BA,0x76E4,0x778E,0x7787,0x778C,
+0x7791,0x778B,0x78CB,0x78C5,0x78BA,0x78CA,0x78BE,0x78D5,
+0x78BC,0x78D0,0x7A3F,0x7A3C,0x7A40,0x7A3D,0x7A37,0x7A3B,
+0x7AAF,0x7AAE,0x7BAD,0x7BB1,0x7BC4,0x7BB4,0x7BC6,0x7BC7,
+0x7BC1,0x7BA0,0x7BCC,0x7CCA,0x7DE0,0x7DF4,0x7DEF,0x7DFB,
+0x7DD8,0x7DEC,0x7DDD,0x7DE8,0x7DE3,0x7DDA,0x7DDE,0x7DE9,
+0x7D9E,0x7DD9,0x7DF2,0x7DF9,0x7F75,0x7F77,0x7FAF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7FE9,0x8026,0x819B,0x819C,0x819D,0x81A0,0x819A,
+0x8198,0x8517,0x853D,0x851A,0x84EE,0x852C,0x852D,0x8513,
+0x8511,0x8523,0x8521,0x8514,0x84EC,0x8525,0x84FF,0x8506,
+0x8782,0x8774,0x8776,0x8760,0x8766,0x8778,0x8768,0x8759,
+0x8757,0x874C,0x8753,0x885B,0x885D,0x8910,0x8907,0x8912,
+0x8913,0x8915,0x890A,0x8ABC,0x8AD2,0x8AC7,0x8AC4,0x8A95,
+0x8ACB,0x8AF8,0x8AB2,0x8AC9,0x8AC2,0x8ABF,0x8AB0,0x8AD6,
+0x8ACD,0x8AB6,0x8AB9,0x8ADB,0x8C4C,0x8C4E,0x8C6C,0x8CE0,
+0x8CDE,0x8CE6,0x8CE4,0x8CEC,0x8CED,0x8CE2,0x8CE3,0x8CDC,
+0x8CEA,0x8CE1,0x8D6D,0x8D9F,0x8DA3,0x8E2B,0x8E10,0x8E1D,
+0x8E22,0x8E0F,0x8E29,0x8E1F,0x8E21,0x8E1E,0x8EBA,0x8F1D,
+0x8F1B,0x8F1F,0x8F29,0x8F26,0x8F2A,0x8F1C,0x8F1E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8F25,0x9069,0x906E,0x9068,0x906D,0x9077,0x9130,0x912D,
+0x9127,0x9131,0x9187,0x9189,0x918B,0x9183,0x92C5,0x92BB,
+0x92B7,0x92EA,0x92AC,0x92E4,0x92C1,0x92B3,0x92BC,0x92D2,
+0x92C7,0x92F0,0x92B2,0x95AD,0x95B1,0x9704,0x9706,0x9707,
+0x9709,0x9760,0x978D,0x978B,0x978F,0x9821,0x982B,0x981C,
+0x98B3,0x990A,0x9913,0x9912,0x9918,0x99DD,0x99D0,0x99DF,
+0x99DB,0x99D1,0x99D5,0x99D2,0x99D9,0x9AB7,0x9AEE,0x9AEF,
+0x9B27,0x9B45,0x9B44,0x9B77,0x9B6F,0x9D06,0x9D09, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9D03,0x9EA9,0x9EBE,0x9ECE,0x58A8,0x9F52,0x5112,
+0x5118,0x5114,0x5110,0x5115,0x5180,0x51AA,0x51DD,0x5291,
+0x5293,0x52F3,0x5659,0x566B,0x5679,0x5669,0x5664,0x5678,
+0x566A,0x5668,0x5665,0x5671,0x566F,0x566C,0x5662,0x5676,
+0x58C1,0x58BE,0x58C7,0x58C5,0x596E,0x5B1D,0x5B34,0x5B78,
+0x5BF0,0x5C0E,0x5F4A,0x61B2,0x6191,0x61A9,0x618A,0x61CD,
+0x61B6,0x61BE,0x61CA,0x61C8,0x6230,0x64C5,0x64C1,0x64CB,
+0x64BB,0x64BC,0x64DA,0x64C4,0x64C7,0x64C2,0x64CD,0x64BF,
+0x64D2,0x64D4,0x64BE,0x6574,0x66C6,0x66C9,0x66B9,0x66C4,
+0x66C7,0x66B8,0x6A3D,0x6A38,0x6A3A,0x6A59,0x6A6B,0x6A58,
+0x6A39,0x6A44,0x6A62,0x6A61,0x6A4B,0x6A47,0x6A35,0x6A5F,
+0x6A48,0x6B59,0x6B77,0x6C05,0x6FC2,0x6FB1,0x6FA1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6FC3,0x6FA4,0x6FC1,0x6FA7,0x6FB3,0x6FC0,0x6FB9,0x6FB6,
+0x6FA6,0x6FA0,0x6FB4,0x71BE,0x71C9,0x71D0,0x71D2,0x71C8,
+0x71D5,0x71B9,0x71CE,0x71D9,0x71DC,0x71C3,0x71C4,0x7368,
+0x749C,0x74A3,0x7498,0x749F,0x749E,0x74E2,0x750C,0x750D,
+0x7634,0x7638,0x763A,0x76E7,0x76E5,0x77A0,0x779E,0x779F,
+0x77A5,0x78E8,0x78DA,0x78EC,0x78E7,0x79A6,0x7A4D,0x7A4E,
+0x7A46,0x7A4C,0x7A4B,0x7ABA,0x7BD9,0x7C11,0x7BC9,0x7BE4,
+0x7BDB,0x7BE1,0x7BE9,0x7BE6,0x7CD5,0x7CD6,0x7E0A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7E11,0x7E08,0x7E1B,0x7E23,0x7E1E,0x7E1D,0x7E09,
+0x7E10,0x7F79,0x7FB2,0x7FF0,0x7FF1,0x7FEE,0x8028,0x81B3,
+0x81A9,0x81A8,0x81FB,0x8208,0x8258,0x8259,0x854A,0x8559,
+0x8548,0x8568,0x8569,0x8543,0x8549,0x856D,0x856A,0x855E,
+0x8783,0x879F,0x879E,0x87A2,0x878D,0x8861,0x892A,0x8932,
+0x8925,0x892B,0x8921,0x89AA,0x89A6,0x8AE6,0x8AFA,0x8AEB,
+0x8AF1,0x8B00,0x8ADC,0x8AE7,0x8AEE,0x8AFE,0x8B01,0x8B02,
+0x8AF7,0x8AED,0x8AF3,0x8AF6,0x8AFC,0x8C6B,0x8C6D,0x8C93,
+0x8CF4,0x8E44,0x8E31,0x8E34,0x8E42,0x8E39,0x8E35,0x8F3B,
+0x8F2F,0x8F38,0x8F33,0x8FA8,0x8FA6,0x9075,0x9074,0x9078,
+0x9072,0x907C,0x907A,0x9134,0x9192,0x9320,0x9336,0x92F8,
+0x9333,0x932F,0x9322,0x92FC,0x932B,0x9304,0x931A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9310,0x9326,0x9321,0x9315,0x932E,0x9319,0x95BB,0x96A7,
+0x96A8,0x96AA,0x96D5,0x970E,0x9711,0x9716,0x970D,0x9713,
+0x970F,0x975B,0x975C,0x9766,0x9798,0x9830,0x9838,0x983B,
+0x9837,0x982D,0x9839,0x9824,0x9910,0x9928,0x991E,0x991B,
+0x9921,0x991A,0x99ED,0x99E2,0x99F1,0x9AB8,0x9ABC,0x9AFB,
+0x9AED,0x9B28,0x9B91,0x9D15,0x9D23,0x9D26,0x9D28,0x9D12,
+0x9D1B,0x9ED8,0x9ED4,0x9F8D,0x9F9C,0x512A,0x511F,0x5121,
+0x5132,0x52F5,0x568E,0x5680,0x5690,0x5685,0x5687, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x568F,0x58D5,0x58D3,0x58D1,0x58CE,0x5B30,0x5B2A,
+0x5B24,0x5B7A,0x5C37,0x5C68,0x5DBC,0x5DBA,0x5DBD,0x5DB8,
+0x5E6B,0x5F4C,0x5FBD,0x61C9,0x61C2,0x61C7,0x61E6,0x61CB,
+0x6232,0x6234,0x64CE,0x64CA,0x64D8,0x64E0,0x64F0,0x64E6,
+0x64EC,0x64F1,0x64E2,0x64ED,0x6582,0x6583,0x66D9,0x66D6,
+0x6A80,0x6A94,0x6A84,0x6AA2,0x6A9C,0x6ADB,0x6AA3,0x6A7E,
+0x6A97,0x6A90,0x6AA0,0x6B5C,0x6BAE,0x6BDA,0x6C08,0x6FD8,
+0x6FF1,0x6FDF,0x6FE0,0x6FDB,0x6FE4,0x6FEB,0x6FEF,0x6F80,
+0x6FEC,0x6FE1,0x6FE9,0x6FD5,0x6FEE,0x6FF0,0x71E7,0x71DF,
+0x71EE,0x71E6,0x71E5,0x71ED,0x71EC,0x71F4,0x71E0,0x7235,
+0x7246,0x7370,0x7372,0x74A9,0x74B0,0x74A6,0x74A8,0x7646,
+0x7642,0x764C,0x76EA,0x77B3,0x77AA,0x77B0,0x77AC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x77A7,0x77AD,0x77EF,0x78F7,0x78FA,0x78F4,0x78EF,0x7901,
+0x79A7,0x79AA,0x7A57,0x7ABF,0x7C07,0x7C0D,0x7BFE,0x7BF7,
+0x7C0C,0x7BE0,0x7CE0,0x7CDC,0x7CDE,0x7CE2,0x7CDF,0x7CD9,
+0x7CDD,0x7E2E,0x7E3E,0x7E46,0x7E37,0x7E32,0x7E43,0x7E2B,
+0x7E3D,0x7E31,0x7E45,0x7E41,0x7E34,0x7E39,0x7E48,0x7E35,
+0x7E3F,0x7E2F,0x7F44,0x7FF3,0x7FFC,0x8071,0x8072,0x8070,
+0x806F,0x8073,0x81C6,0x81C3,0x81BA,0x81C2,0x81C0,0x81BF,
+0x81BD,0x81C9,0x81BE,0x81E8,0x8209,0x8271,0x85AA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8584,0x857E,0x859C,0x8591,0x8594,0x85AF,0x859B,
+0x8587,0x85A8,0x858A,0x8667,0x87C0,0x87D1,0x87B3,0x87D2,
+0x87C6,0x87AB,0x87BB,0x87BA,0x87C8,0x87CB,0x893B,0x8936,
+0x8944,0x8938,0x893D,0x89AC,0x8B0E,0x8B17,0x8B19,0x8B1B,
+0x8B0A,0x8B20,0x8B1D,0x8B04,0x8B10,0x8C41,0x8C3F,0x8C73,
+0x8CFA,0x8CFD,0x8CFC,0x8CF8,0x8CFB,0x8DA8,0x8E49,0x8E4B,
+0x8E48,0x8E4A,0x8F44,0x8F3E,0x8F42,0x8F45,0x8F3F,0x907F,
+0x907D,0x9084,0x9081,0x9082,0x9080,0x9139,0x91A3,0x919E,
+0x919C,0x934D,0x9382,0x9328,0x9375,0x934A,0x9365,0x934B,
+0x9318,0x937E,0x936C,0x935B,0x9370,0x935A,0x9354,0x95CA,
+0x95CB,0x95CC,0x95C8,0x95C6,0x96B1,0x96B8,0x96D6,0x971C,
+0x971E,0x97A0,0x97D3,0x9846,0x98B6,0x9935,0x9A01, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x99FF,0x9BAE,0x9BAB,0x9BAA,0x9BAD,0x9D3B,0x9D3F,0x9E8B,
+0x9ECF,0x9EDE,0x9EDC,0x9EDD,0x9EDB,0x9F3E,0x9F4B,0x53E2,
+0x5695,0x56AE,0x58D9,0x58D8,0x5B38,0x5F5D,0x61E3,0x6233,
+0x64F4,0x64F2,0x64FE,0x6506,0x64FA,0x64FB,0x64F7,0x65B7,
+0x66DC,0x6726,0x6AB3,0x6AAC,0x6AC3,0x6ABB,0x6AB8,0x6AC2,
+0x6AAE,0x6AAF,0x6B5F,0x6B78,0x6BAF,0x7009,0x700B,0x6FFE,
+0x7006,0x6FFA,0x7011,0x700F,0x71FB,0x71FC,0x71FE,0x71F8,
+0x7377,0x7375,0x74A7,0x74BF,0x7515,0x7656,0x7658, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7652,0x77BD,0x77BF,0x77BB,0x77BC,0x790E,0x79AE,
+0x7A61,0x7A62,0x7A60,0x7AC4,0x7AC5,0x7C2B,0x7C27,0x7C2A,
+0x7C1E,0x7C23,0x7C21,0x7CE7,0x7E54,0x7E55,0x7E5E,0x7E5A,
+0x7E61,0x7E52,0x7E59,0x7F48,0x7FF9,0x7FFB,0x8077,0x8076,
+0x81CD,0x81CF,0x820A,0x85CF,0x85A9,0x85CD,0x85D0,0x85C9,
+0x85B0,0x85BA,0x85B9,0x85A6,0x87EF,0x87EC,0x87F2,0x87E0,
+0x8986,0x89B2,0x89F4,0x8B28,0x8B39,0x8B2C,0x8B2B,0x8C50,
+0x8D05,0x8E59,0x8E63,0x8E66,0x8E64,0x8E5F,0x8E55,0x8EC0,
+0x8F49,0x8F4D,0x9087,0x9083,0x9088,0x91AB,0x91AC,0x91D0,
+0x9394,0x938A,0x9396,0x93A2,0x93B3,0x93AE,0x93AC,0x93B0,
+0x9398,0x939A,0x9397,0x95D4,0x95D6,0x95D0,0x95D5,0x96E2,
+0x96DC,0x96D9,0x96DB,0x96DE,0x9724,0x97A3,0x97A6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x97AD,0x97F9,0x984D,0x984F,0x984C,0x984E,0x9853,0x98BA,
+0x993E,0x993F,0x993D,0x992E,0x99A5,0x9A0E,0x9AC1,0x9B03,
+0x9B06,0x9B4F,0x9B4E,0x9B4D,0x9BCA,0x9BC9,0x9BFD,0x9BC8,
+0x9BC0,0x9D51,0x9D5D,0x9D60,0x9EE0,0x9F15,0x9F2C,0x5133,
+0x56A5,0x58DE,0x58DF,0x58E2,0x5BF5,0x9F90,0x5EEC,0x61F2,
+0x61F7,0x61F6,0x61F5,0x6500,0x650F,0x66E0,0x66DD,0x6AE5,
+0x6ADD,0x6ADA,0x6AD3,0x701B,0x701F,0x7028,0x701A,0x701D,
+0x7015,0x7018,0x7206,0x720D,0x7258,0x72A2,0x7378, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x737A,0x74BD,0x74CA,0x74E3,0x7587,0x7586,0x765F,
+0x7661,0x77C7,0x7919,0x79B1,0x7A6B,0x7A69,0x7C3E,0x7C3F,
+0x7C38,0x7C3D,0x7C37,0x7C40,0x7E6B,0x7E6D,0x7E79,0x7E69,
+0x7E6A,0x7F85,0x7E73,0x7FB6,0x7FB9,0x7FB8,0x81D8,0x85E9,
+0x85DD,0x85EA,0x85D5,0x85E4,0x85E5,0x85F7,0x87FB,0x8805,
+0x880D,0x87F9,0x87FE,0x8960,0x895F,0x8956,0x895E,0x8B41,
+0x8B5C,0x8B58,0x8B49,0x8B5A,0x8B4E,0x8B4F,0x8B46,0x8B59,
+0x8D08,0x8D0A,0x8E7C,0x8E72,0x8E87,0x8E76,0x8E6C,0x8E7A,
+0x8E74,0x8F54,0x8F4E,0x8FAD,0x908A,0x908B,0x91B1,0x91AE,
+0x93E1,0x93D1,0x93DF,0x93C3,0x93C8,0x93DC,0x93DD,0x93D6,
+0x93E2,0x93CD,0x93D8,0x93E4,0x93D7,0x93E8,0x95DC,0x96B4,
+0x96E3,0x972A,0x9727,0x9761,0x97DC,0x97FB,0x985E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9858,0x985B,0x98BC,0x9945,0x9949,0x9A16,0x9A19,0x9B0D,
+0x9BE8,0x9BE7,0x9BD6,0x9BDB,0x9D89,0x9D61,0x9D72,0x9D6A,
+0x9D6C,0x9E92,0x9E97,0x9E93,0x9EB4,0x52F8,0x56A8,0x56B7,
+0x56B6,0x56B4,0x56BC,0x58E4,0x5B40,0x5B43,0x5B7D,0x5BF6,
+0x5DC9,0x61F8,0x61FA,0x6518,0x6514,0x6519,0x66E6,0x6727,
+0x6AEC,0x703E,0x7030,0x7032,0x7210,0x737B,0x74CF,0x7662,
+0x7665,0x7926,0x792A,0x792C,0x792B,0x7AC7,0x7AF6,0x7C4C,
+0x7C43,0x7C4D,0x7CEF,0x7CF0,0x8FAE,0x7E7D,0x7E7C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7E82,0x7F4C,0x8000,0x81DA,0x8266,0x85FB,0x85F9,
+0x8611,0x85FA,0x8606,0x860B,0x8607,0x860A,0x8814,0x8815,
+0x8964,0x89BA,0x89F8,0x8B70,0x8B6C,0x8B66,0x8B6F,0x8B5F,
+0x8B6B,0x8D0F,0x8D0D,0x8E89,0x8E81,0x8E85,0x8E82,0x91B4,
+0x91CB,0x9418,0x9403,0x93FD,0x95E1,0x9730,0x98C4,0x9952,
+0x9951,0x99A8,0x9A2B,0x9A30,0x9A37,0x9A35,0x9C13,0x9C0D,
+0x9E79,0x9EB5,0x9EE8,0x9F2F,0x9F5F,0x9F63,0x9F61,0x5137,
+0x5138,0x56C1,0x56C0,0x56C2,0x5914,0x5C6C,0x5DCD,0x61FC,
+0x61FE,0x651D,0x651C,0x6595,0x66E9,0x6AFB,0x6B04,0x6AFA,
+0x6BB2,0x704C,0x721B,0x72A7,0x74D6,0x74D4,0x7669,0x77D3,
+0x7C50,0x7E8F,0x7E8C,0x7FBC,0x8617,0x862D,0x861A,0x8823,
+0x8822,0x8821,0x881F,0x896A,0x896C,0x89BD,0x8B74, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B77,0x8B7D,0x8D13,0x8E8A,0x8E8D,0x8E8B,0x8F5F,0x8FAF,
+0x91BA,0x942E,0x9433,0x9435,0x943A,0x9438,0x9432,0x942B,
+0x95E2,0x9738,0x9739,0x9732,0x97FF,0x9867,0x9865,0x9957,
+0x9A45,0x9A43,0x9A40,0x9A3E,0x9ACF,0x9B54,0x9B51,0x9C2D,
+0x9C25,0x9DAF,0x9DB4,0x9DC2,0x9DB8,0x9E9D,0x9EEF,0x9F19,
+0x9F5C,0x9F66,0x9F67,0x513C,0x513B,0x56C8,0x56CA,0x56C9,
+0x5B7F,0x5DD4,0x5DD2,0x5F4E,0x61FF,0x6524,0x6B0A,0x6B61,
+0x7051,0x7058,0x7380,0x74E4,0x758A,0x766E,0x766C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x79B3,0x7C60,0x7C5F,0x807E,0x807D,0x81DF,0x8972,
+0x896F,0x89FC,0x8B80,0x8D16,0x8D17,0x8E91,0x8E93,0x8F61,
+0x9148,0x9444,0x9451,0x9452,0x973D,0x973E,0x97C3,0x97C1,
+0x986B,0x9955,0x9A55,0x9A4D,0x9AD2,0x9B1A,0x9C49,0x9C31,
+0x9C3E,0x9C3B,0x9DD3,0x9DD7,0x9F34,0x9F6C,0x9F6A,0x9F94,
+0x56CC,0x5DD6,0x6200,0x6523,0x652B,0x652A,0x66EC,0x6B10,
+0x74DA,0x7ACA,0x7C64,0x7C63,0x7C65,0x7E93,0x7E96,0x7E94,
+0x81E2,0x8638,0x863F,0x8831,0x8B8A,0x9090,0x908F,0x9463,
+0x9460,0x9464,0x9768,0x986F,0x995C,0x9A5A,0x9A5B,0x9A57,
+0x9AD3,0x9AD4,0x9AD1,0x9C54,0x9C57,0x9C56,0x9DE5,0x9E9F,
+0x9EF4,0x56D1,0x58E9,0x652C,0x705E,0x7671,0x7672,0x77D7,
+0x7F50,0x7F88,0x8836,0x8839,0x8862,0x8B93,0x8B92, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B96,0x8277,0x8D1B,0x91C0,0x946A,0x9742,0x9748,0x9744,
+0x97C6,0x9870,0x9A5F,0x9B22,0x9B58,0x9C5F,0x9DF9,0x9DFA,
+0x9E7C,0x9E7D,0x9F07,0x9F77,0x9F72,0x5EF3,0x6B16,0x7063,
+0x7C6C,0x7C6E,0x883B,0x89C0,0x8EA1,0x91C1,0x9472,0x9470,
+0x9871,0x995E,0x9AD6,0x9B23,0x9ECC,0x7064,0x77DA,0x8B9A,
+0x9477,0x97C9,0x9A62,0x9A65,0x7E9C,0x8B9C,0x8EAA,0x91C5,
+0x947D,0x947E,0x947C,0x9C77,0x9C78,0x9EF7,0x8C54,0x947F,
+0x9E1A,0x7228,0x9A6A,0x9B31,0x9E1B,0x9E1E,0x7C72, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x30FE,0x309D,0x309E,0x3005,0x3041,0x3042,0x3043,
+0x3044,0x3045,0x3046,0x3047,0x3048,0x3049,0x304A,0x304B,
+0x304C,0x304D,0x304E,0x304F,0x3050,0x3051,0x3052,0x3053,
+0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,0x305A,0x305B,
+0x305C,0x305D,0x305E,0x305F,0x3060,0x3061,0x3062,0x3063,
+0x3064,0x3065,0x3066,0x3067,0x3068,0x3069,0x306A,0x306B,
+0x306C,0x306D,0x306E,0x306F,0x3070,0x3071,0x3072,0x3073,
+0x3074,0x3075,0x3076,0x3077,0x3078,0x3079,0x307A,0x307B,
+0x307C,0x307D,0x307E,0x307F,0x3080,0x3081,0x3082,0x3083,
+0x3084,0x3085,0x3086,0x3087,0x3088,0x3089,0x308A,0x308B,
+0x308C,0x308D,0x308E,0x308F,0x3090,0x3091,0x3092,0x3093,
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x30A8,0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,
+0x30B0,0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,
+0x30B8,0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,
+0x30C0,0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,
+0x30C8,0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,
+0x30D0,0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,
+0x30D8,0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,
+0x30E0,0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x30E7,0x30E8,0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,
+0x30EE,0x30EF,0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,
+0x30F6,0x0414,0x0415,0x0401,0x0416,0x0417,0x0418,0x0419,
+0x041A,0x041B,0x041C,0x0423,0x0424,0x0425,0x0426,0x0427,
+0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,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,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,
+0x2467,0x2468,0x2469,0x2474,0x2475,0x2476,0x2477,0x2478,
+0x2479,0x247A,0x247B,0x247C,0x247D};
+
+/* page 1 0xC940-0xF9D5 */
+static uint16 tab_big5_uni1[]={
+0x4E42,0x4E5C,0x51F5,0x531A,0x5382,0x4E07,0x4E0C,0x4E47,
+0x4E8D,0x56D7,0xFA0C,0x5C6E,0x5F73,0x4E0F,0x5187,0x4E0E,
+0x4E2E,0x4E93,0x4EC2,0x4EC9,0x4EC8,0x5198,0x52FC,0x536C,
+0x53B9,0x5720,0x5903,0x592C,0x5C10,0x5DFF,0x65E1,0x6BB3,
+0x6BCC,0x6C14,0x723F,0x4E31,0x4E3C,0x4EE8,0x4EDC,0x4EE9,
+0x4EE1,0x4EDD,0x4EDA,0x520C,0x531C,0x534C,0x5722,0x5723,
+0x5917,0x592F,0x5B81,0x5B84,0x5C12,0x5C3B,0x5C74,0x5C73,
+0x5E04,0x5E80,0x5E82,0x5FC9,0x6209,0x6250,0x6C15, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C36,0x6C43,0x6C3F,0x6C3B,0x72AE,0x72B0,0x738A,
+0x79B8,0x808A,0x961E,0x4F0E,0x4F18,0x4F2C,0x4EF5,0x4F14,
+0x4EF1,0x4F00,0x4EF7,0x4F08,0x4F1D,0x4F02,0x4F05,0x4F22,
+0x4F13,0x4F04,0x4EF4,0x4F12,0x51B1,0x5213,0x5209,0x5210,
+0x52A6,0x5322,0x531F,0x534D,0x538A,0x5407,0x56E1,0x56DF,
+0x572E,0x572A,0x5734,0x593C,0x5980,0x597C,0x5985,0x597B,
+0x597E,0x5977,0x597F,0x5B56,0x5C15,0x5C25,0x5C7C,0x5C7A,
+0x5C7B,0x5C7E,0x5DDF,0x5E75,0x5E84,0x5F02,0x5F1A,0x5F74,
+0x5FD5,0x5FD4,0x5FCF,0x625C,0x625E,0x6264,0x6261,0x6266,
+0x6262,0x6259,0x6260,0x625A,0x6265,0x65EF,0x65EE,0x673E,
+0x6739,0x6738,0x673B,0x673A,0x673F,0x673C,0x6733,0x6C18,
+0x6C46,0x6C52,0x6C5C,0x6C4F,0x6C4A,0x6C54,0x6C4B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C4C,0x7071,0x725E,0x72B4,0x72B5,0x738E,0x752A,0x767F,
+0x7A75,0x7F51,0x8278,0x827C,0x8280,0x827D,0x827F,0x864D,
+0x897E,0x9099,0x9097,0x9098,0x909B,0x9094,0x9622,0x9624,
+0x9620,0x9623,0x4F56,0x4F3B,0x4F62,0x4F49,0x4F53,0x4F64,
+0x4F3E,0x4F67,0x4F52,0x4F5F,0x4F41,0x4F58,0x4F2D,0x4F33,
+0x4F3F,0x4F61,0x518F,0x51B9,0x521C,0x521E,0x5221,0x52AD,
+0x52AE,0x5309,0x5363,0x5372,0x538E,0x538F,0x5430,0x5437,
+0x542A,0x5454,0x5445,0x5419,0x541C,0x5425,0x5418, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x543D,0x544F,0x5441,0x5428,0x5424,0x5447,0x56EE,
+0x56E7,0x56E5,0x5741,0x5745,0x574C,0x5749,0x574B,0x5752,
+0x5906,0x5940,0x59A6,0x5998,0x59A0,0x5997,0x598E,0x59A2,
+0x5990,0x598F,0x59A7,0x59A1,0x5B8E,0x5B92,0x5C28,0x5C2A,
+0x5C8D,0x5C8F,0x5C88,0x5C8B,0x5C89,0x5C92,0x5C8A,0x5C86,
+0x5C93,0x5C95,0x5DE0,0x5E0A,0x5E0E,0x5E8B,0x5E89,0x5E8C,
+0x5E88,0x5E8D,0x5F05,0x5F1D,0x5F78,0x5F76,0x5FD2,0x5FD1,
+0x5FD0,0x5FED,0x5FE8,0x5FEE,0x5FF3,0x5FE1,0x5FE4,0x5FE3,
+0x5FFA,0x5FEF,0x5FF7,0x5FFB,0x6000,0x5FF4,0x623A,0x6283,
+0x628C,0x628E,0x628F,0x6294,0x6287,0x6271,0x627B,0x627A,
+0x6270,0x6281,0x6288,0x6277,0x627D,0x6272,0x6274,0x6537,
+0x65F0,0x65F4,0x65F3,0x65F2,0x65F5,0x6745,0x6747, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6759,0x6755,0x674C,0x6748,0x675D,0x674D,0x675A,0x674B,
+0x6BD0,0x6C19,0x6C1A,0x6C78,0x6C67,0x6C6B,0x6C84,0x6C8B,
+0x6C8F,0x6C71,0x6C6F,0x6C69,0x6C9A,0x6C6D,0x6C87,0x6C95,
+0x6C9C,0x6C66,0x6C73,0x6C65,0x6C7B,0x6C8E,0x7074,0x707A,
+0x7263,0x72BF,0x72BD,0x72C3,0x72C6,0x72C1,0x72BA,0x72C5,
+0x7395,0x7397,0x7393,0x7394,0x7392,0x753A,0x7539,0x7594,
+0x7595,0x7681,0x793D,0x8034,0x8095,0x8099,0x8090,0x8092,
+0x809C,0x8290,0x828F,0x8285,0x828E,0x8291,0x8293, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x828A,0x8283,0x8284,0x8C78,0x8FC9,0x8FBF,0x909F,
+0x90A1,0x90A5,0x909E,0x90A7,0x90A0,0x9630,0x9628,0x962F,
+0x962D,0x4E33,0x4F98,0x4F7C,0x4F85,0x4F7D,0x4F80,0x4F87,
+0x4F76,0x4F74,0x4F89,0x4F84,0x4F77,0x4F4C,0x4F97,0x4F6A,
+0x4F9A,0x4F79,0x4F81,0x4F78,0x4F90,0x4F9C,0x4F94,0x4F9E,
+0x4F92,0x4F82,0x4F95,0x4F6B,0x4F6E,0x519E,0x51BC,0x51BE,
+0x5235,0x5232,0x5233,0x5246,0x5231,0x52BC,0x530A,0x530B,
+0x533C,0x5392,0x5394,0x5487,0x547F,0x5481,0x5491,0x5482,
+0x5488,0x546B,0x547A,0x547E,0x5465,0x546C,0x5474,0x5466,
+0x548D,0x546F,0x5461,0x5460,0x5498,0x5463,0x5467,0x5464,
+0x56F7,0x56F9,0x576F,0x5772,0x576D,0x576B,0x5771,0x5770,
+0x5776,0x5780,0x5775,0x577B,0x5773,0x5774,0x5762, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5768,0x577D,0x590C,0x5945,0x59B5,0x59BA,0x59CF,0x59CE,
+0x59B2,0x59CC,0x59C1,0x59B6,0x59BC,0x59C3,0x59D6,0x59B1,
+0x59BD,0x59C0,0x59C8,0x59B4,0x59C7,0x5B62,0x5B65,0x5B93,
+0x5B95,0x5C44,0x5C47,0x5CAE,0x5CA4,0x5CA0,0x5CB5,0x5CAF,
+0x5CA8,0x5CAC,0x5C9F,0x5CA3,0x5CAD,0x5CA2,0x5CAA,0x5CA7,
+0x5C9D,0x5CA5,0x5CB6,0x5CB0,0x5CA6,0x5E17,0x5E14,0x5E19,
+0x5F28,0x5F22,0x5F23,0x5F24,0x5F54,0x5F82,0x5F7E,0x5F7D,
+0x5FDE,0x5FE5,0x602D,0x6026,0x6019,0x6032,0x600B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6034,0x600A,0x6017,0x6033,0x601A,0x601E,0x602C,
+0x6022,0x600D,0x6010,0x602E,0x6013,0x6011,0x600C,0x6009,
+0x601C,0x6214,0x623D,0x62AD,0x62B4,0x62D1,0x62BE,0x62AA,
+0x62B6,0x62CA,0x62AE,0x62B3,0x62AF,0x62BB,0x62A9,0x62B0,
+0x62B8,0x653D,0x65A8,0x65BB,0x6609,0x65FC,0x6604,0x6612,
+0x6608,0x65FB,0x6603,0x660B,0x660D,0x6605,0x65FD,0x6611,
+0x6610,0x66F6,0x670A,0x6785,0x676C,0x678E,0x6792,0x6776,
+0x677B,0x6798,0x6786,0x6784,0x6774,0x678D,0x678C,0x677A,
+0x679F,0x6791,0x6799,0x6783,0x677D,0x6781,0x6778,0x6779,
+0x6794,0x6B25,0x6B80,0x6B7E,0x6BDE,0x6C1D,0x6C93,0x6CEC,
+0x6CEB,0x6CEE,0x6CD9,0x6CB6,0x6CD4,0x6CAD,0x6CE7,0x6CB7,
+0x6CD0,0x6CC2,0x6CBA,0x6CC3,0x6CC6,0x6CED,0x6CF2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6CD2,0x6CDD,0x6CB4,0x6C8A,0x6C9D,0x6C80,0x6CDE,0x6CC0,
+0x6D30,0x6CCD,0x6CC7,0x6CB0,0x6CF9,0x6CCF,0x6CE9,0x6CD1,
+0x7094,0x7098,0x7085,0x7093,0x7086,0x7084,0x7091,0x7096,
+0x7082,0x709A,0x7083,0x726A,0x72D6,0x72CB,0x72D8,0x72C9,
+0x72DC,0x72D2,0x72D4,0x72DA,0x72CC,0x72D1,0x73A4,0x73A1,
+0x73AD,0x73A6,0x73A2,0x73A0,0x73AC,0x739D,0x74DD,0x74E8,
+0x753F,0x7540,0x753E,0x758C,0x7598,0x76AF,0x76F3,0x76F1,
+0x76F0,0x76F5,0x77F8,0x77FC,0x77F9,0x77FB,0x77FA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x77F7,0x7942,0x793F,0x79C5,0x7A78,0x7A7B,0x7AFB,
+0x7C75,0x7CFD,0x8035,0x808F,0x80AE,0x80A3,0x80B8,0x80B5,
+0x80AD,0x8220,0x82A0,0x82C0,0x82AB,0x829A,0x8298,0x829B,
+0x82B5,0x82A7,0x82AE,0x82BC,0x829E,0x82BA,0x82B4,0x82A8,
+0x82A1,0x82A9,0x82C2,0x82A4,0x82C3,0x82B6,0x82A2,0x8670,
+0x866F,0x866D,0x866E,0x8C56,0x8FD2,0x8FCB,0x8FD3,0x8FCD,
+0x8FD6,0x8FD5,0x8FD7,0x90B2,0x90B4,0x90AF,0x90B3,0x90B0,
+0x9639,0x963D,0x963C,0x963A,0x9643,0x4FCD,0x4FC5,0x4FD3,
+0x4FB2,0x4FC9,0x4FCB,0x4FC1,0x4FD4,0x4FDC,0x4FD9,0x4FBB,
+0x4FB3,0x4FDB,0x4FC7,0x4FD6,0x4FBA,0x4FC0,0x4FB9,0x4FEC,
+0x5244,0x5249,0x52C0,0x52C2,0x533D,0x537C,0x5397,0x5396,
+0x5399,0x5398,0x54BA,0x54A1,0x54AD,0x54A5,0x54CF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x54C3,0x830D,0x54B7,0x54AE,0x54D6,0x54B6,0x54C5,0x54C6,
+0x54A0,0x5470,0x54BC,0x54A2,0x54BE,0x5472,0x54DE,0x54B0,
+0x57B5,0x579E,0x579F,0x57A4,0x578C,0x5797,0x579D,0x579B,
+0x5794,0x5798,0x578F,0x5799,0x57A5,0x579A,0x5795,0x58F4,
+0x590D,0x5953,0x59E1,0x59DE,0x59EE,0x5A00,0x59F1,0x59DD,
+0x59FA,0x59FD,0x59FC,0x59F6,0x59E4,0x59F2,0x59F7,0x59DB,
+0x59E9,0x59F3,0x59F5,0x59E0,0x59FE,0x59F4,0x59ED,0x5BA8,
+0x5C4C,0x5CD0,0x5CD8,0x5CCC,0x5CD7,0x5CCB,0x5CDB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5CDE,0x5CDA,0x5CC9,0x5CC7,0x5CCA,0x5CD6,0x5CD3,
+0x5CD4,0x5CCF,0x5CC8,0x5CC6,0x5CCE,0x5CDF,0x5CF8,0x5DF9,
+0x5E21,0x5E22,0x5E23,0x5E20,0x5E24,0x5EB0,0x5EA4,0x5EA2,
+0x5E9B,0x5EA3,0x5EA5,0x5F07,0x5F2E,0x5F56,0x5F86,0x6037,
+0x6039,0x6054,0x6072,0x605E,0x6045,0x6053,0x6047,0x6049,
+0x605B,0x604C,0x6040,0x6042,0x605F,0x6024,0x6044,0x6058,
+0x6066,0x606E,0x6242,0x6243,0x62CF,0x630D,0x630B,0x62F5,
+0x630E,0x6303,0x62EB,0x62F9,0x630F,0x630C,0x62F8,0x62F6,
+0x6300,0x6313,0x6314,0x62FA,0x6315,0x62FB,0x62F0,0x6541,
+0x6543,0x65AA,0x65BF,0x6636,0x6621,0x6632,0x6635,0x661C,
+0x6626,0x6622,0x6633,0x662B,0x663A,0x661D,0x6634,0x6639,
+0x662E,0x670F,0x6710,0x67C1,0x67F2,0x67C8,0x67BA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x67DC,0x67BB,0x67F8,0x67D8,0x67C0,0x67B7,0x67C5,0x67EB,
+0x67E4,0x67DF,0x67B5,0x67CD,0x67B3,0x67F7,0x67F6,0x67EE,
+0x67E3,0x67C2,0x67B9,0x67CE,0x67E7,0x67F0,0x67B2,0x67FC,
+0x67C6,0x67ED,0x67CC,0x67AE,0x67E6,0x67DB,0x67FA,0x67C9,
+0x67CA,0x67C3,0x67EA,0x67CB,0x6B28,0x6B82,0x6B84,0x6BB6,
+0x6BD6,0x6BD8,0x6BE0,0x6C20,0x6C21,0x6D28,0x6D34,0x6D2D,
+0x6D1F,0x6D3C,0x6D3F,0x6D12,0x6D0A,0x6CDA,0x6D33,0x6D04,
+0x6D19,0x6D3A,0x6D1A,0x6D11,0x6D00,0x6D1D,0x6D42, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6D01,0x6D18,0x6D37,0x6D03,0x6D0F,0x6D40,0x6D07,
+0x6D20,0x6D2C,0x6D08,0x6D22,0x6D09,0x6D10,0x70B7,0x709F,
+0x70BE,0x70B1,0x70B0,0x70A1,0x70B4,0x70B5,0x70A9,0x7241,
+0x7249,0x724A,0x726C,0x7270,0x7273,0x726E,0x72CA,0x72E4,
+0x72E8,0x72EB,0x72DF,0x72EA,0x72E6,0x72E3,0x7385,0x73CC,
+0x73C2,0x73C8,0x73C5,0x73B9,0x73B6,0x73B5,0x73B4,0x73EB,
+0x73BF,0x73C7,0x73BE,0x73C3,0x73C6,0x73B8,0x73CB,0x74EC,
+0x74EE,0x752E,0x7547,0x7548,0x75A7,0x75AA,0x7679,0x76C4,
+0x7708,0x7703,0x7704,0x7705,0x770A,0x76F7,0x76FB,0x76FA,
+0x77E7,0x77E8,0x7806,0x7811,0x7812,0x7805,0x7810,0x780F,
+0x780E,0x7809,0x7803,0x7813,0x794A,0x794C,0x794B,0x7945,
+0x7944,0x79D5,0x79CD,0x79CF,0x79D6,0x79CE,0x7A80, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7A7E,0x7AD1,0x7B00,0x7B01,0x7C7A,0x7C78,0x7C79,0x7C7F,
+0x7C80,0x7C81,0x7D03,0x7D08,0x7D01,0x7F58,0x7F91,0x7F8D,
+0x7FBE,0x8007,0x800E,0x800F,0x8014,0x8037,0x80D8,0x80C7,
+0x80E0,0x80D1,0x80C8,0x80C2,0x80D0,0x80C5,0x80E3,0x80D9,
+0x80DC,0x80CA,0x80D5,0x80C9,0x80CF,0x80D7,0x80E6,0x80CD,
+0x81FF,0x8221,0x8294,0x82D9,0x82FE,0x82F9,0x8307,0x82E8,
+0x8300,0x82D5,0x833A,0x82EB,0x82D6,0x82F4,0x82EC,0x82E1,
+0x82F2,0x82F5,0x830C,0x82FB,0x82F6,0x82F0,0x82EA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x82E4,0x82E0,0x82FA,0x82F3,0x82ED,0x8677,0x8674,
+0x867C,0x8673,0x8841,0x884E,0x8867,0x886A,0x8869,0x89D3,
+0x8A04,0x8A07,0x8D72,0x8FE3,0x8FE1,0x8FEE,0x8FE0,0x90F1,
+0x90BD,0x90BF,0x90D5,0x90C5,0x90BE,0x90C7,0x90CB,0x90C8,
+0x91D4,0x91D3,0x9654,0x964F,0x9651,0x9653,0x964A,0x964E,
+0x501E,0x5005,0x5007,0x5013,0x5022,0x5030,0x501B,0x4FF5,
+0x4FF4,0x5033,0x5037,0x502C,0x4FF6,0x4FF7,0x5017,0x501C,
+0x5020,0x5027,0x5035,0x502F,0x5031,0x500E,0x515A,0x5194,
+0x5193,0x51CA,0x51C4,0x51C5,0x51C8,0x51CE,0x5261,0x525A,
+0x5252,0x525E,0x525F,0x5255,0x5262,0x52CD,0x530E,0x539E,
+0x5526,0x54E2,0x5517,0x5512,0x54E7,0x54F3,0x54E4,0x551A,
+0x54FF,0x5504,0x5508,0x54EB,0x5511,0x5505,0x54F1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x550A,0x54FB,0x54F7,0x54F8,0x54E0,0x550E,0x5503,0x550B,
+0x5701,0x5702,0x57CC,0x5832,0x57D5,0x57D2,0x57BA,0x57C6,
+0x57BD,0x57BC,0x57B8,0x57B6,0x57BF,0x57C7,0x57D0,0x57B9,
+0x57C1,0x590E,0x594A,0x5A19,0x5A16,0x5A2D,0x5A2E,0x5A15,
+0x5A0F,0x5A17,0x5A0A,0x5A1E,0x5A33,0x5B6C,0x5BA7,0x5BAD,
+0x5BAC,0x5C03,0x5C56,0x5C54,0x5CEC,0x5CFF,0x5CEE,0x5CF1,
+0x5CF7,0x5D00,0x5CF9,0x5E29,0x5E28,0x5EA8,0x5EAE,0x5EAA,
+0x5EAC,0x5F33,0x5F30,0x5F67,0x605D,0x605A,0x6067, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6041,0x60A2,0x6088,0x6080,0x6092,0x6081,0x609D,
+0x6083,0x6095,0x609B,0x6097,0x6087,0x609C,0x608E,0x6219,
+0x6246,0x62F2,0x6310,0x6356,0x632C,0x6344,0x6345,0x6336,
+0x6343,0x63E4,0x6339,0x634B,0x634A,0x633C,0x6329,0x6341,
+0x6334,0x6358,0x6354,0x6359,0x632D,0x6347,0x6333,0x635A,
+0x6351,0x6338,0x6357,0x6340,0x6348,0x654A,0x6546,0x65C6,
+0x65C3,0x65C4,0x65C2,0x664A,0x665F,0x6647,0x6651,0x6712,
+0x6713,0x681F,0x681A,0x6849,0x6832,0x6833,0x683B,0x684B,
+0x684F,0x6816,0x6831,0x681C,0x6835,0x682B,0x682D,0x682F,
+0x684E,0x6844,0x6834,0x681D,0x6812,0x6814,0x6826,0x6828,
+0x682E,0x684D,0x683A,0x6825,0x6820,0x6B2C,0x6B2F,0x6B2D,
+0x6B31,0x6B34,0x6B6D,0x8082,0x6B88,0x6BE6,0x6BE4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6BE8,0x6BE3,0x6BE2,0x6BE7,0x6C25,0x6D7A,0x6D63,0x6D64,
+0x6D76,0x6D0D,0x6D61,0x6D92,0x6D58,0x6D62,0x6D6D,0x6D6F,
+0x6D91,0x6D8D,0x6DEF,0x6D7F,0x6D86,0x6D5E,0x6D67,0x6D60,
+0x6D97,0x6D70,0x6D7C,0x6D5F,0x6D82,0x6D98,0x6D2F,0x6D68,
+0x6D8B,0x6D7E,0x6D80,0x6D84,0x6D16,0x6D83,0x6D7B,0x6D7D,
+0x6D75,0x6D90,0x70DC,0x70D3,0x70D1,0x70DD,0x70CB,0x7F39,
+0x70E2,0x70D7,0x70D2,0x70DE,0x70E0,0x70D4,0x70CD,0x70C5,
+0x70C6,0x70C7,0x70DA,0x70CE,0x70E1,0x7242,0x7278, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7277,0x7276,0x7300,0x72FA,0x72F4,0x72FE,0x72F6,
+0x72F3,0x72FB,0x7301,0x73D3,0x73D9,0x73E5,0x73D6,0x73BC,
+0x73E7,0x73E3,0x73E9,0x73DC,0x73D2,0x73DB,0x73D4,0x73DD,
+0x73DA,0x73D7,0x73D8,0x73E8,0x74DE,0x74DF,0x74F4,0x74F5,
+0x7521,0x755B,0x755F,0x75B0,0x75C1,0x75BB,0x75C4,0x75C0,
+0x75BF,0x75B6,0x75BA,0x768A,0x76C9,0x771D,0x771B,0x7710,
+0x7713,0x7712,0x7723,0x7711,0x7715,0x7719,0x771A,0x7722,
+0x7727,0x7823,0x782C,0x7822,0x7835,0x782F,0x7828,0x782E,
+0x782B,0x7821,0x7829,0x7833,0x782A,0x7831,0x7954,0x795B,
+0x794F,0x795C,0x7953,0x7952,0x7951,0x79EB,0x79EC,0x79E0,
+0x79EE,0x79ED,0x79EA,0x79DC,0x79DE,0x79DD,0x7A86,0x7A89,
+0x7A85,0x7A8B,0x7A8C,0x7A8A,0x7A87,0x7AD8,0x7B10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7B04,0x7B13,0x7B05,0x7B0F,0x7B08,0x7B0A,0x7B0E,0x7B09,
+0x7B12,0x7C84,0x7C91,0x7C8A,0x7C8C,0x7C88,0x7C8D,0x7C85,
+0x7D1E,0x7D1D,0x7D11,0x7D0E,0x7D18,0x7D16,0x7D13,0x7D1F,
+0x7D12,0x7D0F,0x7D0C,0x7F5C,0x7F61,0x7F5E,0x7F60,0x7F5D,
+0x7F5B,0x7F96,0x7F92,0x7FC3,0x7FC2,0x7FC0,0x8016,0x803E,
+0x8039,0x80FA,0x80F2,0x80F9,0x80F5,0x8101,0x80FB,0x8100,
+0x8201,0x822F,0x8225,0x8333,0x832D,0x8344,0x8319,0x8351,
+0x8325,0x8356,0x833F,0x8341,0x8326,0x831C,0x8322, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8342,0x834E,0x831B,0x832A,0x8308,0x833C,0x834D,
+0x8316,0x8324,0x8320,0x8337,0x832F,0x8329,0x8347,0x8345,
+0x834C,0x8353,0x831E,0x832C,0x834B,0x8327,0x8348,0x8653,
+0x8652,0x86A2,0x86A8,0x8696,0x868D,0x8691,0x869E,0x8687,
+0x8697,0x8686,0x868B,0x869A,0x8685,0x86A5,0x8699,0x86A1,
+0x86A7,0x8695,0x8698,0x868E,0x869D,0x8690,0x8694,0x8843,
+0x8844,0x886D,0x8875,0x8876,0x8872,0x8880,0x8871,0x887F,
+0x886F,0x8883,0x887E,0x8874,0x887C,0x8A12,0x8C47,0x8C57,
+0x8C7B,0x8CA4,0x8CA3,0x8D76,0x8D78,0x8DB5,0x8DB7,0x8DB6,
+0x8ED1,0x8ED3,0x8FFE,0x8FF5,0x9002,0x8FFF,0x8FFB,0x9004,
+0x8FFC,0x8FF6,0x90D6,0x90E0,0x90D9,0x90DA,0x90E3,0x90DF,
+0x90E5,0x90D8,0x90DB,0x90D7,0x90DC,0x90E4,0x9150, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x914E,0x914F,0x91D5,0x91E2,0x91DA,0x965C,0x965F,0x96BC,
+0x98E3,0x9ADF,0x9B2F,0x4E7F,0x5070,0x506A,0x5061,0x505E,
+0x5060,0x5053,0x504B,0x505D,0x5072,0x5048,0x504D,0x5041,
+0x505B,0x504A,0x5062,0x5015,0x5045,0x505F,0x5069,0x506B,
+0x5063,0x5064,0x5046,0x5040,0x506E,0x5073,0x5057,0x5051,
+0x51D0,0x526B,0x526D,0x526C,0x526E,0x52D6,0x52D3,0x532D,
+0x539C,0x5575,0x5576,0x553C,0x554D,0x5550,0x5534,0x552A,
+0x5551,0x5562,0x5536,0x5535,0x5530,0x5552,0x5545, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x550C,0x5532,0x5565,0x554E,0x5539,0x5548,0x552D,
+0x553B,0x5540,0x554B,0x570A,0x5707,0x57FB,0x5814,0x57E2,
+0x57F6,0x57DC,0x57F4,0x5800,0x57ED,0x57FD,0x5808,0x57F8,
+0x580B,0x57F3,0x57CF,0x5807,0x57EE,0x57E3,0x57F2,0x57E5,
+0x57EC,0x57E1,0x580E,0x57FC,0x5810,0x57E7,0x5801,0x580C,
+0x57F1,0x57E9,0x57F0,0x580D,0x5804,0x595C,0x5A60,0x5A58,
+0x5A55,0x5A67,0x5A5E,0x5A38,0x5A35,0x5A6D,0x5A50,0x5A5F,
+0x5A65,0x5A6C,0x5A53,0x5A64,0x5A57,0x5A43,0x5A5D,0x5A52,
+0x5A44,0x5A5B,0x5A48,0x5A8E,0x5A3E,0x5A4D,0x5A39,0x5A4C,
+0x5A70,0x5A69,0x5A47,0x5A51,0x5A56,0x5A42,0x5A5C,0x5B72,
+0x5B6E,0x5BC1,0x5BC0,0x5C59,0x5D1E,0x5D0B,0x5D1D,0x5D1A,
+0x5D20,0x5D0C,0x5D28,0x5D0D,0x5D26,0x5D25,0x5D0F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5D30,0x5D12,0x5D23,0x5D1F,0x5D2E,0x5E3E,0x5E34,0x5EB1,
+0x5EB4,0x5EB9,0x5EB2,0x5EB3,0x5F36,0x5F38,0x5F9B,0x5F96,
+0x5F9F,0x608A,0x6090,0x6086,0x60BE,0x60B0,0x60BA,0x60D3,
+0x60D4,0x60CF,0x60E4,0x60D9,0x60DD,0x60C8,0x60B1,0x60DB,
+0x60B7,0x60CA,0x60BF,0x60C3,0x60CD,0x60C0,0x6332,0x6365,
+0x638A,0x6382,0x637D,0x63BD,0x639E,0x63AD,0x639D,0x6397,
+0x63AB,0x638E,0x636F,0x6387,0x6390,0x636E,0x63AF,0x6375,
+0x639C,0x636D,0x63AE,0x637C,0x63A4,0x633B,0x639F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6378,0x6385,0x6381,0x6391,0x638D,0x6370,0x6553,
+0x65CD,0x6665,0x6661,0x665B,0x6659,0x665C,0x6662,0x6718,
+0x6879,0x6887,0x6890,0x689C,0x686D,0x686E,0x68AE,0x68AB,
+0x6956,0x686F,0x68A3,0x68AC,0x68A9,0x6875,0x6874,0x68B2,
+0x688F,0x6877,0x6892,0x687C,0x686B,0x6872,0x68AA,0x6880,
+0x6871,0x687E,0x689B,0x6896,0x688B,0x68A0,0x6889,0x68A4,
+0x6878,0x687B,0x6891,0x688C,0x688A,0x687D,0x6B36,0x6B33,
+0x6B37,0x6B38,0x6B91,0x6B8F,0x6B8D,0x6B8E,0x6B8C,0x6C2A,
+0x6DC0,0x6DAB,0x6DB4,0x6DB3,0x6E74,0x6DAC,0x6DE9,0x6DE2,
+0x6DB7,0x6DF6,0x6DD4,0x6E00,0x6DC8,0x6DE0,0x6DDF,0x6DD6,
+0x6DBE,0x6DE5,0x6DDC,0x6DDD,0x6DDB,0x6DF4,0x6DCA,0x6DBD,
+0x6DED,0x6DF0,0x6DBA,0x6DD5,0x6DC2,0x6DCF,0x6DC9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6DD0,0x6DF2,0x6DD3,0x6DFD,0x6DD7,0x6DCD,0x6DE3,0x6DBB,
+0x70FA,0x710D,0x70F7,0x7117,0x70F4,0x710C,0x70F0,0x7104,
+0x70F3,0x7110,0x70FC,0x70FF,0x7106,0x7113,0x7100,0x70F8,
+0x70F6,0x710B,0x7102,0x710E,0x727E,0x727B,0x727C,0x727F,
+0x731D,0x7317,0x7307,0x7311,0x7318,0x730A,0x7308,0x72FF,
+0x730F,0x731E,0x7388,0x73F6,0x73F8,0x73F5,0x7404,0x7401,
+0x73FD,0x7407,0x7400,0x73FA,0x73FC,0x73FF,0x740C,0x740B,
+0x73F4,0x7408,0x7564,0x7563,0x75CE,0x75D2,0x75CF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x75CB,0x75CC,0x75D1,0x75D0,0x768F,0x7689,0x76D3,
+0x7739,0x772F,0x772D,0x7731,0x7732,0x7734,0x7733,0x773D,
+0x7725,0x773B,0x7735,0x7848,0x7852,0x7849,0x784D,0x784A,
+0x784C,0x7826,0x7845,0x7850,0x7964,0x7967,0x7969,0x796A,
+0x7963,0x796B,0x7961,0x79BB,0x79FA,0x79F8,0x79F6,0x79F7,
+0x7A8F,0x7A94,0x7A90,0x7B35,0x7B47,0x7B34,0x7B25,0x7B30,
+0x7B22,0x7B24,0x7B33,0x7B18,0x7B2A,0x7B1D,0x7B31,0x7B2B,
+0x7B2D,0x7B2F,0x7B32,0x7B38,0x7B1A,0x7B23,0x7C94,0x7C98,
+0x7C96,0x7CA3,0x7D35,0x7D3D,0x7D38,0x7D36,0x7D3A,0x7D45,
+0x7D2C,0x7D29,0x7D41,0x7D47,0x7D3E,0x7D3F,0x7D4A,0x7D3B,
+0x7D28,0x7F63,0x7F95,0x7F9C,0x7F9D,0x7F9B,0x7FCA,0x7FCB,
+0x7FCD,0x7FD0,0x7FD1,0x7FC7,0x7FCF,0x7FC9,0x801F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x801E,0x801B,0x8047,0x8043,0x8048,0x8118,0x8125,0x8119,
+0x811B,0x812D,0x811F,0x812C,0x811E,0x8121,0x8115,0x8127,
+0x811D,0x8122,0x8211,0x8238,0x8233,0x823A,0x8234,0x8232,
+0x8274,0x8390,0x83A3,0x83A8,0x838D,0x837A,0x8373,0x83A4,
+0x8374,0x838F,0x8381,0x8395,0x8399,0x8375,0x8394,0x83A9,
+0x837D,0x8383,0x838C,0x839D,0x839B,0x83AA,0x838B,0x837E,
+0x83A5,0x83AF,0x8388,0x8397,0x83B0,0x837F,0x83A6,0x8387,
+0x83AE,0x8376,0x839A,0x8659,0x8656,0x86BF,0x86B7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x86C2,0x86C1,0x86C5,0x86BA,0x86B0,0x86C8,0x86B9,
+0x86B3,0x86B8,0x86CC,0x86B4,0x86BB,0x86BC,0x86C3,0x86BD,
+0x86BE,0x8852,0x8889,0x8895,0x88A8,0x88A2,0x88AA,0x889A,
+0x8891,0x88A1,0x889F,0x8898,0x88A7,0x8899,0x889B,0x8897,
+0x88A4,0x88AC,0x888C,0x8893,0x888E,0x8982,0x89D6,0x89D9,
+0x89D5,0x8A30,0x8A27,0x8A2C,0x8A1E,0x8C39,0x8C3B,0x8C5C,
+0x8C5D,0x8C7D,0x8CA5,0x8D7D,0x8D7B,0x8D79,0x8DBC,0x8DC2,
+0x8DB9,0x8DBF,0x8DC1,0x8ED8,0x8EDE,0x8EDD,0x8EDC,0x8ED7,
+0x8EE0,0x8EE1,0x9024,0x900B,0x9011,0x901C,0x900C,0x9021,
+0x90EF,0x90EA,0x90F0,0x90F4,0x90F2,0x90F3,0x90D4,0x90EB,
+0x90EC,0x90E9,0x9156,0x9158,0x915A,0x9153,0x9155,0x91EC,
+0x91F4,0x91F1,0x91F3,0x91F8,0x91E4,0x91F9,0x91EA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x91EB,0x91F7,0x91E8,0x91EE,0x957A,0x9586,0x9588,0x967C,
+0x966D,0x966B,0x9671,0x966F,0x96BF,0x976A,0x9804,0x98E5,
+0x9997,0x509B,0x5095,0x5094,0x509E,0x508B,0x50A3,0x5083,
+0x508C,0x508E,0x509D,0x5068,0x509C,0x5092,0x5082,0x5087,
+0x515F,0x51D4,0x5312,0x5311,0x53A4,0x53A7,0x5591,0x55A8,
+0x55A5,0x55AD,0x5577,0x5645,0x55A2,0x5593,0x5588,0x558F,
+0x55B5,0x5581,0x55A3,0x5592,0x55A4,0x557D,0x558C,0x55A6,
+0x557F,0x5595,0x55A1,0x558E,0x570C,0x5829,0x5837, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5819,0x581E,0x5827,0x5823,0x5828,0x57F5,0x5848,
+0x5825,0x581C,0x581B,0x5833,0x583F,0x5836,0x582E,0x5839,
+0x5838,0x582D,0x582C,0x583B,0x5961,0x5AAF,0x5A94,0x5A9F,
+0x5A7A,0x5AA2,0x5A9E,0x5A78,0x5AA6,0x5A7C,0x5AA5,0x5AAC,
+0x5A95,0x5AAE,0x5A37,0x5A84,0x5A8A,0x5A97,0x5A83,0x5A8B,
+0x5AA9,0x5A7B,0x5A7D,0x5A8C,0x5A9C,0x5A8F,0x5A93,0x5A9D,
+0x5BEA,0x5BCD,0x5BCB,0x5BD4,0x5BD1,0x5BCA,0x5BCE,0x5C0C,
+0x5C30,0x5D37,0x5D43,0x5D6B,0x5D41,0x5D4B,0x5D3F,0x5D35,
+0x5D51,0x5D4E,0x5D55,0x5D33,0x5D3A,0x5D52,0x5D3D,0x5D31,
+0x5D59,0x5D42,0x5D39,0x5D49,0x5D38,0x5D3C,0x5D32,0x5D36,
+0x5D40,0x5D45,0x5E44,0x5E41,0x5F58,0x5FA6,0x5FA5,0x5FAB,
+0x60C9,0x60B9,0x60CC,0x60E2,0x60CE,0x60C4,0x6114, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x60F2,0x610A,0x6116,0x6105,0x60F5,0x6113,0x60F8,0x60FC,
+0x60FE,0x60C1,0x6103,0x6118,0x611D,0x6110,0x60FF,0x6104,
+0x610B,0x624A,0x6394,0x63B1,0x63B0,0x63CE,0x63E5,0x63E8,
+0x63EF,0x63C3,0x649D,0x63F3,0x63CA,0x63E0,0x63F6,0x63D5,
+0x63F2,0x63F5,0x6461,0x63DF,0x63BE,0x63DD,0x63DC,0x63C4,
+0x63D8,0x63D3,0x63C2,0x63C7,0x63CC,0x63CB,0x63C8,0x63F0,
+0x63D7,0x63D9,0x6532,0x6567,0x656A,0x6564,0x655C,0x6568,
+0x6565,0x658C,0x659D,0x659E,0x65AE,0x65D0,0x65D2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x667C,0x666C,0x667B,0x6680,0x6671,0x6679,0x666A,
+0x6672,0x6701,0x690C,0x68D3,0x6904,0x68DC,0x692A,0x68EC,
+0x68EA,0x68F1,0x690F,0x68D6,0x68F7,0x68EB,0x68E4,0x68F6,
+0x6913,0x6910,0x68F3,0x68E1,0x6907,0x68CC,0x6908,0x6970,
+0x68B4,0x6911,0x68EF,0x68C6,0x6914,0x68F8,0x68D0,0x68FD,
+0x68FC,0x68E8,0x690B,0x690A,0x6917,0x68CE,0x68C8,0x68DD,
+0x68DE,0x68E6,0x68F4,0x68D1,0x6906,0x68D4,0x68E9,0x6915,
+0x6925,0x68C7,0x6B39,0x6B3B,0x6B3F,0x6B3C,0x6B94,0x6B97,
+0x6B99,0x6B95,0x6BBD,0x6BF0,0x6BF2,0x6BF3,0x6C30,0x6DFC,
+0x6E46,0x6E47,0x6E1F,0x6E49,0x6E88,0x6E3C,0x6E3D,0x6E45,
+0x6E62,0x6E2B,0x6E3F,0x6E41,0x6E5D,0x6E73,0x6E1C,0x6E33,
+0x6E4B,0x6E40,0x6E51,0x6E3B,0x6E03,0x6E2E,0x6E5E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E68,0x6E5C,0x6E61,0x6E31,0x6E28,0x6E60,0x6E71,0x6E6B,
+0x6E39,0x6E22,0x6E30,0x6E53,0x6E65,0x6E27,0x6E78,0x6E64,
+0x6E77,0x6E55,0x6E79,0x6E52,0x6E66,0x6E35,0x6E36,0x6E5A,
+0x7120,0x711E,0x712F,0x70FB,0x712E,0x7131,0x7123,0x7125,
+0x7122,0x7132,0x711F,0x7128,0x713A,0x711B,0x724B,0x725A,
+0x7288,0x7289,0x7286,0x7285,0x728B,0x7312,0x730B,0x7330,
+0x7322,0x7331,0x7333,0x7327,0x7332,0x732D,0x7326,0x7323,
+0x7335,0x730C,0x742E,0x742C,0x7430,0x742B,0x7416, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x741A,0x7421,0x742D,0x7431,0x7424,0x7423,0x741D,
+0x7429,0x7420,0x7432,0x74FB,0x752F,0x756F,0x756C,0x75E7,
+0x75DA,0x75E1,0x75E6,0x75DD,0x75DF,0x75E4,0x75D7,0x7695,
+0x7692,0x76DA,0x7746,0x7747,0x7744,0x774D,0x7745,0x774A,
+0x774E,0x774B,0x774C,0x77DE,0x77EC,0x7860,0x7864,0x7865,
+0x785C,0x786D,0x7871,0x786A,0x786E,0x7870,0x7869,0x7868,
+0x785E,0x7862,0x7974,0x7973,0x7972,0x7970,0x7A02,0x7A0A,
+0x7A03,0x7A0C,0x7A04,0x7A99,0x7AE6,0x7AE4,0x7B4A,0x7B3B,
+0x7B44,0x7B48,0x7B4C,0x7B4E,0x7B40,0x7B58,0x7B45,0x7CA2,
+0x7C9E,0x7CA8,0x7CA1,0x7D58,0x7D6F,0x7D63,0x7D53,0x7D56,
+0x7D67,0x7D6A,0x7D4F,0x7D6D,0x7D5C,0x7D6B,0x7D52,0x7D54,
+0x7D69,0x7D51,0x7D5F,0x7D4E,0x7F3E,0x7F3F,0x7F65, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7F66,0x7FA2,0x7FA0,0x7FA1,0x7FD7,0x8051,0x804F,0x8050,
+0x80FE,0x80D4,0x8143,0x814A,0x8152,0x814F,0x8147,0x813D,
+0x814D,0x813A,0x81E6,0x81EE,0x81F7,0x81F8,0x81F9,0x8204,
+0x823C,0x823D,0x823F,0x8275,0x833B,0x83CF,0x83F9,0x8423,
+0x83C0,0x83E8,0x8412,0x83E7,0x83E4,0x83FC,0x83F6,0x8410,
+0x83C6,0x83C8,0x83EB,0x83E3,0x83BF,0x8401,0x83DD,0x83E5,
+0x83D8,0x83FF,0x83E1,0x83CB,0x83CE,0x83D6,0x83F5,0x83C9,
+0x8409,0x840F,0x83DE,0x8411,0x8406,0x83C2,0x83F3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x83D5,0x83FA,0x83C7,0x83D1,0x83EA,0x8413,0x83C3,
+0x83EC,0x83EE,0x83C4,0x83FB,0x83D7,0x83E2,0x841B,0x83DB,
+0x83FE,0x86D8,0x86E2,0x86E6,0x86D3,0x86E3,0x86DA,0x86EA,
+0x86DD,0x86EB,0x86DC,0x86EC,0x86E9,0x86D7,0x86E8,0x86D1,
+0x8848,0x8856,0x8855,0x88BA,0x88D7,0x88B9,0x88B8,0x88C0,
+0x88BE,0x88B6,0x88BC,0x88B7,0x88BD,0x88B2,0x8901,0x88C9,
+0x8995,0x8998,0x8997,0x89DD,0x89DA,0x89DB,0x8A4E,0x8A4D,
+0x8A39,0x8A59,0x8A40,0x8A57,0x8A58,0x8A44,0x8A45,0x8A52,
+0x8A48,0x8A51,0x8A4A,0x8A4C,0x8A4F,0x8C5F,0x8C81,0x8C80,
+0x8CBA,0x8CBE,0x8CB0,0x8CB9,0x8CB5,0x8D84,0x8D80,0x8D89,
+0x8DD8,0x8DD3,0x8DCD,0x8DC7,0x8DD6,0x8DDC,0x8DCF,0x8DD5,
+0x8DD9,0x8DC8,0x8DD7,0x8DC5,0x8EEF,0x8EF7,0x8EFA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8EF9,0x8EE6,0x8EEE,0x8EE5,0x8EF5,0x8EE7,0x8EE8,0x8EF6,
+0x8EEB,0x8EF1,0x8EEC,0x8EF4,0x8EE9,0x902D,0x9034,0x902F,
+0x9106,0x912C,0x9104,0x90FF,0x90FC,0x9108,0x90F9,0x90FB,
+0x9101,0x9100,0x9107,0x9105,0x9103,0x9161,0x9164,0x915F,
+0x9162,0x9160,0x9201,0x920A,0x9225,0x9203,0x921A,0x9226,
+0x920F,0x920C,0x9200,0x9212,0x91FF,0x91FD,0x9206,0x9204,
+0x9227,0x9202,0x921C,0x9224,0x9219,0x9217,0x9205,0x9216,
+0x957B,0x958D,0x958C,0x9590,0x9687,0x967E,0x9688, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9689,0x9683,0x9680,0x96C2,0x96C8,0x96C3,0x96F1,
+0x96F0,0x976C,0x9770,0x976E,0x9807,0x98A9,0x98EB,0x9CE6,
+0x9EF9,0x4E83,0x4E84,0x4EB6,0x50BD,0x50BF,0x50C6,0x50AE,
+0x50C4,0x50CA,0x50B4,0x50C8,0x50C2,0x50B0,0x50C1,0x50BA,
+0x50B1,0x50CB,0x50C9,0x50B6,0x50B8,0x51D7,0x527A,0x5278,
+0x527B,0x527C,0x55C3,0x55DB,0x55CC,0x55D0,0x55CB,0x55CA,
+0x55DD,0x55C0,0x55D4,0x55C4,0x55E9,0x55BF,0x55D2,0x558D,
+0x55CF,0x55D5,0x55E2,0x55D6,0x55C8,0x55F2,0x55CD,0x55D9,
+0x55C2,0x5714,0x5853,0x5868,0x5864,0x584F,0x584D,0x5849,
+0x586F,0x5855,0x584E,0x585D,0x5859,0x5865,0x585B,0x583D,
+0x5863,0x5871,0x58FC,0x5AC7,0x5AC4,0x5ACB,0x5ABA,0x5AB8,
+0x5AB1,0x5AB5,0x5AB0,0x5ABF,0x5AC8,0x5ABB,0x5AC6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5AB7,0x5AC0,0x5ACA,0x5AB4,0x5AB6,0x5ACD,0x5AB9,0x5A90,
+0x5BD6,0x5BD8,0x5BD9,0x5C1F,0x5C33,0x5D71,0x5D63,0x5D4A,
+0x5D65,0x5D72,0x5D6C,0x5D5E,0x5D68,0x5D67,0x5D62,0x5DF0,
+0x5E4F,0x5E4E,0x5E4A,0x5E4D,0x5E4B,0x5EC5,0x5ECC,0x5EC6,
+0x5ECB,0x5EC7,0x5F40,0x5FAF,0x5FAD,0x60F7,0x6149,0x614A,
+0x612B,0x6145,0x6136,0x6132,0x612E,0x6146,0x612F,0x614F,
+0x6129,0x6140,0x6220,0x9168,0x6223,0x6225,0x6224,0x63C5,
+0x63F1,0x63EB,0x6410,0x6412,0x6409,0x6420,0x6424, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6433,0x6443,0x641F,0x6415,0x6418,0x6439,0x6437,
+0x6422,0x6423,0x640C,0x6426,0x6430,0x6428,0x6441,0x6435,
+0x642F,0x640A,0x641A,0x6440,0x6425,0x6427,0x640B,0x63E7,
+0x641B,0x642E,0x6421,0x640E,0x656F,0x6592,0x65D3,0x6686,
+0x668C,0x6695,0x6690,0x668B,0x668A,0x6699,0x6694,0x6678,
+0x6720,0x6966,0x695F,0x6938,0x694E,0x6962,0x6971,0x693F,
+0x6945,0x696A,0x6939,0x6942,0x6957,0x6959,0x697A,0x6948,
+0x6949,0x6935,0x696C,0x6933,0x693D,0x6965,0x68F0,0x6978,
+0x6934,0x6969,0x6940,0x696F,0x6944,0x6976,0x6958,0x6941,
+0x6974,0x694C,0x693B,0x694B,0x6937,0x695C,0x694F,0x6951,
+0x6932,0x6952,0x692F,0x697B,0x693C,0x6B46,0x6B45,0x6B43,
+0x6B42,0x6B48,0x6B41,0x6B9B,0xFA0D,0x6BFB,0x6BFC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6BF9,0x6BF7,0x6BF8,0x6E9B,0x6ED6,0x6EC8,0x6E8F,0x6EC0,
+0x6E9F,0x6E93,0x6E94,0x6EA0,0x6EB1,0x6EB9,0x6EC6,0x6ED2,
+0x6EBD,0x6EC1,0x6E9E,0x6EC9,0x6EB7,0x6EB0,0x6ECD,0x6EA6,
+0x6ECF,0x6EB2,0x6EBE,0x6EC3,0x6EDC,0x6ED8,0x6E99,0x6E92,
+0x6E8E,0x6E8D,0x6EA4,0x6EA1,0x6EBF,0x6EB3,0x6ED0,0x6ECA,
+0x6E97,0x6EAE,0x6EA3,0x7147,0x7154,0x7152,0x7163,0x7160,
+0x7141,0x715D,0x7162,0x7172,0x7178,0x716A,0x7161,0x7142,
+0x7158,0x7143,0x714B,0x7170,0x715F,0x7150,0x7153, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7144,0x714D,0x715A,0x724F,0x728D,0x728C,0x7291,
+0x7290,0x728E,0x733C,0x7342,0x733B,0x733A,0x7340,0x734A,
+0x7349,0x7444,0x744A,0x744B,0x7452,0x7451,0x7457,0x7440,
+0x744F,0x7450,0x744E,0x7442,0x7446,0x744D,0x7454,0x74E1,
+0x74FF,0x74FE,0x74FD,0x751D,0x7579,0x7577,0x6983,0x75EF,
+0x760F,0x7603,0x75F7,0x75FE,0x75FC,0x75F9,0x75F8,0x7610,
+0x75FB,0x75F6,0x75ED,0x75F5,0x75FD,0x7699,0x76B5,0x76DD,
+0x7755,0x775F,0x7760,0x7752,0x7756,0x775A,0x7769,0x7767,
+0x7754,0x7759,0x776D,0x77E0,0x7887,0x789A,0x7894,0x788F,
+0x7884,0x7895,0x7885,0x7886,0x78A1,0x7883,0x7879,0x7899,
+0x7880,0x7896,0x787B,0x797C,0x7982,0x797D,0x7979,0x7A11,
+0x7A18,0x7A19,0x7A12,0x7A17,0x7A15,0x7A22,0x7A13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7A1B,0x7A10,0x7AA3,0x7AA2,0x7A9E,0x7AEB,0x7B66,0x7B64,
+0x7B6D,0x7B74,0x7B69,0x7B72,0x7B65,0x7B73,0x7B71,0x7B70,
+0x7B61,0x7B78,0x7B76,0x7B63,0x7CB2,0x7CB4,0x7CAF,0x7D88,
+0x7D86,0x7D80,0x7D8D,0x7D7F,0x7D85,0x7D7A,0x7D8E,0x7D7B,
+0x7D83,0x7D7C,0x7D8C,0x7D94,0x7D84,0x7D7D,0x7D92,0x7F6D,
+0x7F6B,0x7F67,0x7F68,0x7F6C,0x7FA6,0x7FA5,0x7FA7,0x7FDB,
+0x7FDC,0x8021,0x8164,0x8160,0x8177,0x815C,0x8169,0x815B,
+0x8162,0x8172,0x6721,0x815E,0x8176,0x8167,0x816F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8144,0x8161,0x821D,0x8249,0x8244,0x8240,0x8242,
+0x8245,0x84F1,0x843F,0x8456,0x8476,0x8479,0x848F,0x848D,
+0x8465,0x8451,0x8440,0x8486,0x8467,0x8430,0x844D,0x847D,
+0x845A,0x8459,0x8474,0x8473,0x845D,0x8507,0x845E,0x8437,
+0x843A,0x8434,0x847A,0x8443,0x8478,0x8432,0x8445,0x8429,
+0x83D9,0x844B,0x842F,0x8442,0x842D,0x845F,0x8470,0x8439,
+0x844E,0x844C,0x8452,0x846F,0x84C5,0x848E,0x843B,0x8447,
+0x8436,0x8433,0x8468,0x847E,0x8444,0x842B,0x8460,0x8454,
+0x846E,0x8450,0x870B,0x8704,0x86F7,0x870C,0x86FA,0x86D6,
+0x86F5,0x874D,0x86F8,0x870E,0x8709,0x8701,0x86F6,0x870D,
+0x8705,0x88D6,0x88CB,0x88CD,0x88CE,0x88DE,0x88DB,0x88DA,
+0x88CC,0x88D0,0x8985,0x899B,0x89DF,0x89E5,0x89E4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x89E1,0x89E0,0x89E2,0x89DC,0x89E6,0x8A76,0x8A86,0x8A7F,
+0x8A61,0x8A3F,0x8A77,0x8A82,0x8A84,0x8A75,0x8A83,0x8A81,
+0x8A74,0x8A7A,0x8C3C,0x8C4B,0x8C4A,0x8C65,0x8C64,0x8C66,
+0x8C86,0x8C84,0x8C85,0x8CCC,0x8D68,0x8D69,0x8D91,0x8D8C,
+0x8D8E,0x8D8F,0x8D8D,0x8D93,0x8D94,0x8D90,0x8D92,0x8DF0,
+0x8DE0,0x8DEC,0x8DF1,0x8DEE,0x8DD0,0x8DE9,0x8DE3,0x8DE2,
+0x8DE7,0x8DF2,0x8DEB,0x8DF4,0x8F06,0x8EFF,0x8F01,0x8F00,
+0x8F05,0x8F07,0x8F08,0x8F02,0x8F0B,0x9052,0x903F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9044,0x9049,0x903D,0x9110,0x910D,0x910F,0x9111,
+0x9116,0x9114,0x910B,0x910E,0x916E,0x916F,0x9248,0x9252,
+0x9230,0x923A,0x9266,0x9233,0x9265,0x925E,0x9283,0x922E,
+0x924A,0x9246,0x926D,0x926C,0x924F,0x9260,0x9267,0x926F,
+0x9236,0x9261,0x9270,0x9231,0x9254,0x9263,0x9250,0x9272,
+0x924E,0x9253,0x924C,0x9256,0x9232,0x959F,0x959C,0x959E,
+0x959B,0x9692,0x9693,0x9691,0x9697,0x96CE,0x96FA,0x96FD,
+0x96F8,0x96F5,0x9773,0x9777,0x9778,0x9772,0x980F,0x980D,
+0x980E,0x98AC,0x98F6,0x98F9,0x99AF,0x99B2,0x99B0,0x99B5,
+0x9AAD,0x9AAB,0x9B5B,0x9CEA,0x9CED,0x9CE7,0x9E80,0x9EFD,
+0x50E6,0x50D4,0x50D7,0x50E8,0x50F3,0x50DB,0x50EA,0x50DD,
+0x50E4,0x50D3,0x50EC,0x50F0,0x50EF,0x50E3,0x50E0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x51D8,0x5280,0x5281,0x52E9,0x52EB,0x5330,0x53AC,0x5627,
+0x5615,0x560C,0x5612,0x55FC,0x560F,0x561C,0x5601,0x5613,
+0x5602,0x55FA,0x561D,0x5604,0x55FF,0x55F9,0x5889,0x587C,
+0x5890,0x5898,0x5886,0x5881,0x587F,0x5874,0x588B,0x587A,
+0x5887,0x5891,0x588E,0x5876,0x5882,0x5888,0x587B,0x5894,
+0x588F,0x58FE,0x596B,0x5ADC,0x5AEE,0x5AE5,0x5AD5,0x5AEA,
+0x5ADA,0x5AED,0x5AEB,0x5AF3,0x5AE2,0x5AE0,0x5ADB,0x5AEC,
+0x5ADE,0x5ADD,0x5AD9,0x5AE8,0x5ADF,0x5B77,0x5BE0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5BE3,0x5C63,0x5D82,0x5D80,0x5D7D,0x5D86,0x5D7A,
+0x5D81,0x5D77,0x5D8A,0x5D89,0x5D88,0x5D7E,0x5D7C,0x5D8D,
+0x5D79,0x5D7F,0x5E58,0x5E59,0x5E53,0x5ED8,0x5ED1,0x5ED7,
+0x5ECE,0x5EDC,0x5ED5,0x5ED9,0x5ED2,0x5ED4,0x5F44,0x5F43,
+0x5F6F,0x5FB6,0x612C,0x6128,0x6141,0x615E,0x6171,0x6173,
+0x6152,0x6153,0x6172,0x616C,0x6180,0x6174,0x6154,0x617A,
+0x615B,0x6165,0x613B,0x616A,0x6161,0x6156,0x6229,0x6227,
+0x622B,0x642B,0x644D,0x645B,0x645D,0x6474,0x6476,0x6472,
+0x6473,0x647D,0x6475,0x6466,0x64A6,0x644E,0x6482,0x645E,
+0x645C,0x644B,0x6453,0x6460,0x6450,0x647F,0x643F,0x646C,
+0x646B,0x6459,0x6465,0x6477,0x6573,0x65A0,0x66A1,0x66A0,
+0x669F,0x6705,0x6704,0x6722,0x69B1,0x69B6,0x69C9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x69A0,0x69CE,0x6996,0x69B0,0x69AC,0x69BC,0x6991,0x6999,
+0x698E,0x69A7,0x698D,0x69A9,0x69BE,0x69AF,0x69BF,0x69C4,
+0x69BD,0x69A4,0x69D4,0x69B9,0x69CA,0x699A,0x69CF,0x69B3,
+0x6993,0x69AA,0x69A1,0x699E,0x69D9,0x6997,0x6990,0x69C2,
+0x69B5,0x69A5,0x69C6,0x6B4A,0x6B4D,0x6B4B,0x6B9E,0x6B9F,
+0x6BA0,0x6BC3,0x6BC4,0x6BFE,0x6ECE,0x6EF5,0x6EF1,0x6F03,
+0x6F25,0x6EF8,0x6F37,0x6EFB,0x6F2E,0x6F09,0x6F4E,0x6F19,
+0x6F1A,0x6F27,0x6F18,0x6F3B,0x6F12,0x6EED,0x6F0A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6F36,0x6F73,0x6EF9,0x6EEE,0x6F2D,0x6F40,0x6F30,
+0x6F3C,0x6F35,0x6EEB,0x6F07,0x6F0E,0x6F43,0x6F05,0x6EFD,
+0x6EF6,0x6F39,0x6F1C,0x6EFC,0x6F3A,0x6F1F,0x6F0D,0x6F1E,
+0x6F08,0x6F21,0x7187,0x7190,0x7189,0x7180,0x7185,0x7182,
+0x718F,0x717B,0x7186,0x7181,0x7197,0x7244,0x7253,0x7297,
+0x7295,0x7293,0x7343,0x734D,0x7351,0x734C,0x7462,0x7473,
+0x7471,0x7475,0x7472,0x7467,0x746E,0x7500,0x7502,0x7503,
+0x757D,0x7590,0x7616,0x7608,0x760C,0x7615,0x7611,0x760A,
+0x7614,0x76B8,0x7781,0x777C,0x7785,0x7782,0x776E,0x7780,
+0x776F,0x777E,0x7783,0x78B2,0x78AA,0x78B4,0x78AD,0x78A8,
+0x787E,0x78AB,0x789E,0x78A5,0x78A0,0x78AC,0x78A2,0x78A4,
+0x7998,0x798A,0x798B,0x7996,0x7995,0x7994,0x7993, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7997,0x7988,0x7992,0x7990,0x7A2B,0x7A4A,0x7A30,0x7A2F,
+0x7A28,0x7A26,0x7AA8,0x7AAB,0x7AAC,0x7AEE,0x7B88,0x7B9C,
+0x7B8A,0x7B91,0x7B90,0x7B96,0x7B8D,0x7B8C,0x7B9B,0x7B8E,
+0x7B85,0x7B98,0x5284,0x7B99,0x7BA4,0x7B82,0x7CBB,0x7CBF,
+0x7CBC,0x7CBA,0x7DA7,0x7DB7,0x7DC2,0x7DA3,0x7DAA,0x7DC1,
+0x7DC0,0x7DC5,0x7D9D,0x7DCE,0x7DC4,0x7DC6,0x7DCB,0x7DCC,
+0x7DAF,0x7DB9,0x7D96,0x7DBC,0x7D9F,0x7DA6,0x7DAE,0x7DA9,
+0x7DA1,0x7DC9,0x7F73,0x7FE2,0x7FE3,0x7FE5,0x7FDE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8024,0x805D,0x805C,0x8189,0x8186,0x8183,0x8187,
+0x818D,0x818C,0x818B,0x8215,0x8497,0x84A4,0x84A1,0x849F,
+0x84BA,0x84CE,0x84C2,0x84AC,0x84AE,0x84AB,0x84B9,0x84B4,
+0x84C1,0x84CD,0x84AA,0x849A,0x84B1,0x84D0,0x849D,0x84A7,
+0x84BB,0x84A2,0x8494,0x84C7,0x84CC,0x849B,0x84A9,0x84AF,
+0x84A8,0x84D6,0x8498,0x84B6,0x84CF,0x84A0,0x84D7,0x84D4,
+0x84D2,0x84DB,0x84B0,0x8491,0x8661,0x8733,0x8723,0x8728,
+0x876B,0x8740,0x872E,0x871E,0x8721,0x8719,0x871B,0x8743,
+0x872C,0x8741,0x873E,0x8746,0x8720,0x8732,0x872A,0x872D,
+0x873C,0x8712,0x873A,0x8731,0x8735,0x8742,0x8726,0x8727,
+0x8738,0x8724,0x871A,0x8730,0x8711,0x88F7,0x88E7,0x88F1,
+0x88F2,0x88FA,0x88FE,0x88EE,0x88FC,0x88F6,0x88FB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x88F0,0x88EC,0x88EB,0x899D,0x89A1,0x899F,0x899E,0x89E9,
+0x89EB,0x89E8,0x8AAB,0x8A99,0x8A8B,0x8A92,0x8A8F,0x8A96,
+0x8C3D,0x8C68,0x8C69,0x8CD5,0x8CCF,0x8CD7,0x8D96,0x8E09,
+0x8E02,0x8DFF,0x8E0D,0x8DFD,0x8E0A,0x8E03,0x8E07,0x8E06,
+0x8E05,0x8DFE,0x8E00,0x8E04,0x8F10,0x8F11,0x8F0E,0x8F0D,
+0x9123,0x911C,0x9120,0x9122,0x911F,0x911D,0x911A,0x9124,
+0x9121,0x911B,0x917A,0x9172,0x9179,0x9173,0x92A5,0x92A4,
+0x9276,0x929B,0x927A,0x92A0,0x9294,0x92AA,0x928D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x92A6,0x929A,0x92AB,0x9279,0x9297,0x927F,0x92A3,
+0x92EE,0x928E,0x9282,0x9295,0x92A2,0x927D,0x9288,0x92A1,
+0x928A,0x9286,0x928C,0x9299,0x92A7,0x927E,0x9287,0x92A9,
+0x929D,0x928B,0x922D,0x969E,0x96A1,0x96FF,0x9758,0x977D,
+0x977A,0x977E,0x9783,0x9780,0x9782,0x977B,0x9784,0x9781,
+0x977F,0x97CE,0x97CD,0x9816,0x98AD,0x98AE,0x9902,0x9900,
+0x9907,0x999D,0x999C,0x99C3,0x99B9,0x99BB,0x99BA,0x99C2,
+0x99BD,0x99C7,0x9AB1,0x9AE3,0x9AE7,0x9B3E,0x9B3F,0x9B60,
+0x9B61,0x9B5F,0x9CF1,0x9CF2,0x9CF5,0x9EA7,0x50FF,0x5103,
+0x5130,0x50F8,0x5106,0x5107,0x50F6,0x50FE,0x510B,0x510C,
+0x50FD,0x510A,0x528B,0x528C,0x52F1,0x52EF,0x5648,0x5642,
+0x564C,0x5635,0x5641,0x564A,0x5649,0x5646,0x5658, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x565A,0x5640,0x5633,0x563D,0x562C,0x563E,0x5638,0x562A,
+0x563A,0x571A,0x58AB,0x589D,0x58B1,0x58A0,0x58A3,0x58AF,
+0x58AC,0x58A5,0x58A1,0x58FF,0x5AFF,0x5AF4,0x5AFD,0x5AF7,
+0x5AF6,0x5B03,0x5AF8,0x5B02,0x5AF9,0x5B01,0x5B07,0x5B05,
+0x5B0F,0x5C67,0x5D99,0x5D97,0x5D9F,0x5D92,0x5DA2,0x5D93,
+0x5D95,0x5DA0,0x5D9C,0x5DA1,0x5D9A,0x5D9E,0x5E69,0x5E5D,
+0x5E60,0x5E5C,0x7DF3,0x5EDB,0x5EDE,0x5EE1,0x5F49,0x5FB2,
+0x618B,0x6183,0x6179,0x61B1,0x61B0,0x61A2,0x6189, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x619B,0x6193,0x61AF,0x61AD,0x619F,0x6192,0x61AA,
+0x61A1,0x618D,0x6166,0x61B3,0x622D,0x646E,0x6470,0x6496,
+0x64A0,0x6485,0x6497,0x649C,0x648F,0x648B,0x648A,0x648C,
+0x64A3,0x649F,0x6468,0x64B1,0x6498,0x6576,0x657A,0x6579,
+0x657B,0x65B2,0x65B3,0x66B5,0x66B0,0x66A9,0x66B2,0x66B7,
+0x66AA,0x66AF,0x6A00,0x6A06,0x6A17,0x69E5,0x69F8,0x6A15,
+0x69F1,0x69E4,0x6A20,0x69FF,0x69EC,0x69E2,0x6A1B,0x6A1D,
+0x69FE,0x6A27,0x69F2,0x69EE,0x6A14,0x69F7,0x69E7,0x6A40,
+0x6A08,0x69E6,0x69FB,0x6A0D,0x69FC,0x69EB,0x6A09,0x6A04,
+0x6A18,0x6A25,0x6A0F,0x69F6,0x6A26,0x6A07,0x69F4,0x6A16,
+0x6B51,0x6BA5,0x6BA3,0x6BA2,0x6BA6,0x6C01,0x6C00,0x6BFF,
+0x6C02,0x6F41,0x6F26,0x6F7E,0x6F87,0x6FC6,0x6F92, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6F8D,0x6F89,0x6F8C,0x6F62,0x6F4F,0x6F85,0x6F5A,0x6F96,
+0x6F76,0x6F6C,0x6F82,0x6F55,0x6F72,0x6F52,0x6F50,0x6F57,
+0x6F94,0x6F93,0x6F5D,0x6F00,0x6F61,0x6F6B,0x6F7D,0x6F67,
+0x6F90,0x6F53,0x6F8B,0x6F69,0x6F7F,0x6F95,0x6F63,0x6F77,
+0x6F6A,0x6F7B,0x71B2,0x71AF,0x719B,0x71B0,0x71A0,0x719A,
+0x71A9,0x71B5,0x719D,0x71A5,0x719E,0x71A4,0x71A1,0x71AA,
+0x719C,0x71A7,0x71B3,0x7298,0x729A,0x7358,0x7352,0x735E,
+0x735F,0x7360,0x735D,0x735B,0x7361,0x735A,0x7359, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7362,0x7487,0x7489,0x748A,0x7486,0x7481,0x747D,
+0x7485,0x7488,0x747C,0x7479,0x7508,0x7507,0x757E,0x7625,
+0x761E,0x7619,0x761D,0x761C,0x7623,0x761A,0x7628,0x761B,
+0x769C,0x769D,0x769E,0x769B,0x778D,0x778F,0x7789,0x7788,
+0x78CD,0x78BB,0x78CF,0x78CC,0x78D1,0x78CE,0x78D4,0x78C8,
+0x78C3,0x78C4,0x78C9,0x799A,0x79A1,0x79A0,0x799C,0x79A2,
+0x799B,0x6B76,0x7A39,0x7AB2,0x7AB4,0x7AB3,0x7BB7,0x7BCB,
+0x7BBE,0x7BAC,0x7BCE,0x7BAF,0x7BB9,0x7BCA,0x7BB5,0x7CC5,
+0x7CC8,0x7CCC,0x7CCB,0x7DF7,0x7DDB,0x7DEA,0x7DE7,0x7DD7,
+0x7DE1,0x7E03,0x7DFA,0x7DE6,0x7DF6,0x7DF1,0x7DF0,0x7DEE,
+0x7DDF,0x7F76,0x7FAC,0x7FB0,0x7FAD,0x7FED,0x7FEB,0x7FEA,
+0x7FEC,0x7FE6,0x7FE8,0x8064,0x8067,0x81A3,0x819F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x819E,0x8195,0x81A2,0x8199,0x8197,0x8216,0x824F,0x8253,
+0x8252,0x8250,0x824E,0x8251,0x8524,0x853B,0x850F,0x8500,
+0x8529,0x850E,0x8509,0x850D,0x851F,0x850A,0x8527,0x851C,
+0x84FB,0x852B,0x84FA,0x8508,0x850C,0x84F4,0x852A,0x84F2,
+0x8515,0x84F7,0x84EB,0x84F3,0x84FC,0x8512,0x84EA,0x84E9,
+0x8516,0x84FE,0x8528,0x851D,0x852E,0x8502,0x84FD,0x851E,
+0x84F6,0x8531,0x8526,0x84E7,0x84E8,0x84F0,0x84EF,0x84F9,
+0x8518,0x8520,0x8530,0x850B,0x8519,0x852F,0x8662, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8756,0x8763,0x8764,0x8777,0x87E1,0x8773,0x8758,
+0x8754,0x875B,0x8752,0x8761,0x875A,0x8751,0x875E,0x876D,
+0x876A,0x8750,0x874E,0x875F,0x875D,0x876F,0x876C,0x877A,
+0x876E,0x875C,0x8765,0x874F,0x877B,0x8775,0x8762,0x8767,
+0x8769,0x885A,0x8905,0x890C,0x8914,0x890B,0x8917,0x8918,
+0x8919,0x8906,0x8916,0x8911,0x890E,0x8909,0x89A2,0x89A4,
+0x89A3,0x89ED,0x89F0,0x89EC,0x8ACF,0x8AC6,0x8AB8,0x8AD3,
+0x8AD1,0x8AD4,0x8AD5,0x8ABB,0x8AD7,0x8ABE,0x8AC0,0x8AC5,
+0x8AD8,0x8AC3,0x8ABA,0x8ABD,0x8AD9,0x8C3E,0x8C4D,0x8C8F,
+0x8CE5,0x8CDF,0x8CD9,0x8CE8,0x8CDA,0x8CDD,0x8CE7,0x8DA0,
+0x8D9C,0x8DA1,0x8D9B,0x8E20,0x8E23,0x8E25,0x8E24,0x8E2E,
+0x8E15,0x8E1B,0x8E16,0x8E11,0x8E19,0x8E26,0x8E27, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8E14,0x8E12,0x8E18,0x8E13,0x8E1C,0x8E17,0x8E1A,0x8F2C,
+0x8F24,0x8F18,0x8F1A,0x8F20,0x8F23,0x8F16,0x8F17,0x9073,
+0x9070,0x906F,0x9067,0x906B,0x912F,0x912B,0x9129,0x912A,
+0x9132,0x9126,0x912E,0x9185,0x9186,0x918A,0x9181,0x9182,
+0x9184,0x9180,0x92D0,0x92C3,0x92C4,0x92C0,0x92D9,0x92B6,
+0x92CF,0x92F1,0x92DF,0x92D8,0x92E9,0x92D7,0x92DD,0x92CC,
+0x92EF,0x92C2,0x92E8,0x92CA,0x92C8,0x92CE,0x92E6,0x92CD,
+0x92D5,0x92C9,0x92E0,0x92DE,0x92E7,0x92D1,0x92D3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x92B5,0x92E1,0x92C6,0x92B4,0x957C,0x95AC,0x95AB,
+0x95AE,0x95B0,0x96A4,0x96A2,0x96D3,0x9705,0x9708,0x9702,
+0x975A,0x978A,0x978E,0x9788,0x97D0,0x97CF,0x981E,0x981D,
+0x9826,0x9829,0x9828,0x9820,0x981B,0x9827,0x98B2,0x9908,
+0x98FA,0x9911,0x9914,0x9916,0x9917,0x9915,0x99DC,0x99CD,
+0x99CF,0x99D3,0x99D4,0x99CE,0x99C9,0x99D6,0x99D8,0x99CB,
+0x99D7,0x99CC,0x9AB3,0x9AEC,0x9AEB,0x9AF3,0x9AF2,0x9AF1,
+0x9B46,0x9B43,0x9B67,0x9B74,0x9B71,0x9B66,0x9B76,0x9B75,
+0x9B70,0x9B68,0x9B64,0x9B6C,0x9CFC,0x9CFA,0x9CFD,0x9CFF,
+0x9CF7,0x9D07,0x9D00,0x9CF9,0x9CFB,0x9D08,0x9D05,0x9D04,
+0x9E83,0x9ED3,0x9F0F,0x9F10,0x511C,0x5113,0x5117,0x511A,
+0x5111,0x51DE,0x5334,0x53E1,0x5670,0x5660,0x566E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5673,0x5666,0x5663,0x566D,0x5672,0x565E,0x5677,0x571C,
+0x571B,0x58C8,0x58BD,0x58C9,0x58BF,0x58BA,0x58C2,0x58BC,
+0x58C6,0x5B17,0x5B19,0x5B1B,0x5B21,0x5B14,0x5B13,0x5B10,
+0x5B16,0x5B28,0x5B1A,0x5B20,0x5B1E,0x5BEF,0x5DAC,0x5DB1,
+0x5DA9,0x5DA7,0x5DB5,0x5DB0,0x5DAE,0x5DAA,0x5DA8,0x5DB2,
+0x5DAD,0x5DAF,0x5DB4,0x5E67,0x5E68,0x5E66,0x5E6F,0x5EE9,
+0x5EE7,0x5EE6,0x5EE8,0x5EE5,0x5F4B,0x5FBC,0x619D,0x61A8,
+0x6196,0x61C5,0x61B4,0x61C6,0x61C1,0x61CC,0x61BA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x61BF,0x61B8,0x618C,0x64D7,0x64D6,0x64D0,0x64CF,
+0x64C9,0x64BD,0x6489,0x64C3,0x64DB,0x64F3,0x64D9,0x6533,
+0x657F,0x657C,0x65A2,0x66C8,0x66BE,0x66C0,0x66CA,0x66CB,
+0x66CF,0x66BD,0x66BB,0x66BA,0x66CC,0x6723,0x6A34,0x6A66,
+0x6A49,0x6A67,0x6A32,0x6A68,0x6A3E,0x6A5D,0x6A6D,0x6A76,
+0x6A5B,0x6A51,0x6A28,0x6A5A,0x6A3B,0x6A3F,0x6A41,0x6A6A,
+0x6A64,0x6A50,0x6A4F,0x6A54,0x6A6F,0x6A69,0x6A60,0x6A3C,
+0x6A5E,0x6A56,0x6A55,0x6A4D,0x6A4E,0x6A46,0x6B55,0x6B54,
+0x6B56,0x6BA7,0x6BAA,0x6BAB,0x6BC8,0x6BC7,0x6C04,0x6C03,
+0x6C06,0x6FAD,0x6FCB,0x6FA3,0x6FC7,0x6FBC,0x6FCE,0x6FC8,
+0x6F5E,0x6FC4,0x6FBD,0x6F9E,0x6FCA,0x6FA8,0x7004,0x6FA5,
+0x6FAE,0x6FBA,0x6FAC,0x6FAA,0x6FCF,0x6FBF,0x6FB8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6FA2,0x6FC9,0x6FAB,0x6FCD,0x6FAF,0x6FB2,0x6FB0,0x71C5,
+0x71C2,0x71BF,0x71B8,0x71D6,0x71C0,0x71C1,0x71CB,0x71D4,
+0x71CA,0x71C7,0x71CF,0x71BD,0x71D8,0x71BC,0x71C6,0x71DA,
+0x71DB,0x729D,0x729E,0x7369,0x7366,0x7367,0x736C,0x7365,
+0x736B,0x736A,0x747F,0x749A,0x74A0,0x7494,0x7492,0x7495,
+0x74A1,0x750B,0x7580,0x762F,0x762D,0x7631,0x763D,0x7633,
+0x763C,0x7635,0x7632,0x7630,0x76BB,0x76E6,0x779A,0x779D,
+0x77A1,0x779C,0x779B,0x77A2,0x77A3,0x7795,0x7799, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7797,0x78DD,0x78E9,0x78E5,0x78EA,0x78DE,0x78E3,
+0x78DB,0x78E1,0x78E2,0x78ED,0x78DF,0x78E0,0x79A4,0x7A44,
+0x7A48,0x7A47,0x7AB6,0x7AB8,0x7AB5,0x7AB1,0x7AB7,0x7BDE,
+0x7BE3,0x7BE7,0x7BDD,0x7BD5,0x7BE5,0x7BDA,0x7BE8,0x7BF9,
+0x7BD4,0x7BEA,0x7BE2,0x7BDC,0x7BEB,0x7BD8,0x7BDF,0x7CD2,
+0x7CD4,0x7CD7,0x7CD0,0x7CD1,0x7E12,0x7E21,0x7E17,0x7E0C,
+0x7E1F,0x7E20,0x7E13,0x7E0E,0x7E1C,0x7E15,0x7E1A,0x7E22,
+0x7E0B,0x7E0F,0x7E16,0x7E0D,0x7E14,0x7E25,0x7E24,0x7F43,
+0x7F7B,0x7F7C,0x7F7A,0x7FB1,0x7FEF,0x802A,0x8029,0x806C,
+0x81B1,0x81A6,0x81AE,0x81B9,0x81B5,0x81AB,0x81B0,0x81AC,
+0x81B4,0x81B2,0x81B7,0x81A7,0x81F2,0x8255,0x8256,0x8257,
+0x8556,0x8545,0x856B,0x854D,0x8553,0x8561,0x8558, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8540,0x8546,0x8564,0x8541,0x8562,0x8544,0x8551,0x8547,
+0x8563,0x853E,0x855B,0x8571,0x854E,0x856E,0x8575,0x8555,
+0x8567,0x8560,0x858C,0x8566,0x855D,0x8554,0x8565,0x856C,
+0x8663,0x8665,0x8664,0x879B,0x878F,0x8797,0x8793,0x8792,
+0x8788,0x8781,0x8796,0x8798,0x8779,0x8787,0x87A3,0x8785,
+0x8790,0x8791,0x879D,0x8784,0x8794,0x879C,0x879A,0x8789,
+0x891E,0x8926,0x8930,0x892D,0x892E,0x8927,0x8931,0x8922,
+0x8929,0x8923,0x892F,0x892C,0x891F,0x89F1,0x8AE0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8AE2,0x8AF2,0x8AF4,0x8AF5,0x8ADD,0x8B14,0x8AE4,
+0x8ADF,0x8AF0,0x8AC8,0x8ADE,0x8AE1,0x8AE8,0x8AFF,0x8AEF,
+0x8AFB,0x8C91,0x8C92,0x8C90,0x8CF5,0x8CEE,0x8CF1,0x8CF0,
+0x8CF3,0x8D6C,0x8D6E,0x8DA5,0x8DA7,0x8E33,0x8E3E,0x8E38,
+0x8E40,0x8E45,0x8E36,0x8E3C,0x8E3D,0x8E41,0x8E30,0x8E3F,
+0x8EBD,0x8F36,0x8F2E,0x8F35,0x8F32,0x8F39,0x8F37,0x8F34,
+0x9076,0x9079,0x907B,0x9086,0x90FA,0x9133,0x9135,0x9136,
+0x9193,0x9190,0x9191,0x918D,0x918F,0x9327,0x931E,0x9308,
+0x931F,0x9306,0x930F,0x937A,0x9338,0x933C,0x931B,0x9323,
+0x9312,0x9301,0x9346,0x932D,0x930E,0x930D,0x92CB,0x931D,
+0x92FA,0x9325,0x9313,0x92F9,0x92F7,0x9334,0x9302,0x9324,
+0x92FF,0x9329,0x9339,0x9335,0x932A,0x9314,0x930C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x930B,0x92FE,0x9309,0x9300,0x92FB,0x9316,0x95BC,0x95CD,
+0x95BE,0x95B9,0x95BA,0x95B6,0x95BF,0x95B5,0x95BD,0x96A9,
+0x96D4,0x970B,0x9712,0x9710,0x9799,0x9797,0x9794,0x97F0,
+0x97F8,0x9835,0x982F,0x9832,0x9924,0x991F,0x9927,0x9929,
+0x999E,0x99EE,0x99EC,0x99E5,0x99E4,0x99F0,0x99E3,0x99EA,
+0x99E9,0x99E7,0x9AB9,0x9ABF,0x9AB4,0x9ABB,0x9AF6,0x9AFA,
+0x9AF9,0x9AF7,0x9B33,0x9B80,0x9B85,0x9B87,0x9B7C,0x9B7E,
+0x9B7B,0x9B82,0x9B93,0x9B92,0x9B90,0x9B7A,0x9B95, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9B7D,0x9B88,0x9D25,0x9D17,0x9D20,0x9D1E,0x9D14,
+0x9D29,0x9D1D,0x9D18,0x9D22,0x9D10,0x9D19,0x9D1F,0x9E88,
+0x9E86,0x9E87,0x9EAE,0x9EAD,0x9ED5,0x9ED6,0x9EFA,0x9F12,
+0x9F3D,0x5126,0x5125,0x5122,0x5124,0x5120,0x5129,0x52F4,
+0x5693,0x568C,0x568D,0x5686,0x5684,0x5683,0x567E,0x5682,
+0x567F,0x5681,0x58D6,0x58D4,0x58CF,0x58D2,0x5B2D,0x5B25,
+0x5B32,0x5B23,0x5B2C,0x5B27,0x5B26,0x5B2F,0x5B2E,0x5B7B,
+0x5BF1,0x5BF2,0x5DB7,0x5E6C,0x5E6A,0x5FBE,0x5FBB,0x61C3,
+0x61B5,0x61BC,0x61E7,0x61E0,0x61E5,0x61E4,0x61E8,0x61DE,
+0x64EF,0x64E9,0x64E3,0x64EB,0x64E4,0x64E8,0x6581,0x6580,
+0x65B6,0x65DA,0x66D2,0x6A8D,0x6A96,0x6A81,0x6AA5,0x6A89,
+0x6A9F,0x6A9B,0x6AA1,0x6A9E,0x6A87,0x6A93,0x6A8E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6A95,0x6A83,0x6AA8,0x6AA4,0x6A91,0x6A7F,0x6AA6,0x6A9A,
+0x6A85,0x6A8C,0x6A92,0x6B5B,0x6BAD,0x6C09,0x6FCC,0x6FA9,
+0x6FF4,0x6FD4,0x6FE3,0x6FDC,0x6FED,0x6FE7,0x6FE6,0x6FDE,
+0x6FF2,0x6FDD,0x6FE2,0x6FE8,0x71E1,0x71F1,0x71E8,0x71F2,
+0x71E4,0x71F0,0x71E2,0x7373,0x736E,0x736F,0x7497,0x74B2,
+0x74AB,0x7490,0x74AA,0x74AD,0x74B1,0x74A5,0x74AF,0x7510,
+0x7511,0x7512,0x750F,0x7584,0x7643,0x7648,0x7649,0x7647,
+0x76A4,0x76E9,0x77B5,0x77AB,0x77B2,0x77B7,0x77B6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x77B4,0x77B1,0x77A8,0x77F0,0x78F3,0x78FD,0x7902,
+0x78FB,0x78FC,0x78F2,0x7905,0x78F9,0x78FE,0x7904,0x79AB,
+0x79A8,0x7A5C,0x7A5B,0x7A56,0x7A58,0x7A54,0x7A5A,0x7ABE,
+0x7AC0,0x7AC1,0x7C05,0x7C0F,0x7BF2,0x7C00,0x7BFF,0x7BFB,
+0x7C0E,0x7BF4,0x7C0B,0x7BF3,0x7C02,0x7C09,0x7C03,0x7C01,
+0x7BF8,0x7BFD,0x7C06,0x7BF0,0x7BF1,0x7C10,0x7C0A,0x7CE8,
+0x7E2D,0x7E3C,0x7E42,0x7E33,0x9848,0x7E38,0x7E2A,0x7E49,
+0x7E40,0x7E47,0x7E29,0x7E4C,0x7E30,0x7E3B,0x7E36,0x7E44,
+0x7E3A,0x7F45,0x7F7F,0x7F7E,0x7F7D,0x7FF4,0x7FF2,0x802C,
+0x81BB,0x81C4,0x81CC,0x81CA,0x81C5,0x81C7,0x81BC,0x81E9,
+0x825B,0x825A,0x825C,0x8583,0x8580,0x858F,0x85A7,0x8595,
+0x85A0,0x858B,0x85A3,0x857B,0x85A4,0x859A,0x859E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8577,0x857C,0x8589,0x85A1,0x857A,0x8578,0x8557,0x858E,
+0x8596,0x8586,0x858D,0x8599,0x859D,0x8581,0x85A2,0x8582,
+0x8588,0x8585,0x8579,0x8576,0x8598,0x8590,0x859F,0x8668,
+0x87BE,0x87AA,0x87AD,0x87C5,0x87B0,0x87AC,0x87B9,0x87B5,
+0x87BC,0x87AE,0x87C9,0x87C3,0x87C2,0x87CC,0x87B7,0x87AF,
+0x87C4,0x87CA,0x87B4,0x87B6,0x87BF,0x87B8,0x87BD,0x87DE,
+0x87B2,0x8935,0x8933,0x893C,0x893E,0x8941,0x8952,0x8937,
+0x8942,0x89AD,0x89AF,0x89AE,0x89F2,0x89F3,0x8B1E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8B18,0x8B16,0x8B11,0x8B05,0x8B0B,0x8B22,0x8B0F,
+0x8B12,0x8B15,0x8B07,0x8B0D,0x8B08,0x8B06,0x8B1C,0x8B13,
+0x8B1A,0x8C4F,0x8C70,0x8C72,0x8C71,0x8C6F,0x8C95,0x8C94,
+0x8CF9,0x8D6F,0x8E4E,0x8E4D,0x8E53,0x8E50,0x8E4C,0x8E47,
+0x8F43,0x8F40,0x9085,0x907E,0x9138,0x919A,0x91A2,0x919B,
+0x9199,0x919F,0x91A1,0x919D,0x91A0,0x93A1,0x9383,0x93AF,
+0x9364,0x9356,0x9347,0x937C,0x9358,0x935C,0x9376,0x9349,
+0x9350,0x9351,0x9360,0x936D,0x938F,0x934C,0x936A,0x9379,
+0x9357,0x9355,0x9352,0x934F,0x9371,0x9377,0x937B,0x9361,
+0x935E,0x9363,0x9367,0x9380,0x934E,0x9359,0x95C7,0x95C0,
+0x95C9,0x95C3,0x95C5,0x95B7,0x96AE,0x96B0,0x96AC,0x9720,
+0x971F,0x9718,0x971D,0x9719,0x979A,0x97A1,0x979C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x979E,0x979D,0x97D5,0x97D4,0x97F1,0x9841,0x9844,0x984A,
+0x9849,0x9845,0x9843,0x9925,0x992B,0x992C,0x992A,0x9933,
+0x9932,0x992F,0x992D,0x9931,0x9930,0x9998,0x99A3,0x99A1,
+0x9A02,0x99FA,0x99F4,0x99F7,0x99F9,0x99F8,0x99F6,0x99FB,
+0x99FD,0x99FE,0x99FC,0x9A03,0x9ABE,0x9AFE,0x9AFD,0x9B01,
+0x9AFC,0x9B48,0x9B9A,0x9BA8,0x9B9E,0x9B9B,0x9BA6,0x9BA1,
+0x9BA5,0x9BA4,0x9B86,0x9BA2,0x9BA0,0x9BAF,0x9D33,0x9D41,
+0x9D67,0x9D36,0x9D2E,0x9D2F,0x9D31,0x9D38,0x9D30, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9D45,0x9D42,0x9D43,0x9D3E,0x9D37,0x9D40,0x9D3D,
+0x7FF5,0x9D2D,0x9E8A,0x9E89,0x9E8D,0x9EB0,0x9EC8,0x9EDA,
+0x9EFB,0x9EFF,0x9F24,0x9F23,0x9F22,0x9F54,0x9FA0,0x5131,
+0x512D,0x512E,0x5698,0x569C,0x5697,0x569A,0x569D,0x5699,
+0x5970,0x5B3C,0x5C69,0x5C6A,0x5DC0,0x5E6D,0x5E6E,0x61D8,
+0x61DF,0x61ED,0x61EE,0x61F1,0x61EA,0x61F0,0x61EB,0x61D6,
+0x61E9,0x64FF,0x6504,0x64FD,0x64F8,0x6501,0x6503,0x64FC,
+0x6594,0x65DB,0x66DA,0x66DB,0x66D8,0x6AC5,0x6AB9,0x6ABD,
+0x6AE1,0x6AC6,0x6ABA,0x6AB6,0x6AB7,0x6AC7,0x6AB4,0x6AAD,
+0x6B5E,0x6BC9,0x6C0B,0x7007,0x700C,0x700D,0x7001,0x7005,
+0x7014,0x700E,0x6FFF,0x7000,0x6FFB,0x7026,0x6FFC,0x6FF7,
+0x700A,0x7201,0x71FF,0x71F9,0x7203,0x71FD,0x7376, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x74B8,0x74C0,0x74B5,0x74C1,0x74BE,0x74B6,0x74BB,0x74C2,
+0x7514,0x7513,0x765C,0x7664,0x7659,0x7650,0x7653,0x7657,
+0x765A,0x76A6,0x76BD,0x76EC,0x77C2,0x77BA,0x78FF,0x790C,
+0x7913,0x7914,0x7909,0x7910,0x7912,0x7911,0x79AD,0x79AC,
+0x7A5F,0x7C1C,0x7C29,0x7C19,0x7C20,0x7C1F,0x7C2D,0x7C1D,
+0x7C26,0x7C28,0x7C22,0x7C25,0x7C30,0x7E5C,0x7E50,0x7E56,
+0x7E63,0x7E58,0x7E62,0x7E5F,0x7E51,0x7E60,0x7E57,0x7E53,
+0x7FB5,0x7FB3,0x7FF7,0x7FF8,0x8075,0x81D1,0x81D2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x81D0,0x825F,0x825E,0x85B4,0x85C6,0x85C0,0x85C3,
+0x85C2,0x85B3,0x85B5,0x85BD,0x85C7,0x85C4,0x85BF,0x85CB,
+0x85CE,0x85C8,0x85C5,0x85B1,0x85B6,0x85D2,0x8624,0x85B8,
+0x85B7,0x85BE,0x8669,0x87E7,0x87E6,0x87E2,0x87DB,0x87EB,
+0x87EA,0x87E5,0x87DF,0x87F3,0x87E4,0x87D4,0x87DC,0x87D3,
+0x87ED,0x87D8,0x87E3,0x87A4,0x87D7,0x87D9,0x8801,0x87F4,
+0x87E8,0x87DD,0x8953,0x894B,0x894F,0x894C,0x8946,0x8950,
+0x8951,0x8949,0x8B2A,0x8B27,0x8B23,0x8B33,0x8B30,0x8B35,
+0x8B47,0x8B2F,0x8B3C,0x8B3E,0x8B31,0x8B25,0x8B37,0x8B26,
+0x8B36,0x8B2E,0x8B24,0x8B3B,0x8B3D,0x8B3A,0x8C42,0x8C75,
+0x8C99,0x8C98,0x8C97,0x8CFE,0x8D04,0x8D02,0x8D00,0x8E5C,
+0x8E62,0x8E60,0x8E57,0x8E56,0x8E5E,0x8E65,0x8E67, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8E5B,0x8E5A,0x8E61,0x8E5D,0x8E69,0x8E54,0x8F46,0x8F47,
+0x8F48,0x8F4B,0x9128,0x913A,0x913B,0x913E,0x91A8,0x91A5,
+0x91A7,0x91AF,0x91AA,0x93B5,0x938C,0x9392,0x93B7,0x939B,
+0x939D,0x9389,0x93A7,0x938E,0x93AA,0x939E,0x93A6,0x9395,
+0x9388,0x9399,0x939F,0x938D,0x93B1,0x9391,0x93B2,0x93A4,
+0x93A8,0x93B4,0x93A3,0x93A5,0x95D2,0x95D3,0x95D1,0x96B3,
+0x96D7,0x96DA,0x5DC2,0x96DF,0x96D8,0x96DD,0x9723,0x9722,
+0x9725,0x97AC,0x97AE,0x97A8,0x97AB,0x97A4,0x97AA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x97A2,0x97A5,0x97D7,0x97D9,0x97D6,0x97D8,0x97FA,
+0x9850,0x9851,0x9852,0x98B8,0x9941,0x993C,0x993A,0x9A0F,
+0x9A0B,0x9A09,0x9A0D,0x9A04,0x9A11,0x9A0A,0x9A05,0x9A07,
+0x9A06,0x9AC0,0x9ADC,0x9B08,0x9B04,0x9B05,0x9B29,0x9B35,
+0x9B4A,0x9B4C,0x9B4B,0x9BC7,0x9BC6,0x9BC3,0x9BBF,0x9BC1,
+0x9BB5,0x9BB8,0x9BD3,0x9BB6,0x9BC4,0x9BB9,0x9BBD,0x9D5C,
+0x9D53,0x9D4F,0x9D4A,0x9D5B,0x9D4B,0x9D59,0x9D56,0x9D4C,
+0x9D57,0x9D52,0x9D54,0x9D5F,0x9D58,0x9D5A,0x9E8E,0x9E8C,
+0x9EDF,0x9F01,0x9F00,0x9F16,0x9F25,0x9F2B,0x9F2A,0x9F29,
+0x9F28,0x9F4C,0x9F55,0x5134,0x5135,0x5296,0x52F7,0x53B4,
+0x56AB,0x56AD,0x56A6,0x56A7,0x56AA,0x56AC,0x58DA,0x58DD,
+0x58DB,0x5912,0x5B3D,0x5B3E,0x5B3F,0x5DC3,0x5E70, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5FBF,0x61FB,0x6507,0x6510,0x650D,0x6509,0x650C,0x650E,
+0x6584,0x65DE,0x65DD,0x66DE,0x6AE7,0x6AE0,0x6ACC,0x6AD1,
+0x6AD9,0x6ACB,0x6ADF,0x6ADC,0x6AD0,0x6AEB,0x6ACF,0x6ACD,
+0x6ADE,0x6B60,0x6BB0,0x6C0C,0x7019,0x7027,0x7020,0x7016,
+0x702B,0x7021,0x7022,0x7023,0x7029,0x7017,0x7024,0x701C,
+0x702A,0x720C,0x720A,0x7207,0x7202,0x7205,0x72A5,0x72A6,
+0x72A4,0x72A3,0x72A1,0x74CB,0x74C5,0x74B7,0x74C3,0x7516,
+0x7660,0x77C9,0x77CA,0x77C4,0x77F1,0x791D,0x791B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7921,0x791C,0x7917,0x791E,0x79B0,0x7A67,0x7A68,
+0x7C33,0x7C3C,0x7C39,0x7C2C,0x7C3B,0x7CEC,0x7CEA,0x7E76,
+0x7E75,0x7E78,0x7E70,0x7E77,0x7E6F,0x7E7A,0x7E72,0x7E74,
+0x7E68,0x7F4B,0x7F4A,0x7F83,0x7F86,0x7FB7,0x7FFD,0x7FFE,
+0x8078,0x81D7,0x81D5,0x8264,0x8261,0x8263,0x85EB,0x85F1,
+0x85ED,0x85D9,0x85E1,0x85E8,0x85DA,0x85D7,0x85EC,0x85F2,
+0x85F8,0x85D8,0x85DF,0x85E3,0x85DC,0x85D1,0x85F0,0x85E6,
+0x85EF,0x85DE,0x85E2,0x8800,0x87FA,0x8803,0x87F6,0x87F7,
+0x8809,0x880C,0x880B,0x8806,0x87FC,0x8808,0x87FF,0x880A,
+0x8802,0x8962,0x895A,0x895B,0x8957,0x8961,0x895C,0x8958,
+0x895D,0x8959,0x8988,0x89B7,0x89B6,0x89F6,0x8B50,0x8B48,
+0x8B4A,0x8B40,0x8B53,0x8B56,0x8B54,0x8B4B,0x8B55, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B51,0x8B42,0x8B52,0x8B57,0x8C43,0x8C77,0x8C76,0x8C9A,
+0x8D06,0x8D07,0x8D09,0x8DAC,0x8DAA,0x8DAD,0x8DAB,0x8E6D,
+0x8E78,0x8E73,0x8E6A,0x8E6F,0x8E7B,0x8EC2,0x8F52,0x8F51,
+0x8F4F,0x8F50,0x8F53,0x8FB4,0x9140,0x913F,0x91B0,0x91AD,
+0x93DE,0x93C7,0x93CF,0x93C2,0x93DA,0x93D0,0x93F9,0x93EC,
+0x93CC,0x93D9,0x93A9,0x93E6,0x93CA,0x93D4,0x93EE,0x93E3,
+0x93D5,0x93C4,0x93CE,0x93C0,0x93D2,0x93E7,0x957D,0x95DA,
+0x95DB,0x96E1,0x9729,0x972B,0x972C,0x9728,0x9726, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x97B3,0x97B7,0x97B6,0x97DD,0x97DE,0x97DF,0x985C,
+0x9859,0x985D,0x9857,0x98BF,0x98BD,0x98BB,0x98BE,0x9948,
+0x9947,0x9943,0x99A6,0x99A7,0x9A1A,0x9A15,0x9A25,0x9A1D,
+0x9A24,0x9A1B,0x9A22,0x9A20,0x9A27,0x9A23,0x9A1E,0x9A1C,
+0x9A14,0x9AC2,0x9B0B,0x9B0A,0x9B0E,0x9B0C,0x9B37,0x9BEA,
+0x9BEB,0x9BE0,0x9BDE,0x9BE4,0x9BE6,0x9BE2,0x9BF0,0x9BD4,
+0x9BD7,0x9BEC,0x9BDC,0x9BD9,0x9BE5,0x9BD5,0x9BE1,0x9BDA,
+0x9D77,0x9D81,0x9D8A,0x9D84,0x9D88,0x9D71,0x9D80,0x9D78,
+0x9D86,0x9D8B,0x9D8C,0x9D7D,0x9D6B,0x9D74,0x9D75,0x9D70,
+0x9D69,0x9D85,0x9D73,0x9D7B,0x9D82,0x9D6F,0x9D79,0x9D7F,
+0x9D87,0x9D68,0x9E94,0x9E91,0x9EC0,0x9EFC,0x9F2D,0x9F40,
+0x9F41,0x9F4D,0x9F56,0x9F57,0x9F58,0x5337,0x56B2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x56B5,0x56B3,0x58E3,0x5B45,0x5DC6,0x5DC7,0x5EEE,0x5EEF,
+0x5FC0,0x5FC1,0x61F9,0x6517,0x6516,0x6515,0x6513,0x65DF,
+0x66E8,0x66E3,0x66E4,0x6AF3,0x6AF0,0x6AEA,0x6AE8,0x6AF9,
+0x6AF1,0x6AEE,0x6AEF,0x703C,0x7035,0x702F,0x7037,0x7034,
+0x7031,0x7042,0x7038,0x703F,0x703A,0x7039,0x7040,0x703B,
+0x7033,0x7041,0x7213,0x7214,0x72A8,0x737D,0x737C,0x74BA,
+0x76AB,0x76AA,0x76BE,0x76ED,0x77CC,0x77CE,0x77CF,0x77CD,
+0x77F2,0x7925,0x7923,0x7927,0x7928,0x7924,0x7929, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x79B2,0x7A6E,0x7A6C,0x7A6D,0x7AF7,0x7C49,0x7C48,
+0x7C4A,0x7C47,0x7C45,0x7CEE,0x7E7B,0x7E7E,0x7E81,0x7E80,
+0x7FBA,0x7FFF,0x8079,0x81DB,0x81D9,0x820B,0x8268,0x8269,
+0x8622,0x85FF,0x8601,0x85FE,0x861B,0x8600,0x85F6,0x8604,
+0x8609,0x8605,0x860C,0x85FD,0x8819,0x8810,0x8811,0x8817,
+0x8813,0x8816,0x8963,0x8966,0x89B9,0x89F7,0x8B60,0x8B6A,
+0x8B5D,0x8B68,0x8B63,0x8B65,0x8B67,0x8B6D,0x8DAE,0x8E86,
+0x8E88,0x8E84,0x8F59,0x8F56,0x8F57,0x8F55,0x8F58,0x8F5A,
+0x908D,0x9143,0x9141,0x91B7,0x91B5,0x91B2,0x91B3,0x940B,
+0x9413,0x93FB,0x9420,0x940F,0x9414,0x93FE,0x9415,0x9410,
+0x9428,0x9419,0x940D,0x93F5,0x9400,0x93F7,0x9407,0x940E,
+0x9416,0x9412,0x93FA,0x9409,0x93F8,0x940A,0x93FF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x93FC,0x940C,0x93F6,0x9411,0x9406,0x95DE,0x95E0,0x95DF,
+0x972E,0x972F,0x97B9,0x97BB,0x97FD,0x97FE,0x9860,0x9862,
+0x9863,0x985F,0x98C1,0x98C2,0x9950,0x994E,0x9959,0x994C,
+0x994B,0x9953,0x9A32,0x9A34,0x9A31,0x9A2C,0x9A2A,0x9A36,
+0x9A29,0x9A2E,0x9A38,0x9A2D,0x9AC7,0x9ACA,0x9AC6,0x9B10,
+0x9B12,0x9B11,0x9C0B,0x9C08,0x9BF7,0x9C05,0x9C12,0x9BF8,
+0x9C40,0x9C07,0x9C0E,0x9C06,0x9C17,0x9C14,0x9C09,0x9D9F,
+0x9D99,0x9DA4,0x9D9D,0x9D92,0x9D98,0x9D90,0x9D9B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9DA0,0x9D94,0x9D9C,0x9DAA,0x9D97,0x9DA1,0x9D9A,
+0x9DA2,0x9DA8,0x9D9E,0x9DA3,0x9DBF,0x9DA9,0x9D96,0x9DA6,
+0x9DA7,0x9E99,0x9E9B,0x9E9A,0x9EE5,0x9EE4,0x9EE7,0x9EE6,
+0x9F30,0x9F2E,0x9F5B,0x9F60,0x9F5E,0x9F5D,0x9F59,0x9F91,
+0x513A,0x5139,0x5298,0x5297,0x56C3,0x56BD,0x56BE,0x5B48,
+0x5B47,0x5DCB,0x5DCF,0x5EF1,0x61FD,0x651B,0x6B02,0x6AFC,
+0x6B03,0x6AF8,0x6B00,0x7043,0x7044,0x704A,0x7048,0x7049,
+0x7045,0x7046,0x721D,0x721A,0x7219,0x737E,0x7517,0x766A,
+0x77D0,0x792D,0x7931,0x792F,0x7C54,0x7C53,0x7CF2,0x7E8A,
+0x7E87,0x7E88,0x7E8B,0x7E86,0x7E8D,0x7F4D,0x7FBB,0x8030,
+0x81DD,0x8618,0x862A,0x8626,0x861F,0x8623,0x861C,0x8619,
+0x8627,0x862E,0x8621,0x8620,0x8629,0x861E,0x8625, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8829,0x881D,0x881B,0x8820,0x8824,0x881C,0x882B,0x884A,
+0x896D,0x8969,0x896E,0x896B,0x89FA,0x8B79,0x8B78,0x8B45,
+0x8B7A,0x8B7B,0x8D10,0x8D14,0x8DAF,0x8E8E,0x8E8C,0x8F5E,
+0x8F5B,0x8F5D,0x9146,0x9144,0x9145,0x91B9,0x943F,0x943B,
+0x9436,0x9429,0x943D,0x943C,0x9430,0x9439,0x942A,0x9437,
+0x942C,0x9440,0x9431,0x95E5,0x95E4,0x95E3,0x9735,0x973A,
+0x97BF,0x97E1,0x9864,0x98C9,0x98C6,0x98C0,0x9958,0x9956,
+0x9A39,0x9A3D,0x9A46,0x9A44,0x9A42,0x9A41,0x9A3A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9A3F,0x9ACD,0x9B15,0x9B17,0x9B18,0x9B16,0x9B3A,
+0x9B52,0x9C2B,0x9C1D,0x9C1C,0x9C2C,0x9C23,0x9C28,0x9C29,
+0x9C24,0x9C21,0x9DB7,0x9DB6,0x9DBC,0x9DC1,0x9DC7,0x9DCA,
+0x9DCF,0x9DBE,0x9DC5,0x9DC3,0x9DBB,0x9DB5,0x9DCE,0x9DB9,
+0x9DBA,0x9DAC,0x9DC8,0x9DB1,0x9DAD,0x9DCC,0x9DB3,0x9DCD,
+0x9DB2,0x9E7A,0x9E9C,0x9EEB,0x9EEE,0x9EED,0x9F1B,0x9F18,
+0x9F1A,0x9F31,0x9F4E,0x9F65,0x9F64,0x9F92,0x4EB9,0x56C6,
+0x56C5,0x56CB,0x5971,0x5B4B,0x5B4C,0x5DD5,0x5DD1,0x5EF2,
+0x6521,0x6520,0x6526,0x6522,0x6B0B,0x6B08,0x6B09,0x6C0D,
+0x7055,0x7056,0x7057,0x7052,0x721E,0x721F,0x72A9,0x737F,
+0x74D8,0x74D5,0x74D9,0x74D7,0x766D,0x76AD,0x7935,0x79B4,
+0x7A70,0x7A71,0x7C57,0x7C5C,0x7C59,0x7C5B,0x7C5A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7CF4,0x7CF1,0x7E91,0x7F4F,0x7F87,0x81DE,0x826B,0x8634,
+0x8635,0x8633,0x862C,0x8632,0x8636,0x882C,0x8828,0x8826,
+0x882A,0x8825,0x8971,0x89BF,0x89BE,0x89FB,0x8B7E,0x8B84,
+0x8B82,0x8B86,0x8B85,0x8B7F,0x8D15,0x8E95,0x8E94,0x8E9A,
+0x8E92,0x8E90,0x8E96,0x8E97,0x8F60,0x8F62,0x9147,0x944C,
+0x9450,0x944A,0x944B,0x944F,0x9447,0x9445,0x9448,0x9449,
+0x9446,0x973F,0x97E3,0x986A,0x9869,0x98CB,0x9954,0x995B,
+0x9A4E,0x9A53,0x9A54,0x9A4C,0x9A4F,0x9A48,0x9A4A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9A49,0x9A52,0x9A50,0x9AD0,0x9B19,0x9B2B,0x9B3B,
+0x9B56,0x9B55,0x9C46,0x9C48,0x9C3F,0x9C44,0x9C39,0x9C33,
+0x9C41,0x9C3C,0x9C37,0x9C34,0x9C32,0x9C3D,0x9C36,0x9DDB,
+0x9DD2,0x9DDE,0x9DDA,0x9DCB,0x9DD0,0x9DDC,0x9DD1,0x9DDF,
+0x9DE9,0x9DD9,0x9DD8,0x9DD6,0x9DF5,0x9DD5,0x9DDD,0x9EB6,
+0x9EF0,0x9F35,0x9F33,0x9F32,0x9F42,0x9F6B,0x9F95,0x9FA2,
+0x513D,0x5299,0x58E8,0x58E7,0x5972,0x5B4D,0x5DD8,0x882F,
+0x5F4F,0x6201,0x6203,0x6204,0x6529,0x6525,0x6596,0x66EB,
+0x6B11,0x6B12,0x6B0F,0x6BCA,0x705B,0x705A,0x7222,0x7382,
+0x7381,0x7383,0x7670,0x77D4,0x7C67,0x7C66,0x7E95,0x826C,
+0x863A,0x8640,0x8639,0x863C,0x8631,0x863B,0x863E,0x8830,
+0x8832,0x882E,0x8833,0x8976,0x8974,0x8973,0x89FE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B8C,0x8B8E,0x8B8B,0x8B88,0x8C45,0x8D19,0x8E98,0x8F64,
+0x8F63,0x91BC,0x9462,0x9455,0x945D,0x9457,0x945E,0x97C4,
+0x97C5,0x9800,0x9A56,0x9A59,0x9B1E,0x9B1F,0x9B20,0x9C52,
+0x9C58,0x9C50,0x9C4A,0x9C4D,0x9C4B,0x9C55,0x9C59,0x9C4C,
+0x9C4E,0x9DFB,0x9DF7,0x9DEF,0x9DE3,0x9DEB,0x9DF8,0x9DE4,
+0x9DF6,0x9DE1,0x9DEE,0x9DE6,0x9DF2,0x9DF0,0x9DE2,0x9DEC,
+0x9DF4,0x9DF3,0x9DE8,0x9DED,0x9EC2,0x9ED0,0x9EF2,0x9EF3,
+0x9F06,0x9F1C,0x9F38,0x9F37,0x9F36,0x9F43,0x9F4F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9F71,0x9F70,0x9F6E,0x9F6F,0x56D3,0x56CD,0x5B4E,
+0x5C6D,0x652D,0x66ED,0x66EE,0x6B13,0x705F,0x7061,0x705D,
+0x7060,0x7223,0x74DB,0x74E5,0x77D5,0x7938,0x79B7,0x79B6,
+0x7C6A,0x7E97,0x7F89,0x826D,0x8643,0x8838,0x8837,0x8835,
+0x884B,0x8B94,0x8B95,0x8E9E,0x8E9F,0x8EA0,0x8E9D,0x91BE,
+0x91BD,0x91C2,0x946B,0x9468,0x9469,0x96E5,0x9746,0x9743,
+0x9747,0x97C7,0x97E5,0x9A5E,0x9AD5,0x9B59,0x9C63,0x9C67,
+0x9C66,0x9C62,0x9C5E,0x9C60,0x9E02,0x9DFE,0x9E07,0x9E03,
+0x9E06,0x9E05,0x9E00,0x9E01,0x9E09,0x9DFF,0x9DFD,0x9E04,
+0x9EA0,0x9F1E,0x9F46,0x9F74,0x9F75,0x9F76,0x56D4,0x652E,
+0x65B8,0x6B18,0x6B19,0x6B17,0x6B1A,0x7062,0x7226,0x72AA,
+0x77D8,0x77D9,0x7939,0x7C69,0x7C6B,0x7CF6,0x7E9A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7E98,0x7E9B,0x7E99,0x81E0,0x81E1,0x8646,0x8647,0x8648,
+0x8979,0x897A,0x897C,0x897B,0x89FF,0x8B98,0x8B99,0x8EA5,
+0x8EA4,0x8EA3,0x946E,0x946D,0x946F,0x9471,0x9473,0x9749,
+0x9872,0x995F,0x9C68,0x9C6E,0x9C6D,0x9E0B,0x9E0D,0x9E10,
+0x9E0F,0x9E12,0x9E11,0x9EA1,0x9EF5,0x9F09,0x9F47,0x9F78,
+0x9F7B,0x9F7A,0x9F79,0x571E,0x7066,0x7C6F,0x883C,0x8DB2,
+0x8EA6,0x91C3,0x9474,0x9478,0x9476,0x9475,0x9A60,0x9C74,
+0x9C73,0x9C71,0x9C75,0x9E14,0x9E13,0x9EF6,0x9F0A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9FA4,0x7068,0x7065,0x7CF7,0x866A,0x883E,0x883D,
+0x883F,0x8B9E,0x8C9C,0x8EA9,0x8EC9,0x974B,0x9873,0x9874,
+0x98CC,0x9961,0x99AB,0x9A64,0x9A66,0x9A67,0x9B24,0x9E15,
+0x9E17,0x9F48,0x6207,0x6B1E,0x7227,0x864C,0x8EA8,0x9482,
+0x9480,0x9481,0x9A69,0x9A68,0x9B2E,0x9E19,0x7229,0x864B,
+0x8B9F,0x9483,0x9C79,0x9EB7,0x7675,0x9A6B,0x9C7A,0x9E1D,
+0x7069,0x706A,0x9EA4,0x9F7E,0x9F49,0x9F98};
+
+static int func_big5_uni_onechar(int code){
+ if ((code>=0xA140)&&(code<=0xC7FC))
+ return(tab_big5_uni0[code-0xA140]);
+ if ((code>=0xC940)&&(code<=0xF9D5))
+ return(tab_big5_uni1[code-0xC940]);
+ return(0);
+}
+
+
+/* page 0 0x00A2-0x00F7 */
+static uint16 tab_uni_big50[]={
+0xA246,0xA247, 0,0xA244, 0,0xA1B1, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA258,0xA1D3,
+ 0, 0, 0, 0, 0,0xA150, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1D1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1D2};
+
+/* page 1 0x02C7-0x0451 */
+static uint16 tab_uni_big51[]={
+0xA3BE, 0,0xA3BC,0xA3BD,0xA3BF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA3BB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA344,0xA345,0xA346,0xA347,0xA348,0xA349,
+0xA34A,0xA34B,0xA34C,0xA34D,0xA34E,0xA34F,0xA350,0xA351,
+0xA352,0xA353,0xA354, 0,0xA355,0xA356,0xA357,0xA358,
+0xA359,0xA35A,0xA35B, 0, 0, 0, 0, 0,
+ 0, 0,0xA35C,0xA35D,0xA35E,0xA35F,0xA360,0xA361,
+0xA362,0xA363,0xA364,0xA365,0xA366,0xA367,0xA368,0xA369,
+0xA36A,0xA36B,0xA36C, 0,0xA36D,0xA36E,0xA36F,0xA370,
+0xA371,0xA372,0xA373, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xC7B3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xC7B1,0xC7B2,0xC7B4,
+0xC7B5,0xC7B6,0xC7B7,0xC7B8,0xC7B9,0xC7BA, 0, 0,
+ 0, 0, 0, 0,0xC7BB,0xC7BC,0xC7BD,0xC7BE,
+0xC7BF,0xC7C0,0xC7C1,0xC7C2,0xC7C3,0xC7C4,0xC7C5,0xC7C6,
+0xC7C7,0xC7C8,0xC7C9,0xC7CA,0xC7CB,0xC7CC,0xC7CD,0xC7CF,
+0xC7D0,0xC7D1,0xC7D2,0xC7D3,0xC7D4,0xC7D5,0xC7D6,0xC7D7,
+0xC7D8,0xC7D9,0xC7DA,0xC7DB,0xC7DC,0xC7DD,0xC7DE,0xC7DF,
+0xC7E0,0xC7E1,0xC7E2,0xC7E3,0xC7E4,0xC7E5,0xC7E6,0xC7E7,
+0xC7E8, 0,0xC7CE};
+
+/* page 2 0x2013-0x22BF */
+static uint16 tab_uni_big52[]={
+0xA156,0xA158, 0, 0, 0,0xA1A5,0xA1A6, 0,
+ 0,0xA1A7,0xA1A8, 0, 0, 0, 0,0xA145,
+ 0, 0,0xA14C,0xA14B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA1AC,
+ 0, 0,0xA1AB, 0, 0, 0, 0, 0,
+0xA1B0, 0, 0,0xA1C2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA24A, 0,0xA1C1, 0, 0, 0,0xA24B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA2B9,0xA2BA,0xA2BB,
+0xA2BC,0xA2BD,0xA2BE,0xA2BF,0xA2C0,0xA2C1,0xA2C2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1F6,0xA1F4,0xA1F7,
+0xA1F5, 0, 0,0xA1F8,0xA1F9,0xA1FB,0xA1FA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA1D4,
+ 0, 0, 0,0xA1DB,0xA1E8,0xA1E7, 0, 0,
+0xA1FD, 0,0xA1FC, 0, 0, 0,0xA1E4,0xA1E5,
+0xA1EC, 0, 0,0xA1ED, 0, 0, 0, 0,
+ 0,0xA1EF,0xA1EE, 0, 0, 0, 0, 0,
+ 0,0xA1E3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA1DC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1DA,0xA1DD, 0,
+ 0, 0, 0,0xA1D8,0xA1D9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA1E6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA1E9};
+
+/* page 3 0x2460-0x2642 */
+static uint16 tab_uni_big53[]={
+0xC7E9,0xC7EA,0xC7EB,0xC7EC,0xC7ED,0xC7EE,0xC7EF,0xC7F0,
+0xC7F1,0xC7F2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xC7F3,0xC7F4,0xC7F5,0xC7F6,
+0xC7F7,0xC7F8,0xC7F9,0xC7FA,0xC7FB,0xC7FC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA277, 0,0xA278, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA27A, 0, 0, 0,
+0xA27B, 0, 0, 0,0xA27C, 0, 0, 0,
+0xA27D, 0, 0, 0,0xA275, 0, 0, 0,
+ 0, 0, 0, 0,0xA274, 0, 0, 0,
+ 0, 0, 0, 0,0xA273, 0, 0, 0,
+ 0, 0, 0, 0,0xA272, 0, 0, 0,
+ 0, 0, 0, 0,0xA271, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA2A4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA2A5, 0,
+ 0,0xA2A7, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA2A6, 0, 0,0xA27E,0xA2A1,0xA2A3,
+0xA2A2,0xA2AC,0xA2AD,0xA2AE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA262,0xA263,0xA264,0xA265,0xA266,0xA267,0xA268,
+0xA269,0xA270,0xA26F,0xA26E,0xA26D,0xA26C,0xA26B,0xA26A,
+ 0, 0, 0, 0,0xA276,0xA279, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1BD,0xA1BC, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA1B6,0xA1B5, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA1BF,0xA1BE, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA1BB,0xA1BA,
+ 0, 0, 0,0xA1B3, 0, 0,0xA1B7,0xA1B4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA2A8,0xA2A9,0xA2AB,0xA2AA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1B9,0xA1B8, 0,
+ 0,0xA1F3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1F0,0xA1F2,0xA1F1};
+
+/* page 4 0x3000-0x3129 */
+static uint16 tab_uni_big54[]={
+0xA140,0xA142,0xA143,0xA1B2, 0,0xC6A4, 0, 0,
+0xA171,0xA172,0xA16D,0xA16E,0xA175,0xA176,0xA179,0xA17A,
+0xA169,0xA16A,0xA245, 0,0xA165,0xA166, 0, 0,
+ 0, 0, 0, 0, 0,0xA1A9,0xA1AA, 0,
+ 0,0xA2C3,0xA2C4,0xA2C5,0xA2C6,0xA2C7,0xA2C8,0xA2C9,
+0xA2CA,0xA2CB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC6A5,0xC6A6,0xC6A7,0xC6A8,0xC6A9,0xC6AA,0xC6AB,
+0xC6AC,0xC6AD,0xC6AE,0xC6AF,0xC6B0,0xC6B1,0xC6B2,0xC6B3,
+0xC6B4,0xC6B5,0xC6B6,0xC6B7,0xC6B8,0xC6B9,0xC6BA,0xC6BB,
+0xC6BC,0xC6BD,0xC6BE,0xC6BF,0xC6C0,0xC6C1,0xC6C2,0xC6C3,
+0xC6C4,0xC6C5,0xC6C6,0xC6C7,0xC6C8,0xC6C9,0xC6CA,0xC6CB,
+0xC6CC,0xC6CD,0xC6CE,0xC6CF,0xC6D0,0xC6D1,0xC6D2,0xC6D3,
+0xC6D4,0xC6D5,0xC6D6,0xC6D7,0xC6D8,0xC6D9,0xC6DA,0xC6DB,
+0xC6DC,0xC6DD,0xC6DE,0xC6DF,0xC6E0,0xC6E1,0xC6E2,0xC6E3,
+0xC6E4,0xC6E5,0xC6E6,0xC6E7,0xC6E8,0xC6E9,0xC6EA,0xC6EB,
+0xC6EC,0xC6ED,0xC6EE,0xC6EF,0xC6F0,0xC6F1,0xC6F2,0xC6F3,
+0xC6F4,0xC6F5,0xC6F6,0xC6F7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xC6A2,0xC6A3, 0,
+ 0,0xC6F8,0xC6F9,0xC6FA,0xC6FB,0xC6FC,0xC6FD,0xC6FE,
+0xC740,0xC741,0xC742,0xC743,0xC744,0xC745,0xC746,0xC747,
+0xC748,0xC749,0xC74A,0xC74B,0xC74C,0xC74D,0xC74E,0xC74F,
+0xC750,0xC751,0xC752,0xC753,0xC754,0xC755,0xC756,0xC757,
+0xC758,0xC759,0xC75A,0xC75B,0xC75C,0xC75D,0xC75E,0xC75F,
+0xC760,0xC761,0xC762,0xC763,0xC764,0xC765,0xC766,0xC767,
+0xC768,0xC769,0xC76A,0xC76B,0xC76C,0xC76D,0xC76E,0xC76F,
+0xC770,0xC771,0xC772,0xC773,0xC774,0xC775,0xC776,0xC777,
+0xC778,0xC779,0xC77A,0xC77B,0xC77C,0xC77D,0xC77E,0xC7A1,
+0xC7A2,0xC7A3,0xC7A4,0xC7A5,0xC7A6,0xC7A7,0xC7A8,0xC7A9,
+0xC7AA,0xC7AB,0xC7AC,0xC7AD,0xC7AE,0xC7AF,0xC7B0, 0,
+ 0, 0, 0, 0, 0, 0,0xC6A1, 0,
+ 0, 0, 0, 0, 0,0xA374,0xA375,0xA376,
+0xA377,0xA378,0xA379,0xA37A,0xA37B,0xA37C,0xA37D,0xA37E,
+0xA3A1,0xA3A2,0xA3A3,0xA3A4,0xA3A5,0xA3A6,0xA3A7,0xA3A8,
+0xA3A9,0xA3AA,0xA3AB,0xA3AC,0xA3AD,0xA3AE,0xA3AF,0xA3B0,
+0xA3B1,0xA3B2,0xA3B3,0xA3B4,0xA3B5,0xA3B6,0xA3B7,0xA3B8,
+0xA3B9,0xA3BA};
+
+/* page 5 0x32A3-0x32A3 */
+static uint16 tab_uni_big55[]={
+0xA1C0};
+
+/* page 6 0x338E-0x33D5 */
+static uint16 tab_uni_big56[]={
+0xA255,0xA256, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA250,0xA251,
+0xA252, 0, 0,0xA254, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA257, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA253, 0, 0,0xA1EB,0xA1EA, 0, 0,0xA24F
+};
+
+/* page 7 0x4E00-0x9483 */
+static uint16 tab_uni_big57[]={
+0xA440,0xA442, 0,0xA443, 0, 0, 0,0xC945,
+0xA456,0xA454,0xA457,0xA455,0xC946,0xA4A3,0xC94F,0xC94D,
+0xA4A2,0xA4A1, 0, 0,0xA542,0xA541,0xA540, 0,
+0xA543,0xA4FE, 0, 0, 0, 0,0xA5E0,0xA5E1,
+ 0, 0, 0, 0, 0, 0,0xA8C3, 0,
+ 0, 0, 0,0xA458, 0,0xA4A4,0xC950, 0,
+0xA4A5,0xC963,0xA6EA,0xCBB1, 0, 0, 0, 0,
+0xA459,0xA4A6, 0,0xA544,0xC964, 0, 0, 0,
+ 0, 0,0xC940,0xA444, 0,0xA45B, 0,0xC947,
+0xA45C, 0, 0,0xA4A7, 0,0xA545,0xA547,0xA546,
+ 0, 0,0xA5E2,0xA5E3, 0, 0,0xA8C4, 0,
+0xADBC,0xA441, 0, 0,0xC941,0xA445,0xA45E,0xA45D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA5E4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA8C5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0AE,0xD44B,
+ 0, 0,0xB6C3,0xDCB1,0xDCB2, 0,0xA446, 0,
+0xA4A9, 0, 0,0xA8C6,0xA447,0xC948,0xA45F, 0,
+ 0,0xA4AA,0xA4AC,0xC951,0xA4AD,0xA4AB, 0, 0,
+ 0,0xA5E5, 0,0xA8C7, 0, 0,0xA8C8,0xAB45,
+ 0,0xA460,0xA4AE, 0,0xA5E6,0xA5E8,0xA5E7, 0,
+0xA6EB, 0, 0,0xA8C9,0xA8CA,0xAB46,0xAB47, 0,
+ 0, 0, 0,0xADBD, 0, 0,0xDCB3, 0,
+ 0,0xF6D6,0xA448, 0, 0, 0, 0, 0,
+0xA4B0,0xA4AF,0xC952,0xA4B1,0xA4B7, 0,0xA4B2,0xA4B3,
+0xC954,0xC953,0xA4B5,0xA4B6, 0,0xA4B4, 0, 0,
+ 0, 0, 0, 0,0xA54A,0xA54B,0xA54C,0xA54D,
+0xA549,0xA550,0xC96A, 0,0xC966,0xC969,0xA551,0xA561,
+ 0,0xC968, 0,0xA54E,0xA54F,0xA548, 0, 0,
+0xC965,0xC967, 0, 0, 0, 0, 0, 0,
+0xA5F5,0xC9B0,0xA5F2,0xA5F6,0xC9BA,0xC9AE,0xA5F3,0xC9B2,
+ 0, 0, 0,0xA5F4, 0,0xA5F7, 0,0xA5E9,
+0xC9B1,0xA5F8,0xC9B5, 0,0xC9B9,0xC9B6, 0, 0,
+0xC9B3,0xA5EA,0xA5EC,0xA5F9, 0,0xA5EE,0xC9AB,0xA5F1,
+0xA5EF,0xA5F0,0xC9BB,0xC9B8,0xC9AF,0xA5ED, 0, 0,
+0xC9AC,0xA5EB, 0, 0, 0,0xC9B4, 0, 0,
+ 0, 0,0xC9B7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xC9AD,0xCA66, 0,0xA742,
+0xA6F4, 0, 0,0xCA67,0xA6F1, 0,0xA744, 0,
+0xA6F9, 0,0xA6F8,0xCA5B,0xA6FC,0xA6F7,0xCA60,0xCA68,
+ 0,0xCA64, 0,0xA6FA, 0, 0,0xA6FD,0xA6EE,
+0xA747,0xCA5D, 0, 0,0xCBBD,0xA6EC,0xA743,0xA6ED,
+0xA6F5,0xA6F6,0xCA62,0xCA5E,0xA6FB,0xA6F3,0xCA5A,0xA6EF,
+0xCA65,0xA745,0xA748,0xA6F2,0xA740,0xA746,0xA6F0,0xCA63,
+0xA741,0xCA69,0xCA5C,0xA6FE,0xCA5F, 0, 0,0xCA61,
+ 0,0xA8D8,0xCBBF,0xCBCB,0xA8D0, 0,0xCBCC,0xA8CB,
+0xA8D5, 0, 0,0xA8CE,0xCBB9,0xA8D6,0xCBB8,0xCBBC,
+0xCBC3,0xCBC1,0xA8DE,0xA8D9,0xCBB3,0xCBB5,0xA8DB,0xA8CF,
+0xCBB6,0xCBC2,0xCBC9,0xA8D4,0xCBBB,0xCBB4,0xA8D3,0xCBB7,
+0xA8D7,0xCBBA, 0,0xA8D2, 0,0xA8CD, 0,0xA8DC,
+0xCBC4,0xA8DD,0xCBC8, 0,0xCBC6,0xCBCA,0xA8DA,0xCBBE,
+0xCBB2, 0,0xCBC0,0xA8D1,0xCBC5,0xA8CC,0xCBC7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xAB56,0xAB4A,
+ 0, 0,0xCDE0,0xCDE8, 0,0xAB49,0xAB51,0xAB5D,
+ 0,0xCDEE,0xCDEC,0xCDE7, 0, 0, 0,0xAB4B,
+0xCDED,0xCDE3,0xAB59,0xAB50,0xAB58,0xCDDE, 0,0xCDEA,
+ 0,0xCDE1,0xAB54,0xCDE2, 0,0xCDDD,0xAB5B,0xAB4E,
+0xAB57,0xAB4D, 0,0xCDDF,0xCDE4, 0,0xCDEB,0xAB55,
+0xAB52,0xCDE6,0xAB5A,0xCDE9,0xCDE5,0xAB4F,0xAB5C,0xAB53,
+0xAB4C,0xAB48, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCDEF, 0,0xADD7,0xADC1,
+ 0,0xADD1, 0,0xADD6,0xD0D0,0xD0CF,0xD0D4,0xD0D5,
+0xADC4, 0,0xADCD, 0, 0, 0,0xADDA, 0,
+0xADCE, 0, 0, 0, 0,0xD0C9,0xADC7,0xD0CA,
+ 0,0xADDC, 0,0xADD3,0xADBE,0xADBF,0xD0DD,0xB0BF,
+ 0,0xADCC,0xADCB,0xD0CB,0xADCF,0xD45B,0xADC6,0xD0D6,
+0xADD5,0xADD4,0xADCA,0xD0CE,0xD0D7, 0,0xD0C8,0xADC9,
+0xD0D8,0xADD2,0xD0CC,0xADC0, 0,0xADC3,0xADC2,0xD0D9,
+0xADD0,0xADC5,0xADD9,0xADDB,0xD0D3,0xADD8, 0,0xD0DB,
+0xD0CD,0xD0DC, 0,0xD0D1, 0,0xD0DA, 0,0xD0D2,
+ 0, 0, 0, 0,0xADC8, 0, 0, 0,
+0xD463,0xD457, 0,0xB0B3, 0,0xD45C,0xD462,0xB0B2,
+0xD455,0xB0B6,0xD459,0xD452,0xB0B4,0xD456,0xB0B9,0xB0BE,
+ 0,0xD467, 0,0xD451, 0,0xB0BA, 0,0xD466,
+ 0, 0,0xB0B5,0xD458,0xB0B1,0xD453,0xD44F,0xD45D,
+0xD450,0xD44E,0xD45A,0xD460,0xD461,0xB0B7, 0, 0,
+0xD85B,0xD45E,0xD44D,0xD45F, 0,0xB0C1,0xD464,0xB0C0,
+0xD44C, 0,0xD454,0xD465,0xB0BC,0xB0BB,0xB0B8,0xB0BD,
+ 0, 0,0xB0AF, 0, 0,0xB0B0, 0, 0,
+0xB3C8, 0,0xD85E,0xD857, 0,0xB3C5, 0,0xD85F,
+ 0, 0, 0,0xD855,0xD858,0xB3C4,0xD859, 0,
+ 0,0xB3C7,0xD85D, 0,0xD853,0xD852,0xB3C9, 0,
+0xB3CA,0xB3C6,0xB3CB,0xD851,0xD85C,0xD85A,0xD854, 0,
+ 0, 0,0xB3C3,0xD856, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB6CA,0xB6C4,0xDCB7,0xB6CD,
+0xDCBD,0xDCC0,0xB6C6,0xB6C7,0xDCBA,0xB6C5,0xDCC3,0xB6CB,
+0xDCC4, 0,0xDCBF,0xB6CC, 0,0xDCB4,0xB6C9,0xDCB5,
+ 0,0xDCBE,0xDCBC, 0,0xDCB8,0xB6C8,0xDCB6,0xB6CE,
+0xDCBB,0xDCC2,0xDCB9,0xDCC1, 0, 0,0xB9B6,0xB9B3,
+ 0,0xB9B4, 0,0xE0F9,0xE0F1,0xB9B2,0xB9AF,0xE0F2,
+ 0, 0,0xB9B1,0xE0F5, 0,0xE0F7, 0, 0,
+0xE0FE, 0, 0,0xE0FD,0xE0F8,0xB9AE,0xE0F0,0xB9AC,
+0xE0F3,0xB9B7,0xE0F6, 0,0xE0FA,0xB9B0,0xB9AD,0xE0FC,
+0xE0FB,0xB9B5, 0,0xE0F4, 0,0xBBF8,0xE4EC, 0,
+0xE4E9,0xBBF9, 0,0xBBF7, 0,0xE4F0,0xE4ED,0xE4E6,
+0xBBF6, 0,0xBBFA,0xE4E7,0xBBF5,0xBBFD,0xE4EA,0xE4EB,
+0xBBFB,0xBBFC,0xE4F1,0xE4EE,0xE4EF, 0, 0, 0,
+0xBEAA,0xE8F8,0xBEA7,0xE8F5,0xBEA9,0xBEAB, 0,0xE8F6,
+0xBEA8, 0,0xE8F7, 0,0xE8F4, 0, 0,0xC076,
+0xECBD,0xC077,0xECBB, 0,0xECBC,0xECBA,0xECB9, 0,
+ 0,0xECBE,0xC075, 0, 0,0xEFB8,0xEFB9, 0,
+0xE4E8,0xEFB7,0xC078,0xC35F,0xF1EB,0xF1EC, 0,0xC4D7,
+0xC4D8,0xF5C1,0xF5C0,0xC56C,0xC56B,0xF7D0, 0,0xA449,
+0xA461,0xA4B9, 0,0xA4B8,0xA553,0xA552,0xA5FC,0xA5FB,
+0xA5FD,0xA5FA, 0,0xA74A,0xA749,0xA74B, 0, 0,
+ 0, 0,0xA8E0, 0,0xA8DF,0xA8E1, 0,0xAB5E,
+ 0,0xA259,0xD0DE,0xA25A,0xB0C2,0xA25C,0xA25B,0xD860,
+ 0,0xA25D,0xB9B8,0xA25E, 0,0xA44A, 0,0xA4BA,
+0xA5FE,0xA8E2, 0,0xA44B,0xA4BD,0xA4BB,0xA4BC, 0,
+ 0,0xA640, 0, 0, 0,0xA74C,0xA8E4,0xA8E3,
+0xA8E5, 0, 0, 0,0xADDD, 0, 0, 0,
+0xBEAC, 0, 0, 0, 0, 0, 0,0xC94E,
+ 0,0xA554,0xA555, 0, 0,0xA641, 0,0xCA6A,
+ 0,0xAB60,0xAB5F,0xD0E0,0xD0DF,0xB0C3, 0,0xA4BE,
+0xC955, 0, 0, 0, 0, 0,0xCBCD, 0,
+0xAB61, 0,0xADE0, 0,0xADDE,0xADDF, 0, 0,
+ 0, 0,0xBEAD, 0,0xA556, 0, 0, 0,
+0xA642,0xC9BC, 0, 0, 0, 0,0xA74D,0xA74E,
+ 0,0xCA6B, 0, 0,0xCBCE,0xA8E6,0xCBCF, 0,
+ 0, 0, 0, 0,0xD0E2,0xD0E3,0xADE3, 0,
+0xD0E4, 0,0xD0E1,0xADE4,0xADE2,0xADE1,0xD0E5, 0,
+0xD468, 0, 0, 0,0xD861, 0, 0,0xDCC5,
+0xE140, 0, 0, 0,0xBBFE,0xBEAE,0xE8F9, 0,
+0xA44C,0xA45A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB0C4,0xB3CD, 0,0xB9B9, 0,0xC942,0xA4BF, 0,
+0xA559,0xA557,0xA558, 0, 0,0xA8E7, 0, 0,
+0xA44D,0xA44E, 0,0xA462, 0, 0,0xA4C0,0xA4C1,
+0xA4C2,0xC9BE,0xA55A, 0,0xC96B, 0,0xA646, 0,
+0xC9BF,0xA644,0xA645,0xC9BD, 0, 0,0xA647,0xA643,
+ 0, 0, 0, 0,0xCA6C,0xAAEC,0xCA6D, 0,
+ 0,0xCA6E, 0, 0,0xA750,0xA74F, 0, 0,
+0xA753,0xA751,0xA752, 0, 0, 0,0xA8ED, 0,
+0xA8EC,0xCBD4,0xCBD1,0xCBD2, 0,0xCBD0,0xA8EE,0xA8EA,
+0xA8E9, 0,0xA8EB,0xA8E8, 0, 0, 0, 0,
+ 0,0xA8EF, 0,0xAB63,0xCDF0, 0,0xCBD3,0xAB68,
+ 0,0xCDF1,0xAB64,0xAB67,0xAB66,0xAB65,0xAB62, 0,
+ 0, 0,0xD0E8, 0,0xADE7,0xD0EB,0xADE5, 0,
+ 0, 0,0xD0E7,0xADE8,0xADE6,0xADE9,0xD0E9,0xD0EA,
+ 0,0xD0E6,0xD0EC, 0, 0, 0, 0, 0,
+ 0,0xB3D1,0xB0C5,0xD469,0xD46B,0xD46A,0xD46C,0xB0C6,
+ 0, 0,0xB3CE, 0,0xB3CF,0xB3D0, 0,0xB6D0,
+0xDCC7, 0,0xDCC6,0xDCC8,0xDCC9,0xB6D1, 0,0xB6CF,
+0xE141,0xE142,0xB9BB,0xB9BA,0xE35A, 0, 0,0xBC40,
+0xBC41,0xBC42,0xBC44,0xE4F2,0xE4F3,0xBC43, 0, 0,
+ 0,0xBEAF, 0,0xBEB0, 0, 0,0xF1ED,0xF5C3,
+0xF5C2,0xF7D1, 0,0xA44F, 0, 0, 0,0xA55C,
+0xA55B, 0, 0,0xA648, 0, 0,0xC9C0, 0,
+ 0,0xA755,0xA756,0xA754,0xA757,0xCA6F,0xCA70, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA8F1,0xCBD5, 0,0xA8F0, 0,
+0xCDF2,0xAB6C,0xCDF3,0xAB6B, 0, 0, 0,0xAB69,
+ 0,0xAB6A, 0, 0, 0,0xD0ED, 0, 0,
+ 0, 0,0xB0C7,0xD46E, 0,0xB0CA,0xD46D,0xB1E5,
+0xB0C9,0xB0C8, 0,0xB3D4, 0,0xB3D3,0xB3D2,0xB6D2,
+ 0, 0,0xB6D5,0xB6D6,0xB6D4, 0,0xB6D3, 0,
+ 0,0xE143, 0,0xE144, 0, 0, 0,0xE4F5,
+0xBC45,0xE4F4, 0,0xBEB1,0xECBF,0xC079, 0,0xF1EE,
+0xC455, 0,0xA463,0xA4C3,0xC956, 0,0xA4C4,0xA4C5,
+ 0, 0, 0, 0, 0,0xA55D,0xA55E, 0,
+0xA649,0xCA71,0xCBD6,0xCBD7, 0,0xAB6D,0xD0EE,0xB0CC,
+0xB0CB,0xD863,0xD862, 0, 0,0xA450,0xA4C6,0xA55F,
+ 0,0xB0CD,0xC943, 0,0xC96C,0xA560, 0,0xC9C2,
+0xA64B,0xA64A,0xC9C1,0xA758, 0, 0, 0, 0,
+ 0, 0,0xADEA, 0, 0,0xD46F, 0,0xB6D7,
+0xE145,0xB9BC, 0, 0,0xE8FA, 0, 0,0xF3FD,
+ 0,0xA4C7, 0, 0,0xCBD8,0xCDF4,0xB0D0,0xB0CE,
+0xB0CF,0xA451, 0,0xA464,0xA2CD,0xA4CA, 0,0xA4C9,
+0xA4C8,0xA563,0xA562, 0,0xC96D,0xC9C3, 0, 0,
+ 0,0xA8F5,0xA8F2,0xA8F4,0xA8F3, 0, 0,0xAB6E,
+ 0, 0,0xB3D5, 0,0xA452, 0,0xA4CB, 0,
+0xA565,0xA564, 0,0xCA72, 0, 0,0xA8F6, 0,
+ 0, 0, 0, 0,0xC957, 0,0xA567,0xA566,
+0xA64C,0xA64D,0xCA73,0xA759, 0,0xA75A, 0,0xA8F7,
+0xA8F8,0xA8F9, 0,0xAB6F,0xCDF5, 0, 0,0xADEB,
+ 0, 0,0xC944, 0,0xA4CC, 0, 0, 0,
+ 0, 0,0xC9C4, 0, 0, 0,0xCA74,0xCA75,
+ 0, 0,0xCBD9, 0,0xCBDA, 0,0xCDF7,0xCDF6,
+0xCDF9,0xCDF8,0xAB70, 0,0xD470,0xADED,0xD0EF,0xADEC,
+ 0, 0, 0, 0,0xD864,0xB3D6, 0,0xD865,
+ 0, 0, 0, 0,0xE146,0xB9BD, 0, 0,
+ 0, 0,0xBC46, 0,0xF1EF, 0, 0, 0,
+ 0,0xC958, 0,0xA568, 0, 0, 0, 0,
+ 0, 0, 0,0xB0D1, 0, 0, 0, 0,
+0xA453,0xA465,0xA4CE,0xA4CD, 0,0xA4CF, 0, 0,
+ 0, 0, 0, 0,0xA8FB, 0,0xA8FA,0xA8FC,
+ 0, 0, 0,0xAB71, 0, 0, 0,0xADEE,
+ 0,0xE8FB,0xC24F,0xA466,0xA56A,0xA579,0xA574, 0,
+0xA56F,0xA56E,0xA575,0xA573,0xA56C,0xA57A,0xA56D,0xA569,
+0xA578,0xA577,0xA576,0xA56B, 0,0xA572, 0, 0,
+0xA571, 0, 0,0xA57B,0xA570, 0, 0, 0,
+ 0,0xA653, 0,0xA659,0xA655, 0,0xA65B,0xC9C5,
+0xA658,0xA64E,0xA651,0xA654,0xA650,0xA657,0xA65A,0xA64F,
+0xA652,0xA656,0xA65C, 0, 0, 0, 0, 0,
+0xCA7E,0xCA7B, 0,0xA767,0xCA7C,0xA75B,0xA75D,0xA775,
+0xA770, 0, 0, 0,0xCAA5,0xCA7D,0xA75F,0xA761,
+0xCAA4,0xA768,0xCA78,0xA774,0xA776,0xA75C,0xA76D, 0,
+0xCA76,0xA773, 0,0xA764, 0,0xA76E,0xA76F,0xCA77,
+0xA76C,0xA76A, 0,0xA76B,0xA771,0xCAA1,0xA75E, 0,
+0xA772,0xCAA3,0xA766,0xA763, 0,0xCA7A,0xA762,0xCAA6,
+0xA765, 0,0xA769, 0, 0, 0,0xA760,0xCAA2,
+ 0, 0, 0, 0,0xCA79, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCBEB,0xCBEA,0xA94F,0xCBED,0xCBEF,0xCBE4,0xCBE7,0xCBEE,
+0xA950, 0, 0,0xCBE1,0xCBE5, 0, 0,0xCBE9,
+0xCE49,0xA94B,0xCE4D,0xA8FD,0xCBE6,0xA8FE,0xA94C,0xA945,
+0xA941, 0,0xCBE2,0xA944,0xA949,0xA952,0xCBE3,0xCBDC,
+0xA943,0xCBDD,0xCBDF, 0,0xA946, 0,0xA948,0xCBDB,
+0xCBE0, 0, 0,0xA951,0xA94D,0xCBE8,0xA953, 0,
+0xA94A,0xCBDE,0xA947, 0, 0,0xA942,0xA940, 0,
+0xCBEC, 0,0xA94E, 0, 0, 0, 0, 0,
+0xCE48,0xCDFB,0xCE4B, 0, 0,0xCDFD,0xAB78,0xABA8,
+0xAB74,0xABA7,0xAB7D,0xABA4,0xAB72,0xCDFC,0xCE43,0xABA3,
+0xCE4F,0xABA5, 0,0xAB79, 0, 0,0xCE45,0xCE42,
+0xAB77, 0,0xCDFA,0xABA6,0xCE4A,0xAB7C,0xCE4C,0xABA9,
+0xAB73,0xAB7E,0xAB7B,0xCE40,0xABA1,0xCE46,0xCE47,0xAB7A,
+0xABA2,0xAB76, 0, 0, 0, 0,0xAB75,0xCDFE,
+ 0, 0, 0, 0, 0, 0,0xCE44, 0,
+ 0, 0, 0, 0, 0, 0,0xCE4E, 0,
+0xD144,0xADFB,0xD0F1, 0,0xD0F6,0xADF4,0xAE40,0xD0F4,
+0xADEF,0xADF9,0xADFE,0xD0FB, 0,0xADFA,0xADFD, 0,
+ 0,0xD0FE,0xADF5,0xD0F5, 0, 0, 0,0xD142,
+0xD143, 0,0xADF7,0xD141,0xADF3,0xAE43, 0,0xD0F8,
+ 0,0xADF1, 0,0xD146,0xD0F9,0xD0FD,0xADF6,0xAE42,
+0xD0FA,0xADFC,0xD140,0xD147,0xD4A1, 0,0xD145,0xAE44,
+0xADF0,0xD0FC,0xD0F3, 0,0xADF8, 0, 0,0xD0F2,
+ 0, 0,0xD0F7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD0F0,0xAE41,
+ 0, 0,0xD477, 0,0xB0E4,0xD4A7,0xB0E2,0xB0DF,
+0xD47C,0xB0DB,0xD4A2,0xB0E6,0xD476,0xD47B,0xD47A,0xADF2,
+0xB0E1,0xD4A5, 0,0xD4A8,0xD473, 0,0xB3E8, 0,
+0xD4A9,0xB0E7, 0,0xB0D9,0xB0D6,0xD47E,0xB0D3, 0,
+0xD4A6, 0,0xB0DA,0xD4AA, 0,0xD474,0xD4A4,0xB0DD,
+0xD475,0xD478,0xD47D, 0, 0,0xB0DE,0xB0DC,0xB0E8,
+ 0, 0, 0, 0,0xB0E3, 0,0xB0D7,0xB1D2,
+ 0,0xB0D8,0xD479,0xB0E5,0xB0E0,0xD4A3,0xB0D5, 0,
+ 0, 0,0xB0D4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD471,0xD472,0xD86A,
+ 0, 0, 0,0xB3D7,0xB3DA,0xD875,0xB3EE,0xD878,
+0xB3D8,0xD871,0xB3DE,0xB3E4,0xB5BD, 0, 0,0xB3E2,
+0xD86E,0xB3EF,0xB3DB,0xB3E3,0xD876,0xDCD7,0xD87B,0xD86F,
+ 0,0xD866,0xD873,0xD86D,0xB3E1,0xD879, 0, 0,
+0xB3DD,0xB3F1,0xB3EA, 0,0xB3DF,0xB3DC, 0,0xB3E7,
+ 0,0xD87A,0xD86C,0xD872,0xD874,0xD868,0xD877,0xB3D9,
+0xD867, 0,0xB3E0,0xB3F0,0xB3EC,0xD869,0xB3E6, 0,
+ 0,0xB3ED,0xB3E9,0xB3E5, 0,0xD870, 0, 0,
+ 0, 0, 0,0xB3EB, 0, 0, 0,0xDCD5,
+0xDCD1, 0,0xDCE0,0xDCCA,0xDCD3,0xB6E5,0xB6E6,0xB6DE,
+0xDCDC,0xB6E8,0xDCCF,0xDCCE,0xDCCC,0xDCDE,0xB6DC,0xDCD8,
+0xDCCD,0xB6DF,0xDCD6,0xB6DA,0xDCD2,0xDCD9,0xDCDB, 0,
+ 0,0xDCDF,0xB6E3,0xDCCB,0xB6DD,0xDCD0, 0,0xB6D8,
+ 0,0xB6E4,0xDCDA,0xB6E0,0xB6E1,0xB6E7,0xB6DB,0xA25F,
+0xB6D9,0xDCD4, 0, 0, 0, 0, 0,0xB6E2,
+ 0, 0,0xDCDD, 0, 0, 0,0xB9CD,0xB9C8,
+ 0,0xE155,0xE151, 0,0xE14B,0xB9C2,0xB9BE,0xE154,
+0xB9BF,0xE14E,0xE150, 0,0xE153, 0,0xB9C4, 0,
+0xB9CB,0xB9C5, 0, 0,0xE149,0xB9C6,0xB9C7,0xE14C,
+0xB9CC, 0,0xE14A,0xE14F,0xB9C3,0xE148,0xB9C9,0xB9C1,
+ 0, 0, 0,0xB9C0,0xE14D,0xE152, 0,0xB9CA,
+ 0, 0, 0, 0, 0, 0, 0,0xE147,
+ 0,0xBC4D,0xE547, 0,0xE544, 0,0xBC47,0xBC53,
+0xBC54, 0,0xBC4A,0xE542,0xBC4C,0xE4F9,0xBC52, 0,
+0xE546,0xBC49,0xE548,0xBC48, 0,0xE543,0xE545,0xBC4B,
+0xE541,0xE4FA,0xE4F7, 0, 0,0xD86B,0xE4FD, 0,
+0xE4F6,0xE4FC,0xE4FB, 0,0xE4F8, 0,0xBC4F, 0,
+ 0, 0, 0,0xBC4E, 0, 0, 0,0xBC50,
+0xE4FE,0xBEB2,0xE540, 0, 0, 0,0xE945, 0,
+0xE8FD, 0,0xBEBE,0xE942,0xBEB6,0xBEBA,0xE941, 0,
+0xBEB9,0xBEB5,0xBEB8,0xBEB3,0xBEBD,0xE943,0xE8FE,0xBEBC,
+0xE8FC,0xBEBB,0xE944,0xE940,0xBC51, 0,0xBEBF,0xE946,
+0xBEB7,0xBEB4, 0, 0, 0, 0,0xECC6,0xECC8,
+0xC07B,0xECC9,0xECC7,0xECC5,0xECC4,0xC07D,0xECC3,0xC07E,
+ 0, 0, 0, 0,0xECC1,0xECC2,0xC07A,0xC0A1,
+0xC07C, 0, 0,0xECC0, 0,0xC250, 0,0xEFBC,
+0xEFBA,0xEFBF,0xEFBD, 0,0xEFBB,0xEFBE, 0, 0,
+ 0, 0, 0, 0, 0,0xC360,0xF1F2,0xF1F3,
+0xC456, 0,0xF1F4,0xF1F0,0xF1F5,0xF1F1,0xC251, 0,
+ 0, 0,0xF3FE,0xF441,0xC459,0xF440,0xC458,0xC457,
+ 0, 0, 0, 0,0xC45A,0xF5C5,0xF5C6, 0,
+0xC4DA,0xC4D9,0xC4DB,0xF5C4, 0,0xF6D8,0xF6D7, 0,
+0xC56D,0xC56F,0xC56E,0xF6D9,0xC5C8,0xF8A6, 0, 0,
+ 0,0xC5F1, 0,0xF8A5,0xF8EE, 0, 0,0xC949,
+ 0, 0,0xA57D,0xA57C, 0,0xA65F,0xA65E,0xC9C7,
+0xA65D,0xC9C6, 0, 0,0xA779,0xCAA9, 0,0xCAA8,
+ 0, 0,0xA777,0xA77A, 0, 0,0xCAA7, 0,
+0xA778, 0, 0, 0, 0, 0, 0,0xCBF0,
+ 0,0xCBF1,0xA954, 0, 0, 0, 0,0xABAA,
+ 0,0xD148,0xD149,0xAE45,0xAE46, 0, 0,0xD4AC,
+0xB0E9,0xB0EB,0xD4AB,0xB0EA,0xD87C,0xB3F2, 0, 0,
+ 0, 0,0xB6E9,0xB6EA,0xDCE1, 0,0xB9CF, 0,
+0xB9CE, 0,0xE549,0xE948,0xE947, 0,0xF96B,0xA467,
+0xC959, 0,0xC96E,0xC96F, 0, 0, 0, 0,
+0xA662,0xA666,0xC9C9, 0,0xA664,0xA663,0xC9C8,0xA665,
+0xA661, 0, 0,0xA660,0xC9CA, 0, 0, 0,
+ 0, 0, 0,0xA7A6, 0, 0,0xA7A3, 0,
+0xA77D,0xCAAA, 0, 0, 0,0xCAAB, 0,0xA7A1,
+ 0,0xCAAD,0xA77B,0xCAAE,0xCAAC,0xA77E,0xA7A2,0xA7A5,
+0xA7A4,0xA77C,0xCAAF, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA959,0xCBFE, 0,0xA95B, 0,0xA95A, 0,
+0xCC40,0xA958,0xA957,0xCBF5, 0,0xCBF4, 0,0xCBF2,
+0xCBF7,0xCBF6,0xCBF3,0xCBFC,0xCBFD,0xCBFA,0xCBF8,0xA956,
+ 0, 0, 0,0xCBFB,0xA95C,0xCC41, 0, 0,
+0xCBF9, 0,0xABAB,0xA955, 0, 0, 0, 0,
+ 0, 0, 0,0xABAC,0xCE54, 0, 0,0xCE5A,
+ 0, 0, 0,0xABB2,0xCE58,0xCE5E, 0,0xCE55,
+0xCE59,0xCE5B,0xCE5D,0xCE57, 0,0xCE56,0xCE51,0xCE52,
+0xABAD, 0,0xABAF,0xABAE,0xCE53,0xCE5C, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xABB1, 0,
+ 0, 0, 0, 0, 0,0xCE50,0xD153, 0,
+0xD152,0xD157,0xD14E, 0,0xD151,0xD150, 0,0xD154,
+ 0,0xD158,0xAE47,0xAE4A, 0, 0,0xD14F,0xD155,
+ 0, 0, 0,0xAE49,0xD14A, 0,0xABB0,0xD4BA,
+0xD156, 0,0xD14D, 0,0xAE48,0xD14C, 0, 0,
+ 0, 0, 0, 0,0xD4B1, 0, 0,0xB0EC,
+0xB0F0,0xD4C1,0xD4AF,0xD4BD,0xB0F1,0xD4BF, 0,0xD4C5,
+ 0,0xD4C9, 0, 0,0xD4C0,0xD4B4,0xD4BC, 0,
+0xD4CA,0xD4C8,0xD4BE,0xD4B9,0xD4B2,0xD8A6,0xD4B0,0xB0F5,
+0xD4B7,0xB0F6,0xB0F2,0xD4AD,0xD4C3,0xD4B5, 0, 0,
+0xD4B3,0xD4C6,0xB0F3, 0,0xD4CC,0xB0ED,0xB0EF,0xD4BB,
+0xD4B6,0xAE4B,0xB0EE,0xD4B8,0xD4C7,0xD4CB,0xD4C2, 0,
+0xD4C4, 0, 0, 0,0xD4AE, 0, 0, 0,
+ 0,0xD8A1, 0,0xD8AA,0xD8A9,0xB3FA,0xD8A2, 0,
+0xB3FB,0xB3F9, 0,0xD8A4,0xB3F6,0xD8A8, 0,0xD8A3,
+0xD8A5,0xD87D,0xB3F4, 0,0xD8B2,0xD8B1,0xD8AE,0xB3F3,
+0xB3F7,0xB3F8,0xD14B,0xD8AB,0xB3F5,0xB0F4,0xD8AD,0xD87E,
+0xD8B0,0xD8AF, 0,0xD8B3, 0,0xDCEF, 0,0xD8AC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD8A7,0xDCE7,0xB6F4,0xB6F7,0xB6F2,0xDCE6,0xDCEA,0xDCE5,
+ 0,0xB6EC,0xB6F6,0xDCE2,0xB6F0,0xDCE9, 0,0xB6EE,
+0xB6ED,0xDCEC,0xB6EF,0xDCEE, 0,0xDCEB,0xB6EB, 0,
+ 0, 0,0xB6F5,0xDCF0,0xDCE4,0xDCED, 0, 0,
+0xDCE3, 0, 0,0xB6F1, 0,0xB6F3, 0,0xDCE8,
+ 0,0xDCF1, 0, 0,0xE15D,0xB9D0,0xE163, 0,
+ 0,0xB9D5,0xE15F,0xE166,0xE157,0xB9D7,0xB9D1,0xE15C,
+0xBC55,0xE15B,0xE164,0xB9D2, 0,0xB9D6,0xE15A,0xE160,
+0xE165,0xE156,0xB9D4,0xE15E, 0, 0,0xE162,0xE168,
+0xE158,0xE161, 0,0xB9D3,0xE167, 0, 0, 0,
+0xE159, 0, 0, 0,0xBC59,0xE54B,0xBC57,0xBC56,
+0xE54D,0xE552, 0,0xE54E, 0,0xE551,0xBC5C, 0,
+0xBEA5,0xBC5B, 0,0xE54A,0xE550, 0,0xBC5A,0xE54F,
+ 0,0xE54C, 0,0xBC58, 0, 0, 0, 0,
+ 0, 0,0xE94D, 0,0xE94F,0xE94A,0xBEC1,0xE94C,
+ 0,0xBEC0,0xE94E, 0, 0,0xBEC3,0xE950,0xBEC2,
+0xE949,0xE94B, 0, 0, 0, 0,0xC0A5,0xECCC,
+ 0,0xC0A4,0xECCD,0xC0A3,0xECCB,0xC0A2,0xECCA, 0,
+0xC253,0xC252,0xF1F6,0xF1F8, 0,0xF1F7,0xC361,0xC362,
+ 0, 0,0xC363,0xF442,0xC45B, 0, 0,0xF7D3,
+0xF7D2,0xC5F2, 0,0xA468,0xA4D0, 0, 0,0xA7A7,
+ 0, 0, 0, 0,0xCE5F, 0, 0, 0,
+ 0,0xB3FC,0xB3FD, 0,0xDCF2,0xB9D8,0xE169,0xE553,
+ 0, 0, 0,0xC95A, 0, 0,0xCAB0, 0,
+ 0, 0, 0, 0,0xCC42,0xCE60,0xD159,0xAE4C,
+ 0, 0,0xF1F9, 0,0xC4DC,0xA469,0xA57E,0xC970,
+ 0,0xA667,0xA668, 0,0xA95D, 0, 0, 0,
+0xB0F7, 0,0xB9DA, 0,0xB9DB,0xB9D9, 0,0xA46A,
+ 0,0xA4D1,0xA4D3,0xA4D2,0xC95B,0xA4D4,0xA5A1,0xC971,
+ 0,0xA5A2, 0, 0, 0, 0, 0,0xA669,
+0xA66A, 0, 0, 0,0xC9CB, 0,0xA7A8, 0,
+0xCAB1, 0, 0, 0,0xA961,0xCC43, 0,0xA95F,
+0xA960,0xA95E,0xD15A, 0, 0, 0,0xABB6,0xABB5,
+0xABB7,0xABB4, 0,0xCE61,0xA962,0xABB3, 0,0xAE4D,
+0xAE4E, 0,0xAE4F, 0,0xD4CD, 0, 0, 0,
+0xB3FE,0xD8B4,0xB0F8, 0, 0, 0, 0,0xB6F8,
+ 0,0xB9DD,0xB9DC,0xE16A, 0,0xBC5D,0xBEC4, 0,
+0xEFC0,0xF6DA,0xF7D4,0xA46B,0xA5A3, 0,0xA5A4,0xC9D1,
+0xA66C,0xA66F, 0,0xC9CF,0xC9CD,0xA66E,0xC9D0,0xC9D2,
+0xC9CC,0xA671,0xA670,0xA66D,0xA66B,0xC9CE, 0, 0,
+ 0, 0,0xA7B3, 0, 0,0xA7B0,0xCAB6,0xCAB9,
+0xCAB8, 0,0xA7AA,0xA7B2, 0, 0,0xA7AF,0xCAB5,
+0xCAB3,0xA7AE, 0, 0, 0,0xA7A9,0xA7AC, 0,
+0xCAB4,0xCABB,0xCAB7,0xA7AD,0xA7B1,0xA7B4,0xCAB2,0xCABA,
+0xA7AB, 0, 0, 0, 0, 0,0xA967,0xA96F,
+ 0,0xCC4F,0xCC48,0xA970,0xCC53,0xCC44,0xCC4B, 0,
+ 0,0xA966,0xCC45,0xA964,0xCC4C,0xCC50,0xA963, 0,
+0xCC51,0xCC4A, 0,0xCC4D, 0,0xA972,0xA969,0xCC54,
+0xCC52, 0,0xA96E,0xA96C,0xCC49,0xA96B,0xCC47,0xCC46,
+0xA96A,0xA968,0xA971,0xA96D,0xA965, 0,0xCC4E, 0,
+0xABB9, 0,0xABC0,0xCE6F,0xABB8,0xCE67,0xCE63, 0,
+0xCE73,0xCE62, 0,0xABBB,0xCE6C,0xABBE,0xABC1, 0,
+0xABBC,0xCE70,0xABBF, 0,0xAE56,0xCE76,0xCE64, 0,
+ 0,0xCE66,0xCE6D,0xCE71,0xCE75,0xCE72,0xCE6B,0xCE6E,
+ 0, 0,0xCE68,0xABC3,0xCE6A,0xCE69,0xCE74,0xABBA,
+0xCE65,0xABC2, 0,0xABBD, 0, 0, 0, 0,
+ 0,0xAE5C,0xD162, 0,0xAE5B, 0, 0,0xD160,
+ 0,0xAE50, 0,0xAE55, 0,0xD15F,0xD15C,0xD161,
+0xAE51,0xD15B, 0,0xAE54,0xAE52, 0,0xD163,0xAE53,
+0xAE57, 0, 0,0xAE58, 0,0xAE5A, 0, 0,
+ 0,0xAE59, 0, 0, 0,0xD15D,0xD15E, 0,
+ 0, 0, 0,0xD164, 0,0xD4D4,0xB0F9,0xD8C2,
+0xD4D3,0xD4E6, 0, 0,0xB140, 0,0xD4E4, 0,
+0xB0FE,0xB0FA,0xD4ED,0xD4DD,0xD4E0, 0,0xB143,0xD4EA,
+0xD4E2,0xB0FB,0xB144, 0,0xD4E7,0xD4E5, 0, 0,
+0xD4D6,0xD4EB,0xD4DF,0xD4DA, 0,0xD4D0,0xD4EC,0xD4DC,
+0xD4CF, 0,0xB142,0xD4E1,0xD4EE,0xD4DE,0xD4D2,0xD4D7,
+0xD4CE, 0,0xB141, 0,0xD4DB,0xD4D8,0xB0FC,0xD4D1,
+ 0,0xD4E9,0xB0FD, 0,0xD4D9,0xD4D5, 0, 0,
+0xD4E8, 0, 0, 0, 0, 0, 0,0xB440,
+0xD8BB, 0,0xD8B8,0xD8C9,0xD8BD,0xD8CA, 0,0xB442,
+ 0, 0, 0,0xD8C6,0xD8C3, 0, 0, 0,
+ 0, 0,0xD8C4,0xD8C7,0xD8CB, 0,0xD4E3,0xD8CD,
+0xDD47, 0,0xB443,0xD8CE,0xD8B6,0xD8C0, 0,0xD8C5,
+ 0, 0,0xB441,0xB444,0xD8CC,0xD8CF,0xD8BA,0xD8B7,
+ 0, 0,0xD8B9, 0, 0,0xD8BE,0xD8BC,0xB445,
+ 0,0xD8C8, 0, 0,0xD8BF, 0,0xD8C1,0xD8B5,
+0xDCFA,0xDCF8,0xB742,0xB740,0xDD43,0xDCF9,0xDD44,0xDD40,
+0xDCF7,0xDD46,0xDCF6,0xDCFD,0xB6FE,0xB6FD,0xB6FC,0xDCFB,
+0xDD41,0xB6F9,0xB741, 0,0xDCF4, 0,0xDCFE,0xDCF3,
+0xDCFC,0xB6FA,0xDD42,0xDCF5,0xB6FB,0xDD45, 0, 0,
+ 0, 0, 0, 0, 0,0xE16E,0xB9E2,0xB9E1,
+0xB9E3,0xE17A,0xE170,0xE176,0xE16B,0xE179,0xE178,0xE17C,
+0xE175,0xB9DE,0xE174,0xB9E4, 0,0xE16D,0xB9DF, 0,
+0xE17B,0xB9E0,0xE16F,0xE172,0xE177,0xE171,0xE16C, 0,
+ 0, 0, 0,0xE173,0xE555,0xBC61,0xE558,0xE557,
+0xE55A,0xE55C, 0,0xBC5F, 0,0xE556, 0,0xE554,
+ 0,0xE55D,0xE55B,0xE559, 0,0xE55F, 0,0xE55E,
+0xBC63,0xBC5E, 0,0xBC60,0xBC62, 0, 0,0xE560,
+0xE957, 0, 0,0xE956,0xE955, 0,0xE958,0xE951,
+ 0,0xE952,0xE95A,0xE953, 0,0xBEC5,0xE95C, 0,
+0xE95B,0xE954, 0,0xECD1,0xC0A8,0xECCF,0xECD4,0xECD3,
+0xE959, 0,0xC0A7, 0,0xECD2,0xECCE,0xECD6,0xECD5,
+0xC0A6, 0,0xECD0, 0,0xBEC6, 0, 0, 0,
+0xC254, 0, 0, 0,0xEFC1,0xF1FA,0xF1FB,0xF1FC,
+0xC45C, 0, 0,0xC45D, 0,0xF443, 0,0xF5C8,
+0xF5C7, 0, 0,0xF6DB,0xF6DC,0xF7D5,0xF8A7, 0,
+0xA46C,0xA46D, 0,0xA46E,0xA4D5,0xA5A5,0xC9D3,0xA672,
+0xA673, 0,0xA7B7,0xA7B8,0xA7B6,0xA7B5, 0,0xA973,
+ 0, 0,0xCC55,0xA975,0xA974,0xCC56, 0, 0,
+ 0,0xABC4, 0,0xAE5D,0xD165, 0,0xD4F0, 0,
+0xB145,0xB447,0xD4EF,0xB446, 0,0xB9E5, 0,0xE17D,
+0xBEC7, 0,0xC0A9,0xECD7, 0,0xC45E, 0,0xC570,
+ 0,0xC972, 0,0xA5A6,0xC973,0xA676, 0,0xA674,
+0xA675,0xA677, 0,0xA7BA,0xA7B9, 0,0xCABC,0xA7BB,
+ 0, 0,0xCABD,0xCC57, 0,0xCC58, 0,0xA976,
+0xA978,0xA97A,0xA977,0xA97B,0xA979, 0, 0, 0,
+ 0, 0,0xABC8,0xABC5,0xABC7,0xABC9,0xABC6,0xD166,
+0xCE77, 0, 0, 0,0xD168,0xD167,0xAE63, 0,
+0xAE5F, 0, 0,0xAE60,0xAE62,0xAE64,0xAE61, 0,
+0xAE66,0xAE65, 0, 0, 0, 0, 0,0xB14A,
+0xD4F2,0xD4F1,0xB149, 0,0xB148,0xB147,0xB14B,0xB146,
+ 0, 0,0xD8D5,0xD8D2,0xB449,0xD8D1,0xD8D6, 0,
+0xB44B,0xD8D4,0xB448,0xB44A,0xD8D3, 0,0xDD48, 0,
+0xDD49,0xDD4A, 0, 0, 0, 0,0xB9E6,0xB9EE,
+0xE17E,0xB9E8,0xB9EC,0xE1A1,0xB9ED,0xB9E9,0xB9EA,0xB9E7,
+0xB9EB,0xBC66,0xD8D0,0xBC67,0xBC65, 0,0xBC64,0xE95D,
+0xBEC8,0xECD8,0xECD9, 0, 0,0xC364,0xC45F, 0,
+0xA46F, 0,0xA678, 0, 0, 0, 0, 0,
+ 0,0xABCA, 0,0xD169,0xAE67, 0, 0,0xB14E,
+0xB14D,0xB14C,0xB44C,0xB44D,0xD8D7,0xB9EF,0xBEC9,0xA470,
+0xC95C,0xA4D6,0xC974, 0, 0,0xC9D4,0xA679, 0,
+ 0, 0,0xA97C, 0, 0, 0, 0,0xDD4B,
+ 0, 0,0xA471, 0,0xA4D7,0xC9D5, 0, 0,
+0xCABE, 0,0xCABF, 0,0xA7BC, 0, 0, 0,
+0xD8D8,0xB44E, 0,0xDD4C, 0, 0, 0,0xC0AA,
+0xA472,0xA4A8,0xA4D8,0xC975,0xA5A7, 0,0xA7C0,0xA7BF,
+0xA7BD,0xA7BE, 0, 0,0xCC59,0xA97E,0xA9A1,0xCC5A,
+0xA97D, 0, 0,0xABCE,0xCE78,0xABCD,0xABCB,0xABCC,
+0xAE6A,0xAE68, 0, 0,0xD16B,0xAE69,0xD16A, 0,
+0xAE5E,0xD4F3, 0, 0,0xB150,0xB151, 0, 0,
+0xB14F, 0,0xB9F0,0xE1A2,0xBC68,0xBC69, 0,0xE561,
+0xC0AB,0xEFC2,0xEFC3, 0,0xC4DD,0xF8A8,0xC94B,0xA4D9,
+ 0,0xA473, 0,0xC977,0xC976, 0, 0, 0,
+ 0,0xA67A,0xC9D7,0xC9D8,0xC9D6, 0,0xC9D9, 0,
+ 0, 0, 0, 0, 0, 0,0xCAC7, 0,
+0xCAC2,0xCAC4,0xCAC6,0xCAC3,0xA7C4,0xCAC0, 0,0xCAC1,
+0xA7C1,0xA7C2,0xCAC5,0xCAC8,0xA7C3,0xCAC9, 0, 0,
+ 0, 0, 0, 0, 0,0xCC68, 0,0xCC62,
+0xCC5D,0xA9A3,0xCC65,0xCC63,0xCC5C,0xCC69,0xCC6C,0xCC67,
+0xCC60,0xA9A5,0xCC66,0xA9A6,0xCC61,0xCC64,0xCC5B,0xCC5F,
+0xCC6B,0xA9A7, 0,0xA9A8, 0,0xCC5E,0xCC6A,0xA9A2,
+0xA9A4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCEAB,0xCEA4,
+0xCEAA,0xCEA3,0xCEA5,0xCE7D,0xCE7B, 0,0xCEAC,0xCEA9,
+0xCE79, 0,0xABD0,0xCEA7,0xCEA8, 0,0xCEA6,0xCE7C,
+0xCE7A,0xABCF,0xCEA2,0xCE7E, 0, 0,0xCEA1,0xCEAD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xAE6F, 0,0xAE6E, 0,0xD16C,0xAE6B,0xD16E, 0,
+0xAE70,0xD16F, 0, 0,0xAE73, 0,0xAE71,0xD170,
+0xCEAE,0xD172, 0,0xAE6D, 0,0xAE6C, 0,0xD16D,
+0xD171,0xAE72, 0, 0, 0, 0,0xB153,0xB152,
+ 0, 0, 0,0xD4F5,0xD4F9,0xD4FB,0xB154,0xD4FE,
+ 0,0xB158,0xD541, 0,0xB15A, 0,0xB156,0xB15E,
+ 0,0xB15B,0xD4F7,0xB155, 0,0xD4F6,0xD4F4,0xD543,
+0xD4F8, 0,0xB157,0xD542,0xB15C,0xD4FD,0xD4FC,0xB15D,
+0xD4FA,0xB159, 0, 0, 0, 0,0xD544, 0,
+0xD540,0xD8E7,0xD8EE,0xD8E3,0xB451,0xD8DF,0xD8EF,0xD8D9,
+0xD8EC,0xD8EA,0xD8E4, 0,0xD8ED,0xD8E6, 0,0xD8DE,
+0xD8F0,0xD8DC,0xD8E9,0xD8DA, 0,0xD8F1, 0,0xB452,
+ 0,0xD8EB,0xDD4F,0xD8DD,0xB44F, 0,0xD8E1, 0,
+0xB450,0xD8E0,0xD8E5, 0, 0,0xD8E2, 0, 0,
+ 0,0xD8E8, 0, 0, 0, 0,0xDD53, 0,
+ 0, 0,0xDD56,0xDD4E, 0,0xDD50, 0,0xDD55,
+0xDD54,0xB743, 0,0xD8DB,0xDD52, 0, 0,0xB744,
+ 0,0xDD4D,0xDD51, 0, 0, 0, 0,0xE1A9,
+ 0,0xE1B0,0xE1A7, 0,0xE1AE,0xE1A5,0xE1AD,0xE1B1,
+0xE1A4,0xE1A8,0xE1A3, 0,0xB9F1, 0,0xE1A6,0xB9F2,
+0xE1AC,0xE1AB,0xE1AA, 0, 0,0xE1AF, 0, 0,
+ 0, 0,0xE565,0xE567,0xBC6B,0xE568, 0,0xE563,
+ 0,0xE562,0xE56C, 0,0xE56A,0xBC6A,0xE56D,0xE564,
+0xE569,0xE56B,0xE566, 0, 0, 0, 0,0xE961,
+0xE966,0xE960,0xE965, 0,0xE95E,0xE968,0xE964,0xE969,
+0xE963,0xE95F,0xE967, 0,0xE96A,0xE962, 0,0xECDA,
+0xC0AF, 0,0xC0AD, 0,0xC0AC,0xC0AE, 0, 0,
+0xEFC4, 0,0xF172,0xF1FD, 0, 0,0xF444,0xF445,
+ 0,0xC460, 0,0xF5C9, 0,0xC4DE, 0,0xF5CA,
+ 0,0xF6DE,0xC572, 0,0xC571,0xF6DD,0xC5C9, 0,
+0xF7D6, 0, 0, 0, 0,0xA474,0xA67B,0xC9DA,
+0xCACA,0xA8B5,0xB15F, 0, 0,0xA475,0xA5AA,0xA5A9,
+0xA5A8, 0, 0,0xA7C5, 0, 0,0xAE74, 0,
+0xDD57,0xA476,0xA477,0xA478,0xA4DA, 0, 0,0xABD1,
+ 0,0xCEAF, 0, 0, 0,0xB453,0xA479,0xC95D,
+ 0, 0,0xA5AB,0xA5AC,0xC978, 0,0xA67C, 0,
+ 0, 0,0xCACB, 0,0xA7C6, 0,0xCACC, 0,
+ 0,0xA9AE, 0, 0,0xCC6E,0xA9AC,0xA9AB,0xCC6D,
+0xA9A9,0xCC6F,0xA9AA,0xA9AD, 0,0xABD2, 0,0xABD4,
+0xCEB3,0xCEB0,0xCEB1,0xCEB2,0xCEB4,0xABD3, 0, 0,
+0xD174,0xD173, 0,0xAE76, 0,0xAE75, 0, 0,
+ 0, 0, 0,0xB162,0xD546, 0,0xB161,0xB163,
+0xB160, 0, 0, 0, 0,0xB455,0xD545, 0,
+0xB456,0xD8F3, 0,0xB457,0xD8F2,0xB454, 0, 0,
+ 0, 0,0xDD5A,0xDD5C,0xB745,0xDD5B,0xDD59,0xDD58,
+ 0, 0, 0,0xE1B4,0xB9F7,0xB9F5, 0,0xB9F6,
+0xE1B2,0xE1B3, 0,0xB9F3,0xE571,0xE56F, 0,0xBC6D,
+0xE570,0xBC6E,0xBC6C,0xB9F4, 0, 0,0xE96D,0xE96B,
+0xE96C,0xE56E,0xECDC,0xC0B0,0xECDB,0xEFC5,0xEFC6,0xE96E,
+0xF1FE, 0,0xA47A,0xA5AD,0xA67E,0xC9DB,0xA67D, 0,
+0xA9AF,0xB746, 0,0xA4DB,0xA5AE,0xABD5,0xB458, 0,
+0xC979, 0,0xC97A, 0,0xC9DC, 0, 0,0xA7C8,
+0xCAD0,0xCACE,0xA7C9,0xCACD,0xCACF,0xCAD1, 0,0xA7C7,
+ 0, 0, 0, 0, 0,0xA9B3,0xA9B4,0xA9B1,
+ 0, 0,0xA9B0,0xCEB8,0xA9B2, 0, 0, 0,
+0xABD6, 0,0xCEB7,0xCEB9,0xCEB6,0xCEBA,0xABD7,0xAE79,
+0xD175, 0,0xD177,0xAE77,0xD178,0xAE78,0xD176, 0,
+0xCEB5,0xD547,0xD54A,0xD54B,0xD548,0xB167,0xB166,0xB164,
+0xB165,0xD549, 0, 0, 0, 0,0xB168, 0,
+ 0,0xB45A,0xB45B, 0,0xB45C,0xDD5D,0xDD5F,0xDD61,
+0xB748,0xB747,0xB459,0xDD60,0xDD5E, 0,0xE1B8, 0,
+ 0,0xE1B6,0xE1BC,0xB9F8,0xE1BD,0xE1BA,0xB9F9,0xE1B7,
+0xE1B5,0xE1BB,0xBC70,0xE573,0xE1B9,0xBC72,0xE574,0xBC71,
+0xBC74,0xE575,0xBC6F,0xBC73, 0,0xE973,0xE971,0xE970,
+0xE972,0xE96F, 0, 0,0xC366, 0,0xF446,0xF447,
+ 0,0xF5CB,0xF6DF,0xC655, 0, 0,0xA9B5,0xA7CA,
+ 0, 0,0xABD8, 0, 0, 0,0xA47B,0xA4DC,
+ 0,0xA5AF,0xC9DD, 0,0xA7CB,0xCAD2, 0,0xCEBB,
+0xABD9, 0,0xB9FA,0xA47C, 0, 0, 0,0xA6A1,
+ 0, 0,0xB749,0xA47D,0xA4DD,0xA4DE, 0,0xA5B1,
+0xA5B0, 0,0xC9DE,0xA6A2, 0,0xCAD3, 0,0xA7CC,
+ 0, 0,0xCC71,0xCC72,0xCC73, 0,0xA9B6,0xA9B7,
+0xCC70,0xA9B8, 0, 0, 0,0xABDA,0xCEBC, 0,
+0xD17A,0xAE7A, 0,0xD179, 0,0xB169,0xD54C,0xB16A,
+0xD54D, 0, 0, 0,0xB45D, 0, 0, 0,
+0xDD62, 0, 0,0xE1BF,0xE1BE, 0,0xB9FB, 0,
+0xBC75,0xE576,0xBECA,0xE974,0xC0B1, 0,0xC573,0xF7D8,
+ 0, 0, 0, 0,0xCC74, 0,0xCEBD,0xB16B,
+0xD8F4,0xB74A, 0, 0, 0,0xC255, 0, 0,
+ 0, 0,0xA7CE, 0,0xA7CD,0xABDB, 0,0xD17B,
+ 0,0xB16D,0xB343,0xB16E,0xB16C,0xB45E, 0,0xE1C0,
+0xB9FC,0xBC76, 0,0xC94C,0xC9DF, 0,0xCAD5,0xA7CF,
+0xCAD4,0xA7D0, 0, 0,0xA9BC,0xCC77,0xCC76,0xA9BB,
+0xA9B9,0xA9BA,0xCC75, 0, 0,0xABDD,0xCEBE,0xABE0,
+0xABDC,0xABE2,0xABDE,0xABDF,0xABE1, 0, 0, 0,
+0xAE7D,0xAE7C,0xAE7B, 0, 0, 0,0xD54F,0xB16F,
+0xB172,0xB170, 0,0xD54E,0xB175, 0,0xB171,0xD550,
+0xB174,0xB173, 0, 0, 0,0xD8F6,0xD8F5, 0,
+0xB461,0xB45F,0xB460,0xD8F7,0xB74B,0xDD64,0xB74C,0xDD63,
+ 0, 0,0xE577, 0, 0,0xBC78,0xE1C1,0xBC77,
+ 0,0xB9FD, 0,0xECDE,0xE975,0xC0B2,0xECDD,0xF240,
+0xF448,0xF449, 0,0xA4DF, 0,0xA5B2, 0, 0,
+ 0,0xC97B, 0, 0,0xA7D2,0xA7D4, 0,0xC9E2,
+0xCAD8,0xCAD7,0xCAD6, 0,0xC9E1,0xC9E0,0xA6A4,0xA7D3,
+0xA7D1,0xA6A3, 0, 0, 0,0xA9BD,0xCC78, 0,
+0xA9BE,0xCADD, 0,0xCADF,0xCADE,0xCC79, 0, 0,
+0xCADA, 0,0xA7D8,0xA7D6, 0,0xCAD9,0xCADB,0xCAE1,
+ 0,0xA7D5, 0,0xCADC,0xCAE5,0xA9C0, 0,0xCAE2,
+0xA7D7, 0,0xCAE0,0xCAE3, 0,0xA9BF, 0,0xA9C1,
+0xCAE4, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCCAF,0xCCA2,0xCC7E,0xCCAE,0xCCA9,0xABE7,0xA9C2,
+0xCCAA,0xCCAD,0xABE3,0xCCAC,0xA9C3,0xA9C8,0xA9C6,0xCCA3,
+ 0,0xCC7C,0xCCA5,0xA9CD,0xCCB0,0xABE4,0xCCA6, 0,
+0xABE5,0xA9C9,0xCCA8, 0,0xCECD,0xABE6,0xCC7B,0xA9CA,
+0xABE8,0xA9CB,0xA9C7,0xA9CC,0xCCA7,0xCC7A,0xCCAB,0xA9C4,
+ 0, 0,0xCC7D,0xCCA4,0xCCA1,0xA9C5, 0,0xCEBF,
+ 0,0xCEC0, 0, 0, 0, 0, 0, 0,
+0xCECA,0xD1A1,0xCECB,0xABEE,0xCECE,0xCEC4,0xABED,0xCEC6,
+ 0,0xCEC7, 0, 0,0xCEC9,0xABE9, 0, 0,
+0xAEA3, 0, 0,0xCEC5,0xCEC1,0xAEA4, 0, 0,
+0xCECF,0xAE7E,0xD17D,0xCEC8, 0,0xD17C,0xCEC3,0xCECC,
+ 0, 0,0xABEC,0xAEA1,0xABF2,0xAEA2,0xCED0,0xD17E,
+0xABEB,0xAEA6,0xABF1,0xABF0,0xABEF,0xAEA5,0xCED1,0xAEA7,
+0xABEA, 0,0xCEC2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xB176,
+0xD1A4,0xD1A6, 0,0xD1A8,0xAEA8,0xAEAE,0xD553,0xD1AC,
+0xD1A3,0xB178,0xD551, 0,0xAEAD,0xAEAB,0xD1AE, 0,
+0xD552, 0,0xD1A5, 0,0xAEAC,0xD1A9,0xAEAF,0xD1AB,
+ 0, 0,0xAEAA,0xD1AA,0xD1AD,0xD1A7, 0,0xAEA9,
+0xB179, 0,0xD1A2,0xB177, 0, 0, 0, 0,
+0xB17A, 0, 0, 0, 0, 0, 0, 0,
+0xD555,0xD55E,0xB464, 0,0xB17C,0xB1A3,0xB465,0xD560,
+0xB1AA,0xD8F9,0xD556,0xB1A2,0xB1A5,0xB17E,0xD554,0xD562,
+0xD565,0xD949, 0,0xD563,0xD8FD,0xB1A1,0xB1A8,0xB1AC,
+0xD55D,0xD8F8,0xD561,0xB17B,0xD8FA,0xD564,0xD8FC,0xD559,
+ 0,0xB462, 0,0xD557,0xD558,0xB1A7, 0, 0,
+0xB1A6,0xD55B,0xB1AB,0xD55F,0xB1A4,0xD55C, 0,0xB1A9,
+0xB466,0xB463,0xD8FB, 0,0xD55A, 0,0xB17D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB46B,0xB46F,0xD940,0xB751,0xB46D,0xD944,0xB471,0xDD65,
+0xD946,0xB753,0xB469,0xB46C,0xD947, 0,0xD948,0xD94E,
+0xB473,0xB754, 0,0xD94A,0xD94F,0xD943,0xB75E, 0,
+0xB755,0xB472,0xD941,0xD950, 0,0xB75D,0xB470,0xB74E,
+0xD94D, 0,0xB474,0xD945,0xD8FE,0xB46A,0xD942, 0,
+0xD94B, 0,0xB74D,0xB752,0xB467,0xD94C, 0,0xB750,
+ 0, 0, 0,0xB468, 0, 0, 0,0xB75C,
+0xE1C3,0xDD70, 0,0xDD68,0xE1C2, 0,0xDD6C,0xDD6E,
+ 0, 0,0xDD6B, 0,0xB75B, 0,0xDD6A,0xB75F,
+ 0, 0, 0,0xE1D2, 0, 0,0xB75A,0xBA40,
+0xDD71,0xE1C4, 0, 0,0xB758,0xDD69,0xDD6D,0xB9FE,
+0xB74F,0xDD66,0xDD67,0xBA41,0xB757,0xB759,0xB756,0xDD6F,
+ 0, 0,0xE1C8,0xE1C9,0xE1CE,0xBC7D,0xE1D5, 0,
+0xBA47, 0,0xBA46,0xE1D0, 0,0xBC7C,0xE1C5,0xBA45,
+ 0,0xE1D4,0xBA43,0xBA44, 0,0xE1D1,0xE5AA,0xBC7A,
+0xB46E, 0,0xE1D3,0xBCA3,0xE1CB, 0,0xBC7B, 0,
+0xBCA2,0xE1C6,0xE1CA,0xE1C7,0xE1CD,0xBA48,0xBC79,0xBA42,
+ 0,0xE57A,0xE1CF, 0,0xBCA1, 0,0xBCA4, 0,
+0xE1CC, 0,0xBC7E,0xE579, 0, 0, 0, 0,
+ 0,0xE57E,0xBECE,0xE578,0xE9A3,0xE5A9,0xBCA8, 0,
+0xBCA6,0xBECC,0xE5A6,0xE5A2,0xBCAC, 0,0xE978, 0,
+ 0, 0,0xBCAA,0xE5A1, 0,0xE976, 0,0xE5A5,
+ 0,0xE5A8,0xE57D, 0,0xBCAB, 0, 0,0xBCA5,
+0xE977,0xBECD,0xE5A7,0xBCA7,0xBCA9,0xE5A4,0xBCAD,0xE5A3,
+0xE57C,0xE57B,0xBECB,0xE5AB,0xE97A,0xECE0,0xBED0, 0,
+0xE9A2, 0,0xE97E, 0,0xECE1, 0,0xBED1,0xE9A1,
+ 0,0xE97C,0xC0B4,0xECDF, 0,0xE979,0xE97B,0xC0B5,
+0xBED3,0xC0B3,0xBED2,0xC0B7,0xE97D,0xBECF, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xEFCF, 0,
+0xEFC7, 0, 0, 0, 0, 0,0xECE7,0xEFC8,
+0xECE3, 0, 0,0xC256,0xECE5,0xECE4,0xC0B6,0xECE2,
+0xECE6,0xEFD0,0xEFCC,0xEFCE, 0,0xEFC9,0xEFCA, 0,
+0xEFCD,0xEFCB,0xC367, 0, 0,0xC36A,0xC369,0xC368,
+0xC461,0xF44A,0xC462,0xF241,0xC4DF,0xF5CC,0xC4E0,0xC574,
+0xC5CA,0xF7D9, 0,0xF7DA,0xF7DB, 0, 0,0xF9BA,
+0xA4E0,0xC97C,0xA5B3, 0,0xA6A6,0xA6A7,0xA6A5, 0,
+0xA6A8,0xA7DA,0xA7D9, 0,0xCCB1,0xA9CF,0xA9CE, 0,
+ 0,0xD1AF,0xB1AD,0xB1AE, 0, 0, 0,0xB475,
+0xDD72,0xB760,0xB761,0xDD74,0xDD76,0xDD75, 0,0xE1D7,
+ 0,0xE1D6,0xBA49,0xE1D8, 0,0xE5AC,0xBCAE, 0,
+0xBED4, 0,0xC0B8,0xC257,0xC0B9, 0,0xA4E1, 0,
+ 0, 0,0xCAE6, 0, 0,0xCCB2,0xA9D1,0xA9D0,
+0xA9D2,0xABF3,0xCED2,0xCED3, 0, 0,0xD1B0,0xAEB0,
+0xB1AF,0xB476,0xD951,0xA4E2, 0,0xA47E,0xA4E3, 0,
+0xC97D,0xA5B7,0xA5B6,0xA5B4,0xA5B5, 0, 0, 0,
+0xA6AB,0xC9E9,0xC9EB,0xA6AA,0xC9E3, 0,0xC9E4, 0,
+0xC9EA,0xC9E6,0xC9E8,0xA6A9,0xC9E5,0xC9EC,0xC9E7, 0,
+ 0, 0, 0, 0, 0,0xA7E1,0xA7EA,0xA7E8,
+0xCAF0,0xCAED,0xCAF5,0xA7E6,0xCAF6, 0,0xA7DF,0xCAF3,
+ 0,0xA7E5,0xCAEF,0xCAEE,0xA7E3,0xCAF4,0xA7E4,0xA9D3,
+0xA7DE,0xCAF1, 0,0xCAE7,0xA7DB, 0,0xA7EE,0xCAEC,
+0xCAF2,0xA7E0,0xA7E2, 0,0xCAE8, 0,0xCAE9,0xCAEA,
+ 0,0xA7ED,0xA7E7,0xA7EC,0xCAEB,0xA7EB,0xA7DD,0xA7DC,
+0xA7E9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA9E1,0xCCBE,0xCCB7,0xA9DC,0xA9EF,0xCCB3,0xCCBA,0xCCBC,
+0xCCBF,0xA9EA, 0,0xCCBB,0xCCB4,0xA9E8,0xCCB8, 0,
+0xCCC0,0xA9D9, 0,0xCCBD,0xA9E3,0xA9E2,0xCCB6,0xA9D7,
+ 0, 0,0xA9D8, 0,0xA9D6, 0,0xA9EE,0xA9E6,
+0xA9E0,0xA9D4,0xCCB9,0xA9DF,0xA9D5,0xA9E7,0xA9F0,0xCED4,
+0xA9E4,0xCCB5,0xA9DA,0xA9DD,0xA9DE, 0,0xA9EC,0xA9ED,
+0xA9EB,0xA9E5,0xA9E9,0xA9DB,0xABF4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCEDA,0xAC41,0xABF8,0xABFA,0xAC40,
+0xCEE6,0xABFD,0xD1B1,0xAEB1,0xAC43,0xCED7,0xCEDF,0xABFE,
+0xCEDE,0xCEDB,0xCEE3,0xCEE5,0xABF7,0xABFB,0xAC42,0xAEB3,
+0xCEE0,0xABF9,0xAC45,0xCED9, 0, 0, 0,0xABFC,
+0xAEB2,0xABF6, 0,0xCED6,0xCEDD,0xCED5,0xCED8,0xCEDC,
+0xD1B2,0xAC44, 0,0xCEE1,0xCEE2,0xCEE4,0xABF5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xAEC1,0xD1BE,0xAEBF,0xAEC0,0xD1B4,0xD1C4, 0,0xAEB6,
+ 0, 0,0xD566,0xD1C6,0xD1C0, 0,0xD1B7, 0,
+0xD1C9,0xD1BA,0xAEBC,0xD57D,0xD1BD,0xAEBE,0xAEB5, 0,
+0xD1CB,0xD1BF,0xAEB8,0xD1B8,0xD1B5,0xD1B6,0xAEB9,0xD1C5,
+0xD1CC,0xAEBB,0xD1BC,0xD1BB,0xAEC3,0xAEC2,0xAEB4,0xAEBA,
+0xAEBD,0xD1C8, 0, 0,0xD1C2,0xAEB7,0xD1B3,0xD1CA,
+0xD1C1,0xD1C3,0xD1C7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD567, 0,0xB1B7,
+0xB1CB,0xB1CA, 0,0xB1BF, 0,0xD579,0xD575,0xD572,
+0xD5A6,0xB1BA,0xB1B2, 0, 0,0xD577,0xB4A8,0xB1B6,
+0xD5A1, 0,0xB1CC,0xB1C9,0xD57B,0xD56A, 0, 0,
+0xB1C8,0xD5A3,0xD569,0xB1BD,0xB1C1,0xD5A2, 0,0xD573,
+0xB1C2,0xB1BC,0xD568, 0,0xB478,0xD5A5,0xD571,0xB1C7,
+0xD574,0xD5A4,0xB1C6, 0,0xD952, 0,0xB1B3,0xD56F,
+0xB1B8,0xB1C3, 0,0xB1BE,0xD578,0xD56E,0xD56C,0xD57E,
+0xB1B0,0xB1C4,0xB1B4,0xB477,0xD57C,0xB1B5, 0,0xB1B1,
+0xB1C0,0xB1BB,0xB1B9,0xD570,0xB1C5,0xD56D,0xD57A,0xD576,
+0xD954,0xD953, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD56B,0xD964, 0,
+0xB47A, 0,0xD96A,0xD959,0xD967,0xDD77,0xB47D,0xD96B,
+0xD96E,0xB47C,0xD95C,0xD96D,0xD96C,0xB47E,0xD955,0xB479,
+0xB4A3, 0,0xB4A1,0xD969, 0,0xD95F,0xB4A5,0xD970,
+0xD968,0xD971,0xB4AD,0xB4AB,0xD966,0xD965, 0,0xD963,
+0xD95D,0xB4A4, 0,0xB4A2,0xD1B9,0xD956, 0,0xDDB7,
+0xD957,0xB47B,0xB4AA,0xDD79, 0,0xB4A6,0xB4A7,0xD958,
+0xD96F,0xDD78,0xD960,0xD95B,0xB4A9,0xD961,0xD95E, 0,
+ 0,0xB4AE, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB770, 0,
+ 0,0xDD7C,0xDDB1,0xDDB6,0xDDAA,0xB76C,0xDDBB,0xB769,
+0xDD7A, 0,0xDD7B,0xB762,0xB76B,0xDDA4,0xB76E,0xB76F,
+0xDDA5, 0,0xDDB2,0xDDB8,0xB76A, 0,0xB764,0xDDA3,
+0xDD7D,0xDDBA,0xDDA8,0xDDA9,0xDD7E,0xDDB4,0xDDAB,0xDDB5,
+0xDDAD, 0,0xB765,0xE1D9,0xB768,0xB766,0xDDB9,0xDDB0,
+0xDDAC, 0, 0,0xDDA1,0xBA53,0xDDAF,0xB76D,0xDDA7,
+ 0,0xDDA6, 0, 0, 0,0xB767,0xB763,0xE1EE,
+0xDDB3,0xDDAE, 0,0xDDA2, 0, 0, 0, 0,
+ 0, 0, 0,0xE1E9, 0,0xE1DA,0xE1E5, 0,
+0xE1EC,0xBA51,0xB4AC,0xE1EA,0xBA4C, 0, 0, 0,
+0xBA4B,0xE1F1, 0,0xE1DB,0xE1E8,0xE1DC,0xE1E7,0xBA4F,
+0xE1EB,0xD962, 0, 0, 0,0xE1F2,0xE1E3,0xBA52,
+0xE5BA,0xBCAF, 0,0xE1F0,0xE1EF,0xBA54,0xE5AD,0xBCB0,
+0xE5AE, 0,0xE1DF,0xE1E0,0xE1DD,0xE1E2,0xE1DE,0xE1F3,
+0xBA4E,0xBCB1,0xBA50,0xBA55, 0,0xE1E1, 0,0xE1ED,
+ 0, 0,0xE1E6, 0, 0,0xE5B1, 0,0xBA4A,
+0xBCB4,0xE9AA,0xE5B6,0xE5B5,0xE5B7, 0, 0,0xE5B4,
+0xBCB5, 0,0xBCBB,0xBCB8, 0,0xBCB9,0xE5AF,0xE5B2,
+0xE5BC,0xBCC1,0xBCBF, 0,0xE5B3,0xD95A,0xBCB2,0xE5B9,
+0xE5B0, 0,0xBCC2,0xE5B8,0xBA4D,0xBCB7,0xE1E4, 0,
+ 0,0xBCBA, 0,0xBCBE,0xBCC0,0xBCBD,0xBCBC, 0,
+0xBCB6,0xE5BB,0xBCB3,0xBCC3, 0, 0, 0, 0,
+ 0, 0, 0,0xBED8,0xBED9,0xE9A9,0xBEE2,0xBEDF,
+ 0,0xBED6,0xBEDD,0xE9AB,0xBEDB,0xBED5, 0,0xBEDC,
+ 0,0xE9A8,0xC0BB,0xBED7, 0,0xBEDE,0xC0BA,0xE9A7,
+0xE9A6, 0,0xBEE0, 0,0xBEE1, 0,0xE9A5,0xE9A4,
+0xC0BC,0xE9AE,0xBEDA,0xE9AC, 0, 0, 0, 0,
+0xC0BD, 0,0xC0C2,0xECEA,0xECEC, 0,0xC0BF, 0,
+0xECED,0xECE9, 0,0xECEB,0xC0C0,0xC0C3, 0,0xECE8,
+0xC0BE,0xC0C1,0xC259,0xE9AD,0xC258, 0, 0,0xC25E,
+0xEFD4, 0,0xC25C,0xC25D,0xEFD7,0xEFD3,0xC25A,0xEFD1,
+0xC36B,0xEFD5, 0,0xEFD6,0xEFD2, 0,0xC25B,0xF242,
+ 0,0xF245, 0, 0,0xF246,0xF244,0xF247,0xC36C,
+0xF243, 0, 0,0xF44E,0xC464,0xF44D,0xF44C,0xF44B,
+0xC463,0xC465, 0,0xF5CD,0xC4E2,0xC4E1, 0, 0,
+0xF6E1,0xF6E0,0xF6E3,0xC5CB,0xC575,0xF7DD,0xF6E2, 0,
+ 0,0xF7DC,0xC5CD,0xC5CC,0xC5F3,0xF8A9,0xF8EF,0xA4E4,
+ 0, 0,0xD972,0xE9AF, 0, 0,0xA6AC,0xCAF7,
+0xA7F1,0xA7EF, 0,0xA7F0, 0,0xCCC1,0xA9F1,0xAC46,
+ 0,0xCEE7, 0,0xCEE8, 0,0xAC47,0xD1CE, 0,
+0xAEC4,0xAEC5,0xD1CD, 0, 0, 0, 0,0xB1D3,
+ 0,0xB1CF, 0,0xD5A7,0xB1D6,0xB1D5,0xB1CE,0xB1D1,
+0xB1D4,0xB1D0, 0, 0,0xD976,0xB1CD,0xB4AF, 0,
+ 0, 0,0xB4B1,0xB4B2,0xD975,0xD978,0xB4B0,0xD973,
+0xD977, 0,0xD974, 0,0xB771, 0, 0,0xDDBC,
+ 0, 0,0xBA56,0xE1F4,0xBEE3,0xBCC4,0xE5BD,0xBCC5,
+0xBCC6,0xE5BF,0xE5BE,0xE5C0,0xE9B1, 0, 0,0xE9B0,
+0xECEF,0xECEE,0xC0C4,0xC0C5,0xF248, 0, 0,0xA4E5,
+ 0, 0, 0, 0,0xD979, 0, 0, 0,
+0xB4B4,0xB4B3,0xDDBD, 0,0xEFD8,0xC4E3,0xF7DE,0xA4E6,
+ 0,0xAEC6, 0,0xB1D8,0xB1D7,0xD97A,0xD97B,0xB772,
+0xE1F5,0xBA57,0xE9B2, 0,0xA4E7,0xA5B8, 0,0xA9F2,
+0xCCC2, 0,0xCEE9,0xAC48,0xB1D9, 0,0xD97C,0xB4B5,
+0xB773, 0,0xE5C1,0xE5C2, 0, 0,0xECF0,0xC25F,
+0xF8F0,0xA4E8, 0,0xCCC3,0xA9F3,0xAC49, 0,0xCEEA,
+ 0,0xAEC7,0xD1D2,0xD1D0,0xD1D1,0xAEC8,0xD1CF, 0,
+ 0, 0, 0,0xB1DB,0xB1DC,0xD5A8,0xB1DD,0xB1DA,
+0xD97D, 0,0xD97E,0xDDBE, 0, 0,0xBA59,0xBA58,
+ 0, 0,0xECF1,0xEFD9, 0,0xF24A,0xF249,0xF44F,
+ 0,0xC95E,0xAC4A, 0, 0,0xA4E9,0xA5B9, 0,
+0xA6AE,0xA6AD, 0, 0,0xA6AF,0xA6B0,0xC9EE,0xC9ED,
+0xCAF8,0xA7F2,0xCAFB,0xCAFA,0xCAF9,0xCAFC, 0, 0,
+ 0, 0,0xA9F4,0xCCC9,0xCCC5,0xCCCE, 0, 0,
+0xA9FB, 0,0xA9F9,0xCCCA,0xCCC6,0xCCCD,0xA9F8,0xAA40,
+0xCCC8,0xCCC4,0xA9FE,0xCCCB,0xA9F7,0xCCCC,0xA9FA,0xA9FC,
+0xCCD0,0xCCCF,0xCCC7,0xA9F6,0xA9F5,0xA9FD, 0, 0,
+ 0, 0, 0, 0,0xCEEF,0xCEF5, 0,0xAC50,
+0xAC4D,0xCEEC,0xCEF1, 0,0xAC53,0xAC4B,0xCEF0,0xAC4E,
+0xAC51, 0, 0,0xCEF3, 0,0xAC4C,0xCEF8,0xAC4F,
+ 0,0xAC52,0xCEED,0xCEF2,0xCEF6,0xCEEE,0xCEEB, 0,
+ 0,0xCEF7,0xCEF4, 0, 0, 0, 0, 0,
+ 0,0xAED0,0xAEC9,0xAECC, 0,0xAECF, 0,0xD1D5,
+ 0,0xAECA,0xD1D3, 0,0xAECE, 0, 0,0xAECB,
+ 0,0xD1D6,0xAECD, 0, 0, 0, 0, 0,
+ 0,0xD5AC,0xB1DF,0xD5AB,0xD5AD,0xB1DE,0xB1E3,0xD1D4,
+ 0,0xD5AA,0xD5AE, 0,0xB1E0,0xD5A9,0xB1E2, 0,
+0xB1E1, 0,0xD9A7, 0,0xD9A2, 0,0xB4B6,0xB4BA,
+0xB4B7,0xD9A5,0xD9A8, 0,0xB4B8, 0,0xB4B9,0xB4BE,
+0xDDC7,0xD9A6,0xB4BC,0xD9A3,0xD9A1, 0,0xB4BD, 0,
+0xD9A4, 0, 0, 0,0xB779, 0,0xDDBF,0xB776,
+0xB777,0xB775,0xDDC4,0xDDC3,0xDDC0,0xB77B, 0, 0,
+0xDDC2,0xB4BB, 0, 0,0xDDC6,0xDDC1,0xB778,0xB774,
+0xB77A,0xDDC5, 0, 0, 0,0xBA5C, 0,0xE1F8,
+0xE1F7,0xE1F6,0xBA5A, 0, 0, 0, 0, 0,
+0xBA5B,0xE5C5,0xE5C8,0xBCC8, 0, 0,0xBCC7,0xE5C9,
+0xE5C4,0xBCCA,0xE5C6, 0,0xBCC9,0xE5C3, 0,0xE5C7,
+0xBEE9,0xBEE6,0xE9BB,0xE9BA, 0,0xE9B9,0xE9B4, 0,
+0xE9B5, 0, 0, 0,0xBEE7, 0,0xBEE4,0xBEE8,
+0xE9B3,0xBEE5,0xE9B6,0xE9B7,0xE9BC, 0, 0,0xE9B8,
+ 0, 0,0xECF2, 0, 0, 0,0xC0C7, 0,
+0xEFDC,0xC0C6,0xEFDA,0xEFDB,0xC260,0xC36E,0xF24B, 0,
+0xC36D, 0, 0,0xF451,0xF452, 0,0xC466, 0,
+0xF450,0xC4E4, 0,0xF7DF,0xC5CE,0xF8AA,0xF8AB, 0,
+0xA4EA, 0,0xA6B1,0xA6B2,0xA7F3, 0,0xCCD1,0xAC54,
+0xAED1,0xB1E4, 0, 0,0xB0D2, 0,0xB4BF,0xB4C0,
+0xB3CC,0xD9A9, 0,0xB77C,0xE1FA,0xE1F9, 0, 0,
+0xA4EB,0xA6B3,0xCCD2,0xAA42, 0,0xAA41, 0,0xCEF9,
+0xCEFA, 0,0xD1D7,0xD1D8,0xAED2,0xAED3, 0,0xAED4,
+0xD5AF, 0, 0,0xB1E6, 0,0xB4C2, 0,0xB4C1,
+0xDDC8,0xDF7A,0xE1FB,0xE9BD, 0, 0,0xC261,0xC467,
+0xA4EC, 0,0xA5BC,0xA5BD,0xA5BB,0xA5BE,0xA5BA, 0,
+ 0,0xA6B6, 0,0xC9F6,0xA6B5,0xA6B7, 0, 0,
+0xC9F1,0xC9F0,0xC9F3,0xC9F2,0xC9F5,0xA6B4,0xC9EF,0xC9F4,
+ 0, 0, 0, 0, 0,0xCAFD,0xA7FD,0xCAFE,
+0xCB43,0xA7FC, 0,0xCB47,0xCB42,0xCB45,0xA7F5,0xA7F6,
+0xA7F7,0xA7F8, 0,0xA840, 0,0xCB41,0xA7FA,0xA841,
+ 0,0xCB40,0xCB46, 0,0xA7F9,0xCB44,0xA7FB,0xA7F4,
+0xA7FE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xAA57, 0,0xCCD4,0xAA43, 0,0xAA4D,
+0xAA4E,0xAA46,0xAA58,0xAA48,0xCCDC,0xAA53,0xCCD7,0xAA49,
+0xCCE6,0xCCE7,0xCCDF,0xCCD8,0xAA56,0xCCE4,0xAA51,0xAA4F,
+ 0,0xCCE5, 0,0xCCE3,0xCCDB,0xCCD3,0xCCDA,0xAA4A,
+ 0,0xAA50, 0,0xAA44,0xCCDE,0xCCDD,0xCCD5, 0,
+0xAA52,0xCCE1,0xCCD6,0xAA55,0xCCE8,0xAA45, 0,0xAA4C,
+0xCCD9,0xCCE2,0xAA54, 0,0xAA47,0xAA4B, 0,0xCCE0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCF5B,0xAC5C,
+0xAC69, 0,0xCF56,0xCF4C,0xAC62,0xCF4A,0xAC5B,0xCF45,
+0xAC65,0xCF52,0xCEFE,0xCF41, 0, 0, 0, 0,
+0xCF44,0xCEFB,0xCF51,0xCF61,0xAC60,0xCF46,0xCF58, 0,
+0xCEFD,0xCF5F,0xCF60,0xCF63,0xCF5A,0xCF4B,0xCF53,0xAC66,
+0xAC59,0xAC61,0xAC6D,0xAC56,0xAC58, 0, 0, 0,
+0xCF43,0xAC6A,0xAC63,0xCF5D,0xCF40,0xAC6C,0xAC67,0xCF49,
+ 0, 0,0xAC6B,0xCF50,0xCF48,0xAC64,0xCF5C,0xCF54,
+ 0,0xAC5E,0xCF62,0xCF47,0xAC5A,0xCF59,0xCF4F,0xAC5F,
+0xCF55,0xAC57,0xCEFC,0xAC68,0xAEE3,0xAC5D,0xCF4E,0xCF4D,
+0xCF42, 0,0xCF5E, 0,0xCF57, 0, 0,0xAC55,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD1EC,0xAEEA,0xD1ED, 0,0xD1E1,0xAEDF,
+0xAEEB, 0,0xD1DA, 0,0xD1E3,0xD1EB, 0,0xD1D9,
+0xD1F4,0xAED5, 0, 0, 0,0xD1F3,0xD1EE, 0,
+0xD1EF,0xAEDD,0xAEE8,0xD1E5, 0,0xD1E6,0xD1F0,0xD1E7,
+ 0,0xD1E2,0xD1DC,0xD1DD,0xD1EA,0xD1E4, 0, 0,
+0xAED6,0xAEDA,0xD1F2,0xD1DE,0xAEE6,0xAEE2, 0, 0,
+0xAEE5,0xAEEC,0xAEDB,0xAEE7,0xD1E9,0xAEE9,0xAED8, 0,
+0xAED7,0xD1DB, 0,0xD1DF,0xAEE0,0xD1F1,0xD1E8,0xD1E0,
+0xAEE4,0xAEE1, 0,0xAED9,0xAEDC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD5C4, 0,0xD5B4,0xD5B5,0xD5B9,
+ 0,0xD5C8,0xD5C5, 0,0xD5BE,0xD5BD,0xB1ED,0xD5C1,
+0xD5D0,0xD5B0, 0,0xD5D1,0xD5C3,0xD5D5,0xD5C9,0xB1EC,
+0xD5C7,0xB1E7,0xB1FC,0xB1F2, 0,0xB1F6,0xB1F5,0xD5B1,
+ 0,0xD5CE,0xD5D4,0xD5CC,0xD5D3, 0, 0,0xD5C0,
+0xD5B2,0xD5D2,0xD5C2,0xB1EA,0xB1F7, 0,0xD5CB,0xB1F0,
+ 0, 0, 0,0xD5CA,0xD5B3,0xB1F8, 0,0xB1FA,
+0xD5CD,0xB1FB,0xB1E9,0xD5BA,0xD5CF, 0, 0,0xB1EF,
+0xB1F9,0xD5BC,0xD5C6,0xD5B7,0xD5BB,0xB1F4,0xD5B6,0xB1E8,
+0xB1F1,0xB1EE,0xD5BF,0xAEDE,0xD9C0,0xB1EB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB1F3, 0,0xD9C3,0xD9D9,
+0xD9CE,0xB4D6, 0,0xB4D1,0xD9BD,0xB4D2,0xD9CD, 0,
+0xD9C6,0xD9D3,0xB4CE,0xD9AB,0xD9D5,0xB4C4,0xD9B3,0xB4C7,
+0xB4C6, 0,0xB4D7, 0,0xD9AD,0xD9CF,0xD9D0,0xB4C9,
+0xB4C5,0xD9BB, 0,0xB4D0,0xD9B6, 0,0xD9D1,0xB4CC,
+0xD9C9,0xD9D6,0xD9B0,0xD9B5,0xD9AF, 0,0xB4CB,0xD9C2,
+0xDDDE,0xD9B1,0xB4CF,0xD9BA,0xD9D2,0xB4CA,0xD9B7,0xD9B4,
+0xD9C5,0xB4CD,0xB4C3,0xB4D9,0xD9C8,0xD9C7, 0, 0,
+ 0, 0, 0, 0,0xD9AC,0xB4C8,0xD9D4,0xD9BC,
+0xD9BE, 0,0xD9CB,0xD9CA,0xD9AA,0xB4D3,0xB4D5,0xD9B2,
+0xD9B9,0xD9C1,0xB4D4,0xD9B8,0xD9C4,0xD9D7, 0,0xD9CC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD9D8, 0, 0,
+ 0, 0,0xD9AE, 0, 0, 0, 0,0xDDF2,
+0xB7A6, 0,0xDDF0,0xDDDB,0xDDE0,0xDDD9, 0,0xDDEC,
+0xDDCB,0xDDD2, 0,0xDDEA,0xDDF4,0xDDDC, 0,0xDDCF,
+0xDDE2,0xDDE7,0xDDD3, 0,0xDDE4,0xDDD0, 0, 0,
+0xDDD7,0xDDD8,0xB7A8,0xDDEB,0xDDE9, 0,0xDDCC,0xDDEE,
+ 0,0xDDEF,0xDDF1,0xB7AC,0xB7A4, 0,0xD5B8,0xDDD4,
+0xDDE6,0xDDD5,0xB7A1,0xB7B1,0xDDED,0xB7AF,0xB7AB,0xDDCA,
+0xB7A3, 0,0xDDCD,0xB7B0, 0,0xDDDD,0xDDC9, 0,
+0xB7A9,0xDDE1,0xDDD1,0xB7AA,0xDDDA,0xB77E,0xB4D8,0xDDE3,
+0xD9BF,0xDDCE, 0, 0,0xDDE8,0xB7A5,0xDDE5,0xB7A2,
+0xDDDF,0xB7AD,0xDDD6,0xDDF3, 0, 0, 0, 0,
+ 0, 0,0xB7A7,0xDEC6, 0, 0,0xB7AE, 0,
+ 0, 0, 0, 0, 0,0xE24A,0xE248, 0,
+0xE25E,0xE246, 0,0xE258,0xB77D,0xBA5F,0xE242,0xE25D,
+ 0,0xE247,0xE255,0xBA64,0xBA5D, 0,0xE25B, 0,
+0xE240,0xE25A, 0,0xBA6F,0xE251,0xE261,0xBA6D,0xE249,
+0xBA5E,0xE24B,0xE259,0xBA67,0xE244,0xBA6B,0xBA61,0xE24D,
+0xE243,0xE1FC, 0,0xE257,0xBA68,0xE260,0xE1FD,0xBA65,
+ 0,0xE253, 0,0xBA66,0xE245,0xE250,0xE24C,0xE24E,
+ 0,0xBA60,0xE25F,0xBA6E,0xE24F, 0,0xE262, 0,
+ 0,0xE1FE,0xE254,0xBA63,0xBA6C,0xBA6A,0xE241,0xE256,
+0xBA69, 0, 0,0xBA62,0xE252, 0, 0, 0,
+ 0,0xE25C, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE5D5, 0,0xE5D1,0xE5CD,0xE5E1,0xE5DE,
+0xBCCD, 0, 0,0xE5E5,0xE5D4,0xBCD8,0xE5DB, 0,
+ 0,0xE5D0,0xE5DA,0xBCD5,0xE5EE, 0,0xE5EB,0xE5DD,
+0xE5CE, 0, 0,0xE5E2,0xE5E4,0xBCD1,0xE5D8,0xE5D3,
+0xE5CA,0xBCCE,0xBCD6, 0,0xE5E7,0xBCD7,0xE5CB,0xE5ED,
+0xE5E0,0xE5E6,0xBCD4, 0, 0,0xE5E3, 0,0xE5EA,
+ 0,0xBCD9, 0,0xBCD3,0xE5DC,0xE5CF,0xE5EF,0xE5CC,
+0xE5E8,0xBCD0, 0,0xE5D6, 0,0xE5D7,0xBCCF,0xBCCC,
+0xE5D2,0xBCD2, 0,0xBCCB, 0,0xE5E9,0xE5EC,0xE5D9,
+0xE9CA, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE9C2, 0,0xE9BE,0xBEF6, 0, 0,
+0xBEEB,0xBEF0,0xBEEC,0xE9CC,0xE9D7,0xBEEA,0xE9C4,0xE9CD,
+0xE5DF,0xE9CE, 0, 0,0xBEF1, 0,0xE9DD,0xBEF5,
+0xBEF8,0xE9C0, 0,0xBEF4, 0,0xE9DB,0xE9DC,0xE9D2,
+0xE9D1,0xE9C9, 0, 0,0xE9D3,0xE9DA,0xE9D9, 0,
+0xBEEF,0xBEED,0xE9CB,0xE9C8, 0,0xE9C5,0xE9D8,0xBEF7,
+0xE9D6,0xBEF3,0xBEF2, 0,0xE9D0, 0,0xE9BF,0xE9C1,
+0xE9C3,0xE9D5,0xE9CF,0xBEEE, 0,0xE9C6, 0,0xE9D4,
+ 0, 0, 0, 0, 0, 0,0xE9C7, 0,
+ 0, 0, 0, 0, 0, 0,0xC0CF,0xED45,
+0xC0C8,0xECF5, 0,0xED41,0xC0CA,0xED48, 0,0xECFC,
+ 0,0xECF7, 0, 0,0xED49,0xECF3,0xECFE, 0,
+0xC0D1,0xED44,0xED4A,0xECFD,0xC0C9,0xED40,0xECF4,0xC0D0,
+ 0, 0,0xED47,0xECF9,0xC0CC, 0,0xECFB,0xECF8,
+0xC0D2,0xECFA,0xC0CB,0xC0CE,0xED43,0xECF6,0xED46, 0,
+0xED42, 0, 0, 0,0xC263,0xEFE7,0xC268,0xC269,
+ 0, 0, 0,0xC262,0xEFE6, 0,0xEFE3,0xEFE4,
+0xC266,0xEFDE,0xEFE2,0xC265, 0,0xEFDF, 0, 0,
+ 0, 0,0xC267,0xC264, 0,0xEFDD,0xEFE1,0xEFE5,
+ 0, 0, 0,0xF251,0xF24E,0xF257, 0,0xF256,
+0xF254,0xF24F, 0,0xC372, 0, 0, 0, 0,
+ 0,0xF250,0xC371,0xC0CD,0xF253,0xC370,0xF258,0xF252,
+0xF24D,0xEFE0, 0, 0, 0,0xC36F, 0,0xF24C,
+0xF456, 0,0xF455,0xF255,0xC468, 0,0xF459,0xF45A,
+0xF454,0xF458, 0,0xF453, 0, 0, 0, 0,
+0xF5D1,0xF457,0xC4E7,0xC4E5,0xF5CF, 0, 0, 0,
+0xF5D2, 0,0xF5CE,0xF5D0,0xC4E6, 0, 0, 0,
+0xF6E5,0xF6E6,0xC576,0xF6E4, 0, 0, 0,0xF7E2,
+0xC5CF,0xF7E0,0xF7E1,0xF8AC, 0, 0,0xC656,0xF8F3,
+0xF8F1,0xF8F2,0xF8F4, 0, 0, 0,0xF9BB, 0,
+0xA4ED,0xA6B8, 0,0xAA59, 0,0xCCE9, 0, 0,
+0xCF64, 0, 0, 0,0xD1F5,0xD1F7, 0,0xD1F6,
+ 0,0xD1F8,0xB1FD,0xD5D7,0xD1F9, 0,0xD5D6,0xD5D8,
+0xD5D9,0xD9DA,0xB4DB,0xD9DB,0xD9DD,0xB4DC,0xB4DA,0xD9DC,
+ 0,0xDDFA,0xDDF8,0xDDF7, 0,0xDDF6,0xDDF5,0xB7B2,
+0xDDF9,0xBA70,0xE263,0xE265,0xBA71,0xE264,0xBCDB, 0,
+0xBCDA,0xE5F0, 0, 0,0xE9DF,0xE9DE,0xE9E0, 0,
+ 0,0xBEF9, 0,0xED4B,0xC0D3, 0,0xEFE8,0xC26A,
+0xF259,0xC577,0xA4EE,0xA5BF,0xA6B9,0xA842,0xAA5A,0xAA5B,
+ 0, 0,0xAC6E, 0, 0,0xD1FA, 0, 0,
+ 0, 0,0xB7B3, 0, 0, 0,0xE6D1,0xBEFA,
+0xC26B,0xA4EF, 0,0xA6BA, 0, 0,0xCCEB,0xAA5C,
+0xCCEA, 0,0xCF65,0xAC6F,0xCF66, 0,0xAC70, 0,
+0xD1FC,0xAEEE,0xAEED, 0,0xD5DE,0xD5DC,0xD5DD,0xD5DB,
+ 0,0xD5DA, 0, 0,0xD9DE,0xD9E1,0xB4DE,0xD9DF,
+0xB4DD,0xD9E0, 0,0xDDFB, 0, 0,0xE266,0xE267,
+0xE268, 0,0xE5F3,0xE5F2,0xBCDC,0xE5F1,0xE5F4,0xE9E1,
+ 0, 0,0xE9E2,0xE9E3, 0,0xED4C,0xC0D4,0xC26C,
+0xF25A, 0,0xC4E8,0xC95F, 0,0xAC71,0xCF67,0xAEEF,
+ 0, 0,0xB1FE, 0,0xB4DF,0xD9E2, 0,0xB7B5,
+0xB7B4, 0, 0,0xE269,0xE26A,0xBCDD,0xBCDE,0xE9E5,
+0xE9E4,0xEFE9,0xF7E3,0xA4F0,0xC960,0xA5C0, 0,0xA843,
+0xCB48, 0,0xAC72,0xB7B6,0xA4F1, 0,0xCF68,0xAC73,
+0xCF69, 0,0xC0D5,0xA4F2, 0, 0,0xCCEC, 0,
+0xCF6A, 0,0xD242,0xD241,0xD1FE, 0,0xD1FD,0xD243,
+0xD240, 0, 0,0xB240,0xB241, 0, 0,0xB4E0,
+0xD9E3, 0,0xD9E4,0xD9E5, 0, 0, 0,0xDE41,
+0xDE42,0xDE40, 0,0xDDFD,0xDDFE,0xB7B7,0xE26B,0xE5F7,
+0xE5F6,0xE5F5,0xE5F8,0xE9E7,0xE9E6,0xBEFB,0xE9E8, 0,
+0xC0D6,0xED4D, 0,0xEFEA,0xF25B,0xF6E7, 0,0xA4F3,
+0xA5C2,0xA5C1, 0,0xAA5D,0xC961,0xC97E,0xA6BB, 0,
+0xC9F7,0xCB49,0xCB4A,0xAA5E, 0,0xCCED, 0,0xAC74,
+0xCF6B,0xCF6C, 0,0xAEF0,0xAEF4,0xD244,0xAEF3,0xAEF1,
+0xAEF2, 0,0xD5DF,0xB242,0xB4E3, 0,0xB4E1,0xB4E2,
+0xD9E6, 0, 0,0xBA72,0xA4F4, 0,0xC9A1, 0,
+0xA5C3, 0, 0,0xC9A4, 0, 0,0xA5C6,0xC9A3,
+0xA5C5,0xA5C4,0xA844,0xC9A2, 0, 0,0xC9F8, 0,
+ 0, 0,0xC9FC,0xC9FE,0xCA40,0xA6C5,0xA6C6,0xC9FB,
+0xA6C1, 0,0xC9F9, 0,0xC9FD,0xA6C2, 0,0xA6BD,
+ 0,0xA6BE, 0,0xA6C4,0xC9FA,0xA6BC,0xA845,0xA6BF,
+0xA6C0,0xA6C3, 0, 0, 0,0xCB5B,0xCB59,0xCB4C,
+0xA851,0xCB53,0xA84C,0xCB4D, 0,0xCB55, 0,0xCB52,
+0xA84F,0xCB51,0xA856,0xCB5A,0xA858, 0,0xA85A, 0,
+0xCB4B, 0,0xA84D,0xCB5C, 0,0xA854,0xA857, 0,
+0xCD45,0xA847,0xA85E,0xA855,0xCB4E,0xA84A,0xA859,0xCB56,
+0xA848,0xA849,0xCD43,0xCB4F,0xA850,0xA85B,0xCB5D,0xCB50,
+0xA84E, 0,0xA853,0xCCEE,0xA85C,0xCB57,0xA852, 0,
+0xA85D,0xA846,0xCB54,0xA84B,0xCB58,0xCD44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xAA6A,0xAA7A,0xCCF5,0xAA71, 0,
+0xCD4B,0xAA62, 0,0xAA65,0xCD42, 0,0xCCF3,0xCCF7,
+0xAA6D,0xAA6F,0xCCFA,0xAA76,0xAA68,0xAA66,0xAA67,0xAA75,
+0xCD47,0xAA70,0xCCF9,0xCCFB,0xAA6E,0xAA73,0xCCFC,0xCD4A,
+ 0,0xAC75,0xAA79, 0,0xAA63,0xCD49, 0,0xCD4D,
+0xCCF8,0xCD4F,0xCD40,0xAA6C,0xCCF4,0xAA6B,0xAA7D,0xAA72,
+ 0,0xCCF2,0xCF75,0xAA78,0xAA7C,0xCD41,0xCD46, 0,
+0xAA7E,0xAA77,0xAA69,0xAA5F, 0,0xAA64, 0,0xCCF6,
+0xAA60,0xCD4E, 0,0xCCF0,0xCCEF,0xCCFD,0xCCF1,0xAA7B,
+0xAEF5,0xAA74,0xCCFE,0xAA61, 0,0xACA6, 0, 0,
+ 0,0xCD4C, 0, 0, 0, 0, 0, 0,
+0xCF7C,0xCFA1, 0,0xCFA4,0xCF77, 0, 0,0xCFA7,
+0xCFAA,0xCFAC,0xCF74,0xAC76,0xAC7B,0xD249,0xACAD,0xCFA5,
+0xCFAD,0xCF7B,0xCF73, 0, 0, 0,0xD264,0xAC7E,
+0xCFA2,0xCF78,0xCF7A,0xACA5, 0,0xCF7D,0xAC7D,0xCF70,
+0xCFA8, 0,0xCFAB, 0, 0,0xAC7A, 0,0xACA8,
+0xCF6D,0xACAA,0xAC78,0xACAE,0xCFA9,0xCF6F,0xACAB,0xD25E,
+0xCD48,0xAC7C,0xAC77,0xCF76,0xCF6E,0xACAC,0xACA4,0xCFA3,
+0xACA9,0xACA7,0xCF79,0xACA1,0xCF71,0xACA2,0xACA3,0xCF72,
+0xCFA6,0xAC79,0xCF7E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD24C,0xAEFD,0xAF43, 0, 0, 0,0xD255,0xD25B,
+0xD257,0xD24A,0xD24D,0xD246,0xD247,0xAF4A,0xAEFA,0xD256,
+0xD25F,0xAF45,0xAEF6, 0,0xAF40,0xD24E,0xAF42,0xD24F,
+0xD259, 0, 0, 0,0xAF44,0xD268,0xD248,0xAEFC,
+0xAEFB,0xAF48,0xD245,0xD266,0xD25A,0xD267,0xD261,0xD253,
+0xD262, 0,0xD25C,0xD265,0xD263,0xAF49,0xD254,0xAEF9,
+0xAEF8,0xAF41,0xAF47,0xD260,0xAF46,0xD251,0xB243, 0,
+0xD269,0xD250,0xD24B,0xAEFE,0xAF4B,0xAEF7, 0,0xD258,
+0xD25D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB265,0xD5E1,0xD5E5, 0,0xB252,0xB250,
+ 0, 0,0xB247,0xD5E3,0xD5E2,0xB25B, 0,0xD5E8,
+0xB255, 0,0xD5FA,0xD647,0xB244,0xD5F7,0xD5F0,0xB267,
+0xD5E0, 0,0xD5FC, 0,0xB264,0xB258,0xB263,0xB24E,
+0xD5EC,0xD5FE,0xD5F6,0xB24F,0xB249,0xD645, 0,0xD5FD,
+0xD640,0xB251,0xB259,0xD642,0xD5EA,0xD5FB,0xD5EF,0xD644,
+0xB25E,0xB246,0xB25C,0xD5F4,0xD5F2,0xD5F3,0xB253,0xD5EE,
+0xD5ED,0xB248,0xD5E7,0xD646,0xB24A,0xD5F1,0xB268, 0,
+0xB262,0xD5E6,0xB25F,0xB25D,0xB266,0xD5F8,0xB261,0xD252,
+0xD5F9,0xB260,0xD641,0xB245,0xD5F5,0xB257,0xD5E9,0xB256,
+ 0,0xB254,0xB24C,0xB24B,0xD9E7,0xD643, 0, 0,
+0xD5EB, 0, 0,0xD9FC, 0,0xB24D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB541,0xB25A,0xB4EE,0xD9F6,0xB4FC, 0,0xD9EA,
+0xB4EB,0xB4E7,0xDA49,0xB4ED,0xB4F1,0xB4EC,0xB4F5,0xDA4D,
+0xDA44, 0, 0,0xD9F1,0xB4FA,0xB4F4,0xD9FD,0xB4E4,
+0xDA4A,0xDA43,0xB4E8,0xD9F7,0xB4F7,0xDA55,0xDA56, 0,
+0xB4E5,0xDA48,0xB4F9,0xD9FB,0xD9ED,0xD9EE,0xB4FD,0xD9F2,
+0xD9F9,0xD9F3, 0,0xB4FB,0xB544,0xD9EF,0xD9E8,0xD9E9,
+ 0,0xD9EB,0xB4EA,0xD9F8, 0,0xB4F8,0xB542, 0,
+ 0,0xD9FA,0xDA53,0xDA4B,0xB4E6,0xDA51,0xB4F2, 0,
+0xB4F0, 0,0xDA57,0xB4EF,0xDA41,0xD9F4,0xD9FE,0xB547,
+0xDA45,0xDA42,0xD9F0,0xB543,0xDA4F,0xDA4C,0xDA54,0xB4E9,
+0xDA40,0xB546, 0,0xDA47, 0, 0,0xB4F3,0xB4F6,
+ 0,0xDA46,0xB545,0xD9F5,0xD5E4, 0, 0,0xDA50,
+0xDA4E,0xDA52, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD9EC,0xB540, 0, 0, 0,0xDE61,0xDE60,0xDE46,
+0xB7BD, 0,0xDE5F,0xDE49,0xDE4A, 0,0xB7C7,0xDE68,
+0xB7C2,0xDE5E, 0,0xDE43,0xB7C8,0xB7BE,0xDE52,0xDE48,
+0xDE4B,0xDE63,0xB7B8,0xDE6A,0xDE62,0xB7C1,0xDE57,0xB7CC,
+ 0, 0,0xB7CB,0xB7C5, 0, 0,0xDE69,0xB7B9,
+0xDE55,0xDE4C,0xDE59,0xDE65,0xB7CD, 0,0xB7BB,0xDE54,
+ 0,0xDE4D,0xB7C4, 0,0xB7C3,0xDE50,0xDE5A,0xDE64,
+0xDE47,0xDE51,0xB7BC,0xDE5B,0xB7C9,0xB7C0,0xDE4E,0xB7BF,
+0xDE45,0xDE53,0xDE67,0xB4FE,0xBAB0,0xDE56,0xE26C,0xDE58,
+0xDE66,0xB7C6,0xDE4F,0xB7BA,0xB7CA,0xBCF0,0xDE44, 0,
+0xDE5D, 0, 0, 0,0xDE5C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE2AA,0xBAAD,0xE27D,0xE2A4,0xBAA2,
+ 0,0xE26E,0xBAAF, 0,0xBA77,0xE26D,0xE2B0,0xBAB1,
+0xE271,0xE2A3, 0,0xE273,0xE2B3,0xE2AF,0xBA75,0xBAA1,
+0xE653,0xBAAE,0xBA7D,0xE26F, 0,0xE2AE,0xBAA3,0xE2AB,
+0xE2B8,0xE275,0xE27E, 0, 0,0xE2B6,0xE2AC,0xBA7C,
+ 0, 0,0xE27C,0xBA76,0xBA74,0xBAA8, 0, 0,
+0xE27A,0xE277,0xE278, 0,0xE2B2, 0,0xE2B7,0xE2B5,
+0xBA7A,0xE2B9,0xBA7E,0xBAA7, 0,0xE270,0xE5FA,0xE279,
+ 0,0xBA78,0xBAAC,0xBAA9,0xBA7B,0xE2A5,0xE274,0xBAAA,
+0xE2A7,0xBAA4,0xBAA6,0xBA73, 0,0xE2A9,0xE2A1,0xE272,
+0xBAA5,0xE2B1,0xE2B4,0xE27B,0xE2A8, 0,0xBA79,0xBCDF,
+0xE2A6,0xE5F9, 0,0xE2AD, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE276,0xE644,
+0xE64E,0xBCE2,0xE64D,0xE659,0xBCE4,0xE64B, 0,0xE64F,
+0xBCEF, 0,0xE646,0xBCE7, 0,0xE652,0xE9F0,0xBCF3,
+0xBCF2,0xE654,0xE643,0xE65E,0xBCED, 0,0xBCE3,0xE657,
+ 0,0xE65B,0xE660,0xE655,0xE649,0xBCE6,0xBCE9,0xBCF1,
+0xBCEC, 0,0xE64C,0xE2A2, 0, 0,0xE648,0xE65F,
+0xBCE8, 0,0xBCEB,0xE661,0xBCE0,0xE656,0xE5FB,0xE65C,
+0xC0DF, 0,0xE64A, 0,0xBCE1,0xE645,0xBCE5,0xE5FC,
+0xBAAB,0xE641, 0,0xE65A,0xE642,0xE640,0xBCEA, 0,
+0xE658, 0,0xE5FE,0xE651,0xE650,0xE65D,0xE647,0xBCEE,
+ 0, 0, 0, 0, 0, 0,0xE9F3, 0,
+0xBF49,0xBEFE,0xEA40,0xE9EB,0xBF41,0xE9F7,0xBF48,0xBF43,
+0xE9F5,0xED4F,0xE9FB,0xEA42,0xE9FA,0xE9E9,0xE9F8,0xEA44,
+0xEA46,0xBEFD,0xEA45,0xBF44,0xBF4A, 0,0xBF47, 0,
+0xE9FE,0xBF46,0xE9F9, 0,0xE9ED,0xE9F2, 0,0xE9FD,
+0xBF45,0xBF42,0xBEFC,0xBF40,0xE9F1, 0,0xE5FD,0xE9EC,
+0xE9EF,0xEA41,0xE9F4,0xE9EA,0xED4E,0xEA43,0xE9EE,0xE9FC,
+ 0, 0, 0, 0,0xED51,0xC0E3, 0, 0,
+0xC0D7, 0, 0,0xC0DB,0xED53,0xED59,0xED57,0xC0D9,
+0xC0DA,0xC0E1,0xED5A,0xED52,0xC0DC, 0,0xED56,0xED55,
+0xED5B,0xC0E2, 0,0xC0DD,0xC0E0,0xED54,0xC0E4,0xC0DE,
+0xC0E5,0xC0D8,0xED58, 0,0xED50, 0, 0,0xEFF7,
+ 0, 0,0xC271,0xEFF4,0xEFF6, 0,0xC26F,0xEFF2,
+0xEFF3,0xEFEE, 0, 0,0xE9F6,0xEFEF,0xC270,0xEFEB,
+ 0,0xC26D,0xEFF8,0xC26E,0xEFEC,0xEFED,0xEFF1,0xC273,
+ 0,0xC272, 0, 0,0xEFF0,0xC378,0xF25F,0xF265,
+0xC379,0xF25C,0xC376,0xC373,0xF267,0xC377, 0,0xC374,
+0xF25E,0xF261,0xF262,0xF263,0xF266, 0,0xEFF5,0xF25D,
+0xC375,0xF264,0xF268,0xF260, 0, 0, 0,0xF45D,
+0xC46A,0xF460,0xC46B,0xF468,0xF45F,0xF45C, 0,0xF45E,
+0xF462,0xF465,0xF464,0xF467,0xF45B, 0,0xC469,0xF463,
+0xF466,0xF469,0xF461,0xF5D3,0xF5D4,0xF5D8,0xF5D9, 0,
+0xF5D6,0xF5D7,0xF5D5, 0,0xC4E9, 0, 0, 0,
+ 0,0xC578,0xF6EB, 0, 0,0xF6E8,0xF6E9,0xF6EA,
+0xC579, 0,0xF7E5,0xF7E4, 0,0xF8AF,0xC5F4,0xF8AD,
+0xF8B0,0xF8AE,0xF8F5,0xC657,0xC665,0xF9A3,0xF96C, 0,
+0xF9A2,0xF9D0,0xF9D1,0xA4F5, 0, 0, 0, 0,
+0xA6C7,0xCA41, 0, 0,0xCB5E, 0,0xA85F, 0,
+0xA862, 0,0xCB5F, 0,0xA860,0xA861, 0, 0,
+ 0, 0,0xCD58,0xCD5A,0xCD55,0xCD52,0xCD54, 0,
+ 0, 0,0xAAA4, 0, 0, 0,0xAAA2, 0,
+ 0,0xCD56,0xAAA3,0xCD53,0xCD50,0xAAA1,0xCD57, 0,
+0xCD51,0xAAA5,0xCD59, 0, 0, 0, 0,0xCFAF,
+ 0,0xCFB3, 0, 0,0xACB7, 0, 0, 0,
+ 0,0xCFB6, 0,0xACAF,0xACB2,0xACB4,0xACB6,0xACB3,
+0xCFB2,0xCFB1, 0,0xACB1,0xCFB4,0xCFB5, 0,0xCFAE,
+0xACB5, 0,0xACB0, 0, 0, 0,0xCFB0, 0,
+ 0, 0, 0, 0, 0,0xD277,0xD278,0xD279,
+0xAF50, 0,0xAF4C,0xD26E, 0,0xD276,0xD27B,0xAF51,
+ 0,0xD26C,0xD272,0xD26B,0xD275, 0, 0,0xD271,
+0xAF4D,0xAF4F,0xD27A, 0,0xD26A,0xD26D,0xD273, 0,
+0xD274,0xD27C,0xD270, 0,0xAF4E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xB26D,
+0xD64E, 0, 0,0xD650,0xD64C, 0,0xD658,0xD64A,
+0xD657,0xB269,0xD648,0xDA5B,0xD652,0xB26C, 0,0xD653,
+0xD656, 0,0xD65A, 0,0xD64F, 0,0xD654, 0,
+ 0,0xB26A,0xB26B,0xD659,0xD64D,0xD649,0xD65B, 0,
+0xD651, 0, 0,0xD655, 0, 0, 0,0xD64B,
+ 0,0xB548,0xB549,0xDA65,0xB54F, 0,0xDA59,0xDA62,
+0xDA58,0xB54C,0xDA60,0xDA5E, 0,0xDA5F,0xB54A, 0,
+0xDA63, 0, 0, 0, 0, 0,0xDA5C,0xDA5A,
+0xB54B,0xDA5D,0xDA61, 0, 0, 0,0xB54D, 0,
+ 0, 0,0xDA64, 0, 0, 0, 0, 0,
+ 0,0xDE70,0xDE77,0xDE79,0xDEA1, 0,0xB7DA,0xDE6B,
+ 0,0xB7D2, 0,0xDE7A,0xB7D7,0xDEA2,0xB7CE, 0,
+0xDE7D, 0,0xDE6D,0xDE7E,0xDE6C, 0,0xB7DC, 0,
+0xDE78,0xB7CF,0xDEA3, 0,0xB7D4,0xDE71,0xB7D9,0xDE7C,
+0xDE6F,0xDE76,0xDE72,0xDE6E,0xB7D1,0xB7D8,0xB7D6,0xB7D3,
+0xB7DB,0xB7D0,0xDE75, 0,0xB7D5, 0,0xB54E, 0,
+0xDE7B, 0,0xDE73, 0, 0, 0, 0, 0,
+0xDE74, 0, 0,0xE2C1, 0,0xBAB4, 0, 0,
+0xE2BD,0xE2C3,0xE2BF, 0,0xBAB6,0xE2BE,0xE2C2,0xE2BA,
+ 0,0xE2BC,0xBAB5, 0, 0, 0, 0,0xE2C0,
+0xE2BB, 0,0xBAB7, 0,0xBAB2, 0, 0,0xE2C4,
+ 0,0xBAB3,0xE667,0xE664,0xE670,0xE66A,0xE66C,0xBCF4,
+0xE666,0xE66E, 0, 0,0xE66D,0xE66B, 0,0xE671,
+0xBCF7,0xE668,0xE66F, 0,0xBCF5, 0, 0,0xE663,
+0xE665,0xBCF6,0xE662,0xE672, 0,0xE669, 0, 0,
+0xEA4A,0xBF51, 0, 0,0xEA55,0xEA53,0xBF4B,0xEA49,
+0xEA4C,0xEA4D,0xEA48,0xBF55,0xBF56,0xEA47,0xEA56,0xEA51,
+0xBF4F,0xBF4C,0xEA50,0xEA4E, 0, 0,0xBF52,0xEA52,
+0xBF4D, 0,0xBF4E, 0,0xEA4F,0xBF50,0xEA4B, 0,
+0xEA54,0xBF53,0xEA57,0xEA58,0xBF54, 0, 0,0xC0E7,
+0xC0EE,0xED5C,0xED62, 0,0xED60,0xC0EA,0xC0E9,0xC0E6,
+0xED5E, 0, 0, 0,0xC0EC,0xC0EB,0xC0E8, 0,
+0xED61,0xED5D,0xED5F, 0,0xC0ED, 0, 0, 0,
+0xC277,0xEFFB, 0,0xC274,0xC275,0xEFFD,0xC276,0xEFFA,
+ 0,0xEFF9,0xF26C,0xEFFC, 0,0xF26D,0xC37A,0xF26B,
+ 0, 0,0xF26A, 0,0xF269,0xC37B, 0, 0,
+0xC46C, 0, 0,0xF46A,0xF46B, 0, 0, 0,
+ 0,0xF5DC,0xF5DB,0xC4EA, 0,0xF5DA,0xF6EC,0xF6ED,
+ 0, 0,0xF7E6,0xF8B1, 0, 0,0xF8F6,0xF9BC,
+0xC679,0xF9C6,0xA4F6, 0,0xAAA6,0xAAA7, 0, 0,
+0xACB8, 0, 0, 0, 0,0xC0EF,0xA4F7, 0,
+0xAAA8,0xAF52,0xB7DD,0xA4F8, 0,0xB26E,0xBAB8,0xC962,
+ 0,0xCFB7,0xD27D, 0,0xE2C5, 0,0xC0F0,0xA4F9,
+0xAAA9,0xCFB8,0xCFB9,0xDA66,0xB550, 0, 0,0xDEA4,
+ 0, 0,0xB7DE,0xE2C6, 0, 0,0xBCF8, 0,
+0xC37C,0xA4FA,0xDA67,0xA4FB, 0,0xA6C9,0xCA42,0xA6C8,
+0xA865,0xA864,0xA863,0xCB60, 0, 0, 0,0xAAAA,
+ 0,0xAAAB,0xCD5B, 0,0xCFBA, 0,0xCFBD,0xACBA,
+0xCFBB, 0,0xACB9,0xCFBC,0xACBB, 0,0xD2A2,0xD2A1,
+0xD27E,0xAF53, 0,0xD65D,0xD65E,0xB26F,0xD65C,0xD65F,
+0xB552,0xB270, 0, 0,0xB551,0xDA6B,0xDA6A, 0,
+0xDA68,0xDA69, 0,0xDA6C,0xDEA6,0xDEA5,0xDEA9, 0,
+0xDEA8,0xDEA7,0xBAB9,0xE2C9, 0,0xE2C8,0xBABA,0xE2C7,
+0xE673, 0,0xE674,0xBCF9, 0,0xEA59,0xEA5A, 0,
+ 0,0xF272,0xC37D,0xF271,0xF270,0xF26E,0xF26F,0xC4EB,
+0xF46C,0xF6EE,0xF8F7, 0,0xA4FC, 0,0xC9A5,0xA5C7,
+0xC9A6, 0, 0, 0,0xCA43,0xCA44, 0, 0,
+ 0, 0,0xCB66, 0, 0,0xCB62, 0,0xCB61,
+0xAAAC,0xCB65,0xA867,0xCB63,0xA866,0xCB67,0xCB64, 0,
+ 0,0xCD5F,0xCFBE,0xCD5D,0xCD64, 0,0xAAAD, 0,
+0xAAB0,0xCD65,0xCD61, 0,0xCD62, 0,0xCD5C,0xAAAF,
+0xCD5E,0xAAAE,0xCD63, 0,0xCD60, 0, 0,0xCFC2,
+0xACBD,0xACBE, 0,0xCFC5,0xCFBF, 0,0xCFC4, 0,
+0xCFC0,0xACBC,0xCFC3,0xCFC1, 0, 0, 0, 0,
+ 0, 0, 0,0xD2A8,0xD2A5, 0,0xD2A7,0xAF58,
+0xAF57,0xAF55,0xD2A4,0xD2A9,0xAF54,0xAF56,0xD2A6,0xD667,
+0xD2A3,0xD2AA, 0, 0, 0, 0, 0,0xD662,
+0xD666, 0,0xD665,0xDA6E,0xDA79, 0, 0,0xD668,
+ 0,0xD663,0xDA6D,0xB274, 0, 0,0xB273,0xD661,
+0xD664,0xB275, 0,0xB272,0xB271,0xD660,0xD669, 0,
+ 0, 0,0xDA70,0xDA77, 0,0xB554,0xDA76,0xDA73,
+ 0,0xB556, 0, 0, 0,0xDA75, 0, 0,
+0xDA6F,0xDA71,0xDA74,0xDA72,0xB555,0xDA78,0xB553,0xB7DF,
+ 0, 0,0xDEAD,0xDEAC,0xDEAA, 0,0xB7E2,0xB7E1,
+0xDEAE, 0,0xDEAB,0xE2CA,0xBABB,0xB7E0, 0, 0,
+ 0,0xDEB0,0xDEAF, 0,0xE2CD,0xE2CB,0xBCFA, 0,
+0xBABC,0xE2CC,0xE676, 0, 0, 0, 0,0xBCFB,
+0xE675,0xE67E,0xE67D,0xE67B, 0,0xE67A,0xE677,0xE678,
+0xE679,0xE67C,0xE6A1, 0, 0,0xEA5F,0xEA5C,0xEA5D,
+0xBF57,0xEA5B,0xEA61,0xEA60,0xEA5E, 0,0xED64,0xED65,
+0xC0F1, 0,0xC0F2,0xED63, 0,0xC279,0xEFFE,0xC278,
+0xC37E, 0,0xC3A1,0xC46D,0xF46E,0xF46D,0xF5DD,0xF6EF,
+0xC57A,0xF7E8,0xF7E7,0xF7E9,0xA5C8,0xCFC6,0xAF59,0xB276,
+0xD66A,0xA5C9,0xC9A7,0xA4FD, 0, 0,0xCA45, 0,
+ 0, 0,0xCB6C,0xCB6A,0xCB6B,0xCB68,0xA868,0xCB69,
+ 0, 0, 0, 0, 0,0xCD6D, 0,0xAAB3,
+0xCD6B,0xCD67,0xCD6A, 0,0xCD66,0xAAB5,0xCD69, 0,
+0xAAB2,0xAAB1, 0,0xAAB4,0xCD6C,0xCD68, 0, 0,
+ 0, 0,0xACC2,0xACC5,0xCFCE,0xCFCD,0xCFCC,0xACBF,
+0xCFD5,0xCFCB, 0,0xACC1,0xD2AF, 0,0xCFD2,0xCFD0,
+0xACC4, 0,0xCFC8,0xCFD3, 0,0xCFCA,0xCFD4,0xCFD1,
+0xCFC9, 0,0xACC0,0xCFD6,0xCFC7,0xACC3, 0, 0,
+ 0, 0,0xD2B4,0xD2AB,0xD2B6, 0,0xD2AE,0xD2B9,
+0xD2BA,0xD2AC,0xD2B8,0xD2B5,0xD2B3,0xD2B7,0xAF5F, 0,
+0xAF5D, 0, 0,0xD2B1, 0,0xD2AD, 0,0xD2B0,
+0xD2BB,0xD2B2,0xAF5E,0xCFCF, 0,0xAF5A,0xAF5C, 0,
+ 0, 0, 0, 0,0xD678,0xD66D,0xD66B, 0,
+0xD66C, 0,0xD673, 0,0xD674,0xD670,0xB27B,0xD675,
+0xD672,0xD66F, 0,0xB279,0xD66E,0xB277,0xB27A,0xD671,
+0xD679,0xAF5B,0xB278,0xD677,0xD676,0xB27C, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDA7E, 0,
+ 0, 0,0xDAA1,0xB560, 0,0xDAA7, 0, 0,
+0xDAA9,0xDAA2,0xB55A,0xDAA6,0xDAA5,0xB55B,0xB561, 0,
+0xB562,0xDAA8,0xB558,0xDA7D,0xDA7B,0xDAA3,0xDA7A,0xB55F,
+0xDA7C,0xDAA4,0xDAAA,0xB559,0xB55E,0xB55C,0xB55D, 0,
+ 0, 0,0xB557, 0, 0, 0, 0,0xB7E9,
+0xDEB7,0xB7E8,0xDEBB, 0,0xDEB1, 0,0xDEBC, 0,
+ 0, 0,0xDEB2,0xDEB3, 0,0xDEBD,0xDEBA,0xDEB8,
+0xDEB9,0xDEB5,0xDEB4, 0,0xDEBE,0xB7E5, 0,0xDEB6,
+ 0,0xB7EA,0xB7E4,0xB7EB,0xB7EC, 0,0xB7E7,0xB7E6,
+ 0, 0,0xE2CE,0xBABE,0xBABD, 0, 0,0xE2D3,
+ 0,0xBCFC,0xBABF, 0, 0,0xBAC1,0xE2D4,0xB7E3,
+0xBAC0,0xE2D0,0xE2D2,0xE2CF, 0,0xE2D1, 0, 0,
+ 0,0xE6AB, 0, 0,0xE6AA,0xE6A7,0xBD40,0xEA62,
+0xBD41,0xE6A6, 0,0xBCFE, 0,0xE6A8,0xE6A5,0xE6A2,
+0xE6A9,0xE6A3,0xE6A4,0xBCFD, 0, 0, 0, 0,
+0xED69, 0,0xEA66, 0,0xEA65,0xEA67, 0,0xED66,
+0xBF5A, 0,0xEA63, 0,0xBF58, 0,0xBF5C,0xBF5B,
+0xEA64,0xEA68, 0,0xBF59, 0,0xED6D,0xC0F5,0xC27A,
+0xC0F6,0xC0F3,0xED6A,0xED68, 0,0xED6B, 0,0xED6E,
+0xC0F4,0xED6C,0xED67, 0, 0,0xF042,0xF045,0xF275,
+0xF040, 0,0xF46F,0xF046, 0,0xC3A2,0xF044,0xC27B,
+0xF041,0xF043,0xF047,0xF276, 0,0xF274, 0, 0,
+ 0, 0,0xC3A3,0xF273, 0, 0, 0,0xC46E,
+ 0, 0, 0, 0,0xC4ED,0xF6F1,0xC4EC,0xF6F3,
+0xF6F0,0xF6F2,0xC5D0,0xF8B2,0xA5CA,0xCD6E,0xD2BC,0xD2BD,
+0xB27D,0xDEBF,0xBF5D,0xC3A4,0xC57B,0xF8B3,0xA5CB, 0,
+0xCD6F,0xA260, 0, 0,0xCFD7, 0,0xCFD8, 0,
+ 0, 0, 0, 0,0xD2BE,0xD2BF,0xB27E,0xB2A1,
+ 0, 0, 0,0xDAAB, 0,0xDEC2,0xDEC1,0xDEC0,
+0xE2D5, 0,0xE2D6,0xE2D7,0xBAC2, 0, 0,0xE6AD,
+0xE6AC, 0, 0,0xEA69,0xBF5E,0xBF5F, 0,0xED72,
+0xED6F,0xED70,0xED71,0xF049,0xF048,0xC27C,0xF277,0xF5DE,
+0xA5CC, 0,0xACC6, 0,0xB2A2,0xDEC3, 0,0xA5CD,
+ 0,0xD2C0,0xB2A3, 0, 0,0xB563,0xB564, 0,
+0xA5CE,0xA5CF,0xCA46,0xA86A,0xA869,0xACC7,0xCFD9,0xDAAC,
+0xA5D0,0xA5D1,0xA5D2,0xA5D3, 0, 0, 0,0xA86B,
+0xA86C,0xCB6E,0xCB6D, 0, 0,0xAAB6,0xCD72,0xCD70,
+0xCD71, 0, 0, 0, 0, 0, 0,0xCFDA,
+0xCFDB, 0, 0,0xACCB,0xACC9, 0,0xACCA,0xACC8,
+ 0, 0, 0, 0,0xAF60, 0, 0, 0,
+ 0,0xAF64,0xAF63,0xD2C1,0xAF62,0xAF61, 0,0xD2C2,
+ 0, 0,0xB2A6,0xD67B,0xD67A,0xB2A4,0xB2A5, 0,
+ 0, 0,0xB566,0xB565,0xDAAE, 0, 0,0xDAAD,
+0xB2A7, 0, 0, 0, 0, 0,0xB7ED,0xDEC5,
+0xB7EE,0xDEC4, 0, 0, 0,0xE2D8,0xE6AE,0xBD42,
+0xEA6A, 0, 0, 0,0xED73, 0,0xC3A6,0xC3A5,
+ 0, 0,0xC57C,0xA5D4,0xCD73, 0, 0,0xB2A8,
+0xE2D9,0xBAC3, 0, 0,0xCB6F,0xCB70, 0, 0,
+0xCD74,0xAAB8,0xAAB9, 0, 0,0xAAB7, 0, 0,
+ 0, 0,0xACCF,0xACD0,0xACCD,0xACCE, 0,0xCFDC,
+ 0, 0,0xCFDD,0xACCC, 0, 0, 0, 0,
+0xD2C3, 0,0xAF68,0xAF69, 0,0xB2AB,0xD2C9, 0,
+0xAF6E,0xAF6C,0xD2CA,0xD2C5,0xAF6B,0xAF6A,0xAF65,0xD2C8,
+0xD2C7,0xD2C4,0xAF6D, 0,0xD2C6,0xAF66, 0,0xAF67,
+ 0, 0,0xB2AC,0xD6A1,0xD6A2,0xB2AD,0xD67C,0xD67E,
+0xD6A4,0xD6A3,0xD67D, 0,0xB2A9,0xB2AA, 0,0xDAB6,
+0xB56B,0xB56A,0xDAB0,0xB568, 0,0xDAB3,0xB56C,0xDAB4,
+0xB56D,0xDAB1,0xB567,0xB569,0xDAB5, 0,0xDAB2,0xDAAF,
+ 0, 0, 0, 0, 0,0xDED2, 0,0xDEC7,
+0xB7F0,0xB7F3,0xB7F2,0xB7F7,0xB7F6,0xDED3,0xDED1,0xDECA,
+0xDECE,0xDECD,0xB7F4,0xDED0,0xDECC,0xDED4,0xDECB,0xB7F5,
+0xB7EF,0xB7F1, 0,0xDEC9, 0, 0, 0, 0,
+0xE2DB,0xBAC7,0xE2DF,0xBAC6,0xE2DC,0xBAC5, 0,0xDEC8,
+0xDECF,0xE2DE, 0,0xBAC8,0xE2E0,0xE2DD,0xE2DA, 0,
+ 0,0xE6B1,0xE6B5,0xE6B7,0xE6B3,0xE6B2,0xE6B0,0xBD45,
+0xBD43,0xBD48,0xBD49,0xE6B4,0xBD46,0xE6AF,0xBD47,0xBAC4,
+0xE6B6,0xBD44, 0, 0, 0,0xEA6C, 0,0xEA6B,
+0xEA73,0xEA6D,0xEA72,0xEA6F,0xBF60,0xEA71, 0, 0,
+0xBF61, 0,0xBF62, 0,0xEA70,0xEA6E, 0, 0,
+ 0, 0,0xC0F8,0xED74, 0, 0,0xC0F7,0xED77,
+0xED75,0xED76, 0, 0,0xC0F9, 0, 0, 0,
+0xF04D, 0,0xC2A1,0xF04E, 0, 0,0xC27D,0xF04F,
+0xC27E,0xF04C,0xF050, 0,0xF04A, 0, 0,0xC3A7,
+0xF278,0xC3A8,0xC46F, 0,0xF04B,0xC470, 0, 0,
+ 0,0xC4EE,0xF5DF, 0,0xC57E,0xF6F4,0xC57D, 0,
+0xF7EA,0xC5F5,0xC5F6, 0, 0,0xF9CC, 0, 0,
+0xACD1,0xCFDE, 0,0xB56E,0xB56F,0xA5D5,0xA6CA,0xCA47,
+ 0,0xCB71,0xA86D, 0,0xAABA, 0,0xACD2,0xACD3,
+0xACD4,0xD6A6,0xD2CB,0xAF6F, 0, 0,0xB2AE,0xD6A5,
+ 0, 0,0xDAB8,0xB571, 0,0xDAB7,0xB570, 0,
+ 0,0xDED5,0xBD4A,0xE6BB,0xE6B8,0xE6B9,0xE6BA, 0,
+ 0, 0, 0, 0,0xED78, 0,0xF051, 0,
+ 0, 0,0xF471,0xF470, 0,0xF6F5,0xA5D6,0xCD75,
+0xAF70, 0, 0, 0,0xB572,0xDED6, 0, 0,
+0xE2E1, 0,0xBD4B,0xEA74, 0,0xF052,0xF472,0xA5D7,
+ 0, 0,0xAABB,0xACD7,0xCFDF,0xACD8,0xACD6, 0,
+0xACD5,0xD2CC,0xAF71, 0, 0,0xAF72,0xAF73, 0,
+ 0, 0,0xB2B0,0xD6A7,0xB2AF, 0, 0, 0,
+ 0, 0,0xDAB9,0xB2B1,0xB573,0xDED7,0xB7F8,0xB7F9,
+ 0,0xBAC9, 0,0xBACA,0xBD4C,0xBF64,0xEA75,0xBF63,
+ 0,0xED79,0xC0FA, 0,0xF053,0xF473,0xA5D8,0xA86E,
+0xCD78,0xCD77,0xAABC,0xCD76,0xAABD,0xCD79, 0,0xCFE5,
+0xACDB,0xACDA,0xCFE7,0xCFE6,0xACDF, 0,0xACDE, 0,
+ 0,0xACD9, 0,0xCFE1,0xCFE2,0xCFE3, 0,0xACE0,
+0xCFE0,0xACDC,0xCFE4,0xACDD, 0, 0, 0, 0,
+0xD2CF,0xD2D3,0xD2D1,0xD2D0, 0,0xD2D4, 0, 0,
+ 0,0xD2D5,0xD2D6,0xD2CE, 0,0xD2CD, 0,0xAF75,
+0xAF76, 0,0xD2D7,0xD2D2, 0,0xD6B0, 0,0xD2D8,
+0xAF77,0xAF74, 0, 0, 0,0xD6AA, 0,0xD6A9,
+ 0,0xD6AB,0xD6AC,0xD6AE,0xD6AD,0xD6B2,0xB2B5,0xB2B2,
+0xB2B6,0xD6A8,0xB2B7,0xD6B1,0xB2B4,0xD6AF,0xB2B3, 0,
+ 0, 0, 0, 0,0xDABC,0xDABE,0xDABA,0xDABB,
+ 0, 0,0xDABF,0xDAC1,0xDAC2,0xDABD,0xDAC0,0xB574,
+ 0, 0,0xDEDB, 0,0xDEE0,0xDED8,0xDEDC, 0,
+ 0,0xDEE1,0xDEDD,0xB7FA,0xB843, 0,0xB7FD,0xDED9,
+0xDEDA,0xBACE,0xB846,0xB7FE, 0,0xB844,0xB7FC,0xDEDF,
+0xB845,0xDEDE,0xB841,0xB7FB,0xB842,0xDEE2,0xE2E6,0xE2E8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB840, 0, 0,0xE2E3,0xBACC,0xE2E9,0xBACD,
+0xE2E7,0xE2E2,0xE2E5,0xE2EA,0xBACB,0xE2E4, 0,0xBD4E,
+0xE6BF,0xE6BE, 0,0xBD51,0xBD4F,0xE6BC,0xBD4D,0xE6BD,
+ 0,0xBD50, 0, 0, 0,0xEA7D, 0,0xEAA1,
+ 0,0xEA7E,0xEA76,0xEA7A,0xEA79,0xEA77,0xBF66,0xBF67,
+0xBF65,0xEA78,0xEA7B,0xEA7C, 0,0xBF68, 0,0xC140,
+0xEDA3, 0,0xC0FC,0xED7B,0xC0FE,0xC141, 0, 0,
+0xC0FD,0xEDA2,0xED7C,0xC0FB,0xEDA1,0xED7A,0xED7E,0xED7D,
+ 0, 0,0xF055,0xC2A4,0xC2A5,0xC2A2, 0,0xC2A3,
+ 0, 0,0xF054, 0,0xF27B, 0, 0,0xC3A9,
+ 0,0xF279,0xF27A, 0,0xF474,0xF477,0xF475,0xF476,
+0xF5E0, 0, 0,0xC4EF,0xF7EB,0xF8B4, 0,0xC5F7,
+0xF8F8,0xF8F9,0xC666,0xA5D9,0xACE1, 0,0xDAC3, 0,
+0xDEE3, 0,0xA5DA,0xA86F, 0,0xAABE, 0,0xCFE8,
+0xCFE9,0xAF78, 0, 0,0xDAC4,0xB575,0xB847,0xC142,
+0xEDA4,0xF27C,0xF478,0xA5DB, 0, 0, 0,0xCDA1,
+0xCD7A,0xCD7C,0xCD7E,0xCD7D,0xCD7B,0xAABF, 0, 0,
+ 0, 0,0xACE2,0xCFF2, 0,0xCFED,0xCFEA, 0,
+ 0,0xCFF1, 0, 0,0xACE4,0xACE5,0xCFF0,0xCFEF,
+0xCFEE,0xCFEB,0xCFEC,0xCFF3,0xACE3, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xAF7C, 0,0xAFA4,
+0xAFA3,0xD2E1,0xD2DB,0xD2D9, 0,0xAFA1,0xD6B9,0xAF7A,
+0xD2DE,0xD2E2,0xD2E4,0xD2E0,0xD2DA,0xAFA2,0xD2DF,0xD2DD,
+0xAF79,0xD2E5,0xAFA5,0xD2E3,0xAF7D,0xD2DC, 0,0xAF7E,
+0xAF7B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xB2B9, 0,0xD6BA, 0, 0,
+0xD6B3,0xD6B5,0xD6B7, 0,0xD6B8,0xD6B6,0xB2BA, 0,
+0xD6BB, 0,0xD6B4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDAC8,0xB576,0xDAD0, 0,
+0xDAC5, 0,0xDAD1, 0,0xDAC6,0xDAC7, 0, 0,
+0xDACF,0xDACE,0xDACB,0xB2B8,0xB577,0xDAC9,0xDACC,0xB578,
+0xDACD,0xDACA, 0, 0, 0, 0, 0, 0,
+ 0,0xDEEE, 0,0xDEF2,0xB84E, 0,0xE2F0,0xB851,
+0xDEF0, 0, 0,0xDEED,0xDEE8,0xDEEA,0xDEEB,0xDEE4,
+ 0,0xB84D, 0, 0,0xB84C, 0,0xB848,0xDEE7,
+ 0,0xB84F, 0,0xB850,0xDEE6,0xDEE9,0xDEF1,0xB84A,
+0xB84B,0xDEEF,0xDEE5, 0, 0, 0,0xE2F2,0xBAD0,
+0xE2F4,0xDEEC,0xE2F6,0xBAD4,0xE2F7,0xE2F3, 0,0xBAD1,
+0xE2EF,0xBAD3,0xE2EC,0xE2F1,0xE2F5,0xE2EE, 0, 0,
+0xB849, 0,0xE2EB,0xBAD2,0xE2ED, 0, 0, 0,
+ 0, 0,0xBD54,0xE6C1,0xBD58, 0,0xBD56, 0,
+ 0,0xBACF, 0,0xE6C8,0xE6C9,0xBD53, 0, 0,
+0xE6C7,0xE6CA,0xBD55,0xBD52,0xE6C3,0xE6C0,0xE6C5,0xE6C2,
+0xBD59,0xE6C4, 0, 0,0xE6C6,0xBD57, 0, 0,
+ 0, 0,0xBF6A,0xEAA8, 0,0xEAA2,0xEAA6,0xEAAC,
+0xEAAD,0xEAA9,0xEAAA,0xEAA7, 0,0xEAA4, 0,0xBF6C,
+0xBF69,0xEAA3,0xEAA5, 0,0xBF6B,0xEAAB, 0,0xC146,
+ 0, 0,0xEDAA,0xEDA5,0xC145, 0, 0,0xC143,
+ 0,0xEDAC,0xC144,0xEDA8,0xEDA9,0xEDA6,0xEDAD,0xF056,
+ 0,0xC147,0xEDA7, 0,0xEDAE,0xEDAB, 0, 0,
+ 0,0xF05A, 0, 0,0xF057, 0,0xC2A6, 0,
+0xF05B,0xF05D,0xF05C,0xF058,0xF059, 0, 0,0xF2A3,
+ 0,0xC3AA, 0,0xF27E,0xF2A2,0xF27D,0xF2A4, 0,
+ 0,0xF2A1, 0,0xF47A,0xF47D,0xF479,0xC471,0xF47B,
+0xF47C,0xF47E,0xC472,0xC474,0xC473,0xF5E1, 0,0xF5E3,
+ 0,0xF5E2, 0, 0, 0,0xF6F6, 0, 0,
+0xF8B5,0xF8FA,0xA5DC, 0, 0,0xCB72,0xAAC0,0xCDA3,
+0xAAC1,0xAAC2,0xCDA2, 0,0xCFF8,0xCFF7,0xACE6,0xACE9,
+0xACE8,0xACE7,0xCFF4,0xCFF6,0xCFF5, 0, 0,0xD2E8,
+0xAFA7,0xD2EC,0xD2EB,0xD2EA,0xD2E6,0xAFA6,0xAFAA,0xAFAD,
+ 0, 0,0xAFAE,0xD2E7,0xD2E9,0xAFAC,0xAFAB,0xAFA9,
+0xAFA8,0xD6C2, 0,0xD6C0,0xD6BC,0xB2BB, 0,0xD6BD,
+0xB2BC,0xD6BE,0xD6BF,0xD6C1, 0,0xB2BD, 0, 0,
+0xDAD5, 0,0xDAD4,0xDAD3,0xDAD2, 0, 0, 0,
+ 0,0xDEF6,0xB852, 0,0xDEF3,0xDEF5, 0,0xB853,
+ 0,0xB854,0xDEF4, 0, 0, 0, 0, 0,
+0xE341, 0,0xE2F9,0xE2FA, 0,0xBAD7,0xBAD5,0xBAD6,
+0xE343, 0,0xE342,0xE2FE,0xE2FD,0xE2FC,0xE2FB,0xE340,
+0xE2F8, 0,0xE6CB,0xE6D0,0xE6CE, 0, 0, 0,
+0xE6CD,0xE6CC,0xE6CF, 0,0xEAAE, 0,0xBF6D,0xC148,
+0xEDB0, 0,0xC149,0xEDAF,0xF05F,0xF05E,0xC2A7, 0,
+0xF2A5,0xC3AB,0xF4A1,0xC5A1,0xF6F7, 0,0xF8B7,0xF8B6,
+0xC9A8,0xACEA,0xACEB,0xD6C3, 0,0xB856,0xA5DD,0xA872,
+0xA871,0xA870, 0, 0, 0,0xCDA4, 0, 0,
+0xAAC4,0xAAC3, 0,0xACEE, 0,0xCFFA,0xCFFD,0xCFFB,
+ 0,0xACEC,0xACED, 0, 0,0xCFF9,0xCFFC, 0,
+0xAFB5, 0, 0, 0,0xD2F3,0xD2F5,0xD2F4,0xAFB2,
+0xD2EF, 0, 0,0xAFB0,0xAFAF, 0,0xAFB3,0xAFB1,
+ 0,0xAFB4,0xD2F2,0xD2ED,0xD2EE,0xD2F1,0xD2F0, 0,
+ 0, 0, 0, 0, 0, 0,0xD6C6,0xD6C7,
+0xD6C5, 0,0xD6C4,0xB2BE, 0, 0, 0, 0,
+0xB57D, 0,0xDAD6,0xDAD8,0xDADA,0xB57C, 0, 0,
+0xB57A, 0,0xDAD7,0xB57B,0xDAD9,0xB579, 0, 0,
+0xDF41,0xDEF7,0xDEFA,0xDEFE,0xB85A,0xDEFC, 0,0xDEFB,
+0xDEF8,0xDEF9,0xB858,0xDF40,0xB857, 0,0xB85C,0xB85B,
+0xB859, 0,0xDEFD, 0, 0, 0,0xE349, 0,
+0xE348, 0, 0,0xE344, 0, 0,0xBAD8,0xE347,
+0xE346,0xBAD9, 0, 0, 0, 0, 0,0xBD5E,
+ 0,0xE6D2, 0,0xBD5F,0xBD5B,0xBD5D, 0,0xBD5A,
+0xBD5C, 0, 0, 0,0xEAAF, 0,0xBF70,0xEAB1,
+0xEAB0, 0,0xE345,0xBF72,0xBF71,0xBF6E,0xBF6F, 0,
+ 0, 0, 0, 0,0xEDB5, 0,0xEDB3,0xC14A,
+0xEDB4, 0,0xEDB6,0xEDB2,0xEDB1, 0, 0,0xF060,
+0xC2AA,0xC2A8,0xC2A9, 0, 0, 0, 0,0xF2A6,
+0xF2A7,0xC3AD, 0,0xC3AC,0xF4A3,0xF4A4,0xF4A2, 0,
+0xF6F8,0xF6F9, 0, 0,0xA5DE,0xCA48,0xA873, 0,
+0xCDA5,0xAAC6,0xAAC5,0xCDA6, 0, 0,0xD040,0xACEF,
+0xCFFE,0xACF0, 0, 0,0xAFB6,0xD2F8,0xD2F6,0xD2FC,
+0xAFB7,0xD2F7,0xD2FB,0xD2F9,0xD2FA, 0, 0,0xD6C8,
+0xD6CA, 0,0xB2BF, 0,0xD6C9,0xB2C0,0xB5A2,0xB5A1,
+0xB57E,0xDADB, 0, 0, 0, 0,0xDF44,0xB85D,
+0xB85E, 0,0xDF43,0xDF42, 0, 0, 0, 0,
+0xE34A,0xBADB,0xBADA,0xE34B,0xE34C, 0,0xBD61,0xBD60,
+ 0,0xEAB5,0xE6D3,0xE6D5,0xE6D4,0xEAB4,0xEAB2,0xEAB6,
+0xEAB3, 0,0xBF73, 0, 0, 0,0xEDB7,0xC14B,
+0xEDB8,0xEDB9, 0, 0,0xC2AB,0xC2AC, 0,0xC475,
+ 0, 0,0xC5D1,0xA5DF, 0, 0, 0, 0,
+ 0,0xD041, 0, 0, 0, 0, 0, 0,
+0xD2FD,0xAFB8, 0, 0, 0, 0, 0,0xB3BA,
+0xB3B9, 0, 0,0xB5A4,0xDADD,0xB5A3,0xDADC, 0,
+ 0, 0, 0,0xDF45, 0,0xBADC,0xE34D,0xBADD,
+ 0, 0, 0, 0, 0, 0,0xC476,0xF4A5,
+ 0,0xA6CB,0xAAC7,0xCDA7, 0,0xACF2, 0,0xACF1,
+0xD042,0xD043, 0, 0,0xD340,0xD342,0xAFB9, 0,
+0xD344,0xD347,0xD345, 0, 0, 0,0xD346,0xD343,
+0xD2FE,0xAFBA,0xD348,0xD341, 0, 0, 0, 0,
+0xD6D3,0xB2C6,0xD6DC,0xB2C3, 0,0xD6D5,0xB2C7, 0,
+0xB2C1, 0,0xD6D0,0xD6DD,0xD6D1,0xD6CE,0xB2C5, 0,
+0xB2C2, 0,0xD6D4,0xD6D7,0xB2C4,0xD6D8,0xB2C8,0xD6D9,
+0xD6CF,0xD6D6,0xD6DA,0xD6D2,0xD6CD,0xD6CB, 0, 0,
+0xD6DB, 0, 0,0xDADF, 0, 0, 0, 0,
+0xDAE4, 0, 0, 0,0xDAE0,0xDAE6,0xB5A7,0xD6CC,
+0xDAE1,0xB5A5,0xDADE,0xB5AC,0xDAE2,0xB5AB,0xDAE3,0xB5AD,
+0xB5A8,0xB5AE,0xB5A9, 0,0xB5AA, 0,0xB5A6, 0,
+0xDAE5, 0, 0, 0, 0, 0, 0, 0,
+0xB861,0xDF50, 0,0xDF53,0xDF47,0xDF4C,0xDF46,0xB863,
+ 0,0xDF4A, 0, 0, 0,0xDF48,0xB862, 0,
+0xDF4F,0xDF4E,0xDF4B,0xDF4D,0xDF49,0xBAE1,0xDF52,0xB85F,
+0xDF51, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE35D, 0,0xBAE8,0xE358, 0,0xBAE7,
+0xE34E, 0,0xE350,0xBAE0,0xE355,0xE354,0xE357,0xBAE5,
+0xE352,0xE351, 0, 0,0xBAE4,0xBADF,0xE353,0xBAE2,
+0xE359,0xE35B, 0,0xE356,0xE34F,0xBAE3, 0, 0,
+0xBD69,0xBADE, 0, 0,0xE35C, 0, 0, 0,
+ 0, 0, 0, 0,0xE6D9,0xBD62, 0,0xE6DB,
+ 0,0xBD63, 0, 0,0xBD65,0xE6DE, 0,0xE6D6,
+0xBAE6,0xE6DC, 0, 0, 0, 0,0xE6D8, 0,
+0xB860,0xBD68, 0, 0,0xBD64, 0,0xBD66,0xBD67,
+ 0,0xBF76,0xE6DD,0xE6D7,0xBD6A, 0,0xE6DA, 0,
+ 0, 0, 0, 0,0xEAC0,0xEABB, 0, 0,
+0xEAC5,0xBF74,0xEABD,0xBF78,0xEAC3,0xEABA,0xEAB7,0xEAC6,
+0xC151,0xBF79,0xEAC2,0xEAB8,0xBF77,0xEABC,0xBF7B,0xEAB9,
+0xEABE,0xBF7A,0xEAC1,0xEAC4, 0, 0, 0, 0,
+0xEDCB,0xEDCC,0xEDBC,0xEDC3,0xEDC1, 0, 0,0xC14F,
+0xEDC8,0xEABF, 0,0xEDBF, 0,0xEDC9,0xC14E,0xEDBE,
+0xEDBD,0xEDC7,0xEDC4,0xEDC6, 0,0xEDBA,0xEDCA,0xC14C,
+ 0,0xEDC5,0xEDCE,0xEDC2,0xC150,0xC14D,0xEDC0,0xEDBB,
+0xEDCD,0xBF75, 0, 0, 0, 0, 0, 0,
+ 0,0xF063, 0, 0,0xF061,0xF067,0xC2B0,0xF065,
+0xF064,0xC2B2,0xF06A,0xC2B1, 0,0xF06B,0xF068,0xC2AE,
+0xF069,0xF062,0xC2AF,0xC2AD,0xF2AB,0xF066, 0, 0,
+0xF06C, 0, 0,0xF2A8, 0, 0, 0,0xC3B2,
+0xC3B0,0xF2AA, 0,0xF2AC,0xF2A9,0xC3B1,0xC3AE,0xC3AF,
+0xC3B3, 0, 0,0xC478, 0,0xF4AA, 0,0xF4A9,
+0xF4A7,0xF4A6,0xF4A8, 0,0xC477,0xC479, 0, 0,
+0xC4F0, 0, 0,0xF5E5,0xF5E4, 0, 0,0xF6FA,
+ 0,0xF6FC,0xF6FE,0xF6FD,0xF6FB, 0, 0,0xC5A3,
+0xC5A2, 0, 0,0xC5D3,0xC5D2,0xC5D4,0xF7ED,0xF7EC,
+ 0,0xF8FB,0xF8B8,0xF8FC,0xC658, 0,0xC659,0xF96D,
+ 0, 0,0xC67E,0xA6CC, 0,0xCDA8, 0, 0,
+0xD045,0xD046,0xD044, 0, 0,0xACF3, 0,0xD047,
+0xD048,0xD049, 0, 0,0xD349,0xD34F, 0, 0,
+0xD34D,0xAFBB,0xD34B, 0,0xD34C,0xD34E, 0, 0,
+ 0,0xD34A,0xB2C9, 0,0xD6DE,0xB2CB,0xD6E0,0xB2CA,
+0xD6DF, 0, 0, 0, 0, 0,0xDAE8,0xB5AF,
+ 0,0xDAEA,0xDAE7,0xD6E1, 0,0xB5B0, 0, 0,
+0xDAE9, 0, 0, 0, 0, 0, 0,0xDF56,
+ 0,0xB864,0xDF54,0xB865,0xDF55,0xB866, 0, 0,
+ 0,0xBAE9,0xE361,0xE35E,0xE360,0xBAEA,0xBAEB,0xE35F,
+ 0, 0, 0, 0, 0,0xE6DF, 0, 0,
+0xE6E0, 0,0xBD6B,0xE6E2,0xE6E1, 0,0xA261, 0,
+0xEACA,0xEACB,0xEAC7, 0,0xEAC8,0xBF7C,0xBF7D,0xEAC9,
+ 0,0xC157, 0, 0,0xC153,0xC158,0xC154,0xC156,
+0xC152, 0,0xC155, 0, 0, 0, 0,0xC2B3,
+0xEDCF, 0,0xF2AE, 0,0xF2AD, 0,0xF4AB,0xC47A,
+0xC47B,0xF741,0xF5E6, 0,0xF740, 0,0xF8FD,0xF9A4,
+0xA6CD, 0, 0,0xA874, 0,0xCDA9,0xAAC8, 0,
+0xACF6,0xD04C,0xACF4,0xD04A,0xACF9,0xACF5,0xACFA,0xACF8,
+0xD04B,0xACF7,0xAFBF,0xAFBE,0xD35A,0xAFC7,0xD353,0xD359,
+0xAFC3,0xD352,0xD358,0xD356,0xAFC2,0xAFC4,0xD355,0xAFBD,
+0xD354,0xAFC8,0xAFC5,0xAFC9,0xAFC6,0xD351,0xD350,0xD357,
+0xAFC0,0xAFBC,0xAFC1, 0, 0, 0, 0, 0,
+0xD6F0,0xD6E9, 0,0xB5B5,0xD6E8, 0,0xB2CF,0xB2D6,
+0xB2D3,0xB2D9,0xB2D8,0xB2D4, 0,0xD6E2,0xD6E5, 0,
+0xD6E4,0xB2D0,0xD6E6,0xD6EF,0xB2D1,0xD6E3,0xD6EC,0xD6ED,
+0xB2D2,0xD6EA,0xB2D7,0xB2CD,0xB2D5,0xD6E7,0xB2CC,0xD6EB,
+ 0, 0,0xD6EE, 0, 0, 0,0xDAFB,0xDAF2,
+0xB5B2,0xDAF9,0xDAF6,0xDAEE,0xDAF7,0xB5B4,0xDAEF, 0,
+0xDAEB, 0, 0,0xB86C,0xDAF4, 0,0xB5B1,0xDAFA,
+ 0,0xB5B8,0xB5BA,0xDAED, 0, 0,0xB5B9,0xDAF0,
+0xB5B3,0xDAF8,0xDAF1,0xDAF5, 0,0xDAF3,0xB5B6,0xDAEC,
+0xB5BB,0xB2CE,0xB5B7,0xB5BC, 0, 0, 0, 0,
+ 0,0xB868,0xDF5D,0xDF5F,0xDF61,0xDF65, 0,0xDF5B,
+0xDF59,0xB86A, 0,0xDF60,0xDF64,0xDF5C,0xDF58, 0,
+0xDF57, 0, 0, 0,0xDF62,0xDF5A,0xDF5E,0xB86B,
+ 0,0xB869,0xDF66,0xB867,0xDF63, 0,0xE372, 0,
+ 0, 0, 0, 0,0xBAEE,0xE36A,0xBD78,0xE374,
+0xBAF1,0xE378,0xBAF7,0xE365, 0, 0,0xE375,0xE362,
+ 0,0xE377,0xE366, 0,0xBAFE,0xBAFB,0xE376,0xE370,
+0xBAED,0xBAF5,0xBAF4, 0,0xBAF3,0xBAF9, 0,0xE363,
+0xBAFA,0xE371,0xBAF6,0xBAEC,0xE373,0xBAEF,0xBAF0,0xBAF8,
+0xE368,0xE367,0xE364, 0,0xE36C,0xE369,0xE36D,0xBAFD,
+ 0,0xE379,0xBAF2,0xE36E,0xE36F, 0,0xE36B, 0,
+ 0, 0,0xBAFC, 0, 0, 0, 0,0xE6E7,
+0xBD70,0xBD79,0xBD75,0xE6E4, 0,0xBD72,0xBD76,0xE6F0,
+0xBD6C,0xE6E8, 0,0xBD74, 0, 0,0xE6EB,0xE6E6,
+0xBD73,0xBD77,0xE6E5, 0,0xBD71, 0,0xE6EF,0xBD6E,
+0xE6EE,0xE6ED,0xBD7A,0xE572,0xBD6D, 0,0xE6EC,0xE6E3,
+ 0,0xBD7B,0xE6EA,0xBD6F, 0, 0, 0, 0,
+ 0, 0, 0,0xE6E9, 0, 0, 0, 0,
+0xBFA2,0xBFA7,0xBF7E,0xEAD8,0xEACF,0xEADB,0xEAD3,0xEAD9,
+0xBFA8,0xBFA1,0xEACC,0xEAD2,0xEADC,0xEAD5,0xEADA,0xEACE,
+ 0, 0,0xEAD6,0xBFA3,0xEAD4,0xBFA6,0xBFA5,0xEAD0,
+0xEAD1,0xEACD,0xEAD7,0xBFA4,0xEADE,0xEADD, 0, 0,
+ 0,0xEDDA,0xEDD6,0xC15F, 0,0xEDD0,0xC159,0xC169,
+0xEDDC,0xC161,0xC15D,0xEDD3,0xC164,0xC167,0xEDDE,0xC15C,
+0xEDD5,0xC165,0xEDE0,0xEDDD,0xEDD1,0xC160,0xC15A,0xC168,
+0xEDD8,0xC163,0xEDD2,0xC15E,0xEDDF,0xC162,0xC15B,0xEDD9,
+0xC166,0xEDD7, 0, 0,0xEDDB, 0, 0, 0,
+0xF06E,0xF074,0xC2B9,0xF077,0xC2B4,0xC2B5,0xF06F,0xF076,
+0xF071,0xC2BA,0xC2B7, 0,0xF06D, 0,0xC2B6,0xF073,
+0xF075,0xC2B8,0xF072,0xF070, 0, 0, 0, 0,
+0xF2B8,0xC3B7,0xC3B8,0xC3B4, 0,0xC3B5, 0,0xF2B4,
+0xF2B2, 0,0xF2B6,0xC3BA,0xF2B7,0xF2B0,0xF2AF,0xF2B3,
+0xF2B1,0xC3B6,0xF2B5,0xF4AC,0xC47E,0xC47D,0xF4AD, 0,
+0xF4AF,0xF4AE,0xC4A1, 0, 0, 0,0xF5EB,0xF5E8,
+0xF5E9, 0,0xF5E7,0xF5EA,0xC4F2,0xF5EC, 0,0xC4F1,
+ 0,0xF742, 0,0xC5D5,0xC5D7,0xF7EE,0xC5D6,0xF8B9,
+0xF940,0xF942,0xF8FE,0xF941,0xC66C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA6CE, 0,
+0xACFB,0xD26F,0xAFCA, 0, 0,0xB2DA,0xDAFC,0xDAFD,
+ 0, 0, 0,0xEADF,0xC16A,0xEDE1, 0, 0,
+0xC2BB, 0,0xF2BA,0xF2B9,0xC4A2,0xF5ED, 0,0xF743,
+0xC5F8,0xCA49, 0, 0,0xAAC9,0xA875, 0, 0,
+0xD04D, 0, 0,0xD360,0xD35B,0xD35F,0xD35D,0xAFCB,
+0xD35E,0xD35C, 0,0xD6F1, 0,0xDAFE,0xDB40,0xDF69,
+0xDF6A,0xB86E,0xB86F,0xDF68,0xDF6B,0xDF67,0xB86D, 0,
+0xBB40, 0,0xB870,0xE37A, 0,0xBD7C,0xE6F1,0xBD7D,
+ 0,0xBFA9,0xEAE2,0xEAE0,0xEAE1,0xEDE4,0xEDE3,0xEDE2,
+ 0, 0, 0,0xF2BB, 0,0xC3B9,0xF2BC,0xF744,
+0xC5F9,0xF8BA,0xA6CF,0xAACB,0xAACA,0xD04F,0xACFC, 0,
+ 0,0xD04E,0xD362, 0,0xAFCC,0xD6F2,0xD361, 0,
+ 0, 0,0xB2DC,0xD6F5,0xD6F3,0xD6F4,0xB2DB, 0,
+0xDB42,0xDB43,0xDB41, 0,0xB873,0xDF6D,0xDF6C,0xDF6E,
+0xB872,0xB871, 0, 0,0xE6F2,0xE6F4, 0,0xBD7E,
+0xE6F3,0xEAE3,0xBFAA,0xF079, 0,0xF078,0xC3BB,0xF2BD,
+0xC3BD,0xC3BC,0xF4B0,0xF5EE,0xC4F3,0xA6D0,0xD050,0xACFD,
+0xD365,0xAFCE,0xD364,0xD363, 0,0xAFCD, 0,0xD6FB,
+ 0,0xD6FD,0xD6F6,0xD6F7,0xB2DD,0xD6F8,0xB2DE,0xD6FC,
+0xD6F9,0xD6FA,0xB2DF, 0,0xB5BE,0xB5BF, 0,0xDB44,
+ 0, 0, 0,0xDF6F,0xDF70, 0,0xE37E,0xBB43,
+0xBB41,0xBB42,0xE37B,0xE37C, 0,0xE37D,0xE6F9, 0,
+0xE6FA,0xBDA1,0xE6F7,0xE6F6,0xE6F8,0xE6F5,0xBFAD,0xEAE4,
+0xBFAB,0xBFAC,0xEDE6,0xC16B,0xEDE5,0xEFA8, 0,0xF07A,
+0xF07B,0xC2BC, 0,0xC2BD,0xC16C,0xF2BE,0xF2BF,0xF4B1,
+0xC4A3,0xA6D1, 0,0xA6D2,0xACFE,0xAACC,0xAFCF,0xD051,
+ 0, 0, 0,0xB5C0,0xA6D3,0xAD41,0xD052,0xD053,
+0xAD40,0xAD42,0xA6D4, 0,0xD054,0xAFD1,0xD366,0xAFD3,
+0xAFD0,0xAFD2, 0,0xD741,0xB2E0, 0,0xD740,0xD6FE,
+ 0,0xDF71, 0, 0,0xE3A1, 0,0xBDA2, 0,
+0xBFAE,0xEAE6,0xEAE5, 0,0xEDE7, 0, 0, 0,
+0xF5EF, 0, 0,0xA6D5,0xCB73,0xCDAA,0xAD43,0xD055,
+ 0,0xD368, 0, 0, 0,0xAFD4,0xD367,0xAFD5,
+ 0, 0, 0,0xD743, 0, 0,0xB2E2,0xD742,
+0xD744, 0,0xB2E1, 0, 0, 0, 0,0xDB46,
+0xDB47,0xDB45,0xB5C1, 0, 0, 0,0xB874, 0,
+0xB875, 0,0xBB45, 0,0xE3A3,0xE3A2,0xBB44, 0,
+ 0, 0, 0, 0,0xE6FB, 0, 0,0xE6FC,
+ 0, 0, 0, 0,0xEAE7, 0, 0,0xC170,
+0xC16F,0xC16D,0xC16E,0xC171, 0,0xF07C,0xC2BF,0xC2BE,
+0xF2C0,0xF4B2, 0, 0, 0,0xC5A5,0xC5A4,0xA6D6,
+ 0, 0,0xD1FB, 0,0xB877,0xB5C2,0xB876,0xBB46,
+ 0,0xA6D7,0xC9A9,0xA6D8,0xA6D9, 0, 0,0xCDAB,
+0xCB76, 0,0xCB77,0xA877, 0,0xCB74,0xA876, 0,
+0xA879,0xCB75,0xA87B,0xA87A,0xCB78,0xA878, 0, 0,
+ 0,0xAAD1,0xAACF,0xCDAD, 0,0xAACE, 0, 0,
+ 0,0xAAD3,0xAAD5,0xAAD2, 0,0xCDB0,0xCDAC,0xAAD6,
+ 0,0xAAD0,0xA87C, 0,0xAAD4,0xCDAF, 0, 0,
+0xCDAE, 0,0xAACD, 0, 0, 0, 0, 0,
+ 0, 0,0xD05B,0xAD47,0xAD48,0xD05D, 0,0xD057,
+0xD05A,0xD063,0xD061, 0,0xAD49,0xD067,0xAD4C,0xD064,
+0xD05C,0xD059, 0, 0,0xDB49,0xD062,0xAD44,0xD065,
+0xD056,0xD05F,0xAD46,0xAD4B,0xD060,0xAD4F,0xAD4D, 0,
+0xD058,0xAD4A, 0,0xD05E,0xAD4E,0xAD45,0xD066, 0,
+ 0, 0, 0, 0, 0,0xAFDA, 0,0xAFE3,
+0xAFD8,0xAFD6,0xD36A,0xAFDE,0xAFDB,0xD36C, 0, 0,
+0xAFDD,0xD36B,0xD369,0xD36E,0xAFE2,0xAFE0,0xDB48, 0,
+0xD36F,0xD36D,0xAFD7, 0, 0,0xAFD9,0xAFDC, 0,
+0xAFDF, 0,0xAFE1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD74E,0xB2E4, 0,
+0xD745,0xD747, 0,0xD748, 0,0xD750,0xD74C,0xD74A,
+ 0,0xD74D,0xD751,0xB2E5,0xB2E9,0xD746, 0,0xD74F,
+ 0,0xB2E7, 0,0xB2E6,0xD74B,0xD749, 0,0xB2E3,
+0xB2E8, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB5C8,0xDB51, 0, 0,0xDB4F,0xB5CA, 0,
+ 0, 0, 0,0xDB4A,0xDFA1, 0,0xB5C9,0xDB4E,
+ 0, 0,0xDB4B,0xB5C5,0xB5CB,0xDB50,0xB5C7,0xDB4D,
+0xBB47,0xB5C6,0xDB4C,0xB5CC,0xB5C4,0xB5C3, 0, 0,
+ 0, 0, 0,0xDF77,0xDF75, 0,0xDF7B, 0,
+0xDF73,0xDFA2,0xDF78, 0,0xDF72,0xB87B,0xB8A3,0xDF7D,
+ 0,0xDF76, 0,0xB87E, 0, 0,0xB87C,0xDF7E,
+0xB879,0xB878,0xDF79,0xB87D,0xB5CD, 0,0xDF7C,0xDF74,
+0xB87A,0xB8A1,0xB8A2, 0, 0, 0, 0,0xBB4C,
+0xBB48, 0,0xBB4D,0xE3A6, 0, 0,0xE3A5,0xE3A7,
+0xBB4A,0xE3A4,0xBB4B,0xE3AA,0xE3A9,0xE3A8, 0,0xBB49,
+ 0, 0, 0, 0, 0,0xE741, 0,0xE744,
+0xBDA8,0xE743,0xBDA7,0xBDA3,0xBDA4,0xBDA5,0xE740,0xE6FE,
+0xBDA6, 0,0xE742,0xE6FD, 0, 0,0xEAE9,0xEAF3,
+0xBFB1,0xBFB0, 0,0xEAED,0xEAEF, 0,0xEAEA, 0,
+0xEAEE,0xEAE8,0xEAF1,0xBFAF,0xEAF0,0xEAEC, 0,0xEAF2,
+ 0,0xEAEB,0xC174,0xEDE8,0xEDEE,0xC178,0xC17A,0xC177,
+0xC176, 0,0xC175,0xC173,0xEDE9,0xEDEC,0xC172,0xEDED,
+ 0,0xC179,0xEDEB, 0,0xEDEA,0xC2C0, 0,0xC2C1,
+0xF0A1,0xF07D,0xF07E, 0, 0,0xF2C2, 0,0xF2C1,
+0xC3BE,0xF4B4,0xC4A4,0xF4B3, 0,0xF5F0,0xF745,0xC5A6,
+0xF943,0xF944,0xC5D8,0xA6DA, 0,0xAAD7,0xDB52,0xBB4E,
+0xC17B,0xEDEF,0xA6DB, 0,0xAFE5,0xAFE4,0xDB53, 0,
+ 0, 0,0xEAF4,0xA6DC,0xAD50, 0, 0,0xDB54,
+0xDB55,0xDB56,0xBB4F,0xBFB2,0xA6DD, 0,0xAAD8,0xD068,
+0xAFE6,0xD370,0xB2EA, 0,0xDB57,0xB8A4, 0,0xBB50,
+0xBFB3,0xC17C,0xC2C2,0xF4B5,0xA6DE,0xAAD9, 0, 0,
+0xAFE7,0xD752,0xB5CE, 0,0xBB51,0xE3AB,0xE745, 0,
+ 0, 0, 0,0xA6DF,0xB5CF,0xDFA3,0xBB52,0xA6E0,
+0xCDB1,0xD069,0xAD51, 0, 0,0xD372, 0, 0,
+0xAFEA, 0,0xAFE8,0xAFE9,0xAFEB, 0, 0,0xD371,
+ 0, 0,0xD757,0xD754,0xD756,0xB2EB,0xB2ED,0xB2EC,
+0xD753,0xB2EE,0xD755, 0,0xDB58,0xDB59, 0,0xDB5A,
+0xDFA6, 0,0xDFA7, 0,0xDFA5,0xDFA8, 0,0xB8A5,
+ 0,0xDFA4, 0,0xBB53, 0, 0,0xE74A,0xE746,
+0xE749,0xE74B,0xE748,0xE747, 0,0xEAF5,0xEAF6,0xEAF7,
+0xBFB4,0xBFB5,0xEDF1,0xEDF0,0xEDF2, 0,0xF0A3,0xF0A2,
+ 0,0xF2C4, 0,0xF2C5,0xF2C3, 0,0xC4A5, 0,
+0xF4B6,0xF4B7, 0,0xF746,0xF7EF,0xF8BB,0xA6E1,0xA87D,
+ 0,0xC17D,0xA6E2, 0,0xD758,0xDB5B, 0,0xC641,
+0xCA4A, 0, 0, 0,0xCA4B,0xCA4D,0xA6E3,0xCA4E,
+0xCA4C, 0, 0,0xCBA2,0xCBA3,0xCB7B, 0, 0,
+ 0, 0,0xCBA1,0xA8A1, 0,0xA8A2,0xCB7C,0xCB7A,
+0xCB79,0xCB7D,0xA87E,0xCB7E,0xD06A, 0, 0, 0,
+0xCDB6,0xAADC,0xCDB5,0xCDB7, 0,0xAADB,0xCDBC,0xAADF,
+0xCDB2,0xCDC0,0xCDC6,0xAAE6,0xCDC3,0xAAE3, 0,0xCDB9,
+0xCDBF,0xCDC1, 0,0xCDB4,0xAAE2,0xAADD,0xCDBA,0xAAE4,
+0xAAE7,0xAAE1, 0,0xAADA,0xCDBE,0xCDB8,0xCDC5,0xAAE9,
+0xAAE5,0xAAE0,0xCDBD,0xAFEC,0xCDBB,0xAADE,0xAAE8, 0,
+0xCDB3, 0,0xCDC2,0xCDC4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xAD62,0xAD5C,0xAD64,0xAD61,0xD071,0xD074,0xAD5D,
+ 0,0xD06B, 0,0xAD56,0xAD60, 0,0xAD63,0xAD65,
+0xD0A2,0xD077, 0,0xAD55,0xD0A1,0xAD59,0xAD57,0xAD52,
+0xD06F, 0,0xD07E,0xD073,0xD076,0xD0A5, 0,0xAD66,
+0xD07D,0xAD5E,0xD078,0xD0A4,0xD075,0xD079,0xD07C, 0,
+ 0,0xD06D,0xD0A3,0xD07B, 0, 0,0xD06C, 0,
+0xD070,0xAD5F,0xAD5A,0xAD53,0xAD58,0xAD54,0xAD67,0xD06E,
+0xD3A5,0xAD5B, 0, 0,0xD07A,0xCE41, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD3A8,0xAFFA,
+ 0,0xD376, 0,0xD3A3,0xD37D, 0,0xD3B2, 0,
+0xD3AA, 0,0xD37E, 0,0xD3A9,0xD378,0xD37C,0xD3B5,
+0xAFFD,0xD3AD,0xD3A4,0xAFED,0xD3B3,0xD374, 0,0xD3AC,
+ 0,0xAFFC,0xAFF7,0xD373,0xAFF5,0xAFF4,0xAFF9,0xD3AB,
+0xAFF1,0xAFF8,0xD072,0xDB5C,0xD3A6, 0, 0,0xD37A,
+0xAFFB,0xD37B,0xD3A1,0xAFFE,0xD375,0xD3AF, 0,0xD3AE,
+0xD3B6,0xAFF3,0xAFF0,0xD3B4,0xD3B0,0xD3A7,0xD3A2,0xAFF6,
+0xAFF2,0xD377,0xAFEE,0xD3B1,0xAFEF, 0,0xD379, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD75E,0xD760,0xD765,0xD779,0xB2FC,
+0xB2F2, 0,0xD75D,0xB2FD,0xB2FE,0xD768,0xD76F,0xD775,
+ 0,0xD762, 0,0xD769, 0, 0,0xB340,0xD777,
+0xD772,0xB2FA,0xB2F8,0xD76E,0xD76A,0xD75C,0xB2EF,0xD761,
+0xD759, 0,0xB2F7,0xB2F9,0xD766,0xD763,0xB2F4,0xD773,
+0xB2F1,0xD764,0xD77A,0xD76C, 0,0xD76B,0xB2F0, 0,
+0xB2FB, 0,0xB2F3,0xD75A,0xD75F,0xD770,0xD776,0xB341,
+0xD75B,0xD767,0xD76D,0xB2F6, 0, 0,0xD778,0xD771,
+0xD774, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xB2F5, 0,0xDB6C,
+0xDB60,0xB5D7,0xDB7D,0xDBA7,0xDBAA,0xB5D5,0xDB68,0xDBA3,
+0xDB69,0xDB77,0xB5E2,0xDB73,0xB5DF, 0,0xDB74,0xDB5D,
+ 0,0xDBA4, 0, 0,0xB5E8,0xDBA1,0xDB75,0xDBAC,
+0xDB70,0xDFC8, 0,0xDBAF,0xB5E6,0xDB6E,0xDB7A,0xB5E9,
+0xB5D4,0xDB72,0xDBAD,0xDB6B,0xDB64,0xDB6F, 0,0xDB63,
+0xDB61,0xB5D0,0xDBA5,0xDB6A,0xDBA8, 0,0xDBA9,0xB5D8,
+0xB5DD,0xB5D9,0xB5E1,0xDB7E,0xB5DA,0xDB76,0xDB66, 0,
+0xB5D2,0xDB5E,0xDBA2,0xDBAB,0xDB65,0xB5E0,0xDBB0,0xDB71,
+ 0,0xDB6D, 0,0xB5D1,0xB5E5, 0,0xDB7C,0xB5E7,
+ 0,0xDB78,0xB5DC,0xB5D6,0xB5DE,0xB5D3,0xB5E4,0xDB79,
+0xDB67,0xDB7B,0xDB62,0xDBA6, 0, 0, 0, 0,
+ 0, 0, 0,0xDBAE, 0, 0, 0, 0,
+ 0, 0, 0,0xDB5F, 0, 0, 0, 0,
+ 0,0xDFC7, 0,0xDFDD,0xB855,0xDFCC, 0,0xDFCA,
+0xDFB5,0xB8A9,0xDFC5,0xDFD9,0xDFC1,0xB8B1,0xDFD8,0xDFBF,
+0xB5E3,0xDFCF,0xDFC0,0xDFD6,0xB8B0,0xB8A8, 0,0xDFAA,
+0xDFB2, 0,0xDFCB,0xDFC3,0xDFDC,0xDFC6,0xB8B6,0xDFD7,
+ 0,0xB8AD, 0,0xDFC9,0xDFD1,0xDFB6,0xDFD0, 0,
+0xDFE1,0xDFB1,0xDFD2, 0,0xDFDF, 0,0xDFAB,0xB5DB,
+ 0,0xDFB9,0xDFB8,0xB8AF, 0,0xDFBC,0xDFBE,0xDFCD,
+0xDFDE,0xB8B2, 0,0xB8B3, 0,0xDFB0,0xB8AB,0xDFB4,
+0xDFDA,0xB8B4, 0,0xB8AC,0xB8AE,0xB8B5,0xDFE0,0xDFD3,
+0xDFCE, 0, 0,0xDFBB,0xDFBA,0xB8AA,0xDFAC,0xB8A7,
+0xDFC4,0xDFAD,0xDFC2, 0, 0,0xDFB7,0xDFDB, 0,
+ 0, 0,0xB8A6, 0, 0, 0,0xDFB3, 0,
+ 0, 0, 0, 0, 0,0xDFAF,0xDFD5,0xDFAE,
+0xBB60,0xE3D3, 0, 0,0xE3C2, 0, 0,0xE3AC,
+0xE3CA,0xBB58,0xE3BB,0xE3C5,0xBB5B,0xE3BE,0xBB59,0xE3AF,
+0xE3CD,0xE3AE,0xE3C1, 0,0xE3AD, 0, 0,0xE3BF,
+0xE3C8,0xE3C6,0xE3BA,0xE3B5,0xE3B3, 0,0xE3B4,0xE3C7,
+0xE3D2,0xE3BC,0xBB5A, 0,0xE3B7, 0,0xE3CB, 0,
+0xBB5D,0xE3B6,0xE3B0,0xE3C0,0xBB61, 0, 0,0xBB55,
+0xBB5E,0xE3B8,0xE3B2, 0,0xBB57,0xDFD4,0xBB56,0xE3C3,
+ 0,0xBB54,0xBB63,0xBB5C,0xE3C4,0xE3B9,0xE3B1,0xE3CC,
+0xE3BD,0xBB62,0xE3D0,0xBB5F,0xE3CF, 0,0xE3C9,0xE3CE,
+ 0, 0, 0,0xE3D1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE773,
+0xE774,0xE767,0xE766,0xE762,0xBDB4, 0,0xBDAC,0xE776,
+0xE775,0xDFA9,0xE75F,0xE763,0xE75D, 0,0xE770,0xE761,
+ 0,0xE777,0xE75A,0xE758,0xE764,0xE76E,0xE769,0xBDB6,
+0xE74F, 0,0xE76D, 0, 0, 0,0xBDB7,0xDFBD,
+0xE75B,0xE752,0xE755,0xE77B,0xE75C,0xE753,0xE751,0xE74E,
+ 0,0xBDB0,0xE765,0xBDAF,0xBDB3,0xE760,0xE768,0xBDA9,
+0xE778,0xE77C,0xBDAB, 0,0xE757,0xE76B,0xE76F,0xE754,
+0xE779,0xBDB2, 0,0xBDB1,0xE74C,0xBDB5,0xE772,0xE756,
+0xE76A,0xE750,0xE75E,0xE759,0xBDAD,0xBDAE,0xE76C,0xE77D,
+0xE77A,0xE771, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE74D, 0,0xBDAA,0xEB49, 0,
+0xEB40,0xEB43, 0,0xBFBB,0xEB45,0xEAF9,0xEB41,0xEB47,
+0xBFB8,0xBFBC,0xBFB6, 0, 0,0xEAFB,0xEB4C, 0,
+ 0,0xEB46, 0,0xEAFC,0xEB55,0xEB4F,0xEAF8,0xEE46,
+0xEAFE,0xBFB7, 0,0xEB4A, 0,0xEB54,0xBFBF, 0,
+0xEB51,0xEAFD,0xEB44,0xEB48,0xEB42,0xEB56,0xEB53,0xEB50,
+0xBFB9,0xBFBA,0xBFBE,0xEAFA,0xEB57,0xBFBD,0xEB4D, 0,
+ 0,0xEB4B, 0, 0, 0,0xEB4E,0xEE53,0xEE40,
+0xEE45,0xEE52,0xEE44,0xEDFB,0xEE41, 0,0xC1A2, 0,
+0xEDF4,0xEE4D,0xEE4F,0xEDF3,0xC1A1,0xEE51,0xEE49,0xC1A8,
+0xEE50,0xEE42,0xC1AA,0xEDF9,0xEB52,0xEE4A,0xEE47,0xEDF5,
+0xEE55,0xC1A4, 0, 0,0xC1A5,0xEDF7,0xEE48, 0,
+0xEE54,0xEE4B,0xEDFD,0xC1A7,0xC1A3,0xEE4C,0xEDFE,0xEE56,
+0xEDF8,0xEE43,0xEE4E,0xEDFA,0xEDFC, 0,0xC2CB,0xEDF6,
+0xC1A9,0xC2C4,0xC17E, 0, 0, 0, 0,0xC1A6,
+0xC2C8,0xF0B3, 0,0xF0A9,0xF0A4,0xF0AA,0xF0B4,0xF0B8,
+0xF0B7,0xC2CA,0xC2C9, 0, 0,0xF0AB,0xF0B9,0xF0AE,
+0xF0A6, 0,0xF0A8,0xF0A7,0xF0AD,0xF0B2,0xF0A5,0xF0AC,
+0xF0B1,0xC2C7, 0,0xF0AF, 0,0xC2C5,0xF0B0,0xC2C3,
+0xC2C6,0xF2D5,0xF0B5, 0, 0,0xC3C2, 0,0xF2CD,
+0xF2D1,0xF2C9,0xF2CC, 0,0xF2D4,0xC3C0,0xF2D9,0xF2D2,
+ 0,0xF2CA,0xF2DA,0xF2D3,0xC3C3,0xC3C4,0xF2D7, 0,
+0xF2CB,0xC3BF,0xC3C1,0xF2C6,0xF2CE,0xF2C8, 0,0xF2D8,
+0xF2D6,0xF2C7,0xF2CF, 0, 0, 0,0xF4BE,0xC3C5,
+0xF2D0,0xC4A7,0xC4A9,0xC4A6, 0,0xF4C3,0xF4BB,0xF4B9,
+0xF4BD,0xF4BA, 0, 0,0xF4BF,0xF4C1,0xC4AA,0xC4AC,
+ 0,0xF4C0,0xC4AD,0xC4AB,0xF4C2, 0, 0, 0,
+ 0,0xC4A8, 0, 0, 0, 0, 0,0xC4F4,
+0xF5F1,0xF5F7,0xC4F6,0xF4BC,0xF5F6, 0,0xF5FD,0xF5F4,
+0xF5FB,0xF5FA,0xF4B8,0xF5F5,0xF0B6,0xF5FE,0xF5F3,0xF5F8,
+ 0,0xF5FC,0xF5F2, 0,0xF74A,0xC4F5,0xF5F9, 0,
+ 0,0xF7F4,0xF74B,0xF749,0xF747,0xF748,0xF74C, 0,
+0xC5D9,0xF7F2,0xF7F0,0xF7F5,0xF7F3, 0,0xF7F6,0xC5DA,
+0xF7F1, 0, 0,0xF8BC, 0, 0,0xF945,0xF946,
+0xF947, 0, 0,0xF9C7,0xF9BD,0xCA4F,0xAAEA, 0,
+0xAD68, 0,0xD3B8,0xD3B7,0xB040,0xB342,0xD77C, 0,
+ 0,0xD77B, 0,0xB5EA,0xB8B8, 0,0xB8B7,0xB8B9,
+ 0,0xE3D4,0xE77E,0xEB58,0xEB5A,0xEB59, 0,0xC1AB,
+0xEE57,0xF0BA,0xF9A5,0xA6E4, 0,0xCDC9,0xCDCA,0xCDC8,
+0xCDC7,0xAAEB, 0,0xD0A9,0xD0A7, 0, 0,0xD0A6,
+ 0,0xAD69,0xAD6B,0xAD6A,0xD0A8, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD3C4,0xD3C1,0xD3BF,
+ 0, 0,0xB041,0xD3C2,0xB046,0xD3BC,0xD3CB, 0,
+0xD3CD,0xD3BD, 0,0xB043,0xD3CE,0xD3C9,0xD3BB,0xD3C0,
+0xD3CA,0xD3C6,0xD3C3, 0,0xB048,0xD3CC,0xD3BE, 0,
+ 0,0xD3C7,0xD3B9,0xB047,0xB044,0xD3C5, 0,0xD3C8,
+0xD3BA,0xB045,0xB042, 0, 0, 0, 0,0xB34C,
+0xD7A5,0xB34B, 0,0xD7A8,0xD7AB,0xB348,0xB346,0xD77E,
+0xD7A9,0xD7A7,0xD7A4,0xD7AC,0xD7AD,0xD7AF,0xD7B0,0xD77D,
+0xB345,0xD7A2,0xD7A1,0xD7AE,0xB347,0xD7A3,0xB349,0xB344,
+0xD7A6,0xB34D, 0,0xB34A,0xD7AA, 0, 0, 0,
+0xB5F1,0xDBBF, 0,0xDBB4,0xB5EE, 0,0xDFE7,0xDBBD,
+0xDBB1,0xB5EC,0xDBB6,0xB5EF,0xDBBA,0xDBB8,0xB5F2,0xB5EB,
+ 0, 0,0xDBB2,0xDBB5,0xB5F0, 0,0xDBB3, 0,
+0xDBBE,0xDBBC,0xDBB7,0xDBB9,0xDBBB,0xB5ED, 0, 0,
+ 0, 0, 0, 0, 0,0xDFE8,0xDFEE,0xDFE4,
+0xDFEA,0xB8BA,0xDFE6,0xB8C0, 0, 0,0xB8BF, 0,
+0xB8BE,0xDFED,0xB8C1,0xB8C2,0xDFE3,0xDFF0,0xB8C3,0xB8BD,
+0xB8BC,0xDFEC,0xB8C4,0xDFE2,0xDFE5,0xDFEF,0xDFEB, 0,
+ 0,0xE3F4,0xE3E9,0xB8BB, 0, 0, 0, 0,
+0xBB6A,0xE3DD,0xE3F2,0xE3DE,0xBB65, 0,0xE3DB, 0,
+0xE3E4,0xE3DC,0xBB67,0xE3D6,0xE3F1,0xBB68,0xE3EE,0xE3EF,
+0xE3D7,0xBB6D,0xE3E6, 0,0xE3E0,0xE3E7,0xE3DA, 0,
+0xE3F3,0xE3EB,0xE3E5,0xE3D5,0xBB69,0xE3EC, 0,0xBB6C,
+0xE3F0, 0,0xE3EA,0xBB66,0xE3E8, 0,0xE3E2,0xBB64,
+0xE3D9,0xE3E1,0xE3ED,0xE3DF, 0, 0,0xE3E3, 0,
+ 0, 0, 0, 0,0xBDC1,0xDFE9,0xE7B2,0xE7BB,
+0xE7B1,0xE7AD,0xE7AA,0xBDC2,0xE7A8,0xBB6B,0xE7A1,0xBDC0,
+0xE7A7,0xBDBF,0xE7AC,0xE7A9,0xE7B9,0xE7B4,0xE7AE,0xE7B3,
+0xBDBB,0xE7AB,0xE7BE,0xE7A2,0xE7A3,0xE7BA,0xBDBC,0xE7BF,
+0xBDBE,0xE7C0,0xE7B0,0xE3D8,0xE7B6,0xE7AF,0xE7B8,0xE7B5,
+ 0, 0, 0,0xE7A6,0xBDB9,0xE7BD,0xBDBA,0xE7A4,
+0xBDBD,0xEB64,0xE7B7,0xE7BC, 0, 0, 0, 0,
+ 0,0xEB61,0xBDB8,0xBFC0,0xEB6B,0xEB67, 0,0xEB65,
+0xEB60,0xEB6F, 0, 0, 0,0xBFC4, 0,0xEB5C,
+0xEB68,0xEB69,0xEB5F,0xEB5E,0xEB6C, 0,0xEB62,0xEB5D,
+0xEB63, 0,0xEB6E,0xEB5B,0xEB6D,0xEB6A,0xBFC2,0xBFC1,
+ 0, 0,0xBFC3,0xEB66,0xF0CB, 0, 0, 0,
+ 0, 0,0xEE59,0xC1B1,0xEE5D,0xEE5A,0xEE61,0xEE67,
+0xEE5C, 0,0xEE70,0xC1AE,0xEE6A,0xEE5F,0xEE6B,0xEE66,
+0xEE6D,0xEE5E,0xC1B3,0xC1B2,0xEE60,0xEE6E,0xEE58,0xEE6C,
+0xC1AC, 0,0xEE64,0xEE63,0xEE68,0xEE5B,0xC1B0, 0,
+0xC1B4,0xEE62,0xEE69,0xC1B5,0xEE65, 0, 0, 0,
+ 0,0xC1AD,0xC1AF,0xF0C7,0xF0C5, 0, 0,0xF0CC,
+0xF0C9,0xF0CD, 0,0xF0BE,0xF0C6,0xF0D1,0xEE6F,0xF0C2,
+0xC2CF,0xE7A5,0xF0BD,0xF0CA,0xF0C4,0xF0C1,0xF0BC,0xF0BB,
+0xF0D0, 0,0xF0C0,0xF0BF,0xC2CD,0xF0C8, 0,0xC2CC,
+ 0, 0,0xC2CE,0xF0C3,0xF0CF, 0,0xF2DE,0xF2DF,
+ 0,0xC3C9,0xF2DC,0xC3C6,0xF2E4, 0,0xC3CA,0xF2E6,
+0xF2DB,0xF0CE,0xF2E8,0xF2DD, 0,0xC3C7,0xF2E3, 0,
+0xF2E5,0xF2E0,0xF2E7,0xF2E2,0xF2E1,0xC3C8, 0, 0,
+0xF4C5,0xF4C6, 0,0xF4C8,0xC4AE,0xC4AF,0xF4C9,0xF4C7,
+ 0,0xF4C4, 0,0xF642,0xF645,0xF641, 0,0xC4FA,
+0xF643,0xC4F9,0xC4F8,0xC4F7,0xF644,0xF751,0xF74F, 0,
+0xF74E,0xF640,0xF750,0xF646,0xF74D, 0,0xF7F9,0xF7D7,
+0xF7F7,0xC5DB,0xF7F8,0xF7FA, 0,0xF8BF,0xC5FA,0xF8BE,
+0xF8BD,0xC5FB, 0,0xC65A,0xF96E,0xF9A7,0xF9A6,0xF9A8,
+0xA6E5,0xD0AA, 0,0xD3CF,0xD3D0, 0, 0, 0,
+0xDBC0, 0,0xF647,0xF8C0,0xA6E6,0xAD6C,0xD0AB, 0,
+ 0, 0,0xD7B1,0xB34E, 0,0xDBC2,0xDBC1,0xB5F3,
+ 0,0xB8C5,0xE7C1,0xBDC3, 0,0xBDC4, 0, 0,
+ 0,0xBFC5,0xC5FC,0xA6E7, 0, 0, 0,0xD0AC,
+0xAAED,0xD0AE,0xD0AD,0xAD6D, 0,0xD3D1, 0,0xD3D8,
+0xB049,0xD3D6,0xD3D4, 0,0xD3DB,0xD3D2,0xD3D3,0xB04A,
+ 0,0xB04E, 0, 0,0xD3DC,0xB04D,0xD3DA,0xD3D7,
+0xD3D5,0xB04B,0xB04C,0xD3D9, 0, 0, 0, 0,
+0xB350,0xD7B2, 0,0xB355,0xD7C2,0xB354,0xD7C4, 0,
+ 0,0xD7B8,0xB352,0xD7C3, 0,0xD7B3,0xB353,0xD7BF,
+0xD7BB,0xD7BD,0xD7B7,0xD7BE, 0, 0,0xB34F,0xD7BA,
+ 0,0xD7B9,0xD7B5, 0,0xD7C0, 0, 0,0xD7BC,
+0xD7B4, 0,0xD7B6,0xB351,0xD7C1, 0, 0, 0,
+ 0,0xB5F6,0xDBCD, 0, 0, 0,0xDBC9,0xDBCB,
+0xDBC6,0xDBC5,0xDBC3, 0,0xDBCA,0xDBCC,0xDBC8, 0,
+0xDBC7,0xB5F4,0xB5F5, 0, 0, 0, 0, 0,
+ 0,0xDBCF,0xB8CD,0xDFF2,0xDFF8,0xDFF3,0xDFF4, 0,
+0xDFF9, 0,0xB8CF, 0,0xB8C7,0xB8CE,0xDFF1,0xDBC4,
+0xB8CA,0xB8C8,0xDFF7,0xDFF6,0xB8C9,0xB8CB,0xDFF5,0xB8C6,
+ 0,0xB8CC, 0, 0, 0, 0, 0,0xE3F6,
+0xBB74, 0, 0,0xE442,0xE441, 0,0xE3FB,0xBB76,
+0xE440,0xE3F7,0xE3F8,0xBB6E,0xBB70, 0,0xE3FD,0xE3F5,
+0xBB72,0xBB71,0xE3F9,0xE3FE,0xE3FC,0xBB73,0xE3FA, 0,
+ 0,0xDBCE,0xBB6F, 0, 0,0xE7C2,0xE7C9,0xBDC6,
+ 0,0xE7CD,0xBDCA,0xE7C5,0xE7C3, 0,0xE7CC, 0,
+0xBDC5,0xE7CB,0xBDC7,0xBDC8,0xE7C4,0xBDC9,0xE7CA,0xE7C6,
+0xE7C7,0xE7C8,0xBB75, 0, 0, 0,0xEB70,0xEB7C,
+ 0,0xBFCA,0xEB77,0xEB79, 0,0xBFC8,0xEB71,0xEB75,
+ 0,0xEB78,0xBFC6,0xBFC9,0xEB7B,0xEB73,0xEB74,0xEB7A,
+0xEB72,0xEB76,0xBFC7,0xEE72, 0,0xEE71,0xC1B7,0xEE77,
+0xC1B9, 0, 0,0xC1B6,0xEE73,0xC1BA,0xEE74, 0,
+ 0,0xEE75,0xEE78, 0,0xC1B8, 0,0xF0D6, 0,
+ 0,0xF0D9, 0,0xF0D3,0xF0D5, 0, 0,0xF0D4,
+0xF0D7,0xF0D8,0xEE76,0xF0D2, 0, 0,0xC3CD,0xF2EC,
+0xF2EF,0xF2F1,0xF2EA,0xF2EB,0xF2EE,0xF2F0,0xC3CE,0xC3CC,
+0xC3CB,0xF2ED,0xF2E9,0xF4CA,0xC4B0, 0,0xF4CB, 0,
+ 0,0xF649,0xC4FB,0xF64B,0xC4FC,0xF648,0xF64A,0xC5A8,
+ 0,0xF752,0xC5A7,0xF7FD,0xF7FC, 0,0xF7FB, 0,
+ 0,0xF948,0xF949,0xF94B,0xF94A, 0,0xCA50,0xA6E8,
+ 0,0xAD6E,0xD7C5,0xB5F7, 0,0xDFFA,0xC2D0, 0,
+0xF2F2, 0, 0,0xA8A3, 0, 0, 0,0xB357,
+ 0, 0, 0,0xB356, 0,0xDBD0,0xB5F8,0xDBD2,
+0xDBD1, 0, 0,0xDFFB,0xB8D0,0xE443,0xE446,0xE445,
+ 0,0xE444,0xE7CE,0xE7D0,0xE7CF, 0,0xBFCC, 0,
+ 0, 0,0xBFCB, 0,0xC1BB,0xEE79,0xEE7B,0xEE7A,
+ 0, 0,0xC2D1, 0, 0, 0,0xF2F4,0xF2F3,
+ 0,0xF4CC,0xC4B1, 0, 0,0xC4FD,0xF754,0xF753,
+0xC65B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA8A4,0xD0AF,0xAD6F,0xD7C8,0xD7C6, 0,
+ 0,0xD7C7,0xDBD4,0xDBD5,0xE043,0xDBD3, 0,0xDFFC,
+0xE041,0xE040,0xE042,0xB8D1,0xDFFE,0xDFFD,0xE044, 0,
+0xE449,0xE447, 0,0xE448,0xE7D3,0xE7D1, 0, 0,
+0xE7D2,0xEB7D,0xEE7C,0xEE7D,0xC2D2, 0,0xF2F5,0xF4CD,
+0xC4B2, 0,0xF64C,0xF755,0xC5A9, 0,0xF7FE,0xF94C,
+0xA8A5, 0,0xAD71,0xAD72,0xD0B0, 0, 0,0xD0B1,
+0xAD70, 0,0xB054, 0,0xB052, 0,0xB051,0xB058,
+0xB050,0xB059,0xD3DD,0xB056, 0,0xB053,0xB057,0xB055,
+0xB04F, 0, 0,0xB35F, 0,0xB359,0xD7CC,0xB35E,
+ 0, 0,0xB360,0xB35A, 0,0xB35B, 0,0xD7CA,
+ 0, 0,0xB358, 0,0xD7CB,0xB35D, 0, 0,
+0xD7C9,0xB35C, 0, 0,0xB644, 0,0xB646, 0,
+ 0,0xDBD8,0xB645,0xB5F9,0xB5FD, 0,0xB8E4,0xE049,
+0xDBDA,0xB5FE, 0, 0,0xDBDD,0xDBDE,0xB643, 0,
+0xDBE0, 0,0xDBE2, 0,0xDBE3,0xDBD7,0xDBD6,0xDBE4,
+0xB642,0xDBE1,0xDBDF, 0,0xB640,0xB5FB,0xB647,0xDBDB,
+0xDBDC,0xDBD9, 0,0xB641, 0, 0,0xB5FC, 0,
+0xB5FA,0xE048,0xB8DF,0xB8DA, 0, 0,0xB8D5, 0,
+0xB8E5,0xB8D6, 0,0xB8D2,0xB8E1,0xB8DE,0xB8E0, 0,
+0xB8D7,0xB8DC,0xB8D3,0xB8D4,0xE050,0xE04D,0xE045,0xE04A,
+ 0,0xB8E2,0xE051,0xB8E3,0xB8D9, 0, 0,0xE047,
+ 0,0xE04F,0xE04B,0xE04E,0xE04C,0xB8DD,0xE046,0xB8D8,
+ 0, 0, 0,0xE44C,0xBB78,0xBB7B, 0,0xE44E,
+ 0,0xBBA5,0xE44D,0xBB7D, 0,0xBDCF,0xE44F, 0,
+0xBBA4,0xE44B,0xBBA6, 0, 0, 0,0xBB79, 0,
+0xB8DB,0xBB7C, 0,0xBB7A,0xBB7E,0xBBA2,0xBB77,0xBBA7,
+0xBBA3, 0,0xBBA1,0xE44A, 0, 0, 0, 0,
+0xBDD6, 0,0xBDD2, 0, 0, 0,0xBDD9, 0,
+0xE7D6,0xBDDA,0xE7E2,0xE7DB,0xBDCB,0xE7E3,0xE7DD,0xBDD5,
+0xE7DE, 0,0xBDD4,0xE7E1,0xBDCE,0xE7DF,0xE7D5,0xBDCD,
+0xEBAA,0xBDD3, 0,0xBDD0, 0,0xBDD8, 0,0xE7D4,
+ 0,0xE7D8,0xBDCC,0xE7D7,0xE7D9,0xE7DA,0xBDD7,0xE7DC,
+0xE7E0,0xE7E4, 0,0xBDDB,0xBFD2,0xEBA5,0xEBAB,0xEBA8,
+0xEB7E,0xEBAC,0xEBA1, 0,0xEBA7, 0,0xBFCD,0xBFD3,
+0xEBAD, 0, 0,0xBFCF, 0,0xBFD9,0xBFD4,0xEBAF,
+0xEBA9,0xBFD0,0xEBA2,0xBFDA,0xEBA3,0xEBA4,0xBFDB,0xBFD8,
+0xBDD1, 0,0xBFCE,0xEBB0,0xBFDC, 0,0xBFD5,0xEBAE,
+0xBFD1,0xBFD6,0xBFD7, 0,0xC1C3,0xEEA4,0xEEAD,0xEEAA,
+0xEEAC, 0,0xC1C0,0xEEA5, 0,0xEEAB,0xC1BC,0xEEA7,
+0xC1C4,0xEEA3,0xEEA8,0xEEAF,0xEBA6,0xEEA9,0xEEA2,0xC1BD,
+0xEEA1,0xC1BE,0xEEB0,0xC1BF,0xEEAE,0xC1C2,0xEE7E, 0,
+0xC1C1, 0,0xEEA6,0xF0DC,0xF0EA,0xF0E5,0xF0E7,0xF0DB,
+0xC2D3, 0,0xF0DA,0xC2D6,0xC2D5, 0,0xF0E9,0xF0E1,
+0xF0DE,0xF0E4, 0,0xF0DD, 0,0xF0DF,0xF0E8,0xF0E6,
+ 0,0xC2D4,0xF0ED,0xF0EB,0xF0E2,0xF0EC,0xF0E3, 0,
+0xF2F9,0xC3CF,0xF341, 0, 0,0xF64F,0xC3D6,0xF0E0,
+0xF2F7,0xC3D2,0xF2F8,0xF2FD, 0, 0,0xC3D4,0xC3D5,
+0xF2F6,0xF340,0xF342,0xF2FA,0xF2FC,0xF2FE,0xF2FB,0xF343,
+0xC3D1,0xC3D7,0xC3D3, 0,0xC3D0,0xF4D0, 0,0xC4B7,
+0xF4CE, 0, 0,0xF4D2, 0,0xF4D3,0xC4B5,0xF4D4,
+0xF4D1, 0,0xF4CF,0xC4B8,0xC4B4,0xF4D5, 0,0xC4B6,
+0xC4B3, 0, 0, 0,0xC4FE, 0, 0,0xC540,
+0xF64E,0xF64D,0xF650,0xF651, 0,0xC541,0xF756,0xF75B,
+0xC5AA, 0,0xF758, 0,0xF757,0xF75A,0xF759, 0,
+0xF843, 0,0xC5DC,0xF842,0xF840, 0,0xF841, 0,
+ 0, 0,0xC5FE,0xC5FD,0xF8C1,0xF8C2,0xC640, 0,
+0xF94D,0xF94E,0xC667, 0,0xC66D, 0,0xF9A9,0xF9C8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA8A6,
+ 0,0xD7CD, 0,0xD7CE,0xE052,0xE450,0xE7E5,0xC1C6,
+ 0,0xC1C5,0xF0EE,0xF344, 0,0xF844,0xA8A7,0xD3DE,
+0xB05A,0xB361,0xE054,0xE053,0xBDDC,0xE7E6,0xBDDD,0xEEB1,
+0xC2D7, 0, 0, 0,0xC676,0xA8A8,0xCDCB,0xD3DF,
+ 0, 0,0xB362, 0,0xD7CF,0xD7D0, 0,0xDBE5,
+ 0,0xB648,0xB8E6, 0,0xE056,0xE055,0xE057, 0,
+0xE451,0xE452,0xBBA8,0xBFDD,0xBDDE,0xBFDE, 0,0xEEB5,
+0xEEB2,0xEEB4,0xEEB3,0xC1C7, 0,0xF0EF,0xF346,0xF345,
+0xCBA4,0xB05C,0xB05B,0xD3E0, 0,0xD7D1, 0, 0,
+0xDBE7,0xDBE6,0xB649, 0,0xE059,0xE05A,0xE058, 0,
+ 0,0xB8E8,0xB8E7, 0,0xBBAA,0xBBA9, 0,0xE7E7,
+0xEBB3,0xEBB1,0xEBB2,0xBFDF,0xEEB7,0xEEB6, 0,0xF0F2,
+0xF0F1,0xF0F0,0xF347, 0,0xF9AA,0xA8A9,0xAD73, 0,
+0xAD74,0xB05D,0xB05E,0xD3E2,0xD3E1,0xD7D2, 0,0xB368,
+0xB366,0xB363,0xB367,0xB365,0xB364, 0, 0,0xB64A,
+0xDBEA, 0,0xB8ED,0xB64C,0xB651,0xDBEC,0xB653,0xB652,
+0xB655,0xDBEB,0xDBE8,0xB64F,0xB64B,0xB64D,0xDBE9,0xB654,
+0xB650,0xB64E,0xB8EF,0xB8EE,0xB8EC,0xB8F0, 0,0xB8EA,
+0xB8EB, 0,0xB8E9, 0,0xE05B, 0, 0,0xE454,
+ 0,0xBBAC,0xBBAD,0xBBAB, 0,0xE453, 0,0xE455,
+ 0,0xE7EA,0xE7EC, 0,0xBDE7,0xE7ED,0xBDE0,0xE7E9,
+0xBDDF,0xBDE9,0xBDE5,0xBDE6,0xBDE2,0xE7E8,0xBDE1,0xE7EE,
+0xE7EB, 0,0xBDE8, 0,0xBDE3,0xBDE4,0xEBB5, 0,
+0xEBB7,0xEBB6, 0,0xEBB8,0xBFE0,0xEBB4, 0, 0,
+0xC1CB,0xEEB8,0xC1C8,0xC1CC,0xC1CA,0xC1C9,0xF0F3, 0,
+0xF0F6, 0,0xF0F5, 0,0xF0F4,0xC2D8,0xF348,0xF349,
+0xC3D8,0xF34A,0xC3D9, 0, 0,0xC4BA, 0,0xC4B9,
+0xF652, 0, 0,0xC542,0xF653,0xF75C,0xC5AB,0xC5AC,
+ 0,0xF845, 0,0xC642, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA8AA, 0,0xB36A,0xB369,
+0xE05C,0xE05D, 0,0xBBAE,0xEBB9,0xBDEA,0xEBBA,0xEEB9,
+0xA8AB, 0,0xD0B2,0xAD76,0xAD75, 0,0xD3E3,0xB05F,
+0xD3E4,0xD7D5, 0,0xD7D4, 0,0xD7D3, 0, 0,
+0xDBEE,0xB658, 0, 0,0xDBED,0xB657, 0, 0,
+ 0,0xDBEF,0xB656, 0,0xE05F,0xE062,0xE060,0xE061,
+0xE065,0xE05E,0xE066,0xE063,0xE064,0xBBB0,0xE456, 0,
+ 0,0xBBAF, 0,0xE7F2,0xE7F0, 0, 0,0xBDEB,
+0xE7EF,0xE7F1, 0,0xBDEC, 0,0xEBBB, 0,0xEBBC,
+0xC1CD, 0,0xF34C,0xF34E,0xF34B,0xF34D,0xF4D6,0xF654,
+ 0, 0,0xF96F,0xA8AC,0xAD77,0xD3E5,0xD3E7,0xD3E6,
+ 0,0xD7D8,0xB36C, 0,0xD7D6, 0,0xB36B,0xD7D9,
+ 0,0xD7DA,0xD7D7, 0, 0,0xDBFB,0xB660,0xDBF3,
+0xDBF9, 0, 0,0xB65B,0xB65E,0xDBF2,0xB659,0xDBF6,
+0xE06C,0xB65D, 0,0xDBF1, 0,0xDBF7,0xDBF4,0xDBFA,
+0xDBF0,0xDBF8,0xB65C,0xB65F,0xDBF5,0xB65A, 0,0xB8F2,
+0xE068,0xB8F1,0xE06F,0xE06E,0xB8F8, 0,0xB8F9,0xE070,
+0xB8F3,0xE06D,0xB8F7,0xE072,0xE069, 0,0xE06B,0xB8F4,
+0xE067,0xE06A,0xE071,0xB8F5,0xE073, 0, 0, 0,
+ 0, 0,0xB8F6, 0,0xBBB1,0xE45B,0xE461,0xE459,
+0xE462, 0,0xE458,0xE45D,0xE463,0xE460,0xE45F,0xE45E,
+ 0,0xE457,0xE45C, 0, 0,0xE45A, 0,0xBDF1,
+0xBDEE,0xE7FB,0xE841,0xE843,0xE840,0xE7F8,0xE7FA,0xE845,
+0xE842,0xE7FC,0xE846,0xE7F9,0xE844,0xBDEF,0xBDF5,0xBDF3,
+0xE7F3,0xBDF4,0xBDF0,0xE7F4,0xE7F6,0xE7F5,0xE7FD,0xE7FE,
+ 0,0xBDF2, 0,0xBDED, 0, 0,0xE7F7, 0,
+0xEBC6,0xBFE2, 0,0xEBBD,0xBFE3,0xBFE6,0xEBC2, 0,
+0xEBBF,0xBFE5, 0, 0,0xEBC3,0xEBC4,0xEBBE,0xEBC7,
+0xEBC0,0xEBC5,0xBFE4, 0,0xBFE1,0xEBC1, 0,0xEEBF,
+0xC1D0,0xC1CE,0xC1D1,0xC1CF,0xEEBE,0xEEBB,0xEEBA, 0,
+0xEEBD, 0, 0,0xEEBC,0xF145,0xC2DE,0xF0FB,0xF0FA,
+ 0,0xC2D9,0xF141,0xF140,0xF0F7,0xF143,0xF0FC,0xC2DD,
+0xF0F9,0xF142,0xF0F8,0xC2DA,0xC2DC,0xF0FD,0xC2DB,0xF0FE,
+ 0,0xF144,0xF352, 0,0xC3DE,0xF34F, 0,0xF353,
+ 0, 0,0xC3DB,0xF351,0xC3E0, 0,0xC3DD, 0,
+0xF350, 0,0xC3DF,0xF354,0xC3DA, 0, 0, 0,
+ 0,0xC4BC,0xC4BE, 0,0xF4D9,0xC4BD,0xF4D7,0xC3DC,
+0xF4D8,0xC4BB,0xC543,0xC545,0xF656,0xC544,0xF655, 0,
+0xF761,0xC5AD,0xF760,0xC5AE,0xF75E,0xF75D,0xF762,0xF763,
+0xF846, 0,0xF75F, 0, 0,0xF8C6,0xF8C3,0xF8C4,
+0xF8C5,0xC65C, 0,0xF951,0xF950,0xF94F,0xF970, 0,
+0xF9BE,0xF9AB,0xC66E,0xA8AD,0xB060, 0, 0, 0,
+ 0, 0,0xB8FA, 0, 0, 0, 0, 0,
+ 0, 0,0xBDF6, 0, 0,0xEBC8, 0, 0,
+0xC2DF, 0,0xF355, 0, 0, 0, 0, 0,
+ 0,0xF9AC,0xA8AE,0xAAEE,0xAD79,0xAD78, 0,0xB063,
+ 0,0xD3E8,0xB061,0xD3E9,0xB062, 0, 0,0xD7DF,
+0xD7DB, 0, 0,0xB36D,0xD7DE,0xD7DD,0xD7DC,0xB36E,
+0xD7E0,0xD7E1, 0, 0, 0,0xDC43,0xDC41,0xDC45,
+0xDC46,0xDC4C, 0,0xDC48,0xDC4A, 0,0xDC42,0xDBFC,
+ 0,0xDC49, 0, 0,0xDC4B,0xDC44,0xDC47,0xDBFD,
+0xB662,0xDC40,0xDBFE,0xB661,0xB663, 0,0xB8FD,0xE075,
+0xE077,0xE076,0xE07B,0xB8FB, 0,0xE078,0xE074,0xE079,
+0xE07A,0xB8FC,0xB8FE,0xE07C, 0,0xE467,0xE466, 0,
+0xE464,0xE465,0xBBB3,0xBBB5,0xBBB2,0xBBB4,0xE84D,0xE84E,
+0xE849, 0,0xE84A,0xBDF8,0xBDFD,0xBDF7,0xBDFE,0xBDF9,
+0xE84B, 0, 0,0xE84C,0xE848,0xBE40,0xBDFB, 0,
+ 0,0xBDFA,0xBDFC, 0,0xE847, 0,0xEBCA,0xBFE8,
+ 0, 0,0xEBCC,0xBFEA,0xEBCF,0xEBCB,0xEBC9,0xEBCE,
+0xBFE9,0xEBCD, 0,0xBFE7, 0, 0,0xC1D3,0xC1D6,
+0xEEC1, 0,0xC1D4,0xEEC0,0xC1D2,0xC1D5,0xF146,0xF147,
+0xF148,0xC2E0, 0,0xF149, 0,0xC2E1,0xC3E2,0xF358,
+0xF359,0xF357,0xF356,0xF35A,0xC3E1,0xF4DD,0xF4DB,0xF4DC,
+0xF4DE,0xF4DA,0xF4DF,0xF658, 0,0xF659,0xF657,0xC546,
+0xF764,0xC5AF,0xF765,0xF848,0xF847, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA8AF,0xB664, 0, 0,0xB940,
+ 0, 0, 0,0xBBB6, 0, 0,0xBFEC, 0,
+0xBFEB, 0, 0, 0, 0,0xC3E3,0xC47C,0xC547,
+0xA8B0,0xB064,0xB941, 0,0xF35B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCBA6,
+ 0, 0,0xA8B1, 0,0xA8B4,0xA8B3,0xA8B2, 0,
+ 0,0xCBA5, 0,0xCDCD, 0,0xCDCF,0xAAEF, 0,
+ 0,0xAAF1,0xCDCC,0xCDCE,0xAAF0,0xCDD1,0xCDD0,0xCDD2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD0B6,0xD0B4,0xAD7C,0xD0B3,0xADA3,0xAD7E,0xAD7B, 0,
+0xADA4, 0,0xAD7D,0xADA2, 0,0xADA1,0xD0B5, 0,
+0xAD7A, 0, 0, 0,0xB06A,0xD3EB,0xD3F1,0xB067,
+0xB06E, 0,0xB069,0xD3EE,0xD3F0,0xB06C,0xD3EA,0xD3ED,
+0xB068,0xB065,0xD3EC,0xB06B,0xD3EF,0xB06D,0xB066, 0,
+ 0, 0, 0,0xD7E3,0xD7E6,0xB370, 0,0xB37A,
+0xB376,0xD7E4, 0, 0,0xB37E,0xB377,0xB37C,0xB372,
+ 0,0xB36F,0xB371,0xB37D,0xD7E5,0xB375,0xB378,0xB374,
+0xB379,0xD7E7,0xB37B,0xB373,0xD7E2, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xDC4D,0xB665,0xDC4F,
+ 0,0xB667,0xB669, 0,0xDC4E,0xB666,0xB66A, 0,
+0xB668, 0, 0, 0,0xB947,0xE0A3,0xB94F,0xE07E,
+ 0,0xB950,0xB945, 0,0xE0A1, 0, 0,0xB94A,
+ 0,0xE0A2,0xB943,0xB942, 0,0xB94D,0xB94C,0xB94B,
+0xB949,0xB94E,0xE07D,0xB944,0xB946,0xB948, 0, 0,
+0xBBB8,0xBBBB, 0,0xBBBF,0xBBB9,0xBBBE,0xBBBC, 0,
+0xBBB7, 0,0xBBBD,0xBBBA, 0, 0, 0,0xE852,
+0xBE43,0xBE41, 0,0xE853, 0,0xBE44,0xBE42,0xE851,
+0xE850, 0,0xBFF0,0xE84F,0xBFEE,0xBFED,0xEBD0,0xBE45,
+0xBFEF,0xEBD1,0xBFF2,0xEBD2,0xBFF1,0xC1D8,0xEEC3,0xC1D7,
+0xC1DC,0xC1DA,0xC1DB,0xC2E3,0xC1D9,0xEEC2,0xEBD3,0xC2E2,
+0xC2E4, 0,0xC3E4,0xC3E5, 0,0xF4E0, 0,0xC5DE,
+0xC5DD,0xA8B6, 0, 0,0xCA55,0xB06F, 0,0xCA52,
+0xCA53,0xCA51, 0,0xCA54, 0, 0,0xCBAA,0xCBA7,
+0xCBAC,0xCBA8,0xA8B7,0xA8BA, 0,0xCBA9,0xA8B9,0xCBAB,
+ 0, 0,0xA8B8, 0, 0, 0, 0,0xCDD5,
+0xCDD7,0xAAF4,0xCDD3,0xCDD6,0xCDD4,0xAAF2,0xAAF5, 0,
+0xAAF3, 0, 0, 0, 0,0xD0B8,0xD0BC,0xD0B9,
+ 0,0xADA7, 0,0xADA8, 0,0xD0BB, 0,0xD0BD,
+0xD0BF, 0,0xADA5,0xD0BE, 0, 0,0xADA6, 0,
+ 0, 0, 0, 0,0xD7EE,0xD0BA,0xD3F2,0xD3FB,
+0xD3F9,0xD3F4,0xD3F5,0xD3FA,0xD3FC,0xB071, 0,0xD3F7,
+0xD3F3,0xB070,0xB072,0xD3F6,0xD3FD,0xD3F8, 0, 0,
+0xB3A1,0xD7F1,0xD7E9,0xD7EF,0xD7F0,0xB3A2, 0,0xD7E8,
+0xD7EA,0xD0B7,0xD7EC,0xD7ED,0xD7EB,0xB66C, 0, 0,
+ 0,0xDC56,0xEBD4,0xDC57,0xDC54,0xB3A3,0xB66E,0xDC53,
+0xDC59,0xDC58,0xB66B,0xDC5C,0xDC52,0xDC5B,0xDC50,0xDC5A,
+0xDC55,0xB66D, 0,0xE0AA, 0,0xE0A5,0xE0AB,0xE0A6,
+0xE0A4,0xE0A7,0xB951, 0,0xE0A9, 0,0xE0A8,0xB952,
+0xBBC1,0xBBC0,0xE46E,0xE471,0xE469,0xE46D,0xBBC2,0xE46C,
+0xE46A,0xE470,0xE46B,0xE468,0xE46F, 0,0xE859,0xBE48,
+0xF14A,0xE856,0xE857,0xE855,0xDC51,0xBE47,0xE85A,0xE854,
+0xBE46,0xBE49,0xE858,0xEBD5,0xBFF3,0xEBD6,0xEBD7, 0,
+0xEEC4,0xC1DD,0xF14B,0xF14C, 0, 0,0xF14D,0xF35D,
+0xF35C,0xF4E2, 0,0xF4E1,0xF65B,0xF65C,0xF65A,0xF766,
+0xC5B0,0xA8BB,0xADAA,0xADA9,0xB075,0xB074,0xD440,0xD441,
+0xD3FE, 0,0xB073,0xD7F5, 0,0xD7F6,0xD7F2,0xB3A4,
+0xD7F3, 0,0xD7F4, 0, 0, 0, 0,0xDC5F,
+0xDC61,0xDC5D,0xDC60,0xB66F,0xDC5E,0xB670, 0, 0,
+0xDD73,0xB955,0xB954, 0,0xB953, 0,0xE0AC,0xE0AD,
+ 0, 0,0xE473,0xE475,0xBBC6,0xBBC3, 0,0xBBC5,
+0xBBC4,0xE474,0xE472, 0, 0, 0, 0, 0,
+0xE861,0xE85E,0xE85F,0xBE4D,0xE860,0xE85B,0xE85C,0xBE4A,
+ 0,0xBE4B,0xE85D,0xBE4C, 0,0xEBDB, 0,0xEBDC,
+0xEBD9,0xEBDA,0xBFF4,0xEBD8, 0, 0, 0, 0,
+ 0,0xEEC8,0xEEC5,0xEEC7,0xC1E0,0xEECB,0xC1DF,0xEEC9,
+0xEECC,0xEECA,0xEEC6,0xC1DE, 0,0xF14F, 0,0xF150,
+0xF14E, 0,0xF152,0xC2E5,0xC2E6,0xF35F,0xC3E7,0xF151,
+0xF35E,0xC3E6,0xF4E5,0xF4E6,0xC4BF,0xF4E4, 0,0xF4E3,
+ 0,0xF65D,0xC548, 0,0xF849,0xF8C8,0xF8C7, 0,
+0xC643,0xC65D,0xF8C9,0xF971, 0,0xC66F,0xA8BC,0xAAF6,
+ 0,0xB956, 0,0xC4C0,0xA8BD,0xADAB,0xB3A5,0xB671,
+0xC2E7,0xAAF7, 0,0xD0C1,0xD0C0,0xD442, 0,0xB078,
+0xB076,0xB07A,0xD444, 0,0xB079,0xB077, 0, 0,
+ 0, 0,0xD443,0xB3A8,0xD7FC, 0,0xB3A7,0xB3A9,
+0xD842,0xB3AB,0xD7FE,0xD840,0xD7F7,0xB3AA,0xD843, 0,
+ 0,0xD7F9, 0,0xD7FA,0xD7F8,0xB3A6, 0,0xD841,
+0xD7FB,0xD7FD, 0, 0, 0,0xDC6D, 0,0xDC6C,
+0xDC6A,0xDC62,0xDC71,0xDC65,0xDC6F,0xDC76,0xDC6E,0xB679,
+ 0,0xB675,0xDC63, 0,0xDC69,0xB677, 0,0xDC68,
+0xB678,0xB67A,0xDC6B, 0,0xB672,0xB673,0xDC77,0xDC75,
+ 0,0xDC74,0xDC66, 0,0xDC72, 0,0xB676, 0,
+ 0, 0, 0,0xB674,0xDC73,0xDC64,0xDC67,0xDC70,
+ 0, 0, 0, 0, 0,0xE4BA,0xE0B7, 0,
+0xE0B0,0xE0C3,0xE0CC,0xE0B3,0xB961, 0,0xE0C0,0xB957,
+0xB959,0xB965,0xE0B1, 0, 0,0xB95A,0xB95C,0xB966,
+0xB95B, 0, 0, 0, 0,0xB964,0xE0B9, 0,
+0xE0AE,0xB962,0xE0B8,0xB95E,0xE0CA,0xB963,0xE0C8,0xE0BC,
+0xE0C6,0xB960,0xE0AF,0xE0C9,0xE0C4, 0,0xE0CB,0xB958,
+ 0, 0,0xB967,0xB95D, 0, 0,0xE0B5, 0,
+0xE0BD,0xE0C1, 0,0xE0C5,0xB95F,0xE0B4,0xE0B2,0xE0BE,
+ 0, 0, 0, 0,0xE0BB,0xE0BA, 0,0xE0BF,
+0xE0C2, 0,0xE0C7, 0, 0, 0,0xE478, 0,
+0xBBC7,0xE4A4,0xE47A,0xBBCC,0xBBD0,0xE4AD,0xE4B5,0xE4A6,
+0xBBC8, 0,0xE4AA,0xE0B6, 0,0xBBC9,0xE4B1,0xE4B6,
+0xE4AE, 0,0xE4B0,0xE4B9,0xE4B2,0xE47E,0xE4A9, 0,
+ 0,0xBBD1, 0,0xBBCD,0xE47C,0xE4AB,0xBBCB,0xE4A5,
+0xBBCA,0xE4B3,0xE4A2,0xE479,0xBBCE,0xE4B8, 0, 0,
+0xE47B,0xE4AF,0xE4AC,0xE4A7,0xE477,0xE476,0xE4A1,0xE4B4,
+0xBBCF,0xE4B7,0xE47D,0xE4A3,0xBE52, 0, 0, 0,
+ 0, 0,0xBE5A,0xBE55,0xE8A4,0xE8A1,0xE867,0xBE50,
+ 0, 0, 0,0xBE4F,0xBE56, 0, 0, 0,
+0xE865,0xBE54,0xE871,0xE863,0xE864,0xBE4E,0xE8A3,0xBE58,
+0xE874,0xE879,0xE873,0xEBEE,0xE86F,0xE877,0xE875,0xE868,
+0xE862,0xE87D,0xBE57,0xE87E, 0,0xE878, 0,0xE86D,
+0xE86B,0xE866, 0, 0, 0,0xE86E,0xE87B,0xE86A,
+0xE87A,0xE8A2, 0, 0,0xBE53, 0,0xE876,0xE87C,
+0xE872,0xE86C,0xBE51, 0, 0, 0,0xE4A8,0xE870,
+0xBE59,0xE869, 0, 0, 0, 0, 0,0xEBF4,
+0xBFF7,0xEBF3,0xEBF0,0xEC44,0xBFFB, 0,0xEC41,0xEBF8,
+0xEC43,0xEBE9,0xEBF6, 0,0xBFFD, 0,0xEBE1, 0,
+0xEBDF,0xEC42, 0,0xEC40,0xEBFE,0xEBED,0xEBEC,0xEBE2,
+0xC040, 0,0xEBE8,0xEBF2,0xEBFD,0xC043,0xEC45, 0,
+0xC1E8,0xC045,0xBFFE,0xEBE6, 0,0xEBEF,0xEBDE,0xEBE0,
+0xBFF5,0xC042,0xBFFA,0xEBE7,0xEBF7,0xEBF1,0xC041,0xEBDD,
+0xC1E3,0xEBF9,0xEBFC,0xBFFC, 0,0xEBEB,0xC044,0xBFF9,
+ 0, 0, 0,0xBFF8,0xEBF5,0xEBFB,0xBFF6, 0,
+0xEBE4,0xEBFA, 0, 0,0xEBE5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xEBEA,0xEED2,
+ 0,0xEED7,0xC1E5,0xC1E7,0xEEDD,0xC1E1,0xEEEC,0xEEE3,
+0xEED8,0xEED9,0xEEE2, 0,0xC1EE,0xEEE1,0xEED1,0xEEE0,
+0xEED4,0xEEED,0xC1ED,0xC1EB,0xEED5, 0,0xEEE8, 0,
+0xEEDA,0xEEE7, 0,0xEEE9,0xEED0,0xC1E6, 0,0xEEEA,
+ 0, 0,0xEEDE, 0,0xC1EA,0xEEDB, 0, 0,
+0xC1EC,0xEEE4, 0, 0, 0,0xC1E4,0xEED6,0xEEE5,
+ 0,0xEEDF,0xEBE3,0xEEE6,0xEED3, 0,0xC1E9, 0,
+0xEEEB, 0,0xC1E2,0xEECE, 0, 0, 0, 0,
+0xF160,0xF159,0xC2E9, 0,0xF154,0xF163,0xF15B,0xEEDC,
+ 0,0xF165,0xF155, 0,0xC2E8,0xF15F,0xC2EA,0xC2F2,
+0xC2F0,0xF161,0xC2F1,0xF157, 0,0xF158,0xF15D,0xF162,
+ 0,0xEECD,0xC2EB,0xF16A,0xF167,0xF16B,0xF15E,0xF15A,
+0xF168,0xF36A,0xF15C, 0,0xC2EE, 0,0xC2ED,0xEECF,
+0xC2EF,0xF164,0xF166,0xC2EC,0xF169,0xF153, 0,0xF156,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF373, 0,0xF363,0xC3EB,0xF371, 0, 0,0xF361,
+0xC3EC, 0,0xF36C, 0,0xF368,0xC3F1,0xF372,0xF362,
+0xF365,0xC3E9,0xF374, 0,0xF36D,0xF370,0xC3EF,0xC3F4,
+0xC3F2,0xF369,0xF364, 0,0xC3ED,0xC3EE,0xF360,0xC3EA,
+ 0,0xC3E8,0xC3F0,0xF36F,0xC3F3, 0,0xF36B,0xF375,
+0xC3F5, 0, 0, 0,0xF367, 0,0xF36E, 0,
+ 0, 0, 0, 0, 0,0xF4F3,0xF542,0xF4F5,
+0xF4FC,0xF366,0xF4FA,0xF4E9,0xF540,0xC4C3,0xF4ED,0xF4FE,
+0xF4F4, 0, 0,0xC4C2, 0, 0,0xF544,0xF4F6,
+ 0,0xF4FB,0xF4FD,0xF4E7,0xF541,0xF4F2,0xF4F7,0xF4EB,
+0xF4EF,0xF543,0xF4F9,0xF4E8,0xF4EC,0xF4EE,0xF4F8, 0,
+0xC4C1,0xF4F1, 0, 0, 0, 0, 0, 0,
+0xF4EA, 0, 0, 0, 0, 0, 0, 0,
+0xF4F0,0xF661,0xF666,0xC54F,0xF668, 0,0xC549, 0,
+0xF664,0xF66A,0xC54E,0xC54A, 0,0xC54B,0xF660,0xF667,
+0xC54D,0xF665,0xC54C,0xF65F,0xF663,0xF662, 0,0xF65E,
+0xF669, 0, 0, 0,0xC5B1,0xF76D,0xF770,0xF76C,
+0xF76E,0xF76F,0xF769,0xF76A,0xF767, 0, 0,0xF76B,
+0xF768,0xC5B2,0xC5B3, 0, 0,0xF84B, 0,0xF84D,
+ 0, 0, 0, 0, 0,0xF84C,0xF84E, 0,
+0xC5E0, 0,0xF84A,0xC5DF,0xC5E1, 0, 0, 0,
+0xF8CB,0xF8CC,0xC644,0xF8CA, 0,0xF953,0xF952,0xF954,
+0xC65F,0xF955,0xC65E,0xF956,0xF972,0xF975,0xF974,0xC668,
+0xF973, 0, 0, 0,0xC672,0xC670,0xC671,0xC677,
+0xF9C0,0xF9C1,0xF9BF,0xF9C9};
+
+/* page 8 0x9577-0x9FA4 */
+static uint16 tab_uni_big58[]={
+0xAAF8, 0, 0,0xD844,0xDC78,0xE8A5,0xF376, 0,
+ 0,0xAAF9, 0,0xADAC,0xB07B, 0, 0,0xD845,
+ 0,0xD846,0xB3AC, 0,0xB67D,0xDC7A,0xDC79,0xB6A3,
+0xB67C,0xDC7B,0xB67E,0xB6A2,0xB6A1,0xB67B, 0, 0,
+ 0,0xB968, 0, 0,0xE0D0,0xE0CE, 0,0xE0CF,
+0xE0CD, 0,0xBBD2, 0,0xBBD5,0xBBD7,0xBBD6, 0,
+ 0,0xBBD3,0xBBD4, 0,0xE8A7,0xE8A6,0xBE5B,0xE8A8,
+ 0,0xE8A9,0xBE5C, 0, 0, 0,0xEC4D,0xEC4B,
+0xEEF3, 0,0xEC49,0xEC4A,0xC046,0xEC46,0xEC4E,0xEC48,
+0xEC4C,0xEEEF, 0, 0,0xEEF1, 0,0xEEF2,0xC1F3,
+0xEEEE,0xC1F2,0xEEF0,0xC1EF,0xC1F0,0xC1F1,0xEC47, 0,
+ 0,0xC2F5,0xF16E,0xF16C,0xF16D,0xC2F3,0xC2F6,0xC2F4,
+ 0, 0, 0,0xF377,0xF378,0xC3F6, 0,0xF545,
+0xF547,0xF546,0xC4C4,0xC550,0xF66D,0xF66C,0xF66B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xAAFA, 0,0xC9AA,
+ 0,0xCA58,0xA6E9,0xCA56,0xCA59,0xCA57, 0, 0,
+ 0,0xCBAE, 0,0xA8C1, 0,0xA8C2,0xCBB0,0xA8BF,
+0xCBAF,0xCBAD,0xA8C0,0xA8BE, 0, 0, 0, 0,
+ 0, 0,0xCDD8,0xCDDB,0xAAFD,0xCDDA,0xCDD9, 0,
+0xAAFC,0xAAFB, 0,0xAB40,0xCDDC,0xAAFE, 0, 0,
+ 0, 0, 0,0xD0C6,0xADAE,0xADAF,0xADB0,0xD0C7,
+0xD0C3,0xADAD,0xD0C4, 0,0xD0C5,0xD0C2, 0, 0,
+ 0,0xB0A4, 0, 0,0xB0A1,0xD445,0xB0A2,0xB0A5,
+0xD446, 0,0xB07E,0xB07C,0xB07D,0xB0A3, 0, 0,
+ 0, 0, 0,0xB3AD,0xD849,0xB3B5,0xD848, 0,
+0xD84B,0xB3B1,0xD84A,0xB6AB,0xB3AF,0xB3B2,0xB3AE,0xB3B3,
+0xB3B4,0xB3B0, 0, 0, 0,0xD847,0xB6A7,0xDC7D,
+ 0,0xDCA3, 0, 0,0xDCA2,0xB6AC,0xB6A8,0xB6A9,
+0xDC7C,0xDC7E,0xDCA1,0xB6A4,0xB6A6, 0,0xB6AA,0xB6A5,
+ 0, 0,0xE0D3,0xE0D1,0xE0D2,0xB96A,0xB96B, 0,
+0xE0D4,0xB969,0xBBD8, 0,0xBBDA,0xBBD9, 0,0xE4BB,
+ 0, 0,0xE4BC,0xE8AB, 0,0xE8AA, 0, 0,
+0xC047,0xC048,0xEC4F,0xC049, 0,0xEEF6, 0,0xEEF4,
+ 0,0xEEF5,0xC1F4, 0,0xF16F,0xC3F7, 0, 0,
+ 0,0xC1F5,0xAB41, 0,0xB0A6,0xD447, 0, 0,
+0xD84C,0xB3B6,0xB6AD,0xDCA4,0xDCA6,0xB6AF,0xB6AE,0xB6B0,
+0xB6B1,0xDCA5,0xB96E,0xB96F,0xB96D,0xBBDB,0xB96C,0xE0D5,
+ 0, 0, 0,0xBBDC,0xE8AC,0xEC50,0xC04A,0xC1F6,
+0xF170,0xF174,0xC2F9,0xF171,0xC2FA,0xC2F8,0xF175,0xC2FB,
+0xF173, 0,0xF379,0xC2F7,0xC3F8, 0,0xF8CD, 0,
+ 0,0xAB42,0xB3B8,0xB3B7, 0, 0, 0, 0,
+0xB6B2,0xDCA8,0xDCA7,0xB6B3, 0, 0,0xE0D9,0xB973,
+0xB970,0xE0D8,0xB972,0xE0D6,0xB971, 0,0xE0D7, 0,
+0xE4BD,0xBBDD, 0,0xE8AF, 0,0xBE5D,0xE8AD,0xBE5E,
+0xBE5F,0xE8AE,0xBE60, 0,0xEC51, 0,0xC04E,0xC04B,
+0xC050,0xEC53,0xC04C,0xEC52,0xC04F, 0, 0,0xC04D,
+ 0,0xEEF9,0xEEFB, 0, 0,0xC1F7,0xEEFA,0xC1F8,
+0xEEF8,0xEEF7, 0,0xF177,0xF176,0xC2FC,0xF178,0xF37E,
+0xC3FA,0xF37D,0xF37A,0xC3F9,0xF37B,0xF37C, 0,0xF548,
+0xF549,0xC4C5, 0,0xC553, 0, 0,0xF66E, 0,
+ 0,0xC551,0xC552,0xF66F, 0, 0,0xC5B4,0xC5B5,
+0xF771, 0, 0,0xC645,0xF8CF,0xC647, 0,0xF8CE,
+0xF8D0,0xC646,0xF957, 0,0xF9AD, 0, 0, 0,
+ 0, 0, 0,0xAB43, 0, 0, 0,0xB974,
+ 0,0xE4BE, 0,0xE8B0,0xC051,0xC052, 0,0xAB44,
+ 0,0xBE61,0xC3FB,0xADB1, 0, 0, 0,0xC053,
+ 0,0xC5E2,0xADB2,0xD84D, 0,0xDCA9, 0,0xDCAB,
+ 0,0xDCAA, 0,0xE0DD,0xE0DA,0xB975, 0,0xB976,
+0xE0DB,0xE0DC, 0,0xE4C0,0xE4C5,0xBBDE,0xE4BF,0xE4C1,
+0xE4C8,0xE4C3,0xE4C7,0xE4C4,0xE4C2,0xE4C6,0xBBDF, 0,
+ 0,0xE8B3, 0,0xE8B1,0xBE63, 0,0xBE62,0xE8B2,
+0xBE64, 0, 0, 0, 0,0xEC56, 0, 0,
+0xEC55,0xC054,0xEC54,0xEEFC, 0,0xEEFE,0xEF41,0xEF40,
+ 0,0xC1F9,0xEEFD,0xF1A1,0xC2FD,0xF17D,0xF1A2,0xC2FE,
+ 0,0xF17B, 0,0xF17E,0xF17C,0xF179,0xC340,0xF17A,
+ 0, 0, 0, 0,0xF3A1, 0, 0,0xF3A3,
+0xF3A2, 0,0xF54A, 0,0xF54B, 0, 0, 0,
+0xF670, 0,0xC5B7, 0,0xC5B6,0xF84F,0xF850,0xC648,
+0xF8D1, 0,0xC669, 0,0xADB3,0xB6B4,0xE4CA,0xE4C9,
+0xE8B5,0xE8B4, 0, 0,0xC1FA,0xEF43,0xEF42,0xF1A5,
+0xF1A3,0xF1A6,0xF1A4, 0, 0,0xC3FC,0xF3A4,0xF3A5,
+0xF3A6, 0,0xF671, 0,0xF772, 0,0xF8D2, 0,
+ 0, 0, 0, 0, 0, 0,0xADB4, 0,
+ 0,0xEC57,0xEF44, 0,0xADB5, 0, 0,0xBBE0,
+ 0,0xEC58,0xC341,0xF1A7,0xC3FD, 0,0xF54C,0xF54D,
+0xC554,0xF851,0xADB6,0xB3BB,0xB3BC,0xD84E,0xB6B5,0xB6B6,
+0xDCAC,0xB6B7, 0,0xB97A, 0,0xB97C,0xE0DF,0xE0E0,
+0xE0DE,0xB977,0xB978,0xB97B,0xB979, 0, 0,0xE4CB,
+0xBBE1,0xBBE2, 0, 0,0xE8BC,0xBE67,0xE8B7,0xE8B6,
+ 0,0xE8BB,0xBE65, 0, 0,0xC05B, 0,0xE8B8,
+0xE8BD,0xE8BA,0xE8B9, 0,0xBE66, 0,0xC059, 0,
+0xEC5A,0xC055, 0,0xEC5B, 0, 0,0xEC59, 0,
+0xC058,0xC056,0xC05A, 0,0xC057, 0, 0, 0,
+ 0, 0,0xEF45, 0,0xEF4A,0xEF46,0xEF49,0xC1FB,
+ 0,0xEDD4,0xEF48,0xEF47, 0,0xC344,0xC342,0xC345,
+0xC343,0xF1A8,0xF1A9,0xF1AA,0xC346, 0, 0, 0,
+0xF3AA,0xC440,0xF3A8, 0,0xC441,0xF3A7,0xF3A9,0xC3FE,
+0xF551,0xF54E, 0,0xF54F,0xF550,0xF672,0xC556, 0,
+0xC555, 0,0xF774,0xF773,0xC5B8, 0, 0, 0,
+0xC5E3,0xC649,0xC660,0xF958,0xF9AE,0xF9AF, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xADB7,0xDCAD, 0, 0,0xE0E1,0xE4CC,0xE4CD,
+0xBBE3, 0,0xBBE4,0xE8BE,0xBE68, 0, 0,0xC1FC,
+ 0,0xF1AB, 0,0xC347,0xF3AD,0xC442,0xF3AC,0xF3AE,
+0xF3AB,0xF675,0xF552,0xF553, 0,0xC4C6, 0,0xF674,
+ 0, 0,0xF673, 0,0xF775,0xF9B0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xADB8, 0, 0, 0,
+0xADB9, 0, 0,0xB0A7,0xD448, 0,0xD84F, 0,
+0xB6B8, 0,0xB6BB,0xB6B9,0xDCAE, 0,0xB6BD, 0,
+0xB6BA, 0, 0,0xB6BC, 0,0xB97E, 0,0xE0E2,
+ 0, 0,0xE0E3,0xE8C0, 0,0xB97D,0xB9A1,0xB9A2,
+ 0,0xE4CF, 0,0xE4CE,0xBBE5, 0,0xBBE6, 0,
+0xE4D0,0xE8BF,0xBBE8,0xBE69, 0,0xBBE7, 0, 0,
+ 0,0xC05C,0xE8C1,0xBE6B,0xBE6A,0xE8C2,0xE8C5,0xE8C3,
+0xE8C4,0xBE6C, 0,0xC061,0xC05F, 0, 0,0xC05E,
+0xEC5D, 0,0xC060, 0, 0,0xEC5C,0xEF4B, 0,
+0xEC5E,0xC05D,0xEC5F,0xEF4E,0xEF4C,0xEF4D,0xEF52,0xC34B,
+0xEF51,0xEF54,0xEF53,0xEF50,0xEF4F, 0,0xC1FD, 0,
+ 0, 0, 0,0xF1AE, 0,0xF1AD,0xC34A,0xC348,
+0xC349, 0,0xF1AC, 0,0xF3B1, 0,0xC443, 0,
+0xF3B0,0xF3AF,0xC444, 0,0xF558,0xF557, 0,0xF555,
+ 0,0xF554,0xC4C8,0xC4C7,0xF559,0xF776,0xC5B9,0xF677,
+0xC557,0xF676,0xF556, 0,0xF777,0xC5E4, 0,0xC661,
+0xF959, 0,0xF9B1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xADBA,
+0xD850,0xEF55,0xADBB, 0, 0,0xE4D2,0xE4D1,0xEC60,
+ 0, 0,0xEF57, 0,0xEF56, 0,0xC34C,0xF3B2,
+0xF3B3,0xC4C9, 0, 0,0xF9B2,0xB0A8,0xB6BF,0xB6BE,
+0xE0E4,0xE0E6,0xB9A4,0xE0E5,0xB9A3,0xB9A5,0xE0E7, 0,
+ 0, 0,0xE4D4,0xE4D6,0xE4D5, 0,0xE4D8, 0,
+ 0, 0,0xBBE9,0xE4D7,0xE4D3, 0, 0, 0,
+0xE4D9, 0,0xE8CC, 0,0xE8CF,0xE8D1,0xE8C7,0xE8CB,
+0xE8C8,0xBE6E,0xBE71,0xBE73,0xE8C9,0xE8CA,0xBE72,0xE8CD,
+0xE8D0,0xE8CE,0xBE74, 0,0xBE70,0xE8C6,0xBE6D, 0,
+0xBE6F, 0, 0,0xC063,0xEC66,0xEC64,0xEC63, 0,
+0xEC69, 0,0xEC68,0xEC67, 0,0xEC62,0xC062,0xEC61,
+ 0,0xEC65,0xC064, 0, 0,0xEF5A, 0,0xEF5E,
+0xEF5B,0xEF5D,0xEF5C,0xEF59,0xEF5F,0xEF62,0xEF60,0xEF61,
+0xC240, 0,0xC1FE,0xEF58,0xEF63,0xF1B3,0xF1B6,0xF1B8,
+0xF1B7, 0,0xF1B1,0xF1B5,0xF1B0, 0,0xF1B2,0xC34D,
+0xF1AF, 0,0xF1B4, 0, 0,0xF3C0,0xF3B5,0xC445,
+ 0, 0,0xC446,0xF3B4,0xF3B9,0xF3BF,0xF3B7,0xF3BE,
+ 0,0xF3BB, 0,0xF3BA,0xF3BD,0xF3B8,0xF3B6, 0,
+0xF3BC, 0,0xF560,0xF55E,0xC4CA,0xF55D,0xF563,0xF561,
+ 0,0xC4CB,0xF55C,0xF55A, 0,0xF55B,0xC4CD,0xF55F,
+0xC4CC,0xF562,0xF678,0xF67E, 0, 0,0xF679,0xC55B,
+0xF6A1,0xC55A,0xF67D,0xF67C,0xC559,0xF67B,0xC558,0xF67A,
+ 0,0xF77D,0xF7A1,0xF77E, 0,0xF77B,0xC5BB,0xF778,
+0xF77C,0xF7A3, 0,0xF7A2,0xF779,0xF77A,0xC5BA,0xF852,
+0xC5E7, 0,0xF853,0xC5E5,0xC5E6, 0, 0,0xF8D3,
+0xC64A,0xF976, 0,0xC66A, 0,0xF9B3,0xC66B,0xF9B4,
+0xF9B5,0xF9C3,0xF9C2,0xC67A,0xF9CD, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB0A9, 0, 0,0xE0E9, 0,0xE0E8, 0,
+0xBBEA,0xBBEB,0xE4DA, 0,0xE8D2,0xEC6C, 0, 0,
+0xBE75,0xC065,0xEC6A, 0,0xEC6D,0xC066, 0,0xEF64,
+0xEC6B,0xF1B9,0xC34E,0xF3C1, 0, 0, 0,0xF566,
+0xF564, 0, 0,0xF565, 0, 0,0xF6A2, 0,
+0xC55C,0xF7A4,0xC5EA,0xC5BC,0xC5E8,0xC5E9,0xF8D4,0xC662,
+ 0,0xB0AA, 0, 0, 0,0xF1BA, 0, 0,
+0xD449, 0,0xB9A6, 0,0xE4DB, 0, 0,0xBBEC,
+0xE4DC, 0, 0, 0,0xE8D4,0xE8D3,0xC068,0xBE76,
+0xBE77, 0,0xE8D7,0xE8D6,0xE8D5, 0, 0,0xEC6E,
+0xEC71, 0,0xEC70,0xEC6F,0xC067,0xEF68,0xEF66,0xEF65,
+ 0, 0,0xEF67, 0,0xC34F,0xF1BC,0xF1BD,0xC350,
+ 0,0xF1BB, 0,0xF3C3,0xF3C2,0xF3C5,0xC447,0xF3C4,
+ 0,0xF567,0xF569,0xF568, 0, 0,0xF6A3,0xF6A6,
+0xF6A4,0xF6A5,0xF7A5,0xC5BD, 0, 0, 0,0xF854,
+0xF855,0xF856, 0,0xC64B,0xC663,0xF9B6,0xB0AB, 0,
+0xBE78,0xC069,0xF1BE, 0,0xF7A6, 0, 0,0xF9C4,
+0xD44A, 0,0xC67B,0xB0AC,0xEC72, 0,0xF1BF, 0,
+0xF3C6, 0, 0,0xF6A7,0xF7A7,0xB0AD, 0,0xE4DD,
+0xE4DE, 0,0xBBED,0xBBEE,0xE8D9,0xBE7A,0xBE79,0xE8D8,
+ 0,0xEF69, 0,0xF1C0,0xF1C2,0xF1C1,0xC353,0xC352,
+0xC351, 0,0xC55E,0xF6A8, 0,0xC55D,0xF7A9,0xF7A8,
+ 0,0xC64C,0xF8D5,0xB3BD,0xE0EA, 0, 0, 0,
+0xE4E1,0xE4DF,0xE4E0, 0, 0,0xE8E2, 0,0xE8DD,
+0xE8DA,0xE8E1, 0, 0, 0,0xE8E3, 0, 0,
+0xBE7C,0xE8E0,0xE8DC, 0, 0,0xE8DB,0xE8DF,0xE8DE,
+0xBE7B, 0, 0,0xEC7D,0xEC78,0xEC76,0xECA1,0xEC77,
+ 0,0xEC73, 0,0xEC79, 0, 0,0xEC74,0xEF72,
+0xEC75,0xECA2, 0, 0, 0, 0, 0, 0,
+ 0,0xEC7C,0xC06A,0xEC7B,0xEC7A, 0,0xEC7E, 0,
+ 0, 0, 0,0xEF6A,0xEF6D, 0, 0,0xEF6C,
+ 0,0xEF74,0xEF6F,0xEF73, 0,0xEF71,0xEF70,0xEF6E,
+ 0,0xEF6B, 0,0xC243,0xC242, 0,0xC244,0xC241,
+0xEF75, 0, 0, 0, 0, 0,0xF1C8,0xF1CB,
+ 0,0xF1C9,0xF1CD, 0, 0, 0,0xF1CE, 0,
+0xF1C6,0xC358,0xF1C7, 0,0xF1C5,0xF1CC, 0,0xF1C4,
+0xF1C3,0xC357,0xC355,0xC354, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF1CA,0xF3CF,0xF3D5,0xC44A,
+0xF3D0, 0,0xF3D3,0xF3D7,0xC44B,0xF3D2, 0,0xF3CA,
+ 0,0xF3C9,0xF3D6,0xF3CD, 0,0xF3CB,0xF3D4,0xF3CC,
+0xC449,0xC448, 0,0xF3C7,0xF3C8,0xF3D1, 0, 0,
+ 0,0xF3CE, 0, 0, 0, 0, 0, 0,
+0xF56C,0xF56F, 0, 0, 0, 0,0xC356, 0,
+ 0, 0, 0, 0, 0, 0,0xF56D,0xF573,
+0xF571,0xF56B,0xF576, 0,0xF56A, 0,0xC4CF,0xF572,
+ 0, 0, 0,0xF56E,0xC4CE,0xF575, 0, 0,
+0xF574, 0, 0, 0, 0,0xF6AB,0xF6AA, 0,
+ 0, 0,0xF6B1, 0,0xF6AD,0xF6B0,0xC560, 0,
+ 0,0xF6AE,0xF6AF, 0,0xF6A9,0xF6AC,0xC55F, 0,
+ 0, 0,0xC5BF,0xF7B4,0xF7AF,0xF7B3, 0,0xF7B6,
+0xF7B2, 0,0xF7AE, 0,0xC5C1,0xF7B1,0xF7B5,0xC5C0,
+0xF7AC,0xF570,0xF7B0, 0, 0,0xF7AD, 0,0xF7AA,
+ 0,0xF7AB,0xC5BE,0xF85A,0xF85C,0xF85F,0xF85B,0xF860,
+ 0,0xF859, 0,0xF857, 0,0xC5EB,0xF85D,0xC5ED,
+0xC5EC,0xF858,0xF85E, 0, 0, 0, 0,0xF8DA,
+0xC64D,0xF8DB, 0,0xF8D9,0xF8D6, 0, 0,0xF8D8,
+0xF8D7,0xF95A, 0, 0, 0, 0,0xF95C,0xF95B,
+ 0, 0,0xF979, 0,0xF978,0xF977,0xF97A, 0,
+0xC673,0xC674,0xF9CA,0xF9CE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB3BE,0xDCAF,
+0xE0ED, 0,0xB9A7,0xE0EB, 0, 0,0xE0EC, 0,
+ 0, 0,0xE4E2,0xE4E3,0xBBF1,0xBBEF,0xE4E4,0xBBF0,
+0xE8E8, 0,0xE8EB,0xE8E5,0xE8EC,0xE8E4,0xE8E6, 0,
+0xE8E7,0xE8EA, 0, 0,0xBEA1,0xE8EF,0xE8EE,0xBE7D,
+0xE8E9,0xE8ED,0xBE7E, 0, 0, 0, 0, 0,
+ 0,0xECAC, 0,0xC06F, 0,0xECA7,0xC06B, 0,
+0xECA4,0xECAA,0xECAD, 0,0xC070, 0,0xECA9,0xECA6,
+0xECAE,0xECA5, 0,0xECAB,0xC06C, 0,0xECA3,0xC06D,
+ 0,0xC06E,0xECA8, 0, 0, 0,0xEFA9,0xEF7A,
+0xEF7B,0xEF7E,0xEF7C, 0,0xEF76, 0, 0,0xEF79,
+0xEFA5,0xEF7D, 0, 0,0xC245, 0,0xEFA7,0xEFA4,
+0xC246,0xEFA6,0xEF77,0xEFA2,0xEFA3, 0,0xEFA1, 0,
+ 0, 0, 0,0xF1D2,0xF1D4,0xF1D7, 0, 0,
+0xF1D1, 0,0xC359,0xF1D9,0xF1D0,0xF1DA, 0,0xF1D6,
+0xF1D8,0xF1DC,0xF1D5,0xF1DD,0xF1D3,0xF1CF,0xC35A, 0,
+0xF1DB,0xC35B,0xC44D, 0, 0, 0, 0, 0,
+0xEF78,0xF3F1,0xF3E8,0xC44F,0xF3E4,0xC450, 0, 0,
+0xF3ED,0xF3E7,0xF3DD,0xC44E,0xF3EA,0xF3E5,0xF3E6, 0,
+0xF3D8,0xF3DF,0xF3EE, 0,0xF3EB, 0,0xF3E3, 0,
+0xF3EF,0xF3DE,0xF3D9,0xF3EC, 0,0xF3DB,0xF3E9,0xF3E0,
+0xF3F0,0xF3DC,0xC44C,0xF3DA,0xF3E1,0xF3E2, 0, 0,
+ 0,0xF57D, 0,0xF57B, 0,0xF5A2, 0,0xF5AE,
+0xF5A5,0xF57C,0xF578,0xF5A7,0xF57E,0xF5A3,0xF57A,0xF5AA,
+0xF577,0xF5A1,0xF5A6,0xF5A8,0xF5AB,0xF579, 0,0xF5AF,
+0xF5B0,0xF5A9,0xF5AD,0xF5A4, 0,0xF6C1,0xF6C4, 0,
+0xC561, 0,0xF6C3,0xF6C8,0xF6C6,0xC562,0xF6BD,0xF6B3,
+0xF6B2,0xC564,0xF6BF,0xF6C0,0xF6BC,0xF6B4, 0,0xF6B9,
+0xF5AC, 0,0xF6B5,0xC563,0xF6BB, 0,0xF6BA, 0,
+0xF6B6,0xF6C2, 0,0xF6B7,0xF7BB,0xF6C5,0xF6C7,0xF6BE,
+0xF6B8,0xF7BC,0xF7BE,0xF7B8,0xC5C2, 0,0xF7C5,0xF7C3,
+0xC5C3,0xF7C2,0xF7C1,0xF7BA,0xF7B7,0xF7BD,0xF7C6,0xF7B9,
+0xF7BF, 0,0xF869,0xF86E,0xF864,0xF867,0xC5EE,0xF86B,
+ 0,0xF872,0xF7C0, 0,0xF865,0xF86F,0xF873,0xF86A,
+0xF863,0xF86D, 0,0xF86C,0xF871,0xF870,0xF7C4,0xF868,
+0xF862,0xF866,0xC64E,0xC64F,0xF861, 0,0xF8E6,0xF8DD,
+0xF8E5,0xF8E2,0xF8E3,0xF8DC,0xF8DF,0xF8E7,0xF8E1,0xF8E0,
+0xF8DE, 0,0xF8E4, 0,0xF95D, 0,0xF95E, 0,
+0xF960,0xF95F,0xF962,0xF961,0xF97C,0xF97B,0xF9B7, 0,
+0xF9B8, 0,0xF9C5,0xC678,0xC67C, 0,0xF9CF,0xC67D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB3BF, 0,
+ 0, 0,0xC4D0,0xF6C9, 0,0xC650,0xC651, 0,
+0xB3C0,0xE0EE, 0,0xB9A8,0xE8F0, 0, 0,0xECB0,
+0xECB1,0xECAF,0xEFAB,0xEFAA,0xC247,0xF1DF,0xEFAC,0xF1DE,
+ 0, 0,0xF3F3,0xC451,0xC453,0xF3F2, 0, 0,
+0xC452, 0,0xF5B1,0xF5B3,0xF5B2,0xF6CA,0xC565, 0,
+0xC5EF,0xF8E8,0xF963, 0, 0,0xF9D2,0xB3C1, 0,
+0xE4E5, 0,0xBEA2, 0, 0, 0,0xECB3,0xECB2,
+ 0,0xEFAD, 0, 0, 0,0xC454,0xC4D1,0xF7C7,
+0xF9CB, 0, 0, 0,0xB3C2,0xBBF2, 0,0xBEA3,
+ 0,0xF3F4, 0,0xF874,0xB6C0, 0, 0, 0,
+ 0,0xEFAE, 0, 0, 0,0xC664,0xB6C1,0xBEA4,
+0xC248,0xF875,0xB6C2, 0,0xE8F1,0xC072,0xECB4,0xECB5,
+ 0,0xC071, 0,0xEFAF,0xC24C,0xC24A,0xC24B,0xC249,
+0xF1E0,0xC35C, 0, 0, 0,0xF5B5,0xF5B4,0xF5B7,
+0xF5B6,0xC4D2, 0, 0,0xF6CB, 0,0xF6CD,0xF6CC,
+0xC566,0xF7C8, 0,0xF876,0xF877,0xC5F0,0xF964,0xF97D,
+0xC675, 0,0xDCB0,0xECB6,0xEFB0,0xF3F5,0xE0EF, 0,
+0xEFB1,0xF1E2,0xF1E1, 0, 0, 0, 0,0xF878,
+0xC652, 0,0xF965,0xF97E, 0, 0, 0,0xB9A9,
+0xE8F2,0xE8F3, 0,0xECB7,0xB9AA, 0,0xC35D,0xF1E3,
+ 0,0xF6CF,0xC567,0xF6D0,0xF6CE,0xF879, 0,0xF8E9,
+ 0,0xB9AB, 0,0xEFB4,0xEFB3,0xEFB2,0xF1E4, 0,
+ 0,0xF1E8,0xF1E7,0xF1E6,0xF1E5,0xC35E,0xF3F6,0xF5B9,
+0xC4D3,0xF5B8,0xF6D1,0xF7CB,0xF7CA,0xC5C4,0xF7C9,0xF87C,
+0xF87B,0xF87A, 0, 0,0xBBF3, 0,0xECB8,0xC24D,
+ 0,0xF3F7,0xF3F8,0xF7CC,0xF87D, 0, 0,0xF8EA,
+0xF966,0xF9B9,0xF9D4,0xBBF4,0xC24E,0xF1E9,0xF3F9,0xF6D2,
+0xF87E, 0, 0,0xBEA6, 0,0xEFB5,0xF1EA,0xF3FA,
+0xF3FB,0xF3FC,0xF5BE, 0,0xF5BA,0xC568,0xF5BD,0xF5BC,
+0xC4D4,0xF5BB,0xC4D6, 0,0xC4D5,0xF6D4,0xF6D3,0xC569,
+0xC56A, 0, 0,0xC5C6,0xF7CD,0xC5C5, 0,0xF8A3,
+0xF8A4,0xF8A2,0xF8A1,0xC654, 0,0xF8EB,0xF8EC,0xF8ED,
+0xC653,0xF967,0xF96A,0xF969,0xF968, 0, 0,0xF9D3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC073, 0,
+ 0,0xC365,0xF5BF,0xF6D5, 0,0xC5C7,0xF7CE, 0,
+ 0,0xF9D5, 0, 0, 0,0xC074, 0, 0,
+ 0,0xEFB6, 0,0xF7CF, 0,0xF9A1};
+
+/* page 9 0xFA0C-0xFA0D */
+static uint16 tab_uni_big59[]={
+0xC94A,0xDDFC};
+
+/* page 10 0xFE30-0xFFFD */
+static uint16 tab_uni_big510[]={
+0xA14A,0xA157, 0,0xA159,0xA15B,0xA15F,0xA160,0xA163,
+0xA164,0xA167,0xA168,0xA16B,0xA16C,0xA16F,0xA170,0xA173,
+0xA174,0xA177,0xA178,0xA17B,0xA17C, 0, 0, 0,
+ 0,0xA1C6,0xA1C7,0xA1CA,0xA1CB,0xA1C8,0xA1C9,0xA15C,
+0xA14D, 0,0xA14F, 0,0xA151,0xA152,0xA153,0xA154,
+ 0,0xA17D,0xA17E,0xA1A1,0xA1A2,0xA1A3,0xA1A4,0xA1CC,
+0xA1CD,0xA1CE,0xA1DE,0xA1DF,0xA1E0,0xA1E1,0xA1E2, 0,
+ 0,0xA24C,0xA24D,0xA24E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA149, 0,0xA1AD,0xA243,0xA248,0xA1AE, 0,
+0xA15D,0xA15E,0xA1AF,0xA1CF,0xA141,0xA1D0,0xA144,0xA241,
+0xA2AF,0xA2B0,0xA2B1,0xA2B2,0xA2B3,0xA2B4,0xA2B5,0xA2B6,
+0xA2B7,0xA2B8,0xA147,0xA146,0xA1D5,0xA1D7,0xA1D6,0xA148,
+0xA249,0xA2CF,0xA2D0,0xA2D1,0xA2D2,0xA2D3,0xA2D4,0xA2D5,
+0xA2D6,0xA2D7,0xA2D8,0xA2D9,0xA2DA,0xA2DB,0xA2DC,0xA2DD,
+0xA2DE,0xA2DF,0xA2E0,0xA2E1,0xA2E2,0xA2E3,0xA2E4,0xA2E5,
+0xA2E6,0xA2E7,0xA2E8, 0,0xA242, 0, 0,0xA1C4,
+ 0,0xA2E9,0xA2EA,0xA2EB,0xA2EC,0xA2ED,0xA2EE,0xA2EF,
+0xA2F0,0xA2F1,0xA2F2,0xA2F3,0xA2F4,0xA2F5,0xA2F6,0xA2F7,
+0xA2F8,0xA2F9,0xA2FA,0xA2FB,0xA2FC,0xA2FD,0xA2FE,0xA340,
+0xA341,0xA342,0xA343,0xA161,0xA155,0xA162, 0, 0,
+ 0, 0, 0, 0,0xA14E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA2CE};
+
+static int func_uni_big5_onechar(int code){
+ if ((code>=0x00A2)&&(code<=0x00F7))
+ return(tab_uni_big50[code-0x00A2]);
+ if ((code>=0x02C7)&&(code<=0x0451))
+ return(tab_uni_big51[code-0x02C7]);
+ if ((code>=0x2013)&&(code<=0x22BF))
+ return(tab_uni_big52[code-0x2013]);
+ if ((code>=0x2460)&&(code<=0x2642))
+ return(tab_uni_big53[code-0x2460]);
+ if ((code>=0x3000)&&(code<=0x3129))
+ return(tab_uni_big54[code-0x3000]);
+ if ((code>=0x32A3)&&(code<=0x32A3))
+ return(tab_uni_big55[code-0x32A3]);
+ if ((code>=0x338E)&&(code<=0x33D5))
+ return(tab_uni_big56[code-0x338E]);
+ if ((code>=0x4E00)&&(code<=0x9483))
+ return(tab_uni_big57[code-0x4E00]);
+ if ((code>=0x9577)&&(code<=0x9FA4))
+ return(tab_uni_big58[code-0x9577]);
+ if ((code>=0xFA0C)&&(code<=0xFA0D))
+ return(tab_uni_big59[code-0xFA0C]);
+ if ((code>=0xFE30)&&(code<=0xFFFD))
+ return(tab_uni_big510[code-0xFE30]);
+ return(0);
+}
+
+
+static int
+my_wc_mb_big5(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, unsigned char *s, unsigned char *e)
+{
+
+ int code;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if(wc<0x80)
+ {
+ s[0]=wc;
+ return 1;
+ }
+
+ if(!(code=func_uni_big5_onechar(wc)))
+ return MY_CS_ILUNI;
+
+ if(s+2>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=code>>8;
+ s[1]=code&0xFF;
+
+ return 2;
+}
+
+static int
+my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *pwc,const uchar *s,const uchar *e)
+{
+
+ int hi=s[0];
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ if(hi<0x80)
+ {
+ pwc[0]=hi;
+ return 1;
+ }
+
+ if(s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ if(!(pwc[0]=func_big5_uni_onechar((hi<<8)+s[1])))
+ return MY_CS_ILSEQ;
+
+ return 2;
+}
+
+CHARSET_INFO my_charset_big5 =
+{
+ 1, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ "big5", /* cs name */
+ "big5", /* name */
+ "", /* comment */
+ ctype_big5,
+ to_lower_big5,
+ to_upper_big5,
+ sort_order_big5,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 1, /* strxfrm_multiply */
+ my_strnncoll_big5,
+ my_strnncollsp_big5,
+ my_strnxfrm_big5,
+ my_like_range_big5,
+ my_wildcmp_mb,
+ 2, /* mbmaxlen */
+ ismbchar_big5,
+ ismbhead_big5,
+ mbcharlen_big5,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_mb_wc_big5, /* mb_wc */
+ my_wc_mb_big5, /* wc_mb */
+ my_caseup_str_mb,
+ my_casedn_str_mb,
+ my_caseup_mb,
+ my_casedn_mb,
+ NULL, /* tosort */
+ my_strcasecmp_mb,
+ my_strncasecmp_mb,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+
+#endif
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
new file mode 100644
index 00000000000..c219bd95fd4
--- /dev/null
+++ b/strings/ctype-bin.c
@@ -0,0 +1,343 @@
+/* Copyright (C) 2002 MySQL AB & tommy@valley.ne.jp.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library 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 */
+
+/* This file is for binary pseudo charset, created by bar@mysql.com */
+
+
+#include <my_global.h>
+#include "m_string.h"
+#include "m_ctype.h"
+
+static uchar ctype_bin[]=
+{
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+
+/* Dummy array for toupper / tolower / sortorder */
+
+static uchar bin_char_array[] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+
+static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ int cmp= memcmp(s,t,min(slen,tlen));
+ return cmp ? cmp : (int) (slen - tlen);
+}
+
+static void my_caseup_str_bin(CHARSET_INFO *cs __attribute__((unused)),
+ char *str __attribute__((unused)))
+{
+}
+
+static void my_casedn_str_bin(CHARSET_INFO * cs __attribute__((unused)),
+ char *str __attribute__((unused)))
+{
+}
+
+static void my_caseup_bin(CHARSET_INFO * cs __attribute__((unused)),
+ char *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+}
+
+static void my_casedn_bin(CHARSET_INFO * cs __attribute__((unused)),
+ char *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+}
+
+static void my_tosort_bin(CHARSET_INFO * cs __attribute__((unused)),
+ char *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+}
+
+static int my_strcasecmp_bin(CHARSET_INFO * cs __attribute__((unused)),
+ const char *s, const char *t)
+{
+ return strcmp(s,t);
+}
+
+static int my_strncasecmp_bin(CHARSET_INFO * cs __attribute__((unused)),
+ const char *s, const char *t, uint len)
+{
+ return memcmp(s,t,len);
+}
+
+static int my_mb_wc_bin(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *wc,
+ const unsigned char *str,
+ const unsigned char *end __attribute__((unused)))
+{
+ if (str >= end)
+ return MY_CS_TOOFEW(0);
+
+ *wc=str[0];
+ return 1;
+}
+
+static int my_wc_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc,
+ unsigned char *s,
+ unsigned char *e __attribute__((unused)))
+{
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if (wc < 256)
+ {
+ s[0]= (char) wc;
+ return 1;
+ }
+ return MY_CS_ILUNI;
+}
+
+
+#ifndef NEW_HASH_FUNCTION
+
+ /* Calc hashvalue for a key, case indepenently */
+
+static uint my_hash_caseup_bin(CHARSET_INFO *cs __attribute__((unused)),
+ const byte *key, uint length)
+{
+ register uint nr=1, nr2=4;
+
+ while (length--)
+ {
+ nr^= (((nr & 63)+nr2)*
+ ((uint) (uchar) *key++)) + (nr << 8);
+ nr2+=3;
+ }
+ return((uint) nr);
+}
+
+#else
+
+static uint my_hash_caseup_bin(CHARSET_INFO *cs __attribute__((unused)),
+ const byte *key, uint len)
+{
+ const byte *end=key+len;
+ uint hash;
+ for (hash = 0; key < end; key++)
+ {
+ hash *= 16777619;
+ hash ^= (uint) (uchar) *key;
+ }
+ return (hash);
+}
+
+#endif
+
+void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *key, uint len,ulong *nr1, ulong *nr2)
+{
+ const uchar *pos = key;
+
+ key+= len;
+
+ for (; pos < (uchar*) key ; pos++)
+ {
+ nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
+ ((uint)*pos)) + (nr1[0] << 8);
+ nr2[0]+=3;
+ }
+}
+
+
+static int my_wildcmp_bin(CHARSET_INFO *cs,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many)
+{
+ int result= -1; // Not found, using wildcards
+
+ while (wildstr != wildend)
+ {
+ while (*wildstr != w_many && *wildstr != w_one)
+ {
+ if (*wildstr == escape && wildstr+1 != wildend)
+ wildstr++;
+ if (str == str_end || *wildstr++ != *str++)
+ {
+ return(1);
+ }
+ if (wildstr == wildend)
+ {
+ return(str != str_end); // Match if both are at end
+ }
+ result=1; // Found an anchor char
+ }
+ if (*wildstr == w_one)
+ {
+ do
+ {
+ if (str == str_end) // Skip one char if possible
+ return(result);
+ str++;
+ } while (*++wildstr == w_one && wildstr != wildend);
+ if (wildstr == wildend)
+ break;
+ }
+ if (*wildstr == w_many)
+ { // Found w_many
+ char cmp;
+
+ wildstr++;
+ /* Remove any '%' and '_' from the wild search string */
+ for (; wildstr != wildend ; wildstr++)
+ {
+ if (*wildstr == w_many)
+ continue;
+ if (*wildstr == w_one)
+ {
+ if (str == str_end)
+ {
+ return(-1);
+ }
+ str++;
+ continue;
+ }
+ break; // Not a wild character
+ }
+ if (wildstr == wildend)
+ {
+ return(0); // Ok if w_many is last
+ }
+ if (str == str_end)
+ {
+ return(-1);
+ }
+
+ if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
+ cmp= *++wildstr;
+ wildstr++; // This is compared trough cmp
+ do
+ {
+ while (str != str_end && *str != cmp)
+ str++;
+ if (str++ == str_end)
+ {
+ return(-1);
+ }
+ {
+ int tmp=my_wildcmp_bin(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);
+ if (tmp <= 0)
+ {
+ return(tmp);
+ }
+ }
+ } while (str != str_end && wildstr[0] != w_many);
+ return(-1);
+ }
+ }
+ return(str != str_end ? 1 : 0);
+}
+
+static int my_strnxfrm_bin(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar *src,
+ uint srclen __attribute__((unused)))
+{
+ memcpy(dest,src,len= min(len,srclen));
+ return len;
+}
+
+CHARSET_INFO my_charset_bin =
+{
+ 63, /* number */
+ MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_PRIMARY,/* state */
+ "binary", /* cs name */
+ "binary", /* name */
+ "", /* comment */
+ ctype_bin, /* ctype */
+ bin_char_array, /* to_lower */
+ bin_char_array, /* to_upper */
+ bin_char_array, /* sort_order */
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_binary, /* strnncoll */
+ my_strnncoll_binary,
+ my_strnxfrm_bin, /* strxnfrm */
+ my_like_range_simple, /* like_range */
+ my_wildcmp_bin, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_bin, /* mb_wc */
+ my_wc_mb_bin, /* wc_mb */
+ my_caseup_str_bin, /* caseup_str */
+ my_casedn_str_bin, /* casedn_str */
+ my_caseup_bin, /* caseup */
+ my_casedn_bin, /* casedn */
+ my_tosort_bin, /* tosort */
+ my_strcasecmp_bin, /* strcasecmp */
+ my_strncasecmp_bin, /* strncasecmp */
+ my_hash_caseup_bin, /* hash_caseup */
+ my_hash_sort_bin, /* hash_sort */
+ (char) 255, /* max_sort_char */
+ my_snprintf_8bit, /* snprintf */
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 70f95e0d5d6..f42ab66fed9 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -68,6 +68,7 @@
#include <my_global.h>
#include "m_string.h"
+#include "m_ctype.h"
#else
@@ -76,6 +77,8 @@
#endif
+#ifdef HAVE_CHARSET_czech
+
/*
These are four tables for four passes of the algorithm. Please see
below for what are the "special values"
@@ -230,8 +233,9 @@ static struct wordvalue doubles[] = {
#define IS_END(p, src, len) (!(*p))
+#if 0
/* Function strcoll, with Czech sorting, for zero terminated strings */
-int my_strcoll_czech(const uchar * s1, const uchar * s2)
+static int my_strcoll_czech(const uchar * s1, const uchar * s2)
{
int v1, v2;
const uchar * p1, * p2, * store1, * store2;
@@ -251,9 +255,11 @@ int my_strcoll_czech(const uchar * s1, const uchar * s2)
while (v1);
return 0;
}
+#endif
+#if 0
/* Function strxfrm, with Czech sorting, for zero terminated strings */
-int my_strxfrm_czech(uchar * dest, const uchar * src, int len)
+static int my_strxfrm_czech(uchar * dest, const uchar * src, int len)
{
int value;
const uchar * p, * store;
@@ -269,17 +275,18 @@ int my_strxfrm_czech(uchar * dest, const uchar * src, int len)
while (value);
return totlen;
}
-
-#undef IS_END
-
+#endif
+#undef IS_END
#define IS_END(p, src, len) (((char *)p - (char *)src) >= (len))
/* Function strnncoll, actually strcoll, with Czech sorting, which expect
the length of the strings being specified */
-int my_strnncoll_czech(const uchar * s1, int len1, const uchar * s2, int len2)
+static int my_strnncoll_czech(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar * s1, uint len1,
+ const uchar * s2, uint len2)
{
int v1, v2;
const uchar * p1, * p2, * store1, * store2;
@@ -291,8 +298,8 @@ int my_strnncoll_czech(const uchar * s1, int len1, const uchar * s2, int len2)
do
{
- NEXT_CMP_VALUE(s1, p1, store1, pass1, v1, len1);
- NEXT_CMP_VALUE(s2, p2, store2, pass2, v2, len2);
+ NEXT_CMP_VALUE(s1, p1, store1, pass1, v1, (int)len1);
+ NEXT_CMP_VALUE(s2, p2, store2, pass2, v2, (int)len2);
diff = v1 - v2;
if (diff != 0) return diff;
@@ -303,7 +310,9 @@ int my_strnncoll_czech(const uchar * s1, int len1, const uchar * s2, int len2)
/* Function strnxfrm, actually strxfrm, with Czech sorting, which expect
the length of the strings being specified */
-int my_strnxfrm_czech(uchar * dest, const uchar * src, int len, int srclen)
+static int my_strnxfrm_czech(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar * src, uint srclen)
{
int value;
const uchar * p, * store;
@@ -313,8 +322,8 @@ int my_strnxfrm_czech(uchar * dest, const uchar * src, int len, int srclen)
do
{
- NEXT_CMP_VALUE(src, p, store, pass, value, srclen);
- ADD_TO_RESULT(dest, len, totlen, value);
+ NEXT_CMP_VALUE(src, p, store, pass, value, (int)srclen);
+ ADD_TO_RESULT(dest, (int)len, totlen, value);
}
while (value);
return totlen;
@@ -366,12 +375,12 @@ int my_strnxfrm_czech(uchar * dest, const uchar * src, int len, int srclen)
#define min_sort_char ' '
#define max_sort_char '9'
-#define wild_one '_'
-#define wild_many '%'
#define EXAMPLE
-my_bool my_like_range_czech(const char *ptr,uint ptr_length,pchar escape,
+static my_bool my_like_range_czech(CHARSET_INFO *cs __attribute__((unused)),
+ const char *ptr,uint ptr_length,
+ int escape, int w_one, int w_many,
uint res_length, char *min_str,char *max_str,
uint *min_length,uint *max_length)
{
@@ -383,9 +392,9 @@ my_bool my_like_range_czech(const char *ptr,uint ptr_length,pchar escape,
for (; ptr != end && min_str != min_end ; ptr++)
{
- if (*ptr == wild_one) /* '_' in SQL */
+ if (*ptr == w_one) /* '_' in SQL */
{ break; }
- if (*ptr == wild_many) /* '%' in SQL */
+ if (*ptr == w_many) /* '%' in SQL */
{ break; }
if (*ptr == escape && ptr+1 != end)
@@ -429,7 +438,7 @@ my_bool my_like_range_czech(const char *ptr,uint ptr_length,pchar escape,
#include <my_global.h>
#include "m_string.h"
-uchar NEAR ctype_czech[257] = {
+static uchar NEAR ctype_czech[257] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@@ -449,7 +458,7 @@ uchar NEAR ctype_czech[257] = {
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 16,
};
-uchar NEAR to_lower_czech[] = {
+static uchar NEAR to_lower_czech[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -468,7 +477,7 @@ uchar NEAR to_lower_czech[] = {
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
};
-uchar NEAR to_upper_czech[] = {
+static uchar NEAR to_upper_czech[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -487,7 +496,7 @@ uchar NEAR to_upper_czech[] = {
240,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255,
};
-uchar NEAR sort_order_czech[] = {
+static uchar NEAR sort_order_czech[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -506,4 +515,145 @@ uchar NEAR sort_order_czech[] = {
255, 98, 99,101,102,103,104,255,109,119,118,120,121,126,116,255,
};
+static uint16 tab_8859_2_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+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
+};
+
+
+/* 0000-00FD , 254 chars */
+static uchar tab_uni_8859_2_plane00[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0x00,0x00,0x00,0xA4,0x00,0x00,0xA7,0xA8,0x00,0x00,0x00,0x00,0xAD,0x00,0x00,
+0xB0,0x00,0x00,0x00,0xB4,0x00,0x00,0x00,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xC1,0xC2,0x00,0xC4,0x00,0x00,0xC7,0x00,0xC9,0x00,0xCB,0x00,0xCD,0xCE,0x00,
+0x00,0x00,0x00,0xD3,0xD4,0x00,0xD6,0xD7,0x00,0x00,0xDA,0x00,0xDC,0xDD,0x00,0xDF,
+0x00,0xE1,0xE2,0x00,0xE4,0x00,0x00,0xE7,0x00,0xE9,0x00,0xEB,0x00,0xED,0xEE,0x00,
+0x00,0x00,0x00,0xF3,0xF4,0x00,0xF6,0xF7,0x00,0x00,0xFA,0x00,0xFC,0xFD};
+
+/* 0102-017E , 125 chars */
+static uchar tab_uni_8859_2_plane01[]={
+0xC3,0xE3,0xA1,0xB1,0xC6,0xE6,0x00,0x00,0x00,0x00,0xC8,0xE8,0xCF,0xEF,0xD0,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xE5,0x00,0x00,0xA5,0xB5,0x00,0x00,0xA3,
+0xB3,0xD1,0xF1,0x00,0x00,0xD2,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD5,0xF5,
+0x00,0x00,0xC0,0xE0,0x00,0x00,0xD8,0xF8,0xA6,0xB6,0x00,0x00,0xAA,0xBA,0xA9,0xB9,
+0xDE,0xFE,0xAB,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xF9,0xDB,0xFB,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0xBC,0xAF,0xBF,0xAE,0xBE};
+
+/* 02C7-02DD , 23 chars */
+static uchar tab_uni_8859_2_plane02[]={
+0xB7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xA2,0xFF,0x00,0xB2,0x00,0xBD};
+
+static MY_UNI_IDX idx_uni_8859_2[]={
+ {0x0000,0x00FD,tab_uni_8859_2_plane00},
+ {0x0102,0x017E,tab_uni_8859_2_plane01},
+ {0x02C7,0x02DD,tab_uni_8859_2_plane02},
+ {0,0,NULL}
+};
+
+
+static
+int my_strnncollsp_czech(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_czech(cs,s,slen,t,tlen);
+}
+
+
+CHARSET_INFO my_charset_czech =
+{
+ 2, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */
+ "latin2", /* cs name */
+ "czech", /* name */
+ "", /* comment */
+ ctype_czech,
+ to_lower_czech,
+ to_upper_czech,
+ sort_order_czech,
+ tab_8859_2_uni, /* tab_to_uni */
+ idx_uni_8859_2, /* tab_from_uni */
+ 4, /* strxfrm_multiply */
+ my_strnncoll_czech,
+ my_strnncollsp_czech,
+ my_strnxfrm_czech,
+ my_like_range_czech,
+ my_wildcmp_8bit,
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ NULL, /* tosort */
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+#endif
+
#endif
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index d05ca518283..e49bf6a38fd 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -28,8 +28,12 @@
#include <my_global.h>
#include "m_string.h"
+#include "m_ctype.h"
-uchar NEAR ctype_euc_kr[257] =
+#ifdef HAVE_CHARSET_euc_kr
+
+
+static uchar NEAR ctype_euc_kr[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -66,7 +70,7 @@ uchar NEAR ctype_euc_kr[257] =
0020, 0020, 0020, 0020, 0020, 0020, 0020, 0000,
};
-uchar NEAR to_lower_euc_kr[]=
+static uchar NEAR to_lower_euc_kr[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -102,7 +106,7 @@ uchar NEAR to_lower_euc_kr[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR to_upper_euc_kr[]=
+static uchar NEAR to_upper_euc_kr[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -138,7 +142,7 @@ uchar NEAR to_upper_euc_kr[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR sort_order_euc_kr[]=
+static uchar NEAR sort_order_euc_kr[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -179,19 +183,8509 @@ uchar NEAR sort_order_euc_kr[]=
#define iseuc_kr(c) ((0xa1<=(uchar)(c) && (uchar)(c)<=0xfe))
-int ismbchar_euc_kr(const char* p, const char *e)
+static int ismbchar_euc_kr(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
{
return ((*(uchar*)(p)<0x80)? 0:\
iseuc_kr(*(p)) && (e)-(p)>1 && iseuc_kr(*((p)+1))? 2:\
0);
}
-my_bool ismbhead_euc_kr(uint c)
+static my_bool ismbhead_euc_kr(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (iseuc_kr(c));
}
-int mbcharlen_euc_kr(uint c)
+static int mbcharlen_euc_kr(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (iseuc_kr(c) ? 2 : 0);
}
+
+
+/* page 0 0x8141-0xC8FE */
+static uint16 tab_ksc5601_uni0[]={
+0xAC02,0xAC03,0xAC05,0xAC06,0xAC0B,0xAC0C,0xAC0D,0xAC0E,
+0xAC0F,0xAC18,0xAC1E,0xAC1F,0xAC21,0xAC22,0xAC23,0xAC25,
+0xAC26,0xAC27,0xAC28,0xAC29,0xAC2A,0xAC2B,0xAC2E,0xAC32,
+0xAC33,0xAC34, 0, 0, 0, 0, 0, 0,
+0xAC35,0xAC36,0xAC37,0xAC3A,0xAC3B,0xAC3D,0xAC3E,0xAC3F,
+0xAC41,0xAC42,0xAC43,0xAC44,0xAC45,0xAC46,0xAC47,0xAC48,
+0xAC49,0xAC4A,0xAC4C,0xAC4E,0xAC4F,0xAC50,0xAC51,0xAC52,
+0xAC53,0xAC55, 0, 0, 0, 0, 0, 0,
+0xAC56,0xAC57,0xAC59,0xAC5A,0xAC5B,0xAC5D,0xAC5E,0xAC5F,
+0xAC60,0xAC61,0xAC62,0xAC63,0xAC64,0xAC65,0xAC66,0xAC67,
+0xAC68,0xAC69,0xAC6A,0xAC6B,0xAC6C,0xAC6D,0xAC6E,0xAC6F,
+0xAC72,0xAC73,0xAC75,0xAC76,0xAC79,0xAC7B,0xAC7C,0xAC7D,
+0xAC7E,0xAC7F,0xAC82,0xAC87,0xAC88,0xAC8D,0xAC8E,0xAC8F,
+0xAC91,0xAC92,0xAC93,0xAC95,0xAC96,0xAC97,0xAC98,0xAC99,
+0xAC9A,0xAC9B,0xAC9E,0xACA2,0xACA3,0xACA4,0xACA5,0xACA6,
+0xACA7,0xACAB,0xACAD,0xACAE,0xACB1,0xACB2,0xACB3,0xACB4,
+0xACB5,0xACB6,0xACB7,0xACBA,0xACBE,0xACBF,0xACC0,0xACC2,
+0xACC3,0xACC5,0xACC6,0xACC7,0xACC9,0xACCA,0xACCB,0xACCD,
+0xACCE,0xACCF,0xACD0,0xACD1,0xACD2,0xACD3,0xACD4,0xACD6,
+0xACD8,0xACD9,0xACDA,0xACDB,0xACDC,0xACDD,0xACDE,0xACDF,
+0xACE2,0xACE3,0xACE5,0xACE6,0xACE9,0xACEB,0xACED,0xACEE,
+0xACF2,0xACF4,0xACF7,0xACF8,0xACF9,0xACFA,0xACFB,0xACFE,
+0xACFF,0xAD01,0xAD02,0xAD03,0xAD05,0xAD07,0xAD08,0xAD09,
+0xAD0A,0xAD0B,0xAD0E,0xAD10,0xAD12,0xAD13, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xAD14,0xAD15,0xAD16,0xAD17,0xAD19,0xAD1A,0xAD1B,0xAD1D,
+0xAD1E,0xAD1F,0xAD21,0xAD22,0xAD23,0xAD24,0xAD25,0xAD26,
+0xAD27,0xAD28,0xAD2A,0xAD2B,0xAD2E,0xAD2F,0xAD30,0xAD31,
+0xAD32,0xAD33, 0, 0, 0, 0, 0, 0,
+0xAD36,0xAD37,0xAD39,0xAD3A,0xAD3B,0xAD3D,0xAD3E,0xAD3F,
+0xAD40,0xAD41,0xAD42,0xAD43,0xAD46,0xAD48,0xAD4A,0xAD4B,
+0xAD4C,0xAD4D,0xAD4E,0xAD4F,0xAD51,0xAD52,0xAD53,0xAD55,
+0xAD56,0xAD57, 0, 0, 0, 0, 0, 0,
+0xAD59,0xAD5A,0xAD5B,0xAD5C,0xAD5D,0xAD5E,0xAD5F,0xAD60,
+0xAD62,0xAD64,0xAD65,0xAD66,0xAD67,0xAD68,0xAD69,0xAD6A,
+0xAD6B,0xAD6E,0xAD6F,0xAD71,0xAD72,0xAD77,0xAD78,0xAD79,
+0xAD7A,0xAD7E,0xAD80,0xAD83,0xAD84,0xAD85,0xAD86,0xAD87,
+0xAD8A,0xAD8B,0xAD8D,0xAD8E,0xAD8F,0xAD91,0xAD92,0xAD93,
+0xAD94,0xAD95,0xAD96,0xAD97,0xAD98,0xAD99,0xAD9A,0xAD9B,
+0xAD9E,0xAD9F,0xADA0,0xADA1,0xADA2,0xADA3,0xADA5,0xADA6,
+0xADA7,0xADA8,0xADA9,0xADAA,0xADAB,0xADAC,0xADAD,0xADAE,
+0xADAF,0xADB0,0xADB1,0xADB2,0xADB3,0xADB4,0xADB5,0xADB6,
+0xADB8,0xADB9,0xADBA,0xADBB,0xADBC,0xADBD,0xADBE,0xADBF,
+0xADC2,0xADC3,0xADC5,0xADC6,0xADC7,0xADC9,0xADCA,0xADCB,
+0xADCC,0xADCD,0xADCE,0xADCF,0xADD2,0xADD4,0xADD5,0xADD6,
+0xADD7,0xADD8,0xADD9,0xADDA,0xADDB,0xADDD,0xADDE,0xADDF,
+0xADE1,0xADE2,0xADE3,0xADE5,0xADE6,0xADE7,0xADE8,0xADE9,
+0xADEA,0xADEB,0xADEC,0xADED,0xADEE,0xADEF,0xADF0,0xADF1,
+0xADF2,0xADF3,0xADF4,0xADF5,0xADF6,0xADF7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xADFA,0xADFB,0xADFD,0xADFE,0xAE02,0xAE03,0xAE04,0xAE05,
+0xAE06,0xAE07,0xAE0A,0xAE0C,0xAE0E,0xAE0F,0xAE10,0xAE11,
+0xAE12,0xAE13,0xAE15,0xAE16,0xAE17,0xAE18,0xAE19,0xAE1A,
+0xAE1B,0xAE1C, 0, 0, 0, 0, 0, 0,
+0xAE1D,0xAE1E,0xAE1F,0xAE20,0xAE21,0xAE22,0xAE23,0xAE24,
+0xAE25,0xAE26,0xAE27,0xAE28,0xAE29,0xAE2A,0xAE2B,0xAE2C,
+0xAE2D,0xAE2E,0xAE2F,0xAE32,0xAE33,0xAE35,0xAE36,0xAE39,
+0xAE3B,0xAE3C, 0, 0, 0, 0, 0, 0,
+0xAE3D,0xAE3E,0xAE3F,0xAE42,0xAE44,0xAE47,0xAE48,0xAE49,
+0xAE4B,0xAE4F,0xAE51,0xAE52,0xAE53,0xAE55,0xAE57,0xAE58,
+0xAE59,0xAE5A,0xAE5B,0xAE5E,0xAE62,0xAE63,0xAE64,0xAE66,
+0xAE67,0xAE6A,0xAE6B,0xAE6D,0xAE6E,0xAE6F,0xAE71,0xAE72,
+0xAE73,0xAE74,0xAE75,0xAE76,0xAE77,0xAE7A,0xAE7E,0xAE7F,
+0xAE80,0xAE81,0xAE82,0xAE83,0xAE86,0xAE87,0xAE88,0xAE89,
+0xAE8A,0xAE8B,0xAE8D,0xAE8E,0xAE8F,0xAE90,0xAE91,0xAE92,
+0xAE93,0xAE94,0xAE95,0xAE96,0xAE97,0xAE98,0xAE99,0xAE9A,
+0xAE9B,0xAE9C,0xAE9D,0xAE9E,0xAE9F,0xAEA0,0xAEA1,0xAEA2,
+0xAEA3,0xAEA4,0xAEA5,0xAEA6,0xAEA7,0xAEA8,0xAEA9,0xAEAA,
+0xAEAB,0xAEAC,0xAEAD,0xAEAE,0xAEAF,0xAEB0,0xAEB1,0xAEB2,
+0xAEB3,0xAEB4,0xAEB5,0xAEB6,0xAEB7,0xAEB8,0xAEB9,0xAEBA,
+0xAEBB,0xAEBF,0xAEC1,0xAEC2,0xAEC3,0xAEC5,0xAEC6,0xAEC7,
+0xAEC8,0xAEC9,0xAECA,0xAECB,0xAECE,0xAED2,0xAED3,0xAED4,
+0xAED5,0xAED6,0xAED7,0xAEDA,0xAEDB,0xAEDD,0xAEDE,0xAEDF,
+0xAEE0,0xAEE1,0xAEE2,0xAEE3,0xAEE4,0xAEE5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xAEE6,0xAEE7,0xAEE9,0xAEEA,0xAEEC,0xAEEE,0xAEEF,0xAEF0,
+0xAEF1,0xAEF2,0xAEF3,0xAEF5,0xAEF6,0xAEF7,0xAEF9,0xAEFA,
+0xAEFB,0xAEFD,0xAEFE,0xAEFF,0xAF00,0xAF01,0xAF02,0xAF03,
+0xAF04,0xAF05, 0, 0, 0, 0, 0, 0,
+0xAF06,0xAF09,0xAF0A,0xAF0B,0xAF0C,0xAF0E,0xAF0F,0xAF11,
+0xAF12,0xAF13,0xAF14,0xAF15,0xAF16,0xAF17,0xAF18,0xAF19,
+0xAF1A,0xAF1B,0xAF1C,0xAF1D,0xAF1E,0xAF1F,0xAF20,0xAF21,
+0xAF22,0xAF23, 0, 0, 0, 0, 0, 0,
+0xAF24,0xAF25,0xAF26,0xAF27,0xAF28,0xAF29,0xAF2A,0xAF2B,
+0xAF2E,0xAF2F,0xAF31,0xAF33,0xAF35,0xAF36,0xAF37,0xAF38,
+0xAF39,0xAF3A,0xAF3B,0xAF3E,0xAF40,0xAF44,0xAF45,0xAF46,
+0xAF47,0xAF4A,0xAF4B,0xAF4C,0xAF4D,0xAF4E,0xAF4F,0xAF51,
+0xAF52,0xAF53,0xAF54,0xAF55,0xAF56,0xAF57,0xAF58,0xAF59,
+0xAF5A,0xAF5B,0xAF5E,0xAF5F,0xAF60,0xAF61,0xAF62,0xAF63,
+0xAF66,0xAF67,0xAF68,0xAF69,0xAF6A,0xAF6B,0xAF6C,0xAF6D,
+0xAF6E,0xAF6F,0xAF70,0xAF71,0xAF72,0xAF73,0xAF74,0xAF75,
+0xAF76,0xAF77,0xAF78,0xAF7A,0xAF7B,0xAF7C,0xAF7D,0xAF7E,
+0xAF7F,0xAF81,0xAF82,0xAF83,0xAF85,0xAF86,0xAF87,0xAF89,
+0xAF8A,0xAF8B,0xAF8C,0xAF8D,0xAF8E,0xAF8F,0xAF92,0xAF93,
+0xAF94,0xAF96,0xAF97,0xAF98,0xAF99,0xAF9A,0xAF9B,0xAF9D,
+0xAF9E,0xAF9F,0xAFA0,0xAFA1,0xAFA2,0xAFA3,0xAFA4,0xAFA5,
+0xAFA6,0xAFA7,0xAFA8,0xAFA9,0xAFAA,0xAFAB,0xAFAC,0xAFAD,
+0xAFAE,0xAFAF,0xAFB0,0xAFB1,0xAFB2,0xAFB3,0xAFB4,0xAFB5,
+0xAFB6,0xAFB7,0xAFBA,0xAFBB,0xAFBD,0xAFBE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xAFBF,0xAFC1,0xAFC2,0xAFC3,0xAFC4,0xAFC5,0xAFC6,0xAFCA,
+0xAFCC,0xAFCF,0xAFD0,0xAFD1,0xAFD2,0xAFD3,0xAFD5,0xAFD6,
+0xAFD7,0xAFD8,0xAFD9,0xAFDA,0xAFDB,0xAFDD,0xAFDE,0xAFDF,
+0xAFE0,0xAFE1, 0, 0, 0, 0, 0, 0,
+0xAFE2,0xAFE3,0xAFE4,0xAFE5,0xAFE6,0xAFE7,0xAFEA,0xAFEB,
+0xAFEC,0xAFED,0xAFEE,0xAFEF,0xAFF2,0xAFF3,0xAFF5,0xAFF6,
+0xAFF7,0xAFF9,0xAFFA,0xAFFB,0xAFFC,0xAFFD,0xAFFE,0xAFFF,
+0xB002,0xB003, 0, 0, 0, 0, 0, 0,
+0xB005,0xB006,0xB007,0xB008,0xB009,0xB00A,0xB00B,0xB00D,
+0xB00E,0xB00F,0xB011,0xB012,0xB013,0xB015,0xB016,0xB017,
+0xB018,0xB019,0xB01A,0xB01B,0xB01E,0xB01F,0xB020,0xB021,
+0xB022,0xB023,0xB024,0xB025,0xB026,0xB027,0xB029,0xB02A,
+0xB02B,0xB02C,0xB02D,0xB02E,0xB02F,0xB030,0xB031,0xB032,
+0xB033,0xB034,0xB035,0xB036,0xB037,0xB038,0xB039,0xB03A,
+0xB03B,0xB03C,0xB03D,0xB03E,0xB03F,0xB040,0xB041,0xB042,
+0xB043,0xB046,0xB047,0xB049,0xB04B,0xB04D,0xB04F,0xB050,
+0xB051,0xB052,0xB056,0xB058,0xB05A,0xB05B,0xB05C,0xB05E,
+0xB05F,0xB060,0xB061,0xB062,0xB063,0xB064,0xB065,0xB066,
+0xB067,0xB068,0xB069,0xB06A,0xB06B,0xB06C,0xB06D,0xB06E,
+0xB06F,0xB070,0xB071,0xB072,0xB073,0xB074,0xB075,0xB076,
+0xB077,0xB078,0xB079,0xB07A,0xB07B,0xB07E,0xB07F,0xB081,
+0xB082,0xB083,0xB085,0xB086,0xB087,0xB088,0xB089,0xB08A,
+0xB08B,0xB08E,0xB090,0xB092,0xB093,0xB094,0xB095,0xB096,
+0xB097,0xB09B,0xB09D,0xB09E,0xB0A3,0xB0A4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB0A5,0xB0A6,0xB0A7,0xB0AA,0xB0B0,0xB0B2,0xB0B6,0xB0B7,
+0xB0B9,0xB0BA,0xB0BB,0xB0BD,0xB0BE,0xB0BF,0xB0C0,0xB0C1,
+0xB0C2,0xB0C3,0xB0C6,0xB0CA,0xB0CB,0xB0CC,0xB0CD,0xB0CE,
+0xB0CF,0xB0D2, 0, 0, 0, 0, 0, 0,
+0xB0D3,0xB0D5,0xB0D6,0xB0D7,0xB0D9,0xB0DA,0xB0DB,0xB0DC,
+0xB0DD,0xB0DE,0xB0DF,0xB0E1,0xB0E2,0xB0E3,0xB0E4,0xB0E6,
+0xB0E7,0xB0E8,0xB0E9,0xB0EA,0xB0EB,0xB0EC,0xB0ED,0xB0EE,
+0xB0EF,0xB0F0, 0, 0, 0, 0, 0, 0,
+0xB0F1,0xB0F2,0xB0F3,0xB0F4,0xB0F5,0xB0F6,0xB0F7,0xB0F8,
+0xB0F9,0xB0FA,0xB0FB,0xB0FC,0xB0FD,0xB0FE,0xB0FF,0xB100,
+0xB101,0xB102,0xB103,0xB104,0xB105,0xB106,0xB107,0xB10A,
+0xB10D,0xB10E,0xB10F,0xB111,0xB114,0xB115,0xB116,0xB117,
+0xB11A,0xB11E,0xB11F,0xB120,0xB121,0xB122,0xB126,0xB127,
+0xB129,0xB12A,0xB12B,0xB12D,0xB12E,0xB12F,0xB130,0xB131,
+0xB132,0xB133,0xB136,0xB13A,0xB13B,0xB13C,0xB13D,0xB13E,
+0xB13F,0xB142,0xB143,0xB145,0xB146,0xB147,0xB149,0xB14A,
+0xB14B,0xB14C,0xB14D,0xB14E,0xB14F,0xB152,0xB153,0xB156,
+0xB157,0xB159,0xB15A,0xB15B,0xB15D,0xB15E,0xB15F,0xB161,
+0xB162,0xB163,0xB164,0xB165,0xB166,0xB167,0xB168,0xB169,
+0xB16A,0xB16B,0xB16C,0xB16D,0xB16E,0xB16F,0xB170,0xB171,
+0xB172,0xB173,0xB174,0xB175,0xB176,0xB177,0xB17A,0xB17B,
+0xB17D,0xB17E,0xB17F,0xB181,0xB183,0xB184,0xB185,0xB186,
+0xB187,0xB18A,0xB18C,0xB18E,0xB18F,0xB190,0xB191,0xB195,
+0xB196,0xB197,0xB199,0xB19A,0xB19B,0xB19D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB19E,0xB19F,0xB1A0,0xB1A1,0xB1A2,0xB1A3,0xB1A4,0xB1A5,
+0xB1A6,0xB1A7,0xB1A9,0xB1AA,0xB1AB,0xB1AC,0xB1AD,0xB1AE,
+0xB1AF,0xB1B0,0xB1B1,0xB1B2,0xB1B3,0xB1B4,0xB1B5,0xB1B6,
+0xB1B7,0xB1B8, 0, 0, 0, 0, 0, 0,
+0xB1B9,0xB1BA,0xB1BB,0xB1BC,0xB1BD,0xB1BE,0xB1BF,0xB1C0,
+0xB1C1,0xB1C2,0xB1C3,0xB1C4,0xB1C5,0xB1C6,0xB1C7,0xB1C8,
+0xB1C9,0xB1CA,0xB1CB,0xB1CD,0xB1CE,0xB1CF,0xB1D1,0xB1D2,
+0xB1D3,0xB1D5, 0, 0, 0, 0, 0, 0,
+0xB1D6,0xB1D7,0xB1D8,0xB1D9,0xB1DA,0xB1DB,0xB1DE,0xB1E0,
+0xB1E1,0xB1E2,0xB1E3,0xB1E4,0xB1E5,0xB1E6,0xB1E7,0xB1EA,
+0xB1EB,0xB1ED,0xB1EE,0xB1EF,0xB1F1,0xB1F2,0xB1F3,0xB1F4,
+0xB1F5,0xB1F6,0xB1F7,0xB1F8,0xB1FA,0xB1FC,0xB1FE,0xB1FF,
+0xB200,0xB201,0xB202,0xB203,0xB206,0xB207,0xB209,0xB20A,
+0xB20D,0xB20E,0xB20F,0xB210,0xB211,0xB212,0xB213,0xB216,
+0xB218,0xB21A,0xB21B,0xB21C,0xB21D,0xB21E,0xB21F,0xB221,
+0xB222,0xB223,0xB224,0xB225,0xB226,0xB227,0xB228,0xB229,
+0xB22A,0xB22B,0xB22C,0xB22D,0xB22E,0xB22F,0xB230,0xB231,
+0xB232,0xB233,0xB235,0xB236,0xB237,0xB238,0xB239,0xB23A,
+0xB23B,0xB23D,0xB23E,0xB23F,0xB240,0xB241,0xB242,0xB243,
+0xB244,0xB245,0xB246,0xB247,0xB248,0xB249,0xB24A,0xB24B,
+0xB24C,0xB24D,0xB24E,0xB24F,0xB250,0xB251,0xB252,0xB253,
+0xB254,0xB255,0xB256,0xB257,0xB259,0xB25A,0xB25B,0xB25D,
+0xB25E,0xB25F,0xB261,0xB262,0xB263,0xB264,0xB265,0xB266,
+0xB267,0xB26A,0xB26B,0xB26C,0xB26D,0xB26E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB26F,0xB270,0xB271,0xB272,0xB273,0xB276,0xB277,0xB278,
+0xB279,0xB27A,0xB27B,0xB27D,0xB27E,0xB27F,0xB280,0xB281,
+0xB282,0xB283,0xB286,0xB287,0xB288,0xB28A,0xB28B,0xB28C,
+0xB28D,0xB28E, 0, 0, 0, 0, 0, 0,
+0xB28F,0xB292,0xB293,0xB295,0xB296,0xB297,0xB29B,0xB29C,
+0xB29D,0xB29E,0xB29F,0xB2A2,0xB2A4,0xB2A7,0xB2A8,0xB2A9,
+0xB2AB,0xB2AD,0xB2AE,0xB2AF,0xB2B1,0xB2B2,0xB2B3,0xB2B5,
+0xB2B6,0xB2B7, 0, 0, 0, 0, 0, 0,
+0xB2B8,0xB2B9,0xB2BA,0xB2BB,0xB2BC,0xB2BD,0xB2BE,0xB2BF,
+0xB2C0,0xB2C1,0xB2C2,0xB2C3,0xB2C4,0xB2C5,0xB2C6,0xB2C7,
+0xB2CA,0xB2CB,0xB2CD,0xB2CE,0xB2CF,0xB2D1,0xB2D3,0xB2D4,
+0xB2D5,0xB2D6,0xB2D7,0xB2DA,0xB2DC,0xB2DE,0xB2DF,0xB2E0,
+0xB2E1,0xB2E3,0xB2E7,0xB2E9,0xB2EA,0xB2F0,0xB2F1,0xB2F2,
+0xB2F6,0xB2FC,0xB2FD,0xB2FE,0xB302,0xB303,0xB305,0xB306,
+0xB307,0xB309,0xB30A,0xB30B,0xB30C,0xB30D,0xB30E,0xB30F,
+0xB312,0xB316,0xB317,0xB318,0xB319,0xB31A,0xB31B,0xB31D,
+0xB31E,0xB31F,0xB320,0xB321,0xB322,0xB323,0xB324,0xB325,
+0xB326,0xB327,0xB328,0xB329,0xB32A,0xB32B,0xB32C,0xB32D,
+0xB32E,0xB32F,0xB330,0xB331,0xB332,0xB333,0xB334,0xB335,
+0xB336,0xB337,0xB338,0xB339,0xB33A,0xB33B,0xB33C,0xB33D,
+0xB33E,0xB33F,0xB340,0xB341,0xB342,0xB343,0xB344,0xB345,
+0xB346,0xB347,0xB348,0xB349,0xB34A,0xB34B,0xB34C,0xB34D,
+0xB34E,0xB34F,0xB350,0xB351,0xB352,0xB353,0xB357,0xB359,
+0xB35A,0xB35D,0xB360,0xB361,0xB362,0xB363, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB366,0xB368,0xB36A,0xB36C,0xB36D,0xB36F,0xB372,0xB373,
+0xB375,0xB376,0xB377,0xB379,0xB37A,0xB37B,0xB37C,0xB37D,
+0xB37E,0xB37F,0xB382,0xB386,0xB387,0xB388,0xB389,0xB38A,
+0xB38B,0xB38D, 0, 0, 0, 0, 0, 0,
+0xB38E,0xB38F,0xB391,0xB392,0xB393,0xB395,0xB396,0xB397,
+0xB398,0xB399,0xB39A,0xB39B,0xB39C,0xB39D,0xB39E,0xB39F,
+0xB3A2,0xB3A3,0xB3A4,0xB3A5,0xB3A6,0xB3A7,0xB3A9,0xB3AA,
+0xB3AB,0xB3AD, 0, 0, 0, 0, 0, 0,
+0xB3AE,0xB3AF,0xB3B0,0xB3B1,0xB3B2,0xB3B3,0xB3B4,0xB3B5,
+0xB3B6,0xB3B7,0xB3B8,0xB3B9,0xB3BA,0xB3BB,0xB3BC,0xB3BD,
+0xB3BE,0xB3BF,0xB3C0,0xB3C1,0xB3C2,0xB3C3,0xB3C6,0xB3C7,
+0xB3C9,0xB3CA,0xB3CD,0xB3CF,0xB3D1,0xB3D2,0xB3D3,0xB3D6,
+0xB3D8,0xB3DA,0xB3DC,0xB3DE,0xB3DF,0xB3E1,0xB3E2,0xB3E3,
+0xB3E5,0xB3E6,0xB3E7,0xB3E9,0xB3EA,0xB3EB,0xB3EC,0xB3ED,
+0xB3EE,0xB3EF,0xB3F0,0xB3F1,0xB3F2,0xB3F3,0xB3F4,0xB3F5,
+0xB3F6,0xB3F7,0xB3F8,0xB3F9,0xB3FA,0xB3FB,0xB3FD,0xB3FE,
+0xB3FF,0xB400,0xB401,0xB402,0xB403,0xB404,0xB405,0xB406,
+0xB407,0xB408,0xB409,0xB40A,0xB40B,0xB40C,0xB40D,0xB40E,
+0xB40F,0xB411,0xB412,0xB413,0xB414,0xB415,0xB416,0xB417,
+0xB419,0xB41A,0xB41B,0xB41D,0xB41E,0xB41F,0xB421,0xB422,
+0xB423,0xB424,0xB425,0xB426,0xB427,0xB42A,0xB42C,0xB42D,
+0xB42E,0xB42F,0xB430,0xB431,0xB432,0xB433,0xB435,0xB436,
+0xB437,0xB438,0xB439,0xB43A,0xB43B,0xB43C,0xB43D,0xB43E,
+0xB43F,0xB440,0xB441,0xB442,0xB443,0xB444, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB445,0xB446,0xB447,0xB448,0xB449,0xB44A,0xB44B,0xB44C,
+0xB44D,0xB44E,0xB44F,0xB452,0xB453,0xB455,0xB456,0xB457,
+0xB459,0xB45A,0xB45B,0xB45C,0xB45D,0xB45E,0xB45F,0xB462,
+0xB464,0xB466, 0, 0, 0, 0, 0, 0,
+0xB467,0xB468,0xB469,0xB46A,0xB46B,0xB46D,0xB46E,0xB46F,
+0xB470,0xB471,0xB472,0xB473,0xB474,0xB475,0xB476,0xB477,
+0xB478,0xB479,0xB47A,0xB47B,0xB47C,0xB47D,0xB47E,0xB47F,
+0xB481,0xB482, 0, 0, 0, 0, 0, 0,
+0xB483,0xB484,0xB485,0xB486,0xB487,0xB489,0xB48A,0xB48B,
+0xB48C,0xB48D,0xB48E,0xB48F,0xB490,0xB491,0xB492,0xB493,
+0xB494,0xB495,0xB496,0xB497,0xB498,0xB499,0xB49A,0xB49B,
+0xB49C,0xB49E,0xB49F,0xB4A0,0xB4A1,0xB4A2,0xB4A3,0xB4A5,
+0xB4A6,0xB4A7,0xB4A9,0xB4AA,0xB4AB,0xB4AD,0xB4AE,0xB4AF,
+0xB4B0,0xB4B1,0xB4B2,0xB4B3,0xB4B4,0xB4B6,0xB4B8,0xB4BA,
+0xB4BB,0xB4BC,0xB4BD,0xB4BE,0xB4BF,0xB4C1,0xB4C2,0xB4C3,
+0xB4C5,0xB4C6,0xB4C7,0xB4C9,0xB4CA,0xB4CB,0xB4CC,0xB4CD,
+0xB4CE,0xB4CF,0xB4D1,0xB4D2,0xB4D3,0xB4D4,0xB4D6,0xB4D7,
+0xB4D8,0xB4D9,0xB4DA,0xB4DB,0xB4DE,0xB4DF,0xB4E1,0xB4E2,
+0xB4E5,0xB4E7,0xB4E8,0xB4E9,0xB4EA,0xB4EB,0xB4EE,0xB4F0,
+0xB4F2,0xB4F3,0xB4F4,0xB4F5,0xB4F6,0xB4F7,0xB4F9,0xB4FA,
+0xB4FB,0xB4FC,0xB4FD,0xB4FE,0xB4FF,0xB500,0xB501,0xB502,
+0xB503,0xB504,0xB505,0xB506,0xB507,0xB508,0xB509,0xB50A,
+0xB50B,0xB50C,0xB50D,0xB50E,0xB50F,0xB510,0xB511,0xB512,
+0xB513,0xB516,0xB517,0xB519,0xB51A,0xB51D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB51E,0xB51F,0xB520,0xB521,0xB522,0xB523,0xB526,0xB52B,
+0xB52C,0xB52D,0xB52E,0xB52F,0xB532,0xB533,0xB535,0xB536,
+0xB537,0xB539,0xB53A,0xB53B,0xB53C,0xB53D,0xB53E,0xB53F,
+0xB542,0xB546, 0, 0, 0, 0, 0, 0,
+0xB547,0xB548,0xB549,0xB54A,0xB54E,0xB54F,0xB551,0xB552,
+0xB553,0xB555,0xB556,0xB557,0xB558,0xB559,0xB55A,0xB55B,
+0xB55E,0xB562,0xB563,0xB564,0xB565,0xB566,0xB567,0xB568,
+0xB569,0xB56A, 0, 0, 0, 0, 0, 0,
+0xB56B,0xB56C,0xB56D,0xB56E,0xB56F,0xB570,0xB571,0xB572,
+0xB573,0xB574,0xB575,0xB576,0xB577,0xB578,0xB579,0xB57A,
+0xB57B,0xB57C,0xB57D,0xB57E,0xB57F,0xB580,0xB581,0xB582,
+0xB583,0xB584,0xB585,0xB586,0xB587,0xB588,0xB589,0xB58A,
+0xB58B,0xB58C,0xB58D,0xB58E,0xB58F,0xB590,0xB591,0xB592,
+0xB593,0xB594,0xB595,0xB596,0xB597,0xB598,0xB599,0xB59A,
+0xB59B,0xB59C,0xB59D,0xB59E,0xB59F,0xB5A2,0xB5A3,0xB5A5,
+0xB5A6,0xB5A7,0xB5A9,0xB5AC,0xB5AD,0xB5AE,0xB5AF,0xB5B2,
+0xB5B6,0xB5B7,0xB5B8,0xB5B9,0xB5BA,0xB5BE,0xB5BF,0xB5C1,
+0xB5C2,0xB5C3,0xB5C5,0xB5C6,0xB5C7,0xB5C8,0xB5C9,0xB5CA,
+0xB5CB,0xB5CE,0xB5D2,0xB5D3,0xB5D4,0xB5D5,0xB5D6,0xB5D7,
+0xB5D9,0xB5DA,0xB5DB,0xB5DC,0xB5DD,0xB5DE,0xB5DF,0xB5E0,
+0xB5E1,0xB5E2,0xB5E3,0xB5E4,0xB5E5,0xB5E6,0xB5E7,0xB5E8,
+0xB5E9,0xB5EA,0xB5EB,0xB5ED,0xB5EE,0xB5EF,0xB5F0,0xB5F1,
+0xB5F2,0xB5F3,0xB5F4,0xB5F5,0xB5F6,0xB5F7,0xB5F8,0xB5F9,
+0xB5FA,0xB5FB,0xB5FC,0xB5FD,0xB5FE,0xB5FF, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB600,0xB601,0xB602,0xB603,0xB604,0xB605,0xB606,0xB607,
+0xB608,0xB609,0xB60A,0xB60B,0xB60C,0xB60D,0xB60E,0xB60F,
+0xB612,0xB613,0xB615,0xB616,0xB617,0xB619,0xB61A,0xB61B,
+0xB61C,0xB61D, 0, 0, 0, 0, 0, 0,
+0xB61E,0xB61F,0xB620,0xB621,0xB622,0xB623,0xB624,0xB626,
+0xB627,0xB628,0xB629,0xB62A,0xB62B,0xB62D,0xB62E,0xB62F,
+0xB630,0xB631,0xB632,0xB633,0xB635,0xB636,0xB637,0xB638,
+0xB639,0xB63A, 0, 0, 0, 0, 0, 0,
+0xB63B,0xB63C,0xB63D,0xB63E,0xB63F,0xB640,0xB641,0xB642,
+0xB643,0xB644,0xB645,0xB646,0xB647,0xB649,0xB64A,0xB64B,
+0xB64C,0xB64D,0xB64E,0xB64F,0xB650,0xB651,0xB652,0xB653,
+0xB654,0xB655,0xB656,0xB657,0xB658,0xB659,0xB65A,0xB65B,
+0xB65C,0xB65D,0xB65E,0xB65F,0xB660,0xB661,0xB662,0xB663,
+0xB665,0xB666,0xB667,0xB669,0xB66A,0xB66B,0xB66C,0xB66D,
+0xB66E,0xB66F,0xB670,0xB671,0xB672,0xB673,0xB674,0xB675,
+0xB676,0xB677,0xB678,0xB679,0xB67A,0xB67B,0xB67C,0xB67D,
+0xB67E,0xB67F,0xB680,0xB681,0xB682,0xB683,0xB684,0xB685,
+0xB686,0xB687,0xB688,0xB689,0xB68A,0xB68B,0xB68C,0xB68D,
+0xB68E,0xB68F,0xB690,0xB691,0xB692,0xB693,0xB694,0xB695,
+0xB696,0xB697,0xB698,0xB699,0xB69A,0xB69B,0xB69E,0xB69F,
+0xB6A1,0xB6A2,0xB6A3,0xB6A5,0xB6A6,0xB6A7,0xB6A8,0xB6A9,
+0xB6AA,0xB6AD,0xB6AE,0xB6AF,0xB6B0,0xB6B2,0xB6B3,0xB6B4,
+0xB6B5,0xB6B6,0xB6B7,0xB6B8,0xB6B9,0xB6BA,0xB6BB,0xB6BC,
+0xB6BD,0xB6BE,0xB6BF,0xB6C0,0xB6C1,0xB6C2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB6C3,0xB6C4,0xB6C5,0xB6C6,0xB6C7,0xB6C8,0xB6C9,0xB6CA,
+0xB6CB,0xB6CC,0xB6CD,0xB6CE,0xB6CF,0xB6D0,0xB6D1,0xB6D2,
+0xB6D3,0xB6D5,0xB6D6,0xB6D7,0xB6D8,0xB6D9,0xB6DA,0xB6DB,
+0xB6DC,0xB6DD, 0, 0, 0, 0, 0, 0,
+0xB6DE,0xB6DF,0xB6E0,0xB6E1,0xB6E2,0xB6E3,0xB6E4,0xB6E5,
+0xB6E6,0xB6E7,0xB6E8,0xB6E9,0xB6EA,0xB6EB,0xB6EC,0xB6ED,
+0xB6EE,0xB6EF,0xB6F1,0xB6F2,0xB6F3,0xB6F5,0xB6F6,0xB6F7,
+0xB6F9,0xB6FA, 0, 0, 0, 0, 0, 0,
+0xB6FB,0xB6FC,0xB6FD,0xB6FE,0xB6FF,0xB702,0xB703,0xB704,
+0xB706,0xB707,0xB708,0xB709,0xB70A,0xB70B,0xB70C,0xB70D,
+0xB70E,0xB70F,0xB710,0xB711,0xB712,0xB713,0xB714,0xB715,
+0xB716,0xB717,0xB718,0xB719,0xB71A,0xB71B,0xB71C,0xB71D,
+0xB71E,0xB71F,0xB720,0xB721,0xB722,0xB723,0xB724,0xB725,
+0xB726,0xB727,0xB72A,0xB72B,0xB72D,0xB72E,0xB731,0xB732,
+0xB733,0xB734,0xB735,0xB736,0xB737,0xB73A,0xB73C,0xB73D,
+0xB73E,0xB73F,0xB740,0xB741,0xB742,0xB743,0xB745,0xB746,
+0xB747,0xB749,0xB74A,0xB74B,0xB74D,0xB74E,0xB74F,0xB750,
+0xB751,0xB752,0xB753,0xB756,0xB757,0xB758,0xB759,0xB75A,
+0xB75B,0xB75C,0xB75D,0xB75E,0xB75F,0xB761,0xB762,0xB763,
+0xB765,0xB766,0xB767,0xB769,0xB76A,0xB76B,0xB76C,0xB76D,
+0xB76E,0xB76F,0xB772,0xB774,0xB776,0xB777,0xB778,0xB779,
+0xB77A,0xB77B,0xB77E,0xB77F,0xB781,0xB782,0xB783,0xB785,
+0xB786,0xB787,0xB788,0xB789,0xB78A,0xB78B,0xB78E,0xB793,
+0xB794,0xB795,0xB79A,0xB79B,0xB79D,0xB79E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB79F,0xB7A1,0xB7A2,0xB7A3,0xB7A4,0xB7A5,0xB7A6,0xB7A7,
+0xB7AA,0xB7AE,0xB7AF,0xB7B0,0xB7B1,0xB7B2,0xB7B3,0xB7B6,
+0xB7B7,0xB7B9,0xB7BA,0xB7BB,0xB7BC,0xB7BD,0xB7BE,0xB7BF,
+0xB7C0,0xB7C1, 0, 0, 0, 0, 0, 0,
+0xB7C2,0xB7C3,0xB7C4,0xB7C5,0xB7C6,0xB7C8,0xB7CA,0xB7CB,
+0xB7CC,0xB7CD,0xB7CE,0xB7CF,0xB7D0,0xB7D1,0xB7D2,0xB7D3,
+0xB7D4,0xB7D5,0xB7D6,0xB7D7,0xB7D8,0xB7D9,0xB7DA,0xB7DB,
+0xB7DC,0xB7DD, 0, 0, 0, 0, 0, 0,
+0xB7DE,0xB7DF,0xB7E0,0xB7E1,0xB7E2,0xB7E3,0xB7E4,0xB7E5,
+0xB7E6,0xB7E7,0xB7E8,0xB7E9,0xB7EA,0xB7EB,0xB7EE,0xB7EF,
+0xB7F1,0xB7F2,0xB7F3,0xB7F5,0xB7F6,0xB7F7,0xB7F8,0xB7F9,
+0xB7FA,0xB7FB,0xB7FE,0xB802,0xB803,0xB804,0xB805,0xB806,
+0xB80A,0xB80B,0xB80D,0xB80E,0xB80F,0xB811,0xB812,0xB813,
+0xB814,0xB815,0xB816,0xB817,0xB81A,0xB81C,0xB81E,0xB81F,
+0xB820,0xB821,0xB822,0xB823,0xB826,0xB827,0xB829,0xB82A,
+0xB82B,0xB82D,0xB82E,0xB82F,0xB830,0xB831,0xB832,0xB833,
+0xB836,0xB83A,0xB83B,0xB83C,0xB83D,0xB83E,0xB83F,0xB841,
+0xB842,0xB843,0xB845,0xB846,0xB847,0xB848,0xB849,0xB84A,
+0xB84B,0xB84C,0xB84D,0xB84E,0xB84F,0xB850,0xB852,0xB854,
+0xB855,0xB856,0xB857,0xB858,0xB859,0xB85A,0xB85B,0xB85E,
+0xB85F,0xB861,0xB862,0xB863,0xB865,0xB866,0xB867,0xB868,
+0xB869,0xB86A,0xB86B,0xB86E,0xB870,0xB872,0xB873,0xB874,
+0xB875,0xB876,0xB877,0xB879,0xB87A,0xB87B,0xB87D,0xB87E,
+0xB87F,0xB880,0xB881,0xB882,0xB883,0xB884, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB885,0xB886,0xB887,0xB888,0xB889,0xB88A,0xB88B,0xB88C,
+0xB88E,0xB88F,0xB890,0xB891,0xB892,0xB893,0xB894,0xB895,
+0xB896,0xB897,0xB898,0xB899,0xB89A,0xB89B,0xB89C,0xB89D,
+0xB89E,0xB89F, 0, 0, 0, 0, 0, 0,
+0xB8A0,0xB8A1,0xB8A2,0xB8A3,0xB8A4,0xB8A5,0xB8A6,0xB8A7,
+0xB8A9,0xB8AA,0xB8AB,0xB8AC,0xB8AD,0xB8AE,0xB8AF,0xB8B1,
+0xB8B2,0xB8B3,0xB8B5,0xB8B6,0xB8B7,0xB8B9,0xB8BA,0xB8BB,
+0xB8BC,0xB8BD, 0, 0, 0, 0, 0, 0,
+0xB8BE,0xB8BF,0xB8C2,0xB8C4,0xB8C6,0xB8C7,0xB8C8,0xB8C9,
+0xB8CA,0xB8CB,0xB8CD,0xB8CE,0xB8CF,0xB8D1,0xB8D2,0xB8D3,
+0xB8D5,0xB8D6,0xB8D7,0xB8D8,0xB8D9,0xB8DA,0xB8DB,0xB8DC,
+0xB8DE,0xB8E0,0xB8E2,0xB8E3,0xB8E4,0xB8E5,0xB8E6,0xB8E7,
+0xB8EA,0xB8EB,0xB8ED,0xB8EE,0xB8EF,0xB8F1,0xB8F2,0xB8F3,
+0xB8F4,0xB8F5,0xB8F6,0xB8F7,0xB8FA,0xB8FC,0xB8FE,0xB8FF,
+0xB900,0xB901,0xB902,0xB903,0xB905,0xB906,0xB907,0xB908,
+0xB909,0xB90A,0xB90B,0xB90C,0xB90D,0xB90E,0xB90F,0xB910,
+0xB911,0xB912,0xB913,0xB914,0xB915,0xB916,0xB917,0xB919,
+0xB91A,0xB91B,0xB91C,0xB91D,0xB91E,0xB91F,0xB921,0xB922,
+0xB923,0xB924,0xB925,0xB926,0xB927,0xB928,0xB929,0xB92A,
+0xB92B,0xB92C,0xB92D,0xB92E,0xB92F,0xB930,0xB931,0xB932,
+0xB933,0xB934,0xB935,0xB936,0xB937,0xB938,0xB939,0xB93A,
+0xB93B,0xB93E,0xB93F,0xB941,0xB942,0xB943,0xB945,0xB946,
+0xB947,0xB948,0xB949,0xB94A,0xB94B,0xB94D,0xB94E,0xB950,
+0xB952,0xB953,0xB954,0xB955,0xB956,0xB957, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xB95A,0xB95B,0xB95D,0xB95E,0xB95F,0xB961,0xB962,0xB963,
+0xB964,0xB965,0xB966,0xB967,0xB96A,0xB96C,0xB96E,0xB96F,
+0xB970,0xB971,0xB972,0xB973,0xB976,0xB977,0xB979,0xB97A,
+0xB97B,0xB97D, 0, 0, 0, 0, 0, 0,
+0xB97E,0xB97F,0xB980,0xB981,0xB982,0xB983,0xB986,0xB988,
+0xB98B,0xB98C,0xB98F,0xB990,0xB991,0xB992,0xB993,0xB994,
+0xB995,0xB996,0xB997,0xB998,0xB999,0xB99A,0xB99B,0xB99C,
+0xB99D,0xB99E, 0, 0, 0, 0, 0, 0,
+0xB99F,0xB9A0,0xB9A1,0xB9A2,0xB9A3,0xB9A4,0xB9A5,0xB9A6,
+0xB9A7,0xB9A8,0xB9A9,0xB9AA,0xB9AB,0xB9AE,0xB9AF,0xB9B1,
+0xB9B2,0xB9B3,0xB9B5,0xB9B6,0xB9B7,0xB9B8,0xB9B9,0xB9BA,
+0xB9BB,0xB9BE,0xB9C0,0xB9C2,0xB9C3,0xB9C4,0xB9C5,0xB9C6,
+0xB9C7,0xB9CA,0xB9CB,0xB9CD,0xB9D3,0xB9D4,0xB9D5,0xB9D6,
+0xB9D7,0xB9DA,0xB9DC,0xB9DF,0xB9E0,0xB9E2,0xB9E6,0xB9E7,
+0xB9E9,0xB9EA,0xB9EB,0xB9ED,0xB9EE,0xB9EF,0xB9F0,0xB9F1,
+0xB9F2,0xB9F3,0xB9F6,0xB9FB,0xB9FC,0xB9FD,0xB9FE,0xB9FF,
+0xBA02,0xBA03,0xBA04,0xBA05,0xBA06,0xBA07,0xBA09,0xBA0A,
+0xBA0B,0xBA0C,0xBA0D,0xBA0E,0xBA0F,0xBA10,0xBA11,0xBA12,
+0xBA13,0xBA14,0xBA16,0xBA17,0xBA18,0xBA19,0xBA1A,0xBA1B,
+0xBA1C,0xBA1D,0xBA1E,0xBA1F,0xBA20,0xBA21,0xBA22,0xBA23,
+0xBA24,0xBA25,0xBA26,0xBA27,0xBA28,0xBA29,0xBA2A,0xBA2B,
+0xBA2C,0xBA2D,0xBA2E,0xBA2F,0xBA30,0xBA31,0xBA32,0xBA33,
+0xBA34,0xBA35,0xBA36,0xBA37,0xBA3A,0xBA3B,0xBA3D,0xBA3E,
+0xBA3F,0xBA41,0xBA43,0xBA44,0xBA45,0xBA46, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBA47,0xBA4A,0xBA4C,0xBA4F,0xBA50,0xBA51,0xBA52,0xBA56,
+0xBA57,0xBA59,0xBA5A,0xBA5B,0xBA5D,0xBA5E,0xBA5F,0xBA60,
+0xBA61,0xBA62,0xBA63,0xBA66,0xBA6A,0xBA6B,0xBA6C,0xBA6D,
+0xBA6E,0xBA6F, 0, 0, 0, 0, 0, 0,
+0xBA72,0xBA73,0xBA75,0xBA76,0xBA77,0xBA79,0xBA7A,0xBA7B,
+0xBA7C,0xBA7D,0xBA7E,0xBA7F,0xBA80,0xBA81,0xBA82,0xBA86,
+0xBA88,0xBA89,0xBA8A,0xBA8B,0xBA8D,0xBA8E,0xBA8F,0xBA90,
+0xBA91,0xBA92, 0, 0, 0, 0, 0, 0,
+0xBA93,0xBA94,0xBA95,0xBA96,0xBA97,0xBA98,0xBA99,0xBA9A,
+0xBA9B,0xBA9C,0xBA9D,0xBA9E,0xBA9F,0xBAA0,0xBAA1,0xBAA2,
+0xBAA3,0xBAA4,0xBAA5,0xBAA6,0xBAA7,0xBAAA,0xBAAD,0xBAAE,
+0xBAAF,0xBAB1,0xBAB3,0xBAB4,0xBAB5,0xBAB6,0xBAB7,0xBABA,
+0xBABC,0xBABE,0xBABF,0xBAC0,0xBAC1,0xBAC2,0xBAC3,0xBAC5,
+0xBAC6,0xBAC7,0xBAC9,0xBACA,0xBACB,0xBACC,0xBACD,0xBACE,
+0xBACF,0xBAD0,0xBAD1,0xBAD2,0xBAD3,0xBAD4,0xBAD5,0xBAD6,
+0xBAD7,0xBADA,0xBADB,0xBADC,0xBADD,0xBADE,0xBADF,0xBAE0,
+0xBAE1,0xBAE2,0xBAE3,0xBAE4,0xBAE5,0xBAE6,0xBAE7,0xBAE8,
+0xBAE9,0xBAEA,0xBAEB,0xBAEC,0xBAED,0xBAEE,0xBAEF,0xBAF0,
+0xBAF1,0xBAF2,0xBAF3,0xBAF4,0xBAF5,0xBAF6,0xBAF7,0xBAF8,
+0xBAF9,0xBAFA,0xBAFB,0xBAFD,0xBAFE,0xBAFF,0xBB01,0xBB02,
+0xBB03,0xBB05,0xBB06,0xBB07,0xBB08,0xBB09,0xBB0A,0xBB0B,
+0xBB0C,0xBB0E,0xBB10,0xBB12,0xBB13,0xBB14,0xBB15,0xBB16,
+0xBB17,0xBB19,0xBB1A,0xBB1B,0xBB1D,0xBB1E,0xBB1F,0xBB21,
+0xBB22,0xBB23,0xBB24,0xBB25,0xBB26,0xBB27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBB28,0xBB2A,0xBB2C,0xBB2D,0xBB2E,0xBB2F,0xBB30,0xBB31,
+0xBB32,0xBB33,0xBB37,0xBB39,0xBB3A,0xBB3F,0xBB40,0xBB41,
+0xBB42,0xBB43,0xBB46,0xBB48,0xBB4A,0xBB4B,0xBB4C,0xBB4E,
+0xBB51,0xBB52, 0, 0, 0, 0, 0, 0,
+0xBB53,0xBB55,0xBB56,0xBB57,0xBB59,0xBB5A,0xBB5B,0xBB5C,
+0xBB5D,0xBB5E,0xBB5F,0xBB60,0xBB62,0xBB64,0xBB65,0xBB66,
+0xBB67,0xBB68,0xBB69,0xBB6A,0xBB6B,0xBB6D,0xBB6E,0xBB6F,
+0xBB70,0xBB71, 0, 0, 0, 0, 0, 0,
+0xBB72,0xBB73,0xBB74,0xBB75,0xBB76,0xBB77,0xBB78,0xBB79,
+0xBB7A,0xBB7B,0xBB7C,0xBB7D,0xBB7E,0xBB7F,0xBB80,0xBB81,
+0xBB82,0xBB83,0xBB84,0xBB85,0xBB86,0xBB87,0xBB89,0xBB8A,
+0xBB8B,0xBB8D,0xBB8E,0xBB8F,0xBB91,0xBB92,0xBB93,0xBB94,
+0xBB95,0xBB96,0xBB97,0xBB98,0xBB99,0xBB9A,0xBB9B,0xBB9C,
+0xBB9D,0xBB9E,0xBB9F,0xBBA0,0xBBA1,0xBBA2,0xBBA3,0xBBA5,
+0xBBA6,0xBBA7,0xBBA9,0xBBAA,0xBBAB,0xBBAD,0xBBAE,0xBBAF,
+0xBBB0,0xBBB1,0xBBB2,0xBBB3,0xBBB5,0xBBB6,0xBBB8,0xBBB9,
+0xBBBA,0xBBBB,0xBBBC,0xBBBD,0xBBBE,0xBBBF,0xBBC1,0xBBC2,
+0xBBC3,0xBBC5,0xBBC6,0xBBC7,0xBBC9,0xBBCA,0xBBCB,0xBBCC,
+0xBBCD,0xBBCE,0xBBCF,0xBBD1,0xBBD2,0xBBD4,0xBBD5,0xBBD6,
+0xBBD7,0xBBD8,0xBBD9,0xBBDA,0xBBDB,0xBBDC,0xBBDD,0xBBDE,
+0xBBDF,0xBBE0,0xBBE1,0xBBE2,0xBBE3,0xBBE4,0xBBE5,0xBBE6,
+0xBBE7,0xBBE8,0xBBE9,0xBBEA,0xBBEB,0xBBEC,0xBBED,0xBBEE,
+0xBBEF,0xBBF0,0xBBF1,0xBBF2,0xBBF3,0xBBF4,0xBBF5,0xBBF6,
+0xBBF7,0xBBFA,0xBBFB,0xBBFD,0xBBFE,0xBC01, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBC03,0xBC04,0xBC05,0xBC06,0xBC07,0xBC0A,0xBC0E,0xBC10,
+0xBC12,0xBC13,0xBC19,0xBC1A,0xBC20,0xBC21,0xBC22,0xBC23,
+0xBC26,0xBC28,0xBC2A,0xBC2B,0xBC2C,0xBC2E,0xBC2F,0xBC32,
+0xBC33,0xBC35, 0, 0, 0, 0, 0, 0,
+0xBC36,0xBC37,0xBC39,0xBC3A,0xBC3B,0xBC3C,0xBC3D,0xBC3E,
+0xBC3F,0xBC42,0xBC46,0xBC47,0xBC48,0xBC4A,0xBC4B,0xBC4E,
+0xBC4F,0xBC51,0xBC52,0xBC53,0xBC54,0xBC55,0xBC56,0xBC57,
+0xBC58,0xBC59, 0, 0, 0, 0, 0, 0,
+0xBC5A,0xBC5B,0xBC5C,0xBC5E,0xBC5F,0xBC60,0xBC61,0xBC62,
+0xBC63,0xBC64,0xBC65,0xBC66,0xBC67,0xBC68,0xBC69,0xBC6A,
+0xBC6B,0xBC6C,0xBC6D,0xBC6E,0xBC6F,0xBC70,0xBC71,0xBC72,
+0xBC73,0xBC74,0xBC75,0xBC76,0xBC77,0xBC78,0xBC79,0xBC7A,
+0xBC7B,0xBC7C,0xBC7D,0xBC7E,0xBC7F,0xBC80,0xBC81,0xBC82,
+0xBC83,0xBC86,0xBC87,0xBC89,0xBC8A,0xBC8D,0xBC8F,0xBC90,
+0xBC91,0xBC92,0xBC93,0xBC96,0xBC98,0xBC9B,0xBC9C,0xBC9D,
+0xBC9E,0xBC9F,0xBCA2,0xBCA3,0xBCA5,0xBCA6,0xBCA9,0xBCAA,
+0xBCAB,0xBCAC,0xBCAD,0xBCAE,0xBCAF,0xBCB2,0xBCB6,0xBCB7,
+0xBCB8,0xBCB9,0xBCBA,0xBCBB,0xBCBE,0xBCBF,0xBCC1,0xBCC2,
+0xBCC3,0xBCC5,0xBCC6,0xBCC7,0xBCC8,0xBCC9,0xBCCA,0xBCCB,
+0xBCCC,0xBCCE,0xBCD2,0xBCD3,0xBCD4,0xBCD6,0xBCD7,0xBCD9,
+0xBCDA,0xBCDB,0xBCDD,0xBCDE,0xBCDF,0xBCE0,0xBCE1,0xBCE2,
+0xBCE3,0xBCE4,0xBCE5,0xBCE6,0xBCE7,0xBCE8,0xBCE9,0xBCEA,
+0xBCEB,0xBCEC,0xBCED,0xBCEE,0xBCEF,0xBCF0,0xBCF1,0xBCF2,
+0xBCF3,0xBCF7,0xBCF9,0xBCFA,0xBCFB,0xBCFD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBCFE,0xBCFF,0xBD00,0xBD01,0xBD02,0xBD03,0xBD06,0xBD08,
+0xBD0A,0xBD0B,0xBD0C,0xBD0D,0xBD0E,0xBD0F,0xBD11,0xBD12,
+0xBD13,0xBD15,0xBD16,0xBD17,0xBD18,0xBD19,0xBD1A,0xBD1B,
+0xBD1C,0xBD1D, 0, 0, 0, 0, 0, 0,
+0xBD1E,0xBD1F,0xBD20,0xBD21,0xBD22,0xBD23,0xBD25,0xBD26,
+0xBD27,0xBD28,0xBD29,0xBD2A,0xBD2B,0xBD2D,0xBD2E,0xBD2F,
+0xBD30,0xBD31,0xBD32,0xBD33,0xBD34,0xBD35,0xBD36,0xBD37,
+0xBD38,0xBD39, 0, 0, 0, 0, 0, 0,
+0xBD3A,0xBD3B,0xBD3C,0xBD3D,0xBD3E,0xBD3F,0xBD41,0xBD42,
+0xBD43,0xBD44,0xBD45,0xBD46,0xBD47,0xBD4A,0xBD4B,0xBD4D,
+0xBD4E,0xBD4F,0xBD51,0xBD52,0xBD53,0xBD54,0xBD55,0xBD56,
+0xBD57,0xBD5A,0xBD5B,0xBD5C,0xBD5D,0xBD5E,0xBD5F,0xBD60,
+0xBD61,0xBD62,0xBD63,0xBD65,0xBD66,0xBD67,0xBD69,0xBD6A,
+0xBD6B,0xBD6C,0xBD6D,0xBD6E,0xBD6F,0xBD70,0xBD71,0xBD72,
+0xBD73,0xBD74,0xBD75,0xBD76,0xBD77,0xBD78,0xBD79,0xBD7A,
+0xBD7B,0xBD7C,0xBD7D,0xBD7E,0xBD7F,0xBD82,0xBD83,0xBD85,
+0xBD86,0xBD8B,0xBD8C,0xBD8D,0xBD8E,0xBD8F,0xBD92,0xBD94,
+0xBD96,0xBD97,0xBD98,0xBD9B,0xBD9D,0xBD9E,0xBD9F,0xBDA0,
+0xBDA1,0xBDA2,0xBDA3,0xBDA5,0xBDA6,0xBDA7,0xBDA8,0xBDA9,
+0xBDAA,0xBDAB,0xBDAC,0xBDAD,0xBDAE,0xBDAF,0xBDB1,0xBDB2,
+0xBDB3,0xBDB4,0xBDB5,0xBDB6,0xBDB7,0xBDB9,0xBDBA,0xBDBB,
+0xBDBC,0xBDBD,0xBDBE,0xBDBF,0xBDC0,0xBDC1,0xBDC2,0xBDC3,
+0xBDC4,0xBDC5,0xBDC6,0xBDC7,0xBDC8,0xBDC9,0xBDCA,0xBDCB,
+0xBDCC,0xBDCD,0xBDCE,0xBDCF,0xBDD0,0xBDD1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBDD2,0xBDD3,0xBDD6,0xBDD7,0xBDD9,0xBDDA,0xBDDB,0xBDDD,
+0xBDDE,0xBDDF,0xBDE0,0xBDE1,0xBDE2,0xBDE3,0xBDE4,0xBDE5,
+0xBDE6,0xBDE7,0xBDE8,0xBDEA,0xBDEB,0xBDEC,0xBDED,0xBDEE,
+0xBDEF,0xBDF1, 0, 0, 0, 0, 0, 0,
+0xBDF2,0xBDF3,0xBDF5,0xBDF6,0xBDF7,0xBDF9,0xBDFA,0xBDFB,
+0xBDFC,0xBDFD,0xBDFE,0xBDFF,0xBE01,0xBE02,0xBE04,0xBE06,
+0xBE07,0xBE08,0xBE09,0xBE0A,0xBE0B,0xBE0E,0xBE0F,0xBE11,
+0xBE12,0xBE13, 0, 0, 0, 0, 0, 0,
+0xBE15,0xBE16,0xBE17,0xBE18,0xBE19,0xBE1A,0xBE1B,0xBE1E,
+0xBE20,0xBE21,0xBE22,0xBE23,0xBE24,0xBE25,0xBE26,0xBE27,
+0xBE28,0xBE29,0xBE2A,0xBE2B,0xBE2C,0xBE2D,0xBE2E,0xBE2F,
+0xBE30,0xBE31,0xBE32,0xBE33,0xBE34,0xBE35,0xBE36,0xBE37,
+0xBE38,0xBE39,0xBE3A,0xBE3B,0xBE3C,0xBE3D,0xBE3E,0xBE3F,
+0xBE40,0xBE41,0xBE42,0xBE43,0xBE46,0xBE47,0xBE49,0xBE4A,
+0xBE4B,0xBE4D,0xBE4F,0xBE50,0xBE51,0xBE52,0xBE53,0xBE56,
+0xBE58,0xBE5C,0xBE5D,0xBE5E,0xBE5F,0xBE62,0xBE63,0xBE65,
+0xBE66,0xBE67,0xBE69,0xBE6B,0xBE6C,0xBE6D,0xBE6E,0xBE6F,
+0xBE72,0xBE76,0xBE77,0xBE78,0xBE79,0xBE7A,0xBE7E,0xBE7F,
+0xBE81,0xBE82,0xBE83,0xBE85,0xBE86,0xBE87,0xBE88,0xBE89,
+0xBE8A,0xBE8B,0xBE8E,0xBE92,0xBE93,0xBE94,0xBE95,0xBE96,
+0xBE97,0xBE9A,0xBE9B,0xBE9C,0xBE9D,0xBE9E,0xBE9F,0xBEA0,
+0xBEA1,0xBEA2,0xBEA3,0xBEA4,0xBEA5,0xBEA6,0xBEA7,0xBEA9,
+0xBEAA,0xBEAB,0xBEAC,0xBEAD,0xBEAE,0xBEAF,0xBEB0,0xBEB1,
+0xBEB2,0xBEB3,0xBEB4,0xBEB5,0xBEB6,0xBEB7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBEB8,0xBEB9,0xBEBA,0xBEBB,0xBEBC,0xBEBD,0xBEBE,0xBEBF,
+0xBEC0,0xBEC1,0xBEC2,0xBEC3,0xBEC4,0xBEC5,0xBEC6,0xBEC7,
+0xBEC8,0xBEC9,0xBECA,0xBECB,0xBECC,0xBECD,0xBECE,0xBECF,
+0xBED2,0xBED3, 0, 0, 0, 0, 0, 0,
+0xBED5,0xBED6,0xBED9,0xBEDA,0xBEDB,0xBEDC,0xBEDD,0xBEDE,
+0xBEDF,0xBEE1,0xBEE2,0xBEE6,0xBEE7,0xBEE8,0xBEE9,0xBEEA,
+0xBEEB,0xBEED,0xBEEE,0xBEEF,0xBEF0,0xBEF1,0xBEF2,0xBEF3,
+0xBEF4,0xBEF5, 0, 0, 0, 0, 0, 0,
+0xBEF6,0xBEF7,0xBEF8,0xBEF9,0xBEFA,0xBEFB,0xBEFC,0xBEFD,
+0xBEFE,0xBEFF,0xBF00,0xBF02,0xBF03,0xBF04,0xBF05,0xBF06,
+0xBF07,0xBF0A,0xBF0B,0xBF0C,0xBF0D,0xBF0E,0xBF0F,0xBF10,
+0xBF11,0xBF12,0xBF13,0xBF14,0xBF15,0xBF16,0xBF17,0xBF1A,
+0xBF1E,0xBF1F,0xBF20,0xBF21,0xBF22,0xBF23,0xBF24,0xBF25,
+0xBF26,0xBF27,0xBF28,0xBF29,0xBF2A,0xBF2B,0xBF2C,0xBF2D,
+0xBF2E,0xBF2F,0xBF30,0xBF31,0xBF32,0xBF33,0xBF34,0xBF35,
+0xBF36,0xBF37,0xBF38,0xBF39,0xBF3A,0xBF3B,0xBF3C,0xBF3D,
+0xBF3E,0xBF3F,0xBF42,0xBF43,0xBF45,0xBF46,0xBF47,0xBF49,
+0xBF4A,0xBF4B,0xBF4C,0xBF4D,0xBF4E,0xBF4F,0xBF52,0xBF53,
+0xBF54,0xBF56,0xBF57,0xBF58,0xBF59,0xBF5A,0xBF5B,0xBF5C,
+0xBF5D,0xBF5E,0xBF5F,0xBF60,0xBF61,0xBF62,0xBF63,0xBF64,
+0xBF65,0xBF66,0xBF67,0xBF68,0xBF69,0xBF6A,0xBF6B,0xBF6C,
+0xBF6D,0xBF6E,0xBF6F,0xBF70,0xBF71,0xBF72,0xBF73,0xBF74,
+0xBF75,0xBF76,0xBF77,0xBF78,0xBF79,0xBF7A,0xBF7B,0xBF7C,
+0xBF7D,0xBF7E,0xBF7F,0xBF80,0xBF81,0xBF82, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xBF83,0xBF84,0xBF85,0xBF86,0xBF87,0xBF88,0xBF89,0xBF8A,
+0xBF8B,0xBF8C,0xBF8D,0xBF8E,0xBF8F,0xBF90,0xBF91,0xBF92,
+0xBF93,0xBF95,0xBF96,0xBF97,0xBF98,0xBF99,0xBF9A,0xBF9B,
+0xBF9C,0xBF9D, 0, 0, 0, 0, 0, 0,
+0xBF9E,0xBF9F,0xBFA0,0xBFA1,0xBFA2,0xBFA3,0xBFA4,0xBFA5,
+0xBFA6,0xBFA7,0xBFA8,0xBFA9,0xBFAA,0xBFAB,0xBFAC,0xBFAD,
+0xBFAE,0xBFAF,0xBFB1,0xBFB2,0xBFB3,0xBFB4,0xBFB5,0xBFB6,
+0xBFB7,0xBFB8, 0, 0, 0, 0, 0, 0,
+0xBFB9,0xBFBA,0xBFBB,0xBFBC,0xBFBD,0xBFBE,0xBFBF,0xBFC0,
+0xBFC1,0xBFC2,0xBFC3,0xBFC4,0xBFC6,0xBFC7,0xBFC8,0xBFC9,
+0xBFCA,0xBFCB,0xBFCE,0xBFCF,0xBFD1,0xBFD2,0xBFD3,0xBFD5,
+0xBFD6,0xBFD7,0xBFD8,0xBFD9,0xBFDA,0xBFDB,0xBFDD,0xBFDE,
+0xBFE0,0xBFE2,0xBFE3,0xBFE4,0xBFE5,0xBFE6,0xBFE7,0xBFE8,
+0xBFE9,0xBFEA,0xBFEB,0xBFEC,0xBFED,0xBFEE,0xBFEF,0xBFF0,
+0xBFF1,0xBFF2,0xBFF3,0xBFF4,0xBFF5,0xBFF6,0xBFF7,0xBFF8,
+0xBFF9,0xBFFA,0xBFFB,0xBFFC,0xBFFD,0xBFFE,0xBFFF,0xC000,
+0xC001,0xC002,0xC003,0xC004,0xC005,0xC006,0xC007,0xC008,
+0xC009,0xC00A,0xC00B,0xC00C,0xC00D,0xC00E,0xC00F,0xC010,
+0xC011,0xC012,0xC013,0xC014,0xC015,0xC016,0xC017,0xC018,
+0xC019,0xC01A,0xC01B,0xC01C,0xC01D,0xC01E,0xC01F,0xC020,
+0xC021,0xC022,0xC023,0xC024,0xC025,0xC026,0xC027,0xC028,
+0xC029,0xC02A,0xC02B,0xC02C,0xC02D,0xC02E,0xC02F,0xC030,
+0xC031,0xC032,0xC033,0xC034,0xC035,0xC036,0xC037,0xC038,
+0xC039,0xC03A,0xC03B,0xC03D,0xC03E,0xC03F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC040,0xC041,0xC042,0xC043,0xC044,0xC045,0xC046,0xC047,
+0xC048,0xC049,0xC04A,0xC04B,0xC04C,0xC04D,0xC04E,0xC04F,
+0xC050,0xC052,0xC053,0xC054,0xC055,0xC056,0xC057,0xC059,
+0xC05A,0xC05B, 0, 0, 0, 0, 0, 0,
+0xC05D,0xC05E,0xC05F,0xC061,0xC062,0xC063,0xC064,0xC065,
+0xC066,0xC067,0xC06A,0xC06B,0xC06C,0xC06D,0xC06E,0xC06F,
+0xC070,0xC071,0xC072,0xC073,0xC074,0xC075,0xC076,0xC077,
+0xC078,0xC079, 0, 0, 0, 0, 0, 0,
+0xC07A,0xC07B,0xC07C,0xC07D,0xC07E,0xC07F,0xC080,0xC081,
+0xC082,0xC083,0xC084,0xC085,0xC086,0xC087,0xC088,0xC089,
+0xC08A,0xC08B,0xC08C,0xC08D,0xC08E,0xC08F,0xC092,0xC093,
+0xC095,0xC096,0xC097,0xC099,0xC09A,0xC09B,0xC09C,0xC09D,
+0xC09E,0xC09F,0xC0A2,0xC0A4,0xC0A6,0xC0A7,0xC0A8,0xC0A9,
+0xC0AA,0xC0AB,0xC0AE,0xC0B1,0xC0B2,0xC0B7,0xC0B8,0xC0B9,
+0xC0BA,0xC0BB,0xC0BE,0xC0C2,0xC0C3,0xC0C4,0xC0C6,0xC0C7,
+0xC0CA,0xC0CB,0xC0CD,0xC0CE,0xC0CF,0xC0D1,0xC0D2,0xC0D3,
+0xC0D4,0xC0D5,0xC0D6,0xC0D7,0xC0DA,0xC0DE,0xC0DF,0xC0E0,
+0xC0E1,0xC0E2,0xC0E3,0xC0E6,0xC0E7,0xC0E9,0xC0EA,0xC0EB,
+0xC0ED,0xC0EE,0xC0EF,0xC0F0,0xC0F1,0xC0F2,0xC0F3,0xC0F6,
+0xC0F8,0xC0FA,0xC0FB,0xC0FC,0xC0FD,0xC0FE,0xC0FF,0xC101,
+0xC102,0xC103,0xC105,0xC106,0xC107,0xC109,0xC10A,0xC10B,
+0xC10C,0xC10D,0xC10E,0xC10F,0xC111,0xC112,0xC113,0xC114,
+0xC116,0xC117,0xC118,0xC119,0xC11A,0xC11B,0xC121,0xC122,
+0xC125,0xC128,0xC129,0xC12A,0xC12B,0xC12E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC132,0xC133,0xC134,0xC135,0xC137,0xC13A,0xC13B,0xC13D,
+0xC13E,0xC13F,0xC141,0xC142,0xC143,0xC144,0xC145,0xC146,
+0xC147,0xC14A,0xC14E,0xC14F,0xC150,0xC151,0xC152,0xC153,
+0xC156,0xC157, 0, 0, 0, 0, 0, 0,
+0xC159,0xC15A,0xC15B,0xC15D,0xC15E,0xC15F,0xC160,0xC161,
+0xC162,0xC163,0xC166,0xC16A,0xC16B,0xC16C,0xC16D,0xC16E,
+0xC16F,0xC171,0xC172,0xC173,0xC175,0xC176,0xC177,0xC179,
+0xC17A,0xC17B, 0, 0, 0, 0, 0, 0,
+0xC17C,0xC17D,0xC17E,0xC17F,0xC180,0xC181,0xC182,0xC183,
+0xC184,0xC186,0xC187,0xC188,0xC189,0xC18A,0xC18B,0xC18F,
+0xC191,0xC192,0xC193,0xC195,0xC197,0xC198,0xC199,0xC19A,
+0xC19B,0xC19E,0xC1A0,0xC1A2,0xC1A3,0xC1A4,0xC1A6,0xC1A7,
+0xC1AA,0xC1AB,0xC1AD,0xC1AE,0xC1AF,0xC1B1,0xC1B2,0xC1B3,
+0xC1B4,0xC1B5,0xC1B6,0xC1B7,0xC1B8,0xC1B9,0xC1BA,0xC1BB,
+0xC1BC,0xC1BE,0xC1BF,0xC1C0,0xC1C1,0xC1C2,0xC1C3,0xC1C5,
+0xC1C6,0xC1C7,0xC1C9,0xC1CA,0xC1CB,0xC1CD,0xC1CE,0xC1CF,
+0xC1D0,0xC1D1,0xC1D2,0xC1D3,0xC1D5,0xC1D6,0xC1D9,0xC1DA,
+0xC1DB,0xC1DC,0xC1DD,0xC1DE,0xC1DF,0xC1E1,0xC1E2,0xC1E3,
+0xC1E5,0xC1E6,0xC1E7,0xC1E9,0xC1EA,0xC1EB,0xC1EC,0xC1ED,
+0xC1EE,0xC1EF,0xC1F2,0xC1F4,0xC1F5,0xC1F6,0xC1F7,0xC1F8,
+0xC1F9,0xC1FA,0xC1FB,0xC1FE,0xC1FF,0xC201,0xC202,0xC203,
+0xC205,0xC206,0xC207,0xC208,0xC209,0xC20A,0xC20B,0xC20E,
+0xC210,0xC212,0xC213,0xC214,0xC215,0xC216,0xC217,0xC21A,
+0xC21B,0xC21D,0xC21E,0xC221,0xC222,0xC223, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC224,0xC225,0xC226,0xC227,0xC22A,0xC22C,0xC22E,0xC230,
+0xC233,0xC235,0xC236,0xC237,0xC238,0xC239,0xC23A,0xC23B,
+0xC23C,0xC23D,0xC23E,0xC23F,0xC240,0xC241,0xC242,0xC243,
+0xC244,0xC245, 0, 0, 0, 0, 0, 0,
+0xC246,0xC247,0xC249,0xC24A,0xC24B,0xC24C,0xC24D,0xC24E,
+0xC24F,0xC252,0xC253,0xC255,0xC256,0xC257,0xC259,0xC25A,
+0xC25B,0xC25C,0xC25D,0xC25E,0xC25F,0xC261,0xC262,0xC263,
+0xC264,0xC266, 0, 0, 0, 0, 0, 0,
+0xC267,0xC268,0xC269,0xC26A,0xC26B,0xC26E,0xC26F,0xC271,
+0xC272,0xC273,0xC275,0xC276,0xC277,0xC278,0xC279,0xC27A,
+0xC27B,0xC27E,0xC280,0xC282,0xC283,0xC284,0xC285,0xC286,
+0xC287,0xC28A,0xC28B,0xC28C,0xC28D,0xC28E,0xC28F,0xC291,
+0xC292,0xC293,0xC294,0xC295,0xC296,0xC297,0xC299,0xC29A,
+0xC29C,0xC29E,0xC29F,0xC2A0,0xC2A1,0xC2A2,0xC2A3,0xC2A6,
+0xC2A7,0xC2A9,0xC2AA,0xC2AB,0xC2AE,0xC2AF,0xC2B0,0xC2B1,
+0xC2B2,0xC2B3,0xC2B6,0xC2B8,0xC2BA,0xC2BB,0xC2BC,0xC2BD,
+0xC2BE,0xC2BF,0xC2C0,0xC2C1,0xC2C2,0xC2C3,0xC2C4,0xC2C5,
+0xC2C6,0xC2C7,0xC2C8,0xC2C9,0xC2CA,0xC2CB,0xC2CC,0xC2CD,
+0xC2CE,0xC2CF,0xC2D0,0xC2D1,0xC2D2,0xC2D3,0xC2D4,0xC2D5,
+0xC2D6,0xC2D7,0xC2D8,0xC2D9,0xC2DA,0xC2DB,0xC2DE,0xC2DF,
+0xC2E1,0xC2E2,0xC2E5,0xC2E6,0xC2E7,0xC2E8,0xC2E9,0xC2EA,
+0xC2EE,0xC2F0,0xC2F2,0xC2F3,0xC2F4,0xC2F5,0xC2F7,0xC2FA,
+0xC2FD,0xC2FE,0xC2FF,0xC301,0xC302,0xC303,0xC304,0xC305,
+0xC306,0xC307,0xC30A,0xC30B,0xC30E,0xC30F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC310,0xC311,0xC312,0xC316,0xC317,0xC319,0xC31A,0xC31B,
+0xC31D,0xC31E,0xC31F,0xC320,0xC321,0xC322,0xC323,0xC326,
+0xC327,0xC32A,0xC32B,0xC32C,0xC32D,0xC32E,0xC32F,0xC330,
+0xC331,0xC332, 0, 0, 0, 0, 0, 0,
+0xC333,0xC334,0xC335,0xC336,0xC337,0xC338,0xC339,0xC33A,
+0xC33B,0xC33C,0xC33D,0xC33E,0xC33F,0xC340,0xC341,0xC342,
+0xC343,0xC344,0xC346,0xC347,0xC348,0xC349,0xC34A,0xC34B,
+0xC34C,0xC34D, 0, 0, 0, 0, 0, 0,
+0xC34E,0xC34F,0xC350,0xC351,0xC352,0xC353,0xC354,0xC355,
+0xC356,0xC357,0xC358,0xC359,0xC35A,0xC35B,0xC35C,0xC35D,
+0xC35E,0xC35F,0xC360,0xC361,0xC362,0xC363,0xC364,0xC365,
+0xC366,0xC367,0xC36A,0xC36B,0xC36D,0xC36E,0xC36F,0xC371,
+0xC373,0xC374,0xC375,0xC376,0xC377,0xC37A,0xC37B,0xC37E,
+0xC37F,0xC380,0xC381,0xC382,0xC383,0xC385,0xC386,0xC387,
+0xC389,0xC38A,0xC38B,0xC38D,0xC38E,0xC38F,0xC390,0xC391,
+0xC392,0xC393,0xC394,0xC395,0xC396,0xC397,0xC398,0xC399,
+0xC39A,0xC39B,0xC39C,0xC39D,0xC39E,0xC39F,0xC3A0,0xC3A1,
+0xC3A2,0xC3A3,0xC3A4,0xC3A5,0xC3A6,0xC3A7,0xC3A8,0xC3A9,
+0xC3AA,0xC3AB,0xC3AC,0xC3AD,0xC3AE,0xC3AF,0xC3B0,0xC3B1,
+0xC3B2,0xC3B3,0xC3B4,0xC3B5,0xC3B6,0xC3B7,0xC3B8,0xC3B9,
+0xC3BA,0xC3BB,0xC3BC,0xC3BD,0xC3BE,0xC3BF,0xC3C1,0xC3C2,
+0xC3C3,0xC3C4,0xC3C5,0xC3C6,0xC3C7,0xC3C8,0xC3C9,0xC3CA,
+0xC3CB,0xC3CC,0xC3CD,0xC3CE,0xC3CF,0xC3D0,0xC3D1,0xC3D2,
+0xC3D3,0xC3D4,0xC3D5,0xC3D6,0xC3D7,0xC3DA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC3DB,0xC3DD,0xC3DE,0xC3E1,0xC3E3,0xC3E4,0xC3E5,0xC3E6,
+0xC3E7,0xC3EA,0xC3EB,0xC3EC,0xC3EE,0xC3EF,0xC3F0,0xC3F1,
+0xC3F2,0xC3F3,0xC3F6,0xC3F7,0xC3F9,0xC3FA,0xC3FB,0xC3FC,
+0xC3FD,0xC3FE, 0, 0, 0, 0, 0, 0,
+0xC3FF,0xC400,0xC401,0xC402,0xC403,0xC404,0xC405,0xC406,
+0xC407,0xC409,0xC40A,0xC40B,0xC40C,0xC40D,0xC40E,0xC40F,
+0xC411,0xC412,0xC413,0xC414,0xC415,0xC416,0xC417,0xC418,
+0xC419,0xC41A, 0, 0, 0, 0, 0, 0,
+0xC41B,0xC41C,0xC41D,0xC41E,0xC41F,0xC420,0xC421,0xC422,
+0xC423,0xC425,0xC426,0xC427,0xC428,0xC429,0xC42A,0xC42B,
+0xC42D,0xC42E,0xC42F,0xC431,0xC432,0xC433,0xC435,0xC436,
+0xC437,0xC438,0xC439,0xC43A,0xC43B,0xC43E,0xC43F,0xC440,
+0xC441,0xC442,0xC443,0xC444,0xC445,0xC446,0xC447,0xC449,
+0xC44A,0xC44B,0xC44C,0xC44D,0xC44E,0xC44F,0xC450,0xC451,
+0xC452,0xC453,0xC454,0xC455,0xC456,0xC457,0xC458,0xC459,
+0xC45A,0xC45B,0xC45C,0xC45D,0xC45E,0xC45F,0xC460,0xC461,
+0xC462,0xC463,0xC466,0xC467,0xC469,0xC46A,0xC46B,0xC46D,
+0xC46E,0xC46F,0xC470,0xC471,0xC472,0xC473,0xC476,0xC477,
+0xC478,0xC47A,0xC47B,0xC47C,0xC47D,0xC47E,0xC47F,0xC481,
+0xC482,0xC483,0xC484,0xC485,0xC486,0xC487,0xC488,0xC489,
+0xC48A,0xC48B,0xC48C,0xC48D,0xC48E,0xC48F,0xC490,0xC491,
+0xC492,0xC493,0xC495,0xC496,0xC497,0xC498,0xC499,0xC49A,
+0xC49B,0xC49D,0xC49E,0xC49F,0xC4A0,0xC4A1,0xC4A2,0xC4A3,
+0xC4A4,0xC4A5,0xC4A6,0xC4A7,0xC4A8,0xC4A9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC4AA,0xC4AB,0xC4AC,0xC4AD,0xC4AE,0xC4AF,0xC4B0,0xC4B1,
+0xC4B2,0xC4B3,0xC4B4,0xC4B5,0xC4B6,0xC4B7,0xC4B9,0xC4BA,
+0xC4BB,0xC4BD,0xC4BE,0xC4BF,0xC4C0,0xC4C1,0xC4C2,0xC4C3,
+0xC4C4,0xC4C5, 0, 0, 0, 0, 0, 0,
+0xC4C6,0xC4C7,0xC4C8,0xC4C9,0xC4CA,0xC4CB,0xC4CC,0xC4CD,
+0xC4CE,0xC4CF,0xC4D0,0xC4D1,0xC4D2,0xC4D3,0xC4D4,0xC4D5,
+0xC4D6,0xC4D7,0xC4D8,0xC4D9,0xC4DA,0xC4DB,0xC4DC,0xC4DD,
+0xC4DE,0xC4DF, 0, 0, 0, 0, 0, 0,
+0xC4E0,0xC4E1,0xC4E2,0xC4E3,0xC4E4,0xC4E5,0xC4E6,0xC4E7,
+0xC4E8,0xC4EA,0xC4EB,0xC4EC,0xC4ED,0xC4EE,0xC4EF,0xC4F2,
+0xC4F3,0xC4F5,0xC4F6,0xC4F7,0xC4F9,0xC4FB,0xC4FC,0xC4FD,
+0xC4FE,0xC502,0xC503,0xC504,0xC505,0xC506,0xC507,0xC508,
+0xC509,0xC50A,0xC50B,0xC50D,0xC50E,0xC50F,0xC511,0xC512,
+0xC513,0xC515,0xC516,0xC517,0xC518,0xC519,0xC51A,0xC51B,
+0xC51D,0xC51E,0xC51F,0xC520,0xC521,0xC522,0xC523,0xC524,
+0xC525,0xC526,0xC527,0xC52A,0xC52B,0xC52D,0xC52E,0xC52F,
+0xC531,0xC532,0xC533,0xC534,0xC535,0xC536,0xC537,0xC53A,
+0xC53C,0xC53E,0xC53F,0xC540,0xC541,0xC542,0xC543,0xC546,
+0xC547,0xC54B,0xC54F,0xC550,0xC551,0xC552,0xC556,0xC55A,
+0xC55B,0xC55C,0xC55F,0xC562,0xC563,0xC565,0xC566,0xC567,
+0xC569,0xC56A,0xC56B,0xC56C,0xC56D,0xC56E,0xC56F,0xC572,
+0xC576,0xC577,0xC578,0xC579,0xC57A,0xC57B,0xC57E,0xC57F,
+0xC581,0xC582,0xC583,0xC585,0xC586,0xC588,0xC589,0xC58A,
+0xC58B,0xC58E,0xC590,0xC592,0xC593,0xC594, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC596,0xC599,0xC59A,0xC59B,0xC59D,0xC59E,0xC59F,0xC5A1,
+0xC5A2,0xC5A3,0xC5A4,0xC5A5,0xC5A6,0xC5A7,0xC5A8,0xC5AA,
+0xC5AB,0xC5AC,0xC5AD,0xC5AE,0xC5AF,0xC5B0,0xC5B1,0xC5B2,
+0xC5B3,0xC5B6, 0, 0, 0, 0, 0, 0,
+0xC5B7,0xC5BA,0xC5BF,0xC5C0,0xC5C1,0xC5C2,0xC5C3,0xC5CB,
+0xC5CD,0xC5CF,0xC5D2,0xC5D3,0xC5D5,0xC5D6,0xC5D7,0xC5D9,
+0xC5DA,0xC5DB,0xC5DC,0xC5DD,0xC5DE,0xC5DF,0xC5E2,0xC5E4,
+0xC5E6,0xC5E7, 0, 0, 0, 0, 0, 0,
+0xC5E8,0xC5E9,0xC5EA,0xC5EB,0xC5EF,0xC5F1,0xC5F2,0xC5F3,
+0xC5F5,0xC5F8,0xC5F9,0xC5FA,0xC5FB,0xC602,0xC603,0xC604,
+0xC609,0xC60A,0xC60B,0xC60D,0xC60E,0xC60F,0xC611,0xC612,
+0xC613,0xC614,0xC615,0xC616,0xC617,0xC61A,0xC61D,0xC61E,
+0xC61F,0xC620,0xC621,0xC622,0xC623,0xC626,0xC627,0xC629,
+0xC62A,0xC62B,0xC62F,0xC631,0xC632,0xC636,0xC638,0xC63A,
+0xC63C,0xC63D,0xC63E,0xC63F,0xC642,0xC643,0xC645,0xC646,
+0xC647,0xC649,0xC64A,0xC64B,0xC64C,0xC64D,0xC64E,0xC64F,
+0xC652,0xC656,0xC657,0xC658,0xC659,0xC65A,0xC65B,0xC65E,
+0xC65F,0xC661,0xC662,0xC663,0xC664,0xC665,0xC666,0xC667,
+0xC668,0xC669,0xC66A,0xC66B,0xC66D,0xC66E,0xC670,0xC672,
+0xC673,0xC674,0xC675,0xC676,0xC677,0xC67A,0xC67B,0xC67D,
+0xC67E,0xC67F,0xC681,0xC682,0xC683,0xC684,0xC685,0xC686,
+0xC687,0xC68A,0xC68C,0xC68E,0xC68F,0xC690,0xC691,0xC692,
+0xC693,0xC696,0xC697,0xC699,0xC69A,0xC69B,0xC69D,0xC69E,
+0xC69F,0xC6A0,0xC6A1,0xC6A2,0xC6A3,0xC6A6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC6A8,0xC6AA,0xC6AB,0xC6AC,0xC6AD,0xC6AE,0xC6AF,0xC6B2,
+0xC6B3,0xC6B5,0xC6B6,0xC6B7,0xC6BB,0xC6BC,0xC6BD,0xC6BE,
+0xC6BF,0xC6C2,0xC6C4,0xC6C6,0xC6C7,0xC6C8,0xC6C9,0xC6CA,
+0xC6CB,0xC6CE, 0, 0, 0, 0, 0, 0,
+0xC6CF,0xC6D1,0xC6D2,0xC6D3,0xC6D5,0xC6D6,0xC6D7,0xC6D8,
+0xC6D9,0xC6DA,0xC6DB,0xC6DE,0xC6DF,0xC6E2,0xC6E3,0xC6E4,
+0xC6E5,0xC6E6,0xC6E7,0xC6EA,0xC6EB,0xC6ED,0xC6EE,0xC6EF,
+0xC6F1,0xC6F2, 0, 0, 0, 0, 0, 0,
+0xC6F3,0xC6F4,0xC6F5,0xC6F6,0xC6F7,0xC6FA,0xC6FB,0xC6FC,
+0xC6FE,0xC6FF,0xC700,0xC701,0xC702,0xC703,0xC706,0xC707,
+0xC709,0xC70A,0xC70B,0xC70D,0xC70E,0xC70F,0xC710,0xC711,
+0xC712,0xC713,0xC716,0xC718,0xC71A,0xC71B,0xC71C,0xC71D,
+0xC71E,0xC71F,0xC722,0xC723,0xC725,0xC726,0xC727,0xC729,
+0xC72A,0xC72B,0xC72C,0xC72D,0xC72E,0xC72F,0xC732,0xC734,
+0xC736,0xC738,0xC739,0xC73A,0xC73B,0xC73E,0xC73F,0xC741,
+0xC742,0xC743,0xC745,0xC746,0xC747,0xC748,0xC749,0xC74B,
+0xC74E,0xC750,0xC759,0xC75A,0xC75B,0xC75D,0xC75E,0xC75F,
+0xC761,0xC762,0xC763,0xC764,0xC765,0xC766,0xC767,0xC769,
+0xC76A,0xC76C,0xC76D,0xC76E,0xC76F,0xC770,0xC771,0xC772,
+0xC773,0xC776,0xC777,0xC779,0xC77A,0xC77B,0xC77F,0xC780,
+0xC781,0xC782,0xC786,0xC78B,0xC78C,0xC78D,0xC78F,0xC792,
+0xC793,0xC795,0xC799,0xC79B,0xC79C,0xC79D,0xC79E,0xC79F,
+0xC7A2,0xC7A7,0xC7A8,0xC7A9,0xC7AA,0xC7AB,0xC7AE,0xC7AF,
+0xC7B1,0xC7B2,0xC7B3,0xC7B5,0xC7B6,0xC7B7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC7B8,0xC7B9,0xC7BA,0xC7BB,0xC7BE,0xC7C2,0xC7C3,0xC7C4,
+0xC7C5,0xC7C6,0xC7C7,0xC7CA,0xC7CB,0xC7CD,0xC7CF,0xC7D1,
+0xC7D2,0xC7D3,0xC7D4,0xC7D5,0xC7D6,0xC7D7,0xC7D9,0xC7DA,
+0xC7DB,0xC7DC, 0, 0, 0, 0, 0, 0,
+0xC7DE,0xC7DF,0xC7E0,0xC7E1,0xC7E2,0xC7E3,0xC7E5,0xC7E6,
+0xC7E7,0xC7E9,0xC7EA,0xC7EB,0xC7ED,0xC7EE,0xC7EF,0xC7F0,
+0xC7F1,0xC7F2,0xC7F3,0xC7F4,0xC7F5,0xC7F6,0xC7F7,0xC7F8,
+0xC7F9,0xC7FA, 0, 0, 0, 0, 0, 0,
+0xC7FB,0xC7FC,0xC7FD,0xC7FE,0xC7FF,0xC802,0xC803,0xC805,
+0xC806,0xC807,0xC809,0xC80B,0xC80C,0xC80D,0xC80E,0xC80F,
+0xC812,0xC814,0xC817,0xC818,0xC819,0xC81A,0xC81B,0xC81E,
+0xC81F,0xC821,0xC822,0xC823,0xC825,0xC826,0xC827,0xC828,
+0xC829,0xC82A,0xC82B,0xC82E,0xC830,0xC832,0xC833,0xC834,
+0xC835,0xC836,0xC837,0xC839,0xC83A,0xC83B,0xC83D,0xC83E,
+0xC83F,0xC841,0xC842,0xC843,0xC844,0xC845,0xC846,0xC847,
+0xC84A,0xC84B,0xC84E,0xC84F,0xC850,0xC851,0xC852,0xC853,
+0xC855,0xC856,0xC857,0xC858,0xC859,0xC85A,0xC85B,0xC85C,
+0xC85D,0xC85E,0xC85F,0xC860,0xC861,0xC862,0xC863,0xC864,
+0xC865,0xC866,0xC867,0xC868,0xC869,0xC86A,0xC86B,0xC86C,
+0xC86D,0xC86E,0xC86F,0xC872,0xC873,0xC875,0xC876,0xC877,
+0xC879,0xC87B,0xC87C,0xC87D,0xC87E,0xC87F,0xC882,0xC884,
+0xC888,0xC889,0xC88A,0xC88E,0xC88F,0xC890,0xC891,0xC892,
+0xC893,0xC895,0xC896,0xC897,0xC898,0xC899,0xC89A,0xC89B,
+0xC89C,0xC89E,0xC8A0,0xC8A2,0xC8A3,0xC8A4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC8A5,0xC8A6,0xC8A7,0xC8A9,0xC8AA,0xC8AB,0xC8AC,0xC8AD,
+0xC8AE,0xC8AF,0xC8B0,0xC8B1,0xC8B2,0xC8B3,0xC8B4,0xC8B5,
+0xC8B6,0xC8B7,0xC8B8,0xC8B9,0xC8BA,0xC8BB,0xC8BE,0xC8BF,
+0xC8C0,0xC8C1, 0, 0, 0, 0, 0, 0,
+0xC8C2,0xC8C3,0xC8C5,0xC8C6,0xC8C7,0xC8C9,0xC8CA,0xC8CB,
+0xC8CD,0xC8CE,0xC8CF,0xC8D0,0xC8D1,0xC8D2,0xC8D3,0xC8D6,
+0xC8D8,0xC8DA,0xC8DB,0xC8DC,0xC8DD,0xC8DE,0xC8DF,0xC8E2,
+0xC8E3,0xC8E5, 0, 0, 0, 0, 0, 0,
+0xC8E6,0xC8E7,0xC8E8,0xC8E9,0xC8EA,0xC8EB,0xC8EC,0xC8ED,
+0xC8EE,0xC8EF,0xC8F0,0xC8F1,0xC8F2,0xC8F3,0xC8F4,0xC8F6,
+0xC8F7,0xC8F8,0xC8F9,0xC8FA,0xC8FB,0xC8FE,0xC8FF,0xC901,
+0xC902,0xC903,0xC907,0xC908,0xC909,0xC90A,0xC90B,0xC90E,
+0x3000,0x3001,0x3002,0x00B7,0x2025,0x2026,0x00A8,0x3003,
+0x00AD,0x2015,0x2225,0xFF3C,0x223C,0x2018,0x2019,0x201C,
+0x201D,0x3014,0x3015,0x3008,0x3009,0x300A,0x300B,0x300C,
+0x300D,0x300E,0x300F,0x3010,0x3011,0x00B1,0x00D7,0x00F7,
+0x2260,0x2264,0x2265,0x221E,0x2234,0x00B0,0x2032,0x2033,
+0x2103,0x212B,0xFFE0,0xFFE1,0xFFE5,0x2642,0x2640,0x2220,
+0x22A5,0x2312,0x2202,0x2207,0x2261,0x2252,0x00A7,0x203B,
+0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7,0x25C6,0x25A1,
+0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x2192,0x2190,0x2191,
+0x2193,0x2194,0x3013,0x226A,0x226B,0x221A,0x223D,0x221D,
+0x2235,0x222B,0x222C,0x2208,0x220B,0x2286,0x2287,0x2282,
+0x2283,0x222A,0x2229,0x2227,0x2228,0xFFE2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC910,0xC912,0xC913,0xC914,0xC915,0xC916,0xC917,0xC919,
+0xC91A,0xC91B,0xC91C,0xC91D,0xC91E,0xC91F,0xC920,0xC921,
+0xC922,0xC923,0xC924,0xC925,0xC926,0xC927,0xC928,0xC929,
+0xC92A,0xC92B, 0, 0, 0, 0, 0, 0,
+0xC92D,0xC92E,0xC92F,0xC930,0xC931,0xC932,0xC933,0xC935,
+0xC936,0xC937,0xC938,0xC939,0xC93A,0xC93B,0xC93C,0xC93D,
+0xC93E,0xC93F,0xC940,0xC941,0xC942,0xC943,0xC944,0xC945,
+0xC946,0xC947, 0, 0, 0, 0, 0, 0,
+0xC948,0xC949,0xC94A,0xC94B,0xC94C,0xC94D,0xC94E,0xC94F,
+0xC952,0xC953,0xC955,0xC956,0xC957,0xC959,0xC95A,0xC95B,
+0xC95C,0xC95D,0xC95E,0xC95F,0xC962,0xC964,0xC965,0xC966,
+0xC967,0xC968,0xC969,0xC96A,0xC96B,0xC96D,0xC96E,0xC96F,
+0x21D2,0x21D4,0x2200,0x2203,0x00B4,0xFF5E,0x02C7,0x02D8,
+0x02DD,0x02DA,0x02D9,0x00B8,0x02DB,0x00A1,0x00BF,0x02D0,
+0x222E,0x2211,0x220F,0x00A4,0x2109,0x2030,0x25C1,0x25C0,
+0x25B7,0x25B6,0x2664,0x2660,0x2661,0x2665,0x2667,0x2663,
+0x2299,0x25C8,0x25A3,0x25D0,0x25D1,0x2592,0x25A4,0x25A5,
+0x25A8,0x25A7,0x25A6,0x25A9,0x2668,0x260F,0x260E,0x261C,
+0x261E,0x00B6,0x2020,0x2021,0x2195,0x2197,0x2199,0x2196,
+0x2198,0x266D,0x2669,0x266A,0x266C,0x327F,0x321C,0x2116,
+0x33C7,0x2122,0x33C2,0x33D8,0x2121, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC971,0xC972,0xC973,0xC975,0xC976,0xC977,0xC978,0xC979,
+0xC97A,0xC97B,0xC97D,0xC97E,0xC97F,0xC980,0xC981,0xC982,
+0xC983,0xC984,0xC985,0xC986,0xC987,0xC98A,0xC98B,0xC98D,
+0xC98E,0xC98F, 0, 0, 0, 0, 0, 0,
+0xC991,0xC992,0xC993,0xC994,0xC995,0xC996,0xC997,0xC99A,
+0xC99C,0xC99E,0xC99F,0xC9A0,0xC9A1,0xC9A2,0xC9A3,0xC9A4,
+0xC9A5,0xC9A6,0xC9A7,0xC9A8,0xC9A9,0xC9AA,0xC9AB,0xC9AC,
+0xC9AD,0xC9AE, 0, 0, 0, 0, 0, 0,
+0xC9AF,0xC9B0,0xC9B1,0xC9B2,0xC9B3,0xC9B4,0xC9B5,0xC9B6,
+0xC9B7,0xC9B8,0xC9B9,0xC9BA,0xC9BB,0xC9BC,0xC9BD,0xC9BE,
+0xC9BF,0xC9C2,0xC9C3,0xC9C5,0xC9C6,0xC9C9,0xC9CB,0xC9CC,
+0xC9CD,0xC9CE,0xC9CF,0xC9D2,0xC9D4,0xC9D7,0xC9D8,0xC9DB,
+0xFF01,0xFF02,0xFF03,0xFF04,0xFF05,0xFF06,0xFF07,0xFF08,
+0xFF09,0xFF0A,0xFF0B,0xFF0C,0xFF0D,0xFF0E,0xFF0F,0xFF10,
+0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,
+0xFF19,0xFF1A,0xFF1B,0xFF1C,0xFF1D,0xFF1E,0xFF1F,0xFF20,
+0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,
+0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,
+0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,
+0xFF39,0xFF3A,0xFF3B,0xFFE6,0xFF3D,0xFF3E,0xFF3F,0xFF40,
+0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,
+0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,
+0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,
+0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFFE3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xC9DE,0xC9DF,0xC9E1,0xC9E3,0xC9E5,0xC9E6,0xC9E8,0xC9E9,
+0xC9EA,0xC9EB,0xC9EE,0xC9F2,0xC9F3,0xC9F4,0xC9F5,0xC9F6,
+0xC9F7,0xC9FA,0xC9FB,0xC9FD,0xC9FE,0xC9FF,0xCA01,0xCA02,
+0xCA03,0xCA04, 0, 0, 0, 0, 0, 0,
+0xCA05,0xCA06,0xCA07,0xCA0A,0xCA0E,0xCA0F,0xCA10,0xCA11,
+0xCA12,0xCA13,0xCA15,0xCA16,0xCA17,0xCA19,0xCA1A,0xCA1B,
+0xCA1C,0xCA1D,0xCA1E,0xCA1F,0xCA20,0xCA21,0xCA22,0xCA23,
+0xCA24,0xCA25, 0, 0, 0, 0, 0, 0,
+0xCA26,0xCA27,0xCA28,0xCA2A,0xCA2B,0xCA2C,0xCA2D,0xCA2E,
+0xCA2F,0xCA30,0xCA31,0xCA32,0xCA33,0xCA34,0xCA35,0xCA36,
+0xCA37,0xCA38,0xCA39,0xCA3A,0xCA3B,0xCA3C,0xCA3D,0xCA3E,
+0xCA3F,0xCA40,0xCA41,0xCA42,0xCA43,0xCA44,0xCA45,0xCA46,
+0x3131,0x3132,0x3133,0x3134,0x3135,0x3136,0x3137,0x3138,
+0x3139,0x313A,0x313B,0x313C,0x313D,0x313E,0x313F,0x3140,
+0x3141,0x3142,0x3143,0x3144,0x3145,0x3146,0x3147,0x3148,
+0x3149,0x314A,0x314B,0x314C,0x314D,0x314E,0x314F,0x3150,
+0x3151,0x3152,0x3153,0x3154,0x3155,0x3156,0x3157,0x3158,
+0x3159,0x315A,0x315B,0x315C,0x315D,0x315E,0x315F,0x3160,
+0x3161,0x3162,0x3163,0x3164,0x3165,0x3166,0x3167,0x3168,
+0x3169,0x316A,0x316B,0x316C,0x316D,0x316E,0x316F,0x3170,
+0x3171,0x3172,0x3173,0x3174,0x3175,0x3176,0x3177,0x3178,
+0x3179,0x317A,0x317B,0x317C,0x317D,0x317E,0x317F,0x3180,
+0x3181,0x3182,0x3183,0x3184,0x3185,0x3186,0x3187,0x3188,
+0x3189,0x318A,0x318B,0x318C,0x318D,0x318E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCA47,0xCA48,0xCA49,0xCA4A,0xCA4B,0xCA4E,0xCA4F,0xCA51,
+0xCA52,0xCA53,0xCA55,0xCA56,0xCA57,0xCA58,0xCA59,0xCA5A,
+0xCA5B,0xCA5E,0xCA62,0xCA63,0xCA64,0xCA65,0xCA66,0xCA67,
+0xCA69,0xCA6A, 0, 0, 0, 0, 0, 0,
+0xCA6B,0xCA6C,0xCA6D,0xCA6E,0xCA6F,0xCA70,0xCA71,0xCA72,
+0xCA73,0xCA74,0xCA75,0xCA76,0xCA77,0xCA78,0xCA79,0xCA7A,
+0xCA7B,0xCA7C,0xCA7E,0xCA7F,0xCA80,0xCA81,0xCA82,0xCA83,
+0xCA85,0xCA86, 0, 0, 0, 0, 0, 0,
+0xCA87,0xCA88,0xCA89,0xCA8A,0xCA8B,0xCA8C,0xCA8D,0xCA8E,
+0xCA8F,0xCA90,0xCA91,0xCA92,0xCA93,0xCA94,0xCA95,0xCA96,
+0xCA97,0xCA99,0xCA9A,0xCA9B,0xCA9C,0xCA9D,0xCA9E,0xCA9F,
+0xCAA0,0xCAA1,0xCAA2,0xCAA3,0xCAA4,0xCAA5,0xCAA6,0xCAA7,
+0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,
+0x2178,0x2179, 0, 0, 0, 0, 0,0x2160,
+0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,
+0x2169, 0, 0, 0, 0, 0, 0, 0,
+0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
+0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
+0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,
+0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,0x03C0,
+0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCAA8,0xCAA9,0xCAAA,0xCAAB,0xCAAC,0xCAAD,0xCAAE,0xCAAF,
+0xCAB0,0xCAB1,0xCAB2,0xCAB3,0xCAB4,0xCAB5,0xCAB6,0xCAB7,
+0xCAB8,0xCAB9,0xCABA,0xCABB,0xCABE,0xCABF,0xCAC1,0xCAC2,
+0xCAC3,0xCAC5, 0, 0, 0, 0, 0, 0,
+0xCAC6,0xCAC7,0xCAC8,0xCAC9,0xCACA,0xCACB,0xCACE,0xCAD0,
+0xCAD2,0xCAD4,0xCAD5,0xCAD6,0xCAD7,0xCADA,0xCADB,0xCADC,
+0xCADD,0xCADE,0xCADF,0xCAE1,0xCAE2,0xCAE3,0xCAE4,0xCAE5,
+0xCAE6,0xCAE7, 0, 0, 0, 0, 0, 0,
+0xCAE8,0xCAE9,0xCAEA,0xCAEB,0xCAED,0xCAEE,0xCAEF,0xCAF0,
+0xCAF1,0xCAF2,0xCAF3,0xCAF5,0xCAF6,0xCAF7,0xCAF8,0xCAF9,
+0xCAFA,0xCAFB,0xCAFC,0xCAFD,0xCAFE,0xCAFF,0xCB00,0xCB01,
+0xCB02,0xCB03,0xCB04,0xCB05,0xCB06,0xCB07,0xCB09,0xCB0A,
+0x2500,0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,
+0x2524,0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,
+0x2517,0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,
+0x2528,0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542,
+0x2512,0x2511,0x251A,0x2519,0x2516,0x2515,0x250E,0x250D,
+0x251E,0x251F,0x2521,0x2522,0x2526,0x2527,0x2529,0x252A,
+0x252D,0x252E,0x2531,0x2532,0x2535,0x2536,0x2539,0x253A,
+0x253D,0x253E,0x2540,0x2541,0x2543,0x2544,0x2545,0x2546,
+0x2547,0x2548,0x2549,0x254A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCB0B,0xCB0C,0xCB0D,0xCB0E,0xCB0F,0xCB11,0xCB12,0xCB13,
+0xCB15,0xCB16,0xCB17,0xCB19,0xCB1A,0xCB1B,0xCB1C,0xCB1D,
+0xCB1E,0xCB1F,0xCB22,0xCB23,0xCB24,0xCB25,0xCB26,0xCB27,
+0xCB28,0xCB29, 0, 0, 0, 0, 0, 0,
+0xCB2A,0xCB2B,0xCB2C,0xCB2D,0xCB2E,0xCB2F,0xCB30,0xCB31,
+0xCB32,0xCB33,0xCB34,0xCB35,0xCB36,0xCB37,0xCB38,0xCB39,
+0xCB3A,0xCB3B,0xCB3C,0xCB3D,0xCB3E,0xCB3F,0xCB40,0xCB42,
+0xCB43,0xCB44, 0, 0, 0, 0, 0, 0,
+0xCB45,0xCB46,0xCB47,0xCB4A,0xCB4B,0xCB4D,0xCB4E,0xCB4F,
+0xCB51,0xCB52,0xCB53,0xCB54,0xCB55,0xCB56,0xCB57,0xCB5A,
+0xCB5B,0xCB5C,0xCB5E,0xCB5F,0xCB60,0xCB61,0xCB62,0xCB63,
+0xCB65,0xCB66,0xCB67,0xCB68,0xCB69,0xCB6A,0xCB6B,0xCB6C,
+0x3395,0x3396,0x3397,0x2113,0x3398,0x33C4,0x33A3,0x33A4,
+0x33A5,0x33A6,0x3399,0x339A,0x339B,0x339C,0x339D,0x339E,
+0x339F,0x33A0,0x33A1,0x33A2,0x33CA,0x338D,0x338E,0x338F,
+0x33CF,0x3388,0x3389,0x33C8,0x33A7,0x33A8,0x33B0,0x33B1,
+0x33B2,0x33B3,0x33B4,0x33B5,0x33B6,0x33B7,0x33B8,0x33B9,
+0x3380,0x3381,0x3382,0x3383,0x3384,0x33BA,0x33BB,0x33BC,
+0x33BD,0x33BE,0x33BF,0x3390,0x3391,0x3392,0x3393,0x3394,
+0x2126,0x33C0,0x33C1,0x338A,0x338B,0x338C,0x33D6,0x33C5,
+0x33AD,0x33AE,0x33AF,0x33DB,0x33A9,0x33AA,0x33AB,0x33AC,
+0x33DD,0x33D0,0x33D3,0x33C3,0x33C9,0x33DC,0x33C6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCB6D,0xCB6E,0xCB6F,0xCB70,0xCB71,0xCB72,0xCB73,0xCB74,
+0xCB75,0xCB76,0xCB77,0xCB7A,0xCB7B,0xCB7C,0xCB7D,0xCB7E,
+0xCB7F,0xCB80,0xCB81,0xCB82,0xCB83,0xCB84,0xCB85,0xCB86,
+0xCB87,0xCB88, 0, 0, 0, 0, 0, 0,
+0xCB89,0xCB8A,0xCB8B,0xCB8C,0xCB8D,0xCB8E,0xCB8F,0xCB90,
+0xCB91,0xCB92,0xCB93,0xCB94,0xCB95,0xCB96,0xCB97,0xCB98,
+0xCB99,0xCB9A,0xCB9B,0xCB9D,0xCB9E,0xCB9F,0xCBA0,0xCBA1,
+0xCBA2,0xCBA3, 0, 0, 0, 0, 0, 0,
+0xCBA4,0xCBA5,0xCBA6,0xCBA7,0xCBA8,0xCBA9,0xCBAA,0xCBAB,
+0xCBAC,0xCBAD,0xCBAE,0xCBAF,0xCBB0,0xCBB1,0xCBB2,0xCBB3,
+0xCBB4,0xCBB5,0xCBB6,0xCBB7,0xCBB9,0xCBBA,0xCBBB,0xCBBC,
+0xCBBD,0xCBBE,0xCBBF,0xCBC0,0xCBC1,0xCBC2,0xCBC3,0xCBC4,
+0x00C6,0x00D0,0x00AA,0x0126, 0,0x0132, 0,0x013F,
+0x0141,0x00D8,0x0152,0x00BA,0x00DE,0x0166,0x014A, 0,
+0x3260,0x3261,0x3262,0x3263,0x3264,0x3265,0x3266,0x3267,
+0x3268,0x3269,0x326A,0x326B,0x326C,0x326D,0x326E,0x326F,
+0x3270,0x3271,0x3272,0x3273,0x3274,0x3275,0x3276,0x3277,
+0x3278,0x3279,0x327A,0x327B,0x24D0,0x24D1,0x24D2,0x24D3,
+0x24D4,0x24D5,0x24D6,0x24D7,0x24D8,0x24D9,0x24DA,0x24DB,
+0x24DC,0x24DD,0x24DE,0x24DF,0x24E0,0x24E1,0x24E2,0x24E3,
+0x24E4,0x24E5,0x24E6,0x24E7,0x24E8,0x24E9,0x2460,0x2461,
+0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,0x2468,0x2469,
+0x246A,0x246B,0x246C,0x246D,0x246E,0x00BD,0x2153,0x2154,
+0x00BC,0x00BE,0x215B,0x215C,0x215D,0x215E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCBC5,0xCBC6,0xCBC7,0xCBC8,0xCBC9,0xCBCA,0xCBCB,0xCBCC,
+0xCBCD,0xCBCE,0xCBCF,0xCBD0,0xCBD1,0xCBD2,0xCBD3,0xCBD5,
+0xCBD6,0xCBD7,0xCBD8,0xCBD9,0xCBDA,0xCBDB,0xCBDC,0xCBDD,
+0xCBDE,0xCBDF, 0, 0, 0, 0, 0, 0,
+0xCBE0,0xCBE1,0xCBE2,0xCBE3,0xCBE5,0xCBE6,0xCBE8,0xCBEA,
+0xCBEB,0xCBEC,0xCBED,0xCBEE,0xCBEF,0xCBF0,0xCBF1,0xCBF2,
+0xCBF3,0xCBF4,0xCBF5,0xCBF6,0xCBF7,0xCBF8,0xCBF9,0xCBFA,
+0xCBFB,0xCBFC, 0, 0, 0, 0, 0, 0,
+0xCBFD,0xCBFE,0xCBFF,0xCC00,0xCC01,0xCC02,0xCC03,0xCC04,
+0xCC05,0xCC06,0xCC07,0xCC08,0xCC09,0xCC0A,0xCC0B,0xCC0E,
+0xCC0F,0xCC11,0xCC12,0xCC13,0xCC15,0xCC16,0xCC17,0xCC18,
+0xCC19,0xCC1A,0xCC1B,0xCC1E,0xCC1F,0xCC20,0xCC23,0xCC24,
+0x00E6,0x0111,0x00F0,0x0127,0x0131,0x0133,0x0138,0x0140,
+0x0142,0x00F8,0x0153,0x00DF,0x00FE,0x0167,0x014B,0x0149,
+0x3200,0x3201,0x3202,0x3203,0x3204,0x3205,0x3206,0x3207,
+0x3208,0x3209,0x320A,0x320B,0x320C,0x320D,0x320E,0x320F,
+0x3210,0x3211,0x3212,0x3213,0x3214,0x3215,0x3216,0x3217,
+0x3218,0x3219,0x321A,0x321B,0x249C,0x249D,0x249E,0x249F,
+0x24A0,0x24A1,0x24A2,0x24A3,0x24A4,0x24A5,0x24A6,0x24A7,
+0x24A8,0x24A9,0x24AA,0x24AB,0x24AC,0x24AD,0x24AE,0x24AF,
+0x24B0,0x24B1,0x24B2,0x24B3,0x24B4,0x24B5,0x2474,0x2475,
+0x2476,0x2477,0x2478,0x2479,0x247A,0x247B,0x247C,0x247D,
+0x247E,0x247F,0x2480,0x2481,0x2482,0x00B9,0x00B2,0x00B3,
+0x2074,0x207F,0x2081,0x2082,0x2083,0x2084, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCC25,0xCC26,0xCC2A,0xCC2B,0xCC2D,0xCC2F,0xCC31,0xCC32,
+0xCC33,0xCC34,0xCC35,0xCC36,0xCC37,0xCC3A,0xCC3F,0xCC40,
+0xCC41,0xCC42,0xCC43,0xCC46,0xCC47,0xCC49,0xCC4A,0xCC4B,
+0xCC4D,0xCC4E, 0, 0, 0, 0, 0, 0,
+0xCC4F,0xCC50,0xCC51,0xCC52,0xCC53,0xCC56,0xCC5A,0xCC5B,
+0xCC5C,0xCC5D,0xCC5E,0xCC5F,0xCC61,0xCC62,0xCC63,0xCC65,
+0xCC67,0xCC69,0xCC6A,0xCC6B,0xCC6C,0xCC6D,0xCC6E,0xCC6F,
+0xCC71,0xCC72, 0, 0, 0, 0, 0, 0,
+0xCC73,0xCC74,0xCC76,0xCC77,0xCC78,0xCC79,0xCC7A,0xCC7B,
+0xCC7C,0xCC7D,0xCC7E,0xCC7F,0xCC80,0xCC81,0xCC82,0xCC83,
+0xCC84,0xCC85,0xCC86,0xCC87,0xCC88,0xCC89,0xCC8A,0xCC8B,
+0xCC8C,0xCC8D,0xCC8E,0xCC8F,0xCC90,0xCC91,0xCC92,0xCC93,
+0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
+0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
+0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
+0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,
+0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,
+0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,
+0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,
+0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,
+0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,
+0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,
+0x3091,0x3092,0x3093, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCC94,0xCC95,0xCC96,0xCC97,0xCC9A,0xCC9B,0xCC9D,0xCC9E,
+0xCC9F,0xCCA1,0xCCA2,0xCCA3,0xCCA4,0xCCA5,0xCCA6,0xCCA7,
+0xCCAA,0xCCAE,0xCCAF,0xCCB0,0xCCB1,0xCCB2,0xCCB3,0xCCB6,
+0xCCB7,0xCCB9, 0, 0, 0, 0, 0, 0,
+0xCCBA,0xCCBB,0xCCBD,0xCCBE,0xCCBF,0xCCC0,0xCCC1,0xCCC2,
+0xCCC3,0xCCC6,0xCCC8,0xCCCA,0xCCCB,0xCCCC,0xCCCD,0xCCCE,
+0xCCCF,0xCCD1,0xCCD2,0xCCD3,0xCCD5,0xCCD6,0xCCD7,0xCCD8,
+0xCCD9,0xCCDA, 0, 0, 0, 0, 0, 0,
+0xCCDB,0xCCDC,0xCCDD,0xCCDE,0xCCDF,0xCCE0,0xCCE1,0xCCE2,
+0xCCE3,0xCCE5,0xCCE6,0xCCE7,0xCCE8,0xCCE9,0xCCEA,0xCCEB,
+0xCCED,0xCCEE,0xCCEF,0xCCF1,0xCCF2,0xCCF3,0xCCF4,0xCCF5,
+0xCCF6,0xCCF7,0xCCF8,0xCCF9,0xCCFA,0xCCFB,0xCCFC,0xCCFD,
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
+0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
+0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
+0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,
+0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,
+0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,
+0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,
+0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,0x30E0,
+0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,
+0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,0x30F0,
+0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCCFE,0xCCFF,0xCD00,0xCD02,0xCD03,0xCD04,0xCD05,0xCD06,
+0xCD07,0xCD0A,0xCD0B,0xCD0D,0xCD0E,0xCD0F,0xCD11,0xCD12,
+0xCD13,0xCD14,0xCD15,0xCD16,0xCD17,0xCD1A,0xCD1C,0xCD1E,
+0xCD1F,0xCD20, 0, 0, 0, 0, 0, 0,
+0xCD21,0xCD22,0xCD23,0xCD25,0xCD26,0xCD27,0xCD29,0xCD2A,
+0xCD2B,0xCD2D,0xCD2E,0xCD2F,0xCD30,0xCD31,0xCD32,0xCD33,
+0xCD34,0xCD35,0xCD36,0xCD37,0xCD38,0xCD3A,0xCD3B,0xCD3C,
+0xCD3D,0xCD3E, 0, 0, 0, 0, 0, 0,
+0xCD3F,0xCD40,0xCD41,0xCD42,0xCD43,0xCD44,0xCD45,0xCD46,
+0xCD47,0xCD48,0xCD49,0xCD4A,0xCD4B,0xCD4C,0xCD4D,0xCD4E,
+0xCD4F,0xCD50,0xCD51,0xCD52,0xCD53,0xCD54,0xCD55,0xCD56,
+0xCD57,0xCD58,0xCD59,0xCD5A,0xCD5B,0xCD5D,0xCD5E,0xCD5F,
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCD61,0xCD62,0xCD63,0xCD65,0xCD66,0xCD67,0xCD68,0xCD69,
+0xCD6A,0xCD6B,0xCD6E,0xCD70,0xCD72,0xCD73,0xCD74,0xCD75,
+0xCD76,0xCD77,0xCD79,0xCD7A,0xCD7B,0xCD7C,0xCD7D,0xCD7E,
+0xCD7F,0xCD80, 0, 0, 0, 0, 0, 0,
+0xCD81,0xCD82,0xCD83,0xCD84,0xCD85,0xCD86,0xCD87,0xCD89,
+0xCD8A,0xCD8B,0xCD8C,0xCD8D,0xCD8E,0xCD8F,0xCD90,0xCD91,
+0xCD92,0xCD93,0xCD96,0xCD97,0xCD99,0xCD9A,0xCD9B,0xCD9D,
+0xCD9E,0xCD9F, 0, 0, 0, 0, 0, 0,
+0xCDA0,0xCDA1,0xCDA2,0xCDA3,0xCDA6,0xCDA8,0xCDAA,0xCDAB,
+0xCDAC,0xCDAD,0xCDAE,0xCDAF,0xCDB1,0xCDB2,0xCDB3,0xCDB4,
+0xCDB5,0xCDB6,0xCDB7,0xCDB8,0xCDB9,0xCDBA,0xCDBB,0xCDBC,
+0xCDBD,0xCDBE,0xCDBF,0xCDC0,0xCDC1,0xCDC2,0xCDC3,0xCDC5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCDC6,0xCDC7,0xCDC8,0xCDC9,0xCDCA,0xCDCB,0xCDCD,0xCDCE,
+0xCDCF,0xCDD1,0xCDD2,0xCDD3,0xCDD4,0xCDD5,0xCDD6,0xCDD7,
+0xCDD8,0xCDD9,0xCDDA,0xCDDB,0xCDDC,0xCDDD,0xCDDE,0xCDDF,
+0xCDE0,0xCDE1, 0, 0, 0, 0, 0, 0,
+0xCDE2,0xCDE3,0xCDE4,0xCDE5,0xCDE6,0xCDE7,0xCDE9,0xCDEA,
+0xCDEB,0xCDED,0xCDEE,0xCDEF,0xCDF1,0xCDF2,0xCDF3,0xCDF4,
+0xCDF5,0xCDF6,0xCDF7,0xCDFA,0xCDFC,0xCDFE,0xCDFF,0xCE00,
+0xCE01,0xCE02, 0, 0, 0, 0, 0, 0,
+0xCE03,0xCE05,0xCE06,0xCE07,0xCE09,0xCE0A,0xCE0B,0xCE0D,
+0xCE0E,0xCE0F,0xCE10,0xCE11,0xCE12,0xCE13,0xCE15,0xCE16,
+0xCE17,0xCE18,0xCE1A,0xCE1B,0xCE1C,0xCE1D,0xCE1E,0xCE1F,
+0xCE22,0xCE23,0xCE25,0xCE26,0xCE27,0xCE29,0xCE2A,0xCE2B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCE2C,0xCE2D,0xCE2E,0xCE2F,0xCE32,0xCE34,0xCE36,0xCE37,
+0xCE38,0xCE39,0xCE3A,0xCE3B,0xCE3C,0xCE3D,0xCE3E,0xCE3F,
+0xCE40,0xCE41,0xCE42,0xCE43,0xCE44,0xCE45,0xCE46,0xCE47,
+0xCE48,0xCE49, 0, 0, 0, 0, 0, 0,
+0xCE4A,0xCE4B,0xCE4C,0xCE4D,0xCE4E,0xCE4F,0xCE50,0xCE51,
+0xCE52,0xCE53,0xCE54,0xCE55,0xCE56,0xCE57,0xCE5A,0xCE5B,
+0xCE5D,0xCE5E,0xCE62,0xCE63,0xCE64,0xCE65,0xCE66,0xCE67,
+0xCE6A,0xCE6C, 0, 0, 0, 0, 0, 0,
+0xCE6E,0xCE6F,0xCE70,0xCE71,0xCE72,0xCE73,0xCE76,0xCE77,
+0xCE79,0xCE7A,0xCE7B,0xCE7D,0xCE7E,0xCE7F,0xCE80,0xCE81,
+0xCE82,0xCE83,0xCE86,0xCE88,0xCE8A,0xCE8B,0xCE8C,0xCE8D,
+0xCE8E,0xCE8F,0xCE92,0xCE93,0xCE95,0xCE96,0xCE97,0xCE99,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCE9A,0xCE9B,0xCE9C,0xCE9D,0xCE9E,0xCE9F,0xCEA2,0xCEA6,
+0xCEA7,0xCEA8,0xCEA9,0xCEAA,0xCEAB,0xCEAE,0xCEAF,0xCEB0,
+0xCEB1,0xCEB2,0xCEB3,0xCEB4,0xCEB5,0xCEB6,0xCEB7,0xCEB8,
+0xCEB9,0xCEBA, 0, 0, 0, 0, 0, 0,
+0xCEBB,0xCEBC,0xCEBD,0xCEBE,0xCEBF,0xCEC0,0xCEC2,0xCEC3,
+0xCEC4,0xCEC5,0xCEC6,0xCEC7,0xCEC8,0xCEC9,0xCECA,0xCECB,
+0xCECC,0xCECD,0xCECE,0xCECF,0xCED0,0xCED1,0xCED2,0xCED3,
+0xCED4,0xCED5, 0, 0, 0, 0, 0, 0,
+0xCED6,0xCED7,0xCED8,0xCED9,0xCEDA,0xCEDB,0xCEDC,0xCEDD,
+0xCEDE,0xCEDF,0xCEE0,0xCEE1,0xCEE2,0xCEE3,0xCEE6,0xCEE7,
+0xCEE9,0xCEEA,0xCEED,0xCEEE,0xCEEF,0xCEF0,0xCEF1,0xCEF2,
+0xCEF3,0xCEF6,0xCEFA,0xCEFB,0xCEFC,0xCEFD,0xCEFE,0xCEFF,
+0xAC00,0xAC01,0xAC04,0xAC07,0xAC08,0xAC09,0xAC0A,0xAC10,
+0xAC11,0xAC12,0xAC13,0xAC14,0xAC15,0xAC16,0xAC17,0xAC19,
+0xAC1A,0xAC1B,0xAC1C,0xAC1D,0xAC20,0xAC24,0xAC2C,0xAC2D,
+0xAC2F,0xAC30,0xAC31,0xAC38,0xAC39,0xAC3C,0xAC40,0xAC4B,
+0xAC4D,0xAC54,0xAC58,0xAC5C,0xAC70,0xAC71,0xAC74,0xAC77,
+0xAC78,0xAC7A,0xAC80,0xAC81,0xAC83,0xAC84,0xAC85,0xAC86,
+0xAC89,0xAC8A,0xAC8B,0xAC8C,0xAC90,0xAC94,0xAC9C,0xAC9D,
+0xAC9F,0xACA0,0xACA1,0xACA8,0xACA9,0xACAA,0xACAC,0xACAF,
+0xACB0,0xACB8,0xACB9,0xACBB,0xACBC,0xACBD,0xACC1,0xACC4,
+0xACC8,0xACCC,0xACD5,0xACD7,0xACE0,0xACE1,0xACE4,0xACE7,
+0xACE8,0xACEA,0xACEC,0xACEF,0xACF0,0xACF1,0xACF3,0xACF5,
+0xACF6,0xACFC,0xACFD,0xAD00,0xAD04,0xAD06, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCF02,0xCF03,0xCF05,0xCF06,0xCF07,0xCF09,0xCF0A,0xCF0B,
+0xCF0C,0xCF0D,0xCF0E,0xCF0F,0xCF12,0xCF14,0xCF16,0xCF17,
+0xCF18,0xCF19,0xCF1A,0xCF1B,0xCF1D,0xCF1E,0xCF1F,0xCF21,
+0xCF22,0xCF23, 0, 0, 0, 0, 0, 0,
+0xCF25,0xCF26,0xCF27,0xCF28,0xCF29,0xCF2A,0xCF2B,0xCF2E,
+0xCF32,0xCF33,0xCF34,0xCF35,0xCF36,0xCF37,0xCF39,0xCF3A,
+0xCF3B,0xCF3C,0xCF3D,0xCF3E,0xCF3F,0xCF40,0xCF41,0xCF42,
+0xCF43,0xCF44, 0, 0, 0, 0, 0, 0,
+0xCF45,0xCF46,0xCF47,0xCF48,0xCF49,0xCF4A,0xCF4B,0xCF4C,
+0xCF4D,0xCF4E,0xCF4F,0xCF50,0xCF51,0xCF52,0xCF53,0xCF56,
+0xCF57,0xCF59,0xCF5A,0xCF5B,0xCF5D,0xCF5E,0xCF5F,0xCF60,
+0xCF61,0xCF62,0xCF63,0xCF66,0xCF68,0xCF6A,0xCF6B,0xCF6C,
+0xAD0C,0xAD0D,0xAD0F,0xAD11,0xAD18,0xAD1C,0xAD20,0xAD29,
+0xAD2C,0xAD2D,0xAD34,0xAD35,0xAD38,0xAD3C,0xAD44,0xAD45,
+0xAD47,0xAD49,0xAD50,0xAD54,0xAD58,0xAD61,0xAD63,0xAD6C,
+0xAD6D,0xAD70,0xAD73,0xAD74,0xAD75,0xAD76,0xAD7B,0xAD7C,
+0xAD7D,0xAD7F,0xAD81,0xAD82,0xAD88,0xAD89,0xAD8C,0xAD90,
+0xAD9C,0xAD9D,0xADA4,0xADB7,0xADC0,0xADC1,0xADC4,0xADC8,
+0xADD0,0xADD1,0xADD3,0xADDC,0xADE0,0xADE4,0xADF8,0xADF9,
+0xADFC,0xADFF,0xAE00,0xAE01,0xAE08,0xAE09,0xAE0B,0xAE0D,
+0xAE14,0xAE30,0xAE31,0xAE34,0xAE37,0xAE38,0xAE3A,0xAE40,
+0xAE41,0xAE43,0xAE45,0xAE46,0xAE4A,0xAE4C,0xAE4D,0xAE4E,
+0xAE50,0xAE54,0xAE56,0xAE5C,0xAE5D,0xAE5F,0xAE60,0xAE61,
+0xAE65,0xAE68,0xAE69,0xAE6C,0xAE70,0xAE78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCF6D,0xCF6E,0xCF6F,0xCF72,0xCF73,0xCF75,0xCF76,0xCF77,
+0xCF79,0xCF7A,0xCF7B,0xCF7C,0xCF7D,0xCF7E,0xCF7F,0xCF81,
+0xCF82,0xCF83,0xCF84,0xCF86,0xCF87,0xCF88,0xCF89,0xCF8A,
+0xCF8B,0xCF8D, 0, 0, 0, 0, 0, 0,
+0xCF8E,0xCF8F,0xCF90,0xCF91,0xCF92,0xCF93,0xCF94,0xCF95,
+0xCF96,0xCF97,0xCF98,0xCF99,0xCF9A,0xCF9B,0xCF9C,0xCF9D,
+0xCF9E,0xCF9F,0xCFA0,0xCFA2,0xCFA3,0xCFA4,0xCFA5,0xCFA6,
+0xCFA7,0xCFA9, 0, 0, 0, 0, 0, 0,
+0xCFAA,0xCFAB,0xCFAC,0xCFAD,0xCFAE,0xCFAF,0xCFB1,0xCFB2,
+0xCFB3,0xCFB4,0xCFB5,0xCFB6,0xCFB7,0xCFB8,0xCFB9,0xCFBA,
+0xCFBB,0xCFBC,0xCFBD,0xCFBE,0xCFBF,0xCFC0,0xCFC1,0xCFC2,
+0xCFC3,0xCFC5,0xCFC6,0xCFC7,0xCFC8,0xCFC9,0xCFCA,0xCFCB,
+0xAE79,0xAE7B,0xAE7C,0xAE7D,0xAE84,0xAE85,0xAE8C,0xAEBC,
+0xAEBD,0xAEBE,0xAEC0,0xAEC4,0xAECC,0xAECD,0xAECF,0xAED0,
+0xAED1,0xAED8,0xAED9,0xAEDC,0xAEE8,0xAEEB,0xAEED,0xAEF4,
+0xAEF8,0xAEFC,0xAF07,0xAF08,0xAF0D,0xAF10,0xAF2C,0xAF2D,
+0xAF30,0xAF32,0xAF34,0xAF3C,0xAF3D,0xAF3F,0xAF41,0xAF42,
+0xAF43,0xAF48,0xAF49,0xAF50,0xAF5C,0xAF5D,0xAF64,0xAF65,
+0xAF79,0xAF80,0xAF84,0xAF88,0xAF90,0xAF91,0xAF95,0xAF9C,
+0xAFB8,0xAFB9,0xAFBC,0xAFC0,0xAFC7,0xAFC8,0xAFC9,0xAFCB,
+0xAFCD,0xAFCE,0xAFD4,0xAFDC,0xAFE8,0xAFE9,0xAFF0,0xAFF1,
+0xAFF4,0xAFF8,0xB000,0xB001,0xB004,0xB00C,0xB010,0xB014,
+0xB01C,0xB01D,0xB028,0xB044,0xB045,0xB048,0xB04A,0xB04C,
+0xB04E,0xB053,0xB054,0xB055,0xB057,0xB059, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCFCC,0xCFCD,0xCFCE,0xCFCF,0xCFD0,0xCFD1,0xCFD2,0xCFD3,
+0xCFD4,0xCFD5,0xCFD6,0xCFD7,0xCFD8,0xCFD9,0xCFDA,0xCFDB,
+0xCFDC,0xCFDD,0xCFDE,0xCFDF,0xCFE2,0xCFE3,0xCFE5,0xCFE6,
+0xCFE7,0xCFE9, 0, 0, 0, 0, 0, 0,
+0xCFEA,0xCFEB,0xCFEC,0xCFED,0xCFEE,0xCFEF,0xCFF2,0xCFF4,
+0xCFF6,0xCFF7,0xCFF8,0xCFF9,0xCFFA,0xCFFB,0xCFFD,0xCFFE,
+0xCFFF,0xD001,0xD002,0xD003,0xD005,0xD006,0xD007,0xD008,
+0xD009,0xD00A, 0, 0, 0, 0, 0, 0,
+0xD00B,0xD00C,0xD00D,0xD00E,0xD00F,0xD010,0xD012,0xD013,
+0xD014,0xD015,0xD016,0xD017,0xD019,0xD01A,0xD01B,0xD01C,
+0xD01D,0xD01E,0xD01F,0xD020,0xD021,0xD022,0xD023,0xD024,
+0xD025,0xD026,0xD027,0xD028,0xD029,0xD02A,0xD02B,0xD02C,
+0xB05D,0xB07C,0xB07D,0xB080,0xB084,0xB08C,0xB08D,0xB08F,
+0xB091,0xB098,0xB099,0xB09A,0xB09C,0xB09F,0xB0A0,0xB0A1,
+0xB0A2,0xB0A8,0xB0A9,0xB0AB,0xB0AC,0xB0AD,0xB0AE,0xB0AF,
+0xB0B1,0xB0B3,0xB0B4,0xB0B5,0xB0B8,0xB0BC,0xB0C4,0xB0C5,
+0xB0C7,0xB0C8,0xB0C9,0xB0D0,0xB0D1,0xB0D4,0xB0D8,0xB0E0,
+0xB0E5,0xB108,0xB109,0xB10B,0xB10C,0xB110,0xB112,0xB113,
+0xB118,0xB119,0xB11B,0xB11C,0xB11D,0xB123,0xB124,0xB125,
+0xB128,0xB12C,0xB134,0xB135,0xB137,0xB138,0xB139,0xB140,
+0xB141,0xB144,0xB148,0xB150,0xB151,0xB154,0xB155,0xB158,
+0xB15C,0xB160,0xB178,0xB179,0xB17C,0xB180,0xB182,0xB188,
+0xB189,0xB18B,0xB18D,0xB192,0xB193,0xB194,0xB198,0xB19C,
+0xB1A8,0xB1CC,0xB1D0,0xB1D4,0xB1DC,0xB1DD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD02E,0xD02F,0xD030,0xD031,0xD032,0xD033,0xD036,0xD037,
+0xD039,0xD03A,0xD03B,0xD03D,0xD03E,0xD03F,0xD040,0xD041,
+0xD042,0xD043,0xD046,0xD048,0xD04A,0xD04B,0xD04C,0xD04D,
+0xD04E,0xD04F, 0, 0, 0, 0, 0, 0,
+0xD051,0xD052,0xD053,0xD055,0xD056,0xD057,0xD059,0xD05A,
+0xD05B,0xD05C,0xD05D,0xD05E,0xD05F,0xD061,0xD062,0xD063,
+0xD064,0xD065,0xD066,0xD067,0xD068,0xD069,0xD06A,0xD06B,
+0xD06E,0xD06F, 0, 0, 0, 0, 0, 0,
+0xD071,0xD072,0xD073,0xD075,0xD076,0xD077,0xD078,0xD079,
+0xD07A,0xD07B,0xD07E,0xD07F,0xD080,0xD082,0xD083,0xD084,
+0xD085,0xD086,0xD087,0xD088,0xD089,0xD08A,0xD08B,0xD08C,
+0xD08D,0xD08E,0xD08F,0xD090,0xD091,0xD092,0xD093,0xD094,
+0xB1DF,0xB1E8,0xB1E9,0xB1EC,0xB1F0,0xB1F9,0xB1FB,0xB1FD,
+0xB204,0xB205,0xB208,0xB20B,0xB20C,0xB214,0xB215,0xB217,
+0xB219,0xB220,0xB234,0xB23C,0xB258,0xB25C,0xB260,0xB268,
+0xB269,0xB274,0xB275,0xB27C,0xB284,0xB285,0xB289,0xB290,
+0xB291,0xB294,0xB298,0xB299,0xB29A,0xB2A0,0xB2A1,0xB2A3,
+0xB2A5,0xB2A6,0xB2AA,0xB2AC,0xB2B0,0xB2B4,0xB2C8,0xB2C9,
+0xB2CC,0xB2D0,0xB2D2,0xB2D8,0xB2D9,0xB2DB,0xB2DD,0xB2E2,
+0xB2E4,0xB2E5,0xB2E6,0xB2E8,0xB2EB,0xB2EC,0xB2ED,0xB2EE,
+0xB2EF,0xB2F3,0xB2F4,0xB2F5,0xB2F7,0xB2F8,0xB2F9,0xB2FA,
+0xB2FB,0xB2FF,0xB300,0xB301,0xB304,0xB308,0xB310,0xB311,
+0xB313,0xB314,0xB315,0xB31C,0xB354,0xB355,0xB356,0xB358,
+0xB35B,0xB35C,0xB35E,0xB35F,0xB364,0xB365, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD095,0xD096,0xD097,0xD098,0xD099,0xD09A,0xD09B,0xD09C,
+0xD09D,0xD09E,0xD09F,0xD0A0,0xD0A1,0xD0A2,0xD0A3,0xD0A6,
+0xD0A7,0xD0A9,0xD0AA,0xD0AB,0xD0AD,0xD0AE,0xD0AF,0xD0B0,
+0xD0B1,0xD0B2, 0, 0, 0, 0, 0, 0,
+0xD0B3,0xD0B6,0xD0B8,0xD0BA,0xD0BB,0xD0BC,0xD0BD,0xD0BE,
+0xD0BF,0xD0C2,0xD0C3,0xD0C5,0xD0C6,0xD0C7,0xD0CA,0xD0CB,
+0xD0CC,0xD0CD,0xD0CE,0xD0CF,0xD0D2,0xD0D6,0xD0D7,0xD0D8,
+0xD0D9,0xD0DA, 0, 0, 0, 0, 0, 0,
+0xD0DB,0xD0DE,0xD0DF,0xD0E1,0xD0E2,0xD0E3,0xD0E5,0xD0E6,
+0xD0E7,0xD0E8,0xD0E9,0xD0EA,0xD0EB,0xD0EE,0xD0F2,0xD0F3,
+0xD0F4,0xD0F5,0xD0F6,0xD0F7,0xD0F9,0xD0FA,0xD0FB,0xD0FC,
+0xD0FD,0xD0FE,0xD0FF,0xD100,0xD101,0xD102,0xD103,0xD104,
+0xB367,0xB369,0xB36B,0xB36E,0xB370,0xB371,0xB374,0xB378,
+0xB380,0xB381,0xB383,0xB384,0xB385,0xB38C,0xB390,0xB394,
+0xB3A0,0xB3A1,0xB3A8,0xB3AC,0xB3C4,0xB3C5,0xB3C8,0xB3CB,
+0xB3CC,0xB3CE,0xB3D0,0xB3D4,0xB3D5,0xB3D7,0xB3D9,0xB3DB,
+0xB3DD,0xB3E0,0xB3E4,0xB3E8,0xB3FC,0xB410,0xB418,0xB41C,
+0xB420,0xB428,0xB429,0xB42B,0xB434,0xB450,0xB451,0xB454,
+0xB458,0xB460,0xB461,0xB463,0xB465,0xB46C,0xB480,0xB488,
+0xB49D,0xB4A4,0xB4A8,0xB4AC,0xB4B5,0xB4B7,0xB4B9,0xB4C0,
+0xB4C4,0xB4C8,0xB4D0,0xB4D5,0xB4DC,0xB4DD,0xB4E0,0xB4E3,
+0xB4E4,0xB4E6,0xB4EC,0xB4ED,0xB4EF,0xB4F1,0xB4F8,0xB514,
+0xB515,0xB518,0xB51B,0xB51C,0xB524,0xB525,0xB527,0xB528,
+0xB529,0xB52A,0xB530,0xB531,0xB534,0xB538, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD105,0xD106,0xD107,0xD108,0xD109,0xD10A,0xD10B,0xD10C,
+0xD10E,0xD10F,0xD110,0xD111,0xD112,0xD113,0xD114,0xD115,
+0xD116,0xD117,0xD118,0xD119,0xD11A,0xD11B,0xD11C,0xD11D,
+0xD11E,0xD11F, 0, 0, 0, 0, 0, 0,
+0xD120,0xD121,0xD122,0xD123,0xD124,0xD125,0xD126,0xD127,
+0xD128,0xD129,0xD12A,0xD12B,0xD12C,0xD12D,0xD12E,0xD12F,
+0xD132,0xD133,0xD135,0xD136,0xD137,0xD139,0xD13B,0xD13C,
+0xD13D,0xD13E, 0, 0, 0, 0, 0, 0,
+0xD13F,0xD142,0xD146,0xD147,0xD148,0xD149,0xD14A,0xD14B,
+0xD14E,0xD14F,0xD151,0xD152,0xD153,0xD155,0xD156,0xD157,
+0xD158,0xD159,0xD15A,0xD15B,0xD15E,0xD160,0xD162,0xD163,
+0xD164,0xD165,0xD166,0xD167,0xD169,0xD16A,0xD16B,0xD16D,
+0xB540,0xB541,0xB543,0xB544,0xB545,0xB54B,0xB54C,0xB54D,
+0xB550,0xB554,0xB55C,0xB55D,0xB55F,0xB560,0xB561,0xB5A0,
+0xB5A1,0xB5A4,0xB5A8,0xB5AA,0xB5AB,0xB5B0,0xB5B1,0xB5B3,
+0xB5B4,0xB5B5,0xB5BB,0xB5BC,0xB5BD,0xB5C0,0xB5C4,0xB5CC,
+0xB5CD,0xB5CF,0xB5D0,0xB5D1,0xB5D8,0xB5EC,0xB610,0xB611,
+0xB614,0xB618,0xB625,0xB62C,0xB634,0xB648,0xB664,0xB668,
+0xB69C,0xB69D,0xB6A0,0xB6A4,0xB6AB,0xB6AC,0xB6B1,0xB6D4,
+0xB6F0,0xB6F4,0xB6F8,0xB700,0xB701,0xB705,0xB728,0xB729,
+0xB72C,0xB72F,0xB730,0xB738,0xB739,0xB73B,0xB744,0xB748,
+0xB74C,0xB754,0xB755,0xB760,0xB764,0xB768,0xB770,0xB771,
+0xB773,0xB775,0xB77C,0xB77D,0xB780,0xB784,0xB78C,0xB78D,
+0xB78F,0xB790,0xB791,0xB792,0xB796,0xB797, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD16E,0xD16F,0xD170,0xD171,0xD172,0xD173,0xD174,0xD175,
+0xD176,0xD177,0xD178,0xD179,0xD17A,0xD17B,0xD17D,0xD17E,
+0xD17F,0xD180,0xD181,0xD182,0xD183,0xD185,0xD186,0xD187,
+0xD189,0xD18A, 0, 0, 0, 0, 0, 0,
+0xD18B,0xD18C,0xD18D,0xD18E,0xD18F,0xD190,0xD191,0xD192,
+0xD193,0xD194,0xD195,0xD196,0xD197,0xD198,0xD199,0xD19A,
+0xD19B,0xD19C,0xD19D,0xD19E,0xD19F,0xD1A2,0xD1A3,0xD1A5,
+0xD1A6,0xD1A7, 0, 0, 0, 0, 0, 0,
+0xD1A9,0xD1AA,0xD1AB,0xD1AC,0xD1AD,0xD1AE,0xD1AF,0xD1B2,
+0xD1B4,0xD1B6,0xD1B7,0xD1B8,0xD1B9,0xD1BB,0xD1BD,0xD1BE,
+0xD1BF,0xD1C1,0xD1C2,0xD1C3,0xD1C4,0xD1C5,0xD1C6,0xD1C7,
+0xD1C8,0xD1C9,0xD1CA,0xD1CB,0xD1CC,0xD1CD,0xD1CE,0xD1CF,
+0xB798,0xB799,0xB79C,0xB7A0,0xB7A8,0xB7A9,0xB7AB,0xB7AC,
+0xB7AD,0xB7B4,0xB7B5,0xB7B8,0xB7C7,0xB7C9,0xB7EC,0xB7ED,
+0xB7F0,0xB7F4,0xB7FC,0xB7FD,0xB7FF,0xB800,0xB801,0xB807,
+0xB808,0xB809,0xB80C,0xB810,0xB818,0xB819,0xB81B,0xB81D,
+0xB824,0xB825,0xB828,0xB82C,0xB834,0xB835,0xB837,0xB838,
+0xB839,0xB840,0xB844,0xB851,0xB853,0xB85C,0xB85D,0xB860,
+0xB864,0xB86C,0xB86D,0xB86F,0xB871,0xB878,0xB87C,0xB88D,
+0xB8A8,0xB8B0,0xB8B4,0xB8B8,0xB8C0,0xB8C1,0xB8C3,0xB8C5,
+0xB8CC,0xB8D0,0xB8D4,0xB8DD,0xB8DF,0xB8E1,0xB8E8,0xB8E9,
+0xB8EC,0xB8F0,0xB8F8,0xB8F9,0xB8FB,0xB8FD,0xB904,0xB918,
+0xB920,0xB93C,0xB93D,0xB940,0xB944,0xB94C,0xB94F,0xB951,
+0xB958,0xB959,0xB95C,0xB960,0xB968,0xB969, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD1D0,0xD1D1,0xD1D2,0xD1D3,0xD1D4,0xD1D5,0xD1D6,0xD1D7,
+0xD1D9,0xD1DA,0xD1DB,0xD1DC,0xD1DD,0xD1DE,0xD1DF,0xD1E0,
+0xD1E1,0xD1E2,0xD1E3,0xD1E4,0xD1E5,0xD1E6,0xD1E7,0xD1E8,
+0xD1E9,0xD1EA, 0, 0, 0, 0, 0, 0,
+0xD1EB,0xD1EC,0xD1ED,0xD1EE,0xD1EF,0xD1F0,0xD1F1,0xD1F2,
+0xD1F3,0xD1F5,0xD1F6,0xD1F7,0xD1F9,0xD1FA,0xD1FB,0xD1FC,
+0xD1FD,0xD1FE,0xD1FF,0xD200,0xD201,0xD202,0xD203,0xD204,
+0xD205,0xD206, 0, 0, 0, 0, 0, 0,
+0xD208,0xD20A,0xD20B,0xD20C,0xD20D,0xD20E,0xD20F,0xD211,
+0xD212,0xD213,0xD214,0xD215,0xD216,0xD217,0xD218,0xD219,
+0xD21A,0xD21B,0xD21C,0xD21D,0xD21E,0xD21F,0xD220,0xD221,
+0xD222,0xD223,0xD224,0xD225,0xD226,0xD227,0xD228,0xD229,
+0xB96B,0xB96D,0xB974,0xB975,0xB978,0xB97C,0xB984,0xB985,
+0xB987,0xB989,0xB98A,0xB98D,0xB98E,0xB9AC,0xB9AD,0xB9B0,
+0xB9B4,0xB9BC,0xB9BD,0xB9BF,0xB9C1,0xB9C8,0xB9C9,0xB9CC,
+0xB9CE,0xB9CF,0xB9D0,0xB9D1,0xB9D2,0xB9D8,0xB9D9,0xB9DB,
+0xB9DD,0xB9DE,0xB9E1,0xB9E3,0xB9E4,0xB9E5,0xB9E8,0xB9EC,
+0xB9F4,0xB9F5,0xB9F7,0xB9F8,0xB9F9,0xB9FA,0xBA00,0xBA01,
+0xBA08,0xBA15,0xBA38,0xBA39,0xBA3C,0xBA40,0xBA42,0xBA48,
+0xBA49,0xBA4B,0xBA4D,0xBA4E,0xBA53,0xBA54,0xBA55,0xBA58,
+0xBA5C,0xBA64,0xBA65,0xBA67,0xBA68,0xBA69,0xBA70,0xBA71,
+0xBA74,0xBA78,0xBA83,0xBA84,0xBA85,0xBA87,0xBA8C,0xBAA8,
+0xBAA9,0xBAAB,0xBAAC,0xBAB0,0xBAB2,0xBAB8,0xBAB9,0xBABB,
+0xBABD,0xBAC4,0xBAC8,0xBAD8,0xBAD9,0xBAFC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD22A,0xD22B,0xD22E,0xD22F,0xD231,0xD232,0xD233,0xD235,
+0xD236,0xD237,0xD238,0xD239,0xD23A,0xD23B,0xD23E,0xD240,
+0xD242,0xD243,0xD244,0xD245,0xD246,0xD247,0xD249,0xD24A,
+0xD24B,0xD24C, 0, 0, 0, 0, 0, 0,
+0xD24D,0xD24E,0xD24F,0xD250,0xD251,0xD252,0xD253,0xD254,
+0xD255,0xD256,0xD257,0xD258,0xD259,0xD25A,0xD25B,0xD25D,
+0xD25E,0xD25F,0xD260,0xD261,0xD262,0xD263,0xD265,0xD266,
+0xD267,0xD268, 0, 0, 0, 0, 0, 0,
+0xD269,0xD26A,0xD26B,0xD26C,0xD26D,0xD26E,0xD26F,0xD270,
+0xD271,0xD272,0xD273,0xD274,0xD275,0xD276,0xD277,0xD278,
+0xD279,0xD27A,0xD27B,0xD27C,0xD27D,0xD27E,0xD27F,0xD282,
+0xD283,0xD285,0xD286,0xD287,0xD289,0xD28A,0xD28B,0xD28C,
+0xBB00,0xBB04,0xBB0D,0xBB0F,0xBB11,0xBB18,0xBB1C,0xBB20,
+0xBB29,0xBB2B,0xBB34,0xBB35,0xBB36,0xBB38,0xBB3B,0xBB3C,
+0xBB3D,0xBB3E,0xBB44,0xBB45,0xBB47,0xBB49,0xBB4D,0xBB4F,
+0xBB50,0xBB54,0xBB58,0xBB61,0xBB63,0xBB6C,0xBB88,0xBB8C,
+0xBB90,0xBBA4,0xBBA8,0xBBAC,0xBBB4,0xBBB7,0xBBC0,0xBBC4,
+0xBBC8,0xBBD0,0xBBD3,0xBBF8,0xBBF9,0xBBFC,0xBBFF,0xBC00,
+0xBC02,0xBC08,0xBC09,0xBC0B,0xBC0C,0xBC0D,0xBC0F,0xBC11,
+0xBC14,0xBC15,0xBC16,0xBC17,0xBC18,0xBC1B,0xBC1C,0xBC1D,
+0xBC1E,0xBC1F,0xBC24,0xBC25,0xBC27,0xBC29,0xBC2D,0xBC30,
+0xBC31,0xBC34,0xBC38,0xBC40,0xBC41,0xBC43,0xBC44,0xBC45,
+0xBC49,0xBC4C,0xBC4D,0xBC50,0xBC5D,0xBC84,0xBC85,0xBC88,
+0xBC8B,0xBC8C,0xBC8E,0xBC94,0xBC95,0xBC97, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD28D,0xD28E,0xD28F,0xD292,0xD293,0xD294,0xD296,0xD297,
+0xD298,0xD299,0xD29A,0xD29B,0xD29D,0xD29E,0xD29F,0xD2A1,
+0xD2A2,0xD2A3,0xD2A5,0xD2A6,0xD2A7,0xD2A8,0xD2A9,0xD2AA,
+0xD2AB,0xD2AD, 0, 0, 0, 0, 0, 0,
+0xD2AE,0xD2AF,0xD2B0,0xD2B2,0xD2B3,0xD2B4,0xD2B5,0xD2B6,
+0xD2B7,0xD2BA,0xD2BB,0xD2BD,0xD2BE,0xD2C1,0xD2C3,0xD2C4,
+0xD2C5,0xD2C6,0xD2C7,0xD2CA,0xD2CC,0xD2CD,0xD2CE,0xD2CF,
+0xD2D0,0xD2D1, 0, 0, 0, 0, 0, 0,
+0xD2D2,0xD2D3,0xD2D5,0xD2D6,0xD2D7,0xD2D9,0xD2DA,0xD2DB,
+0xD2DD,0xD2DE,0xD2DF,0xD2E0,0xD2E1,0xD2E2,0xD2E3,0xD2E6,
+0xD2E7,0xD2E8,0xD2E9,0xD2EA,0xD2EB,0xD2EC,0xD2ED,0xD2EE,
+0xD2EF,0xD2F2,0xD2F3,0xD2F5,0xD2F6,0xD2F7,0xD2F9,0xD2FA,
+0xBC99,0xBC9A,0xBCA0,0xBCA1,0xBCA4,0xBCA7,0xBCA8,0xBCB0,
+0xBCB1,0xBCB3,0xBCB4,0xBCB5,0xBCBC,0xBCBD,0xBCC0,0xBCC4,
+0xBCCD,0xBCCF,0xBCD0,0xBCD1,0xBCD5,0xBCD8,0xBCDC,0xBCF4,
+0xBCF5,0xBCF6,0xBCF8,0xBCFC,0xBD04,0xBD05,0xBD07,0xBD09,
+0xBD10,0xBD14,0xBD24,0xBD2C,0xBD40,0xBD48,0xBD49,0xBD4C,
+0xBD50,0xBD58,0xBD59,0xBD64,0xBD68,0xBD80,0xBD81,0xBD84,
+0xBD87,0xBD88,0xBD89,0xBD8A,0xBD90,0xBD91,0xBD93,0xBD95,
+0xBD99,0xBD9A,0xBD9C,0xBDA4,0xBDB0,0xBDB8,0xBDD4,0xBDD5,
+0xBDD8,0xBDDC,0xBDE9,0xBDF0,0xBDF4,0xBDF8,0xBE00,0xBE03,
+0xBE05,0xBE0C,0xBE0D,0xBE10,0xBE14,0xBE1C,0xBE1D,0xBE1F,
+0xBE44,0xBE45,0xBE48,0xBE4C,0xBE4E,0xBE54,0xBE55,0xBE57,
+0xBE59,0xBE5A,0xBE5B,0xBE60,0xBE61,0xBE64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD2FB,0xD2FC,0xD2FD,0xD2FE,0xD2FF,0xD302,0xD304,0xD306,
+0xD307,0xD308,0xD309,0xD30A,0xD30B,0xD30F,0xD311,0xD312,
+0xD313,0xD315,0xD317,0xD318,0xD319,0xD31A,0xD31B,0xD31E,
+0xD322,0xD323, 0, 0, 0, 0, 0, 0,
+0xD324,0xD326,0xD327,0xD32A,0xD32B,0xD32D,0xD32E,0xD32F,
+0xD331,0xD332,0xD333,0xD334,0xD335,0xD336,0xD337,0xD33A,
+0xD33E,0xD33F,0xD340,0xD341,0xD342,0xD343,0xD346,0xD347,
+0xD348,0xD349, 0, 0, 0, 0, 0, 0,
+0xD34A,0xD34B,0xD34C,0xD34D,0xD34E,0xD34F,0xD350,0xD351,
+0xD352,0xD353,0xD354,0xD355,0xD356,0xD357,0xD358,0xD359,
+0xD35A,0xD35B,0xD35C,0xD35D,0xD35E,0xD35F,0xD360,0xD361,
+0xD362,0xD363,0xD364,0xD365,0xD366,0xD367,0xD368,0xD369,
+0xBE68,0xBE6A,0xBE70,0xBE71,0xBE73,0xBE74,0xBE75,0xBE7B,
+0xBE7C,0xBE7D,0xBE80,0xBE84,0xBE8C,0xBE8D,0xBE8F,0xBE90,
+0xBE91,0xBE98,0xBE99,0xBEA8,0xBED0,0xBED1,0xBED4,0xBED7,
+0xBED8,0xBEE0,0xBEE3,0xBEE4,0xBEE5,0xBEEC,0xBF01,0xBF08,
+0xBF09,0xBF18,0xBF19,0xBF1B,0xBF1C,0xBF1D,0xBF40,0xBF41,
+0xBF44,0xBF48,0xBF50,0xBF51,0xBF55,0xBF94,0xBFB0,0xBFC5,
+0xBFCC,0xBFCD,0xBFD0,0xBFD4,0xBFDC,0xBFDF,0xBFE1,0xC03C,
+0xC051,0xC058,0xC05C,0xC060,0xC068,0xC069,0xC090,0xC091,
+0xC094,0xC098,0xC0A0,0xC0A1,0xC0A3,0xC0A5,0xC0AC,0xC0AD,
+0xC0AF,0xC0B0,0xC0B3,0xC0B4,0xC0B5,0xC0B6,0xC0BC,0xC0BD,
+0xC0BF,0xC0C0,0xC0C1,0xC0C5,0xC0C8,0xC0C9,0xC0CC,0xC0D0,
+0xC0D8,0xC0D9,0xC0DB,0xC0DC,0xC0DD,0xC0E4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD36A,0xD36B,0xD36C,0xD36D,0xD36E,0xD36F,0xD370,0xD371,
+0xD372,0xD373,0xD374,0xD375,0xD376,0xD377,0xD378,0xD379,
+0xD37A,0xD37B,0xD37E,0xD37F,0xD381,0xD382,0xD383,0xD385,
+0xD386,0xD387, 0, 0, 0, 0, 0, 0,
+0xD388,0xD389,0xD38A,0xD38B,0xD38E,0xD392,0xD393,0xD394,
+0xD395,0xD396,0xD397,0xD39A,0xD39B,0xD39D,0xD39E,0xD39F,
+0xD3A1,0xD3A2,0xD3A3,0xD3A4,0xD3A5,0xD3A6,0xD3A7,0xD3AA,
+0xD3AC,0xD3AE, 0, 0, 0, 0, 0, 0,
+0xD3AF,0xD3B0,0xD3B1,0xD3B2,0xD3B3,0xD3B5,0xD3B6,0xD3B7,
+0xD3B9,0xD3BA,0xD3BB,0xD3BD,0xD3BE,0xD3BF,0xD3C0,0xD3C1,
+0xD3C2,0xD3C3,0xD3C6,0xD3C7,0xD3CA,0xD3CB,0xD3CC,0xD3CD,
+0xD3CE,0xD3CF,0xD3D1,0xD3D2,0xD3D3,0xD3D4,0xD3D5,0xD3D6,
+0xC0E5,0xC0E8,0xC0EC,0xC0F4,0xC0F5,0xC0F7,0xC0F9,0xC100,
+0xC104,0xC108,0xC110,0xC115,0xC11C,0xC11D,0xC11E,0xC11F,
+0xC120,0xC123,0xC124,0xC126,0xC127,0xC12C,0xC12D,0xC12F,
+0xC130,0xC131,0xC136,0xC138,0xC139,0xC13C,0xC140,0xC148,
+0xC149,0xC14B,0xC14C,0xC14D,0xC154,0xC155,0xC158,0xC15C,
+0xC164,0xC165,0xC167,0xC168,0xC169,0xC170,0xC174,0xC178,
+0xC185,0xC18C,0xC18D,0xC18E,0xC190,0xC194,0xC196,0xC19C,
+0xC19D,0xC19F,0xC1A1,0xC1A5,0xC1A8,0xC1A9,0xC1AC,0xC1B0,
+0xC1BD,0xC1C4,0xC1C8,0xC1CC,0xC1D4,0xC1D7,0xC1D8,0xC1E0,
+0xC1E4,0xC1E8,0xC1F0,0xC1F1,0xC1F3,0xC1FC,0xC1FD,0xC200,
+0xC204,0xC20C,0xC20D,0xC20F,0xC211,0xC218,0xC219,0xC21C,
+0xC21F,0xC220,0xC228,0xC229,0xC22B,0xC22D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD3D7,0xD3D9,0xD3DA,0xD3DB,0xD3DC,0xD3DD,0xD3DE,0xD3DF,
+0xD3E0,0xD3E2,0xD3E4,0xD3E5,0xD3E6,0xD3E7,0xD3E8,0xD3E9,
+0xD3EA,0xD3EB,0xD3EE,0xD3EF,0xD3F1,0xD3F2,0xD3F3,0xD3F5,
+0xD3F6,0xD3F7, 0, 0, 0, 0, 0, 0,
+0xD3F8,0xD3F9,0xD3FA,0xD3FB,0xD3FE,0xD400,0xD402,0xD403,
+0xD404,0xD405,0xD406,0xD407,0xD409,0xD40A,0xD40B,0xD40C,
+0xD40D,0xD40E,0xD40F,0xD410,0xD411,0xD412,0xD413,0xD414,
+0xD415,0xD416, 0, 0, 0, 0, 0, 0,
+0xD417,0xD418,0xD419,0xD41A,0xD41B,0xD41C,0xD41E,0xD41F,
+0xD420,0xD421,0xD422,0xD423,0xD424,0xD425,0xD426,0xD427,
+0xD428,0xD429,0xD42A,0xD42B,0xD42C,0xD42D,0xD42E,0xD42F,
+0xD430,0xD431,0xD432,0xD433,0xD434,0xD435,0xD436,0xD437,
+0xC22F,0xC231,0xC232,0xC234,0xC248,0xC250,0xC251,0xC254,
+0xC258,0xC260,0xC265,0xC26C,0xC26D,0xC270,0xC274,0xC27C,
+0xC27D,0xC27F,0xC281,0xC288,0xC289,0xC290,0xC298,0xC29B,
+0xC29D,0xC2A4,0xC2A5,0xC2A8,0xC2AC,0xC2AD,0xC2B4,0xC2B5,
+0xC2B7,0xC2B9,0xC2DC,0xC2DD,0xC2E0,0xC2E3,0xC2E4,0xC2EB,
+0xC2EC,0xC2ED,0xC2EF,0xC2F1,0xC2F6,0xC2F8,0xC2F9,0xC2FB,
+0xC2FC,0xC300,0xC308,0xC309,0xC30C,0xC30D,0xC313,0xC314,
+0xC315,0xC318,0xC31C,0xC324,0xC325,0xC328,0xC329,0xC345,
+0xC368,0xC369,0xC36C,0xC370,0xC372,0xC378,0xC379,0xC37C,
+0xC37D,0xC384,0xC388,0xC38C,0xC3C0,0xC3D8,0xC3D9,0xC3DC,
+0xC3DF,0xC3E0,0xC3E2,0xC3E8,0xC3E9,0xC3ED,0xC3F4,0xC3F5,
+0xC3F8,0xC408,0xC410,0xC424,0xC42C,0xC430, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD438,0xD439,0xD43A,0xD43B,0xD43C,0xD43D,0xD43E,0xD43F,
+0xD441,0xD442,0xD443,0xD445,0xD446,0xD447,0xD448,0xD449,
+0xD44A,0xD44B,0xD44C,0xD44D,0xD44E,0xD44F,0xD450,0xD451,
+0xD452,0xD453, 0, 0, 0, 0, 0, 0,
+0xD454,0xD455,0xD456,0xD457,0xD458,0xD459,0xD45A,0xD45B,
+0xD45D,0xD45E,0xD45F,0xD461,0xD462,0xD463,0xD465,0xD466,
+0xD467,0xD468,0xD469,0xD46A,0xD46B,0xD46C,0xD46E,0xD470,
+0xD471,0xD472, 0, 0, 0, 0, 0, 0,
+0xD473,0xD474,0xD475,0xD476,0xD477,0xD47A,0xD47B,0xD47D,
+0xD47E,0xD481,0xD483,0xD484,0xD485,0xD486,0xD487,0xD48A,
+0xD48C,0xD48E,0xD48F,0xD490,0xD491,0xD492,0xD493,0xD495,
+0xD496,0xD497,0xD498,0xD499,0xD49A,0xD49B,0xD49C,0xD49D,
+0xC434,0xC43C,0xC43D,0xC448,0xC464,0xC465,0xC468,0xC46C,
+0xC474,0xC475,0xC479,0xC480,0xC494,0xC49C,0xC4B8,0xC4BC,
+0xC4E9,0xC4F0,0xC4F1,0xC4F4,0xC4F8,0xC4FA,0xC4FF,0xC500,
+0xC501,0xC50C,0xC510,0xC514,0xC51C,0xC528,0xC529,0xC52C,
+0xC530,0xC538,0xC539,0xC53B,0xC53D,0xC544,0xC545,0xC548,
+0xC549,0xC54A,0xC54C,0xC54D,0xC54E,0xC553,0xC554,0xC555,
+0xC557,0xC558,0xC559,0xC55D,0xC55E,0xC560,0xC561,0xC564,
+0xC568,0xC570,0xC571,0xC573,0xC574,0xC575,0xC57C,0xC57D,
+0xC580,0xC584,0xC587,0xC58C,0xC58D,0xC58F,0xC591,0xC595,
+0xC597,0xC598,0xC59C,0xC5A0,0xC5A9,0xC5B4,0xC5B5,0xC5B8,
+0xC5B9,0xC5BB,0xC5BC,0xC5BD,0xC5BE,0xC5C4,0xC5C5,0xC5C6,
+0xC5C7,0xC5C8,0xC5C9,0xC5CA,0xC5CC,0xC5CE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD49E,0xD49F,0xD4A0,0xD4A1,0xD4A2,0xD4A3,0xD4A4,0xD4A5,
+0xD4A6,0xD4A7,0xD4A8,0xD4AA,0xD4AB,0xD4AC,0xD4AD,0xD4AE,
+0xD4AF,0xD4B0,0xD4B1,0xD4B2,0xD4B3,0xD4B4,0xD4B5,0xD4B6,
+0xD4B7,0xD4B8, 0, 0, 0, 0, 0, 0,
+0xD4B9,0xD4BA,0xD4BB,0xD4BC,0xD4BD,0xD4BE,0xD4BF,0xD4C0,
+0xD4C1,0xD4C2,0xD4C3,0xD4C4,0xD4C5,0xD4C6,0xD4C7,0xD4C8,
+0xD4C9,0xD4CA,0xD4CB,0xD4CD,0xD4CE,0xD4CF,0xD4D1,0xD4D2,
+0xD4D3,0xD4D5, 0, 0, 0, 0, 0, 0,
+0xD4D6,0xD4D7,0xD4D8,0xD4D9,0xD4DA,0xD4DB,0xD4DD,0xD4DE,
+0xD4E0,0xD4E1,0xD4E2,0xD4E3,0xD4E4,0xD4E5,0xD4E6,0xD4E7,
+0xD4E9,0xD4EA,0xD4EB,0xD4ED,0xD4EE,0xD4EF,0xD4F1,0xD4F2,
+0xD4F3,0xD4F4,0xD4F5,0xD4F6,0xD4F7,0xD4F9,0xD4FA,0xD4FC,
+0xC5D0,0xC5D1,0xC5D4,0xC5D8,0xC5E0,0xC5E1,0xC5E3,0xC5E5,
+0xC5EC,0xC5ED,0xC5EE,0xC5F0,0xC5F4,0xC5F6,0xC5F7,0xC5FC,
+0xC5FD,0xC5FE,0xC5FF,0xC600,0xC601,0xC605,0xC606,0xC607,
+0xC608,0xC60C,0xC610,0xC618,0xC619,0xC61B,0xC61C,0xC624,
+0xC625,0xC628,0xC62C,0xC62D,0xC62E,0xC630,0xC633,0xC634,
+0xC635,0xC637,0xC639,0xC63B,0xC640,0xC641,0xC644,0xC648,
+0xC650,0xC651,0xC653,0xC654,0xC655,0xC65C,0xC65D,0xC660,
+0xC66C,0xC66F,0xC671,0xC678,0xC679,0xC67C,0xC680,0xC688,
+0xC689,0xC68B,0xC68D,0xC694,0xC695,0xC698,0xC69C,0xC6A4,
+0xC6A5,0xC6A7,0xC6A9,0xC6B0,0xC6B1,0xC6B4,0xC6B8,0xC6B9,
+0xC6BA,0xC6C0,0xC6C1,0xC6C3,0xC6C5,0xC6CC,0xC6CD,0xC6D0,
+0xC6D4,0xC6DC,0xC6DD,0xC6E0,0xC6E1,0xC6E8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD4FE,0xD4FF,0xD500,0xD501,0xD502,0xD503,0xD505,0xD506,
+0xD507,0xD509,0xD50A,0xD50B,0xD50D,0xD50E,0xD50F,0xD510,
+0xD511,0xD512,0xD513,0xD516,0xD518,0xD519,0xD51A,0xD51B,
+0xD51C,0xD51D, 0, 0, 0, 0, 0, 0,
+0xD51E,0xD51F,0xD520,0xD521,0xD522,0xD523,0xD524,0xD525,
+0xD526,0xD527,0xD528,0xD529,0xD52A,0xD52B,0xD52C,0xD52D,
+0xD52E,0xD52F,0xD530,0xD531,0xD532,0xD533,0xD534,0xD535,
+0xD536,0xD537, 0, 0, 0, 0, 0, 0,
+0xD538,0xD539,0xD53A,0xD53B,0xD53E,0xD53F,0xD541,0xD542,
+0xD543,0xD545,0xD546,0xD547,0xD548,0xD549,0xD54A,0xD54B,
+0xD54E,0xD550,0xD552,0xD553,0xD554,0xD555,0xD556,0xD557,
+0xD55A,0xD55B,0xD55D,0xD55E,0xD55F,0xD561,0xD562,0xD563,
+0xC6E9,0xC6EC,0xC6F0,0xC6F8,0xC6F9,0xC6FD,0xC704,0xC705,
+0xC708,0xC70C,0xC714,0xC715,0xC717,0xC719,0xC720,0xC721,
+0xC724,0xC728,0xC730,0xC731,0xC733,0xC735,0xC737,0xC73C,
+0xC73D,0xC740,0xC744,0xC74A,0xC74C,0xC74D,0xC74F,0xC751,
+0xC752,0xC753,0xC754,0xC755,0xC756,0xC757,0xC758,0xC75C,
+0xC760,0xC768,0xC76B,0xC774,0xC775,0xC778,0xC77C,0xC77D,
+0xC77E,0xC783,0xC784,0xC785,0xC787,0xC788,0xC789,0xC78A,
+0xC78E,0xC790,0xC791,0xC794,0xC796,0xC797,0xC798,0xC79A,
+0xC7A0,0xC7A1,0xC7A3,0xC7A4,0xC7A5,0xC7A6,0xC7AC,0xC7AD,
+0xC7B0,0xC7B4,0xC7BC,0xC7BD,0xC7BF,0xC7C0,0xC7C1,0xC7C8,
+0xC7C9,0xC7CC,0xC7CE,0xC7D0,0xC7D8,0xC7DD,0xC7E4,0xC7E8,
+0xC7EC,0xC800,0xC801,0xC804,0xC808,0xC80A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD564,0xD566,0xD567,0xD56A,0xD56C,0xD56E,0xD56F,0xD570,
+0xD571,0xD572,0xD573,0xD576,0xD577,0xD579,0xD57A,0xD57B,
+0xD57D,0xD57E,0xD57F,0xD580,0xD581,0xD582,0xD583,0xD586,
+0xD58A,0xD58B, 0, 0, 0, 0, 0, 0,
+0xD58C,0xD58D,0xD58E,0xD58F,0xD591,0xD592,0xD593,0xD594,
+0xD595,0xD596,0xD597,0xD598,0xD599,0xD59A,0xD59B,0xD59C,
+0xD59D,0xD59E,0xD59F,0xD5A0,0xD5A1,0xD5A2,0xD5A3,0xD5A4,
+0xD5A6,0xD5A7, 0, 0, 0, 0, 0, 0,
+0xD5A8,0xD5A9,0xD5AA,0xD5AB,0xD5AC,0xD5AD,0xD5AE,0xD5AF,
+0xD5B0,0xD5B1,0xD5B2,0xD5B3,0xD5B4,0xD5B5,0xD5B6,0xD5B7,
+0xD5B8,0xD5B9,0xD5BA,0xD5BB,0xD5BC,0xD5BD,0xD5BE,0xD5BF,
+0xD5C0,0xD5C1,0xD5C2,0xD5C3,0xD5C4,0xD5C5,0xD5C6,0xD5C7,
+0xC810,0xC811,0xC813,0xC815,0xC816,0xC81C,0xC81D,0xC820,
+0xC824,0xC82C,0xC82D,0xC82F,0xC831,0xC838,0xC83C,0xC840,
+0xC848,0xC849,0xC84C,0xC84D,0xC854,0xC870,0xC871,0xC874,
+0xC878,0xC87A,0xC880,0xC881,0xC883,0xC885,0xC886,0xC887,
+0xC88B,0xC88C,0xC88D,0xC894,0xC89D,0xC89F,0xC8A1,0xC8A8,
+0xC8BC,0xC8BD,0xC8C4,0xC8C8,0xC8CC,0xC8D4,0xC8D5,0xC8D7,
+0xC8D9,0xC8E0,0xC8E1,0xC8E4,0xC8F5,0xC8FC,0xC8FD,0xC900,
+0xC904,0xC905,0xC906,0xC90C,0xC90D,0xC90F,0xC911,0xC918,
+0xC92C,0xC934,0xC950,0xC951,0xC954,0xC958,0xC960,0xC961,
+0xC963,0xC96C,0xC970,0xC974,0xC97C,0xC988,0xC989,0xC98C,
+0xC990,0xC998,0xC999,0xC99B,0xC99D,0xC9C0,0xC9C1,0xC9C4,
+0xC9C7,0xC9C8,0xC9CA,0xC9D0,0xC9D1,0xC9D3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD5CA,0xD5CB,0xD5CD,0xD5CE,0xD5CF,0xD5D1,0xD5D3,0xD5D4,
+0xD5D5,0xD5D6,0xD5D7,0xD5DA,0xD5DC,0xD5DE,0xD5DF,0xD5E0,
+0xD5E1,0xD5E2,0xD5E3,0xD5E6,0xD5E7,0xD5E9,0xD5EA,0xD5EB,
+0xD5ED,0xD5EE, 0, 0, 0, 0, 0, 0,
+0xD5EF,0xD5F0,0xD5F1,0xD5F2,0xD5F3,0xD5F6,0xD5F8,0xD5FA,
+0xD5FB,0xD5FC,0xD5FD,0xD5FE,0xD5FF,0xD602,0xD603,0xD605,
+0xD606,0xD607,0xD609,0xD60A,0xD60B,0xD60C,0xD60D,0xD60E,
+0xD60F,0xD612, 0, 0, 0, 0, 0, 0,
+0xD616,0xD617,0xD618,0xD619,0xD61A,0xD61B,0xD61D,0xD61E,
+0xD61F,0xD621,0xD622,0xD623,0xD625,0xD626,0xD627,0xD628,
+0xD629,0xD62A,0xD62B,0xD62C,0xD62E,0xD62F,0xD630,0xD631,
+0xD632,0xD633,0xD634,0xD635,0xD636,0xD637,0xD63A,0xD63B,
+0xC9D5,0xC9D6,0xC9D9,0xC9DA,0xC9DC,0xC9DD,0xC9E0,0xC9E2,
+0xC9E4,0xC9E7,0xC9EC,0xC9ED,0xC9EF,0xC9F0,0xC9F1,0xC9F8,
+0xC9F9,0xC9FC,0xCA00,0xCA08,0xCA09,0xCA0B,0xCA0C,0xCA0D,
+0xCA14,0xCA18,0xCA29,0xCA4C,0xCA4D,0xCA50,0xCA54,0xCA5C,
+0xCA5D,0xCA5F,0xCA60,0xCA61,0xCA68,0xCA7D,0xCA84,0xCA98,
+0xCABC,0xCABD,0xCAC0,0xCAC4,0xCACC,0xCACD,0xCACF,0xCAD1,
+0xCAD3,0xCAD8,0xCAD9,0xCAE0,0xCAEC,0xCAF4,0xCB08,0xCB10,
+0xCB14,0xCB18,0xCB20,0xCB21,0xCB41,0xCB48,0xCB49,0xCB4C,
+0xCB50,0xCB58,0xCB59,0xCB5D,0xCB64,0xCB78,0xCB79,0xCB9C,
+0xCBB8,0xCBD4,0xCBE4,0xCBE7,0xCBE9,0xCC0C,0xCC0D,0xCC10,
+0xCC14,0xCC1C,0xCC1D,0xCC21,0xCC22,0xCC27,0xCC28,0xCC29,
+0xCC2C,0xCC2E,0xCC30,0xCC38,0xCC39,0xCC3B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD63D,0xD63E,0xD63F,0xD641,0xD642,0xD643,0xD644,0xD646,
+0xD647,0xD64A,0xD64C,0xD64E,0xD64F,0xD650,0xD652,0xD653,
+0xD656,0xD657,0xD659,0xD65A,0xD65B,0xD65D,0xD65E,0xD65F,
+0xD660,0xD661, 0, 0, 0, 0, 0, 0,
+0xD662,0xD663,0xD664,0xD665,0xD666,0xD668,0xD66A,0xD66B,
+0xD66C,0xD66D,0xD66E,0xD66F,0xD672,0xD673,0xD675,0xD676,
+0xD677,0xD678,0xD679,0xD67A,0xD67B,0xD67C,0xD67D,0xD67E,
+0xD67F,0xD680, 0, 0, 0, 0, 0, 0,
+0xD681,0xD682,0xD684,0xD686,0xD687,0xD688,0xD689,0xD68A,
+0xD68B,0xD68E,0xD68F,0xD691,0xD692,0xD693,0xD695,0xD696,
+0xD697,0xD698,0xD699,0xD69A,0xD69B,0xD69C,0xD69E,0xD6A0,
+0xD6A2,0xD6A3,0xD6A4,0xD6A5,0xD6A6,0xD6A7,0xD6A9,0xD6AA,
+0xCC3C,0xCC3D,0xCC3E,0xCC44,0xCC45,0xCC48,0xCC4C,0xCC54,
+0xCC55,0xCC57,0xCC58,0xCC59,0xCC60,0xCC64,0xCC66,0xCC68,
+0xCC70,0xCC75,0xCC98,0xCC99,0xCC9C,0xCCA0,0xCCA8,0xCCA9,
+0xCCAB,0xCCAC,0xCCAD,0xCCB4,0xCCB5,0xCCB8,0xCCBC,0xCCC4,
+0xCCC5,0xCCC7,0xCCC9,0xCCD0,0xCCD4,0xCCE4,0xCCEC,0xCCF0,
+0xCD01,0xCD08,0xCD09,0xCD0C,0xCD10,0xCD18,0xCD19,0xCD1B,
+0xCD1D,0xCD24,0xCD28,0xCD2C,0xCD39,0xCD5C,0xCD60,0xCD64,
+0xCD6C,0xCD6D,0xCD6F,0xCD71,0xCD78,0xCD88,0xCD94,0xCD95,
+0xCD98,0xCD9C,0xCDA4,0xCDA5,0xCDA7,0xCDA9,0xCDB0,0xCDC4,
+0xCDCC,0xCDD0,0xCDE8,0xCDEC,0xCDF0,0xCDF8,0xCDF9,0xCDFB,
+0xCDFD,0xCE04,0xCE08,0xCE0C,0xCE14,0xCE19,0xCE20,0xCE21,
+0xCE24,0xCE28,0xCE30,0xCE31,0xCE33,0xCE35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD6AB,0xD6AD,0xD6AE,0xD6AF,0xD6B1,0xD6B2,0xD6B3,0xD6B4,
+0xD6B5,0xD6B6,0xD6B7,0xD6B8,0xD6BA,0xD6BC,0xD6BD,0xD6BE,
+0xD6BF,0xD6C0,0xD6C1,0xD6C2,0xD6C3,0xD6C6,0xD6C7,0xD6C9,
+0xD6CA,0xD6CB, 0, 0, 0, 0, 0, 0,
+0xD6CD,0xD6CE,0xD6CF,0xD6D0,0xD6D2,0xD6D3,0xD6D5,0xD6D6,
+0xD6D8,0xD6DA,0xD6DB,0xD6DC,0xD6DD,0xD6DE,0xD6DF,0xD6E1,
+0xD6E2,0xD6E3,0xD6E5,0xD6E6,0xD6E7,0xD6E9,0xD6EA,0xD6EB,
+0xD6EC,0xD6ED, 0, 0, 0, 0, 0, 0,
+0xD6EE,0xD6EF,0xD6F1,0xD6F2,0xD6F3,0xD6F4,0xD6F6,0xD6F7,
+0xD6F8,0xD6F9,0xD6FA,0xD6FB,0xD6FE,0xD6FF,0xD701,0xD702,
+0xD703,0xD705,0xD706,0xD707,0xD708,0xD709,0xD70A,0xD70B,
+0xD70C,0xD70D,0xD70E,0xD70F,0xD710,0xD712,0xD713,0xD714,
+0xCE58,0xCE59,0xCE5C,0xCE5F,0xCE60,0xCE61,0xCE68,0xCE69,
+0xCE6B,0xCE6D,0xCE74,0xCE75,0xCE78,0xCE7C,0xCE84,0xCE85,
+0xCE87,0xCE89,0xCE90,0xCE91,0xCE94,0xCE98,0xCEA0,0xCEA1,
+0xCEA3,0xCEA4,0xCEA5,0xCEAC,0xCEAD,0xCEC1,0xCEE4,0xCEE5,
+0xCEE8,0xCEEB,0xCEEC,0xCEF4,0xCEF5,0xCEF7,0xCEF8,0xCEF9,
+0xCF00,0xCF01,0xCF04,0xCF08,0xCF10,0xCF11,0xCF13,0xCF15,
+0xCF1C,0xCF20,0xCF24,0xCF2C,0xCF2D,0xCF2F,0xCF30,0xCF31,
+0xCF38,0xCF54,0xCF55,0xCF58,0xCF5C,0xCF64,0xCF65,0xCF67,
+0xCF69,0xCF70,0xCF71,0xCF74,0xCF78,0xCF80,0xCF85,0xCF8C,
+0xCFA1,0xCFA8,0xCFB0,0xCFC4,0xCFE0,0xCFE1,0xCFE4,0xCFE8,
+0xCFF0,0xCFF1,0xCFF3,0xCFF5,0xCFFC,0xD000,0xD004,0xD011,
+0xD018,0xD02D,0xD034,0xD035,0xD038,0xD03C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD715,0xD716,0xD717,0xD71A,0xD71B,0xD71D,0xD71E,0xD71F,
+0xD721,0xD722,0xD723,0xD724,0xD725,0xD726,0xD727,0xD72A,
+0xD72C,0xD72E,0xD72F,0xD730,0xD731,0xD732,0xD733,0xD736,
+0xD737,0xD739, 0, 0, 0, 0, 0, 0,
+0xD73A,0xD73B,0xD73D,0xD73E,0xD73F,0xD740,0xD741,0xD742,
+0xD743,0xD745,0xD746,0xD748,0xD74A,0xD74B,0xD74C,0xD74D,
+0xD74E,0xD74F,0xD752,0xD753,0xD755,0xD75A,0xD75B,0xD75C,
+0xD75D,0xD75E, 0, 0, 0, 0, 0, 0,
+0xD75F,0xD762,0xD764,0xD766,0xD767,0xD768,0xD76A,0xD76B,
+0xD76D,0xD76E,0xD76F,0xD771,0xD772,0xD773,0xD775,0xD776,
+0xD777,0xD778,0xD779,0xD77A,0xD77B,0xD77E,0xD77F,0xD780,
+0xD782,0xD783,0xD784,0xD785,0xD786,0xD787,0xD78A,0xD78B,
+0xD044,0xD045,0xD047,0xD049,0xD050,0xD054,0xD058,0xD060,
+0xD06C,0xD06D,0xD070,0xD074,0xD07C,0xD07D,0xD081,0xD0A4,
+0xD0A5,0xD0A8,0xD0AC,0xD0B4,0xD0B5,0xD0B7,0xD0B9,0xD0C0,
+0xD0C1,0xD0C4,0xD0C8,0xD0C9,0xD0D0,0xD0D1,0xD0D3,0xD0D4,
+0xD0D5,0xD0DC,0xD0DD,0xD0E0,0xD0E4,0xD0EC,0xD0ED,0xD0EF,
+0xD0F0,0xD0F1,0xD0F8,0xD10D,0xD130,0xD131,0xD134,0xD138,
+0xD13A,0xD140,0xD141,0xD143,0xD144,0xD145,0xD14C,0xD14D,
+0xD150,0xD154,0xD15C,0xD15D,0xD15F,0xD161,0xD168,0xD16C,
+0xD17C,0xD184,0xD188,0xD1A0,0xD1A1,0xD1A4,0xD1A8,0xD1B0,
+0xD1B1,0xD1B3,0xD1B5,0xD1BA,0xD1BC,0xD1C0,0xD1D8,0xD1F4,
+0xD1F8,0xD207,0xD209,0xD210,0xD22C,0xD22D,0xD230,0xD234,
+0xD23C,0xD23D,0xD23F,0xD241,0xD248,0xD25C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD78D,0xD78E,0xD78F,0xD791,0xD792,0xD793,0xD794,0xD795,
+0xD796,0xD797,0xD79A,0xD79C,0xD79E,0xD79F,0xD7A0,0xD7A1,
+0xD7A2,0xD7A3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD264,0xD280,0xD281,0xD284,0xD288,0xD290,0xD291,0xD295,
+0xD29C,0xD2A0,0xD2A4,0xD2AC,0xD2B1,0xD2B8,0xD2B9,0xD2BC,
+0xD2BF,0xD2C0,0xD2C2,0xD2C8,0xD2C9,0xD2CB,0xD2D4,0xD2D8,
+0xD2DC,0xD2E4,0xD2E5,0xD2F0,0xD2F1,0xD2F4,0xD2F8,0xD300,
+0xD301,0xD303,0xD305,0xD30C,0xD30D,0xD30E,0xD310,0xD314,
+0xD316,0xD31C,0xD31D,0xD31F,0xD320,0xD321,0xD325,0xD328,
+0xD329,0xD32C,0xD330,0xD338,0xD339,0xD33B,0xD33C,0xD33D,
+0xD344,0xD345,0xD37C,0xD37D,0xD380,0xD384,0xD38C,0xD38D,
+0xD38F,0xD390,0xD391,0xD398,0xD399,0xD39C,0xD3A0,0xD3A8,
+0xD3A9,0xD3AB,0xD3AD,0xD3B4,0xD3B8,0xD3BC,0xD3C4,0xD3C5,
+0xD3C8,0xD3C9,0xD3D0,0xD3D8,0xD3E1,0xD3E3,0xD3EC,0xD3ED,
+0xD3F0,0xD3F4,0xD3FC,0xD3FD,0xD3FF,0xD401, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD408,0xD41D,0xD440,0xD444,0xD45C,0xD460,0xD464,0xD46D,
+0xD46F,0xD478,0xD479,0xD47C,0xD47F,0xD480,0xD482,0xD488,
+0xD489,0xD48B,0xD48D,0xD494,0xD4A9,0xD4CC,0xD4D0,0xD4D4,
+0xD4DC,0xD4DF,0xD4E8,0xD4EC,0xD4F0,0xD4F8,0xD4FB,0xD4FD,
+0xD504,0xD508,0xD50C,0xD514,0xD515,0xD517,0xD53C,0xD53D,
+0xD540,0xD544,0xD54C,0xD54D,0xD54F,0xD551,0xD558,0xD559,
+0xD55C,0xD560,0xD565,0xD568,0xD569,0xD56B,0xD56D,0xD574,
+0xD575,0xD578,0xD57C,0xD584,0xD585,0xD587,0xD588,0xD589,
+0xD590,0xD5A5,0xD5C8,0xD5C9,0xD5CC,0xD5D0,0xD5D2,0xD5D8,
+0xD5D9,0xD5DB,0xD5DD,0xD5E4,0xD5E5,0xD5E8,0xD5EC,0xD5F4,
+0xD5F5,0xD5F7,0xD5F9,0xD600,0xD601,0xD604,0xD608,0xD610,
+0xD611,0xD613,0xD614,0xD615,0xD61C,0xD620, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD624,0xD62D,0xD638,0xD639,0xD63C,0xD640,0xD645,0xD648,
+0xD649,0xD64B,0xD64D,0xD651,0xD654,0xD655,0xD658,0xD65C,
+0xD667,0xD669,0xD670,0xD671,0xD674,0xD683,0xD685,0xD68C,
+0xD68D,0xD690,0xD694,0xD69D,0xD69F,0xD6A1,0xD6A8,0xD6AC,
+0xD6B0,0xD6B9,0xD6BB,0xD6C4,0xD6C5,0xD6C8,0xD6CC,0xD6D1,
+0xD6D4,0xD6D7,0xD6D9,0xD6E0,0xD6E4,0xD6E8,0xD6F0,0xD6F5,
+0xD6FC,0xD6FD,0xD700,0xD704,0xD711,0xD718,0xD719,0xD71C,
+0xD720,0xD728,0xD729,0xD72B,0xD72D,0xD734,0xD735,0xD738,
+0xD73C,0xD744,0xD747,0xD749,0xD750,0xD751,0xD754,0xD756,
+0xD757,0xD758,0xD759,0xD760,0xD761,0xD763,0xD765,0xD769,
+0xD76C,0xD770,0xD774,0xD77C,0xD77D,0xD781,0xD788,0xD789,
+0xD78C,0xD790,0xD798,0xD799,0xD79B,0xD79D};
+
+/* page 1 0xCAA1-0xFDFE */
+static uint16 tab_ksc5601_uni1[]={
+0x4F3D,0x4F73,0x5047,0x50F9,0x52A0,0x53EF,0x5475,0x54E5,
+0x5609,0x5AC1,0x5BB6,0x6687,0x67B6,0x67B7,0x67EF,0x6B4C,
+0x73C2,0x75C2,0x7A3C,0x82DB,0x8304,0x8857,0x8888,0x8A36,
+0x8CC8,0x8DCF,0x8EFB,0x8FE6,0x99D5,0x523B,0x5374,0x5404,
+0x606A,0x6164,0x6BBC,0x73CF,0x811A,0x89BA,0x89D2,0x95A3,
+0x4F83,0x520A,0x58BE,0x5978,0x59E6,0x5E72,0x5E79,0x61C7,
+0x63C0,0x6746,0x67EC,0x687F,0x6F97,0x764E,0x770B,0x78F5,
+0x7A08,0x7AFF,0x7C21,0x809D,0x826E,0x8271,0x8AEB,0x9593,
+0x4E6B,0x559D,0x66F7,0x6E34,0x78A3,0x7AED,0x845B,0x8910,
+0x874E,0x97A8,0x52D8,0x574E,0x582A,0x5D4C,0x611F,0x61BE,
+0x6221,0x6562,0x67D1,0x6A44,0x6E1B,0x7518,0x75B3,0x76E3,
+0x77B0,0x7D3A,0x90AF,0x9451,0x9452,0x9F95, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5323,0x5CAC,0x7532,0x80DB,0x9240,0x9598,0x525B,0x5808,
+0x59DC,0x5CA1,0x5D17,0x5EB7,0x5F3A,0x5F4A,0x6177,0x6C5F,
+0x757A,0x7586,0x7CE0,0x7D73,0x7DB1,0x7F8C,0x8154,0x8221,
+0x8591,0x8941,0x8B1B,0x92FC,0x964D,0x9C47,0x4ECB,0x4EF7,
+0x500B,0x51F1,0x584F,0x6137,0x613E,0x6168,0x6539,0x69EA,
+0x6F11,0x75A5,0x7686,0x76D6,0x7B87,0x82A5,0x84CB,0xF900,
+0x93A7,0x958B,0x5580,0x5BA2,0x5751,0xF901,0x7CB3,0x7FB9,
+0x91B5,0x5028,0x53BB,0x5C45,0x5DE8,0x62D2,0x636E,0x64DA,
+0x64E7,0x6E20,0x70AC,0x795B,0x8DDD,0x8E1E,0xF902,0x907D,
+0x9245,0x92F8,0x4E7E,0x4EF6,0x5065,0x5DFE,0x5EFA,0x6106,
+0x6957,0x8171,0x8654,0x8E47,0x9375,0x9A2B,0x4E5E,0x5091,
+0x6770,0x6840,0x5109,0x528D,0x5292,0x6AA2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x77BC,0x9210,0x9ED4,0x52AB,0x602F,0x8FF2,0x5048,0x61A9,
+0x63ED,0x64CA,0x683C,0x6A84,0x6FC0,0x8188,0x89A1,0x9694,
+0x5805,0x727D,0x72AC,0x7504,0x7D79,0x7E6D,0x80A9,0x898B,
+0x8B74,0x9063,0x9D51,0x6289,0x6C7A,0x6F54,0x7D50,0x7F3A,
+0x8A23,0x517C,0x614A,0x7B9D,0x8B19,0x9257,0x938C,0x4EAC,
+0x4FD3,0x501E,0x50BE,0x5106,0x52C1,0x52CD,0x537F,0x5770,
+0x5883,0x5E9A,0x5F91,0x6176,0x61AC,0x64CE,0x656C,0x666F,
+0x66BB,0x66F4,0x6897,0x6D87,0x7085,0x70F1,0x749F,0x74A5,
+0x74CA,0x75D9,0x786C,0x78EC,0x7ADF,0x7AF6,0x7D45,0x7D93,
+0x8015,0x803F,0x811B,0x8396,0x8B66,0x8F15,0x9015,0x93E1,
+0x9803,0x9838,0x9A5A,0x9BE8,0x4FC2,0x5553,0x583A,0x5951,
+0x5B63,0x5C46,0x60B8,0x6212,0x6842,0x68B0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x68E8,0x6EAA,0x754C,0x7678,0x78CE,0x7A3D,0x7CFB,0x7E6B,
+0x7E7C,0x8A08,0x8AA1,0x8C3F,0x968E,0x9DC4,0x53E4,0x53E9,
+0x544A,0x5471,0x56FA,0x59D1,0x5B64,0x5C3B,0x5EAB,0x62F7,
+0x6537,0x6545,0x6572,0x66A0,0x67AF,0x69C1,0x6CBD,0x75FC,
+0x7690,0x777E,0x7A3F,0x7F94,0x8003,0x80A1,0x818F,0x82E6,
+0x82FD,0x83F0,0x85C1,0x8831,0x88B4,0x8AA5,0xF903,0x8F9C,
+0x932E,0x96C7,0x9867,0x9AD8,0x9F13,0x54ED,0x659B,0x66F2,
+0x688F,0x7A40,0x8C37,0x9D60,0x56F0,0x5764,0x5D11,0x6606,
+0x68B1,0x68CD,0x6EFE,0x7428,0x889E,0x9BE4,0x6C68,0xF904,
+0x9AA8,0x4F9B,0x516C,0x5171,0x529F,0x5B54,0x5DE5,0x6050,
+0x606D,0x62F1,0x63A7,0x653B,0x73D9,0x7A7A,0x86A3,0x8CA2,
+0x978F,0x4E32,0x5BE1,0x6208,0x679C,0x74DC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x79D1,0x83D3,0x8A87,0x8AB2,0x8DE8,0x904E,0x934B,0x9846,
+0x5ED3,0x69E8,0x85FF,0x90ED,0xF905,0x51A0,0x5B98,0x5BEC,
+0x6163,0x68FA,0x6B3E,0x704C,0x742F,0x74D8,0x7BA1,0x7F50,
+0x83C5,0x89C0,0x8CAB,0x95DC,0x9928,0x522E,0x605D,0x62EC,
+0x9002,0x4F8A,0x5149,0x5321,0x58D9,0x5EE3,0x66E0,0x6D38,
+0x709A,0x72C2,0x73D6,0x7B50,0x80F1,0x945B,0x5366,0x639B,
+0x7F6B,0x4E56,0x5080,0x584A,0x58DE,0x602A,0x6127,0x62D0,
+0x69D0,0x9B41,0x5B8F,0x7D18,0x80B1,0x8F5F,0x4EA4,0x50D1,
+0x54AC,0x55AC,0x5B0C,0x5DA0,0x5DE7,0x652A,0x654E,0x6821,
+0x6A4B,0x72E1,0x768E,0x77EF,0x7D5E,0x7FF9,0x81A0,0x854E,
+0x86DF,0x8F03,0x8F4E,0x90CA,0x9903,0x9A55,0x9BAB,0x4E18,
+0x4E45,0x4E5D,0x4EC7,0x4FF1,0x5177,0x52FE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5340,0x53E3,0x53E5,0x548E,0x5614,0x5775,0x57A2,0x5BC7,
+0x5D87,0x5ED0,0x61FC,0x62D8,0x6551,0x67B8,0x67E9,0x69CB,
+0x6B50,0x6BC6,0x6BEC,0x6C42,0x6E9D,0x7078,0x72D7,0x7396,
+0x7403,0x77BF,0x77E9,0x7A76,0x7D7F,0x8009,0x81FC,0x8205,
+0x820A,0x82DF,0x8862,0x8B33,0x8CFC,0x8EC0,0x9011,0x90B1,
+0x9264,0x92B6,0x99D2,0x9A45,0x9CE9,0x9DD7,0x9F9C,0x570B,
+0x5C40,0x83CA,0x97A0,0x97AB,0x9EB4,0x541B,0x7A98,0x7FA4,
+0x88D9,0x8ECD,0x90E1,0x5800,0x5C48,0x6398,0x7A9F,0x5BAE,
+0x5F13,0x7A79,0x7AAE,0x828E,0x8EAC,0x5026,0x5238,0x52F8,
+0x5377,0x5708,0x62F3,0x6372,0x6B0A,0x6DC3,0x7737,0x53A5,
+0x7357,0x8568,0x8E76,0x95D5,0x673A,0x6AC3,0x6F70,0x8A6D,
+0x8ECC,0x994B,0xF906,0x6677,0x6B78,0x8CB4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9B3C,0xF907,0x53EB,0x572D,0x594E,0x63C6,0x69FB,0x73EA,
+0x7845,0x7ABA,0x7AC5,0x7CFE,0x8475,0x898F,0x8D73,0x9035,
+0x95A8,0x52FB,0x5747,0x7547,0x7B60,0x83CC,0x921E,0xF908,
+0x6A58,0x514B,0x524B,0x5287,0x621F,0x68D8,0x6975,0x9699,
+0x50C5,0x52A4,0x52E4,0x61C3,0x65A4,0x6839,0x69FF,0x747E,
+0x7B4B,0x82B9,0x83EB,0x89B2,0x8B39,0x8FD1,0x9949,0xF909,
+0x4ECA,0x5997,0x64D2,0x6611,0x6A8E,0x7434,0x7981,0x79BD,
+0x82A9,0x887E,0x887F,0x895F,0xF90A,0x9326,0x4F0B,0x53CA,
+0x6025,0x6271,0x6C72,0x7D1A,0x7D66,0x4E98,0x5162,0x77DC,
+0x80AF,0x4F01,0x4F0E,0x5176,0x5180,0x55DC,0x5668,0x573B,
+0x57FA,0x57FC,0x5914,0x5947,0x5993,0x5BC4,0x5C90,0x5D0E,
+0x5DF1,0x5E7E,0x5FCC,0x6280,0x65D7,0x65E3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x671E,0x671F,0x675E,0x68CB,0x68C4,0x6A5F,0x6B3A,0x6C23,
+0x6C7D,0x6C82,0x6DC7,0x7398,0x7426,0x742A,0x7482,0x74A3,
+0x7578,0x757F,0x7881,0x78EF,0x7941,0x7947,0x7948,0x797A,
+0x7B95,0x7D00,0x7DBA,0x7F88,0x8006,0x802D,0x808C,0x8A18,
+0x8B4F,0x8C48,0x8D77,0x9321,0x9324,0x98E2,0x9951,0x9A0E,
+0x9A0F,0x9A65,0x9E92,0x7DCA,0x4F76,0x5409,0x62EE,0x6854,
+0x91D1,0x55AB,0x513A,0xF90B,0xF90C,0x5A1C,0x61E6,0xF90D,
+0x62CF,0x62FF,0xF90E,0xF90F,0xF910,0xF911,0xF912,0xF913,
+0x90A3,0xF914,0xF915,0xF916,0xF917,0xF918,0x8AFE,0xF919,
+0xF91A,0xF91B,0xF91C,0x6696,0xF91D,0x7156,0xF91E,0xF91F,
+0x96E3,0xF920,0x634F,0x637A,0x5357,0xF921,0x678F,0x6960,
+0x6E73,0xF922,0x7537,0xF923,0xF924,0xF925, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7D0D,0xF926,0xF927,0x8872,0x56CA,0x5A18,0xF928,0xF929,
+0xF92A,0xF92B,0xF92C,0x4E43,0xF92D,0x5167,0x5948,0x67F0,
+0x8010,0xF92E,0x5973,0x5E74,0x649A,0x79CA,0x5FF5,0x606C,
+0x62C8,0x637B,0x5BE7,0x5BD7,0x52AA,0xF92F,0x5974,0x5F29,
+0x6012,0xF930,0xF931,0xF932,0x7459,0xF933,0xF934,0xF935,
+0xF936,0xF937,0xF938,0x99D1,0xF939,0xF93A,0xF93B,0xF93C,
+0xF93D,0xF93E,0xF93F,0xF940,0xF941,0xF942,0xF943,0x6FC3,
+0xF944,0xF945,0x81BF,0x8FB2,0x60F1,0xF946,0xF947,0x8166,
+0xF948,0xF949,0x5C3F,0xF94A,0xF94B,0xF94C,0xF94D,0xF94E,
+0xF94F,0xF950,0xF951,0x5AE9,0x8A25,0x677B,0x7D10,0xF952,
+0xF953,0xF954,0xF955,0xF956,0xF957,0x80FD,0xF958,0xF959,
+0x5C3C,0x6CE5,0x533F,0x6EBA,0x591A,0x8336, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E39,0x4EB6,0x4F46,0x55AE,0x5718,0x58C7,0x5F56,0x65B7,
+0x65E6,0x6A80,0x6BB5,0x6E4D,0x77ED,0x7AEF,0x7C1E,0x7DDE,
+0x86CB,0x8892,0x9132,0x935B,0x64BB,0x6FBE,0x737A,0x75B8,
+0x9054,0x5556,0x574D,0x61BA,0x64D4,0x66C7,0x6DE1,0x6E5B,
+0x6F6D,0x6FB9,0x75F0,0x8043,0x81BD,0x8541,0x8983,0x8AC7,
+0x8B5A,0x931F,0x6C93,0x7553,0x7B54,0x8E0F,0x905D,0x5510,
+0x5802,0x5858,0x5E62,0x6207,0x649E,0x68E0,0x7576,0x7CD6,
+0x87B3,0x9EE8,0x4EE3,0x5788,0x576E,0x5927,0x5C0D,0x5CB1,
+0x5E36,0x5F85,0x6234,0x64E1,0x73B3,0x81FA,0x888B,0x8CB8,
+0x968A,0x9EDB,0x5B85,0x5FB7,0x60B3,0x5012,0x5200,0x5230,
+0x5716,0x5835,0x5857,0x5C0E,0x5C60,0x5CF6,0x5D8B,0x5EA6,
+0x5F92,0x60BC,0x6311,0x6389,0x6417,0x6843, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x68F9,0x6AC2,0x6DD8,0x6E21,0x6ED4,0x6FE4,0x71FE,0x76DC,
+0x7779,0x79B1,0x7A3B,0x8404,0x89A9,0x8CED,0x8DF3,0x8E48,
+0x9003,0x9014,0x9053,0x90FD,0x934D,0x9676,0x97DC,0x6BD2,
+0x7006,0x7258,0x72A2,0x7368,0x7763,0x79BF,0x7BE4,0x7E9B,
+0x8B80,0x58A9,0x60C7,0x6566,0x65FD,0x66BE,0x6C8C,0x711E,
+0x71C9,0x8C5A,0x9813,0x4E6D,0x7A81,0x4EDD,0x51AC,0x51CD,
+0x52D5,0x540C,0x61A7,0x6771,0x6850,0x68DF,0x6D1E,0x6F7C,
+0x75BC,0x77B3,0x7AE5,0x80F4,0x8463,0x9285,0x515C,0x6597,
+0x675C,0x6793,0x75D8,0x7AC7,0x8373,0xF95A,0x8C46,0x9017,
+0x982D,0x5C6F,0x81C0,0x829A,0x9041,0x906F,0x920D,0x5F97,
+0x5D9D,0x6A59,0x71C8,0x767B,0x7B49,0x85E4,0x8B04,0x9127,
+0x9A30,0x5587,0x61F6,0xF95B,0x7669,0x7F85, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x863F,0x87BA,0x88F8,0x908F,0xF95C,0x6D1B,0x70D9,0x73DE,
+0x7D61,0x843D,0xF95D,0x916A,0x99F1,0xF95E,0x4E82,0x5375,
+0x6B04,0x6B12,0x703E,0x721B,0x862D,0x9E1E,0x524C,0x8FA3,
+0x5D50,0x64E5,0x652C,0x6B16,0x6FEB,0x7C43,0x7E9C,0x85CD,
+0x8964,0x89BD,0x62C9,0x81D8,0x881F,0x5ECA,0x6717,0x6D6A,
+0x72FC,0x7405,0x746F,0x8782,0x90DE,0x4F86,0x5D0D,0x5FA0,
+0x840A,0x51B7,0x63A0,0x7565,0x4EAE,0x5006,0x5169,0x51C9,
+0x6881,0x6A11,0x7CAE,0x7CB1,0x7CE7,0x826F,0x8AD2,0x8F1B,
+0x91CF,0x4FB6,0x5137,0x52F5,0x5442,0x5EEC,0x616E,0x623E,
+0x65C5,0x6ADA,0x6FFE,0x792A,0x85DC,0x8823,0x95AD,0x9A62,
+0x9A6A,0x9E97,0x9ECE,0x529B,0x66C6,0x6B77,0x701D,0x792B,
+0x8F62,0x9742,0x6190,0x6200,0x6523,0x6F23, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7149,0x7489,0x7DF4,0x806F,0x84EE,0x8F26,0x9023,0x934A,
+0x51BD,0x5217,0x52A3,0x6D0C,0x70C8,0x88C2,0x5EC9,0x6582,
+0x6BAE,0x6FC2,0x7C3E,0x7375,0x4EE4,0x4F36,0x56F9,0xF95F,
+0x5CBA,0x5DBA,0x601C,0x73B2,0x7B2D,0x7F9A,0x7FCE,0x8046,
+0x901E,0x9234,0x96F6,0x9748,0x9818,0x9F61,0x4F8B,0x6FA7,
+0x79AE,0x91B4,0x96B7,0x52DE,0xF960,0x6488,0x64C4,0x6AD3,
+0x6F5E,0x7018,0x7210,0x76E7,0x8001,0x8606,0x865C,0x8DEF,
+0x8F05,0x9732,0x9B6F,0x9DFA,0x9E75,0x788C,0x797F,0x7DA0,
+0x83C9,0x9304,0x9E7F,0x9E93,0x8AD6,0x58DF,0x5F04,0x6727,
+0x7027,0x74CF,0x7C60,0x807E,0x5121,0x7028,0x7262,0x78CA,
+0x8CC2,0x8CDA,0x8CF4,0x96F7,0x4E86,0x50DA,0x5BEE,0x5ED6,
+0x6599,0x71CE,0x7642,0x77AD,0x804A,0x84FC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x907C,0x9B27,0x9F8D,0x58D8,0x5A41,0x5C62,0x6A13,0x6DDA,
+0x6F0F,0x763B,0x7D2F,0x7E37,0x851E,0x8938,0x93E4,0x964B,
+0x5289,0x65D2,0x67F3,0x69B4,0x6D41,0x6E9C,0x700F,0x7409,
+0x7460,0x7559,0x7624,0x786B,0x8B2C,0x985E,0x516D,0x622E,
+0x9678,0x4F96,0x502B,0x5D19,0x6DEA,0x7DB8,0x8F2A,0x5F8B,
+0x6144,0x6817,0xF961,0x9686,0x52D2,0x808B,0x51DC,0x51CC,
+0x695E,0x7A1C,0x7DBE,0x83F1,0x9675,0x4FDA,0x5229,0x5398,
+0x540F,0x550E,0x5C65,0x60A7,0x674E,0x68A8,0x6D6C,0x7281,
+0x72F8,0x7406,0x7483,0xF962,0x75E2,0x7C6C,0x7F79,0x7FB8,
+0x8389,0x88CF,0x88E1,0x91CC,0x91D0,0x96E2,0x9BC9,0x541D,
+0x6F7E,0x71D0,0x7498,0x85FA,0x8EAA,0x96A3,0x9C57,0x9E9F,
+0x6797,0x6DCB,0x7433,0x81E8,0x9716,0x782C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7ACB,0x7B20,0x7C92,0x6469,0x746A,0x75F2,0x78BC,0x78E8,
+0x99AC,0x9B54,0x9EBB,0x5BDE,0x5E55,0x6F20,0x819C,0x83AB,
+0x9088,0x4E07,0x534D,0x5A29,0x5DD2,0x5F4E,0x6162,0x633D,
+0x6669,0x66FC,0x6EFF,0x6F2B,0x7063,0x779E,0x842C,0x8513,
+0x883B,0x8F13,0x9945,0x9C3B,0x551C,0x62B9,0x672B,0x6CAB,
+0x8309,0x896A,0x977A,0x4EA1,0x5984,0x5FD8,0x5FD9,0x671B,
+0x7DB2,0x7F54,0x8292,0x832B,0x83BD,0x8F1E,0x9099,0x57CB,
+0x59B9,0x5A92,0x5BD0,0x6627,0x679A,0x6885,0x6BCF,0x7164,
+0x7F75,0x8CB7,0x8CE3,0x9081,0x9B45,0x8108,0x8C8A,0x964C,
+0x9A40,0x9EA5,0x5B5F,0x6C13,0x731B,0x76F2,0x76DF,0x840C,
+0x51AA,0x8993,0x514D,0x5195,0x52C9,0x68C9,0x6C94,0x7704,
+0x7720,0x7DBF,0x7DEC,0x9762,0x9EB5,0x6EC5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8511,0x51A5,0x540D,0x547D,0x660E,0x669D,0x6927,0x6E9F,
+0x76BF,0x7791,0x8317,0x84C2,0x879F,0x9169,0x9298,0x9CF4,
+0x8882,0x4FAE,0x5192,0x52DF,0x59C6,0x5E3D,0x6155,0x6478,
+0x6479,0x66AE,0x67D0,0x6A21,0x6BCD,0x6BDB,0x725F,0x7261,
+0x7441,0x7738,0x77DB,0x8017,0x82BC,0x8305,0x8B00,0x8B28,
+0x8C8C,0x6728,0x6C90,0x7267,0x76EE,0x7766,0x7A46,0x9DA9,
+0x6B7F,0x6C92,0x5922,0x6726,0x8499,0x536F,0x5893,0x5999,
+0x5EDF,0x63CF,0x6634,0x6773,0x6E3A,0x732B,0x7AD7,0x82D7,
+0x9328,0x52D9,0x5DEB,0x61AE,0x61CB,0x620A,0x62C7,0x64AB,
+0x65E0,0x6959,0x6B66,0x6BCB,0x7121,0x73F7,0x755D,0x7E46,
+0x821E,0x8302,0x856A,0x8AA3,0x8CBF,0x9727,0x9D61,0x58A8,
+0x9ED8,0x5011,0x520E,0x543B,0x554F,0x6587, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C76,0x7D0A,0x7D0B,0x805E,0x868A,0x9580,0x96EF,0x52FF,
+0x6C95,0x7269,0x5473,0x5A9A,0x5C3E,0x5D4B,0x5F4C,0x5FAE,
+0x672A,0x68B6,0x6963,0x6E3C,0x6E44,0x7709,0x7C73,0x7F8E,
+0x8587,0x8B0E,0x8FF7,0x9761,0x9EF4,0x5CB7,0x60B6,0x610D,
+0x61AB,0x654F,0x65FB,0x65FC,0x6C11,0x6CEF,0x739F,0x73C9,
+0x7DE1,0x9594,0x5BC6,0x871C,0x8B10,0x525D,0x535A,0x62CD,
+0x640F,0x64B2,0x6734,0x6A38,0x6CCA,0x73C0,0x749E,0x7B94,
+0x7C95,0x7E1B,0x818A,0x8236,0x8584,0x8FEB,0x96F9,0x99C1,
+0x4F34,0x534A,0x53CD,0x53DB,0x62CC,0x642C,0x6500,0x6591,
+0x69C3,0x6CEE,0x6F58,0x73ED,0x7554,0x7622,0x76E4,0x76FC,
+0x78D0,0x78FB,0x792C,0x7D46,0x822C,0x87E0,0x8FD4,0x9812,
+0x98EF,0x52C3,0x62D4,0x64A5,0x6E24,0x6F51, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x767C,0x8DCB,0x91B1,0x9262,0x9AEE,0x9B43,0x5023,0x508D,
+0x574A,0x59A8,0x5C28,0x5E47,0x5F77,0x623F,0x653E,0x65B9,
+0x65C1,0x6609,0x678B,0x699C,0x6EC2,0x78C5,0x7D21,0x80AA,
+0x8180,0x822B,0x82B3,0x84A1,0x868C,0x8A2A,0x8B17,0x90A6,
+0x9632,0x9F90,0x500D,0x4FF3,0xF963,0x57F9,0x5F98,0x62DC,
+0x6392,0x676F,0x6E43,0x7119,0x76C3,0x80CC,0x80DA,0x88F4,
+0x88F5,0x8919,0x8CE0,0x8F29,0x914D,0x966A,0x4F2F,0x4F70,
+0x5E1B,0x67CF,0x6822,0x767D,0x767E,0x9B44,0x5E61,0x6A0A,
+0x7169,0x71D4,0x756A,0xF964,0x7E41,0x8543,0x85E9,0x98DC,
+0x4F10,0x7B4F,0x7F70,0x95A5,0x51E1,0x5E06,0x68B5,0x6C3E,
+0x6C4E,0x6CDB,0x72AF,0x7BC4,0x8303,0x6CD5,0x743A,0x50FB,
+0x5288,0x58C1,0x64D8,0x6A97,0x74A7,0x7656, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x78A7,0x8617,0x95E2,0x9739,0xF965,0x535E,0x5F01,0x8B8A,
+0x8FA8,0x8FAF,0x908A,0x5225,0x77A5,0x9C49,0x9F08,0x4E19,
+0x5002,0x5175,0x5C5B,0x5E77,0x661E,0x663A,0x67C4,0x68C5,
+0x70B3,0x7501,0x75C5,0x79C9,0x7ADD,0x8F27,0x9920,0x9A08,
+0x4FDD,0x5821,0x5831,0x5BF6,0x666E,0x6B65,0x6D11,0x6E7A,
+0x6F7D,0x73E4,0x752B,0x83E9,0x88DC,0x8913,0x8B5C,0x8F14,
+0x4F0F,0x50D5,0x5310,0x535C,0x5B93,0x5FA9,0x670D,0x798F,
+0x8179,0x832F,0x8514,0x8907,0x8986,0x8F39,0x8F3B,0x99A5,
+0x9C12,0x672C,0x4E76,0x4FF8,0x5949,0x5C01,0x5CEF,0x5CF0,
+0x6367,0x68D2,0x70FD,0x71A2,0x742B,0x7E2B,0x84EC,0x8702,
+0x9022,0x92D2,0x9CF3,0x4E0D,0x4ED8,0x4FEF,0x5085,0x5256,
+0x526F,0x5426,0x5490,0x57E0,0x592B,0x5A66, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5B5A,0x5B75,0x5BCC,0x5E9C,0xF966,0x6276,0x6577,0x65A7,
+0x6D6E,0x6EA5,0x7236,0x7B26,0x7C3F,0x7F36,0x8150,0x8151,
+0x819A,0x8240,0x8299,0x83A9,0x8A03,0x8CA0,0x8CE6,0x8CFB,
+0x8D74,0x8DBA,0x90E8,0x91DC,0x961C,0x9644,0x99D9,0x9CE7,
+0x5317,0x5206,0x5429,0x5674,0x58B3,0x5954,0x596E,0x5FFF,
+0x61A4,0x626E,0x6610,0x6C7E,0x711A,0x76C6,0x7C89,0x7CDE,
+0x7D1B,0x82AC,0x8CC1,0x96F0,0xF967,0x4F5B,0x5F17,0x5F7F,
+0x62C2,0x5D29,0x670B,0x68DA,0x787C,0x7E43,0x9D6C,0x4E15,
+0x5099,0x5315,0x532A,0x5351,0x5983,0x5A62,0x5E87,0x60B2,
+0x618A,0x6249,0x6279,0x6590,0x6787,0x69A7,0x6BD4,0x6BD6,
+0x6BD7,0x6BD8,0x6CB8,0xF968,0x7435,0x75FA,0x7812,0x7891,
+0x79D5,0x79D8,0x7C83,0x7DCB,0x7FE1,0x80A5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x813E,0x81C2,0x83F2,0x871A,0x88E8,0x8AB9,0x8B6C,0x8CBB,
+0x9119,0x975E,0x98DB,0x9F3B,0x56AC,0x5B2A,0x5F6C,0x658C,
+0x6AB3,0x6BAF,0x6D5C,0x6FF1,0x7015,0x725D,0x73AD,0x8CA7,
+0x8CD3,0x983B,0x6191,0x6C37,0x8058,0x9A01,0x4E4D,0x4E8B,
+0x4E9B,0x4ED5,0x4F3A,0x4F3C,0x4F7F,0x4FDF,0x50FF,0x53F2,
+0x53F8,0x5506,0x55E3,0x56DB,0x58EB,0x5962,0x5A11,0x5BEB,
+0x5BFA,0x5C04,0x5DF3,0x5E2B,0x5F99,0x601D,0x6368,0x659C,
+0x65AF,0x67F6,0x67FB,0x68AD,0x6B7B,0x6C99,0x6CD7,0x6E23,
+0x7009,0x7345,0x7802,0x793E,0x7940,0x7960,0x79C1,0x7BE9,
+0x7D17,0x7D72,0x8086,0x820D,0x838E,0x84D1,0x86C7,0x88DF,
+0x8A50,0x8A5E,0x8B1D,0x8CDC,0x8D66,0x8FAD,0x90AA,0x98FC,
+0x99DF,0x9E9D,0x524A,0xF969,0x6714,0xF96A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5098,0x522A,0x5C71,0x6563,0x6C55,0x73CA,0x7523,0x759D,
+0x7B97,0x849C,0x9178,0x9730,0x4E77,0x6492,0x6BBA,0x715E,
+0x85A9,0x4E09,0xF96B,0x6749,0x68EE,0x6E17,0x829F,0x8518,
+0x886B,0x63F7,0x6F81,0x9212,0x98AF,0x4E0A,0x50B7,0x50CF,
+0x511F,0x5546,0x55AA,0x5617,0x5B40,0x5C19,0x5CE0,0x5E38,
+0x5E8A,0x5EA0,0x5EC2,0x60F3,0x6851,0x6A61,0x6E58,0x723D,
+0x7240,0x72C0,0x76F8,0x7965,0x7BB1,0x7FD4,0x88F3,0x89F4,
+0x8A73,0x8C61,0x8CDE,0x971C,0x585E,0x74BD,0x8CFD,0x55C7,
+0xF96C,0x7A61,0x7D22,0x8272,0x7272,0x751F,0x7525,0xF96D,
+0x7B19,0x5885,0x58FB,0x5DBC,0x5E8F,0x5EB6,0x5F90,0x6055,
+0x6292,0x637F,0x654D,0x6691,0x66D9,0x66F8,0x6816,0x68F2,
+0x7280,0x745E,0x7B6E,0x7D6E,0x7DD6,0x7F72, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x80E5,0x8212,0x85AF,0x897F,0x8A93,0x901D,0x92E4,0x9ECD,
+0x9F20,0x5915,0x596D,0x5E2D,0x60DC,0x6614,0x6673,0x6790,
+0x6C50,0x6DC5,0x6F5F,0x77F3,0x78A9,0x84C6,0x91CB,0x932B,
+0x4ED9,0x50CA,0x5148,0x5584,0x5B0B,0x5BA3,0x6247,0x657E,
+0x65CB,0x6E32,0x717D,0x7401,0x7444,0x7487,0x74BF,0x766C,
+0x79AA,0x7DDA,0x7E55,0x7FA8,0x817A,0x81B3,0x8239,0x861A,
+0x87EC,0x8A75,0x8DE3,0x9078,0x9291,0x9425,0x994D,0x9BAE,
+0x5368,0x5C51,0x6954,0x6CC4,0x6D29,0x6E2B,0x820C,0x859B,
+0x893B,0x8A2D,0x8AAA,0x96EA,0x9F67,0x5261,0x66B9,0x6BB2,
+0x7E96,0x87FE,0x8D0D,0x9583,0x965D,0x651D,0x6D89,0x71EE,
+0xF96E,0x57CE,0x59D3,0x5BAC,0x6027,0x60FA,0x6210,0x661F,
+0x665F,0x7329,0x73F9,0x76DB,0x7701,0x7B6C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8056,0x8072,0x8165,0x8AA0,0x9192,0x4E16,0x52E2,0x6B72,
+0x6D17,0x7A05,0x7B39,0x7D30,0xF96F,0x8CB0,0x53EC,0x562F,
+0x5851,0x5BB5,0x5C0F,0x5C11,0x5DE2,0x6240,0x6383,0x6414,
+0x662D,0x68B3,0x6CBC,0x6D88,0x6EAF,0x701F,0x70A4,0x71D2,
+0x7526,0x758F,0x758E,0x7619,0x7B11,0x7BE0,0x7C2B,0x7D20,
+0x7D39,0x852C,0x856D,0x8607,0x8A34,0x900D,0x9061,0x90B5,
+0x92B7,0x97F6,0x9A37,0x4FD7,0x5C6C,0x675F,0x6D91,0x7C9F,
+0x7E8C,0x8B16,0x8D16,0x901F,0x5B6B,0x5DFD,0x640D,0x84C0,
+0x905C,0x98E1,0x7387,0x5B8B,0x609A,0x677E,0x6DDE,0x8A1F,
+0x8AA6,0x9001,0x980C,0x5237,0xF970,0x7051,0x788E,0x9396,
+0x8870,0x91D7,0x4FEE,0x53D7,0x55FD,0x56DA,0x5782,0x58FD,
+0x5AC2,0x5B88,0x5CAB,0x5CC0,0x5E25,0x6101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x620D,0x624B,0x6388,0x641C,0x6536,0x6578,0x6A39,0x6B8A,
+0x6C34,0x6D19,0x6F31,0x71E7,0x72E9,0x7378,0x7407,0x74B2,
+0x7626,0x7761,0x79C0,0x7A57,0x7AEA,0x7CB9,0x7D8F,0x7DAC,
+0x7E61,0x7F9E,0x8129,0x8331,0x8490,0x84DA,0x85EA,0x8896,
+0x8AB0,0x8B90,0x8F38,0x9042,0x9083,0x916C,0x9296,0x92B9,
+0x968B,0x96A7,0x96A8,0x96D6,0x9700,0x9808,0x9996,0x9AD3,
+0x9B1A,0x53D4,0x587E,0x5919,0x5B70,0x5BBF,0x6DD1,0x6F5A,
+0x719F,0x7421,0x74B9,0x8085,0x83FD,0x5DE1,0x5F87,0x5FAA,
+0x6042,0x65EC,0x6812,0x696F,0x6A53,0x6B89,0x6D35,0x6DF3,
+0x73E3,0x76FE,0x77AC,0x7B4D,0x7D14,0x8123,0x821C,0x8340,
+0x84F4,0x8563,0x8A62,0x8AC4,0x9187,0x931E,0x9806,0x99B4,
+0x620C,0x8853,0x8FF0,0x9265,0x5D07,0x5D27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5D69,0x745F,0x819D,0x8768,0x6FD5,0x62FE,0x7FD2,0x8936,
+0x8972,0x4E1E,0x4E58,0x50E7,0x52DD,0x5347,0x627F,0x6607,
+0x7E69,0x8805,0x965E,0x4F8D,0x5319,0x5636,0x59CB,0x5AA4,
+0x5C38,0x5C4E,0x5C4D,0x5E02,0x5F11,0x6043,0x65BD,0x662F,
+0x6642,0x67BE,0x67F4,0x731C,0x77E2,0x793A,0x7FC5,0x8494,
+0x84CD,0x8996,0x8A66,0x8A69,0x8AE1,0x8C55,0x8C7A,0x57F4,
+0x5BD4,0x5F0F,0x606F,0x62ED,0x690D,0x6B96,0x6E5C,0x7184,
+0x7BD2,0x8755,0x8B58,0x8EFE,0x98DF,0x98FE,0x4F38,0x4F81,
+0x4FE1,0x547B,0x5A20,0x5BB8,0x613C,0x65B0,0x6668,0x71FC,
+0x7533,0x795E,0x7D33,0x814E,0x81E3,0x8398,0x85AA,0x85CE,
+0x8703,0x8A0A,0x8EAB,0x8F9B,0xF971,0x8FC5,0x5931,0x5BA4,
+0x5BE6,0x6089,0x5BE9,0x5C0B,0x5FC3,0x6C81, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF972,0x6DF1,0x700B,0x751A,0x82AF,0x8AF6,0x4EC0,0x5341,
+0xF973,0x96D9,0x6C0F,0x4E9E,0x4FC4,0x5152,0x555E,0x5A25,
+0x5CE8,0x6211,0x7259,0x82BD,0x83AA,0x86FE,0x8859,0x8A1D,
+0x963F,0x96C5,0x9913,0x9D09,0x9D5D,0x580A,0x5CB3,0x5DBD,
+0x5E44,0x60E1,0x6115,0x63E1,0x6A02,0x6E25,0x9102,0x9354,
+0x984E,0x9C10,0x9F77,0x5B89,0x5CB8,0x6309,0x664F,0x6848,
+0x773C,0x96C1,0x978D,0x9854,0x9B9F,0x65A1,0x8B01,0x8ECB,
+0x95BC,0x5535,0x5CA9,0x5DD6,0x5EB5,0x6697,0x764C,0x83F4,
+0x95C7,0x58D3,0x62BC,0x72CE,0x9D28,0x4EF0,0x592E,0x600F,
+0x663B,0x6B83,0x79E7,0x9D26,0x5393,0x54C0,0x57C3,0x5D16,
+0x611B,0x66D6,0x6DAF,0x788D,0x827E,0x9698,0x9744,0x5384,
+0x627C,0x6396,0x6DB2,0x7E0A,0x814B,0x984D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6AFB,0x7F4C,0x9DAF,0x9E1A,0x4E5F,0x503B,0x51B6,0x591C,
+0x60F9,0x63F6,0x6930,0x723A,0x8036,0xF974,0x91CE,0x5F31,
+0xF975,0xF976,0x7D04,0x82E5,0x846F,0x84BB,0x85E5,0x8E8D,
+0xF977,0x4F6F,0xF978,0xF979,0x58E4,0x5B43,0x6059,0x63DA,
+0x6518,0x656D,0x6698,0xF97A,0x694A,0x6A23,0x6D0B,0x7001,
+0x716C,0x75D2,0x760D,0x79B3,0x7A70,0xF97B,0x7F8A,0xF97C,
+0x8944,0xF97D,0x8B93,0x91C0,0x967D,0xF97E,0x990A,0x5704,
+0x5FA1,0x65BC,0x6F01,0x7600,0x79A6,0x8A9E,0x99AD,0x9B5A,
+0x9F6C,0x5104,0x61B6,0x6291,0x6A8D,0x81C6,0x5043,0x5830,
+0x5F66,0x7109,0x8A00,0x8AFA,0x5B7C,0x8616,0x4FFA,0x513C,
+0x56B4,0x5944,0x63A9,0x6DF9,0x5DAA,0x696D,0x5186,0x4E88,
+0x4F59,0xF97F,0xF980,0xF981,0x5982,0xF982, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF983,0x6B5F,0x6C5D,0xF984,0x74B5,0x7916,0xF985,0x8207,
+0x8245,0x8339,0x8F3F,0x8F5D,0xF986,0x9918,0xF987,0xF988,
+0xF989,0x4EA6,0xF98A,0x57DF,0x5F79,0x6613,0xF98B,0xF98C,
+0x75AB,0x7E79,0x8B6F,0xF98D,0x9006,0x9A5B,0x56A5,0x5827,
+0x59F8,0x5A1F,0x5BB4,0xF98E,0x5EF6,0xF98F,0xF990,0x6350,
+0x633B,0xF991,0x693D,0x6C87,0x6CBF,0x6D8E,0x6D93,0x6DF5,
+0x6F14,0xF992,0x70DF,0x7136,0x7159,0xF993,0x71C3,0x71D5,
+0xF994,0x784F,0x786F,0xF995,0x7B75,0x7DE3,0xF996,0x7E2F,
+0xF997,0x884D,0x8EDF,0xF998,0xF999,0xF99A,0x925B,0xF99B,
+0x9CF6,0xF99C,0xF99D,0xF99E,0x6085,0x6D85,0xF99F,0x71B1,
+0xF9A0,0xF9A1,0x95B1,0x53AD,0xF9A2,0xF9A3,0xF9A4,0x67D3,
+0xF9A5,0x708E,0x7130,0x7430,0x8276,0x82D2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF9A6,0x95BB,0x9AE5,0x9E7D,0x66C4,0xF9A7,0x71C1,0x8449,
+0xF9A8,0xF9A9,0x584B,0xF9AA,0xF9AB,0x5DB8,0x5F71,0xF9AC,
+0x6620,0x668E,0x6979,0x69AE,0x6C38,0x6CF3,0x6E36,0x6F41,
+0x6FDA,0x701B,0x702F,0x7150,0x71DF,0x7370,0xF9AD,0x745B,
+0xF9AE,0x74D4,0x76C8,0x7A4E,0x7E93,0xF9AF,0xF9B0,0x82F1,
+0x8A60,0x8FCE,0xF9B1,0x9348,0xF9B2,0x9719,0xF9B3,0xF9B4,
+0x4E42,0x502A,0xF9B5,0x5208,0x53E1,0x66F3,0x6C6D,0x6FCA,
+0x730A,0x777F,0x7A62,0x82AE,0x85DD,0x8602,0xF9B6,0x88D4,
+0x8A63,0x8B7D,0x8C6B,0xF9B7,0x92B3,0xF9B8,0x9713,0x9810,
+0x4E94,0x4F0D,0x4FC9,0x50B2,0x5348,0x543E,0x5433,0x55DA,
+0x5862,0x58BA,0x5967,0x5A1B,0x5BE4,0x609F,0xF9B9,0x61CA,
+0x6556,0x65FF,0x6664,0x68A7,0x6C5A,0x6FB3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x70CF,0x71AC,0x7352,0x7B7D,0x8708,0x8AA4,0x9C32,0x9F07,
+0x5C4B,0x6C83,0x7344,0x7389,0x923A,0x6EAB,0x7465,0x761F,
+0x7A69,0x7E15,0x860A,0x5140,0x58C5,0x64C1,0x74EE,0x7515,
+0x7670,0x7FC1,0x9095,0x96CD,0x9954,0x6E26,0x74E6,0x7AA9,
+0x7AAA,0x81E5,0x86D9,0x8778,0x8A1B,0x5A49,0x5B8C,0x5B9B,
+0x68A1,0x6900,0x6D63,0x73A9,0x7413,0x742C,0x7897,0x7DE9,
+0x7FEB,0x8118,0x8155,0x839E,0x8C4C,0x962E,0x9811,0x66F0,
+0x5F80,0x65FA,0x6789,0x6C6A,0x738B,0x502D,0x5A03,0x6B6A,
+0x77EE,0x5916,0x5D6C,0x5DCD,0x7325,0x754F,0xF9BA,0xF9BB,
+0x50E5,0x51F9,0x582F,0x592D,0x5996,0x59DA,0x5BE5,0xF9BC,
+0xF9BD,0x5DA2,0x62D7,0x6416,0x6493,0x64FE,0xF9BE,0x66DC,
+0xF9BF,0x6A48,0xF9C0,0x71FF,0x7464,0xF9C1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7A88,0x7AAF,0x7E47,0x7E5E,0x8000,0x8170,0xF9C2,0x87EF,
+0x8981,0x8B20,0x9059,0xF9C3,0x9080,0x9952,0x617E,0x6B32,
+0x6D74,0x7E1F,0x8925,0x8FB1,0x4FD1,0x50AD,0x5197,0x52C7,
+0x57C7,0x5889,0x5BB9,0x5EB8,0x6142,0x6995,0x6D8C,0x6E67,
+0x6EB6,0x7194,0x7462,0x7528,0x752C,0x8073,0x8338,0x84C9,
+0x8E0A,0x9394,0x93DE,0xF9C4,0x4E8E,0x4F51,0x5076,0x512A,
+0x53C8,0x53CB,0x53F3,0x5B87,0x5BD3,0x5C24,0x611A,0x6182,
+0x65F4,0x725B,0x7397,0x7440,0x76C2,0x7950,0x7991,0x79B9,
+0x7D06,0x7FBD,0x828B,0x85D5,0x865E,0x8FC2,0x9047,0x90F5,
+0x91EA,0x9685,0x96E8,0x96E9,0x52D6,0x5F67,0x65ED,0x6631,
+0x682F,0x715C,0x7A36,0x90C1,0x980A,0x4E91,0xF9C5,0x6A52,
+0x6B9E,0x6F90,0x7189,0x8018,0x82B8,0x8553, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x904B,0x9695,0x96F2,0x97FB,0x851A,0x9B31,0x4E90,0x718A,
+0x96C4,0x5143,0x539F,0x54E1,0x5713,0x5712,0x57A3,0x5A9B,
+0x5AC4,0x5BC3,0x6028,0x613F,0x63F4,0x6C85,0x6D39,0x6E72,
+0x6E90,0x7230,0x733F,0x7457,0x82D1,0x8881,0x8F45,0x9060,
+0xF9C6,0x9662,0x9858,0x9D1B,0x6708,0x8D8A,0x925E,0x4F4D,
+0x5049,0x50DE,0x5371,0x570D,0x59D4,0x5A01,0x5C09,0x6170,
+0x6690,0x6E2D,0x7232,0x744B,0x7DEF,0x80C3,0x840E,0x8466,
+0x853F,0x875F,0x885B,0x8918,0x8B02,0x9055,0x97CB,0x9B4F,
+0x4E73,0x4F91,0x5112,0x516A,0xF9C7,0x552F,0x55A9,0x5B7A,
+0x5BA5,0x5E7C,0x5E7D,0x5EBE,0x60A0,0x60DF,0x6108,0x6109,
+0x63C4,0x6538,0x6709,0xF9C8,0x67D4,0x67DA,0xF9C9,0x6961,
+0x6962,0x6CB9,0x6D27,0xF9CA,0x6E38,0xF9CB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6FE1,0x7336,0x7337,0xF9CC,0x745C,0x7531,0xF9CD,0x7652,
+0xF9CE,0xF9CF,0x7DAD,0x81FE,0x8438,0x88D5,0x8A98,0x8ADB,
+0x8AED,0x8E30,0x8E42,0x904A,0x903E,0x907A,0x9149,0x91C9,
+0x936E,0xF9D0,0xF9D1,0x5809,0xF9D2,0x6BD3,0x8089,0x80B2,
+0xF9D3,0xF9D4,0x5141,0x596B,0x5C39,0xF9D5,0xF9D6,0x6F64,
+0x73A7,0x80E4,0x8D07,0xF9D7,0x9217,0x958F,0xF9D8,0xF9D9,
+0xF9DA,0xF9DB,0x807F,0x620E,0x701C,0x7D68,0x878D,0xF9DC,
+0x57A0,0x6069,0x6147,0x6BB7,0x8ABE,0x9280,0x96B1,0x4E59,
+0x541F,0x6DEB,0x852D,0x9670,0x97F3,0x98EE,0x63D6,0x6CE3,
+0x9091,0x51DD,0x61C9,0x81BA,0x9DF9,0x4F9D,0x501A,0x5100,
+0x5B9C,0x610F,0x61FF,0x64EC,0x6905,0x6BC5,0x7591,0x77E3,
+0x7FA9,0x8264,0x858F,0x87FB,0x8863,0x8ABC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B70,0x91AB,0x4E8C,0x4EE5,0x4F0A,0xF9DD,0xF9DE,0x5937,
+0x59E8,0xF9DF,0x5DF2,0x5F1B,0x5F5B,0x6021,0xF9E0,0xF9E1,
+0xF9E2,0xF9E3,0x723E,0x73E5,0xF9E4,0x7570,0x75CD,0xF9E5,
+0x79FB,0xF9E6,0x800C,0x8033,0x8084,0x82E1,0x8351,0xF9E7,
+0xF9E8,0x8CBD,0x8CB3,0x9087,0xF9E9,0xF9EA,0x98F4,0x990C,
+0xF9EB,0xF9EC,0x7037,0x76CA,0x7FCA,0x7FCC,0x7FFC,0x8B1A,
+0x4EBA,0x4EC1,0x5203,0x5370,0xF9ED,0x54BD,0x56E0,0x59FB,
+0x5BC5,0x5F15,0x5FCD,0x6E6E,0xF9EE,0xF9EF,0x7D6A,0x8335,
+0xF9F0,0x8693,0x8A8D,0xF9F1,0x976D,0x9777,0xF9F2,0xF9F3,
+0x4E00,0x4F5A,0x4F7E,0x58F9,0x65E5,0x6EA2,0x9038,0x93B0,
+0x99B9,0x4EFB,0x58EC,0x598A,0x59D9,0x6041,0xF9F4,0xF9F5,
+0x7A14,0xF9F6,0x834F,0x8CC3,0x5165,0x5344, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF9F7,0xF9F8,0xF9F9,0x4ECD,0x5269,0x5B55,0x82BF,0x4ED4,
+0x523A,0x54A8,0x59C9,0x59FF,0x5B50,0x5B57,0x5B5C,0x6063,
+0x6148,0x6ECB,0x7099,0x716E,0x7386,0x74F7,0x75B5,0x78C1,
+0x7D2B,0x8005,0x81EA,0x8328,0x8517,0x85C9,0x8AEE,0x8CC7,
+0x96CC,0x4F5C,0x52FA,0x56BC,0x65AB,0x6628,0x707C,0x70B8,
+0x7235,0x7DBD,0x828D,0x914C,0x96C0,0x9D72,0x5B71,0x68E7,
+0x6B98,0x6F7A,0x76DE,0x5C91,0x66AB,0x6F5B,0x7BB4,0x7C2A,
+0x8836,0x96DC,0x4E08,0x4ED7,0x5320,0x5834,0x58BB,0x58EF,
+0x596C,0x5C07,0x5E33,0x5E84,0x5F35,0x638C,0x66B2,0x6756,
+0x6A1F,0x6AA3,0x6B0C,0x6F3F,0x7246,0xF9FA,0x7350,0x748B,
+0x7AE0,0x7CA7,0x8178,0x81DF,0x81E7,0x838A,0x846C,0x8523,
+0x8594,0x85CF,0x88DD,0x8D13,0x91AC,0x9577, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x969C,0x518D,0x54C9,0x5728,0x5BB0,0x624D,0x6750,0x683D,
+0x6893,0x6E3D,0x6ED3,0x707D,0x7E21,0x88C1,0x8CA1,0x8F09,
+0x9F4B,0x9F4E,0x722D,0x7B8F,0x8ACD,0x931A,0x4F47,0x4F4E,
+0x5132,0x5480,0x59D0,0x5E95,0x62B5,0x6775,0x696E,0x6A17,
+0x6CAE,0x6E1A,0x72D9,0x732A,0x75BD,0x7BB8,0x7D35,0x82E7,
+0x83F9,0x8457,0x85F7,0x8A5B,0x8CAF,0x8E87,0x9019,0x90B8,
+0x96CE,0x9F5F,0x52E3,0x540A,0x5AE1,0x5BC2,0x6458,0x6575,
+0x6EF4,0x72C4,0xF9FB,0x7684,0x7A4D,0x7B1B,0x7C4D,0x7E3E,
+0x7FDF,0x837B,0x8B2B,0x8CCA,0x8D64,0x8DE1,0x8E5F,0x8FEA,
+0x8FF9,0x9069,0x93D1,0x4F43,0x4F7A,0x50B3,0x5168,0x5178,
+0x524D,0x526A,0x5861,0x587C,0x5960,0x5C08,0x5C55,0x5EDB,
+0x609B,0x6230,0x6813,0x6BBF,0x6C08,0x6FB1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x714E,0x7420,0x7530,0x7538,0x7551,0x7672,0x7B4C,0x7B8B,
+0x7BAD,0x7BC6,0x7E8F,0x8A6E,0x8F3E,0x8F49,0x923F,0x9293,
+0x9322,0x942B,0x96FB,0x985A,0x986B,0x991E,0x5207,0x622A,
+0x6298,0x6D59,0x7664,0x7ACA,0x7BC0,0x7D76,0x5360,0x5CBE,
+0x5E97,0x6F38,0x70B9,0x7C98,0x9711,0x9B8E,0x9EDE,0x63A5,
+0x647A,0x8776,0x4E01,0x4E95,0x4EAD,0x505C,0x5075,0x5448,
+0x59C3,0x5B9A,0x5E40,0x5EAD,0x5EF7,0x5F81,0x60C5,0x633A,
+0x653F,0x6574,0x65CC,0x6676,0x6678,0x67FE,0x6968,0x6A89,
+0x6B63,0x6C40,0x6DC0,0x6DE8,0x6E1F,0x6E5E,0x701E,0x70A1,
+0x738E,0x73FD,0x753A,0x775B,0x7887,0x798E,0x7A0B,0x7A7D,
+0x7CBE,0x7D8E,0x8247,0x8A02,0x8AEA,0x8C9E,0x912D,0x914A,
+0x91D8,0x9266,0x92CC,0x9320,0x9706,0x9756, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x975C,0x9802,0x9F0E,0x5236,0x5291,0x557C,0x5824,0x5E1D,
+0x5F1F,0x608C,0x63D0,0x68AF,0x6FDF,0x796D,0x7B2C,0x81CD,
+0x85BA,0x88FD,0x8AF8,0x8E44,0x918D,0x9664,0x969B,0x973D,
+0x984C,0x9F4A,0x4FCE,0x5146,0x51CB,0x52A9,0x5632,0x5F14,
+0x5F6B,0x63AA,0x64CD,0x65E9,0x6641,0x66FA,0x66F9,0x671D,
+0x689D,0x68D7,0x69FD,0x6F15,0x6F6E,0x7167,0x71E5,0x722A,
+0x74AA,0x773A,0x7956,0x795A,0x79DF,0x7A20,0x7A95,0x7C97,
+0x7CDF,0x7D44,0x7E70,0x8087,0x85FB,0x86A4,0x8A54,0x8ABF,
+0x8D99,0x8E81,0x9020,0x906D,0x91E3,0x963B,0x96D5,0x9CE5,
+0x65CF,0x7C07,0x8DB3,0x93C3,0x5B58,0x5C0A,0x5352,0x62D9,
+0x731D,0x5027,0x5B97,0x5F9E,0x60B0,0x616B,0x68D5,0x6DD9,
+0x742E,0x7A2E,0x7D42,0x7D9C,0x7E31,0x816B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8E2A,0x8E35,0x937E,0x9418,0x4F50,0x5750,0x5DE6,0x5EA7,
+0x632B,0x7F6A,0x4E3B,0x4F4F,0x4F8F,0x505A,0x59DD,0x80C4,
+0x546A,0x5468,0x55FE,0x594F,0x5B99,0x5DDE,0x5EDA,0x665D,
+0x6731,0x67F1,0x682A,0x6CE8,0x6D32,0x6E4A,0x6F8D,0x70B7,
+0x73E0,0x7587,0x7C4C,0x7D02,0x7D2C,0x7DA2,0x821F,0x86DB,
+0x8A3B,0x8A85,0x8D70,0x8E8A,0x8F33,0x9031,0x914E,0x9152,
+0x9444,0x99D0,0x7AF9,0x7CA5,0x4FCA,0x5101,0x51C6,0x57C8,
+0x5BEF,0x5CFB,0x6659,0x6A3D,0x6D5A,0x6E96,0x6FEC,0x710C,
+0x756F,0x7AE3,0x8822,0x9021,0x9075,0x96CB,0x99FF,0x8301,
+0x4E2D,0x4EF2,0x8846,0x91CD,0x537D,0x6ADB,0x696B,0x6C41,
+0x847A,0x589E,0x618E,0x66FE,0x62EF,0x70DD,0x7511,0x75C7,
+0x7E52,0x84B8,0x8B49,0x8D08,0x4E4B,0x53EA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x54AB,0x5730,0x5740,0x5FD7,0x6301,0x6307,0x646F,0x652F,
+0x65E8,0x667A,0x679D,0x67B3,0x6B62,0x6C60,0x6C9A,0x6F2C,
+0x77E5,0x7825,0x7949,0x7957,0x7D19,0x80A2,0x8102,0x81F3,
+0x829D,0x82B7,0x8718,0x8A8C,0xF9FC,0x8D04,0x8DBE,0x9072,
+0x76F4,0x7A19,0x7A37,0x7E54,0x8077,0x5507,0x55D4,0x5875,
+0x632F,0x6422,0x6649,0x664B,0x686D,0x699B,0x6B84,0x6D25,
+0x6EB1,0x73CD,0x7468,0x74A1,0x755B,0x75B9,0x76E1,0x771E,
+0x778B,0x79E6,0x7E09,0x7E1D,0x81FB,0x852F,0x8897,0x8A3A,
+0x8CD1,0x8EEB,0x8FB0,0x9032,0x93AD,0x9663,0x9673,0x9707,
+0x4F84,0x53F1,0x59EA,0x5AC9,0x5E19,0x684E,0x74C6,0x75BE,
+0x79E9,0x7A92,0x81A3,0x86ED,0x8CEA,0x8DCC,0x8FED,0x659F,
+0x6715,0xF9FD,0x57F7,0x6F57,0x7DDD,0x8F2F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x93F6,0x96C6,0x5FB5,0x61F2,0x6F84,0x4E14,0x4F98,0x501F,
+0x53C9,0x55DF,0x5D6F,0x5DEE,0x6B21,0x6B64,0x78CB,0x7B9A,
+0xF9FE,0x8E49,0x8ECA,0x906E,0x6349,0x643E,0x7740,0x7A84,
+0x932F,0x947F,0x9F6A,0x64B0,0x6FAF,0x71E6,0x74A8,0x74DA,
+0x7AC4,0x7C12,0x7E82,0x7CB2,0x7E98,0x8B9A,0x8D0A,0x947D,
+0x9910,0x994C,0x5239,0x5BDF,0x64E6,0x672D,0x7D2E,0x50ED,
+0x53C3,0x5879,0x6158,0x6159,0x61FA,0x65AC,0x7AD9,0x8B92,
+0x8B96,0x5009,0x5021,0x5275,0x5531,0x5A3C,0x5EE0,0x5F70,
+0x6134,0x655E,0x660C,0x6636,0x66A2,0x69CD,0x6EC4,0x6F32,
+0x7316,0x7621,0x7A93,0x8139,0x8259,0x83D6,0x84BC,0x50B5,
+0x57F0,0x5BC0,0x5BE8,0x5F69,0x63A1,0x7826,0x7DB5,0x83DC,
+0x8521,0x91C7,0x91F5,0x518A,0x67F5,0x7B56, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8CAC,0x51C4,0x59BB,0x60BD,0x8655,0x501C,0xF9FF,0x5254,
+0x5C3A,0x617D,0x621A,0x62D3,0x64F2,0x65A5,0x6ECC,0x7620,
+0x810A,0x8E60,0x965F,0x96BB,0x4EDF,0x5343,0x5598,0x5929,
+0x5DDD,0x64C5,0x6CC9,0x6DFA,0x7394,0x7A7F,0x821B,0x85A6,
+0x8CE4,0x8E10,0x9077,0x91E7,0x95E1,0x9621,0x97C6,0x51F8,
+0x54F2,0x5586,0x5FB9,0x64A4,0x6F88,0x7DB4,0x8F1F,0x8F4D,
+0x9435,0x50C9,0x5C16,0x6CBE,0x6DFB,0x751B,0x77BB,0x7C3D,
+0x7C64,0x8A79,0x8AC2,0x581E,0x59BE,0x5E16,0x6377,0x7252,
+0x758A,0x776B,0x8ADC,0x8CBC,0x8F12,0x5EF3,0x6674,0x6DF8,
+0x807D,0x83C1,0x8ACB,0x9751,0x9BD6,0xFA00,0x5243,0x66FF,
+0x6D95,0x6EEF,0x7DE0,0x8AE6,0x902E,0x905E,0x9AD4,0x521D,
+0x527F,0x54E8,0x6194,0x6284,0x62DB,0x68A2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6912,0x695A,0x6A35,0x7092,0x7126,0x785D,0x7901,0x790E,
+0x79D2,0x7A0D,0x8096,0x8278,0x82D5,0x8349,0x8549,0x8C82,
+0x8D85,0x9162,0x918B,0x91AE,0x4FC3,0x56D1,0x71ED,0x77D7,
+0x8700,0x89F8,0x5BF8,0x5FD6,0x6751,0x90A8,0x53E2,0x585A,
+0x5BF5,0x60A4,0x6181,0x6460,0x7E3D,0x8070,0x8525,0x9283,
+0x64AE,0x50AC,0x5D14,0x6700,0x589C,0x62BD,0x63A8,0x690E,
+0x6978,0x6A1E,0x6E6B,0x76BA,0x79CB,0x82BB,0x8429,0x8ACF,
+0x8DA8,0x8FFD,0x9112,0x914B,0x919C,0x9310,0x9318,0x939A,
+0x96DB,0x9A36,0x9C0D,0x4E11,0x755C,0x795D,0x7AFA,0x7B51,
+0x7BC9,0x7E2E,0x84C4,0x8E59,0x8E74,0x8EF8,0x9010,0x6625,
+0x693F,0x7443,0x51FA,0x672E,0x9EDC,0x5145,0x5FE0,0x6C96,
+0x87F2,0x885D,0x8877,0x60B4,0x81B5,0x8403, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8D05,0x53D6,0x5439,0x5634,0x5A36,0x5C31,0x708A,0x7FE0,
+0x805A,0x8106,0x81ED,0x8DA3,0x9189,0x9A5F,0x9DF2,0x5074,
+0x4EC4,0x53A0,0x60FB,0x6E2C,0x5C64,0x4F88,0x5024,0x55E4,
+0x5CD9,0x5E5F,0x6065,0x6894,0x6CBB,0x6DC4,0x71BE,0x75D4,
+0x75F4,0x7661,0x7A1A,0x7A49,0x7DC7,0x7DFB,0x7F6E,0x81F4,
+0x86A9,0x8F1C,0x96C9,0x99B3,0x9F52,0x5247,0x52C5,0x98ED,
+0x89AA,0x4E03,0x67D2,0x6F06,0x4FB5,0x5BE2,0x6795,0x6C88,
+0x6D78,0x741B,0x7827,0x91DD,0x937C,0x87C4,0x79E4,0x7A31,
+0x5FEB,0x4ED6,0x54A4,0x553E,0x58AE,0x59A5,0x60F0,0x6253,
+0x62D6,0x6736,0x6955,0x8235,0x9640,0x99B1,0x99DD,0x502C,
+0x5353,0x5544,0x577C,0xFA01,0x6258,0xFA02,0x64E2,0x666B,
+0x67DD,0x6FC1,0x6FEF,0x7422,0x7438,0x8A17, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9438,0x5451,0x5606,0x5766,0x5F48,0x619A,0x6B4E,0x7058,
+0x70AD,0x7DBB,0x8A95,0x596A,0x812B,0x63A2,0x7708,0x803D,
+0x8CAA,0x5854,0x642D,0x69BB,0x5B95,0x5E11,0x6E6F,0xFA03,
+0x8569,0x514C,0x53F0,0x592A,0x6020,0x614B,0x6B86,0x6C70,
+0x6CF0,0x7B1E,0x80CE,0x82D4,0x8DC6,0x90B0,0x98B1,0xFA04,
+0x64C7,0x6FA4,0x6491,0x6504,0x514E,0x5410,0x571F,0x8A0E,
+0x615F,0x6876,0xFA05,0x75DB,0x7B52,0x7D71,0x901A,0x5806,
+0x69CC,0x817F,0x892A,0x9000,0x9839,0x5078,0x5957,0x59AC,
+0x6295,0x900F,0x9B2A,0x615D,0x7279,0x95D6,0x5761,0x5A46,
+0x5DF4,0x628A,0x64AD,0x64FA,0x6777,0x6CE2,0x6D3E,0x722C,
+0x7436,0x7834,0x7F77,0x82AD,0x8DDB,0x9817,0x5224,0x5742,
+0x677F,0x7248,0x74E3,0x8CA9,0x8FA6,0x9211, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x962A,0x516B,0x53ED,0x634C,0x4F69,0x5504,0x6096,0x6557,
+0x6C9B,0x6D7F,0x724C,0x72FD,0x7A17,0x8987,0x8C9D,0x5F6D,
+0x6F8E,0x70F9,0x81A8,0x610E,0x4FBF,0x504F,0x6241,0x7247,
+0x7BC7,0x7DE8,0x7FE9,0x904D,0x97AD,0x9A19,0x8CB6,0x576A,
+0x5E73,0x67B0,0x840D,0x8A55,0x5420,0x5B16,0x5E63,0x5EE2,
+0x5F0A,0x6583,0x80BA,0x853D,0x9589,0x965B,0x4F48,0x5305,
+0x530D,0x530F,0x5486,0x54FA,0x5703,0x5E03,0x6016,0x629B,
+0x62B1,0x6355,0xFA06,0x6CE1,0x6D66,0x75B1,0x7832,0x80DE,
+0x812F,0x82DE,0x8461,0x84B2,0x888D,0x8912,0x900B,0x92EA,
+0x98FD,0x9B91,0x5E45,0x66B4,0x66DD,0x7011,0x7206,0xFA07,
+0x4FF5,0x527D,0x5F6A,0x6153,0x6753,0x6A19,0x6F02,0x74E2,
+0x7968,0x8868,0x8C79,0x98C7,0x98C4,0x9A43, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x54C1,0x7A1F,0x6953,0x8AF7,0x8C4A,0x98A8,0x99AE,0x5F7C,
+0x62AB,0x75B2,0x76AE,0x88AB,0x907F,0x9642,0x5339,0x5F3C,
+0x5FC5,0x6CCC,0x73CC,0x7562,0x758B,0x7B46,0x82FE,0x999D,
+0x4E4F,0x903C,0x4E0B,0x4F55,0x53A6,0x590F,0x5EC8,0x6630,
+0x6CB3,0x7455,0x8377,0x8766,0x8CC0,0x9050,0x971E,0x9C15,
+0x58D1,0x5B78,0x8650,0x8B14,0x9DB4,0x5BD2,0x6068,0x608D,
+0x65F1,0x6C57,0x6F22,0x6FA3,0x701A,0x7F55,0x7FF0,0x9591,
+0x9592,0x9650,0x97D3,0x5272,0x8F44,0x51FD,0x542B,0x54B8,
+0x5563,0x558A,0x6ABB,0x6DB5,0x7DD8,0x8266,0x929C,0x9677,
+0x9E79,0x5408,0x54C8,0x76D2,0x86E4,0x95A4,0x95D4,0x965C,
+0x4EA2,0x4F09,0x59EE,0x5AE6,0x5DF7,0x6052,0x6297,0x676D,
+0x6841,0x6C86,0x6E2F,0x7F38,0x809B,0x822A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFA08,0xFA09,0x9805,0x4EA5,0x5055,0x54B3,0x5793,0x595A,
+0x5B69,0x5BB3,0x61C8,0x6977,0x6D77,0x7023,0x87F9,0x89E3,
+0x8A72,0x8AE7,0x9082,0x99ED,0x9AB8,0x52BE,0x6838,0x5016,
+0x5E78,0x674F,0x8347,0x884C,0x4EAB,0x5411,0x56AE,0x73E6,
+0x9115,0x97FF,0x9909,0x9957,0x9999,0x5653,0x589F,0x865B,
+0x8A31,0x61B2,0x6AF6,0x737B,0x8ED2,0x6B47,0x96AA,0x9A57,
+0x5955,0x7200,0x8D6B,0x9769,0x4FD4,0x5CF4,0x5F26,0x61F8,
+0x665B,0x6CEB,0x70AB,0x7384,0x73B9,0x73FE,0x7729,0x774D,
+0x7D43,0x7D62,0x7E23,0x8237,0x8852,0xFA0A,0x8CE2,0x9249,
+0x986F,0x5B51,0x7A74,0x8840,0x9801,0x5ACC,0x4FE0,0x5354,
+0x593E,0x5CFD,0x633E,0x6D79,0x72F9,0x8105,0x8107,0x83A2,
+0x92CF,0x9830,0x4EA8,0x5144,0x5211,0x578B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F62,0x6CC2,0x6ECE,0x7005,0x7050,0x70AF,0x7192,0x73E9,
+0x7469,0x834A,0x87A2,0x8861,0x9008,0x90A2,0x93A3,0x99A8,
+0x516E,0x5F57,0x60E0,0x6167,0x66B3,0x8559,0x8E4A,0x91AF,
+0x978B,0x4E4E,0x4E92,0x547C,0x58D5,0x58FA,0x597D,0x5CB5,
+0x5F27,0x6236,0x6248,0x660A,0x6667,0x6BEB,0x6D69,0x6DCF,
+0x6E56,0x6EF8,0x6F94,0x6FE0,0x6FE9,0x705D,0x72D0,0x7425,
+0x745A,0x74E0,0x7693,0x795C,0x7CCA,0x7E1E,0x80E1,0x82A6,
+0x846B,0x84BF,0x864E,0x865F,0x8774,0x8B77,0x8C6A,0x93AC,
+0x9800,0x9865,0x60D1,0x6216,0x9177,0x5A5A,0x660F,0x6DF7,
+0x6E3E,0x743F,0x9B42,0x5FFD,0x60DA,0x7B0F,0x54C4,0x5F18,
+0x6C5E,0x6CD3,0x6D2A,0x70D8,0x7D05,0x8679,0x8A0C,0x9D3B,
+0x5316,0x548C,0x5B05,0x6A3A,0x706B,0x7575, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x798D,0x79BE,0x82B1,0x83EF,0x8A71,0x8B41,0x8CA8,0x9774,
+0xFA0B,0x64F4,0x652B,0x78BA,0x78BB,0x7A6B,0x4E38,0x559A,
+0x5950,0x5BA6,0x5E7B,0x60A3,0x63DB,0x6B61,0x6665,0x6853,
+0x6E19,0x7165,0x74B0,0x7D08,0x9084,0x9A69,0x9C25,0x6D3B,
+0x6ED1,0x733E,0x8C41,0x95CA,0x51F0,0x5E4C,0x5FA8,0x604D,
+0x60F6,0x6130,0x614C,0x6643,0x6644,0x69A5,0x6CC1,0x6E5F,
+0x6EC9,0x6F62,0x714C,0x749C,0x7687,0x7BC1,0x7C27,0x8352,
+0x8757,0x9051,0x968D,0x9EC3,0x532F,0x56DE,0x5EFB,0x5F8A,
+0x6062,0x6094,0x61F7,0x6666,0x6703,0x6A9C,0x6DEE,0x6FAE,
+0x7070,0x736A,0x7E6A,0x81BE,0x8334,0x86D4,0x8AA8,0x8CC4,
+0x5283,0x7372,0x5B96,0x6A6B,0x9404,0x54EE,0x5686,0x5B5D,
+0x6548,0x6585,0x66C9,0x689F,0x6D8D,0x6DC6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x723B,0x80B4,0x9175,0x9A4D,0x4FAF,0x5019,0x539A,0x540E,
+0x543C,0x5589,0x55C5,0x5E3F,0x5F8C,0x673D,0x7166,0x73DD,
+0x9005,0x52DB,0x52F3,0x5864,0x58CE,0x7104,0x718F,0x71FB,
+0x85B0,0x8A13,0x6688,0x85A8,0x55A7,0x6684,0x714A,0x8431,
+0x5349,0x5599,0x6BC1,0x5F59,0x5FBD,0x63EE,0x6689,0x7147,
+0x8AF1,0x8F1D,0x9EBE,0x4F11,0x643A,0x70CB,0x7566,0x8667,
+0x6064,0x8B4E,0x9DF8,0x5147,0x51F6,0x5308,0x6D36,0x80F8,
+0x9ED1,0x6615,0x6B23,0x7098,0x75D5,0x5403,0x5C79,0x7D07,
+0x8A16,0x6B20,0x6B3D,0x6B46,0x5438,0x6070,0x6D3D,0x7FD5,
+0x8208,0x50D6,0x51DE,0x559C,0x566B,0x56CD,0x59EC,0x5B09,
+0x5E0C,0x6199,0x6198,0x6231,0x665E,0x66E6,0x7199,0x71B9,
+0x71BA,0x72A7,0x79A7,0x7A00,0x7FB2,0x8A70};
+
+static int func_ksc5601_uni_onechar(int code){
+ if ((code>=0x8141)&&(code<=0xC8FE))
+ return(tab_ksc5601_uni0[code-0x8141]);
+ if ((code>=0xCAA1)&&(code<=0xFDFE))
+ return(tab_ksc5601_uni1[code-0xCAA1]);
+ return(0);
+}
+/* page 0 0x00A1-0x0167 */
+static uint16 tab_uni_ksc56010[]={
+0xA2AE, 0, 0,0xA2B4, 0, 0,0xA1D7,0xA1A7,
+ 0,0xA8A3, 0, 0,0xA1A9, 0, 0,0xA1C6,
+0xA1BE,0xA9F7,0xA9F8,0xA2A5, 0,0xA2D2,0xA1A4,0xA2AC,
+0xA9F6,0xA8AC, 0,0xA8F9,0xA8F6,0xA8FA,0xA2AF, 0,
+ 0, 0, 0, 0, 0,0xA8A1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA8A2,
+ 0, 0, 0, 0, 0, 0,0xA1BF,0xA8AA,
+ 0, 0, 0, 0, 0,0xA8AD,0xA9AC, 0,
+ 0, 0, 0, 0, 0,0xA9A1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA9A3,
+ 0, 0, 0, 0, 0, 0,0xA1C0,0xA9AA,
+ 0, 0, 0, 0, 0,0xA9AD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA9A2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA8A4,0xA9A4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA9A5,0xA8A6,0xA9A6, 0, 0, 0, 0,0xA9A7,
+ 0, 0, 0, 0, 0, 0,0xA8A8,0xA9A8,
+0xA8A9,0xA9A9, 0, 0, 0, 0, 0, 0,
+0xA9B0,0xA8AF,0xA9AF, 0, 0, 0, 0, 0,
+ 0,0xA8AB,0xA9AB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA8AE,0xA9AE};
+
+/* page 1 0x02C7-0x0451 */
+static uint16 tab_uni_ksc56011[]={
+0xA2A7, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA2B0, 0, 0, 0, 0, 0, 0,
+ 0,0xA2A8,0xA2AB,0xA2AA,0xA2AD, 0,0xA2A9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA5C1,0xA5C2,0xA5C3,0xA5C4,0xA5C5,0xA5C6,
+0xA5C7,0xA5C8,0xA5C9,0xA5CA,0xA5CB,0xA5CC,0xA5CD,0xA5CE,
+0xA5CF,0xA5D0,0xA5D1, 0,0xA5D2,0xA5D3,0xA5D4,0xA5D5,
+0xA5D6,0xA5D7,0xA5D8, 0, 0, 0, 0, 0,
+ 0, 0,0xA5E1,0xA5E2,0xA5E3,0xA5E4,0xA5E5,0xA5E6,
+0xA5E7,0xA5E8,0xA5E9,0xA5EA,0xA5EB,0xA5EC,0xA5ED,0xA5EE,
+0xA5EF,0xA5F0,0xA5F1, 0,0xA5F2,0xA5F3,0xA5F4,0xA5F5,
+0xA5F6,0xA5F7,0xA5F8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xACA7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xACA1,0xACA2,0xACA3,0xACA4,0xACA5,0xACA6,0xACA8,
+0xACA9,0xACAA,0xACAB,0xACAC,0xACAD,0xACAE,0xACAF,0xACB0,
+0xACB1,0xACB2,0xACB3,0xACB4,0xACB5,0xACB6,0xACB7,0xACB8,
+0xACB9,0xACBA,0xACBB,0xACBC,0xACBD,0xACBE,0xACBF,0xACC0,
+0xACC1,0xACD1,0xACD2,0xACD3,0xACD4,0xACD5,0xACD6,0xACD8,
+0xACD9,0xACDA,0xACDB,0xACDC,0xACDD,0xACDE,0xACDF,0xACE0,
+0xACE1,0xACE2,0xACE3,0xACE4,0xACE5,0xACE6,0xACE7,0xACE8,
+0xACE9,0xACEA,0xACEB,0xACEC,0xACED,0xACEE,0xACEF,0xACF0,
+0xACF1, 0,0xACD7};
+
+/* page 2 0x2015-0x2312 */
+static uint16 tab_uni_ksc56012[]={
+0xA1AA, 0, 0,0xA1AE,0xA1AF, 0, 0,0xA1B0,
+0xA1B1, 0, 0,0xA2D3,0xA2D4, 0, 0, 0,
+0xA1A5,0xA1A6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA2B6, 0,0xA1C7,0xA1C8, 0,
+ 0, 0, 0, 0, 0, 0,0xA1D8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA9F9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA9FA, 0,0xA9FB,0xA9FC,0xA9FD,0xA9FE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA1C9, 0,
+ 0, 0, 0, 0,0xA2B5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA7A4, 0,
+ 0,0xA2E0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA2E5,0xA2E2, 0, 0,
+ 0,0xA7D9, 0, 0, 0, 0,0xA1CA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA8F7,0xA8F8,
+ 0, 0, 0, 0, 0, 0,0xA8FB,0xA8FC,
+0xA8FD,0xA8FE, 0,0xA5B0,0xA5B1,0xA5B2,0xA5B3,0xA5B4,
+0xA5B5,0xA5B6,0xA5B7,0xA5B8,0xA5B9, 0, 0, 0,
+ 0, 0, 0,0xA5A1,0xA5A2,0xA5A3,0xA5A4,0xA5A5,
+0xA5A6,0xA5A7,0xA5A8,0xA5A9,0xA5AA, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA1E7,0xA1E8,0xA1E6,0xA1E9,0xA1EA,
+0xA2D5,0xA2D8,0xA2D6,0xA2D9,0xA2D7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA2A1, 0,0xA2A2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA2A3, 0,0xA1D3,0xA2A4, 0,
+ 0, 0,0xA1D4,0xA1F4, 0, 0,0xA1F5, 0,
+ 0, 0,0xA2B3, 0,0xA2B2, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1EE, 0, 0,
+0xA1F0,0xA1C4, 0,0xA1D0, 0, 0, 0, 0,
+0xA1AB, 0,0xA1FC,0xA1FD,0xA1FB,0xA1FA,0xA1F2,0xA1F3,
+ 0,0xA2B1, 0, 0, 0, 0, 0,0xA1C5,
+0xA1F1, 0, 0, 0, 0, 0, 0,0xA1AD,
+0xA1EF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1D6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA1C1,0xA1D5, 0, 0,0xA1C2,
+0xA1C3, 0, 0, 0, 0,0xA1EC,0xA1ED, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1F8,0xA1F9, 0,
+ 0,0xA1F6,0xA1F7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA2C1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1D1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1D2};
+
+/* page 3 0x2460-0x266D */
+static uint16 tab_uni_ksc56013[]={
+0xA8E7,0xA8E8,0xA8E9,0xA8EA,0xA8EB,0xA8EC,0xA8ED,0xA8EE,
+0xA8EF,0xA8F0,0xA8F1,0xA8F2,0xA8F3,0xA8F4,0xA8F5, 0,
+ 0, 0, 0, 0,0xA9E7,0xA9E8,0xA9E9,0xA9EA,
+0xA9EB,0xA9EC,0xA9ED,0xA9EE,0xA9EF,0xA9F0,0xA9F1,0xA9F2,
+0xA9F3,0xA9F4,0xA9F5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA9CD,0xA9CE,0xA9CF,0xA9D0,
+0xA9D1,0xA9D2,0xA9D3,0xA9D4,0xA9D5,0xA9D6,0xA9D7,0xA9D8,
+0xA9D9,0xA9DA,0xA9DB,0xA9DC,0xA9DD,0xA9DE,0xA9DF,0xA9E0,
+0xA9E1,0xA9E2,0xA9E3,0xA9E4,0xA9E5,0xA9E6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA8CD,0xA8CE,0xA8CF,0xA8D0,0xA8D1,0xA8D2,0xA8D3,0xA8D4,
+0xA8D5,0xA8D6,0xA8D7,0xA8D8,0xA8D9,0xA8DA,0xA8DB,0xA8DC,
+0xA8DD,0xA8DE,0xA8DF,0xA8E0,0xA8E1,0xA8E2,0xA8E3,0xA8E4,
+0xA8E5,0xA8E6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA6A1,0xA6AC,0xA6A2,0xA6AD, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA6A3,0xA6C8,0xA6C7,0xA6AE,
+0xA6A4,0xA6C2,0xA6C1,0xA6AF,0xA6A6,0xA6C6,0xA6C5,0xA6B1,
+0xA6A5,0xA6C4,0xA6C3,0xA6B0,0xA6A7,0xA6BC,0xA6C9,0xA6CA,
+0xA6B7,0xA6CB,0xA6CC,0xA6B2,0xA6A9,0xA6BE,0xA6CD,0xA6CE,
+0xA6B9,0xA6CF,0xA6D0,0xA6B4,0xA6A8,0xA6D1,0xA6D2,0xA6B8,
+0xA6BD,0xA6D3,0xA6D4,0xA6B3,0xA6AA,0xA6D5,0xA6D6,0xA6BA,
+0xA6BF,0xA6D7,0xA6D8,0xA6B5,0xA6AB,0xA6D9,0xA6DA,0xA6BB,
+0xA6DB,0xA6DC,0xA6C0,0xA6DD,0xA6DE,0xA6DF,0xA6E0,0xA6E1,
+0xA6E2,0xA6E3,0xA6E4,0xA6B6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA2C6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1E1,0xA1E0, 0,0xA2C3,0xA2C7,0xA2C8,0xA2CB,0xA2CA,
+0xA2C9,0xA2CC, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA1E3,0xA1E2, 0, 0,0xA2BA,0xA2B9,
+ 0, 0, 0, 0,0xA1E5,0xA1E4, 0, 0,
+0xA2B8,0xA2B7, 0, 0, 0, 0,0xA1DF,0xA1DE,
+0xA2C2, 0, 0,0xA1DB, 0, 0,0xA1DD,0xA1DC,
+0xA2C4,0xA2C5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1DA,0xA1D9, 0,
+ 0, 0, 0, 0, 0, 0,0xA2CF,0xA2CE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA2D0, 0,0xA2D1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1CF, 0,0xA1CE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA2BC,0xA2BD, 0,0xA2C0,0xA2BB,0xA2BE, 0,0xA2BF,
+0xA2CD,0xA2DB,0xA2DC, 0,0xA2DD,0xA2DA};
+
+/* page 4 0x3000-0x327F */
+static uint16 tab_uni_ksc56014[]={
+0xA1A1,0xA1A2,0xA1A3,0xA1A8, 0, 0, 0, 0,
+0xA1B4,0xA1B5,0xA1B6,0xA1B7,0xA1B8,0xA1B9,0xA1BA,0xA1BB,
+0xA1BC,0xA1BD, 0,0xA1EB,0xA1B2,0xA1B3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xAAA1,0xAAA2,0xAAA3,0xAAA4,0xAAA5,0xAAA6,0xAAA7,
+0xAAA8,0xAAA9,0xAAAA,0xAAAB,0xAAAC,0xAAAD,0xAAAE,0xAAAF,
+0xAAB0,0xAAB1,0xAAB2,0xAAB3,0xAAB4,0xAAB5,0xAAB6,0xAAB7,
+0xAAB8,0xAAB9,0xAABA,0xAABB,0xAABC,0xAABD,0xAABE,0xAABF,
+0xAAC0,0xAAC1,0xAAC2,0xAAC3,0xAAC4,0xAAC5,0xAAC6,0xAAC7,
+0xAAC8,0xAAC9,0xAACA,0xAACB,0xAACC,0xAACD,0xAACE,0xAACF,
+0xAAD0,0xAAD1,0xAAD2,0xAAD3,0xAAD4,0xAAD5,0xAAD6,0xAAD7,
+0xAAD8,0xAAD9,0xAADA,0xAADB,0xAADC,0xAADD,0xAADE,0xAADF,
+0xAAE0,0xAAE1,0xAAE2,0xAAE3,0xAAE4,0xAAE5,0xAAE6,0xAAE7,
+0xAAE8,0xAAE9,0xAAEA,0xAAEB,0xAAEC,0xAAED,0xAAEE,0xAAEF,
+0xAAF0,0xAAF1,0xAAF2,0xAAF3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xABA1,0xABA2,0xABA3,0xABA4,0xABA5,0xABA6,0xABA7,
+0xABA8,0xABA9,0xABAA,0xABAB,0xABAC,0xABAD,0xABAE,0xABAF,
+0xABB0,0xABB1,0xABB2,0xABB3,0xABB4,0xABB5,0xABB6,0xABB7,
+0xABB8,0xABB9,0xABBA,0xABBB,0xABBC,0xABBD,0xABBE,0xABBF,
+0xABC0,0xABC1,0xABC2,0xABC3,0xABC4,0xABC5,0xABC6,0xABC7,
+0xABC8,0xABC9,0xABCA,0xABCB,0xABCC,0xABCD,0xABCE,0xABCF,
+0xABD0,0xABD1,0xABD2,0xABD3,0xABD4,0xABD5,0xABD6,0xABD7,
+0xABD8,0xABD9,0xABDA,0xABDB,0xABDC,0xABDD,0xABDE,0xABDF,
+0xABE0,0xABE1,0xABE2,0xABE3,0xABE4,0xABE5,0xABE6,0xABE7,
+0xABE8,0xABE9,0xABEA,0xABEB,0xABEC,0xABED,0xABEE,0xABEF,
+0xABF0,0xABF1,0xABF2,0xABF3,0xABF4,0xABF5,0xABF6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA4A1,0xA4A2,0xA4A3,0xA4A4,0xA4A5,0xA4A6,0xA4A7,
+0xA4A8,0xA4A9,0xA4AA,0xA4AB,0xA4AC,0xA4AD,0xA4AE,0xA4AF,
+0xA4B0,0xA4B1,0xA4B2,0xA4B3,0xA4B4,0xA4B5,0xA4B6,0xA4B7,
+0xA4B8,0xA4B9,0xA4BA,0xA4BB,0xA4BC,0xA4BD,0xA4BE,0xA4BF,
+0xA4C0,0xA4C1,0xA4C2,0xA4C3,0xA4C4,0xA4C5,0xA4C6,0xA4C7,
+0xA4C8,0xA4C9,0xA4CA,0xA4CB,0xA4CC,0xA4CD,0xA4CE,0xA4CF,
+0xA4D0,0xA4D1,0xA4D2,0xA4D3,0xA4D4,0xA4D5,0xA4D6,0xA4D7,
+0xA4D8,0xA4D9,0xA4DA,0xA4DB,0xA4DC,0xA4DD,0xA4DE,0xA4DF,
+0xA4E0,0xA4E1,0xA4E2,0xA4E3,0xA4E4,0xA4E5,0xA4E6,0xA4E7,
+0xA4E8,0xA4E9,0xA4EA,0xA4EB,0xA4EC,0xA4ED,0xA4EE,0xA4EF,
+0xA4F0,0xA4F1,0xA4F2,0xA4F3,0xA4F4,0xA4F5,0xA4F6,0xA4F7,
+0xA4F8,0xA4F9,0xA4FA,0xA4FB,0xA4FC,0xA4FD,0xA4FE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA9B1,0xA9B2,0xA9B3,0xA9B4,0xA9B5,0xA9B6,0xA9B7,0xA9B8,
+0xA9B9,0xA9BA,0xA9BB,0xA9BC,0xA9BD,0xA9BE,0xA9BF,0xA9C0,
+0xA9C1,0xA9C2,0xA9C3,0xA9C4,0xA9C5,0xA9C6,0xA9C7,0xA9C8,
+0xA9C9,0xA9CA,0xA9CB,0xA9CC,0xA2DF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA8B1,0xA8B2,0xA8B3,0xA8B4,0xA8B5,0xA8B6,0xA8B7,0xA8B8,
+0xA8B9,0xA8BA,0xA8BB,0xA8BC,0xA8BD,0xA8BE,0xA8BF,0xA8C0,
+0xA8C1,0xA8C2,0xA8C3,0xA8C4,0xA8C5,0xA8C6,0xA8C7,0xA8C8,
+0xA8C9,0xA8CA,0xA8CB,0xA8CC, 0, 0, 0,0xA2DE
+};
+
+/* page 5 0x3380-0x33DD */
+static uint16 tab_uni_ksc56015[]={
+0xA7C9,0xA7CA,0xA7CB,0xA7CC,0xA7CD, 0, 0, 0,
+0xA7BA,0xA7BB,0xA7DC,0xA7DD,0xA7DE,0xA7B6,0xA7B7,0xA7B8,
+0xA7D4,0xA7D5,0xA7D6,0xA7D7,0xA7D8,0xA7A1,0xA7A2,0xA7A3,
+0xA7A5,0xA7AB,0xA7AC,0xA7AD,0xA7AE,0xA7AF,0xA7B0,0xA7B1,
+0xA7B2,0xA7B3,0xA7B4,0xA7A7,0xA7A8,0xA7A9,0xA7AA,0xA7BD,
+0xA7BE,0xA7E5,0xA7E6,0xA7E7,0xA7E8,0xA7E1,0xA7E2,0xA7E3,
+0xA7BF,0xA7C0,0xA7C1,0xA7C2,0xA7C3,0xA7C4,0xA7C5,0xA7C6,
+0xA7C7,0xA7C8,0xA7CE,0xA7CF,0xA7D0,0xA7D1,0xA7D2,0xA7D3,
+0xA7DA,0xA7DB,0xA2E3,0xA7EC,0xA7A6,0xA7E0,0xA7EF,0xA2E1,
+0xA7BC,0xA7ED,0xA7B5, 0, 0, 0, 0,0xA7B9,
+0xA7EA, 0, 0,0xA7EB, 0, 0,0xA7DF, 0,
+0xA2E4, 0, 0,0xA7E4,0xA7EE,0xA7E9};
+
+/* page 6 0x4E00-0x947F */
+static uint16 tab_uni_ksc56016[]={
+0xECE9,0xEFCB, 0,0xF6D2, 0, 0, 0,0xD8B2,
+0xEDDB,0xDFB2,0xDFBE,0xF9BB, 0,0xDCF4, 0, 0,
+ 0,0xF5E4, 0, 0,0xF3A6,0xDDE0,0xE1A6, 0,
+0xCEF8,0xDCB0, 0, 0, 0, 0,0xE3AA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF1E9, 0, 0,
+ 0, 0,0xCDFA, 0, 0, 0, 0, 0,
+0xFCAF,0xD3A1, 0,0xF1AB, 0, 0, 0, 0,
+ 0, 0,0xE7D1,0xD2AC, 0,0xCEF9, 0, 0,
+ 0, 0, 0,0xF1FD, 0,0xDEBF,0xFBBA,0xF9B9,
+ 0, 0, 0, 0, 0, 0,0xCED2, 0,
+0xE3AB,0xEBE0, 0, 0, 0,0xCEFA,0xCBF7,0xE5A5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCAE1, 0,0xD4CC, 0, 0,
+ 0, 0, 0,0xEAE1, 0, 0,0xDCE3,0xDFAD,
+ 0, 0, 0, 0, 0, 0,0xCBEB, 0,
+ 0, 0,0xD5AF, 0, 0, 0,0xD6F5, 0,
+0xE5F8, 0, 0,0xDEC0,0xECA3, 0,0xE9CD, 0,
+0xEAA7,0xE9F6,0xFBBB, 0,0xE7E9,0xEFCC, 0, 0,
+0xD0E6, 0, 0,0xDEC1, 0, 0,0xE4AC, 0,
+ 0,0xD8CC,0xF9F1, 0,0xCEDF,0xFAA4,0xE6B2, 0,
+0xFAFB, 0, 0,0xFABD,0xCCC8,0xEFCD,0xD5D5, 0,
+ 0, 0, 0, 0, 0, 0,0xD3A2, 0,
+ 0, 0,0xECD1, 0, 0, 0, 0, 0,
+0xE4A7,0xECD2, 0, 0,0xF6B1, 0, 0,0xCEFB,
+ 0, 0,0xD0D1,0xCBBF, 0,0xEDA4, 0, 0,
+ 0, 0, 0, 0,0xEDA8,0xDEC2,0xF6E2,0xEDDC,
+0xDCF5,0xE0B9, 0, 0, 0,0xD4CE, 0,0xF4B5,
+ 0, 0, 0,0xD3DB,0xD6B5,0xECA4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE4E6, 0,0xF1EA, 0, 0, 0,0xCBEC,0xCBC0,
+ 0, 0, 0,0xECF2, 0, 0, 0, 0,
+ 0,0xD0EA, 0, 0, 0, 0, 0, 0,
+ 0,0xF9F2,0xECA5,0xD0DF, 0,0xE7EA,0xD0EB,0xDCD1,
+0xDBE9,0xFDCC, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDBD7,
+ 0, 0, 0, 0,0xDAE1, 0,0xD6B6, 0,
+0xE3DF, 0,0xDEC3, 0,0xDEC4,0xCAA1, 0, 0,
+ 0, 0, 0,0xEEEC, 0, 0,0xD3A3,0xEEB7,
+0xF8CF, 0, 0, 0, 0,0xEAC8,0xEEB8,0xF1AC,
+0xF1A5,0xE9CE, 0, 0, 0,0xF9BC, 0, 0,
+ 0,0xE5F9,0xECEA,0xDDD6,0xEDC2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF8A5, 0, 0, 0, 0, 0,0xE5BA,
+0xDBD8, 0, 0,0xCAA2, 0, 0,0xD1CD, 0,
+ 0, 0,0xEEED, 0, 0, 0,0xECEB,0xDEC5,
+ 0,0xE3E0, 0,0xCAC9,0xF2E9, 0,0xD5CE, 0,
+0xF6B6, 0,0xCEC2,0xD6C7, 0,0xE3B4, 0,0xF1AD,
+ 0,0xEAE2, 0, 0, 0, 0,0xD7C2, 0,
+0xF3A7, 0, 0,0xCDEA, 0,0xEBEE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD9B2,0xFDA5,
+ 0, 0, 0, 0, 0,0xF6D5,0xD5E2, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF8B5,
+ 0, 0,0xCCF5,0xF5B5,0xE4AD, 0, 0, 0,
+ 0,0xE7EB,0xF1D5, 0, 0, 0,0xF0BB, 0,
+ 0,0xE9B5, 0,0xCCC9,0xFAD5, 0, 0,0xE1D4,
+ 0, 0,0xD7D6, 0, 0,0xDCC1, 0,0xDEC6,
+0xFAEF,0xE3E1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE1F3,0xDCF6,
+ 0,0xCEFC, 0,0xDBC4, 0,0xF8F1, 0, 0,
+0xDCE4, 0,0xE5EF, 0, 0, 0, 0, 0,
+ 0, 0,0xDCB1, 0, 0, 0,0xD5D6, 0,
+ 0,0xF3DA, 0,0xCBC1, 0,0xDBC3, 0, 0,
+ 0,0xD9FA,0xD3EE, 0, 0, 0,0xFAB8, 0,
+ 0,0xFDA6,0xEBEF, 0,0xF4A6, 0,0xCCCA,0xF3A8,
+ 0,0xF3DB, 0,0xDBA7,0xF6B7, 0,0xCFE6,0xF0F2,
+0xCBDA, 0,0xE7D2,0xD7C3,0xF6F0,0xE8DE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE5A6, 0, 0, 0, 0,
+ 0, 0, 0,0xE5E7, 0, 0, 0,0xCAA3,
+0xCCA7,0xEAC9, 0, 0, 0, 0, 0,0xF8B6,
+ 0, 0, 0, 0, 0,0xFAA5, 0, 0,
+ 0, 0,0xF1AE, 0,0xEFCE, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCBED, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF6B0,0xEFCF,0xE9CF, 0,
+0xF7DE, 0, 0, 0, 0, 0, 0, 0,
+0xCED3, 0, 0, 0, 0,0xDCF7, 0, 0,
+ 0, 0, 0, 0, 0,0xDBA8, 0, 0,
+ 0,0xCBF8, 0, 0, 0, 0, 0, 0,
+0xDFA1,0xDDE1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF5CA,0xE9B6, 0, 0,
+ 0, 0,0xE7EC,0xEEEE, 0,0xF3F0, 0,0xDFBF,
+ 0, 0, 0, 0, 0, 0,0xCCCB, 0,
+ 0, 0, 0, 0, 0,0xD0C1, 0, 0,
+ 0,0xF4D2,0xE0BA, 0, 0, 0, 0,0xDFC0,
+ 0,0xCEE0, 0, 0, 0,0xDCD2,0xFDEA, 0,
+ 0, 0,0xD6F6, 0, 0, 0,0xEACA, 0,
+ 0, 0, 0, 0, 0,0xE8E9, 0,0xE3AC,
+ 0, 0, 0, 0, 0,0xF3D0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCAA4, 0,0xDBF8, 0, 0, 0,0xDEC7,
+0xEBF0,0xF1D6, 0, 0,0xE5E2, 0,0xCCCC, 0,
+ 0,0xCBFB, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEAE3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDFC1,
+ 0,0xD6ED, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE9D0, 0, 0, 0, 0, 0,
+ 0, 0,0xEEB9, 0, 0, 0, 0,0xD5E3,
+ 0, 0,0xD1D3, 0,0xE5F0, 0, 0, 0,
+0xE8B4,0xEBC3, 0,0xEAAA,0xFAFC,0xF5F6,0xF0BC,0xFDD4,
+0xE0BB,0xCEC3, 0,0xD0BA,0xF7BA,0xD8F3,0xF7CD, 0,
+ 0, 0,0xE4AE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD4DF, 0, 0, 0,
+ 0, 0,0xD0E7, 0, 0,0xECFD, 0,0xD2AE,
+0xEEEF,0xD5D7,0xEAE4,0xF8A2,0xCDEB,0xD7BF,0xFBB1, 0,
+ 0,0xCDEC, 0, 0, 0,0xDCB2,0xD0EC,0xCEFD,
+0xEEF0, 0, 0, 0,0xCCC2, 0, 0, 0,
+0xD0ED, 0, 0, 0, 0, 0,0xE5F7, 0,
+ 0, 0,0xF3FC, 0, 0,0xEEA2, 0, 0,
+ 0, 0,0xD9B3, 0, 0,0xD8F4, 0,0xE9B7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCEAE, 0, 0, 0, 0,0xD9A2, 0, 0,
+ 0, 0,0xD8F1, 0,0xD4CF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE5A7,0xD5D2,
+ 0, 0, 0, 0, 0,0xD6A9, 0, 0,
+ 0, 0, 0, 0,0xF4A2, 0,0xF1D7, 0,
+ 0,0xD5D8, 0,0xF0BD,0xD7D0,0xD4D0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD7CF,0xEBEA,0xFDEB, 0,
+ 0,0xDBED, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFCC5,0xCBC2, 0, 0, 0, 0,0xFDD5, 0,
+0xF4C8,0xE8EA,0xF5F3, 0, 0,0xF9DE, 0, 0,
+0xD3EF, 0, 0,0xECD3, 0, 0,0xDDC2,0xEFB7,
+0xE7D4, 0,0xCACA, 0, 0, 0,0xD9FB, 0,
+ 0,0xFAFD, 0, 0, 0, 0, 0,0xD6AA,
+ 0, 0, 0, 0, 0,0xF4F8, 0, 0,
+ 0, 0, 0, 0,0xF7F7,0xDCAC, 0, 0,
+ 0,0xD7D7,0xDFA2, 0, 0, 0,0xCEBE, 0,
+0xD3F0, 0, 0, 0, 0, 0,0xF0A4,0xE1EC,
+0xCFE7,0xF3CB,0xEDA9,0xCABE, 0, 0, 0, 0,
+ 0, 0, 0,0xF4EF, 0, 0, 0,0xF6CE,
+ 0, 0,0xDEFB,0xD0BB,0xD5B7,0xEEF1, 0, 0,
+ 0, 0, 0, 0,0xF4A8, 0,0xDCF8, 0,
+ 0, 0, 0,0xCBA7, 0,0xDACE, 0, 0,
+ 0,0xE0E6, 0, 0, 0, 0, 0, 0,
+ 0,0xEDA5,0xEEF2, 0, 0, 0, 0,0xDCF9,
+ 0, 0,0xF9DC, 0, 0,0xF3DC, 0, 0,
+ 0, 0, 0, 0, 0,0xF8F2, 0,0xF4F9,
+ 0, 0, 0,0xFCF1, 0, 0, 0,0xD0BC,
+0xDBF9,0xD7B1, 0, 0, 0,0xCBFC, 0, 0,
+ 0,0xF0A5,0xCBFD, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD5F4, 0, 0, 0,0xCDED,
+0xCAA5, 0, 0,0xD6AB,0xD0C2, 0, 0, 0,
+ 0,0xF0BE,0xD2BD,0xCCA4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFAB6, 0,
+ 0,0xCCCD, 0,0xDAFA, 0,0xF6CF, 0,0xE9B8,
+ 0,0xD8F5, 0, 0, 0,0xCCCE, 0, 0,
+ 0, 0,0xD7CD, 0, 0,0xD4D1,0xE9ED, 0,
+0xCAEB,0xD9E2, 0,0xFDB2, 0,0xE3AD,0xD6CC,0xD9B4,
+ 0, 0,0xE1A7,0xEED3,0xD0C3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFDB3, 0,0xD5E4, 0, 0,
+0xCFE8, 0,0xEDC3,0xD0B2, 0, 0,0xCEFE,0xDAA8,
+ 0, 0, 0, 0, 0,0xF8D0, 0, 0,
+0xFDD6, 0, 0, 0, 0,0xF8D1, 0,0xF8D2,
+0xDCD3, 0, 0, 0, 0,0xDDE2,0xFBF9,0xDDC1,
+ 0,0xE3B5, 0, 0, 0, 0, 0, 0,
+0xEDDD,0xCEC4, 0,0xCBA1, 0, 0, 0, 0,
+ 0, 0,0xDDE3, 0, 0, 0, 0,0xFCDD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF9AF, 0, 0, 0, 0, 0,0xD2FB,
+0xCFA1,0xE4A8, 0,0xF4B6,0xECFE, 0, 0,0xE3AE,
+0xE7ED,0xFDC1,0xDAE2, 0, 0,0xD8B3, 0, 0,
+ 0,0xDDE4,0xF0EF,0xF6F1,0xFAF0, 0, 0,0xD1F5,
+ 0, 0,0xDACF, 0,0xDCD4, 0,0xDCA6, 0,
+0xEFBF, 0, 0, 0, 0, 0,0xCECF, 0,
+0xE0D9, 0, 0, 0, 0, 0, 0,0xD9D6,
+0xECD4,0xEACB, 0, 0,0xCABF,0xD5B0, 0,0xCFE9,
+ 0, 0, 0, 0, 0,0xF1ED, 0,0xCCCF,
+ 0, 0, 0, 0,0xE4F8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE4ED, 0, 0, 0, 0,
+0xD7D8, 0,0xFDA7, 0, 0, 0, 0,0xEAAB,
+0xF6B2, 0, 0, 0, 0,0xCFF0,0xF9BD, 0,
+ 0, 0, 0, 0, 0,0xE6F4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCBDB, 0, 0, 0, 0,
+ 0, 0, 0,0xF3D1, 0, 0, 0, 0,
+0xE9D1,0xF3A9,0xD0E0,0xE9D2, 0,0xDAE3, 0, 0,
+ 0, 0, 0, 0,0xE2D2, 0,0xF6A2,0xE1F4,
+ 0, 0, 0,0xDAE4, 0, 0, 0, 0,
+ 0,0xE7D5,0xF5BF,0xCFA2,0xCDAF,0xCFA3, 0, 0,
+ 0,0xCDB0,0xF1FE,0xD0A3,0xE1AF,0xF8A3, 0,0xCAA6,
+0xF7BB,0xF2EA,0xDEC8,0xE9D3, 0, 0, 0, 0,
+0xDEC9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFDDE,0xCAC0, 0, 0, 0,
+0xF9EA,0xD1CE,0xEED4, 0,0xD4D2,0xD9A3,0xFDA8,0xD7D9,
+0xF7CE,0xFABE, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCFD6, 0,0xD7F0, 0,0xEBE1,
+0xF8C5, 0, 0, 0, 0, 0,0xDCFA, 0,
+ 0,0xDDC3, 0,0xF9DF, 0, 0, 0, 0,
+ 0, 0, 0,0xE7EF, 0, 0, 0, 0,
+0xFDE5,0xF6A3, 0,0xD9FC,0xFDA9, 0,0xE7EE, 0,
+ 0, 0,0xD5E5, 0, 0, 0, 0, 0,
+0xEFD0, 0,0xCDB1, 0, 0, 0, 0, 0,
+ 0,0xF7A2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF1B2, 0,0xF1B1, 0, 0, 0, 0, 0,
+ 0,0xCDB2, 0,0xDAAB, 0,0xCAA7, 0, 0,
+ 0, 0, 0,0xE3E2,0xFBBC,0xD9A4, 0, 0,
+0xEEBA, 0, 0, 0, 0, 0,0xF8D3, 0,
+ 0, 0, 0, 0,0xFBFA, 0,0xCFA4, 0,
+0xDCFB, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF6E3, 0, 0, 0,
+0xEDAA, 0, 0,0xF2A1,0xCEE1, 0, 0, 0,
+ 0, 0, 0,0xFAA6, 0, 0, 0, 0,
+0xF9E0, 0, 0, 0, 0,0xECD6, 0, 0,
+0xE4EE,0xF9A1, 0, 0,0xFBEF, 0, 0, 0,
+0xF9EB,0xEEA3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEAAC, 0, 0, 0,0xCAA8, 0, 0,
+0xF4FA, 0, 0, 0, 0,0xCDD6,0xFCF6, 0,
+ 0, 0,0xF4C9, 0, 0, 0, 0, 0,
+ 0, 0,0xF8D4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF8A6, 0,0xDECA,0xF2C6,
+ 0, 0, 0, 0, 0, 0,0xD7DA, 0,
+0xD3D0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD8C5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEAE6,
+ 0,0xF3DD, 0, 0, 0,0xE4DA, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF6E4, 0,
+ 0, 0, 0, 0,0xF6F2, 0,0xDFC2, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9FD,
+ 0, 0, 0,0xCCF6, 0, 0,0xD3BA, 0,
+ 0, 0, 0, 0, 0, 0,0xE4AF, 0,
+ 0, 0, 0,0xF9E1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF0A6, 0, 0, 0,
+0xCBD3, 0, 0, 0,0xE0BC, 0,0xF4CA,0xD4FA,
+ 0,0xFDAA,0xF9E2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF4B7,0xFDC2,0xFCB0, 0,0xFDEC,0xCAE2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xFDBD,
+ 0,0xEAE7,0xDFC3,0xD1D2,0xCEE2, 0,0xD3A4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFDAB, 0,0xDFE0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF2C7, 0, 0, 0,
+ 0, 0,0xE7F0, 0,0xD0EE, 0, 0,0xF3AA,
+ 0, 0, 0,0xDECB,0xF6B8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE1F5,0xF1B3, 0,
+ 0, 0, 0, 0, 0, 0,0xF7A3, 0,
+ 0,0xCAA9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCFA5, 0, 0,0xDFC4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE1B0,
+ 0, 0,0xF0BF, 0,0xF6A4, 0,0xE3B6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFAC6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD0EF, 0, 0,0xFDED, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDDC4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFCF7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE6BF, 0, 0,
+ 0, 0, 0, 0,0xDEAD, 0,0xFABF, 0,
+ 0, 0, 0, 0,0xE5F1, 0, 0, 0,
+ 0, 0, 0, 0,0xEDC4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD2A5, 0, 0,0xFDEE, 0, 0,
+ 0,0xF5B6, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE1F6,0xDECC, 0, 0,0xFCDE, 0,
+0xECD7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCDDD, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD6B7,0xCDB3, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF8D5,0xE5D8, 0, 0, 0,
+0xCFEA, 0, 0,0xCFD0, 0,0xEACC, 0, 0,
+ 0, 0,0xEAAE,0xEAAD, 0, 0,0xD3F1, 0,
+0xD3A5, 0, 0, 0, 0, 0, 0,0xF7CF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEEA4, 0, 0, 0, 0,0xD0A4, 0, 0,
+0xF2A2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0F0, 0, 0, 0, 0,
+0xF2A3, 0,0xF7F8, 0, 0, 0, 0,0xD0B3,
+ 0, 0,0xDBA9, 0, 0,0xD3BB,0xCAEC, 0,
+0xF1A6,0xCBD5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF7E7, 0, 0,0xCDDE, 0,0xF7A4, 0,
+ 0, 0,0xF8C0, 0, 0, 0,0xD3DD, 0,
+0xCCD0, 0, 0, 0, 0,0xCFA6, 0, 0,
+ 0, 0, 0, 0,0xF6F3, 0, 0, 0,
+ 0, 0,0xE1F7, 0, 0, 0, 0, 0,
+0xD3DC, 0, 0,0xFAFE, 0, 0, 0, 0,
+ 0, 0, 0,0xFAA7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEBD9, 0,0xCFA7,0xEAAF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE4EF, 0, 0, 0,0xE9B9,
+0xF1D8, 0, 0,0xD8D8, 0, 0,0xE0F2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE6B4,
+0xDCFC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF3F1, 0, 0, 0,0xE3D0, 0, 0,0xF2FB,
+ 0,0xDBC6,0xD0F1, 0,0xD0F2, 0, 0, 0,
+0xCFDC, 0,0xD3D1, 0, 0,0xCCB1,0xF7D8, 0,
+0xCBA8,0xEBBC,0xE4BE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF4DC, 0,
+ 0,0xDCC2, 0, 0,0xF0A7, 0, 0,0xE6C0,
+ 0, 0,0xCAED, 0, 0, 0, 0,0xE8EB,
+0xE5E8,0xDCC3, 0, 0,0xEDDE,0xD3F2, 0, 0,
+ 0, 0,0xCCF7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xCED4,0xE7AB, 0, 0, 0,0xCBC3,
+ 0,0xE1B1, 0, 0,0xF7B2, 0, 0,0xD3F3,
+0xD3D2, 0,0xF5C0, 0, 0, 0,0xDFDD, 0,
+ 0,0xEEF3,0xE7F1, 0,0xFDB4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF2C8, 0, 0,
+ 0,0xF3D2, 0, 0,0xEEF4, 0,0xE2D3, 0,
+ 0, 0, 0,0xCCD1, 0,0xDFEA, 0, 0,
+ 0,0xE9BA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD9D7, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF5CD, 0,0xF1F2,0xFAC7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD9F8,0xD4C2, 0, 0, 0, 0,0xF6E5, 0,
+ 0, 0, 0,0xDDC5, 0, 0, 0, 0,
+ 0, 0,0xE7F2,0xEDDF, 0, 0,0xCACB, 0,
+ 0,0xDBFA, 0, 0, 0,0xE8B5, 0,0xD3A6,
+ 0, 0, 0, 0, 0, 0,0xFDB5, 0,
+ 0,0xF9C9, 0,0xE4E2, 0,0xFBBD, 0, 0,
+0xD7A4,0xCEC5, 0, 0, 0, 0,0xCED5,0xD6E6,
+ 0, 0, 0, 0,0xE5BD, 0, 0, 0,
+ 0, 0, 0,0xDECD,0xECF3, 0, 0,0xEDE0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xECEC,0xFBBE,0xDFEB, 0,0xE1F8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF9BE,
+ 0, 0, 0, 0,0xD0F3,0xE0AA,0xE8E2, 0,
+ 0,0xE2D4,0xD2FD, 0,0xE5A8, 0, 0, 0,
+ 0, 0,0xD9D3, 0, 0, 0, 0,0xD3DE,
+ 0,0xF4B8,0xF7BC,0xDCFD, 0,0xE8EC,0xE4E7, 0,
+ 0,0xE3F7, 0, 0, 0, 0, 0,0xECA8,
+ 0, 0, 0, 0, 0, 0,0xFAF1, 0,
+ 0, 0, 0, 0,0xE5F2, 0, 0,0xD0F4,
+0xD2AF,0xDCE5, 0, 0, 0, 0,0xD0A5,0xF1B4,
+0xFCB1,0xCCF8, 0, 0,0xDDC6,0xFAD1, 0,0xF7DF,
+ 0, 0,0xFAA8, 0, 0, 0, 0, 0,
+0xEEF5, 0,0xDECE, 0, 0, 0, 0,0xE7F3,
+ 0, 0,0xF7AC,0xEBC4,0xEDE1,0xE0AB,0xDDC7, 0,
+ 0, 0, 0,0xD2B3,0xD2BF, 0, 0, 0,
+0xCACC, 0, 0, 0, 0,0xFBBF, 0, 0,
+ 0, 0,0xE5FD,0xDDE5,0xD8CD, 0, 0, 0,
+ 0, 0,0xECF4, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0F5, 0, 0,0xE8ED,0xD0D2,
+ 0,0xD9D8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF6E6, 0, 0,
+0xDBAA, 0, 0, 0,0xF7E0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD8D9, 0,0xF4A3, 0, 0,0xF4DD, 0,
+ 0, 0, 0,0xEFD1, 0, 0,0xD9B5, 0,
+ 0,0xEDAB, 0,0xE3B7, 0, 0, 0, 0,
+0xEEBB,0xCDB4, 0,0xE0F3,0xEACD, 0, 0, 0,
+ 0,0xECF5,0xE8EE, 0,0xCBA9,0xF1AF, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCACD, 0,
+0xECA9, 0,0xF2EB, 0,0xFDEF, 0,0xF9F3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE6C1, 0, 0,0xECD8, 0, 0, 0,0xEDAC,
+ 0,0xEACE, 0,0xE8DF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDECF, 0, 0, 0, 0, 0, 0,
+0xD2A6, 0, 0,0xE7F4,0xD1D6, 0, 0,0xE6C2,
+0xE3E3, 0, 0, 0, 0,0xE4B0, 0, 0,
+ 0,0xD8B4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF6A5, 0,
+ 0, 0, 0, 0,0xF3DE, 0, 0, 0,
+ 0,0xD7A5, 0, 0, 0, 0,0xF7E8, 0,
+ 0,0xE8C6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFBE6, 0, 0, 0, 0, 0,
+ 0, 0,0xDDE6, 0, 0, 0,0xDCFE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD8DA, 0, 0, 0, 0, 0,
+ 0, 0,0xDAAC,0xEAB0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE3B8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCAAA,0xE1F9, 0,0xEAB1, 0, 0, 0,
+ 0,0xF2EC, 0, 0,0xFAEE, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEED5, 0, 0, 0, 0,0xF9F4, 0,
+ 0,0xD2EC, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFBFB, 0, 0,
+ 0,0xFDF0, 0,0xE0BD,0xCEE3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF8C6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDEAE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xDFC5, 0, 0,0xE5BE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEDAD,0xFAEA, 0, 0,0xCDEE,0xEDA6, 0,0xEDAE,
+0xF0ED, 0,0xDDA1, 0,0xEDAF,0xFCF8, 0,0xD8EB,
+ 0, 0, 0,0xCCF9,0xCDB5, 0, 0, 0,
+ 0,0xFAA9, 0,0xE1DD, 0, 0, 0, 0,
+0xE2D5,0xEDCF, 0, 0, 0,0xDDA2, 0, 0,
+0xF9CA, 0,0xEAE8, 0,0xE5ED, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD3EB, 0,0xE9D4,
+0xE1FA,0xE4CC, 0,0xE1E4,0xE8C7, 0, 0,0xCEDB,
+ 0, 0, 0,0xDCD5, 0,0xF7B5,0xFCF3,0xF0F3,
+0xCEAF,0xF1B5,0xEFD2,0xE8C8,0xEBF1, 0, 0, 0,
+ 0, 0,0xCBD4,0xE0BE,0xE3F8,0xEAE9,0xFCB2, 0,
+ 0, 0, 0, 0,0xE0F4, 0,0xCFE0, 0,
+0xEEA5, 0, 0,0xFAAA,0xE6C3,0xE1B2,0xCAAB, 0,
+0xE3E4,0xE9BB, 0, 0, 0, 0, 0,0xE2D6,
+0xF3F2, 0,0xEED6,0xEAB2,0xD0F6,0xECD9,0xDACB,0xCFA8,
+ 0, 0, 0, 0,0xDDA3, 0, 0, 0,
+0xD8DB, 0,0xF9CE,0xE9D5,0xE3D1, 0, 0,0xD2BC,
+ 0, 0, 0, 0, 0, 0,0xD8AC,0xF3CC,
+ 0,0xCDFB,0xF6D6, 0,0xE7F5,0xE8EF,0xE3F9,0xD2BB,
+0xF3F3,0xE3FB, 0,0xDED0,0xCEB0, 0,0xD6F7,0xF1D9,
+ 0, 0, 0, 0, 0,0xF5C1,0xDCC4, 0,
+0xF5BB, 0,0xDED1, 0, 0, 0, 0, 0,
+ 0,0xDCE6, 0, 0,0xDED2, 0, 0,0xEDE2,
+0xEEF6,0xEACF,0xF0EE,0xE3FC, 0,0xD3DF,0xD3F4,0xE1B3,
+ 0,0xE1B4, 0, 0, 0, 0,0xF4D3, 0,
+ 0,0xDFC6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE9D6, 0, 0, 0,
+0xDBAB, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF6A6, 0, 0, 0, 0, 0, 0,
+0xE3B9,0xEBC5,0xF4A9,0xCDB6,0xD2F9, 0,0xDAAD,0xD2E3,
+0xCFD1, 0, 0, 0, 0,0xCBDC,0xCCFA, 0,
+0xCFDD, 0, 0,0xE8A9, 0,0xE3BB,0xE3BA, 0,
+ 0,0xE0DA, 0, 0, 0,0xEEF7, 0, 0,
+ 0, 0, 0,0xDCB3, 0, 0, 0, 0,
+0xD3F5, 0,0xD7A6, 0,0xF6B5,0xD7DB, 0, 0,
+ 0, 0, 0, 0,0xE1D5, 0, 0,0xD4EA,
+ 0,0xDFA3, 0, 0, 0, 0, 0, 0,
+ 0,0xFDDF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD0F7,0xEDD4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCBAA, 0, 0, 0, 0, 0, 0,
+ 0,0xE4DB, 0,0xE1FB,0xCBA2, 0, 0, 0,
+ 0,0xD3E0, 0,0xE4BF, 0,0xFBC0, 0,0xDABE,
+0xE4CD, 0,0xD6B9, 0, 0, 0,0xEFC0, 0,
+0xE1FC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF6B9, 0, 0, 0, 0, 0, 0,
+0xDFC7, 0, 0, 0, 0, 0, 0, 0,
+0xE4B1, 0, 0, 0, 0, 0, 0,0xDCE7,
+0xDCE8, 0, 0, 0,0xFAD6, 0,0xD3F6, 0,
+ 0, 0, 0,0xF1DA, 0,0xFAF2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE2FD,
+ 0, 0, 0, 0, 0,0xD5CF,0xD0F8, 0,
+ 0,0xCDDF, 0, 0,0xF5CB, 0,0xE4F0,0xCBAB,
+ 0,0xD7C4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE2FE,
+ 0,0xDDDA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xDAAE,0xCAEE, 0, 0, 0,
+0xD5B9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE3A1, 0, 0,0xE8E3, 0, 0,0xF3AB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCFA9,
+ 0, 0, 0,0xD3F7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD4F1, 0, 0,
+0xCEE4, 0,0xE8F2, 0, 0, 0, 0, 0,
+ 0, 0,0xE5F5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE7AE, 0,0xD6BA, 0,0xDFEC,0xE4C0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE8E4, 0, 0,
+ 0, 0,0xD8B5, 0, 0, 0,0xE4DC, 0,
+ 0, 0, 0, 0, 0,0xF4B9,0xF1B6, 0,
+ 0,0xE2DE,0xE1B5, 0, 0,0xCDEF,0xF1A7,0xCEE5,
+0xCBDD, 0, 0,0xD9E3, 0, 0,0xF3AC, 0,
+ 0,0xD0F9,0xECAB,0xDED3,0xF7E9, 0, 0,0xF9F5,
+ 0, 0, 0, 0, 0,0xE1DE,0xCBEE, 0,
+ 0, 0,0xE3BC,0xF8D6, 0, 0,0xDBEE, 0,
+ 0, 0, 0, 0,0xFDF1, 0, 0, 0,
+ 0,0xF7B6, 0, 0, 0, 0,0xF4DE, 0,
+ 0,0xF2ED, 0,0xDBD9, 0,0xF0A8, 0, 0,
+ 0, 0, 0, 0, 0,0xE1FD, 0, 0,
+ 0, 0, 0,0xDED4, 0,0xE0AC, 0, 0,
+ 0, 0, 0,0xEDE3, 0, 0,0xD3E1, 0,
+0xDFC8, 0, 0, 0, 0,0xD9B6, 0,0xFDAC,
+0xEFD3, 0, 0, 0,0xE4C1,0xF8EB, 0,0xDBAC,
+ 0, 0, 0, 0,0xFCC6, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD8AD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF6BA,
+ 0,0xDBDF,0xD3D3,0xF8C7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xCACE,0xF8C1,0xD2B4, 0, 0,0xDCB4,
+0xFAB9,0xCACF, 0,0xFCB3,0xEAEA,0xEAEB,0xD0FA, 0,
+ 0, 0, 0, 0,0xEDE4, 0, 0,0xDDE7,
+ 0, 0,0xDFC9, 0, 0, 0, 0,0xDFED,
+ 0, 0, 0, 0, 0,0xEEBC, 0,0xEFC1,
+ 0, 0,0xCCD2, 0,0xDDA4, 0, 0, 0,
+0xDFCA, 0, 0, 0, 0, 0,0xD3F8,0xF1A8,
+ 0, 0, 0,0xCDB7, 0,0xEFD4, 0, 0,
+ 0, 0, 0, 0, 0,0xE4DD,0xDFEE,0xCBAC,
+0xE9BC, 0, 0, 0, 0, 0,0xEAEC, 0,
+ 0, 0,0xDFCB, 0, 0, 0, 0, 0,
+0xF9BF,0xD6AF,0xD5C6, 0, 0, 0, 0, 0,
+0xCFAA, 0, 0,0xCEA9, 0, 0,0xD6F8, 0,
+ 0, 0,0xF1B7,0xEEF8, 0, 0, 0,0xD9D9,
+0xF3DF, 0,0xF8C8,0xCEC6, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD5E6, 0, 0, 0,
+ 0, 0, 0,0xF4E6, 0, 0,0xE6C5,0xEFD5,
+ 0, 0,0xCBEF,0xFCDF, 0, 0, 0, 0,
+ 0,0xDCA7, 0, 0,0xD6E7, 0, 0, 0,
+ 0, 0,0xF8C9, 0, 0, 0, 0,0xE3D2,
+ 0,0xE3BD, 0,0xCFE1,0xF0C0,0xECDA, 0,0xDDD7,
+0xFBF0, 0, 0,0xECAC, 0, 0, 0,0xF0A9,
+ 0, 0, 0, 0, 0, 0,0xFAD7,0xFBC1,
+ 0,0xD2C0, 0, 0, 0, 0, 0, 0,
+ 0,0xE5B0, 0, 0, 0,0xEDE5, 0, 0,
+ 0, 0,0xCBAD, 0,0xF9B0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF7A5, 0,0xCBAE, 0,0xDAAF, 0,0xD8B6, 0,
+ 0, 0, 0, 0, 0, 0,0xD3A7,0xFBB2,
+ 0,0xFDC4, 0,0xECAD, 0, 0, 0, 0,
+ 0, 0,0xFBA1, 0, 0, 0,0xE5E9,0xE9EE,
+ 0,0xF3F4,0xF8F3,0xF0C1,0xDEAF,0xF8B0, 0, 0,
+0xF3E0,0xE7AF, 0, 0, 0, 0, 0,0xDBAD,
+ 0,0xE6B5, 0, 0,0xF9A8, 0, 0,0xDDD8,
+0xE8D9,0xEFD6, 0, 0, 0,0xD3E2, 0,0xE2DF,
+ 0, 0,0xFCE0,0xD7C8,0xFDAD, 0, 0, 0,
+0xDFEF,0xCCD3,0xD3F9, 0, 0, 0, 0,0xD4F0,
+0xDBC7,0xDED5, 0, 0, 0, 0,0xF0F4, 0,
+0xD5D0,0xE5D9, 0, 0, 0, 0, 0, 0,
+0xFCC7,0xDCD6,0xE2E0, 0, 0, 0,0xDAB0, 0,
+ 0, 0, 0, 0, 0,0xF3A3, 0,0xD3EC,
+ 0,0xF4CB, 0, 0, 0,0xFDC5, 0, 0,
+ 0, 0, 0,0xE3FD, 0,0xF9B1, 0, 0,
+ 0, 0, 0, 0,0xD0FB,0xECDB, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF5BC,0xF2A4,
+0xD8CE,0xD8CF, 0, 0, 0, 0, 0, 0,
+0xF5F7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF6E1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD2B7, 0, 0,
+ 0, 0, 0, 0, 0,0xFBEC, 0,0xDDC8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4E8,
+ 0, 0,0xD2C1, 0, 0, 0,0xF8D7, 0,
+ 0, 0, 0, 0,0xD6BB,0xDED6, 0, 0,
+0xF7BD,0xECAE, 0, 0, 0,0xD0E1, 0,0xE0F5,
+0xEAB3, 0,0xCED6, 0, 0, 0, 0,0xCCA5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xECF6,0xE2E1,0xE3BE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFCC8, 0, 0,
+0xCDF0, 0,0xF9F6, 0, 0,0xDFF0, 0, 0,
+ 0,0xE5BF, 0, 0, 0,0xCEBF, 0, 0,
+ 0, 0,0xFCE1,0xEDB0,0xFDD1,0xF6BB, 0, 0,
+0xF9CF,0xEBDA,0xCAC1, 0,0xD2B8,0xCDF1, 0,0xE3D3,
+0xFDE6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE6ED, 0, 0,
+ 0,0xE3FA, 0, 0,0xF0AA,0xF9D0, 0, 0,
+ 0, 0, 0, 0,0xFCE2, 0,0xF8A7, 0,
+ 0, 0,0xE1E5,0xEEF9, 0, 0, 0,0xE7F6,
+0xEAED, 0, 0,0xFCB4,0xF5C2, 0, 0,0xD7DC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF0F5, 0,0xDDE8,0xD3ED,0xF5FC, 0,0xDABF, 0,
+0xCCFB, 0, 0, 0,0xD3FA,0xF4A4, 0, 0,
+ 0, 0, 0, 0, 0,0xEFD7, 0,0xD4C3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFBE3, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFBED, 0,0xE0AD, 0, 0,0xEAEE,
+0xFBB3,0xE4C2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF6E7,0xD2DD, 0,0xDFCC, 0, 0,0xFCC9, 0,
+ 0,0xE5A9,0xE0F6,0xF6B3, 0, 0, 0, 0,
+ 0,0xE1FE, 0, 0, 0, 0,0xCBF0, 0,
+0xEAEF,0xEAF0, 0, 0, 0,0xDAC0,0xF8B4,0xEBF2,
+ 0, 0, 0, 0, 0,0xE4C3, 0, 0,
+ 0, 0,0xE9D7,0xE4F1, 0, 0, 0,0xCAEF,
+ 0, 0, 0, 0, 0, 0, 0,0xCED7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFCCA, 0, 0, 0,0xF3E1, 0, 0,0xCBC4,
+ 0, 0, 0, 0,0xE3E5, 0,0xCBC5,0xEAB4,
+ 0, 0,0xE9BD, 0,0xD7C9, 0, 0,0xEBDB,
+0xEDB1, 0,0xCCC3,0xF7BE,0xFCCB, 0, 0, 0,
+ 0, 0, 0,0xF8F4, 0,0xD9B7, 0, 0,
+0xF3D3,0xF3D4, 0, 0, 0,0xF7E4, 0,0xF7D1,
+ 0, 0,0xD8B7,0xCEB1,0xCAC2, 0, 0,0xFBB4,
+0xCBC6, 0, 0,0xF0F6, 0, 0,0xD5E7, 0,
+0xEAD0, 0, 0, 0, 0, 0,0xCCD4,0xCBAF,
+ 0, 0, 0, 0, 0,0xF4AA,0xE9AF, 0,
+ 0,0xF5C3,0xE9D8, 0, 0, 0, 0, 0,
+ 0, 0,0xDDE9, 0, 0, 0,0xF1F3, 0,
+0xD5FB,0xDEBB, 0, 0,0xF4FB, 0, 0, 0,
+0xFDF3,0xFDF2,0xF7A6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDDC9, 0, 0,0xD4D3,
+ 0,0xCCA8, 0,0xDAC1,0xCCD5, 0,0xD9E4, 0,
+ 0, 0,0xFACA, 0, 0, 0,0xE5E3, 0,
+ 0, 0,0xD3BC, 0, 0, 0,0xCAF0, 0,
+ 0, 0, 0,0xD0C4, 0, 0, 0,0xCAD0,
+0xFAAB,0xEBEB,0xE7F8,0xD9E5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD1D7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF3A4, 0, 0, 0,0xD4FB,0xFCE3,
+0xFAD8, 0,0xF3D5, 0,0xCFAB, 0, 0,0xEBF3,
+0xD5FC, 0, 0, 0, 0, 0, 0,0xD3D4,
+0xCDFC, 0,0xD9E6, 0,0xE2F9,0xE2A1,0xEBD4, 0,
+0xE0F7,0xE4B2,0xCCFC, 0, 0, 0,0xFBE4, 0,
+ 0, 0,0xF4AB, 0, 0, 0, 0,0xD0BD,
+ 0,0xCAF1, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEFB8, 0, 0, 0,0xD7C0, 0,
+0xEEFA,0xFDF4, 0, 0,0xD3E3, 0,0xFBC2, 0,
+ 0, 0, 0, 0, 0, 0,0xD5E8,0xDBAE,
+0xE1B6,0xF8B7, 0, 0, 0, 0, 0,0xE0BF,
+0xFBC3,0xDDEA, 0,0xE2A2, 0,0xEEA6, 0, 0,
+ 0, 0, 0,0xF6E8, 0, 0, 0, 0,
+0xF6F5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDDCA, 0,
+ 0,0xD0E2, 0, 0, 0, 0,0xDDA6, 0,
+ 0,0xDDEB, 0, 0,0xE4F9, 0, 0,0xE3AF,
+0xD0FC, 0, 0, 0,0xF4FC, 0, 0, 0,
+ 0,0xCCBC,0xF7EA, 0, 0, 0, 0, 0,
+ 0,0xE5E4,0xDFF1, 0, 0,0xF7E1, 0,0xF9F7,
+0xEFB9, 0, 0,0xF8D8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF9A9, 0, 0, 0, 0,
+ 0,0xF8D9, 0, 0, 0,0xEEBD, 0, 0,
+ 0,0xD8C6, 0, 0,0xE4E3,0xF5CE, 0, 0,
+ 0, 0,0xDDD9, 0, 0, 0, 0,0xD9E7,
+0xD2B9,0xD5C3, 0, 0,0xDAE5,0xDAD0, 0,0xD1D9,
+0xCED8, 0,0xCBDE,0xF4AC,0xDAFB, 0,0xF6E9,0xE8F3,
+0xCFAC,0xF0F0, 0,0xF4FD,0xDBC8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCEC0,0xE3D4,0xD1CF,0xF1F5,
+ 0,0xCDF2, 0,0xCFEB, 0, 0, 0,0xCDB8,
+ 0, 0, 0, 0, 0, 0,0xE3A6,0xD1DA,
+ 0,0xF2A5, 0, 0, 0, 0, 0,0xF2A6,
+ 0,0xE4CE, 0, 0, 0, 0, 0, 0,
+ 0,0xD3FB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF1A9, 0, 0, 0,0xF2C9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEFD8,0xE6C9, 0,0xD8B8,0xFAF3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF3B5, 0, 0,0xF8A4, 0, 0,0xD1F3,
+0xE6C8, 0, 0, 0, 0,0xF8DA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDCE9,
+0xDED7, 0, 0, 0, 0, 0,0xCBDF, 0,
+ 0, 0,0xCFEC, 0, 0, 0, 0,0xF4DF,
+ 0, 0,0xD1F4,0xD2BA, 0, 0, 0,0xDFF2,
+ 0, 0, 0,0xE1B7, 0, 0, 0, 0,
+0xE2A3,0xD3FC, 0, 0,0xEDE6, 0, 0, 0,
+ 0, 0,0xDBC9, 0, 0, 0,0xE4FA, 0,
+0xCFDE, 0, 0,0xCED0, 0, 0, 0, 0,
+0xD5D3,0xF3F5,0xF7AE, 0, 0,0xEFC8, 0,0xCDF3,
+0xF5CF,0xE5F3,0xF0C2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCAD1, 0, 0, 0,0xEAF1, 0,0xD0A6, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9DA,
+0xF0AB, 0, 0, 0, 0, 0,0xEBE7, 0,
+ 0, 0,0xE5C0,0xFCB5, 0, 0, 0, 0,
+ 0,0xE4C4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCCA9,0xFDC6, 0,
+ 0, 0, 0, 0,0xEAB5, 0,0xE5AA,0xDFBA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE1DF, 0,0xDAD1,
+ 0, 0, 0, 0,0xE1B8, 0,0xE8F4,0xD3FD,
+ 0, 0, 0, 0,0xE2A4, 0, 0, 0,
+ 0, 0,0xF2CA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDAE6,0xF7B3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFDCD, 0, 0, 0,0xF3B6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEED7, 0, 0, 0, 0, 0, 0, 0,
+0xF5C4, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD8A4, 0, 0, 0, 0, 0,0xF2A7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD9B8,0xD9B9,0xEFC9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD6CE, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF7CB,0xDFAE,0xE8F5, 0, 0, 0, 0,
+ 0, 0,0xD2B5, 0, 0, 0,0xD3D5, 0,
+ 0, 0, 0, 0,0xF4CC,0xDAFC, 0, 0,
+ 0, 0, 0,0xD9E8, 0,0xF7EB,0xF5C9, 0,
+0xF3BC, 0,0xDAD2, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD3B5, 0, 0, 0, 0,
+ 0,0xE8B6, 0, 0,0xD6CF,0xF4BA, 0,0xF7C9,
+ 0, 0,0xCCAA, 0, 0,0xF0C3,0xCCD6, 0,
+ 0, 0,0xD0D3, 0,0xD3BD, 0, 0, 0,
+0xDBFB, 0,0xCBE0, 0, 0, 0, 0, 0,
+ 0,0xD3E4,0xF6F7, 0, 0,0xD5BA,0xF3CD,0xCBE1,
+ 0, 0, 0, 0,0xEBF4, 0, 0, 0,
+ 0, 0,0xF4AD, 0,0xFCAA, 0, 0, 0,
+ 0, 0,0xF7EC, 0, 0, 0,0xE8F6, 0,
+0xDAE7, 0, 0, 0,0xF7CC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE5C1, 0, 0, 0, 0,0xE0EE, 0, 0,
+ 0, 0, 0,0xD5FD, 0, 0, 0, 0,
+ 0, 0,0xCEE6,0xFCAB,0xD5BB, 0, 0,0xF2A8,
+ 0, 0, 0, 0, 0, 0,0xE2A5,0xCDB9,
+0xEAF2,0xCBC7, 0,0xCDF4, 0, 0,0xDBAF,0xEFD9,
+ 0, 0, 0, 0, 0,0xCDBA, 0, 0,
+0xFCF9, 0, 0, 0, 0,0xDFF3,0xCEE7,0xDAC2,
+ 0,0xCFAD, 0, 0, 0, 0,0xE7F9,0xF8A8,
+ 0, 0, 0, 0, 0, 0,0xF3E2, 0,
+ 0, 0,0xCAF2,0xDFA4, 0, 0,0xD4C4, 0,
+ 0, 0, 0, 0,0xCCD7,0xE5C2, 0, 0,
+ 0, 0,0xCDBB, 0,0xEFDA,0xEED8, 0,0xDDA7,
+0xE2A6, 0, 0, 0, 0, 0,0xE0C0, 0,
+ 0, 0,0xD6B0,0xF8CA, 0,0xFCFA, 0,0xD9FE,
+ 0, 0, 0, 0,0xDEB0, 0, 0, 0,
+0xDDEC,0xDAE8, 0, 0, 0, 0, 0,0xD4E0,
+ 0,0xD6F9, 0,0xCDD7,0xDED8, 0, 0,0xF2F8,
+ 0,0xE4D6, 0, 0,0xD0C5,0xF4AE, 0,0xDDA8,
+ 0, 0, 0,0xEDC5,0xF3D6, 0, 0,0xDED9,
+0xE3E6, 0, 0, 0, 0, 0, 0,0xD3A8,
+ 0,0xDBB0, 0, 0,0xE5DA,0xE3BF, 0, 0,
+ 0,0xDBB1, 0, 0, 0,0xD5E9, 0, 0,
+ 0, 0, 0,0xE0C1,0xEFDB, 0, 0,0xF0E9,
+ 0, 0,0xD7B2, 0, 0, 0, 0,0xD0FD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD9E9, 0, 0,0xD0FE, 0,0xECED,0xD3A9, 0,
+0xF2A9,0xF0C4, 0, 0,0xE2E2,0xE9EF, 0, 0,
+ 0,0xF9D1, 0, 0,0xE9D9, 0, 0, 0,
+ 0, 0,0xE8DA,0xDAC3,0xDAC4,0xD4C5, 0,0xE7FA,
+ 0, 0, 0, 0, 0, 0,0xCDE0,0xE3B0,
+ 0,0xDBB2,0xFBC4, 0,0xF3E3, 0,0xD9A5,0xFBE7,
+0xDDCB,0xD0D4, 0,0xE6B6,0xE0AE,0xFDDA, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDCB5,0xE0F8,
+0xE7B1, 0, 0, 0, 0,0xF5F0, 0,0xD8DC,
+0xEDC6, 0, 0, 0, 0,0xE1B9, 0,0xE3C0,
+0xF9C0,0xE9F0, 0, 0,0xD9DB, 0,0xF3E4, 0,
+ 0, 0,0xDCB6,0xE4E9, 0, 0, 0, 0,
+ 0,0xF0C5,0xE3C1,0xFCCC,0xFCCD, 0, 0, 0,
+ 0,0xF2CB, 0,0xF2CC, 0, 0, 0,0xE4CF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF1DB, 0,0xFAD9, 0,0xF1B8,0xFDF5,0xE0F9,
+ 0, 0, 0, 0,0xE7FB,0xFCB7,0xFCE4,0xFBC5,
+0xE3E7,0xD8B9, 0,0xF6F8, 0, 0,0xDCC5,0xCCD8,
+ 0, 0, 0,0xE0AF,0xF4E7, 0,0xEFDC,0xCFFC,
+0xEFDD, 0,0xF2AA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFDBE, 0, 0,0xCAAC,
+0xFDBB,0xFDC7, 0, 0, 0, 0,0xE7B2, 0,
+0xEAD1,0xDFF4, 0, 0, 0, 0,0xD1EC,0xE4DE,
+0xE5C3, 0, 0, 0, 0,0xD9A6, 0, 0,
+0xCDBC, 0,0xF3E5, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEDD5, 0, 0,0xD9BA, 0,
+ 0, 0,0xEDE7,0xFBB5,0xF8EC, 0, 0, 0,
+ 0,0xE0E7, 0,0xCCD9, 0, 0,0xD4C6, 0,
+ 0, 0, 0, 0,0xE7A5, 0,0xD5F5,0xD3BE,
+ 0,0xFCFB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE4F2, 0,
+ 0,0xDFF5, 0, 0,0xE8F8,0xF8ED, 0, 0,
+0xCEC7, 0, 0, 0, 0, 0,0xFDF6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE8D8, 0,0xCDD8,0xE7D6,0xCCDA, 0, 0,0xCAE3,
+0xDFF6,0xF0C7,0xF0C6, 0,0xD8BA, 0,0xF1F4,0xF4F0,
+0xF5CC, 0, 0,0xFCE5, 0, 0, 0, 0,
+0xEAC5,0xEAF3, 0,0xDDDB, 0,0xDCD7, 0, 0,
+ 0, 0, 0, 0,0xDEFD,0xF2F9, 0,0xD5C7,
+ 0, 0, 0,0xD8D0, 0,0xF0C8,0xD1A1,0xD1A2,
+ 0, 0, 0, 0, 0, 0,0xD9D4,0xD6E8,
+0xD9CA, 0,0xDAB1,0xD8C7,0xDCE2,0xF3CE,0xF5F4, 0,
+ 0,0xF1B9, 0, 0,0xDAD3, 0,0xF6EA, 0,
+ 0, 0,0xCFF5, 0, 0,0xFDAE, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCAD2, 0,
+ 0,0xDFB4, 0, 0, 0, 0,0xD7DD,0xFABA,
+0xEEA7,0xF5BD, 0,0xF8F5, 0, 0,0xEDE8, 0,
+ 0, 0, 0, 0,0xD4E1, 0,0xD1A3,0xE1D6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF9F8, 0,0xDBCA,
+0xCBF9,0xD4D4, 0,0xD9DC, 0,0xEEBE, 0,0xF7ED,
+ 0, 0, 0,0xD2EE, 0, 0,0xE1E6,0xF7F9,
+ 0, 0, 0, 0, 0, 0, 0,0xDDED,
+ 0,0xE8DB, 0,0xDBB3, 0, 0, 0,0xD1F7,
+0xE0B0, 0, 0,0xD4E2, 0,0xF6D7, 0,0xD7F9,
+ 0, 0,0xD8DD, 0,0xCDFD,0xF2AB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCDBD,
+0xF8C2, 0, 0,0xF2AC, 0, 0,0xCAAD,0xCAAE,
+0xCFAE, 0, 0, 0, 0, 0,0xE3C2, 0,
+ 0, 0, 0, 0,0xDCB7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDBDA,
+0xD9BB,0xCAF3,0xF6D3,0xE6F8,0xEAF5, 0, 0, 0,
+ 0, 0,0xEAF6, 0, 0,0xF6F9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCFAF, 0, 0,0xCAD3, 0, 0,0xCAAF,
+0xD2B0,0xF1BA, 0,0xD7B3,0xE3C3,0xF3FD,0xDEDA, 0,
+ 0, 0, 0,0xDEDB, 0, 0,0xEFDE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE2E3,0xEEFB, 0, 0,0xDFF7,0xD7CA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCEE8,0xDBDB, 0, 0, 0, 0, 0,
+ 0, 0,0xF1BB, 0, 0, 0, 0,0xE9F1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFAB7,0xD0C6, 0, 0,0xCCAB,0xEEA8, 0, 0,
+0xCBFA,0xF9F9,0xCCFD,0xD3FE, 0, 0, 0, 0,
+0xE4D0, 0, 0, 0, 0, 0,0xF2EE, 0,
+0xD4D5,0xDFCD, 0,0xFCB8,0xD1D0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF2CD, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF7D2, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCAD4,
+ 0,0xD5D9, 0, 0, 0,0xD8DE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCDD9,
+ 0, 0, 0,0xEEA9,0xF6BC, 0, 0,0xCCDB,
+ 0, 0, 0, 0, 0,0xF0C9, 0,0xFCFC,
+ 0,0xE8C9,0xF4FE, 0, 0, 0, 0,0xE7FC,
+0xD7DE, 0, 0, 0, 0,0xDEDC, 0,0xF0AC,
+0xCCFE,0xCDE1, 0,0xE1BA, 0,0xDBEF,0xDAB2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD1A5,0xDCB8, 0, 0,
+ 0,0xD8F6, 0,0xD1A4, 0,0xCDE2, 0, 0,
+ 0, 0,0xDCEA, 0, 0,0xF0F7, 0,0xF0CA,
+0xD0BE, 0,0xDDDC, 0, 0, 0, 0,0xD4D6,
+0xD3D6, 0, 0, 0, 0, 0, 0,0xEDD0,
+0xCDA1, 0, 0, 0, 0, 0,0xDFB5, 0,
+ 0, 0,0xDFF8, 0, 0, 0, 0, 0,
+ 0,0xD4A1,0xCEB2, 0, 0, 0, 0, 0,
+0xE8CA, 0, 0, 0, 0,0xEBF5, 0, 0,
+ 0, 0, 0, 0, 0,0xE3D5,0xF5D0, 0,
+ 0, 0,0xF5A1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9A7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE5AB, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE6CB, 0,0xF5F1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE5C5, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF9A3,0xE0DB,0xF6EB, 0,0xCBF1,
+ 0,0xD9EA,0xF5A2, 0, 0, 0,0xD7D1, 0,
+0xD1F8,0xEAF8,0xEAF9,0xDAB3, 0, 0, 0, 0,
+0xEFDF, 0, 0,0xF1EF, 0,0xE5F6,0xEEBF,0xE2E4,
+ 0, 0, 0, 0, 0,0xD0BF, 0,0xFAAC,
+0xF5D1,0xE7B3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE9BE, 0, 0,
+ 0, 0, 0,0xF2CE,0xDBB4, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFCCE, 0,0xDDEE,
+ 0, 0, 0, 0, 0, 0,0xE7B4, 0,
+ 0, 0, 0, 0,0xD7B4, 0, 0, 0,
+ 0, 0, 0,0xF7B4, 0, 0, 0, 0,
+ 0,0xCDBE, 0,0xDAE9, 0, 0, 0, 0,
+ 0, 0, 0,0xCFB0,0xF7D9,0xF3E6, 0, 0,
+0xCED9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCEAA, 0,0xCBC8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0A7, 0,0xF0CB, 0,0xD0C7,
+ 0, 0,0xE4C5, 0, 0, 0, 0, 0,
+ 0, 0,0xDBE0, 0, 0, 0, 0, 0,
+ 0,0xD5DA, 0,0xD7A7, 0, 0, 0,0xEEC0,
+ 0,0xF8F6, 0, 0, 0, 0,0xF5D2,0xEDE9,
+ 0,0xD9BC, 0,0xE5C6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF5A3, 0, 0,
+0xDAD4,0xE2A7,0xFBFC, 0, 0,0xF1DC, 0, 0,
+ 0, 0, 0, 0,0xCAF4, 0, 0, 0,
+0xE8FA, 0, 0,0xCEE9, 0, 0, 0, 0,
+ 0, 0,0xE9F8,0xE2E5, 0, 0, 0, 0,
+0xD0B9,0xD4F2, 0, 0, 0, 0, 0,0xD1A6,
+ 0,0xDFCE, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFCF4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD3AA, 0, 0, 0,0xCCAC, 0, 0, 0,
+ 0,0xEFE0, 0, 0, 0,0xE5E5,0xD0D5, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDBFC,
+ 0, 0, 0, 0,0xFCE6, 0, 0, 0,
+ 0, 0,0xCBFE,0xEDEA, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xDEB1, 0, 0, 0, 0,
+ 0, 0, 0,0xF9E3, 0, 0, 0, 0,
+ 0, 0,0xD4A2,0xCFF6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD6D0, 0, 0, 0, 0,
+ 0, 0,0xD5EA,0xF1EE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFACB, 0,
+ 0, 0, 0,0xE5A1, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD5B1, 0, 0, 0,
+ 0, 0,0xCFED, 0,0xEDEB, 0, 0, 0,
+ 0, 0,0xD5B2, 0, 0, 0,0xD5BC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFDE2,0xF3AD, 0,0xFDDB, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE9B0, 0, 0, 0, 0, 0,
+ 0, 0,0xD1A7, 0, 0,0xFDE3,0xCEB3, 0,
+ 0, 0, 0, 0, 0, 0,0xFDE4,0xFACE,
+ 0, 0, 0, 0,0xCAB0, 0,0xF7A7, 0,
+0xCFB1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE6A2,
+ 0,0xFCB6,0xF2AD,0xEFE1,0xF3AE,0xDCC6,0xD9EB, 0,
+ 0, 0,0xE8E0, 0, 0, 0, 0, 0,
+ 0, 0,0xE1A8, 0, 0, 0, 0,0xD5F6,
+0xCFFD, 0, 0,0xDEDD, 0, 0, 0,0xD9D1,
+ 0, 0, 0,0xE4EA,0xF2CF, 0,0xF7BF, 0,
+ 0,0xE2E6,0xE2A8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE3D6, 0,
+0xEDD1, 0, 0, 0, 0, 0,0xE9F9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD6B1,0xDEB2,
+ 0, 0,0xE0E8, 0, 0,0xD3AB, 0,0xEBDC,
+ 0, 0,0xDFAF, 0,0xCAC3, 0, 0,0xEEFC,
+ 0,0xFDC3, 0, 0, 0,0xEBF6,0xCFB2, 0,
+ 0, 0, 0,0xD9EC, 0,0xD9BD, 0,0xD8DF,
+ 0, 0,0xD4B8,0xEBBE,0xDDEF, 0,0xDDF0,0xDDF1,
+0xDDF2, 0, 0,0xD9BE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFBC6,0xCFB3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEEFD, 0, 0, 0, 0, 0, 0,0xE4AB,
+ 0,0xDAC5, 0,0xD8EC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD1A8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE2A9, 0, 0,0xDEBC,
+0xE7B5, 0, 0, 0, 0, 0,0xDBF0, 0,
+0xEFE2,0xF1F0,0xCFB4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDBF1, 0,
+0xE0B1, 0, 0, 0, 0,0xDFA5, 0,0xF9D2,
+ 0, 0,0xE7FD, 0, 0,0xE6A3,0xFBF1,0xCBB0,
+0xF2AE, 0, 0, 0, 0, 0, 0, 0,
+0xCDE7, 0,0xE8DC, 0, 0,0xE7D7, 0, 0,
+0xF7C0, 0,0xD0E3, 0, 0, 0,0xDAA1, 0,
+ 0, 0,0xCCBD, 0, 0,0xD1A9,0xDDCC, 0,
+ 0,0xE3FE,0xD1AA,0xE8AA, 0,0xEAB6,0xF9FA,0xE6CC,
+0xF6D8, 0, 0, 0,0xD4C7, 0, 0, 0,
+0xD9CB, 0,0xD9D2,0xD3CB,0xD8F7,0xDAA9,0xF5F8, 0,
+ 0,0xDEDE,0xF2AF,0xF8A9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD8C8, 0, 0,0xEEC1, 0,
+ 0, 0, 0,0xF9C1, 0, 0, 0, 0,
+0xDDF3,0xEAFA, 0,0xF6BD,0xE1BB,0xCDBF,0xF4D4,0xE6CD,
+ 0,0xFCCF,0xFBA2, 0,0xE0DC, 0, 0, 0,
+ 0,0xF4BB,0xDAD5, 0,0xF9B2, 0, 0, 0,
+ 0, 0, 0,0xFBF2, 0,0xDBF6, 0,0xDEDF,
+ 0, 0, 0,0xDBF2, 0, 0, 0, 0,
+ 0,0xF8DC,0xF7EE,0xEBE8, 0,0xD2FA, 0, 0,
+0xF1BC, 0, 0,0xFADA, 0, 0,0xDAEA,0xDAC6,
+0xF7C1, 0, 0,0xE7B6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE5C7,0xD6AC, 0, 0, 0,
+ 0,0xDCC7, 0, 0, 0, 0, 0,0xE1A9,
+ 0,0xE2AA, 0,0xD5A6, 0, 0,0xD4D7, 0,
+ 0, 0, 0, 0, 0,0xF2D0, 0,0xEAFB,
+ 0,0xE0DD,0xFBF3, 0, 0, 0, 0, 0,
+ 0, 0,0xF1BD, 0, 0,0xE2E7,0xFDD7, 0,
+0xCEC8,0xEAB7, 0,0xFCC0, 0,0xFDE7,0xF7EF, 0,
+ 0,0xD7B5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEFBA,0xF1DD, 0,0xDEB3, 0, 0, 0,
+ 0, 0, 0,0xE8CB, 0, 0,0xF8DD, 0,
+ 0,0xFBC7,0xD5C8, 0,0xD7DF, 0,0xDDA9, 0,
+ 0, 0, 0, 0,0xE9B1, 0, 0,0xFAAD,
+0xF6D9,0xFAF4, 0, 0, 0, 0, 0,0xF8AA,
+ 0, 0, 0, 0, 0,0xE6EE, 0,0xCCDC,
+0xE1BC,0xE0EF, 0, 0,0xE9BF,0xFCFD,0xE6CE, 0,
+ 0,0xE1D7, 0,0xE6CF, 0,0xF4F1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4F3,
+ 0, 0,0xE4FB, 0, 0,0xF9E4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEFE3, 0, 0,0xCFEE,0xF6BE,0xE0B2,0xFCFE,0xD1AB,
+ 0, 0, 0,0xD7FA, 0, 0, 0,0xFBC8,
+ 0,0xE2D7, 0, 0, 0, 0, 0, 0,
+0xD4A3,0xF0F8,0xD7A8, 0, 0, 0,0xE1E7, 0,
+ 0,0xD3BF, 0, 0, 0, 0, 0, 0,
+0xEFE4, 0,0xD7C5,0xEBE2, 0, 0,0xFCE7, 0,
+ 0,0xE4A2, 0,0xE2E8, 0,0xE6D0, 0,0xFBE8,
+0xF4E8,0xE5F4,0xF4BC,0xF4D5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDFB6,
+ 0,0xFCB9,0xEEC2,0xCAF5, 0, 0, 0,0xEFE5,
+0xCBE2,0xD4A4, 0,0xDEE0,0xDAFD,0xE4C6,0xE8BE, 0,
+ 0, 0, 0,0xE0DE,0xF6B4,0xEAD2, 0,0xF9FB,
+ 0, 0,0xE0C2, 0,0xCAE4, 0,0xE7B7, 0,
+0xEAFD, 0,0xD9DD, 0,0xDAB4,0xEEAA,0xFBE9, 0,
+ 0, 0, 0,0xDBCB,0xDAB5, 0, 0, 0,
+ 0, 0,0xF1BE, 0, 0,0xD3AC, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFBC9, 0,
+0xDFCF, 0, 0,0xD3C0,0xE3D7, 0,0xEFE6,0xFCD0,
+ 0, 0, 0, 0, 0, 0, 0,0xE9C0,
+ 0, 0, 0,0xF5D3, 0, 0,0xECDC,0xF7B7,
+ 0, 0,0xEAB8,0xD1F9, 0, 0, 0, 0,
+ 0, 0,0xDCC8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEAB9, 0, 0, 0, 0, 0,0xF1DE, 0,
+ 0, 0, 0, 0,0xD7B6,0xCFB5, 0,0xD9A8,
+ 0, 0,0xECEE, 0, 0,0xDDAA, 0, 0,
+ 0, 0,0xCDA2,0xE8AE, 0, 0, 0,0xE1BD,
+ 0,0xF2D1, 0, 0, 0, 0,0xE9C1, 0,
+ 0, 0,0xD2FC, 0, 0, 0, 0, 0,
+ 0, 0,0xDBB5, 0,0xF3E7,0xD8FE, 0, 0,
+ 0,0xFCD1, 0,0xEDB2,0xF4AF, 0,0xFBA3, 0,
+ 0,0xFCC1, 0,0xEEAB,0xD4A5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4F2,
+ 0, 0, 0, 0,0xEED9, 0, 0, 0,
+0xFBCA, 0, 0, 0, 0, 0,0xCDE3,0xD8BB,
+ 0,0xE5DB,0xF8F7, 0, 0, 0,0xF6D4, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD7A9,
+ 0,0xCBC9, 0, 0,0xE6D1,0xF0CC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD8AE, 0,0xF9D3,0xD5FE, 0, 0, 0, 0,
+ 0, 0, 0,0xD8BC,0xF2B0, 0, 0, 0,
+ 0,0xE2AB,0xF3E8, 0, 0, 0, 0, 0,
+0xEFC2, 0, 0, 0, 0, 0, 0,0xEDEC,
+ 0,0xE7B8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDAFE, 0, 0,0xCCBE, 0, 0,0xF2FC,
+0xDAEB, 0,0xE2D8,0xEDD6, 0, 0,0xD6D1,0xE0B3,
+ 0, 0,0xFCD2, 0,0xEBC8, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD3C1,0xF0CD, 0,
+0xCFF7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEDD2, 0,0xD4D8,0xDCC9,0xD7F1, 0,
+ 0,0xDFBB, 0, 0,0xF3A5, 0, 0, 0,
+0xF4CD, 0, 0, 0, 0,0xF1BF,0xF8B1, 0,
+0xE9FA, 0, 0, 0,0xFBCB, 0, 0,0xCAD5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF9D4,0xF7CA, 0, 0,0xD6C8,
+ 0, 0, 0, 0, 0, 0,0xFCE8,0xF3BD,
+ 0,0xEEFE, 0,0xE7FE, 0, 0, 0, 0,
+ 0,0xD3C2, 0, 0, 0, 0,0xD3B6, 0,
+0xCCAD,0xF6FA,0xD6B2,0xD2D8, 0, 0, 0, 0,
+ 0, 0,0xE7D8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE3A5, 0, 0,
+ 0, 0,0xE7B9, 0, 0, 0, 0,0xF0AD,
+0xFBCC,0xEBA1, 0, 0,0xD4A6, 0, 0, 0,
+ 0,0xFBCD, 0,0xD5BD,0xF1DF, 0, 0,0xF6FB,
+ 0,0xDEB4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD5EB, 0,
+ 0,0xE5C8, 0, 0, 0,0xFBA4,0xD4B9, 0,
+ 0,0xDEE1, 0,0xE4A3, 0, 0, 0,0xD7B7,
+ 0,0xF8EE, 0, 0, 0,0xDEB5, 0, 0,
+0xD6D2, 0,0xF9D5,0xE7BA,0xEBD5,0xD5F7,0xEFE7,0xE1BE,
+ 0, 0, 0,0xFAAE, 0, 0, 0,0xD6E9,
+0xD6EE, 0, 0, 0, 0, 0, 0,0xE7BB,
+ 0, 0, 0, 0, 0, 0, 0,0xECCB,
+ 0, 0, 0, 0, 0, 0,0xD5B3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCEB4, 0, 0, 0,
+0xFBA5,0xE1EE, 0, 0, 0, 0, 0, 0,
+0xF7A8, 0, 0, 0, 0,0xFBCE, 0, 0,
+ 0, 0, 0,0xD8BD, 0, 0, 0, 0,
+ 0, 0, 0,0xFBFD, 0, 0, 0, 0,
+0xFCE9, 0, 0, 0, 0, 0, 0, 0,
+0xCFB6, 0, 0, 0,0xEDC7,0xEEAC, 0, 0,
+ 0, 0, 0, 0, 0,0xCCDD, 0, 0,
+ 0, 0,0xF6A7, 0, 0, 0,0xE6FA, 0,
+ 0, 0,0xF5A4, 0, 0, 0, 0, 0,
+0xFDDC,0xEDB3,0xCEC9, 0, 0, 0, 0, 0,
+ 0,0xEFE8, 0, 0,0xE1BF, 0, 0, 0,
+ 0, 0, 0,0xFADB,0xCBE3,0xF7A9, 0,0xFBA6,
+ 0, 0, 0,0xDCB9, 0, 0, 0,0xF1C0,
+0xEDC8,0xEFC3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD6AD, 0, 0,0xFDCE, 0, 0, 0,0xE8A1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFBF4,0xD5A7, 0, 0, 0,0xF1F6, 0,0xE6D3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCCDE, 0, 0, 0, 0, 0, 0,
+ 0,0xF8B2, 0, 0, 0,0xDCEB, 0, 0,
+ 0, 0, 0, 0,0xFDB6, 0, 0, 0,
+ 0,0xE5EA, 0, 0,0xF1E0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDBCC,0xDDCD, 0, 0, 0,0xD4C8, 0,
+ 0,0xD9ED, 0, 0, 0, 0,0xF5A5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE6FB, 0, 0, 0, 0, 0,0xE6D4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xFDC8,
+ 0,0xD6A1,0xFDBF, 0,0xFCD3, 0,0xEFA1, 0,
+0xE7BC, 0, 0, 0, 0, 0,0xD1EE, 0,
+ 0,0xE6D5, 0, 0,0xE9F2, 0,0xDFB0, 0,
+ 0, 0, 0, 0,0xD8E0,0xFCBA,0xFDAF,0xF0CE,
+ 0,0xDBE1, 0, 0,0xE5C9, 0,0xEDB4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE0C3, 0, 0,
+ 0, 0, 0, 0,0xE3D8, 0, 0, 0,
+ 0,0xE9FB,0xEAA8, 0, 0, 0, 0,0xFDB7,
+ 0, 0,0xFBA7, 0,0xE9C2, 0, 0, 0,
+ 0,0xFDF7, 0, 0, 0, 0, 0,0xE2D9,
+ 0, 0,0xDCEC, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE8A2, 0, 0, 0,
+ 0,0xE6F0, 0, 0, 0, 0, 0, 0,
+ 0,0xFDF8,0xFDF9, 0, 0, 0,0xF6BF, 0,
+ 0,0xE7A7, 0,0xE6D7, 0, 0, 0, 0,
+0xD4F3,0xD4C9, 0, 0, 0, 0,0xD6FA, 0,
+0xD7F2, 0,0xE1C0, 0,0xDBE2,0xE6D8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE7BD,
+ 0, 0, 0, 0, 0,0xF0CF,0xF3BE,0xE2AC,
+ 0, 0, 0, 0, 0,0xF5B7,0xE0F0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFDB8,0xE3E8, 0,0xD4A7,0xE8FC,
+0xFAD2, 0, 0, 0, 0, 0,0xF8EF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD6D3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD5B4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF0D0, 0,0xF7F0,0xEEB3, 0, 0,
+0xEABA, 0,0xEAD3, 0, 0,0xEDC9,0xDDAB, 0,
+ 0, 0,0xE5AC,0xFDA1, 0,0xDFD0,0xECB3, 0,
+0xDFD1, 0, 0, 0, 0, 0,0xEDED,0xF8B8,
+0xF7FA, 0, 0, 0,0xF8AB, 0, 0, 0,
+ 0, 0,0xF4E0, 0, 0, 0, 0, 0,
+0xD4BA,0xE4B3, 0,0xE9DA, 0,0xDEB6, 0,0xD9BF,
+ 0,0xD9C0,0xD6EF, 0, 0, 0, 0,0xD9CC,
+ 0,0xDAAA, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDFE5, 0, 0, 0, 0, 0,
+ 0,0xF7E5, 0, 0, 0,0xCCB2, 0, 0,
+0xDFF9,0xD7E0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD4BB, 0, 0, 0, 0,0xFDFA,
+ 0, 0, 0, 0,0xCCB3, 0, 0,0xDBF3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xDFD2, 0,0xCECA, 0,0xEEDA, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE4E4, 0,
+0xFBCF, 0, 0, 0, 0, 0, 0,0xCFB7,
+ 0,0xEEC3, 0, 0, 0, 0, 0, 0,
+ 0,0xCEEA, 0, 0, 0, 0, 0, 0,
+ 0,0xE2AD, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD7E1,0xFAF5, 0, 0,0xD5C9,0xF8AC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE7D9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF3E9, 0,
+ 0, 0, 0,0xD8ED,0xE3C4,0xF0F1, 0, 0,
+ 0, 0, 0, 0, 0,0xE8E5, 0, 0,
+ 0,0xE0FA,0xEEC4,0xD9DE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xEBA2,0xEBA3,
+ 0, 0, 0, 0, 0, 0,0xFCC2,0xEABB,
+ 0, 0, 0, 0,0xE8AB,0xDEE2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEDEF, 0,0xE8A3, 0, 0, 0, 0,0xCFF1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD4BC, 0,0xFCEA, 0, 0, 0, 0, 0,
+0xE7BE, 0,0xFCF2, 0, 0,0xD6B4, 0, 0,
+0xE2AE, 0,0xD3B7,0xFACC, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFADC, 0,0xEDB5,0xE1E3,
+ 0,0xE8AC, 0,0xE8DD, 0, 0,0xEFE9, 0,
+ 0, 0, 0, 0,0xF4BD, 0,0xCFB8,0xE9DB,
+0xD1AC, 0, 0, 0, 0, 0, 0,0xDAC7,
+ 0, 0, 0, 0, 0, 0, 0,0xEBC9,
+ 0,0xE8CC, 0, 0, 0,0xDEB7, 0, 0,
+ 0, 0,0xD6BC,0xD3E5, 0, 0, 0, 0,
+ 0,0xFADD, 0, 0, 0, 0, 0, 0,
+0xDAD6, 0,0xCAB1, 0, 0, 0, 0, 0,
+ 0,0xDAC8,0xDFA6, 0,0xF9B3,0xF2D2, 0,0xCAC4,
+ 0, 0, 0, 0, 0, 0,0xCECB, 0,
+ 0,0xCDF5, 0, 0, 0,0xFDB0,0xD5A8, 0,
+0xF1C1, 0, 0,0xE2E9,0xDCCA,0xECB4,0xFAC0, 0,
+ 0,0xFBA8,0xD0A8, 0, 0,0xDAEC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9EE,
+ 0,0xE0FB, 0, 0, 0,0xEFEA,0xFADE, 0,
+ 0,0xE0C4, 0,0xCFB9, 0,0xD5CA,0xD7E2,0xE2AF,
+ 0,0xD7B8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE8CD, 0, 0, 0, 0,
+ 0, 0, 0,0xF6DA, 0, 0, 0, 0,
+0xEFA2,0xE2DA,0xF6FC, 0, 0,0xFBD0,0xD1AD, 0,
+0xCDE4, 0,0xD1AE,0xDCED,0xE8CE, 0,0xF0F9,0xCEB5,
+0xE6FC, 0, 0,0xD7FB,0xD0D6,0xDDF5,0xF7F1, 0,
+0xF6FD, 0,0xDBF7, 0, 0, 0, 0,0xFBEA,
+0xE9DC,0xD9C1, 0,0xF5F2,0xE0C5, 0, 0, 0,
+ 0, 0, 0,0xEAD4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF9C2, 0,0xEABC,
+ 0,0xD2C5,0xFBD1,0xE7C0,0xEBA5, 0,0xDFFA,0xE3A2,
+0xD7B9, 0,0xE9C3, 0,0xE8FD,0xE8AF, 0, 0,
+0xF2D3,0xFBA9,0xD8A5, 0, 0, 0, 0,0xD5CB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD0C8, 0,
+ 0, 0,0xD1AF,0xD7E3, 0, 0, 0,0xE0C6,
+ 0,0xD6A2, 0,0xEDF0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD7F3, 0, 0, 0,0xFCD4, 0,0xDAD7,0xCCDF,
+ 0,0xF2D4, 0,0xD1B0, 0,0xCCE0, 0,0xDBFD,
+0xF3BF, 0,0xF0D1, 0, 0, 0, 0, 0,
+0xFCBB, 0,0xE2B0, 0, 0,0xE6A5, 0, 0,
+ 0,0xE2DB, 0, 0, 0,0xDFDE, 0,0xE0C7,
+ 0, 0, 0, 0, 0, 0,0xF2EF, 0,
+ 0, 0,0xCCE1, 0, 0, 0, 0,0xD6EA,
+ 0, 0, 0, 0,0xE7C2, 0, 0, 0,
+0xCEB6, 0,0xF3C0, 0,0xCDFE, 0, 0, 0,
+0xFBD2, 0,0xF8F8,0xF7FB, 0, 0,0xE8BF, 0,
+ 0, 0, 0, 0, 0, 0,0xE8B7, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEDB6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDCBA, 0, 0,0xCCB4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF1F7, 0, 0, 0,0xE8B8, 0, 0,
+0xCAF6, 0,0xE4A4,0xF4D6, 0, 0, 0,0xDFE6,
+ 0, 0, 0,0xDFA7, 0,0xDFE7,0xE1C1, 0,
+0xE9C4, 0, 0,0xDCCB,0xE9C5, 0, 0, 0,
+0xEFA3,0xEBA6,0xCBA3,0xE3E9, 0, 0, 0,0xD1FB,
+0xEFA4, 0,0xEFEB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0B4,
+ 0, 0, 0, 0,0xCDA3, 0, 0,0xE8E6,
+ 0,0xEFA5, 0,0xD3CC,0xDAED, 0, 0, 0,
+ 0,0xD7BA, 0,0xF2D5,0xF5E5,0xD9EF, 0, 0,
+ 0, 0,0xF9B4, 0, 0,0xD5D4,0xFDCF, 0,
+ 0, 0,0xDBE3, 0, 0, 0, 0,0xF1E1,
+0xECB6, 0, 0, 0, 0,0xFBFE,0xD3D7, 0,
+0xD1B1, 0,0xCBB1, 0, 0, 0, 0,0xD1B2,
+ 0, 0, 0, 0, 0, 0,0xCBB2,0xF1C2,
+ 0, 0,0xF4E1,0xF9B5, 0, 0,0xE1C3,0xE1C2,
+ 0,0xEBF7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xDFA8, 0, 0,
+ 0, 0, 0, 0, 0,0xCBCA, 0, 0,
+ 0, 0, 0,0xE6B9, 0, 0, 0, 0,
+ 0,0xF8DE,0xF9AA,0xCAF7, 0,0xEDB7, 0, 0,
+0xD3B8,0xF2D6, 0, 0,0xD4D9,0xEEC5,0xF2F0, 0,
+ 0, 0,0xCAB2, 0, 0,0xDCBB, 0,0xF1F8,
+ 0, 0, 0, 0, 0,0xECB7, 0, 0,
+ 0, 0,0xE5CA, 0,0xF6C0,0xFDDD, 0, 0,
+0xD4E3,0xCCE2, 0,0xF7D4, 0, 0, 0, 0,
+ 0, 0,0xD7E5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD3C3, 0,0xD8A6, 0,0xF6C1, 0, 0, 0,
+ 0, 0,0xDDF6, 0,0xCDC0, 0, 0, 0,
+0xE5DC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE5CB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE1C4, 0, 0, 0, 0, 0,0xE8B0,
+0xF4B0,0xF3EA,0xDAEE, 0,0xD7BB, 0,0xE2B1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD7AA, 0, 0, 0, 0,
+ 0, 0,0xD6FB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE4DF, 0,0xCAD6, 0,
+ 0, 0,0xEBA8, 0, 0, 0,0xDBFE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF6C2, 0, 0,0xEFBB, 0, 0, 0,
+ 0,0xD4FD, 0, 0,0xE0C8, 0, 0, 0,
+0xE8B9, 0,0xEFA6, 0, 0, 0, 0, 0,
+0xCDA4, 0, 0,0xD4F4,0xDBA1,0xDBDC,0xDBDD, 0,
+ 0, 0, 0, 0,0xEEDC, 0,0xCBCB,0xFCD5,
+ 0, 0, 0, 0, 0, 0,0xCEEB, 0,
+0xCDC1, 0, 0,0xFBD3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF9AB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF5D4, 0, 0, 0, 0,0xD9A9,
+ 0, 0,0xE9DD,0xDBCD, 0, 0,0xDDCE, 0,
+0xE7C3, 0,0xECCC, 0, 0, 0, 0, 0,
+ 0, 0,0xF9EC, 0, 0, 0,0xCBCC, 0,
+ 0, 0, 0,0xE0FC,0xD4A8, 0,0xEDD3,0xD8EF,
+ 0,0xF2D7, 0,0xCAF8,0xDAEF, 0, 0,0xD6D4,
+ 0, 0, 0, 0, 0, 0,0xD9CD, 0,
+ 0, 0,0xD8EE, 0,0xF2C1, 0, 0, 0,
+0xDFD3, 0, 0, 0,0xDAF0, 0,0xE2EA, 0,
+ 0,0xE0FD, 0, 0,0xD8F8, 0, 0, 0,
+0xF7AF,0xDAB6, 0,0xCAD7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF2D8, 0,
+0xD8F9, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFADF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCFEF,
+0xD9C2, 0,0xF0D2, 0,0xE4D1, 0, 0, 0,
+0xF3B7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFAE0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEFEC, 0, 0, 0, 0,
+ 0,0xE2B2, 0,0xD4BD, 0, 0,0xD9CE, 0,
+ 0, 0, 0,0xF4E2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD4A9, 0, 0, 0, 0,0xCDC2,0xE7DA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF2D9, 0, 0, 0, 0,
+ 0,0xD9AA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD8BE, 0,
+ 0, 0, 0, 0, 0,0xDCAD, 0, 0,
+ 0, 0, 0, 0,0xE2EB,0xD6FC, 0, 0,
+0xCAF9, 0, 0,0xD4DA, 0, 0, 0, 0,
+ 0, 0, 0,0xF4D7,0xCCA1, 0, 0,0xCFBA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF5B8,
+ 0, 0, 0,0xD9C3,0xD0E8, 0, 0, 0,
+ 0, 0,0xE3C5,0xEBF8, 0,0xF2B1, 0, 0,
+ 0,0xCFBB, 0, 0, 0,0xD3AD,0xE8E1,0xCEEC,
+ 0, 0, 0,0xE0B4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDEE3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDDF7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF2B2,0xF3F6,0xF6DB,
+ 0, 0, 0, 0,0xD7FE, 0, 0, 0,
+ 0, 0,0xF8DF, 0,0xF7F2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD0A9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE6DA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF5A6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD7BC,0xCCE3, 0, 0,0xE6DB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDDDD, 0, 0, 0,
+ 0,0xD1B3, 0, 0, 0, 0, 0,0xEFED,
+ 0, 0, 0, 0,0xD6DE,0xE4F4,0xE1EF, 0,
+ 0,0xDDF8, 0, 0, 0, 0, 0,0xE8CF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCAE5, 0, 0, 0,0xDCA1,
+ 0,0xE0B5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFCAC,0xFCAD,0xD8A7, 0, 0, 0,
+ 0,0xEDB8, 0, 0, 0,0xDBB6, 0, 0,
+ 0, 0,0xD6F0,0xF3AF, 0, 0,0xCDA5, 0,
+0xDAF1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD8A8, 0, 0, 0,0xCCE4, 0, 0,0xD1B4,
+ 0, 0, 0, 0, 0,0xCAD8, 0, 0,
+ 0, 0, 0,0xDAF2, 0, 0, 0, 0,
+ 0,0xF5A7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF5A8, 0,
+ 0, 0, 0, 0, 0, 0,0xE6A6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD5EC,0xD5F8,0xDAF3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE3C6, 0, 0, 0,0xDEE4, 0,
+0xDEE5,0xD1B5, 0, 0, 0, 0, 0,0xD1B6,
+0xD1B7,0xF2B3, 0, 0, 0, 0, 0, 0,
+0xE9DE, 0, 0, 0, 0, 0,0xF0D3,0xF2B4,
+ 0, 0,0xF0D4,0xCBE4,0xFBD4,0xF5E6,0xE3EA, 0,
+0xDEE6, 0, 0, 0, 0,0xDFD4, 0, 0,
+0xF8F9, 0, 0, 0, 0,0xF0AE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD1B8, 0, 0, 0, 0,0xD6DF,
+ 0,0xD0D7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFCA1,0xEFEE,0xDCD8,
+ 0,0xE9DF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE5DD,0xFDFB,
+ 0, 0,0xE0C9, 0, 0, 0,0xD6C9, 0,
+ 0,0xD4AA, 0,0xE5CC, 0, 0, 0, 0,
+ 0,0xE9E0, 0, 0, 0,0xD0D8,0xFCA2,0xD4BE,
+0xE2B3,0xDEE7, 0, 0, 0, 0, 0, 0,
+ 0,0xDCBC,0xD2B6,0xF5D5, 0, 0, 0, 0,
+ 0,0xCEA1,0xF5A9, 0, 0,0xDDF9, 0, 0,
+0xDDFA, 0, 0, 0, 0, 0, 0,0xF0D5,
+ 0, 0, 0, 0,0xF6DF, 0,0xF2DA,0xE4EB,
+ 0,0xF2F1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xECB9, 0, 0, 0, 0,
+0xFDFC, 0, 0, 0, 0,0xE1AA, 0, 0,
+0xCAD9, 0, 0,0xEFEF, 0,0xF5AA, 0, 0,
+ 0, 0, 0, 0,0xECF9, 0, 0,0xF8AD,
+ 0,0xF2C2,0xF6C3, 0,0xD7D2, 0, 0,0xF9A2,
+0xF0D6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF0FA, 0,
+ 0,0xF6E0, 0, 0, 0, 0,0xE9F3,0xF2C3,
+ 0, 0, 0,0xD4AB,0xCAB3,0xCDA6, 0,0xCDC3,
+0xCDDA, 0, 0, 0, 0, 0,0xD9CF, 0,
+ 0,0xF6C4, 0, 0, 0,0xEEDD,0xE7C4, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE2B4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDFE2,0xE7DB, 0, 0, 0, 0, 0,
+ 0,0xE8B1, 0,0xFCAE, 0, 0, 0, 0,
+0xE5CD, 0, 0, 0,0xFAEB, 0,0xCFBC, 0,
+ 0,0xCFE2,0xCDF6, 0, 0,0xEFF0, 0,0xF4BE,
+ 0,0xD4CD, 0, 0,0xF3B8, 0, 0, 0,
+0xE9A1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF2F2,0xF3EB, 0,0xF0D7, 0, 0,
+0xCFD7, 0, 0, 0, 0, 0, 0,0xCFDF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE8C0,0xE8C1, 0, 0, 0,0xCFE3,0xE9A2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD0AA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF3C1,0xD0AB, 0,0xD4E4,
+ 0, 0,0xEFBC,0xD8A1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9DF,
+ 0,0xF3D7, 0, 0, 0,0xDCBD, 0,0xCCE5,
+0xEDF1, 0, 0,0xF1E2, 0,0xD4DB, 0, 0,
+ 0, 0,0xE2B5, 0, 0,0xCAE6, 0,0xD3AE,
+ 0, 0, 0, 0, 0, 0,0xCCE6, 0,
+ 0,0xF1D3,0xF5E7, 0, 0, 0, 0,0xCADA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xFBEE,
+ 0,0xE1C5, 0, 0, 0, 0, 0, 0,
+ 0,0xDFE9, 0,0xEEDE, 0, 0,0xF7C2, 0,
+0xD8A2, 0, 0, 0, 0, 0,0xDDAC, 0,
+ 0, 0, 0, 0,0xF0AF,0xD6BD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE1AB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF9B6, 0,
+ 0,0xD4F5, 0,0xD0C9,0xEFA7,0xE2EC, 0,0xDBEA,
+0xCECC,0xF5E8,0xF7D5, 0,0xD3CD, 0,0xF3FE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD0B5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0FE, 0,0xDFFB, 0,
+ 0, 0, 0, 0, 0,0xE6DD, 0, 0,
+ 0, 0, 0, 0, 0,0xE8A4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCBCD,
+ 0, 0, 0,0xEFA8, 0, 0, 0,0xEEB4,
+ 0, 0, 0, 0,0xDAD8,0xD1B9, 0,0xDFA9,
+ 0, 0,0xF3B0, 0, 0,0xCCC4, 0, 0,
+ 0,0xCEB7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xEFA9, 0, 0,
+ 0,0xDFD5, 0, 0,0xEDD7, 0, 0, 0,
+0xEEC6, 0, 0, 0, 0, 0, 0, 0,
+0xEFBD,0xFCD6, 0, 0,0xDBF4, 0,0xEFAA,0xF8B9,
+ 0,0xF5E9, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE3D9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE1C6, 0, 0, 0,0xD4BF, 0, 0, 0,
+ 0,0xDEE8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF0EA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF3C2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD3AF, 0,
+ 0,0xCADB, 0, 0, 0, 0, 0,0xFCD7,
+ 0, 0,0xEDD8,0xE1C7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF4D8,0xD6B3,0xDDAD,
+ 0, 0, 0,0xD5BE, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF1C3,0xEEDF, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD6EB, 0, 0, 0,0xF4D9, 0, 0, 0,
+ 0, 0, 0, 0,0xD7E6, 0, 0, 0,
+ 0, 0, 0,0xDAB7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xDDFB, 0, 0, 0, 0,
+ 0,0xDDCF, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD8A3, 0, 0,0xDAD9, 0,0xF0D8,
+0xEFC4, 0, 0, 0, 0, 0, 0,0xE1D8,
+ 0, 0, 0, 0, 0,0xF1D4, 0,0xEDF2,
+ 0, 0, 0, 0, 0, 0,0xD5DB, 0,
+ 0,0xD5DC,0xF3C4,0xCBD7, 0, 0, 0, 0,
+ 0,0xE2B6, 0, 0, 0, 0,0xEFF1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFBD5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD3D8, 0,
+ 0, 0, 0, 0, 0, 0,0xDDD0,0xF0D9,
+0xCBB3, 0, 0, 0, 0, 0, 0,0xD5DD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCDA7, 0, 0,0xD0AC, 0,
+0xD1BA, 0,0xF1C4, 0,0xE5B3,0xFBF5,0xE9E1,0xFDE0,
+0xFCBC, 0,0xDAA2,0xDAA3, 0,0xD2A1, 0, 0,
+0xD2EF, 0, 0, 0,0xE2ED, 0, 0,0xDEE9,
+0xCEDC,0xF2B5,0xD0E4,0xDDD1, 0, 0, 0, 0,
+0xE1C8,0xDBB7,0xDFE3, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEDB9,0xF1C5, 0,0xF3CF,0xD7AB,
+0xE1AC, 0, 0,0xE3EB, 0,0xEEC7, 0, 0,
+ 0,0xE1C9,0xCAFA, 0, 0, 0, 0, 0,
+ 0, 0,0xF0FB,0xFAE1,0xF0DA,0xCCE7,0xDAF4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCCBF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCEED, 0,
+ 0,0xD5A9,0xFAE2, 0, 0, 0,0xD0E5, 0,
+0xEBD6, 0,0xECDF, 0, 0, 0,0xDFFC, 0,
+ 0,0xF7D6,0xDEEA,0xCBB4, 0, 0,0xEFBE, 0,
+ 0,0xCCB5, 0, 0, 0, 0, 0,0xCFBD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xEFF2,0xE2B7,
+ 0, 0, 0,0xCCE8, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF0FC, 0, 0, 0,
+0xD6E0, 0,0xF1C6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE2B8,0xEBAB, 0, 0,
+ 0,0xCBB5,0xD8D1, 0,0xF4CE,0xF3F7, 0, 0,
+0xD7C6, 0,0xD1BB,0xF7AA, 0,0xEDCA,0xD7D3,0xD8FA,
+ 0, 0, 0, 0, 0, 0, 0,0xF6C5,
+ 0, 0,0xD1CC,0xDDFC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDFFD, 0,
+0xF9E5, 0,0xE0CA, 0, 0,0xF2FD,0xD3B0, 0,
+0xF4F3,0xDAC9, 0,0xE6DE, 0, 0, 0, 0,
+0xF8BA,0xE8D0, 0, 0,0xD8FB, 0, 0,0xEAD5,
+ 0, 0, 0, 0,0xD6A3, 0, 0, 0,
+ 0, 0, 0,0xF6C6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF2DB,0xE4FC, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE8B2, 0, 0,
+ 0, 0, 0,0xDADA, 0,0xF2DC,0xFBD6,0xE9B2,
+ 0,0xEEAD, 0,0xFAE3, 0, 0, 0, 0,
+ 0, 0, 0,0xDCEE, 0, 0,0xF5EA,0xE6E0,
+ 0,0xF0FD, 0, 0, 0, 0, 0,0xD7AC,
+ 0, 0, 0, 0, 0,0xF5C5,0xEEE0, 0,
+ 0,0xDBE5, 0,0xDDDE, 0, 0,0xD9F0,0xE9A3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF1F9, 0,0xF2C4,0xE0CB, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE9A4, 0,
+ 0,0xE2B9, 0, 0, 0, 0, 0, 0,
+ 0,0xE3B1,0xFCEB,0xCDA8, 0,0xCCB6, 0, 0,
+0xF0DB, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE6BA, 0, 0,0xCDA9, 0, 0, 0,
+ 0, 0,0xF3C3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE1D9, 0, 0,0xEFAB,
+ 0, 0, 0,0xE7C5, 0, 0,0xE0E9, 0,
+0xF3C5, 0, 0,0xD4C0,0xD5BF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDDAE, 0,
+0xF9FC, 0,0xCCC0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE5A2, 0, 0, 0,
+0xCEB8, 0, 0, 0,0xD8D2,0xF9D6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF1AA,0xCED1, 0, 0,0xF6C7, 0,
+0xDBEB, 0,0xDFFE, 0, 0,0xD8E1, 0,0xF7F3,
+ 0,0xD7E7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD4FE, 0, 0,
+0xD1BC, 0,0xE5CF, 0,0xCBB6, 0,0xDAB8, 0,
+ 0, 0, 0, 0,0xCDC4, 0, 0, 0,
+ 0, 0,0xD6BE, 0, 0, 0,0xE2BA, 0,
+ 0, 0, 0, 0,0xCFD8, 0, 0, 0,
+0xE0CC,0xEBF9, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFDFD, 0, 0, 0, 0, 0,
+0xD7E8,0xCBD8, 0, 0, 0,0xE9E2, 0, 0,
+ 0,0xE8BA, 0, 0, 0,0xE3C7, 0, 0,
+ 0, 0,0xECCD, 0,0xECCE, 0,0xD6BF, 0,
+ 0, 0,0xE3A7, 0,0xDFD6,0xFDE8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEEE1,
+0xF6A8,0xDDFD, 0, 0, 0, 0, 0, 0,
+ 0,0xF8BB, 0,0xE8D1, 0, 0, 0, 0,
+0xF9D7, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCEEE, 0, 0,0xECCF, 0, 0, 0,
+0xE9A5,0xD6D5, 0,0xCDC5, 0,0xEDBA,0xD1BD, 0,
+ 0,0xCFBE, 0, 0,0xECBB, 0, 0, 0,
+0xD2B1, 0, 0, 0, 0,0xCCE9, 0,0xD9C4,
+0xE9FC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD1BE, 0, 0,
+ 0, 0, 0,0xECBC, 0, 0,0xE5AD, 0,
+ 0, 0, 0, 0, 0,0xF7B0, 0,0xCCEA,
+ 0, 0, 0,0xD3C4, 0, 0,0xD6C0, 0,
+ 0, 0,0xD6FD, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE1A1, 0,
+0xDEBD, 0,0xF6A9, 0, 0, 0,0xDAA4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD6A4,
+0xF5C6, 0,0xE1A2,0xE9C6, 0, 0, 0,0xF2C5,
+ 0, 0, 0, 0, 0,0xF4E9,0xD6EC,0xEBD3,
+ 0, 0, 0, 0,0xECBD,0xE2DC,0xDEEB,0xF0DC,
+ 0,0xEBBF, 0,0xD7CE,0xD1BF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF5AB, 0,
+ 0, 0, 0,0xF9FD, 0,0xCADC, 0, 0,
+ 0,0xCDC6,0xF2B6, 0, 0,0xDDFE, 0, 0,
+ 0,0xCCB7,0xDBB8, 0, 0, 0, 0,0xD0E9,
+ 0,0xCEDD,0xEBC0, 0,0xFDA2, 0, 0, 0,
+ 0, 0,0xF8CB, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEAD6,0xF1B0, 0, 0, 0,
+ 0, 0, 0, 0,0xDBCE, 0,0xF7C3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDBCF,0xCBA4, 0, 0,0xF8E0, 0,
+ 0,0xFBD7, 0, 0,0xEBCA,0xE0A1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCECD, 0, 0,0xD4DC, 0, 0, 0,
+0xFDD8, 0, 0, 0, 0,0xD2F6, 0, 0,
+ 0, 0,0xF2B7, 0, 0,0xFAF6,0xF6AA,0xFAF7,
+0xD8E6, 0,0xF4B1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE8D2, 0,0xCAC5,0xCCEB, 0, 0, 0, 0,
+ 0, 0, 0,0xE2EE, 0, 0, 0, 0,
+ 0,0xE2BB, 0,0xF7AD, 0, 0, 0,0xF8E1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF3EC, 0, 0, 0, 0,0xDEA1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE4FD, 0, 0,0xE3EC, 0,
+0xDDAF,0xDDB0, 0, 0,0xCBB7,0xE8D3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE1A3,0xD2E0, 0,
+ 0, 0, 0,0xF0FE, 0, 0, 0, 0,
+0xE9A6,0xCBF2, 0, 0, 0, 0, 0, 0,
+0xEDF3,0xDCD9,0xE0CD, 0, 0, 0, 0,0xF7DA,
+0xDBB9, 0, 0, 0, 0, 0, 0, 0,
+0xCCAE, 0,0xDADB, 0, 0, 0, 0,0xCDC7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDDB1, 0,0xD8AF,0xE3A3, 0, 0,
+0xCEEF, 0, 0,0xF2F3, 0, 0, 0, 0,
+0xF8B3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE0CE, 0,0xF5FD, 0, 0,
+ 0, 0,0xEBEC, 0, 0,0xD3C5,0xFCEC,0xD2DB,
+0xD4EB, 0,0xDEA2, 0, 0, 0,0xE5E6, 0,
+ 0, 0, 0, 0, 0,0xF0B0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD5C4, 0, 0, 0, 0, 0, 0,0xEDF4,
+ 0, 0, 0,0xE3ED, 0,0xE8C2, 0,0xEDF5,
+0xD7FC, 0,0xEDBB, 0, 0,0xF6AB, 0, 0,
+ 0, 0, 0,0xF2B8,0xF6C8, 0, 0, 0,
+ 0, 0,0xD3E6,0xF2DD,0xCFBF, 0,0xEBAC, 0,
+ 0, 0, 0, 0, 0,0xCFC0, 0,0xE6A8,
+0xFDE9, 0,0xCFC1, 0,0xE0DF,0xDEEC, 0, 0,
+ 0, 0,0xE0A2, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF4BF,0xE2EF, 0,0xD9F1,0xF1C7,
+ 0,0xCBB8, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF9FE,0xDBBA,0xDAF5, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF6EC,0xDADC,0xFAE4,
+ 0,0xE0CF, 0, 0, 0, 0, 0, 0,
+0xDDB2, 0, 0, 0, 0,0xE6A9, 0,0xEFF3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF3ED, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xEBFA, 0,0xF9E6, 0,
+ 0, 0, 0, 0, 0, 0,0xCADD,0xD5DE,
+ 0,0xCADE,0xDFE4, 0, 0, 0,0xE6FD, 0,
+0xF5AC, 0, 0, 0, 0, 0,0xE4F5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE9E3, 0,0xEDCB,0xCFE4, 0,
+ 0, 0,0xD8D3, 0, 0, 0, 0, 0,
+ 0,0xDDB3,0xD4EC, 0, 0,0xF2B9, 0,0xDFB7,
+ 0, 0, 0, 0, 0,0xCBCE,0xFBD8, 0,
+ 0,0xD0D9, 0, 0,0xDDD2,0xF7F4,0xE7DC,0xE4A5,
+ 0,0xFCA3, 0,0xDBBB, 0, 0, 0,0xF2BA,
+0xE9FD,0xD0CA, 0,0xF5D6,0xD9C5,0xE4B4, 0,0xEDA7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEABD,0xE6FE, 0,0xF7C4,0xF5AD, 0,0xD9E0,
+ 0, 0, 0,0xCAB4, 0, 0,0xF8E2,0xCFC2,
+ 0,0xECBE, 0, 0, 0,0xE5B4,0xCDC8,0xEEC8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE7C8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCDC9,0xF9B7, 0,
+ 0,0xF1E8,0xD9F2,0xDBF5,0xCAB5,0xD9C6, 0, 0,
+ 0,0xD8C9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9AB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEDBC, 0, 0,0xD8D4, 0, 0, 0,0xDCDA,
+ 0,0xE2BC, 0, 0,0xFCED,0xECE0,0xD2FE, 0,
+0xE9C7,0xE6AA, 0, 0, 0, 0, 0, 0,
+0xE2F0, 0, 0, 0, 0, 0, 0,0xFABB,
+ 0,0xF5AE,0xFBAA, 0, 0, 0, 0,0xECFB,
+ 0,0xECBF,0xFCD8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD4E5, 0, 0, 0,0xF9C3,
+ 0, 0, 0,0xEEE2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD7E9,0xEDF6, 0, 0, 0,0xDEED, 0,
+ 0, 0, 0, 0, 0, 0,0xCCEC, 0,
+0xE3EE, 0, 0, 0, 0, 0,0xE8D4, 0,
+ 0, 0,0xFAF8, 0, 0, 0, 0, 0,
+ 0,0xDDB4,0xE4B5,0xD8B0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD8D5, 0, 0,
+ 0,0xF4EA, 0, 0, 0,0xCEB9, 0, 0,
+ 0,0xD6E1,0xCFD2, 0,0xD0B6, 0, 0, 0,
+ 0, 0, 0,0xCEA2, 0, 0,0xF3EE, 0,
+ 0, 0, 0, 0,0xF3F8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDCCC, 0,0xD0CB, 0, 0, 0,0xFCA4,
+0xCDCA,0xD7D4,0xDEA3, 0,0xE4E0, 0, 0, 0,
+ 0,0xEEC9, 0, 0, 0,0xE2DD, 0, 0,
+ 0, 0, 0,0xF5FE,0xD4AC, 0, 0, 0,
+ 0, 0,0xD5D1, 0,0xD8F0,0xF8C3,0xEAD7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF5D7, 0, 0,0xD8BF, 0, 0, 0,
+ 0,0xFDC0, 0, 0, 0, 0, 0, 0,
+0xEBAD, 0, 0, 0, 0,0xD5AA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE7A8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEECA,
+ 0, 0, 0,0xCAE7, 0, 0, 0, 0,
+ 0,0xF8E3, 0,0xD4DD, 0, 0,0xEAD8, 0,
+ 0, 0, 0,0xFBD9,0xEDF7, 0, 0,0xE5B5,
+ 0, 0, 0, 0, 0,0xD0AD, 0, 0,
+ 0, 0,0xF1F1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE2BD, 0, 0, 0,0xE3C8, 0, 0, 0,
+ 0,0xD9D5, 0, 0,0xDFAA, 0, 0, 0,
+ 0,0xDBBC, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF8E4, 0, 0, 0, 0, 0,
+0xF1FA, 0, 0,0xE5B6,0xF3EF, 0, 0,0xFBDA,
+0xE1E0, 0,0xD9AC, 0,0xF5EB, 0,0xE0B6, 0,
+ 0,0xE9C8, 0,0xCBCF, 0,0xE3C9, 0, 0,
+ 0,0xDEEE, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE2BE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDCEF, 0,0xD6A5, 0,
+ 0, 0, 0, 0,0xE2F1, 0, 0, 0,
+ 0, 0, 0, 0,0xD6FE, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD9A1, 0,0xD8C0,0xDCDB, 0, 0,0xEDBD,
+0xDFB8, 0,0xEAA5, 0, 0, 0,0xD7AD, 0,
+ 0,0xF3F9, 0,0xEDF8, 0,0xF5C7, 0, 0,
+ 0, 0, 0, 0,0xE1CA,0xEBE3, 0,0xF2DE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF8CC, 0,0xEAD9,
+ 0,0xD3C6, 0,0xDBE6, 0, 0, 0, 0,
+ 0,0xF5AF, 0, 0, 0, 0,0xCEF0, 0,
+ 0, 0, 0,0xE9FE, 0, 0, 0, 0,
+ 0,0xFBB6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE2F2, 0, 0, 0, 0,
+0xCFF2,0xF7B9,0xD9F3, 0, 0,0xE1CB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDADD, 0, 0,0xDAB9,
+ 0, 0, 0, 0, 0, 0, 0,0xEBFB,
+ 0,0xCBB9, 0, 0,0xEDF9, 0, 0, 0,
+ 0, 0, 0,0xE0E0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF4C0, 0,
+0xFDBC,0xDFB1,0xE3EF, 0, 0, 0, 0,0xE0A3,
+0xFDB9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF0B1, 0, 0, 0, 0, 0,
+ 0,0xCDCB, 0, 0, 0, 0, 0, 0,
+ 0,0xEDBE, 0, 0, 0,0xD5C0,0xE3F0,0xEDFA,
+ 0, 0, 0, 0, 0,0xE9E4, 0, 0,
+ 0, 0, 0, 0,0xD5ED,0xE7DD, 0, 0,
+ 0, 0, 0, 0,0xD4F6,0xE5B7, 0, 0,
+ 0,0xDBE7,0xE2BF, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEECB,
+ 0, 0,0xD7F4,0xF0DD, 0, 0, 0,0xCEAB,
+ 0, 0,0xE7DE, 0, 0, 0,0xD6D6,0xE1CC,
+ 0, 0,0xE8B3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE5EE,0xDCA2,
+ 0, 0,0xE0D0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD5B5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD5A1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFBDB, 0,
+0xF9CB, 0, 0, 0,0xCBF3,0xF4A5, 0, 0,
+ 0, 0, 0,0xFAC8,0xD6D7, 0,0xE9E5,0xFBDC,
+ 0, 0, 0, 0, 0, 0, 0,0xFDD0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFBF6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDAA5, 0,0xDBBD, 0, 0, 0,
+ 0, 0, 0,0xECE2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCDF7,0xF0DE, 0, 0, 0,
+ 0,0xF6C9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDEEF,
+ 0, 0, 0,0xD3B1, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFCEE, 0, 0, 0,
+ 0,0xE8C3, 0,0xF1C8, 0, 0, 0,0xCEF1,
+ 0, 0, 0, 0,0xF9ED, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF2F4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE4B6, 0,
+0xF5B9, 0,0xDCF0,0xE3F1, 0, 0, 0, 0,
+0xE8A5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF2BB, 0,0xDEA4, 0,0xDACC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCAE9, 0,
+ 0, 0, 0, 0, 0,0xE3DA, 0,0xFCD9,
+ 0, 0, 0, 0, 0, 0, 0,0xEADA,
+ 0, 0, 0, 0, 0, 0,0xF9C4, 0,
+0xE3A4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFBDD, 0,0xEFCA, 0,
+0xE8C4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD5CC, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xEBD7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD9AD,
+ 0, 0,0xFBAB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD3D9, 0, 0, 0, 0,
+ 0, 0,0xD5A2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF6DE, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xDAF6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0D1, 0, 0,0xE9A8,
+ 0, 0,0xF5F9, 0, 0, 0, 0, 0,
+ 0,0xFAAF, 0,0xEBFC, 0, 0,0xE0EA, 0,
+ 0, 0, 0, 0, 0,0xE3B2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD5C5,
+ 0, 0,0xF1E3,0xD5EE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCDCC, 0, 0, 0, 0,0xEDD9, 0,
+ 0, 0, 0,0xD8C1, 0, 0, 0, 0,
+0xFAEC, 0, 0, 0, 0, 0,0xF1EB, 0,
+ 0, 0, 0, 0,0xFABC,0xE6E2, 0, 0,
+ 0, 0,0xFAE5,0xE2FA, 0, 0, 0,0xCAB6,
+ 0,0xE4B7, 0,0xEADB, 0,0xF5FA, 0, 0,
+ 0,0xFBAC,0xCFC3,0xEBFD, 0, 0, 0, 0,
+0xF8FA, 0, 0,0xDFB9, 0, 0, 0, 0,
+0xE1F1, 0,0xD2A4, 0, 0, 0, 0,0xF5FB,
+ 0, 0, 0, 0, 0, 0,0xD0DA,0xD0DB,
+ 0,0xEABE,0xD9B1, 0, 0, 0, 0, 0,
+0xCAB7, 0, 0,0xD3E7, 0,0xF8E5, 0, 0,
+ 0, 0,0xD3B2, 0, 0, 0,0xE2C0,0xF2DF,
+ 0, 0, 0, 0, 0, 0,0xCDE5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF9AC, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCDCD, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEEAE,0xD6AE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD7EA,
+ 0, 0, 0, 0,0xE7E0,0xEBAE, 0, 0,
+ 0,0xCFD9, 0, 0,0xDCCD,0xEDFB, 0,0xDEF0,
+ 0,0xD7EB, 0, 0, 0, 0, 0, 0,
+0xDEA5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xDFD7,0xDBD0,0xDBD1, 0, 0,
+0xD5A3, 0, 0, 0, 0,0xF0B2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDCDC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCAE8, 0,0xF8E6,0xDCCE, 0, 0, 0, 0,
+0xEADC,0xDBD2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE9B3, 0, 0,
+ 0, 0,0xF7DB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE3A8, 0,
+0xD7AE, 0, 0,0xE0E1, 0, 0, 0, 0,
+ 0,0xCBBA, 0, 0,0xE5D1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0DC,
+ 0, 0, 0, 0,0xD5C1, 0, 0, 0,
+ 0, 0,0xD8CA, 0, 0, 0, 0, 0,
+ 0, 0,0xE3A9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE0A4,
+ 0,0xE9A9, 0,0xD3C7, 0, 0,0xDCDD,0xF8AE,
+ 0, 0, 0,0xCCB8, 0, 0, 0,0xD0AE,
+ 0, 0, 0,0xD8F2, 0, 0,0xE3CA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCCAF, 0, 0, 0, 0, 0, 0,
+ 0,0xD4AD,0xF6D1, 0, 0, 0, 0, 0,
+ 0, 0,0xD0CC, 0, 0, 0, 0, 0,
+ 0, 0,0xCAC6, 0, 0,0xD5C2, 0, 0,
+0xCEBA, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xCAC7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFAB0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDFD8, 0, 0, 0,
+0xF5BA, 0, 0, 0, 0, 0, 0, 0,
+0xE5EB, 0,0xEFF4,0xDDB5, 0, 0, 0, 0,
+0xCDAA, 0,0xE3F2, 0,0xFBF7, 0,0xF7D0, 0,
+ 0, 0, 0,0xFDBA, 0, 0,0xFDE1,0xF6FE,
+0xD1C0, 0, 0,0xE8C5, 0,0xE4B8, 0,0xE1E8,
+ 0, 0, 0,0xCCC1, 0,0xD2ED, 0, 0,
+ 0, 0,0xDBBE, 0, 0,0xE0E2, 0, 0,
+ 0,0xFAC9, 0, 0,0xE1CD, 0,0xCAB8, 0,
+ 0, 0,0xF2E0,0xF1C9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xDEF1, 0, 0, 0,0xF0DF,0xF8C4, 0, 0,
+ 0, 0, 0,0xEECC, 0, 0,0xDEF2, 0,
+0xE7C9, 0,0xE2F3,0xE7E1, 0, 0,0xE3CB, 0,
+ 0,0xE3CC, 0, 0, 0,0xCFF8,0xEFAC, 0,
+0xFDFE,0xFCA5,0xFAB1,0xDFD9, 0,0xE0D2, 0, 0,
+ 0,0xF4DA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF1CA, 0,0xCEA3,
+ 0, 0, 0, 0,0xF2BC,0xECE3, 0, 0,
+ 0, 0, 0,0xE0A5, 0,0xF7AB, 0, 0,
+0xEBAF, 0, 0, 0, 0, 0,0xE5DE, 0,
+0xE1A4,0xCDAB, 0,0xD9F4,0xE8A6,0xCDCE,0xE1E9, 0,
+0xFCEF, 0,0xE0E3, 0, 0, 0, 0, 0,
+0xE2C1, 0,0xCEA4, 0, 0, 0, 0, 0,
+ 0,0xDEA6, 0, 0,0xEBFE, 0,0xEBDD,0xF0E0,
+ 0, 0,0xF4DB, 0,0xE2F4, 0, 0,0xD3C8,
+ 0, 0, 0,0xF4EB, 0,0xEEB5, 0,0xF5D8,
+ 0, 0,0xD5DF, 0, 0, 0,0xD6E5, 0,
+ 0, 0, 0,0xEBB0,0xF4E3, 0, 0, 0,
+ 0,0xE3CD, 0, 0, 0, 0,0xF4F4,0xFAB2,
+ 0, 0,0xEFF5,0xCADF, 0,0xEBB1,0xEDBF, 0,
+ 0,0xFDC9, 0, 0, 0, 0,0xE4A6,0xF9A4,
+0xF0B3, 0,0xE5EC, 0, 0, 0,0xD1E7, 0,
+0xD9C7,0xE4D7,0xEADD, 0,0xD4F7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xDABA, 0,
+0xDACD, 0, 0, 0,0xF9CC, 0,0xE1DA,0xDBBF,
+ 0,0xCCC5,0xECD0,0xCBBB, 0,0xDEF3, 0, 0,
+0xE9AA, 0, 0, 0, 0, 0, 0, 0,
+0xD9C8, 0, 0,0xEEE3,0xD7BD, 0, 0, 0,
+ 0, 0, 0,0xCFC4, 0, 0, 0, 0,
+ 0,0xD0CD, 0, 0, 0, 0, 0, 0,
+ 0,0xFCA6, 0, 0, 0, 0, 0, 0,
+ 0,0xF1FB, 0, 0, 0, 0,0xFDD2,0xD1C1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE3DB, 0,0xD3C9, 0,0xDCCF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCCED, 0,
+ 0, 0, 0, 0,0xDEA7, 0, 0,0xE6BB,
+0xECA1, 0, 0, 0,0xCCB9, 0, 0,0xFBDE,
+ 0, 0, 0, 0, 0,0xE7E2, 0, 0,
+0xD4C1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xDCA8, 0, 0, 0, 0, 0,
+0xE2C2, 0,0xF3D8,0xE5D3, 0, 0,0xF3D9, 0,
+ 0, 0,0xF3C6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCDDB,
+ 0, 0, 0, 0, 0, 0, 0,0xCDAC,
+ 0,0xFCC3, 0, 0, 0, 0,0xD4E7, 0,
+0xD1C2, 0,0xF9A5, 0,0xE8D5, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE3CE, 0, 0,
+ 0, 0,0xD4CA, 0, 0, 0, 0, 0,
+ 0,0xDFDA, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFBDF,0xE7E3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF8FB,0xE3CF, 0, 0, 0, 0, 0,
+ 0, 0,0xF5B0, 0, 0, 0, 0, 0,
+ 0, 0,0xD8E7, 0,0xD9C9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF8AF,0xEFF6, 0,
+0xDDB6,0xEEAF,0xCDF8, 0, 0, 0, 0,0xDEB8,
+0xFCA7,0xF7FC,0xF7B1,0xCEBB,0xF4A1, 0, 0,0xEECD,
+0xE1AE, 0, 0,0xECC3,0xCFFE, 0,0xF8BF,0xD8E2,
+0xD3E8, 0, 0,0xDEA8,0xF4E4,0xECC2, 0,0xD9F5,
+0xF9C5,0xDDD3,0xD6F1,0xECFC,0xFCF0, 0, 0,0xEDC0,
+0xCAB9, 0,0xEEE4, 0, 0, 0, 0, 0,
+ 0,0xF2E1, 0,0xDEB9, 0, 0, 0, 0,
+ 0, 0,0xD6F2, 0,0xDEF4, 0,0xDFDB, 0,
+0xDBD3, 0,0xFAE7,0xD8E3,0xF4C1, 0,0xDDB7, 0,
+ 0, 0,0xF2F5, 0, 0,0xD4AE, 0, 0,
+ 0, 0, 0, 0,0xD6F3, 0, 0, 0,
+ 0, 0, 0,0xDDB8,0xCFC5,0xDFDF, 0, 0,
+ 0, 0, 0, 0,0xF2BE,0xF6A1, 0,0xEBCB,
+0xF1FC, 0,0xF3C7, 0, 0,0xE0EB, 0, 0,
+ 0, 0, 0,0xEDFC, 0, 0,0xE1DB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xEEE5, 0,0xDEF5, 0,
+ 0, 0, 0,0xFAD3, 0, 0, 0, 0,
+0xF1CB, 0, 0,0xD0AF,0xDDB9, 0, 0,0xD1C3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF5B1, 0, 0,
+ 0, 0,0xEAC6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF0E1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF6AC, 0, 0, 0, 0,
+0xF5D9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0EB, 0, 0, 0, 0,
+ 0, 0,0xDDBA, 0, 0, 0,0xF2BF, 0,
+ 0, 0, 0, 0, 0, 0,0xF7C5, 0,
+ 0, 0, 0,0xDBA2,0xF2F6, 0, 0,0xCABA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF7F5, 0,0xCBE5, 0, 0,
+ 0,0xEEE6, 0,0xE0D3, 0, 0, 0, 0,
+0xCEA5, 0, 0, 0, 0, 0, 0,0xD6D8,
+ 0, 0, 0,0xD4AF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE9C9, 0, 0, 0, 0,0xD3CE,
+0xF4C2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCBE6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF1A1, 0, 0, 0, 0, 0,
+0xEBB2, 0, 0, 0, 0,0xF1A2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEBB3, 0,0xF0B4, 0, 0,0xCBF4,
+0xD4B0,0xF3B2,0xFBB7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF5EC, 0, 0, 0, 0, 0,0xEEE7,
+0xF4B2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF5ED, 0,0xCFF3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF0E2, 0, 0, 0, 0, 0,0xEECE,
+ 0, 0,0xF1CC, 0, 0,0xE5B8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD7F5,0xE3F3,0xCFE5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCFC6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF3B3,0xE4D8,0xCFF9,0xCFDA, 0, 0,
+ 0, 0,0xFACD, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE6E3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF2E2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF5EE, 0, 0,0xCABB, 0, 0,0xE3DC, 0,
+ 0, 0, 0,0xCEF2, 0,0xD6D9, 0, 0,
+ 0,0xEEB0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF4E5,0xD8C2,0xDCD0,0xCCEE, 0, 0,
+ 0, 0, 0,0xD5E0,0xF6CA,0xFDCA,0xD8D6,0xF4CF,
+ 0, 0, 0, 0, 0, 0,0xD6A6,0xDCBE,
+ 0,0xDBD4,0xD7C7, 0, 0, 0, 0,0xF2FE,
+ 0, 0, 0,0xF1CD, 0, 0, 0, 0,
+0xE2C3,0xDCDE, 0,0xDCDF, 0, 0,0xEFAD,0xE6AB,
+ 0, 0, 0, 0,0xF9DD,0xEABF, 0, 0,
+ 0,0xEFAE, 0, 0, 0,0xF4D0,0xCEF3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE6AC, 0,0xCEDE,
+ 0, 0,0xD5F9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE3F4,0xCDD0, 0, 0, 0,
+ 0, 0, 0,0xD5B8, 0, 0,0xF7FD, 0,
+0xDCA9, 0, 0, 0, 0,0xDEF6, 0,0xDCAA,
+0xF2E3,0xE9B4,0xD2DC, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE9E6, 0, 0,0xE3F6, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE7CA, 0,
+ 0,0xD0CE, 0, 0,0xDAF7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCABC, 0,
+ 0, 0,0xEEE8,0xDADE, 0,0xF2F7, 0, 0,
+0xE2FB, 0,0xCCA6, 0, 0, 0, 0,0xDABB,
+ 0,0xEEE9, 0, 0, 0,0xF5DA, 0, 0,
+0xF7DC,0xE1EA,0xCEC1,0xD4B1, 0,0xFDB1,0xE6BD, 0,
+0xFBAD, 0, 0,0xF8E7, 0,0xE1CE, 0,0xF7E2,
+0xF5EF,0xCFC7, 0, 0,0xD4B2,0xCCEF, 0,0xD4E8,
+ 0,0xEECF,0xF7D7, 0, 0,0xE0A6,0xD6C1,0xE1DC,
+0xF0E3,0xF1E4,0xDCF1,0xD6A7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF4F5, 0,
+ 0,0xF1CE,0xF2E4, 0, 0,0xD0B0, 0, 0,
+0xECEF, 0, 0, 0,0xF9BA, 0,0xEBB5, 0,
+ 0,0xD4ED,0xE2C4, 0, 0, 0, 0,0xE9E7,
+ 0, 0,0xEBB4,0xEAA1, 0,0xF8BC,0xCEA6, 0,
+0xF9C6,0xFCDA, 0,0xD4B3,0xD3B9,0xEADE, 0, 0,
+ 0,0xE9AB, 0, 0,0xE1E1,0xD3CF,0xF4F6, 0,
+0xEAC0,0xE1CF, 0,0xCCBA, 0, 0, 0, 0,
+ 0,0xEEEA, 0, 0, 0,0xF0E4,0xF3B4,0xD4EE,
+ 0, 0,0xF2C0, 0, 0,0xF1E5, 0,0xF4C3,
+0xE0D4, 0,0xEBB6, 0,0xD7A1,0xCBE8, 0,0xF9AD,
+0xE9AD,0xD8E4,0xFAB3,0xE2C5,0xFCBD, 0, 0,0xECC4,
+0xD8B1, 0,0xDCAB, 0, 0, 0, 0,0xD5A4,
+ 0,0xEBE9, 0, 0, 0,0xE8BB, 0, 0,
+ 0,0xD8D7, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xFBAE,0xD1E1, 0, 0,0xDBC0, 0,
+0xF5BE, 0,0xDEF7, 0, 0, 0, 0,0xCAFB,
+0xF7C6,0xCFC8, 0, 0, 0,0xE1D0, 0, 0,
+0xEED0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE9F4, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xCEF4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD5CD, 0,
+ 0,0xCFDB, 0, 0, 0, 0, 0, 0,
+0xDDBB, 0, 0, 0, 0,0xCEAC, 0, 0,
+ 0, 0, 0, 0, 0,0xE9E8, 0, 0,
+ 0, 0, 0, 0, 0,0xD4B4, 0, 0,
+ 0, 0,0xE4C7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF5DB, 0, 0,0xFAC1, 0, 0,
+ 0,0xDEA9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD4F8,
+ 0, 0, 0, 0, 0,0xEFF7, 0, 0,
+ 0, 0,0xD3B3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEBB7,0xEFF8,0xF5DC,0xEDCC,0xDBD5,0xF1CF, 0,
+ 0, 0,0xF1D0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF5B2, 0, 0, 0, 0, 0,
+ 0,0xD9AE,0xD5AC, 0,0xE2C6, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFDA3, 0,0xFBE5,
+0xDFAB, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE2F5,
+ 0,0xF6AD, 0,0xF5B3, 0,0xF0B5, 0, 0,
+ 0, 0,0xE1A5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF5DD, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xECA2,0xEDFD, 0,0xF5B4,0xFBB8,
+ 0,0xDBA3, 0, 0,0xD6CA,0xCBD9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE5D4, 0, 0, 0, 0, 0, 0,0xF3FA,
+ 0,0xEBB8, 0,0xE0B7,0xD7EC,0xF1EC,0xE5AF,0xD5E1,
+0xD7ED,0xD1D1, 0, 0, 0, 0, 0,0xE1F2,
+0xEFF9, 0, 0, 0,0xDDBC,0xF6DC, 0, 0,
+ 0, 0, 0,0xF0E5, 0, 0, 0,0xF4C4,
+ 0, 0,0xE9E9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF3FB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD4EF, 0, 0,
+0xCCA2,0xF7FE,0xDFBC, 0, 0, 0, 0,0xEBCD,
+ 0, 0, 0, 0, 0, 0,0xD0B7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD6C2, 0, 0, 0,
+ 0, 0,0xE8AD, 0, 0, 0, 0,0xEFAF,
+0xCBA5, 0, 0, 0, 0,0xCBE9, 0, 0,
+ 0,0xFAE8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCCC6,
+ 0, 0, 0,0xE6E7, 0, 0,0xEAC7, 0,
+ 0, 0,0xDBA4, 0,0xCFC9,0xE2FC,0xEFFA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEBDE, 0, 0,0xF5C8, 0,0xD4DE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE0D5, 0,0xEFB0, 0, 0,0xE2C7, 0,
+0xD9AF, 0, 0, 0,0xF9E7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE7E5, 0, 0,0xCFCA,0xE1D1,
+ 0,0xE2C8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xEFFB, 0, 0,0xFAF9,
+ 0, 0,0xDCF2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0A7, 0, 0, 0,
+ 0, 0,0xF8E8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCBEA, 0, 0, 0,0xCBBC, 0, 0, 0,
+ 0, 0, 0, 0,0xD6E2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF5DE, 0, 0, 0, 0, 0, 0, 0,
+0xF5DF, 0,0xEEB6, 0, 0, 0,0xE2F6,0xD3CA,
+0xEFFC,0xD1C4,0xEFB1, 0,0xD1C5, 0,0xD0DE, 0,
+0xD9E1, 0, 0,0xE0B8, 0, 0,0xCDD1,0xF3B9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE7CC, 0,0xD6A8,0xCEA7, 0,0xD4B5, 0, 0,
+ 0, 0, 0, 0,0xE4C8, 0, 0, 0,
+ 0, 0, 0,0xD3B4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xEBB9, 0,
+ 0, 0, 0, 0, 0,0xCBF5, 0, 0,
+ 0, 0, 0, 0,0xF6DD, 0,0xF1A3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCCC7, 0, 0, 0,
+ 0, 0, 0, 0,0xE9CA, 0,0xE1F0, 0,
+ 0, 0,0xF5E0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFBAF, 0, 0, 0,0xCBD1,
+ 0, 0, 0, 0,0xFBE0,0xF2E5, 0, 0,
+0xECF0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0EC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEEEB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE9CB, 0,
+ 0,0xCCF0, 0, 0,0xD7AF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF3A1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFCF5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF1A4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE0D6, 0, 0,
+ 0, 0, 0,0xEFB2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF4D1, 0, 0,
+0xF7A1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF1D1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCAFC,0xCAFD, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCECE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF3C8, 0,0xF3BA
+};
+
+/* page 7 0x9577-0x9F9C */
+static uint16 tab_uni_ksc56017[]={
+0xEDFE, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDAA6, 0, 0,0xE0EC, 0, 0, 0,
+ 0, 0,0xF8CD, 0,0xCBD2, 0, 0, 0,
+0xEBCE, 0,0xF9D8,0xF9D9,0xCAE0,0xDACA, 0, 0,
+ 0,0xCBA6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCAC8,0xF9EE,0xDBEC, 0,
+ 0,0xD0B1, 0, 0, 0, 0,0xD5EF, 0,
+ 0, 0,0xE6F3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE7A2,0xE4D9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE4E1, 0, 0,0xFCC4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF9EF,0xCFF4,0xF7E6,
+ 0, 0, 0, 0, 0,0xCEBC, 0, 0,
+ 0, 0,0xF4C5,0xDCA3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xDDBD, 0, 0,
+ 0, 0,0xF4C6, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF8A1, 0, 0, 0,0xE8D6,
+ 0, 0, 0,0xDBC1, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF0E6, 0, 0, 0,
+0xE4B9,0xF6ED, 0,0xF9AE, 0,0xDDBE, 0, 0,
+ 0, 0, 0, 0,0xD7B0,0xD8E8,0xCBBD, 0,
+ 0,0xF9DA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xF8CE,0xF9F0,0xE0ED,0xE3B3,
+0xF4B3, 0, 0,0xEAC2,0xF2E6,0xF0B6, 0, 0,
+ 0, 0, 0,0xDBD6, 0, 0, 0, 0,
+ 0,0xEBE4, 0, 0,0xF2E7, 0,0xD7D5,0xD4B6,
+0xF9E8,0xD7C1, 0, 0, 0, 0,0xE5D5, 0,
+ 0, 0, 0, 0, 0, 0,0xE9EA,0xD7CC,
+ 0, 0, 0,0xD3E9,0xE2C9, 0,0xFCDB,0xCDAD,
+ 0, 0, 0, 0, 0,0xCCB0,0xEAA2, 0,
+ 0,0xE4F6,0xD0C0, 0,0xF0B7,0xEEA1, 0, 0,
+ 0, 0, 0, 0,0xD7F6, 0, 0, 0,
+0xE2CA,0xE2CB, 0,0xFACF, 0, 0, 0, 0,
+ 0, 0,0xEBDF, 0, 0, 0, 0, 0,
+0xD6CB, 0, 0, 0,0xF4B4, 0, 0, 0,
+ 0,0xEDCD,0xE4D2, 0, 0,0xEAA9,0xE4BA,0xF3A2,
+0xCDD2, 0,0xF6CB, 0,0xF1E6,0xEDC1,0xE8BC,0xEED1,
+ 0, 0, 0, 0, 0, 0,0xF0E7,0xE2CC,
+ 0, 0,0xE4AA, 0,0xF5E1,0xEDDA, 0, 0,
+ 0, 0, 0,0xD7EE,0xD1F1, 0, 0, 0,
+ 0,0xE9EB,0xE9EC,0xE0E4, 0, 0, 0, 0,
+0xDAA7,0xDDD4, 0,0xEAA3, 0, 0, 0,0xD6C3,
+0xD6F4, 0,0xDADF, 0,0xEFB3, 0, 0, 0,
+ 0,0xE2CD, 0, 0, 0, 0, 0,0xEFFD,
+0xF2E8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEFC5, 0,0xE7E7, 0, 0,0xD7FD,
+ 0, 0,0xE7CE, 0, 0,0xDFDC, 0,0xF9C7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD9F6, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xDFAC, 0,0xD6DA, 0, 0, 0, 0,
+ 0, 0,0xDCA4, 0, 0, 0,0xF0B8, 0,
+ 0, 0, 0,0xD5FA, 0,0xE4F7, 0, 0,
+ 0,0xD6C4, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF4EC, 0, 0, 0, 0,0xEFFE,
+ 0, 0, 0, 0, 0,0xF0A1, 0,0xDEAA,
+ 0, 0,0xDABC,0xD8FC, 0, 0, 0, 0,
+ 0, 0,0xFAD4, 0, 0, 0,0xECE5, 0,
+ 0, 0, 0, 0, 0,0xFCA8, 0, 0,
+0xECE6, 0, 0,0xD8CB, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFBB9, 0,0xE4D3, 0,
+0xCDF9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCFD3, 0, 0, 0, 0, 0, 0,
+ 0,0xCAEA, 0, 0,0xCFD4, 0,0xF8BD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4C7,
+ 0, 0, 0, 0,0xEADF, 0, 0, 0,
+ 0, 0, 0, 0,0xF9DB, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD4B7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xEBE5, 0, 0,0xE1D2,
+ 0, 0, 0, 0,0xEAA4, 0, 0, 0,
+0xFAC2,0xFBE1,0xFAED,0xF0A2,0xCCF1, 0,0xFAA3,0xE2F7,
+ 0,0xE2CE, 0,0xE9F5, 0,0xE1EB, 0, 0,
+ 0,0xE7E8,0xE8D7,0xDAF8,0xD4CB, 0, 0, 0,
+0xF7F6,0xD6C5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD4E9, 0,
+ 0,0xFAFA, 0, 0, 0, 0, 0, 0,
+ 0,0xCCF2,0xF7DD, 0,0xDEBA, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xCEA8,
+ 0, 0, 0, 0, 0,0xF0B9,0xE4FE,0xE4C9,
+ 0, 0, 0, 0, 0,0xE4D4, 0, 0,
+ 0,0xEAC3, 0,0xEFB4, 0, 0, 0,0xD7BE,
+ 0, 0, 0, 0, 0, 0,0xFBE2, 0,
+0xCDD3, 0, 0, 0,0xEFB5, 0, 0, 0,
+0xFAE9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF9A6, 0, 0, 0, 0, 0, 0,
+0xDFBD, 0,0xF7C7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xF8FD, 0, 0,
+0xF8FC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDEAB,0xDBE8, 0, 0,
+0xE3DD, 0,0xE1E2,0xD1C6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF6D0,0xEBE6,
+0xDAF9, 0, 0, 0, 0,0xECC7, 0, 0,
+ 0, 0, 0, 0, 0,0xDEF8,0xF8E9,0xE3DE,
+ 0, 0, 0, 0,0xCEF5, 0, 0, 0,
+ 0, 0,0xFAC3,0xE5D7, 0,0xECC8, 0, 0,
+ 0,0xF3C9, 0, 0,0xE4BB, 0, 0, 0,
+ 0,0xE6AE, 0, 0, 0, 0, 0,0xEFB6,
+ 0,0xDCBF, 0, 0, 0, 0, 0, 0,
+ 0,0xCEBD, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD8C3, 0,
+ 0, 0,0xD0CF, 0,0xCFFA,0xF3CA,0xE0D7, 0,
+ 0, 0,0xD1C7,0xE9AE, 0,0xE8BD, 0, 0,
+0xFAC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE2CF,
+ 0, 0,0xFAC5, 0, 0, 0,0xF9B8, 0,
+ 0, 0, 0, 0, 0, 0,0xDCE0, 0,
+ 0,0xFBB0, 0, 0, 0,0xD8A9,0xE5DF,0xF9A7,
+ 0, 0,0xF6EE, 0,0xF6CC,0xE2F8, 0, 0,
+ 0, 0,0xECF1, 0, 0, 0, 0, 0,
+ 0, 0,0xDAE0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF1D2,0xD2CC,0xCFCB, 0, 0,0xCABD, 0,
+ 0, 0,0xDDBF, 0, 0, 0,0xF6EF, 0,
+0xDEF9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFAB4, 0,
+ 0, 0,0xD5AD, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF1E7, 0,0xDEBE, 0, 0, 0, 0, 0,
+ 0,0xDCC0, 0, 0, 0, 0, 0,0xD1C8,
+0xD1C9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF8BE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCBF6, 0, 0, 0,
+ 0,0xD4F9, 0, 0, 0, 0, 0,0xF5E2,
+0xE1D3, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD8E9, 0, 0,0xF8FE, 0,0xCFCC, 0,
+ 0, 0, 0, 0, 0, 0,0xFDA4, 0,
+ 0, 0, 0, 0, 0, 0,0xCEF6, 0,
+0xFAD0, 0, 0,0xCCF3,0xE6BE, 0, 0, 0,
+0xF6AE, 0, 0,0xD5F0, 0, 0,0xD1CA, 0,
+ 0, 0,0xFCBE,0xD5F1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xCDE9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFAB5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE2D0,0xF4F7, 0, 0,
+ 0,0xCDD4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE7A3, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xDBA5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE2D1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD7A2, 0, 0,0xF7E3, 0, 0, 0, 0,
+ 0, 0,0xEAA6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xD0A1, 0, 0,
+ 0, 0,0xCEDA,0xFBEB,0xDBA6,0xDBDE,0xD8E5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEAE0, 0, 0, 0, 0,0xD8AA, 0, 0,
+ 0, 0, 0,0xE5E0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD6DB, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEFC6,
+ 0, 0,0xF8EA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE4D5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xCEF7, 0, 0,0xE0D8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD7EF, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4ED,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCDE6, 0, 0,
+ 0,0xCCF4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF5E3, 0,
+ 0,0xE4CA, 0,0xDCE1, 0, 0,0xF9C8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xFCBF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE8A7, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xD8C4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCBBE, 0,0xDCAE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD7F7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xF0E8, 0,
+0xDDC0, 0,0xCFCD, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDCF3,0xD9B0, 0,0xE6E9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE4BC, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xEAC4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4EC,
+ 0,0xE4E5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xFBF8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xCCBB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE4BD, 0,
+ 0,0xCDDC,0xD9F7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xDDDF, 0, 0,
+ 0, 0, 0,0xEDCE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD9D0, 0, 0, 0, 0, 0,
+0xE5A3, 0, 0, 0, 0,0xF9CD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCDAE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xCFCE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF6AF, 0, 0, 0, 0,
+ 0,0xFDD3,0xEBED,0xD6DC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE5A4, 0, 0, 0,0xD5B6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD6DD, 0,
+ 0, 0,0xF9E9, 0, 0, 0,0xE7A4, 0,
+0xD6E3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD1CB,0xD6E4, 0, 0, 0,
+0xD5F2, 0, 0, 0, 0, 0,0xDEFA, 0,
+0xD7F8, 0, 0, 0, 0, 0,0xD8EA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCFD5,0xD8FD, 0,
+ 0, 0, 0, 0,0xD8AB, 0, 0,0xFDCB,
+ 0, 0, 0, 0,0xFCDC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE0A8,0xD5F3,
+ 0, 0,0xFDD9, 0, 0,0xCCA3, 0, 0,
+ 0,0xD9F9, 0, 0,0xD3EA,0xF5F5, 0,0xEFC7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD3DA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xDABD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE8A8,0xDCAF, 0, 0, 0, 0, 0,0xF0A3,
+ 0, 0, 0, 0,0xCDD5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE0A9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xDEAC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0BA,0xEEB1, 0, 0,0xEEB2,
+ 0, 0, 0,0xF6CD, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEED2, 0,0xD6C6, 0, 0, 0, 0, 0,
+0xE0E5, 0, 0,0xF3BB, 0,0xE5E1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE4CB, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD7A3, 0,
+ 0,0xDBC2, 0, 0, 0, 0,0xCAFE, 0,
+ 0, 0, 0, 0, 0,0xCFCF};
+
+/* page 8 0xAC00-0xD7A3 */
+static uint16 tab_uni_ksc56018[]={
+0xB0A1,0xB0A2,0x8141,0x8142,0xB0A3,0x8143,0x8144,0xB0A4,
+0xB0A5,0xB0A6,0xB0A7,0x8145,0x8146,0x8147,0x8148,0x8149,
+0xB0A8,0xB0A9,0xB0AA,0xB0AB,0xB0AC,0xB0AD,0xB0AE,0xB0AF,
+0x814A,0xB0B0,0xB0B1,0xB0B2,0xB0B3,0xB0B4,0x814B,0x814C,
+0xB0B5,0x814D,0x814E,0x814F,0xB0B6,0x8150,0x8151,0x8152,
+0x8153,0x8154,0x8155,0x8156,0xB0B7,0xB0B8,0x8157,0xB0B9,
+0xB0BA,0xB0BB,0x8158,0x8159,0x815A,0x8161,0x8162,0x8163,
+0xB0BC,0xB0BD,0x8164,0x8165,0xB0BE,0x8166,0x8167,0x8168,
+0xB0BF,0x8169,0x816A,0x816B,0x816C,0x816D,0x816E,0x816F,
+0x8170,0x8171,0x8172,0xB0C0,0x8173,0xB0C1,0x8174,0x8175,
+0x8176,0x8177,0x8178,0x8179,0xB0C2,0x817A,0x8181,0x8182,
+0xB0C3,0x8183,0x8184,0x8185,0xB0C4,0x8186,0x8187,0x8188,
+0x8189,0x818A,0x818B,0x818C,0x818D,0x818E,0x818F,0x8190,
+0x8191,0x8192,0x8193,0x8194,0x8195,0x8196,0x8197,0x8198,
+0xB0C5,0xB0C6,0x8199,0x819A,0xB0C7,0x819B,0x819C,0xB0C8,
+0xB0C9,0x819D,0xB0CA,0x819E,0x819F,0x81A0,0x81A1,0x81A2,
+0xB0CB,0xB0CC,0x81A3,0xB0CD,0xB0CE,0xB0CF,0xB0D0,0x81A4,
+0x81A5,0xB0D1,0xB0D2,0xB0D3,0xB0D4,0x81A6,0x81A7,0x81A8,
+0xB0D5,0x81A9,0x81AA,0x81AB,0xB0D6,0x81AC,0x81AD,0x81AE,
+0x81AF,0x81B0,0x81B1,0x81B2,0xB0D7,0xB0D8,0x81B3,0xB0D9,
+0xB0DA,0xB0DB,0x81B4,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9,
+0xB0DC,0xB0DD,0xB0DE,0x81BA,0xB0DF,0x81BB,0x81BC,0xB0E0,
+0xB0E1,0x81BD,0x81BE,0x81BF,0x81C0,0x81C1,0x81C2,0x81C3,
+0xB0E2,0xB0E3,0x81C4,0xB0E4,0xB0E5,0xB0E6,0x81C5,0x81C6,
+0x81C7,0xB0E7,0x81C8,0x81C9,0xB0E8,0x81CA,0x81CB,0x81CC,
+0xB0E9,0x81CD,0x81CE,0x81CF,0xB0EA,0x81D0,0x81D1,0x81D2,
+0x81D3,0x81D4,0x81D5,0x81D6,0x81D7,0xB0EB,0x81D8,0xB0EC,
+0x81D9,0x81DA,0x81DB,0x81DC,0x81DD,0x81DE,0x81DF,0x81E0,
+0xB0ED,0xB0EE,0x81E1,0x81E2,0xB0EF,0x81E3,0x81E4,0xB0F0,
+0xB0F1,0x81E5,0xB0F2,0x81E6,0xB0F3,0x81E7,0x81E8,0xB0F4,
+0xB0F5,0xB0F6,0x81E9,0xB0F7,0x81EA,0xB0F8,0xB0F9,0x81EB,
+0x81EC,0x81ED,0x81EE,0x81EF,0xB0FA,0xB0FB,0x81F0,0x81F1,
+0xB0FC,0x81F2,0x81F3,0x81F4,0xB0FD,0x81F5,0xB0FE,0x81F6,
+0x81F7,0x81F8,0x81F9,0x81FA,0xB1A1,0xB1A2,0x81FB,0xB1A3,
+0x81FC,0xB1A4,0x81FD,0x81FE,0x8241,0x8242,0x8243,0x8244,
+0xB1A5,0x8245,0x8246,0x8247,0xB1A6,0x8248,0x8249,0x824A,
+0xB1A7,0x824B,0x824C,0x824D,0x824E,0x824F,0x8250,0x8251,
+0x8252,0xB1A8,0x8253,0x8254,0xB1A9,0xB1AA,0x8255,0x8256,
+0x8257,0x8258,0x8259,0x825A,0xB1AB,0xB1AC,0x8261,0x8262,
+0xB1AD,0x8263,0x8264,0x8265,0xB1AE,0x8266,0x8267,0x8268,
+0x8269,0x826A,0x826B,0x826C,0xB1AF,0xB1B0,0x826D,0xB1B1,
+0x826E,0xB1B2,0x826F,0x8270,0x8271,0x8272,0x8273,0x8274,
+0xB1B3,0x8275,0x8276,0x8277,0xB1B4,0x8278,0x8279,0x827A,
+0xB1B5,0x8281,0x8282,0x8283,0x8284,0x8285,0x8286,0x8287,
+0x8288,0xB1B6,0x8289,0xB1B7,0x828A,0x828B,0x828C,0x828D,
+0x828E,0x828F,0x8290,0x8291,0xB1B8,0xB1B9,0x8292,0x8293,
+0xB1BA,0x8294,0x8295,0xB1BB,0xB1BC,0xB1BD,0xB1BE,0x8296,
+0x8297,0x8298,0x8299,0xB1BF,0xB1C0,0xB1C1,0x829A,0xB1C2,
+0x829B,0xB1C3,0xB1C4,0x829C,0x829D,0x829E,0x829F,0x82A0,
+0xB1C5,0xB1C6,0x82A1,0x82A2,0xB1C7,0x82A3,0x82A4,0x82A5,
+0xB1C8,0x82A6,0x82A7,0x82A8,0x82A9,0x82AA,0x82AB,0x82AC,
+0x82AD,0x82AE,0x82AF,0x82B0,0xB1C9,0xB1CA,0x82B1,0x82B2,
+0x82B3,0x82B4,0x82B5,0x82B6,0xB1CB,0x82B7,0x82B8,0x82B9,
+0x82BA,0x82BB,0x82BC,0x82BD,0x82BE,0x82BF,0x82C0,0x82C1,
+0x82C2,0x82C3,0x82C4,0x82C5,0x82C6,0x82C7,0x82C8,0xB1CC,
+0x82C9,0x82CA,0x82CB,0x82CC,0x82CD,0x82CE,0x82CF,0x82D0,
+0xB1CD,0xB1CE,0x82D1,0x82D2,0xB1CF,0x82D3,0x82D4,0x82D5,
+0xB1D0,0x82D6,0x82D7,0x82D8,0x82D9,0x82DA,0x82DB,0x82DC,
+0xB1D1,0xB1D2,0x82DD,0xB1D3,0x82DE,0x82DF,0x82E0,0x82E1,
+0x82E2,0x82E3,0x82E4,0x82E5,0xB1D4,0x82E6,0x82E7,0x82E8,
+0xB1D5,0x82E9,0x82EA,0x82EB,0xB1D6,0x82EC,0x82ED,0x82EE,
+0x82EF,0x82F0,0x82F1,0x82F2,0x82F3,0x82F4,0x82F5,0x82F6,
+0x82F7,0x82F8,0x82F9,0x82FA,0x82FB,0x82FC,0x82FD,0x82FE,
+0xB1D7,0xB1D8,0x8341,0x8342,0xB1D9,0x8343,0x8344,0xB1DA,
+0xB1DB,0xB1DC,0x8345,0x8346,0x8347,0x8348,0x8349,0x834A,
+0xB1DD,0xB1DE,0x834B,0xB1DF,0x834C,0xB1E0,0x834D,0x834E,
+0x834F,0x8350,0x8351,0x8352,0xB1E1,0x8353,0x8354,0x8355,
+0x8356,0x8357,0x8358,0x8359,0x835A,0x8361,0x8362,0x8363,
+0x8364,0x8365,0x8366,0x8367,0x8368,0x8369,0x836A,0x836B,
+0x836C,0x836D,0x836E,0x836F,0x8370,0x8371,0x8372,0x8373,
+0xB1E2,0xB1E3,0x8374,0x8375,0xB1E4,0x8376,0x8377,0xB1E5,
+0xB1E6,0x8378,0xB1E7,0x8379,0x837A,0x8381,0x8382,0x8383,
+0xB1E8,0xB1E9,0x8384,0xB1EA,0x8385,0xB1EB,0xB1EC,0x8386,
+0x8387,0x8388,0xB1ED,0x8389,0xB1EE,0xB1EF,0xB1F0,0x838A,
+0xB1F1,0x838B,0x838C,0x838D,0xB1F2,0x838E,0xB1F3,0x838F,
+0x8390,0x8391,0x8392,0x8393,0xB1F4,0xB1F5,0x8394,0xB1F6,
+0xB1F7,0xB1F8,0x8395,0x8396,0x8397,0xB1F9,0x8398,0x8399,
+0xB1FA,0xB1FB,0x839A,0x839B,0xB1FC,0x839C,0x839D,0x839E,
+0xB1FD,0x839F,0x83A0,0x83A1,0x83A2,0x83A3,0x83A4,0x83A5,
+0xB1FE,0xB2A1,0x83A6,0xB2A2,0xB2A3,0xB2A4,0x83A7,0x83A8,
+0x83A9,0x83AA,0x83AB,0x83AC,0xB2A5,0xB2A6,0x83AD,0x83AE,
+0x83AF,0x83B0,0x83B1,0x83B2,0xB2A7,0x83B3,0x83B4,0x83B5,
+0x83B6,0x83B7,0x83B8,0x83B9,0x83BA,0x83BB,0x83BC,0x83BD,
+0x83BE,0x83BF,0x83C0,0x83C1,0x83C2,0x83C3,0x83C4,0x83C5,
+0x83C6,0x83C7,0x83C8,0x83C9,0x83CA,0x83CB,0x83CC,0x83CD,
+0x83CE,0x83CF,0x83D0,0x83D1,0x83D2,0x83D3,0x83D4,0x83D5,
+0x83D6,0x83D7,0x83D8,0x83D9,0x83DA,0x83DB,0x83DC,0x83DD,
+0x83DE,0x83DF,0x83E0,0x83E1,0xB2A8,0xB2A9,0xB2AA,0x83E2,
+0xB2AB,0x83E3,0x83E4,0x83E5,0xB2AC,0x83E6,0x83E7,0x83E8,
+0x83E9,0x83EA,0x83EB,0x83EC,0xB2AD,0xB2AE,0x83ED,0xB2AF,
+0xB2B0,0xB2B1,0x83EE,0x83EF,0x83F0,0x83F1,0x83F2,0x83F3,
+0xB2B2,0xB2B3,0x83F4,0x83F5,0xB2B4,0x83F6,0x83F7,0x83F8,
+0x83F9,0x83FA,0x83FB,0x83FC,0x83FD,0x83FE,0x8441,0x8442,
+0xB2B5,0x8443,0x8444,0xB2B6,0x8445,0xB2B7,0x8446,0x8447,
+0x8448,0x8449,0x844A,0x844B,0xB2B8,0x844C,0x844D,0x844E,
+0xB2B9,0x844F,0x8450,0x8451,0xB2BA,0x8452,0x8453,0x8454,
+0x8455,0x8456,0x8457,0x8458,0x8459,0x845A,0x8461,0xB2BB,
+0xB2BC,0x8462,0x8463,0x8464,0x8465,0xB2BD,0x8466,0x8467,
+0xB2BE,0x8468,0x8469,0x846A,0x846B,0x846C,0x846D,0x846E,
+0x846F,0x8470,0x8471,0x8472,0x8473,0x8474,0x8475,0x8476,
+0x8477,0x8478,0x8479,0x847A,0x8481,0x8482,0x8483,0x8484,
+0x8485,0x8486,0x8487,0x8488,0xB2BF,0xB2C0,0x8489,0x848A,
+0xB2C1,0x848B,0xB2C2,0x848C,0xB2C3,0x848D,0x848E,0x848F,
+0x8490,0x8491,0x8492,0x8493,0xB2C4,0xB2C5,0x8494,0xB2C6,
+0x8495,0xB2C7,0xB2C8,0xB2C9,0x8496,0x8497,0x8498,0x8499,
+0xB2CA,0xB2CB,0x849A,0x849B,0x849C,0x849D,0x849E,0x849F,
+0xB2CC,0x84A0,0x84A1,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,
+0x84A7,0x84A8,0x84A9,0x84AA,0xB2CD,0xB2CE,0x84AB,0x84AC,
+0x84AD,0x84AE,0x84AF,0x84B0,0xB2CF,0xB2D0,0x84B1,0x84B2,
+0x84B3,0x84B4,0x84B5,0x84B6,0x84B7,0x84B8,0x84B9,0x84BA,
+0x84BB,0x84BC,0x84BD,0x84BE,0x84BF,0x84C0,0x84C1,0x84C2,
+0x84C3,0xB2D1,0x84C4,0x84C5,0x84C6,0x84C7,0x84C8,0x84C9,
+0xB2D2,0x84CA,0x84CB,0x84CC,0xB2D3,0x84CD,0x84CE,0x84CF,
+0xB2D4,0x84D0,0x84D1,0x84D2,0x84D3,0x84D4,0x84D5,0x84D6,
+0xB2D5,0xB2D6,0x84D7,0x84D8,0x84D9,0xB2D7,0x84DA,0x84DB,
+0x84DC,0x84DD,0x84DE,0x84DF,0xB2D8,0x84E0,0x84E1,0x84E2,
+0x84E3,0x84E4,0x84E5,0x84E6,0x84E7,0x84E8,0x84E9,0x84EA,
+0x84EB,0x84EC,0x84ED,0x84EE,0x84EF,0x84F0,0x84F1,0x84F2,
+0x84F3,0x84F4,0x84F5,0x84F6,0x84F7,0x84F8,0x84F9,0x84FA,
+0xB2D9,0xB2DA,0x84FB,0x84FC,0xB2DB,0x84FD,0x84FE,0x8541,
+0xB2DC,0x8542,0x8543,0x8544,0x8545,0x8546,0x8547,0xB2DD,
+0xB2DE,0xB2DF,0x8548,0xB2E0,0x8549,0xB2E1,0xB2E2,0x854A,
+0x854B,0x854C,0x854D,0x854E,0xB2E3,0x854F,0x8550,0x8551,
+0x8552,0x8553,0x8554,0x8555,0xB2E4,0x8556,0x8557,0x8558,
+0x8559,0x855A,0x8561,0x8562,0x8563,0x8564,0x8565,0x8566,
+0xB2E5,0xB2E6,0x8567,0x8568,0x8569,0x856A,0x856B,0x856C,
+0xB2E7,0xB2E8,0x856D,0x856E,0xB2E9,0x856F,0x8570,0x8571,
+0xB2EA,0x8572,0x8573,0x8574,0x8575,0x8576,0x8577,0x8578,
+0xB2EB,0xB2EC,0x8579,0x857A,0xB2ED,0x8581,0x8582,0x8583,
+0x8584,0x8585,0x8586,0x8587,0xB2EE,0x8588,0x8589,0x858A,
+0xB2EF,0x858B,0x858C,0x858D,0xB2F0,0x858E,0x858F,0x8590,
+0x8591,0x8592,0x8593,0x8594,0xB2F1,0xB2F2,0x8595,0x8596,
+0x8597,0x8598,0x8599,0x859A,0x859B,0x859C,0x859D,0x859E,
+0xB2F3,0x859F,0x85A0,0x85A1,0x85A2,0x85A3,0x85A4,0x85A5,
+0x85A6,0x85A7,0x85A8,0x85A9,0x85AA,0x85AB,0x85AC,0x85AD,
+0x85AE,0x85AF,0x85B0,0x85B1,0x85B2,0x85B3,0x85B4,0x85B5,
+0x85B6,0x85B7,0x85B8,0x85B9,0xB2F4,0xB2F5,0x85BA,0x85BB,
+0xB2F6,0x85BC,0xB2F7,0x85BD,0xB2F8,0x85BE,0xB2F9,0x85BF,
+0x85C0,0x85C1,0x85C2,0xB2FA,0xB2FB,0xB2FC,0x85C3,0xB2FD,
+0x85C4,0xB2FE,0x85C5,0x85C6,0x85C7,0xB3A1,0x85C8,0x85C9,
+0x85CA,0x85CB,0x85CC,0x85CD,0x85CE,0x85CF,0x85D0,0x85D1,
+0x85D2,0x85D3,0x85D4,0x85D5,0x85D6,0x85D7,0x85D8,0x85D9,
+0x85DA,0x85DB,0x85DC,0x85DD,0x85DE,0x85DF,0x85E0,0x85E1,
+0x85E2,0x85E3,0x85E4,0x85E5,0xB3A2,0xB3A3,0x85E6,0x85E7,
+0xB3A4,0x85E8,0x85E9,0x85EA,0xB3A5,0x85EB,0x85EC,0x85ED,
+0x85EE,0x85EF,0x85F0,0x85F1,0xB3A6,0xB3A7,0x85F2,0xB3A8,
+0x85F3,0xB3A9,0x85F4,0x85F5,0x85F6,0x85F7,0x85F8,0x85F9,
+0xB3AA,0xB3AB,0xB3AC,0x85FA,0xB3AD,0x85FB,0x85FC,0xB3AE,
+0xB3AF,0xB3B0,0xB3B1,0x85FD,0x85FE,0x8641,0x8642,0x8643,
+0xB3B2,0xB3B3,0x8644,0xB3B4,0xB3B5,0xB3B6,0xB3B7,0xB3B8,
+0x8645,0xB3B9,0x8646,0xB3BA,0xB3BB,0xB3BC,0x8647,0x8648,
+0xB3BD,0x8649,0x864A,0x864B,0xB3BE,0x864C,0x864D,0x864E,
+0x864F,0x8650,0x8651,0x8652,0xB3BF,0xB3C0,0x8653,0xB3C1,
+0xB3C2,0xB3C3,0x8654,0x8655,0x8656,0x8657,0x8658,0x8659,
+0xB3C4,0xB3C5,0x865A,0x8661,0xB3C6,0x8662,0x8663,0x8664,
+0xB3C7,0x8665,0x8666,0x8667,0x8668,0x8669,0x866A,0x866B,
+0xB3C8,0x866C,0x866D,0x866E,0x866F,0xB3C9,0x8670,0x8671,
+0x8672,0x8673,0x8674,0x8675,0x8676,0x8677,0x8678,0x8679,
+0x867A,0x8681,0x8682,0x8683,0x8684,0x8685,0x8686,0x8687,
+0x8688,0x8689,0x868A,0x868B,0x868C,0x868D,0x868E,0x868F,
+0x8690,0x8691,0x8692,0x8693,0x8694,0x8695,0x8696,0x8697,
+0xB3CA,0xB3CB,0x8698,0xB3CC,0xB3CD,0x8699,0x869A,0x869B,
+0xB3CE,0x869C,0xB3CF,0xB3D0,0x869D,0x869E,0x869F,0x86A0,
+0xB3D1,0xB3D2,0x86A1,0xB3D3,0xB3D4,0xB3D5,0x86A2,0x86A3,
+0x86A4,0x86A5,0x86A6,0xB3D6,0xB3D7,0xB3D8,0x86A7,0x86A8,
+0xB3D9,0x86A9,0x86AA,0x86AB,0xB3DA,0x86AC,0x86AD,0x86AE,
+0x86AF,0x86B0,0x86B1,0x86B2,0xB3DB,0xB3DC,0x86B3,0xB3DD,
+0xB3DE,0xB3DF,0x86B4,0x86B5,0x86B6,0x86B7,0x86B8,0x86B9,
+0xB3E0,0xB3E1,0x86BA,0x86BB,0xB3E2,0x86BC,0x86BD,0x86BE,
+0xB3E3,0x86BF,0x86C0,0x86C1,0x86C2,0x86C3,0x86C4,0x86C5,
+0xB3E4,0xB3E5,0x86C6,0x86C7,0xB3E6,0xB3E7,0x86C8,0x86C9,
+0xB3E8,0x86CA,0x86CB,0x86CC,0xB3E9,0x86CD,0x86CE,0x86CF,
+0xB3EA,0x86D0,0x86D1,0x86D2,0x86D3,0x86D4,0x86D5,0x86D6,
+0x86D7,0x86D8,0x86D9,0x86DA,0x86DB,0x86DC,0x86DD,0x86DE,
+0x86DF,0x86E0,0x86E1,0x86E2,0x86E3,0x86E4,0x86E5,0x86E6,
+0xB3EB,0xB3EC,0x86E7,0x86E8,0xB3ED,0x86E9,0x86EA,0x86EB,
+0xB3EE,0x86EC,0xB3EF,0x86ED,0x86EE,0x86EF,0x86F0,0x86F1,
+0xB3F0,0xB3F1,0x86F2,0xB3F2,0x86F3,0xB3F3,0x86F4,0x86F5,
+0x86F6,0x86F7,0xB3F4,0xB3F5,0xB3F6,0x86F8,0x86F9,0x86FA,
+0xB3F7,0x86FB,0x86FC,0x86FD,0xB3F8,0x86FE,0x8741,0x8742,
+0x8743,0x8744,0x8745,0x8746,0x8747,0x8748,0x8749,0x874A,
+0xB3F9,0x874B,0x874C,0x874D,0x874E,0x874F,0x8750,0x8751,
+0x8752,0x8753,0x8754,0x8755,0x8756,0x8757,0x8758,0x8759,
+0x875A,0x8761,0x8762,0x8763,0x8764,0x8765,0x8766,0x8767,
+0x8768,0x8769,0x876A,0x876B,0x876C,0x876D,0x876E,0x876F,
+0x8770,0x8771,0x8772,0x8773,0xB3FA,0x8774,0x8775,0x8776,
+0xB3FB,0x8777,0x8778,0x8779,0xB3FC,0x877A,0x8781,0x8782,
+0x8783,0x8784,0x8785,0x8786,0xB3FD,0xB3FE,0x8787,0xB4A1,
+0x8788,0x8789,0x878A,0x878B,0x878C,0x878D,0x878E,0x878F,
+0xB4A2,0xB4A3,0x8790,0x8791,0xB4A4,0x8792,0x8793,0x8794,
+0xB4A5,0x8795,0x8796,0x8797,0x8798,0x8799,0x879A,0x879B,
+0x879C,0xB4A6,0x879D,0xB4A7,0x879E,0xB4A8,0x879F,0x87A0,
+0x87A1,0x87A2,0x87A3,0x87A4,0xB4A9,0xB4AA,0x87A5,0x87A6,
+0xB4AB,0x87A7,0x87A8,0xB4AC,0xB4AD,0x87A9,0x87AA,0x87AB,
+0x87AC,0x87AD,0x87AE,0x87AF,0xB4AE,0xB4AF,0x87B0,0xB4B0,
+0x87B1,0xB4B1,0x87B2,0x87B3,0x87B4,0x87B5,0x87B6,0x87B7,
+0xB4B2,0x87B8,0x87B9,0x87BA,0x87BB,0x87BC,0x87BD,0x87BE,
+0x87BF,0x87C0,0x87C1,0x87C2,0x87C3,0x87C4,0x87C5,0x87C6,
+0x87C7,0x87C8,0x87C9,0x87CA,0xB4B3,0x87CB,0x87CC,0x87CD,
+0x87CE,0x87CF,0x87D0,0x87D1,0xB4B4,0x87D2,0x87D3,0x87D4,
+0x87D5,0x87D6,0x87D7,0x87D8,0x87D9,0x87DA,0x87DB,0x87DC,
+0x87DD,0x87DE,0x87DF,0x87E0,0x87E1,0x87E2,0x87E3,0x87E4,
+0x87E5,0x87E6,0x87E7,0x87E8,0x87E9,0x87EA,0x87EB,0x87EC,
+0xB4B5,0x87ED,0x87EE,0x87EF,0xB4B6,0x87F0,0x87F1,0x87F2,
+0xB4B7,0x87F3,0x87F4,0x87F5,0x87F6,0x87F7,0x87F8,0x87F9,
+0xB4B8,0xB4B9,0x87FA,0x87FB,0x87FC,0x87FD,0x87FE,0x8841,
+0x8842,0x8843,0x8844,0x8845,0xB4BA,0xB4BB,0x8846,0x8847,
+0x8848,0x8849,0x884A,0x884B,0xB4BC,0x884C,0x884D,0x884E,
+0x884F,0x8850,0x8851,0x8852,0xB4BD,0xB4BE,0x8853,0x8854,
+0x8855,0xB4BF,0x8856,0x8857,0x8858,0x8859,0x885A,0x8861,
+0xB4C0,0xB4C1,0x8862,0x8863,0xB4C2,0x8864,0x8865,0x8866,
+0xB4C3,0xB4C4,0xB4C5,0x8867,0x8868,0x8869,0x886A,0x886B,
+0xB4C6,0xB4C7,0x886C,0xB4C8,0x886D,0xB4C9,0xB4CA,0x886E,
+0x886F,0x8870,0xB4CB,0x8871,0xB4CC,0x8872,0x8873,0x8874,
+0xB4CD,0x8875,0x8876,0x8877,0xB4CE,0x8878,0x8879,0x887A,
+0x8881,0x8882,0x8883,0x8884,0x8885,0x8886,0x8887,0x8888,
+0x8889,0x888A,0x888B,0x888C,0x888D,0x888E,0x888F,0x8890,
+0xB4CF,0xB4D0,0x8891,0x8892,0xB4D1,0x8893,0x8894,0x8895,
+0xB4D2,0x8896,0xB4D3,0x8897,0x8898,0x8899,0x889A,0x889B,
+0xB4D4,0xB4D5,0x889C,0xB4D6,0x889D,0xB4D7,0x889E,0x889F,
+0x88A0,0x88A1,0xB4D8,0x88A2,0xB4D9,0xB4DA,0xB4DB,0x88A3,
+0xB4DC,0x88A4,0x88A5,0xB4DD,0xB4DE,0xB4DF,0xB4E0,0xB4E1,
+0x88A6,0x88A7,0x88A8,0xB4E2,0xB4E3,0xB4E4,0x88A9,0xB4E5,
+0xB4E6,0xB4E7,0xB4E8,0xB4E9,0x88AA,0x88AB,0x88AC,0xB4EA,
+0xB4EB,0xB4EC,0x88AD,0x88AE,0xB4ED,0x88AF,0x88B0,0x88B1,
+0xB4EE,0x88B2,0x88B3,0x88B4,0x88B5,0x88B6,0x88B7,0x88B8,
+0xB4EF,0xB4F0,0x88B9,0xB4F1,0xB4F2,0xB4F3,0x88BA,0x88BB,
+0x88BC,0x88BD,0x88BE,0x88BF,0xB4F4,0x88C0,0x88C1,0x88C2,
+0x88C3,0x88C4,0x88C5,0x88C6,0x88C7,0x88C8,0x88C9,0x88CA,
+0x88CB,0x88CC,0x88CD,0x88CE,0x88CF,0x88D0,0x88D1,0x88D2,
+0x88D3,0x88D4,0x88D5,0x88D6,0x88D7,0x88D8,0x88D9,0x88DA,
+0x88DB,0x88DC,0x88DD,0x88DE,0x88DF,0x88E0,0x88E1,0x88E2,
+0x88E3,0x88E4,0x88E5,0x88E6,0x88E7,0x88E8,0x88E9,0x88EA,
+0x88EB,0x88EC,0x88ED,0x88EE,0x88EF,0x88F0,0x88F1,0x88F2,
+0x88F3,0x88F4,0x88F5,0x88F6,0xB4F5,0xB4F6,0xB4F7,0x88F7,
+0xB4F8,0x88F8,0x88F9,0xB4F9,0xB4FA,0x88FA,0xB4FB,0xB4FC,
+0x88FB,0x88FC,0x88FD,0x88FE,0xB4FD,0xB4FE,0x8941,0xB5A1,
+0x8942,0xB5A2,0x8943,0xB5A3,0x8944,0x8945,0xB5A4,0x8946,
+0xB5A5,0xB5A6,0x8947,0x8948,0xB5A7,0x8949,0x894A,0x894B,
+0xB5A8,0x894C,0x894D,0x894E,0x894F,0x8950,0x8951,0x8952,
+0xB5A9,0xB5AA,0x8953,0xB5AB,0xB5AC,0xB5AD,0x8954,0x8955,
+0x8956,0x8957,0x8958,0x8959,0xB5AE,0x895A,0x8961,0x8962,
+0xB5AF,0x8963,0x8964,0x8965,0xB5B0,0x8966,0x8967,0x8968,
+0x8969,0x896A,0x896B,0x896C,0x896D,0x896E,0x896F,0x8970,
+0xB5B1,0xB5B2,0x8971,0x8972,0x8973,0x8974,0x8975,0x8976,
+0xB5B3,0x8977,0x8978,0x8979,0xB5B4,0x897A,0x8981,0x8982,
+0x8983,0x8984,0x8985,0x8986,0x8987,0x8988,0x8989,0x898A,
+0x898B,0x898C,0x898D,0x898E,0x898F,0x8990,0x8991,0x8992,
+0x8993,0x8994,0x8995,0x8996,0xB5B5,0xB5B6,0x8997,0x8998,
+0xB5B7,0x8999,0x899A,0xB5B8,0xB5B9,0x899B,0xB5BA,0x899C,
+0xB5BB,0x899D,0x899E,0x899F,0xB5BC,0xB5BD,0x89A0,0xB5BE,
+0x89A1,0xB5BF,0x89A2,0xB5C0,0x89A3,0xB5C1,0x89A4,0x89A5,
+0xB5C2,0x89A6,0x89A7,0x89A8,0xB5C3,0x89A9,0x89AA,0x89AB,
+0xB5C4,0x89AC,0x89AD,0x89AE,0x89AF,0x89B0,0x89B1,0x89B2,
+0x89B3,0x89B4,0x89B5,0x89B6,0x89B7,0x89B8,0x89B9,0x89BA,
+0x89BB,0x89BC,0x89BD,0x89BE,0xB5C5,0x89BF,0x89C0,0x89C1,
+0x89C2,0x89C3,0x89C4,0x89C5,0x89C6,0x89C7,0x89C8,0x89C9,
+0x89CA,0x89CB,0x89CC,0x89CD,0x89CE,0x89CF,0x89D0,0x89D1,
+0xB5C6,0x89D2,0x89D3,0x89D4,0x89D5,0x89D6,0x89D7,0x89D8,
+0xB5C7,0x89D9,0x89DA,0x89DB,0xB5C8,0x89DC,0x89DD,0x89DE,
+0xB5C9,0x89DF,0x89E0,0x89E1,0x89E2,0x89E3,0x89E4,0x89E5,
+0xB5CA,0xB5CB,0x89E6,0xB5CC,0x89E7,0x89E8,0x89E9,0x89EA,
+0x89EB,0x89EC,0x89ED,0x89EE,0xB5CD,0x89EF,0x89F0,0x89F1,
+0x89F2,0x89F3,0x89F4,0x89F5,0x89F6,0x89F7,0x89F8,0x89F9,
+0x89FA,0x89FB,0x89FC,0x89FD,0x89FE,0x8A41,0x8A42,0x8A43,
+0x8A44,0x8A45,0x8A46,0x8A47,0x8A48,0x8A49,0x8A4A,0x8A4B,
+0xB5CE,0xB5CF,0x8A4C,0x8A4D,0xB5D0,0x8A4E,0x8A4F,0x8A50,
+0xB5D1,0x8A51,0x8A52,0x8A53,0x8A54,0x8A55,0x8A56,0x8A57,
+0xB5D2,0xB5D3,0x8A58,0xB5D4,0x8A59,0xB5D5,0x8A5A,0x8A61,
+0x8A62,0x8A63,0x8A64,0x8A65,0xB5D6,0x8A66,0x8A67,0x8A68,
+0x8A69,0x8A6A,0x8A6B,0x8A6C,0x8A6D,0x8A6E,0x8A6F,0x8A70,
+0x8A71,0x8A72,0x8A73,0x8A74,0x8A75,0x8A76,0x8A77,0x8A78,
+0xB5D7,0x8A79,0x8A7A,0x8A81,0x8A82,0x8A83,0x8A84,0x8A85,
+0xB5D8,0x8A86,0x8A87,0x8A88,0x8A89,0x8A8A,0x8A8B,0x8A8C,
+0x8A8D,0x8A8E,0x8A8F,0x8A90,0x8A91,0x8A92,0x8A93,0x8A94,
+0x8A95,0x8A96,0x8A97,0x8A98,0x8A99,0xB5D9,0x8A9A,0x8A9B,
+0x8A9C,0x8A9D,0x8A9E,0x8A9F,0xB5DA,0x8AA0,0x8AA1,0x8AA2,
+0xB5DB,0x8AA3,0x8AA4,0x8AA5,0xB5DC,0x8AA6,0x8AA7,0x8AA8,
+0x8AA9,0x8AAA,0x8AAB,0x8AAC,0x8AAD,0xB5DD,0x8AAE,0xB5DE,
+0x8AAF,0xB5DF,0x8AB0,0x8AB1,0x8AB2,0x8AB3,0x8AB4,0x8AB5,
+0xB5E0,0x8AB6,0x8AB7,0x8AB8,0xB5E1,0x8AB9,0x8ABA,0x8ABB,
+0xB5E2,0x8ABC,0x8ABD,0x8ABE,0x8ABF,0x8AC0,0x8AC1,0x8AC2,
+0xB5E3,0x8AC3,0x8AC4,0x8AC5,0x8AC6,0xB5E4,0x8AC7,0x8AC8,
+0x8AC9,0x8ACA,0x8ACB,0x8ACC,0xB5E5,0xB5E6,0x8ACD,0x8ACE,
+0xB5E7,0x8ACF,0x8AD0,0xB5E8,0xB5E9,0x8AD1,0xB5EA,0x8AD2,
+0x8AD3,0x8AD4,0x8AD5,0x8AD6,0xB5EB,0xB5EC,0x8AD7,0xB5ED,
+0x8AD8,0xB5EE,0x8AD9,0x8ADA,0x8ADB,0x8ADC,0x8ADD,0x8ADE,
+0xB5EF,0x8ADF,0x8AE0,0x8AE1,0x8AE2,0x8AE3,0x8AE4,0x8AE5,
+0x8AE6,0x8AE7,0x8AE8,0x8AE9,0x8AEA,0x8AEB,0x8AEC,0x8AED,
+0x8AEE,0x8AEF,0x8AF0,0x8AF1,0x8AF2,0x8AF3,0x8AF4,0x8AF5,
+0x8AF6,0x8AF7,0x8AF8,0x8AF9,0xB5F0,0xB5F1,0x8AFA,0x8AFB,
+0xB5F2,0x8AFC,0x8AFD,0xB5F3,0xB5F4,0x8AFE,0x8B41,0x8B42,
+0x8B43,0x8B44,0x8B45,0x8B46,0xB5F5,0xB5F6,0x8B47,0xB5F7,
+0xB5F8,0xB5F9,0xB5FA,0x8B48,0x8B49,0x8B4A,0x8B4B,0x8B4C,
+0xB5FB,0xB5FC,0x8B4D,0x8B4E,0xB5FD,0x8B4F,0x8B50,0x8B51,
+0xB5FE,0x8B52,0x8B53,0x8B54,0x8B55,0x8B56,0x8B57,0x8B58,
+0xB6A1,0xB6A2,0x8B59,0xB6A3,0xB6A4,0xB6A5,0x8B5A,0x8B61,
+0x8B62,0x8B63,0x8B64,0xB6A6,0xB6A7,0xB6A8,0x8B65,0x8B66,
+0xB6A9,0x8B67,0x8B68,0x8B69,0xB6AA,0x8B6A,0x8B6B,0x8B6C,
+0x8B6D,0x8B6E,0x8B6F,0x8B70,0xB6AB,0xB6AC,0x8B71,0xB6AD,
+0xB6AE,0xB6AF,0x8B72,0x8B73,0x8B74,0x8B75,0x8B76,0x8B77,
+0x8B78,0x8B79,0x8B7A,0x8B81,0x8B82,0x8B83,0x8B84,0x8B85,
+0x8B86,0x8B87,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0x8B8D,
+0x8B8E,0x8B8F,0x8B90,0x8B91,0x8B92,0x8B93,0x8B94,0x8B95,
+0x8B96,0x8B97,0x8B98,0x8B99,0x8B9A,0x8B9B,0x8B9C,0x8B9D,
+0x8B9E,0x8B9F,0x8BA0,0x8BA1,0x8BA2,0x8BA3,0x8BA4,0x8BA5,
+0x8BA6,0x8BA7,0x8BA8,0x8BA9,0x8BAA,0x8BAB,0x8BAC,0x8BAD,
+0x8BAE,0x8BAF,0x8BB0,0x8BB1,0x8BB2,0x8BB3,0x8BB4,0x8BB5,
+0xB6B0,0xB6B1,0x8BB6,0x8BB7,0xB6B2,0x8BB8,0x8BB9,0x8BBA,
+0xB6B3,0x8BBB,0xB6B4,0xB6B5,0x8BBC,0x8BBD,0x8BBE,0x8BBF,
+0xB6B6,0xB6B7,0x8BC0,0xB6B8,0xB6B9,0xB6BA,0x8BC1,0x8BC2,
+0x8BC3,0x8BC4,0x8BC5,0xB6BB,0xB6BC,0xB6BD,0x8BC6,0x8BC7,
+0xB6BE,0x8BC8,0x8BC9,0x8BCA,0xB6BF,0x8BCB,0x8BCC,0x8BCD,
+0x8BCE,0x8BCF,0x8BD0,0x8BD1,0xB6C0,0xB6C1,0x8BD2,0xB6C2,
+0xB6C3,0xB6C4,0x8BD3,0x8BD4,0x8BD5,0x8BD6,0x8BD7,0x8BD8,
+0xB6C5,0x8BD9,0x8BDA,0x8BDB,0x8BDC,0x8BDD,0x8BDE,0x8BDF,
+0x8BE0,0x8BE1,0x8BE2,0x8BE3,0x8BE4,0x8BE5,0x8BE6,0x8BE7,
+0x8BE8,0x8BE9,0x8BEA,0x8BEB,0xB6C6,0x8BEC,0x8BED,0x8BEE,
+0x8BEF,0x8BF0,0x8BF1,0x8BF2,0x8BF3,0x8BF4,0x8BF5,0x8BF6,
+0x8BF7,0x8BF8,0x8BF9,0x8BFA,0x8BFB,0x8BFC,0x8BFD,0x8BFE,
+0x8C41,0x8C42,0x8C43,0x8C44,0x8C45,0x8C46,0x8C47,0x8C48,
+0x8C49,0x8C4A,0x8C4B,0x8C4C,0x8C4D,0x8C4E,0x8C4F,0x8C50,
+0xB6C7,0xB6C8,0x8C51,0x8C52,0xB6C9,0x8C53,0x8C54,0x8C55,
+0xB6CA,0x8C56,0x8C57,0x8C58,0x8C59,0x8C5A,0x8C61,0x8C62,
+0x8C63,0x8C64,0x8C65,0x8C66,0x8C67,0xB6CB,0x8C68,0x8C69,
+0x8C6A,0x8C6B,0x8C6C,0x8C6D,0xB6CC,0x8C6E,0x8C6F,0x8C70,
+0x8C71,0x8C72,0x8C73,0x8C74,0xB6CD,0x8C75,0x8C76,0x8C77,
+0x8C78,0x8C79,0x8C7A,0x8C81,0x8C82,0x8C83,0x8C84,0x8C85,
+0x8C86,0x8C87,0x8C88,0x8C89,0x8C8A,0x8C8B,0x8C8C,0x8C8D,
+0xB6CE,0x8C8E,0x8C8F,0x8C90,0x8C91,0x8C92,0x8C93,0x8C94,
+0x8C95,0x8C96,0x8C97,0x8C98,0x8C99,0x8C9A,0x8C9B,0x8C9C,
+0x8C9D,0x8C9E,0x8C9F,0x8CA0,0x8CA1,0x8CA2,0x8CA3,0x8CA4,
+0x8CA5,0x8CA6,0x8CA7,0x8CA8,0xB6CF,0x8CA9,0x8CAA,0x8CAB,
+0xB6D0,0x8CAC,0x8CAD,0x8CAE,0x8CAF,0x8CB0,0x8CB1,0x8CB2,
+0x8CB3,0x8CB4,0x8CB5,0x8CB6,0x8CB7,0x8CB8,0x8CB9,0x8CBA,
+0x8CBB,0x8CBC,0x8CBD,0x8CBE,0x8CBF,0x8CC0,0x8CC1,0x8CC2,
+0x8CC3,0x8CC4,0x8CC5,0x8CC6,0x8CC7,0x8CC8,0x8CC9,0x8CCA,
+0x8CCB,0x8CCC,0x8CCD,0x8CCE,0x8CCF,0x8CD0,0x8CD1,0x8CD2,
+0x8CD3,0x8CD4,0x8CD5,0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,
+0x8CDB,0x8CDC,0x8CDD,0x8CDE,0xB6D1,0xB6D2,0x8CDF,0x8CE0,
+0xB6D3,0x8CE1,0x8CE2,0x8CE3,0xB6D4,0x8CE4,0x8CE5,0x8CE6,
+0x8CE7,0x8CE8,0x8CE9,0xB6D5,0xB6D6,0x8CEA,0x8CEB,0x8CEC,
+0x8CED,0xB6D7,0x8CEE,0x8CEF,0x8CF0,0x8CF1,0x8CF2,0x8CF3,
+0x8CF4,0x8CF5,0x8CF6,0x8CF7,0x8CF8,0x8CF9,0x8CFA,0x8CFB,
+0x8CFC,0x8CFD,0x8CFE,0x8D41,0x8D42,0x8D43,0x8D44,0x8D45,
+0x8D46,0x8D47,0x8D48,0x8D49,0x8D4A,0x8D4B,0x8D4C,0x8D4D,
+0x8D4E,0x8D4F,0x8D50,0x8D51,0xB6D8,0x8D52,0x8D53,0x8D54,
+0x8D55,0x8D56,0x8D57,0x8D58,0x8D59,0x8D5A,0x8D61,0x8D62,
+0x8D63,0x8D64,0x8D65,0x8D66,0x8D67,0x8D68,0x8D69,0x8D6A,
+0x8D6B,0x8D6C,0x8D6D,0x8D6E,0x8D6F,0x8D70,0x8D71,0x8D72,
+0xB6D9,0x8D73,0x8D74,0x8D75,0xB6DA,0x8D76,0x8D77,0x8D78,
+0xB6DB,0x8D79,0x8D7A,0x8D81,0x8D82,0x8D83,0x8D84,0x8D85,
+0xB6DC,0xB6DD,0x8D86,0x8D87,0x8D88,0xB6DE,0x8D89,0x8D8A,
+0x8D8B,0x8D8C,0x8D8D,0x8D8E,0x8D8F,0x8D90,0x8D91,0x8D92,
+0x8D93,0x8D94,0x8D95,0x8D96,0x8D97,0x8D98,0x8D99,0x8D9A,
+0x8D9B,0x8D9C,0x8D9D,0x8D9E,0x8D9F,0x8DA0,0x8DA1,0x8DA2,
+0x8DA3,0x8DA4,0x8DA5,0x8DA6,0x8DA7,0x8DA8,0x8DA9,0x8DAA,
+0xB6DF,0xB6E0,0x8DAB,0x8DAC,0xB6E1,0x8DAD,0x8DAE,0xB6E2,
+0xB6E3,0x8DAF,0x8DB0,0x8DB1,0x8DB2,0x8DB3,0x8DB4,0x8DB5,
+0xB6E4,0xB6E5,0x8DB6,0xB6E6,0x8DB7,0x8DB8,0x8DB9,0x8DBA,
+0x8DBB,0x8DBC,0x8DBD,0x8DBE,0xB6E7,0x8DBF,0x8DC0,0x8DC1,
+0xB6E8,0x8DC2,0x8DC3,0x8DC4,0xB6E9,0x8DC5,0x8DC6,0x8DC7,
+0x8DC8,0x8DC9,0x8DCA,0x8DCB,0xB6EA,0xB6EB,0x8DCC,0x8DCD,
+0x8DCE,0x8DCF,0x8DD0,0x8DD1,0x8DD2,0x8DD3,0x8DD4,0x8DD5,
+0xB6EC,0x8DD6,0x8DD7,0x8DD8,0xB6ED,0x8DD9,0x8DDA,0x8DDB,
+0xB6EE,0x8DDC,0x8DDD,0x8DDE,0x8DDF,0x8DE0,0x8DE1,0x8DE2,
+0xB6EF,0xB6F0,0x8DE3,0xB6F1,0x8DE4,0xB6F2,0x8DE5,0x8DE6,
+0x8DE7,0x8DE8,0x8DE9,0x8DEA,0xB6F3,0xB6F4,0x8DEB,0x8DEC,
+0xB6F5,0x8DED,0x8DEE,0x8DEF,0xB6F6,0x8DF0,0x8DF1,0x8DF2,
+0x8DF3,0x8DF4,0x8DF5,0x8DF6,0xB6F7,0xB6F8,0x8DF7,0xB6F9,
+0xB6FA,0xB6FB,0xB6FC,0x8DF8,0x8DF9,0x8DFA,0xB6FD,0xB6FE,
+0xB7A1,0xB7A2,0x8DFB,0x8DFC,0xB7A3,0x8DFD,0x8DFE,0x8E41,
+0xB7A4,0x8E42,0x8E43,0x8E44,0x8E45,0x8E46,0x8E47,0x8E48,
+0xB7A5,0xB7A6,0x8E49,0xB7A7,0xB7A8,0xB7A9,0x8E4A,0x8E4B,
+0x8E4C,0x8E4D,0x8E4E,0x8E4F,0xB7AA,0xB7AB,0x8E50,0x8E51,
+0xB7AC,0x8E52,0x8E53,0x8E54,0x8E55,0x8E56,0x8E57,0x8E58,
+0x8E59,0x8E5A,0x8E61,0x8E62,0x8E63,0x8E64,0x8E65,0xB7AD,
+0x8E66,0xB7AE,0x8E67,0x8E68,0x8E69,0x8E6A,0x8E6B,0x8E6C,
+0x8E6D,0x8E6E,0x8E6F,0x8E70,0x8E71,0x8E72,0x8E73,0x8E74,
+0x8E75,0x8E76,0x8E77,0x8E78,0x8E79,0x8E7A,0x8E81,0x8E82,
+0x8E83,0x8E84,0x8E85,0x8E86,0x8E87,0x8E88,0x8E89,0x8E8A,
+0x8E8B,0x8E8C,0x8E8D,0x8E8E,0xB7AF,0xB7B0,0x8E8F,0x8E90,
+0xB7B1,0x8E91,0x8E92,0x8E93,0xB7B2,0x8E94,0x8E95,0x8E96,
+0x8E97,0x8E98,0x8E99,0x8E9A,0xB7B3,0xB7B4,0x8E9B,0xB7B5,
+0xB7B6,0xB7B7,0x8E9C,0x8E9D,0x8E9E,0x8E9F,0x8EA0,0xB7B8,
+0xB7B9,0xB7BA,0x8EA1,0x8EA2,0xB7BB,0x8EA3,0x8EA4,0x8EA5,
+0xB7BC,0x8EA6,0x8EA7,0x8EA8,0x8EA9,0x8EAA,0x8EAB,0x8EAC,
+0xB7BD,0xB7BE,0x8EAD,0xB7BF,0x8EAE,0xB7C0,0x8EAF,0x8EB0,
+0x8EB1,0x8EB2,0x8EB3,0x8EB4,0xB7C1,0xB7C2,0x8EB5,0x8EB6,
+0xB7C3,0x8EB7,0x8EB8,0x8EB9,0xB7C4,0x8EBA,0x8EBB,0x8EBC,
+0x8EBD,0x8EBE,0x8EBF,0x8EC0,0xB7C5,0xB7C6,0x8EC1,0xB7C7,
+0xB7C8,0xB7C9,0x8EC2,0x8EC3,0x8EC4,0x8EC5,0x8EC6,0x8EC7,
+0xB7CA,0x8EC8,0x8EC9,0x8ECA,0xB7CB,0x8ECB,0x8ECC,0x8ECD,
+0x8ECE,0x8ECF,0x8ED0,0x8ED1,0x8ED2,0x8ED3,0x8ED4,0x8ED5,
+0x8ED6,0xB7CC,0x8ED7,0xB7CD,0x8ED8,0x8ED9,0x8EDA,0x8EDB,
+0x8EDC,0x8EDD,0x8EDE,0x8EDF,0xB7CE,0xB7CF,0x8EE0,0x8EE1,
+0xB7D0,0x8EE2,0x8EE3,0x8EE4,0xB7D1,0x8EE5,0x8EE6,0x8EE7,
+0x8EE8,0x8EE9,0x8EEA,0x8EEB,0xB7D2,0xB7D3,0x8EEC,0xB7D4,
+0x8EED,0xB7D5,0x8EEE,0x8EEF,0x8EF0,0x8EF1,0x8EF2,0x8EF3,
+0xB7D6,0x8EF4,0x8EF5,0x8EF6,0xB7D7,0x8EF7,0x8EF8,0x8EF9,
+0x8EFA,0x8EFB,0x8EFC,0x8EFD,0x8EFE,0x8F41,0x8F42,0x8F43,
+0x8F44,0x8F45,0x8F46,0x8F47,0x8F48,0xB7D8,0x8F49,0x8F4A,
+0x8F4B,0x8F4C,0x8F4D,0x8F4E,0x8F4F,0x8F50,0x8F51,0x8F52,
+0x8F53,0x8F54,0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A,
+0x8F61,0x8F62,0x8F63,0x8F64,0x8F65,0x8F66,0x8F67,0x8F68,
+0xB7D9,0x8F69,0x8F6A,0x8F6B,0x8F6C,0x8F6D,0x8F6E,0x8F6F,
+0xB7DA,0x8F70,0x8F71,0x8F72,0xB7DB,0x8F73,0x8F74,0x8F75,
+0xB7DC,0x8F76,0x8F77,0x8F78,0x8F79,0x8F7A,0x8F81,0x8F82,
+0xB7DD,0xB7DE,0x8F83,0xB7DF,0x8F84,0xB7E0,0x8F85,0x8F86,
+0x8F87,0x8F88,0x8F89,0x8F8A,0xB7E1,0x8F8B,0x8F8C,0x8F8D,
+0xB7E2,0x8F8E,0x8F8F,0x8F90,0xB7E3,0x8F91,0x8F92,0x8F93,
+0x8F94,0x8F95,0x8F96,0x8F97,0x8F98,0xB7E4,0x8F99,0xB7E5,
+0x8F9A,0xB7E6,0x8F9B,0x8F9C,0x8F9D,0x8F9E,0x8F9F,0x8FA0,
+0xB7E7,0xB7E8,0x8FA1,0x8FA2,0xB7E9,0x8FA3,0x8FA4,0x8FA5,
+0xB7EA,0x8FA6,0x8FA7,0x8FA8,0x8FA9,0x8FAA,0x8FAB,0x8FAC,
+0xB7EB,0xB7EC,0x8FAD,0xB7ED,0x8FAE,0xB7EE,0x8FAF,0x8FB0,
+0x8FB1,0x8FB2,0x8FB3,0x8FB4,0xB7EF,0x8FB5,0x8FB6,0x8FB7,
+0x8FB8,0x8FB9,0x8FBA,0x8FBB,0x8FBC,0x8FBD,0x8FBE,0x8FBF,
+0x8FC0,0x8FC1,0x8FC2,0x8FC3,0x8FC4,0x8FC5,0x8FC6,0x8FC7,
+0xB7F0,0x8FC8,0x8FC9,0x8FCA,0x8FCB,0x8FCC,0x8FCD,0x8FCE,
+0xB7F1,0x8FCF,0x8FD0,0x8FD1,0x8FD2,0x8FD3,0x8FD4,0x8FD5,
+0x8FD6,0x8FD7,0x8FD8,0x8FD9,0x8FDA,0x8FDB,0x8FDC,0x8FDD,
+0x8FDE,0x8FDF,0x8FE0,0x8FE1,0x8FE2,0x8FE3,0x8FE4,0x8FE5,
+0x8FE6,0x8FE7,0x8FE8,0x8FE9,0xB7F2,0xB7F3,0x8FEA,0x8FEB,
+0xB7F4,0x8FEC,0x8FED,0x8FEE,0xB7F5,0x8FEF,0x8FF0,0x8FF1,
+0x8FF2,0x8FF3,0x8FF4,0x8FF5,0xB7F6,0x8FF6,0x8FF7,0xB7F7,
+0x8FF8,0xB7F8,0x8FF9,0x8FFA,0x8FFB,0x8FFC,0x8FFD,0x8FFE,
+0xB7F9,0xB7FA,0x9041,0x9042,0xB7FB,0x9043,0x9044,0x9045,
+0xB7FC,0x9046,0x9047,0x9048,0x9049,0x904A,0x904B,0x904C,
+0xB7FD,0xB7FE,0x904D,0xB8A1,0x904E,0xB8A2,0x904F,0x9050,
+0x9051,0x9052,0x9053,0x9054,0xB8A3,0xB8A4,0x9055,0x9056,
+0xB8A5,0x9057,0x9058,0x9059,0xB8A6,0x905A,0x9061,0x9062,
+0x9063,0x9064,0x9065,0x9066,0xB8A7,0xB8A8,0x9067,0xB8A9,
+0x9068,0xB8AA,0xB8AB,0x9069,0x906A,0xB8AC,0xB8AD,0x906B,
+0x906C,0x906D,0x906E,0x906F,0x9070,0x9071,0x9072,0x9073,
+0x9074,0x9075,0x9076,0x9077,0x9078,0x9079,0x907A,0x9081,
+0x9082,0x9083,0x9084,0x9085,0x9086,0x9087,0x9088,0x9089,
+0x908A,0x908B,0x908C,0x908D,0xB8AE,0xB8AF,0x908E,0x908F,
+0xB8B0,0x9090,0x9091,0x9092,0xB8B1,0x9093,0x9094,0x9095,
+0x9096,0x9097,0x9098,0x9099,0xB8B2,0xB8B3,0x909A,0xB8B4,
+0x909B,0xB8B5,0x909C,0x909D,0x909E,0x909F,0x90A0,0x90A1,
+0xB8B6,0xB8B7,0x90A2,0x90A3,0xB8B8,0x90A4,0xB8B9,0xB8BA,
+0xB8BB,0xB8BC,0xB8BD,0x90A5,0x90A6,0x90A7,0x90A8,0x90A9,
+0xB8BE,0xB8BF,0x90AA,0xB8C0,0x90AB,0xB8C1,0xB8C2,0x90AC,
+0x90AD,0xB8C3,0x90AE,0xB8C4,0xB8C5,0xB8C6,0x90AF,0x90B0,
+0xB8C7,0x90B1,0x90B2,0x90B3,0xB8C8,0x90B4,0x90B5,0x90B6,
+0x90B7,0x90B8,0x90B9,0x90BA,0xB8C9,0xB8CA,0x90BB,0xB8CB,
+0xB8CC,0xB8CD,0xB8CE,0x90BC,0x90BD,0x90BE,0x90BF,0x90C0,
+0xB8CF,0xB8D0,0x90C1,0x90C2,0x90C3,0x90C4,0x90C5,0x90C6,
+0xB8D1,0x90C7,0x90C8,0x90C9,0x90CA,0x90CB,0x90CC,0x90CD,
+0x90CE,0x90CF,0x90D0,0x90D1,0x90D2,0xB8D2,0x90D3,0x90D4,
+0x90D5,0x90D6,0x90D7,0x90D8,0x90D9,0x90DA,0x90DB,0x90DC,
+0x90DD,0x90DE,0x90DF,0x90E0,0x90E1,0x90E2,0x90E3,0x90E4,
+0x90E5,0x90E6,0x90E7,0x90E8,0x90E9,0x90EA,0x90EB,0x90EC,
+0x90ED,0x90EE,0x90EF,0x90F0,0x90F1,0x90F2,0x90F3,0x90F4,
+0xB8D3,0xB8D4,0x90F5,0x90F6,0xB8D5,0x90F7,0x90F8,0x90F9,
+0xB8D6,0x90FA,0xB8D7,0x90FB,0x90FC,0x90FD,0x90FE,0x9141,
+0xB8D8,0xB8D9,0x9142,0xB8DA,0x9143,0xB8DB,0xB8DC,0x9144,
+0x9145,0x9146,0x9147,0xB8DD,0xB8DE,0xB8DF,0x9148,0x9149,
+0xB8E0,0x914A,0x914B,0x914C,0xB8E1,0x914D,0x914E,0x914F,
+0x9150,0x9151,0x9152,0x9153,0xB8E2,0xB8E3,0x9154,0xB8E4,
+0xB8E5,0xB8E6,0x9155,0x9156,0x9157,0x9158,0x9159,0x915A,
+0xB8E7,0xB8E8,0x9161,0x9162,0xB8E9,0x9163,0x9164,0x9165,
+0xB8EA,0x9166,0x9167,0x9168,0x9169,0x916A,0x916B,0x916C,
+0x916D,0x916E,0x916F,0xB8EB,0xB8EC,0xB8ED,0x9170,0xB8EE,
+0x9171,0x9172,0x9173,0x9174,0xB8EF,0x9175,0x9176,0x9177,
+0x9178,0x9179,0x917A,0x9181,0x9182,0x9183,0x9184,0x9185,
+0x9186,0x9187,0x9188,0x9189,0x918A,0x918B,0x918C,0x918D,
+0x918E,0x918F,0x9190,0x9191,0x9192,0x9193,0x9194,0x9195,
+0xB8F0,0xB8F1,0x9196,0xB8F2,0xB8F3,0x9197,0x9198,0x9199,
+0xB8F4,0x919A,0xB8F5,0x919B,0x919C,0x919D,0x919E,0x919F,
+0xB8F6,0xB8F7,0x91A0,0xB8F8,0x91A1,0xB8F9,0x91A2,0x91A3,
+0x91A4,0x91A5,0x91A6,0x91A7,0xB8FA,0x91A8,0x91A9,0x91AA,
+0xB8FB,0x91AB,0x91AC,0x91AD,0x91AE,0x91AF,0x91B0,0x91B1,
+0x91B2,0x91B3,0x91B4,0x91B5,0x91B6,0x91B7,0x91B8,0x91B9,
+0xB8FC,0xB8FD,0x91BA,0x91BB,0x91BC,0x91BD,0x91BE,0x91BF,
+0x91C0,0x91C1,0x91C2,0x91C3,0x91C4,0x91C5,0x91C6,0x91C7,
+0x91C8,0x91C9,0x91CA,0x91CB,0x91CC,0x91CD,0x91CE,0x91CF,
+0x91D0,0x91D1,0x91D2,0x91D3,0x91D4,0x91D5,0x91D6,0x91D7,
+0x91D8,0x91D9,0x91DA,0x91DB,0xB8FE,0x91DC,0x91DD,0x91DE,
+0xB9A1,0x91DF,0x91E0,0x91E1,0xB9A2,0x91E2,0x91E3,0x91E4,
+0x91E5,0x91E6,0x91E7,0x91E8,0x91E9,0xB9A3,0x91EA,0xB9A4,
+0x91EB,0xB9A5,0x91EC,0x91ED,0x91EE,0x91EF,0x91F0,0x91F1,
+0xB9A6,0x91F2,0x91F3,0x91F4,0xB9A7,0x91F5,0x91F6,0x91F7,
+0xB9A8,0x91F8,0x91F9,0x91FA,0x91FB,0x91FC,0x91FD,0x91FE,
+0x9241,0xB9A9,0x9242,0xB9AA,0x9243,0x9244,0x9245,0x9246,
+0x9247,0x9248,0x9249,0x924A,0xB9AB,0xB9AC,0xB9AD,0x924B,
+0xB9AE,0x924C,0x924D,0xB9AF,0xB9B0,0xB9B1,0xB9B2,0x924E,
+0x924F,0x9250,0x9251,0x9252,0xB9B3,0xB9B4,0x9253,0xB9B5,
+0x9254,0xB9B6,0x9255,0x9256,0x9257,0xB9B7,0x9258,0xB9B8,
+0xB9B9,0x9259,0x925A,0x9261,0xB9BA,0x9262,0x9263,0x9264,
+0xB9BB,0x9265,0x9266,0x9267,0x9268,0x9269,0x926A,0x926B,
+0x926C,0xB9BC,0x926D,0xB9BD,0x926E,0x926F,0x9270,0x9271,
+0x9272,0x9273,0x9274,0x9275,0xB9BE,0x9276,0x9277,0x9278,
+0x9279,0x927A,0x9281,0x9282,0x9283,0x9284,0x9285,0x9286,
+0x9287,0x9288,0x9289,0x928A,0x928B,0x928C,0x928D,0x928E,
+0x928F,0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296,
+0xB9BF,0x9297,0x9298,0x9299,0xB9C0,0x929A,0x929B,0x929C,
+0xB9C1,0x929D,0x929E,0x929F,0x92A0,0x92A1,0x92A2,0x92A3,
+0x92A4,0x92A5,0x92A6,0x92A7,0x92A8,0x92A9,0x92AA,0x92AB,
+0x92AC,0x92AD,0x92AE,0x92AF,0xB9C2,0x92B0,0x92B1,0x92B2,
+0xB9C3,0x92B3,0x92B4,0x92B5,0xB9C4,0x92B6,0x92B7,0x92B8,
+0x92B9,0x92BA,0x92BB,0x92BC,0xB9C5,0x92BD,0x92BE,0xB9C6,
+0x92BF,0x92C0,0x92C1,0x92C2,0x92C3,0x92C4,0x92C5,0x92C6,
+0xB9C7,0x92C7,0x92C8,0x92C9,0xB9C8,0x92CA,0x92CB,0x92CC,
+0xB9C9,0x92CD,0x92CE,0x92CF,0x92D0,0x92D1,0x92D2,0x92D3,
+0xB9CA,0x92D4,0x92D5,0xB9CB,0x92D6,0x92D7,0x92D8,0x92D9,
+0x92DA,0x92DB,0x92DC,0x92DD,0x92DE,0x92DF,0x92E0,0x92E1,
+0x92E2,0x92E3,0x92E4,0x92E5,0x92E6,0x92E7,0x92E8,0x92E9,
+0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF,0x92F0,0x92F1,
+0x92F2,0x92F3,0x92F4,0x92F5,0x92F6,0x92F7,0x92F8,0x92F9,
+0xB9CC,0xB9CD,0x92FA,0x92FB,0xB9CE,0x92FC,0x92FD,0xB9CF,
+0xB9D0,0x92FE,0xB9D1,0x9341,0x9342,0x9343,0x9344,0x9345,
+0xB9D2,0xB9D3,0x9346,0xB9D4,0xB9D5,0xB9D6,0x9347,0xB9D7,
+0x9348,0xB9D8,0x9349,0x934A,0xB9D9,0xB9DA,0xB9DB,0xB9DC,
+0xB9DD,0x934B,0x934C,0xB9DE,0xB9DF,0xB9E0,0xB9E1,0xB9E2,
+0x934D,0x934E,0x934F,0x9350,0xB9E3,0xB9E4,0x9351,0xB9E5,
+0x9352,0xB9E6,0x9353,0x9354,0x9355,0xB9E7,0x9356,0x9357,
+0xB9E8,0xB9E9,0x9358,0x9359,0xB9EA,0x935A,0x9361,0x9362,
+0xB9EB,0x9363,0x9364,0x9365,0x9366,0x9367,0x9368,0x9369,
+0xB9EC,0xB9ED,0x936A,0xB9EE,0xB9EF,0xB9F0,0x936B,0x936C,
+0x936D,0xB9F1,0x936E,0x936F,0xB9F2,0xB9F3,0x9370,0x9371,
+0xB9F4,0x9372,0x9373,0x9374,0x9375,0x9376,0x9377,0x9378,
+0x9379,0x937A,0x9381,0x9382,0x9383,0xB9F5,0x9384,0x9385,
+0x9386,0x9387,0x9388,0x9389,0x938A,0x938B,0x938C,0x938D,
+0x938E,0x938F,0x9390,0x9391,0x9392,0x9393,0x9394,0x9395,
+0x9396,0x9397,0x9398,0x9399,0x939A,0x939B,0x939C,0x939D,
+0x939E,0x939F,0x93A0,0x93A1,0x93A2,0x93A3,0x93A4,0x93A5,
+0x93A6,0x93A7,0x93A8,0x93A9,0xB9F6,0xB9F7,0x93AA,0x93AB,
+0xB9F8,0x93AC,0x93AD,0xB9F9,0xB9FA,0x93AE,0xB9FB,0x93AF,
+0x93B0,0x93B1,0x93B2,0x93B3,0xB9FC,0xB9FD,0x93B4,0xB9FE,
+0x93B5,0xBAA1,0xBAA2,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,
+0xBAA3,0xBAA4,0x93BB,0x93BC,0xBAA5,0x93BD,0x93BE,0xBAA6,
+0xBAA7,0x93BF,0x93C0,0x93C1,0x93C2,0x93C3,0x93C4,0x93C5,
+0xBAA8,0xBAA9,0x93C6,0xBAAA,0xBAAB,0xBAAC,0x93C7,0x93C8,
+0x93C9,0x93CA,0x93CB,0x93CC,0xBAAD,0xBAAE,0x93CD,0x93CE,
+0xBAAF,0x93CF,0x93D0,0x93D1,0xBAB0,0x93D2,0x93D3,0x93D4,
+0x93D5,0x93D6,0x93D7,0x93D8,0x93D9,0xBAB1,0x93DA,0xBAB2,
+0xBAB3,0xBAB4,0x93DB,0x93DC,0x93DD,0xBAB5,0x93DE,0x93DF,
+0xBAB6,0x93E0,0x93E1,0x93E2,0xBAB7,0x93E3,0x93E4,0x93E5,
+0x93E6,0x93E7,0x93E8,0x93E9,0x93EA,0x93EB,0x93EC,0x93ED,
+0x93EE,0x93EF,0x93F0,0x93F1,0x93F2,0x93F3,0x93F4,0x93F5,
+0x93F6,0x93F7,0x93F8,0x93F9,0xBAB8,0xBAB9,0xBABA,0x93FA,
+0xBABB,0x93FB,0x93FC,0x93FD,0xBABC,0x93FE,0x9441,0x9442,
+0x9443,0x9444,0x9445,0x9446,0xBABD,0xBABE,0x9447,0xBABF,
+0x9448,0xBAC0,0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,
+0xBAC1,0x944F,0x9450,0x9451,0xBAC2,0x9452,0x9453,0x9454,
+0x9455,0x9456,0x9457,0x9458,0x9459,0x945A,0x9461,0x9462,
+0x9463,0x9464,0x9465,0x9466,0xBAC3,0x9467,0x9468,0x9469,
+0x946A,0x946B,0x946C,0x946D,0xBAC4,0x946E,0x946F,0x9470,
+0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477,0x9478,
+0x9479,0x947A,0x9481,0x9482,0x9483,0x9484,0x9485,0x9486,
+0xBAC5,0x9487,0x9488,0x9489,0x948A,0x948B,0x948C,0x948D,
+0xBAC6,0xBAC7,0x948E,0x948F,0xBAC8,0x9490,0x9491,0x9492,
+0xBAC9,0x9493,0x9494,0x9495,0x9496,0x9497,0x9498,0x9499,
+0xBACA,0xBACB,0x949A,0x949B,0x949C,0x949D,0x949E,0x949F,
+0x94A0,0x94A1,0x94A2,0x94A3,0xBACC,0x94A4,0x94A5,0x94A6,
+0xBACD,0x94A7,0x94A8,0x94A9,0x94AA,0x94AB,0x94AC,0x94AD,
+0x94AE,0x94AF,0x94B0,0x94B1,0x94B2,0x94B3,0x94B4,0x94B5,
+0x94B6,0x94B7,0x94B8,0x94B9,0x94BA,0x94BB,0x94BC,0x94BD,
+0xBACE,0xBACF,0x94BE,0x94BF,0xBAD0,0x94C0,0x94C1,0xBAD1,
+0xBAD2,0xBAD3,0xBAD4,0x94C2,0x94C3,0x94C4,0x94C5,0x94C6,
+0xBAD5,0xBAD6,0x94C7,0xBAD7,0x94C8,0xBAD8,0x94C9,0x94CA,
+0x94CB,0xBAD9,0xBADA,0x94CC,0xBADB,0x94CD,0x94CE,0x94CF,
+0x94D0,0x94D1,0x94D2,0x94D3,0xBADC,0x94D4,0x94D5,0x94D6,
+0x94D7,0x94D8,0x94D9,0x94DA,0x94DB,0x94DC,0x94DD,0x94DE,
+0xBADD,0x94DF,0x94E0,0x94E1,0x94E2,0x94E3,0x94E4,0x94E5,
+0xBADE,0x94E6,0x94E7,0x94E8,0x94E9,0x94EA,0x94EB,0x94EC,
+0x94ED,0x94EE,0x94EF,0x94F0,0x94F1,0x94F2,0x94F3,0x94F4,
+0x94F5,0x94F6,0x94F7,0x94F8,0x94F9,0x94FA,0x94FB,0x94FC,
+0x94FD,0x94FE,0x9541,0x9542,0xBADF,0xBAE0,0x9543,0x9544,
+0xBAE1,0x9545,0x9546,0x9547,0xBAE2,0x9548,0x9549,0x954A,
+0x954B,0x954C,0x954D,0x954E,0x954F,0x9550,0x9551,0x9552,
+0x9553,0xBAE3,0x9554,0x9555,0x9556,0x9557,0x9558,0x9559,
+0xBAE4,0x955A,0x9561,0x9562,0xBAE5,0x9563,0x9564,0x9565,
+0xBAE6,0x9566,0x9567,0x9568,0x9569,0x956A,0x956B,0x956C,
+0xBAE7,0x956D,0x956E,0xBAE8,0x956F,0xBAE9,0x9570,0x9571,
+0x9572,0x9573,0x9574,0x9575,0xBAEA,0xBAEB,0x9576,0x9577,
+0xBAEC,0x9578,0x9579,0x957A,0xBAED,0x9581,0x9582,0x9583,
+0x9584,0x9585,0x9586,0x9587,0xBAEE,0xBAEF,0x9588,0xBAF0,
+0x9589,0x958A,0x958B,0x958C,0x958D,0x958E,0x958F,0x9590,
+0x9591,0x9592,0x9593,0x9594,0x9595,0x9596,0x9597,0x9598,
+0x9599,0x959A,0x959B,0x959C,0x959D,0x959E,0x959F,0x95A0,
+0x95A1,0x95A2,0x95A3,0x95A4,0x95A5,0x95A6,0x95A7,0x95A8,
+0x95A9,0x95AA,0x95AB,0x95AC,0xBAF1,0xBAF2,0x95AD,0x95AE,
+0xBAF3,0x95AF,0x95B0,0x95B1,0xBAF4,0x95B2,0xBAF5,0x95B3,
+0x95B4,0x95B5,0x95B6,0x95B7,0xBAF6,0xBAF7,0x95B8,0xBAF8,
+0x95B9,0xBAF9,0xBAFA,0xBAFB,0x95BA,0x95BB,0x95BC,0x95BD,
+0xBAFC,0xBAFD,0x95BE,0x95BF,0xBAFE,0x95C0,0x95C1,0x95C2,
+0xBBA1,0x95C3,0xBBA2,0x95C4,0x95C5,0x95C6,0x95C7,0x95C8,
+0xBBA3,0xBBA4,0x95C9,0xBBA5,0xBBA6,0xBBA7,0x95CA,0x95CB,
+0x95CC,0x95CD,0x95CE,0xBBA8,0xBBA9,0xBBAA,0x95CF,0x95D0,
+0xBBAB,0x95D1,0x95D2,0x95D3,0xBBAC,0x95D4,0x95D5,0x95D6,
+0x95D7,0x95D8,0x95D9,0x95DA,0xBBAD,0xBBAE,0x95DB,0xBBAF,
+0xBBB0,0xBBB1,0x95DC,0x95DD,0x95DE,0x95DF,0x95E0,0x95E1,
+0xBBB2,0xBBB3,0x95E2,0x95E3,0x95E4,0x95E5,0x95E6,0x95E7,
+0x95E8,0x95E9,0x95EA,0x95EB,0x95EC,0x95ED,0x95EE,0x95EF,
+0xBBB4,0x95F0,0x95F1,0x95F2,0x95F3,0x95F4,0x95F5,0x95F6,
+0x95F7,0x95F8,0x95F9,0x95FA,0x95FB,0x95FC,0x95FD,0x95FE,
+0x9641,0x9642,0x9643,0x9644,0x9645,0x9646,0x9647,0x9648,
+0x9649,0x964A,0x964B,0x964C,0x964D,0x964E,0x964F,0x9650,
+0x9651,0x9652,0x9653,0x9654,0x9655,0x9656,0x9657,0x9658,
+0xBBB5,0xBBB6,0x9659,0x965A,0xBBB7,0x9661,0x9662,0xBBB8,
+0xBBB9,0x9663,0x9664,0x9665,0x9666,0x9667,0x9668,0x9669,
+0xBBBA,0x966A,0x966B,0xBBBB,0xBBBC,0xBBBD,0x966C,0x966D,
+0x966E,0x966F,0x9670,0x9671,0xBBBE,0x9672,0x9673,0x9674,
+0x9675,0x9676,0x9677,0x9678,0x9679,0x967A,0x9681,0x9682,
+0x9683,0x9684,0x9685,0x9686,0x9687,0x9688,0x9689,0x968A,
+0x968B,0xBBBF,0x968C,0x968D,0x968E,0x968F,0x9690,0x9691,
+0xBBC0,0xBBC1,0x9692,0x9693,0x9694,0x9695,0x9696,0x9697,
+0x9698,0x9699,0x969A,0x969B,0x969C,0x969D,0x969E,0x969F,
+0xBBC2,0xBBC3,0x96A0,0xBBC4,0xBBC5,0xBBC6,0x96A1,0x96A2,
+0x96A3,0x96A4,0x96A5,0x96A6,0x96A7,0x96A8,0x96A9,0x96AA,
+0x96AB,0x96AC,0x96AD,0x96AE,0x96AF,0x96B0,0x96B1,0x96B2,
+0x96B3,0x96B4,0x96B5,0x96B6,0x96B7,0x96B8,0x96B9,0x96BA,
+0x96BB,0x96BC,0x96BD,0x96BE,0x96BF,0x96C0,0x96C1,0x96C2,
+0xBBC7,0xBBC8,0x96C3,0x96C4,0xBBC9,0x96C5,0x96C6,0x96C7,
+0xBBCA,0x96C8,0x96C9,0x96CA,0x96CB,0x96CC,0x96CD,0x96CE,
+0xBBCB,0xBBCC,0x96CF,0x96D0,0x96D1,0xBBCD,0x96D2,0x96D3,
+0x96D4,0x96D5,0x96D6,0x96D7,0x96D8,0x96D9,0x96DA,0x96DB,
+0x96DC,0x96DD,0x96DE,0x96DF,0x96E0,0x96E1,0x96E2,0x96E3,
+0x96E4,0x96E5,0x96E6,0x96E7,0x96E8,0x96E9,0x96EA,0x96EB,
+0x96EC,0x96ED,0x96EE,0x96EF,0x96F0,0x96F1,0x96F2,0x96F3,
+0x96F4,0x96F5,0x96F6,0x96F7,0x96F8,0x96F9,0x96FA,0x96FB,
+0x96FC,0x96FD,0x96FE,0x9741,0x9742,0x9743,0x9744,0x9745,
+0x9746,0x9747,0x9748,0x9749,0x974A,0x974B,0x974C,0x974D,
+0x974E,0x974F,0x9750,0x9751,0xBBCE,0x9752,0x9753,0x9754,
+0x9755,0x9756,0x9757,0x9758,0x9759,0x975A,0x9761,0x9762,
+0x9763,0x9764,0x9765,0x9766,0x9767,0x9768,0x9769,0x976A,
+0x976B,0x976C,0x976D,0x976E,0x976F,0x9770,0x9771,0x9772,
+0xBBCF,0x9773,0x9774,0x9775,0x9776,0x9777,0x9778,0x9779,
+0x977A,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786,0x9787,
+0x9788,0x9789,0x978A,0x978B,0x978C,0xBBD0,0x978D,0x978E,
+0x978F,0x9790,0x9791,0x9792,0xBBD1,0xBBD2,0x9793,0x9794,
+0xBBD3,0x9795,0x9796,0x9797,0xBBD4,0x9798,0x9799,0x979A,
+0x979B,0x979C,0x979D,0x979E,0xBBD5,0x979F,0x97A0,0xBBD6,
+0x97A1,0xBBD7,0x97A2,0x97A3,0x97A4,0x97A5,0x97A6,0x97A7,
+0x97A8,0x97A9,0x97AA,0x97AB,0x97AC,0x97AD,0x97AE,0x97AF,
+0x97B0,0x97B1,0x97B2,0x97B3,0x97B4,0x97B5,0x97B6,0x97B7,
+0x97B8,0x97B9,0x97BA,0x97BB,0x97BC,0x97BD,0x97BE,0x97BF,
+0x97C0,0x97C1,0x97C2,0x97C3,0x97C4,0x97C5,0x97C6,0x97C7,
+0x97C8,0x97C9,0x97CA,0x97CB,0x97CC,0x97CD,0x97CE,0x97CF,
+0x97D0,0x97D1,0x97D2,0x97D3,0x97D4,0x97D5,0x97D6,0x97D7,
+0x97D8,0x97D9,0x97DA,0x97DB,0x97DC,0x97DD,0x97DE,0x97DF,
+0x97E0,0x97E1,0x97E2,0x97E3,0x97E4,0x97E5,0x97E6,0x97E7,
+0x97E8,0x97E9,0x97EA,0x97EB,0x97EC,0x97ED,0x97EE,0x97EF,
+0x97F0,0x97F1,0x97F2,0x97F3,0x97F4,0x97F5,0x97F6,0x97F7,
+0x97F8,0x97F9,0x97FA,0x97FB,0xBBD8,0x97FC,0x97FD,0x97FE,
+0x9841,0x9842,0x9843,0x9844,0x9845,0x9846,0x9847,0x9848,
+0x9849,0x984A,0x984B,0x984C,0x984D,0x984E,0x984F,0x9850,
+0x9851,0xBBD9,0x9852,0x9853,0x9854,0x9855,0x9856,0x9857,
+0xBBDA,0x9858,0x9859,0x985A,0xBBDB,0x9861,0x9862,0x9863,
+0xBBDC,0x9864,0x9865,0x9866,0x9867,0x9868,0x9869,0x986A,
+0xBBDD,0xBBDE,0x986B,0x986C,0x986D,0x986E,0x986F,0x9870,
+0x9871,0x9872,0x9873,0x9874,0x9875,0x9876,0x9877,0x9878,
+0x9879,0x987A,0x9881,0x9882,0x9883,0x9884,0x9885,0x9886,
+0x9887,0x9888,0x9889,0x988A,0x988B,0x988C,0x988D,0x988E,
+0x988F,0x9890,0x9891,0x9892,0x9893,0x9894,0x9895,0x9896,
+0xBBDF,0xBBE0,0x9897,0x9898,0xBBE1,0x9899,0x989A,0x989B,
+0xBBE2,0x989C,0x989D,0x989E,0x989F,0x98A0,0x98A1,0x98A2,
+0xBBE3,0xBBE4,0x98A3,0xBBE5,0x98A4,0xBBE6,0x98A5,0x98A6,
+0x98A7,0x98A8,0x98A9,0x98AA,0xBBE7,0xBBE8,0x98AB,0xBBE9,
+0xBBEA,0x98AC,0x98AD,0xBBEB,0xBBEC,0xBBED,0xBBEE,0x98AE,
+0x98AF,0x98B0,0x98B1,0x98B2,0xBBEF,0xBBF0,0x98B3,0xBBF1,
+0xBBF2,0xBBF3,0x98B4,0x98B5,0x98B6,0xBBF4,0x98B7,0x98B8,
+0xBBF5,0xBBF6,0x98B9,0x98BA,0xBBF7,0x98BB,0x98BC,0x98BD,
+0xBBF8,0x98BE,0x98BF,0x98C0,0x98C1,0x98C2,0x98C3,0x98C4,
+0xBBF9,0xBBFA,0x98C5,0xBBFB,0xBBFC,0xBBFD,0x98C6,0x98C7,
+0x98C8,0x98C9,0x98CA,0x98CB,0xBBFE,0xBCA1,0x98CC,0x98CD,
+0xBCA2,0x98CE,0x98CF,0x98D0,0xBCA3,0x98D1,0x98D2,0x98D3,
+0x98D4,0x98D5,0x98D6,0x98D7,0xBCA4,0xBCA5,0x98D8,0xBCA6,
+0x98D9,0xBCA7,0x98DA,0x98DB,0x98DC,0x98DD,0x98DE,0x98DF,
+0xBCA8,0x98E0,0x98E1,0x98E2,0xBCA9,0x98E3,0x98E4,0x98E5,
+0xBCAA,0x98E6,0x98E7,0x98E8,0x98E9,0x98EA,0x98EB,0x98EC,
+0xBCAB,0x98ED,0x98EE,0x98EF,0x98F0,0xBCAC,0x98F1,0x98F2,
+0x98F3,0x98F4,0x98F5,0x98F6,0xBCAD,0xBCAE,0xBCAF,0xBCB0,
+0xBCB1,0x98F7,0x98F8,0xBCB2,0xBCB3,0x98F9,0xBCB4,0xBCB5,
+0x98FA,0x98FB,0x98FC,0x98FD,0xBCB6,0xBCB7,0x98FE,0xBCB8,
+0xBCB9,0xBCBA,0x9941,0x9942,0x9943,0x9944,0xBCBB,0x9945,
+0xBCBC,0xBCBD,0x9946,0x9947,0xBCBE,0x9948,0x9949,0x994A,
+0xBCBF,0x994B,0x994C,0x994D,0x994E,0x994F,0x9950,0x9951,
+0xBCC0,0xBCC1,0x9952,0xBCC2,0xBCC3,0xBCC4,0x9953,0x9954,
+0x9955,0x9956,0x9957,0x9958,0xBCC5,0xBCC6,0x9959,0x995A,
+0xBCC7,0x9961,0x9962,0x9963,0xBCC8,0x9964,0x9965,0x9966,
+0x9967,0x9968,0x9969,0x996A,0xBCC9,0xBCCA,0x996B,0xBCCB,
+0xBCCC,0xBCCD,0x996C,0x996D,0x996E,0x996F,0x9970,0x9971,
+0xBCCE,0x9972,0x9973,0x9974,0xBCCF,0x9975,0x9976,0x9977,
+0xBCD0,0x9978,0x9979,0x997A,0x9981,0x9982,0x9983,0x9984,
+0x9985,0x9986,0x9987,0x9988,0x9989,0xBCD1,0x998A,0x998B,
+0x998C,0x998D,0x998E,0x998F,0xBCD2,0xBCD3,0xBCD4,0x9990,
+0xBCD5,0x9991,0x9992,0x9993,0xBCD6,0x9994,0xBCD7,0x9995,
+0x9996,0x9997,0x9998,0x9999,0xBCD8,0xBCD9,0x999A,0xBCDA,
+0x999B,0xBCDB,0x999C,0x999D,0x999E,0xBCDC,0x999F,0x99A0,
+0xBCDD,0xBCDE,0x99A1,0x99A2,0xBCDF,0x99A3,0x99A4,0x99A5,
+0xBCE0,0x99A6,0x99A7,0x99A8,0x99A9,0x99AA,0x99AB,0x99AC,
+0x99AD,0x99AE,0x99AF,0x99B0,0x99B1,0xBCE1,0x99B2,0x99B3,
+0x99B4,0x99B5,0x99B6,0x99B7,0xBCE2,0x99B8,0x99B9,0x99BA,
+0xBCE3,0x99BB,0x99BC,0x99BD,0xBCE4,0x99BE,0x99BF,0x99C0,
+0x99C1,0x99C2,0x99C3,0x99C4,0xBCE5,0x99C5,0x99C6,0xBCE6,
+0xBCE7,0x99C7,0x99C8,0x99C9,0x99CA,0x99CB,0x99CC,0x99CD,
+0xBCE8,0x99CE,0x99CF,0x99D0,0xBCE9,0x99D1,0x99D2,0x99D3,
+0xBCEA,0x99D4,0x99D5,0x99D6,0x99D7,0x99D8,0x99D9,0x99DA,
+0xBCEB,0xBCEC,0x99DB,0xBCED,0x99DC,0x99DD,0x99DE,0x99DF,
+0x99E0,0x99E1,0x99E2,0x99E3,0xBCEE,0xBCEF,0x99E4,0x99E5,
+0xBCF0,0x99E6,0x99E7,0x99E8,0xBCF1,0x99E9,0x99EA,0x99EB,
+0x99EC,0x99ED,0x99EE,0x99EF,0xBCF2,0xBCF3,0x99F0,0xBCF4,
+0x99F1,0xBCF5,0x99F2,0x99F3,0x99F4,0x99F5,0x99F6,0x99F7,
+0xBCF6,0xBCF7,0x99F8,0x99F9,0xBCF8,0x99FA,0x99FB,0xBCF9,
+0xBCFA,0x99FC,0x99FD,0x99FE,0x9A41,0x9A42,0x9A43,0x9A44,
+0xBCFB,0xBCFC,0x9A45,0xBCFD,0x9A46,0xBCFE,0x9A47,0xBDA1,
+0x9A48,0xBDA2,0xBDA3,0x9A49,0xBDA4,0x9A4A,0x9A4B,0x9A4C,
+0x9A4D,0x9A4E,0x9A4F,0x9A50,0x9A51,0x9A52,0x9A53,0x9A54,
+0x9A55,0x9A56,0x9A57,0x9A58,0x9A59,0x9A5A,0x9A61,0x9A62,
+0xBDA5,0x9A63,0x9A64,0x9A65,0x9A66,0x9A67,0x9A68,0x9A69,
+0xBDA6,0xBDA7,0x9A6A,0x9A6B,0xBDA8,0x9A6C,0x9A6D,0x9A6E,
+0xBDA9,0x9A6F,0x9A70,0x9A71,0x9A72,0x9A73,0x9A74,0x9A75,
+0xBDAA,0x9A76,0x9A77,0x9A78,0x9A79,0xBDAB,0x9A7A,0x9A81,
+0x9A82,0x9A83,0x9A84,0x9A85,0xBDAC,0xBDAD,0x9A86,0x9A87,
+0xBDAE,0x9A88,0x9A89,0x9A8A,0xBDAF,0x9A8B,0x9A8C,0x9A8D,
+0x9A8E,0x9A8F,0x9A90,0x9A91,0xBDB0,0xBDB1,0x9A92,0xBDB2,
+0x9A93,0xBDB3,0x9A94,0x9A95,0x9A96,0x9A97,0x9A98,0x9A99,
+0xBDB4,0xBDB5,0x9A9A,0x9A9B,0x9A9C,0x9A9D,0x9A9E,0x9A9F,
+0xBDB6,0x9AA0,0x9AA1,0x9AA2,0x9AA3,0x9AA4,0x9AA5,0x9AA6,
+0xBDB7,0x9AA7,0x9AA8,0xBDB8,0x9AA9,0xBDB9,0x9AAA,0x9AAB,
+0x9AAC,0x9AAD,0x9AAE,0x9AAF,0xBDBA,0xBDBB,0x9AB0,0x9AB1,
+0xBDBC,0x9AB2,0x9AB3,0x9AB4,0xBDBD,0xBDBE,0x9AB5,0x9AB6,
+0x9AB7,0x9AB8,0x9AB9,0x9ABA,0xBDBF,0xBDC0,0x9ABB,0xBDC1,
+0x9ABC,0xBDC2,0x9ABD,0x9ABE,0x9ABF,0x9AC0,0x9AC1,0x9AC2,
+0x9AC3,0x9AC4,0x9AC5,0x9AC6,0x9AC7,0x9AC8,0x9AC9,0x9ACA,
+0x9ACB,0x9ACC,0x9ACD,0x9ACE,0x9ACF,0x9AD0,0x9AD1,0x9AD2,
+0x9AD3,0x9AD4,0x9AD5,0x9AD6,0x9AD7,0x9AD8,0x9AD9,0x9ADA,
+0x9ADB,0x9ADC,0x9ADD,0x9ADE,0xBDC3,0xBDC4,0x9ADF,0x9AE0,
+0xBDC5,0x9AE1,0x9AE2,0xBDC6,0xBDC7,0x9AE3,0x9AE4,0x9AE5,
+0x9AE6,0x9AE7,0x9AE8,0xBDC8,0xBDC9,0xBDCA,0x9AE9,0xBDCB,
+0x9AEA,0xBDCC,0x9AEB,0x9AEC,0x9AED,0x9AEE,0xBDCD,0x9AEF,
+0xBDCE,0xBDCF,0x9AF0,0xBDD0,0xBDD1,0x9AF1,0x9AF2,0x9AF3,
+0xBDD2,0x9AF4,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AF9,0x9AFA,
+0xBDD3,0xBDD4,0x9AFB,0x9AFC,0xBDD5,0xBDD6,0x9AFD,0x9AFE,
+0x9B41,0x9B42,0x9B43,0xBDD7,0xBDD8,0xBDD9,0x9B44,0x9B45,
+0xBDDA,0x9B46,0x9B47,0x9B48,0xBDDB,0x9B49,0x9B4A,0x9B4B,
+0x9B4C,0x9B4D,0x9B4E,0x9B4F,0xBDDC,0xBDDD,0x9B50,0x9B51,
+0xBDDE,0xBDDF,0x9B52,0x9B53,0x9B54,0x9B55,0x9B56,0x9B57,
+0x9B58,0x9B59,0x9B5A,0x9B61,0x9B62,0x9B63,0x9B64,0x9B65,
+0x9B66,0x9B67,0x9B68,0x9B69,0x9B6A,0x9B6B,0x9B6C,0x9B6D,
+0x9B6E,0x9B6F,0x9B70,0x9B71,0x9B72,0xBDE0,0x9B73,0x9B74,
+0x9B75,0x9B76,0x9B77,0x9B78,0x9B79,0x9B7A,0x9B81,0x9B82,
+0x9B83,0x9B84,0x9B85,0x9B86,0x9B87,0x9B88,0x9B89,0x9B8A,
+0x9B8B,0x9B8C,0x9B8D,0x9B8E,0x9B8F,0x9B90,0x9B91,0x9B92,
+0x9B93,0x9B94,0x9B95,0x9B96,0x9B97,0x9B98,0x9B99,0x9B9A,
+0xBDE1,0xBDE2,0x9B9B,0x9B9C,0xBDE3,0x9B9D,0x9B9E,0x9B9F,
+0xBDE4,0x9BA0,0xBDE5,0x9BA1,0x9BA2,0x9BA3,0x9BA4,0x9BA5,
+0xBDE6,0xBDE7,0x9BA6,0x9BA7,0xBDE8,0xBDE9,0x9BA8,0x9BA9,
+0x9BAA,0x9BAB,0x9BAC,0x9BAD,0xBDEA,0x9BAE,0x9BAF,0x9BB0,
+0xBDEB,0x9BB1,0x9BB2,0x9BB3,0xBDEC,0x9BB4,0x9BB5,0x9BB6,
+0x9BB7,0x9BB8,0x9BB9,0x9BBA,0x9BBB,0x9BBC,0x9BBD,0x9BBE,
+0x9BBF,0x9BC0,0x9BC1,0x9BC2,0x9BC3,0x9BC4,0x9BC5,0x9BC6,
+0x9BC7,0x9BC8,0x9BC9,0x9BCA,0x9BCB,0x9BCC,0x9BCD,0x9BCE,
+0x9BCF,0x9BD0,0x9BD1,0x9BD2,0x9BD3,0x9BD4,0x9BD5,0x9BD6,
+0x9BD7,0x9BD8,0x9BD9,0x9BDA,0x9BDB,0x9BDC,0x9BDD,0x9BDE,
+0x9BDF,0x9BE0,0x9BE1,0x9BE2,0x9BE3,0x9BE4,0x9BE5,0x9BE6,
+0xBDED,0x9BE7,0x9BE8,0x9BE9,0x9BEA,0x9BEB,0x9BEC,0x9BED,
+0x9BEE,0x9BEF,0x9BF0,0x9BF1,0x9BF2,0x9BF3,0x9BF4,0x9BF5,
+0x9BF6,0x9BF7,0x9BF8,0x9BF9,0x9BFA,0x9BFB,0x9BFC,0x9BFD,
+0xBDEE,0xBDEF,0x9BFE,0x9C41,0xBDF0,0x9C42,0x9C43,0xBDF1,
+0xBDF2,0x9C44,0xBDF3,0x9C45,0x9C46,0x9C47,0x9C48,0x9C49,
+0xBDF4,0xBDF5,0x9C4A,0x9C4B,0x9C4C,0xBDF6,0x9C4D,0x9C4E,
+0x9C4F,0x9C50,0x9C51,0x9C52,0xBDF7,0xBDF8,0x9C53,0x9C54,
+0xBDF9,0x9C55,0x9C56,0x9C57,0x9C58,0x9C59,0x9C5A,0x9C61,
+0x9C62,0x9C63,0x9C64,0x9C65,0x9C66,0x9C67,0x9C68,0x9C69,
+0xBDFA,0x9C6A,0x9C6B,0x9C6C,0x9C6D,0x9C6E,0x9C6F,0x9C70,
+0xBDFB,0x9C71,0x9C72,0x9C73,0x9C74,0x9C75,0x9C76,0x9C77,
+0x9C78,0x9C79,0x9C7A,0x9C81,0x9C82,0x9C83,0x9C84,0x9C85,
+0x9C86,0x9C87,0x9C88,0x9C89,0xBDFC,0x9C8A,0x9C8B,0x9C8C,
+0x9C8D,0x9C8E,0x9C8F,0x9C90,0xBDFD,0x9C91,0x9C92,0x9C93,
+0xBDFE,0x9C94,0x9C95,0x9C96,0xBEA1,0x9C97,0x9C98,0x9C99,
+0x9C9A,0x9C9B,0x9C9C,0x9C9D,0xBEA2,0xBEA3,0x9C9E,0x9C9F,
+0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA4,0x9CA5,0x9CA6,0x9CA7,
+0xBEA4,0x9CA8,0x9CA9,0x9CAA,0x9CAB,0x9CAC,0x9CAD,0x9CAE,
+0x9CAF,0x9CB0,0x9CB1,0x9CB2,0x9CB3,0x9CB4,0x9CB5,0x9CB6,
+0x9CB7,0x9CB8,0x9CB9,0x9CBA,0x9CBB,0x9CBC,0x9CBD,0x9CBE,
+0x9CBF,0x9CC0,0x9CC1,0x9CC2,0xBEA5,0xBEA6,0x9CC3,0x9CC4,
+0xBEA7,0x9CC5,0x9CC6,0x9CC7,0xBEA8,0x9CC8,0x9CC9,0x9CCA,
+0x9CCB,0x9CCC,0x9CCD,0x9CCE,0xBEA9,0xBEAA,0x9CCF,0x9CD0,
+0x9CD1,0xBEAB,0x9CD2,0x9CD3,0x9CD4,0x9CD5,0x9CD6,0x9CD7,
+0xBEAC,0x9CD8,0x9CD9,0x9CDA,0x9CDB,0x9CDC,0x9CDD,0x9CDE,
+0x9CDF,0x9CE0,0x9CE1,0x9CE2,0x9CE3,0x9CE4,0x9CE5,0x9CE6,
+0x9CE7,0x9CE8,0x9CE9,0x9CEA,0xBEAD,0x9CEB,0x9CEC,0x9CED,
+0x9CEE,0x9CEF,0x9CF0,0x9CF1,0xBEAE,0x9CF2,0x9CF3,0x9CF4,
+0x9CF5,0x9CF6,0x9CF7,0x9CF8,0x9CF9,0x9CFA,0x9CFB,0x9CFC,
+0x9CFD,0x9CFE,0x9D41,0x9D42,0x9D43,0x9D44,0x9D45,0x9D46,
+0x9D47,0x9D48,0x9D49,0x9D4A,0x9D4B,0x9D4C,0x9D4D,0x9D4E,
+0xBEAF,0x9D4F,0x9D50,0x9D51,0xBEB0,0x9D52,0x9D53,0x9D54,
+0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0x9D5A,0x9D61,0x9D62,
+0x9D63,0x9D64,0x9D65,0x9D66,0x9D67,0x9D68,0x9D69,0x9D6A,
+0x9D6B,0x9D6C,0x9D6D,0x9D6E,0x9D6F,0x9D70,0x9D71,0x9D72,
+0x9D73,0x9D74,0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A,
+0x9D81,0x9D82,0x9D83,0x9D84,0x9D85,0x9D86,0x9D87,0x9D88,
+0x9D89,0xBEB1,0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F,
+0xBEB2,0xBEB3,0x9D90,0x9D91,0xBEB4,0x9D92,0x9D93,0x9D94,
+0xBEB5,0x9D95,0xBEB6,0x9D96,0x9D97,0x9D98,0x9D99,0xBEB7,
+0xBEB8,0xBEB9,0x9D9A,0x9D9B,0x9D9C,0x9D9D,0x9D9E,0x9D9F,
+0x9DA0,0x9DA1,0x9DA2,0x9DA3,0xBEBA,0x9DA4,0x9DA5,0x9DA6,
+0xBEBB,0x9DA7,0x9DA8,0x9DA9,0xBEBC,0x9DAA,0x9DAB,0x9DAC,
+0x9DAD,0x9DAE,0x9DAF,0x9DB0,0xBEBD,0x9DB1,0x9DB2,0x9DB3,
+0x9DB4,0x9DB5,0x9DB6,0x9DB7,0x9DB8,0x9DB9,0x9DBA,0x9DBB,
+0xBEBE,0xBEBF,0x9DBC,0x9DBD,0xBEC0,0x9DBE,0x9DBF,0x9DC0,
+0xBEC1,0x9DC1,0x9DC2,0x9DC3,0x9DC4,0x9DC5,0x9DC6,0x9DC7,
+0xBEC2,0xBEC3,0x9DC8,0xBEC4,0x9DC9,0xBEC5,0x9DCA,0x9DCB,
+0x9DCC,0x9DCD,0x9DCE,0x9DCF,0xBEC6,0xBEC7,0x9DD0,0x9DD1,
+0xBEC8,0xBEC9,0xBECA,0x9DD2,0xBECB,0xBECC,0xBECD,0x9DD3,
+0x9DD4,0x9DD5,0x9DD6,0xBECE,0xBECF,0xBED0,0x9DD7,0xBED1,
+0xBED2,0xBED3,0x9DD8,0x9DD9,0x9DDA,0xBED4,0xBED5,0x9DDB,
+0xBED6,0xBED7,0x9DDC,0x9DDD,0xBED8,0x9DDE,0x9DDF,0x9DE0,
+0xBED9,0x9DE1,0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6,0x9DE7,
+0xBEDA,0xBEDB,0x9DE8,0xBEDC,0xBEDD,0xBEDE,0x9DE9,0x9DEA,
+0x9DEB,0x9DEC,0x9DED,0x9DEE,0xBEDF,0xBEE0,0x9DEF,0x9DF0,
+0xBEE1,0x9DF1,0x9DF2,0x9DF3,0xBEE2,0x9DF4,0x9DF5,0xBEE3,
+0x9DF6,0x9DF7,0x9DF8,0x9DF9,0xBEE4,0xBEE5,0x9DFA,0xBEE6,
+0x9DFB,0xBEE7,0x9DFC,0x9DFD,0x9DFE,0xBEE8,0x9E41,0xBEE9,
+0xBEEA,0x9E42,0x9E43,0x9E44,0xBEEB,0x9E45,0x9E46,0x9E47,
+0xBEEC,0x9E48,0x9E49,0x9E4A,0x9E4B,0x9E4C,0x9E4D,0x9E4E,
+0x9E4F,0xBEED,0x9E50,0x9E51,0x9E52,0x9E53,0x9E54,0x9E55,
+0x9E56,0x9E57,0x9E58,0x9E59,0xBEEE,0xBEEF,0x9E5A,0x9E61,
+0xBEF0,0xBEF1,0x9E62,0xBEF2,0xBEF3,0xBEF4,0xBEF5,0x9E63,
+0x9E64,0x9E65,0x9E66,0x9E67,0xBEF6,0xBEF7,0xBEF8,0xBEF9,
+0xBEFA,0xBEFB,0xBEFC,0x9E68,0xBEFD,0x9E69,0xBEFE,0x9E6A,
+0xBFA1,0xBFA2,0x9E6B,0x9E6C,0xBFA3,0x9E6D,0x9E6E,0x9E6F,
+0xBFA4,0x9E70,0x9E71,0x9E72,0x9E73,0x9E74,0x9E75,0x9E76,
+0xBFA5,0xBFA6,0x9E77,0xBFA7,0x9E78,0xBFA8,0x9E79,0x9E7A,
+0x9E81,0x9E82,0x9E83,0x9E84,0xBFA9,0xBFAA,0xBFAB,0x9E85,
+0xBFAC,0x9E86,0x9E87,0x9E88,0xBFAD,0x9E89,0xBFAE,0xBFAF,
+0x9E8A,0x9E8B,0x9E8C,0x9E8D,0xBFB0,0xBFB1,0xBFB2,0xBFB3,
+0xBFB4,0xBFB5,0x9E8E,0x9E8F,0x9E90,0xBFB6,0xBFB7,0xBFB8,
+0xBFB9,0x9E91,0x9E92,0x9E93,0xBFBA,0x9E94,0x9E95,0x9E96,
+0xBFBB,0x9E97,0x9E98,0x9E99,0x9E9A,0x9E9B,0x9E9C,0x9E9D,
+0xBFBC,0xBFBD,0x9E9E,0xBFBE,0xBFBF,0x9E9F,0x9EA0,0x9EA1,
+0x9EA2,0x9EA3,0x9EA4,0x9EA5,0xBFC0,0xBFC1,0x9EA6,0x9EA7,
+0xBFC2,0x9EA8,0x9EA9,0x9EAA,0xBFC3,0xBFC4,0xBFC5,0x9EAB,
+0xBFC6,0x9EAC,0x9EAD,0xBFC7,0xBFC8,0xBFC9,0x9EAE,0xBFCA,
+0x9EAF,0xBFCB,0x9EB0,0xBFCC,0x9EB1,0x9EB2,0x9EB3,0x9EB4,
+0xBFCD,0xBFCE,0x9EB5,0x9EB6,0xBFCF,0x9EB7,0x9EB8,0x9EB9,
+0xBFD0,0x9EBA,0x9EBB,0x9EBC,0x9EBD,0x9EBE,0x9EBF,0x9EC0,
+0xBFD1,0xBFD2,0x9EC1,0xBFD3,0xBFD4,0xBFD5,0x9EC2,0x9EC3,
+0x9EC4,0x9EC5,0x9EC6,0x9EC7,0xBFD6,0xBFD7,0x9EC8,0x9EC9,
+0xBFD8,0x9ECA,0x9ECB,0x9ECC,0x9ECD,0x9ECE,0x9ECF,0x9ED0,
+0x9ED1,0x9ED2,0x9ED3,0x9ED4,0xBFD9,0x9ED5,0x9ED6,0xBFDA,
+0x9ED7,0xBFDB,0x9ED8,0x9ED9,0x9EDA,0x9EDB,0x9EDC,0x9EDD,
+0xBFDC,0xBFDD,0x9EDE,0x9EDF,0xBFDE,0x9EE0,0x9EE1,0x9EE2,
+0xBFDF,0x9EE3,0x9EE4,0x9EE5,0x9EE6,0x9EE7,0x9EE8,0x9EE9,
+0xBFE0,0xBFE1,0x9EEA,0xBFE2,0x9EEB,0xBFE3,0x9EEC,0x9EED,
+0x9EEE,0x9EEF,0x9EF0,0x9EF1,0xBFE4,0xBFE5,0x9EF2,0x9EF3,
+0xBFE6,0x9EF4,0x9EF5,0x9EF6,0xBFE7,0x9EF7,0x9EF8,0x9EF9,
+0x9EFA,0x9EFB,0x9EFC,0x9EFD,0xBFE8,0xBFE9,0x9EFE,0xBFEA,
+0x9F41,0xBFEB,0x9F42,0x9F43,0x9F44,0x9F45,0x9F46,0x9F47,
+0xBFEC,0xBFED,0x9F48,0x9F49,0xBFEE,0x9F4A,0x9F4B,0x9F4C,
+0xBFEF,0xBFF0,0xBFF1,0x9F4D,0x9F4E,0x9F4F,0x9F50,0x9F51,
+0xBFF2,0xBFF3,0x9F52,0xBFF4,0x9F53,0xBFF5,0x9F54,0x9F55,
+0x9F56,0x9F57,0x9F58,0x9F59,0xBFF6,0xBFF7,0x9F5A,0x9F61,
+0xBFF8,0x9F62,0x9F63,0x9F64,0xBFF9,0x9F65,0x9F66,0x9F67,
+0x9F68,0x9F69,0x9F6A,0x9F6B,0xBFFA,0xBFFB,0x9F6C,0x9F6D,
+0xBFFC,0xBFFD,0x9F6E,0x9F6F,0x9F70,0x9F71,0x9F72,0x9F73,
+0xBFFE,0xC0A1,0x9F74,0x9F75,0xC0A2,0x9F76,0x9F77,0x9F78,
+0xC0A3,0x9F79,0x9F7A,0x9F81,0x9F82,0x9F83,0x9F84,0x9F85,
+0xC0A4,0xC0A5,0x9F86,0x9F87,0x9F88,0xC0A6,0x9F89,0x9F8A,
+0x9F8B,0x9F8C,0x9F8D,0x9F8E,0xC0A7,0xC0A8,0x9F8F,0x9F90,
+0xC0A9,0x9F91,0x9F92,0x9F93,0xC0AA,0x9F94,0x9F95,0x9F96,
+0x9F97,0x9F98,0x9F99,0x9F9A,0xC0AB,0xC0AC,0x9F9B,0xC0AD,
+0x9F9C,0xC0AE,0x9F9D,0x9F9E,0x9F9F,0x9FA0,0x9FA1,0x9FA2,
+0xC0AF,0xC0B0,0x9FA3,0x9FA4,0xC0B1,0x9FA5,0x9FA6,0x9FA7,
+0xC0B2,0x9FA8,0x9FA9,0x9FAA,0x9FAB,0x9FAC,0x9FAD,0x9FAE,
+0xC0B3,0xC0B4,0x9FAF,0xC0B5,0x9FB0,0xC0B6,0x9FB1,0xC0B7,
+0x9FB2,0x9FB3,0x9FB4,0x9FB5,0xC0B8,0xC0B9,0x9FB6,0x9FB7,
+0xC0BA,0x9FB8,0x9FB9,0x9FBA,0xC0BB,0x9FBB,0x9FBC,0x9FBD,
+0x9FBE,0x9FBF,0xC0BC,0x9FC0,0xC0BD,0xC0BE,0x9FC1,0xC0BF,
+0x9FC2,0xC0C0,0xC0C1,0xC0C2,0xC0C3,0xC0C4,0xC0C5,0xC0C6,
+0xC0C7,0x9FC3,0x9FC4,0x9FC5,0xC0C8,0x9FC6,0x9FC7,0x9FC8,
+0xC0C9,0x9FC9,0x9FCA,0x9FCB,0x9FCC,0x9FCD,0x9FCE,0x9FCF,
+0xC0CA,0x9FD0,0x9FD1,0xC0CB,0x9FD2,0x9FD3,0x9FD4,0x9FD5,
+0x9FD6,0x9FD7,0x9FD8,0x9FD9,0xC0CC,0xC0CD,0x9FDA,0x9FDB,
+0xC0CE,0x9FDC,0x9FDD,0x9FDE,0xC0CF,0xC0D0,0xC0D1,0x9FDF,
+0x9FE0,0x9FE1,0x9FE2,0xC0D2,0xC0D3,0xC0D4,0x9FE3,0xC0D5,
+0xC0D6,0xC0D7,0xC0D8,0x9FE4,0x9FE5,0x9FE6,0xC0D9,0x9FE7,
+0xC0DA,0xC0DB,0x9FE8,0x9FE9,0xC0DC,0x9FEA,0xC0DD,0xC0DE,
+0xC0DF,0x9FEB,0xC0E0,0x9FEC,0x9FED,0x9FEE,0x9FEF,0x9FF0,
+0xC0E1,0xC0E2,0x9FF1,0xC0E3,0xC0E4,0xC0E5,0xC0E6,0x9FF2,
+0x9FF3,0x9FF4,0x9FF5,0x9FF6,0xC0E7,0xC0E8,0x9FF7,0x9FF8,
+0xC0E9,0x9FF9,0x9FFA,0x9FFB,0xC0EA,0x9FFC,0x9FFD,0x9FFE,
+0xA041,0xA042,0xA043,0xA044,0xC0EB,0xC0EC,0xA045,0xC0ED,
+0xC0EE,0xC0EF,0xA046,0xA047,0xA048,0xA049,0xA04A,0xA04B,
+0xC0F0,0xC0F1,0xA04C,0xA04D,0xC0F2,0xA04E,0xC0F3,0xA04F,
+0xC0F4,0xA050,0xA051,0xA052,0xA053,0xA054,0xA055,0xA056,
+0xC0F5,0xA057,0xA058,0xA059,0xA05A,0xC0F6,0xA061,0xA062,
+0xA063,0xA064,0xA065,0xA066,0xC0F7,0xA067,0xA068,0xA069,
+0xC0F8,0xA06A,0xA06B,0xA06C,0xC0F9,0xA06D,0xA06E,0xA06F,
+0xA070,0xA071,0xA072,0xA073,0xA074,0xA075,0xA076,0xA077,
+0xA078,0xA079,0xA07A,0xA081,0xA082,0xA083,0xA084,0xA085,
+0xC0FA,0xC0FB,0xA086,0xA087,0xC0FC,0xA088,0xA089,0xA08A,
+0xC0FD,0xA08B,0xC0FE,0xA08C,0xA08D,0xA08E,0xA08F,0xA090,
+0xC1A1,0xC1A2,0xA091,0xC1A3,0xA092,0xC1A4,0xC1A5,0xA093,
+0xA094,0xA095,0xA096,0xA097,0xC1A6,0xC1A7,0xA098,0xA099,
+0xC1A8,0xA09A,0xA09B,0xA09C,0xC1A9,0xA09D,0xA09E,0xA09F,
+0xA0A0,0xA0A1,0xA0A2,0xA0A3,0xC1AA,0xC1AB,0xA0A4,0xC1AC,
+0xA0A5,0xC1AD,0xA0A6,0xA0A7,0xA0A8,0xA0A9,0xA0AA,0xA0AB,
+0xC1AE,0xA0AC,0xA0AD,0xA0AE,0xC1AF,0xA0AF,0xA0B0,0xA0B1,
+0xC1B0,0xA0B2,0xA0B3,0xA0B4,0xA0B5,0xA0B6,0xA0B7,0xA0B8,
+0xC1B1,0xC1B2,0xA0B9,0xA0BA,0xC1B3,0xC1B4,0xA0BB,0xA0BC,
+0xA0BD,0xA0BE,0xA0BF,0xA0C0,0xC1B5,0xA0C1,0xA0C2,0xA0C3,
+0xA0C4,0xA0C5,0xA0C6,0xA0C7,0xA0C8,0xA0C9,0xA0CA,0xA0CB,
+0xA0CC,0xA0CD,0xA0CE,0xA0CF,0xA0D0,0xA0D1,0xA0D2,0xA0D3,
+0xA0D4,0xA0D5,0xA0D6,0xA0D7,0xA0D8,0xA0D9,0xA0DA,0xA0DB,
+0xC1B6,0xC1B7,0xA0DC,0xA0DD,0xC1B8,0xA0DE,0xA0DF,0xA0E0,
+0xC1B9,0xA0E1,0xC1BA,0xA0E2,0xA0E3,0xA0E4,0xA0E5,0xA0E6,
+0xC1BB,0xC1BC,0xA0E7,0xC1BD,0xA0E8,0xC1BE,0xC1BF,0xC1C0,
+0xA0E9,0xA0EA,0xA0EB,0xC1C1,0xC1C2,0xC1C3,0xA0EC,0xA0ED,
+0xA0EE,0xA0EF,0xA0F0,0xA0F1,0xC1C4,0xA0F2,0xA0F3,0xA0F4,
+0xA0F5,0xA0F6,0xA0F7,0xA0F8,0xA0F9,0xC1C5,0xA0FA,0xC1C6,
+0xA0FB,0xC1C7,0xA0FC,0xA0FD,0xA0FE,0xA141,0xA142,0xA143,
+0xC1C8,0xA144,0xA145,0xA146,0xA147,0xA148,0xA149,0xA14A,
+0xA14B,0xA14C,0xA14D,0xA14E,0xA14F,0xA150,0xA151,0xA152,
+0xA153,0xA154,0xA155,0xA156,0xC1C9,0xC1CA,0xA157,0xA158,
+0xA159,0xA15A,0xA161,0xA162,0xC1CB,0xA163,0xA164,0xA165,
+0xC1CC,0xA166,0xA167,0xA168,0xC1CD,0xA169,0xA16A,0xA16B,
+0xA16C,0xA16D,0xA16E,0xA16F,0xC1CE,0xC1CF,0xA170,0xC1D0,
+0xA171,0xC1D1,0xA172,0xA173,0xA174,0xA175,0xA176,0xA177,
+0xC1D2,0xC1D3,0xA178,0xA179,0xC1D4,0xA17A,0xA181,0xA182,
+0xA183,0xA184,0xA185,0xA186,0xA187,0xA188,0xA189,0xA18A,
+0xA18B,0xA18C,0xA18D,0xA18E,0xA18F,0xC1D5,0xA190,0xA191,
+0xA192,0xA193,0xA194,0xA195,0xC1D6,0xC1D7,0xA196,0xA197,
+0xC1D8,0xA198,0xA199,0xA19A,0xC1D9,0xC1DA,0xC1DB,0xA19B,
+0xA19C,0xA19D,0xA19E,0xA19F,0xC1DC,0xC1DD,0xA1A0,0xC1DE,
+0xA241,0xC1DF,0xA242,0xA243,0xA244,0xA245,0xA246,0xA247,
+0xC1E0,0xA248,0xA249,0xA24A,0xA24B,0xA24C,0xA24D,0xA24E,
+0xA24F,0xA250,0xA251,0xA252,0xA253,0xA254,0xA255,0xA256,
+0xA257,0xA258,0xA259,0xA25A,0xC1E1,0xA261,0xA262,0xA263,
+0xA264,0xA265,0xA266,0xA267,0xC1E2,0xA268,0xA269,0xA26A,
+0xA26B,0xA26C,0xA26D,0xA26E,0xA26F,0xA270,0xA271,0xA272,
+0xA273,0xA274,0xA275,0xA276,0xA277,0xA278,0xA279,0xA27A,
+0xA281,0xA282,0xA283,0xA284,0xA285,0xA286,0xA287,0xA288,
+0xC1E3,0xC1E4,0xA289,0xA28A,0xC1E5,0xA28B,0xA28C,0xA28D,
+0xC1E6,0xA28E,0xA28F,0xA290,0xA291,0xA292,0xA293,0xA294,
+0xC1E7,0xC1E8,0xA295,0xC1E9,0xA296,0xA297,0xA298,0xA299,
+0xA29A,0xA29B,0xA29C,0xA29D,0xC1EA,0xA29E,0xA29F,0xA2A0,
+0xC1EB,0xA341,0xA342,0xA343,0xC1EC,0xA344,0xA345,0xA346,
+0xA347,0xA348,0xA349,0xA34A,0xC1ED,0xA34B,0xA34C,0xA34D,
+0xA34E,0xA34F,0xA350,0xA351,0xA352,0xA353,0xA354,0xA355,
+0xC1EE,0xC1EF,0xA356,0xA357,0xC1F0,0xA358,0xA359,0xA35A,
+0xC1F1,0xA361,0xA362,0xA363,0xA364,0xA365,0xA366,0xA367,
+0xC1F2,0xC1F3,0xA368,0xC1F4,0xA369,0xC1F5,0xA36A,0xA36B,
+0xA36C,0xA36D,0xA36E,0xA36F,0xA370,0xA371,0xA372,0xA373,
+0xA374,0xA375,0xA376,0xA377,0xA378,0xA379,0xA37A,0xA381,
+0xA382,0xA383,0xA384,0xA385,0xA386,0xA387,0xA388,0xA389,
+0xA38A,0xA38B,0xA38C,0xA38D,0xA38E,0xA38F,0xA390,0xA391,
+0xC1F6,0xC1F7,0xA392,0xA393,0xC1F8,0xA394,0xA395,0xC1F9,
+0xC1FA,0xA396,0xC1FB,0xA397,0xA398,0xA399,0xA39A,0xA39B,
+0xC1FC,0xC1FD,0xA39C,0xC1FE,0xA39D,0xC2A1,0xC2A2,0xA39E,
+0xA39F,0xC2A3,0xC2A4,0xA3A0,0xC2A5,0xC2A6,0xA441,0xA442,
+0xC2A7,0xA443,0xC2A8,0xA444,0xC2A9,0xA445,0xA446,0xC2AA,
+0xA447,0xA448,0xA449,0xA44A,0xC2AB,0xC2AC,0xA44B,0xC2AD,
+0xC2AE,0xC2AF,0xA44C,0xA44D,0xA44E,0xA44F,0xA450,0xA451,
+0xC2B0,0xC2B1,0xA452,0xA453,0xC2B2,0xA454,0xA455,0xA456,
+0xC2B3,0xA457,0xA458,0xA459,0xA45A,0xA461,0xA462,0xA463,
+0xC2B4,0xC2B5,0xA464,0xC2B6,0xC2B7,0xC2B8,0xA465,0xA466,
+0xA467,0xA468,0xA469,0xA46A,0xC2B9,0xA46B,0xA46C,0xA46D,
+0xC2BA,0xA46E,0xA46F,0xA470,0xA471,0xA472,0xA473,0xA474,
+0xA475,0xA476,0xA477,0xA478,0xA479,0xA47A,0xA481,0xA482,
+0xA483,0xC2BB,0xA484,0xA485,0xA486,0xA487,0xA488,0xA489,
+0xA48A,0xA48B,0xA48C,0xA48D,0xA48E,0xA48F,0xA490,0xA491,
+0xA492,0xA493,0xA494,0xA495,0xA496,0xA497,0xA498,0xA499,
+0xA49A,0xA49B,0xA49C,0xA49D,0xA49E,0xA49F,0xA4A0,0xA541,
+0xA542,0xA543,0xA544,0xA545,0xC2BC,0xC2BD,0xA546,0xA547,
+0xC2BE,0xA548,0xA549,0xA54A,0xC2BF,0xA54B,0xA54C,0xA54D,
+0xA54E,0xA54F,0xA550,0xA551,0xC2C0,0xC2C1,0xA552,0xC2C2,
+0xC2C3,0xC2C4,0xA553,0xA554,0xA555,0xA556,0xA557,0xA558,
+0xC2C5,0xA559,0xA55A,0xA561,0xA562,0xA563,0xA564,0xA565,
+0xA566,0xA567,0xA568,0xA569,0xA56A,0xA56B,0xA56C,0xA56D,
+0xA56E,0xA56F,0xA570,0xA571,0xA572,0xC2C6,0xA573,0xA574,
+0xA575,0xA576,0xA577,0xA578,0xC2C7,0xA579,0xA57A,0xA581,
+0xA582,0xA583,0xA584,0xA585,0xA586,0xA587,0xA588,0xA589,
+0xA58A,0xA58B,0xA58C,0xA58D,0xA58E,0xA58F,0xA590,0xA591,
+0xC2C8,0xA592,0xA593,0xA594,0xA595,0xA596,0xA597,0xA598,
+0xA599,0xA59A,0xA59B,0xA59C,0xA59D,0xA59E,0xA59F,0xA5A0,
+0xA641,0xA642,0xA643,0xA644,0xA645,0xA646,0xA647,0xA648,
+0xA649,0xA64A,0xA64B,0xA64C,0xA64D,0xA64E,0xA64F,0xA650,
+0xA651,0xA652,0xA653,0xA654,0xC2C9,0xC2CA,0xA655,0xA656,
+0xC2CB,0xA657,0xA658,0xA659,0xC2CC,0xA65A,0xA661,0xA662,
+0xA663,0xA664,0xA665,0xA666,0xC2CD,0xC2CE,0xA667,0xC2CF,
+0xA668,0xC2D0,0xA669,0xC2D1,0xA66A,0xA66B,0xA66C,0xA66D,
+0xC2D2,0xC2D3,0xA66E,0xA66F,0xA670,0xA671,0xA672,0xA673,
+0xC2D4,0xA674,0xA675,0xA676,0xA677,0xA678,0xA679,0xA67A,
+0xA681,0xA682,0xA683,0xA684,0xC2D5,0xA685,0xA686,0xA687,
+0xA688,0xA689,0xA68A,0xA68B,0xC2D6,0xA68C,0xA68D,0xA68E,
+0xA68F,0xA690,0xA691,0xA692,0xA693,0xA694,0xA695,0xA696,
+0xA697,0xA698,0xA699,0xA69A,0xA69B,0xA69C,0xA69D,0xA69E,
+0xC2D7,0xA69F,0xA6A0,0xA741,0xA742,0xA743,0xA744,0xA745,
+0xC2D8,0xA746,0xA747,0xA748,0xC2D9,0xA749,0xA74A,0xA74B,
+0xC2DA,0xA74C,0xA74D,0xA74E,0xA74F,0xA750,0xA751,0xA752,
+0xC2DB,0xC2DC,0xA753,0xA754,0xA755,0xA756,0xA757,0xA758,
+0xA759,0xA75A,0xA761,0xA762,0xA763,0xA764,0xA765,0xA766,
+0xA767,0xA768,0xA769,0xA76A,0xA76B,0xA76C,0xA76D,0xA76E,
+0xA76F,0xA770,0xA771,0xA772,0xA773,0xA774,0xA775,0xA776,
+0xA777,0xC2DD,0xA778,0xA779,0xA77A,0xA781,0xA782,0xA783,
+0xC2DE,0xC2DF,0xA784,0xA785,0xC2E0,0xA786,0xA787,0xA788,
+0xC2E1,0xA789,0xA78A,0xA78B,0xA78C,0xA78D,0xA78E,0xA78F,
+0xC2E2,0xC2E3,0xA790,0xA791,0xA792,0xC2E4,0xA793,0xA794,
+0xA795,0xA796,0xA797,0xA798,0xC2E5,0xA799,0xA79A,0xA79B,
+0xA79C,0xA79D,0xA79E,0xA79F,0xA7A0,0xA841,0xA842,0xA843,
+0xA844,0xA845,0xA846,0xA847,0xA848,0xA849,0xA84A,0xA84B,
+0xC2E6,0xC2E7,0xA84C,0xA84D,0xA84E,0xA84F,0xA850,0xA851,
+0xA852,0xA853,0xA854,0xA855,0xA856,0xA857,0xA858,0xA859,
+0xA85A,0xA861,0xA862,0xA863,0xA864,0xA865,0xA866,0xA867,
+0xA868,0xA869,0xA86A,0xA86B,0xA86C,0xA86D,0xA86E,0xA86F,
+0xA870,0xA871,0xA872,0xA873,0xC2E8,0xA874,0xA875,0xA876,
+0xA877,0xA878,0xA879,0xA87A,0xA881,0xA882,0xA883,0xA884,
+0xA885,0xA886,0xA887,0xA888,0xA889,0xA88A,0xA88B,0xA88C,
+0xA88D,0xA88E,0xA88F,0xA890,0xA891,0xA892,0xA893,0xA894,
+0xC2E9,0xA895,0xA896,0xA897,0xA898,0xA899,0xA89A,0xA89B,
+0xA89C,0xA89D,0xA89E,0xA89F,0xA8A0,0xA941,0xA942,0xA943,
+0xA944,0xA945,0xA946,0xA947,0xA948,0xA949,0xA94A,0xA94B,
+0xA94C,0xA94D,0xA94E,0xA94F,0xC2EA,0xA950,0xA951,0xA952,
+0xA953,0xA954,0xA955,0xA956,0xA957,0xA958,0xA959,0xA95A,
+0xA961,0xA962,0xA963,0xA964,0xC2EB,0xA965,0xA966,0xC2EC,
+0xA967,0xC2ED,0xA968,0xA969,0xA96A,0xA96B,0xA96C,0xA96D,
+0xA96E,0xA96F,0xA970,0xA971,0xA972,0xA973,0xA974,0xA975,
+0xA976,0xA977,0xA978,0xA979,0xA97A,0xA981,0xA982,0xA983,
+0xA984,0xA985,0xA986,0xA987,0xA988,0xA989,0xA98A,0xA98B,
+0xA98C,0xA98D,0xA98E,0xA98F,0xC2EE,0xC2EF,0xA990,0xA991,
+0xC2F0,0xA992,0xA993,0xA994,0xC2F1,0xA995,0xA996,0xA997,
+0xA998,0xA999,0xA99A,0xA99B,0xC2F2,0xC2F3,0xA99C,0xA99D,
+0xA99E,0xC2F4,0xC2F5,0xA99F,0xA9A0,0xAA41,0xAA42,0xC2F6,
+0xC2F7,0xC2F8,0xAA43,0xAA44,0xC2F9,0xAA45,0xC2FA,0xAA46,
+0xC2FB,0xAA47,0xAA48,0xAA49,0xAA4A,0xAA4B,0xAA4C,0xAA4D,
+0xC2FC,0xC2FD,0xAA4E,0xC2FE,0xC3A1,0xC3A2,0xC3A3,0xAA4F,
+0xAA50,0xAA51,0xAA52,0xAA53,0xC3A4,0xC3A5,0xAA54,0xAA55,
+0xC3A6,0xAA56,0xAA57,0xAA58,0xC3A7,0xAA59,0xAA5A,0xAA61,
+0xAA62,0xAA63,0xAA64,0xAA65,0xC3A8,0xC3A9,0xAA66,0xC3AA,
+0xC3AB,0xC3AC,0xAA67,0xAA68,0xAA69,0xAA6A,0xAA6B,0xAA6C,
+0xC3AD,0xAA6D,0xAA6E,0xAA6F,0xC3AE,0xAA70,0xC3AF,0xAA71,
+0xC3B0,0xAA72,0xAA73,0xAA74,0xAA75,0xAA76,0xAA77,0xAA78,
+0xC3B1,0xAA79,0xAA7A,0xAA81,0xAA82,0xC3B2,0xAA83,0xAA84,
+0xAA85,0xAA86,0xAA87,0xAA88,0xAA89,0xAA8A,0xAA8B,0xAA8C,
+0xAA8D,0xAA8E,0xAA8F,0xAA90,0xAA91,0xAA92,0xAA93,0xAA94,
+0xAA95,0xAA96,0xAA97,0xAA98,0xAA99,0xAA9A,0xAA9B,0xAA9C,
+0xAA9D,0xAA9E,0xAA9F,0xAAA0,0xAB41,0xAB42,0xAB43,0xAB44,
+0xC3B3,0xC3B4,0xAB45,0xAB46,0xC3B5,0xAB47,0xAB48,0xAB49,
+0xC3B6,0xAB4A,0xAB4B,0xAB4C,0xAB4D,0xAB4E,0xAB4F,0xAB50,
+0xC3B7,0xC3B8,0xAB51,0xC3B9,0xC3BA,0xC3BB,0xAB52,0xAB53,
+0xAB54,0xAB55,0xAB56,0xAB57,0xC3BC,0xC3BD,0xAB58,0xAB59,
+0xC3BE,0xAB5A,0xAB61,0xAB62,0xC3BF,0xAB63,0xAB64,0xAB65,
+0xAB66,0xAB67,0xAB68,0xAB69,0xC3C0,0xC3C1,0xAB6A,0xC3C2,
+0xAB6B,0xC3C3,0xAB6C,0xAB6D,0xAB6E,0xAB6F,0xAB70,0xAB71,
+0xC3C4,0xAB72,0xAB73,0xAB74,0xC3C5,0xAB75,0xAB76,0xAB77,
+0xAB78,0xAB79,0xAB7A,0xAB81,0xAB82,0xAB83,0xAB84,0xAB85,
+0xAB86,0xAB87,0xAB88,0xAB89,0xC3C6,0xAB8A,0xAB8B,0xAB8C,
+0xAB8D,0xAB8E,0xAB8F,0xAB90,0xC3C7,0xAB91,0xAB92,0xAB93,
+0xC3C8,0xAB94,0xAB95,0xAB96,0xAB97,0xAB98,0xAB99,0xAB9A,
+0xAB9B,0xAB9C,0xAB9D,0xAB9E,0xAB9F,0xABA0,0xAC41,0xAC42,
+0xAC43,0xC3C9,0xAC44,0xAC45,0xAC46,0xAC47,0xAC48,0xAC49,
+0xC3CA,0xC3CB,0xAC4A,0xAC4B,0xC3CC,0xAC4C,0xAC4D,0xAC4E,
+0xC3CD,0xAC4F,0xAC50,0xAC51,0xAC52,0xAC53,0xAC54,0xAC55,
+0xC3CE,0xC3CF,0xAC56,0xC3D0,0xAC57,0xC3D1,0xAC58,0xAC59,
+0xAC5A,0xAC61,0xAC62,0xAC63,0xC3D2,0xAC64,0xAC65,0xAC66,
+0xC3D3,0xAC67,0xAC68,0xAC69,0xC3D4,0xAC6A,0xAC6B,0xAC6C,
+0xAC6D,0xAC6E,0xAC6F,0xAC70,0xAC71,0xAC72,0xAC73,0xAC74,
+0xAC75,0xC3D5,0xAC76,0xAC77,0xAC78,0xAC79,0xAC7A,0xAC81,
+0xAC82,0xAC83,0xAC84,0xAC85,0xAC86,0xAC87,0xAC88,0xAC89,
+0xAC8A,0xAC8B,0xAC8C,0xAC8D,0xAC8E,0xAC8F,0xAC90,0xAC91,
+0xAC92,0xAC93,0xAC94,0xAC95,0xAC96,0xAC97,0xAC98,0xAC99,
+0xAC9A,0xAC9B,0xAC9C,0xAC9D,0xC3D6,0xAC9E,0xAC9F,0xACA0,
+0xC3D7,0xAD41,0xAD42,0xAD43,0xC3D8,0xAD44,0xAD45,0xAD46,
+0xAD47,0xAD48,0xAD49,0xAD4A,0xC3D9,0xC3DA,0xAD4B,0xC3DB,
+0xAD4C,0xC3DC,0xAD4D,0xAD4E,0xAD4F,0xAD50,0xAD51,0xAD52,
+0xC3DD,0xAD53,0xAD54,0xAD55,0xAD56,0xAD57,0xAD58,0xAD59,
+0xAD5A,0xAD61,0xAD62,0xAD63,0xAD64,0xAD65,0xAD66,0xAD67,
+0xC3DE,0xAD68,0xAD69,0xAD6A,0xAD6B,0xAD6C,0xAD6D,0xAD6E,
+0xAD6F,0xAD70,0xAD71,0xAD72,0xC3DF,0xC3E0,0xAD73,0xAD74,
+0xC3E1,0xAD75,0xAD76,0xAD77,0xC3E2,0xAD78,0xAD79,0xAD7A,
+0xAD81,0xAD82,0xAD83,0xAD84,0xC3E3,0xC3E4,0xAD85,0xC3E5,
+0xAD86,0xC3E6,0xAD87,0xAD88,0xAD89,0xAD8A,0xAD8B,0xAD8C,
+0xC3E7,0xAD8D,0xAD8E,0xAD8F,0xAD90,0xAD91,0xAD92,0xAD93,
+0xAD94,0xAD95,0xAD96,0xAD97,0xAD98,0xAD99,0xAD9A,0xAD9B,
+0xAD9C,0xAD9D,0xAD9E,0xAD9F,0xC3E8,0xADA0,0xAE41,0xAE42,
+0xAE43,0xAE44,0xAE45,0xAE46,0xC3E9,0xAE47,0xAE48,0xAE49,
+0xC3EA,0xAE4A,0xAE4B,0xAE4C,0xAE4D,0xAE4E,0xAE4F,0xAE50,
+0xAE51,0xAE52,0xAE53,0xAE54,0xAE55,0xAE56,0xAE57,0xAE58,
+0xAE59,0xAE5A,0xAE61,0xAE62,0xAE63,0xAE64,0xAE65,0xAE66,
+0xC3EB,0xAE67,0xAE68,0xAE69,0xC3EC,0xAE6A,0xAE6B,0xAE6C,
+0xC3ED,0xAE6D,0xAE6E,0xAE6F,0xAE70,0xAE71,0xAE72,0xAE73,
+0xC3EE,0xC3EF,0xAE74,0xC3F0,0xAE75,0xC3F1,0xAE76,0xAE77,
+0xAE78,0xAE79,0xAE7A,0xAE81,0xC3F2,0xAE82,0xAE83,0xAE84,
+0xC3F3,0xAE85,0xAE86,0xAE87,0xC3F4,0xAE88,0xAE89,0xAE8A,
+0xAE8B,0xAE8C,0xAE8D,0xAE8E,0xC3F5,0xAE8F,0xAE90,0xAE91,
+0xAE92,0xC3F6,0xAE93,0xAE94,0xAE95,0xAE96,0xAE97,0xAE98,
+0xC3F7,0xC3F8,0xAE99,0xAE9A,0xC3F9,0xAE9B,0xAE9C,0xAE9D,
+0xC3FA,0xAE9E,0xAE9F,0xAEA0,0xAF41,0xAF42,0xAF43,0xAF44,
+0xC3FB,0xC3FC,0xAF45,0xC3FD,0xAF46,0xC3FE,0xAF47,0xAF48,
+0xAF49,0xAF4A,0xAF4B,0xAF4C,0xAF4D,0xAF4E,0xAF4F,0xAF50,
+0xAF51,0xAF52,0xAF53,0xAF54,0xAF55,0xAF56,0xAF57,0xAF58,
+0xAF59,0xAF5A,0xAF61,0xAF62,0xAF63,0xAF64,0xAF65,0xAF66,
+0xAF67,0xAF68,0xAF69,0xAF6A,0xAF6B,0xAF6C,0xAF6D,0xAF6E,
+0xC4A1,0xC4A2,0xAF6F,0xAF70,0xC4A3,0xAF71,0xAF72,0xC4A4,
+0xC4A5,0xC4A6,0xAF73,0xAF74,0xAF75,0xAF76,0xAF77,0xAF78,
+0xC4A7,0xC4A8,0xAF79,0xC4A9,0xAF7A,0xC4AA,0xAF81,0xAF82,
+0xAF83,0xAF84,0xAF85,0xAF86,0xC4AB,0xC4AC,0xAF87,0xAF88,
+0xC4AD,0xAF89,0xAF8A,0xAF8B,0xC4AE,0xAF8C,0xAF8D,0xAF8E,
+0xAF8F,0xAF90,0xAF91,0xAF92,0xC4AF,0xC4B0,0xAF93,0xC4B1,
+0xAF94,0xC4B2,0xAF95,0xAF96,0xAF97,0xAF98,0xAF99,0xAF9A,
+0xC4B3,0xC4B4,0xAF9B,0xAF9C,0xC4B5,0xAF9D,0xAF9E,0xAF9F,
+0xC4B6,0xAFA0,0xB041,0xB042,0xB043,0xB044,0xB045,0xB046,
+0xC4B7,0xC4B8,0xB047,0xC4B9,0xC4BA,0xC4BB,0xB048,0xB049,
+0xB04A,0xB04B,0xB04C,0xB04D,0xC4BC,0xC4BD,0xB04E,0xB04F,
+0xB050,0xB051,0xB052,0xB053,0xB054,0xB055,0xB056,0xB057,
+0xB058,0xB059,0xB05A,0xB061,0xB062,0xB063,0xB064,0xB065,
+0xB066,0xC4BE,0xB067,0xB068,0xB069,0xB06A,0xB06B,0xB06C,
+0xB06D,0xB06E,0xB06F,0xB070,0xB071,0xB072,0xB073,0xB074,
+0xB075,0xB076,0xB077,0xB078,0xB079,0xB07A,0xB081,0xB082,
+0xB083,0xB084,0xB085,0xB086,0xB087,0xB088,0xB089,0xB08A,
+0xB08B,0xB08C,0xB08D,0xB08E,0xC4BF,0xC4C0,0xB08F,0xB090,
+0xC4C1,0xB091,0xB092,0xC4C2,0xC4C3,0xB093,0xB094,0xB095,
+0xB096,0xB097,0xB098,0xB099,0xC4C4,0xC4C5,0xB09A,0xC4C6,
+0xC4C7,0xC4C8,0xB09B,0xB09C,0xB09D,0xB09E,0xB09F,0xB0A0,
+0xC4C9,0xC4CA,0xB141,0xB142,0xC4CB,0xB143,0xB144,0xB145,
+0xC4CC,0xB146,0xB147,0xB148,0xB149,0xB14A,0xB14B,0xB14C,
+0xC4CD,0xC4CE,0xB14D,0xC4CF,0xB14E,0xC4D0,0xB14F,0xB150,
+0xB151,0xB152,0xB153,0xB154,0xC4D1,0xB155,0xB156,0xB157,
+0xC4D2,0xB158,0xB159,0xB15A,0xC4D3,0xB161,0xB162,0xB163,
+0xB164,0xB165,0xB166,0xB167,0xC4D4,0xC4D5,0xB168,0xC4D6,
+0xC4D7,0xC4D8,0xB169,0xB16A,0xB16B,0xB16C,0xB16D,0xB16E,
+0xC4D9,0xB16F,0xB170,0xB171,0xB172,0xB173,0xB174,0xB175,
+0xB176,0xB177,0xB178,0xB179,0xB17A,0xB181,0xB182,0xB183,
+0xB184,0xB185,0xB186,0xB187,0xB188,0xB189,0xB18A,0xB18B,
+0xB18C,0xB18D,0xB18E,0xB18F,0xC4DA,0xC4DB,0xB190,0xB191,
+0xC4DC,0xB192,0xB193,0xB194,0xC4DD,0xB195,0xB196,0xB197,
+0xB198,0xB199,0xB19A,0xB19B,0xC4DE,0xC4DF,0xB19C,0xC4E0,
+0xB19D,0xC4E1,0xB19E,0xB19F,0xB1A0,0xB241,0xB242,0xB243,
+0xC4E2,0xC4E3,0xB244,0xB245,0xC4E4,0xB246,0xB247,0xB248,
+0xC4E5,0xB249,0xB24A,0xB24B,0xB24C,0xB24D,0xB24E,0xB24F,
+0xC4E6,0xB250,0xB251,0xB252,0xB253,0xC4E7,0xB254,0xB255,
+0xB256,0xB257,0xB258,0xB259,0xC4E8,0xB25A,0xB261,0xB262,
+0xB263,0xB264,0xB265,0xB266,0xB267,0xB268,0xB269,0xB26A,
+0xB26B,0xB26C,0xB26D,0xB26E,0xB26F,0xB270,0xB271,0xB272,
+0xB273,0xC4E9,0xB274,0xB275,0xB276,0xB277,0xB278,0xB279,
+0xC4EA,0xB27A,0xB281,0xB282,0xB283,0xB284,0xB285,0xB286,
+0xC4EB,0xB287,0xB288,0xB289,0xB28A,0xB28B,0xB28C,0xB28D,
+0xB28E,0xB28F,0xB290,0xB291,0xB292,0xB293,0xB294,0xB295,
+0xB296,0xB297,0xB298,0xB299,0xC4EC,0xB29A,0xB29B,0xB29C,
+0xB29D,0xB29E,0xB29F,0xB2A0,0xB341,0xB342,0xB343,0xB344,
+0xB345,0xB346,0xB347,0xB348,0xB349,0xB34A,0xB34B,0xB34C,
+0xB34D,0xB34E,0xB34F,0xB350,0xB351,0xB352,0xB353,0xB354,
+0xC4ED,0xC4EE,0xB355,0xB356,0xC4EF,0xB357,0xB358,0xB359,
+0xC4F0,0xB35A,0xB361,0xB362,0xB363,0xB364,0xB365,0xB366,
+0xC4F1,0xC4F2,0xB367,0xC4F3,0xB368,0xC4F4,0xB369,0xB36A,
+0xB36B,0xB36C,0xB36D,0xB36E,0xC4F5,0xB36F,0xB370,0xB371,
+0xC4F6,0xB372,0xB373,0xB374,0xC4F7,0xB375,0xB376,0xB377,
+0xB378,0xB379,0xB37A,0xB381,0xB382,0xB383,0xB384,0xB385,
+0xB386,0xC4F8,0xB387,0xB388,0xB389,0xB38A,0xB38B,0xB38C,
+0xC4F9,0xB38D,0xB38E,0xB38F,0xB390,0xB391,0xB392,0xB393,
+0xB394,0xB395,0xB396,0xB397,0xB398,0xB399,0xB39A,0xB39B,
+0xB39C,0xB39D,0xB39E,0xB39F,0xB3A0,0xC4FA,0xB441,0xB442,
+0xB443,0xB444,0xB445,0xB446,0xC4FB,0xC4FC,0xB447,0xB448,
+0xC4FD,0xB449,0xB44A,0xB44B,0xC4FE,0xB44C,0xB44D,0xB44E,
+0xB44F,0xB450,0xB451,0xB452,0xC5A1,0xC5A2,0xB453,0xC5A3,
+0xB454,0xC5A4,0xB455,0xB456,0xB457,0xB458,0xB459,0xB45A,
+0xC5A5,0xB461,0xB462,0xB463,0xC5A6,0xB464,0xB465,0xB466,
+0xC5A7,0xB467,0xB468,0xB469,0xB46A,0xB46B,0xB46C,0xB46D,
+0xC5A8,0xB46E,0xB46F,0xB470,0xB471,0xB472,0xB473,0xB474,
+0xB475,0xB476,0xB477,0xB478,0xC5A9,0xC5AA,0xB479,0xB47A,
+0xC5AB,0xB481,0xB482,0xB483,0xC5AC,0xB484,0xB485,0xB486,
+0xB487,0xB488,0xB489,0xB48A,0xC5AD,0xC5AE,0xB48B,0xB48C,
+0xB48D,0xC5AF,0xB48E,0xB48F,0xB490,0xB491,0xB492,0xB493,
+0xB494,0xB495,0xB496,0xB497,0xB498,0xB499,0xB49A,0xB49B,
+0xB49C,0xB49D,0xB49E,0xB49F,0xB4A0,0xB541,0xB542,0xB543,
+0xB544,0xB545,0xB546,0xB547,0xB548,0xB549,0xB54A,0xB54B,
+0xB54C,0xB54D,0xB54E,0xB54F,0xC5B0,0xC5B1,0xB550,0xB551,
+0xC5B2,0xB552,0xB553,0xB554,0xC5B3,0xB555,0xB556,0xB557,
+0xB558,0xB559,0xB55A,0xB561,0xC5B4,0xC5B5,0xB562,0xC5B6,
+0xB563,0xC5B7,0xB564,0xB565,0xB566,0xB567,0xB568,0xB569,
+0xC5B8,0xC5B9,0xB56A,0xB56B,0xC5BA,0xB56C,0xB56D,0xB56E,
+0xC5BB,0xC5BC,0xB56F,0xB570,0xB571,0xB572,0xB573,0xB574,
+0xC5BD,0xC5BE,0xB575,0xC5BF,0xC5C0,0xC5C1,0xB576,0xB577,
+0xB578,0xB579,0xB57A,0xB581,0xC5C2,0xC5C3,0xB582,0xB583,
+0xC5C4,0xB584,0xB585,0xB586,0xC5C5,0xB587,0xB588,0xB589,
+0xB58A,0xB58B,0xB58C,0xB58D,0xC5C6,0xC5C7,0xB58E,0xC5C8,
+0xC5C9,0xC5CA,0xB58F,0xB590,0xB591,0xB592,0xB593,0xB594,
+0xC5CB,0xB595,0xB596,0xB597,0xB598,0xB599,0xB59A,0xB59B,
+0xB59C,0xB59D,0xB59E,0xB59F,0xB5A0,0xB641,0xB642,0xB643,
+0xB644,0xB645,0xB646,0xB647,0xB648,0xC5CC,0xB649,0xB64A,
+0xB64B,0xB64C,0xB64D,0xB64E,0xB64F,0xB650,0xB651,0xB652,
+0xB653,0xB654,0xB655,0xB656,0xB657,0xB658,0xB659,0xB65A,
+0xB661,0xB662,0xB663,0xB664,0xB665,0xB666,0xB667,0xB668,
+0xB669,0xB66A,0xB66B,0xB66C,0xB66D,0xB66E,0xB66F,0xB670,
+0xC5CD,0xC5CE,0xB671,0xB672,0xC5CF,0xB673,0xB674,0xB675,
+0xC5D0,0xB676,0xC5D1,0xB677,0xB678,0xB679,0xB67A,0xB681,
+0xC5D2,0xC5D3,0xB682,0xC5D4,0xC5D5,0xC5D6,0xB683,0xB684,
+0xB685,0xB686,0xB687,0xB688,0xC5D7,0xC5D8,0xB689,0xB68A,
+0xC5D9,0xB68B,0xB68C,0xB68D,0xC5DA,0xB68E,0xB68F,0xB690,
+0xB691,0xB692,0xB693,0xB694,0xC5DB,0xC5DC,0xB695,0xC5DD,
+0xB696,0xC5DE,0xB697,0xB698,0xB699,0xB69A,0xB69B,0xB69C,
+0xC5DF,0xB69D,0xB69E,0xB69F,0xC5E0,0xB6A0,0xB741,0xB742,
+0xB743,0xB744,0xB745,0xB746,0xB747,0xB748,0xB749,0xB74A,
+0xB74B,0xB74C,0xB74D,0xB74E,0xC5E1,0xB74F,0xB750,0xB751,
+0xB752,0xB753,0xB754,0xB755,0xC5E2,0xB756,0xB757,0xB758,
+0xC5E3,0xB759,0xB75A,0xB761,0xB762,0xB763,0xB764,0xB765,
+0xB766,0xB767,0xB768,0xB769,0xB76A,0xB76B,0xB76C,0xB76D,
+0xB76E,0xB76F,0xB770,0xB771,0xB772,0xB773,0xB774,0xB775,
+0xC5E4,0xC5E5,0xB776,0xB777,0xC5E6,0xB778,0xB779,0xB77A,
+0xC5E7,0xB781,0xB782,0xB783,0xB784,0xB785,0xB786,0xB787,
+0xC5E8,0xC5E9,0xB788,0xC5EA,0xB789,0xC5EB,0xB78A,0xB78B,
+0xB78C,0xB78D,0xC5EC,0xB78E,0xC5ED,0xB78F,0xB790,0xB791,
+0xC5EE,0xB792,0xB793,0xB794,0xB795,0xB796,0xB797,0xB798,
+0xB799,0xB79A,0xB79B,0xB79C,0xB79D,0xB79E,0xB79F,0xB7A0,
+0xB841,0xB842,0xB843,0xB844,0xB845,0xB846,0xB847,0xB848,
+0xC5EF,0xB849,0xB84A,0xB84B,0xB84C,0xB84D,0xB84E,0xB84F,
+0xB850,0xB851,0xB852,0xB853,0xB854,0xB855,0xB856,0xB857,
+0xB858,0xB859,0xB85A,0xB861,0xB862,0xB863,0xB864,0xB865,
+0xB866,0xB867,0xB868,0xB869,0xC5F0,0xB86A,0xB86B,0xB86C,
+0xC5F1,0xB86D,0xB86E,0xB86F,0xB870,0xB871,0xB872,0xB873,
+0xB874,0xB875,0xB876,0xB877,0xB878,0xB879,0xB87A,0xC5F2,
+0xB881,0xC5F3,0xB882,0xB883,0xB884,0xB885,0xB886,0xB887,
+0xC5F4,0xB888,0xB889,0xB88A,0xB88B,0xB88C,0xB88D,0xB88E,
+0xB88F,0xB890,0xB891,0xB892,0xB893,0xB894,0xB895,0xB896,
+0xB897,0xB898,0xB899,0xB89A,0xB89B,0xB89C,0xB89D,0xB89E,
+0xB89F,0xB8A0,0xB941,0xB942,0xC5F5,0xC5F6,0xB943,0xB944,
+0xC5F7,0xB945,0xB946,0xB947,0xC5F8,0xB948,0xB949,0xB94A,
+0xB94B,0xB94C,0xB94D,0xB94E,0xC5F9,0xC5FA,0xB94F,0xC5FB,
+0xB950,0xC5FC,0xB951,0xB952,0xB953,0xB954,0xB955,0xB956,
+0xC5FD,0xB957,0xB958,0xB959,0xB95A,0xB961,0xB962,0xB963,
+0xB964,0xB965,0xB966,0xB967,0xB968,0xB969,0xB96A,0xB96B,
+0xB96C,0xB96D,0xB96E,0xB96F,0xC5FE,0xB970,0xB971,0xB972,
+0xB973,0xB974,0xB975,0xB976,0xC6A1,0xB977,0xB978,0xB979,
+0xB97A,0xB981,0xB982,0xB983,0xB984,0xB985,0xB986,0xB987,
+0xB988,0xB989,0xB98A,0xB98B,0xB98C,0xB98D,0xB98E,0xB98F,
+0xB990,0xB991,0xB992,0xB993,0xB994,0xB995,0xB996,0xB997,
+0xC6A2,0xC6A3,0xB998,0xB999,0xC6A4,0xB99A,0xB99B,0xB99C,
+0xC6A5,0xB99D,0xB99E,0xB99F,0xB9A0,0xBA41,0xBA42,0xBA43,
+0xC6A6,0xC6A7,0xBA44,0xBA45,0xBA46,0xC6A8,0xBA47,0xBA48,
+0xBA49,0xBA4A,0xBA4B,0xBA4C,0xC6A9,0xBA4D,0xBA4E,0xBA4F,
+0xC6AA,0xBA50,0xBA51,0xBA52,0xC6AB,0xBA53,0xBA54,0xBA55,
+0xBA56,0xBA57,0xBA58,0xBA59,0xC6AC,0xBA5A,0xBA61,0xBA62,
+0xBA63,0xC6AD,0xBA64,0xBA65,0xBA66,0xBA67,0xBA68,0xBA69,
+0xC6AE,0xC6AF,0xBA6A,0xBA6B,0xC6B0,0xBA6C,0xBA6D,0xC6B1,
+0xC6B2,0xBA6E,0xC6B3,0xBA6F,0xBA70,0xBA71,0xBA72,0xBA73,
+0xC6B4,0xC6B5,0xBA74,0xC6B6,0xBA75,0xBA76,0xBA77,0xBA78,
+0xBA79,0xBA7A,0xBA81,0xBA82,0xC6B7,0xBA83,0xBA84,0xBA85,
+0xC6B8,0xBA86,0xBA87,0xBA88,0xC6B9,0xBA89,0xBA8A,0xBA8B,
+0xBA8C,0xBA8D,0xBA8E,0xBA8F,0xC6BA,0xC6BB,0xBA90,0xBA91,
+0xBA92,0xBA93,0xBA94,0xBA95,0xBA96,0xBA97,0xBA98,0xBA99,
+0xC6BC,0xC6BD,0xBA9A,0xBA9B,0xC6BE,0xBA9C,0xBA9D,0xBA9E,
+0xC6BF,0xBA9F,0xBAA0,0xBB41,0xBB42,0xBB43,0xBB44,0xBB45,
+0xC6C0,0xC6C1,0xBB46,0xC6C2,0xBB47,0xC6C3,0xBB48,0xBB49,
+0xBB4A,0xBB4B,0xBB4C,0xBB4D,0xC6C4,0xC6C5,0xC6C6,0xBB4E,
+0xC6C7,0xBB4F,0xBB50,0xBB51,0xC6C8,0xBB52,0xC6C9,0xBB53,
+0xBB54,0xBB55,0xBB56,0xBB57,0xC6CA,0xC6CB,0xBB58,0xC6CC,
+0xC6CD,0xC6CE,0xBB59,0xBB5A,0xBB61,0xC6CF,0xBB62,0xBB63,
+0xC6D0,0xC6D1,0xBB64,0xBB65,0xC6D2,0xBB66,0xBB67,0xBB68,
+0xC6D3,0xBB69,0xBB6A,0xBB6B,0xBB6C,0xBB6D,0xBB6E,0xBB6F,
+0xC6D4,0xC6D5,0xBB70,0xC6D6,0xC6D7,0xC6D8,0xBB71,0xBB72,
+0xBB73,0xBB74,0xBB75,0xBB76,0xC6D9,0xC6DA,0xBB77,0xBB78,
+0xBB79,0xBB7A,0xBB81,0xBB82,0xBB83,0xBB84,0xBB85,0xBB86,
+0xBB87,0xBB88,0xBB89,0xBB8A,0xBB8B,0xBB8C,0xBB8D,0xBB8E,
+0xBB8F,0xBB90,0xBB91,0xBB92,0xBB93,0xBB94,0xBB95,0xBB96,
+0xBB97,0xBB98,0xBB99,0xBB9A,0xBB9B,0xBB9C,0xBB9D,0xBB9E,
+0xBB9F,0xBBA0,0xBC41,0xBC42,0xBC43,0xBC44,0xBC45,0xBC46,
+0xBC47,0xBC48,0xBC49,0xBC4A,0xBC4B,0xBC4C,0xBC4D,0xBC4E,
+0xBC4F,0xBC50,0xBC51,0xBC52,0xC6DB,0xC6DC,0xBC53,0xBC54,
+0xC6DD,0xBC55,0xBC56,0xBC57,0xC6DE,0xBC58,0xBC59,0xBC5A,
+0xBC61,0xBC62,0xBC63,0xBC64,0xC6DF,0xC6E0,0xBC65,0xC6E1,
+0xC6E2,0xC6E3,0xBC66,0xBC67,0xBC68,0xBC69,0xBC6A,0xBC6B,
+0xC6E4,0xC6E5,0xBC6C,0xBC6D,0xC6E6,0xBC6E,0xBC6F,0xBC70,
+0xC6E7,0xBC71,0xBC72,0xBC73,0xBC74,0xBC75,0xBC76,0xBC77,
+0xC6E8,0xC6E9,0xBC78,0xC6EA,0xBC79,0xC6EB,0xBC7A,0xBC81,
+0xBC82,0xBC83,0xBC84,0xBC85,0xC6EC,0xBC86,0xBC87,0xBC88,
+0xC6ED,0xBC89,0xBC8A,0xBC8B,0xC6EE,0xBC8C,0xBC8D,0xBC8E,
+0xBC8F,0xBC90,0xBC91,0xBC92,0xC6EF,0xC6F0,0xBC93,0xBC94,
+0xC6F1,0xC6F2,0xBC95,0xBC96,0xBC97,0xBC98,0xBC99,0xBC9A,
+0xC6F3,0xBC9B,0xBC9C,0xBC9D,0xBC9E,0xBC9F,0xBCA0,0xBD41,
+0xC6F4,0xBD42,0xBD43,0xBD44,0xBD45,0xBD46,0xBD47,0xBD48,
+0xBD49,0xC6F5,0xBD4A,0xC6F6,0xBD4B,0xBD4C,0xBD4D,0xBD4E,
+0xBD4F,0xBD50,0xBD51,0xBD52,0xC6F7,0xC6F8,0xBD53,0xBD54,
+0xC6F9,0xBD55,0xBD56,0xBD57,0xC6FA,0xBD58,0xBD59,0xBD5A,
+0xBD61,0xBD62,0xBD63,0xBD64,0xC6FB,0xC6FC,0xBD65,0xC6FD,
+0xBD66,0xC6FE,0xBD67,0xBD68,0xBD69,0xBD6A,0xBD6B,0xBD6C,
+0xC7A1,0xBD6D,0xBD6E,0xBD6F,0xBD70,0xBD71,0xBD72,0xBD73,
+0xBD74,0xBD75,0xBD76,0xBD77,0xBD78,0xBD79,0xBD7A,0xBD81,
+0xBD82,0xBD83,0xBD84,0xBD85,0xBD86,0xC7A2,0xBD87,0xBD88,
+0xBD89,0xBD8A,0xBD8B,0xBD8C,0xBD8D,0xBD8E,0xBD8F,0xBD90,
+0xBD91,0xBD92,0xBD93,0xBD94,0xBD95,0xBD96,0xBD97,0xBD98,
+0xBD99,0xBD9A,0xBD9B,0xBD9C,0xBD9D,0xBD9E,0xBD9F,0xBDA0,
+0xBE41,0xBE42,0xBE43,0xBE44,0xBE45,0xBE46,0xBE47,0xBE48,
+0xC7A3,0xBE49,0xBE4A,0xBE4B,0xC7A4,0xBE4C,0xBE4D,0xBE4E,
+0xBE4F,0xBE50,0xBE51,0xBE52,0xBE53,0xBE54,0xBE55,0xBE56,
+0xBE57,0xBE58,0xBE59,0xBE5A,0xBE61,0xBE62,0xBE63,0xBE64,
+0xBE65,0xBE66,0xBE67,0xBE68,0xC7A5,0xBE69,0xBE6A,0xBE6B,
+0xC7A6,0xBE6C,0xBE6D,0xBE6E,0xC7A7,0xBE6F,0xBE70,0xBE71,
+0xBE72,0xBE73,0xBE74,0xBE75,0xBE76,0xC7A8,0xBE77,0xC7A9,
+0xBE78,0xBE79,0xBE7A,0xBE81,0xBE82,0xBE83,0xBE84,0xBE85,
+0xC7AA,0xC7AB,0xBE86,0xBE87,0xC7AC,0xBE88,0xBE89,0xC7AD,
+0xC7AE,0xBE8A,0xC7AF,0xBE8B,0xBE8C,0xBE8D,0xBE8E,0xBE8F,
+0xC7B0,0xC7B1,0xBE90,0xC7B2,0xBE91,0xC7B3,0xBE92,0xBE93,
+0xBE94,0xBE95,0xBE96,0xBE97,0xC7B4,0xBE98,0xBE99,0xBE9A,
+0xBE9B,0xBE9C,0xBE9D,0xBE9E,0xBE9F,0xBEA0,0xBF41,0xBF42,
+0xBF43,0xBF44,0xBF45,0xBF46,0xBF47,0xBF48,0xBF49,0xBF4A,
+0xBF4B,0xC7B5,0xBF4C,0xBF4D,0xBF4E,0xBF4F,0xBF50,0xBF51,
+0xBF52,0xBF53,0xBF54,0xBF55,0xBF56,0xBF57,0xBF58,0xBF59,
+0xBF5A,0xBF61,0xBF62,0xBF63,0xBF64,0xBF65,0xBF66,0xBF67,
+0xBF68,0xBF69,0xBF6A,0xBF6B,0xBF6C,0xBF6D,0xBF6E,0xBF6F,
+0xBF70,0xBF71,0xBF72,0xBF73,0xC7B6,0xBF74,0xBF75,0xBF76,
+0xC7B7,0xBF77,0xBF78,0xBF79,0xC7B8,0xBF7A,0xBF81,0xBF82,
+0xBF83,0xBF84,0xBF85,0xBF86,0xC7B9,0xBF87,0xBF88,0xC7BA,
+0xBF89,0xBF8A,0xBF8B,0xBF8C,0xBF8D,0xBF8E,0xBF8F,0xBF90,
+0xC7BB,0xBF91,0xBF92,0xBF93,0xC7BC,0xBF94,0xBF95,0xBF96,
+0xC7BD,0xBF97,0xBF98,0xBF99,0xBF9A,0xBF9B,0xBF9C,0xBF9D,
+0xC7BE,0xBF9E,0xBF9F,0xC7BF,0xBFA0,0xC7C0,0xC041,0xC042,
+0xC043,0xC044,0xC045,0xC046,0xC7C1,0xC047,0xC048,0xC049,
+0xC7C2,0xC04A,0xC04B,0xC04C,0xC7C3,0xC04D,0xC04E,0xC04F,
+0xC050,0xC051,0xC052,0xC053,0xC7C4,0xC7C5,0xC054,0xC7C6,
+0xC055,0xC056,0xC057,0xC058,0xC059,0xC05A,0xC061,0xC062,
+0xC063,0xC064,0xC065,0xC066,0xC067,0xC068,0xC069,0xC06A,
+0xC06B,0xC06C,0xC06D,0xC06E,0xC06F,0xC070,0xC071,0xC072,
+0xC073,0xC074,0xC075,0xC076,0xC077,0xC078,0xC079,0xC07A,
+0xC081,0xC082,0xC083,0xC084,0xC7C7,0xC7C8,0xC085,0xC086,
+0xC7C9,0xC087,0xC088,0xC089,0xC7CA,0xC08A,0xC08B,0xC08C,
+0xC08D,0xC08E,0xC08F,0xC090,0xC7CB,0xC7CC,0xC091,0xC7CD,
+0xC092,0xC7CE,0xC093,0xC094,0xC095,0xC096,0xC097,0xC098,
+0xC7CF,0xC7D0,0xC099,0xC09A,0xC7D1,0xC09B,0xC09C,0xC09D,
+0xC7D2,0xC09E,0xC09F,0xC0A0,0xC141,0xC7D3,0xC142,0xC143,
+0xC7D4,0xC7D5,0xC144,0xC7D6,0xC145,0xC7D7,0xC146,0xC147,
+0xC148,0xC149,0xC14A,0xC14B,0xC7D8,0xC7D9,0xC14C,0xC14D,
+0xC7DA,0xC14E,0xC14F,0xC150,0xC7DB,0xC151,0xC152,0xC153,
+0xC154,0xC155,0xC156,0xC157,0xC7DC,0xC7DD,0xC158,0xC7DE,
+0xC7DF,0xC7E0,0xC159,0xC15A,0xC161,0xC162,0xC163,0xC164,
+0xC7E1,0xC165,0xC166,0xC167,0xC168,0xC169,0xC16A,0xC16B,
+0xC16C,0xC16D,0xC16E,0xC16F,0xC170,0xC171,0xC172,0xC173,
+0xC174,0xC175,0xC176,0xC177,0xC178,0xC7E2,0xC179,0xC17A,
+0xC181,0xC182,0xC183,0xC184,0xC185,0xC186,0xC187,0xC188,
+0xC189,0xC18A,0xC18B,0xC18C,0xC18D,0xC18E,0xC18F,0xC190,
+0xC191,0xC192,0xC193,0xC194,0xC195,0xC196,0xC197,0xC198,
+0xC199,0xC19A,0xC19B,0xC19C,0xC19D,0xC19E,0xC19F,0xC1A0,
+0xC7E3,0xC7E4,0xC241,0xC242,0xC7E5,0xC243,0xC244,0xC245,
+0xC7E6,0xC246,0xC7E7,0xC247,0xC248,0xC249,0xC24A,0xC24B,
+0xC7E8,0xC7E9,0xC24C,0xC7EA,0xC24D,0xC7EB,0xC24E,0xC24F,
+0xC250,0xC251,0xC252,0xC253,0xC7EC,0xC7ED,0xC254,0xC255,
+0xC7EE,0xC256,0xC257,0xC258,0xC7EF,0xC259,0xC25A,0xC261,
+0xC262,0xC263,0xC264,0xC265,0xC7F0,0xC7F1,0xC266,0xC7F2,
+0xC267,0xC7F3,0xC268,0xC269,0xC26A,0xC26B,0xC26C,0xC26D,
+0xC7F4,0xC7F5,0xC26E,0xC26F,0xC7F6,0xC270,0xC271,0xC272,
+0xC7F7,0xC273,0xC274,0xC275,0xC276,0xC277,0xC278,0xC279,
+0xC7F8,0xC7F9,0xC27A,0xC7FA,0xC7FB,0xC7FC,0xC281,0xC282,
+0xC283,0xC284,0xC285,0xC286,0xC7FD,0xC287,0xC288,0xC289,
+0xC7FE,0xC28A,0xC28B,0xC28C,0xC8A1,0xC28D,0xC28E,0xC28F,
+0xC290,0xC291,0xC292,0xC293,0xC294,0xC8A2,0xC295,0xC296,
+0xC297,0xC298,0xC299,0xC29A,0xC29B,0xC29C,0xC29D,0xC29E,
+0xC8A3,0xC8A4,0xC29F,0xC2A0,0xC8A5,0xC341,0xC342,0xC343,
+0xC8A6,0xC344,0xC345,0xC346,0xC347,0xC8A7,0xC348,0xC349,
+0xC8A8,0xC8A9,0xC34A,0xC8AA,0xC34B,0xC8AB,0xC34C,0xC34D,
+0xC34E,0xC8AC,0xC34F,0xC350,0xC8AD,0xC8AE,0xC351,0xC352,
+0xC8AF,0xC353,0xC354,0xC355,0xC8B0,0xC356,0xC357,0xC358,
+0xC359,0xC35A,0xC361,0xC362,0xC363,0xC364,0xC365,0xC8B1,
+0xC366,0xC8B2,0xC367,0xC368,0xC369,0xC36A,0xC36B,0xC36C,
+0xC8B3,0xC8B4,0xC36D,0xC36E,0xC8B5,0xC36F,0xC370,0xC371,
+0xC372,0xC373,0xC374,0xC375,0xC376,0xC377,0xC378,0xC379,
+0xC37A,0xC381,0xC382,0xC8B6,0xC383,0xC8B7,0xC384,0xC385,
+0xC386,0xC387,0xC388,0xC389,0xC8B8,0xC8B9,0xC38A,0xC38B,
+0xC8BA,0xC38C,0xC38D,0xC38E,0xC8BB,0xC38F,0xC390,0xC391,
+0xC392,0xC393,0xC394,0xC395,0xC396,0xC8BC,0xC397,0xC8BD,
+0xC398,0xC8BE,0xC399,0xC39A,0xC39B,0xC39C,0xC39D,0xC39E,
+0xC8BF,0xC39F,0xC3A0,0xC441,0xC8C0,0xC442,0xC443,0xC444,
+0xC8C1,0xC445,0xC446,0xC447,0xC448,0xC449,0xC44A,0xC44B,
+0xC44C,0xC8C2,0xC44D,0xC8C3,0xC44E,0xC44F,0xC450,0xC451,
+0xC452,0xC453,0xC454,0xC455,0xC8C4,0xC8C5,0xC456,0xC457,
+0xC8C6,0xC458,0xC459,0xC45A,0xC8C7,0xC461,0xC462,0xC463,
+0xC464,0xC8C8,0xC465,0xC466,0xC8C9,0xC467,0xC468,0xC8CA,
+0xC469,0xC8CB,0xC46A,0xC46B,0xC46C,0xC46D,0xC46E,0xC46F,
+0xC8CC,0xC470,0xC471,0xC472,0xC8CD,0xC473,0xC474,0xC475,
+0xC8CE,0xC476,0xC477,0xC478,0xC479,0xC47A,0xC481,0xC482,
+0xC8CF,0xC483,0xC484,0xC485,0xC486,0xC8D0,0xC487,0xC488,
+0xC489,0xC48A,0xC48B,0xC48C,0xC8D1,0xC8D2,0xC48D,0xC48E,
+0xC8D3,0xC48F,0xC490,0xC491,0xC8D4,0xC492,0xC493,0xC494,
+0xC495,0xC496,0xC497,0xC498,0xC499,0xC49A,0xC49B,0xC49C,
+0xC49D,0xC8D5,0xC49E,0xC49F,0xC4A0,0xC541,0xC542,0xC543,
+0xC8D6,0xC8D7,0xC544,0xC545,0xC8D8,0xC546,0xC547,0xC548,
+0xC8D9,0xC549,0xC54A,0xC54B,0xC54C,0xC54D,0xC54E,0xC54F,
+0xC8DA,0xC8DB,0xC550,0xC8DC,0xC551,0xC8DD,0xC552,0xC553,
+0xC554,0xC555,0xC556,0xC557,0xC8DE,0xC8DF,0xC558,0xC559,
+0xC8E0,0xC55A,0xC561,0xC562,0xC8E1,0xC563,0xC564,0xC565,
+0xC566,0xC567,0xC568,0xC569,0xC8E2,0xC56A,0xC56B,0xC8E3,
+0xC56C,0xC8E4,0xC56D,0xC56E,0xC56F,0xC570,0xC571,0xC572,
+0xC8E5,0xC8E6,0xC573,0xC574,0xC8E7,0xC575,0xC8E8,0xC8E9,
+0xC8EA,0xC8EB,0xC576,0xC577,0xC578,0xC579,0xC57A,0xC581,
+0xC8EC,0xC8ED,0xC582,0xC8EE,0xC583,0xC8EF,0xC584,0xC585,
+0xC586,0xC8F0,0xC587,0xC588,0xC8F1,0xC589,0xC58A,0xC58B,
+0xC8F2,0xC58C,0xC58D,0xC58E,0xC8F3,0xC58F,0xC590,0xC591,
+0xC592,0xC593,0xC594,0xC595,0xC8F4,0xC8F5,0xC596,0xC597,
+0xC598,0xC8F6,0xC599,0xC59A,0xC59B,0xC59C,0xC59D,0xC59E,
+0xC8F7,0xC8F8,0xC59F,0xC5A0,0xC8F9,0xC641,0xC642,0xC643,
+0xC8FA,0xC644,0xC645,0xC646,0xC647,0xC648,0xC649,0xC64A,
+0xC8FB,0xC8FC,0xC64B,0xC8FD,0xC64C,0xC8FE,0xC64D,0xC64E,
+0xC64F,0xC650,0xC651,0xC652};
+
+/* page 9 0xF900-0xFA0B */
+static uint16 tab_uni_ksc56019[]={
+0xCBD0,0xCBD6,0xCBE7,0xCDCF,0xCDE8,0xCEAD,0xCFFB,0xD0A2,
+0xD0B8,0xD0D0,0xD0DD,0xD1D4,0xD1D5,0xD1D8,0xD1DB,0xD1DC,
+0xD1DD,0xD1DE,0xD1DF,0xD1E0,0xD1E2,0xD1E3,0xD1E4,0xD1E5,
+0xD1E6,0xD1E8,0xD1E9,0xD1EA,0xD1EB,0xD1ED,0xD1EF,0xD1F0,
+0xD1F2,0xD1F6,0xD1FA,0xD1FC,0xD1FD,0xD1FE,0xD2A2,0xD2A3,
+0xD2A7,0xD2A8,0xD2A9,0xD2AA,0xD2AB,0xD2AD,0xD2B2,0xD2BE,
+0xD2C2,0xD2C3,0xD2C4,0xD2C6,0xD2C7,0xD2C8,0xD2C9,0xD2CA,
+0xD2CB,0xD2CD,0xD2CE,0xD2CF,0xD2D0,0xD2D1,0xD2D2,0xD2D3,
+0xD2D4,0xD2D5,0xD2D6,0xD2D7,0xD2D9,0xD2DA,0xD2DE,0xD2DF,
+0xD2E1,0xD2E2,0xD2E4,0xD2E5,0xD2E6,0xD2E7,0xD2E8,0xD2E9,
+0xD2EA,0xD2EB,0xD2F0,0xD2F1,0xD2F2,0xD2F3,0xD2F4,0xD2F5,
+0xD2F7,0xD2F8,0xD4E6,0xD4FC,0xD5A5,0xD5AB,0xD5AE,0xD6B8,
+0xD6CD,0xD7CB,0xD7E4,0xDBC5,0xDBE4,0xDCA5,0xDDA5,0xDDD5,
+0xDDF4,0xDEFC,0xDEFE,0xDFB3,0xDFE1,0xDFE8,0xE0F1,0xE1AD,
+0xE1ED,0xE3F5,0xE4A1,0xE4A9,0xE5AE,0xE5B1,0xE5B2,0xE5B9,
+0xE5BB,0xE5BC,0xE5C4,0xE5CE,0xE5D0,0xE5D2,0xE5D6,0xE5FA,
+0xE5FB,0xE5FC,0xE5FE,0xE6A1,0xE6A4,0xE6A7,0xE6AD,0xE6AF,
+0xE6B0,0xE6B1,0xE6B3,0xE6B7,0xE6B8,0xE6BC,0xE6C4,0xE6C6,
+0xE6C7,0xE6CA,0xE6D2,0xE6D6,0xE6D9,0xE6DC,0xE6DF,0xE6E1,
+0xE6E4,0xE6E5,0xE6E6,0xE6E8,0xE6EA,0xE6EB,0xE6EC,0xE6EF,
+0xE6F1,0xE6F2,0xE6F5,0xE6F6,0xE6F7,0xE6F9,0xE7A1,0xE7A6,
+0xE7A9,0xE7AA,0xE7AC,0xE7AD,0xE7B0,0xE7BF,0xE7C1,0xE7C6,
+0xE7C7,0xE7CB,0xE7CD,0xE7CF,0xE7D0,0xE7D3,0xE7DF,0xE7E4,
+0xE7E6,0xE7F7,0xE8E7,0xE8E8,0xE8F0,0xE8F1,0xE8F7,0xE8F9,
+0xE8FB,0xE8FE,0xE9A7,0xE9AC,0xE9CC,0xE9F7,0xEAC1,0xEAE5,
+0xEAF4,0xEAF7,0xEAFC,0xEAFE,0xEBA4,0xEBA7,0xEBA9,0xEBAA,
+0xEBBA,0xEBBB,0xEBBD,0xEBC1,0xEBC2,0xEBC6,0xEBC7,0xEBCC,
+0xEBCF,0xEBD0,0xEBD1,0xEBD2,0xEBD8,0xECA6,0xECA7,0xECAA,
+0xECAF,0xECB0,0xECB1,0xECB2,0xECB5,0xECB8,0xECBA,0xECC0,
+0xECC1,0xECC5,0xECC6,0xECC9,0xECCA,0xECD5,0xECDD,0xECDE,
+0xECE1,0xECE4,0xECE7,0xECE8,0xECF7,0xECF8,0xECFA,0xEDA1,
+0xEDA2,0xEDA3,0xEDEE,0xEEDB,0xF2BD,0xF2FA,0xF3B1,0xF4A7,
+0xF4EE,0xF6F4,0xF6F6,0xF7B8,0xF7C8,0xF7D3,0xF8DB,0xF8F0,
+0xFAA1,0xFAA2,0xFAE6,0xFCA9};
+
+/* page 10 0xFF01-0xFFE6 */
+static uint16 tab_uni_ksc560110[]={
+0xA3A1,0xA3A2,0xA3A3,0xA3A4,0xA3A5,0xA3A6,0xA3A7,0xA3A8,
+0xA3A9,0xA3AA,0xA3AB,0xA3AC,0xA3AD,0xA3AE,0xA3AF,0xA3B0,
+0xA3B1,0xA3B2,0xA3B3,0xA3B4,0xA3B5,0xA3B6,0xA3B7,0xA3B8,
+0xA3B9,0xA3BA,0xA3BB,0xA3BC,0xA3BD,0xA3BE,0xA3BF,0xA3C0,
+0xA3C1,0xA3C2,0xA3C3,0xA3C4,0xA3C5,0xA3C6,0xA3C7,0xA3C8,
+0xA3C9,0xA3CA,0xA3CB,0xA3CC,0xA3CD,0xA3CE,0xA3CF,0xA3D0,
+0xA3D1,0xA3D2,0xA3D3,0xA3D4,0xA3D5,0xA3D6,0xA3D7,0xA3D8,
+0xA3D9,0xA3DA,0xA3DB,0xA1AC,0xA3DD,0xA3DE,0xA3DF,0xA3E0,
+0xA3E1,0xA3E2,0xA3E3,0xA3E4,0xA3E5,0xA3E6,0xA3E7,0xA3E8,
+0xA3E9,0xA3EA,0xA3EB,0xA3EC,0xA3ED,0xA3EE,0xA3EF,0xA3F0,
+0xA3F1,0xA3F2,0xA3F3,0xA3F4,0xA3F5,0xA3F6,0xA3F7,0xA3F8,
+0xA3F9,0xA3FA,0xA3FB,0xA3FC,0xA3FD,0xA2A6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA1CB,
+0xA1CC,0xA1FE,0xA3FE, 0,0xA1CD,0xA3DC};
+
+static int func_uni_ksc5601_onechar(int code){
+ if ((code>=0x00A1)&&(code<=0x0167))
+ return(tab_uni_ksc56010[code-0x00A1]);
+ if ((code>=0x02C7)&&(code<=0x0451))
+ return(tab_uni_ksc56011[code-0x02C7]);
+ if ((code>=0x2015)&&(code<=0x2312))
+ return(tab_uni_ksc56012[code-0x2015]);
+ if ((code>=0x2460)&&(code<=0x266D))
+ return(tab_uni_ksc56013[code-0x2460]);
+ if ((code>=0x3000)&&(code<=0x327F))
+ return(tab_uni_ksc56014[code-0x3000]);
+ if ((code>=0x3380)&&(code<=0x33DD))
+ return(tab_uni_ksc56015[code-0x3380]);
+ if ((code>=0x4E00)&&(code<=0x947F))
+ return(tab_uni_ksc56016[code-0x4E00]);
+ if ((code>=0x9577)&&(code<=0x9F9C))
+ return(tab_uni_ksc56017[code-0x9577]);
+ if ((code>=0xAC00)&&(code<=0xD7A3))
+ return(tab_uni_ksc56018[code-0xAC00]);
+ if ((code>=0xF900)&&(code<=0xFA0B))
+ return(tab_uni_ksc56019[code-0xF900]);
+ if ((code>=0xFF01)&&(code<=0xFFE6))
+ return(tab_uni_ksc560110[code-0xFF01]);
+ return(0);
+}
+
+
+static int
+my_wc_mb_euc_kr(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *s, uchar *e)
+{
+ int code;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if (wc<0x80)
+ {
+ s[0]=wc;
+ return 1;
+ }
+
+ if (!(code=func_uni_ksc5601_onechar(wc)))
+ return MY_CS_ILUNI;
+
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=code>>8;
+ s[1]=code&0xFF;
+
+ return 2;
+}
+
+static int
+my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *pwc, const uchar *s, const uchar *e)
+{
+
+ int hi=s[0];
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ if (hi<0x80)
+ {
+ pwc[0]=hi;
+ return 1;
+ }
+
+ if (s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ if (!(pwc[0]=func_ksc5601_uni_onechar((hi<<8)+s[1])))
+ return MY_CS_ILSEQ;
+
+ return 2;
+}
+
+CHARSET_INFO my_charset_euc_kr =
+{
+ 19, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "euckr", /* cs name */
+ "euckr", /* name */
+ "", /* comment */
+ ctype_euc_kr,
+ to_lower_euc_kr,
+ to_upper_euc_kr,
+ sort_order_euc_kr,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_mb, /* wildcmp */
+ 2, /* mbmaxlen */
+ ismbchar_euc_kr,
+ ismbhead_euc_kr,
+ mbcharlen_euc_kr,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_mb_wc_euc_kr, /* mb_wc */
+ my_wc_mb_euc_kr, /* wc_mb */
+ my_caseup_str_mb,
+ my_casedn_str_mb,
+ my_caseup_mb,
+ my_casedn_mb,
+ my_tosort_8bit,
+ my_strcasecmp_mb,
+ my_strncasecmp_mb,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+#endif
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
new file mode 100644
index 00000000000..3e3cd38c063
--- /dev/null
+++ b/strings/ctype-extra.c
@@ -0,0 +1,3972 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <my_global.h>
+#include <m_ctype.h>
+
+
+#ifndef HAVE_CHARSET_latin1
+#define HAVE_CHARSET_latin1
+#endif
+
+#if defined(HAVE_CHARSET_latin1)||defined(HAVE_CHARSET_latin1_de)||\
+defined(HAVE_CHARSET_danish)||defined(HAVE_CHARSET_german1)
+
+static uint16 tab_8859_1_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+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,
+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 uchar tab_uni_8859_1_plane00[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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};
+
+static MY_UNI_IDX idx_uni_8859_1[]={
+ {0x0000,0x00FF,tab_uni_8859_1_plane00},
+ {0,0,NULL}
+};
+#endif
+
+#if defined(HAVE_CHARSET_latin2)||defined(HAVE_CHARSET_croat)||\
+defined(HAVE_CHARSET_hungarian)
+
+static uint16 tab_8859_2_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+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
+};
+
+
+/* 0000-00FD , 254 chars */
+static uchar tab_uni_8859_2_plane00[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0x00,0x00,0x00,0xA4,0x00,0x00,0xA7,0xA8,0x00,0x00,0x00,0x00,0xAD,0x00,0x00,
+0xB0,0x00,0x00,0x00,0xB4,0x00,0x00,0x00,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xC1,0xC2,0x00,0xC4,0x00,0x00,0xC7,0x00,0xC9,0x00,0xCB,0x00,0xCD,0xCE,0x00,
+0x00,0x00,0x00,0xD3,0xD4,0x00,0xD6,0xD7,0x00,0x00,0xDA,0x00,0xDC,0xDD,0x00,0xDF,
+0x00,0xE1,0xE2,0x00,0xE4,0x00,0x00,0xE7,0x00,0xE9,0x00,0xEB,0x00,0xED,0xEE,0x00,
+0x00,0x00,0x00,0xF3,0xF4,0x00,0xF6,0xF7,0x00,0x00,0xFA,0x00,0xFC,0xFD};
+
+/* 0102-017E , 125 chars */
+static uchar tab_uni_8859_2_plane01[]={
+0xC3,0xE3,0xA1,0xB1,0xC6,0xE6,0x00,0x00,0x00,0x00,0xC8,0xE8,0xCF,0xEF,0xD0,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xE5,0x00,0x00,0xA5,0xB5,0x00,0x00,0xA3,
+0xB3,0xD1,0xF1,0x00,0x00,0xD2,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD5,0xF5,
+0x00,0x00,0xC0,0xE0,0x00,0x00,0xD8,0xF8,0xA6,0xB6,0x00,0x00,0xAA,0xBA,0xA9,0xB9,
+0xDE,0xFE,0xAB,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xF9,0xDB,0xFB,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0xBC,0xAF,0xBF,0xAE,0xBE};
+
+/* 02C7-02DD , 23 chars */
+static uchar tab_uni_8859_2_plane02[]={
+0xB7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xA2,0xFF,0x00,0xB2,0x00,0xBD};
+
+static MY_UNI_IDX idx_uni_8859_2[]={
+ {0x0000,0x00FD,tab_uni_8859_2_plane00},
+ {0x0102,0x017E,tab_uni_8859_2_plane01},
+ {0x02C7,0x02DD,tab_uni_8859_2_plane02},
+ {0,0,NULL}
+};
+#endif
+
+#if defined(HAVE_CHARSET_cp1251) || defined(HAVE_CHARSET_win1251) || defined(HAVE_CHARSET_win1251ukr)
+static uint16 tab_cp1251_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x0402,0x0403,0x201A,0x0453,0x201E,0x2026,0x2020,0x2021,
+ 0,0x2030,0x0409,0x2039,0x040A,0x040C,0x040B,0x040F,
+0x0452,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
+ 0,0x2122,0x0459,0x203A,0x045A,0x045C,0x045B,0x045F,
+0x00A0,0x040E,0x045E,0x0408,0x00A4,0x0490,0x00A6,0x00A7,
+0x0401,0x00A9,0x0404,0x00AB,0x00AC,0x00AD,0x00AE,0x0407,
+0x00B0,0x00B1,0x0406,0x0456,0x0491,0x00B5,0x00B6,0x00B7,
+0x0451,0x2116,0x0454,0x00BB,0x0458,0x0405,0x0455,0x0457,
+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
+};
+
+/* 0000-00BB , 188 chars */
+static uchar tab_uni_cp1251_plane00[]={
+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,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,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,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0x00,0x00,0x00,0xA4,0x00,0xA6,0xA7,0x00,0xA9,0x00,0xAB,0xAC,0xAD,0xAE,0x00,
+0xB0,0xB1,0x00,0x00,0x00,0xB5,0xB6,0xB7,0x00,0x00,0x00,0xBB};
+
+/* 0401-0491 , 145 chars */
+static uchar tab_uni_cp1251_plane04[]={
+0xA8,0x80,0x81,0xAA,0xBD,0xB2,0xAF,0xA3,0x8A,0x8C,0x8E,0x8D,0x00,0xA1,0x8F,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,0x00,
+0xB8,0x90,0x83,0xBA,0xBE,0xB3,0xBF,0xBC,0x9A,0x9C,0x9E,0x9D,0x00,0xA2,0x9F,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,
+0xB4};
+
+/* 2013-203A , 40 chars */
+static uchar tab_uni_cp1251_plane20[]={
+0x96,0x97,0x00,0x00,0x00,0x91,0x92,0x82,0x00,0x93,0x94,0x84,0x00,0x86,0x87,0x95,
+0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x9B};
+
+/* 2116-2122 , 13 chars */
+static uchar tab_uni_cp1251_plane21[]={
+0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x99};
+
+static MY_UNI_IDX idx_uni_cp1251[]={
+ {0x0000,0x00BB,tab_uni_cp1251_plane00},
+ {0x0401,0x0491,tab_uni_cp1251_plane04},
+ {0x2013,0x203A,tab_uni_cp1251_plane20},
+ {0x2116,0x2122,tab_uni_cp1251_plane21},
+ {0,0,NULL}
+};
+#endif
+
+
+
+#ifdef HAVE_CHARSET_armscii8
+static uchar ctype_armscii8[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 16, 16
+};
+
+static uchar to_lower_armscii8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,184,169,170,171,172,173,174,175,
+ 176,177,179,179,181,181,183,183,185,185,187,187,189,189,191,191,
+ 193,193,195,195,197,197,199,199,201,201,203,203,205,205,207,207,
+ 209,209,211,211,213,213,215,215,217,217,219,219,221,221,223,223,
+ 225,225,227,227,229,229,231,231,233,233,235,235,237,237,239,239,
+ 241,241,243,243,245,245,247,247,249,249,251,251,253,253,254,255
+};
+
+static uchar to_upper_armscii8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,178,180,180,182,182,184,184,186,186,188,188,190,190,
+ 192,192,194,194,196,196,198,198,200,200,202,202,204,204,206,206,
+ 208,208,210,210,212,212,214,214,216,216,218,218,220,220,222,222,
+ 224,224,226,226,228,228,230,230,232,232,234,234,236,236,238,238,
+ 240,240,242,242,244,244,246,246,248,248,250,250,252,252,254,255
+};
+
+static uchar sort_order_armscii8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uint16 tab_armscii_8_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+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,0x2741,0x00A7,0x0589,0x0029,0x0028,0x00BB,0x00AB,
+0x2014,0x002E,0x055D,0x002C,0x002D,0x055F,0x2026,0x055C,
+0x055B,0x055E,0x0531,0x0561,0x0532,0x0562,0x0533,0x0563,
+0x0534,0x0564,0x0535,0x0565,0x0536,0x0566,0x0537,0x0567,
+0x0538,0x0568,0x0539,0x0569,0x053A,0x056A,0x053B,0x056B,
+0x053C,0x056C,0x053D,0x056D,0x053E,0x056E,0x053F,0x056F,
+0x0540,0x0570,0x0541,0x0571,0x0542,0x0572,0x0543,0x0573,
+0x0544,0x0574,0x0545,0x0575,0x0546,0x0576,0x0547,0x0577,
+0x0548,0x0578,0x0549,0x0579,0x054A,0x057A,0x054B,0x057B,
+0x054C,0x057C,0x054D,0x057D,0x054E,0x057E,0x054F,0x057F,
+0x0550,0x0580,0x0551,0x0581,0x0552,0x0582,0x0553,0x0583,
+0x0554,0x0584,0x0555,0x0585,0x0556,0x0586,0x2019,0x0027
+};
+
+
+/* 0000-00BB , 188 chars */
+static uchar tab_uni_armscii_8_plane00[]={
+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,0xFF,0xA5,0xA4,0x2A,0x2B,0xAB,0xAC,0xA9,0x2F,
+0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0x00,0x00,0x00,0xA7,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA6};
+
+/* 0531-0589 , 89 chars */
+static uchar tab_uni_armscii_8_plane05[]={
+0xB2,0xB4,0xB6,0xB8,0xBA,0xBC,0xBE,0xC0,0xC2,0xC4,0xC6,0xC8,0xCA,0xCC,0xCE,0xD0,
+0xD2,0xD4,0xD6,0xD8,0xDA,0xDC,0xDE,0xE0,0xE2,0xE4,0xE6,0xE8,0xEA,0xEC,0xEE,0xF0,
+0xF2,0xF4,0xF6,0xF8,0xFA,0xFC,0x00,0x00,0x00,0x00,0xB0,0xAF,0xAA,0xB1,0xAD,0x00,
+0xB3,0xB5,0xB7,0xB9,0xBB,0xBD,0xBF,0xC1,0xC3,0xC5,0xC7,0xC9,0xCB,0xCD,0xCF,0xD1,
+0xD3,0xD5,0xD7,0xD9,0xDB,0xDD,0xDF,0xE1,0xE3,0xE5,0xE7,0xE9,0xEB,0xED,0xEF,0xF1,
+0xF3,0xF5,0xF7,0xF9,0xFB,0xFD,0x00,0x00,0xA3};
+
+/* 2014-2026 , 19 chars */
+static uchar tab_uni_armscii_8_plane20[]={
+0xA8,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xAE};
+
+/* 2741-2741 , 1 chars */
+static uchar tab_uni_armscii_8_plane27[]={
+0xA1};
+
+
+static MY_UNI_IDX idx_uni_armscii_8[]={
+ {0x0000,0x00BB,tab_uni_armscii_8_plane00},
+ {0x0531,0x0589,tab_uni_armscii_8_plane05},
+ {0x2014,0x2026,tab_uni_armscii_8_plane20},
+ {0x2741,0x2741,tab_uni_armscii_8_plane27},
+ {0,0,NULL}
+};
+
+#endif
+
+
+#ifdef HAVE_CHARSET_cp1251
+
+/* The cp1251 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_cp1251[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_cp1251[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,184,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_cp1251[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,168,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
+};
+
+static uchar sort_order_cp1251[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,124,125,126,127,128,
+ 129, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,130,131,132,133,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255, 97,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255, 97,255,255,255,255,255,255,255,
+ 91, 92, 93, 94, 95, 96, 98, 99,100,101,102,103,104,105,106,107,
+ 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,
+ 91, 92, 93, 94, 95, 96, 98, 99,100,101,102,103,104,105,106,107,
+ 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123
+};
+
+#endif
+
+
+#ifdef HAVE_CHARSET_cp1257
+
+/* The cp1257 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_cp1257[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
+ 2, 2, 0, 0, 0, 0, 2, 0, 2, 0, 0, 2, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0
+};
+
+static uchar to_lower_cp1257[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,194,195,196,197,230,199,232,201,202,235,204,205,206,207,
+ 240,209,210,211,212,213,214,215,248,217,218,251,220,221,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_cp1257[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,226,227,228,229,198,231,200,233,234,203,236,237,238,239,
+ 208,241,242,243,244,245,246,247,216,249,250,219,252,253,222,255
+};
+
+static uchar sort_order_cp1257[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 67, 68, 70, 71, 74, 75, 76, 77, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 91, 92, 95, 96, 97, 78,255, 98, 99,100,101,102,
+ 103, 65, 67, 68, 70, 71, 74, 75, 76, 77, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 91, 92, 95, 96, 97, 78,255,104,105,106,107,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 66, 79,255,255,255,255, 72,255, 69,255,255, 73,255,255,255,255,
+ 90,255,255,255,255,255,255,255, 94,255,255, 93,255,255,255,255,
+ 255, 79,255,255,255,255, 72,255, 69,255,255, 73,255,255,255,255,
+ 90,255,255,255,255,255,255,255, 94,255,255, 93,255,255,255,255
+};
+
+static uint16 tab_cp1257_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x20AC, 0,0x201A, 0,0x201E,0x2026,0x2020,0x2021,
+ 0,0x2030, 0,0x2039, 0,0x00A8,0x02C7,0x00B8,
+ 0,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
+ 0,0x2122, 0,0x203A, 0,0x00AF,0x02DB, 0,
+0x00A0, 0,0x00A2,0x00A3,0x00A4, 0,0x00A6,0x00A7,
+0x00D8,0x00A9,0x0156,0x00AB,0x00AC,0x00AD,0x00AE,0x00C6,
+0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,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,0x02D9
+};
+
+
+/* 0000-00FC , 253 chars */
+static uchar tab_uni_cp1257_plane00[]={
+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,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,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,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0x00,0xA2,0xA3,0xA4,0x00,0xA6,0xA7,0x8D,0xA9,0x00,0xAB,0xAC,0xAD,0xAE,0x9D,
+0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0x8F,0xB9,0x00,0xBB,0xBC,0xBD,0xBE,0x00,
+0x00,0x00,0x00,0x00,0xC4,0xC5,0xAF,0x00,0x00,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0xD3,0x00,0xD5,0xD6,0xD7,0xA8,0x00,0x00,0x00,0xDC,0x00,0x00,0xDF,
+0x00,0x00,0x00,0x00,0xE4,0xE5,0xBF,0x00,0x00,0xE9,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0xF3,0x00,0xF5,0xF6,0xF7,0xB8,0x00,0x00,0x00,0xFC};
+
+/* 0100-017E , 127 chars */
+static uchar tab_uni_cp1257_plane01[]={
+0xC2,0xE2,0x00,0x00,0xC0,0xE0,0xC3,0xE3,0x00,0x00,0x00,0x00,0xC8,0xE8,0x00,0x00,
+0x00,0x00,0xC7,0xE7,0x00,0x00,0xCB,0xEB,0xC6,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xEE,0x00,0x00,0xC1,0xE1,
+0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0xED,0x00,0x00,0x00,0xCF,0xEF,0x00,0x00,0x00,
+0x00,0xD9,0xF9,0xD1,0xF1,0xD2,0xF2,0x00,0x00,0x00,0x00,0x00,0xD4,0xF4,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xBA,0x00,0x00,0xDA,0xFA,0x00,0x00,0x00,0x00,
+0xD0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xFB,0x00,0x00,0x00,0x00,
+0x00,0x00,0xD8,0xF8,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xDD,0xFD,0xDE,0xFE};
+
+/* 2013-20AC , 154 chars */
+static uchar tab_uni_cp1257_plane20[]={
+0x96,0x97,0x00,0x00,0x00,0x91,0x92,0x82,0x00,0x93,0x94,0x84,0x00,0x86,0x87,0x95,
+0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80};
+
+/* 02C7-02DB , 21 chars */
+static uchar tab_uni_cp1257_plane02[]={
+0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xFF,0x00,0x9E};
+
+/* 2122-2122 , 1 chars */
+static uchar tab_uni_cp1257_plane21[]={
+0x99};
+
+static MY_UNI_IDX idx_uni_cp1257[]={
+ {0x0000,0x00FC,tab_uni_cp1257_plane00},
+ {0x0100,0x017E,tab_uni_cp1257_plane01},
+ {0x2013,0x20AC,tab_uni_cp1257_plane20},
+ {0x02C7,0x02DB,tab_uni_cp1257_plane02},
+ {0x2122,0x2122,tab_uni_cp1257_plane21},
+ {0,0,NULL}
+};
+
+#endif
+
+
+#ifdef HAVE_CHARSET_croat
+
+/* The croat character set. Generated by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_croat[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_croat[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,154,139,140,141,158,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_croat[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,138,155,156,157,142,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_croat[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137, 87,139,140,141, 95,143,
+ 144,145,146,147,148,149,150,151,152,153, 87,155,156,157, 95,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65, 92, 91, 69, 67, 68, 69, 69, 69, 73, 73, 73, 73,
+ 71, 78, 79, 79, 79, 79, 93,215,216, 85, 85, 85, 89, 89,222,223,
+ 65, 65, 65, 65, 92, 91, 69, 67, 68, 69, 69, 69, 73, 73, 73, 73,
+ 71, 78, 79, 79, 79, 79, 93,247,216, 85, 85, 85, 89, 89,222,255
+};
+#endif
+
+
+#ifdef HAVE_CHARSET_danish
+
+/* The danish character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_danish[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_danish[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_danish[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_danish[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65, 91, 93, 91, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 92,215, 92, 85, 85, 85, 89, 89,222,223,
+ 65, 65, 65, 65, 91, 93, 91, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 92,247, 92, 85, 85, 85, 89, 89,222,255
+};
+#endif
+
+
+
+#ifdef HAVE_CHARSET_dec8
+
+/* The dec8 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_dec8[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_dec8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_dec8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_dec8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 93,215,216, 85, 85, 85, 89, 89,222,223,
+ 65, 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 93,247,216, 85, 85, 85, 89, 89,222,255
+};
+#endif
+
+
+#ifdef HAVE_CHARSET_dos
+
+/* The dos character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_dos[] = {
+ 0,
+ 32, 48, 48, 48, 48, 48, 48, 32, 32, 40, 40, 40, 40, 40, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32, 48, 48, 48, 48, 48,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 48,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+ 1, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 16, 16, 16, 16, 16,
+ 2, 2, 2, 2, 2, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32
+};
+
+static uchar to_lower_dos[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 135,129,130,131,132,133,134,135,136,137,138,139,140,141,132,134,
+ 130,145,145,147,148,149,150,151,152,148,129,155,156,157,158,159,
+ 160,161,162,163,164,164,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_dos[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,154,144, 65,142, 65,143,128, 69, 69, 69, 73, 73, 73,142,143,
+ 144,146,146, 79,153, 79, 85, 85, 89,153,154,155,156,157,158,159,
+ 65, 73, 79, 85,165,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_dos[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 67, 89, 69, 65, 92, 65, 91, 67, 69, 69, 69, 73, 73, 73, 92, 91,
+ 69, 92, 92, 79, 93, 79, 85, 85, 89, 93, 89, 36, 36, 36, 36, 36,
+ 65, 73, 79, 85, 78, 78,166,167, 63,169,170,171,172, 33, 34, 34,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_estonia
+
+/* The estonia character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_estonia[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_estonia[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,184,169,186,171,172,173,174,191,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_estonia[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,168,185,170,187,188,189,190,175,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_estonia[] = {
+ 0, 2, 3, 4, 5, 6, 7, 8, 9, 46, 47, 48, 49, 50, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 44, 51, 52, 53, 54, 55, 56, 39, 57, 58, 59, 93, 60, 40, 61, 62,
+ 118,122,124,126,128,129,130,131,132,133, 63, 64, 94, 95, 96, 65,
+ 66,134,144,146,152,154,164,166,170,172,178,180,184,190,192,198,
+ 206,208,210,214,229,232,238,240,250,252,221, 67, 68, 69, 70, 71,
+ 72,135,145,147,153,155,165,167,171,173,179,181,185,191,193,199,
+ 207,209,211,215,230,233,239,241,251,253,222, 73, 74, 75, 76, 28,
+ 1, 29, 87, 30, 90,116,113,114, 31,117, 32, 91, 33, 78, 82, 81,
+ 34, 85, 86, 88, 89,115, 42, 43, 35,231, 36, 92, 37, 79, 84, 38,
+ 45,254,102,103,104,255, 77,105,204,106,212, 98,107, 41,108,142,
+ 109, 97,125,127, 80,110,111,112,205,123,213, 99,119,120,121,143,
+ 140,176,136,148,244,138,162,160,150,156,223,158,168,182,174,186,
+ 219,194,196,200,202,242,246,100,236,188,216,234,248,225,227,218,
+ 141,177,137,149,245,139,163,161,151,157,224,159,169,183,175,187,
+ 220,195,197,201,203,243,247,101,237,189,217,235,249,226,228, 83
+};
+#endif
+
+#ifdef HAVE_CHARSET_german1
+
+/* The german1 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_german1[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_german1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_german1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_german1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 208, 78, 79, 79, 79, 79, 79,215, 79, 85, 85, 85, 85, 89,222, 83,
+ 65, 65, 65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 208, 78, 79, 79, 79, 79, 79,247, 79, 85, 85, 85, 85, 89,222,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_greek
+
+/* The greek character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_greek[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 0, 0, 16, 16, 16, 16, 0, 16, 16, 16, 0, 16,
+ 16, 16, 16, 16, 16, 16, 1, 16, 1, 1, 1, 16, 1, 16, 1, 1,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0
+};
+
+static uchar to_lower_greek[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,220,183,221,222,223,187,252,189,253,254,
+ 192,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,210,243,244,245,246,247,248,249,250,251,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_greek[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 218,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,193,197,199,201,
+ 219,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,211,211,212,213,214,215,216,217,218,219,207,213,217,255
+};
+
+static uchar sort_order_greek[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,193,183,197,199,201,187,207,189,213,217,
+ 201,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,201,213,193,197,199,201,
+ 213,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,211,211,212,213,214,215,216,217,201,213,207,213,217,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_hebrew
+
+/* The hebrew character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_hebrew[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0
+};
+
+static uchar to_lower_hebrew[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_hebrew[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_hebrew[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_hp8
+
+/* The hp8 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_hp8[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 2, 16, 2, 2,
+ 1, 16, 16, 1, 2, 16, 16, 2, 1, 16, 1, 1, 1, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32
+};
+
+static uchar to_lower_hp8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,200,192,201,193,205,209,221,168,169,170,171,172,203,195,175,
+ 176,178,178,179,181,181,183,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 212,209,214,215,212,213,214,215,204,217,206,207,197,221,222,194,
+ 196,226,226,228,228,213,217,198,202,234,234,236,236,199,239,239,
+ 241,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_hp8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,177,179,180,180,182,182,184,185,186,187,188,189,190,191,
+ 162,164,223,174,224,220,231,237,161,163,232,173,216,165,218,219,
+ 208,166,210,211,208,229,210,211,216,230,218,219,220,167,222,223,
+ 224,225,225,227,227,229,230,231,232,233,233,235,235,237,238,238,
+ 240,240,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_hp8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 91, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_hungarian
+
+/* The hungarian character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_hungarian[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 72,
+ 1, 16, 1, 16, 1, 1, 16, 0, 0, 1, 1, 1, 1, 16, 1, 1,
+ 16, 2, 16, 2, 16, 2, 2, 16, 16, 2, 2, 2, 2, 16, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 16, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 16,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 16
+};
+
+static uchar to_lower_hungarian[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,139,139,161,161,142,160,
+ 130,145,146,147,148,162,150,163,150,148,129,155,156,157,158,159,
+ 160,161,162,163,181,182,166,147,168,185,186,187,188,173,190,191,
+ 176,177,178,179,180,225,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 208,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 162,225,226,227,228,229,230,231,232,233,234,150,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_hungarian[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,154,144,131,132,133,134,135,136,137,138,138,140,141,142,143,
+ 144,145,146,167,153,149,152,151,152,153,154,155,156,157,158,159,
+ 143,141,149,151,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,160,178,162,180,181,165,183,184,169,170,171,172,189,174,175,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,193,194,195,196,197,198,199,200,201,202,235,204,205,206,207,
+ 240,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_hungarian[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 71, 72, 76, 78, 83, 84, 85, 86, 90, 91, 92, 96, 97,100,
+ 105,106,107,110,114,117,122,123,124,125,127,131,132,133,134,135,
+ 136, 65, 71, 72, 76, 78, 83, 84, 85, 86, 90, 91, 92, 96, 97,100,
+ 105,106,107,110,114,117,122,123,124,125,127,137,138,139,140, 0,
+ 1,120, 78, 4, 5, 6, 7, 8, 9, 10,103,103, 86, 86, 15, 65,
+ 78, 18, 19,103,103,100,120,117,120,103,120, 28, 29, 30, 31,255,
+ 65, 86,100,117, 94,111,255,103,255,112,113,115,128,255,129,130,
+ 255, 66,255, 93,255, 65,111,255,255,112,113,115,128,255,129,130,
+ 108, 65, 68, 69, 70, 95, 73, 75, 74, 78, 81, 82, 80, 86, 87, 77,
+ 255, 98, 99,100,102,103,103,255,109,119,117,120,120,126,116,255,
+ 100, 65, 68, 69, 70, 95, 73, 75, 74, 78, 81,120, 80, 86, 88, 77,
+ 255, 98, 99,100,102,103,103,255,109,119,117,120,120,126,116,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_koi8_ru
+
+/* The koi8_ru character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_koi8_ru[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static uchar to_lower_koi8_ru[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,163,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
+};
+
+static uchar to_upper_koi8_ru[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,179,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_koi8_ru[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,229,163,164,165,166,167,168,169,170,171,172,173,174,
+ 175,176,177,229,178,179,180,181,182,183,184,185,186,187,188,189,
+ 254,223,224,246,227,228,244,226,245,232,233,234,235,236,237,238,
+ 239,255,240,241,242,243,230,225,252,251,231,248,253,249,247,250,
+ 254,223,224,246,227,228,244,226,245,232,233,234,235,236,237,238,
+ 239,255,240,241,242,243,230,225,252,251,231,248,253,249,247,250
+};
+
+static uint16 tab_koi8_r_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x2500,0x2502,0x250C,0x2510,0x2514,0x2518,0x251C,0x2524,
+0x252C,0x2534,0x253C,0x2580,0x2584,0x2588,0x258C,0x2590,
+0x2591,0x2592,0x2593,0x2320,0x25A0,0x2219,0x221A,0x2248,
+0x2264,0x2265,0x00A0,0x2321,0x00B0,0x00B2,0x00B7,0x00F7,
+0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
+0x2557,0x2558,0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,
+0x255F,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
+0x2566,0x2567,0x2568,0x2569,0x256A,0x256B,0x256C,0x00A9,
+0x044E,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
+0x0445,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,
+0x043F,0x044F,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
+0x044C,0x044B,0x0437,0x0448,0x044D,0x0449,0x0447,0x044A,
+0x042E,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
+0x0425,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
+0x041F,0x042F,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
+0x042C,0x042B,0x0417,0x0428,0x042D,0x0429,0x0427,0x042A
+};
+
+
+/* 0000-00F7 , 248 chars */
+static uchar tab_uni_koi8_r_plane00[]={
+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,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,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,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,
+0x9C,0x00,0x9D,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F};
+
+/* 0401-0451 , 81 chars */
+static uchar tab_uni_koi8_r_plane04[]={
+0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,
+0xE2,0xF7,0xE7,0xE4,0xE5,0xF6,0xFA,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF2,
+0xF3,0xF4,0xF5,0xE6,0xE8,0xE3,0xFE,0xFB,0xFD,0xFF,0xF9,0xF8,0xFC,0xE0,0xF1,0xC1,
+0xC2,0xD7,0xC7,0xC4,0xC5,0xD6,0xDA,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD2,
+0xD3,0xD4,0xD5,0xC6,0xC8,0xC3,0xDE,0xDB,0xDD,0xDF,0xD9,0xD8,0xDC,0xC0,0xD1,0x00,
+0xA3};
+
+/* 2500-25A0 , 161 chars */
+static uchar tab_uni_koi8_r_plane25[]={
+0x80,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,
+0x83,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x86,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0xA1,0xA2,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,
+0xB1,0xB2,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8B,0x00,0x00,0x00,0x8C,0x00,0x00,0x00,0x8D,0x00,0x00,0x00,0x8E,0x00,0x00,0x00,
+0x8F,0x90,0x91,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x94};
+
+/* 2219-2265 , 77 chars */
+static uchar tab_uni_koi8_r_plane22[]={
+0x95,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x97,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x99};
+
+/* 2320-2321 , 2 chars */
+static uchar tab_uni_koi8_r_plane23[]={
+0x93,0x9B};
+
+
+static MY_UNI_IDX idx_uni_koi8_r[]={
+ {0x0000,0x00F7,tab_uni_koi8_r_plane00},
+ {0x0401,0x0451,tab_uni_koi8_r_plane04},
+ {0x2500,0x25A0,tab_uni_koi8_r_plane25},
+ {0x2219,0x2265,tab_uni_koi8_r_plane22},
+ {0x2320,0x2321,tab_uni_koi8_r_plane23},
+ {0,0,NULL}
+};
+
+#endif
+
+#ifdef HAVE_CHARSET_koi8_ukr
+
+/* The koi8_ukr character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_koi8_ukr[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 2, 2, 16, 2, 2, 16, 16, 16, 16, 16, 2, 16, 16,
+ 16, 16, 16, 1, 1, 16, 1, 1, 16, 16, 16, 16, 16, 1, 16, 16,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static uchar to_lower_koi8_ukr[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 32, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32,163,164, 32,166,167, 32, 32, 32, 32, 32,173, 32, 32,
+ 32, 32, 32,163,164, 32,166,167, 32, 32, 32, 32, 32,173, 32, 32,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
+};
+
+static uchar to_upper_koi8_ukr[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 32, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32,179,180, 32,182,183, 32, 32, 32, 32, 32,189, 32, 32,
+ 32, 32, 32,179,180, 32,182,183, 32, 32, 32, 32, 32,189, 32, 32,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_koi8_ukr[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 32, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,
+ 181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
+ 197,198,199,136,135,200,140,141,201,202,203,204,205,132,206,207,
+ 208,209,210,136,135,211,140,141,212,213,214,215,216,132,217,218,
+ 163,128,129,155,133,134,153,131,154,139,142,143,144,145,146,147,
+ 148,164,149,150,151,152,137,130,161,160,138,157,162,158,156,159,
+ 163,128,129,155,133,134,153,131,154,139,142,143,144,145,146,147,
+ 148,164,149,150,151,152,137,130,161,160,138,157,162,158,156,159
+};
+
+static uint16 tab_koi8_u_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+0x2500,0x2502,0x250C,0x2510,0x2514,0x2518,0x251C,0x2524,
+0x252C,0x2534,0x253C,0x2580,0x2584,0x2588,0x258C,0x2590,
+0x2591,0x2592,0x2593,0x2320,0x25A0,0x2022,0x221A,0x2248,
+0x2264,0x2265,0x00A0,0x2321,0x00B0,0x00B2,0x00B7,0x00F7,
+0x2550,0x2551,0x2552,0x0451,0x0454,0x2554,0x0456,0x0457,
+0x2557,0x2558,0x2559,0x255A,0x255B,0x0491,0x255D,0x255E,
+0x255F,0x2560,0x2561,0x0401,0x0404,0x2563,0x0406,0x0407,
+0x2566,0x2567,0x2568,0x2569,0x256A,0x0490,0x256C,0x00A9,
+0x044E,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
+0x0445,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,
+0x043F,0x044F,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
+0x044C,0x044B,0x0437,0x0448,0x044D,0x0449,0x0447,0x044A,
+0x042E,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
+0x0425,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
+0x041F,0x042F,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
+0x042C,0x042B,0x0417,0x0428,0x042D,0x0429,0x0427,0x042A
+};
+
+
+/* 0000-00F7 , 248 chars */
+static uchar tab_uni_koi8_u_plane00[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,
+0x9C,0x00,0x9D,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F};
+
+/* 0401-0491 , 145 chars */
+static uchar tab_uni_koi8_u_plane04[]={
+0xB3,0x00,0x00,0xB4,0x00,0xB6,0xB7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,
+0xE2,0xF7,0xE7,0xE4,0xE5,0xF6,0xFA,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF2,
+0xF3,0xF4,0xF5,0xE6,0xE8,0xE3,0xFE,0xFB,0xFD,0xFF,0xF9,0xF8,0xFC,0xE0,0xF1,0xC1,
+0xC2,0xD7,0xC7,0xC4,0xC5,0xD6,0xDA,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD2,
+0xD3,0xD4,0xD5,0xC6,0xC8,0xC3,0xDE,0xDB,0xDD,0xDF,0xD9,0xD8,0xDC,0xC0,0xD1,0x00,
+0xA3,0x00,0x00,0xA4,0x00,0xA6,0xA7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD,
+0xAD};
+
+/* 2500-25A0 , 161 chars */
+static uchar tab_uni_koi8_u_plane25[]={
+0x80,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,
+0x83,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x86,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0xA1,0xA2,0x00,0xA5,0x00,0x00,0xA8,0xA9,0xAA,0xAB,0xAC,0x00,0xAE,0xAF,0xB0,
+0xB1,0xB2,0x00,0xB5,0x00,0x00,0xB8,0xB9,0xBA,0xBB,0xBC,0x00,0xBE,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8B,0x00,0x00,0x00,0x8C,0x00,0x00,0x00,0x8D,0x00,0x00,0x00,0x8E,0x00,0x00,0x00,
+0x8F,0x90,0x91,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x94};
+
+/* 221A-2265 , 76 chars */
+static uchar tab_uni_koi8_u_plane22[]={
+0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x97,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x99};
+
+/* 2320-2321 , 2 chars */
+static uchar tab_uni_koi8_u_plane23[]={
+0x93,0x9B};
+
+/* 2022-2022 , 1 chars */
+static uchar tab_uni_koi8_u_plane20[]={
+0x95};
+
+
+static MY_UNI_IDX idx_uni_koi8_u[]={
+ {0x0000,0x00F7,tab_uni_koi8_u_plane00},
+ {0x0401,0x0491,tab_uni_koi8_u_plane04},
+ {0x2500,0x25A0,tab_uni_koi8_u_plane25},
+ {0x221A,0x2265,tab_uni_koi8_u_plane22},
+ {0x2320,0x2321,tab_uni_koi8_u_plane23},
+ {0x2022,0x2022,tab_uni_koi8_u_plane20},
+ {0,0,NULL}
+};
+
+#endif
+
+#ifdef HAVE_CHARSET_latin1
+
+/* The latin1 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_latin1[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_latin1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_latin1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_latin1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 93,215,216, 85, 85, 85, 89, 89,222,223,
+ 65, 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 93,247,216, 85, 85, 85, 89, 89,222,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_latin2
+
+/* The latin2 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_latin2[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 1, 16, 1, 16, 1, 1, 16, 16, 1, 1, 1, 1, 16, 1, 1,
+ 16, 2, 16, 2, 16, 2, 2, 16, 16, 2, 2, 2, 2, 16, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 16, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 16,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 16
+};
+
+static uchar to_lower_latin2[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,177,162,179,164,181,182,167,168,185,186,187,188,173,190,191,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 208,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_latin2[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,161,178,163,180,165,166,183,184,169,170,171,172,189,174,175,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 240,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_latin2[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 68, 69, 72, 73, 75, 76, 77, 78, 79, 80, 81, 83, 84, 86,
+ 88, 89, 90, 91, 94, 95, 96, 97, 98, 99,100,104,105,106,107,108,
+ 109, 65, 68, 69, 72, 73, 75, 76, 77, 78, 79, 80, 81, 83, 84, 86,
+ 88, 89, 90, 91, 94, 95, 96, 97, 98, 99,100,110,111,112,113,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255, 66,255, 82,255, 81, 92,255,255, 93, 91, 94,101,255,103,102,
+ 255, 66,255, 82,255, 81, 92,255,255, 93, 91, 94,101,255,103,102,
+ 90, 67, 67, 67, 67, 81, 70, 69, 71, 73, 74, 73, 73, 78, 78, 72,
+ 255, 85, 84, 87, 86, 86, 86,255, 90, 95, 95, 95, 95, 99, 94,255,
+ 90, 67, 67, 67, 67, 81, 70, 69, 71, 73, 74, 73, 73, 78, 78, 72,
+ 255, 85, 84, 87, 86, 86, 86,255, 90, 95, 95, 95, 95, 99, 94,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_latin5
+
+/* The latin5 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_latin5[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_latin5[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,253,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,105,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_latin5[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72,221, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220, 73,222,255
+};
+
+static uchar sort_order_latin5[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 69, 70, 71, 72, 74, 75, 77, 78, 79, 80, 81, 82,
+ 84, 85, 86, 87, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99,100,101,
+ 102, 65, 66, 67, 69, 70, 71, 72, 74, 76, 77, 78, 79, 80, 81, 82,
+ 84, 85, 86, 87, 89, 90, 92, 93, 94, 95, 96,135,136,137,138,139,
+ 140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
+ 156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,
+ 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,
+ 188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,
+ 204,205,206,207,208,209,210, 68,211,212,213,214,215,216,217,218,
+ 73,219,220,221,222,223, 83,224,225,226,227,228, 91, 76, 88,229,
+ 204,205,206,207,208,209,210, 68,211,212,213,214,215,216,217,218,
+ 73,219,220,221,222,223, 83,250,225,226,227,228, 91, 75, 88,255
+};
+
+static uint16 tab_8859_9_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+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
+};
+
+
+/* 0000-00FF , 256 chars */
+static uchar tab_uni_8859_9_plane00[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,
+0x00,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0x00,0x00,0xDF,
+0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+0x00,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0x00,0x00,0xFF};
+
+/* 011E-015F , 66 chars */
+static uchar tab_uni_8859_9_plane01[]={
+0xD0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xDD,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xDE,0xFE};
+
+
+static MY_UNI_IDX idx_uni_8859_9[]={
+ {0x0000,0x00FF,tab_uni_8859_9_plane00},
+ {0x011E,0x015F,tab_uni_8859_9_plane01},
+ {0,0,NULL}
+};
+
+#endif
+
+#ifdef HAVE_CHARSET_swe7
+
+/* The swe7 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_swe7[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 1,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16,
+ 1,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static uchar to_lower_swe7[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_swe7[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_swe7[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 69, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 91, 89, 95,
+ 69, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 91, 89,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+#endif
+
+#ifdef HAVE_CHARSET_usa7
+
+/* The usa7 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_usa7[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static uchar to_lower_usa7[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_usa7[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_usa7[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 91, 94, 95,
+ 69, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125, 89,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uint16 tab_us_ascii_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+/* 0000-007E , 127 chars */
+static uchar tab_uni_us_ascii_plane00[]={
+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,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,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};
+
+
+static MY_UNI_IDX idx_uni_us_ascii[]={
+ {0x0000,0x007E,tab_uni_us_ascii_plane00},
+ {0,0,NULL}
+};
+
+#endif
+
+#ifdef HAVE_CHARSET_win1250
+
+/* The win1250 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_win1250[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 32, 32, 16, 32, 16, 16, 16, 16, 32, 16, 1, 16, 1, 1, 1, 1,
+ 32, 16, 16, 16, 16, 16, 16, 16, 32, 16, 2, 16, 2, 2, 2, 2,
+ 72, 16, 16, 1, 16, 1, 16, 1, 16, 16, 1, 16, 16, 16, 16, 1,
+ 16, 16, 16, 2, 16, 16, 16, 16, 16, 2, 2, 16, 1, 16, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 16
+};
+
+static uchar to_lower_win1250[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,154,139,156,157,158,159,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,179,164,185,166,223,168,169,186,171,172,173,174,191,
+ 176,177,178,179,180,181,182,183,184,185,186,187,190,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_win1250[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,138,155,140,141,142,143,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,163,180,181,182,183,184,165,170,187,188,189,188,175,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,167,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_win1250[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 70, 73, 74, 75, 76, 77, 78, 79, 80, 82, 83, 85,
+ 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 99,100,101,102,103,
+ 104, 65, 66, 67, 70, 73, 74, 75, 76, 77, 78, 79, 80, 82, 83, 85,
+ 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137, 90,139, 90, 91, 98, 98,
+ 144,145,146,147,148,149,150,151,152,153, 90,155, 90, 91, 98, 98,
+ 32,161,162, 80,164, 65,166, 89,168,169, 89,171,172,173,174, 98,
+ 176,177,178, 80,180,181,182,183,184, 65, 89,187, 80,189, 80, 98,
+ 88, 65, 65, 65, 65, 80, 69, 67, 68, 73, 73, 73, 73, 77, 77, 70,
+ 71, 83, 83, 85, 85, 85, 85,215, 88, 92, 92, 92, 92, 96, 91, 89,
+ 88, 65, 65, 65, 65, 80, 69, 67, 68, 73, 73, 73, 73, 77, 77, 70,
+ 71, 83, 83, 85, 85, 85, 85,247, 88, 92, 92, 92, 92, 96, 91,255
+};
+#endif
+
+#if defined(HAVE_CHARSET_win1250)
+
+static uint16 tab_cp1250_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x20AC, 0,0x201A, 0,0x201E,0x2026,0x2020,0x2021,
+ 0,0x2030,0x0160,0x2039,0x015A,0x0164,0x017D,0x0179,
+ 0,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
+ 0,0x2122,0x0161,0x203A,0x015B,0x0165,0x017E,0x017A,
+0x00A0,0x02C7,0x02D8,0x0141,0x00A4,0x0104,0x00A6,0x00A7,
+0x00A8,0x00A9,0x015E,0x00AB,0x00AC,0x00AD,0x00AE,0x017B,
+0x00B0,0x00B1,0x02DB,0x0142,0x00B4,0x00B5,0x00B6,0x00B7,
+0x00B8,0x0105,0x015F,0x00BB,0x013D,0x02DD,0x013E,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
+};
+
+
+/* 0000-00FD , 254 chars */
+static uchar tab_uni_cp1250_plane00[]={
+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,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,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,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0x00,0x00,0x00,0xA4,0x00,0xA6,0xA7,0xA8,0xA9,0x00,0xAB,0xAC,0xAD,0xAE,0x00,
+0xB0,0xB1,0x00,0x00,0xB4,0xB5,0xB6,0xB7,0xB8,0x00,0x00,0xBB,0x00,0x00,0x00,0x00,
+0x00,0xC1,0xC2,0x00,0xC4,0x00,0x00,0xC7,0x00,0xC9,0x00,0xCB,0x00,0xCD,0xCE,0x00,
+0x00,0x00,0x00,0xD3,0xD4,0x00,0xD6,0xD7,0x00,0x00,0xDA,0x00,0xDC,0xDD,0x00,0xDF,
+0x00,0xE1,0xE2,0x00,0xE4,0x00,0x00,0xE7,0x00,0xE9,0x00,0xEB,0x00,0xED,0xEE,0x00,
+0x00,0x00,0x00,0xF3,0xF4,0x00,0xF6,0xF7,0x00,0x00,0xFA,0x00,0xFC,0xFD};
+
+/* 0102-017E , 125 chars */
+static uchar tab_uni_cp1250_plane01[]={
+0xC3,0xE3,0xA5,0xB9,0xC6,0xE6,0x00,0x00,0x00,0x00,0xC8,0xE8,0xCF,0xEF,0xD0,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xE5,0x00,0x00,0xBC,0xBE,0x00,0x00,0xA3,
+0xB3,0xD1,0xF1,0x00,0x00,0xD2,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD5,0xF5,
+0x00,0x00,0xC0,0xE0,0x00,0x00,0xD8,0xF8,0x8C,0x9C,0x00,0x00,0xAA,0xBA,0x8A,0x9A,
+0xDE,0xFE,0x8D,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xF9,0xDB,0xFB,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x9F,0xAF,0xBF,0x8E,0x9E};
+
+/* 2013-20AC , 154 chars */
+static uchar tab_uni_cp1250_plane20[]={
+0x96,0x97,0x00,0x00,0x00,0x91,0x92,0x82,0x00,0x93,0x94,0x84,0x00,0x86,0x87,0x95,
+0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80};
+
+/* 02C7-02DD , 23 chars */
+static uchar tab_uni_cp1250_plane02[]={
+0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xA2,0xFF,0x00,0xB2,0x00,0xBD};
+
+/* 2122-2122 , 1 chars */
+static uchar tab_uni_cp1250_plane21[]={
+0x99};
+
+
+static MY_UNI_IDX idx_uni_cp1250[]={
+ {0x0000,0x00FD,tab_uni_cp1250_plane00},
+ {0x0102,0x017E,tab_uni_cp1250_plane01},
+ {0x2013,0x20AC,tab_uni_cp1250_plane20},
+ {0x02C7,0x02DD,tab_uni_cp1250_plane02},
+ {0x2122,0x2122,tab_uni_cp1250_plane21},
+ {0,0,NULL}
+};
+
+#endif
+
+#ifdef HAVE_CHARSET_win1251
+
+/* The win1251 character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_win1251[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_win1251[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,184,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,245,247,248,249,250,251,252,253,254,255,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_win1251[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,168,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,213,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
+};
+
+static uchar sort_order_win1251[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,198,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,198,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,199,200,201,202,203,204,205,206,207,208,
+ 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
+ 192,193,194,195,196,197,199,200,201,202,203,204,205,206,207,208,
+ 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224
+};
+#endif
+
+#ifdef HAVE_CHARSET_win1251ukr
+
+/* The win1251ukr character set. Generated automatically by
+ * the ./conf_to_src program
+ */
+
+static uchar ctype_win1251ukr[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 1, 16, 16, 16, 16, 1,
+ 16, 16, 1, 2, 16, 16, 16, 16, 2, 16, 2, 16, 16, 16, 16, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_win1251ukr[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 32, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32,165, 32, 32,168, 32,170, 32, 32, 32, 32,175,
+ 32, 32,178,178,165, 32, 32, 32,168, 32,170, 32, 32, 32, 32,175,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
+};
+
+static uchar to_upper_win1251ukr[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 32, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32,180, 32, 32,184, 32,186, 32, 32, 32, 32,191,
+ 32, 32,179,179,180, 32, 32, 32,184, 32,186, 32, 32, 32, 32,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar sort_order_win1251ukr[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 32, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,
+ 181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
+ 197,198,199,200,201,132,202,203,136,204,135,205,206,207,208,141,
+ 209,210,140,140,132,211,212,213,136,214,135,215,216,217,218,141,
+ 128,129,130,131,133,134,137,138,139,142,143,144,145,146,147,148,
+ 149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,
+ 128,129,130,131,133,134,137,138,139,142,143,144,145,146,147,148,
+ 149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164
+};
+#endif
+
+
+
+CHARSET_INFO compiled_charsets[] = {
+
+#ifdef HAVE_CHARSET_latin1
+ {
+ 8, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "latin1", /* cs name */
+ "latin1", /* name */
+ "", /* comment */
+ ctype_latin1,
+ to_lower_latin1,
+ to_upper_latin1,
+ sort_order_latin1,
+ tab_8859_1_uni, /* tab_to_uni */
+ idx_uni_8859_1, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+
+#ifdef HAVE_CHARSET_cp1251
+ {
+ 14, /* number */
+ MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
+ "cp1251", /* name */
+ "", /* comment */
+ ctype_cp1251,
+ to_lower_cp1251,
+ to_upper_cp1251,
+ sort_order_cp1251,
+ tab_cp1251_uni, /* tab_to_uni */
+ idx_uni_cp1251, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_cp1257
+ {
+ 29, /* number */
+ MY_CS_COMPILED, /* state */
+ "cp1257", /* cs name */
+ "cp1257", /* name */
+ "", /* comment */
+ ctype_cp1257,
+ to_lower_cp1257,
+ to_upper_cp1257,
+ sort_order_cp1257,
+ tab_cp1257_uni, /* tab_to_uni */
+ idx_uni_cp1257, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_croat
+ {
+ 27, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
+ "croat", /* name */
+ "", /* comment */
+ ctype_croat,
+ to_lower_croat,
+ to_upper_croat,
+ sort_order_croat,
+ tab_8859_2_uni, /* tab_to_uni */
+ idx_uni_8859_2, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+
+#ifdef HAVE_CHARSET_danish
+ {
+ 15, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
+ "danish", /* name */
+ "", /* comment */
+ ctype_danish,
+ to_lower_danish,
+ to_upper_danish,
+ sort_order_danish,
+ tab_8859_1_uni, /* tab_to_uni */
+ idx_uni_8859_1, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_dec8
+ {
+ 3, /* number */
+ MY_CS_COMPILED, /* state */
+ "dec8", /* cs name */
+ "dec8", /* name */
+ "", /* comment */
+ ctype_dec8,
+ to_lower_dec8,
+ to_upper_dec8,
+ sort_order_dec8,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_dos
+ {
+ 4, /* number */
+ MY_CS_COMPILED, /* state */
+ "cp850", /* cs name */
+ "dos", /* name */
+ "", /* comment */
+ ctype_dos,
+ to_lower_dos,
+ to_upper_dos,
+ sort_order_dos,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_estonia
+ {
+ 20, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin7", /* cs name */
+ "estonia", /* name */
+ "", /* comment */
+ ctype_estonia,
+ to_lower_estonia,
+ to_upper_estonia,
+ sort_order_estonia,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+
+#ifdef HAVE_CHARSET_german1
+ {
+ 5, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
+ "german1", /* name */
+ "", /* comment */
+ ctype_german1,
+ to_lower_german1,
+ to_upper_german1,
+ sort_order_german1,
+ tab_8859_1_uni, /* tab_to_uni */
+ idx_uni_8859_1, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_greek
+ {
+ 25, /* number */
+ MY_CS_COMPILED, /* state */
+ "greek", /* cs name */
+ "greek", /* name */
+ "", /* comment */
+ ctype_greek,
+ to_lower_greek,
+ to_upper_greek,
+ sort_order_greek,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_hebrew
+ {
+ 16, /* number */
+ MY_CS_COMPILED, /* state */
+ "hebrew", /* cs name */
+ "hebrew", /* name */
+ "", /* comment */
+ ctype_hebrew,
+ to_lower_hebrew,
+ to_upper_hebrew,
+ sort_order_hebrew,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_hp8
+ {
+ 6, /* number */
+ MY_CS_COMPILED, /* state */
+ "hp8", /* cs name */
+ "hp8", /* name */
+ "", /* comment */
+ ctype_hp8,
+ to_lower_hp8,
+ to_upper_hp8,
+ sort_order_hp8,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_hungarian
+ {
+ 21, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
+ "hungarian", /* name */
+ "", /* comment */
+ ctype_hungarian,
+ to_lower_hungarian,
+ to_upper_hungarian,
+ sort_order_hungarian,
+ tab_8859_2_uni, /* tab_to_uni */
+ idx_uni_8859_2, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_koi8_ru
+ {
+ 7, /* number */
+ MY_CS_COMPILED, /* state */
+ "koi8r", /* cs name */
+ "koi8r", /* name */
+ "", /* comment */
+ ctype_koi8_ru,
+ to_lower_koi8_ru,
+ to_upper_koi8_ru,
+ sort_order_koi8_ru,
+ tab_koi8_r_uni, /* tab_to_uni */
+ idx_uni_koi8_r, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_koi8_ukr
+ {
+ 22, /* number */
+ MY_CS_COMPILED, /* state */
+ "koi8u", /* cs name */
+ "koi8u", /* name */
+ "", /* comment */
+ ctype_koi8_ukr,
+ to_lower_koi8_ukr,
+ to_upper_koi8_ukr,
+ sort_order_koi8_ukr,
+ tab_koi8_u_uni, /* tab_to_uni */
+ idx_uni_koi8_u, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+
+#ifdef HAVE_CHARSET_latin2
+ {
+ 9, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
+ "latin2", /* name */
+ "", /* comment */
+ ctype_latin2,
+ to_lower_latin2,
+ to_upper_latin2,
+ sort_order_latin2,
+ tab_8859_2_uni, /* tab_to_uni */
+ idx_uni_8859_2, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_latin5
+ {
+ 30, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin5", /* cs name */
+ "latin5", /* name */
+ "", /* comment */
+ ctype_latin5,
+ to_lower_latin5,
+ to_upper_latin5,
+ sort_order_latin5,
+ tab_8859_9_uni, /* tab_to_uni */
+ idx_uni_8859_9, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+
+#ifdef HAVE_CHARSET_swe7
+ {
+ 10, /* number */
+ MY_CS_COMPILED, /* state */
+ "swe7", /* cs name */
+ "swe7", /* name */
+ "", /* comment */
+ ctype_swe7,
+ to_lower_swe7,
+ to_upper_swe7,
+ sort_order_swe7,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+
+#ifdef HAVE_CHARSET_usa7
+ {
+ 11, /* number */
+ MY_CS_COMPILED, /* state */
+ "ascii", /* cs name */
+ "ascii", /* name */
+ "", /* comment */
+ ctype_usa7,
+ to_lower_usa7,
+ to_upper_usa7,
+ sort_order_usa7,
+ tab_us_ascii_uni, /* tab_to_uni */
+ idx_uni_us_ascii, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_win1250
+ {
+ 26, /* number */
+ MY_CS_COMPILED, /* state */
+ "cp1250", /* cs name */
+ "cp1250", /* name */
+ "", /* comment */
+ ctype_win1250,
+ to_lower_win1250,
+ to_upper_win1250,
+ sort_order_win1250,
+ tab_cp1250_uni, /* tab_to_uni */
+ idx_uni_cp1250, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_win1251ukr
+ {
+ 23, /* number */
+ MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
+ "win1251ukr", /* name */
+ "", /* comment */
+ ctype_win1251ukr,
+ to_lower_win1251ukr,
+ to_upper_win1251ukr,
+ sort_order_win1251ukr,
+ tab_cp1251_uni, /* tab_to_uni */
+ idx_uni_cp1251, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_strcasecmp_8bit,
+ my_tosort_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_armscii8
+ {
+ 32, /* number */
+ MY_CS_COMPILED, /* state */
+ "armscii8", /* cs name */
+ "armscii8", /* name */
+ "", /* comment */
+ ctype_armscii8,
+ to_lower_armscii8,
+ to_upper_armscii8,
+ sort_order_armscii8,
+ tab_armscii_8_uni, /* tab_to_uni */
+ idx_uni_armscii_8, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+#ifdef HAVE_CHARSET_win1251
+ {
+ 17, /* number */
+ MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
+ "win1251", /* name */
+ "", /* comment */
+ ctype_win1251,
+ to_lower_win1251,
+ to_upper_win1251,
+ sort_order_win1251,
+ tab_cp1251_uni, /* tab_to_uni */
+ idx_uni_cp1251, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,/* strnncollsp */
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ my_tosort_8bit,
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+ },
+#endif
+
+ {
+ 0, /* end-of-list marker */
+ 0, /* state */
+ NullS, /* cs name */
+ NullS, /* name */
+ NullS, /* comment */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0,
+ NULL, /* strnncoll */
+ NULL, /* strnncollsp */
+ NULL, /* strnxfrm */
+ NULL, /* like_range */
+ NULL, /* wildcmp */
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* mb_wc */
+ NULL, /* wc_mb */
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* hash_caseup */
+ NULL, /* hash_sort */
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ }
+};
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index 28717d98403..9cc19dc46ef 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -26,8 +26,11 @@
#include <my_global.h>
#include "m_string.h"
+#include "m_ctype.h"
-uchar NEAR ctype_gb2312[257] =
+#ifdef HAVE_CHARSET_gb2312
+
+static uchar NEAR ctype_gb2312[257] =
{
0, /* For standard library */
32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
@@ -48,7 +51,7 @@ uchar NEAR ctype_gb2312[257] =
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
};
-uchar NEAR to_lower_gb2312[]=
+static uchar NEAR to_lower_gb2312[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -84,7 +87,7 @@ uchar NEAR to_lower_gb2312[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR to_upper_gb2312[]=
+static uchar NEAR to_upper_gb2312[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -120,7 +123,7 @@ uchar NEAR to_upper_gb2312[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR sort_order_gb2312[]=
+static uchar NEAR sort_order_gb2312[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -163,17 +166,5576 @@ uchar NEAR sort_order_gb2312[]=
#define isgb2312tail(c) (0xa1<=(uchar)(c) && (uchar)(c)<=0xfe)
-int ismbchar_gb2312(const char* p, const char *e)
+static int ismbchar_gb2312(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
{
return (isgb2312head(*(p)) && (e)-(p)>1 && isgb2312tail(*((p)+1))? 2: 0);
}
-my_bool ismbhead_gb2312(uint c)
+static my_bool ismbhead_gb2312(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return isgb2312head(c);
}
-int mbcharlen_gb2312(uint c)
+static int mbcharlen_gb2312(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (isgb2312head(c)? 2:0);
}
+
+
+/* page 0 0x2121-0x2658 */
+static uint16 tab_gb2312_uni0[]={
+0x3000,0x3001,0x3002,0x30FB,0x02C9,0x02C7,0x00A8,0x3003,
+0x3005,0x2015,0xFF5E,0x2016,0x2026,0x2018,0x2019,0x201C,
+0x201D,0x3014,0x3015,0x3008,0x3009,0x300A,0x300B,0x300C,
+0x300D,0x300E,0x300F,0x3016,0x3017,0x3010,0x3011,0x00B1,
+0x00D7,0x00F7,0x2236,0x2227,0x2228,0x2211,0x220F,0x222A,
+0x2229,0x2208,0x2237,0x221A,0x22A5,0x2225,0x2220,0x2312,
+0x2299,0x222B,0x222E,0x2261,0x224C,0x2248,0x223D,0x221D,
+0x2260,0x226E,0x226F,0x2264,0x2265,0x221E,0x2235,0x2234,
+0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFF04,0x00A4,
+0xFFE0,0xFFE1,0x2030,0x00A7,0x2116,0x2606,0x2605,0x25CB,
+0x25CF,0x25CE,0x25C7,0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,
+0x203B,0x2192,0x2190,0x2191,0x2193,0x3013, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2488,0x2489,0x248A,0x248B,0x248C,0x248D,0x248E,0x248F,
+0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,0x2497,
+0x2498,0x2499,0x249A,0x249B,0x2474,0x2475,0x2476,0x2477,
+0x2478,0x2479,0x247A,0x247B,0x247C,0x247D,0x247E,0x247F,
+0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,0x2487,
+0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
+0x2468,0x2469, 0, 0,0x3220,0x3221,0x3222,0x3223,
+0x3224,0x3225,0x3226,0x3227,0x3228,0x3229, 0, 0,
+0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,
+0x2168,0x2169,0x216A,0x216B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFF01,0xFF02,0xFF03,0xFFE5,0xFF05,0xFF06,0xFF07,0xFF08,
+0xFF09,0xFF0A,0xFF0B,0xFF0C,0xFF0D,0xFF0E,0xFF0F,0xFF10,
+0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,
+0xFF19,0xFF1A,0xFF1B,0xFF1C,0xFF1D,0xFF1E,0xFF1F,0xFF20,
+0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,
+0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,
+0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,
+0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,0xFF40,
+0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,
+0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,
+0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,
+0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFFE3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
+0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
+0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
+0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,
+0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,
+0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,
+0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,
+0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,
+0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,
+0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,
+0x3091,0x3092,0x3093, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
+0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
+0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
+0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,
+0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,
+0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,
+0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,
+0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,0x30E0,
+0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,
+0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,0x30F0,
+0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
+0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
+0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,
+0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,0x03C0,
+0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9
+};
+
+/* page 1 0x2721-0x296F */
+static uint16 tab_gb2312_uni1[]={
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0101,0x00E1,0x01CE,0x00E0,0x0113,0x00E9,0x011B,0x00E8,
+0x012B,0x00ED,0x01D0,0x00EC,0x014D,0x00F3,0x01D2,0x00F2,
+0x016B,0x00FA,0x01D4,0x00F9,0x01D6,0x01D8,0x01DA,0x01DC,
+0x00FC,0x00EA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3105,0x3106,0x3107,0x3108,
+0x3109,0x310A,0x310B,0x310C,0x310D,0x310E,0x310F,0x3110,
+0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117,0x3118,
+0x3119,0x311A,0x311B,0x311C,0x311D,0x311E,0x311F,0x3120,
+0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127,0x3128,
+0x3129, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2500,0x2501,0x2502,0x2503,0x2504,
+0x2505,0x2506,0x2507,0x2508,0x2509,0x250A,0x250B,0x250C,
+0x250D,0x250E,0x250F,0x2510,0x2511,0x2512,0x2513,0x2514,
+0x2515,0x2516,0x2517,0x2518,0x2519,0x251A,0x251B,0x251C,
+0x251D,0x251E,0x251F,0x2520,0x2521,0x2522,0x2523,0x2524,
+0x2525,0x2526,0x2527,0x2528,0x2529,0x252A,0x252B,0x252C,
+0x252D,0x252E,0x252F,0x2530,0x2531,0x2532,0x2533,0x2534,
+0x2535,0x2536,0x2537,0x2538,0x2539,0x253A,0x253B,0x253C,
+0x253D,0x253E,0x253F,0x2540,0x2541,0x2542,0x2543,0x2544,
+0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B};
+
+/* page 2 0x3021-0x777E */
+static uint16 tab_gb2312_uni2[]={
+0x554A,0x963F,0x57C3,0x6328,0x54CE,0x5509,0x54C0,0x7691,
+0x764C,0x853C,0x77EE,0x827E,0x788D,0x7231,0x9698,0x978D,
+0x6C28,0x5B89,0x4FFA,0x6309,0x6697,0x5CB8,0x80FA,0x6848,
+0x80AE,0x6602,0x76CE,0x51F9,0x6556,0x71AC,0x7FF1,0x8884,
+0x50B2,0x5965,0x61CA,0x6FB3,0x82AD,0x634C,0x6252,0x53ED,
+0x5427,0x7B06,0x516B,0x75A4,0x5DF4,0x62D4,0x8DCB,0x9776,
+0x628A,0x8019,0x575D,0x9738,0x7F62,0x7238,0x767D,0x67CF,
+0x767E,0x6446,0x4F70,0x8D25,0x62DC,0x7A17,0x6591,0x73ED,
+0x642C,0x6273,0x822C,0x9881,0x677F,0x7248,0x626E,0x62CC,
+0x4F34,0x74E3,0x534A,0x529E,0x7ECA,0x90A6,0x5E2E,0x6886,
+0x699C,0x8180,0x7ED1,0x68D2,0x78C5,0x868C,0x9551,0x508D,
+0x8C24,0x82DE,0x80DE,0x5305,0x8912,0x5265, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8584,0x96F9,0x4FDD,0x5821,0x9971,0x5B9D,0x62B1,0x62A5,
+0x66B4,0x8C79,0x9C8D,0x7206,0x676F,0x7891,0x60B2,0x5351,
+0x5317,0x8F88,0x80CC,0x8D1D,0x94A1,0x500D,0x72C8,0x5907,
+0x60EB,0x7119,0x88AB,0x5954,0x82EF,0x672C,0x7B28,0x5D29,
+0x7EF7,0x752D,0x6CF5,0x8E66,0x8FF8,0x903C,0x9F3B,0x6BD4,
+0x9119,0x7B14,0x5F7C,0x78A7,0x84D6,0x853D,0x6BD5,0x6BD9,
+0x6BD6,0x5E01,0x5E87,0x75F9,0x95ED,0x655D,0x5F0A,0x5FC5,
+0x8F9F,0x58C1,0x81C2,0x907F,0x965B,0x97AD,0x8FB9,0x7F16,
+0x8D2C,0x6241,0x4FBF,0x53D8,0x535E,0x8FA8,0x8FA9,0x8FAB,
+0x904D,0x6807,0x5F6A,0x8198,0x8868,0x9CD6,0x618B,0x522B,
+0x762A,0x5F6C,0x658C,0x6FD2,0x6EE8,0x5BBE,0x6448,0x5175,
+0x51B0,0x67C4,0x4E19,0x79C9,0x997C,0x70B3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x75C5,0x5E76,0x73BB,0x83E0,0x64AD,0x62E8,0x94B5,0x6CE2,
+0x535A,0x52C3,0x640F,0x94C2,0x7B94,0x4F2F,0x5E1B,0x8236,
+0x8116,0x818A,0x6E24,0x6CCA,0x9A73,0x6355,0x535C,0x54FA,
+0x8865,0x57E0,0x4E0D,0x5E03,0x6B65,0x7C3F,0x90E8,0x6016,
+0x64E6,0x731C,0x88C1,0x6750,0x624D,0x8D22,0x776C,0x8E29,
+0x91C7,0x5F69,0x83DC,0x8521,0x9910,0x53C2,0x8695,0x6B8B,
+0x60ED,0x60E8,0x707F,0x82CD,0x8231,0x4ED3,0x6CA7,0x85CF,
+0x64CD,0x7CD9,0x69FD,0x66F9,0x8349,0x5395,0x7B56,0x4FA7,
+0x518C,0x6D4B,0x5C42,0x8E6D,0x63D2,0x53C9,0x832C,0x8336,
+0x67E5,0x78B4,0x643D,0x5BDF,0x5C94,0x5DEE,0x8BE7,0x62C6,
+0x67F4,0x8C7A,0x6400,0x63BA,0x8749,0x998B,0x8C17,0x7F20,
+0x94F2,0x4EA7,0x9610,0x98A4,0x660C,0x7316, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x573A,0x5C1D,0x5E38,0x957F,0x507F,0x80A0,0x5382,0x655E,
+0x7545,0x5531,0x5021,0x8D85,0x6284,0x949E,0x671D,0x5632,
+0x6F6E,0x5DE2,0x5435,0x7092,0x8F66,0x626F,0x64A4,0x63A3,
+0x5F7B,0x6F88,0x90F4,0x81E3,0x8FB0,0x5C18,0x6668,0x5FF1,
+0x6C89,0x9648,0x8D81,0x886C,0x6491,0x79F0,0x57CE,0x6A59,
+0x6210,0x5448,0x4E58,0x7A0B,0x60E9,0x6F84,0x8BDA,0x627F,
+0x901E,0x9A8B,0x79E4,0x5403,0x75F4,0x6301,0x5319,0x6C60,
+0x8FDF,0x5F1B,0x9A70,0x803B,0x9F7F,0x4F88,0x5C3A,0x8D64,
+0x7FC5,0x65A5,0x70BD,0x5145,0x51B2,0x866B,0x5D07,0x5BA0,
+0x62BD,0x916C,0x7574,0x8E0C,0x7A20,0x6101,0x7B79,0x4EC7,
+0x7EF8,0x7785,0x4E11,0x81ED,0x521D,0x51FA,0x6A71,0x53A8,
+0x8E87,0x9504,0x96CF,0x6EC1,0x9664,0x695A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7840,0x50A8,0x77D7,0x6410,0x89E6,0x5904,0x63E3,0x5DDD,
+0x7A7F,0x693D,0x4F20,0x8239,0x5598,0x4E32,0x75AE,0x7A97,
+0x5E62,0x5E8A,0x95EF,0x521B,0x5439,0x708A,0x6376,0x9524,
+0x5782,0x6625,0x693F,0x9187,0x5507,0x6DF3,0x7EAF,0x8822,
+0x6233,0x7EF0,0x75B5,0x8328,0x78C1,0x96CC,0x8F9E,0x6148,
+0x74F7,0x8BCD,0x6B64,0x523A,0x8D50,0x6B21,0x806A,0x8471,
+0x56F1,0x5306,0x4ECE,0x4E1B,0x51D1,0x7C97,0x918B,0x7C07,
+0x4FC3,0x8E7F,0x7BE1,0x7A9C,0x6467,0x5D14,0x50AC,0x8106,
+0x7601,0x7CB9,0x6DEC,0x7FE0,0x6751,0x5B58,0x5BF8,0x78CB,
+0x64AE,0x6413,0x63AA,0x632B,0x9519,0x642D,0x8FBE,0x7B54,
+0x7629,0x6253,0x5927,0x5446,0x6B79,0x50A3,0x6234,0x5E26,
+0x6B86,0x4EE3,0x8D37,0x888B,0x5F85,0x902E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6020,0x803D,0x62C5,0x4E39,0x5355,0x90F8,0x63B8,0x80C6,
+0x65E6,0x6C2E,0x4F46,0x60EE,0x6DE1,0x8BDE,0x5F39,0x86CB,
+0x5F53,0x6321,0x515A,0x8361,0x6863,0x5200,0x6363,0x8E48,
+0x5012,0x5C9B,0x7977,0x5BFC,0x5230,0x7A3B,0x60BC,0x9053,
+0x76D7,0x5FB7,0x5F97,0x7684,0x8E6C,0x706F,0x767B,0x7B49,
+0x77AA,0x51F3,0x9093,0x5824,0x4F4E,0x6EF4,0x8FEA,0x654C,
+0x7B1B,0x72C4,0x6DA4,0x7FDF,0x5AE1,0x62B5,0x5E95,0x5730,
+0x8482,0x7B2C,0x5E1D,0x5F1F,0x9012,0x7F14,0x98A0,0x6382,
+0x6EC7,0x7898,0x70B9,0x5178,0x975B,0x57AB,0x7535,0x4F43,
+0x7538,0x5E97,0x60E6,0x5960,0x6DC0,0x6BBF,0x7889,0x53FC,
+0x96D5,0x51CB,0x5201,0x6389,0x540A,0x9493,0x8C03,0x8DCC,
+0x7239,0x789F,0x8776,0x8FED,0x8C0D,0x53E0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E01,0x76EF,0x53EE,0x9489,0x9876,0x9F0E,0x952D,0x5B9A,
+0x8BA2,0x4E22,0x4E1C,0x51AC,0x8463,0x61C2,0x52A8,0x680B,
+0x4F97,0x606B,0x51BB,0x6D1E,0x515C,0x6296,0x6597,0x9661,
+0x8C46,0x9017,0x75D8,0x90FD,0x7763,0x6BD2,0x728A,0x72EC,
+0x8BFB,0x5835,0x7779,0x8D4C,0x675C,0x9540,0x809A,0x5EA6,
+0x6E21,0x5992,0x7AEF,0x77ED,0x953B,0x6BB5,0x65AD,0x7F0E,
+0x5806,0x5151,0x961F,0x5BF9,0x58A9,0x5428,0x8E72,0x6566,
+0x987F,0x56E4,0x949D,0x76FE,0x9041,0x6387,0x54C6,0x591A,
+0x593A,0x579B,0x8EB2,0x6735,0x8DFA,0x8235,0x5241,0x60F0,
+0x5815,0x86FE,0x5CE8,0x9E45,0x4FC4,0x989D,0x8BB9,0x5A25,
+0x6076,0x5384,0x627C,0x904F,0x9102,0x997F,0x6069,0x800C,
+0x513F,0x8033,0x5C14,0x9975,0x6D31,0x4E8C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8D30,0x53D1,0x7F5A,0x7B4F,0x4F10,0x4E4F,0x9600,0x6CD5,
+0x73D0,0x85E9,0x5E06,0x756A,0x7FFB,0x6A0A,0x77FE,0x9492,
+0x7E41,0x51E1,0x70E6,0x53CD,0x8FD4,0x8303,0x8D29,0x72AF,
+0x996D,0x6CDB,0x574A,0x82B3,0x65B9,0x80AA,0x623F,0x9632,
+0x59A8,0x4EFF,0x8BBF,0x7EBA,0x653E,0x83F2,0x975E,0x5561,
+0x98DE,0x80A5,0x532A,0x8BFD,0x5420,0x80BA,0x5E9F,0x6CB8,
+0x8D39,0x82AC,0x915A,0x5429,0x6C1B,0x5206,0x7EB7,0x575F,
+0x711A,0x6C7E,0x7C89,0x594B,0x4EFD,0x5FFF,0x6124,0x7CAA,
+0x4E30,0x5C01,0x67AB,0x8702,0x5CF0,0x950B,0x98CE,0x75AF,
+0x70FD,0x9022,0x51AF,0x7F1D,0x8BBD,0x5949,0x51E4,0x4F5B,
+0x5426,0x592B,0x6577,0x80A4,0x5B75,0x6276,0x62C2,0x8F90,
+0x5E45,0x6C1F,0x7B26,0x4F0F,0x4FD8,0x670D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6D6E,0x6DAA,0x798F,0x88B1,0x5F17,0x752B,0x629A,0x8F85,
+0x4FEF,0x91DC,0x65A7,0x812F,0x8151,0x5E9C,0x8150,0x8D74,
+0x526F,0x8986,0x8D4B,0x590D,0x5085,0x4ED8,0x961C,0x7236,
+0x8179,0x8D1F,0x5BCC,0x8BA3,0x9644,0x5987,0x7F1A,0x5490,
+0x5676,0x560E,0x8BE5,0x6539,0x6982,0x9499,0x76D6,0x6E89,
+0x5E72,0x7518,0x6746,0x67D1,0x7AFF,0x809D,0x8D76,0x611F,
+0x79C6,0x6562,0x8D63,0x5188,0x521A,0x94A2,0x7F38,0x809B,
+0x7EB2,0x5C97,0x6E2F,0x6760,0x7BD9,0x768B,0x9AD8,0x818F,
+0x7F94,0x7CD5,0x641E,0x9550,0x7A3F,0x544A,0x54E5,0x6B4C,
+0x6401,0x6208,0x9E3D,0x80F3,0x7599,0x5272,0x9769,0x845B,
+0x683C,0x86E4,0x9601,0x9694,0x94EC,0x4E2A,0x5404,0x7ED9,
+0x6839,0x8DDF,0x8015,0x66F4,0x5E9A,0x7FB9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x57C2,0x803F,0x6897,0x5DE5,0x653B,0x529F,0x606D,0x9F9A,
+0x4F9B,0x8EAC,0x516C,0x5BAB,0x5F13,0x5DE9,0x6C5E,0x62F1,
+0x8D21,0x5171,0x94A9,0x52FE,0x6C9F,0x82DF,0x72D7,0x57A2,
+0x6784,0x8D2D,0x591F,0x8F9C,0x83C7,0x5495,0x7B8D,0x4F30,
+0x6CBD,0x5B64,0x59D1,0x9F13,0x53E4,0x86CA,0x9AA8,0x8C37,
+0x80A1,0x6545,0x987E,0x56FA,0x96C7,0x522E,0x74DC,0x5250,
+0x5BE1,0x6302,0x8902,0x4E56,0x62D0,0x602A,0x68FA,0x5173,
+0x5B98,0x51A0,0x89C2,0x7BA1,0x9986,0x7F50,0x60EF,0x704C,
+0x8D2F,0x5149,0x5E7F,0x901B,0x7470,0x89C4,0x572D,0x7845,
+0x5F52,0x9F9F,0x95FA,0x8F68,0x9B3C,0x8BE1,0x7678,0x6842,
+0x67DC,0x8DEA,0x8D35,0x523D,0x8F8A,0x6EDA,0x68CD,0x9505,
+0x90ED,0x56FD,0x679C,0x88F9,0x8FC7,0x54C8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9AB8,0x5B69,0x6D77,0x6C26,0x4EA5,0x5BB3,0x9A87,0x9163,
+0x61A8,0x90AF,0x97E9,0x542B,0x6DB5,0x5BD2,0x51FD,0x558A,
+0x7F55,0x7FF0,0x64BC,0x634D,0x65F1,0x61BE,0x608D,0x710A,
+0x6C57,0x6C49,0x592F,0x676D,0x822A,0x58D5,0x568E,0x8C6A,
+0x6BEB,0x90DD,0x597D,0x8017,0x53F7,0x6D69,0x5475,0x559D,
+0x8377,0x83CF,0x6838,0x79BE,0x548C,0x4F55,0x5408,0x76D2,
+0x8C89,0x9602,0x6CB3,0x6DB8,0x8D6B,0x8910,0x9E64,0x8D3A,
+0x563F,0x9ED1,0x75D5,0x5F88,0x72E0,0x6068,0x54FC,0x4EA8,
+0x6A2A,0x8861,0x6052,0x8F70,0x54C4,0x70D8,0x8679,0x9E3F,
+0x6D2A,0x5B8F,0x5F18,0x7EA2,0x5589,0x4FAF,0x7334,0x543C,
+0x539A,0x5019,0x540E,0x547C,0x4E4E,0x5FFD,0x745A,0x58F6,
+0x846B,0x80E1,0x8774,0x72D0,0x7CCA,0x6E56, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F27,0x864E,0x552C,0x62A4,0x4E92,0x6CAA,0x6237,0x82B1,
+0x54D7,0x534E,0x733E,0x6ED1,0x753B,0x5212,0x5316,0x8BDD,
+0x69D0,0x5F8A,0x6000,0x6DEE,0x574F,0x6B22,0x73AF,0x6853,
+0x8FD8,0x7F13,0x6362,0x60A3,0x5524,0x75EA,0x8C62,0x7115,
+0x6DA3,0x5BA6,0x5E7B,0x8352,0x614C,0x9EC4,0x78FA,0x8757,
+0x7C27,0x7687,0x51F0,0x60F6,0x714C,0x6643,0x5E4C,0x604D,
+0x8C0E,0x7070,0x6325,0x8F89,0x5FBD,0x6062,0x86D4,0x56DE,
+0x6BC1,0x6094,0x6167,0x5349,0x60E0,0x6666,0x8D3F,0x79FD,
+0x4F1A,0x70E9,0x6C47,0x8BB3,0x8BF2,0x7ED8,0x8364,0x660F,
+0x5A5A,0x9B42,0x6D51,0x6DF7,0x8C41,0x6D3B,0x4F19,0x706B,
+0x83B7,0x6216,0x60D1,0x970D,0x8D27,0x7978,0x51FB,0x573E,
+0x57FA,0x673A,0x7578,0x7A3D,0x79EF,0x7B95, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x808C,0x9965,0x8FF9,0x6FC0,0x8BA5,0x9E21,0x59EC,0x7EE9,
+0x7F09,0x5409,0x6781,0x68D8,0x8F91,0x7C4D,0x96C6,0x53CA,
+0x6025,0x75BE,0x6C72,0x5373,0x5AC9,0x7EA7,0x6324,0x51E0,
+0x810A,0x5DF1,0x84DF,0x6280,0x5180,0x5B63,0x4F0E,0x796D,
+0x5242,0x60B8,0x6D4E,0x5BC4,0x5BC2,0x8BA1,0x8BB0,0x65E2,
+0x5FCC,0x9645,0x5993,0x7EE7,0x7EAA,0x5609,0x67B7,0x5939,
+0x4F73,0x5BB6,0x52A0,0x835A,0x988A,0x8D3E,0x7532,0x94BE,
+0x5047,0x7A3C,0x4EF7,0x67B6,0x9A7E,0x5AC1,0x6B7C,0x76D1,
+0x575A,0x5C16,0x7B3A,0x95F4,0x714E,0x517C,0x80A9,0x8270,
+0x5978,0x7F04,0x8327,0x68C0,0x67EC,0x78B1,0x7877,0x62E3,
+0x6361,0x7B80,0x4FED,0x526A,0x51CF,0x8350,0x69DB,0x9274,
+0x8DF5,0x8D31,0x89C1,0x952E,0x7BAD,0x4EF6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5065,0x8230,0x5251,0x996F,0x6E10,0x6E85,0x6DA7,0x5EFA,
+0x50F5,0x59DC,0x5C06,0x6D46,0x6C5F,0x7586,0x848B,0x6868,
+0x5956,0x8BB2,0x5320,0x9171,0x964D,0x8549,0x6912,0x7901,
+0x7126,0x80F6,0x4EA4,0x90CA,0x6D47,0x9A84,0x5A07,0x56BC,
+0x6405,0x94F0,0x77EB,0x4FA5,0x811A,0x72E1,0x89D2,0x997A,
+0x7F34,0x7EDE,0x527F,0x6559,0x9175,0x8F7F,0x8F83,0x53EB,
+0x7A96,0x63ED,0x63A5,0x7686,0x79F8,0x8857,0x9636,0x622A,
+0x52AB,0x8282,0x6854,0x6770,0x6377,0x776B,0x7AED,0x6D01,
+0x7ED3,0x89E3,0x59D0,0x6212,0x85C9,0x82A5,0x754C,0x501F,
+0x4ECB,0x75A5,0x8BEB,0x5C4A,0x5DFE,0x7B4B,0x65A4,0x91D1,
+0x4ECA,0x6D25,0x895F,0x7D27,0x9526,0x4EC5,0x8C28,0x8FDB,
+0x9773,0x664B,0x7981,0x8FD1,0x70EC,0x6D78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5C3D,0x52B2,0x8346,0x5162,0x830E,0x775B,0x6676,0x9CB8,
+0x4EAC,0x60CA,0x7CBE,0x7CB3,0x7ECF,0x4E95,0x8B66,0x666F,
+0x9888,0x9759,0x5883,0x656C,0x955C,0x5F84,0x75C9,0x9756,
+0x7ADF,0x7ADE,0x51C0,0x70AF,0x7A98,0x63EA,0x7A76,0x7EA0,
+0x7396,0x97ED,0x4E45,0x7078,0x4E5D,0x9152,0x53A9,0x6551,
+0x65E7,0x81FC,0x8205,0x548E,0x5C31,0x759A,0x97A0,0x62D8,
+0x72D9,0x75BD,0x5C45,0x9A79,0x83CA,0x5C40,0x5480,0x77E9,
+0x4E3E,0x6CAE,0x805A,0x62D2,0x636E,0x5DE8,0x5177,0x8DDD,
+0x8E1E,0x952F,0x4FF1,0x53E5,0x60E7,0x70AC,0x5267,0x6350,
+0x9E43,0x5A1F,0x5026,0x7737,0x5377,0x7EE2,0x6485,0x652B,
+0x6289,0x6398,0x5014,0x7235,0x89C9,0x51B3,0x8BC0,0x7EDD,
+0x5747,0x83CC,0x94A7,0x519B,0x541B,0x5CFB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4FCA,0x7AE3,0x6D5A,0x90E1,0x9A8F,0x5580,0x5496,0x5361,
+0x54AF,0x5F00,0x63E9,0x6977,0x51EF,0x6168,0x520A,0x582A,
+0x52D8,0x574E,0x780D,0x770B,0x5EB7,0x6177,0x7CE0,0x625B,
+0x6297,0x4EA2,0x7095,0x8003,0x62F7,0x70E4,0x9760,0x5777,
+0x82DB,0x67EF,0x68F5,0x78D5,0x9897,0x79D1,0x58F3,0x54B3,
+0x53EF,0x6E34,0x514B,0x523B,0x5BA2,0x8BFE,0x80AF,0x5543,
+0x57A6,0x6073,0x5751,0x542D,0x7A7A,0x6050,0x5B54,0x63A7,
+0x62A0,0x53E3,0x6263,0x5BC7,0x67AF,0x54ED,0x7A9F,0x82E6,
+0x9177,0x5E93,0x88E4,0x5938,0x57AE,0x630E,0x8DE8,0x80EF,
+0x5757,0x7B77,0x4FA9,0x5FEB,0x5BBD,0x6B3E,0x5321,0x7B50,
+0x72C2,0x6846,0x77FF,0x7736,0x65F7,0x51B5,0x4E8F,0x76D4,
+0x5CBF,0x7AA5,0x8475,0x594E,0x9B41,0x5080, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9988,0x6127,0x6E83,0x5764,0x6606,0x6346,0x56F0,0x62EC,
+0x6269,0x5ED3,0x9614,0x5783,0x62C9,0x5587,0x8721,0x814A,
+0x8FA3,0x5566,0x83B1,0x6765,0x8D56,0x84DD,0x5A6A,0x680F,
+0x62E6,0x7BEE,0x9611,0x5170,0x6F9C,0x8C30,0x63FD,0x89C8,
+0x61D2,0x7F06,0x70C2,0x6EE5,0x7405,0x6994,0x72FC,0x5ECA,
+0x90CE,0x6717,0x6D6A,0x635E,0x52B3,0x7262,0x8001,0x4F6C,
+0x59E5,0x916A,0x70D9,0x6D9D,0x52D2,0x4E50,0x96F7,0x956D,
+0x857E,0x78CA,0x7D2F,0x5121,0x5792,0x64C2,0x808B,0x7C7B,
+0x6CEA,0x68F1,0x695E,0x51B7,0x5398,0x68A8,0x7281,0x9ECE,
+0x7BF1,0x72F8,0x79BB,0x6F13,0x7406,0x674E,0x91CC,0x9CA4,
+0x793C,0x8389,0x8354,0x540F,0x6817,0x4E3D,0x5389,0x52B1,
+0x783E,0x5386,0x5229,0x5088,0x4F8B,0x4FD0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x75E2,0x7ACB,0x7C92,0x6CA5,0x96B6,0x529B,0x7483,0x54E9,
+0x4FE9,0x8054,0x83B2,0x8FDE,0x9570,0x5EC9,0x601C,0x6D9F,
+0x5E18,0x655B,0x8138,0x94FE,0x604B,0x70BC,0x7EC3,0x7CAE,
+0x51C9,0x6881,0x7CB1,0x826F,0x4E24,0x8F86,0x91CF,0x667E,
+0x4EAE,0x8C05,0x64A9,0x804A,0x50DA,0x7597,0x71CE,0x5BE5,
+0x8FBD,0x6F66,0x4E86,0x6482,0x9563,0x5ED6,0x6599,0x5217,
+0x88C2,0x70C8,0x52A3,0x730E,0x7433,0x6797,0x78F7,0x9716,
+0x4E34,0x90BB,0x9CDE,0x6DCB,0x51DB,0x8D41,0x541D,0x62CE,
+0x73B2,0x83F1,0x96F6,0x9F84,0x94C3,0x4F36,0x7F9A,0x51CC,
+0x7075,0x9675,0x5CAD,0x9886,0x53E6,0x4EE4,0x6E9C,0x7409,
+0x69B4,0x786B,0x998F,0x7559,0x5218,0x7624,0x6D41,0x67F3,
+0x516D,0x9F99,0x804B,0x5499,0x7B3C,0x7ABF, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9686,0x5784,0x62E2,0x9647,0x697C,0x5A04,0x6402,0x7BD3,
+0x6F0F,0x964B,0x82A6,0x5362,0x9885,0x5E90,0x7089,0x63B3,
+0x5364,0x864F,0x9C81,0x9E93,0x788C,0x9732,0x8DEF,0x8D42,
+0x9E7F,0x6F5E,0x7984,0x5F55,0x9646,0x622E,0x9A74,0x5415,
+0x94DD,0x4FA3,0x65C5,0x5C65,0x5C61,0x7F15,0x8651,0x6C2F,
+0x5F8B,0x7387,0x6EE4,0x7EFF,0x5CE6,0x631B,0x5B6A,0x6EE6,
+0x5375,0x4E71,0x63A0,0x7565,0x62A1,0x8F6E,0x4F26,0x4ED1,
+0x6CA6,0x7EB6,0x8BBA,0x841D,0x87BA,0x7F57,0x903B,0x9523,
+0x7BA9,0x9AA1,0x88F8,0x843D,0x6D1B,0x9A86,0x7EDC,0x5988,
+0x9EBB,0x739B,0x7801,0x8682,0x9A6C,0x9A82,0x561B,0x5417,
+0x57CB,0x4E70,0x9EA6,0x5356,0x8FC8,0x8109,0x7792,0x9992,
+0x86EE,0x6EE1,0x8513,0x66FC,0x6162,0x6F2B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8C29,0x8292,0x832B,0x76F2,0x6C13,0x5FD9,0x83BD,0x732B,
+0x8305,0x951A,0x6BDB,0x77DB,0x94C6,0x536F,0x8302,0x5192,
+0x5E3D,0x8C8C,0x8D38,0x4E48,0x73AB,0x679A,0x6885,0x9176,
+0x9709,0x7164,0x6CA1,0x7709,0x5A92,0x9541,0x6BCF,0x7F8E,
+0x6627,0x5BD0,0x59B9,0x5A9A,0x95E8,0x95F7,0x4EEC,0x840C,
+0x8499,0x6AAC,0x76DF,0x9530,0x731B,0x68A6,0x5B5F,0x772F,
+0x919A,0x9761,0x7CDC,0x8FF7,0x8C1C,0x5F25,0x7C73,0x79D8,
+0x89C5,0x6CCC,0x871C,0x5BC6,0x5E42,0x68C9,0x7720,0x7EF5,
+0x5195,0x514D,0x52C9,0x5A29,0x7F05,0x9762,0x82D7,0x63CF,
+0x7784,0x85D0,0x79D2,0x6E3A,0x5E99,0x5999,0x8511,0x706D,
+0x6C11,0x62BF,0x76BF,0x654F,0x60AF,0x95FD,0x660E,0x879F,
+0x9E23,0x94ED,0x540D,0x547D,0x8C2C,0x6478, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6479,0x8611,0x6A21,0x819C,0x78E8,0x6469,0x9B54,0x62B9,
+0x672B,0x83AB,0x58A8,0x9ED8,0x6CAB,0x6F20,0x5BDE,0x964C,
+0x8C0B,0x725F,0x67D0,0x62C7,0x7261,0x4EA9,0x59C6,0x6BCD,
+0x5893,0x66AE,0x5E55,0x52DF,0x6155,0x6728,0x76EE,0x7766,
+0x7267,0x7A46,0x62FF,0x54EA,0x5450,0x94A0,0x90A3,0x5A1C,
+0x7EB3,0x6C16,0x4E43,0x5976,0x8010,0x5948,0x5357,0x7537,
+0x96BE,0x56CA,0x6320,0x8111,0x607C,0x95F9,0x6DD6,0x5462,
+0x9981,0x5185,0x5AE9,0x80FD,0x59AE,0x9713,0x502A,0x6CE5,
+0x5C3C,0x62DF,0x4F60,0x533F,0x817B,0x9006,0x6EBA,0x852B,
+0x62C8,0x5E74,0x78BE,0x64B5,0x637B,0x5FF5,0x5A18,0x917F,
+0x9E1F,0x5C3F,0x634F,0x8042,0x5B7D,0x556E,0x954A,0x954D,
+0x6D85,0x60A8,0x67E0,0x72DE,0x51DD,0x5B81, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x62E7,0x6CDE,0x725B,0x626D,0x94AE,0x7EBD,0x8113,0x6D53,
+0x519C,0x5F04,0x5974,0x52AA,0x6012,0x5973,0x6696,0x8650,
+0x759F,0x632A,0x61E6,0x7CEF,0x8BFA,0x54E6,0x6B27,0x9E25,
+0x6BB4,0x85D5,0x5455,0x5076,0x6CA4,0x556A,0x8DB4,0x722C,
+0x5E15,0x6015,0x7436,0x62CD,0x6392,0x724C,0x5F98,0x6E43,
+0x6D3E,0x6500,0x6F58,0x76D8,0x78D0,0x76FC,0x7554,0x5224,
+0x53DB,0x4E53,0x5E9E,0x65C1,0x802A,0x80D6,0x629B,0x5486,
+0x5228,0x70AE,0x888D,0x8DD1,0x6CE1,0x5478,0x80DA,0x57F9,
+0x88F4,0x8D54,0x966A,0x914D,0x4F69,0x6C9B,0x55B7,0x76C6,
+0x7830,0x62A8,0x70F9,0x6F8E,0x5F6D,0x84EC,0x68DA,0x787C,
+0x7BF7,0x81A8,0x670B,0x9E4F,0x6367,0x78B0,0x576F,0x7812,
+0x9739,0x6279,0x62AB,0x5288,0x7435,0x6BD7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5564,0x813E,0x75B2,0x76AE,0x5339,0x75DE,0x50FB,0x5C41,
+0x8B6C,0x7BC7,0x504F,0x7247,0x9A97,0x98D8,0x6F02,0x74E2,
+0x7968,0x6487,0x77A5,0x62FC,0x9891,0x8D2B,0x54C1,0x8058,
+0x4E52,0x576A,0x82F9,0x840D,0x5E73,0x51ED,0x74F6,0x8BC4,
+0x5C4F,0x5761,0x6CFC,0x9887,0x5A46,0x7834,0x9B44,0x8FEB,
+0x7C95,0x5256,0x6251,0x94FA,0x4EC6,0x8386,0x8461,0x83E9,
+0x84B2,0x57D4,0x6734,0x5703,0x666E,0x6D66,0x8C31,0x66DD,
+0x7011,0x671F,0x6B3A,0x6816,0x621A,0x59BB,0x4E03,0x51C4,
+0x6F06,0x67D2,0x6C8F,0x5176,0x68CB,0x5947,0x6B67,0x7566,
+0x5D0E,0x8110,0x9F50,0x65D7,0x7948,0x7941,0x9A91,0x8D77,
+0x5C82,0x4E5E,0x4F01,0x542F,0x5951,0x780C,0x5668,0x6C14,
+0x8FC4,0x5F03,0x6C7D,0x6CE3,0x8BAB,0x6390, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6070,0x6D3D,0x7275,0x6266,0x948E,0x94C5,0x5343,0x8FC1,
+0x7B7E,0x4EDF,0x8C26,0x4E7E,0x9ED4,0x94B1,0x94B3,0x524D,
+0x6F5C,0x9063,0x6D45,0x8C34,0x5811,0x5D4C,0x6B20,0x6B49,
+0x67AA,0x545B,0x8154,0x7F8C,0x5899,0x8537,0x5F3A,0x62A2,
+0x6A47,0x9539,0x6572,0x6084,0x6865,0x77A7,0x4E54,0x4FA8,
+0x5DE7,0x9798,0x64AC,0x7FD8,0x5CED,0x4FCF,0x7A8D,0x5207,
+0x8304,0x4E14,0x602F,0x7A83,0x94A6,0x4FB5,0x4EB2,0x79E6,
+0x7434,0x52E4,0x82B9,0x64D2,0x79BD,0x5BDD,0x6C81,0x9752,
+0x8F7B,0x6C22,0x503E,0x537F,0x6E05,0x64CE,0x6674,0x6C30,
+0x60C5,0x9877,0x8BF7,0x5E86,0x743C,0x7A77,0x79CB,0x4E18,
+0x90B1,0x7403,0x6C42,0x56DA,0x914B,0x6CC5,0x8D8B,0x533A,
+0x86C6,0x66F2,0x8EAF,0x5C48,0x9A71,0x6E20, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x53D6,0x5A36,0x9F8B,0x8DA3,0x53BB,0x5708,0x98A7,0x6743,
+0x919B,0x6CC9,0x5168,0x75CA,0x62F3,0x72AC,0x5238,0x529D,
+0x7F3A,0x7094,0x7638,0x5374,0x9E4A,0x69B7,0x786E,0x96C0,
+0x88D9,0x7FA4,0x7136,0x71C3,0x5189,0x67D3,0x74E4,0x58E4,
+0x6518,0x56B7,0x8BA9,0x9976,0x6270,0x7ED5,0x60F9,0x70ED,
+0x58EC,0x4EC1,0x4EBA,0x5FCD,0x97E7,0x4EFB,0x8BA4,0x5203,
+0x598A,0x7EAB,0x6254,0x4ECD,0x65E5,0x620E,0x8338,0x84C9,
+0x8363,0x878D,0x7194,0x6EB6,0x5BB9,0x7ED2,0x5197,0x63C9,
+0x67D4,0x8089,0x8339,0x8815,0x5112,0x5B7A,0x5982,0x8FB1,
+0x4E73,0x6C5D,0x5165,0x8925,0x8F6F,0x962E,0x854A,0x745E,
+0x9510,0x95F0,0x6DA6,0x82E5,0x5F31,0x6492,0x6D12,0x8428,
+0x816E,0x9CC3,0x585E,0x8D5B,0x4E09,0x53C1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4F1E,0x6563,0x6851,0x55D3,0x4E27,0x6414,0x9A9A,0x626B,
+0x5AC2,0x745F,0x8272,0x6DA9,0x68EE,0x50E7,0x838E,0x7802,
+0x6740,0x5239,0x6C99,0x7EB1,0x50BB,0x5565,0x715E,0x7B5B,
+0x6652,0x73CA,0x82EB,0x6749,0x5C71,0x5220,0x717D,0x886B,
+0x95EA,0x9655,0x64C5,0x8D61,0x81B3,0x5584,0x6C55,0x6247,
+0x7F2E,0x5892,0x4F24,0x5546,0x8D4F,0x664C,0x4E0A,0x5C1A,
+0x88F3,0x68A2,0x634E,0x7A0D,0x70E7,0x828D,0x52FA,0x97F6,
+0x5C11,0x54E8,0x90B5,0x7ECD,0x5962,0x8D4A,0x86C7,0x820C,
+0x820D,0x8D66,0x6444,0x5C04,0x6151,0x6D89,0x793E,0x8BBE,
+0x7837,0x7533,0x547B,0x4F38,0x8EAB,0x6DF1,0x5A20,0x7EC5,
+0x795E,0x6C88,0x5BA1,0x5A76,0x751A,0x80BE,0x614E,0x6E17,
+0x58F0,0x751F,0x7525,0x7272,0x5347,0x7EF3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7701,0x76DB,0x5269,0x80DC,0x5723,0x5E08,0x5931,0x72EE,
+0x65BD,0x6E7F,0x8BD7,0x5C38,0x8671,0x5341,0x77F3,0x62FE,
+0x65F6,0x4EC0,0x98DF,0x8680,0x5B9E,0x8BC6,0x53F2,0x77E2,
+0x4F7F,0x5C4E,0x9A76,0x59CB,0x5F0F,0x793A,0x58EB,0x4E16,
+0x67FF,0x4E8B,0x62ED,0x8A93,0x901D,0x52BF,0x662F,0x55DC,
+0x566C,0x9002,0x4ED5,0x4F8D,0x91CA,0x9970,0x6C0F,0x5E02,
+0x6043,0x5BA4,0x89C6,0x8BD5,0x6536,0x624B,0x9996,0x5B88,
+0x5BFF,0x6388,0x552E,0x53D7,0x7626,0x517D,0x852C,0x67A2,
+0x68B3,0x6B8A,0x6292,0x8F93,0x53D4,0x8212,0x6DD1,0x758F,
+0x4E66,0x8D4E,0x5B70,0x719F,0x85AF,0x6691,0x66D9,0x7F72,
+0x8700,0x9ECD,0x9F20,0x5C5E,0x672F,0x8FF0,0x6811,0x675F,
+0x620D,0x7AD6,0x5885,0x5EB6,0x6570,0x6F31, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6055,0x5237,0x800D,0x6454,0x8870,0x7529,0x5E05,0x6813,
+0x62F4,0x971C,0x53CC,0x723D,0x8C01,0x6C34,0x7761,0x7A0E,
+0x542E,0x77AC,0x987A,0x821C,0x8BF4,0x7855,0x6714,0x70C1,
+0x65AF,0x6495,0x5636,0x601D,0x79C1,0x53F8,0x4E1D,0x6B7B,
+0x8086,0x5BFA,0x55E3,0x56DB,0x4F3A,0x4F3C,0x9972,0x5DF3,
+0x677E,0x8038,0x6002,0x9882,0x9001,0x5B8B,0x8BBC,0x8BF5,
+0x641C,0x8258,0x64DE,0x55FD,0x82CF,0x9165,0x4FD7,0x7D20,
+0x901F,0x7C9F,0x50F3,0x5851,0x6EAF,0x5BBF,0x8BC9,0x8083,
+0x9178,0x849C,0x7B97,0x867D,0x968B,0x968F,0x7EE5,0x9AD3,
+0x788E,0x5C81,0x7A57,0x9042,0x96A7,0x795F,0x5B59,0x635F,
+0x7B0B,0x84D1,0x68AD,0x5506,0x7F29,0x7410,0x7D22,0x9501,
+0x6240,0x584C,0x4ED6,0x5B83,0x5979,0x5854, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x736D,0x631E,0x8E4B,0x8E0F,0x80CE,0x82D4,0x62AC,0x53F0,
+0x6CF0,0x915E,0x592A,0x6001,0x6C70,0x574D,0x644A,0x8D2A,
+0x762B,0x6EE9,0x575B,0x6A80,0x75F0,0x6F6D,0x8C2D,0x8C08,
+0x5766,0x6BEF,0x8892,0x78B3,0x63A2,0x53F9,0x70AD,0x6C64,
+0x5858,0x642A,0x5802,0x68E0,0x819B,0x5510,0x7CD6,0x5018,
+0x8EBA,0x6DCC,0x8D9F,0x70EB,0x638F,0x6D9B,0x6ED4,0x7EE6,
+0x8404,0x6843,0x9003,0x6DD8,0x9676,0x8BA8,0x5957,0x7279,
+0x85E4,0x817E,0x75BC,0x8A8A,0x68AF,0x5254,0x8E22,0x9511,
+0x63D0,0x9898,0x8E44,0x557C,0x4F53,0x66FF,0x568F,0x60D5,
+0x6D95,0x5243,0x5C49,0x5929,0x6DFB,0x586B,0x7530,0x751C,
+0x606C,0x8214,0x8146,0x6311,0x6761,0x8FE2,0x773A,0x8DF3,
+0x8D34,0x94C1,0x5E16,0x5385,0x542C,0x70C3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C40,0x5EF7,0x505C,0x4EAD,0x5EAD,0x633A,0x8247,0x901A,
+0x6850,0x916E,0x77B3,0x540C,0x94DC,0x5F64,0x7AE5,0x6876,
+0x6345,0x7B52,0x7EDF,0x75DB,0x5077,0x6295,0x5934,0x900F,
+0x51F8,0x79C3,0x7A81,0x56FE,0x5F92,0x9014,0x6D82,0x5C60,
+0x571F,0x5410,0x5154,0x6E4D,0x56E2,0x63A8,0x9893,0x817F,
+0x8715,0x892A,0x9000,0x541E,0x5C6F,0x81C0,0x62D6,0x6258,
+0x8131,0x9E35,0x9640,0x9A6E,0x9A7C,0x692D,0x59A5,0x62D3,
+0x553E,0x6316,0x54C7,0x86D9,0x6D3C,0x5A03,0x74E6,0x889C,
+0x6B6A,0x5916,0x8C4C,0x5F2F,0x6E7E,0x73A9,0x987D,0x4E38,
+0x70F7,0x5B8C,0x7897,0x633D,0x665A,0x7696,0x60CB,0x5B9B,
+0x5A49,0x4E07,0x8155,0x6C6A,0x738B,0x4EA1,0x6789,0x7F51,
+0x5F80,0x65FA,0x671B,0x5FD8,0x5984,0x5A01, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5DCD,0x5FAE,0x5371,0x97E6,0x8FDD,0x6845,0x56F4,0x552F,
+0x60DF,0x4E3A,0x6F4D,0x7EF4,0x82C7,0x840E,0x59D4,0x4F1F,
+0x4F2A,0x5C3E,0x7EAC,0x672A,0x851A,0x5473,0x754F,0x80C3,
+0x5582,0x9B4F,0x4F4D,0x6E2D,0x8C13,0x5C09,0x6170,0x536B,
+0x761F,0x6E29,0x868A,0x6587,0x95FB,0x7EB9,0x543B,0x7A33,
+0x7D0A,0x95EE,0x55E1,0x7FC1,0x74EE,0x631D,0x8717,0x6DA1,
+0x7A9D,0x6211,0x65A1,0x5367,0x63E1,0x6C83,0x5DEB,0x545C,
+0x94A8,0x4E4C,0x6C61,0x8BEC,0x5C4B,0x65E0,0x829C,0x68A7,
+0x543E,0x5434,0x6BCB,0x6B66,0x4E94,0x6342,0x5348,0x821E,
+0x4F0D,0x4FAE,0x575E,0x620A,0x96FE,0x6664,0x7269,0x52FF,
+0x52A1,0x609F,0x8BEF,0x6614,0x7199,0x6790,0x897F,0x7852,
+0x77FD,0x6670,0x563B,0x5438,0x9521,0x727A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7A00,0x606F,0x5E0C,0x6089,0x819D,0x5915,0x60DC,0x7184,
+0x70EF,0x6EAA,0x6C50,0x7280,0x6A84,0x88AD,0x5E2D,0x4E60,
+0x5AB3,0x559C,0x94E3,0x6D17,0x7CFB,0x9699,0x620F,0x7EC6,
+0x778E,0x867E,0x5323,0x971E,0x8F96,0x6687,0x5CE1,0x4FA0,
+0x72ED,0x4E0B,0x53A6,0x590F,0x5413,0x6380,0x9528,0x5148,
+0x4ED9,0x9C9C,0x7EA4,0x54B8,0x8D24,0x8854,0x8237,0x95F2,
+0x6D8E,0x5F26,0x5ACC,0x663E,0x9669,0x73B0,0x732E,0x53BF,
+0x817A,0x9985,0x7FA1,0x5BAA,0x9677,0x9650,0x7EBF,0x76F8,
+0x53A2,0x9576,0x9999,0x7BB1,0x8944,0x6E58,0x4E61,0x7FD4,
+0x7965,0x8BE6,0x60F3,0x54CD,0x4EAB,0x9879,0x5DF7,0x6A61,
+0x50CF,0x5411,0x8C61,0x8427,0x785D,0x9704,0x524A,0x54EE,
+0x56A3,0x9500,0x6D88,0x5BB5,0x6DC6,0x6653, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5C0F,0x5B5D,0x6821,0x8096,0x5578,0x7B11,0x6548,0x6954,
+0x4E9B,0x6B47,0x874E,0x978B,0x534F,0x631F,0x643A,0x90AA,
+0x659C,0x80C1,0x8C10,0x5199,0x68B0,0x5378,0x87F9,0x61C8,
+0x6CC4,0x6CFB,0x8C22,0x5C51,0x85AA,0x82AF,0x950C,0x6B23,
+0x8F9B,0x65B0,0x5FFB,0x5FC3,0x4FE1,0x8845,0x661F,0x8165,
+0x7329,0x60FA,0x5174,0x5211,0x578B,0x5F62,0x90A2,0x884C,
+0x9192,0x5E78,0x674F,0x6027,0x59D3,0x5144,0x51F6,0x80F8,
+0x5308,0x6C79,0x96C4,0x718A,0x4F11,0x4FEE,0x7F9E,0x673D,
+0x55C5,0x9508,0x79C0,0x8896,0x7EE3,0x589F,0x620C,0x9700,
+0x865A,0x5618,0x987B,0x5F90,0x8BB8,0x84C4,0x9157,0x53D9,
+0x65ED,0x5E8F,0x755C,0x6064,0x7D6E,0x5A7F,0x7EEA,0x7EED,
+0x8F69,0x55A7,0x5BA3,0x60AC,0x65CB,0x7384, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9009,0x7663,0x7729,0x7EDA,0x9774,0x859B,0x5B66,0x7A74,
+0x96EA,0x8840,0x52CB,0x718F,0x5FAA,0x65EC,0x8BE2,0x5BFB,
+0x9A6F,0x5DE1,0x6B89,0x6C5B,0x8BAD,0x8BAF,0x900A,0x8FC5,
+0x538B,0x62BC,0x9E26,0x9E2D,0x5440,0x4E2B,0x82BD,0x7259,
+0x869C,0x5D16,0x8859,0x6DAF,0x96C5,0x54D1,0x4E9A,0x8BB6,
+0x7109,0x54BD,0x9609,0x70DF,0x6DF9,0x76D0,0x4E25,0x7814,
+0x8712,0x5CA9,0x5EF6,0x8A00,0x989C,0x960E,0x708E,0x6CBF,
+0x5944,0x63A9,0x773C,0x884D,0x6F14,0x8273,0x5830,0x71D5,
+0x538C,0x781A,0x96C1,0x5501,0x5F66,0x7130,0x5BB4,0x8C1A,
+0x9A8C,0x6B83,0x592E,0x9E2F,0x79E7,0x6768,0x626C,0x4F6F,
+0x75A1,0x7F8A,0x6D0B,0x9633,0x6C27,0x4EF0,0x75D2,0x517B,
+0x6837,0x6F3E,0x9080,0x8170,0x5996,0x7476, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6447,0x5C27,0x9065,0x7A91,0x8C23,0x59DA,0x54AC,0x8200,
+0x836F,0x8981,0x8000,0x6930,0x564E,0x8036,0x7237,0x91CE,
+0x51B6,0x4E5F,0x9875,0x6396,0x4E1A,0x53F6,0x66F3,0x814B,
+0x591C,0x6DB2,0x4E00,0x58F9,0x533B,0x63D6,0x94F1,0x4F9D,
+0x4F0A,0x8863,0x9890,0x5937,0x9057,0x79FB,0x4EEA,0x80F0,
+0x7591,0x6C82,0x5B9C,0x59E8,0x5F5D,0x6905,0x8681,0x501A,
+0x5DF2,0x4E59,0x77E3,0x4EE5,0x827A,0x6291,0x6613,0x9091,
+0x5C79,0x4EBF,0x5F79,0x81C6,0x9038,0x8084,0x75AB,0x4EA6,
+0x88D4,0x610F,0x6BC5,0x5FC6,0x4E49,0x76CA,0x6EA2,0x8BE3,
+0x8BAE,0x8C0A,0x8BD1,0x5F02,0x7FFC,0x7FCC,0x7ECE,0x8335,
+0x836B,0x56E0,0x6BB7,0x97F3,0x9634,0x59FB,0x541F,0x94F6,
+0x6DEB,0x5BC5,0x996E,0x5C39,0x5F15,0x9690, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5370,0x82F1,0x6A31,0x5A74,0x9E70,0x5E94,0x7F28,0x83B9,
+0x8424,0x8425,0x8367,0x8747,0x8FCE,0x8D62,0x76C8,0x5F71,
+0x9896,0x786C,0x6620,0x54DF,0x62E5,0x4F63,0x81C3,0x75C8,
+0x5EB8,0x96CD,0x8E0A,0x86F9,0x548F,0x6CF3,0x6D8C,0x6C38,
+0x607F,0x52C7,0x7528,0x5E7D,0x4F18,0x60A0,0x5FE7,0x5C24,
+0x7531,0x90AE,0x94C0,0x72B9,0x6CB9,0x6E38,0x9149,0x6709,
+0x53CB,0x53F3,0x4F51,0x91C9,0x8BF1,0x53C8,0x5E7C,0x8FC2,
+0x6DE4,0x4E8E,0x76C2,0x6986,0x865E,0x611A,0x8206,0x4F59,
+0x4FDE,0x903E,0x9C7C,0x6109,0x6E1D,0x6E14,0x9685,0x4E88,
+0x5A31,0x96E8,0x4E0E,0x5C7F,0x79B9,0x5B87,0x8BED,0x7FBD,
+0x7389,0x57DF,0x828B,0x90C1,0x5401,0x9047,0x55BB,0x5CEA,
+0x5FA1,0x6108,0x6B32,0x72F1,0x80B2,0x8A89, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6D74,0x5BD3,0x88D5,0x9884,0x8C6B,0x9A6D,0x9E33,0x6E0A,
+0x51A4,0x5143,0x57A3,0x8881,0x539F,0x63F4,0x8F95,0x56ED,
+0x5458,0x5706,0x733F,0x6E90,0x7F18,0x8FDC,0x82D1,0x613F,
+0x6028,0x9662,0x66F0,0x7EA6,0x8D8A,0x8DC3,0x94A5,0x5CB3,
+0x7CA4,0x6708,0x60A6,0x9605,0x8018,0x4E91,0x90E7,0x5300,
+0x9668,0x5141,0x8FD0,0x8574,0x915D,0x6655,0x97F5,0x5B55,
+0x531D,0x7838,0x6742,0x683D,0x54C9,0x707E,0x5BB0,0x8F7D,
+0x518D,0x5728,0x54B1,0x6512,0x6682,0x8D5E,0x8D43,0x810F,
+0x846C,0x906D,0x7CDF,0x51FF,0x85FB,0x67A3,0x65E9,0x6FA1,
+0x86A4,0x8E81,0x566A,0x9020,0x7682,0x7076,0x71E5,0x8D23,
+0x62E9,0x5219,0x6CFD,0x8D3C,0x600E,0x589E,0x618E,0x66FE,
+0x8D60,0x624E,0x55B3,0x6E23,0x672D,0x8F67, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x94E1,0x95F8,0x7728,0x6805,0x69A8,0x548B,0x4E4D,0x70B8,
+0x8BC8,0x6458,0x658B,0x5B85,0x7A84,0x503A,0x5BE8,0x77BB,
+0x6BE1,0x8A79,0x7C98,0x6CBE,0x76CF,0x65A9,0x8F97,0x5D2D,
+0x5C55,0x8638,0x6808,0x5360,0x6218,0x7AD9,0x6E5B,0x7EFD,
+0x6A1F,0x7AE0,0x5F70,0x6F33,0x5F20,0x638C,0x6DA8,0x6756,
+0x4E08,0x5E10,0x8D26,0x4ED7,0x80C0,0x7634,0x969C,0x62DB,
+0x662D,0x627E,0x6CBC,0x8D75,0x7167,0x7F69,0x5146,0x8087,
+0x53EC,0x906E,0x6298,0x54F2,0x86F0,0x8F99,0x8005,0x9517,
+0x8517,0x8FD9,0x6D59,0x73CD,0x659F,0x771F,0x7504,0x7827,
+0x81FB,0x8D1E,0x9488,0x4FA6,0x6795,0x75B9,0x8BCA,0x9707,
+0x632F,0x9547,0x9635,0x84B8,0x6323,0x7741,0x5F81,0x72F0,
+0x4E89,0x6014,0x6574,0x62EF,0x6B63,0x653F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5E27,0x75C7,0x90D1,0x8BC1,0x829D,0x679D,0x652F,0x5431,
+0x8718,0x77E5,0x80A2,0x8102,0x6C41,0x4E4B,0x7EC7,0x804C,
+0x76F4,0x690D,0x6B96,0x6267,0x503C,0x4F84,0x5740,0x6307,
+0x6B62,0x8DBE,0x53EA,0x65E8,0x7EB8,0x5FD7,0x631A,0x63B7,
+0x81F3,0x81F4,0x7F6E,0x5E1C,0x5CD9,0x5236,0x667A,0x79E9,
+0x7A1A,0x8D28,0x7099,0x75D4,0x6EDE,0x6CBB,0x7A92,0x4E2D,
+0x76C5,0x5FE0,0x949F,0x8877,0x7EC8,0x79CD,0x80BF,0x91CD,
+0x4EF2,0x4F17,0x821F,0x5468,0x5DDE,0x6D32,0x8BCC,0x7CA5,
+0x8F74,0x8098,0x5E1A,0x5492,0x76B1,0x5B99,0x663C,0x9AA4,
+0x73E0,0x682A,0x86DB,0x6731,0x732A,0x8BF8,0x8BDB,0x9010,
+0x7AF9,0x70DB,0x716E,0x62C4,0x77A9,0x5631,0x4E3B,0x8457,
+0x67F1,0x52A9,0x86C0,0x8D2E,0x94F8,0x7B51, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4F4F,0x6CE8,0x795D,0x9A7B,0x6293,0x722A,0x62FD,0x4E13,
+0x7816,0x8F6C,0x64B0,0x8D5A,0x7BC6,0x6869,0x5E84,0x88C5,
+0x5986,0x649E,0x58EE,0x72B6,0x690E,0x9525,0x8FFD,0x8D58,
+0x5760,0x7F00,0x8C06,0x51C6,0x6349,0x62D9,0x5353,0x684C,
+0x7422,0x8301,0x914C,0x5544,0x7740,0x707C,0x6D4A,0x5179,
+0x54A8,0x8D44,0x59FF,0x6ECB,0x6DC4,0x5B5C,0x7D2B,0x4ED4,
+0x7C7D,0x6ED3,0x5B50,0x81EA,0x6E0D,0x5B57,0x9B03,0x68D5,
+0x8E2A,0x5B97,0x7EFC,0x603B,0x7EB5,0x90B9,0x8D70,0x594F,
+0x63CD,0x79DF,0x8DB3,0x5352,0x65CF,0x7956,0x8BC5,0x963B,
+0x7EC4,0x94BB,0x7E82,0x5634,0x9189,0x6700,0x7F6A,0x5C0A,
+0x9075,0x6628,0x5DE6,0x4F50,0x67DE,0x505A,0x4F5C,0x5750,
+0x5EA7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E8D,0x4E0C,0x5140,0x4E10,0x5EFF,0x5345,0x4E15,0x4E98,
+0x4E1E,0x9B32,0x5B6C,0x5669,0x4E28,0x79BA,0x4E3F,0x5315,
+0x4E47,0x592D,0x723B,0x536E,0x6C10,0x56DF,0x80E4,0x9997,
+0x6BD3,0x777E,0x9F17,0x4E36,0x4E9F,0x9F10,0x4E5C,0x4E69,
+0x4E93,0x8288,0x5B5B,0x556C,0x560F,0x4EC4,0x538D,0x539D,
+0x53A3,0x53A5,0x53AE,0x9765,0x8D5D,0x531A,0x53F5,0x5326,
+0x532E,0x533E,0x8D5C,0x5366,0x5363,0x5202,0x5208,0x520E,
+0x522D,0x5233,0x523F,0x5240,0x524C,0x525E,0x5261,0x525C,
+0x84AF,0x527D,0x5282,0x5281,0x5290,0x5293,0x5182,0x7F54,
+0x4EBB,0x4EC3,0x4EC9,0x4EC2,0x4EE8,0x4EE1,0x4EEB,0x4EDE,
+0x4F1B,0x4EF3,0x4F22,0x4F64,0x4EF5,0x4F25,0x4F27,0x4F09,
+0x4F2B,0x4F5E,0x4F67,0x6538,0x4F5A,0x4F5D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4F5F,0x4F57,0x4F32,0x4F3D,0x4F76,0x4F74,0x4F91,0x4F89,
+0x4F83,0x4F8F,0x4F7E,0x4F7B,0x4FAA,0x4F7C,0x4FAC,0x4F94,
+0x4FE6,0x4FE8,0x4FEA,0x4FC5,0x4FDA,0x4FE3,0x4FDC,0x4FD1,
+0x4FDF,0x4FF8,0x5029,0x504C,0x4FF3,0x502C,0x500F,0x502E,
+0x502D,0x4FFE,0x501C,0x500C,0x5025,0x5028,0x507E,0x5043,
+0x5055,0x5048,0x504E,0x506C,0x507B,0x50A5,0x50A7,0x50A9,
+0x50BA,0x50D6,0x5106,0x50ED,0x50EC,0x50E6,0x50EE,0x5107,
+0x510B,0x4EDD,0x6C3D,0x4F58,0x4F65,0x4FCE,0x9FA0,0x6C46,
+0x7C74,0x516E,0x5DFD,0x9EC9,0x9998,0x5181,0x5914,0x52F9,
+0x530D,0x8A07,0x5310,0x51EB,0x5919,0x5155,0x4EA0,0x5156,
+0x4EB3,0x886E,0x88A4,0x4EB5,0x8114,0x88D2,0x7980,0x5B34,
+0x8803,0x7FB8,0x51AB,0x51B1,0x51BD,0x51BC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x51C7,0x5196,0x51A2,0x51A5,0x8BA0,0x8BA6,0x8BA7,0x8BAA,
+0x8BB4,0x8BB5,0x8BB7,0x8BC2,0x8BC3,0x8BCB,0x8BCF,0x8BCE,
+0x8BD2,0x8BD3,0x8BD4,0x8BD6,0x8BD8,0x8BD9,0x8BDC,0x8BDF,
+0x8BE0,0x8BE4,0x8BE8,0x8BE9,0x8BEE,0x8BF0,0x8BF3,0x8BF6,
+0x8BF9,0x8BFC,0x8BFF,0x8C00,0x8C02,0x8C04,0x8C07,0x8C0C,
+0x8C0F,0x8C11,0x8C12,0x8C14,0x8C15,0x8C16,0x8C19,0x8C1B,
+0x8C18,0x8C1D,0x8C1F,0x8C20,0x8C21,0x8C25,0x8C27,0x8C2A,
+0x8C2B,0x8C2E,0x8C2F,0x8C32,0x8C33,0x8C35,0x8C36,0x5369,
+0x537A,0x961D,0x9622,0x9621,0x9631,0x962A,0x963D,0x963C,
+0x9642,0x9649,0x9654,0x965F,0x9667,0x966C,0x9672,0x9674,
+0x9688,0x968D,0x9697,0x96B0,0x9097,0x909B,0x909D,0x9099,
+0x90AC,0x90A1,0x90B4,0x90B3,0x90B6,0x90BA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x90B8,0x90B0,0x90CF,0x90C5,0x90BE,0x90D0,0x90C4,0x90C7,
+0x90D3,0x90E6,0x90E2,0x90DC,0x90D7,0x90DB,0x90EB,0x90EF,
+0x90FE,0x9104,0x9122,0x911E,0x9123,0x9131,0x912F,0x9139,
+0x9143,0x9146,0x520D,0x5942,0x52A2,0x52AC,0x52AD,0x52BE,
+0x54FF,0x52D0,0x52D6,0x52F0,0x53DF,0x71EE,0x77CD,0x5EF4,
+0x51F5,0x51FC,0x9B2F,0x53B6,0x5F01,0x755A,0x5DEF,0x574C,
+0x57A9,0x57A1,0x587E,0x58BC,0x58C5,0x58D1,0x5729,0x572C,
+0x572A,0x5733,0x5739,0x572E,0x572F,0x575C,0x573B,0x5742,
+0x5769,0x5785,0x576B,0x5786,0x577C,0x577B,0x5768,0x576D,
+0x5776,0x5773,0x57AD,0x57A4,0x578C,0x57B2,0x57CF,0x57A7,
+0x57B4,0x5793,0x57A0,0x57D5,0x57D8,0x57DA,0x57D9,0x57D2,
+0x57B8,0x57F4,0x57EF,0x57F8,0x57E4,0x57DD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x580B,0x580D,0x57FD,0x57ED,0x5800,0x581E,0x5819,0x5844,
+0x5820,0x5865,0x586C,0x5881,0x5889,0x589A,0x5880,0x99A8,
+0x9F19,0x61FF,0x8279,0x827D,0x827F,0x828F,0x828A,0x82A8,
+0x8284,0x828E,0x8291,0x8297,0x8299,0x82AB,0x82B8,0x82BE,
+0x82B0,0x82C8,0x82CA,0x82E3,0x8298,0x82B7,0x82AE,0x82CB,
+0x82CC,0x82C1,0x82A9,0x82B4,0x82A1,0x82AA,0x829F,0x82C4,
+0x82CE,0x82A4,0x82E1,0x8309,0x82F7,0x82E4,0x830F,0x8307,
+0x82DC,0x82F4,0x82D2,0x82D8,0x830C,0x82FB,0x82D3,0x8311,
+0x831A,0x8306,0x8314,0x8315,0x82E0,0x82D5,0x831C,0x8351,
+0x835B,0x835C,0x8308,0x8392,0x833C,0x8334,0x8331,0x839B,
+0x835E,0x832F,0x834F,0x8347,0x8343,0x835F,0x8340,0x8317,
+0x8360,0x832D,0x833A,0x8333,0x8366,0x8365, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8368,0x831B,0x8369,0x836C,0x836A,0x836D,0x836E,0x83B0,
+0x8378,0x83B3,0x83B4,0x83A0,0x83AA,0x8393,0x839C,0x8385,
+0x837C,0x83B6,0x83A9,0x837D,0x83B8,0x837B,0x8398,0x839E,
+0x83A8,0x83BA,0x83BC,0x83C1,0x8401,0x83E5,0x83D8,0x5807,
+0x8418,0x840B,0x83DD,0x83FD,0x83D6,0x841C,0x8438,0x8411,
+0x8406,0x83D4,0x83DF,0x840F,0x8403,0x83F8,0x83F9,0x83EA,
+0x83C5,0x83C0,0x8426,0x83F0,0x83E1,0x845C,0x8451,0x845A,
+0x8459,0x8473,0x8487,0x8488,0x847A,0x8489,0x8478,0x843C,
+0x8446,0x8469,0x8476,0x848C,0x848E,0x8431,0x846D,0x84C1,
+0x84CD,0x84D0,0x84E6,0x84BD,0x84D3,0x84CA,0x84BF,0x84BA,
+0x84E0,0x84A1,0x84B9,0x84B4,0x8497,0x84E5,0x84E3,0x850C,
+0x750D,0x8538,0x84F0,0x8539,0x851F,0x853A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8556,0x853B,0x84FF,0x84FC,0x8559,0x8548,0x8568,0x8564,
+0x855E,0x857A,0x77A2,0x8543,0x8572,0x857B,0x85A4,0x85A8,
+0x8587,0x858F,0x8579,0x85AE,0x859C,0x8585,0x85B9,0x85B7,
+0x85B0,0x85D3,0x85C1,0x85DC,0x85FF,0x8627,0x8605,0x8629,
+0x8616,0x863C,0x5EFE,0x5F08,0x593C,0x5941,0x8037,0x5955,
+0x595A,0x5958,0x530F,0x5C22,0x5C25,0x5C2C,0x5C34,0x624C,
+0x626A,0x629F,0x62BB,0x62CA,0x62DA,0x62D7,0x62EE,0x6322,
+0x62F6,0x6339,0x634B,0x6343,0x63AD,0x63F6,0x6371,0x637A,
+0x638E,0x63B4,0x636D,0x63AC,0x638A,0x6369,0x63AE,0x63BC,
+0x63F2,0x63F8,0x63E0,0x63FF,0x63C4,0x63DE,0x63CE,0x6452,
+0x63C6,0x63BE,0x6445,0x6441,0x640B,0x641B,0x6420,0x640C,
+0x6426,0x6421,0x645E,0x6484,0x646D,0x6496, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x647A,0x64B7,0x64B8,0x6499,0x64BA,0x64C0,0x64D0,0x64D7,
+0x64E4,0x64E2,0x6509,0x6525,0x652E,0x5F0B,0x5FD2,0x7519,
+0x5F11,0x535F,0x53F1,0x53FD,0x53E9,0x53E8,0x53FB,0x5412,
+0x5416,0x5406,0x544B,0x5452,0x5453,0x5454,0x5456,0x5443,
+0x5421,0x5457,0x5459,0x5423,0x5432,0x5482,0x5494,0x5477,
+0x5471,0x5464,0x549A,0x549B,0x5484,0x5476,0x5466,0x549D,
+0x54D0,0x54AD,0x54C2,0x54B4,0x54D2,0x54A7,0x54A6,0x54D3,
+0x54D4,0x5472,0x54A3,0x54D5,0x54BB,0x54BF,0x54CC,0x54D9,
+0x54DA,0x54DC,0x54A9,0x54AA,0x54A4,0x54DD,0x54CF,0x54DE,
+0x551B,0x54E7,0x5520,0x54FD,0x5514,0x54F3,0x5522,0x5523,
+0x550F,0x5511,0x5527,0x552A,0x5567,0x558F,0x55B5,0x5549,
+0x556D,0x5541,0x5555,0x553F,0x5550,0x553C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5537,0x5556,0x5575,0x5576,0x5577,0x5533,0x5530,0x555C,
+0x558B,0x55D2,0x5583,0x55B1,0x55B9,0x5588,0x5581,0x559F,
+0x557E,0x55D6,0x5591,0x557B,0x55DF,0x55BD,0x55BE,0x5594,
+0x5599,0x55EA,0x55F7,0x55C9,0x561F,0x55D1,0x55EB,0x55EC,
+0x55D4,0x55E6,0x55DD,0x55C4,0x55EF,0x55E5,0x55F2,0x55F3,
+0x55CC,0x55CD,0x55E8,0x55F5,0x55E4,0x8F94,0x561E,0x5608,
+0x560C,0x5601,0x5624,0x5623,0x55FE,0x5600,0x5627,0x562D,
+0x5658,0x5639,0x5657,0x562C,0x564D,0x5662,0x5659,0x565C,
+0x564C,0x5654,0x5686,0x5664,0x5671,0x566B,0x567B,0x567C,
+0x5685,0x5693,0x56AF,0x56D4,0x56D7,0x56DD,0x56E1,0x56F5,
+0x56EB,0x56F9,0x56FF,0x5704,0x570A,0x5709,0x571C,0x5E0F,
+0x5E19,0x5E14,0x5E11,0x5E31,0x5E3B,0x5E3C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5E37,0x5E44,0x5E54,0x5E5B,0x5E5E,0x5E61,0x5C8C,0x5C7A,
+0x5C8D,0x5C90,0x5C96,0x5C88,0x5C98,0x5C99,0x5C91,0x5C9A,
+0x5C9C,0x5CB5,0x5CA2,0x5CBD,0x5CAC,0x5CAB,0x5CB1,0x5CA3,
+0x5CC1,0x5CB7,0x5CC4,0x5CD2,0x5CE4,0x5CCB,0x5CE5,0x5D02,
+0x5D03,0x5D27,0x5D26,0x5D2E,0x5D24,0x5D1E,0x5D06,0x5D1B,
+0x5D58,0x5D3E,0x5D34,0x5D3D,0x5D6C,0x5D5B,0x5D6F,0x5D5D,
+0x5D6B,0x5D4B,0x5D4A,0x5D69,0x5D74,0x5D82,0x5D99,0x5D9D,
+0x8C73,0x5DB7,0x5DC5,0x5F73,0x5F77,0x5F82,0x5F87,0x5F89,
+0x5F8C,0x5F95,0x5F99,0x5F9C,0x5FA8,0x5FAD,0x5FB5,0x5FBC,
+0x8862,0x5F61,0x72AD,0x72B0,0x72B4,0x72B7,0x72B8,0x72C3,
+0x72C1,0x72CE,0x72CD,0x72D2,0x72E8,0x72EF,0x72E9,0x72F2,
+0x72F4,0x72F7,0x7301,0x72F3,0x7303,0x72FA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x72FB,0x7317,0x7313,0x7321,0x730A,0x731E,0x731D,0x7315,
+0x7322,0x7339,0x7325,0x732C,0x7338,0x7331,0x7350,0x734D,
+0x7357,0x7360,0x736C,0x736F,0x737E,0x821B,0x5925,0x98E7,
+0x5924,0x5902,0x9963,0x9967,0x9968,0x9969,0x996A,0x996B,
+0x996C,0x9974,0x9977,0x997D,0x9980,0x9984,0x9987,0x998A,
+0x998D,0x9990,0x9991,0x9993,0x9994,0x9995,0x5E80,0x5E91,
+0x5E8B,0x5E96,0x5EA5,0x5EA0,0x5EB9,0x5EB5,0x5EBE,0x5EB3,
+0x8D53,0x5ED2,0x5ED1,0x5EDB,0x5EE8,0x5EEA,0x81BA,0x5FC4,
+0x5FC9,0x5FD6,0x5FCF,0x6003,0x5FEE,0x6004,0x5FE1,0x5FE4,
+0x5FFE,0x6005,0x6006,0x5FEA,0x5FED,0x5FF8,0x6019,0x6035,
+0x6026,0x601B,0x600F,0x600D,0x6029,0x602B,0x600A,0x603F,
+0x6021,0x6078,0x6079,0x607B,0x607A,0x6042, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x606A,0x607D,0x6096,0x609A,0x60AD,0x609D,0x6083,0x6092,
+0x608C,0x609B,0x60EC,0x60BB,0x60B1,0x60DD,0x60D8,0x60C6,
+0x60DA,0x60B4,0x6120,0x6126,0x6115,0x6123,0x60F4,0x6100,
+0x610E,0x612B,0x614A,0x6175,0x61AC,0x6194,0x61A7,0x61B7,
+0x61D4,0x61F5,0x5FDD,0x96B3,0x95E9,0x95EB,0x95F1,0x95F3,
+0x95F5,0x95F6,0x95FC,0x95FE,0x9603,0x9604,0x9606,0x9608,
+0x960A,0x960B,0x960C,0x960D,0x960F,0x9612,0x9615,0x9616,
+0x9617,0x9619,0x961A,0x4E2C,0x723F,0x6215,0x6C35,0x6C54,
+0x6C5C,0x6C4A,0x6CA3,0x6C85,0x6C90,0x6C94,0x6C8C,0x6C68,
+0x6C69,0x6C74,0x6C76,0x6C86,0x6CA9,0x6CD0,0x6CD4,0x6CAD,
+0x6CF7,0x6CF8,0x6CF1,0x6CD7,0x6CB2,0x6CE0,0x6CD6,0x6CFA,
+0x6CEB,0x6CEE,0x6CB1,0x6CD3,0x6CEF,0x6CFE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6D39,0x6D27,0x6D0C,0x6D43,0x6D48,0x6D07,0x6D04,0x6D19,
+0x6D0E,0x6D2B,0x6D4D,0x6D2E,0x6D35,0x6D1A,0x6D4F,0x6D52,
+0x6D54,0x6D33,0x6D91,0x6D6F,0x6D9E,0x6DA0,0x6D5E,0x6D93,
+0x6D94,0x6D5C,0x6D60,0x6D7C,0x6D63,0x6E1A,0x6DC7,0x6DC5,
+0x6DDE,0x6E0E,0x6DBF,0x6DE0,0x6E11,0x6DE6,0x6DDD,0x6DD9,
+0x6E16,0x6DAB,0x6E0C,0x6DAE,0x6E2B,0x6E6E,0x6E4E,0x6E6B,
+0x6EB2,0x6E5F,0x6E86,0x6E53,0x6E54,0x6E32,0x6E25,0x6E44,
+0x6EDF,0x6EB1,0x6E98,0x6EE0,0x6F2D,0x6EE2,0x6EA5,0x6EA7,
+0x6EBD,0x6EBB,0x6EB7,0x6ED7,0x6EB4,0x6ECF,0x6E8F,0x6EC2,
+0x6E9F,0x6F62,0x6F46,0x6F47,0x6F24,0x6F15,0x6EF9,0x6F2F,
+0x6F36,0x6F4B,0x6F74,0x6F2A,0x6F09,0x6F29,0x6F89,0x6F8D,
+0x6F8C,0x6F78,0x6F72,0x6F7C,0x6F7A,0x6FD1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6FC9,0x6FA7,0x6FB9,0x6FB6,0x6FC2,0x6FE1,0x6FEE,0x6FDE,
+0x6FE0,0x6FEF,0x701A,0x7023,0x701B,0x7039,0x7035,0x704F,
+0x705E,0x5B80,0x5B84,0x5B95,0x5B93,0x5BA5,0x5BB8,0x752F,
+0x9A9E,0x6434,0x5BE4,0x5BEE,0x8930,0x5BF0,0x8E47,0x8B07,
+0x8FB6,0x8FD3,0x8FD5,0x8FE5,0x8FEE,0x8FE4,0x8FE9,0x8FE6,
+0x8FF3,0x8FE8,0x9005,0x9004,0x900B,0x9026,0x9011,0x900D,
+0x9016,0x9021,0x9035,0x9036,0x902D,0x902F,0x9044,0x9051,
+0x9052,0x9050,0x9068,0x9058,0x9062,0x905B,0x66B9,0x9074,
+0x907D,0x9082,0x9088,0x9083,0x908B,0x5F50,0x5F57,0x5F56,
+0x5F58,0x5C3B,0x54AB,0x5C50,0x5C59,0x5B71,0x5C63,0x5C66,
+0x7FBC,0x5F2A,0x5F29,0x5F2D,0x8274,0x5F3C,0x9B3B,0x5C6E,
+0x5981,0x5983,0x598D,0x59A9,0x59AA,0x59A3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5997,0x59CA,0x59AB,0x599E,0x59A4,0x59D2,0x59B2,0x59AF,
+0x59D7,0x59BE,0x5A05,0x5A06,0x59DD,0x5A08,0x59E3,0x59D8,
+0x59F9,0x5A0C,0x5A09,0x5A32,0x5A34,0x5A11,0x5A23,0x5A13,
+0x5A40,0x5A67,0x5A4A,0x5A55,0x5A3C,0x5A62,0x5A75,0x80EC,
+0x5AAA,0x5A9B,0x5A77,0x5A7A,0x5ABE,0x5AEB,0x5AB2,0x5AD2,
+0x5AD4,0x5AB8,0x5AE0,0x5AE3,0x5AF1,0x5AD6,0x5AE6,0x5AD8,
+0x5ADC,0x5B09,0x5B17,0x5B16,0x5B32,0x5B37,0x5B40,0x5C15,
+0x5C1C,0x5B5A,0x5B65,0x5B73,0x5B51,0x5B53,0x5B62,0x9A75,
+0x9A77,0x9A78,0x9A7A,0x9A7F,0x9A7D,0x9A80,0x9A81,0x9A85,
+0x9A88,0x9A8A,0x9A90,0x9A92,0x9A93,0x9A96,0x9A98,0x9A9B,
+0x9A9C,0x9A9D,0x9A9F,0x9AA0,0x9AA2,0x9AA3,0x9AA5,0x9AA7,
+0x7E9F,0x7EA1,0x7EA3,0x7EA5,0x7EA8,0x7EA9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7EAD,0x7EB0,0x7EBE,0x7EC0,0x7EC1,0x7EC2,0x7EC9,0x7ECB,
+0x7ECC,0x7ED0,0x7ED4,0x7ED7,0x7EDB,0x7EE0,0x7EE1,0x7EE8,
+0x7EEB,0x7EEE,0x7EEF,0x7EF1,0x7EF2,0x7F0D,0x7EF6,0x7EFA,
+0x7EFB,0x7EFE,0x7F01,0x7F02,0x7F03,0x7F07,0x7F08,0x7F0B,
+0x7F0C,0x7F0F,0x7F11,0x7F12,0x7F17,0x7F19,0x7F1C,0x7F1B,
+0x7F1F,0x7F21,0x7F22,0x7F23,0x7F24,0x7F25,0x7F26,0x7F27,
+0x7F2A,0x7F2B,0x7F2C,0x7F2D,0x7F2F,0x7F30,0x7F31,0x7F32,
+0x7F33,0x7F35,0x5E7A,0x757F,0x5DDB,0x753E,0x9095,0x738E,
+0x7391,0x73AE,0x73A2,0x739F,0x73CF,0x73C2,0x73D1,0x73B7,
+0x73B3,0x73C0,0x73C9,0x73C8,0x73E5,0x73D9,0x987C,0x740A,
+0x73E9,0x73E7,0x73DE,0x73BA,0x73F2,0x740F,0x742A,0x745B,
+0x7426,0x7425,0x7428,0x7430,0x742E,0x742C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x741B,0x741A,0x7441,0x745C,0x7457,0x7455,0x7459,0x7477,
+0x746D,0x747E,0x749C,0x748E,0x7480,0x7481,0x7487,0x748B,
+0x749E,0x74A8,0x74A9,0x7490,0x74A7,0x74D2,0x74BA,0x97EA,
+0x97EB,0x97EC,0x674C,0x6753,0x675E,0x6748,0x6769,0x67A5,
+0x6787,0x676A,0x6773,0x6798,0x67A7,0x6775,0x67A8,0x679E,
+0x67AD,0x678B,0x6777,0x677C,0x67F0,0x6809,0x67D8,0x680A,
+0x67E9,0x67B0,0x680C,0x67D9,0x67B5,0x67DA,0x67B3,0x67DD,
+0x6800,0x67C3,0x67B8,0x67E2,0x680E,0x67C1,0x67FD,0x6832,
+0x6833,0x6860,0x6861,0x684E,0x6862,0x6844,0x6864,0x6883,
+0x681D,0x6855,0x6866,0x6841,0x6867,0x6840,0x683E,0x684A,
+0x6849,0x6829,0x68B5,0x688F,0x6874,0x6877,0x6893,0x686B,
+0x68C2,0x696E,0x68FC,0x691F,0x6920,0x68F9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6924,0x68F0,0x690B,0x6901,0x6957,0x68E3,0x6910,0x6971,
+0x6939,0x6960,0x6942,0x695D,0x6984,0x696B,0x6980,0x6998,
+0x6978,0x6934,0x69CC,0x6987,0x6988,0x69CE,0x6989,0x6966,
+0x6963,0x6979,0x699B,0x69A7,0x69BB,0x69AB,0x69AD,0x69D4,
+0x69B1,0x69C1,0x69CA,0x69DF,0x6995,0x69E0,0x698D,0x69FF,
+0x6A2F,0x69ED,0x6A17,0x6A18,0x6A65,0x69F2,0x6A44,0x6A3E,
+0x6AA0,0x6A50,0x6A5B,0x6A35,0x6A8E,0x6A79,0x6A3D,0x6A28,
+0x6A58,0x6A7C,0x6A91,0x6A90,0x6AA9,0x6A97,0x6AAB,0x7337,
+0x7352,0x6B81,0x6B82,0x6B87,0x6B84,0x6B92,0x6B93,0x6B8D,
+0x6B9A,0x6B9B,0x6BA1,0x6BAA,0x8F6B,0x8F6D,0x8F71,0x8F72,
+0x8F73,0x8F75,0x8F76,0x8F78,0x8F77,0x8F79,0x8F7A,0x8F7C,
+0x8F7E,0x8F81,0x8F82,0x8F84,0x8F87,0x8F8B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8F8D,0x8F8E,0x8F8F,0x8F98,0x8F9A,0x8ECE,0x620B,0x6217,
+0x621B,0x621F,0x6222,0x6221,0x6225,0x6224,0x622C,0x81E7,
+0x74EF,0x74F4,0x74FF,0x750F,0x7511,0x7513,0x6534,0x65EE,
+0x65EF,0x65F0,0x660A,0x6619,0x6772,0x6603,0x6615,0x6600,
+0x7085,0x66F7,0x661D,0x6634,0x6631,0x6636,0x6635,0x8006,
+0x665F,0x6654,0x6641,0x664F,0x6656,0x6661,0x6657,0x6677,
+0x6684,0x668C,0x66A7,0x669D,0x66BE,0x66DB,0x66DC,0x66E6,
+0x66E9,0x8D32,0x8D33,0x8D36,0x8D3B,0x8D3D,0x8D40,0x8D45,
+0x8D46,0x8D48,0x8D49,0x8D47,0x8D4D,0x8D55,0x8D59,0x89C7,
+0x89CA,0x89CB,0x89CC,0x89CE,0x89CF,0x89D0,0x89D1,0x726E,
+0x729F,0x725D,0x7266,0x726F,0x727E,0x727F,0x7284,0x728B,
+0x728D,0x728F,0x7292,0x6308,0x6332,0x63B0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x643F,0x64D8,0x8004,0x6BEA,0x6BF3,0x6BFD,0x6BF5,0x6BF9,
+0x6C05,0x6C07,0x6C06,0x6C0D,0x6C15,0x6C18,0x6C19,0x6C1A,
+0x6C21,0x6C29,0x6C24,0x6C2A,0x6C32,0x6535,0x6555,0x656B,
+0x724D,0x7252,0x7256,0x7230,0x8662,0x5216,0x809F,0x809C,
+0x8093,0x80BC,0x670A,0x80BD,0x80B1,0x80AB,0x80AD,0x80B4,
+0x80B7,0x80E7,0x80E8,0x80E9,0x80EA,0x80DB,0x80C2,0x80C4,
+0x80D9,0x80CD,0x80D7,0x6710,0x80DD,0x80EB,0x80F1,0x80F4,
+0x80ED,0x810D,0x810E,0x80F2,0x80FC,0x6715,0x8112,0x8C5A,
+0x8136,0x811E,0x812C,0x8118,0x8132,0x8148,0x814C,0x8153,
+0x8174,0x8159,0x815A,0x8171,0x8160,0x8169,0x817C,0x817D,
+0x816D,0x8167,0x584D,0x5AB5,0x8188,0x8182,0x8191,0x6ED5,
+0x81A3,0x81AA,0x81CC,0x6726,0x81CA,0x81BB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x81C1,0x81A6,0x6B24,0x6B37,0x6B39,0x6B43,0x6B46,0x6B59,
+0x98D1,0x98D2,0x98D3,0x98D5,0x98D9,0x98DA,0x6BB3,0x5F40,
+0x6BC2,0x89F3,0x6590,0x9F51,0x6593,0x65BC,0x65C6,0x65C4,
+0x65C3,0x65CC,0x65CE,0x65D2,0x65D6,0x7080,0x709C,0x7096,
+0x709D,0x70BB,0x70C0,0x70B7,0x70AB,0x70B1,0x70E8,0x70CA,
+0x7110,0x7113,0x7116,0x712F,0x7131,0x7173,0x715C,0x7168,
+0x7145,0x7172,0x714A,0x7178,0x717A,0x7198,0x71B3,0x71B5,
+0x71A8,0x71A0,0x71E0,0x71D4,0x71E7,0x71F9,0x721D,0x7228,
+0x706C,0x7118,0x7166,0x71B9,0x623E,0x623D,0x6243,0x6248,
+0x6249,0x793B,0x7940,0x7946,0x7949,0x795B,0x795C,0x7953,
+0x795A,0x7962,0x7957,0x7960,0x796F,0x7967,0x797A,0x7985,
+0x798A,0x799A,0x79A7,0x79B3,0x5FD1,0x5FD0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x603C,0x605D,0x605A,0x6067,0x6041,0x6059,0x6063,0x60AB,
+0x6106,0x610D,0x615D,0x61A9,0x619D,0x61CB,0x61D1,0x6206,
+0x8080,0x807F,0x6C93,0x6CF6,0x6DFC,0x77F6,0x77F8,0x7800,
+0x7809,0x7817,0x7818,0x7811,0x65AB,0x782D,0x781C,0x781D,
+0x7839,0x783A,0x783B,0x781F,0x783C,0x7825,0x782C,0x7823,
+0x7829,0x784E,0x786D,0x7856,0x7857,0x7826,0x7850,0x7847,
+0x784C,0x786A,0x789B,0x7893,0x789A,0x7887,0x789C,0x78A1,
+0x78A3,0x78B2,0x78B9,0x78A5,0x78D4,0x78D9,0x78C9,0x78EC,
+0x78F2,0x7905,0x78F4,0x7913,0x7924,0x791E,0x7934,0x9F9B,
+0x9EF9,0x9EFB,0x9EFC,0x76F1,0x7704,0x770D,0x76F9,0x7707,
+0x7708,0x771A,0x7722,0x7719,0x772D,0x7726,0x7735,0x7738,
+0x7750,0x7751,0x7747,0x7743,0x775A,0x7768, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7762,0x7765,0x777F,0x778D,0x777D,0x7780,0x778C,0x7791,
+0x779F,0x77A0,0x77B0,0x77B5,0x77BD,0x753A,0x7540,0x754E,
+0x754B,0x7548,0x755B,0x7572,0x7579,0x7583,0x7F58,0x7F61,
+0x7F5F,0x8A48,0x7F68,0x7F74,0x7F71,0x7F79,0x7F81,0x7F7E,
+0x76CD,0x76E5,0x8832,0x9485,0x9486,0x9487,0x948B,0x948A,
+0x948C,0x948D,0x948F,0x9490,0x9494,0x9497,0x9495,0x949A,
+0x949B,0x949C,0x94A3,0x94A4,0x94AB,0x94AA,0x94AD,0x94AC,
+0x94AF,0x94B0,0x94B2,0x94B4,0x94B6,0x94B7,0x94B8,0x94B9,
+0x94BA,0x94BC,0x94BD,0x94BF,0x94C4,0x94C8,0x94C9,0x94CA,
+0x94CB,0x94CC,0x94CD,0x94CE,0x94D0,0x94D1,0x94D2,0x94D5,
+0x94D6,0x94D7,0x94D9,0x94D8,0x94DB,0x94DE,0x94DF,0x94E0,
+0x94E2,0x94E4,0x94E5,0x94E7,0x94E8,0x94EA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x94E9,0x94EB,0x94EE,0x94EF,0x94F3,0x94F4,0x94F5,0x94F7,
+0x94F9,0x94FC,0x94FD,0x94FF,0x9503,0x9502,0x9506,0x9507,
+0x9509,0x950A,0x950D,0x950E,0x950F,0x9512,0x9513,0x9514,
+0x9515,0x9516,0x9518,0x951B,0x951D,0x951E,0x951F,0x9522,
+0x952A,0x952B,0x9529,0x952C,0x9531,0x9532,0x9534,0x9536,
+0x9537,0x9538,0x953C,0x953E,0x953F,0x9542,0x9535,0x9544,
+0x9545,0x9546,0x9549,0x954C,0x954E,0x954F,0x9552,0x9553,
+0x9554,0x9556,0x9557,0x9558,0x9559,0x955B,0x955E,0x955F,
+0x955D,0x9561,0x9562,0x9564,0x9565,0x9566,0x9567,0x9568,
+0x9569,0x956A,0x956B,0x956C,0x956F,0x9571,0x9572,0x9573,
+0x953A,0x77E7,0x77EC,0x96C9,0x79D5,0x79ED,0x79E3,0x79EB,
+0x7A06,0x5D47,0x7A03,0x7A02,0x7A1E,0x7A14, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7A39,0x7A37,0x7A51,0x9ECF,0x99A5,0x7A70,0x7688,0x768E,
+0x7693,0x7699,0x76A4,0x74DE,0x74E0,0x752C,0x9E20,0x9E22,
+0x9E28,0x9E29,0x9E2A,0x9E2B,0x9E2C,0x9E32,0x9E31,0x9E36,
+0x9E38,0x9E37,0x9E39,0x9E3A,0x9E3E,0x9E41,0x9E42,0x9E44,
+0x9E46,0x9E47,0x9E48,0x9E49,0x9E4B,0x9E4C,0x9E4E,0x9E51,
+0x9E55,0x9E57,0x9E5A,0x9E5B,0x9E5C,0x9E5E,0x9E63,0x9E66,
+0x9E67,0x9E68,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E71,0x9E6D,
+0x9E73,0x7592,0x7594,0x7596,0x75A0,0x759D,0x75AC,0x75A3,
+0x75B3,0x75B4,0x75B8,0x75C4,0x75B1,0x75B0,0x75C3,0x75C2,
+0x75D6,0x75CD,0x75E3,0x75E8,0x75E6,0x75E4,0x75EB,0x75E7,
+0x7603,0x75F1,0x75FC,0x75FF,0x7610,0x7600,0x7605,0x760C,
+0x7617,0x760A,0x7625,0x7618,0x7615,0x7619, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x761B,0x763C,0x7622,0x7620,0x7640,0x762D,0x7630,0x763F,
+0x7635,0x7643,0x763E,0x7633,0x764D,0x765E,0x7654,0x765C,
+0x7656,0x766B,0x766F,0x7FCA,0x7AE6,0x7A78,0x7A79,0x7A80,
+0x7A86,0x7A88,0x7A95,0x7AA6,0x7AA0,0x7AAC,0x7AA8,0x7AAD,
+0x7AB3,0x8864,0x8869,0x8872,0x887D,0x887F,0x8882,0x88A2,
+0x88C6,0x88B7,0x88BC,0x88C9,0x88E2,0x88CE,0x88E3,0x88E5,
+0x88F1,0x891A,0x88FC,0x88E8,0x88FE,0x88F0,0x8921,0x8919,
+0x8913,0x891B,0x890A,0x8934,0x892B,0x8936,0x8941,0x8966,
+0x897B,0x758B,0x80E5,0x76B2,0x76B4,0x77DC,0x8012,0x8014,
+0x8016,0x801C,0x8020,0x8022,0x8025,0x8026,0x8027,0x8029,
+0x8028,0x8031,0x800B,0x8035,0x8043,0x8046,0x804D,0x8052,
+0x8069,0x8071,0x8983,0x9878,0x9880,0x9883, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9889,0x988C,0x988D,0x988F,0x9894,0x989A,0x989B,0x989E,
+0x989F,0x98A1,0x98A2,0x98A5,0x98A6,0x864D,0x8654,0x866C,
+0x866E,0x867F,0x867A,0x867C,0x867B,0x86A8,0x868D,0x868B,
+0x86AC,0x869D,0x86A7,0x86A3,0x86AA,0x8693,0x86A9,0x86B6,
+0x86C4,0x86B5,0x86CE,0x86B0,0x86BA,0x86B1,0x86AF,0x86C9,
+0x86CF,0x86B4,0x86E9,0x86F1,0x86F2,0x86ED,0x86F3,0x86D0,
+0x8713,0x86DE,0x86F4,0x86DF,0x86D8,0x86D1,0x8703,0x8707,
+0x86F8,0x8708,0x870A,0x870D,0x8709,0x8723,0x873B,0x871E,
+0x8725,0x872E,0x871A,0x873E,0x8748,0x8734,0x8731,0x8729,
+0x8737,0x873F,0x8782,0x8722,0x877D,0x877E,0x877B,0x8760,
+0x8770,0x874C,0x876E,0x878B,0x8753,0x8763,0x877C,0x8764,
+0x8759,0x8765,0x8793,0x87AF,0x87A8,0x87D2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x87C6,0x8788,0x8785,0x87AD,0x8797,0x8783,0x87AB,0x87E5,
+0x87AC,0x87B5,0x87B3,0x87CB,0x87D3,0x87BD,0x87D1,0x87C0,
+0x87CA,0x87DB,0x87EA,0x87E0,0x87EE,0x8816,0x8813,0x87FE,
+0x880A,0x881B,0x8821,0x8839,0x883C,0x7F36,0x7F42,0x7F44,
+0x7F45,0x8210,0x7AFA,0x7AFD,0x7B08,0x7B03,0x7B04,0x7B15,
+0x7B0A,0x7B2B,0x7B0F,0x7B47,0x7B38,0x7B2A,0x7B19,0x7B2E,
+0x7B31,0x7B20,0x7B25,0x7B24,0x7B33,0x7B3E,0x7B1E,0x7B58,
+0x7B5A,0x7B45,0x7B75,0x7B4C,0x7B5D,0x7B60,0x7B6E,0x7B7B,
+0x7B62,0x7B72,0x7B71,0x7B90,0x7BA6,0x7BA7,0x7BB8,0x7BAC,
+0x7B9D,0x7BA8,0x7B85,0x7BAA,0x7B9C,0x7BA2,0x7BAB,0x7BB4,
+0x7BD1,0x7BC1,0x7BCC,0x7BDD,0x7BDA,0x7BE5,0x7BE6,0x7BEA,
+0x7C0C,0x7BFE,0x7BFC,0x7C0F,0x7C16,0x7C0B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7C1F,0x7C2A,0x7C26,0x7C38,0x7C41,0x7C40,0x81FE,0x8201,
+0x8202,0x8204,0x81EC,0x8844,0x8221,0x8222,0x8223,0x822D,
+0x822F,0x8228,0x822B,0x8238,0x823B,0x8233,0x8234,0x823E,
+0x8244,0x8249,0x824B,0x824F,0x825A,0x825F,0x8268,0x887E,
+0x8885,0x8888,0x88D8,0x88DF,0x895E,0x7F9D,0x7F9F,0x7FA7,
+0x7FAF,0x7FB0,0x7FB2,0x7C7C,0x6549,0x7C91,0x7C9D,0x7C9C,
+0x7C9E,0x7CA2,0x7CB2,0x7CBC,0x7CBD,0x7CC1,0x7CC7,0x7CCC,
+0x7CCD,0x7CC8,0x7CC5,0x7CD7,0x7CE8,0x826E,0x66A8,0x7FBF,
+0x7FCE,0x7FD5,0x7FE5,0x7FE1,0x7FE6,0x7FE9,0x7FEE,0x7FF3,
+0x7CF8,0x7D77,0x7DA6,0x7DAE,0x7E47,0x7E9B,0x9EB8,0x9EB4,
+0x8D73,0x8D84,0x8D94,0x8D91,0x8DB1,0x8D67,0x8D6D,0x8C47,
+0x8C49,0x914A,0x9150,0x914E,0x914F,0x9164, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9162,0x9161,0x9170,0x9169,0x916F,0x917D,0x917E,0x9172,
+0x9174,0x9179,0x918C,0x9185,0x9190,0x918D,0x9191,0x91A2,
+0x91A3,0x91AA,0x91AD,0x91AE,0x91AF,0x91B5,0x91B4,0x91BA,
+0x8C55,0x9E7E,0x8DB8,0x8DEB,0x8E05,0x8E59,0x8E69,0x8DB5,
+0x8DBF,0x8DBC,0x8DBA,0x8DC4,0x8DD6,0x8DD7,0x8DDA,0x8DDE,
+0x8DCE,0x8DCF,0x8DDB,0x8DC6,0x8DEC,0x8DF7,0x8DF8,0x8DE3,
+0x8DF9,0x8DFB,0x8DE4,0x8E09,0x8DFD,0x8E14,0x8E1D,0x8E1F,
+0x8E2C,0x8E2E,0x8E23,0x8E2F,0x8E3A,0x8E40,0x8E39,0x8E35,
+0x8E3D,0x8E31,0x8E49,0x8E41,0x8E42,0x8E51,0x8E52,0x8E4A,
+0x8E70,0x8E76,0x8E7C,0x8E6F,0x8E74,0x8E85,0x8E8F,0x8E94,
+0x8E90,0x8E9C,0x8E9E,0x8C78,0x8C82,0x8C8A,0x8C85,0x8C98,
+0x8C94,0x659B,0x89D6,0x89DE,0x89DA,0x89DC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x89E5,0x89EB,0x89EF,0x8A3E,0x8B26,0x9753,0x96E9,0x96F3,
+0x96EF,0x9706,0x9701,0x9708,0x970F,0x970E,0x972A,0x972D,
+0x9730,0x973E,0x9F80,0x9F83,0x9F85,0x9F86,0x9F87,0x9F88,
+0x9F89,0x9F8A,0x9F8C,0x9EFE,0x9F0B,0x9F0D,0x96B9,0x96BC,
+0x96BD,0x96CE,0x96D2,0x77BF,0x96E0,0x928E,0x92AE,0x92C8,
+0x933E,0x936A,0x93CA,0x938F,0x943E,0x946B,0x9C7F,0x9C82,
+0x9C85,0x9C86,0x9C87,0x9C88,0x7A23,0x9C8B,0x9C8E,0x9C90,
+0x9C91,0x9C92,0x9C94,0x9C95,0x9C9A,0x9C9B,0x9C9E,0x9C9F,
+0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA5,0x9CA6,0x9CA7,0x9CA8,
+0x9CA9,0x9CAB,0x9CAD,0x9CAE,0x9CB0,0x9CB1,0x9CB2,0x9CB3,
+0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CBA,0x9CBB,0x9CBC,0x9CBD,
+0x9CC4,0x9CC5,0x9CC6,0x9CC7,0x9CCA,0x9CCB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9CCC,0x9CCD,0x9CCE,0x9CCF,0x9CD0,0x9CD3,0x9CD4,0x9CD5,
+0x9CD7,0x9CD8,0x9CD9,0x9CDC,0x9CDD,0x9CDF,0x9CE2,0x977C,
+0x9785,0x9791,0x9792,0x9794,0x97AF,0x97AB,0x97A3,0x97B2,
+0x97B4,0x9AB1,0x9AB0,0x9AB7,0x9E58,0x9AB6,0x9ABA,0x9ABC,
+0x9AC1,0x9AC0,0x9AC5,0x9AC2,0x9ACB,0x9ACC,0x9AD1,0x9B45,
+0x9B43,0x9B47,0x9B49,0x9B48,0x9B4D,0x9B51,0x98E8,0x990D,
+0x992E,0x9955,0x9954,0x9ADF,0x9AE1,0x9AE6,0x9AEF,0x9AEB,
+0x9AFB,0x9AED,0x9AF9,0x9B08,0x9B0F,0x9B13,0x9B1F,0x9B23,
+0x9EBD,0x9EBE,0x7E3B,0x9E82,0x9E87,0x9E88,0x9E8B,0x9E92,
+0x93D6,0x9E9D,0x9E9F,0x9EDB,0x9EDC,0x9EDD,0x9EE0,0x9EDF,
+0x9EE2,0x9EE9,0x9EE7,0x9EE5,0x9EEA,0x9EEF,0x9F22,0x9F2C,
+0x9F2F,0x9F39,0x9F37,0x9F3D,0x9F3E,0x9F44};
+
+static int func_gb2312_uni_onechar(int code){
+ if ((code>=0x2121)&&(code<=0x2658))
+ return(tab_gb2312_uni0[code-0x2121]);
+ if ((code>=0x2721)&&(code<=0x296F))
+ return(tab_gb2312_uni1[code-0x2721]);
+ if ((code>=0x3021)&&(code<=0x777E))
+ return(tab_gb2312_uni2[code-0x3021]);
+ return(0);
+}
+
+
+/* page 0 0x00A4-0x01DC */
+static uint16 tab_uni_gb23120[]={
+0x2168, 0, 0,0x216C,0x2127, 0, 0, 0,
+ 0, 0, 0, 0,0x2163,0x2140, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2141, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2824,0x2822, 0, 0,
+ 0, 0, 0, 0,0x2828,0x2826,0x283A, 0,
+0x282C,0x282A, 0, 0, 0, 0,0x2830,0x282E,
+ 0, 0, 0,0x2142, 0,0x2834,0x2832, 0,
+0x2839, 0, 0, 0, 0,0x2821, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2825,
+ 0, 0, 0, 0, 0, 0, 0,0x2827,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2829,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x282D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2831,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2823, 0,0x282B, 0,0x282F, 0,
+0x2833, 0,0x2835, 0,0x2836, 0,0x2837, 0,
+0x2838};
+
+/* page 1 0x02C7-0x0451 */
+static uint16 tab_uni_gb23121[]={
+0x2126, 0,0x2125, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,
+0x2627,0x2628,0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,
+0x262F,0x2630,0x2631, 0,0x2632,0x2633,0x2634,0x2635,
+0x2636,0x2637,0x2638, 0, 0, 0, 0, 0,
+ 0, 0,0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,
+0x2647,0x2648,0x2649,0x264A,0x264B,0x264C,0x264D,0x264E,
+0x264F,0x2650,0x2651, 0,0x2652,0x2653,0x2654,0x2655,
+0x2656,0x2657,0x2658, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2727, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2721,0x2722,0x2723,0x2724,0x2725,0x2726,0x2728,
+0x2729,0x272A,0x272B,0x272C,0x272D,0x272E,0x272F,0x2730,
+0x2731,0x2732,0x2733,0x2734,0x2735,0x2736,0x2737,0x2738,
+0x2739,0x273A,0x273B,0x273C,0x273D,0x273E,0x273F,0x2740,
+0x2741,0x2751,0x2752,0x2753,0x2754,0x2755,0x2756,0x2758,
+0x2759,0x275A,0x275B,0x275C,0x275D,0x275E,0x275F,0x2760,
+0x2761,0x2762,0x2763,0x2764,0x2765,0x2766,0x2767,0x2768,
+0x2769,0x276A,0x276B,0x276C,0x276D,0x276E,0x276F,0x2770,
+0x2771, 0,0x2757};
+
+/* page 2 0x2015-0x2312 */
+static uint16 tab_uni_gb23122[]={
+0x212A,0x212C, 0,0x212E,0x212F, 0, 0,0x2130,
+0x2131, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x212D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x216B, 0,0x2164,0x2165, 0,
+ 0, 0, 0, 0, 0, 0,0x2179, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2166, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x216D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2271,0x2272,0x2273,0x2274,0x2275,
+0x2276,0x2277,0x2278,0x2279,0x227A,0x227B,0x227C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x217B,0x217C,0x217A,0x217D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x214A, 0, 0, 0, 0,
+ 0, 0,0x2147, 0,0x2146, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x214C, 0, 0,
+0x2158,0x215E, 0,0x214F, 0, 0, 0, 0,
+0x214E, 0,0x2144,0x2145,0x2149,0x2148,0x2152, 0,
+ 0,0x2153, 0, 0, 0, 0, 0,0x2160,
+0x215F,0x2143,0x214B, 0, 0, 0, 0, 0,
+0x2157, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2156, 0, 0, 0,0x2155,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2159,0x2154, 0, 0,0x215C,
+0x215D, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x215A,0x215B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2151, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x214D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x2150};
+
+/* page 3 0x2460-0x2642 */
+static uint16 tab_uni_gb23123[]={
+0x2259,0x225A,0x225B,0x225C,0x225D,0x225E,0x225F,0x2260,
+0x2261,0x2262, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2245,0x2246,0x2247,0x2248,
+0x2249,0x224A,0x224B,0x224C,0x224D,0x224E,0x224F,0x2250,
+0x2251,0x2252,0x2253,0x2254,0x2255,0x2256,0x2257,0x2258,
+0x2231,0x2232,0x2233,0x2234,0x2235,0x2236,0x2237,0x2238,
+0x2239,0x223A,0x223B,0x223C,0x223D,0x223E,0x223F,0x2240,
+0x2241,0x2242,0x2243,0x2244, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2924,0x2925,0x2926,0x2927,0x2928,0x2929,0x292A,0x292B,
+0x292C,0x292D,0x292E,0x292F,0x2930,0x2931,0x2932,0x2933,
+0x2934,0x2935,0x2936,0x2937,0x2938,0x2939,0x293A,0x293B,
+0x293C,0x293D,0x293E,0x293F,0x2940,0x2941,0x2942,0x2943,
+0x2944,0x2945,0x2946,0x2947,0x2948,0x2949,0x294A,0x294B,
+0x294C,0x294D,0x294E,0x294F,0x2950,0x2951,0x2952,0x2953,
+0x2954,0x2955,0x2956,0x2957,0x2958,0x2959,0x295A,0x295B,
+0x295C,0x295D,0x295E,0x295F,0x2960,0x2961,0x2962,0x2963,
+0x2964,0x2965,0x2966,0x2967,0x2968,0x2969,0x296A,0x296B,
+0x296C,0x296D,0x296E,0x296F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2176,0x2175, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2178,0x2177, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2174,0x2173,
+ 0, 0, 0,0x2170, 0, 0,0x2172,0x2171,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x216F,0x216E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2162, 0,0x2161};
+
+/* page 4 0x3000-0x3129 */
+static uint16 tab_uni_gb23124[]={
+0x2121,0x2122,0x2123,0x2128, 0,0x2129, 0, 0,
+0x2134,0x2135,0x2136,0x2137,0x2138,0x2139,0x213A,0x213B,
+0x213E,0x213F, 0,0x217E,0x2132,0x2133,0x213C,0x213D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,
+0x2428,0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,
+0x2430,0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,
+0x2438,0x2439,0x243A,0x243B,0x243C,0x243D,0x243E,0x243F,
+0x2440,0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447,
+0x2448,0x2449,0x244A,0x244B,0x244C,0x244D,0x244E,0x244F,
+0x2450,0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457,
+0x2458,0x2459,0x245A,0x245B,0x245C,0x245D,0x245E,0x245F,
+0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
+0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
+0x2470,0x2471,0x2472,0x2473, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527,
+0x2528,0x2529,0x252A,0x252B,0x252C,0x252D,0x252E,0x252F,
+0x2530,0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537,
+0x2538,0x2539,0x253A,0x253B,0x253C,0x253D,0x253E,0x253F,
+0x2540,0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547,
+0x2548,0x2549,0x254A,0x254B,0x254C,0x254D,0x254E,0x254F,
+0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,
+0x2558,0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,0x255F,
+0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,
+0x2568,0x2569,0x256A,0x256B,0x256C,0x256D,0x256E,0x256F,
+0x2570,0x2571,0x2572,0x2573,0x2574,0x2575,0x2576, 0,
+ 0, 0, 0,0x2124, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x2845,0x2846,0x2847,
+0x2848,0x2849,0x284A,0x284B,0x284C,0x284D,0x284E,0x284F,
+0x2850,0x2851,0x2852,0x2853,0x2854,0x2855,0x2856,0x2857,
+0x2858,0x2859,0x285A,0x285B,0x285C,0x285D,0x285E,0x285F,
+0x2860,0x2861,0x2862,0x2863,0x2864,0x2865,0x2866,0x2867,
+0x2868,0x2869};
+
+/* page 5 0x3220-0x3229 */
+static uint16 tab_uni_gb23125[]={
+0x2265,0x2266,0x2267,0x2268,0x2269,0x226A,0x226B,0x226C,
+0x226D,0x226E};
+
+/* page 6 0x4E00-0x9B54 */
+static uint16 tab_uni_gb23126[]={
+0x523B,0x3621, 0,0x465F, 0, 0, 0,0x4D72,
+0x5549,0x487D,0x494F,0x4F42,0x5822,0x323B,0x536B, 0,
+0x5824,0x3373, 0,0x5728,0x4752,0x5827,0x4A40, 0,
+0x4770,0x317B,0x5235,0x3454,0x362B,0x4B3F,0x5829, 0,
+ 0, 0,0x362A, 0,0x413D,0x514F, 0,0x4925,
+0x582D, 0,0x3876,0x513E,0x635C,0x5650, 0, 0,
+0x3761, 0,0x342E, 0,0x4159, 0,0x583C, 0,
+0x4D68,0x3524,0x4E2A,0x5677, 0,0x4076,0x3E59,0x582F,
+ 0, 0, 0,0x444B, 0,0x3E43, 0,0x5831,
+0x4334,0x5265, 0,0x562E,0x4E5A,0x5527,0x3A75,0x3726,
+0x4056, 0,0x4639,0x4552,0x4747, 0,0x3954, 0,
+0x334B,0x5252, 0, 0,0x583F,0x3E45,0x4672,0x5232,
+0x4F30,0x4F67, 0, 0, 0, 0,0x4A69, 0,
+ 0,0x5840, 0, 0, 0, 0, 0, 0,
+0x4272,0x4252, 0,0x4869, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x472C, 0,
+ 0, 0, 0, 0, 0, 0,0x414B, 0,
+0x5368,0x5579, 0,0x4A42,0x367E,0x5821,0x535A,0x3F77,
+ 0,0x5446,0x3B25,0x5841,0x4E65,0x3E2E, 0, 0,
+0x5828, 0,0x5147,0x5029, 0, 0, 0,0x583D,
+0x596F,0x4D76,0x3F3A, 0,0x3D3B,0x3A25,0x5260,0x327A,
+0x3A60,0x4436, 0,0x4F6D,0x3E29,0x4D24,0x4141, 0,
+ 0, 0,0x4757,0x5971, 0,0x5974, 0, 0,
+ 0, 0,0x484B,0x5869, 0, 0, 0,0x525A,
+0x4A32,0x484A,0x586C,0x586A,0x5846,0x3D76,0x464D,0x3370,
+ 0,0x586B,0x3D71,0x3D69, 0,0x4854,0x3453, 0,
+ 0,0x4258, 0,0x3256,0x5750,0x4A4B,0x4B7B,0x554C,
+0x3836,0x4F49, 0, 0, 0,0x595A,0x5870,0x472A,
+ 0,0x586E, 0,0x347A,0x416E,0x5254, 0, 0,
+0x586D, 0,0x5247,0x586F,0x4347, 0, 0, 0,
+0x5176, 0,0x5659,0x5872, 0,0x5875,0x3C7E,0x3C5B,
+ 0, 0, 0,0x484E, 0,0x375D, 0,0x3742,
+ 0,0x4673, 0, 0, 0, 0, 0, 0,
+ 0,0x5878,0x5241, 0, 0,0x4E69,0x3C3F,0x377C,
+0x3725,0x505D, 0, 0, 0, 0, 0,0x565A,
+0x5345,0x3B6F,0x3B61,0x5871, 0, 0,0x4921,0x4E30,
+0x342B, 0,0x5873, 0,0x494B,0x5876,0x4257,0x5877,
+ 0, 0,0x4E31,0x5879, 0, 0, 0,0x322E,
+0x3940, 0,0x5923, 0,0x3069, 0,0x4166, 0,
+0x496C, 0,0x4B45, 0,0x4B46,0x5924, 0, 0,
+ 0, 0, 0,0x3568, 0, 0,0x352B, 0,
+ 0, 0, 0, 0, 0,0x4E3B,0x354D,0x5721,
+0x5774,0x5353, 0,0x4C65, 0,0x3A4E, 0,0x5922,
+0x595C,0x5360,0x587D,0x3770,0x5777,0x587E,0x587A,0x5921,
+0x4463, 0, 0,0x5336,0x5874,0x595D, 0,0x587B,
+ 0,0x4565, 0, 0,0x4050, 0, 0,0x5170,
+0x305B, 0, 0,0x3C51,0x5926, 0,0x5925, 0,
+ 0, 0, 0,0x592C,0x592E, 0,0x592B,0x4A39,
+ 0, 0, 0,0x5929,0x5636, 0, 0, 0,
+0x335E,0x5928, 0,0x407D, 0,0x4A4C, 0,0x592A,
+ 0,0x5927, 0, 0,0x5930, 0, 0,0x3631,
+ 0, 0, 0,0x3929, 0,0x5240, 0, 0,
+0x4F40, 0, 0,0x4242, 0,0x3D44,0x556C,0x3260,
+0x4748,0x3F6B,0x592D, 0,0x592F, 0,0x4E6A,0x3A6E,
+ 0, 0, 0, 0, 0,0x4756, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3163,
+ 0, 0, 0,0x3459,0x366D,0x5934, 0, 0,
+ 0, 0,0x3F21, 0, 0, 0,0x595E,0x474E,
+0x407E,0x5938, 0, 0, 0, 0, 0,0x4B57,
+0x377D, 0,0x5935, 0,0x5937,0x3123,0x5361,0x5939,
+ 0,0x5045, 0,0x5936, 0, 0,0x5931, 0,
+0x5932,0x4129,0x5933, 0, 0,0x3C73,0x505E,0x3829,
+ 0,0x3E63, 0,0x593D, 0, 0, 0, 0,
+0x593A, 0,0x3033, 0, 0, 0,0x5942, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5944,0x3136, 0,0x593F,
+ 0, 0,0x3539, 0,0x3E73, 0, 0, 0,
+0x4C48,0x3A72,0x5250, 0,0x5943, 0, 0,0x3D68,
+ 0,0x332B, 0, 0, 0,0x5945,0x3E6B, 0,
+0x5946,0x593B,0x445F, 0,0x593E,0x5941,0x5940, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x552E, 0,0x5635, 0,0x4763, 0,
+ 0, 0, 0,0x5948, 0, 0, 0,0x3C59,
+0x594A, 0, 0, 0,0x593C, 0,0x594B,0x462B,
+ 0, 0, 0, 0, 0,0x5949, 0, 0,
+ 0, 0,0x5776, 0,0x4D23, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3D21, 0, 0,
+ 0, 0, 0, 0,0x594C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x453C,0x4D35,
+ 0, 0, 0,0x594D, 0, 0,0x5947,0x3325,
+0x3F7E, 0, 0, 0, 0,0x3835, 0, 0,
+0x407C, 0, 0, 0, 0,0x3078, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3476, 0,0x594E, 0,0x594F,
+0x3422,0x5950, 0, 0,0x345F, 0, 0, 0,
+ 0, 0,0x3041, 0, 0, 0, 0, 0,
+ 0, 0,0x5951,0x4935, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4F71,
+ 0, 0, 0, 0, 0, 0,0x5952, 0,
+ 0, 0,0x4145, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5956,0x492E,
+ 0, 0, 0, 0,0x5955,0x5954,0x5957, 0,
+ 0, 0, 0,0x4B5B, 0,0x3D29, 0, 0,
+ 0, 0, 0,0x4627, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5953,0x5958,
+ 0, 0, 0,0x5959, 0, 0, 0, 0,
+ 0, 0,0x4865, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x405C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3679,
+0x5823,0x544A, 0,0x542A,0x5056,0x3364,0x5557, 0,
+0x4F48,0x3962, 0,0x3F4B, 0,0x4362, 0, 0,
+ 0,0x3652, 0, 0,0x4D43,0x596E,0x5970, 0,
+ 0, 0,0x3533, 0,0x3635, 0, 0, 0,
+ 0, 0,0x3E24, 0, 0,0x486B, 0, 0,
+0x482B, 0, 0,0x304B,0x392B,0x4179,0x5962, 0,
+0x403C,0x3932, 0,0x3958,0x504B,0x3178,0x4664,0x3E5F,
+0x3564,0x5748, 0,0x5178,0x3C66,0x4A5E, 0, 0,
+0x3C3D,0x5966,0x5867, 0, 0,0x445A, 0, 0,
+0x3854,0x483D, 0, 0,0x3261,0x5459, 0, 0,
+ 0, 0,0x4330, 0, 0,0x4361,0x5A22,0x485F,
+ 0,0x5034, 0,0x3E7C,0x4529, 0, 0, 0,
+0x395A, 0,0x5A23, 0,0x5429,0x5A24, 0, 0,
+ 0, 0, 0,0x597B,0x362C, 0, 0,0x376B,
+0x3179,0x597C,0x3365,0x3E76, 0,0x3F76,0x5231,0x4064,
+ 0, 0, 0,0x3633,0x597E,0x597D, 0, 0,
+0x3E3B, 0, 0, 0,0x4660, 0,0x573C,0x5A21,
+ 0,0x4139, 0,0x3572,0x4168, 0, 0,0x3C75,
+ 0,0x3455, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x415D, 0,0x447D, 0, 0,
+0x3C38,0x3732, 0, 0,0x376F, 0, 0, 0,
+ 0, 0, 0,0x596C, 0,0x463E, 0,0x3F2D,
+0x3B4B, 0, 0,0x354A, 0,0x5B49,0x5057, 0,
+0x4D39,0x303C,0x3376,0x3B77,0x5B4A,0x3A2F, 0,0x5464,
+0x3536,0x3573,0x5856,0x4850, 0, 0,0x3756,0x4750,
+0x5857, 0,0x3F2F, 0, 0,0x5B3B,0x5858, 0,
+ 0,0x504C,0x3B2E, 0, 0, 0,0x6B3E,0x4150,
+0x4175,0x5472,0x3855,0x3434, 0,0x3375, 0, 0,
+0x493E, 0, 0, 0,0x4550, 0, 0, 0,
+0x4559,0x407B, 0,0x3170, 0,0x5859,0x394E, 0,
+0x353D, 0, 0,0x585A, 0, 0,0x5646,0x4B22,
+0x482F,0x4932,0x344C,0x3F4C, 0,0x3974, 0,0x585B,
+0x585C,0x3667,0x3C41,0x4C6A, 0, 0, 0, 0,
+ 0, 0,0x4F77, 0,0x585D,0x4730, 0, 0,
+0x3950,0x3D23, 0, 0,0x4C5E, 0,0x464A, 0,
+ 0, 0, 0, 0,0x5860, 0,0x585E, 0,
+ 0,0x585F, 0, 0, 0,0x307E, 0,0x3E67,
+ 0,0x4A23,0x3C74, 0, 0, 0, 0,0x3831,
+ 0, 0,0x386E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5862, 0,0x3D4B,
+ 0,0x5864,0x5863, 0, 0, 0, 0, 0,
+0x457C, 0, 0, 0, 0, 0, 0, 0,
+0x5865, 0, 0,0x5866, 0, 0, 0, 0,
+ 0, 0, 0,0x4126, 0,0x4830,0x306C,0x3926,
+0x3C53,0x4E71,0x5B3D,0x4153, 0, 0, 0, 0,
+0x362F,0x567A,0x452C,0x3D59,0x5B3E,0x5B3F, 0, 0,
+ 0,0x4078,0x3E22,0x404D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5B40,0x4A46,
+ 0, 0, 0,0x322A, 0, 0, 0,0x5342,
+ 0,0x4363, 0,0x512B, 0, 0, 0, 0,
+0x5B42, 0,0x4055, 0, 0, 0,0x5B43, 0,
+0x3F31, 0, 0, 0, 0, 0, 0,0x443C,
+ 0, 0, 0, 0,0x475A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5B44, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5968,0x4957, 0, 0, 0,0x3934,0x4E70,
+0x5448, 0, 0, 0, 0,0x307C,0x3452, 0,
+0x5059, 0, 0, 0, 0,0x5969, 0,0x5E4B,
+0x596B, 0, 0, 0, 0,0x5830,0x3B2F,0x3131,
+ 0,0x3357,0x584E, 0, 0,0x5451, 0, 0,
+0x3D33,0x3F6F, 0,0x4F3B, 0, 0,0x5850, 0,
+ 0, 0,0x374B, 0, 0, 0,0x5851, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4625,0x4778,0x523D, 0, 0,0x5852,0x4464,
+ 0,0x4A2E, 0,0x4727, 0,0x5826, 0,0x497D,
+0x4E67,0x3B5C,0x306B, 0, 0, 0,0x3B2A,0x502D,
+ 0,0x3130,0x5764,0x573F, 0,0x3525,0x4274,0x444F,
+ 0, 0,0x3229, 0,0x3237, 0,0x3165,0x5F32,
+0x553C,0x3F28,0x422C,0x5855,0x4231, 0,0x5854,0x4E54,
+ 0,0x5A60, 0,0x4E40, 0, 0,0x5834,0x432E,
+0x5321,0x4E23, 0,0x3C34,0x4834,0x4251, 0,0x3E6D,
+0x5036, 0,0x5A61, 0, 0, 0, 0,0x4764,
+ 0, 0,0x3327, 0,0x3672,0x4C7C,0x407A, 0,
+ 0,0x4077, 0,0x5139,0x5161,0x5847, 0, 0,
+ 0, 0, 0, 0, 0,0x325E, 0, 0,
+0x4065, 0,0x3A71, 0, 0,0x5848, 0,0x542D,
+ 0, 0,0x4F61,0x5849, 0,0x584A,0x4F43, 0,
+0x3378,0x3E47, 0, 0, 0, 0,0x584B, 0,
+ 0, 0, 0, 0, 0, 0,0x5B4C, 0,
+ 0, 0, 0,0x4825, 0, 0, 0,0x4F58,
+ 0,0x487E,0x324E, 0, 0, 0, 0, 0,
+0x5356,0x3266,0x3C30,0x5351,0x4B2B,0x3734, 0, 0,
+ 0,0x3722, 0, 0,0x4A65, 0,0x4821,0x4A5C,
+0x3164,0x5070, 0,0x4551, 0, 0, 0,0x5B45,
+0x357E, 0, 0,0x3F5A,0x3945,0x3E64,0x416D, 0,
+0x5F36,0x5F35,0x563B,0x3D50,0x5559,0x3048,0x3623,0x3F49,
+0x4C28,0x5F33,0x4A37,0x5352, 0,0x584F,0x5236,0x3A45,
+0x4B3E,0x4C3E, 0,0x5F37,0x3570,0x5F34, 0, 0,
+ 0,0x5375, 0,0x3354,0x3877, 0,0x5F3A, 0,
+0x3A4F,0x3C2A,0x3575, 0,0x4D2C,0x437B,0x3A73,0x4074,
+0x4D42,0x4F72,0x5F38,0x4F45, 0,0x4240,0x5F39,0x4270,
+ 0, 0, 0,0x3E7D, 0,0x415F,0x4D4C,0x5277,
+0x374D,0x5F41, 0,0x5F44, 0, 0,0x3771,0x3049,
+0x3656,0x3754, 0,0x3A2C,0x4C7D,0x3F54,0x4B31,0x4674,
+ 0,0x5628,0x5F45, 0,0x4E62,0x3333, 0, 0,
+0x4E7C,0x3435, 0,0x4E47,0x3A70, 0,0x4E61, 0,
+0x513D, 0, 0,0x5F40, 0, 0,0x3474, 0,
+0x334A, 0,0x3866,0x5F3B, 0, 0, 0, 0,
+0x4445, 0,0x5F3C,0x5F3D,0x5F3E,0x453B,0x5F3F,0x5F42,
+0x5431,0x5F43, 0,0x473A,0x4E58, 0, 0, 0,
+ 0, 0,0x4458, 0,0x5F4A, 0,0x5F4F, 0,
+0x565C, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F49,0x5F5A,0x4E36, 0,0x3A47,0x5F4E,0x5F48,
+0x455E, 0, 0,0x496B,0x3A74,0x437C, 0, 0,
+0x3E57, 0,0x5F46, 0,0x5F4D, 0,0x4558, 0,
+ 0, 0, 0,0x5526,0x3A4D, 0,0x3E4C,0x533D,
+0x3840, 0,0x5664, 0,0x5F47,0x393E,0x3F27, 0,
+ 0,0x417C,0x5F4B,0x5F4C, 0,0x5F50, 0, 0,
+ 0, 0, 0,0x5F5B,0x5F65, 0,0x5F57,0x5F56,
+0x5749,0x5F63,0x5F64,0x656B,0x5227,0x5F52, 0,0x3F29,
+ 0,0x545B, 0,0x3F48,0x5F54, 0, 0, 0,
+0x4F4C, 0, 0,0x5F5D, 0,0x514A, 0,0x5F5E,
+0x3027,0x4637,0x5F53, 0,0x3A65, 0,0x365F,0x4D5B,
+0x397E,0x5455, 0, 0,0x5F5F,0x4F6C,0x3025,0x5F67,
+0x5F51,0x5146,0x5F55,0x5F58,0x5F59,0x5F5C, 0,0x3B29,
+ 0,0x5F60,0x5F61, 0,0x5F62,0x5F66,0x5F68,0x5334,
+ 0, 0, 0, 0, 0,0x3867,0x4536,0x5F6A,
+0x495A,0x4128,0x4444, 0, 0,0x3F5E,0x4F78, 0,
+ 0, 0,0x555C,0x5F6E, 0, 0, 0, 0,
+ 0, 0,0x3238, 0,0x3A5F,0x5F6C, 0,0x5B41,
+ 0,0x5164, 0, 0, 0, 0,0x4B74,0x343D,
+ 0,0x3026, 0, 0, 0, 0, 0,0x5F71,
+0x4C46,0x5F72, 0, 0,0x5F6D, 0, 0, 0,
+ 0, 0, 0,0x5F69, 0, 0, 0, 0,
+0x5F6B, 0,0x5F6F,0x5F70,0x3B3D, 0, 0,0x5F73,
+ 0, 0,0x5F74, 0,0x3B23, 0,0x4A5B,0x4E28,
+0x6027,0x332A, 0,0x6026, 0, 0, 0,0x6021,
+ 0, 0, 0, 0,0x5F7E, 0,0x4D59,0x5F7C,
+ 0,0x5F7A, 0,0x3F50,0x5744, 0,0x494C, 0,
+ 0,0x5F78,0x3021, 0, 0, 0, 0, 0,
+0x5F7D, 0, 0, 0, 0,0x5F7B,0x6022, 0,
+ 0, 0, 0, 0,0x6028, 0, 0, 0,
+ 0,0x3748, 0, 0,0x4621,0x4936,0x4032,0x5F75,
+ 0, 0,0x453E, 0,0x5844,0x5F79,0x4476, 0,
+ 0, 0, 0, 0, 0,0x6023,0x6024,0x6025,
+0x5025, 0, 0,0x6034,0x4C64, 0,0x6031, 0,
+0x3F26,0x602F,0x4E39,0x602B,0x4946, 0, 0,0x402E,
+0x602E,0x3A6D,0x3A30,0x6029, 0, 0, 0,0x5F76,
+ 0,0x6033, 0, 0,0x6038, 0, 0, 0,
+0x342D,0x6039, 0, 0,0x4F32,0x3A48, 0,0x6030,
+ 0, 0, 0, 0, 0, 0, 0,0x507A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x602C, 0,0x547B, 0,0x5F77, 0,0x4567,
+ 0,0x602D, 0,0x5377, 0,0x6036,0x6037, 0,
+ 0, 0, 0, 0,0x6044,0x5061, 0, 0,
+ 0,0x603C, 0, 0,0x6049,0x604A, 0, 0,
+ 0,0x603E,0x602A,0x4924,0x6041, 0,0x6032, 0,
+ 0, 0, 0, 0,0x4A48,0x6043, 0,0x6035,
+ 0,0x4E4B, 0,0x4B43,0x604D,0x6046,0x6042, 0,
+0x604B, 0,0x603A,0x603F,0x6040, 0, 0,0x6045,
+ 0, 0,0x6047,0x6048, 0,0x604C, 0,0x603B,
+ 0, 0, 0, 0, 0,0x4B54,0x6055, 0,
+0x6056,0x6052, 0, 0, 0, 0, 0, 0,
+0x6050,0x3C4E, 0, 0,0x6051, 0,0x3842,0x5845,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x506A, 0, 0,0x426F, 0, 0,0x604F,0x603D,
+ 0, 0, 0,0x6054,0x6053, 0, 0,0x6057,
+ 0, 0, 0, 0,0x605C,0x6058, 0, 0,
+ 0,0x5676,0x3330, 0,0x576C, 0,0x4B3B, 0,
+ 0,0x605A, 0,0x4E7B, 0, 0, 0,0x3A59,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6061,0x605D,0x522D, 0,
+ 0, 0, 0, 0,0x6062, 0, 0,0x605B,
+0x6059,0x605F, 0, 0,0x6060, 0, 0, 0,
+ 0, 0,0x605E, 0,0x6064, 0, 0, 0,
+0x4677,0x582C,0x546B,0x6066,0x4A49, 0, 0, 0,
+ 0,0x6065, 0, 0, 0, 0,0x3841, 0,
+ 0, 0, 0,0x6067,0x6068, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6069,0x6063, 0,
+ 0, 0, 0, 0, 0, 0,0x3A3F,0x4C67,
+ 0, 0, 0,0x606A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4F79, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x606B,
+ 0, 0, 0, 0, 0, 0, 0,0x4842,
+ 0, 0, 0, 0,0x3D40, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4452, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x606C, 0, 0,0x606D,
+ 0, 0,0x4774,0x4B44, 0,0x606E,0x3B58,0x5836,
+0x5272,0x606F,0x4D45, 0,0x365A, 0, 0, 0,
+ 0, 0, 0,0x6071, 0,0x5430, 0, 0,
+0x4027,0x3451, 0, 0,0x4E27,0x6070, 0, 0,
+ 0,0x6072,0x394C, 0, 0,0x397A,0x4D3C,0x6073,
+ 0, 0, 0,0x4654,0x6074, 0,0x5432, 0,
+0x4826,0x6076,0x6075, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6077, 0, 0,0x4D41,
+ 0, 0, 0,0x4A25, 0, 0, 0, 0,
+0x545A,0x5B57,0x5B59, 0,0x5B58,0x3967,0x5B5C,0x5B5D,
+0x3558, 0, 0,0x5B5A, 0, 0, 0, 0,
+ 0,0x5B5B,0x3321,0x5B5F, 0, 0,0x3B78, 0,
+0x5637, 0,0x5B60, 0, 0, 0, 0,0x3E79,
+ 0, 0,0x373B, 0,0x5B50,0x4C2E,0x3F32,0x3B35,
+0x5778,0x3F53, 0, 0, 0, 0, 0,0x3F69,
+ 0, 0,0x3C61,0x4C33,0x5B5E,0x3053,0x4E6B,0x3758,
+0x5739,0x4642, 0, 0,0x4024, 0,0x4C39, 0,
+0x5B67,0x5B61,0x463A,0x5B63, 0,0x5B68, 0,0x4577,
+ 0, 0, 0,0x5B6A, 0, 0,0x5B69,0x3F40,
+ 0, 0, 0,0x5B66,0x5B65, 0, 0, 0,
+ 0, 0,0x3439,0x402C,0x4222,0x5B62,0x5B64, 0,
+ 0, 0, 0,0x504D,0x5B6D, 0, 0, 0,
+ 0, 0,0x405D,0x5B72, 0, 0, 0, 0,
+ 0, 0, 0,0x3662, 0, 0, 0, 0,
+0x5B73,0x5B52,0x3938,0x542B,0x5B6C, 0,0x3F51,0x5B70,
+ 0,0x5B51, 0,0x3566, 0,0x5B6B,0x3F65, 0,
+ 0, 0,0x5B6E, 0,0x5B71, 0, 0, 0,
+0x5B79, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3921,0x3023, 0, 0, 0, 0,
+ 0, 0, 0,0x4271, 0, 0,0x3347,0x5B6F,
+ 0, 0,0x5B78, 0,0x4652,0x5B74, 0, 0,
+0x5B75,0x5B77,0x5B76, 0, 0,0x5B7E, 0,0x5372,
+0x323A, 0, 0, 0,0x5B7D, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5C24, 0,0x5B7B,
+ 0, 0, 0, 0,0x5B7A, 0, 0, 0,
+0x5B7C,0x4560,0x3B79, 0, 0,0x5C23, 0, 0,
+0x5C25, 0,0x4C43, 0, 0, 0,0x3651,0x5D40,
+ 0, 0, 0,0x5C21, 0,0x5C22, 0, 0,
+ 0,0x4735, 0, 0, 0,0x3669, 0, 0,
+ 0,0x5C27, 0, 0, 0, 0,0x5C26, 0,
+0x5C29,0x3124, 0, 0,0x354C, 0, 0, 0,
+ 0, 0,0x3F30, 0, 0, 0, 0, 0,
+0x515F, 0, 0, 0, 0,0x3642, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5C28, 0, 0, 0,
+ 0, 0, 0, 0,0x4B7A,0x6B73, 0, 0,
+ 0,0x4B5C, 0, 0,0x4B7E, 0, 0, 0,
+0x4C41, 0, 0, 0, 0, 0,0x487B, 0,
+ 0, 0, 0, 0, 0,0x5C2A, 0, 0,
+ 0, 0, 0,0x4C6E,0x5C2B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5B53, 0,
+0x5C2F,0x5C2C, 0,0x3E33, 0,0x4A7B, 0, 0,
+ 0,0x5C2D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x494A,0x4439, 0, 0, 0, 0,
+ 0,0x473D,0x5C2E, 0, 0, 0,0x5476,0x5066,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x442B,0x3655, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5B54, 0, 0, 0,
+ 0,0x315A, 0, 0, 0,0x5B55, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B56, 0, 0, 0,0x3A3E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4840, 0, 0, 0,
+ 0, 0, 0,0x4A3F,0x4849, 0,0x5733, 0,
+0x4979, 0, 0,0x3F47, 0, 0,0x3A78, 0,
+ 0,0x523C, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x623A, 0,0x3426, 0, 0,0x3138,
+ 0, 0, 0, 0, 0,0x3834, 0,0x4F44,
+ 0, 0, 0, 0,0x5967,0x4F26,0x4D62, 0,
+ 0,0x596D,0x3660, 0,0x5239, 0, 0,0x393B,
+ 0, 0, 0, 0,0x6239,0x6237, 0,0x3473,
+ 0,0x4C6C,0x4C2B,0x3772, 0,0x5832,0x516B,0x3A3B,
+ 0,0x4A27, 0, 0,0x4D37, 0, 0,0x5244,
+0x3F64,0x3C50,0x3661, 0,0x5E45, 0, 0, 0,
+ 0,0x5E46,0x5B3C, 0,0x5159, 0, 0,0x4666,
+0x444E,0x376E, 0,0x375C, 0, 0,0x3F7C,0x5760,
+ 0,0x4675, 0, 0,0x313C,0x5E48,0x3D31,0x4C57,
+0x5E4A, 0,0x5E49, 0, 0, 0, 0, 0,
+0x356C, 0,0x495D, 0, 0,0x3042, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x452E,0x452B, 0,0x444C, 0,
+0x3C69,0x4B7D, 0, 0, 0,0x3A43, 0, 0,
+ 0,0x6579,0x4867,0x657A,0x4D7D, 0,0x5731,0x383E,
+0x4268, 0,0x4851, 0, 0,0x657B, 0, 0,
+ 0, 0,0x364A,0x3C4B, 0, 0,0x517D,0x6621,
+ 0,0x436E, 0, 0, 0, 0,0x6624, 0,
+ 0, 0, 0,0x657E,0x6625,0x4D57, 0, 0,
+0x3741,0x657C,0x657D,0x6623, 0, 0,0x445D,0x6628,
+ 0, 0,0x6627, 0, 0, 0, 0, 0,
+ 0,0x4343, 0,0x465E, 0, 0,0x662A, 0,
+ 0, 0, 0, 0, 0, 0,0x4437, 0,
+ 0, 0,0x6622,0x4A3C, 0, 0, 0, 0,
+0x3D63,0x3943,0x6626,0x5055,0x4E2F, 0, 0,0x6629,
+0x6630, 0,0x5226, 0,0x3D2A,0x662D, 0, 0,
+ 0, 0, 0,0x662F, 0,0x4051, 0, 0,
+0x524C, 0, 0, 0,0x3C27, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6631, 0,0x5276, 0, 0, 0,0x574B,
+ 0,0x4D7E, 0,0x4D5E,0x4226,0x662B,0x662C,0x3D3F,
+0x662E,0x6633, 0, 0,0x6632, 0, 0, 0,
+ 0,0x6636, 0,0x6638, 0, 0, 0, 0,
+0x446F, 0, 0, 0,0x4448, 0, 0,0x3E6A,
+0x496F, 0, 0,0x6637, 0,0x3670, 0, 0,
+ 0,0x4364, 0, 0, 0, 0, 0, 0,
+ 0,0x5369,0x6634, 0,0x6635, 0,0x4822, 0,
+ 0, 0, 0, 0,0x663D, 0, 0, 0,
+0x6639, 0, 0, 0, 0, 0,0x4645, 0,
+ 0,0x4D71,0x663B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x663C, 0, 0,
+ 0, 0,0x3B69, 0, 0, 0, 0, 0,
+ 0, 0,0x663E, 0, 0, 0, 0,0x663A,
+ 0, 0,0x4037, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5324,0x663F,0x4974,0x6643,
+ 0, 0,0x6644, 0, 0, 0, 0,0x5076,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x433D, 0, 0, 0, 0, 0,
+ 0, 0,0x4344,0x6642, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6641, 0, 0, 0, 0, 0,
+ 0, 0,0x6647,0x4F31, 0,0x6B74, 0, 0,
+0x664A, 0, 0, 0, 0, 0,0x6645, 0,
+ 0,0x3C5E,0x4929, 0, 0, 0, 0, 0,
+ 0,0x3C35, 0, 0,0x4F53, 0, 0, 0,
+ 0, 0,0x6648, 0,0x6649, 0,0x664E, 0,
+0x6650, 0, 0, 0,0x6651, 0, 0, 0,
+0x664B,0x3555, 0,0x664C, 0, 0,0x664F, 0,
+ 0,0x445B, 0,0x6646, 0, 0, 0, 0,
+ 0,0x664D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6652, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6654,0x6653,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6655, 0,0x5978, 0, 0,0x6656,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6657, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5753,0x665D, 0,0x665E,0x3F57,0x5450, 0,0x5756,
+0x3466,0x4B6F,0x665A,0x5843,0x574E,0x5022, 0,0x434F,
+ 0, 0,0x665F,0x3C3E,0x3942,0x665B,0x5127, 0,
+ 0,0x3A22,0x424F, 0,0x582B, 0, 0, 0,
+0x4A6B,0x656E, 0,0x665C, 0,0x3775, 0, 0,
+ 0, 0,0x4866, 0, 0,0x4475, 0, 0,
+0x6532,0x447E, 0,0x4B7C,0x6533,0x552C, 0,0x536E,
+0x4A58,0x3032, 0,0x4B4E,0x4D6A, 0, 0,0x3A6A,
+ 0, 0, 0,0x6535, 0,0x6534, 0,0x575A,
+0x3959,0x5666,0x3628,0x4D70,0x524B,0x3126,0x4A35, 0,
+0x3368,0x4973,0x3F4D,0x507B,0x4A52,0x6536,0x3B42, 0,
+ 0, 0,0x4F5C,0x392C, 0, 0, 0, 0,
+0x5457, 0, 0,0x3A26,0x5167,0x4F7C,0x3C52, 0,
+0x6537,0x485D, 0, 0, 0,0x3F6D,0x3176,0x4B5E,
+ 0, 0,0x3C45, 0,0x3C44,0x527A,0x435C,0x3F5C,
+ 0, 0, 0, 0,0x383B, 0, 0, 0,
+0x4342, 0,0x3A2E,0x5422, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x475E,0x442F,0x326C,
+ 0,0x3951, 0, 0,0x653B,0x4148, 0, 0,
+0x552F, 0, 0, 0, 0, 0,0x653C, 0,
+0x653E, 0, 0, 0, 0, 0, 0, 0,
+0x3467,0x3654,0x4B42,0x5130,0x353C, 0, 0,0x4A59,
+ 0,0x3762, 0, 0,0x4964, 0,0x3D2B, 0,
+ 0,0x4E3E,0x5770, 0, 0, 0, 0,0x5021,
+ 0,0x4959, 0, 0,0x367B,0x6658,0x3C62, 0,
+0x333E, 0,0x4950, 0,0x6659,0x3322, 0, 0,
+ 0, 0,0x5E4C, 0,0x5348,0x5E4D, 0,0x5222,
+ 0, 0, 0, 0,0x5E4E, 0, 0, 0,
+ 0,0x3E4D, 0, 0,0x5E4F, 0, 0, 0,
+0x4A2C,0x527C,0x335F,0x656A,0x4461,0x3E21,0x4E32,0x4472,
+0x3E56,0x4628,0x3263, 0, 0,0x3E53, 0, 0,
+0x477C,0x4C6B,0x3D6C,0x4E5D, 0, 0,0x4A3A,0x4641,
+0x656C,0x503C, 0, 0, 0,0x5539, 0, 0,
+ 0,0x656D, 0, 0, 0, 0,0x4A74, 0,
+0x4D40,0x4245, 0,0x656F, 0,0x4244,0x6570, 0,
+ 0, 0, 0, 0, 0, 0,0x6578,0x4D4D,
+ 0,0x493D, 0, 0, 0, 0, 0, 0,
+ 0,0x5259,0x6128, 0, 0, 0, 0,0x536C,
+ 0,0x4B6A,0x4671, 0, 0, 0, 0, 0,
+0x612C, 0, 0, 0,0x6127,0x6129, 0, 0,
+0x612A,0x612F, 0, 0,0x326D, 0,0x612B,0x385A,
+0x612D,0x612E,0x6130,0x353A,0x6131, 0, 0, 0,
+ 0, 0,0x6133,0x6138, 0, 0, 0, 0,
+ 0,0x5152, 0,0x6136,0x6135,0x416B, 0, 0,
+ 0,0x6137, 0,0x5440, 0,0x6132, 0,0x613A,
+0x3036, 0, 0, 0, 0,0x6134, 0,0x3F79,
+ 0,0x6139, 0, 0,0x613B, 0, 0, 0,
+ 0, 0, 0,0x613E, 0, 0, 0, 0,
+ 0, 0,0x613C, 0, 0, 0, 0, 0,
+ 0,0x5645, 0, 0, 0, 0, 0, 0,
+ 0,0x4F3F, 0, 0,0x613D,0x613F,0x424D, 0,
+0x366B, 0,0x5378, 0, 0,0x474D, 0, 0,
+0x3765, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3E7E, 0, 0, 0, 0,
+ 0, 0,0x6140,0x6141, 0, 0,0x6147,0x3367,
+ 0, 0, 0, 0, 0, 0,0x4669, 0,
+ 0, 0, 0, 0,0x345E, 0,0x5142, 0,
+ 0, 0, 0,0x6148, 0, 0,0x6146, 0,
+ 0, 0, 0, 0,0x6145, 0,0x6143,0x6142,
+ 0,0x3140, 0, 0, 0,0x5538,0x6144, 0,
+ 0, 0, 0, 0,0x614B, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x614C,0x614A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6F7A,
+ 0, 0,0x6153,0x6152,0x4736, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6149, 0, 0,0x614E, 0,0x6150, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6154, 0,0x6151,0x614D, 0, 0,0x614F,
+ 0, 0, 0, 0,0x6155, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6156, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6157, 0, 0, 0,0x6158, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x615A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x615B, 0, 0,
+ 0, 0, 0, 0, 0,0x4E21, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x675D, 0,0x3428,0x565D, 0,
+ 0,0x5132,0x3332, 0, 0,0x3924,0x5773,0x4749,
+0x3E5E,0x392E, 0,0x4E57, 0, 0,0x326E,0x5B4F,
+ 0,0x3C3A,0x5251,0x4B48,0x304D, 0, 0,0x4F6F,
+ 0, 0, 0, 0, 0,0x5963,0x3D6D, 0,
+ 0,0x3152,0x4A50,0x323C, 0,0x4B27,0x372B, 0,
+0x4A26, 0, 0, 0,0x4F23, 0, 0,0x6078,
+0x554A,0x607B, 0, 0,0x607A,0x4541,0x4C7B, 0,
+0x4131,0x6079,0x5663,0x322F,0x5644,0x355B, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3478,0x5621,
+ 0, 0, 0, 0, 0,0x4F2F,0x306F, 0,
+ 0,0x607C, 0, 0, 0, 0, 0,0x6121,
+0x3323, 0, 0,0x607D,0x607E,0x4331, 0, 0,
+ 0, 0,0x435D, 0,0x6122,0x3779, 0, 0,
+ 0, 0, 0, 0,0x3B4F, 0, 0, 0,
+ 0, 0, 0, 0,0x6123,0x443B, 0, 0,
+ 0, 0, 0,0x6124, 0, 0,0x6125, 0,
+ 0,0x6126,0x3431, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3849,0x463D,0x446A, 0,0x3222, 0,
+0x5052, 0,0x675B,0x3B43,0x5357,0x5344, 0,0x3963,
+0x624F, 0, 0, 0,0x572F, 0,0x476C,0x3153,
+ 0, 0,0x3432,0x6251, 0, 0, 0,0x5072,
+0x422E,0x6250, 0,0x3F62,0x5326,0x3557,0x6252,0x356A,
+ 0,0x436D,0x387D, 0,0x382E, 0,0x4553,0x374F,
+0x6254, 0, 0, 0, 0,0x6253,0x3648,0x5779,
+ 0, 0, 0, 0, 0,0x4D25, 0, 0,
+ 0, 0, 0,0x6258, 0,0x6256,0x4A7C,0x3F35,
+0x5339,0x6255, 0, 0, 0, 0,0x6257, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x412E,0x4048, 0, 0, 0, 0, 0,
+ 0,0x625B,0x625A,0x402A, 0, 0,0x414E, 0,
+ 0, 0, 0,0x625C, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x625D, 0,0x625E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5B48, 0,0x5153,0x4D22,
+ 0, 0,0x3D28, 0, 0, 0,0x5E43,0x5825,
+0x3F2A,0x5B4D,0x526C,0x467A,0x452A, 0, 0, 0,
+0x5E44, 0,0x3157,0x5F2E, 0, 0, 0,0x4A3D,
+ 0,0x5F31, 0,0x392D, 0,0x527D, 0,0x3825,
+0x3A6B, 0, 0,0x335A, 0, 0, 0,0x355C,
+0x5545, 0, 0, 0, 0,0x4356,0x4F52,0x3B21,
+ 0,0x6573,0x6572, 0, 0,0x6574, 0,0x4D64,
+ 0,0x4875, 0, 0, 0, 0, 0, 0,
+ 0,0x352F,0x473F, 0,0x6576, 0, 0, 0,
+0x6C30, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6566, 0,0x3969,0x3531, 0,0x423C,0x6568,0x6567,
+0x6569, 0, 0, 0, 0,0x524D, 0, 0,
+ 0,0x616A,0x504E, 0,0x4D2E, 0,0x5165, 0,
+ 0,0x324A,0x316B, 0,0x3172,0x456D, 0, 0,
+0x5543,0x5330, 0,0x615C, 0, 0, 0,0x615D,
+ 0,0x525B, 0,0x3339,0x314B, 0, 0, 0,
+0x4D79,0x5577,0x615E, 0,0x3E36,0x347D, 0,0x615F,
+0x3A5C,0x6160,0x3B32,0x4249,0x6161, 0, 0, 0,
+0x506C, 0,0x4D3D, 0, 0,0x6162, 0,0x3543,
+0x4547,0x6163, 0, 0,0x6164, 0, 0, 0,
+ 0,0x5379, 0, 0, 0, 0, 0, 0,
+0x6165, 0,0x512D, 0, 0,0x6166,0x4E22, 0,
+ 0, 0, 0, 0, 0,0x6167, 0,0x3542,
+ 0, 0, 0, 0,0x6168,0x3B55, 0, 0,
+ 0, 0, 0,0x5044,0x6260,0x3158,0x5264, 0,
+ 0,0x6261, 0, 0,0x3C49,0x484C, 0,0x6263,
+0x6C7E,0x6C7D,0x5F2F, 0, 0, 0,0x6262,0x563E,
+0x4D7C,0x4326, 0, 0, 0,0x6343, 0, 0,
+0x5652,0x6267, 0, 0,0x6268, 0, 0,0x5347,
+ 0, 0,0x626C,0x3F6C, 0,0x626D,0x6265, 0,
+ 0,0x3340, 0, 0, 0,0x446E, 0, 0,
+0x626E, 0, 0,0x5043, 0,0x3A76,0x6269,0x375E,
+0x3B33,0x4C2C,0x4B4B,0x6264,0x6266,0x626A,0x626B, 0,
+ 0, 0,0x6277, 0, 0,0x6274,0x5475,0x6273,
+ 0, 0,0x452D, 0,0x557A,0x4542,0x3240, 0,
+ 0,0x626F, 0,0x6272,0x412F,0x4B3C, 0, 0,
+0x3521,0x6279, 0, 0, 0,0x3C31,0x6271,0x5054,
+0x5439,0x6275,0x3956,0x6276, 0, 0, 0,0x4753,
+ 0, 0, 0, 0, 0,0x6270, 0, 0,
+ 0, 0, 0,0x575C,0x6D21, 0, 0,0x6278,
+ 0,0x6D25,0x627E,0x4A51, 0, 0, 0, 0,
+ 0, 0, 0,0x4135, 0,0x3B50, 0, 0,
+0x3F56, 0,0x3A63, 0, 0,0x4B21, 0, 0,
+ 0,0x6D26,0x6D23, 0, 0,0x6D22, 0, 0,
+ 0, 0,0x3B56,0x6D27,0x5074, 0, 0,0x6D24,
+0x3A5E,0x3677,0x6321,0x3632,0x4C71,0x3927, 0,0x4F22,
+0x4721, 0, 0,0x3F52, 0, 0,0x3671, 0,
+0x627A,0x627B,0x627D,0x627C,0x4455,0x6322, 0,0x5341,
+ 0, 0, 0,0x6327,0x4744, 0, 0, 0,
+ 0,0x4F24, 0, 0,0x6329,0x3A37, 0, 0,
+ 0, 0,0x6328, 0,0x3B5A, 0,0x6323, 0,
+ 0, 0,0x6324,0x632A, 0,0x6326, 0,0x4E72,
+0x5346, 0, 0,0x3B3C, 0, 0,0x5443, 0,
+0x447A, 0, 0,0x6D28,0x507C,0x6325, 0,0x4375,
+ 0,0x632D,0x312F, 0,0x6332, 0, 0, 0,
+0x3C42, 0, 0,0x632C,0x353F, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4769,0x6330, 0,
+ 0, 0,0x3E2A,0x4D6F, 0, 0, 0, 0,
+ 0,0x3B73, 0, 0, 0,0x4C68, 0, 0,
+0x632F, 0,0x6331, 0,0x4F27,0x632E, 0,0x4E29,
+0x3B5D, 0, 0, 0, 0, 0,0x356B,0x3E65,
+0x3252,0x334D, 0,0x3139,0x632B,0x3251,0x352C,0x395F,
+0x3668, 0, 0,0x4F6B,0x6337, 0,0x3B4C, 0,
+ 0,0x4847,0x504A, 0, 0, 0, 0, 0,
+0x6338,0x336E, 0, 0, 0, 0,0x6D29, 0,
+0x537A,0x5364, 0, 0, 0,0x6D2A,0x6339,0x5262,
+ 0, 0, 0, 0, 0,0x6335, 0, 0,
+ 0, 0,0x535E, 0, 0, 0, 0,0x3850,
+0x6333, 0, 0,0x6336,0x375F, 0,0x6334,0x4022,
+ 0, 0, 0,0x633A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5438,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3448, 0,0x633B, 0,0x3B45, 0,0x4977, 0,
+ 0,0x4965, 0, 0, 0,0x443D, 0, 0,
+ 0, 0, 0, 0, 0,0x6D2B, 0, 0,
+ 0, 0,0x427D, 0, 0, 0, 0,0x3B5B,
+0x3F2E, 0, 0, 0, 0, 0, 0, 0,
+0x4E3F, 0, 0, 0, 0,0x633C, 0,0x3F36,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x316F, 0, 0,0x5477, 0,
+ 0, 0, 0, 0,0x633E, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6D2D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x633F,
+0x3A29,0x6D2C, 0, 0,0x633D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6340,
+ 0, 0, 0, 0, 0, 0,0x3A36, 0,
+ 0, 0,0x362E, 0, 0, 0, 0, 0,
+0x5038, 0,0x3043,0x6D2E, 0, 0, 0, 0,
+ 0,0x6D2F,0x4041, 0,0x6341, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4533, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6342, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5C32,
+ 0, 0, 0, 0, 0, 0,0x6D30, 0,
+0x386A, 0,0x4E6C,0x6A27,0x5067,0x4A79,0x4856,0x4F37,
+0x3349,0x4E52,0x3D64, 0, 0,0x635E,0x3B72,0x6A28,
+0x553D, 0,0x465D,0x6A29, 0, 0, 0,0x6A2A,
+ 0,0x6A2C,0x6A2B, 0,0x6A2E,0x6A2D, 0, 0,
+ 0, 0,0x3D58, 0,0x6A2F, 0,0x423E, 0,
+ 0, 0, 0,0x3441,0x3477, 0, 0,0x3B27,
+ 0, 0, 0, 0, 0,0x6C66,0x6C65,0x373F,
+0x4B79,0x3162, 0,0x6C67, 0, 0, 0,0x4948,
+0x6C68,0x6C69, 0,0x4A56,0x5E50,0x3245,0x547A, 0,
+ 0,0x464B,0x3047,0x3472,0x4853, 0, 0, 0,
+0x4D50, 0, 0,0x3F38, 0, 0, 0, 0,
+ 0, 0, 0,0x3F5B, 0, 0,0x4724,0x5634,
+ 0,0x4029,0x5E51,0x4928,0x516F,0x4524,0x3067,0x3336,
+0x4845, 0, 0,0x3062, 0, 0,0x3776, 0,
+ 0,0x457A, 0, 0,0x3673, 0,0x5552,0x3350,
+0x3C3C, 0, 0, 0,0x332D, 0, 0, 0,
+ 0,0x3E71,0x3051, 0, 0, 0, 0, 0,
+ 0,0x5256,0x4A63,0x5725, 0,0x4D36,0x3636,0x3F39,
+0x555B, 0,0x3827,0x4557, 0, 0, 0,0x5E52,
+0x3F59,0x4255,0x4740, 0,0x3B24,0x3128, 0, 0,
+0x456A, 0, 0,0x457B,0x4C27, 0, 0, 0,
+ 0,0x3127, 0, 0, 0,0x3556, 0, 0,
+ 0,0x4428, 0,0x5E53,0x513A,0x3369, 0,0x4372,
+ 0, 0,0x3777, 0,0x5674,0x3523,0x3270,0x4434,
+0x4469,0x402D,0x5E54, 0,0x3068,0x4544,0x4160, 0,
+0x3955, 0,0x3E5C,0x4D58,0x304E, 0,0x4D4F,0x5E56,
+0x3E50,0x573E,0x5E55,0x5550,0x305D, 0, 0,0x4462,
+ 0, 0,0x4223,0x3C70, 0,0x5335,0x4039,0x4521,
+0x3226,0x5471, 0, 0,0x4028,0x4A43,0x5E57,0x557C,
+ 0,0x3930, 0,0x482D,0x4B29, 0,0x5E59,0x3F3D,
+ 0, 0, 0, 0,0x4634,0x5727,0x4A30,0x4443,
+ 0,0x3356,0x3952, 0, 0, 0, 0,0x5638,
+0x6A7C,0x3034, 0, 0, 0, 0,0x3F66, 0,
+ 0,0x4C74, 0, 0, 0, 0,0x4D5A, 0,
+ 0, 0,0x563F,0x424E, 0,0x4E4E,0x4C22,0x502E,
+0x4453,0x3532,0x5E58,0x5575,0x3C37,0x3B53, 0, 0,
+0x3024, 0,0x4532,0x346C, 0, 0, 0,0x5571,
+ 0, 0,0x6A7D, 0, 0, 0, 0, 0,
+ 0,0x5E5A,0x4D26, 0, 0,0x4D6C, 0, 0,
+ 0, 0,0x4E66,0x5E5C, 0,0x4D31,0x4026, 0,
+ 0,0x573D, 0,0x5E5B,0x3046,0x3A34,0x4953,0x4473,
+0x3E68, 0, 0, 0, 0,0x3236, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x404C,0x4B70,
+ 0,0x3C71,0x3B3B,0x3537, 0, 0, 0,0x4575,
+ 0,0x5E66, 0, 0, 0,0x5E63,0x3E5D, 0,
+ 0,0x5E5F, 0, 0, 0, 0,0x3437,0x3D5D,
+ 0, 0,0x5E60,0x446D, 0, 0, 0, 0,
+0x4F46, 0,0x3560, 0, 0, 0, 0,0x365E,
+0x4A5A,0x3574,0x5E65, 0,0x5546, 0,0x5E61,0x4C4D,
+0x467E, 0,0x4545, 0, 0, 0,0x5234, 0,
+0x3E72, 0, 0, 0, 0, 0, 0, 0,
+0x4253, 0,0x4C3D,0x3338, 0,0x3D53, 0,0x3F58,
+0x4D46,0x515A,0x346B, 0,0x5E64,0x5E5D,0x5E67, 0,
+0x6A7E, 0, 0,0x4230,0x5E62, 0, 0,0x5640,
+0x3527, 0,0x3274, 0,0x5E68, 0,0x5E72, 0,
+ 0, 0, 0, 0,0x5E6D, 0,0x5E71, 0,
+ 0,0x4860, 0, 0, 0,0x5761,0x5E6F,0x4368,
+0x4C61, 0,0x3265, 0, 0, 0,0x523E, 0,
+ 0, 0, 0, 0, 0, 0,0x5E6E, 0,
+0x5E6B,0x4E55, 0,0x3427, 0, 0, 0, 0,
+ 0,0x3F2B,0x3E3E, 0, 0,0x3D52, 0, 0,
+ 0, 0,0x5E69, 0,0x542E, 0,0x5E5E, 0,
+0x5E6A, 0, 0, 0, 0,0x403F, 0,0x5E6C,
+0x3273,0x3869,0x4227, 0, 0,0x3D41, 0, 0,
+ 0, 0, 0,0x5E75,0x5E78, 0, 0,0x322B,
+0x3424, 0, 0,0x346A,0x4926, 0, 0, 0,
+ 0, 0, 0,0x5E76,0x4B51, 0,0x3863, 0,
+0x5E77,0x5E7A, 0, 0, 0, 0,0x5E79, 0,
+ 0, 0,0x4C42, 0,0x3061,0x346E, 0, 0,
+ 0, 0, 0, 0,0x653A, 0, 0, 0,
+ 0, 0,0x502F, 0, 0,0x326B, 0,0x6B21,
+ 0,0x5E74, 0, 0,0x4963,0x5E73,0x305A,0x5221,
+0x3177, 0,0x4C2F, 0, 0, 0, 0, 0,
+ 0, 0,0x5E70, 0,0x4B24, 0, 0, 0,
+0x552A, 0, 0, 0, 0, 0,0x5E7B, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x345D,
+ 0,0x4426, 0, 0, 0,0x5E7D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x437E,0x4421,0x5F21, 0, 0, 0, 0, 0,
+ 0, 0,0x414C, 0,0x5E7C,0x3E6F, 0,0x4632,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3345,0x4876, 0, 0,0x4B3A,0x5E7E, 0,
+ 0,0x5F24, 0, 0, 0, 0,0x5732, 0,
+ 0, 0, 0, 0,0x3337, 0, 0, 0,
+ 0,0x4143, 0, 0,0x474B,0x3225,0x3469, 0,
+0x572B, 0, 0, 0, 0,0x446C, 0,0x5F22,
+0x5F23, 0,0x5F25, 0,0x3A33, 0, 0, 0,
+0x5F26, 0,0x405E, 0, 0,0x4943, 0, 0,
+ 0, 0, 0, 0, 0,0x3259,0x4766, 0,
+0x5F27, 0,0x475C, 0, 0, 0, 0,0x5F28,
+0x6B22, 0, 0, 0, 0, 0,0x4B53, 0,
+ 0, 0,0x5F2A, 0,0x5F29, 0,0x3241, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x454A, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F2B, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x545C, 0, 0, 0, 0, 0,
+0x4841, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5F2C, 0, 0,
+ 0, 0, 0,0x3E70, 0, 0,0x5F2D,0x5627,
+ 0, 0, 0, 0,0x6A37,0x6B36,0x4A55, 0,
+0x587C,0x3844, 0,0x3925, 0, 0,0x3745,0x557E,
+ 0, 0, 0, 0, 0,0x394A, 0, 0,
+0x5027,0x744D, 0, 0,0x3550, 0, 0,0x4374,
+ 0,0x3E48, 0, 0, 0,0x6B37,0x303D, 0,
+ 0,0x3D4C, 0,0x4132, 0,0x3156,0x3328, 0,
+ 0, 0,0x3852,0x4922, 0, 0,0x3658, 0,
+ 0, 0, 0,0x6B38,0x3E34, 0, 0, 0,
+0x4A7D, 0,0x4743, 0,0x557B, 0, 0,0x3773,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4E44,
+ 0, 0, 0,0x552B,0x3173, 0, 0, 0,
+0x6C33,0x305F, 0,0x6C35, 0, 0, 0,0x3637,
+ 0,0x414F, 0,0x757A,0x5031, 0, 0,0x5565,
+ 0,0x4E53, 0, 0,0x3D6F,0x3362, 0,0x382B,
+ 0,0x5536, 0,0x6D3D, 0,0x364F, 0,0x4B39,
+0x5042, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x373D, 0, 0,0x6C36,0x4A29, 0, 0,
+ 0,0x4554, 0,0x6C39,0x6C38,0x4243,0x6C37, 0,
+ 0, 0, 0,0x507D,0x6C3A, 0,0x6C3B,0x5765,
+ 0, 0,0x6C3C, 0, 0, 0,0x6C3D,0x466C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E5E, 0,0x3C48, 0, 0,0x4855,0x3529,0x3E49,
+0x563C,0x5467, 0, 0,0x512E,0x5071,0x6A38,0x6A39,
+0x6A3A,0x3A35, 0, 0, 0, 0,0x4A31,0x3F75,
+ 0, 0,0x4D7A, 0, 0, 0, 0, 0,
+0x6A40, 0,0x303A,0x6A3E, 0, 0,0x4025, 0,
+ 0, 0,0x6A3B, 0,0x327D, 0,0x4377,0x3B68,
+ 0, 0, 0,0x5257,0x4E74,0x6A3F, 0, 0,
+ 0,0x6A3C, 0, 0, 0,0x6A43, 0,0x5047,
+0x5333, 0, 0, 0, 0,0x343A, 0,0x4341,
+0x5772, 0, 0, 0, 0,0x5551, 0,0x4A47,
+ 0,0x6A45, 0, 0,0x6A44,0x6A47,0x6A46, 0,
+ 0, 0, 0, 0,0x5667, 0,0x4F54, 0,
+ 0,0x6A4B, 0,0x3B4E, 0, 0, 0, 0,
+ 0, 0, 0,0x3D7A,0x494E, 0, 0,0x6A4C,
+ 0, 0,0x4939,0x4F7E,0x6A4A,0x544E,0x6A4D,0x6A4F,
+ 0, 0,0x4D6D, 0, 0, 0, 0,0x6A49,
+ 0,0x6A4E, 0, 0,0x4E6E, 0,0x3B5E, 0,
+0x333F, 0, 0, 0, 0, 0,0x4655,0x3E30,
+0x4E7A, 0, 0, 0,0x4767, 0,0x3E27,0x6A50,
+ 0, 0,0x5647, 0, 0, 0,0x4140, 0,
+ 0, 0,0x545D, 0,0x6A51, 0, 0,0x4F3E,
+ 0, 0, 0, 0,0x6A52, 0, 0, 0,
+ 0,0x4A6E, 0, 0, 0, 0,0x452F,0x3035,
+ 0, 0, 0, 0, 0,0x6A54, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6A53,
+0x745F, 0, 0, 0, 0, 0,0x443A, 0,
+ 0, 0, 0, 0,0x3129, 0, 0, 0,
+ 0,0x655F, 0, 0, 0, 0,0x6A55, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4A6F, 0,0x6A56,0x6A57,0x4658, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A58, 0,
+ 0,0x6A59, 0, 0, 0, 0, 0, 0,
+0x543B, 0,0x477A,0x5237,0x387C, 0, 0,0x6A42,
+ 0,0x325C, 0, 0,0x427C, 0,0x5478,0x4C66,
+0x576E, 0, 0, 0, 0, 0, 0, 0,
+0x5442,0x5350,0x6B43,0x4573, 0,0x377E, 0, 0,
+0x6B54, 0, 0, 0,0x4B37,0x6B5E, 0,0x404A,
+ 0, 0, 0,0x4D7B, 0,0x332F, 0,0x465A,
+ 0, 0, 0, 0, 0, 0,0x6B7C, 0,
+0x443E, 0,0x4E34,0x4429,0x313E,0x547D, 0,0x4A75,
+ 0,0x566C, 0, 0,0x4653,0x3664, 0, 0,
+ 0, 0,0x3B7A, 0, 0,0x5060, 0, 0,
+0x4931, 0,0x5453,0x4828, 0, 0,0x384B, 0,
+0x683E,0x493C, 0, 0,0x683B, 0,0x406E,0x5053,
+0x3244,0x3465, 0,0x683C, 0, 0,0x5548, 0,
+ 0, 0, 0, 0,0x3645, 0,0x683D,0x4A78,
+0x385C,0x4C75, 0, 0, 0,0x4034, 0, 0,
+0x516E,0x683F,0x6842, 0, 0,0x3A3C, 0,0x312D,
+0x3D5C, 0,0x6A3D,0x6843, 0,0x6846, 0,0x684B,
+ 0, 0, 0, 0,0x684C, 0,0x4B49,0x3065,
+ 0,0x3C2B, 0, 0,0x3939, 0, 0,0x6841,
+ 0,0x4D77, 0,0x684A, 0, 0, 0, 0,
+0x4E76, 0, 0, 0, 0,0x556D, 0,0x4156,
+0x6844, 0,0x4336, 0,0x397B,0x5626,0x6848, 0,
+ 0, 0,0x4A60,0x5466, 0,0x6840, 0,0x6845,
+0x6847, 0,0x4739,0x3763, 0,0x6849, 0,0x3F5D,
+0x6852, 0, 0,0x6857, 0,0x6855,0x3C5C,0x3C4F,
+0x685B, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x685E, 0,0x685A,0x317A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3058,
+0x4433,0x384C,0x4662,0x483E,0x4861, 0, 0, 0,
+0x684F,0x6854,0x6856, 0,0x3971,0x6858,0x5775, 0,
+0x447B, 0,0x685C, 0, 0,0x3269, 0, 0,
+ 0,0x6851, 0, 0,0x3C6D, 0, 0,0x3F42,
+0x684D,0x5679, 0,0x4178,0x3271, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x685F, 0,0x4A41,
+0x6859, 0, 0, 0, 0,0x5524, 0,0x316A,
+0x553B,0x684E,0x6850,0x3630,0x6853, 0,0x685D,0x4038,
+ 0,0x4A77, 0,0x4B28, 0, 0,0x465C,0x4075,
+ 0, 0, 0, 0, 0,0x6869, 0, 0,
+ 0,0x5023, 0, 0, 0, 0, 0, 0,
+ 0,0x6872,0x566A, 0, 0, 0, 0, 0,
+ 0, 0,0x6860,0x6861, 0, 0, 0,0x5179,
+0x3A4B,0x3879, 0, 0,0x3871,0x5454,0x686F, 0,
+0x686E,0x686C,0x3970,0x4C52,0x6866,0x4E26,0x3F72, 0,
+0x3038,0x6871,0x6870, 0,0x5740, 0,0x6864, 0,
+0x4D29,0x4923, 0,0x3B38,0x3D5B,0x686A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6862,0x6863,0x6865,0x3535,0x6867,0x4745,0x686B,0x686D,
+0x3D30,0x572E, 0,0x6878, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6875, 0,0x4D30,0x6876,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x413A, 0,0x6868, 0,0x4337,0x3070, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6874,
+ 0, 0, 0,0x6877, 0, 0, 0,0x3923,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4952, 0, 0, 0,0x434E,0x4E60,
+0x4066, 0, 0, 0, 0,0x4B73, 0,0x4C5D,
+0x5035, 0, 0,0x4A61, 0,0x6873, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3C6C, 0,0x6879, 0, 0, 0, 0, 0,
+ 0,0x435E, 0,0x4665, 0,0x3977, 0, 0,
+ 0, 0,0x3074, 0, 0,0x5758, 0, 0,
+0x3C2C, 0,0x456F, 0, 0, 0, 0, 0,
+0x4C44, 0, 0,0x6926, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x492D, 0,
+0x6922,0x4062, 0, 0, 0,0x3F43, 0, 0,
+ 0,0x687E,0x3957, 0,0x687B, 0, 0, 0,
+ 0,0x6924, 0, 0, 0,0x524E, 0, 0,
+ 0, 0, 0,0x6923, 0,0x5632,0x5735, 0,
+0x6927, 0,0x3D37, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x687C,
+0x687D, 0, 0, 0,0x6921, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4D56, 0, 0,
+0x522C, 0, 0, 0,0x6932, 0, 0, 0,
+ 0,0x6929, 0, 0, 0,0x342A, 0,0x343B,
+ 0, 0,0x692B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5028, 0, 0,0x6925,
+ 0, 0,0x337E, 0, 0,0x692C,0x4063, 0,
+0x692A, 0, 0,0x6939, 0, 0,0x6938, 0,
+ 0, 0, 0,0x692E, 0, 0,0x687A, 0,
+ 0,0x6928, 0, 0, 0, 0, 0,0x3F2C,
+0x6931,0x693A, 0, 0,0x4225, 0, 0, 0,
+0x692F, 0,0x3845, 0,0x692D, 0,0x535C,0x6934,
+0x6935,0x6937, 0, 0, 0,0x6947, 0, 0,
+ 0, 0, 0, 0,0x4046,0x6945, 0, 0,
+0x6930, 0, 0,0x693B,0x3071, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x693C,
+0x5525, 0, 0,0x693E, 0,0x693F, 0, 0,
+ 0,0x6941, 0, 0,0x4171, 0, 0,0x4836,
+ 0, 0, 0,0x693D, 0, 0, 0, 0,
+ 0,0x6942, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6943, 0,0x6933, 0,0x6936, 0,
+0x3B31, 0, 0, 0,0x6940, 0, 0, 0,
+ 0, 0, 0,0x3C77, 0, 0, 0,0x6944,
+0x6946, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x694A, 0, 0,
+ 0, 0,0x694E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x325B, 0,0x6948,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x372E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x694B,
+0x694C, 0, 0, 0, 0, 0, 0,0x5541,
+ 0,0x4423, 0, 0, 0, 0, 0, 0,
+0x6958, 0,0x3A61, 0, 0, 0, 0,0x6949,
+ 0,0x5323, 0, 0, 0,0x6954, 0, 0,
+ 0, 0, 0, 0, 0,0x6957,0x6950, 0,
+ 0, 0, 0, 0,0x694F, 0, 0,0x4741,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6952, 0, 0, 0, 0, 0, 0, 0,
+0x6959,0x3348, 0,0x6953, 0, 0, 0, 0,
+ 0,0x4F70, 0, 0, 0,0x694D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3377, 0, 0, 0, 0, 0, 0,
+ 0,0x6956, 0, 0,0x695A, 0, 0, 0,
+0x4C34, 0, 0, 0,0x4F2D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6955, 0,
+0x695C,0x695B, 0, 0, 0, 0, 0,0x695E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6951, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x695D, 0,0x695F,0x434A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4737,0x344E,0x3B36,0x5040,0x6C23, 0, 0,0x4537,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x537B, 0, 0, 0, 0,0x6C24,
+ 0,0x6C25,0x465B, 0, 0, 0,0x3F6E, 0,
+ 0, 0, 0,0x6C26, 0, 0,0x6C27,0x502A,
+ 0,0x4738, 0, 0,0x3868, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C28, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5639,0x557D,0x344B,0x323D,0x4E64,0x4667,
+ 0, 0,0x4D61, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3475, 0,0x4B40,0x3C5F, 0, 0, 0,
+ 0,0x6962,0x6963,0x516A,0x6965, 0,0x3479,0x6964,
+ 0,0x5133,0x4A62,0x3250, 0,0x6968, 0, 0,
+ 0, 0,0x6966,0x6967, 0, 0,0x5633, 0,
+ 0, 0,0x6969,0x696A, 0, 0, 0, 0,
+ 0,0x696B, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x696C, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C2F,0x4539,0x364E, 0,0x5273,
+ 0, 0, 0, 0, 0, 0, 0,0x356E,
+ 0,0x3B59,0x6C31, 0, 0,0x5263, 0, 0,
+ 0, 0, 0,0x4E63, 0,0x4438, 0,0x433F,
+ 0, 0,0x363E,0x5839,0x3148,0x314F,0x3151,0x457E,
+ 0,0x3150, 0,0x432B, 0, 0, 0, 0,
+ 0,0x5531, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6B24,0x3A41, 0, 0, 0,0x4C3A,
+ 0, 0, 0,0x6B25, 0,0x6B27, 0, 0,
+ 0,0x6B28, 0, 0, 0,0x6B26, 0, 0,
+ 0, 0, 0, 0, 0,0x6B29,0x6B2B,0x6B2A,
+ 0, 0, 0, 0, 0,0x6B2C, 0,0x4A4F,
+0x5835,0x4371, 0,0x4325,0x4678,0x6B2D,0x444A, 0,
+0x6B2E,0x6B2F,0x6B30,0x3755, 0, 0, 0,0x377A,
+ 0,0x6B31,0x4762, 0,0x6B33, 0,0x3A24,0x5175,
+0x3031,0x6B32,0x6B34, 0, 0, 0,0x352A,0x4248,
+0x4768, 0,0x6B35, 0,0x4B2E,0x635F, 0, 0,
+0x5340, 0, 0, 0, 0,0x595B, 0, 0,
+0x4D21,0x562D,0x4773, 0, 0, 0,0x5960,0x3B63,
+ 0,0x3A3A,0x6362, 0, 0, 0, 0, 0,
+0x4F2B, 0, 0, 0,0x6360,0x4947, 0,0x3A39,
+ 0, 0, 0,0x5134,0x6361,0x486A,0x392F,0x3D2D,
+0x3358,0x4E5B, 0, 0,0x4C40, 0, 0, 0,
+0x6368,0x6369,0x4D74, 0, 0, 0, 0, 0,
+0x4C2D, 0,0x3C33, 0,0x636A, 0,0x636B, 0,
+ 0,0x505A, 0, 0, 0,0x467B,0x375A, 0,
+ 0,0x475F,0x524A,0x4E56, 0,0x6364,0x636C, 0,
+0x4972,0x3341, 0, 0,0x6367, 0, 0,0x4663,
+0x6365, 0, 0,0x6D33,0x6366, 0, 0, 0,
+ 0,0x4933, 0,0x4566, 0, 0, 0,0x3935,
+ 0,0x433B, 0,0x6363,0x453D,0x4124,0x4259,0x3257,
+ 0,0x636D,0x3B26,0x442D, 0,0x6370,0x3E5A, 0,
+ 0,0x637B,0x6375,0x3A53, 0, 0, 0, 0,
+0x3750,0x534D, 0,0x564E,0x5553,0x3941,0x5534,0x5158,
+ 0, 0, 0, 0,0x5039,0x4776, 0, 0,
+ 0,0x482A,0x3234, 0,0x435A, 0, 0, 0,
+0x636E, 0, 0,0x637C,0x636F,0x3728,0x6377,0x6374,
+ 0, 0, 0,0x373A, 0, 0,0x4522, 0,
+0x6376,0x455D,0x3228,0x467C, 0,0x4460, 0, 0,
+0x5722, 0,0x4061,0x6379, 0, 0,0x637A,0x637D,
+0x4C29,0x6373, 0,0x533E, 0,0x3143,0x6D34,0x6371,
+0x6372, 0,0x6378,0x503A,0x4643,0x5473,0x637E, 0,
+ 0,0x3D60, 0, 0,0x6427, 0, 0,0x6426,
+ 0, 0, 0,0x5173,0x6423, 0,0x6429, 0,
+ 0, 0,0x4877, 0, 0, 0, 0,0x4F34,
+ 0,0x6428,0x642E,0x4265, 0, 0,0x3634, 0,
+ 0, 0, 0, 0, 0,0x3D72, 0,0x6422,
+ 0, 0,0x3A69,0x642A, 0, 0,0x642C, 0,
+ 0,0x367D,0x565E,0x6432, 0,0x642D, 0, 0,
+ 0,0x6421, 0,0x3B6E,0x4D5D,0x4722,0x4549, 0,
+ 0,0x4177, 0,0x6424, 0,0x4733,0x3D2C,0x3D3D,
+0x6425, 0,0x5747,0x3262, 0,0x642B,0x3C43,0x642F,
+ 0,0x3B6B,0x6430,0x4528,0x6431, 0, 0, 0,
+ 0,0x5563,0x3F23, 0,0x643A, 0,0x6437, 0,
+0x643B, 0, 0,0x643D, 0, 0,0x4656, 0,
+ 0,0x3A46,0x404B, 0, 0, 0,0x3821,0x6434,
+ 0, 0, 0, 0,0x5421, 0, 0,0x3A23,
+0x3D7E, 0, 0, 0,0x643C, 0, 0, 0,
+ 0, 0,0x4D3F, 0, 0,0x4479, 0, 0,
+0x4F7B,0x4966, 0, 0,0x533F, 0,0x4F51, 0,
+ 0,0x6433, 0,0x6438,0x6439,0x4C69, 0, 0,
+ 0, 0, 0,0x4C4E, 0,0x4054,0x6435,0x4130,
+0x6436,0x4E50, 0,0x3B41,0x3553, 0,0x4873,0x3D27,
+0x5547,0x492C,0x3822,0x644A, 0, 0,0x644C,0x5144,
+ 0, 0,0x523A, 0, 0,0x3A2D, 0, 0,
+0x3A54, 0, 0, 0, 0, 0, 0,0x6443,
+0x356D, 0, 0, 0,0x574D,0x6440,0x4F7D,0x643F,
+ 0, 0, 0,0x415C,0x4C4A, 0, 0, 0,
+ 0,0x4A67, 0, 0, 0, 0,0x4457, 0,
+0x4C54,0x6448, 0, 0, 0,0x6447,0x6441, 0,
+0x6444,0x352D, 0, 0,0x5359, 0,0x6446, 0,
+ 0, 0, 0,0x5279,0x3463, 0,0x3B34, 0,
+ 0,0x496E, 0,0x343E, 0, 0, 0,0x3B6C,
+ 0,0x514D, 0,0x4C6D,0x6D35, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4765, 0, 0,
+ 0, 0,0x5428, 0,0x644B,0x5755,0x6442, 0,
+0x3D25,0x6445, 0, 0,0x5366, 0,0x6449,0x4978,
+ 0, 0,0x643E, 0, 0,0x5365, 0, 0,
+0x477E,0x3649, 0,0x547C,0x3233,0x6457, 0, 0,
+ 0,0x4E42, 0,0x644D, 0,0x4E3C, 0,0x385B,
+ 0, 0,0x6456, 0,0x3F4A, 0, 0, 0,
+0x534E, 0,0x436C, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4548,0x6458, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4D44,0x644F, 0,
+ 0, 0, 0,0x6454,0x6455, 0,0x3A7E, 0,
+0x4F66, 0, 0,0x553F, 0, 0, 0,0x6452,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6450, 0, 0,0x644E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4D65,0x4A2A,
+ 0, 0, 0,0x4023, 0,0x3D26,0x6453, 0,
+ 0,0x3848, 0, 0, 0, 0, 0,0x6467,
+0x5434, 0, 0, 0, 0, 0, 0, 0,
+0x645B, 0, 0, 0,0x416F, 0, 0,0x6469,
+ 0, 0,0x5267, 0, 0,0x645F, 0,0x6460,
+ 0, 0,0x4F2A, 0, 0, 0, 0,0x4B5D,
+ 0,0x645A,0x6451, 0,0x6465, 0,0x485C,0x6463,
+ 0, 0,0x4467,0x6462, 0,0x6461, 0, 0,
+ 0,0x337C,0x6468, 0, 0, 0, 0,0x3561,
+ 0, 0, 0,0x574C, 0, 0, 0,0x6466,
+ 0,0x3B2C, 0,0x5752,0x4C4F,0x6B78, 0,0x6464,
+ 0, 0,0x3976, 0, 0, 0,0x564D,0x6459,
+0x645C,0x427A,0x645E, 0,0x424B,0x4044,0x4250, 0,
+0x3175,0x4C32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x354E, 0, 0, 0,
+ 0,0x646F, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x462F, 0, 0, 0,0x4661, 0,
+ 0,0x6475, 0, 0, 0, 0, 0,0x4229,
+ 0, 0, 0,0x406C,0x515D,0x646E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x442E, 0, 0, 0,0x646D, 0, 0, 0,
+ 0,0x6476,0x6474,0x427E, 0,0x645D, 0,0x6470,
+ 0,0x4A7E, 0,0x5544, 0, 0,0x6471, 0,
+ 0, 0, 0, 0, 0, 0,0x517A, 0,
+ 0, 0, 0, 0, 0, 0,0x646B,0x646C,
+ 0, 0, 0,0x6472, 0,0x4E2B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x454B, 0, 0, 0,0x4731, 0,0x423A, 0,
+ 0, 0,0x646A, 0, 0, 0,0x414A, 0,
+ 0, 0, 0, 0, 0,0x4C36,0x3331, 0,
+ 0, 0,0x647B, 0,0x6473, 0, 0, 0,
+0x647A, 0,0x647D, 0,0x647C, 0, 0, 0,
+ 0, 0, 0, 0,0x334E, 0, 0, 0,
+0x333A,0x6477, 0, 0,0x6479,0x6478,0x456C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x403D, 0, 0, 0,
+ 0,0x5468, 0, 0, 0, 0, 0,0x6522,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3044, 0, 0,0x6524, 0,
+ 0,0x6523, 0, 0, 0, 0, 0, 0,
+0x3C24, 0,0x6525, 0, 0, 0, 0, 0,
+ 0,0x6521, 0, 0, 0, 0, 0, 0,
+ 0,0x647E,0x3174, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6528, 0,
+0x6529,0x6526, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6527,0x652A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4659, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x652B,0x652D, 0, 0, 0, 0,
+ 0, 0, 0,0x652C, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x652F, 0, 0,
+ 0,0x652E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3960, 0, 0,0x6530,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6531, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3B70,0x6C61,0x4370, 0,0x3546,
+0x3B52, 0, 0, 0, 0,0x4169,0x546E, 0,
+0x3E44, 0, 0, 0,0x5746, 0,0x5456,0x3253,
+0x6C3E, 0, 0, 0, 0,0x6A41, 0, 0,
+ 0,0x422F,0x3436, 0, 0, 0,0x5157, 0,
+ 0, 0,0x3334, 0,0x4832,0x3F3B,0x6C40, 0,
+ 0,0x564B, 0, 0,0x6C3F,0x6C41, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C45,0x3E66,0x4C3F,0x455A,0x3E3C,
+ 0,0x6C46, 0,0x317E, 0, 0, 0,0x6C44,
+0x5528,0x3563, 0,0x6C42,0x4136,0x3363, 0, 0,
+0x6C43,0x4B38,0x4043,0x4C7E, 0, 0, 0, 0,
+0x4152, 0,0x6C48, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3A66,0x4053, 0,0x5672, 0, 0, 0,0x514C,
+ 0, 0, 0, 0,0x3F3E, 0,0x3733,0x4955,
+0x6C47,0x3B62, 0,0x4C4C,0x3D7D,0x4848, 0,0x4F29,
+ 0, 0, 0, 0, 0, 0, 0,0x4D69,
+ 0,0x456B, 0, 0, 0,0x3769, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5149,0x3A38, 0, 0, 0, 0, 0,
+0x6C49, 0, 0,0x6C4A, 0,0x3B40,0x6C4B, 0,
+0x6C62,0x313A,0x3759, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D39, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6C4C,
+0x5166,0x6C4D, 0, 0, 0, 0,0x483B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C51, 0, 0,
+ 0, 0,0x6C53, 0,0x3B4D, 0,0x3C65, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C4F, 0,0x4937, 0,
+ 0, 0, 0, 0,0x433A, 0,0x6C63,0x5555,
+0x6C50, 0, 0, 0, 0, 0,0x5673, 0,
+ 0, 0,0x6C52,0x6C4E, 0, 0, 0, 0,
+0x6C54, 0,0x6C55, 0, 0,0x493F, 0, 0,
+ 0, 0, 0, 0,0x4F28, 0, 0, 0,
+ 0, 0,0x505C, 0, 0, 0, 0,0x512C,
+ 0, 0, 0, 0,0x485B, 0, 0, 0,
+0x6C56,0x4E75, 0, 0, 0, 0, 0,0x4A6C,
+0x6C5A, 0, 0, 0, 0, 0, 0, 0,
+0x6C59, 0, 0, 0,0x303E, 0, 0, 0,
+ 0, 0, 0,0x6C57, 0,0x6C58, 0, 0,
+ 0,0x6C64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x483C, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4147, 0,
+ 0, 0, 0, 0,0x6C5C,0x5160, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C5B, 0, 0, 0, 0,0x546F, 0,0x6C5D,
+ 0, 0, 0, 0, 0, 0,0x5B46, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C5E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x312C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C5F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C60, 0,0x5726, 0,0x4540, 0, 0, 0,
+0x6B3C,0x302E, 0, 0, 0,0x3E74,0x3838,0x522F,
+0x3056,0x3579, 0,0x5833, 0,0x4B2C, 0,0x635D,
+ 0, 0, 0, 0, 0, 0, 0,0x462C,
+0x3066, 0, 0, 0,0x4546,0x6B39, 0, 0,
+ 0, 0,0x6B3A, 0, 0, 0,0x6B3B, 0,
+ 0,0x5140, 0,0x4523, 0,0x6A72, 0,0x4432,
+ 0,0x4435,0x404E, 0, 0, 0,0x6A73,0x4441,
+ 0,0x4E6F, 0, 0, 0, 0,0x6A70,0x6A74,
+ 0, 0,0x497C, 0, 0,0x4723, 0, 0,
+ 0,0x4C58,0x4E7E, 0, 0, 0,0x6A75,0x6A76,
+0x4F2C,0x4067, 0, 0,0x6A77, 0, 0, 0,
+ 0, 0,0x363F,0x6A78, 0,0x6A79, 0,0x6A7A,
+ 0, 0,0x6A7B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6A71,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x482E,0x616B, 0,0x3738,
+0x616C, 0, 0, 0,0x616D, 0,0x5734,0x616E,
+0x616F,0x534C, 0, 0, 0, 0, 0, 0,
+ 0,0x6171,0x3F71,0x6170,0x3552, 0, 0, 0,
+0x3137, 0, 0, 0, 0,0x6173,0x6172, 0,
+0x3A7C, 0,0x6174, 0, 0, 0, 0,0x3937,
+ 0,0x3E51, 0, 0, 0, 0,0x447C, 0,
+0x3A5D,0x3D46, 0, 0, 0, 0, 0, 0,
+0x6175,0x6177, 0, 0,0x3640,0x4F41,0x4A28,0x6176,
+0x5578,0x537C,0x6178,0x617C,0x6179, 0, 0,0x617A,
+0x406A, 0,0x617E,0x6221,0x4047, 0, 0, 0,
+ 0,0x617B, 0,0x617D, 0, 0, 0, 0,
+ 0, 0,0x6225, 0, 0, 0,0x4154, 0,
+ 0, 0, 0,0x6223, 0,0x6228,0x327E,0x6222,
+ 0, 0, 0,0x434D,0x3242,0x6227,0x6226, 0,
+ 0,0x6224,0x6229, 0, 0,0x622B, 0, 0,
+ 0,0x5049,0x566D,0x4328,0x622C, 0,0x4F57, 0,
+ 0,0x622E, 0, 0,0x3A6F, 0, 0,0x6960,
+0x622D,0x622A, 0, 0, 0, 0,0x3B2B,0x5433,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6230, 0, 0,
+0x622F, 0,0x6961, 0, 0, 0, 0,0x6231,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6232, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6233,0x4C21, 0,0x6234,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6235, 0,
+ 0, 0, 0, 0,0x507E, 0, 0,0x424A,
+ 0,0x5371, 0,0x4D75, 0, 0,0x6760, 0,
+ 0,0x6761, 0, 0, 0, 0,0x3E41, 0,
+ 0, 0, 0,0x426A, 0, 0, 0,0x6764,
+ 0, 0,0x6763, 0, 0, 0, 0, 0,
+ 0,0x4D66, 0,0x4335, 0, 0,0x6762,0x3B37,
+0x4F56, 0,0x4161,0x6769, 0, 0, 0,0x6768,
+ 0, 0,0x6774,0x3223, 0, 0, 0, 0,
+0x676A, 0,0x6766, 0, 0, 0, 0, 0,
+0x676C,0x676B,0x493A, 0, 0,0x5564, 0,0x6765,
+0x3729,0x6767, 0, 0, 0, 0, 0, 0,
+ 0,0x676E, 0, 0, 0, 0,0x6773, 0,
+0x5669, 0, 0, 0, 0,0x676D, 0,0x6772,
+ 0,0x6771, 0, 0, 0,0x3060, 0, 0,
+ 0, 0,0x6775, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4772, 0,0x4045,0x406D, 0,
+ 0,0x4170,0x6770, 0, 0, 0, 0,0x6776,
+0x4B76, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6822,0x6821, 0, 0, 0, 0,
+ 0, 0,0x5741, 0, 0,0x677A,0x6779, 0,
+0x677B, 0,0x6777, 0,0x677E, 0,0x677D, 0,
+0x677C, 0, 0,0x4155,0x4759,0x457D,0x4543, 0,
+ 0, 0, 0, 0,0x476D, 0, 0, 0,
+ 0,0x6823, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6826, 0,0x6825,
+ 0,0x6827,0x3A77,0x6778,0x6824, 0,0x4870,0x492A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6829, 0, 0,
+0x3965, 0, 0, 0, 0, 0,0x517E,0x6828,
+ 0, 0, 0, 0, 0, 0,0x682A, 0,
+0x682D,0x682E, 0,0x4127, 0, 0, 0,0x682F,
+ 0, 0, 0,0x6830, 0, 0,0x682C, 0,
+0x6834, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x682B, 0,0x6831, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6835,
+0x6832,0x6833, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6837, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6836, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x394F, 0,0x702C, 0,
+0x702D, 0,0x4630,0x306A,0x483F, 0,0x4D5F, 0,
+ 0, 0, 0, 0, 0, 0,0x4E4D,0x6A31,
+ 0, 0, 0, 0,0x6A32, 0,0x463F,0x3449,
+ 0, 0, 0, 0, 0, 0, 0,0x6A33,
+ 0, 0, 0, 0,0x5567, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5D79, 0,0x6A34,
+ 0,0x6A35, 0,0x6A36, 0, 0, 0, 0,
+0x384A,0x5F30,0x4975, 0,0x4C70, 0, 0,0x497A,
+ 0, 0, 0, 0, 0,0x497B, 0, 0,
+0x5343,0x4B26, 0,0x3826,0x702E,0x3142, 0,0x6538,
+0x4C6F,0x5349,0x3C57,0x496A, 0,0x3567, 0,0x4450,
+0x3569, 0,0x6E2E,0x3B2D, 0, 0,0x675E, 0,
+0x6E2F, 0, 0, 0, 0,0x3329, 0, 0,
+0x6E32, 0, 0,0x6E31,0x3D67, 0,0x6E30,0x4E37,
+ 0, 0, 0, 0,0x454F, 0, 0, 0,
+ 0,0x4174,0x5B4E,0x6E33,0x5073, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4254,0x4668, 0,
+ 0, 0,0x372C, 0, 0, 0, 0, 0,
+ 0, 0,0x6E34, 0,0x336B, 0, 0, 0,
+0x3B7B,0x6E35, 0, 0, 0, 0, 0,0x675C,
+ 0, 0, 0,0x6E36, 0, 0,0x3D2E, 0,
+ 0, 0, 0,0x7162, 0, 0, 0,0x4A68,
+ 0,0x5249,0x705A, 0,0x705B, 0,0x705C,0x4146,
+ 0,0x386D,0x3E4E, 0, 0,0x705E, 0,0x4531,
+0x705D,0x5171, 0,0x7060,0x304C,0x3D6A, 0, 0,
+ 0, 0, 0,0x525F,0x705F, 0,0x342F,0x3768,
+0x7066,0x7065,0x4623,0x7061,0x7062,0x3443, 0, 0,
+0x7063,0x556E, 0, 0,0x4C5B,0x3E52,0x3C32, 0,
+ 0, 0,0x7068,0x7067,0x7064,0x3221, 0,0x5622,
+0x5338,0x3E37,0x482C, 0, 0,0x706A, 0, 0,
+ 0, 0,0x5177, 0,0x564C,0x3A5B,0x7069, 0,
+0x363B, 0, 0,0x4D34, 0, 0,0x4626, 0,
+ 0, 0,0x4121,0x706B,0x706E, 0,0x706D,0x7070,
+0x706C, 0,0x3B3E,0x706F, 0, 0, 0, 0,
+0x4C35,0x7072, 0, 0,0x3355, 0, 0, 0,
+ 0,0x3154, 0, 0,0x7073, 0, 0,0x7074,
+0x7076,0x3461, 0,0x7071, 0,0x7077, 0, 0,
+ 0, 0,0x707A, 0,0x7078, 0, 0, 0,
+0x7075, 0, 0, 0, 0,0x707D, 0,0x7079,
+0x707C,0x707E, 0,0x7121, 0, 0, 0,0x4E41,
+0x7124, 0,0x7123, 0,0x4176,0x707B,0x4A5D, 0,
+ 0,0x3471,0x3171,0x4C31, 0,0x7126, 0, 0,
+0x7127, 0, 0,0x712C,0x554E,0x7129, 0, 0,
+0x4833, 0, 0, 0,0x7122, 0,0x712B,0x7128,
+0x7125, 0, 0,0x712A, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3029,0x712D, 0, 0,
+ 0, 0, 0, 0,0x712F, 0,0x7131, 0,
+ 0, 0, 0, 0,0x7130, 0,0x712E, 0,
+ 0, 0, 0,0x5122, 0, 0, 0, 0,
+ 0, 0, 0,0x7132, 0, 0, 0,0x7133,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x396F, 0, 0,0x3547, 0,0x3057,0x3059, 0,
+ 0, 0,0x546D, 0,0x3544, 0,0x3D54,0x3B4A,
+0x7027, 0, 0,0x385E, 0, 0,0x7028, 0,
+ 0,0x3028, 0,0x7029, 0, 0,0x4D6E, 0,
+ 0,0x702A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x702B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4624, 0,
+ 0,0x5665,0x7164, 0,0x7165, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4373,
+ 0, 0,0x535B, 0, 0,0x5651,0x4568, 0,
+0x532F, 0,0x5266, 0, 0,0x6E41,0x303B,0x5535,
+0x514E,0x3C60,0x3A50, 0,0x3F78, 0,0x3847,0x3541,
+0x454C, 0, 0,0x4A22, 0, 0, 0,0x434B,
+ 0, 0, 0, 0, 0,0x6E42, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x443F,0x3622,
+ 0,0x6D6C,0x4324, 0,0x5631, 0, 0, 0,
+0x4F60,0x6D6F, 0, 0,0x454E, 0,0x365C, 0,
+ 0,0x4A21, 0, 0,0x6D6D, 0, 0,0x6D70,
+0x6D71,0x433C, 0,0x3F34, 0,0x6D6E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6D74,0x6D72, 0, 0, 0, 0,0x5566,
+0x435F, 0,0x6D73, 0, 0, 0,0x6D76, 0,
+0x5523,0x5123, 0, 0, 0,0x6D75, 0,0x4350,
+ 0, 0, 0, 0, 0,0x6D77,0x3F74,0x3E6C,
+0x6D78, 0,0x4C77, 0,0x515B, 0, 0, 0,
+0x5745,0x5576, 0,0x6D7C, 0, 0, 0,0x6D7B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6D79,0x6D7A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6D7D,0x3E26, 0, 0, 0, 0,
+ 0,0x4B2F,0x6E21,0x363D, 0,0x6E22,0x4440, 0,
+0x6D7E, 0, 0,0x3D5E,0x3247, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3643, 0, 0, 0,0x6E25,0x583A,0x6E23,
+0x6E26, 0, 0, 0,0x4369,0x3372, 0, 0,
+ 0, 0, 0, 0,0x6E27,0x6E24,0x4F39, 0,
+ 0,0x6E28,0x4277, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6E29,
+0x6E2A, 0,0x5E2B, 0, 0,0x4633, 0,0x4746,
+ 0,0x5675,0x3549, 0,0x4B32, 0, 0, 0,
+0x6E2B, 0, 0,0x4D2B, 0,0x6E2C, 0, 0,
+ 0, 0, 0,0x5530, 0,0x6E2D, 0,0x7644,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5B47, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3423,
+ 0, 0, 0,0x432C,0x7166, 0, 0, 0,
+ 0, 0,0x4A38,0x5253, 0,0x562A, 0,0x6F72,
+ 0,0x3E58, 0,0x3D43,0x6F73,0x364C,0x302B, 0,
+ 0, 0, 0,0x4A2F, 0, 0,0x6D36, 0,
+0x6D37, 0, 0, 0, 0,0x4E79,0x372F,0x3F73,
+0x6D38,0x426B,0x4930, 0, 0, 0, 0, 0,
+ 0,0x6D39, 0, 0,0x4676,0x3F33, 0, 0,
+ 0,0x6D3C,0x4578, 0,0x5150, 0,0x5729,0x6D3A,
+0x6D3B, 0,0x5162, 0,0x6D3F,0x6D40, 0,0x6D44,
+ 0, 0, 0,0x6D48, 0,0x6D46,0x6D4E,0x5568,
+ 0,0x6D49, 0, 0,0x6D47,0x6D3E, 0, 0,
+0x4569, 0, 0, 0,0x4646, 0, 0,0x4969,
+0x5452,0x6D41,0x6D42,0x6D43,0x6D45, 0,0x4079, 0,
+0x3421, 0, 0, 0, 0,0x3968, 0,0x6D50,
+ 0, 0, 0, 0,0x6D51, 0,0x6D4A, 0,
+0x6D4F, 0,0x4E78, 0, 0,0x4B36,0x6D4C,0x6D4D,
+ 0, 0, 0, 0, 0,0x4F75, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6D52,0x4172,0x5332,0x6D4B,0x4837, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C6F,
+ 0, 0, 0, 0,0x4570, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6D56,
+ 0,0x356F, 0, 0,0x4235,0x302D,0x4B69, 0,
+ 0,0x312E, 0,0x6D54, 0, 0, 0,0x4D6B,
+0x3562, 0,0x6D55,0x6D53,0x6D57, 0, 0,0x357A,
+ 0,0x6D58, 0,0x6D59, 0,0x6D5C, 0,0x314C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4576,0x3C6E,0x6D5A,0x4C3C,0x326A, 0, 0, 0,
+ 0,0x6D5B, 0, 0, 0, 0,0x446B, 0,
+ 0,0x3445, 0, 0, 0,0x3075, 0, 0,
+ 0,0x6D5F,0x405A,0x3468, 0, 0, 0, 0,
+0x454D, 0, 0, 0,0x6D5D,0x3F44, 0, 0,
+ 0,0x6D5E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4425, 0, 0, 0,0x6D60, 0, 0, 0,
+ 0, 0,0x6D61, 0,0x6D63, 0, 0,0x4157,
+ 0, 0,0x3B47, 0, 0, 0, 0, 0,
+ 0,0x3D38, 0, 0, 0,0x6D62, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6D64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D66, 0,
+ 0, 0, 0, 0,0x6D65, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6D67, 0, 0, 0,
+ 0, 0,0x4A3E,0x6C6A,0x4071, 0,0x4967, 0,
+0x6C6B,0x466E, 0, 0, 0, 0,0x6C6C, 0,
+0x466D,0x6C6D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C70, 0, 0,0x5766,0x6C73,
+ 0, 0,0x6C71,0x6C6E,0x6C6F,0x5723,0x4971,0x4B6E,
+0x6C74, 0,0x6C72, 0, 0,0x4F69, 0,0x6C76,
+0x4631, 0, 0, 0, 0,0x3C40, 0,0x6C75,
+ 0, 0, 0, 0, 0, 0, 0,0x353B,
+0x3B76, 0,0x6C77, 0, 0, 0, 0, 0,
+0x5977,0x3D7B, 0, 0,0x423B,0x6C78, 0, 0,
+ 0, 0,0x6C79, 0, 0, 0, 0,0x3823,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C7A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6C7B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C7C, 0, 0, 0, 0,
+ 0,0x536D,0x582E,0x406B, 0,0x475D,0x3A4C, 0,
+0x5063,0x4B3D, 0,0x4D3A, 0, 0,0x3851, 0,
+ 0,0x317C, 0,0x476F, 0,0x5656, 0, 0,
+ 0,0x3F46,0x436B, 0, 0,0x6F75, 0, 0,
+0x4358, 0, 0, 0, 0, 0, 0,0x5762,
+ 0, 0, 0,0x6F77,0x3353, 0,0x4758,0x516D,
+ 0,0x5648, 0,0x6F78, 0,0x6F76, 0,0x3B7D,
+0x3346, 0, 0, 0, 0, 0, 0, 0,
+0x3D55, 0, 0,0x5246, 0,0x3B60, 0, 0,
+0x4F21, 0,0x6F7C,0x6F7B, 0, 0,0x6F79, 0,
+ 0, 0, 0,0x334C, 0,0x4954,0x4B30, 0,
+ 0, 0, 0, 0,0x6F7E, 0, 0,0x305E,
+ 0, 0,0x5649, 0, 0, 0,0x6F7D, 0,
+0x336D, 0, 0,0x7655, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4E48, 0, 0, 0,0x7022,
+ 0,0x7021, 0,0x353E,0x3C5A,0x3B7C, 0,0x3865,
+ 0, 0, 0, 0, 0, 0,0x4442, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7023, 0, 0, 0, 0, 0,0x4B6B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7026, 0, 0, 0,0x5128, 0,0x3E3F,0x476E,
+0x7136,0x7137,0x3F55, 0, 0, 0, 0,0x3429,
+0x7138,0x4D3B, 0,0x4754,0x552D, 0,0x7139, 0,
+0x713A, 0, 0, 0, 0,0x474F, 0, 0,
+ 0,0x5224,0x564F, 0, 0,0x713B,0x3D51,0x3430,
+0x3E3D, 0, 0, 0,0x345C,0x4E51, 0,0x3F5F,
+0x713D, 0, 0, 0, 0,0x3F7A,0x713C, 0,
+0x713F, 0, 0, 0,0x713E,0x7140, 0, 0,
+ 0, 0, 0,0x7141, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x417E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4122, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A7A, 0,
+ 0,0x553E, 0, 0, 0, 0,0x3E3A,0x3E39,
+0x5542, 0, 0,0x3F22, 0,0x4D2F,0x7135, 0,
+ 0, 0, 0, 0, 0,0x3D5F, 0,0x364B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5671,0x7343, 0, 0,0x7344, 0,0x384D,
+ 0, 0, 0,0x7346,0x7347, 0,0x304A, 0,
+0x7345, 0,0x7349,0x4B71, 0, 0, 0,0x734B,
+ 0,0x5026, 0, 0,0x314A,0x7348, 0, 0,
+ 0,0x734F, 0,0x3551, 0, 0,0x7357, 0,
+0x7352, 0, 0, 0,0x7354,0x7353,0x377B, 0,
+0x313F, 0,0x734E,0x734A,0x355A, 0,0x7350, 0,
+ 0,0x7351, 0,0x7355, 0, 0, 0, 0,
+0x734D, 0,0x3C63, 0,0x417D, 0,0x7356, 0,
+ 0, 0, 0, 0, 0,0x735A, 0,0x734C,
+ 0,0x3548, 0,0x3D6E,0x735C, 0, 0,0x3724,
+0x3F70,0x567E,0x4D32, 0,0x3470, 0,0x325F, 0,
+0x7358, 0,0x7359,0x4938, 0,0x735D, 0, 0,
+0x735E, 0,0x7361, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x735F, 0,
+ 0,0x7363,0x7362, 0, 0,0x735B, 0,0x3F6A,
+ 0,0x336F, 0,0x7360, 0, 0,0x4729, 0,
+0x3C72, 0, 0, 0, 0,0x736B, 0, 0,
+ 0, 0, 0, 0, 0,0x393F, 0, 0,
+0x7364, 0, 0, 0,0x322D,0x3B7E, 0,0x4B63,
+ 0, 0, 0, 0,0x736D,0x7369, 0, 0,
+ 0,0x395C,0x736E, 0, 0, 0,0x7365,0x7366,
+0x736A,0x4261,0x736C,0x736F,0x7368,0x3C7D, 0, 0,
+ 0,0x4F64, 0, 0,0x7370, 0, 0, 0,
+0x7367, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7372, 0, 0, 0, 0,0x572D,0x462A,
+ 0, 0, 0, 0,0x7373, 0, 0, 0,
+ 0,0x7371, 0,0x4228, 0, 0, 0, 0,
+ 0,0x385D,0x7375, 0, 0,0x7374, 0, 0,
+ 0,0x345B, 0, 0, 0,0x7376,0x7377, 0,
+ 0, 0,0x7378, 0, 0, 0,0x403A, 0,
+ 0,0x4069, 0, 0, 0, 0, 0,0x4571,
+ 0, 0, 0, 0,0x737B, 0,0x737A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3458,
+ 0, 0, 0,0x737E,0x7379, 0, 0,0x737C,
+ 0, 0, 0, 0, 0, 0,0x737D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7421,
+ 0, 0, 0, 0, 0, 0,0x7423,0x3B49,
+ 0, 0,0x7422, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7424, 0, 0, 0, 0, 0, 0,0x323E,
+0x7426,0x7425, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C2E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4357,0x5961, 0, 0, 0,
+ 0, 0, 0,0x4060,0x744C,0x5751, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x375B, 0, 0, 0, 0, 0, 0,
+ 0,0x744E,0x4123, 0, 0,0x4649, 0,0x3456,
+0x5533, 0, 0, 0,0x7450,0x744F,0x7451,0x4B5A,
+ 0, 0,0x7452, 0,0x5441,0x5660, 0, 0,
+ 0, 0,0x3760, 0, 0, 0,0x4138, 0,
+ 0,0x413B,0x7453,0x3E2C, 0, 0, 0, 0,
+ 0,0x3462, 0, 0,0x7454,0x7455,0x3E2B, 0,
+ 0,0x7456, 0, 0, 0,0x745B, 0,0x7457,
+0x745A, 0,0x3A7D, 0,0x7458,0x7459, 0, 0,
+ 0, 0, 0, 0, 0,0x3862,0x4C47,0x745C,
+ 0,0x325A, 0, 0,0x4353, 0, 0,0x5463,
+0x3F37, 0, 0, 0, 0, 0, 0, 0,
+0x745D, 0, 0, 0, 0, 0, 0,0x4534,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7469, 0, 0,0x4F35, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4E49, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4B58, 0,0x4B77, 0, 0, 0, 0,0x3D74,
+ 0, 0, 0,0x574F, 0, 0, 0,0x405B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5075, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x746A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x746B, 0,
+ 0, 0, 0, 0, 0, 0,0x746C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7763, 0, 0, 0, 0,
+ 0,0x3731, 0, 0, 0, 0, 0,0x746D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x576B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x746E, 0, 0, 0,0x6679,
+0x3E40,0x667A,0x3A6C,0x667B,0x4F4B,0x667C,0x543C,0x3C36,
+0x667D,0x667E,0x3C4D,0x4852,0x4E33,0x6721, 0,0x343F,
+0x6722,0x4934,0x3859,0x4449, 0,0x575D,0x425A,0x3757,
+0x563D,0x4E46,0x3744, 0, 0,0x4526,0x6723,0x4F5F,
+0x6724,0x6725,0x6726,0x4137,0x5769,0x4970,0x4F38,0x562F,
+0x5655,0x6727,0x306D,0x6728,0x6729,0x495C,0x526F,0x3E2D,
+0x672A,0x3073,0x485E,0x3D61,0x672B,0x4846, 0,0x672C,
+0x3B66,0x3878,0x5124,0x672D,0x4267,0x3E78,0x3D4A,0x4D33,
+0x672E,0x672F,0x3E6E,0x5065, 0,0x4B67,0x4C50,0x3C4C,
+0x6730,0x3C28,0x5077,0x6731, 0,0x5078,0x6732,0x6733,
+0x3442,0x6734,0x6735,0x497E,0x4E2C,0x4360,0x6737,0x3141,
+0x3371, 0,0x6738,0x6739,0x575B,0x5540,0x673A,0x424C,
+0x573A,0x673B,0x673C,0x673D,0x3C6A,0x4365,0x4042,0x673E,
+0x673F,0x3C29, 0,0x6740,0x6741,0x6736,0x3650,0x6742,
+ 0,0x6743,0x6744,0x3B3A,0x355E,0x4246,0x3160,0x6745,
+0x5435,0x6746,0x383F,0x6748,0x6747,0x376C, 0,0x6749,
+0x3278,0x674A,0x674B,0x674C,0x674D,0x674E,0x674F,0x6750,
+0x5327,0x4B75,0x6751,0x6752,0x6753,0x6754,0x4949,0x6755,
+0x6756,0x6757,0x6758,0x6759,0x3D49,0x675A,0x733E, 0,
+0x3857, 0,0x4831, 0, 0, 0, 0, 0,
+ 0, 0,0x733F, 0,0x7340,0x7341, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x395E,0x4D78, 0, 0,0x5868,0x3A31, 0,0x425E,
+0x6E37, 0,0x3723, 0, 0, 0, 0,0x6E39,
+ 0,0x6E38,0x3055, 0, 0, 0, 0, 0,
+0x6E3B,0x5556,0x576F, 0, 0, 0,0x5643, 0,
+ 0,0x6E3D,0x4A70, 0,0x6E3C, 0, 0, 0,
+ 0,0x6E3E, 0, 0, 0, 0,0x6E40, 0,
+ 0,0x6E3F, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5172, 0,0x473C, 0,0x4340, 0,
+ 0, 0, 0, 0,0x3861, 0, 0, 0,
+ 0, 0,0x4167, 0, 0,0x7446,0x505F,0x7447,
+ 0,0x4F5B, 0, 0,0x483A, 0, 0,0x7448,
+ 0, 0, 0, 0, 0, 0, 0,0x7449,
+0x744A, 0,0x744B, 0, 0, 0, 0, 0,
+0x597A,0x387E, 0, 0,0x6571,0x5370, 0,0x7460,
+ 0,0x4E4C, 0, 0, 0,0x3361, 0, 0,
+ 0, 0,0x7134, 0,0x526E, 0,0x7461, 0,
+ 0, 0, 0, 0,0x4F68,0x7462, 0, 0,
+0x474C, 0, 0, 0, 0, 0, 0,0x3554,
+0x3464,0x7464, 0, 0, 0,0x7463,0x7465, 0,
+ 0,0x7466, 0, 0, 0, 0,0x7467, 0,
+0x3A32,0x303F, 0,0x7468, 0, 0, 0, 0,
+ 0, 0, 0,0x372D,0x526D, 0, 0, 0,
+0x522B,0x404F, 0,0x3F3C,0x6B23,0x555F,0x6A48, 0,
+ 0, 0, 0,0x7173,0x3678,0x4B23, 0, 0,
+0x444D, 0,0x7167, 0,0x7168,0x387B,0x7169,0x3A44,
+0x5445,0x3052, 0, 0,0x716A, 0, 0, 0,
+0x716B, 0,0x716C, 0, 0,0x716D,0x716E,0x716F,
+0x7171,0x7170,0x4555, 0, 0, 0, 0, 0,
+ 0,0x7172, 0,0x367A, 0,0x7174,0x522E,0x5E47,
+0x4B4A, 0, 0,0x335C, 0,0x3522, 0,0x3922,
+ 0, 0,0x4474,0x7175, 0, 0,0x7176, 0,
+ 0, 0,0x4144,0x417B,0x5630,0x7177, 0, 0,
+ 0, 0,0x7178, 0,0x412A, 0, 0, 0,
+0x4638, 0,0x3E5B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7179,0x344F, 0, 0, 0, 0, 0,
+ 0,0x717A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6D32,
+0x6D31, 0, 0,0x4B60,0x525E, 0,0x4B41,0x5558,
+ 0,0x4862, 0,0x405F,0x3C21, 0, 0, 0,
+ 0, 0, 0,0x6B41, 0, 0,0x5024, 0,
+0x5662, 0,0x3647,0x3858,0x6B40,0x384E, 0,0x6B3F,
+0x3326,0x3949,0x562B, 0,0x3774,0x374A, 0, 0,
+ 0,0x3C67,0x373E,0x6B46, 0,0x6B47,0x3039,0x3F4F,
+ 0,0x6B45,0x537D, 0,0x6B48, 0, 0,0x6B49,
+ 0, 0,0x374E, 0,0x6B42,0x6B44,0x4976,0x5657,
+0x554D,0x5032,0x6B4F,0x4E38,0x6B50, 0,0x3528, 0,
+ 0, 0, 0, 0,0x3133,0x6B52,0x4C25, 0,
+ 0, 0, 0, 0, 0, 0,0x4556,0x6B53,
+ 0,0x6B51,0x455F,0x6B4E,0x4A24,0x6B55,0x307B, 0,
+ 0,0x3A7A, 0, 0,0x5837,0x7163, 0,0x6B4A,
+0x6B4B,0x6B4C,0x6B4D,0x6B56,0x6640,0x6B59, 0,0x3F68,
+0x5248,0x6B57,0x6B5C,0x386C,0x6B58, 0,0x3D3A, 0,
+0x5058, 0,0x3037, 0,0x6B5D,0x445C, 0, 0,
+ 0, 0,0x562C, 0, 0, 0,0x3460, 0,
+ 0,0x4276,0x3C39, 0, 0,0x6B5A,0x6B5B,0x5460,
+0x466A,0x4454,0x6B5F,0x4527,0x5975, 0,0x3231, 0,
+0x6B64, 0,0x3D45, 0, 0, 0,0x6B62, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6B63, 0, 0,0x382C,
+ 0,0x4D51,0x6B65, 0, 0, 0,0x6B61, 0,
+0x4133, 0, 0, 0, 0, 0,0x4622, 0,
+ 0, 0, 0, 0, 0, 0,0x4C73, 0,
+0x6B66, 0,0x4030,0x5238,0x6B67, 0, 0, 0,
+0x382F,0x382D, 0,0x6B68,0x473B,0x4D73, 0, 0,
+ 0,0x6B6A,0x6B6B, 0, 0, 0, 0, 0,
+0x6B6D, 0, 0, 0, 0,0x5048, 0,0x6B72,
+ 0,0x6B6E, 0, 0, 0,0x6B71,0x4879, 0,
+0x517C,0x6B6C, 0, 0,0x6B69, 0, 0, 0,
+ 0,0x3839,0x4F59,0x4465,0x6B6F,0x6B70,0x4C5A,0x4D48,
+0x3072, 0,0x6B76, 0, 0, 0, 0, 0,
+0x6B75, 0,0x3232, 0, 0, 0, 0,0x3860,
+ 0,0x6B77, 0, 0, 0, 0, 0, 0,
+0x316C, 0, 0,0x4C45,0x4424,0x4F25, 0, 0,
+ 0, 0, 0,0x6B79, 0, 0,0x6C22, 0,
+0x4572, 0,0x6B7A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4945, 0, 0, 0, 0,
+ 0, 0,0x625F,0x6B7E, 0, 0, 0, 0,
+0x4D4E,0x6C21,0x315B,0x5337, 0, 0,0x525C, 0,
+ 0, 0,0x6B7D, 0,0x6B7B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x333C, 0, 0, 0,0x6A30,
+ 0, 0,0x5754, 0,0x742B,0x3374, 0, 0,
+ 0, 0, 0,0x5641,0x5642, 0, 0, 0,
+ 0, 0, 0,0x5569,0x3E4A, 0,0x7427, 0,
+0x5228,0x7428,0x7429, 0,0x742A,0x3E4B,0x535F, 0,
+ 0, 0, 0, 0,0x4960,0x4961, 0, 0,
+0x7342, 0,0x4A66, 0,0x4C72, 0, 0, 0,
+ 0, 0, 0,0x6236,0x4B34, 0,0x4E68,0x565B,
+ 0,0x742D,0x742E,0x742F, 0, 0, 0, 0,
+0x7432, 0,0x3A3D,0x7433,0x3063,0x7430, 0,0x7431,
+0x3D22,0x3255, 0,0x7436,0x7437,0x3666,0x3230,0x4F4F,
+0x7434,0x342C, 0,0x7435, 0, 0,0x7438, 0,
+ 0, 0, 0, 0,0x7439, 0, 0,0x4D27,
+ 0,0x743A, 0,0x743B, 0, 0, 0,0x743C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4B52, 0,0x743D, 0, 0, 0, 0,0x743E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x743F, 0, 0, 0, 0, 0,0x745E,0x413C,
+0x3C68, 0,0x492B,0x515E,0x6575, 0, 0, 0,
+ 0,0x5C33,0x5255, 0, 0,0x5C34,0x302C,0x5C35,
+ 0, 0,0x3D5A, 0,0x5C39, 0, 0, 0,
+0x5842, 0,0x5C37,0x5373, 0,0x4956,0x5C3A,0x5C36,
+ 0,0x5C3B,0x4322, 0, 0, 0, 0,0x5C3C,
+0x5C45,0x5C3D, 0, 0,0x4E5F,0x5625, 0,0x5C4F,
+ 0,0x5C4D, 0, 0,0x5C52,0x3D66,0x422B, 0,
+0x5C38,0x5C4B,0x5C4E,0x5C3E,0x3752,0x3045,0x5C47,0x503E,
+0x5C41,0x3B28, 0,0x373C,0x5C4C, 0, 0,0x5C46,
+0x5C3F,0x475B, 0, 0, 0,0x513F,0x5C40, 0,
+ 0,0x5C4A, 0, 0,0x5C50, 0, 0,0x4E2D,
+0x5C42, 0,0x5C43,0x5C48,0x5C49,0x3254,0x5C51,0x4B55,
+ 0,0x5437,0x5C5B,0x5C5F,0x4C26,0x5C66, 0,0x4367,
+0x5C5C, 0, 0,0x3F41,0x5C59, 0,0x307A,0x3936,
+0x5C65,0x5C53, 0,0x5C44,0x5C56,0x4874,0x3F60, 0,
+ 0, 0, 0,0x493B, 0, 0, 0,0x313D,
+ 0,0x5322, 0, 0,0x5C5A, 0, 0,0x5C55,
+ 0,0x463B, 0,0x5C5E, 0, 0, 0, 0,
+ 0,0x5742,0x432F,0x3736,0x4751,0x4329,0x5C62,0x5C58,
+0x5C6B,0x5C54, 0, 0,0x5C5D, 0,0x3E25,0x5C57,
+ 0,0x5C60, 0, 0,0x5C63,0x5C64, 0,0x5C78,
+ 0, 0,0x5C61,0x5D22,0x5C67, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C6B,
+0x3444, 0, 0,0x4323,0x3267,0x5C7A, 0,0x5C72,
+ 0,0x5C6F, 0,0x5C7C,0x5C6E,0x5270,0x3268, 0,
+0x4857,0x4863,0x5C7B, 0,0x5C6D, 0, 0, 0,
+0x5C77, 0, 0,0x5C75, 0, 0,0x3E23,0x5C74,
+ 0,0x325D, 0, 0, 0, 0, 0,0x5C73,
+0x3C76,0x5C68,0x3B44, 0,0x4073, 0, 0, 0,
+ 0, 0,0x3C54,0x5C69,0x5C6A, 0,0x5C71,0x5C76,
+0x5C79,0x3534, 0,0x4859,0x3B67,0x5C7E,0x5C7D,0x532B,
+0x5D21,0x5D23,0x5D25,0x5271,0x5D24,0x5D26,0x5D27,0x5229,
+ 0, 0, 0, 0, 0, 0, 0,0x3A49,
+0x5D29, 0, 0,0x5D36,0x5D31,0x5D34, 0, 0,
+ 0, 0, 0, 0, 0,0x5D30,0x464E, 0,
+ 0,0x4072, 0, 0, 0, 0,0x492F, 0,
+ 0, 0,0x5C6C,0x5D2E, 0, 0, 0, 0,
+0x5D37, 0, 0,0x5C70,0x5D2F, 0,0x5D38, 0,
+0x5D2C, 0, 0, 0, 0, 0, 0, 0,
+0x5D39,0x5D33,0x5D2D,0x442A, 0, 0, 0, 0,
+0x5D28,0x4033,0x412B,0x5D2A,0x5D2B, 0,0x5D32,0x3B71,
+0x5D35,0x5328,0x5D3A, 0,0x5D3B,0x4327, 0, 0,
+0x5D52,0x5D3C, 0, 0, 0,0x5D51, 0,0x393D,
+ 0, 0,0x3E55, 0,0x3E7A, 0, 0,0x3A4A,
+ 0, 0, 0, 0,0x5D4A, 0,0x5D45, 0,
+0x5D3F, 0, 0, 0,0x324B,0x5D43, 0,0x5D4B,
+0x3224,0x5D55, 0, 0, 0,0x5D3E, 0, 0,
+ 0,0x4650,0x5D50, 0, 0, 0, 0, 0,
+0x5D54,0x4162,0x3746, 0, 0, 0, 0, 0,
+0x5D4E,0x5D4F, 0, 0, 0,0x5D44, 0, 0,
+ 0,0x5D3D, 0,0x5D4D,0x4C51, 0,0x5D49, 0,
+ 0, 0, 0,0x5D42,0x4348,0x463C,0x4E2E,0x5D4C,
+ 0,0x5D48, 0, 0, 0, 0, 0, 0,
+0x5D41, 0, 0, 0,0x5D46,0x425C, 0, 0,
+ 0, 0, 0, 0,0x5329,0x532A,0x5D53,0x4F74,
+0x4878, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D66, 0, 0, 0, 0, 0, 0,
+0x5D47, 0, 0, 0,0x5D60,0x4264, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5D61, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D57, 0, 0, 0, 0, 0,0x5678,
+ 0,0x5D59,0x5D58,0x3870,0x5D56, 0, 0, 0,
+ 0,0x464F, 0,0x362D, 0, 0, 0, 0,
+ 0,0x5D62, 0,0x3A79,0x5461,0x5D67, 0, 0,
+ 0,0x3450, 0,0x5D5A, 0,0x3F7B,0x5D63, 0,
+0x5D5F, 0,0x5D5D, 0, 0, 0, 0, 0,
+ 0, 0,0x3559, 0, 0, 0, 0,0x5D5B,
+0x5D5C,0x5D5E, 0,0x3D2F,0x5D64, 0,0x5D65, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5D75,
+ 0,0x4349, 0, 0,0x4B62, 0, 0, 0,
+ 0,0x5D72, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5861,
+ 0, 0,0x4651, 0,0x5D74, 0, 0, 0,
+0x5574,0x5D73,0x5D70, 0, 0,0x5D6C, 0,0x5D6F,
+ 0,0x5D68, 0, 0,0x506E, 0, 0, 0,
+ 0,0x4858,0x5D6E, 0, 0,0x5D69, 0, 0,
+0x5D6A,0x4B72, 0,0x5D6D, 0, 0,0x314D, 0,
+ 0, 0, 0, 0, 0,0x4036, 0,0x3C3B,
+0x5D71, 0, 0,0x5D77, 0,0x5D76,0x5D6B, 0,
+ 0, 0, 0, 0,0x456E, 0, 0, 0,
+0x5D7B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5E24, 0, 0,0x5E23,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5D78, 0, 0, 0,
+ 0,0x436F, 0,0x427B, 0, 0, 0,0x5561,
+ 0, 0,0x4E35, 0, 0, 0, 0,0x5D7D,
+ 0,0x324C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4468,0x4A5F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x473E,
+0x5D7A,0x5D7C,0x5D7E,0x5E22,0x302A,0x314E, 0, 0,
+ 0, 0, 0,0x5E2C, 0, 0, 0, 0,
+0x5E26,0x3D36,0x486F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5E21, 0,
+ 0,0x5E25, 0, 0, 0, 0,0x5E29, 0,
+ 0, 0, 0, 0,0x5E28, 0, 0, 0,
+0x5E27, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5E2D, 0,0x544C, 0, 0, 0,
+ 0,0x5E33,0x5E2A,0x5E2E, 0, 0,0x4059, 0,
+ 0, 0, 0, 0,0x3121,0x5E36, 0,0x5E31,
+ 0, 0, 0, 0, 0, 0, 0,0x5E32,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5126,0x5E35, 0, 0, 0,
+ 0, 0, 0, 0,0x5E2F, 0, 0, 0,
+0x5E30, 0,0x503D, 0, 0, 0,0x5E34,0x4A6D,
+0x5E39, 0, 0, 0, 0, 0, 0,0x5E38,
+ 0,0x5E37, 0, 0, 0, 0, 0, 0,
+ 0,0x5E3B, 0, 0, 0, 0, 0, 0,
+ 0,0x3D65, 0, 0, 0, 0, 0,0x3258,
+0x436A, 0, 0,0x5E3A, 0,0x453A, 0, 0,
+ 0, 0, 0, 0,0x5E3C, 0, 0, 0,
+ 0, 0, 0, 0,0x4C59, 0, 0, 0,
+ 0,0x372A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5465, 0, 0, 0,0x5E3D,
+ 0, 0, 0, 0, 0,0x5E3F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4422, 0, 0, 0, 0,0x5E41, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5E3E,
+ 0,0x5E40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x553A, 0, 0, 0,0x5E42, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x722E,0x3B22,0x4232,
+0x4530,0x4247, 0, 0,0x722F, 0, 0, 0,
+ 0, 0,0x5069, 0, 0, 0,0x535D, 0,
+ 0, 0,0x6B3D, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3366,0x7230, 0,0x7231, 0,
+ 0,0x4A2D, 0, 0, 0, 0, 0, 0,
+ 0,0x3A67,0x7233,0x7235,0x7234,0x4B64,0x4F3A,0x7232,
+0x4A34,0x524F,0x426C, 0, 0, 0, 0, 0,
+ 0, 0,0x4E43,0x7238,0x3076,0x7237, 0, 0,
+ 0, 0, 0,0x723E, 0,0x324F, 0, 0,
+ 0, 0, 0, 0,0x5141,0x723A, 0, 0,
+ 0, 0, 0,0x723C,0x5469, 0, 0,0x723B,
+0x7236,0x723F,0x723D, 0,0x7239, 0, 0,0x7247,
+0x7244,0x7246, 0, 0,0x724A,0x7242,0x7240, 0,
+ 0, 0,0x7245, 0, 0, 0, 0, 0,
+0x567B, 0, 0, 0,0x7241, 0,0x4779,0x495F,
+ 0,0x7248,0x3946,0x3530, 0, 0,0x7243,0x7249,
+0x7250,0x7256, 0, 0,0x3B57, 0, 0, 0,
+0x7255,0x4D5C, 0,0x566B, 0, 0,0x7252,0x7254,
+ 0, 0, 0, 0,0x3872, 0, 0, 0,
+ 0,0x724B, 0, 0, 0,0x724E,0x4279, 0,
+0x555D,0x724C,0x724D,0x724F,0x7253, 0, 0, 0,
+0x7259,0x533C, 0, 0, 0, 0,0x366A, 0,
+0x4A71, 0,0x3764,0x7257, 0, 0, 0,0x7258,
+0x725A,0x725D,0x725B, 0, 0,0x725C, 0, 0,
+ 0, 0,0x5151,0x7251, 0,0x4D49, 0,0x4E4F,
+0x5629, 0,0x7263, 0,0x435B, 0,0x7260, 0,
+ 0,0x402F,0x726C,0x725E, 0,0x7261, 0, 0,
+ 0,0x7268, 0, 0, 0, 0,0x7262, 0,
+ 0,0x7267, 0, 0,0x7266, 0, 0,0x7269,
+ 0, 0, 0,0x725F, 0, 0,0x7264,0x726A,
+ 0, 0, 0, 0, 0, 0, 0,0x532C,
+0x7265,0x3275, 0, 0,0x7272, 0,0x502B, 0,
+ 0, 0, 0,0x7275, 0, 0, 0,0x3B48,
+ 0,0x7279, 0, 0, 0, 0, 0, 0,
+0x7270, 0, 0,0x7276,0x7278,0x727A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7273, 0,
+0x7271, 0, 0, 0,0x3A7B, 0,0x357B, 0,
+ 0, 0, 0,0x726F,0x7277,0x726D,0x726E, 0,
+ 0, 0,0x726B,0x7326, 0,0x7323, 0, 0,
+0x7322, 0, 0,0x7274, 0,0x485A, 0, 0,
+ 0, 0, 0,0x727B, 0, 0, 0,0x7325,
+ 0, 0, 0, 0, 0, 0, 0,0x4378,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x727D, 0, 0,0x7327,0x7329,0x7324, 0,0x727C,
+ 0, 0, 0,0x732B, 0,0x732A, 0, 0,
+ 0, 0,0x425D, 0, 0,0x732E, 0, 0,
+0x7330, 0, 0, 0, 0, 0,0x7321, 0,
+ 0, 0,0x7331,0x732C, 0, 0, 0, 0,
+ 0,0x732F,0x727E,0x732D, 0, 0, 0, 0,
+ 0, 0, 0,0x7332, 0, 0, 0, 0,
+0x7334, 0, 0, 0, 0,0x7328, 0, 0,
+ 0, 0,0x7333, 0, 0, 0,0x7335, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5037, 0, 0, 0, 0,0x7338, 0,
+ 0, 0, 0,0x5979, 0, 0, 0, 0,
+ 0, 0,0x7339, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7337, 0,0x4864,0x7336, 0,
+ 0, 0, 0,0x733A, 0, 0, 0, 0,
+ 0,0x733B,0x3440, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6E43, 0, 0, 0, 0, 0,
+ 0,0x733C, 0, 0,0x733D, 0, 0, 0,
+0x512A, 0, 0, 0,0x742C,0x5046, 0, 0,
+ 0, 0, 0, 0,0x5050,0x515C, 0, 0,
+ 0, 0, 0, 0,0x4F4E, 0, 0,0x3D56,
+ 0,0x5143, 0, 0, 0, 0, 0, 0,
+ 0,0x3A62,0x6169,0x5242,0x7142,0x3239, 0, 0,
+0x316D,0x7143, 0,0x4940,0x3344, 0,0x5972, 0,
+0x4B25, 0,0x7144, 0, 0, 0, 0,0x5654,
+ 0, 0, 0, 0, 0,0x7145,0x7440,0x7146,
+ 0,0x542C,0x7147, 0,0x3040,0x7441, 0, 0,
+0x7442, 0, 0,0x347C, 0,0x455B, 0, 0,
+ 0, 0,0x4C3B, 0, 0, 0,0x5064, 0,
+ 0, 0, 0, 0,0x4D60, 0, 0, 0,
+ 0, 0,0x7148, 0,0x5973, 0, 0, 0,
+ 0, 0, 0,0x313B, 0,0x4F2E, 0, 0,
+ 0,0x3824, 0, 0, 0, 0, 0,0x714A,
+ 0, 0, 0, 0,0x714B, 0, 0, 0,
+ 0,0x3243,0x4151, 0, 0,0x5730,0x7149, 0,
+ 0,0x714C, 0, 0, 0, 0,0x714E, 0,
+ 0, 0,0x5976, 0,0x5261,0x5423, 0, 0,
+0x7443,0x4839, 0, 0, 0, 0, 0,0x7444,
+ 0, 0,0x714D,0x714F,0x3F63,0x7150, 0, 0,
+0x7154, 0, 0, 0, 0, 0, 0, 0,
+0x7156,0x7151, 0,0x4951,0x4561, 0, 0, 0,
+0x4263,0x397C, 0, 0,0x7153, 0,0x7155, 0,
+ 0, 0,0x3953, 0, 0, 0, 0, 0,
+ 0, 0,0x715B, 0, 0, 0, 0, 0,
+0x3A56, 0,0x307D,0x7159, 0, 0, 0, 0,
+ 0,0x7158,0x7152,0x715A, 0, 0, 0, 0,
+ 0,0x7157, 0, 0, 0,0x486C, 0, 0,
+ 0, 0,0x4D4A,0x715D, 0, 0, 0, 0,
+0x653D, 0, 0, 0,0x715C, 0,0x715E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x715F, 0, 0,0x4F65, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7445,0x3D73,
+ 0, 0, 0, 0, 0, 0,0x7160, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7161, 0, 0, 0,0x4E77,
+ 0,0x522A, 0,0x717B, 0, 0,0x3832, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3C7B,0x395B, 0,0x3966,0x4359,0x4A53,0x6A68,
+0x4040,0x3E75,0x6A69,0x6A6A,0x6A6B, 0,0x6A6C,0x6A6D,
+0x6A6E,0x6A6F,0x3D47, 0, 0, 0,0x757B, 0,
+ 0, 0,0x757D, 0,0x757E, 0,0x757C, 0,
+ 0, 0, 0,0x3D62, 0,0x7621,0x3425, 0,
+ 0, 0, 0,0x7622, 0, 0, 0,0x7623,
+ 0, 0, 0,0x6C32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5154, 0, 0, 0, 0, 0, 0,0x596A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7624, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E3A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5532, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x537E,0x4C5C, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4A44, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6540,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7625, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E2F, 0,
+ 0, 0, 0, 0,0x4629, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5A25,0x3C46,0x3629,0x383C,0x484F,0x3C25,0x5A26,0x5A27,
+0x4C56,0x4843,0x5A28,0x467D, 0,0x5135,0x5269,0x5136,
+0x3C47, 0,0x3D32,0x3B64,0x5A29,0x5A2A,0x5148,0x5A2B,
+0x506D,0x366F,0x425B, 0,0x4B4F,0x376D,0x4968,0x3743,
+0x3E77,0x5624,0x5A2C,0x5A2D,0x4640,0x5767,0x4A36, 0,
+0x5529,0x4B5F,0x556F,0x5A2E,0x565F,0x344A,0x5A30,0x5A2F,
+ 0,0x526B,0x5A31,0x5A32,0x5A33,0x4A54,0x5A34,0x4A2B,
+0x5A35,0x5A36,0x334F,0x566F,0x5A37,0x3B30,0x352E,0x5A38,
+0x5A39,0x396E,0x512F,0x5268,0x5A3A,0x3843,0x4F6A,0x326F,
+0x5A3B,0x5A3C, 0,0x3D6B,0x4E5C,0x536F,0x5A3D,0x4E73,
+0x5A3E,0x5355,0x3B65,0x5A3F,0x4B35,0x4B50,0x5A40,0x476B,
+0x566E,0x5A41,0x4535,0x3641,0x5A42,0x374C,0x3F4E,0x5A43,
+0x5A44,0x4B2D,0x5A45,0x3577,0x5A46,0x4142,0x573B,0x5A47,
+0x4C38, 0,0x526A,0x4431,0x5A48,0x357D,0x3B51,0x5A49,
+0x5033,0x5A4A,0x5A4B,0x4E3D,0x5A4C,0x5A4D,0x5A4E,0x3277,
+0x5A51,0x5A4F,0x5168,0x5A50,0x4355,0x5A52, 0,0x5A53,
+0x5A54,0x5A55,0x503B,0x5225,0x3079,0x5A56,0x472B,0x5A57,
+0x3D77,0x4321,0x5A58,0x5A59,0x437D,0x4C37,0x5A5A,0x5A5B,
+0x403E,0x4657,0x5A5C,0x5A5D,0x4734,0x5A5E,0x5A5F,0x3948,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3B6D, 0, 0, 0, 0,0x3639,0x7478,
+ 0,0x7479, 0, 0,0x4D63, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7539, 0, 0,
+ 0, 0,0x6B60, 0, 0, 0, 0, 0,
+ 0,0x4F73,0x3B3F, 0, 0, 0, 0, 0,
+ 0, 0,0x3A40,0x5425, 0, 0, 0, 0,
+ 0, 0, 0,0x6159, 0, 0, 0, 0,
+0x7574,0x312A,0x3272, 0, 0, 0, 0, 0,
+ 0, 0,0x7575, 0, 0,0x7577, 0, 0,
+ 0,0x3A51,0x7576, 0,0x4332, 0, 0, 0,
+ 0, 0, 0, 0,0x7579, 0, 0, 0,
+0x7578, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3134,0x556A,0x383A,
+ 0,0x3931,0x3246,0x5470,0x4F4D,0x305C,0x554B,0x3B75,
+0x564A,0x3737,0x4C30,0x4636,0x3161,0x393A,0x567C,0x3961,
+0x3721,0x3C7A,0x6A5A,0x6A5B,0x4C79,0x3973,0x6A5C,0x347B,
+0x4333,0x3751,0x3A58,0x6A5D,0x5474,0x6A5E,0x3C56,0x3B5F,
+0x6A5F,0x415E,0x4238,0x545F,0x574A,0x6A60,0x6A61,0x6A64,
+0x6A62,0x6A63,0x495E,0x3833,0x3644,0x6A65,0x4A6A,0x494D,
+0x344D, 0, 0,0x6259,0x4562,0x6A66,0x4035, 0,
+0x5738,0x6A67,0x572C,0x487C,0x5853,0x584D,0x545E, 0,
+0x5479,0x4944,0x532E,0x3853,0x3360, 0,0x4962,0x7476,
+ 0, 0, 0,0x3A55, 0,0x7477, 0, 0,
+0x575F, 0, 0,0x7471,0x3830,0x5554,0x384F,0x4670,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3343, 0, 0,0x7472,0x332C, 0, 0,
+ 0, 0,0x543D,0x4777, 0, 0, 0, 0,
+ 0,0x7474, 0, 0,0x7473, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4C4B,
+ 0, 0, 0,0x4824, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7475, 0,0x5763,0x453F,0x7540, 0, 0,
+0x753B, 0,0x7543, 0,0x7542, 0,0x563A,0x7541,
+ 0, 0, 0,0x543E,0x7544, 0,0x754C, 0,
+ 0, 0, 0,0x304F,0x3578, 0,0x7549,0x754A,
+ 0,0x455C, 0, 0, 0, 0,0x7545,0x7546,
+ 0, 0,0x7547,0x754B, 0,0x3E60,0x7548,0x387A,
+ 0, 0, 0,0x7550,0x7553, 0, 0, 0,
+0x3F67, 0,0x3972,0x753C,0x754D, 0, 0,0x4237,
+ 0, 0, 0,0x4C78, 0,0x3C79, 0,0x754E,
+0x754F,0x7551,0x3665,0x7552, 0,0x7555, 0, 0,
+ 0, 0, 0, 0, 0,0x753D, 0, 0,
+ 0,0x7554,0x533B, 0,0x336C, 0, 0,0x4C24,
+ 0, 0, 0, 0,0x7556, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7557,0x3E61,0x7558,
+ 0, 0,0x4C5F,0x755B, 0, 0, 0, 0,
+ 0,0x3248,0x5759, 0,0x7559, 0,0x755A,0x755C,
+ 0,0x7562, 0, 0, 0,0x7560, 0, 0,
+ 0,0x755F,0x755D, 0, 0,0x7561, 0, 0,
+0x755E,0x7564,0x7565, 0,0x4C63, 0, 0,0x653F,
+0x3538,0x7563,0x7568,0x4C23, 0, 0, 0, 0,
+ 0,0x7566,0x7567, 0, 0, 0, 0, 0,
+ 0,0x753E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3144, 0,
+ 0,0x753F, 0, 0,0x3545,0x3264, 0,0x756C,
+0x7569, 0,0x3657, 0,0x756D, 0,0x756A, 0,
+ 0, 0, 0, 0,0x756B, 0, 0,0x345A,
+ 0,0x546A, 0, 0, 0,0x756E, 0,0x3379,
+ 0, 0, 0, 0, 0, 0, 0,0x756F,
+0x7571, 0, 0, 0,0x7570, 0, 0, 0,
+ 0, 0, 0, 0,0x7572, 0,0x7573, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x496D,0x392A, 0, 0,0x477B,
+ 0, 0,0x3663, 0, 0, 0, 0, 0,
+ 0, 0,0x4C49, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A26, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3335,0x547E,
+0x396C,0x5079, 0,0x696D,0x572A,0x696E,0x4256,0x486D,
+0x3A64,0x696F,0x6970,0x6971,0x5661,0x6972,0x6973,0x6975,
+0x6974,0x6976,0x6977,0x4761,0x6978,0x5458,0x6979,0x3D4E,
+ 0,0x697A,0x697B,0x3D4F,0x697C,0x3828,0x413E,0x697D,
+0x3132,0x3B54,0x3975,0x697E, 0,0x6A21,0x6A22,0x6A23,
+0x3778,0x3C2D, 0,0x4A64,0x604E,0x542F,0x4F3D,0x5537,
+0x6A24,0x555E,0x6A25,0x5041,0x393C, 0,0x3447,0x3159,
+ 0, 0, 0,0x4031, 0, 0, 0, 0,
+0x3166,0x3167, 0,0x3168, 0, 0, 0, 0,
+0x333D,0x4868, 0, 0, 0, 0,0x6541, 0,
+ 0,0x315F, 0, 0, 0,0x4149,0x346F, 0,
+ 0,0x4728,0x5358, 0,0x4679,0x5138, 0,0x397D,
+0x4275, 0, 0, 0, 0, 0,0x532D, 0,
+0x544B,0x3D7C, 0,0x6542,0x3735,0x6543, 0, 0,
+0x3B39,0x5562, 0,0x3D78,0x5436,0x4E25,0x412C,0x3359,
+ 0, 0,0x4C76, 0,0x6546,0x6544,0x6548, 0,
+0x654A,0x6547,0x354F,0x4648, 0,0x357C,0x6545, 0,
+0x4A76, 0, 0,0x6549, 0, 0, 0,0x4354,
+0x3145,0x3C23, 0, 0, 0,0x5737, 0, 0,
+0x4D4B,0x4B4D,0x4A4A,0x4C53,0x654C,0x654B,0x4466, 0,
+ 0,0x5121,0x5137,0x654D, 0,0x6550, 0,0x4D38,
+0x5670,0x654F,0x355D, 0,0x4D3E, 0,0x6551,0x363A,
+ 0, 0,0x4D28,0x3964, 0,0x4A45,0x3351,0x4B59,
+0x546C,0x6552,0x376A, 0, 0, 0,0x654E, 0,
+ 0, 0, 0, 0, 0,0x6555,0x347E,0x6556,
+ 0, 0, 0, 0, 0,0x6553,0x6554, 0,
+0x525D, 0, 0,0x425F,0x3146, 0,0x5362, 0,
+ 0,0x365D,0x4B6C, 0,0x6557, 0, 0,0x5376,
+ 0, 0, 0, 0, 0,0x3169, 0,0x3674,
+0x655A,0x6558,0x6559,0x3540, 0, 0, 0,0x5245,
+0x655C, 0, 0,0x655E, 0, 0, 0, 0,
+ 0, 0,0x655D,0x4732, 0,0x5223, 0, 0,
+0x655B, 0, 0, 0, 0,0x5462,0x555A, 0,
+ 0, 0, 0, 0,0x6560,0x5771, 0, 0,
+ 0, 0, 0, 0, 0,0x6561, 0,0x315C,
+0x517B, 0,0x6562,0x6564, 0, 0, 0, 0,
+0x6563, 0, 0,0x6565, 0, 0, 0, 0,
+ 0,0x5258, 0,0x354B, 0,0x675F, 0,0x5A75,
+ 0,0x5A78, 0,0x5A76, 0,0x5A77, 0, 0,
+ 0,0x5A7A,0x504F,0x4447, 0, 0,0x306E, 0,
+ 0, 0,0x5030, 0,0x5A79, 0,0x534A,0x3A2A,
+0x5B22,0x4771, 0,0x5A7C,0x5A7B,0x495B,0x5A7D, 0,
+0x5B21,0x575E,0x5A7E,0x415A, 0, 0,0x5B25, 0,
+ 0,0x5374, 0, 0,0x5B27,0x5B24, 0,0x5B28,
+ 0, 0,0x3D3C, 0, 0, 0,0x4049,0x5B23,
+0x5B26,0x5623, 0,0x5B29, 0, 0, 0,0x5B2D,
+ 0, 0, 0,0x5B2E,0x5B2C,0x3A42, 0, 0,
+ 0,0x3F24,0x5B2B, 0, 0, 0,0x5B2A,0x5447,
+0x323F, 0, 0,0x5B2F, 0,0x3979, 0,0x5B30,
+ 0, 0, 0, 0,0x333B, 0, 0, 0,
+0x3526, 0, 0, 0, 0,0x363C,0x5B31, 0,
+ 0, 0,0x3675, 0,0x5B32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3149, 0, 0, 0, 0,0x5B34, 0,
+ 0, 0,0x5B33,0x5B35, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5B37,
+ 0,0x5B36, 0, 0, 0, 0, 0, 0,
+ 0,0x5B38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5B39, 0, 0,0x5B3A, 0,
+ 0,0x534F,0x747A,0x4775,0x5743,0x4564,0x747C,0x747D,
+0x747B, 0,0x3E46, 0, 0, 0, 0,0x506F,
+ 0, 0,0x3753, 0, 0,0x544D,0x4C2A, 0,
+ 0,0x7522,0x7521,0x3A28,0x747E,0x4B56, 0, 0,
+ 0,0x7524,0x4052, 0,0x336A, 0,0x4D2A,0x7525,
+0x7523,0x3D34,0x7528, 0,0x7529,0x3D4D,0x4338,0x3F61,
+0x4B61,0x752A, 0, 0, 0,0x7526,0x7527,0x4470,
+ 0, 0, 0, 0, 0,0x752C, 0,0x343C,
+ 0,0x576D, 0,0x3457,0x752B,0x752E, 0, 0,
+0x752D,0x752F,0x5051, 0, 0, 0, 0, 0,
+ 0, 0,0x4351,0x4829, 0, 0, 0, 0,
+ 0, 0,0x7530,0x7531, 0, 0, 0, 0,
+ 0, 0,0x7532, 0, 0,0x7533,0x7534,0x7535,
+ 0, 0, 0, 0,0x7537,0x7536, 0, 0,
+ 0, 0,0x7538, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3249,
+ 0,0x5354,0x4A4D, 0,0x406F,0x5658,0x5230,0x413F,
+ 0,0x3D70, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x382A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3C78, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7646, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7647, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7648, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7649, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x764A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x764C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x764B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7769, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x764D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x764E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6E44,0x6E45,0x6E46,
+0x556B,0x3624,0x6E48,0x6E47,0x6E49,0x6E4A,0x4725,0x6E4B,
+0x6E4C, 0,0x3730,0x3576,0x6E4D,0x6E4F, 0,0x6E4E,
+ 0,0x3846,0x6E50,0x6E51,0x6E52,0x365B,0x332E,0x5653,
+0x4446,0x3135,0x3856,0x6E53,0x6E54,0x543F,0x4755,0x3E7B,
+0x4E59,0x3933,0x6E56,0x6E55,0x6E58,0x6E57,0x4525,0x6E59,
+0x6E5A,0x472E,0x6E5B,0x472F,0x6E5C,0x3227,0x6E5D,0x6E5E,
+0x6E5F,0x6E60,0x6E61,0x576A,0x6E62,0x6E63,0x3C58,0x6E64,
+0x534B,0x4C7A,0x322C,0x4165,0x6E65,0x4726,0x432D, 0,
+0x6E66,0x6E67,0x6E68,0x6E69,0x6E6A,0x6E6B,0x6E6C, 0,
+0x6E6D,0x6E6E,0x6E6F, 0, 0,0x6E70,0x6E71,0x6E72,
+0x6E74,0x6E73, 0,0x6E75,0x4D2D,0x4241,0x6E76,0x6E77,
+0x6E78,0x5521,0x6E79,0x4F33,0x6E7A,0x6E7B, 0,0x6E7C,
+0x6E7D,0x6F21,0x6E7E,0x6F22,0x3875,0x437A,0x6F23,0x6F24,
+0x3D42,0x523F,0x3279,0x6F25,0x6F26,0x6F27,0x5278,0x6F28,
+0x567D,0x6F29,0x464C, 0,0x6F2A,0x6F2B,0x4134,0x6F2C,
+0x4F7A,0x4B78,0x6F2E,0x6F2D,0x337A,0x3978,0x6F2F,0x6F30,
+0x5062,0x6F31,0x6F32,0x3766,0x503F,0x6F33,0x6F34,0x6F35,
+0x4871,0x4C60,0x6F36,0x6F37,0x6F38,0x6F39,0x6F3A,0x5560,
+0x6F3B,0x346D,0x432A,0x6F3C, 0,0x6F3D,0x6F3E,0x6F3F,
+ 0,0x4E7D,0x6F40,0x4260,0x3438,0x5736,0x3D75, 0,
+0x4F47,0x6F43,0x6F41,0x6F42,0x6F44,0x3627,0x3C7C,0x3E62,
+0x434C,0x6F45,0x6F46, 0,0x6F47,0x6F4F,0x6F48,0x6F49,
+0x6F4A,0x4742,0x6F71,0x364D,0x6F4B, 0,0x6F4C,0x6F4D,
+0x3646,0x433E,0x6F4E, 0,0x6F50,0x6F51,0x6F52,0x5572,
+ 0,0x6F53,0x4477, 0,0x6F54,0x4478,0x6F55,0x6F56,
+0x3864,0x3077,0x6F57,0x6F58,0x6F59, 0,0x6F5A,0x6F5B,
+0x6F5C,0x6F5D, 0,0x6F5E,0x3E35,0x6F61,0x6F5F,0x6F60,
+ 0,0x6F62,0x6F63,0x414D,0x6F64,0x6F65,0x6F66,0x6F67,
+0x6F68,0x6F69,0x6F6A,0x6F6B,0x6F6C,0x4058, 0,0x6F6D,
+0x412D,0x6F6E,0x6F6F,0x6F70, 0, 0,0x4F62, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3324,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4345,0x6345,0x4941,0x6346, 0,0x3155,0x4E4A,0x3433,
+0x4872,0x6347,0x4F50,0x6348,0x3C64,0x6349,0x634A,0x4346,
+0x5522,0x4456,0x396B,0x4E45,0x634B,0x4376,0x634C, 0,
+0x3727,0x3873,0x3A52,0x634D,0x634E,0x5444,0x634F, 0,
+0x6350,0x514B,0x6351,0x6352,0x6353,0x6354,0x5156,0x6355,
+0x327B,0x403B,0x6356, 0,0x402B,0x6357,0x6358,0x6359,
+ 0,0x635A,0x635B, 0,0x3837,0x5A62, 0,0x3653,
+ 0,0x5A64,0x5A63, 0, 0, 0, 0, 0,
+ 0, 0,0x5A66, 0, 0, 0,0x486E, 0,
+ 0,0x5A65,0x3740,0x5174,0x5275,0x5573,0x3D57, 0,
+ 0, 0, 0,0x5768,0x5A68,0x5A67, 0,0x3022,
+0x4D53, 0,0x5A69, 0,0x383D,0x3C4A,0x423D,0x4224,
+0x3342,0x5A6A, 0,0x422A,0x4430,0x3D35, 0, 0,
+0x4F5E, 0, 0, 0,0x5A6B,0x4942, 0, 0,
+ 0, 0, 0,0x315D, 0, 0, 0,0x5A6C,
+ 0,0x3638,0x543A, 0,0x337D, 0, 0,0x5A6D,
+0x5449,0x4F55,0x4563, 0,0x5A6E, 0, 0, 0,
+ 0, 0,0x5A6F, 0,0x5A70,0x416A,0x4C55,0x4F5D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5367,0x4221, 0,
+0x5A71, 0, 0,0x4B65, 0,0x5A72, 0,0x4B66,
+0x527E, 0, 0, 0,0x3874, 0, 0,0x5A73,
+0x302F,0x4F36, 0, 0,0x554F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4B6D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5A74, 0, 0,0x6344, 0, 0,0x4125, 0,
+ 0,0x763F, 0, 0,0x7640,0x7641,0x4451, 0,
+0x4838,0x5163, 0, 0,0x505B,0x5145,0x3C2F,0x394D,
+ 0,0x6F74, 0, 0,0x3446,0x533A,0x7642,0x337B,
+ 0, 0,0x7643, 0, 0,0x3571, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7645, 0, 0, 0, 0, 0, 0, 0,
+0x536A,0x7627,0x5129, 0, 0, 0, 0,0x7629,
+ 0, 0, 0,0x7628, 0, 0,0x4163,0x4057,
+ 0,0x3122, 0, 0, 0, 0,0x4E6D, 0,
+0x5068,0x762B, 0, 0,0x4F76, 0,0x762A,0x5570,
+0x762C,0x4339, 0, 0, 0,0x3B74,0x762E,0x762D,
+ 0, 0, 0,0x445E, 0, 0,0x4158, 0,
+ 0, 0, 0, 0,0x4B2A, 0,0x4F3C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x762F, 0, 0,0x7630, 0, 0,
+0x7631, 0,0x4236, 0, 0, 0, 0, 0,
+0x3054,0x4579, 0, 0, 0, 0,0x7632, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4760,0x7626, 0, 0,0x3E38, 0,
+ 0,0x3E32, 0,0x3565, 0, 0,0x3747, 0,
+0x3F3F,0x4352,0x4366, 0, 0,0x584C, 0, 0,
+ 0,0x386F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3D79,0x5125, 0,0x3050, 0,
+ 0, 0, 0, 0,0x7730, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7731, 0, 0,
+ 0, 0, 0,0x502C, 0,0x3030, 0, 0,
+ 0,0x7732,0x7733, 0,0x7734, 0, 0, 0,
+0x474A, 0, 0, 0, 0, 0, 0, 0,
+0x3E4F, 0, 0,0x7737, 0, 0, 0, 0,
+ 0, 0, 0,0x7736, 0,0x315E, 0,0x7735,
+ 0, 0,0x7738, 0,0x7739, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4E24,0x484D,
+ 0,0x3A2B,0x6838,0x6839,0x683A,0x3E42, 0, 0,
+ 0, 0, 0,0x5274, 0,0x544F,0x4958, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5233,0x3625,0x476A,
+0x717C,0x4F6E,0x4B33,0x506B,0x676F,0x4D67,0x394B,0x3659,
+0x717D,0x3064,0x4B4C,0x717E,0x5424,0x422D,0x416C,0x4644,
+0x3E31,0x7221,0x3C55, 0,0x7222,0x7223, 0,0x7224,
+0x5243,0x4635, 0,0x4D47,0x7225, 0,0x5331,0x3F45,
+0x4C62, 0,0x7226,0x7227,0x5155,0x366E,0x7228,0x7229,
+0x355F,0x722A,0x722B, 0,0x327C,0x722C,0x722D,0x4827,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3767, 0,
+ 0,0x6C29,0x6C2A,0x6C2B, 0,0x6C2C, 0, 0,
+0x462E,0x6C2D,0x6C2E, 0, 0, 0,0x3749,0x4A33,
+ 0, 0, 0, 0, 0, 0, 0,0x6238,
+0x774F, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7750, 0, 0,
+0x324D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7751, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x7753,0x7752, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x623B, 0,0x3C22, 0,0x623C,
+0x623D,0x623E,0x623F,0x6240,0x6241,0x3739,0x527B,0x3D24,
+0x4A4E,0x3125,0x4B47, 0,0x6242,0x367C,0x4844,0x6243,
+ 0, 0,0x3D48, 0,0x317D,0x6244, 0,0x3676,
+0x6245,0x4459, 0, 0,0x6246,0x4F5A,0x395D,0x6247,
+0x4021, 0,0x6248,0x3276, 0,0x6249, 0,0x4173,
+0x624A,0x624B,0x4278,0x624C,0x624D,0x624E,0x4A57,0x5838,
+0x5965,0x4F63, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7025, 0, 0,
+0x5C30, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x426D,0x5426,0x4D54,0x5131,
+0x335B,0x477D, 0,0x3235,0x423F,0x6660,0x4A3B,0x6661,
+0x6662,0x3E54,0x6663,0x5724,0x4D55,0x6665,0x3C5D,0x6664,
+0x6666,0x6667,0x426E, 0,0x3D3E,0x6668,0x4266,0x3A27,
+0x6669, 0,0x666A,0x3352,0x5169, 0, 0,0x3F25,
+0x666B,0x466F,0x666C,0x666D, 0, 0,0x666E,0x462D,
+0x666F, 0,0x4927,0x6670,0x6671,0x6672,0x6539,0x6673,
+0x6674,0x4262,0x6675,0x6676,0x5668,0x6677, 0,0x6678,
+0x3947, 0, 0, 0, 0, 0, 0, 0,
+0x773B,0x773A, 0, 0, 0, 0,0x773E,0x773C,
+0x3A21, 0,0x773F, 0,0x7740, 0, 0, 0,
+0x7742,0x7741,0x7744, 0, 0,0x7743, 0, 0,
+ 0, 0, 0,0x7745,0x7746, 0, 0, 0,
+ 0,0x7747, 0,0x4B68, 0, 0, 0, 0,
+0x385F, 0, 0, 0, 0, 0, 0,0x7754,
+ 0,0x7755, 0, 0, 0, 0,0x7756, 0,
+ 0, 0, 0,0x7758, 0,0x775A, 0,0x7757,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x775B, 0,0x7759, 0, 0, 0, 0,
+ 0, 0, 0,0x5757, 0, 0, 0, 0,
+0x775C, 0, 0, 0, 0, 0, 0,0x775D,
+ 0, 0, 0,0x775E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x775F,
+ 0, 0, 0,0x7760, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5B4B,
+ 0, 0,0x582A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6577,0x396D, 0, 0, 0,
+ 0,0x3F7D,0x3B6A,0x7749,0x4647,0x7748, 0,0x774A,
+0x774C,0x774B, 0, 0, 0,0x774D, 0,0x4E3A,
+ 0,0x774E, 0, 0,0x4427};
+
+/* page 7 0x9C7C-0x9CE2 */
+static uint16 tab_uni_gb23127[]={
+0x5363, 0, 0,0x764F, 0,0x4233,0x7650, 0,
+ 0,0x7651,0x7652,0x7653,0x7654, 0, 0,0x7656,
+ 0,0x312B,0x7657, 0,0x7658,0x7659,0x765A, 0,
+0x765B,0x765C, 0, 0, 0, 0,0x765D,0x765E,
+0x4F4A, 0,0x765F,0x7660,0x7661,0x7662,0x7663,0x7664,
+0x4070,0x7665,0x7666,0x7667,0x7668,0x7669, 0,0x766A,
+ 0,0x766B,0x766C, 0,0x766D,0x766E,0x766F,0x7670,
+0x7671,0x7672,0x7673,0x7674,0x3E28, 0,0x7675,0x7676,
+0x7677,0x7678, 0, 0, 0, 0, 0,0x487A,
+0x7679,0x767A,0x767B,0x767C, 0, 0,0x767D,0x767E,
+0x7721,0x7722,0x7723,0x7724,0x7725, 0, 0,0x7726,
+0x7727,0x7728,0x316E,0x7729,0x772A,0x772B, 0, 0,
+0x772C,0x772D,0x415B,0x772E, 0, 0,0x772F};
+
+/* page 8 0x9E1F-0x9FA0 */
+static uint16 tab_uni_gb23128[]={
+0x4471,0x702F,0x3C26,0x7030,0x4379, 0,0x4538,0x513B,
+ 0,0x7031,0x7032,0x7033,0x7034,0x7035,0x513C, 0,
+0x516C, 0,0x7037,0x7036,0x5427, 0,0x4D52,0x7038,
+0x703A,0x7039,0x703B,0x703C, 0, 0,0x386B,0x703D,
+0x3A68, 0,0x703E,0x703F,0x3E69,0x7040,0x366C,0x7041,
+0x7042,0x7043,0x7044,0x4835,0x7045,0x7046, 0,0x7047,
+0x4574, 0,0x7048, 0, 0, 0,0x7049, 0,
+0x704A,0x773D, 0,0x704B,0x704C,0x704D, 0,0x704E,
+ 0, 0, 0, 0,0x704F,0x3A57, 0,0x7050,
+0x7051,0x7052,0x7053,0x7054,0x7055,0x7056,0x7058, 0,
+ 0,0x5325,0x7057, 0,0x7059, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x753A,
+0x4239, 0, 0,0x7764, 0, 0, 0, 0,
+0x7765,0x7766, 0, 0,0x7767, 0, 0, 0,
+ 0, 0, 0,0x7768,0x4234, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x776A, 0,
+0x776B, 0, 0, 0, 0, 0, 0,0x4273,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7470, 0, 0,
+ 0,0x746F, 0, 0,0x4269, 0,0x7761,0x7762,
+ 0, 0, 0, 0, 0,0x3B46, 0, 0,
+ 0, 0,0x5964, 0, 0, 0,0x4A72,0x4068,
+0x7024, 0,0x3A5A, 0, 0,0x472D, 0, 0,
+ 0,0x442C, 0, 0,0x776C,0x776D,0x776E, 0,
+0x7770,0x776F, 0,0x7771, 0, 0,0x7774, 0,
+0x7773, 0,0x7772,0x7775, 0, 0, 0, 0,
+0x7776, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6D69, 0,0x6D6A,0x6D6B, 0,0x763C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x763D, 0,0x763E,0x3626,
+ 0,0x583E, 0, 0,0x3944, 0, 0, 0,
+0x583B, 0,0x5C31, 0, 0, 0, 0, 0,
+ 0,0x4A73, 0,0x7777, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7778, 0, 0,
+0x7779, 0, 0, 0, 0, 0, 0, 0,
+0x777B, 0,0x777A, 0,0x3147, 0,0x777C,0x777D,
+ 0, 0, 0, 0, 0,0x777E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x466B,0x6C34, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x335D,0x7633, 0, 0,0x7634,0x4164,0x7635,0x7636,
+0x7637,0x7638,0x7639,0x763A,0x4823,0x763B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x417A,0x3928,0x6D68, 0, 0, 0,
+0x396A,0x595F};
+
+/* page 9 0xFF01-0xFFE5 */
+static uint16 tab_uni_gb23129[]={
+0x2321,0x2322,0x2323,0x2167,0x2325,0x2326,0x2327,0x2328,
+0x2329,0x232A,0x232B,0x232C,0x232D,0x232E,0x232F,0x2330,
+0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,
+0x2339,0x233A,0x233B,0x233C,0x233D,0x233E,0x233F,0x2340,
+0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,0x2348,
+0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F,0x2350,
+0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,0x2358,
+0x2359,0x235A,0x235B,0x235C,0x235D,0x235E,0x235F,0x2360,
+0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,0x2368,
+0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F,0x2370,
+0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,0x2378,
+0x2379,0x237A,0x237B,0x237C,0x237D,0x212B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2169,
+0x216A, 0,0x237E, 0,0x2324};
+
+static int func_uni_gb2312_onechar(int code){
+ if ((code>=0x00A4)&&(code<=0x01DC))
+ return(tab_uni_gb23120[code-0x00A4]);
+ if ((code>=0x02C7)&&(code<=0x0451))
+ return(tab_uni_gb23121[code-0x02C7]);
+ if ((code>=0x2015)&&(code<=0x2312))
+ return(tab_uni_gb23122[code-0x2015]);
+ if ((code>=0x2460)&&(code<=0x2642))
+ return(tab_uni_gb23123[code-0x2460]);
+ if ((code>=0x3000)&&(code<=0x3129))
+ return(tab_uni_gb23124[code-0x3000]);
+ if ((code>=0x3220)&&(code<=0x3229))
+ return(tab_uni_gb23125[code-0x3220]);
+ if ((code>=0x4E00)&&(code<=0x9B54))
+ return(tab_uni_gb23126[code-0x4E00]);
+ if ((code>=0x9C7C)&&(code<=0x9CE2))
+ return(tab_uni_gb23127[code-0x9C7C]);
+ if ((code>=0x9E1F)&&(code<=0x9FA0))
+ return(tab_uni_gb23128[code-0x9E1F]);
+ if ((code>=0xFF01)&&(code<=0xFFE5))
+ return(tab_uni_gb23129[code-0xFF01]);
+ return(0);
+}
+
+
+static int
+my_wc_mb_gb2312(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *s, uchar *e)
+{
+ int code;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if (wc<0x80)
+ {
+ s[0]=wc;
+ return 1;
+ }
+
+ if (!(code=func_uni_gb2312_onechar(wc)))
+ return MY_CS_ILUNI;
+
+ if(s+2>e)
+ return MY_CS_TOOSMALL;
+
+ code|=0x8080;
+ s[0]=code>>8;
+ s[1]=code&0xFF;
+ return 2;
+}
+
+static int
+my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *pwc, const uchar *s, const uchar *e){
+ int hi;
+
+ hi=s[0];
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ if(hi<0x80)
+ {
+ pwc[0]=hi;
+ return 1;
+ }
+
+ if(s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ if(!(pwc[0]=func_gb2312_uni_onechar(((hi<<8)+s[1])&0x7F7F)))
+ return MY_CS_ILSEQ;
+
+ return 2;
+}
+
+CHARSET_INFO my_charset_gb2312 =
+{
+ 24, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "gb2312", /* cs name */
+ "gb2312", /* name */
+ "", /* comment */
+ ctype_gb2312,
+ to_lower_gb2312,
+ to_upper_gb2312,
+ sort_order_gb2312,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_mb, /* wildcmp */
+ 2, /* mbmaxlen */
+ ismbchar_gb2312,
+ ismbhead_gb2312,
+ mbcharlen_gb2312,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_mb_wc_gb2312, /* mb_wc */
+ my_wc_mb_gb2312, /* wc_mb */
+ my_caseup_str_mb,
+ my_casedn_str_mb,
+ my_caseup_mb,
+ my_casedn_mb,
+ my_tosort_8bit,
+ my_strcasecmp_mb,
+ my_strncasecmp_mb,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+#endif
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 9fccce175d8..42a3686475a 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -31,6 +31,9 @@
#include "m_string.h"
#include "m_ctype.h"
+#ifdef HAVE_CHARSET_gbk
+
+
/* Support for Chinese(GBK) characters, by hewei@mail.ied.ac.cn */
#define isgbkhead(c) (0x81<=(uchar)(c) && (uchar)(c)<=0xfe)
@@ -42,7 +45,7 @@
#define gbkhead(e) ((uchar)(e>>8))
#define gbktail(e) ((uchar)(e&0xff))
-uchar NEAR ctype_gbk[257] =
+static uchar NEAR ctype_gbk[257] =
{
0, /* For standard library */
32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
@@ -63,7 +66,7 @@ uchar NEAR ctype_gbk[257] =
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
};
-uchar NEAR to_lower_gbk[]=
+static uchar NEAR to_lower_gbk[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -99,7 +102,7 @@ uchar NEAR to_lower_gbk[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR to_upper_gbk[]=
+static uchar NEAR to_upper_gbk[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -135,7 +138,7 @@ uchar NEAR to_upper_gbk[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-uchar NEAR sort_order_gbk[]=
+static uchar NEAR sort_order_gbk[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -2579,7 +2582,9 @@ static uint16 gbksortorder(uint16 i)
}
-int my_strnncoll_gbk(const uchar * s1, int len1, const uchar * s2, int len2)
+int my_strnncoll_gbk(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar * s1, uint len1,
+ const uchar * s2, uint len2)
{
uint len,c1,c2;
@@ -2603,13 +2608,20 @@ int my_strnncoll_gbk(const uchar * s1, int len1, const uchar * s2, int len2)
return (int) (len1-len2);
}
-int my_strcoll_gbk(const uchar * s1, const uchar * s2)
+static
+int my_strnncollsp_gbk(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
{
- return my_strnncoll_gbk(s1, (uint) strlen((char*) s1),
- s2, (uint) strlen((char*) s2));
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_gbk(cs,s,slen,t,tlen);
}
-int my_strnxfrm_gbk(uchar * dest, const uchar * src, int len, int srclen)
+
+int my_strnxfrm_gbk(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar * src, uint srclen)
{
uint16 e;
@@ -2629,10 +2641,6 @@ int my_strnxfrm_gbk(uchar * dest, const uchar * src, int len, int srclen)
return srclen;
}
-int my_strxfrm_gbk(uchar * dest, const uchar * src, int len)
-{
- return my_strnxfrm_gbk(dest,src,len,(uint) strlen((char*) src));
-}
/*
** Calculate min_str and max_str that ranges a LIKE string.
@@ -2652,10 +2660,10 @@ int my_strxfrm_gbk(uchar * dest, const uchar * src, int len)
*/
#define max_sort_char ((uchar) 255)
-#define wild_one '_'
-#define wild_many '%'
-extern my_bool my_like_range_gbk(const char *ptr,uint ptr_length,pchar escape,
+extern my_bool my_like_range_gbk(CHARSET_INFO *cs __attribute__((unused)),
+ const char *ptr,uint ptr_length,
+ int escape, int w_one, int w_many,
uint res_length, char *min_str,char *max_str,
uint *min_length,uint *max_length)
{
@@ -2677,13 +2685,13 @@ extern my_bool my_like_range_gbk(const char *ptr,uint ptr_length,pchar escape,
*min_str++= *max_str++ = *ptr;
continue;
}
- if (*ptr == wild_one) /* '_' in SQL */
+ if (*ptr == w_one) /* '_' in SQL */
{
*min_str++='\0'; /* This should be min char */
*max_str++=max_sort_char;
continue;
}
- if (*ptr == wild_many) /* '%' in SQL */
+ if (*ptr == w_many) /* '%' in SQL */
{
*min_length= (uint) (min_str - min_org);
*max_length= res_length;
@@ -2705,17 +2713,7227 @@ extern my_bool my_like_range_gbk(const char *ptr,uint ptr_length,pchar escape,
}
-int ismbchar_gbk(const char* p, const char *e)
+int ismbchar_gbk(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
{
return (isgbkhead(*(p)) && (e)-(p)>1 && isgbktail(*((p)+1))? 2: 0);
}
-my_bool ismbhead_gbk(uint c)
+my_bool ismbhead_gbk(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return isgbkhead(c);
}
-int mbcharlen_gbk(uint c)
+int mbcharlen_gbk(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (isgbkhead(c)? 2:0);
}
+
+/* page 0 0x8140-0xFE4F */
+static uint16 tab_gbk_uni0[]={
+0x4E02,0x4E04,0x4E05,0x4E06,0x4E0F,0x4E12,0x4E17,0x4E1F,
+0x4E20,0x4E21,0x4E23,0x4E26,0x4E29,0x4E2E,0x4E2F,0x4E31,
+0x4E33,0x4E35,0x4E37,0x4E3C,0x4E40,0x4E41,0x4E42,0x4E44,
+0x4E46,0x4E4A,0x4E51,0x4E55,0x4E57,0x4E5A,0x4E5B,0x4E62,
+0x4E63,0x4E64,0x4E65,0x4E67,0x4E68,0x4E6A,0x4E6B,0x4E6C,
+0x4E6D,0x4E6E,0x4E6F,0x4E72,0x4E74,0x4E75,0x4E76,0x4E77,
+0x4E78,0x4E79,0x4E7A,0x4E7B,0x4E7C,0x4E7D,0x4E7F,0x4E80,
+0x4E81,0x4E82,0x4E83,0x4E84,0x4E85,0x4E87,0x4E8A, 0,
+0x4E90,0x4E96,0x4E97,0x4E99,0x4E9C,0x4E9D,0x4E9E,0x4EA3,
+0x4EAA,0x4EAF,0x4EB0,0x4EB1,0x4EB4,0x4EB6,0x4EB7,0x4EB8,
+0x4EB9,0x4EBC,0x4EBD,0x4EBE,0x4EC8,0x4ECC,0x4ECF,0x4ED0,
+0x4ED2,0x4EDA,0x4EDB,0x4EDC,0x4EE0,0x4EE2,0x4EE6,0x4EE7,
+0x4EE9,0x4EED,0x4EEE,0x4EEF,0x4EF1,0x4EF4,0x4EF8,0x4EF9,
+0x4EFA,0x4EFC,0x4EFE,0x4F00,0x4F02,0x4F03,0x4F04,0x4F05,
+0x4F06,0x4F07,0x4F08,0x4F0B,0x4F0C,0x4F12,0x4F13,0x4F14,
+0x4F15,0x4F16,0x4F1C,0x4F1D,0x4F21,0x4F23,0x4F28,0x4F29,
+0x4F2C,0x4F2D,0x4F2E,0x4F31,0x4F33,0x4F35,0x4F37,0x4F39,
+0x4F3B,0x4F3E,0x4F3F,0x4F40,0x4F41,0x4F42,0x4F44,0x4F45,
+0x4F47,0x4F48,0x4F49,0x4F4A,0x4F4B,0x4F4C,0x4F52,0x4F54,
+0x4F56,0x4F61,0x4F62,0x4F66,0x4F68,0x4F6A,0x4F6B,0x4F6D,
+0x4F6E,0x4F71,0x4F72,0x4F75,0x4F77,0x4F78,0x4F79,0x4F7A,
+0x4F7D,0x4F80,0x4F81,0x4F82,0x4F85,0x4F86,0x4F87,0x4F8A,
+0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,0x4F95,0x4F96,0x4F98,
+0x4F99,0x4F9A,0x4F9C,0x4F9E,0x4F9F,0x4FA1,0x4FA2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4FA4,0x4FAB,0x4FAD,0x4FB0,0x4FB1,0x4FB2,0x4FB3,0x4FB4,
+0x4FB6,0x4FB7,0x4FB8,0x4FB9,0x4FBA,0x4FBB,0x4FBC,0x4FBD,
+0x4FBE,0x4FC0,0x4FC1,0x4FC2,0x4FC6,0x4FC7,0x4FC8,0x4FC9,
+0x4FCB,0x4FCC,0x4FCD,0x4FD2,0x4FD3,0x4FD4,0x4FD5,0x4FD6,
+0x4FD9,0x4FDB,0x4FE0,0x4FE2,0x4FE4,0x4FE5,0x4FE7,0x4FEB,
+0x4FEC,0x4FF0,0x4FF2,0x4FF4,0x4FF5,0x4FF6,0x4FF7,0x4FF9,
+0x4FFB,0x4FFC,0x4FFD,0x4FFF,0x5000,0x5001,0x5002,0x5003,
+0x5004,0x5005,0x5006,0x5007,0x5008,0x5009,0x500A, 0,
+0x500B,0x500E,0x5010,0x5011,0x5013,0x5015,0x5016,0x5017,
+0x501B,0x501D,0x501E,0x5020,0x5022,0x5023,0x5024,0x5027,
+0x502B,0x502F,0x5030,0x5031,0x5032,0x5033,0x5034,0x5035,
+0x5036,0x5037,0x5038,0x5039,0x503B,0x503D,0x503F,0x5040,
+0x5041,0x5042,0x5044,0x5045,0x5046,0x5049,0x504A,0x504B,
+0x504D,0x5050,0x5051,0x5052,0x5053,0x5054,0x5056,0x5057,
+0x5058,0x5059,0x505B,0x505D,0x505E,0x505F,0x5060,0x5061,
+0x5062,0x5063,0x5064,0x5066,0x5067,0x5068,0x5069,0x506A,
+0x506B,0x506D,0x506E,0x506F,0x5070,0x5071,0x5072,0x5073,
+0x5074,0x5075,0x5078,0x5079,0x507A,0x507C,0x507D,0x5081,
+0x5082,0x5083,0x5084,0x5086,0x5087,0x5089,0x508A,0x508B,
+0x508C,0x508E,0x508F,0x5090,0x5091,0x5092,0x5093,0x5094,
+0x5095,0x5096,0x5097,0x5098,0x5099,0x509A,0x509B,0x509C,
+0x509D,0x509E,0x509F,0x50A0,0x50A1,0x50A2,0x50A4,0x50A6,
+0x50AA,0x50AB,0x50AD,0x50AE,0x50AF,0x50B0,0x50B1,0x50B3,
+0x50B4,0x50B5,0x50B6,0x50B7,0x50B8,0x50B9,0x50BC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x50BD,0x50BE,0x50BF,0x50C0,0x50C1,0x50C2,0x50C3,0x50C4,
+0x50C5,0x50C6,0x50C7,0x50C8,0x50C9,0x50CA,0x50CB,0x50CC,
+0x50CD,0x50CE,0x50D0,0x50D1,0x50D2,0x50D3,0x50D4,0x50D5,
+0x50D7,0x50D8,0x50D9,0x50DB,0x50DC,0x50DD,0x50DE,0x50DF,
+0x50E0,0x50E1,0x50E2,0x50E3,0x50E4,0x50E5,0x50E8,0x50E9,
+0x50EA,0x50EB,0x50EF,0x50F0,0x50F1,0x50F2,0x50F4,0x50F6,
+0x50F7,0x50F8,0x50F9,0x50FA,0x50FC,0x50FD,0x50FE,0x50FF,
+0x5100,0x5101,0x5102,0x5103,0x5104,0x5105,0x5108, 0,
+0x5109,0x510A,0x510C,0x510D,0x510E,0x510F,0x5110,0x5111,
+0x5113,0x5114,0x5115,0x5116,0x5117,0x5118,0x5119,0x511A,
+0x511B,0x511C,0x511D,0x511E,0x511F,0x5120,0x5122,0x5123,
+0x5124,0x5125,0x5126,0x5127,0x5128,0x5129,0x512A,0x512B,
+0x512C,0x512D,0x512E,0x512F,0x5130,0x5131,0x5132,0x5133,
+0x5134,0x5135,0x5136,0x5137,0x5138,0x5139,0x513A,0x513B,
+0x513C,0x513D,0x513E,0x5142,0x5147,0x514A,0x514C,0x514E,
+0x514F,0x5150,0x5152,0x5153,0x5157,0x5158,0x5159,0x515B,
+0x515D,0x515E,0x515F,0x5160,0x5161,0x5163,0x5164,0x5166,
+0x5167,0x5169,0x516A,0x516F,0x5172,0x517A,0x517E,0x517F,
+0x5183,0x5184,0x5186,0x5187,0x518A,0x518B,0x518E,0x518F,
+0x5190,0x5191,0x5193,0x5194,0x5198,0x519A,0x519D,0x519E,
+0x519F,0x51A1,0x51A3,0x51A6,0x51A7,0x51A8,0x51A9,0x51AA,
+0x51AD,0x51AE,0x51B4,0x51B8,0x51B9,0x51BA,0x51BE,0x51BF,
+0x51C1,0x51C2,0x51C3,0x51C5,0x51C8,0x51CA,0x51CD,0x51CE,
+0x51D0,0x51D2,0x51D3,0x51D4,0x51D5,0x51D6,0x51D7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x51D8,0x51D9,0x51DA,0x51DC,0x51DE,0x51DF,0x51E2,0x51E3,
+0x51E5,0x51E6,0x51E7,0x51E8,0x51E9,0x51EA,0x51EC,0x51EE,
+0x51F1,0x51F2,0x51F4,0x51F7,0x51FE,0x5204,0x5205,0x5209,
+0x520B,0x520C,0x520F,0x5210,0x5213,0x5214,0x5215,0x521C,
+0x521E,0x521F,0x5221,0x5222,0x5223,0x5225,0x5226,0x5227,
+0x522A,0x522C,0x522F,0x5231,0x5232,0x5234,0x5235,0x523C,
+0x523E,0x5244,0x5245,0x5246,0x5247,0x5248,0x5249,0x524B,
+0x524E,0x524F,0x5252,0x5253,0x5255,0x5257,0x5258, 0,
+0x5259,0x525A,0x525B,0x525D,0x525F,0x5260,0x5262,0x5263,
+0x5264,0x5266,0x5268,0x526B,0x526C,0x526D,0x526E,0x5270,
+0x5271,0x5273,0x5274,0x5275,0x5276,0x5277,0x5278,0x5279,
+0x527A,0x527B,0x527C,0x527E,0x5280,0x5283,0x5284,0x5285,
+0x5286,0x5287,0x5289,0x528A,0x528B,0x528C,0x528D,0x528E,
+0x528F,0x5291,0x5292,0x5294,0x5295,0x5296,0x5297,0x5298,
+0x5299,0x529A,0x529C,0x52A4,0x52A5,0x52A6,0x52A7,0x52AE,
+0x52AF,0x52B0,0x52B4,0x52B5,0x52B6,0x52B7,0x52B8,0x52B9,
+0x52BA,0x52BB,0x52BC,0x52BD,0x52C0,0x52C1,0x52C2,0x52C4,
+0x52C5,0x52C6,0x52C8,0x52CA,0x52CC,0x52CD,0x52CE,0x52CF,
+0x52D1,0x52D3,0x52D4,0x52D5,0x52D7,0x52D9,0x52DA,0x52DB,
+0x52DC,0x52DD,0x52DE,0x52E0,0x52E1,0x52E2,0x52E3,0x52E5,
+0x52E6,0x52E7,0x52E8,0x52E9,0x52EA,0x52EB,0x52EC,0x52ED,
+0x52EE,0x52EF,0x52F1,0x52F2,0x52F3,0x52F4,0x52F5,0x52F6,
+0x52F7,0x52F8,0x52FB,0x52FC,0x52FD,0x5301,0x5302,0x5303,
+0x5304,0x5307,0x5309,0x530A,0x530B,0x530C,0x530E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5311,0x5312,0x5313,0x5314,0x5318,0x531B,0x531C,0x531E,
+0x531F,0x5322,0x5324,0x5325,0x5327,0x5328,0x5329,0x532B,
+0x532C,0x532D,0x532F,0x5330,0x5331,0x5332,0x5333,0x5334,
+0x5335,0x5336,0x5337,0x5338,0x533C,0x533D,0x5340,0x5342,
+0x5344,0x5346,0x534B,0x534C,0x534D,0x5350,0x5354,0x5358,
+0x5359,0x535B,0x535D,0x5365,0x5368,0x536A,0x536C,0x536D,
+0x5372,0x5376,0x5379,0x537B,0x537C,0x537D,0x537E,0x5380,
+0x5381,0x5383,0x5387,0x5388,0x538A,0x538E,0x538F, 0,
+0x5390,0x5391,0x5392,0x5393,0x5394,0x5396,0x5397,0x5399,
+0x539B,0x539C,0x539E,0x53A0,0x53A1,0x53A4,0x53A7,0x53AA,
+0x53AB,0x53AC,0x53AD,0x53AF,0x53B0,0x53B1,0x53B2,0x53B3,
+0x53B4,0x53B5,0x53B7,0x53B8,0x53B9,0x53BA,0x53BC,0x53BD,
+0x53BE,0x53C0,0x53C3,0x53C4,0x53C5,0x53C6,0x53C7,0x53CE,
+0x53CF,0x53D0,0x53D2,0x53D3,0x53D5,0x53DA,0x53DC,0x53DD,
+0x53DE,0x53E1,0x53E2,0x53E7,0x53F4,0x53FA,0x53FE,0x53FF,
+0x5400,0x5402,0x5405,0x5407,0x540B,0x5414,0x5418,0x5419,
+0x541A,0x541C,0x5422,0x5424,0x5425,0x542A,0x5430,0x5433,
+0x5436,0x5437,0x543A,0x543D,0x543F,0x5441,0x5442,0x5444,
+0x5445,0x5447,0x5449,0x544C,0x544D,0x544E,0x544F,0x5451,
+0x545A,0x545D,0x545E,0x545F,0x5460,0x5461,0x5463,0x5465,
+0x5467,0x5469,0x546A,0x546B,0x546C,0x546D,0x546E,0x546F,
+0x5470,0x5474,0x5479,0x547A,0x547E,0x547F,0x5481,0x5483,
+0x5485,0x5487,0x5488,0x5489,0x548A,0x548D,0x5491,0x5493,
+0x5497,0x5498,0x549C,0x549E,0x549F,0x54A0,0x54A1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x54A2,0x54A5,0x54AE,0x54B0,0x54B2,0x54B5,0x54B6,0x54B7,
+0x54B9,0x54BA,0x54BC,0x54BE,0x54C3,0x54C5,0x54CA,0x54CB,
+0x54D6,0x54D8,0x54DB,0x54E0,0x54E1,0x54E2,0x54E3,0x54E4,
+0x54EB,0x54EC,0x54EF,0x54F0,0x54F1,0x54F4,0x54F5,0x54F6,
+0x54F7,0x54F8,0x54F9,0x54FB,0x54FE,0x5500,0x5502,0x5503,
+0x5504,0x5505,0x5508,0x550A,0x550B,0x550C,0x550D,0x550E,
+0x5512,0x5513,0x5515,0x5516,0x5517,0x5518,0x5519,0x551A,
+0x551C,0x551D,0x551E,0x551F,0x5521,0x5525,0x5526, 0,
+0x5528,0x5529,0x552B,0x552D,0x5532,0x5534,0x5535,0x5536,
+0x5538,0x5539,0x553A,0x553B,0x553D,0x5540,0x5542,0x5545,
+0x5547,0x5548,0x554B,0x554C,0x554D,0x554E,0x554F,0x5551,
+0x5552,0x5553,0x5554,0x5557,0x5558,0x5559,0x555A,0x555B,
+0x555D,0x555E,0x555F,0x5560,0x5562,0x5563,0x5568,0x5569,
+0x556B,0x556F,0x5570,0x5571,0x5572,0x5573,0x5574,0x5579,
+0x557A,0x557D,0x557F,0x5585,0x5586,0x558C,0x558D,0x558E,
+0x5590,0x5592,0x5593,0x5595,0x5596,0x5597,0x559A,0x559B,
+0x559E,0x55A0,0x55A1,0x55A2,0x55A3,0x55A4,0x55A5,0x55A6,
+0x55A8,0x55A9,0x55AA,0x55AB,0x55AC,0x55AD,0x55AE,0x55AF,
+0x55B0,0x55B2,0x55B4,0x55B6,0x55B8,0x55BA,0x55BC,0x55BF,
+0x55C0,0x55C1,0x55C2,0x55C3,0x55C6,0x55C7,0x55C8,0x55CA,
+0x55CB,0x55CE,0x55CF,0x55D0,0x55D5,0x55D7,0x55D8,0x55D9,
+0x55DA,0x55DB,0x55DE,0x55E0,0x55E2,0x55E7,0x55E9,0x55ED,
+0x55EE,0x55F0,0x55F1,0x55F4,0x55F6,0x55F8,0x55F9,0x55FA,
+0x55FB,0x55FC,0x55FF,0x5602,0x5603,0x5604,0x5605, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5606,0x5607,0x560A,0x560B,0x560D,0x5610,0x5611,0x5612,
+0x5613,0x5614,0x5615,0x5616,0x5617,0x5619,0x561A,0x561C,
+0x561D,0x5620,0x5621,0x5622,0x5625,0x5626,0x5628,0x5629,
+0x562A,0x562B,0x562E,0x562F,0x5630,0x5633,0x5635,0x5637,
+0x5638,0x563A,0x563C,0x563D,0x563E,0x5640,0x5641,0x5642,
+0x5643,0x5644,0x5645,0x5646,0x5647,0x5648,0x5649,0x564A,
+0x564B,0x564F,0x5650,0x5651,0x5652,0x5653,0x5655,0x5656,
+0x565A,0x565B,0x565D,0x565E,0x565F,0x5660,0x5661, 0,
+0x5663,0x5665,0x5666,0x5667,0x566D,0x566E,0x566F,0x5670,
+0x5672,0x5673,0x5674,0x5675,0x5677,0x5678,0x5679,0x567A,
+0x567D,0x567E,0x567F,0x5680,0x5681,0x5682,0x5683,0x5684,
+0x5687,0x5688,0x5689,0x568A,0x568B,0x568C,0x568D,0x5690,
+0x5691,0x5692,0x5694,0x5695,0x5696,0x5697,0x5698,0x5699,
+0x569A,0x569B,0x569C,0x569D,0x569E,0x569F,0x56A0,0x56A1,
+0x56A2,0x56A4,0x56A5,0x56A6,0x56A7,0x56A8,0x56A9,0x56AA,
+0x56AB,0x56AC,0x56AD,0x56AE,0x56B0,0x56B1,0x56B2,0x56B3,
+0x56B4,0x56B5,0x56B6,0x56B8,0x56B9,0x56BA,0x56BB,0x56BD,
+0x56BE,0x56BF,0x56C0,0x56C1,0x56C2,0x56C3,0x56C4,0x56C5,
+0x56C6,0x56C7,0x56C8,0x56C9,0x56CB,0x56CC,0x56CD,0x56CE,
+0x56CF,0x56D0,0x56D1,0x56D2,0x56D3,0x56D5,0x56D6,0x56D8,
+0x56D9,0x56DC,0x56E3,0x56E5,0x56E6,0x56E7,0x56E8,0x56E9,
+0x56EA,0x56EC,0x56EE,0x56EF,0x56F2,0x56F3,0x56F6,0x56F7,
+0x56F8,0x56FB,0x56FC,0x5700,0x5701,0x5702,0x5705,0x5707,
+0x570B,0x570C,0x570D,0x570E,0x570F,0x5710,0x5711, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5712,0x5713,0x5714,0x5715,0x5716,0x5717,0x5718,0x5719,
+0x571A,0x571B,0x571D,0x571E,0x5720,0x5721,0x5722,0x5724,
+0x5725,0x5726,0x5727,0x572B,0x5731,0x5732,0x5734,0x5735,
+0x5736,0x5737,0x5738,0x573C,0x573D,0x573F,0x5741,0x5743,
+0x5744,0x5745,0x5746,0x5748,0x5749,0x574B,0x5752,0x5753,
+0x5754,0x5755,0x5756,0x5758,0x5759,0x5762,0x5763,0x5765,
+0x5767,0x576C,0x576E,0x5770,0x5771,0x5772,0x5774,0x5775,
+0x5778,0x5779,0x577A,0x577D,0x577E,0x577F,0x5780, 0,
+0x5781,0x5787,0x5788,0x5789,0x578A,0x578D,0x578E,0x578F,
+0x5790,0x5791,0x5794,0x5795,0x5796,0x5797,0x5798,0x5799,
+0x579A,0x579C,0x579D,0x579E,0x579F,0x57A5,0x57A8,0x57AA,
+0x57AC,0x57AF,0x57B0,0x57B1,0x57B3,0x57B5,0x57B6,0x57B7,
+0x57B9,0x57BA,0x57BB,0x57BC,0x57BD,0x57BE,0x57BF,0x57C0,
+0x57C1,0x57C4,0x57C5,0x57C6,0x57C7,0x57C8,0x57C9,0x57CA,
+0x57CC,0x57CD,0x57D0,0x57D1,0x57D3,0x57D6,0x57D7,0x57DB,
+0x57DC,0x57DE,0x57E1,0x57E2,0x57E3,0x57E5,0x57E6,0x57E7,
+0x57E8,0x57E9,0x57EA,0x57EB,0x57EC,0x57EE,0x57F0,0x57F1,
+0x57F2,0x57F3,0x57F5,0x57F6,0x57F7,0x57FB,0x57FC,0x57FE,
+0x57FF,0x5801,0x5803,0x5804,0x5805,0x5808,0x5809,0x580A,
+0x580C,0x580E,0x580F,0x5810,0x5812,0x5813,0x5814,0x5816,
+0x5817,0x5818,0x581A,0x581B,0x581C,0x581D,0x581F,0x5822,
+0x5823,0x5825,0x5826,0x5827,0x5828,0x5829,0x582B,0x582C,
+0x582D,0x582E,0x582F,0x5831,0x5832,0x5833,0x5834,0x5836,
+0x5837,0x5838,0x5839,0x583A,0x583B,0x583C,0x583D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x583E,0x583F,0x5840,0x5841,0x5842,0x5843,0x5845,0x5846,
+0x5847,0x5848,0x5849,0x584A,0x584B,0x584E,0x584F,0x5850,
+0x5852,0x5853,0x5855,0x5856,0x5857,0x5859,0x585A,0x585B,
+0x585C,0x585D,0x585F,0x5860,0x5861,0x5862,0x5863,0x5864,
+0x5866,0x5867,0x5868,0x5869,0x586A,0x586D,0x586E,0x586F,
+0x5870,0x5871,0x5872,0x5873,0x5874,0x5875,0x5876,0x5877,
+0x5878,0x5879,0x587A,0x587B,0x587C,0x587D,0x587F,0x5882,
+0x5884,0x5886,0x5887,0x5888,0x588A,0x588B,0x588C, 0,
+0x588D,0x588E,0x588F,0x5890,0x5891,0x5894,0x5895,0x5896,
+0x5897,0x5898,0x589B,0x589C,0x589D,0x58A0,0x58A1,0x58A2,
+0x58A3,0x58A4,0x58A5,0x58A6,0x58A7,0x58AA,0x58AB,0x58AC,
+0x58AD,0x58AE,0x58AF,0x58B0,0x58B1,0x58B2,0x58B3,0x58B4,
+0x58B5,0x58B6,0x58B7,0x58B8,0x58B9,0x58BA,0x58BB,0x58BD,
+0x58BE,0x58BF,0x58C0,0x58C2,0x58C3,0x58C4,0x58C6,0x58C7,
+0x58C8,0x58C9,0x58CA,0x58CB,0x58CC,0x58CD,0x58CE,0x58CF,
+0x58D0,0x58D2,0x58D3,0x58D4,0x58D6,0x58D7,0x58D8,0x58D9,
+0x58DA,0x58DB,0x58DC,0x58DD,0x58DE,0x58DF,0x58E0,0x58E1,
+0x58E2,0x58E3,0x58E5,0x58E6,0x58E7,0x58E8,0x58E9,0x58EA,
+0x58ED,0x58EF,0x58F1,0x58F2,0x58F4,0x58F5,0x58F7,0x58F8,
+0x58FA,0x58FB,0x58FC,0x58FD,0x58FE,0x58FF,0x5900,0x5901,
+0x5903,0x5905,0x5906,0x5908,0x5909,0x590A,0x590B,0x590C,
+0x590E,0x5910,0x5911,0x5912,0x5913,0x5917,0x5918,0x591B,
+0x591D,0x591E,0x5920,0x5921,0x5922,0x5923,0x5926,0x5928,
+0x592C,0x5930,0x5932,0x5933,0x5935,0x5936,0x593B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x593D,0x593E,0x593F,0x5940,0x5943,0x5945,0x5946,0x594A,
+0x594C,0x594D,0x5950,0x5952,0x5953,0x5959,0x595B,0x595C,
+0x595D,0x595E,0x595F,0x5961,0x5963,0x5964,0x5966,0x5967,
+0x5968,0x5969,0x596A,0x596B,0x596C,0x596D,0x596E,0x596F,
+0x5970,0x5971,0x5972,0x5975,0x5977,0x597A,0x597B,0x597C,
+0x597E,0x597F,0x5980,0x5985,0x5989,0x598B,0x598C,0x598E,
+0x598F,0x5990,0x5991,0x5994,0x5995,0x5998,0x599A,0x599B,
+0x599C,0x599D,0x599F,0x59A0,0x59A1,0x59A2,0x59A6, 0,
+0x59A7,0x59AC,0x59AD,0x59B0,0x59B1,0x59B3,0x59B4,0x59B5,
+0x59B6,0x59B7,0x59B8,0x59BA,0x59BC,0x59BD,0x59BF,0x59C0,
+0x59C1,0x59C2,0x59C3,0x59C4,0x59C5,0x59C7,0x59C8,0x59C9,
+0x59CC,0x59CD,0x59CE,0x59CF,0x59D5,0x59D6,0x59D9,0x59DB,
+0x59DE,0x59DF,0x59E0,0x59E1,0x59E2,0x59E4,0x59E6,0x59E7,
+0x59E9,0x59EA,0x59EB,0x59ED,0x59EE,0x59EF,0x59F0,0x59F1,
+0x59F2,0x59F3,0x59F4,0x59F5,0x59F6,0x59F7,0x59F8,0x59FA,
+0x59FC,0x59FD,0x59FE,0x5A00,0x5A02,0x5A0A,0x5A0B,0x5A0D,
+0x5A0E,0x5A0F,0x5A10,0x5A12,0x5A14,0x5A15,0x5A16,0x5A17,
+0x5A19,0x5A1A,0x5A1B,0x5A1D,0x5A1E,0x5A21,0x5A22,0x5A24,
+0x5A26,0x5A27,0x5A28,0x5A2A,0x5A2B,0x5A2C,0x5A2D,0x5A2E,
+0x5A2F,0x5A30,0x5A33,0x5A35,0x5A37,0x5A38,0x5A39,0x5A3A,
+0x5A3B,0x5A3D,0x5A3E,0x5A3F,0x5A41,0x5A42,0x5A43,0x5A44,
+0x5A45,0x5A47,0x5A48,0x5A4B,0x5A4C,0x5A4D,0x5A4E,0x5A4F,
+0x5A50,0x5A51,0x5A52,0x5A53,0x5A54,0x5A56,0x5A57,0x5A58,
+0x5A59,0x5A5B,0x5A5C,0x5A5D,0x5A5E,0x5A5F,0x5A60, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5A61,0x5A63,0x5A64,0x5A65,0x5A66,0x5A68,0x5A69,0x5A6B,
+0x5A6C,0x5A6D,0x5A6E,0x5A6F,0x5A70,0x5A71,0x5A72,0x5A73,
+0x5A78,0x5A79,0x5A7B,0x5A7C,0x5A7D,0x5A7E,0x5A80,0x5A81,
+0x5A82,0x5A83,0x5A84,0x5A85,0x5A86,0x5A87,0x5A88,0x5A89,
+0x5A8A,0x5A8B,0x5A8C,0x5A8D,0x5A8E,0x5A8F,0x5A90,0x5A91,
+0x5A93,0x5A94,0x5A95,0x5A96,0x5A97,0x5A98,0x5A99,0x5A9C,
+0x5A9D,0x5A9E,0x5A9F,0x5AA0,0x5AA1,0x5AA2,0x5AA3,0x5AA4,
+0x5AA5,0x5AA6,0x5AA7,0x5AA8,0x5AA9,0x5AAB,0x5AAC, 0,
+0x5AAD,0x5AAE,0x5AAF,0x5AB0,0x5AB1,0x5AB4,0x5AB6,0x5AB7,
+0x5AB9,0x5ABA,0x5ABB,0x5ABC,0x5ABD,0x5ABF,0x5AC0,0x5AC3,
+0x5AC4,0x5AC5,0x5AC6,0x5AC7,0x5AC8,0x5ACA,0x5ACB,0x5ACD,
+0x5ACE,0x5ACF,0x5AD0,0x5AD1,0x5AD3,0x5AD5,0x5AD7,0x5AD9,
+0x5ADA,0x5ADB,0x5ADD,0x5ADE,0x5ADF,0x5AE2,0x5AE4,0x5AE5,
+0x5AE7,0x5AE8,0x5AEA,0x5AEC,0x5AED,0x5AEE,0x5AEF,0x5AF0,
+0x5AF2,0x5AF3,0x5AF4,0x5AF5,0x5AF6,0x5AF7,0x5AF8,0x5AF9,
+0x5AFA,0x5AFB,0x5AFC,0x5AFD,0x5AFE,0x5AFF,0x5B00,0x5B01,
+0x5B02,0x5B03,0x5B04,0x5B05,0x5B06,0x5B07,0x5B08,0x5B0A,
+0x5B0B,0x5B0C,0x5B0D,0x5B0E,0x5B0F,0x5B10,0x5B11,0x5B12,
+0x5B13,0x5B14,0x5B15,0x5B18,0x5B19,0x5B1A,0x5B1B,0x5B1C,
+0x5B1D,0x5B1E,0x5B1F,0x5B20,0x5B21,0x5B22,0x5B23,0x5B24,
+0x5B25,0x5B26,0x5B27,0x5B28,0x5B29,0x5B2A,0x5B2B,0x5B2C,
+0x5B2D,0x5B2E,0x5B2F,0x5B30,0x5B31,0x5B33,0x5B35,0x5B36,
+0x5B38,0x5B39,0x5B3A,0x5B3B,0x5B3C,0x5B3D,0x5B3E,0x5B3F,
+0x5B41,0x5B42,0x5B43,0x5B44,0x5B45,0x5B46,0x5B47, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5B48,0x5B49,0x5B4A,0x5B4B,0x5B4C,0x5B4D,0x5B4E,0x5B4F,
+0x5B52,0x5B56,0x5B5E,0x5B60,0x5B61,0x5B67,0x5B68,0x5B6B,
+0x5B6D,0x5B6E,0x5B6F,0x5B72,0x5B74,0x5B76,0x5B77,0x5B78,
+0x5B79,0x5B7B,0x5B7C,0x5B7E,0x5B7F,0x5B82,0x5B86,0x5B8A,
+0x5B8D,0x5B8E,0x5B90,0x5B91,0x5B92,0x5B94,0x5B96,0x5B9F,
+0x5BA7,0x5BA8,0x5BA9,0x5BAC,0x5BAD,0x5BAE,0x5BAF,0x5BB1,
+0x5BB2,0x5BB7,0x5BBA,0x5BBB,0x5BBC,0x5BC0,0x5BC1,0x5BC3,
+0x5BC8,0x5BC9,0x5BCA,0x5BCB,0x5BCD,0x5BCE,0x5BCF, 0,
+0x5BD1,0x5BD4,0x5BD5,0x5BD6,0x5BD7,0x5BD8,0x5BD9,0x5BDA,
+0x5BDB,0x5BDC,0x5BE0,0x5BE2,0x5BE3,0x5BE6,0x5BE7,0x5BE9,
+0x5BEA,0x5BEB,0x5BEC,0x5BED,0x5BEF,0x5BF1,0x5BF2,0x5BF3,
+0x5BF4,0x5BF5,0x5BF6,0x5BF7,0x5BFD,0x5BFE,0x5C00,0x5C02,
+0x5C03,0x5C05,0x5C07,0x5C08,0x5C0B,0x5C0C,0x5C0D,0x5C0E,
+0x5C10,0x5C12,0x5C13,0x5C17,0x5C19,0x5C1B,0x5C1E,0x5C1F,
+0x5C20,0x5C21,0x5C23,0x5C26,0x5C28,0x5C29,0x5C2A,0x5C2B,
+0x5C2D,0x5C2E,0x5C2F,0x5C30,0x5C32,0x5C33,0x5C35,0x5C36,
+0x5C37,0x5C43,0x5C44,0x5C46,0x5C47,0x5C4C,0x5C4D,0x5C52,
+0x5C53,0x5C54,0x5C56,0x5C57,0x5C58,0x5C5A,0x5C5B,0x5C5C,
+0x5C5D,0x5C5F,0x5C62,0x5C64,0x5C67,0x5C68,0x5C69,0x5C6A,
+0x5C6B,0x5C6C,0x5C6D,0x5C70,0x5C72,0x5C73,0x5C74,0x5C75,
+0x5C76,0x5C77,0x5C78,0x5C7B,0x5C7C,0x5C7D,0x5C7E,0x5C80,
+0x5C83,0x5C84,0x5C85,0x5C86,0x5C87,0x5C89,0x5C8A,0x5C8B,
+0x5C8E,0x5C8F,0x5C92,0x5C93,0x5C95,0x5C9D,0x5C9E,0x5C9F,
+0x5CA0,0x5CA1,0x5CA4,0x5CA5,0x5CA6,0x5CA7,0x5CA8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5CAA,0x5CAE,0x5CAF,0x5CB0,0x5CB2,0x5CB4,0x5CB6,0x5CB9,
+0x5CBA,0x5CBB,0x5CBC,0x5CBE,0x5CC0,0x5CC2,0x5CC3,0x5CC5,
+0x5CC6,0x5CC7,0x5CC8,0x5CC9,0x5CCA,0x5CCC,0x5CCD,0x5CCE,
+0x5CCF,0x5CD0,0x5CD1,0x5CD3,0x5CD4,0x5CD5,0x5CD6,0x5CD7,
+0x5CD8,0x5CDA,0x5CDB,0x5CDC,0x5CDD,0x5CDE,0x5CDF,0x5CE0,
+0x5CE2,0x5CE3,0x5CE7,0x5CE9,0x5CEB,0x5CEC,0x5CEE,0x5CEF,
+0x5CF1,0x5CF2,0x5CF3,0x5CF4,0x5CF5,0x5CF6,0x5CF7,0x5CF8,
+0x5CF9,0x5CFA,0x5CFC,0x5CFD,0x5CFE,0x5CFF,0x5D00, 0,
+0x5D01,0x5D04,0x5D05,0x5D08,0x5D09,0x5D0A,0x5D0B,0x5D0C,
+0x5D0D,0x5D0F,0x5D10,0x5D11,0x5D12,0x5D13,0x5D15,0x5D17,
+0x5D18,0x5D19,0x5D1A,0x5D1C,0x5D1D,0x5D1F,0x5D20,0x5D21,
+0x5D22,0x5D23,0x5D25,0x5D28,0x5D2A,0x5D2B,0x5D2C,0x5D2F,
+0x5D30,0x5D31,0x5D32,0x5D33,0x5D35,0x5D36,0x5D37,0x5D38,
+0x5D39,0x5D3A,0x5D3B,0x5D3C,0x5D3F,0x5D40,0x5D41,0x5D42,
+0x5D43,0x5D44,0x5D45,0x5D46,0x5D48,0x5D49,0x5D4D,0x5D4E,
+0x5D4F,0x5D50,0x5D51,0x5D52,0x5D53,0x5D54,0x5D55,0x5D56,
+0x5D57,0x5D59,0x5D5A,0x5D5C,0x5D5E,0x5D5F,0x5D60,0x5D61,
+0x5D62,0x5D63,0x5D64,0x5D65,0x5D66,0x5D67,0x5D68,0x5D6A,
+0x5D6D,0x5D6E,0x5D70,0x5D71,0x5D72,0x5D73,0x5D75,0x5D76,
+0x5D77,0x5D78,0x5D79,0x5D7A,0x5D7B,0x5D7C,0x5D7D,0x5D7E,
+0x5D7F,0x5D80,0x5D81,0x5D83,0x5D84,0x5D85,0x5D86,0x5D87,
+0x5D88,0x5D89,0x5D8A,0x5D8B,0x5D8C,0x5D8D,0x5D8E,0x5D8F,
+0x5D90,0x5D91,0x5D92,0x5D93,0x5D94,0x5D95,0x5D96,0x5D97,
+0x5D98,0x5D9A,0x5D9B,0x5D9C,0x5D9E,0x5D9F,0x5DA0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5DA1,0x5DA2,0x5DA3,0x5DA4,0x5DA5,0x5DA6,0x5DA7,0x5DA8,
+0x5DA9,0x5DAA,0x5DAB,0x5DAC,0x5DAD,0x5DAE,0x5DAF,0x5DB0,
+0x5DB1,0x5DB2,0x5DB3,0x5DB4,0x5DB5,0x5DB6,0x5DB8,0x5DB9,
+0x5DBA,0x5DBB,0x5DBC,0x5DBD,0x5DBE,0x5DBF,0x5DC0,0x5DC1,
+0x5DC2,0x5DC3,0x5DC4,0x5DC6,0x5DC7,0x5DC8,0x5DC9,0x5DCA,
+0x5DCB,0x5DCC,0x5DCE,0x5DCF,0x5DD0,0x5DD1,0x5DD2,0x5DD3,
+0x5DD4,0x5DD5,0x5DD6,0x5DD7,0x5DD8,0x5DD9,0x5DDA,0x5DDC,
+0x5DDF,0x5DE0,0x5DE3,0x5DE4,0x5DEA,0x5DEC,0x5DED, 0,
+0x5DF0,0x5DF5,0x5DF6,0x5DF8,0x5DF9,0x5DFA,0x5DFB,0x5DFC,
+0x5DFF,0x5E00,0x5E04,0x5E07,0x5E09,0x5E0A,0x5E0B,0x5E0D,
+0x5E0E,0x5E12,0x5E13,0x5E17,0x5E1E,0x5E1F,0x5E20,0x5E21,
+0x5E22,0x5E23,0x5E24,0x5E25,0x5E28,0x5E29,0x5E2A,0x5E2B,
+0x5E2C,0x5E2F,0x5E30,0x5E32,0x5E33,0x5E34,0x5E35,0x5E36,
+0x5E39,0x5E3A,0x5E3E,0x5E3F,0x5E40,0x5E41,0x5E43,0x5E46,
+0x5E47,0x5E48,0x5E49,0x5E4A,0x5E4B,0x5E4D,0x5E4E,0x5E4F,
+0x5E50,0x5E51,0x5E52,0x5E53,0x5E56,0x5E57,0x5E58,0x5E59,
+0x5E5A,0x5E5C,0x5E5D,0x5E5F,0x5E60,0x5E63,0x5E64,0x5E65,
+0x5E66,0x5E67,0x5E68,0x5E69,0x5E6A,0x5E6B,0x5E6C,0x5E6D,
+0x5E6E,0x5E6F,0x5E70,0x5E71,0x5E75,0x5E77,0x5E79,0x5E7E,
+0x5E81,0x5E82,0x5E83,0x5E85,0x5E88,0x5E89,0x5E8C,0x5E8D,
+0x5E8E,0x5E92,0x5E98,0x5E9B,0x5E9D,0x5EA1,0x5EA2,0x5EA3,
+0x5EA4,0x5EA8,0x5EA9,0x5EAA,0x5EAB,0x5EAC,0x5EAE,0x5EAF,
+0x5EB0,0x5EB1,0x5EB2,0x5EB4,0x5EBA,0x5EBB,0x5EBC,0x5EBD,
+0x5EBF,0x5EC0,0x5EC1,0x5EC2,0x5EC3,0x5EC4,0x5EC5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5EC6,0x5EC7,0x5EC8,0x5ECB,0x5ECC,0x5ECD,0x5ECE,0x5ECF,
+0x5ED0,0x5ED4,0x5ED5,0x5ED7,0x5ED8,0x5ED9,0x5EDA,0x5EDC,
+0x5EDD,0x5EDE,0x5EDF,0x5EE0,0x5EE1,0x5EE2,0x5EE3,0x5EE4,
+0x5EE5,0x5EE6,0x5EE7,0x5EE9,0x5EEB,0x5EEC,0x5EED,0x5EEE,
+0x5EEF,0x5EF0,0x5EF1,0x5EF2,0x5EF3,0x5EF5,0x5EF8,0x5EF9,
+0x5EFB,0x5EFC,0x5EFD,0x5F05,0x5F06,0x5F07,0x5F09,0x5F0C,
+0x5F0D,0x5F0E,0x5F10,0x5F12,0x5F14,0x5F16,0x5F19,0x5F1A,
+0x5F1C,0x5F1D,0x5F1E,0x5F21,0x5F22,0x5F23,0x5F24, 0,
+0x5F28,0x5F2B,0x5F2C,0x5F2E,0x5F30,0x5F32,0x5F33,0x5F34,
+0x5F35,0x5F36,0x5F37,0x5F38,0x5F3B,0x5F3D,0x5F3E,0x5F3F,
+0x5F41,0x5F42,0x5F43,0x5F44,0x5F45,0x5F46,0x5F47,0x5F48,
+0x5F49,0x5F4A,0x5F4B,0x5F4C,0x5F4D,0x5F4E,0x5F4F,0x5F51,
+0x5F54,0x5F59,0x5F5A,0x5F5B,0x5F5C,0x5F5E,0x5F5F,0x5F60,
+0x5F63,0x5F65,0x5F67,0x5F68,0x5F6B,0x5F6E,0x5F6F,0x5F72,
+0x5F74,0x5F75,0x5F76,0x5F78,0x5F7A,0x5F7D,0x5F7E,0x5F7F,
+0x5F83,0x5F86,0x5F8D,0x5F8E,0x5F8F,0x5F91,0x5F93,0x5F94,
+0x5F96,0x5F9A,0x5F9B,0x5F9D,0x5F9E,0x5F9F,0x5FA0,0x5FA2,
+0x5FA3,0x5FA4,0x5FA5,0x5FA6,0x5FA7,0x5FA9,0x5FAB,0x5FAC,
+0x5FAF,0x5FB0,0x5FB1,0x5FB2,0x5FB3,0x5FB4,0x5FB6,0x5FB8,
+0x5FB9,0x5FBA,0x5FBB,0x5FBE,0x5FBF,0x5FC0,0x5FC1,0x5FC2,
+0x5FC7,0x5FC8,0x5FCA,0x5FCB,0x5FCE,0x5FD3,0x5FD4,0x5FD5,
+0x5FDA,0x5FDB,0x5FDC,0x5FDE,0x5FDF,0x5FE2,0x5FE3,0x5FE5,
+0x5FE6,0x5FE8,0x5FE9,0x5FEC,0x5FEF,0x5FF0,0x5FF2,0x5FF3,
+0x5FF4,0x5FF6,0x5FF7,0x5FF9,0x5FFA,0x5FFC,0x6007, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6008,0x6009,0x600B,0x600C,0x6010,0x6011,0x6013,0x6017,
+0x6018,0x601A,0x601E,0x601F,0x6022,0x6023,0x6024,0x602C,
+0x602D,0x602E,0x6030,0x6031,0x6032,0x6033,0x6034,0x6036,
+0x6037,0x6038,0x6039,0x603A,0x603D,0x603E,0x6040,0x6044,
+0x6045,0x6046,0x6047,0x6048,0x6049,0x604A,0x604C,0x604E,
+0x604F,0x6051,0x6053,0x6054,0x6056,0x6057,0x6058,0x605B,
+0x605C,0x605E,0x605F,0x6060,0x6061,0x6065,0x6066,0x606E,
+0x6071,0x6072,0x6074,0x6075,0x6077,0x607E,0x6080, 0,
+0x6081,0x6082,0x6085,0x6086,0x6087,0x6088,0x608A,0x608B,
+0x608E,0x608F,0x6090,0x6091,0x6093,0x6095,0x6097,0x6098,
+0x6099,0x609C,0x609E,0x60A1,0x60A2,0x60A4,0x60A5,0x60A7,
+0x60A9,0x60AA,0x60AE,0x60B0,0x60B3,0x60B5,0x60B6,0x60B7,
+0x60B9,0x60BA,0x60BD,0x60BE,0x60BF,0x60C0,0x60C1,0x60C2,
+0x60C3,0x60C4,0x60C7,0x60C8,0x60C9,0x60CC,0x60CD,0x60CE,
+0x60CF,0x60D0,0x60D2,0x60D3,0x60D4,0x60D6,0x60D7,0x60D9,
+0x60DB,0x60DE,0x60E1,0x60E2,0x60E3,0x60E4,0x60E5,0x60EA,
+0x60F1,0x60F2,0x60F5,0x60F7,0x60F8,0x60FB,0x60FC,0x60FD,
+0x60FE,0x60FF,0x6102,0x6103,0x6104,0x6105,0x6107,0x610A,
+0x610B,0x610C,0x6110,0x6111,0x6112,0x6113,0x6114,0x6116,
+0x6117,0x6118,0x6119,0x611B,0x611C,0x611D,0x611E,0x6121,
+0x6122,0x6125,0x6128,0x6129,0x612A,0x612C,0x612D,0x612E,
+0x612F,0x6130,0x6131,0x6132,0x6133,0x6134,0x6135,0x6136,
+0x6137,0x6138,0x6139,0x613A,0x613B,0x613C,0x613D,0x613E,
+0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6147,0x6149,0x614B,0x614D,0x614F,0x6150,0x6152,0x6153,
+0x6154,0x6156,0x6157,0x6158,0x6159,0x615A,0x615B,0x615C,
+0x615E,0x615F,0x6160,0x6161,0x6163,0x6164,0x6165,0x6166,
+0x6169,0x616A,0x616B,0x616C,0x616D,0x616E,0x616F,0x6171,
+0x6172,0x6173,0x6174,0x6176,0x6178,0x6179,0x617A,0x617B,
+0x617C,0x617D,0x617E,0x617F,0x6180,0x6181,0x6182,0x6183,
+0x6184,0x6185,0x6186,0x6187,0x6188,0x6189,0x618A,0x618C,
+0x618D,0x618F,0x6190,0x6191,0x6192,0x6193,0x6195, 0,
+0x6196,0x6197,0x6198,0x6199,0x619A,0x619B,0x619C,0x619E,
+0x619F,0x61A0,0x61A1,0x61A2,0x61A3,0x61A4,0x61A5,0x61A6,
+0x61AA,0x61AB,0x61AD,0x61AE,0x61AF,0x61B0,0x61B1,0x61B2,
+0x61B3,0x61B4,0x61B5,0x61B6,0x61B8,0x61B9,0x61BA,0x61BB,
+0x61BC,0x61BD,0x61BF,0x61C0,0x61C1,0x61C3,0x61C4,0x61C5,
+0x61C6,0x61C7,0x61C9,0x61CC,0x61CD,0x61CE,0x61CF,0x61D0,
+0x61D3,0x61D5,0x61D6,0x61D7,0x61D8,0x61D9,0x61DA,0x61DB,
+0x61DC,0x61DD,0x61DE,0x61DF,0x61E0,0x61E1,0x61E2,0x61E3,
+0x61E4,0x61E5,0x61E7,0x61E8,0x61E9,0x61EA,0x61EB,0x61EC,
+0x61ED,0x61EE,0x61EF,0x61F0,0x61F1,0x61F2,0x61F3,0x61F4,
+0x61F6,0x61F7,0x61F8,0x61F9,0x61FA,0x61FB,0x61FC,0x61FD,
+0x61FE,0x6200,0x6201,0x6202,0x6203,0x6204,0x6205,0x6207,
+0x6209,0x6213,0x6214,0x6219,0x621C,0x621D,0x621E,0x6220,
+0x6223,0x6226,0x6227,0x6228,0x6229,0x622B,0x622D,0x622F,
+0x6230,0x6231,0x6232,0x6235,0x6236,0x6238,0x6239,0x623A,
+0x623B,0x623C,0x6242,0x6244,0x6245,0x6246,0x624A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x624F,0x6250,0x6255,0x6256,0x6257,0x6259,0x625A,0x625C,
+0x625D,0x625E,0x625F,0x6260,0x6261,0x6262,0x6264,0x6265,
+0x6268,0x6271,0x6272,0x6274,0x6275,0x6277,0x6278,0x627A,
+0x627B,0x627D,0x6281,0x6282,0x6283,0x6285,0x6286,0x6287,
+0x6288,0x628B,0x628C,0x628D,0x628E,0x628F,0x6290,0x6294,
+0x6299,0x629C,0x629D,0x629E,0x62A3,0x62A6,0x62A7,0x62A9,
+0x62AA,0x62AD,0x62AE,0x62AF,0x62B0,0x62B2,0x62B3,0x62B4,
+0x62B6,0x62B7,0x62B8,0x62BA,0x62BE,0x62C0,0x62C1, 0,
+0x62C3,0x62CB,0x62CF,0x62D1,0x62D5,0x62DD,0x62DE,0x62E0,
+0x62E1,0x62E4,0x62EA,0x62EB,0x62F0,0x62F2,0x62F5,0x62F8,
+0x62F9,0x62FA,0x62FB,0x6300,0x6303,0x6304,0x6305,0x6306,
+0x630A,0x630B,0x630C,0x630D,0x630F,0x6310,0x6312,0x6313,
+0x6314,0x6315,0x6317,0x6318,0x6319,0x631C,0x6326,0x6327,
+0x6329,0x632C,0x632D,0x632E,0x6330,0x6331,0x6333,0x6334,
+0x6335,0x6336,0x6337,0x6338,0x633B,0x633C,0x633E,0x633F,
+0x6340,0x6341,0x6344,0x6347,0x6348,0x634A,0x6351,0x6352,
+0x6353,0x6354,0x6356,0x6357,0x6358,0x6359,0x635A,0x635B,
+0x635C,0x635D,0x6360,0x6364,0x6365,0x6366,0x6368,0x636A,
+0x636B,0x636C,0x636F,0x6370,0x6372,0x6373,0x6374,0x6375,
+0x6378,0x6379,0x637C,0x637D,0x637E,0x637F,0x6381,0x6383,
+0x6384,0x6385,0x6386,0x638B,0x638D,0x6391,0x6393,0x6394,
+0x6395,0x6397,0x6399,0x639A,0x639B,0x639C,0x639D,0x639E,
+0x639F,0x63A1,0x63A4,0x63A6,0x63AB,0x63AF,0x63B1,0x63B2,
+0x63B5,0x63B6,0x63B9,0x63BB,0x63BD,0x63BF,0x63C0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x63C1,0x63C2,0x63C3,0x63C5,0x63C7,0x63C8,0x63CA,0x63CB,
+0x63CC,0x63D1,0x63D3,0x63D4,0x63D5,0x63D7,0x63D8,0x63D9,
+0x63DA,0x63DB,0x63DC,0x63DD,0x63DF,0x63E2,0x63E4,0x63E5,
+0x63E6,0x63E7,0x63E8,0x63EB,0x63EC,0x63EE,0x63EF,0x63F0,
+0x63F1,0x63F3,0x63F5,0x63F7,0x63F9,0x63FA,0x63FB,0x63FC,
+0x63FE,0x6403,0x6404,0x6406,0x6407,0x6408,0x6409,0x640A,
+0x640D,0x640E,0x6411,0x6412,0x6415,0x6416,0x6417,0x6418,
+0x6419,0x641A,0x641D,0x641F,0x6422,0x6423,0x6424, 0,
+0x6425,0x6427,0x6428,0x6429,0x642B,0x642E,0x642F,0x6430,
+0x6431,0x6432,0x6433,0x6435,0x6436,0x6437,0x6438,0x6439,
+0x643B,0x643C,0x643E,0x6440,0x6442,0x6443,0x6449,0x644B,
+0x644C,0x644D,0x644E,0x644F,0x6450,0x6451,0x6453,0x6455,
+0x6456,0x6457,0x6459,0x645A,0x645B,0x645C,0x645D,0x645F,
+0x6460,0x6461,0x6462,0x6463,0x6464,0x6465,0x6466,0x6468,
+0x646A,0x646B,0x646C,0x646E,0x646F,0x6470,0x6471,0x6472,
+0x6473,0x6474,0x6475,0x6476,0x6477,0x647B,0x647C,0x647D,
+0x647E,0x647F,0x6480,0x6481,0x6483,0x6486,0x6488,0x6489,
+0x648A,0x648B,0x648C,0x648D,0x648E,0x648F,0x6490,0x6493,
+0x6494,0x6497,0x6498,0x649A,0x649B,0x649C,0x649D,0x649F,
+0x64A0,0x64A1,0x64A2,0x64A3,0x64A5,0x64A6,0x64A7,0x64A8,
+0x64AA,0x64AB,0x64AF,0x64B1,0x64B2,0x64B3,0x64B4,0x64B6,
+0x64B9,0x64BB,0x64BD,0x64BE,0x64BF,0x64C1,0x64C3,0x64C4,
+0x64C6,0x64C7,0x64C8,0x64C9,0x64CA,0x64CB,0x64CC,0x64CF,
+0x64D1,0x64D3,0x64D4,0x64D5,0x64D6,0x64D9,0x64DA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x64DB,0x64DC,0x64DD,0x64DF,0x64E0,0x64E1,0x64E3,0x64E5,
+0x64E7,0x64E8,0x64E9,0x64EA,0x64EB,0x64EC,0x64ED,0x64EE,
+0x64EF,0x64F0,0x64F1,0x64F2,0x64F3,0x64F4,0x64F5,0x64F6,
+0x64F7,0x64F8,0x64F9,0x64FA,0x64FB,0x64FC,0x64FD,0x64FE,
+0x64FF,0x6501,0x6502,0x6503,0x6504,0x6505,0x6506,0x6507,
+0x6508,0x650A,0x650B,0x650C,0x650D,0x650E,0x650F,0x6510,
+0x6511,0x6513,0x6514,0x6515,0x6516,0x6517,0x6519,0x651A,
+0x651B,0x651C,0x651D,0x651E,0x651F,0x6520,0x6521, 0,
+0x6522,0x6523,0x6524,0x6526,0x6527,0x6528,0x6529,0x652A,
+0x652C,0x652D,0x6530,0x6531,0x6532,0x6533,0x6537,0x653A,
+0x653C,0x653D,0x6540,0x6541,0x6542,0x6543,0x6544,0x6546,
+0x6547,0x654A,0x654B,0x654D,0x654E,0x6550,0x6552,0x6553,
+0x6554,0x6557,0x6558,0x655A,0x655C,0x655F,0x6560,0x6561,
+0x6564,0x6565,0x6567,0x6568,0x6569,0x656A,0x656D,0x656E,
+0x656F,0x6571,0x6573,0x6575,0x6576,0x6578,0x6579,0x657A,
+0x657B,0x657C,0x657D,0x657E,0x657F,0x6580,0x6581,0x6582,
+0x6583,0x6584,0x6585,0x6586,0x6588,0x6589,0x658A,0x658D,
+0x658E,0x658F,0x6592,0x6594,0x6595,0x6596,0x6598,0x659A,
+0x659D,0x659E,0x65A0,0x65A2,0x65A3,0x65A6,0x65A8,0x65AA,
+0x65AC,0x65AE,0x65B1,0x65B2,0x65B3,0x65B4,0x65B5,0x65B6,
+0x65B7,0x65B8,0x65BA,0x65BB,0x65BE,0x65BF,0x65C0,0x65C2,
+0x65C7,0x65C8,0x65C9,0x65CA,0x65CD,0x65D0,0x65D1,0x65D3,
+0x65D4,0x65D5,0x65D8,0x65D9,0x65DA,0x65DB,0x65DC,0x65DD,
+0x65DE,0x65DF,0x65E1,0x65E3,0x65E4,0x65EA,0x65EB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x65F2,0x65F3,0x65F4,0x65F5,0x65F8,0x65F9,0x65FB,0x65FC,
+0x65FD,0x65FE,0x65FF,0x6601,0x6604,0x6605,0x6607,0x6608,
+0x6609,0x660B,0x660D,0x6610,0x6611,0x6612,0x6616,0x6617,
+0x6618,0x661A,0x661B,0x661C,0x661E,0x6621,0x6622,0x6623,
+0x6624,0x6626,0x6629,0x662A,0x662B,0x662C,0x662E,0x6630,
+0x6632,0x6633,0x6637,0x6638,0x6639,0x663A,0x663B,0x663D,
+0x663F,0x6640,0x6642,0x6644,0x6645,0x6646,0x6647,0x6648,
+0x6649,0x664A,0x664D,0x664E,0x6650,0x6651,0x6658, 0,
+0x6659,0x665B,0x665C,0x665D,0x665E,0x6660,0x6662,0x6663,
+0x6665,0x6667,0x6669,0x666A,0x666B,0x666C,0x666D,0x6671,
+0x6672,0x6673,0x6675,0x6678,0x6679,0x667B,0x667C,0x667D,
+0x667F,0x6680,0x6681,0x6683,0x6685,0x6686,0x6688,0x6689,
+0x668A,0x668B,0x668D,0x668E,0x668F,0x6690,0x6692,0x6693,
+0x6694,0x6695,0x6698,0x6699,0x669A,0x669B,0x669C,0x669E,
+0x669F,0x66A0,0x66A1,0x66A2,0x66A3,0x66A4,0x66A5,0x66A6,
+0x66A9,0x66AA,0x66AB,0x66AC,0x66AD,0x66AF,0x66B0,0x66B1,
+0x66B2,0x66B3,0x66B5,0x66B6,0x66B7,0x66B8,0x66BA,0x66BB,
+0x66BC,0x66BD,0x66BF,0x66C0,0x66C1,0x66C2,0x66C3,0x66C4,
+0x66C5,0x66C6,0x66C7,0x66C8,0x66C9,0x66CA,0x66CB,0x66CC,
+0x66CD,0x66CE,0x66CF,0x66D0,0x66D1,0x66D2,0x66D3,0x66D4,
+0x66D5,0x66D6,0x66D7,0x66D8,0x66DA,0x66DE,0x66DF,0x66E0,
+0x66E1,0x66E2,0x66E3,0x66E4,0x66E5,0x66E7,0x66E8,0x66EA,
+0x66EB,0x66EC,0x66ED,0x66EE,0x66EF,0x66F1,0x66F5,0x66F6,
+0x66F8,0x66FA,0x66FB,0x66FD,0x6701,0x6702,0x6703, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6704,0x6705,0x6706,0x6707,0x670C,0x670E,0x670F,0x6711,
+0x6712,0x6713,0x6716,0x6718,0x6719,0x671A,0x671C,0x671E,
+0x6720,0x6721,0x6722,0x6723,0x6724,0x6725,0x6727,0x6729,
+0x672E,0x6730,0x6732,0x6733,0x6736,0x6737,0x6738,0x6739,
+0x673B,0x673C,0x673E,0x673F,0x6741,0x6744,0x6745,0x6747,
+0x674A,0x674B,0x674D,0x6752,0x6754,0x6755,0x6757,0x6758,
+0x6759,0x675A,0x675B,0x675D,0x6762,0x6763,0x6764,0x6766,
+0x6767,0x676B,0x676C,0x676E,0x6771,0x6774,0x6776, 0,
+0x6778,0x6779,0x677A,0x677B,0x677D,0x6780,0x6782,0x6783,
+0x6785,0x6786,0x6788,0x678A,0x678C,0x678D,0x678E,0x678F,
+0x6791,0x6792,0x6793,0x6794,0x6796,0x6799,0x679B,0x679F,
+0x67A0,0x67A1,0x67A4,0x67A6,0x67A9,0x67AC,0x67AE,0x67B1,
+0x67B2,0x67B4,0x67B9,0x67BA,0x67BB,0x67BC,0x67BD,0x67BE,
+0x67BF,0x67C0,0x67C2,0x67C5,0x67C6,0x67C7,0x67C8,0x67C9,
+0x67CA,0x67CB,0x67CC,0x67CD,0x67CE,0x67D5,0x67D6,0x67D7,
+0x67DB,0x67DF,0x67E1,0x67E3,0x67E4,0x67E6,0x67E7,0x67E8,
+0x67EA,0x67EB,0x67ED,0x67EE,0x67F2,0x67F5,0x67F6,0x67F7,
+0x67F8,0x67F9,0x67FA,0x67FB,0x67FC,0x67FE,0x6801,0x6802,
+0x6803,0x6804,0x6806,0x680D,0x6810,0x6812,0x6814,0x6815,
+0x6818,0x6819,0x681A,0x681B,0x681C,0x681E,0x681F,0x6820,
+0x6822,0x6823,0x6824,0x6825,0x6826,0x6827,0x6828,0x682B,
+0x682C,0x682D,0x682E,0x682F,0x6830,0x6831,0x6834,0x6835,
+0x6836,0x683A,0x683B,0x683F,0x6847,0x684B,0x684D,0x684F,
+0x6852,0x6856,0x6857,0x6858,0x6859,0x685A,0x685B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x685C,0x685D,0x685E,0x685F,0x686A,0x686C,0x686D,0x686E,
+0x686F,0x6870,0x6871,0x6872,0x6873,0x6875,0x6878,0x6879,
+0x687A,0x687B,0x687C,0x687D,0x687E,0x687F,0x6880,0x6882,
+0x6884,0x6887,0x6888,0x6889,0x688A,0x688B,0x688C,0x688D,
+0x688E,0x6890,0x6891,0x6892,0x6894,0x6895,0x6896,0x6898,
+0x6899,0x689A,0x689B,0x689C,0x689D,0x689E,0x689F,0x68A0,
+0x68A1,0x68A3,0x68A4,0x68A5,0x68A9,0x68AA,0x68AB,0x68AC,
+0x68AE,0x68B1,0x68B2,0x68B4,0x68B6,0x68B7,0x68B8, 0,
+0x68B9,0x68BA,0x68BB,0x68BC,0x68BD,0x68BE,0x68BF,0x68C1,
+0x68C3,0x68C4,0x68C5,0x68C6,0x68C7,0x68C8,0x68CA,0x68CC,
+0x68CE,0x68CF,0x68D0,0x68D1,0x68D3,0x68D4,0x68D6,0x68D7,
+0x68D9,0x68DB,0x68DC,0x68DD,0x68DE,0x68DF,0x68E1,0x68E2,
+0x68E4,0x68E5,0x68E6,0x68E7,0x68E8,0x68E9,0x68EA,0x68EB,
+0x68EC,0x68ED,0x68EF,0x68F2,0x68F3,0x68F4,0x68F6,0x68F7,
+0x68F8,0x68FB,0x68FD,0x68FE,0x68FF,0x6900,0x6902,0x6903,
+0x6904,0x6906,0x6907,0x6908,0x6909,0x690A,0x690C,0x690F,
+0x6911,0x6913,0x6914,0x6915,0x6916,0x6917,0x6918,0x6919,
+0x691A,0x691B,0x691C,0x691D,0x691E,0x6921,0x6922,0x6923,
+0x6925,0x6926,0x6927,0x6928,0x6929,0x692A,0x692B,0x692C,
+0x692E,0x692F,0x6931,0x6932,0x6933,0x6935,0x6936,0x6937,
+0x6938,0x693A,0x693B,0x693C,0x693E,0x6940,0x6941,0x6943,
+0x6944,0x6945,0x6946,0x6947,0x6948,0x6949,0x694A,0x694B,
+0x694C,0x694D,0x694E,0x694F,0x6950,0x6951,0x6952,0x6953,
+0x6955,0x6956,0x6958,0x6959,0x695B,0x695C,0x695F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6961,0x6962,0x6964,0x6965,0x6967,0x6968,0x6969,0x696A,
+0x696C,0x696D,0x696F,0x6970,0x6972,0x6973,0x6974,0x6975,
+0x6976,0x697A,0x697B,0x697D,0x697E,0x697F,0x6981,0x6983,
+0x6985,0x698A,0x698B,0x698C,0x698E,0x698F,0x6990,0x6991,
+0x6992,0x6993,0x6996,0x6997,0x6999,0x699A,0x699D,0x699E,
+0x699F,0x69A0,0x69A1,0x69A2,0x69A3,0x69A4,0x69A5,0x69A6,
+0x69A9,0x69AA,0x69AC,0x69AE,0x69AF,0x69B0,0x69B2,0x69B3,
+0x69B5,0x69B6,0x69B8,0x69B9,0x69BA,0x69BC,0x69BD, 0,
+0x69BE,0x69BF,0x69C0,0x69C2,0x69C3,0x69C4,0x69C5,0x69C6,
+0x69C7,0x69C8,0x69C9,0x69CB,0x69CD,0x69CF,0x69D1,0x69D2,
+0x69D3,0x69D5,0x69D6,0x69D7,0x69D8,0x69D9,0x69DA,0x69DC,
+0x69DD,0x69DE,0x69E1,0x69E2,0x69E3,0x69E4,0x69E5,0x69E6,
+0x69E7,0x69E8,0x69E9,0x69EA,0x69EB,0x69EC,0x69EE,0x69EF,
+0x69F0,0x69F1,0x69F3,0x69F4,0x69F5,0x69F6,0x69F7,0x69F8,
+0x69F9,0x69FA,0x69FB,0x69FC,0x69FE,0x6A00,0x6A01,0x6A02,
+0x6A03,0x6A04,0x6A05,0x6A06,0x6A07,0x6A08,0x6A09,0x6A0B,
+0x6A0C,0x6A0D,0x6A0E,0x6A0F,0x6A10,0x6A11,0x6A12,0x6A13,
+0x6A14,0x6A15,0x6A16,0x6A19,0x6A1A,0x6A1B,0x6A1C,0x6A1D,
+0x6A1E,0x6A20,0x6A22,0x6A23,0x6A24,0x6A25,0x6A26,0x6A27,
+0x6A29,0x6A2B,0x6A2C,0x6A2D,0x6A2E,0x6A30,0x6A32,0x6A33,
+0x6A34,0x6A36,0x6A37,0x6A38,0x6A39,0x6A3A,0x6A3B,0x6A3C,
+0x6A3F,0x6A40,0x6A41,0x6A42,0x6A43,0x6A45,0x6A46,0x6A48,
+0x6A49,0x6A4A,0x6A4B,0x6A4C,0x6A4D,0x6A4E,0x6A4F,0x6A51,
+0x6A52,0x6A53,0x6A54,0x6A55,0x6A56,0x6A57,0x6A5A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6A5C,0x6A5D,0x6A5E,0x6A5F,0x6A60,0x6A62,0x6A63,0x6A64,
+0x6A66,0x6A67,0x6A68,0x6A69,0x6A6A,0x6A6B,0x6A6C,0x6A6D,
+0x6A6E,0x6A6F,0x6A70,0x6A72,0x6A73,0x6A74,0x6A75,0x6A76,
+0x6A77,0x6A78,0x6A7A,0x6A7B,0x6A7D,0x6A7E,0x6A7F,0x6A81,
+0x6A82,0x6A83,0x6A85,0x6A86,0x6A87,0x6A88,0x6A89,0x6A8A,
+0x6A8B,0x6A8C,0x6A8D,0x6A8F,0x6A92,0x6A93,0x6A94,0x6A95,
+0x6A96,0x6A98,0x6A99,0x6A9A,0x6A9B,0x6A9C,0x6A9D,0x6A9E,
+0x6A9F,0x6AA1,0x6AA2,0x6AA3,0x6AA4,0x6AA5,0x6AA6, 0,
+0x6AA7,0x6AA8,0x6AAA,0x6AAD,0x6AAE,0x6AAF,0x6AB0,0x6AB1,
+0x6AB2,0x6AB3,0x6AB4,0x6AB5,0x6AB6,0x6AB7,0x6AB8,0x6AB9,
+0x6ABA,0x6ABB,0x6ABC,0x6ABD,0x6ABE,0x6ABF,0x6AC0,0x6AC1,
+0x6AC2,0x6AC3,0x6AC4,0x6AC5,0x6AC6,0x6AC7,0x6AC8,0x6AC9,
+0x6ACA,0x6ACB,0x6ACC,0x6ACD,0x6ACE,0x6ACF,0x6AD0,0x6AD1,
+0x6AD2,0x6AD3,0x6AD4,0x6AD5,0x6AD6,0x6AD7,0x6AD8,0x6AD9,
+0x6ADA,0x6ADB,0x6ADC,0x6ADD,0x6ADE,0x6ADF,0x6AE0,0x6AE1,
+0x6AE2,0x6AE3,0x6AE4,0x6AE5,0x6AE6,0x6AE7,0x6AE8,0x6AE9,
+0x6AEA,0x6AEB,0x6AEC,0x6AED,0x6AEE,0x6AEF,0x6AF0,0x6AF1,
+0x6AF2,0x6AF3,0x6AF4,0x6AF5,0x6AF6,0x6AF7,0x6AF8,0x6AF9,
+0x6AFA,0x6AFB,0x6AFC,0x6AFD,0x6AFE,0x6AFF,0x6B00,0x6B01,
+0x6B02,0x6B03,0x6B04,0x6B05,0x6B06,0x6B07,0x6B08,0x6B09,
+0x6B0A,0x6B0B,0x6B0C,0x6B0D,0x6B0E,0x6B0F,0x6B10,0x6B11,
+0x6B12,0x6B13,0x6B14,0x6B15,0x6B16,0x6B17,0x6B18,0x6B19,
+0x6B1A,0x6B1B,0x6B1C,0x6B1D,0x6B1E,0x6B1F,0x6B25,0x6B26,
+0x6B28,0x6B29,0x6B2A,0x6B2B,0x6B2C,0x6B2D,0x6B2E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6B2F,0x6B30,0x6B31,0x6B33,0x6B34,0x6B35,0x6B36,0x6B38,
+0x6B3B,0x6B3C,0x6B3D,0x6B3F,0x6B40,0x6B41,0x6B42,0x6B44,
+0x6B45,0x6B48,0x6B4A,0x6B4B,0x6B4D,0x6B4E,0x6B4F,0x6B50,
+0x6B51,0x6B52,0x6B53,0x6B54,0x6B55,0x6B56,0x6B57,0x6B58,
+0x6B5A,0x6B5B,0x6B5C,0x6B5D,0x6B5E,0x6B5F,0x6B60,0x6B61,
+0x6B68,0x6B69,0x6B6B,0x6B6C,0x6B6D,0x6B6E,0x6B6F,0x6B70,
+0x6B71,0x6B72,0x6B73,0x6B74,0x6B75,0x6B76,0x6B77,0x6B78,
+0x6B7A,0x6B7D,0x6B7E,0x6B7F,0x6B80,0x6B85,0x6B88, 0,
+0x6B8C,0x6B8E,0x6B8F,0x6B90,0x6B91,0x6B94,0x6B95,0x6B97,
+0x6B98,0x6B99,0x6B9C,0x6B9D,0x6B9E,0x6B9F,0x6BA0,0x6BA2,
+0x6BA3,0x6BA4,0x6BA5,0x6BA6,0x6BA7,0x6BA8,0x6BA9,0x6BAB,
+0x6BAC,0x6BAD,0x6BAE,0x6BAF,0x6BB0,0x6BB1,0x6BB2,0x6BB6,
+0x6BB8,0x6BB9,0x6BBA,0x6BBB,0x6BBC,0x6BBD,0x6BBE,0x6BC0,
+0x6BC3,0x6BC4,0x6BC6,0x6BC7,0x6BC8,0x6BC9,0x6BCA,0x6BCC,
+0x6BCE,0x6BD0,0x6BD1,0x6BD8,0x6BDA,0x6BDC,0x6BDD,0x6BDE,
+0x6BDF,0x6BE0,0x6BE2,0x6BE3,0x6BE4,0x6BE5,0x6BE6,0x6BE7,
+0x6BE8,0x6BE9,0x6BEC,0x6BED,0x6BEE,0x6BF0,0x6BF1,0x6BF2,
+0x6BF4,0x6BF6,0x6BF7,0x6BF8,0x6BFA,0x6BFB,0x6BFC,0x6BFE,
+0x6BFF,0x6C00,0x6C01,0x6C02,0x6C03,0x6C04,0x6C08,0x6C09,
+0x6C0A,0x6C0B,0x6C0C,0x6C0E,0x6C12,0x6C17,0x6C1C,0x6C1D,
+0x6C1E,0x6C20,0x6C23,0x6C25,0x6C2B,0x6C2C,0x6C2D,0x6C31,
+0x6C33,0x6C36,0x6C37,0x6C39,0x6C3A,0x6C3B,0x6C3C,0x6C3E,
+0x6C3F,0x6C43,0x6C44,0x6C45,0x6C48,0x6C4B,0x6C4C,0x6C4D,
+0x6C4E,0x6C4F,0x6C51,0x6C52,0x6C53,0x6C56,0x6C58, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C59,0x6C5A,0x6C62,0x6C63,0x6C65,0x6C66,0x6C67,0x6C6B,
+0x6C6C,0x6C6D,0x6C6E,0x6C6F,0x6C71,0x6C73,0x6C75,0x6C77,
+0x6C78,0x6C7A,0x6C7B,0x6C7C,0x6C7F,0x6C80,0x6C84,0x6C87,
+0x6C8A,0x6C8B,0x6C8D,0x6C8E,0x6C91,0x6C92,0x6C95,0x6C96,
+0x6C97,0x6C98,0x6C9A,0x6C9C,0x6C9D,0x6C9E,0x6CA0,0x6CA2,
+0x6CA8,0x6CAC,0x6CAF,0x6CB0,0x6CB4,0x6CB5,0x6CB6,0x6CB7,
+0x6CBA,0x6CC0,0x6CC1,0x6CC2,0x6CC3,0x6CC6,0x6CC7,0x6CC8,
+0x6CCB,0x6CCD,0x6CCE,0x6CCF,0x6CD1,0x6CD2,0x6CD8, 0,
+0x6CD9,0x6CDA,0x6CDC,0x6CDD,0x6CDF,0x6CE4,0x6CE6,0x6CE7,
+0x6CE9,0x6CEC,0x6CED,0x6CF2,0x6CF4,0x6CF9,0x6CFF,0x6D00,
+0x6D02,0x6D03,0x6D05,0x6D06,0x6D08,0x6D09,0x6D0A,0x6D0D,
+0x6D0F,0x6D10,0x6D11,0x6D13,0x6D14,0x6D15,0x6D16,0x6D18,
+0x6D1C,0x6D1D,0x6D1F,0x6D20,0x6D21,0x6D22,0x6D23,0x6D24,
+0x6D26,0x6D28,0x6D29,0x6D2C,0x6D2D,0x6D2F,0x6D30,0x6D34,
+0x6D36,0x6D37,0x6D38,0x6D3A,0x6D3F,0x6D40,0x6D42,0x6D44,
+0x6D49,0x6D4C,0x6D50,0x6D55,0x6D56,0x6D57,0x6D58,0x6D5B,
+0x6D5D,0x6D5F,0x6D61,0x6D62,0x6D64,0x6D65,0x6D67,0x6D68,
+0x6D6B,0x6D6C,0x6D6D,0x6D70,0x6D71,0x6D72,0x6D73,0x6D75,
+0x6D76,0x6D79,0x6D7A,0x6D7B,0x6D7D,0x6D7E,0x6D7F,0x6D80,
+0x6D81,0x6D83,0x6D84,0x6D86,0x6D87,0x6D8A,0x6D8B,0x6D8D,
+0x6D8F,0x6D90,0x6D92,0x6D96,0x6D97,0x6D98,0x6D99,0x6D9A,
+0x6D9C,0x6DA2,0x6DA5,0x6DAC,0x6DAD,0x6DB0,0x6DB1,0x6DB3,
+0x6DB4,0x6DB6,0x6DB7,0x6DB9,0x6DBA,0x6DBB,0x6DBC,0x6DBD,
+0x6DBE,0x6DC1,0x6DC2,0x6DC3,0x6DC8,0x6DC9,0x6DCA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6DCD,0x6DCE,0x6DCF,0x6DD0,0x6DD2,0x6DD3,0x6DD4,0x6DD5,
+0x6DD7,0x6DDA,0x6DDB,0x6DDC,0x6DDF,0x6DE2,0x6DE3,0x6DE5,
+0x6DE7,0x6DE8,0x6DE9,0x6DEA,0x6DED,0x6DEF,0x6DF0,0x6DF2,
+0x6DF4,0x6DF5,0x6DF6,0x6DF8,0x6DFA,0x6DFD,0x6DFE,0x6DFF,
+0x6E00,0x6E01,0x6E02,0x6E03,0x6E04,0x6E06,0x6E07,0x6E08,
+0x6E09,0x6E0B,0x6E0F,0x6E12,0x6E13,0x6E15,0x6E18,0x6E19,
+0x6E1B,0x6E1C,0x6E1E,0x6E1F,0x6E22,0x6E26,0x6E27,0x6E28,
+0x6E2A,0x6E2C,0x6E2E,0x6E30,0x6E31,0x6E33,0x6E35, 0,
+0x6E36,0x6E37,0x6E39,0x6E3B,0x6E3C,0x6E3D,0x6E3E,0x6E3F,
+0x6E40,0x6E41,0x6E42,0x6E45,0x6E46,0x6E47,0x6E48,0x6E49,
+0x6E4A,0x6E4B,0x6E4C,0x6E4F,0x6E50,0x6E51,0x6E52,0x6E55,
+0x6E57,0x6E59,0x6E5A,0x6E5C,0x6E5D,0x6E5E,0x6E60,0x6E61,
+0x6E62,0x6E63,0x6E64,0x6E65,0x6E66,0x6E67,0x6E68,0x6E69,
+0x6E6A,0x6E6C,0x6E6D,0x6E6F,0x6E70,0x6E71,0x6E72,0x6E73,
+0x6E74,0x6E75,0x6E76,0x6E77,0x6E78,0x6E79,0x6E7A,0x6E7B,
+0x6E7C,0x6E7D,0x6E80,0x6E81,0x6E82,0x6E84,0x6E87,0x6E88,
+0x6E8A,0x6E8B,0x6E8C,0x6E8D,0x6E8E,0x6E91,0x6E92,0x6E93,
+0x6E94,0x6E95,0x6E96,0x6E97,0x6E99,0x6E9A,0x6E9B,0x6E9D,
+0x6E9E,0x6EA0,0x6EA1,0x6EA3,0x6EA4,0x6EA6,0x6EA8,0x6EA9,
+0x6EAB,0x6EAC,0x6EAD,0x6EAE,0x6EB0,0x6EB3,0x6EB5,0x6EB8,
+0x6EB9,0x6EBC,0x6EBE,0x6EBF,0x6EC0,0x6EC3,0x6EC4,0x6EC5,
+0x6EC6,0x6EC8,0x6EC9,0x6ECA,0x6ECC,0x6ECD,0x6ECE,0x6ED0,
+0x6ED2,0x6ED6,0x6ED8,0x6ED9,0x6EDB,0x6EDC,0x6EDD,0x6EE3,
+0x6EE7,0x6EEA,0x6EEB,0x6EEC,0x6EED,0x6EEE,0x6EEF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6EF0,0x6EF1,0x6EF2,0x6EF3,0x6EF5,0x6EF6,0x6EF7,0x6EF8,
+0x6EFA,0x6EFB,0x6EFC,0x6EFD,0x6EFE,0x6EFF,0x6F00,0x6F01,
+0x6F03,0x6F04,0x6F05,0x6F07,0x6F08,0x6F0A,0x6F0B,0x6F0C,
+0x6F0D,0x6F0E,0x6F10,0x6F11,0x6F12,0x6F16,0x6F17,0x6F18,
+0x6F19,0x6F1A,0x6F1B,0x6F1C,0x6F1D,0x6F1E,0x6F1F,0x6F21,
+0x6F22,0x6F23,0x6F25,0x6F26,0x6F27,0x6F28,0x6F2C,0x6F2E,
+0x6F30,0x6F32,0x6F34,0x6F35,0x6F37,0x6F38,0x6F39,0x6F3A,
+0x6F3B,0x6F3C,0x6F3D,0x6F3F,0x6F40,0x6F41,0x6F42, 0,
+0x6F43,0x6F44,0x6F45,0x6F48,0x6F49,0x6F4A,0x6F4C,0x6F4E,
+0x6F4F,0x6F50,0x6F51,0x6F52,0x6F53,0x6F54,0x6F55,0x6F56,
+0x6F57,0x6F59,0x6F5A,0x6F5B,0x6F5D,0x6F5F,0x6F60,0x6F61,
+0x6F63,0x6F64,0x6F65,0x6F67,0x6F68,0x6F69,0x6F6A,0x6F6B,
+0x6F6C,0x6F6F,0x6F70,0x6F71,0x6F73,0x6F75,0x6F76,0x6F77,
+0x6F79,0x6F7B,0x6F7D,0x6F7E,0x6F7F,0x6F80,0x6F81,0x6F82,
+0x6F83,0x6F85,0x6F86,0x6F87,0x6F8A,0x6F8B,0x6F8F,0x6F90,
+0x6F91,0x6F92,0x6F93,0x6F94,0x6F95,0x6F96,0x6F97,0x6F98,
+0x6F99,0x6F9A,0x6F9B,0x6F9D,0x6F9E,0x6F9F,0x6FA0,0x6FA2,
+0x6FA3,0x6FA4,0x6FA5,0x6FA6,0x6FA8,0x6FA9,0x6FAA,0x6FAB,
+0x6FAC,0x6FAD,0x6FAE,0x6FAF,0x6FB0,0x6FB1,0x6FB2,0x6FB4,
+0x6FB5,0x6FB7,0x6FB8,0x6FBA,0x6FBB,0x6FBC,0x6FBD,0x6FBE,
+0x6FBF,0x6FC1,0x6FC3,0x6FC4,0x6FC5,0x6FC6,0x6FC7,0x6FC8,
+0x6FCA,0x6FCB,0x6FCC,0x6FCD,0x6FCE,0x6FCF,0x6FD0,0x6FD3,
+0x6FD4,0x6FD5,0x6FD6,0x6FD7,0x6FD8,0x6FD9,0x6FDA,0x6FDB,
+0x6FDC,0x6FDD,0x6FDF,0x6FE2,0x6FE3,0x6FE4,0x6FE5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6FE6,0x6FE7,0x6FE8,0x6FE9,0x6FEA,0x6FEB,0x6FEC,0x6FED,
+0x6FF0,0x6FF1,0x6FF2,0x6FF3,0x6FF4,0x6FF5,0x6FF6,0x6FF7,
+0x6FF8,0x6FF9,0x6FFA,0x6FFB,0x6FFC,0x6FFD,0x6FFE,0x6FFF,
+0x7000,0x7001,0x7002,0x7003,0x7004,0x7005,0x7006,0x7007,
+0x7008,0x7009,0x700A,0x700B,0x700C,0x700D,0x700E,0x700F,
+0x7010,0x7012,0x7013,0x7014,0x7015,0x7016,0x7017,0x7018,
+0x7019,0x701C,0x701D,0x701E,0x701F,0x7020,0x7021,0x7022,
+0x7024,0x7025,0x7026,0x7027,0x7028,0x7029,0x702A, 0,
+0x702B,0x702C,0x702D,0x702E,0x702F,0x7030,0x7031,0x7032,
+0x7033,0x7034,0x7036,0x7037,0x7038,0x703A,0x703B,0x703C,
+0x703D,0x703E,0x703F,0x7040,0x7041,0x7042,0x7043,0x7044,
+0x7045,0x7046,0x7047,0x7048,0x7049,0x704A,0x704B,0x704D,
+0x704E,0x7050,0x7051,0x7052,0x7053,0x7054,0x7055,0x7056,
+0x7057,0x7058,0x7059,0x705A,0x705B,0x705C,0x705D,0x705F,
+0x7060,0x7061,0x7062,0x7063,0x7064,0x7065,0x7066,0x7067,
+0x7068,0x7069,0x706A,0x706E,0x7071,0x7072,0x7073,0x7074,
+0x7077,0x7079,0x707A,0x707B,0x707D,0x7081,0x7082,0x7083,
+0x7084,0x7086,0x7087,0x7088,0x708B,0x708C,0x708D,0x708F,
+0x7090,0x7091,0x7093,0x7097,0x7098,0x709A,0x709B,0x709E,
+0x709F,0x70A0,0x70A1,0x70A2,0x70A3,0x70A4,0x70A5,0x70A6,
+0x70A7,0x70A8,0x70A9,0x70AA,0x70B0,0x70B2,0x70B4,0x70B5,
+0x70B6,0x70BA,0x70BE,0x70BF,0x70C4,0x70C5,0x70C6,0x70C7,
+0x70C9,0x70CB,0x70CC,0x70CD,0x70CE,0x70CF,0x70D0,0x70D1,
+0x70D2,0x70D3,0x70D4,0x70D5,0x70D6,0x70D7,0x70DA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x70DC,0x70DD,0x70DE,0x70E0,0x70E1,0x70E2,0x70E3,0x70E5,
+0x70EA,0x70EE,0x70F0,0x70F1,0x70F2,0x70F3,0x70F4,0x70F5,
+0x70F6,0x70F8,0x70FA,0x70FB,0x70FC,0x70FE,0x70FF,0x7100,
+0x7101,0x7102,0x7103,0x7104,0x7105,0x7106,0x7107,0x7108,
+0x710B,0x710C,0x710D,0x710E,0x710F,0x7111,0x7112,0x7114,
+0x7117,0x711B,0x711C,0x711D,0x711E,0x711F,0x7120,0x7121,
+0x7122,0x7123,0x7124,0x7125,0x7127,0x7128,0x7129,0x712A,
+0x712B,0x712C,0x712D,0x712E,0x7132,0x7133,0x7134, 0,
+0x7135,0x7137,0x7138,0x7139,0x713A,0x713B,0x713C,0x713D,
+0x713E,0x713F,0x7140,0x7141,0x7142,0x7143,0x7144,0x7146,
+0x7147,0x7148,0x7149,0x714B,0x714D,0x714F,0x7150,0x7151,
+0x7152,0x7153,0x7154,0x7155,0x7156,0x7157,0x7158,0x7159,
+0x715A,0x715B,0x715D,0x715F,0x7160,0x7161,0x7162,0x7163,
+0x7165,0x7169,0x716A,0x716B,0x716C,0x716D,0x716F,0x7170,
+0x7171,0x7174,0x7175,0x7176,0x7177,0x7179,0x717B,0x717C,
+0x717E,0x717F,0x7180,0x7181,0x7182,0x7183,0x7185,0x7186,
+0x7187,0x7188,0x7189,0x718B,0x718C,0x718D,0x718E,0x7190,
+0x7191,0x7192,0x7193,0x7195,0x7196,0x7197,0x719A,0x719B,
+0x719C,0x719D,0x719E,0x71A1,0x71A2,0x71A3,0x71A4,0x71A5,
+0x71A6,0x71A7,0x71A9,0x71AA,0x71AB,0x71AD,0x71AE,0x71AF,
+0x71B0,0x71B1,0x71B2,0x71B4,0x71B6,0x71B7,0x71B8,0x71BA,
+0x71BB,0x71BC,0x71BD,0x71BE,0x71BF,0x71C0,0x71C1,0x71C2,
+0x71C4,0x71C5,0x71C6,0x71C7,0x71C8,0x71C9,0x71CA,0x71CB,
+0x71CC,0x71CD,0x71CF,0x71D0,0x71D1,0x71D2,0x71D3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x71D6,0x71D7,0x71D8,0x71D9,0x71DA,0x71DB,0x71DC,0x71DD,
+0x71DE,0x71DF,0x71E1,0x71E2,0x71E3,0x71E4,0x71E6,0x71E8,
+0x71E9,0x71EA,0x71EB,0x71EC,0x71ED,0x71EF,0x71F0,0x71F1,
+0x71F2,0x71F3,0x71F4,0x71F5,0x71F6,0x71F7,0x71F8,0x71FA,
+0x71FB,0x71FC,0x71FD,0x71FE,0x71FF,0x7200,0x7201,0x7202,
+0x7203,0x7204,0x7205,0x7207,0x7208,0x7209,0x720A,0x720B,
+0x720C,0x720D,0x720E,0x720F,0x7210,0x7211,0x7212,0x7213,
+0x7214,0x7215,0x7216,0x7217,0x7218,0x7219,0x721A, 0,
+0x721B,0x721C,0x721E,0x721F,0x7220,0x7221,0x7222,0x7223,
+0x7224,0x7225,0x7226,0x7227,0x7229,0x722B,0x722D,0x722E,
+0x722F,0x7232,0x7233,0x7234,0x723A,0x723C,0x723E,0x7240,
+0x7241,0x7242,0x7243,0x7244,0x7245,0x7246,0x7249,0x724A,
+0x724B,0x724E,0x724F,0x7250,0x7251,0x7253,0x7254,0x7255,
+0x7257,0x7258,0x725A,0x725C,0x725E,0x7260,0x7263,0x7264,
+0x7265,0x7268,0x726A,0x726B,0x726C,0x726D,0x7270,0x7271,
+0x7273,0x7274,0x7276,0x7277,0x7278,0x727B,0x727C,0x727D,
+0x7282,0x7283,0x7285,0x7286,0x7287,0x7288,0x7289,0x728C,
+0x728E,0x7290,0x7291,0x7293,0x7294,0x7295,0x7296,0x7297,
+0x7298,0x7299,0x729A,0x729B,0x729C,0x729D,0x729E,0x72A0,
+0x72A1,0x72A2,0x72A3,0x72A4,0x72A5,0x72A6,0x72A7,0x72A8,
+0x72A9,0x72AA,0x72AB,0x72AE,0x72B1,0x72B2,0x72B3,0x72B5,
+0x72BA,0x72BB,0x72BC,0x72BD,0x72BE,0x72BF,0x72C0,0x72C5,
+0x72C6,0x72C7,0x72C9,0x72CA,0x72CB,0x72CC,0x72CF,0x72D1,
+0x72D3,0x72D4,0x72D5,0x72D6,0x72D8,0x72DA,0x72DB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3000,0x3001,0x3002,0x00B7,0x02C9,0x02C7,0x00A8,
+0x3003,0x3005,0x2014,0xFF5E,0x2016,0x2026,0x2018,0x2019,
+0x201C,0x201D,0x3014,0x3015,0x3008,0x3009,0x300A,0x300B,
+0x300C,0x300D,0x300E,0x300F,0x3016,0x3017,0x3010,0x3011,
+0x00B1,0x00D7,0x00F7,0x2236,0x2227,0x2228,0x2211,0x220F,
+0x222A,0x2229,0x2208,0x2237,0x221A,0x22A5,0x2225,0x2220,
+0x2312,0x2299,0x222B,0x222E,0x2261,0x224C,0x2248,0x223D,
+0x221D,0x2260,0x226E,0x226F,0x2264,0x2265,0x221E,0x2235,
+0x2234,0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFF04,
+0x00A4,0xFFE0,0xFFE1,0x2030,0x00A7,0x2116,0x2606,0x2605,
+0x25CB,0x25CF,0x25CE,0x25C7,0x25C6,0x25A1,0x25A0,0x25B3,
+0x25B2,0x203B,0x2192,0x2190,0x2191,0x2193,0x3013, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,
+0x2177,0x2178,0x2179, 0, 0, 0, 0, 0,
+ 0,0x2488,0x2489,0x248A,0x248B,0x248C,0x248D,0x248E,
+0x248F,0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,
+0x2497,0x2498,0x2499,0x249A,0x249B,0x2474,0x2475,0x2476,
+0x2477,0x2478,0x2479,0x247A,0x247B,0x247C,0x247D,0x247E,
+0x247F,0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,
+0x2487,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,
+0x2467,0x2468,0x2469, 0, 0,0x3220,0x3221,0x3222,
+0x3223,0x3224,0x3225,0x3226,0x3227,0x3228,0x3229, 0,
+ 0,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,
+0x2167,0x2168,0x2169,0x216A,0x216B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFF01,0xFF02,0xFF03,0xFFE5,0xFF05,0xFF06,0xFF07,
+0xFF08,0xFF09,0xFF0A,0xFF0B,0xFF0C,0xFF0D,0xFF0E,0xFF0F,
+0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,
+0xFF18,0xFF19,0xFF1A,0xFF1B,0xFF1C,0xFF1D,0xFF1E,0xFF1F,
+0xFF20,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,
+0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,
+0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
+0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,
+0xFF40,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,
+0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,
+0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,
+0xFF58,0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFFE3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,
+0x3048,0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,
+0x3050,0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,
+0x3058,0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,
+0x3060,0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,
+0x3068,0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,
+0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,
+0x3078,0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,
+0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,
+0x3088,0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,
+0x3090,0x3091,0x3092,0x3093, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,
+0x30A8,0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,
+0x30B0,0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,
+0x30B8,0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,
+0x30C0,0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,
+0x30C8,0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,
+0x30D0,0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,
+0x30D8,0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,
+0x30E0,0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,
+0x30E8,0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,
+0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,
+0x0398,0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,
+0x03A0,0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,
+0x03A9, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,
+0x03B8,0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,
+0x03C0,0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,
+0x03C9, 0, 0, 0, 0, 0, 0, 0,
+0xFE35,0xFE36,0xFE39,0xFE3A,0xFE3F,0xFE40,0xFE3D,0xFE3E,
+0xFE41,0xFE42,0xFE43,0xFE44, 0, 0,0xFE3B,0xFE3C,
+0xFE37,0xFE38,0xFE31, 0,0xFE33,0xFE34, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,
+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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,
+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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x02CA,0x02CB,0x02D9,0x2013,0x2015,0x2025,0x2035,0x2105,
+0x2109,0x2196,0x2197,0x2198,0x2199,0x2215,0x221F,0x2223,
+0x2252,0x2266,0x2267,0x22BF,0x2550,0x2551,0x2552,0x2553,
+0x2554,0x2555,0x2556,0x2557,0x2558,0x2559,0x255A,0x255B,
+0x255C,0x255D,0x255E,0x255F,0x2560,0x2561,0x2562,0x2563,
+0x2564,0x2565,0x2566,0x2567,0x2568,0x2569,0x256A,0x256B,
+0x256C,0x256D,0x256E,0x256F,0x2570,0x2571,0x2572,0x2573,
+0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,0x2587, 0,
+0x2588,0x2589,0x258A,0x258B,0x258C,0x258D,0x258E,0x258F,
+0x2593,0x2594,0x2595,0x25BC,0x25BD,0x25E2,0x25E3,0x25E4,
+0x25E5,0x2609,0x2295,0x3012,0x301D,0x301E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0101,0x00E1,0x01CE,0x00E0,0x0113,0x00E9,0x011B,
+0x00E8,0x012B,0x00ED,0x01D0,0x00EC,0x014D,0x00F3,0x01D2,
+0x00F2,0x016B,0x00FA,0x01D4,0x00F9,0x01D6,0x01D8,0x01DA,
+0x01DC,0x00FC,0x00EA,0x0251, 0,0x0144,0x0148, 0,
+0x0261, 0, 0, 0, 0,0x3105,0x3106,0x3107,
+0x3108,0x3109,0x310A,0x310B,0x310C,0x310D,0x310E,0x310F,
+0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117,
+0x3118,0x3119,0x311A,0x311B,0x311C,0x311D,0x311E,0x311F,
+0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127,
+0x3128,0x3129, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3021,0x3022,0x3023,0x3024,0x3025,0x3026,0x3027,0x3028,
+0x3029,0x32A3,0x338E,0x338F,0x339C,0x339D,0x339E,0x33A1,
+0x33C4,0x33CE,0x33D1,0x33D2,0x33D5,0xFE30,0xFFE2,0xFFE4,
+ 0,0x2121,0x3231, 0,0x2010, 0, 0, 0,
+0x30FC,0x309B,0x309C,0x30FD,0x30FE,0x3006,0x309D,0x309E,
+0xFE49,0xFE4A,0xFE4B,0xFE4C,0xFE4D,0xFE4E,0xFE4F,0xFE50,
+0xFE51,0xFE52,0xFE54,0xFE55,0xFE56,0xFE57,0xFE59,0xFE5A,
+0xFE5B,0xFE5C,0xFE5D,0xFE5E,0xFE5F,0xFE60,0xFE61, 0,
+0xFE62,0xFE63,0xFE64,0xFE65,0xFE66,0xFE68,0xFE69,0xFE6A,
+0xFE6B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3007, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2500,0x2501,0x2502,0x2503,
+0x2504,0x2505,0x2506,0x2507,0x2508,0x2509,0x250A,0x250B,
+0x250C,0x250D,0x250E,0x250F,0x2510,0x2511,0x2512,0x2513,
+0x2514,0x2515,0x2516,0x2517,0x2518,0x2519,0x251A,0x251B,
+0x251C,0x251D,0x251E,0x251F,0x2520,0x2521,0x2522,0x2523,
+0x2524,0x2525,0x2526,0x2527,0x2528,0x2529,0x252A,0x252B,
+0x252C,0x252D,0x252E,0x252F,0x2530,0x2531,0x2532,0x2533,
+0x2534,0x2535,0x2536,0x2537,0x2538,0x2539,0x253A,0x253B,
+0x253C,0x253D,0x253E,0x253F,0x2540,0x2541,0x2542,0x2543,
+0x2544,0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x72DC,0x72DD,0x72DF,0x72E2,0x72E3,0x72E4,0x72E5,0x72E6,
+0x72E7,0x72EA,0x72EB,0x72F5,0x72F6,0x72F9,0x72FD,0x72FE,
+0x72FF,0x7300,0x7302,0x7304,0x7305,0x7306,0x7307,0x7308,
+0x7309,0x730B,0x730C,0x730D,0x730F,0x7310,0x7311,0x7312,
+0x7314,0x7318,0x7319,0x731A,0x731F,0x7320,0x7323,0x7324,
+0x7326,0x7327,0x7328,0x732D,0x732F,0x7330,0x7332,0x7333,
+0x7335,0x7336,0x733A,0x733B,0x733C,0x733D,0x7340,0x7341,
+0x7342,0x7343,0x7344,0x7345,0x7346,0x7347,0x7348, 0,
+0x7349,0x734A,0x734B,0x734C,0x734E,0x734F,0x7351,0x7353,
+0x7354,0x7355,0x7356,0x7358,0x7359,0x735A,0x735B,0x735C,
+0x735D,0x735E,0x735F,0x7361,0x7362,0x7363,0x7364,0x7365,
+0x7366,0x7367,0x7368,0x7369,0x736A,0x736B,0x736E,0x7370,
+0x7371, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7372,0x7373,0x7374,0x7375,0x7376,0x7377,0x7378,0x7379,
+0x737A,0x737B,0x737C,0x737D,0x737F,0x7380,0x7381,0x7382,
+0x7383,0x7385,0x7386,0x7388,0x738A,0x738C,0x738D,0x738F,
+0x7390,0x7392,0x7393,0x7394,0x7395,0x7397,0x7398,0x7399,
+0x739A,0x739C,0x739D,0x739E,0x73A0,0x73A1,0x73A3,0x73A4,
+0x73A5,0x73A6,0x73A7,0x73A8,0x73AA,0x73AC,0x73AD,0x73B1,
+0x73B4,0x73B5,0x73B6,0x73B8,0x73B9,0x73BC,0x73BD,0x73BE,
+0x73BF,0x73C1,0x73C3,0x73C4,0x73C5,0x73C6,0x73C7, 0,
+0x73CB,0x73CC,0x73CE,0x73D2,0x73D3,0x73D4,0x73D5,0x73D6,
+0x73D7,0x73D8,0x73DA,0x73DB,0x73DC,0x73DD,0x73DF,0x73E1,
+0x73E2,0x73E3,0x73E4,0x73E6,0x73E8,0x73EA,0x73EB,0x73EC,
+0x73EE,0x73EF,0x73F0,0x73F1,0x73F3,0x73F4,0x73F5,0x73F6,
+0x73F7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x73F8,0x73F9,0x73FA,0x73FB,0x73FC,0x73FD,0x73FE,0x73FF,
+0x7400,0x7401,0x7402,0x7404,0x7407,0x7408,0x740B,0x740C,
+0x740D,0x740E,0x7411,0x7412,0x7413,0x7414,0x7415,0x7416,
+0x7417,0x7418,0x7419,0x741C,0x741D,0x741E,0x741F,0x7420,
+0x7421,0x7423,0x7424,0x7427,0x7429,0x742B,0x742D,0x742F,
+0x7431,0x7432,0x7437,0x7438,0x7439,0x743A,0x743B,0x743D,
+0x743E,0x743F,0x7440,0x7442,0x7443,0x7444,0x7445,0x7446,
+0x7447,0x7448,0x7449,0x744A,0x744B,0x744C,0x744D, 0,
+0x744E,0x744F,0x7450,0x7451,0x7452,0x7453,0x7454,0x7456,
+0x7458,0x745D,0x7460,0x7461,0x7462,0x7463,0x7464,0x7465,
+0x7466,0x7467,0x7468,0x7469,0x746A,0x746B,0x746C,0x746E,
+0x746F,0x7471,0x7472,0x7473,0x7474,0x7475,0x7478,0x7479,
+0x747A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x747B,0x747C,0x747D,0x747F,0x7482,0x7484,0x7485,0x7486,
+0x7488,0x7489,0x748A,0x748C,0x748D,0x748F,0x7491,0x7492,
+0x7493,0x7494,0x7495,0x7496,0x7497,0x7498,0x7499,0x749A,
+0x749B,0x749D,0x749F,0x74A0,0x74A1,0x74A2,0x74A3,0x74A4,
+0x74A5,0x74A6,0x74AA,0x74AB,0x74AC,0x74AD,0x74AE,0x74AF,
+0x74B0,0x74B1,0x74B2,0x74B3,0x74B4,0x74B5,0x74B6,0x74B7,
+0x74B8,0x74B9,0x74BB,0x74BC,0x74BD,0x74BE,0x74BF,0x74C0,
+0x74C1,0x74C2,0x74C3,0x74C4,0x74C5,0x74C6,0x74C7, 0,
+0x74C8,0x74C9,0x74CA,0x74CB,0x74CC,0x74CD,0x74CE,0x74CF,
+0x74D0,0x74D1,0x74D3,0x74D4,0x74D5,0x74D6,0x74D7,0x74D8,
+0x74D9,0x74DA,0x74DB,0x74DD,0x74DF,0x74E1,0x74E5,0x74E7,
+0x74E8,0x74E9,0x74EA,0x74EB,0x74EC,0x74ED,0x74F0,0x74F1,
+0x74F2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x74F3,0x74F5,0x74F8,0x74F9,0x74FA,0x74FB,0x74FC,0x74FD,
+0x74FE,0x7500,0x7501,0x7502,0x7503,0x7505,0x7506,0x7507,
+0x7508,0x7509,0x750A,0x750B,0x750C,0x750E,0x7510,0x7512,
+0x7514,0x7515,0x7516,0x7517,0x751B,0x751D,0x751E,0x7520,
+0x7521,0x7522,0x7523,0x7524,0x7526,0x7527,0x752A,0x752E,
+0x7534,0x7536,0x7539,0x753C,0x753D,0x753F,0x7541,0x7542,
+0x7543,0x7544,0x7546,0x7547,0x7549,0x754A,0x754D,0x7550,
+0x7551,0x7552,0x7553,0x7555,0x7556,0x7557,0x7558, 0,
+0x755D,0x755E,0x755F,0x7560,0x7561,0x7562,0x7563,0x7564,
+0x7567,0x7568,0x7569,0x756B,0x756C,0x756D,0x756E,0x756F,
+0x7570,0x7571,0x7573,0x7575,0x7576,0x7577,0x757A,0x757B,
+0x757C,0x757D,0x757E,0x7580,0x7581,0x7582,0x7584,0x7585,
+0x7587, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7588,0x7589,0x758A,0x758C,0x758D,0x758E,0x7590,0x7593,
+0x7595,0x7598,0x759B,0x759C,0x759E,0x75A2,0x75A6,0x75A7,
+0x75A8,0x75A9,0x75AA,0x75AD,0x75B6,0x75B7,0x75BA,0x75BB,
+0x75BF,0x75C0,0x75C1,0x75C6,0x75CB,0x75CC,0x75CE,0x75CF,
+0x75D0,0x75D1,0x75D3,0x75D7,0x75D9,0x75DA,0x75DC,0x75DD,
+0x75DF,0x75E0,0x75E1,0x75E5,0x75E9,0x75EC,0x75ED,0x75EE,
+0x75EF,0x75F2,0x75F3,0x75F5,0x75F6,0x75F7,0x75F8,0x75FA,
+0x75FB,0x75FD,0x75FE,0x7602,0x7604,0x7606,0x7607, 0,
+0x7608,0x7609,0x760B,0x760D,0x760E,0x760F,0x7611,0x7612,
+0x7613,0x7614,0x7616,0x761A,0x761C,0x761D,0x761E,0x7621,
+0x7623,0x7627,0x7628,0x762C,0x762E,0x762F,0x7631,0x7632,
+0x7636,0x7637,0x7639,0x763A,0x763B,0x763D,0x7641,0x7642,
+0x7644, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7645,0x7646,0x7647,0x7648,0x7649,0x764A,0x764B,0x764E,
+0x764F,0x7650,0x7651,0x7652,0x7653,0x7655,0x7657,0x7658,
+0x7659,0x765A,0x765B,0x765D,0x765F,0x7660,0x7661,0x7662,
+0x7664,0x7665,0x7666,0x7667,0x7668,0x7669,0x766A,0x766C,
+0x766D,0x766E,0x7670,0x7671,0x7672,0x7673,0x7674,0x7675,
+0x7676,0x7677,0x7679,0x767A,0x767C,0x767F,0x7680,0x7681,
+0x7683,0x7685,0x7689,0x768A,0x768C,0x768D,0x768F,0x7690,
+0x7692,0x7694,0x7695,0x7697,0x7698,0x769A,0x769B, 0,
+0x769C,0x769D,0x769E,0x769F,0x76A0,0x76A1,0x76A2,0x76A3,
+0x76A5,0x76A6,0x76A7,0x76A8,0x76A9,0x76AA,0x76AB,0x76AC,
+0x76AD,0x76AF,0x76B0,0x76B3,0x76B5,0x76B6,0x76B7,0x76B8,
+0x76B9,0x76BA,0x76BB,0x76BC,0x76BD,0x76BE,0x76C0,0x76C1,
+0x76C3,0x554A,0x963F,0x57C3,0x6328,0x54CE,0x5509,0x54C0,
+0x7691,0x764C,0x853C,0x77EE,0x827E,0x788D,0x7231,0x9698,
+0x978D,0x6C28,0x5B89,0x4FFA,0x6309,0x6697,0x5CB8,0x80FA,
+0x6848,0x80AE,0x6602,0x76CE,0x51F9,0x6556,0x71AC,0x7FF1,
+0x8884,0x50B2,0x5965,0x61CA,0x6FB3,0x82AD,0x634C,0x6252,
+0x53ED,0x5427,0x7B06,0x516B,0x75A4,0x5DF4,0x62D4,0x8DCB,
+0x9776,0x628A,0x8019,0x575D,0x9738,0x7F62,0x7238,0x767D,
+0x67CF,0x767E,0x6446,0x4F70,0x8D25,0x62DC,0x7A17,0x6591,
+0x73ED,0x642C,0x6273,0x822C,0x9881,0x677F,0x7248,0x626E,
+0x62CC,0x4F34,0x74E3,0x534A,0x529E,0x7ECA,0x90A6,0x5E2E,
+0x6886,0x699C,0x8180,0x7ED1,0x68D2,0x78C5,0x868C,0x9551,
+0x508D,0x8C24,0x82DE,0x80DE,0x5305,0x8912,0x5265, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x76C4,0x76C7,0x76C9,0x76CB,0x76CC,0x76D3,0x76D5,0x76D9,
+0x76DA,0x76DC,0x76DD,0x76DE,0x76E0,0x76E1,0x76E2,0x76E3,
+0x76E4,0x76E6,0x76E7,0x76E8,0x76E9,0x76EA,0x76EB,0x76EC,
+0x76ED,0x76F0,0x76F3,0x76F5,0x76F6,0x76F7,0x76FA,0x76FB,
+0x76FD,0x76FF,0x7700,0x7702,0x7703,0x7705,0x7706,0x770A,
+0x770C,0x770E,0x770F,0x7710,0x7711,0x7712,0x7713,0x7714,
+0x7715,0x7716,0x7717,0x7718,0x771B,0x771C,0x771D,0x771E,
+0x7721,0x7723,0x7724,0x7725,0x7727,0x772A,0x772B, 0,
+0x772C,0x772E,0x7730,0x7731,0x7732,0x7733,0x7734,0x7739,
+0x773B,0x773D,0x773E,0x773F,0x7742,0x7744,0x7745,0x7746,
+0x7748,0x7749,0x774A,0x774B,0x774C,0x774D,0x774E,0x774F,
+0x7752,0x7753,0x7754,0x7755,0x7756,0x7757,0x7758,0x7759,
+0x775C,0x8584,0x96F9,0x4FDD,0x5821,0x9971,0x5B9D,0x62B1,
+0x62A5,0x66B4,0x8C79,0x9C8D,0x7206,0x676F,0x7891,0x60B2,
+0x5351,0x5317,0x8F88,0x80CC,0x8D1D,0x94A1,0x500D,0x72C8,
+0x5907,0x60EB,0x7119,0x88AB,0x5954,0x82EF,0x672C,0x7B28,
+0x5D29,0x7EF7,0x752D,0x6CF5,0x8E66,0x8FF8,0x903C,0x9F3B,
+0x6BD4,0x9119,0x7B14,0x5F7C,0x78A7,0x84D6,0x853D,0x6BD5,
+0x6BD9,0x6BD6,0x5E01,0x5E87,0x75F9,0x95ED,0x655D,0x5F0A,
+0x5FC5,0x8F9F,0x58C1,0x81C2,0x907F,0x965B,0x97AD,0x8FB9,
+0x7F16,0x8D2C,0x6241,0x4FBF,0x53D8,0x535E,0x8FA8,0x8FA9,
+0x8FAB,0x904D,0x6807,0x5F6A,0x8198,0x8868,0x9CD6,0x618B,
+0x522B,0x762A,0x5F6C,0x658C,0x6FD2,0x6EE8,0x5BBE,0x6448,
+0x5175,0x51B0,0x67C4,0x4E19,0x79C9,0x997C,0x70B3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x775D,0x775E,0x775F,0x7760,0x7764,0x7767,0x7769,0x776A,
+0x776D,0x776E,0x776F,0x7770,0x7771,0x7772,0x7773,0x7774,
+0x7775,0x7776,0x7777,0x7778,0x777A,0x777B,0x777C,0x7781,
+0x7782,0x7783,0x7786,0x7787,0x7788,0x7789,0x778A,0x778B,
+0x778F,0x7790,0x7793,0x7794,0x7795,0x7796,0x7797,0x7798,
+0x7799,0x779A,0x779B,0x779C,0x779D,0x779E,0x77A1,0x77A3,
+0x77A4,0x77A6,0x77A8,0x77AB,0x77AD,0x77AE,0x77AF,0x77B1,
+0x77B2,0x77B4,0x77B6,0x77B7,0x77B8,0x77B9,0x77BA, 0,
+0x77BC,0x77BE,0x77C0,0x77C1,0x77C2,0x77C3,0x77C4,0x77C5,
+0x77C6,0x77C7,0x77C8,0x77C9,0x77CA,0x77CB,0x77CC,0x77CE,
+0x77CF,0x77D0,0x77D1,0x77D2,0x77D3,0x77D4,0x77D5,0x77D6,
+0x77D8,0x77D9,0x77DA,0x77DD,0x77DE,0x77DF,0x77E0,0x77E1,
+0x77E4,0x75C5,0x5E76,0x73BB,0x83E0,0x64AD,0x62E8,0x94B5,
+0x6CE2,0x535A,0x52C3,0x640F,0x94C2,0x7B94,0x4F2F,0x5E1B,
+0x8236,0x8116,0x818A,0x6E24,0x6CCA,0x9A73,0x6355,0x535C,
+0x54FA,0x8865,0x57E0,0x4E0D,0x5E03,0x6B65,0x7C3F,0x90E8,
+0x6016,0x64E6,0x731C,0x88C1,0x6750,0x624D,0x8D22,0x776C,
+0x8E29,0x91C7,0x5F69,0x83DC,0x8521,0x9910,0x53C2,0x8695,
+0x6B8B,0x60ED,0x60E8,0x707F,0x82CD,0x8231,0x4ED3,0x6CA7,
+0x85CF,0x64CD,0x7CD9,0x69FD,0x66F9,0x8349,0x5395,0x7B56,
+0x4FA7,0x518C,0x6D4B,0x5C42,0x8E6D,0x63D2,0x53C9,0x832C,
+0x8336,0x67E5,0x78B4,0x643D,0x5BDF,0x5C94,0x5DEE,0x8BE7,
+0x62C6,0x67F4,0x8C7A,0x6400,0x63BA,0x8749,0x998B,0x8C17,
+0x7F20,0x94F2,0x4EA7,0x9610,0x98A4,0x660C,0x7316, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x77E6,0x77E8,0x77EA,0x77EF,0x77F0,0x77F1,0x77F2,0x77F4,
+0x77F5,0x77F7,0x77F9,0x77FA,0x77FB,0x77FC,0x7803,0x7804,
+0x7805,0x7806,0x7807,0x7808,0x780A,0x780B,0x780E,0x780F,
+0x7810,0x7813,0x7815,0x7819,0x781B,0x781E,0x7820,0x7821,
+0x7822,0x7824,0x7828,0x782A,0x782B,0x782E,0x782F,0x7831,
+0x7832,0x7833,0x7835,0x7836,0x783D,0x783F,0x7841,0x7842,
+0x7843,0x7844,0x7846,0x7848,0x7849,0x784A,0x784B,0x784D,
+0x784F,0x7851,0x7853,0x7854,0x7858,0x7859,0x785A, 0,
+0x785B,0x785C,0x785E,0x785F,0x7860,0x7861,0x7862,0x7863,
+0x7864,0x7865,0x7866,0x7867,0x7868,0x7869,0x786F,0x7870,
+0x7871,0x7872,0x7873,0x7874,0x7875,0x7876,0x7878,0x7879,
+0x787A,0x787B,0x787D,0x787E,0x787F,0x7880,0x7881,0x7882,
+0x7883,0x573A,0x5C1D,0x5E38,0x957F,0x507F,0x80A0,0x5382,
+0x655E,0x7545,0x5531,0x5021,0x8D85,0x6284,0x949E,0x671D,
+0x5632,0x6F6E,0x5DE2,0x5435,0x7092,0x8F66,0x626F,0x64A4,
+0x63A3,0x5F7B,0x6F88,0x90F4,0x81E3,0x8FB0,0x5C18,0x6668,
+0x5FF1,0x6C89,0x9648,0x8D81,0x886C,0x6491,0x79F0,0x57CE,
+0x6A59,0x6210,0x5448,0x4E58,0x7A0B,0x60E9,0x6F84,0x8BDA,
+0x627F,0x901E,0x9A8B,0x79E4,0x5403,0x75F4,0x6301,0x5319,
+0x6C60,0x8FDF,0x5F1B,0x9A70,0x803B,0x9F7F,0x4F88,0x5C3A,
+0x8D64,0x7FC5,0x65A5,0x70BD,0x5145,0x51B2,0x866B,0x5D07,
+0x5BA0,0x62BD,0x916C,0x7574,0x8E0C,0x7A20,0x6101,0x7B79,
+0x4EC7,0x7EF8,0x7785,0x4E11,0x81ED,0x521D,0x51FA,0x6A71,
+0x53A8,0x8E87,0x9504,0x96CF,0x6EC1,0x9664,0x695A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7884,0x7885,0x7886,0x7888,0x788A,0x788B,0x788F,0x7890,
+0x7892,0x7894,0x7895,0x7896,0x7899,0x789D,0x789E,0x78A0,
+0x78A2,0x78A4,0x78A6,0x78A8,0x78A9,0x78AA,0x78AB,0x78AC,
+0x78AD,0x78AE,0x78AF,0x78B5,0x78B6,0x78B7,0x78B8,0x78BA,
+0x78BB,0x78BC,0x78BD,0x78BF,0x78C0,0x78C2,0x78C3,0x78C4,
+0x78C6,0x78C7,0x78C8,0x78CC,0x78CD,0x78CE,0x78CF,0x78D1,
+0x78D2,0x78D3,0x78D6,0x78D7,0x78D8,0x78DA,0x78DB,0x78DC,
+0x78DD,0x78DE,0x78DF,0x78E0,0x78E1,0x78E2,0x78E3, 0,
+0x78E4,0x78E5,0x78E6,0x78E7,0x78E9,0x78EA,0x78EB,0x78ED,
+0x78EE,0x78EF,0x78F0,0x78F1,0x78F3,0x78F5,0x78F6,0x78F8,
+0x78F9,0x78FB,0x78FC,0x78FD,0x78FE,0x78FF,0x7900,0x7902,
+0x7903,0x7904,0x7906,0x7907,0x7908,0x7909,0x790A,0x790B,
+0x790C,0x7840,0x50A8,0x77D7,0x6410,0x89E6,0x5904,0x63E3,
+0x5DDD,0x7A7F,0x693D,0x4F20,0x8239,0x5598,0x4E32,0x75AE,
+0x7A97,0x5E62,0x5E8A,0x95EF,0x521B,0x5439,0x708A,0x6376,
+0x9524,0x5782,0x6625,0x693F,0x9187,0x5507,0x6DF3,0x7EAF,
+0x8822,0x6233,0x7EF0,0x75B5,0x8328,0x78C1,0x96CC,0x8F9E,
+0x6148,0x74F7,0x8BCD,0x6B64,0x523A,0x8D50,0x6B21,0x806A,
+0x8471,0x56F1,0x5306,0x4ECE,0x4E1B,0x51D1,0x7C97,0x918B,
+0x7C07,0x4FC3,0x8E7F,0x7BE1,0x7A9C,0x6467,0x5D14,0x50AC,
+0x8106,0x7601,0x7CB9,0x6DEC,0x7FE0,0x6751,0x5B58,0x5BF8,
+0x78CB,0x64AE,0x6413,0x63AA,0x632B,0x9519,0x642D,0x8FBE,
+0x7B54,0x7629,0x6253,0x5927,0x5446,0x6B79,0x50A3,0x6234,
+0x5E26,0x6B86,0x4EE3,0x8D37,0x888B,0x5F85,0x902E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x790D,0x790E,0x790F,0x7910,0x7911,0x7912,0x7914,0x7915,
+0x7916,0x7917,0x7918,0x7919,0x791A,0x791B,0x791C,0x791D,
+0x791F,0x7920,0x7921,0x7922,0x7923,0x7925,0x7926,0x7927,
+0x7928,0x7929,0x792A,0x792B,0x792C,0x792D,0x792E,0x792F,
+0x7930,0x7931,0x7932,0x7933,0x7935,0x7936,0x7937,0x7938,
+0x7939,0x793D,0x793F,0x7942,0x7943,0x7944,0x7945,0x7947,
+0x794A,0x794B,0x794C,0x794D,0x794E,0x794F,0x7950,0x7951,
+0x7952,0x7954,0x7955,0x7958,0x7959,0x7961,0x7963, 0,
+0x7964,0x7966,0x7969,0x796A,0x796B,0x796C,0x796E,0x7970,
+0x7971,0x7972,0x7973,0x7974,0x7975,0x7976,0x7979,0x797B,
+0x797C,0x797D,0x797E,0x797F,0x7982,0x7983,0x7986,0x7987,
+0x7988,0x7989,0x798B,0x798C,0x798D,0x798E,0x7990,0x7991,
+0x7992,0x6020,0x803D,0x62C5,0x4E39,0x5355,0x90F8,0x63B8,
+0x80C6,0x65E6,0x6C2E,0x4F46,0x60EE,0x6DE1,0x8BDE,0x5F39,
+0x86CB,0x5F53,0x6321,0x515A,0x8361,0x6863,0x5200,0x6363,
+0x8E48,0x5012,0x5C9B,0x7977,0x5BFC,0x5230,0x7A3B,0x60BC,
+0x9053,0x76D7,0x5FB7,0x5F97,0x7684,0x8E6C,0x706F,0x767B,
+0x7B49,0x77AA,0x51F3,0x9093,0x5824,0x4F4E,0x6EF4,0x8FEA,
+0x654C,0x7B1B,0x72C4,0x6DA4,0x7FDF,0x5AE1,0x62B5,0x5E95,
+0x5730,0x8482,0x7B2C,0x5E1D,0x5F1F,0x9012,0x7F14,0x98A0,
+0x6382,0x6EC7,0x7898,0x70B9,0x5178,0x975B,0x57AB,0x7535,
+0x4F43,0x7538,0x5E97,0x60E6,0x5960,0x6DC0,0x6BBF,0x7889,
+0x53FC,0x96D5,0x51CB,0x5201,0x6389,0x540A,0x9493,0x8C03,
+0x8DCC,0x7239,0x789F,0x8776,0x8FED,0x8C0D,0x53E0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7993,0x7994,0x7995,0x7996,0x7997,0x7998,0x7999,0x799B,
+0x799C,0x799D,0x799E,0x799F,0x79A0,0x79A1,0x79A2,0x79A3,
+0x79A4,0x79A5,0x79A6,0x79A8,0x79A9,0x79AA,0x79AB,0x79AC,
+0x79AD,0x79AE,0x79AF,0x79B0,0x79B1,0x79B2,0x79B4,0x79B5,
+0x79B6,0x79B7,0x79B8,0x79BC,0x79BF,0x79C2,0x79C4,0x79C5,
+0x79C7,0x79C8,0x79CA,0x79CC,0x79CE,0x79CF,0x79D0,0x79D3,
+0x79D4,0x79D6,0x79D7,0x79D9,0x79DA,0x79DB,0x79DC,0x79DD,
+0x79DE,0x79E0,0x79E1,0x79E2,0x79E5,0x79E8,0x79EA, 0,
+0x79EC,0x79EE,0x79F1,0x79F2,0x79F3,0x79F4,0x79F5,0x79F6,
+0x79F7,0x79F9,0x79FA,0x79FC,0x79FE,0x79FF,0x7A01,0x7A04,
+0x7A05,0x7A07,0x7A08,0x7A09,0x7A0A,0x7A0C,0x7A0F,0x7A10,
+0x7A11,0x7A12,0x7A13,0x7A15,0x7A16,0x7A18,0x7A19,0x7A1B,
+0x7A1C,0x4E01,0x76EF,0x53EE,0x9489,0x9876,0x9F0E,0x952D,
+0x5B9A,0x8BA2,0x4E22,0x4E1C,0x51AC,0x8463,0x61C2,0x52A8,
+0x680B,0x4F97,0x606B,0x51BB,0x6D1E,0x515C,0x6296,0x6597,
+0x9661,0x8C46,0x9017,0x75D8,0x90FD,0x7763,0x6BD2,0x728A,
+0x72EC,0x8BFB,0x5835,0x7779,0x8D4C,0x675C,0x9540,0x809A,
+0x5EA6,0x6E21,0x5992,0x7AEF,0x77ED,0x953B,0x6BB5,0x65AD,
+0x7F0E,0x5806,0x5151,0x961F,0x5BF9,0x58A9,0x5428,0x8E72,
+0x6566,0x987F,0x56E4,0x949D,0x76FE,0x9041,0x6387,0x54C6,
+0x591A,0x593A,0x579B,0x8EB2,0x6735,0x8DFA,0x8235,0x5241,
+0x60F0,0x5815,0x86FE,0x5CE8,0x9E45,0x4FC4,0x989D,0x8BB9,
+0x5A25,0x6076,0x5384,0x627C,0x904F,0x9102,0x997F,0x6069,
+0x800C,0x513F,0x8033,0x5C14,0x9975,0x6D31,0x4E8C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7A1D,0x7A1F,0x7A21,0x7A22,0x7A24,0x7A25,0x7A26,0x7A27,
+0x7A28,0x7A29,0x7A2A,0x7A2B,0x7A2C,0x7A2D,0x7A2E,0x7A2F,
+0x7A30,0x7A31,0x7A32,0x7A34,0x7A35,0x7A36,0x7A38,0x7A3A,
+0x7A3E,0x7A40,0x7A41,0x7A42,0x7A43,0x7A44,0x7A45,0x7A47,
+0x7A48,0x7A49,0x7A4A,0x7A4B,0x7A4C,0x7A4D,0x7A4E,0x7A4F,
+0x7A50,0x7A52,0x7A53,0x7A54,0x7A55,0x7A56,0x7A58,0x7A59,
+0x7A5A,0x7A5B,0x7A5C,0x7A5D,0x7A5E,0x7A5F,0x7A60,0x7A61,
+0x7A62,0x7A63,0x7A64,0x7A65,0x7A66,0x7A67,0x7A68, 0,
+0x7A69,0x7A6A,0x7A6B,0x7A6C,0x7A6D,0x7A6E,0x7A6F,0x7A71,
+0x7A72,0x7A73,0x7A75,0x7A7B,0x7A7C,0x7A7D,0x7A7E,0x7A82,
+0x7A85,0x7A87,0x7A89,0x7A8A,0x7A8B,0x7A8C,0x7A8E,0x7A8F,
+0x7A90,0x7A93,0x7A94,0x7A99,0x7A9A,0x7A9B,0x7A9E,0x7AA1,
+0x7AA2,0x8D30,0x53D1,0x7F5A,0x7B4F,0x4F10,0x4E4F,0x9600,
+0x6CD5,0x73D0,0x85E9,0x5E06,0x756A,0x7FFB,0x6A0A,0x77FE,
+0x9492,0x7E41,0x51E1,0x70E6,0x53CD,0x8FD4,0x8303,0x8D29,
+0x72AF,0x996D,0x6CDB,0x574A,0x82B3,0x65B9,0x80AA,0x623F,
+0x9632,0x59A8,0x4EFF,0x8BBF,0x7EBA,0x653E,0x83F2,0x975E,
+0x5561,0x98DE,0x80A5,0x532A,0x8BFD,0x5420,0x80BA,0x5E9F,
+0x6CB8,0x8D39,0x82AC,0x915A,0x5429,0x6C1B,0x5206,0x7EB7,
+0x575F,0x711A,0x6C7E,0x7C89,0x594B,0x4EFD,0x5FFF,0x6124,
+0x7CAA,0x4E30,0x5C01,0x67AB,0x8702,0x5CF0,0x950B,0x98CE,
+0x75AF,0x70FD,0x9022,0x51AF,0x7F1D,0x8BBD,0x5949,0x51E4,
+0x4F5B,0x5426,0x592B,0x6577,0x80A4,0x5B75,0x6276,0x62C2,
+0x8F90,0x5E45,0x6C1F,0x7B26,0x4F0F,0x4FD8,0x670D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7AA3,0x7AA4,0x7AA7,0x7AA9,0x7AAA,0x7AAB,0x7AAE,0x7AAF,
+0x7AB0,0x7AB1,0x7AB2,0x7AB4,0x7AB5,0x7AB6,0x7AB7,0x7AB8,
+0x7AB9,0x7ABA,0x7ABB,0x7ABC,0x7ABD,0x7ABE,0x7AC0,0x7AC1,
+0x7AC2,0x7AC3,0x7AC4,0x7AC5,0x7AC6,0x7AC7,0x7AC8,0x7AC9,
+0x7ACA,0x7ACC,0x7ACD,0x7ACE,0x7ACF,0x7AD0,0x7AD1,0x7AD2,
+0x7AD3,0x7AD4,0x7AD5,0x7AD7,0x7AD8,0x7ADA,0x7ADB,0x7ADC,
+0x7ADD,0x7AE1,0x7AE2,0x7AE4,0x7AE7,0x7AE8,0x7AE9,0x7AEA,
+0x7AEB,0x7AEC,0x7AEE,0x7AF0,0x7AF1,0x7AF2,0x7AF3, 0,
+0x7AF4,0x7AF5,0x7AF6,0x7AF7,0x7AF8,0x7AFB,0x7AFC,0x7AFE,
+0x7B00,0x7B01,0x7B02,0x7B05,0x7B07,0x7B09,0x7B0C,0x7B0D,
+0x7B0E,0x7B10,0x7B12,0x7B13,0x7B16,0x7B17,0x7B18,0x7B1A,
+0x7B1C,0x7B1D,0x7B1F,0x7B21,0x7B22,0x7B23,0x7B27,0x7B29,
+0x7B2D,0x6D6E,0x6DAA,0x798F,0x88B1,0x5F17,0x752B,0x629A,
+0x8F85,0x4FEF,0x91DC,0x65A7,0x812F,0x8151,0x5E9C,0x8150,
+0x8D74,0x526F,0x8986,0x8D4B,0x590D,0x5085,0x4ED8,0x961C,
+0x7236,0x8179,0x8D1F,0x5BCC,0x8BA3,0x9644,0x5987,0x7F1A,
+0x5490,0x5676,0x560E,0x8BE5,0x6539,0x6982,0x9499,0x76D6,
+0x6E89,0x5E72,0x7518,0x6746,0x67D1,0x7AFF,0x809D,0x8D76,
+0x611F,0x79C6,0x6562,0x8D63,0x5188,0x521A,0x94A2,0x7F38,
+0x809B,0x7EB2,0x5C97,0x6E2F,0x6760,0x7BD9,0x768B,0x9AD8,
+0x818F,0x7F94,0x7CD5,0x641E,0x9550,0x7A3F,0x544A,0x54E5,
+0x6B4C,0x6401,0x6208,0x9E3D,0x80F3,0x7599,0x5272,0x9769,
+0x845B,0x683C,0x86E4,0x9601,0x9694,0x94EC,0x4E2A,0x5404,
+0x7ED9,0x6839,0x8DDF,0x8015,0x66F4,0x5E9A,0x7FB9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7B2F,0x7B30,0x7B32,0x7B34,0x7B35,0x7B36,0x7B37,0x7B39,
+0x7B3B,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B42,0x7B43,0x7B44,
+0x7B46,0x7B48,0x7B4A,0x7B4D,0x7B4E,0x7B53,0x7B55,0x7B57,
+0x7B59,0x7B5C,0x7B5E,0x7B5F,0x7B61,0x7B63,0x7B64,0x7B65,
+0x7B66,0x7B67,0x7B68,0x7B69,0x7B6A,0x7B6B,0x7B6C,0x7B6D,
+0x7B6F,0x7B70,0x7B73,0x7B74,0x7B76,0x7B78,0x7B7A,0x7B7C,
+0x7B7D,0x7B7F,0x7B81,0x7B82,0x7B83,0x7B84,0x7B86,0x7B87,
+0x7B88,0x7B89,0x7B8A,0x7B8B,0x7B8C,0x7B8E,0x7B8F, 0,
+0x7B91,0x7B92,0x7B93,0x7B96,0x7B98,0x7B99,0x7B9A,0x7B9B,
+0x7B9E,0x7B9F,0x7BA0,0x7BA3,0x7BA4,0x7BA5,0x7BAE,0x7BAF,
+0x7BB0,0x7BB2,0x7BB3,0x7BB5,0x7BB6,0x7BB7,0x7BB9,0x7BBA,
+0x7BBB,0x7BBC,0x7BBD,0x7BBE,0x7BBF,0x7BC0,0x7BC2,0x7BC3,
+0x7BC4,0x57C2,0x803F,0x6897,0x5DE5,0x653B,0x529F,0x606D,
+0x9F9A,0x4F9B,0x8EAC,0x516C,0x5BAB,0x5F13,0x5DE9,0x6C5E,
+0x62F1,0x8D21,0x5171,0x94A9,0x52FE,0x6C9F,0x82DF,0x72D7,
+0x57A2,0x6784,0x8D2D,0x591F,0x8F9C,0x83C7,0x5495,0x7B8D,
+0x4F30,0x6CBD,0x5B64,0x59D1,0x9F13,0x53E4,0x86CA,0x9AA8,
+0x8C37,0x80A1,0x6545,0x987E,0x56FA,0x96C7,0x522E,0x74DC,
+0x5250,0x5BE1,0x6302,0x8902,0x4E56,0x62D0,0x602A,0x68FA,
+0x5173,0x5B98,0x51A0,0x89C2,0x7BA1,0x9986,0x7F50,0x60EF,
+0x704C,0x8D2F,0x5149,0x5E7F,0x901B,0x7470,0x89C4,0x572D,
+0x7845,0x5F52,0x9F9F,0x95FA,0x8F68,0x9B3C,0x8BE1,0x7678,
+0x6842,0x67DC,0x8DEA,0x8D35,0x523D,0x8F8A,0x6EDA,0x68CD,
+0x9505,0x90ED,0x56FD,0x679C,0x88F9,0x8FC7,0x54C8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7BC5,0x7BC8,0x7BC9,0x7BCA,0x7BCB,0x7BCD,0x7BCE,0x7BCF,
+0x7BD0,0x7BD2,0x7BD4,0x7BD5,0x7BD6,0x7BD7,0x7BD8,0x7BDB,
+0x7BDC,0x7BDE,0x7BDF,0x7BE0,0x7BE2,0x7BE3,0x7BE4,0x7BE7,
+0x7BE8,0x7BE9,0x7BEB,0x7BEC,0x7BED,0x7BEF,0x7BF0,0x7BF2,
+0x7BF3,0x7BF4,0x7BF5,0x7BF6,0x7BF8,0x7BF9,0x7BFA,0x7BFB,
+0x7BFD,0x7BFF,0x7C00,0x7C01,0x7C02,0x7C03,0x7C04,0x7C05,
+0x7C06,0x7C08,0x7C09,0x7C0A,0x7C0D,0x7C0E,0x7C10,0x7C11,
+0x7C12,0x7C13,0x7C14,0x7C15,0x7C17,0x7C18,0x7C19, 0,
+0x7C1A,0x7C1B,0x7C1C,0x7C1D,0x7C1E,0x7C20,0x7C21,0x7C22,
+0x7C23,0x7C24,0x7C25,0x7C28,0x7C29,0x7C2B,0x7C2C,0x7C2D,
+0x7C2E,0x7C2F,0x7C30,0x7C31,0x7C32,0x7C33,0x7C34,0x7C35,
+0x7C36,0x7C37,0x7C39,0x7C3A,0x7C3B,0x7C3C,0x7C3D,0x7C3E,
+0x7C42,0x9AB8,0x5B69,0x6D77,0x6C26,0x4EA5,0x5BB3,0x9A87,
+0x9163,0x61A8,0x90AF,0x97E9,0x542B,0x6DB5,0x5BD2,0x51FD,
+0x558A,0x7F55,0x7FF0,0x64BC,0x634D,0x65F1,0x61BE,0x608D,
+0x710A,0x6C57,0x6C49,0x592F,0x676D,0x822A,0x58D5,0x568E,
+0x8C6A,0x6BEB,0x90DD,0x597D,0x8017,0x53F7,0x6D69,0x5475,
+0x559D,0x8377,0x83CF,0x6838,0x79BE,0x548C,0x4F55,0x5408,
+0x76D2,0x8C89,0x9602,0x6CB3,0x6DB8,0x8D6B,0x8910,0x9E64,
+0x8D3A,0x563F,0x9ED1,0x75D5,0x5F88,0x72E0,0x6068,0x54FC,
+0x4EA8,0x6A2A,0x8861,0x6052,0x8F70,0x54C4,0x70D8,0x8679,
+0x9E3F,0x6D2A,0x5B8F,0x5F18,0x7EA2,0x5589,0x4FAF,0x7334,
+0x543C,0x539A,0x5019,0x540E,0x547C,0x4E4E,0x5FFD,0x745A,
+0x58F6,0x846B,0x80E1,0x8774,0x72D0,0x7CCA,0x6E56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7C43,0x7C44,0x7C45,0x7C46,0x7C47,0x7C48,0x7C49,0x7C4A,
+0x7C4B,0x7C4C,0x7C4E,0x7C4F,0x7C50,0x7C51,0x7C52,0x7C53,
+0x7C54,0x7C55,0x7C56,0x7C57,0x7C58,0x7C59,0x7C5A,0x7C5B,
+0x7C5C,0x7C5D,0x7C5E,0x7C5F,0x7C60,0x7C61,0x7C62,0x7C63,
+0x7C64,0x7C65,0x7C66,0x7C67,0x7C68,0x7C69,0x7C6A,0x7C6B,
+0x7C6C,0x7C6D,0x7C6E,0x7C6F,0x7C70,0x7C71,0x7C72,0x7C75,
+0x7C76,0x7C77,0x7C78,0x7C79,0x7C7A,0x7C7E,0x7C7F,0x7C80,
+0x7C81,0x7C82,0x7C83,0x7C84,0x7C85,0x7C86,0x7C87, 0,
+0x7C88,0x7C8A,0x7C8B,0x7C8C,0x7C8D,0x7C8E,0x7C8F,0x7C90,
+0x7C93,0x7C94,0x7C96,0x7C99,0x7C9A,0x7C9B,0x7CA0,0x7CA1,
+0x7CA3,0x7CA6,0x7CA7,0x7CA8,0x7CA9,0x7CAB,0x7CAC,0x7CAD,
+0x7CAF,0x7CB0,0x7CB4,0x7CB5,0x7CB6,0x7CB7,0x7CB8,0x7CBA,
+0x7CBB,0x5F27,0x864E,0x552C,0x62A4,0x4E92,0x6CAA,0x6237,
+0x82B1,0x54D7,0x534E,0x733E,0x6ED1,0x753B,0x5212,0x5316,
+0x8BDD,0x69D0,0x5F8A,0x6000,0x6DEE,0x574F,0x6B22,0x73AF,
+0x6853,0x8FD8,0x7F13,0x6362,0x60A3,0x5524,0x75EA,0x8C62,
+0x7115,0x6DA3,0x5BA6,0x5E7B,0x8352,0x614C,0x9EC4,0x78FA,
+0x8757,0x7C27,0x7687,0x51F0,0x60F6,0x714C,0x6643,0x5E4C,
+0x604D,0x8C0E,0x7070,0x6325,0x8F89,0x5FBD,0x6062,0x86D4,
+0x56DE,0x6BC1,0x6094,0x6167,0x5349,0x60E0,0x6666,0x8D3F,
+0x79FD,0x4F1A,0x70E9,0x6C47,0x8BB3,0x8BF2,0x7ED8,0x8364,
+0x660F,0x5A5A,0x9B42,0x6D51,0x6DF7,0x8C41,0x6D3B,0x4F19,
+0x706B,0x83B7,0x6216,0x60D1,0x970D,0x8D27,0x7978,0x51FB,
+0x573E,0x57FA,0x673A,0x7578,0x7A3D,0x79EF,0x7B95, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7CBF,0x7CC0,0x7CC2,0x7CC3,0x7CC4,0x7CC6,0x7CC9,0x7CCB,
+0x7CCE,0x7CCF,0x7CD0,0x7CD1,0x7CD2,0x7CD3,0x7CD4,0x7CD8,
+0x7CDA,0x7CDB,0x7CDD,0x7CDE,0x7CE1,0x7CE2,0x7CE3,0x7CE4,
+0x7CE5,0x7CE6,0x7CE7,0x7CE9,0x7CEA,0x7CEB,0x7CEC,0x7CED,
+0x7CEE,0x7CF0,0x7CF1,0x7CF2,0x7CF3,0x7CF4,0x7CF5,0x7CF6,
+0x7CF7,0x7CF9,0x7CFA,0x7CFC,0x7CFD,0x7CFE,0x7CFF,0x7D00,
+0x7D01,0x7D02,0x7D03,0x7D04,0x7D05,0x7D06,0x7D07,0x7D08,
+0x7D09,0x7D0B,0x7D0C,0x7D0D,0x7D0E,0x7D0F,0x7D10, 0,
+0x7D11,0x7D12,0x7D13,0x7D14,0x7D15,0x7D16,0x7D17,0x7D18,
+0x7D19,0x7D1A,0x7D1B,0x7D1C,0x7D1D,0x7D1E,0x7D1F,0x7D21,
+0x7D23,0x7D24,0x7D25,0x7D26,0x7D28,0x7D29,0x7D2A,0x7D2C,
+0x7D2D,0x7D2E,0x7D30,0x7D31,0x7D32,0x7D33,0x7D34,0x7D35,
+0x7D36,0x808C,0x9965,0x8FF9,0x6FC0,0x8BA5,0x9E21,0x59EC,
+0x7EE9,0x7F09,0x5409,0x6781,0x68D8,0x8F91,0x7C4D,0x96C6,
+0x53CA,0x6025,0x75BE,0x6C72,0x5373,0x5AC9,0x7EA7,0x6324,
+0x51E0,0x810A,0x5DF1,0x84DF,0x6280,0x5180,0x5B63,0x4F0E,
+0x796D,0x5242,0x60B8,0x6D4E,0x5BC4,0x5BC2,0x8BA1,0x8BB0,
+0x65E2,0x5FCC,0x9645,0x5993,0x7EE7,0x7EAA,0x5609,0x67B7,
+0x5939,0x4F73,0x5BB6,0x52A0,0x835A,0x988A,0x8D3E,0x7532,
+0x94BE,0x5047,0x7A3C,0x4EF7,0x67B6,0x9A7E,0x5AC1,0x6B7C,
+0x76D1,0x575A,0x5C16,0x7B3A,0x95F4,0x714E,0x517C,0x80A9,
+0x8270,0x5978,0x7F04,0x8327,0x68C0,0x67EC,0x78B1,0x7877,
+0x62E3,0x6361,0x7B80,0x4FED,0x526A,0x51CF,0x8350,0x69DB,
+0x9274,0x8DF5,0x8D31,0x89C1,0x952E,0x7BAD,0x4EF6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7D37,0x7D38,0x7D39,0x7D3A,0x7D3B,0x7D3C,0x7D3D,0x7D3E,
+0x7D3F,0x7D40,0x7D41,0x7D42,0x7D43,0x7D44,0x7D45,0x7D46,
+0x7D47,0x7D48,0x7D49,0x7D4A,0x7D4B,0x7D4C,0x7D4D,0x7D4E,
+0x7D4F,0x7D50,0x7D51,0x7D52,0x7D53,0x7D54,0x7D55,0x7D56,
+0x7D57,0x7D58,0x7D59,0x7D5A,0x7D5B,0x7D5C,0x7D5D,0x7D5E,
+0x7D5F,0x7D60,0x7D61,0x7D62,0x7D63,0x7D64,0x7D65,0x7D66,
+0x7D67,0x7D68,0x7D69,0x7D6A,0x7D6B,0x7D6C,0x7D6D,0x7D6F,
+0x7D70,0x7D71,0x7D72,0x7D73,0x7D74,0x7D75,0x7D76, 0,
+0x7D78,0x7D79,0x7D7A,0x7D7B,0x7D7C,0x7D7D,0x7D7E,0x7D7F,
+0x7D80,0x7D81,0x7D82,0x7D83,0x7D84,0x7D85,0x7D86,0x7D87,
+0x7D88,0x7D89,0x7D8A,0x7D8B,0x7D8C,0x7D8D,0x7D8E,0x7D8F,
+0x7D90,0x7D91,0x7D92,0x7D93,0x7D94,0x7D95,0x7D96,0x7D97,
+0x7D98,0x5065,0x8230,0x5251,0x996F,0x6E10,0x6E85,0x6DA7,
+0x5EFA,0x50F5,0x59DC,0x5C06,0x6D46,0x6C5F,0x7586,0x848B,
+0x6868,0x5956,0x8BB2,0x5320,0x9171,0x964D,0x8549,0x6912,
+0x7901,0x7126,0x80F6,0x4EA4,0x90CA,0x6D47,0x9A84,0x5A07,
+0x56BC,0x6405,0x94F0,0x77EB,0x4FA5,0x811A,0x72E1,0x89D2,
+0x997A,0x7F34,0x7EDE,0x527F,0x6559,0x9175,0x8F7F,0x8F83,
+0x53EB,0x7A96,0x63ED,0x63A5,0x7686,0x79F8,0x8857,0x9636,
+0x622A,0x52AB,0x8282,0x6854,0x6770,0x6377,0x776B,0x7AED,
+0x6D01,0x7ED3,0x89E3,0x59D0,0x6212,0x85C9,0x82A5,0x754C,
+0x501F,0x4ECB,0x75A5,0x8BEB,0x5C4A,0x5DFE,0x7B4B,0x65A4,
+0x91D1,0x4ECA,0x6D25,0x895F,0x7D27,0x9526,0x4EC5,0x8C28,
+0x8FDB,0x9773,0x664B,0x7981,0x8FD1,0x70EC,0x6D78, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7D99,0x7D9A,0x7D9B,0x7D9C,0x7D9D,0x7D9E,0x7D9F,0x7DA0,
+0x7DA1,0x7DA2,0x7DA3,0x7DA4,0x7DA5,0x7DA7,0x7DA8,0x7DA9,
+0x7DAA,0x7DAB,0x7DAC,0x7DAD,0x7DAF,0x7DB0,0x7DB1,0x7DB2,
+0x7DB3,0x7DB4,0x7DB5,0x7DB6,0x7DB7,0x7DB8,0x7DB9,0x7DBA,
+0x7DBB,0x7DBC,0x7DBD,0x7DBE,0x7DBF,0x7DC0,0x7DC1,0x7DC2,
+0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DC7,0x7DC8,0x7DC9,0x7DCA,
+0x7DCB,0x7DCC,0x7DCD,0x7DCE,0x7DCF,0x7DD0,0x7DD1,0x7DD2,
+0x7DD3,0x7DD4,0x7DD5,0x7DD6,0x7DD7,0x7DD8,0x7DD9, 0,
+0x7DDA,0x7DDB,0x7DDC,0x7DDD,0x7DDE,0x7DDF,0x7DE0,0x7DE1,
+0x7DE2,0x7DE3,0x7DE4,0x7DE5,0x7DE6,0x7DE7,0x7DE8,0x7DE9,
+0x7DEA,0x7DEB,0x7DEC,0x7DED,0x7DEE,0x7DEF,0x7DF0,0x7DF1,
+0x7DF2,0x7DF3,0x7DF4,0x7DF5,0x7DF6,0x7DF7,0x7DF8,0x7DF9,
+0x7DFA,0x5C3D,0x52B2,0x8346,0x5162,0x830E,0x775B,0x6676,
+0x9CB8,0x4EAC,0x60CA,0x7CBE,0x7CB3,0x7ECF,0x4E95,0x8B66,
+0x666F,0x9888,0x9759,0x5883,0x656C,0x955C,0x5F84,0x75C9,
+0x9756,0x7ADF,0x7ADE,0x51C0,0x70AF,0x7A98,0x63EA,0x7A76,
+0x7EA0,0x7396,0x97ED,0x4E45,0x7078,0x4E5D,0x9152,0x53A9,
+0x6551,0x65E7,0x81FC,0x8205,0x548E,0x5C31,0x759A,0x97A0,
+0x62D8,0x72D9,0x75BD,0x5C45,0x9A79,0x83CA,0x5C40,0x5480,
+0x77E9,0x4E3E,0x6CAE,0x805A,0x62D2,0x636E,0x5DE8,0x5177,
+0x8DDD,0x8E1E,0x952F,0x4FF1,0x53E5,0x60E7,0x70AC,0x5267,
+0x6350,0x9E43,0x5A1F,0x5026,0x7737,0x5377,0x7EE2,0x6485,
+0x652B,0x6289,0x6398,0x5014,0x7235,0x89C9,0x51B3,0x8BC0,
+0x7EDD,0x5747,0x83CC,0x94A7,0x519B,0x541B,0x5CFB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7DFB,0x7DFC,0x7DFD,0x7DFE,0x7DFF,0x7E00,0x7E01,0x7E02,
+0x7E03,0x7E04,0x7E05,0x7E06,0x7E07,0x7E08,0x7E09,0x7E0A,
+0x7E0B,0x7E0C,0x7E0D,0x7E0E,0x7E0F,0x7E10,0x7E11,0x7E12,
+0x7E13,0x7E14,0x7E15,0x7E16,0x7E17,0x7E18,0x7E19,0x7E1A,
+0x7E1B,0x7E1C,0x7E1D,0x7E1E,0x7E1F,0x7E20,0x7E21,0x7E22,
+0x7E23,0x7E24,0x7E25,0x7E26,0x7E27,0x7E28,0x7E29,0x7E2A,
+0x7E2B,0x7E2C,0x7E2D,0x7E2E,0x7E2F,0x7E30,0x7E31,0x7E32,
+0x7E33,0x7E34,0x7E35,0x7E36,0x7E37,0x7E38,0x7E39, 0,
+0x7E3A,0x7E3C,0x7E3D,0x7E3E,0x7E3F,0x7E40,0x7E42,0x7E43,
+0x7E44,0x7E45,0x7E46,0x7E48,0x7E49,0x7E4A,0x7E4B,0x7E4C,
+0x7E4D,0x7E4E,0x7E4F,0x7E50,0x7E51,0x7E52,0x7E53,0x7E54,
+0x7E55,0x7E56,0x7E57,0x7E58,0x7E59,0x7E5A,0x7E5B,0x7E5C,
+0x7E5D,0x4FCA,0x7AE3,0x6D5A,0x90E1,0x9A8F,0x5580,0x5496,
+0x5361,0x54AF,0x5F00,0x63E9,0x6977,0x51EF,0x6168,0x520A,
+0x582A,0x52D8,0x574E,0x780D,0x770B,0x5EB7,0x6177,0x7CE0,
+0x625B,0x6297,0x4EA2,0x7095,0x8003,0x62F7,0x70E4,0x9760,
+0x5777,0x82DB,0x67EF,0x68F5,0x78D5,0x9897,0x79D1,0x58F3,
+0x54B3,0x53EF,0x6E34,0x514B,0x523B,0x5BA2,0x8BFE,0x80AF,
+0x5543,0x57A6,0x6073,0x5751,0x542D,0x7A7A,0x6050,0x5B54,
+0x63A7,0x62A0,0x53E3,0x6263,0x5BC7,0x67AF,0x54ED,0x7A9F,
+0x82E6,0x9177,0x5E93,0x88E4,0x5938,0x57AE,0x630E,0x8DE8,
+0x80EF,0x5757,0x7B77,0x4FA9,0x5FEB,0x5BBD,0x6B3E,0x5321,
+0x7B50,0x72C2,0x6846,0x77FF,0x7736,0x65F7,0x51B5,0x4E8F,
+0x76D4,0x5CBF,0x7AA5,0x8475,0x594E,0x9B41,0x5080, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7E5E,0x7E5F,0x7E60,0x7E61,0x7E62,0x7E63,0x7E64,0x7E65,
+0x7E66,0x7E67,0x7E68,0x7E69,0x7E6A,0x7E6B,0x7E6C,0x7E6D,
+0x7E6E,0x7E6F,0x7E70,0x7E71,0x7E72,0x7E73,0x7E74,0x7E75,
+0x7E76,0x7E77,0x7E78,0x7E79,0x7E7A,0x7E7B,0x7E7C,0x7E7D,
+0x7E7E,0x7E7F,0x7E80,0x7E81,0x7E83,0x7E84,0x7E85,0x7E86,
+0x7E87,0x7E88,0x7E89,0x7E8A,0x7E8B,0x7E8C,0x7E8D,0x7E8E,
+0x7E8F,0x7E90,0x7E91,0x7E92,0x7E93,0x7E94,0x7E95,0x7E96,
+0x7E97,0x7E98,0x7E99,0x7E9A,0x7E9C,0x7E9D,0x7E9E, 0,
+0x7EAE,0x7EB4,0x7EBB,0x7EBC,0x7ED6,0x7EE4,0x7EEC,0x7EF9,
+0x7F0A,0x7F10,0x7F1E,0x7F37,0x7F39,0x7F3B,0x7F3C,0x7F3D,
+0x7F3E,0x7F3F,0x7F40,0x7F41,0x7F43,0x7F46,0x7F47,0x7F48,
+0x7F49,0x7F4A,0x7F4B,0x7F4C,0x7F4D,0x7F4E,0x7F4F,0x7F52,
+0x7F53,0x9988,0x6127,0x6E83,0x5764,0x6606,0x6346,0x56F0,
+0x62EC,0x6269,0x5ED3,0x9614,0x5783,0x62C9,0x5587,0x8721,
+0x814A,0x8FA3,0x5566,0x83B1,0x6765,0x8D56,0x84DD,0x5A6A,
+0x680F,0x62E6,0x7BEE,0x9611,0x5170,0x6F9C,0x8C30,0x63FD,
+0x89C8,0x61D2,0x7F06,0x70C2,0x6EE5,0x7405,0x6994,0x72FC,
+0x5ECA,0x90CE,0x6717,0x6D6A,0x635E,0x52B3,0x7262,0x8001,
+0x4F6C,0x59E5,0x916A,0x70D9,0x6D9D,0x52D2,0x4E50,0x96F7,
+0x956D,0x857E,0x78CA,0x7D2F,0x5121,0x5792,0x64C2,0x808B,
+0x7C7B,0x6CEA,0x68F1,0x695E,0x51B7,0x5398,0x68A8,0x7281,
+0x9ECE,0x7BF1,0x72F8,0x79BB,0x6F13,0x7406,0x674E,0x91CC,
+0x9CA4,0x793C,0x8389,0x8354,0x540F,0x6817,0x4E3D,0x5389,
+0x52B1,0x783E,0x5386,0x5229,0x5088,0x4F8B,0x4FD0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7F56,0x7F59,0x7F5B,0x7F5C,0x7F5D,0x7F5E,0x7F60,0x7F63,
+0x7F64,0x7F65,0x7F66,0x7F67,0x7F6B,0x7F6C,0x7F6D,0x7F6F,
+0x7F70,0x7F73,0x7F75,0x7F76,0x7F77,0x7F78,0x7F7A,0x7F7B,
+0x7F7C,0x7F7D,0x7F7F,0x7F80,0x7F82,0x7F83,0x7F84,0x7F85,
+0x7F86,0x7F87,0x7F88,0x7F89,0x7F8B,0x7F8D,0x7F8F,0x7F90,
+0x7F91,0x7F92,0x7F93,0x7F95,0x7F96,0x7F97,0x7F98,0x7F99,
+0x7F9B,0x7F9C,0x7FA0,0x7FA2,0x7FA3,0x7FA5,0x7FA6,0x7FA8,
+0x7FA9,0x7FAA,0x7FAB,0x7FAC,0x7FAD,0x7FAE,0x7FB1, 0,
+0x7FB3,0x7FB4,0x7FB5,0x7FB6,0x7FB7,0x7FBA,0x7FBB,0x7FBE,
+0x7FC0,0x7FC2,0x7FC3,0x7FC4,0x7FC6,0x7FC7,0x7FC8,0x7FC9,
+0x7FCB,0x7FCD,0x7FCF,0x7FD0,0x7FD1,0x7FD2,0x7FD3,0x7FD6,
+0x7FD7,0x7FD9,0x7FDA,0x7FDB,0x7FDC,0x7FDD,0x7FDE,0x7FE2,
+0x7FE3,0x75E2,0x7ACB,0x7C92,0x6CA5,0x96B6,0x529B,0x7483,
+0x54E9,0x4FE9,0x8054,0x83B2,0x8FDE,0x9570,0x5EC9,0x601C,
+0x6D9F,0x5E18,0x655B,0x8138,0x94FE,0x604B,0x70BC,0x7EC3,
+0x7CAE,0x51C9,0x6881,0x7CB1,0x826F,0x4E24,0x8F86,0x91CF,
+0x667E,0x4EAE,0x8C05,0x64A9,0x804A,0x50DA,0x7597,0x71CE,
+0x5BE5,0x8FBD,0x6F66,0x4E86,0x6482,0x9563,0x5ED6,0x6599,
+0x5217,0x88C2,0x70C8,0x52A3,0x730E,0x7433,0x6797,0x78F7,
+0x9716,0x4E34,0x90BB,0x9CDE,0x6DCB,0x51DB,0x8D41,0x541D,
+0x62CE,0x73B2,0x83F1,0x96F6,0x9F84,0x94C3,0x4F36,0x7F9A,
+0x51CC,0x7075,0x9675,0x5CAD,0x9886,0x53E6,0x4EE4,0x6E9C,
+0x7409,0x69B4,0x786B,0x998F,0x7559,0x5218,0x7624,0x6D41,
+0x67F3,0x516D,0x9F99,0x804B,0x5499,0x7B3C,0x7ABF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7FE4,0x7FE7,0x7FE8,0x7FEA,0x7FEB,0x7FEC,0x7FED,0x7FEF,
+0x7FF2,0x7FF4,0x7FF5,0x7FF6,0x7FF7,0x7FF8,0x7FF9,0x7FFA,
+0x7FFD,0x7FFE,0x7FFF,0x8002,0x8007,0x8008,0x8009,0x800A,
+0x800E,0x800F,0x8011,0x8013,0x801A,0x801B,0x801D,0x801E,
+0x801F,0x8021,0x8023,0x8024,0x802B,0x802C,0x802D,0x802E,
+0x802F,0x8030,0x8032,0x8034,0x8039,0x803A,0x803C,0x803E,
+0x8040,0x8041,0x8044,0x8045,0x8047,0x8048,0x8049,0x804E,
+0x804F,0x8050,0x8051,0x8053,0x8055,0x8056,0x8057, 0,
+0x8059,0x805B,0x805C,0x805D,0x805E,0x805F,0x8060,0x8061,
+0x8062,0x8063,0x8064,0x8065,0x8066,0x8067,0x8068,0x806B,
+0x806C,0x806D,0x806E,0x806F,0x8070,0x8072,0x8073,0x8074,
+0x8075,0x8076,0x8077,0x8078,0x8079,0x807A,0x807B,0x807C,
+0x807D,0x9686,0x5784,0x62E2,0x9647,0x697C,0x5A04,0x6402,
+0x7BD3,0x6F0F,0x964B,0x82A6,0x5362,0x9885,0x5E90,0x7089,
+0x63B3,0x5364,0x864F,0x9C81,0x9E93,0x788C,0x9732,0x8DEF,
+0x8D42,0x9E7F,0x6F5E,0x7984,0x5F55,0x9646,0x622E,0x9A74,
+0x5415,0x94DD,0x4FA3,0x65C5,0x5C65,0x5C61,0x7F15,0x8651,
+0x6C2F,0x5F8B,0x7387,0x6EE4,0x7EFF,0x5CE6,0x631B,0x5B6A,
+0x6EE6,0x5375,0x4E71,0x63A0,0x7565,0x62A1,0x8F6E,0x4F26,
+0x4ED1,0x6CA6,0x7EB6,0x8BBA,0x841D,0x87BA,0x7F57,0x903B,
+0x9523,0x7BA9,0x9AA1,0x88F8,0x843D,0x6D1B,0x9A86,0x7EDC,
+0x5988,0x9EBB,0x739B,0x7801,0x8682,0x9A6C,0x9A82,0x561B,
+0x5417,0x57CB,0x4E70,0x9EA6,0x5356,0x8FC8,0x8109,0x7792,
+0x9992,0x86EE,0x6EE1,0x8513,0x66FC,0x6162,0x6F2B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x807E,0x8081,0x8082,0x8085,0x8088,0x808A,0x808D,0x808E,
+0x808F,0x8090,0x8091,0x8092,0x8094,0x8095,0x8097,0x8099,
+0x809E,0x80A3,0x80A6,0x80A7,0x80A8,0x80AC,0x80B0,0x80B3,
+0x80B5,0x80B6,0x80B8,0x80B9,0x80BB,0x80C5,0x80C7,0x80C8,
+0x80C9,0x80CA,0x80CB,0x80CF,0x80D0,0x80D1,0x80D2,0x80D3,
+0x80D4,0x80D5,0x80D8,0x80DF,0x80E0,0x80E2,0x80E3,0x80E6,
+0x80EE,0x80F5,0x80F7,0x80F9,0x80FB,0x80FE,0x80FF,0x8100,
+0x8101,0x8103,0x8104,0x8105,0x8107,0x8108,0x810B, 0,
+0x810C,0x8115,0x8117,0x8119,0x811B,0x811C,0x811D,0x811F,
+0x8120,0x8121,0x8122,0x8123,0x8124,0x8125,0x8126,0x8127,
+0x8128,0x8129,0x812A,0x812B,0x812D,0x812E,0x8130,0x8133,
+0x8134,0x8135,0x8137,0x8139,0x813A,0x813B,0x813C,0x813D,
+0x813F,0x8C29,0x8292,0x832B,0x76F2,0x6C13,0x5FD9,0x83BD,
+0x732B,0x8305,0x951A,0x6BDB,0x77DB,0x94C6,0x536F,0x8302,
+0x5192,0x5E3D,0x8C8C,0x8D38,0x4E48,0x73AB,0x679A,0x6885,
+0x9176,0x9709,0x7164,0x6CA1,0x7709,0x5A92,0x9541,0x6BCF,
+0x7F8E,0x6627,0x5BD0,0x59B9,0x5A9A,0x95E8,0x95F7,0x4EEC,
+0x840C,0x8499,0x6AAC,0x76DF,0x9530,0x731B,0x68A6,0x5B5F,
+0x772F,0x919A,0x9761,0x7CDC,0x8FF7,0x8C1C,0x5F25,0x7C73,
+0x79D8,0x89C5,0x6CCC,0x871C,0x5BC6,0x5E42,0x68C9,0x7720,
+0x7EF5,0x5195,0x514D,0x52C9,0x5A29,0x7F05,0x9762,0x82D7,
+0x63CF,0x7784,0x85D0,0x79D2,0x6E3A,0x5E99,0x5999,0x8511,
+0x706D,0x6C11,0x62BF,0x76BF,0x654F,0x60AF,0x95FD,0x660E,
+0x879F,0x9E23,0x94ED,0x540D,0x547D,0x8C2C,0x6478, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8140,0x8141,0x8142,0x8143,0x8144,0x8145,0x8147,0x8149,
+0x814D,0x814E,0x814F,0x8152,0x8156,0x8157,0x8158,0x815B,
+0x815C,0x815D,0x815E,0x815F,0x8161,0x8162,0x8163,0x8164,
+0x8166,0x8168,0x816A,0x816B,0x816C,0x816F,0x8172,0x8173,
+0x8175,0x8176,0x8177,0x8178,0x8181,0x8183,0x8184,0x8185,
+0x8186,0x8187,0x8189,0x818B,0x818C,0x818D,0x818E,0x8190,
+0x8192,0x8193,0x8194,0x8195,0x8196,0x8197,0x8199,0x819A,
+0x819E,0x819F,0x81A0,0x81A1,0x81A2,0x81A4,0x81A5, 0,
+0x81A7,0x81A9,0x81AB,0x81AC,0x81AD,0x81AE,0x81AF,0x81B0,
+0x81B1,0x81B2,0x81B4,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9,
+0x81BC,0x81BD,0x81BE,0x81BF,0x81C4,0x81C5,0x81C7,0x81C8,
+0x81C9,0x81CB,0x81CD,0x81CE,0x81CF,0x81D0,0x81D1,0x81D2,
+0x81D3,0x6479,0x8611,0x6A21,0x819C,0x78E8,0x6469,0x9B54,
+0x62B9,0x672B,0x83AB,0x58A8,0x9ED8,0x6CAB,0x6F20,0x5BDE,
+0x964C,0x8C0B,0x725F,0x67D0,0x62C7,0x7261,0x4EA9,0x59C6,
+0x6BCD,0x5893,0x66AE,0x5E55,0x52DF,0x6155,0x6728,0x76EE,
+0x7766,0x7267,0x7A46,0x62FF,0x54EA,0x5450,0x94A0,0x90A3,
+0x5A1C,0x7EB3,0x6C16,0x4E43,0x5976,0x8010,0x5948,0x5357,
+0x7537,0x96BE,0x56CA,0x6320,0x8111,0x607C,0x95F9,0x6DD6,
+0x5462,0x9981,0x5185,0x5AE9,0x80FD,0x59AE,0x9713,0x502A,
+0x6CE5,0x5C3C,0x62DF,0x4F60,0x533F,0x817B,0x9006,0x6EBA,
+0x852B,0x62C8,0x5E74,0x78BE,0x64B5,0x637B,0x5FF5,0x5A18,
+0x917F,0x9E1F,0x5C3F,0x634F,0x8042,0x5B7D,0x556E,0x954A,
+0x954D,0x6D85,0x60A8,0x67E0,0x72DE,0x51DD,0x5B81, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x81D4,0x81D5,0x81D6,0x81D7,0x81D8,0x81D9,0x81DA,0x81DB,
+0x81DC,0x81DD,0x81DE,0x81DF,0x81E0,0x81E1,0x81E2,0x81E4,
+0x81E5,0x81E6,0x81E8,0x81E9,0x81EB,0x81EE,0x81EF,0x81F0,
+0x81F1,0x81F2,0x81F5,0x81F6,0x81F7,0x81F8,0x81F9,0x81FA,
+0x81FD,0x81FF,0x8203,0x8207,0x8208,0x8209,0x820A,0x820B,
+0x820E,0x820F,0x8211,0x8213,0x8215,0x8216,0x8217,0x8218,
+0x8219,0x821A,0x821D,0x8220,0x8224,0x8225,0x8226,0x8227,
+0x8229,0x822E,0x8232,0x823A,0x823C,0x823D,0x823F, 0,
+0x8240,0x8241,0x8242,0x8243,0x8245,0x8246,0x8248,0x824A,
+0x824C,0x824D,0x824E,0x8250,0x8251,0x8252,0x8253,0x8254,
+0x8255,0x8256,0x8257,0x8259,0x825B,0x825C,0x825D,0x825E,
+0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267,
+0x8269,0x62E7,0x6CDE,0x725B,0x626D,0x94AE,0x7EBD,0x8113,
+0x6D53,0x519C,0x5F04,0x5974,0x52AA,0x6012,0x5973,0x6696,
+0x8650,0x759F,0x632A,0x61E6,0x7CEF,0x8BFA,0x54E6,0x6B27,
+0x9E25,0x6BB4,0x85D5,0x5455,0x5076,0x6CA4,0x556A,0x8DB4,
+0x722C,0x5E15,0x6015,0x7436,0x62CD,0x6392,0x724C,0x5F98,
+0x6E43,0x6D3E,0x6500,0x6F58,0x76D8,0x78D0,0x76FC,0x7554,
+0x5224,0x53DB,0x4E53,0x5E9E,0x65C1,0x802A,0x80D6,0x629B,
+0x5486,0x5228,0x70AE,0x888D,0x8DD1,0x6CE1,0x5478,0x80DA,
+0x57F9,0x88F4,0x8D54,0x966A,0x914D,0x4F69,0x6C9B,0x55B7,
+0x76C6,0x7830,0x62A8,0x70F9,0x6F8E,0x5F6D,0x84EC,0x68DA,
+0x787C,0x7BF7,0x81A8,0x670B,0x9E4F,0x6367,0x78B0,0x576F,
+0x7812,0x9739,0x6279,0x62AB,0x5288,0x7435,0x6BD7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x826A,0x826B,0x826C,0x826D,0x8271,0x8275,0x8276,0x8277,
+0x8278,0x827B,0x827C,0x8280,0x8281,0x8283,0x8285,0x8286,
+0x8287,0x8289,0x828C,0x8290,0x8293,0x8294,0x8295,0x8296,
+0x829A,0x829B,0x829E,0x82A0,0x82A2,0x82A3,0x82A7,0x82B2,
+0x82B5,0x82B6,0x82BA,0x82BB,0x82BC,0x82BF,0x82C0,0x82C2,
+0x82C3,0x82C5,0x82C6,0x82C9,0x82D0,0x82D6,0x82D9,0x82DA,
+0x82DD,0x82E2,0x82E7,0x82E8,0x82E9,0x82EA,0x82EC,0x82ED,
+0x82EE,0x82F0,0x82F2,0x82F3,0x82F5,0x82F6,0x82F8, 0,
+0x82FA,0x82FC,0x82FD,0x82FE,0x82FF,0x8300,0x830A,0x830B,
+0x830D,0x8310,0x8312,0x8313,0x8316,0x8318,0x8319,0x831D,
+0x831E,0x831F,0x8320,0x8321,0x8322,0x8323,0x8324,0x8325,
+0x8326,0x8329,0x832A,0x832E,0x8330,0x8332,0x8337,0x833B,
+0x833D,0x5564,0x813E,0x75B2,0x76AE,0x5339,0x75DE,0x50FB,
+0x5C41,0x8B6C,0x7BC7,0x504F,0x7247,0x9A97,0x98D8,0x6F02,
+0x74E2,0x7968,0x6487,0x77A5,0x62FC,0x9891,0x8D2B,0x54C1,
+0x8058,0x4E52,0x576A,0x82F9,0x840D,0x5E73,0x51ED,0x74F6,
+0x8BC4,0x5C4F,0x5761,0x6CFC,0x9887,0x5A46,0x7834,0x9B44,
+0x8FEB,0x7C95,0x5256,0x6251,0x94FA,0x4EC6,0x8386,0x8461,
+0x83E9,0x84B2,0x57D4,0x6734,0x5703,0x666E,0x6D66,0x8C31,
+0x66DD,0x7011,0x671F,0x6B3A,0x6816,0x621A,0x59BB,0x4E03,
+0x51C4,0x6F06,0x67D2,0x6C8F,0x5176,0x68CB,0x5947,0x6B67,
+0x7566,0x5D0E,0x8110,0x9F50,0x65D7,0x7948,0x7941,0x9A91,
+0x8D77,0x5C82,0x4E5E,0x4F01,0x542F,0x5951,0x780C,0x5668,
+0x6C14,0x8FC4,0x5F03,0x6C7D,0x6CE3,0x8BAB,0x6390, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x833E,0x833F,0x8341,0x8342,0x8344,0x8345,0x8348,0x834A,
+0x834B,0x834C,0x834D,0x834E,0x8353,0x8355,0x8356,0x8357,
+0x8358,0x8359,0x835D,0x8362,0x8370,0x8371,0x8372,0x8373,
+0x8374,0x8375,0x8376,0x8379,0x837A,0x837E,0x837F,0x8380,
+0x8381,0x8382,0x8383,0x8384,0x8387,0x8388,0x838A,0x838B,
+0x838C,0x838D,0x838F,0x8390,0x8391,0x8394,0x8395,0x8396,
+0x8397,0x8399,0x839A,0x839D,0x839F,0x83A1,0x83A2,0x83A3,
+0x83A4,0x83A5,0x83A6,0x83A7,0x83AC,0x83AD,0x83AE, 0,
+0x83AF,0x83B5,0x83BB,0x83BE,0x83BF,0x83C2,0x83C3,0x83C4,
+0x83C6,0x83C8,0x83C9,0x83CB,0x83CD,0x83CE,0x83D0,0x83D1,
+0x83D2,0x83D3,0x83D5,0x83D7,0x83D9,0x83DA,0x83DB,0x83DE,
+0x83E2,0x83E3,0x83E4,0x83E6,0x83E7,0x83E8,0x83EB,0x83EC,
+0x83ED,0x6070,0x6D3D,0x7275,0x6266,0x948E,0x94C5,0x5343,
+0x8FC1,0x7B7E,0x4EDF,0x8C26,0x4E7E,0x9ED4,0x94B1,0x94B3,
+0x524D,0x6F5C,0x9063,0x6D45,0x8C34,0x5811,0x5D4C,0x6B20,
+0x6B49,0x67AA,0x545B,0x8154,0x7F8C,0x5899,0x8537,0x5F3A,
+0x62A2,0x6A47,0x9539,0x6572,0x6084,0x6865,0x77A7,0x4E54,
+0x4FA8,0x5DE7,0x9798,0x64AC,0x7FD8,0x5CED,0x4FCF,0x7A8D,
+0x5207,0x8304,0x4E14,0x602F,0x7A83,0x94A6,0x4FB5,0x4EB2,
+0x79E6,0x7434,0x52E4,0x82B9,0x64D2,0x79BD,0x5BDD,0x6C81,
+0x9752,0x8F7B,0x6C22,0x503E,0x537F,0x6E05,0x64CE,0x6674,
+0x6C30,0x60C5,0x9877,0x8BF7,0x5E86,0x743C,0x7A77,0x79CB,
+0x4E18,0x90B1,0x7403,0x6C42,0x56DA,0x914B,0x6CC5,0x8D8B,
+0x533A,0x86C6,0x66F2,0x8EAF,0x5C48,0x9A71,0x6E20, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x83EE,0x83EF,0x83F3,0x83F4,0x83F5,0x83F6,0x83F7,0x83FA,
+0x83FB,0x83FC,0x83FE,0x83FF,0x8400,0x8402,0x8405,0x8407,
+0x8408,0x8409,0x840A,0x8410,0x8412,0x8413,0x8414,0x8415,
+0x8416,0x8417,0x8419,0x841A,0x841B,0x841E,0x841F,0x8420,
+0x8421,0x8422,0x8423,0x8429,0x842A,0x842B,0x842C,0x842D,
+0x842E,0x842F,0x8430,0x8432,0x8433,0x8434,0x8435,0x8436,
+0x8437,0x8439,0x843A,0x843B,0x843E,0x843F,0x8440,0x8441,
+0x8442,0x8443,0x8444,0x8445,0x8447,0x8448,0x8449, 0,
+0x844A,0x844B,0x844C,0x844D,0x844E,0x844F,0x8450,0x8452,
+0x8453,0x8454,0x8455,0x8456,0x8458,0x845D,0x845E,0x845F,
+0x8460,0x8462,0x8464,0x8465,0x8466,0x8467,0x8468,0x846A,
+0x846E,0x846F,0x8470,0x8472,0x8474,0x8477,0x8479,0x847B,
+0x847C,0x53D6,0x5A36,0x9F8B,0x8DA3,0x53BB,0x5708,0x98A7,
+0x6743,0x919B,0x6CC9,0x5168,0x75CA,0x62F3,0x72AC,0x5238,
+0x529D,0x7F3A,0x7094,0x7638,0x5374,0x9E4A,0x69B7,0x786E,
+0x96C0,0x88D9,0x7FA4,0x7136,0x71C3,0x5189,0x67D3,0x74E4,
+0x58E4,0x6518,0x56B7,0x8BA9,0x9976,0x6270,0x7ED5,0x60F9,
+0x70ED,0x58EC,0x4EC1,0x4EBA,0x5FCD,0x97E7,0x4EFB,0x8BA4,
+0x5203,0x598A,0x7EAB,0x6254,0x4ECD,0x65E5,0x620E,0x8338,
+0x84C9,0x8363,0x878D,0x7194,0x6EB6,0x5BB9,0x7ED2,0x5197,
+0x63C9,0x67D4,0x8089,0x8339,0x8815,0x5112,0x5B7A,0x5982,
+0x8FB1,0x4E73,0x6C5D,0x5165,0x8925,0x8F6F,0x962E,0x854A,
+0x745E,0x9510,0x95F0,0x6DA6,0x82E5,0x5F31,0x6492,0x6D12,
+0x8428,0x816E,0x9CC3,0x585E,0x8D5B,0x4E09,0x53C1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x847D,0x847E,0x847F,0x8480,0x8481,0x8483,0x8484,0x8485,
+0x8486,0x848A,0x848D,0x848F,0x8490,0x8491,0x8492,0x8493,
+0x8494,0x8495,0x8496,0x8498,0x849A,0x849B,0x849D,0x849E,
+0x849F,0x84A0,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,0x84A7,
+0x84A8,0x84A9,0x84AA,0x84AB,0x84AC,0x84AD,0x84AE,0x84B0,
+0x84B1,0x84B3,0x84B5,0x84B6,0x84B7,0x84BB,0x84BC,0x84BE,
+0x84C0,0x84C2,0x84C3,0x84C5,0x84C6,0x84C7,0x84C8,0x84CB,
+0x84CC,0x84CE,0x84CF,0x84D2,0x84D4,0x84D5,0x84D7, 0,
+0x84D8,0x84D9,0x84DA,0x84DB,0x84DC,0x84DE,0x84E1,0x84E2,
+0x84E4,0x84E7,0x84E8,0x84E9,0x84EA,0x84EB,0x84ED,0x84EE,
+0x84EF,0x84F1,0x84F2,0x84F3,0x84F4,0x84F5,0x84F6,0x84F7,
+0x84F8,0x84F9,0x84FA,0x84FB,0x84FD,0x84FE,0x8500,0x8501,
+0x8502,0x4F1E,0x6563,0x6851,0x55D3,0x4E27,0x6414,0x9A9A,
+0x626B,0x5AC2,0x745F,0x8272,0x6DA9,0x68EE,0x50E7,0x838E,
+0x7802,0x6740,0x5239,0x6C99,0x7EB1,0x50BB,0x5565,0x715E,
+0x7B5B,0x6652,0x73CA,0x82EB,0x6749,0x5C71,0x5220,0x717D,
+0x886B,0x95EA,0x9655,0x64C5,0x8D61,0x81B3,0x5584,0x6C55,
+0x6247,0x7F2E,0x5892,0x4F24,0x5546,0x8D4F,0x664C,0x4E0A,
+0x5C1A,0x88F3,0x68A2,0x634E,0x7A0D,0x70E7,0x828D,0x52FA,
+0x97F6,0x5C11,0x54E8,0x90B5,0x7ECD,0x5962,0x8D4A,0x86C7,
+0x820C,0x820D,0x8D66,0x6444,0x5C04,0x6151,0x6D89,0x793E,
+0x8BBE,0x7837,0x7533,0x547B,0x4F38,0x8EAB,0x6DF1,0x5A20,
+0x7EC5,0x795E,0x6C88,0x5BA1,0x5A76,0x751A,0x80BE,0x614E,
+0x6E17,0x58F0,0x751F,0x7525,0x7272,0x5347,0x7EF3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8503,0x8504,0x8505,0x8506,0x8507,0x8508,0x8509,0x850A,
+0x850B,0x850D,0x850E,0x850F,0x8510,0x8512,0x8514,0x8515,
+0x8516,0x8518,0x8519,0x851B,0x851C,0x851D,0x851E,0x8520,
+0x8522,0x8523,0x8524,0x8525,0x8526,0x8527,0x8528,0x8529,
+0x852A,0x852D,0x852E,0x852F,0x8530,0x8531,0x8532,0x8533,
+0x8534,0x8535,0x8536,0x853E,0x853F,0x8540,0x8541,0x8542,
+0x8544,0x8545,0x8546,0x8547,0x854B,0x854C,0x854D,0x854E,
+0x854F,0x8550,0x8551,0x8552,0x8553,0x8554,0x8555, 0,
+0x8557,0x8558,0x855A,0x855B,0x855C,0x855D,0x855F,0x8560,
+0x8561,0x8562,0x8563,0x8565,0x8566,0x8567,0x8569,0x856A,
+0x856B,0x856C,0x856D,0x856E,0x856F,0x8570,0x8571,0x8573,
+0x8575,0x8576,0x8577,0x8578,0x857C,0x857D,0x857F,0x8580,
+0x8581,0x7701,0x76DB,0x5269,0x80DC,0x5723,0x5E08,0x5931,
+0x72EE,0x65BD,0x6E7F,0x8BD7,0x5C38,0x8671,0x5341,0x77F3,
+0x62FE,0x65F6,0x4EC0,0x98DF,0x8680,0x5B9E,0x8BC6,0x53F2,
+0x77E2,0x4F7F,0x5C4E,0x9A76,0x59CB,0x5F0F,0x793A,0x58EB,
+0x4E16,0x67FF,0x4E8B,0x62ED,0x8A93,0x901D,0x52BF,0x662F,
+0x55DC,0x566C,0x9002,0x4ED5,0x4F8D,0x91CA,0x9970,0x6C0F,
+0x5E02,0x6043,0x5BA4,0x89C6,0x8BD5,0x6536,0x624B,0x9996,
+0x5B88,0x5BFF,0x6388,0x552E,0x53D7,0x7626,0x517D,0x852C,
+0x67A2,0x68B3,0x6B8A,0x6292,0x8F93,0x53D4,0x8212,0x6DD1,
+0x758F,0x4E66,0x8D4E,0x5B70,0x719F,0x85AF,0x6691,0x66D9,
+0x7F72,0x8700,0x9ECD,0x9F20,0x5C5E,0x672F,0x8FF0,0x6811,
+0x675F,0x620D,0x7AD6,0x5885,0x5EB6,0x6570,0x6F31, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8582,0x8583,0x8586,0x8588,0x8589,0x858A,0x858B,0x858C,
+0x858D,0x858E,0x8590,0x8591,0x8592,0x8593,0x8594,0x8595,
+0x8596,0x8597,0x8598,0x8599,0x859A,0x859D,0x859E,0x859F,
+0x85A0,0x85A1,0x85A2,0x85A3,0x85A5,0x85A6,0x85A7,0x85A9,
+0x85AB,0x85AC,0x85AD,0x85B1,0x85B2,0x85B3,0x85B4,0x85B5,
+0x85B6,0x85B8,0x85BA,0x85BB,0x85BC,0x85BD,0x85BE,0x85BF,
+0x85C0,0x85C2,0x85C3,0x85C4,0x85C5,0x85C6,0x85C7,0x85C8,
+0x85CA,0x85CB,0x85CC,0x85CD,0x85CE,0x85D1,0x85D2, 0,
+0x85D4,0x85D6,0x85D7,0x85D8,0x85D9,0x85DA,0x85DB,0x85DD,
+0x85DE,0x85DF,0x85E0,0x85E1,0x85E2,0x85E3,0x85E5,0x85E6,
+0x85E7,0x85E8,0x85EA,0x85EB,0x85EC,0x85ED,0x85EE,0x85EF,
+0x85F0,0x85F1,0x85F2,0x85F3,0x85F4,0x85F5,0x85F6,0x85F7,
+0x85F8,0x6055,0x5237,0x800D,0x6454,0x8870,0x7529,0x5E05,
+0x6813,0x62F4,0x971C,0x53CC,0x723D,0x8C01,0x6C34,0x7761,
+0x7A0E,0x542E,0x77AC,0x987A,0x821C,0x8BF4,0x7855,0x6714,
+0x70C1,0x65AF,0x6495,0x5636,0x601D,0x79C1,0x53F8,0x4E1D,
+0x6B7B,0x8086,0x5BFA,0x55E3,0x56DB,0x4F3A,0x4F3C,0x9972,
+0x5DF3,0x677E,0x8038,0x6002,0x9882,0x9001,0x5B8B,0x8BBC,
+0x8BF5,0x641C,0x8258,0x64DE,0x55FD,0x82CF,0x9165,0x4FD7,
+0x7D20,0x901F,0x7C9F,0x50F3,0x5851,0x6EAF,0x5BBF,0x8BC9,
+0x8083,0x9178,0x849C,0x7B97,0x867D,0x968B,0x968F,0x7EE5,
+0x9AD3,0x788E,0x5C81,0x7A57,0x9042,0x96A7,0x795F,0x5B59,
+0x635F,0x7B0B,0x84D1,0x68AD,0x5506,0x7F29,0x7410,0x7D22,
+0x9501,0x6240,0x584C,0x4ED6,0x5B83,0x5979,0x5854, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x85F9,0x85FA,0x85FC,0x85FD,0x85FE,0x8600,0x8601,0x8602,
+0x8603,0x8604,0x8606,0x8607,0x8608,0x8609,0x860A,0x860B,
+0x860C,0x860D,0x860E,0x860F,0x8610,0x8612,0x8613,0x8614,
+0x8615,0x8617,0x8618,0x8619,0x861A,0x861B,0x861C,0x861D,
+0x861E,0x861F,0x8620,0x8621,0x8622,0x8623,0x8624,0x8625,
+0x8626,0x8628,0x862A,0x862B,0x862C,0x862D,0x862E,0x862F,
+0x8630,0x8631,0x8632,0x8633,0x8634,0x8635,0x8636,0x8637,
+0x8639,0x863A,0x863B,0x863D,0x863E,0x863F,0x8640, 0,
+0x8641,0x8642,0x8643,0x8644,0x8645,0x8646,0x8647,0x8648,
+0x8649,0x864A,0x864B,0x864C,0x8652,0x8653,0x8655,0x8656,
+0x8657,0x8658,0x8659,0x865B,0x865C,0x865D,0x865F,0x8660,
+0x8661,0x8663,0x8664,0x8665,0x8666,0x8667,0x8668,0x8669,
+0x866A,0x736D,0x631E,0x8E4B,0x8E0F,0x80CE,0x82D4,0x62AC,
+0x53F0,0x6CF0,0x915E,0x592A,0x6001,0x6C70,0x574D,0x644A,
+0x8D2A,0x762B,0x6EE9,0x575B,0x6A80,0x75F0,0x6F6D,0x8C2D,
+0x8C08,0x5766,0x6BEF,0x8892,0x78B3,0x63A2,0x53F9,0x70AD,
+0x6C64,0x5858,0x642A,0x5802,0x68E0,0x819B,0x5510,0x7CD6,
+0x5018,0x8EBA,0x6DCC,0x8D9F,0x70EB,0x638F,0x6D9B,0x6ED4,
+0x7EE6,0x8404,0x6843,0x9003,0x6DD8,0x9676,0x8BA8,0x5957,
+0x7279,0x85E4,0x817E,0x75BC,0x8A8A,0x68AF,0x5254,0x8E22,
+0x9511,0x63D0,0x9898,0x8E44,0x557C,0x4F53,0x66FF,0x568F,
+0x60D5,0x6D95,0x5243,0x5C49,0x5929,0x6DFB,0x586B,0x7530,
+0x751C,0x606C,0x8214,0x8146,0x6311,0x6761,0x8FE2,0x773A,
+0x8DF3,0x8D34,0x94C1,0x5E16,0x5385,0x542C,0x70C3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x866D,0x866F,0x8670,0x8672,0x8673,0x8674,0x8675,0x8676,
+0x8677,0x8678,0x8683,0x8684,0x8685,0x8686,0x8687,0x8688,
+0x8689,0x868E,0x868F,0x8690,0x8691,0x8692,0x8694,0x8696,
+0x8697,0x8698,0x8699,0x869A,0x869B,0x869E,0x869F,0x86A0,
+0x86A1,0x86A2,0x86A5,0x86A6,0x86AB,0x86AD,0x86AE,0x86B2,
+0x86B3,0x86B7,0x86B8,0x86B9,0x86BB,0x86BC,0x86BD,0x86BE,
+0x86BF,0x86C1,0x86C2,0x86C3,0x86C5,0x86C8,0x86CC,0x86CD,
+0x86D2,0x86D3,0x86D5,0x86D6,0x86D7,0x86DA,0x86DC, 0,
+0x86DD,0x86E0,0x86E1,0x86E2,0x86E3,0x86E5,0x86E6,0x86E7,
+0x86E8,0x86EA,0x86EB,0x86EC,0x86EF,0x86F5,0x86F6,0x86F7,
+0x86FA,0x86FB,0x86FC,0x86FD,0x86FF,0x8701,0x8704,0x8705,
+0x8706,0x870B,0x870C,0x870E,0x870F,0x8710,0x8711,0x8714,
+0x8716,0x6C40,0x5EF7,0x505C,0x4EAD,0x5EAD,0x633A,0x8247,
+0x901A,0x6850,0x916E,0x77B3,0x540C,0x94DC,0x5F64,0x7AE5,
+0x6876,0x6345,0x7B52,0x7EDF,0x75DB,0x5077,0x6295,0x5934,
+0x900F,0x51F8,0x79C3,0x7A81,0x56FE,0x5F92,0x9014,0x6D82,
+0x5C60,0x571F,0x5410,0x5154,0x6E4D,0x56E2,0x63A8,0x9893,
+0x817F,0x8715,0x892A,0x9000,0x541E,0x5C6F,0x81C0,0x62D6,
+0x6258,0x8131,0x9E35,0x9640,0x9A6E,0x9A7C,0x692D,0x59A5,
+0x62D3,0x553E,0x6316,0x54C7,0x86D9,0x6D3C,0x5A03,0x74E6,
+0x889C,0x6B6A,0x5916,0x8C4C,0x5F2F,0x6E7E,0x73A9,0x987D,
+0x4E38,0x70F7,0x5B8C,0x7897,0x633D,0x665A,0x7696,0x60CB,
+0x5B9B,0x5A49,0x4E07,0x8155,0x6C6A,0x738B,0x4EA1,0x6789,
+0x7F51,0x5F80,0x65FA,0x671B,0x5FD8,0x5984,0x5A01, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8719,0x871B,0x871D,0x871F,0x8720,0x8724,0x8726,0x8727,
+0x8728,0x872A,0x872B,0x872C,0x872D,0x872F,0x8730,0x8732,
+0x8733,0x8735,0x8736,0x8738,0x8739,0x873A,0x873C,0x873D,
+0x8740,0x8741,0x8742,0x8743,0x8744,0x8745,0x8746,0x874A,
+0x874B,0x874D,0x874F,0x8750,0x8751,0x8752,0x8754,0x8755,
+0x8756,0x8758,0x875A,0x875B,0x875C,0x875D,0x875E,0x875F,
+0x8761,0x8762,0x8766,0x8767,0x8768,0x8769,0x876A,0x876B,
+0x876C,0x876D,0x876F,0x8771,0x8772,0x8773,0x8775, 0,
+0x8777,0x8778,0x8779,0x877A,0x877F,0x8780,0x8781,0x8784,
+0x8786,0x8787,0x8789,0x878A,0x878C,0x878E,0x878F,0x8790,
+0x8791,0x8792,0x8794,0x8795,0x8796,0x8798,0x8799,0x879A,
+0x879B,0x879C,0x879D,0x879E,0x87A0,0x87A1,0x87A2,0x87A3,
+0x87A4,0x5DCD,0x5FAE,0x5371,0x97E6,0x8FDD,0x6845,0x56F4,
+0x552F,0x60DF,0x4E3A,0x6F4D,0x7EF4,0x82C7,0x840E,0x59D4,
+0x4F1F,0x4F2A,0x5C3E,0x7EAC,0x672A,0x851A,0x5473,0x754F,
+0x80C3,0x5582,0x9B4F,0x4F4D,0x6E2D,0x8C13,0x5C09,0x6170,
+0x536B,0x761F,0x6E29,0x868A,0x6587,0x95FB,0x7EB9,0x543B,
+0x7A33,0x7D0A,0x95EE,0x55E1,0x7FC1,0x74EE,0x631D,0x8717,
+0x6DA1,0x7A9D,0x6211,0x65A1,0x5367,0x63E1,0x6C83,0x5DEB,
+0x545C,0x94A8,0x4E4C,0x6C61,0x8BEC,0x5C4B,0x65E0,0x829C,
+0x68A7,0x543E,0x5434,0x6BCB,0x6B66,0x4E94,0x6342,0x5348,
+0x821E,0x4F0D,0x4FAE,0x575E,0x620A,0x96FE,0x6664,0x7269,
+0x52FF,0x52A1,0x609F,0x8BEF,0x6614,0x7199,0x6790,0x897F,
+0x7852,0x77FD,0x6670,0x563B,0x5438,0x9521,0x727A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x87A5,0x87A6,0x87A7,0x87A9,0x87AA,0x87AE,0x87B0,0x87B1,
+0x87B2,0x87B4,0x87B6,0x87B7,0x87B8,0x87B9,0x87BB,0x87BC,
+0x87BE,0x87BF,0x87C1,0x87C2,0x87C3,0x87C4,0x87C5,0x87C7,
+0x87C8,0x87C9,0x87CC,0x87CD,0x87CE,0x87CF,0x87D0,0x87D4,
+0x87D5,0x87D6,0x87D7,0x87D8,0x87D9,0x87DA,0x87DC,0x87DD,
+0x87DE,0x87DF,0x87E1,0x87E2,0x87E3,0x87E4,0x87E6,0x87E7,
+0x87E8,0x87E9,0x87EB,0x87EC,0x87ED,0x87EF,0x87F0,0x87F1,
+0x87F2,0x87F3,0x87F4,0x87F5,0x87F6,0x87F7,0x87F8, 0,
+0x87FA,0x87FB,0x87FC,0x87FD,0x87FF,0x8800,0x8801,0x8802,
+0x8804,0x8805,0x8806,0x8807,0x8808,0x8809,0x880B,0x880C,
+0x880D,0x880E,0x880F,0x8810,0x8811,0x8812,0x8814,0x8817,
+0x8818,0x8819,0x881A,0x881C,0x881D,0x881E,0x881F,0x8820,
+0x8823,0x7A00,0x606F,0x5E0C,0x6089,0x819D,0x5915,0x60DC,
+0x7184,0x70EF,0x6EAA,0x6C50,0x7280,0x6A84,0x88AD,0x5E2D,
+0x4E60,0x5AB3,0x559C,0x94E3,0x6D17,0x7CFB,0x9699,0x620F,
+0x7EC6,0x778E,0x867E,0x5323,0x971E,0x8F96,0x6687,0x5CE1,
+0x4FA0,0x72ED,0x4E0B,0x53A6,0x590F,0x5413,0x6380,0x9528,
+0x5148,0x4ED9,0x9C9C,0x7EA4,0x54B8,0x8D24,0x8854,0x8237,
+0x95F2,0x6D8E,0x5F26,0x5ACC,0x663E,0x9669,0x73B0,0x732E,
+0x53BF,0x817A,0x9985,0x7FA1,0x5BAA,0x9677,0x9650,0x7EBF,
+0x76F8,0x53A2,0x9576,0x9999,0x7BB1,0x8944,0x6E58,0x4E61,
+0x7FD4,0x7965,0x8BE6,0x60F3,0x54CD,0x4EAB,0x9879,0x5DF7,
+0x6A61,0x50CF,0x5411,0x8C61,0x8427,0x785D,0x9704,0x524A,
+0x54EE,0x56A3,0x9500,0x6D88,0x5BB5,0x6DC6,0x6653, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8824,0x8825,0x8826,0x8827,0x8828,0x8829,0x882A,0x882B,
+0x882C,0x882D,0x882E,0x882F,0x8830,0x8831,0x8833,0x8834,
+0x8835,0x8836,0x8837,0x8838,0x883A,0x883B,0x883D,0x883E,
+0x883F,0x8841,0x8842,0x8843,0x8846,0x8847,0x8848,0x8849,
+0x884A,0x884B,0x884E,0x884F,0x8850,0x8851,0x8852,0x8853,
+0x8855,0x8856,0x8858,0x885A,0x885B,0x885C,0x885D,0x885E,
+0x885F,0x8860,0x8866,0x8867,0x886A,0x886D,0x886F,0x8871,
+0x8873,0x8874,0x8875,0x8876,0x8878,0x8879,0x887A, 0,
+0x887B,0x887C,0x8880,0x8883,0x8886,0x8887,0x8889,0x888A,
+0x888C,0x888E,0x888F,0x8890,0x8891,0x8893,0x8894,0x8895,
+0x8897,0x8898,0x8899,0x889A,0x889B,0x889D,0x889E,0x889F,
+0x88A0,0x88A1,0x88A3,0x88A5,0x88A6,0x88A7,0x88A8,0x88A9,
+0x88AA,0x5C0F,0x5B5D,0x6821,0x8096,0x5578,0x7B11,0x6548,
+0x6954,0x4E9B,0x6B47,0x874E,0x978B,0x534F,0x631F,0x643A,
+0x90AA,0x659C,0x80C1,0x8C10,0x5199,0x68B0,0x5378,0x87F9,
+0x61C8,0x6CC4,0x6CFB,0x8C22,0x5C51,0x85AA,0x82AF,0x950C,
+0x6B23,0x8F9B,0x65B0,0x5FFB,0x5FC3,0x4FE1,0x8845,0x661F,
+0x8165,0x7329,0x60FA,0x5174,0x5211,0x578B,0x5F62,0x90A2,
+0x884C,0x9192,0x5E78,0x674F,0x6027,0x59D3,0x5144,0x51F6,
+0x80F8,0x5308,0x6C79,0x96C4,0x718A,0x4F11,0x4FEE,0x7F9E,
+0x673D,0x55C5,0x9508,0x79C0,0x8896,0x7EE3,0x589F,0x620C,
+0x9700,0x865A,0x5618,0x987B,0x5F90,0x8BB8,0x84C4,0x9157,
+0x53D9,0x65ED,0x5E8F,0x755C,0x6064,0x7D6E,0x5A7F,0x7EEA,
+0x7EED,0x8F69,0x55A7,0x5BA3,0x60AC,0x65CB,0x7384, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x88AC,0x88AE,0x88AF,0x88B0,0x88B2,0x88B3,0x88B4,0x88B5,
+0x88B6,0x88B8,0x88B9,0x88BA,0x88BB,0x88BD,0x88BE,0x88BF,
+0x88C0,0x88C3,0x88C4,0x88C7,0x88C8,0x88CA,0x88CB,0x88CC,
+0x88CD,0x88CF,0x88D0,0x88D1,0x88D3,0x88D6,0x88D7,0x88DA,
+0x88DB,0x88DC,0x88DD,0x88DE,0x88E0,0x88E1,0x88E6,0x88E7,
+0x88E9,0x88EA,0x88EB,0x88EC,0x88ED,0x88EE,0x88EF,0x88F2,
+0x88F5,0x88F6,0x88F7,0x88FA,0x88FB,0x88FD,0x88FF,0x8900,
+0x8901,0x8903,0x8904,0x8905,0x8906,0x8907,0x8908, 0,
+0x8909,0x890B,0x890C,0x890D,0x890E,0x890F,0x8911,0x8914,
+0x8915,0x8916,0x8917,0x8918,0x891C,0x891D,0x891E,0x891F,
+0x8920,0x8922,0x8923,0x8924,0x8926,0x8927,0x8928,0x8929,
+0x892C,0x892D,0x892E,0x892F,0x8931,0x8932,0x8933,0x8935,
+0x8937,0x9009,0x7663,0x7729,0x7EDA,0x9774,0x859B,0x5B66,
+0x7A74,0x96EA,0x8840,0x52CB,0x718F,0x5FAA,0x65EC,0x8BE2,
+0x5BFB,0x9A6F,0x5DE1,0x6B89,0x6C5B,0x8BAD,0x8BAF,0x900A,
+0x8FC5,0x538B,0x62BC,0x9E26,0x9E2D,0x5440,0x4E2B,0x82BD,
+0x7259,0x869C,0x5D16,0x8859,0x6DAF,0x96C5,0x54D1,0x4E9A,
+0x8BB6,0x7109,0x54BD,0x9609,0x70DF,0x6DF9,0x76D0,0x4E25,
+0x7814,0x8712,0x5CA9,0x5EF6,0x8A00,0x989C,0x960E,0x708E,
+0x6CBF,0x5944,0x63A9,0x773C,0x884D,0x6F14,0x8273,0x5830,
+0x71D5,0x538C,0x781A,0x96C1,0x5501,0x5F66,0x7130,0x5BB4,
+0x8C1A,0x9A8C,0x6B83,0x592E,0x9E2F,0x79E7,0x6768,0x626C,
+0x4F6F,0x75A1,0x7F8A,0x6D0B,0x9633,0x6C27,0x4EF0,0x75D2,
+0x517B,0x6837,0x6F3E,0x9080,0x8170,0x5996,0x7476, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8938,0x8939,0x893A,0x893B,0x893C,0x893D,0x893E,0x893F,
+0x8940,0x8942,0x8943,0x8945,0x8946,0x8947,0x8948,0x8949,
+0x894A,0x894B,0x894C,0x894D,0x894E,0x894F,0x8950,0x8951,
+0x8952,0x8953,0x8954,0x8955,0x8956,0x8957,0x8958,0x8959,
+0x895A,0x895B,0x895C,0x895D,0x8960,0x8961,0x8962,0x8963,
+0x8964,0x8965,0x8967,0x8968,0x8969,0x896A,0x896B,0x896C,
+0x896D,0x896E,0x896F,0x8970,0x8971,0x8972,0x8973,0x8974,
+0x8975,0x8976,0x8977,0x8978,0x8979,0x897A,0x897C, 0,
+0x897D,0x897E,0x8980,0x8982,0x8984,0x8985,0x8987,0x8988,
+0x8989,0x898A,0x898B,0x898C,0x898D,0x898E,0x898F,0x8990,
+0x8991,0x8992,0x8993,0x8994,0x8995,0x8996,0x8997,0x8998,
+0x8999,0x899A,0x899B,0x899C,0x899D,0x899E,0x899F,0x89A0,
+0x89A1,0x6447,0x5C27,0x9065,0x7A91,0x8C23,0x59DA,0x54AC,
+0x8200,0x836F,0x8981,0x8000,0x6930,0x564E,0x8036,0x7237,
+0x91CE,0x51B6,0x4E5F,0x9875,0x6396,0x4E1A,0x53F6,0x66F3,
+0x814B,0x591C,0x6DB2,0x4E00,0x58F9,0x533B,0x63D6,0x94F1,
+0x4F9D,0x4F0A,0x8863,0x9890,0x5937,0x9057,0x79FB,0x4EEA,
+0x80F0,0x7591,0x6C82,0x5B9C,0x59E8,0x5F5D,0x6905,0x8681,
+0x501A,0x5DF2,0x4E59,0x77E3,0x4EE5,0x827A,0x6291,0x6613,
+0x9091,0x5C79,0x4EBF,0x5F79,0x81C6,0x9038,0x8084,0x75AB,
+0x4EA6,0x88D4,0x610F,0x6BC5,0x5FC6,0x4E49,0x76CA,0x6EA2,
+0x8BE3,0x8BAE,0x8C0A,0x8BD1,0x5F02,0x7FFC,0x7FCC,0x7ECE,
+0x8335,0x836B,0x56E0,0x6BB7,0x97F3,0x9634,0x59FB,0x541F,
+0x94F6,0x6DEB,0x5BC5,0x996E,0x5C39,0x5F15,0x9690, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x89A2,0x89A3,0x89A4,0x89A5,0x89A6,0x89A7,0x89A8,0x89A9,
+0x89AA,0x89AB,0x89AC,0x89AD,0x89AE,0x89AF,0x89B0,0x89B1,
+0x89B2,0x89B3,0x89B4,0x89B5,0x89B6,0x89B7,0x89B8,0x89B9,
+0x89BA,0x89BB,0x89BC,0x89BD,0x89BE,0x89BF,0x89C0,0x89C3,
+0x89CD,0x89D3,0x89D4,0x89D5,0x89D7,0x89D8,0x89D9,0x89DB,
+0x89DD,0x89DF,0x89E0,0x89E1,0x89E2,0x89E4,0x89E7,0x89E8,
+0x89E9,0x89EA,0x89EC,0x89ED,0x89EE,0x89F0,0x89F1,0x89F2,
+0x89F4,0x89F5,0x89F6,0x89F7,0x89F8,0x89F9,0x89FA, 0,
+0x89FB,0x89FC,0x89FD,0x89FE,0x89FF,0x8A01,0x8A02,0x8A03,
+0x8A04,0x8A05,0x8A06,0x8A08,0x8A09,0x8A0A,0x8A0B,0x8A0C,
+0x8A0D,0x8A0E,0x8A0F,0x8A10,0x8A11,0x8A12,0x8A13,0x8A14,
+0x8A15,0x8A16,0x8A17,0x8A18,0x8A19,0x8A1A,0x8A1B,0x8A1C,
+0x8A1D,0x5370,0x82F1,0x6A31,0x5A74,0x9E70,0x5E94,0x7F28,
+0x83B9,0x8424,0x8425,0x8367,0x8747,0x8FCE,0x8D62,0x76C8,
+0x5F71,0x9896,0x786C,0x6620,0x54DF,0x62E5,0x4F63,0x81C3,
+0x75C8,0x5EB8,0x96CD,0x8E0A,0x86F9,0x548F,0x6CF3,0x6D8C,
+0x6C38,0x607F,0x52C7,0x7528,0x5E7D,0x4F18,0x60A0,0x5FE7,
+0x5C24,0x7531,0x90AE,0x94C0,0x72B9,0x6CB9,0x6E38,0x9149,
+0x6709,0x53CB,0x53F3,0x4F51,0x91C9,0x8BF1,0x53C8,0x5E7C,
+0x8FC2,0x6DE4,0x4E8E,0x76C2,0x6986,0x865E,0x611A,0x8206,
+0x4F59,0x4FDE,0x903E,0x9C7C,0x6109,0x6E1D,0x6E14,0x9685,
+0x4E88,0x5A31,0x96E8,0x4E0E,0x5C7F,0x79B9,0x5B87,0x8BED,
+0x7FBD,0x7389,0x57DF,0x828B,0x90C1,0x5401,0x9047,0x55BB,
+0x5CEA,0x5FA1,0x6108,0x6B32,0x72F1,0x80B2,0x8A89, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8A1E,0x8A1F,0x8A20,0x8A21,0x8A22,0x8A23,0x8A24,0x8A25,
+0x8A26,0x8A27,0x8A28,0x8A29,0x8A2A,0x8A2B,0x8A2C,0x8A2D,
+0x8A2E,0x8A2F,0x8A30,0x8A31,0x8A32,0x8A33,0x8A34,0x8A35,
+0x8A36,0x8A37,0x8A38,0x8A39,0x8A3A,0x8A3B,0x8A3C,0x8A3D,
+0x8A3F,0x8A40,0x8A41,0x8A42,0x8A43,0x8A44,0x8A45,0x8A46,
+0x8A47,0x8A49,0x8A4A,0x8A4B,0x8A4C,0x8A4D,0x8A4E,0x8A4F,
+0x8A50,0x8A51,0x8A52,0x8A53,0x8A54,0x8A55,0x8A56,0x8A57,
+0x8A58,0x8A59,0x8A5A,0x8A5B,0x8A5C,0x8A5D,0x8A5E, 0,
+0x8A5F,0x8A60,0x8A61,0x8A62,0x8A63,0x8A64,0x8A65,0x8A66,
+0x8A67,0x8A68,0x8A69,0x8A6A,0x8A6B,0x8A6C,0x8A6D,0x8A6E,
+0x8A6F,0x8A70,0x8A71,0x8A72,0x8A73,0x8A74,0x8A75,0x8A76,
+0x8A77,0x8A78,0x8A7A,0x8A7B,0x8A7C,0x8A7D,0x8A7E,0x8A7F,
+0x8A80,0x6D74,0x5BD3,0x88D5,0x9884,0x8C6B,0x9A6D,0x9E33,
+0x6E0A,0x51A4,0x5143,0x57A3,0x8881,0x539F,0x63F4,0x8F95,
+0x56ED,0x5458,0x5706,0x733F,0x6E90,0x7F18,0x8FDC,0x82D1,
+0x613F,0x6028,0x9662,0x66F0,0x7EA6,0x8D8A,0x8DC3,0x94A5,
+0x5CB3,0x7CA4,0x6708,0x60A6,0x9605,0x8018,0x4E91,0x90E7,
+0x5300,0x9668,0x5141,0x8FD0,0x8574,0x915D,0x6655,0x97F5,
+0x5B55,0x531D,0x7838,0x6742,0x683D,0x54C9,0x707E,0x5BB0,
+0x8F7D,0x518D,0x5728,0x54B1,0x6512,0x6682,0x8D5E,0x8D43,
+0x810F,0x846C,0x906D,0x7CDF,0x51FF,0x85FB,0x67A3,0x65E9,
+0x6FA1,0x86A4,0x8E81,0x566A,0x9020,0x7682,0x7076,0x71E5,
+0x8D23,0x62E9,0x5219,0x6CFD,0x8D3C,0x600E,0x589E,0x618E,
+0x66FE,0x8D60,0x624E,0x55B3,0x6E23,0x672D,0x8F67, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8A81,0x8A82,0x8A83,0x8A84,0x8A85,0x8A86,0x8A87,0x8A88,
+0x8A8B,0x8A8C,0x8A8D,0x8A8E,0x8A8F,0x8A90,0x8A91,0x8A92,
+0x8A94,0x8A95,0x8A96,0x8A97,0x8A98,0x8A99,0x8A9A,0x8A9B,
+0x8A9C,0x8A9D,0x8A9E,0x8A9F,0x8AA0,0x8AA1,0x8AA2,0x8AA3,
+0x8AA4,0x8AA5,0x8AA6,0x8AA7,0x8AA8,0x8AA9,0x8AAA,0x8AAB,
+0x8AAC,0x8AAD,0x8AAE,0x8AAF,0x8AB0,0x8AB1,0x8AB2,0x8AB3,
+0x8AB4,0x8AB5,0x8AB6,0x8AB7,0x8AB8,0x8AB9,0x8ABA,0x8ABB,
+0x8ABC,0x8ABD,0x8ABE,0x8ABF,0x8AC0,0x8AC1,0x8AC2, 0,
+0x8AC3,0x8AC4,0x8AC5,0x8AC6,0x8AC7,0x8AC8,0x8AC9,0x8ACA,
+0x8ACB,0x8ACC,0x8ACD,0x8ACE,0x8ACF,0x8AD0,0x8AD1,0x8AD2,
+0x8AD3,0x8AD4,0x8AD5,0x8AD6,0x8AD7,0x8AD8,0x8AD9,0x8ADA,
+0x8ADB,0x8ADC,0x8ADD,0x8ADE,0x8ADF,0x8AE0,0x8AE1,0x8AE2,
+0x8AE3,0x94E1,0x95F8,0x7728,0x6805,0x69A8,0x548B,0x4E4D,
+0x70B8,0x8BC8,0x6458,0x658B,0x5B85,0x7A84,0x503A,0x5BE8,
+0x77BB,0x6BE1,0x8A79,0x7C98,0x6CBE,0x76CF,0x65A9,0x8F97,
+0x5D2D,0x5C55,0x8638,0x6808,0x5360,0x6218,0x7AD9,0x6E5B,
+0x7EFD,0x6A1F,0x7AE0,0x5F70,0x6F33,0x5F20,0x638C,0x6DA8,
+0x6756,0x4E08,0x5E10,0x8D26,0x4ED7,0x80C0,0x7634,0x969C,
+0x62DB,0x662D,0x627E,0x6CBC,0x8D75,0x7167,0x7F69,0x5146,
+0x8087,0x53EC,0x906E,0x6298,0x54F2,0x86F0,0x8F99,0x8005,
+0x9517,0x8517,0x8FD9,0x6D59,0x73CD,0x659F,0x771F,0x7504,
+0x7827,0x81FB,0x8D1E,0x9488,0x4FA6,0x6795,0x75B9,0x8BCA,
+0x9707,0x632F,0x9547,0x9635,0x84B8,0x6323,0x7741,0x5F81,
+0x72F0,0x4E89,0x6014,0x6574,0x62EF,0x6B63,0x653F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8AE4,0x8AE5,0x8AE6,0x8AE7,0x8AE8,0x8AE9,0x8AEA,0x8AEB,
+0x8AEC,0x8AED,0x8AEE,0x8AEF,0x8AF0,0x8AF1,0x8AF2,0x8AF3,
+0x8AF4,0x8AF5,0x8AF6,0x8AF7,0x8AF8,0x8AF9,0x8AFA,0x8AFB,
+0x8AFC,0x8AFD,0x8AFE,0x8AFF,0x8B00,0x8B01,0x8B02,0x8B03,
+0x8B04,0x8B05,0x8B06,0x8B08,0x8B09,0x8B0A,0x8B0B,0x8B0C,
+0x8B0D,0x8B0E,0x8B0F,0x8B10,0x8B11,0x8B12,0x8B13,0x8B14,
+0x8B15,0x8B16,0x8B17,0x8B18,0x8B19,0x8B1A,0x8B1B,0x8B1C,
+0x8B1D,0x8B1E,0x8B1F,0x8B20,0x8B21,0x8B22,0x8B23, 0,
+0x8B24,0x8B25,0x8B27,0x8B28,0x8B29,0x8B2A,0x8B2B,0x8B2C,
+0x8B2D,0x8B2E,0x8B2F,0x8B30,0x8B31,0x8B32,0x8B33,0x8B34,
+0x8B35,0x8B36,0x8B37,0x8B38,0x8B39,0x8B3A,0x8B3B,0x8B3C,
+0x8B3D,0x8B3E,0x8B3F,0x8B40,0x8B41,0x8B42,0x8B43,0x8B44,
+0x8B45,0x5E27,0x75C7,0x90D1,0x8BC1,0x829D,0x679D,0x652F,
+0x5431,0x8718,0x77E5,0x80A2,0x8102,0x6C41,0x4E4B,0x7EC7,
+0x804C,0x76F4,0x690D,0x6B96,0x6267,0x503C,0x4F84,0x5740,
+0x6307,0x6B62,0x8DBE,0x53EA,0x65E8,0x7EB8,0x5FD7,0x631A,
+0x63B7,0x81F3,0x81F4,0x7F6E,0x5E1C,0x5CD9,0x5236,0x667A,
+0x79E9,0x7A1A,0x8D28,0x7099,0x75D4,0x6EDE,0x6CBB,0x7A92,
+0x4E2D,0x76C5,0x5FE0,0x949F,0x8877,0x7EC8,0x79CD,0x80BF,
+0x91CD,0x4EF2,0x4F17,0x821F,0x5468,0x5DDE,0x6D32,0x8BCC,
+0x7CA5,0x8F74,0x8098,0x5E1A,0x5492,0x76B1,0x5B99,0x663C,
+0x9AA4,0x73E0,0x682A,0x86DB,0x6731,0x732A,0x8BF8,0x8BDB,
+0x9010,0x7AF9,0x70DB,0x716E,0x62C4,0x77A9,0x5631,0x4E3B,
+0x8457,0x67F1,0x52A9,0x86C0,0x8D2E,0x94F8,0x7B51, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B46,0x8B47,0x8B48,0x8B49,0x8B4A,0x8B4B,0x8B4C,0x8B4D,
+0x8B4E,0x8B4F,0x8B50,0x8B51,0x8B52,0x8B53,0x8B54,0x8B55,
+0x8B56,0x8B57,0x8B58,0x8B59,0x8B5A,0x8B5B,0x8B5C,0x8B5D,
+0x8B5E,0x8B5F,0x8B60,0x8B61,0x8B62,0x8B63,0x8B64,0x8B65,
+0x8B67,0x8B68,0x8B69,0x8B6A,0x8B6B,0x8B6D,0x8B6E,0x8B6F,
+0x8B70,0x8B71,0x8B72,0x8B73,0x8B74,0x8B75,0x8B76,0x8B77,
+0x8B78,0x8B79,0x8B7A,0x8B7B,0x8B7C,0x8B7D,0x8B7E,0x8B7F,
+0x8B80,0x8B81,0x8B82,0x8B83,0x8B84,0x8B85,0x8B86, 0,
+0x8B87,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0x8B8D,0x8B8E,
+0x8B8F,0x8B90,0x8B91,0x8B92,0x8B93,0x8B94,0x8B95,0x8B96,
+0x8B97,0x8B98,0x8B99,0x8B9A,0x8B9B,0x8B9C,0x8B9D,0x8B9E,
+0x8B9F,0x8BAC,0x8BB1,0x8BBB,0x8BC7,0x8BD0,0x8BEA,0x8C09,
+0x8C1E,0x4F4F,0x6CE8,0x795D,0x9A7B,0x6293,0x722A,0x62FD,
+0x4E13,0x7816,0x8F6C,0x64B0,0x8D5A,0x7BC6,0x6869,0x5E84,
+0x88C5,0x5986,0x649E,0x58EE,0x72B6,0x690E,0x9525,0x8FFD,
+0x8D58,0x5760,0x7F00,0x8C06,0x51C6,0x6349,0x62D9,0x5353,
+0x684C,0x7422,0x8301,0x914C,0x5544,0x7740,0x707C,0x6D4A,
+0x5179,0x54A8,0x8D44,0x59FF,0x6ECB,0x6DC4,0x5B5C,0x7D2B,
+0x4ED4,0x7C7D,0x6ED3,0x5B50,0x81EA,0x6E0D,0x5B57,0x9B03,
+0x68D5,0x8E2A,0x5B97,0x7EFC,0x603B,0x7EB5,0x90B9,0x8D70,
+0x594F,0x63CD,0x79DF,0x8DB3,0x5352,0x65CF,0x7956,0x8BC5,
+0x963B,0x7EC4,0x94BB,0x7E82,0x5634,0x9189,0x6700,0x7F6A,
+0x5C0A,0x9075,0x6628,0x5DE6,0x4F50,0x67DE,0x505A,0x4F5C,
+0x5750,0x5EA7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8C38,0x8C39,0x8C3A,0x8C3B,0x8C3C,0x8C3D,0x8C3E,0x8C3F,
+0x8C40,0x8C42,0x8C43,0x8C44,0x8C45,0x8C48,0x8C4A,0x8C4B,
+0x8C4D,0x8C4E,0x8C4F,0x8C50,0x8C51,0x8C52,0x8C53,0x8C54,
+0x8C56,0x8C57,0x8C58,0x8C59,0x8C5B,0x8C5C,0x8C5D,0x8C5E,
+0x8C5F,0x8C60,0x8C63,0x8C64,0x8C65,0x8C66,0x8C67,0x8C68,
+0x8C69,0x8C6C,0x8C6D,0x8C6E,0x8C6F,0x8C70,0x8C71,0x8C72,
+0x8C74,0x8C75,0x8C76,0x8C77,0x8C7B,0x8C7C,0x8C7D,0x8C7E,
+0x8C7F,0x8C80,0x8C81,0x8C83,0x8C84,0x8C86,0x8C87, 0,
+0x8C88,0x8C8B,0x8C8D,0x8C8E,0x8C8F,0x8C90,0x8C91,0x8C92,
+0x8C93,0x8C95,0x8C96,0x8C97,0x8C99,0x8C9A,0x8C9B,0x8C9C,
+0x8C9D,0x8C9E,0x8C9F,0x8CA0,0x8CA1,0x8CA2,0x8CA3,0x8CA4,
+0x8CA5,0x8CA6,0x8CA7,0x8CA8,0x8CA9,0x8CAA,0x8CAB,0x8CAC,
+0x8CAD,0x4E8D,0x4E0C,0x5140,0x4E10,0x5EFF,0x5345,0x4E15,
+0x4E98,0x4E1E,0x9B32,0x5B6C,0x5669,0x4E28,0x79BA,0x4E3F,
+0x5315,0x4E47,0x592D,0x723B,0x536E,0x6C10,0x56DF,0x80E4,
+0x9997,0x6BD3,0x777E,0x9F17,0x4E36,0x4E9F,0x9F10,0x4E5C,
+0x4E69,0x4E93,0x8288,0x5B5B,0x556C,0x560F,0x4EC4,0x538D,
+0x539D,0x53A3,0x53A5,0x53AE,0x9765,0x8D5D,0x531A,0x53F5,
+0x5326,0x532E,0x533E,0x8D5C,0x5366,0x5363,0x5202,0x5208,
+0x520E,0x522D,0x5233,0x523F,0x5240,0x524C,0x525E,0x5261,
+0x525C,0x84AF,0x527D,0x5282,0x5281,0x5290,0x5293,0x5182,
+0x7F54,0x4EBB,0x4EC3,0x4EC9,0x4EC2,0x4EE8,0x4EE1,0x4EEB,
+0x4EDE,0x4F1B,0x4EF3,0x4F22,0x4F64,0x4EF5,0x4F25,0x4F27,
+0x4F09,0x4F2B,0x4F5E,0x4F67,0x6538,0x4F5A,0x4F5D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8CAE,0x8CAF,0x8CB0,0x8CB1,0x8CB2,0x8CB3,0x8CB4,0x8CB5,
+0x8CB6,0x8CB7,0x8CB8,0x8CB9,0x8CBA,0x8CBB,0x8CBC,0x8CBD,
+0x8CBE,0x8CBF,0x8CC0,0x8CC1,0x8CC2,0x8CC3,0x8CC4,0x8CC5,
+0x8CC6,0x8CC7,0x8CC8,0x8CC9,0x8CCA,0x8CCB,0x8CCC,0x8CCD,
+0x8CCE,0x8CCF,0x8CD0,0x8CD1,0x8CD2,0x8CD3,0x8CD4,0x8CD5,
+0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,0x8CDB,0x8CDC,0x8CDD,
+0x8CDE,0x8CDF,0x8CE0,0x8CE1,0x8CE2,0x8CE3,0x8CE4,0x8CE5,
+0x8CE6,0x8CE7,0x8CE8,0x8CE9,0x8CEA,0x8CEB,0x8CEC, 0,
+0x8CED,0x8CEE,0x8CEF,0x8CF0,0x8CF1,0x8CF2,0x8CF3,0x8CF4,
+0x8CF5,0x8CF6,0x8CF7,0x8CF8,0x8CF9,0x8CFA,0x8CFB,0x8CFC,
+0x8CFD,0x8CFE,0x8CFF,0x8D00,0x8D01,0x8D02,0x8D03,0x8D04,
+0x8D05,0x8D06,0x8D07,0x8D08,0x8D09,0x8D0A,0x8D0B,0x8D0C,
+0x8D0D,0x4F5F,0x4F57,0x4F32,0x4F3D,0x4F76,0x4F74,0x4F91,
+0x4F89,0x4F83,0x4F8F,0x4F7E,0x4F7B,0x4FAA,0x4F7C,0x4FAC,
+0x4F94,0x4FE6,0x4FE8,0x4FEA,0x4FC5,0x4FDA,0x4FE3,0x4FDC,
+0x4FD1,0x4FDF,0x4FF8,0x5029,0x504C,0x4FF3,0x502C,0x500F,
+0x502E,0x502D,0x4FFE,0x501C,0x500C,0x5025,0x5028,0x507E,
+0x5043,0x5055,0x5048,0x504E,0x506C,0x507B,0x50A5,0x50A7,
+0x50A9,0x50BA,0x50D6,0x5106,0x50ED,0x50EC,0x50E6,0x50EE,
+0x5107,0x510B,0x4EDD,0x6C3D,0x4F58,0x4F65,0x4FCE,0x9FA0,
+0x6C46,0x7C74,0x516E,0x5DFD,0x9EC9,0x9998,0x5181,0x5914,
+0x52F9,0x530D,0x8A07,0x5310,0x51EB,0x5919,0x5155,0x4EA0,
+0x5156,0x4EB3,0x886E,0x88A4,0x4EB5,0x8114,0x88D2,0x7980,
+0x5B34,0x8803,0x7FB8,0x51AB,0x51B1,0x51BD,0x51BC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8D0E,0x8D0F,0x8D10,0x8D11,0x8D12,0x8D13,0x8D14,0x8D15,
+0x8D16,0x8D17,0x8D18,0x8D19,0x8D1A,0x8D1B,0x8D1C,0x8D20,
+0x8D51,0x8D52,0x8D57,0x8D5F,0x8D65,0x8D68,0x8D69,0x8D6A,
+0x8D6C,0x8D6E,0x8D6F,0x8D71,0x8D72,0x8D78,0x8D79,0x8D7A,
+0x8D7B,0x8D7C,0x8D7D,0x8D7E,0x8D7F,0x8D80,0x8D82,0x8D83,
+0x8D86,0x8D87,0x8D88,0x8D89,0x8D8C,0x8D8D,0x8D8E,0x8D8F,
+0x8D90,0x8D92,0x8D93,0x8D95,0x8D96,0x8D97,0x8D98,0x8D99,
+0x8D9A,0x8D9B,0x8D9C,0x8D9D,0x8D9E,0x8DA0,0x8DA1, 0,
+0x8DA2,0x8DA4,0x8DA5,0x8DA6,0x8DA7,0x8DA8,0x8DA9,0x8DAA,
+0x8DAB,0x8DAC,0x8DAD,0x8DAE,0x8DAF,0x8DB0,0x8DB2,0x8DB6,
+0x8DB7,0x8DB9,0x8DBB,0x8DBD,0x8DC0,0x8DC1,0x8DC2,0x8DC5,
+0x8DC7,0x8DC8,0x8DC9,0x8DCA,0x8DCD,0x8DD0,0x8DD2,0x8DD3,
+0x8DD4,0x51C7,0x5196,0x51A2,0x51A5,0x8BA0,0x8BA6,0x8BA7,
+0x8BAA,0x8BB4,0x8BB5,0x8BB7,0x8BC2,0x8BC3,0x8BCB,0x8BCF,
+0x8BCE,0x8BD2,0x8BD3,0x8BD4,0x8BD6,0x8BD8,0x8BD9,0x8BDC,
+0x8BDF,0x8BE0,0x8BE4,0x8BE8,0x8BE9,0x8BEE,0x8BF0,0x8BF3,
+0x8BF6,0x8BF9,0x8BFC,0x8BFF,0x8C00,0x8C02,0x8C04,0x8C07,
+0x8C0C,0x8C0F,0x8C11,0x8C12,0x8C14,0x8C15,0x8C16,0x8C19,
+0x8C1B,0x8C18,0x8C1D,0x8C1F,0x8C20,0x8C21,0x8C25,0x8C27,
+0x8C2A,0x8C2B,0x8C2E,0x8C2F,0x8C32,0x8C33,0x8C35,0x8C36,
+0x5369,0x537A,0x961D,0x9622,0x9621,0x9631,0x962A,0x963D,
+0x963C,0x9642,0x9649,0x9654,0x965F,0x9667,0x966C,0x9672,
+0x9674,0x9688,0x968D,0x9697,0x96B0,0x9097,0x909B,0x909D,
+0x9099,0x90AC,0x90A1,0x90B4,0x90B3,0x90B6,0x90BA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8DD5,0x8DD8,0x8DD9,0x8DDC,0x8DE0,0x8DE1,0x8DE2,0x8DE5,
+0x8DE6,0x8DE7,0x8DE9,0x8DED,0x8DEE,0x8DF0,0x8DF1,0x8DF2,
+0x8DF4,0x8DF6,0x8DFC,0x8DFE,0x8DFF,0x8E00,0x8E01,0x8E02,
+0x8E03,0x8E04,0x8E06,0x8E07,0x8E08,0x8E0B,0x8E0D,0x8E0E,
+0x8E10,0x8E11,0x8E12,0x8E13,0x8E15,0x8E16,0x8E17,0x8E18,
+0x8E19,0x8E1A,0x8E1B,0x8E1C,0x8E20,0x8E21,0x8E24,0x8E25,
+0x8E26,0x8E27,0x8E28,0x8E2B,0x8E2D,0x8E30,0x8E32,0x8E33,
+0x8E34,0x8E36,0x8E37,0x8E38,0x8E3B,0x8E3C,0x8E3E, 0,
+0x8E3F,0x8E43,0x8E45,0x8E46,0x8E4C,0x8E4D,0x8E4E,0x8E4F,
+0x8E50,0x8E53,0x8E54,0x8E55,0x8E56,0x8E57,0x8E58,0x8E5A,
+0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E5F,0x8E60,0x8E61,0x8E62,
+0x8E63,0x8E64,0x8E65,0x8E67,0x8E68,0x8E6A,0x8E6B,0x8E6E,
+0x8E71,0x90B8,0x90B0,0x90CF,0x90C5,0x90BE,0x90D0,0x90C4,
+0x90C7,0x90D3,0x90E6,0x90E2,0x90DC,0x90D7,0x90DB,0x90EB,
+0x90EF,0x90FE,0x9104,0x9122,0x911E,0x9123,0x9131,0x912F,
+0x9139,0x9143,0x9146,0x520D,0x5942,0x52A2,0x52AC,0x52AD,
+0x52BE,0x54FF,0x52D0,0x52D6,0x52F0,0x53DF,0x71EE,0x77CD,
+0x5EF4,0x51F5,0x51FC,0x9B2F,0x53B6,0x5F01,0x755A,0x5DEF,
+0x574C,0x57A9,0x57A1,0x587E,0x58BC,0x58C5,0x58D1,0x5729,
+0x572C,0x572A,0x5733,0x5739,0x572E,0x572F,0x575C,0x573B,
+0x5742,0x5769,0x5785,0x576B,0x5786,0x577C,0x577B,0x5768,
+0x576D,0x5776,0x5773,0x57AD,0x57A4,0x578C,0x57B2,0x57CF,
+0x57A7,0x57B4,0x5793,0x57A0,0x57D5,0x57D8,0x57DA,0x57D9,
+0x57D2,0x57B8,0x57F4,0x57EF,0x57F8,0x57E4,0x57DD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8E73,0x8E75,0x8E77,0x8E78,0x8E79,0x8E7A,0x8E7B,0x8E7D,
+0x8E7E,0x8E80,0x8E82,0x8E83,0x8E84,0x8E86,0x8E88,0x8E89,
+0x8E8A,0x8E8B,0x8E8C,0x8E8D,0x8E8E,0x8E91,0x8E92,0x8E93,
+0x8E95,0x8E96,0x8E97,0x8E98,0x8E99,0x8E9A,0x8E9B,0x8E9D,
+0x8E9F,0x8EA0,0x8EA1,0x8EA2,0x8EA3,0x8EA4,0x8EA5,0x8EA6,
+0x8EA7,0x8EA8,0x8EA9,0x8EAA,0x8EAD,0x8EAE,0x8EB0,0x8EB1,
+0x8EB3,0x8EB4,0x8EB5,0x8EB6,0x8EB7,0x8EB8,0x8EB9,0x8EBB,
+0x8EBC,0x8EBD,0x8EBE,0x8EBF,0x8EC0,0x8EC1,0x8EC2, 0,
+0x8EC3,0x8EC4,0x8EC5,0x8EC6,0x8EC7,0x8EC8,0x8EC9,0x8ECA,
+0x8ECB,0x8ECC,0x8ECD,0x8ECF,0x8ED0,0x8ED1,0x8ED2,0x8ED3,
+0x8ED4,0x8ED5,0x8ED6,0x8ED7,0x8ED8,0x8ED9,0x8EDA,0x8EDB,
+0x8EDC,0x8EDD,0x8EDE,0x8EDF,0x8EE0,0x8EE1,0x8EE2,0x8EE3,
+0x8EE4,0x580B,0x580D,0x57FD,0x57ED,0x5800,0x581E,0x5819,
+0x5844,0x5820,0x5865,0x586C,0x5881,0x5889,0x589A,0x5880,
+0x99A8,0x9F19,0x61FF,0x8279,0x827D,0x827F,0x828F,0x828A,
+0x82A8,0x8284,0x828E,0x8291,0x8297,0x8299,0x82AB,0x82B8,
+0x82BE,0x82B0,0x82C8,0x82CA,0x82E3,0x8298,0x82B7,0x82AE,
+0x82CB,0x82CC,0x82C1,0x82A9,0x82B4,0x82A1,0x82AA,0x829F,
+0x82C4,0x82CE,0x82A4,0x82E1,0x8309,0x82F7,0x82E4,0x830F,
+0x8307,0x82DC,0x82F4,0x82D2,0x82D8,0x830C,0x82FB,0x82D3,
+0x8311,0x831A,0x8306,0x8314,0x8315,0x82E0,0x82D5,0x831C,
+0x8351,0x835B,0x835C,0x8308,0x8392,0x833C,0x8334,0x8331,
+0x839B,0x835E,0x832F,0x834F,0x8347,0x8343,0x835F,0x8340,
+0x8317,0x8360,0x832D,0x833A,0x8333,0x8366,0x8365, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8EE5,0x8EE6,0x8EE7,0x8EE8,0x8EE9,0x8EEA,0x8EEB,0x8EEC,
+0x8EED,0x8EEE,0x8EEF,0x8EF0,0x8EF1,0x8EF2,0x8EF3,0x8EF4,
+0x8EF5,0x8EF6,0x8EF7,0x8EF8,0x8EF9,0x8EFA,0x8EFB,0x8EFC,
+0x8EFD,0x8EFE,0x8EFF,0x8F00,0x8F01,0x8F02,0x8F03,0x8F04,
+0x8F05,0x8F06,0x8F07,0x8F08,0x8F09,0x8F0A,0x8F0B,0x8F0C,
+0x8F0D,0x8F0E,0x8F0F,0x8F10,0x8F11,0x8F12,0x8F13,0x8F14,
+0x8F15,0x8F16,0x8F17,0x8F18,0x8F19,0x8F1A,0x8F1B,0x8F1C,
+0x8F1D,0x8F1E,0x8F1F,0x8F20,0x8F21,0x8F22,0x8F23, 0,
+0x8F24,0x8F25,0x8F26,0x8F27,0x8F28,0x8F29,0x8F2A,0x8F2B,
+0x8F2C,0x8F2D,0x8F2E,0x8F2F,0x8F30,0x8F31,0x8F32,0x8F33,
+0x8F34,0x8F35,0x8F36,0x8F37,0x8F38,0x8F39,0x8F3A,0x8F3B,
+0x8F3C,0x8F3D,0x8F3E,0x8F3F,0x8F40,0x8F41,0x8F42,0x8F43,
+0x8F44,0x8368,0x831B,0x8369,0x836C,0x836A,0x836D,0x836E,
+0x83B0,0x8378,0x83B3,0x83B4,0x83A0,0x83AA,0x8393,0x839C,
+0x8385,0x837C,0x83B6,0x83A9,0x837D,0x83B8,0x837B,0x8398,
+0x839E,0x83A8,0x83BA,0x83BC,0x83C1,0x8401,0x83E5,0x83D8,
+0x5807,0x8418,0x840B,0x83DD,0x83FD,0x83D6,0x841C,0x8438,
+0x8411,0x8406,0x83D4,0x83DF,0x840F,0x8403,0x83F8,0x83F9,
+0x83EA,0x83C5,0x83C0,0x8426,0x83F0,0x83E1,0x845C,0x8451,
+0x845A,0x8459,0x8473,0x8487,0x8488,0x847A,0x8489,0x8478,
+0x843C,0x8446,0x8469,0x8476,0x848C,0x848E,0x8431,0x846D,
+0x84C1,0x84CD,0x84D0,0x84E6,0x84BD,0x84D3,0x84CA,0x84BF,
+0x84BA,0x84E0,0x84A1,0x84B9,0x84B4,0x8497,0x84E5,0x84E3,
+0x850C,0x750D,0x8538,0x84F0,0x8539,0x851F,0x853A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8F45,0x8F46,0x8F47,0x8F48,0x8F49,0x8F4A,0x8F4B,0x8F4C,
+0x8F4D,0x8F4E,0x8F4F,0x8F50,0x8F51,0x8F52,0x8F53,0x8F54,
+0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A,0x8F5B,0x8F5C,
+0x8F5D,0x8F5E,0x8F5F,0x8F60,0x8F61,0x8F62,0x8F63,0x8F64,
+0x8F65,0x8F6A,0x8F80,0x8F8C,0x8F92,0x8F9D,0x8FA0,0x8FA1,
+0x8FA2,0x8FA4,0x8FA5,0x8FA6,0x8FA7,0x8FAA,0x8FAC,0x8FAD,
+0x8FAE,0x8FAF,0x8FB2,0x8FB3,0x8FB4,0x8FB5,0x8FB7,0x8FB8,
+0x8FBA,0x8FBB,0x8FBC,0x8FBF,0x8FC0,0x8FC3,0x8FC6, 0,
+0x8FC9,0x8FCA,0x8FCB,0x8FCC,0x8FCD,0x8FCF,0x8FD2,0x8FD6,
+0x8FD7,0x8FDA,0x8FE0,0x8FE1,0x8FE3,0x8FE7,0x8FEC,0x8FEF,
+0x8FF1,0x8FF2,0x8FF4,0x8FF5,0x8FF6,0x8FFA,0x8FFB,0x8FFC,
+0x8FFE,0x8FFF,0x9007,0x9008,0x900C,0x900E,0x9013,0x9015,
+0x9018,0x8556,0x853B,0x84FF,0x84FC,0x8559,0x8548,0x8568,
+0x8564,0x855E,0x857A,0x77A2,0x8543,0x8572,0x857B,0x85A4,
+0x85A8,0x8587,0x858F,0x8579,0x85AE,0x859C,0x8585,0x85B9,
+0x85B7,0x85B0,0x85D3,0x85C1,0x85DC,0x85FF,0x8627,0x8605,
+0x8629,0x8616,0x863C,0x5EFE,0x5F08,0x593C,0x5941,0x8037,
+0x5955,0x595A,0x5958,0x530F,0x5C22,0x5C25,0x5C2C,0x5C34,
+0x624C,0x626A,0x629F,0x62BB,0x62CA,0x62DA,0x62D7,0x62EE,
+0x6322,0x62F6,0x6339,0x634B,0x6343,0x63AD,0x63F6,0x6371,
+0x637A,0x638E,0x63B4,0x636D,0x63AC,0x638A,0x6369,0x63AE,
+0x63BC,0x63F2,0x63F8,0x63E0,0x63FF,0x63C4,0x63DE,0x63CE,
+0x6452,0x63C6,0x63BE,0x6445,0x6441,0x640B,0x641B,0x6420,
+0x640C,0x6426,0x6421,0x645E,0x6484,0x646D,0x6496, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9019,0x901C,0x9023,0x9024,0x9025,0x9027,0x9028,0x9029,
+0x902A,0x902B,0x902C,0x9030,0x9031,0x9032,0x9033,0x9034,
+0x9037,0x9039,0x903A,0x903D,0x903F,0x9040,0x9043,0x9045,
+0x9046,0x9048,0x9049,0x904A,0x904B,0x904C,0x904E,0x9054,
+0x9055,0x9056,0x9059,0x905A,0x905C,0x905D,0x905E,0x905F,
+0x9060,0x9061,0x9064,0x9066,0x9067,0x9069,0x906A,0x906B,
+0x906C,0x906F,0x9070,0x9071,0x9072,0x9073,0x9076,0x9077,
+0x9078,0x9079,0x907A,0x907B,0x907C,0x907E,0x9081, 0,
+0x9084,0x9085,0x9086,0x9087,0x9089,0x908A,0x908C,0x908D,
+0x908E,0x908F,0x9090,0x9092,0x9094,0x9096,0x9098,0x909A,
+0x909C,0x909E,0x909F,0x90A0,0x90A4,0x90A5,0x90A7,0x90A8,
+0x90A9,0x90AB,0x90AD,0x90B2,0x90B7,0x90BC,0x90BD,0x90BF,
+0x90C0,0x647A,0x64B7,0x64B8,0x6499,0x64BA,0x64C0,0x64D0,
+0x64D7,0x64E4,0x64E2,0x6509,0x6525,0x652E,0x5F0B,0x5FD2,
+0x7519,0x5F11,0x535F,0x53F1,0x53FD,0x53E9,0x53E8,0x53FB,
+0x5412,0x5416,0x5406,0x544B,0x5452,0x5453,0x5454,0x5456,
+0x5443,0x5421,0x5457,0x5459,0x5423,0x5432,0x5482,0x5494,
+0x5477,0x5471,0x5464,0x549A,0x549B,0x5484,0x5476,0x5466,
+0x549D,0x54D0,0x54AD,0x54C2,0x54B4,0x54D2,0x54A7,0x54A6,
+0x54D3,0x54D4,0x5472,0x54A3,0x54D5,0x54BB,0x54BF,0x54CC,
+0x54D9,0x54DA,0x54DC,0x54A9,0x54AA,0x54A4,0x54DD,0x54CF,
+0x54DE,0x551B,0x54E7,0x5520,0x54FD,0x5514,0x54F3,0x5522,
+0x5523,0x550F,0x5511,0x5527,0x552A,0x5567,0x558F,0x55B5,
+0x5549,0x556D,0x5541,0x5555,0x553F,0x5550,0x553C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x90C2,0x90C3,0x90C6,0x90C8,0x90C9,0x90CB,0x90CC,0x90CD,
+0x90D2,0x90D4,0x90D5,0x90D6,0x90D8,0x90D9,0x90DA,0x90DE,
+0x90DF,0x90E0,0x90E3,0x90E4,0x90E5,0x90E9,0x90EA,0x90EC,
+0x90EE,0x90F0,0x90F1,0x90F2,0x90F3,0x90F5,0x90F6,0x90F7,
+0x90F9,0x90FA,0x90FB,0x90FC,0x90FF,0x9100,0x9101,0x9103,
+0x9105,0x9106,0x9107,0x9108,0x9109,0x910A,0x910B,0x910C,
+0x910D,0x910E,0x910F,0x9110,0x9111,0x9112,0x9113,0x9114,
+0x9115,0x9116,0x9117,0x9118,0x911A,0x911B,0x911C, 0,
+0x911D,0x911F,0x9120,0x9121,0x9124,0x9125,0x9126,0x9127,
+0x9128,0x9129,0x912A,0x912B,0x912C,0x912D,0x912E,0x9130,
+0x9132,0x9133,0x9134,0x9135,0x9136,0x9137,0x9138,0x913A,
+0x913B,0x913C,0x913D,0x913E,0x913F,0x9140,0x9141,0x9142,
+0x9144,0x5537,0x5556,0x5575,0x5576,0x5577,0x5533,0x5530,
+0x555C,0x558B,0x55D2,0x5583,0x55B1,0x55B9,0x5588,0x5581,
+0x559F,0x557E,0x55D6,0x5591,0x557B,0x55DF,0x55BD,0x55BE,
+0x5594,0x5599,0x55EA,0x55F7,0x55C9,0x561F,0x55D1,0x55EB,
+0x55EC,0x55D4,0x55E6,0x55DD,0x55C4,0x55EF,0x55E5,0x55F2,
+0x55F3,0x55CC,0x55CD,0x55E8,0x55F5,0x55E4,0x8F94,0x561E,
+0x5608,0x560C,0x5601,0x5624,0x5623,0x55FE,0x5600,0x5627,
+0x562D,0x5658,0x5639,0x5657,0x562C,0x564D,0x5662,0x5659,
+0x565C,0x564C,0x5654,0x5686,0x5664,0x5671,0x566B,0x567B,
+0x567C,0x5685,0x5693,0x56AF,0x56D4,0x56D7,0x56DD,0x56E1,
+0x56F5,0x56EB,0x56F9,0x56FF,0x5704,0x570A,0x5709,0x571C,
+0x5E0F,0x5E19,0x5E14,0x5E11,0x5E31,0x5E3B,0x5E3C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9145,0x9147,0x9148,0x9151,0x9153,0x9154,0x9155,0x9156,
+0x9158,0x9159,0x915B,0x915C,0x915F,0x9160,0x9166,0x9167,
+0x9168,0x916B,0x916D,0x9173,0x917A,0x917B,0x917C,0x9180,
+0x9181,0x9182,0x9183,0x9184,0x9186,0x9188,0x918A,0x918E,
+0x918F,0x9193,0x9194,0x9195,0x9196,0x9197,0x9198,0x9199,
+0x919C,0x919D,0x919E,0x919F,0x91A0,0x91A1,0x91A4,0x91A5,
+0x91A6,0x91A7,0x91A8,0x91A9,0x91AB,0x91AC,0x91B0,0x91B1,
+0x91B2,0x91B3,0x91B6,0x91B7,0x91B8,0x91B9,0x91BB, 0,
+0x91BC,0x91BD,0x91BE,0x91BF,0x91C0,0x91C1,0x91C2,0x91C3,
+0x91C4,0x91C5,0x91C6,0x91C8,0x91CB,0x91D0,0x91D2,0x91D3,
+0x91D4,0x91D5,0x91D6,0x91D7,0x91D8,0x91D9,0x91DA,0x91DB,
+0x91DD,0x91DE,0x91DF,0x91E0,0x91E1,0x91E2,0x91E3,0x91E4,
+0x91E5,0x5E37,0x5E44,0x5E54,0x5E5B,0x5E5E,0x5E61,0x5C8C,
+0x5C7A,0x5C8D,0x5C90,0x5C96,0x5C88,0x5C98,0x5C99,0x5C91,
+0x5C9A,0x5C9C,0x5CB5,0x5CA2,0x5CBD,0x5CAC,0x5CAB,0x5CB1,
+0x5CA3,0x5CC1,0x5CB7,0x5CC4,0x5CD2,0x5CE4,0x5CCB,0x5CE5,
+0x5D02,0x5D03,0x5D27,0x5D26,0x5D2E,0x5D24,0x5D1E,0x5D06,
+0x5D1B,0x5D58,0x5D3E,0x5D34,0x5D3D,0x5D6C,0x5D5B,0x5D6F,
+0x5D5D,0x5D6B,0x5D4B,0x5D4A,0x5D69,0x5D74,0x5D82,0x5D99,
+0x5D9D,0x8C73,0x5DB7,0x5DC5,0x5F73,0x5F77,0x5F82,0x5F87,
+0x5F89,0x5F8C,0x5F95,0x5F99,0x5F9C,0x5FA8,0x5FAD,0x5FB5,
+0x5FBC,0x8862,0x5F61,0x72AD,0x72B0,0x72B4,0x72B7,0x72B8,
+0x72C3,0x72C1,0x72CE,0x72CD,0x72D2,0x72E8,0x72EF,0x72E9,
+0x72F2,0x72F4,0x72F7,0x7301,0x72F3,0x7303,0x72FA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x91E6,0x91E7,0x91E8,0x91E9,0x91EA,0x91EB,0x91EC,0x91ED,
+0x91EE,0x91EF,0x91F0,0x91F1,0x91F2,0x91F3,0x91F4,0x91F5,
+0x91F6,0x91F7,0x91F8,0x91F9,0x91FA,0x91FB,0x91FC,0x91FD,
+0x91FE,0x91FF,0x9200,0x9201,0x9202,0x9203,0x9204,0x9205,
+0x9206,0x9207,0x9208,0x9209,0x920A,0x920B,0x920C,0x920D,
+0x920E,0x920F,0x9210,0x9211,0x9212,0x9213,0x9214,0x9215,
+0x9216,0x9217,0x9218,0x9219,0x921A,0x921B,0x921C,0x921D,
+0x921E,0x921F,0x9220,0x9221,0x9222,0x9223,0x9224, 0,
+0x9225,0x9226,0x9227,0x9228,0x9229,0x922A,0x922B,0x922C,
+0x922D,0x922E,0x922F,0x9230,0x9231,0x9232,0x9233,0x9234,
+0x9235,0x9236,0x9237,0x9238,0x9239,0x923A,0x923B,0x923C,
+0x923D,0x923E,0x923F,0x9240,0x9241,0x9242,0x9243,0x9244,
+0x9245,0x72FB,0x7317,0x7313,0x7321,0x730A,0x731E,0x731D,
+0x7315,0x7322,0x7339,0x7325,0x732C,0x7338,0x7331,0x7350,
+0x734D,0x7357,0x7360,0x736C,0x736F,0x737E,0x821B,0x5925,
+0x98E7,0x5924,0x5902,0x9963,0x9967,0x9968,0x9969,0x996A,
+0x996B,0x996C,0x9974,0x9977,0x997D,0x9980,0x9984,0x9987,
+0x998A,0x998D,0x9990,0x9991,0x9993,0x9994,0x9995,0x5E80,
+0x5E91,0x5E8B,0x5E96,0x5EA5,0x5EA0,0x5EB9,0x5EB5,0x5EBE,
+0x5EB3,0x8D53,0x5ED2,0x5ED1,0x5EDB,0x5EE8,0x5EEA,0x81BA,
+0x5FC4,0x5FC9,0x5FD6,0x5FCF,0x6003,0x5FEE,0x6004,0x5FE1,
+0x5FE4,0x5FFE,0x6005,0x6006,0x5FEA,0x5FED,0x5FF8,0x6019,
+0x6035,0x6026,0x601B,0x600F,0x600D,0x6029,0x602B,0x600A,
+0x603F,0x6021,0x6078,0x6079,0x607B,0x607A,0x6042, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9246,0x9247,0x9248,0x9249,0x924A,0x924B,0x924C,0x924D,
+0x924E,0x924F,0x9250,0x9251,0x9252,0x9253,0x9254,0x9255,
+0x9256,0x9257,0x9258,0x9259,0x925A,0x925B,0x925C,0x925D,
+0x925E,0x925F,0x9260,0x9261,0x9262,0x9263,0x9264,0x9265,
+0x9266,0x9267,0x9268,0x9269,0x926A,0x926B,0x926C,0x926D,
+0x926E,0x926F,0x9270,0x9271,0x9272,0x9273,0x9275,0x9276,
+0x9277,0x9278,0x9279,0x927A,0x927B,0x927C,0x927D,0x927E,
+0x927F,0x9280,0x9281,0x9282,0x9283,0x9284,0x9285, 0,
+0x9286,0x9287,0x9288,0x9289,0x928A,0x928B,0x928C,0x928D,
+0x928F,0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296,
+0x9297,0x9298,0x9299,0x929A,0x929B,0x929C,0x929D,0x929E,
+0x929F,0x92A0,0x92A1,0x92A2,0x92A3,0x92A4,0x92A5,0x92A6,
+0x92A7,0x606A,0x607D,0x6096,0x609A,0x60AD,0x609D,0x6083,
+0x6092,0x608C,0x609B,0x60EC,0x60BB,0x60B1,0x60DD,0x60D8,
+0x60C6,0x60DA,0x60B4,0x6120,0x6126,0x6115,0x6123,0x60F4,
+0x6100,0x610E,0x612B,0x614A,0x6175,0x61AC,0x6194,0x61A7,
+0x61B7,0x61D4,0x61F5,0x5FDD,0x96B3,0x95E9,0x95EB,0x95F1,
+0x95F3,0x95F5,0x95F6,0x95FC,0x95FE,0x9603,0x9604,0x9606,
+0x9608,0x960A,0x960B,0x960C,0x960D,0x960F,0x9612,0x9615,
+0x9616,0x9617,0x9619,0x961A,0x4E2C,0x723F,0x6215,0x6C35,
+0x6C54,0x6C5C,0x6C4A,0x6CA3,0x6C85,0x6C90,0x6C94,0x6C8C,
+0x6C68,0x6C69,0x6C74,0x6C76,0x6C86,0x6CA9,0x6CD0,0x6CD4,
+0x6CAD,0x6CF7,0x6CF8,0x6CF1,0x6CD7,0x6CB2,0x6CE0,0x6CD6,
+0x6CFA,0x6CEB,0x6CEE,0x6CB1,0x6CD3,0x6CEF,0x6CFE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x92A8,0x92A9,0x92AA,0x92AB,0x92AC,0x92AD,0x92AF,0x92B0,
+0x92B1,0x92B2,0x92B3,0x92B4,0x92B5,0x92B6,0x92B7,0x92B8,
+0x92B9,0x92BA,0x92BB,0x92BC,0x92BD,0x92BE,0x92BF,0x92C0,
+0x92C1,0x92C2,0x92C3,0x92C4,0x92C5,0x92C6,0x92C7,0x92C9,
+0x92CA,0x92CB,0x92CC,0x92CD,0x92CE,0x92CF,0x92D0,0x92D1,
+0x92D2,0x92D3,0x92D4,0x92D5,0x92D6,0x92D7,0x92D8,0x92D9,
+0x92DA,0x92DB,0x92DC,0x92DD,0x92DE,0x92DF,0x92E0,0x92E1,
+0x92E2,0x92E3,0x92E4,0x92E5,0x92E6,0x92E7,0x92E8, 0,
+0x92E9,0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF,0x92F0,
+0x92F1,0x92F2,0x92F3,0x92F4,0x92F5,0x92F6,0x92F7,0x92F8,
+0x92F9,0x92FA,0x92FB,0x92FC,0x92FD,0x92FE,0x92FF,0x9300,
+0x9301,0x9302,0x9303,0x9304,0x9305,0x9306,0x9307,0x9308,
+0x9309,0x6D39,0x6D27,0x6D0C,0x6D43,0x6D48,0x6D07,0x6D04,
+0x6D19,0x6D0E,0x6D2B,0x6D4D,0x6D2E,0x6D35,0x6D1A,0x6D4F,
+0x6D52,0x6D54,0x6D33,0x6D91,0x6D6F,0x6D9E,0x6DA0,0x6D5E,
+0x6D93,0x6D94,0x6D5C,0x6D60,0x6D7C,0x6D63,0x6E1A,0x6DC7,
+0x6DC5,0x6DDE,0x6E0E,0x6DBF,0x6DE0,0x6E11,0x6DE6,0x6DDD,
+0x6DD9,0x6E16,0x6DAB,0x6E0C,0x6DAE,0x6E2B,0x6E6E,0x6E4E,
+0x6E6B,0x6EB2,0x6E5F,0x6E86,0x6E53,0x6E54,0x6E32,0x6E25,
+0x6E44,0x6EDF,0x6EB1,0x6E98,0x6EE0,0x6F2D,0x6EE2,0x6EA5,
+0x6EA7,0x6EBD,0x6EBB,0x6EB7,0x6ED7,0x6EB4,0x6ECF,0x6E8F,
+0x6EC2,0x6E9F,0x6F62,0x6F46,0x6F47,0x6F24,0x6F15,0x6EF9,
+0x6F2F,0x6F36,0x6F4B,0x6F74,0x6F2A,0x6F09,0x6F29,0x6F89,
+0x6F8D,0x6F8C,0x6F78,0x6F72,0x6F7C,0x6F7A,0x6FD1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x930A,0x930B,0x930C,0x930D,0x930E,0x930F,0x9310,0x9311,
+0x9312,0x9313,0x9314,0x9315,0x9316,0x9317,0x9318,0x9319,
+0x931A,0x931B,0x931C,0x931D,0x931E,0x931F,0x9320,0x9321,
+0x9322,0x9323,0x9324,0x9325,0x9326,0x9327,0x9328,0x9329,
+0x932A,0x932B,0x932C,0x932D,0x932E,0x932F,0x9330,0x9331,
+0x9332,0x9333,0x9334,0x9335,0x9336,0x9337,0x9338,0x9339,
+0x933A,0x933B,0x933C,0x933D,0x933F,0x9340,0x9341,0x9342,
+0x9343,0x9344,0x9345,0x9346,0x9347,0x9348,0x9349, 0,
+0x934A,0x934B,0x934C,0x934D,0x934E,0x934F,0x9350,0x9351,
+0x9352,0x9353,0x9354,0x9355,0x9356,0x9357,0x9358,0x9359,
+0x935A,0x935B,0x935C,0x935D,0x935E,0x935F,0x9360,0x9361,
+0x9362,0x9363,0x9364,0x9365,0x9366,0x9367,0x9368,0x9369,
+0x936B,0x6FC9,0x6FA7,0x6FB9,0x6FB6,0x6FC2,0x6FE1,0x6FEE,
+0x6FDE,0x6FE0,0x6FEF,0x701A,0x7023,0x701B,0x7039,0x7035,
+0x704F,0x705E,0x5B80,0x5B84,0x5B95,0x5B93,0x5BA5,0x5BB8,
+0x752F,0x9A9E,0x6434,0x5BE4,0x5BEE,0x8930,0x5BF0,0x8E47,
+0x8B07,0x8FB6,0x8FD3,0x8FD5,0x8FE5,0x8FEE,0x8FE4,0x8FE9,
+0x8FE6,0x8FF3,0x8FE8,0x9005,0x9004,0x900B,0x9026,0x9011,
+0x900D,0x9016,0x9021,0x9035,0x9036,0x902D,0x902F,0x9044,
+0x9051,0x9052,0x9050,0x9068,0x9058,0x9062,0x905B,0x66B9,
+0x9074,0x907D,0x9082,0x9088,0x9083,0x908B,0x5F50,0x5F57,
+0x5F56,0x5F58,0x5C3B,0x54AB,0x5C50,0x5C59,0x5B71,0x5C63,
+0x5C66,0x7FBC,0x5F2A,0x5F29,0x5F2D,0x8274,0x5F3C,0x9B3B,
+0x5C6E,0x5981,0x5983,0x598D,0x59A9,0x59AA,0x59A3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x936C,0x936D,0x936E,0x936F,0x9370,0x9371,0x9372,0x9373,
+0x9374,0x9375,0x9376,0x9377,0x9378,0x9379,0x937A,0x937B,
+0x937C,0x937D,0x937E,0x937F,0x9380,0x9381,0x9382,0x9383,
+0x9384,0x9385,0x9386,0x9387,0x9388,0x9389,0x938A,0x938B,
+0x938C,0x938D,0x938E,0x9390,0x9391,0x9392,0x9393,0x9394,
+0x9395,0x9396,0x9397,0x9398,0x9399,0x939A,0x939B,0x939C,
+0x939D,0x939E,0x939F,0x93A0,0x93A1,0x93A2,0x93A3,0x93A4,
+0x93A5,0x93A6,0x93A7,0x93A8,0x93A9,0x93AA,0x93AB, 0,
+0x93AC,0x93AD,0x93AE,0x93AF,0x93B0,0x93B1,0x93B2,0x93B3,
+0x93B4,0x93B5,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,0x93BB,
+0x93BC,0x93BD,0x93BE,0x93BF,0x93C0,0x93C1,0x93C2,0x93C3,
+0x93C4,0x93C5,0x93C6,0x93C7,0x93C8,0x93C9,0x93CB,0x93CC,
+0x93CD,0x5997,0x59CA,0x59AB,0x599E,0x59A4,0x59D2,0x59B2,
+0x59AF,0x59D7,0x59BE,0x5A05,0x5A06,0x59DD,0x5A08,0x59E3,
+0x59D8,0x59F9,0x5A0C,0x5A09,0x5A32,0x5A34,0x5A11,0x5A23,
+0x5A13,0x5A40,0x5A67,0x5A4A,0x5A55,0x5A3C,0x5A62,0x5A75,
+0x80EC,0x5AAA,0x5A9B,0x5A77,0x5A7A,0x5ABE,0x5AEB,0x5AB2,
+0x5AD2,0x5AD4,0x5AB8,0x5AE0,0x5AE3,0x5AF1,0x5AD6,0x5AE6,
+0x5AD8,0x5ADC,0x5B09,0x5B17,0x5B16,0x5B32,0x5B37,0x5B40,
+0x5C15,0x5C1C,0x5B5A,0x5B65,0x5B73,0x5B51,0x5B53,0x5B62,
+0x9A75,0x9A77,0x9A78,0x9A7A,0x9A7F,0x9A7D,0x9A80,0x9A81,
+0x9A85,0x9A88,0x9A8A,0x9A90,0x9A92,0x9A93,0x9A96,0x9A98,
+0x9A9B,0x9A9C,0x9A9D,0x9A9F,0x9AA0,0x9AA2,0x9AA3,0x9AA5,
+0x9AA7,0x7E9F,0x7EA1,0x7EA3,0x7EA5,0x7EA8,0x7EA9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x93CE,0x93CF,0x93D0,0x93D1,0x93D2,0x93D3,0x93D4,0x93D5,
+0x93D7,0x93D8,0x93D9,0x93DA,0x93DB,0x93DC,0x93DD,0x93DE,
+0x93DF,0x93E0,0x93E1,0x93E2,0x93E3,0x93E4,0x93E5,0x93E6,
+0x93E7,0x93E8,0x93E9,0x93EA,0x93EB,0x93EC,0x93ED,0x93EE,
+0x93EF,0x93F0,0x93F1,0x93F2,0x93F3,0x93F4,0x93F5,0x93F6,
+0x93F7,0x93F8,0x93F9,0x93FA,0x93FB,0x93FC,0x93FD,0x93FE,
+0x93FF,0x9400,0x9401,0x9402,0x9403,0x9404,0x9405,0x9406,
+0x9407,0x9408,0x9409,0x940A,0x940B,0x940C,0x940D, 0,
+0x940E,0x940F,0x9410,0x9411,0x9412,0x9413,0x9414,0x9415,
+0x9416,0x9417,0x9418,0x9419,0x941A,0x941B,0x941C,0x941D,
+0x941E,0x941F,0x9420,0x9421,0x9422,0x9423,0x9424,0x9425,
+0x9426,0x9427,0x9428,0x9429,0x942A,0x942B,0x942C,0x942D,
+0x942E,0x7EAD,0x7EB0,0x7EBE,0x7EC0,0x7EC1,0x7EC2,0x7EC9,
+0x7ECB,0x7ECC,0x7ED0,0x7ED4,0x7ED7,0x7EDB,0x7EE0,0x7EE1,
+0x7EE8,0x7EEB,0x7EEE,0x7EEF,0x7EF1,0x7EF2,0x7F0D,0x7EF6,
+0x7EFA,0x7EFB,0x7EFE,0x7F01,0x7F02,0x7F03,0x7F07,0x7F08,
+0x7F0B,0x7F0C,0x7F0F,0x7F11,0x7F12,0x7F17,0x7F19,0x7F1C,
+0x7F1B,0x7F1F,0x7F21,0x7F22,0x7F23,0x7F24,0x7F25,0x7F26,
+0x7F27,0x7F2A,0x7F2B,0x7F2C,0x7F2D,0x7F2F,0x7F30,0x7F31,
+0x7F32,0x7F33,0x7F35,0x5E7A,0x757F,0x5DDB,0x753E,0x9095,
+0x738E,0x7391,0x73AE,0x73A2,0x739F,0x73CF,0x73C2,0x73D1,
+0x73B7,0x73B3,0x73C0,0x73C9,0x73C8,0x73E5,0x73D9,0x987C,
+0x740A,0x73E9,0x73E7,0x73DE,0x73BA,0x73F2,0x740F,0x742A,
+0x745B,0x7426,0x7425,0x7428,0x7430,0x742E,0x742C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x942F,0x9430,0x9431,0x9432,0x9433,0x9434,0x9435,0x9436,
+0x9437,0x9438,0x9439,0x943A,0x943B,0x943C,0x943D,0x943F,
+0x9440,0x9441,0x9442,0x9443,0x9444,0x9445,0x9446,0x9447,
+0x9448,0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,0x944F,
+0x9450,0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457,
+0x9458,0x9459,0x945A,0x945B,0x945C,0x945D,0x945E,0x945F,
+0x9460,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467,
+0x9468,0x9469,0x946A,0x946C,0x946D,0x946E,0x946F, 0,
+0x9470,0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477,
+0x9478,0x9479,0x947A,0x947B,0x947C,0x947D,0x947E,0x947F,
+0x9480,0x9481,0x9482,0x9483,0x9484,0x9491,0x9496,0x9498,
+0x94C7,0x94CF,0x94D3,0x94D4,0x94DA,0x94E6,0x94FB,0x951C,
+0x9520,0x741B,0x741A,0x7441,0x745C,0x7457,0x7455,0x7459,
+0x7477,0x746D,0x747E,0x749C,0x748E,0x7480,0x7481,0x7487,
+0x748B,0x749E,0x74A8,0x74A9,0x7490,0x74A7,0x74D2,0x74BA,
+0x97EA,0x97EB,0x97EC,0x674C,0x6753,0x675E,0x6748,0x6769,
+0x67A5,0x6787,0x676A,0x6773,0x6798,0x67A7,0x6775,0x67A8,
+0x679E,0x67AD,0x678B,0x6777,0x677C,0x67F0,0x6809,0x67D8,
+0x680A,0x67E9,0x67B0,0x680C,0x67D9,0x67B5,0x67DA,0x67B3,
+0x67DD,0x6800,0x67C3,0x67B8,0x67E2,0x680E,0x67C1,0x67FD,
+0x6832,0x6833,0x6860,0x6861,0x684E,0x6862,0x6844,0x6864,
+0x6883,0x681D,0x6855,0x6866,0x6841,0x6867,0x6840,0x683E,
+0x684A,0x6849,0x6829,0x68B5,0x688F,0x6874,0x6877,0x6893,
+0x686B,0x68C2,0x696E,0x68FC,0x691F,0x6920,0x68F9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9527,0x9533,0x953D,0x9543,0x9548,0x954B,0x9555,0x955A,
+0x9560,0x956E,0x9574,0x9575,0x9577,0x9578,0x9579,0x957A,
+0x957B,0x957C,0x957D,0x957E,0x9580,0x9581,0x9582,0x9583,
+0x9584,0x9585,0x9586,0x9587,0x9588,0x9589,0x958A,0x958B,
+0x958C,0x958D,0x958E,0x958F,0x9590,0x9591,0x9592,0x9593,
+0x9594,0x9595,0x9596,0x9597,0x9598,0x9599,0x959A,0x959B,
+0x959C,0x959D,0x959E,0x959F,0x95A0,0x95A1,0x95A2,0x95A3,
+0x95A4,0x95A5,0x95A6,0x95A7,0x95A8,0x95A9,0x95AA, 0,
+0x95AB,0x95AC,0x95AD,0x95AE,0x95AF,0x95B0,0x95B1,0x95B2,
+0x95B3,0x95B4,0x95B5,0x95B6,0x95B7,0x95B8,0x95B9,0x95BA,
+0x95BB,0x95BC,0x95BD,0x95BE,0x95BF,0x95C0,0x95C1,0x95C2,
+0x95C3,0x95C4,0x95C5,0x95C6,0x95C7,0x95C8,0x95C9,0x95CA,
+0x95CB,0x6924,0x68F0,0x690B,0x6901,0x6957,0x68E3,0x6910,
+0x6971,0x6939,0x6960,0x6942,0x695D,0x6984,0x696B,0x6980,
+0x6998,0x6978,0x6934,0x69CC,0x6987,0x6988,0x69CE,0x6989,
+0x6966,0x6963,0x6979,0x699B,0x69A7,0x69BB,0x69AB,0x69AD,
+0x69D4,0x69B1,0x69C1,0x69CA,0x69DF,0x6995,0x69E0,0x698D,
+0x69FF,0x6A2F,0x69ED,0x6A17,0x6A18,0x6A65,0x69F2,0x6A44,
+0x6A3E,0x6AA0,0x6A50,0x6A5B,0x6A35,0x6A8E,0x6A79,0x6A3D,
+0x6A28,0x6A58,0x6A7C,0x6A91,0x6A90,0x6AA9,0x6A97,0x6AAB,
+0x7337,0x7352,0x6B81,0x6B82,0x6B87,0x6B84,0x6B92,0x6B93,
+0x6B8D,0x6B9A,0x6B9B,0x6BA1,0x6BAA,0x8F6B,0x8F6D,0x8F71,
+0x8F72,0x8F73,0x8F75,0x8F76,0x8F78,0x8F77,0x8F79,0x8F7A,
+0x8F7C,0x8F7E,0x8F81,0x8F82,0x8F84,0x8F87,0x8F8B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x95CC,0x95CD,0x95CE,0x95CF,0x95D0,0x95D1,0x95D2,0x95D3,
+0x95D4,0x95D5,0x95D6,0x95D7,0x95D8,0x95D9,0x95DA,0x95DB,
+0x95DC,0x95DD,0x95DE,0x95DF,0x95E0,0x95E1,0x95E2,0x95E3,
+0x95E4,0x95E5,0x95E6,0x95E7,0x95EC,0x95FF,0x9607,0x9613,
+0x9618,0x961B,0x961E,0x9620,0x9623,0x9624,0x9625,0x9626,
+0x9627,0x9628,0x9629,0x962B,0x962C,0x962D,0x962F,0x9630,
+0x9637,0x9638,0x9639,0x963A,0x963E,0x9641,0x9643,0x964A,
+0x964E,0x964F,0x9651,0x9652,0x9653,0x9656,0x9657, 0,
+0x9658,0x9659,0x965A,0x965C,0x965D,0x965E,0x9660,0x9663,
+0x9665,0x9666,0x966B,0x966D,0x966E,0x966F,0x9670,0x9671,
+0x9673,0x9678,0x9679,0x967A,0x967B,0x967C,0x967D,0x967E,
+0x967F,0x9680,0x9681,0x9682,0x9683,0x9684,0x9687,0x9689,
+0x968A,0x8F8D,0x8F8E,0x8F8F,0x8F98,0x8F9A,0x8ECE,0x620B,
+0x6217,0x621B,0x621F,0x6222,0x6221,0x6225,0x6224,0x622C,
+0x81E7,0x74EF,0x74F4,0x74FF,0x750F,0x7511,0x7513,0x6534,
+0x65EE,0x65EF,0x65F0,0x660A,0x6619,0x6772,0x6603,0x6615,
+0x6600,0x7085,0x66F7,0x661D,0x6634,0x6631,0x6636,0x6635,
+0x8006,0x665F,0x6654,0x6641,0x664F,0x6656,0x6661,0x6657,
+0x6677,0x6684,0x668C,0x66A7,0x669D,0x66BE,0x66DB,0x66DC,
+0x66E6,0x66E9,0x8D32,0x8D33,0x8D36,0x8D3B,0x8D3D,0x8D40,
+0x8D45,0x8D46,0x8D48,0x8D49,0x8D47,0x8D4D,0x8D55,0x8D59,
+0x89C7,0x89CA,0x89CB,0x89CC,0x89CE,0x89CF,0x89D0,0x89D1,
+0x726E,0x729F,0x725D,0x7266,0x726F,0x727E,0x727F,0x7284,
+0x728B,0x728D,0x728F,0x7292,0x6308,0x6332,0x63B0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x968C,0x968E,0x9691,0x9692,0x9693,0x9695,0x9696,0x969A,
+0x969B,0x969D,0x969E,0x969F,0x96A0,0x96A1,0x96A2,0x96A3,
+0x96A4,0x96A5,0x96A6,0x96A8,0x96A9,0x96AA,0x96AB,0x96AC,
+0x96AD,0x96AE,0x96AF,0x96B1,0x96B2,0x96B4,0x96B5,0x96B7,
+0x96B8,0x96BA,0x96BB,0x96BF,0x96C2,0x96C3,0x96C8,0x96CA,
+0x96CB,0x96D0,0x96D1,0x96D3,0x96D4,0x96D6,0x96D7,0x96D8,
+0x96D9,0x96DA,0x96DB,0x96DC,0x96DD,0x96DE,0x96DF,0x96E1,
+0x96E2,0x96E3,0x96E4,0x96E5,0x96E6,0x96E7,0x96EB, 0,
+0x96EC,0x96ED,0x96EE,0x96F0,0x96F1,0x96F2,0x96F4,0x96F5,
+0x96F8,0x96FA,0x96FB,0x96FC,0x96FD,0x96FF,0x9702,0x9703,
+0x9705,0x970A,0x970B,0x970C,0x9710,0x9711,0x9712,0x9714,
+0x9715,0x9717,0x9718,0x9719,0x971A,0x971B,0x971D,0x971F,
+0x9720,0x643F,0x64D8,0x8004,0x6BEA,0x6BF3,0x6BFD,0x6BF5,
+0x6BF9,0x6C05,0x6C07,0x6C06,0x6C0D,0x6C15,0x6C18,0x6C19,
+0x6C1A,0x6C21,0x6C29,0x6C24,0x6C2A,0x6C32,0x6535,0x6555,
+0x656B,0x724D,0x7252,0x7256,0x7230,0x8662,0x5216,0x809F,
+0x809C,0x8093,0x80BC,0x670A,0x80BD,0x80B1,0x80AB,0x80AD,
+0x80B4,0x80B7,0x80E7,0x80E8,0x80E9,0x80EA,0x80DB,0x80C2,
+0x80C4,0x80D9,0x80CD,0x80D7,0x6710,0x80DD,0x80EB,0x80F1,
+0x80F4,0x80ED,0x810D,0x810E,0x80F2,0x80FC,0x6715,0x8112,
+0x8C5A,0x8136,0x811E,0x812C,0x8118,0x8132,0x8148,0x814C,
+0x8153,0x8174,0x8159,0x815A,0x8171,0x8160,0x8169,0x817C,
+0x817D,0x816D,0x8167,0x584D,0x5AB5,0x8188,0x8182,0x8191,
+0x6ED5,0x81A3,0x81AA,0x81CC,0x6726,0x81CA,0x81BB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9721,0x9722,0x9723,0x9724,0x9725,0x9726,0x9727,0x9728,
+0x9729,0x972B,0x972C,0x972E,0x972F,0x9731,0x9733,0x9734,
+0x9735,0x9736,0x9737,0x973A,0x973B,0x973C,0x973D,0x973F,
+0x9740,0x9741,0x9742,0x9743,0x9744,0x9745,0x9746,0x9747,
+0x9748,0x9749,0x974A,0x974B,0x974C,0x974D,0x974E,0x974F,
+0x9750,0x9751,0x9754,0x9755,0x9757,0x9758,0x975A,0x975C,
+0x975D,0x975F,0x9763,0x9764,0x9766,0x9767,0x9768,0x976A,
+0x976B,0x976C,0x976D,0x976E,0x976F,0x9770,0x9771, 0,
+0x9772,0x9775,0x9777,0x9778,0x9779,0x977A,0x977B,0x977D,
+0x977E,0x977F,0x9780,0x9781,0x9782,0x9783,0x9784,0x9786,
+0x9787,0x9788,0x9789,0x978A,0x978C,0x978E,0x978F,0x9790,
+0x9793,0x9795,0x9796,0x9797,0x9799,0x979A,0x979B,0x979C,
+0x979D,0x81C1,0x81A6,0x6B24,0x6B37,0x6B39,0x6B43,0x6B46,
+0x6B59,0x98D1,0x98D2,0x98D3,0x98D5,0x98D9,0x98DA,0x6BB3,
+0x5F40,0x6BC2,0x89F3,0x6590,0x9F51,0x6593,0x65BC,0x65C6,
+0x65C4,0x65C3,0x65CC,0x65CE,0x65D2,0x65D6,0x7080,0x709C,
+0x7096,0x709D,0x70BB,0x70C0,0x70B7,0x70AB,0x70B1,0x70E8,
+0x70CA,0x7110,0x7113,0x7116,0x712F,0x7131,0x7173,0x715C,
+0x7168,0x7145,0x7172,0x714A,0x7178,0x717A,0x7198,0x71B3,
+0x71B5,0x71A8,0x71A0,0x71E0,0x71D4,0x71E7,0x71F9,0x721D,
+0x7228,0x706C,0x7118,0x7166,0x71B9,0x623E,0x623D,0x6243,
+0x6248,0x6249,0x793B,0x7940,0x7946,0x7949,0x795B,0x795C,
+0x7953,0x795A,0x7962,0x7957,0x7960,0x796F,0x7967,0x797A,
+0x7985,0x798A,0x799A,0x79A7,0x79B3,0x5FD1,0x5FD0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x979E,0x979F,0x97A1,0x97A2,0x97A4,0x97A5,0x97A6,0x97A7,
+0x97A8,0x97A9,0x97AA,0x97AC,0x97AE,0x97B0,0x97B1,0x97B3,
+0x97B5,0x97B6,0x97B7,0x97B8,0x97B9,0x97BA,0x97BB,0x97BC,
+0x97BD,0x97BE,0x97BF,0x97C0,0x97C1,0x97C2,0x97C3,0x97C4,
+0x97C5,0x97C6,0x97C7,0x97C8,0x97C9,0x97CA,0x97CB,0x97CC,
+0x97CD,0x97CE,0x97CF,0x97D0,0x97D1,0x97D2,0x97D3,0x97D4,
+0x97D5,0x97D6,0x97D7,0x97D8,0x97D9,0x97DA,0x97DB,0x97DC,
+0x97DD,0x97DE,0x97DF,0x97E0,0x97E1,0x97E2,0x97E3, 0,
+0x97E4,0x97E5,0x97E8,0x97EE,0x97EF,0x97F0,0x97F1,0x97F2,
+0x97F4,0x97F7,0x97F8,0x97F9,0x97FA,0x97FB,0x97FC,0x97FD,
+0x97FE,0x97FF,0x9800,0x9801,0x9802,0x9803,0x9804,0x9805,
+0x9806,0x9807,0x9808,0x9809,0x980A,0x980B,0x980C,0x980D,
+0x980E,0x603C,0x605D,0x605A,0x6067,0x6041,0x6059,0x6063,
+0x60AB,0x6106,0x610D,0x615D,0x61A9,0x619D,0x61CB,0x61D1,
+0x6206,0x8080,0x807F,0x6C93,0x6CF6,0x6DFC,0x77F6,0x77F8,
+0x7800,0x7809,0x7817,0x7818,0x7811,0x65AB,0x782D,0x781C,
+0x781D,0x7839,0x783A,0x783B,0x781F,0x783C,0x7825,0x782C,
+0x7823,0x7829,0x784E,0x786D,0x7856,0x7857,0x7826,0x7850,
+0x7847,0x784C,0x786A,0x789B,0x7893,0x789A,0x7887,0x789C,
+0x78A1,0x78A3,0x78B2,0x78B9,0x78A5,0x78D4,0x78D9,0x78C9,
+0x78EC,0x78F2,0x7905,0x78F4,0x7913,0x7924,0x791E,0x7934,
+0x9F9B,0x9EF9,0x9EFB,0x9EFC,0x76F1,0x7704,0x770D,0x76F9,
+0x7707,0x7708,0x771A,0x7722,0x7719,0x772D,0x7726,0x7735,
+0x7738,0x7750,0x7751,0x7747,0x7743,0x775A,0x7768, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x980F,0x9810,0x9811,0x9812,0x9813,0x9814,0x9815,0x9816,
+0x9817,0x9818,0x9819,0x981A,0x981B,0x981C,0x981D,0x981E,
+0x981F,0x9820,0x9821,0x9822,0x9823,0x9824,0x9825,0x9826,
+0x9827,0x9828,0x9829,0x982A,0x982B,0x982C,0x982D,0x982E,
+0x982F,0x9830,0x9831,0x9832,0x9833,0x9834,0x9835,0x9836,
+0x9837,0x9838,0x9839,0x983A,0x983B,0x983C,0x983D,0x983E,
+0x983F,0x9840,0x9841,0x9842,0x9843,0x9844,0x9845,0x9846,
+0x9847,0x9848,0x9849,0x984A,0x984B,0x984C,0x984D, 0,
+0x984E,0x984F,0x9850,0x9851,0x9852,0x9853,0x9854,0x9855,
+0x9856,0x9857,0x9858,0x9859,0x985A,0x985B,0x985C,0x985D,
+0x985E,0x985F,0x9860,0x9861,0x9862,0x9863,0x9864,0x9865,
+0x9866,0x9867,0x9868,0x9869,0x986A,0x986B,0x986C,0x986D,
+0x986E,0x7762,0x7765,0x777F,0x778D,0x777D,0x7780,0x778C,
+0x7791,0x779F,0x77A0,0x77B0,0x77B5,0x77BD,0x753A,0x7540,
+0x754E,0x754B,0x7548,0x755B,0x7572,0x7579,0x7583,0x7F58,
+0x7F61,0x7F5F,0x8A48,0x7F68,0x7F74,0x7F71,0x7F79,0x7F81,
+0x7F7E,0x76CD,0x76E5,0x8832,0x9485,0x9486,0x9487,0x948B,
+0x948A,0x948C,0x948D,0x948F,0x9490,0x9494,0x9497,0x9495,
+0x949A,0x949B,0x949C,0x94A3,0x94A4,0x94AB,0x94AA,0x94AD,
+0x94AC,0x94AF,0x94B0,0x94B2,0x94B4,0x94B6,0x94B7,0x94B8,
+0x94B9,0x94BA,0x94BC,0x94BD,0x94BF,0x94C4,0x94C8,0x94C9,
+0x94CA,0x94CB,0x94CC,0x94CD,0x94CE,0x94D0,0x94D1,0x94D2,
+0x94D5,0x94D6,0x94D7,0x94D9,0x94D8,0x94DB,0x94DE,0x94DF,
+0x94E0,0x94E2,0x94E4,0x94E5,0x94E7,0x94E8,0x94EA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x986F,0x9870,0x9871,0x9872,0x9873,0x9874,0x988B,0x988E,
+0x9892,0x9895,0x9899,0x98A3,0x98A8,0x98A9,0x98AA,0x98AB,
+0x98AC,0x98AD,0x98AE,0x98AF,0x98B0,0x98B1,0x98B2,0x98B3,
+0x98B4,0x98B5,0x98B6,0x98B7,0x98B8,0x98B9,0x98BA,0x98BB,
+0x98BC,0x98BD,0x98BE,0x98BF,0x98C0,0x98C1,0x98C2,0x98C3,
+0x98C4,0x98C5,0x98C6,0x98C7,0x98C8,0x98C9,0x98CA,0x98CB,
+0x98CC,0x98CD,0x98CF,0x98D0,0x98D4,0x98D6,0x98D7,0x98DB,
+0x98DC,0x98DD,0x98E0,0x98E1,0x98E2,0x98E3,0x98E4, 0,
+0x98E5,0x98E6,0x98E9,0x98EA,0x98EB,0x98EC,0x98ED,0x98EE,
+0x98EF,0x98F0,0x98F1,0x98F2,0x98F3,0x98F4,0x98F5,0x98F6,
+0x98F7,0x98F8,0x98F9,0x98FA,0x98FB,0x98FC,0x98FD,0x98FE,
+0x98FF,0x9900,0x9901,0x9902,0x9903,0x9904,0x9905,0x9906,
+0x9907,0x94E9,0x94EB,0x94EE,0x94EF,0x94F3,0x94F4,0x94F5,
+0x94F7,0x94F9,0x94FC,0x94FD,0x94FF,0x9503,0x9502,0x9506,
+0x9507,0x9509,0x950A,0x950D,0x950E,0x950F,0x9512,0x9513,
+0x9514,0x9515,0x9516,0x9518,0x951B,0x951D,0x951E,0x951F,
+0x9522,0x952A,0x952B,0x9529,0x952C,0x9531,0x9532,0x9534,
+0x9536,0x9537,0x9538,0x953C,0x953E,0x953F,0x9542,0x9535,
+0x9544,0x9545,0x9546,0x9549,0x954C,0x954E,0x954F,0x9552,
+0x9553,0x9554,0x9556,0x9557,0x9558,0x9559,0x955B,0x955E,
+0x955F,0x955D,0x9561,0x9562,0x9564,0x9565,0x9566,0x9567,
+0x9568,0x9569,0x956A,0x956B,0x956C,0x956F,0x9571,0x9572,
+0x9573,0x953A,0x77E7,0x77EC,0x96C9,0x79D5,0x79ED,0x79E3,
+0x79EB,0x7A06,0x5D47,0x7A03,0x7A02,0x7A1E,0x7A14, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9908,0x9909,0x990A,0x990B,0x990C,0x990E,0x990F,0x9911,
+0x9912,0x9913,0x9914,0x9915,0x9916,0x9917,0x9918,0x9919,
+0x991A,0x991B,0x991C,0x991D,0x991E,0x991F,0x9920,0x9921,
+0x9922,0x9923,0x9924,0x9925,0x9926,0x9927,0x9928,0x9929,
+0x992A,0x992B,0x992C,0x992D,0x992F,0x9930,0x9931,0x9932,
+0x9933,0x9934,0x9935,0x9936,0x9937,0x9938,0x9939,0x993A,
+0x993B,0x993C,0x993D,0x993E,0x993F,0x9940,0x9941,0x9942,
+0x9943,0x9944,0x9945,0x9946,0x9947,0x9948,0x9949, 0,
+0x994A,0x994B,0x994C,0x994D,0x994E,0x994F,0x9950,0x9951,
+0x9952,0x9953,0x9956,0x9957,0x9958,0x9959,0x995A,0x995B,
+0x995C,0x995D,0x995E,0x995F,0x9960,0x9961,0x9962,0x9964,
+0x9966,0x9973,0x9978,0x9979,0x997B,0x997E,0x9982,0x9983,
+0x9989,0x7A39,0x7A37,0x7A51,0x9ECF,0x99A5,0x7A70,0x7688,
+0x768E,0x7693,0x7699,0x76A4,0x74DE,0x74E0,0x752C,0x9E20,
+0x9E22,0x9E28,0x9E29,0x9E2A,0x9E2B,0x9E2C,0x9E32,0x9E31,
+0x9E36,0x9E38,0x9E37,0x9E39,0x9E3A,0x9E3E,0x9E41,0x9E42,
+0x9E44,0x9E46,0x9E47,0x9E48,0x9E49,0x9E4B,0x9E4C,0x9E4E,
+0x9E51,0x9E55,0x9E57,0x9E5A,0x9E5B,0x9E5C,0x9E5E,0x9E63,
+0x9E66,0x9E67,0x9E68,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E71,
+0x9E6D,0x9E73,0x7592,0x7594,0x7596,0x75A0,0x759D,0x75AC,
+0x75A3,0x75B3,0x75B4,0x75B8,0x75C4,0x75B1,0x75B0,0x75C3,
+0x75C2,0x75D6,0x75CD,0x75E3,0x75E8,0x75E6,0x75E4,0x75EB,
+0x75E7,0x7603,0x75F1,0x75FC,0x75FF,0x7610,0x7600,0x7605,
+0x760C,0x7617,0x760A,0x7625,0x7618,0x7615,0x7619, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x998C,0x998E,0x999A,0x999B,0x999C,0x999D,0x999E,0x999F,
+0x99A0,0x99A1,0x99A2,0x99A3,0x99A4,0x99A6,0x99A7,0x99A9,
+0x99AA,0x99AB,0x99AC,0x99AD,0x99AE,0x99AF,0x99B0,0x99B1,
+0x99B2,0x99B3,0x99B4,0x99B5,0x99B6,0x99B7,0x99B8,0x99B9,
+0x99BA,0x99BB,0x99BC,0x99BD,0x99BE,0x99BF,0x99C0,0x99C1,
+0x99C2,0x99C3,0x99C4,0x99C5,0x99C6,0x99C7,0x99C8,0x99C9,
+0x99CA,0x99CB,0x99CC,0x99CD,0x99CE,0x99CF,0x99D0,0x99D1,
+0x99D2,0x99D3,0x99D4,0x99D5,0x99D6,0x99D7,0x99D8, 0,
+0x99D9,0x99DA,0x99DB,0x99DC,0x99DD,0x99DE,0x99DF,0x99E0,
+0x99E1,0x99E2,0x99E3,0x99E4,0x99E5,0x99E6,0x99E7,0x99E8,
+0x99E9,0x99EA,0x99EB,0x99EC,0x99ED,0x99EE,0x99EF,0x99F0,
+0x99F1,0x99F2,0x99F3,0x99F4,0x99F5,0x99F6,0x99F7,0x99F8,
+0x99F9,0x761B,0x763C,0x7622,0x7620,0x7640,0x762D,0x7630,
+0x763F,0x7635,0x7643,0x763E,0x7633,0x764D,0x765E,0x7654,
+0x765C,0x7656,0x766B,0x766F,0x7FCA,0x7AE6,0x7A78,0x7A79,
+0x7A80,0x7A86,0x7A88,0x7A95,0x7AA6,0x7AA0,0x7AAC,0x7AA8,
+0x7AAD,0x7AB3,0x8864,0x8869,0x8872,0x887D,0x887F,0x8882,
+0x88A2,0x88C6,0x88B7,0x88BC,0x88C9,0x88E2,0x88CE,0x88E3,
+0x88E5,0x88F1,0x891A,0x88FC,0x88E8,0x88FE,0x88F0,0x8921,
+0x8919,0x8913,0x891B,0x890A,0x8934,0x892B,0x8936,0x8941,
+0x8966,0x897B,0x758B,0x80E5,0x76B2,0x76B4,0x77DC,0x8012,
+0x8014,0x8016,0x801C,0x8020,0x8022,0x8025,0x8026,0x8027,
+0x8029,0x8028,0x8031,0x800B,0x8035,0x8043,0x8046,0x804D,
+0x8052,0x8069,0x8071,0x8983,0x9878,0x9880,0x9883, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x99FA,0x99FB,0x99FC,0x99FD,0x99FE,0x99FF,0x9A00,0x9A01,
+0x9A02,0x9A03,0x9A04,0x9A05,0x9A06,0x9A07,0x9A08,0x9A09,
+0x9A0A,0x9A0B,0x9A0C,0x9A0D,0x9A0E,0x9A0F,0x9A10,0x9A11,
+0x9A12,0x9A13,0x9A14,0x9A15,0x9A16,0x9A17,0x9A18,0x9A19,
+0x9A1A,0x9A1B,0x9A1C,0x9A1D,0x9A1E,0x9A1F,0x9A20,0x9A21,
+0x9A22,0x9A23,0x9A24,0x9A25,0x9A26,0x9A27,0x9A28,0x9A29,
+0x9A2A,0x9A2B,0x9A2C,0x9A2D,0x9A2E,0x9A2F,0x9A30,0x9A31,
+0x9A32,0x9A33,0x9A34,0x9A35,0x9A36,0x9A37,0x9A38, 0,
+0x9A39,0x9A3A,0x9A3B,0x9A3C,0x9A3D,0x9A3E,0x9A3F,0x9A40,
+0x9A41,0x9A42,0x9A43,0x9A44,0x9A45,0x9A46,0x9A47,0x9A48,
+0x9A49,0x9A4A,0x9A4B,0x9A4C,0x9A4D,0x9A4E,0x9A4F,0x9A50,
+0x9A51,0x9A52,0x9A53,0x9A54,0x9A55,0x9A56,0x9A57,0x9A58,
+0x9A59,0x9889,0x988C,0x988D,0x988F,0x9894,0x989A,0x989B,
+0x989E,0x989F,0x98A1,0x98A2,0x98A5,0x98A6,0x864D,0x8654,
+0x866C,0x866E,0x867F,0x867A,0x867C,0x867B,0x86A8,0x868D,
+0x868B,0x86AC,0x869D,0x86A7,0x86A3,0x86AA,0x8693,0x86A9,
+0x86B6,0x86C4,0x86B5,0x86CE,0x86B0,0x86BA,0x86B1,0x86AF,
+0x86C9,0x86CF,0x86B4,0x86E9,0x86F1,0x86F2,0x86ED,0x86F3,
+0x86D0,0x8713,0x86DE,0x86F4,0x86DF,0x86D8,0x86D1,0x8703,
+0x8707,0x86F8,0x8708,0x870A,0x870D,0x8709,0x8723,0x873B,
+0x871E,0x8725,0x872E,0x871A,0x873E,0x8748,0x8734,0x8731,
+0x8729,0x8737,0x873F,0x8782,0x8722,0x877D,0x877E,0x877B,
+0x8760,0x8770,0x874C,0x876E,0x878B,0x8753,0x8763,0x877C,
+0x8764,0x8759,0x8765,0x8793,0x87AF,0x87A8,0x87D2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9A5A,0x9A5B,0x9A5C,0x9A5D,0x9A5E,0x9A5F,0x9A60,0x9A61,
+0x9A62,0x9A63,0x9A64,0x9A65,0x9A66,0x9A67,0x9A68,0x9A69,
+0x9A6A,0x9A6B,0x9A72,0x9A83,0x9A89,0x9A8D,0x9A8E,0x9A94,
+0x9A95,0x9A99,0x9AA6,0x9AA9,0x9AAA,0x9AAB,0x9AAC,0x9AAD,
+0x9AAE,0x9AAF,0x9AB2,0x9AB3,0x9AB4,0x9AB5,0x9AB9,0x9ABB,
+0x9ABD,0x9ABE,0x9ABF,0x9AC3,0x9AC4,0x9AC6,0x9AC7,0x9AC8,
+0x9AC9,0x9ACA,0x9ACD,0x9ACE,0x9ACF,0x9AD0,0x9AD2,0x9AD4,
+0x9AD5,0x9AD6,0x9AD7,0x9AD9,0x9ADA,0x9ADB,0x9ADC, 0,
+0x9ADD,0x9ADE,0x9AE0,0x9AE2,0x9AE3,0x9AE4,0x9AE5,0x9AE7,
+0x9AE8,0x9AE9,0x9AEA,0x9AEC,0x9AEE,0x9AF0,0x9AF1,0x9AF2,
+0x9AF3,0x9AF4,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AFA,0x9AFC,
+0x9AFD,0x9AFE,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B04,0x9B05,
+0x9B06,0x87C6,0x8788,0x8785,0x87AD,0x8797,0x8783,0x87AB,
+0x87E5,0x87AC,0x87B5,0x87B3,0x87CB,0x87D3,0x87BD,0x87D1,
+0x87C0,0x87CA,0x87DB,0x87EA,0x87E0,0x87EE,0x8816,0x8813,
+0x87FE,0x880A,0x881B,0x8821,0x8839,0x883C,0x7F36,0x7F42,
+0x7F44,0x7F45,0x8210,0x7AFA,0x7AFD,0x7B08,0x7B03,0x7B04,
+0x7B15,0x7B0A,0x7B2B,0x7B0F,0x7B47,0x7B38,0x7B2A,0x7B19,
+0x7B2E,0x7B31,0x7B20,0x7B25,0x7B24,0x7B33,0x7B3E,0x7B1E,
+0x7B58,0x7B5A,0x7B45,0x7B75,0x7B4C,0x7B5D,0x7B60,0x7B6E,
+0x7B7B,0x7B62,0x7B72,0x7B71,0x7B90,0x7BA6,0x7BA7,0x7BB8,
+0x7BAC,0x7B9D,0x7BA8,0x7B85,0x7BAA,0x7B9C,0x7BA2,0x7BAB,
+0x7BB4,0x7BD1,0x7BC1,0x7BCC,0x7BDD,0x7BDA,0x7BE5,0x7BE6,
+0x7BEA,0x7C0C,0x7BFE,0x7BFC,0x7C0F,0x7C16,0x7C0B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9B07,0x9B09,0x9B0A,0x9B0B,0x9B0C,0x9B0D,0x9B0E,0x9B10,
+0x9B11,0x9B12,0x9B14,0x9B15,0x9B16,0x9B17,0x9B18,0x9B19,
+0x9B1A,0x9B1B,0x9B1C,0x9B1D,0x9B1E,0x9B20,0x9B21,0x9B22,
+0x9B24,0x9B25,0x9B26,0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2B,
+0x9B2C,0x9B2D,0x9B2E,0x9B30,0x9B31,0x9B33,0x9B34,0x9B35,
+0x9B36,0x9B37,0x9B38,0x9B39,0x9B3A,0x9B3D,0x9B3E,0x9B3F,
+0x9B40,0x9B46,0x9B4A,0x9B4B,0x9B4C,0x9B4E,0x9B50,0x9B52,
+0x9B53,0x9B55,0x9B56,0x9B57,0x9B58,0x9B59,0x9B5A, 0,
+0x9B5B,0x9B5C,0x9B5D,0x9B5E,0x9B5F,0x9B60,0x9B61,0x9B62,
+0x9B63,0x9B64,0x9B65,0x9B66,0x9B67,0x9B68,0x9B69,0x9B6A,
+0x9B6B,0x9B6C,0x9B6D,0x9B6E,0x9B6F,0x9B70,0x9B71,0x9B72,
+0x9B73,0x9B74,0x9B75,0x9B76,0x9B77,0x9B78,0x9B79,0x9B7A,
+0x9B7B,0x7C1F,0x7C2A,0x7C26,0x7C38,0x7C41,0x7C40,0x81FE,
+0x8201,0x8202,0x8204,0x81EC,0x8844,0x8221,0x8222,0x8223,
+0x822D,0x822F,0x8228,0x822B,0x8238,0x823B,0x8233,0x8234,
+0x823E,0x8244,0x8249,0x824B,0x824F,0x825A,0x825F,0x8268,
+0x887E,0x8885,0x8888,0x88D8,0x88DF,0x895E,0x7F9D,0x7F9F,
+0x7FA7,0x7FAF,0x7FB0,0x7FB2,0x7C7C,0x6549,0x7C91,0x7C9D,
+0x7C9C,0x7C9E,0x7CA2,0x7CB2,0x7CBC,0x7CBD,0x7CC1,0x7CC7,
+0x7CCC,0x7CCD,0x7CC8,0x7CC5,0x7CD7,0x7CE8,0x826E,0x66A8,
+0x7FBF,0x7FCE,0x7FD5,0x7FE5,0x7FE1,0x7FE6,0x7FE9,0x7FEE,
+0x7FF3,0x7CF8,0x7D77,0x7DA6,0x7DAE,0x7E47,0x7E9B,0x9EB8,
+0x9EB4,0x8D73,0x8D84,0x8D94,0x8D91,0x8DB1,0x8D67,0x8D6D,
+0x8C47,0x8C49,0x914A,0x9150,0x914E,0x914F,0x9164, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9B7C,0x9B7D,0x9B7E,0x9B7F,0x9B80,0x9B81,0x9B82,0x9B83,
+0x9B84,0x9B85,0x9B86,0x9B87,0x9B88,0x9B89,0x9B8A,0x9B8B,
+0x9B8C,0x9B8D,0x9B8E,0x9B8F,0x9B90,0x9B91,0x9B92,0x9B93,
+0x9B94,0x9B95,0x9B96,0x9B97,0x9B98,0x9B99,0x9B9A,0x9B9B,
+0x9B9C,0x9B9D,0x9B9E,0x9B9F,0x9BA0,0x9BA1,0x9BA2,0x9BA3,
+0x9BA4,0x9BA5,0x9BA6,0x9BA7,0x9BA8,0x9BA9,0x9BAA,0x9BAB,
+0x9BAC,0x9BAD,0x9BAE,0x9BAF,0x9BB0,0x9BB1,0x9BB2,0x9BB3,
+0x9BB4,0x9BB5,0x9BB6,0x9BB7,0x9BB8,0x9BB9,0x9BBA, 0,
+0x9BBB,0x9BBC,0x9BBD,0x9BBE,0x9BBF,0x9BC0,0x9BC1,0x9BC2,
+0x9BC3,0x9BC4,0x9BC5,0x9BC6,0x9BC7,0x9BC8,0x9BC9,0x9BCA,
+0x9BCB,0x9BCC,0x9BCD,0x9BCE,0x9BCF,0x9BD0,0x9BD1,0x9BD2,
+0x9BD3,0x9BD4,0x9BD5,0x9BD6,0x9BD7,0x9BD8,0x9BD9,0x9BDA,
+0x9BDB,0x9162,0x9161,0x9170,0x9169,0x916F,0x917D,0x917E,
+0x9172,0x9174,0x9179,0x918C,0x9185,0x9190,0x918D,0x9191,
+0x91A2,0x91A3,0x91AA,0x91AD,0x91AE,0x91AF,0x91B5,0x91B4,
+0x91BA,0x8C55,0x9E7E,0x8DB8,0x8DEB,0x8E05,0x8E59,0x8E69,
+0x8DB5,0x8DBF,0x8DBC,0x8DBA,0x8DC4,0x8DD6,0x8DD7,0x8DDA,
+0x8DDE,0x8DCE,0x8DCF,0x8DDB,0x8DC6,0x8DEC,0x8DF7,0x8DF8,
+0x8DE3,0x8DF9,0x8DFB,0x8DE4,0x8E09,0x8DFD,0x8E14,0x8E1D,
+0x8E1F,0x8E2C,0x8E2E,0x8E23,0x8E2F,0x8E3A,0x8E40,0x8E39,
+0x8E35,0x8E3D,0x8E31,0x8E49,0x8E41,0x8E42,0x8E51,0x8E52,
+0x8E4A,0x8E70,0x8E76,0x8E7C,0x8E6F,0x8E74,0x8E85,0x8E8F,
+0x8E94,0x8E90,0x8E9C,0x8E9E,0x8C78,0x8C82,0x8C8A,0x8C85,
+0x8C98,0x8C94,0x659B,0x89D6,0x89DE,0x89DA,0x89DC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9BDC,0x9BDD,0x9BDE,0x9BDF,0x9BE0,0x9BE1,0x9BE2,0x9BE3,
+0x9BE4,0x9BE5,0x9BE6,0x9BE7,0x9BE8,0x9BE9,0x9BEA,0x9BEB,
+0x9BEC,0x9BED,0x9BEE,0x9BEF,0x9BF0,0x9BF1,0x9BF2,0x9BF3,
+0x9BF4,0x9BF5,0x9BF6,0x9BF7,0x9BF8,0x9BF9,0x9BFA,0x9BFB,
+0x9BFC,0x9BFD,0x9BFE,0x9BFF,0x9C00,0x9C01,0x9C02,0x9C03,
+0x9C04,0x9C05,0x9C06,0x9C07,0x9C08,0x9C09,0x9C0A,0x9C0B,
+0x9C0C,0x9C0D,0x9C0E,0x9C0F,0x9C10,0x9C11,0x9C12,0x9C13,
+0x9C14,0x9C15,0x9C16,0x9C17,0x9C18,0x9C19,0x9C1A, 0,
+0x9C1B,0x9C1C,0x9C1D,0x9C1E,0x9C1F,0x9C20,0x9C21,0x9C22,
+0x9C23,0x9C24,0x9C25,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,
+0x9C2B,0x9C2C,0x9C2D,0x9C2E,0x9C2F,0x9C30,0x9C31,0x9C32,
+0x9C33,0x9C34,0x9C35,0x9C36,0x9C37,0x9C38,0x9C39,0x9C3A,
+0x9C3B,0x89E5,0x89EB,0x89EF,0x8A3E,0x8B26,0x9753,0x96E9,
+0x96F3,0x96EF,0x9706,0x9701,0x9708,0x970F,0x970E,0x972A,
+0x972D,0x9730,0x973E,0x9F80,0x9F83,0x9F85,0x9F86,0x9F87,
+0x9F88,0x9F89,0x9F8A,0x9F8C,0x9EFE,0x9F0B,0x9F0D,0x96B9,
+0x96BC,0x96BD,0x96CE,0x96D2,0x77BF,0x96E0,0x928E,0x92AE,
+0x92C8,0x933E,0x936A,0x93CA,0x938F,0x943E,0x946B,0x9C7F,
+0x9C82,0x9C85,0x9C86,0x9C87,0x9C88,0x7A23,0x9C8B,0x9C8E,
+0x9C90,0x9C91,0x9C92,0x9C94,0x9C95,0x9C9A,0x9C9B,0x9C9E,
+0x9C9F,0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA5,0x9CA6,0x9CA7,
+0x9CA8,0x9CA9,0x9CAB,0x9CAD,0x9CAE,0x9CB0,0x9CB1,0x9CB2,
+0x9CB3,0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CBA,0x9CBB,0x9CBC,
+0x9CBD,0x9CC4,0x9CC5,0x9CC6,0x9CC7,0x9CCA,0x9CCB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9C3C,0x9C3D,0x9C3E,0x9C3F,0x9C40,0x9C41,0x9C42,0x9C43,
+0x9C44,0x9C45,0x9C46,0x9C47,0x9C48,0x9C49,0x9C4A,0x9C4B,
+0x9C4C,0x9C4D,0x9C4E,0x9C4F,0x9C50,0x9C51,0x9C52,0x9C53,
+0x9C54,0x9C55,0x9C56,0x9C57,0x9C58,0x9C59,0x9C5A,0x9C5B,
+0x9C5C,0x9C5D,0x9C5E,0x9C5F,0x9C60,0x9C61,0x9C62,0x9C63,
+0x9C64,0x9C65,0x9C66,0x9C67,0x9C68,0x9C69,0x9C6A,0x9C6B,
+0x9C6C,0x9C6D,0x9C6E,0x9C6F,0x9C70,0x9C71,0x9C72,0x9C73,
+0x9C74,0x9C75,0x9C76,0x9C77,0x9C78,0x9C79,0x9C7A, 0,
+0x9C7B,0x9C7D,0x9C7E,0x9C80,0x9C83,0x9C84,0x9C89,0x9C8A,
+0x9C8C,0x9C8F,0x9C93,0x9C96,0x9C97,0x9C98,0x9C99,0x9C9D,
+0x9CAA,0x9CAC,0x9CAF,0x9CB9,0x9CBE,0x9CBF,0x9CC0,0x9CC1,
+0x9CC2,0x9CC8,0x9CC9,0x9CD1,0x9CD2,0x9CDA,0x9CDB,0x9CE0,
+0x9CE1,0x9CCC,0x9CCD,0x9CCE,0x9CCF,0x9CD0,0x9CD3,0x9CD4,
+0x9CD5,0x9CD7,0x9CD8,0x9CD9,0x9CDC,0x9CDD,0x9CDF,0x9CE2,
+0x977C,0x9785,0x9791,0x9792,0x9794,0x97AF,0x97AB,0x97A3,
+0x97B2,0x97B4,0x9AB1,0x9AB0,0x9AB7,0x9E58,0x9AB6,0x9ABA,
+0x9ABC,0x9AC1,0x9AC0,0x9AC5,0x9AC2,0x9ACB,0x9ACC,0x9AD1,
+0x9B45,0x9B43,0x9B47,0x9B49,0x9B48,0x9B4D,0x9B51,0x98E8,
+0x990D,0x992E,0x9955,0x9954,0x9ADF,0x9AE1,0x9AE6,0x9AEF,
+0x9AEB,0x9AFB,0x9AED,0x9AF9,0x9B08,0x9B0F,0x9B13,0x9B1F,
+0x9B23,0x9EBD,0x9EBE,0x7E3B,0x9E82,0x9E87,0x9E88,0x9E8B,
+0x9E92,0x93D6,0x9E9D,0x9E9F,0x9EDB,0x9EDC,0x9EDD,0x9EE0,
+0x9EDF,0x9EE2,0x9EE9,0x9EE7,0x9EE5,0x9EEA,0x9EEF,0x9F22,
+0x9F2C,0x9F2F,0x9F39,0x9F37,0x9F3D,0x9F3E,0x9F44, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9CE3,0x9CE4,0x9CE5,0x9CE6,0x9CE7,0x9CE8,0x9CE9,0x9CEA,
+0x9CEB,0x9CEC,0x9CED,0x9CEE,0x9CEF,0x9CF0,0x9CF1,0x9CF2,
+0x9CF3,0x9CF4,0x9CF5,0x9CF6,0x9CF7,0x9CF8,0x9CF9,0x9CFA,
+0x9CFB,0x9CFC,0x9CFD,0x9CFE,0x9CFF,0x9D00,0x9D01,0x9D02,
+0x9D03,0x9D04,0x9D05,0x9D06,0x9D07,0x9D08,0x9D09,0x9D0A,
+0x9D0B,0x9D0C,0x9D0D,0x9D0E,0x9D0F,0x9D10,0x9D11,0x9D12,
+0x9D13,0x9D14,0x9D15,0x9D16,0x9D17,0x9D18,0x9D19,0x9D1A,
+0x9D1B,0x9D1C,0x9D1D,0x9D1E,0x9D1F,0x9D20,0x9D21, 0,
+0x9D22,0x9D23,0x9D24,0x9D25,0x9D26,0x9D27,0x9D28,0x9D29,
+0x9D2A,0x9D2B,0x9D2C,0x9D2D,0x9D2E,0x9D2F,0x9D30,0x9D31,
+0x9D32,0x9D33,0x9D34,0x9D35,0x9D36,0x9D37,0x9D38,0x9D39,
+0x9D3A,0x9D3B,0x9D3C,0x9D3D,0x9D3E,0x9D3F,0x9D40,0x9D41,
+0x9D42, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9D43,0x9D44,0x9D45,0x9D46,0x9D47,0x9D48,0x9D49,0x9D4A,
+0x9D4B,0x9D4C,0x9D4D,0x9D4E,0x9D4F,0x9D50,0x9D51,0x9D52,
+0x9D53,0x9D54,0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0x9D5A,
+0x9D5B,0x9D5C,0x9D5D,0x9D5E,0x9D5F,0x9D60,0x9D61,0x9D62,
+0x9D63,0x9D64,0x9D65,0x9D66,0x9D67,0x9D68,0x9D69,0x9D6A,
+0x9D6B,0x9D6C,0x9D6D,0x9D6E,0x9D6F,0x9D70,0x9D71,0x9D72,
+0x9D73,0x9D74,0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A,
+0x9D7B,0x9D7C,0x9D7D,0x9D7E,0x9D7F,0x9D80,0x9D81, 0,
+0x9D82,0x9D83,0x9D84,0x9D85,0x9D86,0x9D87,0x9D88,0x9D89,
+0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F,0x9D90,0x9D91,
+0x9D92,0x9D93,0x9D94,0x9D95,0x9D96,0x9D97,0x9D98,0x9D99,
+0x9D9A,0x9D9B,0x9D9C,0x9D9D,0x9D9E,0x9D9F,0x9DA0,0x9DA1,
+0x9DA2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9DA3,0x9DA4,0x9DA5,0x9DA6,0x9DA7,0x9DA8,0x9DA9,0x9DAA,
+0x9DAB,0x9DAC,0x9DAD,0x9DAE,0x9DAF,0x9DB0,0x9DB1,0x9DB2,
+0x9DB3,0x9DB4,0x9DB5,0x9DB6,0x9DB7,0x9DB8,0x9DB9,0x9DBA,
+0x9DBB,0x9DBC,0x9DBD,0x9DBE,0x9DBF,0x9DC0,0x9DC1,0x9DC2,
+0x9DC3,0x9DC4,0x9DC5,0x9DC6,0x9DC7,0x9DC8,0x9DC9,0x9DCA,
+0x9DCB,0x9DCC,0x9DCD,0x9DCE,0x9DCF,0x9DD0,0x9DD1,0x9DD2,
+0x9DD3,0x9DD4,0x9DD5,0x9DD6,0x9DD7,0x9DD8,0x9DD9,0x9DDA,
+0x9DDB,0x9DDC,0x9DDD,0x9DDE,0x9DDF,0x9DE0,0x9DE1, 0,
+0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6,0x9DE7,0x9DE8,0x9DE9,
+0x9DEA,0x9DEB,0x9DEC,0x9DED,0x9DEE,0x9DEF,0x9DF0,0x9DF1,
+0x9DF2,0x9DF3,0x9DF4,0x9DF5,0x9DF6,0x9DF7,0x9DF8,0x9DF9,
+0x9DFA,0x9DFB,0x9DFC,0x9DFD,0x9DFE,0x9DFF,0x9E00,0x9E01,
+0x9E02, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9E03,0x9E04,0x9E05,0x9E06,0x9E07,0x9E08,0x9E09,0x9E0A,
+0x9E0B,0x9E0C,0x9E0D,0x9E0E,0x9E0F,0x9E10,0x9E11,0x9E12,
+0x9E13,0x9E14,0x9E15,0x9E16,0x9E17,0x9E18,0x9E19,0x9E1A,
+0x9E1B,0x9E1C,0x9E1D,0x9E1E,0x9E24,0x9E27,0x9E2E,0x9E30,
+0x9E34,0x9E3B,0x9E3C,0x9E40,0x9E4D,0x9E50,0x9E52,0x9E53,
+0x9E54,0x9E56,0x9E59,0x9E5D,0x9E5F,0x9E60,0x9E61,0x9E62,
+0x9E65,0x9E6E,0x9E6F,0x9E72,0x9E74,0x9E75,0x9E76,0x9E77,
+0x9E78,0x9E79,0x9E7A,0x9E7B,0x9E7C,0x9E7D,0x9E80, 0,
+0x9E81,0x9E83,0x9E84,0x9E85,0x9E86,0x9E89,0x9E8A,0x9E8C,
+0x9E8D,0x9E8E,0x9E8F,0x9E90,0x9E91,0x9E94,0x9E95,0x9E96,
+0x9E97,0x9E98,0x9E99,0x9E9A,0x9E9B,0x9E9C,0x9E9E,0x9EA0,
+0x9EA1,0x9EA2,0x9EA3,0x9EA4,0x9EA5,0x9EA7,0x9EA8,0x9EA9,
+0x9EAA, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9EAB,0x9EAC,0x9EAD,0x9EAE,0x9EAF,0x9EB0,0x9EB1,0x9EB2,
+0x9EB3,0x9EB5,0x9EB6,0x9EB7,0x9EB9,0x9EBA,0x9EBC,0x9EBF,
+0x9EC0,0x9EC1,0x9EC2,0x9EC3,0x9EC5,0x9EC6,0x9EC7,0x9EC8,
+0x9ECA,0x9ECB,0x9ECC,0x9ED0,0x9ED2,0x9ED3,0x9ED5,0x9ED6,
+0x9ED7,0x9ED9,0x9EDA,0x9EDE,0x9EE1,0x9EE3,0x9EE4,0x9EE6,
+0x9EE8,0x9EEB,0x9EEC,0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2,
+0x9EF3,0x9EF4,0x9EF5,0x9EF6,0x9EF7,0x9EF8,0x9EFA,0x9EFD,
+0x9EFF,0x9F00,0x9F01,0x9F02,0x9F03,0x9F04,0x9F05, 0,
+0x9F06,0x9F07,0x9F08,0x9F09,0x9F0A,0x9F0C,0x9F0F,0x9F11,
+0x9F12,0x9F14,0x9F15,0x9F16,0x9F18,0x9F1A,0x9F1B,0x9F1C,
+0x9F1D,0x9F1E,0x9F1F,0x9F21,0x9F23,0x9F24,0x9F25,0x9F26,
+0x9F27,0x9F28,0x9F29,0x9F2A,0x9F2B,0x9F2D,0x9F2E,0x9F30,
+0x9F31, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9F32,0x9F33,0x9F34,0x9F35,0x9F36,0x9F38,0x9F3A,0x9F3C,
+0x9F3F,0x9F40,0x9F41,0x9F42,0x9F43,0x9F45,0x9F46,0x9F47,
+0x9F48,0x9F49,0x9F4A,0x9F4B,0x9F4C,0x9F4D,0x9F4E,0x9F4F,
+0x9F52,0x9F53,0x9F54,0x9F55,0x9F56,0x9F57,0x9F58,0x9F59,
+0x9F5A,0x9F5B,0x9F5C,0x9F5D,0x9F5E,0x9F5F,0x9F60,0x9F61,
+0x9F62,0x9F63,0x9F64,0x9F65,0x9F66,0x9F67,0x9F68,0x9F69,
+0x9F6A,0x9F6B,0x9F6C,0x9F6D,0x9F6E,0x9F6F,0x9F70,0x9F71,
+0x9F72,0x9F73,0x9F74,0x9F75,0x9F76,0x9F77,0x9F78, 0,
+0x9F79,0x9F7A,0x9F7B,0x9F7C,0x9F7D,0x9F7E,0x9F81,0x9F82,
+0x9F8D,0x9F8E,0x9F8F,0x9F90,0x9F91,0x9F92,0x9F93,0x9F94,
+0x9F95,0x9F96,0x9F97,0x9F98,0x9F9C,0x9F9D,0x9F9E,0x9FA1,
+0x9FA2,0x9FA3,0x9FA4,0x9FA5,0xF92C,0xF979,0xF995,0xF9E7,
+0xF9F1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFA0C,0xFA0D,0xFA0E,0xFA0F,0xFA11,0xFA13,0xFA14,0xFA18,
+0xFA1F,0xFA20,0xFA21,0xFA23,0xFA24,0xFA27,0xFA28,0xFA29
+};
+
+static int func_gbk_uni_onechar(int code){
+ if ((code>=0x8140)&&(code<=0xFE4F))
+ return(tab_gbk_uni0[code-0x8140]);
+ return(0);
+}
+
+
+
+/* page 0 0x00A4-0x0451 */
+static uint16 tab_uni_gbk0[]={
+0xA1E8, 0, 0,0xA1EC,0xA1A7, 0, 0, 0,
+ 0, 0, 0, 0,0xA1E3,0xA1C0, 0, 0,
+ 0, 0, 0,0xA1A4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA1C1, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA8A4,0xA8A2, 0, 0,
+ 0, 0, 0, 0,0xA8A8,0xA8A6,0xA8BA, 0,
+0xA8AC,0xA8AA, 0, 0, 0, 0,0xA8B0,0xA8AE,
+ 0, 0, 0,0xA1C2, 0,0xA8B4,0xA8B2, 0,
+0xA8B9, 0, 0, 0, 0,0xA8A1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA8A5,
+ 0, 0, 0, 0, 0, 0, 0,0xA8A7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA8A9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA8BD, 0, 0, 0,0xA8BE, 0, 0, 0,
+ 0,0xA8AD, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA8B1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA8A3, 0,0xA8AB, 0,0xA8AF, 0,
+0xA8B3, 0,0xA8B5, 0,0xA8B6, 0,0xA8B7, 0,
+0xA8B8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA8BB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA8C0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA1A6, 0,0xA1A5,0xA840,0xA841,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA842, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA6A1,0xA6A2,0xA6A3,
+0xA6A4,0xA6A5,0xA6A6,0xA6A7,0xA6A8,0xA6A9,0xA6AA,0xA6AB,
+0xA6AC,0xA6AD,0xA6AE,0xA6AF,0xA6B0,0xA6B1, 0,0xA6B2,
+0xA6B3,0xA6B4,0xA6B5,0xA6B6,0xA6B7,0xA6B8, 0, 0,
+ 0, 0, 0, 0, 0,0xA6C1,0xA6C2,0xA6C3,
+0xA6C4,0xA6C5,0xA6C6,0xA6C7,0xA6C8,0xA6C9,0xA6CA,0xA6CB,
+0xA6CC,0xA6CD,0xA6CE,0xA6CF,0xA6D0,0xA6D1, 0,0xA6D2,
+0xA6D3,0xA6D4,0xA6D5,0xA6D6,0xA6D7,0xA6D8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA7A7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA7A1,0xA7A2,0xA7A3,0xA7A4,
+0xA7A5,0xA7A6,0xA7A8,0xA7A9,0xA7AA,0xA7AB,0xA7AC,0xA7AD,
+0xA7AE,0xA7AF,0xA7B0,0xA7B1,0xA7B2,0xA7B3,0xA7B4,0xA7B5,
+0xA7B6,0xA7B7,0xA7B8,0xA7B9,0xA7BA,0xA7BB,0xA7BC,0xA7BD,
+0xA7BE,0xA7BF,0xA7C0,0xA7C1,0xA7D1,0xA7D2,0xA7D3,0xA7D4,
+0xA7D5,0xA7D6,0xA7D8,0xA7D9,0xA7DA,0xA7DB,0xA7DC,0xA7DD,
+0xA7DE,0xA7DF,0xA7E0,0xA7E1,0xA7E2,0xA7E3,0xA7E4,0xA7E5,
+0xA7E6,0xA7E7,0xA7E8,0xA7E9,0xA7EA,0xA7EB,0xA7EC,0xA7ED,
+0xA7EE,0xA7EF,0xA7F0,0xA7F1, 0,0xA7D7};
+
+/* page 1 0x2010-0x2312 */
+static uint16 tab_uni_gbk1[]={
+0xA95C, 0, 0,0xA843,0xA1AA,0xA844,0xA1AC, 0,
+0xA1AE,0xA1AF, 0, 0,0xA1B0,0xA1B1, 0, 0,
+ 0, 0, 0, 0, 0,0xA845,0xA1AD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1EB, 0,0xA1E4,0xA1E5, 0,0xA846, 0, 0,
+ 0, 0, 0,0xA1F9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA1E6, 0,0xA847, 0, 0,
+ 0,0xA848, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA1ED, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA959, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA2F1,0xA2F2,0xA2F3,0xA2F4,0xA2F5,0xA2F6,0xA2F7,0xA2F8,
+0xA2F9,0xA2FA,0xA2FB,0xA2FC, 0, 0, 0, 0,
+0xA2A1,0xA2A2,0xA2A3,0xA2A4,0xA2A5,0xA2A6,0xA2A7,0xA2A8,
+0xA2A9,0xA2AA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1FB,0xA1FC,0xA1FA,0xA1FD, 0, 0,0xA849,0xA84A,
+0xA84B,0xA84C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1CA, 0, 0, 0, 0, 0, 0,0xA1C7,
+ 0,0xA1C6, 0, 0, 0,0xA84D, 0, 0,
+ 0, 0,0xA1CC, 0, 0,0xA1D8,0xA1DE,0xA84E,
+0xA1CF, 0, 0,0xA84F, 0,0xA1CE, 0,0xA1C4,
+0xA1C5,0xA1C9,0xA1C8,0xA1D2, 0, 0,0xA1D3, 0,
+ 0, 0, 0, 0,0xA1E0,0xA1DF,0xA1C3,0xA1CB,
+ 0, 0, 0, 0, 0,0xA1D7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1D6, 0, 0, 0,0xA1D5, 0, 0, 0,
+ 0, 0,0xA850, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1D9,0xA1D4, 0, 0,0xA1DC,0xA1DD,0xA851,0xA852,
+ 0, 0, 0, 0, 0, 0,0xA1DA,0xA1DB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA892, 0, 0,
+ 0,0xA1D1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1CD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA853,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA1D0};
+
+/* page 2 0x2460-0x2642 */
+static uint16 tab_uni_gbk2[]={
+0xA2D9,0xA2DA,0xA2DB,0xA2DC,0xA2DD,0xA2DE,0xA2DF,0xA2E0,
+0xA2E1,0xA2E2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA2C5,0xA2C6,0xA2C7,0xA2C8,
+0xA2C9,0xA2CA,0xA2CB,0xA2CC,0xA2CD,0xA2CE,0xA2CF,0xA2D0,
+0xA2D1,0xA2D2,0xA2D3,0xA2D4,0xA2D5,0xA2D6,0xA2D7,0xA2D8,
+0xA2B1,0xA2B2,0xA2B3,0xA2B4,0xA2B5,0xA2B6,0xA2B7,0xA2B8,
+0xA2B9,0xA2BA,0xA2BB,0xA2BC,0xA2BD,0xA2BE,0xA2BF,0xA2C0,
+0xA2C1,0xA2C2,0xA2C3,0xA2C4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA9A4,0xA9A5,0xA9A6,0xA9A7,0xA9A8,0xA9A9,0xA9AA,0xA9AB,
+0xA9AC,0xA9AD,0xA9AE,0xA9AF,0xA9B0,0xA9B1,0xA9B2,0xA9B3,
+0xA9B4,0xA9B5,0xA9B6,0xA9B7,0xA9B8,0xA9B9,0xA9BA,0xA9BB,
+0xA9BC,0xA9BD,0xA9BE,0xA9BF,0xA9C0,0xA9C1,0xA9C2,0xA9C3,
+0xA9C4,0xA9C5,0xA9C6,0xA9C7,0xA9C8,0xA9C9,0xA9CA,0xA9CB,
+0xA9CC,0xA9CD,0xA9CE,0xA9CF,0xA9D0,0xA9D1,0xA9D2,0xA9D3,
+0xA9D4,0xA9D5,0xA9D6,0xA9D7,0xA9D8,0xA9D9,0xA9DA,0xA9DB,
+0xA9DC,0xA9DD,0xA9DE,0xA9DF,0xA9E0,0xA9E1,0xA9E2,0xA9E3,
+0xA9E4,0xA9E5,0xA9E6,0xA9E7,0xA9E8,0xA9E9,0xA9EA,0xA9EB,
+0xA9EC,0xA9ED,0xA9EE,0xA9EF, 0, 0, 0, 0,
+0xA854,0xA855,0xA856,0xA857,0xA858,0xA859,0xA85A,0xA85B,
+0xA85C,0xA85D,0xA85E,0xA85F,0xA860,0xA861,0xA862,0xA863,
+0xA864,0xA865,0xA866,0xA867,0xA868,0xA869,0xA86A,0xA86B,
+0xA86C,0xA86D,0xA86E,0xA86F,0xA870,0xA871,0xA872,0xA873,
+0xA874,0xA875,0xA876,0xA877, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA878,0xA879,0xA87A,0xA87B,0xA87C,0xA87D,0xA87E,
+0xA880,0xA881,0xA882,0xA883,0xA884,0xA885,0xA886,0xA887,
+ 0, 0, 0,0xA888,0xA889,0xA88A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1F6,0xA1F5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA1F8,0xA1F7, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xA88B,0xA88C, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA1F4,0xA1F3,
+ 0, 0, 0,0xA1F0, 0, 0,0xA1F2,0xA1F1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA88D,0xA88E,0xA88F,0xA890, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA1EF,0xA1EE, 0,
+ 0,0xA891, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1E2, 0,0xA1E1};
+
+/* page 3 0x3000-0x3129 */
+static uint16 tab_uni_gbk3[]={
+0xA1A1,0xA1A2,0xA1A3,0xA1A8, 0,0xA1A9,0xA965,0xA996,
+0xA1B4,0xA1B5,0xA1B6,0xA1B7,0xA1B8,0xA1B9,0xA1BA,0xA1BB,
+0xA1BE,0xA1BF,0xA893,0xA1FE,0xA1B2,0xA1B3,0xA1BC,0xA1BD,
+ 0, 0, 0, 0, 0,0xA894,0xA895, 0,
+ 0,0xA940,0xA941,0xA942,0xA943,0xA944,0xA945,0xA946,
+0xA947,0xA948, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA4A1,0xA4A2,0xA4A3,0xA4A4,0xA4A5,0xA4A6,0xA4A7,
+0xA4A8,0xA4A9,0xA4AA,0xA4AB,0xA4AC,0xA4AD,0xA4AE,0xA4AF,
+0xA4B0,0xA4B1,0xA4B2,0xA4B3,0xA4B4,0xA4B5,0xA4B6,0xA4B7,
+0xA4B8,0xA4B9,0xA4BA,0xA4BB,0xA4BC,0xA4BD,0xA4BE,0xA4BF,
+0xA4C0,0xA4C1,0xA4C2,0xA4C3,0xA4C4,0xA4C5,0xA4C6,0xA4C7,
+0xA4C8,0xA4C9,0xA4CA,0xA4CB,0xA4CC,0xA4CD,0xA4CE,0xA4CF,
+0xA4D0,0xA4D1,0xA4D2,0xA4D3,0xA4D4,0xA4D5,0xA4D6,0xA4D7,
+0xA4D8,0xA4D9,0xA4DA,0xA4DB,0xA4DC,0xA4DD,0xA4DE,0xA4DF,
+0xA4E0,0xA4E1,0xA4E2,0xA4E3,0xA4E4,0xA4E5,0xA4E6,0xA4E7,
+0xA4E8,0xA4E9,0xA4EA,0xA4EB,0xA4EC,0xA4ED,0xA4EE,0xA4EF,
+0xA4F0,0xA4F1,0xA4F2,0xA4F3, 0, 0, 0, 0,
+ 0, 0, 0,0xA961,0xA962,0xA966,0xA967, 0,
+ 0,0xA5A1,0xA5A2,0xA5A3,0xA5A4,0xA5A5,0xA5A6,0xA5A7,
+0xA5A8,0xA5A9,0xA5AA,0xA5AB,0xA5AC,0xA5AD,0xA5AE,0xA5AF,
+0xA5B0,0xA5B1,0xA5B2,0xA5B3,0xA5B4,0xA5B5,0xA5B6,0xA5B7,
+0xA5B8,0xA5B9,0xA5BA,0xA5BB,0xA5BC,0xA5BD,0xA5BE,0xA5BF,
+0xA5C0,0xA5C1,0xA5C2,0xA5C3,0xA5C4,0xA5C5,0xA5C6,0xA5C7,
+0xA5C8,0xA5C9,0xA5CA,0xA5CB,0xA5CC,0xA5CD,0xA5CE,0xA5CF,
+0xA5D0,0xA5D1,0xA5D2,0xA5D3,0xA5D4,0xA5D5,0xA5D6,0xA5D7,
+0xA5D8,0xA5D9,0xA5DA,0xA5DB,0xA5DC,0xA5DD,0xA5DE,0xA5DF,
+0xA5E0,0xA5E1,0xA5E2,0xA5E3,0xA5E4,0xA5E5,0xA5E6,0xA5E7,
+0xA5E8,0xA5E9,0xA5EA,0xA5EB,0xA5EC,0xA5ED,0xA5EE,0xA5EF,
+0xA5F0,0xA5F1,0xA5F2,0xA5F3,0xA5F4,0xA5F5,0xA5F6, 0,
+ 0, 0, 0, 0,0xA960,0xA963,0xA964, 0,
+ 0, 0, 0, 0, 0,0xA8C5,0xA8C6,0xA8C7,
+0xA8C8,0xA8C9,0xA8CA,0xA8CB,0xA8CC,0xA8CD,0xA8CE,0xA8CF,
+0xA8D0,0xA8D1,0xA8D2,0xA8D3,0xA8D4,0xA8D5,0xA8D6,0xA8D7,
+0xA8D8,0xA8D9,0xA8DA,0xA8DB,0xA8DC,0xA8DD,0xA8DE,0xA8DF,
+0xA8E0,0xA8E1,0xA8E2,0xA8E3,0xA8E4,0xA8E5,0xA8E6,0xA8E7,
+0xA8E8,0xA8E9};
+
+/* page 4 0x3220-0x32A3 */
+static uint16 tab_uni_gbk4[]={
+0xA2E5,0xA2E6,0xA2E7,0xA2E8,0xA2E9,0xA2EA,0xA2EB,0xA2EC,
+0xA2ED,0xA2EE, 0, 0, 0, 0, 0, 0,
+ 0,0xA95A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xA949};
+
+/* page 5 0x338E-0x33D5 */
+static uint16 tab_uni_gbk5[]={
+0xA94A,0xA94B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA94C,0xA94D,
+0xA94E, 0, 0,0xA94F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA950, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA951, 0, 0,0xA952,0xA953, 0, 0,0xA954
+};
+
+/* page 6 0x4E00-0x9FA5 */
+static uint16 tab_uni_gbk6[]={
+0xD2BB,0xB6A1,0x8140,0xC6DF,0x8141,0x8142,0x8143,0xCDF2,
+0xD5C9,0xC8FD,0xC9CF,0xCFC2,0xD8A2,0xB2BB,0xD3EB,0x8144,
+0xD8A4,0xB3F3,0x8145,0xD7A8,0xC7D2,0xD8A7,0xCAC0,0x8146,
+0xC7F0,0xB1FB,0xD2B5,0xB4D4,0xB6AB,0xCBBF,0xD8A9,0x8147,
+0x8148,0x8149,0xB6AA,0x814A,0xC1BD,0xD1CF,0x814B,0xC9A5,
+0xD8AD,0x814C,0xB8F6,0xD1BE,0xE3DC,0xD6D0,0x814D,0x814E,
+0xB7E1,0x814F,0xB4AE,0x8150,0xC1D9,0x8151,0xD8BC,0x8152,
+0xCDE8,0xB5A4,0xCEAA,0xD6F7,0x8153,0xC0F6,0xBED9,0xD8AF,
+0x8154,0x8155,0x8156,0xC4CB,0x8157,0xBEC3,0x8158,0xD8B1,
+0xC3B4,0xD2E5,0x8159,0xD6AE,0xCEDA,0xD5A7,0xBAF5,0xB7A6,
+0xC0D6,0x815A,0xC6B9,0xC5D2,0xC7C7,0x815B,0xB9D4,0x815C,
+0xB3CB,0xD2D2,0x815D,0x815E,0xD8BF,0xBEC5,0xC6F2,0xD2B2,
+0xCFB0,0xCFE7,0x815F,0x8160,0x8161,0x8162,0xCAE9,0x8163,
+0x8164,0xD8C0,0x8165,0x8166,0x8167,0x8168,0x8169,0x816A,
+0xC2F2,0xC2D2,0x816B,0xC8E9,0x816C,0x816D,0x816E,0x816F,
+0x8170,0x8171,0x8172,0x8173,0x8174,0x8175,0xC7AC,0x8176,
+0x8177,0x8178,0x8179,0x817A,0x817B,0x817C,0xC1CB,0x817D,
+0xD3E8,0xD5F9,0x817E,0xCAC2,0xB6FE,0xD8A1,0xD3DA,0xBFF7,
+0x8180,0xD4C6,0xBBA5,0xD8C1,0xCEE5,0xBEAE,0x8181,0x8182,
+0xD8A8,0x8183,0xD1C7,0xD0A9,0x8184,0x8185,0x8186,0xD8BD,
+0xD9EF,0xCDF6,0xBFBA,0x8187,0xBDBB,0xBAA5,0xD2E0,0xB2FA,
+0xBAE0,0xC4B6,0x8188,0xCFED,0xBEA9,0xCDA4,0xC1C1,0x8189,
+0x818A,0x818B,0xC7D7,0xD9F1,0x818C,0xD9F4,0x818D,0x818E,
+0x818F,0x8190,0xC8CB,0xD8E9,0x8191,0x8192,0x8193,0xD2DA,
+0xCAB2,0xC8CA,0xD8EC,0xD8EA,0xD8C6,0xBDF6,0xC6CD,0xB3F0,
+0x8194,0xD8EB,0xBDF1,0xBDE9,0x8195,0xC8D4,0xB4D3,0x8196,
+0x8197,0xC2D8,0x8198,0xB2D6,0xD7D0,0xCACB,0xCBFB,0xD5CC,
+0xB8B6,0xCFC9,0x8199,0x819A,0x819B,0xD9DA,0xD8F0,0xC7AA,
+0x819C,0xD8EE,0x819D,0xB4FA,0xC1EE,0xD2D4,0x819E,0x819F,
+0xD8ED,0x81A0,0xD2C7,0xD8EF,0xC3C7,0x81A1,0x81A2,0x81A3,
+0xD1F6,0x81A4,0xD6D9,0xD8F2,0x81A5,0xD8F5,0xBCFE,0xBCDB,
+0x81A6,0x81A7,0x81A8,0xC8CE,0x81A9,0xB7DD,0x81AA,0xB7C2,
+0x81AB,0xC6F3,0x81AC,0x81AD,0x81AE,0x81AF,0x81B0,0x81B1,
+0x81B2,0xD8F8,0xD2C1,0x81B3,0x81B4,0xCEE9,0xBCBF,0xB7FC,
+0xB7A5,0xD0DD,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9,0xD6DA,
+0xD3C5,0xBBEF,0xBBE1,0xD8F1,0x81BA,0x81BB,0xC9A1,0xCEB0,
+0xB4AB,0x81BC,0xD8F3,0x81BD,0xC9CB,0xD8F6,0xC2D7,0xD8F7,
+0x81BE,0x81BF,0xCEB1,0xD8F9,0x81C0,0x81C1,0x81C2,0xB2AE,
+0xB9C0,0x81C3,0xD9A3,0x81C4,0xB0E9,0x81C5,0xC1E6,0x81C6,
+0xC9EC,0x81C7,0xCBC5,0x81C8,0xCBC6,0xD9A4,0x81C9,0x81CA,
+0x81CB,0x81CC,0x81CD,0xB5E8,0x81CE,0x81CF,0xB5AB,0x81D0,
+0x81D1,0x81D2,0x81D3,0x81D4,0x81D5,0xCEBB,0xB5CD,0xD7A1,
+0xD7F4,0xD3D3,0x81D6,0xCCE5,0x81D7,0xBACE,0x81D8,0xD9A2,
+0xD9DC,0xD3E0,0xD8FD,0xB7F0,0xD7F7,0xD8FE,0xD8FA,0xD9A1,
+0xC4E3,0x81D9,0x81DA,0xD3B6,0xD8F4,0xD9DD,0x81DB,0xD8FB,
+0x81DC,0xC5E5,0x81DD,0x81DE,0xC0D0,0x81DF,0x81E0,0xD1F0,
+0xB0DB,0x81E1,0x81E2,0xBCD1,0xD9A6,0x81E3,0xD9A5,0x81E4,
+0x81E5,0x81E6,0x81E7,0xD9AC,0xD9AE,0x81E8,0xD9AB,0xCAB9,
+0x81E9,0x81EA,0x81EB,0xD9A9,0xD6B6,0x81EC,0x81ED,0x81EE,
+0xB3DE,0xD9A8,0x81EF,0xC0FD,0x81F0,0xCACC,0x81F1,0xD9AA,
+0x81F2,0xD9A7,0x81F3,0x81F4,0xD9B0,0x81F5,0x81F6,0xB6B1,
+0x81F7,0x81F8,0x81F9,0xB9A9,0x81FA,0xD2C0,0x81FB,0x81FC,
+0xCFC0,0x81FD,0x81FE,0xC2C2,0x8240,0xBDC4,0xD5EC,0xB2E0,
+0xC7C8,0xBFEB,0xD9AD,0x8241,0xD9AF,0x8242,0xCEEA,0xBAEE,
+0x8243,0x8244,0x8245,0x8246,0x8247,0xC7D6,0x8248,0x8249,
+0x824A,0x824B,0x824C,0x824D,0x824E,0x824F,0x8250,0xB1E3,
+0x8251,0x8252,0x8253,0xB4D9,0xB6ED,0xD9B4,0x8254,0x8255,
+0x8256,0x8257,0xBFA1,0x8258,0x8259,0x825A,0xD9DE,0xC7CE,
+0xC0FE,0xD9B8,0x825B,0x825C,0x825D,0x825E,0x825F,0xCBD7,
+0xB7FD,0x8260,0xD9B5,0x8261,0xD9B7,0xB1A3,0xD3E1,0xD9B9,
+0x8262,0xD0C5,0x8263,0xD9B6,0x8264,0x8265,0xD9B1,0x8266,
+0xD9B2,0xC1A9,0xD9B3,0x8267,0x8268,0xBCF3,0xD0DE,0xB8A9,
+0x8269,0xBEE3,0x826A,0xD9BD,0x826B,0x826C,0x826D,0x826E,
+0xD9BA,0x826F,0xB0B3,0x8270,0x8271,0x8272,0xD9C2,0x8273,
+0x8274,0x8275,0x8276,0x8277,0x8278,0x8279,0x827A,0x827B,
+0x827C,0x827D,0x827E,0x8280,0xD9C4,0xB1B6,0x8281,0xD9BF,
+0x8282,0x8283,0xB5B9,0x8284,0xBEF3,0x8285,0x8286,0x8287,
+0xCCC8,0xBAF2,0xD2D0,0x8288,0xD9C3,0x8289,0x828A,0xBDE8,
+0x828B,0xB3AB,0x828C,0x828D,0x828E,0xD9C5,0xBEEB,0x828F,
+0xD9C6,0xD9BB,0xC4DF,0x8290,0xD9BE,0xD9C1,0xD9C0,0x8291,
+0x8292,0x8293,0x8294,0x8295,0x8296,0x8297,0x8298,0x8299,
+0x829A,0x829B,0xD5AE,0x829C,0xD6B5,0x829D,0xC7E3,0x829E,
+0x829F,0x82A0,0x82A1,0xD9C8,0x82A2,0x82A3,0x82A4,0xBCD9,
+0xD9CA,0x82A5,0x82A6,0x82A7,0xD9BC,0x82A8,0xD9CB,0xC6AB,
+0x82A9,0x82AA,0x82AB,0x82AC,0x82AD,0xD9C9,0x82AE,0x82AF,
+0x82B0,0x82B1,0xD7F6,0x82B2,0xCDA3,0x82B3,0x82B4,0x82B5,
+0x82B6,0x82B7,0x82B8,0x82B9,0x82BA,0xBDA1,0x82BB,0x82BC,
+0x82BD,0x82BE,0x82BF,0x82C0,0xD9CC,0x82C1,0x82C2,0x82C3,
+0x82C4,0x82C5,0x82C6,0x82C7,0x82C8,0x82C9,0xC5BC,0xCDB5,
+0x82CA,0x82CB,0x82CC,0xD9CD,0x82CD,0x82CE,0xD9C7,0xB3A5,
+0xBFFE,0x82CF,0x82D0,0x82D1,0x82D2,0xB8B5,0x82D3,0x82D4,
+0xC0FC,0x82D5,0x82D6,0x82D7,0x82D8,0xB0F8,0x82D9,0x82DA,
+0x82DB,0x82DC,0x82DD,0x82DE,0x82DF,0x82E0,0x82E1,0x82E2,
+0x82E3,0x82E4,0x82E5,0x82E6,0x82E7,0x82E8,0x82E9,0x82EA,
+0x82EB,0x82EC,0x82ED,0xB4F6,0x82EE,0xD9CE,0x82EF,0xD9CF,
+0xB4A2,0xD9D0,0x82F0,0x82F1,0xB4DF,0x82F2,0x82F3,0x82F4,
+0x82F5,0x82F6,0xB0C1,0x82F7,0x82F8,0x82F9,0x82FA,0x82FB,
+0x82FC,0x82FD,0xD9D1,0xC9B5,0x82FE,0x8340,0x8341,0x8342,
+0x8343,0x8344,0x8345,0x8346,0x8347,0x8348,0x8349,0x834A,
+0x834B,0x834C,0x834D,0x834E,0x834F,0x8350,0x8351,0xCFF1,
+0x8352,0x8353,0x8354,0x8355,0x8356,0x8357,0xD9D2,0x8358,
+0x8359,0x835A,0xC1C5,0x835B,0x835C,0x835D,0x835E,0x835F,
+0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0xD9D6,0xC9AE,
+0x8366,0x8367,0x8368,0x8369,0xD9D5,0xD9D4,0xD9D7,0x836A,
+0x836B,0x836C,0x836D,0xCBDB,0x836E,0xBDA9,0x836F,0x8370,
+0x8371,0x8372,0x8373,0xC6A7,0x8374,0x8375,0x8376,0x8377,
+0x8378,0x8379,0x837A,0x837B,0x837C,0x837D,0xD9D3,0xD9D8,
+0x837E,0x8380,0x8381,0xD9D9,0x8382,0x8383,0x8384,0x8385,
+0x8386,0x8387,0xC8E5,0x8388,0x8389,0x838A,0x838B,0x838C,
+0x838D,0x838E,0x838F,0x8390,0x8391,0x8392,0x8393,0x8394,
+0x8395,0xC0DC,0x8396,0x8397,0x8398,0x8399,0x839A,0x839B,
+0x839C,0x839D,0x839E,0x839F,0x83A0,0x83A1,0x83A2,0x83A3,
+0x83A4,0x83A5,0x83A6,0x83A7,0x83A8,0x83A9,0x83AA,0x83AB,
+0x83AC,0x83AD,0x83AE,0x83AF,0x83B0,0x83B1,0x83B2,0xB6F9,
+0xD8A3,0xD4CA,0x83B3,0xD4AA,0xD0D6,0xB3E4,0xD5D7,0x83B4,
+0xCFC8,0xB9E2,0x83B5,0xBFCB,0x83B6,0xC3E2,0x83B7,0x83B8,
+0x83B9,0xB6D2,0x83BA,0x83BB,0xCDC3,0xD9EE,0xD9F0,0x83BC,
+0x83BD,0x83BE,0xB5B3,0x83BF,0xB6B5,0x83C0,0x83C1,0x83C2,
+0x83C3,0x83C4,0xBEA4,0x83C5,0x83C6,0xC8EB,0x83C7,0x83C8,
+0xC8AB,0x83C9,0x83CA,0xB0CB,0xB9AB,0xC1F9,0xD9E2,0x83CB,
+0xC0BC,0xB9B2,0x83CC,0xB9D8,0xD0CB,0xB1F8,0xC6E4,0xBEDF,
+0xB5E4,0xD7C8,0x83CD,0xD1F8,0xBCE6,0xCADE,0x83CE,0x83CF,
+0xBCBD,0xD9E6,0xD8E7,0x83D0,0x83D1,0xC4DA,0x83D2,0x83D3,
+0xB8D4,0xC8BD,0x83D4,0x83D5,0xB2E1,0xD4D9,0x83D6,0x83D7,
+0x83D8,0x83D9,0xC3B0,0x83DA,0x83DB,0xC3E1,0xDAA2,0xC8DF,
+0x83DC,0xD0B4,0x83DD,0xBEFC,0xC5A9,0x83DE,0x83DF,0x83E0,
+0xB9DA,0x83E1,0xDAA3,0x83E2,0xD4A9,0xDAA4,0x83E3,0x83E4,
+0x83E5,0x83E6,0x83E7,0xD9FB,0xB6AC,0x83E8,0x83E9,0xB7EB,
+0xB1F9,0xD9FC,0xB3E5,0xBEF6,0x83EA,0xBFF6,0xD2B1,0xC0E4,
+0x83EB,0x83EC,0x83ED,0xB6B3,0xD9FE,0xD9FD,0x83EE,0x83EF,
+0xBEBB,0x83F0,0x83F1,0x83F2,0xC6E0,0x83F3,0xD7BC,0xDAA1,
+0x83F4,0xC1B9,0x83F5,0xB5F2,0xC1E8,0x83F6,0x83F7,0xBCF5,
+0x83F8,0xB4D5,0x83F9,0x83FA,0x83FB,0x83FC,0x83FD,0x83FE,
+0x8440,0x8441,0x8442,0xC1DD,0x8443,0xC4FD,0x8444,0x8445,
+0xBCB8,0xB7B2,0x8446,0x8447,0xB7EF,0x8448,0x8449,0x844A,
+0x844B,0x844C,0x844D,0xD9EC,0x844E,0xC6BE,0x844F,0xBFAD,
+0xBBCB,0x8450,0x8451,0xB5CA,0x8452,0xDBC9,0xD0D7,0x8453,
+0xCDB9,0xB0BC,0xB3F6,0xBBF7,0xDBCA,0xBAAF,0x8454,0xD4E4,
+0xB5B6,0xB5F3,0xD8D6,0xC8D0,0x8455,0x8456,0xB7D6,0xC7D0,
+0xD8D7,0x8457,0xBFAF,0x8458,0x8459,0xDBBB,0xD8D8,0x845A,
+0x845B,0xD0CC,0xBBAE,0x845C,0x845D,0x845E,0xEBBE,0xC1D0,
+0xC1F5,0xD4F2,0xB8D5,0xB4B4,0x845F,0xB3F5,0x8460,0x8461,
+0xC9BE,0x8462,0x8463,0x8464,0xC5D0,0x8465,0x8466,0x8467,
+0xC5D9,0xC0FB,0x8468,0xB1F0,0x8469,0xD8D9,0xB9CE,0x846A,
+0xB5BD,0x846B,0x846C,0xD8DA,0x846D,0x846E,0xD6C6,0xCBA2,
+0xC8AF,0xC9B2,0xB4CC,0xBFCC,0x846F,0xB9F4,0x8470,0xD8DB,
+0xD8DC,0xB6E7,0xBCC1,0xCCEA,0x8471,0x8472,0x8473,0x8474,
+0x8475,0x8476,0xCFF7,0x8477,0xD8DD,0xC7B0,0x8478,0x8479,
+0xB9D0,0xBDA3,0x847A,0x847B,0xCCDE,0x847C,0xC6CA,0x847D,
+0x847E,0x8480,0x8481,0x8482,0xD8E0,0x8483,0xD8DE,0x8484,
+0x8485,0xD8DF,0x8486,0x8487,0x8488,0xB0FE,0x8489,0xBEE7,
+0x848A,0xCAA3,0xBCF4,0x848B,0x848C,0x848D,0x848E,0xB8B1,
+0x848F,0x8490,0xB8EE,0x8491,0x8492,0x8493,0x8494,0x8495,
+0x8496,0x8497,0x8498,0x8499,0x849A,0xD8E2,0x849B,0xBDCB,
+0x849C,0xD8E4,0xD8E3,0x849D,0x849E,0x849F,0x84A0,0x84A1,
+0xC5FC,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,0x84A7,0x84A8,
+0xD8E5,0x84A9,0x84AA,0xD8E6,0x84AB,0x84AC,0x84AD,0x84AE,
+0x84AF,0x84B0,0x84B1,0xC1A6,0x84B2,0xC8B0,0xB0EC,0xB9A6,
+0xBCD3,0xCEF1,0xDBBD,0xC1D3,0x84B3,0x84B4,0x84B5,0x84B6,
+0xB6AF,0xD6FA,0xC5AC,0xBDD9,0xDBBE,0xDBBF,0x84B7,0x84B8,
+0x84B9,0xC0F8,0xBEA2,0xC0CD,0x84BA,0x84BB,0x84BC,0x84BD,
+0x84BE,0x84BF,0x84C0,0x84C1,0x84C2,0x84C3,0xDBC0,0xCAC6,
+0x84C4,0x84C5,0x84C6,0xB2AA,0x84C7,0x84C8,0x84C9,0xD3C2,
+0x84CA,0xC3E3,0x84CB,0xD1AB,0x84CC,0x84CD,0x84CE,0x84CF,
+0xDBC2,0x84D0,0xC0D5,0x84D1,0x84D2,0x84D3,0xDBC3,0x84D4,
+0xBFB1,0x84D5,0x84D6,0x84D7,0x84D8,0x84D9,0x84DA,0xC4BC,
+0x84DB,0x84DC,0x84DD,0x84DE,0xC7DA,0x84DF,0x84E0,0x84E1,
+0x84E2,0x84E3,0x84E4,0x84E5,0x84E6,0x84E7,0x84E8,0x84E9,
+0xDBC4,0x84EA,0x84EB,0x84EC,0x84ED,0x84EE,0x84EF,0x84F0,
+0x84F1,0xD9E8,0xC9D7,0x84F2,0x84F3,0x84F4,0xB9B4,0xCEF0,
+0xD4C8,0x84F5,0x84F6,0x84F7,0x84F8,0xB0FC,0xB4D2,0x84F9,
+0xD0D9,0x84FA,0x84FB,0x84FC,0x84FD,0xD9E9,0x84FE,0xDECB,
+0xD9EB,0x8540,0x8541,0x8542,0x8543,0xD8B0,0xBBAF,0xB1B1,
+0x8544,0xB3D7,0xD8CE,0x8545,0x8546,0xD4D1,0x8547,0x8548,
+0xBDB3,0xBFEF,0x8549,0xCFBB,0x854A,0x854B,0xD8D0,0x854C,
+0x854D,0x854E,0xB7CB,0x854F,0x8550,0x8551,0xD8D1,0x8552,
+0x8553,0x8554,0x8555,0x8556,0x8557,0x8558,0x8559,0x855A,
+0x855B,0xC6A5,0xC7F8,0xD2BD,0x855C,0x855D,0xD8D2,0xC4E4,
+0x855E,0xCAAE,0x855F,0xC7A7,0x8560,0xD8A6,0x8561,0xC9FD,
+0xCEE7,0xBBDC,0xB0EB,0x8562,0x8563,0x8564,0xBBAA,0xD0AD,
+0x8565,0xB1B0,0xD7E4,0xD7BF,0x8566,0xB5A5,0xC2F4,0xC4CF,
+0x8567,0x8568,0xB2A9,0x8569,0xB2B7,0x856A,0xB1E5,0xDFB2,
+0xD5BC,0xBFA8,0xC2AC,0xD8D5,0xC2B1,0x856B,0xD8D4,0xCED4,
+0x856C,0xDAE0,0x856D,0xCEC0,0x856E,0x856F,0xD8B4,0xC3AE,
+0xD3A1,0xCEA3,0x8570,0xBCB4,0xC8B4,0xC2D1,0x8571,0xBEED,
+0xD0B6,0x8572,0xDAE1,0x8573,0x8574,0x8575,0x8576,0xC7E4,
+0x8577,0x8578,0xB3A7,0x8579,0xB6F2,0xCCFC,0xC0FA,0x857A,
+0x857B,0xC0F7,0x857C,0xD1B9,0xD1E1,0xD8C7,0x857D,0x857E,
+0x8580,0x8581,0x8582,0x8583,0x8584,0xB2DE,0x8585,0x8586,
+0xC0E5,0x8587,0xBAF1,0x8588,0x8589,0xD8C8,0x858A,0xD4AD,
+0x858B,0x858C,0xCFE1,0xD8C9,0x858D,0xD8CA,0xCFC3,0x858E,
+0xB3F8,0xBEC7,0x858F,0x8590,0x8591,0x8592,0xD8CB,0x8593,
+0x8594,0x8595,0x8596,0x8597,0x8598,0x8599,0xDBCC,0x859A,
+0x859B,0x859C,0x859D,0xC8A5,0x859E,0x859F,0x85A0,0xCFD8,
+0x85A1,0xC8FE,0xB2CE,0x85A2,0x85A3,0x85A4,0x85A5,0x85A6,
+0xD3D6,0xB2E6,0xBCB0,0xD3D1,0xCBAB,0xB7B4,0x85A7,0x85A8,
+0x85A9,0xB7A2,0x85AA,0x85AB,0xCAE5,0x85AC,0xC8A1,0xCADC,
+0xB1E4,0xD0F0,0x85AD,0xC5D1,0x85AE,0x85AF,0x85B0,0xDBC5,
+0xB5FE,0x85B1,0x85B2,0xBFDA,0xB9C5,0xBEE4,0xC1ED,0x85B3,
+0xDFB6,0xDFB5,0xD6BB,0xBDD0,0xD5D9,0xB0C8,0xB6A3,0xBFC9,
+0xCCA8,0xDFB3,0xCAB7,0xD3D2,0x85B4,0xD8CF,0xD2B6,0xBAC5,
+0xCBBE,0xCCBE,0x85B5,0xDFB7,0xB5F0,0xDFB4,0x85B6,0x85B7,
+0x85B8,0xD3F5,0x85B9,0xB3D4,0xB8F7,0x85BA,0xDFBA,0x85BB,
+0xBACF,0xBCAA,0xB5F5,0x85BC,0xCDAC,0xC3FB,0xBAF3,0xC0F4,
+0xCDC2,0xCFF2,0xDFB8,0xCFC5,0x85BD,0xC2C0,0xDFB9,0xC2F0,
+0x85BE,0x85BF,0x85C0,0xBEFD,0x85C1,0xC1DF,0xCDCC,0xD2F7,
+0xB7CD,0xDFC1,0x85C2,0xDFC4,0x85C3,0x85C4,0xB7F1,0xB0C9,
+0xB6D6,0xB7D4,0x85C5,0xBAAC,0xCCFD,0xBFD4,0xCBB1,0xC6F4,
+0x85C6,0xD6A8,0xDFC5,0x85C7,0xCEE2,0xB3B3,0x85C8,0x85C9,
+0xCEFC,0xB4B5,0x85CA,0xCEC7,0xBAF0,0x85CB,0xCEE1,0x85CC,
+0xD1BD,0x85CD,0x85CE,0xDFC0,0x85CF,0x85D0,0xB4F4,0x85D1,
+0xB3CA,0x85D2,0xB8E6,0xDFBB,0x85D3,0x85D4,0x85D5,0x85D6,
+0xC4C5,0x85D7,0xDFBC,0xDFBD,0xDFBE,0xC5BB,0xDFBF,0xDFC2,
+0xD4B1,0xDFC3,0x85D8,0xC7BA,0xCED8,0x85D9,0x85DA,0x85DB,
+0x85DC,0x85DD,0xC4D8,0x85DE,0xDFCA,0x85DF,0xDFCF,0x85E0,
+0xD6DC,0x85E1,0x85E2,0x85E3,0x85E4,0x85E5,0x85E6,0x85E7,
+0x85E8,0xDFC9,0xDFDA,0xCEB6,0x85E9,0xBAC7,0xDFCE,0xDFC8,
+0xC5DE,0x85EA,0x85EB,0xC9EB,0xBAF4,0xC3FC,0x85EC,0x85ED,
+0xBED7,0x85EE,0xDFC6,0x85EF,0xDFCD,0x85F0,0xC5D8,0x85F1,
+0x85F2,0x85F3,0x85F4,0xD5A6,0xBACD,0x85F5,0xBECC,0xD3BD,
+0xB8C0,0x85F6,0xD6E4,0x85F7,0xDFC7,0xB9BE,0xBFA7,0x85F8,
+0x85F9,0xC1FC,0xDFCB,0xDFCC,0x85FA,0xDFD0,0x85FB,0x85FC,
+0x85FD,0x85FE,0x8640,0xDFDB,0xDFE5,0x8641,0xDFD7,0xDFD6,
+0xD7C9,0xDFE3,0xDFE4,0xE5EB,0xD2A7,0xDFD2,0x8642,0xBFA9,
+0x8643,0xD4DB,0x8644,0xBFC8,0xDFD4,0x8645,0x8646,0x8647,
+0xCFCC,0x8648,0x8649,0xDFDD,0x864A,0xD1CA,0x864B,0xDFDE,
+0xB0A7,0xC6B7,0xDFD3,0x864C,0xBAE5,0x864D,0xB6DF,0xCDDB,
+0xB9FE,0xD4D5,0x864E,0x864F,0xDFDF,0xCFEC,0xB0A5,0xDFE7,
+0xDFD1,0xD1C6,0xDFD5,0xDFD8,0xDFD9,0xDFDC,0x8650,0xBBA9,
+0x8651,0xDFE0,0xDFE1,0x8652,0xDFE2,0xDFE6,0xDFE8,0xD3B4,
+0x8653,0x8654,0x8655,0x8656,0x8657,0xB8E7,0xC5B6,0xDFEA,
+0xC9DA,0xC1A8,0xC4C4,0x8658,0x8659,0xBFDE,0xCFF8,0x865A,
+0x865B,0x865C,0xD5DC,0xDFEE,0x865D,0x865E,0x865F,0x8660,
+0x8661,0x8662,0xB2B8,0x8663,0xBADF,0xDFEC,0x8664,0xDBC1,
+0x8665,0xD1E4,0x8666,0x8667,0x8668,0x8669,0xCBF4,0xB4BD,
+0x866A,0xB0A6,0x866B,0x866C,0x866D,0x866E,0x866F,0xDFF1,
+0xCCC6,0xDFF2,0x8670,0x8671,0xDFED,0x8672,0x8673,0x8674,
+0x8675,0x8676,0x8677,0xDFE9,0x8678,0x8679,0x867A,0x867B,
+0xDFEB,0x867C,0xDFEF,0xDFF0,0xBBBD,0x867D,0x867E,0xDFF3,
+0x8680,0x8681,0xDFF4,0x8682,0xBBA3,0x8683,0xCADB,0xCEA8,
+0xE0A7,0xB3AA,0x8684,0xE0A6,0x8685,0x8686,0x8687,0xE0A1,
+0x8688,0x8689,0x868A,0x868B,0xDFFE,0x868C,0xCDD9,0xDFFC,
+0x868D,0xDFFA,0x868E,0xBFD0,0xD7C4,0x868F,0xC9CC,0x8690,
+0x8691,0xDFF8,0xB0A1,0x8692,0x8693,0x8694,0x8695,0x8696,
+0xDFFD,0x8697,0x8698,0x8699,0x869A,0xDFFB,0xE0A2,0x869B,
+0x869C,0x869D,0x869E,0x869F,0xE0A8,0x86A0,0x86A1,0x86A2,
+0x86A3,0xB7C8,0x86A4,0x86A5,0xC6A1,0xC9B6,0xC0B2,0xDFF5,
+0x86A6,0x86A7,0xC5BE,0x86A8,0xD8C4,0xDFF9,0xC4F6,0x86A9,
+0x86AA,0x86AB,0x86AC,0x86AD,0x86AE,0xE0A3,0xE0A4,0xE0A5,
+0xD0A5,0x86AF,0x86B0,0xE0B4,0xCCE4,0x86B1,0xE0B1,0x86B2,
+0xBFA6,0xE0AF,0xCEB9,0xE0AB,0xC9C6,0x86B3,0x86B4,0xC0AE,
+0xE0AE,0xBAED,0xBAB0,0xE0A9,0x86B5,0x86B6,0x86B7,0xDFF6,
+0x86B8,0xE0B3,0x86B9,0x86BA,0xE0B8,0x86BB,0x86BC,0x86BD,
+0xB4AD,0xE0B9,0x86BE,0x86BF,0xCFB2,0xBAC8,0x86C0,0xE0B0,
+0x86C1,0x86C2,0x86C3,0x86C4,0x86C5,0x86C6,0x86C7,0xD0FA,
+0x86C8,0x86C9,0x86CA,0x86CB,0x86CC,0x86CD,0x86CE,0x86CF,
+0x86D0,0xE0AC,0x86D1,0xD4FB,0x86D2,0xDFF7,0x86D3,0xC5E7,
+0x86D4,0xE0AD,0x86D5,0xD3F7,0x86D6,0xE0B6,0xE0B7,0x86D7,
+0x86D8,0x86D9,0x86DA,0x86DB,0xE0C4,0xD0E1,0x86DC,0x86DD,
+0x86DE,0xE0BC,0x86DF,0x86E0,0xE0C9,0xE0CA,0x86E1,0x86E2,
+0x86E3,0xE0BE,0xE0AA,0xC9A4,0xE0C1,0x86E4,0xE0B2,0x86E5,
+0x86E6,0x86E7,0x86E8,0x86E9,0xCAC8,0xE0C3,0x86EA,0xE0B5,
+0x86EB,0xCECB,0x86EC,0xCBC3,0xE0CD,0xE0C6,0xE0C2,0x86ED,
+0xE0CB,0x86EE,0xE0BA,0xE0BF,0xE0C0,0x86EF,0x86F0,0xE0C5,
+0x86F1,0x86F2,0xE0C7,0xE0C8,0x86F3,0xE0CC,0x86F4,0xE0BB,
+0x86F5,0x86F6,0x86F7,0x86F8,0x86F9,0xCBD4,0xE0D5,0x86FA,
+0xE0D6,0xE0D2,0x86FB,0x86FC,0x86FD,0x86FE,0x8740,0x8741,
+0xE0D0,0xBCCE,0x8742,0x8743,0xE0D1,0x8744,0xB8C2,0xD8C5,
+0x8745,0x8746,0x8747,0x8748,0x8749,0x874A,0x874B,0x874C,
+0xD0EA,0x874D,0x874E,0xC2EF,0x874F,0x8750,0xE0CF,0xE0BD,
+0x8751,0x8752,0x8753,0xE0D4,0xE0D3,0x8754,0x8755,0xE0D7,
+0x8756,0x8757,0x8758,0x8759,0xE0DC,0xE0D8,0x875A,0x875B,
+0x875C,0xD6F6,0xB3B0,0x875D,0xD7EC,0x875E,0xCBBB,0x875F,
+0x8760,0xE0DA,0x8761,0xCEFB,0x8762,0x8763,0x8764,0xBAD9,
+0x8765,0x8766,0x8767,0x8768,0x8769,0x876A,0x876B,0x876C,
+0x876D,0x876E,0x876F,0x8770,0xE0E1,0xE0DD,0xD2AD,0x8771,
+0x8772,0x8773,0x8774,0x8775,0xE0E2,0x8776,0x8777,0xE0DB,
+0xE0D9,0xE0DF,0x8778,0x8779,0xE0E0,0x877A,0x877B,0x877C,
+0x877D,0x877E,0xE0DE,0x8780,0xE0E4,0x8781,0x8782,0x8783,
+0xC6F7,0xD8AC,0xD4EB,0xE0E6,0xCAC9,0x8784,0x8785,0x8786,
+0x8787,0xE0E5,0x8788,0x8789,0x878A,0x878B,0xB8C1,0x878C,
+0x878D,0x878E,0x878F,0xE0E7,0xE0E8,0x8790,0x8791,0x8792,
+0x8793,0x8794,0x8795,0x8796,0x8797,0xE0E9,0xE0E3,0x8798,
+0x8799,0x879A,0x879B,0x879C,0x879D,0x879E,0xBABF,0xCCE7,
+0x879F,0x87A0,0x87A1,0xE0EA,0x87A2,0x87A3,0x87A4,0x87A5,
+0x87A6,0x87A7,0x87A8,0x87A9,0x87AA,0x87AB,0x87AC,0x87AD,
+0x87AE,0x87AF,0x87B0,0xCFF9,0x87B1,0x87B2,0x87B3,0x87B4,
+0x87B5,0x87B6,0x87B7,0x87B8,0x87B9,0x87BA,0x87BB,0xE0EB,
+0x87BC,0x87BD,0x87BE,0x87BF,0x87C0,0x87C1,0x87C2,0xC8C2,
+0x87C3,0x87C4,0x87C5,0x87C6,0xBDC0,0x87C7,0x87C8,0x87C9,
+0x87CA,0x87CB,0x87CC,0x87CD,0x87CE,0x87CF,0x87D0,0x87D1,
+0x87D2,0x87D3,0xC4D2,0x87D4,0x87D5,0x87D6,0x87D7,0x87D8,
+0x87D9,0x87DA,0x87DB,0x87DC,0xE0EC,0x87DD,0x87DE,0xE0ED,
+0x87DF,0x87E0,0xC7F4,0xCBC4,0x87E1,0xE0EE,0xBBD8,0xD8B6,
+0xD2F2,0xE0EF,0xCDC5,0x87E2,0xB6DA,0x87E3,0x87E4,0x87E5,
+0x87E6,0x87E7,0x87E8,0xE0F1,0x87E9,0xD4B0,0x87EA,0x87EB,
+0xC0A7,0xB4D1,0x87EC,0x87ED,0xCEA7,0xE0F0,0x87EE,0x87EF,
+0x87F0,0xE0F2,0xB9CC,0x87F1,0x87F2,0xB9FA,0xCDBC,0xE0F3,
+0x87F3,0x87F4,0x87F5,0xC6D4,0xE0F4,0x87F6,0xD4B2,0x87F7,
+0xC8A6,0xE0F6,0xE0F5,0x87F8,0x87F9,0x87FA,0x87FB,0x87FC,
+0x87FD,0x87FE,0x8840,0x8841,0x8842,0x8843,0x8844,0x8845,
+0x8846,0x8847,0x8848,0x8849,0xE0F7,0x884A,0x884B,0xCDC1,
+0x884C,0x884D,0x884E,0xCAA5,0x884F,0x8850,0x8851,0x8852,
+0xD4DA,0xDBD7,0xDBD9,0x8853,0xDBD8,0xB9E7,0xDBDC,0xDBDD,
+0xB5D8,0x8854,0x8855,0xDBDA,0x8856,0x8857,0x8858,0x8859,
+0x885A,0xDBDB,0xB3A1,0xDBDF,0x885B,0x885C,0xBBF8,0x885D,
+0xD6B7,0x885E,0xDBE0,0x885F,0x8860,0x8861,0x8862,0xBEF9,
+0x8863,0x8864,0xB7BB,0x8865,0xDBD0,0xCCAE,0xBFB2,0xBBB5,
+0xD7F8,0xBFD3,0x8866,0x8867,0x8868,0x8869,0x886A,0xBFE9,
+0x886B,0x886C,0xBCE1,0xCCB3,0xDBDE,0xB0D3,0xCEEB,0xB7D8,
+0xD7B9,0xC6C2,0x886D,0x886E,0xC0A4,0x886F,0xCCB9,0x8870,
+0xDBE7,0xDBE1,0xC6BA,0xDBE3,0x8871,0xDBE8,0x8872,0xC5F7,
+0x8873,0x8874,0x8875,0xDBEA,0x8876,0x8877,0xDBE9,0xBFC0,
+0x8878,0x8879,0x887A,0xDBE6,0xDBE5,0x887B,0x887C,0x887D,
+0x887E,0x8880,0xB4B9,0xC0AC,0xC2A2,0xDBE2,0xDBE4,0x8881,
+0x8882,0x8883,0x8884,0xD0CD,0xDBED,0x8885,0x8886,0x8887,
+0x8888,0x8889,0xC0DD,0xDBF2,0x888A,0x888B,0x888C,0x888D,
+0x888E,0x888F,0x8890,0xB6E2,0x8891,0x8892,0x8893,0x8894,
+0xDBF3,0xDBD2,0xB9B8,0xD4AB,0xDBEC,0x8895,0xBFD1,0xDBF0,
+0x8896,0xDBD1,0x8897,0xB5E6,0x8898,0xDBEB,0xBFE5,0x8899,
+0x889A,0x889B,0xDBEE,0x889C,0xDBF1,0x889D,0x889E,0x889F,
+0xDBF9,0x88A0,0x88A1,0x88A2,0x88A3,0x88A4,0x88A5,0x88A6,
+0x88A7,0x88A8,0xB9A1,0xB0A3,0x88A9,0x88AA,0x88AB,0x88AC,
+0x88AD,0x88AE,0x88AF,0xC2F1,0x88B0,0x88B1,0xB3C7,0xDBEF,
+0x88B2,0x88B3,0xDBF8,0x88B4,0xC6D2,0xDBF4,0x88B5,0x88B6,
+0xDBF5,0xDBF7,0xDBF6,0x88B7,0x88B8,0xDBFE,0x88B9,0xD3F2,
+0xB2BA,0x88BA,0x88BB,0x88BC,0xDBFD,0x88BD,0x88BE,0x88BF,
+0x88C0,0x88C1,0x88C2,0x88C3,0x88C4,0xDCA4,0x88C5,0xDBFB,
+0x88C6,0x88C7,0x88C8,0x88C9,0xDBFA,0x88CA,0x88CB,0x88CC,
+0xDBFC,0xC5E0,0xBBF9,0x88CD,0x88CE,0xDCA3,0x88CF,0x88D0,
+0xDCA5,0x88D1,0xCCC3,0x88D2,0x88D3,0x88D4,0xB6D1,0xDDC0,
+0x88D5,0x88D6,0x88D7,0xDCA1,0x88D8,0xDCA2,0x88D9,0x88DA,
+0x88DB,0xC7B5,0x88DC,0x88DD,0x88DE,0xB6E9,0x88DF,0x88E0,
+0x88E1,0xDCA7,0x88E2,0x88E3,0x88E4,0x88E5,0xDCA6,0x88E6,
+0xDCA9,0xB1A4,0x88E7,0x88E8,0xB5CC,0x88E9,0x88EA,0x88EB,
+0x88EC,0x88ED,0xBFB0,0x88EE,0x88EF,0x88F0,0x88F1,0x88F2,
+0xD1DF,0x88F3,0x88F4,0x88F5,0x88F6,0xB6C2,0x88F7,0x88F8,
+0x88F9,0x88FA,0x88FB,0x88FC,0x88FD,0x88FE,0x8940,0x8941,
+0x8942,0x8943,0x8944,0x8945,0xDCA8,0x8946,0x8947,0x8948,
+0x8949,0x894A,0x894B,0x894C,0xCBFA,0xEBF3,0x894D,0x894E,
+0x894F,0xCBDC,0x8950,0x8951,0xCBFE,0x8952,0x8953,0x8954,
+0xCCC1,0x8955,0x8956,0x8957,0x8958,0x8959,0xC8FB,0x895A,
+0x895B,0x895C,0x895D,0x895E,0x895F,0xDCAA,0x8960,0x8961,
+0x8962,0x8963,0x8964,0xCCEE,0xDCAB,0x8965,0x8966,0x8967,
+0x8968,0x8969,0x896A,0x896B,0x896C,0x896D,0x896E,0x896F,
+0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0xDBD3,0x8976,
+0xDCAF,0xDCAC,0x8977,0xBEB3,0x8978,0xCAFB,0x8979,0x897A,
+0x897B,0xDCAD,0x897C,0x897D,0x897E,0x8980,0x8981,0x8982,
+0x8983,0x8984,0xC9CA,0xC4B9,0x8985,0x8986,0x8987,0x8988,
+0x8989,0xC7BD,0xDCAE,0x898A,0x898B,0x898C,0xD4F6,0xD0E6,
+0x898D,0x898E,0x898F,0x8990,0x8991,0x8992,0x8993,0x8994,
+0xC4AB,0xB6D5,0x8995,0x8996,0x8997,0x8998,0x8999,0x899A,
+0x899B,0x899C,0x899D,0x899E,0x899F,0x89A0,0x89A1,0x89A2,
+0x89A3,0x89A4,0x89A5,0x89A6,0xDBD4,0x89A7,0x89A8,0x89A9,
+0x89AA,0xB1DA,0x89AB,0x89AC,0x89AD,0xDBD5,0x89AE,0x89AF,
+0x89B0,0x89B1,0x89B2,0x89B3,0x89B4,0x89B5,0x89B6,0x89B7,
+0x89B8,0xDBD6,0x89B9,0x89BA,0x89BB,0xBABE,0x89BC,0x89BD,
+0x89BE,0x89BF,0x89C0,0x89C1,0x89C2,0x89C3,0x89C4,0x89C5,
+0x89C6,0x89C7,0x89C8,0x89C9,0xC8C0,0x89CA,0x89CB,0x89CC,
+0x89CD,0x89CE,0x89CF,0xCABF,0xC8C9,0x89D0,0xD7B3,0x89D1,
+0xC9F9,0x89D2,0x89D3,0xBFC7,0x89D4,0x89D5,0xBAF8,0x89D6,
+0x89D7,0xD2BC,0x89D8,0x89D9,0x89DA,0x89DB,0x89DC,0x89DD,
+0x89DE,0x89DF,0xE2BA,0x89E0,0xB4A6,0x89E1,0x89E2,0xB1B8,
+0x89E3,0x89E4,0x89E5,0x89E6,0x89E7,0xB8B4,0x89E8,0xCFC4,
+0x89E9,0x89EA,0x89EB,0x89EC,0xD9E7,0xCFA6,0xCDE2,0x89ED,
+0x89EE,0xD9ED,0xB6E0,0x89EF,0xD2B9,0x89F0,0x89F1,0xB9BB,
+0x89F2,0x89F3,0x89F4,0x89F5,0xE2B9,0xE2B7,0x89F6,0xB4F3,
+0x89F7,0xCCEC,0xCCAB,0xB7F2,0x89F8,0xD8B2,0xD1EB,0xBABB,
+0x89F9,0xCAA7,0x89FA,0x89FB,0xCDB7,0x89FC,0x89FD,0xD2C4,
+0xBFE4,0xBCD0,0xB6E1,0x89FE,0xDEC5,0x8A40,0x8A41,0x8A42,
+0x8A43,0xDEC6,0xDBBC,0x8A44,0xD1D9,0x8A45,0x8A46,0xC6E6,
+0xC4CE,0xB7EE,0x8A47,0xB7DC,0x8A48,0x8A49,0xBFFC,0xD7E0,
+0x8A4A,0xC6F5,0x8A4B,0x8A4C,0xB1BC,0xDEC8,0xBDB1,0xCCD7,
+0xDECA,0x8A4D,0xDEC9,0x8A4E,0x8A4F,0x8A50,0x8A51,0x8A52,
+0xB5EC,0x8A53,0xC9DD,0x8A54,0x8A55,0xB0C2,0x8A56,0x8A57,
+0x8A58,0x8A59,0x8A5A,0x8A5B,0x8A5C,0x8A5D,0x8A5E,0x8A5F,
+0x8A60,0x8A61,0x8A62,0xC5AE,0xC5AB,0x8A63,0xC4CC,0x8A64,
+0xBCE9,0xCBFD,0x8A65,0x8A66,0x8A67,0xBAC3,0x8A68,0x8A69,
+0x8A6A,0xE5F9,0xC8E7,0xE5FA,0xCDFD,0x8A6B,0xD7B1,0xB8BE,
+0xC2E8,0x8A6C,0xC8D1,0x8A6D,0x8A6E,0xE5FB,0x8A6F,0x8A70,
+0x8A71,0x8A72,0xB6CA,0xBCCB,0x8A73,0x8A74,0xD1FD,0xE6A1,
+0x8A75,0xC3EE,0x8A76,0x8A77,0x8A78,0x8A79,0xE6A4,0x8A7A,
+0x8A7B,0x8A7C,0x8A7D,0xE5FE,0xE6A5,0xCDD7,0x8A7E,0x8A80,
+0xB7C1,0xE5FC,0xE5FD,0xE6A3,0x8A81,0x8A82,0xC4DD,0xE6A8,
+0x8A83,0x8A84,0xE6A7,0x8A85,0x8A86,0x8A87,0x8A88,0x8A89,
+0x8A8A,0xC3C3,0x8A8B,0xC6DE,0x8A8C,0x8A8D,0xE6AA,0x8A8E,
+0x8A8F,0x8A90,0x8A91,0x8A92,0x8A93,0x8A94,0xC4B7,0x8A95,
+0x8A96,0x8A97,0xE6A2,0xCABC,0x8A98,0x8A99,0x8A9A,0x8A9B,
+0xBDE3,0xB9C3,0xE6A6,0xD0D5,0xCEAF,0x8A9C,0x8A9D,0xE6A9,
+0xE6B0,0x8A9E,0xD2A6,0x8A9F,0xBDAA,0xE6AD,0x8AA0,0x8AA1,
+0x8AA2,0x8AA3,0x8AA4,0xE6AF,0x8AA5,0xC0D1,0x8AA6,0x8AA7,
+0xD2CC,0x8AA8,0x8AA9,0x8AAA,0xBCA7,0x8AAB,0x8AAC,0x8AAD,
+0x8AAE,0x8AAF,0x8AB0,0x8AB1,0x8AB2,0x8AB3,0x8AB4,0x8AB5,
+0x8AB6,0xE6B1,0x8AB7,0xD2F6,0x8AB8,0x8AB9,0x8ABA,0xD7CB,
+0x8ABB,0xCDFE,0x8ABC,0xCDDE,0xC2A6,0xE6AB,0xE6AC,0xBDBF,
+0xE6AE,0xE6B3,0x8ABD,0x8ABE,0xE6B2,0x8ABF,0x8AC0,0x8AC1,
+0x8AC2,0xE6B6,0x8AC3,0xE6B8,0x8AC4,0x8AC5,0x8AC6,0x8AC7,
+0xC4EF,0x8AC8,0x8AC9,0x8ACA,0xC4C8,0x8ACB,0x8ACC,0xBEEA,
+0xC9EF,0x8ACD,0x8ACE,0xE6B7,0x8ACF,0xB6F0,0x8AD0,0x8AD1,
+0x8AD2,0xC3E4,0x8AD3,0x8AD4,0x8AD5,0x8AD6,0x8AD7,0x8AD8,
+0x8AD9,0xD3E9,0xE6B4,0x8ADA,0xE6B5,0x8ADB,0xC8A2,0x8ADC,
+0x8ADD,0x8ADE,0x8ADF,0x8AE0,0xE6BD,0x8AE1,0x8AE2,0x8AE3,
+0xE6B9,0x8AE4,0x8AE5,0x8AE6,0x8AE7,0x8AE8,0xC6C5,0x8AE9,
+0x8AEA,0xCDF1,0xE6BB,0x8AEB,0x8AEC,0x8AED,0x8AEE,0x8AEF,
+0x8AF0,0x8AF1,0x8AF2,0x8AF3,0x8AF4,0xE6BC,0x8AF5,0x8AF6,
+0x8AF7,0x8AF8,0xBBE9,0x8AF9,0x8AFA,0x8AFB,0x8AFC,0x8AFD,
+0x8AFE,0x8B40,0xE6BE,0x8B41,0x8B42,0x8B43,0x8B44,0xE6BA,
+0x8B45,0x8B46,0xC0B7,0x8B47,0x8B48,0x8B49,0x8B4A,0x8B4B,
+0x8B4C,0x8B4D,0x8B4E,0x8B4F,0xD3A4,0xE6BF,0xC9F4,0xE6C3,
+0x8B50,0x8B51,0xE6C4,0x8B52,0x8B53,0x8B54,0x8B55,0xD0F6,
+0x8B56,0x8B57,0x8B58,0x8B59,0x8B5A,0x8B5B,0x8B5C,0x8B5D,
+0x8B5E,0x8B5F,0x8B60,0x8B61,0x8B62,0x8B63,0x8B64,0x8B65,
+0x8B66,0x8B67,0xC3BD,0x8B68,0x8B69,0x8B6A,0x8B6B,0x8B6C,
+0x8B6D,0x8B6E,0xC3C4,0xE6C2,0x8B6F,0x8B70,0x8B71,0x8B72,
+0x8B73,0x8B74,0x8B75,0x8B76,0x8B77,0x8B78,0x8B79,0x8B7A,
+0x8B7B,0x8B7C,0xE6C1,0x8B7D,0x8B7E,0x8B80,0x8B81,0x8B82,
+0x8B83,0x8B84,0xE6C7,0xCFB1,0x8B85,0xEBF4,0x8B86,0x8B87,
+0xE6CA,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0xE6C5,0x8B8D,
+0x8B8E,0xBCDE,0xC9A9,0x8B8F,0x8B90,0x8B91,0x8B92,0x8B93,
+0x8B94,0xBCB5,0x8B95,0x8B96,0xCFD3,0x8B97,0x8B98,0x8B99,
+0x8B9A,0x8B9B,0xE6C8,0x8B9C,0xE6C9,0x8B9D,0xE6CE,0x8B9E,
+0xE6D0,0x8B9F,0x8BA0,0x8BA1,0xE6D1,0x8BA2,0x8BA3,0x8BA4,
+0xE6CB,0xB5D5,0x8BA5,0xE6CC,0x8BA6,0x8BA7,0xE6CF,0x8BA8,
+0x8BA9,0xC4DB,0x8BAA,0xE6C6,0x8BAB,0x8BAC,0x8BAD,0x8BAE,
+0x8BAF,0xE6CD,0x8BB0,0x8BB1,0x8BB2,0x8BB3,0x8BB4,0x8BB5,
+0x8BB6,0x8BB7,0x8BB8,0x8BB9,0x8BBA,0x8BBB,0x8BBC,0x8BBD,
+0x8BBE,0x8BBF,0x8BC0,0x8BC1,0x8BC2,0x8BC3,0x8BC4,0x8BC5,
+0x8BC6,0xE6D2,0x8BC7,0x8BC8,0x8BC9,0x8BCA,0x8BCB,0x8BCC,
+0x8BCD,0x8BCE,0x8BCF,0x8BD0,0x8BD1,0x8BD2,0xE6D4,0xE6D3,
+0x8BD3,0x8BD4,0x8BD5,0x8BD6,0x8BD7,0x8BD8,0x8BD9,0x8BDA,
+0x8BDB,0x8BDC,0x8BDD,0x8BDE,0x8BDF,0x8BE0,0x8BE1,0x8BE2,
+0x8BE3,0x8BE4,0x8BE5,0x8BE6,0x8BE7,0x8BE8,0x8BE9,0x8BEA,
+0x8BEB,0x8BEC,0xE6D5,0x8BED,0xD9F8,0x8BEE,0x8BEF,0xE6D6,
+0x8BF0,0x8BF1,0x8BF2,0x8BF3,0x8BF4,0x8BF5,0x8BF6,0x8BF7,
+0xE6D7,0x8BF8,0x8BF9,0x8BFA,0x8BFB,0x8BFC,0x8BFD,0x8BFE,
+0x8C40,0x8C41,0x8C42,0x8C43,0x8C44,0x8C45,0x8C46,0x8C47,
+0xD7D3,0xE6DD,0x8C48,0xE6DE,0xBFD7,0xD4D0,0x8C49,0xD7D6,
+0xB4E6,0xCBEF,0xE6DA,0xD8C3,0xD7CE,0xD0A2,0x8C4A,0xC3CF,
+0x8C4B,0x8C4C,0xE6DF,0xBCBE,0xB9C2,0xE6DB,0xD1A7,0x8C4D,
+0x8C4E,0xBAA2,0xC2CF,0x8C4F,0xD8AB,0x8C50,0x8C51,0x8C52,
+0xCAEB,0xE5EE,0x8C53,0xE6DC,0x8C54,0xB7F5,0x8C55,0x8C56,
+0x8C57,0x8C58,0xC8E6,0x8C59,0x8C5A,0xC4F5,0x8C5B,0x8C5C,
+0xE5B2,0xC4FE,0x8C5D,0xCBFC,0xE5B3,0xD5AC,0x8C5E,0xD3EE,
+0xCAD8,0xB0B2,0x8C5F,0xCBCE,0xCDEA,0x8C60,0x8C61,0xBAEA,
+0x8C62,0x8C63,0x8C64,0xE5B5,0x8C65,0xE5B4,0x8C66,0xD7DA,
+0xB9D9,0xD6E6,0xB6A8,0xCDF0,0xD2CB,0xB1A6,0xCAB5,0x8C67,
+0xB3E8,0xC9F3,0xBFCD,0xD0FB,0xCAD2,0xE5B6,0xBBC2,0x8C68,
+0x8C69,0x8C6A,0xCFDC,0xB9AC,0x8C6B,0x8C6C,0x8C6D,0x8C6E,
+0xD4D7,0x8C6F,0x8C70,0xBAA6,0xD1E7,0xCFFC,0xBCD2,0x8C71,
+0xE5B7,0xC8DD,0x8C72,0x8C73,0x8C74,0xBFED,0xB1F6,0xCBDE,
+0x8C75,0x8C76,0xBCC5,0x8C77,0xBCC4,0xD2FA,0xC3DC,0xBFDC,
+0x8C78,0x8C79,0x8C7A,0x8C7B,0xB8BB,0x8C7C,0x8C7D,0x8C7E,
+0xC3C2,0x8C80,0xBAAE,0xD4A2,0x8C81,0x8C82,0x8C83,0x8C84,
+0x8C85,0x8C86,0x8C87,0x8C88,0x8C89,0xC7DE,0xC4AF,0xB2EC,
+0x8C8A,0xB9D1,0x8C8B,0x8C8C,0xE5BB,0xC1C8,0x8C8D,0x8C8E,
+0xD5AF,0x8C8F,0x8C90,0x8C91,0x8C92,0x8C93,0xE5BC,0x8C94,
+0xE5BE,0x8C95,0x8C96,0x8C97,0x8C98,0x8C99,0x8C9A,0x8C9B,
+0xB4E7,0xB6D4,0xCBC2,0xD1B0,0xB5BC,0x8C9C,0x8C9D,0xCAD9,
+0x8C9E,0xB7E2,0x8C9F,0x8CA0,0xC9E4,0x8CA1,0xBDAB,0x8CA2,
+0x8CA3,0xCEBE,0xD7F0,0x8CA4,0x8CA5,0x8CA6,0x8CA7,0xD0A1,
+0x8CA8,0xC9D9,0x8CA9,0x8CAA,0xB6FB,0xE6D8,0xBCE2,0x8CAB,
+0xB3BE,0x8CAC,0xC9D0,0x8CAD,0xE6D9,0xB3A2,0x8CAE,0x8CAF,
+0x8CB0,0x8CB1,0xDECC,0x8CB2,0xD3C8,0xDECD,0x8CB3,0xD2A2,
+0x8CB4,0x8CB5,0x8CB6,0x8CB7,0xDECE,0x8CB8,0x8CB9,0x8CBA,
+0x8CBB,0xBECD,0x8CBC,0x8CBD,0xDECF,0x8CBE,0x8CBF,0x8CC0,
+0xCAAC,0xD2FC,0xB3DF,0xE5EA,0xC4E1,0xBEA1,0xCEB2,0xC4F2,
+0xBED6,0xC6A8,0xB2E3,0x8CC1,0x8CC2,0xBED3,0x8CC3,0x8CC4,
+0xC7FC,0xCCEB,0xBDEC,0xCEDD,0x8CC5,0x8CC6,0xCABA,0xC6C1,
+0xE5EC,0xD0BC,0x8CC7,0x8CC8,0x8CC9,0xD5B9,0x8CCA,0x8CCB,
+0x8CCC,0xE5ED,0x8CCD,0x8CCE,0x8CCF,0x8CD0,0xCAF4,0x8CD1,
+0xCDC0,0xC2C5,0x8CD2,0xE5EF,0x8CD3,0xC2C4,0xE5F0,0x8CD4,
+0x8CD5,0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,0xE5F8,0xCDCD,
+0x8CDB,0xC9BD,0x8CDC,0x8CDD,0x8CDE,0x8CDF,0x8CE0,0x8CE1,
+0x8CE2,0xD2D9,0xE1A8,0x8CE3,0x8CE4,0x8CE5,0x8CE6,0xD3EC,
+0x8CE7,0xCBEA,0xC6F1,0x8CE8,0x8CE9,0x8CEA,0x8CEB,0x8CEC,
+0xE1AC,0x8CED,0x8CEE,0x8CEF,0xE1A7,0xE1A9,0x8CF0,0x8CF1,
+0xE1AA,0xE1AF,0x8CF2,0x8CF3,0xB2ED,0x8CF4,0xE1AB,0xB8DA,
+0xE1AD,0xE1AE,0xE1B0,0xB5BA,0xE1B1,0x8CF5,0x8CF6,0x8CF7,
+0x8CF8,0x8CF9,0xE1B3,0xE1B8,0x8CFA,0x8CFB,0x8CFC,0x8CFD,
+0x8CFE,0xD1D2,0x8D40,0xE1B6,0xE1B5,0xC1EB,0x8D41,0x8D42,
+0x8D43,0xE1B7,0x8D44,0xD4C0,0x8D45,0xE1B2,0x8D46,0xE1BA,
+0xB0B6,0x8D47,0x8D48,0x8D49,0x8D4A,0xE1B4,0x8D4B,0xBFF9,
+0x8D4C,0xE1B9,0x8D4D,0x8D4E,0xE1BB,0x8D4F,0x8D50,0x8D51,
+0x8D52,0x8D53,0x8D54,0xE1BE,0x8D55,0x8D56,0x8D57,0x8D58,
+0x8D59,0x8D5A,0xE1BC,0x8D5B,0x8D5C,0x8D5D,0x8D5E,0x8D5F,
+0x8D60,0xD6C5,0x8D61,0x8D62,0x8D63,0x8D64,0x8D65,0x8D66,
+0x8D67,0xCFBF,0x8D68,0x8D69,0xE1BD,0xE1BF,0xC2CD,0x8D6A,
+0xB6EB,0x8D6B,0xD3F8,0x8D6C,0x8D6D,0xC7CD,0x8D6E,0x8D6F,
+0xB7E5,0x8D70,0x8D71,0x8D72,0x8D73,0x8D74,0x8D75,0x8D76,
+0x8D77,0x8D78,0x8D79,0xBEFE,0x8D7A,0x8D7B,0x8D7C,0x8D7D,
+0x8D7E,0x8D80,0xE1C0,0xE1C1,0x8D81,0x8D82,0xE1C7,0xB3E7,
+0x8D83,0x8D84,0x8D85,0x8D86,0x8D87,0x8D88,0xC6E9,0x8D89,
+0x8D8A,0x8D8B,0x8D8C,0x8D8D,0xB4DE,0x8D8E,0xD1C2,0x8D8F,
+0x8D90,0x8D91,0x8D92,0xE1C8,0x8D93,0x8D94,0xE1C6,0x8D95,
+0x8D96,0x8D97,0x8D98,0x8D99,0xE1C5,0x8D9A,0xE1C3,0xE1C2,
+0x8D9B,0xB1C0,0x8D9C,0x8D9D,0x8D9E,0xD5B8,0xE1C4,0x8D9F,
+0x8DA0,0x8DA1,0x8DA2,0x8DA3,0xE1CB,0x8DA4,0x8DA5,0x8DA6,
+0x8DA7,0x8DA8,0x8DA9,0x8DAA,0x8DAB,0xE1CC,0xE1CA,0x8DAC,
+0x8DAD,0x8DAE,0x8DAF,0x8DB0,0x8DB1,0x8DB2,0x8DB3,0xEFFA,
+0x8DB4,0x8DB5,0xE1D3,0xE1D2,0xC7B6,0x8DB6,0x8DB7,0x8DB8,
+0x8DB9,0x8DBA,0x8DBB,0x8DBC,0x8DBD,0x8DBE,0x8DBF,0x8DC0,
+0xE1C9,0x8DC1,0x8DC2,0xE1CE,0x8DC3,0xE1D0,0x8DC4,0x8DC5,
+0x8DC6,0x8DC7,0x8DC8,0x8DC9,0x8DCA,0x8DCB,0x8DCC,0x8DCD,
+0x8DCE,0xE1D4,0x8DCF,0xE1D1,0xE1CD,0x8DD0,0x8DD1,0xE1CF,
+0x8DD2,0x8DD3,0x8DD4,0x8DD5,0xE1D5,0x8DD6,0x8DD7,0x8DD8,
+0x8DD9,0x8DDA,0x8DDB,0x8DDC,0x8DDD,0x8DDE,0x8DDF,0x8DE0,
+0x8DE1,0x8DE2,0xE1D6,0x8DE3,0x8DE4,0x8DE5,0x8DE6,0x8DE7,
+0x8DE8,0x8DE9,0x8DEA,0x8DEB,0x8DEC,0x8DED,0x8DEE,0x8DEF,
+0x8DF0,0x8DF1,0x8DF2,0x8DF3,0x8DF4,0x8DF5,0x8DF6,0x8DF7,
+0x8DF8,0xE1D7,0x8DF9,0x8DFA,0x8DFB,0xE1D8,0x8DFC,0x8DFD,
+0x8DFE,0x8E40,0x8E41,0x8E42,0x8E43,0x8E44,0x8E45,0x8E46,
+0x8E47,0x8E48,0x8E49,0x8E4A,0x8E4B,0x8E4C,0x8E4D,0x8E4E,
+0x8E4F,0x8E50,0x8E51,0x8E52,0x8E53,0x8E54,0x8E55,0xE1DA,
+0x8E56,0x8E57,0x8E58,0x8E59,0x8E5A,0x8E5B,0x8E5C,0x8E5D,
+0x8E5E,0x8E5F,0x8E60,0x8E61,0x8E62,0xE1DB,0x8E63,0x8E64,
+0x8E65,0x8E66,0x8E67,0x8E68,0x8E69,0xCEA1,0x8E6A,0x8E6B,
+0x8E6C,0x8E6D,0x8E6E,0x8E6F,0x8E70,0x8E71,0x8E72,0x8E73,
+0x8E74,0x8E75,0x8E76,0xE7DD,0x8E77,0xB4A8,0xD6DD,0x8E78,
+0x8E79,0xD1B2,0xB3B2,0x8E7A,0x8E7B,0xB9A4,0xD7F3,0xC7C9,
+0xBEDE,0xB9AE,0x8E7C,0xCED7,0x8E7D,0x8E7E,0xB2EE,0xDBCF,
+0x8E80,0xBCBA,0xD2D1,0xCBC8,0xB0CD,0x8E81,0x8E82,0xCFEF,
+0x8E83,0x8E84,0x8E85,0x8E86,0x8E87,0xD9E3,0xBDED,0x8E88,
+0x8E89,0xB1D2,0xCAD0,0xB2BC,0x8E8A,0xCBA7,0xB7AB,0x8E8B,
+0xCAA6,0x8E8C,0x8E8D,0x8E8E,0xCFA3,0x8E8F,0x8E90,0xE0F8,
+0xD5CA,0xE0FB,0x8E91,0x8E92,0xE0FA,0xC5C1,0xCCFB,0x8E93,
+0xC1B1,0xE0F9,0xD6E3,0xB2AF,0xD6C4,0xB5DB,0x8E94,0x8E95,
+0x8E96,0x8E97,0x8E98,0x8E99,0x8E9A,0x8E9B,0xB4F8,0xD6A1,
+0x8E9C,0x8E9D,0x8E9E,0x8E9F,0x8EA0,0xCFAF,0xB0EF,0x8EA1,
+0x8EA2,0xE0FC,0x8EA3,0x8EA4,0x8EA5,0x8EA6,0x8EA7,0xE1A1,
+0xB3A3,0x8EA8,0x8EA9,0xE0FD,0xE0FE,0xC3B1,0x8EAA,0x8EAB,
+0x8EAC,0x8EAD,0xC3DD,0x8EAE,0xE1A2,0xB7F9,0x8EAF,0x8EB0,
+0x8EB1,0x8EB2,0x8EB3,0x8EB4,0xBBCF,0x8EB5,0x8EB6,0x8EB7,
+0x8EB8,0x8EB9,0x8EBA,0x8EBB,0xE1A3,0xC4BB,0x8EBC,0x8EBD,
+0x8EBE,0x8EBF,0x8EC0,0xE1A4,0x8EC1,0x8EC2,0xE1A5,0x8EC3,
+0x8EC4,0xE1A6,0xB4B1,0x8EC5,0x8EC6,0x8EC7,0x8EC8,0x8EC9,
+0x8ECA,0x8ECB,0x8ECC,0x8ECD,0x8ECE,0x8ECF,0x8ED0,0x8ED1,
+0x8ED2,0x8ED3,0xB8C9,0xC6BD,0xC4EA,0x8ED4,0xB2A2,0x8ED5,
+0xD0D2,0x8ED6,0xE7DB,0xBBC3,0xD3D7,0xD3C4,0x8ED7,0xB9E3,
+0xE2CF,0x8ED8,0x8ED9,0x8EDA,0xD7AF,0x8EDB,0xC7EC,0xB1D3,
+0x8EDC,0x8EDD,0xB4B2,0xE2D1,0x8EDE,0x8EDF,0x8EE0,0xD0F2,
+0xC2AE,0xE2D0,0x8EE1,0xBFE2,0xD3A6,0xB5D7,0xE2D2,0xB5EA,
+0x8EE2,0xC3ED,0xB8FD,0x8EE3,0xB8AE,0x8EE4,0xC5D3,0xB7CF,
+0xE2D4,0x8EE5,0x8EE6,0x8EE7,0x8EE8,0xE2D3,0xB6C8,0xD7F9,
+0x8EE9,0x8EEA,0x8EEB,0x8EEC,0x8EED,0xCDA5,0x8EEE,0x8EEF,
+0x8EF0,0x8EF1,0x8EF2,0xE2D8,0x8EF3,0xE2D6,0xCAFC,0xBFB5,
+0xD3B9,0xE2D5,0x8EF4,0x8EF5,0x8EF6,0x8EF7,0xE2D7,0x8EF8,
+0x8EF9,0x8EFA,0x8EFB,0x8EFC,0x8EFD,0x8EFE,0x8F40,0x8F41,
+0x8F42,0xC1AE,0xC0C8,0x8F43,0x8F44,0x8F45,0x8F46,0x8F47,
+0x8F48,0xE2DB,0xE2DA,0xC0AA,0x8F49,0x8F4A,0xC1CE,0x8F4B,
+0x8F4C,0x8F4D,0x8F4E,0xE2DC,0x8F4F,0x8F50,0x8F51,0x8F52,
+0x8F53,0x8F54,0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A,
+0xE2DD,0x8F5B,0xE2DE,0x8F5C,0x8F5D,0x8F5E,0x8F5F,0x8F60,
+0x8F61,0x8F62,0x8F63,0x8F64,0xDBC8,0x8F65,0xD1D3,0xCDA2,
+0x8F66,0x8F67,0xBDA8,0x8F68,0x8F69,0x8F6A,0xDEC3,0xD8A5,
+0xBFAA,0xDBCD,0xD2EC,0xC6FA,0xC5AA,0x8F6B,0x8F6C,0x8F6D,
+0xDEC4,0x8F6E,0xB1D7,0xDFAE,0x8F6F,0x8F70,0x8F71,0xCABD,
+0x8F72,0xDFB1,0x8F73,0xB9AD,0x8F74,0xD2FD,0x8F75,0xB8A5,
+0xBAEB,0x8F76,0x8F77,0xB3DA,0x8F78,0x8F79,0x8F7A,0xB5DC,
+0xD5C5,0x8F7B,0x8F7C,0x8F7D,0x8F7E,0xC3D6,0xCFD2,0xBBA1,
+0x8F80,0xE5F3,0xE5F2,0x8F81,0x8F82,0xE5F4,0x8F83,0xCDE4,
+0x8F84,0xC8F5,0x8F85,0x8F86,0x8F87,0x8F88,0x8F89,0x8F8A,
+0x8F8B,0xB5AF,0xC7BF,0x8F8C,0xE5F6,0x8F8D,0x8F8E,0x8F8F,
+0xECB0,0x8F90,0x8F91,0x8F92,0x8F93,0x8F94,0x8F95,0x8F96,
+0x8F97,0x8F98,0x8F99,0x8F9A,0x8F9B,0x8F9C,0x8F9D,0x8F9E,
+0xE5E6,0x8F9F,0xB9E9,0xB5B1,0x8FA0,0xC2BC,0xE5E8,0xE5E7,
+0xE5E9,0x8FA1,0x8FA2,0x8FA3,0x8FA4,0xD2CD,0x8FA5,0x8FA6,
+0x8FA7,0xE1EA,0xD0CE,0x8FA8,0xCDAE,0x8FA9,0xD1E5,0x8FAA,
+0x8FAB,0xB2CA,0xB1EB,0x8FAC,0xB1F2,0xC5ED,0x8FAD,0x8FAE,
+0xD5C3,0xD3B0,0x8FAF,0xE1DC,0x8FB0,0x8FB1,0x8FB2,0xE1DD,
+0x8FB3,0xD2DB,0x8FB4,0xB3B9,0xB1CB,0x8FB5,0x8FB6,0x8FB7,
+0xCDF9,0xD5F7,0xE1DE,0x8FB8,0xBEB6,0xB4FD,0x8FB9,0xE1DF,
+0xBADC,0xE1E0,0xBBB2,0xC2C9,0xE1E1,0x8FBA,0x8FBB,0x8FBC,
+0xD0EC,0x8FBD,0xCDBD,0x8FBE,0x8FBF,0xE1E2,0x8FC0,0xB5C3,
+0xC5C7,0xE1E3,0x8FC1,0x8FC2,0xE1E4,0x8FC3,0x8FC4,0x8FC5,
+0x8FC6,0xD3F9,0x8FC7,0x8FC8,0x8FC9,0x8FCA,0x8FCB,0x8FCC,
+0xE1E5,0x8FCD,0xD1AD,0x8FCE,0x8FCF,0xE1E6,0xCEA2,0x8FD0,
+0x8FD1,0x8FD2,0x8FD3,0x8FD4,0x8FD5,0xE1E7,0x8FD6,0xB5C2,
+0x8FD7,0x8FD8,0x8FD9,0x8FDA,0xE1E8,0xBBD5,0x8FDB,0x8FDC,
+0x8FDD,0x8FDE,0x8FDF,0xD0C4,0xE2E0,0xB1D8,0xD2E4,0x8FE0,
+0x8FE1,0xE2E1,0x8FE2,0x8FE3,0xBCC9,0xC8CC,0x8FE4,0xE2E3,
+0xECFE,0xECFD,0xDFAF,0x8FE5,0x8FE6,0x8FE7,0xE2E2,0xD6BE,
+0xCDFC,0xC3A6,0x8FE8,0x8FE9,0x8FEA,0xE3C3,0x8FEB,0x8FEC,
+0xD6D2,0xE2E7,0x8FED,0x8FEE,0xE2E8,0x8FEF,0x8FF0,0xD3C7,
+0x8FF1,0x8FF2,0xE2EC,0xBFEC,0x8FF3,0xE2ED,0xE2E5,0x8FF4,
+0x8FF5,0xB3C0,0x8FF6,0x8FF7,0x8FF8,0xC4EE,0x8FF9,0x8FFA,
+0xE2EE,0x8FFB,0x8FFC,0xD0C3,0x8FFD,0xBAF6,0xE2E9,0xB7DE,
+0xBBB3,0xCCAC,0xCBCB,0xE2E4,0xE2E6,0xE2EA,0xE2EB,0x8FFE,
+0x9040,0x9041,0xE2F7,0x9042,0x9043,0xE2F4,0xD4F5,0xE2F3,
+0x9044,0x9045,0xC5AD,0x9046,0xD5FA,0xC5C2,0xB2C0,0x9047,
+0x9048,0xE2EF,0x9049,0xE2F2,0xC1AF,0xCBBC,0x904A,0x904B,
+0xB5A1,0xE2F9,0x904C,0x904D,0x904E,0xBCB1,0xE2F1,0xD0D4,
+0xD4B9,0xE2F5,0xB9D6,0xE2F6,0x904F,0x9050,0x9051,0xC7D3,
+0x9052,0x9053,0x9054,0x9055,0x9056,0xE2F0,0x9057,0x9058,
+0x9059,0x905A,0x905B,0xD7DC,0xEDA1,0x905C,0x905D,0xE2F8,
+0x905E,0xEDA5,0xE2FE,0xCAD1,0x905F,0x9060,0x9061,0x9062,
+0x9063,0x9064,0x9065,0xC1B5,0x9066,0xBBD0,0x9067,0x9068,
+0xBFD6,0x9069,0xBAE3,0x906A,0x906B,0xCBA1,0x906C,0x906D,
+0x906E,0xEDA6,0xEDA3,0x906F,0x9070,0xEDA2,0x9071,0x9072,
+0x9073,0x9074,0xBBD6,0xEDA7,0xD0F4,0x9075,0x9076,0xEDA4,
+0xBADE,0xB6F7,0xE3A1,0xB6B2,0xCCF1,0xB9A7,0x9077,0xCFA2,
+0xC7A1,0x9078,0x9079,0xBFD2,0x907A,0x907B,0xB6F1,0x907C,
+0xE2FA,0xE2FB,0xE2FD,0xE2FC,0xC4D5,0xE3A2,0x907D,0xD3C1,
+0x907E,0x9080,0x9081,0xE3A7,0xC7C4,0x9082,0x9083,0x9084,
+0x9085,0xCFA4,0x9086,0x9087,0xE3A9,0xBAB7,0x9088,0x9089,
+0x908A,0x908B,0xE3A8,0x908C,0xBBDA,0x908D,0xE3A3,0x908E,
+0x908F,0x9090,0xE3A4,0xE3AA,0x9091,0xE3A6,0x9092,0xCEF2,
+0xD3C6,0x9093,0x9094,0xBBBC,0x9095,0x9096,0xD4C3,0x9097,
+0xC4FA,0x9098,0x9099,0xEDA8,0xD0FC,0xE3A5,0x909A,0xC3F5,
+0x909B,0xE3AD,0xB1AF,0x909C,0xE3B2,0x909D,0x909E,0x909F,
+0xBCC2,0x90A0,0x90A1,0xE3AC,0xB5BF,0x90A2,0x90A3,0x90A4,
+0x90A5,0x90A6,0x90A7,0x90A8,0x90A9,0xC7E9,0xE3B0,0x90AA,
+0x90AB,0x90AC,0xBEAA,0xCDEF,0x90AD,0x90AE,0x90AF,0x90B0,
+0x90B1,0xBBF3,0x90B2,0x90B3,0x90B4,0xCCE8,0x90B5,0x90B6,
+0xE3AF,0x90B7,0xE3B1,0x90B8,0xCFA7,0xE3AE,0x90B9,0xCEA9,
+0xBBDD,0x90BA,0x90BB,0x90BC,0x90BD,0x90BE,0xB5EB,0xBEE5,
+0xB2D2,0xB3CD,0x90BF,0xB1B9,0xE3AB,0xB2D1,0xB5AC,0xB9DF,
+0xB6E8,0x90C0,0x90C1,0xCFEB,0xE3B7,0x90C2,0xBBCC,0x90C3,
+0x90C4,0xC8C7,0xD0CA,0x90C5,0x90C6,0x90C7,0x90C8,0x90C9,
+0xE3B8,0xB3EE,0x90CA,0x90CB,0x90CC,0x90CD,0xEDA9,0x90CE,
+0xD3FA,0xD3E4,0x90CF,0x90D0,0x90D1,0xEDAA,0xE3B9,0xD2E2,
+0x90D2,0x90D3,0x90D4,0x90D5,0x90D6,0xE3B5,0x90D7,0x90D8,
+0x90D9,0x90DA,0xD3DE,0x90DB,0x90DC,0x90DD,0x90DE,0xB8D0,
+0xE3B3,0x90DF,0x90E0,0xE3B6,0xB7DF,0x90E1,0xE3B4,0xC0A2,
+0x90E2,0x90E3,0x90E4,0xE3BA,0x90E5,0x90E6,0x90E7,0x90E8,
+0x90E9,0x90EA,0x90EB,0x90EC,0x90ED,0x90EE,0x90EF,0x90F0,
+0x90F1,0x90F2,0x90F3,0x90F4,0x90F5,0x90F6,0x90F7,0xD4B8,
+0x90F8,0x90F9,0x90FA,0x90FB,0x90FC,0x90FD,0x90FE,0x9140,
+0xB4C8,0x9141,0xE3BB,0x9142,0xBBC5,0x9143,0xC9F7,0x9144,
+0x9145,0xC9E5,0x9146,0x9147,0x9148,0xC4BD,0x9149,0x914A,
+0x914B,0x914C,0x914D,0x914E,0x914F,0xEDAB,0x9150,0x9151,
+0x9152,0x9153,0xC2FD,0x9154,0x9155,0x9156,0x9157,0xBBDB,
+0xBFAE,0x9158,0x9159,0x915A,0x915B,0x915C,0x915D,0x915E,
+0xCEBF,0x915F,0x9160,0x9161,0x9162,0xE3BC,0x9163,0xBFB6,
+0x9164,0x9165,0x9166,0x9167,0x9168,0x9169,0x916A,0x916B,
+0x916C,0x916D,0x916E,0x916F,0x9170,0x9171,0x9172,0x9173,
+0x9174,0x9175,0x9176,0xB1EF,0x9177,0x9178,0xD4F7,0x9179,
+0x917A,0x917B,0x917C,0x917D,0xE3BE,0x917E,0x9180,0x9181,
+0x9182,0x9183,0x9184,0x9185,0x9186,0xEDAD,0x9187,0x9188,
+0x9189,0x918A,0x918B,0x918C,0x918D,0x918E,0x918F,0xE3BF,
+0xBAA9,0xEDAC,0x9190,0x9191,0xE3BD,0x9192,0x9193,0x9194,
+0x9195,0x9196,0x9197,0x9198,0x9199,0x919A,0x919B,0xE3C0,
+0x919C,0x919D,0x919E,0x919F,0x91A0,0x91A1,0xBAB6,0x91A2,
+0x91A3,0x91A4,0xB6AE,0x91A5,0x91A6,0x91A7,0x91A8,0x91A9,
+0xD0B8,0x91AA,0xB0C3,0xEDAE,0x91AB,0x91AC,0x91AD,0x91AE,
+0x91AF,0xEDAF,0xC0C1,0x91B0,0xE3C1,0x91B1,0x91B2,0x91B3,
+0x91B4,0x91B5,0x91B6,0x91B7,0x91B8,0x91B9,0x91BA,0x91BB,
+0x91BC,0x91BD,0x91BE,0x91BF,0x91C0,0x91C1,0xC5B3,0x91C2,
+0x91C3,0x91C4,0x91C5,0x91C6,0x91C7,0x91C8,0x91C9,0x91CA,
+0x91CB,0x91CC,0x91CD,0x91CE,0x91CF,0xE3C2,0x91D0,0x91D1,
+0x91D2,0x91D3,0x91D4,0x91D5,0x91D6,0x91D7,0x91D8,0xDCB2,
+0x91D9,0x91DA,0x91DB,0x91DC,0x91DD,0x91DE,0xEDB0,0x91DF,
+0xB8EA,0x91E0,0xCEEC,0xEAA7,0xD0E7,0xCAF9,0xC8D6,0xCFB7,
+0xB3C9,0xCED2,0xBDE4,0x91E1,0x91E2,0xE3DE,0xBBF2,0xEAA8,
+0xD5BD,0x91E3,0xC6DD,0xEAA9,0x91E4,0x91E5,0x91E6,0xEAAA,
+0x91E7,0xEAAC,0xEAAB,0x91E8,0xEAAE,0xEAAD,0x91E9,0x91EA,
+0x91EB,0x91EC,0xBDD8,0x91ED,0xEAAF,0x91EE,0xC2BE,0x91EF,
+0x91F0,0x91F1,0x91F2,0xB4C1,0xB4F7,0x91F3,0x91F4,0xBBA7,
+0x91F5,0x91F6,0x91F7,0x91F8,0x91F9,0xECE6,0xECE5,0xB7BF,
+0xCBF9,0xB1E2,0x91FA,0xECE7,0x91FB,0x91FC,0x91FD,0xC9C8,
+0xECE8,0xECE9,0x91FE,0xCAD6,0xDED0,0xB2C5,0xD4FA,0x9240,
+0x9241,0xC6CB,0xB0C7,0xB4F2,0xC8D3,0x9242,0x9243,0x9244,
+0xCDD0,0x9245,0x9246,0xBFB8,0x9247,0x9248,0x9249,0x924A,
+0x924B,0x924C,0x924D,0xBFDB,0x924E,0x924F,0xC7A4,0xD6B4,
+0x9250,0xC0A9,0xDED1,0xC9A8,0xD1EF,0xC5A4,0xB0E7,0xB3B6,
+0xC8C5,0x9251,0x9252,0xB0E2,0x9253,0x9254,0xB7F6,0x9255,
+0x9256,0xC5FA,0x9257,0x9258,0xB6F3,0x9259,0xD5D2,0xB3D0,
+0xBCBC,0x925A,0x925B,0x925C,0xB3AD,0x925D,0x925E,0x925F,
+0x9260,0xBEF1,0xB0D1,0x9261,0x9262,0x9263,0x9264,0x9265,
+0x9266,0xD2D6,0xCAE3,0xD7A5,0x9267,0xCDB6,0xB6B6,0xBFB9,
+0xD5DB,0x9268,0xB8A7,0xC5D7,0x9269,0x926A,0x926B,0xDED2,
+0xBFD9,0xC2D5,0xC7C0,0x926C,0xBBA4,0xB1A8,0x926D,0x926E,
+0xC5EA,0x926F,0x9270,0xC5FB,0xCCA7,0x9271,0x9272,0x9273,
+0x9274,0xB1A7,0x9275,0x9276,0x9277,0xB5D6,0x9278,0x9279,
+0x927A,0xC4A8,0x927B,0xDED3,0xD1BA,0xB3E9,0x927C,0xC3F2,
+0x927D,0x927E,0xB7F7,0x9280,0xD6F4,0xB5A3,0xB2F0,0xC4B4,
+0xC4E9,0xC0AD,0xDED4,0x9281,0xB0E8,0xC5C4,0xC1E0,0x9282,
+0xB9D5,0x9283,0xBEDC,0xCDD8,0xB0CE,0x9284,0xCDCF,0xDED6,
+0xBED0,0xD7BE,0xDED5,0xD5D0,0xB0DD,0x9285,0x9286,0xC4E2,
+0x9287,0x9288,0xC2A3,0xBCF0,0x9289,0xD3B5,0xC0B9,0xC5A1,
+0xB2A6,0xD4F1,0x928A,0x928B,0xC0A8,0xCAC3,0xDED7,0xD5FC,
+0x928C,0xB9B0,0x928D,0xC8AD,0xCBA9,0x928E,0xDED9,0xBFBD,
+0x928F,0x9290,0x9291,0x9292,0xC6B4,0xD7A7,0xCAB0,0xC4C3,
+0x9293,0xB3D6,0xB9D2,0x9294,0x9295,0x9296,0x9297,0xD6B8,
+0xEAFC,0xB0B4,0x9298,0x9299,0x929A,0x929B,0xBFE6,0x929C,
+0x929D,0xCCF4,0x929E,0x929F,0x92A0,0x92A1,0xCDDA,0x92A2,
+0x92A3,0x92A4,0xD6BF,0xC2CE,0x92A5,0xCECE,0xCCA2,0xD0AE,
+0xC4D3,0xB5B2,0xDED8,0xD5F5,0xBCB7,0xBBD3,0x92A6,0x92A7,
+0xB0A4,0x92A8,0xC5B2,0xB4EC,0x92A9,0x92AA,0x92AB,0xD5F1,
+0x92AC,0x92AD,0xEAFD,0x92AE,0x92AF,0x92B0,0x92B1,0x92B2,
+0x92B3,0xDEDA,0xCDA6,0x92B4,0x92B5,0xCDEC,0x92B6,0x92B7,
+0x92B8,0x92B9,0xCEE6,0xDEDC,0x92BA,0xCDB1,0xC0A6,0x92BB,
+0x92BC,0xD7BD,0x92BD,0xDEDB,0xB0C6,0xBAB4,0xC9D3,0xC4F3,
+0xBEE8,0x92BE,0x92BF,0x92C0,0x92C1,0xB2B6,0x92C2,0x92C3,
+0x92C4,0x92C5,0x92C6,0x92C7,0x92C8,0x92C9,0xC0CC,0xCBF0,
+0x92CA,0xBCF1,0xBBBB,0xB5B7,0x92CB,0x92CC,0x92CD,0xC5F5,
+0x92CE,0xDEE6,0x92CF,0x92D0,0x92D1,0xDEE3,0xBEDD,0x92D2,
+0x92D3,0xDEDF,0x92D4,0x92D5,0x92D6,0x92D7,0xB4B7,0xBDDD,
+0x92D8,0x92D9,0xDEE0,0xC4ED,0x92DA,0x92DB,0x92DC,0x92DD,
+0xCFC6,0x92DE,0xB5E0,0x92DF,0x92E0,0x92E1,0x92E2,0xB6DE,
+0xCADA,0xB5F4,0xDEE5,0x92E3,0xD5C6,0x92E4,0xDEE1,0xCCCD,
+0xC6FE,0x92E5,0xC5C5,0x92E6,0x92E7,0x92E8,0xD2B4,0x92E9,
+0xBEF2,0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF,0x92F0,
+0xC2D3,0x92F1,0xCCBD,0xB3B8,0x92F2,0xBDD3,0x92F3,0xBFD8,
+0xCDC6,0xD1DA,0xB4EB,0x92F4,0xDEE4,0xDEDD,0xDEE7,0x92F5,
+0xEAFE,0x92F6,0x92F7,0xC2B0,0xDEE2,0x92F8,0x92F9,0xD6C0,
+0xB5A7,0x92FA,0xB2F4,0x92FB,0xDEE8,0x92FC,0xDEF2,0x92FD,
+0x92FE,0x9340,0x9341,0x9342,0xDEED,0x9343,0xDEF1,0x9344,
+0x9345,0xC8E0,0x9346,0x9347,0x9348,0xD7E1,0xDEEF,0xC3E8,
+0xCCE1,0x9349,0xB2E5,0x934A,0x934B,0x934C,0xD2BE,0x934D,
+0x934E,0x934F,0x9350,0x9351,0x9352,0x9353,0xDEEE,0x9354,
+0xDEEB,0xCED5,0x9355,0xB4A7,0x9356,0x9357,0x9358,0x9359,
+0x935A,0xBFAB,0xBEBE,0x935B,0x935C,0xBDD2,0x935D,0x935E,
+0x935F,0x9360,0xDEE9,0x9361,0xD4AE,0x9362,0xDEDE,0x9363,
+0xDEEA,0x9364,0x9365,0x9366,0x9367,0xC0BF,0x9368,0xDEEC,
+0xB2F3,0xB8E9,0xC2A7,0x9369,0x936A,0xBDC1,0x936B,0x936C,
+0x936D,0x936E,0x936F,0xDEF5,0xDEF8,0x9370,0x9371,0xB2AB,
+0xB4A4,0x9372,0x9373,0xB4EA,0xC9A6,0x9374,0x9375,0x9376,
+0x9377,0x9378,0x9379,0xDEF6,0xCBD1,0x937A,0xB8E3,0x937B,
+0xDEF7,0xDEFA,0x937C,0x937D,0x937E,0x9380,0xDEF9,0x9381,
+0x9382,0x9383,0xCCC2,0x9384,0xB0E1,0xB4EE,0x9385,0x9386,
+0x9387,0x9388,0x9389,0x938A,0xE5BA,0x938B,0x938C,0x938D,
+0x938E,0x938F,0xD0AF,0x9390,0x9391,0xB2EB,0x9392,0xEBA1,
+0x9393,0xDEF4,0x9394,0x9395,0xC9E3,0xDEF3,0xB0DA,0xD2A1,
+0xB1F7,0x9396,0xCCAF,0x9397,0x9398,0x9399,0x939A,0x939B,
+0x939C,0x939D,0xDEF0,0x939E,0xCBA4,0x939F,0x93A0,0x93A1,
+0xD5AA,0x93A2,0x93A3,0x93A4,0x93A5,0x93A6,0xDEFB,0x93A7,
+0x93A8,0x93A9,0x93AA,0x93AB,0x93AC,0x93AD,0x93AE,0xB4DD,
+0x93AF,0xC4A6,0x93B0,0x93B1,0x93B2,0xDEFD,0x93B3,0x93B4,
+0x93B5,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,0x93BB,0x93BC,
+0xC3FE,0xC4A1,0xDFA1,0x93BD,0x93BE,0x93BF,0x93C0,0x93C1,
+0x93C2,0x93C3,0xC1CC,0x93C4,0xDEFC,0xBEEF,0x93C5,0xC6B2,
+0x93C6,0x93C7,0x93C8,0x93C9,0x93CA,0x93CB,0x93CC,0x93CD,
+0x93CE,0xB3C5,0xC8F6,0x93CF,0x93D0,0xCBBA,0xDEFE,0x93D1,
+0x93D2,0xDFA4,0x93D3,0x93D4,0x93D5,0x93D6,0xD7B2,0x93D7,
+0x93D8,0x93D9,0x93DA,0x93DB,0xB3B7,0x93DC,0x93DD,0x93DE,
+0x93DF,0xC1C3,0x93E0,0x93E1,0xC7CB,0xB2A5,0xB4E9,0x93E2,
+0xD7AB,0x93E3,0x93E4,0x93E5,0x93E6,0xC4EC,0x93E7,0xDFA2,
+0xDFA3,0x93E8,0xDFA5,0x93E9,0xBAB3,0x93EA,0x93EB,0x93EC,
+0xDFA6,0x93ED,0xC0DE,0x93EE,0x93EF,0xC9C3,0x93F0,0x93F1,
+0x93F2,0x93F3,0x93F4,0x93F5,0x93F6,0xB2D9,0xC7E6,0x93F7,
+0xDFA7,0x93F8,0xC7DC,0x93F9,0x93FA,0x93FB,0x93FC,0xDFA8,
+0xEBA2,0x93FD,0x93FE,0x9440,0x9441,0x9442,0xCBD3,0x9443,
+0x9444,0x9445,0xDFAA,0x9446,0xDFA9,0x9447,0xB2C1,0x9448,
+0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,0x944F,0x9450,
+0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457,0x9458,
+0x9459,0x945A,0x945B,0x945C,0x945D,0x945E,0x945F,0x9460,
+0xC5CA,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467,
+0x9468,0xDFAB,0x9469,0x946A,0x946B,0x946C,0x946D,0x946E,
+0x946F,0x9470,0xD4DC,0x9471,0x9472,0x9473,0x9474,0x9475,
+0xC8C1,0x9476,0x9477,0x9478,0x9479,0x947A,0x947B,0x947C,
+0x947D,0x947E,0x9480,0x9481,0x9482,0xDFAC,0x9483,0x9484,
+0x9485,0x9486,0x9487,0xBEF0,0x9488,0x9489,0xDFAD,0xD6A7,
+0x948A,0x948B,0x948C,0x948D,0xEAB7,0xEBB6,0xCAD5,0x948E,
+0xD8FC,0xB8C4,0x948F,0xB9A5,0x9490,0x9491,0xB7C5,0xD5FE,
+0x9492,0x9493,0x9494,0x9495,0x9496,0xB9CA,0x9497,0x9498,
+0xD0A7,0xF4CD,0x9499,0x949A,0xB5D0,0x949B,0x949C,0xC3F4,
+0x949D,0xBEC8,0x949E,0x949F,0x94A0,0xEBB7,0xB0BD,0x94A1,
+0x94A2,0xBDCC,0x94A3,0xC1B2,0x94A4,0xB1D6,0xB3A8,0x94A5,
+0x94A6,0x94A7,0xB8D2,0xC9A2,0x94A8,0x94A9,0xB6D8,0x94AA,
+0x94AB,0x94AC,0x94AD,0xEBB8,0xBEB4,0x94AE,0x94AF,0x94B0,
+0xCAFD,0x94B1,0xC7C3,0x94B2,0xD5FB,0x94B3,0x94B4,0xB7F3,
+0x94B5,0x94B6,0x94B7,0x94B8,0x94B9,0x94BA,0x94BB,0x94BC,
+0x94BD,0x94BE,0x94BF,0x94C0,0x94C1,0x94C2,0x94C3,0xCEC4,
+0x94C4,0x94C5,0x94C6,0xD5AB,0xB1F3,0x94C7,0x94C8,0x94C9,
+0xECB3,0xB0DF,0x94CA,0xECB5,0x94CB,0x94CC,0x94CD,0xB6B7,
+0x94CE,0xC1CF,0x94CF,0xF5FA,0xD0B1,0x94D0,0x94D1,0xD5E5,
+0x94D2,0xCED3,0x94D3,0x94D4,0xBDEF,0xB3E2,0x94D5,0xB8AB,
+0x94D6,0xD5B6,0x94D7,0xEDBD,0x94D8,0xB6CF,0x94D9,0xCBB9,
+0xD0C2,0x94DA,0x94DB,0x94DC,0x94DD,0x94DE,0x94DF,0x94E0,
+0x94E1,0xB7BD,0x94E2,0x94E3,0xECB6,0xCAA9,0x94E4,0x94E5,
+0x94E6,0xC5D4,0x94E7,0xECB9,0xECB8,0xC2C3,0xECB7,0x94E8,
+0x94E9,0x94EA,0x94EB,0xD0FD,0xECBA,0x94EC,0xECBB,0xD7E5,
+0x94ED,0x94EE,0xECBC,0x94EF,0x94F0,0x94F1,0xECBD,0xC6EC,
+0x94F2,0x94F3,0x94F4,0x94F5,0x94F6,0x94F7,0x94F8,0x94F9,
+0xCEDE,0x94FA,0xBCC8,0x94FB,0x94FC,0xC8D5,0xB5A9,0xBEC9,
+0xD6BC,0xD4E7,0x94FD,0x94FE,0xD1AE,0xD0F1,0xEAB8,0xEAB9,
+0xEABA,0xBAB5,0x9540,0x9541,0x9542,0x9543,0xCAB1,0xBFF5,
+0x9544,0x9545,0xCDFA,0x9546,0x9547,0x9548,0x9549,0x954A,
+0xEAC0,0x954B,0xB0BA,0xEABE,0x954C,0x954D,0xC0A5,0x954E,
+0x954F,0x9550,0xEABB,0x9551,0xB2FD,0x9552,0xC3F7,0xBBE8,
+0x9553,0x9554,0x9555,0xD2D7,0xCEF4,0xEABF,0x9556,0x9557,
+0x9558,0xEABC,0x9559,0x955A,0x955B,0xEAC3,0x955C,0xD0C7,
+0xD3B3,0x955D,0x955E,0x955F,0x9560,0xB4BA,0x9561,0xC3C1,
+0xD7F2,0x9562,0x9563,0x9564,0x9565,0xD5D1,0x9566,0xCAC7,
+0x9567,0xEAC5,0x9568,0x9569,0xEAC4,0xEAC7,0xEAC6,0x956A,
+0x956B,0x956C,0x956D,0x956E,0xD6E7,0x956F,0xCFD4,0x9570,
+0x9571,0xEACB,0x9572,0xBBCE,0x9573,0x9574,0x9575,0x9576,
+0x9577,0x9578,0x9579,0xBDFA,0xC9CE,0x957A,0x957B,0xEACC,
+0x957C,0x957D,0xC9B9,0xCFFE,0xEACA,0xD4CE,0xEACD,0xEACF,
+0x957E,0x9580,0xCDED,0x9581,0x9582,0x9583,0x9584,0xEAC9,
+0x9585,0xEACE,0x9586,0x9587,0xCEEE,0x9588,0xBBDE,0x9589,
+0xB3BF,0x958A,0x958B,0x958C,0x958D,0x958E,0xC6D5,0xBEB0,
+0xCEFA,0x958F,0x9590,0x9591,0xC7E7,0x9592,0xBEA7,0xEAD0,
+0x9593,0x9594,0xD6C7,0x9595,0x9596,0x9597,0xC1C0,0x9598,
+0x9599,0x959A,0xD4DD,0x959B,0xEAD1,0x959C,0x959D,0xCFBE,
+0x959E,0x959F,0x95A0,0x95A1,0xEAD2,0x95A2,0x95A3,0x95A4,
+0x95A5,0xCAEE,0x95A6,0x95A7,0x95A8,0x95A9,0xC5AF,0xB0B5,
+0x95AA,0x95AB,0x95AC,0x95AD,0x95AE,0xEAD4,0x95AF,0x95B0,
+0x95B1,0x95B2,0x95B3,0x95B4,0x95B5,0x95B6,0x95B7,0xEAD3,
+0xF4DF,0x95B8,0x95B9,0x95BA,0x95BB,0x95BC,0xC4BA,0x95BD,
+0x95BE,0x95BF,0x95C0,0x95C1,0xB1A9,0x95C2,0x95C3,0x95C4,
+0x95C5,0xE5DF,0x95C6,0x95C7,0x95C8,0x95C9,0xEAD5,0x95CA,
+0x95CB,0x95CC,0x95CD,0x95CE,0x95CF,0x95D0,0x95D1,0x95D2,
+0x95D3,0x95D4,0x95D5,0x95D6,0x95D7,0x95D8,0x95D9,0x95DA,
+0x95DB,0x95DC,0x95DD,0x95DE,0x95DF,0x95E0,0x95E1,0x95E2,
+0x95E3,0xCAEF,0x95E4,0xEAD6,0xEAD7,0xC6D8,0x95E5,0x95E6,
+0x95E7,0x95E8,0x95E9,0x95EA,0x95EB,0x95EC,0xEAD8,0x95ED,
+0x95EE,0xEAD9,0x95EF,0x95F0,0x95F1,0x95F2,0x95F3,0x95F4,
+0xD4BB,0x95F5,0xC7FA,0xD2B7,0xB8FC,0x95F6,0x95F7,0xEAC2,
+0x95F8,0xB2DC,0x95F9,0x95FA,0xC2FC,0x95FB,0xD4F8,0xCCE6,
+0xD7EE,0x95FC,0x95FD,0x95FE,0x9640,0x9641,0x9642,0x9643,
+0xD4C2,0xD3D0,0xEBC3,0xC5F3,0x9644,0xB7FE,0x9645,0x9646,
+0xEBD4,0x9647,0x9648,0x9649,0xCBB7,0xEBDE,0x964A,0xC0CA,
+0x964B,0x964C,0x964D,0xCDFB,0x964E,0xB3AF,0x964F,0xC6DA,
+0x9650,0x9651,0x9652,0x9653,0x9654,0x9655,0xEBFC,0x9656,
+0xC4BE,0x9657,0xCEB4,0xC4A9,0xB1BE,0xD4FD,0x9658,0xCAF5,
+0x9659,0xD6EC,0x965A,0x965B,0xC6D3,0xB6E4,0x965C,0x965D,
+0x965E,0x965F,0xBBFA,0x9660,0x9661,0xD0E0,0x9662,0x9663,
+0xC9B1,0x9664,0xD4D3,0xC8A8,0x9665,0x9666,0xB8CB,0x9667,
+0xE8BE,0xC9BC,0x9668,0x9669,0xE8BB,0x966A,0xC0EE,0xD0D3,
+0xB2C4,0xB4E5,0x966B,0xE8BC,0x966C,0x966D,0xD5C8,0x966E,
+0x966F,0x9670,0x9671,0x9672,0xB6C5,0x9673,0xE8BD,0xCAF8,
+0xB8DC,0xCCF5,0x9674,0x9675,0x9676,0xC0B4,0x9677,0x9678,
+0xD1EE,0xE8BF,0xE8C2,0x9679,0x967A,0xBABC,0x967B,0xB1AD,
+0xBDDC,0x967C,0xEABD,0xE8C3,0x967D,0xE8C6,0x967E,0xE8CB,
+0x9680,0x9681,0x9682,0x9683,0xE8CC,0x9684,0xCBC9,0xB0E5,
+0x9685,0xBCAB,0x9686,0x9687,0xB9B9,0x9688,0x9689,0xE8C1,
+0x968A,0xCDF7,0x968B,0xE8CA,0x968C,0x968D,0x968E,0x968F,
+0xCEF6,0x9690,0x9691,0x9692,0x9693,0xD5ED,0x9694,0xC1D6,
+0xE8C4,0x9695,0xC3B6,0x9696,0xB9FB,0xD6A6,0xE8C8,0x9697,
+0x9698,0x9699,0xCAE0,0xD4E6,0x969A,0xE8C0,0x969B,0xE8C5,
+0xE8C7,0x969C,0xC7B9,0xB7E3,0x969D,0xE8C9,0x969E,0xBFDD,
+0xE8D2,0x969F,0x96A0,0xE8D7,0x96A1,0xE8D5,0xBCDC,0xBCCF,
+0xE8DB,0x96A2,0x96A3,0x96A4,0x96A5,0x96A6,0x96A7,0x96A8,
+0x96A9,0xE8DE,0x96AA,0xE8DA,0xB1FA,0x96AB,0x96AC,0x96AD,
+0x96AE,0x96AF,0x96B0,0x96B1,0x96B2,0x96B3,0x96B4,0xB0D8,
+0xC4B3,0xB8CC,0xC6E2,0xC8BE,0xC8E1,0x96B5,0x96B6,0x96B7,
+0xE8CF,0xE8D4,0xE8D6,0x96B8,0xB9F1,0xE8D8,0xD7F5,0x96B9,
+0xC4FB,0x96BA,0xE8DC,0x96BB,0x96BC,0xB2E9,0x96BD,0x96BE,
+0x96BF,0xE8D1,0x96C0,0x96C1,0xBCED,0x96C2,0x96C3,0xBFC2,
+0xE8CD,0xD6F9,0x96C4,0xC1F8,0xB2F1,0x96C5,0x96C6,0x96C7,
+0x96C8,0x96C9,0x96CA,0x96CB,0x96CC,0xE8DF,0x96CD,0xCAC1,
+0xE8D9,0x96CE,0x96CF,0x96D0,0x96D1,0xD5A4,0x96D2,0xB1EA,
+0xD5BB,0xE8CE,0xE8D0,0xB6B0,0xE8D3,0x96D3,0xE8DD,0xC0B8,
+0x96D4,0xCAF7,0x96D5,0xCBA8,0x96D6,0x96D7,0xC6DC,0xC0F5,
+0x96D8,0x96D9,0x96DA,0x96DB,0x96DC,0xE8E9,0x96DD,0x96DE,
+0x96DF,0xD0A3,0x96E0,0x96E1,0x96E2,0x96E3,0x96E4,0x96E5,
+0x96E6,0xE8F2,0xD6EA,0x96E7,0x96E8,0x96E9,0x96EA,0x96EB,
+0x96EC,0x96ED,0xE8E0,0xE8E1,0x96EE,0x96EF,0x96F0,0xD1F9,
+0xBACB,0xB8F9,0x96F1,0x96F2,0xB8F1,0xD4D4,0xE8EF,0x96F3,
+0xE8EE,0xE8EC,0xB9F0,0xCCD2,0xE8E6,0xCEA6,0xBFF2,0x96F4,
+0xB0B8,0xE8F1,0xE8F0,0x96F5,0xD7C0,0x96F6,0xE8E4,0x96F7,
+0xCDA9,0xC9A3,0x96F8,0xBBB8,0xBDDB,0xE8EA,0x96F9,0x96FA,
+0x96FB,0x96FC,0x96FD,0x96FE,0x9740,0x9741,0x9742,0x9743,
+0xE8E2,0xE8E3,0xE8E5,0xB5B5,0xE8E7,0xC7C5,0xE8EB,0xE8ED,
+0xBDB0,0xD7AE,0x9744,0xE8F8,0x9745,0x9746,0x9747,0x9748,
+0x9749,0x974A,0x974B,0x974C,0xE8F5,0x974D,0xCDB0,0xE8F6,
+0x974E,0x974F,0x9750,0x9751,0x9752,0x9753,0x9754,0x9755,
+0x9756,0xC1BA,0x9757,0xE8E8,0x9758,0xC3B7,0xB0F0,0x9759,
+0x975A,0x975B,0x975C,0x975D,0x975E,0x975F,0x9760,0xE8F4,
+0x9761,0x9762,0x9763,0xE8F7,0x9764,0x9765,0x9766,0xB9A3,
+0x9767,0x9768,0x9769,0x976A,0x976B,0x976C,0x976D,0x976E,
+0x976F,0x9770,0xC9D2,0x9771,0x9772,0x9773,0xC3CE,0xCEE0,
+0xC0E6,0x9774,0x9775,0x9776,0x9777,0xCBF3,0x9778,0xCCDD,
+0xD0B5,0x9779,0x977A,0xCAE1,0x977B,0xE8F3,0x977C,0x977D,
+0x977E,0x9780,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786,
+0xBCEC,0x9787,0xE8F9,0x9788,0x9789,0x978A,0x978B,0x978C,
+0x978D,0xC3DE,0x978E,0xC6E5,0x978F,0xB9F7,0x9790,0x9791,
+0x9792,0x9793,0xB0F4,0x9794,0x9795,0xD7D8,0x9796,0x9797,
+0xBCAC,0x9798,0xC5EF,0x9799,0x979A,0x979B,0x979C,0x979D,
+0xCCC4,0x979E,0x979F,0xE9A6,0x97A0,0x97A1,0x97A2,0x97A3,
+0x97A4,0x97A5,0x97A6,0x97A7,0x97A8,0x97A9,0xC9AD,0x97AA,
+0xE9A2,0xC0E2,0x97AB,0x97AC,0x97AD,0xBFC3,0x97AE,0x97AF,
+0x97B0,0xE8FE,0xB9D7,0x97B1,0xE8FB,0x97B2,0x97B3,0x97B4,
+0x97B5,0xE9A4,0x97B6,0x97B7,0x97B8,0xD2CE,0x97B9,0x97BA,
+0x97BB,0x97BC,0x97BD,0xE9A3,0x97BE,0xD6B2,0xD7B5,0x97BF,
+0xE9A7,0x97C0,0xBDB7,0x97C1,0x97C2,0x97C3,0x97C4,0x97C5,
+0x97C6,0x97C7,0x97C8,0x97C9,0x97CA,0x97CB,0x97CC,0xE8FC,
+0xE8FD,0x97CD,0x97CE,0x97CF,0xE9A1,0x97D0,0x97D1,0x97D2,
+0x97D3,0x97D4,0x97D5,0x97D6,0x97D7,0xCDD6,0x97D8,0x97D9,
+0xD2AC,0x97DA,0x97DB,0x97DC,0xE9B2,0x97DD,0x97DE,0x97DF,
+0x97E0,0xE9A9,0x97E1,0x97E2,0x97E3,0xB4AA,0x97E4,0xB4BB,
+0x97E5,0x97E6,0xE9AB,0x97E7,0x97E8,0x97E9,0x97EA,0x97EB,
+0x97EC,0x97ED,0x97EE,0x97EF,0x97F0,0x97F1,0x97F2,0x97F3,
+0x97F4,0x97F5,0x97F6,0x97F7,0xD0A8,0x97F8,0x97F9,0xE9A5,
+0x97FA,0x97FB,0xB3FE,0x97FC,0x97FD,0xE9AC,0xC0E3,0x97FE,
+0xE9AA,0x9840,0x9841,0xE9B9,0x9842,0x9843,0xE9B8,0x9844,
+0x9845,0x9846,0x9847,0xE9AE,0x9848,0x9849,0xE8FA,0x984A,
+0x984B,0xE9A8,0x984C,0x984D,0x984E,0x984F,0x9850,0xBFAC,
+0xE9B1,0xE9BA,0x9851,0x9852,0xC2A5,0x9853,0x9854,0x9855,
+0xE9AF,0x9856,0xB8C5,0x9857,0xE9AD,0x9858,0xD3DC,0xE9B4,
+0xE9B5,0xE9B7,0x9859,0x985A,0x985B,0xE9C7,0x985C,0x985D,
+0x985E,0x985F,0x9860,0x9861,0xC0C6,0xE9C5,0x9862,0x9863,
+0xE9B0,0x9864,0x9865,0xE9BB,0xB0F1,0x9866,0x9867,0x9868,
+0x9869,0x986A,0x986B,0x986C,0x986D,0x986E,0x986F,0xE9BC,
+0xD5A5,0x9870,0x9871,0xE9BE,0x9872,0xE9BF,0x9873,0x9874,
+0x9875,0xE9C1,0x9876,0x9877,0xC1F1,0x9878,0x9879,0xC8B6,
+0x987A,0x987B,0x987C,0xE9BD,0x987D,0x987E,0x9880,0x9881,
+0x9882,0xE9C2,0x9883,0x9884,0x9885,0x9886,0x9887,0x9888,
+0x9889,0x988A,0xE9C3,0x988B,0xE9B3,0x988C,0xE9B6,0x988D,
+0xBBB1,0x988E,0x988F,0x9890,0xE9C0,0x9891,0x9892,0x9893,
+0x9894,0x9895,0x9896,0xBCF7,0x9897,0x9898,0x9899,0xE9C4,
+0xE9C6,0x989A,0x989B,0x989C,0x989D,0x989E,0x989F,0x98A0,
+0x98A1,0x98A2,0x98A3,0x98A4,0x98A5,0xE9CA,0x98A6,0x98A7,
+0x98A8,0x98A9,0xE9CE,0x98AA,0x98AB,0x98AC,0x98AD,0x98AE,
+0x98AF,0x98B0,0x98B1,0x98B2,0x98B3,0xB2DB,0x98B4,0xE9C8,
+0x98B5,0x98B6,0x98B7,0x98B8,0x98B9,0x98BA,0x98BB,0x98BC,
+0x98BD,0x98BE,0xB7AE,0x98BF,0x98C0,0x98C1,0x98C2,0x98C3,
+0x98C4,0x98C5,0x98C6,0x98C7,0x98C8,0x98C9,0x98CA,0xE9CB,
+0xE9CC,0x98CB,0x98CC,0x98CD,0x98CE,0x98CF,0x98D0,0xD5C1,
+0x98D1,0xC4A3,0x98D2,0x98D3,0x98D4,0x98D5,0x98D6,0x98D7,
+0xE9D8,0x98D8,0xBAE1,0x98D9,0x98DA,0x98DB,0x98DC,0xE9C9,
+0x98DD,0xD3A3,0x98DE,0x98DF,0x98E0,0xE9D4,0x98E1,0x98E2,
+0x98E3,0x98E4,0x98E5,0x98E6,0x98E7,0xE9D7,0xE9D0,0x98E8,
+0x98E9,0x98EA,0x98EB,0x98EC,0xE9CF,0x98ED,0x98EE,0xC7C1,
+0x98EF,0x98F0,0x98F1,0x98F2,0x98F3,0x98F4,0x98F5,0x98F6,
+0xE9D2,0x98F7,0x98F8,0x98F9,0x98FA,0x98FB,0x98FC,0x98FD,
+0xE9D9,0xB3C8,0x98FE,0xE9D3,0x9940,0x9941,0x9942,0x9943,
+0x9944,0xCFF0,0x9945,0x9946,0x9947,0xE9CD,0x9948,0x9949,
+0x994A,0x994B,0x994C,0x994D,0x994E,0x994F,0x9950,0x9951,
+0x9952,0xB3F7,0x9953,0x9954,0x9955,0x9956,0x9957,0x9958,
+0x9959,0xE9D6,0x995A,0x995B,0xE9DA,0x995C,0x995D,0x995E,
+0xCCB4,0x995F,0x9960,0x9961,0xCFAD,0x9962,0x9963,0x9964,
+0x9965,0x9966,0x9967,0x9968,0x9969,0x996A,0xE9D5,0x996B,
+0xE9DC,0xE9DB,0x996C,0x996D,0x996E,0x996F,0x9970,0xE9DE,
+0x9971,0x9972,0x9973,0x9974,0x9975,0x9976,0x9977,0x9978,
+0xE9D1,0x9979,0x997A,0x997B,0x997C,0x997D,0x997E,0x9980,
+0x9981,0xE9DD,0x9982,0xE9DF,0xC3CA,0x9983,0x9984,0x9985,
+0x9986,0x9987,0x9988,0x9989,0x998A,0x998B,0x998C,0x998D,
+0x998E,0x998F,0x9990,0x9991,0x9992,0x9993,0x9994,0x9995,
+0x9996,0x9997,0x9998,0x9999,0x999A,0x999B,0x999C,0x999D,
+0x999E,0x999F,0x99A0,0x99A1,0x99A2,0x99A3,0x99A4,0x99A5,
+0x99A6,0x99A7,0x99A8,0x99A9,0x99AA,0x99AB,0x99AC,0x99AD,
+0x99AE,0x99AF,0x99B0,0x99B1,0x99B2,0x99B3,0x99B4,0x99B5,
+0x99B6,0x99B7,0x99B8,0x99B9,0x99BA,0x99BB,0x99BC,0x99BD,
+0x99BE,0x99BF,0x99C0,0x99C1,0x99C2,0x99C3,0x99C4,0x99C5,
+0x99C6,0x99C7,0x99C8,0x99C9,0x99CA,0x99CB,0x99CC,0x99CD,
+0x99CE,0x99CF,0x99D0,0x99D1,0x99D2,0x99D3,0x99D4,0x99D5,
+0x99D6,0x99D7,0x99D8,0x99D9,0x99DA,0x99DB,0x99DC,0x99DD,
+0x99DE,0x99DF,0x99E0,0x99E1,0x99E2,0x99E3,0x99E4,0x99E5,
+0x99E6,0x99E7,0x99E8,0x99E9,0x99EA,0x99EB,0x99EC,0x99ED,
+0x99EE,0x99EF,0x99F0,0x99F1,0x99F2,0x99F3,0x99F4,0x99F5,
+0xC7B7,0xB4CE,0xBBB6,0xD0C0,0xECA3,0x99F6,0x99F7,0xC5B7,
+0x99F8,0x99F9,0x99FA,0x99FB,0x99FC,0x99FD,0x99FE,0x9A40,
+0x9A41,0x9A42,0xD3FB,0x9A43,0x9A44,0x9A45,0x9A46,0xECA4,
+0x9A47,0xECA5,0xC6DB,0x9A48,0x9A49,0x9A4A,0xBFEE,0x9A4B,
+0x9A4C,0x9A4D,0x9A4E,0xECA6,0x9A4F,0x9A50,0xECA7,0xD0AA,
+0x9A51,0xC7B8,0x9A52,0x9A53,0xB8E8,0x9A54,0x9A55,0x9A56,
+0x9A57,0x9A58,0x9A59,0x9A5A,0x9A5B,0x9A5C,0x9A5D,0x9A5E,
+0x9A5F,0xECA8,0x9A60,0x9A61,0x9A62,0x9A63,0x9A64,0x9A65,
+0x9A66,0x9A67,0xD6B9,0xD5FD,0xB4CB,0xB2BD,0xCEE4,0xC6E7,
+0x9A68,0x9A69,0xCDE1,0x9A6A,0x9A6B,0x9A6C,0x9A6D,0x9A6E,
+0x9A6F,0x9A70,0x9A71,0x9A72,0x9A73,0x9A74,0x9A75,0x9A76,
+0x9A77,0xB4F5,0x9A78,0xCBC0,0xBCDF,0x9A79,0x9A7A,0x9A7B,
+0x9A7C,0xE9E2,0xE9E3,0xD1EA,0xE9E5,0x9A7D,0xB4F9,0xE9E4,
+0x9A7E,0xD1B3,0xCAE2,0xB2D0,0x9A80,0xE9E8,0x9A81,0x9A82,
+0x9A83,0x9A84,0xE9E6,0xE9E7,0x9A85,0x9A86,0xD6B3,0x9A87,
+0x9A88,0x9A89,0xE9E9,0xE9EA,0x9A8A,0x9A8B,0x9A8C,0x9A8D,
+0x9A8E,0xE9EB,0x9A8F,0x9A90,0x9A91,0x9A92,0x9A93,0x9A94,
+0x9A95,0x9A96,0xE9EC,0x9A97,0x9A98,0x9A99,0x9A9A,0x9A9B,
+0x9A9C,0x9A9D,0x9A9E,0xECAF,0xC5B9,0xB6CE,0x9A9F,0xD2F3,
+0x9AA0,0x9AA1,0x9AA2,0x9AA3,0x9AA4,0x9AA5,0x9AA6,0xB5EE,
+0x9AA7,0xBBD9,0xECB1,0x9AA8,0x9AA9,0xD2E3,0x9AAA,0x9AAB,
+0x9AAC,0x9AAD,0x9AAE,0xCEE3,0x9AAF,0xC4B8,0x9AB0,0xC3BF,
+0x9AB1,0x9AB2,0xB6BE,0xD8B9,0xB1C8,0xB1CF,0xB1D1,0xC5FE,
+0x9AB3,0xB1D0,0x9AB4,0xC3AB,0x9AB5,0x9AB6,0x9AB7,0x9AB8,
+0x9AB9,0xD5B1,0x9ABA,0x9ABB,0x9ABC,0x9ABD,0x9ABE,0x9ABF,
+0x9AC0,0x9AC1,0xEBA4,0xBAC1,0x9AC2,0x9AC3,0x9AC4,0xCCBA,
+0x9AC5,0x9AC6,0x9AC7,0xEBA5,0x9AC8,0xEBA7,0x9AC9,0x9ACA,
+0x9ACB,0xEBA8,0x9ACC,0x9ACD,0x9ACE,0xEBA6,0x9ACF,0x9AD0,
+0x9AD1,0x9AD2,0x9AD3,0x9AD4,0x9AD5,0xEBA9,0xEBAB,0xEBAA,
+0x9AD6,0x9AD7,0x9AD8,0x9AD9,0x9ADA,0xEBAC,0x9ADB,0xCACF,
+0xD8B5,0xC3F1,0x9ADC,0xC3A5,0xC6F8,0xEBAD,0xC4CA,0x9ADD,
+0xEBAE,0xEBAF,0xEBB0,0xB7D5,0x9ADE,0x9ADF,0x9AE0,0xB7FA,
+0x9AE1,0xEBB1,0xC7E2,0x9AE2,0xEBB3,0x9AE3,0xBAA4,0xD1F5,
+0xB0B1,0xEBB2,0xEBB4,0x9AE4,0x9AE5,0x9AE6,0xB5AA,0xC2C8,
+0xC7E8,0x9AE7,0xEBB5,0x9AE8,0xCBAE,0xE3DF,0x9AE9,0x9AEA,
+0xD3C0,0x9AEB,0x9AEC,0x9AED,0x9AEE,0xD9DB,0x9AEF,0x9AF0,
+0xCDA1,0xD6AD,0xC7F3,0x9AF1,0x9AF2,0x9AF3,0xD9E0,0xBBE3,
+0x9AF4,0xBABA,0xE3E2,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AF9,
+0xCFAB,0x9AFA,0x9AFB,0x9AFC,0xE3E0,0xC9C7,0x9AFD,0xBAB9,
+0x9AFE,0x9B40,0x9B41,0xD1B4,0xE3E1,0xC8EA,0xB9AF,0xBDAD,
+0xB3D8,0xCEDB,0x9B42,0x9B43,0xCCC0,0x9B44,0x9B45,0x9B46,
+0xE3E8,0xE3E9,0xCDF4,0x9B47,0x9B48,0x9B49,0x9B4A,0x9B4B,
+0xCCAD,0x9B4C,0xBCB3,0x9B4D,0xE3EA,0x9B4E,0xE3EB,0x9B4F,
+0x9B50,0xD0DA,0x9B51,0x9B52,0x9B53,0xC6FB,0xB7DA,0x9B54,
+0x9B55,0xC7DF,0xD2CA,0xCED6,0x9B56,0xE3E4,0xE3EC,0x9B57,
+0xC9F2,0xB3C1,0x9B58,0x9B59,0xE3E7,0x9B5A,0x9B5B,0xC6E3,
+0xE3E5,0x9B5C,0x9B5D,0xEDB3,0xE3E6,0x9B5E,0x9B5F,0x9B60,
+0x9B61,0xC9B3,0x9B62,0xC5E6,0x9B63,0x9B64,0x9B65,0xB9B5,
+0x9B66,0xC3BB,0x9B67,0xE3E3,0xC5BD,0xC1A4,0xC2D9,0xB2D7,
+0x9B68,0xE3ED,0xBBA6,0xC4AD,0x9B69,0xE3F0,0xBEDA,0x9B6A,
+0x9B6B,0xE3FB,0xE3F5,0xBAD3,0x9B6C,0x9B6D,0x9B6E,0x9B6F,
+0xB7D0,0xD3CD,0x9B70,0xD6CE,0xD5D3,0xB9C1,0xD5B4,0xD1D8,
+0x9B71,0x9B72,0x9B73,0x9B74,0xD0B9,0xC7F6,0x9B75,0x9B76,
+0x9B77,0xC8AA,0xB2B4,0x9B78,0xC3DA,0x9B79,0x9B7A,0x9B7B,
+0xE3EE,0x9B7C,0x9B7D,0xE3FC,0xE3EF,0xB7A8,0xE3F7,0xE3F4,
+0x9B7E,0x9B80,0x9B81,0xB7BA,0x9B82,0x9B83,0xC5A2,0x9B84,
+0xE3F6,0xC5DD,0xB2A8,0xC6FC,0x9B85,0xC4E0,0x9B86,0x9B87,
+0xD7A2,0x9B88,0xC0E1,0xE3F9,0x9B89,0x9B8A,0xE3FA,0xE3FD,
+0xCCA9,0xE3F3,0x9B8B,0xD3BE,0x9B8C,0xB1C3,0xEDB4,0xE3F1,
+0xE3F2,0x9B8D,0xE3F8,0xD0BA,0xC6C3,0xD4F3,0xE3FE,0x9B8E,
+0x9B8F,0xBDE0,0x9B90,0x9B91,0xE4A7,0x9B92,0x9B93,0xE4A6,
+0x9B94,0x9B95,0x9B96,0xD1F3,0xE4A3,0x9B97,0xE4A9,0x9B98,
+0x9B99,0x9B9A,0xC8F7,0x9B9B,0x9B9C,0x9B9D,0x9B9E,0xCFB4,
+0x9B9F,0xE4A8,0xE4AE,0xC2E5,0x9BA0,0x9BA1,0xB6B4,0x9BA2,
+0x9BA3,0x9BA4,0x9BA5,0x9BA6,0x9BA7,0xBDF2,0x9BA8,0xE4A2,
+0x9BA9,0x9BAA,0xBAE9,0xE4AA,0x9BAB,0x9BAC,0xE4AC,0x9BAD,
+0x9BAE,0xB6FD,0xD6DE,0xE4B2,0x9BAF,0xE4AD,0x9BB0,0x9BB1,
+0x9BB2,0xE4A1,0x9BB3,0xBBEE,0xCDDD,0xC7A2,0xC5C9,0x9BB4,
+0x9BB5,0xC1F7,0x9BB6,0xE4A4,0x9BB7,0xC7B3,0xBDAC,0xBDBD,
+0xE4A5,0x9BB8,0xD7C7,0xB2E2,0x9BB9,0xE4AB,0xBCC3,0xE4AF,
+0x9BBA,0xBBEB,0xE4B0,0xC5A8,0xE4B1,0x9BBB,0x9BBC,0x9BBD,
+0x9BBE,0xD5E3,0xBFA3,0x9BBF,0xE4BA,0x9BC0,0xE4B7,0x9BC1,
+0xE4BB,0x9BC2,0x9BC3,0xE4BD,0x9BC4,0x9BC5,0xC6D6,0x9BC6,
+0x9BC7,0xBAC6,0xC0CB,0x9BC8,0x9BC9,0x9BCA,0xB8A1,0xE4B4,
+0x9BCB,0x9BCC,0x9BCD,0x9BCE,0xD4A1,0x9BCF,0x9BD0,0xBAA3,
+0xBDFE,0x9BD1,0x9BD2,0x9BD3,0xE4BC,0x9BD4,0x9BD5,0x9BD6,
+0x9BD7,0x9BD8,0xCDBF,0x9BD9,0x9BDA,0xC4F9,0x9BDB,0x9BDC,
+0xCFFB,0xC9E6,0x9BDD,0x9BDE,0xD3BF,0x9BDF,0xCFD1,0x9BE0,
+0x9BE1,0xE4B3,0x9BE2,0xE4B8,0xE4B9,0xCCE9,0x9BE3,0x9BE4,
+0x9BE5,0x9BE6,0x9BE7,0xCCCE,0x9BE8,0xC0D4,0xE4B5,0xC1B0,
+0xE4B6,0xCED0,0x9BE9,0xBBC1,0xB5D3,0x9BEA,0xC8F3,0xBDA7,
+0xD5C7,0xC9AC,0xB8A2,0xE4CA,0x9BEB,0x9BEC,0xE4CC,0xD1C4,
+0x9BED,0x9BEE,0xD2BA,0x9BEF,0x9BF0,0xBAAD,0x9BF1,0x9BF2,
+0xBAD4,0x9BF3,0x9BF4,0x9BF5,0x9BF6,0x9BF7,0x9BF8,0xE4C3,
+0xB5ED,0x9BF9,0x9BFA,0x9BFB,0xD7CD,0xE4C0,0xCFFD,0xE4BF,
+0x9BFC,0x9BFD,0x9BFE,0xC1DC,0xCCCA,0x9C40,0x9C41,0x9C42,
+0x9C43,0xCAE7,0x9C44,0x9C45,0x9C46,0x9C47,0xC4D7,0x9C48,
+0xCCD4,0xE4C8,0x9C49,0x9C4A,0x9C4B,0xE4C7,0xE4C1,0x9C4C,
+0xE4C4,0xB5AD,0x9C4D,0x9C4E,0xD3D9,0x9C4F,0xE4C6,0x9C50,
+0x9C51,0x9C52,0x9C53,0xD2F9,0xB4E3,0x9C54,0xBBB4,0x9C55,
+0x9C56,0xC9EE,0x9C57,0xB4BE,0x9C58,0x9C59,0x9C5A,0xBBEC,
+0x9C5B,0xD1CD,0x9C5C,0xCCED,0xEDB5,0x9C5D,0x9C5E,0x9C5F,
+0x9C60,0x9C61,0x9C62,0x9C63,0x9C64,0xC7E5,0x9C65,0x9C66,
+0x9C67,0x9C68,0xD4A8,0x9C69,0xE4CB,0xD7D5,0xE4C2,0x9C6A,
+0xBDA5,0xE4C5,0x9C6B,0x9C6C,0xD3E6,0x9C6D,0xE4C9,0xC9F8,
+0x9C6E,0x9C6F,0xE4BE,0x9C70,0x9C71,0xD3E5,0x9C72,0x9C73,
+0xC7FE,0xB6C9,0x9C74,0xD4FC,0xB2B3,0xE4D7,0x9C75,0x9C76,
+0x9C77,0xCEC2,0x9C78,0xE4CD,0x9C79,0xCEBC,0x9C7A,0xB8DB,
+0x9C7B,0x9C7C,0xE4D6,0x9C7D,0xBFCA,0x9C7E,0x9C80,0x9C81,
+0xD3CE,0x9C82,0xC3EC,0x9C83,0x9C84,0x9C85,0x9C86,0x9C87,
+0x9C88,0x9C89,0x9C8A,0xC5C8,0xE4D8,0x9C8B,0x9C8C,0x9C8D,
+0x9C8E,0x9C8F,0x9C90,0x9C91,0x9C92,0xCDC4,0xE4CF,0x9C93,
+0x9C94,0x9C95,0x9C96,0xE4D4,0xE4D5,0x9C97,0xBAFE,0x9C98,
+0xCFE6,0x9C99,0x9C9A,0xD5BF,0x9C9B,0x9C9C,0x9C9D,0xE4D2,
+0x9C9E,0x9C9F,0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA4,0x9CA5,
+0x9CA6,0x9CA7,0x9CA8,0xE4D0,0x9CA9,0x9CAA,0xE4CE,0x9CAB,
+0x9CAC,0x9CAD,0x9CAE,0x9CAF,0x9CB0,0x9CB1,0x9CB2,0x9CB3,
+0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CB8,0x9CB9,0xCDE5,0xCAAA,
+0x9CBA,0x9CBB,0x9CBC,0xC0A3,0x9CBD,0xBDA6,0xE4D3,0x9CBE,
+0x9CBF,0xB8C8,0x9CC0,0x9CC1,0x9CC2,0x9CC3,0x9CC4,0xE4E7,
+0xD4B4,0x9CC5,0x9CC6,0x9CC7,0x9CC8,0x9CC9,0x9CCA,0x9CCB,
+0xE4DB,0x9CCC,0x9CCD,0x9CCE,0xC1EF,0x9CCF,0x9CD0,0xE4E9,
+0x9CD1,0x9CD2,0xD2E7,0x9CD3,0x9CD4,0xE4DF,0x9CD5,0xE4E0,
+0x9CD6,0x9CD7,0xCFAA,0x9CD8,0x9CD9,0x9CDA,0x9CDB,0xCBDD,
+0x9CDC,0xE4DA,0xE4D1,0x9CDD,0xE4E5,0x9CDE,0xC8DC,0xE4E3,
+0x9CDF,0x9CE0,0xC4E7,0xE4E2,0x9CE1,0xE4E1,0x9CE2,0x9CE3,
+0x9CE4,0xB3FC,0xE4E8,0x9CE5,0x9CE6,0x9CE7,0x9CE8,0xB5E1,
+0x9CE9,0x9CEA,0x9CEB,0xD7CC,0x9CEC,0x9CED,0x9CEE,0xE4E6,
+0x9CEF,0xBBAC,0x9CF0,0xD7D2,0xCCCF,0xEBF8,0x9CF1,0xE4E4,
+0x9CF2,0x9CF3,0xB9F6,0x9CF4,0x9CF5,0x9CF6,0xD6CD,0xE4D9,
+0xE4DC,0xC2FA,0xE4DE,0x9CF7,0xC2CB,0xC0C4,0xC2D0,0x9CF8,
+0xB1F5,0xCCB2,0x9CF9,0x9CFA,0x9CFB,0x9CFC,0x9CFD,0x9CFE,
+0x9D40,0x9D41,0x9D42,0x9D43,0xB5CE,0x9D44,0x9D45,0x9D46,
+0x9D47,0xE4EF,0x9D48,0x9D49,0x9D4A,0x9D4B,0x9D4C,0x9D4D,
+0x9D4E,0x9D4F,0xC6AF,0x9D50,0x9D51,0x9D52,0xC6E1,0x9D53,
+0x9D54,0xE4F5,0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0xC2A9,
+0x9D5A,0x9D5B,0x9D5C,0xC0EC,0xD1DD,0xE4EE,0x9D5D,0x9D5E,
+0x9D5F,0x9D60,0x9D61,0x9D62,0x9D63,0x9D64,0x9D65,0x9D66,
+0xC4AE,0x9D67,0x9D68,0x9D69,0xE4ED,0x9D6A,0x9D6B,0x9D6C,
+0x9D6D,0xE4F6,0xE4F4,0xC2FE,0x9D6E,0xE4DD,0x9D6F,0xE4F0,
+0x9D70,0xCAFE,0x9D71,0xD5C4,0x9D72,0x9D73,0xE4F1,0x9D74,
+0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A,0xD1FA,0x9D7B,
+0x9D7C,0x9D7D,0x9D7E,0x9D80,0x9D81,0x9D82,0xE4EB,0xE4EC,
+0x9D83,0x9D84,0x9D85,0xE4F2,0x9D86,0xCEAB,0x9D87,0x9D88,
+0x9D89,0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F,0x9D90,
+0xC5CB,0x9D91,0x9D92,0x9D93,0xC7B1,0x9D94,0xC2BA,0x9D95,
+0x9D96,0x9D97,0xE4EA,0x9D98,0x9D99,0x9D9A,0xC1CA,0x9D9B,
+0x9D9C,0x9D9D,0x9D9E,0x9D9F,0x9DA0,0xCCB6,0xB3B1,0x9DA1,
+0x9DA2,0x9DA3,0xE4FB,0x9DA4,0xE4F3,0x9DA5,0x9DA6,0x9DA7,
+0xE4FA,0x9DA8,0xE4FD,0x9DA9,0xE4FC,0x9DAA,0x9DAB,0x9DAC,
+0x9DAD,0x9DAE,0x9DAF,0x9DB0,0xB3CE,0x9DB1,0x9DB2,0x9DB3,
+0xB3BA,0xE4F7,0x9DB4,0x9DB5,0xE4F9,0xE4F8,0xC5EC,0x9DB6,
+0x9DB7,0x9DB8,0x9DB9,0x9DBA,0x9DBB,0x9DBC,0x9DBD,0x9DBE,
+0x9DBF,0x9DC0,0x9DC1,0x9DC2,0xC0BD,0x9DC3,0x9DC4,0x9DC5,
+0x9DC6,0xD4E8,0x9DC7,0x9DC8,0x9DC9,0x9DCA,0x9DCB,0xE5A2,
+0x9DCC,0x9DCD,0x9DCE,0x9DCF,0x9DD0,0x9DD1,0x9DD2,0x9DD3,
+0x9DD4,0x9DD5,0x9DD6,0xB0C4,0x9DD7,0x9DD8,0xE5A4,0x9DD9,
+0x9DDA,0xE5A3,0x9DDB,0x9DDC,0x9DDD,0x9DDE,0x9DDF,0x9DE0,
+0xBCA4,0x9DE1,0xE5A5,0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6,
+0x9DE7,0xE5A1,0x9DE8,0x9DE9,0x9DEA,0x9DEB,0x9DEC,0x9DED,
+0x9DEE,0xE4FE,0xB1F4,0x9DEF,0x9DF0,0x9DF1,0x9DF2,0x9DF3,
+0x9DF4,0x9DF5,0x9DF6,0x9DF7,0x9DF8,0x9DF9,0xE5A8,0x9DFA,
+0xE5A9,0xE5A6,0x9DFB,0x9DFC,0x9DFD,0x9DFE,0x9E40,0x9E41,
+0x9E42,0x9E43,0x9E44,0x9E45,0x9E46,0x9E47,0xE5A7,0xE5AA,
+0x9E48,0x9E49,0x9E4A,0x9E4B,0x9E4C,0x9E4D,0x9E4E,0x9E4F,
+0x9E50,0x9E51,0x9E52,0x9E53,0x9E54,0x9E55,0x9E56,0x9E57,
+0x9E58,0x9E59,0x9E5A,0x9E5B,0x9E5C,0x9E5D,0x9E5E,0x9E5F,
+0x9E60,0x9E61,0x9E62,0x9E63,0x9E64,0x9E65,0x9E66,0x9E67,
+0x9E68,0xC6D9,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E6D,0x9E6E,
+0x9E6F,0x9E70,0xE5AB,0xE5AD,0x9E71,0x9E72,0x9E73,0x9E74,
+0x9E75,0x9E76,0x9E77,0xE5AC,0x9E78,0x9E79,0x9E7A,0x9E7B,
+0x9E7C,0x9E7D,0x9E7E,0x9E80,0x9E81,0x9E82,0x9E83,0x9E84,
+0x9E85,0x9E86,0x9E87,0x9E88,0x9E89,0xE5AF,0x9E8A,0x9E8B,
+0x9E8C,0xE5AE,0x9E8D,0x9E8E,0x9E8F,0x9E90,0x9E91,0x9E92,
+0x9E93,0x9E94,0x9E95,0x9E96,0x9E97,0x9E98,0x9E99,0x9E9A,
+0x9E9B,0x9E9C,0x9E9D,0x9E9E,0xB9E0,0x9E9F,0x9EA0,0xE5B0,
+0x9EA1,0x9EA2,0x9EA3,0x9EA4,0x9EA5,0x9EA6,0x9EA7,0x9EA8,
+0x9EA9,0x9EAA,0x9EAB,0x9EAC,0x9EAD,0x9EAE,0xE5B1,0x9EAF,
+0x9EB0,0x9EB1,0x9EB2,0x9EB3,0x9EB4,0x9EB5,0x9EB6,0x9EB7,
+0x9EB8,0x9EB9,0x9EBA,0xBBF0,0xECE1,0xC3F0,0x9EBB,0xB5C6,
+0xBBD2,0x9EBC,0x9EBD,0x9EBE,0x9EBF,0xC1E9,0xD4EE,0x9EC0,
+0xBEC4,0x9EC1,0x9EC2,0x9EC3,0xD7C6,0x9EC4,0xD4D6,0xB2D3,
+0xECBE,0x9EC5,0x9EC6,0x9EC7,0x9EC8,0xEAC1,0x9EC9,0x9ECA,
+0x9ECB,0xC2AF,0xB4B6,0x9ECC,0x9ECD,0x9ECE,0xD1D7,0x9ECF,
+0x9ED0,0x9ED1,0xB3B4,0x9ED2,0xC8B2,0xBFBB,0xECC0,0x9ED3,
+0x9ED4,0xD6CB,0x9ED5,0x9ED6,0xECBF,0xECC1,0x9ED7,0x9ED8,
+0x9ED9,0x9EDA,0x9EDB,0x9EDC,0x9EDD,0x9EDE,0x9EDF,0x9EE0,
+0x9EE1,0x9EE2,0x9EE3,0xECC5,0xBEE6,0xCCBF,0xC5DA,0xBEBC,
+0x9EE4,0xECC6,0x9EE5,0xB1FE,0x9EE6,0x9EE7,0x9EE8,0xECC4,
+0xD5A8,0xB5E3,0x9EE9,0xECC2,0xC1B6,0xB3E3,0x9EEA,0x9EEB,
+0xECC3,0xCBB8,0xC0C3,0xCCFE,0x9EEC,0x9EED,0x9EEE,0x9EEF,
+0xC1D2,0x9EF0,0xECC8,0x9EF1,0x9EF2,0x9EF3,0x9EF4,0x9EF5,
+0x9EF6,0x9EF7,0x9EF8,0x9EF9,0x9EFA,0x9EFB,0x9EFC,0x9EFD,
+0xBAE6,0xC0D3,0x9EFE,0xD6F2,0x9F40,0x9F41,0x9F42,0xD1CC,
+0x9F43,0x9F44,0x9F45,0x9F46,0xBFBE,0x9F47,0xB7B3,0xC9D5,
+0xECC7,0xBBE2,0x9F48,0xCCCC,0xBDFD,0xC8C8,0x9F49,0xCFA9,
+0x9F4A,0x9F4B,0x9F4C,0x9F4D,0x9F4E,0x9F4F,0x9F50,0xCDE9,
+0x9F51,0xC5EB,0x9F52,0x9F53,0x9F54,0xB7E9,0x9F55,0x9F56,
+0x9F57,0x9F58,0x9F59,0x9F5A,0x9F5B,0x9F5C,0x9F5D,0x9F5E,
+0x9F5F,0xD1C9,0xBAB8,0x9F60,0x9F61,0x9F62,0x9F63,0x9F64,
+0xECC9,0x9F65,0x9F66,0xECCA,0x9F67,0xBBC0,0xECCB,0x9F68,
+0xECE2,0xB1BA,0xB7D9,0x9F69,0x9F6A,0x9F6B,0x9F6C,0x9F6D,
+0x9F6E,0x9F6F,0x9F70,0x9F71,0x9F72,0x9F73,0xBDB9,0x9F74,
+0x9F75,0x9F76,0x9F77,0x9F78,0x9F79,0x9F7A,0x9F7B,0xECCC,
+0xD1E6,0xECCD,0x9F7C,0x9F7D,0x9F7E,0x9F80,0xC8BB,0x9F81,
+0x9F82,0x9F83,0x9F84,0x9F85,0x9F86,0x9F87,0x9F88,0x9F89,
+0x9F8A,0x9F8B,0x9F8C,0x9F8D,0x9F8E,0xECD1,0x9F8F,0x9F90,
+0x9F91,0x9F92,0xECD3,0x9F93,0xBBCD,0x9F94,0xBCE5,0x9F95,
+0x9F96,0x9F97,0x9F98,0x9F99,0x9F9A,0x9F9B,0x9F9C,0x9F9D,
+0x9F9E,0x9F9F,0x9FA0,0x9FA1,0xECCF,0x9FA2,0xC9B7,0x9FA3,
+0x9FA4,0x9FA5,0x9FA6,0x9FA7,0xC3BA,0x9FA8,0xECE3,0xD5D5,
+0xECD0,0x9FA9,0x9FAA,0x9FAB,0x9FAC,0x9FAD,0xD6F3,0x9FAE,
+0x9FAF,0x9FB0,0xECD2,0xECCE,0x9FB1,0x9FB2,0x9FB3,0x9FB4,
+0xECD4,0x9FB5,0xECD5,0x9FB6,0x9FB7,0xC9BF,0x9FB8,0x9FB9,
+0x9FBA,0x9FBB,0x9FBC,0x9FBD,0xCFA8,0x9FBE,0x9FBF,0x9FC0,
+0x9FC1,0x9FC2,0xD0DC,0x9FC3,0x9FC4,0x9FC5,0x9FC6,0xD1AC,
+0x9FC7,0x9FC8,0x9FC9,0x9FCA,0xC8DB,0x9FCB,0x9FCC,0x9FCD,
+0xECD6,0xCEF5,0x9FCE,0x9FCF,0x9FD0,0x9FD1,0x9FD2,0xCAEC,
+0xECDA,0x9FD3,0x9FD4,0x9FD5,0x9FD6,0x9FD7,0x9FD8,0x9FD9,
+0xECD9,0x9FDA,0x9FDB,0x9FDC,0xB0BE,0x9FDD,0x9FDE,0x9FDF,
+0x9FE0,0x9FE1,0x9FE2,0xECD7,0x9FE3,0xECD8,0x9FE4,0x9FE5,
+0x9FE6,0xECE4,0x9FE7,0x9FE8,0x9FE9,0x9FEA,0x9FEB,0x9FEC,
+0x9FED,0x9FEE,0x9FEF,0xC8BC,0x9FF0,0x9FF1,0x9FF2,0x9FF3,
+0x9FF4,0x9FF5,0x9FF6,0x9FF7,0x9FF8,0x9FF9,0xC1C7,0x9FFA,
+0x9FFB,0x9FFC,0x9FFD,0x9FFE,0xECDC,0xD1E0,0xA040,0xA041,
+0xA042,0xA043,0xA044,0xA045,0xA046,0xA047,0xA048,0xA049,
+0xECDB,0xA04A,0xA04B,0xA04C,0xA04D,0xD4EF,0xA04E,0xECDD,
+0xA04F,0xA050,0xA051,0xA052,0xA053,0xA054,0xDBC6,0xA055,
+0xA056,0xA057,0xA058,0xA059,0xA05A,0xA05B,0xA05C,0xA05D,
+0xA05E,0xECDE,0xA05F,0xA060,0xA061,0xA062,0xA063,0xA064,
+0xA065,0xA066,0xA067,0xA068,0xA069,0xA06A,0xB1AC,0xA06B,
+0xA06C,0xA06D,0xA06E,0xA06F,0xA070,0xA071,0xA072,0xA073,
+0xA074,0xA075,0xA076,0xA077,0xA078,0xA079,0xA07A,0xA07B,
+0xA07C,0xA07D,0xA07E,0xA080,0xA081,0xECDF,0xA082,0xA083,
+0xA084,0xA085,0xA086,0xA087,0xA088,0xA089,0xA08A,0xA08B,
+0xECE0,0xA08C,0xD7A6,0xA08D,0xC5C0,0xA08E,0xA08F,0xA090,
+0xEBBC,0xB0AE,0xA091,0xA092,0xA093,0xBEF4,0xB8B8,0xD2AF,
+0xB0D6,0xB5F9,0xA094,0xD8B3,0xA095,0xCBAC,0xA096,0xE3DD,
+0xA097,0xA098,0xA099,0xA09A,0xA09B,0xA09C,0xA09D,0xC6AC,
+0xB0E6,0xA09E,0xA09F,0xA0A0,0xC5C6,0xEBB9,0xA0A1,0xA0A2,
+0xA0A3,0xA0A4,0xEBBA,0xA0A5,0xA0A6,0xA0A7,0xEBBB,0xA0A8,
+0xA0A9,0xD1C0,0xA0AA,0xC5A3,0xA0AB,0xEAF2,0xA0AC,0xC4B2,
+0xA0AD,0xC4B5,0xC0CE,0xA0AE,0xA0AF,0xA0B0,0xEAF3,0xC4C1,
+0xA0B1,0xCEEF,0xA0B2,0xA0B3,0xA0B4,0xA0B5,0xEAF0,0xEAF4,
+0xA0B6,0xA0B7,0xC9FC,0xA0B8,0xA0B9,0xC7A3,0xA0BA,0xA0BB,
+0xA0BC,0xCCD8,0xCEFE,0xA0BD,0xA0BE,0xA0BF,0xEAF5,0xEAF6,
+0xCFAC,0xC0E7,0xA0C0,0xA0C1,0xEAF7,0xA0C2,0xA0C3,0xA0C4,
+0xA0C5,0xA0C6,0xB6BF,0xEAF8,0xA0C7,0xEAF9,0xA0C8,0xEAFA,
+0xA0C9,0xA0CA,0xEAFB,0xA0CB,0xA0CC,0xA0CD,0xA0CE,0xA0CF,
+0xA0D0,0xA0D1,0xA0D2,0xA0D3,0xA0D4,0xA0D5,0xA0D6,0xEAF1,
+0xA0D7,0xA0D8,0xA0D9,0xA0DA,0xA0DB,0xA0DC,0xA0DD,0xA0DE,
+0xA0DF,0xA0E0,0xA0E1,0xA0E2,0xC8AE,0xE1EB,0xA0E3,0xB7B8,
+0xE1EC,0xA0E4,0xA0E5,0xA0E6,0xE1ED,0xA0E7,0xD7B4,0xE1EE,
+0xE1EF,0xD3CC,0xA0E8,0xA0E9,0xA0EA,0xA0EB,0xA0EC,0xA0ED,
+0xA0EE,0xE1F1,0xBFF1,0xE1F0,0xB5D2,0xA0EF,0xA0F0,0xA0F1,
+0xB1B7,0xA0F2,0xA0F3,0xA0F4,0xA0F5,0xE1F3,0xE1F2,0xA0F6,
+0xBAFC,0xA0F7,0xE1F4,0xA0F8,0xA0F9,0xA0FA,0xA0FB,0xB9B7,
+0xA0FC,0xBED1,0xA0FD,0xA0FE,0xAA40,0xAA41,0xC4FC,0xAA42,
+0xBADD,0xBDC6,0xAA43,0xAA44,0xAA45,0xAA46,0xAA47,0xAA48,
+0xE1F5,0xE1F7,0xAA49,0xAA4A,0xB6C0,0xCFC1,0xCAA8,0xE1F6,
+0xD5F8,0xD3FC,0xE1F8,0xE1FC,0xE1F9,0xAA4B,0xAA4C,0xE1FA,
+0xC0EA,0xAA4D,0xE1FE,0xE2A1,0xC0C7,0xAA4E,0xAA4F,0xAA50,
+0xAA51,0xE1FB,0xAA52,0xE1FD,0xAA53,0xAA54,0xAA55,0xAA56,
+0xAA57,0xAA58,0xE2A5,0xAA59,0xAA5A,0xAA5B,0xC1D4,0xAA5C,
+0xAA5D,0xAA5E,0xAA5F,0xE2A3,0xAA60,0xE2A8,0xB2FE,0xE2A2,
+0xAA61,0xAA62,0xAA63,0xC3CD,0xB2C2,0xE2A7,0xE2A6,0xAA64,
+0xAA65,0xE2A4,0xE2A9,0xAA66,0xAA67,0xE2AB,0xAA68,0xAA69,
+0xAA6A,0xD0C9,0xD6ED,0xC3A8,0xE2AC,0xAA6B,0xCFD7,0xAA6C,
+0xAA6D,0xE2AE,0xAA6E,0xAA6F,0xBAEF,0xAA70,0xAA71,0xE9E0,
+0xE2AD,0xE2AA,0xAA72,0xAA73,0xAA74,0xAA75,0xBBAB,0xD4B3,
+0xAA76,0xAA77,0xAA78,0xAA79,0xAA7A,0xAA7B,0xAA7C,0xAA7D,
+0xAA7E,0xAA80,0xAA81,0xAA82,0xAA83,0xE2B0,0xAA84,0xAA85,
+0xE2AF,0xAA86,0xE9E1,0xAA87,0xAA88,0xAA89,0xAA8A,0xE2B1,
+0xAA8B,0xAA8C,0xAA8D,0xAA8E,0xAA8F,0xAA90,0xAA91,0xAA92,
+0xE2B2,0xAA93,0xAA94,0xAA95,0xAA96,0xAA97,0xAA98,0xAA99,
+0xAA9A,0xAA9B,0xAA9C,0xAA9D,0xE2B3,0xCCA1,0xAA9E,0xE2B4,
+0xAA9F,0xAAA0,0xAB40,0xAB41,0xAB42,0xAB43,0xAB44,0xAB45,
+0xAB46,0xAB47,0xAB48,0xAB49,0xAB4A,0xAB4B,0xE2B5,0xAB4C,
+0xAB4D,0xAB4E,0xAB4F,0xAB50,0xD0FE,0xAB51,0xAB52,0xC2CA,
+0xAB53,0xD3F1,0xAB54,0xCDF5,0xAB55,0xAB56,0xE7E0,0xAB57,
+0xAB58,0xE7E1,0xAB59,0xAB5A,0xAB5B,0xAB5C,0xBEC1,0xAB5D,
+0xAB5E,0xAB5F,0xAB60,0xC2EA,0xAB61,0xAB62,0xAB63,0xE7E4,
+0xAB64,0xAB65,0xE7E3,0xAB66,0xAB67,0xAB68,0xAB69,0xAB6A,
+0xAB6B,0xCDE6,0xAB6C,0xC3B5,0xAB6D,0xAB6E,0xE7E2,0xBBB7,
+0xCFD6,0xAB6F,0xC1E1,0xE7E9,0xAB70,0xAB71,0xAB72,0xE7E8,
+0xAB73,0xAB74,0xE7F4,0xB2A3,0xAB75,0xAB76,0xAB77,0xAB78,
+0xE7EA,0xAB79,0xE7E6,0xAB7A,0xAB7B,0xAB7C,0xAB7D,0xAB7E,
+0xE7EC,0xE7EB,0xC9BA,0xAB80,0xAB81,0xD5E4,0xAB82,0xE7E5,
+0xB7A9,0xE7E7,0xAB83,0xAB84,0xAB85,0xAB86,0xAB87,0xAB88,
+0xAB89,0xE7EE,0xAB8A,0xAB8B,0xAB8C,0xAB8D,0xE7F3,0xAB8E,
+0xD6E9,0xAB8F,0xAB90,0xAB91,0xAB92,0xE7ED,0xAB93,0xE7F2,
+0xAB94,0xE7F1,0xAB95,0xAB96,0xAB97,0xB0E0,0xAB98,0xAB99,
+0xAB9A,0xAB9B,0xE7F5,0xAB9C,0xAB9D,0xAB9E,0xAB9F,0xABA0,
+0xAC40,0xAC41,0xAC42,0xAC43,0xAC44,0xAC45,0xAC46,0xAC47,
+0xAC48,0xAC49,0xAC4A,0xC7F2,0xAC4B,0xC0C5,0xC0ED,0xAC4C,
+0xAC4D,0xC1F0,0xE7F0,0xAC4E,0xAC4F,0xAC50,0xAC51,0xE7F6,
+0xCBF6,0xAC52,0xAC53,0xAC54,0xAC55,0xAC56,0xAC57,0xAC58,
+0xAC59,0xAC5A,0xE8A2,0xE8A1,0xAC5B,0xAC5C,0xAC5D,0xAC5E,
+0xAC5F,0xAC60,0xD7C1,0xAC61,0xAC62,0xE7FA,0xE7F9,0xAC63,
+0xE7FB,0xAC64,0xE7F7,0xAC65,0xE7FE,0xAC66,0xE7FD,0xAC67,
+0xE7FC,0xAC68,0xAC69,0xC1D5,0xC7D9,0xC5FD,0xC5C3,0xAC6A,
+0xAC6B,0xAC6C,0xAC6D,0xAC6E,0xC7ED,0xAC6F,0xAC70,0xAC71,
+0xAC72,0xE8A3,0xAC73,0xAC74,0xAC75,0xAC76,0xAC77,0xAC78,
+0xAC79,0xAC7A,0xAC7B,0xAC7C,0xAC7D,0xAC7E,0xAC80,0xAC81,
+0xAC82,0xAC83,0xAC84,0xAC85,0xAC86,0xE8A6,0xAC87,0xE8A5,
+0xAC88,0xE8A7,0xBAF7,0xE7F8,0xE8A4,0xAC89,0xC8F0,0xC9AA,
+0xAC8A,0xAC8B,0xAC8C,0xAC8D,0xAC8E,0xAC8F,0xAC90,0xAC91,
+0xAC92,0xAC93,0xAC94,0xAC95,0xAC96,0xE8A9,0xAC97,0xAC98,
+0xB9E5,0xAC99,0xAC9A,0xAC9B,0xAC9C,0xAC9D,0xD1FE,0xE8A8,
+0xAC9E,0xAC9F,0xACA0,0xAD40,0xAD41,0xAD42,0xE8AA,0xAD43,
+0xE8AD,0xE8AE,0xAD44,0xC1A7,0xAD45,0xAD46,0xAD47,0xE8AF,
+0xAD48,0xAD49,0xAD4A,0xE8B0,0xAD4B,0xAD4C,0xE8AC,0xAD4D,
+0xE8B4,0xAD4E,0xAD4F,0xAD50,0xAD51,0xAD52,0xAD53,0xAD54,
+0xAD55,0xAD56,0xAD57,0xAD58,0xE8AB,0xAD59,0xE8B1,0xAD5A,
+0xAD5B,0xAD5C,0xAD5D,0xAD5E,0xAD5F,0xAD60,0xAD61,0xE8B5,
+0xE8B2,0xE8B3,0xAD62,0xAD63,0xAD64,0xAD65,0xAD66,0xAD67,
+0xAD68,0xAD69,0xAD6A,0xAD6B,0xAD6C,0xAD6D,0xAD6E,0xAD6F,
+0xAD70,0xAD71,0xE8B7,0xAD72,0xAD73,0xAD74,0xAD75,0xAD76,
+0xAD77,0xAD78,0xAD79,0xAD7A,0xAD7B,0xAD7C,0xAD7D,0xAD7E,
+0xAD80,0xAD81,0xAD82,0xAD83,0xAD84,0xAD85,0xAD86,0xAD87,
+0xAD88,0xAD89,0xE8B6,0xAD8A,0xAD8B,0xAD8C,0xAD8D,0xAD8E,
+0xAD8F,0xAD90,0xAD91,0xAD92,0xB9CF,0xAD93,0xF0AC,0xAD94,
+0xF0AD,0xAD95,0xC6B0,0xB0EA,0xC8BF,0xAD96,0xCDDF,0xAD97,
+0xAD98,0xAD99,0xAD9A,0xAD9B,0xAD9C,0xAD9D,0xCECD,0xEAB1,
+0xAD9E,0xAD9F,0xADA0,0xAE40,0xEAB2,0xAE41,0xC6BF,0xB4C9,
+0xAE42,0xAE43,0xAE44,0xAE45,0xAE46,0xAE47,0xAE48,0xEAB3,
+0xAE49,0xAE4A,0xAE4B,0xAE4C,0xD5E7,0xAE4D,0xAE4E,0xAE4F,
+0xAE50,0xAE51,0xAE52,0xAE53,0xAE54,0xDDF9,0xAE55,0xEAB4,
+0xAE56,0xEAB5,0xAE57,0xEAB6,0xAE58,0xAE59,0xAE5A,0xAE5B,
+0xB8CA,0xDFB0,0xC9F5,0xAE5C,0xCCF0,0xAE5D,0xAE5E,0xC9FA,
+0xAE5F,0xAE60,0xAE61,0xAE62,0xAE63,0xC9FB,0xAE64,0xAE65,
+0xD3C3,0xCBA6,0xAE66,0xB8A6,0xF0AE,0xB1C2,0xAE67,0xE5B8,
+0xCCEF,0xD3C9,0xBCD7,0xC9EA,0xAE68,0xB5E7,0xAE69,0xC4D0,
+0xB5E9,0xAE6A,0xEEAE,0xBBAD,0xAE6B,0xAE6C,0xE7DE,0xAE6D,
+0xEEAF,0xAE6E,0xAE6F,0xAE70,0xAE71,0xB3A9,0xAE72,0xAE73,
+0xEEB2,0xAE74,0xAE75,0xEEB1,0xBDE7,0xAE76,0xEEB0,0xCEB7,
+0xAE77,0xAE78,0xAE79,0xAE7A,0xC5CF,0xAE7B,0xAE7C,0xAE7D,
+0xAE7E,0xC1F4,0xDBCE,0xEEB3,0xD0F3,0xAE80,0xAE81,0xAE82,
+0xAE83,0xAE84,0xAE85,0xAE86,0xAE87,0xC2D4,0xC6E8,0xAE88,
+0xAE89,0xAE8A,0xB7AC,0xAE8B,0xAE8C,0xAE8D,0xAE8E,0xAE8F,
+0xAE90,0xAE91,0xEEB4,0xAE92,0xB3EB,0xAE93,0xAE94,0xAE95,
+0xBBFB,0xEEB5,0xAE96,0xAE97,0xAE98,0xAE99,0xAE9A,0xE7DC,
+0xAE9B,0xAE9C,0xAE9D,0xEEB6,0xAE9E,0xAE9F,0xBDAE,0xAEA0,
+0xAF40,0xAF41,0xAF42,0xF1E2,0xAF43,0xAF44,0xAF45,0xCAE8,
+0xAF46,0xD2C9,0xF0DA,0xAF47,0xF0DB,0xAF48,0xF0DC,0xC1C6,
+0xAF49,0xB8ED,0xBECE,0xAF4A,0xAF4B,0xF0DE,0xAF4C,0xC5B1,
+0xF0DD,0xD1F1,0xAF4D,0xF0E0,0xB0CC,0xBDEA,0xAF4E,0xAF4F,
+0xAF50,0xAF51,0xAF52,0xD2DF,0xF0DF,0xAF53,0xB4AF,0xB7E8,
+0xF0E6,0xF0E5,0xC6A3,0xF0E1,0xF0E2,0xB4C3,0xAF54,0xAF55,
+0xF0E3,0xD5EE,0xAF56,0xAF57,0xCCDB,0xBED2,0xBCB2,0xAF58,
+0xAF59,0xAF5A,0xF0E8,0xF0E7,0xF0E4,0xB2A1,0xAF5B,0xD6A2,
+0xD3B8,0xBEB7,0xC8AC,0xAF5C,0xAF5D,0xF0EA,0xAF5E,0xAF5F,
+0xAF60,0xAF61,0xD1F7,0xAF62,0xD6CC,0xBADB,0xF0E9,0xAF63,
+0xB6BB,0xAF64,0xAF65,0xCDB4,0xAF66,0xAF67,0xC6A6,0xAF68,
+0xAF69,0xAF6A,0xC1A1,0xF0EB,0xF0EE,0xAF6B,0xF0ED,0xF0F0,
+0xF0EC,0xAF6C,0xBBBE,0xF0EF,0xAF6D,0xAF6E,0xAF6F,0xAF70,
+0xCCB5,0xF0F2,0xAF71,0xAF72,0xB3D5,0xAF73,0xAF74,0xAF75,
+0xAF76,0xB1D4,0xAF77,0xAF78,0xF0F3,0xAF79,0xAF7A,0xF0F4,
+0xF0F6,0xB4E1,0xAF7B,0xF0F1,0xAF7C,0xF0F7,0xAF7D,0xAF7E,
+0xAF80,0xAF81,0xF0FA,0xAF82,0xF0F8,0xAF83,0xAF84,0xAF85,
+0xF0F5,0xAF86,0xAF87,0xAF88,0xAF89,0xF0FD,0xAF8A,0xF0F9,
+0xF0FC,0xF0FE,0xAF8B,0xF1A1,0xAF8C,0xAF8D,0xAF8E,0xCEC1,
+0xF1A4,0xAF8F,0xF1A3,0xAF90,0xC1F6,0xF0FB,0xCADD,0xAF91,
+0xAF92,0xB4F1,0xB1F1,0xCCB1,0xAF93,0xF1A6,0xAF94,0xAF95,
+0xF1A7,0xAF96,0xAF97,0xF1AC,0xD5CE,0xF1A9,0xAF98,0xAF99,
+0xC8B3,0xAF9A,0xAF9B,0xAF9C,0xF1A2,0xAF9D,0xF1AB,0xF1A8,
+0xF1A5,0xAF9E,0xAF9F,0xF1AA,0xAFA0,0xB040,0xB041,0xB042,
+0xB043,0xB044,0xB045,0xB046,0xB0A9,0xF1AD,0xB047,0xB048,
+0xB049,0xB04A,0xB04B,0xB04C,0xF1AF,0xB04D,0xF1B1,0xB04E,
+0xB04F,0xB050,0xB051,0xB052,0xF1B0,0xB053,0xF1AE,0xB054,
+0xB055,0xB056,0xB057,0xD1A2,0xB058,0xB059,0xB05A,0xB05B,
+0xB05C,0xB05D,0xB05E,0xF1B2,0xB05F,0xB060,0xB061,0xF1B3,
+0xB062,0xB063,0xB064,0xB065,0xB066,0xB067,0xB068,0xB069,
+0xB9EF,0xB06A,0xB06B,0xB5C7,0xB06C,0xB0D7,0xB0D9,0xB06D,
+0xB06E,0xB06F,0xD4ED,0xB070,0xB5C4,0xB071,0xBDD4,0xBBCA,
+0xF0A7,0xB072,0xB073,0xB8DE,0xB074,0xB075,0xF0A8,0xB076,
+0xB077,0xB0A8,0xB078,0xF0A9,0xB079,0xB07A,0xCDEE,0xB07B,
+0xB07C,0xF0AA,0xB07D,0xB07E,0xB080,0xB081,0xB082,0xB083,
+0xB084,0xB085,0xB086,0xB087,0xF0AB,0xB088,0xB089,0xB08A,
+0xB08B,0xB08C,0xB08D,0xB08E,0xB08F,0xB090,0xC6A4,0xB091,
+0xB092,0xD6E5,0xF1E4,0xB093,0xF1E5,0xB094,0xB095,0xB096,
+0xB097,0xB098,0xB099,0xB09A,0xB09B,0xB09C,0xB09D,0xC3F3,
+0xB09E,0xB09F,0xD3DB,0xB0A0,0xB140,0xD6D1,0xC5E8,0xB141,
+0xD3AF,0xB142,0xD2E6,0xB143,0xB144,0xEEC1,0xB0BB,0xD5B5,
+0xD1CE,0xBCE0,0xBAD0,0xB145,0xBFF8,0xB146,0xB8C7,0xB5C1,
+0xC5CC,0xB147,0xB148,0xCAA2,0xB149,0xB14A,0xB14B,0xC3CB,
+0xB14C,0xB14D,0xB14E,0xB14F,0xB150,0xEEC2,0xB151,0xB152,
+0xB153,0xB154,0xB155,0xB156,0xB157,0xB158,0xC4BF,0xB6A2,
+0xB159,0xEDEC,0xC3A4,0xB15A,0xD6B1,0xB15B,0xB15C,0xB15D,
+0xCFE0,0xEDEF,0xB15E,0xB15F,0xC5CE,0xB160,0xB6DC,0xB161,
+0xB162,0xCAA1,0xB163,0xB164,0xEDED,0xB165,0xB166,0xEDF0,
+0xEDF1,0xC3BC,0xB167,0xBFB4,0xB168,0xEDEE,0xB169,0xB16A,
+0xB16B,0xB16C,0xB16D,0xB16E,0xB16F,0xB170,0xB171,0xB172,
+0xB173,0xEDF4,0xEDF2,0xB174,0xB175,0xB176,0xB177,0xD5E6,
+0xC3DF,0xB178,0xEDF3,0xB179,0xB17A,0xB17B,0xEDF6,0xB17C,
+0xD5A3,0xD1A3,0xB17D,0xB17E,0xB180,0xEDF5,0xB181,0xC3D0,
+0xB182,0xB183,0xB184,0xB185,0xB186,0xEDF7,0xBFF4,0xBEEC,
+0xEDF8,0xB187,0xCCF7,0xB188,0xD1DB,0xB189,0xB18A,0xB18B,
+0xD7C5,0xD5F6,0xB18C,0xEDFC,0xB18D,0xB18E,0xB18F,0xEDFB,
+0xB190,0xB191,0xB192,0xB193,0xB194,0xB195,0xB196,0xB197,
+0xEDF9,0xEDFA,0xB198,0xB199,0xB19A,0xB19B,0xB19C,0xB19D,
+0xB19E,0xB19F,0xEDFD,0xBEA6,0xB1A0,0xB240,0xB241,0xB242,
+0xB243,0xCBAF,0xEEA1,0xB6BD,0xB244,0xEEA2,0xC4C0,0xB245,
+0xEDFE,0xB246,0xB247,0xBDDE,0xB2C7,0xB248,0xB249,0xB24A,
+0xB24B,0xB24C,0xB24D,0xB24E,0xB24F,0xB250,0xB251,0xB252,
+0xB253,0xB6C3,0xB254,0xB255,0xB256,0xEEA5,0xD8BA,0xEEA3,
+0xEEA6,0xB257,0xB258,0xB259,0xC3E9,0xB3F2,0xB25A,0xB25B,
+0xB25C,0xB25D,0xB25E,0xB25F,0xEEA7,0xEEA4,0xCFB9,0xB260,
+0xB261,0xEEA8,0xC2F7,0xB262,0xB263,0xB264,0xB265,0xB266,
+0xB267,0xB268,0xB269,0xB26A,0xB26B,0xB26C,0xB26D,0xEEA9,
+0xEEAA,0xB26E,0xDEAB,0xB26F,0xB270,0xC6B3,0xB271,0xC7C6,
+0xB272,0xD6F5,0xB5C9,0xB273,0xCBB2,0xB274,0xB275,0xB276,
+0xEEAB,0xB277,0xB278,0xCDAB,0xB279,0xEEAC,0xB27A,0xB27B,
+0xB27C,0xB27D,0xB27E,0xD5B0,0xB280,0xEEAD,0xB281,0xF6C4,
+0xB282,0xB283,0xB284,0xB285,0xB286,0xB287,0xB288,0xB289,
+0xB28A,0xB28B,0xB28C,0xB28D,0xB28E,0xDBC7,0xB28F,0xB290,
+0xB291,0xB292,0xB293,0xB294,0xB295,0xB296,0xB297,0xB4A3,
+0xB298,0xB299,0xB29A,0xC3AC,0xF1E6,0xB29B,0xB29C,0xB29D,
+0xB29E,0xB29F,0xCAB8,0xD2D3,0xB2A0,0xD6AA,0xB340,0xEFF2,
+0xB341,0xBED8,0xB342,0xBDC3,0xEFF3,0xB6CC,0xB0AB,0xB343,
+0xB344,0xB345,0xB346,0xCAAF,0xB347,0xB348,0xEDB6,0xB349,
+0xEDB7,0xB34A,0xB34B,0xB34C,0xB34D,0xCEF9,0xB7AF,0xBFF3,
+0xEDB8,0xC2EB,0xC9B0,0xB34E,0xB34F,0xB350,0xB351,0xB352,
+0xB353,0xEDB9,0xB354,0xB355,0xC6F6,0xBFB3,0xB356,0xB357,
+0xB358,0xEDBC,0xC5F8,0xB359,0xD1D0,0xB35A,0xD7A9,0xEDBA,
+0xEDBB,0xB35B,0xD1E2,0xB35C,0xEDBF,0xEDC0,0xB35D,0xEDC4,
+0xB35E,0xB35F,0xB360,0xEDC8,0xB361,0xEDC6,0xEDCE,0xD5E8,
+0xB362,0xEDC9,0xB363,0xB364,0xEDC7,0xEDBE,0xB365,0xB366,
+0xC5E9,0xB367,0xB368,0xB369,0xC6C6,0xB36A,0xB36B,0xC9E9,
+0xD4D2,0xEDC1,0xEDC2,0xEDC3,0xEDC5,0xB36C,0xC0F9,0xB36D,
+0xB4A1,0xB36E,0xB36F,0xB370,0xB371,0xB9E8,0xB372,0xEDD0,
+0xB373,0xB374,0xB375,0xB376,0xEDD1,0xB377,0xEDCA,0xB378,
+0xEDCF,0xB379,0xCEF8,0xB37A,0xB37B,0xCBB6,0xEDCC,0xEDCD,
+0xB37C,0xB37D,0xB37E,0xB380,0xB381,0xCFF5,0xB382,0xB383,
+0xB384,0xB385,0xB386,0xB387,0xB388,0xB389,0xB38A,0xB38B,
+0xB38C,0xB38D,0xEDD2,0xC1F2,0xD3B2,0xEDCB,0xC8B7,0xB38E,
+0xB38F,0xB390,0xB391,0xB392,0xB393,0xB394,0xB395,0xBCEF,
+0xB396,0xB397,0xB398,0xB399,0xC5F0,0xB39A,0xB39B,0xB39C,
+0xB39D,0xB39E,0xB39F,0xB3A0,0xB440,0xB441,0xB442,0xEDD6,
+0xB443,0xB5EF,0xB444,0xB445,0xC2B5,0xB0AD,0xCBE9,0xB446,
+0xB447,0xB1AE,0xB448,0xEDD4,0xB449,0xB44A,0xB44B,0xCDEB,
+0xB5E2,0xB44C,0xEDD5,0xEDD3,0xEDD7,0xB44D,0xB44E,0xB5FA,
+0xB44F,0xEDD8,0xB450,0xEDD9,0xB451,0xEDDC,0xB452,0xB1CC,
+0xB453,0xB454,0xB455,0xB456,0xB457,0xB458,0xB459,0xB45A,
+0xC5F6,0xBCEE,0xEDDA,0xCCBC,0xB2EA,0xB45B,0xB45C,0xB45D,
+0xB45E,0xEDDB,0xB45F,0xB460,0xB461,0xB462,0xC4EB,0xB463,
+0xB464,0xB4C5,0xB465,0xB466,0xB467,0xB0F5,0xB468,0xB469,
+0xB46A,0xEDDF,0xC0DA,0xB4E8,0xB46B,0xB46C,0xB46D,0xB46E,
+0xC5CD,0xB46F,0xB470,0xB471,0xEDDD,0xBFC4,0xB472,0xB473,
+0xB474,0xEDDE,0xB475,0xB476,0xB477,0xB478,0xB479,0xB47A,
+0xB47B,0xB47C,0xB47D,0xB47E,0xB480,0xB481,0xB482,0xB483,
+0xC4A5,0xB484,0xB485,0xB486,0xEDE0,0xB487,0xB488,0xB489,
+0xB48A,0xB48B,0xEDE1,0xB48C,0xEDE3,0xB48D,0xB48E,0xC1D7,
+0xB48F,0xB490,0xBBC7,0xB491,0xB492,0xB493,0xB494,0xB495,
+0xB496,0xBDB8,0xB497,0xB498,0xB499,0xEDE2,0xB49A,0xB49B,
+0xB49C,0xB49D,0xB49E,0xB49F,0xB4A0,0xB540,0xB541,0xB542,
+0xB543,0xB544,0xB545,0xEDE4,0xB546,0xB547,0xB548,0xB549,
+0xB54A,0xB54B,0xB54C,0xB54D,0xB54E,0xB54F,0xEDE6,0xB550,
+0xB551,0xB552,0xB553,0xB554,0xEDE5,0xB555,0xB556,0xB557,
+0xB558,0xB559,0xB55A,0xB55B,0xB55C,0xB55D,0xB55E,0xB55F,
+0xB560,0xB561,0xB562,0xB563,0xEDE7,0xB564,0xB565,0xB566,
+0xB567,0xB568,0xCABE,0xECEA,0xC0F1,0xB569,0xC9E7,0xB56A,
+0xECEB,0xC6EE,0xB56B,0xB56C,0xB56D,0xB56E,0xECEC,0xB56F,
+0xC6ED,0xECED,0xB570,0xB571,0xB572,0xB573,0xB574,0xB575,
+0xB576,0xB577,0xB578,0xECF0,0xB579,0xB57A,0xD7E6,0xECF3,
+0xB57B,0xB57C,0xECF1,0xECEE,0xECEF,0xD7A3,0xC9F1,0xCBEE,
+0xECF4,0xB57D,0xECF2,0xB57E,0xB580,0xCFE9,0xB581,0xECF6,
+0xC6B1,0xB582,0xB583,0xB584,0xB585,0xBCC0,0xB586,0xECF5,
+0xB587,0xB588,0xB589,0xB58A,0xB58B,0xB58C,0xB58D,0xB5BB,
+0xBBF6,0xB58E,0xECF7,0xB58F,0xB590,0xB591,0xB592,0xB593,
+0xD9F7,0xBDFB,0xB594,0xB595,0xC2BB,0xECF8,0xB596,0xB597,
+0xB598,0xB599,0xECF9,0xB59A,0xB59B,0xB59C,0xB59D,0xB8A3,
+0xB59E,0xB59F,0xB5A0,0xB640,0xB641,0xB642,0xB643,0xB644,
+0xB645,0xB646,0xECFA,0xB647,0xB648,0xB649,0xB64A,0xB64B,
+0xB64C,0xB64D,0xB64E,0xB64F,0xB650,0xB651,0xB652,0xECFB,
+0xB653,0xB654,0xB655,0xB656,0xB657,0xB658,0xB659,0xB65A,
+0xB65B,0xB65C,0xB65D,0xECFC,0xB65E,0xB65F,0xB660,0xB661,
+0xB662,0xD3ED,0xD8AE,0xC0EB,0xB663,0xC7DD,0xBACC,0xB664,
+0xD0E3,0xCBBD,0xB665,0xCDBA,0xB666,0xB667,0xB8D1,0xB668,
+0xB669,0xB1FC,0xB66A,0xC7EF,0xB66B,0xD6D6,0xB66C,0xB66D,
+0xB66E,0xBFC6,0xC3EB,0xB66F,0xB670,0xEFF5,0xB671,0xB672,
+0xC3D8,0xB673,0xB674,0xB675,0xB676,0xB677,0xB678,0xD7E2,
+0xB679,0xB67A,0xB67B,0xEFF7,0xB3D3,0xB67C,0xC7D8,0xD1ED,
+0xB67D,0xD6C8,0xB67E,0xEFF8,0xB680,0xEFF6,0xB681,0xBBFD,
+0xB3C6,0xB682,0xB683,0xB684,0xB685,0xB686,0xB687,0xB688,
+0xBDD5,0xB689,0xB68A,0xD2C6,0xB68B,0xBBE0,0xB68C,0xB68D,
+0xCFA1,0xB68E,0xEFFC,0xEFFB,0xB68F,0xB690,0xEFF9,0xB691,
+0xB692,0xB693,0xB694,0xB3CC,0xB695,0xC9D4,0xCBB0,0xB696,
+0xB697,0xB698,0xB699,0xB69A,0xEFFE,0xB69B,0xB69C,0xB0DE,
+0xB69D,0xB69E,0xD6C9,0xB69F,0xB6A0,0xB740,0xEFFD,0xB741,
+0xB3ED,0xB742,0xB743,0xF6D5,0xB744,0xB745,0xB746,0xB747,
+0xB748,0xB749,0xB74A,0xB74B,0xB74C,0xB74D,0xB74E,0xB74F,
+0xB750,0xB751,0xB752,0xCEC8,0xB753,0xB754,0xB755,0xF0A2,
+0xB756,0xF0A1,0xB757,0xB5BE,0xBCDA,0xBBFC,0xB758,0xB8E5,
+0xB759,0xB75A,0xB75B,0xB75C,0xB75D,0xB75E,0xC4C2,0xB75F,
+0xB760,0xB761,0xB762,0xB763,0xB764,0xB765,0xB766,0xB767,
+0xB768,0xF0A3,0xB769,0xB76A,0xB76B,0xB76C,0xB76D,0xCBEB,
+0xB76E,0xB76F,0xB770,0xB771,0xB772,0xB773,0xB774,0xB775,
+0xB776,0xB777,0xB778,0xB779,0xB77A,0xB77B,0xB77C,0xB77D,
+0xB77E,0xB780,0xB781,0xB782,0xB783,0xB784,0xB785,0xB786,
+0xF0A6,0xB787,0xB788,0xB789,0xD1A8,0xB78A,0xBEBF,0xC7EE,
+0xF1B6,0xF1B7,0xBFD5,0xB78B,0xB78C,0xB78D,0xB78E,0xB4A9,
+0xF1B8,0xCDBB,0xB78F,0xC7D4,0xD5AD,0xB790,0xF1B9,0xB791,
+0xF1BA,0xB792,0xB793,0xB794,0xB795,0xC7CF,0xB796,0xB797,
+0xB798,0xD2A4,0xD6CF,0xB799,0xB79A,0xF1BB,0xBDD1,0xB4B0,
+0xBEBD,0xB79B,0xB79C,0xB79D,0xB4DC,0xCED1,0xB79E,0xBFDF,
+0xF1BD,0xB79F,0xB7A0,0xB840,0xB841,0xBFFA,0xF1BC,0xB842,
+0xF1BF,0xB843,0xB844,0xB845,0xF1BE,0xF1C0,0xB846,0xB847,
+0xB848,0xB849,0xB84A,0xF1C1,0xB84B,0xB84C,0xB84D,0xB84E,
+0xB84F,0xB850,0xB851,0xB852,0xB853,0xB854,0xB855,0xC1FE,
+0xB856,0xB857,0xB858,0xB859,0xB85A,0xB85B,0xB85C,0xB85D,
+0xB85E,0xB85F,0xB860,0xC1A2,0xB861,0xB862,0xB863,0xB864,
+0xB865,0xB866,0xB867,0xB868,0xB869,0xB86A,0xCAFA,0xB86B,
+0xB86C,0xD5BE,0xB86D,0xB86E,0xB86F,0xB870,0xBEBA,0xBEB9,
+0xD5C2,0xB871,0xB872,0xBFA2,0xB873,0xCDAF,0xF1B5,0xB874,
+0xB875,0xB876,0xB877,0xB878,0xB879,0xBDDF,0xB87A,0xB6CB,
+0xB87B,0xB87C,0xB87D,0xB87E,0xB880,0xB881,0xB882,0xB883,
+0xB884,0xD6F1,0xF3C3,0xB885,0xB886,0xF3C4,0xB887,0xB8CD,
+0xB888,0xB889,0xB88A,0xF3C6,0xF3C7,0xB88B,0xB0CA,0xB88C,
+0xF3C5,0xB88D,0xF3C9,0xCBF1,0xB88E,0xB88F,0xB890,0xF3CB,
+0xB891,0xD0A6,0xB892,0xB893,0xB1CA,0xF3C8,0xB894,0xB895,
+0xB896,0xF3CF,0xB897,0xB5D1,0xB898,0xB899,0xF3D7,0xB89A,
+0xF3D2,0xB89B,0xB89C,0xB89D,0xF3D4,0xF3D3,0xB7FB,0xB89E,
+0xB1BF,0xB89F,0xF3CE,0xF3CA,0xB5DA,0xB8A0,0xF3D0,0xB940,
+0xB941,0xF3D1,0xB942,0xF3D5,0xB943,0xB944,0xB945,0xB946,
+0xF3CD,0xB947,0xBCE3,0xB948,0xC1FD,0xB949,0xF3D6,0xB94A,
+0xB94B,0xB94C,0xB94D,0xB94E,0xB94F,0xF3DA,0xB950,0xF3CC,
+0xB951,0xB5C8,0xB952,0xBDEE,0xF3DC,0xB953,0xB954,0xB7A4,
+0xBFF0,0xD6FE,0xCDB2,0xB955,0xB4F0,0xB956,0xB2DF,0xB957,
+0xF3D8,0xB958,0xF3D9,0xC9B8,0xB959,0xF3DD,0xB95A,0xB95B,
+0xF3DE,0xB95C,0xF3E1,0xB95D,0xB95E,0xB95F,0xB960,0xB961,
+0xB962,0xB963,0xB964,0xB965,0xB966,0xB967,0xF3DF,0xB968,
+0xB969,0xF3E3,0xF3E2,0xB96A,0xB96B,0xF3DB,0xB96C,0xBFEA,
+0xB96D,0xB3EF,0xB96E,0xF3E0,0xB96F,0xB970,0xC7A9,0xB971,
+0xBCF2,0xB972,0xB973,0xB974,0xB975,0xF3EB,0xB976,0xB977,
+0xB978,0xB979,0xB97A,0xB97B,0xB97C,0xB9BF,0xB97D,0xB97E,
+0xF3E4,0xB980,0xB981,0xB982,0xB2AD,0xBBFE,0xB983,0xCBE3,
+0xB984,0xB985,0xB986,0xB987,0xF3ED,0xF3E9,0xB988,0xB989,
+0xB98A,0xB9DC,0xF3EE,0xB98B,0xB98C,0xB98D,0xF3E5,0xF3E6,
+0xF3EA,0xC2E1,0xF3EC,0xF3EF,0xF3E8,0xBCFD,0xB98E,0xB98F,
+0xB990,0xCFE4,0xB991,0xB992,0xF3F0,0xB993,0xB994,0xB995,
+0xF3E7,0xB996,0xB997,0xB998,0xB999,0xB99A,0xB99B,0xB99C,
+0xB99D,0xF3F2,0xB99E,0xB99F,0xB9A0,0xBA40,0xD7AD,0xC6AA,
+0xBA41,0xBA42,0xBA43,0xBA44,0xF3F3,0xBA45,0xBA46,0xBA47,
+0xBA48,0xF3F1,0xBA49,0xC2A8,0xBA4A,0xBA4B,0xBA4C,0xBA4D,
+0xBA4E,0xB8DD,0xF3F5,0xBA4F,0xBA50,0xF3F4,0xBA51,0xBA52,
+0xBA53,0xB4DB,0xBA54,0xBA55,0xBA56,0xF3F6,0xF3F7,0xBA57,
+0xBA58,0xBA59,0xF3F8,0xBA5A,0xBA5B,0xBA5C,0xC0BA,0xBA5D,
+0xBA5E,0xC0E9,0xBA5F,0xBA60,0xBA61,0xBA62,0xBA63,0xC5F1,
+0xBA64,0xBA65,0xBA66,0xBA67,0xF3FB,0xBA68,0xF3FA,0xBA69,
+0xBA6A,0xBA6B,0xBA6C,0xBA6D,0xBA6E,0xBA6F,0xBA70,0xB4D8,
+0xBA71,0xBA72,0xBA73,0xF3FE,0xF3F9,0xBA74,0xBA75,0xF3FC,
+0xBA76,0xBA77,0xBA78,0xBA79,0xBA7A,0xBA7B,0xF3FD,0xBA7C,
+0xBA7D,0xBA7E,0xBA80,0xBA81,0xBA82,0xBA83,0xBA84,0xF4A1,
+0xBA85,0xBA86,0xBA87,0xBA88,0xBA89,0xBA8A,0xF4A3,0xBBC9,
+0xBA8B,0xBA8C,0xF4A2,0xBA8D,0xBA8E,0xBA8F,0xBA90,0xBA91,
+0xBA92,0xBA93,0xBA94,0xBA95,0xBA96,0xBA97,0xBA98,0xBA99,
+0xF4A4,0xBA9A,0xBA9B,0xBA9C,0xBA9D,0xBA9E,0xBA9F,0xB2BE,
+0xF4A6,0xF4A5,0xBAA0,0xBB40,0xBB41,0xBB42,0xBB43,0xBB44,
+0xBB45,0xBB46,0xBB47,0xBB48,0xBB49,0xBCAE,0xBB4A,0xBB4B,
+0xBB4C,0xBB4D,0xBB4E,0xBB4F,0xBB50,0xBB51,0xBB52,0xBB53,
+0xBB54,0xBB55,0xBB56,0xBB57,0xBB58,0xBB59,0xBB5A,0xBB5B,
+0xBB5C,0xBB5D,0xBB5E,0xBB5F,0xBB60,0xBB61,0xBB62,0xBB63,
+0xBB64,0xBB65,0xBB66,0xBB67,0xBB68,0xBB69,0xBB6A,0xBB6B,
+0xBB6C,0xBB6D,0xBB6E,0xC3D7,0xD9E1,0xBB6F,0xBB70,0xBB71,
+0xBB72,0xBB73,0xBB74,0xC0E0,0xF4CC,0xD7D1,0xBB75,0xBB76,
+0xBB77,0xBB78,0xBB79,0xBB7A,0xBB7B,0xBB7C,0xBB7D,0xBB7E,
+0xBB80,0xB7DB,0xBB81,0xBB82,0xBB83,0xBB84,0xBB85,0xBB86,
+0xBB87,0xF4CE,0xC1A3,0xBB88,0xBB89,0xC6C9,0xBB8A,0xB4D6,
+0xD5B3,0xBB8B,0xBB8C,0xBB8D,0xF4D0,0xF4CF,0xF4D1,0xCBDA,
+0xBB8E,0xBB8F,0xF4D2,0xBB90,0xD4C1,0xD6E0,0xBB91,0xBB92,
+0xBB93,0xBB94,0xB7E0,0xBB95,0xBB96,0xBB97,0xC1B8,0xBB98,
+0xBB99,0xC1BB,0xF4D3,0xBEAC,0xBB9A,0xBB9B,0xBB9C,0xBB9D,
+0xBB9E,0xB4E2,0xBB9F,0xBBA0,0xF4D4,0xF4D5,0xBEAB,0xBC40,
+0xBC41,0xF4D6,0xBC42,0xBC43,0xBC44,0xF4DB,0xBC45,0xF4D7,
+0xF4DA,0xBC46,0xBAFD,0xBC47,0xF4D8,0xF4D9,0xBC48,0xBC49,
+0xBC4A,0xBC4B,0xBC4C,0xBC4D,0xBC4E,0xB8E2,0xCCC7,0xF4DC,
+0xBC4F,0xB2DA,0xBC50,0xBC51,0xC3D3,0xBC52,0xBC53,0xD4E3,
+0xBFB7,0xBC54,0xBC55,0xBC56,0xBC57,0xBC58,0xBC59,0xBC5A,
+0xF4DD,0xBC5B,0xBC5C,0xBC5D,0xBC5E,0xBC5F,0xBC60,0xC5B4,
+0xBC61,0xBC62,0xBC63,0xBC64,0xBC65,0xBC66,0xBC67,0xBC68,
+0xF4E9,0xBC69,0xBC6A,0xCFB5,0xBC6B,0xBC6C,0xBC6D,0xBC6E,
+0xBC6F,0xBC70,0xBC71,0xBC72,0xBC73,0xBC74,0xBC75,0xBC76,
+0xBC77,0xBC78,0xCEC9,0xBC79,0xBC7A,0xBC7B,0xBC7C,0xBC7D,
+0xBC7E,0xBC80,0xBC81,0xBC82,0xBC83,0xBC84,0xBC85,0xBC86,
+0xBC87,0xBC88,0xBC89,0xBC8A,0xBC8B,0xBC8C,0xBC8D,0xBC8E,
+0xCBD8,0xBC8F,0xCBF7,0xBC90,0xBC91,0xBC92,0xBC93,0xBDF4,
+0xBC94,0xBC95,0xBC96,0xD7CF,0xBC97,0xBC98,0xBC99,0xC0DB,
+0xBC9A,0xBC9B,0xBC9C,0xBC9D,0xBC9E,0xBC9F,0xBCA0,0xBD40,
+0xBD41,0xBD42,0xBD43,0xBD44,0xBD45,0xBD46,0xBD47,0xBD48,
+0xBD49,0xBD4A,0xBD4B,0xBD4C,0xBD4D,0xBD4E,0xBD4F,0xBD50,
+0xBD51,0xBD52,0xBD53,0xBD54,0xBD55,0xBD56,0xBD57,0xBD58,
+0xBD59,0xBD5A,0xBD5B,0xBD5C,0xBD5D,0xBD5E,0xBD5F,0xBD60,
+0xBD61,0xBD62,0xBD63,0xBD64,0xBD65,0xBD66,0xBD67,0xBD68,
+0xBD69,0xBD6A,0xBD6B,0xBD6C,0xBD6D,0xBD6E,0xBD6F,0xBD70,
+0xBD71,0xBD72,0xBD73,0xBD74,0xBD75,0xBD76,0xD0F5,0xBD77,
+0xBD78,0xBD79,0xBD7A,0xBD7B,0xBD7C,0xBD7D,0xBD7E,0xF4EA,
+0xBD80,0xBD81,0xBD82,0xBD83,0xBD84,0xBD85,0xBD86,0xBD87,
+0xBD88,0xBD89,0xBD8A,0xBD8B,0xBD8C,0xBD8D,0xBD8E,0xBD8F,
+0xBD90,0xBD91,0xBD92,0xBD93,0xBD94,0xBD95,0xBD96,0xBD97,
+0xBD98,0xBD99,0xBD9A,0xBD9B,0xBD9C,0xBD9D,0xBD9E,0xBD9F,
+0xBDA0,0xBE40,0xBE41,0xBE42,0xBE43,0xBE44,0xBE45,0xBE46,
+0xBE47,0xBE48,0xBE49,0xBE4A,0xBE4B,0xBE4C,0xF4EB,0xBE4D,
+0xBE4E,0xBE4F,0xBE50,0xBE51,0xBE52,0xBE53,0xF4EC,0xBE54,
+0xBE55,0xBE56,0xBE57,0xBE58,0xBE59,0xBE5A,0xBE5B,0xBE5C,
+0xBE5D,0xBE5E,0xBE5F,0xBE60,0xBE61,0xBE62,0xBE63,0xBE64,
+0xBE65,0xBE66,0xBE67,0xBE68,0xBE69,0xBE6A,0xBE6B,0xBE6C,
+0xBE6D,0xBE6E,0xBE6F,0xBE70,0xBE71,0xBE72,0xBE73,0xBE74,
+0xBE75,0xBE76,0xBE77,0xBE78,0xBE79,0xBE7A,0xBE7B,0xBE7C,
+0xBE7D,0xBE7E,0xBE80,0xBE81,0xBE82,0xBE83,0xBE84,0xBE85,
+0xBE86,0xBE87,0xBE88,0xBE89,0xBE8A,0xBE8B,0xBE8C,0xBE8D,
+0xBE8E,0xBE8F,0xBE90,0xBE91,0xBE92,0xBE93,0xBE94,0xBE95,
+0xBE96,0xBE97,0xBE98,0xBE99,0xBE9A,0xBE9B,0xBE9C,0xBE9D,
+0xBE9E,0xBE9F,0xBEA0,0xBF40,0xBF41,0xBF42,0xBF43,0xBF44,
+0xBF45,0xBF46,0xBF47,0xBF48,0xBF49,0xBF4A,0xBF4B,0xBF4C,
+0xBF4D,0xBF4E,0xBF4F,0xBF50,0xBF51,0xBF52,0xBF53,0xBF54,
+0xBF55,0xBF56,0xBF57,0xBF58,0xBF59,0xBF5A,0xBF5B,0xBF5C,
+0xBF5D,0xBF5E,0xBF5F,0xBF60,0xBF61,0xBF62,0xBF63,0xBF64,
+0xBF65,0xBF66,0xBF67,0xBF68,0xBF69,0xBF6A,0xBF6B,0xBF6C,
+0xBF6D,0xBF6E,0xBF6F,0xBF70,0xBF71,0xBF72,0xBF73,0xBF74,
+0xBF75,0xBF76,0xBF77,0xBF78,0xBF79,0xBF7A,0xBF7B,0xBF7C,
+0xBF7D,0xBF7E,0xBF80,0xF7E3,0xBF81,0xBF82,0xBF83,0xBF84,
+0xBF85,0xB7B1,0xBF86,0xBF87,0xBF88,0xBF89,0xBF8A,0xF4ED,
+0xBF8B,0xBF8C,0xBF8D,0xBF8E,0xBF8F,0xBF90,0xBF91,0xBF92,
+0xBF93,0xBF94,0xBF95,0xBF96,0xBF97,0xBF98,0xBF99,0xBF9A,
+0xBF9B,0xBF9C,0xBF9D,0xBF9E,0xBF9F,0xBFA0,0xC040,0xC041,
+0xC042,0xC043,0xC044,0xC045,0xC046,0xC047,0xC048,0xC049,
+0xC04A,0xC04B,0xC04C,0xC04D,0xC04E,0xC04F,0xC050,0xC051,
+0xC052,0xC053,0xC054,0xC055,0xC056,0xC057,0xC058,0xC059,
+0xC05A,0xC05B,0xC05C,0xC05D,0xC05E,0xC05F,0xC060,0xC061,
+0xC062,0xC063,0xD7EB,0xC064,0xC065,0xC066,0xC067,0xC068,
+0xC069,0xC06A,0xC06B,0xC06C,0xC06D,0xC06E,0xC06F,0xC070,
+0xC071,0xC072,0xC073,0xC074,0xC075,0xC076,0xC077,0xC078,
+0xC079,0xC07A,0xC07B,0xF4EE,0xC07C,0xC07D,0xC07E,0xE6F9,
+0xBEC0,0xE6FA,0xBAEC,0xE6FB,0xCFCB,0xE6FC,0xD4BC,0xBCB6,
+0xE6FD,0xE6FE,0xBCCD,0xC8D2,0xCEB3,0xE7A1,0xC080,0xB4BF,
+0xE7A2,0xC9B4,0xB8D9,0xC4C9,0xC081,0xD7DD,0xC2DA,0xB7D7,
+0xD6BD,0xCEC6,0xB7C4,0xC082,0xC083,0xC5A6,0xE7A3,0xCFDF,
+0xE7A4,0xE7A5,0xE7A6,0xC1B7,0xD7E9,0xC9F0,0xCFB8,0xD6AF,
+0xD6D5,0xE7A7,0xB0ED,0xE7A8,0xE7A9,0xC9DC,0xD2EF,0xBEAD,
+0xE7AA,0xB0F3,0xC8DE,0xBDE1,0xE7AB,0xC8C6,0xC084,0xE7AC,
+0xBBE6,0xB8F8,0xD1A4,0xE7AD,0xC2E7,0xBEF8,0xBDCA,0xCDB3,
+0xE7AE,0xE7AF,0xBEEE,0xD0E5,0xC085,0xCBE7,0xCCD0,0xBCCC,
+0xE7B0,0xBCA8,0xD0F7,0xE7B1,0xC086,0xD0F8,0xE7B2,0xE7B3,
+0xB4C2,0xE7B4,0xE7B5,0xC9FE,0xCEAC,0xC3E0,0xE7B7,0xB1C1,
+0xB3F1,0xC087,0xE7B8,0xE7B9,0xD7DB,0xD5C0,0xE7BA,0xC2CC,
+0xD7BA,0xE7BB,0xE7BC,0xE7BD,0xBCEA,0xC3E5,0xC0C2,0xE7BE,
+0xE7BF,0xBCA9,0xC088,0xE7C0,0xE7C1,0xE7B6,0xB6D0,0xE7C2,
+0xC089,0xE7C3,0xE7C4,0xBBBA,0xB5DE,0xC2C6,0xB1E0,0xE7C5,
+0xD4B5,0xE7C6,0xB8BF,0xE7C8,0xE7C7,0xB7EC,0xC08A,0xE7C9,
+0xB2F8,0xE7CA,0xE7CB,0xE7CC,0xE7CD,0xE7CE,0xE7CF,0xE7D0,
+0xD3A7,0xCBF5,0xE7D1,0xE7D2,0xE7D3,0xE7D4,0xC9C9,0xE7D5,
+0xE7D6,0xE7D7,0xE7D8,0xE7D9,0xBDC9,0xE7DA,0xF3BE,0xC08B,
+0xB8D7,0xC08C,0xC8B1,0xC08D,0xC08E,0xC08F,0xC090,0xC091,
+0xC092,0xC093,0xF3BF,0xC094,0xF3C0,0xF3C1,0xC095,0xC096,
+0xC097,0xC098,0xC099,0xC09A,0xC09B,0xC09C,0xC09D,0xC09E,
+0xB9DE,0xCDF8,0xC09F,0xC0A0,0xD8E8,0xBAB1,0xC140,0xC2DE,
+0xEEB7,0xC141,0xB7A3,0xC142,0xC143,0xC144,0xC145,0xEEB9,
+0xC146,0xEEB8,0xB0D5,0xC147,0xC148,0xC149,0xC14A,0xC14B,
+0xEEBB,0xD5D6,0xD7EF,0xC14C,0xC14D,0xC14E,0xD6C3,0xC14F,
+0xC150,0xEEBD,0xCAF0,0xC151,0xEEBC,0xC152,0xC153,0xC154,
+0xC155,0xEEBE,0xC156,0xC157,0xC158,0xC159,0xEEC0,0xC15A,
+0xC15B,0xEEBF,0xC15C,0xC15D,0xC15E,0xC15F,0xC160,0xC161,
+0xC162,0xC163,0xD1F2,0xC164,0xC7BC,0xC165,0xC3C0,0xC166,
+0xC167,0xC168,0xC169,0xC16A,0xB8E1,0xC16B,0xC16C,0xC16D,
+0xC16E,0xC16F,0xC1E7,0xC170,0xC171,0xF4C6,0xD0DF,0xF4C7,
+0xC172,0xCFDB,0xC173,0xC174,0xC8BA,0xC175,0xC176,0xF4C8,
+0xC177,0xC178,0xC179,0xC17A,0xC17B,0xC17C,0xC17D,0xF4C9,
+0xF4CA,0xC17E,0xF4CB,0xC180,0xC181,0xC182,0xC183,0xC184,
+0xD9FA,0xB8FE,0xC185,0xC186,0xE5F1,0xD3F0,0xC187,0xF4E0,
+0xC188,0xCECC,0xC189,0xC18A,0xC18B,0xB3E1,0xC18C,0xC18D,
+0xC18E,0xC18F,0xF1B4,0xC190,0xD2EE,0xC191,0xF4E1,0xC192,
+0xC193,0xC194,0xC195,0xC196,0xCFE8,0xF4E2,0xC197,0xC198,
+0xC7CC,0xC199,0xC19A,0xC19B,0xC19C,0xC19D,0xC19E,0xB5D4,
+0xB4E4,0xF4E4,0xC19F,0xC1A0,0xC240,0xF4E3,0xF4E5,0xC241,
+0xC242,0xF4E6,0xC243,0xC244,0xC245,0xC246,0xF4E7,0xC247,
+0xBAB2,0xB0BF,0xC248,0xF4E8,0xC249,0xC24A,0xC24B,0xC24C,
+0xC24D,0xC24E,0xC24F,0xB7AD,0xD2ED,0xC250,0xC251,0xC252,
+0xD2AB,0xC0CF,0xC253,0xBFBC,0xEBA3,0xD5DF,0xEAC8,0xC254,
+0xC255,0xC256,0xC257,0xF1F3,0xB6F8,0xCBA3,0xC258,0xC259,
+0xC4CD,0xC25A,0xF1E7,0xC25B,0xF1E8,0xB8FB,0xF1E9,0xBAC4,
+0xD4C5,0xB0D2,0xC25C,0xC25D,0xF1EA,0xC25E,0xC25F,0xC260,
+0xF1EB,0xC261,0xF1EC,0xC262,0xC263,0xF1ED,0xF1EE,0xF1EF,
+0xF1F1,0xF1F0,0xC5D5,0xC264,0xC265,0xC266,0xC267,0xC268,
+0xC269,0xF1F2,0xC26A,0xB6FA,0xC26B,0xF1F4,0xD2AE,0xDEC7,
+0xCBCA,0xC26C,0xC26D,0xB3DC,0xC26E,0xB5A2,0xC26F,0xB9A2,
+0xC270,0xC271,0xC4F4,0xF1F5,0xC272,0xC273,0xF1F6,0xC274,
+0xC275,0xC276,0xC1C4,0xC1FB,0xD6B0,0xF1F7,0xC277,0xC278,
+0xC279,0xC27A,0xF1F8,0xC27B,0xC1AA,0xC27C,0xC27D,0xC27E,
+0xC6B8,0xC280,0xBEDB,0xC281,0xC282,0xC283,0xC284,0xC285,
+0xC286,0xC287,0xC288,0xC289,0xC28A,0xC28B,0xC28C,0xC28D,
+0xC28E,0xF1F9,0xB4CF,0xC28F,0xC290,0xC291,0xC292,0xC293,
+0xC294,0xF1FA,0xC295,0xC296,0xC297,0xC298,0xC299,0xC29A,
+0xC29B,0xC29C,0xC29D,0xC29E,0xC29F,0xC2A0,0xC340,0xEDB2,
+0xEDB1,0xC341,0xC342,0xCBE0,0xD2DE,0xC343,0xCBC1,0xD5D8,
+0xC344,0xC8E2,0xC345,0xC0DF,0xBCA1,0xC346,0xC347,0xC348,
+0xC349,0xC34A,0xC34B,0xEBC1,0xC34C,0xC34D,0xD0A4,0xC34E,
+0xD6E2,0xC34F,0xB6C7,0xB8D8,0xEBC0,0xB8CE,0xC350,0xEBBF,
+0xB3A6,0xB9C9,0xD6AB,0xC351,0xB7F4,0xB7CA,0xC352,0xC353,
+0xC354,0xBCE7,0xB7BE,0xEBC6,0xC355,0xEBC7,0xB0B9,0xBFCF,
+0xC356,0xEBC5,0xD3FD,0xC357,0xEBC8,0xC358,0xC359,0xEBC9,
+0xC35A,0xC35B,0xB7CE,0xC35C,0xEBC2,0xEBC4,0xC9F6,0xD6D7,
+0xD5CD,0xD0B2,0xEBCF,0xCEB8,0xEBD0,0xC35D,0xB5A8,0xC35E,
+0xC35F,0xC360,0xC361,0xC362,0xB1B3,0xEBD2,0xCCA5,0xC363,
+0xC364,0xC365,0xC366,0xC367,0xC368,0xC369,0xC5D6,0xEBD3,
+0xC36A,0xEBD1,0xC5DF,0xEBCE,0xCAA4,0xEBD5,0xB0FB,0xC36B,
+0xC36C,0xBAFA,0xC36D,0xC36E,0xD8B7,0xF1E3,0xC36F,0xEBCA,
+0xEBCB,0xEBCC,0xEBCD,0xEBD6,0xE6C0,0xEBD9,0xC370,0xBFE8,
+0xD2C8,0xEBD7,0xEBDC,0xB8EC,0xEBD8,0xC371,0xBDBA,0xC372,
+0xD0D8,0xC373,0xB0B7,0xC374,0xEBDD,0xC4DC,0xC375,0xC376,
+0xC377,0xC378,0xD6AC,0xC379,0xC37A,0xC37B,0xB4E0,0xC37C,
+0xC37D,0xC2F6,0xBCB9,0xC37E,0xC380,0xEBDA,0xEBDB,0xD4E0,
+0xC6EA,0xC4D4,0xEBDF,0xC5A7,0xD9F5,0xC381,0xB2B1,0xC382,
+0xEBE4,0xC383,0xBDC5,0xC384,0xC385,0xC386,0xEBE2,0xC387,
+0xC388,0xC389,0xC38A,0xC38B,0xC38C,0xC38D,0xC38E,0xC38F,
+0xC390,0xC391,0xC392,0xC393,0xEBE3,0xC394,0xC395,0xB8AC,
+0xC396,0xCDD1,0xEBE5,0xC397,0xC398,0xC399,0xEBE1,0xC39A,
+0xC1B3,0xC39B,0xC39C,0xC39D,0xC39E,0xC39F,0xC6A2,0xC3A0,
+0xC440,0xC441,0xC442,0xC443,0xC444,0xC445,0xCCF3,0xC446,
+0xEBE6,0xC447,0xC0B0,0xD2B8,0xEBE7,0xC448,0xC449,0xC44A,
+0xB8AF,0xB8AD,0xC44B,0xEBE8,0xC7BB,0xCDF3,0xC44C,0xC44D,
+0xC44E,0xEBEA,0xEBEB,0xC44F,0xC450,0xC451,0xC452,0xC453,
+0xEBED,0xC454,0xC455,0xC456,0xC457,0xD0C8,0xC458,0xEBF2,
+0xC459,0xEBEE,0xC45A,0xC45B,0xC45C,0xEBF1,0xC8F9,0xC45D,
+0xD1FC,0xEBEC,0xC45E,0xC45F,0xEBE9,0xC460,0xC461,0xC462,
+0xC463,0xB8B9,0xCFD9,0xC4E5,0xEBEF,0xEBF0,0xCCDA,0xCDC8,
+0xB0F2,0xC464,0xEBF6,0xC465,0xC466,0xC467,0xC468,0xC469,
+0xEBF5,0xC46A,0xB2B2,0xC46B,0xC46C,0xC46D,0xC46E,0xB8E0,
+0xC46F,0xEBF7,0xC470,0xC471,0xC472,0xC473,0xC474,0xC475,
+0xB1EC,0xC476,0xC477,0xCCC5,0xC4A4,0xCFA5,0xC478,0xC479,
+0xC47A,0xC47B,0xC47C,0xEBF9,0xC47D,0xC47E,0xECA2,0xC480,
+0xC5F2,0xC481,0xEBFA,0xC482,0xC483,0xC484,0xC485,0xC486,
+0xC487,0xC488,0xC489,0xC9C5,0xC48A,0xC48B,0xC48C,0xC48D,
+0xC48E,0xC48F,0xE2DF,0xEBFE,0xC490,0xC491,0xC492,0xC493,
+0xCDCE,0xECA1,0xB1DB,0xD3B7,0xC494,0xC495,0xD2DC,0xC496,
+0xC497,0xC498,0xEBFD,0xC499,0xEBFB,0xC49A,0xC49B,0xC49C,
+0xC49D,0xC49E,0xC49F,0xC4A0,0xC540,0xC541,0xC542,0xC543,
+0xC544,0xC545,0xC546,0xC547,0xC548,0xC549,0xC54A,0xC54B,
+0xC54C,0xC54D,0xC54E,0xB3BC,0xC54F,0xC550,0xC551,0xEAB0,
+0xC552,0xC553,0xD7D4,0xC554,0xF4AB,0xB3F4,0xC555,0xC556,
+0xC557,0xC558,0xC559,0xD6C1,0xD6C2,0xC55A,0xC55B,0xC55C,
+0xC55D,0xC55E,0xC55F,0xD5E9,0xBECA,0xC560,0xF4A7,0xC561,
+0xD2A8,0xF4A8,0xF4A9,0xC562,0xF4AA,0xBECB,0xD3DF,0xC563,
+0xC564,0xC565,0xC566,0xC567,0xC9E0,0xC9E1,0xC568,0xC569,
+0xF3C2,0xC56A,0xCAE6,0xC56B,0xCCF2,0xC56C,0xC56D,0xC56E,
+0xC56F,0xC570,0xC571,0xE2B6,0xCBB4,0xC572,0xCEE8,0xD6DB,
+0xC573,0xF4AD,0xF4AE,0xF4AF,0xC574,0xC575,0xC576,0xC577,
+0xF4B2,0xC578,0xBABD,0xF4B3,0xB0E3,0xF4B0,0xC579,0xF4B1,
+0xBDA2,0xB2D5,0xC57A,0xF4B6,0xF4B7,0xB6E6,0xB2B0,0xCFCF,
+0xF4B4,0xB4AC,0xC57B,0xF4B5,0xC57C,0xC57D,0xF4B8,0xC57E,
+0xC580,0xC581,0xC582,0xC583,0xF4B9,0xC584,0xC585,0xCDA7,
+0xC586,0xF4BA,0xC587,0xF4BB,0xC588,0xC589,0xC58A,0xF4BC,
+0xC58B,0xC58C,0xC58D,0xC58E,0xC58F,0xC590,0xC591,0xC592,
+0xCBD2,0xC593,0xF4BD,0xC594,0xC595,0xC596,0xC597,0xF4BE,
+0xC598,0xC599,0xC59A,0xC59B,0xC59C,0xC59D,0xC59E,0xC59F,
+0xF4BF,0xC5A0,0xC640,0xC641,0xC642,0xC643,0xF4DE,0xC1BC,
+0xBCE8,0xC644,0xC9AB,0xD1DE,0xE5F5,0xC645,0xC646,0xC647,
+0xC648,0xDCB3,0xD2D5,0xC649,0xC64A,0xDCB4,0xB0AC,0xDCB5,
+0xC64B,0xC64C,0xBDDA,0xC64D,0xDCB9,0xC64E,0xC64F,0xC650,
+0xD8C2,0xC651,0xDCB7,0xD3F3,0xC652,0xC9D6,0xDCBA,0xDCB6,
+0xC653,0xDCBB,0xC3A2,0xC654,0xC655,0xC656,0xC657,0xDCBC,
+0xDCC5,0xDCBD,0xC658,0xC659,0xCEDF,0xD6A5,0xC65A,0xDCCF,
+0xC65B,0xDCCD,0xC65C,0xC65D,0xDCD2,0xBDE6,0xC2AB,0xC65E,
+0xDCB8,0xDCCB,0xDCCE,0xDCBE,0xB7D2,0xB0C5,0xDCC7,0xD0BE,
+0xDCC1,0xBBA8,0xC65F,0xB7BC,0xDCCC,0xC660,0xC661,0xDCC6,
+0xDCBF,0xC7DB,0xC662,0xC663,0xC664,0xD1BF,0xDCC0,0xC665,
+0xC666,0xDCCA,0xC667,0xC668,0xDCD0,0xC669,0xC66A,0xCEAD,
+0xDCC2,0xC66B,0xDCC3,0xDCC8,0xDCC9,0xB2D4,0xDCD1,0xCBD5,
+0xC66C,0xD4B7,0xDCDB,0xDCDF,0xCCA6,0xDCE6,0xC66D,0xC3E7,
+0xDCDC,0xC66E,0xC66F,0xBFC1,0xDCD9,0xC670,0xB0FA,0xB9B6,
+0xDCE5,0xDCD3,0xC671,0xDCC4,0xDCD6,0xC8F4,0xBFE0,0xC672,
+0xC673,0xC674,0xC675,0xC9BB,0xC676,0xC677,0xC678,0xB1BD,
+0xC679,0xD3A2,0xC67A,0xC67B,0xDCDA,0xC67C,0xC67D,0xDCD5,
+0xC67E,0xC6BB,0xC680,0xDCDE,0xC681,0xC682,0xC683,0xC684,
+0xC685,0xD7C2,0xC3AF,0xB7B6,0xC7D1,0xC3A9,0xDCE2,0xDCD8,
+0xDCEB,0xDCD4,0xC686,0xC687,0xDCDD,0xC688,0xBEA5,0xDCD7,
+0xC689,0xDCE0,0xC68A,0xC68B,0xDCE3,0xDCE4,0xC68C,0xDCF8,
+0xC68D,0xC68E,0xDCE1,0xDDA2,0xDCE7,0xC68F,0xC690,0xC691,
+0xC692,0xC693,0xC694,0xC695,0xC696,0xC697,0xC698,0xBCEB,
+0xB4C4,0xC699,0xC69A,0xC3A3,0xB2E7,0xDCFA,0xC69B,0xDCF2,
+0xC69C,0xDCEF,0xC69D,0xDCFC,0xDCEE,0xD2F0,0xB2E8,0xC69E,
+0xC8D7,0xC8E3,0xDCFB,0xC69F,0xDCED,0xC6A0,0xC740,0xC741,
+0xDCF7,0xC742,0xC743,0xDCF5,0xC744,0xC745,0xBEA3,0xDCF4,
+0xC746,0xB2DD,0xC747,0xC748,0xC749,0xC74A,0xC74B,0xDCF3,
+0xBCF6,0xDCE8,0xBBC4,0xC74C,0xC0F3,0xC74D,0xC74E,0xC74F,
+0xC750,0xC751,0xBCD4,0xDCE9,0xDCEA,0xC752,0xDCF1,0xDCF6,
+0xDCF9,0xB5B4,0xC753,0xC8D9,0xBBE7,0xDCFE,0xDCFD,0xD3AB,
+0xDDA1,0xDDA3,0xDDA5,0xD2F1,0xDDA4,0xDDA6,0xDDA7,0xD2A9,
+0xC754,0xC755,0xC756,0xC757,0xC758,0xC759,0xC75A,0xBAC9,
+0xDDA9,0xC75B,0xC75C,0xDDB6,0xDDB1,0xDDB4,0xC75D,0xC75E,
+0xC75F,0xC760,0xC761,0xC762,0xC763,0xDDB0,0xC6CE,0xC764,
+0xC765,0xC0F2,0xC766,0xC767,0xC768,0xC769,0xC9AF,0xC76A,
+0xC76B,0xC76C,0xDCEC,0xDDAE,0xC76D,0xC76E,0xC76F,0xC770,
+0xDDB7,0xC771,0xC772,0xDCF0,0xDDAF,0xC773,0xDDB8,0xC774,
+0xDDAC,0xC775,0xC776,0xC777,0xC778,0xC779,0xC77A,0xC77B,
+0xDDB9,0xDDB3,0xDDAD,0xC4AA,0xC77C,0xC77D,0xC77E,0xC780,
+0xDDA8,0xC0B3,0xC1AB,0xDDAA,0xDDAB,0xC781,0xDDB2,0xBBF1,
+0xDDB5,0xD3A8,0xDDBA,0xC782,0xDDBB,0xC3A7,0xC783,0xC784,
+0xDDD2,0xDDBC,0xC785,0xC786,0xC787,0xDDD1,0xC788,0xB9BD,
+0xC789,0xC78A,0xBED5,0xC78B,0xBEFA,0xC78C,0xC78D,0xBACA,
+0xC78E,0xC78F,0xC790,0xC791,0xDDCA,0xC792,0xDDC5,0xC793,
+0xDDBF,0xC794,0xC795,0xC796,0xB2CB,0xDDC3,0xC797,0xDDCB,
+0xB2A4,0xDDD5,0xC798,0xC799,0xC79A,0xDDBE,0xC79B,0xC79C,
+0xC79D,0xC6D0,0xDDD0,0xC79E,0xC79F,0xC7A0,0xC840,0xC841,
+0xDDD4,0xC1E2,0xB7C6,0xC842,0xC843,0xC844,0xC845,0xC846,
+0xDDCE,0xDDCF,0xC847,0xC848,0xC849,0xDDC4,0xC84A,0xC84B,
+0xC84C,0xDDBD,0xC84D,0xDDCD,0xCCD1,0xC84E,0xDDC9,0xC84F,
+0xC850,0xC851,0xC852,0xDDC2,0xC3C8,0xC6BC,0xCEAE,0xDDCC,
+0xC853,0xDDC8,0xC854,0xC855,0xC856,0xC857,0xC858,0xC859,
+0xDDC1,0xC85A,0xC85B,0xC85C,0xDDC6,0xC2DC,0xC85D,0xC85E,
+0xC85F,0xC860,0xC861,0xC862,0xD3A9,0xD3AA,0xDDD3,0xCFF4,
+0xC8F8,0xC863,0xC864,0xC865,0xC866,0xC867,0xC868,0xC869,
+0xC86A,0xDDE6,0xC86B,0xC86C,0xC86D,0xC86E,0xC86F,0xC870,
+0xDDC7,0xC871,0xC872,0xC873,0xDDE0,0xC2E4,0xC874,0xC875,
+0xC876,0xC877,0xC878,0xC879,0xC87A,0xC87B,0xDDE1,0xC87C,
+0xC87D,0xC87E,0xC880,0xC881,0xC882,0xC883,0xC884,0xC885,
+0xC886,0xDDD7,0xC887,0xC888,0xC889,0xC88A,0xC88B,0xD6F8,
+0xC88C,0xDDD9,0xDDD8,0xB8F0,0xDDD6,0xC88D,0xC88E,0xC88F,
+0xC890,0xC6CF,0xC891,0xB6AD,0xC892,0xC893,0xC894,0xC895,
+0xC896,0xDDE2,0xC897,0xBAF9,0xD4E1,0xDDE7,0xC898,0xC899,
+0xC89A,0xB4D0,0xC89B,0xDDDA,0xC89C,0xBFFB,0xDDE3,0xC89D,
+0xDDDF,0xC89E,0xDDDD,0xC89F,0xC8A0,0xC940,0xC941,0xC942,
+0xC943,0xC944,0xB5D9,0xC945,0xC946,0xC947,0xC948,0xDDDB,
+0xDDDC,0xDDDE,0xC949,0xBDAF,0xDDE4,0xC94A,0xDDE5,0xC94B,
+0xC94C,0xC94D,0xC94E,0xC94F,0xC950,0xC951,0xC952,0xDDF5,
+0xC953,0xC3C9,0xC954,0xC955,0xCBE2,0xC956,0xC957,0xC958,
+0xC959,0xDDF2,0xC95A,0xC95B,0xC95C,0xC95D,0xC95E,0xC95F,
+0xC960,0xC961,0xC962,0xC963,0xC964,0xC965,0xC966,0xD8E1,
+0xC967,0xC968,0xC6D1,0xC969,0xDDF4,0xC96A,0xC96B,0xC96C,
+0xD5F4,0xDDF3,0xDDF0,0xC96D,0xC96E,0xDDEC,0xC96F,0xDDEF,
+0xC970,0xDDE8,0xC971,0xC972,0xD0EE,0xC973,0xC974,0xC975,
+0xC976,0xC8D8,0xDDEE,0xC977,0xC978,0xDDE9,0xC979,0xC97A,
+0xDDEA,0xCBF2,0xC97B,0xDDED,0xC97C,0xC97D,0xB1CD,0xC97E,
+0xC980,0xC981,0xC982,0xC983,0xC984,0xC0B6,0xC985,0xBCBB,
+0xDDF1,0xC986,0xC987,0xDDF7,0xC988,0xDDF6,0xDDEB,0xC989,
+0xC98A,0xC98B,0xC98C,0xC98D,0xC5EE,0xC98E,0xC98F,0xC990,
+0xDDFB,0xC991,0xC992,0xC993,0xC994,0xC995,0xC996,0xC997,
+0xC998,0xC999,0xC99A,0xC99B,0xDEA4,0xC99C,0xC99D,0xDEA3,
+0xC99E,0xC99F,0xC9A0,0xCA40,0xCA41,0xCA42,0xCA43,0xCA44,
+0xCA45,0xCA46,0xCA47,0xCA48,0xDDF8,0xCA49,0xCA4A,0xCA4B,
+0xCA4C,0xC3EF,0xCA4D,0xC2FB,0xCA4E,0xCA4F,0xCA50,0xD5E1,
+0xCA51,0xCA52,0xCEB5,0xCA53,0xCA54,0xCA55,0xCA56,0xDDFD,
+0xCA57,0xB2CC,0xCA58,0xCA59,0xCA5A,0xCA5B,0xCA5C,0xCA5D,
+0xCA5E,0xCA5F,0xCA60,0xC4E8,0xCADF,0xCA61,0xCA62,0xCA63,
+0xCA64,0xCA65,0xCA66,0xCA67,0xCA68,0xCA69,0xCA6A,0xC7BE,
+0xDDFA,0xDDFC,0xDDFE,0xDEA2,0xB0AA,0xB1CE,0xCA6B,0xCA6C,
+0xCA6D,0xCA6E,0xCA6F,0xDEAC,0xCA70,0xCA71,0xCA72,0xCA73,
+0xDEA6,0xBDB6,0xC8EF,0xCA74,0xCA75,0xCA76,0xCA77,0xCA78,
+0xCA79,0xCA7A,0xCA7B,0xCA7C,0xCA7D,0xCA7E,0xDEA1,0xCA80,
+0xCA81,0xDEA5,0xCA82,0xCA83,0xCA84,0xCA85,0xDEA9,0xCA86,
+0xCA87,0xCA88,0xCA89,0xCA8A,0xDEA8,0xCA8B,0xCA8C,0xCA8D,
+0xDEA7,0xCA8E,0xCA8F,0xCA90,0xCA91,0xCA92,0xCA93,0xCA94,
+0xCA95,0xCA96,0xDEAD,0xCA97,0xD4CC,0xCA98,0xCA99,0xCA9A,
+0xCA9B,0xDEB3,0xDEAA,0xDEAE,0xCA9C,0xCA9D,0xC0D9,0xCA9E,
+0xCA9F,0xCAA0,0xCB40,0xCB41,0xB1A1,0xDEB6,0xCB42,0xDEB1,
+0xCB43,0xCB44,0xCB45,0xCB46,0xCB47,0xCB48,0xCB49,0xDEB2,
+0xCB4A,0xCB4B,0xCB4C,0xCB4D,0xCB4E,0xCB4F,0xCB50,0xCB51,
+0xCB52,0xCB53,0xCB54,0xD1A6,0xDEB5,0xCB55,0xCB56,0xCB57,
+0xCB58,0xCB59,0xCB5A,0xCB5B,0xDEAF,0xCB5C,0xCB5D,0xCB5E,
+0xDEB0,0xCB5F,0xD0BD,0xCB60,0xCB61,0xCB62,0xDEB4,0xCAED,
+0xDEB9,0xCB63,0xCB64,0xCB65,0xCB66,0xCB67,0xCB68,0xDEB8,
+0xCB69,0xDEB7,0xCB6A,0xCB6B,0xCB6C,0xCB6D,0xCB6E,0xCB6F,
+0xCB70,0xDEBB,0xCB71,0xCB72,0xCB73,0xCB74,0xCB75,0xCB76,
+0xCB77,0xBDE5,0xCB78,0xCB79,0xCB7A,0xCB7B,0xCB7C,0xB2D8,
+0xC3EA,0xCB7D,0xCB7E,0xDEBA,0xCB80,0xC5BA,0xCB81,0xCB82,
+0xCB83,0xCB84,0xCB85,0xCB86,0xDEBC,0xCB87,0xCB88,0xCB89,
+0xCB8A,0xCB8B,0xCB8C,0xCB8D,0xCCD9,0xCB8E,0xCB8F,0xCB90,
+0xCB91,0xB7AA,0xCB92,0xCB93,0xCB94,0xCB95,0xCB96,0xCB97,
+0xCB98,0xCB99,0xCB9A,0xCB9B,0xCB9C,0xCB9D,0xCB9E,0xCB9F,
+0xCBA0,0xCC40,0xCC41,0xD4E5,0xCC42,0xCC43,0xCC44,0xDEBD,
+0xCC45,0xCC46,0xCC47,0xCC48,0xCC49,0xDEBF,0xCC4A,0xCC4B,
+0xCC4C,0xCC4D,0xCC4E,0xCC4F,0xCC50,0xCC51,0xCC52,0xCC53,
+0xCC54,0xC4A2,0xCC55,0xCC56,0xCC57,0xCC58,0xDEC1,0xCC59,
+0xCC5A,0xCC5B,0xCC5C,0xCC5D,0xCC5E,0xCC5F,0xCC60,0xCC61,
+0xCC62,0xCC63,0xCC64,0xCC65,0xCC66,0xCC67,0xCC68,0xDEBE,
+0xCC69,0xDEC0,0xCC6A,0xCC6B,0xCC6C,0xCC6D,0xCC6E,0xCC6F,
+0xCC70,0xCC71,0xCC72,0xCC73,0xCC74,0xCC75,0xCC76,0xCC77,
+0xD5BA,0xCC78,0xCC79,0xCC7A,0xDEC2,0xCC7B,0xCC7C,0xCC7D,
+0xCC7E,0xCC80,0xCC81,0xCC82,0xCC83,0xCC84,0xCC85,0xCC86,
+0xCC87,0xCC88,0xCC89,0xCC8A,0xCC8B,0xF2AE,0xBBA2,0xC2B2,
+0xC5B0,0xC2C7,0xCC8C,0xCC8D,0xF2AF,0xCC8E,0xCC8F,0xCC90,
+0xCC91,0xCC92,0xD0E9,0xCC93,0xCC94,0xCC95,0xD3DD,0xCC96,
+0xCC97,0xCC98,0xEBBD,0xCC99,0xCC9A,0xCC9B,0xCC9C,0xCC9D,
+0xCC9E,0xCC9F,0xCCA0,0xB3E6,0xF2B0,0xCD40,0xF2B1,0xCD41,
+0xCD42,0xCAAD,0xCD43,0xCD44,0xCD45,0xCD46,0xCD47,0xCD48,
+0xCD49,0xBAE7,0xF2B3,0xF2B5,0xF2B4,0xCBE4,0xCFBA,0xF2B2,
+0xCAB4,0xD2CF,0xC2EC,0xCD4A,0xCD4B,0xCD4C,0xCD4D,0xCD4E,
+0xCD4F,0xCD50,0xCEC3,0xF2B8,0xB0F6,0xF2B7,0xCD51,0xCD52,
+0xCD53,0xCD54,0xCD55,0xF2BE,0xCD56,0xB2CF,0xCD57,0xCD58,
+0xCD59,0xCD5A,0xCD5B,0xCD5C,0xD1C1,0xF2BA,0xCD5D,0xCD5E,
+0xCD5F,0xCD60,0xCD61,0xF2BC,0xD4E9,0xCD62,0xCD63,0xF2BB,
+0xF2B6,0xF2BF,0xF2BD,0xCD64,0xF2B9,0xCD65,0xCD66,0xF2C7,
+0xF2C4,0xF2C6,0xCD67,0xCD68,0xF2CA,0xF2C2,0xF2C0,0xCD69,
+0xCD6A,0xCD6B,0xF2C5,0xCD6C,0xCD6D,0xCD6E,0xCD6F,0xCD70,
+0xD6FB,0xCD71,0xCD72,0xCD73,0xF2C1,0xCD74,0xC7F9,0xC9DF,
+0xCD75,0xF2C8,0xB9C6,0xB5B0,0xCD76,0xCD77,0xF2C3,0xF2C9,
+0xF2D0,0xF2D6,0xCD78,0xCD79,0xBBD7,0xCD7A,0xCD7B,0xCD7C,
+0xF2D5,0xCDDC,0xCD7D,0xD6EB,0xCD7E,0xCD80,0xF2D2,0xF2D4,
+0xCD81,0xCD82,0xCD83,0xCD84,0xB8F2,0xCD85,0xCD86,0xCD87,
+0xCD88,0xF2CB,0xCD89,0xCD8A,0xCD8B,0xF2CE,0xC2F9,0xCD8C,
+0xD5DD,0xF2CC,0xF2CD,0xF2CF,0xF2D3,0xCD8D,0xCD8E,0xCD8F,
+0xF2D9,0xD3BC,0xCD90,0xCD91,0xCD92,0xCD93,0xB6EA,0xCD94,
+0xCAF1,0xCD95,0xB7E4,0xF2D7,0xCD96,0xCD97,0xCD98,0xF2D8,
+0xF2DA,0xF2DD,0xF2DB,0xCD99,0xCD9A,0xF2DC,0xCD9B,0xCD9C,
+0xCD9D,0xCD9E,0xD1D1,0xF2D1,0xCD9F,0xCDC9,0xCDA0,0xCECF,
+0xD6A9,0xCE40,0xF2E3,0xCE41,0xC3DB,0xCE42,0xF2E0,0xCE43,
+0xCE44,0xC0AF,0xF2EC,0xF2DE,0xCE45,0xF2E1,0xCE46,0xCE47,
+0xCE48,0xF2E8,0xCE49,0xCE4A,0xCE4B,0xCE4C,0xF2E2,0xCE4D,
+0xCE4E,0xF2E7,0xCE4F,0xCE50,0xF2E6,0xCE51,0xCE52,0xF2E9,
+0xCE53,0xCE54,0xCE55,0xF2DF,0xCE56,0xCE57,0xF2E4,0xF2EA,
+0xCE58,0xCE59,0xCE5A,0xCE5B,0xCE5C,0xCE5D,0xCE5E,0xD3AC,
+0xF2E5,0xB2F5,0xCE5F,0xCE60,0xF2F2,0xCE61,0xD0AB,0xCE62,
+0xCE63,0xCE64,0xCE65,0xF2F5,0xCE66,0xCE67,0xCE68,0xBBC8,
+0xCE69,0xF2F9,0xCE6A,0xCE6B,0xCE6C,0xCE6D,0xCE6E,0xCE6F,
+0xF2F0,0xCE70,0xCE71,0xF2F6,0xF2F8,0xF2FA,0xCE72,0xCE73,
+0xCE74,0xCE75,0xCE76,0xCE77,0xCE78,0xCE79,0xF2F3,0xCE7A,
+0xF2F1,0xCE7B,0xCE7C,0xCE7D,0xBAFB,0xCE7E,0xB5FB,0xCE80,
+0xCE81,0xCE82,0xCE83,0xF2EF,0xF2F7,0xF2ED,0xF2EE,0xCE84,
+0xCE85,0xCE86,0xF2EB,0xF3A6,0xCE87,0xF3A3,0xCE88,0xCE89,
+0xF3A2,0xCE8A,0xCE8B,0xF2F4,0xCE8C,0xC8DA,0xCE8D,0xCE8E,
+0xCE8F,0xCE90,0xCE91,0xF2FB,0xCE92,0xCE93,0xCE94,0xF3A5,
+0xCE95,0xCE96,0xCE97,0xCE98,0xCE99,0xCE9A,0xCE9B,0xC3F8,
+0xCE9C,0xCE9D,0xCE9E,0xCE9F,0xCEA0,0xCF40,0xCF41,0xCF42,
+0xF2FD,0xCF43,0xCF44,0xF3A7,0xF3A9,0xF3A4,0xCF45,0xF2FC,
+0xCF46,0xCF47,0xCF48,0xF3AB,0xCF49,0xF3AA,0xCF4A,0xCF4B,
+0xCF4C,0xCF4D,0xC2DD,0xCF4E,0xCF4F,0xF3AE,0xCF50,0xCF51,
+0xF3B0,0xCF52,0xCF53,0xCF54,0xCF55,0xCF56,0xF3A1,0xCF57,
+0xCF58,0xCF59,0xF3B1,0xF3AC,0xCF5A,0xCF5B,0xCF5C,0xCF5D,
+0xCF5E,0xF3AF,0xF2FE,0xF3AD,0xCF5F,0xCF60,0xCF61,0xCF62,
+0xCF63,0xCF64,0xCF65,0xF3B2,0xCF66,0xCF67,0xCF68,0xCF69,
+0xF3B4,0xCF6A,0xCF6B,0xCF6C,0xCF6D,0xF3A8,0xCF6E,0xCF6F,
+0xCF70,0xCF71,0xF3B3,0xCF72,0xCF73,0xCF74,0xF3B5,0xCF75,
+0xCF76,0xCF77,0xCF78,0xCF79,0xCF7A,0xCF7B,0xCF7C,0xCF7D,
+0xCF7E,0xD0B7,0xCF80,0xCF81,0xCF82,0xCF83,0xF3B8,0xCF84,
+0xCF85,0xCF86,0xCF87,0xD9F9,0xCF88,0xCF89,0xCF8A,0xCF8B,
+0xCF8C,0xCF8D,0xF3B9,0xCF8E,0xCF8F,0xCF90,0xCF91,0xCF92,
+0xCF93,0xCF94,0xCF95,0xF3B7,0xCF96,0xC8E4,0xF3B6,0xCF97,
+0xCF98,0xCF99,0xCF9A,0xF3BA,0xCF9B,0xCF9C,0xCF9D,0xCF9E,
+0xCF9F,0xF3BB,0xB4C0,0xCFA0,0xD040,0xD041,0xD042,0xD043,
+0xD044,0xD045,0xD046,0xD047,0xD048,0xD049,0xD04A,0xD04B,
+0xD04C,0xD04D,0xEEC3,0xD04E,0xD04F,0xD050,0xD051,0xD052,
+0xD053,0xF3BC,0xD054,0xD055,0xF3BD,0xD056,0xD057,0xD058,
+0xD1AA,0xD059,0xD05A,0xD05B,0xF4AC,0xD0C6,0xD05C,0xD05D,
+0xD05E,0xD05F,0xD060,0xD061,0xD0D0,0xD1DC,0xD062,0xD063,
+0xD064,0xD065,0xD066,0xD067,0xCFCE,0xD068,0xD069,0xBDD6,
+0xD06A,0xD1C3,0xD06B,0xD06C,0xD06D,0xD06E,0xD06F,0xD070,
+0xD071,0xBAE2,0xE1E9,0xD2C2,0xF1C2,0xB2B9,0xD072,0xD073,
+0xB1ED,0xF1C3,0xD074,0xC9C0,0xB3C4,0xD075,0xD9F2,0xD076,
+0xCBA5,0xD077,0xF1C4,0xD078,0xD079,0xD07A,0xD07B,0xD6D4,
+0xD07C,0xD07D,0xD07E,0xD080,0xD081,0xF1C5,0xF4C0,0xF1C6,
+0xD082,0xD4AC,0xF1C7,0xD083,0xB0C0,0xF4C1,0xD084,0xD085,
+0xF4C2,0xD086,0xD087,0xB4FC,0xD088,0xC5DB,0xD089,0xD08A,
+0xD08B,0xD08C,0xCCBB,0xD08D,0xD08E,0xD08F,0xD0E4,0xD090,
+0xD091,0xD092,0xD093,0xD094,0xCDE0,0xD095,0xD096,0xD097,
+0xD098,0xD099,0xF1C8,0xD09A,0xD9F3,0xD09B,0xD09C,0xD09D,
+0xD09E,0xD09F,0xD0A0,0xB1BB,0xD140,0xCFAE,0xD141,0xD142,
+0xD143,0xB8A4,0xD144,0xD145,0xD146,0xD147,0xD148,0xF1CA,
+0xD149,0xD14A,0xD14B,0xD14C,0xF1CB,0xD14D,0xD14E,0xD14F,
+0xD150,0xB2C3,0xC1D1,0xD151,0xD152,0xD7B0,0xF1C9,0xD153,
+0xD154,0xF1CC,0xD155,0xD156,0xD157,0xD158,0xF1CE,0xD159,
+0xD15A,0xD15B,0xD9F6,0xD15C,0xD2E1,0xD4A3,0xD15D,0xD15E,
+0xF4C3,0xC8B9,0xD15F,0xD160,0xD161,0xD162,0xD163,0xF4C4,
+0xD164,0xD165,0xF1CD,0xF1CF,0xBFE3,0xF1D0,0xD166,0xD167,
+0xF1D4,0xD168,0xD169,0xD16A,0xD16B,0xD16C,0xD16D,0xD16E,
+0xF1D6,0xF1D1,0xD16F,0xC9D1,0xC5E1,0xD170,0xD171,0xD172,
+0xC2E3,0xB9FC,0xD173,0xD174,0xF1D3,0xD175,0xF1D5,0xD176,
+0xD177,0xD178,0xB9D3,0xD179,0xD17A,0xD17B,0xD17C,0xD17D,
+0xD17E,0xD180,0xF1DB,0xD181,0xD182,0xD183,0xD184,0xD185,
+0xBAD6,0xD186,0xB0FD,0xF1D9,0xD187,0xD188,0xD189,0xD18A,
+0xD18B,0xF1D8,0xF1D2,0xF1DA,0xD18C,0xD18D,0xD18E,0xD18F,
+0xD190,0xF1D7,0xD191,0xD192,0xD193,0xC8EC,0xD194,0xD195,
+0xD196,0xD197,0xCDCA,0xF1DD,0xD198,0xD199,0xD19A,0xD19B,
+0xE5BD,0xD19C,0xD19D,0xD19E,0xF1DC,0xD19F,0xF1DE,0xD1A0,
+0xD240,0xD241,0xD242,0xD243,0xD244,0xD245,0xD246,0xD247,
+0xD248,0xF1DF,0xD249,0xD24A,0xCFE5,0xD24B,0xD24C,0xD24D,
+0xD24E,0xD24F,0xD250,0xD251,0xD252,0xD253,0xD254,0xD255,
+0xD256,0xD257,0xD258,0xD259,0xD25A,0xD25B,0xD25C,0xD25D,
+0xD25E,0xD25F,0xD260,0xD261,0xD262,0xD263,0xF4C5,0xBDF3,
+0xD264,0xD265,0xD266,0xD267,0xD268,0xD269,0xF1E0,0xD26A,
+0xD26B,0xD26C,0xD26D,0xD26E,0xD26F,0xD270,0xD271,0xD272,
+0xD273,0xD274,0xD275,0xD276,0xD277,0xD278,0xD279,0xD27A,
+0xD27B,0xD27C,0xD27D,0xF1E1,0xD27E,0xD280,0xD281,0xCEF7,
+0xD282,0xD2AA,0xD283,0xF1FB,0xD284,0xD285,0xB8B2,0xD286,
+0xD287,0xD288,0xD289,0xD28A,0xD28B,0xD28C,0xD28D,0xD28E,
+0xD28F,0xD290,0xD291,0xD292,0xD293,0xD294,0xD295,0xD296,
+0xD297,0xD298,0xD299,0xD29A,0xD29B,0xD29C,0xD29D,0xD29E,
+0xD29F,0xD2A0,0xD340,0xD341,0xD342,0xD343,0xD344,0xD345,
+0xD346,0xD347,0xD348,0xD349,0xD34A,0xD34B,0xD34C,0xD34D,
+0xD34E,0xD34F,0xD350,0xD351,0xD352,0xD353,0xD354,0xD355,
+0xD356,0xD357,0xD358,0xD359,0xD35A,0xD35B,0xD35C,0xD35D,
+0xD35E,0xBCFB,0xB9DB,0xD35F,0xB9E6,0xC3D9,0xCAD3,0xEAE8,
+0xC0C0,0xBEF5,0xEAE9,0xEAEA,0xEAEB,0xD360,0xEAEC,0xEAED,
+0xEAEE,0xEAEF,0xBDC7,0xD361,0xD362,0xD363,0xF5FB,0xD364,
+0xD365,0xD366,0xF5FD,0xD367,0xF5FE,0xD368,0xF5FC,0xD369,
+0xD36A,0xD36B,0xD36C,0xBDE2,0xD36D,0xF6A1,0xB4A5,0xD36E,
+0xD36F,0xD370,0xD371,0xF6A2,0xD372,0xD373,0xD374,0xF6A3,
+0xD375,0xD376,0xD377,0xECB2,0xD378,0xD379,0xD37A,0xD37B,
+0xD37C,0xD37D,0xD37E,0xD380,0xD381,0xD382,0xD383,0xD384,
+0xD1D4,0xD385,0xD386,0xD387,0xD388,0xD389,0xD38A,0xD9EA,
+0xD38B,0xD38C,0xD38D,0xD38E,0xD38F,0xD390,0xD391,0xD392,
+0xD393,0xD394,0xD395,0xD396,0xD397,0xD398,0xD399,0xD39A,
+0xD39B,0xD39C,0xD39D,0xD39E,0xD39F,0xD3A0,0xD440,0xD441,
+0xD442,0xD443,0xD444,0xD445,0xD446,0xD447,0xD448,0xD449,
+0xD44A,0xD44B,0xD44C,0xD44D,0xD44E,0xD44F,0xD450,0xD451,
+0xD452,0xD453,0xD454,0xD455,0xD456,0xD457,0xD458,0xD459,
+0xD45A,0xD45B,0xD45C,0xD45D,0xD45E,0xD45F,0xF6A4,0xD460,
+0xD461,0xD462,0xD463,0xD464,0xD465,0xD466,0xD467,0xD468,
+0xEEBA,0xD469,0xD46A,0xD46B,0xD46C,0xD46D,0xD46E,0xD46F,
+0xD470,0xD471,0xD472,0xD473,0xD474,0xD475,0xD476,0xD477,
+0xD478,0xD479,0xD47A,0xD47B,0xD47C,0xD47D,0xD47E,0xD480,
+0xD481,0xD482,0xD483,0xD484,0xD485,0xD486,0xD487,0xD488,
+0xD489,0xD48A,0xD48B,0xD48C,0xD48D,0xD48E,0xD48F,0xD490,
+0xD491,0xD492,0xD493,0xD494,0xD495,0xD496,0xD497,0xD498,
+0xD499,0xD5B2,0xD49A,0xD49B,0xD49C,0xD49D,0xD49E,0xD49F,
+0xD4A0,0xD540,0xD541,0xD542,0xD543,0xD544,0xD545,0xD546,
+0xD547,0xD3FE,0xCCDC,0xD548,0xD549,0xD54A,0xD54B,0xD54C,
+0xD54D,0xD54E,0xD54F,0xCAC4,0xD550,0xD551,0xD552,0xD553,
+0xD554,0xD555,0xD556,0xD557,0xD558,0xD559,0xD55A,0xD55B,
+0xD55C,0xD55D,0xD55E,0xD55F,0xD560,0xD561,0xD562,0xD563,
+0xD564,0xD565,0xD566,0xD567,0xD568,0xD569,0xD56A,0xD56B,
+0xD56C,0xD56D,0xD56E,0xD56F,0xD570,0xD571,0xD572,0xD573,
+0xD574,0xD575,0xD576,0xD577,0xD578,0xD579,0xD57A,0xD57B,
+0xD57C,0xD57D,0xD57E,0xD580,0xD581,0xD582,0xD583,0xD584,
+0xD585,0xD586,0xD587,0xD588,0xD589,0xD58A,0xD58B,0xD58C,
+0xD58D,0xD58E,0xD58F,0xD590,0xD591,0xD592,0xD593,0xD594,
+0xD595,0xD596,0xD597,0xD598,0xD599,0xD59A,0xD59B,0xD59C,
+0xD59D,0xD59E,0xD59F,0xD5A0,0xD640,0xD641,0xD642,0xD643,
+0xD644,0xD645,0xD646,0xD647,0xD648,0xD649,0xD64A,0xD64B,
+0xD64C,0xD64D,0xD64E,0xD64F,0xD650,0xD651,0xD652,0xD653,
+0xD654,0xD655,0xD656,0xD657,0xD658,0xD659,0xD65A,0xD65B,
+0xD65C,0xD65D,0xD65E,0xD65F,0xD660,0xD661,0xD662,0xE5C0,
+0xD663,0xD664,0xD665,0xD666,0xD667,0xD668,0xD669,0xD66A,
+0xD66B,0xD66C,0xD66D,0xD66E,0xD66F,0xD670,0xD671,0xD672,
+0xD673,0xD674,0xD675,0xD676,0xD677,0xD678,0xD679,0xD67A,
+0xD67B,0xD67C,0xD67D,0xD67E,0xD680,0xD681,0xF6A5,0xD682,
+0xD683,0xD684,0xD685,0xD686,0xD687,0xD688,0xD689,0xD68A,
+0xD68B,0xD68C,0xD68D,0xD68E,0xD68F,0xD690,0xD691,0xD692,
+0xD693,0xD694,0xD695,0xD696,0xD697,0xD698,0xD699,0xD69A,
+0xD69B,0xD69C,0xD69D,0xD69E,0xD69F,0xD6A0,0xD740,0xD741,
+0xD742,0xD743,0xD744,0xD745,0xD746,0xD747,0xD748,0xD749,
+0xD74A,0xD74B,0xD74C,0xD74D,0xD74E,0xD74F,0xD750,0xD751,
+0xD752,0xD753,0xD754,0xD755,0xD756,0xD757,0xD758,0xD759,
+0xD75A,0xD75B,0xD75C,0xD75D,0xD75E,0xD75F,0xBEAF,0xD760,
+0xD761,0xD762,0xD763,0xD764,0xC6A9,0xD765,0xD766,0xD767,
+0xD768,0xD769,0xD76A,0xD76B,0xD76C,0xD76D,0xD76E,0xD76F,
+0xD770,0xD771,0xD772,0xD773,0xD774,0xD775,0xD776,0xD777,
+0xD778,0xD779,0xD77A,0xD77B,0xD77C,0xD77D,0xD77E,0xD780,
+0xD781,0xD782,0xD783,0xD784,0xD785,0xD786,0xD787,0xD788,
+0xD789,0xD78A,0xD78B,0xD78C,0xD78D,0xD78E,0xD78F,0xD790,
+0xD791,0xD792,0xD793,0xD794,0xD795,0xD796,0xD797,0xD798,
+0xDAA5,0xBCC6,0xB6A9,0xB8BC,0xC8CF,0xBCA5,0xDAA6,0xDAA7,
+0xCCD6,0xC8C3,0xDAA8,0xC6FD,0xD799,0xD1B5,0xD2E9,0xD1B6,
+0xBCC7,0xD79A,0xBDB2,0xBBE4,0xDAA9,0xDAAA,0xD1C8,0xDAAB,
+0xD0ED,0xB6EF,0xC2DB,0xD79B,0xCBCF,0xB7ED,0xC9E8,0xB7C3,
+0xBEF7,0xD6A4,0xDAAC,0xDAAD,0xC6C0,0xD7E7,0xCAB6,0xD79C,
+0xD5A9,0xCBDF,0xD5EF,0xDAAE,0xD6DF,0xB4CA,0xDAB0,0xDAAF,
+0xD79D,0xD2EB,0xDAB1,0xDAB2,0xDAB3,0xCAD4,0xDAB4,0xCAAB,
+0xDAB5,0xDAB6,0xB3CF,0xD6EF,0xDAB7,0xBBB0,0xB5AE,0xDAB8,
+0xDAB9,0xB9EE,0xD1AF,0xD2E8,0xDABA,0xB8C3,0xCFEA,0xB2EF,
+0xDABB,0xDABC,0xD79E,0xBDEB,0xCEDC,0xD3EF,0xDABD,0xCEF3,
+0xDABE,0xD3D5,0xBBE5,0xDABF,0xCBB5,0xCBD0,0xDAC0,0xC7EB,
+0xD6EE,0xDAC1,0xC5B5,0xB6C1,0xDAC2,0xB7CC,0xBFCE,0xDAC3,
+0xDAC4,0xCBAD,0xDAC5,0xB5F7,0xDAC6,0xC1C2,0xD7BB,0xDAC7,
+0xCCB8,0xD79F,0xD2EA,0xC4B1,0xDAC8,0xB5FD,0xBBD1,0xDAC9,
+0xD0B3,0xDACA,0xDACB,0xCEBD,0xDACC,0xDACD,0xDACE,0xB2F7,
+0xDAD1,0xDACF,0xD1E8,0xDAD0,0xC3D5,0xDAD2,0xD7A0,0xDAD3,
+0xDAD4,0xDAD5,0xD0BB,0xD2A5,0xB0F9,0xDAD6,0xC7AB,0xDAD7,
+0xBDF7,0xC3A1,0xDAD8,0xDAD9,0xC3FD,0xCCB7,0xDADA,0xDADB,
+0xC0BE,0xC6D7,0xDADC,0xDADD,0xC7B4,0xDADE,0xDADF,0xB9C8,
+0xD840,0xD841,0xD842,0xD843,0xD844,0xD845,0xD846,0xD847,
+0xD848,0xBBED,0xD849,0xD84A,0xD84B,0xD84C,0xB6B9,0xF4F8,
+0xD84D,0xF4F9,0xD84E,0xD84F,0xCDE3,0xD850,0xD851,0xD852,
+0xD853,0xD854,0xD855,0xD856,0xD857,0xF5B9,0xD858,0xD859,
+0xD85A,0xD85B,0xEBE0,0xD85C,0xD85D,0xD85E,0xD85F,0xD860,
+0xD861,0xCFF3,0xBBBF,0xD862,0xD863,0xD864,0xD865,0xD866,
+0xD867,0xD868,0xBAC0,0xD4A5,0xD869,0xD86A,0xD86B,0xD86C,
+0xD86D,0xD86E,0xD86F,0xE1D9,0xD870,0xD871,0xD872,0xD873,
+0xF5F4,0xB1AA,0xB2F2,0xD874,0xD875,0xD876,0xD877,0xD878,
+0xD879,0xD87A,0xF5F5,0xD87B,0xD87C,0xF5F7,0xD87D,0xD87E,
+0xD880,0xBAD1,0xF5F6,0xD881,0xC3B2,0xD882,0xD883,0xD884,
+0xD885,0xD886,0xD887,0xD888,0xF5F9,0xD889,0xD88A,0xD88B,
+0xF5F8,0xD88C,0xD88D,0xD88E,0xD88F,0xD890,0xD891,0xD892,
+0xD893,0xD894,0xD895,0xD896,0xD897,0xD898,0xD899,0xD89A,
+0xD89B,0xD89C,0xD89D,0xD89E,0xD89F,0xD8A0,0xD940,0xD941,
+0xD942,0xD943,0xD944,0xD945,0xD946,0xD947,0xD948,0xD949,
+0xD94A,0xD94B,0xD94C,0xD94D,0xD94E,0xD94F,0xD950,0xD951,
+0xD952,0xD953,0xD954,0xD955,0xD956,0xD957,0xD958,0xD959,
+0xD95A,0xD95B,0xD95C,0xD95D,0xD95E,0xD95F,0xD960,0xD961,
+0xD962,0xD963,0xD964,0xD965,0xD966,0xD967,0xD968,0xD969,
+0xD96A,0xD96B,0xD96C,0xD96D,0xD96E,0xD96F,0xD970,0xD971,
+0xD972,0xD973,0xD974,0xD975,0xD976,0xD977,0xD978,0xD979,
+0xD97A,0xD97B,0xD97C,0xD97D,0xD97E,0xD980,0xD981,0xD982,
+0xD983,0xD984,0xD985,0xD986,0xD987,0xD988,0xD989,0xD98A,
+0xD98B,0xD98C,0xD98D,0xD98E,0xD98F,0xD990,0xD991,0xD992,
+0xD993,0xD994,0xD995,0xD996,0xD997,0xD998,0xD999,0xD99A,
+0xD99B,0xD99C,0xD99D,0xD99E,0xD99F,0xD9A0,0xDA40,0xDA41,
+0xDA42,0xDA43,0xDA44,0xDA45,0xDA46,0xDA47,0xDA48,0xDA49,
+0xDA4A,0xDA4B,0xDA4C,0xDA4D,0xDA4E,0xB1B4,0xD5EA,0xB8BA,
+0xDA4F,0xB9B1,0xB2C6,0xD4F0,0xCFCD,0xB0DC,0xD5CB,0xBBF5,
+0xD6CA,0xB7B7,0xCCB0,0xC6B6,0xB1E1,0xB9BA,0xD6FC,0xB9E1,
+0xB7A1,0xBCFA,0xEADA,0xEADB,0xCCF9,0xB9F3,0xEADC,0xB4FB,
+0xC3B3,0xB7D1,0xBAD8,0xEADD,0xD4F4,0xEADE,0xBCD6,0xBBDF,
+0xEADF,0xC1DE,0xC2B8,0xD4DF,0xD7CA,0xEAE0,0xEAE1,0xEAE4,
+0xEAE2,0xEAE3,0xC9DE,0xB8B3,0xB6C4,0xEAE5,0xCAEA,0xC9CD,
+0xB4CD,0xDA50,0xDA51,0xE2D9,0xC5E2,0xEAE6,0xC0B5,0xDA52,
+0xD7B8,0xEAE7,0xD7AC,0xC8FC,0xD8D3,0xD8CD,0xD4DE,0xDA53,
+0xD4F9,0xC9C4,0xD3AE,0xB8D3,0xB3E0,0xDA54,0xC9E2,0xF4F6,
+0xDA55,0xDA56,0xDA57,0xBAD5,0xDA58,0xF4F7,0xDA59,0xDA5A,
+0xD7DF,0xDA5B,0xDA5C,0xF4F1,0xB8B0,0xD5D4,0xB8CF,0xC6F0,
+0xDA5D,0xDA5E,0xDA5F,0xDA60,0xDA61,0xDA62,0xDA63,0xDA64,
+0xDA65,0xB3C3,0xDA66,0xDA67,0xF4F2,0xB3AC,0xDA68,0xDA69,
+0xDA6A,0xDA6B,0xD4BD,0xC7F7,0xDA6C,0xDA6D,0xDA6E,0xDA6F,
+0xDA70,0xF4F4,0xDA71,0xDA72,0xF4F3,0xDA73,0xDA74,0xDA75,
+0xDA76,0xDA77,0xDA78,0xDA79,0xDA7A,0xDA7B,0xDA7C,0xCCCB,
+0xDA7D,0xDA7E,0xDA80,0xC8A4,0xDA81,0xDA82,0xDA83,0xDA84,
+0xDA85,0xDA86,0xDA87,0xDA88,0xDA89,0xDA8A,0xDA8B,0xDA8C,
+0xDA8D,0xF4F5,0xDA8E,0xD7E3,0xC5BF,0xF5C0,0xDA8F,0xDA90,
+0xF5BB,0xDA91,0xF5C3,0xDA92,0xF5C2,0xDA93,0xD6BA,0xF5C1,
+0xDA94,0xDA95,0xDA96,0xD4BE,0xF5C4,0xDA97,0xF5CC,0xDA98,
+0xDA99,0xDA9A,0xDA9B,0xB0CF,0xB5F8,0xDA9C,0xF5C9,0xF5CA,
+0xDA9D,0xC5DC,0xDA9E,0xDA9F,0xDAA0,0xDB40,0xF5C5,0xF5C6,
+0xDB41,0xDB42,0xF5C7,0xF5CB,0xDB43,0xBEE0,0xF5C8,0xB8FA,
+0xDB44,0xDB45,0xDB46,0xF5D0,0xF5D3,0xDB47,0xDB48,0xDB49,
+0xBFE7,0xDB4A,0xB9F2,0xF5BC,0xF5CD,0xDB4B,0xDB4C,0xC2B7,
+0xDB4D,0xDB4E,0xDB4F,0xCCF8,0xDB50,0xBCF9,0xDB51,0xF5CE,
+0xF5CF,0xF5D1,0xB6E5,0xF5D2,0xDB52,0xF5D5,0xDB53,0xDB54,
+0xDB55,0xDB56,0xDB57,0xDB58,0xDB59,0xF5BD,0xDB5A,0xDB5B,
+0xDB5C,0xF5D4,0xD3BB,0xDB5D,0xB3EC,0xDB5E,0xDB5F,0xCCA4,
+0xDB60,0xDB61,0xDB62,0xDB63,0xF5D6,0xDB64,0xDB65,0xDB66,
+0xDB67,0xDB68,0xDB69,0xDB6A,0xDB6B,0xF5D7,0xBEE1,0xF5D8,
+0xDB6C,0xDB6D,0xCCDF,0xF5DB,0xDB6E,0xDB6F,0xDB70,0xDB71,
+0xDB72,0xB2C8,0xD7D9,0xDB73,0xF5D9,0xDB74,0xF5DA,0xF5DC,
+0xDB75,0xF5E2,0xDB76,0xDB77,0xDB78,0xF5E0,0xDB79,0xDB7A,
+0xDB7B,0xF5DF,0xF5DD,0xDB7C,0xDB7D,0xF5E1,0xDB7E,0xDB80,
+0xF5DE,0xF5E4,0xF5E5,0xDB81,0xCCE3,0xDB82,0xDB83,0xE5BF,
+0xB5B8,0xF5E3,0xF5E8,0xCCA3,0xDB84,0xDB85,0xDB86,0xDB87,
+0xDB88,0xF5E6,0xF5E7,0xDB89,0xDB8A,0xDB8B,0xDB8C,0xDB8D,
+0xDB8E,0xF5BE,0xDB8F,0xDB90,0xDB91,0xDB92,0xDB93,0xDB94,
+0xDB95,0xDB96,0xDB97,0xDB98,0xDB99,0xDB9A,0xB1C4,0xDB9B,
+0xDB9C,0xF5BF,0xDB9D,0xDB9E,0xB5C5,0xB2E4,0xDB9F,0xF5EC,
+0xF5E9,0xDBA0,0xB6D7,0xDC40,0xF5ED,0xDC41,0xF5EA,0xDC42,
+0xDC43,0xDC44,0xDC45,0xDC46,0xF5EB,0xDC47,0xDC48,0xB4DA,
+0xDC49,0xD4EA,0xDC4A,0xDC4B,0xDC4C,0xF5EE,0xDC4D,0xB3F9,
+0xDC4E,0xDC4F,0xDC50,0xDC51,0xDC52,0xDC53,0xDC54,0xF5EF,
+0xF5F1,0xDC55,0xDC56,0xDC57,0xF5F0,0xDC58,0xDC59,0xDC5A,
+0xDC5B,0xDC5C,0xDC5D,0xDC5E,0xF5F2,0xDC5F,0xF5F3,0xDC60,
+0xDC61,0xDC62,0xDC63,0xDC64,0xDC65,0xDC66,0xDC67,0xDC68,
+0xDC69,0xDC6A,0xDC6B,0xC9ED,0xB9AA,0xDC6C,0xDC6D,0xC7FB,
+0xDC6E,0xDC6F,0xB6E3,0xDC70,0xDC71,0xDC72,0xDC73,0xDC74,
+0xDC75,0xDC76,0xCCC9,0xDC77,0xDC78,0xDC79,0xDC7A,0xDC7B,
+0xDC7C,0xDC7D,0xDC7E,0xDC80,0xDC81,0xDC82,0xDC83,0xDC84,
+0xDC85,0xDC86,0xDC87,0xDC88,0xDC89,0xDC8A,0xEAA6,0xDC8B,
+0xDC8C,0xDC8D,0xDC8E,0xDC8F,0xDC90,0xDC91,0xDC92,0xDC93,
+0xDC94,0xDC95,0xDC96,0xDC97,0xDC98,0xDC99,0xDC9A,0xDC9B,
+0xDC9C,0xDC9D,0xDC9E,0xDC9F,0xDCA0,0xDD40,0xDD41,0xDD42,
+0xDD43,0xDD44,0xDD45,0xDD46,0xDD47,0xDD48,0xDD49,0xDD4A,
+0xDD4B,0xDD4C,0xDD4D,0xDD4E,0xDD4F,0xDD50,0xDD51,0xDD52,
+0xDD53,0xDD54,0xDD55,0xDD56,0xDD57,0xDD58,0xDD59,0xDD5A,
+0xDD5B,0xDD5C,0xDD5D,0xDD5E,0xDD5F,0xDD60,0xDD61,0xDD62,
+0xDD63,0xDD64,0xDD65,0xDD66,0xDD67,0xDD68,0xDD69,0xDD6A,
+0xDD6B,0xDD6C,0xDD6D,0xDD6E,0xDD6F,0xDD70,0xDD71,0xDD72,
+0xDD73,0xDD74,0xDD75,0xDD76,0xDD77,0xDD78,0xDD79,0xDD7A,
+0xDD7B,0xDD7C,0xDD7D,0xDD7E,0xDD80,0xDD81,0xDD82,0xDD83,
+0xDD84,0xDD85,0xDD86,0xDD87,0xDD88,0xDD89,0xDD8A,0xDD8B,
+0xDD8C,0xDD8D,0xDD8E,0xDD8F,0xDD90,0xDD91,0xDD92,0xDD93,
+0xDD94,0xDD95,0xDD96,0xDD97,0xDD98,0xDD99,0xDD9A,0xDD9B,
+0xDD9C,0xDD9D,0xDD9E,0xDD9F,0xDDA0,0xDE40,0xDE41,0xDE42,
+0xDE43,0xDE44,0xDE45,0xDE46,0xDE47,0xDE48,0xDE49,0xDE4A,
+0xDE4B,0xDE4C,0xDE4D,0xDE4E,0xDE4F,0xDE50,0xDE51,0xDE52,
+0xDE53,0xDE54,0xDE55,0xDE56,0xDE57,0xDE58,0xDE59,0xDE5A,
+0xDE5B,0xDE5C,0xDE5D,0xDE5E,0xDE5F,0xDE60,0xB3B5,0xD4FE,
+0xB9EC,0xD0F9,0xDE61,0xE9ED,0xD7AA,0xE9EE,0xC2D6,0xC8ED,
+0xBAE4,0xE9EF,0xE9F0,0xE9F1,0xD6E1,0xE9F2,0xE9F3,0xE9F5,
+0xE9F4,0xE9F6,0xE9F7,0xC7E1,0xE9F8,0xD4D8,0xE9F9,0xBDCE,
+0xDE62,0xE9FA,0xE9FB,0xBDCF,0xE9FC,0xB8A8,0xC1BE,0xE9FD,
+0xB1B2,0xBBD4,0xB9F5,0xE9FE,0xDE63,0xEAA1,0xEAA2,0xEAA3,
+0xB7F8,0xBCAD,0xDE64,0xCAE4,0xE0CE,0xD4AF,0xCFBD,0xD5B7,
+0xEAA4,0xD5DE,0xEAA5,0xD0C1,0xB9BC,0xDE65,0xB4C7,0xB1D9,
+0xDE66,0xDE67,0xDE68,0xC0B1,0xDE69,0xDE6A,0xDE6B,0xDE6C,
+0xB1E6,0xB1E7,0xDE6D,0xB1E8,0xDE6E,0xDE6F,0xDE70,0xDE71,
+0xB3BD,0xC8E8,0xDE72,0xDE73,0xDE74,0xDE75,0xE5C1,0xDE76,
+0xDE77,0xB1DF,0xDE78,0xDE79,0xDE7A,0xC1C9,0xB4EF,0xDE7B,
+0xDE7C,0xC7A8,0xD3D8,0xDE7D,0xC6F9,0xD1B8,0xDE7E,0xB9FD,
+0xC2F5,0xDE80,0xDE81,0xDE82,0xDE83,0xDE84,0xD3AD,0xDE85,
+0xD4CB,0xBDFC,0xDE86,0xE5C2,0xB7B5,0xE5C3,0xDE87,0xDE88,
+0xBBB9,0xD5E2,0xDE89,0xBDF8,0xD4B6,0xCEA5,0xC1AC,0xB3D9,
+0xDE8A,0xDE8B,0xCCF6,0xDE8C,0xE5C6,0xE5C4,0xE5C8,0xDE8D,
+0xE5CA,0xE5C7,0xB5CF,0xC6C8,0xDE8E,0xB5FC,0xE5C5,0xDE8F,
+0xCAF6,0xDE90,0xDE91,0xE5C9,0xDE92,0xDE93,0xDE94,0xC3D4,
+0xB1C5,0xBCA3,0xDE95,0xDE96,0xDE97,0xD7B7,0xDE98,0xDE99,
+0xCDCB,0xCBCD,0xCACA,0xCCD3,0xE5CC,0xE5CB,0xC4E6,0xDE9A,
+0xDE9B,0xD1A1,0xD1B7,0xE5CD,0xDE9C,0xE5D0,0xDE9D,0xCDB8,
+0xD6F0,0xE5CF,0xB5DD,0xDE9E,0xCDBE,0xDE9F,0xE5D1,0xB6BA,
+0xDEA0,0xDF40,0xCDA8,0xB9E4,0xDF41,0xCAC5,0xB3D1,0xCBD9,
+0xD4EC,0xE5D2,0xB7EA,0xDF42,0xDF43,0xDF44,0xE5CE,0xDF45,
+0xDF46,0xDF47,0xDF48,0xDF49,0xDF4A,0xE5D5,0xB4FE,0xE5D6,
+0xDF4B,0xDF4C,0xDF4D,0xDF4E,0xDF4F,0xE5D3,0xE5D4,0xDF50,
+0xD2DD,0xDF51,0xDF52,0xC2DF,0xB1C6,0xDF53,0xD3E2,0xDF54,
+0xDF55,0xB6DD,0xCBEC,0xDF56,0xE5D7,0xDF57,0xDF58,0xD3F6,
+0xDF59,0xDF5A,0xDF5B,0xDF5C,0xDF5D,0xB1E9,0xDF5E,0xB6F4,
+0xE5DA,0xE5D8,0xE5D9,0xB5C0,0xDF5F,0xDF60,0xDF61,0xD2C5,
+0xE5DC,0xDF62,0xDF63,0xE5DE,0xDF64,0xDF65,0xDF66,0xDF67,
+0xDF68,0xDF69,0xE5DD,0xC7B2,0xDF6A,0xD2A3,0xDF6B,0xDF6C,
+0xE5DB,0xDF6D,0xDF6E,0xDF6F,0xDF70,0xD4E2,0xD5DA,0xDF71,
+0xDF72,0xDF73,0xDF74,0xDF75,0xE5E0,0xD7F1,0xDF76,0xDF77,
+0xDF78,0xDF79,0xDF7A,0xDF7B,0xDF7C,0xE5E1,0xDF7D,0xB1DC,
+0xD1FB,0xDF7E,0xE5E2,0xE5E4,0xDF80,0xDF81,0xDF82,0xDF83,
+0xE5E3,0xDF84,0xDF85,0xE5E5,0xDF86,0xDF87,0xDF88,0xDF89,
+0xDF8A,0xD2D8,0xDF8B,0xB5CB,0xDF8C,0xE7DF,0xDF8D,0xDAF5,
+0xDF8E,0xDAF8,0xDF8F,0xDAF6,0xDF90,0xDAF7,0xDF91,0xDF92,
+0xDF93,0xDAFA,0xD0CF,0xC4C7,0xDF94,0xDF95,0xB0EE,0xDF96,
+0xDF97,0xDF98,0xD0B0,0xDF99,0xDAF9,0xDF9A,0xD3CA,0xBAAA,
+0xDBA2,0xC7F1,0xDF9B,0xDAFC,0xDAFB,0xC9DB,0xDAFD,0xDF9C,
+0xDBA1,0xD7DE,0xDAFE,0xC1DA,0xDF9D,0xDF9E,0xDBA5,0xDF9F,
+0xDFA0,0xD3F4,0xE040,0xE041,0xDBA7,0xDBA4,0xE042,0xDBA8,
+0xE043,0xE044,0xBDBC,0xE045,0xE046,0xE047,0xC0C9,0xDBA3,
+0xDBA6,0xD6A3,0xE048,0xDBA9,0xE049,0xE04A,0xE04B,0xDBAD,
+0xE04C,0xE04D,0xE04E,0xDBAE,0xDBAC,0xBAC2,0xE04F,0xE050,
+0xE051,0xBFA4,0xDBAB,0xE052,0xE053,0xE054,0xDBAA,0xD4C7,
+0xB2BF,0xE055,0xE056,0xDBAF,0xE057,0xB9F9,0xE058,0xDBB0,
+0xE059,0xE05A,0xE05B,0xE05C,0xB3BB,0xE05D,0xE05E,0xE05F,
+0xB5A6,0xE060,0xE061,0xE062,0xE063,0xB6BC,0xDBB1,0xE064,
+0xE065,0xE066,0xB6F5,0xE067,0xDBB2,0xE068,0xE069,0xE06A,
+0xE06B,0xE06C,0xE06D,0xE06E,0xE06F,0xE070,0xE071,0xE072,
+0xE073,0xE074,0xE075,0xE076,0xE077,0xE078,0xE079,0xE07A,
+0xE07B,0xB1C9,0xE07C,0xE07D,0xE07E,0xE080,0xDBB4,0xE081,
+0xE082,0xE083,0xDBB3,0xDBB5,0xE084,0xE085,0xE086,0xE087,
+0xE088,0xE089,0xE08A,0xE08B,0xE08C,0xE08D,0xE08E,0xDBB7,
+0xE08F,0xDBB6,0xE090,0xE091,0xE092,0xE093,0xE094,0xE095,
+0xE096,0xDBB8,0xE097,0xE098,0xE099,0xE09A,0xE09B,0xE09C,
+0xE09D,0xE09E,0xE09F,0xDBB9,0xE0A0,0xE140,0xDBBA,0xE141,
+0xE142,0xD3CF,0xF4FA,0xC7F5,0xD7C3,0xC5E4,0xF4FC,0xF4FD,
+0xF4FB,0xE143,0xBEC6,0xE144,0xE145,0xE146,0xE147,0xD0EF,
+0xE148,0xE149,0xB7D3,0xE14A,0xE14B,0xD4CD,0xCCAA,0xE14C,
+0xE14D,0xF5A2,0xF5A1,0xBAA8,0xF4FE,0xCBD6,0xE14E,0xE14F,
+0xE150,0xF5A4,0xC0D2,0xE151,0xB3EA,0xE152,0xCDAA,0xF5A5,
+0xF5A3,0xBDB4,0xF5A8,0xE153,0xF5A9,0xBDCD,0xC3B8,0xBFE1,
+0xCBE1,0xF5AA,0xE154,0xE155,0xE156,0xF5A6,0xF5A7,0xC4F0,
+0xE157,0xE158,0xE159,0xE15A,0xE15B,0xF5AC,0xE15C,0xB4BC,
+0xE15D,0xD7ED,0xE15E,0xB4D7,0xF5AB,0xF5AE,0xE15F,0xE160,
+0xF5AD,0xF5AF,0xD0D1,0xE161,0xE162,0xE163,0xE164,0xE165,
+0xE166,0xE167,0xC3D1,0xC8A9,0xE168,0xE169,0xE16A,0xE16B,
+0xE16C,0xE16D,0xF5B0,0xF5B1,0xE16E,0xE16F,0xE170,0xE171,
+0xE172,0xE173,0xF5B2,0xE174,0xE175,0xF5B3,0xF5B4,0xF5B5,
+0xE176,0xE177,0xE178,0xE179,0xF5B7,0xF5B6,0xE17A,0xE17B,
+0xE17C,0xE17D,0xF5B8,0xE17E,0xE180,0xE181,0xE182,0xE183,
+0xE184,0xE185,0xE186,0xE187,0xE188,0xE189,0xE18A,0xB2C9,
+0xE18B,0xD3D4,0xCACD,0xE18C,0xC0EF,0xD6D8,0xD2B0,0xC1BF,
+0xE18D,0xBDF0,0xE18E,0xE18F,0xE190,0xE191,0xE192,0xE193,
+0xE194,0xE195,0xE196,0xE197,0xB8AA,0xE198,0xE199,0xE19A,
+0xE19B,0xE19C,0xE19D,0xE19E,0xE19F,0xE1A0,0xE240,0xE241,
+0xE242,0xE243,0xE244,0xE245,0xE246,0xE247,0xE248,0xE249,
+0xE24A,0xE24B,0xE24C,0xE24D,0xE24E,0xE24F,0xE250,0xE251,
+0xE252,0xE253,0xE254,0xE255,0xE256,0xE257,0xE258,0xE259,
+0xE25A,0xE25B,0xE25C,0xE25D,0xE25E,0xE25F,0xE260,0xE261,
+0xE262,0xE263,0xE264,0xE265,0xE266,0xE267,0xE268,0xE269,
+0xE26A,0xE26B,0xE26C,0xE26D,0xE26E,0xE26F,0xE270,0xE271,
+0xE272,0xE273,0xE274,0xE275,0xE276,0xE277,0xE278,0xE279,
+0xE27A,0xE27B,0xE27C,0xE27D,0xE27E,0xE280,0xE281,0xE282,
+0xE283,0xE284,0xE285,0xE286,0xE287,0xE288,0xE289,0xE28A,
+0xE28B,0xE28C,0xE28D,0xE28E,0xE28F,0xE290,0xE291,0xE292,
+0xE293,0xE294,0xE295,0xE296,0xE297,0xE298,0xE299,0xE29A,
+0xE29B,0xE29C,0xE29D,0xE29E,0xE29F,0xE2A0,0xE340,0xE341,
+0xE342,0xE343,0xE344,0xE345,0xE346,0xE347,0xE348,0xE349,
+0xE34A,0xE34B,0xE34C,0xE34D,0xE34E,0xE34F,0xE350,0xE351,
+0xE352,0xE353,0xE354,0xE355,0xE356,0xE357,0xE358,0xE359,
+0xE35A,0xE35B,0xE35C,0xE35D,0xE35E,0xE35F,0xE360,0xE361,
+0xE362,0xE363,0xE364,0xE365,0xE366,0xE367,0xE368,0xE369,
+0xE36A,0xE36B,0xE36C,0xE36D,0xBCF8,0xE36E,0xE36F,0xE370,
+0xE371,0xE372,0xE373,0xE374,0xE375,0xE376,0xE377,0xE378,
+0xE379,0xE37A,0xE37B,0xE37C,0xE37D,0xE37E,0xE380,0xE381,
+0xE382,0xE383,0xE384,0xE385,0xE386,0xE387,0xF6C6,0xE388,
+0xE389,0xE38A,0xE38B,0xE38C,0xE38D,0xE38E,0xE38F,0xE390,
+0xE391,0xE392,0xE393,0xE394,0xE395,0xE396,0xE397,0xE398,
+0xE399,0xE39A,0xE39B,0xE39C,0xE39D,0xE39E,0xE39F,0xE3A0,
+0xE440,0xE441,0xE442,0xE443,0xE444,0xE445,0xF6C7,0xE446,
+0xE447,0xE448,0xE449,0xE44A,0xE44B,0xE44C,0xE44D,0xE44E,
+0xE44F,0xE450,0xE451,0xE452,0xE453,0xE454,0xE455,0xE456,
+0xE457,0xE458,0xE459,0xE45A,0xE45B,0xE45C,0xE45D,0xE45E,
+0xF6C8,0xE45F,0xE460,0xE461,0xE462,0xE463,0xE464,0xE465,
+0xE466,0xE467,0xE468,0xE469,0xE46A,0xE46B,0xE46C,0xE46D,
+0xE46E,0xE46F,0xE470,0xE471,0xE472,0xE473,0xE474,0xE475,
+0xE476,0xE477,0xE478,0xE479,0xE47A,0xE47B,0xE47C,0xE47D,
+0xE47E,0xE480,0xE481,0xE482,0xE483,0xE484,0xE485,0xE486,
+0xE487,0xE488,0xE489,0xE48A,0xE48B,0xE48C,0xE48D,0xE48E,
+0xE48F,0xE490,0xE491,0xE492,0xE493,0xE494,0xE495,0xE496,
+0xE497,0xE498,0xE499,0xE49A,0xE49B,0xE49C,0xE49D,0xE49E,
+0xE49F,0xE4A0,0xE540,0xE541,0xE542,0xE543,0xE544,0xE545,
+0xE546,0xE547,0xE548,0xE549,0xE54A,0xE54B,0xE54C,0xE54D,
+0xE54E,0xE54F,0xE550,0xE551,0xE552,0xE553,0xE554,0xE555,
+0xE556,0xE557,0xE558,0xE559,0xE55A,0xE55B,0xE55C,0xE55D,
+0xE55E,0xE55F,0xE560,0xE561,0xE562,0xE563,0xE564,0xE565,
+0xE566,0xE567,0xE568,0xE569,0xE56A,0xE56B,0xE56C,0xE56D,
+0xE56E,0xE56F,0xE570,0xE571,0xE572,0xE573,0xF6C9,0xE574,
+0xE575,0xE576,0xE577,0xE578,0xE579,0xE57A,0xE57B,0xE57C,
+0xE57D,0xE57E,0xE580,0xE581,0xE582,0xE583,0xE584,0xE585,
+0xE586,0xE587,0xE588,0xE589,0xE58A,0xE58B,0xE58C,0xE58D,
+0xE58E,0xE58F,0xE590,0xE591,0xE592,0xE593,0xE594,0xE595,
+0xE596,0xE597,0xE598,0xE599,0xE59A,0xE59B,0xE59C,0xE59D,
+0xE59E,0xE59F,0xF6CA,0xE5A0,0xE640,0xE641,0xE642,0xE643,
+0xE644,0xE645,0xE646,0xE647,0xE648,0xE649,0xE64A,0xE64B,
+0xE64C,0xE64D,0xE64E,0xE64F,0xE650,0xE651,0xE652,0xE653,
+0xE654,0xE655,0xE656,0xE657,0xE658,0xE659,0xE65A,0xE65B,
+0xE65C,0xE65D,0xE65E,0xE65F,0xE660,0xE661,0xE662,0xF6CC,
+0xE663,0xE664,0xE665,0xE666,0xE667,0xE668,0xE669,0xE66A,
+0xE66B,0xE66C,0xE66D,0xE66E,0xE66F,0xE670,0xE671,0xE672,
+0xE673,0xE674,0xE675,0xE676,0xE677,0xE678,0xE679,0xE67A,
+0xE67B,0xE67C,0xE67D,0xE67E,0xE680,0xE681,0xE682,0xE683,
+0xE684,0xE685,0xE686,0xE687,0xE688,0xE689,0xE68A,0xE68B,
+0xE68C,0xE68D,0xE68E,0xE68F,0xE690,0xE691,0xE692,0xE693,
+0xE694,0xE695,0xE696,0xE697,0xE698,0xE699,0xE69A,0xE69B,
+0xE69C,0xE69D,0xF6CB,0xE69E,0xE69F,0xE6A0,0xE740,0xE741,
+0xE742,0xE743,0xE744,0xE745,0xE746,0xE747,0xF7E9,0xE748,
+0xE749,0xE74A,0xE74B,0xE74C,0xE74D,0xE74E,0xE74F,0xE750,
+0xE751,0xE752,0xE753,0xE754,0xE755,0xE756,0xE757,0xE758,
+0xE759,0xE75A,0xE75B,0xE75C,0xE75D,0xE75E,0xE75F,0xE760,
+0xE761,0xE762,0xE763,0xE764,0xE765,0xE766,0xE767,0xE768,
+0xE769,0xE76A,0xE76B,0xE76C,0xE76D,0xE76E,0xE76F,0xE770,
+0xE771,0xE772,0xE773,0xE774,0xE775,0xE776,0xE777,0xE778,
+0xE779,0xE77A,0xE77B,0xE77C,0xE77D,0xE77E,0xE780,0xE781,
+0xE782,0xE783,0xE784,0xE785,0xE786,0xE787,0xE788,0xE789,
+0xE78A,0xE78B,0xE78C,0xE78D,0xE78E,0xE78F,0xE790,0xE791,
+0xE792,0xE793,0xE794,0xE795,0xE796,0xE797,0xE798,0xE799,
+0xE79A,0xE79B,0xE79C,0xE79D,0xE79E,0xE79F,0xE7A0,0xE840,
+0xE841,0xE842,0xE843,0xE844,0xE845,0xE846,0xE847,0xE848,
+0xE849,0xE84A,0xE84B,0xE84C,0xE84D,0xE84E,0xF6CD,0xE84F,
+0xE850,0xE851,0xE852,0xE853,0xE854,0xE855,0xE856,0xE857,
+0xE858,0xE859,0xE85A,0xE85B,0xE85C,0xE85D,0xE85E,0xE85F,
+0xE860,0xE861,0xE862,0xE863,0xE864,0xE865,0xE866,0xE867,
+0xE868,0xE869,0xE86A,0xE86B,0xE86C,0xE86D,0xE86E,0xE86F,
+0xE870,0xE871,0xE872,0xE873,0xE874,0xE875,0xE876,0xE877,
+0xE878,0xE879,0xE87A,0xF6CE,0xE87B,0xE87C,0xE87D,0xE87E,
+0xE880,0xE881,0xE882,0xE883,0xE884,0xE885,0xE886,0xE887,
+0xE888,0xE889,0xE88A,0xE88B,0xE88C,0xE88D,0xE88E,0xE88F,
+0xE890,0xE891,0xE892,0xE893,0xE894,0xEEC4,0xEEC5,0xEEC6,
+0xD5EB,0xB6A4,0xEEC8,0xEEC7,0xEEC9,0xEECA,0xC7A5,0xEECB,
+0xEECC,0xE895,0xB7B0,0xB5F6,0xEECD,0xEECF,0xE896,0xEECE,
+0xE897,0xB8C6,0xEED0,0xEED1,0xEED2,0xB6DB,0xB3AE,0xD6D3,
+0xC4C6,0xB1B5,0xB8D6,0xEED3,0xEED4,0xD4BF,0xC7D5,0xBEFB,
+0xCED9,0xB9B3,0xEED6,0xEED5,0xEED8,0xEED7,0xC5A5,0xEED9,
+0xEEDA,0xC7AE,0xEEDB,0xC7AF,0xEEDC,0xB2A7,0xEEDD,0xEEDE,
+0xEEDF,0xEEE0,0xEEE1,0xD7EA,0xEEE2,0xEEE3,0xBCD8,0xEEE4,
+0xD3CB,0xCCFA,0xB2AC,0xC1E5,0xEEE5,0xC7A6,0xC3AD,0xE898,
+0xEEE6,0xEEE7,0xEEE8,0xEEE9,0xEEEA,0xEEEB,0xEEEC,0xE899,
+0xEEED,0xEEEE,0xEEEF,0xE89A,0xE89B,0xEEF0,0xEEF1,0xEEF2,
+0xEEF4,0xEEF3,0xE89C,0xEEF5,0xCDAD,0xC2C1,0xEEF6,0xEEF7,
+0xEEF8,0xD5A1,0xEEF9,0xCFB3,0xEEFA,0xEEFB,0xE89D,0xEEFC,
+0xEEFD,0xEFA1,0xEEFE,0xEFA2,0xB8F5,0xC3FA,0xEFA3,0xEFA4,
+0xBDC2,0xD2BF,0xB2F9,0xEFA5,0xEFA6,0xEFA7,0xD2F8,0xEFA8,
+0xD6FD,0xEFA9,0xC6CC,0xE89E,0xEFAA,0xEFAB,0xC1B4,0xEFAC,
+0xCFFA,0xCBF8,0xEFAE,0xEFAD,0xB3FA,0xB9F8,0xEFAF,0xEFB0,
+0xD0E2,0xEFB1,0xEFB2,0xB7E6,0xD0BF,0xEFB3,0xEFB4,0xEFB5,
+0xC8F1,0xCCE0,0xEFB6,0xEFB7,0xEFB8,0xEFB9,0xEFBA,0xD5E0,
+0xEFBB,0xB4ED,0xC3AA,0xEFBC,0xE89F,0xEFBD,0xEFBE,0xEFBF,
+0xE8A0,0xCEFD,0xEFC0,0xC2E0,0xB4B8,0xD7B6,0xBDF5,0xE940,
+0xCFC7,0xEFC3,0xEFC1,0xEFC2,0xEFC4,0xB6A7,0xBCFC,0xBEE2,
+0xC3CC,0xEFC5,0xEFC6,0xE941,0xEFC7,0xEFCF,0xEFC8,0xEFC9,
+0xEFCA,0xC7C2,0xEFF1,0xB6CD,0xEFCB,0xE942,0xEFCC,0xEFCD,
+0xB6C6,0xC3BE,0xEFCE,0xE943,0xEFD0,0xEFD1,0xEFD2,0xD5F2,
+0xE944,0xEFD3,0xC4F7,0xE945,0xEFD4,0xC4F8,0xEFD5,0xEFD6,
+0xB8E4,0xB0F7,0xEFD7,0xEFD8,0xEFD9,0xE946,0xEFDA,0xEFDB,
+0xEFDC,0xEFDD,0xE947,0xEFDE,0xBEB5,0xEFE1,0xEFDF,0xEFE0,
+0xE948,0xEFE2,0xEFE3,0xC1CD,0xEFE4,0xEFE5,0xEFE6,0xEFE7,
+0xEFE8,0xEFE9,0xEFEA,0xEFEB,0xEFEC,0xC0D8,0xE949,0xEFED,
+0xC1AD,0xEFEE,0xEFEF,0xEFF0,0xE94A,0xE94B,0xCFE2,0xE94C,
+0xE94D,0xE94E,0xE94F,0xE950,0xE951,0xE952,0xE953,0xB3A4,
+0xE954,0xE955,0xE956,0xE957,0xE958,0xE959,0xE95A,0xE95B,
+0xE95C,0xE95D,0xE95E,0xE95F,0xE960,0xE961,0xE962,0xE963,
+0xE964,0xE965,0xE966,0xE967,0xE968,0xE969,0xE96A,0xE96B,
+0xE96C,0xE96D,0xE96E,0xE96F,0xE970,0xE971,0xE972,0xE973,
+0xE974,0xE975,0xE976,0xE977,0xE978,0xE979,0xE97A,0xE97B,
+0xE97C,0xE97D,0xE97E,0xE980,0xE981,0xE982,0xE983,0xE984,
+0xE985,0xE986,0xE987,0xE988,0xE989,0xE98A,0xE98B,0xE98C,
+0xE98D,0xE98E,0xE98F,0xE990,0xE991,0xE992,0xE993,0xE994,
+0xE995,0xE996,0xE997,0xE998,0xE999,0xE99A,0xE99B,0xE99C,
+0xE99D,0xE99E,0xE99F,0xE9A0,0xEA40,0xEA41,0xEA42,0xEA43,
+0xEA44,0xEA45,0xEA46,0xEA47,0xEA48,0xEA49,0xEA4A,0xEA4B,
+0xEA4C,0xEA4D,0xEA4E,0xEA4F,0xEA50,0xEA51,0xEA52,0xEA53,
+0xEA54,0xEA55,0xEA56,0xEA57,0xEA58,0xEA59,0xEA5A,0xEA5B,
+0xC3C5,0xE3C5,0xC9C1,0xE3C6,0xEA5C,0xB1D5,0xCECA,0xB4B3,
+0xC8F2,0xE3C7,0xCFD0,0xE3C8,0xBCE4,0xE3C9,0xE3CA,0xC3C6,
+0xD5A2,0xC4D6,0xB9EB,0xCEC5,0xE3CB,0xC3F6,0xE3CC,0xEA5D,
+0xB7A7,0xB8F3,0xBAD2,0xE3CD,0xE3CE,0xD4C4,0xE3CF,0xEA5E,
+0xE3D0,0xD1CB,0xE3D1,0xE3D2,0xE3D3,0xE3D4,0xD1D6,0xE3D5,
+0xB2FB,0xC0BB,0xE3D6,0xEA5F,0xC0AB,0xE3D7,0xE3D8,0xE3D9,
+0xEA60,0xE3DA,0xE3DB,0xEA61,0xB8B7,0xDAE2,0xEA62,0xB6D3,
+0xEA63,0xDAE4,0xDAE3,0xEA64,0xEA65,0xEA66,0xEA67,0xEA68,
+0xEA69,0xEA6A,0xDAE6,0xEA6B,0xEA6C,0xEA6D,0xC8EE,0xEA6E,
+0xEA6F,0xDAE5,0xB7C0,0xD1F4,0xD2F5,0xD5F3,0xBDD7,0xEA70,
+0xEA71,0xEA72,0xEA73,0xD7E8,0xDAE8,0xDAE7,0xEA74,0xB0A2,
+0xCDD3,0xEA75,0xDAE9,0xEA76,0xB8BD,0xBCCA,0xC2BD,0xC2A4,
+0xB3C2,0xDAEA,0xEA77,0xC2AA,0xC4B0,0xBDB5,0xEA78,0xEA79,
+0xCFDE,0xEA7A,0xEA7B,0xEA7C,0xDAEB,0xC9C2,0xEA7D,0xEA7E,
+0xEA80,0xEA81,0xEA82,0xB1DD,0xEA83,0xEA84,0xEA85,0xDAEC,
+0xEA86,0xB6B8,0xD4BA,0xEA87,0xB3FD,0xEA88,0xEA89,0xDAED,
+0xD4C9,0xCFD5,0xC5E3,0xEA8A,0xDAEE,0xEA8B,0xEA8C,0xEA8D,
+0xEA8E,0xEA8F,0xDAEF,0xEA90,0xDAF0,0xC1EA,0xCCD5,0xCFDD,
+0xEA91,0xEA92,0xEA93,0xEA94,0xEA95,0xEA96,0xEA97,0xEA98,
+0xEA99,0xEA9A,0xEA9B,0xEA9C,0xEA9D,0xD3E7,0xC2A1,0xEA9E,
+0xDAF1,0xEA9F,0xEAA0,0xCBE5,0xEB40,0xDAF2,0xEB41,0xCBE6,
+0xD2FE,0xEB42,0xEB43,0xEB44,0xB8F4,0xEB45,0xEB46,0xDAF3,
+0xB0AF,0xCFB6,0xEB47,0xEB48,0xD5CF,0xEB49,0xEB4A,0xEB4B,
+0xEB4C,0xEB4D,0xEB4E,0xEB4F,0xEB50,0xEB51,0xEB52,0xCBED,
+0xEB53,0xEB54,0xEB55,0xEB56,0xEB57,0xEB58,0xEB59,0xEB5A,
+0xDAF4,0xEB5B,0xEB5C,0xE3C4,0xEB5D,0xEB5E,0xC1A5,0xEB5F,
+0xEB60,0xF6BF,0xEB61,0xEB62,0xF6C0,0xF6C1,0xC4D1,0xEB63,
+0xC8B8,0xD1E3,0xEB64,0xEB65,0xD0DB,0xD1C5,0xBCAF,0xB9CD,
+0xEB66,0xEFF4,0xEB67,0xEB68,0xB4C6,0xD3BA,0xF6C2,0xB3FB,
+0xEB69,0xEB6A,0xF6C3,0xEB6B,0xEB6C,0xB5F1,0xEB6D,0xEB6E,
+0xEB6F,0xEB70,0xEB71,0xEB72,0xEB73,0xEB74,0xEB75,0xEB76,
+0xF6C5,0xEB77,0xEB78,0xEB79,0xEB7A,0xEB7B,0xEB7C,0xEB7D,
+0xD3EA,0xF6A7,0xD1A9,0xEB7E,0xEB80,0xEB81,0xEB82,0xF6A9,
+0xEB83,0xEB84,0xEB85,0xF6A8,0xEB86,0xEB87,0xC1E3,0xC0D7,
+0xEB88,0xB1A2,0xEB89,0xEB8A,0xEB8B,0xEB8C,0xCEED,0xEB8D,
+0xD0E8,0xF6AB,0xEB8E,0xEB8F,0xCFF6,0xEB90,0xF6AA,0xD5F0,
+0xF6AC,0xC3B9,0xEB91,0xEB92,0xEB93,0xBBF4,0xF6AE,0xF6AD,
+0xEB94,0xEB95,0xEB96,0xC4DE,0xEB97,0xEB98,0xC1D8,0xEB99,
+0xEB9A,0xEB9B,0xEB9C,0xEB9D,0xCBAA,0xEB9E,0xCFBC,0xEB9F,
+0xEBA0,0xEC40,0xEC41,0xEC42,0xEC43,0xEC44,0xEC45,0xEC46,
+0xEC47,0xEC48,0xF6AF,0xEC49,0xEC4A,0xF6B0,0xEC4B,0xEC4C,
+0xF6B1,0xEC4D,0xC2B6,0xEC4E,0xEC4F,0xEC50,0xEC51,0xEC52,
+0xB0D4,0xC5F9,0xEC53,0xEC54,0xEC55,0xEC56,0xF6B2,0xEC57,
+0xEC58,0xEC59,0xEC5A,0xEC5B,0xEC5C,0xEC5D,0xEC5E,0xEC5F,
+0xEC60,0xEC61,0xEC62,0xEC63,0xEC64,0xEC65,0xEC66,0xEC67,
+0xEC68,0xEC69,0xC7E0,0xF6A6,0xEC6A,0xEC6B,0xBEB8,0xEC6C,
+0xEC6D,0xBEB2,0xEC6E,0xB5E5,0xEC6F,0xEC70,0xB7C7,0xEC71,
+0xBFBF,0xC3D2,0xC3E6,0xEC72,0xEC73,0xD8CC,0xEC74,0xEC75,
+0xEC76,0xB8EF,0xEC77,0xEC78,0xEC79,0xEC7A,0xEC7B,0xEC7C,
+0xEC7D,0xEC7E,0xEC80,0xBDF9,0xD1A5,0xEC81,0xB0D0,0xEC82,
+0xEC83,0xEC84,0xEC85,0xEC86,0xF7B0,0xEC87,0xEC88,0xEC89,
+0xEC8A,0xEC8B,0xEC8C,0xEC8D,0xEC8E,0xF7B1,0xEC8F,0xEC90,
+0xEC91,0xEC92,0xEC93,0xD0AC,0xEC94,0xB0B0,0xEC95,0xEC96,
+0xEC97,0xF7B2,0xF7B3,0xEC98,0xF7B4,0xEC99,0xEC9A,0xEC9B,
+0xC7CA,0xEC9C,0xEC9D,0xEC9E,0xEC9F,0xECA0,0xED40,0xED41,
+0xBECF,0xED42,0xED43,0xF7B7,0xED44,0xED45,0xED46,0xED47,
+0xED48,0xED49,0xED4A,0xF7B6,0xED4B,0xB1DE,0xED4C,0xF7B5,
+0xED4D,0xED4E,0xF7B8,0xED4F,0xF7B9,0xED50,0xED51,0xED52,
+0xED53,0xED54,0xED55,0xED56,0xED57,0xED58,0xED59,0xED5A,
+0xED5B,0xED5C,0xED5D,0xED5E,0xED5F,0xED60,0xED61,0xED62,
+0xED63,0xED64,0xED65,0xED66,0xED67,0xED68,0xED69,0xED6A,
+0xED6B,0xED6C,0xED6D,0xED6E,0xED6F,0xED70,0xED71,0xED72,
+0xED73,0xED74,0xED75,0xED76,0xED77,0xED78,0xED79,0xED7A,
+0xED7B,0xED7C,0xED7D,0xED7E,0xED80,0xED81,0xCEA4,0xC8CD,
+0xED82,0xBAAB,0xE8B8,0xE8B9,0xE8BA,0xBEC2,0xED83,0xED84,
+0xED85,0xED86,0xED87,0xD2F4,0xED88,0xD4CF,0xC9D8,0xED89,
+0xED8A,0xED8B,0xED8C,0xED8D,0xED8E,0xED8F,0xED90,0xED91,
+0xED92,0xED93,0xED94,0xED95,0xED96,0xED97,0xED98,0xED99,
+0xED9A,0xED9B,0xED9C,0xED9D,0xED9E,0xED9F,0xEDA0,0xEE40,
+0xEE41,0xEE42,0xEE43,0xEE44,0xEE45,0xEE46,0xEE47,0xEE48,
+0xEE49,0xEE4A,0xEE4B,0xEE4C,0xEE4D,0xEE4E,0xEE4F,0xEE50,
+0xEE51,0xEE52,0xEE53,0xEE54,0xEE55,0xEE56,0xEE57,0xEE58,
+0xEE59,0xEE5A,0xEE5B,0xEE5C,0xEE5D,0xEE5E,0xEE5F,0xEE60,
+0xEE61,0xEE62,0xEE63,0xEE64,0xEE65,0xEE66,0xEE67,0xEE68,
+0xEE69,0xEE6A,0xEE6B,0xEE6C,0xEE6D,0xEE6E,0xEE6F,0xEE70,
+0xEE71,0xEE72,0xEE73,0xEE74,0xEE75,0xEE76,0xEE77,0xEE78,
+0xEE79,0xEE7A,0xEE7B,0xEE7C,0xEE7D,0xEE7E,0xEE80,0xEE81,
+0xEE82,0xEE83,0xEE84,0xEE85,0xEE86,0xEE87,0xEE88,0xEE89,
+0xEE8A,0xEE8B,0xEE8C,0xEE8D,0xEE8E,0xEE8F,0xEE90,0xEE91,
+0xEE92,0xEE93,0xEE94,0xEE95,0xEE96,0xEE97,0xEE98,0xEE99,
+0xEE9A,0xEE9B,0xEE9C,0xEE9D,0xEE9E,0xEE9F,0xEEA0,0xEF40,
+0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xD2B3,0xB6A5,0xC7EA,
+0xF1FC,0xCFEE,0xCBB3,0xD0EB,0xE7EF,0xCDE7,0xB9CB,0xB6D9,
+0xF1FD,0xB0E4,0xCBCC,0xF1FE,0xD4A4,0xC2AD,0xC1EC,0xC6C4,
+0xBEB1,0xF2A1,0xBCD5,0xEF46,0xF2A2,0xF2A3,0xEF47,0xF2A4,
+0xD2C3,0xC6B5,0xEF48,0xCDC7,0xF2A5,0xEF49,0xD3B1,0xBFC5,
+0xCCE2,0xEF4A,0xF2A6,0xF2A7,0xD1D5,0xB6EE,0xF2A8,0xF2A9,
+0xB5DF,0xF2AA,0xF2AB,0xEF4B,0xB2FC,0xF2AC,0xF2AD,0xC8A7,
+0xEF4C,0xEF4D,0xEF4E,0xEF4F,0xEF50,0xEF51,0xEF52,0xEF53,
+0xEF54,0xEF55,0xEF56,0xEF57,0xEF58,0xEF59,0xEF5A,0xEF5B,
+0xEF5C,0xEF5D,0xEF5E,0xEF5F,0xEF60,0xEF61,0xEF62,0xEF63,
+0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0xEF6B,
+0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0xB7E7,0xEF72,
+0xEF73,0xECA9,0xECAA,0xECAB,0xEF74,0xECAC,0xEF75,0xEF76,
+0xC6AE,0xECAD,0xECAE,0xEF77,0xEF78,0xEF79,0xB7C9,0xCAB3,
+0xEF7A,0xEF7B,0xEF7C,0xEF7D,0xEF7E,0xEF80,0xEF81,0xE2B8,
+0xF7CF,0xEF82,0xEF83,0xEF84,0xEF85,0xEF86,0xEF87,0xEF88,
+0xEF89,0xEF8A,0xEF8B,0xEF8C,0xEF8D,0xEF8E,0xEF8F,0xEF90,
+0xEF91,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0xEF97,0xEF98,
+0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0xEF9F,0xEFA0,
+0xF040,0xF041,0xF042,0xF043,0xF044,0xF7D0,0xF045,0xF046,
+0xB2CD,0xF047,0xF048,0xF049,0xF04A,0xF04B,0xF04C,0xF04D,
+0xF04E,0xF04F,0xF050,0xF051,0xF052,0xF053,0xF054,0xF055,
+0xF056,0xF057,0xF058,0xF059,0xF05A,0xF05B,0xF05C,0xF05D,
+0xF05E,0xF05F,0xF060,0xF061,0xF062,0xF063,0xF7D1,0xF064,
+0xF065,0xF066,0xF067,0xF068,0xF069,0xF06A,0xF06B,0xF06C,
+0xF06D,0xF06E,0xF06F,0xF070,0xF071,0xF072,0xF073,0xF074,
+0xF075,0xF076,0xF077,0xF078,0xF079,0xF07A,0xF07B,0xF07C,
+0xF07D,0xF07E,0xF080,0xF081,0xF082,0xF083,0xF084,0xF085,
+0xF086,0xF087,0xF088,0xF089,0xF7D3,0xF7D2,0xF08A,0xF08B,
+0xF08C,0xF08D,0xF08E,0xF08F,0xF090,0xF091,0xF092,0xF093,
+0xF094,0xF095,0xF096,0xE2BB,0xF097,0xBCA2,0xF098,0xE2BC,
+0xE2BD,0xE2BE,0xE2BF,0xE2C0,0xE2C1,0xB7B9,0xD2FB,0xBDA4,
+0xCACE,0xB1A5,0xCBC7,0xF099,0xE2C2,0xB6FC,0xC8C4,0xE2C3,
+0xF09A,0xF09B,0xBDC8,0xF09C,0xB1FD,0xE2C4,0xF09D,0xB6F6,
+0xE2C5,0xC4D9,0xF09E,0xF09F,0xE2C6,0xCFDA,0xB9DD,0xE2C7,
+0xC0A1,0xF0A0,0xE2C8,0xB2F6,0xF140,0xE2C9,0xF141,0xC1F3,
+0xE2CA,0xE2CB,0xC2F8,0xE2CC,0xE2CD,0xE2CE,0xCAD7,0xD8B8,
+0xD9E5,0xCFE3,0xF142,0xF143,0xF144,0xF145,0xF146,0xF147,
+0xF148,0xF149,0xF14A,0xF14B,0xF14C,0xF0A5,0xF14D,0xF14E,
+0xDCB0,0xF14F,0xF150,0xF151,0xF152,0xF153,0xF154,0xF155,
+0xF156,0xF157,0xF158,0xF159,0xF15A,0xF15B,0xF15C,0xF15D,
+0xF15E,0xF15F,0xF160,0xF161,0xF162,0xF163,0xF164,0xF165,
+0xF166,0xF167,0xF168,0xF169,0xF16A,0xF16B,0xF16C,0xF16D,
+0xF16E,0xF16F,0xF170,0xF171,0xF172,0xF173,0xF174,0xF175,
+0xF176,0xF177,0xF178,0xF179,0xF17A,0xF17B,0xF17C,0xF17D,
+0xF17E,0xF180,0xF181,0xF182,0xF183,0xF184,0xF185,0xF186,
+0xF187,0xF188,0xF189,0xF18A,0xF18B,0xF18C,0xF18D,0xF18E,
+0xF18F,0xF190,0xF191,0xF192,0xF193,0xF194,0xF195,0xF196,
+0xF197,0xF198,0xF199,0xF19A,0xF19B,0xF19C,0xF19D,0xF19E,
+0xF19F,0xF1A0,0xF240,0xF241,0xF242,0xF243,0xF244,0xF245,
+0xF246,0xF247,0xF248,0xF249,0xF24A,0xF24B,0xF24C,0xF24D,
+0xF24E,0xF24F,0xF250,0xF251,0xF252,0xF253,0xF254,0xF255,
+0xF256,0xF257,0xF258,0xF259,0xF25A,0xF25B,0xF25C,0xF25D,
+0xF25E,0xF25F,0xF260,0xF261,0xF262,0xF263,0xF264,0xF265,
+0xF266,0xF267,0xF268,0xF269,0xF26A,0xF26B,0xF26C,0xF26D,
+0xF26E,0xF26F,0xF270,0xF271,0xF272,0xF273,0xF274,0xF275,
+0xF276,0xF277,0xF278,0xF279,0xF27A,0xF27B,0xF27C,0xF27D,
+0xF27E,0xF280,0xF281,0xF282,0xF283,0xF284,0xF285,0xF286,
+0xF287,0xF288,0xF289,0xF28A,0xF28B,0xF28C,0xF28D,0xF28E,
+0xF28F,0xF290,0xF291,0xF292,0xF293,0xF294,0xF295,0xF296,
+0xF297,0xF298,0xF299,0xF29A,0xF29B,0xF29C,0xF29D,0xF29E,
+0xF29F,0xF2A0,0xF340,0xF341,0xF342,0xF343,0xF344,0xF345,
+0xF346,0xF347,0xF348,0xF349,0xF34A,0xF34B,0xF34C,0xF34D,
+0xF34E,0xF34F,0xF350,0xF351,0xC2ED,0xD4A6,0xCDD4,0xD1B1,
+0xB3DB,0xC7FD,0xF352,0xB2B5,0xC2BF,0xE6E0,0xCABB,0xE6E1,
+0xE6E2,0xBED4,0xE6E3,0xD7A4,0xCDD5,0xE6E5,0xBCDD,0xE6E4,
+0xE6E6,0xE6E7,0xC2EE,0xF353,0xBDBE,0xE6E8,0xC2E6,0xBAA7,
+0xE6E9,0xF354,0xE6EA,0xB3D2,0xD1E9,0xF355,0xF356,0xBFA5,
+0xE6EB,0xC6EF,0xE6EC,0xE6ED,0xF357,0xF358,0xE6EE,0xC6AD,
+0xE6EF,0xF359,0xC9A7,0xE6F0,0xE6F1,0xE6F2,0xE5B9,0xE6F3,
+0xE6F4,0xC2E2,0xE6F5,0xE6F6,0xD6E8,0xE6F7,0xF35A,0xE6F8,
+0xB9C7,0xF35B,0xF35C,0xF35D,0xF35E,0xF35F,0xF360,0xF361,
+0xF7BB,0xF7BA,0xF362,0xF363,0xF364,0xF365,0xF7BE,0xF7BC,
+0xBAA1,0xF366,0xF7BF,0xF367,0xF7C0,0xF368,0xF369,0xF36A,
+0xF7C2,0xF7C1,0xF7C4,0xF36B,0xF36C,0xF7C3,0xF36D,0xF36E,
+0xF36F,0xF370,0xF371,0xF7C5,0xF7C6,0xF372,0xF373,0xF374,
+0xF375,0xF7C7,0xF376,0xCBE8,0xF377,0xF378,0xF379,0xF37A,
+0xB8DF,0xF37B,0xF37C,0xF37D,0xF37E,0xF380,0xF381,0xF7D4,
+0xF382,0xF7D5,0xF383,0xF384,0xF385,0xF386,0xF7D6,0xF387,
+0xF388,0xF389,0xF38A,0xF7D8,0xF38B,0xF7DA,0xF38C,0xF7D7,
+0xF38D,0xF38E,0xF38F,0xF390,0xF391,0xF392,0xF393,0xF394,
+0xF395,0xF7DB,0xF396,0xF7D9,0xF397,0xF398,0xF399,0xF39A,
+0xF39B,0xF39C,0xF39D,0xD7D7,0xF39E,0xF39F,0xF3A0,0xF440,
+0xF7DC,0xF441,0xF442,0xF443,0xF444,0xF445,0xF446,0xF7DD,
+0xF447,0xF448,0xF449,0xF7DE,0xF44A,0xF44B,0xF44C,0xF44D,
+0xF44E,0xF44F,0xF450,0xF451,0xF452,0xF453,0xF454,0xF7DF,
+0xF455,0xF456,0xF457,0xF7E0,0xF458,0xF459,0xF45A,0xF45B,
+0xF45C,0xF45D,0xF45E,0xF45F,0xF460,0xF461,0xF462,0xDBCB,
+0xF463,0xF464,0xD8AA,0xF465,0xF466,0xF467,0xF468,0xF469,
+0xF46A,0xF46B,0xF46C,0xE5F7,0xB9ED,0xF46D,0xF46E,0xF46F,
+0xF470,0xBFFD,0xBBEA,0xF7C9,0xC6C7,0xF7C8,0xF471,0xF7CA,
+0xF7CC,0xF7CB,0xF472,0xF473,0xF474,0xF7CD,0xF475,0xCEBA,
+0xF476,0xF7CE,0xF477,0xF478,0xC4A7,0xF479,0xF47A,0xF47B,
+0xF47C,0xF47D,0xF47E,0xF480,0xF481,0xF482,0xF483,0xF484,
+0xF485,0xF486,0xF487,0xF488,0xF489,0xF48A,0xF48B,0xF48C,
+0xF48D,0xF48E,0xF48F,0xF490,0xF491,0xF492,0xF493,0xF494,
+0xF495,0xF496,0xF497,0xF498,0xF499,0xF49A,0xF49B,0xF49C,
+0xF49D,0xF49E,0xF49F,0xF4A0,0xF540,0xF541,0xF542,0xF543,
+0xF544,0xF545,0xF546,0xF547,0xF548,0xF549,0xF54A,0xF54B,
+0xF54C,0xF54D,0xF54E,0xF54F,0xF550,0xF551,0xF552,0xF553,
+0xF554,0xF555,0xF556,0xF557,0xF558,0xF559,0xF55A,0xF55B,
+0xF55C,0xF55D,0xF55E,0xF55F,0xF560,0xF561,0xF562,0xF563,
+0xF564,0xF565,0xF566,0xF567,0xF568,0xF569,0xF56A,0xF56B,
+0xF56C,0xF56D,0xF56E,0xF56F,0xF570,0xF571,0xF572,0xF573,
+0xF574,0xF575,0xF576,0xF577,0xF578,0xF579,0xF57A,0xF57B,
+0xF57C,0xF57D,0xF57E,0xF580,0xF581,0xF582,0xF583,0xF584,
+0xF585,0xF586,0xF587,0xF588,0xF589,0xF58A,0xF58B,0xF58C,
+0xF58D,0xF58E,0xF58F,0xF590,0xF591,0xF592,0xF593,0xF594,
+0xF595,0xF596,0xF597,0xF598,0xF599,0xF59A,0xF59B,0xF59C,
+0xF59D,0xF59E,0xF59F,0xF5A0,0xF640,0xF641,0xF642,0xF643,
+0xF644,0xF645,0xF646,0xF647,0xF648,0xF649,0xF64A,0xF64B,
+0xF64C,0xF64D,0xF64E,0xF64F,0xF650,0xF651,0xF652,0xF653,
+0xF654,0xF655,0xF656,0xF657,0xF658,0xF659,0xF65A,0xF65B,
+0xF65C,0xF65D,0xF65E,0xF65F,0xF660,0xF661,0xF662,0xF663,
+0xF664,0xF665,0xF666,0xF667,0xF668,0xF669,0xF66A,0xF66B,
+0xF66C,0xF66D,0xF66E,0xF66F,0xF670,0xF671,0xF672,0xF673,
+0xF674,0xF675,0xF676,0xF677,0xF678,0xF679,0xF67A,0xF67B,
+0xF67C,0xF67D,0xF67E,0xF680,0xF681,0xF682,0xF683,0xF684,
+0xF685,0xF686,0xF687,0xF688,0xF689,0xF68A,0xF68B,0xF68C,
+0xF68D,0xF68E,0xF68F,0xF690,0xF691,0xF692,0xF693,0xF694,
+0xF695,0xF696,0xF697,0xF698,0xF699,0xF69A,0xF69B,0xF69C,
+0xF69D,0xF69E,0xF69F,0xF6A0,0xF740,0xF741,0xF742,0xF743,
+0xF744,0xF745,0xF746,0xF747,0xF748,0xF749,0xF74A,0xF74B,
+0xF74C,0xF74D,0xF74E,0xF74F,0xF750,0xF751,0xF752,0xF753,
+0xF754,0xF755,0xF756,0xF757,0xF758,0xF759,0xF75A,0xF75B,
+0xF75C,0xF75D,0xF75E,0xF75F,0xF760,0xF761,0xF762,0xF763,
+0xF764,0xF765,0xF766,0xF767,0xF768,0xF769,0xF76A,0xF76B,
+0xF76C,0xF76D,0xF76E,0xF76F,0xF770,0xF771,0xF772,0xF773,
+0xF774,0xF775,0xF776,0xF777,0xF778,0xF779,0xF77A,0xF77B,
+0xF77C,0xF77D,0xF77E,0xF780,0xD3E3,0xF781,0xF782,0xF6CF,
+0xF783,0xC2B3,0xF6D0,0xF784,0xF785,0xF6D1,0xF6D2,0xF6D3,
+0xF6D4,0xF786,0xF787,0xF6D6,0xF788,0xB1AB,0xF6D7,0xF789,
+0xF6D8,0xF6D9,0xF6DA,0xF78A,0xF6DB,0xF6DC,0xF78B,0xF78C,
+0xF78D,0xF78E,0xF6DD,0xF6DE,0xCFCA,0xF78F,0xF6DF,0xF6E0,
+0xF6E1,0xF6E2,0xF6E3,0xF6E4,0xC0F0,0xF6E5,0xF6E6,0xF6E7,
+0xF6E8,0xF6E9,0xF790,0xF6EA,0xF791,0xF6EB,0xF6EC,0xF792,
+0xF6ED,0xF6EE,0xF6EF,0xF6F0,0xF6F1,0xF6F2,0xF6F3,0xF6F4,
+0xBEA8,0xF793,0xF6F5,0xF6F6,0xF6F7,0xF6F8,0xF794,0xF795,
+0xF796,0xF797,0xF798,0xC8FA,0xF6F9,0xF6FA,0xF6FB,0xF6FC,
+0xF799,0xF79A,0xF6FD,0xF6FE,0xF7A1,0xF7A2,0xF7A3,0xF7A4,
+0xF7A5,0xF79B,0xF79C,0xF7A6,0xF7A7,0xF7A8,0xB1EE,0xF7A9,
+0xF7AA,0xF7AB,0xF79D,0xF79E,0xF7AC,0xF7AD,0xC1DB,0xF7AE,
+0xF79F,0xF7A0,0xF7AF,0xF840,0xF841,0xF842,0xF843,0xF844,
+0xF845,0xF846,0xF847,0xF848,0xF849,0xF84A,0xF84B,0xF84C,
+0xF84D,0xF84E,0xF84F,0xF850,0xF851,0xF852,0xF853,0xF854,
+0xF855,0xF856,0xF857,0xF858,0xF859,0xF85A,0xF85B,0xF85C,
+0xF85D,0xF85E,0xF85F,0xF860,0xF861,0xF862,0xF863,0xF864,
+0xF865,0xF866,0xF867,0xF868,0xF869,0xF86A,0xF86B,0xF86C,
+0xF86D,0xF86E,0xF86F,0xF870,0xF871,0xF872,0xF873,0xF874,
+0xF875,0xF876,0xF877,0xF878,0xF879,0xF87A,0xF87B,0xF87C,
+0xF87D,0xF87E,0xF880,0xF881,0xF882,0xF883,0xF884,0xF885,
+0xF886,0xF887,0xF888,0xF889,0xF88A,0xF88B,0xF88C,0xF88D,
+0xF88E,0xF88F,0xF890,0xF891,0xF892,0xF893,0xF894,0xF895,
+0xF896,0xF897,0xF898,0xF899,0xF89A,0xF89B,0xF89C,0xF89D,
+0xF89E,0xF89F,0xF8A0,0xF940,0xF941,0xF942,0xF943,0xF944,
+0xF945,0xF946,0xF947,0xF948,0xF949,0xF94A,0xF94B,0xF94C,
+0xF94D,0xF94E,0xF94F,0xF950,0xF951,0xF952,0xF953,0xF954,
+0xF955,0xF956,0xF957,0xF958,0xF959,0xF95A,0xF95B,0xF95C,
+0xF95D,0xF95E,0xF95F,0xF960,0xF961,0xF962,0xF963,0xF964,
+0xF965,0xF966,0xF967,0xF968,0xF969,0xF96A,0xF96B,0xF96C,
+0xF96D,0xF96E,0xF96F,0xF970,0xF971,0xF972,0xF973,0xF974,
+0xF975,0xF976,0xF977,0xF978,0xF979,0xF97A,0xF97B,0xF97C,
+0xF97D,0xF97E,0xF980,0xF981,0xF982,0xF983,0xF984,0xF985,
+0xF986,0xF987,0xF988,0xF989,0xF98A,0xF98B,0xF98C,0xF98D,
+0xF98E,0xF98F,0xF990,0xF991,0xF992,0xF993,0xF994,0xF995,
+0xF996,0xF997,0xF998,0xF999,0xF99A,0xF99B,0xF99C,0xF99D,
+0xF99E,0xF99F,0xF9A0,0xFA40,0xFA41,0xFA42,0xFA43,0xFA44,
+0xFA45,0xFA46,0xFA47,0xFA48,0xFA49,0xFA4A,0xFA4B,0xFA4C,
+0xFA4D,0xFA4E,0xFA4F,0xFA50,0xFA51,0xFA52,0xFA53,0xFA54,
+0xFA55,0xFA56,0xFA57,0xFA58,0xFA59,0xFA5A,0xFA5B,0xFA5C,
+0xFA5D,0xFA5E,0xFA5F,0xFA60,0xFA61,0xFA62,0xFA63,0xFA64,
+0xFA65,0xFA66,0xFA67,0xFA68,0xFA69,0xFA6A,0xFA6B,0xFA6C,
+0xFA6D,0xFA6E,0xFA6F,0xFA70,0xFA71,0xFA72,0xFA73,0xFA74,
+0xFA75,0xFA76,0xFA77,0xFA78,0xFA79,0xFA7A,0xFA7B,0xFA7C,
+0xFA7D,0xFA7E,0xFA80,0xFA81,0xFA82,0xFA83,0xFA84,0xFA85,
+0xFA86,0xFA87,0xFA88,0xFA89,0xFA8A,0xFA8B,0xFA8C,0xFA8D,
+0xFA8E,0xFA8F,0xFA90,0xFA91,0xFA92,0xFA93,0xFA94,0xFA95,
+0xFA96,0xFA97,0xFA98,0xFA99,0xFA9A,0xFA9B,0xFA9C,0xFA9D,
+0xFA9E,0xFA9F,0xFAA0,0xFB40,0xFB41,0xFB42,0xFB43,0xFB44,
+0xFB45,0xFB46,0xFB47,0xFB48,0xFB49,0xFB4A,0xFB4B,0xFB4C,
+0xFB4D,0xFB4E,0xFB4F,0xFB50,0xFB51,0xFB52,0xFB53,0xFB54,
+0xFB55,0xFB56,0xFB57,0xFB58,0xFB59,0xFB5A,0xFB5B,0xC4F1,
+0xF0AF,0xBCA6,0xF0B0,0xC3F9,0xFB5C,0xC5B8,0xD1BB,0xFB5D,
+0xF0B1,0xF0B2,0xF0B3,0xF0B4,0xF0B5,0xD1BC,0xFB5E,0xD1EC,
+0xFB5F,0xF0B7,0xF0B6,0xD4A7,0xFB60,0xCDD2,0xF0B8,0xF0BA,
+0xF0B9,0xF0BB,0xF0BC,0xFB61,0xFB62,0xB8EB,0xF0BD,0xBAE8,
+0xFB63,0xF0BE,0xF0BF,0xBEE9,0xF0C0,0xB6EC,0xF0C1,0xF0C2,
+0xF0C3,0xF0C4,0xC8B5,0xF0C5,0xF0C6,0xFB64,0xF0C7,0xC5F4,
+0xFB65,0xF0C8,0xFB66,0xFB67,0xFB68,0xF0C9,0xFB69,0xF0CA,
+0xF7BD,0xFB6A,0xF0CB,0xF0CC,0xF0CD,0xFB6B,0xF0CE,0xFB6C,
+0xFB6D,0xFB6E,0xFB6F,0xF0CF,0xBAD7,0xFB70,0xF0D0,0xF0D1,
+0xF0D2,0xF0D3,0xF0D4,0xF0D5,0xF0D6,0xF0D8,0xFB71,0xFB72,
+0xD3A5,0xF0D7,0xFB73,0xF0D9,0xFB74,0xFB75,0xFB76,0xFB77,
+0xFB78,0xFB79,0xFB7A,0xFB7B,0xFB7C,0xFB7D,0xF5BA,0xC2B9,
+0xFB7E,0xFB80,0xF7E4,0xFB81,0xFB82,0xFB83,0xFB84,0xF7E5,
+0xF7E6,0xFB85,0xFB86,0xF7E7,0xFB87,0xFB88,0xFB89,0xFB8A,
+0xFB8B,0xFB8C,0xF7E8,0xC2B4,0xFB8D,0xFB8E,0xFB8F,0xFB90,
+0xFB91,0xFB92,0xFB93,0xFB94,0xFB95,0xF7EA,0xFB96,0xF7EB,
+0xFB97,0xFB98,0xFB99,0xFB9A,0xFB9B,0xFB9C,0xC2F3,0xFB9D,
+0xFB9E,0xFB9F,0xFBA0,0xFC40,0xFC41,0xFC42,0xFC43,0xFC44,
+0xFC45,0xFC46,0xFC47,0xFC48,0xF4F0,0xFC49,0xFC4A,0xFC4B,
+0xF4EF,0xFC4C,0xFC4D,0xC2E9,0xFC4E,0xF7E1,0xF7E2,0xFC4F,
+0xFC50,0xFC51,0xFC52,0xFC53,0xBBC6,0xFC54,0xFC55,0xFC56,
+0xFC57,0xD9E4,0xFC58,0xFC59,0xFC5A,0xCAF2,0xC0E8,0xF0A4,
+0xFC5B,0xBADA,0xFC5C,0xFC5D,0xC7AD,0xFC5E,0xFC5F,0xFC60,
+0xC4AC,0xFC61,0xFC62,0xF7EC,0xF7ED,0xF7EE,0xFC63,0xF7F0,
+0xF7EF,0xFC64,0xF7F1,0xFC65,0xFC66,0xF7F4,0xFC67,0xF7F3,
+0xFC68,0xF7F2,0xF7F5,0xFC69,0xFC6A,0xFC6B,0xFC6C,0xF7F6,
+0xFC6D,0xFC6E,0xFC6F,0xFC70,0xFC71,0xFC72,0xFC73,0xFC74,
+0xFC75,0xEDE9,0xFC76,0xEDEA,0xEDEB,0xFC77,0xF6BC,0xFC78,
+0xFC79,0xFC7A,0xFC7B,0xFC7C,0xFC7D,0xFC7E,0xFC80,0xFC81,
+0xFC82,0xFC83,0xFC84,0xF6BD,0xFC85,0xF6BE,0xB6A6,0xFC86,
+0xD8BE,0xFC87,0xFC88,0xB9C4,0xFC89,0xFC8A,0xFC8B,0xD8BB,
+0xFC8C,0xDCB1,0xFC8D,0xFC8E,0xFC8F,0xFC90,0xFC91,0xFC92,
+0xCAF3,0xFC93,0xF7F7,0xFC94,0xFC95,0xFC96,0xFC97,0xFC98,
+0xFC99,0xFC9A,0xFC9B,0xFC9C,0xF7F8,0xFC9D,0xFC9E,0xF7F9,
+0xFC9F,0xFCA0,0xFD40,0xFD41,0xFD42,0xFD43,0xFD44,0xF7FB,
+0xFD45,0xF7FA,0xFD46,0xB1C7,0xFD47,0xF7FC,0xF7FD,0xFD48,
+0xFD49,0xFD4A,0xFD4B,0xFD4C,0xF7FE,0xFD4D,0xFD4E,0xFD4F,
+0xFD50,0xFD51,0xFD52,0xFD53,0xFD54,0xFD55,0xFD56,0xFD57,
+0xC6EB,0xECB4,0xFD58,0xFD59,0xFD5A,0xFD5B,0xFD5C,0xFD5D,
+0xFD5E,0xFD5F,0xFD60,0xFD61,0xFD62,0xFD63,0xFD64,0xFD65,
+0xFD66,0xFD67,0xFD68,0xFD69,0xFD6A,0xFD6B,0xFD6C,0xFD6D,
+0xFD6E,0xFD6F,0xFD70,0xFD71,0xFD72,0xFD73,0xFD74,0xFD75,
+0xFD76,0xFD77,0xFD78,0xFD79,0xFD7A,0xFD7B,0xFD7C,0xFD7D,
+0xFD7E,0xFD80,0xFD81,0xFD82,0xFD83,0xFD84,0xFD85,0xB3DD,
+0xF6B3,0xFD86,0xFD87,0xF6B4,0xC1E4,0xF6B5,0xF6B6,0xF6B7,
+0xF6B8,0xF6B9,0xF6BA,0xC8A3,0xF6BB,0xFD88,0xFD89,0xFD8A,
+0xFD8B,0xFD8C,0xFD8D,0xFD8E,0xFD8F,0xFD90,0xFD91,0xFD92,
+0xFD93,0xC1FA,0xB9A8,0xEDE8,0xFD94,0xFD95,0xFD96,0xB9EA,
+0xD9DF,0xFD97,0xFD98,0xFD99,0xFD9A,0xFD9B};
+
+/* page 7 0xF92C-0xFA29 */
+static uint16 tab_uni_gbk7[]={
+0xFD9C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFD9D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFD9E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFD9F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xFDA0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFE40,0xFE41,0xFE42,0xFE43, 0,0xFE44, 0,0xFE45,
+0xFE46, 0, 0, 0,0xFE47, 0, 0, 0,
+ 0, 0, 0,0xFE48,0xFE49,0xFE4A, 0,0xFE4B,
+0xFE4C, 0, 0,0xFE4D,0xFE4E,0xFE4F};
+
+/* page 8 0xFE30-0xFFE5 */
+static uint16 tab_uni_gbk8[]={
+0xA955,0xA6F2, 0,0xA6F4,0xA6F5,0xA6E0,0xA6E1,0xA6F0,
+0xA6F1,0xA6E2,0xA6E3,0xA6EE,0xA6EF,0xA6E6,0xA6E7,0xA6E4,
+0xA6E5,0xA6E8,0xA6E9,0xA6EA,0xA6EB, 0, 0, 0,
+ 0,0xA968,0xA969,0xA96A,0xA96B,0xA96C,0xA96D,0xA96E,
+0xA96F,0xA970,0xA971, 0,0xA972,0xA973,0xA974,0xA975,
+ 0,0xA976,0xA977,0xA978,0xA979,0xA97A,0xA97B,0xA97C,
+0xA97D,0xA97E,0xA980,0xA981,0xA982,0xA983,0xA984, 0,
+0xA985,0xA986,0xA987,0xA988, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA3A1,0xA3A2,0xA3A3,0xA1E7,0xA3A5,0xA3A6,0xA3A7,
+0xA3A8,0xA3A9,0xA3AA,0xA3AB,0xA3AC,0xA3AD,0xA3AE,0xA3AF,
+0xA3B0,0xA3B1,0xA3B2,0xA3B3,0xA3B4,0xA3B5,0xA3B6,0xA3B7,
+0xA3B8,0xA3B9,0xA3BA,0xA3BB,0xA3BC,0xA3BD,0xA3BE,0xA3BF,
+0xA3C0,0xA3C1,0xA3C2,0xA3C3,0xA3C4,0xA3C5,0xA3C6,0xA3C7,
+0xA3C8,0xA3C9,0xA3CA,0xA3CB,0xA3CC,0xA3CD,0xA3CE,0xA3CF,
+0xA3D0,0xA3D1,0xA3D2,0xA3D3,0xA3D4,0xA3D5,0xA3D6,0xA3D7,
+0xA3D8,0xA3D9,0xA3DA,0xA3DB,0xA3DC,0xA3DD,0xA3DE,0xA3DF,
+0xA3E0,0xA3E1,0xA3E2,0xA3E3,0xA3E4,0xA3E5,0xA3E6,0xA3E7,
+0xA3E8,0xA3E9,0xA3EA,0xA3EB,0xA3EC,0xA3ED,0xA3EE,0xA3EF,
+0xA3F0,0xA3F1,0xA3F2,0xA3F3,0xA3F4,0xA3F5,0xA3F6,0xA3F7,
+0xA3F8,0xA3F9,0xA3FA,0xA3FB,0xA3FC,0xA3FD,0xA1AB, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xA1E9,0xA1EA,0xA956,0xA3FE,0xA957,0xA3A4};
+
+static int func_uni_gbk_onechar(int code){
+ if ((code>=0x00A4)&&(code<=0x0451))
+ return(tab_uni_gbk0[code-0x00A4]);
+ if ((code>=0x2010)&&(code<=0x2312))
+ return(tab_uni_gbk1[code-0x2010]);
+ if ((code>=0x2460)&&(code<=0x2642))
+ return(tab_uni_gbk2[code-0x2460]);
+ if ((code>=0x3000)&&(code<=0x3129))
+ return(tab_uni_gbk3[code-0x3000]);
+ if ((code>=0x3220)&&(code<=0x32A3))
+ return(tab_uni_gbk4[code-0x3220]);
+ if ((code>=0x338E)&&(code<=0x33D5))
+ return(tab_uni_gbk5[code-0x338E]);
+ if ((code>=0x4E00)&&(code<=0x9FA5))
+ return(tab_uni_gbk6[code-0x4E00]);
+ if ((code>=0xF92C)&&(code<=0xFA29))
+ return(tab_uni_gbk7[code-0xF92C]);
+ if ((code>=0xFE30)&&(code<=0xFFE5))
+ return(tab_uni_gbk8[code-0xFE30]);
+ return(0);
+}
+
+static int
+my_wc_mb_gbk(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *s, uchar *e)
+{
+ int code;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if (wc<0x80)
+ {
+ s[0]=wc;
+ return 1;
+ }
+
+ if (!(code=func_uni_gbk_onechar(wc)))
+ return MY_CS_ILUNI;
+
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=code>>8;
+ s[1]=code&0xFF;
+ return 2;
+}
+
+static int
+my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *pwc, const uchar *s, const uchar *e)
+{
+ int hi;
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ hi=s[0];
+
+ if (hi<0x80)
+ {
+ pwc[0]=hi;
+ return 1;
+ }
+
+ if (s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ if (!(pwc[0]=func_gbk_uni_onechar( (hi<<8) + s[1])))
+ return MY_CS_ILSEQ;
+
+ return 2;
+
+}
+
+CHARSET_INFO my_charset_gbk =
+{
+ 28, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ "gbk", /* cs name */
+ "gbk", /* name */
+ "", /* comment */
+ ctype_gbk,
+ to_lower_gbk,
+ to_upper_gbk,
+ sort_order_gbk,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 1, /* strxfrm_multiply */
+ my_strnncoll_gbk,
+ my_strnncollsp_gbk,
+ my_strnxfrm_gbk,
+ my_like_range_gbk,
+ my_wildcmp_mb, /* wildcmp */
+ 2, /* mbmaxlen */
+ ismbchar_gbk,
+ ismbhead_gbk,
+ mbcharlen_gbk,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_mb_wc_gbk, /* mb_wc */
+ my_wc_mb_gbk, /* wc_mb */
+ my_caseup_str_mb,
+ my_casedn_str_mb,
+ my_caseup_mb,
+ my_casedn_mb,
+ NULL, /* tosort */
+ my_strcasecmp_mb,
+ my_strncasecmp_mb,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+
+#endif
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
new file mode 100644
index 00000000000..518418a9050
--- /dev/null
+++ b/strings/ctype-latin1.c
@@ -0,0 +1,225 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <my_global.h>
+#include "m_string.h"
+#include "m_ctype.h"
+
+
+static my_wc_t latin1_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+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,
+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 uchar uni_latin1[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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};
+
+static uchar ctype_latin1[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static uchar to_lower_latin1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_latin1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+static uchar sort_order_latin1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 93,215,216, 85, 85, 85, 89, 89,222,223,
+ 65, 65, 65, 65, 92, 91, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79, 93,247,216, 85, 85, 85, 89, 89,222,255
+};
+
+
+static
+int my_mb_wc_latin1(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *wc,
+ const unsigned char *str,
+ const unsigned char *end)
+{
+ if (str >= end)
+ return MY_CS_TOOFEW(0);
+
+ return ((wc[0]= latin1_uni[*str]) || (!str[0])) ? 1 : MY_CS_ILSEQ;
+}
+
+static
+int my_wc_mb_latin1(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc,
+ unsigned char *str,
+ unsigned char *end)
+{
+ if (str >= end)
+ return MY_CS_TOOSMALL;
+
+ return ((wc < 256) && ((str[0]=uni_latin1[wc]) || (!wc))) ? 1 : MY_CS_ILUNI;
+}
+
+
+CHARSET_INFO my_charset_latin1 =
+{
+ 8, /* number */
+ MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
+ "latin1", /* name */
+ "", /* comment */
+ ctype_latin1,
+ to_lower_latin1,
+ to_upper_latin1,
+ sort_order_latin1,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 2, /* strxfrm_multiply */
+ my_strnncoll_simple,
+ my_strnncollsp_simple,
+ my_strnxfrm_simple,
+ my_like_range_simple,
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_latin1, /* mb_wc */
+ my_wc_mb_latin1, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ NULL, /* tosort */
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c
index 01d377f91c3..93c8ba54bc0 100644
--- a/strings/ctype-latin1_de.c
+++ b/strings/ctype-latin1_de.c
@@ -36,7 +36,67 @@
#include "m_string.h"
#include "m_ctype.h"
-uchar ctype_latin1_de[] = {
+#ifdef HAVE_CHARSET_latin1_de
+
+static uint16 tab_8859_1_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+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,
+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 uchar tab_uni_8859_1_plane00[]={
+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,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,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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};
+
+static MY_UNI_IDX idx_uni_8859_1[]={
+ {0x0000,0x00FF,tab_uni_8859_1_plane00},
+ {0,0,NULL}
+};
+
+static uchar ctype_latin1_de[] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@@ -56,7 +116,7 @@ uchar ctype_latin1_de[] = {
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
};
-uchar to_lower_latin1_de[] = {
+static uchar to_lower_latin1_de[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -75,7 +135,7 @@ uchar to_lower_latin1_de[] = {
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
-uchar to_upper_latin1_de[] = {
+static uchar to_upper_latin1_de[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -102,7 +162,7 @@ uchar to_upper_latin1_de[] = {
* Ü, ü, Ö, ö, Ä, ä
*/
-uchar sort_order_latin1_de[] = {
+static uchar sort_order_latin1_de[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -162,8 +222,9 @@ uchar sort_order_latin1_de[] = {
}
-int my_strnncoll_latin1_de(const uchar * s1, int len1,
- const uchar * s2, int len2)
+static int my_strnncoll_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar * s1, uint len1,
+ const uchar * s2, uint len2)
{
const uchar *e1 = s1 + len1;
const uchar *e2 = s2 + len2;
@@ -234,8 +295,20 @@ int my_strnncoll_latin1_de(const uchar * s1, int len1,
return s1 < e1 ? 1 : s2 < e2 ? -1 : 0;
}
+static
+int my_strnncollsp_latin1_de(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_latin1_de(cs,s,slen,t,tlen);
+}
+
-int my_strnxfrm_latin1_de(uchar * dest, const uchar * src, int len, int srclen)
+static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar * src, uint srclen)
{
const uchar *dest_orig = dest;
const uchar *de = dest + len;
@@ -273,89 +346,53 @@ int my_strnxfrm_latin1_de(uchar * dest, const uchar * src, int len, int srclen)
return dest - dest_orig;
}
-
-int my_strcoll_latin1_de(const uchar * s1, const uchar * s2)
-{
- /* XXX QQ: This should be fixed to not call strlen */
- return my_strnncoll_latin1_de(s1, strlen((char*) s1),
- s2, strlen((char*) s2));
-}
-
-int my_strxfrm_latin1_de(uchar * dest, const uchar * src, int len)
-{
- /* XXX QQ: This should be fixed to not call strlen */
- return my_strnxfrm_latin1_de(dest, src, len, strlen((char*) src));
-}
-
-/*
- * Calculate min_str and max_str that ranges a LIKE string.
- * Arguments:
- * ptr IN: Pointer to LIKE string.
- * ptr_length IN: Length of LIKE string.
- * escape IN: Escape character in LIKE. (Normally '\').
- * No escape characters should appear in min_str or max_str
- * res_length IN: Length of min_str and max_str.
- * min_str IN/OUT: Smallest case sensitive string that ranges LIKE.
- * Should be space padded to res_length.
- * max_str IN/OUT: Largest case sensitive string that ranges LIKE.
- * Normally padded with the biggest character sort value.
- * min_length OUT: Length of min_str without space padding.
- * max_length OUT: Length of max_str without space padding.
- *
- * The function should return 0 if ok and 1 if the LIKE string can't be
- * optimized !
- */
-
-#define min_sort_char ((char) 0)
-#define max_sort_char ((char) 255)
-#define wild_one '_'
-#define wild_many '%'
-
-my_bool my_like_range_latin1_de(const char *ptr, uint ptr_length,
- pchar escape, uint res_length,
- char *min_str, char *max_str,
- uint *min_length, uint *max_length)
+CHARSET_INFO my_charset_latin1_de =
{
- const char *end = ptr + ptr_length;
- char *min_org = min_str;
- char *min_end = min_str + res_length;
-
- for (; ptr != end && min_str != min_end; ptr++)
- {
- if (*ptr == escape && ptr + 1 != end)
- {
- ptr++; /* Skip escape */
- *min_str++ = *max_str++ = *ptr;
- continue;
- }
- if (*ptr == wild_one) /* '_' in SQL */
- {
- *min_str++ = min_sort_char;
- *max_str++ = max_sort_char;
- continue;
- }
- if (*ptr == wild_many) /* '%' in SQL */
- {
- *min_length = (uint)(min_str - min_org);
- *max_length = res_length;
- do {
- *min_str++ = ' '; /* Because if key compression */
- *max_str++ = max_sort_char;
- } while (min_str != min_end);
- return 0;
- }
- *min_str++ = *max_str++ = *ptr;
- }
- *min_length = *max_length = (uint) (min_str - min_org);
-
- /* Temporary fix for handling wild_one at end of string (key compression) */
- {
- char *tmp;
- for (tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
- *--tmp=' ';
- }
+ 31, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */
+ "latin1", /* cs name */
+ "latin1_de", /* name */
+ "", /* comment */
+ ctype_latin1_de,
+ to_lower_latin1_de,
+ to_upper_latin1_de,
+ sort_order_latin1_de,
+ tab_8859_1_uni, /* tab_to_uni */
+ idx_uni_8859_1, /* tab_from_uni */
+ 2, /* strxfrm_multiply */
+ my_strnncoll_latin1_de,
+ my_strnncollsp_latin1_de,
+ my_strnxfrm_latin1_de,
+ my_like_range_simple,
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ NULL, /* tosort */
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
- while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
- return 0;
-}
+#endif
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
new file mode 100644
index 00000000000..aa4ccdb6af7
--- /dev/null
+++ b/strings/ctype-mb.c
@@ -0,0 +1,306 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <my_global.h>
+#include "m_ctype.h"
+#include "m_string.h"
+
+#ifdef USE_MB
+
+
+void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
+{
+ register uint32 l;
+ register char *end=str+strlen(str); /* BAR TODO: remove strlen() call */
+ register uchar *map=cs->to_upper;
+
+ while (*str)
+ {
+ if ((l=my_ismbchar(cs, str,end)))
+ str+=l;
+ else
+ {
+ *str=(char) map[(uchar)*str];
+ str++;
+ }
+ }
+}
+
+void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
+{
+ register uint32 l;
+ register char *end=str+strlen(str);
+ register uchar *map=cs->to_lower;
+
+ while (*str)
+ {
+ if ((l=my_ismbchar(cs, str,end)))
+ str+=l;
+ else
+ {
+ *str=(char) map[(uchar)*str];
+ str++;
+ }
+ }
+}
+
+void my_caseup_mb(CHARSET_INFO * cs, char *str, uint length)
+{
+ register uint32 l;
+ register char *end=str+length;
+ register uchar *map=cs->to_upper;
+
+ while (str<end)
+ {
+ if ((l=my_ismbchar(cs, str,end)))
+ str+=l;
+ else
+ {
+ *str=(char) map[(uchar)*str];
+ str++;
+ }
+ }
+}
+
+void my_casedn_mb(CHARSET_INFO * cs, char *str, uint length)
+{
+ register uint32 l;
+ register char *end=str+length;
+ register uchar *map=cs->to_lower;
+
+ while (str<end)
+ {
+ if ((l=my_ismbchar(cs, str,end)))
+ str+=l;
+ else
+ {
+ *str=(char) map[(uchar)*str];
+ str++;
+ }
+ }
+}
+
+int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
+{
+ register uint32 l;
+ register const char *end=s+strlen(s);
+ register uchar *map=cs->to_upper;
+
+ while (s<end)
+ {
+ if ((l=my_ismbchar(cs, s,end)))
+ {
+ while (l--)
+ if (*s++ != *t++)
+ return 1;
+ }
+ else if (my_ismbhead(cs, *t))
+ return 1;
+ else if (map[(uchar) *s++] != map[(uchar) *t++])
+ return 1;
+ }
+ return *t;
+}
+
+
+int my_strncasecmp_mb(CHARSET_INFO * cs,
+ const char *s, const char *t, uint len)
+{
+ register uint32 l;
+ register const char *end=s+len;
+ register uchar *map=cs->to_upper;
+
+ while (s<end)
+ {
+ if ((l=my_ismbchar(cs, s,end)))
+ {
+ while (l--)
+ if (*s++ != *t++)
+ return 1;
+ }
+ else if (my_ismbhead(cs, *t))
+ return 1;
+ else if (map[(uchar) *s++] != map[(uchar) *t++])
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+** Compare string against string with wildcard
+** 0 if matched
+** -1 if not matched with wildcard
+** 1 if matched with wildcard
+*/
+
+#define INC_PTR(cs,A,B) A+=((use_mb_flag && \
+ my_ismbchar(cs,A,B)) ? my_ismbchar(cs,A,B) : 1)
+
+#ifdef LIKE_CMP_TOUPPER
+#define likeconv(s,A) (uchar) my_toupper(s,A)
+#else
+#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
+#endif
+
+int my_wildcmp_mb(CHARSET_INFO *cs,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many)
+{
+ int result= -1; // Not found, using wildcards
+
+ bool use_mb_flag=use_mb(cs);
+
+ while (wildstr != wildend)
+ {
+ while (*wildstr != w_many && *wildstr != w_one)
+ {
+ int l;
+ if (*wildstr == escape && wildstr+1 != wildend)
+ wildstr++;
+ if (use_mb_flag &&
+ (l = my_ismbchar(cs, wildstr, wildend)))
+ {
+ if (str+l > str_end || memcmp(str, wildstr, l) != 0)
+ return 1;
+ str += l;
+ wildstr += l;
+ }
+ else
+ if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
+ return(1); // No match
+ if (wildstr == wildend)
+ return (str != str_end); // Match if both are at end
+ result=1; // Found an anchor char
+ }
+ if (*wildstr == w_one)
+ {
+ do
+ {
+ if (str == str_end) // Skip one char if possible
+ return (result);
+ INC_PTR(cs,str,str_end);
+ } while (++wildstr < wildend && *wildstr == w_one);
+ if (wildstr == wildend)
+ break;
+ }
+ if (*wildstr == w_many)
+ { // Found w_many
+ uchar cmp;
+ const char* mb = wildstr;
+ int mblen=0;
+
+ wildstr++;
+ /* Remove any '%' and '_' from the wild search string */
+ for (; wildstr != wildend ; wildstr++)
+ {
+ if (*wildstr == w_many)
+ continue;
+ if (*wildstr == w_one)
+ {
+ if (str == str_end)
+ return (-1);
+ INC_PTR(cs,str,str_end);
+ continue;
+ }
+ break; // Not a wild character
+ }
+ if (wildstr == wildend)
+ return(0); // Ok if w_many is last
+ if (str == str_end)
+ return -1;
+
+ if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
+ cmp= *++wildstr;
+
+ mb=wildstr;
+ LINT_INIT(mblen);
+ if (use_mb_flag)
+ mblen = my_ismbchar(cs, wildstr, wildend);
+ INC_PTR(cs,wildstr,wildend); // This is compared trough cmp
+ cmp=likeconv(cs,cmp);
+ do
+ {
+ if (use_mb_flag)
+ {
+ for (;;)
+ {
+ if (str >= str_end)
+ return -1;
+ if (mblen)
+ {
+ if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
+ {
+ str += mblen;
+ break;
+ }
+ }
+ else if (!my_ismbchar(cs, str, str_end) &&
+ likeconv(cs,*str) == cmp)
+ {
+ str++;
+ break;
+ }
+ INC_PTR(cs,str, str_end);
+ }
+ }
+ else
+ {
+ while (str != str_end && likeconv(cs,*str) != cmp)
+ str++;
+ if (str++ == str_end) return (-1);
+ }
+ {
+ int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);
+ if (tmp <= 0)
+ return (tmp);
+ }
+ } while (str != str_end && wildstr[0] != w_many);
+ return(-1);
+ }
+ }
+ return (str != str_end ? 1 : 0);
+}
+
+uint my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b, const char *e)
+{
+ register uint32 n=0,mblen;
+ while (b < e)
+ {
+ b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
+ ++n;
+ }
+ return n;
+}
+
+uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b, const char *e, uint pos)
+{
+ uint mblen;
+ const char *b0=b;
+
+ while (pos && b<e)
+ {
+ b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
+ pos--;
+ }
+ return b-b0;
+}
+
+
+#endif
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
new file mode 100644
index 00000000000..5fb62d3056f
--- /dev/null
+++ b/strings/ctype-simple.c
@@ -0,0 +1,1052 @@
+/* Copyright (C) 2002 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <my_global.h>
+#include "m_string.h"
+#include "m_ctype.h"
+#include <errno.h>
+
+#include "stdarg.h"
+#include "assert.h"
+
+
+int my_strnxfrm_simple(CHARSET_INFO * cs,
+ uchar *dest, uint len,
+ const uchar *src, uint srclen)
+{
+ uchar *map= cs->sort_order;
+ const uchar *end;
+ DBUG_ASSERT(len >= srclen);
+
+ len= min(len,srclen);
+ for ( end=src+len; src < end ; )
+ *dest++= map[*src++];
+ return len;
+}
+
+int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ int len = ( slen > tlen ) ? tlen : slen;
+ uchar *map= cs->sort_order;
+ while (len--)
+ {
+ if (map[*s++] != map[*t++])
+ return ((int) map[s[-1]] - (int) map[t[-1]]);
+ }
+ return (int) (slen-tlen);
+}
+
+
+int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ uchar *map= cs->sort_order;
+ int len;
+
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+
+ len = ( slen > tlen ) ? tlen : slen;
+
+ while (len--)
+ {
+ if (map[*s++] != map[*t++])
+ return ((int) map[s[-1]] - (int) map[t[-1]]);
+ }
+ return (int) (slen-tlen);
+}
+
+void my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
+{
+ register uchar *map=cs->to_upper;
+ while ((*str = (char) map[(uchar) *str]) != 0)
+ str++;
+}
+
+void my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
+{
+ register uchar *map=cs->to_lower;
+ while ((*str = (char) map[(uchar)*str]) != 0)
+ str++;
+}
+
+void my_caseup_8bit(CHARSET_INFO * cs, char *str, uint length)
+{
+ register uchar *map=cs->to_upper;
+ for ( ; length>0 ; length--, str++)
+ *str= (char) map[(uchar)*str];
+}
+
+void my_casedn_8bit(CHARSET_INFO * cs, char *str, uint length)
+{
+ register uchar *map=cs->to_lower;
+ for ( ; length>0 ; length--, str++)
+ *str= (char) map[(uchar) *str];
+}
+
+void my_tosort_8bit(CHARSET_INFO *cs, char *str, uint length)
+{
+ register uchar *map=cs->sort_order;
+ for ( ; length>0 ; length--, str++)
+ *str= (char) map[(uchar) *str];
+}
+
+int my_strcasecmp_8bit(CHARSET_INFO * cs,const char *s, const char *t)
+{
+ register uchar *map=cs->to_upper;
+ while (map[(uchar) *s] == map[(uchar) *t++])
+ if (!*s++) return 0;
+ return ((int) map[(uchar) s[0]] - (int) map[(uchar) t[-1]]);
+}
+
+
+int my_strncasecmp_8bit(CHARSET_INFO * cs,
+ const char *s, const char *t, uint len)
+{
+ register uchar *map=cs->to_upper;
+ while (len-- != 0 && map[(uchar)*s++] == map[(uchar)*t++]) ;
+ return (int) len+1;
+}
+
+int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc,
+ const unsigned char *str,
+ const unsigned char *end __attribute__((unused)))
+{
+ if (str >= end)
+ return MY_CS_TOOFEW(0);
+
+ *wc=cs->tab_to_uni[*str];
+ return (!wc[0] && str[0]) ? MY_CS_ILSEQ : 1;
+}
+
+int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc,
+ unsigned char *str,
+ unsigned char *end __attribute__((unused)))
+{
+ MY_UNI_IDX *idx;
+
+ if (str >= end)
+ return MY_CS_TOOSMALL;
+
+ for (idx=cs->tab_from_uni; idx->tab ; idx++)
+ {
+ if (idx->from <= wc && idx->to >= wc)
+ {
+ str[0]= idx->tab[wc - idx->from];
+ return (!str[0] && wc) ? MY_CS_ILUNI : 1;
+ }
+ }
+ return MY_CS_ILUNI;
+}
+
+
+/*
+ We can't use vsprintf here as it's not guaranteed to return
+ the length on all operating systems.
+ This function is also not called in a safe environment, so the
+ end buffer must be checked.
+*/
+
+int my_snprintf_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ char* to, uint n __attribute__((unused)),
+ const char* fmt, ...)
+{
+ va_list args;
+ int result;
+ va_start(args,fmt);
+ result= my_vsnprintf(to, n, fmt, args);
+ va_end(args);
+ return result;
+}
+
+
+
+#ifndef NEW_HASH_FUNCTION
+
+ /* Calc hashvalue for a key, case indepenently */
+
+uint my_hash_caseup_simple(CHARSET_INFO *cs, const byte *key, uint length)
+{
+ register uint nr=1, nr2=4;
+ register uchar *map=cs->to_upper;
+
+ while (length--)
+ {
+ nr^= (((nr & 63)+nr2)*
+ ((uint) (uchar) map[(uchar)*key++])) + (nr << 8);
+ nr2+=3;
+ }
+ return((uint) nr);
+}
+
+#else
+
+uint my_hash_caseup_simple(CHARSET_INFO *cs, const byte *key, uint len)
+{
+ const byte *end=key+len;
+ uint hash;
+ for (hash = 0; key < end; key++)
+ {
+ hash *= 16777619;
+ hash ^= (uint) (uchar) my_toupper(cs,*key);
+ }
+ return (hash);
+}
+
+#endif
+
+void my_hash_sort_simple(CHARSET_INFO *cs,
+ const uchar *key, uint len,
+ ulong *nr1, ulong *nr2)
+{
+ register uchar *sort_order=cs->sort_order;
+ const uchar *pos = key;
+
+ key+= len;
+
+ for (; pos < (uchar*) key ; pos++)
+ {
+ nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
+ ((uint) sort_order[(uint) *pos])) + (nr1[0] << 8);
+ nr2[0]+=3;
+ }
+}
+
+
+long my_strntol_8bit(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative;
+ register ulong cutoff;
+ register unsigned int cutlim;
+ register ulong i;
+ register const char *s;
+ register unsigned char c;
+ const char *save, *e;
+ int overflow;
+
+ *err= 0; /* Initialize error indicator */
+#ifdef NOT_USED
+ if (base < 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ s = nptr;
+ e = nptr+l;
+
+ for ( ; s<e && my_isspace(cs, *s) ; s++);
+
+ if (s == e)
+ {
+ goto noconv;
+ }
+
+ /* Check for a sign. */
+ if (*s == '-')
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == '+')
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+#ifdef NOT_USED
+ if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
+ s += 2;
+#endif
+
+#ifdef NOT_USED
+ if (base == 0)
+ {
+ if (*s == '0')
+ {
+ if (s[1]=='X' || s[1]=='x')
+ {
+ s += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+#endif
+
+ save = s;
+ cutoff = ((ulong)~0L) / (unsigned long int) base;
+ cutlim = (uint) (((ulong)~0L) % (unsigned long int) base);
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; s != e; c = *++s)
+ {
+ if (c>='0' && c<='9')
+ c -= '0';
+ else if (c>='A' && c<='F')
+ c = c - 'A' + 10;
+ else if (c>='a' && c<='f')
+ c = c - 'a' + 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (ulong) base;
+ i += c;
+ }
+ }
+
+ if (s == save)
+ goto noconv;
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (negative)
+ {
+ if (i > (ulong) LONG_MIN)
+ overflow = 1;
+ }
+ else if (i > (ulong) LONG_MAX)
+ overflow = 1;
+
+ if (overflow)
+ {
+ err[0]= ERANGE;
+ return negative ? LONG_MIN : LONG_MAX;
+ }
+
+ return (negative ? -((long) i) : (long) i);
+
+noconv:
+ err[0]= EDOM;
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return 0L;
+}
+
+
+ulong my_strntoul_8bit(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative;
+ register ulong cutoff;
+ register unsigned int cutlim;
+ register ulong i;
+ register const char *s;
+ register unsigned char c;
+ const char *save, *e;
+ int overflow;
+
+ *err= 0; /* Initialize error indicator */
+#ifdef NOT_USED
+ if (base < 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ s = nptr;
+ e = nptr+l;
+
+ for( ; s<e && my_isspace(cs, *s); s++);
+
+ if (s==e)
+ {
+ goto noconv;
+ }
+
+ if (*s == '-')
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == '+')
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+#ifdef NOT_USED
+ if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
+ s += 2;
+#endif
+
+#ifdef NOT_USED
+ if (base == 0)
+ {
+ if (*s == '0')
+ {
+ if (s[1]=='X' || s[1]=='x')
+ {
+ s += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+#endif
+
+ save = s;
+ cutoff = ((ulong)~0L) / (unsigned long int) base;
+ cutlim = (uint) (((ulong)~0L) % (unsigned long int) base);
+ overflow = 0;
+ i = 0;
+
+ for (c = *s; s != e; c = *++s)
+ {
+ if (c>='0' && c<='9')
+ c -= '0';
+ else if (c>='A' && c<='F')
+ c = c - 'A' + 10;
+ else if (c>='a' && c<='f')
+ c = c - 'a' + 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (ulong) base;
+ i += c;
+ }
+ }
+
+ if (s == save)
+ goto noconv;
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (overflow)
+ {
+ err[0]= ERANGE;
+ return ((ulong)~0L);
+ }
+
+ return (negative ? -((long) i) : (long) i);
+
+noconv:
+ err[0]= EDOM;
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return 0L;
+}
+
+
+longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ const char *nptr, uint l, int base,
+ char **endptr,int *err)
+{
+ int negative;
+ register ulonglong cutoff;
+ register unsigned int cutlim;
+ register ulonglong i;
+ register const char *s, *e;
+ register unsigned char c;
+ const char *save;
+ int overflow;
+
+ *err= 0; /* Initialize error indicator */
+#ifdef NOT_USED
+ if (base < 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ s = nptr;
+ e = nptr+l;
+
+ for(; s<e && my_isspace(cs,*s); s++);
+
+ if (s == e)
+ {
+ goto noconv;
+ }
+
+ if (*s == '-')
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == '+')
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+#ifdef NOT_USED
+ if (base == 16 && s[0] == '0' && (s[1]=='X'|| s[1]=='x'))
+ s += 2;
+#endif
+
+#ifdef NOT_USED
+ if (base == 0)
+ {
+ if (*s == '0')
+ {
+ if (s[1]=='X' || s[1]=='x')
+ {
+ s += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+#endif
+
+ save = s;
+
+ cutoff = (~(ulonglong) 0) / (unsigned long int) base;
+ cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; s != e; c = *++s)
+ {
+ if (c>='0' && c<='9')
+ c -= '0';
+ else if (c>='A' && c<='F')
+ c = c - 'A' + 10;
+ else if (c>='a' && c<='f')
+ c = c - 'a' + 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (ulonglong) base;
+ i += c;
+ }
+ }
+
+ if (s == save)
+ goto noconv;
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (negative)
+ {
+ if (i > (ulonglong) LONGLONG_MIN)
+ overflow = 1;
+ }
+ else if (i > (ulonglong) LONGLONG_MAX)
+ overflow = 1;
+
+ if (overflow)
+ {
+ err[0]= ERANGE;
+ return negative ? LONGLONG_MIN : LONGLONG_MAX;
+ }
+
+ return (negative ? -((longlong) i) : (longlong) i);
+
+noconv:
+ err[0]= EDOM;
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return 0L;
+}
+
+
+ulonglong my_strntoull_8bit(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative;
+ register ulonglong cutoff;
+ register unsigned int cutlim;
+ register ulonglong i;
+ register const char *s, *e;
+ register unsigned char c;
+ const char *save;
+ int overflow;
+
+ *err= 0; /* Initialize error indicator */
+#ifdef NOT_USED
+ if (base < 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ s = nptr;
+ e = nptr+l;
+
+ for(; s<e && my_isspace(cs,*s); s++);
+
+ if (s == e)
+ {
+ goto noconv;
+ }
+
+ if (*s == '-')
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == '+')
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+#ifdef NOT_USED
+ if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
+ s += 2;
+#endif
+
+#ifdef NOT_USED
+ if (base == 0)
+ {
+ if (*s == '0')
+ {
+ if (s[1]=='X' || s[1]=='x')
+ {
+ s += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+#endif
+
+ save = s;
+
+ cutoff = (~(ulonglong) 0) / (unsigned long int) base;
+ cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; s != e; c = *++s)
+ {
+ if (c>='0' && c<='9')
+ c -= '0';
+ else if (c>='A' && c<='F')
+ c = c - 'A' + 10;
+ else if (c>='a' && c<='f')
+ c = c - 'a' + 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (ulonglong) base;
+ i += c;
+ }
+ }
+
+ if (s == save)
+ goto noconv;
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (overflow)
+ {
+ err[0]= ERANGE;
+ return (~(ulonglong) 0);
+ }
+
+ return (negative ? -((longlong) i) : (longlong) i);
+
+noconv:
+ err[0]= EDOM;
+ if (endptr != NULL)
+ *endptr = (char *) nptr;
+ return 0L;
+}
+
+/*
+ Read double from string
+
+ SYNOPSIS:
+ my_strntod_8bit()
+ cs Character set information
+ str String to convert to double
+ length Optional length for string.
+ end result pointer to end of converted string
+ err Error number if failed conversion
+
+ NOTES:
+ If length is not INT_MAX32 or str[length] != 0 then the given str must
+ be writeable
+ If length == INT_MAX32 the str must be \0 terminated.
+
+ It's implemented this way to save a buffer allocation and a memory copy.
+
+ RETURN
+ Value of number in string
+*/
+
+
+double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ char *str, uint length,
+ char **end, int *err)
+{
+ char end_char;
+ double result;
+
+ errno= 0; /* Safety */
+ if (length == INT_MAX32 || str[length] == 0)
+ result= strtod(str, end);
+ else
+ {
+ end_char= str[length];
+ str[length]= 0;
+ result= strtod(str, end);
+ str[length]= end_char; /* Restore end char */
+ }
+ *err= errno;
+ return result;
+}
+
+
+/*
+ This is a fast version optimized for the case of radix 10 / -10
+
+ Assume len >= 1
+*/
+
+int my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ char *dst, uint len, int radix, long int val)
+{
+ char buffer[66];
+ register char *p, *e;
+ long int new_val;
+ uint sign=0;
+
+ e = p = &buffer[sizeof(buffer)-1];
+ *p= 0;
+
+ if (radix < 0)
+ {
+ if (val < 0)
+ {
+ val= -val;
+ *dst++= '-';
+ len--;
+ sign= 1;
+ }
+ }
+
+ new_val = (long) ((unsigned long int) val / 10);
+ *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10);
+ val = new_val;
+
+ while (val != 0)
+ {
+ new_val=val/10;
+ *--p = '0' + (char) (val-new_val*10);
+ val= new_val;
+ }
+
+ len= min(len, (uint) (e-p));
+ memcpy(dst, p, len);
+ return (int) len+sign;
+}
+
+
+int my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ char *dst, uint len, int radix, longlong val)
+{
+ char buffer[65];
+ register char *p, *e;
+ long long_val;
+ uint sign= 0;
+
+ if (radix < 0)
+ {
+ if (val < 0)
+ {
+ val = -val;
+ *dst++= '-';
+ len--;
+ sign= 1;
+ }
+ }
+
+ e = p = &buffer[sizeof(buffer)-1];
+ *p= 0;
+
+ if (val == 0)
+ {
+ *--p= '0';
+ len= 1;
+ goto cnv;
+ }
+
+ while ((ulonglong) val > (ulonglong) LONG_MAX)
+ {
+ ulonglong quo=(ulonglong) val/(uint) 10;
+ uint rem= (uint) (val- quo* (uint) 10);
+ *--p = '0' + rem;
+ val= quo;
+ }
+
+ long_val= (long) val;
+ while (long_val != 0)
+ {
+ long quo= long_val/10;
+ *--p = '0' + (long_val - quo*10);
+ long_val= quo;
+ }
+
+ len= min(len, (uint) (e-p));
+cnv:
+ memcpy(dst, p, len);
+ return len+sign;
+}
+
+
+/*
+** Compare string against string with wildcard
+** 0 if matched
+** -1 if not matched with wildcard
+** 1 if matched with wildcard
+*/
+
+#ifdef LIKE_CMP_TOUPPER
+#define likeconv(s,A) (uchar) my_toupper(s,A)
+#else
+#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
+#endif
+
+#define INC_PTR(cs,A,B) A++
+
+
+int my_wildcmp_8bit(CHARSET_INFO *cs,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many)
+{
+ int result= -1; /* Not found, using wildcards */
+
+ while (wildstr != wildend)
+ {
+ while (*wildstr != w_many && *wildstr != w_one)
+ {
+ if (*wildstr == escape && wildstr+1 != wildend)
+ wildstr++;
+
+ if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
+ return(1); /* No match */
+ if (wildstr == wildend)
+ return (str != str_end); /* Match if both are at end */
+ result=1; /* Found an anchor char */
+ }
+ if (*wildstr == w_one)
+ {
+ do
+ {
+ if (str == str_end) /* Skip one char if possible */
+ return (result);
+ INC_PTR(cs,str,str_end);
+ } while (++wildstr < wildend && *wildstr == w_one);
+ if (wildstr == wildend)
+ break;
+ }
+ if (*wildstr == w_many)
+ { /* Found w_many */
+ uchar cmp;
+
+ wildstr++;
+ /* Remove any '%' and '_' from the wild search string */
+ for (; wildstr != wildend ; wildstr++)
+ {
+ if (*wildstr == w_many)
+ continue;
+ if (*wildstr == w_one)
+ {
+ if (str == str_end)
+ return (-1);
+ INC_PTR(cs,str,str_end);
+ continue;
+ }
+ break; /* Not a wild character */
+ }
+ if (wildstr == wildend)
+ return(0); /* Ok if w_many is last */
+ if (str == str_end)
+ return -1;
+
+ if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
+ cmp= *++wildstr;
+
+ INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
+ cmp=likeconv(cs,cmp);
+ do
+ {
+ while (str != str_end && likeconv(cs,*str) != cmp)
+ str++;
+ if (str++ == str_end) return (-1);
+ {
+ int tmp=my_wildcmp_8bit(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);
+ if (tmp <= 0)
+ return (tmp);
+ }
+ } while (str != str_end && wildstr[0] != w_many);
+ return(-1);
+ }
+ }
+ return (str != str_end ? 1 : 0);
+}
+
+
+/*
+** Calculate min_str and max_str that ranges a LIKE string.
+** Arguments:
+** ptr Pointer to LIKE string.
+** ptr_length Length of LIKE string.
+** escape Escape character in LIKE. (Normally '\').
+** All escape characters should be removed from min_str and max_str
+** res_length Length of min_str and max_str.
+** min_str Smallest case sensitive string that ranges LIKE.
+** Should be space padded to res_length.
+** max_str Largest case sensitive string that ranges LIKE.
+** Normally padded with the biggest character sort value.
+**
+** The function should return 0 if ok and 1 if the LIKE string can't be
+** optimized !
+*/
+
+my_bool my_like_range_simple(CHARSET_INFO *cs,
+ const char *ptr,uint ptr_length,
+ int escape, int w_one, int w_many,
+ uint res_length,
+ char *min_str,char *max_str,
+ uint *min_length,uint *max_length)
+{
+ const char *end=ptr+ptr_length;
+ char *min_org=min_str;
+ char *min_end=min_str+res_length;
+
+ for (; ptr != end && min_str != min_end ; ptr++)
+ {
+ if (*ptr == escape && ptr+1 != end)
+ {
+ ptr++; /* Skip escape */
+ *min_str++= *max_str++ = *ptr;
+ continue;
+ }
+ if (*ptr == w_one) /* '_' in SQL */
+ {
+ *min_str++='\0'; /* This should be min char */
+ *max_str++=cs->max_sort_char;
+ continue;
+ }
+ if (*ptr == w_many) /* '%' in SQL */
+ {
+ *min_length= (uint) (min_str - min_org);
+ *max_length=res_length;
+ do {
+ *min_str++ = ' '; /* Because if key compression */
+ *max_str++ = cs->max_sort_char;
+ } while (min_str != min_end);
+ return 0;
+ }
+ *min_str++= *max_str++ = *ptr;
+ }
+ *min_length= *max_length = (uint) (min_str - min_org);
+
+ /* Temporary fix for handling w_one at end of string (key compression) */
+ {
+ char *tmp;
+ for (tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
+ *--tmp=' ';
+ }
+
+ while (min_str != min_end)
+ *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ return 0;
+}
+
+
+ulong my_scan_8bit(CHARSET_INFO *cs, const char *str, const char *end, int sq)
+{
+ const char *str0= str;
+ switch (sq)
+ {
+ case MY_SEQ_INTTAIL:
+ if (*str == '.')
+ {
+ for(str++ ; str != end && *str == '0' ; str++);
+ return str-str0;
+ }
+ return 0;
+
+ case MY_SEQ_SPACES:
+ for ( ; str < end ; str++)
+ {
+ if (!my_isspace(cs,*str))
+ break;
+ }
+ return str-str0;
+ default:
+ return 0;
+ }
+}
+
+void my_fill_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ char *s, uint l, int fill)
+{
+ bfill(s,l,fill);
+}
+
+uint my_numchars_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b, const char *e)
+{
+ return e-b;
+}
+
+uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b __attribute__((unused)),
+ const char *e __attribute__((unused)),
+ uint pos)
+{
+ return pos;
+}
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 5d5f64cc5fe..a266fa71199 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -21,6 +21,9 @@
#include "m_string.h"
#include "m_ctype.h"
+#ifdef HAVE_CHARSET_sjis
+
+
/*
* This comment is parsed by configure to create ctype.c,
* so don't change it unless you know what you are doing.
@@ -29,7 +32,7 @@
* .configure. mbmaxlen_sjis=2
*/
-uchar NEAR ctype_sjis[257] =
+static uchar NEAR ctype_sjis[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -66,7 +69,7 @@ uchar NEAR ctype_sjis[257] =
0020, 0020, 0020, 0020, 0020, 0000, 0000, 0000
};
-uchar NEAR to_lower_sjis[]=
+static uchar NEAR to_lower_sjis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -102,7 +105,7 @@ uchar NEAR to_lower_sjis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-uchar NEAR to_upper_sjis[]=
+static uchar NEAR to_upper_sjis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -138,7 +141,7 @@ uchar NEAR to_upper_sjis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-uchar NEAR sort_order_sjis[]=
+static uchar NEAR sort_order_sjis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -180,17 +183,18 @@ uchar NEAR sort_order_sjis[]=
(0x80<=(c) && (c)<=0xfc))
-int ismbchar_sjis(const char* p, const char *e)
+static int ismbchar_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
{
return (issjishead((uchar) *p) && (e-p)>1 && issjistail((uchar)p[1]) ? 2: 0);
}
-my_bool ismbhead_sjis(uint c)
+static my_bool ismbhead_sjis(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return issjishead((uchar) c);
}
-int mbcharlen_sjis(uint c)
+static int mbcharlen_sjis(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (issjishead((uchar) c) ? 2: 0);
}
@@ -198,13 +202,15 @@ int mbcharlen_sjis(uint c)
#define sjiscode(c,d) ((((uint) (uchar)(c)) << 8) | (uint) (uchar) (d))
-int my_strnncoll_sjis(const uchar *s1, int len1, const uchar *s2, int len2)
+static int my_strnncoll_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *s1, uint len1,
+ const uchar *s2, uint len2)
{
const uchar *e1 = s1 + len1;
const uchar *e2 = s2 + len2;
while (s1 < e1 && s2 < e2) {
- if (ismbchar_sjis((char*) s1, (char*) e1) &&
- ismbchar_sjis((char*) s2, (char*) e2)) {
+ if (ismbchar_sjis(cs,(char*) s1, (char*) e1) &&
+ ismbchar_sjis(cs,(char*) s2, (char*) e2)) {
uint c1 = sjiscode(*s1, *(s1+1));
uint c2 = sjiscode(*s2, *(s2+1));
if (c1 != c2)
@@ -221,18 +227,24 @@ int my_strnncoll_sjis(const uchar *s1, int len1, const uchar *s2, int len2)
return len1 - len2;
}
-int my_strcoll_sjis(const uchar *s1, const uchar *s2)
+static
+int my_strnncollsp_sjis(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
{
- return (uint) my_strnncoll_sjis(s1,(uint) strlen((char*) s1),
- s2,(uint) strlen((char*) s2));
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_sjis(cs,s,slen,t,tlen);
}
-int my_strnxfrm_sjis(uchar *dest, const uchar *src, int len, int srclen)
+static int my_strnxfrm_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ uchar *dest, uint len,
+ const uchar *src, uint srclen)
{
uchar *d_end = dest + len;
uchar *s_end = (uchar*) src + srclen;
while (dest < d_end && src < s_end) {
- if (ismbchar_sjis((char*) src, (char*) s_end)) {
+ if (ismbchar_sjis(cs,(char*) src, (char*) s_end)) {
*dest++ = *src++;
if (dest < d_end && src < s_end)
*dest++ = *src++;
@@ -243,12 +255,6 @@ int my_strnxfrm_sjis(uchar *dest, const uchar *src, int len, int srclen)
return srclen;
}
-int my_strxfrm_sjis(uchar *dest, const uchar *src, int len)
-{
- return my_strnxfrm_sjis(dest, src, len, (uint) strlen((char*) src));
-}
-
-
/*
** Calculate min_str and max_str that ranges a LIKE string.
** Arguments:
@@ -267,19 +273,19 @@ int my_strxfrm_sjis(uchar *dest, const uchar *src, int len)
*/
#define max_sort_char ((char) 255)
-#define wild_one '_'
-#define wild_many '%'
-my_bool my_like_range_sjis(const char *ptr,uint ptr_length,pchar escape,
- uint res_length, char *min_str,char *max_str,
- uint *min_length,uint *max_length)
+static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ const char *ptr,uint ptr_length,
+ int escape, int w_one, int w_many,
+ uint res_length, char *min_str,char *max_str,
+ uint *min_length,uint *max_length)
{
const char *end=ptr+ptr_length;
char *min_org=min_str;
char *min_end=min_str+res_length;
while (ptr < end && min_str < min_end) {
- if (ismbchar_sjis(ptr, end)) {
+ if (ismbchar_sjis(cs, ptr, end)) {
*min_str++ = *max_str++ = *ptr++;
if (min_str < min_end)
*min_str++ = *max_str++ = *ptr++;
@@ -287,19 +293,19 @@ my_bool my_like_range_sjis(const char *ptr,uint ptr_length,pchar escape,
}
if (*ptr == escape && ptr+1 < end) {
ptr++; /* Skip escape */
- if (ismbchar_sjis(ptr, end))
+ if (ismbchar_sjis(cs, ptr, end))
*min_str++ = *max_str++ = *ptr++;
if (min_str < min_end)
*min_str++ = *max_str++ = *ptr++;
continue;
}
- if (*ptr == wild_one) { /* '_' in SQL */
+ if (*ptr == w_one) { /* '_' in SQL */
*min_str++ = '\0'; /* This should be min char */
*max_str++ = max_sort_char;
ptr++;
continue;
}
- if (*ptr == wild_many) { /* '%' in SQL */
+ if (*ptr == w_many) { /* '%' in SQL */
*min_length = (uint)(min_str - min_org);
*max_length = res_length;
do {
@@ -315,3 +321,4205 @@ my_bool my_like_range_sjis(const char *ptr,uint ptr_length,pchar escape,
*min_str++ = *max_str++ = ' '; /* Because if key compression */
return 0;
}
+
+/* page 0 0x00A1-0x00DF */
+static uint16 tab_sjis_uni0[]={
+0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,0xFF68,
+0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F,0xFF70,
+0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,0xFF78,
+0xFF79,0xFF7A,0xFF7B,0xFF7C,0xFF7D,0xFF7E,0xFF7F,0xFF80,
+0xFF81,0xFF82,0xFF83,0xFF84,0xFF85,0xFF86,0xFF87,0xFF88,
+0xFF89,0xFF8A,0xFF8B,0xFF8C,0xFF8D,0xFF8E,0xFF8F,0xFF90,
+0xFF91,0xFF92,0xFF93,0xFF94,0xFF95,0xFF96,0xFF97,0xFF98,
+0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F};
+
+/* page 1 0x8140-0x84BE */
+static uint16 tab_sjis_uni1[]={
+0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
+0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
+0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
+0x3005,0x3006,0x3007,0x30FC,0x2015,0x2010,0xFF0F,0x005C,
+0x301C,0x2016,0xFF5C,0x2026,0x2025,0x2018,0x2019,0x201C,
+0x201D,0xFF08,0xFF09,0x3014,0x3015,0xFF3B,0xFF3D,0xFF5B,
+0xFF5D,0x3008,0x3009,0x300A,0x300B,0x300C,0x300D,0x300E,
+0x300F,0x3010,0x3011,0xFF0B,0x2212,0x00B1,0x00D7, 0,
+0x00F7,0xFF1D,0x2260,0xFF1C,0xFF1E,0x2266,0x2267,0x221E,
+0x2234,0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFFE5,
+0xFF04,0x00A2,0x00A3,0xFF05,0xFF03,0xFF06,0xFF0A,0xFF20,
+0x00A7,0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7,0x25C6,
+0x25A1,0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x203B,0x3012,
+0x2192,0x2190,0x2191,0x2193,0x3013, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2208,0x220B,0x2286,0x2287,0x2282,0x2283,0x222A,0x2229,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2227,0x2228,0x00AC,0x21D2,0x21D4,0x2200,0x2203, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2220,0x22A5,0x2312,0x2202,0x2207,0x2261,
+0x2252,0x226A,0x226B,0x221A,0x223D,0x221D,0x2235,0x222B,
+0x222C, 0, 0, 0, 0, 0, 0, 0,
+0x212B,0x2030,0x266F,0x266D,0x266A,0x2020,0x2021,0x00B6,
+ 0, 0, 0, 0,0x25EF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xFF10,
+0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,
+0xFF19, 0, 0, 0, 0, 0, 0, 0,
+0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,
+0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,
+0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,
+0xFF39,0xFF3A, 0, 0, 0, 0, 0, 0,
+ 0,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,
+0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,
+0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,
+0xFF58,0xFF59,0xFF5A, 0, 0, 0, 0,0x3041,
+0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,0x3049,
+0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,0x3051,
+0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,
+0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,0x3061,
+0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,0x3069,
+0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,0x3071,
+0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,0x3079,
+0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,0x3081,
+0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,0x3089,
+0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,0x3091,
+0x3092,0x3093, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
+0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
+0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
+0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,
+0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,
+0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,
+0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,
+0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF, 0,
+0x30E0,0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,
+0x30E8,0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,
+0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x0391,
+0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,
+0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,0x03A1,
+0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x03B1,
+0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,0x03B9,
+0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,0x03C0,0x03C1,
+0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,0x0436,
+0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D, 0,
+0x043E,0x043F,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,
+0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,
+0x044E,0x044F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2500,
+0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,0x2524,
+0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,0x2517,
+0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,0x2528,
+0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542};
+
+/* page 2 0x889F-0x9FFC */
+static uint16 tab_sjis_uni2[]={
+0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
+0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
+0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
+0x59D0,0x867B,0x98F4,0x7D62,0x7DBE,0x9B8E,0x6216,0x7C9F,
+0x88B7,0x5B89,0x5EB5,0x6309,0x6697,0x6848,0x95C7,0x978D,
+0x674F,0x4EE5,0x4F0A,0x4F4D,0x4F9D,0x5049,0x56F2,0x5937,
+0x59D4,0x5A01,0x5C09,0x60DF,0x610F,0x6170,0x6613,0x6905,
+0x70BA,0x754F,0x7570,0x79FB,0x7DAD,0x7DEF,0x80C3,0x840E,
+0x8863,0x8B02,0x9055,0x907A,0x533B,0x4E95,0x4EA5,0x57DF,
+0x80B2,0x90C1,0x78EF,0x4E00,0x58F1,0x6EA2,0x9038,0x7A32,
+0x8328,0x828B,0x9C2F,0x5141,0x5370,0x54BD,0x54E1,0x56E0,
+0x59FB,0x5F15,0x98F2,0x6DEB,0x80E4,0x852D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9662,0x9670,0x96A0,0x97FB,0x540B,0x53F3,0x5B87,
+0x70CF,0x7FBD,0x8FC2,0x96E8,0x536F,0x9D5C,0x7ABA,0x4E11,
+0x7893,0x81FC,0x6E26,0x5618,0x5504,0x6B1D,0x851A,0x9C3B,
+0x59E5,0x53A9,0x6D66,0x74DC,0x958F,0x5642,0x4E91,0x904B,
+0x96F2,0x834F,0x990C,0x53E1,0x55B6,0x5B30,0x5F71,0x6620,
+0x66F3,0x6804,0x6C38,0x6CF3,0x6D29,0x745B,0x76C8,0x7A4E,
+0x9834,0x82F1,0x885B,0x8A60,0x92ED,0x6DB2,0x75AB,0x76CA,
+0x99C5,0x60A6,0x8B01,0x8D8A,0x95B2,0x698E,0x53AD,0x5186,
+ 0,0x5712,0x5830,0x5944,0x5BB4,0x5EF6,0x6028,0x63A9,
+0x63F4,0x6CBF,0x6F14,0x708E,0x7114,0x7159,0x71D5,0x733F,
+0x7E01,0x8276,0x82D1,0x8597,0x9060,0x925B,0x9D1B,0x5869,
+0x65BC,0x6C5A,0x7525,0x51F9,0x592E,0x5965,0x5F80,0x5FDC,
+0x62BC,0x65FA,0x6A2A,0x6B27,0x6BB4,0x738B,0x7FC1,0x8956,
+0x9D2C,0x9D0E,0x9EC4,0x5CA1,0x6C96,0x837B,0x5104,0x5C4B,
+0x61B6,0x81C6,0x6876,0x7261,0x4E59,0x4FFA,0x5378,0x6069,
+0x6E29,0x7A4F,0x97F3,0x4E0B,0x5316,0x4EEE,0x4F55,0x4F3D,
+0x4FA1,0x4F73,0x52A0,0x53EF,0x5609,0x590F,0x5AC1,0x5BB6,
+0x5BE1,0x79D1,0x6687,0x679C,0x67B6,0x6B4C,0x6CB3,0x706B,
+0x73C2,0x798D,0x79BE,0x7A3C,0x7B87,0x82B1,0x82DB,0x8304,
+0x8377,0x83EF,0x83D3,0x8766,0x8AB2,0x5629,0x8CA8,0x8FE6,
+0x904E,0x971E,0x868A,0x4FC4,0x5CE8,0x6211,0x7259,0x753B,
+0x81E5,0x82BD,0x86FE,0x8CC0,0x96C5,0x9913,0x99D5,0x4ECB,
+0x4F1A,0x89E3,0x56DE,0x584A,0x58CA,0x5EFB,0x5FEB,0x602A,
+0x6094,0x6062,0x61D0,0x6212,0x62D0,0x6539, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9B41,0x6666,0x68B0,0x6D77,0x7070,0x754C,0x7686,
+0x7D75,0x82A5,0x87F9,0x958B,0x968E,0x8C9D,0x51F1,0x52BE,
+0x5916,0x54B3,0x5BB3,0x5D16,0x6168,0x6982,0x6DAF,0x788D,
+0x84CB,0x8857,0x8A72,0x93A7,0x9AB8,0x6D6C,0x99A8,0x86D9,
+0x57A3,0x67FF,0x86CE,0x920E,0x5283,0x5687,0x5404,0x5ED3,
+0x62E1,0x64B9,0x683C,0x6838,0x6BBB,0x7372,0x78BA,0x7A6B,
+0x899A,0x89D2,0x8D6B,0x8F03,0x90ED,0x95A3,0x9694,0x9769,
+0x5B66,0x5CB3,0x697D,0x984D,0x984E,0x639B,0x7B20,0x6A2B,
+ 0,0x6A7F,0x68B6,0x9C0D,0x6F5F,0x5272,0x559D,0x6070,
+0x62EC,0x6D3B,0x6E07,0x6ED1,0x845B,0x8910,0x8F44,0x4E14,
+0x9C39,0x53F6,0x691B,0x6A3A,0x9784,0x682A,0x515C,0x7AC3,
+0x84B2,0x91DC,0x938C,0x565B,0x9D28,0x6822,0x8305,0x8431,
+0x7CA5,0x5208,0x82C5,0x74E6,0x4E7E,0x4F83,0x51A0,0x5BD2,
+0x520A,0x52D8,0x52E7,0x5DFB,0x559A,0x582A,0x59E6,0x5B8C,
+0x5B98,0x5BDB,0x5E72,0x5E79,0x60A3,0x611F,0x6163,0x61BE,
+0x63DB,0x6562,0x67D1,0x6853,0x68FA,0x6B3E,0x6B53,0x6C57,
+0x6F22,0x6F97,0x6F45,0x74B0,0x7518,0x76E3,0x770B,0x7AFF,
+0x7BA1,0x7C21,0x7DE9,0x7F36,0x7FF0,0x809D,0x8266,0x839E,
+0x89B3,0x8ACC,0x8CAB,0x9084,0x9451,0x9593,0x9591,0x95A2,
+0x9665,0x97D3,0x9928,0x8218,0x4E38,0x542B,0x5CB8,0x5DCC,
+0x73A9,0x764C,0x773C,0x5CA9,0x7FEB,0x8D0B,0x96C1,0x9811,
+0x9854,0x9858,0x4F01,0x4F0E,0x5371,0x559C,0x5668,0x57FA,
+0x5947,0x5B09,0x5BC4,0x5C90,0x5E0C,0x5E7E,0x5FCC,0x63EE,
+0x673A,0x65D7,0x65E2,0x671F,0x68CB,0x68C4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6A5F,0x5E30,0x6BC5,0x6C17,0x6C7D,0x757F,0x7948,
+0x5B63,0x7A00,0x7D00,0x5FBD,0x898F,0x8A18,0x8CB4,0x8D77,
+0x8ECC,0x8F1D,0x98E2,0x9A0E,0x9B3C,0x4E80,0x507D,0x5100,
+0x5993,0x5B9C,0x622F,0x6280,0x64EC,0x6B3A,0x72A0,0x7591,
+0x7947,0x7FA9,0x87FB,0x8ABC,0x8B70,0x63AC,0x83CA,0x97A0,
+0x5409,0x5403,0x55AB,0x6854,0x6A58,0x8A70,0x7827,0x6775,
+0x9ECD,0x5374,0x5BA2,0x811A,0x8650,0x9006,0x4E18,0x4E45,
+0x4EC7,0x4F11,0x53CA,0x5438,0x5BAE,0x5F13,0x6025,0x6551,
+ 0,0x673D,0x6C42,0x6C72,0x6CE3,0x7078,0x7403,0x7A76,
+0x7AAE,0x7B08,0x7D1A,0x7CFE,0x7D66,0x65E7,0x725B,0x53BB,
+0x5C45,0x5DE8,0x62D2,0x62E0,0x6319,0x6E20,0x865A,0x8A31,
+0x8DDD,0x92F8,0x6F01,0x79A6,0x9B5A,0x4EA8,0x4EAB,0x4EAC,
+0x4F9B,0x4FA0,0x50D1,0x5147,0x7AF6,0x5171,0x51F6,0x5354,
+0x5321,0x537F,0x53EB,0x55AC,0x5883,0x5CE1,0x5F37,0x5F4A,
+0x602F,0x6050,0x606D,0x631F,0x6559,0x6A4B,0x6CC1,0x72C2,
+0x72ED,0x77EF,0x80F8,0x8105,0x8208,0x854E,0x90F7,0x93E1,
+0x97FF,0x9957,0x9A5A,0x4EF0,0x51DD,0x5C2D,0x6681,0x696D,
+0x5C40,0x66F2,0x6975,0x7389,0x6850,0x7C81,0x50C5,0x52E4,
+0x5747,0x5DFE,0x9326,0x65A4,0x6B23,0x6B3D,0x7434,0x7981,
+0x79BD,0x7B4B,0x7DCA,0x82B9,0x83CC,0x887F,0x895F,0x8B39,
+0x8FD1,0x91D1,0x541F,0x9280,0x4E5D,0x5036,0x53E5,0x533A,
+0x72D7,0x7396,0x77E9,0x82E6,0x8EAF,0x99C6,0x99C8,0x99D2,
+0x5177,0x611A,0x865E,0x55B0,0x7A7A,0x5076,0x5BD3,0x9047,
+0x9685,0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6398,0x7A9F,0x6C93,0x9774,0x8F61,0x7AAA,0x718A,
+0x9688,0x7C82,0x6817,0x7E70,0x6851,0x936C,0x52F2,0x541B,
+0x85AB,0x8A13,0x7FA4,0x8ECD,0x90E1,0x5366,0x8888,0x7941,
+0x4FC2,0x50BE,0x5211,0x5144,0x5553,0x572D,0x73EA,0x578B,
+0x5951,0x5F62,0x5F84,0x6075,0x6176,0x6167,0x61A9,0x63B2,
+0x643A,0x656C,0x666F,0x6842,0x6E13,0x7566,0x7A3D,0x7CFB,
+0x7D4C,0x7D99,0x7E4B,0x7F6B,0x830E,0x834A,0x86CD,0x8A08,
+0x8A63,0x8B66,0x8EFD,0x981A,0x9D8F,0x82B8,0x8FCE,0x9BE8,
+ 0,0x5287,0x621F,0x6483,0x6FC0,0x9699,0x6841,0x5091,
+0x6B20,0x6C7A,0x6F54,0x7A74,0x7D50,0x8840,0x8A23,0x6708,
+0x4EF6,0x5039,0x5026,0x5065,0x517C,0x5238,0x5263,0x55A7,
+0x570F,0x5805,0x5ACC,0x5EFA,0x61B2,0x61F8,0x62F3,0x6372,
+0x691C,0x6A29,0x727D,0x72AC,0x732E,0x7814,0x786F,0x7D79,
+0x770C,0x80A9,0x898B,0x8B19,0x8CE2,0x8ED2,0x9063,0x9375,
+0x967A,0x9855,0x9A13,0x9E78,0x5143,0x539F,0x53B3,0x5E7B,
+0x5F26,0x6E1B,0x6E90,0x7384,0x73FE,0x7D43,0x8237,0x8A00,
+0x8AFA,0x9650,0x4E4E,0x500B,0x53E4,0x547C,0x56FA,0x59D1,
+0x5B64,0x5DF1,0x5EAB,0x5F27,0x6238,0x6545,0x67AF,0x6E56,
+0x72D0,0x7CCA,0x88B4,0x80A1,0x80E1,0x83F0,0x864E,0x8A87,
+0x8DE8,0x9237,0x96C7,0x9867,0x9F13,0x4E94,0x4E92,0x4F0D,
+0x5348,0x5449,0x543E,0x5A2F,0x5F8C,0x5FA1,0x609F,0x68A7,
+0x6A8E,0x745A,0x7881,0x8A9E,0x8AA4,0x8B77,0x9190,0x4E5E,
+0x9BC9,0x4EA4,0x4F7C,0x4FAF,0x5019,0x5016,0x5149,0x516C,
+0x529F,0x52B9,0x52FE,0x539A,0x53E3,0x5411, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x540E,0x5589,0x5751,0x57A2,0x597D,0x5B54,0x5B5D,
+0x5B8F,0x5DE5,0x5DE7,0x5DF7,0x5E78,0x5E83,0x5E9A,0x5EB7,
+0x5F18,0x6052,0x614C,0x6297,0x62D8,0x63A7,0x653B,0x6602,
+0x6643,0x66F4,0x676D,0x6821,0x6897,0x69CB,0x6C5F,0x6D2A,
+0x6D69,0x6E2F,0x6E9D,0x7532,0x7687,0x786C,0x7A3F,0x7CE0,
+0x7D05,0x7D18,0x7D5E,0x7DB1,0x8015,0x8003,0x80AF,0x80B1,
+0x8154,0x818F,0x822A,0x8352,0x884C,0x8861,0x8B1B,0x8CA2,
+0x8CFC,0x90CA,0x9175,0x9271,0x783F,0x92FC,0x95A4,0x964D,
+ 0,0x9805,0x9999,0x9AD8,0x9D3B,0x525B,0x52AB,0x53F7,
+0x5408,0x58D5,0x62F7,0x6FE0,0x8C6A,0x8F5F,0x9EB9,0x514B,
+0x523B,0x544A,0x56FD,0x7A40,0x9177,0x9D60,0x9ED2,0x7344,
+0x6F09,0x8170,0x7511,0x5FFD,0x60DA,0x9AA8,0x72DB,0x8FBC,
+0x6B64,0x9803,0x4ECA,0x56F0,0x5764,0x58BE,0x5A5A,0x6068,
+0x61C7,0x660F,0x6606,0x6839,0x68B1,0x6DF7,0x75D5,0x7D3A,
+0x826E,0x9B42,0x4E9B,0x4F50,0x53C9,0x5506,0x5D6F,0x5DE6,
+0x5DEE,0x67FB,0x6C99,0x7473,0x7802,0x8A50,0x9396,0x88DF,
+0x5750,0x5EA7,0x632B,0x50B5,0x50AC,0x518D,0x6700,0x54C9,
+0x585E,0x59BB,0x5BB0,0x5F69,0x624D,0x63A1,0x683D,0x6B73,
+0x6E08,0x707D,0x91C7,0x7280,0x7815,0x7826,0x796D,0x658E,
+0x7D30,0x83DC,0x88C1,0x8F09,0x969B,0x5264,0x5728,0x6750,
+0x7F6A,0x8CA1,0x51B4,0x5742,0x962A,0x583A,0x698A,0x80B4,
+0x54B2,0x5D0E,0x57FC,0x7895,0x9DFA,0x4F5C,0x524A,0x548B,
+0x643E,0x6628,0x6714,0x67F5,0x7A84,0x7B56,0x7D22,0x932F,
+0x685C,0x9BAD,0x7B39,0x5319,0x518A,0x5237, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5BDF,0x62F6,0x64AE,0x64E6,0x672D,0x6BBA,0x85A9,
+0x96D1,0x7690,0x9BD6,0x634C,0x9306,0x9BAB,0x76BF,0x6652,
+0x4E09,0x5098,0x53C2,0x5C71,0x60E8,0x6492,0x6563,0x685F,
+0x71E6,0x73CA,0x7523,0x7B97,0x7E82,0x8695,0x8B83,0x8CDB,
+0x9178,0x9910,0x65AC,0x66AB,0x6B8B,0x4ED5,0x4ED4,0x4F3A,
+0x4F7F,0x523A,0x53F8,0x53F2,0x55E3,0x56DB,0x58EB,0x59CB,
+0x59C9,0x59FF,0x5B50,0x5C4D,0x5E02,0x5E2B,0x5FD7,0x601D,
+0x6307,0x652F,0x5B5C,0x65AF,0x65BD,0x65E8,0x679D,0x6B62,
+ 0,0x6B7B,0x6C0F,0x7345,0x7949,0x79C1,0x7CF8,0x7D19,
+0x7D2B,0x80A2,0x8102,0x81F3,0x8996,0x8A5E,0x8A69,0x8A66,
+0x8A8C,0x8AEE,0x8CC7,0x8CDC,0x96CC,0x98FC,0x6B6F,0x4E8B,
+0x4F3C,0x4F8D,0x5150,0x5B57,0x5BFA,0x6148,0x6301,0x6642,
+0x6B21,0x6ECB,0x6CBB,0x723E,0x74BD,0x75D4,0x78C1,0x793A,
+0x800C,0x8033,0x81EA,0x8494,0x8F9E,0x6C50,0x9E7F,0x5F0F,
+0x8B58,0x9D2B,0x7AFA,0x8EF8,0x5B8D,0x96EB,0x4E03,0x53F1,
+0x57F7,0x5931,0x5AC9,0x5BA4,0x6089,0x6E7F,0x6F06,0x75BE,
+0x8CEA,0x5B9F,0x8500,0x7BE0,0x5072,0x67F4,0x829D,0x5C61,
+0x854A,0x7E1E,0x820E,0x5199,0x5C04,0x6368,0x8D66,0x659C,
+0x716E,0x793E,0x7D17,0x8005,0x8B1D,0x8ECA,0x906E,0x86C7,
+0x90AA,0x501F,0x52FA,0x5C3A,0x6753,0x707C,0x7235,0x914C,
+0x91C8,0x932B,0x82E5,0x5BC2,0x5F31,0x60F9,0x4E3B,0x53D6,
+0x5B88,0x624B,0x6731,0x6B8A,0x72E9,0x73E0,0x7A2E,0x816B,
+0x8DA3,0x9152,0x9996,0x5112,0x53D7,0x546A,0x5BFF,0x6388,
+0x6A39,0x7DAC,0x9700,0x56DA,0x53CE,0x5468, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B97,0x5C31,0x5DDE,0x4FEE,0x6101,0x62FE,0x6D32,
+0x79C0,0x79CB,0x7D42,0x7E4D,0x7FD2,0x81ED,0x821F,0x8490,
+0x8846,0x8972,0x8B90,0x8E74,0x8F2F,0x9031,0x914B,0x916C,
+0x96C6,0x919C,0x4EC0,0x4F4F,0x5145,0x5341,0x5F93,0x620E,
+0x67D4,0x6C41,0x6E0B,0x7363,0x7E26,0x91CD,0x9283,0x53D4,
+0x5919,0x5BBF,0x6DD1,0x795D,0x7E2E,0x7C9B,0x587E,0x719F,
+0x51FA,0x8853,0x8FF0,0x4FCA,0x5CFB,0x6625,0x77AC,0x7AE3,
+0x821C,0x99FF,0x51C6,0x5FAA,0x65EC,0x696F,0x6B89,0x6DF3,
+ 0,0x6E96,0x6F64,0x76FE,0x7D14,0x5DE1,0x9075,0x9187,
+0x9806,0x51E6,0x521D,0x6240,0x6691,0x66D9,0x6E1A,0x5EB6,
+0x7DD2,0x7F72,0x66F8,0x85AF,0x85F7,0x8AF8,0x52A9,0x53D9,
+0x5973,0x5E8F,0x5F90,0x6055,0x92E4,0x9664,0x50B7,0x511F,
+0x52DD,0x5320,0x5347,0x53EC,0x54E8,0x5546,0x5531,0x5617,
+0x5968,0x59BE,0x5A3C,0x5BB5,0x5C06,0x5C0F,0x5C11,0x5C1A,
+0x5E84,0x5E8A,0x5EE0,0x5F70,0x627F,0x6284,0x62DB,0x638C,
+0x6377,0x6607,0x660C,0x662D,0x6676,0x677E,0x68A2,0x6A1F,
+0x6A35,0x6CBC,0x6D88,0x6E09,0x6E58,0x713C,0x7126,0x7167,
+0x75C7,0x7701,0x785D,0x7901,0x7965,0x79F0,0x7AE0,0x7B11,
+0x7CA7,0x7D39,0x8096,0x83D6,0x848B,0x8549,0x885D,0x88F3,
+0x8A1F,0x8A3C,0x8A54,0x8A73,0x8C61,0x8CDE,0x91A4,0x9266,
+0x937E,0x9418,0x969C,0x9798,0x4E0A,0x4E08,0x4E1E,0x4E57,
+0x5197,0x5270,0x57CE,0x5834,0x58CC,0x5B22,0x5E38,0x60C5,
+0x64FE,0x6761,0x6756,0x6D44,0x72B6,0x7573,0x7A63,0x84B8,
+0x8B72,0x91B8,0x9320,0x5631,0x57F4,0x98FE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x62ED,0x690D,0x6B96,0x71ED,0x7E54,0x8077,0x8272,
+0x89E6,0x98DF,0x8755,0x8FB1,0x5C3B,0x4F38,0x4FE1,0x4FB5,
+0x5507,0x5A20,0x5BDD,0x5BE9,0x5FC3,0x614E,0x632F,0x65B0,
+0x664B,0x68EE,0x699B,0x6D78,0x6DF1,0x7533,0x75B9,0x771F,
+0x795E,0x79E6,0x7D33,0x81E3,0x82AF,0x85AA,0x89AA,0x8A3A,
+0x8EAB,0x8F9B,0x9032,0x91DD,0x9707,0x4EBA,0x4EC1,0x5203,
+0x5875,0x58EC,0x5C0B,0x751A,0x5C3D,0x814E,0x8A0A,0x8FC5,
+0x9663,0x976D,0x7B25,0x8ACF,0x9808,0x9162,0x56F3,0x53A8,
+ 0,0x9017,0x5439,0x5782,0x5E25,0x63A8,0x6C34,0x708A,
+0x7761,0x7C8B,0x7FE0,0x8870,0x9042,0x9154,0x9310,0x9318,
+0x968F,0x745E,0x9AC4,0x5D07,0x5D69,0x6570,0x67A2,0x8DA8,
+0x96DB,0x636E,0x6749,0x6919,0x83C5,0x9817,0x96C0,0x88FE,
+0x6F84,0x647A,0x5BF8,0x4E16,0x702C,0x755D,0x662F,0x51C4,
+0x5236,0x52E2,0x59D3,0x5F81,0x6027,0x6210,0x653F,0x6574,
+0x661F,0x6674,0x68F2,0x6816,0x6B63,0x6E05,0x7272,0x751F,
+0x76DB,0x7CBE,0x8056,0x58F0,0x88FD,0x897F,0x8AA0,0x8A93,
+0x8ACB,0x901D,0x9192,0x9752,0x9759,0x6589,0x7A0E,0x8106,
+0x96BB,0x5E2D,0x60DC,0x621A,0x65A5,0x6614,0x6790,0x77F3,
+0x7A4D,0x7C4D,0x7E3E,0x810A,0x8CAC,0x8D64,0x8DE1,0x8E5F,
+0x78A9,0x5207,0x62D9,0x63A5,0x6442,0x6298,0x8A2D,0x7A83,
+0x7BC0,0x8AAC,0x96EA,0x7D76,0x820C,0x8749,0x4ED9,0x5148,
+0x5343,0x5360,0x5BA3,0x5C02,0x5C16,0x5DDD,0x6226,0x6247,
+0x64B0,0x6813,0x6834,0x6CC9,0x6D45,0x6D17,0x67D3,0x6F5C,
+0x714E,0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7E4A,0x7FA8,0x817A,0x821B,0x8239,0x85A6,0x8A6E,
+0x8CCE,0x8DF5,0x9078,0x9077,0x92AD,0x9291,0x9583,0x9BAE,
+0x524D,0x5584,0x6F38,0x7136,0x5168,0x7985,0x7E55,0x81B3,
+0x7CCE,0x564C,0x5851,0x5CA8,0x63AA,0x66FE,0x66FD,0x695A,
+0x72D9,0x758F,0x758E,0x790E,0x7956,0x79DF,0x7C97,0x7D20,
+0x7D44,0x8607,0x8A34,0x963B,0x9061,0x9F20,0x50E7,0x5275,
+0x53CC,0x53E2,0x5009,0x55AA,0x58EE,0x594F,0x723D,0x5B8B,
+0x5C64,0x531D,0x60E3,0x60F3,0x635C,0x6383,0x633F,0x63BB,
+ 0,0x64CD,0x65E9,0x66F9,0x5DE3,0x69CD,0x69FD,0x6F15,
+0x71E5,0x4E89,0x75E9,0x76F8,0x7A93,0x7CDF,0x7DCF,0x7D9C,
+0x8061,0x8349,0x8358,0x846C,0x84BC,0x85FB,0x88C5,0x8D70,
+0x9001,0x906D,0x9397,0x971C,0x9A12,0x50CF,0x5897,0x618E,
+0x81D3,0x8535,0x8D08,0x9020,0x4FC3,0x5074,0x5247,0x5373,
+0x606F,0x6349,0x675F,0x6E2C,0x8DB3,0x901F,0x4FD7,0x5C5E,
+0x8CCA,0x65CF,0x7D9A,0x5352,0x8896,0x5176,0x63C3,0x5B58,
+0x5B6B,0x5C0A,0x640D,0x6751,0x905C,0x4ED6,0x591A,0x592A,
+0x6C70,0x8A51,0x553E,0x5815,0x59A5,0x60F0,0x6253,0x67C1,
+0x8235,0x6955,0x9640,0x99C4,0x9A28,0x4F53,0x5806,0x5BFE,
+0x8010,0x5CB1,0x5E2F,0x5F85,0x6020,0x614B,0x6234,0x66FF,
+0x6CF0,0x6EDE,0x80CE,0x817F,0x82D4,0x888B,0x8CB8,0x9000,
+0x902E,0x968A,0x9EDB,0x9BDB,0x4EE3,0x53F0,0x5927,0x7B2C,
+0x918D,0x984C,0x9DF9,0x6EDD,0x7027,0x5353,0x5544,0x5B85,
+0x6258,0x629E,0x62D3,0x6CA2,0x6FEF,0x7422,0x8A17,0x9438,
+0x6FC1,0x8AFE,0x8338,0x51E7,0x86F8,0x53EA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x53E9,0x4F46,0x9054,0x8FB0,0x596A,0x8131,0x5DFD,
+0x7AEA,0x8FBF,0x68DA,0x8C37,0x72F8,0x9C48,0x6A3D,0x8AB0,
+0x4E39,0x5358,0x5606,0x5766,0x62C5,0x63A2,0x65E6,0x6B4E,
+0x6DE1,0x6E5B,0x70AD,0x77ED,0x7AEF,0x7BAA,0x7DBB,0x803D,
+0x80C6,0x86CB,0x8A95,0x935B,0x56E3,0x58C7,0x5F3E,0x65AD,
+0x6696,0x6A80,0x6BB5,0x7537,0x8AC7,0x5024,0x77E5,0x5730,
+0x5F1B,0x6065,0x667A,0x6C60,0x75F4,0x7A1A,0x7F6E,0x81F4,
+0x8718,0x9045,0x99B3,0x7BC9,0x755C,0x7AF9,0x7B51,0x84C4,
+ 0,0x9010,0x79E9,0x7A92,0x8336,0x5AE1,0x7740,0x4E2D,
+0x4EF2,0x5B99,0x5FE0,0x62BD,0x663C,0x67F1,0x6CE8,0x866B,
+0x8877,0x8A3B,0x914E,0x92F3,0x99D0,0x6A17,0x7026,0x732A,
+0x82E7,0x8457,0x8CAF,0x4E01,0x5146,0x51CB,0x558B,0x5BF5,
+0x5E16,0x5E33,0x5E81,0x5F14,0x5F35,0x5F6B,0x5FB4,0x61F2,
+0x6311,0x66A2,0x671D,0x6F6E,0x7252,0x753A,0x773A,0x8074,
+0x8139,0x8178,0x8776,0x8ABF,0x8ADC,0x8D85,0x8DF3,0x929A,
+0x9577,0x9802,0x9CE5,0x52C5,0x6357,0x76F4,0x6715,0x6C88,
+0x73CD,0x8CC3,0x93AE,0x9673,0x6D25,0x589C,0x690E,0x69CC,
+0x8FFD,0x939A,0x75DB,0x901A,0x585A,0x6802,0x63B4,0x69FB,
+0x4F43,0x6F2C,0x67D8,0x8FBB,0x8526,0x7DB4,0x9354,0x693F,
+0x6F70,0x576A,0x58F7,0x5B2C,0x7D2C,0x722A,0x540A,0x91E3,
+0x9DB4,0x4EAD,0x4F4E,0x505C,0x5075,0x5243,0x8C9E,0x5448,
+0x5824,0x5B9A,0x5E1D,0x5E95,0x5EAD,0x5EF7,0x5F1F,0x608C,
+0x62B5,0x633A,0x63D0,0x68AF,0x6C40,0x7887,0x798E,0x7A0B,
+0x7DE0,0x8247,0x8A02,0x8AE6,0x8E44,0x9013, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x90B8,0x912D,0x91D8,0x9F0E,0x6CE5,0x6458,0x64E2,
+0x6575,0x6EF4,0x7684,0x7B1B,0x9069,0x93D1,0x6EBA,0x54F2,
+0x5FB9,0x64A4,0x8F4D,0x8FED,0x9244,0x5178,0x586B,0x5929,
+0x5C55,0x5E97,0x6DFB,0x7E8F,0x751C,0x8CBC,0x8EE2,0x985B,
+0x70B9,0x4F1D,0x6BBF,0x6FB1,0x7530,0x96FB,0x514E,0x5410,
+0x5835,0x5857,0x59AC,0x5C60,0x5F92,0x6597,0x675C,0x6E21,
+0x767B,0x83DF,0x8CED,0x9014,0x90FD,0x934D,0x7825,0x783A,
+0x52AA,0x5EA6,0x571F,0x5974,0x6012,0x5012,0x515A,0x51AC,
+ 0,0x51CD,0x5200,0x5510,0x5854,0x5858,0x5957,0x5B95,
+0x5CF6,0x5D8B,0x60BC,0x6295,0x642D,0x6771,0x6843,0x68BC,
+0x68DF,0x76D7,0x6DD8,0x6E6F,0x6D9B,0x706F,0x71C8,0x5F53,
+0x75D8,0x7977,0x7B49,0x7B54,0x7B52,0x7CD6,0x7D71,0x5230,
+0x8463,0x8569,0x85E4,0x8A0E,0x8B04,0x8C46,0x8E0F,0x9003,
+0x900F,0x9419,0x9676,0x982D,0x9A30,0x95D8,0x50CD,0x52D5,
+0x540C,0x5802,0x5C0E,0x61A7,0x649E,0x6D1E,0x77B3,0x7AE5,
+0x80F4,0x8404,0x9053,0x9285,0x5CE0,0x9D07,0x533F,0x5F97,
+0x5FB3,0x6D9C,0x7279,0x7763,0x79BF,0x7BE4,0x6BD2,0x72EC,
+0x8AAD,0x6803,0x6A61,0x51F8,0x7A81,0x6934,0x5C4A,0x9CF6,
+0x82EB,0x5BC5,0x9149,0x701E,0x5678,0x5C6F,0x60C7,0x6566,
+0x6C8C,0x8C5A,0x9041,0x9813,0x5451,0x66C7,0x920D,0x5948,
+0x90A3,0x5185,0x4E4D,0x51EA,0x8599,0x8B0E,0x7058,0x637A,
+0x934B,0x6962,0x99B4,0x7E04,0x7577,0x5357,0x6960,0x8EDF,
+0x96E3,0x6C5D,0x4E8C,0x5C3C,0x5F10,0x8FE9,0x5302,0x8CD1,
+0x8089,0x8679,0x5EFF,0x65E5,0x4E73,0x5165, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5982,0x5C3F,0x97EE,0x4EFB,0x598A,0x5FCD,0x8A8D,
+0x6FE1,0x79B0,0x7962,0x5BE7,0x8471,0x732B,0x71B1,0x5E74,
+0x5FF5,0x637B,0x649A,0x71C3,0x7C98,0x4E43,0x5EFC,0x4E4B,
+0x57DC,0x56A2,0x60A9,0x6FC3,0x7D0D,0x80FD,0x8133,0x81BF,
+0x8FB2,0x8997,0x86A4,0x5DF4,0x628A,0x64AD,0x8987,0x6777,
+0x6CE2,0x6D3E,0x7436,0x7834,0x5A46,0x7F75,0x82AD,0x99AC,
+0x4FF3,0x5EC3,0x62DD,0x6392,0x6557,0x676F,0x76C3,0x724C,
+0x80CC,0x80BA,0x8F29,0x914D,0x500D,0x57F9,0x5A92,0x6885,
+ 0,0x6973,0x7164,0x72FD,0x8CB7,0x58F2,0x8CE0,0x966A,
+0x9019,0x877F,0x79E4,0x77E7,0x8429,0x4F2F,0x5265,0x535A,
+0x62CD,0x67CF,0x6CCA,0x767D,0x7B94,0x7C95,0x8236,0x8584,
+0x8FEB,0x66DD,0x6F20,0x7206,0x7E1B,0x83AB,0x99C1,0x9EA6,
+0x51FD,0x7BB1,0x7872,0x7BB8,0x8087,0x7B48,0x6AE8,0x5E61,
+0x808C,0x7551,0x7560,0x516B,0x9262,0x6E8C,0x767A,0x9197,
+0x9AEA,0x4F10,0x7F70,0x629C,0x7B4F,0x95A5,0x9CE9,0x567A,
+0x5859,0x86E4,0x96BC,0x4F34,0x5224,0x534A,0x53CD,0x53DB,
+0x5E06,0x642C,0x6591,0x677F,0x6C3E,0x6C4E,0x7248,0x72AF,
+0x73ED,0x7554,0x7E41,0x822C,0x85E9,0x8CA9,0x7BC4,0x91C6,
+0x7169,0x9812,0x98EF,0x633D,0x6669,0x756A,0x76E4,0x78D0,
+0x8543,0x86EE,0x532A,0x5351,0x5426,0x5983,0x5E87,0x5F7C,
+0x60B2,0x6249,0x6279,0x62AB,0x6590,0x6BD4,0x6CCC,0x75B2,
+0x76AE,0x7891,0x79D8,0x7DCB,0x7F77,0x80A5,0x88AB,0x8AB9,
+0x8CBB,0x907F,0x975E,0x98DB,0x6A0B,0x7C38,0x5099,0x5C3E,
+0x5FAE,0x6787,0x6BD8,0x7435,0x7709,0x7F8E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9F3B,0x67CA,0x7A17,0x5339,0x758B,0x9AED,0x5F66,
+0x819D,0x83F1,0x8098,0x5F3C,0x5FC5,0x7562,0x7B46,0x903C,
+0x6867,0x59EB,0x5A9B,0x7D10,0x767E,0x8B2C,0x4FF5,0x5F6A,
+0x6A19,0x6C37,0x6F02,0x74E2,0x7968,0x8868,0x8A55,0x8C79,
+0x5EDF,0x63CF,0x75C5,0x79D2,0x82D7,0x9328,0x92F2,0x849C,
+0x86ED,0x9C2D,0x54C1,0x5F6C,0x658C,0x6D5C,0x7015,0x8CA7,
+0x8CD3,0x983B,0x654F,0x74F6,0x4E0D,0x4ED8,0x57E0,0x592B,
+0x5A66,0x5BCC,0x51A8,0x5E03,0x5E9C,0x6016,0x6276,0x6577,
+ 0,0x65A7,0x666E,0x6D6E,0x7236,0x7B26,0x8150,0x819A,
+0x8299,0x8B5C,0x8CA0,0x8CE6,0x8D74,0x961C,0x9644,0x4FAE,
+0x64AB,0x6B66,0x821E,0x8461,0x856A,0x90E8,0x5C01,0x6953,
+0x98A8,0x847A,0x8557,0x4F0F,0x526F,0x5FA9,0x5E45,0x670D,
+0x798F,0x8179,0x8907,0x8986,0x6DF5,0x5F17,0x6255,0x6CB8,
+0x4ECF,0x7269,0x9B92,0x5206,0x543B,0x5674,0x58B3,0x61A4,
+0x626E,0x711A,0x596E,0x7C89,0x7CDE,0x7D1B,0x96F0,0x6587,
+0x805E,0x4E19,0x4F75,0x5175,0x5840,0x5E63,0x5E73,0x5F0A,
+0x67C4,0x4E26,0x853D,0x9589,0x965B,0x7C73,0x9801,0x50FB,
+0x58C1,0x7656,0x78A7,0x5225,0x77A5,0x8511,0x7B86,0x504F,
+0x5909,0x7247,0x7BC7,0x7DE8,0x8FBA,0x8FD4,0x904D,0x4FBF,
+0x52C9,0x5A29,0x5F01,0x97AD,0x4FDD,0x8217,0x92EA,0x5703,
+0x6355,0x6B69,0x752B,0x88DC,0x8F14,0x7A42,0x52DF,0x5893,
+0x6155,0x620A,0x66AE,0x6BCD,0x7C3F,0x83E9,0x5023,0x4FF8,
+0x5305,0x5446,0x5831,0x5949,0x5B9D,0x5CF0,0x5CEF,0x5D29,
+0x5E96,0x62B1,0x6367,0x653E,0x65B9,0x670B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6CD5,0x6CE1,0x70F9,0x7832,0x7E2B,0x80DE,0x82B3,
+0x840C,0x84EC,0x8702,0x8912,0x8A2A,0x8C4A,0x90A6,0x92D2,
+0x98FD,0x9CF3,0x9D6C,0x4E4F,0x4EA1,0x508D,0x5256,0x574A,
+0x59A8,0x5E3D,0x5FD8,0x5FD9,0x623F,0x66B4,0x671B,0x67D0,
+0x68D2,0x5192,0x7D21,0x80AA,0x81A8,0x8B00,0x8C8C,0x8CBF,
+0x927E,0x9632,0x5420,0x982C,0x5317,0x50D5,0x535C,0x58A8,
+0x64B2,0x6734,0x7267,0x7766,0x7A46,0x91E6,0x52C3,0x6CA1,
+0x6B86,0x5800,0x5E4C,0x5954,0x672C,0x7FFB,0x51E1,0x76C6,
+ 0,0x6469,0x78E8,0x9B54,0x9EBB,0x57CB,0x59B9,0x6627,
+0x679A,0x6BCE,0x54E9,0x69D9,0x5E55,0x819C,0x6795,0x9BAA,
+0x67FE,0x9C52,0x685D,0x4EA6,0x4FE3,0x53C8,0x62B9,0x672B,
+0x6CAB,0x8FC4,0x4FAD,0x7E6D,0x9EBF,0x4E07,0x6162,0x6E80,
+0x6F2B,0x8513,0x5473,0x672A,0x9B45,0x5DF3,0x7B95,0x5CAC,
+0x5BC6,0x871C,0x6E4A,0x84D1,0x7A14,0x8108,0x5999,0x7C8D,
+0x6C11,0x7720,0x52D9,0x5922,0x7121,0x725F,0x77DB,0x9727,
+0x9D61,0x690B,0x5A7F,0x5A18,0x51A5,0x540D,0x547D,0x660E,
+0x76DF,0x8FF7,0x9298,0x9CF4,0x59EA,0x725D,0x6EC5,0x514D,
+0x68C9,0x7DBF,0x7DEC,0x9762,0x9EBA,0x6478,0x6A21,0x8302,
+0x5984,0x5B5F,0x6BDB,0x731B,0x76F2,0x7DB2,0x8017,0x8499,
+0x5132,0x6728,0x9ED9,0x76EE,0x6762,0x52FF,0x9905,0x5C24,
+0x623B,0x7C7E,0x8CB0,0x554F,0x60B6,0x7D0B,0x9580,0x5301,
+0x4E5F,0x51B6,0x591C,0x723A,0x8036,0x91CE,0x5F25,0x77E2,
+0x5384,0x5F79,0x7D04,0x85AC,0x8A33,0x8E8D,0x9756,0x67F3,
+0x85AE,0x9453,0x6109,0x6108,0x6CB9,0x7652, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8AED,0x8F38,0x552F,0x4F51,0x512A,0x52C7,0x53CB,
+0x5BA5,0x5E7D,0x60A0,0x6182,0x63D6,0x6709,0x67DA,0x6E67,
+0x6D8C,0x7336,0x7337,0x7531,0x7950,0x88D5,0x8A98,0x904A,
+0x9091,0x90F5,0x96C4,0x878D,0x5915,0x4E88,0x4F59,0x4E0E,
+0x8A89,0x8F3F,0x9810,0x50AD,0x5E7C,0x5996,0x5BB9,0x5EB8,
+0x63DA,0x63FA,0x64C1,0x66DC,0x694A,0x69D8,0x6D0B,0x6EB6,
+0x7194,0x7528,0x7AAF,0x7F8A,0x8000,0x8449,0x84C9,0x8981,
+0x8B21,0x8E0A,0x9065,0x967D,0x990A,0x617E,0x6291,0x6B32,
+ 0,0x6C83,0x6D74,0x7FCC,0x7FFC,0x6DC0,0x7F85,0x87BA,
+0x88F8,0x6765,0x83B1,0x983C,0x96F7,0x6D1B,0x7D61,0x843D,
+0x916A,0x4E71,0x5375,0x5D50,0x6B04,0x6FEB,0x85CD,0x862D,
+0x89A7,0x5229,0x540F,0x5C65,0x674E,0x68A8,0x7406,0x7483,
+0x75E2,0x88CF,0x88E1,0x91CC,0x96E2,0x9678,0x5F8B,0x7387,
+0x7ACB,0x844E,0x63A0,0x7565,0x5289,0x6D41,0x6E9C,0x7409,
+0x7559,0x786B,0x7C92,0x9686,0x7ADC,0x9F8D,0x4FB6,0x616E,
+0x65C5,0x865C,0x4E86,0x4EAE,0x50DA,0x4E21,0x51CC,0x5BEE,
+0x6599,0x6881,0x6DBC,0x731F,0x7642,0x77AD,0x7A1C,0x7CE7,
+0x826F,0x8AD2,0x907C,0x91CF,0x9675,0x9818,0x529B,0x7DD1,
+0x502B,0x5398,0x6797,0x6DCB,0x71D0,0x7433,0x81E8,0x8F2A,
+0x96A3,0x9C57,0x9E9F,0x7460,0x5841,0x6D99,0x7D2F,0x985E,
+0x4EE4,0x4F36,0x4F8B,0x51B7,0x52B1,0x5DBA,0x601C,0x73B2,
+0x793C,0x82D3,0x9234,0x96B7,0x96F6,0x970A,0x9E97,0x9F62,
+0x66A6,0x6B74,0x5217,0x52A3,0x70C8,0x88C2,0x5EC9,0x604B,
+0x6190,0x6F23,0x7149,0x7C3E,0x7DF4,0x806F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x84EE,0x9023,0x932C,0x5442,0x9B6F,0x6AD3,0x7089,
+0x8CC2,0x8DEF,0x9732,0x52B4,0x5A41,0x5ECA,0x5F04,0x6717,
+0x697C,0x6994,0x6D6A,0x6F0F,0x7262,0x72FC,0x7BED,0x8001,
+0x807E,0x874B,0x90CE,0x516D,0x9E93,0x7984,0x808B,0x9332,
+0x8AD6,0x502D,0x548C,0x8A71,0x6B6A,0x8CC4,0x8107,0x60D1,
+0x67A0,0x9DF2,0x4E99,0x4E98,0x9C10,0x8A6B,0x85C1,0x8568,
+0x6900,0x6E7E,0x7897,0x8155, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F0C,0x4E10,0x4E15,0x4E2A,0x4E31,0x4E36,0x4E3C,0x4E3F,
+0x4E42,0x4E56,0x4E58,0x4E82,0x4E85,0x8C6B,0x4E8A,0x8212,
+0x5F0D,0x4E8E,0x4E9E,0x4E9F,0x4EA0,0x4EA2,0x4EB0,0x4EB3,
+0x4EB6,0x4ECE,0x4ECD,0x4EC4,0x4EC6,0x4EC2,0x4ED7,0x4EDE,
+0x4EED,0x4EDF,0x4EF7,0x4F09,0x4F5A,0x4F30,0x4F5B,0x4F5D,
+0x4F57,0x4F47,0x4F76,0x4F88,0x4F8F,0x4F98,0x4F7B,0x4F69,
+0x4F70,0x4F91,0x4F6F,0x4F86,0x4F96,0x5118,0x4FD4,0x4FDF,
+0x4FCE,0x4FD8,0x4FDB,0x4FD1,0x4FDA,0x4FD0,0x4FE4,0x4FE5,
+0x501A,0x5028,0x5014,0x502A,0x5025,0x5005,0x4F1C,0x4FF6,
+0x5021,0x5029,0x502C,0x4FFE,0x4FEF,0x5011,0x5006,0x5043,
+0x5047,0x6703,0x5055,0x5050,0x5048,0x505A,0x5056,0x506C,
+0x5078,0x5080,0x509A,0x5085,0x50B4,0x50B2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x50C9,0x50CA,0x50B3,0x50C2,0x50D6,0x50DE,0x50E5,
+0x50ED,0x50E3,0x50EE,0x50F9,0x50F5,0x5109,0x5101,0x5102,
+0x5116,0x5115,0x5114,0x511A,0x5121,0x513A,0x5137,0x513C,
+0x513B,0x513F,0x5140,0x5152,0x514C,0x5154,0x5162,0x7AF8,
+0x5169,0x516A,0x516E,0x5180,0x5182,0x56D8,0x518C,0x5189,
+0x518F,0x5191,0x5193,0x5195,0x5196,0x51A4,0x51A6,0x51A2,
+0x51A9,0x51AA,0x51AB,0x51B3,0x51B1,0x51B2,0x51B0,0x51B5,
+0x51BD,0x51C5,0x51C9,0x51DB,0x51E0,0x8655,0x51E9,0x51ED,
+ 0,0x51F0,0x51F5,0x51FE,0x5204,0x520B,0x5214,0x520E,
+0x5227,0x522A,0x522E,0x5233,0x5239,0x524F,0x5244,0x524B,
+0x524C,0x525E,0x5254,0x526A,0x5274,0x5269,0x5273,0x527F,
+0x527D,0x528D,0x5294,0x5292,0x5271,0x5288,0x5291,0x8FA8,
+0x8FA7,0x52AC,0x52AD,0x52BC,0x52B5,0x52C1,0x52CD,0x52D7,
+0x52DE,0x52E3,0x52E6,0x98ED,0x52E0,0x52F3,0x52F5,0x52F8,
+0x52F9,0x5306,0x5308,0x7538,0x530D,0x5310,0x530F,0x5315,
+0x531A,0x5323,0x532F,0x5331,0x5333,0x5338,0x5340,0x5346,
+0x5345,0x4E17,0x5349,0x534D,0x51D6,0x535E,0x5369,0x536E,
+0x5918,0x537B,0x5377,0x5382,0x5396,0x53A0,0x53A6,0x53A5,
+0x53AE,0x53B0,0x53B6,0x53C3,0x7C12,0x96D9,0x53DF,0x66FC,
+0x71EE,0x53EE,0x53E8,0x53ED,0x53FA,0x5401,0x543D,0x5440,
+0x542C,0x542D,0x543C,0x542E,0x5436,0x5429,0x541D,0x544E,
+0x548F,0x5475,0x548E,0x545F,0x5471,0x5477,0x5470,0x5492,
+0x547B,0x5480,0x5476,0x5484,0x5490,0x5486,0x54C7,0x54A2,
+0x54B8,0x54A5,0x54AC,0x54C4,0x54C8,0x54A8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x54AB,0x54C2,0x54A4,0x54BE,0x54BC,0x54D8,0x54E5,
+0x54E6,0x550F,0x5514,0x54FD,0x54EE,0x54ED,0x54FA,0x54E2,
+0x5539,0x5540,0x5563,0x554C,0x552E,0x555C,0x5545,0x5556,
+0x5557,0x5538,0x5533,0x555D,0x5599,0x5580,0x54AF,0x558A,
+0x559F,0x557B,0x557E,0x5598,0x559E,0x55AE,0x557C,0x5583,
+0x55A9,0x5587,0x55A8,0x55DA,0x55C5,0x55DF,0x55C4,0x55DC,
+0x55E4,0x55D4,0x5614,0x55F7,0x5616,0x55FE,0x55FD,0x561B,
+0x55F9,0x564E,0x5650,0x71DF,0x5634,0x5636,0x5632,0x5638,
+ 0,0x566B,0x5664,0x562F,0x566C,0x566A,0x5686,0x5680,
+0x568A,0x56A0,0x5694,0x568F,0x56A5,0x56AE,0x56B6,0x56B4,
+0x56C2,0x56BC,0x56C1,0x56C3,0x56C0,0x56C8,0x56CE,0x56D1,
+0x56D3,0x56D7,0x56EE,0x56F9,0x5700,0x56FF,0x5704,0x5709,
+0x5708,0x570B,0x570D,0x5713,0x5718,0x5716,0x55C7,0x571C,
+0x5726,0x5737,0x5738,0x574E,0x573B,0x5740,0x574F,0x5769,
+0x57C0,0x5788,0x5761,0x577F,0x5789,0x5793,0x57A0,0x57B3,
+0x57A4,0x57AA,0x57B0,0x57C3,0x57C6,0x57D4,0x57D2,0x57D3,
+0x580A,0x57D6,0x57E3,0x580B,0x5819,0x581D,0x5872,0x5821,
+0x5862,0x584B,0x5870,0x6BC0,0x5852,0x583D,0x5879,0x5885,
+0x58B9,0x589F,0x58AB,0x58BA,0x58DE,0x58BB,0x58B8,0x58AE,
+0x58C5,0x58D3,0x58D1,0x58D7,0x58D9,0x58D8,0x58E5,0x58DC,
+0x58E4,0x58DF,0x58EF,0x58FA,0x58F9,0x58FB,0x58FC,0x58FD,
+0x5902,0x590A,0x5910,0x591B,0x68A6,0x5925,0x592C,0x592D,
+0x5932,0x5938,0x593E,0x7AD2,0x5955,0x5950,0x594E,0x595A,
+0x5958,0x5962,0x5960,0x5967,0x596C,0x5969, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5978,0x5981,0x599D,0x4F5E,0x4FAB,0x59A3,0x59B2,
+0x59C6,0x59E8,0x59DC,0x598D,0x59D9,0x59DA,0x5A25,0x5A1F,
+0x5A11,0x5A1C,0x5A09,0x5A1A,0x5A40,0x5A6C,0x5A49,0x5A35,
+0x5A36,0x5A62,0x5A6A,0x5A9A,0x5ABC,0x5ABE,0x5ACB,0x5AC2,
+0x5ABD,0x5AE3,0x5AD7,0x5AE6,0x5AE9,0x5AD6,0x5AFA,0x5AFB,
+0x5B0C,0x5B0B,0x5B16,0x5B32,0x5AD0,0x5B2A,0x5B36,0x5B3E,
+0x5B43,0x5B45,0x5B40,0x5B51,0x5B55,0x5B5A,0x5B5B,0x5B65,
+0x5B69,0x5B70,0x5B73,0x5B75,0x5B78,0x6588,0x5B7A,0x5B80,
+ 0,0x5B83,0x5BA6,0x5BB8,0x5BC3,0x5BC7,0x5BC9,0x5BD4,
+0x5BD0,0x5BE4,0x5BE6,0x5BE2,0x5BDE,0x5BE5,0x5BEB,0x5BF0,
+0x5BF6,0x5BF3,0x5C05,0x5C07,0x5C08,0x5C0D,0x5C13,0x5C20,
+0x5C22,0x5C28,0x5C38,0x5C39,0x5C41,0x5C46,0x5C4E,0x5C53,
+0x5C50,0x5C4F,0x5B71,0x5C6C,0x5C6E,0x4E62,0x5C76,0x5C79,
+0x5C8C,0x5C91,0x5C94,0x599B,0x5CAB,0x5CBB,0x5CB6,0x5CBC,
+0x5CB7,0x5CC5,0x5CBE,0x5CC7,0x5CD9,0x5CE9,0x5CFD,0x5CFA,
+0x5CED,0x5D8C,0x5CEA,0x5D0B,0x5D15,0x5D17,0x5D5C,0x5D1F,
+0x5D1B,0x5D11,0x5D14,0x5D22,0x5D1A,0x5D19,0x5D18,0x5D4C,
+0x5D52,0x5D4E,0x5D4B,0x5D6C,0x5D73,0x5D76,0x5D87,0x5D84,
+0x5D82,0x5DA2,0x5D9D,0x5DAC,0x5DAE,0x5DBD,0x5D90,0x5DB7,
+0x5DBC,0x5DC9,0x5DCD,0x5DD3,0x5DD2,0x5DD6,0x5DDB,0x5DEB,
+0x5DF2,0x5DF5,0x5E0B,0x5E1A,0x5E19,0x5E11,0x5E1B,0x5E36,
+0x5E37,0x5E44,0x5E43,0x5E40,0x5E4E,0x5E57,0x5E54,0x5E5F,
+0x5E62,0x5E64,0x5E47,0x5E75,0x5E76,0x5E7A,0x9EBC,0x5E7F,
+0x5EA0,0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5ED6,0x5EE3,0x5EDD,0x5EDA,0x5EDB,0x5EE2,0x5EE1,
+0x5EE8,0x5EE9,0x5EEC,0x5EF1,0x5EF3,0x5EF0,0x5EF4,0x5EF8,
+0x5EFE,0x5F03,0x5F09,0x5F5D,0x5F5C,0x5F0B,0x5F11,0x5F16,
+0x5F29,0x5F2D,0x5F38,0x5F41,0x5F48,0x5F4C,0x5F4E,0x5F2F,
+0x5F51,0x5F56,0x5F57,0x5F59,0x5F61,0x5F6D,0x5F73,0x5F77,
+0x5F83,0x5F82,0x5F7F,0x5F8A,0x5F88,0x5F91,0x5F87,0x5F9E,
+0x5F99,0x5F98,0x5FA0,0x5FA8,0x5FAD,0x5FBC,0x5FD6,0x5FFB,
+0x5FE4,0x5FF8,0x5FF1,0x5FDD,0x60B3,0x5FFF,0x6021,0x6060,
+ 0,0x6019,0x6010,0x6029,0x600E,0x6031,0x601B,0x6015,
+0x602B,0x6026,0x600F,0x603A,0x605A,0x6041,0x606A,0x6077,
+0x605F,0x604A,0x6046,0x604D,0x6063,0x6043,0x6064,0x6042,
+0x606C,0x606B,0x6059,0x6081,0x608D,0x60E7,0x6083,0x609A,
+0x6084,0x609B,0x6096,0x6097,0x6092,0x60A7,0x608B,0x60E1,
+0x60B8,0x60E0,0x60D3,0x60B4,0x5FF0,0x60BD,0x60C6,0x60B5,
+0x60D8,0x614D,0x6115,0x6106,0x60F6,0x60F7,0x6100,0x60F4,
+0x60FA,0x6103,0x6121,0x60FB,0x60F1,0x610D,0x610E,0x6147,
+0x613E,0x6128,0x6127,0x614A,0x613F,0x613C,0x612C,0x6134,
+0x613D,0x6142,0x6144,0x6173,0x6177,0x6158,0x6159,0x615A,
+0x616B,0x6174,0x616F,0x6165,0x6171,0x615F,0x615D,0x6153,
+0x6175,0x6199,0x6196,0x6187,0x61AC,0x6194,0x619A,0x618A,
+0x6191,0x61AB,0x61AE,0x61CC,0x61CA,0x61C9,0x61F7,0x61C8,
+0x61C3,0x61C6,0x61BA,0x61CB,0x7F79,0x61CD,0x61E6,0x61E3,
+0x61F6,0x61FA,0x61F4,0x61FF,0x61FD,0x61FC,0x61FE,0x6200,
+0x6208,0x6209,0x620D,0x620C,0x6214,0x621B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x621E,0x6221,0x622A,0x622E,0x6230,0x6232,0x6233,
+0x6241,0x624E,0x625E,0x6263,0x625B,0x6260,0x6268,0x627C,
+0x6282,0x6289,0x627E,0x6292,0x6293,0x6296,0x62D4,0x6283,
+0x6294,0x62D7,0x62D1,0x62BB,0x62CF,0x62FF,0x62C6,0x64D4,
+0x62C8,0x62DC,0x62CC,0x62CA,0x62C2,0x62C7,0x629B,0x62C9,
+0x630C,0x62EE,0x62F1,0x6327,0x6302,0x6308,0x62EF,0x62F5,
+0x6350,0x633E,0x634D,0x641C,0x634F,0x6396,0x638E,0x6380,
+0x63AB,0x6376,0x63A3,0x638F,0x6389,0x639F,0x63B5,0x636B,
+ 0,0x6369,0x63BE,0x63E9,0x63C0,0x63C6,0x63E3,0x63C9,
+0x63D2,0x63F6,0x63C4,0x6416,0x6434,0x6406,0x6413,0x6426,
+0x6436,0x651D,0x6417,0x6428,0x640F,0x6467,0x646F,0x6476,
+0x644E,0x652A,0x6495,0x6493,0x64A5,0x64A9,0x6488,0x64BC,
+0x64DA,0x64D2,0x64C5,0x64C7,0x64BB,0x64D8,0x64C2,0x64F1,
+0x64E7,0x8209,0x64E0,0x64E1,0x62AC,0x64E3,0x64EF,0x652C,
+0x64F6,0x64F4,0x64F2,0x64FA,0x6500,0x64FD,0x6518,0x651C,
+0x6505,0x6524,0x6523,0x652B,0x6534,0x6535,0x6537,0x6536,
+0x6538,0x754B,0x6548,0x6556,0x6555,0x654D,0x6558,0x655E,
+0x655D,0x6572,0x6578,0x6582,0x6583,0x8B8A,0x659B,0x659F,
+0x65AB,0x65B7,0x65C3,0x65C6,0x65C1,0x65C4,0x65CC,0x65D2,
+0x65DB,0x65D9,0x65E0,0x65E1,0x65F1,0x6772,0x660A,0x6603,
+0x65FB,0x6773,0x6635,0x6636,0x6634,0x661C,0x664F,0x6644,
+0x6649,0x6641,0x665E,0x665D,0x6664,0x6667,0x6668,0x665F,
+0x6662,0x6670,0x6683,0x6688,0x668E,0x6689,0x6684,0x6698,
+0x669D,0x66C1,0x66B9,0x66C9,0x66BE,0x66BC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x66C4,0x66B8,0x66D6,0x66DA,0x66E0,0x663F,0x66E6,
+0x66E9,0x66F0,0x66F5,0x66F7,0x670F,0x6716,0x671E,0x6726,
+0x6727,0x9738,0x672E,0x673F,0x6736,0x6741,0x6738,0x6737,
+0x6746,0x675E,0x6760,0x6759,0x6763,0x6764,0x6789,0x6770,
+0x67A9,0x677C,0x676A,0x678C,0x678B,0x67A6,0x67A1,0x6785,
+0x67B7,0x67EF,0x67B4,0x67EC,0x67B3,0x67E9,0x67B8,0x67E4,
+0x67DE,0x67DD,0x67E2,0x67EE,0x67B9,0x67CE,0x67C6,0x67E7,
+0x6A9C,0x681E,0x6846,0x6829,0x6840,0x684D,0x6832,0x684E,
+ 0,0x68B3,0x682B,0x6859,0x6863,0x6877,0x687F,0x689F,
+0x688F,0x68AD,0x6894,0x689D,0x689B,0x6883,0x6AAE,0x68B9,
+0x6874,0x68B5,0x68A0,0x68BA,0x690F,0x688D,0x687E,0x6901,
+0x68CA,0x6908,0x68D8,0x6922,0x6926,0x68E1,0x690C,0x68CD,
+0x68D4,0x68E7,0x68D5,0x6936,0x6912,0x6904,0x68D7,0x68E3,
+0x6925,0x68F9,0x68E0,0x68EF,0x6928,0x692A,0x691A,0x6923,
+0x6921,0x68C6,0x6979,0x6977,0x695C,0x6978,0x696B,0x6954,
+0x697E,0x696E,0x6939,0x6974,0x693D,0x6959,0x6930,0x6961,
+0x695E,0x695D,0x6981,0x696A,0x69B2,0x69AE,0x69D0,0x69BF,
+0x69C1,0x69D3,0x69BE,0x69CE,0x5BE8,0x69CA,0x69DD,0x69BB,
+0x69C3,0x69A7,0x6A2E,0x6991,0x69A0,0x699C,0x6995,0x69B4,
+0x69DE,0x69E8,0x6A02,0x6A1B,0x69FF,0x6B0A,0x69F9,0x69F2,
+0x69E7,0x6A05,0x69B1,0x6A1E,0x69ED,0x6A14,0x69EB,0x6A0A,
+0x6A12,0x6AC1,0x6A23,0x6A13,0x6A44,0x6A0C,0x6A72,0x6A36,
+0x6A78,0x6A47,0x6A62,0x6A59,0x6A66,0x6A48,0x6A38,0x6A22,
+0x6A90,0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6A97,0x8617,0x6ABB,0x6AC3,0x6AC2,0x6AB8,0x6AB3,
+0x6AAC,0x6ADE,0x6AD1,0x6ADF,0x6AAA,0x6ADA,0x6AEA,0x6AFB,
+0x6B05,0x8616,0x6AFA,0x6B12,0x6B16,0x9B31,0x6B1F,0x6B38,
+0x6B37,0x76DC,0x6B39,0x98EE,0x6B47,0x6B43,0x6B49,0x6B50,
+0x6B59,0x6B54,0x6B5B,0x6B5F,0x6B61,0x6B78,0x6B79,0x6B7F,
+0x6B80,0x6B84,0x6B83,0x6B8D,0x6B98,0x6B95,0x6B9E,0x6BA4,
+0x6BAA,0x6BAB,0x6BAF,0x6BB2,0x6BB1,0x6BB3,0x6BB7,0x6BBC,
+0x6BC6,0x6BCB,0x6BD3,0x6BDF,0x6BEC,0x6BEB,0x6BF3,0x6BEF,
+ 0,0x9EBE,0x6C08,0x6C13,0x6C14,0x6C1B,0x6C24,0x6C23,
+0x6C5E,0x6C55,0x6C62,0x6C6A,0x6C82,0x6C8D,0x6C9A,0x6C81,
+0x6C9B,0x6C7E,0x6C68,0x6C73,0x6C92,0x6C90,0x6CC4,0x6CF1,
+0x6CD3,0x6CBD,0x6CD7,0x6CC5,0x6CDD,0x6CAE,0x6CB1,0x6CBE,
+0x6CBA,0x6CDB,0x6CEF,0x6CD9,0x6CEA,0x6D1F,0x884D,0x6D36,
+0x6D2B,0x6D3D,0x6D38,0x6D19,0x6D35,0x6D33,0x6D12,0x6D0C,
+0x6D63,0x6D93,0x6D64,0x6D5A,0x6D79,0x6D59,0x6D8E,0x6D95,
+0x6FE4,0x6D85,0x6DF9,0x6E15,0x6E0A,0x6DB5,0x6DC7,0x6DE6,
+0x6DB8,0x6DC6,0x6DEC,0x6DDE,0x6DCC,0x6DE8,0x6DD2,0x6DC5,
+0x6DFA,0x6DD9,0x6DE4,0x6DD5,0x6DEA,0x6DEE,0x6E2D,0x6E6E,
+0x6E2E,0x6E19,0x6E72,0x6E5F,0x6E3E,0x6E23,0x6E6B,0x6E2B,
+0x6E76,0x6E4D,0x6E1F,0x6E43,0x6E3A,0x6E4E,0x6E24,0x6EFF,
+0x6E1D,0x6E38,0x6E82,0x6EAA,0x6E98,0x6EC9,0x6EB7,0x6ED3,
+0x6EBD,0x6EAF,0x6EC4,0x6EB2,0x6ED4,0x6ED5,0x6E8F,0x6EA5,
+0x6EC2,0x6E9F,0x6F41,0x6F11,0x704C,0x6EEC,0x6EF8,0x6EFE,
+0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
+
+/* page 3 0xE040-0xEAA4 */
+static uint16 tab_sjis_uni3[]={
+0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
+0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
+0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
+0x6FC6,0x6FAA,0x6FDF,0x6FD5,0x6FEC,0x6FD4,0x6FD8,0x6FF1,
+0x6FEE,0x6FDB,0x7009,0x700B,0x6FFA,0x7011,0x7001,0x700F,
+0x6FFE,0x701B,0x701A,0x6F74,0x701D,0x7018,0x701F,0x7030,
+0x703E,0x7032,0x7051,0x7063,0x7099,0x7092,0x70AF,0x70F1,
+0x70AC,0x70B8,0x70B3,0x70AE,0x70DF,0x70CB,0x70DD, 0,
+0x70D9,0x7109,0x70FD,0x711C,0x7119,0x7165,0x7155,0x7188,
+0x7166,0x7162,0x714C,0x7156,0x716C,0x718F,0x71FB,0x7184,
+0x7195,0x71A8,0x71AC,0x71D7,0x71B9,0x71BE,0x71D2,0x71C9,
+0x71D4,0x71CE,0x71E0,0x71EC,0x71E7,0x71F5,0x71FC,0x71F9,
+0x71FF,0x720D,0x7210,0x721B,0x7228,0x722D,0x722C,0x7230,
+0x7232,0x723B,0x723C,0x723F,0x7240,0x7246,0x724B,0x7258,
+0x7274,0x727E,0x7282,0x7281,0x7287,0x7292,0x7296,0x72A2,
+0x72A7,0x72B9,0x72B2,0x72C3,0x72C6,0x72C4,0x72CE,0x72D2,
+0x72E2,0x72E0,0x72E1,0x72F9,0x72F7,0x500F,0x7317,0x730A,
+0x731C,0x7316,0x731D,0x7334,0x732F,0x7329,0x7325,0x733E,
+0x734E,0x734F,0x9ED8,0x7357,0x736A,0x7368,0x7370,0x7378,
+0x7375,0x737B,0x737A,0x73C8,0x73B3,0x73CE,0x73BB,0x73C0,
+0x73E5,0x73EE,0x73DE,0x74A2,0x7405,0x746F,0x7425,0x73F8,
+0x7432,0x743A,0x7455,0x743F,0x745F,0x7459,0x7441,0x745C,
+0x7469,0x7470,0x7463,0x746A,0x7476,0x747E,0x748B,0x749E,
+0x74A7,0x74CA,0x74CF,0x74D4,0x73F1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x74E0,0x74E3,0x74E7,0x74E9,0x74EE,0x74F2,0x74F0,0x74F1,
+0x74F8,0x74F7,0x7504,0x7503,0x7505,0x750C,0x750E,0x750D,
+0x7515,0x7513,0x751E,0x7526,0x752C,0x753C,0x7544,0x754D,
+0x754A,0x7549,0x755B,0x7546,0x755A,0x7569,0x7564,0x7567,
+0x756B,0x756D,0x7578,0x7576,0x7586,0x7587,0x7574,0x758A,
+0x7589,0x7582,0x7594,0x759A,0x759D,0x75A5,0x75A3,0x75C2,
+0x75B3,0x75C3,0x75B5,0x75BD,0x75B8,0x75BC,0x75B1,0x75CD,
+0x75CA,0x75D2,0x75D9,0x75E3,0x75DE,0x75FE,0x75FF, 0,
+0x75FC,0x7601,0x75F0,0x75FA,0x75F2,0x75F3,0x760B,0x760D,
+0x7609,0x761F,0x7627,0x7620,0x7621,0x7622,0x7624,0x7634,
+0x7630,0x763B,0x7647,0x7648,0x7646,0x765C,0x7658,0x7661,
+0x7662,0x7668,0x7669,0x766A,0x7667,0x766C,0x7670,0x7672,
+0x7676,0x7678,0x767C,0x7680,0x7683,0x7688,0x768B,0x768E,
+0x7696,0x7693,0x7699,0x769A,0x76B0,0x76B4,0x76B8,0x76B9,
+0x76BA,0x76C2,0x76CD,0x76D6,0x76D2,0x76DE,0x76E1,0x76E5,
+0x76E7,0x76EA,0x862F,0x76FB,0x7708,0x7707,0x7704,0x7729,
+0x7724,0x771E,0x7725,0x7726,0x771B,0x7737,0x7738,0x7747,
+0x775A,0x7768,0x776B,0x775B,0x7765,0x777F,0x777E,0x7779,
+0x778E,0x778B,0x7791,0x77A0,0x779E,0x77B0,0x77B6,0x77B9,
+0x77BF,0x77BC,0x77BD,0x77BB,0x77C7,0x77CD,0x77D7,0x77DA,
+0x77DC,0x77E3,0x77EE,0x77FC,0x780C,0x7812,0x7926,0x7820,
+0x792A,0x7845,0x788E,0x7874,0x7886,0x787C,0x789A,0x788C,
+0x78A3,0x78B5,0x78AA,0x78AF,0x78D1,0x78C6,0x78CB,0x78D4,
+0x78BE,0x78BC,0x78C5,0x78CA,0x78EC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x78E7,0x78DA,0x78FD,0x78F4,0x7907,0x7912,0x7911,0x7919,
+0x792C,0x792B,0x7940,0x7960,0x7957,0x795F,0x795A,0x7955,
+0x7953,0x797A,0x797F,0x798A,0x799D,0x79A7,0x9F4B,0x79AA,
+0x79AE,0x79B3,0x79B9,0x79BA,0x79C9,0x79D5,0x79E7,0x79EC,
+0x79E1,0x79E3,0x7A08,0x7A0D,0x7A18,0x7A19,0x7A20,0x7A1F,
+0x7980,0x7A31,0x7A3B,0x7A3E,0x7A37,0x7A43,0x7A57,0x7A49,
+0x7A61,0x7A62,0x7A69,0x9F9D,0x7A70,0x7A79,0x7A7D,0x7A88,
+0x7A97,0x7A95,0x7A98,0x7A96,0x7AA9,0x7AC8,0x7AB0, 0,
+0x7AB6,0x7AC5,0x7AC4,0x7ABF,0x9083,0x7AC7,0x7ACA,0x7ACD,
+0x7ACF,0x7AD5,0x7AD3,0x7AD9,0x7ADA,0x7ADD,0x7AE1,0x7AE2,
+0x7AE6,0x7AED,0x7AF0,0x7B02,0x7B0F,0x7B0A,0x7B06,0x7B33,
+0x7B18,0x7B19,0x7B1E,0x7B35,0x7B28,0x7B36,0x7B50,0x7B7A,
+0x7B04,0x7B4D,0x7B0B,0x7B4C,0x7B45,0x7B75,0x7B65,0x7B74,
+0x7B67,0x7B70,0x7B71,0x7B6C,0x7B6E,0x7B9D,0x7B98,0x7B9F,
+0x7B8D,0x7B9C,0x7B9A,0x7B8B,0x7B92,0x7B8F,0x7B5D,0x7B99,
+0x7BCB,0x7BC1,0x7BCC,0x7BCF,0x7BB4,0x7BC6,0x7BDD,0x7BE9,
+0x7C11,0x7C14,0x7BE6,0x7BE5,0x7C60,0x7C00,0x7C07,0x7C13,
+0x7BF3,0x7BF7,0x7C17,0x7C0D,0x7BF6,0x7C23,0x7C27,0x7C2A,
+0x7C1F,0x7C37,0x7C2B,0x7C3D,0x7C4C,0x7C43,0x7C54,0x7C4F,
+0x7C40,0x7C50,0x7C58,0x7C5F,0x7C64,0x7C56,0x7C65,0x7C6C,
+0x7C75,0x7C83,0x7C90,0x7CA4,0x7CAD,0x7CA2,0x7CAB,0x7CA1,
+0x7CA8,0x7CB3,0x7CB2,0x7CB1,0x7CAE,0x7CB9,0x7CBD,0x7CC0,
+0x7CC5,0x7CC2,0x7CD8,0x7CD2,0x7CDC,0x7CE2,0x9B3B,0x7CEF,
+0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7D02,0x7D1C,0x7D15,0x7D0A,0x7D45,0x7D4B,0x7D2E,0x7D32,
+0x7D3F,0x7D35,0x7D46,0x7D73,0x7D56,0x7D4E,0x7D72,0x7D68,
+0x7D6E,0x7D4F,0x7D63,0x7D93,0x7D89,0x7D5B,0x7D8F,0x7D7D,
+0x7D9B,0x7DBA,0x7DAE,0x7DA3,0x7DB5,0x7DC7,0x7DBD,0x7DAB,
+0x7E3D,0x7DA2,0x7DAF,0x7DDC,0x7DB8,0x7D9F,0x7DB0,0x7DD8,
+0x7DDD,0x7DE4,0x7DDE,0x7DFB,0x7DF2,0x7DE1,0x7E05,0x7E0A,
+0x7E23,0x7E21,0x7E12,0x7E31,0x7E1F,0x7E09,0x7E0B,0x7E22,
+0x7E46,0x7E66,0x7E3B,0x7E35,0x7E39,0x7E43,0x7E37, 0,
+0x7E32,0x7E3A,0x7E67,0x7E5D,0x7E56,0x7E5E,0x7E59,0x7E5A,
+0x7E79,0x7E6A,0x7E69,0x7E7C,0x7E7B,0x7E83,0x7DD5,0x7E7D,
+0x8FAE,0x7E7F,0x7E88,0x7E89,0x7E8C,0x7E92,0x7E90,0x7E93,
+0x7E94,0x7E96,0x7E8E,0x7E9B,0x7E9C,0x7F38,0x7F3A,0x7F45,
+0x7F4C,0x7F4D,0x7F4E,0x7F50,0x7F51,0x7F55,0x7F54,0x7F58,
+0x7F5F,0x7F60,0x7F68,0x7F69,0x7F67,0x7F78,0x7F82,0x7F86,
+0x7F83,0x7F88,0x7F87,0x7F8C,0x7F94,0x7F9E,0x7F9D,0x7F9A,
+0x7FA3,0x7FAF,0x7FB2,0x7FB9,0x7FAE,0x7FB6,0x7FB8,0x8B71,
+0x7FC5,0x7FC6,0x7FCA,0x7FD5,0x7FD4,0x7FE1,0x7FE6,0x7FE9,
+0x7FF3,0x7FF9,0x98DC,0x8006,0x8004,0x800B,0x8012,0x8018,
+0x8019,0x801C,0x8021,0x8028,0x803F,0x803B,0x804A,0x8046,
+0x8052,0x8058,0x805A,0x805F,0x8062,0x8068,0x8073,0x8072,
+0x8070,0x8076,0x8079,0x807D,0x807F,0x8084,0x8086,0x8085,
+0x809B,0x8093,0x809A,0x80AD,0x5190,0x80AC,0x80DB,0x80E5,
+0x80D9,0x80DD,0x80C4,0x80DA,0x80D6,0x8109,0x80EF,0x80F1,
+0x811B,0x8129,0x8123,0x812F,0x814B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x968B,0x8146,0x813E,0x8153,0x8151,0x80FC,0x8171,0x816E,
+0x8165,0x8166,0x8174,0x8183,0x8188,0x818A,0x8180,0x8182,
+0x81A0,0x8195,0x81A4,0x81A3,0x815F,0x8193,0x81A9,0x81B0,
+0x81B5,0x81BE,0x81B8,0x81BD,0x81C0,0x81C2,0x81BA,0x81C9,
+0x81CD,0x81D1,0x81D9,0x81D8,0x81C8,0x81DA,0x81DF,0x81E0,
+0x81E7,0x81FA,0x81FB,0x81FE,0x8201,0x8202,0x8205,0x8207,
+0x820A,0x820D,0x8210,0x8216,0x8229,0x822B,0x8238,0x8233,
+0x8240,0x8259,0x8258,0x825D,0x825A,0x825F,0x8264, 0,
+0x8262,0x8268,0x826A,0x826B,0x822E,0x8271,0x8277,0x8278,
+0x827E,0x828D,0x8292,0x82AB,0x829F,0x82BB,0x82AC,0x82E1,
+0x82E3,0x82DF,0x82D2,0x82F4,0x82F3,0x82FA,0x8393,0x8303,
+0x82FB,0x82F9,0x82DE,0x8306,0x82DC,0x8309,0x82D9,0x8335,
+0x8334,0x8316,0x8332,0x8331,0x8340,0x8339,0x8350,0x8345,
+0x832F,0x832B,0x8317,0x8318,0x8385,0x839A,0x83AA,0x839F,
+0x83A2,0x8396,0x8323,0x838E,0x8387,0x838A,0x837C,0x83B5,
+0x8373,0x8375,0x83A0,0x8389,0x83A8,0x83F4,0x8413,0x83EB,
+0x83CE,0x83FD,0x8403,0x83D8,0x840B,0x83C1,0x83F7,0x8407,
+0x83E0,0x83F2,0x840D,0x8422,0x8420,0x83BD,0x8438,0x8506,
+0x83FB,0x846D,0x842A,0x843C,0x855A,0x8484,0x8477,0x846B,
+0x84AD,0x846E,0x8482,0x8469,0x8446,0x842C,0x846F,0x8479,
+0x8435,0x84CA,0x8462,0x84B9,0x84BF,0x849F,0x84D9,0x84CD,
+0x84BB,0x84DA,0x84D0,0x84C1,0x84C6,0x84D6,0x84A1,0x8521,
+0x84FF,0x84F4,0x8517,0x8518,0x852C,0x851F,0x8515,0x8514,
+0x84FC,0x8540,0x8563,0x8558,0x8548, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8541,0x8602,0x854B,0x8555,0x8580,0x85A4,0x8588,0x8591,
+0x858A,0x85A8,0x856D,0x8594,0x859B,0x85EA,0x8587,0x859C,
+0x8577,0x857E,0x8590,0x85C9,0x85BA,0x85CF,0x85B9,0x85D0,
+0x85D5,0x85DD,0x85E5,0x85DC,0x85F9,0x860A,0x8613,0x860B,
+0x85FE,0x85FA,0x8606,0x8622,0x861A,0x8630,0x863F,0x864D,
+0x4E55,0x8654,0x865F,0x8667,0x8671,0x8693,0x86A3,0x86A9,
+0x86AA,0x868B,0x868C,0x86B6,0x86AF,0x86C4,0x86C6,0x86B0,
+0x86C9,0x8823,0x86AB,0x86D4,0x86DE,0x86E9,0x86EC, 0,
+0x86DF,0x86DB,0x86EF,0x8712,0x8706,0x8708,0x8700,0x8703,
+0x86FB,0x8711,0x8709,0x870D,0x86F9,0x870A,0x8734,0x873F,
+0x8737,0x873B,0x8725,0x8729,0x871A,0x8760,0x875F,0x8778,
+0x874C,0x874E,0x8774,0x8757,0x8768,0x876E,0x8759,0x8753,
+0x8763,0x876A,0x8805,0x87A2,0x879F,0x8782,0x87AF,0x87CB,
+0x87BD,0x87C0,0x87D0,0x96D6,0x87AB,0x87C4,0x87B3,0x87C7,
+0x87C6,0x87BB,0x87EF,0x87F2,0x87E0,0x880F,0x880D,0x87FE,
+0x87F6,0x87F7,0x880E,0x87D2,0x8811,0x8816,0x8815,0x8822,
+0x8821,0x8831,0x8836,0x8839,0x8827,0x883B,0x8844,0x8842,
+0x8852,0x8859,0x885E,0x8862,0x886B,0x8881,0x887E,0x889E,
+0x8875,0x887D,0x88B5,0x8872,0x8882,0x8897,0x8892,0x88AE,
+0x8899,0x88A2,0x888D,0x88A4,0x88B0,0x88BF,0x88B1,0x88C3,
+0x88C4,0x88D4,0x88D8,0x88D9,0x88DD,0x88F9,0x8902,0x88FC,
+0x88F4,0x88E8,0x88F2,0x8904,0x890C,0x890A,0x8913,0x8943,
+0x891E,0x8925,0x892A,0x892B,0x8941,0x8944,0x893B,0x8936,
+0x8938,0x894C,0x891D,0x8960,0x895E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8966,0x8964,0x896D,0x896A,0x896F,0x8974,0x8977,0x897E,
+0x8983,0x8988,0x898A,0x8993,0x8998,0x89A1,0x89A9,0x89A6,
+0x89AC,0x89AF,0x89B2,0x89BA,0x89BD,0x89BF,0x89C0,0x89DA,
+0x89DC,0x89DD,0x89E7,0x89F4,0x89F8,0x8A03,0x8A16,0x8A10,
+0x8A0C,0x8A1B,0x8A1D,0x8A25,0x8A36,0x8A41,0x8A5B,0x8A52,
+0x8A46,0x8A48,0x8A7C,0x8A6D,0x8A6C,0x8A62,0x8A85,0x8A82,
+0x8A84,0x8AA8,0x8AA1,0x8A91,0x8AA5,0x8AA6,0x8A9A,0x8AA3,
+0x8AC4,0x8ACD,0x8AC2,0x8ADA,0x8AEB,0x8AF3,0x8AE7, 0,
+0x8AE4,0x8AF1,0x8B14,0x8AE0,0x8AE2,0x8AF7,0x8ADE,0x8ADB,
+0x8B0C,0x8B07,0x8B1A,0x8AE1,0x8B16,0x8B10,0x8B17,0x8B20,
+0x8B33,0x97AB,0x8B26,0x8B2B,0x8B3E,0x8B28,0x8B41,0x8B4C,
+0x8B4F,0x8B4E,0x8B49,0x8B56,0x8B5B,0x8B5A,0x8B6B,0x8B5F,
+0x8B6C,0x8B6F,0x8B74,0x8B7D,0x8B80,0x8B8C,0x8B8E,0x8B92,
+0x8B93,0x8B96,0x8B99,0x8B9A,0x8C3A,0x8C41,0x8C3F,0x8C48,
+0x8C4C,0x8C4E,0x8C50,0x8C55,0x8C62,0x8C6C,0x8C78,0x8C7A,
+0x8C82,0x8C89,0x8C85,0x8C8A,0x8C8D,0x8C8E,0x8C94,0x8C7C,
+0x8C98,0x621D,0x8CAD,0x8CAA,0x8CBD,0x8CB2,0x8CB3,0x8CAE,
+0x8CB6,0x8CC8,0x8CC1,0x8CE4,0x8CE3,0x8CDA,0x8CFD,0x8CFA,
+0x8CFB,0x8D04,0x8D05,0x8D0A,0x8D07,0x8D0F,0x8D0D,0x8D10,
+0x9F4E,0x8D13,0x8CCD,0x8D14,0x8D16,0x8D67,0x8D6D,0x8D71,
+0x8D73,0x8D81,0x8D99,0x8DC2,0x8DBE,0x8DBA,0x8DCF,0x8DDA,
+0x8DD6,0x8DCC,0x8DDB,0x8DCB,0x8DEA,0x8DEB,0x8DDF,0x8DE3,
+0x8DFC,0x8E08,0x8E09,0x8DFF,0x8E1D,0x8E1E,0x8E10,0x8E1F,
+0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8E47,0x8E49,0x8E4C,0x8E50,0x8E48,0x8E59,0x8E64,0x8E60,
+0x8E2A,0x8E63,0x8E55,0x8E76,0x8E72,0x8E7C,0x8E81,0x8E87,
+0x8E85,0x8E84,0x8E8B,0x8E8A,0x8E93,0x8E91,0x8E94,0x8E99,
+0x8EAA,0x8EA1,0x8EAC,0x8EB0,0x8EC6,0x8EB1,0x8EBE,0x8EC5,
+0x8EC8,0x8ECB,0x8EDB,0x8EE3,0x8EFC,0x8EFB,0x8EEB,0x8EFE,
+0x8F0A,0x8F05,0x8F15,0x8F12,0x8F19,0x8F13,0x8F1C,0x8F1F,
+0x8F1B,0x8F0C,0x8F26,0x8F33,0x8F3B,0x8F39,0x8F45,0x8F42,
+0x8F3E,0x8F4C,0x8F49,0x8F46,0x8F4E,0x8F57,0x8F5C, 0,
+0x8F62,0x8F63,0x8F64,0x8F9C,0x8F9F,0x8FA3,0x8FAD,0x8FAF,
+0x8FB7,0x8FDA,0x8FE5,0x8FE2,0x8FEA,0x8FEF,0x9087,0x8FF4,
+0x9005,0x8FF9,0x8FFA,0x9011,0x9015,0x9021,0x900D,0x901E,
+0x9016,0x900B,0x9027,0x9036,0x9035,0x9039,0x8FF8,0x904F,
+0x9050,0x9051,0x9052,0x900E,0x9049,0x903E,0x9056,0x9058,
+0x905E,0x9068,0x906F,0x9076,0x96A8,0x9072,0x9082,0x907D,
+0x9081,0x9080,0x908A,0x9089,0x908F,0x90A8,0x90AF,0x90B1,
+0x90B5,0x90E2,0x90E4,0x6248,0x90DB,0x9102,0x9112,0x9119,
+0x9132,0x9130,0x914A,0x9156,0x9158,0x9163,0x9165,0x9169,
+0x9173,0x9172,0x918B,0x9189,0x9182,0x91A2,0x91AB,0x91AF,
+0x91AA,0x91B5,0x91B4,0x91BA,0x91C0,0x91C1,0x91C9,0x91CB,
+0x91D0,0x91D6,0x91DF,0x91E1,0x91DB,0x91FC,0x91F5,0x91F6,
+0x921E,0x91FF,0x9214,0x922C,0x9215,0x9211,0x925E,0x9257,
+0x9245,0x9249,0x9264,0x9248,0x9295,0x923F,0x924B,0x9250,
+0x929C,0x9296,0x9293,0x929B,0x925A,0x92CF,0x92B9,0x92B7,
+0x92E9,0x930F,0x92FA,0x9344,0x932E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9319,0x9322,0x931A,0x9323,0x933A,0x9335,0x933B,0x935C,
+0x9360,0x937C,0x936E,0x9356,0x93B0,0x93AC,0x93AD,0x9394,
+0x93B9,0x93D6,0x93D7,0x93E8,0x93E5,0x93D8,0x93C3,0x93DD,
+0x93D0,0x93C8,0x93E4,0x941A,0x9414,0x9413,0x9403,0x9407,
+0x9410,0x9436,0x942B,0x9435,0x9421,0x943A,0x9441,0x9452,
+0x9444,0x945B,0x9460,0x9462,0x945E,0x946A,0x9229,0x9470,
+0x9475,0x9477,0x947D,0x945A,0x947C,0x947E,0x9481,0x947F,
+0x9582,0x9587,0x958A,0x9594,0x9596,0x9598,0x9599, 0,
+0x95A0,0x95A8,0x95A7,0x95AD,0x95BC,0x95BB,0x95B9,0x95BE,
+0x95CA,0x6FF6,0x95C3,0x95CD,0x95CC,0x95D5,0x95D4,0x95D6,
+0x95DC,0x95E1,0x95E5,0x95E2,0x9621,0x9628,0x962E,0x962F,
+0x9642,0x964C,0x964F,0x964B,0x9677,0x965C,0x965E,0x965D,
+0x965F,0x9666,0x9672,0x966C,0x968D,0x9698,0x9695,0x9697,
+0x96AA,0x96A7,0x96B1,0x96B2,0x96B0,0x96B4,0x96B6,0x96B8,
+0x96B9,0x96CE,0x96CB,0x96C9,0x96CD,0x894D,0x96DC,0x970D,
+0x96D5,0x96F9,0x9704,0x9706,0x9708,0x9713,0x970E,0x9711,
+0x970F,0x9716,0x9719,0x9724,0x972A,0x9730,0x9739,0x973D,
+0x973E,0x9744,0x9746,0x9748,0x9742,0x9749,0x975C,0x9760,
+0x9764,0x9766,0x9768,0x52D2,0x976B,0x9771,0x9779,0x9785,
+0x977C,0x9781,0x977A,0x9786,0x978B,0x978F,0x9790,0x979C,
+0x97A8,0x97A6,0x97A3,0x97B3,0x97B4,0x97C3,0x97C6,0x97C8,
+0x97CB,0x97DC,0x97ED,0x9F4F,0x97F2,0x7ADF,0x97F6,0x97F5,
+0x980F,0x980C,0x9838,0x9824,0x9821,0x9837,0x983D,0x9846,
+0x984F,0x984B,0x986B,0x986F,0x9870, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9871,0x9874,0x9873,0x98AA,0x98AF,0x98B1,0x98B6,0x98C4,
+0x98C3,0x98C6,0x98E9,0x98EB,0x9903,0x9909,0x9912,0x9914,
+0x9918,0x9921,0x991D,0x991E,0x9924,0x9920,0x992C,0x992E,
+0x993D,0x993E,0x9942,0x9949,0x9945,0x9950,0x994B,0x9951,
+0x9952,0x994C,0x9955,0x9997,0x9998,0x99A5,0x99AD,0x99AE,
+0x99BC,0x99DF,0x99DB,0x99DD,0x99D8,0x99D1,0x99ED,0x99EE,
+0x99F1,0x99F2,0x99FB,0x99F8,0x9A01,0x9A0F,0x9A05,0x99E2,
+0x9A19,0x9A2B,0x9A37,0x9A45,0x9A42,0x9A40,0x9A43, 0,
+0x9A3E,0x9A55,0x9A4D,0x9A5B,0x9A57,0x9A5F,0x9A62,0x9A65,
+0x9A64,0x9A69,0x9A6B,0x9A6A,0x9AAD,0x9AB0,0x9ABC,0x9AC0,
+0x9ACF,0x9AD1,0x9AD3,0x9AD4,0x9ADE,0x9ADF,0x9AE2,0x9AE3,
+0x9AE6,0x9AEF,0x9AEB,0x9AEE,0x9AF4,0x9AF1,0x9AF7,0x9AFB,
+0x9B06,0x9B18,0x9B1A,0x9B1F,0x9B22,0x9B23,0x9B25,0x9B27,
+0x9B28,0x9B29,0x9B2A,0x9B2E,0x9B2F,0x9B32,0x9B44,0x9B43,
+0x9B4F,0x9B4D,0x9B4E,0x9B51,0x9B58,0x9B74,0x9B93,0x9B83,
+0x9B91,0x9B96,0x9B97,0x9B9F,0x9BA0,0x9BA8,0x9BB4,0x9BC0,
+0x9BCA,0x9BB9,0x9BC6,0x9BCF,0x9BD1,0x9BD2,0x9BE3,0x9BE2,
+0x9BE4,0x9BD4,0x9BE1,0x9C3A,0x9BF2,0x9BF1,0x9BF0,0x9C15,
+0x9C14,0x9C09,0x9C13,0x9C0C,0x9C06,0x9C08,0x9C12,0x9C0A,
+0x9C04,0x9C2E,0x9C1B,0x9C25,0x9C24,0x9C21,0x9C30,0x9C47,
+0x9C32,0x9C46,0x9C3E,0x9C5A,0x9C60,0x9C67,0x9C76,0x9C78,
+0x9CE7,0x9CEC,0x9CF0,0x9D09,0x9D08,0x9CEB,0x9D03,0x9D06,
+0x9D2A,0x9D26,0x9DAF,0x9D23,0x9D1F,0x9D44,0x9D15,0x9D12,
+0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9D5D,0x9D5E,0x9D64,0x9D51,0x9D50,0x9D59,0x9D72,0x9D89,
+0x9D87,0x9DAB,0x9D6F,0x9D7A,0x9D9A,0x9DA4,0x9DA9,0x9DB2,
+0x9DC4,0x9DC1,0x9DBB,0x9DB8,0x9DBA,0x9DC6,0x9DCF,0x9DC2,
+0x9DD9,0x9DD3,0x9DF8,0x9DE6,0x9DED,0x9DEF,0x9DFD,0x9E1A,
+0x9E1B,0x9E1E,0x9E75,0x9E79,0x9E7D,0x9E81,0x9E88,0x9E8B,
+0x9E8C,0x9E92,0x9E95,0x9E91,0x9E9D,0x9EA5,0x9EA9,0x9EB8,
+0x9EAA,0x9EAD,0x9761,0x9ECC,0x9ECE,0x9ECF,0x9ED0,0x9ED4,
+0x9EDC,0x9EDE,0x9EDD,0x9EE0,0x9EE5,0x9EE8,0x9EEF, 0,
+0x9EF4,0x9EF6,0x9EF7,0x9EF9,0x9EFB,0x9EFC,0x9EFD,0x9F07,
+0x9F08,0x76B7,0x9F15,0x9F21,0x9F2C,0x9F3E,0x9F4A,0x9F52,
+0x9F54,0x9F63,0x9F5F,0x9F60,0x9F61,0x9F66,0x9F67,0x9F6C,
+0x9F6A,0x9F77,0x9F72,0x9F76,0x9F95,0x9F9C,0x9FA0,0x582F,
+0x69C7,0x9059,0x7464,0x51DC,0x7199};
+
+static int func_sjis_uni_onechar(int code){
+ if ((code>=0x00A1)&&(code<=0x00DF))
+ return(tab_sjis_uni0[code-0x00A1]);
+ if ((code>=0x8140)&&(code<=0x84BE))
+ return(tab_sjis_uni1[code-0x8140]);
+ if ((code>=0x889F)&&(code<=0x9FFC))
+ return(tab_sjis_uni2[code-0x889F]);
+ if ((code>=0xE040)&&(code<=0xEAA4))
+ return(tab_sjis_uni3[code-0xE040]);
+ return(0);
+}
+/* page 0 0x005C-0x00F7 */
+static uint16 tab_uni_sjis0[]={
+0x815F, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8191,0x8192,
+ 0, 0, 0,0x8198,0x814E, 0, 0, 0,
+0x81CA, 0, 0, 0,0x818B,0x817D, 0, 0,
+0x814C, 0,0x81F7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x817E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8180};
+
+/* page 1 0x0391-0x0451 */
+static uint16 tab_uni_sjis1[]={
+0x839F,0x83A0,0x83A1,0x83A2,0x83A3,0x83A4,0x83A5,0x83A6,
+0x83A7,0x83A8,0x83A9,0x83AA,0x83AB,0x83AC,0x83AD,0x83AE,
+0x83AF, 0,0x83B0,0x83B1,0x83B2,0x83B3,0x83B4,0x83B5,
+0x83B6, 0, 0, 0, 0, 0, 0, 0,
+0x83BF,0x83C0,0x83C1,0x83C2,0x83C3,0x83C4,0x83C5,0x83C6,
+0x83C7,0x83C8,0x83C9,0x83CA,0x83CB,0x83CC,0x83CD,0x83CE,
+0x83CF, 0,0x83D0,0x83D1,0x83D2,0x83D3,0x83D4,0x83D5,
+0x83D6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8446, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x8440,
+0x8441,0x8442,0x8443,0x8444,0x8445,0x8447,0x8448,0x8449,
+0x844A,0x844B,0x844C,0x844D,0x844E,0x844F,0x8450,0x8451,
+0x8452,0x8453,0x8454,0x8455,0x8456,0x8457,0x8458,0x8459,
+0x845A,0x845B,0x845C,0x845D,0x845E,0x845F,0x8460,0x8470,
+0x8471,0x8472,0x8473,0x8474,0x8475,0x8477,0x8478,0x8479,
+0x847A,0x847B,0x847C,0x847D,0x847E,0x8480,0x8481,0x8482,
+0x8483,0x8484,0x8485,0x8486,0x8487,0x8488,0x8489,0x848A,
+0x848B,0x848C,0x848D,0x848E,0x848F,0x8490,0x8491, 0,
+0x8476};
+
+/* page 2 0x2010-0x2312 */
+static uint16 tab_uni_sjis2[]={
+0x815D, 0, 0, 0, 0,0x815C,0x8161, 0,
+0x8165,0x8166, 0, 0,0x8167,0x8168, 0, 0,
+0x81F5,0x81F6, 0, 0, 0,0x8164,0x8163, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x81F1, 0,0x818C,0x818D, 0, 0, 0, 0,
+ 0, 0, 0,0x81A6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x818E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x81F0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x81A9,0x81AA,0x81A8,0x81AB, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x81CB, 0,0x81CC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x81CD, 0,0x81DD,0x81CE, 0, 0, 0,0x81DE,
+0x81B8, 0, 0,0x81B9, 0, 0, 0, 0,
+ 0, 0,0x817C, 0, 0, 0, 0, 0,
+ 0, 0,0x81E3, 0, 0,0x81E5,0x8187, 0,
+0x81DA, 0, 0, 0, 0, 0, 0,0x81C8,
+0x81C9,0x81BF,0x81BE,0x81E7,0x81E8, 0, 0, 0,
+ 0, 0, 0, 0,0x8188,0x81E6, 0, 0,
+ 0, 0, 0, 0, 0,0x81E4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x81E0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8182,0x81DF, 0, 0, 0, 0,0x8185,0x8186,
+ 0, 0,0x81E1,0x81E2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x81BC,0x81BD, 0, 0,0x81BA,0x81BB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x81DB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x81DC};
+
+/* page 3 0x2500-0x266F */
+static uint16 tab_uni_sjis3[]={
+0x849F,0x84AA,0x84A0,0x84AB, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x84A1, 0, 0,0x84AC,
+0x84A2, 0, 0,0x84AD,0x84A4, 0, 0,0x84AF,
+0x84A3, 0, 0,0x84AE,0x84A5,0x84BA, 0, 0,
+0x84B5, 0, 0,0x84B0,0x84A7,0x84BC, 0, 0,
+0x84B7, 0, 0,0x84B2,0x84A6, 0, 0,0x84B6,
+0x84BB, 0, 0,0x84B1,0x84A8, 0, 0,0x84B8,
+0x84BD, 0, 0,0x84B3,0x84A9, 0, 0,0x84B9,
+ 0, 0,0x84BE, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x84B4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x81A1,0x81A0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x81A3,0x81A2, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x81A5,0x81A4, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x819F,0x819E,
+ 0, 0, 0,0x819B, 0, 0,0x819D,0x819C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x81FC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x819A,0x8199, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x818A, 0,0x8189, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x81F4, 0, 0,0x81F3, 0,0x81F2
+};
+
+/* page 4 0x3000-0x30FE */
+static uint16 tab_uni_sjis4[]={
+0x8140,0x8141,0x8142,0x8156, 0,0x8158,0x8159,0x815A,
+0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177,0x8178,
+0x8179,0x817A,0x81A7,0x81AC,0x816B,0x816C, 0, 0,
+ 0, 0, 0, 0,0x8160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x829F,0x82A0,0x82A1,0x82A2,0x82A3,0x82A4,0x82A5,
+0x82A6,0x82A7,0x82A8,0x82A9,0x82AA,0x82AB,0x82AC,0x82AD,
+0x82AE,0x82AF,0x82B0,0x82B1,0x82B2,0x82B3,0x82B4,0x82B5,
+0x82B6,0x82B7,0x82B8,0x82B9,0x82BA,0x82BB,0x82BC,0x82BD,
+0x82BE,0x82BF,0x82C0,0x82C1,0x82C2,0x82C3,0x82C4,0x82C5,
+0x82C6,0x82C7,0x82C8,0x82C9,0x82CA,0x82CB,0x82CC,0x82CD,
+0x82CE,0x82CF,0x82D0,0x82D1,0x82D2,0x82D3,0x82D4,0x82D5,
+0x82D6,0x82D7,0x82D8,0x82D9,0x82DA,0x82DB,0x82DC,0x82DD,
+0x82DE,0x82DF,0x82E0,0x82E1,0x82E2,0x82E3,0x82E4,0x82E5,
+0x82E6,0x82E7,0x82E8,0x82E9,0x82EA,0x82EB,0x82EC,0x82ED,
+0x82EE,0x82EF,0x82F0,0x82F1, 0, 0, 0, 0,
+ 0, 0, 0,0x814A,0x814B,0x8154,0x8155, 0,
+ 0,0x8340,0x8341,0x8342,0x8343,0x8344,0x8345,0x8346,
+0x8347,0x8348,0x8349,0x834A,0x834B,0x834C,0x834D,0x834E,
+0x834F,0x8350,0x8351,0x8352,0x8353,0x8354,0x8355,0x8356,
+0x8357,0x8358,0x8359,0x835A,0x835B,0x835C,0x835D,0x835E,
+0x835F,0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0x8366,
+0x8367,0x8368,0x8369,0x836A,0x836B,0x836C,0x836D,0x836E,
+0x836F,0x8370,0x8371,0x8372,0x8373,0x8374,0x8375,0x8376,
+0x8377,0x8378,0x8379,0x837A,0x837B,0x837C,0x837D,0x837E,
+0x8380,0x8381,0x8382,0x8383,0x8384,0x8385,0x8386,0x8387,
+0x8388,0x8389,0x838A,0x838B,0x838C,0x838D,0x838E,0x838F,
+0x8390,0x8391,0x8392,0x8393,0x8394,0x8395,0x8396, 0,
+ 0, 0, 0,0x8145,0x815B,0x8152,0x8153};
+
+/* page 5 0x4E00-0x9481 */
+static uint16 tab_uni_sjis5[]={
+0x88EA,0x929A, 0,0x8EB5, 0, 0, 0,0x969C,
+0x8FE4,0x8E4F,0x8FE3,0x89BA, 0,0x9573,0x975E, 0,
+0x98A0,0x894E, 0, 0,0x8A8E,0x98A1,0x90A2,0x99C0,
+0x8B75,0x95B8, 0, 0, 0, 0,0x8FE5, 0,
+ 0,0x97BC, 0, 0, 0, 0,0x95C0, 0,
+ 0, 0,0x98A2, 0, 0,0x9286, 0, 0,
+ 0,0x98A3,0x8BF8, 0, 0, 0,0x98A4, 0,
+0x8ADB,0x924F, 0,0x8EE5,0x98A5, 0, 0,0x98A6,
+ 0, 0,0x98A7,0x9454, 0,0x8B76, 0, 0,
+ 0, 0, 0,0x9456, 0,0x93E1,0x8CC1,0x9652,
+ 0, 0, 0, 0, 0,0xE568,0x98A8,0x8FE6,
+0x98A9,0x89B3, 0, 0, 0,0x8BE3,0x8CEE,0x96E7,
+ 0, 0,0x9BA4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9790, 0,0x93FB, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8AA3, 0,
+0x8B54, 0,0x98AA, 0, 0,0x98AB,0x97B9, 0,
+0x975C,0x9188,0x98AD,0x8E96,0x93F1, 0,0x98B0, 0,
+ 0,0x895D,0x8CDD, 0,0x8CDC,0x88E4, 0, 0,
+0x986A,0x9869, 0,0x8DB1,0x889F, 0,0x98B1,0x98B2,
+0x98B3,0x9653,0x98B4, 0,0x8CF0,0x88E5,0x9692, 0,
+0x8B9C, 0, 0,0x8B9D,0x8B9E,0x92E0,0x97BA, 0,
+0x98B5, 0, 0,0x98B6, 0, 0,0x98B7, 0,
+ 0, 0,0x906C, 0, 0, 0, 0, 0,
+0x8F59,0x906D,0x98BC, 0,0x98BA, 0,0x98BB,0x8B77,
+ 0, 0,0x8DA1,0x89EE, 0,0x98B9,0x98B8,0x95A7,
+ 0, 0, 0, 0,0x8E65,0x8E64,0x91BC,0x98BD,
+0x9574,0x90E5, 0, 0, 0,0x8157,0x98BE,0x98C0,
+ 0, 0, 0,0x91E3,0x97DF,0x88C8, 0, 0,
+ 0, 0, 0, 0, 0,0x98BF,0x89BC, 0,
+0x8BC2, 0,0x9287, 0, 0, 0,0x8C8F,0x98C1,
+ 0, 0, 0,0x9443, 0, 0, 0, 0,
+ 0,0x8AE9, 0, 0, 0, 0, 0, 0,
+ 0,0x98C2,0x88C9, 0, 0,0x8CDE,0x8AEA,0x959A,
+0x94B0,0x8B78, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x89EF, 0,0x98E5,0x9360, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x948C,
+0x98C4, 0, 0, 0,0x94BA, 0,0x97E0, 0,
+0x904C, 0,0x8E66, 0,0x8E97,0x89BE, 0, 0,
+ 0, 0, 0,0x92CF, 0, 0,0x9241,0x98C8,
+ 0, 0, 0, 0, 0,0x88CA,0x92E1,0x8F5A,
+0x8DB2,0x9743, 0,0x91CC, 0,0x89BD, 0,0x98C7,
+ 0,0x975D,0x98C3,0x98C5,0x8DEC,0x98C6,0x9B43, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x98CE, 0, 0, 0, 0, 0,0x98D1,
+0x98CF, 0, 0,0x89C0, 0,0x95B9,0x98C9, 0,
+ 0, 0, 0,0x98CD,0x8CF1, 0, 0,0x8E67,
+ 0, 0, 0,0x8AA4, 0, 0,0x98D2, 0,
+0x98CA, 0, 0,0x97E1, 0,0x8E98, 0,0x98CB,
+ 0,0x98D0, 0, 0, 0, 0,0x98D3, 0,
+0x98CC, 0, 0,0x8B9F, 0,0x88CB, 0, 0,
+0x8BA0,0x89BF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9B44, 0,0x9699,0x958E,0x8CF2,
+ 0, 0, 0, 0, 0,0x904E,0x97B5, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x95D6,
+ 0, 0,0x8C57,0x91A3,0x89E2, 0, 0, 0,
+ 0, 0,0x8F72, 0, 0, 0,0x98D7, 0,
+0x98DC,0x98DA, 0, 0,0x98D5, 0, 0,0x91AD,
+0x98D8, 0,0x98DB,0x98D9, 0,0x95DB, 0,0x98D6,
+ 0,0x904D, 0,0x9693,0x98DD,0x98DE, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8F43,0x98EB,
+ 0, 0, 0,0x946F, 0,0x9555,0x98E6, 0,
+0x95EE, 0,0x89B4, 0, 0, 0,0x98EA, 0,
+ 0, 0, 0, 0, 0,0x98E4,0x98ED, 0,
+ 0,0x9171, 0,0x8CC2, 0,0x947B, 0,0xE0C5,
+ 0,0x98EC,0x937C, 0,0x98E1, 0,0x8CF4, 0,
+ 0,0x8CF3,0x98DF, 0, 0, 0, 0,0x8ED8,
+ 0,0x98E7, 0,0x95ED,0x926C,0x98E3,0x8C91, 0,
+0x98E0,0x98E8,0x98E2,0x97CF,0x98E9,0x9860, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8BE4, 0,
+ 0,0x8C90, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x98EE, 0, 0, 0,0x98EF,
+0x98F3,0x88CC, 0, 0, 0, 0, 0,0x95CE,
+0x98F2, 0, 0, 0, 0,0x98F1,0x98F5, 0,
+ 0, 0,0x98F4, 0,0x92E2, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x8C92, 0, 0,
+ 0, 0, 0, 0,0x98F6, 0, 0, 0,
+ 0, 0,0x8EC3, 0,0x91A4,0x92E3,0x8BF4, 0,
+0x98F7, 0, 0, 0, 0,0x8B55, 0, 0,
+0x98F8, 0, 0, 0, 0,0x98FA, 0, 0,
+ 0, 0, 0, 0, 0,0x9654, 0, 0,
+ 0,0x8C86, 0, 0, 0, 0, 0, 0,
+0x8E50,0x94F5,0x98F9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8DC3,0x9762, 0, 0,
+ 0, 0,0x98FC,0x9942,0x98FB,0x8DC2, 0,0x8F9D,
+ 0, 0, 0, 0, 0, 0,0x8C58, 0,
+ 0, 0,0x9943, 0, 0,0x8BCD, 0, 0,
+ 0,0x9940,0x9941, 0, 0,0x93AD, 0,0x919C,
+ 0,0x8BA1, 0, 0, 0,0x966C,0x9944, 0,
+ 0, 0,0x97BB, 0, 0, 0,0x9945, 0,
+ 0, 0, 0,0x9948, 0,0x9946, 0,0x916D,
+ 0, 0, 0, 0, 0,0x9947,0x9949, 0,
+ 0, 0, 0, 0, 0,0x994B, 0, 0,
+ 0,0x994A, 0,0x95C6, 0, 0, 0, 0,
+0x8B56,0x994D,0x994E, 0,0x89AD, 0, 0, 0,
+ 0,0x994C, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8EF2, 0,0x9951,0x9950,0x994F, 0,
+0x98D4, 0,0x9952, 0, 0, 0, 0,0x8F9E,
+ 0,0x9953, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9744, 0, 0, 0, 0, 0,
+ 0, 0,0x96D7, 0, 0, 0, 0,0x9955,
+ 0, 0,0x9954,0x9957,0x9956, 0, 0,0x9958,
+0x9959,0x88F2, 0,0x8CB3,0x8C5A,0x8F5B,0x929B,0x8BA2,
+0x90E6,0x8CF5, 0,0x8D8E,0x995B,0x96C6,0x9365, 0,
+0x8E99, 0,0x995A, 0,0x995C, 0, 0, 0,
+ 0, 0,0x937D, 0,0x8A95, 0, 0, 0,
+ 0, 0,0x995D, 0, 0,0x93FC, 0, 0,
+0x9153,0x995F,0x9960,0x94AA,0x8CF6,0x985A,0x9961, 0,
+ 0,0x8BA4, 0, 0, 0,0x95BA,0x91B4,0x8BEF,
+0x9354, 0, 0, 0,0x8C93, 0, 0, 0,
+0x9962, 0,0x9963, 0, 0,0x93E0,0x897E, 0,
+ 0,0x9966,0x8DFB, 0,0x9965,0x8DC4, 0,0x9967,
+0xE3EC,0x9968,0x9660,0x9969, 0,0x996A,0x996B,0x8FE7,
+ 0,0x8ECA, 0, 0, 0, 0, 0, 0,
+0x8AA5, 0,0x996E, 0,0x996C,0x96BB,0x996D, 0,
+0x9579,0x996F,0x9970,0x9971,0x937E, 0, 0, 0,
+0x9975,0x9973,0x9974,0x9972,0x8DE1,0x9976,0x96E8,0x97E2,
+ 0, 0, 0, 0, 0,0x9977, 0, 0,
+ 0, 0, 0, 0,0x90A6,0x9978,0x8F79, 0,
+ 0,0x9979, 0,0x929C,0x97BD,0x9380, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x99C3, 0,
+ 0, 0, 0,0x997A,0xEAA3,0x8BC3, 0, 0,
+0x997B,0x967D, 0, 0, 0, 0,0x8F88,0x91FA,
+ 0,0x997D,0x93E2, 0, 0,0x997E, 0, 0,
+0x9980,0x8A4D, 0, 0, 0,0x9981,0x8BA5, 0,
+0x93CA,0x899A,0x8F6F, 0, 0,0x949F,0x9982, 0,
+0x9381, 0, 0,0x906E,0x9983, 0,0x95AA,0x90D8,
+0x8AA0, 0,0x8AA7,0x9984, 0, 0,0x9986, 0,
+ 0,0x8C59, 0, 0,0x9985, 0, 0,0x97F1,
+ 0, 0, 0, 0, 0,0x8F89, 0, 0,
+ 0, 0, 0, 0,0x94BB,0x95CA, 0,0x9987,
+ 0,0x9798,0x9988, 0, 0, 0,0x9989, 0,
+0x939E, 0, 0,0x998A, 0, 0,0x90A7,0x8DFC,
+0x8C94,0x998B,0x8E68,0x8D8F, 0, 0, 0, 0,
+ 0, 0, 0,0x92E4,0x998D, 0, 0,0x91A5,
+ 0, 0,0x8DED,0x998E,0x998F,0x914F, 0,0x998C,
+ 0, 0, 0, 0,0x9991, 0,0x9655, 0,
+ 0, 0, 0,0x8D84, 0, 0,0x9990, 0,
+ 0, 0, 0,0x8C95,0x8DDC,0x948D, 0, 0,
+ 0,0x9994,0x9992, 0, 0, 0, 0,0x959B,
+0x8FE8,0x999B,0x8A84,0x9995,0x9993,0x916E, 0, 0,
+ 0, 0, 0, 0, 0,0x9997, 0,0x9996,
+ 0, 0, 0,0x8A63, 0, 0, 0,0x8C80,
+0x999C,0x97AB, 0, 0, 0,0x9998, 0, 0,
+ 0,0x999D,0x999A, 0,0x9999, 0, 0, 0,
+ 0, 0, 0,0x97CD, 0, 0, 0,0x8CF7,
+0x89C1, 0, 0,0x97F2, 0, 0, 0, 0,
+ 0,0x8F95,0x9377,0x8D85,0x99A0,0x99A1, 0, 0,
+ 0,0x97E3, 0, 0,0x984A,0x99A3, 0, 0,
+ 0,0x8CF8, 0, 0,0x99A2, 0,0x8A4E, 0,
+ 0,0x99A4, 0,0x9675, 0,0x92BA, 0,0x9745,
+ 0,0x95D7, 0, 0, 0,0x99A5, 0, 0,
+ 0, 0,0xE8D3, 0, 0,0x93AE, 0,0x99A6,
+0x8AA8,0x96B1, 0, 0, 0,0x8F9F,0x99A7,0x95E5,
+0x99AB, 0,0x90A8,0x99A8,0x8BCE, 0,0x99A9,0x8AA9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8C4D,0x99AC, 0,0x99AD, 0, 0,
+0x99AE,0x99AF,0x8ED9, 0, 0, 0,0x8CF9,0x96DC,
+ 0,0x96E6,0x93F5, 0, 0,0x95EF,0x99B0, 0,
+0x99B1, 0, 0, 0, 0,0x99B3, 0,0x99B5,
+0x99B4, 0, 0, 0, 0,0x99B6,0x89BB,0x966B,
+ 0,0x8DFA,0x99B7, 0, 0,0x9178, 0, 0,
+0x8FA0,0x8BA7, 0,0x99B8, 0, 0, 0, 0,
+ 0, 0,0x94D9, 0, 0, 0, 0,0x99B9,
+ 0,0x99BA, 0,0x99BB, 0, 0, 0, 0,
+0x99BC,0x9543,0x8BE6,0x88E3, 0, 0, 0,0x93BD,
+0x99BD,0x8F5C, 0,0x90E7, 0,0x99BF,0x99BE,0x8FA1,
+0x8CDF,0x99C1,0x94BC, 0, 0,0x99C2, 0, 0,
+ 0,0x94DA,0x91B2,0x91EC,0x8BA6, 0, 0,0x93EC,
+0x9250, 0,0x948E, 0,0x966D, 0,0x99C4, 0,
+0x90E8, 0, 0, 0, 0, 0,0x8C54, 0,
+ 0,0x99C5, 0, 0, 0, 0,0x99C6,0x894B,
+0x88F3,0x8AEB, 0,0x91A6,0x8B70,0x9791, 0,0x99C9,
+0x89B5, 0, 0,0x99C8, 0, 0, 0,0x8BA8,
+ 0, 0,0x99CA, 0,0x96EF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x99CB, 0,
+0x97D0, 0,0x8CFA, 0, 0, 0, 0,0x8CB4,
+0x99CC, 0, 0, 0, 0,0x99CE,0x99CD, 0,
+0x907E,0x8958, 0, 0, 0,0x897D,0x99CF, 0,
+0x99D0, 0, 0,0x8CB5, 0, 0,0x99D1, 0,
+ 0, 0, 0,0x8B8E, 0, 0, 0, 0,
+ 0, 0,0x8E51,0x99D2, 0, 0, 0, 0,
+0x9694,0x8DB3,0x8B79,0x9746,0x916F,0x94BD,0x8EFB, 0,
+ 0, 0, 0, 0,0x8F66, 0,0x8EE6,0x8EF3,
+ 0,0x8F96, 0,0x94BE, 0, 0, 0,0x99D5,
+ 0,0x8962,0x9170,0x8CFB,0x8CC3,0x8BE5, 0, 0,
+0x99D9,0x9240,0x91FC,0x8BA9,0x8FA2,0x99DA,0x99D8,0x89C2,
+0x91E4,0x8EB6,0x8E6A,0x8945, 0, 0,0x8A90,0x8D86,
+0x8E69, 0,0x99DB, 0, 0, 0, 0, 0,
+ 0,0x99DC, 0,0x8B68,0x8A65, 0, 0, 0,
+0x8D87,0x8B67,0x92DD,0x8944,0x93AF,0x96BC,0x8D40,0x9799,
+0x9366,0x8CFC, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8C4E, 0,0x99E5, 0,0x8BE1,
+0x9669, 0, 0, 0, 0, 0,0x94DB, 0,
+ 0,0x99E4, 0,0x8ADC,0x99DF,0x99E0,0x99E2, 0,
+ 0, 0, 0, 0, 0, 0,0x99E3, 0,
+0x8B7A,0x9081, 0,0x95AB,0x99E1,0x99DD,0x8CE1, 0,
+0x99DE, 0,0x9843, 0, 0, 0,0x95F0, 0,
+0x92E6,0x8CE0,0x8D90, 0, 0, 0,0x99E6, 0,
+ 0,0x93DB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x99EA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8EFC, 0,0x8EF4, 0, 0, 0, 0, 0,
+0x99ED,0x99EB, 0,0x96A1, 0,0x99E8,0x99F1,0x99EC,
+ 0, 0, 0,0x99EF,0x8CC4,0x96BD, 0, 0,
+0x99F0, 0, 0, 0,0x99F2, 0,0x99F4, 0,
+ 0, 0, 0,0x8DEE,0x9861, 0,0x99E9,0x99E7,
+0x99F3, 0,0x99EE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x99F6, 0,0x9A42,0x99F8, 0, 0,
+0x99FC, 0, 0,0x9A40,0x99F9, 0, 0,0x9A5D,
+ 0, 0,0x8DE7,0x8A50, 0, 0, 0, 0,
+0x99F7, 0, 0, 0,0x9A44,0x88F4,0x9A43, 0,
+0x88A3,0x9569,0x9A41, 0,0x99FA, 0, 0,0x99F5,
+0x99FB,0x8DC6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9A45, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x88F5,0x9A4E, 0, 0,0x9A46,0x9A47, 0,
+0x8FA3,0x9689, 0, 0, 0,0x9A4C,0x9A4B, 0,
+ 0, 0,0x934E, 0, 0, 0, 0, 0,
+ 0, 0,0x9A4D, 0, 0,0x9A4A, 0, 0,
+ 0, 0, 0, 0,0x8953, 0,0x8DB4,0x904F,
+ 0, 0, 0, 0, 0, 0, 0,0x9A48,
+0x9382, 0, 0, 0,0x9A49, 0,0x88A0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9A53,0x9742,
+ 0,0x8FA5, 0,0x9A59, 0, 0, 0, 0,
+0x9A58,0x9A4F, 0, 0, 0, 0,0x91C1, 0,
+0x9A50, 0, 0, 0,0x91ED,0x9A55,0x8FA4, 0,
+ 0, 0, 0, 0,0x9A52, 0, 0,0x96E2,
+ 0, 0, 0,0x8C5B, 0, 0,0x9A56,0x9A57,
+ 0, 0, 0, 0,0x9A54,0x9A5A, 0, 0,
+ 0, 0, 0,0x9A51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9A60,0x9A65, 0,0x9A61, 0,
+0x9A5C, 0, 0,0x9A66,0x9150, 0, 0,0x9A68,
+ 0,0x8D41,0x9A5E,0x929D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9A62,0x9A5B,0x8AAB, 0,0x8AEC,0x8A85,0x9A63,0x9A5F,
+ 0, 0, 0, 0, 0, 0, 0,0x8C96,
+0x9A69,0x9A67,0x9172,0x8B69,0x8BAA, 0,0x9A64, 0,
+0x8BF2, 0, 0, 0, 0, 0,0x8963, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9A6D,0x9A6B, 0,0x9AA5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9A70, 0, 0, 0,
+ 0, 0,0x9A6A, 0,0x9A6E, 0, 0,0x9A6C,
+ 0, 0, 0,0x8E6B,0x9A6F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9A72,
+ 0,0x9A77, 0, 0, 0,0x9A75,0x9A74, 0,
+ 0, 0, 0, 0, 0, 0,0x9251, 0,
+ 0,0x89C3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9A71, 0,0x9A73,0x8FA6,
+0x8952, 0, 0,0x9A76, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x89DC, 0, 0, 0, 0, 0,0x9A82,
+ 0,0x8FFA,0x9A7D, 0,0x9A7B, 0,0x9A7C, 0,
+0x9A7E, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x895C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9158, 0,0x9A78, 0,
+0x9A79, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8A9A, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9A81, 0, 0, 0,
+0x8AED, 0,0x9A84,0x9A80,0x9A83, 0, 0, 0,
+ 0, 0, 0, 0,0x95AC, 0, 0, 0,
+0x93D3, 0,0x94B6, 0, 0, 0, 0, 0,
+0x9A86, 0, 0, 0, 0, 0,0x9A85,0x8A64,
+ 0, 0,0x9A87, 0, 0, 0, 0,0x9A8A,
+ 0, 0, 0, 0,0x9A89, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9A88, 0,0x9458, 0, 0,0x9A8B, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9A8C, 0,
+ 0, 0, 0, 0,0x9A8E, 0,0x9A8D, 0,
+ 0, 0, 0, 0,0x9A90, 0, 0, 0,
+0x9A93,0x9A91,0x9A8F,0x9A92, 0, 0, 0, 0,
+0x9A94, 0, 0, 0, 0, 0,0x9A95, 0,
+ 0,0x9A96, 0,0x9A97, 0, 0, 0,0x9A98,
+0x9964, 0,0x8EFA,0x8E6C, 0, 0,0x89F1, 0,
+0x88F6, 0, 0,0x9263, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9A99, 0,
+0x8DA2, 0,0x88CD,0x907D, 0, 0, 0, 0,
+ 0,0x9A9A,0x8CC5, 0, 0,0x8D91, 0,0x9A9C,
+0x9A9B, 0, 0,0x95DE,0x9A9D, 0, 0, 0,
+0x9A9F,0x9A9E, 0,0x9AA0, 0,0x9AA1, 0,0x8C97,
+ 0, 0,0x8980,0x9AA2, 0, 0,0x9AA4, 0,
+0x9AA3, 0, 0, 0,0x9AA6, 0, 0,0x9379,
+ 0, 0, 0, 0, 0, 0,0x9AA7,0x88B3,
+0x8DDD, 0, 0, 0, 0,0x8C5C, 0, 0,
+0x926E, 0, 0, 0, 0, 0, 0,0x9AA8,
+0x9AA9, 0, 0,0x9AAB, 0, 0, 0, 0,
+0x9AAC, 0,0x8DE2, 0, 0, 0, 0,0x8BCF,
+ 0, 0,0x9656, 0, 0, 0,0x9AAA,0x9AAD,
+0x8DBF,0x8D42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9AB1, 0, 0,0x8DA3, 0,0x9252, 0,
+ 0,0x9AAE,0x92D8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9AB2,
+ 0, 0,0x9082, 0, 0, 0, 0, 0,
+0x9AB0,0x9AB3, 0,0x8C5E, 0, 0, 0, 0,
+ 0, 0, 0,0x9AB4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9AB5, 0,0x8D43,0x8A5F,0x9AB7, 0, 0, 0,
+ 0, 0,0x9AB8, 0, 0, 0, 0, 0,
+0x9AB9, 0, 0,0x9AB6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9AAF, 0, 0,0x9ABA, 0, 0,0x9ABB, 0,
+ 0, 0, 0,0x9684, 0, 0,0x8FE9, 0,
+ 0, 0,0x9ABD,0x9ABE,0x9ABC, 0,0x9AC0, 0,
+ 0, 0, 0, 0,0x9457, 0, 0,0x88E6,
+0x9575, 0, 0,0x9AC1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8FFB, 0, 0,0x8EB7,
+ 0,0x947C,0x8AEE, 0,0x8DE9, 0, 0, 0,
+0x9678, 0,0x93B0, 0, 0,0x8C98,0x91CD, 0,
+ 0, 0,0x9ABF,0x9AC2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x91C2, 0, 0,
+ 0,0x9AC3, 0, 0, 0,0x9AC4, 0, 0,
+ 0,0x9AC6, 0, 0,0x92E7, 0, 0, 0,
+ 0, 0,0x8AAC, 0, 0, 0, 0,0xEA9F,
+0x8981,0x95F1, 0, 0,0x8FEA,0x9367, 0, 0,
+ 0, 0,0x8DE4, 0, 0,0x9ACC, 0, 0,
+0x95BB,0x97DB, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x89F2,0x9AC8, 0, 0, 0, 0,
+ 0,0x9159,0x9ACB, 0,0x9383, 0, 0,0x9368,
+0x9384,0x94B7,0x92CB, 0, 0, 0,0x8DC7, 0,
+ 0, 0,0x9AC7, 0, 0, 0, 0, 0,
+ 0,0x8996, 0,0x9355, 0, 0, 0, 0,
+0x9AC9, 0,0x9AC5, 0, 0,0x906F, 0, 0,
+ 0,0x9ACD, 0, 0, 0, 0,0x8F6D, 0,
+ 0, 0, 0,0x8BAB, 0,0x9ACE, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x95E6, 0, 0, 0,0x919D,
+ 0, 0, 0, 0,0x92C4, 0, 0,0x9AD0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x966E, 0, 0,0x9AD1, 0, 0,0x9AD6, 0,
+ 0, 0, 0,0x95AD, 0, 0, 0, 0,
+0x9AD5,0x9ACF,0x9AD2,0x9AD4, 0, 0,0x8DA4, 0,
+ 0,0x95C7, 0, 0, 0,0x9AD7, 0,0x9264,
+ 0, 0,0x89F3, 0,0x8FEB, 0, 0, 0,
+ 0,0x9AD9, 0,0x9AD8, 0,0x8D88, 0,0x9ADA,
+0x9ADC,0x9ADB, 0, 0,0x9ADE, 0,0x9AD3,0x9AE0,
+ 0, 0, 0, 0,0x9ADF,0x9ADD, 0, 0,
+ 0, 0, 0,0x8E6D,0x9070, 0,0x9173,0x9AE1,
+0x90BA,0x88EB,0x9484, 0, 0, 0, 0,0x92D9,
+ 0,0x9AE3,0x9AE2,0x9AE4,0x9AE5,0x9AE6, 0, 0,
+ 0, 0,0x9AE7, 0, 0, 0, 0, 0,
+ 0,0x95CF,0x9AE8, 0, 0, 0, 0,0x89C4,
+0x9AE9, 0, 0, 0, 0,0x975B,0x8A4F, 0,
+0x99C7,0x8F67,0x91BD,0x9AEA,0x96E9, 0, 0, 0,
+ 0, 0,0x96B2, 0, 0,0x9AEC, 0,0x91E5,
+ 0,0x9356,0x91BE,0x9576,0x9AED,0x9AEE,0x899B, 0,
+ 0,0x8EB8,0x9AEF, 0, 0, 0, 0,0x88CE,
+0x9AF0, 0, 0, 0, 0, 0,0x9AF1, 0,
+ 0, 0, 0, 0,0x8982, 0, 0,0x8AEF,
+0x93DE,0x95F2, 0, 0, 0, 0,0x9AF5,0x9174,
+0x9AF4,0x8C5F, 0, 0,0x967A,0x9AF3, 0,0x9385,
+0x9AF7, 0,0x9AF6, 0, 0, 0, 0, 0,
+0x9AF9, 0,0x9AF8, 0, 0,0x899C, 0,0x9AFA,
+0x8FA7,0x9AFC,0x9244, 0,0x9AFB, 0,0x95B1, 0,
+ 0, 0, 0,0x8F97,0x937A, 0, 0, 0,
+0x9B40, 0, 0, 0, 0,0x8D44, 0, 0,
+ 0,0x9B41,0x9440,0x94DC,0x96CF, 0, 0, 0,
+ 0, 0,0x9444, 0, 0,0x9B4A, 0, 0,
+ 0, 0, 0,0x8B57, 0, 0,0x9764, 0,
+ 0,0x96AD, 0,0x9BAA, 0,0x9B42, 0, 0,
+ 0, 0, 0,0x9B45, 0,0x91C3, 0, 0,
+0x9657, 0, 0, 0,0x9369, 0, 0, 0,
+ 0, 0,0x9B46, 0, 0, 0, 0, 0,
+ 0,0x9685, 0,0x8DC8, 0, 0,0x8FA8, 0,
+ 0, 0, 0, 0, 0, 0,0x9B47, 0,
+ 0,0x8E6F, 0,0x8E6E, 0, 0, 0, 0,
+0x88B7,0x8CC6, 0,0x90A9,0x88CF, 0, 0, 0,
+ 0,0x9B4B,0x9B4C, 0,0x9B49, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x8957,0x8AAD, 0,
+0x9B48, 0,0x96C3,0x9550, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x88A6, 0,
+ 0, 0, 0,0x88F7, 0, 0, 0,0x8E70,
+ 0,0x88D0, 0,0x88A1, 0, 0, 0, 0,
+ 0,0x9B51, 0, 0, 0, 0, 0, 0,
+ 0,0x9B4F, 0, 0, 0, 0, 0, 0,
+0x96BA, 0,0x9B52, 0,0x9B50, 0, 0,0x9B4E,
+0x9050, 0, 0, 0, 0,0x9B4D, 0, 0,
+ 0,0x95D8, 0, 0, 0, 0, 0,0x8CE2,
+ 0, 0, 0, 0, 0,0x9B56,0x9B57, 0,
+ 0, 0, 0, 0,0x8FA9, 0, 0, 0,
+0x9B53,0x984B, 0, 0, 0, 0,0x946B, 0,
+ 0,0x9B55, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8DA5, 0, 0, 0, 0, 0,
+ 0, 0,0x9B58, 0, 0, 0,0x9577, 0,
+ 0, 0,0x9B59, 0,0x9B54, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x96B9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x947D, 0, 0, 0, 0, 0,
+ 0, 0,0x9B5A,0x9551, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9B5B,0x9B5F,0x9B5C, 0,
+ 0,0x89C5,0x9B5E, 0, 0, 0, 0, 0,
+ 0,0x8EB9, 0,0x9B5D,0x8C99, 0, 0, 0,
+0x9B6B, 0, 0, 0, 0, 0,0x9B64,0x9B61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9284, 0,0x9B60, 0, 0,0x9B62, 0,
+ 0,0x9B63, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9B65,0x9B66, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8AF0, 0,0x9B68,0x9B67, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9B69, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8FEC, 0, 0, 0, 0, 0,
+ 0, 0,0x9B6C, 0,0x92DA, 0, 0, 0,
+0x8964, 0,0x9B6A, 0, 0, 0,0x9B6D, 0,
+ 0, 0, 0, 0, 0, 0,0x9B6E, 0,
+0x9B71, 0, 0,0x9B6F, 0,0x9B70, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8E71,0x9B72, 0, 0,0x8D45,0x9B73, 0,0x8E9A,
+0x91B6, 0,0x9B74,0x9B75,0x8E79,0x8D46, 0,0x96D0,
+ 0, 0, 0,0x8B47,0x8CC7,0x9B76,0x8A77, 0,
+ 0,0x9B77, 0,0x91B7, 0, 0, 0, 0,
+0x9B78,0x9BA1, 0,0x9B79, 0,0x9B7A, 0, 0,
+0x9B7B, 0,0x9B7D, 0, 0, 0, 0, 0,
+0x9B7E, 0, 0,0x9B80, 0,0x91EE, 0,0x8946,
+0x8EE7,0x88C0, 0,0x9176,0x8AAE,0x8EB3, 0,0x8D47,
+ 0, 0, 0, 0, 0,0x9386, 0,0x8F40,
+0x8AAF,0x9288,0x92E8,0x88B6,0x8B58,0x95F3, 0,0x8EC0,
+ 0, 0,0x8B71,0x90E9,0x8EBA,0x9747,0x9B81, 0,
+ 0, 0, 0, 0, 0, 0,0x8B7B, 0,
+0x8DC9, 0, 0,0x8A51,0x8983,0x8FAA,0x89C6, 0,
+0x9B82,0x9765, 0, 0, 0, 0, 0,0x8F68,
+ 0, 0,0x8EE2,0x9B83,0x8AF1,0x93D0,0x96A7,0x9B84,
+ 0,0x9B85, 0, 0,0x9578, 0, 0, 0,
+0x9B87, 0,0x8AA6,0x8BF5,0x9B86, 0, 0, 0,
+ 0, 0, 0,0x8AB0, 0,0x9051,0x9B8B,0x8E40,
+ 0,0x89C7,0x9B8A, 0,0x9B88,0x9B8C,0x9B89,0x944A,
+0x9ECB,0x9052, 0,0x9B8D, 0, 0,0x97BE, 0,
+0x9B8E, 0, 0,0x9B90, 0,0x929E,0x9B8F, 0,
+0x90A1, 0,0x8E9B, 0, 0, 0,0x91CE,0x8EF5,
+ 0,0x9595,0x90EA, 0,0x8ECB,0x9B91,0x8FAB,0x9B92,
+0x9B93,0x88D1,0x91B8,0x9071, 0,0x9B94,0x93B1,0x8FAC,
+ 0,0x8FAD, 0,0x9B95, 0, 0,0x90EB, 0,
+ 0, 0,0x8FAE, 0, 0, 0, 0, 0,
+0x9B96, 0,0x9B97, 0,0x96DE, 0, 0, 0,
+0x9B98, 0, 0, 0, 0,0x8BC4, 0, 0,
+ 0,0x8F41, 0, 0, 0, 0, 0, 0,
+0x9B99,0x9B9A,0x8EDA,0x904B,0x93F2,0x9073,0x94F6,0x9441,
+0x8BC7,0x9B9B, 0, 0, 0,0x8B8F,0x9B9C, 0,
+0x8BFC, 0,0x93CD,0x89AE, 0,0x8E72,0x9B9D,0x9BA0,
+0x9B9F,0x8BFB, 0,0x9B9E, 0,0x9357, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x91AE, 0,
+0x936A,0x8EC6, 0, 0,0x9177,0x979A, 0, 0,
+ 0, 0, 0, 0,0x9BA2, 0,0x9BA3,0x93D4,
+ 0,0x8E52, 0, 0, 0, 0,0x9BA5, 0,
+ 0,0x9BA6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9BA7, 0, 0, 0,
+0x8AF2,0x9BA8, 0, 0,0x9BA9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x89AA, 0, 0, 0, 0, 0, 0,
+0x915A,0x8AE2, 0,0x9BAB,0x96A6, 0, 0, 0,
+ 0,0x91D0, 0,0x8A78, 0, 0,0x9BAD,0x9BAF,
+0x8ADD, 0, 0,0x9BAC,0x9BAE, 0,0x9BB1, 0,
+ 0, 0, 0, 0, 0,0x9BB0, 0,0x9BB2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9BB3, 0, 0, 0, 0, 0, 0,
+0x93BB,0x8BAC, 0, 0, 0, 0, 0, 0,
+0x89E3,0x9BB4,0x9BB9, 0, 0,0x9BB7, 0,0x95F5,
+0x95F4, 0, 0, 0, 0, 0,0x9387, 0,
+ 0, 0,0x9BB6,0x8F73, 0,0x9BB5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9092,
+ 0, 0, 0,0x9BBA, 0, 0,0x8DE8, 0,
+ 0,0x9BC0, 0, 0,0x9BC1,0x9BBB,0x8A52,0x9BBC,
+0x9BC5,0x9BC4,0x9BC3,0x9BBF, 0, 0, 0,0x9BBE,
+ 0, 0,0x9BC2, 0, 0, 0, 0, 0,
+ 0,0x95F6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9BC9,0x9BC6, 0,0x9BC8, 0,
+0x9792, 0,0x9BC7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9BBD, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9093, 0, 0,0x9BCA, 0, 0,0x8DB5,
+ 0, 0, 0,0x9BCB, 0, 0,0x9BCC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9BCF, 0,0x9BCE, 0, 0,0x9BCD,
+ 0, 0, 0,0x9388,0x9BB8, 0, 0, 0,
+0x9BD5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9BD1, 0, 0,
+ 0, 0,0x9BD0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9BD2, 0,0x9BD3, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9BD6,
+ 0, 0,0x97E4, 0,0x9BD7,0x9BD4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9BD8, 0, 0,0x8ADE,0x9BD9, 0, 0,
+ 0, 0,0x9BDB,0x9BDA, 0, 0,0x9BDC, 0,
+ 0, 0, 0,0x9BDD, 0,0x90EC,0x8F42, 0,
+ 0,0x8F84, 0,0x9183, 0,0x8D48,0x8DB6,0x8D49,
+0x8B90, 0, 0,0x9BDE, 0, 0,0x8DB7, 0,
+ 0,0x8CC8,0x9BDF,0x96A4,0x9462,0x9BE0, 0,0x8D4A,
+ 0, 0, 0,0x8AAA, 0,0x9246,0x8BD0, 0,
+ 0, 0,0x8E73,0x957A, 0, 0,0x94BF, 0,
+ 0, 0, 0,0x9BE1,0x8AF3, 0, 0, 0,
+ 0,0x9BE4, 0, 0, 0, 0,0x929F, 0,
+ 0,0x9BE3,0x9BE2,0x9BE5, 0,0x92E9, 0, 0,
+ 0, 0, 0, 0, 0,0x9083, 0, 0,
+ 0, 0, 0,0x8E74, 0,0x90C8, 0,0x91D1,
+0x8B41, 0, 0,0x92A0, 0, 0,0x9BE6,0x9BE7,
+0x8FED, 0, 0, 0, 0,0x9658, 0, 0,
+0x9BEA, 0, 0,0x9BE9,0x9BE8,0x959D, 0,0x9BF1,
+ 0, 0, 0, 0,0x9679, 0,0x9BEB, 0,
+ 0, 0, 0, 0,0x9BED,0x968B, 0,0x9BEC,
+ 0, 0, 0, 0, 0, 0, 0,0x9BEE,
+ 0,0x94A6,0x9BEF,0x95BC,0x9BF0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8AB1,0x95BD,0x944E,0x9BF2,0x9BF3, 0,
+0x8D4B,0x8AB2,0x9BF4,0x8CB6,0x9763,0x9748,0x8AF4,0x9BF6,
+ 0,0x92A1, 0,0x8D4C,0x8FAF, 0, 0,0x94DD,
+ 0, 0,0x8FB0, 0, 0, 0, 0,0x8F98,
+ 0, 0, 0, 0, 0,0x92EA,0x95F7,0x9358,
+ 0, 0,0x8D4D, 0,0x957B, 0, 0, 0,
+0x9BF7, 0, 0, 0, 0, 0,0x9378,0x8DC0,
+ 0, 0, 0,0x8CC9, 0,0x92EB, 0, 0,
+ 0, 0, 0, 0, 0,0x88C1,0x8F8E,0x8D4E,
+0x9766, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9BF8,0x9BF9,0x9470, 0, 0, 0, 0,
+0x9BFA,0x97F5,0x984C, 0, 0, 0, 0,0x9BFC,
+0x9BFB, 0, 0,0x8A66, 0, 0,0x9C40, 0,
+ 0, 0,0x9C43,0x9C44, 0,0x9C42, 0,0x955F,
+0x8FB1,0x9C46,0x9C45,0x9C41, 0, 0, 0, 0,
+0x9C47,0x9C48, 0, 0,0x9C49, 0, 0, 0,
+0x9C4C,0x9C4A, 0,0x9C4B,0x9C4D, 0,0x8984,0x92EC,
+0x9C4E, 0,0x8C9A,0x89F4,0x9455, 0,0x9C4F,0x93F9,
+ 0,0x95D9, 0,0x9C50,0x984D, 0, 0, 0,
+ 0,0x9C51,0x95BE,0x9C54,0x989F,0x98AF, 0,0x8EAE,
+0x93F3,0x9C55, 0,0x8B7C,0x92A2,0x88F8,0x9C56,0x95A4,
+0x8D4F, 0, 0,0x926F, 0, 0, 0,0x92ED,
+ 0, 0, 0, 0, 0,0x96ED,0x8CB7,0x8CCA,
+ 0,0x9C57, 0, 0, 0,0x9C58, 0,0x9C5E,
+ 0,0x8EE3, 0, 0, 0,0x92A3, 0,0x8BAD,
+0x9C59, 0, 0, 0,0x954A, 0,0x9265, 0,
+ 0,0x9C5A, 0, 0, 0, 0, 0, 0,
+0x9C5B, 0,0x8BAE, 0,0x9C5C, 0,0x9C5D, 0,
+ 0,0x9C5F, 0,0x9396, 0, 0,0x9C60,0x9C61,
+ 0,0x9C62, 0, 0,0x9C53,0x9C52, 0, 0,
+ 0,0x9C63,0x8C60, 0, 0, 0,0x9546, 0,
+ 0,0x8DCA,0x9556,0x92A4,0x956A,0x9C64, 0, 0,
+0x8FB2,0x8965, 0,0x9C65, 0, 0, 0,0x9C66,
+ 0,0x96F0, 0, 0,0x94DE, 0, 0,0x9C69,
+0x899D,0x90AA,0x9C68,0x9C67,0x8C61,0x91D2, 0,0x9C6D,
+0x9C6B, 0,0x9C6A,0x97A5,0x8CE3, 0, 0, 0,
+0x8F99,0x9C6C,0x936B,0x8F5D, 0, 0, 0,0x93BE,
+0x9C70,0x9C6F, 0, 0, 0, 0,0x9C6E, 0,
+0x9C71,0x8CE4, 0, 0, 0, 0, 0, 0,
+0x9C72,0x959C,0x8F7A, 0, 0,0x9C73,0x94F7, 0,
+ 0, 0, 0,0x93BF,0x92A5, 0, 0, 0,
+ 0,0x934F, 0, 0,0x9C74,0x8B4A, 0, 0,
+ 0, 0, 0,0x9053, 0,0x954B, 0, 0,
+ 0, 0, 0, 0,0x8AF5,0x9445, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9C75,0x8E75,
+0x9659,0x965A, 0, 0,0x899E,0x9C7A, 0, 0,
+0x9289, 0, 0, 0,0x9C77, 0, 0, 0,
+ 0, 0, 0,0x89F5, 0, 0, 0, 0,
+0x9CAB,0x9C79, 0, 0, 0,0x944F, 0, 0,
+0x9C78, 0, 0,0x9C76, 0,0x8D9A, 0,0x9C7C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9C83,0x9C89,
+0x9C81, 0,0x937B, 0, 0,0x9C86,0x957C, 0,
+ 0,0x9C80, 0,0x9C85,0x97E5,0x8E76, 0, 0,
+0x91D3,0x9C7D, 0, 0, 0,0x8B7D,0x9C88,0x90AB,
+0x8985,0x9C82,0x89F6,0x9C87, 0, 0, 0,0x8BAF,
+ 0,0x9C84, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9C8A, 0, 0, 0, 0, 0,
+ 0,0x9C8C,0x9C96,0x9C94, 0, 0,0x9C91, 0,
+ 0, 0,0x9C90,0x97F6, 0,0x9C92, 0, 0,
+0x8BB0, 0,0x8D50, 0, 0,0x8F9A, 0, 0,
+ 0,0x9C99,0x9C8B, 0, 0, 0, 0,0x9C8F,
+0x9C7E, 0,0x89F8,0x9C93,0x9C95,0x9270, 0, 0,
+0x8DA6,0x89B6,0x9C8D,0x9C98,0x9C97,0x8BB1, 0,0x91A7,
+0x8A86, 0, 0, 0, 0,0x8C62, 0,0x9C8E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9C9A, 0,0x9C9D,0x9C9F, 0, 0, 0,
+ 0,0x8EBB, 0,0x9CA5,0x92EE,0x9C9B, 0, 0,
+ 0, 0,0x9CA3, 0,0x89F7, 0,0x9CA1,0x9CA2,
+ 0, 0,0x9C9E,0x9CA0, 0, 0, 0,0x8CE5,
+0x9749, 0, 0,0x8AB3, 0, 0,0x8978,0x9CA4,
+ 0,0x9459,0x88AB, 0, 0, 0, 0, 0,
+ 0, 0,0x94DF,0x9C7B,0x9CAA,0x9CAE,0x96E3, 0,
+0x9CA7, 0, 0, 0,0x9389,0x9CAC, 0, 0,
+ 0, 0, 0, 0, 0,0x8FEE,0x9CAD,0x93D5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9866, 0,0x9CA9, 0, 0, 0, 0,
+0x9CAF, 0,0x8D9B, 0,0x90C9, 0, 0,0x88D2,
+0x9CA8,0x9CA6, 0,0x9179, 0, 0, 0,0x9C9C,
+0x8E53, 0, 0, 0, 0, 0, 0, 0,
+0x91C4,0x9CBB, 0,0x917A,0x9CB6, 0,0x9CB3,0x9CB4,
+ 0,0x8EE4,0x9CB7,0x9CBA, 0, 0, 0, 0,
+0x9CB5,0x8F44, 0,0x9CB8, 0, 0,0x9CB2, 0,
+0x96FA,0x96F9, 0, 0, 0,0x9CBC,0x9CBD,0x88D3,
+ 0, 0, 0, 0, 0,0x9CB1, 0, 0,
+ 0, 0,0x8BF0,0x88A4, 0, 0, 0,0x8AB4,
+ 0,0x9CB9, 0, 0, 0, 0, 0,0x9CC1,
+0x9CC0, 0, 0, 0,0x9CC5, 0, 0, 0,
+ 0, 0, 0, 0,0x9CC6, 0, 0, 0,
+ 0, 0, 0, 0,0x9CC4,0x9CC7,0x9CBF,0x9CC3,
+ 0, 0,0x9CC8, 0,0x9CC9, 0, 0,0x9CBE,
+0x8E9C, 0,0x9CC2,0x91D4,0x8D51,0x9CB0,0x9054, 0,
+ 0, 0, 0,0x9CD6, 0,0x95E7, 0, 0,
+0x9CCC,0x9CCD,0x9CCE, 0, 0,0x9CD5, 0,0x9CD4,
+ 0, 0,0x969D,0x8AB5, 0,0x9CD2, 0,0x8C64,
+0x8A53, 0, 0,0x9CCF, 0, 0,0x97B6,0x9CD1,
+0x88D4,0x9CD3, 0,0x9CCA,0x9CD0,0x9CD7,0x8C63,0x9CCB,
+ 0, 0, 0, 0, 0, 0,0x977C, 0,
+ 0, 0,0x974A, 0, 0, 0, 0,0x9CDA,
+ 0, 0,0x9CDE, 0, 0, 0,0x919E, 0,
+0x97F7,0x9CDF, 0, 0,0x9CDC, 0,0x9CD9, 0,
+ 0,0x9CD8,0x9CDD, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x95AE, 0, 0,0x93B2,
+ 0,0x8C65, 0,0x9CE0,0x9CDB, 0,0x9CE1, 0,
+ 0, 0,0x8C9B, 0, 0, 0,0x89AF, 0,
+ 0, 0,0x9CE9, 0, 0, 0,0x8AB6, 0,
+ 0, 0, 0,0x9CE7, 0, 0,0x9CE8,0x8DA7,
+0x9CE6,0x9CE4,0x9CE3,0x9CEA,0x9CE2,0x9CEC, 0, 0,
+0x89F9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9CEE, 0, 0,0x9CED, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x92A6, 0,0x9CF1, 0,0x9CEF,0x9CE5,
+0x8C9C, 0,0x9CF0, 0,0x9CF4,0x9CF3,0x9CF5,0x9CF2,
+0x9CF6, 0, 0, 0, 0, 0, 0, 0,
+0x9CF7,0x9CF8,0x95E8, 0,0x9CFA,0x9CF9,0x8F5E, 0,
+0x90AC,0x89E4,0x89FA, 0,0x9CFB, 0,0x88BD, 0,
+ 0, 0,0x90CA,0x9CFC, 0,0xE6C1,0x9D40,0x8C81,
+ 0,0x9D41, 0, 0, 0, 0,0x90ED, 0,
+ 0, 0,0x9D42, 0, 0, 0,0x9D43,0x8B59,
+0x9D44, 0,0x9D45,0x9D46,0x91D5, 0, 0, 0,
+0x8CCB, 0, 0,0x96DF, 0, 0, 0,0x965B,
+0x8F8A,0x9D47, 0, 0, 0, 0, 0,0x90EE,
+0xE7BB,0x94E0, 0,0x8EE8, 0,0x8DCB,0x9D48, 0,
+ 0, 0, 0,0x91C5, 0,0x95A5, 0, 0,
+0x91EF, 0, 0,0x9D4B, 0, 0,0x9D49, 0,
+0x9D4C, 0, 0,0x9D4A, 0, 0, 0, 0,
+0x9D4D, 0, 0, 0, 0, 0,0x95AF, 0,
+ 0,0x88B5, 0, 0, 0, 0,0x957D, 0,
+ 0,0x94E1, 0, 0,0x9D4E, 0,0x9D51,0x8FB3,
+0x8B5A, 0,0x9D4F,0x9D56,0x8FB4, 0, 0, 0,
+ 0,0x9D50,0x9463, 0, 0, 0, 0, 0,
+ 0,0x977D,0x9D52,0x9D53,0x9D57,0x938A,0x9D54,0x8D52,
+0x90DC, 0, 0,0x9D65,0x94B2, 0,0x91F0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x94E2,0x9DAB, 0, 0, 0,
+ 0,0x95F8, 0, 0, 0,0x92EF, 0, 0,
+ 0,0x9695, 0,0x9D5A,0x899F,0x928A, 0, 0,
+ 0, 0,0x9D63, 0, 0,0x9253,0x9D5D,0x9D64,
+0x9D5F,0x9D66,0x9D62, 0,0x9D61,0x948F, 0,0x9D5B,
+0x89FB,0x9D59,0x8B91,0x91F1,0x9D55, 0, 0,0x9D58,
+0x8D53,0x90D9, 0,0x8FB5,0x9D60,0x9471, 0, 0,
+0x8B92,0x8A67, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8A87,0x9040,0x9D68,0x9D6D,
+ 0,0x9D69, 0,0x8C9D, 0,0x9D6E,0x8E41,0x8D89,
+ 0, 0, 0, 0, 0, 0,0x8F45,0x9D5C,
+ 0,0x8E9D,0x9D6B, 0, 0, 0, 0,0x8E77,
+0x9D6C,0x88C2, 0, 0,0x9D67, 0, 0, 0,
+ 0,0x92A7, 0, 0, 0, 0, 0, 0,
+ 0,0x8B93, 0, 0, 0, 0, 0,0x8BB2,
+ 0, 0, 0, 0, 0, 0, 0,0x9D6A,
+0x88A5, 0, 0,0x8DC1, 0, 0, 0,0x9055,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x92F0, 0, 0,0x94D2,0x9D70,0x917D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x91A8, 0, 0,0x8E4A,0x9D71, 0,0x9D73,
+0x9D6F, 0, 0, 0, 0,0x95DF, 0,0x92BB,
+ 0, 0, 0, 0,0x917B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x95F9,
+0x8ECC,0x9D80, 0,0x9D7E, 0, 0,0x9098, 0,
+ 0, 0,0x8C9E, 0, 0, 0,0x9D78,0x8FB7,
+ 0, 0,0x93E6,0x9450, 0, 0, 0, 0,
+0x9D76, 0, 0,0x917C, 0, 0, 0, 0,
+0x8EF6,0x9D7B, 0, 0,0x8FB6, 0,0x9D75,0x9D7A,
+ 0, 0,0x9472, 0, 0, 0,0x9D74, 0,
+0x8C40, 0, 0,0x8A7C, 0, 0, 0,0x9D7C,
+0x97A9,0x8DCC,0x9254,0x9D79, 0,0x90DA, 0,0x8D54,
+0x9084,0x8986,0x915B,0x9D77,0x8B64, 0, 0, 0,
+ 0, 0,0x8C66, 0,0x92CD,0x9D7D, 0, 0,
+ 0, 0, 0,0x917E, 0, 0,0x9D81, 0,
+0x9D83, 0, 0,0x91B5,0x9D89, 0,0x9D84, 0,
+ 0,0x9D86, 0, 0, 0, 0, 0,0x9560,
+0x92F1, 0,0x9D87, 0, 0, 0,0x974B, 0,
+ 0, 0,0x9767,0x8AB7, 0, 0, 0, 0,
+ 0,0x88AC, 0,0x9D85, 0, 0, 0, 0,
+ 0,0x9D82, 0, 0, 0, 0,0x8AF6, 0,
+ 0, 0, 0, 0,0x8987, 0,0x9D88, 0,
+ 0, 0,0x9768, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9D8C, 0,
+ 0, 0, 0, 0, 0,0x91B9, 0,0x9D93,
+ 0, 0, 0,0x9D8D, 0, 0,0x9D8A,0x9D91,
+ 0, 0, 0, 0,0x9D72, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9D8E, 0,
+0x9D92, 0, 0, 0,0x94C0,0x938B, 0, 0,
+ 0, 0, 0, 0,0x9D8B, 0,0x9D8F, 0,
+ 0, 0,0x8C67, 0, 0, 0,0x8DEF, 0,
+ 0, 0,0x90DB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9D97, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9345, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9D94,
+ 0,0x9680, 0, 0, 0, 0, 0,0x9D95,
+ 0, 0, 0, 0, 0, 0,0x9D96, 0,
+0x96CC, 0,0x90A0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8C82, 0, 0, 0, 0,
+0x9D9D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8E54,0x9D9A, 0,0x9D99, 0, 0,
+ 0, 0,0x9451, 0, 0, 0,0x93B3, 0,
+ 0, 0, 0, 0,0x9350,0x9D9B, 0, 0,
+ 0,0x9D9C, 0,0x958F, 0,0x9464,0x8E42, 0,
+0x90EF, 0,0x966F, 0, 0, 0, 0, 0,
+ 0,0x8A68, 0,0x9DA3,0x9D9E, 0, 0, 0,
+ 0,0x9769,0x9DA5, 0, 0,0x9DA1, 0,0x9DA2,
+ 0, 0, 0, 0, 0,0x9180, 0, 0,
+ 0, 0,0x9DA0, 0,0x9D5E, 0, 0, 0,
+0x9DA4, 0,0x9D9F, 0, 0, 0, 0, 0,
+0x9DA9,0x9DAA,0x9346,0x9DAC, 0, 0,0x8E43,0x9DA7,
+ 0, 0, 0, 0,0x8B5B, 0, 0,0x9DAD,
+ 0,0x9DA6,0x9DB1, 0,0x9DB0, 0,0x9DAF, 0,
+ 0, 0,0x9DB2, 0, 0,0x9DB4,0x8FEF, 0,
+0x9DB3, 0, 0, 0, 0,0x9DB7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9DB5, 0, 0, 0,0x9DB6,0x9D90, 0, 0,
+ 0, 0, 0,0x9DB9,0x9DB8, 0, 0, 0,
+ 0, 0,0x9D98,0x9DBA,0x9DAE, 0, 0,0x8E78,
+ 0, 0, 0, 0,0x9DBB,0x9DBC,0x9DBE,0x9DBD,
+0x9DBF,0x89FC, 0,0x8D55, 0, 0,0x95FA,0x90AD,
+ 0, 0, 0, 0, 0,0x8CCC, 0, 0,
+0x9DC1, 0, 0, 0, 0,0x9DC4, 0,0x9571,
+ 0,0x8B7E, 0, 0, 0,0x9DC3,0x9DC2,0x9473,
+0x9DC5,0x8BB3, 0, 0, 0,0x9DC7,0x9DC6, 0,
+ 0, 0,0x8AB8,0x8E55, 0, 0,0x93D6, 0,
+ 0, 0, 0, 0,0x8C68, 0, 0, 0,
+0x9094, 0,0x9DC8, 0,0x90AE,0x9347, 0,0x957E,
+0x9DC9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9DCA,0x9DCB, 0, 0, 0,0x95B6,
+0x9B7C,0x90C4, 0, 0,0x956B, 0,0x8DD6, 0,
+0x94E3,0x94C1, 0, 0, 0, 0, 0,0x936C,
+ 0,0x97BF, 0,0x9DCD,0x8ECE, 0, 0,0x9DCE,
+ 0,0x88B4, 0, 0,0x8BD2,0x90CB, 0,0x9580,
+ 0, 0, 0,0x9DCF,0x8E61,0x9266, 0,0x8E7A,
+0x9056, 0, 0, 0, 0, 0, 0,0x9DD0,
+ 0,0x95FB, 0, 0,0x8997,0x8E7B, 0, 0,
+ 0,0x9DD3, 0,0x9DD1,0x9DD4,0x97B7,0x9DD2, 0,
+ 0, 0, 0,0x90F9,0x9DD5, 0, 0,0x91B0,
+ 0, 0,0x9DD6, 0, 0, 0, 0,0x8AF8,
+ 0,0x9DD8, 0,0x9DD7, 0, 0, 0, 0,
+0x9DD9,0x9DDA,0x8AF9, 0, 0,0x93FA,0x9255,0x8B8C,
+0x8E7C,0x9181, 0, 0,0x8F7B,0x88AE, 0, 0,
+ 0,0x9DDB, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x89A0,0x9DDF, 0, 0, 0, 0,
+ 0, 0,0x8D56,0x9DDE, 0, 0,0x8DA9,0x8FB8,
+ 0, 0,0x9DDD, 0,0x8FB9, 0,0x96BE,0x8DA8,
+ 0, 0, 0,0x88D5,0x90CC, 0, 0, 0,
+ 0, 0, 0, 0,0x9DE4, 0, 0,0x90AF,
+0x8966, 0, 0, 0, 0,0x8F74, 0,0x9686,
+0x8DF0, 0, 0, 0, 0,0x8FBA, 0,0x90A5,
+ 0, 0, 0, 0,0x9DE3,0x9DE1,0x9DE2, 0,
+ 0, 0, 0, 0,0x928B, 0, 0,0x9E45,
+ 0,0x9DE8,0x8E9E,0x8D57,0x9DE6, 0, 0, 0,
+ 0,0x9DE7, 0,0x9057, 0, 0, 0,0x9DE5,
+ 0, 0,0x8E4E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9DEA,0x9DE9,0x9DEE,
+ 0, 0,0x9DEF, 0,0x9DEB, 0,0x8A41,0x9DEC,
+0x9DED,0x94D3, 0, 0, 0, 0,0x9581,0x8C69,
+0x9DF0, 0, 0, 0,0x90B0, 0,0x8FBB, 0,
+ 0, 0,0x9271, 0, 0, 0, 0, 0,
+ 0,0x8BC5, 0,0x9DF1,0x9DF5, 0, 0,0x89C9,
+0x9DF2,0x9DF4, 0, 0, 0, 0,0x9DF3, 0,
+ 0,0x8F8B, 0, 0, 0, 0,0x9267,0x88C3,
+0x9DF6, 0, 0, 0, 0,0x9DF7, 0, 0,
+ 0, 0,0x92A8, 0, 0, 0,0x97EF, 0,
+ 0, 0, 0,0x8E62, 0, 0,0x95E9, 0,
+ 0, 0, 0, 0,0x965C, 0, 0, 0,
+0x9E41,0x9DF9, 0, 0,0x9DFC, 0,0x9DFB, 0,
+ 0,0x9DF8, 0, 0,0x9E40, 0, 0,0x93DC,
+ 0,0x9DFA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9E42, 0,
+ 0,0x8F8C,0x9E43, 0,0x976A,0x9498, 0, 0,
+0x9E44, 0, 0, 0, 0, 0,0x9E46, 0,
+ 0,0x9E47, 0, 0, 0, 0, 0, 0,
+0x9E48, 0,0x8BC8,0x8967,0x8D58,0x9E49, 0,0x9E4A,
+0x8F91,0x9182, 0, 0,0x99D6,0x915D,0x915C,0x91D6,
+0x8DC5, 0, 0,0x98F0, 0, 0, 0, 0,
+0x8C8E,0x974C, 0,0x95FC, 0,0x959E, 0,0x9E4B,
+ 0, 0, 0, 0,0x8DF1,0x92BD,0x9E4C,0x984E,
+ 0, 0, 0,0x965D, 0,0x92A9,0x9E4D,0x8AFA,
+ 0, 0, 0, 0, 0, 0,0x9E4E,0x9E4F,
+0x96D8, 0,0x96A2,0x9696,0x967B,0x8E44,0x9E51, 0,
+ 0,0x8EE9, 0, 0,0x9670, 0,0x9E53,0x9E56,
+0x9E55, 0,0x8AF7, 0, 0,0x8B80, 0,0x9E52,
+ 0,0x9E54, 0, 0, 0, 0,0x9E57, 0,
+ 0,0x9099, 0, 0, 0, 0,0x979B,0x88C7,
+0x8DDE,0x91BA, 0,0x8EDB, 0, 0,0x8FF1, 0,
+ 0,0x9E5A, 0, 0,0x936D, 0,0x9E58,0x91A9,
+0x9E59,0x8FF0,0x96DB,0x9E5B,0x9E5C,0x9788, 0, 0,
+ 0, 0,0x9E61, 0, 0,0x8D59, 0,0x9474,
+0x9E5E,0x938C,0x9DDC,0x9DE0, 0,0x8B6E, 0,0x9466,
+ 0, 0, 0, 0,0x9E60, 0,0x8FBC,0x94C2,
+ 0, 0, 0, 0, 0,0x9E66, 0,0x94F8,
+ 0,0x9E5D, 0,0x9E63,0x9E62, 0, 0, 0,
+0x90CD, 0, 0, 0, 0,0x968D, 0,0x97D1,
+ 0, 0,0x9687, 0,0x89CA,0x8E7D, 0, 0,
+0x9867,0x9E65,0x9095, 0, 0, 0,0x9E64, 0,
+ 0,0x9E5F, 0, 0, 0, 0, 0,0x8CCD,
+ 0, 0, 0,0x9E6B,0x9E69, 0,0x89CB,0x9E67,
+0x9E6D,0x9E73, 0, 0, 0, 0, 0, 0,
+ 0,0x91C6, 0, 0,0x95BF, 0,0x9E75, 0,
+ 0, 0,0x9541, 0, 0, 0,0x9E74,0x9490,
+0x965E,0x8AB9, 0,0x90F5,0x8F5F, 0, 0, 0,
+0x92D1, 0,0x974D, 0, 0,0x9E70,0x9E6F, 0,
+ 0, 0,0x9E71, 0,0x9E6E, 0, 0,0x9E76,
+ 0,0x9E6C, 0, 0,0x9E6A, 0,0x9E72,0x9E68,
+ 0,0x928C, 0,0x96F6,0x8EC4,0x8DF2, 0, 0,
+ 0, 0, 0,0x8DB8, 0, 0,0x968F,0x8A60,
+ 0, 0,0x92CC,0x93C8,0x8968, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x90F0, 0, 0,0x90B2,0x8C49,
+ 0, 0, 0, 0, 0, 0,0x9E78, 0,
+ 0,0x8D5A,0x8A9C, 0, 0, 0, 0, 0,
+ 0,0x9E7A,0x8A94,0x9E81, 0, 0, 0, 0,
+ 0, 0,0x9E7D, 0,0x90F1, 0, 0, 0,
+0x8A6A,0x8DAA, 0, 0,0x8A69,0x8DCD, 0, 0,
+0x9E7B,0x8C85,0x8C6A,0x938D, 0, 0,0x9E79, 0,
+0x88C4, 0, 0, 0, 0,0x9E7C,0x9E7E, 0,
+0x8BCB,0x8C4B, 0,0x8ABA,0x8B6A, 0, 0, 0,
+ 0,0x9E82, 0, 0,0x8DF7,0x9691, 0,0x8E56,
+ 0, 0, 0,0x9E83, 0, 0, 0,0x954F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9E8F, 0,0x89B1,0x9E84,
+ 0, 0, 0, 0, 0, 0,0x9E95,0x9E85,
+ 0,0x97C0, 0,0x9E8C, 0,0x947E, 0, 0,
+ 0, 0, 0, 0, 0,0x9E94, 0,0x9E87,
+ 0, 0, 0,0x88B2,0x9E89, 0, 0,0x8D5B,
+ 0, 0, 0,0x9E8B, 0,0x9E8A, 0,0x9E86,
+0x9E91, 0,0x8FBD, 0, 0, 0,0x9AEB,0x8CE6,
+0x979C, 0, 0, 0, 0,0x9E88, 0,0x92F2,
+0x8A42,0x8DAB, 0,0x9E80, 0,0x9E90,0x8A81, 0,
+ 0,0x9E8E,0x9E92, 0,0x938E, 0, 0, 0,
+ 0, 0, 0, 0,0x8AFC, 0,0x9EB0, 0,
+ 0,0x96C7,0x9E97,0x8AFB, 0,0x9E9E, 0, 0,
+ 0, 0,0x965F, 0,0x9E9F,0x9EA1, 0,0x9EA5,
+0x9E99, 0,0x9249, 0, 0, 0, 0,0x938F,
+0x9EA9,0x9E9C, 0,0x9EA6, 0, 0, 0,0x9EA0,
+ 0, 0, 0, 0, 0, 0,0x9058,0x9EAA,
+ 0, 0,0x90B1, 0, 0, 0, 0, 0,
+ 0,0x9EA8,0x8ABB, 0, 0, 0, 0, 0,
+0x986F,0x9E96, 0, 0,0x9EA4,0x88D6, 0, 0,
+0x9E98, 0, 0,0x96B8,0x9E9D,0x9041,0x92C5,0x9E93,
+ 0, 0,0x9EA3, 0, 0, 0, 0, 0,
+ 0,0x909A,0x9EAD,0x8A91,0x8C9F, 0, 0, 0,
+ 0,0x9EAF,0x9E9A,0x9EAE, 0,0x9EA7,0x9E9B, 0,
+0x9EAB, 0,0x9EAC, 0, 0, 0, 0, 0,
+0x9EBD, 0, 0, 0,0x93CC, 0,0x9EA2, 0,
+ 0,0x9EB9, 0, 0, 0,0x9EBB, 0,0x92D6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x976B, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9596,0x9EB6,0x91C8, 0, 0,
+ 0,0x9EBC,0x915E, 0,0x9EB3,0x9EC0,0x9EBF, 0,
+0x93ED,0x9EBE,0x93E8, 0, 0, 0, 0, 0,
+ 0, 0,0x9EC2,0x9EB5, 0,0x8BC6,0x9EB8,0x8F7C,
+ 0, 0, 0,0x9480,0x9EBA,0x8BC9, 0,0x9EB2,
+0x9EB4,0x9EB1, 0, 0,0x984F,0x8A79,0x9EB7, 0,
+ 0,0x9EC1,0x8A54, 0, 0, 0, 0, 0,
+ 0, 0,0x8DE5, 0, 0, 0,0x897C, 0,
+ 0,0x9ED2, 0, 0,0x9850,0x9ED5, 0, 0,
+ 0, 0, 0,0x9059,0x9ED4, 0, 0, 0,
+0x9ED3, 0, 0, 0, 0, 0, 0,0x9ED0,
+ 0, 0, 0, 0, 0, 0,0x9EC4, 0,
+ 0,0x9EE1,0x9EC3, 0,0x9ED6, 0, 0, 0,
+ 0, 0, 0,0x9ECE, 0, 0,0x9EC9,0x9EC6,
+ 0,0x9EC7, 0,0x9ECF, 0, 0, 0,0xEAA0,
+ 0, 0,0x9ECC,0x8D5C,0x92C6,0x9184,0x9ECA, 0,
+0x9EC5, 0, 0,0x9EC8, 0, 0, 0, 0,
+0x976C,0x968A, 0, 0, 0,0x9ECD,0x9ED7, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9EDF,
+0x9ED8, 0, 0,0x9EE5, 0,0x9EE3, 0, 0,
+ 0, 0,0x9EDE, 0, 0, 0, 0, 0,
+ 0,0x9EDD, 0,0x92CE, 0,0x9185, 0,0x9EDB,
+ 0, 0,0x9ED9, 0, 0,0x9EE0, 0, 0,
+ 0, 0,0x9EE6,0x94F3,0x9EEC, 0, 0, 0,
+ 0, 0,0x9EE7,0x9EEA,0x9EE4, 0, 0,0x9294,
+ 0,0x9557, 0,0x9EDA, 0, 0,0x9EE2,0x8FBE,
+ 0,0x96CD,0x9EF6,0x9EE9, 0, 0, 0, 0,
+ 0,0x8CA0,0x89A1,0x8A7E, 0, 0,0x9ED1, 0,
+ 0, 0, 0, 0, 0,0x8FBF,0x9EEE, 0,
+0x9EF5,0x8EF7,0x8A92, 0, 0,0x924D, 0, 0,
+ 0, 0, 0, 0,0x9EEB, 0, 0,0x9EF0,
+0x9EF4, 0, 0,0x8BB4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B6B,0x9EF2, 0, 0, 0, 0, 0,0x8B40,
+ 0,0x93C9,0x9EF1, 0, 0, 0,0x9EF3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9EED, 0, 0, 0, 0, 0,
+0x9EEF, 0, 0, 0, 0, 0, 0,0x8A80,
+0x9268, 0, 0, 0,0x9EFA, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9EF8,0x8CE7, 0,
+0x9EF7, 0, 0, 0, 0, 0, 0,0x9F40,
+ 0, 0, 0, 0,0x9E77, 0, 0, 0,
+0x9EF9, 0,0x9EFB,0x9EFC, 0, 0, 0, 0,
+ 0, 0,0x9F4B, 0,0x9F47, 0,0x9E8D, 0,
+ 0, 0, 0,0x9F46, 0, 0, 0, 0,
+0x9F45, 0, 0,0x9F42, 0, 0, 0, 0,
+ 0,0x9EE8,0x9F44,0x9F43, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9F49, 0,0x9845, 0, 0, 0, 0,
+ 0, 0,0x9F4C,0x8BF9, 0, 0,0x9F48,0x9F4A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x94A5, 0,0x9F4D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9F51,0x9F4E, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9793,0x9F4F, 0, 0,
+ 0, 0,0x9EDC, 0, 0, 0, 0, 0,
+ 0, 0,0x9F52, 0, 0, 0,0x9F53, 0,
+ 0, 0, 0, 0, 0,0x8954, 0,0x9F55,
+0x8C87,0x8E9F, 0,0x8BD3, 0, 0, 0,0x89A2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x977E, 0, 0, 0, 0,0x9F57,
+0x9F56,0x9F59,0x8B5C, 0, 0,0x8BD4,0x8ABC, 0,
+ 0, 0, 0,0x9F5C, 0, 0, 0,0x9F5B,
+ 0,0x9F5D, 0, 0,0x89CC, 0,0x9256, 0,
+0x9F5E, 0, 0,0x8ABD,0x9F60, 0, 0, 0,
+ 0,0x9F5F, 0,0x9F61, 0, 0, 0,0x9F62,
+ 0,0x9F63,0x8E7E,0x90B3,0x8D9F, 0,0x9590, 0,
+ 0,0x95E0,0x9863, 0, 0, 0, 0,0x8E95,
+ 0, 0, 0,0x8DCE,0x97F0, 0, 0, 0,
+0x9F64,0x9F65, 0,0x8E80, 0, 0, 0,0x9F66,
+0x9F67, 0, 0,0x9F69,0x9F68, 0,0x9677, 0,
+ 0,0x8F7D,0x8EEA,0x8E63, 0,0x9F6A, 0, 0,
+ 0, 0, 0, 0, 0,0x9F6C,0x9042, 0,
+0x9F6B, 0, 0, 0, 0, 0,0x9F6D, 0,
+ 0, 0, 0, 0,0x9F6E, 0, 0, 0,
+ 0, 0,0x9F6F,0x9F70, 0, 0, 0,0x9F71,
+ 0,0x9F73,0x9F72,0x9F74,0x89A3,0x9269, 0,0x9F75,
+ 0, 0,0x8E45,0x8A6B,0x9F76, 0, 0,0x9361,
+0x9ACA, 0, 0, 0, 0,0x8B42,0x9F77, 0,
+ 0, 0, 0,0x9F78, 0,0x95EA,0x9688, 0,
+ 0, 0,0x93C5,0x9F79,0x94E4, 0, 0, 0,
+0x94F9, 0, 0,0x96D1, 0, 0, 0,0x9F7A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9F7C,0x9F7B, 0, 0,0x9F7E,
+ 0, 0, 0,0x9F7D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9F81, 0, 0, 0, 0, 0, 0,0x8E81,
+ 0,0x96AF, 0,0x9F82,0x9F83, 0, 0,0x8B43,
+ 0, 0, 0,0x9F84, 0, 0, 0, 0,
+ 0, 0, 0,0x9F86,0x9F85, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9085, 0, 0,0x9558,
+0x8969, 0, 0, 0, 0, 0,0x94C3, 0,
+0x92F3,0x8F60,0x8B81, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x94C4, 0,
+0x8EAC, 0, 0, 0, 0,0x9F88, 0,0x8ABE,
+ 0, 0,0x8998, 0, 0,0x93F0,0x9F87,0x8D5D,
+0x9272, 0,0x9F89, 0, 0, 0, 0, 0,
+0x9F91, 0,0x9F8A, 0, 0, 0, 0, 0,
+0x91BF, 0,0x8B82,0x9F92, 0, 0, 0, 0,
+ 0, 0,0x8C88, 0, 0,0x8B44,0x9F90, 0,
+ 0,0x9F8E,0x9F8B,0x9780, 0, 0, 0, 0,
+0x92BE, 0, 0, 0,0x93D7,0x9F8C, 0, 0,
+0x9F94, 0,0x9F93,0x8C42, 0, 0,0x89AB, 0,
+ 0,0x8DB9,0x9F8D,0x9F8F, 0, 0, 0, 0,
+ 0,0x9676,0x91F2, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9697, 0, 0,0x9F9C, 0,
+ 0,0x9F9D, 0,0x89CD, 0, 0, 0, 0,
+0x95A6,0x96FB,0x9F9F,0x8EA1,0x8FC0,0x9F98,0x9F9E,0x8988,
+ 0,0x8BB5, 0, 0,0x9F95,0x9F9A, 0, 0,
+ 0,0x90F2,0x9491, 0,0x94E5, 0, 0, 0,
+ 0, 0, 0,0x9F97, 0,0x9640, 0,0x9F99,
+ 0,0x9FA2, 0,0x9FA0, 0,0x9F9B, 0, 0,
+ 0,0x9641,0x9467,0x8B83, 0,0x9344, 0, 0,
+0x928D, 0,0x9FA3, 0, 0, 0, 0,0x9FA1,
+0x91D7,0x9F96, 0,0x896A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x976D,0x9FAE, 0, 0, 0,
+ 0, 0,0x9FAD, 0, 0, 0, 0,0x90F4,
+ 0,0x9FAA, 0,0x978C, 0, 0,0x93B4,0x9FA4,
+ 0, 0, 0, 0, 0,0x92C3, 0, 0,
+ 0,0x896B,0x8D5E,0x9FA7, 0, 0, 0, 0,
+ 0, 0,0x8F46,0x9FAC, 0,0x9FAB,0x9FA6, 0,
+0x9FA9, 0, 0,0x8A88, 0,0x9FA8,0x9468, 0,
+ 0,0x97AC, 0, 0,0x8FF2,0x90F3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9FB4,0x9FB2, 0,0x956C, 0, 0, 0,
+ 0, 0, 0,0x9FAF,0x9FB1, 0,0x8959, 0,
+ 0,0x8D5F,0x9851, 0,0x8A5C, 0,0x9582, 0,
+ 0, 0, 0, 0,0x9781, 0, 0,0x8A43,
+0x905A,0x9FB3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9FB8, 0, 0,
+0x8FC1, 0, 0, 0,0x974F, 0,0x9FB5, 0,
+ 0, 0, 0,0x9FB0, 0,0x9FB6, 0, 0,
+ 0,0x97DC, 0,0x9393,0x93C0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x8A55,
+ 0, 0,0x8974, 0, 0,0x9FBC, 0, 0,
+0x9FBF, 0, 0, 0,0x97C1, 0, 0, 0,
+0x9784, 0, 0, 0, 0,0x9FC6,0x9FC0,0x9FBD,
+ 0, 0, 0,0x97D2,0x9FC3, 0, 0, 0,
+ 0,0x8F69,0x9FC5, 0, 0,0x9FCA, 0, 0,
+0x9391,0x9FC8, 0, 0, 0, 0,0x9FC2, 0,
+ 0,0x9257, 0, 0,0x9FC9, 0,0x9FBE, 0,
+0x9FC4, 0,0x9FCB,0x88FA,0x9FC1, 0,0x9FCC, 0,
+ 0,0x905B, 0,0x8F7E, 0,0x95A3, 0,0x8DAC,
+ 0,0x9FB9,0x9FC7,0x9359, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x90B4, 0,0x8A89,
+0x8DCF,0x8FC2,0x9FBB,0x8F61, 0, 0, 0, 0,
+ 0, 0, 0,0x8C6B, 0,0x9FBA, 0, 0,
+ 0,0x9FD0,0x8F8D,0x8CB8, 0,0x9FDF, 0,0x9FD9,
+0x8B94,0x936E, 0,0x9FD4,0x9FDD,0x88AD,0x8951, 0,
+ 0,0x89B7, 0,0x9FD6,0x91AA,0x9FCD,0x9FCF,0x8D60,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9FE0, 0,0x9FDB, 0, 0, 0,0x9FD3, 0,
+ 0, 0, 0,0x9FDA, 0, 0, 0, 0,
+ 0, 0,0x96A9, 0, 0,0x9FD8,0x9FDC, 0,
+ 0, 0, 0, 0, 0, 0,0x8CCE, 0,
+0x8FC3, 0, 0,0x9258, 0, 0, 0,0x9FD2,
+ 0, 0, 0, 0, 0, 0, 0,0x974E,
+ 0, 0, 0,0x9FD5, 0, 0,0x9FCE,0x9392,
+ 0, 0,0x9FD1, 0, 0, 0,0x9FD7, 0,
+ 0, 0, 0, 0, 0, 0,0x9870,0x8EBC,
+0x969E, 0,0x9FE1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x94AC, 0, 0,0x9FED,
+0x8CB9, 0, 0, 0, 0, 0,0x8F80, 0,
+0x9FE3, 0, 0, 0,0x97AD,0x8D61, 0,0x9FF0,
+ 0, 0,0x88EC, 0, 0,0x9FEE, 0, 0,
+ 0, 0,0x9FE2, 0, 0, 0, 0,0x9FE8,
+ 0, 0,0x9FEA, 0, 0, 0,0x976E,0x9FE5,
+ 0, 0,0x934D, 0, 0,0x9FE7, 0, 0,
+ 0, 0,0x9FEF, 0,0x9FE9,0x96C5, 0, 0,
+ 0,0x9FE4, 0,0x8EA0,0x9FFC, 0, 0, 0,
+ 0,0x8A8A, 0,0x9FE6,0x9FEB,0x9FEC, 0, 0,
+ 0, 0, 0, 0, 0,0x91EA,0x91D8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9FF4, 0, 0,0x9FFA,
+ 0, 0,0x9FF8, 0,0x9348, 0, 0,0xE042,
+0x9FF5, 0, 0, 0, 0, 0,0x9FF6,0x9FDE,
+ 0,0x8B99,0x9559, 0, 0, 0,0x8EBD, 0,
+ 0,0x8D97, 0, 0, 0, 0, 0,0x9852,
+ 0,0x9FF2, 0,0xE041,0x8989,0x9186, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9499, 0,0x8ABF,0x97F8, 0, 0, 0, 0,
+ 0, 0, 0,0x969F,0x92D0, 0, 0, 0,
+ 0,0x9FF9,0x9FFB, 0, 0, 0, 0, 0,
+0x9151, 0, 0, 0, 0, 0,0xE040,0x9FF7,
+ 0,0x9FF1, 0, 0, 0,0x8AC1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8C89, 0, 0, 0,
+0xE04E, 0, 0,0xE049,0x90F6, 0, 0,0x8A83,
+ 0, 0, 0, 0,0x8F81, 0,0xE052, 0,
+ 0, 0, 0, 0, 0,0xE04B,0x92AA,0xE048,
+0x92D7, 0, 0, 0,0xE06B, 0, 0, 0,
+0xE045, 0,0xE044, 0,0xE04D, 0, 0, 0,
+0xE047,0xE046,0xE04C, 0,0x909F, 0,0xE043, 0,
+ 0, 0, 0, 0, 0, 0,0xE04F, 0,
+ 0,0xE050, 0, 0, 0, 0, 0,0x8AC0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE055, 0,0xE054,0xE056, 0, 0, 0,
+ 0, 0,0xE059, 0, 0, 0, 0, 0,
+ 0,0x9362, 0,0xE053, 0, 0, 0, 0,
+ 0,0xE057, 0, 0, 0, 0, 0, 0,
+0x8C83,0x91F7,0xE051,0x945A, 0, 0,0xE058, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE05D,0xE05B, 0, 0,
+0xE05E, 0, 0,0xE061, 0, 0, 0,0xE05A,
+0x8D8A,0x9447, 0, 0,0x9FB7, 0, 0, 0,
+ 0, 0, 0,0x9794,0xE05C, 0,0xE060,0x91F3,
+ 0,0xE05F, 0,0xE04A, 0, 0,0xE889, 0,
+ 0, 0,0xE064, 0, 0, 0,0xE068, 0,
+ 0,0xE066, 0, 0, 0, 0, 0, 0,
+ 0,0xE062, 0,0xE063, 0, 0, 0,0xE067,
+ 0,0xE065, 0, 0, 0,0x956D, 0, 0,
+0xE06D, 0,0xE06A,0xE069, 0,0xE06C,0x93D2,0xE06E,
+ 0, 0, 0, 0, 0, 0,0x9295,0x91EB,
+ 0, 0, 0, 0,0x90A3, 0, 0, 0,
+0xE06F, 0,0xE071, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE070, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9FF3, 0, 0, 0,
+ 0,0xE072, 0, 0, 0, 0, 0, 0,
+0x93E5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE073, 0, 0, 0, 0,
+ 0, 0, 0,0x89CE, 0, 0, 0,0x9394,
+0x8A44, 0, 0, 0, 0, 0, 0, 0,
+0x8B84, 0, 0, 0,0x8EDC,0x8DD0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9846,0x9086, 0, 0, 0,0x898A, 0,
+ 0, 0,0xE075, 0, 0, 0, 0, 0,
+ 0,0xE074, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE078,0x9259,0xE07B,0xE076,
+ 0, 0, 0,0xE07A, 0, 0, 0, 0,
+0xE079,0x935F,0x88D7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x97F3, 0, 0,0xE07D, 0, 0, 0,0x8947,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE080, 0, 0, 0,0xE07E, 0,0xE07C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE077, 0, 0, 0, 0, 0, 0,
+ 0,0x9642, 0, 0, 0,0xE082, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE081, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x898B, 0, 0, 0,
+ 0,0xE084,0x95B0, 0,0xE083, 0, 0, 0,
+ 0,0x96B3, 0, 0, 0, 0,0x8FC5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9152, 0,
+ 0, 0, 0, 0,0x8FC4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x97F9, 0, 0,0xE08A, 0,0x90F7, 0,
+ 0, 0, 0, 0, 0,0xE086,0xE08B, 0,
+ 0,0x898C, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE089, 0,0x9481,0xE085,0xE088,0x8FC6,
+ 0,0x94CF, 0, 0,0xE08C, 0,0x8ECF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x90F8, 0, 0,
+ 0, 0, 0, 0,0xE08F, 0, 0, 0,
+0xE087, 0,0x8C46, 0, 0, 0, 0,0xE08D,
+ 0, 0, 0, 0,0x976F,0xE090, 0, 0,
+ 0,0xEAA4, 0, 0, 0, 0, 0,0x8F6E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE091, 0, 0, 0,0xE092, 0, 0, 0,
+ 0,0x944D, 0, 0, 0, 0, 0, 0,
+ 0,0xE094, 0, 0, 0, 0,0xE095, 0,
+ 0, 0, 0,0x9452, 0, 0, 0, 0,
+0x9395,0xE097, 0, 0, 0, 0,0xE099, 0,
+0x97D3, 0,0xE096, 0,0xE098,0x898D, 0,0xE093,
+ 0, 0, 0, 0, 0, 0, 0,0x9A7A,
+0xE09A, 0, 0, 0, 0,0x9187,0x8E57,0xE09C,
+ 0, 0, 0, 0,0xE09B,0x9043,0x99D7, 0,
+ 0, 0, 0, 0, 0,0xE09D, 0, 0,
+ 0,0xE09F, 0,0xE08E,0xE09E, 0, 0,0xE0A0,
+ 0, 0, 0, 0, 0, 0,0x949A, 0,
+ 0, 0, 0, 0, 0,0xE0A1, 0, 0,
+0xE0A2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE0A3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE0A4, 0,0x92DC, 0,0xE0A6,0xE0A5, 0, 0,
+0xE0A7, 0,0xE0A8, 0, 0,0x8EDD,0x9583, 0,
+ 0, 0,0x96EA,0xE0A9,0xE0AA,0x9175,0x8EA2,0xE0AB,
+0xE0AC, 0, 0, 0, 0, 0,0xE0AD,0x95D0,
+0x94C5, 0, 0,0xE0AE,0x9476, 0, 0, 0,
+ 0, 0,0x92AB, 0, 0, 0, 0, 0,
+0xE0AF,0x89E5, 0,0x8B8D, 0,0x96C4, 0,0x96B4,
+ 0,0x89B2,0x9853, 0, 0, 0, 0,0x9671,
+ 0,0x95A8, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90B5, 0,0xE0B0, 0, 0, 0,
+ 0,0x93C1, 0, 0, 0,0x8CA1,0xE0B1, 0,
+0x8DD2,0xE0B3,0xE0B2, 0, 0, 0, 0,0xE0B4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0B5, 0, 0, 0,0xE0B6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8B5D, 0,0xE0B7, 0, 0, 0, 0,0xE0B8,
+ 0, 0, 0, 0,0x8CA2, 0, 0,0x94C6,
+ 0, 0,0xE0BA, 0, 0, 0,0x8FF3, 0,
+ 0,0xE0B9, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8BB6,0xE0BB,0xE0BD, 0,0xE0BC, 0,
+ 0, 0, 0, 0, 0, 0,0xE0BE, 0,
+0x8CCF, 0,0xE0BF, 0, 0, 0, 0,0x8BE7,
+ 0,0x915F, 0,0x8D9D, 0, 0, 0, 0,
+0xE0C1,0xE0C2,0xE0C0, 0, 0, 0, 0, 0,
+ 0,0x8EEB, 0, 0,0x93C6,0x8BB7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE0C4,
+0x924B,0xE0C3, 0, 0,0x9854,0x9482, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0C7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE0C9,0xE0C6,
+ 0, 0, 0,0x96D2,0xE0C8,0xE0CA, 0,0x97C2,
+ 0, 0, 0, 0, 0,0xE0CE, 0, 0,
+ 0,0xE0CD,0x9296,0x944C, 0, 0,0x8CA3,0xE0CC,
+ 0, 0, 0, 0,0xE0CB, 0,0x9750,0x9751,
+ 0, 0, 0, 0, 0, 0,0xE0CF,0x898E,
+ 0, 0, 0, 0,0x8D96,0x8E82, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE0D0,0xE0D1,
+ 0, 0, 0, 0, 0, 0, 0,0xE0D3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8F62, 0, 0, 0, 0,
+0xE0D5, 0,0xE0D4, 0, 0, 0, 0, 0,
+0xE0D6, 0,0x8A6C, 0, 0,0xE0D8, 0, 0,
+0xE0D7, 0,0xE0DA,0xE0D9, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8CBA, 0, 0,0x97A6,
+ 0,0x8BCA, 0,0x89A4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8BE8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8ADF, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x97E6,0xE0DC, 0, 0, 0, 0,
+ 0, 0, 0,0xE0DE, 0, 0, 0, 0,
+0xE0DF, 0,0x89CF, 0, 0, 0, 0, 0,
+0xE0DB, 0,0x8E58, 0, 0,0x92BF,0xE0DD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE0E2, 0,
+0x8EEC, 0, 0, 0, 0,0xE0E0, 0, 0,
+ 0, 0,0x8C5D, 0, 0,0x94C7,0xE0E1, 0,
+ 0,0xE0FC, 0, 0, 0, 0, 0, 0,
+0xE0E7, 0, 0, 0, 0, 0,0x8CBB, 0,
+ 0, 0, 0,0x8B85, 0,0xE0E4,0x979D, 0,
+ 0,0x97AE, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x91F4, 0, 0,0xE0E6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0E8,0x97D4,0x8BD5,0x94FA,0x9469, 0,
+ 0, 0,0xE0E9, 0, 0, 0, 0,0xE0EB,
+ 0,0xE0EE, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE0EA, 0, 0,
+ 0,0xE0ED,0x8CE8,0x896C,0xE0EF, 0,0x9090,0xE0EC,
+0x97DA, 0, 0,0xE0F2,0xEAA2, 0, 0, 0,
+ 0,0xE0F0,0xE0F3, 0, 0, 0, 0,0xE0E5,
+0xE0F1, 0, 0,0x8DBA, 0, 0,0xE0F4, 0,
+ 0, 0, 0, 0, 0, 0,0xE0F5, 0,
+ 0, 0, 0,0x979E, 0, 0, 0, 0,
+ 0, 0, 0,0xE0F6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE0F7, 0,
+ 0, 0,0xE0E3, 0, 0, 0, 0,0xE0F8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8AC2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x8EA3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0F9, 0, 0, 0, 0,0xE0FA,
+ 0, 0, 0, 0,0xE0FB, 0, 0, 0,
+ 0, 0, 0, 0,0x895A, 0, 0, 0,
+0xE140, 0,0x955A,0xE141, 0, 0,0x8AA2,0xE142,
+ 0,0xE143, 0, 0, 0, 0,0xE144, 0,
+0xE146,0xE147,0xE145, 0, 0, 0,0x9572,0xE149,
+0xE148, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE14B,0xE14A,0xE14C, 0, 0,
+ 0, 0, 0, 0,0xE14D,0xE14F,0xE14E, 0,
+ 0,0x8D99, 0,0xE151, 0,0xE150, 0, 0,
+0x8AC3, 0,0x9072, 0,0x935B, 0,0xE152,0x90B6,
+ 0, 0, 0,0x8E59, 0,0x8999,0xE153, 0,
+0x9770, 0, 0,0x95E1,0xE154, 0, 0, 0,
+0x9363,0x9752,0x8D62,0x905C, 0, 0, 0,0x926A,
+0x99B2, 0,0x92AC,0x89E6,0xE155, 0, 0, 0,
+ 0, 0, 0, 0,0xE156, 0,0xE15B, 0,
+ 0,0xE159,0xE158,0x9DC0,0x8A45,0xE157, 0,0x88D8,
+ 0,0x94A8, 0, 0,0x94C8, 0, 0, 0,
+ 0,0x97AF,0xE15C,0xE15A,0x927B,0x90A4, 0, 0,
+0x94A9, 0,0x954C, 0,0xE15E,0x97AA,0x8C6C,0xE15F,
+ 0,0xE15D,0x94D4,0xE160, 0,0xE161, 0, 0,
+0x88D9, 0, 0,0x8FF4,0xE166, 0,0xE163,0x93EB,
+0xE162, 0, 0, 0, 0, 0, 0,0x8B45,
+ 0, 0,0xE169, 0, 0, 0,0xE164,0xE165,
+ 0,0xE168,0xE167,0x9544, 0, 0,0x9161,0x9160,
+ 0,0x8B5E, 0, 0,0xE16A, 0, 0, 0,
+ 0, 0,0xE16B, 0, 0,0xE16C, 0, 0,
+ 0, 0, 0,0xE16E, 0,0xE16D, 0, 0,
+ 0, 0, 0,0x8975, 0, 0, 0, 0,
+ 0,0xE176,0x94E6,0xE170, 0,0xE172, 0, 0,
+0xE174,0x905D, 0, 0,0xE175,0xE173,0x8EBE, 0,
+ 0, 0,0xE16F,0xE171, 0,0x9561, 0,0x8FC7,
+ 0, 0,0xE178, 0, 0,0xE177, 0, 0,
+ 0, 0,0xE179, 0,0x8EA4,0x8DAD, 0, 0,
+0x9397,0xE17A, 0,0x92C9, 0, 0,0xE17C, 0,
+ 0, 0,0x979F,0xE17B, 0, 0, 0, 0,
+ 0,0x9189, 0, 0, 0, 0, 0, 0,
+0xE182, 0,0xE184,0xE185,0x9273, 0, 0, 0,
+ 0, 0,0xE183, 0,0xE180, 0,0xE17D,0xE17E,
+ 0,0xE181, 0, 0, 0, 0, 0, 0,
+ 0,0xE188, 0,0xE186, 0,0xE187, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE189,
+0xE18B,0xE18C,0xE18D, 0,0xE18E, 0, 0,0xE18A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE190, 0, 0, 0,0xE18F, 0, 0, 0,
+ 0, 0, 0,0xE191, 0, 0, 0, 0,
+ 0, 0,0x97C3, 0, 0, 0,0xE194,0xE192,
+0xE193, 0, 0, 0,0x8AE0, 0, 0, 0,
+ 0, 0,0x96FC, 0, 0, 0,0x95C8, 0,
+0xE196, 0, 0, 0,0xE195, 0, 0, 0,
+ 0,0xE197,0xE198, 0, 0, 0, 0,0xE19C,
+0xE199,0xE19A,0xE19B, 0,0xE19D, 0, 0, 0,
+0xE19E, 0,0xE19F, 0, 0, 0,0xE1A0, 0,
+0xE1A1, 0,0x94AD,0x936F,0xE1A2,0x9492,0x9553, 0,
+0xE1A3, 0, 0,0xE1A4,0x9349, 0,0x8A46,0x8D63,
+0xE1A5, 0, 0,0xE1A6, 0, 0,0xE1A7, 0,
+0x8E48, 0, 0,0xE1A9, 0, 0,0xE1A8, 0,
+ 0,0xE1AA,0xE1AB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x94E7, 0,
+0xE1AC, 0, 0, 0,0xE1AD, 0, 0,0xEA89,
+0xE1AE,0xE1AF,0xE1B0, 0, 0, 0, 0,0x8E4D,
+ 0, 0,0xE1B1,0x9475, 0, 0,0x967E, 0,
+0x896D, 0,0x8976, 0, 0,0xE1B2, 0, 0,
+ 0, 0,0xE1B4, 0, 0, 0,0xE1B3,0x9390,
+ 0, 0, 0,0x90B7,0x9F58, 0,0xE1B5,0x96BF,
+ 0,0xE1B6, 0,0x8AC4,0x94D5,0xE1B7, 0,0xE1B8,
+ 0, 0,0xE1B9, 0, 0, 0,0x96DA, 0,
+ 0, 0,0x96D3, 0,0x92BC, 0, 0, 0,
+0x918A, 0, 0,0xE1BB, 0, 0,0x8F82, 0,
+ 0,0x8FC8, 0, 0,0xE1BE, 0, 0,0xE1BD,
+0xE1BC,0x94FB, 0,0x8AC5,0x8CA7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE1C4, 0, 0,0xE1C1,0x905E,
+0x96B0, 0, 0, 0,0xE1C0,0xE1C2,0xE1C3, 0,
+ 0,0xE1BF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE1C5,
+0xE1C6, 0,0x92AD, 0,0x8AE1, 0, 0, 0,
+0x9285, 0, 0, 0, 0, 0, 0,0xE1C7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE1C8,0xE1CB, 0, 0, 0, 0,
+ 0,0x9087, 0,0x93C2, 0,0xE1CC,0x9672, 0,
+0xE1C9, 0, 0,0xE1CA, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE1CF, 0, 0, 0, 0,0xE1CE,0xE1CD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE1D1, 0, 0,0xE1D0, 0,
+ 0,0xE1D2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE1D4, 0,
+0xE1D3, 0, 0, 0, 0,0x95CB, 0, 0,
+ 0, 0, 0, 0,0x8F75,0x97C4, 0, 0,
+0xE1D5, 0, 0,0x93B5, 0, 0,0xE1D6, 0,
+ 0,0xE1D7, 0,0xE1DB,0xE1D9,0xE1DA, 0,0xE1D8,
+ 0, 0, 0, 0, 0, 0, 0,0xE1DC,
+ 0, 0, 0, 0, 0,0xE1DD, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE1DE,
+ 0, 0,0xE1DF,0x96B5,0xE1E0, 0, 0, 0,
+ 0, 0,0x96EE,0xE1E1, 0,0x926D, 0,0x948A,
+ 0,0x8BE9, 0, 0, 0,0x925A,0xE1E2,0x8BB8,
+ 0, 0, 0,0x90CE, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE1E3, 0, 0, 0,
+ 0, 0,0x8DBB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE1E4, 0, 0, 0,
+ 0, 0,0xE1E5, 0,0x8CA4,0x8DD3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE1E7, 0, 0, 0, 0,0x9375,0x8DD4,0x8B6D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9643, 0,0x946A, 0, 0, 0,
+ 0, 0,0x9376, 0, 0, 0, 0,0x8D7B,
+ 0, 0, 0, 0, 0,0xE1E9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x8FC9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x97B0,0x8D64, 0, 0,0x8CA5,
+ 0, 0,0x94A1, 0,0xE1EB, 0, 0, 0,
+ 0, 0, 0, 0,0xE1ED, 0, 0, 0,
+ 0,0x8CE9, 0, 0, 0, 0,0xE1EC,0x92F4,
+ 0, 0, 0, 0,0xE1EF,0x8A56,0xE1EA, 0,
+ 0,0x94E8, 0,0x894F, 0,0x8DEA, 0,0x9871,
+ 0, 0,0xE1EE, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE1F0, 0, 0, 0,0x95C9,
+ 0,0x90D7,0xE1F2, 0, 0, 0, 0,0xE1F3,
+ 0, 0, 0, 0, 0,0xE1F1, 0, 0,
+ 0, 0,0x8A6D, 0,0xE1F9, 0,0xE1F8, 0,
+ 0,0x8EA5, 0, 0, 0,0xE1FA,0xE1F5, 0,
+ 0, 0,0xE1FB,0xE1F6, 0, 0, 0, 0,
+0x94D6,0xE1F4, 0, 0,0xE1F7, 0, 0, 0,
+ 0, 0,0xE241, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE240,
+0x9681, 0, 0, 0,0xE1FC, 0, 0,0x88E9,
+ 0, 0, 0, 0,0xE243, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE242, 0, 0,
+ 0,0x8FCA, 0, 0, 0, 0, 0,0xE244,
+ 0, 0, 0, 0, 0, 0,0x9162, 0,
+ 0,0xE246,0xE245, 0, 0, 0, 0, 0,
+ 0,0xE247, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE1E6, 0,
+ 0, 0,0xE1E8,0xE249,0xE248, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8EA6, 0,0x97E7, 0,0x8ED0, 0,
+0xE24A,0x8C56, 0, 0, 0, 0, 0,0x8B5F,
+0x8B46,0x8E83, 0, 0, 0, 0, 0, 0,
+0x9753, 0, 0,0xE250, 0,0xE24F,0x9163,0xE24C,
+ 0, 0,0xE24E, 0, 0,0x8F6A,0x905F,0xE24D,
+0xE24B, 0,0x9449, 0, 0,0x8FCB, 0, 0,
+0x955B, 0, 0, 0, 0,0x8DD5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9398,
+ 0, 0,0xE251, 0, 0, 0, 0,0xE252,
+0xE268,0x8BD6, 0, 0,0x985C,0x9154, 0, 0,
+ 0, 0,0xE253, 0, 0,0x89D0,0x92F5,0x959F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE254, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8B9A,0xE255,
+ 0, 0,0xE257, 0, 0, 0,0xE258, 0,
+0x9448, 0, 0,0xE259, 0, 0, 0, 0,
+ 0,0xE25A,0xE25B, 0, 0,0x8BD7,0x89D1,0x93C3,
+0x8F47,0x8E84, 0, 0, 0, 0, 0, 0,
+ 0,0xE25C, 0,0x8F48, 0, 0, 0, 0,
+ 0,0x89C8,0x9562, 0, 0,0xE25D, 0, 0,
+0x94E9, 0, 0, 0, 0, 0, 0,0x9164,
+ 0,0xE260, 0,0xE261,0x9489, 0,0x9060,0xE25E,
+ 0,0x9281, 0, 0,0xE25F, 0, 0, 0,
+0x8FCC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x88DA, 0, 0, 0, 0,
+0x8B48, 0, 0, 0, 0, 0, 0, 0,
+0xE262, 0, 0,0x92F6, 0,0xE263,0x90C5, 0,
+ 0, 0, 0, 0,0x96AB, 0, 0,0x9542,
+0xE264,0xE265,0x9274, 0,0x97C5, 0, 0,0xE267,
+0xE266, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8EED, 0,
+ 0,0xE269,0x88EE, 0, 0, 0, 0,0xE26C,
+ 0, 0, 0,0xE26A,0x89D2,0x8C6D,0xE26B,0x8D65,
+0x8D92, 0,0x95E4,0xE26D, 0, 0,0x9673, 0,
+ 0,0xE26F, 0, 0, 0,0x90CF,0x896E,0x89B8,
+0x88AA, 0, 0, 0, 0, 0, 0,0xE26E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE270,0xE271,0x8FF5, 0, 0, 0, 0,
+ 0,0xE272, 0,0x8A6E, 0, 0, 0, 0,
+0xE274, 0, 0, 0,0x8C8A, 0,0x8B86, 0,
+ 0,0xE275,0x8BF3, 0, 0,0xE276, 0,0x90FA,
+ 0,0x93CB, 0,0x90DE,0x8DF3, 0, 0, 0,
+0xE277, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x9282,0x918B, 0,0xE279,0xE27B,0xE278,
+0xE27A, 0, 0, 0, 0, 0, 0,0x8C41,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE27C,0x8C45, 0, 0, 0,0x8B87,0x9771,
+0xE27E, 0, 0, 0, 0, 0,0xE280, 0,
+ 0, 0,0x894D, 0, 0, 0, 0,0xE283,
+ 0, 0, 0,0x8A96,0xE282,0xE281, 0,0xE285,
+0xE27D, 0,0xE286,0x97A7, 0,0xE287, 0,0xE288,
+ 0, 0,0x9AF2,0xE28A, 0,0xE289, 0, 0,
+ 0,0xE28B,0xE28C, 0,0x97B3,0xE28D, 0,0xE8ED,
+0x8FCD,0xE28E,0xE28F,0x8F76, 0,0x93B6,0xE290, 0,
+ 0, 0,0x9247, 0, 0,0xE291, 0,0x925B,
+0xE292, 0, 0, 0, 0, 0,0x8BA3, 0,
+0x995E,0x927C,0x8EB1, 0, 0, 0, 0,0x8AC6,
+ 0, 0,0xE293, 0,0xE2A0, 0,0xE296, 0,
+0x8B88, 0,0xE295,0xE2A2, 0, 0, 0,0xE294,
+ 0,0x8FCE, 0, 0, 0, 0, 0, 0,
+0xE298,0xE299, 0,0x934A, 0, 0,0xE29A, 0,
+0x8A7D, 0, 0, 0, 0,0x9079,0x9584, 0,
+0xE29C, 0, 0, 0,0x91E6, 0, 0, 0,
+ 0, 0, 0,0xE297, 0,0xE29B,0xE29D, 0,
+ 0,0x8DF9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE2A4,0x954D, 0,
+0x94A4,0x9399, 0,0x8BD8,0xE2A3,0xE2A1, 0,0x94B3,
+0xE29E,0x927D,0x939B, 0,0x939A, 0,0x8DF4, 0,
+ 0, 0, 0, 0, 0,0xE2B6, 0, 0,
+ 0, 0, 0, 0, 0,0xE2A6, 0,0xE2A8,
+ 0, 0, 0, 0,0xE2AB, 0,0xE2AC, 0,
+0xE2A9,0xE2AA, 0, 0,0xE2A7,0xE2A5, 0, 0,
+ 0, 0,0xE29F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x95CD,0x89D3,
+ 0, 0, 0,0xE2B3, 0,0xE2B0, 0,0xE2B5,
+ 0, 0,0xE2B4, 0,0x9493,0x96A5, 0,0x8E5A,
+0xE2AE,0xE2B7,0xE2B2, 0,0xE2B1,0xE2AD, 0,0xE2AF,
+ 0,0x8AC7, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x925C, 0, 0,0x90FB, 0, 0,
+ 0,0x94A0, 0, 0,0xE2BC, 0, 0, 0,
+0x94A2, 0, 0, 0, 0, 0, 0, 0,
+0x90DF,0xE2B9, 0, 0,0x94CD, 0,0xE2BD,0x95D1,
+ 0,0x927A, 0,0xE2B8,0xE2BA, 0, 0,0xE2BB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE2BE, 0, 0,
+0x8EC2, 0, 0, 0,0x93C4,0xE2C3,0xE2C2, 0,
+ 0,0xE2BF, 0, 0, 0,0x9855, 0, 0,
+ 0, 0, 0,0xE2C8, 0, 0,0xE2CC,0xE2C9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE2C5, 0, 0, 0, 0, 0, 0,0xE2C6,
+ 0, 0, 0, 0, 0,0xE2CB, 0, 0,
+ 0,0xE2C0,0x99D3,0xE2C7,0xE2C1, 0, 0,0xE2CA,
+ 0, 0, 0, 0, 0, 0, 0,0xE2D0,
+ 0,0x8AC8, 0,0xE2CD, 0, 0, 0,0xE2CE,
+ 0, 0,0xE2CF,0xE2D2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE2D1,
+0x94F4, 0, 0, 0, 0,0xE2D3,0x97FA,0x95EB,
+0xE2D8, 0, 0,0xE2D5, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE2D4,0x90D0, 0,0xE2D7,
+0xE2D9, 0, 0, 0,0xE2D6, 0,0xE2DD, 0,
+0xE2DA, 0, 0, 0, 0, 0, 0,0xE2DB,
+0xE2C4, 0, 0, 0,0xE2DC,0xE2DE, 0, 0,
+ 0, 0, 0, 0,0xE2DF, 0, 0, 0,
+ 0, 0, 0,0x95C4, 0,0xE2E0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x96E0, 0,
+ 0,0x8BCC,0x8C48,0xE2E1, 0, 0, 0, 0,
+ 0,0x95B2, 0,0x9088, 0,0x96AE, 0, 0,
+0xE2E2, 0,0x97B1, 0, 0,0x9494, 0,0x9165,
+0x9453, 0, 0,0x8F6C, 0, 0, 0,0x88BE,
+ 0,0xE2E7,0xE2E5, 0,0xE2E3,0x8A9F, 0,0x8FCF,
+0xE2E8, 0, 0,0xE2E6, 0,0xE2E4,0xE2EC, 0,
+ 0,0xE2EB,0xE2EA,0xE2E9, 0, 0, 0, 0,
+ 0,0xE2ED, 0, 0, 0,0xE2EE,0x90B8, 0,
+0xE2EF, 0,0xE2F1, 0, 0,0xE2F0, 0, 0,
+ 0, 0,0x8CD0, 0, 0, 0,0x9157, 0,
+ 0, 0,0xE2F3, 0, 0, 0,0x939C, 0,
+0xE2F2, 0, 0, 0,0xE2F4, 0,0x95B3,0x918C,
+0x8D66, 0,0xE2F5, 0, 0, 0, 0,0x97C6,
+ 0, 0, 0, 0, 0, 0, 0,0xE2F7,
+ 0, 0,0xE2F8, 0,0xE2F9, 0,0xE2FA, 0,
+0x8E85, 0,0xE2FB,0x8C6E, 0, 0,0x8B8A, 0,
+0x8B49, 0,0xE340, 0,0x96F1,0x8D67,0xE2FC, 0,
+ 0, 0,0xE343,0x96E4, 0,0x945B, 0, 0,
+0x9552, 0, 0, 0,0x8F83,0xE342, 0,0x8ED1,
+0x8D68,0x8E86,0x8B89,0x95B4,0xE341, 0, 0, 0,
+0x9166,0x9661,0x8DF5, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8E87,0x92DB, 0,0xE346,0x97DD,
+0x8DD7, 0,0xE347,0x9061, 0,0xE349, 0, 0,
+ 0,0x8FD0,0x8DAE, 0, 0, 0, 0,0xE348,
+ 0, 0,0x8F49,0x8CBC,0x9167,0xE344,0xE34A, 0,
+ 0, 0, 0,0xE345,0x8C6F, 0,0xE34D,0xE351,
+0x8C8B, 0, 0, 0, 0, 0,0xE34C, 0,
+ 0, 0, 0,0xE355, 0, 0,0x8D69, 0,
+ 0,0x978D,0x88BA,0xE352, 0, 0,0x8B8B, 0,
+0xE34F, 0, 0, 0, 0, 0,0xE350, 0,
+ 0,0x939D,0xE34E,0xE34B, 0,0x8A47,0x90E2, 0,
+ 0,0x8CA6, 0, 0, 0,0xE357, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE354, 0, 0, 0, 0, 0,0xE356,
+ 0, 0, 0,0xE353, 0, 0, 0, 0,
+ 0,0x8C70,0x91B1,0xE358,0x918E, 0, 0,0xE365,
+ 0, 0,0xE361,0xE35B, 0, 0, 0, 0,
+ 0, 0, 0,0xE35F,0x8EF8,0x88DB,0xE35A,0xE362,
+0xE366,0x8D6A,0x96D4, 0,0x92D4,0xE35C, 0, 0,
+0xE364, 0,0xE359,0x925D, 0,0xE35E,0x88BB,0x96C8,
+ 0, 0, 0, 0, 0, 0, 0,0xE35D,
+ 0, 0,0x8BD9,0x94EA, 0, 0, 0,0x918D,
+ 0,0x97CE,0x8F8F, 0, 0,0xE38E, 0, 0,
+0xE367, 0,0x90FC, 0,0xE363,0xE368,0xE36A, 0,
+0x92F7,0xE36D, 0, 0,0xE369, 0, 0, 0,
+0x95D2,0x8AC9, 0, 0,0x96C9, 0, 0,0x88DC,
+ 0, 0,0xE36C, 0,0x97FB, 0, 0, 0,
+ 0, 0, 0,0xE36B, 0, 0, 0, 0,
+ 0,0x898F, 0, 0,0x93EA,0xE36E, 0, 0,
+ 0,0xE375,0xE36F,0xE376, 0, 0, 0, 0,
+ 0, 0,0xE372, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x949B, 0, 0,0x8EC8,0xE374,
+ 0,0xE371,0xE377,0xE370, 0, 0,0x8F63, 0,
+ 0, 0, 0,0x9644, 0, 0,0x8F6B, 0,
+ 0,0xE373,0xE380, 0, 0,0xE37B, 0,0xE37E,
+ 0,0xE37C,0xE381,0xE37A, 0,0xE360,0x90D1, 0,
+ 0,0x94C9, 0,0xE37D, 0, 0,0xE378, 0,
+ 0, 0,0x9140,0x8C71, 0,0x8F4A, 0, 0,
+ 0, 0, 0, 0,0x9044,0x9155,0xE384, 0,
+ 0,0xE386,0xE387, 0, 0,0xE383,0xE385, 0,
+ 0, 0, 0, 0, 0, 0,0xE379,0xE382,
+ 0,0xE38A,0xE389, 0, 0,0x969A, 0, 0,
+0x8C4A, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE388, 0,0xE38C,0xE38B,0xE38F, 0,0xE391,
+ 0, 0,0x8E5B,0xE38D, 0, 0, 0, 0,
+0xE392,0xE393, 0, 0,0xE394, 0,0xE39A,0x935A,
+0xE396, 0,0xE395,0xE397,0xE398, 0,0xE399, 0,
+ 0, 0, 0,0xE39B,0xE39C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8ACA, 0,
+0xE39D, 0,0xE39E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE39F, 0, 0,
+ 0, 0, 0, 0,0xE3A0,0xE3A1,0xE3A2, 0,
+0xE3A3,0xE3A4, 0, 0,0xE3A6,0xE3A5, 0, 0,
+0xE3A7, 0, 0, 0, 0, 0, 0,0xE3A8,
+0xE3A9, 0, 0, 0, 0, 0, 0,0xE3AC,
+0xE3AA,0xE3AB,0x8DDF,0x8C72, 0, 0,0x9275, 0,
+0x94B1, 0,0x8F90, 0, 0,0x946C, 0,0x94EB,
+0xE3AD,0x9CEB, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE3AE,0xE3B0, 0,0x9785,0xE3AF,0xE3B2,
+0xE3B1, 0,0x9772, 0,0xE3B3, 0,0x94FC, 0,
+ 0, 0, 0, 0,0xE3B4, 0, 0, 0,
+ 0, 0,0xE3B7, 0, 0,0xE3B6,0xE3B5, 0,
+ 0, 0, 0,0xE3B8,0x8C51, 0, 0, 0,
+0x9141,0x8B60, 0, 0, 0, 0,0xE3BC,0xE3B9,
+ 0, 0,0xE3BA, 0, 0, 0,0xE3BD, 0,
+0xE3BE,0xE3BB, 0, 0, 0,0x8948, 0, 0,
+ 0,0x89A5, 0, 0, 0,0xE3C0,0xE3C1, 0,
+ 0, 0,0xE3C2, 0,0x9782, 0, 0, 0,
+ 0, 0,0x8F4B, 0,0xE3C4,0xE3C3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9089,0xE3C5, 0, 0, 0, 0,0xE3C6, 0,
+ 0,0xE3C7, 0,0x8AE3, 0, 0, 0, 0,
+0x8ACB, 0, 0,0xE3C8, 0, 0, 0, 0,
+ 0,0xE3C9, 0,0x967C,0x9783, 0, 0, 0,
+0x9773,0x9856, 0,0x8D6C,0xE3CC,0x8ED2,0xE3CB, 0,
+ 0, 0, 0,0xE3CD,0x8EA7, 0, 0, 0,
+0x91CF, 0,0xE3CE, 0, 0,0x8D6B, 0,0x96D5,
+0xE3CF,0xE3D0, 0, 0,0xE3D1, 0, 0, 0,
+ 0,0xE3D2, 0, 0, 0, 0, 0, 0,
+0xE3D3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8EA8, 0, 0,0x96EB, 0,
+ 0, 0, 0,0xE3D5, 0,0x925E, 0,0xE3D4,
+ 0, 0, 0, 0, 0, 0,0xE3D7, 0,
+ 0, 0,0xE3D6, 0, 0, 0, 0, 0,
+ 0, 0,0xE3D8, 0, 0, 0,0x90B9, 0,
+0xE3D9, 0,0xE3DA, 0, 0, 0,0x95B7,0xE3DB,
+ 0,0x918F,0xE3DC, 0, 0, 0, 0, 0,
+0xE3DD, 0, 0, 0, 0, 0, 0,0x97FC,
+0xE3E0, 0,0xE3DF,0xE3DE,0x92AE, 0,0xE3E1,0x9045,
+ 0,0xE3E2, 0, 0, 0,0xE3E3,0x9857,0xE3E4,
+ 0, 0, 0, 0,0xE3E5,0xE3E7,0xE3E6,0x94A3,
+ 0,0x93F7, 0,0x985D,0x94A7, 0, 0, 0,
+ 0, 0, 0,0xE3E9, 0, 0,0x8FD1, 0,
+0x9549, 0,0xE3EA,0xE3E8, 0,0x8ACC, 0, 0,
+ 0,0x8CD2,0x8E88, 0, 0,0x94EC, 0, 0,
+ 0,0x8CA8,0x9662, 0,0xE3ED,0xE3EB, 0,0x8D6D,
+ 0,0x8D6E,0x88E7, 0,0x8DE6, 0, 0, 0,
+ 0, 0,0x9478, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x88DD,0xE3F2, 0,0x925F, 0,
+ 0, 0, 0, 0,0x9477, 0,0x91D9, 0,
+ 0, 0, 0, 0, 0, 0,0xE3F4, 0,
+ 0,0xE3F0,0xE3F3,0xE3EE, 0,0xE3F1,0x9645, 0,
+ 0,0x8CD3, 0, 0,0x88FB,0xE3EF, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE3F6,
+ 0,0xE3F7, 0, 0,0x93B7, 0, 0, 0,
+0x8BB9, 0, 0, 0,0xE445,0x945C, 0, 0,
+ 0, 0,0x8E89, 0, 0,0x8BBA,0x90C6,0x9865,
+0x96AC,0xE3F5,0x90D2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8B72,0xE3F8, 0, 0, 0, 0,
+ 0, 0, 0,0xE3FA, 0, 0, 0, 0,
+ 0,0xE3F9, 0, 0, 0, 0, 0,0xE3FB,
+ 0,0x9245, 0,0x945D, 0, 0, 0, 0,
+ 0,0x92AF, 0, 0, 0, 0,0xE442, 0,
+ 0, 0, 0, 0, 0, 0,0xE441, 0,
+ 0, 0, 0,0xE3FC, 0, 0,0x9074, 0,
+0x9585,0xE444, 0,0xE443,0x8D6F,0x9872, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE454,
+ 0, 0, 0, 0, 0,0xE448,0xE449, 0,
+ 0, 0, 0,0x8EEE, 0, 0,0xE447, 0,
+0x8D98,0xE446, 0, 0,0xE44A, 0, 0, 0,
+0x92B0,0x95A0,0x9142, 0, 0, 0, 0,0x91DA,
+0xE44E, 0,0xE44F,0xE44B, 0, 0, 0, 0,
+0xE44C, 0,0xE44D, 0, 0, 0, 0,0x8D70,
+ 0, 0, 0,0xE455, 0,0xE451, 0, 0,
+ 0, 0,0x9586, 0,0x968C,0x9547, 0, 0,
+0xE450, 0, 0,0xE453,0xE452, 0, 0, 0,
+0x9663,0xE456, 0, 0, 0, 0, 0, 0,
+0xE457, 0, 0,0x9156, 0,0xE458, 0, 0,
+0xE45A, 0,0xE45E, 0, 0,0xE45B,0xE459,0x945E,
+0xE45C, 0,0xE45D, 0, 0, 0,0x89B0, 0,
+0xE464,0xE45F, 0, 0, 0,0xE460, 0, 0,
+ 0,0xE461, 0,0x919F, 0, 0, 0, 0,
+0xE463,0xE462,0xE465, 0, 0, 0, 0,0xE466,
+0xE467, 0, 0,0x9062, 0,0x89E7, 0,0xE468,
+0x97D5, 0,0x8EA9, 0, 0,0x8F4C, 0, 0,
+ 0, 0, 0,0x8E8A,0x9276, 0, 0, 0,
+ 0, 0,0xE469,0xE46A,0x8950, 0,0xE46B, 0,
+ 0,0xE46C,0xE46D, 0, 0,0xE46E, 0,0xE46F,
+0x8BBB,0x9DA8,0xE470, 0,0x90E3,0xE471,0x8EC9, 0,
+0xE472, 0,0x98AE, 0, 0, 0,0xE473,0x95DC,
+0x8ADA, 0, 0,0x9143,0x8F77, 0,0x9591,0x8F4D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE474,0x8D71,0xE475,0x94CA, 0,0xE484, 0,
+ 0, 0, 0,0xE477, 0,0x91C7,0x9495,0x8CBD,
+0xE476,0x9144, 0, 0, 0, 0, 0, 0,
+0xE478, 0, 0, 0, 0, 0, 0,0x92F8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE47A,0xE479,0xE47C, 0, 0,0xE47B, 0,0xE47D,
+ 0, 0,0xE480, 0,0xE47E, 0,0x8ACD, 0,
+0xE481, 0,0xE482,0xE483, 0, 0,0x8DAF,0x97C7,
+ 0,0xE485,0x9046, 0, 0, 0,0x8990,0xE486,
+0xE487, 0, 0, 0, 0, 0,0xE488, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x88F0, 0,0xE489, 0, 0,
+ 0, 0,0xE48A, 0, 0, 0, 0, 0,
+ 0,0x9587, 0, 0, 0,0x8EC5, 0,0xE48C,
+ 0, 0, 0, 0, 0,0x8A48,0x88B0, 0,
+ 0, 0, 0,0xE48B,0xE48E,0x946D, 0,0x9063,
+ 0,0x89D4, 0,0x9646, 0, 0, 0, 0,
+0x8C7C,0x8BDA, 0,0xE48D, 0,0x89E8, 0, 0,
+ 0, 0, 0, 0, 0,0x8AA1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8991,0xE492,0x97E8,0x91DB, 0, 0,0x9563,
+ 0,0xE49E, 0,0x89D5,0xE49C, 0,0xE49A,0xE491,
+ 0,0xE48F, 0,0xE490, 0,0x8EE1,0x8BEA,0x9297,
+ 0, 0, 0,0x93CF, 0, 0, 0, 0,
+ 0,0x8970, 0,0xE494,0xE493, 0, 0, 0,
+ 0,0xE499,0xE495,0xE498, 0, 0, 0, 0,
+ 0, 0,0x96CE,0xE497,0x89D6,0x8A9D,0xE49B, 0,
+ 0,0xE49D, 0, 0, 0, 0,0x8C73, 0,
+ 0, 0, 0, 0, 0, 0,0xE4A1,0xE4AA,
+0xE4AB, 0, 0, 0,0x88A9, 0, 0, 0,
+ 0, 0, 0,0xE4B2, 0, 0, 0, 0,
+0x88EF, 0, 0,0xE4A9, 0, 0, 0,0xE4A8,
+ 0,0xE4A3,0xE4A2, 0,0xE4A0,0xE49F,0x9283, 0,
+0x91F9,0xE4A5, 0, 0, 0, 0, 0, 0,
+0xE4A4, 0, 0, 0, 0,0xE4A7, 0, 0,
+ 0,0x9190,0x8C74, 0, 0, 0, 0,0x8960,
+0xE4A6, 0,0x8D72, 0, 0, 0, 0, 0,
+0x9191, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE4B8, 0,0xE4B9, 0,0x89D7,
+ 0, 0, 0,0x89AC,0xE4B6, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE4AC, 0,0xE4B4,
+ 0,0xE4BB,0xE4B5, 0, 0, 0,0xE4B3, 0,
+ 0, 0, 0,0xE496, 0, 0,0xE4B1, 0,
+ 0, 0,0xE4AD, 0, 0, 0,0x8ACE,0xE4AF,
+0xE4BA, 0,0xE4B0, 0, 0, 0, 0, 0,
+0xE4BC, 0,0xE4AE,0x949C, 0, 0, 0, 0,
+ 0,0x9789, 0, 0, 0,0xE4B7, 0, 0,
+ 0, 0, 0, 0, 0,0xE4CD, 0, 0,
+ 0,0xE4C5, 0, 0, 0,0x909B, 0, 0,
+ 0, 0,0x8B65, 0,0x8BDB, 0,0xE4C0, 0,
+ 0, 0, 0,0x89D9, 0, 0,0x8FD2, 0,
+0xE4C3, 0, 0, 0,0x8DD8, 0, 0,0x9370,
+0xE4C8, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x95EC, 0,0xE4BF, 0, 0, 0,0x89D8,
+0x8CD4,0x9548,0xE4C9, 0,0xE4BD, 0, 0,0xE4C6,
+ 0, 0, 0,0xE4D0, 0,0xE4C1, 0, 0,
+ 0, 0, 0,0xE4C2,0x93B8, 0, 0,0xE4C7,
+ 0, 0, 0,0xE4C4,0x9647,0xE4CA,0x88DE, 0,
+ 0, 0, 0,0xE4BE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE4CC, 0,0xE4CB, 0, 0, 0, 0, 0,
+ 0,0x948B,0xE4D2, 0,0xE4DD, 0, 0, 0,
+ 0,0x8A9E, 0, 0, 0,0xE4E0, 0, 0,
+0xE4CE, 0, 0, 0,0xE4D3,0x978E, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE4DC, 0,
+ 0,0x9774, 0, 0, 0, 0,0x97A8, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9298,
+ 0, 0, 0,0x8A8B, 0, 0, 0, 0,
+ 0,0x9592,0xE4E2,0x939F, 0, 0,0x88AF, 0,
+ 0,0xE4DB, 0,0xE4D7,0x9192,0xE4D1,0xE4D9,0xE4DE,
+ 0,0x944B, 0, 0, 0,0x88A8, 0,0xE4D6,
+ 0,0xE4DF,0x9598, 0, 0, 0, 0, 0,
+ 0, 0,0xE4DA, 0,0xE4D5, 0, 0, 0,
+ 0, 0, 0,0x8FD3, 0, 0, 0, 0,
+0x8F4E, 0, 0, 0,0x8EAA, 0, 0, 0,
+ 0,0x96D6, 0, 0,0x9566, 0, 0,0xE4E5,
+ 0,0xE4EE, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE4D8, 0, 0,
+ 0, 0,0x8A97, 0, 0, 0, 0, 0,
+0x8FF6,0xE4E3, 0,0xE4E8,0x9193, 0, 0,0xE4E4,
+ 0,0xE4EB, 0, 0,0x927E, 0,0xE4EC, 0,
+ 0,0x9775,0xE4E1,0x8A57, 0,0xE4E7, 0, 0,
+0xE4EA,0x96AA, 0, 0, 0, 0,0xE4ED, 0,
+ 0,0xE4E6,0xE4E9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9648, 0,0x9840, 0,
+ 0, 0, 0, 0,0xE4F1, 0, 0, 0,
+ 0, 0, 0, 0,0xE4F8, 0, 0,0xE4F0,
+0x8EC1, 0, 0, 0, 0, 0,0xE4CF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x95CC, 0,0x96A0,0xE4F7,0xE4F6, 0,0xE4F2,
+0xE4F3, 0,0x8955, 0, 0, 0, 0,0xE4F5,
+ 0,0xE4EF, 0, 0, 0, 0,0x92D3, 0,
+ 0, 0, 0, 0,0xE4F4,0x88FC, 0, 0,
+ 0, 0, 0, 0, 0,0x91A0, 0, 0,
+ 0, 0, 0, 0, 0,0x95C1, 0, 0,
+0xE4F9,0xE540, 0,0x94D7, 0, 0, 0, 0,
+0xE4FC,0x8FD4,0x8EC7,0xE542, 0, 0,0x8BBC, 0,
+ 0, 0, 0, 0, 0,0xE543, 0,0x9599,
+0xE4FB, 0,0xE4D4, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE4FA, 0, 0, 0, 0,
+0x986E,0x93A0,0x9593, 0, 0,0xE54A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE550,
+ 0, 0, 0, 0, 0, 0,0xE551, 0,
+0xE544, 0, 0, 0,0x9496, 0, 0,0xE54E,
+0xE546, 0,0xE548, 0, 0, 0, 0, 0,
+0xE552,0xE547, 0, 0,0xE54B, 0, 0,0x8992,
+ 0,0x93E3, 0,0xE54C,0xE54F, 0, 0, 0,
+ 0, 0, 0, 0,0xE545, 0,0x9145, 0,
+0xE549,0x8E46,0x9064,0x8C4F,0x96F2, 0,0x96F7,0x8F92,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE556,0xE554, 0, 0, 0, 0, 0,
+ 0,0x986D, 0, 0, 0, 0, 0, 0,
+ 0,0xE553, 0, 0, 0,0x9795, 0,0xE555,
+0xE557, 0, 0, 0, 0,0xE558, 0, 0,
+ 0, 0, 0, 0,0xE55B,0xE559, 0, 0,
+ 0, 0, 0, 0,0x93A1,0xE55A, 0, 0,
+ 0,0x94CB,0xE54D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x8F93,
+ 0,0xE55C,0xE561,0x9194, 0, 0,0xE560, 0,
+ 0, 0,0xE541, 0, 0, 0,0xE562,0x9168,
+ 0, 0,0xE55D,0xE55F, 0, 0, 0, 0,
+ 0, 0, 0,0xE55E, 0, 0,0x9F50,0x9F41,
+ 0, 0,0xE564, 0, 0, 0, 0, 0,
+ 0, 0,0xE563, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9796, 0,0xE1BA,
+0xE565, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE566,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE567,0x8CD5, 0,
+0x8B73, 0, 0, 0,0xE569,0x997C, 0, 0,
+ 0, 0,0x8B95, 0,0x97B8, 0,0x8BF1,0xE56A,
+ 0, 0, 0, 0, 0, 0, 0,0xE56B,
+ 0, 0, 0,0x928E, 0, 0, 0, 0,
+ 0,0xE56C, 0, 0, 0, 0, 0, 0,
+ 0,0x93F8, 0,0x88B8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x89E1,0xE571,0xE572, 0, 0, 0,
+ 0, 0, 0,0xE56D, 0,0x8E5C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE56E,0x9461, 0, 0, 0,
+ 0,0xE56F,0xE570,0xE57A, 0, 0, 0,0xE574,
+0xE577, 0, 0, 0, 0, 0,0xE573, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE575, 0,0xE576,0x8ED6,
+ 0,0xE578, 0,0x9260, 0,0x8C75,0x8A61, 0,
+ 0, 0, 0, 0,0xE57B, 0, 0, 0,
+ 0,0x8A5E, 0,0xE581, 0, 0,0xE57C,0xE580,
+ 0, 0, 0, 0,0x94B8, 0, 0, 0,
+ 0,0xE57D, 0, 0,0xE57E,0x9567,0x94D8,0xE582,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x91FB,0xE58C, 0,0xE588, 0, 0,0x89E9, 0,
+0xE586, 0,0x9649,0xE587, 0, 0,0xE584, 0,
+0xE585,0xE58A,0xE58D, 0, 0,0xE58B, 0, 0,
+ 0,0xE589,0xE583, 0, 0, 0, 0, 0,
+0x9277, 0,0xE594, 0,0x96A8, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE592, 0, 0,
+ 0,0xE593, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE58E, 0, 0,0xE590,
+ 0, 0, 0,0xE591, 0, 0, 0,0xE58F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x90E4, 0,0x9858,0xE598, 0,0xE599, 0,
+ 0, 0, 0,0xE59F, 0,0x9049, 0,0xE59B,
+ 0,0xE59E, 0, 0, 0, 0, 0,0xE596,
+0xE595, 0, 0,0xE5A0, 0, 0,0x89DA, 0,
+0xE59C, 0,0xE5A1, 0, 0, 0,0xE59D, 0,
+ 0, 0, 0, 0,0xE59A, 0,0x92B1, 0,
+0xE597, 0, 0, 0, 0, 0, 0,0x9488,
+ 0, 0,0xE5A5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x975A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE5A4,
+ 0, 0,0xE5A3, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE5AC, 0, 0, 0,0xE5A6,
+ 0, 0, 0,0xE5AE, 0, 0, 0, 0,
+ 0, 0,0x9786,0xE5B1, 0,0xE5A8, 0, 0,
+0xE5A9, 0, 0, 0,0xE5AD, 0,0xE5B0,0xE5AF,
+ 0, 0, 0,0xE5A7, 0, 0, 0, 0,
+0xE5AA, 0,0xE5BB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE5B4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE5B2,
+ 0, 0,0xE5B3, 0, 0, 0,0xE5B8,0xE5B9,
+ 0,0x8A49, 0,0x8B61, 0, 0,0xE5B7, 0,
+ 0, 0, 0, 0, 0,0xE5A2, 0, 0,
+ 0, 0, 0, 0, 0,0xE5B6,0xE5BA,0xE5B5,
+ 0,0xE5BC, 0, 0, 0,0xE5BE,0xE5BD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE5C0,0xE5BF,0xE579, 0, 0, 0,0xE5C4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE5C1, 0, 0, 0, 0,0xE5C2, 0,
+ 0,0xE5C3, 0,0xE5C5, 0, 0, 0, 0,
+0x8C8C, 0,0xE5C7, 0,0xE5C6, 0,0x8F4F, 0,
+ 0, 0, 0, 0,0x8D73,0x9FA5, 0, 0,
+ 0, 0,0xE5C8,0x8F70, 0, 0, 0,0x8A58,
+ 0,0xE5C9, 0,0x8971, 0,0x8FD5,0xE5CA, 0,
+ 0,0x8D74,0xE5CB,0x88DF, 0, 0, 0, 0,
+0x955C, 0, 0,0xE5CC, 0, 0, 0, 0,
+0x908A, 0,0xE5D3, 0, 0,0xE5D0, 0,0x928F,
+ 0, 0, 0, 0, 0,0xE5D1,0xE5CE,0x8BDC,
+ 0,0xE5CD,0xE5D4, 0, 0, 0, 0, 0,
+0x8C55, 0, 0,0x91DC, 0,0xE5DA, 0, 0,
+ 0, 0,0xE5D6, 0, 0, 0,0x91B3,0xE5D5,
+ 0,0xE5D8, 0, 0, 0, 0,0xE5CF, 0,
+ 0, 0,0xE5D9, 0,0xE5DB, 0, 0, 0,
+ 0, 0, 0,0x94ED, 0, 0,0xE5D7, 0,
+0xE5DC,0xE5DE, 0, 0,0x8CD1,0xE5D2, 0,0x88BF,
+ 0, 0, 0, 0, 0, 0, 0,0xE5DD,
+ 0,0x8DD9,0x97F4,0xE5DF,0xE5E0,0x9195, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x97A0,
+ 0, 0, 0, 0,0xE5E1,0x9754, 0, 0,
+0xE5E2,0xE5E3, 0, 0,0x95E2,0xE5E4, 0,0x8DBE,
+ 0,0x97A1, 0, 0, 0, 0, 0, 0,
+0xE5E9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE5EA,0x8FD6,0xE5E8, 0, 0, 0,
+0x9787,0xE5E5, 0, 0,0xE5E7,0x90BB,0x909E, 0,
+ 0, 0,0xE5E6, 0,0xE5EB, 0, 0,0x95A1,
+ 0, 0,0xE5ED, 0,0xE5EC, 0, 0, 0,
+0x8A8C, 0,0x964A,0xE5EE, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE5FA,0xE5F0, 0,
+ 0, 0, 0, 0, 0,0xE5F1, 0, 0,
+ 0, 0,0xE5F2,0xE5F3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE5F7, 0,
+0xE5F8, 0, 0,0xE5F6, 0, 0, 0, 0,
+ 0,0xE5F4, 0,0xE5EF,0xE5F5, 0, 0, 0,
+ 0, 0, 0, 0,0xE5F9,0xE8B5, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x89A6, 0,
+ 0, 0, 0, 0, 0, 0,0xE5FC,0x8BDD,
+0xE5FB, 0, 0, 0,0xE641, 0,0xE640, 0,
+ 0, 0,0xE643, 0, 0,0xE642, 0,0xE644,
+ 0, 0,0x8F50, 0,0xE645, 0, 0,0xE646,
+ 0, 0, 0, 0, 0, 0,0xE647,0x90BC,
+ 0,0x9776, 0,0xE648, 0, 0,0x95A2,0x9465,
+0xE649, 0,0xE64A,0x8CA9, 0, 0, 0,0x8B4B,
+ 0, 0, 0,0xE64B, 0, 0,0x8E8B,0x9460,
+0xE64C, 0,0x8A6F, 0, 0, 0, 0, 0,
+ 0,0xE64D, 0, 0, 0, 0,0xE64F,0x9797,
+ 0,0xE64E,0x9065, 0,0xE650, 0, 0,0xE651,
+ 0, 0,0xE652,0x8ACF, 0, 0, 0, 0,
+ 0, 0,0xE653, 0, 0,0xE654, 0,0xE655,
+0xE656, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8A70, 0, 0, 0, 0, 0,
+ 0, 0,0xE657, 0,0xE658,0xE659, 0, 0,
+ 0, 0, 0,0x89F0, 0, 0,0x9047,0xE65A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE65B, 0, 0, 0,
+0xE65C, 0, 0, 0, 0, 0, 0, 0,
+0x8CBE, 0,0x92F9,0xE65D, 0, 0, 0, 0,
+0x8C76, 0,0x9075, 0,0xE660, 0,0x93A2, 0,
+0xE65F, 0, 0,0x8C50, 0, 0,0xE65E,0x91F5,
+0x8B4C, 0, 0,0xE661, 0,0xE662, 0,0x8FD7,
+ 0, 0, 0,0x8C8D, 0,0xE663, 0, 0,
+ 0, 0,0x964B, 0, 0,0x90DD, 0, 0,
+ 0,0x8B96, 0,0x96F3,0x9169, 0,0xE664, 0,
+ 0, 0,0x9066,0x9290,0x8FD8, 0, 0, 0,
+ 0,0xE665, 0, 0, 0, 0,0xE668, 0,
+0xE669, 0, 0, 0, 0, 0, 0, 0,
+0x8DBC,0x91C0,0xE667, 0,0x8FD9,0x955D, 0, 0,
+ 0, 0, 0,0xE666, 0, 0,0x8E8C, 0,
+0x8972, 0,0xE66D,0x8C77, 0, 0,0x8E8E, 0,
+ 0,0x8E8D, 0,0x986C,0xE66C,0xE66B,0x9146, 0,
+0x8B6C,0x9862,0x8A59,0x8FDA, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE66A, 0, 0, 0,
+ 0, 0,0xE66F, 0,0xE670,0xE66E, 0,0x8CD6,
+ 0,0x975F, 0, 0,0x8E8F,0x9446, 0, 0,
+ 0,0xE673, 0,0x90BE, 0,0x9261, 0, 0,
+0x9755, 0,0xE676, 0, 0, 0,0x8CEA, 0,
+0x90BD,0xE672, 0,0xE677,0x8CEB,0xE674,0xE675, 0,
+0xE671, 0, 0, 0,0x90E0,0x93C7, 0, 0,
+0x924E, 0,0x89DB, 0, 0, 0, 0, 0,
+ 0,0x94EE, 0, 0,0x8B62, 0, 0,0x92B2,
+ 0, 0,0xE67A, 0,0xE678, 0, 0,0x926B,
+ 0, 0, 0,0x90BF,0x8AD0,0xE679, 0,0x907A,
+ 0, 0,0x97C8, 0, 0, 0,0x985F, 0,
+ 0, 0,0xE67B,0xE687,0x92B3, 0,0xE686, 0,
+0xE683,0xE68B,0xE684, 0,0xE680, 0,0x92FA,0xE67E,
+ 0, 0, 0,0xE67C, 0,0x9740,0x8E90, 0,
+ 0,0xE681, 0,0xE67D, 0, 0, 0,0xE685,
+0x8F94, 0,0x8CBF, 0, 0, 0,0x91F8, 0,
+0x9664,0x8979,0x88E0, 0,0x93A3, 0, 0,0xE689,
+ 0, 0, 0, 0,0xE688, 0,0x93E4, 0,
+0xE68D, 0, 0, 0,0xE682, 0,0xE68C,0xE68E,
+ 0,0x8CAA,0xE68A,0x8D75, 0,0x8ED3, 0, 0,
+0xE68F,0x9777, 0, 0, 0, 0,0xE692, 0,
+0xE695, 0, 0,0xE693,0x9554, 0, 0, 0,
+ 0, 0, 0,0xE690, 0, 0, 0, 0,
+ 0,0x8BDE, 0, 0, 0, 0,0xE694, 0,
+ 0,0xE696, 0, 0, 0, 0, 0, 0,
+ 0,0xE69A, 0, 0,0xE697, 0,0xE699,0xE698,
+ 0, 0, 0, 0, 0, 0,0xE69B, 0,
+0x8EAF, 0,0xE69D,0xE69C,0x9588, 0, 0,0xE69F,
+ 0, 0, 0, 0, 0, 0,0x8C78, 0,
+ 0, 0, 0,0xE69E,0xE6A0, 0, 0,0xE6A1,
+0x8B63,0xE3BF,0x8FF7, 0,0xE6A2, 0, 0,0x8CEC,
+ 0, 0, 0, 0, 0,0xE6A3, 0, 0,
+0xE6A4, 0, 0,0x8E5D, 0, 0, 0, 0,
+ 0, 0,0x9DCC, 0,0xE6A5, 0,0xE6A6, 0,
+0x8F51, 0,0xE6A7,0xE6A8, 0, 0,0xE6A9, 0,
+ 0,0xE6AA,0xE6AB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x924A,
+ 0, 0,0xE6AC, 0, 0, 0, 0,0xE6AE,
+ 0,0xE6AD, 0, 0, 0, 0,0x93A4, 0,
+0xE6AF, 0,0x964C, 0,0xE6B0, 0,0xE6B1, 0,
+0xE6B2, 0, 0, 0, 0,0xE6B3, 0, 0,
+ 0, 0,0x93D8, 0, 0, 0, 0, 0,
+ 0,0x8FDB,0xE6B4, 0, 0, 0, 0, 0,
+ 0, 0,0x8D8B,0x98AC,0xE6B5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE6B6,0x955E,0xE6B7, 0,0xE6BF, 0, 0, 0,
+ 0, 0,0xE6B8, 0, 0,0xE6BA, 0, 0,
+ 0,0xE6B9,0xE6BB, 0,0x9665,0xE6BC,0xE6BD, 0,
+ 0, 0, 0, 0,0xE6BE, 0, 0, 0,
+0xE6C0, 0, 0, 0, 0,0x8A4C,0x92E5, 0,
+0x9589,0x8DE0,0x8D76, 0, 0, 0, 0,0x956E,
+0x89DD,0x94CC,0xE6C3,0x8AD1,0x90D3,0xE6C2,0xE6C7,0x9299,
+0x96E1, 0,0xE6C5,0xE6C6,0x8B4D, 0,0xE6C8,0x9483,
+0x91DD, 0, 0,0x94EF,0x935C,0xE6C4, 0,0x9666,
+0x89EA,0xE6CA,0x9847,0x92C0,0x9864, 0, 0,0x8E91,
+0xE6C9, 0,0x91AF, 0, 0,0xE6DA,0x9147, 0,
+ 0,0x93F6, 0,0x956F, 0, 0, 0, 0,
+ 0, 0,0xE6CD,0x8E5E,0x8E92, 0,0x8FDC, 0,
+0x9485, 0,0x8CAB,0xE6CC,0xE6CB, 0,0x958A, 0,
+ 0, 0,0x8EBF, 0, 0,0x9371, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE6CF,0xE6D0,0x8D77,0xE6CE, 0, 0,
+ 0, 0, 0, 0,0xE6D1,0xE6D2, 0,0xE6D4,
+0x91A1, 0,0xE6D3,0x8AE4, 0,0xE6D6, 0,0xE6D5,
+0xE6D7, 0, 0,0xE6D9,0xE6DB, 0,0xE6DC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x90D4, 0,0x8ECD,0xE6DD,
+ 0, 0, 0,0x8A71, 0,0xE6DE, 0, 0,
+0x9196,0xE6DF, 0,0xE6E0,0x958B, 0, 0,0x8B4E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE6E1, 0, 0, 0,0x92B4, 0, 0,
+ 0, 0,0x897A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE6E2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8EEF, 0, 0, 0, 0,
+0x9096, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x91AB, 0, 0, 0, 0,
+ 0, 0,0xE6E5, 0, 0, 0,0xE6E4, 0,
+ 0, 0,0xE6E3, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE6EB,0xE6E9, 0, 0,0xE6E6,
+ 0, 0, 0, 0, 0, 0,0xE6E8, 0,
+ 0, 0,0xE6E7,0xE6EA, 0,0x8B97, 0,0xE6EE,
+ 0,0x90D5, 0,0xE6EF, 0, 0, 0, 0,
+0x8CD7, 0,0xE6EC,0xE6ED, 0, 0, 0,0x9848,
+ 0, 0, 0,0x92B5, 0,0x9148, 0, 0,
+ 0, 0, 0, 0,0xE6F0, 0, 0,0xE6F3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE6F1,0xE6F2,0x9778, 0, 0, 0, 0,0x93A5,
+0xE6F6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE6F4,0xE6F5,0xE6F7,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE748, 0, 0, 0, 0, 0,
+0xE6FA, 0, 0, 0,0xE6FB,0xE6F9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE6F8, 0,0x92FB, 0, 0,0xE740,
+0xE744,0xE741,0xE6FC, 0,0xE742, 0, 0, 0,
+0xE743, 0, 0, 0, 0,0xE74A, 0, 0,
+ 0,0xE745, 0, 0, 0, 0, 0,0x90D6,
+0xE747, 0, 0,0xE749,0xE746, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE74C, 0,0x8F52, 0,0xE74B, 0,
+ 0, 0, 0, 0,0xE74D, 0, 0, 0,
+ 0,0xE74E, 0, 0,0xE751,0xE750, 0,0xE74F,
+ 0, 0,0xE753,0xE752, 0,0x96F4, 0, 0,
+ 0,0xE755, 0,0xE754,0xE756, 0, 0, 0,
+ 0,0xE757, 0, 0, 0, 0, 0, 0,
+ 0,0xE759, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE758,0x9067,0xE75A, 0, 0,0x8BEB,
+0xE75B,0xE75D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE75E, 0,
+ 0, 0, 0, 0, 0,0xE75F,0xE75C, 0,
+0xE760, 0,0x8ED4,0xE761,0x8B4F,0x8C52, 0, 0,
+ 0, 0,0x8CAC, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE762, 0, 0, 0,0x93EE,
+ 0, 0,0x935D,0xE763, 0, 0, 0, 0,
+ 0, 0, 0,0xE766, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8EB2, 0, 0,0xE765,0xE764,0x8C79,0xE767, 0,
+ 0, 0, 0,0x8A72, 0,0xE769, 0, 0,
+ 0,0x8DDA,0xE768, 0,0xE771, 0, 0, 0,
+ 0, 0,0xE76B,0xE76D,0x95E3,0xE76A, 0, 0,
+ 0,0xE76C, 0,0xE770,0xE76E,0x8B50, 0,0xE76F,
+ 0, 0, 0, 0, 0, 0,0xE772, 0,
+ 0,0x9479,0x97D6, 0, 0, 0, 0,0x8F53,
+ 0, 0, 0,0xE773, 0, 0, 0, 0,
+0x9741,0xE775, 0,0xE774, 0, 0,0xE778,0x9760,
+ 0, 0,0xE777, 0,0x8A8D,0xE776,0xE77B, 0,
+ 0,0xE77A, 0, 0,0xE779,0x9351,0xE77C, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE77D,
+ 0, 0, 0, 0,0xE77E, 0, 0,0x8D8C,
+ 0,0x8C44,0xE780,0xE781,0xE782, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9068,0xE783, 0,0x8EAB,0xE784,
+ 0, 0, 0,0xE785, 0, 0, 0,0x999F,
+0x999E, 0, 0, 0, 0,0xE786,0xE390,0xE787,
+0x9243,0x904A,0x945F, 0, 0, 0, 0,0xE788,
+ 0, 0,0x95D3,0x92D2,0x8D9E, 0, 0,0x9248,
+ 0, 0,0x8949, 0,0x9698,0x9076, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8C7D, 0,
+ 0,0x8BDF, 0, 0,0x95D4, 0, 0, 0,
+ 0, 0,0xE789, 0, 0, 0, 0, 0,
+ 0, 0,0xE78B, 0, 0,0xE78A,0x89DE, 0,
+ 0,0x93F4,0xE78C,0x9497, 0,0x9352, 0,0xE78D,
+0x8F71, 0, 0, 0,0xE78F, 0, 0,0x96C0,
+0xE79E,0xE791,0xE792, 0, 0,0x92C7, 0, 0,
+0x91DE,0x9197, 0,0x93A6, 0,0xE790,0x8B74, 0,
+ 0, 0, 0,0xE799, 0,0xE796,0xE7A3,0x93A7,
+0x9280,0xE793, 0,0x92FC,0x9372,0xE794,0xE798,0x9080,
+ 0,0x9487,0x92CA, 0, 0,0x90C0,0xE797,0x91AC,
+0x91A2,0xE795,0x88A7,0x9841, 0, 0, 0,0xE79A,
+ 0, 0, 0, 0, 0, 0,0x91DF, 0,
+ 0,0x8F54,0x9069, 0, 0,0xE79C,0xE79B, 0,
+0x88ED,0xE79D, 0, 0,0x954E, 0,0xE7A5, 0,
+ 0,0x93D9,0x908B, 0, 0,0x9278, 0,0x8BF6,
+ 0,0xE7A4,0x9756,0x895E, 0,0x95D5,0x89DF,0xE79F,
+0xE7A0,0xE7A1,0xE7A2,0x93B9,0x9242,0x88E1,0xE7A6, 0,
+0xE7A7,0xEAA1, 0, 0,0x91BB, 0,0xE7A8, 0,
+0x8993,0x916B, 0,0x8CAD, 0,0x9779, 0, 0,
+0xE7A9,0x934B, 0, 0, 0,0x9198,0x8ED5,0xE7AA,
+ 0, 0,0xE7AD, 0, 0,0x8F85,0xE7AB,0x914A,
+0x9149, 0,0x88E2, 0,0x97C9,0xE7AF, 0,0x94F0,
+0xE7B1,0xE7B0,0xE7AE,0xE284,0x8AD2, 0, 0,0xE78E,
+ 0,0xE7B3,0xE7B2, 0, 0, 0, 0,0xE7B4,
+ 0,0x9757, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x93DF, 0, 0,0x964D, 0,
+0xE7B5, 0,0x8ED7, 0, 0, 0, 0,0xE7B6,
+ 0,0xE7B7, 0, 0, 0,0xE7B8, 0, 0,
+0x9340, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x88E8, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8D78, 0, 0, 0,0x9859, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE7BC, 0, 0, 0, 0,
+ 0,0x8C53,0xE7B9, 0,0xE7BA, 0, 0, 0,
+0x9594, 0, 0, 0, 0,0x8A73, 0, 0,
+ 0, 0, 0, 0, 0,0x9758, 0,0x8BBD,
+ 0, 0, 0, 0, 0,0x9373, 0, 0,
+ 0, 0,0xE7BD, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE7BE, 0, 0, 0, 0, 0,
+ 0,0xE7BF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9341, 0, 0,
+0xE7C1, 0,0xE7C0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x93D1,0xE7C2,0x8F55,0x8EDE,0x947A,0x9291, 0,
+ 0, 0,0x8EF0, 0,0x908C, 0,0xE7C3, 0,
+0xE7C4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x907C,0xE7C5, 0,0xE7C6, 0, 0,
+ 0,0xE7C7,0x978F, 0,0x8F56, 0, 0, 0,
+ 0, 0,0xE7C9,0xE7C8, 0,0x8D79, 0,0x8D93,
+0x8E5F, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE7CC, 0, 0, 0, 0,0x8F86,
+ 0,0xE7CB, 0,0xE7CA, 0,0x91E7, 0, 0,
+0x8CED, 0,0x90C1, 0, 0, 0, 0,0x94AE,
+ 0, 0, 0, 0,0x8F58, 0, 0, 0,
+ 0, 0,0xE7CD, 0,0x8FDD, 0, 0, 0,
+ 0, 0,0xE7D0,0xE7CE, 0, 0, 0,0xE7CF,
+ 0, 0, 0, 0,0xE7D2,0xE7D1, 0, 0,
+0x8FF8, 0,0xE7D3, 0, 0, 0, 0, 0,
+0xE7D4,0xE7D5, 0, 0, 0, 0,0x94CE,0x8DD1,
+0x8EDF,0xE7D6, 0,0xE7D7,0x97A2,0x8F64,0x96EC,0x97CA,
+0xE7D8,0x8BE0, 0, 0, 0, 0,0xE7D9, 0,
+0x9342, 0, 0,0xE7DC,0x8A98,0x906A, 0,0xE7DA,
+ 0,0xE7DB, 0,0x92DE, 0, 0,0x9674,0x8BFA,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE7DE,0xE7DF, 0,
+ 0, 0, 0, 0,0xE7DD, 0, 0,0xE7E1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x93DD,0x8A62, 0,
+ 0,0xE7E5, 0, 0,0xE7E2,0xE7E4, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE7E0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE86E, 0, 0,0xE7E3, 0, 0, 0,
+ 0, 0, 0, 0,0x97E9, 0, 0,0x8CD8,
+ 0, 0, 0, 0, 0, 0, 0,0xE7ED,
+ 0, 0, 0, 0,0x9353,0xE7E8, 0, 0,
+0xE7EB,0xE7E9, 0,0xE7EE, 0, 0, 0, 0,
+0xE7EF, 0, 0, 0, 0, 0, 0,0xE7E7,
+ 0, 0,0xE7F4,0x8994, 0, 0,0xE7E6, 0,
+ 0, 0,0x94AB, 0,0xE7EA, 0,0x8FDE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8D7A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x9667, 0,
+0x8BE2, 0, 0,0x8F65, 0,0x93BA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x914C, 0,0xE7F2, 0,0xE7EC,0xE7F1, 0,
+0x96C1, 0,0x92B6,0xE7F3,0xE7F0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x914B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE7F7,
+ 0,0xE7F6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE7F5,
+ 0, 0,0x964E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8F9B, 0, 0, 0,
+ 0,0xE7F8,0x95DD, 0, 0,0x8973, 0, 0,
+ 0, 0,0x9565,0x9292, 0, 0, 0, 0,
+0x8B98, 0,0xE7FA, 0,0x8D7C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8E4B, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE7F9,
+0x908D, 0, 0, 0, 0, 0, 0, 0,
+0x908E,0xE840,0xE842, 0, 0, 0, 0, 0,
+0x8FF9, 0,0xE841,0xE843, 0, 0,0x8BD1, 0,
+0x9564, 0, 0,0x8EE0,0x9842, 0,0xE7FC,0x8DF6,
+ 0, 0,0x985E, 0, 0,0xE845, 0, 0,
+ 0, 0,0xE844,0xE846, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE7FB, 0, 0, 0,
+ 0, 0, 0,0x93E7, 0,0x9374, 0, 0,
+ 0, 0, 0, 0,0x92D5, 0,0xE84B, 0,
+ 0, 0, 0,0x9262,0xE847, 0, 0, 0,
+0xE848, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8C4C, 0,0xE84A, 0,
+ 0, 0, 0, 0, 0,0x8CAE, 0, 0,
+ 0, 0, 0, 0,0xE849, 0,0x8FDF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8A99, 0, 0, 0,
+ 0, 0, 0, 0,0xE84F, 0,0x8DBD,0x9199,
+ 0, 0,0x92C8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x8A5A,
+ 0, 0, 0, 0,0xE84D,0xE84E,0x92C1, 0,
+0xE84C, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE850, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE856, 0, 0, 0, 0,
+0xE859, 0, 0, 0, 0, 0, 0, 0,
+0xE858,0x934C, 0, 0, 0, 0,0xE851,0xE852,
+0xE855, 0, 0, 0, 0,0xE857, 0, 0,
+ 0,0x8BBE, 0, 0,0xE85A,0xE854, 0, 0,
+0xE853, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE85E, 0, 0, 0,0xE85F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE860, 0, 0,0xE85D,0xE85C, 0, 0, 0,
+0x8FE0,0x93A8,0xE85B, 0, 0, 0, 0, 0,
+ 0,0xE864, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE862, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE863,0xE861, 0,
+0x91F6, 0,0xE865, 0, 0, 0, 0, 0,
+ 0,0xE866, 0, 0,0xE868, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8AD3,0xE867,0x96F8, 0, 0, 0, 0,
+ 0, 0,0xE873,0xE869, 0, 0,0xE86C, 0,
+0xE86A, 0,0xE86B, 0, 0, 0, 0, 0,
+ 0, 0,0xE86D, 0, 0, 0, 0, 0,
+0xE86F, 0, 0, 0, 0,0xE870, 0,0xE871,
+ 0, 0, 0, 0,0xE874,0xE872,0xE875,0xE877,
+ 0,0xE876};
+
+/* page 6 0x9577-0x9FA0 */
+static uint16 tab_uni_sjis6[]={
+0x92B7, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x96E5, 0,0xE878,0x914D, 0, 0, 0,
+0xE879, 0,0x95C2,0xE87A,0x8A4A, 0, 0, 0,
+0x895B, 0,0x8AD5, 0,0x8AD4,0xE87B, 0,0xE87C,
+ 0,0xE87D,0xE87E, 0, 0, 0, 0, 0,
+ 0,0xE880, 0,0x8AD6,0x8A74,0x8D7D,0x94B4, 0,
+0xE882,0xE881, 0, 0, 0, 0,0xE883, 0,
+ 0, 0, 0,0x897B, 0, 0, 0, 0,
+ 0, 0,0xE886, 0,0xE885,0xE884, 0,0xE887,
+ 0, 0, 0, 0,0xE88A, 0, 0, 0,
+0x88C5, 0, 0,0xE888, 0,0xE88C,0xE88B, 0,
+ 0, 0, 0, 0, 0,0xE88E,0xE88D,0xE88F,
+ 0,0x93AC, 0, 0, 0,0xE890, 0, 0,
+ 0, 0,0xE891,0xE893, 0, 0,0xE892, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x958C, 0, 0,
+ 0, 0,0xE894, 0, 0, 0, 0, 0,
+ 0,0xE895, 0,0x8DE3, 0, 0, 0,0xE896,
+0xE897, 0, 0,0x9668, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x916A, 0, 0, 0,
+0x88A2,0x91C9, 0,0xE898, 0,0x958D, 0, 0,
+ 0, 0, 0, 0,0xE89B,0xE899,0x8D7E, 0,
+0xE89A,0x8CC0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x95C3,0xE89D,0xE89F,0xE89E,
+0xE8A0, 0, 0,0x8940,0x9077,0x8F9C,0x8AD7,0xE8A1,
+ 0, 0, 0,0x9486, 0,0xE8A3, 0, 0,
+ 0,0x8941, 0,0xE8A2,0x92C2, 0,0x97CB,0x93A9,
+0xE89C,0x97A4, 0,0x8CAF, 0, 0,0x977A, 0,
+ 0, 0, 0, 0, 0, 0,0x8BF7,0x97B2,
+ 0,0x8C47, 0,0x91E0,0xE440, 0,0xE8A4,0x8A4B,
+0x908F, 0, 0, 0, 0,0x8A75,0xE8A6, 0,
+0xE8A7,0xE8A5,0x8C84, 0,0x8DDB,0x8FE1, 0, 0,
+ 0,0x8942, 0, 0,0x97D7, 0, 0, 0,
+0xE8A9,0xE7AC, 0,0xE8A8, 0, 0, 0, 0,
+ 0,0xE8AC,0xE8AA,0xE8AB, 0,0xE8AD, 0,0xE8AE,
+0x97EA,0xE8AF,0xE8B0, 0,0x90C7,0x94B9, 0, 0,
+ 0,0x909D,0x8AE5, 0, 0,0x9759,0x89EB,0x8F57,
+0x8CD9, 0,0xE8B3, 0,0xE8B2,0x8E93,0xE8B4,0xE8B1,
+ 0, 0,0x8E47, 0, 0, 0,0xE8B8,0xE5AB,
+ 0, 0,0x99D4, 0,0x9097,0xE8B6, 0, 0,
+ 0, 0, 0,0x97A3,0x93EF, 0, 0, 0,
+ 0,0x894A, 0,0x90E1,0x8EB4, 0, 0, 0,
+ 0,0x95B5, 0,0x895F, 0, 0, 0,0x97EB,
+0x978B, 0,0xE8B9, 0,0x9364, 0, 0, 0,
+ 0,0x8EF9, 0, 0, 0,0xE8BA, 0,0xE8BB,
+0x906B,0xE8BC, 0,0x97EC, 0, 0,0xE8B7,0xE8BE,
+0xE8C0, 0,0xE8BF, 0,0xE8BD, 0, 0,0xE8C1,
+ 0, 0,0xE8C2, 0, 0,0x919A, 0,0x89E0,
+ 0, 0, 0, 0, 0,0xE8C3, 0, 0,
+0x96B6, 0, 0,0xE8C4, 0, 0, 0, 0,
+ 0,0xE8C5, 0,0x9849, 0, 0, 0, 0,
+ 0,0x9E50,0xE8C6, 0, 0, 0,0xE8C7,0xE8C8,
+ 0, 0, 0,0xE8CC, 0,0xE8C9, 0,0xE8CA,
+ 0,0xE8CB,0xE8CD, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x90C2, 0, 0, 0,0x96F5,
+ 0, 0,0x90C3, 0, 0,0xE8CE, 0,0x94F1,
+ 0,0xE8CF,0xEA72,0x96CA, 0,0xE8D0, 0,0xE8D1,
+ 0,0xE8D2,0x8A76, 0,0xE8D4, 0,0x9078, 0,
+ 0, 0,0xE8D5, 0, 0,0x8C43, 0, 0,
+ 0, 0,0xE8D6,0xE8DA, 0,0xE8D8, 0, 0,
+ 0, 0,0xE8D9, 0, 0,0x8A93,0xE8D7,0xE8DB,
+ 0, 0, 0, 0,0xE8DC, 0,0x88C6, 0,
+0xE8DD,0xE8DE, 0, 0, 0, 0, 0, 0,
+ 0,0x8FE2, 0, 0, 0,0xE8DF, 0, 0,
+ 0,0x8B66, 0, 0,0xE8E2, 0, 0,0xE8E1,
+ 0,0xE8E0, 0, 0,0xE691, 0,0x95DA, 0,
+ 0, 0, 0, 0,0xE8E3,0xE8E4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE8E5, 0, 0,0xE8E6,
+ 0,0xE8E7, 0, 0,0xE8E8, 0, 0, 0,
+ 0, 0, 0, 0,0x8AD8, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE8E9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE8EA,0x9442,
+ 0, 0, 0,0xE8EC,0x89B9, 0,0xE8EF,0xE8EE,
+ 0, 0, 0, 0,0x8943, 0, 0, 0,
+0x8BBF, 0,0x95C5,0x92B8,0x8DA0, 0,0x8D80,0x8F87,
+ 0,0x907B, 0, 0, 0,0xE8F1, 0, 0,
+0xE8F0,0x9761,0x8AE6,0x94D0,0x93DA, 0, 0, 0,
+0x909C,0x97CC, 0,0x8C7A, 0, 0, 0, 0,
+ 0, 0,0xE8F4, 0, 0,0xE8F3, 0, 0,
+ 0, 0, 0, 0, 0,0x966A,0x93AA, 0,
+ 0, 0, 0, 0, 0,0x896F, 0, 0,
+0xE8F5,0xE8F2, 0, 0,0x9570,0x978A,0xE8F6, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE8F7,
+ 0, 0, 0, 0,0xE8F9,0x91E8,0x8A7A,0x8A7B,
+0xE8F8, 0, 0, 0, 0,0x8AE7,0x8CB0, 0,
+ 0,0x8AE8, 0, 0,0x935E, 0, 0,0x97DE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x8CDA, 0, 0, 0,0xE8FA, 0, 0, 0,
+0xE8FB,0xE8FC,0xE940, 0,0xE942,0xE941, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x9597, 0,0xE943, 0, 0, 0, 0,
+0xE944, 0,0xE945, 0, 0, 0, 0,0xE946,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE948,0xE947, 0,0xE949,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x94F2,0xE3CA, 0, 0,
+0x9048, 0, 0,0x8B51, 0, 0, 0, 0,
+ 0, 0,0xE94A, 0,0xE94B, 0,0x99AA,0x9F5A,
+0x94D1, 0, 0,0x88F9, 0,0x88B9, 0, 0,
+ 0, 0, 0, 0, 0,0x8E94,0x964F,0x8FFC,
+ 0, 0, 0, 0,0xE94C, 0,0x96DD, 0,
+ 0, 0,0xE94D,0x977B, 0,0x8961, 0, 0,
+ 0,0x8E60, 0,0xE94E,0x89EC,0xE94F, 0, 0,
+ 0,0xE950, 0, 0, 0, 0,0xE952,0xE953,
+ 0,0xE955,0xE951, 0, 0,0xE954, 0, 0,
+ 0,0x8AD9, 0, 0, 0,0xE956, 0,0xE957,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE958,0xE959,
+ 0, 0, 0,0xE95A, 0, 0,0xE95C, 0,
+ 0, 0,0xE95B, 0,0xE95E,0xE961, 0, 0,
+ 0,0xE95D,0xE95F,0xE960, 0, 0,0xE962, 0,
+0x8BC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x8EF1,
+0xE963,0xE964,0x8D81, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE965, 0,
+ 0,0x8A5D, 0, 0, 0,0x946E,0xE966,0xE967,
+ 0, 0, 0, 0,0x9279,0x93E9, 0, 0,
+ 0, 0, 0, 0, 0,0xE968, 0, 0,
+ 0, 0,0x949D, 0, 0,0x91CA,0x8977,0x8BEC,
+ 0,0x8BED, 0, 0, 0, 0, 0, 0,
+ 0,0x9293,0xE96D,0x8BEE, 0, 0,0x89ED, 0,
+ 0,0xE96C, 0, 0,0xE96A, 0,0xE96B, 0,
+0xE969, 0, 0,0xE977, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xE96E,0xE96F,
+ 0, 0,0xE970,0xE971, 0, 0, 0, 0,
+ 0,0xE973, 0, 0,0xE972, 0, 0, 0,
+0x8F78, 0,0xE974, 0, 0, 0,0xE976, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x8B52,
+0xE975, 0, 0,0x919B,0x8CB1, 0, 0, 0,
+ 0, 0,0xE978, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x91CB, 0, 0,0xE979, 0, 0, 0,
+ 0,0x93AB, 0, 0, 0, 0, 0, 0,
+0xE97A, 0, 0, 0, 0, 0, 0,0xE980,
+ 0,0xE97D, 0,0xE97C,0xE97E, 0,0xE97B, 0,
+ 0, 0, 0, 0, 0, 0,0xE982, 0,
+ 0, 0, 0, 0, 0, 0,0xE981, 0,
+0xE984, 0, 0,0x8BC1,0xE983, 0, 0, 0,
+0xE985, 0, 0,0xE986, 0,0xE988,0xE987, 0,
+ 0, 0,0xE989,0xE98B,0xE98A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x8D9C, 0, 0, 0, 0,0xE98C, 0,
+ 0,0xE98D, 0, 0, 0, 0, 0, 0,
+ 0,0x8A5B, 0, 0, 0,0xE98E, 0, 0,
+ 0,0xE98F, 0, 0, 0,0x9091, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xE990, 0,0xE991, 0,0xE992,0xE993, 0, 0,
+ 0,0x8D82, 0, 0, 0, 0, 0,0xE994,
+0xE995, 0, 0,0xE996,0xE997, 0, 0,0xE998,
+ 0, 0, 0,0x94AF,0xE99A, 0,0x9545,0xE99B,
+0xE999, 0,0xE99D, 0, 0,0xE99C, 0, 0,
+0xE99E, 0, 0, 0,0xE99F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE9A0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE9A1, 0,0xE9A2, 0, 0, 0, 0,
+0xE9A3, 0, 0,0xE9A4,0xE9A5, 0,0xE9A6, 0,
+0xE9A7,0xE9A8,0xE9A9,0xE9AA, 0, 0, 0,0xE9AB,
+0xE9AC, 0,0x9F54,0xE9AD, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE2F6,0x8B53, 0, 0,
+ 0, 0,0x8A40,0x8DB0,0xE9AF,0xE9AE,0x96A3, 0,
+ 0, 0, 0, 0, 0, 0,0xE9B1,0xE9B2,
+0xE9B0, 0,0xE9B3, 0, 0,0x9682, 0, 0,
+ 0,0xE9B4, 0,0x8B9B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x9844, 0, 0, 0, 0,0xE9B5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE9B7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x88BC,
+ 0, 0,0xE9B8,0x95A9,0xE9B6, 0, 0,0xE9B9,
+0xE9BA, 0, 0, 0, 0, 0, 0, 0,
+0xE9BB,0xE9BC, 0, 0, 0, 0, 0, 0,
+ 0,0xE9BD, 0,0x968E,0x8E4C, 0,0x8DF8,0x914E,
+ 0, 0, 0, 0, 0,0xE9BE, 0, 0,
+ 0, 0,0xE9C1, 0, 0, 0, 0, 0,
+ 0,0xE9BF, 0, 0, 0, 0, 0,0xE9C2,
+ 0, 0,0x8CEF,0xE9C0, 0, 0, 0, 0,
+0xE9C3, 0,0xE9C4,0xE9C5, 0,0xE9C9, 0,0x8E49,
+ 0, 0, 0, 0,0x91E2, 0, 0, 0,
+ 0, 0,0xE9CA,0xE9C7,0xE9C6,0xE9C8, 0, 0,
+ 0,0x8C7E, 0, 0, 0, 0, 0, 0,
+ 0,0xE9CE,0xE9CD,0xE9CC, 0, 0,0x88B1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xE9D8, 0,0xE9D4,
+ 0,0xE9D5,0xE9D1,0xE9D7, 0,0xE9D3,0x8A82, 0,
+ 0,0x986B, 0,0xE9D6,0xE9D2,0xE9D0,0xE9CF, 0,
+ 0, 0, 0, 0,0xE9DA, 0, 0, 0,
+ 0, 0,0xE9DD, 0, 0,0xE9DC,0xE9DB, 0,
+ 0, 0, 0, 0, 0, 0,0x9568,0xE9D9,
+0x88F1,0xE9DE, 0,0xE9E0, 0, 0, 0, 0,
+ 0, 0,0x8A8F,0xE9CB,0x8956, 0, 0,0xE9E2,
+ 0, 0, 0, 0, 0, 0, 0,0xE9E1,
+0xE9DF,0x924C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x9690, 0, 0, 0, 0,
+0x97D8, 0, 0,0xE9E3, 0, 0, 0, 0,
+ 0,0xE9E4, 0, 0, 0, 0, 0, 0,
+0xE9E5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE9E6,
+ 0,0xE9E7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x92B9, 0,
+0xE9E8, 0,0x94B5, 0,0xE9ED,0xE9E9, 0, 0,
+ 0,0xE9EA, 0, 0,0x9650,0x96C2, 0,0x93CE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE9EE, 0, 0,0xE9EF,
+0x93BC,0xE9EC,0xE9EB, 0, 0, 0, 0,0x89A8,
+ 0, 0, 0,0xE9F7, 0, 0,0xE9F6, 0,
+ 0, 0, 0, 0,0x8995, 0, 0, 0,
+0xE9F4, 0, 0, 0,0xE9F3, 0, 0,0xE9F1,
+ 0,0x8A9B, 0,0xE9F0,0x8EB0,0x89A7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8D83, 0, 0,0xE9FA,
+0xE9F9, 0,0xE9F8, 0, 0,0xE9F5, 0,0xE9FB,
+ 0,0xE9FC, 0, 0, 0, 0, 0, 0,
+ 0,0xEA44,0xEA43, 0, 0, 0, 0, 0,
+ 0, 0,0xEA45, 0, 0,0x894C,0xEA40,0xEA41,
+ 0,0x8D94,0x96B7, 0, 0,0xEA42, 0, 0,
+ 0, 0, 0, 0, 0,0x9651, 0, 0,
+0xEA4A, 0, 0,0xEA46, 0, 0, 0, 0,
+ 0, 0, 0,0xEA4B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEA48, 0,0xEA47, 0, 0, 0, 0, 0,
+0x8C7B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEA4C, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xEA4D, 0, 0,
+ 0, 0,0xEA4E, 0,0xEA49, 0, 0, 0,
+0xE9F2, 0, 0,0xEA4F, 0,0x92DF, 0, 0,
+ 0,0xEA53, 0,0xEA54,0xEA52, 0, 0, 0,
+ 0, 0,0xEA51,0xEA57, 0,0xEA50, 0,0xEA55,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEA56, 0, 0, 0,0xEA59, 0, 0, 0,
+ 0, 0,0xEA58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEA5B,
+ 0, 0, 0, 0, 0, 0,0xEA5C, 0,
+0xEA5D, 0, 0,0x9868, 0, 0, 0, 0,
+ 0,0xEA5A,0x91E9,0x8DEB, 0, 0,0xEA5E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEA5F,0xEA60, 0, 0,0xEA61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xEA62, 0,
+ 0,0x8CB2,0xEA63, 0, 0, 0,0xEA64, 0,
+0x8EAD, 0,0xEA65, 0, 0, 0, 0, 0,
+ 0,0xEA66, 0, 0,0xEA67,0xEA68, 0, 0,
+ 0, 0,0xEA6B,0xEA69,0x985B, 0,0xEA6A, 0,
+0x97ED, 0, 0, 0, 0, 0,0xEA6C, 0,
+0x97D9, 0, 0, 0, 0, 0,0xEA6D,0x949E,
+ 0, 0,0xEA6E,0xEA70, 0, 0,0xEA71, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xEA6F,0x8D8D,0x96CB,0x9683,0x9BF5, 0,0x9F80,
+0x969B, 0, 0, 0, 0,0x89A9, 0, 0,
+ 0, 0, 0, 0, 0,0xEA73,0x8B6F,0xEA74,
+0xEA75,0xEA76, 0,0x8D95, 0,0xEA77, 0, 0,
+ 0,0xE0D2,0x96D9, 0,0x91E1,0xEA78,0xEA7A,0xEA79,
+ 0,0xEA7B, 0, 0, 0, 0,0xEA7C, 0,
+ 0,0xEA7D, 0, 0, 0, 0, 0, 0,
+0xEA7E, 0, 0, 0, 0,0xEA80, 0,0xEA81,
+0xEA82, 0,0xEA83, 0,0xEA84,0xEA85,0xEA86, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEA87,0xEA88, 0, 0, 0, 0, 0,0x9343,
+ 0, 0, 0, 0,0x8CDB, 0,0xEA8A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x916C,0xEA8B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xEA8C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x9540, 0, 0,0xEA8D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xEA8E,0xE256, 0, 0,0xE6D8,
+0xE8EB, 0, 0,0xEA8F, 0,0xEA90, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEA92,0xEA93,0xEA94,0x97EE,0xEA91, 0, 0,0xEA95,
+0xEA96, 0, 0,0xEA98, 0,0xEA97, 0, 0,
+ 0, 0, 0,0xEA9A, 0, 0, 0,0xEA9B,
+0xEA99, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x97B4, 0,
+ 0, 0, 0, 0, 0, 0,0xEA9C, 0,
+ 0, 0, 0, 0, 0,0xEA9D,0xE273, 0,
+ 0,0xEA9E};
+
+/* page 7 0xFF01-0xFFE5 */
+static uint16 tab_uni_sjis7[]={
+0x8149, 0,0x8194,0x8190,0x8193,0x8195, 0,0x8169,
+0x816A,0x8196,0x817B,0x8143, 0,0x8144,0x815E,0x824F,
+0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257,
+0x8258,0x8146,0x8147,0x8183,0x8181,0x8184,0x8148,0x8197,
+0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267,
+0x8268,0x8269,0x826A,0x826B,0x826C,0x826D,0x826E,0x826F,
+0x8270,0x8271,0x8272,0x8273,0x8274,0x8275,0x8276,0x8277,
+0x8278,0x8279,0x816D, 0,0x816E,0x814F,0x8151,0x814D,
+0x8281,0x8282,0x8283,0x8284,0x8285,0x8286,0x8287,0x8288,
+0x8289,0x828A,0x828B,0x828C,0x828D,0x828E,0x828F,0x8290,
+0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297,0x8298,
+0x8299,0x829A,0x816F,0x8162,0x8170, 0, 0, 0,
+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,0x00D0,
+0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,
+0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x8150, 0,0x818F};
+
+static int func_uni_sjis_onechar(int code){
+ if ((code>=0x005C)&&(code<=0x00F7))
+ return(tab_uni_sjis0[code-0x005C]);
+ if ((code>=0x0391)&&(code<=0x0451))
+ return(tab_uni_sjis1[code-0x0391]);
+ if ((code>=0x2010)&&(code<=0x2312))
+ return(tab_uni_sjis2[code-0x2010]);
+ if ((code>=0x2500)&&(code<=0x266F))
+ return(tab_uni_sjis3[code-0x2500]);
+ if ((code>=0x3000)&&(code<=0x30FE))
+ return(tab_uni_sjis4[code-0x3000]);
+ if ((code>=0x4E00)&&(code<=0x9481))
+ return(tab_uni_sjis5[code-0x4E00]);
+ if ((code>=0x9577)&&(code<=0x9FA0))
+ return(tab_uni_sjis6[code-0x9577]);
+ if ((code>=0xFF01)&&(code<=0xFFE5))
+ return(tab_uni_sjis7[code-0xFF01]);
+ return(0);
+}
+
+
+static int
+my_wc_mb_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *s, uchar *e)
+{
+ int code;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if(wc<0x80)
+ {
+ s[0]=wc;
+ return 1;
+ }
+
+ if(!(code=func_uni_sjis_onechar(wc)))
+ return MY_CS_ILUNI;
+
+ if(s+2>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=code>>8;
+ s[1]=code&0xFF;
+ return 2;
+}
+
+static int
+my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *pwc, const uchar *s, const uchar *e){
+ int hi=s[0];
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ if(hi<0x80)
+ {
+ pwc[0]=hi;
+ return 1;
+ }
+
+ if(s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ if(!(pwc[0]=func_sjis_uni_onechar((hi<<8)+s[1])))
+ return MY_CS_ILSEQ;
+
+ return 2;
+}
+
+CHARSET_INFO my_charset_sjis =
+{
+ 13, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ "sjis", /* cs name */
+ "sjis", /* name */
+ "", /* comment */
+ ctype_sjis,
+ to_lower_sjis,
+ to_upper_sjis,
+ sort_order_sjis,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 1, /* strxfrm_multiply */
+ my_strnncoll_sjis,
+ my_strnncollsp_sjis,
+ my_strnxfrm_sjis,
+ my_like_range_sjis,
+ my_wildcmp_mb, /* wildcmp */
+ 2, /* mbmaxlen */
+ ismbchar_sjis,
+ ismbhead_sjis,
+ mbcharlen_sjis,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_mb_wc_sjis, /* mb_wc */
+ my_wc_mb_sjis, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ NULL, /* tosort */
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+#endif
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index d5181dc4db0..bf3d332880d 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -49,6 +49,8 @@
#include "m_ctype.h"
#include "t_ctype.h"
+#ifdef HAVE_CHARSET_tis620
+
static uchar* thai2sortable(const uchar *tstr,uint len);
#define BUFFER_MULTIPLY 4
@@ -535,7 +537,9 @@ static uchar* thai2sortable(const uchar * tstr,uint len)
Arg: 2 Strings and it compare length
Ret: strcmp result
*/
-int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
+int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar * s1, uint len1,
+ const uchar * s2, uint len2)
{
uchar *tc1, *tc2;
int i;
@@ -547,11 +551,24 @@ int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
return(i);
}
+static
+int my_strnncollsp_tis620(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_tis620(cs,s,slen,t,tlen);
+}
+
+
/* strnxfrm replacment, convert Thai string to sortable string
Arg: Destination buffer, source string, dest length and source length
Ret: Conveted string size
*/
-int my_strnxfrm_tis620(uchar * dest, const uchar * src, int len, int srclen)
+int my_strnxfrm_tis620(CHARSET_INFO *cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar * src, uint srclen)
{
uint bufSize;
uchar *tmp;
@@ -604,10 +621,10 @@ int my_strxfrm_tis620(uchar * dest, const uchar * src, int len)
thai2sortable string. min_str and max_str will be use for comparison and
converted there. */
#define max_sort_chr ((char) 255)
-#define wild_one '_'
-#define wild_many '%'
-my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
+my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
+ const char *ptr, uint ptr_length,
+ int escape, int w_one, int w_many,
uint res_length, char *min_str, char *max_str,
uint *min_length, uint *max_length)
{
@@ -623,13 +640,13 @@ my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
*min_str++= *max_str++ = *ptr;
continue;
}
- if (*ptr == wild_one) /* '_' in SQL */
+ if (*ptr == w_one) /* '_' in SQL */
{
*min_str++='\0'; /* This should be min char */
*max_str++=max_sort_chr;
continue;
}
- if (*ptr == wild_many) /* '%' in SQL */
+ if (*ptr == w_many) /* '%' in SQL */
{
*min_length= (uint) (min_str - min_org);
*max_length=res_length;
@@ -677,3 +694,56 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
}
}
}
+
+
+CHARSET_INFO my_charset_tis620 =
+{
+ 18, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ "tis620", /* cs name */
+ "tis620", /* name */
+ "", /* comment */
+ ctype_tis620,
+ to_lower_tis620,
+ to_upper_tis620,
+ sort_order_tis620,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 4, /* strxfrm_multiply */
+ my_strnncoll_tis620,
+ my_strnncollsp_tis620,
+ my_strnxfrm_tis620,
+ my_like_range_tis620,
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ NULL, /* tosort */
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+
+#endif
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 650182bfda1..d39be825ef0 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -27,8 +27,12 @@
#include <my_global.h>
#include "m_string.h"
+#include "m_ctype.h"
-uchar NEAR ctype_ujis[257] =
+#ifdef HAVE_CHARSET_ujis
+
+
+static uchar NEAR ctype_ujis[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -65,7 +69,7 @@ uchar NEAR ctype_ujis[257] =
0020, 0020, 0020, 0020, 0020, 0020, 0020, 0000,
};
-uchar NEAR to_lower_ujis[]=
+static uchar NEAR to_lower_ujis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -101,7 +105,7 @@ uchar NEAR to_lower_ujis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-uchar NEAR to_upper_ujis[]=
+static uchar NEAR to_upper_ujis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -137,7 +141,7 @@ uchar NEAR to_upper_ujis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-uchar NEAR sort_order_ujis[]=
+static uchar NEAR sort_order_ujis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -180,7 +184,8 @@ uchar NEAR sort_order_ujis[]=
#define isujis_ss3(c) (((c)&0xff) == 0x8f)
-int ismbchar_ujis(const char* p, const char *e)
+static int ismbchar_ujis(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
{
return ((*(uchar*)(p)<0x80)? 0:\
isujis(*(p)) && (e)-(p)>1 && isujis(*((p)+1))? 2:\
@@ -189,12 +194,8290 @@ int ismbchar_ujis(const char* p, const char *e)
0);
}
-my_bool ismbhead_ujis(uint c)
+static my_bool ismbhead_ujis(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (isujis(c) || isujis_ss2(c) || isujis_ss3(c));
}
-int mbcharlen_ujis(uint c)
+static int mbcharlen_ujis(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (isujis(c)? 2: isujis_ss2(c)? 2: isujis_ss3(c)? 3: 0);
}
+
+
+static uint16 tab_jisx0201_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x00A5,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x203E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,
+0xFF68,0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F,
+0xFF70,0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,
+0xFF78,0xFF79,0xFF7A,0xFF7B,0xFF7C,0xFF7D,0xFF7E,0xFF7F,
+0xFF80,0xFF81,0xFF82,0xFF83,0xFF84,0xFF85,0xFF86,0xFF87,
+0xFF88,0xFF89,0xFF8A,0xFF8B,0xFF8C,0xFF8D,0xFF8E,0xFF8F,
+0xFF90,0xFF91,0xFF92,0xFF93,0xFF94,0xFF95,0xFF96,0xFF97,
+0xFF98,0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+static int
+my_mb_wc_jisx0201(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *wc,const uchar *s,
+ const uchar *e __attribute__((unused)))
+{
+ wc[0]=tab_jisx0201_uni[*s];
+ return (!wc[0] && s[0]) ? MY_CS_ILSEQ : 1;
+}
+
+
+static int
+my_wc_mb_jisx0201(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *s,
+ uchar *e __attribute__((unused)))
+{
+
+ if (wc <= 0x7D)
+ {
+ *s = wc;
+ return (wc == 0x5C) ? MY_CS_ILUNI : 1;
+ }
+
+ if (wc >= 0xFF61 && wc <= 0xFF9F)
+ {
+ *s = (wc - 0xFEC0);
+ return 1;
+ }
+
+ if (wc==0x00A5)
+ {
+ *s = 0x5C;
+ return 1;
+ }
+
+ if (wc==0x203E)
+ {
+ *s = 0x7E;
+ return 1;
+ }
+
+ return MY_CS_ILUNI;
+}
+
+
+/* page 0 0x2121-0x217E */
+static uint16 tab_jisx0208_uni0[]={
+0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
+0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
+0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
+0x3005,0x3006,0x3007,0x30FC,0x2015,0x2010,0xFF0F,0x005C,
+0x301C,0x2016,0xFF5C,0x2026,0x2025,0x2018,0x2019,0x201C,
+0x201D,0xFF08,0xFF09,0x3014,0x3015,0xFF3B,0xFF3D,0xFF5B,
+0xFF5D,0x3008,0x3009,0x300A,0x300B,0x300C,0x300D,0x300E,
+0x300F,0x3010,0x3011,0xFF0B,0x2212,0x00B1,0x00D7,0x00F7,
+0xFF1D,0x2260,0xFF1C,0xFF1E,0x2266,0x2267,0x221E,0x2234,
+0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFFE5,0xFF04,
+0x00A2,0x00A3,0xFF05,0xFF03,0xFF06,0xFF0A,0xFF20,0x00A7,
+0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7};
+
+/* page 1 0x2221-0x227E */
+static uint16 tab_jisx0208_uni1[]={
+0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x203B,
+0x3012,0x2192,0x2190,0x2191,0x2193,0x3013, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2208,0x220B,0x2286,0x2287,0x2282,0x2283,0x222A,
+0x2229, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2227,0x2228,0x00AC,0x21D2,0x21D4,0x2200,0x2203,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2220,0x22A5,0x2312,0x2202,0x2207,
+0x2261,0x2252,0x226A,0x226B,0x221A,0x223D,0x221D,0x2235,
+0x222B,0x222C, 0, 0, 0, 0, 0, 0,
+ 0,0x212B,0x2030,0x266F,0x266D,0x266A,0x2020,0x2021,
+0x00B6, 0, 0, 0, 0,0x25EF};
+
+/* page 2 0x2330-0x237A */
+static uint16 tab_jisx0208_uni2[]={
+0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,
+0xFF18,0xFF19, 0, 0, 0, 0, 0, 0,
+ 0,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,
+0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,
+0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
+0xFF38,0xFF39,0xFF3A, 0, 0, 0, 0, 0,
+ 0,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,
+0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,
+0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,
+0xFF58,0xFF59,0xFF5A};
+
+/* page 3 0x2421-0x2473 */
+static uint16 tab_jisx0208_uni3[]={
+0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
+0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
+0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
+0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,
+0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,
+0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,
+0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,
+0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,
+0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,
+0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,
+0x3091,0x3092,0x3093};
+
+/* page 4 0x2521-0x2576 */
+static uint16 tab_jisx0208_uni4[]={
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
+0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
+0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
+0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,
+0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,
+0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,
+0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,
+0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,0x30E0,
+0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,
+0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,0x30F0,
+0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6};
+
+/* page 5 0x2621-0x2658 */
+static uint16 tab_jisx0208_uni5[]={
+0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
+0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
+0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,
+0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,0x03C0,
+0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9
+};
+
+/* page 6 0x2721-0x2771 */
+static uint16 tab_jisx0208_uni6[]={
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,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};
+
+/* page 7 0x2821-0x2840 */
+static uint16 tab_jisx0208_uni7[]={
+0x2500,0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,
+0x2524,0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,
+0x2517,0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,
+0x2528,0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542
+};
+
+/* page 8 0x3021-0x307E */
+static uint16 tab_jisx0208_uni8[]={
+0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
+0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
+0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
+0x59D0,0x867B,0x98F4,0x7D62,0x7DBE,0x9B8E,0x6216,0x7C9F,
+0x88B7,0x5B89,0x5EB5,0x6309,0x6697,0x6848,0x95C7,0x978D,
+0x674F,0x4EE5,0x4F0A,0x4F4D,0x4F9D,0x5049,0x56F2,0x5937,
+0x59D4,0x5A01,0x5C09,0x60DF,0x610F,0x6170,0x6613,0x6905,
+0x70BA,0x754F,0x7570,0x79FB,0x7DAD,0x7DEF,0x80C3,0x840E,
+0x8863,0x8B02,0x9055,0x907A,0x533B,0x4E95,0x4EA5,0x57DF,
+0x80B2,0x90C1,0x78EF,0x4E00,0x58F1,0x6EA2,0x9038,0x7A32,
+0x8328,0x828B,0x9C2F,0x5141,0x5370,0x54BD,0x54E1,0x56E0,
+0x59FB,0x5F15,0x98F2,0x6DEB,0x80E4,0x852D};
+
+/* page 9 0x3121-0x317E */
+static uint16 tab_jisx0208_uni9[]={
+0x9662,0x9670,0x96A0,0x97FB,0x540B,0x53F3,0x5B87,0x70CF,
+0x7FBD,0x8FC2,0x96E8,0x536F,0x9D5C,0x7ABA,0x4E11,0x7893,
+0x81FC,0x6E26,0x5618,0x5504,0x6B1D,0x851A,0x9C3B,0x59E5,
+0x53A9,0x6D66,0x74DC,0x958F,0x5642,0x4E91,0x904B,0x96F2,
+0x834F,0x990C,0x53E1,0x55B6,0x5B30,0x5F71,0x6620,0x66F3,
+0x6804,0x6C38,0x6CF3,0x6D29,0x745B,0x76C8,0x7A4E,0x9834,
+0x82F1,0x885B,0x8A60,0x92ED,0x6DB2,0x75AB,0x76CA,0x99C5,
+0x60A6,0x8B01,0x8D8A,0x95B2,0x698E,0x53AD,0x5186,0x5712,
+0x5830,0x5944,0x5BB4,0x5EF6,0x6028,0x63A9,0x63F4,0x6CBF,
+0x6F14,0x708E,0x7114,0x7159,0x71D5,0x733F,0x7E01,0x8276,
+0x82D1,0x8597,0x9060,0x925B,0x9D1B,0x5869,0x65BC,0x6C5A,
+0x7525,0x51F9,0x592E,0x5965,0x5F80,0x5FDC};
+
+/* page 10 0x3221-0x327E */
+static uint16 tab_jisx0208_uni10[]={
+0x62BC,0x65FA,0x6A2A,0x6B27,0x6BB4,0x738B,0x7FC1,0x8956,
+0x9D2C,0x9D0E,0x9EC4,0x5CA1,0x6C96,0x837B,0x5104,0x5C4B,
+0x61B6,0x81C6,0x6876,0x7261,0x4E59,0x4FFA,0x5378,0x6069,
+0x6E29,0x7A4F,0x97F3,0x4E0B,0x5316,0x4EEE,0x4F55,0x4F3D,
+0x4FA1,0x4F73,0x52A0,0x53EF,0x5609,0x590F,0x5AC1,0x5BB6,
+0x5BE1,0x79D1,0x6687,0x679C,0x67B6,0x6B4C,0x6CB3,0x706B,
+0x73C2,0x798D,0x79BE,0x7A3C,0x7B87,0x82B1,0x82DB,0x8304,
+0x8377,0x83EF,0x83D3,0x8766,0x8AB2,0x5629,0x8CA8,0x8FE6,
+0x904E,0x971E,0x868A,0x4FC4,0x5CE8,0x6211,0x7259,0x753B,
+0x81E5,0x82BD,0x86FE,0x8CC0,0x96C5,0x9913,0x99D5,0x4ECB,
+0x4F1A,0x89E3,0x56DE,0x584A,0x58CA,0x5EFB,0x5FEB,0x602A,
+0x6094,0x6062,0x61D0,0x6212,0x62D0,0x6539};
+
+/* page 11 0x3321-0x337E */
+static uint16 tab_jisx0208_uni11[]={
+0x9B41,0x6666,0x68B0,0x6D77,0x7070,0x754C,0x7686,0x7D75,
+0x82A5,0x87F9,0x958B,0x968E,0x8C9D,0x51F1,0x52BE,0x5916,
+0x54B3,0x5BB3,0x5D16,0x6168,0x6982,0x6DAF,0x788D,0x84CB,
+0x8857,0x8A72,0x93A7,0x9AB8,0x6D6C,0x99A8,0x86D9,0x57A3,
+0x67FF,0x86CE,0x920E,0x5283,0x5687,0x5404,0x5ED3,0x62E1,
+0x64B9,0x683C,0x6838,0x6BBB,0x7372,0x78BA,0x7A6B,0x899A,
+0x89D2,0x8D6B,0x8F03,0x90ED,0x95A3,0x9694,0x9769,0x5B66,
+0x5CB3,0x697D,0x984D,0x984E,0x639B,0x7B20,0x6A2B,0x6A7F,
+0x68B6,0x9C0D,0x6F5F,0x5272,0x559D,0x6070,0x62EC,0x6D3B,
+0x6E07,0x6ED1,0x845B,0x8910,0x8F44,0x4E14,0x9C39,0x53F6,
+0x691B,0x6A3A,0x9784,0x682A,0x515C,0x7AC3,0x84B2,0x91DC,
+0x938C,0x565B,0x9D28,0x6822,0x8305,0x8431};
+
+/* page 12 0x3421-0x347E */
+static uint16 tab_jisx0208_uni12[]={
+0x7CA5,0x5208,0x82C5,0x74E6,0x4E7E,0x4F83,0x51A0,0x5BD2,
+0x520A,0x52D8,0x52E7,0x5DFB,0x559A,0x582A,0x59E6,0x5B8C,
+0x5B98,0x5BDB,0x5E72,0x5E79,0x60A3,0x611F,0x6163,0x61BE,
+0x63DB,0x6562,0x67D1,0x6853,0x68FA,0x6B3E,0x6B53,0x6C57,
+0x6F22,0x6F97,0x6F45,0x74B0,0x7518,0x76E3,0x770B,0x7AFF,
+0x7BA1,0x7C21,0x7DE9,0x7F36,0x7FF0,0x809D,0x8266,0x839E,
+0x89B3,0x8ACC,0x8CAB,0x9084,0x9451,0x9593,0x9591,0x95A2,
+0x9665,0x97D3,0x9928,0x8218,0x4E38,0x542B,0x5CB8,0x5DCC,
+0x73A9,0x764C,0x773C,0x5CA9,0x7FEB,0x8D0B,0x96C1,0x9811,
+0x9854,0x9858,0x4F01,0x4F0E,0x5371,0x559C,0x5668,0x57FA,
+0x5947,0x5B09,0x5BC4,0x5C90,0x5E0C,0x5E7E,0x5FCC,0x63EE,
+0x673A,0x65D7,0x65E2,0x671F,0x68CB,0x68C4};
+
+/* page 13 0x3521-0x357E */
+static uint16 tab_jisx0208_uni13[]={
+0x6A5F,0x5E30,0x6BC5,0x6C17,0x6C7D,0x757F,0x7948,0x5B63,
+0x7A00,0x7D00,0x5FBD,0x898F,0x8A18,0x8CB4,0x8D77,0x8ECC,
+0x8F1D,0x98E2,0x9A0E,0x9B3C,0x4E80,0x507D,0x5100,0x5993,
+0x5B9C,0x622F,0x6280,0x64EC,0x6B3A,0x72A0,0x7591,0x7947,
+0x7FA9,0x87FB,0x8ABC,0x8B70,0x63AC,0x83CA,0x97A0,0x5409,
+0x5403,0x55AB,0x6854,0x6A58,0x8A70,0x7827,0x6775,0x9ECD,
+0x5374,0x5BA2,0x811A,0x8650,0x9006,0x4E18,0x4E45,0x4EC7,
+0x4F11,0x53CA,0x5438,0x5BAE,0x5F13,0x6025,0x6551,0x673D,
+0x6C42,0x6C72,0x6CE3,0x7078,0x7403,0x7A76,0x7AAE,0x7B08,
+0x7D1A,0x7CFE,0x7D66,0x65E7,0x725B,0x53BB,0x5C45,0x5DE8,
+0x62D2,0x62E0,0x6319,0x6E20,0x865A,0x8A31,0x8DDD,0x92F8,
+0x6F01,0x79A6,0x9B5A,0x4EA8,0x4EAB,0x4EAC};
+
+/* page 14 0x3621-0x367E */
+static uint16 tab_jisx0208_uni14[]={
+0x4F9B,0x4FA0,0x50D1,0x5147,0x7AF6,0x5171,0x51F6,0x5354,
+0x5321,0x537F,0x53EB,0x55AC,0x5883,0x5CE1,0x5F37,0x5F4A,
+0x602F,0x6050,0x606D,0x631F,0x6559,0x6A4B,0x6CC1,0x72C2,
+0x72ED,0x77EF,0x80F8,0x8105,0x8208,0x854E,0x90F7,0x93E1,
+0x97FF,0x9957,0x9A5A,0x4EF0,0x51DD,0x5C2D,0x6681,0x696D,
+0x5C40,0x66F2,0x6975,0x7389,0x6850,0x7C81,0x50C5,0x52E4,
+0x5747,0x5DFE,0x9326,0x65A4,0x6B23,0x6B3D,0x7434,0x7981,
+0x79BD,0x7B4B,0x7DCA,0x82B9,0x83CC,0x887F,0x895F,0x8B39,
+0x8FD1,0x91D1,0x541F,0x9280,0x4E5D,0x5036,0x53E5,0x533A,
+0x72D7,0x7396,0x77E9,0x82E6,0x8EAF,0x99C6,0x99C8,0x99D2,
+0x5177,0x611A,0x865E,0x55B0,0x7A7A,0x5076,0x5BD3,0x9047,
+0x9685,0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48};
+
+/* page 15 0x3721-0x377E */
+static uint16 tab_jisx0208_uni15[]={
+0x6398,0x7A9F,0x6C93,0x9774,0x8F61,0x7AAA,0x718A,0x9688,
+0x7C82,0x6817,0x7E70,0x6851,0x936C,0x52F2,0x541B,0x85AB,
+0x8A13,0x7FA4,0x8ECD,0x90E1,0x5366,0x8888,0x7941,0x4FC2,
+0x50BE,0x5211,0x5144,0x5553,0x572D,0x73EA,0x578B,0x5951,
+0x5F62,0x5F84,0x6075,0x6176,0x6167,0x61A9,0x63B2,0x643A,
+0x656C,0x666F,0x6842,0x6E13,0x7566,0x7A3D,0x7CFB,0x7D4C,
+0x7D99,0x7E4B,0x7F6B,0x830E,0x834A,0x86CD,0x8A08,0x8A63,
+0x8B66,0x8EFD,0x981A,0x9D8F,0x82B8,0x8FCE,0x9BE8,0x5287,
+0x621F,0x6483,0x6FC0,0x9699,0x6841,0x5091,0x6B20,0x6C7A,
+0x6F54,0x7A74,0x7D50,0x8840,0x8A23,0x6708,0x4EF6,0x5039,
+0x5026,0x5065,0x517C,0x5238,0x5263,0x55A7,0x570F,0x5805,
+0x5ACC,0x5EFA,0x61B2,0x61F8,0x62F3,0x6372};
+
+/* page 16 0x3821-0x387E */
+static uint16 tab_jisx0208_uni16[]={
+0x691C,0x6A29,0x727D,0x72AC,0x732E,0x7814,0x786F,0x7D79,
+0x770C,0x80A9,0x898B,0x8B19,0x8CE2,0x8ED2,0x9063,0x9375,
+0x967A,0x9855,0x9A13,0x9E78,0x5143,0x539F,0x53B3,0x5E7B,
+0x5F26,0x6E1B,0x6E90,0x7384,0x73FE,0x7D43,0x8237,0x8A00,
+0x8AFA,0x9650,0x4E4E,0x500B,0x53E4,0x547C,0x56FA,0x59D1,
+0x5B64,0x5DF1,0x5EAB,0x5F27,0x6238,0x6545,0x67AF,0x6E56,
+0x72D0,0x7CCA,0x88B4,0x80A1,0x80E1,0x83F0,0x864E,0x8A87,
+0x8DE8,0x9237,0x96C7,0x9867,0x9F13,0x4E94,0x4E92,0x4F0D,
+0x5348,0x5449,0x543E,0x5A2F,0x5F8C,0x5FA1,0x609F,0x68A7,
+0x6A8E,0x745A,0x7881,0x8A9E,0x8AA4,0x8B77,0x9190,0x4E5E,
+0x9BC9,0x4EA4,0x4F7C,0x4FAF,0x5019,0x5016,0x5149,0x516C,
+0x529F,0x52B9,0x52FE,0x539A,0x53E3,0x5411};
+
+/* page 17 0x3921-0x397E */
+static uint16 tab_jisx0208_uni17[]={
+0x540E,0x5589,0x5751,0x57A2,0x597D,0x5B54,0x5B5D,0x5B8F,
+0x5DE5,0x5DE7,0x5DF7,0x5E78,0x5E83,0x5E9A,0x5EB7,0x5F18,
+0x6052,0x614C,0x6297,0x62D8,0x63A7,0x653B,0x6602,0x6643,
+0x66F4,0x676D,0x6821,0x6897,0x69CB,0x6C5F,0x6D2A,0x6D69,
+0x6E2F,0x6E9D,0x7532,0x7687,0x786C,0x7A3F,0x7CE0,0x7D05,
+0x7D18,0x7D5E,0x7DB1,0x8015,0x8003,0x80AF,0x80B1,0x8154,
+0x818F,0x822A,0x8352,0x884C,0x8861,0x8B1B,0x8CA2,0x8CFC,
+0x90CA,0x9175,0x9271,0x783F,0x92FC,0x95A4,0x964D,0x9805,
+0x9999,0x9AD8,0x9D3B,0x525B,0x52AB,0x53F7,0x5408,0x58D5,
+0x62F7,0x6FE0,0x8C6A,0x8F5F,0x9EB9,0x514B,0x523B,0x544A,
+0x56FD,0x7A40,0x9177,0x9D60,0x9ED2,0x7344,0x6F09,0x8170,
+0x7511,0x5FFD,0x60DA,0x9AA8,0x72DB,0x8FBC};
+
+/* page 18 0x3A21-0x3A7E */
+static uint16 tab_jisx0208_uni18[]={
+0x6B64,0x9803,0x4ECA,0x56F0,0x5764,0x58BE,0x5A5A,0x6068,
+0x61C7,0x660F,0x6606,0x6839,0x68B1,0x6DF7,0x75D5,0x7D3A,
+0x826E,0x9B42,0x4E9B,0x4F50,0x53C9,0x5506,0x5D6F,0x5DE6,
+0x5DEE,0x67FB,0x6C99,0x7473,0x7802,0x8A50,0x9396,0x88DF,
+0x5750,0x5EA7,0x632B,0x50B5,0x50AC,0x518D,0x6700,0x54C9,
+0x585E,0x59BB,0x5BB0,0x5F69,0x624D,0x63A1,0x683D,0x6B73,
+0x6E08,0x707D,0x91C7,0x7280,0x7815,0x7826,0x796D,0x658E,
+0x7D30,0x83DC,0x88C1,0x8F09,0x969B,0x5264,0x5728,0x6750,
+0x7F6A,0x8CA1,0x51B4,0x5742,0x962A,0x583A,0x698A,0x80B4,
+0x54B2,0x5D0E,0x57FC,0x7895,0x9DFA,0x4F5C,0x524A,0x548B,
+0x643E,0x6628,0x6714,0x67F5,0x7A84,0x7B56,0x7D22,0x932F,
+0x685C,0x9BAD,0x7B39,0x5319,0x518A,0x5237};
+
+/* page 19 0x3B21-0x3B7E */
+static uint16 tab_jisx0208_uni19[]={
+0x5BDF,0x62F6,0x64AE,0x64E6,0x672D,0x6BBA,0x85A9,0x96D1,
+0x7690,0x9BD6,0x634C,0x9306,0x9BAB,0x76BF,0x6652,0x4E09,
+0x5098,0x53C2,0x5C71,0x60E8,0x6492,0x6563,0x685F,0x71E6,
+0x73CA,0x7523,0x7B97,0x7E82,0x8695,0x8B83,0x8CDB,0x9178,
+0x9910,0x65AC,0x66AB,0x6B8B,0x4ED5,0x4ED4,0x4F3A,0x4F7F,
+0x523A,0x53F8,0x53F2,0x55E3,0x56DB,0x58EB,0x59CB,0x59C9,
+0x59FF,0x5B50,0x5C4D,0x5E02,0x5E2B,0x5FD7,0x601D,0x6307,
+0x652F,0x5B5C,0x65AF,0x65BD,0x65E8,0x679D,0x6B62,0x6B7B,
+0x6C0F,0x7345,0x7949,0x79C1,0x7CF8,0x7D19,0x7D2B,0x80A2,
+0x8102,0x81F3,0x8996,0x8A5E,0x8A69,0x8A66,0x8A8C,0x8AEE,
+0x8CC7,0x8CDC,0x96CC,0x98FC,0x6B6F,0x4E8B,0x4F3C,0x4F8D,
+0x5150,0x5B57,0x5BFA,0x6148,0x6301,0x6642};
+
+/* page 20 0x3C21-0x3C7E */
+static uint16 tab_jisx0208_uni20[]={
+0x6B21,0x6ECB,0x6CBB,0x723E,0x74BD,0x75D4,0x78C1,0x793A,
+0x800C,0x8033,0x81EA,0x8494,0x8F9E,0x6C50,0x9E7F,0x5F0F,
+0x8B58,0x9D2B,0x7AFA,0x8EF8,0x5B8D,0x96EB,0x4E03,0x53F1,
+0x57F7,0x5931,0x5AC9,0x5BA4,0x6089,0x6E7F,0x6F06,0x75BE,
+0x8CEA,0x5B9F,0x8500,0x7BE0,0x5072,0x67F4,0x829D,0x5C61,
+0x854A,0x7E1E,0x820E,0x5199,0x5C04,0x6368,0x8D66,0x659C,
+0x716E,0x793E,0x7D17,0x8005,0x8B1D,0x8ECA,0x906E,0x86C7,
+0x90AA,0x501F,0x52FA,0x5C3A,0x6753,0x707C,0x7235,0x914C,
+0x91C8,0x932B,0x82E5,0x5BC2,0x5F31,0x60F9,0x4E3B,0x53D6,
+0x5B88,0x624B,0x6731,0x6B8A,0x72E9,0x73E0,0x7A2E,0x816B,
+0x8DA3,0x9152,0x9996,0x5112,0x53D7,0x546A,0x5BFF,0x6388,
+0x6A39,0x7DAC,0x9700,0x56DA,0x53CE,0x5468};
+
+/* page 21 0x3D21-0x3D7E */
+static uint16 tab_jisx0208_uni21[]={
+0x5B97,0x5C31,0x5DDE,0x4FEE,0x6101,0x62FE,0x6D32,0x79C0,
+0x79CB,0x7D42,0x7E4D,0x7FD2,0x81ED,0x821F,0x8490,0x8846,
+0x8972,0x8B90,0x8E74,0x8F2F,0x9031,0x914B,0x916C,0x96C6,
+0x919C,0x4EC0,0x4F4F,0x5145,0x5341,0x5F93,0x620E,0x67D4,
+0x6C41,0x6E0B,0x7363,0x7E26,0x91CD,0x9283,0x53D4,0x5919,
+0x5BBF,0x6DD1,0x795D,0x7E2E,0x7C9B,0x587E,0x719F,0x51FA,
+0x8853,0x8FF0,0x4FCA,0x5CFB,0x6625,0x77AC,0x7AE3,0x821C,
+0x99FF,0x51C6,0x5FAA,0x65EC,0x696F,0x6B89,0x6DF3,0x6E96,
+0x6F64,0x76FE,0x7D14,0x5DE1,0x9075,0x9187,0x9806,0x51E6,
+0x521D,0x6240,0x6691,0x66D9,0x6E1A,0x5EB6,0x7DD2,0x7F72,
+0x66F8,0x85AF,0x85F7,0x8AF8,0x52A9,0x53D9,0x5973,0x5E8F,
+0x5F90,0x6055,0x92E4,0x9664,0x50B7,0x511F};
+
+/* page 22 0x3E21-0x3E7E */
+static uint16 tab_jisx0208_uni22[]={
+0x52DD,0x5320,0x5347,0x53EC,0x54E8,0x5546,0x5531,0x5617,
+0x5968,0x59BE,0x5A3C,0x5BB5,0x5C06,0x5C0F,0x5C11,0x5C1A,
+0x5E84,0x5E8A,0x5EE0,0x5F70,0x627F,0x6284,0x62DB,0x638C,
+0x6377,0x6607,0x660C,0x662D,0x6676,0x677E,0x68A2,0x6A1F,
+0x6A35,0x6CBC,0x6D88,0x6E09,0x6E58,0x713C,0x7126,0x7167,
+0x75C7,0x7701,0x785D,0x7901,0x7965,0x79F0,0x7AE0,0x7B11,
+0x7CA7,0x7D39,0x8096,0x83D6,0x848B,0x8549,0x885D,0x88F3,
+0x8A1F,0x8A3C,0x8A54,0x8A73,0x8C61,0x8CDE,0x91A4,0x9266,
+0x937E,0x9418,0x969C,0x9798,0x4E0A,0x4E08,0x4E1E,0x4E57,
+0x5197,0x5270,0x57CE,0x5834,0x58CC,0x5B22,0x5E38,0x60C5,
+0x64FE,0x6761,0x6756,0x6D44,0x72B6,0x7573,0x7A63,0x84B8,
+0x8B72,0x91B8,0x9320,0x5631,0x57F4,0x98FE};
+
+/* page 23 0x3F21-0x3F7E */
+static uint16 tab_jisx0208_uni23[]={
+0x62ED,0x690D,0x6B96,0x71ED,0x7E54,0x8077,0x8272,0x89E6,
+0x98DF,0x8755,0x8FB1,0x5C3B,0x4F38,0x4FE1,0x4FB5,0x5507,
+0x5A20,0x5BDD,0x5BE9,0x5FC3,0x614E,0x632F,0x65B0,0x664B,
+0x68EE,0x699B,0x6D78,0x6DF1,0x7533,0x75B9,0x771F,0x795E,
+0x79E6,0x7D33,0x81E3,0x82AF,0x85AA,0x89AA,0x8A3A,0x8EAB,
+0x8F9B,0x9032,0x91DD,0x9707,0x4EBA,0x4EC1,0x5203,0x5875,
+0x58EC,0x5C0B,0x751A,0x5C3D,0x814E,0x8A0A,0x8FC5,0x9663,
+0x976D,0x7B25,0x8ACF,0x9808,0x9162,0x56F3,0x53A8,0x9017,
+0x5439,0x5782,0x5E25,0x63A8,0x6C34,0x708A,0x7761,0x7C8B,
+0x7FE0,0x8870,0x9042,0x9154,0x9310,0x9318,0x968F,0x745E,
+0x9AC4,0x5D07,0x5D69,0x6570,0x67A2,0x8DA8,0x96DB,0x636E,
+0x6749,0x6919,0x83C5,0x9817,0x96C0,0x88FE};
+
+/* page 24 0x4021-0x407E */
+static uint16 tab_jisx0208_uni24[]={
+0x6F84,0x647A,0x5BF8,0x4E16,0x702C,0x755D,0x662F,0x51C4,
+0x5236,0x52E2,0x59D3,0x5F81,0x6027,0x6210,0x653F,0x6574,
+0x661F,0x6674,0x68F2,0x6816,0x6B63,0x6E05,0x7272,0x751F,
+0x76DB,0x7CBE,0x8056,0x58F0,0x88FD,0x897F,0x8AA0,0x8A93,
+0x8ACB,0x901D,0x9192,0x9752,0x9759,0x6589,0x7A0E,0x8106,
+0x96BB,0x5E2D,0x60DC,0x621A,0x65A5,0x6614,0x6790,0x77F3,
+0x7A4D,0x7C4D,0x7E3E,0x810A,0x8CAC,0x8D64,0x8DE1,0x8E5F,
+0x78A9,0x5207,0x62D9,0x63A5,0x6442,0x6298,0x8A2D,0x7A83,
+0x7BC0,0x8AAC,0x96EA,0x7D76,0x820C,0x8749,0x4ED9,0x5148,
+0x5343,0x5360,0x5BA3,0x5C02,0x5C16,0x5DDD,0x6226,0x6247,
+0x64B0,0x6813,0x6834,0x6CC9,0x6D45,0x6D17,0x67D3,0x6F5C,
+0x714E,0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA};
+
+/* page 25 0x4121-0x417E */
+static uint16 tab_jisx0208_uni25[]={
+0x7E4A,0x7FA8,0x817A,0x821B,0x8239,0x85A6,0x8A6E,0x8CCE,
+0x8DF5,0x9078,0x9077,0x92AD,0x9291,0x9583,0x9BAE,0x524D,
+0x5584,0x6F38,0x7136,0x5168,0x7985,0x7E55,0x81B3,0x7CCE,
+0x564C,0x5851,0x5CA8,0x63AA,0x66FE,0x66FD,0x695A,0x72D9,
+0x758F,0x758E,0x790E,0x7956,0x79DF,0x7C97,0x7D20,0x7D44,
+0x8607,0x8A34,0x963B,0x9061,0x9F20,0x50E7,0x5275,0x53CC,
+0x53E2,0x5009,0x55AA,0x58EE,0x594F,0x723D,0x5B8B,0x5C64,
+0x531D,0x60E3,0x60F3,0x635C,0x6383,0x633F,0x63BB,0x64CD,
+0x65E9,0x66F9,0x5DE3,0x69CD,0x69FD,0x6F15,0x71E5,0x4E89,
+0x75E9,0x76F8,0x7A93,0x7CDF,0x7DCF,0x7D9C,0x8061,0x8349,
+0x8358,0x846C,0x84BC,0x85FB,0x88C5,0x8D70,0x9001,0x906D,
+0x9397,0x971C,0x9A12,0x50CF,0x5897,0x618E};
+
+/* page 26 0x4221-0x427E */
+static uint16 tab_jisx0208_uni26[]={
+0x81D3,0x8535,0x8D08,0x9020,0x4FC3,0x5074,0x5247,0x5373,
+0x606F,0x6349,0x675F,0x6E2C,0x8DB3,0x901F,0x4FD7,0x5C5E,
+0x8CCA,0x65CF,0x7D9A,0x5352,0x8896,0x5176,0x63C3,0x5B58,
+0x5B6B,0x5C0A,0x640D,0x6751,0x905C,0x4ED6,0x591A,0x592A,
+0x6C70,0x8A51,0x553E,0x5815,0x59A5,0x60F0,0x6253,0x67C1,
+0x8235,0x6955,0x9640,0x99C4,0x9A28,0x4F53,0x5806,0x5BFE,
+0x8010,0x5CB1,0x5E2F,0x5F85,0x6020,0x614B,0x6234,0x66FF,
+0x6CF0,0x6EDE,0x80CE,0x817F,0x82D4,0x888B,0x8CB8,0x9000,
+0x902E,0x968A,0x9EDB,0x9BDB,0x4EE3,0x53F0,0x5927,0x7B2C,
+0x918D,0x984C,0x9DF9,0x6EDD,0x7027,0x5353,0x5544,0x5B85,
+0x6258,0x629E,0x62D3,0x6CA2,0x6FEF,0x7422,0x8A17,0x9438,
+0x6FC1,0x8AFE,0x8338,0x51E7,0x86F8,0x53EA};
+
+/* page 27 0x4321-0x437E */
+static uint16 tab_jisx0208_uni27[]={
+0x53E9,0x4F46,0x9054,0x8FB0,0x596A,0x8131,0x5DFD,0x7AEA,
+0x8FBF,0x68DA,0x8C37,0x72F8,0x9C48,0x6A3D,0x8AB0,0x4E39,
+0x5358,0x5606,0x5766,0x62C5,0x63A2,0x65E6,0x6B4E,0x6DE1,
+0x6E5B,0x70AD,0x77ED,0x7AEF,0x7BAA,0x7DBB,0x803D,0x80C6,
+0x86CB,0x8A95,0x935B,0x56E3,0x58C7,0x5F3E,0x65AD,0x6696,
+0x6A80,0x6BB5,0x7537,0x8AC7,0x5024,0x77E5,0x5730,0x5F1B,
+0x6065,0x667A,0x6C60,0x75F4,0x7A1A,0x7F6E,0x81F4,0x8718,
+0x9045,0x99B3,0x7BC9,0x755C,0x7AF9,0x7B51,0x84C4,0x9010,
+0x79E9,0x7A92,0x8336,0x5AE1,0x7740,0x4E2D,0x4EF2,0x5B99,
+0x5FE0,0x62BD,0x663C,0x67F1,0x6CE8,0x866B,0x8877,0x8A3B,
+0x914E,0x92F3,0x99D0,0x6A17,0x7026,0x732A,0x82E7,0x8457,
+0x8CAF,0x4E01,0x5146,0x51CB,0x558B,0x5BF5};
+
+/* page 28 0x4421-0x447E */
+static uint16 tab_jisx0208_uni28[]={
+0x5E16,0x5E33,0x5E81,0x5F14,0x5F35,0x5F6B,0x5FB4,0x61F2,
+0x6311,0x66A2,0x671D,0x6F6E,0x7252,0x753A,0x773A,0x8074,
+0x8139,0x8178,0x8776,0x8ABF,0x8ADC,0x8D85,0x8DF3,0x929A,
+0x9577,0x9802,0x9CE5,0x52C5,0x6357,0x76F4,0x6715,0x6C88,
+0x73CD,0x8CC3,0x93AE,0x9673,0x6D25,0x589C,0x690E,0x69CC,
+0x8FFD,0x939A,0x75DB,0x901A,0x585A,0x6802,0x63B4,0x69FB,
+0x4F43,0x6F2C,0x67D8,0x8FBB,0x8526,0x7DB4,0x9354,0x693F,
+0x6F70,0x576A,0x58F7,0x5B2C,0x7D2C,0x722A,0x540A,0x91E3,
+0x9DB4,0x4EAD,0x4F4E,0x505C,0x5075,0x5243,0x8C9E,0x5448,
+0x5824,0x5B9A,0x5E1D,0x5E95,0x5EAD,0x5EF7,0x5F1F,0x608C,
+0x62B5,0x633A,0x63D0,0x68AF,0x6C40,0x7887,0x798E,0x7A0B,
+0x7DE0,0x8247,0x8A02,0x8AE6,0x8E44,0x9013};
+
+/* page 29 0x4521-0x457E */
+static uint16 tab_jisx0208_uni29[]={
+0x90B8,0x912D,0x91D8,0x9F0E,0x6CE5,0x6458,0x64E2,0x6575,
+0x6EF4,0x7684,0x7B1B,0x9069,0x93D1,0x6EBA,0x54F2,0x5FB9,
+0x64A4,0x8F4D,0x8FED,0x9244,0x5178,0x586B,0x5929,0x5C55,
+0x5E97,0x6DFB,0x7E8F,0x751C,0x8CBC,0x8EE2,0x985B,0x70B9,
+0x4F1D,0x6BBF,0x6FB1,0x7530,0x96FB,0x514E,0x5410,0x5835,
+0x5857,0x59AC,0x5C60,0x5F92,0x6597,0x675C,0x6E21,0x767B,
+0x83DF,0x8CED,0x9014,0x90FD,0x934D,0x7825,0x783A,0x52AA,
+0x5EA6,0x571F,0x5974,0x6012,0x5012,0x515A,0x51AC,0x51CD,
+0x5200,0x5510,0x5854,0x5858,0x5957,0x5B95,0x5CF6,0x5D8B,
+0x60BC,0x6295,0x642D,0x6771,0x6843,0x68BC,0x68DF,0x76D7,
+0x6DD8,0x6E6F,0x6D9B,0x706F,0x71C8,0x5F53,0x75D8,0x7977,
+0x7B49,0x7B54,0x7B52,0x7CD6,0x7D71,0x5230};
+
+/* page 30 0x4621-0x467E */
+static uint16 tab_jisx0208_uni30[]={
+0x8463,0x8569,0x85E4,0x8A0E,0x8B04,0x8C46,0x8E0F,0x9003,
+0x900F,0x9419,0x9676,0x982D,0x9A30,0x95D8,0x50CD,0x52D5,
+0x540C,0x5802,0x5C0E,0x61A7,0x649E,0x6D1E,0x77B3,0x7AE5,
+0x80F4,0x8404,0x9053,0x9285,0x5CE0,0x9D07,0x533F,0x5F97,
+0x5FB3,0x6D9C,0x7279,0x7763,0x79BF,0x7BE4,0x6BD2,0x72EC,
+0x8AAD,0x6803,0x6A61,0x51F8,0x7A81,0x6934,0x5C4A,0x9CF6,
+0x82EB,0x5BC5,0x9149,0x701E,0x5678,0x5C6F,0x60C7,0x6566,
+0x6C8C,0x8C5A,0x9041,0x9813,0x5451,0x66C7,0x920D,0x5948,
+0x90A3,0x5185,0x4E4D,0x51EA,0x8599,0x8B0E,0x7058,0x637A,
+0x934B,0x6962,0x99B4,0x7E04,0x7577,0x5357,0x6960,0x8EDF,
+0x96E3,0x6C5D,0x4E8C,0x5C3C,0x5F10,0x8FE9,0x5302,0x8CD1,
+0x8089,0x8679,0x5EFF,0x65E5,0x4E73,0x5165};
+
+/* page 31 0x4721-0x477E */
+static uint16 tab_jisx0208_uni31[]={
+0x5982,0x5C3F,0x97EE,0x4EFB,0x598A,0x5FCD,0x8A8D,0x6FE1,
+0x79B0,0x7962,0x5BE7,0x8471,0x732B,0x71B1,0x5E74,0x5FF5,
+0x637B,0x649A,0x71C3,0x7C98,0x4E43,0x5EFC,0x4E4B,0x57DC,
+0x56A2,0x60A9,0x6FC3,0x7D0D,0x80FD,0x8133,0x81BF,0x8FB2,
+0x8997,0x86A4,0x5DF4,0x628A,0x64AD,0x8987,0x6777,0x6CE2,
+0x6D3E,0x7436,0x7834,0x5A46,0x7F75,0x82AD,0x99AC,0x4FF3,
+0x5EC3,0x62DD,0x6392,0x6557,0x676F,0x76C3,0x724C,0x80CC,
+0x80BA,0x8F29,0x914D,0x500D,0x57F9,0x5A92,0x6885,0x6973,
+0x7164,0x72FD,0x8CB7,0x58F2,0x8CE0,0x966A,0x9019,0x877F,
+0x79E4,0x77E7,0x8429,0x4F2F,0x5265,0x535A,0x62CD,0x67CF,
+0x6CCA,0x767D,0x7B94,0x7C95,0x8236,0x8584,0x8FEB,0x66DD,
+0x6F20,0x7206,0x7E1B,0x83AB,0x99C1,0x9EA6};
+
+/* page 32 0x4821-0x487E */
+static uint16 tab_jisx0208_uni32[]={
+0x51FD,0x7BB1,0x7872,0x7BB8,0x8087,0x7B48,0x6AE8,0x5E61,
+0x808C,0x7551,0x7560,0x516B,0x9262,0x6E8C,0x767A,0x9197,
+0x9AEA,0x4F10,0x7F70,0x629C,0x7B4F,0x95A5,0x9CE9,0x567A,
+0x5859,0x86E4,0x96BC,0x4F34,0x5224,0x534A,0x53CD,0x53DB,
+0x5E06,0x642C,0x6591,0x677F,0x6C3E,0x6C4E,0x7248,0x72AF,
+0x73ED,0x7554,0x7E41,0x822C,0x85E9,0x8CA9,0x7BC4,0x91C6,
+0x7169,0x9812,0x98EF,0x633D,0x6669,0x756A,0x76E4,0x78D0,
+0x8543,0x86EE,0x532A,0x5351,0x5426,0x5983,0x5E87,0x5F7C,
+0x60B2,0x6249,0x6279,0x62AB,0x6590,0x6BD4,0x6CCC,0x75B2,
+0x76AE,0x7891,0x79D8,0x7DCB,0x7F77,0x80A5,0x88AB,0x8AB9,
+0x8CBB,0x907F,0x975E,0x98DB,0x6A0B,0x7C38,0x5099,0x5C3E,
+0x5FAE,0x6787,0x6BD8,0x7435,0x7709,0x7F8E};
+
+/* page 33 0x4921-0x497E */
+static uint16 tab_jisx0208_uni33[]={
+0x9F3B,0x67CA,0x7A17,0x5339,0x758B,0x9AED,0x5F66,0x819D,
+0x83F1,0x8098,0x5F3C,0x5FC5,0x7562,0x7B46,0x903C,0x6867,
+0x59EB,0x5A9B,0x7D10,0x767E,0x8B2C,0x4FF5,0x5F6A,0x6A19,
+0x6C37,0x6F02,0x74E2,0x7968,0x8868,0x8A55,0x8C79,0x5EDF,
+0x63CF,0x75C5,0x79D2,0x82D7,0x9328,0x92F2,0x849C,0x86ED,
+0x9C2D,0x54C1,0x5F6C,0x658C,0x6D5C,0x7015,0x8CA7,0x8CD3,
+0x983B,0x654F,0x74F6,0x4E0D,0x4ED8,0x57E0,0x592B,0x5A66,
+0x5BCC,0x51A8,0x5E03,0x5E9C,0x6016,0x6276,0x6577,0x65A7,
+0x666E,0x6D6E,0x7236,0x7B26,0x8150,0x819A,0x8299,0x8B5C,
+0x8CA0,0x8CE6,0x8D74,0x961C,0x9644,0x4FAE,0x64AB,0x6B66,
+0x821E,0x8461,0x856A,0x90E8,0x5C01,0x6953,0x98A8,0x847A,
+0x8557,0x4F0F,0x526F,0x5FA9,0x5E45,0x670D};
+
+/* page 34 0x4A21-0x4A7E */
+static uint16 tab_jisx0208_uni34[]={
+0x798F,0x8179,0x8907,0x8986,0x6DF5,0x5F17,0x6255,0x6CB8,
+0x4ECF,0x7269,0x9B92,0x5206,0x543B,0x5674,0x58B3,0x61A4,
+0x626E,0x711A,0x596E,0x7C89,0x7CDE,0x7D1B,0x96F0,0x6587,
+0x805E,0x4E19,0x4F75,0x5175,0x5840,0x5E63,0x5E73,0x5F0A,
+0x67C4,0x4E26,0x853D,0x9589,0x965B,0x7C73,0x9801,0x50FB,
+0x58C1,0x7656,0x78A7,0x5225,0x77A5,0x8511,0x7B86,0x504F,
+0x5909,0x7247,0x7BC7,0x7DE8,0x8FBA,0x8FD4,0x904D,0x4FBF,
+0x52C9,0x5A29,0x5F01,0x97AD,0x4FDD,0x8217,0x92EA,0x5703,
+0x6355,0x6B69,0x752B,0x88DC,0x8F14,0x7A42,0x52DF,0x5893,
+0x6155,0x620A,0x66AE,0x6BCD,0x7C3F,0x83E9,0x5023,0x4FF8,
+0x5305,0x5446,0x5831,0x5949,0x5B9D,0x5CF0,0x5CEF,0x5D29,
+0x5E96,0x62B1,0x6367,0x653E,0x65B9,0x670B};
+
+/* page 35 0x4B21-0x4B7E */
+static uint16 tab_jisx0208_uni35[]={
+0x6CD5,0x6CE1,0x70F9,0x7832,0x7E2B,0x80DE,0x82B3,0x840C,
+0x84EC,0x8702,0x8912,0x8A2A,0x8C4A,0x90A6,0x92D2,0x98FD,
+0x9CF3,0x9D6C,0x4E4F,0x4EA1,0x508D,0x5256,0x574A,0x59A8,
+0x5E3D,0x5FD8,0x5FD9,0x623F,0x66B4,0x671B,0x67D0,0x68D2,
+0x5192,0x7D21,0x80AA,0x81A8,0x8B00,0x8C8C,0x8CBF,0x927E,
+0x9632,0x5420,0x982C,0x5317,0x50D5,0x535C,0x58A8,0x64B2,
+0x6734,0x7267,0x7766,0x7A46,0x91E6,0x52C3,0x6CA1,0x6B86,
+0x5800,0x5E4C,0x5954,0x672C,0x7FFB,0x51E1,0x76C6,0x6469,
+0x78E8,0x9B54,0x9EBB,0x57CB,0x59B9,0x6627,0x679A,0x6BCE,
+0x54E9,0x69D9,0x5E55,0x819C,0x6795,0x9BAA,0x67FE,0x9C52,
+0x685D,0x4EA6,0x4FE3,0x53C8,0x62B9,0x672B,0x6CAB,0x8FC4,
+0x4FAD,0x7E6D,0x9EBF,0x4E07,0x6162,0x6E80};
+
+/* page 36 0x4C21-0x4C7E */
+static uint16 tab_jisx0208_uni36[]={
+0x6F2B,0x8513,0x5473,0x672A,0x9B45,0x5DF3,0x7B95,0x5CAC,
+0x5BC6,0x871C,0x6E4A,0x84D1,0x7A14,0x8108,0x5999,0x7C8D,
+0x6C11,0x7720,0x52D9,0x5922,0x7121,0x725F,0x77DB,0x9727,
+0x9D61,0x690B,0x5A7F,0x5A18,0x51A5,0x540D,0x547D,0x660E,
+0x76DF,0x8FF7,0x9298,0x9CF4,0x59EA,0x725D,0x6EC5,0x514D,
+0x68C9,0x7DBF,0x7DEC,0x9762,0x9EBA,0x6478,0x6A21,0x8302,
+0x5984,0x5B5F,0x6BDB,0x731B,0x76F2,0x7DB2,0x8017,0x8499,
+0x5132,0x6728,0x9ED9,0x76EE,0x6762,0x52FF,0x9905,0x5C24,
+0x623B,0x7C7E,0x8CB0,0x554F,0x60B6,0x7D0B,0x9580,0x5301,
+0x4E5F,0x51B6,0x591C,0x723A,0x8036,0x91CE,0x5F25,0x77E2,
+0x5384,0x5F79,0x7D04,0x85AC,0x8A33,0x8E8D,0x9756,0x67F3,
+0x85AE,0x9453,0x6109,0x6108,0x6CB9,0x7652};
+
+/* page 37 0x4D21-0x4D7E */
+static uint16 tab_jisx0208_uni37[]={
+0x8AED,0x8F38,0x552F,0x4F51,0x512A,0x52C7,0x53CB,0x5BA5,
+0x5E7D,0x60A0,0x6182,0x63D6,0x6709,0x67DA,0x6E67,0x6D8C,
+0x7336,0x7337,0x7531,0x7950,0x88D5,0x8A98,0x904A,0x9091,
+0x90F5,0x96C4,0x878D,0x5915,0x4E88,0x4F59,0x4E0E,0x8A89,
+0x8F3F,0x9810,0x50AD,0x5E7C,0x5996,0x5BB9,0x5EB8,0x63DA,
+0x63FA,0x64C1,0x66DC,0x694A,0x69D8,0x6D0B,0x6EB6,0x7194,
+0x7528,0x7AAF,0x7F8A,0x8000,0x8449,0x84C9,0x8981,0x8B21,
+0x8E0A,0x9065,0x967D,0x990A,0x617E,0x6291,0x6B32,0x6C83,
+0x6D74,0x7FCC,0x7FFC,0x6DC0,0x7F85,0x87BA,0x88F8,0x6765,
+0x83B1,0x983C,0x96F7,0x6D1B,0x7D61,0x843D,0x916A,0x4E71,
+0x5375,0x5D50,0x6B04,0x6FEB,0x85CD,0x862D,0x89A7,0x5229,
+0x540F,0x5C65,0x674E,0x68A8,0x7406,0x7483};
+
+/* page 38 0x4E21-0x4E7E */
+static uint16 tab_jisx0208_uni38[]={
+0x75E2,0x88CF,0x88E1,0x91CC,0x96E2,0x9678,0x5F8B,0x7387,
+0x7ACB,0x844E,0x63A0,0x7565,0x5289,0x6D41,0x6E9C,0x7409,
+0x7559,0x786B,0x7C92,0x9686,0x7ADC,0x9F8D,0x4FB6,0x616E,
+0x65C5,0x865C,0x4E86,0x4EAE,0x50DA,0x4E21,0x51CC,0x5BEE,
+0x6599,0x6881,0x6DBC,0x731F,0x7642,0x77AD,0x7A1C,0x7CE7,
+0x826F,0x8AD2,0x907C,0x91CF,0x9675,0x9818,0x529B,0x7DD1,
+0x502B,0x5398,0x6797,0x6DCB,0x71D0,0x7433,0x81E8,0x8F2A,
+0x96A3,0x9C57,0x9E9F,0x7460,0x5841,0x6D99,0x7D2F,0x985E,
+0x4EE4,0x4F36,0x4F8B,0x51B7,0x52B1,0x5DBA,0x601C,0x73B2,
+0x793C,0x82D3,0x9234,0x96B7,0x96F6,0x970A,0x9E97,0x9F62,
+0x66A6,0x6B74,0x5217,0x52A3,0x70C8,0x88C2,0x5EC9,0x604B,
+0x6190,0x6F23,0x7149,0x7C3E,0x7DF4,0x806F};
+
+/* page 39 0x4F21-0x4F53 */
+static uint16 tab_jisx0208_uni39[]={
+0x84EE,0x9023,0x932C,0x5442,0x9B6F,0x6AD3,0x7089,0x8CC2,
+0x8DEF,0x9732,0x52B4,0x5A41,0x5ECA,0x5F04,0x6717,0x697C,
+0x6994,0x6D6A,0x6F0F,0x7262,0x72FC,0x7BED,0x8001,0x807E,
+0x874B,0x90CE,0x516D,0x9E93,0x7984,0x808B,0x9332,0x8AD6,
+0x502D,0x548C,0x8A71,0x6B6A,0x8CC4,0x8107,0x60D1,0x67A0,
+0x9DF2,0x4E99,0x4E98,0x9C10,0x8A6B,0x85C1,0x8568,0x6900,
+0x6E7E,0x7897,0x8155};
+
+/* page 40 0x5021-0x507E */
+static uint16 tab_jisx0208_uni40[]={
+0x5F0C,0x4E10,0x4E15,0x4E2A,0x4E31,0x4E36,0x4E3C,0x4E3F,
+0x4E42,0x4E56,0x4E58,0x4E82,0x4E85,0x8C6B,0x4E8A,0x8212,
+0x5F0D,0x4E8E,0x4E9E,0x4E9F,0x4EA0,0x4EA2,0x4EB0,0x4EB3,
+0x4EB6,0x4ECE,0x4ECD,0x4EC4,0x4EC6,0x4EC2,0x4ED7,0x4EDE,
+0x4EED,0x4EDF,0x4EF7,0x4F09,0x4F5A,0x4F30,0x4F5B,0x4F5D,
+0x4F57,0x4F47,0x4F76,0x4F88,0x4F8F,0x4F98,0x4F7B,0x4F69,
+0x4F70,0x4F91,0x4F6F,0x4F86,0x4F96,0x5118,0x4FD4,0x4FDF,
+0x4FCE,0x4FD8,0x4FDB,0x4FD1,0x4FDA,0x4FD0,0x4FE4,0x4FE5,
+0x501A,0x5028,0x5014,0x502A,0x5025,0x5005,0x4F1C,0x4FF6,
+0x5021,0x5029,0x502C,0x4FFE,0x4FEF,0x5011,0x5006,0x5043,
+0x5047,0x6703,0x5055,0x5050,0x5048,0x505A,0x5056,0x506C,
+0x5078,0x5080,0x509A,0x5085,0x50B4,0x50B2};
+
+/* page 41 0x5121-0x517E */
+static uint16 tab_jisx0208_uni41[]={
+0x50C9,0x50CA,0x50B3,0x50C2,0x50D6,0x50DE,0x50E5,0x50ED,
+0x50E3,0x50EE,0x50F9,0x50F5,0x5109,0x5101,0x5102,0x5116,
+0x5115,0x5114,0x511A,0x5121,0x513A,0x5137,0x513C,0x513B,
+0x513F,0x5140,0x5152,0x514C,0x5154,0x5162,0x7AF8,0x5169,
+0x516A,0x516E,0x5180,0x5182,0x56D8,0x518C,0x5189,0x518F,
+0x5191,0x5193,0x5195,0x5196,0x51A4,0x51A6,0x51A2,0x51A9,
+0x51AA,0x51AB,0x51B3,0x51B1,0x51B2,0x51B0,0x51B5,0x51BD,
+0x51C5,0x51C9,0x51DB,0x51E0,0x8655,0x51E9,0x51ED,0x51F0,
+0x51F5,0x51FE,0x5204,0x520B,0x5214,0x520E,0x5227,0x522A,
+0x522E,0x5233,0x5239,0x524F,0x5244,0x524B,0x524C,0x525E,
+0x5254,0x526A,0x5274,0x5269,0x5273,0x527F,0x527D,0x528D,
+0x5294,0x5292,0x5271,0x5288,0x5291,0x8FA8};
+
+/* page 42 0x5221-0x527E */
+static uint16 tab_jisx0208_uni42[]={
+0x8FA7,0x52AC,0x52AD,0x52BC,0x52B5,0x52C1,0x52CD,0x52D7,
+0x52DE,0x52E3,0x52E6,0x98ED,0x52E0,0x52F3,0x52F5,0x52F8,
+0x52F9,0x5306,0x5308,0x7538,0x530D,0x5310,0x530F,0x5315,
+0x531A,0x5323,0x532F,0x5331,0x5333,0x5338,0x5340,0x5346,
+0x5345,0x4E17,0x5349,0x534D,0x51D6,0x535E,0x5369,0x536E,
+0x5918,0x537B,0x5377,0x5382,0x5396,0x53A0,0x53A6,0x53A5,
+0x53AE,0x53B0,0x53B6,0x53C3,0x7C12,0x96D9,0x53DF,0x66FC,
+0x71EE,0x53EE,0x53E8,0x53ED,0x53FA,0x5401,0x543D,0x5440,
+0x542C,0x542D,0x543C,0x542E,0x5436,0x5429,0x541D,0x544E,
+0x548F,0x5475,0x548E,0x545F,0x5471,0x5477,0x5470,0x5492,
+0x547B,0x5480,0x5476,0x5484,0x5490,0x5486,0x54C7,0x54A2,
+0x54B8,0x54A5,0x54AC,0x54C4,0x54C8,0x54A8};
+
+/* page 43 0x5321-0x537E */
+static uint16 tab_jisx0208_uni43[]={
+0x54AB,0x54C2,0x54A4,0x54BE,0x54BC,0x54D8,0x54E5,0x54E6,
+0x550F,0x5514,0x54FD,0x54EE,0x54ED,0x54FA,0x54E2,0x5539,
+0x5540,0x5563,0x554C,0x552E,0x555C,0x5545,0x5556,0x5557,
+0x5538,0x5533,0x555D,0x5599,0x5580,0x54AF,0x558A,0x559F,
+0x557B,0x557E,0x5598,0x559E,0x55AE,0x557C,0x5583,0x55A9,
+0x5587,0x55A8,0x55DA,0x55C5,0x55DF,0x55C4,0x55DC,0x55E4,
+0x55D4,0x5614,0x55F7,0x5616,0x55FE,0x55FD,0x561B,0x55F9,
+0x564E,0x5650,0x71DF,0x5634,0x5636,0x5632,0x5638,0x566B,
+0x5664,0x562F,0x566C,0x566A,0x5686,0x5680,0x568A,0x56A0,
+0x5694,0x568F,0x56A5,0x56AE,0x56B6,0x56B4,0x56C2,0x56BC,
+0x56C1,0x56C3,0x56C0,0x56C8,0x56CE,0x56D1,0x56D3,0x56D7,
+0x56EE,0x56F9,0x5700,0x56FF,0x5704,0x5709};
+
+/* page 44 0x5421-0x547E */
+static uint16 tab_jisx0208_uni44[]={
+0x5708,0x570B,0x570D,0x5713,0x5718,0x5716,0x55C7,0x571C,
+0x5726,0x5737,0x5738,0x574E,0x573B,0x5740,0x574F,0x5769,
+0x57C0,0x5788,0x5761,0x577F,0x5789,0x5793,0x57A0,0x57B3,
+0x57A4,0x57AA,0x57B0,0x57C3,0x57C6,0x57D4,0x57D2,0x57D3,
+0x580A,0x57D6,0x57E3,0x580B,0x5819,0x581D,0x5872,0x5821,
+0x5862,0x584B,0x5870,0x6BC0,0x5852,0x583D,0x5879,0x5885,
+0x58B9,0x589F,0x58AB,0x58BA,0x58DE,0x58BB,0x58B8,0x58AE,
+0x58C5,0x58D3,0x58D1,0x58D7,0x58D9,0x58D8,0x58E5,0x58DC,
+0x58E4,0x58DF,0x58EF,0x58FA,0x58F9,0x58FB,0x58FC,0x58FD,
+0x5902,0x590A,0x5910,0x591B,0x68A6,0x5925,0x592C,0x592D,
+0x5932,0x5938,0x593E,0x7AD2,0x5955,0x5950,0x594E,0x595A,
+0x5958,0x5962,0x5960,0x5967,0x596C,0x5969};
+
+/* page 45 0x5521-0x557E */
+static uint16 tab_jisx0208_uni45[]={
+0x5978,0x5981,0x599D,0x4F5E,0x4FAB,0x59A3,0x59B2,0x59C6,
+0x59E8,0x59DC,0x598D,0x59D9,0x59DA,0x5A25,0x5A1F,0x5A11,
+0x5A1C,0x5A09,0x5A1A,0x5A40,0x5A6C,0x5A49,0x5A35,0x5A36,
+0x5A62,0x5A6A,0x5A9A,0x5ABC,0x5ABE,0x5ACB,0x5AC2,0x5ABD,
+0x5AE3,0x5AD7,0x5AE6,0x5AE9,0x5AD6,0x5AFA,0x5AFB,0x5B0C,
+0x5B0B,0x5B16,0x5B32,0x5AD0,0x5B2A,0x5B36,0x5B3E,0x5B43,
+0x5B45,0x5B40,0x5B51,0x5B55,0x5B5A,0x5B5B,0x5B65,0x5B69,
+0x5B70,0x5B73,0x5B75,0x5B78,0x6588,0x5B7A,0x5B80,0x5B83,
+0x5BA6,0x5BB8,0x5BC3,0x5BC7,0x5BC9,0x5BD4,0x5BD0,0x5BE4,
+0x5BE6,0x5BE2,0x5BDE,0x5BE5,0x5BEB,0x5BF0,0x5BF6,0x5BF3,
+0x5C05,0x5C07,0x5C08,0x5C0D,0x5C13,0x5C20,0x5C22,0x5C28,
+0x5C38,0x5C39,0x5C41,0x5C46,0x5C4E,0x5C53};
+
+/* page 46 0x5621-0x567E */
+static uint16 tab_jisx0208_uni46[]={
+0x5C50,0x5C4F,0x5B71,0x5C6C,0x5C6E,0x4E62,0x5C76,0x5C79,
+0x5C8C,0x5C91,0x5C94,0x599B,0x5CAB,0x5CBB,0x5CB6,0x5CBC,
+0x5CB7,0x5CC5,0x5CBE,0x5CC7,0x5CD9,0x5CE9,0x5CFD,0x5CFA,
+0x5CED,0x5D8C,0x5CEA,0x5D0B,0x5D15,0x5D17,0x5D5C,0x5D1F,
+0x5D1B,0x5D11,0x5D14,0x5D22,0x5D1A,0x5D19,0x5D18,0x5D4C,
+0x5D52,0x5D4E,0x5D4B,0x5D6C,0x5D73,0x5D76,0x5D87,0x5D84,
+0x5D82,0x5DA2,0x5D9D,0x5DAC,0x5DAE,0x5DBD,0x5D90,0x5DB7,
+0x5DBC,0x5DC9,0x5DCD,0x5DD3,0x5DD2,0x5DD6,0x5DDB,0x5DEB,
+0x5DF2,0x5DF5,0x5E0B,0x5E1A,0x5E19,0x5E11,0x5E1B,0x5E36,
+0x5E37,0x5E44,0x5E43,0x5E40,0x5E4E,0x5E57,0x5E54,0x5E5F,
+0x5E62,0x5E64,0x5E47,0x5E75,0x5E76,0x5E7A,0x9EBC,0x5E7F,
+0x5EA0,0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF};
+
+/* page 47 0x5721-0x577E */
+static uint16 tab_jisx0208_uni47[]={
+0x5ED6,0x5EE3,0x5EDD,0x5EDA,0x5EDB,0x5EE2,0x5EE1,0x5EE8,
+0x5EE9,0x5EEC,0x5EF1,0x5EF3,0x5EF0,0x5EF4,0x5EF8,0x5EFE,
+0x5F03,0x5F09,0x5F5D,0x5F5C,0x5F0B,0x5F11,0x5F16,0x5F29,
+0x5F2D,0x5F38,0x5F41,0x5F48,0x5F4C,0x5F4E,0x5F2F,0x5F51,
+0x5F56,0x5F57,0x5F59,0x5F61,0x5F6D,0x5F73,0x5F77,0x5F83,
+0x5F82,0x5F7F,0x5F8A,0x5F88,0x5F91,0x5F87,0x5F9E,0x5F99,
+0x5F98,0x5FA0,0x5FA8,0x5FAD,0x5FBC,0x5FD6,0x5FFB,0x5FE4,
+0x5FF8,0x5FF1,0x5FDD,0x60B3,0x5FFF,0x6021,0x6060,0x6019,
+0x6010,0x6029,0x600E,0x6031,0x601B,0x6015,0x602B,0x6026,
+0x600F,0x603A,0x605A,0x6041,0x606A,0x6077,0x605F,0x604A,
+0x6046,0x604D,0x6063,0x6043,0x6064,0x6042,0x606C,0x606B,
+0x6059,0x6081,0x608D,0x60E7,0x6083,0x609A};
+
+/* page 48 0x5821-0x587E */
+static uint16 tab_jisx0208_uni48[]={
+0x6084,0x609B,0x6096,0x6097,0x6092,0x60A7,0x608B,0x60E1,
+0x60B8,0x60E0,0x60D3,0x60B4,0x5FF0,0x60BD,0x60C6,0x60B5,
+0x60D8,0x614D,0x6115,0x6106,0x60F6,0x60F7,0x6100,0x60F4,
+0x60FA,0x6103,0x6121,0x60FB,0x60F1,0x610D,0x610E,0x6147,
+0x613E,0x6128,0x6127,0x614A,0x613F,0x613C,0x612C,0x6134,
+0x613D,0x6142,0x6144,0x6173,0x6177,0x6158,0x6159,0x615A,
+0x616B,0x6174,0x616F,0x6165,0x6171,0x615F,0x615D,0x6153,
+0x6175,0x6199,0x6196,0x6187,0x61AC,0x6194,0x619A,0x618A,
+0x6191,0x61AB,0x61AE,0x61CC,0x61CA,0x61C9,0x61F7,0x61C8,
+0x61C3,0x61C6,0x61BA,0x61CB,0x7F79,0x61CD,0x61E6,0x61E3,
+0x61F6,0x61FA,0x61F4,0x61FF,0x61FD,0x61FC,0x61FE,0x6200,
+0x6208,0x6209,0x620D,0x620C,0x6214,0x621B};
+
+/* page 49 0x5921-0x597E */
+static uint16 tab_jisx0208_uni49[]={
+0x621E,0x6221,0x622A,0x622E,0x6230,0x6232,0x6233,0x6241,
+0x624E,0x625E,0x6263,0x625B,0x6260,0x6268,0x627C,0x6282,
+0x6289,0x627E,0x6292,0x6293,0x6296,0x62D4,0x6283,0x6294,
+0x62D7,0x62D1,0x62BB,0x62CF,0x62FF,0x62C6,0x64D4,0x62C8,
+0x62DC,0x62CC,0x62CA,0x62C2,0x62C7,0x629B,0x62C9,0x630C,
+0x62EE,0x62F1,0x6327,0x6302,0x6308,0x62EF,0x62F5,0x6350,
+0x633E,0x634D,0x641C,0x634F,0x6396,0x638E,0x6380,0x63AB,
+0x6376,0x63A3,0x638F,0x6389,0x639F,0x63B5,0x636B,0x6369,
+0x63BE,0x63E9,0x63C0,0x63C6,0x63E3,0x63C9,0x63D2,0x63F6,
+0x63C4,0x6416,0x6434,0x6406,0x6413,0x6426,0x6436,0x651D,
+0x6417,0x6428,0x640F,0x6467,0x646F,0x6476,0x644E,0x652A,
+0x6495,0x6493,0x64A5,0x64A9,0x6488,0x64BC};
+
+/* page 50 0x5A21-0x5A7E */
+static uint16 tab_jisx0208_uni50[]={
+0x64DA,0x64D2,0x64C5,0x64C7,0x64BB,0x64D8,0x64C2,0x64F1,
+0x64E7,0x8209,0x64E0,0x64E1,0x62AC,0x64E3,0x64EF,0x652C,
+0x64F6,0x64F4,0x64F2,0x64FA,0x6500,0x64FD,0x6518,0x651C,
+0x6505,0x6524,0x6523,0x652B,0x6534,0x6535,0x6537,0x6536,
+0x6538,0x754B,0x6548,0x6556,0x6555,0x654D,0x6558,0x655E,
+0x655D,0x6572,0x6578,0x6582,0x6583,0x8B8A,0x659B,0x659F,
+0x65AB,0x65B7,0x65C3,0x65C6,0x65C1,0x65C4,0x65CC,0x65D2,
+0x65DB,0x65D9,0x65E0,0x65E1,0x65F1,0x6772,0x660A,0x6603,
+0x65FB,0x6773,0x6635,0x6636,0x6634,0x661C,0x664F,0x6644,
+0x6649,0x6641,0x665E,0x665D,0x6664,0x6667,0x6668,0x665F,
+0x6662,0x6670,0x6683,0x6688,0x668E,0x6689,0x6684,0x6698,
+0x669D,0x66C1,0x66B9,0x66C9,0x66BE,0x66BC};
+
+/* page 51 0x5B21-0x5B7E */
+static uint16 tab_jisx0208_uni51[]={
+0x66C4,0x66B8,0x66D6,0x66DA,0x66E0,0x663F,0x66E6,0x66E9,
+0x66F0,0x66F5,0x66F7,0x670F,0x6716,0x671E,0x6726,0x6727,
+0x9738,0x672E,0x673F,0x6736,0x6741,0x6738,0x6737,0x6746,
+0x675E,0x6760,0x6759,0x6763,0x6764,0x6789,0x6770,0x67A9,
+0x677C,0x676A,0x678C,0x678B,0x67A6,0x67A1,0x6785,0x67B7,
+0x67EF,0x67B4,0x67EC,0x67B3,0x67E9,0x67B8,0x67E4,0x67DE,
+0x67DD,0x67E2,0x67EE,0x67B9,0x67CE,0x67C6,0x67E7,0x6A9C,
+0x681E,0x6846,0x6829,0x6840,0x684D,0x6832,0x684E,0x68B3,
+0x682B,0x6859,0x6863,0x6877,0x687F,0x689F,0x688F,0x68AD,
+0x6894,0x689D,0x689B,0x6883,0x6AAE,0x68B9,0x6874,0x68B5,
+0x68A0,0x68BA,0x690F,0x688D,0x687E,0x6901,0x68CA,0x6908,
+0x68D8,0x6922,0x6926,0x68E1,0x690C,0x68CD};
+
+/* page 52 0x5C21-0x5C7E */
+static uint16 tab_jisx0208_uni52[]={
+0x68D4,0x68E7,0x68D5,0x6936,0x6912,0x6904,0x68D7,0x68E3,
+0x6925,0x68F9,0x68E0,0x68EF,0x6928,0x692A,0x691A,0x6923,
+0x6921,0x68C6,0x6979,0x6977,0x695C,0x6978,0x696B,0x6954,
+0x697E,0x696E,0x6939,0x6974,0x693D,0x6959,0x6930,0x6961,
+0x695E,0x695D,0x6981,0x696A,0x69B2,0x69AE,0x69D0,0x69BF,
+0x69C1,0x69D3,0x69BE,0x69CE,0x5BE8,0x69CA,0x69DD,0x69BB,
+0x69C3,0x69A7,0x6A2E,0x6991,0x69A0,0x699C,0x6995,0x69B4,
+0x69DE,0x69E8,0x6A02,0x6A1B,0x69FF,0x6B0A,0x69F9,0x69F2,
+0x69E7,0x6A05,0x69B1,0x6A1E,0x69ED,0x6A14,0x69EB,0x6A0A,
+0x6A12,0x6AC1,0x6A23,0x6A13,0x6A44,0x6A0C,0x6A72,0x6A36,
+0x6A78,0x6A47,0x6A62,0x6A59,0x6A66,0x6A48,0x6A38,0x6A22,
+0x6A90,0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3};
+
+/* page 53 0x5D21-0x5D7E */
+static uint16 tab_jisx0208_uni53[]={
+0x6A97,0x8617,0x6ABB,0x6AC3,0x6AC2,0x6AB8,0x6AB3,0x6AAC,
+0x6ADE,0x6AD1,0x6ADF,0x6AAA,0x6ADA,0x6AEA,0x6AFB,0x6B05,
+0x8616,0x6AFA,0x6B12,0x6B16,0x9B31,0x6B1F,0x6B38,0x6B37,
+0x76DC,0x6B39,0x98EE,0x6B47,0x6B43,0x6B49,0x6B50,0x6B59,
+0x6B54,0x6B5B,0x6B5F,0x6B61,0x6B78,0x6B79,0x6B7F,0x6B80,
+0x6B84,0x6B83,0x6B8D,0x6B98,0x6B95,0x6B9E,0x6BA4,0x6BAA,
+0x6BAB,0x6BAF,0x6BB2,0x6BB1,0x6BB3,0x6BB7,0x6BBC,0x6BC6,
+0x6BCB,0x6BD3,0x6BDF,0x6BEC,0x6BEB,0x6BF3,0x6BEF,0x9EBE,
+0x6C08,0x6C13,0x6C14,0x6C1B,0x6C24,0x6C23,0x6C5E,0x6C55,
+0x6C62,0x6C6A,0x6C82,0x6C8D,0x6C9A,0x6C81,0x6C9B,0x6C7E,
+0x6C68,0x6C73,0x6C92,0x6C90,0x6CC4,0x6CF1,0x6CD3,0x6CBD,
+0x6CD7,0x6CC5,0x6CDD,0x6CAE,0x6CB1,0x6CBE};
+
+/* page 54 0x5E21-0x5E7E */
+static uint16 tab_jisx0208_uni54[]={
+0x6CBA,0x6CDB,0x6CEF,0x6CD9,0x6CEA,0x6D1F,0x884D,0x6D36,
+0x6D2B,0x6D3D,0x6D38,0x6D19,0x6D35,0x6D33,0x6D12,0x6D0C,
+0x6D63,0x6D93,0x6D64,0x6D5A,0x6D79,0x6D59,0x6D8E,0x6D95,
+0x6FE4,0x6D85,0x6DF9,0x6E15,0x6E0A,0x6DB5,0x6DC7,0x6DE6,
+0x6DB8,0x6DC6,0x6DEC,0x6DDE,0x6DCC,0x6DE8,0x6DD2,0x6DC5,
+0x6DFA,0x6DD9,0x6DE4,0x6DD5,0x6DEA,0x6DEE,0x6E2D,0x6E6E,
+0x6E2E,0x6E19,0x6E72,0x6E5F,0x6E3E,0x6E23,0x6E6B,0x6E2B,
+0x6E76,0x6E4D,0x6E1F,0x6E43,0x6E3A,0x6E4E,0x6E24,0x6EFF,
+0x6E1D,0x6E38,0x6E82,0x6EAA,0x6E98,0x6EC9,0x6EB7,0x6ED3,
+0x6EBD,0x6EAF,0x6EC4,0x6EB2,0x6ED4,0x6ED5,0x6E8F,0x6EA5,
+0x6EC2,0x6E9F,0x6F41,0x6F11,0x704C,0x6EEC,0x6EF8,0x6EFE,
+0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
+
+/* page 55 0x5F21-0x5F7E */
+static uint16 tab_jisx0208_uni55[]={
+0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
+0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
+0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
+0x6FC6,0x6FAA,0x6FDF,0x6FD5,0x6FEC,0x6FD4,0x6FD8,0x6FF1,
+0x6FEE,0x6FDB,0x7009,0x700B,0x6FFA,0x7011,0x7001,0x700F,
+0x6FFE,0x701B,0x701A,0x6F74,0x701D,0x7018,0x701F,0x7030,
+0x703E,0x7032,0x7051,0x7063,0x7099,0x7092,0x70AF,0x70F1,
+0x70AC,0x70B8,0x70B3,0x70AE,0x70DF,0x70CB,0x70DD,0x70D9,
+0x7109,0x70FD,0x711C,0x7119,0x7165,0x7155,0x7188,0x7166,
+0x7162,0x714C,0x7156,0x716C,0x718F,0x71FB,0x7184,0x7195,
+0x71A8,0x71AC,0x71D7,0x71B9,0x71BE,0x71D2,0x71C9,0x71D4,
+0x71CE,0x71E0,0x71EC,0x71E7,0x71F5,0x71FC};
+
+/* page 56 0x6021-0x607E */
+static uint16 tab_jisx0208_uni56[]={
+0x71F9,0x71FF,0x720D,0x7210,0x721B,0x7228,0x722D,0x722C,
+0x7230,0x7232,0x723B,0x723C,0x723F,0x7240,0x7246,0x724B,
+0x7258,0x7274,0x727E,0x7282,0x7281,0x7287,0x7292,0x7296,
+0x72A2,0x72A7,0x72B9,0x72B2,0x72C3,0x72C6,0x72C4,0x72CE,
+0x72D2,0x72E2,0x72E0,0x72E1,0x72F9,0x72F7,0x500F,0x7317,
+0x730A,0x731C,0x7316,0x731D,0x7334,0x732F,0x7329,0x7325,
+0x733E,0x734E,0x734F,0x9ED8,0x7357,0x736A,0x7368,0x7370,
+0x7378,0x7375,0x737B,0x737A,0x73C8,0x73B3,0x73CE,0x73BB,
+0x73C0,0x73E5,0x73EE,0x73DE,0x74A2,0x7405,0x746F,0x7425,
+0x73F8,0x7432,0x743A,0x7455,0x743F,0x745F,0x7459,0x7441,
+0x745C,0x7469,0x7470,0x7463,0x746A,0x7476,0x747E,0x748B,
+0x749E,0x74A7,0x74CA,0x74CF,0x74D4,0x73F1};
+
+/* page 57 0x6121-0x617E */
+static uint16 tab_jisx0208_uni57[]={
+0x74E0,0x74E3,0x74E7,0x74E9,0x74EE,0x74F2,0x74F0,0x74F1,
+0x74F8,0x74F7,0x7504,0x7503,0x7505,0x750C,0x750E,0x750D,
+0x7515,0x7513,0x751E,0x7526,0x752C,0x753C,0x7544,0x754D,
+0x754A,0x7549,0x755B,0x7546,0x755A,0x7569,0x7564,0x7567,
+0x756B,0x756D,0x7578,0x7576,0x7586,0x7587,0x7574,0x758A,
+0x7589,0x7582,0x7594,0x759A,0x759D,0x75A5,0x75A3,0x75C2,
+0x75B3,0x75C3,0x75B5,0x75BD,0x75B8,0x75BC,0x75B1,0x75CD,
+0x75CA,0x75D2,0x75D9,0x75E3,0x75DE,0x75FE,0x75FF,0x75FC,
+0x7601,0x75F0,0x75FA,0x75F2,0x75F3,0x760B,0x760D,0x7609,
+0x761F,0x7627,0x7620,0x7621,0x7622,0x7624,0x7634,0x7630,
+0x763B,0x7647,0x7648,0x7646,0x765C,0x7658,0x7661,0x7662,
+0x7668,0x7669,0x766A,0x7667,0x766C,0x7670};
+
+/* page 58 0x6221-0x627E */
+static uint16 tab_jisx0208_uni58[]={
+0x7672,0x7676,0x7678,0x767C,0x7680,0x7683,0x7688,0x768B,
+0x768E,0x7696,0x7693,0x7699,0x769A,0x76B0,0x76B4,0x76B8,
+0x76B9,0x76BA,0x76C2,0x76CD,0x76D6,0x76D2,0x76DE,0x76E1,
+0x76E5,0x76E7,0x76EA,0x862F,0x76FB,0x7708,0x7707,0x7704,
+0x7729,0x7724,0x771E,0x7725,0x7726,0x771B,0x7737,0x7738,
+0x7747,0x775A,0x7768,0x776B,0x775B,0x7765,0x777F,0x777E,
+0x7779,0x778E,0x778B,0x7791,0x77A0,0x779E,0x77B0,0x77B6,
+0x77B9,0x77BF,0x77BC,0x77BD,0x77BB,0x77C7,0x77CD,0x77D7,
+0x77DA,0x77DC,0x77E3,0x77EE,0x77FC,0x780C,0x7812,0x7926,
+0x7820,0x792A,0x7845,0x788E,0x7874,0x7886,0x787C,0x789A,
+0x788C,0x78A3,0x78B5,0x78AA,0x78AF,0x78D1,0x78C6,0x78CB,
+0x78D4,0x78BE,0x78BC,0x78C5,0x78CA,0x78EC};
+
+/* page 59 0x6321-0x637E */
+static uint16 tab_jisx0208_uni59[]={
+0x78E7,0x78DA,0x78FD,0x78F4,0x7907,0x7912,0x7911,0x7919,
+0x792C,0x792B,0x7940,0x7960,0x7957,0x795F,0x795A,0x7955,
+0x7953,0x797A,0x797F,0x798A,0x799D,0x79A7,0x9F4B,0x79AA,
+0x79AE,0x79B3,0x79B9,0x79BA,0x79C9,0x79D5,0x79E7,0x79EC,
+0x79E1,0x79E3,0x7A08,0x7A0D,0x7A18,0x7A19,0x7A20,0x7A1F,
+0x7980,0x7A31,0x7A3B,0x7A3E,0x7A37,0x7A43,0x7A57,0x7A49,
+0x7A61,0x7A62,0x7A69,0x9F9D,0x7A70,0x7A79,0x7A7D,0x7A88,
+0x7A97,0x7A95,0x7A98,0x7A96,0x7AA9,0x7AC8,0x7AB0,0x7AB6,
+0x7AC5,0x7AC4,0x7ABF,0x9083,0x7AC7,0x7ACA,0x7ACD,0x7ACF,
+0x7AD5,0x7AD3,0x7AD9,0x7ADA,0x7ADD,0x7AE1,0x7AE2,0x7AE6,
+0x7AED,0x7AF0,0x7B02,0x7B0F,0x7B0A,0x7B06,0x7B33,0x7B18,
+0x7B19,0x7B1E,0x7B35,0x7B28,0x7B36,0x7B50};
+
+/* page 60 0x6421-0x647E */
+static uint16 tab_jisx0208_uni60[]={
+0x7B7A,0x7B04,0x7B4D,0x7B0B,0x7B4C,0x7B45,0x7B75,0x7B65,
+0x7B74,0x7B67,0x7B70,0x7B71,0x7B6C,0x7B6E,0x7B9D,0x7B98,
+0x7B9F,0x7B8D,0x7B9C,0x7B9A,0x7B8B,0x7B92,0x7B8F,0x7B5D,
+0x7B99,0x7BCB,0x7BC1,0x7BCC,0x7BCF,0x7BB4,0x7BC6,0x7BDD,
+0x7BE9,0x7C11,0x7C14,0x7BE6,0x7BE5,0x7C60,0x7C00,0x7C07,
+0x7C13,0x7BF3,0x7BF7,0x7C17,0x7C0D,0x7BF6,0x7C23,0x7C27,
+0x7C2A,0x7C1F,0x7C37,0x7C2B,0x7C3D,0x7C4C,0x7C43,0x7C54,
+0x7C4F,0x7C40,0x7C50,0x7C58,0x7C5F,0x7C64,0x7C56,0x7C65,
+0x7C6C,0x7C75,0x7C83,0x7C90,0x7CA4,0x7CAD,0x7CA2,0x7CAB,
+0x7CA1,0x7CA8,0x7CB3,0x7CB2,0x7CB1,0x7CAE,0x7CB9,0x7CBD,
+0x7CC0,0x7CC5,0x7CC2,0x7CD8,0x7CD2,0x7CDC,0x7CE2,0x9B3B,
+0x7CEF,0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06};
+
+/* page 61 0x6521-0x657E */
+static uint16 tab_jisx0208_uni61[]={
+0x7D02,0x7D1C,0x7D15,0x7D0A,0x7D45,0x7D4B,0x7D2E,0x7D32,
+0x7D3F,0x7D35,0x7D46,0x7D73,0x7D56,0x7D4E,0x7D72,0x7D68,
+0x7D6E,0x7D4F,0x7D63,0x7D93,0x7D89,0x7D5B,0x7D8F,0x7D7D,
+0x7D9B,0x7DBA,0x7DAE,0x7DA3,0x7DB5,0x7DC7,0x7DBD,0x7DAB,
+0x7E3D,0x7DA2,0x7DAF,0x7DDC,0x7DB8,0x7D9F,0x7DB0,0x7DD8,
+0x7DDD,0x7DE4,0x7DDE,0x7DFB,0x7DF2,0x7DE1,0x7E05,0x7E0A,
+0x7E23,0x7E21,0x7E12,0x7E31,0x7E1F,0x7E09,0x7E0B,0x7E22,
+0x7E46,0x7E66,0x7E3B,0x7E35,0x7E39,0x7E43,0x7E37,0x7E32,
+0x7E3A,0x7E67,0x7E5D,0x7E56,0x7E5E,0x7E59,0x7E5A,0x7E79,
+0x7E6A,0x7E69,0x7E7C,0x7E7B,0x7E83,0x7DD5,0x7E7D,0x8FAE,
+0x7E7F,0x7E88,0x7E89,0x7E8C,0x7E92,0x7E90,0x7E93,0x7E94,
+0x7E96,0x7E8E,0x7E9B,0x7E9C,0x7F38,0x7F3A};
+
+/* page 62 0x6621-0x667E */
+static uint16 tab_jisx0208_uni62[]={
+0x7F45,0x7F4C,0x7F4D,0x7F4E,0x7F50,0x7F51,0x7F55,0x7F54,
+0x7F58,0x7F5F,0x7F60,0x7F68,0x7F69,0x7F67,0x7F78,0x7F82,
+0x7F86,0x7F83,0x7F88,0x7F87,0x7F8C,0x7F94,0x7F9E,0x7F9D,
+0x7F9A,0x7FA3,0x7FAF,0x7FB2,0x7FB9,0x7FAE,0x7FB6,0x7FB8,
+0x8B71,0x7FC5,0x7FC6,0x7FCA,0x7FD5,0x7FD4,0x7FE1,0x7FE6,
+0x7FE9,0x7FF3,0x7FF9,0x98DC,0x8006,0x8004,0x800B,0x8012,
+0x8018,0x8019,0x801C,0x8021,0x8028,0x803F,0x803B,0x804A,
+0x8046,0x8052,0x8058,0x805A,0x805F,0x8062,0x8068,0x8073,
+0x8072,0x8070,0x8076,0x8079,0x807D,0x807F,0x8084,0x8086,
+0x8085,0x809B,0x8093,0x809A,0x80AD,0x5190,0x80AC,0x80DB,
+0x80E5,0x80D9,0x80DD,0x80C4,0x80DA,0x80D6,0x8109,0x80EF,
+0x80F1,0x811B,0x8129,0x8123,0x812F,0x814B};
+
+/* page 63 0x6721-0x677E */
+static uint16 tab_jisx0208_uni63[]={
+0x968B,0x8146,0x813E,0x8153,0x8151,0x80FC,0x8171,0x816E,
+0x8165,0x8166,0x8174,0x8183,0x8188,0x818A,0x8180,0x8182,
+0x81A0,0x8195,0x81A4,0x81A3,0x815F,0x8193,0x81A9,0x81B0,
+0x81B5,0x81BE,0x81B8,0x81BD,0x81C0,0x81C2,0x81BA,0x81C9,
+0x81CD,0x81D1,0x81D9,0x81D8,0x81C8,0x81DA,0x81DF,0x81E0,
+0x81E7,0x81FA,0x81FB,0x81FE,0x8201,0x8202,0x8205,0x8207,
+0x820A,0x820D,0x8210,0x8216,0x8229,0x822B,0x8238,0x8233,
+0x8240,0x8259,0x8258,0x825D,0x825A,0x825F,0x8264,0x8262,
+0x8268,0x826A,0x826B,0x822E,0x8271,0x8277,0x8278,0x827E,
+0x828D,0x8292,0x82AB,0x829F,0x82BB,0x82AC,0x82E1,0x82E3,
+0x82DF,0x82D2,0x82F4,0x82F3,0x82FA,0x8393,0x8303,0x82FB,
+0x82F9,0x82DE,0x8306,0x82DC,0x8309,0x82D9};
+
+/* page 64 0x6821-0x687E */
+static uint16 tab_jisx0208_uni64[]={
+0x8335,0x8334,0x8316,0x8332,0x8331,0x8340,0x8339,0x8350,
+0x8345,0x832F,0x832B,0x8317,0x8318,0x8385,0x839A,0x83AA,
+0x839F,0x83A2,0x8396,0x8323,0x838E,0x8387,0x838A,0x837C,
+0x83B5,0x8373,0x8375,0x83A0,0x8389,0x83A8,0x83F4,0x8413,
+0x83EB,0x83CE,0x83FD,0x8403,0x83D8,0x840B,0x83C1,0x83F7,
+0x8407,0x83E0,0x83F2,0x840D,0x8422,0x8420,0x83BD,0x8438,
+0x8506,0x83FB,0x846D,0x842A,0x843C,0x855A,0x8484,0x8477,
+0x846B,0x84AD,0x846E,0x8482,0x8469,0x8446,0x842C,0x846F,
+0x8479,0x8435,0x84CA,0x8462,0x84B9,0x84BF,0x849F,0x84D9,
+0x84CD,0x84BB,0x84DA,0x84D0,0x84C1,0x84C6,0x84D6,0x84A1,
+0x8521,0x84FF,0x84F4,0x8517,0x8518,0x852C,0x851F,0x8515,
+0x8514,0x84FC,0x8540,0x8563,0x8558,0x8548};
+
+/* page 65 0x6921-0x697E */
+static uint16 tab_jisx0208_uni65[]={
+0x8541,0x8602,0x854B,0x8555,0x8580,0x85A4,0x8588,0x8591,
+0x858A,0x85A8,0x856D,0x8594,0x859B,0x85EA,0x8587,0x859C,
+0x8577,0x857E,0x8590,0x85C9,0x85BA,0x85CF,0x85B9,0x85D0,
+0x85D5,0x85DD,0x85E5,0x85DC,0x85F9,0x860A,0x8613,0x860B,
+0x85FE,0x85FA,0x8606,0x8622,0x861A,0x8630,0x863F,0x864D,
+0x4E55,0x8654,0x865F,0x8667,0x8671,0x8693,0x86A3,0x86A9,
+0x86AA,0x868B,0x868C,0x86B6,0x86AF,0x86C4,0x86C6,0x86B0,
+0x86C9,0x8823,0x86AB,0x86D4,0x86DE,0x86E9,0x86EC,0x86DF,
+0x86DB,0x86EF,0x8712,0x8706,0x8708,0x8700,0x8703,0x86FB,
+0x8711,0x8709,0x870D,0x86F9,0x870A,0x8734,0x873F,0x8737,
+0x873B,0x8725,0x8729,0x871A,0x8760,0x875F,0x8778,0x874C,
+0x874E,0x8774,0x8757,0x8768,0x876E,0x8759};
+
+/* page 66 0x6A21-0x6A7E */
+static uint16 tab_jisx0208_uni66[]={
+0x8753,0x8763,0x876A,0x8805,0x87A2,0x879F,0x8782,0x87AF,
+0x87CB,0x87BD,0x87C0,0x87D0,0x96D6,0x87AB,0x87C4,0x87B3,
+0x87C7,0x87C6,0x87BB,0x87EF,0x87F2,0x87E0,0x880F,0x880D,
+0x87FE,0x87F6,0x87F7,0x880E,0x87D2,0x8811,0x8816,0x8815,
+0x8822,0x8821,0x8831,0x8836,0x8839,0x8827,0x883B,0x8844,
+0x8842,0x8852,0x8859,0x885E,0x8862,0x886B,0x8881,0x887E,
+0x889E,0x8875,0x887D,0x88B5,0x8872,0x8882,0x8897,0x8892,
+0x88AE,0x8899,0x88A2,0x888D,0x88A4,0x88B0,0x88BF,0x88B1,
+0x88C3,0x88C4,0x88D4,0x88D8,0x88D9,0x88DD,0x88F9,0x8902,
+0x88FC,0x88F4,0x88E8,0x88F2,0x8904,0x890C,0x890A,0x8913,
+0x8943,0x891E,0x8925,0x892A,0x892B,0x8941,0x8944,0x893B,
+0x8936,0x8938,0x894C,0x891D,0x8960,0x895E};
+
+/* page 67 0x6B21-0x6B7E */
+static uint16 tab_jisx0208_uni67[]={
+0x8966,0x8964,0x896D,0x896A,0x896F,0x8974,0x8977,0x897E,
+0x8983,0x8988,0x898A,0x8993,0x8998,0x89A1,0x89A9,0x89A6,
+0x89AC,0x89AF,0x89B2,0x89BA,0x89BD,0x89BF,0x89C0,0x89DA,
+0x89DC,0x89DD,0x89E7,0x89F4,0x89F8,0x8A03,0x8A16,0x8A10,
+0x8A0C,0x8A1B,0x8A1D,0x8A25,0x8A36,0x8A41,0x8A5B,0x8A52,
+0x8A46,0x8A48,0x8A7C,0x8A6D,0x8A6C,0x8A62,0x8A85,0x8A82,
+0x8A84,0x8AA8,0x8AA1,0x8A91,0x8AA5,0x8AA6,0x8A9A,0x8AA3,
+0x8AC4,0x8ACD,0x8AC2,0x8ADA,0x8AEB,0x8AF3,0x8AE7,0x8AE4,
+0x8AF1,0x8B14,0x8AE0,0x8AE2,0x8AF7,0x8ADE,0x8ADB,0x8B0C,
+0x8B07,0x8B1A,0x8AE1,0x8B16,0x8B10,0x8B17,0x8B20,0x8B33,
+0x97AB,0x8B26,0x8B2B,0x8B3E,0x8B28,0x8B41,0x8B4C,0x8B4F,
+0x8B4E,0x8B49,0x8B56,0x8B5B,0x8B5A,0x8B6B};
+
+/* page 68 0x6C21-0x6C7E */
+static uint16 tab_jisx0208_uni68[]={
+0x8B5F,0x8B6C,0x8B6F,0x8B74,0x8B7D,0x8B80,0x8B8C,0x8B8E,
+0x8B92,0x8B93,0x8B96,0x8B99,0x8B9A,0x8C3A,0x8C41,0x8C3F,
+0x8C48,0x8C4C,0x8C4E,0x8C50,0x8C55,0x8C62,0x8C6C,0x8C78,
+0x8C7A,0x8C82,0x8C89,0x8C85,0x8C8A,0x8C8D,0x8C8E,0x8C94,
+0x8C7C,0x8C98,0x621D,0x8CAD,0x8CAA,0x8CBD,0x8CB2,0x8CB3,
+0x8CAE,0x8CB6,0x8CC8,0x8CC1,0x8CE4,0x8CE3,0x8CDA,0x8CFD,
+0x8CFA,0x8CFB,0x8D04,0x8D05,0x8D0A,0x8D07,0x8D0F,0x8D0D,
+0x8D10,0x9F4E,0x8D13,0x8CCD,0x8D14,0x8D16,0x8D67,0x8D6D,
+0x8D71,0x8D73,0x8D81,0x8D99,0x8DC2,0x8DBE,0x8DBA,0x8DCF,
+0x8DDA,0x8DD6,0x8DCC,0x8DDB,0x8DCB,0x8DEA,0x8DEB,0x8DDF,
+0x8DE3,0x8DFC,0x8E08,0x8E09,0x8DFF,0x8E1D,0x8E1E,0x8E10,
+0x8E1F,0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A};
+
+/* page 69 0x6D21-0x6D7E */
+static uint16 tab_jisx0208_uni69[]={
+0x8E47,0x8E49,0x8E4C,0x8E50,0x8E48,0x8E59,0x8E64,0x8E60,
+0x8E2A,0x8E63,0x8E55,0x8E76,0x8E72,0x8E7C,0x8E81,0x8E87,
+0x8E85,0x8E84,0x8E8B,0x8E8A,0x8E93,0x8E91,0x8E94,0x8E99,
+0x8EAA,0x8EA1,0x8EAC,0x8EB0,0x8EC6,0x8EB1,0x8EBE,0x8EC5,
+0x8EC8,0x8ECB,0x8EDB,0x8EE3,0x8EFC,0x8EFB,0x8EEB,0x8EFE,
+0x8F0A,0x8F05,0x8F15,0x8F12,0x8F19,0x8F13,0x8F1C,0x8F1F,
+0x8F1B,0x8F0C,0x8F26,0x8F33,0x8F3B,0x8F39,0x8F45,0x8F42,
+0x8F3E,0x8F4C,0x8F49,0x8F46,0x8F4E,0x8F57,0x8F5C,0x8F62,
+0x8F63,0x8F64,0x8F9C,0x8F9F,0x8FA3,0x8FAD,0x8FAF,0x8FB7,
+0x8FDA,0x8FE5,0x8FE2,0x8FEA,0x8FEF,0x9087,0x8FF4,0x9005,
+0x8FF9,0x8FFA,0x9011,0x9015,0x9021,0x900D,0x901E,0x9016,
+0x900B,0x9027,0x9036,0x9035,0x9039,0x8FF8};
+
+/* page 70 0x6E21-0x6E7E */
+static uint16 tab_jisx0208_uni70[]={
+0x904F,0x9050,0x9051,0x9052,0x900E,0x9049,0x903E,0x9056,
+0x9058,0x905E,0x9068,0x906F,0x9076,0x96A8,0x9072,0x9082,
+0x907D,0x9081,0x9080,0x908A,0x9089,0x908F,0x90A8,0x90AF,
+0x90B1,0x90B5,0x90E2,0x90E4,0x6248,0x90DB,0x9102,0x9112,
+0x9119,0x9132,0x9130,0x914A,0x9156,0x9158,0x9163,0x9165,
+0x9169,0x9173,0x9172,0x918B,0x9189,0x9182,0x91A2,0x91AB,
+0x91AF,0x91AA,0x91B5,0x91B4,0x91BA,0x91C0,0x91C1,0x91C9,
+0x91CB,0x91D0,0x91D6,0x91DF,0x91E1,0x91DB,0x91FC,0x91F5,
+0x91F6,0x921E,0x91FF,0x9214,0x922C,0x9215,0x9211,0x925E,
+0x9257,0x9245,0x9249,0x9264,0x9248,0x9295,0x923F,0x924B,
+0x9250,0x929C,0x9296,0x9293,0x929B,0x925A,0x92CF,0x92B9,
+0x92B7,0x92E9,0x930F,0x92FA,0x9344,0x932E};
+
+/* page 71 0x6F21-0x6F7E */
+static uint16 tab_jisx0208_uni71[]={
+0x9319,0x9322,0x931A,0x9323,0x933A,0x9335,0x933B,0x935C,
+0x9360,0x937C,0x936E,0x9356,0x93B0,0x93AC,0x93AD,0x9394,
+0x93B9,0x93D6,0x93D7,0x93E8,0x93E5,0x93D8,0x93C3,0x93DD,
+0x93D0,0x93C8,0x93E4,0x941A,0x9414,0x9413,0x9403,0x9407,
+0x9410,0x9436,0x942B,0x9435,0x9421,0x943A,0x9441,0x9452,
+0x9444,0x945B,0x9460,0x9462,0x945E,0x946A,0x9229,0x9470,
+0x9475,0x9477,0x947D,0x945A,0x947C,0x947E,0x9481,0x947F,
+0x9582,0x9587,0x958A,0x9594,0x9596,0x9598,0x9599,0x95A0,
+0x95A8,0x95A7,0x95AD,0x95BC,0x95BB,0x95B9,0x95BE,0x95CA,
+0x6FF6,0x95C3,0x95CD,0x95CC,0x95D5,0x95D4,0x95D6,0x95DC,
+0x95E1,0x95E5,0x95E2,0x9621,0x9628,0x962E,0x962F,0x9642,
+0x964C,0x964F,0x964B,0x9677,0x965C,0x965E};
+
+/* page 72 0x7021-0x707E */
+static uint16 tab_jisx0208_uni72[]={
+0x965D,0x965F,0x9666,0x9672,0x966C,0x968D,0x9698,0x9695,
+0x9697,0x96AA,0x96A7,0x96B1,0x96B2,0x96B0,0x96B4,0x96B6,
+0x96B8,0x96B9,0x96CE,0x96CB,0x96C9,0x96CD,0x894D,0x96DC,
+0x970D,0x96D5,0x96F9,0x9704,0x9706,0x9708,0x9713,0x970E,
+0x9711,0x970F,0x9716,0x9719,0x9724,0x972A,0x9730,0x9739,
+0x973D,0x973E,0x9744,0x9746,0x9748,0x9742,0x9749,0x975C,
+0x9760,0x9764,0x9766,0x9768,0x52D2,0x976B,0x9771,0x9779,
+0x9785,0x977C,0x9781,0x977A,0x9786,0x978B,0x978F,0x9790,
+0x979C,0x97A8,0x97A6,0x97A3,0x97B3,0x97B4,0x97C3,0x97C6,
+0x97C8,0x97CB,0x97DC,0x97ED,0x9F4F,0x97F2,0x7ADF,0x97F6,
+0x97F5,0x980F,0x980C,0x9838,0x9824,0x9821,0x9837,0x983D,
+0x9846,0x984F,0x984B,0x986B,0x986F,0x9870};
+
+/* page 73 0x7121-0x717E */
+static uint16 tab_jisx0208_uni73[]={
+0x9871,0x9874,0x9873,0x98AA,0x98AF,0x98B1,0x98B6,0x98C4,
+0x98C3,0x98C6,0x98E9,0x98EB,0x9903,0x9909,0x9912,0x9914,
+0x9918,0x9921,0x991D,0x991E,0x9924,0x9920,0x992C,0x992E,
+0x993D,0x993E,0x9942,0x9949,0x9945,0x9950,0x994B,0x9951,
+0x9952,0x994C,0x9955,0x9997,0x9998,0x99A5,0x99AD,0x99AE,
+0x99BC,0x99DF,0x99DB,0x99DD,0x99D8,0x99D1,0x99ED,0x99EE,
+0x99F1,0x99F2,0x99FB,0x99F8,0x9A01,0x9A0F,0x9A05,0x99E2,
+0x9A19,0x9A2B,0x9A37,0x9A45,0x9A42,0x9A40,0x9A43,0x9A3E,
+0x9A55,0x9A4D,0x9A5B,0x9A57,0x9A5F,0x9A62,0x9A65,0x9A64,
+0x9A69,0x9A6B,0x9A6A,0x9AAD,0x9AB0,0x9ABC,0x9AC0,0x9ACF,
+0x9AD1,0x9AD3,0x9AD4,0x9ADE,0x9ADF,0x9AE2,0x9AE3,0x9AE6,
+0x9AEF,0x9AEB,0x9AEE,0x9AF4,0x9AF1,0x9AF7};
+
+/* page 74 0x7221-0x727E */
+static uint16 tab_jisx0208_uni74[]={
+0x9AFB,0x9B06,0x9B18,0x9B1A,0x9B1F,0x9B22,0x9B23,0x9B25,
+0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2E,0x9B2F,0x9B32,0x9B44,
+0x9B43,0x9B4F,0x9B4D,0x9B4E,0x9B51,0x9B58,0x9B74,0x9B93,
+0x9B83,0x9B91,0x9B96,0x9B97,0x9B9F,0x9BA0,0x9BA8,0x9BB4,
+0x9BC0,0x9BCA,0x9BB9,0x9BC6,0x9BCF,0x9BD1,0x9BD2,0x9BE3,
+0x9BE2,0x9BE4,0x9BD4,0x9BE1,0x9C3A,0x9BF2,0x9BF1,0x9BF0,
+0x9C15,0x9C14,0x9C09,0x9C13,0x9C0C,0x9C06,0x9C08,0x9C12,
+0x9C0A,0x9C04,0x9C2E,0x9C1B,0x9C25,0x9C24,0x9C21,0x9C30,
+0x9C47,0x9C32,0x9C46,0x9C3E,0x9C5A,0x9C60,0x9C67,0x9C76,
+0x9C78,0x9CE7,0x9CEC,0x9CF0,0x9D09,0x9D08,0x9CEB,0x9D03,
+0x9D06,0x9D2A,0x9D26,0x9DAF,0x9D23,0x9D1F,0x9D44,0x9D15,
+0x9D12,0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48};
+
+/* page 75 0x7321-0x737E */
+static uint16 tab_jisx0208_uni75[]={
+0x9D5D,0x9D5E,0x9D64,0x9D51,0x9D50,0x9D59,0x9D72,0x9D89,
+0x9D87,0x9DAB,0x9D6F,0x9D7A,0x9D9A,0x9DA4,0x9DA9,0x9DB2,
+0x9DC4,0x9DC1,0x9DBB,0x9DB8,0x9DBA,0x9DC6,0x9DCF,0x9DC2,
+0x9DD9,0x9DD3,0x9DF8,0x9DE6,0x9DED,0x9DEF,0x9DFD,0x9E1A,
+0x9E1B,0x9E1E,0x9E75,0x9E79,0x9E7D,0x9E81,0x9E88,0x9E8B,
+0x9E8C,0x9E92,0x9E95,0x9E91,0x9E9D,0x9EA5,0x9EA9,0x9EB8,
+0x9EAA,0x9EAD,0x9761,0x9ECC,0x9ECE,0x9ECF,0x9ED0,0x9ED4,
+0x9EDC,0x9EDE,0x9EDD,0x9EE0,0x9EE5,0x9EE8,0x9EEF,0x9EF4,
+0x9EF6,0x9EF7,0x9EF9,0x9EFB,0x9EFC,0x9EFD,0x9F07,0x9F08,
+0x76B7,0x9F15,0x9F21,0x9F2C,0x9F3E,0x9F4A,0x9F52,0x9F54,
+0x9F63,0x9F5F,0x9F60,0x9F61,0x9F66,0x9F67,0x9F6C,0x9F6A,
+0x9F77,0x9F72,0x9F76,0x9F95,0x9F9C,0x9FA0};
+
+/* page 76 0x7421-0x7426 */
+static uint16 tab_jisx0208_uni76[]={
+0x582F,0x69C7,0x9059,0x7464,0x51DC,0x7199};
+
+static int
+my_jisx0208_uni_onechar(int code){
+ if ((code>=0x2121)&&(code<=0x217E))
+ return(tab_jisx0208_uni0[code-0x2121]);
+ if ((code>=0x2221)&&(code<=0x227E))
+ return(tab_jisx0208_uni1[code-0x2221]);
+ if ((code>=0x2330)&&(code<=0x237A))
+ return(tab_jisx0208_uni2[code-0x2330]);
+ if ((code>=0x2421)&&(code<=0x2473))
+ return(tab_jisx0208_uni3[code-0x2421]);
+ if ((code>=0x2521)&&(code<=0x2576))
+ return(tab_jisx0208_uni4[code-0x2521]);
+ if ((code>=0x2621)&&(code<=0x2658))
+ return(tab_jisx0208_uni5[code-0x2621]);
+ if ((code>=0x2721)&&(code<=0x2771))
+ return(tab_jisx0208_uni6[code-0x2721]);
+ if ((code>=0x2821)&&(code<=0x2840))
+ return(tab_jisx0208_uni7[code-0x2821]);
+ if ((code>=0x3021)&&(code<=0x307E))
+ return(tab_jisx0208_uni8[code-0x3021]);
+ if ((code>=0x3121)&&(code<=0x317E))
+ return(tab_jisx0208_uni9[code-0x3121]);
+ if ((code>=0x3221)&&(code<=0x327E))
+ return(tab_jisx0208_uni10[code-0x3221]);
+ if ((code>=0x3321)&&(code<=0x337E))
+ return(tab_jisx0208_uni11[code-0x3321]);
+ if ((code>=0x3421)&&(code<=0x347E))
+ return(tab_jisx0208_uni12[code-0x3421]);
+ if ((code>=0x3521)&&(code<=0x357E))
+ return(tab_jisx0208_uni13[code-0x3521]);
+ if ((code>=0x3621)&&(code<=0x367E))
+ return(tab_jisx0208_uni14[code-0x3621]);
+ if ((code>=0x3721)&&(code<=0x377E))
+ return(tab_jisx0208_uni15[code-0x3721]);
+ if ((code>=0x3821)&&(code<=0x387E))
+ return(tab_jisx0208_uni16[code-0x3821]);
+ if ((code>=0x3921)&&(code<=0x397E))
+ return(tab_jisx0208_uni17[code-0x3921]);
+ if ((code>=0x3A21)&&(code<=0x3A7E))
+ return(tab_jisx0208_uni18[code-0x3A21]);
+ if ((code>=0x3B21)&&(code<=0x3B7E))
+ return(tab_jisx0208_uni19[code-0x3B21]);
+ if ((code>=0x3C21)&&(code<=0x3C7E))
+ return(tab_jisx0208_uni20[code-0x3C21]);
+ if ((code>=0x3D21)&&(code<=0x3D7E))
+ return(tab_jisx0208_uni21[code-0x3D21]);
+ if ((code>=0x3E21)&&(code<=0x3E7E))
+ return(tab_jisx0208_uni22[code-0x3E21]);
+ if ((code>=0x3F21)&&(code<=0x3F7E))
+ return(tab_jisx0208_uni23[code-0x3F21]);
+ if ((code>=0x4021)&&(code<=0x407E))
+ return(tab_jisx0208_uni24[code-0x4021]);
+ if ((code>=0x4121)&&(code<=0x417E))
+ return(tab_jisx0208_uni25[code-0x4121]);
+ if ((code>=0x4221)&&(code<=0x427E))
+ return(tab_jisx0208_uni26[code-0x4221]);
+ if ((code>=0x4321)&&(code<=0x437E))
+ return(tab_jisx0208_uni27[code-0x4321]);
+ if ((code>=0x4421)&&(code<=0x447E))
+ return(tab_jisx0208_uni28[code-0x4421]);
+ if ((code>=0x4521)&&(code<=0x457E))
+ return(tab_jisx0208_uni29[code-0x4521]);
+ if ((code>=0x4621)&&(code<=0x467E))
+ return(tab_jisx0208_uni30[code-0x4621]);
+ if ((code>=0x4721)&&(code<=0x477E))
+ return(tab_jisx0208_uni31[code-0x4721]);
+ if ((code>=0x4821)&&(code<=0x487E))
+ return(tab_jisx0208_uni32[code-0x4821]);
+ if ((code>=0x4921)&&(code<=0x497E))
+ return(tab_jisx0208_uni33[code-0x4921]);
+ if ((code>=0x4A21)&&(code<=0x4A7E))
+ return(tab_jisx0208_uni34[code-0x4A21]);
+ if ((code>=0x4B21)&&(code<=0x4B7E))
+ return(tab_jisx0208_uni35[code-0x4B21]);
+ if ((code>=0x4C21)&&(code<=0x4C7E))
+ return(tab_jisx0208_uni36[code-0x4C21]);
+ if ((code>=0x4D21)&&(code<=0x4D7E))
+ return(tab_jisx0208_uni37[code-0x4D21]);
+ if ((code>=0x4E21)&&(code<=0x4E7E))
+ return(tab_jisx0208_uni38[code-0x4E21]);
+ if ((code>=0x4F21)&&(code<=0x4F53))
+ return(tab_jisx0208_uni39[code-0x4F21]);
+ if ((code>=0x5021)&&(code<=0x507E))
+ return(tab_jisx0208_uni40[code-0x5021]);
+ if ((code>=0x5121)&&(code<=0x517E))
+ return(tab_jisx0208_uni41[code-0x5121]);
+ if ((code>=0x5221)&&(code<=0x527E))
+ return(tab_jisx0208_uni42[code-0x5221]);
+ if ((code>=0x5321)&&(code<=0x537E))
+ return(tab_jisx0208_uni43[code-0x5321]);
+ if ((code>=0x5421)&&(code<=0x547E))
+ return(tab_jisx0208_uni44[code-0x5421]);
+ if ((code>=0x5521)&&(code<=0x557E))
+ return(tab_jisx0208_uni45[code-0x5521]);
+ if ((code>=0x5621)&&(code<=0x567E))
+ return(tab_jisx0208_uni46[code-0x5621]);
+ if ((code>=0x5721)&&(code<=0x577E))
+ return(tab_jisx0208_uni47[code-0x5721]);
+ if ((code>=0x5821)&&(code<=0x587E))
+ return(tab_jisx0208_uni48[code-0x5821]);
+ if ((code>=0x5921)&&(code<=0x597E))
+ return(tab_jisx0208_uni49[code-0x5921]);
+ if ((code>=0x5A21)&&(code<=0x5A7E))
+ return(tab_jisx0208_uni50[code-0x5A21]);
+ if ((code>=0x5B21)&&(code<=0x5B7E))
+ return(tab_jisx0208_uni51[code-0x5B21]);
+ if ((code>=0x5C21)&&(code<=0x5C7E))
+ return(tab_jisx0208_uni52[code-0x5C21]);
+ if ((code>=0x5D21)&&(code<=0x5D7E))
+ return(tab_jisx0208_uni53[code-0x5D21]);
+ if ((code>=0x5E21)&&(code<=0x5E7E))
+ return(tab_jisx0208_uni54[code-0x5E21]);
+ if ((code>=0x5F21)&&(code<=0x5F7E))
+ return(tab_jisx0208_uni55[code-0x5F21]);
+ if ((code>=0x6021)&&(code<=0x607E))
+ return(tab_jisx0208_uni56[code-0x6021]);
+ if ((code>=0x6121)&&(code<=0x617E))
+ return(tab_jisx0208_uni57[code-0x6121]);
+ if ((code>=0x6221)&&(code<=0x627E))
+ return(tab_jisx0208_uni58[code-0x6221]);
+ if ((code>=0x6321)&&(code<=0x637E))
+ return(tab_jisx0208_uni59[code-0x6321]);
+ if ((code>=0x6421)&&(code<=0x647E))
+ return(tab_jisx0208_uni60[code-0x6421]);
+ if ((code>=0x6521)&&(code<=0x657E))
+ return(tab_jisx0208_uni61[code-0x6521]);
+ if ((code>=0x6621)&&(code<=0x667E))
+ return(tab_jisx0208_uni62[code-0x6621]);
+ if ((code>=0x6721)&&(code<=0x677E))
+ return(tab_jisx0208_uni63[code-0x6721]);
+ if ((code>=0x6821)&&(code<=0x687E))
+ return(tab_jisx0208_uni64[code-0x6821]);
+ if ((code>=0x6921)&&(code<=0x697E))
+ return(tab_jisx0208_uni65[code-0x6921]);
+ if ((code>=0x6A21)&&(code<=0x6A7E))
+ return(tab_jisx0208_uni66[code-0x6A21]);
+ if ((code>=0x6B21)&&(code<=0x6B7E))
+ return(tab_jisx0208_uni67[code-0x6B21]);
+ if ((code>=0x6C21)&&(code<=0x6C7E))
+ return(tab_jisx0208_uni68[code-0x6C21]);
+ if ((code>=0x6D21)&&(code<=0x6D7E))
+ return(tab_jisx0208_uni69[code-0x6D21]);
+ if ((code>=0x6E21)&&(code<=0x6E7E))
+ return(tab_jisx0208_uni70[code-0x6E21]);
+ if ((code>=0x6F21)&&(code<=0x6F7E))
+ return(tab_jisx0208_uni71[code-0x6F21]);
+ if ((code>=0x7021)&&(code<=0x707E))
+ return(tab_jisx0208_uni72[code-0x7021]);
+ if ((code>=0x7121)&&(code<=0x717E))
+ return(tab_jisx0208_uni73[code-0x7121]);
+ if ((code>=0x7221)&&(code<=0x727E))
+ return(tab_jisx0208_uni74[code-0x7221]);
+ if ((code>=0x7321)&&(code<=0x737E))
+ return(tab_jisx0208_uni75[code-0x7321]);
+ if ((code>=0x7421)&&(code<=0x7426))
+ return(tab_jisx0208_uni76[code-0x7421]);
+ return(0);
+}
+
+
+/* page 0 0x005C-0x005C */
+static uint16 tab_uni_jisx02080[]={
+0x2140};
+
+/* page 1 0x00A2-0x00B6 */
+static uint16 tab_uni_jisx02081[]={
+0x2171,0x2172, 0, 0, 0,0x2178,0x212F, 0,
+ 0, 0,0x224C, 0, 0, 0,0x216B,0x215E,
+ 0, 0,0x212D, 0,0x2279};
+
+/* page 2 0x00D7-0x00D7 */
+static uint16 tab_uni_jisx02082[]={
+0x215F};
+
+/* page 3 0x00F7-0x00F7 */
+static uint16 tab_uni_jisx02083[]={
+0x2160};
+
+/* page 4 0x0391-0x03C9 */
+static uint16 tab_uni_jisx02084[]={
+0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,0x2628,
+0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F,0x2630,
+0x2631, 0,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637,
+0x2638, 0, 0, 0, 0, 0, 0, 0,
+0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,0x2647,0x2648,
+0x2649,0x264A,0x264B,0x264C,0x264D,0x264E,0x264F,0x2650,
+0x2651, 0,0x2652,0x2653,0x2654,0x2655,0x2656,0x2657,
+0x2658};
+
+/* page 5 0x0401-0x0451 */
+static uint16 tab_uni_jisx02085[]={
+0x2727, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2721,
+0x2722,0x2723,0x2724,0x2725,0x2726,0x2728,0x2729,0x272A,
+0x272B,0x272C,0x272D,0x272E,0x272F,0x2730,0x2731,0x2732,
+0x2733,0x2734,0x2735,0x2736,0x2737,0x2738,0x2739,0x273A,
+0x273B,0x273C,0x273D,0x273E,0x273F,0x2740,0x2741,0x2751,
+0x2752,0x2753,0x2754,0x2755,0x2756,0x2758,0x2759,0x275A,
+0x275B,0x275C,0x275D,0x275E,0x275F,0x2760,0x2761,0x2762,
+0x2763,0x2764,0x2765,0x2766,0x2767,0x2768,0x2769,0x276A,
+0x276B,0x276C,0x276D,0x276E,0x276F,0x2770,0x2771, 0,
+0x2757};
+
+/* page 6 0x2010-0x203B */
+static uint16 tab_uni_jisx02086[]={
+0x213E, 0, 0, 0, 0,0x213D,0x2142, 0,
+0x2146,0x2147, 0, 0,0x2148,0x2149, 0, 0,
+0x2277,0x2278, 0, 0, 0,0x2145,0x2144, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2273, 0,0x216C,0x216D, 0, 0, 0, 0,
+ 0, 0, 0,0x2228};
+
+/* page 7 0x2103-0x2103 */
+static uint16 tab_uni_jisx02087[]={
+0x216E};
+
+/* page 8 0x212B-0x212B */
+static uint16 tab_uni_jisx02088[]={
+0x2272};
+
+/* page 9 0x2190-0x2193 */
+static uint16 tab_uni_jisx02089[]={
+0x222B,0x222C,0x222A,0x222D};
+
+/* page 10 0x21D2-0x21D4 */
+static uint16 tab_uni_jisx020810[]={
+0x224D, 0,0x224E};
+
+/* page 11 0x2200-0x223D */
+static uint16 tab_uni_jisx020811[]={
+0x224F, 0,0x225F,0x2250, 0, 0, 0,0x2260,
+0x223A, 0, 0,0x223B, 0, 0, 0, 0,
+ 0, 0,0x215D, 0, 0, 0, 0, 0,
+ 0, 0,0x2265, 0, 0,0x2267,0x2167, 0,
+0x225C, 0, 0, 0, 0, 0, 0,0x224A,
+0x224B,0x2241,0x2240,0x2269,0x226A, 0, 0, 0,
+ 0, 0, 0, 0,0x2168,0x2268, 0, 0,
+ 0, 0, 0, 0, 0,0x2266};
+
+/* page 12 0x2252-0x226B */
+static uint16 tab_uni_jisx020812[]={
+0x2262, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2162,0x2261,
+ 0, 0, 0, 0,0x2165,0x2166, 0, 0,
+0x2263,0x2264};
+
+/* page 13 0x2282-0x2287 */
+static uint16 tab_uni_jisx020813[]={
+0x223E,0x223F, 0, 0,0x223C,0x223D};
+
+/* page 14 0x22A5-0x22A5 */
+static uint16 tab_uni_jisx020814[]={
+0x225D};
+
+/* page 15 0x2312-0x2312 */
+static uint16 tab_uni_jisx020815[]={
+0x225E};
+
+/* page 16 0x2500-0x254B */
+static uint16 tab_uni_jisx020816[]={
+0x2821,0x282C,0x2822,0x282D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2823, 0, 0,0x282E,
+0x2824, 0, 0,0x282F,0x2826, 0, 0,0x2831,
+0x2825, 0, 0,0x2830,0x2827,0x283C, 0, 0,
+0x2837, 0, 0,0x2832,0x2829,0x283E, 0, 0,
+0x2839, 0, 0,0x2834,0x2828, 0, 0,0x2838,
+0x283D, 0, 0,0x2833,0x282A, 0, 0,0x283A,
+0x283F, 0, 0,0x2835,0x282B, 0, 0,0x283B,
+ 0, 0,0x2840, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2836};
+
+/* page 17 0x25A0-0x25CF */
+static uint16 tab_uni_jisx020817[]={
+0x2223,0x2222, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2225,0x2224, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2227,0x2226, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2221,0x217E,
+ 0, 0, 0,0x217B, 0, 0,0x217D,0x217C
+};
+
+/* page 18 0x25EF-0x25EF */
+static uint16 tab_uni_jisx020818[]={
+0x227E};
+
+/* page 19 0x2605-0x2606 */
+static uint16 tab_uni_jisx020819[]={
+0x217A,0x2179};
+
+/* page 20 0x2640-0x2642 */
+static uint16 tab_uni_jisx020820[]={
+0x216A, 0,0x2169};
+
+/* page 21 0x266A-0x266F */
+static uint16 tab_uni_jisx020821[]={
+0x2276, 0, 0,0x2275, 0,0x2274};
+
+/* page 22 0x3000-0x301C */
+static uint16 tab_uni_jisx020822[]={
+0x2121,0x2122,0x2123,0x2137, 0,0x2139,0x213A,0x213B,
+0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,
+0x215A,0x215B,0x2229,0x222E,0x214C,0x214D, 0, 0,
+ 0, 0, 0, 0,0x2141};
+
+/* page 23 0x3041-0x30FE */
+static uint16 tab_uni_jisx020823[]={
+0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,0x2428,
+0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,0x2430,
+0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,0x2438,
+0x2439,0x243A,0x243B,0x243C,0x243D,0x243E,0x243F,0x2440,
+0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447,0x2448,
+0x2449,0x244A,0x244B,0x244C,0x244D,0x244E,0x244F,0x2450,
+0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457,0x2458,
+0x2459,0x245A,0x245B,0x245C,0x245D,0x245E,0x245F,0x2460,
+0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,0x2468,
+0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,0x2470,
+0x2471,0x2472,0x2473, 0, 0, 0, 0, 0,
+ 0, 0,0x212B,0x212C,0x2135,0x2136, 0, 0,
+0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527,0x2528,
+0x2529,0x252A,0x252B,0x252C,0x252D,0x252E,0x252F,0x2530,
+0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537,0x2538,
+0x2539,0x253A,0x253B,0x253C,0x253D,0x253E,0x253F,0x2540,
+0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547,0x2548,
+0x2549,0x254A,0x254B,0x254C,0x254D,0x254E,0x254F,0x2550,
+0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,0x2558,
+0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,0x255F,0x2560,
+0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,0x2568,
+0x2569,0x256A,0x256B,0x256C,0x256D,0x256E,0x256F,0x2570,
+0x2571,0x2572,0x2573,0x2574,0x2575,0x2576, 0, 0,
+ 0, 0,0x2126,0x213C,0x2133,0x2134};
+
+/* page 24 0x4E00-0x5516 */
+static uint16 tab_uni_jisx020824[]={
+0x306C,0x437A, 0,0x3C37, 0, 0, 0,0x4B7C,
+0x3E66,0x3B30,0x3E65,0x323C, 0,0x4954,0x4D3F, 0,
+0x5022,0x312F, 0, 0,0x336E,0x5023,0x4024,0x5242,
+0x3556,0x4A3A, 0, 0, 0, 0,0x3E67, 0,
+ 0,0x4E3E, 0, 0, 0, 0,0x4A42, 0,
+ 0, 0,0x5024, 0, 0,0x4366, 0, 0,
+ 0,0x5025,0x367A, 0, 0, 0,0x5026, 0,
+0x345D,0x4330, 0,0x3C67,0x5027, 0, 0,0x5028,
+ 0, 0,0x5029,0x4735, 0,0x3557, 0, 0,
+ 0, 0, 0,0x4737, 0,0x4663,0x3843,0x4B33,
+ 0, 0, 0, 0, 0,0x6949,0x502A,0x3E68,
+0x502B,0x3235, 0, 0, 0,0x3665,0x3870,0x4C69,
+ 0, 0,0x5626, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4D70, 0,0x467D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3425, 0,
+0x3535, 0,0x502C, 0, 0,0x502D,0x4E3B, 0,
+0x4D3D,0x4168,0x502F,0x3B76,0x4673, 0,0x5032, 0,
+ 0,0x313E,0x385F, 0,0x385E,0x3066, 0, 0,
+0x4F4B,0x4F4A, 0,0x3A33,0x3021, 0,0x5033,0x5034,
+0x5035,0x4B34,0x5036, 0,0x3872,0x3067,0x4B72, 0,
+0x357C, 0, 0,0x357D,0x357E,0x4462,0x4E3C, 0,
+0x5037, 0, 0,0x5038, 0, 0,0x5039, 0,
+ 0, 0,0x3F4D, 0, 0, 0, 0, 0,
+0x3D3A,0x3F4E,0x503E, 0,0x503C, 0,0x503D,0x3558,
+ 0, 0,0x3A23,0x3270, 0,0x503B,0x503A,0x4A29,
+ 0, 0, 0, 0,0x3B46,0x3B45,0x423E,0x503F,
+0x4955,0x4067, 0, 0, 0,0x2138,0x5040,0x5042,
+ 0, 0, 0,0x4265,0x4E61,0x304A, 0, 0,
+ 0, 0, 0, 0, 0,0x5041,0x323E, 0,
+0x3644, 0,0x4367, 0, 0, 0,0x376F,0x5043,
+ 0, 0, 0,0x4724, 0, 0, 0, 0,
+ 0,0x346B, 0, 0, 0, 0, 0, 0,
+ 0,0x5044,0x304B, 0, 0,0x3860,0x346C,0x497A,
+0x4832,0x3559, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3271, 0,0x5067,0x4541, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x476C,
+0x5046, 0, 0, 0,0x483C, 0,0x4E62, 0,
+0x3F2D, 0,0x3B47, 0,0x3B77,0x3240, 0, 0,
+ 0, 0, 0,0x4451, 0, 0,0x4322,0x504A,
+ 0, 0, 0, 0, 0,0x304C,0x4463,0x3D3B,
+0x3A34,0x4D24, 0,0x424E, 0,0x323F, 0,0x5049,
+ 0,0x4D3E,0x5045,0x5047,0x3A6E,0x5048,0x5524, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5050, 0, 0, 0, 0, 0,0x5053,
+0x5051, 0, 0,0x3242, 0,0x4A3B,0x504B, 0,
+ 0, 0, 0,0x504F,0x3873, 0, 0,0x3B48,
+ 0, 0, 0,0x3426, 0, 0,0x5054, 0,
+0x504C, 0, 0,0x4E63, 0,0x3B78, 0,0x504D,
+ 0,0x5052, 0, 0, 0, 0,0x5055, 0,
+0x504E, 0, 0,0x3621, 0,0x304D, 0, 0,
+0x3622,0x3241, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5525, 0,0x4B79,0x496E,0x3874,
+ 0, 0, 0, 0, 0,0x3F2F,0x4E37, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4A58,
+ 0, 0,0x3738,0x4225,0x3264, 0, 0, 0,
+ 0, 0,0x3D53, 0, 0, 0,0x5059, 0,
+0x505E,0x505C, 0, 0,0x5057, 0, 0,0x422F,
+0x505A, 0,0x505D,0x505B, 0,0x4A5D, 0,0x5058,
+ 0,0x3F2E, 0,0x4B73,0x505F,0x5060, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D24,0x506D,
+ 0, 0, 0,0x4750, 0,0x4936,0x5068, 0,
+0x4A70, 0,0x3236, 0, 0, 0,0x506C, 0,
+ 0, 0, 0, 0, 0,0x5066,0x506F, 0,
+ 0,0x4152, 0,0x3844, 0,0x475C, 0,0x6047,
+ 0,0x506E,0x455D, 0,0x5063, 0,0x3876, 0,
+ 0,0x3875,0x5061, 0, 0, 0, 0,0x3C5A,
+ 0,0x5069, 0,0x4A6F,0x434D,0x5065,0x3771, 0,
+0x5062,0x506A,0x5064,0x4E51,0x506B,0x4F41, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3666, 0,
+ 0,0x3770, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5070, 0, 0, 0,0x5071,
+0x5075,0x304E, 0, 0, 0, 0, 0,0x4A50,
+0x5074, 0, 0, 0, 0,0x5073,0x5077, 0,
+ 0, 0,0x5076, 0,0x4464, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3772, 0, 0,
+ 0, 0, 0, 0,0x5078, 0, 0, 0,
+ 0, 0,0x3C45, 0,0x4226,0x4465,0x3676, 0,
+0x5079, 0, 0, 0, 0,0x3536, 0, 0,
+0x507A, 0, 0, 0, 0,0x507C, 0, 0,
+ 0, 0, 0, 0, 0,0x4B35, 0, 0,
+ 0,0x3766, 0, 0, 0, 0, 0, 0,
+0x3B31,0x4877,0x507B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3A45,0x4D43, 0, 0,
+ 0, 0,0x507E,0x5123,0x507D,0x3A44, 0,0x3D7D,
+ 0, 0, 0, 0, 0, 0,0x3739, 0,
+ 0, 0,0x5124, 0, 0,0x364F, 0, 0,
+ 0,0x5121,0x5122, 0, 0,0x462F, 0,0x417C,
+ 0,0x3623, 0, 0, 0,0x4B4D,0x5125, 0,
+ 0, 0,0x4E3D, 0, 0, 0,0x5126, 0,
+ 0, 0, 0,0x5129, 0,0x5127, 0,0x414E,
+ 0, 0, 0, 0, 0,0x5128,0x512A, 0,
+ 0, 0, 0, 0, 0,0x512C, 0, 0,
+ 0,0x512B, 0,0x4A48, 0, 0, 0, 0,
+0x3537,0x512E,0x512F, 0,0x322F, 0, 0, 0,
+ 0,0x512D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3C74, 0,0x5132,0x5131,0x5130, 0,
+0x5056, 0,0x5133, 0, 0, 0, 0,0x3D7E,
+ 0,0x5134, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D25, 0, 0, 0, 0, 0,
+ 0, 0,0x4C59, 0, 0, 0, 0,0x5136,
+ 0, 0,0x5135,0x5138,0x5137, 0, 0,0x5139,
+0x513A,0x3074, 0,0x3835,0x373B,0x3D3C,0x437B,0x3624,
+0x4068,0x3877, 0,0x396E,0x513C,0x4C48,0x4546, 0,
+0x3B79, 0,0x513B, 0,0x513D, 0, 0, 0,
+ 0, 0,0x455E, 0,0x3375, 0, 0, 0,
+ 0, 0,0x513E, 0, 0,0x467E, 0, 0,
+0x4134,0x5140,0x5141,0x482C,0x3878,0x4F3B,0x5142, 0,
+ 0,0x3626, 0, 0, 0,0x4A3C,0x4236,0x3671,
+0x4535, 0, 0, 0,0x3773, 0, 0, 0,
+0x5143, 0,0x5144, 0, 0,0x4662,0x315F, 0,
+ 0,0x5147,0x3A7D, 0,0x5146,0x3A46, 0,0x5148,
+0x666E,0x5149,0x4B41,0x514A, 0,0x514B,0x514C,0x3E69,
+ 0,0x3C4C, 0, 0, 0, 0, 0, 0,
+0x3427, 0,0x514F, 0,0x514D,0x4C3D,0x514E, 0,
+0x495A,0x5150,0x5151,0x5152,0x455F, 0, 0, 0,
+0x5156,0x5154,0x5155,0x5153,0x3A63,0x5157,0x4C6A,0x4E64,
+ 0, 0, 0, 0, 0,0x5158, 0, 0,
+ 0, 0, 0, 0,0x4028,0x5159,0x3D5A, 0,
+ 0,0x515A, 0,0x437C,0x4E3F,0x4560, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5245, 0,
+ 0, 0, 0,0x515B,0x7425,0x3645, 0, 0,
+0x515C,0x4B5E, 0, 0, 0, 0,0x3D68,0x427C,
+ 0,0x515E,0x4664, 0, 0,0x515F, 0, 0,
+0x5160,0x332E, 0, 0, 0,0x5161,0x3627, 0,
+0x464C,0x317A,0x3D50, 0, 0,0x4821,0x5162, 0,
+0x4561, 0, 0,0x3F4F,0x5163, 0,0x4A2C,0x405A,
+0x3422, 0,0x3429,0x5164, 0, 0,0x5166, 0,
+ 0,0x373A, 0, 0,0x5165, 0, 0,0x4E73,
+ 0, 0, 0, 0, 0,0x3D69, 0, 0,
+ 0, 0, 0, 0,0x483D,0x4A4C, 0,0x5167,
+ 0,0x4D78,0x5168, 0, 0, 0,0x5169, 0,
+0x457E, 0, 0,0x516A, 0, 0,0x4029,0x3A7E,
+0x3774,0x516B,0x3B49,0x396F, 0, 0, 0, 0,
+ 0, 0, 0,0x4466,0x516D, 0, 0,0x4227,
+ 0, 0,0x3A6F,0x516E,0x516F,0x4130, 0,0x516C,
+ 0, 0, 0, 0,0x5171, 0,0x4B36, 0,
+ 0, 0, 0,0x3964, 0, 0,0x5170, 0,
+ 0, 0, 0,0x3775,0x3A5E,0x476D, 0, 0,
+ 0,0x5174,0x5172, 0, 0, 0, 0,0x497B,
+0x3E6A,0x517B,0x3364,0x5175,0x5173,0x414F, 0, 0,
+ 0, 0, 0, 0, 0,0x5177, 0,0x5176,
+ 0, 0, 0,0x3344, 0, 0, 0,0x3760,
+0x517C,0x4E2D, 0, 0, 0,0x5178, 0, 0,
+ 0,0x517D,0x517A, 0,0x5179, 0, 0, 0,
+ 0, 0, 0,0x4E4F, 0, 0, 0,0x3879,
+0x3243, 0, 0,0x4E74, 0, 0, 0, 0,
+ 0,0x3D75,0x4558,0x3965,0x5222,0x5223, 0, 0,
+ 0,0x4E65, 0, 0,0x4F2B,0x5225, 0, 0,
+ 0,0x387A, 0, 0,0x5224, 0,0x332F, 0,
+ 0,0x5226, 0,0x4B56, 0,0x443C, 0,0x4D26,
+ 0,0x4A59, 0, 0, 0,0x5227, 0, 0,
+ 0, 0,0x7055, 0, 0,0x4630, 0,0x5228,
+0x342A,0x4C33, 0, 0, 0,0x3E21,0x5229,0x4A67,
+0x522D, 0,0x402A,0x522A,0x3650, 0,0x522B,0x342B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x372E,0x522E, 0,0x522F, 0, 0,
+0x5230,0x5231,0x3C5B, 0, 0, 0,0x387B,0x4C5E,
+ 0,0x4C68,0x4677, 0, 0,0x4A71,0x5232, 0,
+0x5233, 0, 0, 0, 0,0x5235, 0,0x5237,
+0x5236, 0, 0, 0, 0,0x5238,0x323D,0x4B4C,
+ 0,0x3A7C,0x5239, 0, 0,0x4159, 0, 0,
+0x3E22,0x3629, 0,0x523A, 0, 0, 0, 0,
+ 0, 0,0x485B, 0, 0, 0, 0,0x523B,
+ 0,0x523C, 0,0x523D, 0, 0, 0, 0,
+0x523E,0x4924,0x3668,0x3065, 0, 0, 0,0x463F,
+0x523F,0x3D3D, 0,0x4069, 0,0x5241,0x5240,0x3E23,
+0x3861,0x5243,0x483E, 0, 0,0x5244, 0, 0,
+ 0,0x485C,0x4234,0x426E,0x3628, 0, 0,0x466E,
+0x4331, 0,0x476E, 0,0x4B4E, 0,0x5246, 0,
+0x406A, 0, 0, 0, 0, 0,0x3735, 0,
+ 0,0x5247, 0, 0, 0, 0,0x5248,0x312C,
+0x3075,0x346D, 0,0x4228,0x3551,0x4D71, 0,0x524B,
+0x3237, 0, 0,0x524A, 0, 0, 0,0x362A,
+ 0, 0,0x524C, 0,0x4C71, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x524D, 0,
+0x4E52, 0,0x387C, 0, 0, 0, 0,0x3836,
+0x524E, 0, 0, 0, 0,0x5250,0x524F, 0,
+0x3F5F,0x3139, 0, 0, 0,0x315E,0x5251, 0,
+0x5252, 0, 0,0x3837, 0, 0,0x5253, 0,
+ 0, 0, 0,0x356E, 0, 0, 0, 0,
+ 0, 0,0x3B32,0x5254, 0, 0, 0, 0,
+0x4B74,0x3A35,0x355A,0x4D27,0x4150,0x483F,0x3C7D, 0,
+ 0, 0, 0, 0,0x3D47, 0,0x3C68,0x3C75,
+ 0,0x3D76, 0,0x4840, 0, 0, 0,0x5257,
+ 0,0x3143,0x4151,0x387D,0x3845,0x3667, 0, 0,
+0x525B,0x4321,0x427E,0x362B,0x3E24,0x525C,0x525A,0x3244,
+0x4266,0x3C38,0x3B4B,0x3126, 0, 0,0x3370,0x3966,
+0x3B4A, 0,0x525D, 0, 0, 0, 0, 0,
+ 0,0x525E, 0,0x3549,0x3346, 0, 0, 0,
+0x3967,0x3548,0x445F,0x3125,0x4631,0x4C3E,0x3921,0x4D79,
+0x4547,0x387E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x372F, 0,0x5267, 0,0x3663,
+0x4B4A, 0, 0, 0, 0, 0,0x485D, 0,
+ 0,0x5266, 0,0x345E,0x5261,0x5262,0x5264, 0,
+ 0, 0, 0, 0, 0, 0,0x5265, 0,
+0x355B,0x3F61, 0,0x4A2D,0x5263,0x525F,0x3863, 0,
+0x5260, 0,0x4F24, 0, 0, 0,0x4A72, 0,
+0x4468,0x3862,0x3970, 0, 0, 0,0x5268, 0,
+ 0,0x465D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x526C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3C7E, 0,0x3C76, 0, 0, 0, 0, 0,
+0x526F,0x526D, 0,0x4C23, 0,0x526A,0x5273,0x526E,
+ 0, 0, 0,0x5271,0x3846,0x4C3F, 0, 0,
+0x5272, 0, 0, 0,0x5274, 0,0x5276, 0,
+ 0, 0, 0,0x3A70,0x4F42, 0,0x526B,0x5269,
+0x5275, 0,0x5270, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5278, 0,0x5323,0x527A, 0, 0,
+0x527E, 0, 0,0x5321,0x527B, 0, 0,0x533E,
+ 0, 0,0x3A69,0x3331, 0, 0, 0, 0,
+0x5279, 0, 0, 0,0x5325,0x3076,0x5324, 0,
+0x3025,0x494A,0x5322, 0,0x527C, 0, 0,0x5277,
+0x527D,0x3A48, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5326, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3077,0x532F, 0, 0,0x5327,0x5328, 0,
+0x3E25,0x4B69, 0, 0, 0,0x532D,0x532C, 0,
+ 0, 0,0x452F, 0, 0, 0, 0, 0,
+ 0, 0,0x532E, 0, 0,0x532B, 0, 0,
+ 0, 0, 0, 0,0x3134, 0,0x3A36,0x3F30,
+ 0, 0, 0, 0, 0, 0, 0,0x5329,
+0x4562, 0, 0, 0,0x532A, 0,0x3022};
+
+/* page 25 0x552E-0x5563 */
+static uint16 tab_uni_jisx020825[]={
+0x5334,0x4D23, 0,0x3E27, 0,0x533A, 0, 0,
+ 0, 0,0x5339,0x5330, 0, 0, 0, 0,
+0x4243, 0,0x5331, 0, 0, 0,0x426F,0x5336,
+0x3E26, 0, 0, 0, 0, 0,0x5333, 0,
+ 0,0x4C64, 0, 0, 0,0x373C, 0, 0,
+0x5337,0x5338, 0, 0, 0, 0,0x5335,0x533B,
+ 0, 0, 0, 0, 0,0x5332};
+
+/* page 26 0x557B-0x576A */
+static uint16 tab_uni_jisx020826[]={
+0x5341,0x5346, 0,0x5342, 0,0x533D, 0, 0,
+0x5347,0x4131, 0, 0,0x5349, 0,0x3922,0x533F,
+0x437D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5343,0x533C,0x342D,
+ 0,0x346E,0x3365,0x5344,0x5340, 0, 0, 0,
+ 0, 0, 0, 0,0x3776,0x534A,0x5348,0x4153,
+0x354A,0x362C, 0,0x5345, 0,0x3674, 0, 0,
+ 0, 0, 0,0x3144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x534E,0x534C, 0,0x5427, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5351, 0, 0, 0, 0, 0,0x534B,
+ 0,0x534F, 0, 0,0x534D, 0, 0, 0,
+0x3B4C,0x5350, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5353, 0,0x5358, 0,
+ 0, 0,0x5356,0x5355, 0, 0, 0, 0,
+ 0, 0, 0,0x4332, 0, 0,0x3245, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5352, 0,0x5354,0x3E28,0x3133, 0, 0,
+0x5357, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x325E, 0,
+ 0, 0, 0, 0,0x5362, 0,0x3E7C,0x535E,
+ 0,0x535C, 0,0x535D, 0,0x535F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x313D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4139, 0,0x5359, 0,0x535A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x337A, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5361, 0, 0, 0,0x346F, 0,0x5364,
+0x5360,0x5363, 0, 0, 0, 0, 0, 0,
+ 0,0x4A2E, 0, 0, 0,0x4655, 0,0x4838,
+ 0, 0, 0, 0, 0,0x5366, 0, 0,
+ 0, 0, 0,0x5365,0x3345, 0, 0,0x5367,
+ 0, 0, 0, 0,0x536A, 0, 0, 0,
+ 0,0x5369, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5368, 0,0x4739,
+ 0, 0,0x536B, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x536C, 0, 0, 0, 0,
+ 0,0x536E, 0,0x536D, 0, 0, 0, 0,
+ 0,0x5370, 0, 0, 0,0x5373,0x5371,0x536F,
+0x5372, 0, 0, 0, 0,0x5374, 0, 0,
+ 0, 0, 0,0x5375, 0, 0,0x5376, 0,
+0x5377, 0, 0, 0,0x5378,0x5145, 0,0x3C7C,
+0x3B4D, 0, 0,0x3273, 0,0x3078, 0, 0,
+0x4344, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5379, 0,0x3A24, 0,0x304F,
+0x3F5E, 0, 0, 0, 0, 0,0x537A,0x3847,
+ 0, 0,0x3971, 0,0x537C,0x537B, 0, 0,
+0x4A60,0x537D, 0, 0, 0,0x5421,0x537E, 0,
+0x5422, 0,0x5423, 0,0x3777, 0, 0,0x3160,
+0x5424, 0, 0,0x5426, 0,0x5425, 0, 0,
+ 0,0x5428, 0, 0,0x455A, 0, 0, 0,
+ 0, 0, 0,0x5429,0x3035,0x3A5F, 0, 0,
+ 0, 0,0x373D, 0, 0,0x434F, 0, 0,
+ 0, 0, 0, 0,0x542A,0x542B, 0, 0,
+0x542D, 0, 0, 0, 0,0x542E, 0,0x3A64,
+ 0, 0, 0, 0,0x3651, 0, 0,0x4B37,
+ 0, 0, 0,0x542C,0x542F,0x3A41,0x3923, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5433, 0,
+ 0,0x3A25, 0,0x4333, 0, 0,0x5430,0x445A
+};
+
+/* page 27 0x577F-0x5A9B */
+static uint16 tab_uni_jisx020827[]={
+0x5434, 0, 0,0x3F62, 0, 0, 0, 0,
+ 0,0x5432,0x5435, 0,0x373F, 0, 0, 0,
+ 0, 0, 0, 0,0x5436, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5437, 0,0x3924,0x3340,0x5439, 0, 0,
+ 0, 0, 0,0x543A, 0, 0, 0, 0,
+ 0,0x543B, 0, 0,0x5438, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5431, 0, 0,0x543C, 0, 0,0x543D,
+ 0, 0, 0, 0,0x4B64, 0, 0,0x3E6B,
+ 0, 0, 0,0x543F,0x5440,0x543E, 0,0x5442,
+ 0, 0, 0, 0, 0,0x4738, 0, 0,
+0x3068,0x4956, 0, 0,0x5443, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3E7D, 0, 0,
+0x3C39, 0,0x475D,0x3470, 0,0x3A6B, 0, 0,
+ 0,0x4B59, 0,0x4632, 0, 0,0x3778,0x424F,
+ 0, 0, 0,0x5441,0x5444, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4244, 0,
+ 0, 0,0x5445, 0, 0, 0,0x5446, 0,
+ 0, 0,0x5448, 0, 0,0x4469, 0, 0,
+ 0, 0, 0,0x342E, 0, 0, 0, 0,
+0x7421,0x3161,0x4A73, 0, 0,0x3E6C,0x4548, 0,
+ 0, 0, 0,0x3A66, 0, 0,0x544E, 0,
+ 0,0x4A3D,0x4E5D, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3274,0x544A, 0, 0, 0,
+ 0, 0,0x413A,0x544D, 0,0x4563, 0, 0,
+0x4549,0x4564,0x4839,0x444D, 0, 0, 0,0x3A49,
+ 0, 0, 0,0x5449, 0, 0, 0, 0,
+ 0, 0,0x3176, 0,0x4536, 0, 0, 0,
+ 0,0x544B, 0,0x5447, 0, 0,0x3F50, 0,
+ 0, 0,0x544F, 0, 0, 0, 0,0x3D4E,
+ 0, 0, 0, 0,0x362D, 0,0x5450, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4A68, 0, 0, 0,
+0x417D, 0, 0, 0, 0,0x4446, 0, 0,
+0x5452, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4B4F, 0, 0,0x5453, 0, 0,0x5458,
+ 0, 0, 0, 0,0x4A2F, 0, 0, 0,
+ 0,0x5457,0x5451,0x5454,0x5456, 0, 0,0x3A26,
+ 0, 0,0x4A49, 0, 0, 0,0x5459, 0,
+0x4345, 0, 0,0x3275, 0,0x3E6D, 0, 0,
+ 0, 0,0x545B, 0,0x545A, 0,0x3968, 0,
+0x545C,0x545E,0x545D, 0, 0,0x5460, 0,0x5455,
+0x5462, 0, 0, 0, 0,0x5461,0x545F, 0,
+ 0, 0, 0, 0,0x3B4E,0x3F51, 0,0x4154,
+0x5463,0x403C,0x306D,0x4764, 0, 0, 0, 0,
+0x445B, 0,0x5465,0x5464,0x5466,0x5467,0x5468, 0,
+ 0, 0, 0,0x5469, 0, 0, 0, 0,
+ 0, 0,0x4A51,0x546A, 0, 0, 0, 0,
+0x3246,0x546B, 0, 0, 0, 0,0x4D3C,0x3330,
+ 0,0x5249,0x3D48,0x423F,0x546C,0x4C6B, 0, 0,
+ 0, 0, 0,0x4C34, 0, 0,0x546E, 0,
+0x4267, 0,0x4537,0x4240,0x4957,0x546F,0x5470,0x317B,
+ 0, 0,0x3C3A,0x5471, 0, 0, 0, 0,
+0x3050,0x5472, 0, 0, 0, 0, 0,0x5473,
+ 0, 0, 0, 0, 0,0x3162, 0, 0,
+0x3471,0x4660,0x4A74, 0, 0, 0, 0,0x5477,
+0x4155,0x5476,0x3740, 0, 0,0x4B5B,0x5475, 0,
+0x4565,0x5479, 0,0x5478, 0, 0, 0, 0,
+ 0,0x547B, 0,0x547A, 0, 0,0x317C, 0,
+0x547C,0x3E29,0x547E,0x4325, 0,0x547D, 0,0x4A33,
+ 0, 0, 0, 0,0x3D77,0x455B, 0, 0,
+ 0,0x5521, 0, 0, 0, 0,0x3925, 0,
+ 0, 0,0x5522,0x4721,0x485E,0x4C51, 0, 0,
+ 0, 0, 0,0x4725, 0, 0,0x552B, 0,
+ 0, 0, 0, 0,0x3538, 0, 0,0x4D45,
+ 0, 0,0x4C2F, 0,0x562C, 0,0x5523, 0,
+ 0, 0, 0, 0,0x5526, 0,0x4245, 0,
+ 0,0x4B38, 0, 0, 0,0x454A, 0, 0,
+ 0, 0, 0,0x5527, 0, 0, 0, 0,
+ 0, 0,0x4B65, 0,0x3A4A, 0, 0,0x3E2A,
+ 0, 0, 0, 0, 0, 0, 0,0x5528,
+ 0, 0,0x3B50, 0,0x3B4F, 0, 0, 0,
+ 0,0x3039,0x3848, 0,0x402B,0x3051, 0, 0,
+ 0, 0,0x552C,0x552D, 0,0x552A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3138,0x342F,
+ 0,0x5529, 0,0x4C45,0x4931, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3028,
+ 0, 0, 0, 0,0x3079, 0, 0, 0,
+0x3B51, 0,0x3052, 0,0x3023, 0, 0, 0,
+ 0, 0,0x5532, 0, 0, 0, 0, 0,
+ 0, 0,0x5530, 0, 0, 0, 0, 0,
+ 0,0x4C3C, 0,0x5533, 0,0x5531, 0, 0,
+0x552F,0x3F31, 0, 0, 0, 0,0x552E, 0,
+ 0, 0,0x4A5A, 0, 0, 0, 0, 0,
+0x3864, 0, 0, 0, 0, 0,0x5537,0x5538,
+ 0, 0, 0, 0, 0,0x3E2B, 0, 0,
+ 0,0x5534,0x4F2C, 0, 0, 0, 0,0x474C,
+ 0, 0,0x5536, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3A27, 0, 0, 0, 0,
+ 0, 0, 0,0x5539, 0, 0, 0,0x4958,
+ 0, 0, 0,0x553A, 0,0x5535, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4C3B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x475E, 0, 0, 0, 0,
+ 0, 0, 0,0x553B,0x4932};
+
+/* page 28 0x5ABC-0x5D29 */
+static uint16 tab_uni_jisx020828[]={
+0x553C,0x5540,0x553D, 0, 0,0x3247,0x553F, 0,
+ 0, 0, 0, 0, 0,0x3C3B, 0,0x553E,
+0x3779, 0, 0, 0,0x554C, 0, 0, 0,
+ 0, 0,0x5545,0x5542, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4364, 0,0x5541,
+ 0, 0,0x5543, 0, 0,0x5544, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5546,0x5547,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3472, 0,0x5549,
+0x5548, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x554A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E6E, 0,
+ 0, 0, 0, 0, 0, 0,0x554D, 0,
+0x445C, 0, 0, 0,0x3145, 0,0x554B, 0,
+ 0, 0,0x554E, 0, 0, 0, 0, 0,
+ 0, 0,0x554F, 0,0x5552, 0, 0,0x5550,
+ 0,0x5551, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3B52,0x5553, 0, 0,
+0x3926,0x5554, 0,0x3B7A,0x4238, 0,0x5555,0x5556,
+0x3B5A,0x3927, 0,0x4C52, 0, 0, 0,0x3528,
+0x3849,0x5557,0x3358, 0, 0,0x5558, 0,0x4239,
+ 0, 0, 0, 0,0x5559,0x5623, 0,0x555A,
+ 0,0x555B, 0, 0,0x555C, 0,0x555E, 0,
+ 0, 0, 0, 0,0x555F, 0, 0,0x5560,
+ 0,0x4270, 0,0x3127,0x3C69,0x3042, 0,0x4157,
+0x3430,0x3C35, 0,0x3928, 0, 0, 0, 0,
+ 0,0x4566, 0,0x3D21,0x3431,0x4368,0x446A,0x3038,
+0x3539,0x4A75, 0,0x3C42, 0, 0,0x3552,0x406B,
+0x3C3C,0x4D28,0x5561, 0, 0, 0, 0, 0,
+ 0, 0,0x355C, 0,0x3A4B, 0, 0,0x3332,
+0x3163,0x3E2C,0x3248, 0,0x5562,0x4D46, 0, 0,
+ 0, 0, 0,0x3D49, 0, 0,0x3C64,0x5563,
+0x3473,0x4652,0x4C29,0x5564, 0,0x5565, 0, 0,
+0x4959, 0, 0, 0,0x5567, 0,0x3428,0x3677,
+0x5566, 0, 0, 0, 0, 0, 0,0x3432,
+ 0,0x3F32,0x556B,0x3B21, 0,0x3249,0x556A, 0,
+0x5568,0x556C,0x5569,0x472B,0x5C4D,0x3F33, 0,0x556D,
+ 0, 0,0x4E40, 0,0x556E, 0, 0,0x5570,
+ 0,0x437E,0x556F, 0,0x4023, 0,0x3B7B, 0,
+ 0, 0,0x4250,0x3C77, 0,0x4975,0x406C, 0,
+0x3C4D,0x5571,0x3E2D,0x5572,0x5573,0x3053,0x423A,0x3F52,
+ 0,0x5574,0x4633,0x3E2E, 0,0x3E2F, 0,0x5575,
+ 0, 0,0x406D, 0, 0, 0,0x3E30, 0,
+ 0, 0, 0, 0,0x5576, 0,0x5577, 0,
+0x4C60, 0, 0, 0,0x5578, 0, 0, 0,
+ 0,0x3646, 0, 0, 0,0x3D22, 0, 0,
+ 0, 0, 0, 0,0x5579,0x557A,0x3C5C,0x3F2C,
+0x4674,0x3F54,0x4878,0x4722,0x3649,0x557B, 0, 0,
+ 0,0x356F,0x557C, 0,0x367E, 0,0x464F,0x3230,
+ 0,0x3B53,0x557D,0x5622,0x5621,0x367D, 0,0x557E,
+ 0,0x4538, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4230, 0,0x454B,0x3C48, 0, 0,
+0x4158,0x4D7A, 0, 0, 0, 0, 0, 0,
+0x5624, 0,0x5625,0x4656, 0,0x3B33, 0, 0,
+ 0, 0,0x5627, 0, 0,0x5628, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5629, 0, 0, 0,0x3474,0x562A, 0, 0,
+0x562B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x322C, 0, 0,
+ 0, 0, 0, 0,0x413B,0x3464, 0,0x562D,
+0x4C28, 0, 0, 0, 0,0x4252, 0,0x3359,
+ 0, 0,0x562F,0x5631,0x345F, 0, 0,0x562E,
+0x5630, 0,0x5633, 0, 0, 0, 0, 0,
+ 0,0x5632, 0,0x5634, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5635, 0, 0,
+ 0, 0, 0, 0,0x463D,0x362E, 0, 0,
+ 0, 0, 0, 0,0x3265,0x5636,0x563B, 0,
+ 0,0x5639, 0,0x4A77,0x4A76, 0, 0, 0,
+ 0, 0,0x4567, 0, 0, 0,0x5638,0x3D54,
+ 0,0x5637, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F72, 0, 0, 0,0x563C,
+ 0, 0,0x3A6A, 0, 0,0x5642, 0, 0,
+0x5643,0x563D,0x3333,0x563E,0x5647,0x5646,0x5645,0x5641,
+ 0, 0, 0,0x5640, 0, 0,0x5644, 0,
+ 0, 0, 0, 0, 0,0x4A78};
+
+/* page 29 0x5D4B-0x6BF3 */
+static uint16 tab_uni_jisx020829[]={
+0x564B,0x5648, 0,0x564A, 0,0x4D72, 0,0x5649,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x563F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3F73, 0,
+ 0,0x564C, 0, 0,0x3A37, 0, 0, 0,
+0x564D, 0, 0,0x564E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5651,
+ 0,0x5650, 0, 0,0x564F, 0, 0, 0,
+0x4568,0x563A, 0, 0, 0,0x5657, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5653, 0, 0, 0, 0,0x5652,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5654, 0,0x5655, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5658, 0, 0,0x4E66,
+ 0,0x5659,0x5656, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x565A, 0,
+ 0,0x3460,0x565B, 0, 0, 0, 0,0x565D,
+0x565C, 0, 0,0x565E, 0, 0, 0, 0,
+0x565F, 0,0x406E,0x3D23, 0, 0,0x3D64, 0,
+0x4163, 0,0x3929,0x3A38,0x392A,0x3570, 0, 0,
+0x5660, 0, 0,0x3A39, 0, 0,0x384A,0x5661,
+0x4C26,0x4743,0x5662, 0,0x392B, 0, 0, 0,
+0x342C, 0,0x4327,0x3652, 0, 0, 0,0x3B54,
+0x495B, 0, 0,0x4841, 0, 0, 0, 0,
+0x5663,0x3475, 0, 0, 0, 0,0x5666, 0,
+ 0, 0, 0,0x4421, 0, 0,0x5665,0x5664,
+0x5667, 0,0x446B, 0, 0, 0, 0, 0,
+ 0, 0,0x3F63, 0, 0, 0, 0, 0,
+0x3B55, 0,0x404A, 0,0x4253,0x3522, 0, 0,
+0x4422, 0, 0,0x5668,0x5669,0x3E6F, 0, 0,
+ 0, 0,0x4B39, 0, 0,0x566C, 0, 0,
+0x566B,0x566A,0x497D, 0,0x5673, 0, 0, 0,
+ 0,0x4B5A, 0,0x566D, 0, 0, 0, 0,
+ 0,0x566F,0x4B6B, 0,0x566E, 0, 0, 0,
+ 0, 0, 0, 0,0x5670, 0,0x4828,0x5671,
+0x4A3E,0x5672, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3433,
+0x4A3F,0x472F,0x5674,0x5675, 0,0x392C,0x3434,0x5676,
+0x3838,0x4D44,0x4D29,0x3476,0x5678, 0,0x4423, 0,
+0x392D,0x3E31, 0, 0,0x485F, 0, 0,0x3E32,
+ 0, 0, 0, 0,0x3D78, 0, 0, 0,
+ 0, 0,0x446C,0x4A79,0x4539, 0, 0,0x392E,
+ 0,0x495C, 0, 0, 0,0x5679, 0, 0,
+ 0, 0, 0,0x4559,0x3A42, 0, 0, 0,
+0x384B, 0,0x446D, 0, 0, 0, 0, 0,
+ 0, 0,0x3043,0x3D6E,0x392F,0x4D47, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x567A,0x567B,
+0x4751, 0, 0, 0, 0,0x567C,0x4E77,0x4F2D,
+ 0, 0, 0, 0,0x567E,0x567D, 0, 0,
+0x3347, 0, 0,0x5721, 0, 0, 0,0x5724,
+0x5725, 0,0x5723, 0,0x4940,0x3E33,0x5727,0x5726,
+0x5722, 0, 0, 0, 0,0x5728,0x5729, 0,
+ 0,0x572A, 0, 0, 0,0x572D,0x572B, 0,
+0x572C,0x572E, 0,0x3164,0x446E,0x572F, 0,0x377A,
+0x3276,0x4736, 0,0x5730,0x467B, 0,0x4A5B, 0,
+0x5731,0x4F2E, 0, 0, 0, 0,0x5732,0x4A40,
+0x5735,0x5021,0x5031, 0,0x3C30,0x4675,0x5736, 0,
+0x355D,0x4424,0x307A,0x5737,0x4A26,0x3930, 0, 0,
+0x4350, 0, 0, 0,0x446F, 0, 0, 0,
+ 0, 0,0x4C6F,0x3839,0x384C, 0,0x5738, 0,
+ 0, 0,0x5739, 0,0x573F, 0,0x3C65, 0,
+ 0, 0,0x4425, 0,0x362F,0x573A, 0, 0,
+ 0,0x492B, 0,0x4346, 0, 0,0x573B, 0,
+ 0, 0, 0, 0, 0,0x573C, 0,0x3630,
+ 0,0x573D, 0,0x573E, 0, 0,0x5740, 0,
+0x4576, 0, 0,0x5741,0x5742, 0,0x5743, 0,
+ 0,0x5734,0x5733, 0, 0, 0,0x5744,0x3741,
+ 0, 0, 0,0x4927, 0, 0,0x3A4C,0x4937,
+0x4426,0x494B,0x5745, 0, 0,0x3E34,0x3146, 0,
+0x5746, 0, 0, 0,0x5747, 0,0x4C72, 0,
+ 0,0x4860, 0, 0,0x574A,0x317D,0x402C,0x5749,
+0x5748,0x3742,0x4254, 0,0x574E,0x574C, 0,0x574B,
+0x4E27,0x3865, 0, 0, 0,0x3D79,0x574D,0x454C,
+0x3D3E, 0, 0, 0,0x4640,0x5751,0x5750, 0,
+ 0, 0, 0,0x574F, 0,0x5752,0x3866, 0,
+ 0, 0, 0, 0, 0,0x5753,0x497C,0x3D5B,
+ 0, 0,0x5754,0x4879, 0, 0, 0, 0,
+0x4641,0x4427, 0, 0, 0, 0,0x4530, 0,
+ 0,0x5755,0x352B, 0, 0, 0, 0, 0,
+0x3F34, 0,0x492C, 0, 0, 0, 0, 0,
+ 0,0x3477,0x4726, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5756,0x3B56,0x4B3A,0x4B3B, 0,
+ 0,0x317E,0x575B, 0, 0,0x4369, 0, 0,
+ 0,0x5758, 0, 0, 0, 0, 0, 0,
+0x3277, 0, 0, 0, 0,0x582D,0x575A, 0,
+ 0, 0,0x4730, 0, 0,0x5759, 0, 0,
+0x5757, 0,0x397A, 0,0x575D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5763,0x5769,0x5761, 0,0x455C,
+ 0, 0,0x5766,0x495D, 0, 0,0x5760, 0,
+0x5765,0x4E67,0x3B57, 0, 0,0x4255,0x575E, 0,
+ 0, 0,0x355E,0x5768,0x402D,0x3165,0x5762,0x3278,
+0x5767, 0, 0, 0,0x3631, 0,0x5764, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x576A,
+ 0, 0, 0, 0, 0, 0,0x576C,0x5776,
+0x5774, 0, 0,0x5771, 0, 0, 0,0x5770,
+0x4E78, 0,0x5772, 0, 0,0x3632, 0,0x3931,
+ 0, 0,0x3D7A, 0, 0, 0,0x5779,0x576B,
+ 0, 0, 0, 0,0x576F,0x575F, 0,0x327A,
+0x5773,0x5775,0x4351, 0, 0,0x3A28,0x3238,0x576D,
+0x5778,0x5777,0x3633, 0,0x4229,0x3366, 0, 0,
+ 0, 0,0x3743, 0,0x576E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x577A, 0,
+0x577D,0x5821, 0, 0, 0, 0,0x3C3D, 0,
+0x5827,0x4470,0x577B, 0, 0, 0, 0,0x5825,
+ 0,0x3279, 0,0x5823,0x5824, 0, 0,0x577E,
+0x5822, 0, 0, 0,0x3867,0x4D2A, 0, 0,
+0x3435, 0, 0,0x3159,0x5826, 0,0x473A,0x302D,
+ 0, 0, 0, 0, 0, 0, 0,0x4861,
+0x575C,0x582C,0x5830,0x4C65, 0,0x5829, 0, 0,
+ 0,0x4569,0x582E, 0, 0, 0, 0, 0,
+ 0, 0,0x3E70,0x582F,0x4657, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4F47, 0,
+0x582B, 0, 0, 0, 0,0x5831, 0,0x397B,
+ 0,0x404B, 0, 0,0x3054,0x582A,0x5828, 0,
+0x415A, 0, 0, 0,0x577C,0x3B34, 0, 0,
+ 0, 0, 0, 0, 0,0x4246,0x583D, 0,
+0x415B,0x5838, 0,0x5835,0x5836, 0,0x3C66,0x5839,
+0x583C, 0, 0, 0, 0,0x5837,0x3D25, 0,
+0x583A, 0, 0,0x5834, 0,0x4C7C,0x4C7B, 0,
+ 0, 0,0x583E,0x583F,0x3055, 0, 0, 0,
+ 0, 0,0x5833, 0, 0, 0, 0,0x3672,
+0x3026, 0, 0, 0,0x3436, 0,0x583B, 0,
+ 0, 0, 0, 0,0x5843,0x5842, 0, 0,
+ 0,0x5847, 0, 0, 0, 0, 0, 0,
+ 0,0x5848, 0, 0, 0, 0, 0, 0,
+ 0,0x5846,0x5849,0x5841,0x5845, 0, 0,0x584A,
+ 0,0x584B, 0, 0,0x5840,0x3B7C, 0,0x5844,
+0x4256,0x3932,0x5832,0x3F35, 0, 0, 0, 0,
+0x5858, 0,0x4A69, 0, 0,0x584E,0x584F,0x5850,
+ 0, 0,0x5857, 0,0x5856, 0, 0,0x4B7D,
+0x3437, 0,0x5854, 0,0x3745,0x3334, 0, 0,
+0x5851, 0, 0,0x4E38,0x5853,0x3056,0x5855, 0,
+0x584C,0x5852,0x5859,0x3744,0x584D, 0, 0, 0,
+ 0, 0, 0,0x4D5D, 0, 0, 0,0x4D2B,
+ 0, 0, 0, 0,0x585C, 0, 0,0x5860,
+ 0, 0, 0,0x417E, 0,0x4E79,0x5861, 0,
+ 0,0x585E, 0,0x585B, 0, 0,0x585A,0x585F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4A30, 0, 0,0x4634, 0,0x3746, 0,
+0x5862,0x585D, 0,0x5863, 0, 0, 0,0x377B,
+ 0, 0, 0,0x3231, 0, 0, 0,0x586B,
+ 0, 0, 0,0x3438, 0, 0, 0, 0,
+0x5869, 0, 0,0x586A,0x3A29,0x5868,0x5866,0x5865,
+0x586C,0x5864,0x586E, 0, 0,0x327B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5870, 0, 0,0x586F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4428,
+ 0,0x5873, 0,0x5871,0x5867,0x377C, 0,0x5872,
+ 0,0x5876,0x5875,0x5877,0x5874,0x5878, 0, 0,
+ 0, 0, 0, 0, 0,0x5879,0x587A,0x4A6A,
+ 0,0x587C,0x587B,0x3D3F, 0,0x402E,0x3266,0x327C,
+ 0,0x587D, 0,0x303F, 0, 0, 0,0x404C,
+0x587E, 0,0x6C43,0x5921,0x3761, 0,0x5922, 0,
+ 0, 0, 0,0x406F, 0, 0, 0,0x5923,
+ 0, 0, 0,0x5924,0x353A,0x5925, 0,0x5926,
+0x5927,0x4257, 0, 0, 0,0x384D, 0, 0,
+0x4C61, 0, 0, 0,0x4B3C,0x3D6A,0x5928, 0,
+ 0, 0, 0, 0,0x4070,0x6E3D,0x4862, 0,
+0x3C6A, 0,0x3A4D,0x5929, 0, 0, 0, 0,
+0x4247, 0,0x4A27, 0, 0,0x4271, 0, 0,
+0x592C, 0, 0,0x592A, 0,0x592D, 0, 0,
+0x592B, 0, 0, 0, 0,0x592E, 0, 0,
+ 0, 0, 0,0x4A31, 0, 0,0x3037, 0,
+ 0, 0, 0,0x495E, 0, 0,0x4863, 0,
+ 0,0x592F, 0,0x5932,0x3E35,0x353B, 0,0x5930,
+0x5937,0x3E36, 0, 0, 0, 0,0x5931,0x4744,
+ 0, 0, 0, 0, 0, 0,0x4D5E,0x5933,
+0x5934,0x5938,0x456A,0x5935,0x3933,0x405E, 0, 0,
+0x5946,0x4834, 0,0x4272, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4864,0x5A2D, 0, 0, 0, 0,0x4A7A, 0,
+ 0, 0,0x4471, 0, 0, 0,0x4B75, 0,
+0x593B,0x3221,0x436A, 0, 0, 0, 0,0x5944,
+ 0, 0,0x4334,0x593E,0x5945,0x5940,0x5947,0x5943,
+ 0,0x5942,0x476F, 0,0x593C,0x327D,0x593A,0x3571,
+0x4273,0x5936, 0, 0,0x5939,0x3934,0x405B, 0,
+0x3E37,0x5941,0x4752, 0, 0,0x3572,0x3348, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3367,0x3F21,0x5949,0x594E, 0,0x594A, 0,
+0x377D, 0,0x594F,0x3B22,0x3969, 0, 0, 0,
+ 0, 0, 0,0x3D26,0x593D, 0,0x3B7D,0x594C,
+ 0, 0, 0, 0,0x3B58,0x594D,0x3044, 0,
+ 0,0x5948, 0, 0, 0, 0,0x4429, 0,
+ 0, 0, 0, 0, 0, 0,0x3573, 0,
+ 0, 0, 0, 0,0x3634, 0, 0, 0,
+ 0, 0, 0, 0,0x594B,0x3027, 0, 0,
+0x3A43, 0, 0, 0,0x3F36, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4472,
+ 0, 0,0x4854,0x5951,0x415E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x422A, 0,
+ 0,0x3B2B,0x5952, 0,0x5954,0x5950, 0, 0,
+ 0, 0,0x4A61, 0,0x443D, 0, 0, 0,
+ 0,0x415C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4A7B,0x3C4E,0x5960, 0,
+0x595F, 0, 0,0x3F78, 0, 0, 0,0x377E,
+ 0, 0, 0,0x5959,0x3E39, 0, 0,0x4668,
+0x4731, 0, 0, 0, 0,0x5957, 0, 0,
+0x415D, 0, 0, 0, 0,0x3C78,0x595C, 0,
+ 0,0x3E38, 0,0x5956,0x595B, 0, 0,0x4753,
+ 0, 0, 0,0x5955, 0,0x3721, 0, 0,
+0x335D, 0, 0, 0,0x595D,0x4E2B,0x3A4E,0x4335,
+0x595A, 0,0x405C, 0,0x3935,0x3F64,0x3166,0x413C,
+0x5958,0x3545, 0, 0, 0, 0, 0,0x3747,
+ 0,0x444F,0x595E, 0, 0, 0, 0, 0,
+0x415F, 0, 0,0x5961, 0,0x5963, 0, 0,
+0x4237,0x5969, 0,0x5964, 0, 0,0x5966, 0,
+ 0, 0, 0, 0,0x4941,0x4473, 0,0x5967,
+ 0, 0, 0,0x4D2C, 0, 0, 0,0x4D48,
+0x3439, 0, 0, 0, 0, 0,0x302E, 0,
+0x5965, 0, 0, 0, 0, 0,0x5962, 0,
+ 0, 0, 0,0x3478, 0, 0, 0, 0,
+ 0,0x3167, 0,0x5968, 0, 0, 0,0x4D49,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x596C, 0, 0, 0, 0,
+ 0, 0,0x423B, 0,0x5973, 0, 0, 0,
+0x596D, 0, 0,0x596A,0x5971, 0, 0, 0,
+ 0,0x5953, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x596E, 0,0x5972, 0, 0,
+ 0,0x4842,0x456B, 0, 0, 0, 0, 0,
+ 0,0x596B, 0,0x596F, 0, 0, 0,0x3748,
+ 0, 0, 0,0x3A71, 0, 0, 0,0x405D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5977, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4526, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5974, 0,0x4B60, 0,
+ 0, 0, 0, 0,0x5975, 0, 0, 0,
+ 0, 0, 0,0x5976, 0,0x4C4E, 0,0x4022,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3762, 0, 0, 0, 0,0x597D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3B35,
+0x597A, 0,0x5979, 0, 0, 0, 0,0x4732,
+ 0, 0, 0,0x4635, 0, 0, 0, 0,
+ 0,0x4531,0x597B, 0, 0, 0,0x597C, 0,
+0x496F, 0,0x4745,0x3B23, 0,0x4071, 0,0x4B50,
+ 0, 0, 0, 0, 0, 0,0x3349, 0,
+0x5A25,0x597E, 0, 0, 0, 0,0x4D4A,0x5A27,
+ 0, 0,0x5A23, 0,0x5A24, 0, 0, 0,
+ 0, 0,0x4160, 0, 0, 0, 0,0x5A22,
+ 0,0x593F, 0, 0, 0,0x5A26, 0,0x5A21,
+ 0, 0, 0, 0, 0,0x5A2B,0x5A2C,0x4527,
+0x5A2E, 0, 0,0x3B24,0x5A29, 0, 0, 0,
+ 0,0x353C, 0, 0,0x5A2F, 0,0x5A28,0x5A33,
+ 0,0x5A32, 0,0x5A31, 0, 0, 0,0x5A34,
+ 0, 0,0x5A36,0x3E71, 0,0x5A35, 0, 0,
+ 0, 0,0x5A39, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5A37, 0, 0,
+ 0,0x5A38,0x5970, 0, 0, 0, 0, 0,
+0x5A3B,0x5A3A, 0, 0, 0, 0, 0,0x5978,
+0x5A3C,0x5A30, 0, 0,0x3B59, 0, 0, 0,
+ 0,0x5A3D,0x5A3E,0x5A40,0x5A3F,0x5A41,0x327E, 0,
+0x3936, 0, 0,0x4A7C,0x402F, 0, 0, 0,
+ 0, 0,0x384E, 0, 0,0x5A43, 0, 0,
+ 0, 0,0x5A46, 0,0x4952, 0,0x355F, 0,
+ 0, 0,0x5A45,0x5A44,0x4754,0x5A47,0x3635, 0,
+ 0, 0,0x5A49,0x5A48, 0, 0, 0,0x343A,
+0x3B36, 0, 0,0x4658, 0, 0, 0, 0,
+ 0,0x3749, 0, 0, 0,0x3F74, 0,0x5A4A,
+ 0,0x4030,0x4528, 0,0x495F,0x5A4B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5A4C,
+0x5A4D, 0, 0, 0,0x4A38,0x555D,0x4046, 0,
+ 0,0x494C, 0,0x3A58, 0,0x4865,0x4843, 0,
+ 0, 0, 0, 0,0x454D, 0,0x4E41, 0,
+0x5A4F,0x3C50, 0, 0,0x5A50, 0,0x3036, 0,
+ 0,0x3654,0x404D, 0,0x4960, 0, 0, 0,
+0x5A51,0x3B42,0x4347, 0,0x3B5B,0x3F37, 0, 0,
+ 0, 0, 0, 0,0x5A52, 0,0x4A7D, 0,
+ 0,0x3177,0x3B5C, 0, 0, 0,0x5A55, 0,
+0x5A53,0x5A56,0x4E39,0x5A54, 0, 0, 0, 0,
+0x407B,0x5A57, 0, 0,0x4232, 0, 0,0x5A58,
+ 0, 0, 0, 0,0x347A, 0,0x5A5A, 0,
+0x5A59, 0, 0, 0, 0,0x5A5B,0x5A5C,0x347B,
+ 0, 0,0x467C,0x4336,0x356C,0x3B5D,0x4161, 0,
+ 0,0x3D5C,0x3030, 0, 0, 0,0x5A5D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3222,
+0x5A61, 0, 0, 0, 0, 0, 0,0x3937,
+0x5A60, 0, 0,0x3A2B,0x3E3A, 0, 0,0x5A5F,
+ 0,0x3E3B, 0,0x4C40,0x3A2A, 0, 0, 0,
+0x3057,0x404E, 0, 0, 0, 0, 0, 0,
+ 0,0x5A66, 0, 0,0x4031,0x3147, 0, 0,
+ 0, 0,0x3D55, 0,0x4B66,0x3A72, 0, 0,
+ 0, 0,0x3E3C, 0,0x4027, 0, 0, 0,
+ 0,0x5A65,0x5A63,0x5A64, 0, 0, 0, 0,
+ 0,0x436B, 0, 0,0x5B26, 0,0x5A6A,0x3B7E,
+0x3938,0x5A68, 0, 0, 0, 0,0x5A69, 0,
+0x3F38, 0, 0, 0,0x5A67, 0, 0,0x3B2F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5A6C,0x5A6B,0x5A70, 0, 0,0x5A71,
+ 0,0x5A6D, 0,0x3322,0x5A6E,0x5A6F,0x4855, 0,
+ 0, 0, 0,0x4961,0x374A,0x5A72, 0, 0,
+ 0,0x4032, 0,0x3E3D, 0, 0, 0,0x4352,
+ 0, 0, 0, 0, 0, 0,0x3647, 0,
+0x5A73,0x5A77, 0, 0,0x324B,0x5A74,0x5A76, 0,
+ 0, 0, 0,0x5A75, 0, 0,0x3D6B, 0,
+ 0, 0, 0,0x4348,0x3045,0x5A78, 0, 0,
+ 0, 0,0x5A79, 0, 0, 0, 0,0x442A,
+ 0, 0, 0,0x4E71, 0, 0, 0, 0,
+0x3B43, 0, 0,0x4A6B, 0, 0, 0, 0,
+ 0,0x4B3D, 0, 0, 0,0x5B22,0x5A7B, 0,
+ 0,0x5A7E, 0,0x5A7D, 0, 0,0x5A7A, 0,
+ 0,0x5B21, 0, 0,0x465E, 0,0x5A7C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5B23, 0, 0,0x3D6C,0x5B24,
+ 0,0x4D4B,0x4778, 0, 0,0x5B25, 0, 0,
+ 0, 0, 0,0x5B27, 0, 0,0x5B28, 0,
+ 0, 0, 0, 0, 0,0x5B29, 0,0x364A,
+0x3148,0x3939,0x5B2A, 0,0x5B2B,0x3D71,0x4162, 0,
+ 0,0x5258,0x413E,0x413D,0x4258,0x3A47, 0, 0,
+0x5072, 0, 0, 0, 0,0x376E,0x4D2D, 0,
+0x4A7E, 0,0x497E, 0,0x5B2C, 0, 0, 0,
+ 0,0x3A73,0x443F,0x5B2D,0x4F2F, 0, 0, 0,
+0x4B3E, 0,0x442B,0x5B2E,0x347C, 0, 0, 0,
+ 0, 0, 0,0x5B2F,0x5B30,0x4C5A, 0,0x4C24,
+0x4B76,0x4B5C,0x3B25,0x5B32, 0, 0,0x3C6B, 0,
+ 0,0x4B51, 0,0x5B34,0x5B37,0x5B36, 0,0x3479,
+ 0, 0,0x3560, 0,0x5B33, 0,0x5B35, 0,
+ 0, 0, 0,0x5B38, 0, 0,0x3F79, 0,
+ 0, 0, 0,0x4D7B,0x3049,0x3A60,0x423C, 0,
+0x3C5D, 0, 0,0x3E73, 0, 0,0x5B3B, 0,
+ 0,0x454E, 0,0x5B39,0x422B,0x5B3A,0x3E72,0x4C5D,
+0x5B3C,0x5B3D,0x4D68, 0, 0, 0, 0,0x5B42,
+ 0, 0,0x393A, 0,0x4755,0x5B3F,0x456C,0x5A5E,
+0x5A62, 0,0x354F, 0,0x4747, 0, 0, 0,
+ 0,0x5B41, 0,0x3E3E,0x4844, 0, 0, 0,
+ 0, 0,0x5B47, 0,0x487A, 0,0x5B3E, 0,
+0x5B44,0x5B43, 0, 0, 0,0x404F, 0, 0,
+ 0, 0,0x4B6D, 0,0x4E53, 0, 0,0x4B67,
+ 0,0x324C,0x3B5E, 0, 0,0x4F48,0x5B46,0x3F75,
+ 0, 0, 0,0x5B45, 0, 0,0x5B40, 0,
+ 0, 0, 0, 0,0x384F, 0, 0, 0,
+0x5B4C,0x5B4A, 0,0x324D,0x5B48,0x5B4E,0x5B54, 0,
+ 0, 0, 0, 0, 0, 0,0x4248, 0,
+ 0,0x4A41, 0,0x5B56, 0, 0, 0,0x4922,
+ 0, 0, 0,0x5B55,0x4770,0x4B3F,0x343B, 0,
+0x4077,0x3D40, 0, 0, 0,0x4453, 0,0x4D2E,
+ 0, 0,0x5B51,0x5B50, 0, 0, 0,0x5B52,
+ 0,0x5B4F, 0, 0,0x5B57, 0,0x5B4D, 0,
+ 0,0x5B4B, 0,0x5B53,0x5B49, 0,0x436C, 0,
+0x4C78,0x3C46,0x3A74, 0, 0, 0, 0, 0,
+0x3A3A, 0, 0,0x4B6F,0x3341, 0, 0,0x444E,
+0x464A,0x3149, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4072, 0, 0,0x4034,0x372A, 0, 0, 0,
+ 0, 0, 0,0x5B59, 0, 0,0x393B,0x337C,
+ 0, 0, 0, 0, 0, 0,0x5B5B,0x3374,
+0x5B61, 0, 0, 0, 0, 0, 0,0x5B5E,
+ 0,0x4073, 0, 0, 0,0x334B,0x3A2C, 0,
+ 0,0x334A,0x3A4F, 0, 0,0x5B5C,0x3765,0x374B,
+0x456D, 0, 0,0x5B5A, 0,0x3046, 0, 0,
+ 0, 0,0x5B5D,0x5B5F, 0,0x364D,0x372C, 0,
+0x343C,0x354B, 0, 0, 0, 0,0x5B62, 0,
+ 0,0x3A79,0x4B71, 0,0x3B37, 0, 0, 0,
+0x5B63, 0, 0, 0,0x4930, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B6F, 0,0x3233,0x5B64, 0, 0, 0,
+ 0, 0, 0,0x5B75,0x5B65, 0,0x4E42, 0,
+0x5B6C, 0,0x475F, 0, 0, 0, 0, 0,
+ 0, 0,0x5B74, 0,0x5B67, 0, 0, 0,
+0x3034,0x5B69, 0, 0,0x393C, 0, 0, 0,
+0x5B6B, 0,0x5B6A, 0,0x5B66,0x5B71, 0,0x3E3F,
+ 0, 0, 0,0x546D,0x3868,0x4D7C, 0, 0,
+ 0, 0,0x5B68, 0,0x4474,0x3323,0x3A2D, 0,
+0x5B60, 0,0x5B70,0x3361, 0, 0,0x5B6E,0x5B72,
+ 0,0x456E, 0, 0, 0, 0, 0, 0,
+ 0,0x347E, 0,0x5C32, 0, 0,0x4C49,0x5B77,
+0x347D, 0,0x5B7E, 0, 0, 0, 0,0x4B40,
+ 0,0x5C21,0x5C23, 0,0x5C27,0x5B79, 0,0x432A,
+ 0, 0, 0, 0,0x456F,0x5C2B,0x5B7C, 0,
+0x5C28, 0, 0, 0,0x5C22, 0, 0, 0,
+ 0, 0, 0,0x3F39,0x5C2C, 0, 0,0x4033,
+ 0, 0, 0, 0, 0, 0,0x5C2A,0x343D,
+ 0, 0, 0, 0, 0,0x4F50,0x5B76, 0,
+ 0,0x5C26,0x3058, 0, 0,0x5B78, 0, 0,
+0x4C3A,0x5B7D,0x3F22,0x4447,0x5B73, 0, 0,0x5C25,
+ 0, 0, 0, 0, 0, 0,0x3F7A,0x5C2F,
+0x3371,0x3821, 0, 0, 0, 0,0x5C31,0x5B7A,
+0x5C30, 0,0x5C29,0x5B7B, 0,0x5C2D, 0,0x5C2E,
+ 0, 0, 0, 0, 0,0x5C3F, 0, 0,
+ 0,0x464E, 0,0x5C24, 0, 0,0x5C3B, 0,
+ 0, 0,0x5C3D, 0,0x4458, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4D4C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4976,0x5C38,0x424A, 0, 0, 0,0x5C3E,0x413F,
+ 0,0x5C35,0x5C42,0x5C41, 0,0x466F,0x5C40,0x466A,
+ 0, 0, 0, 0, 0, 0, 0,0x5C44,
+0x5C37, 0,0x3648,0x5C3A,0x3D5D, 0, 0, 0,
+0x4760,0x5C3C,0x364B, 0,0x5C34,0x5C36,0x5C33, 0,
+ 0,0x4F30,0x335A,0x5C39, 0, 0,0x5C43,0x3335,
+ 0, 0, 0, 0, 0, 0, 0,0x3A67,
+ 0, 0, 0,0x315D, 0, 0,0x5C54, 0,
+ 0,0x4F31,0x5C57, 0, 0, 0, 0, 0,
+0x3F3A,0x5C56, 0, 0, 0,0x5C55, 0, 0,
+ 0, 0, 0, 0,0x5C52, 0, 0, 0,
+ 0, 0, 0,0x5C46, 0, 0,0x5C63,0x5C45,
+ 0,0x5C58, 0, 0, 0, 0, 0, 0,
+0x5C50, 0, 0,0x5C4B,0x5C48, 0,0x5C49, 0,
+0x5C51, 0, 0, 0,0x7422, 0, 0,0x5C4E,
+0x393D,0x4448,0x4164,0x5C4C, 0,0x5C47, 0, 0,
+0x5C4A, 0, 0, 0, 0,0x4D4D,0x4B6A, 0,
+ 0, 0,0x5C4F,0x5C59, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5C61,0x5C5A, 0, 0,
+0x5C67, 0,0x5C65, 0, 0, 0, 0,0x5C60,
+ 0, 0, 0, 0, 0, 0,0x5C5F, 0,
+0x4450, 0,0x4165, 0,0x5C5D, 0, 0,0x5C5B,
+ 0, 0,0x5C62, 0, 0, 0, 0,0x5C68,
+0x4875,0x5C6E, 0, 0, 0, 0, 0,0x5C69,
+0x5C6C,0x5C66, 0, 0,0x4374, 0,0x4938, 0,
+0x5C5C, 0, 0,0x5C64,0x3E40, 0,0x4C4F,0x5C78,
+0x5C6B, 0, 0, 0, 0, 0,0x3822,0x3223,
+0x335F, 0, 0,0x5C53, 0, 0, 0, 0,
+ 0, 0,0x3E41,0x5C70, 0,0x5C77,0x3C79,0x3372,
+ 0, 0,0x432E, 0, 0, 0, 0, 0,
+ 0,0x5C6D, 0, 0,0x5C72,0x5C76, 0, 0,
+0x3636, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x354C,0x5C74, 0,
+ 0, 0, 0, 0,0x3521, 0,0x464B,0x5C73,
+ 0, 0, 0,0x5C75, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5C6F,
+ 0, 0, 0, 0, 0,0x5C71, 0, 0,
+ 0, 0, 0, 0,0x3360,0x4349, 0, 0,
+ 0,0x5C7C, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C7A,0x3869, 0,0x5C79, 0, 0,
+ 0, 0, 0, 0,0x5D21, 0, 0, 0,
+ 0,0x5B58, 0, 0, 0,0x5C7B, 0,0x5C7D,
+0x5C7E, 0, 0, 0, 0, 0, 0,0x5D2C,
+ 0,0x5D28, 0,0x5B6D, 0, 0, 0, 0,
+0x5D27, 0, 0, 0, 0,0x5D26, 0, 0,
+0x5D23, 0, 0, 0, 0, 0,0x5C6A,0x5D25,
+0x5D24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5D2A, 0,
+0x4F26, 0, 0, 0, 0, 0, 0,0x5D2D,
+0x367B, 0, 0,0x5D29,0x5D2B, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4827, 0,0x5D2E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5D32,
+0x5D2F, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4D73,0x5D30, 0, 0, 0, 0,0x5C5E,
+ 0, 0, 0, 0, 0, 0, 0,0x5D33,
+ 0, 0, 0,0x5D34, 0, 0, 0, 0,
+ 0, 0,0x3135, 0,0x5D36,0x3767,0x3C21, 0,
+0x3655, 0, 0, 0,0x3224, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4D5F,
+ 0, 0, 0, 0,0x5D38,0x5D37,0x5D3A,0x353D,
+ 0, 0,0x3656,0x343E, 0, 0, 0, 0,
+0x5D3D, 0, 0, 0,0x5D3C, 0,0x5D3E, 0,
+ 0,0x324E, 0,0x4337, 0,0x5D3F, 0, 0,
+0x343F,0x5D41, 0, 0, 0, 0,0x5D40, 0,
+0x5D42, 0, 0, 0,0x5D43, 0,0x5D44,0x3B5F,
+0x4035,0x3A21, 0,0x4970, 0, 0,0x4A62,0x4F44,
+ 0, 0, 0, 0,0x3B75, 0, 0, 0,
+0x3A50,0x4E72, 0, 0, 0,0x5D45,0x5D46, 0,
+0x3B60, 0, 0, 0,0x5D47,0x5D48, 0, 0,
+0x5D4A,0x5D49, 0,0x4B58, 0, 0,0x3D5E,0x3C6C,
+0x3B44, 0,0x5D4B, 0, 0, 0, 0, 0,
+ 0, 0,0x5D4D,0x3F23, 0,0x5D4C, 0, 0,
+ 0, 0, 0,0x5D4E, 0, 0, 0, 0,
+ 0,0x5D4F, 0, 0, 0, 0, 0,0x5D50,
+0x5D51, 0, 0, 0,0x5D52, 0,0x5D54,0x5D53,
+0x5D55,0x3225,0x434A, 0,0x5D56, 0, 0,0x3B26,
+0x334C,0x5D57, 0, 0,0x4542,0x544C, 0, 0,
+ 0, 0,0x3523,0x5D58, 0, 0, 0, 0,
+0x5D59, 0,0x4A6C,0x4B68, 0, 0, 0,0x4647,
+0x5D5A,0x4866, 0, 0, 0,0x487B, 0, 0,
+0x4C53, 0, 0, 0,0x5D5B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5D5D,0x5D5C, 0, 0,0x5D5F, 0, 0, 0,
+0x5D5E};
+
+/* page 30 0x6C08-0x6CF3 */
+static uint16 tab_uni_jisx020830[]={
+0x5D61, 0, 0, 0, 0, 0, 0,0x3B61,
+ 0,0x4C31, 0,0x5D62,0x5D63, 0, 0,0x3524,
+ 0, 0, 0,0x5D64, 0, 0, 0, 0,
+ 0, 0, 0,0x5D66,0x5D65, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3F65, 0, 0,0x4939,
+0x314A, 0, 0, 0, 0, 0,0x4845, 0,
+0x4475,0x3D41,0x3561, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4846, 0,
+0x3C2E, 0, 0, 0, 0,0x5D68, 0,0x3440,
+ 0, 0,0x3178, 0, 0,0x4672,0x5D67,0x393E,
+0x4353, 0,0x5D69, 0, 0, 0, 0, 0,
+0x5D71, 0,0x5D6A, 0, 0, 0, 0, 0,
+0x4241, 0,0x3562,0x5D72, 0, 0, 0, 0,
+ 0, 0,0x3768, 0, 0,0x3525,0x5D70, 0,
+ 0,0x5D6E,0x5D6B,0x4D60, 0, 0, 0, 0,
+0x4440, 0, 0, 0,0x4659,0x5D6C, 0, 0,
+0x5D74, 0,0x5D73,0x3723, 0, 0,0x322D, 0,
+ 0,0x3A3B,0x5D6D,0x5D6F, 0, 0, 0, 0,
+ 0,0x4B57,0x4274, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4B77, 0, 0,0x5D7C, 0,
+ 0,0x5D7D, 0,0x324F, 0, 0, 0, 0,
+0x4A28,0x4C7D,0x5E21,0x3C23,0x3E42,0x5D78,0x5D7E,0x3168,
+ 0,0x3637, 0, 0,0x5D75,0x5D7A, 0, 0,
+ 0,0x4074,0x4771, 0,0x4867, 0, 0, 0,
+ 0, 0, 0,0x5D77, 0,0x4B21, 0,0x5D79,
+ 0,0x5E24, 0,0x5E22, 0,0x5D7B, 0, 0,
+ 0,0x4B22,0x4748,0x3563, 0,0x4525, 0, 0,
+0x436D, 0,0x5E25, 0, 0, 0, 0,0x5E23,
+0x4259,0x5D76, 0,0x314B};
+
+/* page 31 0x6D0B-0x7409 */
+static uint16 tab_uni_jisx020831[]={
+0x4D4E,0x5E30, 0, 0, 0, 0, 0,0x5E2F,
+ 0, 0, 0, 0,0x4076, 0,0x5E2C, 0,
+0x4D6C, 0, 0,0x4636,0x5E26, 0, 0, 0,
+ 0, 0,0x4445, 0, 0, 0,0x314C,0x393F,
+0x5E29, 0, 0, 0, 0, 0, 0,0x3D27,
+0x5E2E, 0,0x5E2D,0x5E28, 0,0x5E2B, 0, 0,
+0x3368, 0,0x5E2A,0x4749, 0, 0,0x4E2E, 0,
+ 0,0x3E74,0x4075, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5E36,0x5E34,
+ 0,0x494D, 0, 0, 0, 0, 0, 0,
+0x5E31,0x5E33, 0,0x313A, 0, 0,0x3940,0x4F32,
+ 0,0x333D, 0,0x4962, 0, 0, 0, 0,
+ 0,0x4D61, 0, 0,0x3324,0x3F3B,0x5E35, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5E3A, 0, 0,0x3E43, 0, 0,
+ 0,0x4D30, 0,0x5E37, 0, 0, 0, 0,
+0x5E32, 0,0x5E38, 0, 0, 0,0x4E5E, 0,
+0x4573,0x4642, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3336, 0, 0,0x3155,
+ 0, 0,0x5E3E, 0, 0,0x5E41, 0, 0,
+ 0,0x4E43, 0, 0, 0,0x4D64, 0, 0,
+ 0, 0,0x5E48,0x5E42,0x5E3F, 0, 0, 0,
+0x4E54,0x5E45, 0, 0, 0, 0,0x3D4A,0x5E47,
+ 0, 0,0x5E4C, 0, 0,0x4571,0x5E4A, 0,
+ 0, 0, 0,0x5E44, 0, 0,0x4338, 0,
+ 0,0x5E4B, 0,0x5E40, 0,0x5E46, 0,0x5E4D,
+0x307C,0x5E43, 0,0x5E4E, 0, 0,0x3F3C, 0,
+0x3D5F, 0,0x4A25, 0,0x3A2E, 0,0x5E3B,0x5E49,
+0x453A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4036, 0,0x3369,0x3A51,0x3E44,0x5E3D,
+0x3D42, 0, 0, 0, 0, 0, 0, 0,
+0x374C, 0,0x5E3C, 0, 0, 0,0x5E52,0x3D6D,
+0x383A, 0,0x5E61, 0,0x5E5B,0x3574,0x454F, 0,
+0x5E56,0x5E5F,0x302F,0x3132, 0, 0,0x3239, 0,
+0x5E58,0x422C,0x5E4F,0x5E51,0x3941, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5E62, 0,0x5E5D,
+ 0, 0, 0,0x5E55, 0, 0, 0, 0,
+0x5E5C, 0, 0, 0, 0, 0, 0,0x4C2B,
+ 0, 0,0x5E5A,0x5E5E, 0, 0, 0, 0,
+ 0, 0, 0,0x3850, 0,0x3E45, 0, 0,
+0x4339, 0, 0, 0,0x5E54, 0, 0, 0,
+ 0, 0, 0, 0,0x4D2F, 0, 0, 0,
+0x5E57, 0, 0,0x5E50,0x4572, 0, 0,0x5E53,
+ 0, 0, 0,0x5E59, 0, 0, 0, 0,
+ 0, 0, 0,0x4F51,0x3C3E,0x4B7E, 0,0x5E63,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x482E, 0, 0,0x5E6F,0x383B, 0, 0,
+ 0, 0, 0,0x3D60, 0,0x5E65, 0, 0,
+ 0,0x4E2F,0x3942, 0,0x5E72, 0, 0,0x306E,
+ 0, 0,0x5E70, 0, 0, 0, 0,0x5E64,
+ 0, 0, 0, 0,0x5E6A, 0, 0,0x5E6C,
+ 0, 0, 0,0x4D4F,0x5E67, 0, 0,0x452E,
+ 0, 0,0x5E69, 0, 0, 0, 0,0x5E71,
+ 0,0x5E6B,0x4C47, 0, 0, 0,0x5E66, 0,
+0x3C22,0x5E7E, 0, 0, 0, 0,0x336A, 0,
+0x5E68,0x5E6D,0x5E6E, 0, 0, 0, 0, 0,
+ 0, 0,0x426C,0x425A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E76, 0, 0,0x5E7C, 0, 0,0x5E7A,
+ 0,0x4529, 0, 0,0x5F23,0x5E77, 0, 0,
+ 0, 0, 0,0x5E78,0x5E60, 0,0x3579,0x493A,
+ 0, 0, 0,0x3C3F, 0, 0,0x3977, 0,
+ 0, 0, 0, 0,0x4F33, 0,0x5E74, 0,
+0x5F22,0x3169,0x4166, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4779, 0,0x3441,
+0x4E7A, 0, 0, 0, 0, 0, 0, 0,
+0x4C21,0x4452, 0, 0, 0, 0,0x5E7B,0x5E7D,
+ 0, 0, 0, 0, 0,0x4132, 0, 0,
+ 0, 0, 0,0x5F21,0x5E79, 0,0x5E73, 0,
+ 0, 0,0x3443, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3769, 0, 0, 0,0x5F2F, 0, 0,
+0x5F2A,0x4078, 0, 0,0x3363, 0, 0, 0,
+ 0,0x3D61, 0,0x5F33, 0, 0, 0, 0,
+ 0, 0,0x5F2C,0x442C,0x5F29,0x4459, 0, 0,
+ 0,0x5F4C, 0, 0, 0,0x5F26, 0,0x5F25,
+ 0,0x5F2E, 0, 0, 0,0x5F28,0x5F27,0x5F2D,
+ 0,0x4021, 0,0x5F24, 0, 0, 0, 0,
+ 0, 0, 0,0x5F30, 0, 0,0x5F31, 0,
+ 0, 0, 0, 0,0x3442, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F36, 0,
+0x5F35,0x5F37, 0, 0, 0, 0, 0,0x5F3A,
+ 0, 0, 0, 0, 0, 0,0x4543, 0,
+0x5F34, 0, 0, 0, 0, 0,0x5F38, 0,
+ 0, 0, 0, 0, 0,0x3763,0x4279,0x5F32,
+0x473B, 0, 0,0x5F39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F3E,0x5F3C, 0, 0,0x5F3F, 0, 0,
+0x5F42, 0, 0, 0,0x5F3B,0x396A,0x4728, 0,
+ 0,0x5E39, 0, 0, 0, 0, 0, 0,
+0x4D74,0x5F3D, 0,0x5F41,0x4275, 0,0x5F40, 0,
+0x5F2B, 0, 0,0x6F69, 0, 0, 0,0x5F45,
+ 0, 0, 0,0x5F49, 0, 0,0x5F47, 0,
+ 0, 0, 0, 0, 0, 0,0x5F43, 0,
+0x5F44, 0, 0, 0,0x5F48, 0,0x5F46, 0,
+ 0, 0,0x494E, 0, 0,0x5F4E, 0,0x5F4B,
+0x5F4A, 0,0x5F4D,0x4654,0x5F4F, 0, 0, 0,
+ 0, 0, 0,0x4375,0x426D, 0, 0, 0,
+ 0,0x4025, 0, 0, 0,0x5F50, 0,0x5F52,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5F51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E75, 0, 0, 0, 0,0x5F53, 0,
+ 0, 0, 0, 0, 0,0x4667, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F54, 0, 0, 0, 0, 0, 0, 0,
+0x3250, 0, 0, 0,0x4574,0x3325, 0, 0,
+ 0, 0, 0, 0, 0,0x3564, 0, 0,
+ 0,0x3C5E,0x3A52, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4F27,0x3F66,
+ 0, 0, 0,0x316A, 0, 0, 0,0x5F56,
+ 0, 0, 0, 0, 0, 0,0x5F55, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F59,0x433A,0x5F5C,0x5F57, 0, 0, 0,
+0x5F5B, 0, 0, 0, 0,0x5F5A,0x4540,0x3059,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4E75, 0, 0,
+0x5F5E, 0, 0, 0,0x3128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F60, 0,
+ 0, 0,0x5F5F, 0,0x5F5D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F58, 0,
+ 0, 0, 0, 0, 0, 0,0x4B23, 0,
+ 0, 0,0x5F62, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F61, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x316B, 0, 0, 0, 0,0x5F64,0x4A32,
+ 0,0x5F63, 0, 0, 0, 0,0x4C35, 0,
+ 0, 0, 0,0x3E47, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4133, 0, 0, 0, 0,
+ 0,0x3E46, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4E7B, 0,
+ 0,0x5F6A, 0,0x4079, 0, 0, 0, 0,
+ 0, 0,0x5F66,0x5F6B, 0, 0,0x316C, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5F69,
+ 0,0x4761,0x5F65,0x5F68,0x3E48, 0,0x4851, 0,
+ 0,0x5F6C, 0,0x3C51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x407A, 0, 0, 0, 0, 0,
+ 0,0x5F6F, 0, 0, 0,0x5F67, 0,0x3727,
+ 0, 0, 0, 0,0x5F6D, 0, 0, 0,
+ 0,0x4D50,0x5F70, 0, 0, 0,0x7426, 0,
+ 0, 0, 0, 0,0x3D4F, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5F71, 0, 0,
+ 0,0x5F72, 0, 0, 0, 0,0x472E, 0,
+ 0, 0, 0, 0, 0, 0,0x5F74, 0,
+ 0, 0, 0,0x5F75, 0, 0, 0, 0,
+0x4733, 0, 0, 0, 0,0x4575,0x5F77, 0,
+ 0, 0, 0,0x5F79, 0,0x4E55, 0,0x5F76,
+ 0,0x5F78,0x316D, 0,0x5F73, 0, 0, 0,
+ 0, 0, 0, 0,0x535B,0x5F7A, 0, 0,
+ 0, 0,0x4167,0x3B38,0x5F7C, 0, 0, 0,
+ 0,0x5F7B,0x3F24,0x5259, 0, 0, 0, 0,
+ 0, 0,0x5F7D, 0, 0, 0,0x6021, 0,
+0x5F6E,0x5F7E, 0, 0,0x6022, 0, 0, 0,
+ 0, 0, 0,0x477A, 0, 0, 0, 0,
+ 0, 0,0x6023, 0, 0,0x6024, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6025, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6026, 0,0x445E,
+ 0,0x6028,0x6027, 0, 0,0x6029, 0,0x602A,
+ 0, 0,0x3C5F,0x4963, 0, 0, 0,0x4C6C,
+0x602B,0x602C,0x4156,0x3C24,0x602D,0x602E, 0, 0,
+ 0, 0, 0,0x602F,0x4A52,0x4847, 0, 0,
+0x6030,0x4757, 0, 0, 0, 0, 0,0x442D,
+ 0, 0, 0, 0, 0,0x6031,0x3267, 0,
+0x356D, 0,0x4C46, 0,0x4C36, 0,0x3234,0x4F34,
+ 0, 0, 0, 0,0x4B52, 0,0x4A2A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4037,
+ 0,0x6032, 0, 0, 0, 0,0x4643, 0,
+ 0, 0,0x3823,0x6033, 0,0x3A54,0x6035,0x6034,
+ 0, 0, 0, 0,0x6036, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6037,
+ 0, 0, 0,0x6038, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x353E, 0,0x6039,
+ 0, 0, 0, 0,0x603A, 0, 0, 0,
+ 0,0x3824, 0, 0,0x4848, 0, 0,0x603C,
+ 0, 0, 0,0x3E75, 0, 0,0x603B, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3638,
+0x603D,0x603F, 0,0x603E, 0, 0, 0, 0,
+ 0, 0, 0,0x6040, 0,0x3851, 0,0x6041,
+ 0, 0, 0, 0,0x3669, 0,0x4140, 0,
+0x397D, 0, 0, 0, 0,0x6043,0x6044,0x6042,
+ 0, 0, 0, 0, 0, 0,0x3C6D, 0,
+ 0,0x4648,0x3639, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6046,0x432C,0x6045, 0,
+ 0,0x4F35,0x4762, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6049,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x604B,0x6048, 0, 0, 0,
+0x4C54,0x604A,0x604C, 0,0x4E44, 0, 0, 0,
+ 0, 0,0x6050, 0, 0, 0,0x604F,0x4376,
+0x472D, 0, 0,0x3825,0x604E, 0, 0, 0,
+ 0,0x604D, 0,0x4D31,0x4D32, 0, 0, 0,
+ 0, 0, 0,0x6051,0x316E, 0, 0, 0,
+ 0,0x3976,0x3B62, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6052,0x6053, 0, 0, 0,
+ 0, 0, 0, 0,0x6055, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3D43, 0, 0, 0, 0,0x6057, 0,0x6056,
+ 0, 0, 0, 0, 0,0x6058, 0,0x334D,
+ 0, 0,0x605A, 0, 0,0x6059, 0,0x605C,
+0x605B, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x383C, 0, 0,0x4E28, 0,0x364C, 0,
+0x3226, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x366A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3461, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4E68,
+0x605E, 0, 0, 0, 0, 0, 0, 0,
+0x6060, 0, 0, 0, 0,0x6061, 0,0x3251,
+ 0, 0, 0, 0, 0,0x605D, 0,0x3B39,
+ 0, 0,0x4441,0x605F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6064, 0,0x3C6E, 0, 0,
+ 0, 0,0x6062, 0, 0, 0, 0,0x373E,
+ 0, 0,0x4849,0x6063, 0, 0,0x607E, 0,
+ 0, 0, 0, 0, 0,0x6069, 0, 0,
+ 0, 0, 0,0x383D, 0, 0, 0, 0,
+0x3565, 0,0x6066,0x4D7D, 0, 0,0x4E30};
+
+/* page 32 0x7422-0x7845 */
+static uint16 tab_uni_jisx020832[]={
+0x4276, 0, 0,0x6068, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x606A,0x4E56,0x3657,0x487C,0x474A, 0, 0, 0,
+0x606B, 0, 0, 0, 0,0x606D, 0,0x6070,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x606C, 0, 0, 0,0x606F,
+0x386A,0x314D,0x6071, 0,0x3F70,0x606E,0x4E5C, 0,
+ 0,0x6074,0x7424, 0, 0, 0, 0,0x6072,
+0x6075, 0, 0, 0, 0,0x6067,0x6073, 0,
+ 0,0x3A3C, 0, 0,0x6076, 0, 0, 0,
+ 0, 0, 0, 0,0x6077, 0, 0, 0,
+ 0,0x4D7E, 0, 0, 0, 0, 0, 0,
+ 0,0x6078, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6079, 0, 0, 0,
+0x6065, 0, 0, 0, 0,0x607A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3444, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3C25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x607B, 0, 0, 0, 0,0x607C, 0, 0,
+ 0, 0,0x607D, 0, 0, 0, 0, 0,
+ 0, 0,0x313B, 0, 0, 0,0x6121, 0,
+0x493B,0x6122, 0, 0,0x3424,0x6123, 0,0x6124,
+ 0, 0, 0, 0,0x6125, 0,0x6127,0x6128,
+0x6126, 0, 0, 0,0x4953,0x612A,0x6129, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x612C,0x612B,0x612D, 0, 0, 0, 0,
+ 0, 0,0x612E,0x6130,0x612F, 0, 0,0x3979,
+ 0,0x6132, 0,0x6131, 0, 0,0x3445, 0,
+0x3F53, 0,0x453C, 0,0x6133,0x4038, 0, 0,
+ 0,0x3B3A, 0,0x3179,0x6134, 0,0x4D51, 0,
+ 0,0x4A63,0x6135, 0, 0, 0,0x4544,0x4D33,
+0x3943,0x3F3D, 0, 0, 0,0x434B,0x5234, 0,
+0x442E,0x3268,0x6136, 0, 0, 0, 0, 0,
+ 0, 0,0x6137, 0,0x613C, 0, 0,0x613A,
+0x6139,0x5A42,0x3326,0x6138, 0,0x305A, 0,0x482A,
+ 0, 0,0x484A, 0, 0, 0, 0,0x4E31,
+0x613D,0x613B,0x435C,0x4026, 0, 0,0x482B, 0,
+0x492D, 0,0x613F,0x4E2C,0x374D,0x6140, 0,0x613E,
+0x4856,0x6141, 0,0x6142, 0, 0,0x305B, 0,
+ 0,0x3E76,0x6147, 0,0x6144,0x466D,0x6143, 0,
+ 0, 0, 0, 0, 0,0x3526, 0, 0,
+0x614A, 0, 0, 0,0x6145,0x6146, 0,0x6149,
+0x6148,0x4925, 0, 0,0x4142,0x4141, 0,0x353F,
+ 0, 0,0x614B, 0, 0, 0, 0, 0,
+0x614C, 0, 0,0x614D, 0, 0, 0, 0,
+ 0,0x614F, 0,0x614E, 0, 0, 0, 0,
+ 0,0x3156, 0, 0, 0, 0, 0,0x6157,
+0x4868,0x6151, 0,0x6153, 0, 0,0x6155,0x3F3E,
+ 0, 0,0x6156,0x6154,0x3C40, 0, 0, 0,
+0x6150,0x6152, 0,0x4942, 0,0x3E49, 0, 0,
+0x6159, 0, 0,0x6158, 0, 0, 0, 0,
+0x615A, 0,0x3C26,0x3A2F, 0, 0,0x4577,0x615B,
+ 0,0x444B, 0, 0,0x615D, 0, 0, 0,
+0x4E21,0x615C, 0, 0, 0, 0, 0,0x4169,
+ 0, 0, 0, 0, 0, 0,0x6162, 0,
+0x6164,0x6165,0x4354, 0, 0, 0, 0, 0,
+0x6163, 0,0x6160, 0,0x615E,0x615F, 0,0x6161,
+ 0, 0, 0, 0, 0, 0, 0,0x6168,
+ 0,0x6166, 0,0x6167, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6169,0x616B,0x616C,
+0x616D, 0,0x616E, 0, 0,0x616A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6170, 0,
+ 0, 0,0x616F, 0, 0, 0, 0, 0,
+ 0,0x6171, 0, 0, 0, 0, 0, 0,
+0x4E45, 0, 0, 0,0x6174,0x6172,0x6173, 0,
+ 0, 0,0x3462, 0, 0, 0, 0, 0,
+0x4C7E, 0, 0, 0,0x4A4A, 0,0x6176, 0,
+ 0, 0,0x6175, 0, 0, 0, 0,0x6177,
+0x6178, 0, 0, 0, 0,0x617C,0x6179,0x617A,
+0x617B, 0,0x617D, 0, 0, 0,0x617E, 0,
+0x6221, 0, 0, 0,0x6222, 0,0x6223, 0,
+0x482F,0x4550,0x6224,0x4772,0x4934, 0,0x6225, 0,
+ 0,0x6226,0x452A, 0,0x3327,0x3944,0x6227, 0,
+ 0,0x6228, 0, 0,0x6229, 0,0x3B29, 0,
+ 0,0x622B, 0, 0,0x622A, 0, 0,0x622C,
+0x622D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4869, 0,0x622E, 0,
+ 0, 0,0x622F, 0, 0,0x7369,0x6230,0x6231,
+0x6232, 0, 0, 0, 0,0x3B2E, 0, 0,
+0x6233,0x4756, 0, 0,0x4B5F, 0,0x314E, 0,
+0x3157, 0, 0,0x6234, 0, 0, 0, 0,
+0x6236, 0, 0, 0,0x6235,0x4570, 0, 0,
+ 0,0x4039,0x5D39, 0,0x6237,0x4C41, 0,0x6238,
+ 0,0x3446,0x4857,0x6239, 0,0x623A, 0, 0,
+0x623B, 0, 0, 0,0x4C5C, 0, 0, 0,
+0x4C55, 0,0x443E, 0, 0, 0,0x416A, 0,
+ 0,0x623D, 0, 0,0x3D62, 0, 0,0x3E4A,
+ 0, 0,0x6240, 0, 0,0x623F,0x623E,0x487D,
+ 0,0x3447,0x3829, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6246, 0, 0,0x6243,0x3F3F,0x4C32, 0,
+ 0, 0,0x6242,0x6244,0x6245, 0, 0,0x6241,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6247,0x6248, 0,
+0x442F, 0,0x3463, 0, 0, 0,0x4365, 0,
+ 0, 0, 0, 0, 0,0x6249, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x624A,0x624D, 0, 0, 0, 0, 0,0x3F67,
+ 0,0x4644, 0,0x624E,0x4B53, 0,0x624B, 0,
+ 0,0x624C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6251,
+ 0, 0, 0, 0,0x6250,0x624F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6253, 0, 0,0x6252, 0, 0,0x6254,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6256, 0,0x6255, 0,
+ 0, 0, 0,0x4A4D, 0, 0, 0, 0,
+ 0, 0,0x3D56,0x4E46, 0, 0,0x6257, 0,
+ 0,0x4637, 0, 0,0x6258, 0, 0,0x6259,
+ 0,0x625D,0x625B,0x625C, 0,0x625A, 0, 0,
+ 0, 0, 0, 0, 0,0x625E, 0, 0,
+ 0, 0, 0,0x625F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6260, 0, 0,
+0x6261,0x4C37,0x6262, 0, 0, 0, 0, 0,
+0x4C70,0x6263, 0,0x434E, 0,0x476A, 0,0x366B,
+ 0, 0, 0,0x433B,0x6264,0x363A, 0, 0,
+ 0,0x4050, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6265, 0, 0, 0, 0, 0,
+0x3A3D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6266, 0, 0, 0, 0, 0,
+0x6267, 0,0x3826,0x3A55, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6269, 0,
+ 0, 0, 0,0x4556,0x3A56,0x354E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4B24, 0,0x474B, 0, 0, 0, 0, 0,
+0x4557, 0, 0, 0, 0,0x395C, 0, 0,
+ 0, 0, 0,0x626B};
+
+/* page 33 0x785D-0x7E9C */
+static uint16 tab_uni_jisx020833[]={
+0x3E4B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4E32,0x3945,
+ 0, 0,0x3827, 0, 0,0x4823, 0,0x626D,
+ 0, 0, 0, 0, 0, 0, 0,0x626F,
+ 0, 0, 0, 0,0x386B, 0, 0, 0,
+ 0,0x626E,0x4476, 0, 0, 0, 0,0x6271,
+0x3337,0x626C, 0, 0,0x486A, 0,0x3130, 0,
+0x3A6C, 0,0x4F52, 0, 0,0x6270, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6272, 0,
+ 0, 0,0x4A4B, 0,0x4059,0x6274, 0, 0,
+ 0, 0,0x6275, 0, 0, 0, 0, 0,
+0x6273, 0, 0, 0, 0,0x334E, 0,0x627B,
+ 0,0x627A, 0, 0,0x3C27, 0, 0, 0,
+0x627C,0x6277, 0, 0, 0,0x627D,0x6278, 0,
+ 0, 0, 0,0x4858,0x6276, 0, 0,0x6279,
+ 0, 0, 0, 0, 0,0x6322, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6321,0x4B61, 0, 0, 0,0x627E,
+ 0, 0,0x306B, 0, 0, 0, 0,0x6324,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6323, 0, 0, 0,0x3E4C, 0, 0, 0,
+ 0, 0,0x6325, 0, 0, 0, 0, 0,
+ 0,0x4143, 0, 0,0x6327,0x6326, 0, 0,
+ 0, 0, 0, 0,0x6328, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6268, 0, 0, 0,0x626A,0x632A,0x6329,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C28, 0,0x4E69,
+ 0,0x3C52, 0,0x632B,0x3737, 0, 0, 0,
+ 0, 0,0x3540,0x3527,0x3B63, 0, 0, 0,
+ 0, 0, 0,0x4D34, 0, 0,0x6331, 0,
+0x6330,0x4144,0x632D, 0, 0,0x632F, 0, 0,
+0x3D4B,0x3F40,0x632E,0x632C, 0,0x472A, 0, 0,
+0x3E4D, 0, 0,0x493C, 0, 0, 0, 0,
+0x3A57, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4578, 0, 0,0x6332, 0, 0,
+ 0, 0,0x6333,0x6349,0x3658, 0, 0,0x4F3D,
+0x4135, 0, 0, 0, 0,0x6334, 0, 0,
+0x3252,0x4477,0x4A21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6335, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x357A,0x6336, 0, 0,0x6338, 0, 0,
+ 0,0x6339, 0,0x4729, 0, 0,0x633A, 0,
+ 0, 0, 0, 0,0x633B,0x633C, 0, 0,
+0x3659,0x3253,0x4645,0x3D28,0x3B64, 0, 0, 0,
+ 0, 0, 0, 0,0x633D, 0,0x3D29, 0,
+ 0, 0, 0, 0,0x324A,0x4943, 0, 0,
+0x633E, 0, 0,0x486B, 0, 0, 0, 0,
+ 0, 0,0x4145, 0,0x6341, 0,0x6342,0x4769,
+ 0,0x3F41,0x633F, 0,0x4361, 0, 0,0x6340,
+ 0, 0, 0,0x3E4E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x305C, 0,
+ 0, 0, 0,0x3529, 0, 0, 0, 0,
+ 0, 0, 0,0x6343, 0, 0,0x4478, 0,
+0x6344,0x4047, 0, 0, 0, 0, 0,0x4C2D,
+ 0, 0,0x4923,0x6345,0x6346,0x4355, 0,0x4E47,
+ 0, 0,0x6348,0x6347, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3C6F, 0, 0,0x634A,0x3070, 0, 0,
+ 0, 0,0x634D, 0, 0, 0,0x634B,0x3254,
+0x374E,0x634C,0x3946,0x3972, 0,0x4A66,0x634E, 0,
+ 0,0x4B54, 0, 0,0x6350, 0, 0, 0,
+0x4051,0x314F,0x323A,0x302C, 0, 0, 0, 0,
+ 0, 0,0x634F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6351,0x6352,0x3E77, 0,
+ 0, 0, 0, 0,0x6353, 0,0x334F, 0,
+ 0, 0, 0,0x6355, 0, 0, 0,0x376A,
+ 0,0x3566, 0, 0,0x6356,0x3675, 0, 0,
+0x6357, 0,0x407C, 0,0x464D, 0,0x4060,0x3A75,
+ 0, 0, 0,0x6358, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4362,0x416B, 0,
+0x635A,0x635C,0x6359,0x635B, 0, 0, 0, 0,
+ 0, 0,0x3722, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x635D,0x3726, 0, 0,
+ 0,0x3567,0x4D52,0x635F, 0, 0, 0, 0,
+ 0,0x6360, 0, 0, 0,0x312E, 0, 0,
+ 0, 0,0x6363, 0, 0, 0,0x3376,0x6362,
+0x6361, 0,0x6365,0x635E, 0,0x6366,0x4E29, 0,
+0x6367, 0,0x6368, 0, 0,0x5474,0x636A, 0,
+0x6369, 0, 0, 0,0x636B,0x636C, 0,0x4E35,
+0x636D, 0,0x706F,0x3E4F,0x636E,0x636F,0x3D57, 0,
+0x4638,0x6370, 0, 0, 0,0x4328, 0, 0,
+0x6371, 0,0x433C,0x6372, 0, 0, 0, 0,
+ 0,0x3625, 0,0x513F,0x435D,0x3C33, 0, 0,
+ 0, 0,0x3448, 0, 0,0x6373, 0,0x6422,
+ 0,0x6376, 0,0x3568, 0,0x6375,0x6424, 0,
+ 0, 0,0x6374, 0,0x3E50, 0, 0, 0,
+ 0, 0, 0,0x6378,0x6379, 0,0x452B, 0,
+ 0,0x637A, 0,0x335E, 0, 0, 0, 0,
+0x3F5A,0x4964, 0,0x637C, 0, 0, 0,0x4268,
+ 0, 0, 0, 0, 0, 0,0x6377, 0,
+0x637B,0x637D, 0, 0,0x3A7B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6426,0x492E, 0,0x4826,0x4579, 0,0x365A,0x6425,
+0x6423, 0,0x4835,0x637E,0x435E,0x457B, 0,0x457A,
+ 0,0x3A76, 0, 0, 0, 0, 0, 0,
+0x6438, 0, 0, 0, 0, 0, 0, 0,
+0x6428, 0,0x642A, 0, 0, 0, 0,0x642D,
+ 0,0x642E, 0,0x642B,0x642C, 0, 0,0x6429,
+0x6427, 0, 0, 0, 0,0x6421, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4A4F,0x3255, 0, 0, 0,0x6435, 0,
+0x6432, 0,0x6437, 0, 0,0x6436, 0,0x4773,
+0x4C27, 0,0x3B3B,0x6430,0x6439,0x6434, 0,0x6433,
+0x642F, 0,0x6431, 0,0x3449, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x433D, 0, 0,
+0x407D, 0, 0, 0,0x4822, 0, 0,0x643E,
+ 0, 0, 0,0x4824, 0, 0, 0, 0,
+ 0, 0, 0,0x4061,0x643B, 0, 0,0x484F,
+ 0,0x643F,0x4A53, 0,0x435B, 0,0x643A,0x643C,
+ 0, 0,0x643D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6440, 0, 0,0x3C44, 0, 0, 0,0x4646,
+0x6445,0x6444, 0, 0,0x6441, 0, 0, 0,
+0x4F36, 0, 0, 0, 0, 0,0x644A, 0,
+ 0,0x644E,0x644B, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6447, 0, 0, 0, 0,
+ 0, 0,0x6448, 0, 0, 0, 0, 0,
+0x644D, 0, 0, 0,0x6442,0x5255,0x6449,0x6443,
+ 0, 0,0x644C, 0, 0, 0, 0, 0,
+ 0, 0,0x6452, 0,0x344A, 0,0x644F, 0,
+ 0, 0,0x6450, 0, 0,0x6451,0x6454, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6453,0x4876, 0, 0, 0, 0,
+0x6455,0x4E7C,0x4A6D,0x645A, 0, 0,0x6457, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6456,
+0x4052, 0,0x6459,0x645B, 0, 0, 0,0x6458,
+ 0,0x645F, 0,0x645C, 0, 0, 0, 0,
+ 0, 0,0x645D,0x6446, 0, 0, 0,0x645E,
+0x6460, 0, 0, 0, 0, 0, 0,0x6461,
+ 0, 0, 0, 0, 0, 0,0x4A46, 0,
+0x6462, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4C62, 0, 0,0x364E,0x3729,0x6463, 0,
+ 0, 0, 0, 0,0x4A34, 0,0x3F68, 0,
+0x4C30, 0, 0,0x6464, 0,0x4E33, 0, 0,
+0x4774, 0,0x4146,0x4734, 0, 0,0x3D4D, 0,
+ 0, 0,0x3040, 0,0x6469,0x6467, 0,0x6465,
+0x3421, 0,0x3E51,0x646A, 0, 0,0x6468, 0,
+0x6466,0x646E, 0, 0,0x646D,0x646C,0x646B, 0,
+ 0, 0, 0, 0,0x646F, 0, 0, 0,
+0x6470,0x403A, 0,0x6471, 0,0x6473, 0, 0,
+0x6472, 0, 0, 0, 0,0x3852, 0, 0,
+ 0,0x4138, 0, 0, 0,0x6475, 0, 0,
+ 0,0x457C, 0,0x6474, 0, 0, 0,0x6476,
+ 0,0x4A35,0x416C,0x3947, 0,0x6477, 0, 0,
+ 0, 0,0x4E48, 0, 0, 0, 0, 0,
+ 0, 0,0x6479, 0, 0,0x647A, 0,0x647B,
+ 0,0x647C, 0,0x3B65, 0,0x647D,0x374F, 0,
+ 0,0x356A, 0,0x352A, 0,0x6521, 0,0x4C73,
+0x3948,0x647E, 0, 0, 0,0x6524,0x4C66, 0,
+0x473C, 0, 0,0x4933, 0, 0, 0,0x3D63,
+0x6523, 0,0x3C53,0x3949,0x3B66,0x3569,0x4A36,0x6522,
+ 0, 0, 0,0x4147,0x4B42,0x3A77, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B67,0x445D,
+ 0,0x6527,0x4E5F,0x3A59, 0,0x6528,0x3F42, 0,
+0x652A, 0, 0, 0,0x3E52,0x3A30, 0, 0,
+ 0, 0,0x6529, 0, 0,0x3D2A,0x383E,0x4148,
+0x6525,0x652B, 0, 0, 0, 0,0x6526,0x3750,
+ 0,0x652E,0x6532,0x376B, 0, 0, 0, 0,
+ 0,0x652D, 0, 0, 0, 0,0x6536, 0,
+ 0,0x394A, 0, 0,0x4D6D,0x303C,0x6533, 0,
+ 0,0x356B, 0,0x6530, 0, 0, 0, 0,
+ 0,0x6531, 0, 0,0x457D,0x652F,0x652C, 0,
+0x3328,0x4064, 0, 0,0x3828, 0, 0, 0,
+0x6538, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6535, 0, 0, 0,
+ 0, 0,0x6537, 0, 0, 0,0x6534, 0,
+ 0, 0, 0, 0,0x3751,0x4233,0x6539,0x416E,
+ 0, 0,0x6546, 0, 0,0x6542,0x653C, 0,
+ 0, 0, 0, 0, 0, 0,0x6540,0x3C7A,
+0x305D,0x653B,0x6543,0x6547,0x394B,0x4C56, 0,0x4456,
+0x653D, 0, 0,0x6545, 0,0x653A,0x433E, 0,
+0x653F,0x303D,0x4C4A, 0, 0, 0, 0, 0,
+ 0, 0,0x653E, 0, 0,0x365B,0x486C, 0,
+ 0, 0,0x416D, 0,0x4E50,0x3D6F, 0, 0,
+0x656E, 0, 0,0x6548, 0,0x407E, 0,0x6544,
+0x6549,0x654B, 0,0x4479,0x654E, 0, 0,0x654A,
+ 0, 0, 0,0x4A54,0x344B, 0, 0,0x4C4B,
+ 0, 0,0x305E, 0, 0,0x654D, 0,0x4E7D,
+ 0, 0, 0, 0, 0, 0,0x654C, 0,
+ 0, 0, 0, 0,0x316F, 0, 0,0x466C,
+0x654F, 0, 0, 0,0x6556,0x6550,0x6557, 0,
+ 0, 0, 0, 0, 0,0x6553, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x477B, 0,
+ 0,0x3C4A,0x6555, 0,0x6552,0x6558,0x6551, 0,
+ 0,0x3D44, 0, 0, 0, 0,0x4B25, 0,
+ 0,0x3D4C, 0, 0,0x6554,0x6560, 0, 0,
+0x655C, 0,0x655F, 0,0x655D,0x6561,0x655B, 0,
+0x6541,0x4053, 0, 0,0x484B, 0,0x655E, 0,
+ 0,0x6559, 0, 0, 0,0x4121,0x3752, 0,
+0x3D2B, 0, 0, 0, 0, 0, 0,0x3F25,
+0x4136,0x6564, 0, 0,0x6566,0x6567, 0, 0,
+0x6563,0x6565, 0, 0, 0, 0, 0, 0,
+ 0,0x655A,0x6562, 0,0x656A,0x6569, 0, 0,
+0x4B7A, 0, 0,0x372B, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6568, 0,0x656C,0x656B,
+0x656F, 0,0x6571, 0, 0,0x3B3C,0x656D, 0,
+ 0, 0, 0,0x6572,0x6573, 0, 0,0x6574,
+ 0,0x657A,0x453B,0x6576, 0,0x6575,0x6577,0x6578,
+ 0,0x6579, 0, 0, 0, 0,0x657B,0x657C
+};
+
+/* page 34 0x7F36-0x8358 */
+static uint16 tab_uni_jisx020834[]={
+0x344C, 0,0x657D, 0,0x657E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6621,
+ 0, 0, 0, 0, 0, 0,0x6622,0x6623,
+0x6624, 0,0x6625,0x6626, 0, 0,0x6628,0x6627,
+ 0, 0,0x6629, 0, 0, 0, 0, 0,
+ 0,0x662A,0x662B, 0, 0, 0, 0, 0,
+ 0,0x662E,0x662C,0x662D,0x3A61,0x3753, 0, 0,
+0x4356, 0,0x4833, 0,0x3D70, 0, 0,0x474D,
+ 0,0x486D,0x662F,0x586D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6630,0x6632, 0,0x4D65,
+0x6631,0x6634,0x6633, 0,0x4D53, 0,0x6635, 0,
+0x487E, 0, 0, 0, 0, 0,0x6636, 0,
+ 0, 0, 0, 0,0x6639, 0, 0,0x6638,
+0x6637, 0, 0, 0, 0,0x663A,0x3732, 0,
+ 0, 0,0x4122,0x3541, 0, 0, 0, 0,
+0x663E,0x663B, 0, 0,0x663C, 0, 0, 0,
+0x663F, 0,0x6640,0x663D, 0, 0, 0,0x3129,
+ 0, 0, 0,0x3227, 0, 0, 0,0x6642,
+0x6643, 0, 0, 0,0x6644, 0,0x4D62, 0,
+ 0, 0, 0, 0,0x3D2C, 0,0x6646,0x6645,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3F69,0x6647, 0, 0, 0, 0,
+0x6648, 0, 0,0x6649, 0,0x3465, 0, 0,
+ 0, 0,0x344D, 0, 0,0x664A, 0, 0,
+ 0, 0, 0,0x664B, 0,0x4B5D,0x4D63, 0,
+ 0, 0,0x4D54,0x4F37, 0,0x394D,0x664E,0x3C54,
+0x664D, 0, 0, 0, 0,0x664F,0x3C29, 0,
+ 0, 0,0x4251, 0,0x6650, 0, 0,0x394C,
+ 0,0x4C57,0x6651,0x6652, 0, 0,0x6653, 0,
+ 0, 0, 0,0x6654, 0, 0, 0, 0,
+ 0, 0,0x6655, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C2A, 0, 0,
+0x4C6D, 0, 0, 0, 0,0x6657, 0,0x433F,
+ 0,0x6656, 0, 0, 0, 0, 0, 0,
+0x6659, 0, 0, 0,0x6658, 0, 0, 0,
+ 0, 0, 0, 0,0x665A, 0, 0, 0,
+0x403B, 0,0x665B, 0,0x665C, 0, 0, 0,
+0x4A39,0x665D, 0,0x416F,0x665E, 0, 0, 0,
+ 0, 0,0x665F, 0, 0, 0, 0, 0,
+ 0,0x4E7E,0x6662, 0,0x6661,0x6660,0x4430, 0,
+0x6663,0x3F26, 0,0x6664, 0, 0, 0,0x6665,
+0x4F38,0x6666, 0, 0, 0, 0,0x6667,0x6669,
+0x6668,0x4825, 0,0x4679, 0,0x4F3E,0x4829, 0,
+ 0, 0, 0, 0, 0,0x666B, 0, 0,
+0x3E53, 0,0x492A, 0,0x666C,0x666A, 0,0x344E,
+ 0, 0, 0,0x3854,0x3B68, 0, 0,0x486E,
+ 0, 0, 0,0x382A,0x4B43, 0,0x666F,0x666D,
+ 0,0x394E, 0,0x394F,0x3069, 0,0x3A68, 0,
+ 0, 0, 0, 0,0x4759, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x305F,0x6674, 0,
+0x4340, 0, 0, 0, 0, 0,0x4758, 0,
+0x425B, 0, 0, 0, 0, 0, 0, 0,
+0x6676, 0, 0,0x6672,0x6675,0x6670, 0,0x6673,
+0x4B26, 0, 0,0x3855, 0, 0,0x307D,0x6671,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6678, 0,0x6679, 0, 0,0x4639, 0,
+ 0, 0,0x363B, 0, 0, 0,0x6726,0x473D,
+ 0, 0, 0, 0,0x3B69, 0, 0,0x363C,
+0x4048,0x4F46,0x4C2E,0x6677,0x4054, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3553,0x667A, 0, 0,
+ 0, 0, 0, 0, 0,0x667C, 0, 0,
+ 0, 0, 0,0x667B, 0, 0, 0, 0,
+ 0,0x667D, 0,0x4326, 0,0x473E, 0, 0,
+ 0, 0, 0,0x4431, 0, 0, 0, 0,
+0x6723, 0, 0, 0, 0, 0, 0, 0,
+0x6722, 0, 0, 0, 0,0x667E, 0, 0,
+0x3F55, 0,0x4965,0x6725, 0,0x6724,0x3950,0x4F53,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6735, 0, 0, 0, 0, 0,0x6729,
+0x672A, 0, 0, 0, 0,0x3C70, 0, 0,
+0x6728, 0,0x3978,0x6727, 0, 0,0x672B, 0,
+ 0, 0,0x4432,0x4A22,0x4123, 0, 0, 0,
+ 0,0x425C,0x672F, 0,0x6730,0x672C, 0, 0,
+ 0, 0,0x672D, 0,0x672E, 0, 0, 0,
+ 0,0x3951, 0, 0, 0,0x6736, 0,0x6732,
+ 0, 0, 0, 0,0x4966, 0,0x4B6C,0x4928,
+ 0, 0,0x6731, 0, 0,0x6734,0x6733, 0,
+ 0, 0,0x4B44,0x6737, 0, 0, 0, 0,
+ 0, 0,0x6738, 0, 0,0x4137, 0,0x6739,
+ 0, 0,0x673B, 0,0x673F, 0, 0,0x673C,
+0x673A,0x473F,0x673D, 0,0x673E, 0, 0, 0,
+0x3232, 0,0x6745,0x6740, 0, 0, 0,0x6741,
+ 0, 0, 0,0x6742, 0,0x4221, 0, 0,
+ 0, 0,0x6744,0x6743,0x6746, 0, 0, 0,
+ 0,0x6747,0x6748, 0, 0,0x3F43, 0,0x3269,
+ 0,0x6749,0x4E57, 0,0x3C2B, 0, 0,0x3D2D,
+ 0, 0, 0, 0, 0,0x3B6A,0x4357, 0,
+ 0, 0, 0, 0,0x674A,0x674B,0x3131, 0,
+0x674C, 0, 0,0x674D,0x674E, 0, 0,0x674F,
+ 0,0x6750,0x363D,0x5A2A,0x6751, 0,0x4065,0x6752,
+0x3C4B, 0,0x6753, 0,0x5030, 0, 0, 0,
+0x6754,0x4A5E,0x345C, 0, 0,0x4124,0x3D58, 0,
+0x4971,0x3D2E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6755,0x3952,0x6756,0x484C, 0,
+0x6764, 0, 0, 0, 0,0x6758, 0,0x4249,
+0x4775,0x383F,0x6757,0x4125, 0, 0, 0, 0,
+ 0, 0,0x6759, 0, 0, 0, 0, 0,
+ 0,0x447A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x675B,0x675A,0x675D, 0, 0,0x675C,
+ 0,0x675E, 0, 0,0x6760, 0,0x675F, 0,
+0x344F, 0,0x6761, 0,0x6762,0x6763, 0, 0,
+0x3A31,0x4E49, 0,0x6765,0x3F27, 0, 0, 0,
+0x3170,0x6766,0x6767, 0, 0, 0, 0, 0,
+0x6768, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3072, 0,0x6769,
+ 0, 0, 0, 0,0x676A, 0, 0, 0,
+ 0, 0, 0,0x4967, 0, 0, 0,0x3C47,
+ 0,0x676C, 0, 0, 0, 0, 0,0x3329,
+0x3032, 0, 0, 0, 0,0x676B,0x676E,0x474E,
+ 0,0x3F44, 0,0x3256, 0,0x4B27, 0, 0,
+ 0, 0,0x375D,0x365C, 0,0x676D, 0,0x326A,
+ 0, 0, 0, 0, 0, 0, 0,0x3423,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3171,0x6772,0x4E6A,0x425D, 0,
+ 0,0x4944, 0,0x677E, 0,0x3257,0x677C, 0,
+0x677A,0x6771, 0,0x676F, 0,0x6770, 0,0x3C63,
+0x366C,0x4377, 0, 0, 0,0x4651, 0, 0,
+ 0, 0, 0,0x3151, 0,0x6774,0x6773, 0,
+ 0, 0, 0,0x6779,0x6775,0x6778, 0, 0,
+ 0, 0, 0, 0,0x4C50,0x6777,0x3258,0x337D,
+0x677B, 0, 0,0x677D, 0, 0, 0, 0,
+0x3754, 0, 0, 0, 0, 0, 0, 0,
+0x6823,0x682C,0x682D, 0, 0, 0,0x302B, 0,
+ 0, 0, 0, 0, 0,0x6834, 0, 0,
+ 0, 0,0x3071, 0, 0,0x682B, 0, 0,
+ 0,0x682A, 0,0x6825,0x6824, 0,0x6822,0x6821,
+0x4363, 0,0x427B,0x6827, 0, 0, 0, 0,
+ 0, 0,0x6826, 0, 0, 0, 0,0x6829,
+ 0, 0, 0,0x4170,0x3755, 0, 0, 0,
+ 0,0x3141,0x6828, 0,0x3953, 0, 0, 0,
+ 0, 0,0x4171};
+
+/* page 35 0x8373-0x8B9A */
+static uint16 tab_uni_jisx020835[]={
+0x683A, 0,0x683B, 0,0x3259, 0, 0, 0,
+0x322E,0x6838, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x682E, 0,0x6836, 0,0x683D,0x6837,
+ 0, 0, 0,0x6835, 0, 0, 0, 0,
+0x6776, 0, 0,0x6833, 0, 0, 0,0x682F,
+ 0, 0, 0,0x3450,0x6831,0x683C, 0,0x6832,
+ 0, 0, 0, 0, 0,0x683E, 0,0x6830,
+0x477C, 0, 0, 0, 0, 0,0x4D69, 0,
+ 0, 0,0x6839, 0, 0, 0, 0, 0,
+ 0, 0,0x684F, 0, 0, 0,0x6847, 0,
+ 0, 0,0x3F7B, 0, 0, 0, 0,0x3546,
+ 0,0x365D, 0,0x6842, 0, 0, 0, 0,
+0x325B, 0, 0,0x3E54, 0,0x6845, 0, 0,
+ 0,0x3A5A, 0, 0,0x4551,0x684A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A6E, 0,
+0x6841, 0, 0, 0,0x325A,0x3856,0x4929,0x684B,
+ 0,0x683F, 0, 0,0x6848, 0, 0, 0,
+0x6852, 0,0x6843, 0, 0, 0, 0, 0,
+0x6844,0x463A, 0, 0,0x6849, 0, 0, 0,
+0x6846,0x4B28,0x684C,0x3060, 0, 0, 0, 0,
+0x6840, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x684E, 0,0x684D,
+ 0, 0, 0, 0, 0, 0,0x476B,0x6854,
+ 0,0x685F, 0, 0, 0, 0,0x337E, 0,
+ 0, 0,0x6862, 0, 0,0x6850, 0, 0,
+ 0,0x6855,0x4D6E, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x685E, 0, 0,0x4D55, 0,
+ 0, 0, 0,0x4E2A, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4378, 0, 0, 0,
+0x336B, 0, 0, 0, 0, 0,0x4972,0x6864,
+0x4621, 0, 0,0x3031, 0, 0,0x685D, 0,
+0x6859,0x4172,0x6853,0x685B,0x6860, 0,0x472C, 0,
+ 0, 0,0x302A, 0,0x6858, 0,0x6861,0x4978,
+ 0, 0, 0, 0, 0, 0, 0,0x685C,
+ 0,0x6857, 0, 0, 0, 0, 0, 0,
+0x3E55, 0, 0, 0, 0,0x3D2F, 0, 0,
+ 0,0x3C2C, 0, 0, 0, 0,0x4C58, 0,
+ 0,0x4947, 0, 0,0x6867, 0,0x6870, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x685A, 0, 0, 0, 0,0x3377,
+ 0, 0, 0, 0, 0,0x3E78,0x6865, 0,
+0x686A,0x4173, 0, 0,0x6866, 0,0x686D, 0,
+ 0,0x435F, 0,0x686E, 0, 0,0x4D56,0x6863,
+0x3338, 0,0x6869, 0, 0,0x686C,0x4C2C, 0,
+ 0, 0, 0,0x686F, 0, 0,0x6868,0x686B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4B29, 0,0x4F21, 0, 0, 0, 0,
+ 0,0x6873, 0, 0, 0, 0, 0, 0,
+ 0,0x687A, 0, 0,0x6872,0x3C43, 0, 0,
+ 0, 0, 0,0x6851, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A4E, 0,
+0x4C22,0x6879,0x6878, 0,0x6874,0x6875, 0,0x3136,
+ 0, 0, 0, 0,0x6877, 0,0x6871, 0,
+ 0, 0, 0,0x4455, 0, 0, 0, 0,
+ 0,0x6876,0x307E, 0, 0, 0, 0, 0,
+ 0, 0,0x4222, 0, 0, 0, 0, 0,
+ 0, 0,0x4A43, 0, 0,0x687B,0x6921, 0,
+0x4859, 0, 0, 0, 0,0x687E,0x3E56,0x3C49,
+0x6923, 0, 0,0x363E, 0, 0, 0, 0,
+ 0, 0,0x6924, 0,0x4979,0x687D, 0,0x6856,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x687C, 0, 0, 0, 0,0x4F4F,0x4622,0x4973,
+ 0, 0,0x692B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6931, 0, 0, 0,
+ 0, 0, 0,0x6932, 0,0x6925, 0, 0,
+ 0,0x4776, 0, 0,0x692F,0x6927, 0,0x6929,
+ 0, 0, 0, 0, 0,0x6933,0x6928, 0,
+ 0,0x692C, 0, 0,0x3172, 0,0x4665, 0,
+0x692D,0x6930, 0, 0, 0, 0, 0, 0,
+ 0,0x6926, 0,0x4126, 0,0x692A,0x3B27,0x3F45,
+0x3730,0x4C74, 0,0x4C79,0x3D72, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6937,0x6935,
+ 0, 0, 0, 0, 0, 0,0x4F4E, 0,
+ 0, 0, 0, 0, 0, 0,0x6934, 0,
+ 0, 0,0x4D75, 0,0x6936,0x6938, 0, 0,
+ 0, 0,0x6939, 0, 0, 0, 0, 0,
+ 0,0x693C,0x693A, 0, 0, 0, 0, 0,
+ 0,0x4623,0x693B, 0, 0, 0,0x484D,0x692E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3D73, 0,0x693D,0x6942,
+0x4174, 0, 0,0x6941, 0, 0, 0,0x6922,
+ 0, 0, 0,0x6943,0x4149, 0, 0,0x693E,
+0x6940, 0, 0, 0, 0, 0, 0, 0,
+0x693F, 0, 0,0x5D31,0x5D22, 0, 0,0x6945,
+ 0, 0, 0, 0, 0, 0, 0,0x6944,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D76, 0,0x623C,0x6946, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6947, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6948,0x3857, 0,0x3554, 0, 0,
+ 0,0x694A,0x515D, 0, 0, 0, 0,0x3575,
+ 0,0x4E3A, 0,0x3673,0x694B, 0, 0, 0,
+ 0, 0, 0, 0,0x694C, 0, 0, 0,
+0x436E, 0, 0, 0, 0, 0,0x694D, 0,
+ 0, 0, 0, 0, 0, 0,0x467A, 0,
+0x303A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3263,
+0x6952,0x6953, 0, 0, 0, 0, 0, 0,
+0x694E, 0,0x3B3D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x694F,0x4742, 0, 0, 0, 0,0x6950,0x6951,
+0x695B, 0, 0, 0,0x6955,0x6958, 0, 0,
+ 0, 0, 0,0x6954, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6956, 0,0x6957,0x3C58, 0,0x6959, 0,
+0x4341, 0,0x3756,0x3342, 0, 0, 0, 0,
+ 0,0x695C, 0, 0, 0, 0,0x333F, 0,
+0x6961, 0, 0,0x695D,0x6960, 0, 0, 0,
+ 0,0x483A, 0, 0, 0, 0,0x695E, 0,
+ 0,0x695F,0x4948,0x485A,0x6962, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x427D,0x696C, 0,
+0x6968, 0, 0,0x326B, 0,0x6966, 0,0x4B2A,
+0x6967, 0, 0,0x6964, 0,0x6965,0x696A,0x696D,
+ 0, 0,0x696B, 0, 0, 0,0x6969,0x6963,
+ 0, 0, 0, 0, 0,0x4358, 0,0x6974,
+ 0,0x4C2A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6972, 0, 0, 0,0x6973, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x696E, 0, 0,0x6970, 0, 0, 0,
+0x6971, 0, 0, 0,0x696F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4066, 0,
+0x4F39,0x6978, 0,0x6979, 0, 0, 0, 0,
+0x6A21, 0,0x3F2A, 0,0x697B, 0,0x697E, 0,
+ 0, 0, 0, 0,0x6976,0x6975, 0, 0,
+0x6A22, 0, 0,0x325C, 0,0x697C, 0,0x6A23,
+ 0, 0, 0,0x697D, 0, 0, 0, 0,
+ 0,0x697A, 0,0x4433, 0,0x6977, 0, 0,
+ 0, 0, 0, 0,0x4768, 0, 0,0x6A27,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D3B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6A26, 0, 0,0x6A25,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6A2E, 0, 0, 0,0x6A28, 0, 0, 0,
+0x6A30, 0, 0, 0, 0, 0, 0,0x4D66,
+0x6A33, 0,0x6A2A, 0, 0,0x6A2B, 0, 0,
+ 0,0x6A2F, 0,0x6A32,0x6A31, 0, 0, 0,
+0x6A29, 0, 0, 0, 0,0x6A2C, 0,0x6A3D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6A36, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6A34, 0, 0,0x6A35,
+ 0, 0, 0,0x6A3A,0x6A3B, 0,0x332A, 0,
+0x3542, 0, 0,0x6A39, 0, 0, 0, 0,
+ 0, 0,0x6A24, 0, 0, 0, 0, 0,
+ 0, 0,0x6A38,0x6A3C,0x6A37, 0,0x6A3E, 0,
+ 0, 0,0x6A40,0x6A3F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A42,0x6A41,
+0x695A, 0, 0, 0,0x6A46, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A43, 0,
+ 0, 0, 0,0x6A44, 0, 0,0x6A45, 0,
+0x6A47, 0, 0, 0, 0,0x376C, 0,0x6A49,
+ 0,0x6A48, 0,0x3D30, 0, 0, 0, 0,
+ 0,0x3954,0x5E27, 0, 0, 0, 0,0x6A4A,
+0x3D51, 0, 0, 0,0x3339, 0,0x6A4B, 0,
+0x3152, 0,0x3E57,0x6A4C, 0, 0,0x3955,0x6A4D,
+0x3061, 0, 0, 0, 0,0x493D, 0, 0,
+0x6A4E, 0, 0, 0, 0,0x3F6A, 0,0x6A55,
+ 0, 0,0x6A52, 0,0x436F, 0, 0, 0,
+ 0, 0,0x6A53,0x6A50,0x365E, 0,0x6A4F,0x6A56,
+ 0, 0, 0, 0, 0,0x3736, 0, 0,
+0x425E, 0,0x6A5C, 0, 0, 0, 0,0x6A58,
+ 0, 0, 0,0x4235,0x6A57, 0,0x6A5A, 0,
+ 0, 0, 0,0x6A51, 0, 0, 0,0x6A5B,
+ 0,0x6A5D, 0, 0, 0, 0, 0, 0,
+0x486F, 0, 0,0x6A59, 0,0x6A5E,0x6A60, 0,
+ 0,0x3853,0x6A54, 0,0x3041, 0, 0, 0,
+ 0, 0, 0, 0,0x6A5F, 0,0x3A5B,0x4E76,
+0x6A61,0x6A62,0x4175, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4E22, 0, 0, 0,
+ 0,0x6A63,0x4D35, 0, 0,0x6A64,0x6A65, 0,
+ 0,0x4A64,0x6A66, 0,0x3A40, 0,0x4E23, 0,
+ 0, 0, 0, 0, 0,0x6A6B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6A6C,
+0x3E58,0x6A6A, 0, 0, 0,0x4D67,0x6A67, 0,
+ 0,0x6A69,0x403D,0x3F7E, 0, 0, 0,0x6A68,
+ 0,0x6A6D, 0, 0,0x4A23, 0, 0,0x6A6F,
+ 0,0x6A6E, 0, 0, 0,0x336C, 0,0x4B2B,
+0x6A70, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6A7C,0x6A72, 0, 0, 0, 0,
+ 0, 0,0x6A73, 0, 0, 0, 0,0x6A74,
+0x6A75, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6A79, 0,0x6A7A, 0, 0,
+0x6A78, 0, 0, 0, 0, 0,0x6A76, 0,
+0x6A71,0x6A77, 0, 0, 0, 0, 0, 0,
+ 0,0x6A7B,0x7037, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3228, 0, 0, 0, 0,
+ 0, 0, 0,0x6A7E,0x365F,0x6A7D, 0, 0,
+ 0,0x6B22, 0,0x6B21, 0, 0, 0,0x6B24,
+ 0, 0,0x6B23, 0,0x6B25, 0, 0,0x3D31,
+ 0,0x6B26, 0, 0,0x6B27, 0, 0, 0,
+ 0, 0, 0,0x6B28,0x403E, 0,0x4D57, 0,
+0x6B29, 0, 0,0x4A24,0x4746,0x6B2A, 0,0x6B2B,
+0x382B, 0, 0, 0,0x352C, 0, 0, 0,
+0x6B2C, 0, 0,0x3B6B,0x4741,0x6B2D, 0,0x3350,
+ 0, 0, 0, 0, 0, 0,0x6B2E, 0,
+ 0, 0, 0,0x6B30,0x4D77, 0,0x6B2F,0x3F46,
+ 0,0x6B31, 0, 0,0x6B32, 0, 0,0x6B33,
+0x3451, 0, 0, 0, 0, 0, 0,0x6B34,
+ 0, 0,0x6B35, 0,0x6B36,0x6B37, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3351,
+ 0, 0, 0, 0, 0, 0, 0,0x6B38,
+ 0,0x6B39,0x6B3A, 0, 0, 0, 0, 0,
+0x3272, 0, 0,0x3F28,0x6B3B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B3C, 0, 0, 0,0x6B3D, 0, 0,
+ 0, 0, 0, 0, 0,0x3840, 0,0x447B,
+0x6B3E, 0, 0, 0, 0,0x3757, 0,0x3F56,
+ 0,0x6B41, 0,0x4624, 0,0x6B40, 0, 0,
+0x3731, 0, 0,0x6B3F,0x4277,0x352D, 0, 0,
+0x6B42, 0,0x6B43, 0,0x3E59, 0, 0, 0,
+0x376D, 0,0x6B44, 0, 0, 0, 0,0x4B2C,
+ 0, 0,0x405F, 0, 0, 0,0x3576, 0,
+0x4C75,0x414A, 0,0x6B45, 0, 0, 0,0x3F47,
+0x4370,0x3E5A, 0, 0, 0, 0,0x6B46, 0,
+ 0, 0, 0,0x6B49, 0,0x6B4A, 0, 0,
+ 0, 0, 0, 0, 0,0x3A3E,0x4242,0x6B48,
+ 0,0x3E5B,0x493E, 0, 0, 0, 0, 0,
+0x6B47, 0, 0,0x3B6C, 0,0x3153, 0,0x6B4E,
+0x3758, 0, 0,0x3B6E, 0, 0,0x3B6D, 0,
+0x4F4D,0x6B4D,0x6B4C,0x4127, 0,0x354D,0x4F43,0x333A,
+0x3E5C, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B4B, 0, 0, 0, 0, 0,0x6B50,
+ 0,0x6B51,0x6B4F, 0,0x3858, 0,0x4D40, 0,
+ 0,0x3B6F,0x4727, 0, 0, 0,0x6B54, 0,
+0x4040, 0,0x4342, 0, 0,0x4D36, 0,0x6B57,
+ 0, 0, 0,0x386C, 0,0x403F,0x6B53, 0,
+0x6B58,0x386D,0x6B55,0x6B56, 0,0x6B52, 0, 0,
+ 0,0x4062,0x4649, 0, 0,0x432F, 0,0x325D,
+ 0, 0, 0, 0, 0, 0,0x4870, 0,
+ 0,0x3543, 0, 0,0x4434, 0, 0,0x6B5B,
+ 0,0x6B59, 0, 0,0x434C, 0, 0, 0,
+0x4041,0x3452,0x6B5A, 0,0x3F5B, 0, 0,0x4E4A,
+ 0, 0, 0,0x4F40, 0, 0, 0,0x6B5C,
+0x6B67,0x4435, 0,0x6B66, 0,0x6B63,0x6B6B,0x6B64,
+ 0,0x6B60, 0,0x447C,0x6B5F, 0, 0, 0,
+0x6B5D, 0,0x4D21,0x3B70, 0, 0,0x6B61, 0,
+0x6B5E, 0, 0, 0,0x6B65,0x3D74, 0,0x3841,
+ 0, 0, 0,0x427A, 0,0x4B45,0x315A,0x3062,
+ 0,0x4625, 0, 0,0x6B69, 0, 0, 0,
+ 0,0x6B68, 0,0x4666, 0,0x6B6D, 0, 0,
+ 0,0x6B62, 0,0x6B6C,0x6B6E, 0,0x382C,0x6B6A,
+0x3956, 0,0x3C55, 0, 0,0x6B6F,0x4D58, 0,
+ 0, 0, 0,0x6B72, 0,0x6B75, 0, 0,
+0x6B73,0x4935, 0, 0, 0, 0, 0, 0,
+0x6B70, 0, 0, 0, 0, 0,0x3660, 0,
+ 0, 0, 0,0x6B74, 0, 0,0x6B76, 0,
+ 0, 0, 0, 0, 0, 0,0x6B7A, 0,
+ 0,0x6B77, 0,0x6B79,0x6B78, 0, 0, 0,
+ 0, 0, 0,0x6B7B, 0,0x3C31, 0,0x6B7D,
+0x6B7C,0x4968, 0, 0,0x6C21, 0, 0, 0,
+ 0, 0, 0,0x3759, 0, 0, 0, 0,
+0x6B7E,0x6C22, 0, 0,0x6C23,0x3544,0x6641,0x3E79,
+ 0,0x6C24, 0, 0,0x386E, 0, 0, 0,
+ 0, 0,0x6C25, 0, 0,0x6C26, 0, 0,
+0x3B3E, 0, 0, 0, 0, 0, 0,0x5A4E,
+ 0,0x6C27, 0,0x6C28, 0,0x3D32, 0,0x6C29,
+0x6C2A, 0, 0,0x6C2B, 0, 0,0x6C2C,0x6C2D
+};
+
+/* page 36 0x8C37-0x8D16 */
+static uint16 tab_uni_jisx020836[]={
+0x432B, 0, 0,0x6C2E, 0, 0, 0, 0,
+0x6C30, 0,0x6C2F, 0, 0, 0, 0,0x4626,
+ 0,0x6C31, 0,0x4B2D, 0,0x6C32, 0,0x6C33,
+ 0,0x6C34, 0, 0, 0, 0,0x6C35, 0,
+ 0, 0, 0,0x465A, 0, 0, 0, 0,
+ 0, 0,0x3E5D,0x6C36, 0, 0, 0, 0,
+ 0, 0, 0,0x396B,0x502E,0x6C37, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C38,0x493F,0x6C39, 0,0x6C41, 0, 0,
+ 0, 0, 0,0x6C3A, 0, 0,0x6C3C, 0,
+ 0, 0,0x6C3B,0x6C3D, 0,0x4B46,0x6C3E,0x6C3F,
+ 0, 0, 0, 0, 0,0x6C40, 0, 0,
+ 0,0x6C42, 0, 0, 0, 0,0x332D,0x4467,
+ 0,0x4969,0x3A62,0x3957, 0, 0, 0, 0,
+0x494F,0x325F,0x484E,0x6C45,0x3453,0x4055,0x6C44,0x6C49,
+0x4379,0x4C63, 0,0x6C47,0x6C48,0x352E, 0,0x6C4A,
+0x4763,0x425F, 0, 0,0x4871,0x453D,0x6C46, 0,
+0x4B47,0x326C,0x6C4C,0x4F28,0x4442,0x4F45, 0, 0,
+0x3B71,0x6C4B, 0,0x4231, 0, 0,0x6C5C,0x4128,
+ 0, 0,0x4678, 0,0x4950, 0, 0, 0,
+ 0, 0, 0,0x6C4F,0x3B3F,0x3B72, 0,0x3E5E,
+ 0,0x4765, 0,0x382D,0x6C4E,0x6C4D, 0,0x496A,
+ 0, 0, 0,0x3C41, 0, 0,0x4552, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C51,0x6C52,0x3958,0x6C50, 0,
+ 0, 0, 0, 0, 0,0x6C53,0x6C54, 0,
+0x6C56,0x4223, 0,0x6C55,0x3466, 0,0x6C58, 0,
+0x6C57,0x6C59, 0, 0,0x6C5B,0x6C5D, 0,0x6C5E
+};
+
+/* page 37 0x8D64-0x8F64 */
+static uint16 tab_uni_jisx020837[]={
+0x4056, 0,0x3C4F,0x6C5F, 0, 0, 0,0x3352,
+ 0,0x6C60, 0, 0,0x4176,0x6C61, 0,0x6C62,
+0x496B, 0, 0,0x352F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C63, 0, 0,
+ 0,0x4436, 0, 0, 0, 0,0x315B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C71,
+ 0, 0, 0, 0,0x3F76, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x422D,
+ 0, 0, 0, 0, 0, 0,0x6C67, 0,
+ 0, 0,0x6C66, 0, 0, 0,0x6C65, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6C6D,
+0x6C6B, 0, 0,0x6C68, 0, 0, 0, 0,
+ 0, 0,0x6C6A, 0, 0, 0,0x6C69,0x6C6C,
+ 0,0x3577, 0,0x6C70, 0,0x4057, 0,0x6C71,
+ 0, 0, 0, 0,0x3859, 0,0x6C6E,0x6C6F,
+ 0, 0, 0,0x4F29, 0, 0, 0,0x4437,
+ 0,0x4129, 0, 0, 0, 0, 0, 0,
+0x6C72, 0, 0,0x6C75, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C73,0x6C74,0x4D59, 0,
+ 0, 0, 0,0x4627,0x6C78, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C76,0x6C77,0x6C79, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D29, 0,
+ 0, 0, 0, 0,0x6C7C, 0, 0, 0,
+0x6C7D,0x6C7B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6C7A, 0,
+0x447D, 0, 0,0x6D21,0x6D25,0x6D22,0x6C7E, 0,
+0x6D23, 0, 0, 0,0x6D24, 0, 0, 0,
+ 0,0x6D2B, 0, 0, 0,0x6D26, 0, 0,
+ 0, 0, 0,0x4058,0x6D28, 0, 0,0x6D2A,
+0x6D27, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D2D, 0,
+0x3D33, 0,0x6D2C, 0, 0, 0, 0, 0,
+0x6D2E, 0, 0, 0, 0,0x6D2F, 0, 0,
+0x6D32,0x6D31, 0,0x6D30, 0, 0,0x6D34,0x6D33,
+ 0,0x4C76, 0, 0, 0,0x6D36, 0,0x6D35,
+0x6D37, 0, 0, 0, 0,0x6D38, 0, 0,
+ 0, 0, 0, 0, 0,0x6D3A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D39,0x3F48,
+0x6D3B, 0, 0,0x366D,0x6D3C,0x6D3E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6D3F, 0, 0, 0, 0, 0,
+ 0,0x6D40,0x6D3D, 0,0x6D41, 0,0x3C56,0x6D42,
+0x3530,0x3733, 0, 0, 0, 0,0x382E, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6D43,
+ 0, 0, 0,0x4670, 0, 0,0x453E,0x6D44,
+ 0, 0, 0, 0, 0, 0, 0,0x6D47,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3C34, 0, 0,0x6D46,
+0x6D45,0x375A,0x6D48, 0, 0, 0, 0,0x3353,
+ 0,0x6D4A, 0, 0, 0,0x3A5C,0x6D49, 0,
+0x6D52, 0, 0, 0, 0, 0,0x6D4C,0x6D4E,
+0x4A65,0x6D4B, 0, 0, 0,0x6D4D, 0,0x6D51,
+0x6D4F,0x3531, 0,0x6D50, 0, 0, 0, 0,
+ 0, 0,0x6D53, 0, 0,0x475A,0x4E58, 0,
+ 0, 0, 0,0x3D34, 0, 0, 0,0x6D54,
+ 0, 0, 0, 0,0x4D22,0x6D56, 0,0x6D55,
+ 0, 0,0x6D59,0x4D41, 0, 0,0x6D58, 0,
+0x336D,0x6D57,0x6D5C, 0, 0,0x6D5B, 0, 0,
+0x6D5A,0x4532,0x6D5D, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6D5E, 0, 0, 0, 0,
+0x6D5F, 0, 0,0x396C, 0,0x3725,0x6D60,0x6D61,
+0x6D62};
+
+/* page 38 0x8F9B-0x9132 */
+static uint16 tab_uni_jisx020838[]={
+0x3F49,0x6D63, 0,0x3C2D,0x6D64, 0, 0, 0,
+0x6D65, 0, 0, 0,0x5221,0x517E, 0, 0,
+ 0, 0,0x6D66,0x6570,0x6D67,0x4324,0x3F2B,0x4740,
+ 0, 0, 0, 0,0x6D68, 0, 0,0x4A55,
+0x4454,0x397E, 0, 0,0x4329, 0, 0,0x312A,
+ 0,0x4B78,0x3F57, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x375E, 0, 0,0x3661, 0,
+ 0,0x4A56, 0, 0, 0, 0, 0,0x6D69,
+ 0, 0, 0, 0, 0, 0, 0,0x6D6B,
+ 0, 0,0x6D6A,0x3260, 0, 0,0x4676,0x6D6C,
+0x4777, 0,0x4533, 0,0x6D6D,0x3D52, 0, 0,
+ 0,0x6D6F, 0, 0,0x4C42,0x6D7E,0x6D71,0x6D72,
+ 0, 0,0x4449, 0, 0,0x4260,0x4177, 0,
+0x4628, 0,0x6D70,0x3555, 0, 0, 0, 0,
+0x6D79, 0,0x6D76,0x6E25,0x4629,0x4360,0x6D73, 0,
+0x447E,0x4553,0x6D74,0x6D78,0x3F60, 0,0x4767,0x444C,
+ 0, 0,0x4042,0x6D77,0x422E,0x4224,0x6D75,0x3029,
+0x4F22, 0, 0, 0,0x6D7A, 0, 0, 0,
+ 0, 0, 0,0x4261, 0, 0,0x3D35,0x3F4A,
+ 0, 0,0x6D7C,0x6D7B, 0,0x306F,0x6D7D, 0,
+ 0,0x492F, 0,0x6E27, 0, 0,0x465B,0x3F6B,
+ 0, 0,0x4359, 0,0x3678, 0,0x6E26,0x4D37,
+0x313F, 0,0x4A57,0x3261,0x6E21,0x6E22,0x6E23,0x6E24,
+0x463B,0x4323,0x3063,0x6E28, 0,0x6E29,0x7423, 0,
+ 0,0x423D, 0,0x6E2A, 0,0x3173,0x414C, 0,
+0x382F, 0,0x4D5A, 0, 0,0x6E2B,0x452C, 0,
+ 0, 0,0x4178,0x3C57,0x6E2C, 0, 0,0x6E2F,
+ 0, 0,0x3D65,0x6E2D,0x412B,0x412A, 0,0x3064,
+ 0,0x4E4B,0x6E31, 0,0x4872,0x6E33,0x6E32,0x6E30,
+0x6364,0x3454, 0, 0,0x6D6E, 0,0x6E35,0x6E34,
+ 0, 0, 0, 0,0x6E36, 0,0x4D38, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4661, 0, 0,0x4B2E, 0,0x6E37, 0,0x3C59,
+ 0, 0, 0, 0,0x6E38, 0,0x6E39, 0,
+ 0, 0,0x6E3A, 0, 0,0x4521, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x306A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3959,
+ 0, 0, 0,0x4F3A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E3E, 0, 0, 0, 0, 0,0x3734,0x6E3B,
+ 0,0x6E3C, 0, 0, 0,0x4974, 0, 0,
+ 0, 0,0x3354, 0, 0, 0, 0, 0,
+ 0, 0,0x4D39, 0,0x363F, 0, 0, 0,
+ 0, 0,0x4554, 0, 0, 0, 0,0x6E3F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6E40,
+ 0, 0, 0, 0, 0, 0,0x6E41, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4522, 0, 0,0x6E43, 0,0x6E42
+};
+
+/* page 39 0x9149-0x92B9 */
+static uint16 tab_uni_jisx020839[]={
+0x4653,0x6E44,0x3D36,0x3C60,0x475B,0x4371, 0, 0,
+ 0,0x3C72, 0,0x3F6C, 0,0x6E45, 0,0x6E46,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3F5D,0x6E47, 0,0x6E48, 0, 0, 0,
+0x6E49,0x4D6F, 0,0x3D37, 0, 0, 0, 0,
+ 0,0x6E4B,0x6E4A, 0,0x395A, 0,0x3973,0x3B40,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6E4E, 0, 0, 0, 0,0x3D66, 0,
+0x6E4D, 0,0x6E4C, 0,0x4269, 0, 0,0x386F,
+ 0,0x4043, 0, 0, 0, 0,0x4830, 0,
+ 0, 0, 0,0x3D39, 0, 0, 0, 0,
+ 0,0x6E4F, 0,0x3E5F, 0, 0, 0, 0,
+ 0,0x6E52,0x6E50, 0, 0, 0,0x6E51, 0,
+ 0, 0, 0,0x6E54,0x6E53, 0, 0,0x3E7A,
+ 0,0x6E55, 0, 0, 0, 0, 0,0x6E56,
+0x6E57, 0, 0, 0, 0,0x4850,0x3A53,0x3C61,
+0x6E58, 0,0x6E59,0x4E24,0x3D45,0x4C6E,0x4E4C,0x6E5A,
+0x3662, 0, 0, 0, 0,0x6E5B, 0,0x4523,
+ 0, 0,0x6E5E,0x3378,0x3F4B, 0,0x6E5C, 0,
+0x6E5D, 0,0x4460, 0, 0,0x4B55,0x367C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6E60,0x6E61, 0, 0,
+ 0, 0, 0,0x6E5F, 0, 0,0x6E63, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x465F,0x3343, 0, 0,
+0x6E67, 0, 0,0x6E64,0x6E66, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6E62, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6F4F, 0, 0,0x6E65, 0, 0, 0, 0,
+ 0, 0, 0,0x4E6B, 0, 0,0x385A, 0,
+ 0, 0, 0, 0, 0, 0,0x6E6F, 0,
+ 0, 0, 0,0x4534,0x6E6A, 0, 0,0x6E6D,
+0x6E6B, 0,0x6E70, 0, 0, 0, 0,0x6E71,
+ 0, 0, 0, 0, 0, 0,0x6E69, 0,
+ 0,0x6E76,0x3174, 0, 0,0x6E68, 0, 0,
+ 0,0x482D, 0,0x6E6C, 0,0x3E60, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x395B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B48, 0,0x3664,
+ 0, 0,0x3D46, 0,0x463C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x412D, 0,0x6E74, 0,0x6E6E,0x6E73, 0,0x4C43,
+ 0,0x4438,0x6E75,0x6E72, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x412C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6E79, 0,
+0x6E78};
+
+/* page 40 0x92CF-0x93E8 */
+static uint16 tab_uni_jisx020840[]={
+0x6E77, 0, 0,0x4B2F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3D7B, 0, 0,
+ 0, 0,0x6E7A,0x4A5F, 0, 0,0x3154, 0,
+ 0, 0, 0,0x4946,0x4372, 0, 0, 0,
+ 0,0x3578, 0,0x6E7C, 0,0x395D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3B2C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E7B,0x3F6D, 0, 0, 0, 0, 0, 0,
+ 0,0x3F6E,0x6F21,0x6F23, 0, 0, 0, 0,
+ 0,0x3E7B, 0,0x6F22,0x6F24, 0, 0,0x3653,
+ 0,0x4945, 0, 0,0x3C62,0x4F23, 0,0x6E7E,
+0x3A78, 0, 0,0x4F3F, 0, 0,0x6F26, 0,
+ 0, 0, 0,0x6F25,0x6F27, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6E7D, 0, 0,
+ 0, 0, 0, 0,0x4669, 0,0x4555, 0,
+ 0, 0, 0, 0, 0,0x4457, 0,0x6F2C,
+ 0, 0, 0, 0,0x4343,0x6F28, 0, 0,
+ 0,0x6F29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x372D, 0,0x6F2B,
+ 0, 0, 0, 0, 0, 0,0x3830, 0,
+ 0, 0, 0, 0, 0,0x6F2A, 0,0x3E61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3379, 0, 0,
+ 0, 0, 0, 0, 0,0x6F30, 0,0x3A3F,
+0x4179, 0, 0,0x444A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x333B, 0, 0, 0, 0,0x6F2E,0x6F2F,0x4443,
+ 0,0x6F2D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6F31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6F37, 0, 0, 0,
+ 0,0x6F3A, 0, 0, 0, 0, 0, 0,
+ 0,0x6F39,0x452D, 0, 0, 0, 0,0x6F32,
+0x6F33,0x6F36, 0, 0, 0, 0,0x6F38, 0,
+ 0, 0,0x3640, 0, 0,0x6F3B,0x6F35, 0,
+ 0,0x6F34};
+
+/* page 41 0x9403-0x9481 */
+static uint16 tab_uni_jisx020841[]={
+0x6F3F, 0, 0, 0,0x6F40, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6F41, 0, 0,
+0x6F3E,0x6F3D, 0, 0, 0,0x3E62,0x462A,0x6F3C,
+ 0, 0, 0, 0, 0, 0,0x6F45, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6F43, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6F44,0x6F42, 0,0x4278, 0,0x6F46,
+ 0, 0, 0, 0, 0, 0,0x6F47, 0,
+ 0,0x6F49, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3455,0x6F48,
+0x4C7A, 0, 0, 0, 0, 0, 0,0x6F54,
+0x6F4A, 0, 0,0x6F4D, 0,0x6F4B, 0,0x6F4C,
+ 0, 0, 0, 0, 0, 0, 0,0x6F4E,
+ 0, 0, 0, 0, 0,0x6F50, 0, 0,
+ 0, 0,0x6F51, 0,0x6F52, 0, 0, 0,
+ 0,0x6F55,0x6F53,0x6F56,0x6F58, 0,0x6F57};
+
+/* page 42 0x9577-0x95E5 */
+static uint16 tab_uni_jisx020842[]={
+0x4439, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4C67, 0,0x6F59,0x412E, 0, 0, 0,
+0x6F5A, 0,0x4A44,0x6F5B,0x332B, 0, 0, 0,
+0x313C, 0,0x3457, 0,0x3456,0x6F5C, 0,0x6F5D,
+ 0,0x6F5E,0x6F5F, 0, 0, 0, 0, 0,
+ 0,0x6F60, 0,0x3458,0x3355,0x395E,0x4836, 0,
+0x6F62,0x6F61, 0, 0, 0, 0,0x6F63, 0,
+ 0, 0, 0,0x315C, 0, 0, 0, 0,
+ 0, 0,0x6F66, 0,0x6F65,0x6F64, 0,0x6F67,
+ 0, 0, 0, 0,0x6F6A, 0, 0, 0,
+0x3047, 0, 0,0x6F68, 0,0x6F6C,0x6F6B, 0,
+ 0, 0, 0, 0, 0,0x6F6E,0x6F6D,0x6F6F,
+ 0,0x462E, 0, 0, 0,0x6F70, 0, 0,
+ 0, 0,0x6F71,0x6F73, 0, 0,0x6F72};
+
+/* page 43 0x961C-0x9874 */
+static uint16 tab_uni_jisx020843[]={
+0x496C, 0, 0, 0, 0,0x6F74, 0, 0,
+ 0, 0, 0, 0,0x6F75, 0,0x3A65, 0,
+ 0, 0,0x6F76,0x6F77, 0, 0,0x4B49, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x414B,
+ 0, 0, 0,0x3024,0x424B, 0,0x6F78, 0,
+0x496D, 0, 0, 0, 0, 0, 0,0x6F7B,
+0x6F79,0x395F, 0,0x6F7A,0x3842, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4A45,
+0x6F7D,0x7021,0x6F7E,0x7022, 0, 0,0x3121,0x3F58,
+0x3D7C,0x3459,0x7023, 0, 0, 0,0x4766, 0,
+0x7025, 0, 0, 0,0x3122, 0,0x7024,0x4444,
+ 0,0x4E4D,0x462B,0x6F7C,0x4E26, 0,0x3831, 0,
+ 0,0x4D5B, 0, 0, 0, 0, 0, 0,
+ 0,0x3679,0x4E34, 0,0x3728, 0,0x4262,0x6721,
+ 0,0x7026,0x332C,0x3F6F, 0, 0, 0, 0,
+0x3356,0x7028, 0,0x7029,0x7027,0x3764, 0,0x3A5D,
+0x3E63, 0, 0, 0,0x3123, 0, 0,0x4E59,
+ 0, 0, 0,0x702B,0x6E2E, 0,0x702A, 0,
+ 0, 0, 0, 0,0x702E,0x702C,0x702D, 0,
+0x702F, 0,0x7030,0x4E6C,0x7031,0x7032, 0,0x4049,
+0x483B, 0, 0, 0,0x3F7D,0x3467, 0, 0,
+0x4D3A,0x326D,0x3D38,0x385B, 0,0x7035, 0,0x7034,
+0x3B73,0x7036,0x7033, 0, 0,0x3B28, 0, 0,
+ 0,0x703A,0x6A2D, 0, 0,0x5256, 0,0x3F77,
+0x7038, 0, 0, 0, 0, 0,0x4E25,0x4671,
+ 0, 0, 0, 0,0x312B, 0,0x4063,0x3C36,
+ 0, 0, 0, 0,0x4A37, 0,0x3140, 0,
+ 0, 0,0x4E6D,0x4D6B, 0,0x703B, 0,0x4545,
+ 0, 0, 0, 0,0x3C7B, 0, 0, 0,
+0x703C, 0,0x703D,0x3F4C,0x703E, 0,0x4E6E, 0,
+ 0,0x7039,0x7040,0x7042, 0,0x7041, 0,0x703F,
+ 0, 0,0x7043, 0, 0,0x7044, 0, 0,
+0x417A, 0,0x3262, 0, 0, 0, 0, 0,
+0x7045, 0, 0,0x4C38, 0, 0,0x7046, 0,
+ 0, 0, 0, 0,0x7047, 0,0x4F2A, 0,
+ 0, 0, 0, 0,0x5B31,0x7048, 0, 0,
+ 0,0x7049,0x704A, 0, 0, 0,0x704E, 0,
+0x704B, 0,0x704C, 0,0x704D,0x704F, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4044, 0,
+ 0, 0,0x4C77, 0, 0,0x4045, 0, 0,
+0x7050, 0,0x4873, 0,0x7051,0x7353,0x4C4C, 0,
+0x7052, 0,0x7053, 0,0x7054,0x3357, 0,0x7056,
+ 0,0x3F59, 0, 0, 0,0x7057, 0, 0,
+0x3724, 0, 0, 0, 0,0x7058,0x705C, 0,
+0x705A, 0, 0, 0, 0,0x705B, 0, 0,
+0x3373,0x7059,0x705D, 0, 0, 0, 0,0x705E,
+ 0,0x3048, 0,0x705F,0x7060, 0, 0, 0,
+ 0, 0, 0, 0,0x3E64, 0, 0, 0,
+0x7061, 0, 0, 0,0x3547, 0, 0,0x7064,
+ 0, 0,0x7063, 0,0x7062, 0, 0,0x6B71,
+ 0,0x4A5C, 0, 0, 0, 0, 0,0x7065,
+0x7066, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7067,
+ 0, 0,0x7068, 0,0x7069, 0, 0,0x706A,
+ 0, 0, 0, 0, 0, 0, 0,0x345A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x706B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x706C,0x4723, 0, 0, 0,0x706E,0x323B,
+ 0,0x7071,0x7070, 0, 0, 0, 0,0x3124,
+ 0, 0, 0,0x3641, 0,0x4A47,0x443A,0x3A22,
+ 0,0x3960,0x3D67, 0,0x3F5C, 0, 0, 0,
+0x7073, 0, 0,0x7072,0x4D42,0x3468,0x4852,0x465C,
+ 0, 0, 0,0x3F7C,0x4E4E, 0,0x375B, 0,
+ 0, 0, 0, 0, 0,0x7076, 0, 0,
+0x7075, 0, 0, 0, 0, 0, 0, 0,
+0x4B4B,0x462C, 0, 0, 0, 0, 0, 0,
+0x3150, 0, 0,0x7077,0x7074, 0, 0,0x4951,
+0x4D6A,0x7078, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7079, 0, 0, 0, 0,0x707B,
+0x426A,0x335B,0x335C,0x707A, 0, 0, 0, 0,
+0x3469,0x3832, 0, 0,0x346A, 0, 0,0x453F,
+ 0, 0,0x4E60, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x385C, 0, 0, 0,0x707C,
+ 0, 0, 0,0x707D,0x707E,0x7121, 0,0x7123,
+0x7122};
+
+/* page 44 0x98A8-0x98C6 */
+static uint16 tab_uni_jisx020844[]={
+0x4977, 0,0x7124, 0, 0, 0, 0,0x7125,
+ 0,0x7126, 0, 0, 0, 0,0x7127, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7129,0x7128, 0,0x712A};
+
+/* page 45 0x98DB-0x9957 */
+static uint16 tab_uni_jisx020845[]={
+0x4874,0x664C, 0, 0,0x3F29, 0, 0,0x3532,
+ 0, 0, 0, 0, 0, 0,0x712B, 0,
+0x712C, 0,0x522C,0x5D3B,0x4853, 0, 0,0x307B,
+ 0,0x303B, 0, 0, 0, 0, 0, 0,
+ 0,0x3B74,0x4B30,0x3E7E, 0, 0, 0, 0,
+0x712D, 0,0x4C5F, 0, 0, 0,0x712E,0x4D5C,
+ 0,0x3142, 0, 0, 0,0x3B41, 0,0x712F,
+0x326E,0x7130, 0, 0, 0,0x7131, 0, 0,
+ 0, 0,0x7133,0x7134, 0,0x7136,0x7132, 0,
+ 0,0x7135, 0, 0, 0,0x345B, 0, 0,
+ 0,0x7137, 0,0x7138, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7139,0x713A, 0, 0, 0,0x713B,
+ 0, 0,0x713D, 0, 0, 0,0x713C, 0,
+0x713F,0x7142, 0, 0, 0,0x713E,0x7140,0x7141,
+ 0, 0,0x7143, 0,0x3642};
+
+/* page 46 0x9996-0x9A6B */
+static uint16 tab_uni_jisx020846[]={
+0x3C73,0x7144,0x7145,0x3961, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7146,
+ 0, 0,0x333E, 0, 0, 0,0x474F,0x7147,
+0x7148, 0, 0, 0, 0,0x435A,0x466B, 0,
+ 0, 0, 0, 0, 0, 0,0x7149, 0,
+ 0, 0, 0,0x477D, 0, 0,0x424C,0x3158,
+0x366E, 0,0x366F, 0, 0, 0, 0, 0,
+ 0, 0,0x4373,0x714E,0x3670, 0, 0,0x326F,
+ 0, 0,0x714D, 0, 0,0x714B, 0,0x714C,
+ 0,0x714A, 0, 0,0x7158, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x714F,
+0x7150, 0, 0,0x7151,0x7152, 0, 0, 0,
+ 0, 0,0x7154, 0, 0,0x7153, 0, 0,
+ 0,0x3D59, 0,0x7155, 0, 0, 0,0x7157,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3533,0x7156, 0, 0,0x417B,0x3833, 0, 0,
+ 0, 0, 0,0x7159, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x424D, 0, 0,0x715A, 0, 0,
+ 0, 0,0x462D, 0, 0, 0, 0, 0,
+ 0,0x715B, 0, 0, 0, 0, 0, 0,
+0x7160, 0,0x715E, 0,0x715D,0x715F, 0,0x715C,
+ 0, 0, 0, 0, 0, 0, 0,0x7162,
+ 0, 0, 0, 0, 0, 0, 0,0x7161,
+ 0,0x7164, 0, 0,0x3643,0x7163, 0, 0,
+ 0,0x7165, 0, 0,0x7166, 0,0x7168,0x7167,
+ 0, 0, 0,0x7169,0x716B,0x716A};
+
+/* page 47 0x9AA8-0x9B5A */
+static uint16 tab_uni_jisx020847[]={
+0x397C, 0, 0, 0, 0,0x716C, 0, 0,
+0x716D, 0, 0, 0, 0, 0, 0, 0,
+0x333C, 0, 0, 0,0x716E, 0, 0, 0,
+0x716F, 0, 0, 0,0x3F71, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7170,
+ 0,0x7171, 0,0x7172,0x7173, 0, 0, 0,
+0x3962, 0, 0, 0, 0, 0,0x7174,0x7175,
+ 0, 0,0x7176,0x7177, 0, 0,0x7178, 0,
+ 0, 0,0x4831,0x717A, 0,0x4926,0x717B,0x7179,
+ 0,0x717D, 0, 0,0x717C, 0, 0,0x717E,
+ 0, 0, 0,0x7221, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7222, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7223, 0,0x7224, 0, 0, 0, 0,0x7225,
+ 0, 0,0x7226,0x7227, 0,0x7228, 0,0x7229,
+0x722A,0x722B,0x722C, 0, 0, 0,0x722D,0x722E,
+ 0,0x5D35,0x722F, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6478,0x3534, 0, 0, 0,
+ 0,0x3321,0x3A32,0x7231,0x7230,0x4C25, 0, 0,
+ 0, 0, 0, 0, 0,0x7233,0x7234,0x7232,
+ 0,0x7235, 0, 0,0x4B62, 0, 0, 0,
+0x7236, 0,0x357B};
+
+/* page 48 0x9B6F-0x9C78 */
+static uint16 tab_uni_jisx020848[]={
+0x4F25, 0, 0, 0, 0,0x7237, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x7239, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x303E,
+ 0, 0,0x723A,0x4A2B,0x7238, 0, 0,0x723B,
+0x723C, 0, 0, 0, 0, 0, 0, 0,
+0x723D,0x723E, 0, 0, 0, 0, 0, 0,
+ 0,0x723F, 0,0x4B6E,0x3B2D, 0,0x3A7A,0x412F,
+ 0, 0, 0, 0, 0,0x7240, 0, 0,
+ 0, 0,0x7243, 0, 0, 0, 0, 0,
+ 0,0x7241, 0, 0, 0, 0, 0,0x7244,
+ 0, 0,0x3871,0x7242, 0, 0, 0, 0,
+0x7245, 0,0x7246,0x7247, 0,0x724B, 0,0x3B2A,
+ 0, 0, 0, 0,0x4264, 0, 0, 0,
+ 0, 0,0x724C,0x7249,0x7248,0x724A, 0, 0,
+ 0,0x375F, 0, 0, 0, 0, 0, 0,
+ 0,0x7250,0x724F,0x724E, 0, 0,0x3033, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x725A, 0,0x7256,
+ 0,0x7257,0x7253,0x7259, 0,0x7255,0x3362, 0,
+ 0,0x4F4C, 0,0x7258,0x7254,0x7252,0x7251, 0,
+ 0, 0, 0, 0,0x725C, 0, 0, 0,
+ 0, 0,0x725F, 0, 0,0x725E,0x725D, 0,
+ 0, 0, 0, 0, 0, 0,0x4949,0x725B,
+0x3073,0x7260, 0,0x7262, 0, 0, 0, 0,
+ 0, 0,0x336F,0x724D,0x3137, 0, 0,0x7264,
+ 0, 0, 0, 0, 0, 0, 0,0x7263,
+0x7261,0x432D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4B70, 0, 0, 0, 0,
+0x4E5A, 0, 0,0x7265, 0, 0, 0, 0,
+ 0,0x7266, 0, 0, 0, 0, 0, 0,
+0x7267, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7268,
+ 0,0x7269};
+
+/* page 49 0x9CE5-0x9DFD */
+static uint16 tab_uni_jisx020849[]={
+0x443B, 0,0x726A, 0,0x4837, 0,0x726F,0x726B,
+ 0, 0, 0,0x726C, 0, 0,0x4B31,0x4C44,
+ 0,0x4650, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7270, 0,
+ 0,0x7271,0x463E,0x726E,0x726D, 0, 0, 0,
+ 0,0x322A, 0, 0, 0,0x7279, 0, 0,
+0x7278, 0, 0, 0, 0, 0,0x3175, 0,
+ 0, 0,0x7276, 0, 0, 0,0x7275, 0,
+ 0,0x7273, 0,0x337B, 0,0x7272,0x3C32,0x3229,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3963, 0,
+ 0,0x727C,0x727B, 0,0x727A, 0, 0,0x7277,
+ 0,0x727D, 0,0x727E, 0, 0, 0, 0,
+ 0, 0, 0,0x7325,0x7324, 0, 0, 0,
+ 0, 0, 0, 0,0x7326, 0, 0,0x312D,
+0x7321,0x7322, 0,0x3974,0x4C39, 0, 0,0x7323,
+ 0, 0, 0, 0, 0, 0, 0,0x4B32,
+ 0, 0,0x732B, 0, 0,0x7327, 0, 0,
+ 0, 0, 0, 0, 0,0x732C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7329, 0,0x7328, 0, 0, 0,
+ 0, 0,0x375C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x732D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x732E,
+ 0, 0, 0, 0,0x732F, 0,0x732A, 0,
+ 0, 0,0x7274, 0, 0,0x7330, 0,0x4461,
+ 0, 0, 0,0x7334, 0,0x7335,0x7333, 0,
+ 0, 0, 0, 0,0x7332,0x7338, 0,0x7331,
+ 0,0x7336, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7337, 0, 0, 0,0x733A, 0,
+ 0, 0, 0, 0,0x7339, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x733C, 0, 0, 0, 0, 0, 0,
+0x733D, 0,0x733E, 0, 0,0x4F49, 0, 0,
+ 0, 0, 0,0x733B,0x426B,0x3A6D, 0, 0,
+0x733F};
+
+/* page 50 0x9E1A-0x9E1E */
+static uint16 tab_uni_jisx020850[]={
+0x7340,0x7341, 0, 0,0x7342};
+
+/* page 51 0x9E75-0x9F77 */
+static uint16 tab_uni_jisx020851[]={
+0x7343, 0, 0,0x3834,0x7344, 0, 0, 0,
+0x7345, 0,0x3C2F, 0,0x7346, 0, 0, 0,
+ 0, 0, 0,0x7347, 0, 0,0x7348,0x7349,
+ 0, 0, 0, 0,0x734C,0x734A,0x4F3C, 0,
+0x734B, 0,0x4E6F, 0, 0, 0, 0, 0,
+0x734D, 0,0x4E5B, 0, 0, 0, 0, 0,
+0x734E,0x477E, 0, 0,0x734F,0x7351, 0, 0,
+0x7352, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7350,0x396D,0x4C4D,0x4B63,0x5677,
+ 0,0x5D60,0x4B7B, 0, 0, 0, 0,0x322B,
+ 0, 0, 0, 0, 0, 0, 0,0x7354,
+0x3550,0x7355,0x7356,0x7357, 0,0x3975, 0,0x7358,
+ 0, 0, 0,0x6054,0x4C5B, 0,0x4263,0x7359,
+0x735B,0x735A, 0,0x735C, 0, 0, 0, 0,
+0x735D, 0, 0,0x735E, 0, 0, 0, 0,
+ 0, 0,0x735F, 0, 0, 0, 0,0x7360,
+ 0,0x7361,0x7362, 0,0x7363, 0,0x7364,0x7365,
+0x7366, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7367,0x7368, 0, 0, 0, 0,
+ 0,0x4524, 0, 0, 0, 0,0x385D, 0,
+0x736A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x414D,0x736B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x736C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4921, 0,
+ 0,0x736D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x736E,0x6337, 0,
+ 0,0x6C5A,0x706D, 0, 0,0x736F, 0,0x7370,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7372,0x7373,0x7374,0x4E70,0x7371, 0,
+ 0,0x7375,0x7376, 0, 0,0x7378, 0,0x7377,
+ 0, 0, 0, 0, 0,0x737A, 0, 0,
+ 0,0x737B,0x7379};
+
+/* page 52 0x9F8D-0x9FA0 */
+static uint16 tab_uni_jisx020852[]={
+0x4E36, 0, 0, 0, 0, 0, 0, 0,
+0x737C, 0, 0, 0, 0, 0, 0,0x737D,
+0x6354, 0, 0,0x737E};
+
+/* page 53 0xFF01-0xFF5D */
+static uint16 tab_uni_jisx020853[]={
+0x212A, 0,0x2174,0x2170,0x2173,0x2175, 0,0x214A,
+0x214B,0x2176,0x215C,0x2124, 0,0x2125,0x213F,0x2330,
+0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,
+0x2339,0x2127,0x2128,0x2163,0x2161,0x2164,0x2129,0x2177,
+0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,0x2348,
+0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F,0x2350,
+0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,0x2358,
+0x2359,0x235A,0x214E, 0,0x214F,0x2130,0x2132,0x212E,
+0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,0x2368,
+0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F,0x2370,
+0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,0x2378,
+0x2379,0x237A,0x2150,0x2143,0x2151};
+
+/* page 54 0xFFE3-0xFFE5 */
+static uint16 tab_uni_jisx020854[]={
+0x2131, 0,0x216F};
+
+static int
+my_uni_jisx0208_onechar(int code){
+ if ((code>=0x005C)&&(code<=0x005C))
+ return(tab_uni_jisx02080[code-0x005C]);
+ if ((code>=0x00A2)&&(code<=0x00B6))
+ return(tab_uni_jisx02081[code-0x00A2]);
+ if ((code>=0x00D7)&&(code<=0x00D7))
+ return(tab_uni_jisx02082[code-0x00D7]);
+ if ((code>=0x00F7)&&(code<=0x00F7))
+ return(tab_uni_jisx02083[code-0x00F7]);
+ if ((code>=0x0391)&&(code<=0x03C9))
+ return(tab_uni_jisx02084[code-0x0391]);
+ if ((code>=0x0401)&&(code<=0x0451))
+ return(tab_uni_jisx02085[code-0x0401]);
+ if ((code>=0x2010)&&(code<=0x203B))
+ return(tab_uni_jisx02086[code-0x2010]);
+ if ((code>=0x2103)&&(code<=0x2103))
+ return(tab_uni_jisx02087[code-0x2103]);
+ if ((code>=0x212B)&&(code<=0x212B))
+ return(tab_uni_jisx02088[code-0x212B]);
+ if ((code>=0x2190)&&(code<=0x2193))
+ return(tab_uni_jisx02089[code-0x2190]);
+ if ((code>=0x21D2)&&(code<=0x21D4))
+ return(tab_uni_jisx020810[code-0x21D2]);
+ if ((code>=0x2200)&&(code<=0x223D))
+ return(tab_uni_jisx020811[code-0x2200]);
+ if ((code>=0x2252)&&(code<=0x226B))
+ return(tab_uni_jisx020812[code-0x2252]);
+ if ((code>=0x2282)&&(code<=0x2287))
+ return(tab_uni_jisx020813[code-0x2282]);
+ if ((code>=0x22A5)&&(code<=0x22A5))
+ return(tab_uni_jisx020814[code-0x22A5]);
+ if ((code>=0x2312)&&(code<=0x2312))
+ return(tab_uni_jisx020815[code-0x2312]);
+ if ((code>=0x2500)&&(code<=0x254B))
+ return(tab_uni_jisx020816[code-0x2500]);
+ if ((code>=0x25A0)&&(code<=0x25CF))
+ return(tab_uni_jisx020817[code-0x25A0]);
+ if ((code>=0x25EF)&&(code<=0x25EF))
+ return(tab_uni_jisx020818[code-0x25EF]);
+ if ((code>=0x2605)&&(code<=0x2606))
+ return(tab_uni_jisx020819[code-0x2605]);
+ if ((code>=0x2640)&&(code<=0x2642))
+ return(tab_uni_jisx020820[code-0x2640]);
+ if ((code>=0x266A)&&(code<=0x266F))
+ return(tab_uni_jisx020821[code-0x266A]);
+ if ((code>=0x3000)&&(code<=0x301C))
+ return(tab_uni_jisx020822[code-0x3000]);
+ if ((code>=0x3041)&&(code<=0x30FE))
+ return(tab_uni_jisx020823[code-0x3041]);
+ if ((code>=0x4E00)&&(code<=0x5516))
+ return(tab_uni_jisx020824[code-0x4E00]);
+ if ((code>=0x552E)&&(code<=0x5563))
+ return(tab_uni_jisx020825[code-0x552E]);
+ if ((code>=0x557B)&&(code<=0x576A))
+ return(tab_uni_jisx020826[code-0x557B]);
+ if ((code>=0x577F)&&(code<=0x5A9B))
+ return(tab_uni_jisx020827[code-0x577F]);
+ if ((code>=0x5ABC)&&(code<=0x5D29))
+ return(tab_uni_jisx020828[code-0x5ABC]);
+ if ((code>=0x5D4B)&&(code<=0x6BF3))
+ return(tab_uni_jisx020829[code-0x5D4B]);
+ if ((code>=0x6C08)&&(code<=0x6CF3))
+ return(tab_uni_jisx020830[code-0x6C08]);
+ if ((code>=0x6D0B)&&(code<=0x7409))
+ return(tab_uni_jisx020831[code-0x6D0B]);
+ if ((code>=0x7422)&&(code<=0x7845))
+ return(tab_uni_jisx020832[code-0x7422]);
+ if ((code>=0x785D)&&(code<=0x7E9C))
+ return(tab_uni_jisx020833[code-0x785D]);
+ if ((code>=0x7F36)&&(code<=0x8358))
+ return(tab_uni_jisx020834[code-0x7F36]);
+ if ((code>=0x8373)&&(code<=0x8B9A))
+ return(tab_uni_jisx020835[code-0x8373]);
+ if ((code>=0x8C37)&&(code<=0x8D16))
+ return(tab_uni_jisx020836[code-0x8C37]);
+ if ((code>=0x8D64)&&(code<=0x8F64))
+ return(tab_uni_jisx020837[code-0x8D64]);
+ if ((code>=0x8F9B)&&(code<=0x9132))
+ return(tab_uni_jisx020838[code-0x8F9B]);
+ if ((code>=0x9149)&&(code<=0x92B9))
+ return(tab_uni_jisx020839[code-0x9149]);
+ if ((code>=0x92CF)&&(code<=0x93E8))
+ return(tab_uni_jisx020840[code-0x92CF]);
+ if ((code>=0x9403)&&(code<=0x9481))
+ return(tab_uni_jisx020841[code-0x9403]);
+ if ((code>=0x9577)&&(code<=0x95E5))
+ return(tab_uni_jisx020842[code-0x9577]);
+ if ((code>=0x961C)&&(code<=0x9874))
+ return(tab_uni_jisx020843[code-0x961C]);
+ if ((code>=0x98A8)&&(code<=0x98C6))
+ return(tab_uni_jisx020844[code-0x98A8]);
+ if ((code>=0x98DB)&&(code<=0x9957))
+ return(tab_uni_jisx020845[code-0x98DB]);
+ if ((code>=0x9996)&&(code<=0x9A6B))
+ return(tab_uni_jisx020846[code-0x9996]);
+ if ((code>=0x9AA8)&&(code<=0x9B5A))
+ return(tab_uni_jisx020847[code-0x9AA8]);
+ if ((code>=0x9B6F)&&(code<=0x9C78))
+ return(tab_uni_jisx020848[code-0x9B6F]);
+ if ((code>=0x9CE5)&&(code<=0x9DFD))
+ return(tab_uni_jisx020849[code-0x9CE5]);
+ if ((code>=0x9E1A)&&(code<=0x9E1E))
+ return(tab_uni_jisx020850[code-0x9E1A]);
+ if ((code>=0x9E75)&&(code<=0x9F77))
+ return(tab_uni_jisx020851[code-0x9E75]);
+ if ((code>=0x9F8D)&&(code<=0x9FA0))
+ return(tab_uni_jisx020852[code-0x9F8D]);
+ if ((code>=0xFF01)&&(code<=0xFF5D))
+ return(tab_uni_jisx020853[code-0xFF01]);
+ if ((code>=0xFFE3)&&(code<=0xFFE5))
+ return(tab_uni_jisx020854[code-0xFFE3]);
+ return(0);
+}
+
+
+
+/* page 0 0x007E-0x007E */
+static uint16 tab_uni_jisx02120[]={
+0x2237};
+
+/* page 1 0x00A1-0x017E */
+static uint16 tab_uni_jisx02121[]={
+0x2242, 0, 0,0x2270, 0,0x2243, 0, 0,
+0x226D,0x226C, 0, 0, 0,0x226E,0x2234, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2231,
+ 0,0x226B, 0, 0, 0, 0,0x2244,0x2A22,
+0x2A21,0x2A24,0x2A2A,0x2A23,0x2A29,0x2921,0x2A2E,0x2A32,
+0x2A31,0x2A34,0x2A33,0x2A40,0x2A3F,0x2A42,0x2A41, 0,
+0x2A50,0x2A52,0x2A51,0x2A54,0x2A58,0x2A53, 0,0x292C,
+0x2A63,0x2A62,0x2A65,0x2A64,0x2A72,0x2930,0x294E,0x2B22,
+0x2B21,0x2B24,0x2B2A,0x2B23,0x2B29,0x2941,0x2B2E,0x2B32,
+0x2B31,0x2B34,0x2B33,0x2B40,0x2B3F,0x2B42,0x2B41,0x2943,
+0x2B50,0x2B52,0x2B51,0x2B54,0x2B58,0x2B53, 0,0x294C,
+0x2B63,0x2B62,0x2B65,0x2B64,0x2B72,0x2950,0x2B73,0x2A27,
+0x2B27,0x2A25,0x2B25,0x2A28,0x2B28,0x2A2B,0x2B2B,0x2A2C,
+0x2B2C,0x2A2F,0x2B2F,0x2A2D,0x2B2D,0x2A30,0x2B30,0x2922,
+0x2942,0x2A37,0x2B37, 0, 0,0x2A36,0x2B36,0x2A38,
+0x2B38,0x2A35,0x2B35,0x2A3A,0x2B3A,0x2A3B,0x2B3B,0x2A3D,
+0x2B3D,0x2A3C, 0,0x2A3E,0x2B3E,0x2924,0x2944,0x2A47,
+0x2B47,0x2A45,0x2B45, 0, 0,0x2A46,0x2B46,0x2A44,
+0x2945,0x2926,0x2946,0x2A48,0x2B48,0x2A49,0x2B49,0x2947,
+0x2A4A,0x2B4A,0x2A4C,0x2B4C,0x2A4B,0x2B4B,0x2929,0x2949,
+0x2928,0x2948,0x2A4D,0x2B4D,0x2A4F,0x2B4F,0x2A4E,0x2B4E,
+0x294A,0x292B,0x294B,0x2A57,0x2B57, 0, 0,0x2A56,
+0x2B56,0x292D,0x294D,0x2A59,0x2B59,0x2A5B,0x2B5B,0x2A5A,
+0x2B5A,0x2A5C,0x2B5C,0x2A5D,0x2B5D,0x2A5F,0x2B5F,0x2A5E,
+0x2B5E,0x2A61,0x2B61,0x2A60,0x2B60,0x292F,0x294F,0x2A6C,
+0x2B6C,0x2A69,0x2B69,0x2A66,0x2B66,0x2A6B,0x2B6B,0x2A68,
+0x2B68,0x2A6A,0x2B6A,0x2A71,0x2B71,0x2A74,0x2B74,0x2A73,
+0x2A75,0x2B75,0x2A77,0x2B77,0x2A76,0x2B76};
+
+/* page 2 0x01CD-0x01DC */
+static uint16 tab_uni_jisx02122[]={
+0x2A26,0x2B26,0x2A43,0x2B43,0x2A55,0x2B55,0x2A67,0x2B67,
+0x2A70,0x2B70,0x2A6D,0x2B6D,0x2A6F,0x2B6F,0x2A6E,0x2B6E
+};
+
+/* page 3 0x01F5-0x01F5 */
+static uint16 tab_uni_jisx02123[]={
+0x2B39};
+
+/* page 4 0x02C7-0x02DD */
+static uint16 tab_uni_jisx02124[]={
+0x2230, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x222F,0x2232,0x2236,0x2235, 0,0x2233};
+
+/* page 5 0x0384-0x0390 */
+static uint16 tab_uni_jisx02125[]={
+0x2238,0x2239,0x2661, 0,0x2662,0x2663,0x2664, 0,
+0x2667, 0,0x2669,0x266C,0x2676};
+
+/* page 6 0x03AA-0x03CE */
+static uint16 tab_uni_jisx02126[]={
+0x2665,0x266A,0x2671,0x2672,0x2673,0x2674,0x267B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2678, 0, 0, 0, 0, 0, 0, 0,
+0x2675,0x267A,0x2677,0x2679,0x267C};
+
+/* page 7 0x0402-0x040F */
+static uint16 tab_uni_jisx02127[]={
+0x2742,0x2743,0x2744,0x2745,0x2746,0x2747,0x2748,0x2749,
+0x274A,0x274B,0x274C, 0,0x274D,0x274E};
+
+/* page 8 0x0452-0x045F */
+static uint16 tab_uni_jisx02128[]={
+0x2772,0x2773,0x2774,0x2775,0x2776,0x2777,0x2778,0x2779,
+0x277A,0x277B,0x277C, 0,0x277D,0x277E};
+
+/* page 9 0x2116-0x2122 */
+static uint16 tab_uni_jisx02129[]={
+0x2271, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x226F};
+
+/* page 10 0x4E02-0x4F19 */
+static uint16 tab_uni_jisx021210[]={
+0x3021, 0,0x3022,0x3023, 0, 0, 0, 0,
+ 0, 0,0x3024, 0, 0, 0, 0, 0,
+0x3025, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3026, 0, 0,
+ 0,0x3027,0x3028, 0, 0, 0,0x3029, 0,
+ 0,0x302A, 0, 0,0x302B,0x302C,0x302D, 0,
+ 0, 0, 0,0x302E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x302F,0x3030,
+ 0, 0,0x3031, 0, 0,0x3032, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3033,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3034, 0,0x3035, 0, 0, 0, 0, 0,
+ 0,0x3036, 0, 0, 0, 0,0x3037,0x3038,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3039,0x303A, 0, 0, 0,0x303B,
+ 0, 0, 0, 0, 0,0x303C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x303D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x303E,0x303F, 0, 0,
+ 0, 0, 0,0x3040, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3041, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3042,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3043, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3044, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3045,0x3046, 0, 0, 0, 0,0x3047,0x3048,
+0x3049, 0, 0, 0, 0, 0,0x304A, 0,
+ 0, 0, 0, 0, 0,0x304B, 0,0x304C,
+ 0,0x304D, 0,0x304E, 0, 0, 0, 0,
+ 0, 0, 0,0x304F,0x3050,0x3051,0x3052, 0,
+0x3053,0x3054, 0, 0, 0, 0,0x3055, 0,
+ 0,0x3056,0x3057, 0, 0, 0, 0, 0,
+0x3058, 0, 0,0x3059,0x305A,0x305B, 0,0x305C
+};
+
+/* page 11 0x4F2E-0x5166 */
+static uint16 tab_uni_jisx021211[]={
+0x305D, 0, 0,0x305E, 0,0x3060, 0,0x3061,
+ 0,0x3062, 0,0x3063, 0,0x3064, 0, 0,
+0x3065, 0,0x3066, 0,0x3067, 0, 0, 0,
+ 0, 0,0x3068,0x3069, 0,0x306A,0x306B, 0,
+ 0, 0, 0, 0,0x306C, 0,0x306D, 0,
+0x306E, 0,0x306F, 0, 0, 0, 0, 0,
+ 0,0x3070,0x305F, 0, 0,0x3071, 0, 0,
+ 0, 0, 0, 0,0x3072, 0,0x3073, 0,
+0x3074, 0, 0,0x3075, 0, 0, 0, 0,
+ 0,0x3076,0x3077,0x3078,0x3079, 0, 0,0x307A,
+0x307B, 0, 0,0x307C,0x307D, 0,0x307E,0x3121,
+ 0, 0, 0,0x3122,0x3123, 0,0x3124, 0,
+0x3125, 0,0x3126, 0,0x3127,0x3128,0x3129, 0,
+ 0,0x312A, 0,0x312B,0x312C, 0, 0, 0,
+0x312D,0x312E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x312F, 0, 0, 0,
+ 0,0x3130, 0,0x3131, 0,0x3132,0x3133,0x3134,
+0x3135, 0,0x3136,0x3137, 0, 0, 0,0x3138,
+0x3139, 0,0x313A,0x313B, 0,0x313C,0x313D,0x313E,
+ 0,0x313F, 0, 0,0x3140, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3141, 0,
+ 0, 0,0x3142, 0,0x3143, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3144, 0,0x3145, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3146,0x3147,
+ 0,0x3148,0x3149,0x314A, 0, 0,0x314B, 0,
+ 0,0x314C, 0, 0,0x314D, 0,0x314E, 0,
+0x314F, 0,0x3150, 0, 0,0x3151, 0, 0,
+ 0,0x3152,0x3153, 0, 0,0x3154,0x3155,0x3156,
+0x3157, 0, 0, 0,0x3158, 0, 0, 0,
+ 0,0x3159, 0, 0, 0, 0, 0, 0,
+0x315A, 0,0x315B, 0,0x315C,0x315D, 0,0x315E,
+ 0, 0, 0, 0, 0,0x3176, 0, 0,
+ 0, 0,0x315F,0x3160,0x3161, 0, 0,0x3162,
+0x3163, 0, 0, 0,0x3164, 0,0x3165, 0,
+0x3166, 0, 0,0x3167,0x3168,0x3169, 0, 0,
+ 0,0x316A, 0,0x316B, 0, 0, 0, 0,
+ 0,0x316C,0x316D, 0,0x316E,0x316F, 0, 0,
+0x3170,0x3171, 0, 0,0x3172, 0, 0,0x3173,
+ 0, 0,0x3174,0x3175, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3177, 0,0x3178,0x3179, 0,
+0x317A, 0, 0, 0,0x317B, 0, 0, 0,
+0x317C,0x317D,0x317E, 0,0x3221,0x3222,0x3223, 0,
+0x3224, 0, 0, 0, 0,0x3225,0x3226, 0,
+0x3227,0x3228,0x3229,0x322A,0x322B, 0, 0, 0,
+ 0, 0, 0, 0,0x322C, 0, 0, 0,
+ 0,0x322D,0x322E, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x322F,0x3230, 0, 0,0x3231,
+ 0, 0,0x3232, 0, 0,0x3233,0x3234, 0,
+ 0,0x3235, 0, 0, 0, 0,0x3236, 0,
+0x3237, 0,0x3238, 0, 0,0x3239,0x323A, 0,
+ 0, 0,0x323B, 0, 0, 0,0x323C,0x323D,
+ 0,0x323E, 0, 0,0x323F, 0,0x3240, 0,
+0x3241, 0,0x3242,0x3243, 0, 0, 0, 0,
+ 0,0x3244, 0,0x3245,0x3251, 0, 0, 0,
+0x3246, 0, 0, 0,0x3247, 0, 0, 0,
+0x3248, 0, 0, 0, 0,0x3249, 0, 0,
+0x324A,0x324B,0x324C, 0, 0,0x324D,0x324E,0x324F,
+0x3250, 0,0x3252, 0, 0, 0, 0, 0,
+ 0,0x3253, 0,0x3254, 0,0x3255,0x3256,0x3257,
+0x3258, 0, 0, 0, 0,0x3259, 0, 0,
+ 0,0x325A,0x325B, 0, 0, 0,0x325C,0x325D,
+ 0,0x325E, 0,0x325F, 0,0x3260,0x3261,0x3262,
+ 0, 0,0x3263,0x3264, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3265, 0, 0, 0,
+ 0, 0, 0, 0,0x3266, 0, 0, 0,
+ 0,0x3267, 0, 0, 0,0x3268, 0,0x3269,
+ 0,0x326A,0x326B, 0, 0, 0, 0, 0,
+ 0,0x326C, 0, 0, 0, 0,0x326D, 0,
+0x326E};
+
+/* page 12 0x517E-0x5515 */
+static uint16 tab_uni_jisx021212[]={
+0x326F, 0, 0, 0, 0,0x3270,0x3271, 0,
+ 0, 0, 0, 0, 0,0x3272, 0, 0,
+0x3273, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3274, 0, 0, 0, 0,0x3275,
+ 0, 0, 0,0x3276, 0,0x3277, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3278,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3279, 0,0x327A, 0,0x327B, 0,
+0x327C,0x327D, 0, 0,0x327E, 0, 0, 0,
+ 0, 0,0x3321, 0, 0, 0, 0, 0,
+ 0,0x3322, 0,0x3323,0x3324,0x3325, 0,0x3326,
+ 0, 0,0x3327, 0, 0, 0, 0, 0,
+0x3328, 0, 0, 0,0x3329, 0, 0,0x332A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x332B, 0, 0, 0,0x332C,0x332D,0x332E, 0,
+ 0,0x332F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3330,0x3331, 0, 0,0x3332,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3333,0x3334, 0,0x3335,
+0x3336, 0,0x3337, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3338, 0, 0, 0,
+ 0, 0,0x3339, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x333A,0x333B, 0, 0,0x333C,
+ 0, 0, 0, 0, 0, 0,0x333D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x333E,
+ 0, 0, 0,0x333F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3340,
+ 0,0x3341,0x3342, 0,0x3343, 0,0x3344, 0,
+ 0,0x3345,0x3346,0x3347, 0, 0, 0, 0,
+0x3348, 0, 0, 0, 0, 0, 0, 0,
+0x3349, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x334A,0x334B,0x334C, 0, 0, 0, 0,
+ 0, 0,0x334D, 0,0x334E, 0, 0,0x334F,
+ 0, 0, 0, 0,0x3350, 0,0x3351, 0,
+ 0, 0, 0, 0, 0,0x3352, 0,0x3353,
+0x3354,0x3355,0x3356, 0,0x3357, 0,0x3358, 0,
+ 0, 0, 0, 0, 0, 0,0x3359,0x335A,
+0x335B,0x335C, 0, 0, 0, 0, 0, 0,
+ 0,0x335D,0x335E, 0, 0, 0, 0, 0,
+0x335F,0x3360,0x3361, 0,0x3362,0x3363, 0,0x3364,
+ 0, 0,0x3365, 0, 0, 0,0x3366, 0,
+0x3367, 0,0x3368, 0, 0, 0,0x3369, 0,
+ 0,0x336A, 0,0x336B, 0, 0,0x336C, 0,
+0x336D, 0, 0, 0, 0,0x336E,0x336F, 0,
+ 0, 0, 0,0x3370, 0, 0, 0,0x3371,
+ 0, 0,0x3372,0x3373,0x3374, 0,0x3375, 0,
+ 0, 0,0x3376,0x3377, 0, 0,0x3378, 0,
+0x3379,0x337A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x337B, 0, 0,0x337C, 0, 0,
+ 0, 0, 0, 0,0x337D,0x337E,0x3421, 0,
+ 0, 0, 0,0x3422, 0,0x3423, 0, 0,
+ 0, 0,0x3424, 0, 0,0x3425,0x3426, 0,
+0x3427,0x3428, 0, 0, 0, 0, 0,0x3429,
+ 0,0x342A,0x342B,0x342C, 0,0x342D,0x342E,0x342F,
+ 0, 0,0x3430, 0,0x3431, 0, 0,0x3432,
+ 0, 0, 0, 0, 0, 0,0x3433,0x3434,
+0x3435, 0, 0, 0,0x3436, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3438,0x3437, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3439, 0,0x343A, 0, 0,
+ 0, 0, 0,0x343B, 0,0x343C, 0,0x343D,
+ 0, 0, 0, 0, 0, 0,0x343E,0x343F,
+ 0, 0, 0, 0,0x3440, 0, 0, 0,
+ 0, 0, 0,0x3441, 0, 0, 0, 0,
+0x3442, 0, 0, 0, 0,0x3443, 0, 0,
+ 0,0x3444,0x3445, 0, 0, 0, 0, 0,
+0x3446, 0, 0, 0, 0,0x3447,0x3448, 0,
+ 0, 0, 0,0x3449, 0, 0, 0,0x344A,
+ 0, 0, 0,0x344B, 0, 0,0x344C, 0,
+ 0, 0, 0, 0,0x344D,0x344E, 0, 0,
+ 0,0x344F, 0, 0,0x3450, 0,0x3451,0x3452,
+ 0,0x3453,0x3454, 0,0x3455, 0, 0,0x3456,
+ 0, 0,0x3457, 0, 0, 0, 0,0x3458,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3459, 0, 0,0x345A,0x345B, 0,0x345C,
+ 0, 0, 0, 0,0x345D, 0, 0,0x345E,
+0x345F, 0,0x3460, 0, 0, 0, 0, 0,
+0x3461,0x3462, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3463,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3464, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3465, 0, 0,
+ 0, 0, 0, 0,0x3466, 0, 0, 0,
+ 0, 0, 0,0x3467, 0, 0, 0, 0,
+ 0,0x3468,0x3469, 0,0x346A, 0, 0, 0,
+ 0,0x346B, 0,0x346C, 0, 0,0x346D,0x346E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x346F,0x3470, 0,
+ 0,0x3471, 0, 0, 0, 0, 0,0x3472,
+ 0,0x3473, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3474, 0, 0, 0,0x3475, 0,0x3476, 0,
+0x3477,0x3478, 0,0x3479, 0,0x347A, 0,0x347B,
+0x347C, 0, 0, 0, 0, 0,0x347D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x347E, 0,0x3521, 0,0x3522, 0,0x3523,
+ 0, 0,0x3524,0x3525, 0, 0, 0,0x3526,
+ 0, 0, 0,0x3527, 0, 0, 0,0x3528,
+0x3529, 0, 0, 0, 0, 0,0x352A, 0,
+ 0,0x352B, 0,0x352C, 0, 0, 0, 0,
+0x352D,0x352E, 0,0x352F,0x3530, 0, 0,0x3531,
+0x3532, 0, 0,0x3533, 0, 0, 0, 0,
+ 0,0x3534, 0,0x3535,0x3536,0x3537, 0, 0,
+ 0,0x3538, 0, 0, 0, 0, 0, 0,
+0x3539, 0, 0, 0,0x353A, 0, 0,0x353B,
+0x353C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x353D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x353E, 0,0x353F, 0,
+ 0,0x3540, 0, 0, 0, 0, 0, 0,
+0x3541, 0, 0, 0, 0, 0,0x3542, 0,
+0x3543,0x3544,0x3545,0x3546, 0, 0, 0,0x3547,
+ 0, 0,0x3548,0x3549, 0, 0,0x354A,0x354B,
+0x354C, 0, 0, 0, 0, 0, 0,0x354D
+};
+
+/* page 13 0x552A-0x5566 */
+static uint16 tab_uni_jisx021213[]={
+0x354E,0x354F, 0, 0, 0, 0, 0, 0,
+0x3550, 0, 0,0x3551,0x3552, 0, 0, 0,
+ 0,0x3553,0x3554,0x3555, 0, 0, 0,0x3556,
+ 0, 0, 0, 0, 0,0x3557, 0,0x3558,
+0x3559, 0, 0,0x355A, 0, 0,0x355B,0x355C,
+ 0, 0, 0, 0, 0, 0,0x355D, 0,
+0x355E,0x355F, 0, 0,0x3560, 0,0x3561,0x3562,
+ 0, 0,0x3563, 0,0x3564};
+
+/* page 14 0x557F-0x5C36 */
+static uint16 tab_uni_jisx021214[]={
+0x3565, 0,0x3566,0x3567, 0, 0, 0,0x3568,
+ 0,0x3569, 0, 0, 0, 0, 0,0x356A,
+0x356B, 0,0x356C,0x356D,0x356E,0x356F, 0, 0,
+0x3570, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3571,0x3572, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3573, 0,
+ 0, 0, 0,0x3574, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3575, 0,0x3576, 0,0x3577, 0, 0,0x3578,
+ 0, 0,0x3579, 0,0x357A,0x357B, 0,0x357C,
+ 0, 0,0x357D,0x357E,0x3621, 0, 0, 0,
+0x3622,0x3623, 0, 0,0x3624, 0, 0,0x3625,
+ 0, 0, 0,0x3626, 0, 0, 0, 0,
+ 0, 0,0x3627, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3628,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3629, 0, 0, 0, 0, 0,0x362A, 0,
+ 0,0x362B, 0,0x362C, 0, 0,0x362D,0x362E,
+0x362F,0x3630,0x3631,0x3632, 0, 0, 0, 0,
+ 0, 0,0x3633, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3634, 0, 0,
+ 0,0x3635, 0, 0,0x3636, 0,0x3637, 0,
+0x3638, 0,0x3639, 0,0x363A,0x363B,0x363C, 0,
+0x363D,0x363E,0x363F, 0,0x3640,0x3641, 0,0x3642,
+ 0, 0,0x3643, 0,0x3644, 0,0x3645, 0,
+0x3646, 0, 0, 0, 0,0x3647, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3648,
+ 0,0x3649,0x364A,0x364B,0x364C, 0, 0,0x364D,
+ 0, 0,0x364E, 0, 0, 0,0x364F, 0,
+0x3650, 0,0x3651,0x3652, 0, 0,0x3653, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3654,0x3655, 0,
+ 0,0x3656, 0, 0,0x3657,0x3658, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3659, 0,
+ 0, 0,0x365A,0x365B, 0, 0,0x365C,0x365D,
+0x365E, 0, 0, 0, 0, 0, 0,0x365F,
+0x3660,0x3661,0x3662, 0,0x3663,0x3664,0x3665, 0,
+ 0, 0,0x3666, 0,0x3667, 0, 0, 0,
+0x3668, 0, 0, 0, 0, 0, 0,0x3669,
+ 0, 0, 0, 0, 0, 0,0x366A, 0,
+ 0, 0,0x366B,0x366C,0x366D,0x3670,0x3671, 0,
+0x366E,0x366F, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3672, 0, 0,0x3673,0x3674, 0,
+0x3675, 0,0x3676, 0, 0,0x3677,0x3678,0x3679,
+0x367A,0x367B, 0, 0,0x367D, 0,0x367E, 0,
+ 0, 0,0x367C, 0, 0, 0, 0,0x3721,
+0x3722, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3723,0x3724, 0, 0, 0, 0,
+0x3725, 0, 0,0x3726, 0,0x3727, 0, 0,
+ 0, 0,0x3728, 0, 0, 0,0x3729, 0,
+ 0, 0, 0,0x372A,0x372B, 0,0x372C, 0,
+ 0,0x372D, 0,0x372E,0x372F,0x3730,0x3731, 0,
+ 0, 0,0x3732,0x3733, 0,0x3734, 0,0x3735,
+0x3736, 0, 0, 0,0x3737,0x3738, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3739,0x373A,
+0x373B, 0, 0, 0, 0, 0,0x373C,0x373D,
+ 0, 0, 0, 0, 0,0x373E,0x373F, 0,
+ 0, 0, 0,0x3740, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3741, 0, 0,0x3742, 0,
+0x3743,0x3744, 0, 0,0x3745, 0,0x3746,0x3747,
+0x3748,0x3749,0x374A, 0,0x374B,0x374C,0x374D, 0,
+0x374E, 0,0x374F,0x3750,0x3751,0x3752, 0,0x3753,
+ 0, 0,0x3754, 0,0x3755, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3756, 0, 0,
+ 0, 0, 0, 0, 0,0x3757,0x3760, 0,
+0x3758, 0,0x3759,0x375A, 0,0x375B,0x375C,0x375D,
+0x375E, 0,0x375F, 0, 0, 0, 0, 0,
+0x3761,0x3762,0x3763, 0, 0,0x3764, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3765, 0, 0, 0, 0,0x3766, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3767,0x3768, 0, 0, 0,0x3769, 0, 0,
+0x376A, 0, 0, 0, 0, 0,0x376B, 0,
+ 0, 0, 0, 0, 0, 0,0x376C,0x376D,
+ 0, 0,0x377E, 0, 0,0x376E, 0,0x376F,
+0x3770, 0,0x3771, 0, 0, 0,0x3772, 0,
+ 0,0x3773, 0, 0, 0, 0,0x3774,0x3775,
+ 0,0x3776, 0, 0, 0, 0,0x3777,0x3778,
+0x3779, 0, 0, 0,0x377A,0x377B, 0, 0,
+ 0,0x377C,0x377D, 0, 0,0x3821,0x3822, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3823, 0, 0,0x3824,
+0x3825,0x3826, 0, 0, 0, 0, 0,0x3827,
+0x3828, 0, 0, 0, 0, 0,0x3829, 0,
+ 0, 0, 0,0x382A, 0, 0, 0, 0,
+ 0, 0,0x382B, 0, 0, 0, 0, 0,
+0x382C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x382D, 0, 0,0x382E,0x382F, 0,
+0x3830,0x3831, 0, 0, 0, 0,0x3832, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3833, 0,0x3834, 0, 0,0x3835, 0, 0,
+0x3836,0x3837, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3838, 0, 0, 0,0x3839, 0, 0,
+0x383A,0x383B,0x383C, 0, 0, 0, 0, 0,
+0x383D,0x383E,0x383F,0x3840, 0,0x3841,0x3842, 0,
+0x3843,0x3844, 0, 0, 0,0x3845, 0,0x3846,
+ 0, 0, 0, 0, 0, 0,0x3847, 0,
+ 0,0x3848,0x3849,0x384A, 0, 0, 0,0x384B,
+ 0, 0,0x384C, 0, 0, 0, 0, 0,
+ 0, 0,0x384D,0x384E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3850, 0, 0,
+ 0, 0, 0,0x3851, 0,0x384F, 0, 0,
+ 0,0x3852, 0, 0, 0, 0,0x3853,0x3854,
+ 0,0x3855, 0,0x3856, 0,0x3857, 0,0x3858,
+ 0, 0, 0,0x3859, 0, 0,0x385A, 0,
+ 0, 0,0x385B,0x385C, 0, 0, 0, 0,
+ 0, 0,0x385D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x385E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x385F,0x3860,
+ 0, 0, 0, 0,0x3861,0x3862, 0, 0,
+ 0, 0, 0,0x3863,0x3864,0x3865, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3867, 0,
+ 0, 0,0x3868, 0,0x3869,0x386A, 0, 0,
+ 0,0x386B, 0, 0, 0, 0, 0, 0,
+0x386C,0x386D, 0, 0,0x386E, 0,0x386F,0x3870,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3871, 0, 0, 0,0x3872, 0, 0,0x3873,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3874,0x3875, 0, 0, 0,
+ 0, 0,0x3876, 0,0x3877, 0,0x3878,0x3879,
+0x387A, 0,0x387B, 0,0x387C, 0, 0, 0,
+ 0, 0, 0, 0,0x387D, 0,0x387E, 0,
+0x3921, 0, 0,0x3922, 0, 0,0x3923,0x3924,
+ 0, 0,0x3925, 0,0x3926,0x3927, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3928,0x3929, 0,0x392A,
+ 0, 0, 0,0x392B, 0, 0,0x392C, 0,
+0x392D, 0, 0, 0, 0, 0, 0, 0,
+0x392E, 0, 0, 0, 0,0x392F, 0, 0,
+0x3930, 0, 0, 0, 0, 0,0x3931,0x3932,
+0x3933,0x3934, 0, 0,0x3935, 0, 0, 0,
+0x3936, 0, 0,0x3937, 0,0x3938, 0, 0,
+ 0, 0,0x3939, 0,0x393A,0x393B, 0, 0,
+ 0,0x393C, 0,0x393D, 0, 0,0x393E, 0,
+ 0, 0, 0,0x393F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3940,0x3941,
+0x3942, 0, 0, 0,0x3943,0x3944, 0, 0,
+0x3945, 0, 0, 0, 0, 0, 0,0x3946,
+0x3947, 0,0x3948,0x3949, 0,0x394A, 0, 0,
+0x394B, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x394C, 0, 0, 0,0x394D, 0, 0,
+ 0, 0, 0, 0, 0,0x394E,0x394F,0x3950,
+ 0, 0, 0,0x3951,0x3952, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3953,
+ 0, 0, 0, 0,0x3954,0x3955, 0, 0,
+0x3956,0x3957, 0,0x3958, 0, 0,0x3959, 0,
+ 0,0x395A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x395B,0x395C, 0,
+0x395D,0x395E, 0, 0, 0,0x395F, 0, 0,
+ 0,0x3960, 0, 0, 0, 0,0x3961, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3962,
+ 0, 0, 0, 0,0x3963, 0,0x3964, 0,
+0x3965, 0, 0, 0, 0, 0,0x3966, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3967, 0, 0,0x3968,0x3969, 0, 0,0x396A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x396B, 0, 0, 0,
+ 0,0x396C, 0, 0,0x396D, 0, 0,0x396E,
+ 0, 0,0x396F, 0, 0,0x3970, 0,0x3971,
+0x3972,0x3973, 0,0x3974, 0, 0, 0, 0,
+0x3975, 0, 0, 0, 0,0x3976, 0, 0,
+ 0, 0,0x3977,0x3978,0x3979, 0,0x397A, 0,
+ 0,0x397B, 0,0x397C,0x397D, 0, 0, 0,
+0x397E, 0, 0, 0, 0,0x3A21, 0,0x3A22,
+ 0,0x3A23, 0, 0, 0, 0, 0, 0,
+0x3A24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3A25, 0,0x3A26, 0, 0,
+ 0,0x3A27, 0, 0, 0, 0,0x3A28, 0,
+ 0, 0, 0,0x3A29, 0, 0, 0,0x3A2A,
+ 0, 0, 0, 0, 0, 0,0x3A2B,0x3A2C,
+ 0, 0, 0, 0, 0, 0,0x3A2D, 0,
+ 0,0x3A2E,0x3A2F, 0, 0, 0, 0, 0,
+ 0,0x3A30, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3A31, 0,0x3A33, 0,0x3A34, 0,0x3A35, 0,
+ 0, 0,0x3A36, 0, 0, 0,0x3A37, 0,
+ 0, 0, 0, 0, 0, 0,0x3A38, 0,
+ 0, 0, 0, 0, 0,0x3A32, 0, 0,
+ 0,0x3A39, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3A3A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3A3B,0x3A3C, 0, 0,
+ 0, 0, 0,0x3A3D, 0, 0, 0,0x3A3E,
+ 0, 0, 0, 0, 0, 0, 0,0x3A3F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3A40, 0, 0, 0, 0, 0,0x3A41,
+0x3A42, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3A43,0x3A44,0x3A45,
+0x3A46, 0,0x3A47, 0, 0,0x3A48, 0,0x3A49,
+ 0, 0, 0,0x3A4A, 0, 0, 0,0x3A4B,
+ 0,0x3A4C,0x3A4D, 0,0x3A4E,0x3A4F, 0,0x3A50,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3A51,0x3A52, 0, 0,0x3A53,0x3A54, 0,
+0x3A55, 0,0x3A56,0x3A57, 0, 0, 0, 0,
+0x3A58, 0, 0,0x3A59, 0,0x3A5A, 0, 0,
+ 0,0x3A5B,0x3A5C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3A5D, 0,
+0x3A5E, 0, 0, 0, 0, 0, 0,0x3A5F,
+0x3A60,0x3A61,0x3A62,0x3A63, 0, 0, 0, 0,
+ 0,0x3A64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3A65, 0,0x3A66, 0, 0,0x3A67, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3A68, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3A69, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3A6A, 0, 0, 0, 0, 0, 0,0x3A6B,
+0x3A6C, 0, 0, 0,0x3A6D, 0, 0,0x3A6E,
+ 0, 0,0x3A6F, 0,0x3A70,0x3A71, 0,0x3A72,
+ 0,0x3A73, 0,0x3A74, 0, 0,0x3A75,0x3A76
+};
+
+/* page 15 0x5C59-0x5EEB */
+static uint16 tab_uni_jisx021215[]={
+0x3A77,0x3A78, 0,0x3A79, 0, 0, 0, 0,
+ 0,0x3A7A,0x3A7B, 0, 0, 0,0x3A7C,0x3A7D,
+0x3A7E, 0, 0, 0,0x3B21, 0, 0,0x3B22,
+ 0, 0, 0,0x3B23,0x3B24, 0, 0, 0,
+ 0,0x3B25,0x3B26,0x3B27,0x3B28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B29,0x3B2A,
+ 0,0x3B2B, 0, 0, 0, 0,0x3B2C, 0,
+ 0,0x3B2D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3B2E, 0,0x3B2F,0x3B30,
+ 0,0x3B31,0x3B32, 0, 0,0x3B33, 0, 0,
+ 0,0x3B34, 0, 0, 0, 0, 0, 0,
+ 0,0x3B35, 0,0x3B36,0x3B37, 0, 0, 0,
+ 0,0x3B38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3B39, 0,0x3B3A, 0, 0, 0, 0, 0,
+ 0,0x3B3B, 0, 0, 0, 0,0x3B3D, 0,
+ 0, 0, 0, 0,0x3B3C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3B3E, 0, 0,
+0x3B3F,0x3B40, 0,0x3B41, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3B42, 0, 0, 0, 0,0x3B43, 0, 0,
+ 0, 0, 0, 0,0x3B44, 0, 0, 0,
+ 0,0x3B45, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3B47,0x3B48, 0,0x3B49,0x3B4A, 0,
+ 0, 0,0x3B46, 0, 0, 0, 0, 0,
+0x3B4B, 0, 0,0x3B4C, 0, 0, 0, 0,
+0x3B4D, 0, 0, 0,0x3B4E, 0,0x3B4F, 0,
+ 0,0x3B50,0x3B51, 0, 0,0x3B52, 0,0x3B53,
+ 0,0x3B57, 0, 0, 0, 0, 0, 0,
+0x3B55, 0, 0, 0,0x3B54, 0, 0, 0,
+0x3B56, 0, 0, 0, 0, 0,0x3B58,0x3B59,
+0x3B5A,0x3B5B, 0,0x3B5C, 0, 0, 0, 0,
+ 0,0x3B5D, 0, 0,0x3B5E, 0, 0,0x3B5F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3B60,0x3B61, 0, 0, 0,0x3B62,0x3B63, 0,
+0x3B64, 0,0x3B65, 0, 0, 0, 0,0x3B66,
+ 0,0x3B67, 0, 0, 0, 0, 0, 0,
+ 0,0x3B68,0x3B69,0x3B6A,0x3B6B, 0, 0, 0,
+0x3B6C, 0,0x3B6D, 0, 0, 0,0x3B6E,0x3B6F,
+ 0, 0, 0, 0, 0, 0,0x3B70, 0,
+ 0, 0,0x3B71, 0, 0, 0, 0,0x3B72,
+ 0,0x6674, 0,0x3B73, 0, 0, 0,0x3B74,
+0x3B75, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3B76, 0, 0, 0,0x3B77, 0,
+ 0, 0,0x3B78, 0, 0,0x3B7A, 0,0x3B79,
+ 0, 0, 0, 0, 0, 0, 0,0x3B7B,
+0x3B7C, 0, 0, 0, 0, 0, 0,0x3B7D,
+ 0, 0, 0,0x3B7E, 0, 0, 0, 0,
+0x3C21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C22,
+0x3C23, 0, 0, 0, 0, 0, 0,0x3C24,
+ 0, 0, 0, 0, 0, 0,0x3C25, 0,
+ 0, 0, 0, 0,0x3C26, 0, 0, 0,
+ 0,0x3C27, 0,0x3C28,0x3C29, 0, 0,0x3C2A,
+ 0, 0, 0, 0, 0, 0,0x3C2B,0x3C2C,
+ 0, 0, 0, 0, 0, 0, 0,0x3C2E,
+ 0, 0, 0, 0, 0,0x3C2D, 0, 0,
+ 0,0x3C2F, 0, 0,0x3C30, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C31, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3C34, 0,0x3C32, 0, 0, 0, 0,0x3C33,
+0x3C35, 0, 0, 0, 0,0x3C36, 0,0x3C37,
+ 0, 0,0x3C38,0x3C39, 0,0x3C3A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C3B,
+ 0,0x3C3C,0x3C3D,0x3C3E,0x3C3F,0x3C40, 0,0x3C41,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C42,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3C43, 0, 0,0x3C44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3C45, 0,0x3C46,0x3C47, 0, 0,0x3C48,
+ 0,0x3C49, 0,0x3C4A, 0, 0, 0, 0,
+0x3C4B, 0,0x3C4C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3C4D,0x3C4E,0x3C4F, 0,
+ 0, 0, 0, 0, 0,0x3C50, 0, 0,
+ 0, 0,0x3C52,0x3C51, 0,0x3C53, 0, 0,
+0x3C54,0x3C55, 0,0x3C56,0x3C57, 0, 0, 0,
+ 0, 0, 0,0x3C58, 0,0x3C59, 0, 0,
+ 0, 0, 0, 0,0x3C5A, 0, 0, 0,
+ 0, 0,0x3C5B};
+
+/* page 16 0x5F02-0x6149 */
+static uint16 tab_uni_jisx021216[]={
+0x3C5C, 0, 0, 0,0x3C5D,0x3C5E,0x3C5F, 0,
+ 0, 0, 0, 0,0x3C60, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C61,
+ 0, 0,0x3C62,0x3C63, 0, 0, 0,0x3C64,
+0x3C65,0x3C66,0x3C67, 0, 0, 0,0x3C68, 0,
+ 0,0x3C69,0x3C6A, 0,0x3C6B, 0,0x3C6C, 0,
+ 0, 0,0x3C6D, 0,0x3C6E, 0, 0, 0,
+ 0,0x3C6F, 0,0x3C70, 0,0x3C71,0x3C72, 0,
+ 0, 0,0x3C73,0x3C74, 0,0x3C75, 0, 0,
+ 0, 0, 0,0x3C76, 0, 0,0x3C77, 0,
+ 0, 0,0x3C78, 0, 0, 0,0x3C79, 0,
+ 0,0x3C7A, 0, 0, 0, 0,0x3C7B, 0,
+ 0,0x3C7C,0x3C7D, 0, 0,0x3C7E, 0, 0,
+ 0, 0, 0, 0, 0,0x3D21, 0, 0,
+0x3D22, 0,0x3D23,0x3D24, 0, 0,0x3D25, 0,
+0x3D26, 0, 0,0x3D27,0x3D28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3D29,
+ 0, 0, 0,0x3D2A, 0,0x3D2B, 0, 0,
+ 0, 0, 0, 0,0x3D2C, 0, 0, 0,
+ 0, 0,0x3D2D,0x3D2E, 0, 0, 0, 0,
+0x3D2F, 0,0x3D32, 0, 0,0x3D30, 0, 0,
+ 0,0x3D31,0x3D33, 0, 0,0x3D34,0x3D35,0x3D36,
+ 0, 0, 0, 0, 0, 0,0x3D37, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3D38, 0, 0,0x3D39,0x3D3A,0x3D3B,
+ 0,0x3D3C, 0, 0, 0, 0,0x3D3D,0x3D3E,
+0x3D3F,0x3D40,0x3D41, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3D42, 0, 0,0x3D43,
+0x3D44, 0, 0, 0, 0, 0,0x3D45,0x3D46,
+0x3D47, 0,0x3D48,0x3D49,0x3D4A,0x3D4B, 0, 0,
+0x3D4C,0x3D4D, 0, 0,0x3D4E, 0, 0, 0,
+0x3D4F, 0,0x3D50, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3D51, 0, 0,
+0x3D52, 0, 0,0x3D53, 0, 0, 0, 0,
+ 0,0x3D54,0x3D55, 0, 0,0x3D56,0x3D57, 0,
+0x3D58, 0, 0, 0, 0,0x3D59, 0, 0,
+ 0, 0,0x3D5A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3D5B, 0, 0, 0, 0,
+ 0,0x3D5C, 0,0x3D5D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D5E, 0,
+ 0, 0, 0, 0, 0,0x3D5F,0x3D60,0x3D61,
+ 0, 0,0x3D62, 0, 0, 0, 0,0x3D63,
+ 0, 0,0x3D64, 0,0x3D65,0x3D66, 0, 0,
+ 0, 0, 0,0x3D67, 0, 0, 0,0x3D68,
+ 0, 0, 0, 0, 0,0x3D69, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3D6A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3D6B,0x3D6C, 0, 0,
+0x3D6D, 0, 0, 0,0x3D6E, 0,0x3D6F, 0,
+0x3D70, 0, 0, 0,0x3D71, 0, 0,0x3D72,
+ 0,0x3D73, 0,0x3D74, 0, 0,0x3D75, 0,
+ 0, 0, 0,0x3D76,0x3D77, 0, 0, 0,
+0x3D78, 0,0x3D79,0x3D7A, 0, 0,0x3D7B, 0,
+ 0, 0, 0, 0, 0, 0,0x3D7C,0x3D7D,
+ 0, 0, 0, 0, 0,0x3D7E, 0, 0,
+ 0,0x3E21, 0, 0,0x3E22, 0, 0, 0,
+0x3E23, 0,0x3E24, 0, 0, 0,0x3E25,0x3E26,
+0x3E27,0x3E28, 0, 0,0x3E29,0x3E2A, 0, 0,
+ 0, 0,0x3E2B,0x3E2C, 0, 0, 0,0x3E2D,
+ 0,0x3E2E, 0,0x3E2F,0x3E30, 0, 0, 0,
+0x3E31, 0, 0,0x3E32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3E33, 0, 0,0x3E34, 0, 0,0x3E35, 0,
+ 0, 0,0x3E36,0x3E37, 0, 0, 0, 0,
+0x3E38, 0, 0, 0, 0,0x3E39, 0, 0,
+0x3E3A, 0,0x3E3B, 0, 0, 0,0x3E3C,0x3E3D,
+0x3E3E,0x3E3F,0x3E40, 0,0x3E41,0x3E42, 0,0x3E43,
+ 0, 0,0x3E44, 0,0x3E45, 0, 0, 0,
+0x3E46, 0, 0, 0, 0, 0, 0, 0,
+0x3E47,0x3E48, 0, 0, 0, 0,0x3E49,0x3E4A,
+ 0, 0, 0,0x3E4B,0x3E4C,0x3E4D, 0,0x3E4E,
+ 0, 0, 0, 0, 0, 0, 0,0x3E4F,
+ 0, 0, 0,0x3E50,0x3E51, 0, 0,0x3E52
+};
+
+/* page 17 0x615E-0x6290 */
+static uint16 tab_uni_jisx021217[]={
+0x3E53, 0,0x3E54, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E55, 0,
+ 0, 0, 0, 0,0x3E56, 0, 0, 0,
+ 0, 0,0x3E57, 0, 0,0x3E58,0x3E59, 0,
+ 0,0x3E5A,0x3E5B,0x3E5C, 0,0x3E5D,0x3E5E, 0,
+ 0, 0, 0, 0, 0,0x3E5F, 0,0x3E60,
+ 0, 0, 0, 0,0x3E61,0x3E62, 0, 0,
+ 0,0x3E63,0x3E64, 0, 0, 0,0x3E65,0x3E66,
+ 0,0x3E67,0x3E68, 0, 0, 0, 0,0x3E69,
+ 0, 0,0x3E6A, 0,0x3E6B, 0, 0,0x3E6C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3E6D,0x3E6E, 0, 0,0x3E6F, 0,
+ 0, 0,0x3E70,0x3E71,0x3E72, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3E73,0x3E74, 0, 0, 0, 0, 0,0x3E75,
+ 0, 0, 0, 0, 0, 0,0x3E76,0x3E77,
+0x3E78,0x3E79, 0,0x3E7A,0x3E7B, 0, 0,0x3E7E,
+ 0,0x3E7C, 0,0x3E7D, 0, 0,0x3F21,0x3F22,
+ 0,0x3F23, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F24, 0,0x3F25,0x3F26, 0,
+ 0,0x3F27, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3F28, 0,0x3F29,
+ 0, 0, 0, 0, 0, 0,0x3F2A, 0,
+ 0, 0,0x3F2B, 0,0x3F2C,0x3F2D, 0, 0,
+ 0,0x3F2E, 0,0x3F2F, 0,0x3F30, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F31, 0, 0, 0,0x3F32,
+ 0, 0, 0, 0,0x3F33,0x3F34,0x3F35, 0,
+0x3F36, 0, 0, 0, 0, 0,0x3F37, 0,
+ 0, 0,0x3F38,0x3F39,0x3F3A, 0,0x3F3B, 0,
+0x3F3C, 0, 0, 0,0x3F3D, 0,0x3F3E, 0,
+ 0, 0, 0, 0, 0, 0,0x3F3F, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3F40,
+ 0,0x3F41, 0, 0, 0,0x3F42, 0, 0,
+ 0, 0, 0, 0,0x3F43, 0, 0,0x3F44,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3F45,
+0x3F46,0x3F47,0x3F48};
+
+/* page 18 0x62A6-0x679B */
+static uint16 tab_uni_jisx021218[]={
+0x3F49, 0,0x3F4A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3F4B, 0, 0,
+0x3F4C,0x3F4D, 0, 0,0x3F4E, 0, 0, 0,
+0x3F4F,0x3F50, 0, 0, 0, 0,0x3F51, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3F52, 0, 0, 0, 0, 0, 0,0x3F53,
+0x3F54, 0, 0, 0,0x3F55, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3F56, 0, 0, 0,
+ 0, 0, 0, 0,0x3F57, 0,0x3F58, 0,
+ 0, 0, 0, 0, 0, 0,0x3F59,0x3F5A,
+ 0, 0, 0, 0, 0,0x3F5B,0x3F5C, 0,
+ 0, 0, 0, 0,0x3F5D,0x3F5E, 0,0x3F5F,
+ 0, 0,0x3F60, 0, 0,0x3F61, 0, 0,
+0x3F62, 0,0x3F63, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F64,0x3F65, 0, 0,0x3F66,
+ 0, 0, 0, 0, 0, 0, 0,0x3F67,
+0x3F68, 0, 0,0x3F69, 0, 0,0x3F6A, 0,
+ 0, 0, 0,0x3F6B,0x3F6C,0x3F6D,0x3F6E, 0,
+0x3F6F, 0, 0, 0,0x3F70,0x3F71, 0, 0,
+0x3F72, 0, 0, 0,0x3F73,0x3F74,0x3F75, 0,
+ 0, 0,0x3F76, 0, 0,0x3F77, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3F78,
+0x3F79, 0, 0, 0, 0, 0,0x3F7A,0x3F7B,
+ 0, 0, 0,0x3F7C, 0, 0,0x3F7D,0x3F7E,
+ 0, 0,0x4021, 0, 0, 0,0x4022,0x4023,
+ 0,0x4024, 0, 0,0x4025, 0,0x4026, 0,
+ 0,0x4027, 0, 0,0x4028, 0, 0, 0,
+ 0, 0,0x4029, 0, 0, 0,0x402A,0x402B,
+ 0, 0, 0,0x402C,0x402D, 0, 0, 0,
+0x402E, 0, 0, 0, 0, 0,0x402F, 0,
+0x4030, 0, 0, 0, 0, 0, 0,0x4031,
+0x4032,0x4033, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4034,
+ 0, 0, 0,0x4035, 0, 0, 0,0x4036,
+ 0, 0,0x4037, 0, 0, 0, 0, 0,
+0x4038, 0, 0,0x4039, 0,0x403A,0x403B,0x403C,
+ 0, 0, 0, 0, 0, 0,0x403D, 0,
+ 0, 0,0x403E, 0, 0, 0, 0,0x403F,
+ 0, 0, 0, 0,0x4040, 0,0x4041, 0,
+ 0, 0, 0, 0,0x4042,0x4043, 0,0x4044,
+ 0, 0,0x4045,0x4046, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4047,0x4048, 0, 0, 0,
+ 0, 0,0x4049, 0,0x404A, 0,0x404B, 0,
+ 0, 0,0x404C, 0, 0, 0, 0, 0,
+0x404D, 0,0x404E, 0,0x404F, 0,0x4050,0x4051,
+ 0, 0, 0,0x4052,0x4053, 0, 0, 0,
+ 0,0x4054,0x4055, 0, 0, 0, 0,0x4056,
+ 0, 0, 0, 0, 0, 0, 0,0x4057,
+ 0,0x4058, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4059, 0, 0,
+ 0,0x405A, 0,0x405B,0x405C,0x405D,0x405E, 0,
+ 0, 0, 0, 0,0x405F,0x4060,0x4061,0x4062,
+ 0,0x4063,0x4064,0x4065, 0,0x4066, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4067,
+ 0, 0, 0, 0, 0,0x4068,0x4069, 0,
+ 0, 0, 0, 0, 0,0x406A, 0,0x406B,
+ 0, 0, 0, 0, 0, 0, 0,0x406C,
+ 0,0x406D, 0, 0, 0, 0, 0, 0,
+ 0,0x406E,0x406F,0x4070, 0, 0, 0, 0,
+ 0, 0,0x4071,0x4072, 0,0x4073, 0,0x4074,
+ 0,0x4075, 0,0x4076, 0,0x4077, 0, 0,
+0x4078, 0,0x4079, 0, 0, 0,0x407A, 0,
+ 0, 0, 0, 0, 0,0x407B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x407C,
+0x407D,0x407E, 0, 0, 0, 0,0x4121, 0,
+ 0, 0, 0,0x4122,0x4123,0x4124,0x4125, 0,
+0x4126, 0,0x4127,0x4128, 0, 0, 0,0x4129,
+ 0,0x412A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x412B,0x412C,
+ 0, 0, 0,0x412D,0x412E, 0, 0,0x412F,
+ 0, 0,0x4130, 0, 0, 0, 0,0x4131,
+ 0,0x4132, 0, 0, 0,0x4133, 0, 0,
+ 0,0x4134, 0,0x4135, 0, 0,0x4136, 0,
+ 0, 0,0x4137,0x4138,0x4139, 0, 0, 0,
+ 0,0x413A, 0, 0, 0,0x413B,0x413C, 0,
+0x413D, 0, 0,0x413E, 0,0x413F, 0, 0,
+0x4140,0x4141, 0, 0,0x4142, 0, 0, 0,
+0x4143, 0, 0,0x4144, 0, 0, 0, 0,
+0x4145, 0, 0,0x4146, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4147, 0,0x4148,0x4149,
+ 0, 0, 0, 0, 0,0x414A, 0, 0,
+ 0,0x414B, 0,0x414C, 0, 0, 0, 0,
+ 0, 0,0x414D, 0,0x414E, 0,0x414F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4150,0x4151, 0, 0, 0, 0, 0,
+ 0,0x4152, 0, 0, 0,0x4153, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4154, 0, 0,0x4155,
+ 0, 0, 0,0x4156, 0, 0, 0,0x4157,
+ 0, 0, 0, 0,0x4158, 0, 0, 0,
+ 0, 0, 0, 0,0x4159, 0, 0,0x415A,
+ 0, 0,0x415B, 0, 0, 0, 0,0x415C,
+ 0, 0,0x415D, 0, 0,0x415E, 0, 0,
+0x415F, 0, 0, 0, 0, 0, 0, 0,
+0x4160, 0, 0, 0,0x4161,0x4162,0x4163, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4164, 0, 0,0x4165, 0, 0, 0,
+ 0, 0,0x4166,0x4167, 0, 0, 0, 0,
+0x4168, 0,0x4169, 0, 0, 0,0x416A, 0,
+0x416B, 0,0x416C, 0, 0, 0, 0, 0,
+ 0,0x416D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x416E, 0,0x416F, 0,0x4170,0x4171,
+ 0, 0, 0,0x4172, 0, 0, 0, 0,
+0x4173,0x4174,0x4175, 0, 0, 0,0x4176, 0,
+ 0, 0,0x4177,0x4178, 0, 0, 0,0x4179,
+ 0, 0, 0,0x417A,0x417B, 0, 0,0x417C,
+0x417D, 0, 0, 0, 0, 0, 0,0x417E,
+0x4221, 0, 0,0x4222,0x4223,0x4224,0x4225, 0,
+0x4226, 0, 0,0x4227,0x4228,0x4229,0x422A, 0,
+0x422B, 0,0x422C,0x422D, 0,0x422E, 0, 0,
+ 0,0x4230, 0,0x422F, 0, 0, 0, 0,
+ 0, 0,0x4231, 0, 0, 0, 0,0x4232,
+0x4233, 0, 0, 0,0x4234, 0,0x4235, 0,
+0x4237, 0, 0,0x4236, 0, 0, 0, 0,
+ 0,0x4238,0x4239,0x423A, 0,0x423B,0x423C, 0,
+ 0, 0,0x423D,0x423E, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4240,0x4241,0x4242, 0,
+ 0, 0, 0, 0, 0,0x4244, 0,0x4245,
+ 0,0x4247,0x4248,0x4249, 0,0x424A,0x424C, 0,
+0x4243,0x4246,0x424B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x424D,0x424E,0x424F,
+ 0, 0,0x4250, 0,0x4251, 0, 0, 0,
+ 0, 0, 0,0x4252,0x4253,0x4254,0x4255, 0,
+ 0,0x4256,0x4257, 0, 0, 0,0x4258, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4259,
+ 0, 0, 0,0x425A,0x425B, 0, 0,0x425C,
+ 0, 0, 0, 0, 0,0x425D, 0, 0,
+ 0,0x425E,0x425F, 0,0x4260,0x4261, 0, 0,
+ 0, 0,0x4262, 0, 0, 0,0x4263, 0,
+0x4264,0x4265, 0, 0, 0, 0,0x4266, 0,
+ 0, 0, 0, 0, 0,0x4267, 0, 0,
+ 0,0x4268, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4269, 0, 0,0x426A,0x426B, 0,
+0x426C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x426D,0x423F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x426E,
+ 0,0x426F, 0, 0, 0, 0, 0, 0,
+0x4270, 0, 0, 0, 0,0x4271, 0, 0,
+ 0, 0, 0,0x4272, 0, 0,0x4273, 0,
+ 0, 0,0x4274, 0,0x4275, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4276, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4277, 0, 0, 0, 0, 0, 0,0x4278,
+ 0,0x4279,0x427A, 0, 0, 0,0x427B, 0,
+ 0, 0, 0, 0, 0, 0,0x427C,0x427D,
+ 0, 0, 0, 0, 0, 0, 0,0x427E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4321, 0, 0, 0, 0, 0,0x4322, 0,
+0x4323, 0, 0, 0, 0, 0,0x4324, 0,
+0x4325, 0, 0, 0, 0,0x4326, 0, 0,
+ 0, 0, 0,0x4327, 0, 0,0x4328, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4329,0x432A, 0,0x432B, 0,0x432C, 0, 0,
+0x432D, 0,0x432E,0x432F, 0,0x4330};
+
+/* page 19 0x67B0-0x67F9 */
+static uint16 tab_uni_jisx021219[]={
+0x4331,0x4332,0x4333, 0, 0,0x4334, 0, 0,
+ 0, 0, 0,0x4335,0x4336,0x4337, 0, 0,
+0x4339, 0,0x433A,0x433B, 0,0x433C, 0, 0,
+0x433D,0x433E, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x433F, 0, 0, 0, 0,0x4340,
+ 0,0x4341, 0, 0,0x4342, 0, 0, 0,
+ 0,0x4343, 0, 0, 0, 0,0x4344, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4345, 0,0x4346, 0, 0, 0,0x4347,0x4348,
+ 0,0x4338};
+
+/* page 20 0x6814-0x6917 */
+static uint16 tab_uni_jisx021220[]={
+0x434A, 0, 0, 0, 0,0x434B, 0, 0,
+ 0,0x434C, 0,0x434D, 0, 0, 0, 0,
+ 0, 0, 0,0x434F,0x434E, 0, 0, 0,
+0x4350,0x4351, 0,0x4352,0x4353,0x4354, 0,0x4355,
+ 0, 0, 0, 0, 0, 0, 0,0x4356,
+ 0, 0, 0,0x4357, 0, 0, 0, 0,
+0x4358,0x4359, 0, 0, 0, 0,0x435A, 0,
+0x435B, 0, 0, 0, 0, 0,0x4349, 0,
+ 0,0x435C, 0,0x435D,0x435E, 0, 0,0x435F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4360,
+ 0, 0,0x4361,0x4362,0x4363,0x4364,0x4365, 0,
+ 0,0x4366, 0, 0, 0,0x4367,0x4368,0x4369,
+0x436A, 0, 0, 0, 0, 0,0x436B, 0,
+0x436C, 0,0x436D, 0,0x436E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x436F, 0,0x4370, 0,0x4371, 0,
+0x4372, 0, 0, 0, 0,0x4373, 0,0x4374,
+ 0,0x4375, 0, 0, 0,0x4376,0x4377, 0,
+ 0, 0,0x4378, 0, 0, 0,0x4379, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x437A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x437B, 0, 0,0x437C, 0, 0, 0,
+0x437D, 0, 0,0x437E,0x4421,0x4422, 0,0x4423,
+ 0, 0,0x4424, 0, 0,0x4425, 0, 0,
+0x4426,0x4427, 0, 0, 0, 0, 0, 0,
+ 0,0x4428, 0, 0,0x4429, 0,0x442A,0x442B,
+0x442C,0x442D, 0, 0,0x442E,0x442F, 0, 0,
+ 0,0x4430,0x4431, 0, 0, 0, 0,0x4432,
+0x4433,0x4434, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4435, 0, 0,0x4436,0x4437, 0,
+ 0, 0, 0, 0,0x4438,0x4439, 0,0x443A,
+ 0, 0,0x443B,0x443C};
+
+/* page 21 0x6931-0x6D3F */
+static uint16 tab_uni_jisx021221[]={
+0x443D, 0,0x443E, 0,0x443F, 0, 0,0x4440,
+ 0, 0,0x4441, 0, 0, 0, 0, 0,
+ 0,0x4442, 0, 0,0x4443, 0, 0, 0,
+0x4444, 0, 0, 0, 0,0x4445, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4446, 0,
+ 0, 0,0x4447, 0, 0, 0, 0, 0,
+ 0, 0,0x4448,0x4449,0x444A,0x444B, 0,0x444C,
+0x444D, 0, 0,0x444E, 0, 0, 0,0x444F,
+0x4450,0x4451, 0, 0, 0, 0, 0, 0,
+ 0,0x4452,0x4453, 0, 0, 0,0x4454,0x4455,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4456, 0, 0, 0,
+ 0,0x4457, 0, 0, 0,0x4458, 0,0x4459,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x445A, 0, 0, 0,0x445B,0x445C, 0,0x445D,
+ 0, 0,0x445E, 0,0x445F, 0,0x4460, 0,
+ 0, 0, 0, 0, 0, 0,0x4461,0x4462,
+ 0,0x4463, 0,0x4464, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4465, 0, 0,0x4466,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4467, 0, 0, 0, 0,0x4468,0x4469, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x446A, 0, 0,0x446B, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x446C,0x446D, 0,
+0x446E, 0,0x446F, 0,0x4470, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4471, 0,0x4472,
+0x4473, 0,0x4474, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4475, 0,
+0x4476, 0, 0, 0,0x4477, 0, 0, 0,
+ 0,0x4478, 0, 0,0x4479, 0, 0,0x447A,
+ 0, 0, 0,0x447B, 0, 0, 0,0x447C,
+ 0, 0, 0, 0, 0, 0, 0,0x447D,
+ 0,0x447E, 0,0x4521, 0, 0,0x4522, 0,
+ 0, 0,0x4523, 0, 0,0x4524,0x4525, 0,
+ 0, 0, 0, 0,0x4526,0x4527, 0, 0,
+0x4528,0x4529, 0, 0, 0,0x452A, 0,0x452B,
+0x452C,0x452D, 0, 0,0x452E,0x452F, 0, 0,
+ 0, 0,0x4530, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4531, 0, 0,0x4532, 0,
+ 0,0x4533, 0, 0, 0, 0, 0, 0,
+0x4534, 0,0x4535, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4536, 0, 0,
+0x4537, 0,0x4538, 0, 0,0x4539,0x453A, 0,
+0x453B, 0,0x453C, 0, 0, 0, 0, 0,
+0x453D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x453E, 0,0x453F,0x4540,0x4541, 0,
+ 0, 0, 0, 0,0x4542, 0, 0, 0,
+ 0, 0,0x4543, 0, 0, 0,0x4544,0x4545,
+0x4546, 0, 0,0x4547, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4548,0x4549,0x454A, 0,
+ 0, 0, 0, 0, 0,0x454B, 0,0x454D,
+0x454C, 0, 0,0x454E, 0, 0, 0,0x454F,
+ 0, 0, 0,0x4550,0x4551,0x4552, 0, 0,
+ 0, 0, 0,0x4553,0x4554, 0, 0, 0,
+ 0, 0, 0,0x4555, 0, 0,0x4556, 0,
+ 0, 0, 0,0x4557, 0, 0, 0,0x4558,
+0x4559,0x455A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x455B,0x455C, 0, 0, 0,
+ 0,0x455D,0x455E, 0, 0,0x455F,0x4560, 0,
+0x4561, 0, 0, 0, 0, 0,0x4562,0x4563,
+0x4564, 0, 0, 0, 0, 0,0x4565, 0,
+ 0, 0,0x4566, 0, 0,0x4567, 0, 0,
+ 0, 0, 0,0x4568, 0, 0, 0,0x4569,
+ 0, 0,0x456A,0x456B, 0, 0,0x456C, 0,
+ 0, 0, 0, 0,0x456D,0x456E, 0, 0,
+ 0, 0,0x456F, 0, 0, 0,0x4570, 0,
+ 0, 0, 0, 0, 0,0x4571, 0, 0,
+ 0,0x4572, 0, 0,0x4573, 0, 0, 0,
+ 0,0x4574, 0, 0, 0,0x4575, 0,0x4576,
+ 0, 0, 0, 0,0x4577, 0, 0,0x4578,
+ 0, 0, 0, 0, 0, 0,0x4579, 0,
+ 0, 0,0x457A, 0, 0,0x457B, 0,0x457C,
+ 0, 0, 0, 0,0x457D, 0, 0, 0,
+ 0, 0, 0, 0,0x457E,0x4621, 0, 0,
+ 0,0x4622, 0, 0,0x4623, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4624, 0,
+ 0, 0,0x4625, 0, 0, 0,0x4626,0x4627,
+ 0,0x4628,0x4629, 0, 0, 0, 0,0x462A,
+0x462B, 0, 0,0x462C,0x462D,0x462E, 0,0x462F,
+ 0, 0, 0, 0, 0, 0, 0,0x4630,
+0x4631, 0, 0, 0,0x4632,0x4633, 0, 0,
+ 0, 0,0x4634,0x4635, 0, 0, 0, 0,
+0x4636, 0, 0,0x4637, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4638, 0, 0,
+ 0,0x4639, 0, 0, 0, 0, 0, 0,
+0x463A, 0,0x463B, 0, 0,0x463C,0x463D, 0,
+ 0, 0, 0, 0, 0,0x463E, 0, 0,
+0x463F, 0, 0, 0, 0, 0,0x4640, 0,
+0x4641, 0, 0, 0, 0, 0,0x4642, 0,
+ 0,0x4643, 0,0x4644,0x4645, 0, 0, 0,
+0x4646, 0, 0, 0,0x4647,0x4648, 0,0x4649,
+ 0,0x464A, 0, 0, 0, 0, 0, 0,
+0x464B, 0, 0, 0, 0, 0,0x464C, 0,
+ 0, 0, 0, 0, 0,0x464D,0x464E,0x464F,
+ 0, 0, 0,0x4650, 0,0x4651, 0, 0,
+ 0, 0,0x4652, 0,0x4653,0x4654, 0, 0,
+ 0,0x4655,0x4656, 0, 0, 0,0x4657, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4658,0x4659, 0,0x465A, 0,0x465B, 0,
+ 0,0x465C, 0,0x465D, 0, 0, 0, 0,
+0x465E, 0,0x465F,0x4660, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4736, 0,
+ 0, 0,0x4661, 0,0x4662, 0,0x4663, 0,
+ 0, 0, 0,0x4664, 0,0x4665, 0,0x4666,
+0x4667, 0,0x4668, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4669,0x466A,0x466B, 0,
+0x466C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x466D,0x466E, 0,0x466F,0x4670,
+ 0, 0, 0,0x4671, 0, 0,0x4672, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4673,
+ 0,0x4674, 0,0x4675, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4676, 0, 0, 0,0x4677, 0, 0,
+ 0, 0, 0, 0,0x4678, 0,0x4679,0x467A,
+0x467B,0x467C, 0,0x467D, 0,0x467E, 0, 0,
+ 0,0x4721, 0,0x4722, 0, 0, 0,0x4723,
+ 0, 0, 0, 0, 0, 0,0x4724, 0,
+0x4725, 0,0x4726,0x4727, 0,0x4728, 0, 0,
+ 0,0x4729, 0,0x472A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x472B, 0, 0,0x472C, 0,
+ 0,0x472D, 0, 0, 0,0x472E,0x472F, 0,
+0x4730, 0,0x4731, 0, 0, 0, 0, 0,
+ 0,0x4732, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4733,0x4734,0x4735,
+ 0, 0, 0, 0, 0,0x4737,0x4738, 0,
+0x4739, 0, 0, 0, 0, 0, 0, 0,
+0x473A, 0, 0,0x473B, 0, 0,0x473C};
+
+/* page 22 0x6D57-0x6E04 */
+static uint16 tab_uni_jisx021222[]={
+0x473D, 0, 0, 0, 0, 0, 0,0x473E,
+0x473F, 0,0x4740, 0, 0, 0,0x4741, 0,
+0x4742, 0, 0, 0, 0, 0, 0, 0,
+0x4743,0x4744, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4745, 0, 0,
+ 0, 0, 0,0x4746, 0, 0, 0, 0,
+0x4747, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4748,0x4749, 0,0x474A, 0,0x474B,
+0x474C,0x474D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x474E, 0,0x474F, 0, 0,
+ 0, 0, 0, 0, 0,0x4750, 0, 0,
+0x4751, 0,0x4752, 0, 0, 0,0x4753, 0,
+0x4754, 0, 0, 0, 0,0x4755, 0, 0,
+ 0,0x4756, 0,0x4757, 0, 0, 0,0x4758,
+0x4759, 0, 0, 0, 0, 0, 0,0x475A,
+ 0, 0, 0, 0,0x475B, 0,0x475C, 0,
+0x475D,0x475E, 0,0x475F, 0, 0,0x4760, 0,
+ 0, 0,0x4761, 0, 0, 0, 0, 0,
+0x4762,0x4763, 0, 0, 0,0x4764, 0,0x4765,
+ 0, 0, 0, 0, 0,0x4766, 0, 0,
+ 0,0x4767, 0, 0, 0,0x4768};
+
+/* page 23 0x6E1E-0x6ECF */
+static uint16 tab_uni_jisx021223[]={
+0x4769, 0, 0, 0,0x476A, 0, 0, 0,
+ 0,0x476B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x476C, 0, 0, 0,
+0x476D, 0, 0,0x476E, 0,0x476F,0x4770, 0,
+ 0, 0, 0, 0, 0, 0,0x4771,0x4772,
+ 0, 0,0x4773,0x4774, 0,0x4775, 0, 0,
+ 0,0x4776, 0,0x4777,0x4778,0x4779,0x477A, 0,
+ 0,0x477B, 0, 0, 0, 0,0x477C,0x477D,
+0x477E, 0, 0, 0,0x4821,0x4822, 0, 0,
+ 0, 0,0x4823, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4824, 0, 0,
+ 0, 0, 0, 0, 0,0x4825, 0,0x4826,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4827,
+ 0, 0, 0, 0, 0,0x4828, 0, 0,
+ 0, 0, 0,0x4829, 0, 0, 0, 0,
+ 0, 0,0x482A, 0, 0, 0, 0, 0,
+ 0,0x482B, 0, 0, 0, 0, 0,0x482C,
+0x482D, 0, 0,0x482E, 0,0x482F, 0, 0,
+ 0, 0, 0, 0, 0,0x4830, 0, 0,
+ 0,0x4831,0x4832,0x4833, 0,0x4834, 0, 0,
+ 0,0x4835,0x4836, 0,0x4837, 0, 0,0x4838,
+0x4839,0x483A};
+
+/* page 24 0x6EEB-0x70E4 */
+static uint16 tab_uni_jisx021224[]={
+0x483B, 0,0x483C,0x483D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x483E, 0,
+0x483F, 0,0x4840, 0, 0, 0, 0, 0,
+ 0,0x4841, 0, 0, 0,0x4842, 0,0x4843,
+ 0,0x4844,0x4845, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4846, 0,0x4847, 0,0x4848,
+0x4849, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x484A, 0, 0,0x484B,0x484C,
+ 0, 0,0x4853, 0,0x484D,0x484E, 0, 0,
+0x484F, 0, 0,0x4850, 0, 0, 0, 0,
+0x4851,0x4852, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4854, 0,0x4855,0x4856,
+0x4857, 0, 0, 0,0x4858, 0,0x4859,0x485A,
+ 0, 0,0x485B,0x485C, 0, 0,0x485D,0x485E,
+ 0, 0, 0, 0, 0,0x485F, 0, 0,
+ 0,0x4860, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4861,0x4862, 0, 0, 0, 0,
+0x4863, 0, 0, 0,0x4864,0x4865, 0, 0,
+0x4866,0x4867,0x4868, 0, 0,0x4869, 0,0x486A,
+0x486B,0x486C, 0,0x486D, 0, 0, 0,0x486E,
+ 0, 0, 0, 0,0x486F,0x4870, 0, 0,
+ 0, 0,0x4871,0x4872,0x4873,0x4874, 0, 0,
+ 0, 0, 0,0x4875,0x4876,0x4877, 0, 0,
+ 0, 0,0x4878,0x4879, 0, 0, 0, 0,
+ 0,0x487A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x487B, 0,0x487C,0x487D, 0,0x487E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4921,
+ 0, 0, 0,0x4922, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4923,0x4924, 0,
+ 0, 0, 0, 0, 0,0x4925, 0, 0,
+ 0, 0,0x4926, 0, 0, 0,0x4927, 0,
+ 0,0x4928,0x4929, 0, 0,0x492A, 0, 0,
+ 0, 0,0x492B,0x492C,0x492D, 0, 0, 0,
+ 0, 0,0x492E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x492F, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4930, 0, 0,
+0x4931, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4932, 0, 0, 0,
+ 0,0x4933, 0, 0,0x4934, 0,0x4935, 0,
+ 0,0x4936, 0, 0, 0, 0, 0, 0,
+0x4937,0x4938, 0, 0, 0,0x4939,0x493A,0x493B,
+0x493C, 0, 0,0x4941, 0, 0, 0, 0,
+ 0,0x493D,0x493E, 0, 0, 0, 0, 0,
+ 0, 0,0x493F,0x4940, 0, 0, 0, 0,
+ 0,0x4942,0x4943, 0, 0, 0, 0, 0,
+ 0,0x4944, 0,0x4945, 0, 0, 0, 0,
+ 0, 0,0x4946,0x4947, 0, 0, 0, 0,
+ 0, 0, 0,0x4948, 0, 0,0x4949, 0,
+ 0, 0,0x494A,0x494B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x494C,0x494D,0x494E,0x494F,0x4950, 0, 0,
+0x4951, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4952, 0, 0, 0, 0, 0, 0,
+0x4953, 0, 0, 0, 0,0x4954,0x4955, 0,
+ 0,0x4956, 0, 0,0x4957, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4958,
+ 0, 0, 0, 0, 0, 0,0x4959, 0,
+0x495A,0x495B,0x495C,0x495D, 0,0x495E, 0, 0,
+ 0,0x495F, 0, 0, 0, 0, 0, 0,
+ 0,0x4960};
+
+/* page 25 0x70FA-0x71DC */
+static uint16 tab_uni_jisx021225[]={
+0x4961, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4962,0x4963,0x4964,0x4965,0x4966, 0, 0,
+ 0,0x4967,0x4968, 0, 0,0x4969, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x496A, 0,0x496B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x496C, 0,0x496D, 0,0x496E,0x496F,0x4970,
+ 0, 0, 0, 0, 0, 0,0x4971, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4972,
+ 0, 0, 0,0x4973,0x4974,0x4975, 0, 0,
+0x4976,0x4977, 0, 0, 0, 0,0x4978, 0,
+0x4979, 0, 0, 0, 0,0x497A, 0, 0,
+0x497B, 0,0x497C, 0,0x497D, 0,0x497E, 0,
+ 0, 0, 0, 0, 0, 0,0x4A21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4A22,
+ 0, 0, 0, 0, 0, 0,0x4A23, 0,
+ 0, 0, 0,0x4A24, 0,0x4A25, 0, 0,
+ 0, 0,0x4A26, 0, 0, 0, 0, 0,
+0x4A27, 0, 0, 0, 0, 0, 0, 0,
+0x4A28,0x4A29, 0, 0, 0, 0,0x4A2A, 0,
+0x4A2B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4A2C,0x4A2D, 0,
+0x4A2E,0x4A2F, 0, 0, 0, 0, 0, 0,
+0x4A30, 0, 0, 0, 0,0x4A31,0x4A32,0x4A33,
+ 0, 0,0x4A34, 0, 0, 0, 0, 0,
+ 0,0x4A35,0x4A36, 0, 0, 0, 0, 0,
+ 0,0x4A37, 0, 0,0x4A38, 0, 0,0x4A39,
+0x4A3A, 0,0x4A3B};
+
+/* page 26 0x71F8-0x7E9E */
+static uint16 tab_uni_jisx021226[]={
+0x4A3C, 0, 0, 0, 0, 0,0x4A3D, 0,
+0x4A3E, 0, 0, 0, 0, 0, 0,0x4A3F,
+0x4A40,0x4A41, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4A42, 0, 0, 0,0x4A43,
+ 0, 0,0x4A44, 0, 0,0x4A45, 0,0x4A46,
+ 0, 0, 0, 0,0x4A47, 0, 0, 0,
+ 0, 0, 0,0x4A48, 0, 0, 0,0x4A49,
+ 0, 0, 0, 0,0x4A4A, 0, 0, 0,
+0x4A4B,0x4A4C, 0, 0, 0, 0, 0, 0,
+ 0,0x4A4D,0x4A4E,0x4A4F, 0,0x4A50, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A51,0x4A52,
+0x4A53, 0, 0,0x4A54, 0,0x4A55,0x4A56, 0,
+ 0, 0,0x4A57, 0,0x4A58, 0,0x4A59, 0,
+0x4A5A, 0, 0,0x4A5B, 0, 0, 0, 0,
+0x4A5C, 0, 0,0x4A5D, 0, 0,0x4A5E,0x4A5F,
+ 0,0x4A60, 0, 0, 0, 0, 0,0x4A61,
+0x4A62, 0, 0,0x4A63,0x4A64, 0, 0,0x4A65,
+ 0, 0, 0, 0,0x4A66, 0, 0, 0,
+ 0,0x4A67, 0, 0, 0,0x4A68,0x4A69, 0,
+ 0, 0, 0,0x4A6A, 0, 0, 0, 0,
+ 0, 0, 0,0x4A6B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4A6C, 0, 0, 0, 0,0x4A6D,0x4A6E, 0,
+ 0,0x4A6F, 0, 0,0x4A70, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A71, 0,
+ 0,0x4A72, 0, 0, 0, 0, 0,0x4A73,
+ 0,0x4A74, 0, 0,0x4A75, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4A76,0x4A77, 0,
+0x4A78, 0, 0, 0, 0, 0, 0,0x4A79,
+ 0, 0, 0, 0, 0,0x4A7A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4A7B,0x4A7C, 0, 0, 0,
+ 0, 0,0x4A7D,0x4A7E, 0, 0,0x4B21, 0,
+ 0, 0,0x4B22, 0,0x4B23,0x4B24, 0,0x4B25,
+ 0, 0, 0,0x4B26, 0,0x4B27, 0, 0,
+ 0, 0,0x4B28,0x4B29, 0, 0, 0, 0,
+0x4B2A,0x4B2B, 0, 0, 0, 0,0x4B2C, 0,
+ 0, 0,0x4B2D, 0,0x4B2E, 0, 0,0x4B2F,
+0x4B30, 0, 0, 0,0x4B31, 0, 0, 0,
+ 0,0x4B32,0x4B33, 0, 0,0x4B34, 0, 0,
+ 0, 0,0x4B35,0x4B36, 0,0x4B37, 0, 0,
+ 0, 0, 0,0x4B38, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B39, 0, 0,
+0x4B3A, 0,0x4B3B, 0, 0, 0,0x4B3C, 0,
+0x4B3D, 0, 0, 0, 0,0x4B3E,0x4B3F,0x4B40,
+0x4B41, 0, 0, 0, 0, 0,0x4B42,0x4B43,
+ 0,0x4B44, 0,0x4B45,0x4B46, 0,0x4B47,0x4B48,
+ 0,0x4B49, 0, 0, 0, 0, 0,0x4B4A,
+ 0,0x4B4B, 0, 0,0x4B4C, 0, 0, 0,
+0x4B4D,0x4B4E, 0,0x4B4F, 0,0x4B50,0x4B51, 0,
+ 0, 0, 0, 0, 0, 0,0x4B52, 0,
+0x4B53, 0, 0,0x4B54, 0,0x4B55, 0,0x4B56,
+0x4B57, 0, 0, 0,0x4B58, 0,0x4B59,0x4B5A,
+0x4B5B, 0,0x4B5C, 0, 0,0x4B5D,0x4B5E, 0,
+ 0, 0,0x4B5F,0x4B60, 0,0x4B61, 0, 0,
+ 0, 0, 0, 0, 0,0x4B62, 0,0x4B63,
+ 0,0x4B64, 0, 0,0x4B65,0x4B66, 0,0x4B67,
+ 0, 0, 0, 0, 0,0x4B68,0x4B69, 0,
+ 0,0x4B6A, 0,0x4B6B,0x4B6C, 0, 0,0x4B6D,
+ 0, 0,0x4B6E,0x4B6F, 0, 0,0x4B70, 0,
+ 0,0x4B71, 0, 0, 0,0x4B72, 0, 0,
+ 0,0x4B73, 0,0x4B74, 0, 0,0x4B75,0x4B76,
+ 0,0x4B77, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4B78,0x4B79, 0,0x4B7A,
+ 0,0x4B7B,0x4B7C,0x4B7D, 0,0x4B7E, 0,0x4C21,
+0x4C22,0x4C23, 0, 0,0x4C24, 0, 0,0x4C25,
+ 0, 0,0x4C26, 0, 0, 0, 0, 0,
+ 0,0x4C27, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4C28,0x4C29, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4C2A, 0,0x4C2B, 0,
+0x4C2C,0x4C2D,0x4C2E,0x4C2F,0x4C30,0x4C31,0x4C32,0x4C33,
+0x4C34,0x4C35, 0, 0, 0, 0, 0, 0,
+ 0,0x4C36, 0, 0, 0, 0, 0, 0,
+0x4C37, 0, 0,0x4C38,0x4C39, 0,0x4C3A,0x4C3B,
+ 0, 0, 0,0x4C3C, 0,0x4C3D, 0, 0,
+ 0,0x4C3E,0x4C3F, 0, 0, 0, 0,0x4C40,
+ 0, 0, 0, 0, 0,0x4C41, 0, 0,
+ 0, 0,0x4C42, 0, 0, 0,0x4C43,0x4C44,
+0x4C45, 0, 0,0x4C46, 0,0x4C47,0x4C48, 0,
+ 0,0x4C49,0x4C4A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4C4B,0x4C4C, 0, 0, 0,0x4C4D,0x4C4E,0x4C4F,
+ 0,0x4C50, 0, 0, 0, 0, 0,0x4C51,
+0x4C52,0x4C53,0x4C54, 0, 0, 0, 0, 0,
+0x4C55,0x4C56,0x4C57, 0,0x4C58, 0, 0,0x4C59,
+0x4C5A,0x4C5B, 0,0x4C5C, 0, 0,0x4C5D, 0,
+0x4C5E,0x4C5F,0x4C60,0x4C61, 0, 0,0x4C62,0x4C63,
+ 0,0x4C64,0x4C65, 0, 0,0x4C66, 0, 0,
+ 0,0x4C67, 0,0x4C68, 0, 0, 0,0x4C69,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4C6A,0x4C6B, 0, 0,0x4C6C, 0, 0, 0,
+0x4C6D, 0, 0,0x4C6E, 0, 0, 0, 0,
+0x4C6F, 0,0x4C70,0x4C71, 0, 0,0x4C72,0x4C73,
+ 0, 0, 0, 0,0x4C74, 0, 0, 0,
+0x4C75, 0,0x4C76,0x4C77, 0, 0, 0,0x4C78,
+ 0, 0, 0, 0,0x4C79, 0, 0, 0,
+ 0, 0,0x4C7A,0x4C7B,0x4C7C, 0, 0,0x4C7D,
+ 0, 0, 0, 0, 0, 0,0x4C7E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D21, 0, 0, 0,0x4D22,0x4D23,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4D24,0x4D25, 0, 0,0x4D26, 0, 0,0x4D27,
+ 0,0x4D28,0x4D29, 0, 0, 0, 0,0x4D2A,
+ 0, 0, 0, 0, 0, 0,0x4D2B, 0,
+ 0,0x4D2C, 0, 0, 0,0x4D2D,0x4D2E,0x4D2F,
+0x4D30, 0, 0,0x4D31, 0, 0, 0,0x4D32,
+0x4D33, 0, 0, 0, 0, 0,0x4D34, 0,
+0x4D35, 0,0x4D36, 0, 0, 0, 0,0x4D37,
+ 0, 0, 0, 0, 0, 0,0x4D38,0x4D39,
+ 0,0x4D3A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4D3B,
+ 0,0x4D3C, 0, 0, 0, 0, 0, 0,
+ 0,0x4D3D,0x4D3E,0x4D3F,0x4D40,0x4D41,0x4D42, 0,
+ 0,0x4D43, 0, 0, 0,0x4D44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4D45, 0,0x4D46,0x4D47, 0,0x4D48, 0, 0,
+ 0,0x4D49, 0, 0,0x4D4A, 0, 0, 0,
+ 0, 0,0x4D4B, 0,0x4D4C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4D4D, 0, 0, 0,
+ 0, 0,0x4D4E, 0, 0, 0, 0,0x4D4F,
+0x4D50,0x4D51, 0, 0,0x4D52, 0,0x4D53, 0,
+ 0, 0, 0, 0,0x4D54, 0,0x4D55,0x4D56,
+ 0, 0, 0, 0, 0, 0, 0,0x4D57,
+ 0, 0, 0, 0,0x4D58, 0, 0,0x4D59,
+0x4D5A,0x4D5B, 0, 0,0x4D5C, 0, 0,0x4D5D,
+ 0, 0, 0, 0,0x4D5E, 0,0x4D5F,0x4D60,
+ 0,0x4D61, 0, 0, 0, 0, 0, 0,
+ 0,0x4D62, 0, 0, 0, 0, 0, 0,
+0x4D63, 0,0x4D64,0x4D65,0x4D66, 0, 0,0x4D67,
+0x4D68, 0,0x4D69, 0,0x4D6A, 0, 0,0x4D6B,
+ 0, 0,0x4D6C,0x4D6D, 0,0x4D6E,0x4D6F, 0,
+ 0,0x4D70, 0,0x4D71,0x4D72,0x4D73,0x4D74, 0,
+ 0, 0, 0,0x4D75, 0,0x4D76,0x4D77, 0,
+ 0,0x4D78, 0, 0, 0,0x4D79, 0, 0,
+ 0, 0,0x4D7A,0x4D7B, 0,0x4D7C, 0, 0,
+0x4D7D,0x4D7E,0x4E21, 0,0x4E22, 0, 0, 0,
+0x4E24,0x4E25, 0,0x4E26,0x4E27,0x4E28, 0, 0,
+ 0,0x4E29,0x4E23,0x4E2A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4E2B, 0, 0,
+ 0,0x4E2C, 0, 0, 0, 0, 0,0x4E2D,
+ 0, 0, 0, 0,0x4E2E,0x4E2F, 0, 0,
+ 0, 0, 0, 0, 0,0x4E30,0x4E31,0x4E32,
+ 0,0x4E33, 0, 0,0x4E34, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4E35, 0, 0, 0,0x4E36, 0, 0,
+ 0, 0, 0, 0,0x4E37,0x4E38, 0, 0,
+ 0, 0, 0, 0, 0,0x4E39, 0, 0,
+ 0, 0, 0,0x4E3A,0x4E3B,0x4E3C, 0,0x4E3D,
+0x4E3E, 0,0x4E3F,0x4E40,0x4E41,0x4E42,0x4E43,0x4E44,
+0x4E45, 0,0x4E46, 0, 0,0x4E47, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4E48, 0, 0,
+ 0,0x4E49, 0, 0, 0,0x4E4A, 0, 0,
+ 0,0x4E4B, 0,0x4E4C,0x4E4D, 0,0x4E4E, 0,
+ 0, 0, 0, 0,0x4E4F, 0, 0, 0,
+ 0,0x4E50, 0, 0, 0, 0, 0, 0,
+0x4E51, 0, 0, 0, 0, 0,0x4E52, 0,
+0x4E53, 0, 0, 0,0x4E54, 0, 0, 0,
+0x4E55,0x4E56, 0, 0, 0, 0,0x4E57, 0,
+ 0,0x4E58, 0, 0,0x4E59, 0, 0, 0,
+0x4E5A, 0, 0, 0, 0, 0,0x4E5B, 0,
+ 0, 0,0x4E5C, 0, 0, 0,0x4E5D, 0,
+ 0, 0,0x4E5E, 0,0x4E5F,0x4E60, 0,0x4E61,
+ 0,0x4E62,0x4E63, 0,0x4E64, 0, 0, 0,
+ 0, 0,0x4E65, 0, 0, 0, 0, 0,
+0x4E66, 0, 0, 0, 0,0x4E67,0x4E68,0x4E69,
+ 0, 0, 0, 0,0x4E6A,0x4E6B,0x4E6C, 0,
+ 0,0x4E6D, 0, 0, 0,0x4E6E,0x4E6F, 0,
+ 0, 0,0x4E70, 0, 0,0x4E71,0x4E72, 0,
+ 0, 0,0x4E73, 0, 0,0x4E74,0x4E75,0x4E76,
+ 0, 0,0x4E77, 0, 0, 0,0x4E78,0x4E79,
+ 0, 0, 0, 0,0x4E7A, 0,0x4E7B,0x4E7C,
+0x4E7D, 0,0x4E7E, 0,0x4F21, 0, 0,0x4F22,
+ 0, 0,0x4F23, 0,0x4F24, 0, 0, 0,
+0x4F25, 0,0x4F26,0x4F27,0x4F28, 0, 0, 0,
+ 0, 0,0x4F29, 0, 0,0x4F2A, 0, 0,
+0x4F2B, 0, 0, 0,0x4F2C, 0, 0, 0,
+ 0, 0, 0, 0,0x4F2D,0x4F2E, 0, 0,
+ 0, 0, 0, 0,0x4F2F,0x4F30,0x4F31, 0,
+ 0, 0,0x4F32, 0, 0, 0, 0,0x4F33,
+ 0, 0,0x4F34, 0, 0, 0, 0,0x4F35,
+ 0, 0,0x4F36, 0, 0, 0,0x4F37,0x4F38,
+ 0,0x4F39, 0, 0, 0,0x4F3A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4F3B, 0,
+ 0, 0, 0,0x4F3C, 0, 0, 0, 0,
+ 0,0x4F3D, 0, 0, 0, 0, 0, 0,
+ 0,0x4F3E,0x4F3F, 0, 0,0x4F40, 0, 0,
+ 0,0x4F41, 0, 0, 0, 0,0x4F42,0x4F43,
+0x4F44, 0, 0, 0,0x4F45, 0,0x4F46, 0,
+ 0, 0,0x4F47, 0,0x4F48, 0, 0, 0,
+0x4F49,0x4F4A, 0, 0,0x4F4B, 0, 0, 0,
+0x4F4C, 0, 0,0x4F4D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4F4E,0x4F4F, 0,
+ 0,0x4F50, 0, 0, 0,0x4F51,0x4F52, 0,
+ 0,0x4F53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4F54, 0, 0,
+ 0,0x4F55,0x4F56,0x4F57, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4F58,0x4F59, 0,
+0x4F5A, 0, 0, 0, 0,0x4F5B, 0,0x4F5C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4F5D,0x4F5E, 0, 0,0x4F5F,
+0x4F60, 0, 0, 0,0x4F61, 0,0x4F62, 0,
+ 0, 0,0x4F63, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4F64, 0,0x4F65, 0,
+0x4F66,0x4F67, 0,0x4F68,0x4F69, 0, 0, 0,
+0x4F6A, 0,0x4F6B, 0, 0, 0,0x4F6C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4F6D, 0, 0, 0,0x4F6E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4F6F, 0, 0, 0, 0,0x4F70,
+ 0, 0, 0, 0,0x4F71, 0, 0, 0,
+0x4F72, 0, 0, 0, 0,0x4F74,0x4F75,0x4F76,
+ 0,0x4F73, 0, 0,0x4F77, 0, 0, 0,
+0x4F78, 0, 0, 0,0x4F79,0x4F7A, 0, 0,
+0x4F7B,0x4F7C,0x4F7D,0x4F7E, 0, 0, 0, 0,
+ 0, 0, 0,0x5021, 0,0x5022, 0,0x5023,
+ 0, 0, 0, 0, 0, 0, 0,0x5024,
+0x5025,0x5026, 0, 0,0x5027, 0,0x5028, 0,
+ 0, 0,0x5029,0x502A, 0,0x502B,0x502C, 0,
+ 0, 0, 0,0x502E, 0, 0, 0,0x502F,
+0x5030,0x5031, 0, 0,0x502D, 0,0x5032, 0,
+ 0, 0,0x5033, 0, 0, 0, 0, 0,
+ 0, 0,0x5034,0x5035, 0, 0,0x5037,0x5038,
+ 0, 0,0x5039,0x503A, 0, 0, 0,0x503B,
+0x5036, 0, 0, 0, 0, 0,0x503C, 0,
+ 0, 0, 0, 0,0x503D, 0, 0, 0,
+0x503E, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x503F, 0,0x5040, 0,0x5041,0x5042,
+0x5043, 0, 0, 0, 0,0x5044, 0,0x5045,
+ 0,0x5046, 0, 0, 0,0x5047, 0, 0,
+ 0,0x5048, 0, 0,0x5049,0x504A, 0, 0,
+ 0, 0, 0,0x504B, 0,0x504C, 0,0x504D,
+ 0, 0, 0, 0,0x504E,0x504F,0x5050, 0,
+ 0, 0,0x5051,0x5052, 0, 0, 0,0x5053,
+ 0,0x5054, 0, 0,0x5055, 0, 0, 0,
+0x5056, 0, 0,0x5057,0x5058, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5059,
+ 0,0x505A, 0,0x505B, 0, 0, 0, 0,
+ 0, 0,0x505C, 0, 0, 0, 0, 0,
+ 0,0x505D, 0,0x505E,0x505F, 0,0x5060, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5061,0x5062, 0, 0, 0,
+ 0,0x5063, 0,0x5064,0x5065,0x5066,0x5067, 0,
+0x5068, 0, 0,0x5069,0x506A, 0, 0, 0,
+ 0,0x506B, 0, 0, 0, 0, 0, 0,
+0x506C,0x506D, 0,0x506E, 0, 0, 0,0x506F,
+ 0,0x5070, 0, 0,0x5071, 0, 0, 0,
+0x5072, 0, 0,0x5073, 0, 0, 0, 0,
+ 0, 0,0x5074, 0,0x5075, 0, 0,0x5076,
+0x5077, 0,0x5078, 0, 0, 0, 0,0x5079,
+ 0, 0, 0, 0,0x507A, 0,0x507B, 0,
+ 0, 0,0x507C, 0, 0,0x507D,0x507E, 0,
+0x5121, 0,0x5122, 0, 0,0x5123, 0, 0,
+ 0, 0,0x5124,0x5125, 0,0x5126, 0, 0,
+ 0,0x5127, 0, 0, 0, 0, 0, 0,
+0x5128, 0, 0, 0,0x5129, 0, 0, 0,
+ 0, 0,0x512A,0x512B, 0, 0, 0,0x512C,
+ 0,0x512D,0x512E, 0,0x512F, 0, 0, 0,
+ 0,0x5130, 0, 0, 0,0x5131, 0, 0,
+ 0, 0, 0,0x5132, 0, 0,0x5133, 0,
+ 0,0x5134, 0, 0, 0, 0, 0,0x5135,
+ 0, 0, 0,0x5136, 0,0x5137, 0,0x5138,
+0x5139, 0, 0, 0,0x513A,0x513B, 0, 0,
+0x513C,0x513D,0x513E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x513F,0x5140, 0,0x5141,
+0x5142, 0, 0, 0,0x5143, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5144,0x5145, 0,
+ 0,0x5146, 0, 0,0x5147,0x5148, 0,0x5149,
+0x514A, 0, 0, 0, 0,0x514B, 0,0x514C,
+ 0, 0,0x514D, 0, 0,0x514E, 0, 0,
+ 0, 0, 0, 0, 0,0x514F, 0, 0,
+0x5150, 0, 0, 0, 0, 0,0x5151, 0,
+0x5152, 0,0x5153, 0, 0,0x5154,0x5155, 0,
+ 0, 0,0x5156,0x5157, 0, 0, 0, 0,
+0x5158,0x5159, 0, 0,0x515A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x515B, 0,
+0x515C, 0, 0,0x515D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x515E, 0, 0, 0,
+ 0, 0, 0,0x515F, 0,0x5160, 0, 0,
+ 0,0x5161, 0,0x5162,0x5163, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5164, 0,
+ 0,0x5165, 0, 0,0x5166, 0,0x5167, 0,
+ 0,0x5168, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5169, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x516A,0x516B, 0,0x516C,0x516D, 0, 0, 0,
+ 0,0x516E, 0, 0,0x516F, 0, 0, 0,
+ 0, 0, 0,0x5170, 0,0x5171,0x5172, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5173,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5174, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5175,
+ 0, 0, 0,0x5176, 0, 0, 0,0x5177,
+ 0,0x5178,0x5179,0x517A, 0,0x517B,0x517C,0x517D,
+0x517E,0x5221, 0, 0,0x5222, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5223, 0,0x5224,
+0x5225,0x5226, 0, 0, 0, 0, 0,0x5227,
+ 0, 0, 0, 0, 0, 0,0x5228, 0,
+ 0, 0, 0, 0, 0,0x5229, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x522A, 0, 0, 0,0x522B, 0,0x522C, 0,
+ 0,0x522D,0x522E, 0, 0,0x522F, 0,0x5230,
+ 0, 0,0x5231,0x5232, 0, 0, 0,0x5233,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5234, 0, 0, 0,
+ 0,0x5235, 0, 0, 0, 0,0x5236, 0,
+0x5237,0x5238, 0, 0, 0, 0,0x5239, 0,
+ 0, 0, 0,0x523A, 0, 0,0x523B, 0,
+0x523C, 0, 0, 0, 0,0x523D, 0, 0,
+ 0, 0, 0, 0,0x523E, 0, 0,0x523F,
+0x5240, 0,0x5241, 0, 0,0x5242,0x5243, 0,
+ 0, 0,0x5244,0x5245,0x5246,0x5247, 0, 0,
+ 0, 0,0x5248, 0, 0,0x5249, 0, 0,
+0x524A, 0,0x524B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x524C, 0,0x524D,0x524E,
+ 0,0x524F,0x5250,0x5251, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5252, 0,0x5253, 0, 0, 0, 0, 0,
+ 0, 0,0x5254, 0,0x5255,0x5256, 0, 0,
+0x5257,0x5258,0x5259, 0,0x525A, 0,0x525B, 0,
+ 0,0x525C,0x525D,0x525E,0x525F, 0,0x5260, 0,
+ 0,0x5261, 0,0x5262,0x5263, 0,0x5264,0x5265,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5266, 0,0x5267, 0, 0, 0, 0,
+0x5268, 0, 0, 0, 0,0x5269,0x526A, 0,
+0x526B, 0, 0, 0,0x526C, 0, 0, 0,
+ 0,0x526D, 0,0x526E,0x526F, 0,0x5270, 0,
+ 0,0x5271,0x5272, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5273, 0,
+ 0, 0,0x5274, 0, 0, 0, 0, 0,
+ 0,0x5276,0x5277,0x5278, 0,0x5275, 0, 0,
+ 0,0x5279,0x527A,0x527B,0x527C,0x527D,0x527E, 0,
+ 0,0x5321, 0,0x5322, 0, 0, 0,0x5323,
+ 0,0x5324, 0, 0, 0,0x5325,0x5326, 0,
+0x5327, 0,0x5328, 0, 0, 0, 0, 0,
+ 0,0x5329, 0, 0,0x532A,0x532B, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x532C,0x532D,
+ 0, 0, 0, 0, 0, 0, 0,0x532E,
+ 0, 0, 0, 0,0x532F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5330, 0,
+0x5331, 0, 0, 0, 0, 0,0x5332, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5333, 0, 0, 0, 0, 0,0x5334,0x5335,
+ 0, 0,0x5336,0x5337,0x5338, 0, 0,0x5339,
+ 0, 0, 0, 0,0x533A, 0, 0,0x533B,
+0x533C,0x533D, 0, 0, 0,0x533E, 0,0x533F,
+ 0, 0, 0,0x5340,0x5341,0x5342, 0,0x5343,
+ 0,0x5344,0x5345, 0, 0,0x5346, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5347, 0,
+ 0,0x5348, 0,0x5349, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x534A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x534B, 0, 0, 0,0x534C,
+0x534D,0x534E, 0, 0, 0, 0, 0,0x534F,
+ 0,0x5350,0x5351,0x5352, 0, 0,0x5353, 0,
+ 0, 0, 0, 0, 0,0x5354,0x5355, 0,
+ 0, 0, 0,0x5356, 0, 0,0x5357, 0,
+ 0, 0,0x5358, 0, 0,0x5359, 0, 0,
+ 0,0x535A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x535B,0x535C,0x535D, 0,
+0x535E,0x535F, 0, 0, 0, 0, 0,0x5360,
+0x5361, 0, 0, 0, 0,0x5362, 0, 0,
+ 0,0x5363, 0,0x5364, 0, 0, 0,0x5365,
+ 0,0x5366,0x5367, 0,0x5368,0x5369, 0, 0,
+ 0, 0, 0, 0, 0,0x536A, 0,0x536B,
+ 0, 0,0x536C, 0, 0, 0, 0, 0,
+0x536D, 0, 0, 0, 0, 0, 0, 0,
+0x536E, 0,0x536F,0x5370, 0, 0, 0,0x5371,
+ 0,0x5372,0x5373,0x5374, 0,0x5375,0x5376, 0,
+0x5377, 0, 0,0x5378,0x5379,0x537A, 0, 0,
+ 0,0x537B, 0, 0, 0, 0,0x537C,0x537D,
+ 0, 0, 0, 0, 0,0x537E,0x5421, 0,
+ 0, 0, 0, 0, 0, 0,0x5422,0x5423,
+ 0, 0,0x5424, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5425, 0, 0,0x5426,0x5427,
+ 0,0x5428, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5429,0x542A,0x542B,0x542C,0x542D, 0,
+ 0, 0, 0, 0,0x542E,0x542F,0x5430, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5431,
+ 0,0x5432, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5434, 0, 0,0x5435,0x5436, 0,
+ 0, 0,0x5437,0x5438, 0,0x5439, 0, 0,
+ 0,0x543A, 0, 0, 0,0x543B,0x543C, 0,
+ 0,0x543D,0x543E, 0, 0, 0, 0, 0,
+0x5433, 0, 0, 0, 0, 0, 0, 0,
+0x543F, 0, 0, 0, 0, 0, 0, 0,
+0x5440,0x5441, 0, 0, 0,0x5442, 0,0x5443,
+ 0, 0, 0, 0,0x5444,0x5445, 0, 0,
+0x5446, 0, 0, 0, 0, 0, 0,0x5447,
+0x5448, 0, 0, 0,0x5449,0x544A, 0,0x544B,
+ 0, 0, 0,0x544C, 0, 0,0x544D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x544E,
+ 0, 0, 0, 0,0x544F,0x5450, 0,0x5451,
+ 0, 0, 0, 0, 0, 0,0x5452, 0,
+0x5453, 0,0x5454, 0, 0, 0, 0, 0,
+0x5455, 0, 0, 0, 0, 0, 0,0x5456,
+ 0,0x5457,0x5458, 0, 0,0x5459, 0, 0,
+ 0, 0, 0,0x545A, 0, 0,0x545B,0x545C,
+ 0, 0, 0,0x545D, 0, 0, 0, 0,
+0x545E, 0, 0, 0, 0, 0,0x545F, 0,
+ 0,0x5460, 0, 0, 0, 0,0x5461,0x5462,
+ 0, 0,0x5463, 0, 0,0x5464, 0, 0,
+ 0,0x5465, 0, 0, 0,0x5466, 0, 0,
+0x5467, 0,0x5468, 0, 0,0x5469,0x546A};
+
+/* page 27 0x7F3B-0x8044 */
+static uint16 tab_uni_jisx021227[]={
+0x546C,0x546B,0x546D,0x546E,0x546F, 0, 0, 0,
+0x5470,0x5471, 0, 0,0x5472, 0, 0, 0,
+ 0, 0, 0, 0,0x5473, 0, 0,0x5474,
+0x5475, 0, 0, 0, 0, 0, 0, 0,
+0x5476,0x5477,0x5478, 0, 0, 0,0x5479, 0,
+0x547A,0x547B,0x547C,0x547D, 0, 0, 0, 0,
+ 0, 0,0x547E, 0, 0, 0,0x5521, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5522,0x5523,0x5524,0x5525, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5526, 0,0x5527, 0,0x5528,0x5529,0x552A, 0,
+ 0, 0, 0,0x552B,0x552C, 0, 0, 0,
+ 0,0x552D, 0, 0, 0, 0,0x552E,0x552F,
+ 0, 0, 0,0x5530, 0, 0, 0,0x5531,
+ 0, 0,0x5532, 0, 0, 0, 0, 0,
+ 0,0x5533, 0, 0, 0, 0, 0, 0,
+ 0,0x5534, 0, 0,0x5535,0x5536, 0, 0,
+0x5537, 0, 0, 0, 0,0x5538, 0, 0,
+ 0, 0, 0,0x5539,0x553A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x553B, 0, 0, 0,0x553C, 0, 0, 0,
+0x553D, 0,0x553E, 0, 0,0x553F, 0, 0,
+ 0,0x5540, 0,0x5541,0x5542, 0, 0,0x5543,
+ 0, 0, 0, 0, 0, 0, 0,0x5544,
+ 0, 0,0x5545,0x5546,0x5547, 0, 0, 0,
+ 0, 0, 0, 0,0x5548,0x5549, 0,0x554A,
+ 0, 0,0x554B,0x554C,0x554D, 0,0x554E, 0,
+0x554F,0x5550, 0,0x5551, 0, 0, 0, 0,
+ 0, 0,0x5552,0x5553,0x5554,0x5555, 0, 0,
+ 0,0x5556, 0,0x5557, 0, 0, 0, 0,
+ 0,0x5558, 0,0x5559, 0,0x555A, 0, 0,
+ 0,0x555B,0x555C, 0,0x555D, 0,0x555E,0x555F,
+ 0,0x5560, 0,0x5561, 0,0x5562, 0, 0,
+ 0,0x5563};
+
+/* page 28 0x8060-0x8357 */
+static uint16 tab_uni_jisx021228[]={
+0x5564, 0, 0, 0,0x5565, 0,0x5566, 0,
+ 0, 0, 0, 0, 0,0x5567, 0, 0,
+ 0,0x5568, 0, 0, 0,0x5569, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x556A, 0, 0, 0, 0, 0, 0,
+0x556B, 0, 0, 0, 0, 0,0x556C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x556D, 0,0x556E, 0,
+ 0, 0, 0, 0, 0, 0,0x556F,0x5570,
+ 0, 0, 0,0x5571, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5572,0x5573, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5574, 0, 0, 0, 0,0x5575, 0,0x5576,
+ 0, 0,0x5577, 0,0x5578,0x5579, 0,0x557A,
+0x557B, 0, 0, 0, 0, 0, 0, 0,
+0x557C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x557D,0x557E, 0,
+0x5621, 0,0x5622,0x5623, 0, 0,0x5624, 0,
+ 0,0x5625,0x5626, 0, 0, 0,0x5627, 0,
+ 0, 0, 0,0x5628, 0, 0, 0, 0,
+ 0, 0, 0,0x5629, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x562A,0x562B,
+0x562C, 0, 0, 0,0x562D, 0,0x562E, 0,
+0x562F, 0, 0, 0,0x5630, 0, 0,0x5631,
+ 0, 0, 0, 0,0x5632, 0, 0, 0,
+0x5633, 0, 0, 0, 0,0x5634, 0, 0,
+ 0, 0,0x5635, 0,0x5636, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5637, 0,0x5638,
+ 0, 0,0x5639, 0,0x563A, 0, 0, 0,
+ 0, 0,0x563B, 0, 0, 0, 0,0x563C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x563D,0x563E, 0, 0, 0, 0, 0,0x563F,
+0x5640,0x5641, 0, 0, 0,0x5642, 0,0x5643,
+ 0, 0, 0, 0, 0, 0, 0,0x5644,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5645, 0, 0,0x5647,0x5648,0x5649, 0,
+ 0, 0, 0,0x564A, 0, 0,0x564B, 0,
+0x5646, 0, 0, 0, 0, 0,0x564C, 0,
+0x564D, 0, 0,0x564E, 0, 0,0x564F, 0,
+ 0, 0,0x5650, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5651, 0,
+ 0, 0,0x5652, 0,0x5653, 0, 0, 0,
+ 0, 0, 0,0x5654, 0, 0, 0, 0,
+ 0, 0, 0,0x5656, 0,0x5657, 0, 0,
+ 0, 0,0x5658,0x5655, 0, 0,0x5659,0x565A,
+ 0, 0, 0, 0, 0,0x565B, 0,0x565C,
+ 0, 0, 0,0x565D, 0,0x565E,0x565F, 0,
+ 0,0x5660, 0, 0,0x5661, 0, 0, 0,
+ 0, 0, 0,0x5662,0x5663, 0, 0, 0,
+0x5664,0x5665,0x5666, 0, 0,0x5667,0x5668, 0,
+0x5669,0x566A, 0, 0, 0,0x566B, 0,0x566C,
+0x566D, 0, 0,0x566E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x566F,
+ 0, 0, 0,0x5670,0x5671, 0, 0, 0,
+ 0,0x5672,0x5673, 0, 0,0x5674, 0, 0,
+ 0,0x5675,0x5676, 0, 0, 0, 0, 0,
+0x5677, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5678, 0,0x5679, 0, 0, 0,
+ 0, 0,0x567A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x567B,0x567C,0x567D,0x567E, 0,
+ 0, 0, 0,0x5721, 0, 0,0x5722,0x5723,
+ 0,0x5724, 0, 0, 0, 0,0x5725, 0,
+ 0, 0, 0, 0,0x5726, 0, 0, 0,
+0x5727, 0, 0,0x5728, 0, 0, 0,0x5729,
+ 0, 0, 0, 0, 0,0x572A, 0, 0,
+ 0, 0, 0, 0,0x572B, 0, 0, 0,
+ 0, 0, 0,0x572C, 0,0x572D, 0,0x572E,
+0x572F,0x5730, 0,0x5731,0x5732, 0, 0,0x5733,
+ 0,0x5734,0x5735, 0, 0, 0,0x5736, 0,
+ 0,0x5737, 0, 0,0x5738, 0,0x5739, 0,
+0x573A, 0,0x573B,0x573C, 0, 0, 0, 0,
+0x573D,0x573E, 0,0x573F,0x5740, 0, 0,0x5741,
+0x5742,0x5743,0x5744, 0, 0, 0,0x5745, 0,
+0x5746, 0,0x5747, 0,0x5748, 0, 0,0x5749,
+ 0, 0,0x574A, 0,0x574B, 0,0x574C,0x574D,
+ 0, 0, 0, 0, 0, 0,0x574E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x574F, 0, 0, 0, 0,0x5750, 0, 0,
+ 0, 0,0x5751, 0, 0, 0, 0, 0,
+0x5752, 0,0x5753, 0,0x5754, 0, 0, 0,
+0x5755, 0,0x5756, 0, 0,0x5757, 0,0x5758,
+ 0, 0, 0, 0, 0, 0,0x5759,0x575A,
+ 0, 0, 0, 0, 0,0x575B,0x575C, 0,
+0x575D,0x575E, 0, 0, 0, 0, 0,0x575F,
+0x5760, 0,0x5761,0x5762, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5764, 0,0x5765,0x5766,0x5767,
+ 0,0x5768,0x5769, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x576A,0x576B,0x576C, 0,
+0x576D, 0, 0,0x576E, 0, 0, 0,0x576F,
+ 0, 0,0x5770, 0,0x5771,0x5772, 0, 0,
+ 0, 0,0x5773,0x5774,0x5775, 0, 0,0x5776,
+ 0, 0, 0, 0, 0,0x5777,0x5778, 0,
+ 0,0x5779, 0,0x583E,0x5763,0x577A,0x577B,0x577C
+};
+
+/* page 29 0x8370-0x8419 */
+static uint16 tab_uni_jisx021229[]={
+0x577D, 0, 0, 0, 0, 0, 0, 0,
+0x577E, 0, 0, 0, 0,0x5821, 0,0x5822,
+0x5823, 0,0x5824, 0,0x5825, 0,0x5826, 0,
+ 0, 0, 0, 0, 0,0x5827, 0, 0,
+ 0, 0,0x5828, 0,0x5829,0x582A, 0, 0,
+0x582B,0x582C, 0,0x582D,0x582E,0x582F, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5830,0x5831,
+ 0,0x5832, 0, 0,0x5833,0x584C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5834,0x5835,
+0x5836, 0, 0, 0, 0, 0, 0,0x5837,
+ 0,0x5838, 0, 0, 0, 0, 0,0x5839,
+0x583A,0x583B, 0, 0,0x583C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x583D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x583F, 0,0x5840, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5841, 0,
+0x5842,0x5843, 0, 0,0x5844, 0, 0, 0,
+ 0,0x5845, 0, 0, 0, 0,0x5846, 0,
+ 0, 0,0x5847, 0, 0, 0, 0,0x5848,
+ 0,0x5849, 0, 0, 0,0x584A, 0, 0,
+ 0,0x584B};
+
+/* page 30 0x842F-0x8880 */
+static uint16 tab_uni_jisx021230[]={
+0x584D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x584E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x584F, 0,
+0x5850,0x5851, 0,0x5852, 0, 0,0x5853, 0,
+0x5854, 0,0x5855,0x5856, 0, 0, 0,0x5857,
+ 0,0x5858,0x5859,0x585A, 0,0x585B, 0, 0,
+ 0,0x585C, 0, 0, 0,0x585D,0x585E, 0,
+0x585F, 0, 0,0x5860, 0, 0, 0, 0,
+ 0,0x5861, 0, 0,0x5862,0x5863, 0,0x5864,
+ 0,0x5865, 0, 0, 0,0x5866,0x5867, 0,
+ 0, 0,0x5868, 0, 0, 0,0x5869, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x586A,0x586B, 0,0x586C, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x586D,
+ 0, 0, 0, 0, 0, 0, 0,0x586E,
+ 0,0x586F,0x5870,0x5871, 0, 0, 0, 0,
+0x5872, 0,0x5873, 0, 0,0x5874, 0, 0,
+ 0, 0, 0,0x5875, 0, 0,0x5876,0x5877,
+ 0,0x5878, 0,0x5879, 0, 0, 0, 0,
+0x587A,0x587B, 0, 0, 0,0x587C, 0, 0,
+0x587D, 0, 0, 0,0x587E, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5921, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5922, 0, 0,0x5923, 0, 0, 0, 0,
+0x5924,0x5925,0x5926,0x5927, 0, 0, 0, 0,
+0x5928, 0, 0,0x592A,0x592B, 0,0x592C, 0,
+ 0, 0, 0,0x592D,0x592E, 0, 0, 0,
+0x592F, 0, 0, 0, 0,0x5930, 0,0x5931,
+ 0,0x5932, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5933, 0,0x5934,
+ 0, 0, 0,0x5935,0x5936,0x5937,0x5938, 0,
+0x5939, 0, 0,0x593A,0x593B, 0, 0, 0,
+0x593C, 0, 0,0x5929,0x593D,0x593E, 0,0x593F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5940, 0, 0, 0, 0, 0, 0,0x5941,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5942,0x5943,0x5944,0x5945,0x5946, 0, 0,0x5947,
+ 0, 0,0x5948, 0, 0,0x5949,0x594A,0x594B,
+0x594C,0x594D,0x594E,0x594F, 0,0x5950, 0, 0,
+ 0, 0, 0, 0,0x5951, 0, 0, 0,
+0x5952, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5953,0x5954,0x5955, 0,0x5956, 0,
+0x5957, 0,0x5958, 0, 0, 0,0x5959,0x595A,
+ 0, 0,0x595B, 0,0x595C,0x595D, 0, 0,
+0x595E, 0, 0, 0,0x595F, 0, 0, 0,
+ 0,0x5960, 0, 0, 0, 0,0x5961, 0,
+0x5962,0x5963, 0,0x5964, 0, 0,0x5965, 0,
+0x5966, 0, 0, 0, 0, 0,0x5974, 0,
+ 0, 0, 0, 0, 0,0x5967, 0,0x5968,
+0x5969,0x596A, 0, 0, 0,0x596B,0x596C,0x596D,
+0x596E, 0, 0,0x596F, 0, 0, 0, 0,
+0x5970, 0, 0,0x5971,0x5972, 0, 0,0x5973,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5975, 0,0x5976, 0, 0, 0, 0,
+0x5977,0x5978, 0, 0, 0, 0, 0,0x5979,
+ 0,0x597A, 0, 0, 0, 0,0x597B, 0,
+ 0, 0, 0, 0,0x597C, 0, 0,0x597D,
+ 0, 0, 0, 0, 0,0x597E, 0, 0,
+0x5A21,0x5A22, 0, 0, 0,0x5A23,0x5A24, 0,
+ 0, 0, 0, 0, 0, 0,0x5A25,0x5A26,
+ 0,0x5A27,0x5A28,0x5A29, 0, 0, 0, 0,
+ 0,0x5A2A,0x5A2B, 0,0x5A2C, 0, 0,0x5A2D,
+ 0, 0,0x5A2E, 0, 0, 0, 0, 0,
+0x5A2F, 0,0x5A30, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5A31,
+ 0,0x5A32, 0,0x5A33, 0,0x5A34,0x5A35, 0,
+ 0,0x5A36,0x3866,0x5A37, 0, 0, 0,0x5A38,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5A39,0x5A3A, 0, 0,0x5A3B,
+0x5A3C,0x5A3D,0x5A3E, 0, 0, 0,0x5A3F, 0,
+ 0,0x5A40,0x5A41,0x5A42,0x5A43,0x5A44, 0, 0,
+ 0, 0,0x5A45, 0, 0,0x5A46, 0, 0,
+0x5A47, 0, 0, 0, 0, 0,0x5A48,0x5A49,
+0x5A4A, 0, 0,0x5A4B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5A6D, 0, 0, 0, 0,0x5A4C, 0,
+ 0, 0,0x5A4D, 0, 0, 0, 0,0x5A4E,
+ 0,0x5A4F, 0,0x5A50, 0,0x5A51, 0, 0,
+ 0, 0,0x5A52, 0, 0, 0, 0,0x5A53,
+0x5A54,0x5A55, 0, 0, 0, 0,0x5A56, 0,
+ 0, 0,0x5A57, 0,0x5A58,0x5A59,0x5A5A, 0,
+0x5A5B,0x5A5C,0x5A5D, 0, 0, 0, 0, 0,
+0x5A5E,0x5A5F,0x5A60, 0,0x5A61, 0,0x5A62, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5A63,0x5A64, 0, 0,0x5A65, 0,
+0x5A66, 0, 0,0x5A67, 0,0x5A68, 0, 0,
+ 0,0x5A69, 0, 0,0x5A6A, 0,0x5A6B, 0,
+0x5A6C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5A6E, 0,0x5A6F,0x5A70, 0,
+ 0, 0, 0, 0, 0,0x5A71,0x5A72, 0,
+0x5A73, 0, 0, 0,0x5A74, 0, 0,0x5A75,
+0x5A76,0x5A77, 0, 0,0x5A78,0x5A79, 0, 0,
+ 0, 0,0x5A7A, 0, 0, 0, 0,0x5A7B,
+0x5A7C, 0,0x5A7D, 0,0x5A7E, 0, 0, 0,
+ 0,0x5B21, 0, 0, 0, 0, 0,0x5B22,
+0x5B23, 0,0x5B24,0x5B25, 0, 0, 0, 0,
+ 0, 0,0x5B26,0x5B27, 0,0x5B28,0x5B29,0x5B2A,
+ 0,0x5B2B, 0, 0,0x5B2C, 0,0x5B2D, 0,
+ 0, 0, 0, 0, 0, 0,0x5B2E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B2F, 0, 0, 0, 0,0x5B30, 0,
+ 0, 0,0x5B31, 0, 0,0x5B32,0x5B33, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5B34, 0,0x5B35,0x5B36, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5B37, 0, 0, 0,
+ 0, 0, 0, 0,0x5B38,0x5B39,0x5B3A,0x5B3B,
+0x5B3C,0x5B3D,0x5B3E, 0,0x5B3F,0x5B40, 0, 0,
+ 0,0x5B41, 0, 0,0x5B42, 0,0x5B43, 0,
+0x5B44,0x5B45,0x5B46, 0, 0, 0, 0,0x5B47,
+ 0,0x5B48, 0, 0,0x5B49, 0, 0, 0,
+0x5B4A, 0, 0, 0, 0,0x5B4B,0x5B4C,0x5B4D,
+ 0, 0,0x5B4E, 0, 0, 0,0x5B4F, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5B50,
+0x5B51, 0,0x5B52, 0, 0, 0, 0, 0,
+ 0,0x5B53,0x5B54,0x5B55, 0, 0, 0,0x5B56,
+ 0, 0, 0, 0, 0, 0,0x5B57,0x5B58,
+ 0, 0,0x5B59,0x5B5A, 0,0x5B5B, 0, 0,
+0x5B5C, 0, 0,0x5B5D,0x5B5E,0x5B5F, 0, 0,
+ 0, 0, 0,0x5B60,0x5B61, 0,0x5B62, 0,
+ 0, 0,0x5B63, 0,0x5B64, 0, 0, 0,
+ 0,0x5B65, 0,0x5B66, 0, 0, 0, 0,
+0x5B67, 0,0x5B68, 0,0x5B69, 0, 0,0x5B6A,
+ 0, 0,0x5B6B,0x5B6C,0x5B6D, 0, 0, 0,
+ 0,0x5B6E, 0,0x5B70,0x5B71,0x5B72, 0, 0,
+ 0,0x5B73,0x5B6F,0x5B74,0x5B75,0x5B76, 0,0x5B77,
+0x5B78, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B79, 0, 0, 0, 0,0x5B7A,0x5B7B,
+ 0,0x5B7C, 0,0x5B7D, 0, 0,0x5B7E, 0,
+ 0, 0, 0,0x5C21, 0,0x5C22, 0, 0,
+ 0, 0,0x5C23, 0,0x5C24, 0,0x5C25, 0,
+ 0,0x5C26,0x5C27,0x5C28,0x5C29, 0, 0,0x5C2A,
+ 0, 0,0x5C2B, 0, 0, 0,0x5C2C,0x5C2D,
+ 0,0x5C2E, 0,0x5C2F, 0,0x5C30, 0, 0,
+0x5C31,0x5C32, 0, 0, 0,0x5C33, 0, 0,
+ 0, 0,0x5C34, 0, 0, 0, 0, 0,
+ 0, 0,0x5C35, 0, 0, 0, 0, 0,
+ 0, 0,0x5C36, 0,0x5C37, 0, 0, 0,
+ 0,0x5C38};
+
+/* page 31 0x8898-0x89BC */
+static uint16 tab_uni_jisx021231[]={
+0x5C39, 0,0x5C3A,0x5C3B,0x5C3C, 0, 0,0x5C3D,
+0x5C3E, 0, 0, 0, 0, 0, 0, 0,
+0x5C3F, 0,0x5C40, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C41, 0, 0,0x5C42,0x5C43, 0,
+0x5C44, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C45,0x5C46,0x5C47,0x5C48,0x5C49, 0,
+ 0,0x5C4A,0x5C4B,0x5C4C, 0, 0, 0, 0,
+ 0, 0, 0,0x5C4D, 0, 0,0x5C4E, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5C4F,
+ 0, 0, 0, 0, 0, 0, 0,0x5C50,
+0x5C51,0x5C52, 0, 0, 0,0x5C53, 0,0x5C54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5C55, 0, 0, 0, 0,0x5C56, 0,
+ 0, 0, 0, 0, 0,0x5C57,0x5C58,0x5C59,
+ 0, 0, 0, 0, 0,0x5C5A,0x5C5B, 0,
+0x5C5C,0x5C5D,0x5C5E, 0,0x5C5F, 0, 0, 0,
+0x5C60, 0, 0, 0, 0, 0,0x5C61,0x5C62,
+0x5C63, 0, 0, 0, 0, 0, 0, 0,
+0x5C64,0x5C65,0x5C66, 0, 0,0x5C67, 0, 0,
+ 0,0x5C68,0x5C69, 0, 0, 0,0x5C6A, 0,
+0x5C6B, 0,0x5C6C, 0, 0,0x5C6D,0x5C6E, 0,
+ 0,0x5C6F, 0, 0, 0, 0, 0,0x5C70,
+ 0, 0,0x5C71, 0, 0, 0, 0,0x5C72,
+ 0, 0,0x5C73,0x5C74,0x5C75, 0, 0, 0,
+ 0,0x5C76,0x5C77,0x5C78, 0, 0, 0, 0,
+ 0, 0, 0,0x5C79, 0, 0,0x5C7A, 0,
+0x5C7B, 0, 0,0x5C7C, 0,0x5C7D, 0, 0,
+ 0, 0,0x5C7E,0x5D21,0x5D22,0x5D23, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D24, 0, 0, 0,0x5D25, 0, 0,
+0x5D26, 0, 0, 0,0x5D27,0x5D28, 0, 0,
+ 0, 0, 0,0x5D29,0x5D2A, 0, 0,0x5D2B,
+0x5D2C, 0, 0, 0, 0,0x5D2D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5D2E, 0, 0, 0,0x5D2F,0x5D30,0x5D31,0x5D32,
+ 0, 0, 0, 0,0x5D33};
+
+/* page 32 0x89D4-0x8B9F */
+static uint16 tab_uni_jisx021232[]={
+0x5D34,0x5D35,0x5D36,0x5D37,0x5D38, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D39, 0, 0, 0,0x5D3A, 0,0x5D3B,
+ 0,0x5D3C, 0, 0, 0,0x5D3D, 0,0x5D3E,
+ 0, 0,0x5D3F, 0, 0,0x5D40, 0, 0,
+ 0,0x5D41, 0,0x5D42, 0, 0, 0, 0,
+0x5D43,0x5D44, 0,0x5D45, 0, 0, 0, 0,
+ 0, 0, 0,0x5D46, 0,0x5D47,0x5D48, 0,
+0x5D49,0x5D4A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5D4B, 0,0x5D4C, 0,0x5D4D, 0,
+0x5D4E, 0,0x5D4F, 0, 0, 0, 0,0x5D50,
+0x5D51, 0, 0,0x5D52, 0, 0, 0, 0,
+ 0,0x5D53, 0,0x5D54, 0, 0, 0, 0,
+ 0,0x5D55,0x5D56, 0,0x5D57, 0, 0,0x5D58,
+ 0,0x5D59, 0,0x5D5A, 0,0x5D5B, 0, 0,
+ 0,0x5D5C,0x5D5D, 0, 0, 0, 0,0x5D5E,
+ 0, 0,0x5D5F,0x5D60,0x5D61, 0, 0, 0,
+0x5D62,0x5D63, 0, 0, 0,0x5D64, 0, 0,
+ 0,0x5D65, 0,0x5D66, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D67,0x5D68,0x5D69, 0,0x5D6A,0x5D6B,0x5D6C,
+ 0, 0,0x5D6D,0x5D6E,0x5D6F, 0, 0,0x5D70,
+ 0, 0,0x5D71, 0, 0, 0, 0,0x5D72,
+ 0, 0, 0,0x5D73,0x5D74, 0,0x5D75, 0,
+ 0, 0,0x5D76,0x5D77, 0,0x5D78, 0, 0,
+ 0, 0, 0,0x5D79, 0, 0, 0, 0,
+ 0, 0, 0,0x5D7A, 0,0x5D7B, 0, 0,
+ 0, 0,0x5D7C,0x5D7D, 0, 0, 0,0x5D7E,
+ 0, 0,0x5E21,0x5E22, 0, 0, 0,0x5E23,
+ 0, 0,0x5E24, 0, 0, 0, 0,0x5E25,
+ 0, 0,0x5E26, 0,0x5E27,0x5E28,0x5E29, 0,
+ 0, 0, 0, 0, 0,0x5E2A, 0,0x5E2B,
+0x5E2C,0x5E2D, 0,0x5E2E, 0, 0, 0, 0,
+ 0,0x5E2F, 0,0x5E30, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5E31, 0, 0, 0,0x5E32, 0, 0, 0,
+0x5E33,0x5E34,0x5E35, 0, 0, 0, 0, 0,
+0x5E36, 0, 0,0x5E37, 0, 0, 0, 0,
+ 0,0x5E38,0x5E39, 0, 0, 0,0x5E3F,0x5E3A,
+ 0, 0, 0, 0, 0,0x5E3B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5E3C, 0,0x5E3D,0x5E3E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E40, 0, 0,0x5E41, 0, 0, 0,
+ 0, 0, 0,0x5E42, 0, 0, 0, 0,
+0x5E43, 0, 0, 0, 0, 0,0x5E44,0x5E45,
+0x5E46,0x5E47,0x5E48, 0,0x5E49, 0, 0, 0,
+ 0,0x5E4E, 0, 0, 0, 0,0x5E4A,0x5E4B,
+0x5E4C, 0, 0, 0, 0,0x5E4D, 0, 0,
+ 0, 0,0x5E4F, 0, 0, 0, 0,0x5E50,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E51, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5E52, 0,0x5E53,0x5E54, 0, 0,
+0x5E55, 0,0x5E56, 0, 0,0x5E57, 0, 0,
+0x5E58,0x5E59, 0, 0, 0, 0, 0,0x5E5A,
+ 0,0x5E5B, 0,0x5E5C, 0, 0, 0, 0,
+0x5E5D,0x5E5E, 0, 0, 0, 0, 0, 0,
+0x5E5F, 0,0x5E60,0x5E61};
+
+/* page 33 0x8C38-0x8CA4 */
+static uint16 tab_uni_jisx021233[]={
+0x5E62,0x5E63, 0, 0, 0,0x5E64,0x5E65, 0,
+ 0, 0, 0, 0, 0,0x5E66, 0,0x5E67,
+ 0,0x5E68, 0,0x5E69, 0, 0, 0,0x5E6A,
+ 0,0x5E6B, 0,0x5E6C,0x5E6D, 0, 0,0x5E6E,
+0x5E6F,0x5E72, 0,0x5E70, 0,0x5E71, 0, 0,
+ 0, 0, 0,0x5E73,0x5E74, 0,0x5E75, 0,
+0x5E76,0x5E77, 0, 0, 0,0x5E78, 0, 0,
+ 0, 0, 0,0x5E79, 0,0x5E7A,0x5E7B, 0,
+ 0, 0, 0,0x5E7C, 0, 0,0x5E7D, 0,
+ 0, 0, 0, 0, 0, 0,0x5E7E,0x5F21,
+ 0, 0, 0,0x5F22, 0, 0, 0, 0,
+0x5F23, 0,0x5F24,0x5F25, 0, 0, 0, 0,
+ 0,0x5F26, 0,0x5F27,0x5F28, 0, 0, 0,
+ 0, 0, 0, 0,0x5F29};
+
+/* page 34 0x8CB9-0x8D1B */
+static uint16 tab_uni_jisx021234[]={
+0x5F2A,0x5F2B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5F2C,0x5F2D, 0, 0,
+0x5F2E, 0,0x5F2F, 0, 0, 0,0x5F30, 0,
+ 0, 0, 0, 0,0x5F32,0x5F31, 0, 0,
+0x5F33, 0, 0, 0,0x5F34, 0, 0, 0,
+0x5F35, 0, 0, 0, 0, 0, 0,0x5F36,
+ 0, 0, 0,0x5F37, 0, 0,0x5F38,0x5F39,
+ 0,0x5F3A, 0, 0,0x5F3B, 0,0x5F3C,0x5F3D,
+ 0, 0, 0, 0, 0,0x5F3E,0x5F3F, 0,
+0x5F40, 0,0x5F41, 0, 0, 0, 0, 0,
+0x5F42, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F43, 0, 0, 0, 0,0x5F44, 0,
+ 0, 0,0x5F45};
+
+/* page 35 0x8D65-0x8F65 */
+static uint16 tab_uni_jisx021235[]={
+0x5F46, 0, 0, 0,0x5F47, 0, 0,0x5F48,
+ 0,0x5F49, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5F4A, 0, 0,0x5F4B, 0,0x5F4C,
+ 0, 0, 0,0x5F4D, 0, 0, 0, 0,
+0x5F4E, 0, 0,0x5F4F,0x5F50, 0, 0, 0,
+0x5F51, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F52,0x5F53,0x5F54, 0, 0, 0, 0,
+ 0,0x5F55, 0, 0, 0, 0,0x5F56,0x5F57,
+ 0, 0,0x5F58, 0, 0,0x5F59, 0, 0,
+0x5F5A, 0,0x5F5B, 0,0x5F5C, 0,0x5F5D,0x5F6F,
+ 0, 0, 0,0x5F5E, 0, 0, 0, 0,
+0x5F5F,0x5F60,0x5F61,0x5F62, 0,0x5F63, 0, 0,
+ 0,0x5F64, 0, 0,0x5F65, 0, 0,0x5F66,
+0x5F67, 0,0x5F68, 0,0x5F69, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5F6A,
+0x5F6B, 0,0x5F6C, 0, 0, 0, 0,0x5F6D,
+ 0, 0, 0,0x5F6E,0x5F70,0x5F71, 0,0x5F72,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F73, 0, 0, 0,0x5F74, 0, 0,0x5F75,
+0x5F76,0x5F77, 0, 0, 0, 0,0x5F78, 0,
+ 0, 0, 0, 0,0x5F79, 0, 0,0x5F7A,
+ 0,0x5F7B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5F7C,0x5F7D,0x5F7E,0x6021, 0,
+ 0,0x6022,0x6023, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6024, 0,0x6025, 0,
+ 0,0x6026,0x6027,0x6028,0x6029, 0, 0, 0,
+0x602A, 0, 0,0x602B,0x602C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x602D, 0,
+0x602E,0x602F,0x6030, 0, 0, 0, 0,0x6031,
+ 0, 0, 0, 0, 0, 0,0x6032,0x6033,
+0x6034,0x6035, 0, 0,0x6036,0x6037, 0, 0,
+ 0, 0, 0, 0,0x6038, 0, 0,0x6039,
+0x603A, 0,0x603B,0x603C,0x603D, 0, 0, 0,
+ 0, 0, 0, 0,0x603E,0x603F,0x6040, 0,
+ 0, 0, 0, 0, 0,0x6041,0x6042, 0,
+ 0, 0, 0, 0,0x6043, 0, 0, 0,
+ 0, 0, 0,0x6044, 0,0x6045, 0, 0,
+0x6046, 0, 0, 0, 0,0x6047,0x6048, 0,
+0x6049,0x604A, 0, 0, 0,0x604B, 0, 0,
+ 0, 0,0x604C, 0,0x604D, 0, 0, 0,
+0x604E,0x604F, 0, 0, 0, 0,0x6050, 0,
+0x6051, 0, 0, 0, 0,0x6052,0x6053, 0,
+ 0, 0, 0,0x6054,0x6055, 0,0x6056,0x6057,
+ 0, 0,0x6058, 0, 0, 0, 0, 0,
+ 0, 0,0x6059, 0,0x605A, 0, 0,0x605B,
+ 0, 0, 0, 0, 0, 0, 0,0x605C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x605D, 0, 0, 0, 0,
+0x6064,0x605E, 0,0x605F,0x6060, 0, 0, 0,
+ 0, 0,0x6061, 0,0x6062,0x6063, 0, 0,
+ 0, 0, 0,0x6065, 0,0x6066, 0, 0,
+ 0, 0,0x6067,0x6068, 0, 0, 0, 0,
+ 0, 0,0x6069,0x606A, 0, 0, 0, 0,
+ 0,0x606B,0x606C,0x606D, 0, 0, 0, 0,
+ 0,0x606E, 0,0x606F,0x6070, 0,0x6071, 0,
+0x6072, 0,0x6073,0x6074, 0, 0, 0,0x6075,
+0x6076,0x6077, 0, 0, 0, 0, 0,0x6078,
+0x6079,0x607A,0x607B, 0, 0,0x607C, 0, 0,
+ 0, 0, 0,0x607D,0x607E, 0,0x6121, 0,
+ 0, 0,0x6122, 0, 0, 0, 0, 0,
+ 0, 0,0x6123, 0,0x6124,0x6125,0x6126,0x6127,
+0x6128, 0, 0,0x6129, 0, 0, 0, 0,
+0x612A,0x612B, 0, 0, 0, 0, 0, 0,
+0x612C};
+
+/* page 36 0x8F9D-0x9484 */
+static uint16 tab_uni_jisx021236[]={
+0x612D, 0, 0,0x612E,0x612F, 0, 0,0x6130,
+0x6131,0x6132, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6133,0x6134, 0,0x6135, 0, 0, 0, 0,
+ 0,0x6136, 0,0x6137,0x6138, 0, 0, 0,
+ 0,0x6139, 0, 0, 0,0x613A,0x613B, 0,
+0x613C, 0, 0,0x613D, 0,0x613E,0x613F, 0,
+0x6140, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6141, 0, 0,0x6142,0x6143,
+ 0, 0, 0,0x6144, 0, 0, 0, 0,
+ 0,0x6145, 0, 0,0x6146, 0, 0, 0,
+0x6147,0x6148, 0, 0, 0, 0,0x6149, 0,
+ 0,0x614A, 0, 0, 0,0x614B, 0,0x614C,
+ 0, 0, 0,0x614D, 0, 0, 0,0x614E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x614F, 0, 0,0x6150, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6151,0x6152,0x6154, 0,0x6155,
+0x6156, 0,0x6153, 0, 0, 0,0x6157,0x6158,
+ 0, 0,0x6159, 0, 0, 0, 0, 0,
+ 0, 0,0x615A, 0, 0, 0,0x615B,0x615C,
+ 0, 0, 0, 0, 0, 0, 0,0x615D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x615E, 0,
+0x615F, 0, 0, 0, 0,0x6160, 0, 0,
+ 0,0x6161,0x6162, 0, 0, 0, 0,0x6163,
+ 0, 0, 0,0x6164, 0, 0, 0,0x6165,
+ 0, 0, 0, 0,0x6166, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6167, 0, 0,0x6168, 0, 0,0x6169,0x616A,
+ 0,0x616B, 0,0x616C, 0, 0, 0, 0,
+0x616D, 0,0x616E,0x616F,0x6170, 0,0x6171, 0,
+ 0, 0, 0,0x6172,0x6173,0x6174, 0, 0,
+0x6175, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6176, 0,0x6177,0x6178,0x6179,
+ 0,0x617A, 0, 0, 0, 0, 0, 0,
+0x617B,0x617D, 0, 0, 0, 0,0x617E,0x6221,
+0x6222, 0,0x6223,0x6224, 0, 0, 0,0x617C,
+ 0, 0, 0, 0, 0,0x622D, 0, 0,
+0x6225, 0,0x6226,0x6227,0x6228, 0, 0,0x6229,
+0x622A, 0,0x622B, 0, 0, 0, 0, 0,
+0x622C, 0, 0, 0, 0, 0,0x622F, 0,
+ 0, 0,0x6230,0x6231, 0, 0, 0,0x6232,
+ 0,0x622E, 0, 0, 0, 0, 0, 0,
+ 0,0x6233,0x6234,0x6235, 0, 0, 0,0x6236,
+0x6237,0x6238, 0,0x6239, 0, 0, 0, 0,
+0x623A, 0, 0,0x623B, 0, 0, 0,0x623C,
+ 0,0x623D,0x623E,0x623F, 0,0x6240, 0,0x6241,
+ 0,0x6242, 0,0x6243, 0,0x6245,0x6246, 0,
+0x6244, 0,0x6247, 0,0x6248, 0, 0, 0,
+ 0,0x6249,0x624A, 0,0x624B, 0, 0,0x624C,
+ 0,0x624D,0x624E, 0,0x624F,0x6250, 0,0x6251,
+0x6252, 0, 0, 0, 0, 0,0x6253, 0,
+ 0, 0,0x6254,0x6255, 0, 0, 0, 0,
+ 0, 0,0x6256, 0, 0, 0,0x6257, 0,
+ 0, 0,0x6258, 0,0x6259,0x625A,0x625B, 0,
+ 0, 0, 0, 0,0x625C, 0, 0,0x625D,
+ 0, 0,0x625E, 0, 0, 0, 0, 0,
+0x625F, 0, 0, 0, 0, 0, 0,0x6260,
+ 0, 0, 0, 0,0x6261,0x6262,0x6263, 0,
+ 0, 0, 0, 0,0x6264, 0,0x6265, 0,
+0x6266,0x6267, 0, 0, 0,0x6268, 0, 0,
+ 0,0x6269, 0, 0,0x626A, 0,0x626B,0x626C,
+0x626D, 0, 0,0x626E, 0, 0, 0, 0,
+ 0,0x626F, 0, 0,0x6270, 0, 0, 0,
+ 0,0x6271, 0,0x6272, 0, 0, 0,0x6273,
+0x6274,0x6275, 0,0x6276,0x6277,0x6278,0x6279, 0,
+ 0,0x627A, 0, 0, 0, 0,0x627B,0x627C,
+0x627D, 0,0x627E, 0, 0,0x6321,0x6322, 0,
+0x6323, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6324,0x6325,
+ 0, 0,0x6326, 0,0x6327,0x6328, 0, 0,
+ 0,0x6329, 0, 0, 0, 0, 0,0x632A,
+0x632B, 0, 0, 0,0x632C,0x632D, 0,0x632E,
+0x632F,0x6330,0x6331,0x6332,0x6333, 0, 0, 0,
+ 0, 0,0x6334, 0,0x6335, 0,0x6336, 0,
+0x6337, 0, 0,0x6338,0x6339, 0, 0,0x633A,
+0x633B,0x633C,0x633D, 0,0x633E,0x633F, 0,0x6340,
+ 0, 0, 0,0x6341, 0,0x6342,0x6343, 0,
+ 0,0x6344, 0,0x6345, 0, 0, 0,0x6346,
+0x6347, 0, 0, 0, 0, 0,0x6348,0x6349,
+0x634A,0x634B, 0,0x634C, 0, 0, 0, 0,
+ 0,0x634D,0x634E,0x634F, 0, 0,0x6350, 0,
+0x6351,0x6352, 0,0x6353,0x6354,0x6355, 0,0x6356,
+ 0,0x6357, 0,0x6358, 0,0x6359,0x635A, 0,
+ 0,0x635B,0x635C, 0, 0,0x635D, 0, 0,
+0x635E,0x635F,0x6360, 0,0x6361, 0, 0, 0,
+ 0, 0, 0,0x6362,0x6363, 0, 0,0x6364,
+0x6365, 0, 0,0x6366,0x6367, 0, 0, 0,
+0x6368, 0,0x6369,0x636A,0x636B, 0, 0, 0,
+ 0,0x636C,0x636D,0x636E, 0, 0, 0, 0,
+0x636F,0x6370,0x6371,0x6372,0x6373, 0,0x6374,0x6375,
+0x6376, 0,0x6377, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6378,0x6379,0x637A, 0, 0,
+0x637B,0x637C, 0, 0, 0,0x637D, 0, 0,
+ 0, 0,0x637E, 0,0x6421, 0, 0, 0,
+ 0, 0,0x6422,0x6423, 0, 0, 0,0x6424,
+0x6425, 0,0x6426,0x6427, 0, 0,0x6428, 0,
+ 0, 0,0x6429, 0, 0,0x642A, 0, 0,
+ 0,0x642B, 0,0x642C, 0,0x642D,0x642E,0x642F,
+0x6430, 0,0x6431,0x6432,0x6433,0x6434,0x6435, 0,
+0x6436,0x6437,0x6438,0x6439, 0, 0,0x643A,0x643B,
+0x643C,0x643D, 0,0x643E, 0, 0,0x643F, 0,
+0x6440, 0,0x6441,0x6442,0x6443, 0, 0,0x6444,
+0x6445, 0,0x6446,0x6447,0x6448, 0,0x6449, 0,
+0x644A, 0,0x644B,0x644C, 0, 0, 0,0x644D,
+ 0,0x644E, 0,0x644F, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6450, 0,0x6451, 0,
+ 0, 0,0x6452,0x6453, 0,0x6454, 0, 0,
+ 0, 0, 0,0x6455, 0, 0, 0, 0,
+0x6456, 0, 0, 0,0x6457, 0, 0,0x6458,
+0x6459, 0, 0, 0, 0, 0, 0,0x645A,
+0x645B,0x645C,0x645D, 0,0x645E, 0, 0,0x645F,
+0x6460, 0,0x6461, 0,0x6462,0x6463, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6464,0x6465,
+ 0,0x6466,0x6467, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6468,0x6469,0x646A, 0, 0, 0,
+ 0, 0, 0,0x646B,0x646C,0x646D, 0, 0,
+0x646E, 0,0x646F,0x6470, 0,0x6471, 0, 0,
+ 0,0x6472, 0, 0, 0, 0, 0,0x6473,
+0x6474, 0,0x6475, 0,0x6476,0x6477, 0, 0,
+0x6478, 0,0x6479,0x647A,0x647B, 0,0x647C,0x647D,
+ 0,0x647E, 0, 0, 0,0x6521, 0, 0,
+0x6522, 0,0x6523,0x6524,0x6525,0x6526, 0, 0,
+ 0, 0, 0,0x6527, 0,0x6528,0x6529, 0,
+0x652A, 0,0x652B, 0, 0,0x652C, 0, 0,
+0x652D, 0, 0,0x652E, 0, 0,0x652F, 0,
+ 0,0x6530, 0, 0,0x6531, 0,0x6532,0x6533,
+ 0,0x6534, 0,0x6535,0x653B, 0,0x6536, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6537,
+0x6538,0x6539, 0, 0, 0,0x653A, 0, 0,
+ 0, 0, 0, 0,0x653C, 0, 0,0x653D,
+0x653E,0x653F,0x6540, 0,0x6541,0x6542,0x6543,0x6544,
+0x6545, 0, 0, 0, 0, 0,0x6546, 0,
+ 0, 0, 0, 0,0x6547, 0, 0,0x6548,
+ 0,0x6549,0x654A, 0, 0,0x654B, 0, 0,
+ 0,0x654C,0x654D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x654F,0x6550,0x654E,0x6551,0x6552, 0,
+0x6553, 0, 0, 0,0x6554,0x6555, 0,0x6556,
+ 0, 0, 0,0x6557,0x6558, 0, 0, 0,
+0x6559,0x655A,0x655B, 0, 0, 0, 0, 0,
+0x655C,0x655D,0x655E, 0, 0, 0, 0, 0,
+ 0, 0,0x655F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6560,0x6561, 0,0x6562,0x6563,0x6564,0x6565,
+ 0, 0, 0, 0, 0, 0,0x6566, 0,
+0x6568, 0,0x6567, 0, 0, 0,0x6569, 0,
+0x656A, 0, 0,0x656B, 0,0x656C, 0,0x656D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x656E, 0, 0, 0,0x656F, 0, 0,0x6570,
+ 0, 0,0x6571, 0,0x6572, 0,0x6573, 0,
+ 0, 0, 0,0x6574, 0, 0,0x6575, 0,
+0x6576,0x6577,0x6578, 0,0x6579,0x657A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x657C,0x657B
+};
+
+/* page 37 0x9578-0x95E6 */
+static uint16 tab_uni_jisx021237[]={
+0x657D,0x657E, 0, 0, 0, 0,0x6621, 0,
+ 0, 0, 0, 0,0x6622, 0, 0, 0,
+0x6623, 0, 0, 0,0x6624,0x6625,0x6626, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6627,0x6628,0x6629,
+ 0,0x662A, 0, 0, 0, 0,0x662B, 0,
+ 0,0x662C, 0,0x662D,0x662E, 0, 0, 0,
+ 0, 0, 0, 0,0x662F, 0,0x6630, 0,
+ 0, 0,0x6631, 0, 0,0x6632, 0,0x6633,
+ 0, 0, 0, 0, 0, 0,0x6634, 0,
+0x6635,0x6636, 0,0x6637, 0, 0, 0, 0,
+0x6638,0x6639,0x663A,0x663B, 0, 0, 0, 0,
+ 0,0x663C,0x663D, 0, 0,0x663E,0x663F,0x6640,
+0x6641, 0, 0, 0,0x6642, 0,0x6643};
+
+/* page 38 0x961D-0x986C */
+static uint16 tab_uni_jisx021238[]={
+0x6644,0x6645, 0, 0, 0,0x6646, 0,0x6647,
+0x6648,0x6649, 0, 0, 0, 0, 0,0x664A,
+ 0, 0, 0, 0,0x664B, 0,0x664C, 0,
+ 0, 0,0x664D,0x664E,0x664F,0x6650, 0,0x6651,
+0x6652, 0, 0, 0,0x6653, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6654, 0,0x6655,
+ 0,0x6656,0x6657,0x6658, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6659, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x665A, 0, 0, 0, 0, 0,0x665B,
+ 0, 0, 0, 0, 0, 0,0x665C,0x665D,
+ 0,0x665E,0x665F, 0,0x6660,0x6661,0x6662,0x6663,
+ 0, 0, 0, 0,0x6664, 0, 0, 0,
+ 0, 0, 0, 0,0x6665, 0, 0, 0,
+ 0,0x6666, 0, 0, 0,0x6667, 0, 0,
+0x6668, 0,0x6669, 0, 0, 0, 0,0x666A,
+0x666B,0x666C, 0, 0,0x666D, 0, 0, 0,
+ 0,0x666E,0x666F, 0, 0, 0,0x6670, 0,
+ 0, 0, 0, 0, 0,0x6671, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6672, 0, 0,
+ 0, 0, 0, 0, 0,0x6673, 0, 0,
+ 0, 0, 0,0x6675, 0,0x6676, 0, 0,
+0x6677,0x6678,0x6679, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x667A, 0, 0, 0,
+ 0, 0,0x667B, 0,0x667C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x667D, 0, 0,
+ 0, 0, 0, 0, 0,0x667E,0x6721, 0,
+0x6722, 0, 0, 0,0x6723, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6724,0x6725, 0,
+0x6726, 0, 0, 0,0x6727,0x6728,0x6729, 0,
+ 0, 0, 0,0x672A, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x672B, 0,0x672C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x672D, 0,0x672E, 0,
+ 0, 0, 0, 0, 0,0x672F, 0, 0,
+ 0,0x6730,0x6731, 0, 0, 0, 0, 0,
+0x6732, 0,0x6733,0x6734, 0,0x6735,0x6736, 0,
+ 0, 0, 0, 0, 0, 0,0x6737, 0,
+ 0, 0,0x6738, 0, 0,0x6739, 0, 0,
+ 0,0x673A, 0, 0, 0, 0,0x673B, 0,
+ 0,0x673C,0x673D,0x673E, 0, 0,0x673F, 0,
+0x6740, 0,0x6741,0x6742, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6743, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6744,0x6745,0x6746, 0,0x6747,0x6748, 0, 0,
+ 0,0x6749,0x674A, 0, 0,0x674B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x674C,
+ 0,0x674D, 0, 0,0x674E,0x674F, 0, 0,
+0x6750,0x6751, 0,0x6752,0x6753,0x6754, 0,0x6755,
+ 0,0x6756,0x6757, 0,0x6758, 0, 0,0x6759,
+0x675A, 0,0x675B, 0,0x675C,0x675D, 0,0x675E,
+0x675F,0x6760, 0,0x6761,0x6762, 0, 0,0x6763,
+ 0, 0,0x6764,0x6765,0x6766, 0,0x676A, 0,
+0x6767,0x6768, 0,0x6769,0x676B, 0, 0,0x676C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x676D, 0,0x676E, 0, 0,0x676F,
+ 0, 0,0x6770,0x6771, 0,0x6772, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6773, 0, 0,0x6774, 0, 0,
+0x6776,0x6777, 0, 0, 0, 0, 0,0x6778,
+ 0,0x6779, 0, 0,0x6775, 0, 0,0x677A,
+ 0,0x677B, 0,0x677C, 0, 0,0x677D, 0,
+0x6828,0x677E, 0, 0, 0, 0,0x6821, 0,
+ 0,0x6822,0x6823,0x6824, 0,0x6825,0x6826, 0,
+0x6827, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6829, 0, 0, 0, 0, 0,0x682A,
+ 0, 0,0x682B, 0, 0,0x682C, 0, 0,
+ 0, 0, 0, 0,0x682D,0x682E,0x682F, 0,
+ 0,0x6830,0x6831, 0,0x6832,0x6833, 0, 0,
+ 0, 0, 0, 0, 0,0x6834,0x6835, 0,
+0x6836,0x6837, 0, 0, 0,0x6838, 0,0x6839
+};
+
+/* page 39 0x98AB-0x98CC */
+static uint16 tab_uni_jisx021239[]={
+0x683A, 0,0x683B,0x683C, 0,0x683D, 0, 0,
+ 0,0x683E, 0, 0,0x683F,0x6840, 0,0x6841,
+0x6842, 0, 0, 0,0x6843, 0, 0,0x6844,
+ 0, 0,0x6845, 0, 0,0x6846, 0, 0,
+ 0,0x6847};
+
+/* page 40 0x98E1-0x9960 */
+static uint16 tab_uni_jisx021240[]={
+0x6848, 0,0x6849, 0,0x684A,0x684B,0x684C, 0,
+ 0,0x684D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x684E, 0, 0,0x684F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6850, 0, 0, 0, 0,0x6851,0x6852,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6853, 0, 0, 0,0x6854,0x6855,0x6856, 0,
+ 0,0x6857,0x6858,0x6859, 0, 0,0x685A, 0,
+ 0,0x685B, 0, 0, 0,0x685C,0x685D, 0,
+ 0, 0,0x685E, 0, 0, 0, 0, 0,
+0x685F,0x6860,0x6861,0x6862,0x6863, 0, 0, 0,
+0x6864,0x6865,0x6866,0x6867, 0, 0, 0,0x6868,
+0x6869, 0, 0, 0, 0,0x686A,0x686B,0x686C,
+ 0, 0, 0, 0,0x686D,0x686E, 0, 0,
+ 0, 0, 0,0x686F, 0, 0, 0,0x6870,
+0x6871, 0,0x6872,0x6873, 0,0x6874,0x6875,0x6876
+};
+
+/* page 41 0x999B-0x9A5D */
+static uint16 tab_uni_jisx021241[]={
+0x6877, 0,0x6878, 0,0x6879, 0, 0, 0,
+ 0, 0, 0,0x687A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x687B,0x687C,0x687D,
+ 0, 0,0x687E, 0, 0, 0,0x6921,0x6922,
+ 0, 0,0x6923, 0,0x6924, 0, 0, 0,
+0x6925, 0, 0, 0, 0, 0,0x6926, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6927,0x6928, 0, 0, 0, 0,0x6929,0x692A,
+ 0,0x692B, 0,0x692C, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x692D, 0, 0,0x692E,
+0x692F,0x6930, 0, 0, 0,0x6931, 0, 0,
+ 0,0x6932,0x6933, 0, 0, 0,0x6934, 0,
+ 0, 0,0x6935,0x6936, 0, 0, 0,0x6937,
+0x6938,0x6939, 0, 0, 0, 0, 0, 0,
+0x693A,0x693B, 0, 0, 0,0x693C,0x693D, 0,
+ 0, 0, 0,0x693E, 0, 0, 0, 0,
+ 0, 0, 0,0x693F, 0,0x6940, 0,0x6941,
+0x6942,0x6943, 0, 0,0x6944, 0, 0, 0,
+ 0, 0,0x6945,0x6946, 0, 0, 0, 0,
+0x6947, 0,0x6948,0x6949, 0,0x694A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x694C, 0,
+ 0,0x694D, 0, 0,0x694B, 0, 0,0x694E,
+0x694F,0x6950, 0,0x6951, 0, 0,0x6952, 0,
+ 0,0x6953, 0,0x6954, 0, 0, 0, 0,
+ 0, 0,0x6955};
+
+/* page 42 0x9AAA-0x9C7B */
+static uint16 tab_uni_jisx021242[]={
+0x6956, 0,0x6957, 0,0x6958,0x6959, 0, 0,
+0x695A, 0,0x695B,0x695C,0x695D, 0, 0,0x695E,
+ 0,0x695F, 0, 0,0x6960,0x6961, 0,0x6962,
+ 0,0x6963, 0, 0,0x6964, 0,0x6965, 0,
+ 0, 0, 0, 0,0x6966, 0,0x6967, 0,
+0x6968, 0, 0,0x6969,0x696A,0x696B, 0, 0,
+ 0,0x696C,0x696D, 0, 0, 0,0x696E, 0,
+ 0, 0,0x696F,0x6970, 0,0x6971, 0,0x6972,
+ 0, 0,0x6973, 0, 0, 0, 0, 0,
+0x6974,0x6975, 0,0x6976, 0, 0, 0,0x6977,
+0x6978, 0, 0,0x6979, 0,0x697A,0x697B,0x697C,
+0x697D,0x697E,0x6A21,0x6A22, 0, 0,0x6A23,0x6A24,
+ 0,0x6A25,0x6A26,0x6A27,0x6A28, 0,0x6A29, 0,
+0x6A2A, 0, 0, 0,0x6A2B, 0, 0,0x6A2C,
+ 0,0x6A2D,0x6A2E, 0, 0, 0,0x6A2F, 0,
+ 0, 0, 0, 0,0x6A30, 0, 0, 0,
+ 0,0x6A31, 0,0x6A32, 0, 0, 0, 0,
+ 0,0x6A33,0x6A34,0x6A35, 0,0x6A36, 0,0x6A37,
+0x6A38, 0, 0,0x6A39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A3A, 0,
+ 0,0x6A3B,0x6A3C, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6A3D,0x6A3E,0x6A3F, 0, 0,
+ 0,0x6A40, 0, 0,0x6A41, 0, 0,0x6A42,
+ 0,0x6A43, 0,0x6A44,0x6A45, 0,0x6A46, 0,
+0x6A47,0x6A48,0x6A49,0x6A4A,0x6A4B, 0, 0, 0,
+ 0,0x6A4C, 0,0x6A4D, 0,0x6A4E,0x6A4F,0x6A50,
+ 0, 0, 0, 0, 0,0x6A51,0x6A52, 0,
+ 0, 0,0x6A53,0x6A54,0x6A55,0x6A56, 0,0x6A57,
+0x6A58,0x6A59, 0,0x6A5A, 0,0x6A5B,0x6A5C, 0,
+ 0, 0,0x6A5D, 0, 0, 0, 0, 0,
+0x6A5E, 0, 0,0x6A5F,0x6A60, 0, 0, 0,
+ 0, 0, 0, 0,0x6A61,0x6A62, 0,0x6A63,
+ 0, 0,0x6A64, 0, 0, 0,0x6A65,0x6A66,
+0x6A67, 0, 0, 0, 0,0x6A68,0x6A69, 0,
+ 0,0x6A6A,0x6A6B, 0,0x6A6C,0x6A6D, 0,0x6A6E,
+ 0, 0, 0, 0, 0,0x6A6F,0x6A70, 0,
+ 0, 0, 0, 0,0x6A71, 0,0x6A72, 0,
+ 0, 0, 0, 0, 0,0x6A73,0x6A74, 0,
+ 0, 0, 0,0x6A75, 0,0x6A76, 0, 0,
+ 0, 0, 0,0x6A77, 0,0x6A78, 0, 0,
+0x6A79,0x6A7A, 0, 0, 0,0x6A7B, 0, 0,
+ 0,0x6A7C, 0, 0, 0,0x6A7D,0x6A7E,0x6B21,
+0x6B22, 0, 0,0x6B23, 0,0x6B24,0x6B25, 0,
+0x6B26, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B27, 0, 0, 0,0x6B28, 0,0x6B29,
+ 0, 0, 0, 0,0x6B2A, 0,0x6B2B,0x6B2C,
+0x6B2D, 0,0x6B2E, 0,0x6B2F, 0, 0, 0,
+0x6B30,0x6B31, 0, 0,0x6B32,0x6B33,0x6B34,0x6B35,
+0x6B36, 0, 0, 0, 0, 0, 0,0x6B37,
+ 0, 0, 0,0x6B38,0x6B39,0x6B3A, 0, 0,
+ 0, 0, 0,0x6B3B, 0, 0, 0,0x6B3C,
+ 0,0x6B3D,0x6B3E,0x6B3F, 0, 0, 0,0x6B40,
+0x6B41, 0, 0, 0,0x6B42,0x6B43,0x6B44, 0,
+ 0,0x6B45,0x6B46, 0,0x6B47, 0,0x6B48, 0,
+ 0,0x6B49,0x6B50,0x6B4A,0x6B4B,0x6B4C, 0, 0,
+ 0,0x6B4D, 0, 0, 0, 0,0x6B52,0x6B4E,
+0x6B4F,0x6B51, 0, 0,0x6B53, 0,0x6B54, 0,
+0x6B55, 0, 0,0x6B56, 0,0x6B57, 0, 0,
+ 0,0x6B58};
+
+/* page 43 0x9CE6-0x9E1D */
+static uint16 tab_uni_jisx021243[]={
+0x6B59, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6B5A, 0, 0, 0,
+ 0,0x6B5B, 0,0x6B5C, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6B5E, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6B5D, 0, 0,
+ 0, 0, 0,0x6B5F, 0, 0, 0, 0,
+ 0,0x6B60,0x6B61, 0, 0, 0,0x6B62,0x6B63,
+0x6B64, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B65,0x6B66, 0,0x6B67,0x6B68,0x6B69, 0,
+ 0, 0, 0, 0,0x6B6A, 0,0x6B6B,0x6B6D,
+ 0, 0, 0, 0,0x6B6E,0x6B6F, 0,0x6B6C,
+ 0,0x6B70, 0, 0,0x6B71, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6B72,0x6B73, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B74, 0, 0,0x6B76,0x6B75, 0,0x6B77,
+ 0, 0, 0,0x6B78,0x6B79,0x6B7A, 0, 0,
+ 0, 0,0x6B7B, 0, 0, 0, 0, 0,
+0x6B7C,0x6B7D, 0, 0, 0,0x6B7E,0x6C21, 0,
+0x6C22, 0, 0, 0, 0,0x6C23,0x6C24, 0,
+0x6C25, 0, 0, 0,0x6C26, 0, 0,0x6C27,
+0x6C28, 0, 0, 0,0x6C29,0x6C2A, 0,0x6C2B,
+0x6C2C,0x6C2D,0x6C2E, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C2F, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C30, 0,0x6C31, 0,
+0x6C32, 0, 0,0x6C33, 0, 0, 0,0x6C34,
+ 0, 0, 0,0x6C35, 0, 0,0x6C36, 0,
+ 0,0x6C37, 0, 0, 0,0x6C38, 0, 0,
+ 0,0x6C39, 0,0x6C3A,0x6C3B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6C3C,0x6C3D,
+0x6C3E,0x6C3F, 0, 0,0x6C40, 0, 0, 0,
+0x6C41,0x6C42,0x6C43, 0, 0, 0, 0,0x6C44,
+ 0,0x6C45, 0,0x6C46, 0,0x6C47, 0, 0,
+0x6C48, 0,0x6C49, 0, 0,0x6C4A,0x6C4B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C4C, 0, 0, 0,0x6C4E, 0, 0, 0,
+ 0,0x6C4F, 0, 0,0x6C4D, 0, 0, 0,
+0x6C50, 0,0x6C51,0x6C52,0x6C53, 0, 0,0x6C54,
+0x6C55, 0, 0,0x6C56, 0, 0,0x6C57,0x6C58
+};
+
+/* page 44 0x9E7A-0x9FA5 */
+static uint16 tab_uni_jisx021244[]={
+0x6C59,0x6C5A,0x6C5B, 0, 0, 0,0x6C5C, 0,
+0x6C5D,0x6C5E,0x6C5F,0x6C60, 0,0x6C61, 0, 0,
+ 0, 0, 0, 0,0x6C62,0x6C63, 0, 0,
+ 0, 0, 0, 0,0x6C64, 0,0x6C65, 0,
+ 0,0x6C66, 0, 0,0x6C67, 0, 0, 0,
+ 0, 0,0x6C68, 0, 0, 0,0x6C69, 0,
+ 0, 0,0x6C6A, 0,0x6C6B,0x6C6C,0x6C6D, 0,
+ 0,0x6C6E,0x6C6F,0x6C70, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C71, 0,0x6C72, 0,
+ 0,0x6C73, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C74, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C75, 0, 0,
+ 0, 0,0x6C76, 0, 0,0x6C77, 0, 0,
+ 0, 0,0x6C78,0x6C79,0x6C7A, 0,0x6C7B,0x6C7C,
+0x6C7D, 0, 0,0x6C7E, 0, 0,0x6D21, 0,
+ 0, 0, 0, 0, 0,0x6D22, 0, 0,
+0x6D23,0x6D24, 0, 0, 0, 0, 0,0x6D25,
+ 0, 0, 0, 0, 0,0x6D26,0x6D27,0x6D28,
+0x6D29, 0,0x6D2A, 0,0x6D2B,0x6D2C, 0,0x6D2D,
+0x6D2E,0x6D2F, 0, 0, 0,0x6D30, 0, 0,
+0x6D31, 0, 0, 0,0x6D32, 0, 0, 0,
+0x6D33,0x6D34, 0, 0, 0,0x6D35, 0,0x6D36,
+0x6D37, 0,0x6D38, 0, 0,0x6D39, 0,0x6D3A,
+0x6D3B, 0,0x6D3C,0x6D3D, 0,0x6D3E, 0,0x6D3F,
+ 0,0x6D40,0x6D41,0x6D42,0x6D43,0x6D44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6D45, 0,0x6D46,0x6D47,0x6D48,0x6D49, 0,
+0x6D4A, 0, 0,0x6D4B,0x6D4C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D4D,0x6D4E,
+ 0, 0, 0,0x6D4F,0x6D50,0x6D51,0x6D52,0x6D53,
+ 0,0x6D54, 0,0x6D55, 0, 0, 0, 0,
+0x6D56, 0, 0,0x6D57, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6D58,0x6D59,0x6D5A,
+0x6D5B, 0,0x6D5C, 0,0x6D5D,0x6D5E, 0, 0,
+ 0, 0, 0, 0,0x6D5F, 0, 0,0x6D60,
+0x6D61,0x6D62, 0,0x6D63};
+
+static int
+my_uni_jisx0212_onechar(int code){
+ if ((code>=0x007E)&&(code<=0x007E))
+ return(tab_uni_jisx02120[code-0x007E]);
+ if ((code>=0x00A1)&&(code<=0x017E))
+ return(tab_uni_jisx02121[code-0x00A1]);
+ if ((code>=0x01CD)&&(code<=0x01DC))
+ return(tab_uni_jisx02122[code-0x01CD]);
+ if ((code>=0x01F5)&&(code<=0x01F5))
+ return(tab_uni_jisx02123[code-0x01F5]);
+ if ((code>=0x02C7)&&(code<=0x02DD))
+ return(tab_uni_jisx02124[code-0x02C7]);
+ if ((code>=0x0384)&&(code<=0x0390))
+ return(tab_uni_jisx02125[code-0x0384]);
+ if ((code>=0x03AA)&&(code<=0x03CE))
+ return(tab_uni_jisx02126[code-0x03AA]);
+ if ((code>=0x0402)&&(code<=0x040F))
+ return(tab_uni_jisx02127[code-0x0402]);
+ if ((code>=0x0452)&&(code<=0x045F))
+ return(tab_uni_jisx02128[code-0x0452]);
+ if ((code>=0x2116)&&(code<=0x2122))
+ return(tab_uni_jisx02129[code-0x2116]);
+ if ((code>=0x4E02)&&(code<=0x4F19))
+ return(tab_uni_jisx021210[code-0x4E02]);
+ if ((code>=0x4F2E)&&(code<=0x5166))
+ return(tab_uni_jisx021211[code-0x4F2E]);
+ if ((code>=0x517E)&&(code<=0x5515))
+ return(tab_uni_jisx021212[code-0x517E]);
+ if ((code>=0x552A)&&(code<=0x5566))
+ return(tab_uni_jisx021213[code-0x552A]);
+ if ((code>=0x557F)&&(code<=0x5C36))
+ return(tab_uni_jisx021214[code-0x557F]);
+ if ((code>=0x5C59)&&(code<=0x5EEB))
+ return(tab_uni_jisx021215[code-0x5C59]);
+ if ((code>=0x5F02)&&(code<=0x6149))
+ return(tab_uni_jisx021216[code-0x5F02]);
+ if ((code>=0x615E)&&(code<=0x6290))
+ return(tab_uni_jisx021217[code-0x615E]);
+ if ((code>=0x62A6)&&(code<=0x679B))
+ return(tab_uni_jisx021218[code-0x62A6]);
+ if ((code>=0x67B0)&&(code<=0x67F9))
+ return(tab_uni_jisx021219[code-0x67B0]);
+ if ((code>=0x6814)&&(code<=0x6917))
+ return(tab_uni_jisx021220[code-0x6814]);
+ if ((code>=0x6931)&&(code<=0x6D3F))
+ return(tab_uni_jisx021221[code-0x6931]);
+ if ((code>=0x6D57)&&(code<=0x6E04))
+ return(tab_uni_jisx021222[code-0x6D57]);
+ if ((code>=0x6E1E)&&(code<=0x6ECF))
+ return(tab_uni_jisx021223[code-0x6E1E]);
+ if ((code>=0x6EEB)&&(code<=0x70E4))
+ return(tab_uni_jisx021224[code-0x6EEB]);
+ if ((code>=0x70FA)&&(code<=0x71DC))
+ return(tab_uni_jisx021225[code-0x70FA]);
+ if ((code>=0x71F8)&&(code<=0x7E9E))
+ return(tab_uni_jisx021226[code-0x71F8]);
+ if ((code>=0x7F3B)&&(code<=0x8044))
+ return(tab_uni_jisx021227[code-0x7F3B]);
+ if ((code>=0x8060)&&(code<=0x8357))
+ return(tab_uni_jisx021228[code-0x8060]);
+ if ((code>=0x8370)&&(code<=0x8419))
+ return(tab_uni_jisx021229[code-0x8370]);
+ if ((code>=0x842F)&&(code<=0x8880))
+ return(tab_uni_jisx021230[code-0x842F]);
+ if ((code>=0x8898)&&(code<=0x89BC))
+ return(tab_uni_jisx021231[code-0x8898]);
+ if ((code>=0x89D4)&&(code<=0x8B9F))
+ return(tab_uni_jisx021232[code-0x89D4]);
+ if ((code>=0x8C38)&&(code<=0x8CA4))
+ return(tab_uni_jisx021233[code-0x8C38]);
+ if ((code>=0x8CB9)&&(code<=0x8D1B))
+ return(tab_uni_jisx021234[code-0x8CB9]);
+ if ((code>=0x8D65)&&(code<=0x8F65))
+ return(tab_uni_jisx021235[code-0x8D65]);
+ if ((code>=0x8F9D)&&(code<=0x9484))
+ return(tab_uni_jisx021236[code-0x8F9D]);
+ if ((code>=0x9578)&&(code<=0x95E6))
+ return(tab_uni_jisx021237[code-0x9578]);
+ if ((code>=0x961D)&&(code<=0x986C))
+ return(tab_uni_jisx021238[code-0x961D]);
+ if ((code>=0x98AB)&&(code<=0x98CC))
+ return(tab_uni_jisx021239[code-0x98AB]);
+ if ((code>=0x98E1)&&(code<=0x9960))
+ return(tab_uni_jisx021240[code-0x98E1]);
+ if ((code>=0x999B)&&(code<=0x9A5D))
+ return(tab_uni_jisx021241[code-0x999B]);
+ if ((code>=0x9AAA)&&(code<=0x9C7B))
+ return(tab_uni_jisx021242[code-0x9AAA]);
+ if ((code>=0x9CE6)&&(code<=0x9E1D))
+ return(tab_uni_jisx021243[code-0x9CE6]);
+ if ((code>=0x9E7A)&&(code<=0x9FA5))
+ return(tab_uni_jisx021244[code-0x9E7A]);
+ return(0);
+}
+
+
+/* page 0 0x222F-0x2244 */
+static uint16 tab_jisx0212_uni0[]={
+0x02D8,0x02C7,0x00B8,0x02D9,0x02DD,0x00AF,0x02DB,0x02DA,
+0x007E,0x0384,0x0385, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x00A1,0x00A6,0x00BF};
+
+/* page 1 0x226B-0x2271 */
+static uint16 tab_jisx0212_uni1[]={
+0x00BA,0x00AA,0x00A9,0x00AE,0x2122,0x00A4,0x2116};
+
+/* page 2 0x2661-0x267C */
+static uint16 tab_jisx0212_uni2[]={
+0x0386,0x0388,0x0389,0x038A,0x03AA, 0,0x038C, 0,
+0x038E,0x03AB, 0,0x038F, 0, 0, 0, 0,
+0x03AC,0x03AD,0x03AE,0x03AF,0x03CA,0x0390,0x03CC,0x03C2,
+0x03CD,0x03CB,0x03B0,0x03CE};
+
+/* page 3 0x2742-0x274E */
+static uint16 tab_jisx0212_uni3[]={
+0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,0x0409,
+0x040A,0x040B,0x040C,0x040E,0x040F};
+
+/* page 4 0x2772-0x277E */
+static uint16 tab_jisx0212_uni4[]={
+0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,
+0x045A,0x045B,0x045C,0x045E,0x045F};
+
+/* page 5 0x2921-0x2950 */
+static uint16 tab_jisx0212_uni5[]={
+0x00C6,0x0110, 0,0x0126, 0,0x0132, 0,0x0141,
+0x013F, 0,0x014A,0x00D8,0x0152, 0,0x0166,0x00DE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x00E6,0x0111,0x00F0,0x0127,0x0131,0x0133,0x0138,0x0142,
+0x0140,0x0149,0x014B,0x00F8,0x0153,0x00DF,0x0167,0x00FE
+};
+
+/* page 6 0x2A21-0x2A77 */
+static uint16 tab_jisx0212_uni6[]={
+0x00C1,0x00C0,0x00C4,0x00C2,0x0102,0x01CD,0x0100,0x0104,
+0x00C5,0x00C3,0x0106,0x0108,0x010C,0x00C7,0x010A,0x010E,
+0x00C9,0x00C8,0x00CB,0x00CA,0x011A,0x0116,0x0112,0x0118,
+ 0,0x011C,0x011E,0x0122,0x0120,0x0124,0x00CD,0x00CC,
+0x00CF,0x00CE,0x01CF,0x0130,0x012A,0x012E,0x0128,0x0134,
+0x0136,0x0139,0x013D,0x013B,0x0143,0x0147,0x0145,0x00D1,
+0x00D3,0x00D2,0x00D6,0x00D4,0x01D1,0x0150,0x014C,0x00D5,
+0x0154,0x0158,0x0156,0x015A,0x015C,0x0160,0x015E,0x0164,
+0x0162,0x00DA,0x00D9,0x00DC,0x00DB,0x016C,0x01D3,0x0170,
+0x016A,0x0172,0x016E,0x0168,0x01D7,0x01DB,0x01D9,0x01D5,
+0x0174,0x00DD,0x0178,0x0176,0x0179,0x017D,0x017B};
+
+/* page 7 0x2B21-0x2B77 */
+static uint16 tab_jisx0212_uni7[]={
+0x00E1,0x00E0,0x00E4,0x00E2,0x0103,0x01CE,0x0101,0x0105,
+0x00E5,0x00E3,0x0107,0x0109,0x010D,0x00E7,0x010B,0x010F,
+0x00E9,0x00E8,0x00EB,0x00EA,0x011B,0x0117,0x0113,0x0119,
+0x01F5,0x011D,0x011F, 0,0x0121,0x0125,0x00ED,0x00EC,
+0x00EF,0x00EE,0x01D0, 0,0x012B,0x012F,0x0129,0x0135,
+0x0137,0x013A,0x013E,0x013C,0x0144,0x0148,0x0146,0x00F1,
+0x00F3,0x00F2,0x00F6,0x00F4,0x01D2,0x0151,0x014D,0x00F5,
+0x0155,0x0159,0x0157,0x015B,0x015D,0x0161,0x015F,0x0165,
+0x0163,0x00FA,0x00F9,0x00FC,0x00FB,0x016D,0x01D4,0x0171,
+0x016B,0x0173,0x016F,0x0169,0x01D8,0x01DC,0x01DA,0x01D6,
+0x0175,0x00FD,0x00FF,0x0177,0x017A,0x017E,0x017C};
+
+/* page 8 0x3021-0x307E */
+static uint16 tab_jisx0212_uni8[]={
+0x4E02,0x4E04,0x4E05,0x4E0C,0x4E12,0x4E1F,0x4E23,0x4E24,
+0x4E28,0x4E2B,0x4E2E,0x4E2F,0x4E30,0x4E35,0x4E40,0x4E41,
+0x4E44,0x4E47,0x4E51,0x4E5A,0x4E5C,0x4E63,0x4E68,0x4E69,
+0x4E74,0x4E75,0x4E79,0x4E7F,0x4E8D,0x4E96,0x4E97,0x4E9D,
+0x4EAF,0x4EB9,0x4EC3,0x4ED0,0x4EDA,0x4EDB,0x4EE0,0x4EE1,
+0x4EE2,0x4EE8,0x4EEF,0x4EF1,0x4EF3,0x4EF5,0x4EFD,0x4EFE,
+0x4EFF,0x4F00,0x4F02,0x4F03,0x4F08,0x4F0B,0x4F0C,0x4F12,
+0x4F15,0x4F16,0x4F17,0x4F19,0x4F2E,0x4F31,0x4F60,0x4F33,
+0x4F35,0x4F37,0x4F39,0x4F3B,0x4F3E,0x4F40,0x4F42,0x4F48,
+0x4F49,0x4F4B,0x4F4C,0x4F52,0x4F54,0x4F56,0x4F58,0x4F5F,
+0x4F63,0x4F6A,0x4F6C,0x4F6E,0x4F71,0x4F77,0x4F78,0x4F79,
+0x4F7A,0x4F7D,0x4F7E,0x4F81,0x4F82,0x4F84};
+
+/* page 9 0x3121-0x317E */
+static uint16 tab_jisx0212_uni9[]={
+0x4F85,0x4F89,0x4F8A,0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,
+0x4F94,0x4F97,0x4F99,0x4F9A,0x4F9E,0x4F9F,0x4FB2,0x4FB7,
+0x4FB9,0x4FBB,0x4FBC,0x4FBD,0x4FBE,0x4FC0,0x4FC1,0x4FC5,
+0x4FC6,0x4FC8,0x4FC9,0x4FCB,0x4FCC,0x4FCD,0x4FCF,0x4FD2,
+0x4FDC,0x4FE0,0x4FE2,0x4FF0,0x4FF2,0x4FFC,0x4FFD,0x4FFF,
+0x5000,0x5001,0x5004,0x5007,0x500A,0x500C,0x500E,0x5010,
+0x5013,0x5017,0x5018,0x501B,0x501C,0x501D,0x501E,0x5022,
+0x5027,0x502E,0x5030,0x5032,0x5033,0x5035,0x5040,0x5041,
+0x5042,0x5045,0x5046,0x504A,0x504C,0x504E,0x5051,0x5052,
+0x5053,0x5057,0x5059,0x505F,0x5060,0x5062,0x5063,0x5066,
+0x5067,0x506A,0x506D,0x5070,0x5071,0x503B,0x5081,0x5083,
+0x5084,0x5086,0x508A,0x508E,0x508F,0x5090};
+
+/* page 10 0x3221-0x327E */
+static uint16 tab_jisx0212_uni10[]={
+0x5092,0x5093,0x5094,0x5096,0x509B,0x509C,0x509E,0x509F,
+0x50A0,0x50A1,0x50A2,0x50AA,0x50AF,0x50B0,0x50B9,0x50BA,
+0x50BD,0x50C0,0x50C3,0x50C4,0x50C7,0x50CC,0x50CE,0x50D0,
+0x50D3,0x50D4,0x50D8,0x50DC,0x50DD,0x50DF,0x50E2,0x50E4,
+0x50E6,0x50E8,0x50E9,0x50EF,0x50F1,0x50F6,0x50FA,0x50FE,
+0x5103,0x5106,0x5107,0x5108,0x510B,0x510C,0x510D,0x510E,
+0x50F2,0x5110,0x5117,0x5119,0x511B,0x511C,0x511D,0x511E,
+0x5123,0x5127,0x5128,0x512C,0x512D,0x512F,0x5131,0x5133,
+0x5134,0x5135,0x5138,0x5139,0x5142,0x514A,0x514F,0x5153,
+0x5155,0x5157,0x5158,0x515F,0x5164,0x5166,0x517E,0x5183,
+0x5184,0x518B,0x518E,0x5198,0x519D,0x51A1,0x51A3,0x51AD,
+0x51B8,0x51BA,0x51BC,0x51BE,0x51BF,0x51C2};
+
+/* page 11 0x3321-0x337E */
+static uint16 tab_jisx0212_uni11[]={
+0x51C8,0x51CF,0x51D1,0x51D2,0x51D3,0x51D5,0x51D8,0x51DE,
+0x51E2,0x51E5,0x51EE,0x51F2,0x51F3,0x51F4,0x51F7,0x5201,
+0x5202,0x5205,0x5212,0x5213,0x5215,0x5216,0x5218,0x5222,
+0x5228,0x5231,0x5232,0x5235,0x523C,0x5245,0x5249,0x5255,
+0x5257,0x5258,0x525A,0x525C,0x525F,0x5260,0x5261,0x5266,
+0x526E,0x5277,0x5278,0x5279,0x5280,0x5282,0x5285,0x528A,
+0x528C,0x5293,0x5295,0x5296,0x5297,0x5298,0x529A,0x529C,
+0x52A4,0x52A5,0x52A6,0x52A7,0x52AF,0x52B0,0x52B6,0x52B7,
+0x52B8,0x52BA,0x52BB,0x52BD,0x52C0,0x52C4,0x52C6,0x52C8,
+0x52CC,0x52CF,0x52D1,0x52D4,0x52D6,0x52DB,0x52DC,0x52E1,
+0x52E5,0x52E8,0x52E9,0x52EA,0x52EC,0x52F0,0x52F1,0x52F4,
+0x52F6,0x52F7,0x5300,0x5303,0x530A,0x530B};
+
+/* page 12 0x3421-0x347E */
+static uint16 tab_jisx0212_uni12[]={
+0x530C,0x5311,0x5313,0x5318,0x531B,0x531C,0x531E,0x531F,
+0x5325,0x5327,0x5328,0x5329,0x532B,0x532C,0x532D,0x5330,
+0x5332,0x5335,0x533C,0x533D,0x533E,0x5342,0x534C,0x534B,
+0x5359,0x535B,0x5361,0x5363,0x5365,0x536C,0x536D,0x5372,
+0x5379,0x537E,0x5383,0x5387,0x5388,0x538E,0x5393,0x5394,
+0x5399,0x539D,0x53A1,0x53A4,0x53AA,0x53AB,0x53AF,0x53B2,
+0x53B4,0x53B5,0x53B7,0x53B8,0x53BA,0x53BD,0x53C0,0x53C5,
+0x53CF,0x53D2,0x53D3,0x53D5,0x53DA,0x53DD,0x53DE,0x53E0,
+0x53E6,0x53E7,0x53F5,0x5402,0x5413,0x541A,0x5421,0x5427,
+0x5428,0x542A,0x542F,0x5431,0x5434,0x5435,0x5443,0x5444,
+0x5447,0x544D,0x544F,0x545E,0x5462,0x5464,0x5466,0x5467,
+0x5469,0x546B,0x546D,0x546E,0x5474,0x547F};
+
+/* page 13 0x3521-0x357E */
+static uint16 tab_jisx0212_uni13[]={
+0x5481,0x5483,0x5485,0x5488,0x5489,0x548D,0x5491,0x5495,
+0x5496,0x549C,0x549F,0x54A1,0x54A6,0x54A7,0x54A9,0x54AA,
+0x54AD,0x54AE,0x54B1,0x54B7,0x54B9,0x54BA,0x54BB,0x54BF,
+0x54C6,0x54CA,0x54CD,0x54CE,0x54E0,0x54EA,0x54EC,0x54EF,
+0x54F6,0x54FC,0x54FE,0x54FF,0x5500,0x5501,0x5505,0x5508,
+0x5509,0x550C,0x550D,0x550E,0x5515,0x552A,0x552B,0x5532,
+0x5535,0x5536,0x553B,0x553C,0x553D,0x5541,0x5547,0x5549,
+0x554A,0x554D,0x5550,0x5551,0x5558,0x555A,0x555B,0x555E,
+0x5560,0x5561,0x5564,0x5566,0x557F,0x5581,0x5582,0x5586,
+0x5588,0x558E,0x558F,0x5591,0x5592,0x5593,0x5594,0x5597,
+0x55A3,0x55A4,0x55AD,0x55B2,0x55BF,0x55C1,0x55C3,0x55C6,
+0x55C9,0x55CB,0x55CC,0x55CE,0x55D1,0x55D2};
+
+/* page 14 0x3621-0x367E */
+static uint16 tab_jisx0212_uni14[]={
+0x55D3,0x55D7,0x55D8,0x55DB,0x55DE,0x55E2,0x55E9,0x55F6,
+0x55FF,0x5605,0x5608,0x560A,0x560D,0x560E,0x560F,0x5610,
+0x5611,0x5612,0x5619,0x562C,0x5630,0x5633,0x5635,0x5637,
+0x5639,0x563B,0x563C,0x563D,0x563F,0x5640,0x5641,0x5643,
+0x5644,0x5646,0x5649,0x564B,0x564D,0x564F,0x5654,0x565E,
+0x5660,0x5661,0x5662,0x5663,0x5666,0x5669,0x566D,0x566F,
+0x5671,0x5672,0x5675,0x5684,0x5685,0x5688,0x568B,0x568C,
+0x5695,0x5699,0x569A,0x569D,0x569E,0x569F,0x56A6,0x56A7,
+0x56A8,0x56A9,0x56AB,0x56AC,0x56AD,0x56B1,0x56B3,0x56B7,
+0x56BE,0x56C5,0x56C9,0x56CA,0x56CB,0x56CF,0x56D0,0x56CC,
+0x56CD,0x56D9,0x56DC,0x56DD,0x56DF,0x56E1,0x56E4,0x56E5,
+0x56E6,0x56E7,0x56E8,0x56F1,0x56EB,0x56ED};
+
+/* page 15 0x3721-0x377E */
+static uint16 tab_jisx0212_uni15[]={
+0x56F6,0x56F7,0x5701,0x5702,0x5707,0x570A,0x570C,0x5711,
+0x5715,0x571A,0x571B,0x571D,0x5720,0x5722,0x5723,0x5724,
+0x5725,0x5729,0x572A,0x572C,0x572E,0x572F,0x5733,0x5734,
+0x573D,0x573E,0x573F,0x5745,0x5746,0x574C,0x574D,0x5752,
+0x5762,0x5765,0x5767,0x5768,0x576B,0x576D,0x576E,0x576F,
+0x5770,0x5771,0x5773,0x5774,0x5775,0x5777,0x5779,0x577A,
+0x577B,0x577C,0x577E,0x5781,0x5783,0x578C,0x5794,0x5797,
+0x5799,0x579A,0x579C,0x579D,0x579E,0x579F,0x57A1,0x5795,
+0x57A7,0x57A8,0x57A9,0x57AC,0x57B8,0x57BD,0x57C7,0x57C8,
+0x57CC,0x57CF,0x57D5,0x57DD,0x57DE,0x57E4,0x57E6,0x57E7,
+0x57E9,0x57ED,0x57F0,0x57F5,0x57F6,0x57F8,0x57FD,0x57FE,
+0x57FF,0x5803,0x5804,0x5808,0x5809,0x57E1};
+
+/* page 16 0x3821-0x387E */
+static uint16 tab_jisx0212_uni16[]={
+0x580C,0x580D,0x581B,0x581E,0x581F,0x5820,0x5826,0x5827,
+0x582D,0x5832,0x5839,0x583F,0x5849,0x584C,0x584D,0x584F,
+0x5850,0x5855,0x585F,0x5861,0x5864,0x5867,0x5868,0x5878,
+0x587C,0x587F,0x5880,0x5881,0x5887,0x5888,0x5889,0x588A,
+0x588C,0x588D,0x588F,0x5890,0x5894,0x5896,0x589D,0x58A0,
+0x58A1,0x58A2,0x58A6,0x58A9,0x58B1,0x58B2,0x58C4,0x58BC,
+0x58C2,0x58C8,0x58CD,0x58CE,0x58D0,0x58D2,0x58D4,0x58D6,
+0x58DA,0x58DD,0x58E1,0x58E2,0x58E9,0x58F3,0x5905,0x5906,
+0x590B,0x590C,0x5912,0x5913,0x5914,0x8641,0x591D,0x5921,
+0x5923,0x5924,0x5928,0x592F,0x5930,0x5933,0x5935,0x5936,
+0x593F,0x5943,0x5946,0x5952,0x5953,0x5959,0x595B,0x595D,
+0x595E,0x595F,0x5961,0x5963,0x596B,0x596D};
+
+/* page 17 0x3921-0x397E */
+static uint16 tab_jisx0212_uni17[]={
+0x596F,0x5972,0x5975,0x5976,0x5979,0x597B,0x597C,0x598B,
+0x598C,0x598E,0x5992,0x5995,0x5997,0x599F,0x59A4,0x59A7,
+0x59AD,0x59AE,0x59AF,0x59B0,0x59B3,0x59B7,0x59BA,0x59BC,
+0x59C1,0x59C3,0x59C4,0x59C8,0x59CA,0x59CD,0x59D2,0x59DD,
+0x59DE,0x59DF,0x59E3,0x59E4,0x59E7,0x59EE,0x59EF,0x59F1,
+0x59F2,0x59F4,0x59F7,0x5A00,0x5A04,0x5A0C,0x5A0D,0x5A0E,
+0x5A12,0x5A13,0x5A1E,0x5A23,0x5A24,0x5A27,0x5A28,0x5A2A,
+0x5A2D,0x5A30,0x5A44,0x5A45,0x5A47,0x5A48,0x5A4C,0x5A50,
+0x5A55,0x5A5E,0x5A63,0x5A65,0x5A67,0x5A6D,0x5A77,0x5A7A,
+0x5A7B,0x5A7E,0x5A8B,0x5A90,0x5A93,0x5A96,0x5A99,0x5A9C,
+0x5A9E,0x5A9F,0x5AA0,0x5AA2,0x5AA7,0x5AAC,0x5AB1,0x5AB2,
+0x5AB3,0x5AB5,0x5AB8,0x5ABA,0x5ABB,0x5ABF};
+
+/* page 18 0x3A21-0x3A7E */
+static uint16 tab_jisx0212_uni18[]={
+0x5AC4,0x5AC6,0x5AC8,0x5ACF,0x5ADA,0x5ADC,0x5AE0,0x5AE5,
+0x5AEA,0x5AEE,0x5AF5,0x5AF6,0x5AFD,0x5B00,0x5B01,0x5B08,
+0x5B17,0x5B34,0x5B19,0x5B1B,0x5B1D,0x5B21,0x5B25,0x5B2D,
+0x5B38,0x5B41,0x5B4B,0x5B4C,0x5B52,0x5B56,0x5B5E,0x5B68,
+0x5B6E,0x5B6F,0x5B7C,0x5B7D,0x5B7E,0x5B7F,0x5B81,0x5B84,
+0x5B86,0x5B8A,0x5B8E,0x5B90,0x5B91,0x5B93,0x5B94,0x5B96,
+0x5BA8,0x5BA9,0x5BAC,0x5BAD,0x5BAF,0x5BB1,0x5BB2,0x5BB7,
+0x5BBA,0x5BBC,0x5BC0,0x5BC1,0x5BCD,0x5BCF,0x5BD6,0x5BD7,
+0x5BD8,0x5BD9,0x5BDA,0x5BE0,0x5BEF,0x5BF1,0x5BF4,0x5BFD,
+0x5C0C,0x5C17,0x5C1E,0x5C1F,0x5C23,0x5C26,0x5C29,0x5C2B,
+0x5C2C,0x5C2E,0x5C30,0x5C32,0x5C35,0x5C36,0x5C59,0x5C5A,
+0x5C5C,0x5C62,0x5C63,0x5C67,0x5C68,0x5C69};
+
+/* page 19 0x3B21-0x3B7E */
+static uint16 tab_jisx0212_uni19[]={
+0x5C6D,0x5C70,0x5C74,0x5C75,0x5C7A,0x5C7B,0x5C7C,0x5C7D,
+0x5C87,0x5C88,0x5C8A,0x5C8F,0x5C92,0x5C9D,0x5C9F,0x5CA0,
+0x5CA2,0x5CA3,0x5CA6,0x5CAA,0x5CB2,0x5CB4,0x5CB5,0x5CBA,
+0x5CC9,0x5CCB,0x5CD2,0x5CDD,0x5CD7,0x5CEE,0x5CF1,0x5CF2,
+0x5CF4,0x5D01,0x5D06,0x5D0D,0x5D12,0x5D2B,0x5D23,0x5D24,
+0x5D26,0x5D27,0x5D31,0x5D34,0x5D39,0x5D3D,0x5D3F,0x5D42,
+0x5D43,0x5D46,0x5D48,0x5D55,0x5D51,0x5D59,0x5D4A,0x5D5F,
+0x5D60,0x5D61,0x5D62,0x5D64,0x5D6A,0x5D6D,0x5D70,0x5D79,
+0x5D7A,0x5D7E,0x5D7F,0x5D81,0x5D83,0x5D88,0x5D8A,0x5D92,
+0x5D93,0x5D94,0x5D95,0x5D99,0x5D9B,0x5D9F,0x5DA0,0x5DA7,
+0x5DAB,0x5DB0,0x5DB4,0x5DB8,0x5DB9,0x5DC3,0x5DC7,0x5DCB,
+0x5DD0,0x5DCE,0x5DD8,0x5DD9,0x5DE0,0x5DE4};
+
+/* page 20 0x3C21-0x3C7E */
+static uint16 tab_jisx0212_uni20[]={
+0x5DE9,0x5DF8,0x5DF9,0x5E00,0x5E07,0x5E0D,0x5E12,0x5E14,
+0x5E15,0x5E18,0x5E1F,0x5E20,0x5E2E,0x5E28,0x5E32,0x5E35,
+0x5E3E,0x5E4B,0x5E50,0x5E49,0x5E51,0x5E56,0x5E58,0x5E5B,
+0x5E5C,0x5E5E,0x5E68,0x5E6A,0x5E6B,0x5E6C,0x5E6D,0x5E6E,
+0x5E70,0x5E80,0x5E8B,0x5E8E,0x5EA2,0x5EA4,0x5EA5,0x5EA8,
+0x5EAA,0x5EAC,0x5EB1,0x5EB3,0x5EBD,0x5EBE,0x5EBF,0x5EC6,
+0x5ECC,0x5ECB,0x5ECE,0x5ED1,0x5ED2,0x5ED4,0x5ED5,0x5EDC,
+0x5EDE,0x5EE5,0x5EEB,0x5F02,0x5F06,0x5F07,0x5F08,0x5F0E,
+0x5F19,0x5F1C,0x5F1D,0x5F21,0x5F22,0x5F23,0x5F24,0x5F28,
+0x5F2B,0x5F2C,0x5F2E,0x5F30,0x5F34,0x5F36,0x5F3B,0x5F3D,
+0x5F3F,0x5F40,0x5F44,0x5F45,0x5F47,0x5F4D,0x5F50,0x5F54,
+0x5F58,0x5F5B,0x5F60,0x5F63,0x5F64,0x5F67};
+
+/* page 21 0x3D21-0x3D7E */
+static uint16 tab_jisx0212_uni21[]={
+0x5F6F,0x5F72,0x5F74,0x5F75,0x5F78,0x5F7A,0x5F7D,0x5F7E,
+0x5F89,0x5F8D,0x5F8F,0x5F96,0x5F9C,0x5F9D,0x5FA2,0x5FA7,
+0x5FAB,0x5FA4,0x5FAC,0x5FAF,0x5FB0,0x5FB1,0x5FB8,0x5FC4,
+0x5FC7,0x5FC8,0x5FC9,0x5FCB,0x5FD0,0x5FD1,0x5FD2,0x5FD3,
+0x5FD4,0x5FDE,0x5FE1,0x5FE2,0x5FE8,0x5FE9,0x5FEA,0x5FEC,
+0x5FED,0x5FEE,0x5FEF,0x5FF2,0x5FF3,0x5FF6,0x5FFA,0x5FFC,
+0x6007,0x600A,0x600D,0x6013,0x6014,0x6017,0x6018,0x601A,
+0x601F,0x6024,0x602D,0x6033,0x6035,0x6040,0x6047,0x6048,
+0x6049,0x604C,0x6051,0x6054,0x6056,0x6057,0x605D,0x6061,
+0x6067,0x6071,0x607E,0x607F,0x6082,0x6086,0x6088,0x608A,
+0x608E,0x6091,0x6093,0x6095,0x6098,0x609D,0x609E,0x60A2,
+0x60A4,0x60A5,0x60A8,0x60B0,0x60B1,0x60B7};
+
+/* page 22 0x3E21-0x3E7E */
+static uint16 tab_jisx0212_uni22[]={
+0x60BB,0x60BE,0x60C2,0x60C4,0x60C8,0x60C9,0x60CA,0x60CB,
+0x60CE,0x60CF,0x60D4,0x60D5,0x60D9,0x60DB,0x60DD,0x60DE,
+0x60E2,0x60E5,0x60F2,0x60F5,0x60F8,0x60FC,0x60FD,0x6102,
+0x6107,0x610A,0x610C,0x6110,0x6111,0x6112,0x6113,0x6114,
+0x6116,0x6117,0x6119,0x611C,0x611E,0x6122,0x612A,0x612B,
+0x6130,0x6131,0x6135,0x6136,0x6137,0x6139,0x6141,0x6145,
+0x6146,0x6149,0x615E,0x6160,0x616C,0x6172,0x6178,0x617B,
+0x617C,0x617F,0x6180,0x6181,0x6183,0x6184,0x618B,0x618D,
+0x6192,0x6193,0x6197,0x6198,0x619C,0x619D,0x619F,0x61A0,
+0x61A5,0x61A8,0x61AA,0x61AD,0x61B8,0x61B9,0x61BC,0x61C0,
+0x61C1,0x61C2,0x61CE,0x61CF,0x61D5,0x61DC,0x61DD,0x61DE,
+0x61DF,0x61E1,0x61E2,0x61E7,0x61E9,0x61E5};
+
+/* page 23 0x3F21-0x3F7E */
+static uint16 tab_jisx0212_uni23[]={
+0x61EC,0x61ED,0x61EF,0x6201,0x6203,0x6204,0x6207,0x6213,
+0x6215,0x621C,0x6220,0x6222,0x6223,0x6227,0x6229,0x622B,
+0x6239,0x623D,0x6242,0x6243,0x6244,0x6246,0x624C,0x6250,
+0x6251,0x6252,0x6254,0x6256,0x625A,0x625C,0x6264,0x626D,
+0x626F,0x6273,0x627A,0x627D,0x628D,0x628E,0x628F,0x6290,
+0x62A6,0x62A8,0x62B3,0x62B6,0x62B7,0x62BA,0x62BE,0x62BF,
+0x62C4,0x62CE,0x62D5,0x62D6,0x62DA,0x62EA,0x62F2,0x62F4,
+0x62FC,0x62FD,0x6303,0x6304,0x630A,0x630B,0x630D,0x6310,
+0x6313,0x6316,0x6318,0x6329,0x632A,0x632D,0x6335,0x6336,
+0x6339,0x633C,0x6341,0x6342,0x6343,0x6344,0x6346,0x634A,
+0x634B,0x634E,0x6352,0x6353,0x6354,0x6358,0x635B,0x6365,
+0x6366,0x636C,0x636D,0x6371,0x6374,0x6375};
+
+/* page 24 0x4021-0x407E */
+static uint16 tab_jisx0212_uni24[]={
+0x6378,0x637C,0x637D,0x637F,0x6382,0x6384,0x6387,0x638A,
+0x6390,0x6394,0x6395,0x6399,0x639A,0x639E,0x63A4,0x63A6,
+0x63AD,0x63AE,0x63AF,0x63BD,0x63C1,0x63C5,0x63C8,0x63CE,
+0x63D1,0x63D3,0x63D4,0x63D5,0x63DC,0x63E0,0x63E5,0x63EA,
+0x63EC,0x63F2,0x63F3,0x63F5,0x63F8,0x63F9,0x6409,0x640A,
+0x6410,0x6412,0x6414,0x6418,0x641E,0x6420,0x6422,0x6424,
+0x6425,0x6429,0x642A,0x642F,0x6430,0x6435,0x643D,0x643F,
+0x644B,0x644F,0x6451,0x6452,0x6453,0x6454,0x645A,0x645B,
+0x645C,0x645D,0x645F,0x6460,0x6461,0x6463,0x646D,0x6473,
+0x6474,0x647B,0x647D,0x6485,0x6487,0x648F,0x6490,0x6491,
+0x6498,0x6499,0x649B,0x649D,0x649F,0x64A1,0x64A3,0x64A6,
+0x64A8,0x64AC,0x64B3,0x64BD,0x64BE,0x64BF};
+
+/* page 25 0x4121-0x417E */
+static uint16 tab_jisx0212_uni25[]={
+0x64C4,0x64C9,0x64CA,0x64CB,0x64CC,0x64CE,0x64D0,0x64D1,
+0x64D5,0x64D7,0x64E4,0x64E5,0x64E9,0x64EA,0x64ED,0x64F0,
+0x64F5,0x64F7,0x64FB,0x64FF,0x6501,0x6504,0x6508,0x6509,
+0x650A,0x650F,0x6513,0x6514,0x6516,0x6519,0x651B,0x651E,
+0x651F,0x6522,0x6526,0x6529,0x652E,0x6531,0x653A,0x653C,
+0x653D,0x6543,0x6547,0x6549,0x6550,0x6552,0x6554,0x655F,
+0x6560,0x6567,0x656B,0x657A,0x657D,0x6581,0x6585,0x658A,
+0x6592,0x6595,0x6598,0x659D,0x65A0,0x65A3,0x65A6,0x65AE,
+0x65B2,0x65B3,0x65B4,0x65BF,0x65C2,0x65C8,0x65C9,0x65CE,
+0x65D0,0x65D4,0x65D6,0x65D8,0x65DF,0x65F0,0x65F2,0x65F4,
+0x65F5,0x65F9,0x65FE,0x65FF,0x6600,0x6604,0x6608,0x6609,
+0x660D,0x6611,0x6612,0x6615,0x6616,0x661D};
+
+/* page 26 0x4221-0x427E */
+static uint16 tab_jisx0212_uni26[]={
+0x661E,0x6621,0x6622,0x6623,0x6624,0x6626,0x6629,0x662A,
+0x662B,0x662C,0x662E,0x6630,0x6631,0x6633,0x6639,0x6637,
+0x6640,0x6645,0x6646,0x664A,0x664C,0x6651,0x664E,0x6657,
+0x6658,0x6659,0x665B,0x665C,0x6660,0x6661,0x66FB,0x666A,
+0x666B,0x666C,0x667E,0x6673,0x6675,0x667F,0x6677,0x6678,
+0x6679,0x667B,0x6680,0x667C,0x668B,0x668C,0x668D,0x6690,
+0x6692,0x6699,0x669A,0x669B,0x669C,0x669F,0x66A0,0x66A4,
+0x66AD,0x66B1,0x66B2,0x66B5,0x66BB,0x66BF,0x66C0,0x66C2,
+0x66C3,0x66C8,0x66CC,0x66CE,0x66CF,0x66D4,0x66DB,0x66DF,
+0x66E8,0x66EB,0x66EC,0x66EE,0x66FA,0x6705,0x6707,0x670E,
+0x6713,0x6719,0x671C,0x6720,0x6722,0x6733,0x673E,0x6745,
+0x6747,0x6748,0x674C,0x6754,0x6755,0x675D};
+
+/* page 27 0x4321-0x437E */
+static uint16 tab_jisx0212_uni27[]={
+0x6766,0x676C,0x676E,0x6774,0x6776,0x677B,0x6781,0x6784,
+0x678E,0x678F,0x6791,0x6793,0x6796,0x6798,0x6799,0x679B,
+0x67B0,0x67B1,0x67B2,0x67B5,0x67BB,0x67BC,0x67BD,0x67F9,
+0x67C0,0x67C2,0x67C3,0x67C5,0x67C8,0x67C9,0x67D2,0x67D7,
+0x67D9,0x67DC,0x67E1,0x67E6,0x67F0,0x67F2,0x67F6,0x67F7,
+0x6852,0x6814,0x6819,0x681D,0x681F,0x6828,0x6827,0x682C,
+0x682D,0x682F,0x6830,0x6831,0x6833,0x683B,0x683F,0x6844,
+0x6845,0x684A,0x684C,0x6855,0x6857,0x6858,0x685B,0x686B,
+0x686E,0x686F,0x6870,0x6871,0x6872,0x6875,0x6879,0x687A,
+0x687B,0x687C,0x6882,0x6884,0x6886,0x6888,0x6896,0x6898,
+0x689A,0x689C,0x68A1,0x68A3,0x68A5,0x68A9,0x68AA,0x68AE,
+0x68B2,0x68BB,0x68C5,0x68C8,0x68CC,0x68CF};
+
+/* page 28 0x4421-0x447E */
+static uint16 tab_jisx0212_uni28[]={
+0x68D0,0x68D1,0x68D3,0x68D6,0x68D9,0x68DC,0x68DD,0x68E5,
+0x68E8,0x68EA,0x68EB,0x68EC,0x68ED,0x68F0,0x68F1,0x68F5,
+0x68F6,0x68FB,0x68FC,0x68FD,0x6906,0x6909,0x690A,0x6910,
+0x6911,0x6913,0x6916,0x6917,0x6931,0x6933,0x6935,0x6938,
+0x693B,0x6942,0x6945,0x6949,0x694E,0x6957,0x695B,0x6963,
+0x6964,0x6965,0x6966,0x6968,0x6969,0x696C,0x6970,0x6971,
+0x6972,0x697A,0x697B,0x697F,0x6980,0x698D,0x6992,0x6996,
+0x6998,0x69A1,0x69A5,0x69A6,0x69A8,0x69AB,0x69AD,0x69AF,
+0x69B7,0x69B8,0x69BA,0x69BC,0x69C5,0x69C8,0x69D1,0x69D6,
+0x69D7,0x69E2,0x69E5,0x69EE,0x69EF,0x69F1,0x69F3,0x69F5,
+0x69FE,0x6A00,0x6A01,0x6A03,0x6A0F,0x6A11,0x6A15,0x6A1A,
+0x6A1D,0x6A20,0x6A24,0x6A28,0x6A30,0x6A32};
+
+/* page 29 0x4521-0x457E */
+static uint16 tab_jisx0212_uni29[]={
+0x6A34,0x6A37,0x6A3B,0x6A3E,0x6A3F,0x6A45,0x6A46,0x6A49,
+0x6A4A,0x6A4E,0x6A50,0x6A51,0x6A52,0x6A55,0x6A56,0x6A5B,
+0x6A64,0x6A67,0x6A6A,0x6A71,0x6A73,0x6A7E,0x6A81,0x6A83,
+0x6A86,0x6A87,0x6A89,0x6A8B,0x6A91,0x6A9B,0x6A9D,0x6A9E,
+0x6A9F,0x6AA5,0x6AAB,0x6AAF,0x6AB0,0x6AB1,0x6AB4,0x6ABD,
+0x6ABE,0x6ABF,0x6AC6,0x6AC9,0x6AC8,0x6ACC,0x6AD0,0x6AD4,
+0x6AD5,0x6AD6,0x6ADC,0x6ADD,0x6AE4,0x6AE7,0x6AEC,0x6AF0,
+0x6AF1,0x6AF2,0x6AFC,0x6AFD,0x6B02,0x6B03,0x6B06,0x6B07,
+0x6B09,0x6B0F,0x6B10,0x6B11,0x6B17,0x6B1B,0x6B1E,0x6B24,
+0x6B28,0x6B2B,0x6B2C,0x6B2F,0x6B35,0x6B36,0x6B3B,0x6B3F,
+0x6B46,0x6B4A,0x6B4D,0x6B52,0x6B56,0x6B58,0x6B5D,0x6B60,
+0x6B67,0x6B6B,0x6B6E,0x6B70,0x6B75,0x6B7D};
+
+/* page 30 0x4621-0x467E */
+static uint16 tab_jisx0212_uni30[]={
+0x6B7E,0x6B82,0x6B85,0x6B97,0x6B9B,0x6B9F,0x6BA0,0x6BA2,
+0x6BA3,0x6BA8,0x6BA9,0x6BAC,0x6BAD,0x6BAE,0x6BB0,0x6BB8,
+0x6BB9,0x6BBD,0x6BBE,0x6BC3,0x6BC4,0x6BC9,0x6BCC,0x6BD6,
+0x6BDA,0x6BE1,0x6BE3,0x6BE6,0x6BE7,0x6BEE,0x6BF1,0x6BF7,
+0x6BF9,0x6BFF,0x6C02,0x6C04,0x6C05,0x6C09,0x6C0D,0x6C0E,
+0x6C10,0x6C12,0x6C19,0x6C1F,0x6C26,0x6C27,0x6C28,0x6C2C,
+0x6C2E,0x6C33,0x6C35,0x6C36,0x6C3A,0x6C3B,0x6C3F,0x6C4A,
+0x6C4B,0x6C4D,0x6C4F,0x6C52,0x6C54,0x6C59,0x6C5B,0x6C5C,
+0x6C6B,0x6C6D,0x6C6F,0x6C74,0x6C76,0x6C78,0x6C79,0x6C7B,
+0x6C85,0x6C86,0x6C87,0x6C89,0x6C94,0x6C95,0x6C97,0x6C98,
+0x6C9C,0x6C9F,0x6CB0,0x6CB2,0x6CB4,0x6CC2,0x6CC6,0x6CCD,
+0x6CCF,0x6CD0,0x6CD1,0x6CD2,0x6CD4,0x6CD6};
+
+/* page 31 0x4721-0x477E */
+static uint16 tab_jisx0212_uni31[]={
+0x6CDA,0x6CDC,0x6CE0,0x6CE7,0x6CE9,0x6CEB,0x6CEC,0x6CEE,
+0x6CF2,0x6CF4,0x6D04,0x6D07,0x6D0A,0x6D0E,0x6D0F,0x6D11,
+0x6D13,0x6D1A,0x6D26,0x6D27,0x6D28,0x6C67,0x6D2E,0x6D2F,
+0x6D31,0x6D39,0x6D3C,0x6D3F,0x6D57,0x6D5E,0x6D5F,0x6D61,
+0x6D65,0x6D67,0x6D6F,0x6D70,0x6D7C,0x6D82,0x6D87,0x6D91,
+0x6D92,0x6D94,0x6D96,0x6D97,0x6D98,0x6DAA,0x6DAC,0x6DB4,
+0x6DB7,0x6DB9,0x6DBD,0x6DBF,0x6DC4,0x6DC8,0x6DCA,0x6DCE,
+0x6DCF,0x6DD6,0x6DDB,0x6DDD,0x6DDF,0x6DE0,0x6DE2,0x6DE5,
+0x6DE9,0x6DEF,0x6DF0,0x6DF4,0x6DF6,0x6DFC,0x6E00,0x6E04,
+0x6E1E,0x6E22,0x6E27,0x6E32,0x6E36,0x6E39,0x6E3B,0x6E3C,
+0x6E44,0x6E45,0x6E48,0x6E49,0x6E4B,0x6E4F,0x6E51,0x6E52,
+0x6E53,0x6E54,0x6E57,0x6E5C,0x6E5D,0x6E5E};
+
+/* page 32 0x4821-0x487E */
+static uint16 tab_jisx0212_uni32[]={
+0x6E62,0x6E63,0x6E68,0x6E73,0x6E7B,0x6E7D,0x6E8D,0x6E93,
+0x6E99,0x6EA0,0x6EA7,0x6EAD,0x6EAE,0x6EB1,0x6EB3,0x6EBB,
+0x6EBF,0x6EC0,0x6EC1,0x6EC3,0x6EC7,0x6EC8,0x6ECA,0x6ECD,
+0x6ECE,0x6ECF,0x6EEB,0x6EED,0x6EEE,0x6EF9,0x6EFB,0x6EFD,
+0x6F04,0x6F08,0x6F0A,0x6F0C,0x6F0D,0x6F16,0x6F18,0x6F1A,
+0x6F1B,0x6F26,0x6F29,0x6F2A,0x6F2F,0x6F30,0x6F33,0x6F36,
+0x6F3B,0x6F3C,0x6F2D,0x6F4F,0x6F51,0x6F52,0x6F53,0x6F57,
+0x6F59,0x6F5A,0x6F5D,0x6F5E,0x6F61,0x6F62,0x6F68,0x6F6C,
+0x6F7D,0x6F7E,0x6F83,0x6F87,0x6F88,0x6F8B,0x6F8C,0x6F8D,
+0x6F90,0x6F92,0x6F93,0x6F94,0x6F96,0x6F9A,0x6F9F,0x6FA0,
+0x6FA5,0x6FA6,0x6FA7,0x6FA8,0x6FAE,0x6FAF,0x6FB0,0x6FB5,
+0x6FB6,0x6FBC,0x6FC5,0x6FC7,0x6FC8,0x6FCA};
+
+/* page 33 0x4921-0x497E */
+static uint16 tab_jisx0212_uni33[]={
+0x6FDA,0x6FDE,0x6FE8,0x6FE9,0x6FF0,0x6FF5,0x6FF9,0x6FFC,
+0x6FFD,0x7000,0x7005,0x7006,0x7007,0x700D,0x7017,0x7020,
+0x7023,0x702F,0x7034,0x7037,0x7039,0x703C,0x7043,0x7044,
+0x7048,0x7049,0x704A,0x704B,0x7054,0x7055,0x705D,0x705E,
+0x704E,0x7064,0x7065,0x706C,0x706E,0x7075,0x7076,0x707E,
+0x7081,0x7085,0x7086,0x7094,0x7095,0x7096,0x7097,0x7098,
+0x709B,0x70A4,0x70AB,0x70B0,0x70B1,0x70B4,0x70B7,0x70CA,
+0x70D1,0x70D3,0x70D4,0x70D5,0x70D6,0x70D8,0x70DC,0x70E4,
+0x70FA,0x7103,0x7104,0x7105,0x7106,0x7107,0x710B,0x710C,
+0x710F,0x711E,0x7120,0x712B,0x712D,0x712F,0x7130,0x7131,
+0x7138,0x7141,0x7145,0x7146,0x7147,0x714A,0x714B,0x7150,
+0x7152,0x7157,0x715A,0x715C,0x715E,0x7160};
+
+/* page 34 0x4A21-0x4A7E */
+static uint16 tab_jisx0212_uni34[]={
+0x7168,0x7179,0x7180,0x7185,0x7187,0x718C,0x7192,0x719A,
+0x719B,0x71A0,0x71A2,0x71AF,0x71B0,0x71B2,0x71B3,0x71BA,
+0x71BF,0x71C0,0x71C1,0x71C4,0x71CB,0x71CC,0x71D3,0x71D6,
+0x71D9,0x71DA,0x71DC,0x71F8,0x71FE,0x7200,0x7207,0x7208,
+0x7209,0x7213,0x7217,0x721A,0x721D,0x721F,0x7224,0x722B,
+0x722F,0x7234,0x7238,0x7239,0x7241,0x7242,0x7243,0x7245,
+0x724E,0x724F,0x7250,0x7253,0x7255,0x7256,0x725A,0x725C,
+0x725E,0x7260,0x7263,0x7268,0x726B,0x726E,0x726F,0x7271,
+0x7277,0x7278,0x727B,0x727C,0x727F,0x7284,0x7289,0x728D,
+0x728E,0x7293,0x729B,0x72A8,0x72AD,0x72AE,0x72B1,0x72B4,
+0x72BE,0x72C1,0x72C7,0x72C9,0x72CC,0x72D5,0x72D6,0x72D8,
+0x72DF,0x72E5,0x72F3,0x72F4,0x72FA,0x72FB};
+
+/* page 35 0x4B21-0x4B7E */
+static uint16 tab_jisx0212_uni35[]={
+0x72FE,0x7302,0x7304,0x7305,0x7307,0x730B,0x730D,0x7312,
+0x7313,0x7318,0x7319,0x731E,0x7322,0x7324,0x7327,0x7328,
+0x732C,0x7331,0x7332,0x7335,0x733A,0x733B,0x733D,0x7343,
+0x734D,0x7350,0x7352,0x7356,0x7358,0x735D,0x735E,0x735F,
+0x7360,0x7366,0x7367,0x7369,0x736B,0x736C,0x736E,0x736F,
+0x7371,0x7377,0x7379,0x737C,0x7380,0x7381,0x7383,0x7385,
+0x7386,0x738E,0x7390,0x7393,0x7395,0x7397,0x7398,0x739C,
+0x739E,0x739F,0x73A0,0x73A2,0x73A5,0x73A6,0x73AA,0x73AB,
+0x73AD,0x73B5,0x73B7,0x73B9,0x73BC,0x73BD,0x73BF,0x73C5,
+0x73C6,0x73C9,0x73CB,0x73CC,0x73CF,0x73D2,0x73D3,0x73D6,
+0x73D9,0x73DD,0x73E1,0x73E3,0x73E6,0x73E7,0x73E9,0x73F4,
+0x73F5,0x73F7,0x73F9,0x73FA,0x73FB,0x73FD};
+
+/* page 36 0x4C21-0x4C7E */
+static uint16 tab_jisx0212_uni36[]={
+0x73FF,0x7400,0x7401,0x7404,0x7407,0x740A,0x7411,0x741A,
+0x741B,0x7424,0x7426,0x7428,0x7429,0x742A,0x742B,0x742C,
+0x742D,0x742E,0x742F,0x7430,0x7431,0x7439,0x7440,0x7443,
+0x7444,0x7446,0x7447,0x744B,0x744D,0x7451,0x7452,0x7457,
+0x745D,0x7462,0x7466,0x7467,0x7468,0x746B,0x746D,0x746E,
+0x7471,0x7472,0x7480,0x7481,0x7485,0x7486,0x7487,0x7489,
+0x748F,0x7490,0x7491,0x7492,0x7498,0x7499,0x749A,0x749C,
+0x749F,0x74A0,0x74A1,0x74A3,0x74A6,0x74A8,0x74A9,0x74AA,
+0x74AB,0x74AE,0x74AF,0x74B1,0x74B2,0x74B5,0x74B9,0x74BB,
+0x74BF,0x74C8,0x74C9,0x74CC,0x74D0,0x74D3,0x74D8,0x74DA,
+0x74DB,0x74DE,0x74DF,0x74E4,0x74E8,0x74EA,0x74EB,0x74EF,
+0x74F4,0x74FA,0x74FB,0x74FC,0x74FF,0x7506};
+
+/* page 37 0x4D21-0x4D7E */
+static uint16 tab_jisx0212_uni37[]={
+0x7512,0x7516,0x7517,0x7520,0x7521,0x7524,0x7527,0x7529,
+0x752A,0x752F,0x7536,0x7539,0x753D,0x753E,0x753F,0x7540,
+0x7543,0x7547,0x7548,0x754E,0x7550,0x7552,0x7557,0x755E,
+0x755F,0x7561,0x756F,0x7571,0x7579,0x757A,0x757B,0x757C,
+0x757D,0x757E,0x7581,0x7585,0x7590,0x7592,0x7593,0x7595,
+0x7599,0x759C,0x75A2,0x75A4,0x75B4,0x75BA,0x75BF,0x75C0,
+0x75C1,0x75C4,0x75C6,0x75CC,0x75CE,0x75CF,0x75D7,0x75DC,
+0x75DF,0x75E0,0x75E1,0x75E4,0x75E7,0x75EC,0x75EE,0x75EF,
+0x75F1,0x75F9,0x7600,0x7602,0x7603,0x7604,0x7607,0x7608,
+0x760A,0x760C,0x760F,0x7612,0x7613,0x7615,0x7616,0x7619,
+0x761B,0x761C,0x761D,0x761E,0x7623,0x7625,0x7626,0x7629,
+0x762D,0x7632,0x7633,0x7635,0x7638,0x7639};
+
+/* page 38 0x4E21-0x4E7E */
+static uint16 tab_jisx0212_uni38[]={
+0x763A,0x763C,0x764A,0x7640,0x7641,0x7643,0x7644,0x7645,
+0x7649,0x764B,0x7655,0x7659,0x765F,0x7664,0x7665,0x766D,
+0x766E,0x766F,0x7671,0x7674,0x7681,0x7685,0x768C,0x768D,
+0x7695,0x769B,0x769C,0x769D,0x769F,0x76A0,0x76A2,0x76A3,
+0x76A4,0x76A5,0x76A6,0x76A7,0x76A8,0x76AA,0x76AD,0x76BD,
+0x76C1,0x76C5,0x76C9,0x76CB,0x76CC,0x76CE,0x76D4,0x76D9,
+0x76E0,0x76E6,0x76E8,0x76EC,0x76F0,0x76F1,0x76F6,0x76F9,
+0x76FC,0x7700,0x7706,0x770A,0x770E,0x7712,0x7714,0x7715,
+0x7717,0x7719,0x771A,0x771C,0x7722,0x7728,0x772D,0x772E,
+0x772F,0x7734,0x7735,0x7736,0x7739,0x773D,0x773E,0x7742,
+0x7745,0x7746,0x774A,0x774D,0x774E,0x774F,0x7752,0x7756,
+0x7757,0x775C,0x775E,0x775F,0x7760,0x7762};
+
+/* page 39 0x4F21-0x4F7E */
+static uint16 tab_jisx0212_uni39[]={
+0x7764,0x7767,0x776A,0x776C,0x7770,0x7772,0x7773,0x7774,
+0x777A,0x777D,0x7780,0x7784,0x778C,0x778D,0x7794,0x7795,
+0x7796,0x779A,0x779F,0x77A2,0x77A7,0x77AA,0x77AE,0x77AF,
+0x77B1,0x77B5,0x77BE,0x77C3,0x77C9,0x77D1,0x77D2,0x77D5,
+0x77D9,0x77DE,0x77DF,0x77E0,0x77E4,0x77E6,0x77EA,0x77EC,
+0x77F0,0x77F1,0x77F4,0x77F8,0x77FB,0x7805,0x7806,0x7809,
+0x780D,0x780E,0x7811,0x781D,0x7821,0x7822,0x7823,0x782D,
+0x782E,0x7830,0x7835,0x7837,0x7843,0x7844,0x7847,0x7848,
+0x784C,0x784E,0x7852,0x785C,0x785E,0x7860,0x7861,0x7863,
+0x7864,0x7868,0x786A,0x786E,0x787A,0x787E,0x788A,0x788F,
+0x7894,0x7898,0x78A1,0x789D,0x789E,0x789F,0x78A4,0x78A8,
+0x78AC,0x78AD,0x78B0,0x78B1,0x78B2,0x78B3};
+
+/* page 40 0x5021-0x507E */
+static uint16 tab_jisx0212_uni40[]={
+0x78BB,0x78BD,0x78BF,0x78C7,0x78C8,0x78C9,0x78CC,0x78CE,
+0x78D2,0x78D3,0x78D5,0x78D6,0x78E4,0x78DB,0x78DF,0x78E0,
+0x78E1,0x78E6,0x78EA,0x78F2,0x78F3,0x7900,0x78F6,0x78F7,
+0x78FA,0x78FB,0x78FF,0x7906,0x790C,0x7910,0x791A,0x791C,
+0x791E,0x791F,0x7920,0x7925,0x7927,0x7929,0x792D,0x7931,
+0x7934,0x7935,0x793B,0x793D,0x793F,0x7944,0x7945,0x7946,
+0x794A,0x794B,0x794F,0x7951,0x7954,0x7958,0x795B,0x795C,
+0x7967,0x7969,0x796B,0x7972,0x7979,0x797B,0x797C,0x797E,
+0x798B,0x798C,0x7991,0x7993,0x7994,0x7995,0x7996,0x7998,
+0x799B,0x799C,0x79A1,0x79A8,0x79A9,0x79AB,0x79AF,0x79B1,
+0x79B4,0x79B8,0x79BB,0x79C2,0x79C4,0x79C7,0x79C8,0x79CA,
+0x79CF,0x79D4,0x79D6,0x79DA,0x79DD,0x79DE};
+
+/* page 41 0x5121-0x517E */
+static uint16 tab_jisx0212_uni41[]={
+0x79E0,0x79E2,0x79E5,0x79EA,0x79EB,0x79ED,0x79F1,0x79F8,
+0x79FC,0x7A02,0x7A03,0x7A07,0x7A09,0x7A0A,0x7A0C,0x7A11,
+0x7A15,0x7A1B,0x7A1E,0x7A21,0x7A27,0x7A2B,0x7A2D,0x7A2F,
+0x7A30,0x7A34,0x7A35,0x7A38,0x7A39,0x7A3A,0x7A44,0x7A45,
+0x7A47,0x7A48,0x7A4C,0x7A55,0x7A56,0x7A59,0x7A5C,0x7A5D,
+0x7A5F,0x7A60,0x7A65,0x7A67,0x7A6A,0x7A6D,0x7A75,0x7A78,
+0x7A7E,0x7A80,0x7A82,0x7A85,0x7A86,0x7A8A,0x7A8B,0x7A90,
+0x7A91,0x7A94,0x7A9E,0x7AA0,0x7AA3,0x7AAC,0x7AB3,0x7AB5,
+0x7AB9,0x7ABB,0x7ABC,0x7AC6,0x7AC9,0x7ACC,0x7ACE,0x7AD1,
+0x7ADB,0x7AE8,0x7AE9,0x7AEB,0x7AEC,0x7AF1,0x7AF4,0x7AFB,
+0x7AFD,0x7AFE,0x7B07,0x7B14,0x7B1F,0x7B23,0x7B27,0x7B29,
+0x7B2A,0x7B2B,0x7B2D,0x7B2E,0x7B2F,0x7B30};
+
+/* page 42 0x5221-0x527E */
+static uint16 tab_jisx0212_uni42[]={
+0x7B31,0x7B34,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B47,0x7B4E,
+0x7B55,0x7B60,0x7B64,0x7B66,0x7B69,0x7B6A,0x7B6D,0x7B6F,
+0x7B72,0x7B73,0x7B77,0x7B84,0x7B89,0x7B8E,0x7B90,0x7B91,
+0x7B96,0x7B9B,0x7B9E,0x7BA0,0x7BA5,0x7BAC,0x7BAF,0x7BB0,
+0x7BB2,0x7BB5,0x7BB6,0x7BBA,0x7BBB,0x7BBC,0x7BBD,0x7BC2,
+0x7BC5,0x7BC8,0x7BCA,0x7BD4,0x7BD6,0x7BD7,0x7BD9,0x7BDA,
+0x7BDB,0x7BE8,0x7BEA,0x7BF2,0x7BF4,0x7BF5,0x7BF8,0x7BF9,
+0x7BFA,0x7BFC,0x7BFE,0x7C01,0x7C02,0x7C03,0x7C04,0x7C06,
+0x7C09,0x7C0B,0x7C0C,0x7C0E,0x7C0F,0x7C19,0x7C1B,0x7C20,
+0x7C25,0x7C26,0x7C28,0x7C2C,0x7C31,0x7C33,0x7C34,0x7C36,
+0x7C39,0x7C3A,0x7C46,0x7C4A,0x7C55,0x7C51,0x7C52,0x7C53,
+0x7C59,0x7C5A,0x7C5B,0x7C5C,0x7C5D,0x7C5E};
+
+/* page 43 0x5321-0x537E */
+static uint16 tab_jisx0212_uni43[]={
+0x7C61,0x7C63,0x7C67,0x7C69,0x7C6D,0x7C6E,0x7C70,0x7C72,
+0x7C79,0x7C7C,0x7C7D,0x7C86,0x7C87,0x7C8F,0x7C94,0x7C9E,
+0x7CA0,0x7CA6,0x7CB0,0x7CB6,0x7CB7,0x7CBA,0x7CBB,0x7CBC,
+0x7CBF,0x7CC4,0x7CC7,0x7CC8,0x7CC9,0x7CCD,0x7CCF,0x7CD3,
+0x7CD4,0x7CD5,0x7CD7,0x7CD9,0x7CDA,0x7CDD,0x7CE6,0x7CE9,
+0x7CEB,0x7CF5,0x7D03,0x7D07,0x7D08,0x7D09,0x7D0F,0x7D11,
+0x7D12,0x7D13,0x7D16,0x7D1D,0x7D1E,0x7D23,0x7D26,0x7D2A,
+0x7D2D,0x7D31,0x7D3C,0x7D3D,0x7D3E,0x7D40,0x7D41,0x7D47,
+0x7D48,0x7D4D,0x7D51,0x7D53,0x7D57,0x7D59,0x7D5A,0x7D5C,
+0x7D5D,0x7D65,0x7D67,0x7D6A,0x7D70,0x7D78,0x7D7A,0x7D7B,
+0x7D7F,0x7D81,0x7D82,0x7D83,0x7D85,0x7D86,0x7D88,0x7D8B,
+0x7D8C,0x7D8D,0x7D91,0x7D96,0x7D97,0x7D9D};
+
+/* page 44 0x5421-0x547E */
+static uint16 tab_jisx0212_uni44[]={
+0x7D9E,0x7DA6,0x7DA7,0x7DAA,0x7DB3,0x7DB6,0x7DB7,0x7DB9,
+0x7DC2,0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DCC,0x7DCD,0x7DCE,
+0x7DD7,0x7DD9,0x7E00,0x7DE2,0x7DE5,0x7DE6,0x7DEA,0x7DEB,
+0x7DED,0x7DF1,0x7DF5,0x7DF6,0x7DF9,0x7DFA,0x7E08,0x7E10,
+0x7E11,0x7E15,0x7E17,0x7E1C,0x7E1D,0x7E20,0x7E27,0x7E28,
+0x7E2C,0x7E2D,0x7E2F,0x7E33,0x7E36,0x7E3F,0x7E44,0x7E45,
+0x7E47,0x7E4E,0x7E50,0x7E52,0x7E58,0x7E5F,0x7E61,0x7E62,
+0x7E65,0x7E6B,0x7E6E,0x7E6F,0x7E73,0x7E78,0x7E7E,0x7E81,
+0x7E86,0x7E87,0x7E8A,0x7E8D,0x7E91,0x7E95,0x7E98,0x7E9A,
+0x7E9D,0x7E9E,0x7F3C,0x7F3B,0x7F3D,0x7F3E,0x7F3F,0x7F43,
+0x7F44,0x7F47,0x7F4F,0x7F52,0x7F53,0x7F5B,0x7F5C,0x7F5D,
+0x7F61,0x7F63,0x7F64,0x7F65,0x7F66,0x7F6D};
+
+/* page 45 0x5521-0x557E */
+static uint16 tab_jisx0212_uni45[]={
+0x7F71,0x7F7D,0x7F7E,0x7F7F,0x7F80,0x7F8B,0x7F8D,0x7F8F,
+0x7F90,0x7F91,0x7F96,0x7F97,0x7F9C,0x7FA1,0x7FA2,0x7FA6,
+0x7FAA,0x7FAD,0x7FB4,0x7FBC,0x7FBF,0x7FC0,0x7FC3,0x7FC8,
+0x7FCE,0x7FCF,0x7FDB,0x7FDF,0x7FE3,0x7FE5,0x7FE8,0x7FEC,
+0x7FEE,0x7FEF,0x7FF2,0x7FFA,0x7FFD,0x7FFE,0x7FFF,0x8007,
+0x8008,0x800A,0x800D,0x800E,0x800F,0x8011,0x8013,0x8014,
+0x8016,0x801D,0x801E,0x801F,0x8020,0x8024,0x8026,0x802C,
+0x802E,0x8030,0x8034,0x8035,0x8037,0x8039,0x803A,0x803C,
+0x803E,0x8040,0x8044,0x8060,0x8064,0x8066,0x806D,0x8071,
+0x8075,0x8081,0x8088,0x808E,0x809C,0x809E,0x80A6,0x80A7,
+0x80AB,0x80B8,0x80B9,0x80C8,0x80CD,0x80CF,0x80D2,0x80D4,
+0x80D5,0x80D7,0x80D8,0x80E0,0x80ED,0x80EE};
+
+/* page 46 0x5621-0x567E */
+static uint16 tab_jisx0212_uni46[]={
+0x80F0,0x80F2,0x80F3,0x80F6,0x80F9,0x80FA,0x80FE,0x8103,
+0x810B,0x8116,0x8117,0x8118,0x811C,0x811E,0x8120,0x8124,
+0x8127,0x812C,0x8130,0x8135,0x813A,0x813C,0x8145,0x8147,
+0x814A,0x814C,0x8152,0x8157,0x8160,0x8161,0x8167,0x8168,
+0x8169,0x816D,0x816F,0x8177,0x8181,0x8190,0x8184,0x8185,
+0x8186,0x818B,0x818E,0x8196,0x8198,0x819B,0x819E,0x81A2,
+0x81AE,0x81B2,0x81B4,0x81BB,0x81CB,0x81C3,0x81C5,0x81CA,
+0x81CE,0x81CF,0x81D5,0x81D7,0x81DB,0x81DD,0x81DE,0x81E1,
+0x81E4,0x81EB,0x81EC,0x81F0,0x81F1,0x81F2,0x81F5,0x81F6,
+0x81F8,0x81F9,0x81FD,0x81FF,0x8200,0x8203,0x820F,0x8213,
+0x8214,0x8219,0x821A,0x821D,0x8221,0x8222,0x8228,0x8232,
+0x8234,0x823A,0x8243,0x8244,0x8245,0x8246};
+
+/* page 47 0x5721-0x577E */
+static uint16 tab_jisx0212_uni47[]={
+0x824B,0x824E,0x824F,0x8251,0x8256,0x825C,0x8260,0x8263,
+0x8267,0x826D,0x8274,0x827B,0x827D,0x827F,0x8280,0x8281,
+0x8283,0x8284,0x8287,0x8289,0x828A,0x828E,0x8291,0x8294,
+0x8296,0x8298,0x829A,0x829B,0x82A0,0x82A1,0x82A3,0x82A4,
+0x82A7,0x82A8,0x82A9,0x82AA,0x82AE,0x82B0,0x82B2,0x82B4,
+0x82B7,0x82BA,0x82BC,0x82BE,0x82BF,0x82C6,0x82D0,0x82D5,
+0x82DA,0x82E0,0x82E2,0x82E4,0x82E8,0x82EA,0x82ED,0x82EF,
+0x82F6,0x82F7,0x82FD,0x82FE,0x8300,0x8301,0x8307,0x8308,
+0x830A,0x830B,0x8354,0x831B,0x831D,0x831E,0x831F,0x8321,
+0x8322,0x832C,0x832D,0x832E,0x8330,0x8333,0x8337,0x833A,
+0x833C,0x833D,0x8342,0x8343,0x8344,0x8347,0x834D,0x834E,
+0x8351,0x8355,0x8356,0x8357,0x8370,0x8378};
+
+/* page 48 0x5821-0x587E */
+static uint16 tab_jisx0212_uni48[]={
+0x837D,0x837F,0x8380,0x8382,0x8384,0x8386,0x838D,0x8392,
+0x8394,0x8395,0x8398,0x8399,0x839B,0x839C,0x839D,0x83A6,
+0x83A7,0x83A9,0x83AC,0x83BE,0x83BF,0x83C0,0x83C7,0x83C9,
+0x83CF,0x83D0,0x83D1,0x83D4,0x83DD,0x8353,0x83E8,0x83EA,
+0x83F6,0x83F8,0x83F9,0x83FC,0x8401,0x8406,0x840A,0x840F,
+0x8411,0x8415,0x8419,0x83AD,0x842F,0x8439,0x8445,0x8447,
+0x8448,0x844A,0x844D,0x844F,0x8451,0x8452,0x8456,0x8458,
+0x8459,0x845A,0x845C,0x8460,0x8464,0x8465,0x8467,0x846A,
+0x8470,0x8473,0x8474,0x8476,0x8478,0x847C,0x847D,0x8481,
+0x8485,0x8492,0x8493,0x8495,0x849E,0x84A6,0x84A8,0x84A9,
+0x84AA,0x84AF,0x84B1,0x84B4,0x84BA,0x84BD,0x84BE,0x84C0,
+0x84C2,0x84C7,0x84C8,0x84CC,0x84CF,0x84D3};
+
+/* page 49 0x5921-0x597E */
+static uint16 tab_jisx0212_uni49[]={
+0x84DC,0x84E7,0x84EA,0x84EF,0x84F0,0x84F1,0x84F2,0x84F7,
+0x8532,0x84FA,0x84FB,0x84FD,0x8502,0x8503,0x8507,0x850C,
+0x850E,0x8510,0x851C,0x851E,0x8522,0x8523,0x8524,0x8525,
+0x8527,0x852A,0x852B,0x852F,0x8533,0x8534,0x8536,0x853F,
+0x8546,0x854F,0x8550,0x8551,0x8552,0x8553,0x8556,0x8559,
+0x855C,0x855D,0x855E,0x855F,0x8560,0x8561,0x8562,0x8564,
+0x856B,0x856F,0x8579,0x857A,0x857B,0x857D,0x857F,0x8581,
+0x8585,0x8586,0x8589,0x858B,0x858C,0x858F,0x8593,0x8598,
+0x859D,0x859F,0x85A0,0x85A2,0x85A5,0x85A7,0x85B4,0x85B6,
+0x85B7,0x85B8,0x85BC,0x85BD,0x85BE,0x85BF,0x85C2,0x85C7,
+0x85CA,0x85CB,0x85CE,0x85AD,0x85D8,0x85DA,0x85DF,0x85E0,
+0x85E6,0x85E8,0x85ED,0x85F3,0x85F6,0x85FC};
+
+/* page 50 0x5A21-0x5A7E */
+static uint16 tab_jisx0212_uni50[]={
+0x85FF,0x8600,0x8604,0x8605,0x860D,0x860E,0x8610,0x8611,
+0x8612,0x8618,0x8619,0x861B,0x861E,0x8621,0x8627,0x8629,
+0x8636,0x8638,0x863A,0x863C,0x863D,0x8640,0x8642,0x8646,
+0x8652,0x8653,0x8656,0x8657,0x8658,0x8659,0x865D,0x8660,
+0x8661,0x8662,0x8663,0x8664,0x8669,0x866C,0x866F,0x8675,
+0x8676,0x8677,0x867A,0x868D,0x8691,0x8696,0x8698,0x869A,
+0x869C,0x86A1,0x86A6,0x86A7,0x86A8,0x86AD,0x86B1,0x86B3,
+0x86B4,0x86B5,0x86B7,0x86B8,0x86B9,0x86BF,0x86C0,0x86C1,
+0x86C3,0x86C5,0x86D1,0x86D2,0x86D5,0x86D7,0x86DA,0x86DC,
+0x86E0,0x86E3,0x86E5,0x86E7,0x8688,0x86FA,0x86FC,0x86FD,
+0x8704,0x8705,0x8707,0x870B,0x870E,0x870F,0x8710,0x8713,
+0x8714,0x8719,0x871E,0x871F,0x8721,0x8723};
+
+/* page 51 0x5B21-0x5B7E */
+static uint16 tab_jisx0212_uni51[]={
+0x8728,0x872E,0x872F,0x8731,0x8732,0x8739,0x873A,0x873C,
+0x873D,0x873E,0x8740,0x8743,0x8745,0x874D,0x8758,0x875D,
+0x8761,0x8764,0x8765,0x876F,0x8771,0x8772,0x877B,0x8783,
+0x8784,0x8785,0x8786,0x8787,0x8788,0x8789,0x878B,0x878C,
+0x8790,0x8793,0x8795,0x8797,0x8798,0x8799,0x879E,0x87A0,
+0x87A3,0x87A7,0x87AC,0x87AD,0x87AE,0x87B1,0x87B5,0x87BE,
+0x87BF,0x87C1,0x87C8,0x87C9,0x87CA,0x87CE,0x87D5,0x87D6,
+0x87D9,0x87DA,0x87DC,0x87DF,0x87E2,0x87E3,0x87E4,0x87EA,
+0x87EB,0x87ED,0x87F1,0x87F3,0x87F8,0x87FA,0x87FF,0x8801,
+0x8803,0x8806,0x8809,0x880A,0x880B,0x8810,0x8819,0x8812,
+0x8813,0x8814,0x8818,0x881A,0x881B,0x881C,0x881E,0x881F,
+0x8828,0x882D,0x882E,0x8830,0x8832,0x8835};
+
+/* page 52 0x5C21-0x5C7E */
+static uint16 tab_jisx0212_uni52[]={
+0x883A,0x883C,0x8841,0x8843,0x8845,0x8848,0x8849,0x884A,
+0x884B,0x884E,0x8851,0x8855,0x8856,0x8858,0x885A,0x885C,
+0x885F,0x8860,0x8864,0x8869,0x8871,0x8879,0x887B,0x8880,
+0x8898,0x889A,0x889B,0x889C,0x889F,0x88A0,0x88A8,0x88AA,
+0x88BA,0x88BD,0x88BE,0x88C0,0x88CA,0x88CB,0x88CC,0x88CD,
+0x88CE,0x88D1,0x88D2,0x88D3,0x88DB,0x88DE,0x88E7,0x88EF,
+0x88F0,0x88F1,0x88F5,0x88F7,0x8901,0x8906,0x890D,0x890E,
+0x890F,0x8915,0x8916,0x8918,0x8919,0x891A,0x891C,0x8920,
+0x8926,0x8927,0x8928,0x8930,0x8931,0x8932,0x8935,0x8939,
+0x893A,0x893E,0x8940,0x8942,0x8945,0x8946,0x8949,0x894F,
+0x8952,0x8957,0x895A,0x895B,0x895C,0x8961,0x8962,0x8963,
+0x896B,0x896E,0x8970,0x8973,0x8975,0x897A};
+
+/* page 53 0x5D21-0x5D7E */
+static uint16 tab_jisx0212_uni53[]={
+0x897B,0x897C,0x897D,0x8989,0x898D,0x8990,0x8994,0x8995,
+0x899B,0x899C,0x899F,0x89A0,0x89A5,0x89B0,0x89B4,0x89B5,
+0x89B6,0x89B7,0x89BC,0x89D4,0x89D5,0x89D6,0x89D7,0x89D8,
+0x89E5,0x89E9,0x89EB,0x89ED,0x89F1,0x89F3,0x89F6,0x89F9,
+0x89FD,0x89FF,0x8A04,0x8A05,0x8A07,0x8A0F,0x8A11,0x8A12,
+0x8A14,0x8A15,0x8A1E,0x8A20,0x8A22,0x8A24,0x8A26,0x8A2B,
+0x8A2C,0x8A2F,0x8A35,0x8A37,0x8A3D,0x8A3E,0x8A40,0x8A43,
+0x8A45,0x8A47,0x8A49,0x8A4D,0x8A4E,0x8A53,0x8A56,0x8A57,
+0x8A58,0x8A5C,0x8A5D,0x8A61,0x8A65,0x8A67,0x8A75,0x8A76,
+0x8A77,0x8A79,0x8A7A,0x8A7B,0x8A7E,0x8A7F,0x8A80,0x8A83,
+0x8A86,0x8A8B,0x8A8F,0x8A90,0x8A92,0x8A96,0x8A97,0x8A99,
+0x8A9F,0x8AA7,0x8AA9,0x8AAE,0x8AAF,0x8AB3};
+
+/* page 54 0x5E21-0x5E7E */
+static uint16 tab_jisx0212_uni54[]={
+0x8AB6,0x8AB7,0x8ABB,0x8ABE,0x8AC3,0x8AC6,0x8AC8,0x8AC9,
+0x8ACA,0x8AD1,0x8AD3,0x8AD4,0x8AD5,0x8AD7,0x8ADD,0x8ADF,
+0x8AEC,0x8AF0,0x8AF4,0x8AF5,0x8AF6,0x8AFC,0x8AFF,0x8B05,
+0x8B06,0x8B0B,0x8B11,0x8B1C,0x8B1E,0x8B1F,0x8B0A,0x8B2D,
+0x8B30,0x8B37,0x8B3C,0x8B42,0x8B43,0x8B44,0x8B45,0x8B46,
+0x8B48,0x8B52,0x8B53,0x8B54,0x8B59,0x8B4D,0x8B5E,0x8B63,
+0x8B6D,0x8B76,0x8B78,0x8B79,0x8B7C,0x8B7E,0x8B81,0x8B84,
+0x8B85,0x8B8B,0x8B8D,0x8B8F,0x8B94,0x8B95,0x8B9C,0x8B9E,
+0x8B9F,0x8C38,0x8C39,0x8C3D,0x8C3E,0x8C45,0x8C47,0x8C49,
+0x8C4B,0x8C4F,0x8C51,0x8C53,0x8C54,0x8C57,0x8C58,0x8C5B,
+0x8C5D,0x8C59,0x8C63,0x8C64,0x8C66,0x8C68,0x8C69,0x8C6D,
+0x8C73,0x8C75,0x8C76,0x8C7B,0x8C7E,0x8C86};
+
+/* page 55 0x5F21-0x5F7E */
+static uint16 tab_jisx0212_uni55[]={
+0x8C87,0x8C8B,0x8C90,0x8C92,0x8C93,0x8C99,0x8C9B,0x8C9C,
+0x8CA4,0x8CB9,0x8CBA,0x8CC5,0x8CC6,0x8CC9,0x8CCB,0x8CCF,
+0x8CD6,0x8CD5,0x8CD9,0x8CDD,0x8CE1,0x8CE8,0x8CEC,0x8CEF,
+0x8CF0,0x8CF2,0x8CF5,0x8CF7,0x8CF8,0x8CFE,0x8CFF,0x8D01,
+0x8D03,0x8D09,0x8D12,0x8D17,0x8D1B,0x8D65,0x8D69,0x8D6C,
+0x8D6E,0x8D7F,0x8D82,0x8D84,0x8D88,0x8D8D,0x8D90,0x8D91,
+0x8D95,0x8D9E,0x8D9F,0x8DA0,0x8DA6,0x8DAB,0x8DAC,0x8DAF,
+0x8DB2,0x8DB5,0x8DB7,0x8DB9,0x8DBB,0x8DC0,0x8DC5,0x8DC6,
+0x8DC7,0x8DC8,0x8DCA,0x8DCE,0x8DD1,0x8DD4,0x8DD5,0x8DD7,
+0x8DD9,0x8DE4,0x8DE5,0x8DE7,0x8DEC,0x8DF0,0x8DBC,0x8DF1,
+0x8DF2,0x8DF4,0x8DFD,0x8E01,0x8E04,0x8E05,0x8E06,0x8E0B,
+0x8E11,0x8E14,0x8E16,0x8E20,0x8E21,0x8E22};
+
+/* page 56 0x6021-0x607E */
+static uint16 tab_jisx0212_uni56[]={
+0x8E23,0x8E26,0x8E27,0x8E31,0x8E33,0x8E36,0x8E37,0x8E38,
+0x8E39,0x8E3D,0x8E40,0x8E41,0x8E4B,0x8E4D,0x8E4E,0x8E4F,
+0x8E54,0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E61,0x8E62,0x8E69,
+0x8E6C,0x8E6D,0x8E6F,0x8E70,0x8E71,0x8E79,0x8E7A,0x8E7B,
+0x8E82,0x8E83,0x8E89,0x8E90,0x8E92,0x8E95,0x8E9A,0x8E9B,
+0x8E9D,0x8E9E,0x8EA2,0x8EA7,0x8EA9,0x8EAD,0x8EAE,0x8EB3,
+0x8EB5,0x8EBA,0x8EBB,0x8EC0,0x8EC1,0x8EC3,0x8EC4,0x8EC7,
+0x8ECF,0x8ED1,0x8ED4,0x8EDC,0x8EE8,0x8EEE,0x8EF0,0x8EF1,
+0x8EF7,0x8EF9,0x8EFA,0x8EED,0x8F00,0x8F02,0x8F07,0x8F08,
+0x8F0F,0x8F10,0x8F16,0x8F17,0x8F18,0x8F1E,0x8F20,0x8F21,
+0x8F23,0x8F25,0x8F27,0x8F28,0x8F2C,0x8F2D,0x8F2E,0x8F34,
+0x8F35,0x8F36,0x8F37,0x8F3A,0x8F40,0x8F41};
+
+/* page 57 0x6121-0x617E */
+static uint16 tab_jisx0212_uni57[]={
+0x8F43,0x8F47,0x8F4F,0x8F51,0x8F52,0x8F53,0x8F54,0x8F55,
+0x8F58,0x8F5D,0x8F5E,0x8F65,0x8F9D,0x8FA0,0x8FA1,0x8FA4,
+0x8FA5,0x8FA6,0x8FB5,0x8FB6,0x8FB8,0x8FBE,0x8FC0,0x8FC1,
+0x8FC6,0x8FCA,0x8FCB,0x8FCD,0x8FD0,0x8FD2,0x8FD3,0x8FD5,
+0x8FE0,0x8FE3,0x8FE4,0x8FE8,0x8FEE,0x8FF1,0x8FF5,0x8FF6,
+0x8FFB,0x8FFE,0x9002,0x9004,0x9008,0x900C,0x9018,0x901B,
+0x9028,0x9029,0x902F,0x902A,0x902C,0x902D,0x9033,0x9034,
+0x9037,0x903F,0x9043,0x9044,0x904C,0x905B,0x905D,0x9062,
+0x9066,0x9067,0x906C,0x9070,0x9074,0x9079,0x9085,0x9088,
+0x908B,0x908C,0x908E,0x9090,0x9095,0x9097,0x9098,0x9099,
+0x909B,0x90A0,0x90A1,0x90A2,0x90A5,0x90B0,0x90B2,0x90B3,
+0x90B4,0x90B6,0x90BD,0x90CC,0x90BE,0x90C3};
+
+/* page 58 0x6221-0x627E */
+static uint16 tab_jisx0212_uni58[]={
+0x90C4,0x90C5,0x90C7,0x90C8,0x90D5,0x90D7,0x90D8,0x90D9,
+0x90DC,0x90DD,0x90DF,0x90E5,0x90D2,0x90F6,0x90EB,0x90EF,
+0x90F0,0x90F4,0x90FE,0x90FF,0x9100,0x9104,0x9105,0x9106,
+0x9108,0x910D,0x9110,0x9114,0x9116,0x9117,0x9118,0x911A,
+0x911C,0x911E,0x9120,0x9125,0x9122,0x9123,0x9127,0x9129,
+0x912E,0x912F,0x9131,0x9134,0x9136,0x9137,0x9139,0x913A,
+0x913C,0x913D,0x9143,0x9147,0x9148,0x914F,0x9153,0x9157,
+0x9159,0x915A,0x915B,0x9161,0x9164,0x9167,0x916D,0x9174,
+0x9179,0x917A,0x917B,0x9181,0x9183,0x9185,0x9186,0x918A,
+0x918E,0x9191,0x9193,0x9194,0x9195,0x9198,0x919E,0x91A1,
+0x91A6,0x91A8,0x91AC,0x91AD,0x91AE,0x91B0,0x91B1,0x91B2,
+0x91B3,0x91B6,0x91BB,0x91BC,0x91BD,0x91BF};
+
+/* page 59 0x6321-0x637E */
+static uint16 tab_jisx0212_uni59[]={
+0x91C2,0x91C3,0x91C5,0x91D3,0x91D4,0x91D7,0x91D9,0x91DA,
+0x91DE,0x91E4,0x91E5,0x91E9,0x91EA,0x91EC,0x91ED,0x91EE,
+0x91EF,0x91F0,0x91F1,0x91F7,0x91F9,0x91FB,0x91FD,0x9200,
+0x9201,0x9204,0x9205,0x9206,0x9207,0x9209,0x920A,0x920C,
+0x9210,0x9212,0x9213,0x9216,0x9218,0x921C,0x921D,0x9223,
+0x9224,0x9225,0x9226,0x9228,0x922E,0x922F,0x9230,0x9233,
+0x9235,0x9236,0x9238,0x9239,0x923A,0x923C,0x923E,0x9240,
+0x9242,0x9243,0x9246,0x9247,0x924A,0x924D,0x924E,0x924F,
+0x9251,0x9258,0x9259,0x925C,0x925D,0x9260,0x9261,0x9265,
+0x9267,0x9268,0x9269,0x926E,0x926F,0x9270,0x9275,0x9276,
+0x9277,0x9278,0x9279,0x927B,0x927C,0x927D,0x927F,0x9288,
+0x9289,0x928A,0x928D,0x928E,0x9292,0x9297};
+
+/* page 60 0x6421-0x647E */
+static uint16 tab_jisx0212_uni60[]={
+0x9299,0x929F,0x92A0,0x92A4,0x92A5,0x92A7,0x92A8,0x92AB,
+0x92AF,0x92B2,0x92B6,0x92B8,0x92BA,0x92BB,0x92BC,0x92BD,
+0x92BF,0x92C0,0x92C1,0x92C2,0x92C3,0x92C5,0x92C6,0x92C7,
+0x92C8,0x92CB,0x92CC,0x92CD,0x92CE,0x92D0,0x92D3,0x92D5,
+0x92D7,0x92D8,0x92D9,0x92DC,0x92DD,0x92DF,0x92E0,0x92E1,
+0x92E3,0x92E5,0x92E7,0x92E8,0x92EC,0x92EE,0x92F0,0x92F9,
+0x92FB,0x92FF,0x9300,0x9302,0x9308,0x930D,0x9311,0x9314,
+0x9315,0x931C,0x931D,0x931E,0x931F,0x9321,0x9324,0x9325,
+0x9327,0x9329,0x932A,0x9333,0x9334,0x9336,0x9337,0x9347,
+0x9348,0x9349,0x9350,0x9351,0x9352,0x9355,0x9357,0x9358,
+0x935A,0x935E,0x9364,0x9365,0x9367,0x9369,0x936A,0x936D,
+0x936F,0x9370,0x9371,0x9373,0x9374,0x9376};
+
+/* page 61 0x6521-0x657E */
+static uint16 tab_jisx0212_uni61[]={
+0x937A,0x937D,0x937F,0x9380,0x9381,0x9382,0x9388,0x938A,
+0x938B,0x938D,0x938F,0x9392,0x9395,0x9398,0x939B,0x939E,
+0x93A1,0x93A3,0x93A4,0x93A6,0x93A8,0x93AB,0x93B4,0x93B5,
+0x93B6,0x93BA,0x93A9,0x93C1,0x93C4,0x93C5,0x93C6,0x93C7,
+0x93C9,0x93CA,0x93CB,0x93CC,0x93CD,0x93D3,0x93D9,0x93DC,
+0x93DE,0x93DF,0x93E2,0x93E6,0x93E7,0x93F9,0x93F7,0x93F8,
+0x93FA,0x93FB,0x93FD,0x9401,0x9402,0x9404,0x9408,0x9409,
+0x940D,0x940E,0x940F,0x9415,0x9416,0x9417,0x941F,0x942E,
+0x942F,0x9431,0x9432,0x9433,0x9434,0x943B,0x943F,0x943D,
+0x9443,0x9445,0x9448,0x944A,0x944C,0x9455,0x9459,0x945C,
+0x945F,0x9461,0x9463,0x9468,0x946B,0x946D,0x946E,0x946F,
+0x9471,0x9472,0x9484,0x9483,0x9578,0x9579};
+
+/* page 62 0x6621-0x667E */
+static uint16 tab_jisx0212_uni62[]={
+0x957E,0x9584,0x9588,0x958C,0x958D,0x958E,0x959D,0x959E,
+0x959F,0x95A1,0x95A6,0x95A9,0x95AB,0x95AC,0x95B4,0x95B6,
+0x95BA,0x95BD,0x95BF,0x95C6,0x95C8,0x95C9,0x95CB,0x95D0,
+0x95D1,0x95D2,0x95D3,0x95D9,0x95DA,0x95DD,0x95DE,0x95DF,
+0x95E0,0x95E4,0x95E6,0x961D,0x961E,0x9622,0x9624,0x9625,
+0x9626,0x962C,0x9631,0x9633,0x9637,0x9638,0x9639,0x963A,
+0x963C,0x963D,0x9641,0x9652,0x9654,0x9656,0x9657,0x9658,
+0x9661,0x966E,0x9674,0x967B,0x967C,0x967E,0x967F,0x9681,
+0x9682,0x9683,0x9684,0x9689,0x9691,0x9696,0x969A,0x969D,
+0x969F,0x96A4,0x96A5,0x96A6,0x96A9,0x96AE,0x96AF,0x96B3,
+0x96BA,0x96CA,0x96D2,0x5DB2,0x96D8,0x96DA,0x96DD,0x96DE,
+0x96DF,0x96E9,0x96EF,0x96F1,0x96FA,0x9702};
+
+/* page 63 0x6721-0x677E */
+static uint16 tab_jisx0212_uni63[]={
+0x9703,0x9705,0x9709,0x971A,0x971B,0x971D,0x9721,0x9722,
+0x9723,0x9728,0x9731,0x9733,0x9741,0x9743,0x974A,0x974E,
+0x974F,0x9755,0x9757,0x9758,0x975A,0x975B,0x9763,0x9767,
+0x976A,0x976E,0x9773,0x9776,0x9777,0x9778,0x977B,0x977D,
+0x977F,0x9780,0x9789,0x9795,0x9796,0x9797,0x9799,0x979A,
+0x979E,0x979F,0x97A2,0x97AC,0x97AE,0x97B1,0x97B2,0x97B5,
+0x97B6,0x97B8,0x97B9,0x97BA,0x97BC,0x97BE,0x97BF,0x97C1,
+0x97C4,0x97C5,0x97C7,0x97C9,0x97CA,0x97CC,0x97CD,0x97CE,
+0x97D0,0x97D1,0x97D4,0x97D7,0x97D8,0x97D9,0x97DD,0x97DE,
+0x97E0,0x97DB,0x97E1,0x97E4,0x97EF,0x97F1,0x97F4,0x97F7,
+0x97F8,0x97FA,0x9807,0x980A,0x9819,0x980D,0x980E,0x9814,
+0x9816,0x981C,0x981E,0x9820,0x9823,0x9826};
+
+/* page 64 0x6821-0x687E */
+static uint16 tab_jisx0212_uni64[]={
+0x982B,0x982E,0x982F,0x9830,0x9832,0x9833,0x9835,0x9825,
+0x983E,0x9844,0x9847,0x984A,0x9851,0x9852,0x9853,0x9856,
+0x9857,0x9859,0x985A,0x9862,0x9863,0x9865,0x9866,0x986A,
+0x986C,0x98AB,0x98AD,0x98AE,0x98B0,0x98B4,0x98B7,0x98B8,
+0x98BA,0x98BB,0x98BF,0x98C2,0x98C5,0x98C8,0x98CC,0x98E1,
+0x98E3,0x98E5,0x98E6,0x98E7,0x98EA,0x98F3,0x98F6,0x9902,
+0x9907,0x9908,0x9911,0x9915,0x9916,0x9917,0x991A,0x991B,
+0x991C,0x991F,0x9922,0x9926,0x9927,0x992B,0x9931,0x9932,
+0x9933,0x9934,0x9935,0x9939,0x993A,0x993B,0x993C,0x9940,
+0x9941,0x9946,0x9947,0x9948,0x994D,0x994E,0x9954,0x9958,
+0x9959,0x995B,0x995C,0x995E,0x995F,0x9960,0x999B,0x999D,
+0x999F,0x99A6,0x99B0,0x99B1,0x99B2,0x99B5};
+
+/* page 65 0x6921-0x697E */
+static uint16 tab_jisx0212_uni65[]={
+0x99B9,0x99BA,0x99BD,0x99BF,0x99C3,0x99C9,0x99D3,0x99D4,
+0x99D9,0x99DA,0x99DC,0x99DE,0x99E7,0x99EA,0x99EB,0x99EC,
+0x99F0,0x99F4,0x99F5,0x99F9,0x99FD,0x99FE,0x9A02,0x9A03,
+0x9A04,0x9A0B,0x9A0C,0x9A10,0x9A11,0x9A16,0x9A1E,0x9A20,
+0x9A22,0x9A23,0x9A24,0x9A27,0x9A2D,0x9A2E,0x9A33,0x9A35,
+0x9A36,0x9A38,0x9A47,0x9A41,0x9A44,0x9A4A,0x9A4B,0x9A4C,
+0x9A4E,0x9A51,0x9A54,0x9A56,0x9A5D,0x9AAA,0x9AAC,0x9AAE,
+0x9AAF,0x9AB2,0x9AB4,0x9AB5,0x9AB6,0x9AB9,0x9ABB,0x9ABE,
+0x9ABF,0x9AC1,0x9AC3,0x9AC6,0x9AC8,0x9ACE,0x9AD0,0x9AD2,
+0x9AD5,0x9AD6,0x9AD7,0x9ADB,0x9ADC,0x9AE0,0x9AE4,0x9AE5,
+0x9AE7,0x9AE9,0x9AEC,0x9AF2,0x9AF3,0x9AF5,0x9AF9,0x9AFA,
+0x9AFD,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B03};
+
+/* page 66 0x6A21-0x6A7E */
+static uint16 tab_jisx0212_uni66[]={
+0x9B04,0x9B05,0x9B08,0x9B09,0x9B0B,0x9B0C,0x9B0D,0x9B0E,
+0x9B10,0x9B12,0x9B16,0x9B19,0x9B1B,0x9B1C,0x9B20,0x9B26,
+0x9B2B,0x9B2D,0x9B33,0x9B34,0x9B35,0x9B37,0x9B39,0x9B3A,
+0x9B3D,0x9B48,0x9B4B,0x9B4C,0x9B55,0x9B56,0x9B57,0x9B5B,
+0x9B5E,0x9B61,0x9B63,0x9B65,0x9B66,0x9B68,0x9B6A,0x9B6B,
+0x9B6C,0x9B6D,0x9B6E,0x9B73,0x9B75,0x9B77,0x9B78,0x9B79,
+0x9B7F,0x9B80,0x9B84,0x9B85,0x9B86,0x9B87,0x9B89,0x9B8A,
+0x9B8B,0x9B8D,0x9B8F,0x9B90,0x9B94,0x9B9A,0x9B9D,0x9B9E,
+0x9BA6,0x9BA7,0x9BA9,0x9BAC,0x9BB0,0x9BB1,0x9BB2,0x9BB7,
+0x9BB8,0x9BBB,0x9BBC,0x9BBE,0x9BBF,0x9BC1,0x9BC7,0x9BC8,
+0x9BCE,0x9BD0,0x9BD7,0x9BD8,0x9BDD,0x9BDF,0x9BE5,0x9BE7,
+0x9BEA,0x9BEB,0x9BEF,0x9BF3,0x9BF7,0x9BF8};
+
+/* page 67 0x6B21-0x6B7E */
+static uint16 tab_jisx0212_uni67[]={
+0x9BF9,0x9BFA,0x9BFD,0x9BFF,0x9C00,0x9C02,0x9C0B,0x9C0F,
+0x9C11,0x9C16,0x9C18,0x9C19,0x9C1A,0x9C1C,0x9C1E,0x9C22,
+0x9C23,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,0x9C31,0x9C35,
+0x9C36,0x9C37,0x9C3D,0x9C41,0x9C43,0x9C44,0x9C45,0x9C49,
+0x9C4A,0x9C4E,0x9C4F,0x9C50,0x9C53,0x9C54,0x9C56,0x9C58,
+0x9C5B,0x9C5D,0x9C5E,0x9C5F,0x9C63,0x9C69,0x9C6A,0x9C5C,
+0x9C6B,0x9C68,0x9C6E,0x9C70,0x9C72,0x9C75,0x9C77,0x9C7B,
+0x9CE6,0x9CF2,0x9CF7,0x9CF9,0x9D0B,0x9D02,0x9D11,0x9D17,
+0x9D18,0x9D1C,0x9D1D,0x9D1E,0x9D2F,0x9D30,0x9D32,0x9D33,
+0x9D34,0x9D3A,0x9D3C,0x9D45,0x9D3D,0x9D42,0x9D43,0x9D47,
+0x9D4A,0x9D53,0x9D54,0x9D5F,0x9D63,0x9D62,0x9D65,0x9D69,
+0x9D6A,0x9D6B,0x9D70,0x9D76,0x9D77,0x9D7B};
+
+/* page 68 0x6C21-0x6C7E */
+static uint16 tab_jisx0212_uni68[]={
+0x9D7C,0x9D7E,0x9D83,0x9D84,0x9D86,0x9D8A,0x9D8D,0x9D8E,
+0x9D92,0x9D93,0x9D95,0x9D96,0x9D97,0x9D98,0x9DA1,0x9DAA,
+0x9DAC,0x9DAE,0x9DB1,0x9DB5,0x9DB9,0x9DBC,0x9DBF,0x9DC3,
+0x9DC7,0x9DC9,0x9DCA,0x9DD4,0x9DD5,0x9DD6,0x9DD7,0x9DDA,
+0x9DDE,0x9DDF,0x9DE0,0x9DE5,0x9DE7,0x9DE9,0x9DEB,0x9DEE,
+0x9DF0,0x9DF3,0x9DF4,0x9DFE,0x9E0A,0x9E02,0x9E07,0x9E0E,
+0x9E10,0x9E11,0x9E12,0x9E15,0x9E16,0x9E19,0x9E1C,0x9E1D,
+0x9E7A,0x9E7B,0x9E7C,0x9E80,0x9E82,0x9E83,0x9E84,0x9E85,
+0x9E87,0x9E8E,0x9E8F,0x9E96,0x9E98,0x9E9B,0x9E9E,0x9EA4,
+0x9EA8,0x9EAC,0x9EAE,0x9EAF,0x9EB0,0x9EB3,0x9EB4,0x9EB5,
+0x9EC6,0x9EC8,0x9ECB,0x9ED5,0x9EDF,0x9EE4,0x9EE7,0x9EEC,
+0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2,0x9EF5};
+
+/* page 69 0x6D21-0x6D63 */
+static uint16 tab_jisx0212_uni69[]={
+0x9EF8,0x9EFF,0x9F02,0x9F03,0x9F09,0x9F0F,0x9F10,0x9F11,
+0x9F12,0x9F14,0x9F16,0x9F17,0x9F19,0x9F1A,0x9F1B,0x9F1F,
+0x9F22,0x9F26,0x9F2A,0x9F2B,0x9F2F,0x9F31,0x9F32,0x9F34,
+0x9F37,0x9F39,0x9F3A,0x9F3C,0x9F3D,0x9F3F,0x9F41,0x9F43,
+0x9F44,0x9F45,0x9F46,0x9F47,0x9F53,0x9F55,0x9F56,0x9F57,
+0x9F58,0x9F5A,0x9F5D,0x9F5E,0x9F68,0x9F69,0x9F6D,0x9F6E,
+0x9F6F,0x9F70,0x9F71,0x9F73,0x9F75,0x9F7A,0x9F7D,0x9F8F,
+0x9F90,0x9F91,0x9F92,0x9F94,0x9F96,0x9F97,0x9F9E,0x9FA1,
+0x9FA2,0x9FA3,0x9FA5};
+
+static int
+my_jisx0212_uni_onechar(int code){
+ if ((code>=0x222F)&&(code<=0x2244))
+ return(tab_jisx0212_uni0[code-0x222F]);
+ if ((code>=0x226B)&&(code<=0x2271))
+ return(tab_jisx0212_uni1[code-0x226B]);
+ if ((code>=0x2661)&&(code<=0x267C))
+ return(tab_jisx0212_uni2[code-0x2661]);
+ if ((code>=0x2742)&&(code<=0x274E))
+ return(tab_jisx0212_uni3[code-0x2742]);
+ if ((code>=0x2772)&&(code<=0x277E))
+ return(tab_jisx0212_uni4[code-0x2772]);
+ if ((code>=0x2921)&&(code<=0x2950))
+ return(tab_jisx0212_uni5[code-0x2921]);
+ if ((code>=0x2A21)&&(code<=0x2A77))
+ return(tab_jisx0212_uni6[code-0x2A21]);
+ if ((code>=0x2B21)&&(code<=0x2B77))
+ return(tab_jisx0212_uni7[code-0x2B21]);
+ if ((code>=0x3021)&&(code<=0x307E))
+ return(tab_jisx0212_uni8[code-0x3021]);
+ if ((code>=0x3121)&&(code<=0x317E))
+ return(tab_jisx0212_uni9[code-0x3121]);
+ if ((code>=0x3221)&&(code<=0x327E))
+ return(tab_jisx0212_uni10[code-0x3221]);
+ if ((code>=0x3321)&&(code<=0x337E))
+ return(tab_jisx0212_uni11[code-0x3321]);
+ if ((code>=0x3421)&&(code<=0x347E))
+ return(tab_jisx0212_uni12[code-0x3421]);
+ if ((code>=0x3521)&&(code<=0x357E))
+ return(tab_jisx0212_uni13[code-0x3521]);
+ if ((code>=0x3621)&&(code<=0x367E))
+ return(tab_jisx0212_uni14[code-0x3621]);
+ if ((code>=0x3721)&&(code<=0x377E))
+ return(tab_jisx0212_uni15[code-0x3721]);
+ if ((code>=0x3821)&&(code<=0x387E))
+ return(tab_jisx0212_uni16[code-0x3821]);
+ if ((code>=0x3921)&&(code<=0x397E))
+ return(tab_jisx0212_uni17[code-0x3921]);
+ if ((code>=0x3A21)&&(code<=0x3A7E))
+ return(tab_jisx0212_uni18[code-0x3A21]);
+ if ((code>=0x3B21)&&(code<=0x3B7E))
+ return(tab_jisx0212_uni19[code-0x3B21]);
+ if ((code>=0x3C21)&&(code<=0x3C7E))
+ return(tab_jisx0212_uni20[code-0x3C21]);
+ if ((code>=0x3D21)&&(code<=0x3D7E))
+ return(tab_jisx0212_uni21[code-0x3D21]);
+ if ((code>=0x3E21)&&(code<=0x3E7E))
+ return(tab_jisx0212_uni22[code-0x3E21]);
+ if ((code>=0x3F21)&&(code<=0x3F7E))
+ return(tab_jisx0212_uni23[code-0x3F21]);
+ if ((code>=0x4021)&&(code<=0x407E))
+ return(tab_jisx0212_uni24[code-0x4021]);
+ if ((code>=0x4121)&&(code<=0x417E))
+ return(tab_jisx0212_uni25[code-0x4121]);
+ if ((code>=0x4221)&&(code<=0x427E))
+ return(tab_jisx0212_uni26[code-0x4221]);
+ if ((code>=0x4321)&&(code<=0x437E))
+ return(tab_jisx0212_uni27[code-0x4321]);
+ if ((code>=0x4421)&&(code<=0x447E))
+ return(tab_jisx0212_uni28[code-0x4421]);
+ if ((code>=0x4521)&&(code<=0x457E))
+ return(tab_jisx0212_uni29[code-0x4521]);
+ if ((code>=0x4621)&&(code<=0x467E))
+ return(tab_jisx0212_uni30[code-0x4621]);
+ if ((code>=0x4721)&&(code<=0x477E))
+ return(tab_jisx0212_uni31[code-0x4721]);
+ if ((code>=0x4821)&&(code<=0x487E))
+ return(tab_jisx0212_uni32[code-0x4821]);
+ if ((code>=0x4921)&&(code<=0x497E))
+ return(tab_jisx0212_uni33[code-0x4921]);
+ if ((code>=0x4A21)&&(code<=0x4A7E))
+ return(tab_jisx0212_uni34[code-0x4A21]);
+ if ((code>=0x4B21)&&(code<=0x4B7E))
+ return(tab_jisx0212_uni35[code-0x4B21]);
+ if ((code>=0x4C21)&&(code<=0x4C7E))
+ return(tab_jisx0212_uni36[code-0x4C21]);
+ if ((code>=0x4D21)&&(code<=0x4D7E))
+ return(tab_jisx0212_uni37[code-0x4D21]);
+ if ((code>=0x4E21)&&(code<=0x4E7E))
+ return(tab_jisx0212_uni38[code-0x4E21]);
+ if ((code>=0x4F21)&&(code<=0x4F7E))
+ return(tab_jisx0212_uni39[code-0x4F21]);
+ if ((code>=0x5021)&&(code<=0x507E))
+ return(tab_jisx0212_uni40[code-0x5021]);
+ if ((code>=0x5121)&&(code<=0x517E))
+ return(tab_jisx0212_uni41[code-0x5121]);
+ if ((code>=0x5221)&&(code<=0x527E))
+ return(tab_jisx0212_uni42[code-0x5221]);
+ if ((code>=0x5321)&&(code<=0x537E))
+ return(tab_jisx0212_uni43[code-0x5321]);
+ if ((code>=0x5421)&&(code<=0x547E))
+ return(tab_jisx0212_uni44[code-0x5421]);
+ if ((code>=0x5521)&&(code<=0x557E))
+ return(tab_jisx0212_uni45[code-0x5521]);
+ if ((code>=0x5621)&&(code<=0x567E))
+ return(tab_jisx0212_uni46[code-0x5621]);
+ if ((code>=0x5721)&&(code<=0x577E))
+ return(tab_jisx0212_uni47[code-0x5721]);
+ if ((code>=0x5821)&&(code<=0x587E))
+ return(tab_jisx0212_uni48[code-0x5821]);
+ if ((code>=0x5921)&&(code<=0x597E))
+ return(tab_jisx0212_uni49[code-0x5921]);
+ if ((code>=0x5A21)&&(code<=0x5A7E))
+ return(tab_jisx0212_uni50[code-0x5A21]);
+ if ((code>=0x5B21)&&(code<=0x5B7E))
+ return(tab_jisx0212_uni51[code-0x5B21]);
+ if ((code>=0x5C21)&&(code<=0x5C7E))
+ return(tab_jisx0212_uni52[code-0x5C21]);
+ if ((code>=0x5D21)&&(code<=0x5D7E))
+ return(tab_jisx0212_uni53[code-0x5D21]);
+ if ((code>=0x5E21)&&(code<=0x5E7E))
+ return(tab_jisx0212_uni54[code-0x5E21]);
+ if ((code>=0x5F21)&&(code<=0x5F7E))
+ return(tab_jisx0212_uni55[code-0x5F21]);
+ if ((code>=0x6021)&&(code<=0x607E))
+ return(tab_jisx0212_uni56[code-0x6021]);
+ if ((code>=0x6121)&&(code<=0x617E))
+ return(tab_jisx0212_uni57[code-0x6121]);
+ if ((code>=0x6221)&&(code<=0x627E))
+ return(tab_jisx0212_uni58[code-0x6221]);
+ if ((code>=0x6321)&&(code<=0x637E))
+ return(tab_jisx0212_uni59[code-0x6321]);
+ if ((code>=0x6421)&&(code<=0x647E))
+ return(tab_jisx0212_uni60[code-0x6421]);
+ if ((code>=0x6521)&&(code<=0x657E))
+ return(tab_jisx0212_uni61[code-0x6521]);
+ if ((code>=0x6621)&&(code<=0x667E))
+ return(tab_jisx0212_uni62[code-0x6621]);
+ if ((code>=0x6721)&&(code<=0x677E))
+ return(tab_jisx0212_uni63[code-0x6721]);
+ if ((code>=0x6821)&&(code<=0x687E))
+ return(tab_jisx0212_uni64[code-0x6821]);
+ if ((code>=0x6921)&&(code<=0x697E))
+ return(tab_jisx0212_uni65[code-0x6921]);
+ if ((code>=0x6A21)&&(code<=0x6A7E))
+ return(tab_jisx0212_uni66[code-0x6A21]);
+ if ((code>=0x6B21)&&(code<=0x6B7E))
+ return(tab_jisx0212_uni67[code-0x6B21]);
+ if ((code>=0x6C21)&&(code<=0x6C7E))
+ return(tab_jisx0212_uni68[code-0x6C21]);
+ if ((code>=0x6D21)&&(code<=0x6D63))
+ return(tab_jisx0212_uni69[code-0x6D21]);
+ return(0);
+}
+
+
+
+/*
+ EUC-JP encoding subcomponents:
+ [x00-x7F] # ASCII/JIS-Roman (one-byte/character)
+ [x8E][xA0-xDF] # half-width katakana (two bytes/char)
+ [x8F][xA1-xFE][xA1-xFE] # JIS X 0212-1990 (three bytes/char)
+ [xA1-xFE][xA1-xFE] # JIS X 0208:1997 (two bytes/char)
+*/
+
+static int
+my_mb_wc_euc_jp(CHARSET_INFO *cs,my_wc_t *pwc, const uchar *s, const uchar *e)
+{
+ int c1,c2,c3;
+
+ if (s>e)
+ return MY_CS_TOOFEW(0);
+
+ c1=s[0];
+
+ /* Ascii code set */
+ if (c1<=0x7F)
+ {
+ *pwc=c1;
+ return 1;
+ }
+
+ if (s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ c2=s[1];
+
+
+ /* JIS X 0208 code set */
+ if (c1>=0xA1 && c1<=0xFE)
+ {
+ if (c2 < 0xA1 || c2 >0xFE)
+ return MY_CS_ILSEQ;
+
+ if (c1 < 0xF5)
+ {
+ pwc[0]=my_jisx0208_uni_onechar( ((c1-0x80) << 8) + (c2-0x80));
+ if (!pwc[0])
+ return MY_CS_ILSEQ;
+ }
+ else
+ {
+ /* User defined range */
+ pwc[0]=0xE000 + 94*(c1-0xF5) +(c2-0xA1);
+ }
+ return 2;
+ }
+
+ /* JIS X 0201 code set (Half Width Tatakana) */
+ if (c1==0x8E)
+ {
+ int ret;
+
+ if (c2<0xA1 || c2>0xDF)
+ return MY_CS_ILSEQ;
+
+ ret = my_mb_wc_jisx0201(cs,pwc,s+1,e);
+ if (ret!=1)
+ return ret;
+ return 2;
+ }
+
+ /* JIS X 0212 code set */
+ if (c1==0x8F)
+ {
+ if (c2<0xA1 || c2>=0xFF)
+ return MY_CS_ILSEQ;
+
+ if (s+3>e)
+ return MY_CS_TOOFEW(0);
+
+ c3=s[2];
+ if (c3 < 0xA1 || c3>=0xFF)
+ return MY_CS_ILSEQ;
+
+ if (c2<0xF5)
+ {
+ pwc[0]=my_jisx0212_uni_onechar((c2-0x80)*256 + (c3-0x80));
+ if (!pwc)
+ return MY_CS_ILSEQ;
+ }
+ else
+ {
+ /* User defined range */
+ pwc[0]= 0xE3AC + 94*(c2-0xF5) + (c3-0xA1);
+ }
+ return 3;
+ }
+
+ return MY_CS_ILSEQ;
+}
+
+static int
+my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e)
+{
+ unsigned char buf[2];
+ unsigned char c1;
+ int ret,jp;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if (wc<0x80)
+ {
+ if (s>e)
+ return MY_CS_TOOSMALL;
+
+ *s=wc;
+ return 1;
+ }
+
+ if ((jp=my_uni_jisx0208_onechar(wc)))
+ {
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ jp+=0x8080;
+ s[0]=jp>>8;
+ s[1]=jp&0xFF;
+ return 2;
+ }
+
+ ret=my_wc_mb_jisx0201(c,wc,buf,buf+2);
+ if (ret==1)
+ {
+ if (s+1>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=0x8E;
+ s[1]=buf[0];
+ return 1;
+ }
+
+
+ if ((jp=my_uni_jisx0212_onechar(wc)))
+ {
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ jp+=0x8080;
+ s[0]=0x8F;
+ s[1]=jp>>8;
+ s[2]=jp&0xFF;
+ return 3;
+ }
+
+
+ /* User defined range */
+ if (wc>=0xE000 && wc<0xE3AC)
+ {
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ c1=((unsigned)(wc-0xE000)/94)+0xF5;
+ s[0]=c1;
+ c1=((unsigned)(wc-0xE000)%94)+0xa1;
+ s[1]=c1;
+ return 2;
+ }
+
+
+ /* User defined range */
+ if (wc>=0xE3AC && wc<0xE758)
+ {
+ if (s+3>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=0x8F;
+ c1=((unsigned)(wc-0xE3AC)/94)+0xF5;
+ s[1]=c1;
+ c1=((unsigned)(wc-0xE3AC)%94)+0xa1;
+ s[2]=c1;
+ return 3;
+ }
+
+ return MY_CS_ILUNI;
+}
+
+CHARSET_INFO my_charset_ujis =
+{
+ 12, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "ujis", /* cs name */
+ "ujis", /* name */
+ "", /* comment */
+ ctype_ujis,
+ to_lower_ujis,
+ to_upper_ujis,
+ sort_order_ujis,
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 0, /* strxfrm_multiply */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,
+ my_strnxfrm_simple, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_mb, /* wildcmp */
+ 3, /* mbmaxlen */
+ ismbchar_ujis,
+ ismbhead_ujis,
+ mbcharlen_ujis,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_mb_wc_euc_jp, /* mb_wc */
+ my_wc_mb_euc_jp, /* wc_mb */
+ my_caseup_str_mb,
+ my_casedn_str_mb,
+ my_caseup_mb,
+ my_casedn_mb,
+ my_tosort_8bit,
+ my_strcasecmp_mb,
+ my_strncasecmp_mb,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+
+#endif
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
new file mode 100644
index 00000000000..e63405001f9
--- /dev/null
+++ b/strings/ctype-utf8.c
@@ -0,0 +1,3135 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library 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 */
+
+/* UTF8 according RFC 2279 */
+/* Written by Alexander Barkov <bar@udm.net> */
+
+#include <my_global.h>
+#include "m_string.h"
+#include "m_ctype.h"
+#include <errno.h>
+
+#ifndef EILSEQ
+#define EILSEQ ENOENT
+#endif
+
+#ifdef HAVE_CHARSET_utf8
+#define HAVE_UNIDATA
+#endif
+
+#ifdef HAVE_CHARSET_ucs2
+#define HAVE_UNIDATA
+#endif
+
+#ifdef HAVE_UNIDATA
+
+static MY_UNICASE_INFO plane00[]={
+ {0x0000,0x0000,0x0000}, {0x0001,0x0001,0x0001},
+ {0x0002,0x0002,0x0002}, {0x0003,0x0003,0x0003},
+ {0x0004,0x0004,0x0004}, {0x0005,0x0005,0x0005},
+ {0x0006,0x0006,0x0006}, {0x0007,0x0007,0x0007},
+ {0x0008,0x0008,0x0008}, {0x0009,0x0009,0x0009},
+ {0x000A,0x000A,0x000A}, {0x000B,0x000B,0x000B},
+ {0x000C,0x000C,0x000C}, {0x000D,0x000D,0x000D},
+ {0x000E,0x000E,0x000E}, {0x000F,0x000F,0x000F},
+ {0x0010,0x0010,0x0010}, {0x0011,0x0011,0x0011},
+ {0x0012,0x0012,0x0012}, {0x0013,0x0013,0x0013},
+ {0x0014,0x0014,0x0014}, {0x0015,0x0015,0x0015},
+ {0x0016,0x0016,0x0016}, {0x0017,0x0017,0x0017},
+ {0x0018,0x0018,0x0018}, {0x0019,0x0019,0x0019},
+ {0x001A,0x001A,0x001A}, {0x001B,0x001B,0x001B},
+ {0x001C,0x001C,0x001C}, {0x001D,0x001D,0x001D},
+ {0x001E,0x001E,0x001E}, {0x001F,0x001F,0x001F},
+ {0x0020,0x0020,0x0020}, {0x0021,0x0021,0x0021},
+ {0x0022,0x0022,0x0022}, {0x0023,0x0023,0x0023},
+ {0x0024,0x0024,0x0024}, {0x0025,0x0025,0x0025},
+ {0x0026,0x0026,0x0026}, {0x0027,0x0027,0x0027},
+ {0x0028,0x0028,0x0028}, {0x0029,0x0029,0x0029},
+ {0x002A,0x002A,0x002A}, {0x002B,0x002B,0x002B},
+ {0x002C,0x002C,0x002C}, {0x002D,0x002D,0x002D},
+ {0x002E,0x002E,0x002E}, {0x002F,0x002F,0x002F},
+ {0x0030,0x0030,0x0030}, {0x0031,0x0031,0x0031},
+ {0x0032,0x0032,0x0032}, {0x0033,0x0033,0x0033},
+ {0x0034,0x0034,0x0034}, {0x0035,0x0035,0x0035},
+ {0x0036,0x0036,0x0036}, {0x0037,0x0037,0x0037},
+ {0x0038,0x0038,0x0038}, {0x0039,0x0039,0x0039},
+ {0x003A,0x003A,0x003A}, {0x003B,0x003B,0x003B},
+ {0x003C,0x003C,0x003C}, {0x003D,0x003D,0x003D},
+ {0x003E,0x003E,0x003E}, {0x003F,0x003F,0x003F},
+ {0x0040,0x0040,0x0040}, {0x0041,0x0061,0x0041},
+ {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043},
+ {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045},
+ {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047},
+ {0x0048,0x0068,0x0048}, {0x0049,0x0069,0x0049},
+ {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B},
+ {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D},
+ {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F},
+ {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051},
+ {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053},
+ {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055},
+ {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057},
+ {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059},
+ {0x005A,0x007A,0x005A}, {0x005B,0x005B,0x005B},
+ {0x005C,0x005C,0x005C}, {0x005D,0x005D,0x005D},
+ {0x005E,0x005E,0x005E}, {0x005F,0x005F,0x005F},
+ {0x0060,0x0060,0x0060}, {0x0041,0x0061,0x0041},
+ {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043},
+ {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045},
+ {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047},
+ {0x0048,0x0068,0x0048}, {0x0049,0x0069,0x0049},
+ {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B},
+ {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D},
+ {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F},
+ {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051},
+ {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053},
+ {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055},
+ {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057},
+ {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059},
+ {0x005A,0x007A,0x005A}, {0x007B,0x007B,0x007B},
+ {0x007C,0x007C,0x007C}, {0x007D,0x007D,0x007D},
+ {0x007E,0x007E,0x007E}, {0x007F,0x007F,0x007F},
+ {0x0080,0x0080,0x0080}, {0x0081,0x0081,0x0081},
+ {0x0082,0x0082,0x0082}, {0x0083,0x0083,0x0083},
+ {0x0084,0x0084,0x0084}, {0x0085,0x0085,0x0085},
+ {0x0086,0x0086,0x0086}, {0x0087,0x0087,0x0087},
+ {0x0088,0x0088,0x0088}, {0x0089,0x0089,0x0089},
+ {0x008A,0x008A,0x008A}, {0x008B,0x008B,0x008B},
+ {0x008C,0x008C,0x008C}, {0x008D,0x008D,0x008D},
+ {0x008E,0x008E,0x008E}, {0x008F,0x008F,0x008F},
+ {0x0090,0x0090,0x0090}, {0x0091,0x0091,0x0091},
+ {0x0092,0x0092,0x0092}, {0x0093,0x0093,0x0093},
+ {0x0094,0x0094,0x0094}, {0x0095,0x0095,0x0095},
+ {0x0096,0x0096,0x0096}, {0x0097,0x0097,0x0097},
+ {0x0098,0x0098,0x0098}, {0x0099,0x0099,0x0099},
+ {0x009A,0x009A,0x009A}, {0x009B,0x009B,0x009B},
+ {0x009C,0x009C,0x009C}, {0x009D,0x009D,0x009D},
+ {0x009E,0x009E,0x009E}, {0x009F,0x009F,0x009F},
+ {0x00A0,0x00A0,0x00A0}, {0x00A1,0x00A1,0x00A1},
+ {0x00A2,0x00A2,0x00A2}, {0x00A3,0x00A3,0x00A3},
+ {0x00A4,0x00A4,0x00A4}, {0x00A5,0x00A5,0x00A5},
+ {0x00A6,0x00A6,0x00A6}, {0x00A7,0x00A7,0x00A7},
+ {0x00A8,0x00A8,0x00A8}, {0x00A9,0x00A9,0x00A9},
+ {0x00AA,0x00AA,0x00AA}, {0x00AB,0x00AB,0x00AB},
+ {0x00AC,0x00AC,0x00AC}, {0x00AD,0x00AD,0x00AD},
+ {0x00AE,0x00AE,0x00AE}, {0x00AF,0x00AF,0x00AF},
+ {0x00B0,0x00B0,0x00B0}, {0x00B1,0x00B1,0x00B1},
+ {0x00B2,0x00B2,0x00B2}, {0x00B3,0x00B3,0x00B3},
+ {0x00B4,0x00B4,0x00B4}, {0x039C,0x00B5,0x039C},
+ {0x00B6,0x00B6,0x00B6}, {0x00B7,0x00B7,0x00B7},
+ {0x00B8,0x00B8,0x00B8}, {0x00B9,0x00B9,0x00B9},
+ {0x00BA,0x00BA,0x00BA}, {0x00BB,0x00BB,0x00BB},
+ {0x00BC,0x00BC,0x00BC}, {0x00BD,0x00BD,0x00BD},
+ {0x00BE,0x00BE,0x00BE}, {0x00BF,0x00BF,0x00BF},
+ {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041},
+ {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041},
+ {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041},
+ {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043},
+ {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045},
+ {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045},
+ {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049},
+ {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049},
+ {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E},
+ {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F},
+ {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F},
+ {0x00D6,0x00F6,0x004F}, {0x00D7,0x00D7,0x00D7},
+ {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055},
+ {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055},
+ {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059},
+ {0x00DE,0x00FE,0x00DE}, {0x00DF,0x00DF,0x00DF},
+ {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041},
+ {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041},
+ {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041},
+ {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043},
+ {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045},
+ {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045},
+ {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049},
+ {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049},
+ {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E},
+ {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F},
+ {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F},
+ {0x00D6,0x00F6,0x004F}, {0x00F7,0x00F7,0x00F7},
+ {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055},
+ {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055},
+ {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059},
+ {0x00DE,0x00FE,0x00DE}, {0x0178,0x00FF,0x0059}
+};
+
+static MY_UNICASE_INFO plane01[]={
+ {0x0100,0x0101,0x0041}, {0x0100,0x0101,0x0041},
+ {0x0102,0x0103,0x0041}, {0x0102,0x0103,0x0041},
+ {0x0104,0x0105,0x0041}, {0x0104,0x0105,0x0041},
+ {0x0106,0x0107,0x0043}, {0x0106,0x0107,0x0043},
+ {0x0108,0x0109,0x0043}, {0x0108,0x0109,0x0043},
+ {0x010A,0x010B,0x0043}, {0x010A,0x010B,0x0043},
+ {0x010C,0x010D,0x0043}, {0x010C,0x010D,0x0043},
+ {0x010E,0x010F,0x0044}, {0x010E,0x010F,0x0044},
+ {0x0110,0x0111,0x0110}, {0x0110,0x0111,0x0110},
+ {0x0112,0x0113,0x0045}, {0x0112,0x0113,0x0045},
+ {0x0114,0x0115,0x0045}, {0x0114,0x0115,0x0045},
+ {0x0116,0x0117,0x0045}, {0x0116,0x0117,0x0045},
+ {0x0118,0x0119,0x0045}, {0x0118,0x0119,0x0045},
+ {0x011A,0x011B,0x0045}, {0x011A,0x011B,0x0045},
+ {0x011C,0x011D,0x0047}, {0x011C,0x011D,0x0047},
+ {0x011E,0x011F,0x0047}, {0x011E,0x011F,0x0047},
+ {0x0120,0x0121,0x0047}, {0x0120,0x0121,0x0047},
+ {0x0122,0x0123,0x0047}, {0x0122,0x0123,0x0047},
+ {0x0124,0x0125,0x0048}, {0x0124,0x0125,0x0048},
+ {0x0126,0x0127,0x0126}, {0x0126,0x0127,0x0126},
+ {0x0128,0x0129,0x0049}, {0x0128,0x0129,0x0049},
+ {0x012A,0x012B,0x0049}, {0x012A,0x012B,0x0049},
+ {0x012C,0x012D,0x0049}, {0x012C,0x012D,0x0049},
+ {0x012E,0x012F,0x0049}, {0x012E,0x012F,0x0049},
+ {0x0130,0x0069,0x0049}, {0x0049,0x0131,0x0049},
+ {0x0132,0x0133,0x0132}, {0x0132,0x0133,0x0132},
+ {0x0134,0x0135,0x004A}, {0x0134,0x0135,0x004A},
+ {0x0136,0x0137,0x004B}, {0x0136,0x0137,0x004B},
+ {0x0138,0x0138,0x0138}, {0x0139,0x013A,0x004C},
+ {0x0139,0x013A,0x004C}, {0x013B,0x013C,0x004C},
+ {0x013B,0x013C,0x004C}, {0x013D,0x013E,0x004C},
+ {0x013D,0x013E,0x004C}, {0x013F,0x0140,0x013F},
+ {0x013F,0x0140,0x013F}, {0x0141,0x0142,0x0141},
+ {0x0141,0x0142,0x0141}, {0x0143,0x0144,0x004E},
+ {0x0143,0x0144,0x004E}, {0x0145,0x0146,0x004E},
+ {0x0145,0x0146,0x004E}, {0x0147,0x0148,0x004E},
+ {0x0147,0x0148,0x004E}, {0x0149,0x0149,0x0149},
+ {0x014A,0x014B,0x014A}, {0x014A,0x014B,0x014A},
+ {0x014C,0x014D,0x004F}, {0x014C,0x014D,0x004F},
+ {0x014E,0x014F,0x004F}, {0x014E,0x014F,0x004F},
+ {0x0150,0x0151,0x004F}, {0x0150,0x0151,0x004F},
+ {0x0152,0x0153,0x0152}, {0x0152,0x0153,0x0152},
+ {0x0154,0x0155,0x0052}, {0x0154,0x0155,0x0052},
+ {0x0156,0x0157,0x0052}, {0x0156,0x0157,0x0052},
+ {0x0158,0x0159,0x0052}, {0x0158,0x0159,0x0052},
+ {0x015A,0x015B,0x0053}, {0x015A,0x015B,0x0053},
+ {0x015C,0x015D,0x0053}, {0x015C,0x015D,0x0053},
+ {0x015E,0x015F,0x0053}, {0x015E,0x015F,0x0053},
+ {0x0160,0x0161,0x0053}, {0x0160,0x0161,0x0053},
+ {0x0162,0x0163,0x0054}, {0x0162,0x0163,0x0054},
+ {0x0164,0x0165,0x0054}, {0x0164,0x0165,0x0054},
+ {0x0166,0x0167,0x0166}, {0x0166,0x0167,0x0166},
+ {0x0168,0x0169,0x0055}, {0x0168,0x0169,0x0055},
+ {0x016A,0x016B,0x0055}, {0x016A,0x016B,0x0055},
+ {0x016C,0x016D,0x0055}, {0x016C,0x016D,0x0055},
+ {0x016E,0x016F,0x0055}, {0x016E,0x016F,0x0055},
+ {0x0170,0x0171,0x0055}, {0x0170,0x0171,0x0055},
+ {0x0172,0x0173,0x0055}, {0x0172,0x0173,0x0055},
+ {0x0174,0x0175,0x0057}, {0x0174,0x0175,0x0057},
+ {0x0176,0x0177,0x0059}, {0x0176,0x0177,0x0059},
+ {0x0178,0x00FF,0x0059}, {0x0179,0x017A,0x005A},
+ {0x0179,0x017A,0x005A}, {0x017B,0x017C,0x005A},
+ {0x017B,0x017C,0x005A}, {0x017D,0x017E,0x005A},
+ {0x017D,0x017E,0x005A}, {0x0053,0x017F,0x0053},
+ {0x0180,0x0180,0x0180}, {0x0181,0x0253,0x0181},
+ {0x0182,0x0183,0x0182}, {0x0182,0x0183,0x0182},
+ {0x0184,0x0185,0x0184}, {0x0184,0x0185,0x0184},
+ {0x0186,0x0254,0x0186}, {0x0187,0x0188,0x0187},
+ {0x0187,0x0188,0x0187}, {0x0189,0x0256,0x0189},
+ {0x018A,0x0257,0x018A}, {0x018B,0x018C,0x018B},
+ {0x018B,0x018C,0x018B}, {0x018D,0x018D,0x018D},
+ {0x018E,0x01DD,0x018E}, {0x018F,0x0259,0x018F},
+ {0x0190,0x025B,0x0190}, {0x0191,0x0192,0x0191},
+ {0x0191,0x0192,0x0191}, {0x0193,0x0260,0x0193},
+ {0x0194,0x0263,0x0194}, {0x01F6,0x0195,0x01F6},
+ {0x0196,0x0269,0x0196}, {0x0197,0x0268,0x0197},
+ {0x0198,0x0199,0x0198}, {0x0198,0x0199,0x0198},
+ {0x019A,0x019A,0x019A}, {0x019B,0x019B,0x019B},
+ {0x019C,0x026F,0x019C}, {0x019D,0x0272,0x019D},
+ {0x019E,0x019E,0x019E}, {0x019F,0x0275,0x019F},
+ {0x01A0,0x01A1,0x004F}, {0x01A0,0x01A1,0x004F},
+ {0x01A2,0x01A3,0x01A2}, {0x01A2,0x01A3,0x01A2},
+ {0x01A4,0x01A5,0x01A4}, {0x01A4,0x01A5,0x01A4},
+ {0x01A6,0x0280,0x01A6}, {0x01A7,0x01A8,0x01A7},
+ {0x01A7,0x01A8,0x01A7}, {0x01A9,0x0283,0x01A9},
+ {0x01AA,0x01AA,0x01AA}, {0x01AB,0x01AB,0x01AB},
+ {0x01AC,0x01AD,0x01AC}, {0x01AC,0x01AD,0x01AC},
+ {0x01AE,0x0288,0x01AE}, {0x01AF,0x01B0,0x0055},
+ {0x01AF,0x01B0,0x0055}, {0x01B1,0x028A,0x01B1},
+ {0x01B2,0x028B,0x01B2}, {0x01B3,0x01B4,0x01B3},
+ {0x01B3,0x01B4,0x01B3}, {0x01B5,0x01B6,0x01B5},
+ {0x01B5,0x01B6,0x01B5}, {0x01B7,0x0292,0x01B7},
+ {0x01B8,0x01B9,0x01B8}, {0x01B8,0x01B9,0x01B8},
+ {0x01BA,0x01BA,0x01BA}, {0x01BB,0x01BB,0x01BB},
+ {0x01BC,0x01BD,0x01BC}, {0x01BC,0x01BD,0x01BC},
+ {0x01BE,0x01BE,0x01BE}, {0x01F7,0x01BF,0x01F7},
+ {0x01C0,0x01C0,0x01C0}, {0x01C1,0x01C1,0x01C1},
+ {0x01C2,0x01C2,0x01C2}, {0x01C3,0x01C3,0x01C3},
+ {0x01C4,0x01C6,0x01C4}, {0x01C4,0x01C6,0x01C4},
+ {0x01C4,0x01C6,0x01C4}, {0x01C7,0x01C9,0x01C7},
+ {0x01C7,0x01C9,0x01C7}, {0x01C7,0x01C9,0x01C7},
+ {0x01CA,0x01CC,0x01CA}, {0x01CA,0x01CC,0x01CA},
+ {0x01CA,0x01CC,0x01CA}, {0x01CD,0x01CE,0x0041},
+ {0x01CD,0x01CE,0x0041}, {0x01CF,0x01D0,0x0049},
+ {0x01CF,0x01D0,0x0049}, {0x01D1,0x01D2,0x004F},
+ {0x01D1,0x01D2,0x004F}, {0x01D3,0x01D4,0x0055},
+ {0x01D3,0x01D4,0x0055}, {0x01D5,0x01D6,0x0055},
+ {0x01D5,0x01D6,0x0055}, {0x01D7,0x01D8,0x0055},
+ {0x01D7,0x01D8,0x0055}, {0x01D9,0x01DA,0x0055},
+ {0x01D9,0x01DA,0x0055}, {0x01DB,0x01DC,0x0055},
+ {0x01DB,0x01DC,0x0055}, {0x018E,0x01DD,0x018E},
+ {0x01DE,0x01DF,0x0041}, {0x01DE,0x01DF,0x0041},
+ {0x01E0,0x01E1,0x0041}, {0x01E0,0x01E1,0x0041},
+ {0x01E2,0x01E3,0x00C6}, {0x01E2,0x01E3,0x00C6},
+ {0x01E4,0x01E5,0x01E4}, {0x01E4,0x01E5,0x01E4},
+ {0x01E6,0x01E7,0x0047}, {0x01E6,0x01E7,0x0047},
+ {0x01E8,0x01E9,0x004B}, {0x01E8,0x01E9,0x004B},
+ {0x01EA,0x01EB,0x004F}, {0x01EA,0x01EB,0x004F},
+ {0x01EC,0x01ED,0x004F}, {0x01EC,0x01ED,0x004F},
+ {0x01EE,0x01EF,0x01B7}, {0x01EE,0x01EF,0x01B7},
+ {0x01F0,0x01F0,0x004A}, {0x01F1,0x01F3,0x01F1},
+ {0x01F1,0x01F3,0x01F1}, {0x01F1,0x01F3,0x01F1},
+ {0x01F4,0x01F5,0x0047}, {0x01F4,0x01F5,0x0047},
+ {0x01F6,0x0195,0x01F6}, {0x01F7,0x01BF,0x01F7},
+ {0x01F8,0x01F9,0x004E}, {0x01F8,0x01F9,0x004E},
+ {0x01FA,0x01FB,0x0041}, {0x01FA,0x01FB,0x0041},
+ {0x01FC,0x01FD,0x00C6}, {0x01FC,0x01FD,0x00C6},
+ {0x01FE,0x01FF,0x00D8}, {0x01FE,0x01FF,0x00D8}
+};
+
+static MY_UNICASE_INFO plane02[]={
+ {0x0200,0x0201,0x0041}, {0x0200,0x0201,0x0041},
+ {0x0202,0x0203,0x0041}, {0x0202,0x0203,0x0041},
+ {0x0204,0x0205,0x0045}, {0x0204,0x0205,0x0045},
+ {0x0206,0x0207,0x0045}, {0x0206,0x0207,0x0045},
+ {0x0208,0x0209,0x0049}, {0x0208,0x0209,0x0049},
+ {0x020A,0x020B,0x0049}, {0x020A,0x020B,0x0049},
+ {0x020C,0x020D,0x004F}, {0x020C,0x020D,0x004F},
+ {0x020E,0x020F,0x004F}, {0x020E,0x020F,0x004F},
+ {0x0210,0x0211,0x0052}, {0x0210,0x0211,0x0052},
+ {0x0212,0x0213,0x0052}, {0x0212,0x0213,0x0052},
+ {0x0214,0x0215,0x0055}, {0x0214,0x0215,0x0055},
+ {0x0216,0x0217,0x0055}, {0x0216,0x0217,0x0055},
+ {0x0218,0x0219,0x0053}, {0x0218,0x0219,0x0053},
+ {0x021A,0x021B,0x0054}, {0x021A,0x021B,0x0054},
+ {0x021C,0x021D,0x021C}, {0x021C,0x021D,0x021C},
+ {0x021E,0x021F,0x0048}, {0x021E,0x021F,0x0048},
+ {0x0220,0x0220,0x0220}, {0x0221,0x0221,0x0221},
+ {0x0222,0x0223,0x0222}, {0x0222,0x0223,0x0222},
+ {0x0224,0x0225,0x0224}, {0x0224,0x0225,0x0224},
+ {0x0226,0x0227,0x0041}, {0x0226,0x0227,0x0041},
+ {0x0228,0x0229,0x0045}, {0x0228,0x0229,0x0045},
+ {0x022A,0x022B,0x004F}, {0x022A,0x022B,0x004F},
+ {0x022C,0x022D,0x004F}, {0x022C,0x022D,0x004F},
+ {0x022E,0x022F,0x004F}, {0x022E,0x022F,0x004F},
+ {0x0230,0x0231,0x004F}, {0x0230,0x0231,0x004F},
+ {0x0232,0x0233,0x0059}, {0x0232,0x0233,0x0059},
+ {0x0234,0x0234,0x0234}, {0x0235,0x0235,0x0235},
+ {0x0236,0x0236,0x0236}, {0x0237,0x0237,0x0237},
+ {0x0238,0x0238,0x0238}, {0x0239,0x0239,0x0239},
+ {0x023A,0x023A,0x023A}, {0x023B,0x023B,0x023B},
+ {0x023C,0x023C,0x023C}, {0x023D,0x023D,0x023D},
+ {0x023E,0x023E,0x023E}, {0x023F,0x023F,0x023F},
+ {0x0240,0x0240,0x0240}, {0x0241,0x0241,0x0241},
+ {0x0242,0x0242,0x0242}, {0x0243,0x0243,0x0243},
+ {0x0244,0x0244,0x0244}, {0x0245,0x0245,0x0245},
+ {0x0246,0x0246,0x0246}, {0x0247,0x0247,0x0247},
+ {0x0248,0x0248,0x0248}, {0x0249,0x0249,0x0249},
+ {0x024A,0x024A,0x024A}, {0x024B,0x024B,0x024B},
+ {0x024C,0x024C,0x024C}, {0x024D,0x024D,0x024D},
+ {0x024E,0x024E,0x024E}, {0x024F,0x024F,0x024F},
+ {0x0250,0x0250,0x0250}, {0x0251,0x0251,0x0251},
+ {0x0252,0x0252,0x0252}, {0x0181,0x0253,0x0181},
+ {0x0186,0x0254,0x0186}, {0x0255,0x0255,0x0255},
+ {0x0189,0x0256,0x0189}, {0x018A,0x0257,0x018A},
+ {0x0258,0x0258,0x0258}, {0x018F,0x0259,0x018F},
+ {0x025A,0x025A,0x025A}, {0x0190,0x025B,0x0190},
+ {0x025C,0x025C,0x025C}, {0x025D,0x025D,0x025D},
+ {0x025E,0x025E,0x025E}, {0x025F,0x025F,0x025F},
+ {0x0193,0x0260,0x0193}, {0x0261,0x0261,0x0261},
+ {0x0262,0x0262,0x0262}, {0x0194,0x0263,0x0194},
+ {0x0264,0x0264,0x0264}, {0x0265,0x0265,0x0265},
+ {0x0266,0x0266,0x0266}, {0x0267,0x0267,0x0267},
+ {0x0197,0x0268,0x0197}, {0x0196,0x0269,0x0196},
+ {0x026A,0x026A,0x026A}, {0x026B,0x026B,0x026B},
+ {0x026C,0x026C,0x026C}, {0x026D,0x026D,0x026D},
+ {0x026E,0x026E,0x026E}, {0x019C,0x026F,0x019C},
+ {0x0270,0x0270,0x0270}, {0x0271,0x0271,0x0271},
+ {0x019D,0x0272,0x019D}, {0x0273,0x0273,0x0273},
+ {0x0274,0x0274,0x0274}, {0x019F,0x0275,0x019F},
+ {0x0276,0x0276,0x0276}, {0x0277,0x0277,0x0277},
+ {0x0278,0x0278,0x0278}, {0x0279,0x0279,0x0279},
+ {0x027A,0x027A,0x027A}, {0x027B,0x027B,0x027B},
+ {0x027C,0x027C,0x027C}, {0x027D,0x027D,0x027D},
+ {0x027E,0x027E,0x027E}, {0x027F,0x027F,0x027F},
+ {0x01A6,0x0280,0x01A6}, {0x0281,0x0281,0x0281},
+ {0x0282,0x0282,0x0282}, {0x01A9,0x0283,0x01A9},
+ {0x0284,0x0284,0x0284}, {0x0285,0x0285,0x0285},
+ {0x0286,0x0286,0x0286}, {0x0287,0x0287,0x0287},
+ {0x01AE,0x0288,0x01AE}, {0x0289,0x0289,0x0289},
+ {0x01B1,0x028A,0x01B1}, {0x01B2,0x028B,0x01B2},
+ {0x028C,0x028C,0x028C}, {0x028D,0x028D,0x028D},
+ {0x028E,0x028E,0x028E}, {0x028F,0x028F,0x028F},
+ {0x0290,0x0290,0x0290}, {0x0291,0x0291,0x0291},
+ {0x01B7,0x0292,0x01B7}, {0x0293,0x0293,0x0293},
+ {0x0294,0x0294,0x0294}, {0x0295,0x0295,0x0295},
+ {0x0296,0x0296,0x0296}, {0x0297,0x0297,0x0297},
+ {0x0298,0x0298,0x0298}, {0x0299,0x0299,0x0299},
+ {0x029A,0x029A,0x029A}, {0x029B,0x029B,0x029B},
+ {0x029C,0x029C,0x029C}, {0x029D,0x029D,0x029D},
+ {0x029E,0x029E,0x029E}, {0x029F,0x029F,0x029F},
+ {0x02A0,0x02A0,0x02A0}, {0x02A1,0x02A1,0x02A1},
+ {0x02A2,0x02A2,0x02A2}, {0x02A3,0x02A3,0x02A3},
+ {0x02A4,0x02A4,0x02A4}, {0x02A5,0x02A5,0x02A5},
+ {0x02A6,0x02A6,0x02A6}, {0x02A7,0x02A7,0x02A7},
+ {0x02A8,0x02A8,0x02A8}, {0x02A9,0x02A9,0x02A9},
+ {0x02AA,0x02AA,0x02AA}, {0x02AB,0x02AB,0x02AB},
+ {0x02AC,0x02AC,0x02AC}, {0x02AD,0x02AD,0x02AD},
+ {0x02AE,0x02AE,0x02AE}, {0x02AF,0x02AF,0x02AF},
+ {0x02B0,0x02B0,0x02B0}, {0x02B1,0x02B1,0x02B1},
+ {0x02B2,0x02B2,0x02B2}, {0x02B3,0x02B3,0x02B3},
+ {0x02B4,0x02B4,0x02B4}, {0x02B5,0x02B5,0x02B5},
+ {0x02B6,0x02B6,0x02B6}, {0x02B7,0x02B7,0x02B7},
+ {0x02B8,0x02B8,0x02B8}, {0x02B9,0x02B9,0x02B9},
+ {0x02BA,0x02BA,0x02BA}, {0x02BB,0x02BB,0x02BB},
+ {0x02BC,0x02BC,0x02BC}, {0x02BD,0x02BD,0x02BD},
+ {0x02BE,0x02BE,0x02BE}, {0x02BF,0x02BF,0x02BF},
+ {0x02C0,0x02C0,0x02C0}, {0x02C1,0x02C1,0x02C1},
+ {0x02C2,0x02C2,0x02C2}, {0x02C3,0x02C3,0x02C3},
+ {0x02C4,0x02C4,0x02C4}, {0x02C5,0x02C5,0x02C5},
+ {0x02C6,0x02C6,0x02C6}, {0x02C7,0x02C7,0x02C7},
+ {0x02C8,0x02C8,0x02C8}, {0x02C9,0x02C9,0x02C9},
+ {0x02CA,0x02CA,0x02CA}, {0x02CB,0x02CB,0x02CB},
+ {0x02CC,0x02CC,0x02CC}, {0x02CD,0x02CD,0x02CD},
+ {0x02CE,0x02CE,0x02CE}, {0x02CF,0x02CF,0x02CF},
+ {0x02D0,0x02D0,0x02D0}, {0x02D1,0x02D1,0x02D1},
+ {0x02D2,0x02D2,0x02D2}, {0x02D3,0x02D3,0x02D3},
+ {0x02D4,0x02D4,0x02D4}, {0x02D5,0x02D5,0x02D5},
+ {0x02D6,0x02D6,0x02D6}, {0x02D7,0x02D7,0x02D7},
+ {0x02D8,0x02D8,0x02D8}, {0x02D9,0x02D9,0x02D9},
+ {0x02DA,0x02DA,0x02DA}, {0x02DB,0x02DB,0x02DB},
+ {0x02DC,0x02DC,0x02DC}, {0x02DD,0x02DD,0x02DD},
+ {0x02DE,0x02DE,0x02DE}, {0x02DF,0x02DF,0x02DF},
+ {0x02E0,0x02E0,0x02E0}, {0x02E1,0x02E1,0x02E1},
+ {0x02E2,0x02E2,0x02E2}, {0x02E3,0x02E3,0x02E3},
+ {0x02E4,0x02E4,0x02E4}, {0x02E5,0x02E5,0x02E5},
+ {0x02E6,0x02E6,0x02E6}, {0x02E7,0x02E7,0x02E7},
+ {0x02E8,0x02E8,0x02E8}, {0x02E9,0x02E9,0x02E9},
+ {0x02EA,0x02EA,0x02EA}, {0x02EB,0x02EB,0x02EB},
+ {0x02EC,0x02EC,0x02EC}, {0x02ED,0x02ED,0x02ED},
+ {0x02EE,0x02EE,0x02EE}, {0x02EF,0x02EF,0x02EF},
+ {0x02F0,0x02F0,0x02F0}, {0x02F1,0x02F1,0x02F1},
+ {0x02F2,0x02F2,0x02F2}, {0x02F3,0x02F3,0x02F3},
+ {0x02F4,0x02F4,0x02F4}, {0x02F5,0x02F5,0x02F5},
+ {0x02F6,0x02F6,0x02F6}, {0x02F7,0x02F7,0x02F7},
+ {0x02F8,0x02F8,0x02F8}, {0x02F9,0x02F9,0x02F9},
+ {0x02FA,0x02FA,0x02FA}, {0x02FB,0x02FB,0x02FB},
+ {0x02FC,0x02FC,0x02FC}, {0x02FD,0x02FD,0x02FD},
+ {0x02FE,0x02FE,0x02FE}, {0x02FF,0x02FF,0x02FF}
+};
+
+static MY_UNICASE_INFO plane03[]={
+ {0x0300,0x0300,0x0300}, {0x0301,0x0301,0x0301},
+ {0x0302,0x0302,0x0302}, {0x0303,0x0303,0x0303},
+ {0x0304,0x0304,0x0304}, {0x0305,0x0305,0x0305},
+ {0x0306,0x0306,0x0306}, {0x0307,0x0307,0x0307},
+ {0x0308,0x0308,0x0308}, {0x0309,0x0309,0x0309},
+ {0x030A,0x030A,0x030A}, {0x030B,0x030B,0x030B},
+ {0x030C,0x030C,0x030C}, {0x030D,0x030D,0x030D},
+ {0x030E,0x030E,0x030E}, {0x030F,0x030F,0x030F},
+ {0x0310,0x0310,0x0310}, {0x0311,0x0311,0x0311},
+ {0x0312,0x0312,0x0312}, {0x0313,0x0313,0x0313},
+ {0x0314,0x0314,0x0314}, {0x0315,0x0315,0x0315},
+ {0x0316,0x0316,0x0316}, {0x0317,0x0317,0x0317},
+ {0x0318,0x0318,0x0318}, {0x0319,0x0319,0x0319},
+ {0x031A,0x031A,0x031A}, {0x031B,0x031B,0x031B},
+ {0x031C,0x031C,0x031C}, {0x031D,0x031D,0x031D},
+ {0x031E,0x031E,0x031E}, {0x031F,0x031F,0x031F},
+ {0x0320,0x0320,0x0320}, {0x0321,0x0321,0x0321},
+ {0x0322,0x0322,0x0322}, {0x0323,0x0323,0x0323},
+ {0x0324,0x0324,0x0324}, {0x0325,0x0325,0x0325},
+ {0x0326,0x0326,0x0326}, {0x0327,0x0327,0x0327},
+ {0x0328,0x0328,0x0328}, {0x0329,0x0329,0x0329},
+ {0x032A,0x032A,0x032A}, {0x032B,0x032B,0x032B},
+ {0x032C,0x032C,0x032C}, {0x032D,0x032D,0x032D},
+ {0x032E,0x032E,0x032E}, {0x032F,0x032F,0x032F},
+ {0x0330,0x0330,0x0330}, {0x0331,0x0331,0x0331},
+ {0x0332,0x0332,0x0332}, {0x0333,0x0333,0x0333},
+ {0x0334,0x0334,0x0334}, {0x0335,0x0335,0x0335},
+ {0x0336,0x0336,0x0336}, {0x0337,0x0337,0x0337},
+ {0x0338,0x0338,0x0338}, {0x0339,0x0339,0x0339},
+ {0x033A,0x033A,0x033A}, {0x033B,0x033B,0x033B},
+ {0x033C,0x033C,0x033C}, {0x033D,0x033D,0x033D},
+ {0x033E,0x033E,0x033E}, {0x033F,0x033F,0x033F},
+ {0x0340,0x0340,0x0340}, {0x0341,0x0341,0x0341},
+ {0x0342,0x0342,0x0342}, {0x0343,0x0343,0x0343},
+ {0x0344,0x0344,0x0344}, {0x0399,0x0345,0x0399},
+ {0x0346,0x0346,0x0346}, {0x0347,0x0347,0x0347},
+ {0x0348,0x0348,0x0348}, {0x0349,0x0349,0x0349},
+ {0x034A,0x034A,0x034A}, {0x034B,0x034B,0x034B},
+ {0x034C,0x034C,0x034C}, {0x034D,0x034D,0x034D},
+ {0x034E,0x034E,0x034E}, {0x034F,0x034F,0x034F},
+ {0x0350,0x0350,0x0350}, {0x0351,0x0351,0x0351},
+ {0x0352,0x0352,0x0352}, {0x0353,0x0353,0x0353},
+ {0x0354,0x0354,0x0354}, {0x0355,0x0355,0x0355},
+ {0x0356,0x0356,0x0356}, {0x0357,0x0357,0x0357},
+ {0x0358,0x0358,0x0358}, {0x0359,0x0359,0x0359},
+ {0x035A,0x035A,0x035A}, {0x035B,0x035B,0x035B},
+ {0x035C,0x035C,0x035C}, {0x035D,0x035D,0x035D},
+ {0x035E,0x035E,0x035E}, {0x035F,0x035F,0x035F},
+ {0x0360,0x0360,0x0360}, {0x0361,0x0361,0x0361},
+ {0x0362,0x0362,0x0362}, {0x0363,0x0363,0x0363},
+ {0x0364,0x0364,0x0364}, {0x0365,0x0365,0x0365},
+ {0x0366,0x0366,0x0366}, {0x0367,0x0367,0x0367},
+ {0x0368,0x0368,0x0368}, {0x0369,0x0369,0x0369},
+ {0x036A,0x036A,0x036A}, {0x036B,0x036B,0x036B},
+ {0x036C,0x036C,0x036C}, {0x036D,0x036D,0x036D},
+ {0x036E,0x036E,0x036E}, {0x036F,0x036F,0x036F},
+ {0x0370,0x0370,0x0370}, {0x0371,0x0371,0x0371},
+ {0x0372,0x0372,0x0372}, {0x0373,0x0373,0x0373},
+ {0x0374,0x0374,0x0374}, {0x0375,0x0375,0x0375},
+ {0x0376,0x0376,0x0376}, {0x0377,0x0377,0x0377},
+ {0x0378,0x0378,0x0378}, {0x0379,0x0379,0x0379},
+ {0x037A,0x037A,0x037A}, {0x037B,0x037B,0x037B},
+ {0x037C,0x037C,0x037C}, {0x037D,0x037D,0x037D},
+ {0x037E,0x037E,0x037E}, {0x037F,0x037F,0x037F},
+ {0x0380,0x0380,0x0380}, {0x0381,0x0381,0x0381},
+ {0x0382,0x0382,0x0382}, {0x0383,0x0383,0x0383},
+ {0x0384,0x0384,0x0384}, {0x0385,0x0385,0x0385},
+ {0x0386,0x03AC,0x0391}, {0x0387,0x0387,0x0387},
+ {0x0388,0x03AD,0x0395}, {0x0389,0x03AE,0x0397},
+ {0x038A,0x03AF,0x0399}, {0x038B,0x038B,0x038B},
+ {0x038C,0x03CC,0x039F}, {0x038D,0x038D,0x038D},
+ {0x038E,0x03CD,0x03A5}, {0x038F,0x03CE,0x03A9},
+ {0x0390,0x0390,0x0399}, {0x0391,0x03B1,0x0391},
+ {0x0392,0x03B2,0x0392}, {0x0393,0x03B3,0x0393},
+ {0x0394,0x03B4,0x0394}, {0x0395,0x03B5,0x0395},
+ {0x0396,0x03B6,0x0396}, {0x0397,0x03B7,0x0397},
+ {0x0398,0x03B8,0x0398}, {0x0399,0x03B9,0x0399},
+ {0x039A,0x03BA,0x039A}, {0x039B,0x03BB,0x039B},
+ {0x039C,0x03BC,0x039C}, {0x039D,0x03BD,0x039D},
+ {0x039E,0x03BE,0x039E}, {0x039F,0x03BF,0x039F},
+ {0x03A0,0x03C0,0x03A0}, {0x03A1,0x03C1,0x03A1},
+ {0x03A2,0x03A2,0x03A2}, {0x03A3,0x03C3,0x03A3},
+ {0x03A4,0x03C4,0x03A4}, {0x03A5,0x03C5,0x03A5},
+ {0x03A6,0x03C6,0x03A6}, {0x03A7,0x03C7,0x03A7},
+ {0x03A8,0x03C8,0x03A8}, {0x03A9,0x03C9,0x03A9},
+ {0x03AA,0x03CA,0x0399}, {0x03AB,0x03CB,0x03A5},
+ {0x0386,0x03AC,0x0391}, {0x0388,0x03AD,0x0395},
+ {0x0389,0x03AE,0x0397}, {0x038A,0x03AF,0x0399},
+ {0x03B0,0x03B0,0x03A5}, {0x0391,0x03B1,0x0391},
+ {0x0392,0x03B2,0x0392}, {0x0393,0x03B3,0x0393},
+ {0x0394,0x03B4,0x0394}, {0x0395,0x03B5,0x0395},
+ {0x0396,0x03B6,0x0396}, {0x0397,0x03B7,0x0397},
+ {0x0398,0x03B8,0x0398}, {0x0399,0x03B9,0x0399},
+ {0x039A,0x03BA,0x039A}, {0x039B,0x03BB,0x039B},
+ {0x039C,0x03BC,0x039C}, {0x039D,0x03BD,0x039D},
+ {0x039E,0x03BE,0x039E}, {0x039F,0x03BF,0x039F},
+ {0x03A0,0x03C0,0x03A0}, {0x03A1,0x03C1,0x03A1},
+ {0x03A3,0x03C2,0x03A3}, {0x03A3,0x03C3,0x03A3},
+ {0x03A4,0x03C4,0x03A4}, {0x03A5,0x03C5,0x03A5},
+ {0x03A6,0x03C6,0x03A6}, {0x03A7,0x03C7,0x03A7},
+ {0x03A8,0x03C8,0x03A8}, {0x03A9,0x03C9,0x03A9},
+ {0x03AA,0x03CA,0x0399}, {0x03AB,0x03CB,0x03A5},
+ {0x038C,0x03CC,0x039F}, {0x038E,0x03CD,0x03A5},
+ {0x038F,0x03CE,0x03A9}, {0x03CF,0x03CF,0x03CF},
+ {0x0392,0x03D0,0x0392}, {0x0398,0x03D1,0x0398},
+ {0x03D2,0x03D2,0x03D2}, {0x03D3,0x03D3,0x03D2},
+ {0x03D4,0x03D4,0x03D2}, {0x03A6,0x03D5,0x03A6},
+ {0x03A0,0x03D6,0x03A0}, {0x03D7,0x03D7,0x03D7},
+ {0x03D8,0x03D8,0x03D8}, {0x03D9,0x03D9,0x03D9},
+ {0x03DA,0x03DB,0x03DA}, {0x03DA,0x03DB,0x03DA},
+ {0x03DC,0x03DD,0x03DC}, {0x03DC,0x03DD,0x03DC},
+ {0x03DE,0x03DF,0x03DE}, {0x03DE,0x03DF,0x03DE},
+ {0x03E0,0x03E1,0x03E0}, {0x03E0,0x03E1,0x03E0},
+ {0x03E2,0x03E3,0x03E2}, {0x03E2,0x03E3,0x03E2},
+ {0x03E4,0x03E5,0x03E4}, {0x03E4,0x03E5,0x03E4},
+ {0x03E6,0x03E7,0x03E6}, {0x03E6,0x03E7,0x03E6},
+ {0x03E8,0x03E9,0x03E8}, {0x03E8,0x03E9,0x03E8},
+ {0x03EA,0x03EB,0x03EA}, {0x03EA,0x03EB,0x03EA},
+ {0x03EC,0x03ED,0x03EC}, {0x03EC,0x03ED,0x03EC},
+ {0x03EE,0x03EF,0x03EE}, {0x03EE,0x03EF,0x03EE},
+ {0x039A,0x03F0,0x039A}, {0x03A1,0x03F1,0x03A1},
+ {0x03A3,0x03F2,0x03A3}, {0x03F3,0x03F3,0x03F3},
+ {0x03F4,0x03F4,0x03F4}, {0x03F5,0x03F5,0x03F5},
+ {0x03F6,0x03F6,0x03F6}, {0x03F7,0x03F7,0x03F7},
+ {0x03F8,0x03F8,0x03F8}, {0x03F9,0x03F9,0x03F9},
+ {0x03FA,0x03FA,0x03FA}, {0x03FB,0x03FB,0x03FB},
+ {0x03FC,0x03FC,0x03FC}, {0x03FD,0x03FD,0x03FD},
+ {0x03FE,0x03FE,0x03FE}, {0x03FF,0x03FF,0x03FF}
+};
+
+static MY_UNICASE_INFO plane04[]={
+ {0x0400,0x0450,0x0415}, {0x0401,0x0451,0x0415},
+ {0x0402,0x0452,0x0402}, {0x0403,0x0453,0x0413},
+ {0x0404,0x0454,0x0404}, {0x0405,0x0455,0x0405},
+ {0x0406,0x0456,0x0406}, {0x0407,0x0457,0x0406},
+ {0x0408,0x0458,0x0408}, {0x0409,0x0459,0x0409},
+ {0x040A,0x045A,0x040A}, {0x040B,0x045B,0x040B},
+ {0x040C,0x045C,0x041A}, {0x040D,0x045D,0x0418},
+ {0x040E,0x045E,0x0423}, {0x040F,0x045F,0x040F},
+ {0x0410,0x0430,0x0410}, {0x0411,0x0431,0x0411},
+ {0x0412,0x0432,0x0412}, {0x0413,0x0433,0x0413},
+ {0x0414,0x0434,0x0414}, {0x0415,0x0435,0x0415},
+ {0x0416,0x0436,0x0416}, {0x0417,0x0437,0x0417},
+ {0x0418,0x0438,0x0418}, {0x0419,0x0439,0x0418},
+ {0x041A,0x043A,0x041A}, {0x041B,0x043B,0x041B},
+ {0x041C,0x043C,0x041C}, {0x041D,0x043D,0x041D},
+ {0x041E,0x043E,0x041E}, {0x041F,0x043F,0x041F},
+ {0x0420,0x0440,0x0420}, {0x0421,0x0441,0x0421},
+ {0x0422,0x0442,0x0422}, {0x0423,0x0443,0x0423},
+ {0x0424,0x0444,0x0424}, {0x0425,0x0445,0x0425},
+ {0x0426,0x0446,0x0426}, {0x0427,0x0447,0x0427},
+ {0x0428,0x0448,0x0428}, {0x0429,0x0449,0x0429},
+ {0x042A,0x044A,0x042A}, {0x042B,0x044B,0x042B},
+ {0x042C,0x044C,0x042C}, {0x042D,0x044D,0x042D},
+ {0x042E,0x044E,0x042E}, {0x042F,0x044F,0x042F},
+ {0x0410,0x0430,0x0410}, {0x0411,0x0431,0x0411},
+ {0x0412,0x0432,0x0412}, {0x0413,0x0433,0x0413},
+ {0x0414,0x0434,0x0414}, {0x0415,0x0435,0x0415},
+ {0x0416,0x0436,0x0416}, {0x0417,0x0437,0x0417},
+ {0x0418,0x0438,0x0418}, {0x0419,0x0439,0x0418},
+ {0x041A,0x043A,0x041A}, {0x041B,0x043B,0x041B},
+ {0x041C,0x043C,0x041C}, {0x041D,0x043D,0x041D},
+ {0x041E,0x043E,0x041E}, {0x041F,0x043F,0x041F},
+ {0x0420,0x0440,0x0420}, {0x0421,0x0441,0x0421},
+ {0x0422,0x0442,0x0422}, {0x0423,0x0443,0x0423},
+ {0x0424,0x0444,0x0424}, {0x0425,0x0445,0x0425},
+ {0x0426,0x0446,0x0426}, {0x0427,0x0447,0x0427},
+ {0x0428,0x0448,0x0428}, {0x0429,0x0449,0x0429},
+ {0x042A,0x044A,0x042A}, {0x042B,0x044B,0x042B},
+ {0x042C,0x044C,0x042C}, {0x042D,0x044D,0x042D},
+ {0x042E,0x044E,0x042E}, {0x042F,0x044F,0x042F},
+ {0x0400,0x0450,0x0415}, {0x0401,0x0451,0x0415},
+ {0x0402,0x0452,0x0402}, {0x0403,0x0453,0x0413},
+ {0x0404,0x0454,0x0404}, {0x0405,0x0455,0x0405},
+ {0x0406,0x0456,0x0406}, {0x0407,0x0457,0x0406},
+ {0x0408,0x0458,0x0408}, {0x0409,0x0459,0x0409},
+ {0x040A,0x045A,0x040A}, {0x040B,0x045B,0x040B},
+ {0x040C,0x045C,0x041A}, {0x040D,0x045D,0x0418},
+ {0x040E,0x045E,0x0423}, {0x040F,0x045F,0x040F},
+ {0x0460,0x0461,0x0460}, {0x0460,0x0461,0x0460},
+ {0x0462,0x0463,0x0462}, {0x0462,0x0463,0x0462},
+ {0x0464,0x0465,0x0464}, {0x0464,0x0465,0x0464},
+ {0x0466,0x0467,0x0466}, {0x0466,0x0467,0x0466},
+ {0x0468,0x0469,0x0468}, {0x0468,0x0469,0x0468},
+ {0x046A,0x046B,0x046A}, {0x046A,0x046B,0x046A},
+ {0x046C,0x046D,0x046C}, {0x046C,0x046D,0x046C},
+ {0x046E,0x046F,0x046E}, {0x046E,0x046F,0x046E},
+ {0x0470,0x0471,0x0470}, {0x0470,0x0471,0x0470},
+ {0x0472,0x0473,0x0472}, {0x0472,0x0473,0x0472},
+ {0x0474,0x0475,0x0474}, {0x0474,0x0475,0x0474},
+ {0x0476,0x0477,0x0474}, {0x0476,0x0477,0x0474},
+ {0x0478,0x0479,0x0478}, {0x0478,0x0479,0x0478},
+ {0x047A,0x047B,0x047A}, {0x047A,0x047B,0x047A},
+ {0x047C,0x047D,0x047C}, {0x047C,0x047D,0x047C},
+ {0x047E,0x047F,0x047E}, {0x047E,0x047F,0x047E},
+ {0x0480,0x0481,0x0480}, {0x0480,0x0481,0x0480},
+ {0x0482,0x0482,0x0482}, {0x0483,0x0483,0x0483},
+ {0x0484,0x0484,0x0484}, {0x0485,0x0485,0x0485},
+ {0x0486,0x0486,0x0486}, {0x0487,0x0487,0x0487},
+ {0x0488,0x0488,0x0488}, {0x0489,0x0489,0x0489},
+ {0x048A,0x048A,0x048A}, {0x048B,0x048B,0x048B},
+ {0x048C,0x048D,0x048C}, {0x048C,0x048D,0x048C},
+ {0x048E,0x048F,0x048E}, {0x048E,0x048F,0x048E},
+ {0x0490,0x0491,0x0490}, {0x0490,0x0491,0x0490},
+ {0x0492,0x0493,0x0492}, {0x0492,0x0493,0x0492},
+ {0x0494,0x0495,0x0494}, {0x0494,0x0495,0x0494},
+ {0x0496,0x0497,0x0496}, {0x0496,0x0497,0x0496},
+ {0x0498,0x0499,0x0498}, {0x0498,0x0499,0x0498},
+ {0x049A,0x049B,0x049A}, {0x049A,0x049B,0x049A},
+ {0x049C,0x049D,0x049C}, {0x049C,0x049D,0x049C},
+ {0x049E,0x049F,0x049E}, {0x049E,0x049F,0x049E},
+ {0x04A0,0x04A1,0x04A0}, {0x04A0,0x04A1,0x04A0},
+ {0x04A2,0x04A3,0x04A2}, {0x04A2,0x04A3,0x04A2},
+ {0x04A4,0x04A5,0x04A4}, {0x04A4,0x04A5,0x04A4},
+ {0x04A6,0x04A7,0x04A6}, {0x04A6,0x04A7,0x04A6},
+ {0x04A8,0x04A9,0x04A8}, {0x04A8,0x04A9,0x04A8},
+ {0x04AA,0x04AB,0x04AA}, {0x04AA,0x04AB,0x04AA},
+ {0x04AC,0x04AD,0x04AC}, {0x04AC,0x04AD,0x04AC},
+ {0x04AE,0x04AF,0x04AE}, {0x04AE,0x04AF,0x04AE},
+ {0x04B0,0x04B1,0x04B0}, {0x04B0,0x04B1,0x04B0},
+ {0x04B2,0x04B3,0x04B2}, {0x04B2,0x04B3,0x04B2},
+ {0x04B4,0x04B5,0x04B4}, {0x04B4,0x04B5,0x04B4},
+ {0x04B6,0x04B7,0x04B6}, {0x04B6,0x04B7,0x04B6},
+ {0x04B8,0x04B9,0x04B8}, {0x04B8,0x04B9,0x04B8},
+ {0x04BA,0x04BB,0x04BA}, {0x04BA,0x04BB,0x04BA},
+ {0x04BC,0x04BD,0x04BC}, {0x04BC,0x04BD,0x04BC},
+ {0x04BE,0x04BF,0x04BE}, {0x04BE,0x04BF,0x04BE},
+ {0x04C0,0x04C0,0x04C0}, {0x04C1,0x04C2,0x0416},
+ {0x04C1,0x04C2,0x0416}, {0x04C3,0x04C4,0x04C3},
+ {0x04C3,0x04C4,0x04C3}, {0x04C5,0x04C5,0x04C5},
+ {0x04C6,0x04C6,0x04C6}, {0x04C7,0x04C8,0x04C7},
+ {0x04C7,0x04C8,0x04C7}, {0x04C9,0x04C9,0x04C9},
+ {0x04CA,0x04CA,0x04CA}, {0x04CB,0x04CC,0x04CB},
+ {0x04CB,0x04CC,0x04CB}, {0x04CD,0x04CD,0x04CD},
+ {0x04CE,0x04CE,0x04CE}, {0x04CF,0x04CF,0x04CF},
+ {0x04D0,0x04D1,0x0410}, {0x04D0,0x04D1,0x0410},
+ {0x04D2,0x04D3,0x0410}, {0x04D2,0x04D3,0x0410},
+ {0x04D4,0x04D5,0x04D4}, {0x04D4,0x04D5,0x04D4},
+ {0x04D6,0x04D7,0x0415}, {0x04D6,0x04D7,0x0415},
+ {0x04D8,0x04D9,0x04D8}, {0x04D8,0x04D9,0x04D8},
+ {0x04DA,0x04DB,0x04D8}, {0x04DA,0x04DB,0x04D8},
+ {0x04DC,0x04DD,0x0416}, {0x04DC,0x04DD,0x0416},
+ {0x04DE,0x04DF,0x0417}, {0x04DE,0x04DF,0x0417},
+ {0x04E0,0x04E1,0x04E0}, {0x04E0,0x04E1,0x04E0},
+ {0x04E2,0x04E3,0x0418}, {0x04E2,0x04E3,0x0418},
+ {0x04E4,0x04E5,0x0418}, {0x04E4,0x04E5,0x0418},
+ {0x04E6,0x04E7,0x041E}, {0x04E6,0x04E7,0x041E},
+ {0x04E8,0x04E9,0x04E8}, {0x04E8,0x04E9,0x04E8},
+ {0x04EA,0x04EB,0x04E8}, {0x04EA,0x04EB,0x04E8},
+ {0x04EC,0x04ED,0x042D}, {0x04EC,0x04ED,0x042D},
+ {0x04EE,0x04EF,0x0423}, {0x04EE,0x04EF,0x0423},
+ {0x04F0,0x04F1,0x0423}, {0x04F0,0x04F1,0x0423},
+ {0x04F2,0x04F3,0x0423}, {0x04F2,0x04F3,0x0423},
+ {0x04F4,0x04F5,0x0427}, {0x04F4,0x04F5,0x0427},
+ {0x04F6,0x04F6,0x04F6}, {0x04F7,0x04F7,0x04F7},
+ {0x04F8,0x04F9,0x042B}, {0x04F8,0x04F9,0x042B},
+ {0x04FA,0x04FA,0x04FA}, {0x04FB,0x04FB,0x04FB},
+ {0x04FC,0x04FC,0x04FC}, {0x04FD,0x04FD,0x04FD},
+ {0x04FE,0x04FE,0x04FE}, {0x04FF,0x04FF,0x04FF}
+};
+
+static MY_UNICASE_INFO plane05[]={
+ {0x0500,0x0500,0x0500}, {0x0501,0x0501,0x0501},
+ {0x0502,0x0502,0x0502}, {0x0503,0x0503,0x0503},
+ {0x0504,0x0504,0x0504}, {0x0505,0x0505,0x0505},
+ {0x0506,0x0506,0x0506}, {0x0507,0x0507,0x0507},
+ {0x0508,0x0508,0x0508}, {0x0509,0x0509,0x0509},
+ {0x050A,0x050A,0x050A}, {0x050B,0x050B,0x050B},
+ {0x050C,0x050C,0x050C}, {0x050D,0x050D,0x050D},
+ {0x050E,0x050E,0x050E}, {0x050F,0x050F,0x050F},
+ {0x0510,0x0510,0x0510}, {0x0511,0x0511,0x0511},
+ {0x0512,0x0512,0x0512}, {0x0513,0x0513,0x0513},
+ {0x0514,0x0514,0x0514}, {0x0515,0x0515,0x0515},
+ {0x0516,0x0516,0x0516}, {0x0517,0x0517,0x0517},
+ {0x0518,0x0518,0x0518}, {0x0519,0x0519,0x0519},
+ {0x051A,0x051A,0x051A}, {0x051B,0x051B,0x051B},
+ {0x051C,0x051C,0x051C}, {0x051D,0x051D,0x051D},
+ {0x051E,0x051E,0x051E}, {0x051F,0x051F,0x051F},
+ {0x0520,0x0520,0x0520}, {0x0521,0x0521,0x0521},
+ {0x0522,0x0522,0x0522}, {0x0523,0x0523,0x0523},
+ {0x0524,0x0524,0x0524}, {0x0525,0x0525,0x0525},
+ {0x0526,0x0526,0x0526}, {0x0527,0x0527,0x0527},
+ {0x0528,0x0528,0x0528}, {0x0529,0x0529,0x0529},
+ {0x052A,0x052A,0x052A}, {0x052B,0x052B,0x052B},
+ {0x052C,0x052C,0x052C}, {0x052D,0x052D,0x052D},
+ {0x052E,0x052E,0x052E}, {0x052F,0x052F,0x052F},
+ {0x0530,0x0530,0x0530}, {0x0531,0x0561,0x0531},
+ {0x0532,0x0562,0x0532}, {0x0533,0x0563,0x0533},
+ {0x0534,0x0564,0x0534}, {0x0535,0x0565,0x0535},
+ {0x0536,0x0566,0x0536}, {0x0537,0x0567,0x0537},
+ {0x0538,0x0568,0x0538}, {0x0539,0x0569,0x0539},
+ {0x053A,0x056A,0x053A}, {0x053B,0x056B,0x053B},
+ {0x053C,0x056C,0x053C}, {0x053D,0x056D,0x053D},
+ {0x053E,0x056E,0x053E}, {0x053F,0x056F,0x053F},
+ {0x0540,0x0570,0x0540}, {0x0541,0x0571,0x0541},
+ {0x0542,0x0572,0x0542}, {0x0543,0x0573,0x0543},
+ {0x0544,0x0574,0x0544}, {0x0545,0x0575,0x0545},
+ {0x0546,0x0576,0x0546}, {0x0547,0x0577,0x0547},
+ {0x0548,0x0578,0x0548}, {0x0549,0x0579,0x0549},
+ {0x054A,0x057A,0x054A}, {0x054B,0x057B,0x054B},
+ {0x054C,0x057C,0x054C}, {0x054D,0x057D,0x054D},
+ {0x054E,0x057E,0x054E}, {0x054F,0x057F,0x054F},
+ {0x0550,0x0580,0x0550}, {0x0551,0x0581,0x0551},
+ {0x0552,0x0582,0x0552}, {0x0553,0x0583,0x0553},
+ {0x0554,0x0584,0x0554}, {0x0555,0x0585,0x0555},
+ {0x0556,0x0586,0x0556}, {0x0557,0x0557,0x0557},
+ {0x0558,0x0558,0x0558}, {0x0559,0x0559,0x0559},
+ {0x055A,0x055A,0x055A}, {0x055B,0x055B,0x055B},
+ {0x055C,0x055C,0x055C}, {0x055D,0x055D,0x055D},
+ {0x055E,0x055E,0x055E}, {0x055F,0x055F,0x055F},
+ {0x0560,0x0560,0x0560}, {0x0531,0x0561,0x0531},
+ {0x0532,0x0562,0x0532}, {0x0533,0x0563,0x0533},
+ {0x0534,0x0564,0x0534}, {0x0535,0x0565,0x0535},
+ {0x0536,0x0566,0x0536}, {0x0537,0x0567,0x0537},
+ {0x0538,0x0568,0x0538}, {0x0539,0x0569,0x0539},
+ {0x053A,0x056A,0x053A}, {0x053B,0x056B,0x053B},
+ {0x053C,0x056C,0x053C}, {0x053D,0x056D,0x053D},
+ {0x053E,0x056E,0x053E}, {0x053F,0x056F,0x053F},
+ {0x0540,0x0570,0x0540}, {0x0541,0x0571,0x0541},
+ {0x0542,0x0572,0x0542}, {0x0543,0x0573,0x0543},
+ {0x0544,0x0574,0x0544}, {0x0545,0x0575,0x0545},
+ {0x0546,0x0576,0x0546}, {0x0547,0x0577,0x0547},
+ {0x0548,0x0578,0x0548}, {0x0549,0x0579,0x0549},
+ {0x054A,0x057A,0x054A}, {0x054B,0x057B,0x054B},
+ {0x054C,0x057C,0x054C}, {0x054D,0x057D,0x054D},
+ {0x054E,0x057E,0x054E}, {0x054F,0x057F,0x054F},
+ {0x0550,0x0580,0x0550}, {0x0551,0x0581,0x0551},
+ {0x0552,0x0582,0x0552}, {0x0553,0x0583,0x0553},
+ {0x0554,0x0584,0x0554}, {0x0555,0x0585,0x0555},
+ {0x0556,0x0586,0x0556}, {0x0587,0x0587,0x0587},
+ {0x0588,0x0588,0x0588}, {0x0589,0x0589,0x0589},
+ {0x058A,0x058A,0x058A}, {0x058B,0x058B,0x058B},
+ {0x058C,0x058C,0x058C}, {0x058D,0x058D,0x058D},
+ {0x058E,0x058E,0x058E}, {0x058F,0x058F,0x058F},
+ {0x0590,0x0590,0x0590}, {0x0591,0x0591,0x0591},
+ {0x0592,0x0592,0x0592}, {0x0593,0x0593,0x0593},
+ {0x0594,0x0594,0x0594}, {0x0595,0x0595,0x0595},
+ {0x0596,0x0596,0x0596}, {0x0597,0x0597,0x0597},
+ {0x0598,0x0598,0x0598}, {0x0599,0x0599,0x0599},
+ {0x059A,0x059A,0x059A}, {0x059B,0x059B,0x059B},
+ {0x059C,0x059C,0x059C}, {0x059D,0x059D,0x059D},
+ {0x059E,0x059E,0x059E}, {0x059F,0x059F,0x059F},
+ {0x05A0,0x05A0,0x05A0}, {0x05A1,0x05A1,0x05A1},
+ {0x05A2,0x05A2,0x05A2}, {0x05A3,0x05A3,0x05A3},
+ {0x05A4,0x05A4,0x05A4}, {0x05A5,0x05A5,0x05A5},
+ {0x05A6,0x05A6,0x05A6}, {0x05A7,0x05A7,0x05A7},
+ {0x05A8,0x05A8,0x05A8}, {0x05A9,0x05A9,0x05A9},
+ {0x05AA,0x05AA,0x05AA}, {0x05AB,0x05AB,0x05AB},
+ {0x05AC,0x05AC,0x05AC}, {0x05AD,0x05AD,0x05AD},
+ {0x05AE,0x05AE,0x05AE}, {0x05AF,0x05AF,0x05AF},
+ {0x05B0,0x05B0,0x05B0}, {0x05B1,0x05B1,0x05B1},
+ {0x05B2,0x05B2,0x05B2}, {0x05B3,0x05B3,0x05B3},
+ {0x05B4,0x05B4,0x05B4}, {0x05B5,0x05B5,0x05B5},
+ {0x05B6,0x05B6,0x05B6}, {0x05B7,0x05B7,0x05B7},
+ {0x05B8,0x05B8,0x05B8}, {0x05B9,0x05B9,0x05B9},
+ {0x05BA,0x05BA,0x05BA}, {0x05BB,0x05BB,0x05BB},
+ {0x05BC,0x05BC,0x05BC}, {0x05BD,0x05BD,0x05BD},
+ {0x05BE,0x05BE,0x05BE}, {0x05BF,0x05BF,0x05BF},
+ {0x05C0,0x05C0,0x05C0}, {0x05C1,0x05C1,0x05C1},
+ {0x05C2,0x05C2,0x05C2}, {0x05C3,0x05C3,0x05C3},
+ {0x05C4,0x05C4,0x05C4}, {0x05C5,0x05C5,0x05C5},
+ {0x05C6,0x05C6,0x05C6}, {0x05C7,0x05C7,0x05C7},
+ {0x05C8,0x05C8,0x05C8}, {0x05C9,0x05C9,0x05C9},
+ {0x05CA,0x05CA,0x05CA}, {0x05CB,0x05CB,0x05CB},
+ {0x05CC,0x05CC,0x05CC}, {0x05CD,0x05CD,0x05CD},
+ {0x05CE,0x05CE,0x05CE}, {0x05CF,0x05CF,0x05CF},
+ {0x05D0,0x05D0,0x05D0}, {0x05D1,0x05D1,0x05D1},
+ {0x05D2,0x05D2,0x05D2}, {0x05D3,0x05D3,0x05D3},
+ {0x05D4,0x05D4,0x05D4}, {0x05D5,0x05D5,0x05D5},
+ {0x05D6,0x05D6,0x05D6}, {0x05D7,0x05D7,0x05D7},
+ {0x05D8,0x05D8,0x05D8}, {0x05D9,0x05D9,0x05D9},
+ {0x05DA,0x05DA,0x05DA}, {0x05DB,0x05DB,0x05DB},
+ {0x05DC,0x05DC,0x05DC}, {0x05DD,0x05DD,0x05DD},
+ {0x05DE,0x05DE,0x05DE}, {0x05DF,0x05DF,0x05DF},
+ {0x05E0,0x05E0,0x05E0}, {0x05E1,0x05E1,0x05E1},
+ {0x05E2,0x05E2,0x05E2}, {0x05E3,0x05E3,0x05E3},
+ {0x05E4,0x05E4,0x05E4}, {0x05E5,0x05E5,0x05E5},
+ {0x05E6,0x05E6,0x05E6}, {0x05E7,0x05E7,0x05E7},
+ {0x05E8,0x05E8,0x05E8}, {0x05E9,0x05E9,0x05E9},
+ {0x05EA,0x05EA,0x05EA}, {0x05EB,0x05EB,0x05EB},
+ {0x05EC,0x05EC,0x05EC}, {0x05ED,0x05ED,0x05ED},
+ {0x05EE,0x05EE,0x05EE}, {0x05EF,0x05EF,0x05EF},
+ {0x05F0,0x05F0,0x05F0}, {0x05F1,0x05F1,0x05F1},
+ {0x05F2,0x05F2,0x05F2}, {0x05F3,0x05F3,0x05F3},
+ {0x05F4,0x05F4,0x05F4}, {0x05F5,0x05F5,0x05F5},
+ {0x05F6,0x05F6,0x05F6}, {0x05F7,0x05F7,0x05F7},
+ {0x05F8,0x05F8,0x05F8}, {0x05F9,0x05F9,0x05F9},
+ {0x05FA,0x05FA,0x05FA}, {0x05FB,0x05FB,0x05FB},
+ {0x05FC,0x05FC,0x05FC}, {0x05FD,0x05FD,0x05FD},
+ {0x05FE,0x05FE,0x05FE}, {0x05FF,0x05FF,0x05FF}
+};
+
+static MY_UNICASE_INFO plane1E[]={
+ {0x1E00,0x1E01,0x0041}, {0x1E00,0x1E01,0x0041},
+ {0x1E02,0x1E03,0x0042}, {0x1E02,0x1E03,0x0042},
+ {0x1E04,0x1E05,0x0042}, {0x1E04,0x1E05,0x0042},
+ {0x1E06,0x1E07,0x0042}, {0x1E06,0x1E07,0x0042},
+ {0x1E08,0x1E09,0x0043}, {0x1E08,0x1E09,0x0043},
+ {0x1E0A,0x1E0B,0x0044}, {0x1E0A,0x1E0B,0x0044},
+ {0x1E0C,0x1E0D,0x0044}, {0x1E0C,0x1E0D,0x0044},
+ {0x1E0E,0x1E0F,0x0044}, {0x1E0E,0x1E0F,0x0044},
+ {0x1E10,0x1E11,0x0044}, {0x1E10,0x1E11,0x0044},
+ {0x1E12,0x1E13,0x0044}, {0x1E12,0x1E13,0x0044},
+ {0x1E14,0x1E15,0x0045}, {0x1E14,0x1E15,0x0045},
+ {0x1E16,0x1E17,0x0045}, {0x1E16,0x1E17,0x0045},
+ {0x1E18,0x1E19,0x0045}, {0x1E18,0x1E19,0x0045},
+ {0x1E1A,0x1E1B,0x0045}, {0x1E1A,0x1E1B,0x0045},
+ {0x1E1C,0x1E1D,0x0045}, {0x1E1C,0x1E1D,0x0045},
+ {0x1E1E,0x1E1F,0x0046}, {0x1E1E,0x1E1F,0x0046},
+ {0x1E20,0x1E21,0x0047}, {0x1E20,0x1E21,0x0047},
+ {0x1E22,0x1E23,0x0048}, {0x1E22,0x1E23,0x0048},
+ {0x1E24,0x1E25,0x0048}, {0x1E24,0x1E25,0x0048},
+ {0x1E26,0x1E27,0x0048}, {0x1E26,0x1E27,0x0048},
+ {0x1E28,0x1E29,0x0048}, {0x1E28,0x1E29,0x0048},
+ {0x1E2A,0x1E2B,0x0048}, {0x1E2A,0x1E2B,0x0048},
+ {0x1E2C,0x1E2D,0x0049}, {0x1E2C,0x1E2D,0x0049},
+ {0x1E2E,0x1E2F,0x0049}, {0x1E2E,0x1E2F,0x0049},
+ {0x1E30,0x1E31,0x004B}, {0x1E30,0x1E31,0x004B},
+ {0x1E32,0x1E33,0x004B}, {0x1E32,0x1E33,0x004B},
+ {0x1E34,0x1E35,0x004B}, {0x1E34,0x1E35,0x004B},
+ {0x1E36,0x1E37,0x004C}, {0x1E36,0x1E37,0x004C},
+ {0x1E38,0x1E39,0x004C}, {0x1E38,0x1E39,0x004C},
+ {0x1E3A,0x1E3B,0x004C}, {0x1E3A,0x1E3B,0x004C},
+ {0x1E3C,0x1E3D,0x004C}, {0x1E3C,0x1E3D,0x004C},
+ {0x1E3E,0x1E3F,0x004D}, {0x1E3E,0x1E3F,0x004D},
+ {0x1E40,0x1E41,0x004D}, {0x1E40,0x1E41,0x004D},
+ {0x1E42,0x1E43,0x004D}, {0x1E42,0x1E43,0x004D},
+ {0x1E44,0x1E45,0x004E}, {0x1E44,0x1E45,0x004E},
+ {0x1E46,0x1E47,0x004E}, {0x1E46,0x1E47,0x004E},
+ {0x1E48,0x1E49,0x004E}, {0x1E48,0x1E49,0x004E},
+ {0x1E4A,0x1E4B,0x004E}, {0x1E4A,0x1E4B,0x004E},
+ {0x1E4C,0x1E4D,0x004F}, {0x1E4C,0x1E4D,0x004F},
+ {0x1E4E,0x1E4F,0x004F}, {0x1E4E,0x1E4F,0x004F},
+ {0x1E50,0x1E51,0x004F}, {0x1E50,0x1E51,0x004F},
+ {0x1E52,0x1E53,0x004F}, {0x1E52,0x1E53,0x004F},
+ {0x1E54,0x1E55,0x0050}, {0x1E54,0x1E55,0x0050},
+ {0x1E56,0x1E57,0x0050}, {0x1E56,0x1E57,0x0050},
+ {0x1E58,0x1E59,0x0052}, {0x1E58,0x1E59,0x0052},
+ {0x1E5A,0x1E5B,0x0052}, {0x1E5A,0x1E5B,0x0052},
+ {0x1E5C,0x1E5D,0x0052}, {0x1E5C,0x1E5D,0x0052},
+ {0x1E5E,0x1E5F,0x0052}, {0x1E5E,0x1E5F,0x0052},
+ {0x1E60,0x1E61,0x0053}, {0x1E60,0x1E61,0x0053},
+ {0x1E62,0x1E63,0x0053}, {0x1E62,0x1E63,0x0053},
+ {0x1E64,0x1E65,0x0053}, {0x1E64,0x1E65,0x0053},
+ {0x1E66,0x1E67,0x0053}, {0x1E66,0x1E67,0x0053},
+ {0x1E68,0x1E69,0x0053}, {0x1E68,0x1E69,0x0053},
+ {0x1E6A,0x1E6B,0x0054}, {0x1E6A,0x1E6B,0x0054},
+ {0x1E6C,0x1E6D,0x0054}, {0x1E6C,0x1E6D,0x0054},
+ {0x1E6E,0x1E6F,0x0054}, {0x1E6E,0x1E6F,0x0054},
+ {0x1E70,0x1E71,0x0054}, {0x1E70,0x1E71,0x0054},
+ {0x1E72,0x1E73,0x0055}, {0x1E72,0x1E73,0x0055},
+ {0x1E74,0x1E75,0x0055}, {0x1E74,0x1E75,0x0055},
+ {0x1E76,0x1E77,0x0055}, {0x1E76,0x1E77,0x0055},
+ {0x1E78,0x1E79,0x0055}, {0x1E78,0x1E79,0x0055},
+ {0x1E7A,0x1E7B,0x0055}, {0x1E7A,0x1E7B,0x0055},
+ {0x1E7C,0x1E7D,0x0056}, {0x1E7C,0x1E7D,0x0056},
+ {0x1E7E,0x1E7F,0x0056}, {0x1E7E,0x1E7F,0x0056},
+ {0x1E80,0x1E81,0x0057}, {0x1E80,0x1E81,0x0057},
+ {0x1E82,0x1E83,0x0057}, {0x1E82,0x1E83,0x0057},
+ {0x1E84,0x1E85,0x0057}, {0x1E84,0x1E85,0x0057},
+ {0x1E86,0x1E87,0x0057}, {0x1E86,0x1E87,0x0057},
+ {0x1E88,0x1E89,0x0057}, {0x1E88,0x1E89,0x0057},
+ {0x1E8A,0x1E8B,0x0058}, {0x1E8A,0x1E8B,0x0058},
+ {0x1E8C,0x1E8D,0x0058}, {0x1E8C,0x1E8D,0x0058},
+ {0x1E8E,0x1E8F,0x0059}, {0x1E8E,0x1E8F,0x0059},
+ {0x1E90,0x1E91,0x005A}, {0x1E90,0x1E91,0x005A},
+ {0x1E92,0x1E93,0x005A}, {0x1E92,0x1E93,0x005A},
+ {0x1E94,0x1E95,0x005A}, {0x1E94,0x1E95,0x005A},
+ {0x1E96,0x1E96,0x0048}, {0x1E97,0x1E97,0x0054},
+ {0x1E98,0x1E98,0x0057}, {0x1E99,0x1E99,0x0059},
+ {0x1E9A,0x1E9A,0x1E9A}, {0x1E60,0x1E9B,0x0053},
+ {0x1E9C,0x1E9C,0x1E9C}, {0x1E9D,0x1E9D,0x1E9D},
+ {0x1E9E,0x1E9E,0x1E9E}, {0x1E9F,0x1E9F,0x1E9F},
+ {0x1EA0,0x1EA1,0x0041}, {0x1EA0,0x1EA1,0x0041},
+ {0x1EA2,0x1EA3,0x0041}, {0x1EA2,0x1EA3,0x0041},
+ {0x1EA4,0x1EA5,0x0041}, {0x1EA4,0x1EA5,0x0041},
+ {0x1EA6,0x1EA7,0x0041}, {0x1EA6,0x1EA7,0x0041},
+ {0x1EA8,0x1EA9,0x0041}, {0x1EA8,0x1EA9,0x0041},
+ {0x1EAA,0x1EAB,0x0041}, {0x1EAA,0x1EAB,0x0041},
+ {0x1EAC,0x1EAD,0x0041}, {0x1EAC,0x1EAD,0x0041},
+ {0x1EAE,0x1EAF,0x0041}, {0x1EAE,0x1EAF,0x0041},
+ {0x1EB0,0x1EB1,0x0041}, {0x1EB0,0x1EB1,0x0041},
+ {0x1EB2,0x1EB3,0x0041}, {0x1EB2,0x1EB3,0x0041},
+ {0x1EB4,0x1EB5,0x0041}, {0x1EB4,0x1EB5,0x0041},
+ {0x1EB6,0x1EB7,0x0041}, {0x1EB6,0x1EB7,0x0041},
+ {0x1EB8,0x1EB9,0x0045}, {0x1EB8,0x1EB9,0x0045},
+ {0x1EBA,0x1EBB,0x0045}, {0x1EBA,0x1EBB,0x0045},
+ {0x1EBC,0x1EBD,0x0045}, {0x1EBC,0x1EBD,0x0045},
+ {0x1EBE,0x1EBF,0x0045}, {0x1EBE,0x1EBF,0x0045},
+ {0x1EC0,0x1EC1,0x0045}, {0x1EC0,0x1EC1,0x0045},
+ {0x1EC2,0x1EC3,0x0045}, {0x1EC2,0x1EC3,0x0045},
+ {0x1EC4,0x1EC5,0x0045}, {0x1EC4,0x1EC5,0x0045},
+ {0x1EC6,0x1EC7,0x0045}, {0x1EC6,0x1EC7,0x0045},
+ {0x1EC8,0x1EC9,0x0049}, {0x1EC8,0x1EC9,0x0049},
+ {0x1ECA,0x1ECB,0x0049}, {0x1ECA,0x1ECB,0x0049},
+ {0x1ECC,0x1ECD,0x004F}, {0x1ECC,0x1ECD,0x004F},
+ {0x1ECE,0x1ECF,0x004F}, {0x1ECE,0x1ECF,0x004F},
+ {0x1ED0,0x1ED1,0x004F}, {0x1ED0,0x1ED1,0x004F},
+ {0x1ED2,0x1ED3,0x004F}, {0x1ED2,0x1ED3,0x004F},
+ {0x1ED4,0x1ED5,0x004F}, {0x1ED4,0x1ED5,0x004F},
+ {0x1ED6,0x1ED7,0x004F}, {0x1ED6,0x1ED7,0x004F},
+ {0x1ED8,0x1ED9,0x004F}, {0x1ED8,0x1ED9,0x004F},
+ {0x1EDA,0x1EDB,0x004F}, {0x1EDA,0x1EDB,0x004F},
+ {0x1EDC,0x1EDD,0x004F}, {0x1EDC,0x1EDD,0x004F},
+ {0x1EDE,0x1EDF,0x004F}, {0x1EDE,0x1EDF,0x004F},
+ {0x1EE0,0x1EE1,0x004F}, {0x1EE0,0x1EE1,0x004F},
+ {0x1EE2,0x1EE3,0x004F}, {0x1EE2,0x1EE3,0x004F},
+ {0x1EE4,0x1EE5,0x0055}, {0x1EE4,0x1EE5,0x0055},
+ {0x1EE6,0x1EE7,0x0055}, {0x1EE6,0x1EE7,0x0055},
+ {0x1EE8,0x1EE9,0x0055}, {0x1EE8,0x1EE9,0x0055},
+ {0x1EEA,0x1EEB,0x0055}, {0x1EEA,0x1EEB,0x0055},
+ {0x1EEC,0x1EED,0x0055}, {0x1EEC,0x1EED,0x0055},
+ {0x1EEE,0x1EEF,0x0055}, {0x1EEE,0x1EEF,0x0055},
+ {0x1EF0,0x1EF1,0x0055}, {0x1EF0,0x1EF1,0x0055},
+ {0x1EF2,0x1EF3,0x0059}, {0x1EF2,0x1EF3,0x0059},
+ {0x1EF4,0x1EF5,0x0059}, {0x1EF4,0x1EF5,0x0059},
+ {0x1EF6,0x1EF7,0x0059}, {0x1EF6,0x1EF7,0x0059},
+ {0x1EF8,0x1EF9,0x0059}, {0x1EF8,0x1EF9,0x0059},
+ {0x1EFA,0x1EFA,0x1EFA}, {0x1EFB,0x1EFB,0x1EFB},
+ {0x1EFC,0x1EFC,0x1EFC}, {0x1EFD,0x1EFD,0x1EFD},
+ {0x1EFE,0x1EFE,0x1EFE}, {0x1EFF,0x1EFF,0x1EFF}
+};
+
+static MY_UNICASE_INFO plane1F[]={
+ {0x1F08,0x1F00,0x0391}, {0x1F09,0x1F01,0x0391},
+ {0x1F0A,0x1F02,0x0391}, {0x1F0B,0x1F03,0x0391},
+ {0x1F0C,0x1F04,0x0391}, {0x1F0D,0x1F05,0x0391},
+ {0x1F0E,0x1F06,0x0391}, {0x1F0F,0x1F07,0x0391},
+ {0x1F08,0x1F00,0x0391}, {0x1F09,0x1F01,0x0391},
+ {0x1F0A,0x1F02,0x0391}, {0x1F0B,0x1F03,0x0391},
+ {0x1F0C,0x1F04,0x0391}, {0x1F0D,0x1F05,0x0391},
+ {0x1F0E,0x1F06,0x0391}, {0x1F0F,0x1F07,0x0391},
+ {0x1F18,0x1F10,0x0395}, {0x1F19,0x1F11,0x0395},
+ {0x1F1A,0x1F12,0x0395}, {0x1F1B,0x1F13,0x0395},
+ {0x1F1C,0x1F14,0x0395}, {0x1F1D,0x1F15,0x0395},
+ {0x1F16,0x1F16,0x1F16}, {0x1F17,0x1F17,0x1F17},
+ {0x1F18,0x1F10,0x0395}, {0x1F19,0x1F11,0x0395},
+ {0x1F1A,0x1F12,0x0395}, {0x1F1B,0x1F13,0x0395},
+ {0x1F1C,0x1F14,0x0395}, {0x1F1D,0x1F15,0x0395},
+ {0x1F1E,0x1F1E,0x1F1E}, {0x1F1F,0x1F1F,0x1F1F},
+ {0x1F28,0x1F20,0x0397}, {0x1F29,0x1F21,0x0397},
+ {0x1F2A,0x1F22,0x0397}, {0x1F2B,0x1F23,0x0397},
+ {0x1F2C,0x1F24,0x0397}, {0x1F2D,0x1F25,0x0397},
+ {0x1F2E,0x1F26,0x0397}, {0x1F2F,0x1F27,0x0397},
+ {0x1F28,0x1F20,0x0397}, {0x1F29,0x1F21,0x0397},
+ {0x1F2A,0x1F22,0x0397}, {0x1F2B,0x1F23,0x0397},
+ {0x1F2C,0x1F24,0x0397}, {0x1F2D,0x1F25,0x0397},
+ {0x1F2E,0x1F26,0x0397}, {0x1F2F,0x1F27,0x0397},
+ {0x1F38,0x1F30,0x0399}, {0x1F39,0x1F31,0x0399},
+ {0x1F3A,0x1F32,0x0399}, {0x1F3B,0x1F33,0x0399},
+ {0x1F3C,0x1F34,0x0399}, {0x1F3D,0x1F35,0x0399},
+ {0x1F3E,0x1F36,0x0399}, {0x1F3F,0x1F37,0x0399},
+ {0x1F38,0x1F30,0x0399}, {0x1F39,0x1F31,0x0399},
+ {0x1F3A,0x1F32,0x0399}, {0x1F3B,0x1F33,0x0399},
+ {0x1F3C,0x1F34,0x0399}, {0x1F3D,0x1F35,0x0399},
+ {0x1F3E,0x1F36,0x0399}, {0x1F3F,0x1F37,0x0399},
+ {0x1F48,0x1F40,0x039F}, {0x1F49,0x1F41,0x039F},
+ {0x1F4A,0x1F42,0x039F}, {0x1F4B,0x1F43,0x039F},
+ {0x1F4C,0x1F44,0x039F}, {0x1F4D,0x1F45,0x039F},
+ {0x1F46,0x1F46,0x1F46}, {0x1F47,0x1F47,0x1F47},
+ {0x1F48,0x1F40,0x039F}, {0x1F49,0x1F41,0x039F},
+ {0x1F4A,0x1F42,0x039F}, {0x1F4B,0x1F43,0x039F},
+ {0x1F4C,0x1F44,0x039F}, {0x1F4D,0x1F45,0x039F},
+ {0x1F4E,0x1F4E,0x1F4E}, {0x1F4F,0x1F4F,0x1F4F},
+ {0x1F50,0x1F50,0x03A5}, {0x1F59,0x1F51,0x03A5},
+ {0x1F52,0x1F52,0x03A5}, {0x1F5B,0x1F53,0x03A5},
+ {0x1F54,0x1F54,0x03A5}, {0x1F5D,0x1F55,0x03A5},
+ {0x1F56,0x1F56,0x03A5}, {0x1F5F,0x1F57,0x03A5},
+ {0x1F58,0x1F58,0x1F58}, {0x1F59,0x1F51,0x03A5},
+ {0x1F5A,0x1F5A,0x1F5A}, {0x1F5B,0x1F53,0x03A5},
+ {0x1F5C,0x1F5C,0x1F5C}, {0x1F5D,0x1F55,0x03A5},
+ {0x1F5E,0x1F5E,0x1F5E}, {0x1F5F,0x1F57,0x03A5},
+ {0x1F68,0x1F60,0x03A9}, {0x1F69,0x1F61,0x03A9},
+ {0x1F6A,0x1F62,0x03A9}, {0x1F6B,0x1F63,0x03A9},
+ {0x1F6C,0x1F64,0x03A9}, {0x1F6D,0x1F65,0x03A9},
+ {0x1F6E,0x1F66,0x03A9}, {0x1F6F,0x1F67,0x03A9},
+ {0x1F68,0x1F60,0x03A9}, {0x1F69,0x1F61,0x03A9},
+ {0x1F6A,0x1F62,0x03A9}, {0x1F6B,0x1F63,0x03A9},
+ {0x1F6C,0x1F64,0x03A9}, {0x1F6D,0x1F65,0x03A9},
+ {0x1F6E,0x1F66,0x03A9}, {0x1F6F,0x1F67,0x03A9},
+ {0x1FBA,0x1F70,0x0391}, {0x1FBB,0x1F71,0x1FBB},
+ {0x1FC8,0x1F72,0x0395}, {0x1FC9,0x1F73,0x1FC9},
+ {0x1FCA,0x1F74,0x0397}, {0x1FCB,0x1F75,0x1FCB},
+ {0x1FDA,0x1F76,0x0399}, {0x1FDB,0x1F77,0x1FDB},
+ {0x1FF8,0x1F78,0x039F}, {0x1FF9,0x1F79,0x1FF9},
+ {0x1FEA,0x1F7A,0x03A5}, {0x1FEB,0x1F7B,0x1FEB},
+ {0x1FFA,0x1F7C,0x03A9}, {0x1FFB,0x1F7D,0x1FFB},
+ {0x1F7E,0x1F7E,0x1F7E}, {0x1F7F,0x1F7F,0x1F7F},
+ {0x1F88,0x1F80,0x0391}, {0x1F89,0x1F81,0x0391},
+ {0x1F8A,0x1F82,0x0391}, {0x1F8B,0x1F83,0x0391},
+ {0x1F8C,0x1F84,0x0391}, {0x1F8D,0x1F85,0x0391},
+ {0x1F8E,0x1F86,0x0391}, {0x1F8F,0x1F87,0x0391},
+ {0x1F88,0x1F80,0x0391}, {0x1F89,0x1F81,0x0391},
+ {0x1F8A,0x1F82,0x0391}, {0x1F8B,0x1F83,0x0391},
+ {0x1F8C,0x1F84,0x0391}, {0x1F8D,0x1F85,0x0391},
+ {0x1F8E,0x1F86,0x0391}, {0x1F8F,0x1F87,0x0391},
+ {0x1F98,0x1F90,0x0397}, {0x1F99,0x1F91,0x0397},
+ {0x1F9A,0x1F92,0x0397}, {0x1F9B,0x1F93,0x0397},
+ {0x1F9C,0x1F94,0x0397}, {0x1F9D,0x1F95,0x0397},
+ {0x1F9E,0x1F96,0x0397}, {0x1F9F,0x1F97,0x0397},
+ {0x1F98,0x1F90,0x0397}, {0x1F99,0x1F91,0x0397},
+ {0x1F9A,0x1F92,0x0397}, {0x1F9B,0x1F93,0x0397},
+ {0x1F9C,0x1F94,0x0397}, {0x1F9D,0x1F95,0x0397},
+ {0x1F9E,0x1F96,0x0397}, {0x1F9F,0x1F97,0x0397},
+ {0x1FA8,0x1FA0,0x03A9}, {0x1FA9,0x1FA1,0x03A9},
+ {0x1FAA,0x1FA2,0x03A9}, {0x1FAB,0x1FA3,0x03A9},
+ {0x1FAC,0x1FA4,0x03A9}, {0x1FAD,0x1FA5,0x03A9},
+ {0x1FAE,0x1FA6,0x03A9}, {0x1FAF,0x1FA7,0x03A9},
+ {0x1FA8,0x1FA0,0x03A9}, {0x1FA9,0x1FA1,0x03A9},
+ {0x1FAA,0x1FA2,0x03A9}, {0x1FAB,0x1FA3,0x03A9},
+ {0x1FAC,0x1FA4,0x03A9}, {0x1FAD,0x1FA5,0x03A9},
+ {0x1FAE,0x1FA6,0x03A9}, {0x1FAF,0x1FA7,0x03A9},
+ {0x1FB8,0x1FB0,0x0391}, {0x1FB9,0x1FB1,0x0391},
+ {0x1FB2,0x1FB2,0x0391}, {0x1FBC,0x1FB3,0x0391},
+ {0x1FB4,0x1FB4,0x0391}, {0x1FB5,0x1FB5,0x1FB5},
+ {0x1FB6,0x1FB6,0x0391}, {0x1FB7,0x1FB7,0x0391},
+ {0x1FB8,0x1FB0,0x0391}, {0x1FB9,0x1FB1,0x0391},
+ {0x1FBA,0x1F70,0x0391}, {0x1FBB,0x1F71,0x1FBB},
+ {0x1FBC,0x1FB3,0x0391}, {0x1FBD,0x1FBD,0x1FBD},
+ {0x0399,0x1FBE,0x0399}, {0x1FBF,0x1FBF,0x1FBF},
+ {0x1FC0,0x1FC0,0x1FC0}, {0x1FC1,0x1FC1,0x1FC1},
+ {0x1FC2,0x1FC2,0x0397}, {0x1FCC,0x1FC3,0x0397},
+ {0x1FC4,0x1FC4,0x0397}, {0x1FC5,0x1FC5,0x1FC5},
+ {0x1FC6,0x1FC6,0x0397}, {0x1FC7,0x1FC7,0x0397},
+ {0x1FC8,0x1F72,0x0395}, {0x1FC9,0x1F73,0x1FC9},
+ {0x1FCA,0x1F74,0x0397}, {0x1FCB,0x1F75,0x1FCB},
+ {0x1FCC,0x1FC3,0x0397}, {0x1FCD,0x1FCD,0x1FCD},
+ {0x1FCE,0x1FCE,0x1FCE}, {0x1FCF,0x1FCF,0x1FCF},
+ {0x1FD8,0x1FD0,0x0399}, {0x1FD9,0x1FD1,0x0399},
+ {0x1FD2,0x1FD2,0x0399}, {0x1FD3,0x1FD3,0x1FD3},
+ {0x1FD4,0x1FD4,0x1FD4}, {0x1FD5,0x1FD5,0x1FD5},
+ {0x1FD6,0x1FD6,0x0399}, {0x1FD7,0x1FD7,0x0399},
+ {0x1FD8,0x1FD0,0x0399}, {0x1FD9,0x1FD1,0x0399},
+ {0x1FDA,0x1F76,0x0399}, {0x1FDB,0x1F77,0x1FDB},
+ {0x1FDC,0x1FDC,0x1FDC}, {0x1FDD,0x1FDD,0x1FDD},
+ {0x1FDE,0x1FDE,0x1FDE}, {0x1FDF,0x1FDF,0x1FDF},
+ {0x1FE8,0x1FE0,0x03A5}, {0x1FE9,0x1FE1,0x03A5},
+ {0x1FE2,0x1FE2,0x03A5}, {0x1FE3,0x1FE3,0x1FE3},
+ {0x1FE4,0x1FE4,0x03A1}, {0x1FEC,0x1FE5,0x03A1},
+ {0x1FE6,0x1FE6,0x03A5}, {0x1FE7,0x1FE7,0x03A5},
+ {0x1FE8,0x1FE0,0x03A5}, {0x1FE9,0x1FE1,0x03A5},
+ {0x1FEA,0x1F7A,0x03A5}, {0x1FEB,0x1F7B,0x1FEB},
+ {0x1FEC,0x1FE5,0x03A1}, {0x1FED,0x1FED,0x1FED},
+ {0x1FEE,0x1FEE,0x1FEE}, {0x1FEF,0x1FEF,0x1FEF},
+ {0x1FF0,0x1FF0,0x1FF0}, {0x1FF1,0x1FF1,0x1FF1},
+ {0x1FF2,0x1FF2,0x03A9}, {0x1FFC,0x1FF3,0x03A9},
+ {0x1FF4,0x1FF4,0x03A9}, {0x1FF5,0x1FF5,0x1FF5},
+ {0x1FF6,0x1FF6,0x03A9}, {0x1FF7,0x1FF7,0x03A9},
+ {0x1FF8,0x1F78,0x039F}, {0x1FF9,0x1F79,0x1FF9},
+ {0x1FFA,0x1F7C,0x03A9}, {0x1FFB,0x1F7D,0x1FFB},
+ {0x1FFC,0x1FF3,0x03A9}, {0x1FFD,0x1FFD,0x1FFD},
+ {0x1FFE,0x1FFE,0x1FFE}, {0x1FFF,0x1FFF,0x1FFF}
+};
+
+static MY_UNICASE_INFO plane21[]={
+ {0x2100,0x2100,0x2100}, {0x2101,0x2101,0x2101},
+ {0x2102,0x2102,0x2102}, {0x2103,0x2103,0x2103},
+ {0x2104,0x2104,0x2104}, {0x2105,0x2105,0x2105},
+ {0x2106,0x2106,0x2106}, {0x2107,0x2107,0x2107},
+ {0x2108,0x2108,0x2108}, {0x2109,0x2109,0x2109},
+ {0x210A,0x210A,0x210A}, {0x210B,0x210B,0x210B},
+ {0x210C,0x210C,0x210C}, {0x210D,0x210D,0x210D},
+ {0x210E,0x210E,0x210E}, {0x210F,0x210F,0x210F},
+ {0x2110,0x2110,0x2110}, {0x2111,0x2111,0x2111},
+ {0x2112,0x2112,0x2112}, {0x2113,0x2113,0x2113},
+ {0x2114,0x2114,0x2114}, {0x2115,0x2115,0x2115},
+ {0x2116,0x2116,0x2116}, {0x2117,0x2117,0x2117},
+ {0x2118,0x2118,0x2118}, {0x2119,0x2119,0x2119},
+ {0x211A,0x211A,0x211A}, {0x211B,0x211B,0x211B},
+ {0x211C,0x211C,0x211C}, {0x211D,0x211D,0x211D},
+ {0x211E,0x211E,0x211E}, {0x211F,0x211F,0x211F},
+ {0x2120,0x2120,0x2120}, {0x2121,0x2121,0x2121},
+ {0x2122,0x2122,0x2122}, {0x2123,0x2123,0x2123},
+ {0x2124,0x2124,0x2124}, {0x2125,0x2125,0x2125},
+ {0x2126,0x03C9,0x2126}, {0x2127,0x2127,0x2127},
+ {0x2128,0x2128,0x2128}, {0x2129,0x2129,0x2129},
+ {0x212A,0x006B,0x212A}, {0x212B,0x00E5,0x212B},
+ {0x212C,0x212C,0x212C}, {0x212D,0x212D,0x212D},
+ {0x212E,0x212E,0x212E}, {0x212F,0x212F,0x212F},
+ {0x2130,0x2130,0x2130}, {0x2131,0x2131,0x2131},
+ {0x2132,0x2132,0x2132}, {0x2133,0x2133,0x2133},
+ {0x2134,0x2134,0x2134}, {0x2135,0x2135,0x2135},
+ {0x2136,0x2136,0x2136}, {0x2137,0x2137,0x2137},
+ {0x2138,0x2138,0x2138}, {0x2139,0x2139,0x2139},
+ {0x213A,0x213A,0x213A}, {0x213B,0x213B,0x213B},
+ {0x213C,0x213C,0x213C}, {0x213D,0x213D,0x213D},
+ {0x213E,0x213E,0x213E}, {0x213F,0x213F,0x213F},
+ {0x2140,0x2140,0x2140}, {0x2141,0x2141,0x2141},
+ {0x2142,0x2142,0x2142}, {0x2143,0x2143,0x2143},
+ {0x2144,0x2144,0x2144}, {0x2145,0x2145,0x2145},
+ {0x2146,0x2146,0x2146}, {0x2147,0x2147,0x2147},
+ {0x2148,0x2148,0x2148}, {0x2149,0x2149,0x2149},
+ {0x214A,0x214A,0x214A}, {0x214B,0x214B,0x214B},
+ {0x214C,0x214C,0x214C}, {0x214D,0x214D,0x214D},
+ {0x214E,0x214E,0x214E}, {0x214F,0x214F,0x214F},
+ {0x2150,0x2150,0x2150}, {0x2151,0x2151,0x2151},
+ {0x2152,0x2152,0x2152}, {0x2153,0x2153,0x2153},
+ {0x2154,0x2154,0x2154}, {0x2155,0x2155,0x2155},
+ {0x2156,0x2156,0x2156}, {0x2157,0x2157,0x2157},
+ {0x2158,0x2158,0x2158}, {0x2159,0x2159,0x2159},
+ {0x215A,0x215A,0x215A}, {0x215B,0x215B,0x215B},
+ {0x215C,0x215C,0x215C}, {0x215D,0x215D,0x215D},
+ {0x215E,0x215E,0x215E}, {0x215F,0x215F,0x215F},
+ {0x2160,0x2170,0x2160}, {0x2161,0x2171,0x2161},
+ {0x2162,0x2172,0x2162}, {0x2163,0x2173,0x2163},
+ {0x2164,0x2174,0x2164}, {0x2165,0x2175,0x2165},
+ {0x2166,0x2176,0x2166}, {0x2167,0x2177,0x2167},
+ {0x2168,0x2178,0x2168}, {0x2169,0x2179,0x2169},
+ {0x216A,0x217A,0x216A}, {0x216B,0x217B,0x216B},
+ {0x216C,0x217C,0x216C}, {0x216D,0x217D,0x216D},
+ {0x216E,0x217E,0x216E}, {0x216F,0x217F,0x216F},
+ {0x2160,0x2170,0x2160}, {0x2161,0x2171,0x2161},
+ {0x2162,0x2172,0x2162}, {0x2163,0x2173,0x2163},
+ {0x2164,0x2174,0x2164}, {0x2165,0x2175,0x2165},
+ {0x2166,0x2176,0x2166}, {0x2167,0x2177,0x2167},
+ {0x2168,0x2178,0x2168}, {0x2169,0x2179,0x2169},
+ {0x216A,0x217A,0x216A}, {0x216B,0x217B,0x216B},
+ {0x216C,0x217C,0x216C}, {0x216D,0x217D,0x216D},
+ {0x216E,0x217E,0x216E}, {0x216F,0x217F,0x216F},
+ {0x2180,0x2180,0x2180}, {0x2181,0x2181,0x2181},
+ {0x2182,0x2182,0x2182}, {0x2183,0x2183,0x2183},
+ {0x2184,0x2184,0x2184}, {0x2185,0x2185,0x2185},
+ {0x2186,0x2186,0x2186}, {0x2187,0x2187,0x2187},
+ {0x2188,0x2188,0x2188}, {0x2189,0x2189,0x2189},
+ {0x218A,0x218A,0x218A}, {0x218B,0x218B,0x218B},
+ {0x218C,0x218C,0x218C}, {0x218D,0x218D,0x218D},
+ {0x218E,0x218E,0x218E}, {0x218F,0x218F,0x218F},
+ {0x2190,0x2190,0x2190}, {0x2191,0x2191,0x2191},
+ {0x2192,0x2192,0x2192}, {0x2193,0x2193,0x2193},
+ {0x2194,0x2194,0x2194}, {0x2195,0x2195,0x2195},
+ {0x2196,0x2196,0x2196}, {0x2197,0x2197,0x2197},
+ {0x2198,0x2198,0x2198}, {0x2199,0x2199,0x2199},
+ {0x219A,0x219A,0x219A}, {0x219B,0x219B,0x219B},
+ {0x219C,0x219C,0x219C}, {0x219D,0x219D,0x219D},
+ {0x219E,0x219E,0x219E}, {0x219F,0x219F,0x219F},
+ {0x21A0,0x21A0,0x21A0}, {0x21A1,0x21A1,0x21A1},
+ {0x21A2,0x21A2,0x21A2}, {0x21A3,0x21A3,0x21A3},
+ {0x21A4,0x21A4,0x21A4}, {0x21A5,0x21A5,0x21A5},
+ {0x21A6,0x21A6,0x21A6}, {0x21A7,0x21A7,0x21A7},
+ {0x21A8,0x21A8,0x21A8}, {0x21A9,0x21A9,0x21A9},
+ {0x21AA,0x21AA,0x21AA}, {0x21AB,0x21AB,0x21AB},
+ {0x21AC,0x21AC,0x21AC}, {0x21AD,0x21AD,0x21AD},
+ {0x21AE,0x21AE,0x21AE}, {0x21AF,0x21AF,0x21AF},
+ {0x21B0,0x21B0,0x21B0}, {0x21B1,0x21B1,0x21B1},
+ {0x21B2,0x21B2,0x21B2}, {0x21B3,0x21B3,0x21B3},
+ {0x21B4,0x21B4,0x21B4}, {0x21B5,0x21B5,0x21B5},
+ {0x21B6,0x21B6,0x21B6}, {0x21B7,0x21B7,0x21B7},
+ {0x21B8,0x21B8,0x21B8}, {0x21B9,0x21B9,0x21B9},
+ {0x21BA,0x21BA,0x21BA}, {0x21BB,0x21BB,0x21BB},
+ {0x21BC,0x21BC,0x21BC}, {0x21BD,0x21BD,0x21BD},
+ {0x21BE,0x21BE,0x21BE}, {0x21BF,0x21BF,0x21BF},
+ {0x21C0,0x21C0,0x21C0}, {0x21C1,0x21C1,0x21C1},
+ {0x21C2,0x21C2,0x21C2}, {0x21C3,0x21C3,0x21C3},
+ {0x21C4,0x21C4,0x21C4}, {0x21C5,0x21C5,0x21C5},
+ {0x21C6,0x21C6,0x21C6}, {0x21C7,0x21C7,0x21C7},
+ {0x21C8,0x21C8,0x21C8}, {0x21C9,0x21C9,0x21C9},
+ {0x21CA,0x21CA,0x21CA}, {0x21CB,0x21CB,0x21CB},
+ {0x21CC,0x21CC,0x21CC}, {0x21CD,0x21CD,0x21CD},
+ {0x21CE,0x21CE,0x21CE}, {0x21CF,0x21CF,0x21CF},
+ {0x21D0,0x21D0,0x21D0}, {0x21D1,0x21D1,0x21D1},
+ {0x21D2,0x21D2,0x21D2}, {0x21D3,0x21D3,0x21D3},
+ {0x21D4,0x21D4,0x21D4}, {0x21D5,0x21D5,0x21D5},
+ {0x21D6,0x21D6,0x21D6}, {0x21D7,0x21D7,0x21D7},
+ {0x21D8,0x21D8,0x21D8}, {0x21D9,0x21D9,0x21D9},
+ {0x21DA,0x21DA,0x21DA}, {0x21DB,0x21DB,0x21DB},
+ {0x21DC,0x21DC,0x21DC}, {0x21DD,0x21DD,0x21DD},
+ {0x21DE,0x21DE,0x21DE}, {0x21DF,0x21DF,0x21DF},
+ {0x21E0,0x21E0,0x21E0}, {0x21E1,0x21E1,0x21E1},
+ {0x21E2,0x21E2,0x21E2}, {0x21E3,0x21E3,0x21E3},
+ {0x21E4,0x21E4,0x21E4}, {0x21E5,0x21E5,0x21E5},
+ {0x21E6,0x21E6,0x21E6}, {0x21E7,0x21E7,0x21E7},
+ {0x21E8,0x21E8,0x21E8}, {0x21E9,0x21E9,0x21E9},
+ {0x21EA,0x21EA,0x21EA}, {0x21EB,0x21EB,0x21EB},
+ {0x21EC,0x21EC,0x21EC}, {0x21ED,0x21ED,0x21ED},
+ {0x21EE,0x21EE,0x21EE}, {0x21EF,0x21EF,0x21EF},
+ {0x21F0,0x21F0,0x21F0}, {0x21F1,0x21F1,0x21F1},
+ {0x21F2,0x21F2,0x21F2}, {0x21F3,0x21F3,0x21F3},
+ {0x21F4,0x21F4,0x21F4}, {0x21F5,0x21F5,0x21F5},
+ {0x21F6,0x21F6,0x21F6}, {0x21F7,0x21F7,0x21F7},
+ {0x21F8,0x21F8,0x21F8}, {0x21F9,0x21F9,0x21F9},
+ {0x21FA,0x21FA,0x21FA}, {0x21FB,0x21FB,0x21FB},
+ {0x21FC,0x21FC,0x21FC}, {0x21FD,0x21FD,0x21FD},
+ {0x21FE,0x21FE,0x21FE}, {0x21FF,0x21FF,0x21FF}
+};
+
+static MY_UNICASE_INFO plane24[]={
+ {0x2400,0x2400,0x2400}, {0x2401,0x2401,0x2401},
+ {0x2402,0x2402,0x2402}, {0x2403,0x2403,0x2403},
+ {0x2404,0x2404,0x2404}, {0x2405,0x2405,0x2405},
+ {0x2406,0x2406,0x2406}, {0x2407,0x2407,0x2407},
+ {0x2408,0x2408,0x2408}, {0x2409,0x2409,0x2409},
+ {0x240A,0x240A,0x240A}, {0x240B,0x240B,0x240B},
+ {0x240C,0x240C,0x240C}, {0x240D,0x240D,0x240D},
+ {0x240E,0x240E,0x240E}, {0x240F,0x240F,0x240F},
+ {0x2410,0x2410,0x2410}, {0x2411,0x2411,0x2411},
+ {0x2412,0x2412,0x2412}, {0x2413,0x2413,0x2413},
+ {0x2414,0x2414,0x2414}, {0x2415,0x2415,0x2415},
+ {0x2416,0x2416,0x2416}, {0x2417,0x2417,0x2417},
+ {0x2418,0x2418,0x2418}, {0x2419,0x2419,0x2419},
+ {0x241A,0x241A,0x241A}, {0x241B,0x241B,0x241B},
+ {0x241C,0x241C,0x241C}, {0x241D,0x241D,0x241D},
+ {0x241E,0x241E,0x241E}, {0x241F,0x241F,0x241F},
+ {0x2420,0x2420,0x2420}, {0x2421,0x2421,0x2421},
+ {0x2422,0x2422,0x2422}, {0x2423,0x2423,0x2423},
+ {0x2424,0x2424,0x2424}, {0x2425,0x2425,0x2425},
+ {0x2426,0x2426,0x2426}, {0x2427,0x2427,0x2427},
+ {0x2428,0x2428,0x2428}, {0x2429,0x2429,0x2429},
+ {0x242A,0x242A,0x242A}, {0x242B,0x242B,0x242B},
+ {0x242C,0x242C,0x242C}, {0x242D,0x242D,0x242D},
+ {0x242E,0x242E,0x242E}, {0x242F,0x242F,0x242F},
+ {0x2430,0x2430,0x2430}, {0x2431,0x2431,0x2431},
+ {0x2432,0x2432,0x2432}, {0x2433,0x2433,0x2433},
+ {0x2434,0x2434,0x2434}, {0x2435,0x2435,0x2435},
+ {0x2436,0x2436,0x2436}, {0x2437,0x2437,0x2437},
+ {0x2438,0x2438,0x2438}, {0x2439,0x2439,0x2439},
+ {0x243A,0x243A,0x243A}, {0x243B,0x243B,0x243B},
+ {0x243C,0x243C,0x243C}, {0x243D,0x243D,0x243D},
+ {0x243E,0x243E,0x243E}, {0x243F,0x243F,0x243F},
+ {0x2440,0x2440,0x2440}, {0x2441,0x2441,0x2441},
+ {0x2442,0x2442,0x2442}, {0x2443,0x2443,0x2443},
+ {0x2444,0x2444,0x2444}, {0x2445,0x2445,0x2445},
+ {0x2446,0x2446,0x2446}, {0x2447,0x2447,0x2447},
+ {0x2448,0x2448,0x2448}, {0x2449,0x2449,0x2449},
+ {0x244A,0x244A,0x244A}, {0x244B,0x244B,0x244B},
+ {0x244C,0x244C,0x244C}, {0x244D,0x244D,0x244D},
+ {0x244E,0x244E,0x244E}, {0x244F,0x244F,0x244F},
+ {0x2450,0x2450,0x2450}, {0x2451,0x2451,0x2451},
+ {0x2452,0x2452,0x2452}, {0x2453,0x2453,0x2453},
+ {0x2454,0x2454,0x2454}, {0x2455,0x2455,0x2455},
+ {0x2456,0x2456,0x2456}, {0x2457,0x2457,0x2457},
+ {0x2458,0x2458,0x2458}, {0x2459,0x2459,0x2459},
+ {0x245A,0x245A,0x245A}, {0x245B,0x245B,0x245B},
+ {0x245C,0x245C,0x245C}, {0x245D,0x245D,0x245D},
+ {0x245E,0x245E,0x245E}, {0x245F,0x245F,0x245F},
+ {0x2460,0x2460,0x2460}, {0x2461,0x2461,0x2461},
+ {0x2462,0x2462,0x2462}, {0x2463,0x2463,0x2463},
+ {0x2464,0x2464,0x2464}, {0x2465,0x2465,0x2465},
+ {0x2466,0x2466,0x2466}, {0x2467,0x2467,0x2467},
+ {0x2468,0x2468,0x2468}, {0x2469,0x2469,0x2469},
+ {0x246A,0x246A,0x246A}, {0x246B,0x246B,0x246B},
+ {0x246C,0x246C,0x246C}, {0x246D,0x246D,0x246D},
+ {0x246E,0x246E,0x246E}, {0x246F,0x246F,0x246F},
+ {0x2470,0x2470,0x2470}, {0x2471,0x2471,0x2471},
+ {0x2472,0x2472,0x2472}, {0x2473,0x2473,0x2473},
+ {0x2474,0x2474,0x2474}, {0x2475,0x2475,0x2475},
+ {0x2476,0x2476,0x2476}, {0x2477,0x2477,0x2477},
+ {0x2478,0x2478,0x2478}, {0x2479,0x2479,0x2479},
+ {0x247A,0x247A,0x247A}, {0x247B,0x247B,0x247B},
+ {0x247C,0x247C,0x247C}, {0x247D,0x247D,0x247D},
+ {0x247E,0x247E,0x247E}, {0x247F,0x247F,0x247F},
+ {0x2480,0x2480,0x2480}, {0x2481,0x2481,0x2481},
+ {0x2482,0x2482,0x2482}, {0x2483,0x2483,0x2483},
+ {0x2484,0x2484,0x2484}, {0x2485,0x2485,0x2485},
+ {0x2486,0x2486,0x2486}, {0x2487,0x2487,0x2487},
+ {0x2488,0x2488,0x2488}, {0x2489,0x2489,0x2489},
+ {0x248A,0x248A,0x248A}, {0x248B,0x248B,0x248B},
+ {0x248C,0x248C,0x248C}, {0x248D,0x248D,0x248D},
+ {0x248E,0x248E,0x248E}, {0x248F,0x248F,0x248F},
+ {0x2490,0x2490,0x2490}, {0x2491,0x2491,0x2491},
+ {0x2492,0x2492,0x2492}, {0x2493,0x2493,0x2493},
+ {0x2494,0x2494,0x2494}, {0x2495,0x2495,0x2495},
+ {0x2496,0x2496,0x2496}, {0x2497,0x2497,0x2497},
+ {0x2498,0x2498,0x2498}, {0x2499,0x2499,0x2499},
+ {0x249A,0x249A,0x249A}, {0x249B,0x249B,0x249B},
+ {0x249C,0x249C,0x249C}, {0x249D,0x249D,0x249D},
+ {0x249E,0x249E,0x249E}, {0x249F,0x249F,0x249F},
+ {0x24A0,0x24A0,0x24A0}, {0x24A1,0x24A1,0x24A1},
+ {0x24A2,0x24A2,0x24A2}, {0x24A3,0x24A3,0x24A3},
+ {0x24A4,0x24A4,0x24A4}, {0x24A5,0x24A5,0x24A5},
+ {0x24A6,0x24A6,0x24A6}, {0x24A7,0x24A7,0x24A7},
+ {0x24A8,0x24A8,0x24A8}, {0x24A9,0x24A9,0x24A9},
+ {0x24AA,0x24AA,0x24AA}, {0x24AB,0x24AB,0x24AB},
+ {0x24AC,0x24AC,0x24AC}, {0x24AD,0x24AD,0x24AD},
+ {0x24AE,0x24AE,0x24AE}, {0x24AF,0x24AF,0x24AF},
+ {0x24B0,0x24B0,0x24B0}, {0x24B1,0x24B1,0x24B1},
+ {0x24B2,0x24B2,0x24B2}, {0x24B3,0x24B3,0x24B3},
+ {0x24B4,0x24B4,0x24B4}, {0x24B5,0x24B5,0x24B5},
+ {0x24B6,0x24D0,0x24B6}, {0x24B7,0x24D1,0x24B7},
+ {0x24B8,0x24D2,0x24B8}, {0x24B9,0x24D3,0x24B9},
+ {0x24BA,0x24D4,0x24BA}, {0x24BB,0x24D5,0x24BB},
+ {0x24BC,0x24D6,0x24BC}, {0x24BD,0x24D7,0x24BD},
+ {0x24BE,0x24D8,0x24BE}, {0x24BF,0x24D9,0x24BF},
+ {0x24C0,0x24DA,0x24C0}, {0x24C1,0x24DB,0x24C1},
+ {0x24C2,0x24DC,0x24C2}, {0x24C3,0x24DD,0x24C3},
+ {0x24C4,0x24DE,0x24C4}, {0x24C5,0x24DF,0x24C5},
+ {0x24C6,0x24E0,0x24C6}, {0x24C7,0x24E1,0x24C7},
+ {0x24C8,0x24E2,0x24C8}, {0x24C9,0x24E3,0x24C9},
+ {0x24CA,0x24E4,0x24CA}, {0x24CB,0x24E5,0x24CB},
+ {0x24CC,0x24E6,0x24CC}, {0x24CD,0x24E7,0x24CD},
+ {0x24CE,0x24E8,0x24CE}, {0x24CF,0x24E9,0x24CF},
+ {0x24B6,0x24D0,0x24B6}, {0x24B7,0x24D1,0x24B7},
+ {0x24B8,0x24D2,0x24B8}, {0x24B9,0x24D3,0x24B9},
+ {0x24BA,0x24D4,0x24BA}, {0x24BB,0x24D5,0x24BB},
+ {0x24BC,0x24D6,0x24BC}, {0x24BD,0x24D7,0x24BD},
+ {0x24BE,0x24D8,0x24BE}, {0x24BF,0x24D9,0x24BF},
+ {0x24C0,0x24DA,0x24C0}, {0x24C1,0x24DB,0x24C1},
+ {0x24C2,0x24DC,0x24C2}, {0x24C3,0x24DD,0x24C3},
+ {0x24C4,0x24DE,0x24C4}, {0x24C5,0x24DF,0x24C5},
+ {0x24C6,0x24E0,0x24C6}, {0x24C7,0x24E1,0x24C7},
+ {0x24C8,0x24E2,0x24C8}, {0x24C9,0x24E3,0x24C9},
+ {0x24CA,0x24E4,0x24CA}, {0x24CB,0x24E5,0x24CB},
+ {0x24CC,0x24E6,0x24CC}, {0x24CD,0x24E7,0x24CD},
+ {0x24CE,0x24E8,0x24CE}, {0x24CF,0x24E9,0x24CF},
+ {0x24EA,0x24EA,0x24EA}, {0x24EB,0x24EB,0x24EB},
+ {0x24EC,0x24EC,0x24EC}, {0x24ED,0x24ED,0x24ED},
+ {0x24EE,0x24EE,0x24EE}, {0x24EF,0x24EF,0x24EF},
+ {0x24F0,0x24F0,0x24F0}, {0x24F1,0x24F1,0x24F1},
+ {0x24F2,0x24F2,0x24F2}, {0x24F3,0x24F3,0x24F3},
+ {0x24F4,0x24F4,0x24F4}, {0x24F5,0x24F5,0x24F5},
+ {0x24F6,0x24F6,0x24F6}, {0x24F7,0x24F7,0x24F7},
+ {0x24F8,0x24F8,0x24F8}, {0x24F9,0x24F9,0x24F9},
+ {0x24FA,0x24FA,0x24FA}, {0x24FB,0x24FB,0x24FB},
+ {0x24FC,0x24FC,0x24FC}, {0x24FD,0x24FD,0x24FD},
+ {0x24FE,0x24FE,0x24FE}, {0x24FF,0x24FF,0x24FF}
+};
+
+static MY_UNICASE_INFO planeFF[]={
+ {0xFF00,0xFF00,0xFF00}, {0xFF01,0xFF01,0xFF01},
+ {0xFF02,0xFF02,0xFF02}, {0xFF03,0xFF03,0xFF03},
+ {0xFF04,0xFF04,0xFF04}, {0xFF05,0xFF05,0xFF05},
+ {0xFF06,0xFF06,0xFF06}, {0xFF07,0xFF07,0xFF07},
+ {0xFF08,0xFF08,0xFF08}, {0xFF09,0xFF09,0xFF09},
+ {0xFF0A,0xFF0A,0xFF0A}, {0xFF0B,0xFF0B,0xFF0B},
+ {0xFF0C,0xFF0C,0xFF0C}, {0xFF0D,0xFF0D,0xFF0D},
+ {0xFF0E,0xFF0E,0xFF0E}, {0xFF0F,0xFF0F,0xFF0F},
+ {0xFF10,0xFF10,0xFF10}, {0xFF11,0xFF11,0xFF11},
+ {0xFF12,0xFF12,0xFF12}, {0xFF13,0xFF13,0xFF13},
+ {0xFF14,0xFF14,0xFF14}, {0xFF15,0xFF15,0xFF15},
+ {0xFF16,0xFF16,0xFF16}, {0xFF17,0xFF17,0xFF17},
+ {0xFF18,0xFF18,0xFF18}, {0xFF19,0xFF19,0xFF19},
+ {0xFF1A,0xFF1A,0xFF1A}, {0xFF1B,0xFF1B,0xFF1B},
+ {0xFF1C,0xFF1C,0xFF1C}, {0xFF1D,0xFF1D,0xFF1D},
+ {0xFF1E,0xFF1E,0xFF1E}, {0xFF1F,0xFF1F,0xFF1F},
+ {0xFF20,0xFF20,0xFF20}, {0xFF21,0xFF41,0xFF21},
+ {0xFF22,0xFF42,0xFF22}, {0xFF23,0xFF43,0xFF23},
+ {0xFF24,0xFF44,0xFF24}, {0xFF25,0xFF45,0xFF25},
+ {0xFF26,0xFF46,0xFF26}, {0xFF27,0xFF47,0xFF27},
+ {0xFF28,0xFF48,0xFF28}, {0xFF29,0xFF49,0xFF29},
+ {0xFF2A,0xFF4A,0xFF2A}, {0xFF2B,0xFF4B,0xFF2B},
+ {0xFF2C,0xFF4C,0xFF2C}, {0xFF2D,0xFF4D,0xFF2D},
+ {0xFF2E,0xFF4E,0xFF2E}, {0xFF2F,0xFF4F,0xFF2F},
+ {0xFF30,0xFF50,0xFF30}, {0xFF31,0xFF51,0xFF31},
+ {0xFF32,0xFF52,0xFF32}, {0xFF33,0xFF53,0xFF33},
+ {0xFF34,0xFF54,0xFF34}, {0xFF35,0xFF55,0xFF35},
+ {0xFF36,0xFF56,0xFF36}, {0xFF37,0xFF57,0xFF37},
+ {0xFF38,0xFF58,0xFF38}, {0xFF39,0xFF59,0xFF39},
+ {0xFF3A,0xFF5A,0xFF3A}, {0xFF3B,0xFF3B,0xFF3B},
+ {0xFF3C,0xFF3C,0xFF3C}, {0xFF3D,0xFF3D,0xFF3D},
+ {0xFF3E,0xFF3E,0xFF3E}, {0xFF3F,0xFF3F,0xFF3F},
+ {0xFF40,0xFF40,0xFF40}, {0xFF21,0xFF41,0xFF21},
+ {0xFF22,0xFF42,0xFF22}, {0xFF23,0xFF43,0xFF23},
+ {0xFF24,0xFF44,0xFF24}, {0xFF25,0xFF45,0xFF25},
+ {0xFF26,0xFF46,0xFF26}, {0xFF27,0xFF47,0xFF27},
+ {0xFF28,0xFF48,0xFF28}, {0xFF29,0xFF49,0xFF29},
+ {0xFF2A,0xFF4A,0xFF2A}, {0xFF2B,0xFF4B,0xFF2B},
+ {0xFF2C,0xFF4C,0xFF2C}, {0xFF2D,0xFF4D,0xFF2D},
+ {0xFF2E,0xFF4E,0xFF2E}, {0xFF2F,0xFF4F,0xFF2F},
+ {0xFF30,0xFF50,0xFF30}, {0xFF31,0xFF51,0xFF31},
+ {0xFF32,0xFF52,0xFF32}, {0xFF33,0xFF53,0xFF33},
+ {0xFF34,0xFF54,0xFF34}, {0xFF35,0xFF55,0xFF35},
+ {0xFF36,0xFF56,0xFF36}, {0xFF37,0xFF57,0xFF37},
+ {0xFF38,0xFF58,0xFF38}, {0xFF39,0xFF59,0xFF39},
+ {0xFF3A,0xFF5A,0xFF3A}, {0xFF5B,0xFF5B,0xFF5B},
+ {0xFF5C,0xFF5C,0xFF5C}, {0xFF5D,0xFF5D,0xFF5D},
+ {0xFF5E,0xFF5E,0xFF5E}, {0xFF5F,0xFF5F,0xFF5F},
+ {0xFF60,0xFF60,0xFF60}, {0xFF61,0xFF61,0xFF61},
+ {0xFF62,0xFF62,0xFF62}, {0xFF63,0xFF63,0xFF63},
+ {0xFF64,0xFF64,0xFF64}, {0xFF65,0xFF65,0xFF65},
+ {0xFF66,0xFF66,0xFF66}, {0xFF67,0xFF67,0xFF67},
+ {0xFF68,0xFF68,0xFF68}, {0xFF69,0xFF69,0xFF69},
+ {0xFF6A,0xFF6A,0xFF6A}, {0xFF6B,0xFF6B,0xFF6B},
+ {0xFF6C,0xFF6C,0xFF6C}, {0xFF6D,0xFF6D,0xFF6D},
+ {0xFF6E,0xFF6E,0xFF6E}, {0xFF6F,0xFF6F,0xFF6F},
+ {0xFF70,0xFF70,0xFF70}, {0xFF71,0xFF71,0xFF71},
+ {0xFF72,0xFF72,0xFF72}, {0xFF73,0xFF73,0xFF73},
+ {0xFF74,0xFF74,0xFF74}, {0xFF75,0xFF75,0xFF75},
+ {0xFF76,0xFF76,0xFF76}, {0xFF77,0xFF77,0xFF77},
+ {0xFF78,0xFF78,0xFF78}, {0xFF79,0xFF79,0xFF79},
+ {0xFF7A,0xFF7A,0xFF7A}, {0xFF7B,0xFF7B,0xFF7B},
+ {0xFF7C,0xFF7C,0xFF7C}, {0xFF7D,0xFF7D,0xFF7D},
+ {0xFF7E,0xFF7E,0xFF7E}, {0xFF7F,0xFF7F,0xFF7F},
+ {0xFF80,0xFF80,0xFF80}, {0xFF81,0xFF81,0xFF81},
+ {0xFF82,0xFF82,0xFF82}, {0xFF83,0xFF83,0xFF83},
+ {0xFF84,0xFF84,0xFF84}, {0xFF85,0xFF85,0xFF85},
+ {0xFF86,0xFF86,0xFF86}, {0xFF87,0xFF87,0xFF87},
+ {0xFF88,0xFF88,0xFF88}, {0xFF89,0xFF89,0xFF89},
+ {0xFF8A,0xFF8A,0xFF8A}, {0xFF8B,0xFF8B,0xFF8B},
+ {0xFF8C,0xFF8C,0xFF8C}, {0xFF8D,0xFF8D,0xFF8D},
+ {0xFF8E,0xFF8E,0xFF8E}, {0xFF8F,0xFF8F,0xFF8F},
+ {0xFF90,0xFF90,0xFF90}, {0xFF91,0xFF91,0xFF91},
+ {0xFF92,0xFF92,0xFF92}, {0xFF93,0xFF93,0xFF93},
+ {0xFF94,0xFF94,0xFF94}, {0xFF95,0xFF95,0xFF95},
+ {0xFF96,0xFF96,0xFF96}, {0xFF97,0xFF97,0xFF97},
+ {0xFF98,0xFF98,0xFF98}, {0xFF99,0xFF99,0xFF99},
+ {0xFF9A,0xFF9A,0xFF9A}, {0xFF9B,0xFF9B,0xFF9B},
+ {0xFF9C,0xFF9C,0xFF9C}, {0xFF9D,0xFF9D,0xFF9D},
+ {0xFF9E,0xFF9E,0xFF9E}, {0xFF9F,0xFF9F,0xFF9F},
+ {0xFFA0,0xFFA0,0xFFA0}, {0xFFA1,0xFFA1,0xFFA1},
+ {0xFFA2,0xFFA2,0xFFA2}, {0xFFA3,0xFFA3,0xFFA3},
+ {0xFFA4,0xFFA4,0xFFA4}, {0xFFA5,0xFFA5,0xFFA5},
+ {0xFFA6,0xFFA6,0xFFA6}, {0xFFA7,0xFFA7,0xFFA7},
+ {0xFFA8,0xFFA8,0xFFA8}, {0xFFA9,0xFFA9,0xFFA9},
+ {0xFFAA,0xFFAA,0xFFAA}, {0xFFAB,0xFFAB,0xFFAB},
+ {0xFFAC,0xFFAC,0xFFAC}, {0xFFAD,0xFFAD,0xFFAD},
+ {0xFFAE,0xFFAE,0xFFAE}, {0xFFAF,0xFFAF,0xFFAF},
+ {0xFFB0,0xFFB0,0xFFB0}, {0xFFB1,0xFFB1,0xFFB1},
+ {0xFFB2,0xFFB2,0xFFB2}, {0xFFB3,0xFFB3,0xFFB3},
+ {0xFFB4,0xFFB4,0xFFB4}, {0xFFB5,0xFFB5,0xFFB5},
+ {0xFFB6,0xFFB6,0xFFB6}, {0xFFB7,0xFFB7,0xFFB7},
+ {0xFFB8,0xFFB8,0xFFB8}, {0xFFB9,0xFFB9,0xFFB9},
+ {0xFFBA,0xFFBA,0xFFBA}, {0xFFBB,0xFFBB,0xFFBB},
+ {0xFFBC,0xFFBC,0xFFBC}, {0xFFBD,0xFFBD,0xFFBD},
+ {0xFFBE,0xFFBE,0xFFBE}, {0xFFBF,0xFFBF,0xFFBF},
+ {0xFFC0,0xFFC0,0xFFC0}, {0xFFC1,0xFFC1,0xFFC1},
+ {0xFFC2,0xFFC2,0xFFC2}, {0xFFC3,0xFFC3,0xFFC3},
+ {0xFFC4,0xFFC4,0xFFC4}, {0xFFC5,0xFFC5,0xFFC5},
+ {0xFFC6,0xFFC6,0xFFC6}, {0xFFC7,0xFFC7,0xFFC7},
+ {0xFFC8,0xFFC8,0xFFC8}, {0xFFC9,0xFFC9,0xFFC9},
+ {0xFFCA,0xFFCA,0xFFCA}, {0xFFCB,0xFFCB,0xFFCB},
+ {0xFFCC,0xFFCC,0xFFCC}, {0xFFCD,0xFFCD,0xFFCD},
+ {0xFFCE,0xFFCE,0xFFCE}, {0xFFCF,0xFFCF,0xFFCF},
+ {0xFFD0,0xFFD0,0xFFD0}, {0xFFD1,0xFFD1,0xFFD1},
+ {0xFFD2,0xFFD2,0xFFD2}, {0xFFD3,0xFFD3,0xFFD3},
+ {0xFFD4,0xFFD4,0xFFD4}, {0xFFD5,0xFFD5,0xFFD5},
+ {0xFFD6,0xFFD6,0xFFD6}, {0xFFD7,0xFFD7,0xFFD7},
+ {0xFFD8,0xFFD8,0xFFD8}, {0xFFD9,0xFFD9,0xFFD9},
+ {0xFFDA,0xFFDA,0xFFDA}, {0xFFDB,0xFFDB,0xFFDB},
+ {0xFFDC,0xFFDC,0xFFDC}, {0xFFDD,0xFFDD,0xFFDD},
+ {0xFFDE,0xFFDE,0xFFDE}, {0xFFDF,0xFFDF,0xFFDF},
+ {0xFFE0,0xFFE0,0xFFE0}, {0xFFE1,0xFFE1,0xFFE1},
+ {0xFFE2,0xFFE2,0xFFE2}, {0xFFE3,0xFFE3,0xFFE3},
+ {0xFFE4,0xFFE4,0xFFE4}, {0xFFE5,0xFFE5,0xFFE5},
+ {0xFFE6,0xFFE6,0xFFE6}, {0xFFE7,0xFFE7,0xFFE7},
+ {0xFFE8,0xFFE8,0xFFE8}, {0xFFE9,0xFFE9,0xFFE9},
+ {0xFFEA,0xFFEA,0xFFEA}, {0xFFEB,0xFFEB,0xFFEB},
+ {0xFFEC,0xFFEC,0xFFEC}, {0xFFED,0xFFED,0xFFED},
+ {0xFFEE,0xFFEE,0xFFEE}, {0xFFEF,0xFFEF,0xFFEF},
+ {0xFFF0,0xFFF0,0xFFF0}, {0xFFF1,0xFFF1,0xFFF1},
+ {0xFFF2,0xFFF2,0xFFF2}, {0xFFF3,0xFFF3,0xFFF3},
+ {0xFFF4,0xFFF4,0xFFF4}, {0xFFF5,0xFFF5,0xFFF5},
+ {0xFFF6,0xFFF6,0xFFF6}, {0xFFF7,0xFFF7,0xFFF7},
+ {0xFFF8,0xFFF8,0xFFF8}, {0xFFF9,0xFFF9,0xFFF9},
+ {0xFFFA,0xFFFA,0xFFFA}, {0xFFFB,0xFFFB,0xFFFB},
+ {0xFFFC,0xFFFC,0xFFFC}, {0xFFFD,0xFFFD,0xFFFD},
+ {0xFFFE,0xFFFE,0xFFFE}, {0xFFFF,0xFFFF,0xFFFF}
+};
+
+static MY_UNICASE_INFO *uni_plane[256]={
+ plane00, plane01, plane02, plane03, plane04, plane05, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, plane1E, plane1F,
+ NULL, plane21, NULL, NULL, plane24, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, planeFF
+
+};
+
+#endif
+
+
+
+#ifdef HAVE_CHARSET_utf8
+
+/* These arrays are taken from usa7 implementation */
+
+static uchar ctype_utf8[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static uchar to_lower_utf8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_utf8[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+
+static int my_utf8_uni (CHARSET_INFO *cs __attribute__((unused)) ,
+ my_wc_t * pwc, const uchar *s, const uchar *e)
+{
+ unsigned char c = s[0];
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ if (c < 0x80)
+ {
+ *pwc = c;
+ return 1;
+ }
+ else if (c < 0xc2)
+ return MY_CS_ILSEQ;
+ else if (c < 0xe0)
+ {
+ if (s+2 > e) /* We need 2 characters */
+ return MY_CS_TOOFEW(0);
+
+ if (!((s[1] ^ 0x80) < 0x40))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x1f) << 6) | (my_wc_t) (s[1] ^ 0x80);
+ return 2;
+ }
+ else if (c < 0xf0)
+ {
+ if (s+3 > e) /* We need 3 characters */
+ return MY_CS_TOOFEW(0);
+
+ if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (c >= 0xe1 || s[1] >= 0xa0)))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x0f) << 12) |
+ ((my_wc_t) (s[1] ^ 0x80) << 6) |
+ (my_wc_t) (s[2] ^ 0x80);
+
+ return 3;
+
+#ifdef UNICODE_32BIT
+
+ }
+ else if (c < 0xf8 && sizeof(my_wc_t)*8 >= 32)
+ {
+ if (s+4 > e) /* We need 4 characters */
+ return MY_CS_TOOFEW(0);
+
+ if (!((s[1] ^ 0x80) < 0x40 &&
+ (s[2] ^ 0x80) < 0x40 &&
+ (s[3] ^ 0x80) < 0x40 &&
+ (c >= 0xf1 || s[1] >= 0x90)))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x07) << 18) |
+ ((my_wc_t) (s[1] ^ 0x80) << 12) |
+ ((my_wc_t) (s[2] ^ 0x80) << 6) |
+ (my_wc_t) (s[3] ^ 0x80);
+
+ return 4;
+ }
+ else if (c < 0xfc && sizeof(my_wc_t)*8 >= 32)
+ {
+ if (s+5 >e) /* We need 5 characters */
+ return MY_CS_TOOFEW(0);
+
+ if (!((s[1] ^ 0x80) < 0x40 &&
+ (s[2] ^ 0x80) < 0x40 &&
+ (s[3] ^ 0x80) < 0x40 &&
+ (s[4] ^ 0x80) < 0x40 &&
+ (c >= 0xf9 || s[1] >= 0x88)))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x03) << 24) |
+ ((my_wc_t) (s[1] ^ 0x80) << 18) |
+ ((my_wc_t) (s[2] ^ 0x80) << 12) |
+ ((my_wc_t) (s[3] ^ 0x80) << 6) |
+ (my_wc_t) (s[4] ^ 0x80);
+ return 5;
+ }
+ else if (c < 0xfe && sizeof(my_wc_t)*8 >= 32)
+ {
+ if ( s+6 >e ) /* We need 6 characters */
+ return MY_CS_TOOFEW(0);
+
+ if (!((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)))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x01) << 30)
+ | ((my_wc_t) (s[1] ^ 0x80) << 24)
+ | ((my_wc_t) (s[2] ^ 0x80) << 18)
+ | ((my_wc_t) (s[3] ^ 0x80) << 12)
+ | ((my_wc_t) (s[4] ^ 0x80) << 6)
+ | (my_wc_t) (s[5] ^ 0x80);
+ return 6;
+#endif
+ } else
+ return MY_CS_ILSEQ;
+}
+
+static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) ,
+ my_wc_t wc, uchar *r, uchar *e)
+{
+ int count;
+
+ if (r >= e)
+ return MY_CS_TOOSMALL;
+
+ if (wc < 0x80)
+ count = 1;
+ else if (wc < 0x800)
+ count = 2;
+ else if (wc < 0x10000)
+ count = 3;
+#ifdef UNICODE_32BIT
+ else if (wc < 0x200000)
+ count = 4;
+ else if (wc < 0x4000000)
+ count = 5;
+ else if (wc <= 0x7fffffff)
+ count = 6;
+#endif
+ else return MY_CS_ILUNI;
+
+ /*
+ e is a character after the string r, not the last character of it.
+ Because of it (r+count > e), not (r+count-1 >e )
+ */
+ if ( r+count > e )
+ return MY_CS_TOOSMALL;
+
+ switch (count) {
+ /* Fall through all cases!!! */
+#ifdef UNICODE_32BIT
+ case 6: r[5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000;
+ case 5: r[4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000;
+ case 4: r[3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000;
+#endif
+ case 3: r[2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800;
+ case 2: r[1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0;
+ case 1: r[0] = wc;
+ }
+ return count;
+}
+
+
+static void my_caseup_utf8(CHARSET_INFO *cs, char *s, uint slen)
+{
+ my_wc_t wc;
+ int res;
+ char *e=s+slen;
+
+ while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ if (res != my_uni_utf8(cs,wc,(uchar*)s,(uchar*)e))
+ break;
+ s+=res;
+ }
+}
+
+static uint my_hash_caseup_utf8(CHARSET_INFO *cs, const byte *s, uint slen)
+{
+ my_wc_t wc;
+ register uint nr=1, nr2=4;
+ int res;
+ const char *e=s+slen;
+
+ while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ nr^= (((nr & 63)+nr2)*(wc & 0xFF))+ (nr << 8);
+ nr2+=3;
+ nr^= (((nr & 63)+nr2)*(wc >> 8))+ (nr << 8);
+ nr2+=3;
+
+ s+=res;
+ }
+
+ return nr;
+}
+
+
+static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen, ulong *n1, ulong *n2)
+{
+ my_wc_t wc;
+ int res;
+ const uchar *e=s+slen;
+
+ while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].sort : wc;
+ n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8);
+ n2[0]+=3;
+ n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8);
+ n2[0]+=3;
+ s+=res;
+ }
+}
+
+
+static void my_caseup_str_utf8(CHARSET_INFO * cs, char * s)
+{
+ my_caseup_utf8(cs, s, strlen(s));
+}
+
+
+static void my_casedn_utf8(CHARSET_INFO *cs, char *s, uint slen)
+{
+ my_wc_t wc;
+ int res;
+ char *e=s+slen;
+
+ while ((s < e) && (res=my_utf8_uni(cs, &wc, (uchar*)s, (uchar*)e))>0)
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
+ if (res != my_uni_utf8(cs, wc, (uchar*)s, (uchar*)e))
+ {
+ break;
+ }
+ s+=res;
+ }
+}
+
+static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s)
+{
+ my_casedn_utf8(cs, s, strlen(s));
+}
+
+
+static int my_strnncoll_utf8(CHARSET_INFO *cs,
+ const uchar *s, uint slen, const uchar *t, uint tlen)
+{
+ int s_res,t_res;
+ my_wc_t s_wc,t_wc;
+ const uchar *se=s+slen;
+ const uchar *te=t+tlen;
+
+ while ( s < se && t < te )
+ {
+ int plane;
+ s_res=my_utf8_uni(cs,&s_wc, s, se);
+ t_res=my_utf8_uni(cs,&t_wc, t, te);
+
+ if ( s_res <= 0 || t_res <= 0 )
+ {
+ /* Incorrect string, compare by char value */
+ return ((int)s[0]-(int)t[0]);
+ }
+
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = uni_plane[plane] ? uni_plane[plane][s_wc & 0xFF].sort : s_wc;
+ plane=(t_wc>>8) & 0xFF;
+ t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc;
+ if ( s_wc != t_wc )
+ {
+ return ((int) s_wc) - ((int) t_wc);
+ }
+
+ s+=s_res;
+ t+=t_res;
+ }
+ return ( (se-s) - (te-t) );
+}
+
+static
+int my_strnncollsp_utf8(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_utf8(cs,s,slen,t,tlen);
+}
+
+
+static int my_strncasecmp_utf8(CHARSET_INFO *cs,
+ const char *s, const char *t, uint len)
+{
+ int s_res,t_res;
+ my_wc_t s_wc,t_wc;
+ const char *se=s+len;
+ const char *te=t+len;
+
+ while ( s < se && t < te )
+ {
+ int plane;
+
+ s_res=my_utf8_uni(cs,&s_wc, (const uchar*)s, (const uchar*)se);
+ t_res=my_utf8_uni(cs,&t_wc, (const uchar*)t, (const uchar*)te);
+
+ if ( s_res <= 0 || t_res <= 0 )
+ {
+ /* Incorrect string, compare by char value */
+ return ((int)s[0]-(int)t[0]);
+ }
+
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = uni_plane[plane] ? uni_plane[plane][s_wc & 0xFF].tolower : s_wc;
+
+ plane=(t_wc>>8) & 0xFF;
+ t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].tolower : t_wc;
+
+ if ( s_wc != t_wc )
+ return ((int) s_wc) - ((int) t_wc);
+
+ s+=s_res;
+ t+=t_res;
+ }
+ return ( (se-s) - (te-t) );
+}
+
+static int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t)
+{
+ uint s_len=strlen(s);
+ uint t_len=strlen(t);
+ uint len = (s_len > t_len) ? s_len : t_len;
+ return my_strncasecmp_utf8(cs, s, t, len);
+}
+
+static int my_strnxfrm_utf8(CHARSET_INFO *cs,
+ uchar *dst, uint dstlen,
+ const uchar *src, uint srclen)
+{
+ my_wc_t wc;
+ int res;
+ int plane;
+ uchar *de = dst + dstlen;
+ const uchar *se = src + srclen;
+ const uchar *dst_orig = dst;
+
+ while( src < se && dst < de )
+ {
+ if ((res=my_utf8_uni(cs,&wc, src, se))<0)
+ {
+ break;
+ }
+ src+=res;
+ srclen-=res;
+
+ plane=(wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].sort : wc;
+
+ if ((res=my_uni_utf8(cs,wc,dst,de)) <0)
+ {
+ break;
+ }
+ dst+=res;
+ }
+ return dst - dst_orig;
+}
+
+static int my_ismbchar_utf8(CHARSET_INFO *cs,const char *b, const char *e)
+{
+ my_wc_t wc;
+ int res=my_utf8_uni(cs,&wc, (const uchar*)b, (const uchar*)e);
+ return (res>1) ? res : 0;
+}
+
+static my_bool my_ismbhead_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint ch)
+{
+ return ( ch >= 0xc2 );
+}
+
+static int my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint c)
+{
+ if (c < 0x80)
+ return 1;
+ else if (c < 0xc2)
+ return 0; /* Illegal mb head */
+ else if (c < 0xe0)
+ return 2;
+ else if (c < 0xf0)
+ return 3;
+#ifdef UNICODE_32BIT
+ else if (c < 0xf8)
+ return 4;
+ else if (c < 0xfc)
+ return 5;
+ else if (c < 0xfe)
+ return 6;
+#endif
+ return 0; /* Illegal mb head */;
+}
+
+CHARSET_INFO my_charset_utf8 =
+{
+ 33, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ "utf8", /* cs name */
+ "utf8", /* name */
+ "", /* comment */
+ ctype_utf8, /* ctype */
+ to_lower_utf8, /* to_lower */
+ to_upper_utf8, /* to_upper */
+ to_upper_utf8, /* sort_order */
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 1, /* strxfrm_multiply */
+ my_strnncoll_utf8, /* strnncoll */
+ my_strnncollsp_utf8,
+ my_strnxfrm_utf8, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_mb, /* wildcmp */
+ 3, /* mbmaxlen */
+ my_ismbchar_utf8, /* ismbchar */
+ my_ismbhead_utf8, /* ismbhead */
+ my_mbcharlen_utf8, /* mbcharlen */
+ my_numchars_mb,
+ my_charpos_mb,
+ my_utf8_uni, /* mb_wc */
+ my_uni_utf8, /* wc_mb */
+ my_caseup_str_utf8,
+ my_casedn_str_utf8,
+ my_caseup_utf8,
+ my_casedn_utf8,
+ NULL, /* tosort */
+ my_strcasecmp_utf8,
+ my_strncasecmp_utf8,
+ my_hash_caseup_utf8,/* hash_caseup */
+ my_hash_sort_utf8, /* hash_sort */
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+
+#ifdef MY_TEST_UTF8
+
+#include <stdio.h>
+
+static void test_mb(CHARSET_INFO *cs, uchar *s)
+{
+ while(*s)
+ {
+ if(my_ismbhead_utf8(cs,*s))
+ {
+ int len=my_mbcharlen_utf8(cs,*s);
+ while(len--)
+ {
+ printf("%c",*s);
+ s++;
+ }
+ printf("\n");
+ }
+ else
+ {
+ printf("%c\n",*s);
+ s++;
+ }
+ }
+}
+
+int main()
+{
+ char str[1024]=" utf8 test проба ПЕРРпо-РУССКИ";
+ CHARSET_INFO *cs;
+
+ test_mb(cs,(uchar*)str);
+
+ pr1;2cintf("orig :'%s'\n",str);
+
+ my_caseup_utf8(cs,str,15);
+ printf("caseup :'%s'\n",str);
+
+ my_caseup_str_utf8(cs,str);
+ printf("caseup_str:'%s'\n",str);
+
+ my_casedn_utf8(cs,str,15);
+ printf("casedn :'%s'\n",str);
+
+ my_casedn_str_utf8(cs,str);
+ printf("casedn_str:'%s'\n",str);
+
+ return 0;
+}
+
+#endif
+
+#endif /* HAVE_CHARSET_UTF8 */
+
+
+
+#ifdef HAVE_CHARSET_ucs2
+
+static uchar ctype_ucs2[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static uchar to_lower_ucs2[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static uchar to_upper_ucs2[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+
+static int my_ucs2_uni (CHARSET_INFO *cs __attribute__((unused)) ,
+ my_wc_t * pwc, const uchar *s, const uchar *e)
+{
+ if (s+2 > e) /* Need 2 characters */
+ return MY_CS_TOOFEW(0);
+
+ *pwc= ((unsigned char)s[0]) * 256 + ((unsigned char)s[1]);
+ return 2;
+}
+
+static int my_uni_ucs2 (CHARSET_INFO *cs __attribute__((unused)) ,
+ my_wc_t wc, uchar *r, uchar *e)
+{
+ if ( r+2 > e )
+ return MY_CS_TOOSMALL;
+
+ r[0]=wc >> 8;
+ r[1]=wc & 0xFF;
+ return 2;
+}
+
+
+static void my_caseup_ucs2(CHARSET_INFO *cs, char *s, uint slen)
+{
+ my_wc_t wc;
+ int res;
+ char *e=s+slen;
+
+ while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ if (res != my_uni_ucs2(cs,wc,(uchar*)s,(uchar*)e))
+ break;
+ s+=res;
+ }
+}
+
+static uint my_hash_caseup_ucs2(CHARSET_INFO *cs, const byte *s, uint slen)
+{
+ my_wc_t wc;
+ register uint nr=1, nr2=4;
+ int res;
+ const char *e=s+slen;
+
+ while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ nr^= (((nr & 63)+nr2)*(wc & 0xFF))+ (nr << 8);
+ nr2+=3;
+ nr^= (((nr & 63)+nr2)*(wc >> 8))+ (nr << 8);
+ nr2+=3;
+
+ s+=res;
+ }
+
+ return nr;
+}
+
+
+static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, uint slen, ulong *n1, ulong *n2)
+{
+ my_wc_t wc;
+ int res;
+ const uchar *e=s+slen;
+
+ while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].sort : wc;
+ n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8);
+ n2[0]+=3;
+ n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8);
+ n2[0]+=3;
+ s+=res;
+ }
+}
+
+
+static void my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)),
+ char * s __attribute__((unused)))
+{
+}
+
+
+
+static void my_casedn_ucs2(CHARSET_INFO *cs, char *s, uint slen)
+{
+ my_wc_t wc;
+ int res;
+ char *e=s+slen;
+
+ while ((s < e) && (res=my_ucs2_uni(cs, &wc, (uchar*)s, (uchar*)e))>0)
+ {
+ int plane = (wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
+ if (res != my_uni_ucs2(cs, wc, (uchar*)s, (uchar*)e))
+ {
+ break;
+ }
+ s+=res;
+ }
+}
+
+static void my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ char * s __attribute__((unused)))
+{
+}
+
+
+static int my_strnncoll_ucs2(CHARSET_INFO *cs,
+ const uchar *s, uint slen, const uchar *t, uint tlen)
+{
+ int s_res,t_res;
+ my_wc_t s_wc,t_wc;
+ const uchar *se=s+slen;
+ const uchar *te=t+tlen;
+
+ while ( s < se && t < te )
+ {
+ int plane;
+ s_res=my_ucs2_uni(cs,&s_wc, s, se);
+ t_res=my_ucs2_uni(cs,&t_wc, t, te);
+
+ if ( s_res <= 0 || t_res <= 0 )
+ {
+ /* Incorrect string, compare by char value */
+ return ((int)s[0]-(int)t[0]);
+ }
+
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = uni_plane[plane] ? uni_plane[plane][s_wc & 0xFF].sort : s_wc;
+ plane=(t_wc>>8) & 0xFF;
+ t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc;
+ if ( s_wc != t_wc )
+ {
+ return ((int) s_wc) - ((int) t_wc);
+ }
+
+ s+=s_res;
+ t+=t_res;
+ }
+ return ( (se-s) - (te-t) );
+}
+
+static int my_strncasecmp_ucs2(CHARSET_INFO *cs,
+ const char *s, const char *t, uint len)
+{
+ int s_res,t_res;
+ my_wc_t s_wc,t_wc;
+ const char *se=s+len;
+ const char *te=t+len;
+
+ while ( s < se && t < te )
+ {
+ int plane;
+
+ s_res=my_ucs2_uni(cs,&s_wc, (const uchar*)s, (const uchar*)se);
+ t_res=my_ucs2_uni(cs,&t_wc, (const uchar*)t, (const uchar*)te);
+
+ if ( s_res <= 0 || t_res <= 0 )
+ {
+ /* Incorrect string, compare by char value */
+ return ((int)s[0]-(int)t[0]);
+ }
+
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = uni_plane[plane] ? uni_plane[plane][s_wc & 0xFF].tolower : s_wc;
+
+ plane=(t_wc>>8) & 0xFF;
+ t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].tolower : t_wc;
+
+ if ( s_wc != t_wc )
+ return ((int) s_wc) - ((int) t_wc);
+
+ s+=s_res;
+ t+=t_res;
+ }
+ return ( (se-s) - (te-t) );
+}
+
+static int my_strcasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t)
+{
+ uint s_len=strlen(s);
+ uint t_len=strlen(t);
+ uint len = (s_len > t_len) ? s_len : t_len;
+ return my_strncasecmp_ucs2(cs, s, t, len);
+}
+
+static int my_strnxfrm_ucs2(CHARSET_INFO *cs,
+ uchar *dst, uint dstlen, const uchar *src, uint srclen)
+{
+ my_wc_t wc;
+ int res;
+ int plane;
+ uchar *de = dst + dstlen;
+ const uchar *se = src + srclen;
+ const uchar *dst_orig = dst;
+
+ while( src < se && dst < de )
+ {
+ if ((res=my_ucs2_uni(cs,&wc, src, se))<0)
+ {
+ break;
+ }
+ src+=res;
+ srclen-=res;
+
+ plane=(wc>>8) & 0xFF;
+ wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].sort : wc;
+
+ if ((res=my_uni_ucs2(cs,wc,dst,de)) <0)
+ {
+ break;
+ }
+ dst+=res;
+ }
+ return dst - dst_orig;
+}
+
+static int my_ismbchar_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b __attribute__((unused)),
+ const char *e __attribute__((unused)))
+{
+ return 2;
+}
+
+static my_bool my_ismbhead_ucs2(CHARSET_INFO *cs __attribute__((unused)) ,
+ uint ch __attribute__((unused)))
+{
+ return 1;
+}
+
+static int my_mbcharlen_ucs2(CHARSET_INFO *cs __attribute__((unused)) ,
+ uint c __attribute__((unused)))
+{
+ return 2;
+}
+
+
+#include <m_string.h>
+#include <stdarg.h>
+#include <assert.h>
+
+static int my_vsnprintf_ucs2(char *dst, uint n, const char* fmt, va_list ap)
+{
+ char *start=dst, *end=dst+n-1;
+ for (; *fmt ; fmt++)
+ {
+ if (fmt[0] != '%')
+ {
+ if (dst == end) /* End of buffer */
+ break;
+
+ *dst++='\0'; *dst++= *fmt; /* Copy ordinary char */
+ continue;
+ }
+
+ fmt++;
+
+ /* Skip if max size is used (to be compatible with printf) */
+ while ( (*fmt>='0' && *fmt<='9') || *fmt == '.' || *fmt == '-')
+ fmt++;
+
+ if (*fmt == 'l')
+ fmt++;
+
+ if (*fmt == 's') /* String parameter */
+ {
+ reg2 char *par = va_arg(ap, char *);
+ uint plen;
+ uint left_len = (uint)(end-dst);
+ if (!par) par = (char*)"(null)";
+ plen = (uint) strlen(par);
+ if (left_len <= plen*2)
+ plen = left_len/2 - 1;
+
+ for ( ; plen ; plen--, dst+=2, par++)
+ {
+ dst[0]='\0';
+ dst[1]=par[0];
+ }
+ continue;
+ }
+ else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
+ {
+ register int iarg;
+ char nbuf[16];
+ char *pbuf=nbuf;
+
+ if ((uint) (end-dst) < 32)
+ break;
+ iarg = va_arg(ap, int);
+ if (*fmt == 'd')
+ int10_to_str((long) iarg, nbuf, -10);
+ else
+ int10_to_str((long) (uint) iarg,nbuf,10);
+
+ for (; pbuf[0]; pbuf++)
+ {
+ *dst++='\0';
+ *dst++=*pbuf;
+ }
+ continue;
+ }
+
+ /* We come here on '%%', unknown code or too long parameter */
+ if (dst == end)
+ break;
+ *dst++='\0';
+ *dst++='%'; /* % used as % or unknown code */
+ }
+
+ DBUG_ASSERT(dst <= end);
+ *dst='\0'; /* End of errmessage */
+ return (uint) (dst - start);
+}
+
+static int my_snprintf_ucs2(CHARSET_INFO *cs __attribute__((unused))
+ ,char* to, uint n, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args,fmt);
+ return my_vsnprintf_ucs2(to, n, fmt, args);
+}
+
+
+long my_strntol_ucs2(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative=0;
+ int overflow;
+ int cnv;
+ my_wc_t wc;
+ register unsigned int cutlim;
+ register ulong cutoff;
+ register ulong res;
+ register const uchar *s= (const uchar*) nptr;
+ register const uchar *e= (const uchar*) nptr+l;
+ const uchar *save;
+
+ *err= 0;
+ do
+ {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ switch (wc)
+ {
+ case ' ' : break;
+ case '\t': break;
+ case '-' : negative= !negative; break;
+ case '+' : break;
+ default : goto bs;
+ }
+ }
+ else /* No more characters or bad multibyte sequence */
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0] = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM;
+ return 0;
+ }
+ s+=cnv;
+ } while (1);
+
+bs:
+
+#ifdef NOT_USED
+ if (base <= 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ overflow = 0;
+ res = 0;
+ save = s;
+ cutoff = ((ulong)~0L) / (unsigned long int) base;
+ cutlim = (uint) (((ulong)~0L) % (unsigned long int) base);
+
+ do {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ s+=cnv;
+ if ( wc>='0' && wc<='9')
+ wc -= '0';
+ else if ( wc>='A' && wc<='Z')
+ wc = wc - 'A' + 10;
+ else if ( wc>='a' && wc<='z')
+ wc = wc - 'a' + 10;
+ else
+ break;
+ if ((int)wc >= base)
+ break;
+ if (res > cutoff || (res == cutoff && wc > cutlim))
+ overflow = 1;
+ else
+ {
+ res *= (ulong) base;
+ res += wc;
+ }
+ }
+ else if (cnv==MY_CS_ILSEQ)
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0]=EILSEQ;
+ return 0;
+ }
+ else
+ {
+ /* No more characters */
+ break;
+ }
+ } while(1);
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (s == save)
+ {
+ err[0]=EDOM;
+ return 0L;
+ }
+
+ if (negative)
+ {
+ if (res > (ulong) LONG_MIN)
+ overflow = 1;
+ }
+ else if (res > (ulong) LONG_MAX)
+ overflow = 1;
+
+ if (overflow)
+ {
+ err[0]=ERANGE;
+ return negative ? LONG_MIN : LONG_MAX;
+ }
+
+ return (negative ? -((long) res) : (long) res);
+}
+
+
+ulong my_strntoul_ucs2(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative=0;
+ int overflow;
+ int cnv;
+ my_wc_t wc;
+ register unsigned int cutlim;
+ register ulong cutoff;
+ register ulong res;
+ register const uchar *s= (const uchar*) nptr;
+ register const uchar *e= (const uchar*) nptr+l;
+ const uchar *save;
+
+ *err= 0;
+ do
+ {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ switch (wc)
+ {
+ case ' ' : break;
+ case '\t': break;
+ case '-' : negative= !negative; break;
+ case '+' : break;
+ default : goto bs;
+ }
+ }
+ else /* No more characters or bad multibyte sequence */
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0] = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM;
+ return 0;
+ }
+ s+=cnv;
+ } while (1);
+
+bs:
+
+#ifdef NOT_USED
+ if (base <= 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ overflow = 0;
+ res = 0;
+ save = s;
+ cutoff = ((ulong)~0L) / (unsigned long int) base;
+ cutlim = (uint) (((ulong)~0L) % (unsigned long int) base);
+
+ do
+ {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ s+=cnv;
+ if ( wc>='0' && wc<='9')
+ wc -= '0';
+ else if ( wc>='A' && wc<='Z')
+ wc = wc - 'A' + 10;
+ else if ( wc>='a' && wc<='z')
+ wc = wc - 'a' + 10;
+ else
+ break;
+ if ((int)wc >= base)
+ break;
+ if (res > cutoff || (res == cutoff && wc > cutlim))
+ overflow = 1;
+ else
+ {
+ res *= (ulong) base;
+ res += wc;
+ }
+ }
+ else if (cnv==MY_CS_ILSEQ)
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0]=EILSEQ;
+ return 0;
+ }
+ else
+ {
+ /* No more characters */
+ break;
+ }
+ } while(1);
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (s == save)
+ {
+ err[0]=EDOM;
+ return 0L;
+ }
+
+ if (overflow)
+ {
+ err[0]=(ERANGE);
+ return ((ulong)~0L);
+ }
+
+ return (negative ? -((long) res) : (long) res);
+
+}
+
+
+
+longlong my_strntoll_ucs2(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative=0;
+ int overflow;
+ int cnv;
+ my_wc_t wc;
+ register ulonglong cutoff;
+ register unsigned int cutlim;
+ register ulonglong res;
+ register const uchar *s= (const uchar*) nptr;
+ register const uchar *e= (const uchar*) nptr+l;
+ const uchar *save;
+
+ *err= 0;
+ do
+ {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ switch (wc)
+ {
+ case ' ' : break;
+ case '\t': break;
+ case '-' : negative= !negative; break;
+ case '+' : break;
+ default : goto bs;
+ }
+ }
+ else /* No more characters or bad multibyte sequence */
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0] = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM;
+ return 0;
+ }
+ s+=cnv;
+ } while (1);
+
+bs:
+
+#ifdef NOT_USED
+ if (base <= 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ overflow = 0;
+ res = 0;
+ save = s;
+ cutoff = (~(ulonglong) 0) / (unsigned long int) base;
+ cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
+
+ do {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ s+=cnv;
+ if ( wc>='0' && wc<='9')
+ wc -= '0';
+ else if ( wc>='A' && wc<='Z')
+ wc = wc - 'A' + 10;
+ else if ( wc>='a' && wc<='z')
+ wc = wc - 'a' + 10;
+ else
+ break;
+ if ((int)wc >= base)
+ break;
+ if (res > cutoff || (res == cutoff && wc > cutlim))
+ overflow = 1;
+ else
+ {
+ res *= (ulonglong) base;
+ res += wc;
+ }
+ }
+ else if (cnv==MY_CS_ILSEQ)
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0]=EILSEQ;
+ return 0;
+ }
+ else
+ {
+ /* No more characters */
+ break;
+ }
+ } while(1);
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (s == save)
+ {
+ err[0]=EDOM;
+ return 0L;
+ }
+
+ if (negative)
+ {
+ if (res > (ulonglong) LONGLONG_MIN)
+ overflow = 1;
+ }
+ else if (res > (ulonglong) LONGLONG_MAX)
+ overflow = 1;
+
+ if (overflow)
+ {
+ err[0]=ERANGE;
+ return negative ? LONGLONG_MIN : LONGLONG_MAX;
+ }
+
+ return (negative ? -((longlong)res) : (longlong)res);
+}
+
+
+
+
+ulonglong my_strntoull_ucs2(CHARSET_INFO *cs,
+ const char *nptr, uint l, int base,
+ char **endptr, int *err)
+{
+ int negative=0;
+ int overflow;
+ int cnv;
+ my_wc_t wc;
+ register ulonglong cutoff;
+ register unsigned int cutlim;
+ register ulonglong res;
+ register const uchar *s= (const uchar*) nptr;
+ register const uchar *e= (const uchar*) nptr+l;
+ const uchar *save;
+
+ *err= 0;
+ do
+ {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ switch (wc)
+ {
+ case ' ' : break;
+ case '\t': break;
+ case '-' : negative= !negative; break;
+ case '+' : break;
+ default : goto bs;
+ }
+ }
+ else /* No more characters or bad multibyte sequence */
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0]= (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM;
+ return 0;
+ }
+ s+=cnv;
+ } while (1);
+
+bs:
+
+#ifdef NOT_USED
+ if (base <= 0 || base == 1 || base > 36)
+ base = 10;
+#endif
+
+ overflow = 0;
+ res = 0;
+ save = s;
+ cutoff = (~(ulonglong) 0) / (unsigned long int) base;
+ cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
+
+ do
+ {
+ if ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ {
+ s+=cnv;
+ if ( wc>='0' && wc<='9')
+ wc -= '0';
+ else if ( wc>='A' && wc<='Z')
+ wc = wc - 'A' + 10;
+ else if ( wc>='a' && wc<='z')
+ wc = wc - 'a' + 10;
+ else
+ break;
+ if ((int)wc >= base)
+ break;
+ if (res > cutoff || (res == cutoff && wc > cutlim))
+ overflow = 1;
+ else
+ {
+ res *= (ulonglong) base;
+ res += wc;
+ }
+ }
+ else if (cnv==MY_CS_ILSEQ)
+ {
+ if (endptr !=NULL )
+ *endptr = (char*)s;
+ err[0]= EILSEQ;
+ return 0;
+ }
+ else
+ {
+ /* No more characters */
+ break;
+ }
+ } while(1);
+
+ if (endptr != NULL)
+ *endptr = (char *) s;
+
+ if (s == save)
+ {
+ err[0]= EDOM;
+ return 0L;
+ }
+
+ if (overflow)
+ {
+ err[0]= ERANGE;
+ return (~(ulonglong) 0);
+ }
+
+ return (negative ? -((longlong) res) : (longlong) res);
+}
+
+
+double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ char *nptr, uint length,
+ char **endptr, int *err)
+{
+ char buf[256];
+ double res;
+ register char *b=buf;
+ register const uchar *s= (const uchar*) nptr;
+ register const uchar *end;
+ my_wc_t wc;
+ int cnv;
+
+ *err= 0;
+ /* Cut too long strings */
+ if (length >= sizeof(buf))
+ length= sizeof(buf)-1;
+ end= s+length;
+
+ while ((cnv=cs->mb_wc(cs,&wc,s,end)) > 0)
+ {
+ s+=cnv;
+ if (wc > (int) (uchar) 'e' || !wc)
+ break; /* Can't be part of double */
+ *b++=wc;
+ }
+ *b= 0;
+
+ errno= 0;
+ res=strtod(buf, endptr);
+ *err= errno;
+ if (endptr)
+ *endptr=(char*) (*endptr-buf+nptr);
+ return res;
+}
+
+
+/*
+ This is a fast version optimized for the case of radix 10 / -10
+*/
+
+int my_l10tostr_ucs2(CHARSET_INFO *cs,
+ char *dst, uint len, int radix, long int val)
+{
+ char buffer[66];
+ register char *p, *db, *de;
+ long int new_val;
+ int sl=0;
+
+ p = &buffer[sizeof(buffer)-1];
+ *p='\0';
+
+ if (radix < 0)
+ {
+ if (val < 0)
+ {
+ sl = 1;
+ val = -val;
+ }
+ }
+
+ new_val = (long) ((unsigned long int) val / 10);
+ *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10);
+ val = new_val;
+
+ while (val != 0)
+ {
+ new_val=val/10;
+ *--p = '0' + (char) (val-new_val*10);
+ val= new_val;
+ }
+
+ if (sl)
+ {
+ *--p='-';
+ }
+
+ for ( db=dst, de=dst+len ; (dst<de) && *p ; p++)
+ {
+ int cnvres=cs->wc_mb(cs,(my_wc_t)p[0],(uchar*) dst, (uchar*) de);
+ if (cnvres>0)
+ dst+=cnvres;
+ else
+ break;
+ }
+ return (int) (dst-db);
+}
+
+int my_ll10tostr_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ char *dst, uint len, int radix, longlong val)
+{
+ char buffer[65];
+ register char *p, *db, *de;
+ long long_val;
+ int sl=0;
+
+ if (radix < 0)
+ {
+ if (val < 0)
+ {
+ sl=1;
+ val = -val;
+ }
+ }
+
+ p = &buffer[sizeof(buffer)-1];
+ *p='\0';
+
+ if (val == 0)
+ {
+ *--p='0';
+ goto cnv;
+ }
+
+ while ((ulonglong) val > (ulonglong) LONG_MAX)
+ {
+ ulonglong quo=(ulonglong) val/(uint) 10;
+ uint rem= (uint) (val- quo* (uint) 10);
+ *--p = '0' + rem;
+ val= quo;
+ }
+
+ long_val= (long) val;
+ while (long_val != 0)
+ {
+ long quo= long_val/10;
+ *--p = '0' + (long_val - quo*10);
+ long_val= quo;
+ }
+
+cnv:
+ if (sl)
+ {
+ *--p='-';
+ }
+
+ for ( db=dst, de=dst+len ; (dst<de) && *p ; p++)
+ {
+ int cnvres=cs->wc_mb(cs, (my_wc_t) p[0], (uchar*) dst, (uchar*) de);
+ if (cnvres>0)
+ dst+=cnvres;
+ else
+ break;
+ }
+ return (int) (dst-db);
+}
+
+static
+uint my_numchars_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b, const char *e)
+{
+ return (e-b)/2;
+}
+
+static
+uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b __attribute__((unused)),
+ const char *e __attribute__((unused)),
+ uint pos)
+{
+ return pos*2;
+}
+
+CHARSET_INFO my_charset_ucs2 =
+{
+ 35, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ "ucs2", /* cs name */
+ "ucs2", /* name */
+ "", /* comment */
+ ctype_ucs2, /* ctype */
+ to_lower_ucs2, /* to_lower */
+ to_upper_ucs2, /* to_upper */
+ to_upper_ucs2, /* sort_order */
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ 1, /* strxfrm_multiply */
+ my_strnncoll_ucs2, /* strnncoll */
+ my_strnncoll_ucs2,
+ my_strnxfrm_ucs2, /* strnxfrm */
+ my_like_range_simple,/* like_range */
+ my_wildcmp_mb, /* wildcmp */
+ 2, /* mbmaxlen */
+ my_ismbchar_ucs2, /* ismbchar */
+ my_ismbhead_ucs2, /* ismbhead */
+ my_mbcharlen_ucs2, /* mbcharlen */
+ my_numchars_ucs2,
+ my_charpos_ucs2,
+ my_ucs2_uni, /* mb_wc */
+ my_uni_ucs2, /* wc_mb */
+ my_caseup_str_ucs2,
+ my_casedn_str_ucs2,
+ my_caseup_ucs2,
+ my_casedn_ucs2,
+ NULL, /* tosort */
+ my_strcasecmp_ucs2,
+ my_strncasecmp_ucs2,
+ my_hash_caseup_ucs2,/* hash_caseup */
+ my_hash_sort_ucs2, /* hash_sort */
+ 0,
+ my_snprintf_ucs2,
+ my_l10tostr_ucs2,
+ my_ll10tostr_ucs2,
+ my_fill_8bit,
+ my_strntol_ucs2,
+ my_strntoul_ucs2,
+ my_strntoll_ucs2,
+ my_strntoull_ucs2,
+ my_strntod_ucs2,
+ my_scan_8bit
+};
+
+
+#endif
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
new file mode 100644
index 00000000000..467d1ba4c91
--- /dev/null
+++ b/strings/ctype-win1250ch.c
@@ -0,0 +1,693 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/*
+ Shared, independent copyright: (C) 2001 Jan Pazdziora.
+
+ Development of this software was supported by Neocortex, s.r.o.
+ MySQL AB expresses its gratitude to Jan for for giving us this software.
+
+ Bug reports and suggestions are always welcome.
+
+ This file implements the collating sequence for Windows-1250
+ character set. It merely extends the binary sorting of US-ASCII
+ by adding characters with diacritical marks into proper places.
+ In addition, it sorts 'ch' between 'h' and 'i', and the sorting
+ is case sensitive, with uppercase being sorted first, in the
+ second pass.
+*/
+
+/*
+ * This comment is parsed by configure to create ctype.c,
+ * so don't change it unless you know what you are doing.
+ *
+ * .configure. strxfrm_multiply_win1250ch=2
+ */
+
+#define REAL_MYSQL
+
+#ifdef REAL_MYSQL
+
+#include "my_global.h"
+#include "m_string.h"
+#include "m_ctype.h"
+
+static uint16 tab_cp1250_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x20AC, 0,0x201A, 0,0x201E,0x2026,0x2020,0x2021,
+ 0,0x2030,0x0160,0x2039,0x015A,0x0164,0x017D,0x0179,
+ 0,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
+ 0,0x2122,0x0161,0x203A,0x015B,0x0165,0x017E,0x017A,
+0x00A0,0x02C7,0x02D8,0x0141,0x00A4,0x0104,0x00A6,0x00A7,
+0x00A8,0x00A9,0x015E,0x00AB,0x00AC,0x00AD,0x00AE,0x017B,
+0x00B0,0x00B1,0x02DB,0x0142,0x00B4,0x00B5,0x00B6,0x00B7,
+0x00B8,0x0105,0x015F,0x00BB,0x013D,0x02DD,0x013E,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
+};
+
+
+/* 0000-00FD , 254 chars */
+static uchar tab_uni_cp1250_plane00[]={
+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,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,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,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xA0,0x00,0x00,0x00,0xA4,0x00,0xA6,0xA7,0xA8,0xA9,0x00,0xAB,0xAC,0xAD,0xAE,0x00,
+0xB0,0xB1,0x00,0x00,0xB4,0xB5,0xB6,0xB7,0xB8,0x00,0x00,0xBB,0x00,0x00,0x00,0x00,
+0x00,0xC1,0xC2,0x00,0xC4,0x00,0x00,0xC7,0x00,0xC9,0x00,0xCB,0x00,0xCD,0xCE,0x00,
+0x00,0x00,0x00,0xD3,0xD4,0x00,0xD6,0xD7,0x00,0x00,0xDA,0x00,0xDC,0xDD,0x00,0xDF,
+0x00,0xE1,0xE2,0x00,0xE4,0x00,0x00,0xE7,0x00,0xE9,0x00,0xEB,0x00,0xED,0xEE,0x00,
+0x00,0x00,0x00,0xF3,0xF4,0x00,0xF6,0xF7,0x00,0x00,0xFA,0x00,0xFC,0xFD};
+
+/* 0102-017E , 125 chars */
+static uchar tab_uni_cp1250_plane01[]={
+0xC3,0xE3,0xA5,0xB9,0xC6,0xE6,0x00,0x00,0x00,0x00,0xC8,0xE8,0xCF,0xEF,0xD0,0xF0,
+0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xE5,0x00,0x00,0xBC,0xBE,0x00,0x00,0xA3,
+0xB3,0xD1,0xF1,0x00,0x00,0xD2,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD5,0xF5,
+0x00,0x00,0xC0,0xE0,0x00,0x00,0xD8,0xF8,0x8C,0x9C,0x00,0x00,0xAA,0xBA,0x8A,0x9A,
+0xDE,0xFE,0x8D,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xF9,0xDB,0xFB,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x9F,0xAF,0xBF,0x8E,0x9E};
+
+/* 2013-20AC , 154 chars */
+static uchar tab_uni_cp1250_plane20[]={
+0x96,0x97,0x00,0x00,0x00,0x91,0x92,0x82,0x00,0x93,0x94,0x84,0x00,0x86,0x87,0x95,
+0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80};
+
+/* 02C7-02DD , 23 chars */
+static uchar tab_uni_cp1250_plane02[]={
+0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0xA2,0xFF,0x00,0xB2,0x00,0xBD};
+
+/* 2122-2122 , 1 chars */
+static uchar tab_uni_cp1250_plane21[]={
+0x99};
+
+
+static MY_UNI_IDX idx_uni_cp1250[]={
+ {0x0000,0x00FD,tab_uni_cp1250_plane00},
+ {0x0102,0x017E,tab_uni_cp1250_plane01},
+ {0x2013,0x20AC,tab_uni_cp1250_plane20},
+ {0x02C7,0x02DD,tab_uni_cp1250_plane02},
+ {0x2122,0x2122,tab_uni_cp1250_plane21},
+ {0,0,NULL}
+};
+
+
+static uchar NEAR ctype_win1250ch[] = {
+0x00,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x48, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x20,
+0x20, 0x20, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10,
+0x20, 0x10, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x20, 0x10, 0x02, 0x10, 0x02, 0x02, 0x02, 0x02,
+0x48, 0x10, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
+0x10, 0x10, 0x01, 0x10, 0x10, 0x10, 0x10, 0x01,
+0x10, 0x10, 0x10, 0x02, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x02, 0x02, 0x10, 0x01, 0x10, 0x02, 0x02,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10
+};
+
+static uchar NEAR to_lower_win1250ch[] = {
+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, 0x5b, 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, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f,
+0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xb9, 0xa6, 0xdf,
+0xa8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf,
+0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+0xb8, 0xb9, 0xba, 0xbb, 0xbe, 0xbd, 0xbe, 0xbf,
+0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7,
+0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 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
+};
+
+static uchar NEAR to_upper_win1250ch[] = {
+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, 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, 0x5d, 0x5e, 0x5f,
+0x60, 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, 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, 0x8a, 0x9b, 0x8c, 0x8d, 0x8e, 0x8f,
+0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+0xb0, 0xb1, 0xb2, 0xa3, 0xb4, 0xb5, 0xb6, 0xb7,
+0xb8, 0xa5, 0xaa, 0xbb, 0xbc, 0xbd, 0xbc, 0xaf,
+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, 0xa7,
+0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7,
+0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff
+};
+
+#else
+
+#include <stdio.h>
+#define uchar unsigned char
+
+#endif
+
+
+static uchar NEAR sort_order_win1250ch[] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+};
+
+static uchar NEAR _sort_order_win1250ch1[] = {
+0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+/* space ord 32 0x20 */
+0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91,
+/* 0 ord 48 0x30 */
+0x92, 0x93, 0x94, 0x95, 0x95, 0x97, 0x98, 0x99,
+0x9a, 0x9b,
+ /* colon ord 58 0x3a */
+ 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1,
+0xa2,
+ /* A ord 65 0x41 */
+ 0xa4, 0xa5,
+ /* C ord 67 0x43 */
+ 0xff, 0xa8, 0xa9, 0xaa, 0xab,
+0xac, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
+0xb5, 0xb6,
+ /* R ord 82 0x52 */
+ 0xb7,
+ /* S ord 83 0x53 */
+ 0xb9, 0xbc, 0xbd, 0xbe, 0xbf,
+0xc0, 0xc1, 0xc2,
+ /* [ ord 91 0x5b */
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+0xc9,
+ /* a ord 97 0x61 */
+ 0xa4, 0xa5, 0xff, 0xa8, 0xa9, 0xaa, 0xab,
+0xac, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
+0xb5, 0xb6, 0xb7, 0xb9, 0xbc, 0xbd, 0xbe, 0xbf,
+0xc0, 0xc1, 0xc2,
+ /* { ord 123 0x7b */
+ 0xca, 0xcb, 0xcc, 0xcd, 0x81,
+0x81, 0x81, 0xce, 0x81, 0xcf, 0xd0, 0xd1, 0xd2,
+0x81, 0xd3,
+ /* Scaron ord 138 0x8a */
+ 0xba, 0xd4, 0xb9, 0xbc, 0xc3, 0xc2,
+0x81, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
+0x81, 0xdc, 0xba, 0xdd, 0xb9, 0xbc, 0xc3, 0xc2,
+/* nobreakspace ord 160 0xa0 */
+0x82, 0xde, 0xdf, 0xb1, 0xe0, 0xa4, 0xe1, 0xe2,
+0xe3, 0xe4, 0xb9, 0xe5, 0xe6, 0xe7, 0xe8, 0xc2,
+0xe9, 0xea, 0xeb, 0xb1, 0xed, 0xee, 0x81, 0xef,
+/* cedilla ord 183 0xb8 */
+0xf0, 0xa4, 0xb9, 0xf1, 0xb1, 0xf2, 0xb1, 0xc2,
+0xb7, 0xa4, 0xa4, 0xa4, 0xa4, 0xb1, 0xa6, 0xa6,
+0xa7, 0xa9, 0xa9, 0xa9, 0xa9, 0xae, 0xae, 0xa8,
+/* Eth ord 208 0xd0 */
+0xa8, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xf3,
+0xb8, 0xbd, 0xbd, 0xbd, 0xbd, 0xc1, 0xbc, 0xbb,
+/* racute ord 224 0xe0 */
+0xb7, 0xa4, 0xa4, 0xa4, 0xa4, 0xb1, 0xa6, 0xa6,
+0xa7, 0xa9, 0xa9, 0xa9, 0xa9, 0xae, 0xae, 0xa8,
+/* eth ord 240 0xf0 */
+0xa8, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xf4,
+0xb8, 0xbd, 0xbd, 0xbd, 0xbd, 0xc1, 0xbc, 0xf5
+};
+
+static uchar NEAR _sort_order_win1250ch2[] = {
+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,
+/* space ord 32 0x20 */
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+/* 0 ord 48 0x30 */
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01,
+ /* colon ord 58 0x3a */
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01,
+ /* A ord 65 0x41 */
+ 0x01, 0x01,
+ /* C ord 67 0x43 */
+ 0xff, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01,
+ /* R ord 82 0x52 */
+ 0x01,
+ /* S ord 83 0x53 */
+ 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01,
+ /* [ ord 91 0x5b */
+ 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01,
+ /* a ord 97 0x61 */
+ 0x02, 0x02, 0xff, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02,
+ /* { ord 123 0x7b */
+ 0x01, 0x01, 0x01, 0x01, 0x22,
+0x23, 0x24, 0x01, 0x25, 0x01, 0x01, 0x01, 0x01,
+0x26, 0x01,
+ /* Scaron ord 138 0x8a */
+ 0x01, 0x01, 0x03, 0x03, 0x01, 0x05,
+0x27, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x28, 0x01, 0x02, 0x01, 0x04, 0x04, 0x02, 0x06,
+/* nobreakspace ord 160 0xa0 */
+0x02, 0x01, 0x01, 0x07, 0x01, 0x11, 0x01, 0x01,
+0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x03,
+0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x29, 0x01,
+/* cedilla ord 184 0xb8 */
+0x01, 0x12, 0x06, 0x01, 0x05, 0x01, 0x06, 0x04,
+0x03, 0x03, 0x05, 0x07, 0x09, 0x03, 0x03, 0x05,
+0x01, 0x03, 0x09, 0x07, 0x05, 0x03, 0x05, 0x03,
+/* Eth ord 208 0xd0 */
+0x05, 0x03, 0x05, 0x03, 0x05, 0x09, 0x07, 0x01,
+0x01, 0x05, 0x03, 0x09, 0x07, 0x03, 0x05, 0x01,
+/* racute ord 224 0xe0 */
+0x04, 0x04, 0x06, 0x08, 0x0a, 0x04, 0x04, 0x06,
+0x02, 0x04, 0x0a, 0x08, 0x06, 0x04, 0x06, 0x04,
+/* eth ord 240 0xf0 */
+0x06, 0x04, 0x06, 0x04, 0x06, 0x0a, 0x08, 0x01,
+0x02, 0x06, 0x04, 0x0a, 0x08, 0x04, 0x06, 0x01
+};
+
+struct wordvalue {
+ const uchar * word;
+ uchar pass1;
+ uchar pass2;
+};
+static struct wordvalue doubles[] = {
+ { (uchar*) "ch", 0xad, 0x03 },
+ { (uchar*) "c", 0xa6, 0x02 },
+ { (uchar*) "Ch", 0xad, 0x02 },
+ { (uchar*) "CH", 0xad, 0x01 },
+ { (uchar*) "C", 0xa6, 0x01 },
+};
+
+#define NEXT_CMP_VALUE(src, p, pass, value, len) \
+ while (1) { \
+ if (IS_END(p, src, len)) { \
+ if (pass == 0) { p = src; pass++; } \
+ else { value = 0; break; } \
+ } \
+ value = ((pass == 0) ? _sort_order_win1250ch1[*p] \
+ : _sort_order_win1250ch2[*p]); \
+ if (value == 0xff) { \
+ int i; \
+ for (i = 0; i < (int) sizeof(doubles); i++) { \
+ const uchar * patt = doubles[i].word; \
+ const uchar * q = (const uchar *) p; \
+ while (*patt \
+ && !(IS_END(q, src, len)) \
+ && (*patt == *q)) { \
+ patt++; q++; \
+ } \
+ if (!(*patt)) { \
+ value = (int)((pass == 0) \
+ ? doubles[i].pass1 \
+ : doubles[i].pass2); \
+ p = (const uchar *) q - 1; \
+ break; \
+ } \
+ } \
+ } \
+ p++; \
+ break; \
+ }
+
+#define IS_END(p, src, len) (!(*p))
+
+#if UNUSED
+static int my_strcoll_win1250ch(const uchar * s1, const uchar * s2) {
+ int v1, v2;
+ const uchar * p1, * p2;
+ int pass1 = 0, pass2 = 0;
+ int diff;
+
+ p1 = s1; p2 = s2;
+
+ do {
+ NEXT_CMP_VALUE(s1, p1, pass1, v1, 0);
+ NEXT_CMP_VALUE(s2, p2, pass2, v2, 0);
+ diff = v1 - v2;
+ if (diff != 0) return diff;
+ } while (v1);
+ return 0;
+}
+#endif
+
+#ifdef UNUSED
+static int my_strxfrm_win1250ch(uchar * dest, const uchar * src, int len) {
+ int value;
+ const uchar * p;
+ int pass = 0;
+ int totlen = 0;
+ p = src;
+
+ do {
+ NEXT_CMP_VALUE(src, p, pass, value, 0);
+ if (totlen <= len)
+ dest[totlen] = value;
+ totlen++;
+ } while (value);
+ return totlen;
+}
+#endif
+
+#undef IS_END
+
+#define IS_END(p, src, len) (((char *)p - (char *)src) >= (len))
+
+static int my_strnncoll_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar * s1, uint len1,
+ const uchar * s2, uint len2) {
+ int v1, v2;
+ const uchar * p1, * p2;
+ int pass1 = 0, pass2 = 0;
+ int diff;
+
+ p1 = s1; p2 = s2;
+
+ do {
+ NEXT_CMP_VALUE(s1, p1, pass1, v1, (int)len1);
+ NEXT_CMP_VALUE(s2, p2, pass2, v2, (int)len2);
+ diff = v1 - v2;
+ if (diff != 0) return diff;
+ } while (v1);
+ return 0;
+}
+
+static
+int my_strnncollsp_win1250ch(CHARSET_INFO * cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--);
+ for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--);
+ return my_strnncoll_win1250ch(cs,s,slen,t,tlen);
+}
+
+
+static int my_strnxfrm_win1250ch(CHARSET_INFO * cs __attribute__((unused)),
+ uchar * dest, uint len,
+ const uchar * src, uint srclen) {
+ int value;
+ const uchar * p;
+ int pass = 0;
+ uint totlen = 0;
+ p = src;
+
+ do {
+ NEXT_CMP_VALUE(src, p, pass, value, (int)srclen);
+ if (totlen <= len)
+ dest[totlen] = value;
+ totlen++;
+ } while (value) ;
+ return totlen;
+}
+
+#undef IS_END
+
+
+#ifdef REAL_MYSQL
+
+static uchar NEAR like_range_prefix_min_win1250ch[] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+96, 54, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 165, 124, 125, 126, 0,
+0, 0, 130, 0, 132, 133, 134, 135, 0, 137, 138, 139, 83, 84, 142, 90,
+0, 145, 146, 147, 148, 149, 150, 151, 0, 153, 138, 155, 83, 84, 142, 90,
+32, 161, 162, 76, 164, 165, 166, 167, 168, 65, 83, 171, 172, 173, 174, 90,
+176, 177, 178, 76, 180, 181, 0, 183, 184, 65, 83, 187, 76, 189, 76, 90,
+82, 65, 65, 65, 65, 76, 67, 67, 200, 69, 69, 69, 69, 73, 73, 68,
+68, 78, 78, 79, 79, 79, 79, 215, 216, 85, 85, 85, 85, 89, 84, 223,
+82, 65, 65, 65, 65, 76, 67, 67, 200, 69, 69, 69, 69, 73, 73, 68,
+68, 78, 78, 79, 79, 79, 79, 247, 216, 85, 85, 85, 85, 89, 84, 255,
+};
+static uchar NEAR like_range_prefix_max_win1250ch[] = {
+182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+160, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+64, 185, 98, 73, 240, 234, 102, 103, 104, 238, 106, 107, 179, 109, 242, 245,
+112, 113, 224, 186, 254, 251, 118, 119, 120, 253, 159, 91, 92, 93, 94, 95,
+96, 54, 98, 73, 240, 234, 102, 103, 104, 238, 106, 107, 179, 109, 242, 245,
+112, 113, 224, 186, 254, 251, 118, 119, 120, 253, 159, 165, 124, 125, 126, 182,
+182, 182, 130, 182, 132, 133, 134, 135, 182, 137, 154, 139, 186, 254, 158, 159,
+182, 145, 146, 147, 148, 149, 150, 151, 182, 153, 154, 155, 186, 254, 158, 159,
+32, 161, 162, 179, 164, 165, 166, 167, 168, 185, 186, 171, 172, 173, 174, 159,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 179, 189, 179, 159,
+224, 185, 185, 185, 185, 179, 238, 238, 200, 234, 234, 234, 234, 238, 238, 240,
+240, 242, 242, 245, 245, 245, 245, 215, 248, 251, 251, 251, 251, 253, 254, 223,
+224, 185, 185, 185, 185, 179, 238, 238, 200, 234, 234, 234, 234, 238, 238, 240,
+240, 242, 242, 245, 245, 245, 245, 247, 248, 251, 251, 251, 251, 253, 254, 255,
+};
+
+#define min_sort_char '\x00'
+#define max_sort_char '\xff'
+
+/*
+** Calculate min_str and max_str that ranges a LIKE string.
+** Arguments:
+** ptr Pointer to LIKE string.
+** ptr_length Length of LIKE string.
+** escape Escape character in LIKE. (Normally '\').
+** All escape characters should be removed from min_str and max_str
+** res_length Length of min_str and max_str.
+** min_str Smallest case sensitive string that ranges LIKE.
+** Should be space padded to res_length.
+** max_str Largest case sensitive string that ranges LIKE.
+** Normally padded with the biggest character sort value.
+**
+** The function should return 0 if ok and 1 if the LIKE string can't be
+** optimized !
+*/
+
+static my_bool my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
+ const char *ptr, uint ptr_length,
+ int escape, int w_one, int w_many,
+ uint res_length,
+ char *min_str, char *max_str,
+ uint *min_length, uint *max_length) {
+
+ int was_other_than_min = 0;
+ const char *end = ptr + ptr_length;
+ char *min_org = min_str;
+ char *min_end = min_str + res_length;
+
+ /* return 1; */
+
+ for (; ptr != end && min_str != min_end ; ptr++) {
+ if (*ptr == w_one) { /* '_' in SQL */
+ break;
+ }
+ if (*ptr == w_many) { /* '%' in SQL */
+ break;
+ }
+ if (*ptr == escape && ptr + 1 != end) { /* Skip escape */
+ ptr++;
+ }
+ *min_str = like_range_prefix_min_win1250ch[(uint)(*ptr)];
+ if (*min_str != min_sort_char) {
+ was_other_than_min = 1;
+ }
+ min_str++;
+ *max_str++ = like_range_prefix_max_win1250ch[(uint)(*ptr)];
+ }
+
+ *min_length = (uint) (min_str - min_org);
+ *max_length = res_length;
+ while (min_str != min_end) {
+ *min_str++ = min_sort_char;
+ *max_str++ = max_sort_char;
+ }
+ if (! was_other_than_min) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+CHARSET_INFO my_charset_win1250ch =
+{
+ 34, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */
+ "cp1250", /* cs name */
+ "cp1250_czech", /* name */
+ "", /* comment */
+ ctype_win1250ch,
+ to_lower_win1250ch,
+ to_upper_win1250ch,
+ sort_order_win1250ch,
+ tab_cp1250_uni, /* tab_to_uni */
+ idx_uni_cp1250, /* tab_from_uni */
+ 2, /* strxfrm_multiply */
+ my_strnncoll_win1250ch,
+ my_strnncollsp_win1250ch,
+ my_strnxfrm_win1250ch,
+ my_like_range_win1250ch,
+ my_wildcmp_8bit, /* wildcmp */
+ 1, /* mbmaxlen */
+ NULL, /* ismbchar */
+ NULL, /* ismbhead */
+ NULL, /* mbcharlen */
+ my_numchars_8bit,
+ my_charpos_8bit,
+ my_mb_wc_8bit, /* mb_wc */
+ my_wc_mb_8bit, /* wc_mb */
+ my_caseup_str_8bit,
+ my_casedn_str_8bit,
+ my_caseup_8bit,
+ my_casedn_8bit,
+ NULL, /* tosort */
+ my_strcasecmp_8bit,
+ my_strncasecmp_8bit,
+ my_hash_caseup_simple,
+ my_hash_sort_simple,
+ 0,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_scan_8bit
+};
+
+
+#endif
diff --git a/strings/ctype.c b/strings/ctype.c
index 8e3571b1b88..4f6d34ddd7a 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -16,54 +16,232 @@
#include <my_global.h>
#include <m_ctype.h>
+#include <my_xml.h>
#ifndef SCO
#include <m_string.h>
#endif
-/* generated by make, using conf_to_src */
-#include "ctype_extra_sources.c"
-/* generated by configure */
-#include "ctype_autoconf.c"
-CHARSET_INFO *default_charset_info = &compiled_charsets[0];
+static char *mstr(char *str,const char *src,uint l1,uint l2)
+{
+ l1= l1<l2 ? l1 : l2;
+ memcpy(str,src,l1);
+ str[l1]='\0';
+ return str;
+}
+
+
+struct my_cs_file_section_st
+{
+ int state;
+ const char *str;
+};
+
+#define _CS_MISC 1
+#define _CS_ID 2
+#define _CS_CSNAME 3
+#define _CS_FAMILY 4
+#define _CS_ORDER 5
+#define _CS_COLNAME 6
+#define _CS_FLAG 7
+#define _CS_CHARSET 8
+#define _CS_COLLATION 9
+#define _CS_UPPERMAP 10
+#define _CS_LOWERMAP 11
+#define _CS_UNIMAP 12
+#define _CS_COLLMAP 13
+#define _CS_CTYPEMAP 14
-CHARSET_INFO *find_compiled_charset(uint cs_number)
+static struct my_cs_file_section_st sec[] =
{
- CHARSET_INFO *cs;
- for (cs = compiled_charsets; cs->number > 0; cs++)
- if (cs->number == cs_number)
- return cs;
+ {_CS_MISC, "xml"},
+ {_CS_MISC, "xml.version"},
+ {_CS_MISC, "xml.encoding"},
+ {_CS_MISC, "charsets"},
+ {_CS_MISC, "charsets.max-id"},
+ {_CS_MISC, "charsets.description"},
+ {_CS_CHARSET, "charsets.charset"},
+ {_CS_CSNAME, "charsets.charset.name"},
+ {_CS_FAMILY, "charsets.charset.family"},
+ {_CS_MISC, "charsets.charset.alias"},
+ {_CS_MISC, "charsets.charset.ctype"},
+ {_CS_CTYPEMAP, "charsets.charset.ctype.map"},
+ {_CS_MISC, "charsets.charset.upper"},
+ {_CS_UPPERMAP, "charsets.charset.upper.map"},
+ {_CS_MISC, "charsets.charset.lower"},
+ {_CS_LOWERMAP, "charsets.charset.lower.map"},
+ {_CS_MISC, "charsets.charset.unicode"},
+ {_CS_UNIMAP, "charsets.charset.unicode.map"},
+ {_CS_COLLATION, "charsets.charset.collation"},
+ {_CS_COLNAME, "charsets.charset.collation.name"},
+ {_CS_ID, "charsets.charset.collation.id"},
+ {_CS_ORDER, "charsets.charset.collation.order"},
+ {_CS_FLAG, "charsets.charset.collation.flag"},
+ {_CS_COLLMAP, "charsets.charset.collation.map"},
+ {0, NULL}
+};
+static struct my_cs_file_section_st * cs_file_sec(const char *attr, uint len)
+{
+ struct my_cs_file_section_st *s;
+ for (s=sec; s->str; s++)
+ {
+ if (!strncmp(attr,s->str,len))
+ return s;
+ }
return NULL;
}
-CHARSET_INFO *find_compiled_charset_by_name(const char *name)
+typedef struct my_cs_file_info
{
- CHARSET_INFO *cs;
- for (cs = compiled_charsets; cs->number > 0; cs++)
- if (!strcmp(cs->name, name))
- return cs;
+ char csname[MY_CS_NAME_SIZE];
+ char name[MY_CS_NAME_SIZE];
+ uchar ctype[MY_CS_CTYPE_TABLE_SIZE];
+ uchar to_lower[MY_CS_TO_LOWER_TABLE_SIZE];
+ uchar to_upper[MY_CS_TO_UPPER_TABLE_SIZE];
+ uchar sort_order[MY_CS_SORT_ORDER_TABLE_SIZE];
+ uint16 tab_to_uni[MY_CS_TO_UNI_TABLE_SIZE];
+ CHARSET_INFO cs;
+ int (*add_collation)(CHARSET_INFO *cs);
+} MY_CHARSET_LOADER;
- return NULL;
+
+
+static int fill_uchar(uchar *a,uint size,const char *str, uint len)
+{
+ uint i= 0;
+ const char *s, *b, *e=str+len;
+
+ for (s=str ; s < e ; i++)
+ {
+ for ( ; (s < e) && strchr(" \t\r\n",s[0]); s++) ;
+ b=s;
+ for ( ; (s < e) && !strchr(" \t\r\n",s[0]); s++) ;
+ if (s == b || i > size)
+ break;
+ a[i]= (uchar) strtoul(b,NULL,16);
+ }
+ return 0;
+}
+
+static int fill_uint16(uint16 *a,uint size,const char *str, uint len)
+{
+ uint i= 0;
+
+ const char *s, *b, *e=str+len;
+ for (s=str ; s < e ; i++)
+ {
+ for ( ; (s < e) && strchr(" \t\r\n",s[0]); s++) ;
+ b=s;
+ for ( ; (s < e) && !strchr(" \t\r\n",s[0]); s++) ;
+ if (s == b || i > size)
+ break;
+ a[i]= (uint16) strtol(b,NULL,16);
+ }
+ return 0;
}
-uint compiled_charset_number(const char *name)
+
+static int cs_enter(MY_XML_PARSER *st,const char *attr, uint len)
{
- CHARSET_INFO *cs;
- for (cs = compiled_charsets; cs->number > 0; cs++)
- if (!strcmp(cs->name, name))
- return cs->number;
+ struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+
+ if ( s && (s->state == _CS_CHARSET))
+ {
+ bzero(&i->cs,sizeof(i->cs));
+ }
+ return MY_XML_OK;
+}
+
- return 0; /* this mimics find_type() */
+static int cs_leave(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+ int state= s ? s->state : 0;
+ int rc;
+
+ switch(state){
+ case _CS_COLLATION:
+ rc= i->add_collation ? i->add_collation(&i->cs) : MY_XML_OK;
+ break;
+ default:
+ rc=MY_XML_OK;
+ }
+ return rc;
}
-const char *compiled_charset_name(uint charset_number)
+
+static int cs_value(MY_XML_PARSER *st,const char *attr, uint len)
{
- CHARSET_INFO *cs;
- for (cs = compiled_charsets; cs->number > 0; cs++)
- if (cs->number == charset_number)
- return cs->name;
+ struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s;
+ int state= (s=cs_file_sec(st->attr,strlen(st->attr))) ? s->state : 0;
+
+#ifndef DBUG_OFF
+ if(0){
+ char str[1024];
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("VALUE %d %s='%s'\n",state,st->attr,str);
+ }
+#endif
+
+ switch (state) {
+ case _CS_ID:
+ i->cs.number= strtol(attr,(char**)NULL,10);
+ break;
+ case _CS_COLNAME:
+ i->cs.name=mstr(i->name,attr,len,MY_CS_NAME_SIZE-1);
+ break;
+ case _CS_CSNAME:
+ i->cs.csname=mstr(i->csname,attr,len,MY_CS_NAME_SIZE-1);
+ break;
+ case _CS_FLAG:
+ if (!strncmp("primary",attr,len))
+ i->cs.state|= MY_CS_PRIMARY;
+ break;
+ case _CS_UPPERMAP:
+ fill_uchar(i->to_upper,MY_CS_TO_UPPER_TABLE_SIZE,attr,len);
+ i->cs.to_upper=i->to_upper;
+ break;
+ case _CS_LOWERMAP:
+ fill_uchar(i->to_lower,MY_CS_TO_LOWER_TABLE_SIZE,attr,len);
+ i->cs.to_lower=i->to_lower;
+ break;
+ case _CS_UNIMAP:
+ fill_uint16(i->tab_to_uni,MY_CS_TO_UNI_TABLE_SIZE,attr,len);
+ i->cs.tab_to_uni=i->tab_to_uni;
+ break;
+ case _CS_COLLMAP:
+ fill_uchar(i->sort_order,MY_CS_SORT_ORDER_TABLE_SIZE,attr,len);
+ i->cs.sort_order=i->sort_order;
+ break;
+ case _CS_CTYPEMAP:
+ fill_uchar(i->ctype,MY_CS_CTYPE_TABLE_SIZE,attr,len);
+ i->cs.ctype=i->ctype;
+ break;
+ }
+ return MY_XML_OK;
+}
- return "?"; /* this mimics get_type() */
+
+my_bool my_parse_charset_xml(const char *buf, uint len,
+ int (*add_collation)(CHARSET_INFO *cs))
+{
+ MY_XML_PARSER p;
+ struct my_cs_file_info i;
+ my_bool rc;
+
+ my_xml_parser_create(&p);
+ my_xml_set_enter_handler(&p,cs_enter);
+ my_xml_set_value_handler(&p,cs_value);
+ my_xml_set_leave_handler(&p,cs_leave);
+ i.add_collation= add_collation;
+ my_xml_set_user_data(&p,(void*)&i);
+ rc= (my_xml_parse(&p,buf,len) == MY_XML_OK) ? FALSE : TRUE;
+ my_xml_parser_free(&p);
+ return rc;
}
+
diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s
index 98e60acbafb..3bfd1777e18 100644
--- a/strings/longlong2str-x86.s
+++ b/strings/longlong2str-x86.s
@@ -64,7 +64,7 @@ longlong2str:
jne .L150
movb $48,(%edi)
incl %edi
- jmp .L164
+ jmp .L10_end
.align 4
.L150:
@@ -81,9 +81,9 @@ longlong2str:
movl %eax,%ebp
movl %esi,%eax
divl %ebx
+ decl %ecx
movl %eax,%esi # quotent in ebp:esi
movb _dig_vec(%edx),%al # al is faster than dl
- decl %ecx
movb %al,(%ecx) # store value in buff
.align 4
.L155:
@@ -91,7 +91,7 @@ longlong2str:
ja .L153
testl %esi,%esi # rest value
jl .L153
- je .L160 # Ready
+ je .L10_mov # Ready
movl %esi,%eax
movl $_dig_vec,%ebp
.align 4
@@ -105,14 +105,14 @@ longlong2str:
movb %dl,(%ecx)
jne .L154
-.L160:
+.L10_mov:
movl %ecx,%esi
leal 92(%esp),%ecx # End of buffer
subl %esi,%ecx
rep
movsb
-.L164:
+.L10_end:
movl %edi,%eax # Pointer to end null
movb $0,(%edi) # Store the end null
@@ -131,10 +131,93 @@ longlong2str:
.Lfe3:
.size longlong2str,.Lfe3-longlong2str
+#
+# This is almost equal to the above, except that we can do the final
+# loop much more efficient
+#
+
+ .align 4
+.Ltmp:
+ .long 0xcccccccd
+ .align 4
+
.globl longlong10_to_str
.type longlong10_str,@function
longlong10_to_str:
- jmp longlong2str
+ subl $80,%esp
+ pushl %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ movl 100(%esp),%esi # Lower part of val
+ movl 104(%esp),%ebp # Higher part of val
+ movl 108(%esp),%edi # get dst
+ movl 112(%esp),%ebx # Radix (10 or -10)
+ testl %ebx,%ebx
+ jge .L10_10 # Positive radix
+
+ negl %ebx # Change radix to positive (= 10)
+
+ testl %ebp,%ebp # Test if negative value
+ jge .L10_10
+ movb $45,(%edi) # Add sign
+ incl %edi
+ negl %esi # Change sign of val (ebp:esi)
+ adcl $0,%ebp
+ negl %ebp
+ .align 4
+
+.L10_10:
+ leal 92(%esp),%ecx # End of buffer
+ movl %esi,%eax # Test if zero (for easy loop)
+ orl %ebp,%eax
+ jne .L10_30 # Not zero
+
+ # Here when value is zero
+ movb $48,(%edi)
+ incl %edi
+ jmp .L10_end
+ .align 4
+
+.L10_20:
+ # val is stored in in ebp:esi
+ movl %ebp,%eax # High part of value
+ xorl %edx,%edx
+ divl %ebx # Divide by 10
+ movl %eax,%ebp
+ movl %esi,%eax
+ divl %ebx # Divide by 10
+ decl %ecx
+ movl %eax,%esi # quotent in ebp:esi
+ addl $48,%edx # Convert to ascii
+ movb %dl,(%ecx) # store value in buff
+
+.L10_30:
+ testl %ebp,%ebp
+ ja .L10_20
+ testl %esi,%esi # rest value
+ jl .L10_20 # Unsigned, do ulonglong div once more
+ je .L10_mov # Ready
+ movl %esi,%ebx # Move val to %ebx
+
+ # The following code uses some tricks to change division by 10 to
+ # multiplication and shifts
+ movl .Ltmp,%esi # set %esi to 0xcccccccd
+
+.L10_40:
+ movl %ebx,%eax
+ mull %esi
+ decl %ecx
+ shrl $3,%edx
+ leal (%edx,%edx,4),%eax
+ addl %eax,%eax
+ subb %al,%bl # %bl now contains val % 10
+ addb $48,%bl
+ movb %bl,(%ecx)
+ movl %edx,%ebx
+ testl %ebx,%ebx
+ jne .L10_40
+ jmp .L10_mov # Shared end with longlong10_to_str
.L10end:
.size longlong10_to_str,.L10end-longlong10_to_str
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
new file mode 100644
index 00000000000..dbfd2783a80
--- /dev/null
+++ b/strings/my_vsnprintf.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <my_global.h>
+#include <m_string.h>
+#include <stdarg.h>
+#include <m_ctype.h>
+#include <assert.h>
+
+/*
+ Limited snprintf() implementations
+
+ IMPLEMENTION:
+ Supports following formats:
+ %#d
+ %#u
+ %#.#s Note #.# is skiped
+
+ RETURN
+ length of result string
+*/
+
+int my_snprintf(char* to, size_t n, const char* fmt, ...)
+{
+ va_list args;
+ int result;
+ va_start(args,fmt);
+ result= my_vsnprintf(to, n, fmt, args);
+ va_end(args);
+ return result;
+}
+
+
+int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
+{
+ char *start=to, *end=to+n-1;
+ uint length, num_state, pre_zero;
+
+ for (; *fmt ; fmt++)
+ {
+ if (fmt[0] != '%')
+ {
+ if (to == end) /* End of buffer */
+ break;
+ *to++= *fmt; /* Copy ordinary char */
+ continue;
+ }
+ fmt++; /* skip '%' */
+ /* Read max fill size (only used with %d and %u) */
+ if (*fmt == '-')
+ fmt++;
+ length= num_state= pre_zero= 0;
+ for (;; fmt++)
+ {
+ if (my_isdigit(&my_charset_latin1,*fmt))
+ {
+ if (!num_state)
+ {
+ length=length*10+ (uint) (*fmt-'0');
+ if (!length)
+ pre_zero= 1; /* first digit was 0 */
+ }
+ continue;
+ }
+ if (*fmt != '.' || num_state)
+ break;
+ num_state= 1;
+ }
+ if (*fmt == 'l')
+ fmt++;
+ if (*fmt == 's') /* String parameter */
+ {
+ reg2 char *par = va_arg(ap, char *);
+ uint plen,left_len = (uint)(end-to);
+ if (!par) par = (char*)"(null)";
+ plen = (uint) strlen(par);
+ if (left_len <= plen)
+ plen = left_len - 1;
+ to=strnmov(to,par,plen);
+ continue;
+ }
+ else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
+ {
+ register int iarg;
+ char *to_start= to;
+ if ((uint) (end-to) < max(16,length))
+ break;
+ iarg = va_arg(ap, int);
+ if (*fmt == 'd')
+ to=int10_to_str((long) iarg,to, -10);
+ else
+ to=int10_to_str((long) (uint) iarg,to,10);
+ /* If %#d syntax was used, we have to pre-zero/pre-space the string */
+ if (length)
+ {
+ uint res_length= (uint) (to - to_start);
+ if (res_length < length)
+ {
+ uint diff= (length- res_length);
+ bmove_upp(to+diff, to, res_length);
+ bfill(to-res_length, diff, pre_zero ? '0' : ' ');
+ to+= diff;
+ }
+ }
+ continue;
+ }
+ /* We come here on '%%', unknown code or too long parameter */
+ if (to == end)
+ break;
+ *to++='%'; /* % used as % or unknown code */
+ }
+ DBUG_ASSERT(to <= end);
+ *to='\0'; /* End of errmessage */
+ return (uint) (to - start);
+}
+
+#ifdef MAIN
+#define OVERRUN_SENTRY 250
+static void my_printf(const char * fmt, ...)
+{
+ char buf[33];
+ int n;
+ va_list ar;
+ va_start(ar, fmt);
+ buf[sizeof(buf)-1]=OVERRUN_SENTRY;
+ n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
+ printf(buf);
+ printf("n=%d, strlen=%d\n", n, strlen(buf));
+ if (buf[sizeof(buf)-1] != OVERRUN_SENTRY)
+ {
+ fprintf(stderr, "Buffer overrun\n");
+ abort();
+ }
+ va_end(ar);
+}
+
+int main()
+{
+
+ my_printf("Hello\n");
+ my_printf("Hello int, %d\n", 1);
+ my_printf("Hello string '%s'\n", "I am a string");
+ my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
+ my_printf("Hello %d hack %d\n", 1, 4);
+ my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
+ my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
+ my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
+ my_printf("Hello %u\n", 1);
+ my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
+ `%-.64s' (%-.64s)", 1, 0,0,0,0);
+ return 0;
+}
+#endif
diff --git a/strings/str2int.c b/strings/str2int.c
index 58669287473..d328d64d899 100644
--- a/strings/str2int.c
+++ b/strings/str2int.c
@@ -98,7 +98,7 @@ char *str2int(register const char *src, register int radix, long int lower,
converted value (and the scale!) as *negative* numbers,
so the sign is the opposite of what you might expect.
*/
- while (isspace(*src)) src++;
+ while (my_isspace(&my_charset_latin1,*src)) src++;
sign = -1;
if (*src == '+') src++; else
if (*src == '-') src++, sign = 1;
diff --git a/strings/strto.c b/strings/strto.c
index c98b19a7e67..8b838fd00f9 100644
--- a/strings/strto.c
+++ b/strings/strto.c
@@ -95,7 +95,7 @@ function (const char *nptr,char **endptr,int base)
s = nptr;
/* Skip white space. */
- while (isspace (*s))
+ while (my_isspace (my_charset_latin1, *s))
++s;
if (*s == '\0')
{
@@ -115,7 +115,7 @@ function (const char *nptr,char **endptr,int base)
}
- if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
+ if (base == 16 && s[0] == '0' && my_toupper (my_charset_latin1, s[1]) == 'X')
s += 2;
/* If BASE is zero, figure it out ourselves. */
@@ -123,7 +123,7 @@ function (const char *nptr,char **endptr,int base)
{
if (*s == '0')
{
- if (toupper (s[1]) == 'X')
+ if (my_toupper (my_charset_latin1, s[1]) == 'X')
{
s += 2;
base = 16;
@@ -145,10 +145,10 @@ function (const char *nptr,char **endptr,int base)
i = 0;
for (c = *s; c != '\0'; c = *++s)
{
- if (isdigit (c))
+ if (my_isdigit (my_charset_latin1, c))
c -= '0';
- else if (isalpha (c))
- c = toupper (c) - 'A' + 10;
+ else if (my_isalpha (my_charset_latin1, c))
+ c = my_toupper (my_charset_latin1, c) - 'A' + 10;
else
break;
if (c >= base)
diff --git a/strings/xml.c b/strings/xml.c
new file mode 100644
index 00000000000..4f6301249ae
--- /dev/null
+++ b/strings/xml.c
@@ -0,0 +1,374 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 "my_global.h"
+#include "m_string.h"
+#include "my_xml.h"
+
+
+#define MY_XML_EOF 'E'
+#define MY_XML_STRING 'S'
+#define MY_XML_IDENT 'I'
+#define MY_XML_EQ '='
+#define MY_XML_LT '<'
+#define MY_XML_GT '>'
+#define MY_XML_SLASH '/'
+#define MY_XML_COMMENT 'C'
+#define MY_XML_TEXT 'T'
+#define MY_XML_QUESTION '?'
+#define MY_XML_EXCLAM '!'
+
+typedef struct xml_attr_st
+{
+ const char *beg;
+ const char *end;
+} MY_XML_ATTR;
+
+static const char *lex2str(int lex)
+{
+ switch(lex)
+ {
+ case MY_XML_EOF: return "EOF";
+ case MY_XML_STRING: return "STRING";
+ case MY_XML_IDENT: return "IDENT";
+ case MY_XML_EQ: return "'='";
+ case MY_XML_LT: return "'<'";
+ case MY_XML_GT: return "'>'";
+ case MY_XML_SLASH: return "'/'";
+ case MY_XML_COMMENT: return "COMMENT";
+ case MY_XML_TEXT: return "TEXT";
+ case MY_XML_QUESTION: return "'?'";
+ case MY_XML_EXCLAM: return "'!'";
+ }
+ return "UNKNOWN";
+}
+
+static void my_xml_norm_text(MY_XML_ATTR *a)
+{
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->beg[0]) ; a->beg++ );
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->end[-1]) ; a->end-- );
+}
+
+
+static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
+{
+ int lex;
+
+ for( ; ( p->cur < p->end) && strchr(" \t\r\n",p->cur[0]) ; p->cur++);
+
+ if (p->cur >= p->end)
+ {
+ a->beg=p->end;
+ a->end=p->end;
+ lex=MY_XML_EOF;
+ goto ret;
+ }
+
+ a->beg=p->cur;
+ a->end=p->cur;
+
+ if (!memcmp(p->cur,"<!--",4))
+ {
+ for( ; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++);
+ if(!memcmp(p->cur, "-->", 3))
+ p->cur+=3;
+ a->end=p->cur;
+ lex=MY_XML_COMMENT;
+ }
+ else if (strchr("?=/<>!",p->cur[0]))
+ {
+ p->cur++;
+ a->end=p->cur;
+ lex=a->beg[0];
+ }
+ else if ( (p->cur[0]=='"') || (p->cur[0]=='\'') )
+ {
+ p->cur++;
+ for( ; ( p->cur < p->end ) && (p->cur[0]!=a->beg[0]); p->cur++);
+ a->end=p->cur;
+ if (a->beg[0]==p->cur[0])p->cur++;
+ a->beg++;
+ my_xml_norm_text(a);
+ lex=MY_XML_STRING;
+ }
+ else
+ {
+ for( ; (p->cur < p->end) && !strchr("?'\"=/<> \t\r\n", p->cur[0]); p->cur++);
+ a->end=p->cur;
+ my_xml_norm_text(a);
+ lex=MY_XML_IDENT;
+ }
+
+#if 0
+ printf("LEX=%s[%d]\n",lex2str(lex),a->end-a->beg);
+#endif
+
+ret:
+ return lex;
+}
+
+
+static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
+{
+ return (st->value) ? (st->value)(st,str,len) : MY_XML_OK;
+}
+
+
+static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
+{
+ if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
+ {
+ sprintf(st->errstr,"To deep XML");
+ return MY_XML_ERROR;
+ }
+ if (st->attrend > st->attr)
+ {
+ st->attrend[0]='.';
+ st->attrend++;
+ }
+ memcpy(st->attrend,str,len);
+ st->attrend+=len;
+ st->attrend[0]='\0';
+ return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
+}
+
+static void mstr(char *s,const char *src,uint l1, uint l2)
+{
+ l1 = l1<l2 ? l1 : l2;
+ memcpy(s,src,l1);
+ s[l1]='\0';
+}
+
+static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
+{
+ char *e;
+ uint glen;
+ char s[32];
+ char g[32];
+ int rc;
+
+ /* Find previous '.' or beginning */
+ for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
+ glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
+
+ if (str && (slen != glen))
+ {
+ mstr(s,str,sizeof(s)-1,slen);
+ mstr(g,e+1,sizeof(g)-1,glen),
+ sprintf(p->errstr,"'</%s>' unexpected ('</%s>' wanted)",s,g);
+ return MY_XML_ERROR;
+ }
+
+ rc = p->leave ? p->leave(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
+
+ *e='\0';
+ p->attrend=e;
+
+ return rc;
+}
+
+
+int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
+{
+ p->attrend=p->attr;
+ p->beg=str;
+ p->cur=str;
+ p->end=str+len;
+
+ while ( p->cur < p->end )
+ {
+ MY_XML_ATTR a;
+ if(p->cur[0]=='<')
+ {
+ int lex;
+ int question=0;
+ int exclam=0;
+
+ lex=my_xml_scan(p,&a);
+
+ if (MY_XML_COMMENT==lex)
+ {
+ continue;
+ }
+
+ lex=my_xml_scan(p,&a);
+
+ if (MY_XML_SLASH==lex)
+ {
+ if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
+ {
+ sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ goto gt;
+ }
+
+ if (MY_XML_EXCLAM==lex)
+ {
+ lex=my_xml_scan(p,&a);
+ exclam=1;
+ }
+ else if (MY_XML_QUESTION==lex)
+ {
+ lex=my_xml_scan(p,&a);
+ question=1;
+ }
+
+ if (MY_XML_IDENT==lex)
+ {
+ if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
+ return MY_XML_ERROR;
+ }
+ else
+ {
+ sprintf(p->errstr,"3: %s unexpected (ident or '/' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+
+ while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
+ {
+ MY_XML_ATTR b;
+ if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
+ {
+ lex=my_xml_scan(p,&b);
+ if ( (lex==MY_XML_IDENT) || (lex=MY_XML_STRING) )
+ {
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
+ (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ return MY_XML_ERROR;
+ }
+ else
+ {
+ sprintf(p->errstr,"4: %s unexpected (ident or string wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ }
+ else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
+ {
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ return MY_XML_ERROR;
+ }
+ else
+ break;
+ }
+
+ if (lex==MY_XML_SLASH)
+ {
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ }
+
+gt:
+ if (question)
+ {
+ if (lex!=MY_XML_QUESTION)
+ {
+ sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ }
+
+ if (exclam)
+ {
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ }
+
+ if (lex!=MY_XML_GT)
+ {
+ sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ }
+ else
+ {
+ a.beg=p->cur;
+ for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++);
+ a.end=p->cur;
+
+ my_xml_norm_text(&a);
+ if (a.beg!=a.end)
+ {
+ my_xml_value(p,a.beg,a.end-a.beg);
+ }
+ }
+ }
+ return MY_XML_OK;
+}
+
+void my_xml_parser_create(MY_XML_PARSER *p)
+{
+ bzero((void*)p,sizeof(p[0]));
+}
+
+void my_xml_parser_free(MY_XML_PARSER *p __attribute__((unused)))
+{
+}
+
+void my_xml_set_value_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->value=action;
+}
+
+void my_xml_set_enter_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->enter=action;
+}
+
+void my_xml_set_leave_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->leave=action;
+}
+
+void my_xml_set_user_data(MY_XML_PARSER *p, void *user_data)
+{
+ p->user_data=user_data;
+}
+
+const char *my_xml_error_string(MY_XML_PARSER *p)
+{
+ return p->errstr;
+}
+
+
+uint my_xml_error_pos(MY_XML_PARSER *p)
+{
+ const char *beg=p->beg;
+ const char *s;
+ for ( s=p->beg ; s<p->cur; s++)
+ if (s[0]=='\n')
+ beg=s;
+ return p->cur-beg;
+}
+
+uint my_xml_error_lineno(MY_XML_PARSER *p)
+{
+ uint res=0;
+ const char *s;
+ for ( s=p->beg ; s<p->cur; s++)
+ if (s[0]=='\n')
+ res++;
+ return res;
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 356da61ed57..5dc6871bd43 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -26,5 +26,16 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
pmail.pl mail_to_db.pl table_types.pl \
udf_test udf_test.res myisam-big-rows.tst
+#
+# C Test for 4.1 protocol
+#
+INCLUDES = -I$(top_srcdir)/include $(openssl_includes)
+LIBS = @CLIENT_LIBS@
+LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la
+noinst_PROGRAMS = client_test
+client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
+client_test_SOURCES= client_test.c
+client_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/tests/client_test.c b/tests/client_test.c
new file mode 100644
index 00000000000..0ba4b4e564c
--- /dev/null
+++ b/tests/client_test.c
@@ -0,0 +1,5953 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 */
+
+/***************************************************************************
+ This is a test sample to test the new features in MySQL client-server
+ protocol
+
+ Main author: venu ( venu@mysql.com )
+
+ NOTES:
+ - To be able to test which fields are used, we are not clearing
+ the MYSQL_BIND with bzero() but instead just clearing the fields that
+ are used by the API.
+
+***************************************************************************/
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+#include <my_getopt.h>
+#include <m_string.h>
+#include <assert.h>
+
+
+#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
+
+/* set default options */
+static char *opt_db=0;
+static char *opt_user=0;
+static char *opt_password=0;
+static char *opt_host=0;
+static char *opt_unix_socket=0;
+static unsigned int opt_port;
+static my_bool tty_password=0;
+
+static MYSQL *mysql=0;
+static char query[MAX_TEST_QUERY_LENGTH];
+static char current_db[]= "client_test_db";
+static unsigned int test_count= 0;
+static unsigned int opt_count= 0;
+static unsigned int iter_count= 0;
+
+static time_t start_time, end_time;
+static double total_time;
+
+#define myheader(str) \
+{ \
+ fprintf(stdout,"\n\n#####################################\n"); \
+ fprintf(stdout,"%d of (%d/%d): %s",test_count++, iter_count,\
+ opt_count, str); \
+ fprintf(stdout," \n#####################################\n"); \
+}
+#define myheader_r(str) \
+{ \
+ fprintf(stdout,"\n\n#####################################\n"); \
+ fprintf(stdout,"%s", str); \
+ fprintf(stdout," \n#####################################\n"); \
+}
+
+/*
+ TODO: un comment this in 4.1.1 when it supports mysql_param_result
+ and also enable all meta_param_result tests
+*/
+#ifndef mysql_param_result
+#define mysql_param_result mysql_prepare_result
+#endif
+
+static void print_error(const char *msg)
+{
+ if (mysql && mysql_errno(mysql))
+ {
+ if (mysql->server_version)
+ fprintf(stdout,"\n [MySQL-%s]",mysql->server_version);
+ else
+ fprintf(stdout,"\n [MySQL]");
+ fprintf(stdout,"[%d] %s\n",mysql_errno(mysql),mysql_error(mysql));
+ }
+ else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
+}
+
+static void print_st_error(MYSQL_STMT *stmt, const char *msg)
+{
+ if (stmt && mysql_stmt_errno(stmt))
+ {
+ if (stmt->mysql && stmt->mysql->server_version)
+ fprintf(stdout,"\n [MySQL-%s]",stmt->mysql->server_version);
+ else
+ fprintf(stdout,"\n [MySQL]");
+
+ fprintf(stdout,"[%d] %s\n",mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt));
+ }
+ else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
+}
+static void client_disconnect();
+
+#define myerror(msg) print_error(msg)
+#define mysterror(stmt, msg) print_st_error(stmt, msg)
+
+#define myassert(exp) assert(exp)
+#define myassert_r(exp) assert(!(exp))
+
+#define myquery(r) \
+{ \
+if (r) \
+ myerror(NULL); \
+ myassert(r == 0); \
+}
+
+#define myquery_r(r) \
+{ \
+if (r) \
+ myerror(NULL); \
+myassert_r(r == 0); \
+}
+
+#define mystmt(stmt,r) \
+{ \
+if (r) \
+ mysterror(stmt,NULL); \
+myassert(r == 0);\
+}
+
+#define mystmt_r(stmt,r) \
+{ \
+if (r) \
+ mysterror(stmt,NULL); \
+myassert_r(r == 0);\
+}
+
+#define mystmt_init(stmt) \
+{ \
+if ( stmt == 0) \
+ myerror(NULL); \
+myassert(stmt != 0); \
+}
+
+#define mystmt_init_r(stmt) \
+{ \
+if (stmt == 0) \
+ myerror(NULL);\
+myassert(stmt == 0);\
+}
+
+#define mytest(x) if (!x) {myerror(NULL);myassert(TRUE);}
+#define mytest_r(x) if (x) {myerror(NULL);myassert(TRUE);}
+
+/********************************************************
+* connect to the server *
+*********************************************************/
+static void client_connect()
+{
+ int rc;
+ myheader_r("client_connect");
+
+ fprintf(stdout, "\n Establishing a connection ...");
+
+ if (!(mysql = mysql_init(NULL)))
+ {
+ myerror("mysql_init() failed");
+ exit(0);
+ }
+
+ if (!(mysql_real_connect(mysql,opt_host,opt_user,
+ opt_password, opt_db ? opt_db:"test", opt_port,
+ opt_unix_socket, 0)))
+ {
+ myerror("connection failed");
+ mysql_close(mysql);
+ fprintf(stdout,"\n Check the connection options using --help or -?\n");
+ exit(0);
+ }
+
+ fprintf(stdout," OK");
+
+ /* set AUTOCOMMIT to ON*/
+ mysql_autocommit(mysql, TRUE);
+
+ fprintf(stdout, "\n Creating a test database '%s' ...", current_db);
+ strxmov(query,"CREATE DATABASE IF NOT EXISTS ", current_db, NullS);
+
+ rc = mysql_query(mysql, query);
+ myquery(rc);
+
+ strxmov(query,"USE ", current_db, NullS);
+ rc = mysql_query(mysql, query);
+ myquery(rc);
+
+ fprintf(stdout," OK");
+}
+
+/********************************************************
+* close the connection *
+*********************************************************/
+static void client_disconnect()
+{
+ myheader_r("client_disconnect");
+
+ if (mysql)
+ {
+ fprintf(stdout, "\n droping the test database '%s' ...", current_db);
+ strxmov(query,"DROP DATABASE IF EXISTS ", current_db, NullS);
+
+ mysql_query(mysql, query);
+ fprintf(stdout, " OK");
+
+ fprintf(stdout, "\n closing the connection ...");
+ mysql_close(mysql);
+ fprintf(stdout, " OK\n");
+ }
+}
+
+/********************************************************
+* query processing *
+*********************************************************/
+static void client_query()
+{
+ int rc;
+
+ myheader("client_query");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS myclient_test");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE myclient_test(id int primary key auto_increment,\
+ name varchar(20))");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE myclient_test(id int, name varchar(20))");
+ myquery_r(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('mysql')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('monty')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('venu')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('deleted')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('deleted')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"UPDATE myclient_test SET name='updated' WHERE name='deleted'");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"UPDATE myclient_test SET id=3 WHERE name='updated'");
+ myquery_r(rc);
+}
+
+/********************************************************
+* print dashes *
+*********************************************************/
+static void my_print_dashes(MYSQL_RES *result)
+{
+ MYSQL_FIELD *field;
+ unsigned int i,j;
+
+ mysql_field_seek(result,0);
+ fputc('\t',stdout);
+ fputc('+', stdout);
+
+ for(i=0; i< mysql_num_fields(result); i++)
+ {
+ field = mysql_fetch_field(result);
+ for(j=0; j < field->max_length+2; j++)
+ fputc('-',stdout);
+ fputc('+',stdout);
+ }
+ fputc('\n',stdout);
+}
+
+/********************************************************
+* print resultset metadata information *
+*********************************************************/
+static void my_print_result_metadata(MYSQL_RES *result)
+{
+ MYSQL_FIELD *field;
+ unsigned int i,j;
+ unsigned int field_count;
+
+ mysql_field_seek(result,0);
+ fputc('\n', stdout);
+ fputc('\n', stdout);
+
+ field_count = mysql_num_fields(result);
+ for(i=0; i< field_count; i++)
+ {
+ field = mysql_fetch_field(result);
+ j = strlen(field->name);
+ if (j < field->max_length)
+ j = field->max_length;
+ if (j < 4 && !IS_NOT_NULL(field->flags))
+ j = 4;
+ field->max_length = j;
+ }
+ my_print_dashes(result);
+ fputc('\t',stdout);
+ fputc('|', stdout);
+
+ mysql_field_seek(result,0);
+ for(i=0; i< field_count; i++)
+ {
+ field = mysql_fetch_field(result);
+ fprintf(stdout, " %-*s |",(int) field->max_length, field->name);
+ }
+ fputc('\n', stdout);
+ my_print_dashes(result);
+}
+
+/********************************************************
+* process the result set *
+*********************************************************/
+int my_process_result_set(MYSQL_RES *result)
+{
+ MYSQL_ROW row;
+ MYSQL_FIELD *field;
+ unsigned int i;
+ unsigned int row_count=0;
+
+ if (!result)
+ return 0;
+
+ my_print_result_metadata(result);
+
+ while ((row = mysql_fetch_row(result)) != NULL)
+ {
+ mysql_field_seek(result,0);
+ fputc('\t',stdout);
+ fputc('|',stdout);
+
+ for(i=0; i< mysql_num_fields(result); i++)
+ {
+ field = mysql_fetch_field(result);
+ if (row[i] == NULL)
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, row[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
+ }
+ fputc('\t',stdout);
+ fputc('\n',stdout);
+ row_count++;
+ }
+ if (row_count)
+ my_print_dashes(result);
+
+ if (mysql_errno(mysql) != 0)
+ fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
+ else
+ fprintf(stdout,"\n\t%d %s returned\n", row_count,
+ row_count == 1 ? "row" : "rows");
+ return row_count;
+}
+
+/********************************************************
+* process the stmt result set *
+*********************************************************/
+#define MAX_RES_FIELDS 50
+#define MAX_FIELD_DATA_SIZE 255
+
+uint my_process_stmt_result(MYSQL_STMT *stmt)
+{
+ int field_count;
+ uint row_count= 0;
+ MYSQL_BIND buffer[MAX_RES_FIELDS];
+ MYSQL_FIELD *field;
+ MYSQL_RES *result;
+ char data[MAX_RES_FIELDS][MAX_FIELD_DATA_SIZE];
+ ulong length[MAX_RES_FIELDS];
+ my_bool is_null[MAX_RES_FIELDS];
+ int rc, i;
+
+ if (!(result= mysql_prepare_result(stmt))) /* No meta info */
+ {
+ while (!mysql_fetch(stmt))
+ row_count++;
+ return row_count;
+ }
+
+ field_count= min(mysql_num_fields(result), MAX_RES_FIELDS);
+ for(i=0; i < field_count; i++)
+ {
+ buffer[i].buffer_type= MYSQL_TYPE_STRING;
+ buffer[i].buffer_length= MAX_FIELD_DATA_SIZE;
+ buffer[i].length= &length[i];
+ buffer[i].buffer= (char*) data[i];
+ buffer[i].is_null= &is_null[i];
+ }
+ my_print_result_metadata(result);
+
+ rc= mysql_bind_result(stmt,buffer);
+ mystmt(stmt,rc);
+
+ rc= mysql_stmt_store_result(stmt);
+ mystmt(stmt,rc);
+
+ mysql_field_seek(result, 0);
+ while (mysql_fetch(stmt) == 0)
+ {
+ fputc('\t',stdout);
+ fputc('|',stdout);
+
+ mysql_field_seek(result,0);
+ for (i=0; i < field_count; i++)
+ {
+ field = mysql_fetch_field(result);
+ if (is_null[i])
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (length[i] == 0)
+ {
+ data[i][0]='\0'; /* unmodified buffer */
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ }
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
+ }
+ fputc('\t',stdout);
+ fputc('\n',stdout);
+ row_count++;
+ }
+ if (row_count)
+ my_print_dashes(result);
+
+ fprintf(stdout,"\n\t%d %s returned\n", row_count,
+ row_count == 1 ? "row" : "rows");
+ mysql_free_result(result);
+ return row_count;
+}
+
+/********************************************************
+* process the stmt result set *
+*********************************************************/
+uint my_stmt_result(const char *buff, unsigned long length)
+{
+ MYSQL_STMT *stmt;
+ uint row_count;
+ int rc;
+
+ fprintf(stdout,"\n\n %s", buff);
+ stmt= mysql_prepare(mysql,buff,length);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ row_count= my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+
+ return row_count;
+}
+
+/*
+ Utility function to verify a particular column data
+*/
+static void verify_col_data(const char *table, const char *col,
+ const char *exp_data)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc, field= 1;
+
+ if (table && col)
+ {
+ strxmov(query,"SELECT ",col," FROM ",table," LIMIT 1", NullS);
+ fprintf(stdout,"\n %s", query);
+ rc = mysql_query(mysql, query);
+ myquery(rc);
+
+ field= 0;
+ }
+
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ if (!(row= mysql_fetch_row(result)) || !row[field])
+ {
+ fprintf(stdout,"\n *** ERROR: FAILED TO GET THE RESULT ***");
+ exit(1);
+ }
+ fprintf(stdout,"\n obtained: `%s` (expected: `%s`)",
+ row[field], exp_data);
+ myassert(strcmp(row[field],exp_data) == 0);
+ mysql_free_result(result);
+}
+
+/*
+ Utility function to verify the field members
+*/
+
+static void verify_prepare_field(MYSQL_RES *result,
+ unsigned int no,const char *name, const char *org_name,
+ enum enum_field_types type, const char *table,
+ const char *org_table, const char *db)
+{
+ MYSQL_FIELD *field;
+
+ if (!(field= mysql_fetch_field_direct(result,no)))
+ {
+ fprintf(stdout,"\n *** ERROR: FAILED TO GET THE RESULT ***");
+ exit(1);
+ }
+ fprintf(stdout,"\n field[%d]:", no);
+ fprintf(stdout,"\n name :`%s`\t(expected: `%s`)", field->name, name);
+ fprintf(stdout,"\n org_name :`%s`\t(expected: `%s`)", field->org_name, org_name);
+ fprintf(stdout,"\n type :`%d`\t(expected: `%d`)", field->type, type);
+ fprintf(stdout,"\n table :`%s`\t(expected: `%s`)", field->table, table);
+ fprintf(stdout,"\n org_table:`%s`\t(expected: `%s`)", field->org_table, org_table);
+ fprintf(stdout,"\n database :`%s`\t(expected: `%s`)", field->db, db);
+ fprintf(stdout,"\n");
+ myassert(strcmp(field->name,name) == 0);
+ myassert(strcmp(field->org_name,org_name) == 0);
+ myassert(field->type == type);
+ myassert(strcmp(field->table,table) == 0);
+ myassert(strcmp(field->org_table,org_table) == 0);
+ myassert(strcmp(field->db,db) == 0);
+}
+
+/*
+ Utility function to verify the parameter count
+*/
+static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
+{
+ long param_count= mysql_param_count(stmt);
+ fprintf(stdout,"\n total parameters in stmt: `%ld` (expected: `%ld`)",
+ param_count, exp_count);
+ myassert(param_count == exp_count);
+}
+
+/*
+ Utility function to verify the total affected rows
+*/
+static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
+{
+ ulonglong affected_rows= mysql_stmt_affected_rows(stmt);
+ fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)",
+ affected_rows, exp_count);
+ myassert(affected_rows == exp_count);
+}
+
+/*
+ Utility function to verify the total affected rows
+*/
+static void verify_affected_rows(ulonglong exp_count)
+{
+ ulonglong affected_rows= mysql_affected_rows(mysql);
+ fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)",
+ affected_rows, exp_count);
+ myassert(affected_rows == exp_count);
+}
+
+/*
+ Utility function to verify the total fields count
+*/
+static void verify_field_count(MYSQL_RES *result, uint exp_count)
+{
+ uint field_count= mysql_num_fields(result);
+ fprintf(stdout,"\n total fields in the result set: `%d` (expected: `%d`)",
+ field_count, exp_count);
+ myassert(field_count == exp_count);
+}
+
+
+/********************************************************
+* store result processing *
+*********************************************************/
+static void client_store_result()
+{
+ MYSQL_RES *result;
+ int rc;
+
+ myheader("client_store_result");
+
+ rc = mysql_query(mysql, "SELECT * FROM myclient_test");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+}
+
+/********************************************************
+* fetch the results
+*********************************************************/
+static void client_use_result()
+{
+ MYSQL_RES *result;
+ int rc;
+ myheader("client_use_result");
+
+ rc = mysql_query(mysql, "SELECT * FROM myclient_test");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+}
+
+/*
+ Separate thread query to test some cases
+*/
+static my_bool thread_query(char *query)
+{
+ MYSQL *l_mysql;
+ my_bool error;
+
+ error= 0;
+ fprintf(stdout,"\n in thread_query(%s)", query);
+ if (!(l_mysql = mysql_init(NULL)))
+ {
+ myerror("mysql_init() failed");
+ return 1;
+ }
+ if (!(mysql_real_connect(l_mysql,opt_host,opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0)))
+ {
+ myerror("connection failed");
+ error= 1;
+ goto end;
+ }
+ if (mysql_query(l_mysql,(char *)query))
+ {
+ fprintf(stderr,"Query failed (%s)\n",mysql_error(l_mysql));
+ error= 1;
+ goto end;
+ }
+ mysql_commit(l_mysql);
+end:
+ mysql_close(l_mysql);
+ return error;
+}
+
+
+/********************************************************
+* query processing *
+*********************************************************/
+static void test_debug_example()
+{
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_debug_example");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_debug_example");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_debug_example(id int primary key auto_increment,\
+ name varchar(20),xxx int)");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_debug_example(name) VALUES('mysql')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"UPDATE test_debug_example SET name='updated' WHERE name='deleted'");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"SELECT * FROM test_debug_example where name='mysql'");
+ myquery(rc);
+
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+
+ rc = mysql_query(mysql,"DROP TABLE test_debug_example");
+ myquery(rc);
+}
+
+/********************************************************
+* to test autocommit feature *
+*********************************************************/
+static void test_tran_bdb()
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+
+ myheader("test_tran_bdb");
+
+ /* set AUTOCOMMIT to OFF */
+ rc = mysql_autocommit(mysql, FALSE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_demo_transaction");
+ myquery(rc);
+
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
+ rc = mysql_query(mysql,"CREATE TABLE my_demo_transaction(col1 int ,col2 varchar(30)) TYPE = BDB");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(10,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now insert the second row, and rollback the transaction */
+ rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(20,'mysql')");
+ myquery(rc);
+
+ rc = mysql_rollback(mysql);
+ myquery(rc);
+
+ /* delete first row, and rollback it */
+ rc = mysql_query(mysql,"DELETE FROM my_demo_transaction WHERE col1 = 10");
+ myquery(rc);
+
+ rc = mysql_rollback(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ row = mysql_fetch_row(result);
+ mytest(row);
+
+ row = mysql_fetch_row(result);
+ mytest_r(row);
+
+ mysql_free_result(result);
+ mysql_autocommit(mysql,TRUE);
+}
+
+/********************************************************
+* to test autocommit feature *
+*********************************************************/
+static void test_tran_innodb()
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+
+ myheader("test_tran_innodb");
+
+ /* set AUTOCOMMIT to OFF */
+ rc = mysql_autocommit(mysql, FALSE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_demo_transaction");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
+ rc = mysql_query(mysql,"CREATE TABLE my_demo_transaction(col1 int ,col2 varchar(30)) TYPE = InnoDB");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(10,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now insert the second row, and rollback the transaction */
+ rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(20,'mysql')");
+ myquery(rc);
+
+ rc = mysql_rollback(mysql);
+ myquery(rc);
+
+ /* delete first row, and rollback it */
+ rc = mysql_query(mysql,"DELETE FROM my_demo_transaction WHERE col1 = 10");
+ myquery(rc);
+
+ rc = mysql_rollback(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ row = mysql_fetch_row(result);
+ mytest(row);
+
+ row = mysql_fetch_row(result);
+ mytest_r(row);
+
+ mysql_free_result(result);
+ mysql_autocommit(mysql,TRUE);
+}
+
+
+/********************************************************
+ To test simple prepares of all DML statements
+*********************************************************/
+
+static void test_prepare_simple()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ myheader("test_prepare_simple");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_simple");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prepare_simple(id int, name varchar(50))");
+ myquery(rc);
+
+ /* alter table */
+ strmov(query,"ALTER TABLE test_prepare_simple ADD new char(20)");
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+ mysql_stmt_close(stmt);
+
+ /* insert */
+ strmov(query,"INSERT INTO test_prepare_simple VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+ mysql_stmt_close(stmt);
+
+ /* update */
+ strmov(query,"UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?");
+ stmt = mysql_prepare(mysql, query, 100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,3);
+ mysql_stmt_close(stmt);
+
+ /* delete */
+ strmov(query,"DELETE FROM test_prepare_simple WHERE id=10");
+ stmt = mysql_prepare(mysql, query, 60);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ mysql_stmt_close(stmt);
+
+ /* delete */
+ strmov(query,"DELETE FROM test_prepare_simple WHERE id=?");
+ stmt = mysql_prepare(mysql, query, 50);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,1);
+
+ rc = mysql_execute(stmt);
+ mystmt_r(stmt, rc);
+ mysql_stmt_close(stmt);
+
+ /* select */
+ strmov(query,"SELECT * FROM test_prepare_simple WHERE id=? AND name= ?");
+ stmt = mysql_prepare(mysql, query, 100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+}
+
+
+/********************************************************
+* to test simple prepare field results *
+*********************************************************/
+static void test_prepare_field_result()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+
+ myheader("test_prepare_field_result");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_field_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prepare_field_result(int_c int, \
+ var_c varchar(50), ts_c timestamp(14),\
+ char_c char(3), date_c date,extra tinyint)");
+ myquery(rc);
+
+ /* insert */
+ strmov(query,"SELECT int_c,var_c,date_c as date,ts_c,char_c FROM \
+ test_prepare_field_result as t1 WHERE int_c=?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,1);
+
+ result = mysql_prepare_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ fprintf(stdout,"\n\n field attributes:\n");
+ verify_prepare_field(result,0,"int_c","int_c",MYSQL_TYPE_LONG,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,1,"var_c","var_c",MYSQL_TYPE_VAR_STRING,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,2,"date","date_c",MYSQL_TYPE_DATE,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,3,"ts_c","ts_c",MYSQL_TYPE_TIMESTAMP,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,4,"char_c","char_c",MYSQL_TYPE_STRING,
+ "t1","test_prepare_field_result",current_db);
+
+ verify_field_count(result, 5);
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple prepare field results *
+*********************************************************/
+static void test_prepare_syntax()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ myheader("test_prepare_syntax");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_syntax");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prepare_syntax(id int, name varchar(50), extra int)");
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_prepare_syntax VALUES(?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init_r(stmt);
+
+ strmov(query,"SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init_r(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+}
+
+
+/********************************************************
+* to test simple prepare *
+*********************************************************/
+static void test_prepare()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ int int_data, o_int_data;
+ char str_data[50], data[50];
+ char tiny_data, o_tiny_data;
+ short small_data, o_small_data;
+ longlong big_data, o_big_data;
+ float real_data, o_real_data;
+ double double_data, o_double_data;
+ ulong length[7], len;
+ my_bool is_null[7];
+ MYSQL_BIND bind[7];
+
+ myheader("test_prepare");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_prepare");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE my_prepare(col1 tinyint,\
+ col2 varchar(15), col3 int,\
+ col4 smallint, col5 bigint, \
+ col6 float, col7 double )");
+ myquery(rc);
+
+ /* insert by prepare */
+ strxmov(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)",NullS);
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,7);
+
+ /* tinyint */
+ bind[0].buffer_type=FIELD_TYPE_TINY;
+ bind[0].buffer= (char *)&tiny_data;
+ /* string */
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer= (char *)str_data;
+ bind[1].buffer_length= 1000; /* Max string length */
+ /* integer */
+ bind[2].buffer_type=FIELD_TYPE_LONG;
+ bind[2].buffer= (char *)&int_data;
+ /* short */
+ bind[3].buffer_type=FIELD_TYPE_SHORT;
+ bind[3].buffer= (char *)&small_data;
+ /* bigint */
+ bind[4].buffer_type=FIELD_TYPE_LONGLONG;
+ bind[4].buffer= (char *)&big_data;
+ /* float */
+ bind[5].buffer_type=FIELD_TYPE_FLOAT;
+ bind[5].buffer= (char *)&real_data;
+ /* double */
+ bind[6].buffer_type=FIELD_TYPE_DOUBLE;
+ bind[6].buffer= (char *)&double_data;
+
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ bind[i].length= &length[i];
+ bind[i].is_null= &is_null[i];
+ is_null[i]= 0;
+ }
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ int_data = 320;
+ small_data = 1867;
+ big_data = 1000;
+ real_data = 2;
+ double_data = 6578.001;
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (tiny_data=0; tiny_data < 100; tiny_data++)
+ {
+ length[1]= my_sprintf(str_data,(str_data, "MySQL%d",int_data));
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ int_data += 25;
+ small_data += 10;
+ big_data += 100;
+ real_data += 1;
+ double_data += 10.09;
+ }
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ myassert(tiny_data == (char) my_stmt_result("SELECT * FROM my_prepare",50));
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM my_prepare",50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ /* get the result */
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ o_int_data = 320;
+ o_small_data = 1867;
+ o_big_data = 1000;
+ o_real_data = 2;
+ o_double_data = 6578.001;
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (o_tiny_data=0; o_tiny_data < 100; o_tiny_data++)
+ {
+ len = my_sprintf(data, (data, "MySQL%d",o_int_data));
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data,length[0]);
+ fprintf(stdout, "\n\t short : %d (%lu)", small_data,length[3]);
+ fprintf(stdout, "\n\t int : %d (%lu)", int_data,length[2]);
+ fprintf(stdout, "\n\t big : %lld (%lu)", big_data,length[4]);
+
+ fprintf(stdout, "\n\t float : %f (%lu)", real_data,length[5]);
+ fprintf(stdout, "\n\t double : %f (%lu)", double_data,length[6]);
+
+ fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]);
+
+ myassert(tiny_data == o_tiny_data);
+ myassert(is_null[0] == 0);
+ myassert(length[0] == 1);
+
+ myassert(int_data == o_int_data);
+ myassert(length[2] == 4);
+
+ myassert(small_data == o_small_data);
+ myassert(length[3] == 2);
+
+ myassert(big_data == o_big_data);
+ myassert(length[4] == 8);
+
+ myassert(real_data == o_real_data);
+ myassert(length[5] == 4);
+
+ myassert(double_data == o_double_data);
+ myassert(length[6] == 8);
+
+ myassert(strcmp(data,str_data) == 0);
+ myassert(length[1] == len);
+
+ o_int_data += 25;
+ o_small_data += 10;
+ o_big_data += 100;
+ o_real_data += 1;
+ o_double_data += 10.09;
+ }
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+
+}
+
+
+/********************************************************
+* to test double comparision *
+*********************************************************/
+static void test_double_compare()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char real_data[10], tiny_data;
+ double double_data;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[3];
+ ulong length[3];
+
+ myheader("test_double_compare");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_double_compare");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_double_compare(col1 tinyint,\
+ col2 float, col3 double )");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_double_compare VALUES(1,10.2,34.5)");
+ myquery(rc);
+
+ strmov(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?");
+ stmt = mysql_prepare(mysql,query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,3);
+
+ /* tinyint */
+ bind[0].buffer_type=FIELD_TYPE_TINY;
+ bind[0].buffer=(char *)&tiny_data;
+ bind[0].is_null= 0; /* Can never be null */
+
+ /* string->float */
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer= (char *)&real_data;
+ bind[1].buffer_length=sizeof(real_data);
+ bind[1].is_null= 0;
+ bind[1].length= &length[1];
+ length[1]= 10;
+
+ /* double */
+ bind[2].buffer_type=FIELD_TYPE_DOUBLE;
+ bind[2].buffer= (char *)&double_data;
+ bind[2].is_null= 0;
+
+ tiny_data = 1;
+ strmov(real_data,"10.2");
+ double_data = 34.5;
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ verify_affected_rows(0);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM test_double_compare");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert((int)tiny_data == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+* to test simple null *
+*********************************************************/
+static void test_null()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ uint nData;
+ MYSQL_BIND bind[2];
+ my_bool is_null[2];
+
+ myheader("test_null");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_null");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_null(col1 int,col2 varchar(50))");
+ myquery(rc);
+
+ /* insert by prepare, wrong column name */
+ strmov(query,"INSERT INTO test_null(col3,col2) VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init_r(stmt);
+
+ strmov(query,"INSERT INTO test_null(col1,col2) VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ bind[0].buffer_type=MYSQL_TYPE_LONG;
+ bind[0].is_null= &is_null[0];
+ is_null[0]= 1;
+ bind[1]=bind[0];
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (nData=0; nData<10; nData++)
+ {
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ }
+
+ /* Re-bind with MYSQL_TYPE_NULL */
+ bind[0].buffer_type= MYSQL_TYPE_NULL;
+ is_null[0]= 0; /* reset */
+ bind[1]= bind[0];
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt,rc);
+
+ for (nData=0; nData<10; nData++)
+ {
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ }
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ nData*= 2;
+ myassert(nData == my_stmt_result("SELECT * FROM test_null", 30));
+
+ /* Fetch results */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (char *)&nData; /* this buffer won't be altered */
+ bind[0].length= 0;
+ bind[1]= bind[0];
+ bind[0].is_null= &is_null[0];
+ bind[1].is_null= &is_null[1];
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_null",30);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt,rc);
+
+ rc= 0;
+ is_null[0]= is_null[1]= 0;
+ while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ myassert(is_null[0]);
+ myassert(is_null[1]);
+ rc++;
+ is_null[0]= is_null[1]= 0;
+ }
+ myassert(rc == (int)nData);
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test fetch null *
+*********************************************************/
+static void test_fetch_null()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int i, nData;
+ MYSQL_BIND bind[11];
+ ulong length[11];
+ my_bool is_null[11];
+
+ myheader("test_fetch_null");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_fetch_null");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_fetch_null(col1 tinyint, col2 smallint, \
+ col3 int, col4 bigint, \
+ col5 float, col6 double, \
+ col7 date, col8 time, \
+ col9 varbinary(10), \
+ col10 varchar(50),\
+ col11 char(20))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_fetch_null(col11) VALUES(1000),(88),(389789)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* fetch */
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ bind[i].buffer_type=FIELD_TYPE_LONG;
+ bind[i].is_null= &is_null[i];
+ bind[i].length= &length[i];
+ }
+ bind[i-1].buffer=(char *)&nData; /* Last column is not null */
+
+ strmov((char *)query , "SELECT * FROM test_fetch_null");
+
+ myassert(3 == my_stmt_result(query,50));
+
+ stmt = mysql_prepare(mysql, query, 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc= 0;
+ while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rc++;
+ for (i=0; i < 10; i++)
+ {
+ fprintf(stdout, "\n data[%d] : %s", i,
+ is_null[i] ? "NULL" : "NOT NULL");
+ myassert(is_null[i]);
+ }
+ fprintf(stdout, "\n data[%d]: %d", i, nData);
+ myassert(nData == 1000 || nData == 88 || nData == 389789);
+ myassert(is_null[i] == 0);
+ myassert(length[i] == 4);
+ }
+ myassert(rc == 3);
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple select *
+*********************************************************/
+static void test_select_version()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ myheader("test_select_version");
+
+ stmt = mysql_prepare(mysql, "SELECT @@version", 30);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test simple select *
+*********************************************************/
+static void test_select_simple()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ myheader("test_select_simple");
+
+ stmt = mysql_prepare(mysql, "SHOW TABLES FROM mysql", 50);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple select to debug *
+*********************************************************/
+static void test_select_direct()
+{
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_select_direct");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id int, id1 tinyint, \
+ id2 float, \
+ id3 double, \
+ name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,5,2.3,4.5,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"SELECT * FROM test_select");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+* to test simple select with prepare *
+*********************************************************/
+static void test_select_prepare()
+{
+ int rc;
+ MYSQL_STMT *stmt;
+
+ myheader("test_select_prepare");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id int, name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_select",50);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ myassert(1 == my_process_stmt_result(stmt));
+ mysql_stmt_close(stmt);
+
+ rc = mysql_query(mysql,"DROP TABLE test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id tinyint, id1 int, \
+ id2 float, id3 float, \
+ name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select(id,id1,id2,name) VALUES(10,5,2.3,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_select",25);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ myassert(1 == my_process_stmt_result(stmt));
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple select *
+*********************************************************/
+static void test_select()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[25];
+ int nData=1;
+ MYSQL_BIND bind[2];
+ ulong length[2];
+
+ myheader("test_select");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id int,name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now insert the second row, and rollback the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES(20,'mysql')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ strmov(query,"SELECT * FROM test_select WHERE id=? AND name=?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ /* string data */
+ nData=10;
+ strmov(szData,(char *)"venu");
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer=(char *)szData;
+ bind[1].buffer_length= 4;
+ bind[1].length= &length[1];
+ length[1]= 4;
+ bind[1].is_null=0;
+
+ bind[0].buffer=(char *)&nData;
+ bind[0].buffer_type=FIELD_TYPE_LONG;
+ bind[0].is_null= 0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 1);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple select show *
+*********************************************************/
+static void test_select_show()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ myheader("test_select_show");
+
+ mysql_autocommit(mysql,TRUE);
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL, name char(2))");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql, "show columns from test_show", 30);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+
+ stmt = mysql_prepare(mysql, "show tables from mysql like ?", 50);
+ mystmt_init_r(stmt);
+
+ strxmov(query,"show tables from ", current_db, " like \'test_show\'", NullS);
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+
+ stmt = mysql_prepare(mysql, "describe test_show", 30);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple update *
+*********************************************************/
+static void test_simple_update()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[25];
+ int nData=1;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+ ulong length[2];
+
+ myheader("test_simple_update");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_update");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_update(col1 int,\
+ col2 varchar(50), col3 int )");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_update VALUES(1,'MySQL',100)");
+ myquery(rc);
+
+ verify_affected_rows(1);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert by prepare */
+ strmov(query,"UPDATE test_update SET col2=? WHERE col1=?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ nData=1;
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=szData; /* string data */
+ bind[0].buffer_length=sizeof(szData);
+ bind[0].length= &length[0];
+ bind[0].is_null= 0;
+ length[0]= my_sprintf(szData, (szData,"updated-data"));
+
+ bind[1].buffer=(char *) &nData;
+ bind[1].buffer_type=FIELD_TYPE_LONG;
+ bind[1].is_null= 0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ verify_affected_rows(1);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM test_update");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+* to test simple long data handling *
+*********************************************************/
+static void test_long_data()
+{
+ MYSQL_STMT *stmt;
+ int rc, int_data;
+ char *data=NullS;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[3];
+
+ myheader("test_long_data");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_long_data(col1 int,\
+ col2 long varchar, col3 long varbinary)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_long_data(col1,col2) VALUES(?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init_r(stmt);
+
+ strmov(query,"INSERT INTO test_long_data(col1,col2,col3) VALUES(?,?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,3);
+
+ bind[0].buffer=(char *)&int_data;
+ bind[0].buffer_type=FIELD_TYPE_LONG;
+ bind[0].is_null=0;
+
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].is_null=0;
+ bind[1].buffer_length=0; /* Will not be used */
+ bind[1].length=0; /* Will not be used */
+
+ bind[2]=bind[1];
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ int_data= 999;
+ data = (char *)"Michael";
+
+ /* supply data in pieces */
+ rc = mysql_send_long_data(stmt,1,data,strlen(data));
+ data = (char *)" 'Monty' Widenius";
+ rc = mysql_send_long_data(stmt,1,data,strlen(data));
+ mystmt(stmt, rc);
+ rc = mysql_send_long_data(stmt,2,"Venu (venu@mysql.com)",4);
+ mystmt(stmt, rc);
+
+ /* execute */
+ rc = mysql_execute(stmt);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ mystmt(stmt,rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now fetch the results ..*/
+ rc = mysql_query(mysql,"SELECT * FROM test_long_data");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+
+ verify_col_data("test_long_data","col1","999");
+ verify_col_data("test_long_data","col2","Michael 'Monty' Widenius");
+ verify_col_data("test_long_data","col3","Venu");
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test long data (string) handling *
+*********************************************************/
+static void test_long_data_str()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ char data[255];
+ long length, length1;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+ my_bool is_null[2];
+
+ myheader("test_long_data_str");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data_str");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_long_data_str(id int, longstr long varchar)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_long_data_str VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ bind[0].buffer = (char *)&length;
+ bind[0].buffer_type = FIELD_TYPE_LONG;
+ bind[0].is_null= &is_null[0];
+ is_null[0]=0;
+ length= 0;
+
+ bind[1].buffer=data; /* string data */
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].length= &length1;
+ bind[1].buffer_length=0; /* Will not be used */
+ bind[1].is_null= &is_null[1];
+ is_null[1]=0;
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ length = 40;
+ strmov(data,"MySQL AB");
+
+ /* supply data in pieces */
+ for(i=0; i < 4; i++)
+ {
+ rc = mysql_send_long_data(stmt,1,(char *)data,5);
+ mystmt(stmt, rc);
+ }
+ /* execute */
+ rc = mysql_execute(stmt);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ mystmt(stmt,rc);
+
+ mysql_stmt_close(stmt);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now fetch the results ..*/
+ rc = mysql_query(mysql,"SELECT LENGTH(longstr), longstr FROM test_long_data_str");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+
+ my_sprintf(data,(data,"%d", i*5));
+ verify_col_data("test_long_data_str","LENGTH(longstr)", data);
+ data[0]='\0';
+ while (i--)
+ strxmov(data,data,"MySQL",NullS);
+ verify_col_data("test_long_data_str","longstr", data);
+}
+
+
+/********************************************************
+* to test long data (string) handling *
+*********************************************************/
+static void test_long_data_str1()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ char data[255];
+ long length, length1;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+
+ myheader("test_long_data_str1");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data_str");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_long_data_str(longstr long varchar,blb long varbinary)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_long_data_str VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ bind[0].buffer=data; /* string data */
+ bind[0].buffer_length= sizeof(data);
+ bind[0].length= &length1;
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].is_null= 0;
+ length1= 0;
+
+ bind[1] = bind[0];
+ bind[1].buffer_type=FIELD_TYPE_BLOB;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+ length = my_sprintf(data, (data, "MySQL AB"));
+
+ /* supply data in pieces */
+ for (i=0; i < 3; i++)
+ {
+ rc = mysql_send_long_data(stmt,0,data,length);
+ mystmt(stmt, rc);
+
+ rc = mysql_send_long_data(stmt,1,data,2);
+ mystmt(stmt, rc);
+ }
+
+ /* execute */
+ rc = mysql_execute(stmt);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ mystmt(stmt,rc);
+
+ mysql_stmt_close(stmt);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now fetch the results ..*/
+ rc = mysql_query(mysql,"SELECT LENGTH(longstr),longstr,LENGTH(blb),blb FROM test_long_data_str");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+
+ my_sprintf(data,(data,"%ld",(long)i*length));
+ verify_col_data("test_long_data_str","length(longstr)",data);
+
+ my_sprintf(data,(data,"%d",i*2));
+ verify_col_data("test_long_data_str","length(blb)",data);
+}
+
+
+/********************************************************
+* to test long data (binary) handling *
+*********************************************************/
+static void test_long_data_bin()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char data[255];
+ long length;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+
+
+ myheader("test_long_data_bin");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data_bin");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_long_data_bin(id int, longbin long varbinary)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_long_data_bin VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ bind[0].buffer = (char *)&length;
+ bind[0].buffer_type = FIELD_TYPE_LONG;
+ bind[0].is_null= 0;
+ length= 0;
+
+ bind[1].buffer=data; /* string data */
+ bind[1].buffer_type=FIELD_TYPE_LONG_BLOB;
+ bind[1].length= 0; /* Will not be used */
+ bind[1].is_null= 0;
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ length = 10;
+ strmov(data,"MySQL AB");
+
+ /* supply data in pieces */
+ {
+ int i;
+ for (i=0; i < 100; i++)
+ {
+ rc = mysql_send_long_data(stmt,1,(char *)data,4);
+ mystmt(stmt, rc);
+ }
+ }
+ /* execute */
+ rc = mysql_execute(stmt);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ mystmt(stmt,rc);
+
+ mysql_stmt_close(stmt);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* now fetch the results ..*/
+ rc = mysql_query(mysql,"SELECT LENGTH(longbin), longbin FROM test_long_data_bin");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+* to test simple delete *
+*********************************************************/
+static void test_simple_delete()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[30]={0};
+ int nData=1;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+ ulong length[2];
+
+ myheader("test_simple_delete");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_simple_delete");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_simple_delete(col1 int,\
+ col2 varchar(50), col3 int )");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_simple_delete VALUES(1,'MySQL',100)");
+ myquery(rc);
+
+ verify_affected_rows(1);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert by prepare */
+ strmov(query,"DELETE FROM test_simple_delete WHERE col1=? AND col2=? AND col3=100");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ nData=1;
+ strmov(szData,"MySQL");
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer= szData; /* string data */
+ bind[1].buffer_length=sizeof(szData);
+ bind[1].length= &length[1];
+ bind[1].is_null= 0;
+ length[1]= 5;
+
+ bind[0].buffer=(char *)&nData;
+ bind[0].buffer_type=FIELD_TYPE_LONG;
+ bind[0].is_null= 0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ verify_affected_rows(1);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM test_simple_delete");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(0 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+
+/********************************************************
+* to test simple update *
+*********************************************************/
+static void test_update()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[25];
+ int nData=1;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+ ulong length[2];
+
+ myheader("test_update");
+
+ rc = mysql_autocommit(mysql,TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_update");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_update(col1 int primary key auto_increment,\
+ col2 varchar(50), col3 int )");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_update(col2,col3) VALUES(?,?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ /* string data */
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=szData;
+ bind[0].buffer_length= sizeof(szData);
+ bind[0].length= &length[0];
+ length[0]= my_sprintf(szData, (szData, "inserted-data"));
+ bind[0].is_null= 0;
+
+ bind[1].buffer=(char *)&nData;
+ bind[1].buffer_type=FIELD_TYPE_LONG;
+ bind[1].is_null= 0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ nData=100;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ verify_affected_rows(1);
+ mysql_stmt_close(stmt);
+
+ strmov(query,"UPDATE test_update SET col2=? WHERE col3=?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+ nData=100;
+
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=szData;
+ bind[0].buffer_length= sizeof(szData);
+ bind[0].length= &length[0];
+ length[0]= my_sprintf(szData, (szData, "updated-data"));
+ bind[1].buffer=(char *)&nData;
+ bind[1].buffer_type=FIELD_TYPE_LONG;
+ bind[1].is_null= 0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ verify_affected_rows(1);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM test_update");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+* to test simple prepare *
+*********************************************************/
+static void test_prepare_noparam()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_prepare_noparam");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_prepare");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE my_prepare(col1 int ,col2 varchar(50))");
+ myquery(rc);
+
+
+ /* insert by prepare */
+ strmov(query,"INSERT INTO my_prepare VALUES(10,'venu')");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM my_prepare");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+* to test simple bind result *
+*********************************************************/
+static void test_bind_result()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int nData;
+ ulong length, length1;
+ char szData[100];
+ MYSQL_BIND bind[2];
+ my_bool is_null[2];
+
+ myheader("test_bind_result");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(col1 int ,col2 varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(10,'venu')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(20,'MySQL')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result(col2) VALUES('monty')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* fetch */
+
+ bind[0].buffer_type=FIELD_TYPE_LONG;
+ bind[0].buffer= (char *) &nData; /* integer data */
+ bind[0].is_null= &is_null[0];
+ bind[0].length= 0;
+
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer=szData; /* string data */
+ bind[1].buffer_length=sizeof(szData);
+ bind[1].length= &length1;
+ bind[1].is_null= &is_null[1];
+
+ stmt = mysql_prepare(mysql, "SELECT * FROM test_bind_result", 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %d,%s(%lu)",nData, szData, length1);
+ myassert(nData == 10);
+ myassert(strcmp(szData,"venu")==0);
+ myassert(length1 == 4);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 2: %d,%s(%lu)",nData, szData, length1);
+ myassert(nData == 20);
+ myassert(strcmp(szData,"MySQL")==0);
+ myassert(length1 == 5);
+
+ length=99;
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ if (is_null[0])
+ fprintf(stdout,"\n row 3: NULL,%s(%lu)", szData, length1);
+ myassert(is_null[0]);
+ myassert(strcmp(szData,"monty")==0);
+ myassert(length1 == 5);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test ext bind result *
+*********************************************************/
+static void test_bind_result_ext()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ uchar t_data;
+ short s_data;
+ int i_data;
+ longlong b_data;
+ float f_data;
+ double d_data;
+ char szData[20], bData[20];
+ ulong szLength, bLength;
+ MYSQL_BIND bind[8];
+ long length[8];
+ my_bool is_null[8];
+
+ myheader("test_bind_result_ext");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
+ c3 int, c4 bigint, \
+ c5 float, c6 double, \
+ c7 varbinary(10), \
+ c8 varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(19,2999,3999,4999999,\
+ 2345.6,5678.89563,\
+ 'venu','mysql')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ bind[i].length= &length[i];
+ bind[i].is_null= &is_null[i];
+ }
+
+ bind[0].buffer_type=MYSQL_TYPE_TINY;
+ bind[0].buffer=(char *)&t_data;
+
+ bind[1].buffer_type=MYSQL_TYPE_SHORT;
+ bind[2].buffer_type=MYSQL_TYPE_LONG;
+
+ bind[3].buffer_type=MYSQL_TYPE_LONGLONG;
+ bind[1].buffer=(char *)&s_data;
+
+ bind[2].buffer=(char *)&i_data;
+ bind[3].buffer=(char *)&b_data;
+
+ bind[4].buffer_type=MYSQL_TYPE_FLOAT;
+ bind[4].buffer=(char *)&f_data;
+
+ bind[5].buffer_type=MYSQL_TYPE_DOUBLE;
+ bind[5].buffer=(char *)&d_data;
+
+ bind[6].buffer_type=MYSQL_TYPE_STRING;
+ bind[6].buffer= (char *)szData;
+ bind[6].buffer_length= sizeof(szData);
+ bind[6].length= &szLength;
+
+ bind[7].buffer_type=MYSQL_TYPE_TINY_BLOB;
+ bind[7].buffer=(char *)&bData;
+ bind[7].length= &bLength;
+ bind[7].buffer_length= sizeof(bData);
+
+ stmt = mysql_prepare(mysql, "select * from test_bind_result", 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout, "\n data (tiny) : %d", t_data);
+ fprintf(stdout, "\n data (short) : %d", s_data);
+ fprintf(stdout, "\n data (int) : %d", i_data);
+ fprintf(stdout, "\n data (big) : %lld", b_data);
+
+ fprintf(stdout, "\n data (float) : %f", f_data);
+ fprintf(stdout, "\n data (double) : %f", d_data);
+
+ fprintf(stdout, "\n data (str) : %s(%lu)", szData, szLength);
+ fprintf(stdout, "\n data (bin) : %s(%lu)", bData, bLength);
+
+
+ myassert(t_data == 19);
+ myassert(s_data == 2999);
+ myassert(i_data == 3999);
+ myassert(b_data == 4999999);
+ /*myassert(f_data == 2345.60);*/
+ /*myassert(d_data == 5678.89563);*/
+ myassert(strcmp(szData,"venu")==0);
+ myassert(strcmp(bData,"mysql")==0);
+ myassert(szLength == 4);
+ myassert(bLength == 5);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test ext bind result *
+*********************************************************/
+static void test_bind_result_ext1()
+{
+ MYSQL_STMT *stmt;
+ uint i;
+ int rc;
+ char t_data[20];
+ float s_data;
+ short i_data;
+ uchar b_data;
+ int f_data;
+ long bData;
+ char d_data[20];
+ double szData;
+ MYSQL_BIND bind[8];
+ ulong length[8];
+ my_bool is_null[8];
+ myheader("test_bind_result_ext1");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
+ c3 int, c4 bigint, \
+ c5 float, c6 double, \
+ c7 varbinary(10), \
+ c8 varchar(10))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(120,2999,3999,54,\
+ 2.6,58.89,\
+ '206','6.7')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind[0].buffer_type=MYSQL_TYPE_STRING;
+ bind[0].buffer=(char *) t_data;
+ bind[0].buffer_length= sizeof(t_data);
+
+ bind[1].buffer_type=MYSQL_TYPE_FLOAT;
+ bind[1].buffer=(char *)&s_data;
+
+ bind[2].buffer_type=MYSQL_TYPE_SHORT;
+ bind[2].buffer=(char *)&i_data;
+
+ bind[3].buffer_type=MYSQL_TYPE_TINY;
+ bind[3].buffer=(char *)&b_data;
+
+ bind[4].buffer_type=MYSQL_TYPE_LONG;
+ bind[4].buffer=(char *)&f_data;
+
+ bind[5].buffer_type=MYSQL_TYPE_STRING;
+ bind[5].buffer=(char *)d_data;
+
+ bind[6].buffer_type=MYSQL_TYPE_LONG;
+ bind[6].buffer=(char *)&bData;
+
+ bind[7].buffer_type=MYSQL_TYPE_DOUBLE;
+ bind[7].buffer=(char *)&szData;
+
+ for (i= 0; i < array_elements(bind); i++)
+ {
+ bind[i].is_null= &is_null[i];
+ bind[i].length= &length[i];
+ }
+
+ stmt = mysql_prepare(mysql, "select * from test_bind_result", 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout, "\n data (tiny) : %s(%lu)", t_data, length[0]);
+ fprintf(stdout, "\n data (short) : %f(%lu)", s_data, length[1]);
+ fprintf(stdout, "\n data (int) : %d(%lu)", i_data, length[2]);
+ fprintf(stdout, "\n data (big) : %d(%lu)", b_data, length[3]);
+
+ fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]);
+ fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]);
+
+ fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]);
+ fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]);
+
+ myassert(strcmp(t_data,"120")==0);
+ myassert(i_data == 3999);
+ myassert(f_data == 2);
+ myassert(strcmp(d_data,"58.89")==0);
+ myassert(b_data == 54);
+
+ myassert(length[0] == 3);
+ myassert(length[1] == 4);
+ myassert(length[2] == 2);
+ myassert(length[3] == 1);
+ myassert(length[4] == 4);
+ myassert(length[5] == 5);
+ myassert(length[6] == 4);
+ myassert(length[7] == 8);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ Generalized fetch conversion routine for all basic types
+*/
+static void bind_fetch(int row_count)
+{
+ MYSQL_STMT *stmt;
+ int rc, i, count= row_count;
+ ulong bit;
+ long data[10];
+ float f_data;
+ double d_data;
+ char s_data[10];
+ ulong length[10];
+ MYSQL_BIND bind[7];
+ my_bool is_null[7];
+
+ stmt = mysql_prepare(mysql,"INSERT INTO test_bind_fetch VALUES(?,?,?,?,?,?,?)",100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt, 7);
+
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
+ bind[i].buffer= (char *) &data[i];
+ bind[i].is_null= 0;
+ }
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt,rc);
+
+ while (count--)
+ {
+ rc= 10+count;
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ data[i]= rc+i;
+ rc+= 12;
+ }
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ }
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ mysql_stmt_close(stmt);
+
+ myassert(row_count == (int)
+ my_stmt_result("SELECT * FROM test_bind_fetch",50));
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_bind_fetch",50);
+ myquery(rc);
+
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ bind[i].buffer= (char *) &data[i];
+ bind[i].length= &length[i];
+ bind[i].is_null= &is_null[i];
+ }
+
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ bind[2].buffer_type= MYSQL_TYPE_LONG;
+ bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
+
+ bind[4].buffer_type= MYSQL_TYPE_FLOAT;
+ bind[4].buffer= (char *)&f_data;
+
+ bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[5].buffer= (char *)&d_data;
+
+ bind[6].buffer_type= MYSQL_TYPE_STRING;
+ bind[6].buffer= (char *)&s_data;
+ bind[6].buffer_length= sizeof(s_data);
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ while (row_count--)
+ {
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout, "\n");
+ fprintf(stdout, "\n tiny : %ld(%lu)", data[0], length[0]);
+ fprintf(stdout, "\n short : %ld(%lu)", data[1], length[1]);
+ fprintf(stdout, "\n int : %ld(%lu)", data[2], length[2]);
+ fprintf(stdout, "\n longlong : %ld(%lu)", data[3], length[3]);
+ fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]);
+ fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]);
+ fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]);
+
+ bit= 1;
+ rc= 10+row_count;
+ for (i=0; i < 4; i++)
+ {
+ myassert(data[i] == rc+i);
+ myassert(length[i] == bit);
+ bit<<= 1;
+ rc+= 12;
+ }
+
+ /* FLOAT */
+ rc+= i;
+ myassert((int)f_data == rc);
+ myassert(length[4] == 4);
+
+ /* DOUBLE */
+ rc+= 13;
+ myassert((int)d_data == rc);
+ myassert(length[5] == 8);
+
+ /* CHAR */
+ rc+= 13;
+ {
+ char buff[20];
+ long len= my_sprintf(buff, (buff, "%d", rc));
+ myassert(strcmp(s_data,buff)==0);
+ myassert(length[6] == (ulong) len);
+ }
+ }
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test fetching of date, time and ts *
+*********************************************************/
+static void test_fetch_date()
+{
+ MYSQL_STMT *stmt;
+ uint i;
+ int rc, year;
+ char date[25], time[25], ts[25], ts_4[15], ts_6[20], dt[20];
+ ulong d_length, t_length, ts_length, ts4_length, ts6_length,
+ dt_length, y_length;
+ MYSQL_BIND bind[8];
+ my_bool is_null[8];
+ ulong length[8];
+
+ myheader("test_fetch_date");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 date, c2 time, \
+ c3 timestamp(14), \
+ c4 year, \
+ c5 datetime, \
+ c6 timestamp(4), \
+ c7 timestamp(6))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES('2002-01-02',\
+ '12:49:00',\
+ '2002-01-02 17:46:59', \
+ 2010,\
+ '2010-07-10', \
+ '2020','1999-12-29')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ for (i= 0; i < array_elements(bind); i++)
+ {
+ bind[i].is_null= &is_null[i];
+ bind[i].length= &length[i];
+ }
+
+ bind[0].buffer_type=MYSQL_TYPE_STRING;
+ bind[1]=bind[2]=bind[0];
+
+ bind[0].buffer=(char *)&date;
+ bind[0].buffer_length= sizeof(date);
+ bind[0].length= &d_length;
+
+ bind[1].buffer=(char *)&time;
+ bind[1].buffer_length= sizeof(time);
+ bind[1].length= &t_length;
+
+ bind[2].buffer=(char *)&ts;
+ bind[2].buffer_length= sizeof(ts);
+ bind[2].length= &ts_length;
+
+ bind[3].buffer_type=MYSQL_TYPE_LONG;
+ bind[3].buffer=(char *)&year;
+ bind[3].length= &y_length;
+
+ bind[4].buffer_type=MYSQL_TYPE_STRING;
+ bind[4].buffer=(char *)&dt;
+ bind[4].buffer_length= sizeof(dt);
+ bind[4].length= &dt_length;
+
+ bind[5].buffer_type=MYSQL_TYPE_STRING;
+ bind[5].buffer=(char *)&ts_4;
+ bind[5].buffer_length= sizeof(ts_4);
+ bind[5].length= &ts4_length;
+
+ bind[6].buffer_type=MYSQL_TYPE_STRING;
+ bind[6].buffer=(char *)&ts_6;
+ bind[6].buffer_length= sizeof(ts_6);
+ bind[6].length= &ts6_length;
+
+ myassert(1 == my_stmt_result("SELECT * FROM test_bind_result",50));
+
+ stmt = mysql_prepare(mysql, "SELECT * FROM test_bind_result", 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ ts_4[0]='\0';
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout, "\n date : %s(%lu)", date, d_length);
+ fprintf(stdout, "\n time : %s(%lu)", time, t_length);
+ fprintf(stdout, "\n ts : %s(%lu)", ts, ts_length);
+ fprintf(stdout, "\n year : %d(%lu)", year, y_length);
+ fprintf(stdout, "\n dt : %s(%lu)", dt, dt_length);
+ fprintf(stdout, "\n ts(4) : %s(%lu)", ts_4, ts4_length);
+ fprintf(stdout, "\n ts(6) : %s(%lu)", ts_6, ts6_length);
+
+ myassert(strcmp(date,"2002-01-02")==0);
+ myassert(d_length == 10);
+
+ myassert(strcmp(time,"12:49:00")==0);
+ myassert(t_length == 8);
+
+ myassert(strcmp(ts,"2002-01-02 17:46:59")==0);
+ myassert(ts_length == 19);
+
+ myassert(year == 2010);
+ myassert(y_length == 4);
+
+ myassert(strcmp(dt,"2010-07-10 00:00:00")==0);
+ myassert(dt_length == 19);
+
+ myassert(ts_4[0] == '\0');
+ myassert(ts4_length == 0);
+
+ myassert(strcmp(ts_6,"1999-12-29 00:00:00")==0);
+ myassert(ts6_length == 19);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test fetching of str to all types *
+*********************************************************/
+static void test_fetch_str()
+{
+ int rc;
+
+ myheader("test_fetch_str");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 char(10),\
+ c2 char(10),\
+ c3 char(20),\
+ c4 char(20),\
+ c5 char(30),\
+ c6 char(40),\
+ c7 char(20))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(3);
+}
+
+/********************************************************
+* to test fetching of long to all types *
+*********************************************************/
+static void test_fetch_long()
+{
+ int rc;
+
+ myheader("test_fetch_long");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 int unsigned,\
+ c2 int unsigned,\
+ c3 int,\
+ c4 int,\
+ c5 int,\
+ c6 int unsigned,\
+ c7 int)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(4);
+}
+
+
+/********************************************************
+* to test fetching of short to all types *
+*********************************************************/
+static void test_fetch_short()
+{
+ int rc;
+
+ myheader("test_fetch_short");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 smallint unsigned,\
+ c2 smallint,\
+ c3 smallint unsigned,\
+ c4 smallint,\
+ c5 smallint,\
+ c6 smallint,\
+ c7 smallint unsigned)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(5);
+}
+
+
+/********************************************************
+* to test fetching of tiny to all types *
+*********************************************************/
+static void test_fetch_tiny()
+{
+ int rc;
+
+ myheader("test_fetch_tiny");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 tinyint unsigned,\
+ c2 tinyint,\
+ c3 tinyint unsigned,\
+ c4 tinyint,\
+ c5 tinyint,\
+ c6 tinyint,\
+ c7 tinyint unsigned)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(3);
+
+}
+
+
+/********************************************************
+* to test fetching of longlong to all types *
+*********************************************************/
+static void test_fetch_bigint()
+{
+ int rc;
+
+ myheader("test_fetch_bigint");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 bigint,\
+ c2 bigint,\
+ c3 bigint unsigned,\
+ c4 bigint unsigned,\
+ c5 bigint unsigned,\
+ c6 bigint unsigned,\
+ c7 bigint unsigned)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(2);
+
+}
+
+
+/********************************************************
+* to test fetching of float to all types *
+*********************************************************/
+static void test_fetch_float()
+{
+ int rc;
+
+ myheader("test_fetch_float");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 float(3),\
+ c2 float,\
+ c3 float unsigned,\
+ c4 float,\
+ c5 float,\
+ c6 float,\
+ c7 float(10) unsigned)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(2);
+
+}
+
+/********************************************************
+* to test fetching of double to all types *
+*********************************************************/
+static void test_fetch_double()
+{
+ int rc;
+
+ myheader("test_fetch_double");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 double(5,2),\
+ c2 double unsigned,\
+ c3 double unsigned,\
+ c4 double unsigned,\
+ c5 double unsigned,\
+ c6 double unsigned,\
+ c7 double unsigned)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind_fetch(3);
+
+}
+
+/********************************************************
+* to test simple prepare with all possible types *
+*********************************************************/
+static void test_prepare_ext()
+{
+ MYSQL_STMT *stmt;
+ uint i;
+ int rc;
+ char *sql;
+ int nData=1;
+ char tData=1;
+ short sData=10;
+ longlong bData=20;
+ MYSQL_BIND bind[6];
+ myheader("test_prepare_ext");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_ext");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ sql = (char *)"CREATE TABLE test_prepare_ext\
+ (\
+ c1 tinyint,\
+ c2 smallint,\
+ c3 mediumint,\
+ c4 int,\
+ c5 integer,\
+ c6 bigint,\
+ c7 float,\
+ c8 double,\
+ c9 double precision,\
+ c10 real,\
+ c11 decimal(7,4),\
+ c12 numeric(8,4),\
+ c13 date,\
+ c14 datetime,\
+ c15 timestamp(14),\
+ c16 time,\
+ c17 year,\
+ c18 bit,\
+ c19 bool,\
+ c20 char,\
+ c21 char(10),\
+ c22 varchar(30),\
+ c23 tinyblob,\
+ c24 tinytext,\
+ c25 blob,\
+ c26 text,\
+ c27 mediumblob,\
+ c28 mediumtext,\
+ c29 longblob,\
+ c30 longtext,\
+ c31 enum('one','two','three'),\
+ c32 set('monday','tuesday','wednesday'))";
+
+ rc = mysql_query(mysql,sql);
+ myquery(rc);
+
+ /* insert by prepare - all integers */
+ strmov(query,(char *)"INSERT INTO test_prepare_ext(c1,c2,c3,c4,c5,c6) VALUES(?,?,?,?,?,?)");
+ stmt = mysql_prepare(mysql,query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,6);
+
+ /*tinyint*/
+ bind[0].buffer_type=FIELD_TYPE_TINY;
+ bind[0].buffer= (char *)&tData;
+
+ /*smallint*/
+ bind[1].buffer_type=FIELD_TYPE_SHORT;
+ bind[1].buffer= (char *)&sData;
+
+ /*mediumint*/
+ bind[2].buffer_type=FIELD_TYPE_LONG;
+ bind[2].buffer= (char *)&nData;
+
+ /*int*/
+ bind[3].buffer_type=FIELD_TYPE_LONG;
+ bind[3].buffer= (char *)&nData;
+
+ /*integer*/
+ bind[4].buffer_type=FIELD_TYPE_LONG;
+ bind[4].buffer= (char *)&nData;
+
+ /*bigint*/
+ bind[5].buffer_type=FIELD_TYPE_LONGLONG;
+ bind[5].buffer= (char *)&bData;
+
+ for (i= 0; i < array_elements(bind); i++)
+ bind[i].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ /*
+ * integer to integer
+ */
+ for (nData=0; nData<10; nData++, tData++, sData++,bData++)
+ {
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ }
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"SELECT c1,c2,c3,c4,c5,c6 FROM test_prepare_ext",100);
+ mystmt_init(stmt);
+
+ /* get the result */
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(nData == (int)my_process_stmt_result(stmt));
+
+ mysql_stmt_close(stmt);
+}
+
+
+
+/********************************************************
+* to test real and alias names *
+*********************************************************/
+static void test_field_names()
+{
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_field_names");
+
+ fprintf(stdout,"\n %d,%d,%d",MYSQL_TYPE_DECIMAL,MYSQL_TYPE_NEWDATE,MYSQL_TYPE_ENUM);
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_names1");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_names2");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_field_names1(id int,name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_field_names2(id int,name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* with table name included with TRUE column name */
+ rc = mysql_query(mysql,"SELECT id as 'id-alias' FROM test_field_names1");
+ myquery(rc);
+
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ myassert(0 == my_process_result_set(result));
+ mysql_free_result(result);
+
+ /* with table name included with TRUE column name */
+ rc = mysql_query(mysql,"SELECT t1.id as 'id-alias',test_field_names2.name FROM test_field_names1 t1,test_field_names2");
+ myquery(rc);
+
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ myassert(0 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+/********************************************************
+* to test warnings *
+*********************************************************/
+static void test_warnings()
+{
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_warnings");
+
+ mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+
+ rc = mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ myquery(rc);
+
+ fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql));
+ rc = mysql_query(mysql,"SHOW WARNINGS");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+/********************************************************
+* to test errors *
+*********************************************************/
+static void test_errors()
+{
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_errors");
+
+ mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+
+ rc = mysql_query(mysql, "DROP TABLE test_non_exists");
+ myquery_r(rc);
+
+ rc = mysql_query(mysql,"SHOW ERRORS");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ my_process_result_set(result);
+ mysql_free_result(result);
+}
+
+
+
+/********************************************************
+* to test simple prepare-insert *
+*********************************************************/
+static void test_insert()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char str_data[50];
+ char tiny_data;
+ MYSQL_RES *result;
+ MYSQL_BIND bind[2];
+ ulong length;
+
+ myheader("test_insert");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_insert");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_insert(col1 tinyint,\
+ col2 varchar(50))");
+ myquery(rc);
+
+ /* insert by prepare */
+ stmt = mysql_prepare(mysql, "INSERT INTO test_prep_insert VALUES(?,?)", 70);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ /* tinyint */
+ bind[0].buffer_type=FIELD_TYPE_TINY;
+ bind[0].buffer=(char *)&tiny_data;
+ bind[0].is_null= 0;
+ bind[0].length= 0;
+
+ /* string */
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer=str_data;
+ bind[1].buffer_length=sizeof(str_data);;
+ bind[1].is_null= 0;
+ bind[1].length= &length;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (tiny_data=0; tiny_data < 3; tiny_data++)
+ {
+ length = my_sprintf(str_data, (str_data, "MySQL%d",tiny_data));
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ }
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* test the results now, only one row should exists */
+ rc = mysql_query(mysql,"SELECT * FROM test_prep_insert");
+ myquery(rc);
+
+ /* get the result */
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert((int)tiny_data == my_process_result_set(result));
+ mysql_free_result(result);
+
+}
+
+/********************************************************
+* to test simple prepare-resultset info *
+*********************************************************/
+static void test_prepare_resultset()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_prepare_resultset");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_resultset");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prepare_resultset(id int,\
+ name varchar(50),extra double)");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql, "SELECT * FROM test_prepare_resultset", 60);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result = mysql_prepare_result(stmt);
+ mytest(result);
+ my_print_result_metadata(result);
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test field flags (verify .NET provider) *
+*********************************************************/
+
+static void test_field_flags()
+{
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+ unsigned int i;
+
+
+ myheader("test_field_flags");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_flags");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_field_flags(id int NOT NULL AUTO_INCREMENT PRIMARY KEY,\
+ id1 int NOT NULL,\
+ id2 int UNIQUE,\
+ id3 int,\
+ id4 int NOT NULL,\
+ id5 int,\
+ KEY(id3,id4))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* with table name included with TRUE column name */
+ rc = mysql_query(mysql,"SELECT * FROM test_field_flags");
+ myquery(rc);
+
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ mysql_field_seek(result,0);
+ fputc('\n', stdout);
+
+ for(i=0; i< mysql_num_fields(result); i++)
+ {
+ field = mysql_fetch_field(result);
+ fprintf(stdout,"\n field:%d",i);
+ if (field->flags & NOT_NULL_FLAG)
+ fprintf(stdout,"\n NOT_NULL_FLAG");
+ if (field->flags & PRI_KEY_FLAG)
+ fprintf(stdout,"\n PRI_KEY_FLAG");
+ if (field->flags & UNIQUE_KEY_FLAG)
+ fprintf(stdout,"\n UNIQUE_KEY_FLAG");
+ if (field->flags & MULTIPLE_KEY_FLAG)
+ fprintf(stdout,"\n MULTIPLE_KEY_FLAG");
+ if (field->flags & AUTO_INCREMENT_FLAG)
+ fprintf(stdout,"\n AUTO_INCREMENT_FLAG");
+
+ }
+ mysql_free_result(result);
+}
+
+/**************************************************************
+ * Test mysql_stmt_close for open stmts *
+**************************************************************/
+static void test_stmt_close()
+{
+ MYSQL *lmysql;
+ MYSQL_STMT *stmt1, *stmt2, *stmt3, *stmt_x;
+ MYSQL_BIND bind[1];
+ MYSQL_RES *result;
+ unsigned int count;
+ int rc;
+
+ myheader("test_stmt_close");
+
+ fprintf(stdout, "\n Establishing a test connection ...");
+ if (!(lmysql = mysql_init(NULL)))
+ {
+ myerror("mysql_init() failed");
+ exit(0);
+ }
+ if (!(mysql_real_connect(lmysql,opt_host,opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0)))
+ {
+ myerror("connection failed");
+ exit(0);
+ }
+ fprintf(stdout," OK");
+
+
+ /* set AUTOCOMMIT to ON*/
+ mysql_autocommit(lmysql, TRUE);
+
+ rc = mysql_query(lmysql,"DROP TABLE IF EXISTS test_stmt_close");
+ myquery(rc);
+
+ rc = mysql_query(lmysql,"CREATE TABLE test_stmt_close(id int)");
+ myquery(rc);
+
+ strmov(query,"ALTER TABLE test_stmt_close ADD name varchar(20)");
+ stmt1= mysql_prepare(lmysql, query, 70);
+ mystmt_init(stmt1);
+
+ verify_param_count(stmt1, 0);
+
+ strmov(query,"INSERT INTO test_stmt_close(id) VALUES(?)");
+ stmt_x= mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt_x);
+
+ verify_param_count(stmt_x, 1);
+
+ strmov(query,"UPDATE test_stmt_close SET id=? WHERE id=?");
+ stmt3= mysql_prepare(lmysql, query, 70);
+ mystmt_init(stmt3);
+
+ verify_param_count(stmt3, 2);
+
+ strmov(query,"SELECT * FROM test_stmt_close WHERE id=?");
+ stmt2= mysql_prepare(lmysql, query, 70);
+ mystmt_init(stmt2);
+
+ verify_param_count(stmt2, 1);
+
+ rc= mysql_stmt_close(stmt1);
+ fprintf(stdout,"\n mysql_close_stmt(1) returned: %d", rc);
+ myassert(rc == 0);
+
+ mysql_close(lmysql); /* it should free all open stmts(stmt3, 2 and 1) */
+
+#if NOT_VALID
+ rc= mysql_stmt_close(stmt3);
+ fprintf(stdout,"\n mysql_close_stmt(3) returned: %d", rc);
+ myassert( rc == 1);
+
+ rc= mysql_stmt_close(stmt2);
+ fprintf(stdout,"\n mysql_close_stmt(2) returned: %d", rc);
+ myassert( rc == 1);
+#endif
+
+ count= 100;
+ bind[0].buffer=(char *)&count;
+ bind[0].buffer_type=MYSQL_TYPE_LONG;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt_x, bind);
+ mystmt(stmt_x, rc);
+
+ rc = mysql_execute(stmt_x);
+ mystmt(stmt_x, rc);
+
+ verify_st_affected_rows(stmt_x, 1);
+
+ rc= mysql_stmt_close(stmt_x);
+ fprintf(stdout,"\n mysql_close_stmt(x) returned: %d", rc);
+ myassert( rc == 0);
+
+ rc = mysql_query(mysql,"SELECT id FROM test_stmt_close");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+
+/********************************************************
+ * To test simple set-variable prepare *
+*********************************************************/
+static void test_set_variable()
+{
+ MYSQL_STMT *stmt, *stmt1;
+ int rc;
+ int set_count, def_count, get_count;
+ ulong length;
+ char var[NAME_LEN+1];
+ MYSQL_BIND set_bind[1], get_bind[2];
+
+ myheader("test_set_variable");
+
+ mysql_autocommit(mysql, TRUE);
+
+ stmt1 = mysql_prepare(mysql, "show variables like 'max_error_count'", 50);
+ mystmt_init(stmt1);
+
+ get_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ get_bind[0].buffer= (char *)var;
+ get_bind[0].is_null= 0;
+ get_bind[0].length= &length;
+ get_bind[0].buffer_length= (int)NAME_LEN;
+ length= NAME_LEN;
+
+ get_bind[1].buffer_type= MYSQL_TYPE_LONG;
+ get_bind[1].buffer= (char *)&get_count;
+ get_bind[1].is_null= 0;
+ get_bind[1].length= 0;
+
+ rc = mysql_execute(stmt1);
+ mystmt(stmt1, rc);
+
+ rc = mysql_bind_result(stmt1, get_bind);
+ mystmt(stmt1, rc);
+
+ rc = mysql_fetch(stmt1);
+ mystmt(stmt1, rc);
+
+ fprintf(stdout, "\n max_error_count(default): %d", get_count);
+ def_count= get_count;
+
+ myassert(strcmp(var,"max_error_count") == 0);
+ rc = mysql_fetch(stmt1);
+ myassert(rc == MYSQL_NO_DATA);
+
+ stmt = mysql_prepare(mysql, "set max_error_count=?", 50);
+ mystmt_init(stmt);
+
+ set_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ set_bind[0].buffer= (char *)&set_count;
+ set_bind[0].is_null= 0;
+ set_bind[0].length= 0;
+
+ rc = mysql_bind_param(stmt, set_bind);
+ mystmt(stmt,rc);
+
+ set_count= 31;
+ rc= mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ mysql_commit(mysql);
+
+ rc = mysql_execute(stmt1);
+ mystmt(stmt1, rc);
+
+ rc = mysql_fetch(stmt1);
+ mystmt(stmt1, rc);
+
+ fprintf(stdout, "\n max_error_count : %d", get_count);
+ myassert(get_count == set_count);
+
+ rc = mysql_fetch(stmt1);
+ myassert(rc == MYSQL_NO_DATA);
+
+ /* restore back to default */
+ set_count= def_count;
+ rc= mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt1);
+ mystmt(stmt1, rc);
+
+ rc = mysql_fetch(stmt1);
+ mystmt(stmt1, rc);
+
+ fprintf(stdout, "\n max_error_count(default): %d", get_count);
+ myassert(get_count == set_count);
+
+ rc = mysql_fetch(stmt1);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+ mysql_stmt_close(stmt1);
+}
+
+#if NOT_USED
+/* Insert meta info .. */
+static void test_insert_meta()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_insert_meta");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_insert");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_insert(col1 tinyint,\
+ col2 varchar(50), col3 varchar(30))");
+ myquery(rc);
+
+ strmov(query,"INSERT INTO test_prep_insert VALUES(10,'venu1','test')");
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ mysql_stmt_close(stmt);
+
+ strmov(query,"INSERT INTO test_prep_insert VALUES(?,'venu',?)");
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ result= mysql_param_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1");
+ myassert(strcmp(field->name,"col1")==0);
+
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3");
+ myassert(strcmp(field->name,"col3")==0);
+
+ field= mysql_fetch_field(result);
+ mytest_r(field);
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+
+/* Update meta info .. */
+static void test_update_meta()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_update_meta");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_update");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_update(col1 tinyint,\
+ col2 varchar(50), col3 varchar(30))");
+ myquery(rc);
+
+ strmov(query,"UPDATE test_prep_update SET col1=10, col2='venu1' WHERE col3='test'");
+ stmt = mysql_prepare(mysql, query, 100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ mysql_stmt_close(stmt);
+
+ strmov(query,"UPDATE test_prep_update SET col1=?, col2='venu' WHERE col3=?");
+ stmt = mysql_prepare(mysql, query, 100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ result= mysql_param_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ myassert(strcmp(field->name,"col1")==0);
+ myassert(strcmp(field->table,"test_prep_update")==0);
+
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ myassert(strcmp(field->name,"col3")==0);
+ myassert(strcmp(field->table,"test_prep_update")==0);
+
+ field= mysql_fetch_field(result);
+ mytest_r(field);
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+
+/* Select meta info .. */
+static void test_select_meta()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_select_meta");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_select(col1 tinyint,\
+ col2 varchar(50), col3 varchar(30))");
+ myquery(rc);
+
+ strmov(query,"SELECT * FROM test_prep_select WHERE col1=10");
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ strmov(query,"SELECT col1, col3 from test_prep_select WHERE col1=? AND col3='test' AND col2= ?");
+ stmt = mysql_prepare(mysql, query, 120);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ result= mysql_param_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ myassert(strcmp(field->name,"col1")==0);
+ myassert(strcmp(field->table,"test_prep_select")==0);
+
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ myassert(strcmp(field->name,"col2")==0);
+ myassert(strcmp(field->table,"test_prep_select")==0);
+
+ field= mysql_fetch_field(result);
+ mytest_r(field);
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+#endif
+
+
+/* Test FUNCTION field info / DATE_FORMAT() table_name . */
+static void test_func_fields()
+{
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_func_fields");
+
+ rc = mysql_autocommit(mysql, TRUE);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_dateformat");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_dateformat(id int, \
+ ts timestamp)");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "INSERT INTO test_dateformat(id) values(10)");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "SELECT ts FROM test_dateformat");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ field = mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout,"\n table name: `%s` (expected: `%s`)", field->table,
+ "test_dateformat");
+ myassert(strcmp(field->table, "test_dateformat")==0);
+
+ field = mysql_fetch_field(result);
+ mytest_r(field); /* no more fields */
+
+ mysql_free_result(result);
+
+ /* DATE_FORMAT */
+ rc = mysql_query(mysql, "SELECT DATE_FORMAT(ts,'%Y') AS 'venu' FROM test_dateformat");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ field = mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout,"\n table name: `%s` (expected: `%s`)", field->table, "");
+ myassert(field->table[0] == '\0');
+
+ field = mysql_fetch_field(result);
+ mytest_r(field); /* no more fields */
+
+ mysql_free_result(result);
+
+ /* FIELD ALIAS TEST */
+ rc = mysql_query(mysql, "SELECT DATE_FORMAT(ts,'%Y') AS 'YEAR' FROM test_dateformat");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ field = mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout,"\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
+ fprintf(stdout,"\n field org name: `%s` (expected: `%s`)",field->org_name,"");
+ myassert(strcmp(field->name, "YEAR")==0);
+ myassert(field->org_name[0] == '\0');
+
+ field = mysql_fetch_field(result);
+ mytest_r(field); /* no more fields */
+
+ mysql_free_result(result);
+}
+
+
+/* Multiple stmts .. */
+static void test_multi_stmt()
+{
+
+ MYSQL_STMT *stmt, *stmt1, *stmt2;
+ int rc, id;
+ char name[50];
+ MYSQL_BIND bind[2];
+ ulong length[2];
+ my_bool is_null[2];
+ myheader("test_multi_stmt");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_multi_table");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_multi_table(id int, name char(20))");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_multi_table values(10,'mysql')");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql, "SELECT * FROM test_multi_table WHERE id = ?", 100);
+ mystmt_init(stmt);
+
+ stmt2 = mysql_prepare(mysql, "UPDATE test_multi_table SET name='updated' WHERE id=10",100);
+ mystmt_init(stmt2);
+
+ verify_param_count(stmt,1);
+
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ bind[0].buffer= (char *)&id;
+ bind[0].is_null= &is_null[0];
+ bind[0].length= &length[0];
+ is_null[0]= 0;
+ length[0]= 0;
+
+ bind[1].buffer_type = MYSQL_TYPE_STRING;
+ bind[1].buffer = (char *)name;
+ bind[1].length = &length[1];
+ bind[1].is_null= &is_null[1];
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ id = 10;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ id = 999;
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ fprintf(stdout, "\n int_data: %d(%lu)", id, length[0]);
+ fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
+ myassert(id == 10);
+ myassert(strcmp(name,"mysql")==0);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ /* alter the table schema now */
+ stmt1 = mysql_prepare(mysql,"DELETE FROM test_multi_table WHERE id = ? AND name=?",100);
+ mystmt_init(stmt1);
+
+ verify_param_count(stmt1,2);
+
+ rc = mysql_bind_param(stmt1, bind);
+ mystmt(stmt1, rc);
+
+ rc = mysql_execute(stmt2);
+ mystmt(stmt2, rc);
+
+ verify_st_affected_rows(stmt2, 1);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ fprintf(stdout, "\n int_data: %d(%lu)", id, length[0]);
+ fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
+ myassert(id == 10);
+ myassert(strcmp(name,"updated")==0);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ rc = mysql_execute(stmt1);
+ mystmt(stmt1, rc);
+
+ verify_st_affected_rows(stmt1, 1);
+
+ mysql_stmt_close(stmt1);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ myassert(0 == my_stmt_result("SELECT * FROM test_multi_table",50));
+
+ mysql_stmt_close(stmt);
+ mysql_stmt_close(stmt2);
+
+}
+
+
+/********************************************************
+* to test simple sample - manual *
+*********************************************************/
+static void test_manual_sample()
+{
+ unsigned int param_count;
+ MYSQL_STMT *stmt;
+ short small_data;
+ int int_data;
+ char str_data[50];
+ ulonglong affected_rows;
+ MYSQL_BIND bind[3];
+ my_bool is_null;
+
+ myheader("test_manual_sample");
+
+ /*
+ Sample which is incorporated directly in the manual under Prepared
+ statements section (Example from mysql_execute()
+ */
+
+ mysql_autocommit(mysql, 1);
+ if (mysql_query(mysql,"DROP TABLE IF EXISTS test_table"))
+ {
+ fprintf(stderr, "\n drop table failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ }
+ if (mysql_query(mysql,"CREATE TABLE test_table(col1 int, col2 varchar(50), \
+ col3 smallint,\
+ col4 timestamp(14))"))
+ {
+ fprintf(stderr, "\n create table failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ }
+
+ /* Prepare a insert query with 3 parameters */
+ strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)");
+ if (!(stmt = mysql_prepare(mysql,query,strlen(query))))
+ {
+ fprintf(stderr, "\n prepare, insert failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ }
+ fprintf(stdout, "\n prepare, insert successful");
+
+ /* Get the parameter count from the statement */
+ param_count= mysql_param_count(stmt);
+
+ fprintf(stdout, "\n total parameters in insert: %d", param_count);
+ if (param_count != 3) /* validate parameter count */
+ {
+ fprintf(stderr, "\n invalid parameter count returned by MySQL");
+ exit(0);
+ }
+
+ /* Bind the data for the parameters */
+
+ /* INTEGER PART */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (char *)&int_data;
+ bind[0].is_null= 0;
+ bind[0].length= 0;
+
+ /* STRING PART */
+ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[1].buffer= (char *)str_data;
+ bind[1].buffer_length= sizeof(str_data);
+ bind[1].is_null= 0;
+ bind[1].length= 0;
+
+ /* SMALLINT PART */
+ bind[2].buffer_type= MYSQL_TYPE_SHORT;
+ bind[2].buffer= (char *)&small_data;
+ bind[2].is_null= &is_null;
+ bind[2].length= 0;
+ is_null= 0;
+
+ /* Bind the buffers */
+ if (mysql_bind_param(stmt, bind))
+ {
+ fprintf(stderr, "\n param bind failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ }
+
+ /* Specify the data */
+ int_data= 10; /* integer */
+ strmov(str_data,"MySQL"); /* string */
+
+ /* INSERT SMALLINT data as NULL */
+ is_null= 1;
+
+ /* Execute the insert statement - 1*/
+ if (mysql_execute(stmt))
+ {
+ fprintf(stderr, "\n execute 1 failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ }
+
+ /* Get the total rows affected */
+ affected_rows= mysql_stmt_affected_rows(stmt);
+
+ fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ if (affected_rows != 1) /* validate affected rows */
+ {
+ fprintf(stderr, "\n invalid affected rows by MySQL");
+ exit(0);
+ }
+
+ /* Re-execute the insert, by changing the values */
+ int_data= 1000;
+ strmov(str_data,"The most popular open source database");
+ small_data= 1000; /* smallint */
+ is_null= 0; /* reset */
+
+ /* Execute the insert statement - 2*/
+ if (mysql_execute(stmt))
+ {
+ fprintf(stderr, "\n execute 2 failed");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ }
+
+ /* Get the total rows affected */
+ affected_rows= mysql_stmt_affected_rows(stmt);
+
+ fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ if (affected_rows != 1) /* validate affected rows */
+ {
+ fprintf(stderr, "\n invalid affected rows by MySQL");
+ exit(0);
+ }
+
+ /* Close the statement */
+ if (mysql_stmt_close(stmt))
+ {
+ fprintf(stderr, "\n failed while closing the statement");
+ fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
+ exit(0);
+ }
+ myassert(2 == my_stmt_result("SELECT * FROM test_table",50));
+
+ /* DROP THE TABLE */
+ if (mysql_query(mysql,"DROP TABLE test_table"))
+ {
+ fprintf(stderr, "\n drop table failed");
+ fprintf(stderr, "\n %s", mysql_error(mysql));
+ exit(0);
+ }
+ fprintf(stdout, "Success !!!");
+}
+
+
+/********************************************************
+* to test alter table scenario in the middle of prepare *
+*********************************************************/
+static void test_prepare_alter()
+{
+ MYSQL_STMT *stmt;
+ int rc, id;
+ long length;
+ MYSQL_BIND bind[1];
+ my_bool is_null;
+
+ myheader("test_prepare_alter");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_alter");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_alter(id int, name char(20))");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_prep_alter values(10,'venu'),(20,'mysql')");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql, "INSERT INTO test_prep_alter VALUES(?,'monty')", 100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,1);
+
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ bind[0].buffer= (char *)&id;
+ bind[0].is_null= &is_null;
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt, rc);
+
+ id = 30; length= 0;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ if (thread_query((char *)"ALTER TABLE test_prep_alter change id id_new varchar(20)"))
+ exit(0);
+
+ is_null=1;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(4 == my_stmt_result("SELECT * FROM test_prep_alter",50));
+
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test the support of multi-query executions *
+*********************************************************/
+static void test_multi_query()
+{
+ MYSQL *l_mysql, *org_mysql;
+ MYSQL_RES *result;
+ int rc;
+
+ const char *query= "DROP TABLE IF EXISTS test_multi_tab;\
+ CREATE TABLE test_multi_tab(id int,name char(20));\
+ INSERT INTO test_multi_tab(xxxx) VALUES(10);\
+ UPDATE test_multi_tab SET id=10 WHERE unkown_col=10;\
+ CREATE TABLE test_multi_tab(id int,name char(20));\
+ INSERT INTO test_multi_tab(id) VALUES(10),(20);\
+ INSERT INTO test_multi_tab VALUES(20,'insert;comma');\
+ SELECT * FROM test_multi_tab;\
+ UPDATE test_multi_tab SET unknown_col=100 WHERE id=100;\
+ UPDATE test_multi_tab SET name='new;name' WHERE id=20;\
+ DELETE FROM test_multi_tab WHERE name='new;name';\
+ SELECT * FROM test_multi_tab;\
+ DELETE FROM test_multi_tab WHERE id=10;\
+ SELECT * FROM test_multi_tab;\
+ DROP TABLE test_multi_tab;\
+ DROP TABLE test_multi_tab;\
+ DROP TABLE IF EXISTS test_multi_tab";
+ uint count, rows[16]={0,1054,1054,1050,2,1,3,1054,2,2,1,1,0,0,1051,0}, exp_value;
+
+ myheader("test_multi_query");
+
+ rc = mysql_query(mysql, query); /* syntax error */
+ myquery_r(rc);
+
+ myassert(0 == mysql_next_result(mysql));
+ myassert(0 == mysql_more_results(mysql));
+
+ if (!(l_mysql = mysql_init(NULL)))
+ {
+ fprintf(stdout,"\n mysql_init() failed");
+ exit(1);
+ }
+ if (!(mysql_real_connect(l_mysql,opt_host,opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, CLIENT_MULTI_QUERIES))) /* enable multi queries */
+ {
+ fprintf(stdout,"\n connection failed(%s)", mysql_error(l_mysql));
+ exit(1);
+ }
+ org_mysql= mysql;
+ mysql= l_mysql;
+
+ rc = mysql_query(mysql, query);
+ myquery(rc);
+
+ count= exp_value= 0;
+ while (mysql_more_results(mysql) && count < array_elements(rows))
+ {
+ fprintf(stdout,"\n Query %d: ", count);
+ if ((rc= mysql_next_result(mysql)))
+ {
+ exp_value= mysql_errno(mysql);
+ fprintf(stdout, "ERROR %d: %s", exp_value, mysql_error(mysql));
+ }
+ else
+ {
+ if ((result= mysql_store_result(mysql)))
+ my_process_result_set(result);
+ else
+ fprintf(stdout,"OK, %lld row(s) affected, %d warning(s)",
+ mysql_affected_rows(mysql),
+ mysql_warning_count(mysql));
+ exp_value= (uint) mysql_affected_rows(mysql);
+ }
+ myassert(rows[count++] == exp_value);
+ }
+ mysql= org_mysql;
+}
+
+
+/********************************************************
+* to test simple bind store result *
+*********************************************************/
+static void test_store_result()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ long nData;
+ char szData[100];
+ MYSQL_BIND bind[2];
+ ulong length, length1;
+ my_bool is_null[2];
+
+ myheader("test_store_result");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_store_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_store_result(col1 int ,col2 varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_store_result VALUES(10,'venu'),(20,'mysql')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_store_result(col2) VALUES('monty')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* fetch */
+ bind[0].buffer_type=FIELD_TYPE_LONG;
+ bind[0].buffer= (char*) &nData; /* integer data */
+ bind[0].length= &length;
+ bind[0].is_null= &is_null[0];
+
+ length= 0;
+ bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer=szData; /* string data */
+ bind[1].buffer_length=sizeof(szData);
+ bind[1].length= &length1;
+ bind[1].is_null= &is_null[1];
+ length1= 0;
+
+ stmt = mysql_prepare(mysql, "SELECT * FROM test_store_result", 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %ld,%s(%lu)", nData, szData, length1);
+ myassert(nData == 10);
+ myassert(strcmp(szData,"venu")==0);
+ myassert(length1 == 4);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 2: %ld,%s(%lu)",nData, szData, length1);
+ myassert(nData == 20);
+ myassert(strcmp(szData,"mysql")==0);
+ myassert(length1 == 5);
+
+ length=99;
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ if (is_null[0])
+ fprintf(stdout,"\n row 3: NULL,%s(%lu)", szData, length1);
+ myassert(is_null[0]);
+ myassert(strcmp(szData,"monty")==0);
+ myassert(length1 == 5);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %ld,%s(%lu)",nData, szData, length1);
+ myassert(nData == 10);
+ myassert(strcmp(szData,"venu")==0);
+ myassert(length1 == 4);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 2: %ld,%s(%lu)",nData, szData, length1);
+ myassert(nData == 20);
+ myassert(strcmp(szData,"mysql")==0);
+ myassert(length1 == 5);
+
+ length=99;
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ if (is_null[0])
+ fprintf(stdout,"\n row 3: NULL,%s(%lu)", szData, length1);
+ myassert(is_null[0]);
+ myassert(strcmp(szData,"monty")==0);
+ myassert(length1 == 5);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple bind store result *
+*********************************************************/
+static void test_store_result1()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ myheader("test_store_result1");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_store_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_store_result(col1 int ,col2 varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_store_result VALUES(10,'venu'),(20,'mysql')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_store_result(col2) VALUES('monty')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_store_result",100);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = 0;
+ while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ fprintf(stdout, "\n total rows: %d", rc);
+ myassert(rc == 3);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = 0;
+ while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ fprintf(stdout, "\n total rows: %d", rc);
+ myassert(rc == 3);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple bind store result *
+*********************************************************/
+static void test_store_result2()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int nData;
+ long length;
+ MYSQL_BIND bind[1];
+
+ myheader("test_store_result2");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_store_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_store_result(col1 int ,col2 varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_store_result VALUES(10,'venu'),(20,'mysql')");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_store_result(col2) VALUES('monty')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind[0].buffer_type=FIELD_TYPE_LONG;
+ bind[0].buffer= (char *) &nData; /* integer data */
+ bind[0].length= &length;
+ bind[0].is_null= 0;
+
+ strmov((char *)query , "SELECT col1 FROM test_store_result where col1= ?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ nData = 10; length= 0;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ nData = 0;
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %d",nData);
+ myassert(nData == 10);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ nData = 20;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ nData = 0;
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %d",nData);
+ myassert(nData == 20);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test simple subselect prepare *
+*********************************************************/
+static void test_subselect()
+{
+#if TO_BE_FIXED_IN_SERVER
+ MYSQL_STMT *stmt;
+ int rc;
+ int id;
+ ulong length;
+ MYSQL_BIND bind[1];
+
+ myheader("test_subselect");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_sub1");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_sub2");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_sub1(id int)");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_sub2(id int, id1 int)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_sub1 values(2)");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_sub2 VALUES(1,7),(2,7)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* fetch */
+ bind[0].buffer_type= FIELD_TYPE_LONG;
+ bind[0].buffer= (char *) &id;
+ bind[0].length= &length;
+ bind[0].is_null= 0;
+ length= 0;
+
+ strmov((char *)query , "SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=?)");
+ myassert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=8)",100));
+ myassert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=7)",100));
+
+ stmt = mysql_prepare(mysql, query, 150);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ id = 7;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %d (%lu)",id, length);
+ myassert(id == 1);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ id= 8;
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %d (%lu)",id, length);
+ myassert(id == 0);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+#endif
+}
+
+/*
+ Generalized conversion routine to handle DATE, TIME and DATETIME
+ conversion using MYSQL_TIME structure
+*/
+static void test_bind_date_conv(uint row_count)
+{
+ MYSQL_STMT *stmt= 0;
+ uint rc, i, count= row_count;
+ ulong length[4];
+ MYSQL_BIND bind[4];
+ my_bool is_null[4]={0};
+ MYSQL_TIME tm[4];
+ ulong second_part;
+ uint year, month, day, hour, minute, sec;
+
+ stmt = mysql_prepare(mysql,"INSERT INTO test_date VALUES(?,?,?,?)", 100);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt, 4);
+
+ bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
+ bind[1].buffer_type= MYSQL_TYPE_TIME;
+ bind[2].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[3].buffer_type= MYSQL_TYPE_DATE;
+
+ second_part= 0;
+
+ year=2000;
+ month=01;
+ day=10;
+
+ hour=11;
+ minute=16;
+ sec= 20;
+
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ bind[i].buffer= (char *) &tm[i];
+ bind[i].is_null= &is_null[i];
+ bind[i].length= &length[i];
+ bind[i].buffer_length= 30;
+ length[i]=20;
+ }
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt,rc);
+
+ for (count= 0; count < row_count; count++)
+ {
+ for (i= 0; i < (int) array_elements(bind); i++)
+ {
+ tm[i].neg= 0;
+ tm[i].second_part= second_part+count;
+ tm[i].year= year+count;
+ tm[i].month= month+count;
+ tm[i].day= day+count;
+ tm[i].hour= hour+count;
+ tm[i].minute= minute+count;
+ tm[i].second= sec+count;
+ }
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+ }
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ mysql_stmt_close(stmt);
+
+ myassert(row_count == my_stmt_result("SELECT * FROM test_date",50));
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_date",50);
+ myquery(rc);
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ for (count=0; count < row_count; count++)
+ {
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout, "\n");
+ for (i= 0; i < array_elements(bind); i++)
+ {
+ fprintf(stdout, "\n");
+ fprintf(stdout," time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
+ i, tm[i].year, tm[i].month, tm[i].day,
+ tm[i].hour, tm[i].minute, tm[i].second,
+ tm[i].second_part);
+
+ myassert(tm[i].year == 0 || tm[i].year == year+count);
+ myassert(tm[i].month == 0 || tm[i].month == month+count);
+ myassert(tm[i].day == 0 || tm[i].day == day+count);
+
+ myassert(tm[i].hour == 0 || tm[i].hour == hour+count);
+ /*
+ minute causes problems from date<->time, don't assert, instead
+ validate separatly in another routine
+ */
+ /*myassert(tm[i].minute == 0 || tm[i].minute == minute+count);
+ myassert(tm[i].second == 0 || tm[i].second == sec+count);*/
+
+ myassert(tm[i].second_part == 0 || tm[i].second_part == second_part+count);
+ }
+ }
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ Test DATE, TIME, DATETIME and TS with MYSQL_TIME conversion
+*/
+
+static void test_date()
+{
+ int rc;
+
+ myheader("test_date");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_date(c1 TIMESTAMP(14), \
+ c2 TIME,\
+ c3 DATETIME,\
+ c4 DATE)");
+
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ test_bind_date_conv(5);
+}
+
+/*
+ Test all time types to DATE and DATE to all types
+*/
+
+static void test_date_date()
+{
+ int rc;
+
+ myheader("test_date_date");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_date(c1 DATE, \
+ c2 DATE,\
+ c3 DATE,\
+ c4 DATE)");
+
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ test_bind_date_conv(3);
+}
+
+/*
+ Test all time types to TIME and TIME to all types
+*/
+
+static void test_date_time()
+{
+ int rc;
+
+ myheader("test_date_time");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_date(c1 TIME, \
+ c2 TIME,\
+ c3 TIME,\
+ c4 TIME)");
+
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ test_bind_date_conv(3);
+}
+
+/*
+ Test all time types to TIMESTAMP and TIMESTAMP to all types
+*/
+
+static void test_date_ts()
+{
+ int rc;
+
+ myheader("test_date_ts");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_date(c1 TIMESTAMP(10), \
+ c2 TIMESTAMP(14),\
+ c3 TIMESTAMP,\
+ c4 TIMESTAMP(6))");
+
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ test_bind_date_conv(2);
+}
+
+/*
+ Test all time types to DATETIME and DATETIME to all types
+*/
+
+static void test_date_dt()
+{
+ int rc;
+
+ myheader("test_date_dt");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_date(c1 datetime, \
+ c2 datetime,\
+ c3 datetime,\
+ c4 date)");
+
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ test_bind_date_conv(2);
+}
+
+/*
+ Misc tests to keep pure coverage happy
+*/
+static void test_pure_coverage()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ int rc;
+ ulong length;
+
+ myheader("test_pure_coverage");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_pure");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_pure(c1 int, c2 varchar(20))");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"insert into test_pure(c67788) values(10)",100);
+ mystmt_init_r(stmt);
+
+#ifndef DBUG_OFF
+ stmt = mysql_prepare(mysql,(const char *)0,0);
+ mystmt_init_r(stmt);
+
+ stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(10)",100);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt_r(stmt, rc);
+
+ mysql_stmt_close(stmt);
+#endif
+
+ stmt = mysql_prepare(mysql,"insert into test_pure(c2) values(?)",100);
+ mystmt_init(stmt);
+
+#ifndef DBUG_OFF
+ rc = mysql_execute(stmt);
+ mystmt_r(stmt, rc);/* No parameters supplied */
+#endif
+
+ bind[0].length= &length;
+ bind[0].is_null= 0;
+ bind[0].buffer_length= 0;
+
+ bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
+ rc = mysql_bind_param(stmt, bind);
+ mystmt_r(stmt, rc); /* unsupported buffer type */
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_send_long_data(stmt, 20, (char *)"venu", 4);
+ mystmt_r(stmt, rc); /* wrong param number */
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ mysql_stmt_close(stmt);
+
+ stmt = mysql_prepare(mysql,"select * from test_pure",100);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+#ifndef DBUG_OFF
+ rc = mysql_bind_result(stmt, (MYSQL_BIND *)0);
+ mystmt_r(stmt, rc);
+
+ bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
+ rc = mysql_bind_result(stmt, bind);
+ mystmt_r(stmt, rc); /* unsupported buffer type */
+#endif
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt_r(stmt, rc); /* commands out of sync */
+
+ mysql_stmt_close(stmt);
+
+ mysql_query(mysql,"DROP TABLE test_pure");
+ mysql_commit(mysql);
+}
+
+/*
+ test for string buffer fetch
+*/
+
+static void test_buffers()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ int rc;
+ ulong length;
+ my_bool is_null;
+ char buffer[20];
+
+ myheader("test_buffers");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_buffer");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_buffer(str varchar(20))");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"insert into test_buffer values('MySQL')\
+ ,('Database'),('Open-Source'),('Popular')");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"select str from test_buffer",100);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ bind[0].length= &length;
+ bind[0].is_null= &is_null;
+ bind[0].buffer_length= 1;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char *)buffer;
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ buffer[1]='X';
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ myassert(buffer[0] == 'M');
+ myassert(buffer[1] == 'X');
+ myassert(length == 5);
+
+ bind[0].buffer_length=8;
+ rc = mysql_bind_result(stmt, bind);/* re-bind */
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ myassert(strncmp(buffer,"Database",8) == 0);
+ myassert(length == 8);
+
+ bind[0].buffer_length=12;
+ rc = mysql_bind_result(stmt, bind);/* re-bind */
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ myassert(strcmp(buffer,"Open-Source") == 0);
+ myassert(length == 11);
+
+ bind[0].buffer_length=6;
+ rc = mysql_bind_result(stmt, bind);/* re-bind */
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ myassert(strncmp(buffer,"Popula",6) == 0);
+ myassert(length == 7);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ Test the direct query execution in the middle of open stmts
+*/
+static void test_open_direct()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+
+ myheader("test_open_direct");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_open_direct");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_open_direct(id int, name char(6))");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"INSERT INTO test_open_direct values(10,'mysql')", 100);
+ mystmt_init(stmt);
+
+ rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(0 == my_process_result_set(result));
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ verify_st_affected_rows(stmt, 1);
+
+ rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ verify_st_affected_rows(stmt, 1);
+
+ rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(2 == my_process_result_set(result));
+ mysql_stmt_close(stmt);
+
+ /* run a direct query in the middle of a fetch */
+ stmt= mysql_prepare(mysql,"SELECT * FROM test_open_direct",100);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_open_direct(id) VALUES(20)");
+ myquery_r(rc);
+
+ rc = mysql_stmt_close(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_open_direct(id) VALUES(20)");
+ myquery(rc);
+
+ /* run a direct query with store result */
+ stmt= mysql_prepare(mysql,"SELECT * FROM test_open_direct",100);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_query(mysql,"drop table test_open_direct");
+ myquery(rc);
+
+ rc = mysql_stmt_close(stmt);
+ mystmt(stmt, rc);
+}
+
+/*
+ To test fetch without prior bound buffers
+*/
+static void test_fetch_nobuffs()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[4];
+ char str[4][50];
+ int rc;
+
+ myheader("test_fetch_nobuffs");
+
+ stmt = mysql_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), \
+ CURRENT_DATE(), CURRENT_TIME()",100);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = 0;
+ while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+
+ fprintf(stdout, "\n total rows : %d", rc);
+ myassert(rc == 1);
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char *)str[0];
+ bind[0].is_null= 0;
+ bind[0].length= 0;
+ bind[0].buffer_length= sizeof(str[0]);
+ bind[1]= bind[2]= bind[3]= bind[0];
+ bind[1].buffer= (char *)str[1];
+ bind[2].buffer= (char *)str[2];
+ bind[3].buffer= (char *)str[3];
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = 0;
+ while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rc++;
+ fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]);
+ fprintf(stdout, "\n CURRENT_USER() : %s", str[1]);
+ fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]);
+ fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]);
+ }
+ fprintf(stdout, "\n total rows : %d", rc);
+ myassert(rc == 1);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ To test a misc bug
+*/
+static void test_ushort_bug()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[4];
+ ushort short_value;
+ ulong long_value;
+ ulong s_length, l_length, ll_length, t_length;
+ ulonglong longlong_value;
+ int rc;
+ uchar tiny_value;
+
+ myheader("test_ushort_bug");
+
+ rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_ushort");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_ushort(a smallint unsigned, \
+ b smallint unsigned, \
+ c smallint unsigned, \
+ d smallint unsigned)");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)");
+ myquery(rc);
+
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_ushort",50);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ bind[0].buffer= (char *)&short_value;
+ bind[0].is_null= 0;
+ bind[0].length= &s_length;
+
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= (char *)&long_value;
+ bind[1].is_null= 0;
+ bind[1].length= &l_length;
+
+ bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[2].buffer= (char *)&longlong_value;
+ bind[2].is_null= 0;
+ bind[2].length= &ll_length;
+
+ bind[3].buffer_type= MYSQL_TYPE_TINY;
+ bind[3].buffer= (char *)&tiny_value;
+ bind[3].is_null= 0;
+ bind[3].length= &t_length;
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ fprintf(stdout,"\n ushort : %d (%ld)", short_value, s_length);
+ fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length);
+ fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
+
+ myassert(short_value == 35999);
+ myassert(s_length == 2);
+
+ myassert(long_value == 35999);
+ myassert(l_length == 4);
+
+ myassert(longlong_value == 35999);
+ myassert(ll_length == 8);
+
+ myassert(tiny_value == 200);
+ myassert(t_length == 1);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ To test a misc smallint-signed conversion bug
+*/
+static void test_sshort_bug()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[4];
+ short short_value;
+ long long_value;
+ ulong s_length, l_length, ll_length, t_length;
+ ulonglong longlong_value;
+ int rc;
+ uchar tiny_value;
+
+ myheader("test_sshort_bug");
+
+ rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_sshort");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_sshort(a smallint signed, \
+ b smallint signed, \
+ c smallint unsigned, \
+ d smallint unsigned)");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)");
+ myquery(rc);
+
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_sshort",50);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ bind[0].buffer= (char *)&short_value;
+ bind[0].is_null= 0;
+ bind[0].length= &s_length;
+
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= (char *)&long_value;
+ bind[1].is_null= 0;
+ bind[1].length= &l_length;
+
+ bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[2].buffer= (char *)&longlong_value;
+ bind[2].is_null= 0;
+ bind[2].length= &ll_length;
+
+ bind[3].buffer_type= MYSQL_TYPE_TINY;
+ bind[3].buffer= (char *)&tiny_value;
+ bind[3].is_null= 0;
+ bind[3].length= &t_length;
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length);
+ fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length);
+ fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
+
+ myassert(short_value == -5999);
+ myassert(s_length == 2);
+
+ myassert(long_value == -5999);
+ myassert(l_length == 4);
+
+ myassert(longlong_value == 35999);
+ myassert(ll_length == 8);
+
+ myassert(tiny_value == 200);
+ myassert(t_length == 1);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ To test a misc tinyint-signed conversion bug
+*/
+static void test_stiny_bug()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[4];
+ short short_value;
+ long long_value;
+ ulong s_length, l_length, ll_length, t_length;
+ ulonglong longlong_value;
+ int rc;
+ uchar tiny_value;
+
+ myheader("test_stiny_bug");
+
+ rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_stiny");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE test_stiny(a tinyint signed, \
+ b tinyint signed, \
+ c tinyint unsigned, \
+ d tinyint unsigned)");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"INSERT INTO test_stiny VALUES(-128, -127, 255, 0)");
+ myquery(rc);
+
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_stiny",50);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ bind[0].buffer= (char *)&short_value;
+ bind[0].is_null= 0;
+ bind[0].length= &s_length;
+
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= (char *)&long_value;
+ bind[1].is_null= 0;
+ bind[1].length= &l_length;
+
+ bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[2].buffer= (char *)&longlong_value;
+ bind[2].is_null= 0;
+ bind[2].length= &ll_length;
+
+ bind[3].buffer_type= MYSQL_TYPE_TINY;
+ bind[3].buffer= (char *)&tiny_value;
+ bind[3].is_null= 0;
+ bind[3].length= &t_length;
+
+ rc = mysql_bind_result(stmt, bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt, rc);
+
+ fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length);
+ fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length);
+ fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
+
+ myassert(short_value == -128);
+ myassert(s_length == 2);
+
+ myassert(long_value == -127);
+ myassert(l_length == 4);
+
+ myassert(longlong_value == 255);
+ myassert(ll_length == 8);
+
+ myassert(tiny_value == 0);
+ myassert(t_length == 1);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ Read and parse arguments and MySQL options from my.cnf
+*/
+
+static const char *client_test_load_default_groups[]= { "client", 0 };
+static char **defaults_argv;
+
+static struct my_option client_test_long_options[] =
+{
+ {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
+ {"database", 'D', "Database to use", (char **) &opt_db, (char **) &opt_db,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"host", 'h', "Connect to host", (char **) &opt_host, (char **) &opt_host, 0, GET_STR_ALLOC,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"password", 'p',
+ "Password to use when connecting to server. If password is not given it's asked from the tty.",
+ 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#ifndef DONT_ALLOW_USER_CHANGE
+ {"user", 'u', "User for login if not current user", (char **) &opt_user,
+ (char **) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+ {"port", 'P', "Port number to use for connection", (char **) &opt_port,
+ (char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"socket", 'S', "Socket file to use for connection", (char **) &opt_unix_socket,
+ (char **) &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"count", 't', "Number of times test to be executed", (char **) &opt_count,
+ (char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+static void client_test_print_version(void)
+{
+ fprintf(stdout, "%s Distrib %s, for %s (%s)\n\n",
+ my_progname,MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+
+
+static void usage(void)
+{
+ /*
+ * show the usage string when the user asks for this
+ */
+ putc('\n',stdout);
+ puts("***********************************************************************\n");
+ puts(" Test for client-server protocol 4.1");
+ puts(" By Monty & Venu \n");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
+ puts("and you are welcome to modify and redistribute it under the GPL license\n");
+ puts(" Copyright (C) 1995-2003 MySQL AB ");
+ puts("-----------------------------------------------------------------------\n");
+ client_test_print_version();
+ fprintf(stdout,"Usage: %s [OPTIONS]\n\n", my_progname);
+
+ my_print_help(client_test_long_options);
+ print_defaults("my", client_test_load_default_groups);
+ my_print_variables(client_test_long_options);
+
+ puts("***********************************************************************\n");
+}
+
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case 'p':
+ if (argument)
+ {
+ char *start=argument;
+ my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ opt_password= my_strdup(argument, MYF(MY_FAE));
+ while (*argument) *argument++= 'x'; /* Destroy argument */
+ if (*start)
+ start[1]=0;
+ }
+ else
+ tty_password= 1;
+ break;
+ case '?':
+ case 'I': /* Info */
+ usage();
+ exit(0);
+ break;
+ }
+ return 0;
+}
+
+static void get_options(int argc, char **argv)
+{
+ int ho_error;
+ load_defaults("my",client_test_load_default_groups,&argc,&argv);
+
+ if ((ho_error= handle_options(&argc,&argv, client_test_long_options,
+ get_one_option)))
+ exit(ho_error);
+
+ if (tty_password)
+ opt_password=get_tty_password(NullS);
+ return;
+}
+
+/*
+ Print the test output on successful execution before exiting
+*/
+
+static void print_test_output()
+{
+ fprintf(stdout,"\n\n");
+ fprintf(stdout,"All '%d' tests were successful (in '%d' iterations)",
+ test_count-1, opt_count);
+ fprintf(stdout,"\n Total execution time: %g SECS", total_time);
+ if (opt_count > 1)
+ fprintf(stdout," (Avg: %g SECS)", total_time/opt_count);
+
+ fprintf(stdout,"\n\n!!! SUCCESS !!!\n");
+}
+
+/********************************************************
+* main routine *
+*********************************************************/
+int main(int argc, char **argv)
+{
+ MY_INIT(argv[0]);
+
+ load_defaults("my",client_test_load_default_groups,&argc,&argv);
+ defaults_argv= argv;
+ get_options(argc,argv);
+
+ client_connect(); /* connect to server */
+
+ total_time= 0;
+ for (iter_count=1; iter_count <= opt_count; iter_count++)
+ {
+ /* Start of tests */
+ test_count= 1;
+
+ start_time= time((time_t *)0);
+
+ test_fetch_nobuffs(); /* to fecth without prior bound buffers */
+ test_open_direct(); /* direct execution in the middle of open stmts */
+ test_fetch_null(); /* to fetch null data */
+ test_fetch_date(); /* to fetch date,time and timestamp */
+ test_fetch_str(); /* to fetch string to all types */
+ test_fetch_long(); /* to fetch long to all types */
+ test_fetch_short(); /* to fetch short to all types */
+ test_fetch_tiny(); /* to fetch tiny to all types */
+ test_fetch_bigint(); /* to fetch bigint to all types */
+ test_fetch_float(); /* to fetch float to all types */
+ test_fetch_double(); /* to fetch double to all types */
+ test_bind_result_ext(); /* result bind test - extension */
+ test_bind_result_ext1(); /* result bind test - extension */
+ test_select_direct(); /* direct select - protocol_simple debug */
+ test_select_prepare(); /* prepare select - protocol_prep debug */
+ test_select(); /* simple select test */
+ test_select_version(); /* select with variables */
+ test_select_simple(); /* simple select prepare */
+#if NOT_USED
+ /*
+ Enable this tests from 4.1.1 when mysql_param_result() is
+ supported
+ */
+ test_select_meta(); /* select param meta information */
+ test_update_meta(); /* update param meta information */
+ test_insert_meta(); /* insert param meta information */
+#endif
+ test_func_fields(); /* test for new 4.1 MYSQL_FIELD members */
+ test_long_data(); /* test for sending text data in chunks */
+ test_insert(); /* simple insert test - prepare */
+ test_set_variable(); /* prepare with set variables */
+ test_select_show(); /* prepare - show test */
+ test_prepare_noparam(); /* prepare without parameters */
+ test_bind_result(); /* result bind test */
+ test_prepare_simple(); /* simple prepare */
+ test_prepare(); /* prepare test */
+ test_null(); /* test null data handling */
+ test_debug_example(); /* some debugging case */
+ test_update(); /* prepare-update test */
+ test_simple_update(); /* simple prepare with update */
+ test_simple_delete(); /* prepare with delete */
+ test_double_compare(); /* float comparision */
+ client_query(); /* simple client query test */
+ client_store_result(); /* usage of mysql_store_result() */
+ client_use_result(); /* usage of mysql_use_result() */
+ test_tran_bdb(); /* transaction test on BDB table type */
+ test_tran_innodb(); /* transaction test on InnoDB table type */
+ test_prepare_ext(); /* test prepare with all types conversion -- TODO */
+ test_prepare_syntax(); /* syntax check for prepares */
+ test_field_names(); /* test for field names */
+ test_field_flags(); /* test to help .NET provider team */
+ test_long_data_str(); /* long data handling */
+ test_long_data_str1(); /* yet another long data handling */
+ test_long_data_bin(); /* long binary insertion */
+ test_warnings(); /* show warnings test */
+ test_errors(); /* show errors test */
+ test_prepare_resultset();/* prepare meta info test */
+ test_stmt_close(); /* mysql_stmt_close() test -- hangs */
+ test_prepare_field_result(); /* prepare meta info */
+ test_multi_stmt(); /* multi stmt test */
+ test_multi_query(); /* test multi query execution */
+ test_store_result(); /* test the store_result */
+ test_store_result1(); /* test store result without buffers */
+ test_store_result2(); /* test store result for misc case */
+ test_subselect(); /* test subselect prepare -TODO*/
+ test_date(); /* test the MYSQL_TIME conversion */
+ test_date_date(); /* test conversion from DATE to all */
+ test_date_time(); /* test conversion from TIME to all */
+ test_date_ts() ; /* test conversion from TIMESTAMP to all */
+ test_date_dt() ; /* test conversion from DATETIME to all */
+ test_prepare_alter(); /* change table schema in middle of prepare */
+ test_manual_sample(); /* sample in the manual */
+ test_pure_coverage(); /* keep pure coverage happy */
+ test_buffers(); /* misc buffer handling */
+ test_ushort_bug(); /* test a simple conv bug from php */
+ test_sshort_bug(); /* test a simple conv bug from php */
+ test_stiny_bug(); /* test a simple conv bug from php */
+
+ end_time= time((time_t *)0);
+ total_time+= difftime(end_time, start_time);
+
+ /* End of tests */
+ }
+
+ client_disconnect(); /* disconnect from server */
+ free_defaults(defaults_argv);
+ print_test_output();
+
+ return(0);
+}
+
diff --git a/tests/fork_big2.pl b/tests/fork_big2.pl
new file mode 100644
index 00000000000..b552b95ba6b
--- /dev/null
+++ b/tests/fork_big2.pl
@@ -0,0 +1,705 @@
+#!/usr/bin/perl -w
+#
+# This is a test with uses many processes to test a MySQL server.
+#
+# Tested a lot with: --threads=30
+
+$opt_loop_count=500000; # Change this to make test harder/easier
+
+##################### Standard benchmark inits ##############################
+
+use DBI;
+use Getopt::Long;
+use Benchmark;
+
+package main;
+
+$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
+$opt_lock_tables=$opt_debug=$opt_skip_drop=$opt_fast=$opt_force=0;
+$opt_thread_factor=1;
+$opt_insert=1;
+$opt_select=6;$opt_join=4;
+$opt_select_count=$opt_join_count=0;
+$opt_update=1;$opt_delete=0;
+$opt_flush=$opt_check=$opt_repair=$opt_alter=0;
+$opt_join_range=100;
+$opt_time=0;
+$opt_host=$opt_user=$opt_password=""; $opt_db="test";
+
+GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","skip-in","skip-drop",
+ "verbose","fast-insert","lock-tables","debug","fast","force","thread-factor=i",
+ "insert=i", "select=i", "join=i", "select-count=i", "join-count=i", "update=i", "delete=i",
+ "flush=i", "check=i", "repair=i", "alter=i", "max-join_range=i", "time=i") || die "Aborted";
+$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
+
+print "Test of multiple connections that test the following things:\n";
+print "insert, select, delete, update, alter, check, repair and flush\n";
+
+@testtables = ( ["bench_f31", ""],
+ ["bench_f32", "row_format=fixed"],
+ ["bench_f33", "delay_key_write=1"],
+ ["bench_f34", "checksum=1"],
+ ["bench_f35", "delay_key_write=1"]);
+$abort_table="bench_f39";
+
+$numtables = $#testtables+1;
+srand 100; # Make random numbers repeatable
+
+####
+#### Start timeing and start test
+####
+
+$opt_insert*=$opt_thread_factor;
+$opt_select*=$opt_thread_factor;
+$opt_join*=$opt_thread_factor;
+$opt_select_count*=$opt_thread_factor;
+$opt_join_count*=$opt_thread_factor;
+$opt_update*=$opt_thread_factor;
+$opt_delete*=$opt_thread_factor;
+
+if ($opt_time == 0 && $opt_insert == 0)
+{
+ $opt_insert=1;
+}
+
+$start_time=new Benchmark;
+$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+if (!$opt_skip_create)
+{
+ my $table_def;
+ foreach $table_def (@testtables)
+ {
+ my ($table,$extra)= ($table_def->[0], $table_def->[1]);
+ print "Creating table $table in database $opt_db\n";
+ $dbh->do("drop table if exists $table");
+ $dbh->do("create table $table".
+ " (id int(6) not null auto_increment,".
+ " info varchar(32)," .
+ " marker timestamp," .
+ " flag int not null," .
+ " primary key(id)) $extra")
+
+ or die $DBI::errstr;
+ # One row in the table will make future tests easier
+ $dbh->do("insert into $table (id) values (null)")
+ or die $DBI::errstr;
+ }
+ # Create the table we use to signal that we should end the test
+ $dbh->do("drop table if exists $abort_table");
+ $dbh->do("create table $abort_table (id int(6) not null) type=heap") ||
+ die $DBI::errstr;
+}
+
+$dbh->do("delete from $abort_table");
+$dbh->disconnect; $dbh=0; # Close handler
+$|= 1; # Autoflush
+
+####
+#### Start the tests
+####
+if ($opt_time != 0)
+{
+ test_abort() if (($pid=fork()) == 0); $work{$pid}="abort";
+}
+for ($i=0 ; $i < $opt_insert ; $i ++)
+{
+ test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
+}
+$threads=$i;
+for ($i=0 ; $i < $opt_select ; $i ++)
+{
+ test_select() if (($pid=fork()) == 0); $work{$pid}="select";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_join ; $i ++)
+{
+ test_join() if (($pid=fork()) == 0); $work{$pid}="join";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_select_count ; $i ++)
+{
+ test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_join_count ; $i ++)
+{
+ test_join_count() if (($pid=fork()) == 0); $work{$pid}="join_count";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_update ; $i ++)
+{
+ test_update() if (($pid=fork()) == 0); $work{$pid}="update";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_delete ; $i ++)
+{
+ test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_flush ; $i ++)
+{
+ test_flush() if (($pid=fork()) == 0); $work{$pid}="flush";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_check ; $i ++)
+{
+ test_check() if (($pid=fork()) == 0); $work{$pid}="check";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_repair ; $i ++)
+{
+ test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
+}
+$threads+=$i;
+for ($i=0 ; $i < $opt_alter ; $i ++)
+{
+ test_alter() if (($pid=fork()) == 0); $work{$pid}="alter";
+}
+$threads+=$i;
+
+print "Started $threads threads\n";
+
+$errors=0;
+$running_insert_threads=$opt_insert;
+while (($pid=wait()) != -1)
+{
+ $ret=$?/256;
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
+ if ($opt_time == 0)
+ {
+ if ($work{$pid} =~ /^insert/)
+ {
+ if (!--$running_insert_threads)
+ {
+
+ # Time to stop other threads
+ signal_abort();
+ }
+ }
+ }
+ $errors++ if ($ret != 0);
+}
+
+#
+# Cleanup
+#
+
+if (!$opt_skip_drop && !$errors)
+{
+ my $table_def;
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $dbh->do("drop table $abort_table");
+ foreach $table_def (@testtables)
+ {
+ $dbh->do("drop table " . $table_def->[0]);
+ }
+ $dbh->disconnect; $dbh=0; # Close handler
+}
+
+print ($errors ? "Test failed\n" :"Test ok\n");
+$end_time=new Benchmark;
+print "Total time: " .
+ timestr(timediff($end_time, $start_time),"noc") . "\n";
+
+exit(0);
+
+#
+# Sleep and then abort other threads
+#
+
+sub test_abort
+{
+ sleep($opt_time);
+ signal_abort();
+ exit(0);
+}
+
+
+#
+# Insert records in the table
+#
+
+sub test_insert
+{
+ my ($from_table,$to_table)= @_;
+ my ($dbh,$i,$j,$count,$table_def,$table);
+
+ if (!defined($from_table))
+ {
+ $from_table=0; $to_table=$numtables-1;
+ }
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ for ($i=$count=0 ; $i < $opt_loop_count; $i++)
+ {
+ for ($j= $from_table ; $j <= $to_table ; $j++)
+ {
+ my ($table)= ($testtables[$j]->[0]);
+ $dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_insert: Inserted $count rows\n";
+ exit(0);
+}
+
+
+#
+# select records
+# Do continously select over all tables as long as there is changed
+# rows in the table
+#
+
+sub test_select
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($numtables);
+ $count=0;
+ $loop=9999;
+
+ $i=0;
+ while (($i++ % 100) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 100)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+ for ($j=0 ; $j < $numtables ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($table)= $testtables[$j]->[0];
+ simple_query($dbh, "select id,info from $table where id=$id");
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_select: Executed $count selects\n";
+ exit(0);
+}
+
+#
+# Do big select count(distinct..) over the table
+#
+
+sub test_select_count
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count=0;
+ $i=0;
+ while (!test_if_abort($dbh))
+ {
+ for ($j=0 ; $j < $numtables ; $j++)
+ {
+ my ($table)= $testtables[$j]->[0];
+ simple_query($dbh, "select count(distinct marker),count(distinct id),count(distinct info) from $table");
+ $count++;
+ }
+ sleep(20); # This query is quite slow
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_select: Executed $count select count(distinct) queries\n";
+ exit(0);
+}
+
+#
+# select records
+# Do continously joins between the first and second table
+#
+
+sub test_join
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($numtables);
+ $count=0;
+ $loop=9999;
+
+ $i=0;
+ while (($i++ % 100) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 100)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+ for ($j=0 ; $j < $numtables-1 ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
+ simple_query($dbh, "select $t1.id,$t2.info from $t1, $t2 where $t1.id=$t2.id and $t1.id=$id");
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_join: Executed $count joins\n";
+ exit(0);
+}
+
+#
+# select records
+# Do continously joins between the first and second for range and count selected rows
+#
+
+sub test_join_count
+{
+ my ($dbh, $i, $j, $count, $loop);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($numtables);
+ $count=0;
+ $loop=9999;
+ $sum=0;
+
+ srand();
+
+ $i=0;
+ while (($i++ % 10) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 10)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+ for ($j=0 ; $j < $numtables-1 ; $j++)
+ {
+ my ($id1)= int rand $row_counts->[$j];
+ my ($id2)= int rand $row_counts->[$j];
+ if ($id1 > $id2)
+ {
+ my $id0=$id1; $id1=$id2; $id2=$id0;
+ if ($id2-$id1 > $opt_join_range)
+ {
+ $id2=$id1+$opt_join_range;
+ }
+ }
+ my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
+ $row=simple_query($dbh, "select count(*) from $t1, $t2 where $t1.id=$t2.id and $t1.id between $id1 and $id2");
+ $sum+=$row->[0];
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_join_count: Executed $count joins: total $sum rows\n";
+ exit(0);
+}
+
+
+#
+# Delete 1-5 rows from the first 2 tables.
+# Test ends when the number of rows for table 3 didn't change during
+# one loop
+#
+
+sub test_delete
+{
+ my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
+
+ $table_count=2;
+ $count=0;
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query($table_count+1);
+
+ sleep(5); # Give time to insert some rows
+ $i=0;
+ while (($i++ % 10) || !test_if_abort($dbh))
+ {
+ sleep(1);
+ $row_counts=simple_query($dbh, $count_query);
+
+ for ($j=0 ; $j < $table_count ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($table)= $testtables[$j]->[0];
+ $dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_delete: Executed $count deletes\n";
+ exit(0);
+}
+
+#
+# Update the flag for table 2 and 3
+# Will abort after a while when table1 doesn't change max value
+#
+
+sub test_update
+{
+ my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $count_query=make_count_query(3);
+ $loop=9999;
+ $count=0;
+
+ sleep(5); # Give time to insert some rows
+ $i=0;
+ while (($i++ % 100) || !test_if_abort($dbh))
+ {
+ if ($loop++ >= 100)
+ {
+ $loop=0;
+ $row_counts=simple_query($dbh, $count_query);
+ }
+
+ for ($j=1 ; $j <= 2 ; $j++)
+ {
+ my ($id)= int rand $row_counts->[$j];
+ my ($table)= $testtables[$j]->[0];
+ # Fix to not change the same rows as the above delete
+ $id= ($id + $count) % $row_counts->[$j];
+
+ $dbh->do("update $table set flag=flag+1 where id >= $id-2 and id <= $id +2") || die "Got error on update of $table: $DBI::errstr\n";
+ $count++;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "Test_update: Executed $count updates\n";
+ exit(0);
+}
+
+
+#
+# Run a check on all tables except the last one
+# (The last one is not checked to put pressure on the key cache)
+#
+
+sub test_check
+{
+ my ($dbh, $row, $i, $j, $type, $table);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $type= "check";
+ for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(1000);
+ $table=$testtables[$j]->[0];
+ $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+
+ while (($row=$sth->fetchrow_arrayref))
+ {
+ if ($row->[3] ne "OK")
+ {
+ print "Got error " . $row->[3] . " when doing $type on $table\n";
+ exit(1);
+ }
+ }
+ if (++$j == $numtables-1)
+ {
+ $j=0;
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_check: Executed $i checks\n";
+ exit(0);
+}
+
+#
+# Do a repair on the first table once in a while
+#
+
+sub test_repair
+{
+ my ($dbh, $row, $i, $type, $table);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $type= "repair";
+ for ($i=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(2000);
+ $table=$testtables[0]->[0];
+ $sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+
+ while (($row=$sth->fetchrow_arrayref))
+ {
+ if ($row->[3] ne "OK")
+ {
+ print "Got error " . $row->[3] . " when doing $type on $table\n";
+ exit(1);
+ }
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_repair: Executed $i repairs\n";
+ exit(0);
+}
+
+#
+# Do a flush tables on table 3 and 4 once in a while
+#
+
+sub test_flush
+{
+ my ($dbh,$count,$tables);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
+
+ $count=0;
+ while (!test_if_abort($dbh))
+ {
+ sleep(3000);
+ $dbh->do("flush tables $tables") ||
+ die "Got error on flush $DBI::errstr\n";
+ $count++;
+ }
+ $dbh->disconnect; $dbh=0;
+ print "flush: Executed $count flushs\n";
+ exit(0);
+}
+
+
+#
+# Test all tables in a database
+#
+
+sub test_database
+{
+ my ($database) = @_;
+ my ($dbh, $row, $i, $type, $tables);
+ $dbh = DBI->connect("DBI:mysql:$database:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $tables= join(',',$dbh->func('_ListTables'));
+ $type= "check";
+ for ($i=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(120);
+ $sth=$dbh->prepare("$type table $tables") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+
+ while (($row=$sth->fetchrow_arrayref))
+ {
+ if ($row->[3] ne "OK")
+ {
+ print "Got error " . $row->[2] . " " . $row->[3] . " when doing $type on " . $row->[0] . "\n";
+ exit(1);
+ }
+ }
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_check: Executed $i checks\n";
+ exit(0);
+}
+
+#
+# Test ALTER TABLE on the second table
+#
+
+sub test_alter
+{
+ my ($dbh, $row, $i, $type, $table);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ for ($i=0 ; !test_if_abort($dbh) ; $i++)
+ {
+ sleep(100);
+ $table=$testtables[1]->[0];
+ $sth=$dbh->prepare("ALTER table $table modify info char(32)") || die "Got error on prepare: $DBI::errstr\n";
+ $sth->execute || die $DBI::errstr;
+ }
+ $dbh->disconnect; $dbh=0;
+ print "test_alter: Executed $i ALTER TABLE\n";
+ exit(0);
+}
+
+
+#
+# Help functions
+#
+
+sub signal_abort
+{
+ my ($dbh);
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ $dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
+ $dbh->disconnect; $dbh=0;
+}
+
+
+sub test_if_abort()
+{
+ my ($dbh)=@_;
+ $row=simple_query($dbh,"select * from $opt_db.$abort_table");
+ return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
+}
+
+
+sub make_count_query
+{
+ my ($table_count)= @_;
+ my ($tables, $count_query, $i, $tables_def);
+ $tables="";
+ $count_query="select high_priority ";
+ $table_count--;
+ for ($i=0 ; $i < $table_count ; $i++)
+ {
+ my ($table_def)= $testtables[$i];
+ $tables.=$table_def->[0] . ",";
+ $count_query.= "max(" . $table_def->[0] . ".id),";
+ }
+ $table_def=$testtables[$table_count];
+ $tables.=$table_def->[0];
+ $count_query.= "max(" . $table_def->[0] . ".id) from $tables";
+ return $count_query;
+}
+
+sub simple_query()
+{
+ my ($dbh, $query)= @_;
+ my ($sth,$row);
+
+ $sth=$dbh->prepare($query) || die "Got error on '$query': " . $dbh->errstr . "\n";
+ $sth->execute || die "Got error on '$query': " . $dbh->errstr . "\n";
+ $row= $sth->fetchrow_arrayref();
+ $sth=0;
+ return $row;
+}
diff --git a/tests/grant.res b/tests/grant.res
index 3359f970225..15aad01c888 100644
--- a/tests/grant.res
+++ b/tests/grant.res
@@ -27,11 +27,11 @@ show grants for grant_user@localhost
GRANT SELECT ON *.* TO 'grant_user'@'localhost'
insert into mysql.user (host,user) values ('error','grant_user')
-Error in execute: insert command denied to user: 'grant_user@localhost' for table 'user'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
update mysql.user set host='error' WHERE user='grant_user'
-Error in execute: update command denied to user: 'grant_user@localhost' for table 'user'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
create table grant_test.test (a int,b int)
-Error in execute: create command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant select on *.* to grant_user2@localhost
Error in execute: Access denied for user: 'grant_user@localhost' (Using password: NO)
revoke select on grant_test.test from grant_user@opt_host
@@ -106,21 +106,21 @@ select count(*) from grant_test.test
2
select * from mysql.user where user = 'grant_user'
-Error in execute: select command denied to user: 'grant_user@localhost' for table 'user'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
insert into grant_test.test values (4,0)
-Error in execute: insert command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
update grant_test.test set a=1
-Error in execute: update command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
delete from grant_test.test
-Error in execute: delete command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
create table grant_test.test2 (a int)
-Error in execute: create command denied to user: 'grant_user@localhost' for table 'test2'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
ALTER TABLE grant_test.test add c int
-Error in execute: alter command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
CREATE INDEX dummy ON grant_test.test (a)
-Error in execute: index command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
drop table grant_test.test
-Error in execute: drop command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant ALL PRIVILEGES on grant_test.* to grant_user2@localhost
Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant ALL PRIVILEGES on grant_test.* to grant_user@localhost WITH GRANT OPTION
@@ -133,14 +133,14 @@ REVOKE ALL PRIVILEGES on grant_test.* from grant_user@localhost
REVOKE ALL PRIVILEGES on grant_test.* from grant_user@localhost
Connecting grant_user
insert into grant_test.test values (6,0)
-Error in execute: insert command denied to user: 'grant_user@localhost' for table 'test'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
REVOKE GRANT OPTION on grant_test.* from grant_user@localhost
Connecting grant_user
Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant ALL PRIVILEGES on grant_test.* to grant_user@localhost
Connecting grant_user
select * from mysql.user where user = 'grant_user'
-Error in execute: select command denied to user: 'grant_user@localhost' for table 'user'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
insert into grant_test.test values (7,0)
update grant_test.test set a=3 where a=2
delete from grant_test.test where a=3
@@ -152,7 +152,7 @@ show tables from grant_test
test
insert into mysql.user (host,user) values ('error','grant_user',0)
-Error in execute: insert command denied to user: 'grant_user@localhost' for table 'user'
+Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
revoke ALL PRIVILEGES on grant_test.* from grant_user@localhost
select * from mysql.user where user = 'grant_user'
localhost grant_user N N N N N N N N N N N N N N N N N N N N N 0 0 0
@@ -171,7 +171,7 @@ Error in execute: select command denied to user: 'grant_user@localhost' for tabl
show keys from test
Error in execute: select command denied to user: 'grant_user@localhost' for table 'test'
show columns from test2
-a int(11) 0
+a int(11) binary 0
show keys from test2
select * from test
@@ -228,7 +228,7 @@ Error in execute: select command denied to user: 'grant_user@localhost' for tabl
select count(*) from test,test2
Error in execute: select command denied to user: 'grant_user@localhost' for table 'test2'
replace into test2 SELECT a from test
-Error in execute: update command denied to user: 'grant_user@localhost' for table 'test2'
+Error in execute: delete command denied to user: 'grant_user@localhost' for table 'test2'
grant update on grant_test.test2 to grant_user@localhost
replace into test2 SELECT a,a from test
Error in execute: delete command denied to user: 'grant_user@localhost' for table 'test2'
@@ -314,8 +314,8 @@ revoke GRANT OPTION on grant_test.test from grant_user@localhost
Error in execute: There is no such grant defined for user 'grant_user' on host 'localhost' on table 'test'
grant select(a) on grant_test.test to grant_user@localhost
show full columns from test
-a int(11) YES NULL select
-b int(11) YES NULL
+a int(11) binary YES NULL select
+b int(11) binary YES NULL
grant insert (b), update (b) on grant_test.test to grant_user@localhost
select count(a) from test
@@ -472,7 +472,7 @@ GRANT LOCK TABLES ON *.* TO 'grant_user'@'localhost'
GRANT SELECT, INSERT ON grant_test.test3 TO 'grant_user'@'localhost'
select * from mysql.user where user='grant_user'
-127.0.0.1 grant_user 7f70e8b858ee6782 N N N N N N N N N N N N N N N N N N N N N 0 0 0
+127.0.0.1 grant_user *042a99b3d247ae587783f647f2d69496d390aa71eab3 N N N N N N N N N N N N N N N N N N N N N 0 0 0
localhost grant_user N N N N N N N N N N N N N N N N N Y N N N 0 0 0
Connecting grant_user
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 3c786dc9281..0dc0b90c60e 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,5 +1,4 @@
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include \
- $(openssl_includes) -I../include
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include $(openssl_includes)
LDADD= @CLIENT_EXTRA_LDFLAGS@ ../libmysql_r/libmysqlclient_r.la @openssl_libs@
bin_PROGRAMS= mysqlmanager
mysqlmanager_SOURCES= mysqlmanager.c
diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c
index 790a5d56b5a..4f2deeb0052 100644
--- a/tools/mysqlmanager.c
+++ b/tools/mysqlmanager.c
@@ -428,8 +428,8 @@ static int exec_line(struct manager_thd* thd,char* buf,char* buf_end)
{
char* p=buf;
struct manager_cmd* cmd;
- for (;p<buf_end && !isspace(*p);p++)
- *p=tolower(*p);
+ for (;p<buf_end && !my_isspace(system_charset_info,*p);p++)
+ *p=my_tolower(system_charset_info,*p);
log_info("Command '%s'", buf);
if (!(cmd=lookup_cmd(buf,(int)(p-buf))))
{
@@ -439,7 +439,7 @@ static int exec_line(struct manager_thd* thd,char* buf,char* buf_end)
thd->fatal=1;
return 1;
}
- for (;p<buf_end && isspace(*p);p++);
+ for (;p<buf_end && my_isspace(system_charset_info,*p);p++);
return cmd->handler_func(thd,p,buf_end);
}
@@ -716,7 +716,7 @@ HANDLE_DECL(handle_query)
int num_fields,i,ident_len;
char* ident,*query;
query=ident=args_start;
- while (!isspace(*query))
+ while (!my_isspace(system_charset_info,*query))
query++;
if (query == ident)
{
@@ -724,7 +724,7 @@ HANDLE_DECL(handle_query)
goto err;
}
ident_len=(int)(query-ident);
- while (query<args_end && isspace(*query))
+ while (query<args_end && my_isspace(system_charset_info,*query))
query++;
if (query == args_end)
{
@@ -1000,7 +1000,7 @@ static int authenticate(struct manager_thd* thd)
for (buf=thd->cmd_buf,p=thd->user,p_end=p+MAX_USER_NAME;
buf<buf_end && (c=*buf) && p<p_end; buf++,p++)
{
- if (isspace(c))
+ if (my_isspace(system_charset_info,c))
{
*p=0;
break;
@@ -1013,7 +1013,7 @@ static int authenticate(struct manager_thd* thd)
if (!(u=(struct manager_user*)hash_search(&user_hash,thd->user,
(uint)(p-thd->user))))
return 1;
- for (;isspace(*buf) && buf<buf_end;buf++) /* empty */;
+ for (;my_isspace(system_charset_info,*buf) && buf<buf_end;buf++) /* empty */;
my_MD5Init(&context);
my_MD5Update(&context,(uchar*) buf,(uint)(buf_end-buf));
@@ -1582,9 +1582,9 @@ static void manager_exec_free(void* e)
static int hex_val(char c)
{
- if (isdigit(c))
+ if (my_isdigit(system_charset_info,c))
return c-'0';
- c=tolower(c);
+ c=my_tolower(system_charset_info,c);
return c-'a'+10;
}
@@ -1641,7 +1641,8 @@ static void init_user_hash()
FILE* f;
char buf[80];
int line_num=1;
- if (hash_init(&user_hash,1024,0,0,get_user_key,manager_user_free,MYF(0)))
+ if (hash_init(&user_hash,system_charset_info,1024,0,0,
+ get_user_key,manager_user_free,MYF(0)))
die("Could not initialize user hash");
if (!(f=my_fopen(manager_pw_file, O_RDONLY | O_BINARY, MYF(MY_WME))))
{
@@ -1687,7 +1688,8 @@ static void init_pid_file()
static void init_globals()
{
pthread_attr_t thr_attr;
- if (hash_init(&exec_hash,1024,0,0,get_exec_key,manager_exec_free,MYF(0)))
+ if (hash_init(&exec_hash,system_charset_info,1024,0,0,
+ get_exec_key,manager_exec_free,MYF(0)))
die("Exec hash initialization failed");
if (!one_thread)
{
diff --git a/vio/Makefile.am b/vio/Makefile.am
index b53f3be9f91..16c70b12454 100644
--- a/vio/Makefile.am
+++ b/vio/Makefile.am
@@ -14,7 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = -I$(srcdir)/../include -I../include $(openssl_includes)
+INCLUDES = -I$(top_srcdir)/include $(openssl_includes)
LDADD = @CLIENT_EXTRA_LDFLAGS@ libvio.a $(openssl_libs)
pkglib_LIBRARIES = libvio.a
noinst_PROGRAMS = test-ssl test-sslserver test-sslclient
diff --git a/vio/vio.c b/vio/vio.c
index d822651cca6..e629cd043b5 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -45,7 +45,43 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->sd = sd;
vio->hPipe = hPipe;
vio->localhost= localhost;
-#ifdef HAVE_VIO
+#ifdef HAVE_VIO
+#ifdef __WIN__
+ if (type == VIO_TYPE_NAMEDPIPE)
+ {
+ vio->viodelete =vio_delete;
+ vio->vioerrno =vio_errno;
+ vio->read =vio_read_pipe;
+ vio->write =vio_write_pipe;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->vioclose =vio_close_pipe;
+ vio->peer_addr =vio_peer_addr;
+ vio->in_addr =vio_in_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ }
+ else /* default is VIO_TYPE_TCPIP */
+#endif
+#ifdef HAVE_SMEM
+ if (type == VIO_TYPE_SHARED_MEMORY)
+ {
+ vio->viodelete =vio_delete;
+ vio->vioerrno =vio_errno;
+ vio->read =vio_read_shared_memory;
+ vio->write =vio_write_shared_memory;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->vioclose =vio_close_shared_memory;
+ vio->peer_addr =vio_peer_addr;
+ vio->in_addr =vio_in_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ }
+ else
+#endif
#ifdef HAVE_OPENSSL
if (type == VIO_TYPE_SSL)
{
@@ -134,4 +170,44 @@ Vio *vio_new_win32pipe(HANDLE hPipe)
DBUG_RETURN(vio);
}
+#ifdef HAVE_SMEM
+Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map,
+ HANDLE event_server_wrote, HANDLE event_server_read,
+ HANDLE event_client_wrote, HANDLE event_client_read)
+{
+ Vio *vio;
+ DBUG_ENTER("vio_new_win32shared_memory");
+ if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
+ {
+ vio_reset(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, TRUE);
+ vio->handle_file_map = handle_file_map;
+ vio->handle_map = handle_map;
+ vio->event_server_wrote = event_server_wrote;
+ vio->event_server_read = event_server_read;
+ vio->event_client_wrote = event_client_wrote;
+ vio->event_client_read = event_client_read;
+ vio->shared_memory_remain = 0;
+ vio->shared_memory_pos = handle_map;
+ vio->net = net;
+ strmov(vio->desc, "shared memory");
+ }
+ DBUG_RETURN(vio);
+}
+#endif
#endif
+
+void vio_delete(Vio* vio)
+{
+ /* It must be safe to delete null pointers. */
+ /* This matches the semantics of C++'s delete operator. */
+ if (vio)
+ {
+ if (vio->type != VIO_CLOSED)
+#ifdef HAVE_VIO /*WAX*/
+ vio->vioclose(vio);
+#else
+ vio_close(vio);
+#endif
+ my_free((gptr) vio,MYF(0));
+ }
+}
diff --git a/vio/viosocket.c b/vio/viosocket.c
index f69eebd413a..76056704ec2 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -35,18 +35,6 @@
#define HANDLE void *
#endif
-void vio_delete(Vio* vio)
-{
- /* It must be safe to delete null pointers. */
- /* This matches the semantics of C++'s delete operator. */
- if (vio)
- {
- if (vio->type != VIO_CLOSED)
- vio_close(vio);
- my_free((gptr) vio,MYF(0));
- }
-}
-
int vio_errno(Vio *vio __attribute__((unused)))
{
return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
@@ -58,14 +46,8 @@ int vio_read(Vio * vio, gptr buf, int size)
int r;
DBUG_ENTER("vio_read");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+
#ifdef __WIN__
- if (vio->type == VIO_TYPE_NAMEDPIPE)
- {
- DWORD length;
- if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
- DBUG_RETURN(-1);
- DBUG_RETURN(length);
- }
r = recv(vio->sd, buf, size,0);
#else
errno=0; /* For linux */
@@ -87,15 +69,8 @@ int vio_write(Vio * vio, const gptr buf, int size)
int r;
DBUG_ENTER("vio_write");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
-#if defined( __WIN__)
- if ( vio->type == VIO_TYPE_NAMEDPIPE)
- {
- DWORD length;
- if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
- DBUG_RETURN(-1);
- DBUG_RETURN(length);
- }
- r = send(vio->sd, buf, size, 0);
+#ifdef __WIN__
+ r = send(vio->sd, buf, size,0);
#else
r = write(vio->sd, buf, size);
#endif /* __WIN__ */
@@ -109,7 +84,6 @@ int vio_write(Vio * vio, const gptr buf, int size)
DBUG_RETURN(r);
}
-
int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
my_bool *old_mode)
{
@@ -332,3 +306,155 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
#endif
}
+
+#ifdef __WIN__
+int vio_read_pipe(Vio * vio, gptr buf, int size)
+{
+ DWORD length;
+ DBUG_ENTER("vio_read_pipe");
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+
+ if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
+ DBUG_RETURN(-1);
+
+ DBUG_PRINT("exit", ("%d", length));
+ DBUG_RETURN(length);
+}
+
+
+int vio_write_pipe(Vio * vio, const gptr buf, int size)
+{
+ DWORD length;
+ DBUG_ENTER("vio_write_pipe");
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+
+ if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
+ DBUG_RETURN(-1);
+
+ DBUG_PRINT("exit", ("%d", length));
+ DBUG_RETURN(length);
+}
+
+int vio_close_pipe(Vio * vio)
+{
+ int r;
+ DBUG_ENTER("vio_close_pipe");
+#if defined(__NT__) && defined(MYSQL_SERVER)
+ CancelIo(vio->hPipe);
+ DisconnectNamedPipe(vio->hPipe);
+#endif
+ r=CloseHandle(vio->hPipe);
+ if (r)
+ {
+ DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
+ /* FIXME: error handling (not critical for MySQL) */
+ }
+ vio->type= VIO_CLOSED;
+ vio->sd= -1;
+ DBUG_RETURN(r);
+}
+
+#ifdef HAVE_SMEM
+
+int vio_read_shared_memory(Vio * vio, gptr buf, int size)
+{
+ int length;
+ int remain_local;
+ char *current_postion;
+
+ DBUG_ENTER("vio_read_shared_memory");
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+
+ remain_local = size;
+ current_postion=buf;
+ do
+ {
+ if (vio->shared_memory_remain == 0)
+ {
+ if (WaitForSingleObject(vio->event_server_wrote,vio->net->read_timeout*1000) != WAIT_OBJECT_0)
+ {
+ DBUG_RETURN(-1);
+ };
+ vio->shared_memory_pos = vio->handle_map;
+ vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
+ vio->shared_memory_pos+=4;
+ }
+
+ length = size;
+
+ if (vio->shared_memory_remain < length)
+ length = vio->shared_memory_remain;
+ if (length > remain_local)
+ length = remain_local;
+
+ memcpy(current_postion,vio->shared_memory_pos,length);
+
+ vio->shared_memory_remain-=length;
+ vio->shared_memory_pos+=length;
+ current_postion+=length;
+ remain_local-=length;
+
+ if (!vio->shared_memory_remain)
+ if (!SetEvent(vio->event_client_read)) DBUG_RETURN(-1);
+ } while (remain_local);
+ length = size;
+
+ DBUG_PRINT("exit", ("%d", length));
+ DBUG_RETURN(length);
+}
+
+
+int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
+{
+ int length;
+ uint remain;
+ HANDLE pos;
+ int sz;
+ char *current_postion;
+
+ DBUG_ENTER("vio_write_shared_memory");
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+
+ remain = size;
+ current_postion = buf;
+ while (remain != 0)
+ {
+ if (WaitForSingleObject(vio->event_server_read,vio->net->write_timeout*1000) != WAIT_OBJECT_0)
+ {
+ DBUG_RETURN(-1);
+ };
+
+ sz = remain > shared_memory_buffer_length ? shared_memory_buffer_length: remain;
+
+ int4store(vio->handle_map,sz);
+ pos = vio->handle_map + 4;
+ memcpy(pos,current_postion,sz);
+ remain-=sz;
+ current_postion+=sz;
+ if (!SetEvent(vio->event_client_wrote)) DBUG_RETURN(-1);
+ }
+ length = size;
+
+ DBUG_PRINT("exit", ("%d", length));
+ DBUG_RETURN(length);
+}
+
+
+int vio_close_shared_memory(Vio * vio)
+{
+ int r;
+ DBUG_ENTER("vio_close_shared_memory");
+ r=UnmapViewOfFile(vio->handle_map) || CloseHandle(vio->event_server_wrote) ||
+ CloseHandle(vio->event_server_read) || CloseHandle(vio->event_client_wrote) ||
+ CloseHandle(vio->event_client_read) || CloseHandle(vio->handle_file_map);
+ if (r)
+ {
+ DBUG_PRINT("vio_error", ("close() failed, error: %d",r));
+ /* FIXME: error handling (not critical for MySQL) */
+ }
+ vio->type= VIO_CLOSED;
+ vio->sd= -1;
+ DBUG_RETURN(r);
+}
+#endif
+#endif